summaryrefslogtreecommitdiff
path: root/thirdparty
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty')
-rw-r--r--thirdparty/README.md153
-rw-r--r--thirdparty/basis_universal/encoder/apg_bmp.c541
-rw-r--r--thirdparty/basis_universal/encoder/apg_bmp.h123
-rw-r--r--thirdparty/basis_universal/encoder/basisu_astc_decomp.cpp1561
-rw-r--r--thirdparty/basis_universal/encoder/basisu_astc_decomp.h43
-rw-r--r--thirdparty/basis_universal/encoder/basisu_backend.cpp629
-rw-r--r--thirdparty/basis_universal/encoder/basisu_backend.h99
-rw-r--r--thirdparty/basis_universal/encoder/basisu_comp.cpp834
-rw-r--r--thirdparty/basis_universal/encoder/basisu_comp.h169
-rw-r--r--thirdparty/basis_universal/encoder/basisu_enc.cpp222
-rw-r--r--thirdparty/basis_universal/encoder/basisu_enc.h409
-rw-r--r--thirdparty/basis_universal/encoder/basisu_etc.cpp17
-rw-r--r--thirdparty/basis_universal/encoder/basisu_etc.h29
-rw-r--r--thirdparty/basis_universal/encoder/basisu_frontend.cpp1789
-rw-r--r--thirdparty/basis_universal/encoder/basisu_frontend.h45
-rw-r--r--thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.cpp71
-rw-r--r--thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.h46
-rw-r--r--thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp8
-rw-r--r--thirdparty/basis_universal/encoder/basisu_kernels_declares.h2
-rw-r--r--thirdparty/basis_universal/encoder/basisu_kernels_imp.h63
-rw-r--r--thirdparty/basis_universal/encoder/basisu_kernels_sse.cpp2
-rw-r--r--thirdparty/basis_universal/encoder/basisu_miniz.h27
-rw-r--r--thirdparty/basis_universal/encoder/basisu_ocl_kernels.h1439
-rw-r--r--thirdparty/basis_universal/encoder/basisu_opencl.cpp1332
-rw-r--r--thirdparty/basis_universal/encoder/basisu_opencl.h143
-rw-r--r--thirdparty/basis_universal/encoder/basisu_uastc_enc.cpp24
-rw-r--r--thirdparty/basis_universal/encoder/cppspmd_sse.h23
-rw-r--r--thirdparty/basis_universal/encoder/jpgd.cpp19
-rw-r--r--thirdparty/basis_universal/encoder/lodepng.cpp6008
-rw-r--r--thirdparty/basis_universal/encoder/lodepng.h1930
-rw-r--r--thirdparty/basis_universal/encoder/pvpngreader.cpp2662
-rw-r--r--thirdparty/basis_universal/encoder/pvpngreader.h48
-rw-r--r--thirdparty/basis_universal/transcoder/basisu.h10
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_containers.h83
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_containers_impl.h8
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h272
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h675
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.cpp271
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder.h15
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h24
-rw-r--r--thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h4
-rw-r--r--thirdparty/brotli/LICENSE19
-rw-r--r--thirdparty/brotli/common/constants.c15
-rw-r--r--thirdparty/brotli/common/constants.h200
-rw-r--r--thirdparty/brotli/common/context.c156
-rw-r--r--thirdparty/brotli/common/context.h113
-rw-r--r--thirdparty/brotli/common/dictionary.c5916
-rw-r--r--thirdparty/brotli/common/dictionary.h64
-rw-r--r--thirdparty/brotli/common/platform.c22
-rw-r--r--thirdparty/brotli/common/platform.h576
-rw-r--r--thirdparty/brotli/common/shared_dictionary.c515
-rw-r--r--thirdparty/brotli/common/shared_dictionary_internal.h74
-rw-r--r--thirdparty/brotli/common/transform.c291
-rw-r--r--thirdparty/brotli/common/transform.h85
-rw-r--r--thirdparty/brotli/common/version.h26
-rw-r--r--thirdparty/brotli/dec/bit_reader.c76
-rw-r--r--thirdparty/brotli/dec/bit_reader.h361
-rw-r--r--thirdparty/brotli/dec/decode.c2802
-rw-r--r--thirdparty/brotli/dec/huffman.c339
-rw-r--r--thirdparty/brotli/dec/huffman.h121
-rw-r--r--thirdparty/brotli/dec/prefix.h732
-rw-r--r--thirdparty/brotli/dec/state.c165
-rw-r--r--thirdparty/brotli/dec/state.h380
-rw-r--r--thirdparty/brotli/include/brotli/decode.h368
-rw-r--r--thirdparty/brotli/include/brotli/encode.h501
-rw-r--r--thirdparty/brotli/include/brotli/port.h313
-rw-r--r--thirdparty/brotli/include/brotli/shared_dictionary.h97
-rw-r--r--thirdparty/brotli/include/brotli/types.h83
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h38
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp1352
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h1332
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp808
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h197
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h70
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp559
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h427
-rw-r--r--thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h56
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h39
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h55
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp500
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h55
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp297
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h92
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h25
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h28
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h19
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h123
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h171
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h69
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h36
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h486
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h153
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h38
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h797
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h197
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h888
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h175
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h88
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h89
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h31
-rw-r--r--thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h35
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp186
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h110
-rw-r--r--thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h522
-rw-r--r--thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h106
-rw-r--r--thirdparty/bullet/Bullet3Common/b3FileUtils.h133
-rw-r--r--thirdparty/bullet/Bullet3Common/b3HashMap.h462
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.cpp145
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Logging.h74
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Matrix3x3.h1354
-rw-r--r--thirdparty/bullet/Bullet3Common/b3MinMax.h69
-rw-r--r--thirdparty/bullet/Bullet3Common/b3PoolAllocator.h121
-rw-r--r--thirdparty/bullet/Bullet3Common/b3QuadWord.h242
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Quaternion.h908
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Random.h46
-rw-r--r--thirdparty/bullet/Bullet3Common/b3ResizablePool.h171
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Scalar.h689
-rw-r--r--thirdparty/bullet/Bullet3Common/b3StackAlloc.h118
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Transform.h286
-rw-r--r--thirdparty/bullet/Bullet3Common/b3TransformUtil.h210
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Vector3.cpp1637
-rw-r--r--thirdparty/bullet/Bullet3Common/b3Vector3.h1303
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Float4.h90
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Int2.h63
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Int4.h71
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h157
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h41
-rw-r--r--thirdparty/bullet/Bullet3Common/shared/b3Quat.h100
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h149
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp103
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h34
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp737
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h517
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h150
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp1696
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h133
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp190
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h153
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h281
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h73
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp151
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h469
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp447
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h62
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h31
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h148
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h14
-rw-r--r--thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h106
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h217
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp2745
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h99
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp174
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h36
-rw-r--r--thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h116
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h42
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp338
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h80
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp557
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h125
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp76
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h66
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp1298
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h143
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h13
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl216
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h198
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl767
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h728
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl389
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h341
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h51
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp963
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h190
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h17
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp253
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h62
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp4408
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h106
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h7
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp1062
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h79
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp363
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h56
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp1254
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h511
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp207
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h158
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h34
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp24
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h37
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp90
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h10
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp574
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h164
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl283
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h257
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl311
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h1445
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl1374
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h1288
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl2018
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl1888
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h2098
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl1220
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h1456
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h2103
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp203
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h64
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h18
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp119
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h52
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp296
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h300
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp120
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h35
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp120
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h36
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp646
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h84
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl106
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h86
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h131
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl107
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h90
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl154
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl154
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl1071
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h909
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp374
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h28
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl439
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h380
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h17
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp134
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp1305
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h56
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp1013
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h101
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h89
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp1068
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h76
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp1529
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h37
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp677
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h70
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h68
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h210
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h73
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp1128
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h110
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl353
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h387
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl231
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h290
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl32
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h432
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl877
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h720
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.cl501
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h392
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl527
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h420
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl277
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h702
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl613
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h600
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl968
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h908
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl22
-rw-r--r--thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h482
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h987
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp400
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h74
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp69
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h84
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h40
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp616
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h101
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h149
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp1653
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h158
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp18062
-rw-r--r--thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h601
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp33
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h48
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h954
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h79
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp18
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h248
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp22
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h75
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp1357
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h1578
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp828
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h146
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp20
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h110
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp611
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h434
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h41
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp1341
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h543
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp325
-rw-r--r--thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h148
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp215
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h43
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp47
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h35
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp411
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h63
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp80
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h63
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp767
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h40
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h43
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h43
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp289
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h169
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp162
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h38
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp138
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h690
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h49
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp1625
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h513
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp1087
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h169
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp390
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h99
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp413
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h82
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp211
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h83
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp374
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h117
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp873
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h101
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp172
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h82
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp362
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h111
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp30
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h52
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp166
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h162
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp244
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h149
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp900
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h44
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp203
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h163
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp445
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h75
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp209
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h73
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp105
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h64
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp82
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h65
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp74
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h123
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp37
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h339
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp45
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h291
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp462
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h144
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp148
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h182
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h24
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp119
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h174
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp335
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h207
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp24
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h62
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp142
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h175
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp86
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h77
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp244
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h116
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp137
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h208
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp129
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h103
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp302
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h59
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp458
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h75
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp283
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h68
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp253
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h206
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp42
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h65
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp950
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h250
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h38
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp522
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h127
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp71
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h59
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp169
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h95
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp43
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h115
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp364
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h56
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp549
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h106
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp115
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h86
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp95
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h29
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp421
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h60
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp65
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h71
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp93
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h103
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp380
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h153
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp203
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h71
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp28
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h63
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp24
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h37
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp90
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h128
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp84
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h83
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h238
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp167
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h69
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp179
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h82
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h175
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp150
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h84
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h620
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h173
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h105
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp175
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h65
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h105
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp464
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h309
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h85
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp866
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h288
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h56
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp486
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h298
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h91
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp279
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h1115
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp266
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h153
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h198
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h79
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp203
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h169
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_array.h318
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h536
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h117
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h578
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp176
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h640
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h199
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp142
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h168
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h92
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h42
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h857
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h1488
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_math.h148
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp132
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h177
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h28
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h386
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp619
-rw-r--r--thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h368
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h354
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp222
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h53
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp20
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h90
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h35
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h85
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h39
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp164
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h46
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp1104
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h73
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h1063
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp81
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h40
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp1183
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h93
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h174
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp336
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h36
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h884
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp450
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h374
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h58
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp548
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h42
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp175
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h72
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h58
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp143
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h47
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp577
-rw-r--r--thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h173
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h46
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp996
-rw-r--r--thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h200
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp1084
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h62
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp1116
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h423
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h59
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp153
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h65
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h177
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp32
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h30
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp52
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h146
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp975
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h615
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp1243
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h667
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp169
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h135
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp61
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h55
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp1083
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h480
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h150
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp368
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h57
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp205
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h173
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp1875
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h215
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp1554
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h150
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp823
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h349
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp239
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h101
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h285
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h74
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp214
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h532
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp80
-rw-r--r--thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h59
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h41
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp1469
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h244
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp263
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h131
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h174
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp505
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h687
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp260
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h84
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp696
-rw-r--r--thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h112
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp2461
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h953
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp389
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h215
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp1752
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h101
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp895
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h126
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp215
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h91
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp181
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h115
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h247
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h25
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp197
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h63
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp183
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h77
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h303
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h195
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp966
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h187
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp216
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h64
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp234
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h102
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h90
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp180
-rw-r--r--thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h118
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp2158
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h73
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h106
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp369
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h102
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h338
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp620
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h88
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h33
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h142
-rw-r--r--thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h107
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp708
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h218
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h33
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp51
-rw-r--r--thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h116
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp107
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp38
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp32
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp31
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDMath.cpp510
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/IDMath.hpp100
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp548
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp367
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp39
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp202
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp489
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp1286
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp288
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp131
-rw-r--r--thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp113
-rw-r--r--thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h45
-rw-r--r--thirdparty/bullet/BulletSoftBody/btCGProjection.h104
-rw-r--r--thirdparty/bullet/BulletSoftBody/btConjugateGradient.h117
-rw-r--r--thirdparty/bullet/BulletSoftBody/btConjugateResidual.h112
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp146
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h60
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp299
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h198
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp506
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h160
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp720
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h284
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp639
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h99
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h124
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h105
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h372
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h462
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h301
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h162
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp144
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h61
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp814
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h316
-rw-r--r--thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h420
-rw-r--r--thirdparty/bullet/BulletSoftBody/btKrylovSolver.h107
-rw-r--r--thirdparty/bullet/BulletSoftBody/btPreconditioner.h285
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.cpp4730
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBody.h1394
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp316
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h147
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyData.h212
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp1663
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h167
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h2108
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp131
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h43
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h160
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h147
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp355
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h105
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp78
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h71
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp346
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h102
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp48
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h65
-rw-r--r--thirdparty/bullet/BulletSoftBody/btSparseSDF.h372
-rw-r--r--thirdparty/bullet/BulletSoftBody/poly34.cpp447
-rw-r--r--thirdparty/bullet/BulletSoftBody/poly34.h38
-rw-r--r--thirdparty/bullet/LICENSE.txt15
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp792
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h64
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp353
-rw-r--r--thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp458
-rw-r--r--thirdparty/bullet/LinearMath/btAabbUtil2.h217
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedAllocator.cpp263
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedAllocator.h115
-rw-r--r--thirdparty/bullet/LinearMath/btAlignedObjectArray.h504
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHull.cpp1120
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHull.h233
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHullComputer.cpp2760
-rw-r--r--thirdparty/bullet/LinearMath/btConvexHullComputer.h102
-rw-r--r--thirdparty/bullet/LinearMath/btCpuFeatureUtility.h88
-rw-r--r--thirdparty/bullet/LinearMath/btDefaultMotionState.h40
-rw-r--r--thirdparty/bullet/LinearMath/btGeometryUtil.cpp174
-rw-r--r--thirdparty/bullet/LinearMath/btGeometryUtil.h36
-rw-r--r--thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h129
-rw-r--r--thirdparty/bullet/LinearMath/btHashMap.h470
-rw-r--r--thirdparty/bullet/LinearMath/btIDebugDraw.h473
-rw-r--r--thirdparty/bullet/LinearMath/btImplicitQRSVD.h916
-rw-r--r--thirdparty/bullet/LinearMath/btList.h73
-rw-r--r--thirdparty/bullet/LinearMath/btMatrix3x3.h1431
-rw-r--r--thirdparty/bullet/LinearMath/btMatrixX.h532
-rw-r--r--thirdparty/bullet/LinearMath/btMinMax.h69
-rw-r--r--thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h83
-rw-r--r--thirdparty/bullet/LinearMath/btMotionState.h36
-rw-r--r--thirdparty/bullet/LinearMath/btPolarDecomposition.cpp94
-rw-r--r--thirdparty/bullet/LinearMath/btPolarDecomposition.h69
-rw-r--r--thirdparty/bullet/LinearMath/btPoolAllocator.h130
-rw-r--r--thirdparty/bullet/LinearMath/btQuadWord.h238
-rw-r--r--thirdparty/bullet/LinearMath/btQuaternion.h1021
-rw-r--r--thirdparty/bullet/LinearMath/btQuickprof.cpp805
-rw-r--r--thirdparty/bullet/LinearMath/btQuickprof.h200
-rw-r--r--thirdparty/bullet/LinearMath/btRandom.h39
-rw-r--r--thirdparty/bullet/LinearMath/btReducedVector.cpp170
-rw-r--r--thirdparty/bullet/LinearMath/btReducedVector.h320
-rw-r--r--thirdparty/bullet/LinearMath/btScalar.h832
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.cpp692
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer.h866
-rw-r--r--thirdparty/bullet/LinearMath/btSerializer64.cpp692
-rw-r--r--thirdparty/bullet/LinearMath/btSpatialAlgebra.h389
-rw-r--r--thirdparty/bullet/LinearMath/btStackAlloc.h118
-rw-r--r--thirdparty/bullet/LinearMath/btThreads.cpp792
-rw-r--r--thirdparty/bullet/LinearMath/btThreads.h177
-rw-r--r--thirdparty/bullet/LinearMath/btTransform.h286
-rw-r--r--thirdparty/bullet/LinearMath/btTransformUtil.h223
-rw-r--r--thirdparty/bullet/LinearMath/btVector3.cpp1664
-rw-r--r--thirdparty/bullet/LinearMath/btVector3.h1336
-rw-r--r--thirdparty/bullet/VERSION.txt1
-rw-r--r--thirdparty/bullet/btBulletCollisionAll.cpp97
-rw-r--r--thirdparty/bullet/btBulletCollisionCommon.h65
-rw-r--r--thirdparty/bullet/btBulletDynamicsAll.cpp42
-rw-r--r--thirdparty/bullet/btBulletDynamicsCommon.h43
-rw-r--r--thirdparty/bullet/btLinearMathAll.cpp15
-rw-r--r--thirdparty/bullet/clew/clew.c374
-rw-r--r--thirdparty/bullet/clew/clew.h2708
-rw-r--r--thirdparty/bullet/patches/bullet-fix-warnings.patch42
-rw-r--r--thirdparty/bullet/patches/fix-win32-scheduler-uwp.patch24
-rw-r--r--thirdparty/certs/ca-certificates.crt638
-rw-r--r--thirdparty/doctest/doctest.h2961
-rw-r--r--thirdparty/enet/godot.cpp17
-rw-r--r--thirdparty/etcpak/AUTHORS.txt2
-rw-r--r--thirdparty/etcpak/LICENSE.txt2
-rw-r--r--thirdparty/etcpak/ProcessRGB.cpp1092
-rw-r--r--thirdparty/fonts/DroidSansFallback.ttfbin3640264 -> 0 bytes
-rw-r--r--thirdparty/fonts/DroidSansFallback.woff2bin0 -> 1192544 bytes
-rw-r--r--thirdparty/fonts/DroidSansJapanese.ttfbin1173140 -> 0 bytes
-rw-r--r--thirdparty/fonts/DroidSansJapanese.woff2bin0 -> 450032 bytes
-rw-r--r--thirdparty/fonts/JetBrainsMono_Regular.ttfbin203952 -> 0 bytes
-rw-r--r--thirdparty/fonts/JetBrainsMono_Regular.woff2bin0 -> 69168 bytes
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Bold.ttfbin148972 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Bold.woff2bin0 -> 57612 bytes
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Regular.ttfbin150460 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoNaskhArabicUI_Regular.woff2bin0 -> 57340 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Bold.ttfbin123308 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Bold.woff2bin0 -> 44496 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Regular.ttfbin125436 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansBengaliUI_Regular.woff2bin0 -> 43568 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Bold.ttfbin146272 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Bold.woff2bin0 -> 44084 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Regular.ttfbin145348 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansDevanagariUI_Regular.woff2bin0 -> 43724 bytes
-rw-r--r--thirdparty/fonts/NotoSansGeorgian_Bold.ttfbin27024 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansGeorgian_Bold.woff2bin0 -> 11660 bytes
-rw-r--r--thirdparty/fonts/NotoSansGeorgian_Regular.ttfbin26940 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansGeorgian_Regular.woff2bin0 -> 11340 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Bold.ttfbin17592 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Bold.woff2bin0 -> 6692 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Regular.ttfbin17556 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansHebrew_Regular.woff2bin0 -> 6680 bytes
-rw-r--r--thirdparty/fonts/NotoSansMalayalamUI_Bold.ttfbin61084 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansMalayalamUI_Bold.woff2bin0 -> 22736 bytes
-rw-r--r--thirdparty/fonts/NotoSansMalayalamUI_Regular.ttfbin61264 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansMalayalamUI_Regular.woff2bin0 -> 23080 bytes
-rw-r--r--thirdparty/fonts/NotoSansOriyaUI_Bold.ttfbin96424 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansOriyaUI_Bold.woff2bin0 -> 36520 bytes
-rw-r--r--thirdparty/fonts/NotoSansOriyaUI_Regular.ttfbin96996 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansOriyaUI_Regular.woff2bin0 -> 36020 bytes
-rw-r--r--thirdparty/fonts/NotoSansSinhalaUI_Bold.ttfbin183444 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansSinhalaUI_Bold.woff2bin0 -> 40128 bytes
-rw-r--r--thirdparty/fonts/NotoSansSinhalaUI_Regular.ttfbin188112 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansSinhalaUI_Regular.woff2bin0 -> 40124 bytes
-rw-r--r--thirdparty/fonts/NotoSansTamilUI_Bold.ttfbin44588 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansTamilUI_Bold.woff2bin0 -> 17400 bytes
-rw-r--r--thirdparty/fonts/NotoSansTamilUI_Regular.ttfbin44820 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansTamilUI_Regular.woff2bin0 -> 17160 bytes
-rw-r--r--thirdparty/fonts/NotoSansTeluguUI_Bold.ttfbin127720 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansTeluguUI_Bold.woff2bin0 -> 37228 bytes
-rw-r--r--thirdparty/fonts/NotoSansTeluguUI_Regular.ttfbin127912 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansTeluguUI_Regular.woff2bin0 -> 36816 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Bold.ttfbin21820 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Bold.woff2bin0 -> 9420 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Regular.ttfbin22044 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSansThaiUI_Regular.woff2bin0 -> 9468 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Bold.ttfbin313792 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Bold.woff2bin0 -> 115376 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Regular.ttfbin313144 -> 0 bytes
-rw-r--r--thirdparty/fonts/NotoSans_Regular.woff2bin0 -> 117840 bytes
-rw-r--r--thirdparty/fonts/OpenSans_SemiBold.ttfbin100820 -> 0 bytes
-rw-r--r--thirdparty/fonts/OpenSans_SemiBold.woff2bin0 -> 46392 bytes
-rw-r--r--thirdparty/freetype/include/freetype/config/ftconfig.h2
-rw-r--r--thirdparty/freetype/include/freetype/config/ftheader.h14
-rw-r--r--thirdparty/freetype/include/freetype/config/ftmodule.h1
-rw-r--r--thirdparty/freetype/include/freetype/config/ftoption.h22
-rw-r--r--thirdparty/freetype/include/freetype/config/ftstdlib.h2
-rw-r--r--thirdparty/freetype/include/freetype/config/integer-types.h7
-rw-r--r--thirdparty/freetype/include/freetype/config/mac-support.h2
-rw-r--r--thirdparty/freetype/include/freetype/config/public-macros.h2
-rw-r--r--thirdparty/freetype/include/freetype/freetype.h278
-rw-r--r--thirdparty/freetype/include/freetype/ftadvanc.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbbox.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbitmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftbzip2.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcache.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftchapters.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcid.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftcolor.h8
-rw-r--r--thirdparty/freetype/include/freetype/ftdriver.h75
-rw-r--r--thirdparty/freetype/include/freetype/fterrdef.h6
-rw-r--r--thirdparty/freetype/include/freetype/fterrors.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgasp.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftglyph.h102
-rw-r--r--thirdparty/freetype/include/freetype/ftgxval.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftgzip.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftimage.h19
-rw-r--r--thirdparty/freetype/include/freetype/ftincrem.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlcdfil.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlist.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlogging.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftlzw.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmac.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmm.h5
-rw-r--r--thirdparty/freetype/include/freetype/ftmodapi.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftmoderr.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftoutln.h14
-rw-r--r--thirdparty/freetype/include/freetype/ftparams.h17
-rw-r--r--thirdparty/freetype/include/freetype/ftpfr.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftrender.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsizes.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsnames.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftstroke.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsynth.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftsystem.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttrigon.h2
-rw-r--r--thirdparty/freetype/include/freetype/fttypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/ftwinfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/autohint.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/cffotypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/cfftypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/compiler-macros.h8
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftcalc.h15
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdebug.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftdrv.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftgloadr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftmemory.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftobjs.h5
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftpsprop.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftrfork.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftserv.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftstream.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/fttrace.h6
-rw-r--r--thirdparty/freetype/include/freetype/internal/ftvalid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/psaux.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/pshints.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svbdf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcfftl.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svcid.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svfntfmt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgldict.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svgxval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svkern.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmetric.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svmm.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svotval.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpfr.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpostnm.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svprop.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpscmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svpsinfo.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svsfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttcmap.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svtteng.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svttglyf.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/services/svwinfnt.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/sfnt.h44
-rw-r--r--thirdparty/freetype/include/freetype/internal/svginterface.h46
-rw-r--r--thirdparty/freetype/include/freetype/internal/t1types.h2
-rw-r--r--thirdparty/freetype/include/freetype/internal/tttypes.h14
-rw-r--r--thirdparty/freetype/include/freetype/internal/wofftypes.h2
-rw-r--r--thirdparty/freetype/include/freetype/otsvg.h336
-rw-r--r--thirdparty/freetype/include/freetype/t1tables.h168
-rw-r--r--thirdparty/freetype/include/freetype/ttnameid.h2
-rw-r--r--thirdparty/freetype/include/freetype/tttables.h2
-rw-r--r--thirdparty/freetype/include/freetype/tttags.h3
-rw-r--r--thirdparty/freetype/include/ft2build.h2
-rw-r--r--thirdparty/freetype/patches/fix_gcc_lto_build.diff34
-rw-r--r--thirdparty/freetype/src/autofit/afblue.c2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.cin2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.dat1121
-rw-r--r--thirdparty/freetype/src/autofit/afblue.h2
-rw-r--r--thirdparty/freetype/src/autofit/afblue.hin2
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.c14
-rw-r--r--thirdparty/freetype/src/autofit/afcjk.h2
-rw-r--r--thirdparty/freetype/src/autofit/afcover.h2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.c2
-rw-r--r--thirdparty/freetype/src/autofit/afdummy.h2
-rw-r--r--thirdparty/freetype/src/autofit/aferrors.h2
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.c10
-rw-r--r--thirdparty/freetype/src/autofit/afglobal.h2
-rw-r--r--thirdparty/freetype/src/autofit/afhints.c6
-rw-r--r--thirdparty/freetype/src/autofit/afhints.h2
-rw-r--r--thirdparty/freetype/src/autofit/afindic.c2
-rw-r--r--thirdparty/freetype/src/autofit/afindic.h2
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.c12
-rw-r--r--thirdparty/freetype/src/autofit/aflatin.h2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.c2
-rw-r--r--thirdparty/freetype/src/autofit/afloader.h2
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.c2
-rw-r--r--thirdparty/freetype/src/autofit/afmodule.h2
-rw-r--r--thirdparty/freetype/src/autofit/afranges.c2
-rw-r--r--thirdparty/freetype/src/autofit/afranges.h2
-rw-r--r--thirdparty/freetype/src/autofit/afscript.h2
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.c2
-rw-r--r--thirdparty/freetype/src/autofit/afshaper.h2
-rw-r--r--thirdparty/freetype/src/autofit/afstyles.h2
-rw-r--r--thirdparty/freetype/src/autofit/aftypes.h2
-rw-r--r--thirdparty/freetype/src/autofit/afws-decl.h2
-rw-r--r--thirdparty/freetype/src/autofit/afws-iter.h2
-rw-r--r--thirdparty/freetype/src/autofit/autofit.c2
-rw-r--r--thirdparty/freetype/src/base/ftadvanc.c2
-rw-r--r--thirdparty/freetype/src/base/ftbase.c2
-rw-r--r--thirdparty/freetype/src/base/ftbase.h3
-rw-r--r--thirdparty/freetype/src/base/ftbbox.c2
-rw-r--r--thirdparty/freetype/src/base/ftbdf.c2
-rw-r--r--thirdparty/freetype/src/base/ftbitmap.c10
-rw-r--r--thirdparty/freetype/src/base/ftcalc.c2
-rw-r--r--thirdparty/freetype/src/base/ftcid.c2
-rw-r--r--thirdparty/freetype/src/base/ftcolor.c2
-rw-r--r--thirdparty/freetype/src/base/ftdbgmem.c2
-rw-r--r--thirdparty/freetype/src/base/ftdebug.c2
-rw-r--r--thirdparty/freetype/src/base/fterrors.c2
-rw-r--r--thirdparty/freetype/src/base/ftfntfmt.c2
-rw-r--r--thirdparty/freetype/src/base/ftfstype.c2
-rw-r--r--thirdparty/freetype/src/base/ftgasp.c2
-rw-r--r--thirdparty/freetype/src/base/ftgloadr.c2
-rw-r--r--thirdparty/freetype/src/base/ftglyph.c253
-rw-r--r--thirdparty/freetype/src/base/ftgxval.c2
-rw-r--r--thirdparty/freetype/src/base/fthash.c2
-rw-r--r--thirdparty/freetype/src/base/ftinit.c2
-rw-r--r--thirdparty/freetype/src/base/ftlcdfil.c2
-rw-r--r--thirdparty/freetype/src/base/ftmac.c8
-rw-r--r--thirdparty/freetype/src/base/ftmm.c2
-rw-r--r--thirdparty/freetype/src/base/ftobjs.c118
-rw-r--r--thirdparty/freetype/src/base/ftotval.c2
-rw-r--r--thirdparty/freetype/src/base/ftoutln.c2
-rw-r--r--thirdparty/freetype/src/base/ftpatent.c2
-rw-r--r--thirdparty/freetype/src/base/ftpfr.c2
-rw-r--r--thirdparty/freetype/src/base/ftpsprop.c2
-rw-r--r--thirdparty/freetype/src/base/ftrfork.c28
-rw-r--r--thirdparty/freetype/src/base/ftsnames.c2
-rw-r--r--thirdparty/freetype/src/base/ftstream.c2
-rw-r--r--thirdparty/freetype/src/base/ftstroke.c2
-rw-r--r--thirdparty/freetype/src/base/ftsynth.c2
-rw-r--r--thirdparty/freetype/src/base/ftsystem.c2
-rw-r--r--thirdparty/freetype/src/base/fttrigon.c2
-rw-r--r--thirdparty/freetype/src/base/fttype1.c2
-rw-r--r--thirdparty/freetype/src/base/ftutil.c2
-rw-r--r--thirdparty/freetype/src/base/ftver.rc61
-rw-r--r--thirdparty/freetype/src/base/ftwinfnt.c2
-rw-r--r--thirdparty/freetype/src/bdf/README148
-rw-r--r--thirdparty/freetype/src/bdf/bdflib.c8
-rw-r--r--thirdparty/freetype/src/bzip2/ftbzip2.c47
-rw-r--r--thirdparty/freetype/src/cache/ftcache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcbasic.c6
-rw-r--r--thirdparty/freetype/src/cache/ftccache.c2
-rw-r--r--thirdparty/freetype/src/cache/ftccache.h4
-rw-r--r--thirdparty/freetype/src/cache/ftccback.h2
-rw-r--r--thirdparty/freetype/src/cache/ftccmap.c4
-rw-r--r--thirdparty/freetype/src/cache/ftcerror.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcglyph.h8
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.c5
-rw-r--r--thirdparty/freetype/src/cache/ftcimage.h8
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.c2
-rw-r--r--thirdparty/freetype/src/cache/ftcmanag.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.c6
-rw-r--r--thirdparty/freetype/src/cache/ftcmru.h2
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.c10
-rw-r--r--thirdparty/freetype/src/cache/ftcsbits.h4
-rw-r--r--thirdparty/freetype/src/cff/cff.c2
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.c4
-rw-r--r--thirdparty/freetype/src/cff/cffcmap.h2
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.c2
-rw-r--r--thirdparty/freetype/src/cff/cffdrivr.h2
-rw-r--r--thirdparty/freetype/src/cff/cfferrs.h2
-rw-r--r--thirdparty/freetype/src/cff/cffgload.c88
-rw-r--r--thirdparty/freetype/src/cff/cffgload.h2
-rw-r--r--thirdparty/freetype/src/cff/cffload.c2
-rw-r--r--thirdparty/freetype/src/cff/cffload.h2
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.c6
-rw-r--r--thirdparty/freetype/src/cff/cffobjs.h2
-rw-r--r--thirdparty/freetype/src/cff/cffparse.c2
-rw-r--r--thirdparty/freetype/src/cff/cffparse.h2
-rw-r--r--thirdparty/freetype/src/cff/cfftoken.h2
-rw-r--r--thirdparty/freetype/src/cid/ciderrs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidgload.c2
-rw-r--r--thirdparty/freetype/src/cid/cidgload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidload.c2
-rw-r--r--thirdparty/freetype/src/cid/cidload.h2
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.c2
-rw-r--r--thirdparty/freetype/src/cid/cidobjs.h2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.c2
-rw-r--r--thirdparty/freetype/src/cid/cidparse.h2
-rw-r--r--thirdparty/freetype/src/cid/cidriver.c2
-rw-r--r--thirdparty/freetype/src/cid/cidriver.h2
-rw-r--r--thirdparty/freetype/src/cid/cidtoken.h2
-rw-r--r--thirdparty/freetype/src/cid/type1cid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/README532
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvalid.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvbsln.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.c6
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvcommn.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxverror.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfeat.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvfgen.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvjust.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvkern.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvlcar.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmod.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmort5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx.h2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx0.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx1.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx2.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx4.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvmorx5.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvopbd.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvprop.c2
-rw-r--r--thirdparty/freetype/src/gxvalid/gxvtrak.c2
-rw-r--r--thirdparty/freetype/src/gzip/adler32.c188
-rw-r--r--thirdparty/freetype/src/gzip/crc32.c1116
-rw-r--r--thirdparty/freetype/src/gzip/crc32.h9446
-rw-r--r--thirdparty/freetype/src/gzip/ftgzip.c62
-rw-r--r--thirdparty/freetype/src/gzip/ftzconf.h530
-rw-r--r--thirdparty/freetype/src/gzip/gzguts.h219
-rw-r--r--thirdparty/freetype/src/gzip/infback.c641
-rw-r--r--thirdparty/freetype/src/gzip/infblock.c392
-rw-r--r--thirdparty/freetype/src/gzip/infblock.h36
-rw-r--r--thirdparty/freetype/src/gzip/infcodes.c254
-rw-r--r--thirdparty/freetype/src/gzip/infcodes.h31
-rw-r--r--thirdparty/freetype/src/gzip/inffast.c323
-rw-r--r--thirdparty/freetype/src/gzip/inffast.h11
-rw-r--r--thirdparty/freetype/src/gzip/inffixed.h241
-rw-r--r--thirdparty/freetype/src/gzip/inflate.c1843
-rw-r--r--thirdparty/freetype/src/gzip/inflate.h131
-rw-r--r--thirdparty/freetype/src/gzip/inftrees.c710
-rw-r--r--thirdparty/freetype/src/gzip/inftrees.h112
-rw-r--r--thirdparty/freetype/src/gzip/infutil.c86
-rw-r--r--thirdparty/freetype/src/gzip/infutil.h98
-rw-r--r--thirdparty/freetype/src/gzip/zlib.h1962
-rw-r--r--thirdparty/freetype/src/gzip/zutil.c232
-rw-r--r--thirdparty/freetype/src/gzip/zutil.h197
-rw-r--r--thirdparty/freetype/src/lzw/ftlzw.c4
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.c2
-rw-r--r--thirdparty/freetype/src/lzw/ftzopen.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvalid.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvbase.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvcommn.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otverror.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgdef.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgpos.h2
-rw-r--r--thirdparty/freetype/src/otvalid/otvgsub.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvjstf.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmath.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.c2
-rw-r--r--thirdparty/freetype/src/otvalid/otvmod.h2
-rw-r--r--thirdparty/freetype/src/pcf/README96
-rw-r--r--thirdparty/freetype/src/pcf/pcfread.c25
-rw-r--r--thirdparty/freetype/src/pfr/pfr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrcmap.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrdrivr.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrerror.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrgload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.c4
-rw-r--r--thirdparty/freetype/src/pfr/pfrload.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.c4
-rw-r--r--thirdparty/freetype/src/pfr/pfrobjs.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.c2
-rw-r--r--thirdparty/freetype/src/pfr/pfrsbit.h2
-rw-r--r--thirdparty/freetype/src/pfr/pfrtypes.h2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.c2
-rw-r--r--thirdparty/freetype/src/psaux/afmparse.h2
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.c4
-rw-r--r--thirdparty/freetype/src/psaux/cffdecode.h2
-rw-r--r--thirdparty/freetype/src/psaux/psaux.c2
-rw-r--r--thirdparty/freetype/src/psaux/psauxerr.h2
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.c2
-rw-r--r--thirdparty/freetype/src/psaux/psauxmod.h2
-rw-r--r--thirdparty/freetype/src/psaux/psconv.c10
-rw-r--r--thirdparty/freetype/src/psaux/psconv.h2
-rw-r--r--thirdparty/freetype/src/psaux/psintrp.c16
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.c81
-rw-r--r--thirdparty/freetype/src/psaux/psobjs.h2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.c2
-rw-r--r--thirdparty/freetype/src/psaux/t1cmap.h2
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.c2
-rw-r--r--thirdparty/freetype/src/psaux/t1decode.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.c41
-rw-r--r--thirdparty/freetype/src/pshinter/pshalgo.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.c4
-rw-r--r--thirdparty/freetype/src/pshinter/pshglob.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshinter.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.c2
-rw-r--r--thirdparty/freetype/src/pshinter/pshmod.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshnterr.h2
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.c105
-rw-r--r--thirdparty/freetype/src/pshinter/pshrec.h2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.c2
-rw-r--r--thirdparty/freetype/src/psnames/psmodule.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnamerr.h2
-rw-r--r--thirdparty/freetype/src/psnames/psnames.c2
-rw-r--r--thirdparty/freetype/src/psnames/pstables.h2
-rw-r--r--thirdparty/freetype/src/raster/ftmisc.h2
-rw-r--r--thirdparty/freetype/src/raster/ftraster.c4
-rw-r--r--thirdparty/freetype/src/raster/ftraster.h2
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.c2
-rw-r--r--thirdparty/freetype/src/raster/ftrend1.h2
-rw-r--r--thirdparty/freetype/src/raster/raster.c2
-rw-r--r--thirdparty/freetype/src/raster/rasterrs.h2
-rw-r--r--thirdparty/freetype/src/sdf/ftbsdf.c36
-rw-r--r--thirdparty/freetype/src/sdf/ftsdf.c101
-rw-r--r--thirdparty/freetype/src/sdf/ftsdf.h2
-rw-r--r--thirdparty/freetype/src/sdf/ftsdfcommon.c2
-rw-r--r--thirdparty/freetype/src/sdf/ftsdfcommon.h4
-rw-r--r--thirdparty/freetype/src/sdf/ftsdferrs.h2
-rw-r--r--thirdparty/freetype/src/sdf/ftsdfrend.c20
-rw-r--r--thirdparty/freetype/src/sdf/ftsdfrend.h2
-rw-r--r--thirdparty/freetype/src/sdf/sdf.c2
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.c6
-rw-r--r--thirdparty/freetype/src/sfnt/pngshim.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.c29
-rw-r--r--thirdparty/freetype/src/sfnt/sfdriver.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sferrors.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfnt.c3
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.c83
-rw-r--r--thirdparty/freetype/src/sfnt/sfobjs.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff.c3
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff.h2
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff2.c70
-rw-r--r--thirdparty/freetype/src/sfnt/sfwoff2.h3
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttbdf.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.c4
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmap.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcmapc.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.c43
-rw-r--r--thirdparty/freetype/src/sfnt/ttcolr.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttcpal.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.c21
-rw-r--r--thirdparty/freetype/src/sfnt/ttkern.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.c3
-rw-r--r--thirdparty/freetype/src/sfnt/ttload.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttmtx.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.c2
-rw-r--r--thirdparty/freetype/src/sfnt/ttpost.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.c37
-rw-r--r--thirdparty/freetype/src/sfnt/ttsbit.h2
-rw-r--r--thirdparty/freetype/src/sfnt/ttsvg.c403
-rw-r--r--thirdparty/freetype/src/sfnt/ttsvg.h43
-rw-r--r--thirdparty/freetype/src/sfnt/woff2tags.c2
-rw-r--r--thirdparty/freetype/src/sfnt/woff2tags.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.c13
-rw-r--r--thirdparty/freetype/src/smooth/ftgrays.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmerrs.h2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.c2
-rw-r--r--thirdparty/freetype/src/smooth/ftsmooth.h2
-rw-r--r--thirdparty/freetype/src/smooth/smooth.c2
-rw-r--r--thirdparty/freetype/src/svg/ftsvg.c350
-rw-r--r--thirdparty/freetype/src/svg/ftsvg.h35
-rw-r--r--thirdparty/freetype/src/svg/svg.c24
-rw-r--r--thirdparty/freetype/src/svg/svgtypes.h42
-rw-r--r--thirdparty/freetype/src/truetype/truetype.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttdriver.h2
-rw-r--r--thirdparty/freetype/src/truetype/tterrors.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.c227
-rw-r--r--thirdparty/freetype/src/truetype/ttgload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.c18
-rw-r--r--thirdparty/freetype/src/truetype/ttgxvar.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.c55
-rw-r--r--thirdparty/freetype/src/truetype/ttinterp.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.c7
-rw-r--r--thirdparty/freetype/src/truetype/ttobjs.h4
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.c52
-rw-r--r--thirdparty/freetype/src/truetype/ttpload.h2
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.c2
-rw-r--r--thirdparty/freetype/src/truetype/ttsubpix.h2
-rw-r--r--thirdparty/freetype/src/type1/t1afm.c4
-rw-r--r--thirdparty/freetype/src/type1/t1afm.h2
-rw-r--r--thirdparty/freetype/src/type1/t1driver.c2
-rw-r--r--thirdparty/freetype/src/type1/t1driver.h2
-rw-r--r--thirdparty/freetype/src/type1/t1errors.h2
-rw-r--r--thirdparty/freetype/src/type1/t1gload.c2
-rw-r--r--thirdparty/freetype/src/type1/t1gload.h2
-rw-r--r--thirdparty/freetype/src/type1/t1load.c20
-rw-r--r--thirdparty/freetype/src/type1/t1load.h2
-rw-r--r--thirdparty/freetype/src/type1/t1objs.c2
-rw-r--r--thirdparty/freetype/src/type1/t1objs.h2
-rw-r--r--thirdparty/freetype/src/type1/t1parse.c2
-rw-r--r--thirdparty/freetype/src/type1/t1parse.h2
-rw-r--r--thirdparty/freetype/src/type1/t1tokens.h2
-rw-r--r--thirdparty/freetype/src/type1/type1.c2
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.c15
-rw-r--r--thirdparty/freetype/src/type42/t42drivr.h2
-rw-r--r--thirdparty/freetype/src/type42/t42error.h2
-rw-r--r--thirdparty/freetype/src/type42/t42objs.c17
-rw-r--r--thirdparty/freetype/src/type42/t42objs.h2
-rw-r--r--thirdparty/freetype/src/type42/t42parse.c69
-rw-r--r--thirdparty/freetype/src/type42/t42parse.h2
-rw-r--r--thirdparty/freetype/src/type42/t42types.h2
-rw-r--r--thirdparty/freetype/src/type42/type42.c2
-rw-r--r--thirdparty/freetype/src/winfonts/fnterrs.h2
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.c10
-rw-r--r--thirdparty/freetype/src/winfonts/winfnt.h2
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh338
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh126
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh233
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh85
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh84
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh46
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh58
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh70
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh77
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh14
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh32
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh14
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh35
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh301
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh17
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh171
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh56
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh128
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh41
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh219
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh41
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh206
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh42
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh228
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh52
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh46
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh193
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh328
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh189
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh99
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh79
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh79
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh95
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh138
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh154
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh329
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh126
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh62
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh128
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh18
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh21
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh18
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh22
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh61
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh187
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh119
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh71
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh166
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh64
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh121
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh36
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh244
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh165
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh103
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh163
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh136
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh223
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh77
-rw-r--r--thirdparty/harfbuzz/src/OT/Layout/types.hh66
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh298
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/Glyph.hh235
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh50
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh216
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh72
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh90
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf.hh397
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/loca.hh43
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/path-builder.hh135
-rw-r--r--thirdparty/harfbuzz/src/graph/coverage-graph.hh80
-rw-r--r--thirdparty/harfbuzz/src/graph/graph.hh1046
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-context.cc71
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-context.hh67
-rw-r--r--thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh351
-rw-r--r--thirdparty/harfbuzz/src/graph/pairpos-graph.hh299
-rw-r--r--thirdparty/harfbuzz/src/graph/serialize.hh249
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-common.hh20
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh10
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-layout.cc9
-rw-r--r--thirdparty/harfbuzz/src/hb-aat-map.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-algs.hh79
-rw-r--r--thirdparty/harfbuzz/src/hb-array.hh42
-rw-r--r--thirdparty/harfbuzz/src/hb-atomic.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-bimap.hh15
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-page.hh83
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set-invertible.hh19
-rw-r--r--thirdparty/harfbuzz/src/hb-bit-set.hh197
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.cc22
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-blob.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh431
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh588
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-serialize.cc32
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer-verify.cc440
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.cc122
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.h127
-rw-r--r--thirdparty/harfbuzz/src/hb-buffer.hh80
-rw-r--r--thirdparty/harfbuzz/src/hb-cache.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-cff-interp-common.hh118
-rw-r--r--thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh24
-rw-r--r--thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh2
-rw-r--r--thirdparty/harfbuzz/src/hb-cff1-interp-cs.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh89
-rw-r--r--thirdparty/harfbuzz/src/hb-common.cc62
-rw-r--r--thirdparty/harfbuzz/src/hb-common.h19
-rw-r--r--thirdparty/harfbuzz/src/hb-config.hh20
-rw-r--r--thirdparty/harfbuzz/src/hb-coretext.cc74
-rw-r--r--thirdparty/harfbuzz/src/hb-cplusplus.hh221
-rw-r--r--thirdparty/harfbuzz/src/hb-debug.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-deprecated.h2
-rw-r--r--thirdparty/harfbuzz/src/hb-directwrite.cc43
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.cc405
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.h285
-rw-r--r--thirdparty/harfbuzz/src/hb-draw.hh246
-rw-r--r--thirdparty/harfbuzz/src/hb-face.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-font.cc391
-rw-r--r--thirdparty/harfbuzz/src/hb-font.h71
-rw-r--r--thirdparty/harfbuzz/src/hb-font.hh85
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.cc369
-rw-r--r--thirdparty/harfbuzz/src/hb-ft.h9
-rw-r--r--thirdparty/harfbuzz/src/hb-gobject-structs.cc1
-rw-r--r--thirdparty/harfbuzz/src/hb-gobject-structs.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-graphite2.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-iter.hh18
-rw-r--r--thirdparty/harfbuzz/src/hb-machinery.hh16
-rw-r--r--thirdparty/harfbuzz/src/hb-map.cc72
-rw-r--r--thirdparty/harfbuzz/src/hb-map.h12
-rw-r--r--thirdparty/harfbuzz/src/hb-map.hh225
-rw-r--r--thirdparty/harfbuzz/src/hb-meta.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-null.hh35
-rw-r--r--thirdparty/harfbuzz/src/hb-object.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-open-type.hh58
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff-common.hh182
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.cc79
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff1-table.hh174
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.cc60
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cff2-table.hh34
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-cmap-table.hh200
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh65
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color.cc8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-color.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-deprecated.h15
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face-table-list.hh13
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-face.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-font.cc243
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-glyf-table.hh1330
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh233
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh22
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh1736
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh378
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh3094
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh1732
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh1318
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.cc407
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.h62
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout.hh24
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.cc27
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-map.hh28
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math-table.hh78
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.cc49
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-math.h36
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.cc151
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-metrics.h5
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-language-static.hh12
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name-table.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-name.cc2
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-os2-table.hh4
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh14
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-post-table.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh348
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh47
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh441
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh349
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc737
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh50
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc73
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc436
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc185
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh603
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc501
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc1572
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh430
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh396
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc370
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh115
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh492
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc321
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh177
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc103
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh42
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc393
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh576
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh1283
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc502
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc443
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh39
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-complex.hh400
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc6
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc11
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.cc93
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shape.hh8
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh376
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh47
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh118
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh556
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh349
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc752
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh50
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-default.cc73
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc436
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc211
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh589
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc560
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc1540
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh66
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh428
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc382
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh553
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc356
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc98
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh47
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc393
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh931
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh418
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-use.cc504
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc443
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh39
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-shaper.hh397
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-stat-table.hh262
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag-table.hh3564
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-tag.cc131
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh82
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-common.hh63
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh65
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh153
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-var.cc4
-rw-r--r--thirdparty/harfbuzz/src/hb-priority-queue.hh32
-rw-r--r--thirdparty/harfbuzz/src/hb-repacker.hh1209
-rw-r--r--thirdparty/harfbuzz/src/hb-serialize.hh56
-rw-r--r--thirdparty/harfbuzz/src/hb-set-digest.hh30
-rw-r--r--thirdparty/harfbuzz/src/hb-set.cc94
-rw-r--r--thirdparty/harfbuzz/src/hb-set.h16
-rw-r--r--thirdparty/harfbuzz/src/hb-set.hh34
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.cc21
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-shape-plan.hh3
-rw-r--r--thirdparty/harfbuzz/src/hb-shape.cc48
-rw-r--r--thirdparty/harfbuzz/src/hb-shaper.cc16
-rw-r--r--thirdparty/harfbuzz/src/hb-static.cc47
-rw-r--r--thirdparty/harfbuzz/src/hb-style.cc7
-rw-r--r--thirdparty/harfbuzz/src/hb-style.h4
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff-common.hh103
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff1.cc22
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-cff2.cc28
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.cc81
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-input.hh5
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.cc615
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-plan.hh44
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-repacker.cc58
-rw-r--r--thirdparty/harfbuzz/src/hb-subset-repacker.h81
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.cc279
-rw-r--r--thirdparty/harfbuzz/src/hb-subset.h64
-rw-r--r--thirdparty/harfbuzz/src/hb-ucd-table.hh5286
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh59
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.cc14
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.h8
-rw-r--r--thirdparty/harfbuzz/src/hb-unicode.hh7
-rw-r--r--thirdparty/harfbuzz/src/hb-vector.hh96
-rw-r--r--thirdparty/harfbuzz/src/hb-version.h8
-rw-r--r--thirdparty/harfbuzz/src/hb.hh5
-rw-r--r--thirdparty/icu4c/LICENSE125
-rw-r--r--thirdparty/icu4c/common/brkeng.cpp1
-rw-r--r--thirdparty/icu4c/common/brkeng.h2
-rw-r--r--thirdparty/icu4c/common/brkiter.cpp31
-rw-r--r--thirdparty/icu4c/common/dictbe.cpp165
-rw-r--r--thirdparty/icu4c/common/dictbe.h27
-rw-r--r--thirdparty/icu4c/common/localematcher.cpp42
-rw-r--r--thirdparty/icu4c/common/locid.cpp18
-rw-r--r--thirdparty/icu4c/common/lstmbe.cpp3
-rw-r--r--thirdparty/icu4c/common/lstmbe.h1
-rw-r--r--thirdparty/icu4c/common/normalizer2impl.cpp11
-rw-r--r--thirdparty/icu4c/common/rbbi.cpp14
-rw-r--r--thirdparty/icu4c/common/rbbi_cache.cpp2
-rw-r--r--thirdparty/icu4c/common/serv.cpp5
-rw-r--r--thirdparty/icu4c/common/servls.cpp3
-rw-r--r--thirdparty/icu4c/common/servnotf.cpp18
-rw-r--r--thirdparty/icu4c/common/ubrk.cpp12
-rw-r--r--thirdparty/icu4c/common/ucase.cpp40
-rw-r--r--thirdparty/icu4c/common/ucase.h15
-rw-r--r--thirdparty/icu4c/common/ucasemap.cpp115
-rw-r--r--thirdparty/icu4c/common/ucnv.cpp11
-rw-r--r--thirdparty/icu4c/common/ucurr.cpp2
-rw-r--r--thirdparty/icu4c/common/uloc.cpp6
-rw-r--r--thirdparty/icu4c/common/unicode/localematcher.h6
-rw-r--r--thirdparty/icu4c/common/unicode/rbbi.h20
-rw-r--r--thirdparty/icu4c/common/unicode/ubrk.h11
-rw-r--r--thirdparty/icu4c/common/unicode/ucnv.h26
-rw-r--r--thirdparty/icu4c/common/unicode/uniset.h4
-rw-r--r--thirdparty/icu4c/common/unicode/urename.h5
-rw-r--r--thirdparty/icu4c/common/unicode/uset.h18
-rw-r--r--thirdparty/icu4c/common/unicode/uvernum.h10
-rw-r--r--thirdparty/icu4c/common/unistr.cpp8
-rw-r--r--thirdparty/icu4c/common/ustrcase.cpp130
-rw-r--r--thirdparty/icu4c/common/uvector.cpp43
-rw-r--r--thirdparty/icu4c/common/uvector.h12
-rw-r--r--thirdparty/icu4c/common/uvectr32.cpp2
-rw-r--r--thirdparty/icu4c/common/uvectr32.h6
-rw-r--r--thirdparty/icu4c/godot_data.json3
-rw-r--r--thirdparty/icu4c/i18n/scriptset.cpp313
-rw-r--r--thirdparty/icu4c/i18n/scriptset.h86
-rw-r--r--thirdparty/icu4c/i18n/ucln_in.cpp65
-rw-r--r--thirdparty/icu4c/i18n/ucln_in.h74
-rw-r--r--thirdparty/icu4c/i18n/unicode/uspoof.h1577
-rw-r--r--thirdparty/icu4c/i18n/uspoof.cpp839
-rw-r--r--thirdparty/icu4c/i18n/uspoof_impl.cpp959
-rw-r--r--thirdparty/icu4c/i18n/uspoof_impl.h343
-rw-r--r--thirdparty/icu4c/icudt70l.datbin4141152 -> 0 bytes
-rw-r--r--thirdparty/icu4c/icudt71l.datbin0 -> 4271680 bytes
-rw-r--r--thirdparty/jpeg-compressor/jpge.cpp1076
-rw-r--r--thirdparty/jpeg-compressor/jpge.h174
-rw-r--r--thirdparty/mbedtls/LICENSE205
-rw-r--r--thirdparty/mbedtls/include/godot_core_mbedtls_config.h5
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aes.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/aria.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/asn1.h12
-rw-r--r--thirdparty/mbedtls/include/mbedtls/bignum.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/blowfish.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/camellia.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/chachapoly.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/check_config.h49
-rw-r--r--thirdparty/mbedtls/include/mbedtls/config.h143
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ctr_drbg.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/debug.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecjpake.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ecp.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/entropy.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hkdf.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/hmac_drbg.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/oid.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pem.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/pk.h75
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform_time.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/platform_util.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/rsa.h6
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl.h36
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_cache.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_cookie.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_internal.h44
-rw-r--r--thirdparty/mbedtls/include/mbedtls/ssl_ticket.h2
-rw-r--r--thirdparty/mbedtls/include/mbedtls/version.h8
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509.h9
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crl.h4
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_crt.h15
-rw-r--r--thirdparty/mbedtls/include/mbedtls/x509_csr.h7
-rw-r--r--thirdparty/mbedtls/library/aes.c4
-rw-r--r--thirdparty/mbedtls/library/asn1write.c7
-rw-r--r--thirdparty/mbedtls/library/bignum.c4
-rw-r--r--thirdparty/mbedtls/library/cipher.c11
-rw-r--r--thirdparty/mbedtls/library/constant_time.c15
-rw-r--r--thirdparty/mbedtls/library/constant_time_internal.h7
-rw-r--r--thirdparty/mbedtls/library/ctr_drbg.c6
-rw-r--r--thirdparty/mbedtls/library/ecdh.c2
-rw-r--r--thirdparty/mbedtls/library/ecjpake.c2
-rw-r--r--thirdparty/mbedtls/library/ecp.c8
-rw-r--r--thirdparty/mbedtls/library/ecp_curves.c2
-rw-r--r--thirdparty/mbedtls/library/memory_buffer_alloc.c4
-rw-r--r--thirdparty/mbedtls/library/mps_common.h2
-rw-r--r--thirdparty/mbedtls/library/net_sockets.c2
-rw-r--r--thirdparty/mbedtls/library/pkparse.c10
-rw-r--r--thirdparty/mbedtls/library/rsa.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_ciphersuites.c1
-rw-r--r--thirdparty/mbedtls/library/ssl_cli.c111
-rw-r--r--thirdparty/mbedtls/library/ssl_cookie.c3
-rw-r--r--thirdparty/mbedtls/library/ssl_msg.c131
-rw-r--r--thirdparty/mbedtls/library/ssl_srv.c99
-rw-r--r--thirdparty/mbedtls/library/ssl_ticket.c4
-rw-r--r--thirdparty/mbedtls/library/ssl_tls.c58
-rw-r--r--thirdparty/mbedtls/library/threading.c2
-rw-r--r--thirdparty/mbedtls/library/timing.c9
-rw-r--r--thirdparty/mbedtls/library/x509.c21
-rw-r--r--thirdparty/mbedtls/library/x509_crl.c2
-rw-r--r--thirdparty/mbedtls/library/x509_crt.c2
-rw-r--r--thirdparty/mbedtls/library/x509write_crt.c2
-rw-r--r--thirdparty/meshoptimizer/allocator.cpp2
-rw-r--r--thirdparty/meshoptimizer/meshoptimizer.h65
-rw-r--r--thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch30
-rw-r--r--thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch30
-rw-r--r--thirdparty/meshoptimizer/simplifier.cpp10
-rw-r--r--thirdparty/minizip/crypt.h19
-rw-r--r--thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch295
-rw-r--r--thirdparty/minizip/ioapi.c18
-rw-r--r--thirdparty/minizip/ioapi.h8
-rw-r--r--thirdparty/minizip/patches/godot-seek.patch294
-rw-r--r--thirdparty/minizip/patches/unbreak-gentoo.patch (renamed from thirdparty/minizip/godot-zlib-1.2.4-minizip-unbreak-gentoo.patch)0
-rw-r--r--thirdparty/minizip/unzip.c60
-rw-r--r--thirdparty/minizip/unzip.h12
-rw-r--r--thirdparty/minizip/zip.c36
-rw-r--r--thirdparty/minizip/zip.h17
-rw-r--r--thirdparty/misc/ok_color.h688
-rw-r--r--thirdparty/misc/ok_color_shader.h663
-rw-r--r--thirdparty/misc/open-simplex-noise-LICENSE25
-rw-r--r--thirdparty/misc/open-simplex-noise-no-allocate.patch133
-rw-r--r--thirdparty/misc/open-simplex-noise.c2255
-rw-r--r--thirdparty/misc/open-simplex-noise.h58
-rw-r--r--thirdparty/misc/patches/polypartition-godot-types.patch2
-rw-r--r--thirdparty/misc/polypartition.cpp14
-rw-r--r--thirdparty/misc/polypartition.h6
-rw-r--r--thirdparty/misc/stb_rect_pack.h35
-rw-r--r--thirdparty/noise/FastNoise-LICENSE22
-rw-r--r--thirdparty/noise/FastNoiseLite.h2598
-rw-r--r--thirdparty/noise/patches/FastNoiseLite.patch455
-rw-r--r--thirdparty/openxr/COPYING.adoc123
-rw-r--r--thirdparty/openxr/LICENSE (renamed from thirdparty/mbedtls/apache-2.0.txt)0
-rw-r--r--thirdparty/openxr/include/openxr/openxr.h4466
-rw-r--r--thirdparty/openxr/include/openxr/openxr_platform.h690
-rw-r--r--thirdparty/openxr/include/openxr/openxr_platform_defines.h110
-rw-r--r--thirdparty/openxr/include/openxr/openxr_reflection.h3095
-rw-r--r--thirdparty/openxr/src/.clang-format10
-rw-r--r--thirdparty/openxr/src/common/extra_algorithms.h47
-rw-r--r--thirdparty/openxr/src/common/filesystem_utils.cpp322
-rw-r--r--thirdparty/openxr/src/common/filesystem_utils.hpp46
-rw-r--r--thirdparty/openxr/src/common/hex_and_handles.h108
-rw-r--r--thirdparty/openxr/src/common/loader_interfaces.h114
-rw-r--r--thirdparty/openxr/src/common/object_info.cpp276
-rw-r--r--thirdparty/openxr/src/common/object_info.h229
-rw-r--r--thirdparty/openxr/src/common/platform_utils.hpp345
-rw-r--r--thirdparty/openxr/src/common/stdfs_conditions.h45
-rw-r--r--thirdparty/openxr/src/common/xr_dependencies.h89
-rw-r--r--thirdparty/openxr/src/common/xr_linear.h787
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/AUTHORS115
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/LICENSE55
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h88
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h61
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/config.h150
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h43
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/json.h15
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h61
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/reader.h405
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/value.h935
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/version.h28
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/include/json/writer.h369
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp1992
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h138
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp1634
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl156
-rw-r--r--thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp1259
-rw-r--r--thirdparty/openxr/src/loader/.gitignore5
-rw-r--r--thirdparty/openxr/src/loader/android_utilities.cpp319
-rw-r--r--thirdparty/openxr/src/loader/android_utilities.h32
-rw-r--r--thirdparty/openxr/src/loader/api_layer_interface.cpp399
-rw-r--r--thirdparty/openxr/src/loader/api_layer_interface.hpp54
-rw-r--r--thirdparty/openxr/src/loader/exception_handling.hpp40
-rw-r--r--thirdparty/openxr/src/loader/loader_core.cpp847
-rw-r--r--thirdparty/openxr/src/loader/loader_instance.cpp303
-rw-r--r--thirdparty/openxr/src/loader/loader_instance.hpp77
-rw-r--r--thirdparty/openxr/src/loader/loader_logger.cpp239
-rw-r--r--thirdparty/openxr/src/loader/loader_logger.hpp194
-rw-r--r--thirdparty/openxr/src/loader/loader_logger_recorders.cpp291
-rw-r--r--thirdparty/openxr/src/loader/loader_logger_recorders.hpp40
-rw-r--r--thirdparty/openxr/src/loader/loader_platform.hpp204
-rw-r--r--thirdparty/openxr/src/loader/manifest_file.cpp845
-rw-r--r--thirdparty/openxr/src/loader/manifest_file.hpp103
-rw-r--r--thirdparty/openxr/src/loader/runtime_interface.cpp493
-rw-r--r--thirdparty/openxr/src/loader/runtime_interface.hpp84
-rw-r--r--thirdparty/openxr/src/loader/xr_generated_loader.cpp700
-rw-r--r--thirdparty/openxr/src/loader/xr_generated_loader.hpp252
-rw-r--r--thirdparty/openxr/src/xr_generated_dispatch_table.c377
-rw-r--r--thirdparty/openxr/src/xr_generated_dispatch_table.h385
-rw-r--r--thirdparty/pcre2/AUTHORS6
-rw-r--r--thirdparty/pcre2/LICENCE6
-rw-r--r--thirdparty/pcre2/patches/sljit-macos11-conditional.patch31
-rw-r--r--thirdparty/pcre2/src/config.h9
-rw-r--r--thirdparty/pcre2/src/pcre2.h4
-rw-r--r--thirdparty/pcre2/src/pcre2_auto_possess.c43
-rw-r--r--thirdparty/pcre2/src/pcre2_compile.c250
-rw-r--r--thirdparty/pcre2/src/pcre2_dfa_match.c75
-rw-r--r--thirdparty/pcre2/src/pcre2_error.c4
-rw-r--r--thirdparty/pcre2/src/pcre2_extuni.c6
-rw-r--r--thirdparty/pcre2/src/pcre2_internal.h94
-rw-r--r--thirdparty/pcre2/src/pcre2_intmodedep.h17
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_compile.c928
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_match.c2
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_misc.c2
-rw-r--r--thirdparty/pcre2/src/pcre2_jit_simd_inc.h70
-rw-r--r--thirdparty/pcre2/src/pcre2_match.c332
-rw-r--r--thirdparty/pcre2/src/pcre2_script_run.c473
-rw-r--r--thirdparty/pcre2/src/pcre2_string_utils.c2
-rw-r--r--thirdparty/pcre2/src/pcre2_study.c4
-rw-r--r--thirdparty/pcre2/src/pcre2_substitute.c29
-rw-r--r--thirdparty/pcre2/src/pcre2_tables.c657
-rw-r--r--thirdparty/pcre2/src/pcre2_ucd.c8724
-rw-r--r--thirdparty/pcre2/src/pcre2_ucp.h353
-rw-r--r--thirdparty/pcre2/src/pcre2_ucptables.c1524
-rw-r--r--thirdparty/pcre2/src/pcre2_xclass.c20
-rw-r--r--thirdparty/pcre2/src/sljit/sljitConfigInternal.h112
-rw-r--r--thirdparty/pcre2/src/sljit/sljitExecAllocator.c19
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.c611
-rw-r--r--thirdparty/pcre2/src/sljit/sljitLir.h434
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_32.c945
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_64.c637
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c1004
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c279
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c143
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c567
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_32.c21
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_64.c90
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativePPC_common.c598
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeS390X.c973
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c107
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c287
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_32.c1337
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_64.c838
-rw-r--r--thirdparty/pcre2/src/sljit/sljitNativeX86_common.c411
-rw-r--r--thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c6
-rw-r--r--thirdparty/pcre2/src/sljit/sljitUtils.c31
-rw-r--r--thirdparty/recastnavigation/Recast/Include/RecastAlloc.h49
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastContour.cpp4
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp16
-rw-r--r--thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp10
-rw-r--r--thirdparty/rvo2/API.h45
-rw-r--r--thirdparty/rvo2/Agent.cpp590
-rw-r--r--thirdparty/rvo2/Agent.h103
-rw-r--r--thirdparty/rvo2/Definitions.h12
-rw-r--r--thirdparty/rvo2/KdTree.cpp184
-rw-r--r--thirdparty/rvo2/KdTree.h82
-rw-r--r--thirdparty/rvo2/README.md32
-rw-r--r--thirdparty/rvo2/Vector3.h66
-rw-r--r--thirdparty/rvo2/patches/rvo2-godot-changes.patch282
-rw-r--r--thirdparty/spirv-reflect/include/spirv/unified1/spirv.h46
-rw-r--r--thirdparty/spirv-reflect/patches/specialization-constants.patch34
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.c77
-rw-r--r--thirdparty/spirv-reflect/spirv_reflect.h11
-rw-r--r--thirdparty/thorvg/AUTHORS2
-rw-r--r--thirdparty/thorvg/LICENSE2
-rw-r--r--thirdparty/thorvg/inc/config.h2
-rw-r--r--thirdparty/thorvg/inc/thorvg.h5
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h11
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp6
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp67
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h2
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h6
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h2
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp5
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h2
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp8
-rw-r--r--thirdparty/thorvg/src/lib/tvgAccessor.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgArray.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgBezier.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgBezier.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgBinaryDesc.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgCanvas.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgCanvasImpl.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgCommon.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgFill.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgFill.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgGlCanvas.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgInitializer.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgIteratorAccessor.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLinearGradient.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoadModule.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoader.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLoader.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLzw.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgLzw.h6
-rw-r--r--thirdparty/thorvg/src/lib/tvgMath.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgPaint.cpp8
-rw-r--r--thirdparty/thorvg/src/lib/tvgPaint.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgPicture.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgPictureImpl.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgRadialGradient.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgRender.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgRender.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgSaveModule.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgSaver.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgScene.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgSceneImpl.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgShape.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgShapeImpl.h2
-rw-r--r--thirdparty/thorvg/src/lib/tvgSwCanvas.cpp4
-rw-r--r--thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp2
-rw-r--r--thirdparty/thorvg/src/lib/tvgTaskScheduler.h2
-rw-r--r--thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp7
-rw-r--r--thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp4
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp16
-rw-r--r--thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp4
-rw-r--r--thirdparty/thorvg/src/loaders/png/tvgLodePng.h4
-rw-r--r--thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/png/tvgPngLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp188
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h34
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp378
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h52
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp136
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h2
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp63
-rw-r--r--thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h15
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp4
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h4
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp2
-rw-r--r--thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h2
-rw-r--r--thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp4
-rw-r--r--thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h2
-rwxr-xr-xthirdparty/thorvg/update-thorvg.sh4
-rw-r--r--thirdparty/vhacd/0006-fix-gcc13.patch15
-rw-r--r--thirdparty/vhacd/inc/vhacdICHull.h4
-rw-r--r--thirdparty/volk/volk.c175
-rw-r--r--thirdparty/volk/volk.h117
-rw-r--r--thirdparty/vulkan/patches/VMA-use-volk.patch6
-rw-r--r--thirdparty/vulkan/vk_mem_alloc.h23521
-rw-r--r--thirdparty/xatlas/xatlas.cpp5
-rw-r--r--thirdparty/zlib/crc32.c1258
-rw-r--r--thirdparty/zlib/crc32.h9877
-rw-r--r--thirdparty/zlib/deflate.c108
-rw-r--r--thirdparty/zlib/deflate.h27
-rw-r--r--thirdparty/zlib/gzguts.h5
-rw-r--r--thirdparty/zlib/gzlib.c8
-rw-r--r--thirdparty/zlib/gzread.c12
-rw-r--r--thirdparty/zlib/gzwrite.c38
-rw-r--r--thirdparty/zlib/infback.c3
-rw-r--r--thirdparty/zlib/inffast.c28
-rw-r--r--thirdparty/zlib/inflate.c47
-rw-r--r--thirdparty/zlib/inflate.h5
-rw-r--r--thirdparty/zlib/inftrees.c6
-rw-r--r--thirdparty/zlib/trees.c75
-rw-r--r--thirdparty/zlib/zlib.h223
-rw-r--r--thirdparty/zlib/zutil.c4
-rw-r--r--thirdparty/zlib/zutil.h21
-rw-r--r--thirdparty/zstd/common/bitstream.h33
-rw-r--r--thirdparty/zstd/common/compiler.h132
-rw-r--r--thirdparty/zstd/common/entropy_common.c16
-rw-r--r--thirdparty/zstd/common/error_private.h79
-rw-r--r--thirdparty/zstd/common/fse.h3
-rw-r--r--thirdparty/zstd/common/fse_decompress.c2
-rw-r--r--thirdparty/zstd/common/huf.h46
-rw-r--r--thirdparty/zstd/common/mem.h18
-rw-r--r--thirdparty/zstd/common/pool.c17
-rw-r--r--thirdparty/zstd/common/pool.h4
-rw-r--r--thirdparty/zstd/common/portability_macros.h137
-rw-r--r--thirdparty/zstd/common/xxhash.c810
-rw-r--r--thirdparty/zstd/common/xxhash.h5733
-rw-r--r--thirdparty/zstd/common/zstd_internal.h187
-rw-r--r--thirdparty/zstd/common/zstd_trace.h15
-rw-r--r--thirdparty/zstd/compress/clevels.h134
-rw-r--r--thirdparty/zstd/compress/fse_compress.c90
-rw-r--r--thirdparty/zstd/compress/huf_compress.c641
-rw-r--r--thirdparty/zstd/compress/zstd_compress.c680
-rw-r--r--thirdparty/zstd/compress/zstd_compress_internal.h257
-rw-r--r--thirdparty/zstd/compress/zstd_compress_literals.c7
-rw-r--r--thirdparty/zstd/compress/zstd_compress_literals.h4
-rw-r--r--thirdparty/zstd/compress/zstd_compress_sequences.c29
-rw-r--r--thirdparty/zstd/compress/zstd_compress_superblock.c7
-rw-r--r--thirdparty/zstd/compress/zstd_cwksp.h68
-rw-r--r--thirdparty/zstd/compress/zstd_double_fast.c415
-rw-r--r--thirdparty/zstd/compress/zstd_fast.c439
-rw-r--r--thirdparty/zstd/compress/zstd_lazy.c1044
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.c16
-rw-r--r--thirdparty/zstd/compress/zstd_ldm.h2
-rw-r--r--thirdparty/zstd/compress/zstd_ldm_geartab.h5
-rw-r--r--thirdparty/zstd/compress/zstd_opt.c397
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.c114
-rw-r--r--thirdparty/zstd/compress/zstdmt_compress.h5
-rw-r--r--thirdparty/zstd/decompress/huf_decompress.c916
-rw-r--r--thirdparty/zstd/decompress/huf_decompress_amd64.S585
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress.c107
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_block.c964
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_block.h10
-rw-r--r--thirdparty/zstd/decompress/zstd_decompress_internal.h37
-rw-r--r--thirdparty/zstd/zstd.h315
1950 files changed, 167631 insertions, 332726 deletions
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 012087526c..664401fca6 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -7,9 +7,9 @@ readability.
## amd-fsr
-Upstream: https://github.com/GPUOpen-Effects/FidelityFX-FSR
-Version: 1.0.2 (a21ffb8f6c13233ba336352bdff293894c706575, 2021)
-License: MIT
+- Upstream: https://github.com/GPUOpen-Effects/FidelityFX-FSR
+- Version: 1.0.2 (a21ffb8f6c13233ba336352bdff293894c706575, 2021)
+- License: MIT
Files extracted from upstream source:
@@ -20,7 +20,7 @@ Files extracted from upstream source:
## basis_universal
- Upstream: https://github.com/BinomialLLC/basis_universal
-- Version: git (646a9f826131cb0b9e14b5e4740874808315f83a, 2021)
+- Version: git (1531cfaf9ed5232248a0a45736686a849ca3befc, 2022)
- License: Apache 2.0
Files extracted from upstream source:
@@ -29,24 +29,22 @@ Files extracted from upstream source:
- `LICENSE`
-## bullet
+## brotli
-- Upstream: https://github.com/bulletphysics/bullet3
-- Version: 3.17 (ebe1916b90acae8b13cd8c6b637d8327cdc64e94, 2021)
-- License: zlib
+- Upstream: https://github.com/google/brotli
+- Version: git (f4153a09f87cbb9c826d8fc12c74642bb2d879ea, 2022)
+- License: MIT
Files extracted from upstream source:
-- `src/*` apart from CMakeLists.txt and premake4.lua files
-- `LICENSE.txt`, and `VERSION` as `VERSION.txt`
-
-Includes some patches in the `patches` folder which have been sent upstream.
+- `common/`, `dec/` and `include/` folders
+- `LICENSE`
## certs
- Upstream: Mozilla, via https://github.com/bagder/ca-bundle
-- Version: git (8b263a18fca98ea371e54227837321c5cdaa1ba7, 2021)
+- Version: git (7f33e7eb8472dbcf31fdcf50cd216c89a282825d, 2022)
- License: MPL 2.0
@@ -64,10 +62,13 @@ Files extracted from upstream source:
## doctest
- Upstream: https://github.com/onqtam/doctest
-- Version: 2.4.4 (97d5a9447e66cd5e107b7a6c463be4a468a40496, 2020)
+- Version: 2.4.9 (b7c21ec5ceeadb4951b00396fc1e4642dd347e5f, 2022)
- License: MIT
-Extracted from .zip provided. Extracted license and header only.
+Files extracted from upstream source:
+
+- `doctest/doctest.h` as `doctest.h`
+- `LICENSE.txt`
## embree
@@ -117,7 +118,7 @@ will limit its functionality to IPv4 only.
## etcpak
- Upstream: https://github.com/wolfpld/etcpak
-- Version: git (7c3cb6fe708d4ae330b0ab2af1ad472bae2a37a2, 2021)
+- Version: 1.0 (153f0e04a18b93c277684b577365210adcf8e11c, 2022)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -132,39 +133,45 @@ Files extracted from upstream source:
## fonts
-- `NotoSans*.ttf`, `NotoNaskhArabicUI_*.ttf`:
+- `NotoSans*.woff2`, `NotoNaskhArabicUI_*.woff2`:
* Upstream: https://github.com/googlefonts/noto-fonts
* Version: v2017-10-24-phase3-second-cleanup
* License: OFL-1.1
* Comment: Use UI font variant if available, because it has tight vertical metrics and
good for UI.
-- `JetBrainsMono_Regular.ttf`:
+- `JetBrainsMono_Regular.woff2`:
* Upstream: https://github.com/JetBrains/JetBrainsMono
* Version: 2.242
* License: OFL-1.1
-- `DroidSans*.ttf`:
+- `DroidSans*.woff2`:
* Upstream: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/
* Version: ? (pre-2014 commit when DroidSansJapanese.ttf was obsoleted)
* License: Apache 2.0
-- `OpenSans_SemiBold.ttf`:
+- `OpenSans_SemiBold.woff2`:
* Upstream: https://fonts.google.com/specimen/Open+Sans
* Version: 1.10 (downloaded from Google Fonts in February 2021)
* License: Apache 2.0
-
+- All fonts are converted from the `.ttf` sources using `https://github.com/google/woff2` tool.
## freetype
- Upstream: https://www.freetype.org
-- Version: 2.11.1 (3f83daeecb1a78d851b660eed025eeba362c0e4a, 2021)
+- Version: 2.12.1 (e8ebfe988b5f57bfb9a3ecb13c70d9791bce9ecf, 2022)
- License: FreeType License (BSD-like)
Files extracted from upstream source:
-- the `src/` folder, minus the `.mk` files and the `dlg` and `tools` subfolders
-- the `include/` folder, minus the `dlg` subfolder
+- `src/` folder, minus the `dlg` and `tools` subfolders
+ * These files can be removed: `.dat`, `.diff`, `.mk`, `.rc`, `README*`
+- `include/` folder, minus the `dlg` subfolder
- `LICENSE.TXT` and `docs/FTL.TXT`
+Some changes have been made in order to prevent LTO from removing code.
+They are marked with `// -- GODOT start --` and `// -- GODOT end --`
+comments. Apply the patches in the `patches/` folder when syncing on newer upstream
+commits.
+
## glslang
@@ -206,7 +213,7 @@ Files extracted from upstream source:
## harfbuzz
- Upstream: https://github.com/harfbuzz/harfbuzz
-- Version: 3.3.2 (ac46c3248e8b0316235943175c4d4a11c24dd4a9, 2022)
+- Version: 5.1.0 (f1f2be776bcd994fa9262622e1a7098a066e5cf7, 2022)
- License: MIT
Files extracted from upstream source:
@@ -218,24 +225,26 @@ Files extracted from upstream source:
## icu4c
- Upstream: https://github.com/unicode-org/icu
-- Version: 70.1 (a56dde820dc35665a66f2e9ee8ba58e75049b668, 2021)
+- Version: 71.1 (c205e7ee49a7086a28b9c275fcfdac9ca3dc815d, 2022)
- License: Unicode
Files extracted from upstream source:
- the `common` folder
+- `scriptset.*`, `ucln_in.*`, `uspoof.cpp"` and `uspoof_impl.cpp` from the `i18n` folder
+- `uspoof.h` from the `i18n/unicode` folder
- `LICENSE`
Files generated from upstream source:
-- the `icudt70l.dat` built with the provided `godot_data.json` config file (see
+- the `icudt71l.dat` built with the provided `godot_data.json` config file (see
https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md
for instructions).
- Step 1: Build ICU with default options - `./runConfigureICU {PLATFORM} && make`.
- Step 2: Reconfigure ICU with custom data config - `ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common`.
- Step 3: Delete `data/out` folder and rebuild data - `cd data && rm -rf ./out && make`.
-- Step 4: Copy `source/data/out/icudt70l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt70l.dat`.
+- Step 4: Copy `source/data/out/icudt71l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt71l.dat`.
## jpeg-compressor
@@ -247,6 +256,7 @@ Files generated from upstream source:
Files extracted from upstream source:
- `jpgd*.{c,h}`
+- `jpge*.{c,h}`
## libogg
@@ -320,15 +330,15 @@ Files extracted from upstream source:
## mbedtls
-- Upstream: https://tls.mbed.org/
-- Version: 2.16.12 (cf4667126010c665341f9e50ef691b7ef8294188, 2021)
+- Upstream: https://github.com/Mbed-TLS/mbedtls
+- Version: 2.18.1 (dd79db10014d85b26d11fe57218431f2e5ede6f2, 2022)
- License: Apache 2.0
File extracted from upstream release tarball:
- All `*.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/` except `config_psa.h` and `psa_util.h`.
- All `*.c` and `*.h` from `library/` to `thirdparty/mbedtls/library/` except those starting with `psa_*`.
-- `LICENSE` and `apache-2.0.txt` files.
+- The `LICENSE` file.
- Applied the patch in `patches/1453.diff` (upstream PR:
https://github.com/ARMmbed/mbedtls/pull/1453).
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
@@ -338,7 +348,7 @@ File extracted from upstream release tarball:
## meshoptimizer
- Upstream: https://github.com/zeux/meshoptimizer
-- Version: git (f4c356d79fadb99cbf432f7e199d823581b0e19e, 2021)
+- Version: git (ea4558d1c0f217f1d67ed7fe0b07896ece88ae18, 2022)
- License: MIT
Files extracted from upstream repository:
@@ -385,17 +395,17 @@ that file when upgrading.
## minizip
-- Upstream: http://www.zlib.net
-- Version: 1.2.11 (zlib contrib, 2017)
+- Upstream: https://www.zlib.net
+- Version: 1.2.12 (zlib contrib, 2022)
- License: zlib
Files extracted from the upstream source:
-- contrib/minizip/{crypt.h,ioapi.{c,h},zip.{c,h},unzip.{c,h}}
+- contrib/minizip/{crypt.h,ioapi.{c,h},unzip.{c,h},zip.{c,h}}
Important: Some files have Godot-made changes for use in core/io.
They are marked with `/* GODOT start */` and `/* GODOT end */`
-comments and a patch is provided in the minizip/ folder.
+comments and a patch is provided in the `patches` folder.
## misc
@@ -426,10 +436,19 @@ Collection of single-file libraries used in Godot components.
* Upstream: https://archive.blender.org/wiki/index.php/Dev:Shading/Tangent_Space_Normal_Maps/
* Version: 1.0 (2011)
* License: zlib
-- `open-simplex-noise.{c,h}`
- * Upstream: https://github.com/smcameron/open-simplex-noise-in-c
- * Version: git (826f1dd1724e6fb3ff45f58e48c0fbae864c3403, 2020) + custom changes
- * License: Public Domain or Unlicense
+- `FastNoiseLite.h}`
+ * Upstream: https://github.com/Auburn/FastNoiseLite
+ * Version: git (6be3d6bf7fb408de341285f9ee8a29b67fd953f1, 2022) + custom changes
+ * License: MIT
+- `ok_color.h`
+ * Upstream: https://github.com/bottosson/bottosson.github.io/blob/master/misc/ok_color.h
+ * Version: git (d69831edb90ffdcd08b7e64da3c5405acd48ad2c, 2022)
+ * License: MIT
+ * Modifications: License included in header.
+- `ok_color_shader.h`
+ * https://www.shadertoy.com/view/7sK3D1
+ * Version: 2021-09-13
+ * License: MIT
- `pcg.{cpp,h}`
* Upstream: http://www.pcg-random.org
* Version: minimal C implementation, http://www.pcg-random.org/download.html
@@ -454,7 +473,7 @@ Collection of single-file libraries used in Godot components.
* License: Public Domain or MIT
- `stb_rect_pack.h`
* Upstream: https://github.com/nothings/stb
- * Version: 1.00 (2bb4a0accd4003c1db4c24533981e01b1adfd656, 2019)
+ * Version: 1.01 (af1a5bc352164740c1cc1354942b1c6b72eacb8a, 2021)
* License: Public Domain or Unlicense or MIT
- `yuv2rgb.h`
* Upstream: http://wss.co.uk/pinknoise/yuv2rgb/ (to check)
@@ -474,6 +493,7 @@ Files extracted from the upstream source:
- Files in `core/` folder.
- `LICENSE.txt` and `CHANGELOG.md`
+
## oidn
- Upstream: https://github.com/OpenImageDenoise/oidn
@@ -505,10 +525,34 @@ Patch files are provided in `oidn/patches/`.
- scripts/resource_to_cpp.py (used in modules/denoise/resource_to_cpp.py)
+## openxr
+
+- Upstream: https://github.com/KhronosGroup/OpenXR-SDK
+- Version: 1.0.23 (885a90f8934d84121344ba8e4aa5159d5b496e08, 2022)
+- License: Apache 2.0
+
+Files extracted from upstream source:
+
+- include/
+- src/common/
+- src/loader/
+- src/*.{c,h}
+- src/external/jsoncpp/include/
+- src/external/jsoncpp/src/lib_json/
+- LICENSE and COPYING.adoc
+
+Exclude:
+
+- src/external/android-jni-wrappers and src/external/jnipp (not used yet)
+- All CMake stuff: cmake/, CMakeLists.txt and *.cmake
+- All Gradle stuff: *gradle*, AndroidManifest.xml
+- All following files (and their .license files): *.{def,in,json,map,pom,rc}
+
+
## pcre2
- Upstream: http://www.pcre.org
-- Version: 10.39 (35fee4193b852cb504892352bd0155de10809889, 2021)
+- Version: 10.40 (3103b8f20a3b9944b177e812fde29fbfb8b90558, 2022)
- License: BSD-3-Clause
Files extracted from upstream source:
@@ -520,11 +564,14 @@ Files extracted from upstream source:
- src/sljit/
- AUTHORS and LICENCE
+A sljit patch from upstream was backported to fix macOS < 11.0 compilation
+in 10.40, it can be found in the `patches` folder.
+
## recastnavigation
- Upstream: https://github.com/recastnavigation/recastnavigation
-- Version: git (57610fa6ef31b39020231906f8c5d40eaa8294ae, 2019)
+- Version: git (5a870d427e47abd4a8e4ce58a95582ec049434d5, 2022)
- License: zlib
Files extracted from upstream source:
@@ -536,23 +583,23 @@ Files extracted from upstream source:
## rvo2
- Upstream: https://github.com/snape/RVO2-3D
-- Version: 1.0.1 (e3883f288a9e55ecfed3633a01af3e12778c6acf, 2016)
+- Version: git (bfc048670a4e85066e86a1f923d8ea92e3add3b2, 2021)
- License: Apache 2.0
Files extracted from upstream source:
-- All .cpp and .h files in the `src/` folder except for RVO.h, RVOSimulator.cpp and RVOSimulator.h
+- All .cpp and .h files in the `src/` folder except for Export.h, RVO.h, RVOSimulator.cpp and RVOSimulator.h
- LICENSE
Important: Some files have Godot-made changes; so to enrich the features
originally proposed by this library and better integrate this library with
-Godot. Please check the file to know what's new.
+Godot. See the patch in the `patches` folder for details.
## spirv-reflect
- Upstream: https://github.com/KhronosGroup/SPIRV-Reflect
-- Version: git (1aceb6af56e74b92a00378842dda5c5a73f49a4b, 2022)
+- Version: git (1ef99b09fa7ce5aee2c5cf70c61a4f7458d27e09, 2022)
- License: Apache 2.0
Does not track Vulkan SDK releases closely, but try to package a commit newer
@@ -602,7 +649,7 @@ instead of `miniz.h` as an external dependency.
## thorvg
- Upstream: https://github.com/Samsung/thorvg
-- Version: 0.7.1 (d53eb2a880002cb770ace1c1ace9c5dfcfc28252, 2022)
+- Version: 0.8.1 (c4ccb1078f4390ec749ab8e05ba7e9e35f81285f, 2022)
- License: MIT
Files extracted from upstream source:
@@ -665,7 +712,7 @@ Files extracted from upstream source:
SDK release: https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/layers/generated/vk_enum_string_helper.h
`vk_mem_alloc.h` is taken from https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator
-Version: 3.0.0-development (2021-07-07), branch `feature-small-buffers`, commit `cfea2f72851f9ee4a399769f18865047b83711f1`
+Version: 3.0.1 (2022-06-10), commit `cfdc0f8775ab3258a3b9c4e47d8ce4b6f52a5441`
`vk_mem_alloc.cpp` is a Godot file and should be preserved on updates.
Patches in the `patches` directory should be re-applied after updates.
@@ -691,7 +738,7 @@ File extracted from upstream release tarball:
## xatlas
- Upstream: https://github.com/jpcy/xatlas
-- Version: git (ec707faeac3b95e6b416076a9509718cce105b6a, 2021)
+- Version: git (16ace528acd2cf1f16a7c0dde99c42c486488dbe, 2022)
- License: MIT
Files extracted from upstream source:
@@ -702,8 +749,8 @@ Files extracted from upstream source:
## zlib
-- Upstream: http://www.zlib.net
-- Version: 1.2.11 (2017)
+- Upstream: https://www.zlib.net
+- Version: 1.2.12 (2022)
- License: zlib
Files extracted from upstream source:
@@ -714,7 +761,7 @@ Files extracted from upstream source:
## zstd
- Upstream: https://github.com/facebook/zstd
-- Version: 1.5.0 (a488ba114ec17ea1054b9057c26a046fc122b3b6, 2021)
+- Version: 1.5.2 (e47e674cd09583ff0503f0f6defd6d23d8b718d3, 2022)
- License: BSD-3-Clause
Files extracted from upstream source:
diff --git a/thirdparty/basis_universal/encoder/apg_bmp.c b/thirdparty/basis_universal/encoder/apg_bmp.c
deleted file mode 100644
index d342b20fc8..0000000000
--- a/thirdparty/basis_universal/encoder/apg_bmp.c
+++ /dev/null
@@ -1,541 +0,0 @@
-/*
-BMP File Reader/Writer Implementation
-Anton Gerdelan
-Version: 3
-Licence: see apg_bmp.h
-C99
-*/
-
-#ifdef _MSC_VER
-#define _CRT_SECURE_NO_WARNINGS 1
-#endif
-
-#include "apg_bmp.h"
-#include <assert.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/* Maximum pixel dimensions of width or height of an image. Should accommodate max used in graphics APIs.
- NOTE: 65536*65536 is the biggest number storable in 32 bits.
- This needs to be multiplied by n_channels so actual memory indices are not uint32 but size_t to avoid overflow.
- Note this will crash stb_image_write et al at maximum size which use 32bits, so reduce max size to accom. */
-#define _BMP_MAX_DIMS 65536
-#define _BMP_FILE_HDR_SZ 14
-#define _BMP_MIN_DIB_HDR_SZ 40
-#define _BMP_MIN_HDR_SZ ( _BMP_FILE_HDR_SZ + _BMP_MIN_DIB_HDR_SZ )
-#define _BMP_MAX_IMAGE_FILE_SIZE (1024ULL*1024ULL*1024ULL)
-
-#pragma pack( push, 1 ) // supported on GCC in addition to individual packing attribs
-/* All BMP files, regardless of type, start with this file header */
-typedef struct _bmp_file_header_t {
- char file_type[2];
- uint32_t file_sz;
- uint16_t reserved1;
- uint16_t reserved2;
- uint32_t image_data_offset;
-} _bmp_file_header_t;
-
-/* Following the file header is the BMP type header. this is the most commonly used format */
-typedef struct _bmp_dib_BITMAPINFOHEADER_t {
- uint32_t this_header_sz;
- int32_t w; // in older headers w & h these are shorts and may be unsigned
- int32_t h; //
- uint16_t n_planes; // must be 1
- uint16_t bpp; // bits per pixel. 1,4,8,16,24,32.
- uint32_t compression_method; // 16 and 32-bit images must have a value of 3 here
- uint32_t image_uncompressed_sz; // not consistently used in the wild, so ignored here.
- int32_t horiz_pixels_per_meter; // not used.
- int32_t vert_pixels_per_meter; // not used.
- uint32_t n_colours_in_palette; //
- uint32_t n_important_colours; // not used.
- /* NOTE(Anton) a DIB header may end here at 40-bytes. be careful using sizeof() */
- /* if 'compression' value, above, is set to 3 ie the image is 16 or 32-bit, then these colour channel masks follow the headers.
- these are big-endian order bit masks to assign bits of each pixel to different colours. bits used must be contiguous and not overlap. */
- uint32_t bitmask_r;
- uint32_t bitmask_g;
- uint32_t bitmask_b;
-} _bmp_dib_BITMAPINFOHEADER_t;
-#pragma pack( pop )
-
-typedef enum _bmp_compression_t {
- BI_RGB = 0,
- BI_RLE8 = 1,
- BI_RLE4 = 2,
- BI_BITFIELDS = 3,
- BI_JPEG = 4,
- BI_PNG = 5,
- BI_ALPHABITFIELDS = 6,
- BI_CMYK = 11,
- BI_CMYKRLE8 = 12,
- BI_CMYRLE4 = 13
-} _bmp_compression_t;
-
-/* convenience struct and file->memory function */
-typedef struct _entire_file_t {
- void* data;
- size_t sz;
-} _entire_file_t;
-
-/*
-RETURNS
-- true on success. record->data is allocated memory and must be freed by the caller.
-- false on any error. Any allocated memory is freed if false is returned */
-static bool _read_entire_file( const char* filename, _entire_file_t* record ) {
- FILE* fp = fopen( filename, "rb" );
- if ( !fp ) { return false; }
- fseek( fp, 0L, SEEK_END );
- record->sz = (size_t)ftell( fp );
-
- // Immediately bail on anything larger than _BMP_MAX_IMAGE_FILE_SIZE.
- if (record->sz > _BMP_MAX_IMAGE_FILE_SIZE) {
- fclose( fp );
- return false;
- }
-
- record->data = malloc( record->sz );
- if ( !record->data ) {
- fclose( fp );
- return false;
- }
- rewind( fp );
- size_t nr = fread( record->data, record->sz, 1, fp );
- fclose( fp );
- if ( 1 != nr ) { return false; }
- return true;
-}
-
-static bool _validate_file_hdr( _bmp_file_header_t* file_hdr_ptr, size_t file_sz ) {
- if ( !file_hdr_ptr ) { return false; }
- if ( file_hdr_ptr->file_type[0] != 'B' || file_hdr_ptr->file_type[1] != 'M' ) { return false; }
- if ( file_hdr_ptr->image_data_offset > file_sz ) { return false; }
- return true;
-}
-
-static bool _validate_dib_hdr( _bmp_dib_BITMAPINFOHEADER_t* dib_hdr_ptr, size_t file_sz ) {
- if ( !dib_hdr_ptr ) { return false; }
- if ( _BMP_FILE_HDR_SZ + dib_hdr_ptr->this_header_sz > file_sz ) { return false; }
- if ( ( 32 == dib_hdr_ptr->bpp || 16 == dib_hdr_ptr->bpp ) && ( BI_BITFIELDS != dib_hdr_ptr->compression_method && BI_ALPHABITFIELDS != dib_hdr_ptr->compression_method ) ) {
- return false;
- }
- if ( BI_RGB != dib_hdr_ptr->compression_method && BI_BITFIELDS != dib_hdr_ptr->compression_method && BI_ALPHABITFIELDS != dib_hdr_ptr->compression_method ) {
- return false;
- }
- // NOTE(Anton) using abs() in the if-statement was blowing up on large negative numbers. switched to labs()
- if ( 0 == dib_hdr_ptr->w || 0 == dib_hdr_ptr->h || labs( dib_hdr_ptr->w ) > _BMP_MAX_DIMS || labs( dib_hdr_ptr->h ) > _BMP_MAX_DIMS ) { return false; }
-
- /* NOTE(Anton) if images reliably used n_colours_in_palette we could have done a palette/file size integrity check here.
- because some always set 0 then we have to check every palette indexing as we read them */
- return true;
-}
-
-/* NOTE(Anton) this could have ifdef branches on different compilers for the intrinsics versions for perf */
-static uint32_t _bitscan( uint32_t dword ) {
- for ( uint32_t i = 0; i < 32; i++ ) {
- if ( 1 & dword ) { return i; }
- dword = dword >> 1;
- }
- return (uint32_t)-1;
-}
-
-unsigned char* apg_bmp_read( const char* filename, int* w, int* h, unsigned int* n_chans ) {
- if ( !filename || !w || !h || !n_chans ) { return NULL; }
-
- // read in the whole file into memory first - much faster than parsing on-the-fly
- _entire_file_t record;
- if ( !_read_entire_file( filename, &record ) ) { return NULL; }
- if ( record.sz < _BMP_MIN_HDR_SZ ) {
- free( record.data );
- return NULL;
- }
-
- // grab and validate the first, file, header
- _bmp_file_header_t* file_hdr_ptr = (_bmp_file_header_t*)record.data;
- if ( !_validate_file_hdr( file_hdr_ptr, record.sz ) ) {
- free( record.data );
- return NULL;
- }
-
- // grad and validate the second, DIB, header
- _bmp_dib_BITMAPINFOHEADER_t* dib_hdr_ptr = (_bmp_dib_BITMAPINFOHEADER_t*)( (uint8_t*)record.data + _BMP_FILE_HDR_SZ );
- if ( !_validate_dib_hdr( dib_hdr_ptr, record.sz ) ) {
- free( record.data );
- return NULL;
- }
-
- // bitmaps can have negative dims to indicate the image should be flipped
- uint32_t width = *w = abs( dib_hdr_ptr->w );
- uint32_t height = *h = abs( dib_hdr_ptr->h );
-
- // TODO(Anton) flip image memory at the end if this is true. because doing it per row was making me write bugs.
- // bool vertically_flip = dib_hdr_ptr->h > 0 ? false : true;
-
- // channel count and palette are not well defined in the header so we make a good guess here
- uint32_t n_dst_chans = 3, n_src_chans = 3;
- bool has_palette = false;
- switch ( dib_hdr_ptr->bpp ) {
- case 32: n_dst_chans = n_src_chans = 4; break; // technically can be RGB but not supported
- case 24: n_dst_chans = n_src_chans = 3; break; // technically can be RGBA but not supported
- case 8: // seems to always use a BGR0 palette, even for greyscale
- n_dst_chans = 3;
- has_palette = true;
- n_src_chans = 1;
- break;
- case 4: // always has a palette - needed for a MS-saved BMP
- n_dst_chans = 3;
- has_palette = true;
- n_src_chans = 1;
- break;
- case 1: // 1-bpp means the palette has 3 colour channels with 2 colours i.e. monochrome but not always black & white
- n_dst_chans = 3;
- has_palette = true;
- n_src_chans = 1;
- break;
- default: // this includes 2bpp and 16bpp
- free( record.data );
- return NULL;
- } // endswitch
- *n_chans = n_dst_chans;
- // NOTE(Anton) some image formats are not allowed a palette - could check for a bad header spec here also
- if ( dib_hdr_ptr->n_colours_in_palette > 0 ) { has_palette = true; }
-
-#ifdef APG_BMP_DEBUG_OUTPUT
- printf( "apg_bmp_debug: reading image\n|-filename `%s`\n|-dims %ux%u pixels\n|-bpp %u\n|-n_src_chans %u\n|-n_dst_chans %u\n", filename, *w, *h,
- dib_hdr_ptr->bpp, n_src_chans, n_dst_chans );
-#endif
-
- uint32_t palette_offset = _BMP_FILE_HDR_SZ + dib_hdr_ptr->this_header_sz;
- bool has_bitmasks = false;
- if ( BI_BITFIELDS == dib_hdr_ptr->compression_method || BI_ALPHABITFIELDS == dib_hdr_ptr->compression_method ) {
- has_bitmasks = true;
- palette_offset += 12;
- }
- if ( palette_offset > record.sz ) {
- free( record.data );
- return NULL;
- }
-
- // work out if any padding how much to skip at end of each row
- uint32_t unpadded_row_sz = width * n_src_chans;
- // bit-encoded palette indices have different padding properties
- if ( 4 == dib_hdr_ptr->bpp ) {
- unpadded_row_sz = width % 2 > 0 ? width / 2 + 1 : width / 2; // find how many whole bytes required for this bit width
- }
- if ( 1 == dib_hdr_ptr->bpp ) {
- unpadded_row_sz = width % 8 > 0 ? width / 8 + 1 : width / 8; // find how many whole bytes required for this bit width
- }
- uint32_t row_padding_sz = 0 == unpadded_row_sz % 4 ? 0 : 4 - ( unpadded_row_sz % 4 ); // NOTE(Anton) didn't expect operator precedence of - over %
-
- // another file size integrity check: partially validate source image data size
- // 'image_data_offset' is by row padded to 4 bytes and is either colour data or palette indices.
- if ( file_hdr_ptr->image_data_offset + ( unpadded_row_sz + row_padding_sz ) * height > record.sz ) {
- free( record.data );
- return NULL;
- }
-
- // find which bit number each colour channel starts at, so we can separate colours out
- uint32_t bitshift_rgba[4] = {0, 0, 0, 0}; // NOTE(Anton) noticed this was int and not uint32_t so changed it. 17 Mar 2020
- uint32_t bitmask_a = 0;
- if ( has_bitmasks ) {
- bitmask_a = ~( dib_hdr_ptr->bitmask_r | dib_hdr_ptr->bitmask_g | dib_hdr_ptr->bitmask_b );
- bitshift_rgba[0] = _bitscan( dib_hdr_ptr->bitmask_r );
- bitshift_rgba[1] = _bitscan( dib_hdr_ptr->bitmask_g );
- bitshift_rgba[2] = _bitscan( dib_hdr_ptr->bitmask_b );
- bitshift_rgba[3] = _bitscan( bitmask_a );
- }
-
- // allocate memory for the output pixels block. cast to size_t in case width and height are both the max of 65536 and n_dst_chans > 1
- unsigned char* dst_img_ptr = (unsigned char*)malloc( (size_t)width * (size_t)height * (size_t)n_dst_chans );
- if ( !dst_img_ptr ) {
- free( record.data );
- return NULL;
- }
-
- uint8_t* palette_data_ptr = (uint8_t*)record.data + palette_offset;
- uint8_t* src_img_ptr = (uint8_t*)record.data + file_hdr_ptr->image_data_offset;
- size_t dst_stride_sz = width * n_dst_chans;
-
- // == 32-bpp -> 32-bit RGBA. == 32-bit and 16-bit require bitmasks
- if ( 32 == dib_hdr_ptr->bpp ) {
- // check source image has enough data in it to read from
- if ( (size_t)file_hdr_ptr->image_data_offset + (size_t)height * (size_t)width * (size_t)n_src_chans > record.sz ) {
- free( record.data );
- free( dst_img_ptr );
- return NULL;
- }
- size_t src_byte_idx = 0;
- for ( uint32_t r = 0; r < height; r++ ) {
- size_t dst_pixels_idx = r * dst_stride_sz;
- for ( uint32_t c = 0; c < width; c++ ) {
- uint32_t pixel;
- memcpy( &pixel, &src_img_ptr[src_byte_idx], 4 );
- // NOTE(Anton) the below assumes 32-bits is always RGBA 1 byte per channel. 10,10,10 RGB exists though and isn't handled.
- dst_img_ptr[dst_pixels_idx++] = ( uint8_t )( ( pixel & dib_hdr_ptr->bitmask_r ) >> bitshift_rgba[0] );
- dst_img_ptr[dst_pixels_idx++] = ( uint8_t )( ( pixel & dib_hdr_ptr->bitmask_g ) >> bitshift_rgba[1] );
- dst_img_ptr[dst_pixels_idx++] = ( uint8_t )( ( pixel & dib_hdr_ptr->bitmask_b ) >> bitshift_rgba[2] );
- dst_img_ptr[dst_pixels_idx++] = ( uint8_t )( ( pixel & bitmask_a ) >> bitshift_rgba[3] );
- src_byte_idx += 4;
- }
- src_byte_idx += row_padding_sz;
- }
-
- // == 8-bpp -> 24-bit RGB ==
- } else if ( 8 == dib_hdr_ptr->bpp && has_palette ) {
- // validate indices (body of image data) fits in file
- if ( file_hdr_ptr->image_data_offset + height * width > record.sz ) {
- free( record.data );
- free( dst_img_ptr );
- return NULL;
- }
- size_t src_byte_idx = 0;
- for ( uint32_t r = 0; r < height; r++ ) {
- size_t dst_pixels_idx = ( height - 1 - r ) * dst_stride_sz;
- for ( uint32_t c = 0; c < width; c++ ) {
- // "most palettes are 4 bytes in RGB0 order but 3 for..." - it was actually BRG0 in old images -- Anton
- uint8_t index = src_img_ptr[src_byte_idx]; // 8-bit index value per pixel
-
- if ( palette_offset + index * 4 + 2 >= record.sz ) {
- free( record.data );
- return dst_img_ptr;
- }
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[index * 4 + 2];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[index * 4 + 1];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[index * 4 + 0];
- src_byte_idx++;
- }
- src_byte_idx += row_padding_sz;
- }
-
- // == 4-bpp (16-colour) -> 24-bit RGB ==
- } else if ( 4 == dib_hdr_ptr->bpp && has_palette ) {
- size_t src_byte_idx = 0;
- for ( uint32_t r = 0; r < height; r++ ) {
- size_t dst_pixels_idx = ( height - 1 - r ) * dst_stride_sz;
- for ( uint32_t c = 0; c < width; c++ ) {
- if ( file_hdr_ptr->image_data_offset + src_byte_idx > record.sz ) {
- free( record.data );
- free( dst_img_ptr );
- return NULL;
- }
- // handle 2 pixels at a time
- uint8_t pixel_duo = src_img_ptr[src_byte_idx];
- uint8_t a_index = ( 0xFF & pixel_duo ) >> 4;
- uint8_t b_index = 0xF & pixel_duo;
-
- if ( palette_offset + a_index * 4 + 2 >= record.sz ) { // invalid src image
- free( record.data );
- return dst_img_ptr;
- }
- if ( dst_pixels_idx + 3 > width * height * n_dst_chans ) { // done
- free( record.data );
- return dst_img_ptr;
- }
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[a_index * 4 + 2];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[a_index * 4 + 1];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[a_index * 4 + 0];
- if ( ++c >= width ) { // advance a column
- c = 0;
- r++;
- if ( r >= height ) { // done. no need to get second pixel. eg a 1x1 pixel image.
- free( record.data );
- return dst_img_ptr;
- }
- dst_pixels_idx = ( height - 1 - r ) * dst_stride_sz;
- }
-
- if ( palette_offset + b_index * 4 + 2 >= record.sz ) { // invalid src image
- free( record.data );
- return dst_img_ptr;
- }
- if ( dst_pixels_idx + 3 > width * height * n_dst_chans ) { // done. probably redundant check since checking r >= height.
- free( record.data );
- return dst_img_ptr;
- }
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[b_index * 4 + 2];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[b_index * 4 + 1];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[b_index * 4 + 0];
- src_byte_idx++;
- }
- src_byte_idx += row_padding_sz;
- }
-
- // == 1-bpp -> 24-bit RGB ==
- } else if ( 1 == dib_hdr_ptr->bpp && has_palette ) {
- /* encoding method for monochrome is not well documented.
- a 2x2 pixel image is stored as 4 1-bit palette indexes
- the palette is stored as any 2 RGB0 colours (not necessarily B&W)
- so for an image with indexes like so:
- 1 1
- 0 1
- it is bit-encoded as follows, starting at MSB:
- 01000000 00000000 00000000 00000000 (first byte val 64)
- 11000000 00000000 00000000 00000000 (first byte val 192)
- data is still split by row and each row padded to 4 byte multiples
- */
- size_t src_byte_idx = 0;
- for ( uint32_t r = 0; r < height; r++ ) {
- uint8_t bit_idx = 0; // used in monochrome
- size_t dst_pixels_idx = ( height - 1 - r ) * dst_stride_sz;
- for ( uint32_t c = 0; c < width; c++ ) {
- if ( 8 == bit_idx ) { // start reading from the next byte
- src_byte_idx++;
- bit_idx = 0;
- }
- if ( file_hdr_ptr->image_data_offset + src_byte_idx > record.sz ) {
- free( record.data );
- return dst_img_ptr;
- }
- uint8_t pixel_oct = src_img_ptr[src_byte_idx];
- uint8_t bit = 128 >> bit_idx;
- uint8_t masked = pixel_oct & bit;
- uint8_t palette_idx = masked > 0 ? 1 : 0;
-
- if ( palette_offset + palette_idx * 4 + 2 >= record.sz ) {
- free( record.data );
- return dst_img_ptr;
- }
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[palette_idx * 4 + 2];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[palette_idx * 4 + 1];
- dst_img_ptr[dst_pixels_idx++] = palette_data_ptr[palette_idx * 4 + 0];
- bit_idx++;
- }
- src_byte_idx += ( row_padding_sz + 1 ); // 1bpp is special here
- }
-
- // == 24-bpp -> 24-bit RGB == (but also should handle some other n_chans cases)
- } else {
- // NOTE(Anton) this only supports 1 byte per channel
- if ( file_hdr_ptr->image_data_offset + height * width * n_dst_chans > record.sz ) {
- free( record.data );
- free( dst_img_ptr );
- return NULL;
- }
- size_t src_byte_idx = 0;
- for ( uint32_t r = 0; r < height; r++ ) {
- size_t dst_pixels_idx = ( height - 1 - r ) * dst_stride_sz;
- for ( uint32_t c = 0; c < width; c++ ) {
- // re-orders from BGR to RGB
- if ( n_dst_chans > 3 ) { dst_img_ptr[dst_pixels_idx++] = src_img_ptr[src_byte_idx + 3]; }
- if ( n_dst_chans > 2 ) { dst_img_ptr[dst_pixels_idx++] = src_img_ptr[src_byte_idx + 2]; }
- if ( n_dst_chans > 1 ) { dst_img_ptr[dst_pixels_idx++] = src_img_ptr[src_byte_idx + 1]; }
- dst_img_ptr[dst_pixels_idx++] = src_img_ptr[src_byte_idx];
- src_byte_idx += n_src_chans;
- }
- src_byte_idx += row_padding_sz;
- }
- } // endif bpp
-
- free( record.data );
- return dst_img_ptr;
-}
-
-void apg_bmp_free( unsigned char* pixels_ptr ) {
- if ( !pixels_ptr ) { return; }
- free( pixels_ptr );
-}
-
-unsigned int apg_bmp_write( const char* filename, unsigned char* pixels_ptr, int w, int h, unsigned int n_chans ) {
- if ( !filename || !pixels_ptr ) { return 0; }
- if ( 0 == w || 0 == h ) { return 0; }
- if ( labs( w ) > _BMP_MAX_DIMS || labs( h ) > _BMP_MAX_DIMS ) { return 0; }
- if ( n_chans != 3 && n_chans != 4 ) { return 0; }
-
- uint32_t height = (uint32_t)labs( h );
- uint32_t width = (uint32_t)labs( w );
- // work out if any padding how much to skip at end of each row
- const size_t unpadded_row_sz = width * n_chans;
- const size_t row_padding_sz = 0 == unpadded_row_sz % 4 ? 0 : 4 - unpadded_row_sz % 4;
- const size_t row_sz = unpadded_row_sz + row_padding_sz;
- const size_t dst_pixels_padded_sz = row_sz * height;
-
- const size_t dib_hdr_sz = sizeof( _bmp_dib_BITMAPINFOHEADER_t );
- _bmp_file_header_t file_hdr;
- {
- file_hdr.file_type[0] = 'B';
- file_hdr.file_type[1] = 'M';
- file_hdr.file_sz = _BMP_FILE_HDR_SZ + (uint32_t)dib_hdr_sz + (uint32_t)dst_pixels_padded_sz;
- file_hdr.reserved1 = 0;
- file_hdr.reserved2 = 0;
- file_hdr.image_data_offset = _BMP_FILE_HDR_SZ + (uint32_t)dib_hdr_sz;
- }
- _bmp_dib_BITMAPINFOHEADER_t dib_hdr;
- {
- dib_hdr.this_header_sz = _BMP_MIN_DIB_HDR_SZ; // NOTE: must be 40 and not include the bitmask memory in size here
- dib_hdr.w = w;
- dib_hdr.h = h;
- dib_hdr.n_planes = 1;
- dib_hdr.bpp = 3 == n_chans ? 24 : 32;
- dib_hdr.compression_method = 3 == n_chans ? BI_RGB : BI_BITFIELDS;
- dib_hdr.image_uncompressed_sz = 0;
- dib_hdr.horiz_pixels_per_meter = 0;
- dib_hdr.vert_pixels_per_meter = 0;
- dib_hdr.n_colours_in_palette = 0;
- dib_hdr.n_important_colours = 0;
- // big-endian masks. only used in BI_BITFIELDS and BI_ALPHABITFIELDS ( 16 and 32-bit images )
- // important note: GIMP stores BMP data in this array order for 32-bit: [A][B][G][R]
- dib_hdr.bitmask_r = 0xFF000000;
- dib_hdr.bitmask_g = 0x00FF0000;
- dib_hdr.bitmask_b = 0x0000FF00;
- }
-
- uint8_t* dst_pixels_ptr = (uint8_t*)malloc( dst_pixels_padded_sz );
- if ( !dst_pixels_ptr ) { return 0; }
- {
- size_t dst_byte_idx = 0;
- uint8_t padding[4] = {0, 0, 0, 0};
- uint8_t rgba[4] = {0, 0, 0, 0};
- uint8_t bgra[4] = {0, 0, 0, 0};
-
- for ( uint32_t row = 0; row < height; row++ ) {
- size_t src_byte_idx = ( height - 1 - row ) * n_chans * width;
- for ( uint32_t col = 0; col < width; col++ ) {
- for ( uint32_t chan = 0; chan < n_chans; chan++ ) { rgba[chan] = pixels_ptr[src_byte_idx++]; }
- if ( 3 == n_chans ) {
- bgra[0] = rgba[2];
- bgra[1] = rgba[1];
- bgra[2] = rgba[0];
- } else {
- /* NOTE(Anton) RGBA with alpha channel would be better supported with an extended DIB header */
- bgra[0] = rgba[3];
- bgra[1] = rgba[2];
- bgra[2] = rgba[1];
- bgra[3] = rgba[0]; // alpha
- }
- memcpy( &dst_pixels_ptr[dst_byte_idx], bgra, n_chans );
- dst_byte_idx += (size_t)n_chans;
- } // endfor col
- if ( row_padding_sz > 0 ) {
- memcpy( &dst_pixels_ptr[dst_byte_idx], padding, row_padding_sz );
- dst_byte_idx += row_padding_sz;
- }
- } // endfor row
- }
- {
- FILE* fp = fopen( filename, "wb" );
- if ( !fp ) {
- free( dst_pixels_ptr );
- return 0;
- }
- if ( 1 != fwrite( &file_hdr, _BMP_FILE_HDR_SZ, 1, fp ) ) {
- free( dst_pixels_ptr );
- fclose( fp );
- return 0;
- }
- if ( 1 != fwrite( &dib_hdr, dib_hdr_sz, 1, fp ) ) {
- free( dst_pixels_ptr );
- fclose( fp );
- return 0;
- }
- if ( 1 != fwrite( dst_pixels_ptr, dst_pixels_padded_sz, 1, fp ) ) {
- free( dst_pixels_ptr );
- fclose( fp );
- return 0;
- }
- fclose( fp );
- }
- free( dst_pixels_ptr );
-
- return 1;
-}
diff --git a/thirdparty/basis_universal/encoder/apg_bmp.h b/thirdparty/basis_universal/encoder/apg_bmp.h
deleted file mode 100644
index 8cd73b62e0..0000000000
--- a/thirdparty/basis_universal/encoder/apg_bmp.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-BMP File Reader/Writer Implementation
-Anton Gerdelan
-Version: 3.1 18 March 2020.
-Licence: see bottom of file.
-C89 ( Implementation is C99 )
-
-Contributors:
-- Anton Gerdelan - Initial code.
-- Saija Sorsa - Fuzz testing.
-
-Instructions:
-- Just drop this header, and the matching .c file into your project.
-- To get debug printouts during parsing define APG_BMP_DEBUG_OUTPUT.
-
-Advantages:
-- The implementation is fast, simple, and supports more formats than most BMP reader libraries.
-- The reader function is fuzzed with AFL https://lcamtuf.coredump.cx/afl/.
-- The reader is robust to large files and malformed files, and will return any valid partial data in an image.
-- Reader supports 32bpp (with alpha channel), 24bpp, 8bpp, 4bpp, and 1bpp monochrome BMP images.
-- Reader handles indexed BMP images using a colour palette.
-- Writer supports 32bpp RGBA and 24bpp uncompressed RGB images.
-
-Current Limitations:
-- 16-bit images not supported (don't have any samples to test on).
-- No support for interleaved channel bit layouts eg RGB101010 RGB555 RGB565.
-- No support for compressed BMP images, although in practice these are not used.
-- Output images with alpha channel are written in BITMAPINFOHEADER format.
- For better alpha support in other apps the 124-bit v5 header could be used instead,
- at the cost of some backward compatibility and bloat.
-
-To Do:
-- FUZZING
- - create a unique fuzz test set for (8,4,1 BPP).
-- (maybe) FEATURE Flipping the image based on negative width and height in header, and/or function arguments.
-- (maybe) PERF ifdef intrinsics/asm for bitscan. Platform-specific code so won't include unless necessary.
-- (maybe) FEATURE Add parameter for padding output memory to eg 4-byte alignment or n channels.
-- (maybe) FEATURE Improved apps support in alpha channel writing (using v5 header).
-*/
-
-#ifndef APG_BMP_H_
-#define APG_BMP_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* CPP */
-
-/* Reads a bitmap from a file, allocates memory for the raw image data, and returns it.
-PARAMS
- * w,h, - Retrieves the width and height of the BMP in pixels.
- * n_chans - Retrieves the number of channels in the BMP.
-RETURNS
- * Tightly-packed pixel memory in RGBA order. The caller must call free() on the memory.
- * NULL on any error. Any allocated memory is freed before returning NULL. */
-unsigned char* apg_bmp_read( const char* filename, int* w, int* h, unsigned int* n_chans );
-
-/* Calls free() on memory created by apg_bmp_read */
-void apg_bmp_free( unsigned char* pixels_ptr );
-
-/* Writes a bitmap to a file.
-PARAMS
- * filename - e.g."my_bitmap.bmp". Must not be NULL.
- * pixels_ptr - Pointer to tightly-packed pixel memory in RGBA order. Must not be NULL. There must be abs(w)*abs(h)*n_chans bytes in the memory pointed to.
- * w,h, - Width and height of the image in pixels.
- * n_chans - The number of channels in the BMP. 3 or 4 supported for writing, which means RGB or RGBA memory, respectively.
-RETURNS
- * Zero on any error, non zero on success. */
-unsigned int apg_bmp_write( const char* filename, unsigned char* pixels_ptr, int w, int h, unsigned int n_chans );
-
-#ifdef __cplusplus
-}
-#endif /* CPP */
-
-#endif /*_APG_BMP_H_ */
-
-/*
--------------------------------------------------------------------------------------
-This software is available under two licences - you may use it under either licence.
--------------------------------------------------------------------------------------
-FIRST LICENCE OPTION
-
-> Apache License
-> Version 2.0, January 2004
-> http://www.apache.org/licenses/
-> Copyright 2019 Anton Gerdelan.
-> Licensed under the Apache License, Version 2.0 (the "License");
-> you may not use this file except in compliance with the License.
-> You may obtain a copy of the License at
-> http://www.apache.org/licenses/LICENSE-2.0
-> Unless required by applicable law or agreed to in writing, software
-> distributed under the License is distributed on an "AS IS" BASIS,
-> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-> See the License for the specific language governing permissions and
-> limitations under the License.
--------------------------------------------------------------------------------------
-SECOND LICENCE OPTION
-
-> This is free and unencumbered software released into the public domain.
->
-> Anyone is free to copy, modify, publish, use, compile, sell, or
-> distribute this software, either in source code form or as a compiled
-> binary, for any purpose, commercial or non-commercial, and by any
-> means.
->
-> In jurisdictions that recognize copyright laws, the author or authors
-> of this software dedicate any and all copyright interest in the
-> software to the public domain. We make this dedication for the benefit
-> of the public at large and to the detriment of our heirs and
-> successors. We intend this dedication to be an overt act of
-> relinquishment in perpetuity of all present and future rights to this
-> software under copyright law.
->
-> 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 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.
->
-> For more information, please refer to <http://unlicense.org>
--------------------------------------------------------------------------------------
-*/
diff --git a/thirdparty/basis_universal/encoder/basisu_astc_decomp.cpp b/thirdparty/basis_universal/encoder/basisu_astc_decomp.cpp
deleted file mode 100644
index 53bccfc515..0000000000
--- a/thirdparty/basis_universal/encoder/basisu_astc_decomp.cpp
+++ /dev/null
@@ -1,1561 +0,0 @@
-// basisu_astc_decomp.cpp: Only used for ASTC decompression, to validate the transcoder's output.
-// This version does not support HDR.
-
-/*-------------------------------------------------------------------------
- * drawElements Quality Program Tester Core
- * ----------------------------------------
- *
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * rg: Removed external dependencies, remarked out HDR support because
- * we don't need it, minor fix to decompress() so it converts non-sRGB
- * output to 8-bits correctly. I've compared this decoder's output
- * vs. astc-codec with random inputs on 4x4 blocks, and after fixing a few obvious
- * bugs in astc-codec where it didn't correctly follow the spec they match so
- * I'm assuming they are both correct for 4x4 now.
- * HDR support should be easily added back in, but as we don't need it
- * I'm leaving this for someone else.
- *
- *//*!
- * \file
- * \brief ASTC Utilities.
- *//*--------------------------------------------------------------------*/
-#include "basisu_astc_decomp.h"
-#include <assert.h>
-#include <algorithm>
-
-#define DE_LENGTH_OF_ARRAY(x) (sizeof(x)/sizeof(x[0]))
-#define DE_UNREF(x) (void)x
-
-typedef uint8_t deUint8;
-typedef int8_t deInt8;
-typedef uint32_t deUint32;
-typedef int32_t deInt32;
-typedef uint16_t deUint16;
-typedef int16_t deInt16;
-typedef int64_t deInt64;
-typedef uint64_t deUint64;
-
-#define DE_ASSERT assert
-
-#ifdef _MSC_VER
-#pragma warning (disable:4505) // unreferenced local function has been removed
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-#endif
-
-namespace basisu_astc
-{
- static bool inBounds(int v, int l, int h)
- {
- return (v >= l) && (v < h);
- }
-
- static bool inRange(int v, int l, int h)
- {
- return (v >= l) && (v <= h);
- }
-
- template<typename T>
- static inline T max(T a, T b)
- {
- return (a > b) ? a : b;
- }
-
- template<typename T>
- static inline T min(T a, T b)
- {
- return (a < b) ? a : b;
- }
-
- template<typename T>
- static inline T clamp(T a, T l, T h)
- {
- if (a < l)
- return l;
- else if (a > h)
- return h;
- return a;
- }
-
- struct UVec4
- {
- uint32_t m_c[4];
-
- UVec4()
- {
- m_c[0] = 0;
- m_c[1] = 0;
- m_c[2] = 0;
- m_c[3] = 0;
- }
-
- UVec4(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
- {
- m_c[0] = x;
- m_c[1] = y;
- m_c[2] = z;
- m_c[3] = w;
- }
-
- uint32_t x() const { return m_c[0]; }
- uint32_t y() const { return m_c[1]; }
- uint32_t z() const { return m_c[2]; }
- uint32_t w() const { return m_c[3]; }
-
- uint32_t& x() { return m_c[0]; }
- uint32_t& y() { return m_c[1]; }
- uint32_t& z() { return m_c[2]; }
- uint32_t& w() { return m_c[3]; }
-
- uint32_t operator[] (uint32_t idx) const { assert(idx < 4); return m_c[idx]; }
- uint32_t& operator[] (uint32_t idx) { assert(idx < 4); return m_c[idx]; }
- };
-
- struct IVec4
- {
- int32_t m_c[4];
-
- IVec4()
- {
- m_c[0] = 0;
- m_c[1] = 0;
- m_c[2] = 0;
- m_c[3] = 0;
- }
-
- IVec4(int32_t x, int32_t y, int32_t z, int32_t w)
- {
- m_c[0] = x;
- m_c[1] = y;
- m_c[2] = z;
- m_c[3] = w;
- }
-
- int32_t x() const { return m_c[0]; }
- int32_t y() const { return m_c[1]; }
- int32_t z() const { return m_c[2]; }
- int32_t w() const { return m_c[3]; }
-
- int32_t& x() { return m_c[0]; }
- int32_t& y() { return m_c[1]; }
- int32_t& z() { return m_c[2]; }
- int32_t& w() { return m_c[3]; }
-
- UVec4 asUint() const
- {
- return UVec4(basisu::maximum(0, m_c[0]), basisu::maximum(0, m_c[1]), basisu::maximum(0, m_c[2]), basisu::maximum(0, m_c[3]));
- }
-
- int32_t operator[] (uint32_t idx) const { assert(idx < 4); return m_c[idx]; }
- int32_t& operator[] (uint32_t idx) { assert(idx < 4); return m_c[idx]; }
- };
-
- struct IVec3
- {
- int32_t m_c[3];
-
- IVec3()
- {
- m_c[0] = 0;
- m_c[1] = 0;
- m_c[2] = 0;
- }
-
- IVec3(int32_t x, int32_t y, int32_t z)
- {
- m_c[0] = x;
- m_c[1] = y;
- m_c[2] = z;
- }
-
- int32_t x() const { return m_c[0]; }
- int32_t y() const { return m_c[1]; }
- int32_t z() const { return m_c[2]; }
-
- int32_t& x() { return m_c[0]; }
- int32_t& y() { return m_c[1]; }
- int32_t& z() { return m_c[2]; }
-
- int32_t operator[] (uint32_t idx) const { assert(idx < 3); return m_c[idx]; }
- int32_t& operator[] (uint32_t idx) { assert(idx < 3); return m_c[idx]; }
- };
-
- static uint32_t deDivRoundUp32(uint32_t a, uint32_t b)
- {
- return (a + b - 1) / b;
- }
-
- static bool deInBounds32(uint32_t v, uint32_t l, uint32_t h)
- {
- return (v >= l) && (v < h);
- }
-
-namespace astc
-{
-using std::vector;
-namespace
-{
-// Common utilities
-enum
-{
- MAX_BLOCK_WIDTH = 12,
- MAX_BLOCK_HEIGHT = 12
-};
-inline deUint32 getBit (deUint32 src, int ndx)
-{
- DE_ASSERT(basisu_astc::inBounds(ndx, 0, 32));
- return (src >> ndx) & 1;
-}
-inline deUint32 getBits (deUint32 src, int low, int high)
-{
- const int numBits = (high-low) + 1;
- DE_ASSERT(basisu_astc::inRange(numBits, 1, 32));
- if (numBits < 32)
- return (deUint32)((src >> low) & ((1u<<numBits)-1));
- else
- return (deUint32)((src >> low) & 0xFFFFFFFFu);
-}
-inline bool isBitSet (deUint32 src, int ndx)
-{
- return getBit(src, ndx) != 0;
-}
-inline deUint32 reverseBits (deUint32 src, int numBits)
-{
- DE_ASSERT(basisu_astc::inRange(numBits, 0, 32));
- deUint32 result = 0;
- for (int i = 0; i < numBits; i++)
- result |= ((src >> i) & 1) << (numBits-1-i);
- return result;
-}
-inline deUint32 bitReplicationScale (deUint32 src, int numSrcBits, int numDstBits)
-{
- DE_ASSERT(numSrcBits <= numDstBits);
- DE_ASSERT((src & ((1<<numSrcBits)-1)) == src);
- deUint32 dst = 0;
- for (int shift = numDstBits-numSrcBits; shift > -numSrcBits; shift -= numSrcBits)
- dst |= shift >= 0 ? src << shift : src >> -shift;
- return dst;
-}
-
-inline deInt32 signExtend (deInt32 src, int numSrcBits)
-{
- DE_ASSERT(basisu_astc::inRange(numSrcBits, 2, 31));
- const bool negative = (src & (1 << (numSrcBits-1))) != 0;
- return src | (negative ? ~((1 << numSrcBits) - 1) : 0);
-}
-
-//inline bool isFloat16InfOrNan (deFloat16 v)
-//{
-// return getBits(v, 10, 14) == 31;
-//}
-
-enum ISEMode
-{
- ISEMODE_TRIT = 0,
- ISEMODE_QUINT,
- ISEMODE_PLAIN_BIT,
- ISEMODE_LAST
-};
-struct ISEParams
-{
- ISEMode mode;
- int numBits;
- ISEParams (ISEMode mode_, int numBits_) : mode(mode_), numBits(numBits_) {}
-};
-inline int computeNumRequiredBits (const ISEParams& iseParams, int numValues)
-{
- switch (iseParams.mode)
- {
- case ISEMODE_TRIT: return deDivRoundUp32(numValues*8, 5) + numValues*iseParams.numBits;
- case ISEMODE_QUINT: return deDivRoundUp32(numValues*7, 3) + numValues*iseParams.numBits;
- case ISEMODE_PLAIN_BIT: return numValues*iseParams.numBits;
- default:
- DE_ASSERT(false);
- return -1;
- }
-}
-ISEParams computeMaximumRangeISEParams (int numAvailableBits, int numValuesInSequence)
-{
- int curBitsForTritMode = 6;
- int curBitsForQuintMode = 5;
- int curBitsForPlainBitMode = 8;
- while (true)
- {
- DE_ASSERT(curBitsForTritMode > 0 || curBitsForQuintMode > 0 || curBitsForPlainBitMode > 0);
- const int tritRange = curBitsForTritMode > 0 ? (3 << curBitsForTritMode) - 1 : -1;
- const int quintRange = curBitsForQuintMode > 0 ? (5 << curBitsForQuintMode) - 1 : -1;
- const int plainBitRange = curBitsForPlainBitMode > 0 ? (1 << curBitsForPlainBitMode) - 1 : -1;
- const int maxRange = basisu_astc::max(basisu_astc::max(tritRange, quintRange), plainBitRange);
- if (maxRange == tritRange)
- {
- const ISEParams params(ISEMODE_TRIT, curBitsForTritMode);
- if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
- return ISEParams(ISEMODE_TRIT, curBitsForTritMode);
- curBitsForTritMode--;
- }
- else if (maxRange == quintRange)
- {
- const ISEParams params(ISEMODE_QUINT, curBitsForQuintMode);
- if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
- return ISEParams(ISEMODE_QUINT, curBitsForQuintMode);
- curBitsForQuintMode--;
- }
- else
- {
- const ISEParams params(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
- DE_ASSERT(maxRange == plainBitRange);
- if (computeNumRequiredBits(params, numValuesInSequence) <= numAvailableBits)
- return ISEParams(ISEMODE_PLAIN_BIT, curBitsForPlainBitMode);
- curBitsForPlainBitMode--;
- }
- }
-}
-inline int computeNumColorEndpointValues (deUint32 endpointMode)
-{
- DE_ASSERT(endpointMode < 16);
- return (endpointMode/4 + 1) * 2;
-}
-// Decompression utilities
-enum DecompressResult
-{
- DECOMPRESS_RESULT_VALID_BLOCK = 0, //!< Decompressed valid block
- DECOMPRESS_RESULT_ERROR, //!< Encountered error while decompressing, error color written
- DECOMPRESS_RESULT_LAST
-};
-// A helper for getting bits from a 128-bit block.
-class Block128
-{
-private:
- typedef deUint64 Word;
- enum
- {
- WORD_BYTES = sizeof(Word),
- WORD_BITS = 8*WORD_BYTES,
- NUM_WORDS = 128 / WORD_BITS
- };
- //DE_STATIC_ASSERT(128 % WORD_BITS == 0);
-public:
- Block128 (const deUint8* src)
- {
- for (int wordNdx = 0; wordNdx < NUM_WORDS; wordNdx++)
- {
- m_words[wordNdx] = 0;
- for (int byteNdx = 0; byteNdx < WORD_BYTES; byteNdx++)
- m_words[wordNdx] |= (Word)src[wordNdx*WORD_BYTES + byteNdx] << (8*byteNdx);
- }
- }
- deUint32 getBit (int ndx) const
- {
- DE_ASSERT(basisu_astc::inBounds(ndx, 0, 128));
- return (m_words[ndx / WORD_BITS] >> (ndx % WORD_BITS)) & 1;
- }
- deUint32 getBits (int low, int high) const
- {
- DE_ASSERT(basisu_astc::inBounds(low, 0, 128));
- DE_ASSERT(basisu_astc::inBounds(high, 0, 128));
- DE_ASSERT(basisu_astc::inRange(high-low+1, 0, 32));
- if (high-low+1 == 0)
- return 0;
- const int word0Ndx = low / WORD_BITS;
- const int word1Ndx = high / WORD_BITS;
- // \note "foo << bar << 1" done instead of "foo << (bar+1)" to avoid overflow, i.e. shift amount being too big.
- if (word0Ndx == word1Ndx)
- return (deUint32)((m_words[word0Ndx] & ((((Word)1 << high%WORD_BITS << 1) - 1))) >> ((Word)low % WORD_BITS));
- else
- {
- DE_ASSERT(word1Ndx == word0Ndx + 1);
- return (deUint32)(m_words[word0Ndx] >> (low%WORD_BITS)) |
- (deUint32)((m_words[word1Ndx] & (((Word)1 << high%WORD_BITS << 1) - 1)) << (high-low - high%WORD_BITS));
- }
- }
- bool isBitSet (int ndx) const
- {
- DE_ASSERT(basisu_astc::inBounds(ndx, 0, 128));
- return getBit(ndx) != 0;
- }
-private:
- Word m_words[NUM_WORDS];
-};
-// A helper for sequential access into a Block128.
-class BitAccessStream
-{
-public:
- BitAccessStream (const Block128& src, int startNdxInSrc, int length, bool forward)
- : m_src (src)
- , m_startNdxInSrc (startNdxInSrc)
- , m_length (length)
- , m_forward (forward)
- , m_ndx (0)
- {
- }
- // Get the next num bits. Bits at positions greater than or equal to m_length are zeros.
- deUint32 getNext (int num)
- {
- if (num == 0 || m_ndx >= m_length)
- return 0;
- const int end = m_ndx + num;
- const int numBitsFromSrc = basisu_astc::max(0, basisu_astc::min(m_length, end) - m_ndx);
- const int low = m_ndx;
- const int high = m_ndx + numBitsFromSrc - 1;
- m_ndx += num;
- return m_forward ? m_src.getBits(m_startNdxInSrc + low, m_startNdxInSrc + high)
- : reverseBits(m_src.getBits(m_startNdxInSrc - high, m_startNdxInSrc - low), numBitsFromSrc);
- }
-private:
- const Block128& m_src;
- const int m_startNdxInSrc;
- const int m_length;
- const bool m_forward;
- int m_ndx;
-};
-struct ISEDecodedResult
-{
- deUint32 m;
- deUint32 tq; //!< Trit or quint value, depending on ISE mode.
- deUint32 v;
-};
-// Data from an ASTC block's "block mode" part (i.e. bits [0,10]).
-struct ASTCBlockMode
-{
- bool isError;
- // \note Following fields only relevant if !isError.
- bool isVoidExtent;
- // \note Following fields only relevant if !isVoidExtent.
- bool isDualPlane;
- int weightGridWidth;
- int weightGridHeight;
- ISEParams weightISEParams;
- ASTCBlockMode (void)
- : isError (true)
- , isVoidExtent (true)
- , isDualPlane (true)
- , weightGridWidth (-1)
- , weightGridHeight (-1)
- , weightISEParams (ISEMODE_LAST, -1)
- {
- }
-};
-inline int computeNumWeights (const ASTCBlockMode& mode)
-{
- return mode.weightGridWidth * mode.weightGridHeight * (mode.isDualPlane ? 2 : 1);
-}
-struct ColorEndpointPair
-{
- UVec4 e0;
- UVec4 e1;
-};
-struct TexelWeightPair
-{
- deUint32 w[2];
-};
-ASTCBlockMode getASTCBlockMode (deUint32 blockModeData)
-{
- ASTCBlockMode blockMode;
- blockMode.isError = true; // \note Set to false later, if not error.
- blockMode.isVoidExtent = getBits(blockModeData, 0, 8) == 0x1fc;
- if (!blockMode.isVoidExtent)
- {
- if ((getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 6, 8) == 7) || getBits(blockModeData, 0, 3) == 0)
- return blockMode; // Invalid ("reserved").
- deUint32 r = (deUint32)-1; // \note Set in the following branches.
- if (getBits(blockModeData, 0, 1) == 0)
- {
- const deUint32 r0 = getBit(blockModeData, 4);
- const deUint32 r1 = getBit(blockModeData, 2);
- const deUint32 r2 = getBit(blockModeData, 3);
- const deUint32 i78 = getBits(blockModeData, 7, 8);
- r = (r2 << 2) | (r1 << 1) | (r0 << 0);
- if (i78 == 3)
- {
- const bool i5 = isBitSet(blockModeData, 5);
- blockMode.weightGridWidth = i5 ? 10 : 6;
- blockMode.weightGridHeight = i5 ? 6 : 10;
- }
- else
- {
- const deUint32 a = getBits(blockModeData, 5, 6);
- switch (i78)
- {
- case 0: blockMode.weightGridWidth = 12; blockMode.weightGridHeight = a + 2; break;
- case 1: blockMode.weightGridWidth = a + 2; blockMode.weightGridHeight = 12; break;
- case 2: blockMode.weightGridWidth = a + 6; blockMode.weightGridHeight = getBits(blockModeData, 9, 10) + 6; break;
- default: DE_ASSERT(false);
- }
- }
- }
- else
- {
- const deUint32 r0 = getBit(blockModeData, 4);
- const deUint32 r1 = getBit(blockModeData, 0);
- const deUint32 r2 = getBit(blockModeData, 1);
- const deUint32 i23 = getBits(blockModeData, 2, 3);
- const deUint32 a = getBits(blockModeData, 5, 6);
- r = (r2 << 2) | (r1 << 1) | (r0 << 0);
- if (i23 == 3)
- {
- const deUint32 b = getBit(blockModeData, 7);
- const bool i8 = isBitSet(blockModeData, 8);
- blockMode.weightGridWidth = i8 ? b+2 : a+2;
- blockMode.weightGridHeight = i8 ? a+2 : b+6;
- }
- else
- {
- const deUint32 b = getBits(blockModeData, 7, 8);
- switch (i23)
- {
- case 0: blockMode.weightGridWidth = b + 4; blockMode.weightGridHeight = a + 2; break;
- case 1: blockMode.weightGridWidth = b + 8; blockMode.weightGridHeight = a + 2; break;
- case 2: blockMode.weightGridWidth = a + 2; blockMode.weightGridHeight = b + 8; break;
- default: DE_ASSERT(false);
- }
- }
- }
- const bool zeroDH = getBits(blockModeData, 0, 1) == 0 && getBits(blockModeData, 7, 8) == 2;
- const bool h = zeroDH ? 0 : isBitSet(blockModeData, 9);
- blockMode.isDualPlane = zeroDH ? 0 : isBitSet(blockModeData, 10);
- {
- ISEMode& m = blockMode.weightISEParams.mode;
- int& b = blockMode.weightISEParams.numBits;
- m = ISEMODE_PLAIN_BIT;
- b = 0;
- if (h)
- {
- switch (r)
- {
- case 2: m = ISEMODE_QUINT; b = 1; break;
- case 3: m = ISEMODE_TRIT; b = 2; break;
- case 4: b = 4; break;
- case 5: m = ISEMODE_QUINT; b = 2; break;
- case 6: m = ISEMODE_TRIT; b = 3; break;
- case 7: b = 5; break;
- default: DE_ASSERT(false);
- }
- }
- else
- {
- switch (r)
- {
- case 2: b = 1; break;
- case 3: m = ISEMODE_TRIT; break;
- case 4: b = 2; break;
- case 5: m = ISEMODE_QUINT; break;
- case 6: m = ISEMODE_TRIT; b = 1; break;
- case 7: b = 3; break;
- default: DE_ASSERT(false);
- }
- }
- }
- }
- blockMode.isError = false;
- return blockMode;
-}
-inline void setASTCErrorColorBlock (void* dst, int blockWidth, int blockHeight, bool isSRGB)
-{
- if (isSRGB)
- {
- deUint8* const dstU = (deUint8*)dst;
- for (int i = 0; i < blockWidth*blockHeight; i++)
- {
- dstU[4*i + 0] = 0xff;
- dstU[4*i + 1] = 0;
- dstU[4*i + 2] = 0xff;
- dstU[4*i + 3] = 0xff;
- }
- }
- else
- {
- float* const dstF = (float*)dst;
- for (int i = 0; i < blockWidth*blockHeight; i++)
- {
- dstF[4*i + 0] = 1.0f;
- dstF[4*i + 1] = 0.0f;
- dstF[4*i + 2] = 1.0f;
- dstF[4*i + 3] = 1.0f;
- }
- }
-}
-DecompressResult decodeVoidExtentBlock (void* dst, const Block128& blockData, int blockWidth, int blockHeight, bool isSRGB, bool isLDRMode)
-{
- const deUint32 minSExtent = blockData.getBits(12, 24);
- const deUint32 maxSExtent = blockData.getBits(25, 37);
- const deUint32 minTExtent = blockData.getBits(38, 50);
- const deUint32 maxTExtent = blockData.getBits(51, 63);
- const bool allExtentsAllOnes = minSExtent == 0x1fff && maxSExtent == 0x1fff && minTExtent == 0x1fff && maxTExtent == 0x1fff;
- const bool isHDRBlock = blockData.isBitSet(9);
- if ((isLDRMode && isHDRBlock) || (!allExtentsAllOnes && (minSExtent >= maxSExtent || minTExtent >= maxTExtent)))
- {
- setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
- return DECOMPRESS_RESULT_ERROR;
- }
- const deUint32 rgba[4] =
- {
- blockData.getBits(64, 79),
- blockData.getBits(80, 95),
- blockData.getBits(96, 111),
- blockData.getBits(112, 127)
- };
- if (isSRGB)
- {
- deUint8* const dstU = (deUint8*)dst;
- for (int i = 0; i < blockWidth*blockHeight; i++)
- for (int c = 0; c < 4; c++)
- dstU[i*4 + c] = (deUint8)((rgba[c] & 0xff00) >> 8);
- }
- else
- {
- float* const dstF = (float*)dst;
- if (isHDRBlock)
- {
- // rg - REMOVING HDR SUPPORT FOR NOW
-#if 0
- for (int c = 0; c < 4; c++)
- {
- if (isFloat16InfOrNan((deFloat16)rgba[c]))
- throw InternalError("Infinity or NaN color component in HDR void extent block in ASTC texture (behavior undefined by ASTC specification)");
- }
- for (int i = 0; i < blockWidth*blockHeight; i++)
- for (int c = 0; c < 4; c++)
- dstF[i*4 + c] = deFloat16To32((deFloat16)rgba[c]);
-#endif
- }
- else
- {
- for (int i = 0; i < blockWidth*blockHeight; i++)
- for (int c = 0; c < 4; c++)
- dstF[i*4 + c] = rgba[c] == 65535 ? 1.0f : (float)rgba[c] / 65536.0f;
- }
- }
- return DECOMPRESS_RESULT_VALID_BLOCK;
-}
-void decodeColorEndpointModes (deUint32* endpointModesDst, const Block128& blockData, int numPartitions, int extraCemBitsStart)
-{
- if (numPartitions == 1)
- endpointModesDst[0] = blockData.getBits(13, 16);
- else
- {
- const deUint32 highLevelSelector = blockData.getBits(23, 24);
- if (highLevelSelector == 0)
- {
- const deUint32 mode = blockData.getBits(25, 28);
- for (int i = 0; i < numPartitions; i++)
- endpointModesDst[i] = mode;
- }
- else
- {
- for (int partNdx = 0; partNdx < numPartitions; partNdx++)
- {
- const deUint32 cemClass = highLevelSelector - (blockData.isBitSet(25 + partNdx) ? 0 : 1);
- const deUint32 lowBit0Ndx = numPartitions + 2*partNdx;
- const deUint32 lowBit1Ndx = numPartitions + 2*partNdx + 1;
- const deUint32 lowBit0 = blockData.getBit(lowBit0Ndx < 4 ? 25+lowBit0Ndx : extraCemBitsStart+lowBit0Ndx-4);
- const deUint32 lowBit1 = blockData.getBit(lowBit1Ndx < 4 ? 25+lowBit1Ndx : extraCemBitsStart+lowBit1Ndx-4);
- endpointModesDst[partNdx] = (cemClass << 2) | (lowBit1 << 1) | lowBit0;
- }
- }
- }
-}
-int computeNumColorEndpointValues (const deUint32* endpointModes, int numPartitions)
-{
- int result = 0;
- for (int i = 0; i < numPartitions; i++)
- result += computeNumColorEndpointValues(endpointModes[i]);
- return result;
-}
-void decodeISETritBlock (ISEDecodedResult* dst, int numValues, BitAccessStream& data, int numBits)
-{
- DE_ASSERT(basisu_astc::inRange(numValues, 1, 5));
- deUint32 m[5];
- m[0] = data.getNext(numBits);
- deUint32 T01 = data.getNext(2);
- m[1] = data.getNext(numBits);
- deUint32 T23 = data.getNext(2);
- m[2] = data.getNext(numBits);
- deUint32 T4 = data.getNext(1);
- m[3] = data.getNext(numBits);
- deUint32 T56 = data.getNext(2);
- m[4] = data.getNext(numBits);
- deUint32 T7 = data.getNext(1);
- switch (numValues)
- {
- // \note Fall-throughs.
- case 1: T23 = 0;
- case 2: T4 = 0;
- case 3: T56 = 0;
- case 4: T7 = 0;
- case 5: break;
- default:
- DE_ASSERT(false);
- }
- const deUint32 T = (T7 << 7) | (T56 << 5) | (T4 << 4) | (T23 << 2) | (T01 << 0);
- static const deUint32 tritsFromT[256][5] =
- {
- { 0,0,0,0,0 }, { 1,0,0,0,0 }, { 2,0,0,0,0 }, { 0,0,2,0,0 }, { 0,1,0,0,0 }, { 1,1,0,0,0 }, { 2,1,0,0,0 }, { 1,0,2,0,0 }, { 0,2,0,0,0 }, { 1,2,0,0,0 }, { 2,2,0,0,0 }, { 2,0,2,0,0 }, { 0,2,2,0,0 }, { 1,2,2,0,0 }, { 2,2,2,0,0 }, { 2,0,2,0,0 },
- { 0,0,1,0,0 }, { 1,0,1,0,0 }, { 2,0,1,0,0 }, { 0,1,2,0,0 }, { 0,1,1,0,0 }, { 1,1,1,0,0 }, { 2,1,1,0,0 }, { 1,1,2,0,0 }, { 0,2,1,0,0 }, { 1,2,1,0,0 }, { 2,2,1,0,0 }, { 2,1,2,0,0 }, { 0,0,0,2,2 }, { 1,0,0,2,2 }, { 2,0,0,2,2 }, { 0,0,2,2,2 },
- { 0,0,0,1,0 }, { 1,0,0,1,0 }, { 2,0,0,1,0 }, { 0,0,2,1,0 }, { 0,1,0,1,0 }, { 1,1,0,1,0 }, { 2,1,0,1,0 }, { 1,0,2,1,0 }, { 0,2,0,1,0 }, { 1,2,0,1,0 }, { 2,2,0,1,0 }, { 2,0,2,1,0 }, { 0,2,2,1,0 }, { 1,2,2,1,0 }, { 2,2,2,1,0 }, { 2,0,2,1,0 },
- { 0,0,1,1,0 }, { 1,0,1,1,0 }, { 2,0,1,1,0 }, { 0,1,2,1,0 }, { 0,1,1,1,0 }, { 1,1,1,1,0 }, { 2,1,1,1,0 }, { 1,1,2,1,0 }, { 0,2,1,1,0 }, { 1,2,1,1,0 }, { 2,2,1,1,0 }, { 2,1,2,1,0 }, { 0,1,0,2,2 }, { 1,1,0,2,2 }, { 2,1,0,2,2 }, { 1,0,2,2,2 },
- { 0,0,0,2,0 }, { 1,0,0,2,0 }, { 2,0,0,2,0 }, { 0,0,2,2,0 }, { 0,1,0,2,0 }, { 1,1,0,2,0 }, { 2,1,0,2,0 }, { 1,0,2,2,0 }, { 0,2,0,2,0 }, { 1,2,0,2,0 }, { 2,2,0,2,0 }, { 2,0,2,2,0 }, { 0,2,2,2,0 }, { 1,2,2,2,0 }, { 2,2,2,2,0 }, { 2,0,2,2,0 },
- { 0,0,1,2,0 }, { 1,0,1,2,0 }, { 2,0,1,2,0 }, { 0,1,2,2,0 }, { 0,1,1,2,0 }, { 1,1,1,2,0 }, { 2,1,1,2,0 }, { 1,1,2,2,0 }, { 0,2,1,2,0 }, { 1,2,1,2,0 }, { 2,2,1,2,0 }, { 2,1,2,2,0 }, { 0,2,0,2,2 }, { 1,2,0,2,2 }, { 2,2,0,2,2 }, { 2,0,2,2,2 },
- { 0,0,0,0,2 }, { 1,0,0,0,2 }, { 2,0,0,0,2 }, { 0,0,2,0,2 }, { 0,1,0,0,2 }, { 1,1,0,0,2 }, { 2,1,0,0,2 }, { 1,0,2,0,2 }, { 0,2,0,0,2 }, { 1,2,0,0,2 }, { 2,2,0,0,2 }, { 2,0,2,0,2 }, { 0,2,2,0,2 }, { 1,2,2,0,2 }, { 2,2,2,0,2 }, { 2,0,2,0,2 },
- { 0,0,1,0,2 }, { 1,0,1,0,2 }, { 2,0,1,0,2 }, { 0,1,2,0,2 }, { 0,1,1,0,2 }, { 1,1,1,0,2 }, { 2,1,1,0,2 }, { 1,1,2,0,2 }, { 0,2,1,0,2 }, { 1,2,1,0,2 }, { 2,2,1,0,2 }, { 2,1,2,0,2 }, { 0,2,2,2,2 }, { 1,2,2,2,2 }, { 2,2,2,2,2 }, { 2,0,2,2,2 },
- { 0,0,0,0,1 }, { 1,0,0,0,1 }, { 2,0,0,0,1 }, { 0,0,2,0,1 }, { 0,1,0,0,1 }, { 1,1,0,0,1 }, { 2,1,0,0,1 }, { 1,0,2,0,1 }, { 0,2,0,0,1 }, { 1,2,0,0,1 }, { 2,2,0,0,1 }, { 2,0,2,0,1 }, { 0,2,2,0,1 }, { 1,2,2,0,1 }, { 2,2,2,0,1 }, { 2,0,2,0,1 },
- { 0,0,1,0,1 }, { 1,0,1,0,1 }, { 2,0,1,0,1 }, { 0,1,2,0,1 }, { 0,1,1,0,1 }, { 1,1,1,0,1 }, { 2,1,1,0,1 }, { 1,1,2,0,1 }, { 0,2,1,0,1 }, { 1,2,1,0,1 }, { 2,2,1,0,1 }, { 2,1,2,0,1 }, { 0,0,1,2,2 }, { 1,0,1,2,2 }, { 2,0,1,2,2 }, { 0,1,2,2,2 },
- { 0,0,0,1,1 }, { 1,0,0,1,1 }, { 2,0,0,1,1 }, { 0,0,2,1,1 }, { 0,1,0,1,1 }, { 1,1,0,1,1 }, { 2,1,0,1,1 }, { 1,0,2,1,1 }, { 0,2,0,1,1 }, { 1,2,0,1,1 }, { 2,2,0,1,1 }, { 2,0,2,1,1 }, { 0,2,2,1,1 }, { 1,2,2,1,1 }, { 2,2,2,1,1 }, { 2,0,2,1,1 },
- { 0,0,1,1,1 }, { 1,0,1,1,1 }, { 2,0,1,1,1 }, { 0,1,2,1,1 }, { 0,1,1,1,1 }, { 1,1,1,1,1 }, { 2,1,1,1,1 }, { 1,1,2,1,1 }, { 0,2,1,1,1 }, { 1,2,1,1,1 }, { 2,2,1,1,1 }, { 2,1,2,1,1 }, { 0,1,1,2,2 }, { 1,1,1,2,2 }, { 2,1,1,2,2 }, { 1,1,2,2,2 },
- { 0,0,0,2,1 }, { 1,0,0,2,1 }, { 2,0,0,2,1 }, { 0,0,2,2,1 }, { 0,1,0,2,1 }, { 1,1,0,2,1 }, { 2,1,0,2,1 }, { 1,0,2,2,1 }, { 0,2,0,2,1 }, { 1,2,0,2,1 }, { 2,2,0,2,1 }, { 2,0,2,2,1 }, { 0,2,2,2,1 }, { 1,2,2,2,1 }, { 2,2,2,2,1 }, { 2,0,2,2,1 },
- { 0,0,1,2,1 }, { 1,0,1,2,1 }, { 2,0,1,2,1 }, { 0,1,2,2,1 }, { 0,1,1,2,1 }, { 1,1,1,2,1 }, { 2,1,1,2,1 }, { 1,1,2,2,1 }, { 0,2,1,2,1 }, { 1,2,1,2,1 }, { 2,2,1,2,1 }, { 2,1,2,2,1 }, { 0,2,1,2,2 }, { 1,2,1,2,2 }, { 2,2,1,2,2 }, { 2,1,2,2,2 },
- { 0,0,0,1,2 }, { 1,0,0,1,2 }, { 2,0,0,1,2 }, { 0,0,2,1,2 }, { 0,1,0,1,2 }, { 1,1,0,1,2 }, { 2,1,0,1,2 }, { 1,0,2,1,2 }, { 0,2,0,1,2 }, { 1,2,0,1,2 }, { 2,2,0,1,2 }, { 2,0,2,1,2 }, { 0,2,2,1,2 }, { 1,2,2,1,2 }, { 2,2,2,1,2 }, { 2,0,2,1,2 },
- { 0,0,1,1,2 }, { 1,0,1,1,2 }, { 2,0,1,1,2 }, { 0,1,2,1,2 }, { 0,1,1,1,2 }, { 1,1,1,1,2 }, { 2,1,1,1,2 }, { 1,1,2,1,2 }, { 0,2,1,1,2 }, { 1,2,1,1,2 }, { 2,2,1,1,2 }, { 2,1,2,1,2 }, { 0,2,2,2,2 }, { 1,2,2,2,2 }, { 2,2,2,2,2 }, { 2,1,2,2,2 }
- };
- const deUint32 (& trits)[5] = tritsFromT[T];
- for (int i = 0; i < numValues; i++)
- {
- dst[i].m = m[i];
- dst[i].tq = trits[i];
- dst[i].v = (trits[i] << numBits) + m[i];
- }
-}
-void decodeISEQuintBlock (ISEDecodedResult* dst, int numValues, BitAccessStream& data, int numBits)
-{
- DE_ASSERT(basisu_astc::inRange(numValues, 1, 3));
- deUint32 m[3];
- m[0] = data.getNext(numBits);
- deUint32 Q012 = data.getNext(3);
- m[1] = data.getNext(numBits);
- deUint32 Q34 = data.getNext(2);
- m[2] = data.getNext(numBits);
- deUint32 Q56 = data.getNext(2);
- switch (numValues)
- {
- // \note Fall-throughs.
- case 1: Q34 = 0;
- case 2: Q56 = 0;
- case 3: break;
- default:
- DE_ASSERT(false);
- }
- const deUint32 Q = (Q56 << 5) | (Q34 << 3) | (Q012 << 0);
- static const deUint32 quintsFromQ[256][3] =
- {
- { 0,0,0 }, { 1,0,0 }, { 2,0,0 }, { 3,0,0 }, { 4,0,0 }, { 0,4,0 }, { 4,4,0 }, { 4,4,4 }, { 0,1,0 }, { 1,1,0 }, { 2,1,0 }, { 3,1,0 }, { 4,1,0 }, { 1,4,0 }, { 4,4,1 }, { 4,4,4 },
- { 0,2,0 }, { 1,2,0 }, { 2,2,0 }, { 3,2,0 }, { 4,2,0 }, { 2,4,0 }, { 4,4,2 }, { 4,4,4 }, { 0,3,0 }, { 1,3,0 }, { 2,3,0 }, { 3,3,0 }, { 4,3,0 }, { 3,4,0 }, { 4,4,3 }, { 4,4,4 },
- { 0,0,1 }, { 1,0,1 }, { 2,0,1 }, { 3,0,1 }, { 4,0,1 }, { 0,4,1 }, { 4,0,4 }, { 0,4,4 }, { 0,1,1 }, { 1,1,1 }, { 2,1,1 }, { 3,1,1 }, { 4,1,1 }, { 1,4,1 }, { 4,1,4 }, { 1,4,4 },
- { 0,2,1 }, { 1,2,1 }, { 2,2,1 }, { 3,2,1 }, { 4,2,1 }, { 2,4,1 }, { 4,2,4 }, { 2,4,4 }, { 0,3,1 }, { 1,3,1 }, { 2,3,1 }, { 3,3,1 }, { 4,3,1 }, { 3,4,1 }, { 4,3,4 }, { 3,4,4 },
- { 0,0,2 }, { 1,0,2 }, { 2,0,2 }, { 3,0,2 }, { 4,0,2 }, { 0,4,2 }, { 2,0,4 }, { 3,0,4 }, { 0,1,2 }, { 1,1,2 }, { 2,1,2 }, { 3,1,2 }, { 4,1,2 }, { 1,4,2 }, { 2,1,4 }, { 3,1,4 },
- { 0,2,2 }, { 1,2,2 }, { 2,2,2 }, { 3,2,2 }, { 4,2,2 }, { 2,4,2 }, { 2,2,4 }, { 3,2,4 }, { 0,3,2 }, { 1,3,2 }, { 2,3,2 }, { 3,3,2 }, { 4,3,2 }, { 3,4,2 }, { 2,3,4 }, { 3,3,4 },
- { 0,0,3 }, { 1,0,3 }, { 2,0,3 }, { 3,0,3 }, { 4,0,3 }, { 0,4,3 }, { 0,0,4 }, { 1,0,4 }, { 0,1,3 }, { 1,1,3 }, { 2,1,3 }, { 3,1,3 }, { 4,1,3 }, { 1,4,3 }, { 0,1,4 }, { 1,1,4 },
- { 0,2,3 }, { 1,2,3 }, { 2,2,3 }, { 3,2,3 }, { 4,2,3 }, { 2,4,3 }, { 0,2,4 }, { 1,2,4 }, { 0,3,3 }, { 1,3,3 }, { 2,3,3 }, { 3,3,3 }, { 4,3,3 }, { 3,4,3 }, { 0,3,4 }, { 1,3,4 }
- };
- const deUint32 (& quints)[3] = quintsFromQ[Q];
- for (int i = 0; i < numValues; i++)
- {
- dst[i].m = m[i];
- dst[i].tq = quints[i];
- dst[i].v = (quints[i] << numBits) + m[i];
- }
-}
-inline void decodeISEBitBlock (ISEDecodedResult* dst, BitAccessStream& data, int numBits)
-{
- dst[0].m = data.getNext(numBits);
- dst[0].v = dst[0].m;
-}
-void decodeISE (ISEDecodedResult* dst, int numValues, BitAccessStream& data, const ISEParams& params)
-{
- if (params.mode == ISEMODE_TRIT)
- {
- const int numBlocks = deDivRoundUp32(numValues, 5);
- for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
- {
- const int numValuesInBlock = blockNdx == numBlocks-1 ? numValues - 5*(numBlocks-1) : 5;
- decodeISETritBlock(&dst[5*blockNdx], numValuesInBlock, data, params.numBits);
- }
- }
- else if (params.mode == ISEMODE_QUINT)
- {
- const int numBlocks = deDivRoundUp32(numValues, 3);
- for (int blockNdx = 0; blockNdx < numBlocks; blockNdx++)
- {
- const int numValuesInBlock = blockNdx == numBlocks-1 ? numValues - 3*(numBlocks-1) : 3;
- decodeISEQuintBlock(&dst[3*blockNdx], numValuesInBlock, data, params.numBits);
- }
- }
- else
- {
- DE_ASSERT(params.mode == ISEMODE_PLAIN_BIT);
- for (int i = 0; i < numValues; i++)
- decodeISEBitBlock(&dst[i], data, params.numBits);
- }
-}
-void unquantizeColorEndpoints (deUint32* dst, const ISEDecodedResult* iseResults, int numEndpoints, const ISEParams& iseParams)
-{
- if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
- {
- const int rangeCase = iseParams.numBits*2 - (iseParams.mode == ISEMODE_TRIT ? 2 : 1);
- DE_ASSERT(basisu_astc::inRange(rangeCase, 0, 10));
- static const deUint32 Ca[11] = { 204, 113, 93, 54, 44, 26, 22, 13, 11, 6, 5 };
- const deUint32 C = Ca[rangeCase];
- for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
- {
- const deUint32 a = getBit(iseResults[endpointNdx].m, 0);
- const deUint32 b = getBit(iseResults[endpointNdx].m, 1);
- const deUint32 c = getBit(iseResults[endpointNdx].m, 2);
- const deUint32 d = getBit(iseResults[endpointNdx].m, 3);
- const deUint32 e = getBit(iseResults[endpointNdx].m, 4);
- const deUint32 f = getBit(iseResults[endpointNdx].m, 5);
- const deUint32 A = a == 0 ? 0 : (1<<9)-1;
- const deUint32 B = rangeCase == 0 ? 0
- : rangeCase == 1 ? 0
- : rangeCase == 2 ? (b << 8) | (b << 4) | (b << 2) | (b << 1)
- : rangeCase == 3 ? (b << 8) | (b << 3) | (b << 2)
- : rangeCase == 4 ? (c << 8) | (b << 7) | (c << 3) | (b << 2) | (c << 1) | (b << 0)
- : rangeCase == 5 ? (c << 8) | (b << 7) | (c << 2) | (b << 1) | (c << 0)
- : rangeCase == 6 ? (d << 8) | (c << 7) | (b << 6) | (d << 2) | (c << 1) | (b << 0)
- : rangeCase == 7 ? (d << 8) | (c << 7) | (b << 6) | (d << 1) | (c << 0)
- : rangeCase == 8 ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 1) | (d << 0)
- : rangeCase == 9 ? (e << 8) | (d << 7) | (c << 6) | (b << 5) | (e << 0)
- : rangeCase == 10 ? (f << 8) | (e << 7) | (d << 6) | (c << 5) | (b << 4) | (f << 0)
- : (deUint32)-1;
- DE_ASSERT(B != (deUint32)-1);
- dst[endpointNdx] = (((iseResults[endpointNdx].tq*C + B) ^ A) >> 2) | (A & 0x80);
- }
- }
- else
- {
- DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
- for (int endpointNdx = 0; endpointNdx < numEndpoints; endpointNdx++)
- dst[endpointNdx] = bitReplicationScale(iseResults[endpointNdx].v, iseParams.numBits, 8);
- }
-}
-inline void bitTransferSigned (deInt32& a, deInt32& b)
-{
- b >>= 1;
- b |= a & 0x80;
- a >>= 1;
- a &= 0x3f;
- if (isBitSet(a, 5))
- a -= 0x40;
-}
-inline UVec4 clampedRGBA (const IVec4& rgba)
-{
- return UVec4(basisu_astc::clamp(rgba.x(), 0, 0xff),
- basisu_astc::clamp(rgba.y(), 0, 0xff),
- basisu_astc::clamp(rgba.z(), 0, 0xff),
- basisu_astc::clamp(rgba.w(), 0, 0xff));
-}
-inline IVec4 blueContract (int r, int g, int b, int a)
-{
- return IVec4((r+b)>>1, (g+b)>>1, b, a);
-}
-inline bool isColorEndpointModeHDR (deUint32 mode)
-{
- return mode == 2 ||
- mode == 3 ||
- mode == 7 ||
- mode == 11 ||
- mode == 14 ||
- mode == 15;
-}
-void decodeHDREndpointMode7 (UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3)
-{
- const deUint32 m10 = getBit(v1, 7) | (getBit(v2, 7) << 1);
- const deUint32 m23 = getBits(v0, 6, 7);
- const deUint32 majComp = m10 != 3 ? m10
- : m23 != 3 ? m23
- : 0;
- const deUint32 mode = m10 != 3 ? m23
- : m23 != 3 ? 4
- : 5;
- deInt32 red = (deInt32)getBits(v0, 0, 5);
- deInt32 green = (deInt32)getBits(v1, 0, 4);
- deInt32 blue = (deInt32)getBits(v2, 0, 4);
- deInt32 scale = (deInt32)getBits(v3, 0, 4);
- {
-#define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
-#define ASSIGN_X_BITS(V0,S0, V1,S1, V2,S2, V3,S3, V4,S4, V5,S5, V6,S6) do { SHOR(V0,S0,x0); SHOR(V1,S1,x1); SHOR(V2,S2,x2); SHOR(V3,S3,x3); SHOR(V4,S4,x4); SHOR(V5,S5,x5); SHOR(V6,S6,x6); } while (false)
- const deUint32 x0 = getBit(v1, 6);
- const deUint32 x1 = getBit(v1, 5);
- const deUint32 x2 = getBit(v2, 6);
- const deUint32 x3 = getBit(v2, 5);
- const deUint32 x4 = getBit(v3, 7);
- const deUint32 x5 = getBit(v3, 6);
- const deUint32 x6 = getBit(v3, 5);
- deInt32& R = red;
- deInt32& G = green;
- deInt32& B = blue;
- deInt32& S = scale;
- switch (mode)
- {
- case 0: ASSIGN_X_BITS(R,9, R,8, R,7, R,10, R,6, S,6, S,5); break;
- case 1: ASSIGN_X_BITS(R,8, G,5, R,7, B,5, R,6, R,10, R,9); break;
- case 2: ASSIGN_X_BITS(R,9, R,8, R,7, R,6, S,7, S,6, S,5); break;
- case 3: ASSIGN_X_BITS(R,8, G,5, R,7, B,5, R,6, S,6, S,5); break;
- case 4: ASSIGN_X_BITS(G,6, G,5, B,6, B,5, R,6, R,7, S,5); break;
- case 5: ASSIGN_X_BITS(G,6, G,5, B,6, B,5, R,6, S,6, S,5); break;
- default:
- DE_ASSERT(false);
- }
-#undef ASSIGN_X_BITS
-#undef SHOR
- }
- static const int shiftAmounts[] = { 1, 1, 2, 3, 4, 5 };
- DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(shiftAmounts));
- red <<= shiftAmounts[mode];
- green <<= shiftAmounts[mode];
- blue <<= shiftAmounts[mode];
- scale <<= shiftAmounts[mode];
- if (mode != 5)
- {
- green = red - green;
- blue = red - blue;
- }
- if (majComp == 1)
- std::swap(red, green);
- else if (majComp == 2)
- std::swap(red, blue);
- e0 = UVec4(basisu_astc::clamp(red - scale, 0, 0xfff),
- basisu_astc::clamp(green - scale, 0, 0xfff),
- basisu_astc::clamp(blue - scale, 0, 0xfff),
- 0x780);
- e1 = UVec4(basisu_astc::clamp(red, 0, 0xfff),
- basisu_astc::clamp(green, 0, 0xfff),
- basisu_astc::clamp(blue, 0, 0xfff),
- 0x780);
-}
-void decodeHDREndpointMode11 (UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3, deUint32 v4, deUint32 v5)
-{
- const deUint32 major = (getBit(v5, 7) << 1) | getBit(v4, 7);
- if (major == 3)
- {
- e0 = UVec4(v0<<4, v2<<4, getBits(v4,0,6)<<5, 0x780);
- e1 = UVec4(v1<<4, v3<<4, getBits(v5,0,6)<<5, 0x780);
- }
- else
- {
- const deUint32 mode = (getBit(v3, 7) << 2) | (getBit(v2, 7) << 1) | getBit(v1, 7);
- deInt32 a = (deInt32)((getBit(v1, 6) << 8) | v0);
- deInt32 c = (deInt32)(getBits(v1, 0, 5));
- deInt32 b0 = (deInt32)(getBits(v2, 0, 5));
- deInt32 b1 = (deInt32)(getBits(v3, 0, 5));
- deInt32 d0 = (deInt32)(getBits(v4, 0, 4));
- deInt32 d1 = (deInt32)(getBits(v5, 0, 4));
- {
-#define SHOR(DST_VAR, SHIFT, BIT_VAR) (DST_VAR) |= (BIT_VAR) << (SHIFT)
-#define ASSIGN_X_BITS(V0,S0, V1,S1, V2,S2, V3,S3, V4,S4, V5,S5) do { SHOR(V0,S0,x0); SHOR(V1,S1,x1); SHOR(V2,S2,x2); SHOR(V3,S3,x3); SHOR(V4,S4,x4); SHOR(V5,S5,x5); } while (false)
- const deUint32 x0 = getBit(v2, 6);
- const deUint32 x1 = getBit(v3, 6);
- const deUint32 x2 = getBit(v4, 6);
- const deUint32 x3 = getBit(v5, 6);
- const deUint32 x4 = getBit(v4, 5);
- const deUint32 x5 = getBit(v5, 5);
- switch (mode)
- {
- case 0: ASSIGN_X_BITS(b0,6, b1,6, d0,6, d1,6, d0,5, d1,5); break;
- case 1: ASSIGN_X_BITS(b0,6, b1,6, b0,7, b1,7, d0,5, d1,5); break;
- case 2: ASSIGN_X_BITS(a,9, c,6, d0,6, d1,6, d0,5, d1,5); break;
- case 3: ASSIGN_X_BITS(b0,6, b1,6, a,9, c,6, d0,5, d1,5); break;
- case 4: ASSIGN_X_BITS(b0,6, b1,6, b0,7, b1,7, a,9, a,10); break;
- case 5: ASSIGN_X_BITS(a,9, a,10, c,7, c,6, d0,5, d1,5); break;
- case 6: ASSIGN_X_BITS(b0,6, b1,6, a,11, c,6, a,9, a,10); break;
- case 7: ASSIGN_X_BITS(a,9, a,10, a,11, c,6, d0,5, d1,5); break;
- default:
- DE_ASSERT(false);
- }
-#undef ASSIGN_X_BITS
-#undef SHOR
- }
- static const int numDBits[] = { 7, 6, 7, 6, 5, 6, 5, 6 };
- DE_ASSERT(mode < DE_LENGTH_OF_ARRAY(numDBits));
- d0 = signExtend(d0, numDBits[mode]);
- d1 = signExtend(d1, numDBits[mode]);
- const int shiftAmount = (mode >> 1) ^ 3;
- a <<= shiftAmount;
- c <<= shiftAmount;
- b0 <<= shiftAmount;
- b1 <<= shiftAmount;
- d0 <<= shiftAmount;
- d1 <<= shiftAmount;
- e0 = UVec4(basisu_astc::clamp(a-c, 0, 0xfff),
- basisu_astc::clamp(a-b0-c-d0, 0, 0xfff),
- basisu_astc::clamp(a-b1-c-d1, 0, 0xfff),
- 0x780);
- e1 = UVec4(basisu_astc::clamp(a, 0, 0xfff),
- basisu_astc::clamp(a-b0, 0, 0xfff),
- basisu_astc::clamp(a-b1, 0, 0xfff),
- 0x780);
- if (major == 1)
- {
- std::swap(e0.x(), e0.y());
- std::swap(e1.x(), e1.y());
- }
- else if (major == 2)
- {
- std::swap(e0.x(), e0.z());
- std::swap(e1.x(), e1.z());
- }
- }
-}
-void decodeHDREndpointMode15(UVec4& e0, UVec4& e1, deUint32 v0, deUint32 v1, deUint32 v2, deUint32 v3, deUint32 v4, deUint32 v5, deUint32 v6In, deUint32 v7In)
-{
- decodeHDREndpointMode11(e0, e1, v0, v1, v2, v3, v4, v5);
- const deUint32 mode = (getBit(v7In, 7) << 1) | getBit(v6In, 7);
- deInt32 v6 = (deInt32)getBits(v6In, 0, 6);
- deInt32 v7 = (deInt32)getBits(v7In, 0, 6);
- if (mode == 3)
- {
- e0.w() = v6 << 5;
- e1.w() = v7 << 5;
- }
- else
- {
- v6 |= (v7 << (mode+1)) & 0x780;
- v7 &= (0x3f >> mode);
- v7 ^= 0x20 >> mode;
- v7 -= 0x20 >> mode;
- v6 <<= 4-mode;
- v7 <<= 4-mode;
- v7 += v6;
- v7 = basisu_astc::clamp(v7, 0, 0xfff);
- e0.w() = v6;
- e1.w() = v7;
- }
-}
-void decodeColorEndpoints (ColorEndpointPair* dst, const deUint32* unquantizedEndpoints, const deUint32* endpointModes, int numPartitions)
-{
- int unquantizedNdx = 0;
- for (int partitionNdx = 0; partitionNdx < numPartitions; partitionNdx++)
- {
- const deUint32 endpointMode = endpointModes[partitionNdx];
- const deUint32* v = &unquantizedEndpoints[unquantizedNdx];
- UVec4& e0 = dst[partitionNdx].e0;
- UVec4& e1 = dst[partitionNdx].e1;
- unquantizedNdx += computeNumColorEndpointValues(endpointMode);
- switch (endpointMode)
- {
- case 0:
- e0 = UVec4(v[0], v[0], v[0], 0xff);
- e1 = UVec4(v[1], v[1], v[1], 0xff);
- break;
- case 1:
- {
- const deUint32 L0 = (v[0] >> 2) | (getBits(v[1], 6, 7) << 6);
- const deUint32 L1 = basisu_astc::min(0xffu, L0 + getBits(v[1], 0, 5));
- e0 = UVec4(L0, L0, L0, 0xff);
- e1 = UVec4(L1, L1, L1, 0xff);
- break;
- }
- case 2:
- {
- const deUint32 v1Gr = v[1] >= v[0];
- const deUint32 y0 = v1Gr ? v[0]<<4 : (v[1]<<4) + 8;
- const deUint32 y1 = v1Gr ? v[1]<<4 : (v[0]<<4) - 8;
- e0 = UVec4(y0, y0, y0, 0x780);
- e1 = UVec4(y1, y1, y1, 0x780);
- break;
- }
- case 3:
- {
- const bool m = isBitSet(v[0], 7);
- const deUint32 y0 = m ? (getBits(v[1], 5, 7) << 9) | (getBits(v[0], 0, 6) << 2)
- : (getBits(v[1], 4, 7) << 8) | (getBits(v[0], 0, 6) << 1);
- const deUint32 d = m ? getBits(v[1], 0, 4) << 2
- : getBits(v[1], 0, 3) << 1;
- const deUint32 y1 = basisu_astc::min(0xfffu, y0+d);
- e0 = UVec4(y0, y0, y0, 0x780);
- e1 = UVec4(y1, y1, y1, 0x780);
- break;
- }
- case 4:
- e0 = UVec4(v[0], v[0], v[0], v[2]);
- e1 = UVec4(v[1], v[1], v[1], v[3]);
- break;
- case 5:
- {
- deInt32 v0 = (deInt32)v[0];
- deInt32 v1 = (deInt32)v[1];
- deInt32 v2 = (deInt32)v[2];
- deInt32 v3 = (deInt32)v[3];
- bitTransferSigned(v1, v0);
- bitTransferSigned(v3, v2);
- e0 = clampedRGBA(IVec4(v0, v0, v0, v2));
- e1 = clampedRGBA(IVec4(v0+v1, v0+v1, v0+v1, v2+v3));
- break;
- }
- case 6:
- e0 = UVec4((v[0]*v[3]) >> 8, (v[1]*v[3]) >> 8, (v[2]*v[3]) >> 8, 0xff);
- e1 = UVec4(v[0], v[1], v[2], 0xff);
- break;
- case 7:
- decodeHDREndpointMode7(e0, e1, v[0], v[1], v[2], v[3]);
- break;
- case 8:
- if (v[1]+v[3]+v[5] >= v[0]+v[2]+v[4])
- {
- e0 = UVec4(v[0], v[2], v[4], 0xff);
- e1 = UVec4(v[1], v[3], v[5], 0xff);
- }
- else
- {
- e0 = blueContract(v[1], v[3], v[5], 0xff).asUint();
- e1 = blueContract(v[0], v[2], v[4], 0xff).asUint();
- }
- break;
- case 9:
- {
- deInt32 v0 = (deInt32)v[0];
- deInt32 v1 = (deInt32)v[1];
- deInt32 v2 = (deInt32)v[2];
- deInt32 v3 = (deInt32)v[3];
- deInt32 v4 = (deInt32)v[4];
- deInt32 v5 = (deInt32)v[5];
- bitTransferSigned(v1, v0);
- bitTransferSigned(v3, v2);
- bitTransferSigned(v5, v4);
- if (v1+v3+v5 >= 0)
- {
- e0 = clampedRGBA(IVec4(v0, v2, v4, 0xff));
- e1 = clampedRGBA(IVec4(v0+v1, v2+v3, v4+v5, 0xff));
- }
- else
- {
- e0 = clampedRGBA(blueContract(v0+v1, v2+v3, v4+v5, 0xff));
- e1 = clampedRGBA(blueContract(v0, v2, v4, 0xff));
- }
- break;
- }
- case 10:
- e0 = UVec4((v[0]*v[3]) >> 8, (v[1]*v[3]) >> 8, (v[2]*v[3]) >> 8, v[4]);
- e1 = UVec4(v[0], v[1], v[2], v[5]);
- break;
- case 11:
- decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
- break;
- case 12:
- if (v[1]+v[3]+v[5] >= v[0]+v[2]+v[4])
- {
- e0 = UVec4(v[0], v[2], v[4], v[6]);
- e1 = UVec4(v[1], v[3], v[5], v[7]);
- }
- else
- {
- e0 = clampedRGBA(blueContract(v[1], v[3], v[5], v[7]));
- e1 = clampedRGBA(blueContract(v[0], v[2], v[4], v[6]));
- }
- break;
- case 13:
- {
- deInt32 v0 = (deInt32)v[0];
- deInt32 v1 = (deInt32)v[1];
- deInt32 v2 = (deInt32)v[2];
- deInt32 v3 = (deInt32)v[3];
- deInt32 v4 = (deInt32)v[4];
- deInt32 v5 = (deInt32)v[5];
- deInt32 v6 = (deInt32)v[6];
- deInt32 v7 = (deInt32)v[7];
- bitTransferSigned(v1, v0);
- bitTransferSigned(v3, v2);
- bitTransferSigned(v5, v4);
- bitTransferSigned(v7, v6);
- if (v1+v3+v5 >= 0)
- {
- e0 = clampedRGBA(IVec4(v0, v2, v4, v6));
- e1 = clampedRGBA(IVec4(v0+v1, v2+v3, v4+v5, v6+v7));
- }
- else
- {
- e0 = clampedRGBA(blueContract(v0+v1, v2+v3, v4+v5, v6+v7));
- e1 = clampedRGBA(blueContract(v0, v2, v4, v6));
- }
- break;
- }
- case 14:
- decodeHDREndpointMode11(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5]);
- e0.w() = v[6];
- e1.w() = v[7];
- break;
- case 15:
- decodeHDREndpointMode15(e0, e1, v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]);
- break;
- default:
- DE_ASSERT(false);
- }
- }
-}
-void computeColorEndpoints (ColorEndpointPair* dst, const Block128& blockData, const deUint32* endpointModes, int numPartitions, int numColorEndpointValues, const ISEParams& iseParams, int numBitsAvailable)
-{
- const int colorEndpointDataStart = numPartitions == 1 ? 17 : 29;
- ISEDecodedResult colorEndpointData[18];
- {
- BitAccessStream dataStream(blockData, colorEndpointDataStart, numBitsAvailable, true);
- decodeISE(&colorEndpointData[0], numColorEndpointValues, dataStream, iseParams);
- }
- {
- deUint32 unquantizedEndpoints[18];
- unquantizeColorEndpoints(&unquantizedEndpoints[0], &colorEndpointData[0], numColorEndpointValues, iseParams);
- decodeColorEndpoints(dst, &unquantizedEndpoints[0], &endpointModes[0], numPartitions);
- }
-}
-void unquantizeWeights (deUint32 dst[64], const ISEDecodedResult* weightGrid, const ASTCBlockMode& blockMode)
-{
- const int numWeights = computeNumWeights(blockMode);
- const ISEParams& iseParams = blockMode.weightISEParams;
- if (iseParams.mode == ISEMODE_TRIT || iseParams.mode == ISEMODE_QUINT)
- {
- const int rangeCase = iseParams.numBits*2 + (iseParams.mode == ISEMODE_QUINT ? 1 : 0);
- if (rangeCase == 0 || rangeCase == 1)
- {
- static const deUint32 map0[3] = { 0, 32, 63 };
- static const deUint32 map1[5] = { 0, 16, 32, 47, 63 };
- const deUint32* const map = rangeCase == 0 ? &map0[0] : &map1[0];
- for (int i = 0; i < numWeights; i++)
- {
- DE_ASSERT(weightGrid[i].v < (rangeCase == 0 ? 3u : 5u));
- dst[i] = map[weightGrid[i].v];
- }
- }
- else
- {
- DE_ASSERT(rangeCase <= 6);
- static const deUint32 Ca[5] = { 50, 28, 23, 13, 11 };
- const deUint32 C = Ca[rangeCase-2];
- for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
- {
- const deUint32 a = getBit(weightGrid[weightNdx].m, 0);
- const deUint32 b = getBit(weightGrid[weightNdx].m, 1);
- const deUint32 c = getBit(weightGrid[weightNdx].m, 2);
- const deUint32 A = a == 0 ? 0 : (1<<7)-1;
- const deUint32 B = rangeCase == 2 ? 0
- : rangeCase == 3 ? 0
- : rangeCase == 4 ? (b << 6) | (b << 2) | (b << 0)
- : rangeCase == 5 ? (b << 6) | (b << 1)
- : rangeCase == 6 ? (c << 6) | (b << 5) | (c << 1) | (b << 0)
- : (deUint32)-1;
- dst[weightNdx] = (((weightGrid[weightNdx].tq*C + B) ^ A) >> 2) | (A & 0x20);
- }
- }
- }
- else
- {
- DE_ASSERT(iseParams.mode == ISEMODE_PLAIN_BIT);
- for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
- dst[weightNdx] = bitReplicationScale(weightGrid[weightNdx].v, iseParams.numBits, 6);
- }
- for (int weightNdx = 0; weightNdx < numWeights; weightNdx++)
- dst[weightNdx] += dst[weightNdx] > 32 ? 1 : 0;
- // Initialize nonexistent weights to poison values
- for (int weightNdx = numWeights; weightNdx < 64; weightNdx++)
- dst[weightNdx] = ~0u;
-}
-void interpolateWeights (TexelWeightPair* dst, const deUint32 (&unquantizedWeights) [64], int blockWidth, int blockHeight, const ASTCBlockMode& blockMode)
-{
- const int numWeightsPerTexel = blockMode.isDualPlane ? 2 : 1;
- const deUint32 scaleX = (1024 + blockWidth/2) / (blockWidth-1);
- const deUint32 scaleY = (1024 + blockHeight/2) / (blockHeight-1);
- DE_ASSERT(blockMode.weightGridWidth*blockMode.weightGridHeight*numWeightsPerTexel <= (int)DE_LENGTH_OF_ARRAY(unquantizedWeights));
- for (int texelY = 0; texelY < blockHeight; texelY++)
- {
- for (int texelX = 0; texelX < blockWidth; texelX++)
- {
- const deUint32 gX = (scaleX*texelX*(blockMode.weightGridWidth-1) + 32) >> 6;
- const deUint32 gY = (scaleY*texelY*(blockMode.weightGridHeight-1) + 32) >> 6;
- const deUint32 jX = gX >> 4;
- const deUint32 jY = gY >> 4;
- const deUint32 fX = gX & 0xf;
- const deUint32 fY = gY & 0xf;
- const deUint32 w11 = (fX*fY + 8) >> 4;
- const deUint32 w10 = fY - w11;
- const deUint32 w01 = fX - w11;
- const deUint32 w00 = 16 - fX - fY + w11;
- const deUint32 i00 = jY*blockMode.weightGridWidth + jX;
- const deUint32 i01 = i00 + 1;
- const deUint32 i10 = i00 + blockMode.weightGridWidth;
- const deUint32 i11 = i00 + blockMode.weightGridWidth + 1;
- // These addresses can be out of bounds, but respective weights will be 0 then.
- DE_ASSERT(deInBounds32(i00, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w00 == 0);
- DE_ASSERT(deInBounds32(i01, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w01 == 0);
- DE_ASSERT(deInBounds32(i10, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w10 == 0);
- DE_ASSERT(deInBounds32(i11, 0, blockMode.weightGridWidth*blockMode.weightGridHeight) || w11 == 0);
- for (int texelWeightNdx = 0; texelWeightNdx < numWeightsPerTexel; texelWeightNdx++)
- {
- // & 0x3f clamps address to bounds of unquantizedWeights
- const deUint32 p00 = unquantizedWeights[(i00 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
- const deUint32 p01 = unquantizedWeights[(i01 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
- const deUint32 p10 = unquantizedWeights[(i10 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
- const deUint32 p11 = unquantizedWeights[(i11 * numWeightsPerTexel + texelWeightNdx) & 0x3f];
- dst[texelY*blockWidth + texelX].w[texelWeightNdx] = (p00*w00 + p01*w01 + p10*w10 + p11*w11 + 8) >> 4;
- }
- }
- }
-}
-void computeTexelWeights (TexelWeightPair* dst, const Block128& blockData, int blockWidth, int blockHeight, const ASTCBlockMode& blockMode)
-{
- ISEDecodedResult weightGrid[64];
- {
- BitAccessStream dataStream(blockData, 127, computeNumRequiredBits(blockMode.weightISEParams, computeNumWeights(blockMode)), false);
- decodeISE(&weightGrid[0], computeNumWeights(blockMode), dataStream, blockMode.weightISEParams);
- }
- {
- deUint32 unquantizedWeights[64];
- unquantizeWeights(&unquantizedWeights[0], &weightGrid[0], blockMode);
- interpolateWeights(dst, unquantizedWeights, blockWidth, blockHeight, blockMode);
- }
-}
-inline deUint32 hash52 (deUint32 v)
-{
- deUint32 p = v;
- p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4;
- p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3;
- p ^= p << 6; p ^= p >> 17;
- return p;
-}
-int computeTexelPartition (deUint32 seedIn, deUint32 xIn, deUint32 yIn, deUint32 zIn, int numPartitions, bool smallBlock)
-{
- DE_ASSERT(zIn == 0);
- const deUint32 x = smallBlock ? xIn << 1 : xIn;
- const deUint32 y = smallBlock ? yIn << 1 : yIn;
- const deUint32 z = smallBlock ? zIn << 1 : zIn;
- const deUint32 seed = seedIn + 1024*(numPartitions-1);
- const deUint32 rnum = hash52(seed);
- deUint8 seed1 = (deUint8)( rnum & 0xf);
- deUint8 seed2 = (deUint8)((rnum >> 4) & 0xf);
- deUint8 seed3 = (deUint8)((rnum >> 8) & 0xf);
- deUint8 seed4 = (deUint8)((rnum >> 12) & 0xf);
- deUint8 seed5 = (deUint8)((rnum >> 16) & 0xf);
- deUint8 seed6 = (deUint8)((rnum >> 20) & 0xf);
- deUint8 seed7 = (deUint8)((rnum >> 24) & 0xf);
- deUint8 seed8 = (deUint8)((rnum >> 28) & 0xf);
- deUint8 seed9 = (deUint8)((rnum >> 18) & 0xf);
- deUint8 seed10 = (deUint8)((rnum >> 22) & 0xf);
- deUint8 seed11 = (deUint8)((rnum >> 26) & 0xf);
- deUint8 seed12 = (deUint8)(((rnum >> 30) | (rnum << 2)) & 0xf);
- seed1 = (deUint8)(seed1 * seed1 );
- seed2 = (deUint8)(seed2 * seed2 );
- seed3 = (deUint8)(seed3 * seed3 );
- seed4 = (deUint8)(seed4 * seed4 );
- seed5 = (deUint8)(seed5 * seed5 );
- seed6 = (deUint8)(seed6 * seed6 );
- seed7 = (deUint8)(seed7 * seed7 );
- seed8 = (deUint8)(seed8 * seed8 );
- seed9 = (deUint8)(seed9 * seed9 );
- seed10 = (deUint8)(seed10 * seed10);
- seed11 = (deUint8)(seed11 * seed11);
- seed12 = (deUint8)(seed12 * seed12);
- const int shA = (seed & 2) != 0 ? 4 : 5;
- const int shB = numPartitions == 3 ? 6 : 5;
- const int sh1 = (seed & 1) != 0 ? shA : shB;
- const int sh2 = (seed & 1) != 0 ? shB : shA;
- const int sh3 = (seed & 0x10) != 0 ? sh1 : sh2;
- seed1 = (deUint8)(seed1 >> sh1);
- seed2 = (deUint8)(seed2 >> sh2);
- seed3 = (deUint8)(seed3 >> sh1);
- seed4 = (deUint8)(seed4 >> sh2);
- seed5 = (deUint8)(seed5 >> sh1);
- seed6 = (deUint8)(seed6 >> sh2);
- seed7 = (deUint8)(seed7 >> sh1);
- seed8 = (deUint8)(seed8 >> sh2);
- seed9 = (deUint8)(seed9 >> sh3);
- seed10 = (deUint8)(seed10 >> sh3);
- seed11 = (deUint8)(seed11 >> sh3);
- seed12 = (deUint8)(seed12 >> sh3);
- const int a = 0x3f & (seed1*x + seed2*y + seed11*z + (rnum >> 14));
- const int b = 0x3f & (seed3*x + seed4*y + seed12*z + (rnum >> 10));
- const int c = numPartitions >= 3 ? 0x3f & (seed5*x + seed6*y + seed9*z + (rnum >> 6)) : 0;
- const int d = numPartitions >= 4 ? 0x3f & (seed7*x + seed8*y + seed10*z + (rnum >> 2)) : 0;
- return a >= b && a >= c && a >= d ? 0
- : b >= c && b >= d ? 1
- : c >= d ? 2
- : 3;
-}
-DecompressResult setTexelColors (void* dst, ColorEndpointPair* colorEndpoints, TexelWeightPair* texelWeights, int ccs, deUint32 partitionIndexSeed,
- int numPartitions, int blockWidth, int blockHeight, bool isSRGB, bool isLDRMode, const deUint32* colorEndpointModes)
-{
- const bool smallBlock = blockWidth*blockHeight < 31;
- DecompressResult result = DECOMPRESS_RESULT_VALID_BLOCK;
- bool isHDREndpoint[4];
- for (int i = 0; i < numPartitions; i++)
- {
- isHDREndpoint[i] = isColorEndpointModeHDR(colorEndpointModes[i]);
-
- // rg - REMOVING HDR SUPPORT FOR NOW
- if (isHDREndpoint[i])
- return DECOMPRESS_RESULT_ERROR;
- }
-
- for (int texelY = 0; texelY < blockHeight; texelY++)
- for (int texelX = 0; texelX < blockWidth; texelX++)
- {
- const int texelNdx = texelY*blockWidth + texelX;
- const int colorEndpointNdx = numPartitions == 1 ? 0 : computeTexelPartition(partitionIndexSeed, texelX, texelY, 0, numPartitions, smallBlock);
- DE_ASSERT(colorEndpointNdx < numPartitions);
- const UVec4& e0 = colorEndpoints[colorEndpointNdx].e0;
- const UVec4& e1 = colorEndpoints[colorEndpointNdx].e1;
- const TexelWeightPair& weight = texelWeights[texelNdx];
- if (isLDRMode && isHDREndpoint[colorEndpointNdx])
- {
- if (isSRGB)
- {
- ((deUint8*)dst)[texelNdx*4 + 0] = 0xff;
- ((deUint8*)dst)[texelNdx*4 + 1] = 0;
- ((deUint8*)dst)[texelNdx*4 + 2] = 0xff;
- ((deUint8*)dst)[texelNdx*4 + 3] = 0xff;
- }
- else
- {
- ((float*)dst)[texelNdx*4 + 0] = 1.0f;
- ((float*)dst)[texelNdx*4 + 1] = 0;
- ((float*)dst)[texelNdx*4 + 2] = 1.0f;
- ((float*)dst)[texelNdx*4 + 3] = 1.0f;
- }
- result = DECOMPRESS_RESULT_ERROR;
- }
- else
- {
- for (int channelNdx = 0; channelNdx < 4; channelNdx++)
- {
- if (!isHDREndpoint[colorEndpointNdx] || (channelNdx == 3 && colorEndpointModes[colorEndpointNdx] == 14)) // \note Alpha for mode 14 is treated the same as LDR.
- {
- const deUint32 c0 = (e0[channelNdx] << 8) | (isSRGB ? 0x80 : e0[channelNdx]);
- const deUint32 c1 = (e1[channelNdx] << 8) | (isSRGB ? 0x80 : e1[channelNdx]);
- const deUint32 w = weight.w[ccs == channelNdx ? 1 : 0];
- const deUint32 c = (c0*(64-w) + c1*w + 32) / 64;
- if (isSRGB)
- ((deUint8*)dst)[texelNdx*4 + channelNdx] = (deUint8)((c & 0xff00) >> 8);
- else
- ((float*)dst)[texelNdx*4 + channelNdx] = c == 65535 ? 1.0f : (float)c / 65536.0f;
- }
- else
- {
- //DE_STATIC_ASSERT((basisu_astc::meta::TypesSame<deFloat16, deUint16>::Value));
- // rg - REMOVING HDR SUPPORT FOR NOW
-#if 0
- const deUint32 c0 = e0[channelNdx] << 4;
- const deUint32 c1 = e1[channelNdx] << 4;
- const deUint32 w = weight.w[ccs == channelNdx ? 1 : 0];
- const deUint32 c = (c0*(64-w) + c1*w + 32) / 64;
- const deUint32 e = getBits(c, 11, 15);
- const deUint32 m = getBits(c, 0, 10);
- const deUint32 mt = m < 512 ? 3*m
- : m >= 1536 ? 5*m - 2048
- : 4*m - 512;
- const deFloat16 cf = (deFloat16)((e << 10) + (mt >> 3));
- ((float*)dst)[texelNdx*4 + channelNdx] = deFloat16To32(isFloat16InfOrNan(cf) ? 0x7bff : cf);
-#endif
- }
- }
- }
- }
- return result;
-}
-DecompressResult decompressBlock (void* dst, const Block128& blockData, int blockWidth, int blockHeight, bool isSRGB, bool isLDR)
-{
- DE_ASSERT(isLDR || !isSRGB);
- // Decode block mode.
- const ASTCBlockMode blockMode = getASTCBlockMode(blockData.getBits(0, 10));
- // Check for block mode errors.
- if (blockMode.isError)
- {
- setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
- return DECOMPRESS_RESULT_ERROR;
- }
- // Separate path for void-extent.
- if (blockMode.isVoidExtent)
- return decodeVoidExtentBlock(dst, blockData, blockWidth, blockHeight, isSRGB, isLDR);
- // Compute weight grid values.
- const int numWeights = computeNumWeights(blockMode);
- const int numWeightDataBits = computeNumRequiredBits(blockMode.weightISEParams, numWeights);
- const int numPartitions = (int)blockData.getBits(11, 12) + 1;
- // Check for errors in weight grid, partition and dual-plane parameters.
- if (numWeights > 64 ||
- numWeightDataBits > 96 ||
- numWeightDataBits < 24 ||
- blockMode.weightGridWidth > blockWidth ||
- blockMode.weightGridHeight > blockHeight ||
- (numPartitions == 4 && blockMode.isDualPlane))
- {
- setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
- return DECOMPRESS_RESULT_ERROR;
- }
- // Compute number of bits available for color endpoint data.
- const bool isSingleUniqueCem = numPartitions == 1 || blockData.getBits(23, 24) == 0;
- const int numConfigDataBits = (numPartitions == 1 ? 17 : isSingleUniqueCem ? 29 : 25 + 3*numPartitions) +
- (blockMode.isDualPlane ? 2 : 0);
- const int numBitsForColorEndpoints = 128 - numWeightDataBits - numConfigDataBits;
- const int extraCemBitsStart = 127 - numWeightDataBits - (isSingleUniqueCem ? -1
- : numPartitions == 4 ? 7
- : numPartitions == 3 ? 4
- : numPartitions == 2 ? 1
- : 0);
- // Decode color endpoint modes.
- deUint32 colorEndpointModes[4];
- decodeColorEndpointModes(&colorEndpointModes[0], blockData, numPartitions, extraCemBitsStart);
- const int numColorEndpointValues = computeNumColorEndpointValues(colorEndpointModes, numPartitions);
- // Check for errors in color endpoint value count.
- if (numColorEndpointValues > 18 || numBitsForColorEndpoints < (int)deDivRoundUp32(13*numColorEndpointValues, 5))
- {
- setASTCErrorColorBlock(dst, blockWidth, blockHeight, isSRGB);
- return DECOMPRESS_RESULT_ERROR;
- }
- // Compute color endpoints.
- ColorEndpointPair colorEndpoints[4];
- computeColorEndpoints(&colorEndpoints[0], blockData, &colorEndpointModes[0], numPartitions, numColorEndpointValues,
- computeMaximumRangeISEParams(numBitsForColorEndpoints, numColorEndpointValues), numBitsForColorEndpoints);
- // Compute texel weights.
- TexelWeightPair texelWeights[MAX_BLOCK_WIDTH*MAX_BLOCK_HEIGHT];
- computeTexelWeights(&texelWeights[0], blockData, blockWidth, blockHeight, blockMode);
- // Set texel colors.
- const int ccs = blockMode.isDualPlane ? (int)blockData.getBits(extraCemBitsStart-2, extraCemBitsStart-1) : -1;
- const deUint32 partitionIndexSeed = numPartitions > 1 ? blockData.getBits(13, 22) : (deUint32)-1;
- return setTexelColors(dst, &colorEndpoints[0], &texelWeights[0], ccs, partitionIndexSeed, numPartitions, blockWidth, blockHeight, isSRGB, isLDR, &colorEndpointModes[0]);
-}
-
-} // anonymous
-
-bool decompress(uint8_t *pDst, const uint8_t * data, bool isSRGB, int blockWidth, int blockHeight)
-{
- // rg - We only support LDR here, although adding back in HDR would be easy.
- const bool isLDR = true;
- DE_ASSERT(isLDR || !isSRGB);
-
- float linear[MAX_BLOCK_WIDTH * MAX_BLOCK_HEIGHT * 4];
-
- const Block128 blockData(data);
- if (decompressBlock(isSRGB ? (void*)pDst : (void*)& linear[0],
- blockData, blockWidth, blockHeight, isSRGB, isLDR) != DECOMPRESS_RESULT_VALID_BLOCK)
- return false;
-
- if (!isSRGB)
- {
- int pix = 0;
- for (int i = 0; i < blockHeight; i++)
- {
- for (int j = 0; j < blockWidth; j++, pix++)
- {
- pDst[4 * pix + 0] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 0] * 65536.0f + .5f), 0, 65535) >> 8);
- pDst[4 * pix + 1] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 1] * 65536.0f + .5f), 0, 65535) >> 8);
- pDst[4 * pix + 2] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 2] * 65536.0f + .5f), 0, 65535) >> 8);
- pDst[4 * pix + 3] = (uint8_t)(basisu_astc::clamp<int>((int)(linear[pix * 4 + 3] * 65536.0f + .5f), 0, 65535) >> 8);
- }
- }
- }
-
- return true;
-}
-
-} // astc
-} // basisu_astc
-
-#if defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
diff --git a/thirdparty/basis_universal/encoder/basisu_astc_decomp.h b/thirdparty/basis_universal/encoder/basisu_astc_decomp.h
deleted file mode 100644
index 9ec2e46076..0000000000
--- a/thirdparty/basis_universal/encoder/basisu_astc_decomp.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef _TCUASTCUTIL_HPP
-#define _TCUASTCUTIL_HPP
-/*-------------------------------------------------------------------------
- * drawElements Quality Program Tester Core
- * ----------------------------------------
- *
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- *//*!
- * \file
- * \brief ASTC Utilities.
- *//*--------------------------------------------------------------------*/
-
-#include "../transcoder/basisu.h" // to pick up the iterator debug level madness
-#include <vector>
-#include <stdint.h>
-
-namespace basisu_astc
-{
-namespace astc
-{
-
-// Unpacks a single ASTC block to pDst
-// If isSRGB is true, the spec requires the decoder to scale the LDR 8-bit endpoints to 16-bit before interpolation slightly differently,
-// which will lead to different outputs. So be sure to set it correctly (ideally it should match whatever the encoder did).
-bool decompress(uint8_t* pDst, const uint8_t* data, bool isSRGB, int blockWidth, int blockHeight);
-
-} // astc
-} // basisu
-
-#endif
diff --git a/thirdparty/basis_universal/encoder/basisu_backend.cpp b/thirdparty/basis_universal/encoder/basisu_backend.cpp
index 19911fcbb4..abb61750a6 100644
--- a/thirdparty/basis_universal/encoder/basisu_backend.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_backend.cpp
@@ -49,22 +49,17 @@ namespace basisu
m_output.clear();
}
- void basisu_backend::init(basisu_frontend* pFront_end, basisu_backend_params& params, const basisu_backend_slice_desc_vec& slice_descs, const basist::etc1_global_selector_codebook* pGlobal_sel_codebook)
+ void basisu_backend::init(basisu_frontend* pFront_end, basisu_backend_params& params, const basisu_backend_slice_desc_vec& slice_descs)
{
m_pFront_end = pFront_end;
m_params = params;
m_slices = slice_descs;
- m_pGlobal_sel_codebook = pGlobal_sel_codebook;
-
- debug_printf("basisu_backend::Init: Slices: %u, ETC1S: %u, EndpointRDOQualityThresh: %f, SelectorRDOQualityThresh: %f, UseGlobalSelCodebook: %u, GlobalSelCodebookPalBits: %u, GlobalSelCodebookModBits: %u, Use hybrid selector codebooks: %u\n",
+
+ debug_printf("basisu_backend::Init: Slices: %u, ETC1S: %u, EndpointRDOQualityThresh: %f, SelectorRDOQualityThresh: %f\n",
m_slices.size(),
params.m_etc1s,
params.m_endpoint_rdo_quality_thresh,
- params.m_selector_rdo_quality_thresh,
- params.m_use_global_sel_codebook,
- params.m_global_sel_codebook_pal_bits,
- params.m_global_sel_codebook_mod_bits,
- params.m_use_hybrid_sel_codebooks);
+ params.m_selector_rdo_quality_thresh);
debug_printf("Frontend endpoints: %u selectors: %u\n", m_pFront_end->get_total_endpoint_clusters(), m_pFront_end->get_total_selector_clusters());
@@ -106,63 +101,17 @@ namespace basisu
m_selector_palette.resize(r.get_total_selector_clusters());
- if (m_params.m_use_global_sel_codebook)
+ for (uint32_t i = 0; i < r.get_total_selector_clusters(); i++)
{
- m_global_selector_palette_desc.resize(r.get_total_selector_clusters());
-
- for (int i = 0; i < static_cast<int>(r.get_total_selector_clusters()); i++)
- {
- basist::etc1_selector_palette_entry& selector_pal_entry = m_selector_palette[i];
-
- etc1_global_selector_cb_entry_desc& pal_entry_desc = m_global_selector_palette_desc[i];
- pal_entry_desc.m_pal_index = r.get_selector_cluster_global_selector_entry_ids()[i].m_palette_index;
- pal_entry_desc.m_mod_index = r.get_selector_cluster_global_selector_entry_ids()[i].m_modifier.get_index();
-
- pal_entry_desc.m_was_used = true;
- if (m_params.m_use_hybrid_sel_codebooks)
- pal_entry_desc.m_was_used = r.get_selector_cluster_uses_global_cb_vec()[i];
-
- if (pal_entry_desc.m_was_used)
- {
- const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
- (void)selector_bits;
-
- basist::etc1_selector_palette_entry global_pal_entry(m_pGlobal_sel_codebook->get_entry(r.get_selector_cluster_global_selector_entry_ids()[i]));
+ etc1_selector_palette_entry& s = m_selector_palette[i];
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- selector_pal_entry(x, y) = global_pal_entry(x, y);
+ const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
- assert(selector_bits.get_selector(x, y) == global_pal_entry(x, y));
- }
- }
- }
- else
- {
- const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
-
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- selector_pal_entry[y * 4 + x] = static_cast<uint8_t>(selector_bits.get_selector(x, y));
- }
- }
- }
- else
- {
- for (uint32_t i = 0; i < r.get_total_selector_clusters(); i++)
+ for (uint32_t y = 0; y < 4; y++)
{
- basist::etc1_selector_palette_entry& s = m_selector_palette[i];
-
- const etc_block& selector_bits = r.get_selector_cluster_selector_bits(i);
-
- for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
{
- for (uint32_t x = 0; x < 4; x++)
- {
- s[y * 4 + x] = static_cast<uint8_t>(selector_bits.get_selector(x, y));
- }
+ s[y * 4 + x] = static_cast<uint8_t>(selector_bits.get_selector(x, y));
}
}
}
@@ -388,6 +337,8 @@ namespace basisu
if (!is_video)
return;
+ debug_printf("basisu_backend::check_for_valid_cr_blocks\n");
+
uint32_t total_crs = 0;
uint32_t total_invalid_crs = 0;
@@ -454,6 +405,11 @@ namespace basisu
void basisu_backend::create_encoder_blocks()
{
+ debug_printf("basisu_backend::create_encoder_blocks\n");
+
+ interval_timer tm;
+ tm.start();
+
basisu_frontend& r = *m_pFront_end;
const bool is_video = r.get_params().m_tex_type == basist::cBASISTexTypeVideoFrames;
@@ -565,6 +521,7 @@ namespace basisu
{
if ((is_video) && (endpoint_pred == basist::CR_ENDPOINT_PRED_INDEX))
continue;
+
int pred_block_x = block_x + g_endpoint_preds[endpoint_pred].m_dx;
if ((pred_block_x < 0) || (pred_block_x >= (int)num_blocks_x))
continue;
@@ -586,11 +543,23 @@ namespace basisu
unpack_etc1(trial_etc_block, trial_colors);
uint64_t trial_err = 0;
- for (uint32_t p = 0; p < 16; p++)
+ if (r.get_params().m_perceptual)
{
- trial_err += color_distance(r.get_params().m_perceptual, src_pixels.get_ptr()[p], trial_colors[p], false);
- if (trial_err > thresh_err)
- break;
+ for (uint32_t p = 0; p < 16; p++)
+ {
+ trial_err += color_distance(true, src_pixels.get_ptr()[p], trial_colors[p], false);
+ if (trial_err > thresh_err)
+ break;
+ }
+ }
+ else
+ {
+ for (uint32_t p = 0; p < 16; p++)
+ {
+ trial_err += color_distance(false, src_pixels.get_ptr()[p], trial_colors[p], false);
+ if (trial_err > thresh_err)
+ break;
+ }
}
if (trial_err <= thresh_err)
@@ -643,6 +612,8 @@ namespace basisu
sort_selector_codebook();
check_for_valid_cr_blocks();
+
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
}
void basisu_backend::compute_slice_crcs()
@@ -670,7 +641,9 @@ namespace basisu
etc_block& output_block = *(etc_block*)gi.get_block_ptr(block_x, block_y);
output_block.set_diff_bit(true);
- output_block.set_flip_bit(true);
+ // Setting the flip bit to false to be compatible with the Khronos KDFS.
+ //output_block.set_flip_bit(true);
+ output_block.set_flip_bit(false);
const uint32_t endpoint_index = m.m_endpoint_index;
@@ -679,7 +652,7 @@ namespace basisu
const uint32_t selector_idx = m.m_selector_index;
- const basist::etc1_selector_palette_entry& selectors = m_selector_palette[selector_idx];
+ const etc1_selector_palette_entry& selectors = m_selector_palette[selector_idx];
for (uint32_t sy = 0; sy < 4; sy++)
for (uint32_t sx = 0; sx < 4; sx++)
output_block.set_selector(sx, sy, selectors(sx, sy));
@@ -707,6 +680,9 @@ namespace basisu
} // slice_index
}
+ //uint32_t g_color_delta_hist[255 * 3 + 1];
+ //uint32_t g_color_delta_bad_hist[255 * 3 + 1];
+
// TODO: Split this into multiple methods.
bool basisu_backend::encode_image()
{
@@ -737,6 +713,12 @@ namespace basisu
uint_vec block_endpoint_indices, block_selector_indices;
+ interval_timer tm;
+ tm.start();
+
+ const int COLOR_DELTA_THRESH = 8;
+ const int SEL_DIFF_THRESHOLD = 11;
+
for (uint32_t slice_index = 0; slice_index < m_slices.size(); slice_index++)
{
//const int prev_frame_slice_index = is_video ? find_video_frame(slice_index, -1) : -1;
@@ -782,7 +764,7 @@ namespace basisu
} // block_x
} // block_y
-
+
for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++)
{
for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++)
@@ -857,68 +839,170 @@ namespace basisu
etc_block etc_blk(r.get_output_block(block_index));
const uint64_t cur_err = etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+ const uint32_t cur_inten5 = etc_blk.get_inten_table(0);
+ const etc1_endpoint_palette_entry& cur_endpoints = m_endpoint_palette[m.m_endpoint_index];
+
if (cur_err)
{
const float endpoint_remap_thresh = maximum(1.0f, m_params.m_endpoint_rdo_quality_thresh);
const uint64_t thresh_err = (uint64_t)(cur_err * endpoint_remap_thresh);
- uint64_t best_trial_err = UINT64_MAX;
- int best_trial_idx = 0;
-
- etc_block trial_etc_blk(etc_blk);
+ //const int MAX_ENDPOINT_SEARCH_DIST = (m_params.m_compression_level >= 2) ? 64 : 32;
+ const int MAX_ENDPOINT_SEARCH_DIST = (m_params.m_compression_level >= 2) ? 64 : 16;
- const int MAX_ENDPOINT_SEARCH_DIST = 32;
- const int search_dist = minimum<int>(iabs(endpoint_delta) - 1, MAX_ENDPOINT_SEARCH_DIST);
- for (int d = -search_dist; d < search_dist; d++)
+ if (!g_cpu_supports_sse41)
{
- int trial_idx = prev_endpoint_index + d;
- if (trial_idx < 0)
- trial_idx += (int)r.get_total_endpoint_clusters();
- else if (trial_idx >= (int)r.get_total_endpoint_clusters())
- trial_idx -= (int)r.get_total_endpoint_clusters();
+ const uint64_t initial_best_trial_err = UINT64_MAX;
+ uint64_t best_trial_err = initial_best_trial_err;
+ int best_trial_idx = 0;
+
+ etc_block trial_etc_blk(etc_blk);
+
+ const int search_dist = minimum<int>(iabs(endpoint_delta) - 1, MAX_ENDPOINT_SEARCH_DIST);
+ for (int d = -search_dist; d < search_dist; d++)
+ {
+ int trial_idx = prev_endpoint_index + d;
+ if (trial_idx < 0)
+ trial_idx += (int)r.get_total_endpoint_clusters();
+ else if (trial_idx >= (int)r.get_total_endpoint_clusters())
+ trial_idx -= (int)r.get_total_endpoint_clusters();
+
+ if (trial_idx == new_endpoint_index)
+ continue;
+
+ // Skip it if this new endpoint palette entry is actually never used.
+ if (!m_new_endpoint_was_used[trial_idx])
+ continue;
+
+ const etc1_endpoint_palette_entry& p = m_endpoint_palette[m_endpoint_remap_table_new_to_old[trial_idx]];
+
+ if (m_params.m_compression_level <= 1)
+ {
+ if (p.m_inten5 > cur_inten5)
+ continue;
+
+ int delta_r = iabs(cur_endpoints.m_color5.r - p.m_color5.r);
+ int delta_g = iabs(cur_endpoints.m_color5.g - p.m_color5.g);
+ int delta_b = iabs(cur_endpoints.m_color5.b - p.m_color5.b);
+ int color_delta = delta_r + delta_g + delta_b;
+
+ if (color_delta > COLOR_DELTA_THRESH)
+ continue;
+ }
- if (trial_idx == new_endpoint_index)
- continue;
+ trial_etc_blk.set_block_color5_etc1s(p.m_color5);
+ trial_etc_blk.set_inten_tables_etc1s(p.m_inten5);
- // Skip it if this new endpoint palette entry is actually never used.
- if (!m_new_endpoint_was_used[trial_idx])
- continue;
+ uint64_t trial_err = trial_etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+
+ if ((trial_err < best_trial_err) && (trial_err <= thresh_err))
+ {
+ best_trial_err = trial_err;
+ best_trial_idx = trial_idx;
+ }
+ }
+
+ if (best_trial_err != initial_best_trial_err)
+ {
+ m.m_endpoint_index = m_endpoint_remap_table_new_to_old[best_trial_idx];
- const etc1_endpoint_palette_entry& p = m_endpoint_palette[m_endpoint_remap_table_new_to_old[trial_idx]];
- trial_etc_blk.set_block_color5_etc1s(p.m_color5);
- trial_etc_blk.set_inten_tables_etc1s(p.m_inten5);
+ new_endpoint_index = best_trial_idx;
- uint64_t trial_err = trial_etc_blk.evaluate_etc1_error(src_pixels.get_ptr(), r.get_params().m_perceptual);
+ endpoint_delta = new_endpoint_index - prev_endpoint_index;
- if (trial_err <= thresh_err)
+ total_endpoint_indices_remapped++;
+ }
+ }
+ else
+ {
+#if BASISU_SUPPORT_SSE
+ uint8_t block_selectors[16];
+ for (uint32_t i = 0; i < 16; i++)
+ block_selectors[i] = (uint8_t)etc_blk.get_selector(i & 3, i >> 2);
+
+ const int64_t initial_best_trial_err = INT64_MAX;
+ int64_t best_trial_err = initial_best_trial_err;
+ int best_trial_idx = 0;
+
+ const int search_dist = minimum<int>(iabs(endpoint_delta) - 1, MAX_ENDPOINT_SEARCH_DIST);
+ for (int d = -search_dist; d < search_dist; d++)
{
- if (trial_err < best_trial_err)
+ int trial_idx = prev_endpoint_index + d;
+ if (trial_idx < 0)
+ trial_idx += (int)r.get_total_endpoint_clusters();
+ else if (trial_idx >= (int)r.get_total_endpoint_clusters())
+ trial_idx -= (int)r.get_total_endpoint_clusters();
+
+ if (trial_idx == new_endpoint_index)
+ continue;
+
+ // Skip it if this new endpoint palette entry is actually never used.
+ if (!m_new_endpoint_was_used[trial_idx])
+ continue;
+
+ const etc1_endpoint_palette_entry& p = m_endpoint_palette[m_endpoint_remap_table_new_to_old[trial_idx]];
+
+ if (m_params.m_compression_level <= 1)
+ {
+ if (p.m_inten5 > cur_inten5)
+ continue;
+
+ int delta_r = iabs(cur_endpoints.m_color5.r - p.m_color5.r);
+ int delta_g = iabs(cur_endpoints.m_color5.g - p.m_color5.g);
+ int delta_b = iabs(cur_endpoints.m_color5.b - p.m_color5.b);
+ int color_delta = delta_r + delta_g + delta_b;
+
+ if (color_delta > COLOR_DELTA_THRESH)
+ continue;
+ }
+
+ color_rgba block_colors[4];
+ etc_block::get_block_colors_etc1s(block_colors, p.m_color5, p.m_inten5);
+
+ int64_t trial_err;
+ if (r.get_params().m_perceptual)
+ {
+ perceptual_distance_rgb_4_N_sse41(&trial_err, block_selectors, block_colors, src_pixels.get_ptr(), 16, best_trial_err);
+ }
+ else
+ {
+ linear_distance_rgb_4_N_sse41(&trial_err, block_selectors, block_colors, src_pixels.get_ptr(), 16, best_trial_err);
+ }
+
+ //if (trial_err > thresh_err)
+ // g_color_delta_bad_hist[color_delta]++;
+
+ if ((trial_err < best_trial_err) && (trial_err <= (int64_t)thresh_err))
{
best_trial_err = trial_err;
best_trial_idx = trial_idx;
}
}
- }
- if (best_trial_err != UINT64_MAX)
- {
- m.m_endpoint_index = m_endpoint_remap_table_new_to_old[best_trial_idx];
+ if (best_trial_err != initial_best_trial_err)
+ {
+ m.m_endpoint_index = m_endpoint_remap_table_new_to_old[best_trial_idx];
- new_endpoint_index = best_trial_idx;
+ new_endpoint_index = best_trial_idx;
- endpoint_delta = new_endpoint_index - prev_endpoint_index;
+ endpoint_delta = new_endpoint_index - prev_endpoint_index;
- total_endpoint_indices_remapped++;
- }
- }
- }
+ total_endpoint_indices_remapped++;
+ }
+#endif // BASISU_SUPPORT_SSE
+ } // if (!g_cpu_supports_sse41)
+
+ } // if (cur_err)
+
+ } // if ((m_params.m_endpoint_rdo_quality_thresh > 1.0f) && (iabs(endpoint_delta) > 1) && (!block_endpoints_are_referenced(block_x, block_y)))
if (endpoint_delta < 0)
endpoint_delta += (int)r.get_total_endpoint_clusters();
delta_endpoint_histogram.inc(endpoint_delta);
- }
+
+ } // if (m.m_endpoint_predictor == basist::NO_ENDPOINT_PRED_INDEX)
block_endpoint_indices.push_back(m_endpoint_remap_table_new_to_old[new_endpoint_index]);
@@ -927,10 +1011,13 @@ namespace basisu
if ((!is_video) || (m.m_endpoint_predictor != basist::CR_ENDPOINT_PRED_INDEX))
{
int new_selector_index = m_selector_remap_table_old_to_new[m.m_selector_index];
+
+ const float selector_remap_thresh = maximum(1.0f, m_params.m_selector_rdo_quality_thresh); //2.5f;
int selector_history_buf_index = -1;
- if (m.m_is_cr_target)
+ // At low comp levels this hurts compression a tiny amount, but is significantly faster so it's a good tradeoff.
+ if ((m.m_is_cr_target) || (m_params.m_compression_level <= 1))
{
for (uint32_t j = 0; j < selector_history_buf.size(); j++)
{
@@ -944,89 +1031,99 @@ namespace basisu
}
}
}
- else
+
+ // If the block is a CR target we can't override its selectors.
+ if ((!m.m_is_cr_target) && (selector_history_buf_index == -1))
{
const pixel_block& src_pixels = r.get_source_pixel_block(block_index);
- const etc_block& etc_blk = r.get_output_block(block_index);
+ etc_block etc_blk = r.get_output_block(block_index);
+
+ // This is new code - the initial release just used the endpoints from the frontend, which isn't correct/accurate.
+ const etc1_endpoint_palette_entry& q = m_endpoint_palette[m_endpoint_remap_table_new_to_old[new_endpoint_index]];
+ etc_blk.set_block_color5_etc1s(q.m_color5);
+ etc_blk.set_inten_tables_etc1s(q.m_inten5);
+
+ color_rgba block_colors[4];
+ etc_blk.get_block_colors(block_colors, 0);
- color_rgba etc_blk_unpacked[16];
- unpack_etc1(etc_blk, etc_blk_unpacked);
+ const uint8_t* pCur_selectors = &m_selector_palette[m.m_selector_index][0];
uint64_t cur_err = 0;
if (r.get_params().m_perceptual)
{
for (uint32_t p = 0; p < 16; p++)
- cur_err += color_distance(true, src_pixels.get_ptr()[p], etc_blk_unpacked[p], false);
+ cur_err += color_distance(true, src_pixels.get_ptr()[p], block_colors[pCur_selectors[p]], false);
}
else
{
for (uint32_t p = 0; p < 16; p++)
- cur_err += color_distance(false, src_pixels.get_ptr()[p], etc_blk_unpacked[p], false);
+ cur_err += color_distance(false, src_pixels.get_ptr()[p], block_colors[pCur_selectors[p]], false);
}
-
+
+ const uint64_t limit_err = (uint64_t)ceilf(cur_err * selector_remap_thresh);
+
+ // Even if cur_err==limit_err, we still want to scan the history buffer because there may be equivalent entries that are cheaper to code.
+
uint64_t best_trial_err = UINT64_MAX;
int best_trial_idx = 0;
uint32_t best_trial_history_buf_idx = 0;
- const float selector_remap_thresh = maximum(1.0f, m_params.m_selector_rdo_quality_thresh); //2.5f;
- const bool use_strict_search = (m_params.m_compression_level == 0) && (selector_remap_thresh == 1.0f);
-
- const uint64_t limit_err = (uint64_t)ceilf(cur_err * selector_remap_thresh);
-
for (uint32_t j = 0; j < selector_history_buf.size(); j++)
{
const int trial_idx = selector_history_buf[j];
- if (use_strict_search)
+ const uint8_t* pSelectors = &m_selector_palette[m_selector_remap_table_new_to_old[trial_idx]][0];
+
+ if (m_params.m_compression_level <= 1)
{
- if (trial_idx == new_selector_index)
+ // Predict if evaluating the full color error would cause an early out, by summing the abs err of the selector indices.
+ int sel_diff = 0;
+ for (uint32_t p = 0; p < 16; p += 4)
{
- best_trial_err = 0;
- best_trial_idx = trial_idx;
- best_trial_history_buf_idx = j;
- break;
+ sel_diff += iabs(pCur_selectors[p + 0] - pSelectors[p + 0]);
+ sel_diff += iabs(pCur_selectors[p + 1] - pSelectors[p + 1]);
+ sel_diff += iabs(pCur_selectors[p + 2] - pSelectors[p + 2]);
+ sel_diff += iabs(pCur_selectors[p + 3] - pSelectors[p + 3]);
+ if (sel_diff >= SEL_DIFF_THRESHOLD)
+ break;
}
+ if (sel_diff >= SEL_DIFF_THRESHOLD)
+ continue;
}
- else
- {
- uint64_t trial_err = 0;
- const uint64_t thresh_err = minimum(limit_err, best_trial_err);
-
- color_rgba block_colors[4];
- etc_blk.get_block_colors(block_colors, 0);
-
- const uint8_t* pSelectors = &m_selector_palette[m_selector_remap_table_new_to_old[trial_idx]](0, 0);
- if (r.get_params().m_perceptual)
+ const uint64_t thresh_err = minimum(limit_err, best_trial_err);
+ uint64_t trial_err = 0;
+
+ // This tends to early out quickly, so SSE has a hard time competing.
+ if (r.get_params().m_perceptual)
+ {
+ for (uint32_t p = 0; p < 16; p++)
{
- for (uint32_t p = 0; p < 16; p++)
- {
- uint32_t sel = pSelectors[p];
- trial_err += color_distance(true, src_pixels.get_ptr()[p], block_colors[sel], false);
- if (trial_err > thresh_err)
- break;
- }
+ uint32_t sel = pSelectors[p];
+ trial_err += color_distance(true, src_pixels.get_ptr()[p], block_colors[sel], false);
+ if (trial_err > thresh_err)
+ break;
}
- else
+ }
+ else
+ {
+ for (uint32_t p = 0; p < 16; p++)
{
- for (uint32_t p = 0; p < 16; p++)
- {
- uint32_t sel = pSelectors[p];
- trial_err += color_distance(false, src_pixels.get_ptr()[p], block_colors[sel], false);
- if (trial_err > thresh_err)
- break;
- }
+ uint32_t sel = pSelectors[p];
+ trial_err += color_distance(false, src_pixels.get_ptr()[p], block_colors[sel], false);
+ if (trial_err > thresh_err)
+ break;
}
+ }
- if ((trial_err < best_trial_err) && (trial_err <= thresh_err))
- {
- assert(trial_err <= limit_err);
-
- best_trial_err = trial_err;
- best_trial_idx = trial_idx;
- best_trial_history_buf_idx = j;
- }
+ if ((trial_err < best_trial_err) && (trial_err <= thresh_err))
+ {
+ assert(trial_err <= limit_err);
+
+ best_trial_err = trial_err;
+ best_trial_idx = trial_idx;
+ best_trial_history_buf_idx = j;
}
}
@@ -1043,6 +1140,7 @@ namespace basisu
selector_history_buf_histogram.inc(best_trial_history_buf_idx);
}
+
} // if (m_params.m_selector_rdo_quality_thresh > 0.0f)
m.m_selector_index = m_selector_remap_table_new_to_old[new_selector_index];
@@ -1164,6 +1262,14 @@ namespace basisu
} // slice_index
+ //for (int i = 0; i <= 255 * 3; i++)
+ //{
+ // printf("%u, %u, %f\n", g_color_delta_bad_hist[i], g_color_delta_hist[i], g_color_delta_hist[i] ? g_color_delta_bad_hist[i] / (float)g_color_delta_hist[i] : 0);
+ //}
+
+ double total_prep_time = tm.get_elapsed_secs();
+ debug_printf("basisu_backend::encode_image: Total prep time: %3.2f\n", total_prep_time);
+
debug_printf("Endpoint pred RDO total endpoint indices remapped: %u %3.2f%%\n",
total_endpoint_indices_remapped, total_endpoint_indices_remapped * 100.0f / get_total_blocks());
@@ -1554,215 +1660,82 @@ namespace basisu
bool basisu_backend::encode_selector_palette()
{
const basisu_frontend& r = *m_pFront_end;
+
+ histogram delta_selector_pal_histogram(256);
- if ((m_params.m_use_global_sel_codebook) && (!m_params.m_use_hybrid_sel_codebooks))
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
{
- histogram global_mod_indices(1 << m_params.m_global_sel_codebook_mod_bits);
-
- for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
- global_mod_indices.inc(m_global_selector_palette_desc[q].m_mod_index);
-
- huffman_encoding_table global_pal_model, global_mod_model;
-
- if (!global_mod_model.init(global_mod_indices, 16))
- {
- error_printf("global_mod_model.init() failed!");
- return false;
- }
-
- bitwise_coder coder;
- coder.init(1024 * 1024);
-
- coder.put_bits(1, 1); // use global codebook
-
- coder.put_bits(m_params.m_global_sel_codebook_pal_bits, 4); // pal bits
- coder.put_bits(m_params.m_global_sel_codebook_mod_bits, 4); // mod bits
-
- uint32_t mod_model_bits = 0;
- if (m_params.m_global_sel_codebook_mod_bits)
- mod_model_bits = coder.emit_huffman_table(global_mod_model);
-
- uint32_t total_pal_bits = 0;
- uint32_t total_mod_bits = 0;
- for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
- {
- const uint32_t i = m_selector_remap_table_new_to_old[q];
-
- if (m_params.m_global_sel_codebook_pal_bits)
- {
- coder.put_bits(m_global_selector_palette_desc[i].m_pal_index, m_params.m_global_sel_codebook_pal_bits);
- total_pal_bits += m_params.m_global_sel_codebook_pal_bits;
- }
-
- if (m_params.m_global_sel_codebook_mod_bits)
- total_mod_bits += coder.put_code(m_global_selector_palette_desc[i].m_mod_index, global_mod_model);
- }
-
- coder.flush();
+ if (!q)
+ continue;
- m_output.m_selector_palette = coder.get_bytes();
+ const etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
+ const etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
- debug_printf("Modifier model bits: %u Avg per entry: %3.3f\n", mod_model_bits, mod_model_bits / float(r.get_total_selector_clusters()));
- debug_printf("Palette bits: %u Avg per entry: %3.3f, Modifier bits: %u Avg per entry: %3.3f\n", total_pal_bits, total_pal_bits / float(r.get_total_selector_clusters()), total_mod_bits, total_mod_bits / float(r.get_total_selector_clusters()));
+ for (uint32_t j = 0; j < 4; j++)
+ delta_selector_pal_histogram.inc(cur.get_byte(j) ^ predictor.get_byte(j));
}
- else if (m_params.m_use_hybrid_sel_codebooks)
- {
- huff2D used_global_cb_bitflag_huff2D(1, 8);
-
- histogram global_mod_indices(1 << m_params.m_global_sel_codebook_mod_bits);
-
- for (uint32_t s = 0; s < r.get_total_selector_clusters(); s++)
- {
- const uint32_t q = m_selector_remap_table_new_to_old[s];
-
- const bool used_global_cb_flag = r.get_selector_cluster_uses_global_cb_vec()[q];
-
- used_global_cb_bitflag_huff2D.emit(used_global_cb_flag);
- global_mod_indices.inc(m_global_selector_palette_desc[q].m_mod_index);
- }
-
- huffman_encoding_table global_mod_indices_model;
- if (!global_mod_indices_model.init(global_mod_indices, 16))
- {
- error_printf("global_mod_indices_model.init() failed!");
- return false;
- }
-
- bitwise_coder coder;
- coder.init(1024 * 1024);
+ if (!delta_selector_pal_histogram.get_total())
+ delta_selector_pal_histogram.inc(0);
- coder.put_bits(0, 1); // use global codebook
- coder.put_bits(1, 1); // uses hybrid codebooks
+ huffman_encoding_table delta_selector_pal_model;
+ if (!delta_selector_pal_model.init(delta_selector_pal_histogram, 16))
+ {
+ error_printf("delta_selector_pal_model.init() failed!");
+ return false;
+ }
- coder.put_bits(m_params.m_global_sel_codebook_pal_bits, 4); // pal bits
- coder.put_bits(m_params.m_global_sel_codebook_mod_bits, 4); // mod bits
+ bitwise_coder coder;
+ coder.init(1024 * 1024);
- used_global_cb_bitflag_huff2D.start_encoding(16);
- coder.emit_huffman_table(used_global_cb_bitflag_huff2D.get_encoding_table());
+ coder.put_bits(0, 1); // use global codebook
+ coder.put_bits(0, 1); // uses hybrid codebooks
- if (m_params.m_global_sel_codebook_mod_bits)
- coder.emit_huffman_table(global_mod_indices_model);
+ coder.put_bits(0, 1); // raw bytes
- uint32_t total_global_cb_entries = 0;
- uint32_t total_pal_bits = 0;
- uint32_t total_mod_bits = 0;
- uint32_t total_selectors = 0;
- uint32_t total_selector_bits = 0;
- uint32_t total_flag_bits = 0;
+ coder.emit_huffman_table(delta_selector_pal_model);
- for (uint32_t s = 0; s < r.get_total_selector_clusters(); s++)
+ for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
+ {
+ if (!q)
{
- const uint32_t q = m_selector_remap_table_new_to_old[s];
-
- total_flag_bits += used_global_cb_bitflag_huff2D.emit_next_sym(coder);
-
- const bool used_global_cb_flag = r.get_selector_cluster_uses_global_cb_vec()[q];
-
- if (used_global_cb_flag)
- {
- total_global_cb_entries++;
-
- total_pal_bits += coder.put_bits(r.get_selector_cluster_global_selector_entry_ids()[q].m_palette_index, m_params.m_global_sel_codebook_pal_bits);
- total_mod_bits += coder.put_code(r.get_selector_cluster_global_selector_entry_ids()[q].m_modifier.get_index(), global_mod_indices_model);
- }
- else
- {
- total_selectors++;
- total_selector_bits += 32;
-
- for (uint32_t j = 0; j < 4; j++)
- coder.put_bits(m_selector_palette[q].get_byte(j), 8);
- }
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_bits(m_selector_palette[m_selector_remap_table_new_to_old[q]].get_byte(j), 8);
+ continue;
}
- coder.flush();
+ const etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
+ const etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
- m_output.m_selector_palette = coder.get_bytes();
-
- debug_printf("Total global CB entries: %u %3.2f%%\n", total_global_cb_entries, total_global_cb_entries * 100.0f / r.get_total_selector_clusters());
- debug_printf("Total selector entries: %u %3.2f%%\n", total_selectors, total_selectors * 100.0f / r.get_total_selector_clusters());
- debug_printf("Total pal bits: %u, mod bits: %u, selector bits: %u, flag bits: %u\n", total_pal_bits, total_mod_bits, total_selector_bits, total_flag_bits);
+ for (uint32_t j = 0; j < 4; j++)
+ coder.put_code(cur.get_byte(j) ^ predictor.get_byte(j), delta_selector_pal_model);
}
- else
- {
- histogram delta_selector_pal_histogram(256);
-
- for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
- {
- if (!q)
- continue;
- const basist::etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
- const basist::etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
-
- for (uint32_t j = 0; j < 4; j++)
- delta_selector_pal_histogram.inc(cur.get_byte(j) ^ predictor.get_byte(j));
- }
-
- if (!delta_selector_pal_histogram.get_total())
- delta_selector_pal_histogram.inc(0);
+ coder.flush();
- huffman_encoding_table delta_selector_pal_model;
- if (!delta_selector_pal_model.init(delta_selector_pal_histogram, 16))
- {
- error_printf("delta_selector_pal_model.init() failed!");
- return false;
- }
+ m_output.m_selector_palette = coder.get_bytes();
- bitwise_coder coder;
+ if (m_output.m_selector_palette.size() >= r.get_total_selector_clusters() * 4)
+ {
coder.init(1024 * 1024);
coder.put_bits(0, 1); // use global codebook
coder.put_bits(0, 1); // uses hybrid codebooks
- coder.put_bits(0, 1); // raw bytes
-
- coder.emit_huffman_table(delta_selector_pal_model);
+ coder.put_bits(1, 1); // raw bytes
for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
{
- if (!q)
- {
- for (uint32_t j = 0; j < 4; j++)
- coder.put_bits(m_selector_palette[m_selector_remap_table_new_to_old[q]].get_byte(j), 8);
- continue;
- }
-
- const basist::etc1_selector_palette_entry& cur = m_selector_palette[m_selector_remap_table_new_to_old[q]];
- const basist::etc1_selector_palette_entry predictor(m_selector_palette[m_selector_remap_table_new_to_old[q - 1]]);
+ const uint32_t i = m_selector_remap_table_new_to_old[q];
for (uint32_t j = 0; j < 4; j++)
- coder.put_code(cur.get_byte(j) ^ predictor.get_byte(j), delta_selector_pal_model);
+ coder.put_bits(m_selector_palette[i].get_byte(j), 8);
}
coder.flush();
m_output.m_selector_palette = coder.get_bytes();
-
- if (m_output.m_selector_palette.size() >= r.get_total_selector_clusters() * 4)
- {
- coder.init(1024 * 1024);
-
- coder.put_bits(0, 1); // use global codebook
- coder.put_bits(0, 1); // uses hybrid codebooks
-
- coder.put_bits(1, 1); // raw bytes
-
- for (uint32_t q = 0; q < r.get_total_selector_clusters(); q++)
- {
- const uint32_t i = m_selector_remap_table_new_to_old[q];
-
- for (uint32_t j = 0; j < 4; j++)
- coder.put_bits(m_selector_palette[i].get_byte(j), 8);
- }
-
- coder.flush();
-
- m_output.m_selector_palette = coder.get_bytes();
- }
-
- } // if (m_params.m_use_global_sel_codebook)
+ }
debug_printf("Selector codebook bits: %u bytes: %u, Bits per entry: %3.1f, Avg bits/texel: %3.3f\n",
(int)m_output.m_selector_palette.size() * 8, (int)m_output.m_selector_palette.size(),
diff --git a/thirdparty/basis_universal/encoder/basisu_backend.h b/thirdparty/basis_universal/encoder/basisu_backend.h
index 393dccd22f..07778aeb9b 100644
--- a/thirdparty/basis_universal/encoder/basisu_backend.h
+++ b/thirdparty/basis_universal/encoder/basisu_backend.h
@@ -17,11 +17,86 @@
#include "../transcoder/basisu.h"
#include "basisu_enc.h"
#include "../transcoder/basisu_transcoder_internal.h"
-#include "../transcoder/basisu_global_selector_palette.h"
#include "basisu_frontend.h"
namespace basisu
{
+ struct etc1_selector_palette_entry
+ {
+ etc1_selector_palette_entry()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ basisu::clear_obj(*this);
+ }
+
+ uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
+ uint8_t& operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
+
+ void set_uint32(uint32_t v)
+ {
+ for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
+ {
+ uint32_t b = (v >> (byte_index * 8)) & 0xFF;
+
+ m_selectors[byte_index * 4 + 0] = b & 3;
+ m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
+ m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
+ m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
+ }
+ }
+
+ uint32_t get_uint32() const
+ {
+ return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
+ }
+
+ uint32_t get_byte(uint32_t byte_index) const
+ {
+ assert(byte_index < 4);
+
+ return m_selectors[byte_index * 4 + 0] |
+ (m_selectors[byte_index * 4 + 1] << 2) |
+ (m_selectors[byte_index * 4 + 2] << 4) |
+ (m_selectors[byte_index * 4 + 3] << 6);
+ }
+
+ uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
+ uint8_t& operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
+
+ bool operator< (const etc1_selector_palette_entry& other) const
+ {
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ if (m_selectors[i] < other.m_selectors[i])
+ return true;
+ else if (m_selectors[i] != other.m_selectors[i])
+ return false;
+ }
+
+ return false;
+ }
+
+ bool operator== (const etc1_selector_palette_entry& other) const
+ {
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ if (m_selectors[i] != other.m_selectors[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ uint8_t m_selectors[16];
+ };
+
+ typedef basisu::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
+
struct encoder_block
{
encoder_block()
@@ -78,14 +153,11 @@ namespace basisu
float m_endpoint_rdo_quality_thresh;
float m_selector_rdo_quality_thresh;
uint32_t m_compression_level;
-
- bool m_use_global_sel_codebook;
- uint32_t m_global_sel_codebook_pal_bits;
- uint32_t m_global_sel_codebook_mod_bits;
- bool m_use_hybrid_sel_codebooks;
-
+
bool m_used_global_codebooks;
+ bool m_validate;
+
basisu_backend_params()
{
clear();
@@ -99,12 +171,8 @@ namespace basisu
m_endpoint_rdo_quality_thresh = 0.0f;
m_selector_rdo_quality_thresh = 0.0f;
m_compression_level = 0;
-
- m_use_global_sel_codebook = false;
- m_global_sel_codebook_pal_bits = ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS;
- m_global_sel_codebook_mod_bits = basist::etc1_global_palette_entry_modifier::cTotalBits;
- m_use_hybrid_sel_codebooks = false;
m_used_global_codebooks = false;
+ m_validate = true;
}
};
@@ -205,7 +273,7 @@ namespace basisu
void clear();
- void init(basisu_frontend *pFront_end, basisu_backend_params &params, const basisu_backend_slice_desc_vec &slice_desc, const basist::etc1_global_selector_codebook *pGlobal_sel_codebook);
+ void init(basisu_frontend *pFront_end, basisu_backend_params &params, const basisu_backend_slice_desc_vec &slice_desc);
uint32_t encode();
@@ -217,10 +285,9 @@ namespace basisu
basisu_backend_params m_params;
basisu_backend_slice_desc_vec m_slices;
basisu_backend_output m_output;
- const basist::etc1_global_selector_codebook *m_pGlobal_sel_codebook;
-
+
etc1_endpoint_palette_entry_vec m_endpoint_palette;
- basist::etc1_selector_palette_entry_vec m_selector_palette;
+ etc1_selector_palette_entry_vec m_selector_palette;
struct etc1_global_selector_cb_entry_desc
{
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp
index 10f96cec4a..166a1c4fe0 100644
--- a/thirdparty/basis_universal/encoder/basisu_comp.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp
@@ -21,6 +21,8 @@
#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
#include "basisu_miniz.h"
+#include "basisu_opencl.h"
+
#if !BASISD_SUPPORT_KTX2
#error BASISD_SUPPORT_KTX2 must be enabled (set to 1).
#endif
@@ -45,21 +47,45 @@ using namespace buminiz;
namespace basisu
{
basis_compressor::basis_compressor() :
+ m_pOpenCL_context(nullptr),
m_basis_file_size(0),
m_basis_bits_per_texel(0.0f),
m_total_blocks(0),
- m_auto_global_sel_pal(false),
- m_any_source_image_has_alpha(false)
+ m_any_source_image_has_alpha(false),
+ m_opencl_failed(false)
{
debug_printf("basis_compressor::basis_compressor\n");
+
+ assert(g_library_initialized);
}
+ basis_compressor::~basis_compressor()
+ {
+ if (m_pOpenCL_context)
+ {
+ opencl_destroy_context(m_pOpenCL_context);
+ m_pOpenCL_context = nullptr;
+ }
+ }
+
bool basis_compressor::init(const basis_compressor_params &params)
{
debug_printf("basis_compressor::init\n");
+
+ if (!g_library_initialized)
+ {
+ error_printf("basis_compressor::init: basisu_encoder_init() MUST be called before using any encoder functionality!\n");
+ return false;
+ }
+ if (!params.m_pJob_pool)
+ {
+ error_printf("basis_compressor::init: A non-null job_pool pointer must be specified\n");
+ return false;
+ }
+
m_params = params;
-
+
if (m_params.m_debug)
{
debug_printf("basis_compressor::init:\n");
@@ -68,9 +94,7 @@ namespace basisu
#define PRINT_INT_VALUE(v) debug_printf("%s: %i %u\n", BASISU_STRINGIZE2(v), static_cast<int>(m_params.v), m_params.v.was_changed());
#define PRINT_UINT_VALUE(v) debug_printf("%s: %u %u\n", BASISU_STRINGIZE2(v), static_cast<uint32_t>(m_params.v), m_params.v.was_changed());
#define PRINT_FLOAT_VALUE(v) debug_printf("%s: %f %u\n", BASISU_STRINGIZE2(v), static_cast<float>(m_params.v), m_params.v.was_changed());
-
- debug_printf("Has global selector codebook: %i\n", m_params.m_pSel_codebook != nullptr);
-
+
debug_printf("Source images: %u, source filenames: %u, source alpha filenames: %i, Source mipmap images: %u\n",
m_params.m_source_images.size(), m_params.m_source_filenames.size(), m_params.m_source_alpha_filenames.size(), m_params.m_source_mipmap_images.size());
@@ -83,14 +107,12 @@ namespace basisu
}
PRINT_BOOL_VALUE(m_uastc);
+ PRINT_BOOL_VALUE(m_use_opencl);
PRINT_BOOL_VALUE(m_y_flip);
PRINT_BOOL_VALUE(m_debug);
- PRINT_BOOL_VALUE(m_validate);
+ PRINT_BOOL_VALUE(m_validate_etc1s);
PRINT_BOOL_VALUE(m_debug_images);
- PRINT_BOOL_VALUE(m_global_sel_pal);
- PRINT_BOOL_VALUE(m_auto_global_sel_pal);
PRINT_INT_VALUE(m_compression_level);
- PRINT_BOOL_VALUE(m_no_hybrid_sel_cb);
PRINT_BOOL_VALUE(m_perceptual);
PRINT_BOOL_VALUE(m_no_endpoint_rdo);
PRINT_BOOL_VALUE(m_no_selector_rdo);
@@ -107,12 +129,7 @@ namespace basisu
PRINT_BOOL_VALUE(m_renormalize);
PRINT_BOOL_VALUE(m_multithreading);
PRINT_BOOL_VALUE(m_disable_hierarchical_endpoint_codebooks);
-
- PRINT_FLOAT_VALUE(m_hybrid_sel_cb_quality_thresh);
-
- PRINT_INT_VALUE(m_global_pal_bits);
- PRINT_INT_VALUE(m_global_mod_bits);
-
+
PRINT_FLOAT_VALUE(m_endpoint_rdo_thresh);
PRINT_FLOAT_VALUE(m_selector_rdo_thresh);
@@ -148,6 +165,7 @@ namespace basisu
PRINT_INT_VALUE(m_resample_width);
PRINT_INT_VALUE(m_resample_height);
PRINT_FLOAT_VALUE(m_resample_factor);
+
debug_printf("Has global codebooks: %u\n", m_params.m_pGlobal_codebooks ? 1 : 0);
if (m_params.m_pGlobal_codebooks)
{
@@ -165,6 +183,8 @@ namespace basisu
debug_printf("Key: \"%s\"\n", m_params.m_ktx2_key_values[i].m_key.data());
debug_printf("Value size: %u\n", m_params.m_ktx2_key_values[i].m_value.size());
}
+
+ PRINT_BOOL_VALUE(m_validate_output_data);
#undef PRINT_BOOL_VALUE
#undef PRINT_INT_VALUE
@@ -178,6 +198,20 @@ namespace basisu
return false;
}
+ if ((m_params.m_compute_stats) && (!m_params.m_validate_output_data))
+ {
+ m_params.m_validate_output_data = true;
+
+ debug_printf("Note: m_compute_stats is true, so forcing m_validate_output_data to true as well\n");
+ }
+
+ if ((m_params.m_use_opencl) && opencl_is_available() && !m_pOpenCL_context && !m_opencl_failed)
+ {
+ m_pOpenCL_context = opencl_create_context();
+ if (!m_pOpenCL_context)
+ m_opencl_failed = true;
+ }
+
return true;
}
@@ -424,7 +458,7 @@ namespace basisu
#endif
if (m_params.m_debug)
- debug_printf("Total mipmap generation time: %f secs\n", tm.get_elapsed_secs());
+ debug_printf("Total mipmap generation time: %3.3f secs\n", tm.get_elapsed_secs());
return true;
}
@@ -579,11 +613,11 @@ namespace basisu
if ((file_image.get_width() > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION) || (file_image.get_height() > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION))
{
- error_printf("basis_compressor::read_source_images: Source image is too large!\n");
+ error_printf("basis_compressor::read_source_images: Source image \"%s\" is too large!\n", pSource_filename);
return false;
}
- source_images.push_back(file_image);
+ source_images.enlarge(1)->swap(file_image);
source_filenames.push_back(pSource_filename);
}
@@ -624,17 +658,19 @@ namespace basisu
for (uint32_t source_file_index = 0; source_file_index < total_source_files; source_file_index++)
{
- image &file_image = source_images[source_file_index];
const std::string &source_filename = source_filenames[source_file_index];
// Now, for each source image, create the slices corresponding to that image.
basisu::vector<image> slices;
slices.reserve(32);
-
+
// The first (largest) mipmap level.
- slices.push_back(file_image);
-
+ image& file_image = source_images[source_file_index];
+
+ // Reserve a slot for mip0.
+ slices.resize(1);
+
if (m_params.m_source_mipmap_images.size())
{
// User-provided mipmaps for each layer or image in the texture array.
@@ -666,6 +702,10 @@ namespace basisu
return false;
}
+ // Swap in the largest mipmap level here to avoid copying it, because generate_mips() will change the array.
+ // NOTE: file_image is now blank.
+ slices[0].swap(file_image);
+
uint_vec mip_indices(slices.size());
for (uint32_t i = 0; i < slices.size(); i++)
mip_indices[i] = i;
@@ -734,18 +774,16 @@ namespace basisu
save_png(string_format("basis_debug_source_image_%u_slice_%u.png", source_file_index, slice_index).c_str(), slice_image);
}
+ const uint32_t dest_image_index = m_slice_images.size();
+
enlarge_vector(m_stats, 1);
enlarge_vector(m_slice_images, 1);
enlarge_vector(m_slice_descs, 1);
-
- const uint32_t dest_image_index = (uint32_t)m_stats.size() - 1;
-
+
m_stats[dest_image_index].m_filename = source_filename.c_str();
m_stats[dest_image_index].m_width = orig_width;
m_stats[dest_image_index].m_height = orig_height;
-
- m_slice_images[dest_image_index] = slice_image;
-
+
debug_printf("****** Slice %u: mip %u, alpha_slice: %u, filename: \"%s\", original: %ux%u actual: %ux%u\n", m_slice_descs.size() - 1, mip_indices[slice_index], is_alpha_slice, source_filename.c_str(), orig_width, orig_height, slice_image.get_width(), slice_image.get_height());
basisu_backend_slice_desc &slice_desc = m_slice_descs[dest_image_index];
@@ -777,6 +815,10 @@ namespace basisu
m_total_blocks += slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
total_macroblocks += slice_desc.m_num_macroblocks_x * slice_desc.m_num_macroblocks_y;
+
+ // Finally, swap in the slice's image to avoid copying it.
+ // NOTE: slice_image is now blank.
+ m_slice_images[dest_image_index].swap(slice_image);
} // slice_index
@@ -1055,7 +1097,7 @@ namespace basisu
endpoint_clusters = clamp<uint32_t>((uint32_t)(.5f + lerp<float>(ENDPOINT_CODEBOOK_MID_QUALITY_CODEBOOK_SIZE, static_cast<float>(max_endpoints), color_endpoint_quality)), 32, basisu_frontend::cMaxEndpointClusters);
}
- float bits_per_selector_cluster = m_params.m_global_sel_pal ? 21.0f : 14.0f;
+ float bits_per_selector_cluster = 14.0f;
const float max_desired_selector_cluster_bits_per_texel = 1.0f; // .15f
int max_selectors = static_cast<int>((max_desired_selector_cluster_bits_per_texel * total_texels) / bits_per_selector_cluster);
@@ -1110,21 +1152,7 @@ namespace basisu
m_params.m_selector_rdo_thresh *= lerp<float>(1.0f, .75f, l);
}
}
-
- m_auto_global_sel_pal = false;
- if (!m_params.m_global_sel_pal && m_params.m_auto_global_sel_pal)
- {
- const float bits_per_selector_cluster = 31.0f;
- double selector_codebook_bpp_est = (bits_per_selector_cluster * selector_clusters) / total_texels;
- debug_printf("selector_codebook_bpp_est: %f\n", selector_codebook_bpp_est);
- const float force_global_sel_pal_bpp_threshold = .15f;
- if ((total_texels <= 128.0f*128.0f) && (selector_codebook_bpp_est > force_global_sel_pal_bpp_threshold))
- {
- m_auto_global_sel_pal = true;
- debug_printf("Auto global selector palette enabled\n");
- }
- }
-
+
basisu_frontend::params p;
p.m_num_source_blocks = m_total_blocks;
p.m_pSource_blocks = &m_source_blocks[0];
@@ -1137,27 +1165,24 @@ namespace basisu
p.m_tex_type = m_params.m_tex_type;
p.m_multithreaded = m_params.m_multithreading;
p.m_disable_hierarchical_endpoint_codebooks = m_params.m_disable_hierarchical_endpoint_codebooks;
- p.m_validate = m_params.m_validate;
+ p.m_validate = m_params.m_validate_etc1s;
p.m_pJob_pool = m_params.m_pJob_pool;
p.m_pGlobal_codebooks = m_params.m_pGlobal_codebooks;
-
- if ((m_params.m_global_sel_pal) || (m_auto_global_sel_pal))
- {
- p.m_pGlobal_sel_codebook = m_params.m_pSel_codebook;
- p.m_num_global_sel_codebook_pal_bits = m_params.m_global_pal_bits;
- p.m_num_global_sel_codebook_mod_bits = m_params.m_global_mod_bits;
- p.m_use_hybrid_selector_codebooks = !m_params.m_no_hybrid_sel_cb;
- p.m_hybrid_codebook_quality_thresh = m_params.m_hybrid_sel_cb_quality_thresh;
- }
+
+ // Don't keep trying to use OpenCL if it ever fails.
+ p.m_pOpenCL_context = !m_opencl_failed ? m_pOpenCL_context : nullptr;
if (!m_frontend.init(p))
{
error_printf("basisu_frontend::init() failed!\n");
return false;
}
-
+
m_frontend.compress();
+ if (m_frontend.get_opencl_failed())
+ m_opencl_failed = true;
+
if (m_params.m_debug_images)
{
for (uint32_t i = 0; i < m_slice_descs.size(); i++)
@@ -1184,6 +1209,9 @@ namespace basisu
bool basis_compressor::extract_frontend_texture_data()
{
+ if (!m_params.m_compute_stats)
+ return true;
+
debug_printf("basis_compressor::extract_frontend_texture_data\n");
m_frontend_output_textures.resize(m_slice_descs.size());
@@ -1242,13 +1270,10 @@ namespace basisu
if (!m_params.m_no_selector_rdo)
backend_params.m_selector_rdo_quality_thresh = m_params.m_selector_rdo_thresh;
- backend_params.m_use_global_sel_codebook = (m_frontend.get_params().m_pGlobal_sel_codebook != NULL);
- backend_params.m_global_sel_codebook_pal_bits = m_frontend.get_params().m_num_global_sel_codebook_pal_bits;
- backend_params.m_global_sel_codebook_mod_bits = m_frontend.get_params().m_num_global_sel_codebook_mod_bits;
- backend_params.m_use_hybrid_sel_codebooks = m_frontend.get_params().m_use_hybrid_selector_codebooks;
backend_params.m_used_global_codebooks = m_frontend.get_params().m_pGlobal_codebooks != nullptr;
+ backend_params.m_validate = m_params.m_validate_output_data;
- m_backend.init(&m_frontend, backend_params, m_slice_descs, m_params.m_pSel_codebook);
+ m_backend.init(&m_frontend, backend_params, m_slice_descs);
uint32_t total_packed_bytes = m_backend.encode();
if (!total_packed_bytes)
@@ -1278,140 +1303,143 @@ namespace basisu
m_output_basis_file = comp_data;
- interval_timer tm;
- tm.start();
-
- basist::basisu_transcoder_init();
-
- debug_printf("basist::basisu_transcoder_init: Took %f ms\n", tm.get_elapsed_ms());
-
- // Verify the compressed data by transcoding it to ASTC (or ETC1)/BC7 and validating the CRC's.
- basist::basisu_transcoder decoder(m_params.m_pSel_codebook);
- if (!decoder.validate_file_checksums(&comp_data[0], (uint32_t)comp_data.size(), true))
+ uint32_t total_orig_pixels = 0, total_texels = 0, total_orig_texels = 0;
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
{
- error_printf("decoder.validate_file_checksums() failed!\n");
- return false;
+ const basisu_backend_slice_desc& slice_desc = m_slice_descs[i];
+
+ total_orig_pixels += slice_desc.m_orig_width * slice_desc.m_orig_height;
+ total_texels += slice_desc.m_width * slice_desc.m_height;
}
- m_decoded_output_textures.resize(m_slice_descs.size());
- m_decoded_output_textures_unpacked.resize(m_slice_descs.size());
+ m_basis_file_size = (uint32_t)comp_data.size();
+ m_basis_bits_per_texel = total_orig_texels ? (comp_data.size() * 8.0f) / total_orig_texels : 0;
- m_decoded_output_textures_bc7.resize(m_slice_descs.size());
- m_decoded_output_textures_unpacked_bc7.resize(m_slice_descs.size());
-
- tm.start();
- if (m_params.m_pGlobal_codebooks)
- {
- decoder.set_global_codebooks(m_params.m_pGlobal_codebooks);
- }
+ debug_printf("Total .basis output file size: %u, %3.3f bits/texel\n", comp_data.size(), comp_data.size() * 8.0f / total_orig_pixels);
- if (!decoder.start_transcoding(&comp_data[0], (uint32_t)comp_data.size()))
+ if (m_params.m_validate_output_data)
{
- error_printf("decoder.start_transcoding() failed!\n");
- return false;
- }
+ interval_timer tm;
+ tm.start();
- double start_transcoding_time = tm.get_elapsed_secs();
+ basist::basisu_transcoder_init();
- debug_printf("basisu_compressor::start_transcoding() took %3.3fms\n", start_transcoding_time * 1000.0f);
+ debug_printf("basist::basisu_transcoder_init: Took %f ms\n", tm.get_elapsed_ms());
- uint32_t total_orig_pixels = 0;
- uint32_t total_texels = 0;
+ // Verify the compressed data by transcoding it to ASTC (or ETC1)/BC7 and validating the CRC's.
+ basist::basisu_transcoder decoder;
+ if (!decoder.validate_file_checksums(&comp_data[0], (uint32_t)comp_data.size(), true))
+ {
+ error_printf("decoder.validate_file_checksums() failed!\n");
+ return false;
+ }
- double total_time_etc1s_or_astc = 0;
+ m_decoded_output_textures.resize(m_slice_descs.size());
+ m_decoded_output_textures_unpacked.resize(m_slice_descs.size());
- for (uint32_t i = 0; i < m_slice_descs.size(); i++)
- {
- gpu_image decoded_texture;
- decoded_texture.init(m_params.m_uastc ? texture_format::cASTC4x4 : texture_format::cETC1, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
-
- tm.start();
+ m_decoded_output_textures_bc7.resize(m_slice_descs.size());
+ m_decoded_output_textures_unpacked_bc7.resize(m_slice_descs.size());
- basist::block_format format = m_params.m_uastc ? basist::block_format::cASTC_4x4 : basist::block_format::cETC1;
- uint32_t bytes_per_block = m_params.m_uastc ? 16 : 8;
-
- if (!decoder.transcode_slice(&comp_data[0], (uint32_t)comp_data.size(), i,
- reinterpret_cast<etc_block *>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, format, bytes_per_block))
+ tm.start();
+ if (m_params.m_pGlobal_codebooks)
{
- error_printf("Transcoding failed on slice %u!\n", i);
- return false;
+ decoder.set_global_codebooks(m_params.m_pGlobal_codebooks);
}
- total_time_etc1s_or_astc += tm.get_elapsed_secs();
-
- if (encoded_output.m_tex_format == basist::basis_tex_format::cETC1S)
+ if (!decoder.start_transcoding(&comp_data[0], (uint32_t)comp_data.size()))
{
- uint32_t image_crc16 = basist::crc16(decoded_texture.get_ptr(), decoded_texture.get_size_in_bytes(), 0);
- if (image_crc16 != encoded_output.m_slice_image_crcs[i])
- {
- error_printf("Decoded image data CRC check failed on slice %u!\n", i);
- return false;
- }
- debug_printf("Decoded image data CRC check succeeded on slice %i\n", i);
+ error_printf("decoder.start_transcoding() failed!\n");
+ return false;
}
- m_decoded_output_textures[i] = decoded_texture;
+ double start_transcoding_time = tm.get_elapsed_secs();
- total_orig_pixels += m_slice_descs[i].m_orig_width * m_slice_descs[i].m_orig_height;
- total_texels += m_slice_descs[i].m_width * m_slice_descs[i].m_height;
- }
-
- double total_time_bc7 = 0;
+ debug_printf("basisu_compressor::start_transcoding() took %3.3fms\n", start_transcoding_time * 1000.0f);
+
+ double total_time_etc1s_or_astc = 0;
- if (basist::basis_is_format_supported(basist::transcoder_texture_format::cTFBC7_RGBA, basist::basis_tex_format::cUASTC4x4) &&
- basist::basis_is_format_supported(basist::transcoder_texture_format::cTFBC7_RGBA, basist::basis_tex_format::cETC1S))
- {
for (uint32_t i = 0; i < m_slice_descs.size(); i++)
{
gpu_image decoded_texture;
- decoded_texture.init(texture_format::cBC7, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
+ decoded_texture.init(m_params.m_uastc ? texture_format::cUASTC4x4 : texture_format::cETC1, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
tm.start();
+ basist::block_format format = m_params.m_uastc ? basist::block_format::cUASTC_4x4 : basist::block_format::cETC1;
+ uint32_t bytes_per_block = m_params.m_uastc ? 16 : 8;
+
if (!decoder.transcode_slice(&comp_data[0], (uint32_t)comp_data.size(), i,
- reinterpret_cast<etc_block*>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, basist::block_format::cBC7, 16))
+ reinterpret_cast<etc_block*>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, format, bytes_per_block))
{
- error_printf("Transcoding failed to BC7 on slice %u!\n", i);
+ error_printf("Transcoding failed on slice %u!\n", i);
return false;
}
- total_time_bc7 += tm.get_elapsed_secs();
+ total_time_etc1s_or_astc += tm.get_elapsed_secs();
+
+ if (encoded_output.m_tex_format == basist::basis_tex_format::cETC1S)
+ {
+ uint32_t image_crc16 = basist::crc16(decoded_texture.get_ptr(), decoded_texture.get_size_in_bytes(), 0);
+ if (image_crc16 != encoded_output.m_slice_image_crcs[i])
+ {
+ error_printf("Decoded image data CRC check failed on slice %u!\n", i);
+ return false;
+ }
+ debug_printf("Decoded image data CRC check succeeded on slice %i\n", i);
+ }
- m_decoded_output_textures_bc7[i] = decoded_texture;
+ m_decoded_output_textures[i] = decoded_texture;
}
- }
- for (uint32_t i = 0; i < m_slice_descs.size(); i++)
- {
- m_decoded_output_textures[i].unpack(m_decoded_output_textures_unpacked[i]);
+ double total_time_bc7 = 0;
- if (m_decoded_output_textures_bc7[i].get_pixel_width())
- m_decoded_output_textures_bc7[i].unpack(m_decoded_output_textures_unpacked_bc7[i]);
- }
+ if (basist::basis_is_format_supported(basist::transcoder_texture_format::cTFBC7_RGBA, basist::basis_tex_format::cUASTC4x4) &&
+ basist::basis_is_format_supported(basist::transcoder_texture_format::cTFBC7_RGBA, basist::basis_tex_format::cETC1S))
+ {
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ gpu_image decoded_texture;
+ decoded_texture.init(texture_format::cBC7, m_slice_descs[i].m_width, m_slice_descs[i].m_height);
- debug_printf("Transcoded to %s in %3.3fms, %f texels/sec\n", m_params.m_uastc ? "ASTC" : "ETC1", total_time_etc1s_or_astc * 1000.0f, total_orig_pixels / total_time_etc1s_or_astc);
+ tm.start();
- if (total_time_bc7 != 0)
- debug_printf("Transcoded to BC7 in %3.3fms, %f texels/sec\n", total_time_bc7 * 1000.0f, total_orig_pixels / total_time_bc7);
+ if (!decoder.transcode_slice(&comp_data[0], (uint32_t)comp_data.size(), i,
+ reinterpret_cast<etc_block*>(decoded_texture.get_ptr()), m_slice_descs[i].m_num_blocks_x * m_slice_descs[i].m_num_blocks_y, basist::block_format::cBC7, 16))
+ {
+ error_printf("Transcoding failed to BC7 on slice %u!\n", i);
+ return false;
+ }
- debug_printf("Total .basis output file size: %u, %3.3f bits/texel\n", comp_data.size(), comp_data.size() * 8.0f / total_orig_pixels);
-
- uint32_t total_orig_texels = 0;
- for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
- {
- const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
+ total_time_bc7 += tm.get_elapsed_secs();
- total_orig_texels += slice_desc.m_orig_width * slice_desc.m_orig_height;
+ m_decoded_output_textures_bc7[i] = decoded_texture;
+ }
+ }
- const uint32_t total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
- BASISU_NOTE_UNUSED(total_blocks);
+ for (uint32_t i = 0; i < m_slice_descs.size(); i++)
+ {
+ m_decoded_output_textures[i].unpack(m_decoded_output_textures_unpacked[i]);
- assert(m_decoded_output_textures[slice_index].get_total_blocks() == total_blocks);
- }
+ if (m_decoded_output_textures_bc7[i].get_pixel_width())
+ m_decoded_output_textures_bc7[i].unpack(m_decoded_output_textures_unpacked_bc7[i]);
+ }
- m_basis_file_size = (uint32_t)comp_data.size();
- m_basis_bits_per_texel = (comp_data.size() * 8.0f) / total_orig_texels;
+ debug_printf("Transcoded to %s in %3.3fms, %f texels/sec\n", m_params.m_uastc ? "ASTC" : "ETC1", total_time_etc1s_or_astc * 1000.0f, total_orig_pixels / total_time_etc1s_or_astc);
+
+ if (total_time_bc7 != 0)
+ debug_printf("Transcoded to BC7 in %3.3fms, %f texels/sec\n", total_time_bc7 * 1000.0f, total_orig_pixels / total_time_bc7);
+ for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
+ {
+ const basisu_backend_slice_desc& slice_desc = m_slice_descs[slice_index];
+
+ const uint32_t total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y;
+ BASISU_NOTE_UNUSED(total_blocks);
+
+ assert(m_decoded_output_textures[slice_index].get_total_blocks() == total_blocks);
+ }
+ } // if (m_params.m_validate_output_data)
+
return true;
}
@@ -1465,175 +1493,171 @@ namespace basisu
m_stats.resize(m_slice_descs.size());
- uint32_t total_orig_texels = 0;
-
- for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
+ if (m_params.m_validate_output_data)
{
- const basisu_backend_slice_desc &slice_desc = m_slice_descs[slice_index];
-
- total_orig_texels += slice_desc.m_orig_width * slice_desc.m_orig_height;
-
- if (m_params.m_compute_stats)
+ for (uint32_t slice_index = 0; slice_index < m_slice_descs.size(); slice_index++)
{
- printf("Slice: %u\n", slice_index);
+ const basisu_backend_slice_desc& slice_desc = m_slice_descs[slice_index];
- image_stats &s = m_stats[slice_index];
+ if (m_params.m_compute_stats)
+ {
+ printf("Slice: %u\n", slice_index);
- // TODO: We used to output SSIM (during heavy encoder development), but this slowed down compression too much. We'll be adding it back.
+ image_stats& s = m_stats[slice_index];
- image_metrics em;
-
- // ---- .basis stats
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 3);
- em.print(".basis RGB Avg: ");
- s.m_basis_rgb_avg_psnr = em.m_psnr;
+ // TODO: We used to output SSIM (during heavy encoder development), but this slowed down compression too much. We'll be adding it back.
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 4);
- em.print(".basis RGBA Avg: ");
- s.m_basis_rgba_avg_psnr = em.m_psnr;
+ image_metrics em;
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 1);
- em.print(".basis R Avg: ");
-
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 1, 1);
- em.print(".basis G Avg: ");
-
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 2, 1);
- em.print(".basis B Avg: ");
+ // ---- .basis stats
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 3);
+ em.print(".basis RGB Avg: ");
+ s.m_basis_rgb_avg_psnr = em.m_psnr;
- if (m_params.m_uastc)
- {
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 3, 1);
- em.print(".basis A Avg: ");
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 4);
+ em.print(".basis RGBA Avg: ");
+ s.m_basis_rgba_avg_psnr = em.m_psnr;
- s.m_basis_a_avg_psnr = em.m_psnr;
- }
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 1);
+ em.print(".basis R Avg: ");
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0);
- em.print(".basis 709 Luma: ");
- s.m_basis_luma_709_psnr = static_cast<float>(em.m_psnr);
- s.m_basis_luma_709_ssim = static_cast<float>(em.m_ssim);
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 1, 1);
+ em.print(".basis G Avg: ");
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0, true, true);
- em.print(".basis 601 Luma: ");
- s.m_basis_luma_601_psnr = static_cast<float>(em.m_psnr);
-
- if (m_slice_descs.size() == 1)
- {
- const uint32_t output_size = comp_size ? (uint32_t)comp_size : (uint32_t)comp_data.size();
- debug_printf(".basis RGB PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_rgb_avg_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
- debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_luma_709_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
- }
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 2, 1);
+ em.print(".basis B Avg: ");
- if (m_decoded_output_textures_unpacked_bc7[slice_index].get_width())
- {
- // ---- BC7 stats
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 3);
- em.print("BC7 RGB Avg: ");
- s.m_bc7_rgb_avg_psnr = em.m_psnr;
+ if (m_params.m_uastc)
+ {
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 3, 1);
+ em.print(".basis A Avg: ");
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 4);
- em.print("BC7 RGBA Avg: ");
- s.m_bc7_rgba_avg_psnr = em.m_psnr;
+ s.m_basis_a_avg_psnr = em.m_psnr;
+ }
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 1);
- em.print("BC7 R Avg: ");
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0);
+ em.print(".basis 709 Luma: ");
+ s.m_basis_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_basis_luma_709_ssim = static_cast<float>(em.m_ssim);
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 1, 1);
- em.print("BC7 G Avg: ");
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked[slice_index], 0, 0, true, true);
+ em.print(".basis 601 Luma: ");
+ s.m_basis_luma_601_psnr = static_cast<float>(em.m_psnr);
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 2, 1);
- em.print("BC7 B Avg: ");
+ if (m_slice_descs.size() == 1)
+ {
+ const uint32_t output_size = comp_size ? (uint32_t)comp_size : (uint32_t)comp_data.size();
+ debug_printf(".basis RGB PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_rgb_avg_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ debug_printf(".basis Luma 709 PSNR per bit/texel*10000: %3.3f\n", 10000.0f * s.m_basis_luma_709_psnr / ((output_size * 8.0f) / (slice_desc.m_orig_width * slice_desc.m_orig_height)));
+ }
- if (m_params.m_uastc)
+ if (m_decoded_output_textures_unpacked_bc7[slice_index].get_width())
{
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 3, 1);
- em.print("BC7 A Avg: ");
+ // ---- BC7 stats
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 3);
+ em.print("BC7 RGB Avg: ");
+ s.m_bc7_rgb_avg_psnr = em.m_psnr;
- s.m_bc7_a_avg_psnr = em.m_psnr;
- }
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 4);
+ em.print("BC7 RGBA Avg: ");
+ s.m_bc7_rgba_avg_psnr = em.m_psnr;
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0);
- em.print("BC7 709 Luma: ");
- s.m_bc7_luma_709_psnr = static_cast<float>(em.m_psnr);
- s.m_bc7_luma_709_ssim = static_cast<float>(em.m_ssim);
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 1);
+ em.print("BC7 R Avg: ");
- em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0, true, true);
- em.print("BC7 601 Luma: ");
- s.m_bc7_luma_601_psnr = static_cast<float>(em.m_psnr);
- }
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 1, 1);
+ em.print("BC7 G Avg: ");
- if (!m_params.m_uastc)
- {
- // ---- Nearly best possible ETC1S stats
- em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0);
- em.print("Unquantized ETC1S 709 Luma: ");
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 2, 1);
+ em.print("BC7 B Avg: ");
- s.m_best_etc1s_luma_709_psnr = static_cast<float>(em.m_psnr);
- s.m_best_etc1s_luma_709_ssim = static_cast<float>(em.m_ssim);
+ if (m_params.m_uastc)
+ {
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 3, 1);
+ em.print("BC7 A Avg: ");
- em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0, true, true);
- em.print("Unquantized ETC1S 601 Luma: ");
+ s.m_bc7_a_avg_psnr = em.m_psnr;
+ }
- s.m_best_etc1s_luma_601_psnr = static_cast<float>(em.m_psnr);
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0);
+ em.print("BC7 709 Luma: ");
+ s.m_bc7_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_bc7_luma_709_ssim = static_cast<float>(em.m_ssim);
- em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 3);
- em.print("Unquantized ETC1S RGB Avg: ");
+ em.calc(m_slice_images[slice_index], m_decoded_output_textures_unpacked_bc7[slice_index], 0, 0, true, true);
+ em.print("BC7 601 Luma: ");
+ s.m_bc7_luma_601_psnr = static_cast<float>(em.m_psnr);
+ }
- s.m_best_etc1s_rgb_avg_psnr = static_cast<float>(em.m_psnr);
+ if (!m_params.m_uastc)
+ {
+ // ---- Nearly best possible ETC1S stats
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 3);
+ em.print("Unquantized ETC1S RGB Avg: ");
+ s.m_best_etc1s_rgb_avg_psnr = static_cast<float>(em.m_psnr);
+
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0);
+ em.print("Unquantized ETC1S 709 Luma: ");
+ s.m_best_etc1s_luma_709_psnr = static_cast<float>(em.m_psnr);
+ s.m_best_etc1s_luma_709_ssim = static_cast<float>(em.m_ssim);
+
+ em.calc(m_slice_images[slice_index], m_best_etc1s_images_unpacked[slice_index], 0, 0, true, true);
+ em.print("Unquantized ETC1S 601 Luma: ");
+ s.m_best_etc1s_luma_601_psnr = static_cast<float>(em.m_psnr);
+ }
}
- }
-
- std::string out_basename;
- if (m_params.m_out_filename.size())
- string_get_filename(m_params.m_out_filename.c_str(), out_basename);
- else if (m_params.m_source_filenames.size())
- string_get_filename(m_params.m_source_filenames[slice_desc.m_source_file_index].c_str(), out_basename);
- string_remove_extension(out_basename);
- out_basename = "basis_debug_" + out_basename + string_format("_slice_%u", slice_index);
+ std::string out_basename;
+ if (m_params.m_out_filename.size())
+ string_get_filename(m_params.m_out_filename.c_str(), out_basename);
+ else if (m_params.m_source_filenames.size())
+ string_get_filename(m_params.m_source_filenames[slice_desc.m_source_file_index].c_str(), out_basename);
- if ((!m_params.m_uastc) && (m_frontend.get_params().m_debug_images))
- {
- // Write "best" ETC1S debug images
- if (!m_params.m_uastc)
+ string_remove_extension(out_basename);
+ out_basename = "basis_debug_" + out_basename + string_format("_slice_%u", slice_index);
+
+ if ((!m_params.m_uastc) && (m_frontend.get_params().m_debug_images))
{
- gpu_image best_etc1s_gpu_image(m_best_etc1s_images[slice_index]);
- best_etc1s_gpu_image.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
- write_compressed_texture_file((out_basename + "_best_etc1s.ktx").c_str(), best_etc1s_gpu_image);
+ // Write "best" ETC1S debug images
+ if (!m_params.m_uastc)
+ {
+ gpu_image best_etc1s_gpu_image(m_best_etc1s_images[slice_index]);
+ best_etc1s_gpu_image.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_best_etc1s.ktx").c_str(), best_etc1s_gpu_image);
- image best_etc1s_unpacked;
- best_etc1s_gpu_image.unpack(best_etc1s_unpacked);
- save_png(out_basename + "_best_etc1s.png", best_etc1s_unpacked);
+ image best_etc1s_unpacked;
+ best_etc1s_gpu_image.unpack(best_etc1s_unpacked);
+ save_png(out_basename + "_best_etc1s.png", best_etc1s_unpacked);
+ }
}
- }
- if (m_params.m_debug_images)
- {
- // Write decoded ETC1S/ASTC debug images
+ if (m_params.m_debug_images)
{
- gpu_image decoded_etc1s_or_astc(m_decoded_output_textures[slice_index]);
- decoded_etc1s_or_astc.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
- write_compressed_texture_file((out_basename + "_transcoded_etc1s_or_astc.ktx").c_str(), decoded_etc1s_or_astc);
+ // Write decoded ETC1S/ASTC debug images
+ {
+ gpu_image decoded_etc1s_or_astc(m_decoded_output_textures[slice_index]);
+ decoded_etc1s_or_astc.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_transcoded_etc1s_or_astc.ktx").c_str(), decoded_etc1s_or_astc);
- image temp(m_decoded_output_textures_unpacked[slice_index]);
- temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
- save_png(out_basename + "_transcoded_etc1s_or_astc.png", temp);
- }
+ image temp(m_decoded_output_textures_unpacked[slice_index]);
+ temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ save_png(out_basename + "_transcoded_etc1s_or_astc.png", temp);
+ }
- // Write decoded BC7 debug images
- if (m_decoded_output_textures_bc7[slice_index].get_pixel_width())
- {
- gpu_image decoded_bc7(m_decoded_output_textures_bc7[slice_index]);
- decoded_bc7.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
- write_compressed_texture_file((out_basename + "_transcoded_bc7.ktx").c_str(), decoded_bc7);
+ // Write decoded BC7 debug images
+ if (m_decoded_output_textures_bc7[slice_index].get_pixel_width())
+ {
+ gpu_image decoded_bc7(m_decoded_output_textures_bc7[slice_index]);
+ decoded_bc7.override_dimensions(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ write_compressed_texture_file((out_basename + "_transcoded_bc7.ktx").c_str(), decoded_bc7);
- image temp(m_decoded_output_textures_unpacked_bc7[slice_index]);
- temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
- save_png(out_basename + "_transcoded_bc7.png", temp);
+ image temp(m_decoded_output_textures_unpacked_bc7[slice_index]);
+ temp.crop(slice_desc.m_orig_width, slice_desc.m_orig_height);
+ save_png(out_basename + "_transcoded_bc7.png", temp);
+ }
}
}
- }
+ } // if (m_params.m_validate_output_data)
return true;
}
@@ -2116,4 +2140,252 @@ namespace basisu
return true;
}
+ bool basis_parallel_compress(
+ uint32_t total_threads,
+ const basisu::vector<basis_compressor_params>& params_vec,
+ basisu::vector< parallel_results >& results_vec)
+ {
+ assert(g_library_initialized);
+ if (!g_library_initialized)
+ {
+ error_printf("basis_parallel_compress: basisu_encoder_init() MUST be called before using any encoder functionality!\n");
+ return false;
+ }
+
+ assert(total_threads >= 1);
+ total_threads = basisu::maximum<uint32_t>(total_threads, 1);
+
+ job_pool jpool(total_threads);
+
+ results_vec.resize(0);
+ results_vec.resize(params_vec.size());
+
+ std::atomic<bool> result;
+ result = true;
+
+ std::atomic<bool> opencl_failed;
+ opencl_failed = false;
+
+ for (uint32_t pindex = 0; pindex < params_vec.size(); pindex++)
+ {
+ jpool.add_job([pindex, &params_vec, &results_vec, &result, &opencl_failed] {
+
+ basis_compressor_params params = params_vec[pindex];
+ parallel_results& results = results_vec[pindex];
+
+ interval_timer tm;
+ tm.start();
+
+ basis_compressor c;
+
+ // Dummy job pool
+ job_pool task_jpool(1);
+ params.m_pJob_pool = &task_jpool;
+ // TODO: Remove this flag entirely
+ params.m_multithreading = true;
+
+ // Stop using OpenCL if a failure ever occurs.
+ if (opencl_failed)
+ params.m_use_opencl = false;
+
+ bool status = c.init(params);
+
+ if (c.get_opencl_failed())
+ opencl_failed = true;
+
+ if (status)
+ {
+ basis_compressor::error_code ec = c.process();
+
+ if (c.get_opencl_failed())
+ opencl_failed = true;
+
+ results.m_error_code = ec;
+
+ if (ec == basis_compressor::cECSuccess)
+ {
+ results.m_basis_file = c.get_output_basis_file();
+ results.m_ktx2_file = c.get_output_ktx2_file();
+ results.m_stats = c.get_stats();
+ results.m_basis_bits_per_texel = c.get_basis_bits_per_texel();
+ results.m_any_source_image_has_alpha = c.get_any_source_image_has_alpha();
+ }
+ else
+ {
+ result = false;
+ }
+ }
+ else
+ {
+ results.m_error_code = basis_compressor::cECFailedInitializing;
+
+ result = false;
+ }
+
+ results.m_total_time = tm.get_elapsed_secs();
+ } );
+
+ } // pindex
+
+ jpool.wait_for_all();
+
+ if (opencl_failed)
+ error_printf("An OpenCL error occured sometime during compression. The compressor fell back to CPU processing after the failure.\n");
+
+ return result;
+ }
+
+ void* basis_compress(
+ const basisu::vector<image>& source_images,
+ uint32_t flags_and_quality, float uastc_rdo_quality,
+ size_t* pSize,
+ image_stats* pStats)
+ {
+ // Check input parameters
+ if ((!source_images.size()) || (!pSize))
+ {
+ error_printf("basis_compress: Invalid parameter\n");
+ assert(0);
+ return nullptr;
+ }
+
+ *pSize = 0;
+
+ // Initialize a job pool
+ uint32_t num_threads = 1;
+ if (flags_and_quality & cFlagThreaded)
+ num_threads = basisu::maximum<uint32_t>(1, std::thread::hardware_concurrency());
+
+ job_pool jp(num_threads);
+
+ // Initialize the compressor parameter struct
+ basis_compressor_params comp_params;
+ comp_params.m_pJob_pool = &jp;
+
+ comp_params.m_y_flip = (flags_and_quality & cFlagYFlip) != 0;
+ comp_params.m_debug = (flags_and_quality & cFlagDebug) != 0;
+
+ // Copy the largest mipmap level
+ comp_params.m_source_images.resize(1);
+ comp_params.m_source_images[0] = source_images[0];
+
+ // Copy the smaller mipmap levels, if any
+ if (source_images.size() > 1)
+ {
+ comp_params.m_source_mipmap_images.resize(1);
+ comp_params.m_source_mipmap_images[0].resize(source_images.size() - 1);
+
+ for (uint32_t i = 1; i < source_images.size(); i++)
+ comp_params.m_source_mipmap_images[0][i - 1] = source_images[i];
+ }
+
+ comp_params.m_multithreading = (flags_and_quality & cFlagThreaded) != 0;
+ comp_params.m_use_opencl = (flags_and_quality & cFlagUseOpenCL) != 0;
+
+ comp_params.m_write_output_basis_files = false;
+
+ comp_params.m_perceptual = (flags_and_quality & cFlagSRGB) != 0;
+ comp_params.m_mip_srgb = comp_params.m_perceptual;
+ comp_params.m_mip_gen = (flags_and_quality & (cFlagGenMipsWrap | cFlagGenMipsClamp)) != 0;
+ comp_params.m_mip_wrapping = (flags_and_quality & cFlagGenMipsWrap) != 0;
+
+ comp_params.m_uastc = (flags_and_quality & cFlagUASTC) != 0;
+ if (comp_params.m_uastc)
+ {
+ comp_params.m_pack_uastc_flags = flags_and_quality & cPackUASTCLevelMask;
+ comp_params.m_rdo_uastc = (flags_and_quality & cFlagUASTCRDO) != 0;
+ comp_params.m_rdo_uastc_quality_scalar = uastc_rdo_quality;
+ }
+ else
+ comp_params.m_quality_level = basisu::maximum<uint32_t>(1, flags_and_quality & 255);
+
+ comp_params.m_create_ktx2_file = (flags_and_quality & cFlagKTX2) != 0;
+
+ if (comp_params.m_create_ktx2_file)
+ {
+ // Set KTX2 specific parameters.
+ if ((flags_and_quality & cFlagKTX2UASTCSuperCompression) && (comp_params.m_uastc))
+ comp_params.m_ktx2_uastc_supercompression = basist::KTX2_SS_ZSTANDARD;
+
+ comp_params.m_ktx2_srgb_transfer_func = comp_params.m_perceptual;
+ }
+
+ comp_params.m_compute_stats = (pStats != nullptr);
+
+ // Create the compressor, initialize it, and process the input
+ basis_compressor comp;
+ if (!comp.init(comp_params))
+ {
+ error_printf("basis_compress: basis_compressor::init() failed!\n");
+ return nullptr;
+ }
+
+ basis_compressor::error_code ec = comp.process();
+
+ if (ec != basis_compressor::cECSuccess)
+ {
+ error_printf("basis_compress: basis_compressor::process() failed with error code %u\n", (uint32_t)ec);
+ return nullptr;
+ }
+
+ // Get the output file data and return it to the caller
+ void* pFile_data = nullptr;
+ const uint8_vec* pFile_data_vec = comp_params.m_create_ktx2_file ? &comp.get_output_ktx2_file() : &comp.get_output_basis_file();
+
+ pFile_data = malloc(pFile_data_vec->size());
+ if (!pFile_data)
+ {
+ error_printf("basis_compress: Out of memory\n");
+ return nullptr;
+ }
+ memcpy(pFile_data, pFile_data_vec->get_ptr(), pFile_data_vec->size());
+
+ *pSize = pFile_data_vec->size();
+
+ if ((pStats) && (comp.get_stats().size()))
+ {
+ *pStats = comp.get_stats()[0];
+ }
+
+ return pFile_data;
+ }
+
+ void* basis_compress(
+ const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
+ uint32_t flags_and_quality, float uastc_rdo_quality,
+ size_t* pSize,
+ image_stats* pStats)
+ {
+ if (!pitch_in_pixels)
+ pitch_in_pixels = width;
+
+ if ((!pImageRGBA) || (!width) || (!height) || (pitch_in_pixels < width) || (!pSize))
+ {
+ error_printf("basis_compress: Invalid parameter\n");
+ assert(0);
+ return nullptr;
+ }
+
+ *pSize = 0;
+
+ if ((width > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION) || (height > BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION))
+ {
+ error_printf("basis_compress: Image too large\n");
+ return nullptr;
+ }
+
+ // Copy the source image
+ basisu::vector<image> source_image(1);
+ source_image[0].crop(width, height, width, g_black_color, false);
+ for (uint32_t y = 0; y < height; y++)
+ memcpy(source_image[0].get_ptr() + y * width, (const color_rgba*)pImageRGBA + y * pitch_in_pixels, width * sizeof(color_rgba));
+
+ return basis_compress(source_image, flags_and_quality, uastc_rdo_quality, pSize, pStats);
+ }
+
+ void basis_free_data(void* p)
+ {
+ free(p);
+ }
+
} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.h b/thirdparty/basis_universal/encoder/basisu_comp.h
index 2c3af968f7..aa5ea6fec3 100644
--- a/thirdparty/basis_universal/encoder/basisu_comp.h
+++ b/thirdparty/basis_universal/encoder/basisu_comp.h
@@ -16,12 +16,11 @@
#include "basisu_frontend.h"
#include "basisu_backend.h"
#include "basisu_basis_file.h"
-#include "../transcoder/basisu_global_selector_palette.h"
#include "../transcoder/basisu_transcoder.h"
#include "basisu_uastc_enc.h"
-#define BASISU_LIB_VERSION 115
-#define BASISU_LIB_VERSION_STRING "1.15"
+#define BASISU_LIB_VERSION 116
+#define BASISU_LIB_VERSION_STRING "1.16"
#ifndef BASISD_SUPPORT_KTX2
#error BASISD_SUPPORT_KTX2 is undefined
@@ -36,6 +35,9 @@
namespace basisu
{
+ struct opencl_context;
+ typedef opencl_context* opencl_context_ptr;
+
const uint32_t BASISU_MAX_SUPPORTED_TEXTURE_DIMENSION = 16384;
// Allow block's color distance to increase by 1.5 while searching for an alternative nearby endpoint.
@@ -203,13 +205,9 @@ namespace basisu
struct basis_compressor_params
{
basis_compressor_params() :
- m_pSel_codebook(NULL),
m_compression_level((int)BASISU_DEFAULT_COMPRESSION_LEVEL, 0, (int)BASISU_MAX_COMPRESSION_LEVEL),
m_selector_rdo_thresh(BASISU_DEFAULT_SELECTOR_RDO_THRESH, 0.0f, 1e+10f),
m_endpoint_rdo_thresh(BASISU_DEFAULT_ENDPOINT_RDO_THRESH, 0.0f, 1e+10f),
- m_hybrid_sel_cb_quality_thresh(BASISU_DEFAULT_HYBRID_SEL_CB_QUALITY_THRESH, 0.0f, 1e+10f),
- m_global_pal_bits(8, 0, ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS),
- m_global_mod_bits(8, 0, basist::etc1_global_palette_entry_modifier::cTotalBits),
m_mip_scale(1.0f, .000125f, 4.0f),
m_mip_smallest_dimension(1, 1, 16384),
m_max_endpoint_clusters(512),
@@ -234,9 +232,8 @@ namespace basisu
void clear()
{
- m_pSel_codebook = NULL;
-
m_uastc.clear();
+ m_use_opencl.clear();
m_status_output.clear();
m_source_filenames.clear();
@@ -249,11 +246,8 @@ namespace basisu
m_y_flip.clear();
m_debug.clear();
- m_validate.clear();
+ m_validate_etc1s.clear();
m_debug_images.clear();
- m_global_sel_pal.clear();
- m_auto_global_sel_pal.clear();
- m_no_hybrid_sel_cb.clear();
m_perceptual.clear();
m_no_selector_rdo.clear();
m_selector_rdo_thresh.clear();
@@ -269,9 +263,6 @@ namespace basisu
m_swizzle[2] = 2;
m_swizzle[3] = 3;
m_renormalize.clear();
- m_hybrid_sel_cb_quality_thresh.clear();
- m_global_pal_bits.clear();
- m_global_mod_bits.clear();
m_disable_hierarchical_endpoint_codebooks.clear();
m_no_endpoint_rdo.clear();
@@ -319,15 +310,16 @@ namespace basisu
m_ktx2_zstd_supercompression_level.clear();
m_ktx2_srgb_transfer_func.clear();
+ m_validate_output_data.clear();
+
m_pJob_pool = nullptr;
}
-
- // Pointer to the global selector codebook, or nullptr to not use a global selector codebook
- const basist::etc1_global_selector_codebook *m_pSel_codebook;
-
+
// True to generate UASTC .basis file data, otherwise ETC1S.
bool_param<false> m_uastc;
+ bool_param<false> m_use_opencl;
+
// If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG images to read.
// Otherwise, the compressor processes the images in m_source_images.
basisu::vector<std::string> m_source_filenames;
@@ -353,20 +345,16 @@ namespace basisu
// Output debug information during compression
bool_param<false> m_debug;
- bool_param<false> m_validate;
+ bool_param<false> m_validate_etc1s;
// m_debug_images is pretty slow
bool_param<false> m_debug_images;
- // Compression level, from 0 to BASISU_MAX_COMPRESSION_LEVEL (higher is slower)
+ // ETC1S compression level, from 0 to BASISU_MAX_COMPRESSION_LEVEL (higher is slower).
+ // This parameter controls numerous internal encoding speed vs. compression efficiency/performance tradeoffs.
+ // Note this is NOT the same as the ETC1S quality level, and most users shouldn't change this.
param<int> m_compression_level;
-
- bool_param<false> m_global_sel_pal;
- bool_param<false> m_auto_global_sel_pal;
-
- // Frontend/backend codec parameters
- bool_param<false> m_no_hybrid_sel_cb;
-
+
// Use perceptual sRGB colorspace metrics instead of linear
bool_param<true> m_perceptual;
@@ -398,13 +386,10 @@ namespace basisu
bool_param<false> m_renormalize;
+ // If true the front end will not use 2 level endpoint codebook searching, for slightly higher quality but much slower execution.
+ // Note some m_compression_level's disable this automatically.
bool_param<false> m_disable_hierarchical_endpoint_codebooks;
-
- // Global/hybrid selector codebook parameters
- param<float> m_hybrid_sel_cb_quality_thresh;
- param<int> m_global_pal_bits;
- param<int> m_global_mod_bits;
-
+
// mipmap generation parameters
bool_param<false> m_mip_gen;
param<float> m_mip_scale;
@@ -415,9 +400,9 @@ namespace basisu
bool_param<true> m_mip_wrapping;
bool_param<true> m_mip_fast;
param<int> m_mip_smallest_dimension;
-
+
// Codebook size (quality) control.
- // If m_quality_level != -1, it controls the quality level. It ranges from [0,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
+ // If m_quality_level != -1, it controls the quality level. It ranges from [1,255] or [BASISU_QUALITY_MIN, BASISU_QUALITY_MAX].
// Otherwise m_max_endpoint_clusters/m_max_selector_clusters controls the codebook sizes directly.
uint32_t m_max_endpoint_clusters;
uint32_t m_max_selector_clusters;
@@ -444,6 +429,7 @@ namespace basisu
param<int> m_resample_width;
param<int> m_resample_height;
param<float> m_resample_factor;
+
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
// KTX2 specific parameters.
@@ -454,21 +440,27 @@ namespace basisu
param<int> m_ktx2_zstd_supercompression_level;
bool_param<false> m_ktx2_srgb_transfer_func;
+ bool_param<false> m_validate_output_data;
+
job_pool *m_pJob_pool;
};
-
+
+ // Important: basisu_encoder_init() MUST be called first before using this class.
class basis_compressor
{
BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(basis_compressor);
public:
basis_compressor();
+ ~basis_compressor();
+ // Note it *should* be possible to call init() multiple times with different inputs, but this scenario isn't well tested. Ideally, create 1 object, compress, then delete it.
bool init(const basis_compressor_params &params);
enum error_code
{
cECSuccess = 0,
+ cECFailedInitializing,
cECFailedReadingSourceImages,
cECFailedValidating,
cECFailedEncodeUASTC,
@@ -495,9 +487,13 @@ namespace basisu
double get_basis_bits_per_texel() const { return m_basis_bits_per_texel; }
bool get_any_source_image_has_alpha() const { return m_any_source_image_has_alpha; }
+
+ bool get_opencl_failed() const { return m_opencl_failed; }
private:
basis_compressor_params m_params;
+
+ opencl_context_ptr m_pOpenCL_context;
basisu::vector<image> m_slice_images;
@@ -509,8 +505,7 @@ namespace basisu
basisu_backend_slice_desc_vec m_slice_descs;
uint32_t m_total_blocks;
- bool m_auto_global_sel_pal;
-
+
basisu_frontend m_frontend;
pixel_block_vec m_source_blocks;
@@ -536,6 +531,8 @@ namespace basisu
bool m_any_source_image_has_alpha;
+ bool m_opencl_failed;
+
bool read_source_images();
bool extract_source_blocks();
bool process_frontend();
@@ -550,6 +547,98 @@ namespace basisu
void get_dfd(uint8_vec& dfd, const basist::ktx2_header& hdr);
bool create_ktx2_file();
};
+
+ // Alternative simple C-style wrapper API around the basis_compressor class.
+ // This doesn't expose every encoder feature, but it's enough to get going.
+ // Important: basisu_encoder_init() MUST be called first before calling these functions.
+ //
+ // Input parameters:
+ // source_images: Array of "image" objects, one per mipmap level, largest mipmap level first.
+ // OR
+ // pImageRGBA: pointer to a 32-bpp RGBx or RGBA raster image, R first in memory, A last. Top scanline first in memory.
+ // width/height/pitch_in_pixels: dimensions of pImageRGBA
+ //
+ // flags_and_quality: Combination of the above flags logically OR'd with the ETC1S or UASTC level, i.e. "cFlagSRGB | cFlagGenMipsClamp | cFlagThreaded | 128" or "cFlagSRGB | cFlagGenMipsClamp | cFlagUASTC | cFlagThreaded | cPackUASTCLevelDefault".
+ // In ETC1S mode, the lower 8-bits are the ETC1S quality level which ranges from [1,255] (higher=better quality/larger files)
+ // In UASTC mode, the lower 8-bits are the UASTC pack level (see cPackUASTCLevelFastest, etc.). Fastest/lowest quality is 0, so be sure to set it correctly.
+ //
+ // uastc_rdo_quality: Float UASTC RDO quality level (0=no change, higher values lower quality but increase compressibility, initially try .5-1.5)
+ //
+ // pSize: Returns the output data's compressed size in bytes
+ //
+ // Return value is the compressed .basis or .ktx2 file data, or nullptr on failure. Must call basis_free() to free it.
+ enum
+ {
+ cFlagUseOpenCL = 1 << 8, // use OpenCL if available
+ cFlagThreaded = 1 << 9, // use multiple threads for compression
+ cFlagDebug = 1 << 10, // enable debug output
+
+ cFlagKTX2 = 1 << 11, // generate a KTX2 file
+ cFlagKTX2UASTCSuperCompression = 1 << 12, // use KTX2 Zstd supercompression on UASTC files
+
+ cFlagSRGB = 1 << 13, // input texture is sRGB, use perceptual colorspace metrics, also use sRGB filtering during mipmap gen, and also sets KTX2 output transfer func to sRGB
+ cFlagGenMipsClamp = 1 << 14, // generate mipmaps with clamp addressing
+ cFlagGenMipsWrap = 1 << 15, // generate mipmaps with wrap addressing
+
+ cFlagYFlip = 1 << 16, // flip source image on Y axis before compression
+
+ cFlagUASTC = 1 << 17, // use UASTC compression vs. ETC1S
+ cFlagUASTCRDO = 1 << 18 // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
+ };
+ // This function accepts an array of source images.
+ // If more than one image is provided, it's assumed the images form a mipmap pyramid and automatic mipmap generation is disabled.
+ void* basis_compress(
+ const basisu::vector<image> &source_images,
+ uint32_t flags_and_quality, float uastc_rdo_quality,
+ size_t* pSize,
+ image_stats* pStats = nullptr);
+
+ // This function only accepts a single source image.
+ void* basis_compress(
+ const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
+ uint32_t flags_and_quality, float uastc_rdo_quality,
+ size_t* pSize,
+ image_stats* pStats = nullptr);
+
+ // Frees the dynamically allocated file data returned by basis_compress().
+ void basis_free_data(void* p);
+
+ // Parallel compression API
+ struct parallel_results
+ {
+ double m_total_time;
+ basis_compressor::error_code m_error_code;
+ uint8_vec m_basis_file;
+ uint8_vec m_ktx2_file;
+ basisu::vector<image_stats> m_stats;
+ double m_basis_bits_per_texel;
+ bool m_any_source_image_has_alpha;
+
+ parallel_results()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ m_total_time = 0.0f;
+ m_error_code = basis_compressor::cECFailedInitializing;
+ m_basis_file.clear();
+ m_ktx2_file.clear();
+ m_stats.clear();
+ m_basis_bits_per_texel = 0.0f;
+ m_any_source_image_has_alpha = false;
+ }
+ };
+
+ // Compresses an array of input textures across total_threads threads using the basis_compressor class.
+ // Compressing multiple textures at a time is substantially more efficient than just compressing one at a time.
+ // total_threads must be >= 1.
+ bool basis_parallel_compress(
+ uint32_t total_threads,
+ const basisu::vector<basis_compressor_params> &params_vec,
+ basisu::vector< parallel_results > &results_vec);
+
} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
index daaf65badc..b427215ee3 100644
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
@@ -13,16 +13,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "basisu_enc.h"
-#include "lodepng.h"
#include "basisu_resampler.h"
#include "basisu_resampler_filters.h"
#include "basisu_etc.h"
#include "../transcoder/basisu_transcoder.h"
#include "basisu_bc7enc.h"
-#include "apg_bmp.h"
#include "jpgd.h"
+#include "pvpngreader.h"
+#include "basisu_opencl.h"
#include <vector>
+#define MINIZ_HEADER_FILE_ONLY
+#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+#include "basisu_miniz.h"
+
#if defined(_WIN32)
// For QueryPerformanceCounter/QueryPerformanceFrequency
#define WIN32_LEAN_AND_MEAN
@@ -158,34 +162,62 @@ namespace basisu
{ 0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // U+007E (~)
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // U+007F
};
-
+
+ bool g_library_initialized;
+ std::mutex g_encoder_init_mutex;
+
// Encoder library initialization (just call once at startup)
- void basisu_encoder_init()
+ void basisu_encoder_init(bool use_opencl, bool opencl_force_serialization)
{
+ std::lock_guard<std::mutex> lock(g_encoder_init_mutex);
+
+ if (g_library_initialized)
+ return;
+
detect_sse41();
basist::basisu_transcoder_init();
pack_etc1_solid_color_init();
//uastc_init();
bc7enc_compress_block_init(); // must be after uastc_init()
+
+ // Don't bother initializing the OpenCL module at all if it's been completely disabled.
+ if (use_opencl)
+ {
+ opencl_init(opencl_force_serialization);
+ }
+
+ g_library_initialized = true;
}
- void error_printf(const char *pFmt, ...)
+ void basisu_encoder_deinit()
{
- char buf[2048];
+ opencl_deinit();
+
+ g_library_initialized = false;
+ }
+
+ void error_vprintf(const char* pFmt, va_list args)
+ {
+ char buf[8192];
- va_list args;
- va_start(args, pFmt);
#ifdef _WIN32
vsprintf_s(buf, sizeof(buf), pFmt, args);
#else
vsnprintf(buf, sizeof(buf), pFmt, args);
#endif
- va_end(args);
fprintf(stderr, "ERROR: %s", buf);
}
+ void error_printf(const char *pFmt, ...)
+ {
+ va_list args;
+ va_start(args, pFmt);
+ error_vprintf(pFmt, args);
+ va_end(args);
+ }
+
#if defined(_WIN32)
inline void query_counter(timer_ticks* pTicks)
{
@@ -195,7 +227,7 @@ namespace basisu
{
QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(pTicks));
}
-#elif defined(__APPLE__) || defined(__OpenBSD__)
+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#include <sys/time.h>
inline void query_counter(timer_ticks* pTicks)
{
@@ -284,59 +316,6 @@ namespace basisu
}
const uint32_t MAX_32BIT_ALLOC_SIZE = 250000000;
-
- bool load_bmp(const char* pFilename, image& img)
- {
- int w = 0, h = 0;
- unsigned int n_chans = 0;
- unsigned char* pImage_data = apg_bmp_read(pFilename, &w, &h, &n_chans);
-
- if ((!pImage_data) || (!w) || (!h) || ((n_chans != 3) && (n_chans != 4)))
- {
- error_printf("Failed loading .BMP image \"%s\"!\n", pFilename);
-
- if (pImage_data)
- apg_bmp_free(pImage_data);
-
- return false;
- }
-
- if (sizeof(void *) == sizeof(uint32_t))
- {
- if ((w * h * n_chans) > MAX_32BIT_ALLOC_SIZE)
- {
- error_printf("Image \"%s\" is too large (%ux%u) to process in a 32-bit build!\n", pFilename, w, h);
-
- if (pImage_data)
- apg_bmp_free(pImage_data);
-
- return false;
- }
- }
-
- img.resize(w, h);
-
- const uint8_t *pSrc = pImage_data;
- for (int y = 0; y < h; y++)
- {
- color_rgba *pDst = &img(0, y);
-
- for (int x = 0; x < w; x++)
- {
- pDst->r = pSrc[0];
- pDst->g = pSrc[1];
- pDst->b = pSrc[2];
- pDst->a = (n_chans == 3) ? 255 : pSrc[3];
-
- pSrc += n_chans;
- ++pDst;
- }
- }
-
- apg_bmp_free(pImage_data);
-
- return true;
- }
bool load_tga(const char* pFilename, image& img)
{
@@ -392,53 +371,35 @@ namespace basisu
bool load_png(const uint8_t *pBuf, size_t buf_size, image &img, const char *pFilename)
{
+ interval_timer tm;
+ tm.start();
+
if (!buf_size)
return false;
- unsigned err = 0, w = 0, h = 0;
-
- if (sizeof(void*) == sizeof(uint32_t))
+ uint32_t width = 0, height = 0, num_chans = 0;
+ void* pImage = pv_png::load_png(pBuf, buf_size, 4, width, height, num_chans);
+ if (!pBuf)
{
- // Inspect the image first on 32-bit builds, to see if the image would require too much memory.
- lodepng::State state;
- err = lodepng_inspect(&w, &h, &state, pBuf, buf_size);
- if ((err != 0) || (!w) || (!h))
- return false;
-
- const uint32_t exepected_alloc_size = w * h * sizeof(uint32_t);
-
- // If the file is too large on 32-bit builds then just bail now, to prevent causing a memory exception.
- if (exepected_alloc_size >= MAX_32BIT_ALLOC_SIZE)
- {
- error_printf("Image \"%s\" is too large (%ux%u) to process in a 32-bit build!\n", (pFilename != nullptr) ? pFilename : "<memory>", w, h);
- return false;
- }
-
- w = h = 0;
- }
-
- std::vector<uint8_t> out;
- err = lodepng::decode(out, w, h, pBuf, buf_size);
- if ((err != 0) || (!w) || (!h))
- return false;
-
- if (out.size() != (w * h * 4))
+ error_printf("pv_png::load_png failed while loading image \"%s\"\n", pFilename);
return false;
+ }
- img.resize(w, h);
+ img.grant_ownership(reinterpret_cast<color_rgba*>(pImage), width, height);
- memcpy(img.get_ptr(), &out[0], out.size());
+ //debug_printf("Total load_png() time: %3.3f secs\n", tm.get_elapsed_secs());
return true;
}
bool load_png(const char* pFilename, image& img)
{
- std::vector<uint8_t> buffer;
- unsigned err = lodepng::load_file(buffer, std::string(pFilename));
- if (err)
+ uint8_vec buffer;
+ if (!read_file_to_vec(pFilename, buffer))
+ {
+ error_printf("load_png: Failed reading file \"%s\"!\n", pFilename);
return false;
-
+ }
return load_png(buffer.data(), buffer.size(), img, pFilename);
}
@@ -468,8 +429,6 @@ namespace basisu
if (strcasecmp(pExt, "png") == 0)
return load_png(pFilename, img);
- if (strcasecmp(pExt, "bmp") == 0)
- return load_bmp(pFilename, img);
if (strcasecmp(pExt, "tga") == 0)
return load_tga(pFilename, img);
if ( (strcasecmp(pExt, "jpg") == 0) || (strcasecmp(pExt, "jfif") == 0) || (strcasecmp(pExt, "jpeg") == 0) )
@@ -482,61 +441,67 @@ namespace basisu
{
if (!img.get_total_pixels())
return false;
-
- const uint32_t MAX_PNG_IMAGE_DIM = 32768;
- if ((img.get_width() > MAX_PNG_IMAGE_DIM) || (img.get_height() > MAX_PNG_IMAGE_DIM))
- return false;
-
- std::vector<uint8_t> out;
- unsigned err = 0;
+ void* pPNG_data = nullptr;
+ size_t PNG_data_size = 0;
+
if (image_save_flags & cImageSaveGrayscale)
{
- uint8_vec g_pixels(img.get_width() * img.get_height());
- uint8_t *pDst = &g_pixels[0];
+ uint8_vec g_pixels(img.get_total_pixels());
+ uint8_t* pDst = &g_pixels[0];
for (uint32_t y = 0; y < img.get_height(); y++)
for (uint32_t x = 0; x < img.get_width(); x++)
*pDst++ = img(x, y)[grayscale_comp];
- err = lodepng::encode(out, (const uint8_t*)&g_pixels[0], img.get_width(), img.get_height(), LCT_GREY, 8);
+ pPNG_data = buminiz::tdefl_write_image_to_png_file_in_memory_ex(g_pixels.data(), img.get_width(), img.get_height(), 1, &PNG_data_size, 1, false);
}
else
{
- bool has_alpha = img.has_alpha();
- if ((!has_alpha) || ((image_save_flags & cImageSaveIgnoreAlpha) != 0))
+ bool has_alpha = false;
+
+ if ((image_save_flags & cImageSaveIgnoreAlpha) == 0)
+ has_alpha = img.has_alpha();
+
+ if (!has_alpha)
{
- const uint64_t total_bytes = (uint64_t)img.get_width() * 3U * (uint64_t)img.get_height();
- if (total_bytes > INT_MAX)
- return false;
- uint8_vec rgb_pixels(static_cast<size_t>(total_bytes));
- uint8_t *pDst = &rgb_pixels[0];
-
+ uint8_vec rgb_pixels(img.get_total_pixels() * 3);
+ uint8_t* pDst = &rgb_pixels[0];
+
for (uint32_t y = 0; y < img.get_height(); y++)
{
+ const color_rgba* pSrc = &img(0, y);
for (uint32_t x = 0; x < img.get_width(); x++)
{
- const color_rgba& c = img(x, y);
- pDst[0] = c.r;
- pDst[1] = c.g;
- pDst[2] = c.b;
+ pDst[0] = pSrc->r;
+ pDst[1] = pSrc->g;
+ pDst[2] = pSrc->b;
+
+ pSrc++;
pDst += 3;
}
}
- err = lodepng::encode(out, (const uint8_t*)& rgb_pixels[0], img.get_width(), img.get_height(), LCT_RGB, 8);
+ pPNG_data = buminiz::tdefl_write_image_to_png_file_in_memory_ex(rgb_pixels.data(), img.get_width(), img.get_height(), 3, &PNG_data_size, 1, false);
}
else
{
- err = lodepng::encode(out, (const uint8_t*)img.get_ptr(), img.get_width(), img.get_height(), LCT_RGBA, 8);
+ pPNG_data = buminiz::tdefl_write_image_to_png_file_in_memory_ex(img.get_ptr(), img.get_width(), img.get_height(), 4, &PNG_data_size, 1, false);
}
}
- err = lodepng::save_file(out, std::string(pFilename));
- if (err)
+ if (!pPNG_data)
return false;
- return true;
+ bool status = write_data_to_file(pFilename, pPNG_data, PNG_data_size);
+ if (!status)
+ {
+ error_printf("save_png: Failed writing to filename \"%s\"!\n", pFilename);
+ }
+
+ free(pPNG_data);
+
+ return status;
}
bool read_file_to_vec(const char* pFilename, uint8_vec& data)
@@ -1620,7 +1585,8 @@ namespace basisu
void job_pool::job_thread(uint32_t index)
{
- debug_printf("job_pool::job_thread: starting %u\n", index);
+ BASISU_NOTE_UNUSED(index);
+ //debug_printf("job_pool::job_thread: starting %u\n", index);
while (true)
{
@@ -1656,7 +1622,7 @@ namespace basisu
m_no_more_jobs.notify_all();
}
- debug_printf("job_pool::job_thread: exiting\n");
+ //debug_printf("job_pool::job_thread: exiting\n");
}
// .TGA image loading
@@ -1779,6 +1745,8 @@ namespace basisu
return nullptr;
}
+ //const uint32_t bytes_per_line = hdr.m_width * tga_bytes_per_pixel;
+
const uint8_t *pSrc = pBuf + sizeof(tga_header);
uint32_t bytes_remaining = buf_size - sizeof(tga_header);
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.h b/thirdparty/basis_universal/encoder/basisu_enc.h
index 0ce011452d..0efeaa461f 100644
--- a/thirdparty/basis_universal/encoder/basisu_enc.h
+++ b/thirdparty/basis_universal/encoder/basisu_enc.h
@@ -33,14 +33,23 @@
// If BASISU_USE_HIGH_PRECISION_COLOR_DISTANCE is 1, quality in perceptual mode will be slightly greater, but at a large increase in encoding CPU time.
#define BASISU_USE_HIGH_PRECISION_COLOR_DISTANCE (0)
+#if BASISU_SUPPORT_SSE
+// Declared in basisu_kernels_imp.h, but we can't include that here otherwise it would lead to circular type errors.
+extern void update_covar_matrix_16x16_sse41(uint32_t num_vecs, const void* pWeighted_vecs, const void* pOrigin, const uint32_t *pVec_indices, void* pMatrix16x16);
+#endif
+
namespace basisu
{
extern uint8_t g_hamming_dist[256];
extern const uint8_t g_debug_font8x8_basic[127 - 32 + 1][8];
+ // true if basisu_encoder_init() has been called and returned.
+ extern bool g_library_initialized;
+
// Encoder library initialization.
// This function MUST be called before encoding anything!
- void basisu_encoder_init();
+ void basisu_encoder_init(bool use_opencl = false, bool opencl_force_serialization = false);
+ void basisu_encoder_deinit();
// basisu_kernels_sse.cpp - will be a no-op and g_cpu_supports_sse41 will always be false unless compiled with BASISU_SUPPORT_SSE=1
extern void detect_sse41();
@@ -51,8 +60,9 @@ namespace basisu
const bool g_cpu_supports_sse41 = false;
#endif
+ void error_vprintf(const char* pFmt, va_list args);
void error_printf(const char *pFmt, ...);
-
+
// Helpers
inline uint8_t clamp255(int32_t i)
@@ -170,18 +180,24 @@ namespace basisu
class running_stat
{
public:
- running_stat() :
- m_n(0),
- m_old_m(0), m_new_m(0), m_old_s(0), m_new_s(0)
- {
- }
+ running_stat() { clear(); }
+
void clear()
{
m_n = 0;
+ m_total = 0;
+ m_old_m = 0;
+ m_new_m = 0;
+ m_old_s = 0;
+ m_new_s = 0;
+ m_min = 0;
+ m_max = 0;
}
+
void push(double x)
{
m_n++;
+ m_total += x;
if (m_n == 1)
{
m_old_m = m_new_m = x;
@@ -191,6 +207,7 @@ namespace basisu
}
else
{
+ // See Knuth TAOCP vol 2, 3rd edition, page 232
m_new_m = m_old_m + (x - m_old_m) / m_n;
m_new_s = m_old_s + (x - m_old_m) * (x - m_new_m);
m_old_m = m_new_m;
@@ -199,15 +216,23 @@ namespace basisu
m_max = basisu::maximum(x, m_max);
}
}
+
uint32_t get_num() const
{
return m_n;
}
+
+ double get_total() const
+ {
+ return m_total;
+ }
+
double get_mean() const
{
return (m_n > 0) ? m_new_m : 0.0;
}
+ // Returns sample variance
double get_variance() const
{
return ((m_n > 1) ? m_new_s / (m_n - 1) : 0.0);
@@ -230,7 +255,7 @@ namespace basisu
private:
uint32_t m_n;
- double m_old_m, m_new_m, m_old_s, m_new_s, m_min, m_max;
+ double m_total, m_old_m, m_new_m, m_old_s, m_new_s, m_min, m_max;
};
// Linear algebra
@@ -401,6 +426,8 @@ namespace basisu
typedef vec<3, float> vec3F;
typedef vec<2, float> vec2F;
typedef vec<1, float> vec1F;
+
+ typedef vec<16, float> vec16F;
template <uint32_t Rows, uint32_t Cols, typename T>
class matrix
@@ -504,6 +531,164 @@ namespace basisu
[pKeys](uint32_t a, uint32_t b) { return pKeys[a] < pKeys[b]; }
);
}
+
+ // 1-4 byte direct Radix sort.
+ template <typename T>
+ T* radix_sort(uint32_t num_vals, T* pBuf0, T* pBuf1, uint32_t key_ofs, uint32_t key_size)
+ {
+ assert(key_ofs < sizeof(T));
+ assert((key_size >= 1) && (key_size <= 4));
+
+ uint32_t hist[256 * 4];
+
+ memset(hist, 0, sizeof(hist[0]) * 256 * key_size);
+
+#define BASISU_GET_KEY(p) (*(uint32_t *)((uint8_t *)(p) + key_ofs))
+
+ if (key_size == 4)
+ {
+ T* p = pBuf0;
+ T* q = pBuf0 + num_vals;
+ for (; p != q; p++)
+ {
+ const uint32_t key = BASISU_GET_KEY(p);
+
+ hist[key & 0xFF]++;
+ hist[256 + ((key >> 8) & 0xFF)]++;
+ hist[512 + ((key >> 16) & 0xFF)]++;
+ hist[768 + ((key >> 24) & 0xFF)]++;
+ }
+ }
+ else if (key_size == 3)
+ {
+ T* p = pBuf0;
+ T* q = pBuf0 + num_vals;
+ for (; p != q; p++)
+ {
+ const uint32_t key = BASISU_GET_KEY(p);
+
+ hist[key & 0xFF]++;
+ hist[256 + ((key >> 8) & 0xFF)]++;
+ hist[512 + ((key >> 16) & 0xFF)]++;
+ }
+ }
+ else if (key_size == 2)
+ {
+ T* p = pBuf0;
+ T* q = pBuf0 + (num_vals >> 1) * 2;
+
+ for (; p != q; p += 2)
+ {
+ const uint32_t key0 = BASISU_GET_KEY(p);
+ const uint32_t key1 = BASISU_GET_KEY(p + 1);
+
+ hist[key0 & 0xFF]++;
+ hist[256 + ((key0 >> 8) & 0xFF)]++;
+
+ hist[key1 & 0xFF]++;
+ hist[256 + ((key1 >> 8) & 0xFF)]++;
+ }
+
+ if (num_vals & 1)
+ {
+ const uint32_t key = BASISU_GET_KEY(p);
+
+ hist[key & 0xFF]++;
+ hist[256 + ((key >> 8) & 0xFF)]++;
+ }
+ }
+ else
+ {
+ assert(key_size == 1);
+ if (key_size != 1)
+ return NULL;
+
+ T* p = pBuf0;
+ T* q = pBuf0 + (num_vals >> 1) * 2;
+
+ for (; p != q; p += 2)
+ {
+ const uint32_t key0 = BASISU_GET_KEY(p);
+ const uint32_t key1 = BASISU_GET_KEY(p + 1);
+
+ hist[key0 & 0xFF]++;
+ hist[key1 & 0xFF]++;
+ }
+
+ if (num_vals & 1)
+ {
+ const uint32_t key = BASISU_GET_KEY(p);
+ hist[key & 0xFF]++;
+ }
+ }
+
+ T* pCur = pBuf0;
+ T* pNew = pBuf1;
+
+ for (uint32_t pass = 0; pass < key_size; pass++)
+ {
+ const uint32_t* pHist = &hist[pass << 8];
+
+ uint32_t offsets[256];
+
+ uint32_t cur_ofs = 0;
+ for (uint32_t i = 0; i < 256; i += 2)
+ {
+ offsets[i] = cur_ofs;
+ cur_ofs += pHist[i];
+
+ offsets[i + 1] = cur_ofs;
+ cur_ofs += pHist[i + 1];
+ }
+
+ const uint32_t pass_shift = pass << 3;
+
+ T* p = pCur;
+ T* q = pCur + (num_vals >> 1) * 2;
+
+ for (; p != q; p += 2)
+ {
+ uint32_t c0 = (BASISU_GET_KEY(p) >> pass_shift) & 0xFF;
+ uint32_t c1 = (BASISU_GET_KEY(p + 1) >> pass_shift) & 0xFF;
+
+ if (c0 == c1)
+ {
+ uint32_t dst_offset0 = offsets[c0];
+
+ offsets[c0] = dst_offset0 + 2;
+
+ pNew[dst_offset0] = p[0];
+ pNew[dst_offset0 + 1] = p[1];
+ }
+ else
+ {
+ uint32_t dst_offset0 = offsets[c0]++;
+ uint32_t dst_offset1 = offsets[c1]++;
+
+ pNew[dst_offset0] = p[0];
+ pNew[dst_offset1] = p[1];
+ }
+ }
+
+ if (num_vals & 1)
+ {
+ uint32_t c = (BASISU_GET_KEY(p) >> pass_shift) & 0xFF;
+
+ uint32_t dst_offset = offsets[c];
+ offsets[c] = dst_offset + 1;
+
+ pNew[dst_offset] = *p;
+ }
+
+ T* t = pCur;
+ pCur = pNew;
+ pNew = t;
+ }
+
+ return pCur;
+ }
+
+#undef BASISU_GET_KEY
// Very simple job pool with no dependencies.
class job_pool
@@ -805,17 +990,28 @@ namespace basisu
int dg = e1.g - e2.g;
int db = e1.b - e2.b;
+#if 0
int delta_l = dr * 27 + dg * 92 + db * 9;
int delta_cr = dr * 128 - delta_l;
int delta_cb = db * 128 - delta_l;
-
+
uint32_t id = ((uint32_t)(delta_l * delta_l) >> 7U) +
((((uint32_t)(delta_cr * delta_cr) >> 7U) * 26U) >> 7U) +
((((uint32_t)(delta_cb * delta_cb) >> 7U) * 3U) >> 7U);
+#else
+ int64_t delta_l = dr * 27 + dg * 92 + db * 9;
+ int64_t delta_cr = dr * 128 - delta_l;
+ int64_t delta_cb = db * 128 - delta_l;
+
+ uint32_t id = ((uint32_t)((delta_l * delta_l) >> 7U)) +
+ ((((uint32_t)((delta_cr * delta_cr) >> 7U)) * 26U) >> 7U) +
+ ((((uint32_t)((delta_cb * delta_cb) >> 7U)) * 3U) >> 7U);
+#endif
if (alpha)
{
int da = (e1.a - e2.a) << 7;
+ // This shouldn't overflow if da is 255 or -255: 29.99 bits after squaring.
id += ((uint32_t)(da * da) >> 7U);
}
@@ -1258,7 +1454,7 @@ namespace basisu
{
codebook.resize(codebook.size() + 1);
codebook.back() = cur.m_training_vecs;
-
+
if (node_stack.empty())
break;
@@ -1295,6 +1491,9 @@ namespace basisu
uint32_t total_leaf_nodes = 1;
+ //interval_timer tm;
+ //tm.start();
+
while ((var_heap.size()) && (total_leaf_nodes < max_size))
{
const uint32_t node_index = var_heap.get_top_index();
@@ -1315,6 +1514,8 @@ namespace basisu
}
}
+ //debug_printf("tree_vector_quant::generate %u: %3.3f secs\n", TrainingVectorType::num_elements, tm.get_elapsed_secs());
+
return true;
}
@@ -1443,17 +1644,32 @@ namespace basisu
{
const uint32_t N = TrainingVectorType::num_elements;
- matrix<N, N, float> cmatrix(cZero);
+ matrix<N, N, float> cmatrix;
- // Compute covariance matrix from weighted input vectors
- for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ if ((N != 16) || (!g_cpu_supports_sse41))
{
- const TrainingVectorType v(m_training_vecs[node.m_training_vecs[i]].first - node.m_origin);
- const TrainingVectorType w(static_cast<float>(m_training_vecs[node.m_training_vecs[i]].second) * v);
+ cmatrix.set_zero();
+
+ // Compute covariance matrix from weighted input vectors
+ for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
+ {
+ const TrainingVectorType v(m_training_vecs[node.m_training_vecs[i]].first - node.m_origin);
+ const TrainingVectorType w(static_cast<float>(m_training_vecs[node.m_training_vecs[i]].second) * v);
- for (uint32_t x = 0; x < N; x++)
- for (uint32_t y = x; y < N; y++)
- cmatrix[x][y] = cmatrix[x][y] + v[x] * w[y];
+ for (uint32_t x = 0; x < N; x++)
+ for (uint32_t y = x; y < N; y++)
+ cmatrix[x][y] = cmatrix[x][y] + v[x] * w[y];
+ }
+ }
+ else
+ {
+#if BASISU_SUPPORT_SSE
+ // Specialize the case with 16x16 matrices, which are quite expensive without SIMD.
+ // This SSE function takes pointers to void types, so do some sanity checks.
+ assert(sizeof(TrainingVectorType) == sizeof(float) * 16);
+ assert(sizeof(training_vec_with_weight) == sizeof(std::pair<vec16F, uint64_t>));
+ update_covar_matrix_16x16_sse41(node.m_training_vecs.size(), m_training_vecs.data(), &node.m_origin, node.m_training_vecs.data(), &cmatrix);
+#endif
}
const float renorm_scale = 1.0f / node.m_weight;
@@ -1632,16 +1848,19 @@ namespace basisu
}
}
+ // Node is unsplittable using the above algorithm - try something else to split it up.
if ((!l_weight) || (!r_weight))
{
l_children.resize(0);
new_l_child.set(0.0f);
l_ttsum = 0.0f;
l_weight = 0;
+
r_children.resize(0);
new_r_child.set(0.0f);
r_ttsum = 0.0f;
r_weight = 0;
+
TrainingVectorType firstVec;
for (uint32_t i = 0; i < node.m_training_vecs.size(); i++)
{
@@ -1847,31 +2066,67 @@ namespace basisu
uint32_t max_codebook_size, uint32_t max_parent_codebook_size,
basisu::vector<uint_vec>& codebook,
basisu::vector<uint_vec>& parent_codebook,
- uint32_t max_threads, job_pool *pJob_pool)
+ uint32_t max_threads, job_pool *pJob_pool,
+ bool even_odd_input_pairs_equal)
{
typedef bit_hasher<typename Quantizer::training_vec_type> training_vec_bit_hasher;
+
typedef std::unordered_map < typename Quantizer::training_vec_type, weighted_block_group,
training_vec_bit_hasher> group_hash;
+ //interval_timer tm;
+ //tm.start();
+
group_hash unique_vecs;
- weighted_block_group g;
- g.m_indices.resize(1);
+ unique_vecs.reserve(20000);
- for (uint32_t i = 0; i < q.get_training_vecs().size(); i++)
+ weighted_block_group g;
+
+ if (even_odd_input_pairs_equal)
{
- g.m_total_weight = q.get_training_vecs()[i].second;
- g.m_indices[0] = i;
+ g.m_indices.resize(2);
- auto ins_res = unique_vecs.insert(std::make_pair(q.get_training_vecs()[i].first, g));
+ assert(q.get_training_vecs().size() >= 2 && (q.get_training_vecs().size() & 1) == 0);
- if (!ins_res.second)
+ for (uint32_t i = 0; i < q.get_training_vecs().size(); i += 2)
{
- (ins_res.first)->second.m_total_weight += g.m_total_weight;
- (ins_res.first)->second.m_indices.push_back(i);
+ assert(q.get_training_vecs()[i].first == q.get_training_vecs()[i + 1].first);
+
+ g.m_total_weight = q.get_training_vecs()[i].second + q.get_training_vecs()[i + 1].second;
+ g.m_indices[0] = i;
+ g.m_indices[1] = i + 1;
+
+ auto ins_res = unique_vecs.insert(std::make_pair(q.get_training_vecs()[i].first, g));
+
+ if (!ins_res.second)
+ {
+ (ins_res.first)->second.m_total_weight += g.m_total_weight;
+ (ins_res.first)->second.m_indices.push_back(i);
+ (ins_res.first)->second.m_indices.push_back(i + 1);
+ }
+ }
+ }
+ else
+ {
+ g.m_indices.resize(1);
+
+ for (uint32_t i = 0; i < q.get_training_vecs().size(); i++)
+ {
+ g.m_total_weight = q.get_training_vecs()[i].second;
+ g.m_indices[0] = i;
+
+ auto ins_res = unique_vecs.insert(std::make_pair(q.get_training_vecs()[i].first, g));
+
+ if (!ins_res.second)
+ {
+ (ins_res.first)->second.m_total_weight += g.m_total_weight;
+ (ins_res.first)->second.m_indices.push_back(i);
+ }
}
}
+ //debug_printf("generate_hierarchical_codebook_threaded: %u training vectors, %u unique training vectors, %3.3f secs\n", q.get_total_training_vecs(), (uint32_t)unique_vecs.size(), tm.get_elapsed_secs());
debug_printf("generate_hierarchical_codebook_threaded: %u training vectors, %u unique training vectors\n", q.get_total_training_vecs(), (uint32_t)unique_vecs.size());
Quantizer group_quant;
@@ -2491,7 +2746,27 @@ namespace basisu
return *this;
}
- image &crop(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const color_rgba &background = g_black_color)
+ // pPixels MUST have been allocated using malloc() (basisu::vector will eventually use free() on the pointer).
+ image& grant_ownership(color_rgba* pPixels, uint32_t w, uint32_t h, uint32_t p = UINT32_MAX)
+ {
+ if (p == UINT32_MAX)
+ p = w;
+
+ clear();
+
+ if ((!p) || (!w) || (!h))
+ return *this;
+
+ m_pixels.grant_ownership(pPixels, p * h, p * h);
+
+ m_width = w;
+ m_height = h;
+ m_pitch = p;
+
+ return *this;
+ }
+
+ image &crop(uint32_t w, uint32_t h, uint32_t p = UINT32_MAX, const color_rgba &background = g_black_color, bool init_image = true)
{
if (p == UINT32_MAX)
p = w;
@@ -2509,15 +2784,25 @@ namespace basisu
cur_state.swap(m_pixels);
m_pixels.resize(p * h);
-
- for (uint32_t y = 0; y < h; y++)
+
+ if (init_image)
{
- for (uint32_t x = 0; x < w; x++)
+ if (m_width || m_height)
{
- if ((x < m_width) && (y < m_height))
- m_pixels[x + y * p] = cur_state[x + y * m_pitch];
- else
- m_pixels[x + y * p] = background;
+ for (uint32_t y = 0; y < h; y++)
+ {
+ for (uint32_t x = 0; x < w; x++)
+ {
+ if ((x < m_width) && (y < m_height))
+ m_pixels[x + y * p] = cur_state[x + y * m_pitch];
+ else
+ m_pixels[x + y * p] = background;
+ }
+ }
+ }
+ else
+ {
+ m_pixels.set_all(background);
}
}
@@ -2590,9 +2875,25 @@ namespace basisu
const image &extract_block_clamped(color_rgba *pDst, uint32_t src_x, uint32_t src_y, uint32_t w, uint32_t h) const
{
- for (uint32_t y = 0; y < h; y++)
- for (uint32_t x = 0; x < w; x++)
- *pDst++ = get_clamped(src_x + x, src_y + y);
+ if (((src_x + w) > m_width) || ((src_y + h) > m_height))
+ {
+ // Slower clamping case
+ for (uint32_t y = 0; y < h; y++)
+ for (uint32_t x = 0; x < w; x++)
+ *pDst++ = get_clamped(src_x + x, src_y + y);
+ }
+ else
+ {
+ const color_rgba* pSrc = &m_pixels[src_x + src_y * m_pitch];
+
+ for (uint32_t y = 0; y < h; y++)
+ {
+ memcpy(pDst, pSrc, w * sizeof(color_rgba));
+ pSrc += m_pitch;
+ pDst += w;
+ }
+ }
+
return *this;
}
@@ -2947,21 +3248,18 @@ namespace basisu
};
// Image saving/loading/resampling
-
+
bool load_png(const uint8_t* pBuf, size_t buf_size, image& img, const char* pFilename = nullptr);
bool load_png(const char* pFilename, image& img);
inline bool load_png(const std::string &filename, image &img) { return load_png(filename.c_str(), img); }
- bool load_bmp(const char* pFilename, image& img);
- inline bool load_bmp(const std::string &filename, image &img) { return load_bmp(filename.c_str(), img); }
-
bool load_tga(const char* pFilename, image& img);
inline bool load_tga(const std::string &filename, image &img) { return load_tga(filename.c_str(), img); }
bool load_jpg(const char *pFilename, image& img);
inline bool load_jpg(const std::string &filename, image &img) { return load_jpg(filename.c_str(), img); }
- // Currently loads .BMP, .PNG, or .TGA.
+ // Currently loads .PNG, .TGA, or .JPG
bool load_image(const char* pFilename, image& img);
inline bool load_image(const std::string &filename, image &img) { return load_image(filename.c_str(), img); }
@@ -3129,6 +3427,29 @@ namespace basisu
}
void fill_buffer_with_random_bytes(void *pBuf, size_t size, uint32_t seed = 1);
+
+ const uint32_t cPixelBlockWidth = 4;
+ const uint32_t cPixelBlockHeight = 4;
+ const uint32_t cPixelBlockTotalPixels = cPixelBlockWidth * cPixelBlockHeight;
+
+ struct pixel_block
+ {
+ color_rgba m_pixels[cPixelBlockHeight][cPixelBlockWidth]; // [y][x]
+
+ inline const color_rgba& operator() (uint32_t x, uint32_t y) const { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
+ inline color_rgba& operator() (uint32_t x, uint32_t y) { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
+
+ inline const color_rgba* get_ptr() const { return &m_pixels[0][0]; }
+ inline color_rgba* get_ptr() { return &m_pixels[0][0]; }
+
+ inline void clear() { clear_obj(*this); }
+
+ inline bool operator== (const pixel_block& rhs) const
+ {
+ return memcmp(m_pixels, rhs.m_pixels, sizeof(m_pixels)) == 0;
+ }
+ };
+ typedef basisu::vector<pixel_block> pixel_block_vec;
} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_etc.cpp b/thirdparty/basis_universal/encoder/basisu_etc.cpp
index 232e8965b0..f8bd0f12e5 100644
--- a/thirdparty/basis_universal/encoder/basisu_etc.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_etc.cpp
@@ -158,6 +158,22 @@ namespace basisu
}
}
}
+
+#if 0
+ for (uint32_t y = 0; y < 64; y++)
+ {
+ printf("{");
+ for (uint32_t x = 0; x < 256; x++)
+ {
+ printf("0x%X", g_etc1_inverse_lookup[y][x]);
+ if (x != 255)
+ printf(",");
+ if (((x & 63) == 63) && (x != 255))
+ printf("\n");
+ }
+ printf("},\n");
+ }
+#endif
}
// Packs solid color blocks efficiently using a set of small precomputed tables.
@@ -1126,6 +1142,7 @@ namespace basisu
if (!g_eval_dist_tables[inten_table][m_max_comp_spread])
continue;
}
+
#if 0
if (m_pParams->m_quality <= cETCQualityMedium)
{
diff --git a/thirdparty/basis_universal/encoder/basisu_etc.h b/thirdparty/basis_universal/encoder/basisu_etc.h
index 1e3ece43b8..208f2aac1b 100644
--- a/thirdparty/basis_universal/encoder/basisu_etc.h
+++ b/thirdparty/basis_universal/encoder/basisu_etc.h
@@ -490,6 +490,35 @@ namespace basisu
return dc;
}
+ void get_block_colors_etc1s(color_rgba* pBlock_colors) const
+ {
+ color_rgba b;
+
+ unpack_color5(b, get_base5_color(), true);
+
+ const int* pInten_table = g_etc1_inten_tables[get_inten_table(0)];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255);
+ }
+
+ static void get_block_colors_etc1s(color_rgba* pBlock_colors, const color_rgba &base5_color, uint32_t inten_table)
+ {
+ color_rgba b;
+ b.r = (base5_color.r << 3U) | (base5_color.r >> 2U);
+ b.g = (base5_color.g << 3U) | (base5_color.g >> 2U);
+ b.b = (base5_color.b << 3U) | (base5_color.b >> 2U);
+
+ const int* pInten_table = g_etc1_inten_tables[inten_table];
+
+ pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255);
+ pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255);
+ pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255);
+ pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255);
+ }
+
void get_block_color(color_rgba& color, uint32_t subblock_index, uint32_t selector_index) const
{
color_rgba b;
diff --git a/thirdparty/basis_universal/encoder/basisu_frontend.cpp b/thirdparty/basis_universal/encoder/basisu_frontend.cpp
index 324fc8e447..00210e6679 100644
--- a/thirdparty/basis_universal/encoder/basisu_frontend.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_frontend.cpp
@@ -19,6 +19,7 @@
//
#include "../transcoder/basisu.h"
#include "basisu_frontend.h"
+#include "basisu_opencl.h"
#include <unordered_set>
#include <unordered_map>
@@ -43,61 +44,15 @@ namespace basisu
// TODO - How to handle internal verifies in the basisu lib
static inline void handle_verify_failure(int line)
{
- fprintf(stderr, "ERROR: basisu_frontend: verify check failed at line %i!\n", line);
+ error_printf("basisu_frontend: verify check failed at line %i!\n", line);
abort();
}
bool basisu_frontend::init(const params &p)
{
-#if 0
- // HACK HACK
- FILE* pFile;
- fopen_s(&pFile, "tv.bin", "rb");
- if (pFile)
- {
- debug_printf("Using tv.bin\n");
-
- fseek(pFile, 0, SEEK_END);
- uint32_t size = ftell(pFile);
- fseek(pFile, 0, SEEK_SET);
-
- uint32_t tv = size / sizeof(vec6F_quantizer::training_vec_with_weight);
-
- basisu::vector<vec6F_quantizer::training_vec_with_weight> v(tv);
- fread(&v[0], 1, sizeof(v[0]) * tv, pFile);
-
- for (uint32_t i = 0; i < tv; i++)
- m_endpoint_clusterizer.add_training_vec(v[i].first, v[i].second);
-
- m_endpoint_clusterizer.generate(16128);
- basisu::vector<uint_vec> codebook;
- m_endpoint_clusterizer.retrieve(codebook);
-
- printf("Generated %u entries\n", (uint32_t)codebook.size());
-
- fclose(pFile);
- exit(0);
- }
-#endif
-
- if (p.m_use_hybrid_selector_codebooks)
- {
- if (!p.m_pGlobal_sel_codebook)
- {
- debug_printf("basisu_frontend::init: No global sel codebook!\n");
- assert(0);
- return false;
- }
- }
-
- debug_printf("basisu_frontend::init: Multithreaded: %u, NumEndpointClusters: %u, NumSelectorClusters: %u, Perceptual: %u, CompressionLevel: %u\n",
- p.m_multithreaded, p.m_max_endpoint_clusters, p.m_max_selector_clusters, p.m_perceptual, p.m_compression_level);
-
- debug_printf("Global sel codebook pal bits: %u, Global sel codebook mod bits: %u, Use hybrid selector codebook: %u, Hybrid codebook quality thresh: %f\n",
- p.m_num_global_sel_codebook_pal_bits,
- p.m_num_global_sel_codebook_mod_bits,
- p.m_use_hybrid_selector_codebooks,
- p.m_hybrid_codebook_quality_thresh);
+ debug_printf("basisu_frontend::init: Multithreaded: %u, Job pool total threads: %u, NumEndpointClusters: %u, NumSelectorClusters: %u, Perceptual: %u, CompressionLevel: %u\n",
+ p.m_multithreaded, p.m_pJob_pool ? p.m_pJob_pool->get_total_threads() : 0,
+ p.m_max_endpoint_clusters, p.m_max_selector_clusters, p.m_perceptual, p.m_compression_level);
if ((p.m_max_endpoint_clusters < 1) || (p.m_max_endpoint_clusters > cMaxEndpointClusters))
return false;
@@ -106,8 +61,22 @@ namespace basisu
m_source_blocks.resize(0);
append_vector(m_source_blocks, p.m_pSource_blocks, p.m_num_source_blocks);
-
+
m_params = p;
+
+ if (m_params.m_pOpenCL_context)
+ {
+ BASISU_ASSUME(sizeof(cl_pixel_block) == sizeof(pixel_block));
+
+ // Upload the RGBA pixel blocks a single time.
+ if (!opencl_set_pixel_blocks(m_params.m_pOpenCL_context, m_source_blocks.size(), (cl_pixel_block*)m_source_blocks.data()))
+ {
+ // This is not fatal, we just won't use OpenCL.
+ error_printf("basisu_frontend::init: opencl_set_pixel_blocks() failed\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+ }
m_encoded_blocks.resize(m_params.m_num_source_blocks);
memset(&m_encoded_blocks[0], 0, m_encoded_blocks.size() * sizeof(m_encoded_blocks[0]));
@@ -194,8 +163,12 @@ namespace basisu
m_total_blocks = m_params.m_num_source_blocks;
m_total_pixels = m_total_blocks * cPixelBlockTotalPixels;
+ // Encode the initial high quality ETC1S texture
+
init_etc1_images();
+ // First quantize the ETC1S endpoints
+
if (m_params.m_pGlobal_codebooks)
{
init_global_codebooks();
@@ -205,16 +178,26 @@ namespace basisu
init_endpoint_training_vectors();
generate_endpoint_clusters();
-
+
for (uint32_t refine_endpoint_step = 0; refine_endpoint_step < m_num_endpoint_codebook_iterations; refine_endpoint_step++)
{
- BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+ if (m_params.m_validate)
+ {
+ BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+
+ BASISU_FRONTEND_VERIFY(validate_endpoint_cluster_hierarchy(false));
+ }
if (refine_endpoint_step)
{
introduce_new_endpoint_clusters();
}
+ if (m_params.m_validate)
+ {
+ BASISU_FRONTEND_VERIFY(validate_endpoint_cluster_hierarchy(false));
+ }
+
generate_endpoint_codebook(refine_endpoint_step);
if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
@@ -236,7 +219,7 @@ namespace basisu
if ((m_params.m_tex_type == basist::cBASISTexTypeVideoFrames) && (!refine_endpoint_step) && (m_num_endpoint_codebook_iterations == 1))
{
eliminate_redundant_or_empty_endpoint_clusters();
- generate_endpoint_codebook(refine_endpoint_step);
+ generate_endpoint_codebook(basisu::maximum(1U, refine_endpoint_step));
}
if ((m_params.m_debug_images) && (m_params.m_dump_endpoint_clusterization))
@@ -250,22 +233,37 @@ namespace basisu
dump_endpoint_clusterization_visualization(buf, true);
}
}
+
+ if (m_params.m_validate)
+ {
+ BASISU_FRONTEND_VERIFY(validate_endpoint_cluster_hierarchy(false));
+ }
eliminate_redundant_or_empty_endpoint_clusters();
+ if (m_params.m_validate)
+ {
+ BASISU_FRONTEND_VERIFY(validate_endpoint_cluster_hierarchy(false));
+ }
+
if (m_params.m_debug_stats)
debug_printf("Total endpoint clusters: %u\n", (uint32_t)m_endpoint_clusters.size());
if (early_out)
break;
}
-
- BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+
+ if (m_params.m_validate)
+ {
+ BASISU_FRONTEND_VERIFY(check_etc1s_constraints());
+ }
generate_block_endpoint_clusters();
create_initial_packed_texture();
+ // Now quantize the ETC1S selectors
+
generate_selector_clusters();
if (m_use_hierarchical_selector_codebooks)
@@ -276,12 +274,12 @@ namespace basisu
create_optimized_selector_codebook(0);
find_optimal_selector_clusters_for_each_block();
-
+
introduce_special_selector_clusters();
}
else
{
- const uint32_t num_refine_selector_steps = m_params.m_pGlobal_sel_codebook ? 1 : m_num_selector_codebook_iterations;
+ const uint32_t num_refine_selector_steps = m_num_selector_codebook_iterations;
for (uint32_t refine_selector_steps = 0; refine_selector_steps < num_refine_selector_steps; refine_selector_steps++)
{
create_optimized_selector_codebook(refine_selector_steps);
@@ -289,7 +287,7 @@ namespace basisu
find_optimal_selector_clusters_for_each_block();
introduce_special_selector_clusters();
-
+
if ((m_params.m_compression_level >= 4) || (m_params.m_tex_type == basist::cBASISTexTypeVideoFrames))
{
if (!refine_block_endpoints_given_selectors())
@@ -297,7 +295,7 @@ namespace basisu
}
}
}
-
+
optimize_selector_codebook();
if (m_params.m_debug_stats)
@@ -574,9 +572,6 @@ namespace basisu
{
debug_printf("introduce_special_selector_clusters\n");
- if (m_params.m_pGlobal_sel_codebook)
- return;
-
uint32_t total_blocks_relocated = 0;
const uint32_t initial_selector_clusters = (uint32_t)m_selector_cluster_block_indices.size();
@@ -722,23 +717,15 @@ namespace basisu
}
basisu::vector<etc_block> new_optimized_cluster_selectors(m_optimized_cluster_selectors.size() ? total_new_entries : 0);
- basist::etc1_global_selector_codebook_entry_id_vec new_optimized_cluster_selector_global_cb_ids(m_optimized_cluster_selector_global_cb_ids.size() ? total_new_entries : 0);
basisu::vector<uint_vec> new_selector_cluster_indices(m_selector_cluster_block_indices.size() ? total_new_entries : 0);
- bool_vec new_selector_cluster_uses_global_cb(m_selector_cluster_uses_global_cb.size() ? total_new_entries : 0);
for (uint32_t i = 0; i < total_new_entries; i++)
{
if (m_optimized_cluster_selectors.size())
new_optimized_cluster_selectors[i] = m_optimized_cluster_selectors[new_to_old[i]];
- if (m_optimized_cluster_selector_global_cb_ids.size())
- new_optimized_cluster_selector_global_cb_ids[i] = m_optimized_cluster_selector_global_cb_ids[new_to_old[i]];
-
//if (m_selector_cluster_block_indices.size())
// new_selector_cluster_indices[i] = m_selector_cluster_block_indices[new_to_old[i]];
-
- if (m_selector_cluster_uses_global_cb.size())
- new_selector_cluster_uses_global_cb[i] = m_selector_cluster_uses_global_cb[new_to_old[i]];
}
for (uint32_t i = 0; i < m_block_selector_cluster_index.size(); i++)
@@ -747,9 +734,7 @@ namespace basisu
}
m_optimized_cluster_selectors.swap(new_optimized_cluster_selectors);
- m_optimized_cluster_selector_global_cb_ids.swap(new_optimized_cluster_selector_global_cb_ids);
m_selector_cluster_block_indices.swap(new_selector_cluster_indices);
- m_selector_cluster_uses_global_cb.swap(new_selector_cluster_uses_global_cb);
// This isn't strictly necessary - doing it for completeness/future sanity.
if (m_selector_clusters_within_each_parent_cluster.size())
@@ -771,66 +756,93 @@ namespace basisu
m_etc1_blocks_etc1s.resize(m_total_blocks);
- const uint32_t N = 4096;
- for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ bool use_cpu = true;
+
+ if (m_params.m_pOpenCL_context)
+ {
+ uint32_t total_perms = 64;
+ if (m_params.m_compression_level == 0)
+ total_perms = 4;
+ else if (m_params.m_compression_level == 1)
+ total_perms = 16;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ total_perms = OPENCL_ENCODE_ETC1S_MAX_PERMS;
+
+ bool status = opencl_encode_etc1s_blocks(m_params.m_pOpenCL_context, m_etc1_blocks_etc1s.data(), m_params.m_perceptual, total_perms);
+ if (status)
+ use_cpu = false;
+ else
+ {
+ error_printf("basisu_frontend::init_etc1_images: opencl_encode_etc1s_blocks() failed! Using CPU.\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+ }
+
+ if (use_cpu)
{
- const uint32_t first_index = block_index_iter;
- const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+ const uint32_t N = 4096;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+ m_params.m_pJob_pool->add_job([this, first_index, last_index] {
#endif
- for (uint32_t block_index = first_index; block_index < last_index; block_index++)
- {
- const pixel_block &source_blk = get_source_pixel_block(block_index);
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ const pixel_block& source_blk = get_source_pixel_block(block_index);
- etc1_optimizer optimizer;
- etc1_optimizer::params optimizer_params;
- etc1_optimizer::results optimizer_results;
-
- if (m_params.m_compression_level == 0)
- optimizer_params.m_quality = cETCQualityFast;
- else if (m_params.m_compression_level == 1)
- optimizer_params.m_quality = cETCQualityMedium;
- else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
- optimizer_params.m_quality = cETCQualityUber;
-
- optimizer_params.m_num_src_pixels = 16;
- optimizer_params.m_pSrc_pixels = source_blk.get_ptr();
- optimizer_params.m_perceptual = m_params.m_perceptual;
+ etc1_optimizer optimizer;
+ etc1_optimizer::params optimizer_params;
+ etc1_optimizer::results optimizer_results;
- uint8_t selectors[16];
- optimizer_results.m_pSelectors = selectors;
- optimizer_results.m_n = 16;
+ if (m_params.m_compression_level == 0)
+ optimizer_params.m_quality = cETCQualityFast;
+ else if (m_params.m_compression_level == 1)
+ optimizer_params.m_quality = cETCQualityMedium;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ optimizer_params.m_quality = cETCQualityUber;
- optimizer.init(optimizer_params, optimizer_results);
- if (!optimizer.compute())
- BASISU_FRONTEND_VERIFY(false);
+ optimizer_params.m_num_src_pixels = 16;
+ optimizer_params.m_pSrc_pixels = source_blk.get_ptr();
+ optimizer_params.m_perceptual = m_params.m_perceptual;
- etc_block &blk = m_etc1_blocks_etc1s[block_index];
+ uint8_t selectors[16];
+ optimizer_results.m_pSelectors = selectors;
+ optimizer_results.m_n = 16;
- memset(&blk, 0, sizeof(blk));
- blk.set_block_color5_etc1s(optimizer_results.m_block_color_unscaled);
- blk.set_inten_tables_etc1s(optimizer_results.m_block_inten_table);
- blk.set_flip_bit(true);
+ optimizer.init(optimizer_params, optimizer_results);
+ if (!optimizer.compute())
+ BASISU_FRONTEND_VERIFY(false);
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- blk.set_selector(x, y, selectors[x + y * 4]);
- }
+ etc_block& blk = m_etc1_blocks_etc1s[block_index];
+
+ memset(&blk, 0, sizeof(blk));
+ blk.set_block_color5_etc1s(optimizer_results.m_block_color_unscaled);
+ blk.set_inten_tables_etc1s(optimizer_results.m_block_inten_table);
+ blk.set_flip_bit(true);
+
+ for (uint32_t y = 0; y < 4; y++)
+ for (uint32_t x = 0; x < 4; x++)
+ blk.set_selector(x, y, selectors[x + y * 4]);
+ }
#ifndef __EMSCRIPTEN__
- } );
+ });
#endif
- }
+ }
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
+ m_params.m_pJob_pool->wait_for_all();
#endif
- debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+ } // use_cpu
+
+ debug_printf("init_etc1_images: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
}
void basisu_frontend::init_endpoint_training_vectors()
@@ -889,13 +901,15 @@ namespace basisu
const uint32_t parent_codebook_size = (m_params.m_max_endpoint_clusters >= 256) ? BASISU_ENDPOINT_PARENT_CODEBOOK_SIZE : 0;
uint32_t max_threads = 0;
max_threads = m_params.m_multithreaded ? minimum<int>(std::thread::hardware_concurrency(), cMaxCodebookCreationThreads) : 0;
+ if (m_params.m_pJob_pool)
+ max_threads = minimum<int>((int)m_params.m_pJob_pool->get_total_threads(), max_threads);
- debug_printf("Using %u threads to create codebook\n", max_threads);
+ debug_printf("max_threads: %u\n", max_threads);
bool status = generate_hierarchical_codebook_threaded(m_endpoint_clusterizer,
m_params.m_max_endpoint_clusters, m_use_hierarchical_endpoint_codebooks ? parent_codebook_size : 0,
m_endpoint_clusters,
m_endpoint_parent_clusters,
- max_threads, m_params.m_pJob_pool);
+ max_threads, m_params.m_pJob_pool, true);
BASISU_FRONTEND_VERIFY(status);
if (m_use_hierarchical_endpoint_codebooks)
@@ -940,6 +954,9 @@ namespace basisu
for (uint32_t j = 0; j < cluster.size(); j++)
{
const uint32_t block_index = cluster[j] >> 1;
+
+ BASISU_FRONTEND_VERIFY(block_index < m_block_parent_endpoint_cluster.size());
+
if (!j)
{
parent_cluster_index = m_block_parent_endpoint_cluster[block_index];
@@ -956,6 +973,7 @@ namespace basisu
debug_printf("Total endpoint clusters: %u, parent clusters: %u\n", (uint32_t)m_endpoint_clusters.size(), (uint32_t)m_endpoint_parent_clusters.size());
}
+ // Iterate through each array of endpoint cluster block indices and set the m_block_endpoint_clusters_indices[][] array to indicaste which cluster index each block uses.
void basisu_frontend::generate_block_endpoint_clusters()
{
m_block_endpoint_clusters_indices.resize(m_total_blocks);
@@ -974,11 +992,14 @@ namespace basisu
} // cluster_indices_iter
}
- for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ if (m_params.m_validate)
{
- uint32_t cluster_0 = m_block_endpoint_clusters_indices[block_index][0];
- uint32_t cluster_1 = m_block_endpoint_clusters_indices[block_index][1];
- BASISU_FRONTEND_VERIFY(cluster_0 == cluster_1);
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ uint32_t cluster_0 = m_block_endpoint_clusters_indices[block_index][0];
+ uint32_t cluster_1 = m_block_endpoint_clusters_indices[block_index][1];
+ BASISU_FRONTEND_VERIFY(cluster_0 == cluster_1);
+ }
}
}
@@ -989,6 +1010,7 @@ namespace basisu
m_endpoint_clusters_within_each_parent_cluster.resize(0);
m_endpoint_clusters_within_each_parent_cluster.resize(m_endpoint_parent_clusters.size());
+ // Note: It's possible that some blocks got moved into the same cluster, but live in different parent clusters.
for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
{
const uint32_t cluster_index = m_block_endpoint_clusters_indices[block_index][0];
@@ -1125,6 +1147,8 @@ namespace basisu
std::unordered_set<uint32_t> ignore_cluster;
+ uint32_t total_new_clusters = 0;
+
while (num_new_endpoint_clusters)
{
if (m_subblock_endpoint_quant_err_vec.size() == 0)
@@ -1173,10 +1197,14 @@ namespace basisu
cluster_sizes[subblock_to_move.m_cluster_index] -= 2;
ignore_cluster.insert(subblock_to_move.m_cluster_index);
+
+ total_new_clusters++;
num_new_endpoint_clusters--;
}
+ debug_printf("Introduced %i new endpoint clusters\n", total_new_clusters);
+
for (uint32_t i = 0; i < num_orig_endpoint_clusters; i++)
{
uint_vec &cluster_indices = m_endpoint_clusters[i];
@@ -1200,150 +1228,433 @@ namespace basisu
generate_block_endpoint_clusters();
}
+ struct color_rgba_hasher
+ {
+ inline std::size_t operator()(const color_rgba& k) const
+ {
+ uint32_t v = *(const uint32_t*)&k;
+
+ //return bitmix32(v);
+
+ //v ^= (v << 10);
+ //v ^= (v >> 12);
+
+ return v;
+ }
+ };
+
// Given each endpoint cluster, gather all the block pixels which are in that cluster and compute optimized ETC1S endpoints for them.
// TODO: Don't optimize endpoint clusters which haven't changed.
+ // If step>=1, we check to ensure the new endpoint values actually decrease quantization error.
void basisu_frontend::generate_endpoint_codebook(uint32_t step)
{
debug_printf("generate_endpoint_codebook\n");
+
+ interval_timer tm;
+ tm.start();
m_endpoint_cluster_etc_params.resize(m_endpoint_clusters.size());
- const uint32_t N = 128;
- for (uint32_t cluster_index_iter = 0; cluster_index_iter < m_endpoint_clusters.size(); cluster_index_iter += N)
+ bool use_cpu = true;
+ // TODO: Get this working when step>0
+ if (m_params.m_pOpenCL_context && !step)
{
- const uint32_t first_index = cluster_index_iter;
- const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
+ const uint32_t total_clusters = m_endpoint_clusters.size();
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index, step ] {
-#endif
+ basisu::vector<cl_pixel_cluster> pixel_clusters(total_clusters);
+
+ std::vector<color_rgba> input_pixels;
+ input_pixels.reserve(m_total_blocks * 16);
- for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ std::vector<uint32_t> pixel_weights;
+ pixel_weights.reserve(m_total_blocks * 16);
+
+ uint_vec cluster_sizes(total_clusters);
+
+ //typedef basisu::hash_map<color_rgba, uint32_t, color_rgba_hasher> color_hasher_type;
+ //color_hasher_type color_hasher;
+ //color_hasher.reserve(2048);
+
+ interval_timer hash_tm;
+ hash_tm.start();
+
+ basisu::vector<uint32_t> colors, colors2;
+ colors.reserve(65536);
+ colors2.reserve(65536);
+
+ for (uint32_t cluster_index = 0; cluster_index < m_endpoint_clusters.size(); cluster_index++)
+ {
+ const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+ assert((cluster_indices.size() & 1) == 0);
+
+#if 0
+ uint64_t first_pixel_index = input_pixels.size();
+ const uint32_t total_pixels = 16 * (cluster_indices.size() / 2);
+
+ input_pixels.resize(input_pixels.size() + total_pixels);
+ pixel_weights.resize(pixel_weights.size() + total_pixels);
+
+ uint64_t dst_ofs = first_pixel_index;
+
+ uint64_t total_r = 0, total_g = 0, total_b = 0;
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
{
- const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+ if (subblock_index)
+ continue;
- BASISU_FRONTEND_VERIFY(cluster_indices.size());
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
- const uint32_t total_pixels = (uint32_t)cluster_indices.size() * 8;
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ input_pixels[dst_ofs] = pBlock_pixels[i];
+ pixel_weights[dst_ofs] = 1;
+ dst_ofs++;
- basisu::vector<color_rgba> cluster_pixels(total_pixels);
+ total_r += pBlock_pixels[i].r;
+ total_g += pBlock_pixels[i].g;
+ total_b += pBlock_pixels[i].b;
+ }
+ }
- for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ //printf("%i %f %f %f\n", cluster_index, total_r / (float)total_pixels, total_g / (float)total_pixels, total_b / (float)total_pixels);
+
+ pixel_clusters[cluster_index].m_first_pixel_index = first_pixel_index;
+ pixel_clusters[cluster_index].m_total_pixels = total_pixels;
+ cluster_sizes[cluster_index] = total_pixels;
+#elif 1
+ colors.resize(cluster_indices.size() * 8);
+ colors2.resize(cluster_indices.size() * 8);
+ uint32_t dst_ofs = 0;
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+ if (subblock_index)
+ continue;
+
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ memcpy(colors.data() + dst_ofs, pBlock_pixels, sizeof(color_rgba) * 16);
+ dst_ofs += 16;
+
+ } // cluster_indices_iter
+
+ uint32_t* pSorted = radix_sort(colors.size(), colors.data(), colors2.data(), 0, 3);
+
+ const uint64_t first_pixel_index = input_pixels.size();
+
+ uint32_t prev_color = 0, cur_weight = 0;
+
+ for (uint32_t i = 0; i < colors.size(); i++)
+ {
+ uint32_t cur_color = pSorted[i];
+ if (cur_color == prev_color)
{
- const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
- const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+ if (++cur_weight == 0)
+ cur_weight--;
+ }
+ else
+ {
+ if (cur_weight)
+ {
+ input_pixels.push_back(*(const color_rgba*)&prev_color);
+ pixel_weights.push_back(cur_weight);
+ }
- const bool flipped = true;
+ prev_color = cur_color;
+ cur_weight = 1;
+ }
+ }
- const color_rgba *pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+ if (cur_weight)
+ {
+ input_pixels.push_back(*(const color_rgba*)&prev_color);
+ pixel_weights.push_back(cur_weight);
+ }
- for (uint32_t pixel_index = 0; pixel_index < 8; pixel_index++)
+ uint32_t total_unique_pixels = (uint32_t)(input_pixels.size() - first_pixel_index);
+
+ pixel_clusters[cluster_index].m_first_pixel_index = first_pixel_index;
+ pixel_clusters[cluster_index].m_total_pixels = total_unique_pixels;
+
+ cluster_sizes[cluster_index] = total_unique_pixels;
+#else
+ color_hasher.reset();
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
+ {
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
+ if (subblock_index)
+ continue;
+
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
+
+ uint32_t *pPrev_weight = nullptr;
+ color_rgba prev_color;
+
+ {
+ color_rgba cur_color = pBlock_pixels[0];
+ auto res = color_hasher.insert(cur_color, 0);
+
+ uint32_t& weight = (res.first)->second;
+ if (weight != UINT32_MAX)
+ weight++;
+
+ prev_color = cur_color;
+ pPrev_weight = &(res.first)->second;
+ }
+
+ for (uint32_t i = 1; i < 16; i++)
+ {
+ color_rgba cur_color = pBlock_pixels[i];
+
+ if (cur_color == prev_color)
+ {
+ if (*pPrev_weight != UINT32_MAX)
+ *pPrev_weight = *pPrev_weight + 1;
+ }
+ else
{
- const color_rgba &c = pBlock_pixels[g_etc1_pixel_indices[flipped][subblock_index][pixel_index]];
- cluster_pixels[cluster_indices_iter * 8 + pixel_index] = c;
+ auto res = color_hasher.insert(cur_color, 0);
+
+ uint32_t& weight = (res.first)->second;
+ if (weight != UINT32_MAX)
+ weight++;
+
+ prev_color = cur_color;
+ pPrev_weight = &(res.first)->second;
}
}
- endpoint_cluster_etc_params new_subblock_params;
+ } // cluster_indices_iter
+
+ const uint64_t first_pixel_index = input_pixels.size();
+ uint32_t total_unique_pixels = color_hasher.size();
+
+ pixel_clusters[cluster_index].m_first_pixel_index = first_pixel_index;
+ pixel_clusters[cluster_index].m_total_pixels = total_unique_pixels;
+
+ input_pixels.resize(first_pixel_index + total_unique_pixels);
+ pixel_weights.resize(first_pixel_index + total_unique_pixels);
- {
- etc1_optimizer optimizer;
- etc1_solution_coordinates solutions[2];
+ uint32_t j = 0;
+
+ for (auto it = color_hasher.begin(); it != color_hasher.end(); ++it, ++j)
+ {
+ input_pixels[first_pixel_index + j] = it->first;
+ pixel_weights[first_pixel_index + j] = it->second;
+ }
- etc1_optimizer::params cluster_optimizer_params;
- cluster_optimizer_params.m_num_src_pixels = total_pixels;
- cluster_optimizer_params.m_pSrc_pixels = &cluster_pixels[0];
+ cluster_sizes[cluster_index] = total_unique_pixels;
+#endif
- cluster_optimizer_params.m_use_color4 = false;
- cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
+ } // cluster_index
- if (m_params.m_compression_level <= 1)
- cluster_optimizer_params.m_quality = cETCQualityMedium;
- else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
- cluster_optimizer_params.m_quality = cETCQualityUber;
+ debug_printf("Total hash time: %3.3f secs\n", hash_tm.get_elapsed_secs());
- etc1_optimizer::results cluster_optimizer_results;
+ debug_printf("Total unique colors: %llu\n", input_pixels.size());
- basisu::vector<uint8_t> cluster_selectors(total_pixels);
- cluster_optimizer_results.m_n = total_pixels;
- cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
+ uint_vec sorted_cluster_indices_new_to_old(total_clusters);
+ indirect_sort(total_clusters, sorted_cluster_indices_new_to_old.data(), cluster_sizes.data());
+ //for (uint32_t i = 0; i < total_clusters; i++)
+ // sorted_cluster_indices_new_to_old[i] = i;
- optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
+ uint_vec sorted_cluster_indices_old_to_new(total_clusters);
+ for (uint32_t i = 0; i < total_clusters; i++)
+ sorted_cluster_indices_old_to_new[sorted_cluster_indices_new_to_old[i]] = i;
- if (!optimizer.compute())
- BASISU_FRONTEND_VERIFY(false);
+ basisu::vector<cl_pixel_cluster> sorted_pixel_clusters(total_clusters);
+ for (uint32_t i = 0; i < total_clusters; i++)
+ sorted_pixel_clusters[i] = pixel_clusters[sorted_cluster_indices_new_to_old[i]];
- new_subblock_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
- new_subblock_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
- new_subblock_params.m_color_error[0] = cluster_optimizer_results.m_error;
- }
+ uint32_t total_perms = 64;
+ if (m_params.m_compression_level <= 1)
+ total_perms = 16;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ total_perms = OPENCL_ENCODE_ETC1S_MAX_PERMS;
- endpoint_cluster_etc_params &prev_etc_params = m_endpoint_cluster_etc_params[cluster_index];
+ basisu::vector<etc_block> output_blocks(total_clusters);
- bool use_new_subblock_params = false;
- if ((!step) || (!prev_etc_params.m_valid))
- use_new_subblock_params = true;
- else
+ if (opencl_encode_etc1s_pixel_clusters(
+ m_params.m_pOpenCL_context,
+ output_blocks.data(),
+ total_clusters,
+ sorted_pixel_clusters.data(),
+ input_pixels.size(),
+ input_pixels.data(),
+ pixel_weights.data(),
+ m_params.m_perceptual, total_perms))
+ {
+ for (uint32_t old_cluster_index = 0; old_cluster_index < m_endpoint_clusters.size(); old_cluster_index++)
+ {
+ const uint32_t new_cluster_index = sorted_cluster_indices_old_to_new[old_cluster_index];
+
+ const etc_block& blk = output_blocks[new_cluster_index];
+
+ endpoint_cluster_etc_params& prev_etc_params = m_endpoint_cluster_etc_params[old_cluster_index];
+
+ prev_etc_params.m_valid = true;
+ etc_block::unpack_color5(prev_etc_params.m_color_unscaled[0], blk.get_base5_color(), false);
+ prev_etc_params.m_inten_table[0] = blk.get_inten_table(0);
+ prev_etc_params.m_color_error[0] = 0; // dummy value - we don't actually use this
+ }
+
+ use_cpu = false;
+ }
+ else
+ {
+ error_printf("basisu_frontend::generate_endpoint_codebook: opencl_encode_etc1s_pixel_clusters() failed! Using CPU.\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+
+ } // if (opencl_is_available() && m_params.m_use_opencl)
+
+ if (use_cpu)
+ {
+ const uint32_t N = 128;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < m_endpoint_clusters.size(); cluster_index_iter += N)
+ {
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)m_endpoint_clusters.size(), cluster_index_iter + N);
+
+#ifndef __EMSCRIPTEN__
+ m_params.m_pJob_pool->add_job([this, first_index, last_index, step] {
+#endif
+
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
{
- assert(prev_etc_params.m_valid);
+ const basisu::vector<uint32_t>& cluster_indices = m_endpoint_clusters[cluster_index];
- uint64_t total_prev_err = 0;
-
+ BASISU_FRONTEND_VERIFY(cluster_indices.size());
+
+ const uint32_t total_pixels = (uint32_t)cluster_indices.size() * 8;
+
+ basisu::vector<color_rgba> cluster_pixels(total_pixels);
+
+ for (uint32_t cluster_indices_iter = 0; cluster_indices_iter < cluster_indices.size(); cluster_indices_iter++)
{
- color_rgba block_colors[4];
+ const uint32_t block_index = cluster_indices[cluster_indices_iter] >> 1;
+ const uint32_t subblock_index = cluster_indices[cluster_indices_iter] & 1;
- etc_block::get_block_colors5(block_colors, prev_etc_params.m_color_unscaled[0], prev_etc_params.m_inten_table[0], false);
+ const bool flipped = true;
- uint64_t total_err = 0;
+ const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
- for (uint32_t i = 0; i < total_pixels; i++)
+ for (uint32_t pixel_index = 0; pixel_index < 8; pixel_index++)
{
- const color_rgba &c = cluster_pixels[i];
+ const color_rgba& c = pBlock_pixels[g_etc1_pixel_indices[flipped][subblock_index][pixel_index]];
+ cluster_pixels[cluster_indices_iter * 8 + pixel_index] = c;
+ }
+ }
- uint64_t best_err = UINT64_MAX;
- //uint32_t best_index = 0;
+ endpoint_cluster_etc_params new_subblock_params;
+
+ {
+ etc1_optimizer optimizer;
+ etc1_solution_coordinates solutions[2];
+
+ etc1_optimizer::params cluster_optimizer_params;
+ cluster_optimizer_params.m_num_src_pixels = total_pixels;
+ cluster_optimizer_params.m_pSrc_pixels = &cluster_pixels[0];
+
+ cluster_optimizer_params.m_use_color4 = false;
+ cluster_optimizer_params.m_perceptual = m_params.m_perceptual;
+
+ if (m_params.m_compression_level <= 1)
+ cluster_optimizer_params.m_quality = cETCQualityMedium;
+ else if (m_params.m_compression_level == BASISU_MAX_COMPRESSION_LEVEL)
+ cluster_optimizer_params.m_quality = cETCQualityUber;
+
+ etc1_optimizer::results cluster_optimizer_results;
+
+ basisu::vector<uint8_t> cluster_selectors(total_pixels);
+ cluster_optimizer_results.m_n = total_pixels;
+ cluster_optimizer_results.m_pSelectors = &cluster_selectors[0];
+
+ optimizer.init(cluster_optimizer_params, cluster_optimizer_results);
+
+ if (!optimizer.compute())
+ BASISU_FRONTEND_VERIFY(false);
+
+ new_subblock_params.m_color_unscaled[0] = cluster_optimizer_results.m_block_color_unscaled;
+ new_subblock_params.m_inten_table[0] = cluster_optimizer_results.m_block_inten_table;
+ new_subblock_params.m_color_error[0] = cluster_optimizer_results.m_error;
+ }
+
+ endpoint_cluster_etc_params& prev_etc_params = m_endpoint_cluster_etc_params[cluster_index];
+
+ bool use_new_subblock_params = false;
+ if ((!step) || (!prev_etc_params.m_valid))
+ use_new_subblock_params = true;
+ else
+ {
+ assert(prev_etc_params.m_valid);
+
+ uint64_t total_prev_err = 0;
+
+ {
+ color_rgba block_colors[4];
+
+ etc_block::get_block_colors5(block_colors, prev_etc_params.m_color_unscaled[0], prev_etc_params.m_inten_table[0], false);
- for (uint32_t s = 0; s < 4; s++)
+ uint64_t total_err = 0;
+
+ for (uint32_t i = 0; i < total_pixels; i++)
{
- uint64_t err = color_distance(m_params.m_perceptual, c, block_colors[s], false);
- if (err < best_err)
+ const color_rgba& c = cluster_pixels[i];
+
+ uint64_t best_err = UINT64_MAX;
+ //uint32_t best_index = 0;
+
+ for (uint32_t s = 0; s < 4; s++)
{
- best_err = err;
- //best_index = s;
+ uint64_t err = color_distance(m_params.m_perceptual, c, block_colors[s], false);
+ if (err < best_err)
+ {
+ best_err = err;
+ //best_index = s;
+ }
}
+
+ total_err += best_err;
}
- total_err += best_err;
+ total_prev_err += total_err;
}
- total_prev_err += total_err;
+ // See if we should update this cluster's endpoints (if the error has actually fallen)
+ if (total_prev_err > new_subblock_params.m_color_error[0])
+ {
+ use_new_subblock_params = true;
+ }
}
- // See if we should update this cluster's endpoints (if the error has actually fallen)
- if (total_prev_err > new_subblock_params.m_color_error[0])
+ if (use_new_subblock_params)
{
- use_new_subblock_params = true;
- }
- }
+ new_subblock_params.m_valid = true;
- if (use_new_subblock_params)
- {
- new_subblock_params.m_valid = true;
+ prev_etc_params = new_subblock_params;
+ }
- prev_etc_params = new_subblock_params;
- }
-
- } // cluster_index
+ } // cluster_index
#ifndef __EMSCRIPTEN__
- } );
+ });
#endif
- } // cluster_index_iter
+ } // cluster_index_iter
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
+ m_params.m_pJob_pool->wait_for_all();
#endif
+ }
+
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
}
bool basisu_frontend::check_etc1s_constraints() const
@@ -1373,6 +1684,8 @@ namespace basisu
return true;
}
+ // For each block, determine which ETC1S endpoint cluster can encode that block with lowest error.
+ // This reassigns blocks to different endpoint clusters.
uint32_t basisu_frontend::refine_endpoint_clusterization()
{
debug_printf("refine_endpoint_clusterization\n");
@@ -1380,6 +1693,8 @@ namespace basisu
if (m_use_hierarchical_endpoint_codebooks)
compute_endpoint_clusters_within_each_parent_cluster();
+ // Note: It's possible that an endpoint cluster may live in more than one parent cluster after the first refinement step.
+
basisu::vector<vec2U> block_clusters(m_total_blocks);
for (int cluster_index = 0; cluster_index < static_cast<int>(m_endpoint_clusters.size()); cluster_index++)
@@ -1400,156 +1715,255 @@ namespace basisu
// Create a new endpoint clusterization
+ interval_timer tm;
+ tm.start();
+
uint_vec best_cluster_indices(m_total_blocks);
- const uint32_t N = 1024;
- for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ bool use_cpu = true;
+ // TODO: Support non-hierarchical endpoint codebooks here
+ if (m_params.m_pOpenCL_context && m_use_hierarchical_endpoint_codebooks)
{
- const uint32_t first_index = block_index_iter;
- const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+ // For the OpenCL kernel, we order the parent endpoint clusters by smallest to largest for efficiency.
+ // We also prepare an array of block info structs that point into this new parent endpoint cluster array.
+ const uint32_t total_parent_clusters = m_endpoint_clusters_within_each_parent_cluster.size();
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index, &best_cluster_indices, &block_clusters] {
-#endif
+ basisu::vector<cl_block_info_struct> cl_block_info_structs(m_total_blocks);
+
+ // the size of each parent cluster, in total clusters
+ uint_vec parent_cluster_sizes(total_parent_clusters);
+ for (uint32_t i = 0; i < total_parent_clusters; i++)
+ parent_cluster_sizes[i] = m_endpoint_clusters_within_each_parent_cluster[i].size();
+
+ uint_vec first_parent_cluster_ofs(total_parent_clusters);
+ uint32_t cur_ofs = 0;
+ for (uint32_t i = 0; i < total_parent_clusters; i++)
+ {
+ first_parent_cluster_ofs[i] = cur_ofs;
- for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ cur_ofs += parent_cluster_sizes[i];
+ }
+
+ // Note: total_actual_endpoint_clusters is not necessarly equal to m_endpoint_clusters.size(), because clusters may live in multiple parent clusters after the first refinement step.
+ BASISU_FRONTEND_VERIFY(cur_ofs >= m_endpoint_clusters.size());
+ const uint32_t total_actual_endpoint_clusters = cur_ofs;
+ basisu::vector<cl_endpoint_cluster_struct> cl_endpoint_cluster_structs(total_actual_endpoint_clusters);
+
+ for (uint32_t i = 0; i < total_parent_clusters; i++)
+ {
+ const uint32_t dst_ofs = first_parent_cluster_ofs[i];
+
+ const uint32_t parent_cluster_size = parent_cluster_sizes[i];
+
+ assert(m_endpoint_clusters_within_each_parent_cluster[i].size() == parent_cluster_size);
+
+ for (uint32_t j = 0; j < parent_cluster_size; j++)
{
- const uint32_t cluster_index = block_clusters[block_index][0];
- BASISU_FRONTEND_VERIFY(cluster_index == block_clusters[block_index][1]);
+ const uint32_t endpoint_cluster_index = m_endpoint_clusters_within_each_parent_cluster[i][j];
- const color_rgba *pSubblock_pixels = get_source_pixel_block(block_index).get_ptr();
- const uint32_t num_subblock_pixels = 16;
+ color_rgba cluster_etc_base_color(m_endpoint_cluster_etc_params[endpoint_cluster_index].m_color_unscaled[0]);
+ uint32_t cluster_etc_inten = m_endpoint_cluster_etc_params[endpoint_cluster_index].m_inten_table[0];
- uint64_t best_cluster_err = INT64_MAX;
- uint32_t best_cluster_index = 0;
+ cl_endpoint_cluster_structs[dst_ofs + j].m_unscaled_color = cluster_etc_base_color;
+ cl_endpoint_cluster_structs[dst_ofs + j].m_etc_inten = (uint8_t)cluster_etc_inten;
+ cl_endpoint_cluster_structs[dst_ofs + j].m_cluster_index = (uint16_t)endpoint_cluster_index;
+ }
+ }
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ const uint32_t block_parent_endpoint_cluster_index = m_block_parent_endpoint_cluster[block_index];
+
+ cl_block_info_structs[block_index].m_num_clusters = (uint16_t)(parent_cluster_sizes[block_parent_endpoint_cluster_index]);
+ cl_block_info_structs[block_index].m_first_cluster_ofs = (uint16_t)(first_parent_cluster_ofs[block_parent_endpoint_cluster_index]);
- const uint32_t block_parent_endpoint_cluster_index = m_block_parent_endpoint_cluster.size() ? m_block_parent_endpoint_cluster[block_index] : 0;
- const uint_vec *pCluster_indices = m_endpoint_clusters_within_each_parent_cluster.size() ? &m_endpoint_clusters_within_each_parent_cluster[block_parent_endpoint_cluster_index] : nullptr;
+ const uint32_t block_cluster_index = block_clusters[block_index][0];
+ cl_block_info_structs[block_index].m_cur_cluster_index = (uint16_t)block_cluster_index;
+ cl_block_info_structs[block_index].m_cur_cluster_etc_inten = (uint8_t)m_endpoint_cluster_etc_params[block_cluster_index].m_inten_table[0];
+ }
+
+ uint_vec block_cluster_indices(m_total_blocks);
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ block_cluster_indices[i] = block_clusters[i][0];
- const uint32_t total_clusters = m_use_hierarchical_endpoint_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_endpoint_clusters.size();
+ uint_vec sorted_block_indices(m_total_blocks);
+ indirect_sort(m_total_blocks, sorted_block_indices.data(), block_cluster_indices.data());
- for (uint32_t i = 0; i < total_clusters; i++)
+ bool status = opencl_refine_endpoint_clusterization(
+ m_params.m_pOpenCL_context,
+ cl_block_info_structs.data(),
+ total_actual_endpoint_clusters,
+ cl_endpoint_cluster_structs.data(),
+ sorted_block_indices.data(),
+ best_cluster_indices.data(),
+ m_params.m_perceptual);
+
+ if (status)
+ {
+ use_cpu = false;
+ }
+ else
+ {
+ error_printf("basisu_frontend::refine_endpoint_clusterization: opencl_refine_endpoint_clusterization() failed! Using CPU.\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+ }
+
+ if (use_cpu)
+ {
+ const uint32_t N = 1024;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+
+#ifndef __EMSCRIPTEN__
+ m_params.m_pJob_pool->add_job([this, first_index, last_index, &best_cluster_indices, &block_clusters] {
+#endif
+
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
- const uint32_t cluster_iter = m_use_hierarchical_endpoint_codebooks ? (*pCluster_indices)[i] : i;
+ const uint32_t cluster_index = block_clusters[block_index][0];
+ BASISU_FRONTEND_VERIFY(cluster_index == block_clusters[block_index][1]);
- color_rgba cluster_etc_base_color(m_endpoint_cluster_etc_params[cluster_iter].m_color_unscaled[0]);
- uint32_t cluster_etc_inten = m_endpoint_cluster_etc_params[cluster_iter].m_inten_table[0];
+ const color_rgba* pSubblock_pixels = get_source_pixel_block(block_index).get_ptr();
+ const uint32_t num_subblock_pixels = 16;
- uint64_t total_err = 0;
+ uint64_t best_cluster_err = INT64_MAX;
+ uint32_t best_cluster_index = 0;
- const uint32_t low_selector = 0;//subblock_etc_params_vec[j].m_low_selectors[0];
- const uint32_t high_selector = 3;//subblock_etc_params_vec[j].m_high_selectors[0];
- color_rgba subblock_colors[4];
- // Can't assign it here - may result in too much error when selector quant occurs
- if (cluster_etc_inten > m_endpoint_cluster_etc_params[cluster_index].m_inten_table[0])
- {
- total_err = INT64_MAX;
- goto skip_cluster;
- }
+ const uint32_t block_parent_endpoint_cluster_index = m_block_parent_endpoint_cluster.size() ? m_block_parent_endpoint_cluster[block_index] : 0;
+ const uint_vec* pCluster_indices = m_endpoint_clusters_within_each_parent_cluster.size() ? &m_endpoint_clusters_within_each_parent_cluster[block_parent_endpoint_cluster_index] : nullptr;
- etc_block::get_block_colors5(subblock_colors, cluster_etc_base_color, cluster_etc_inten);
-
-#if 0
- for (uint32_t p = 0; p < num_subblock_pixels; p++)
+ const uint32_t total_clusters = m_use_hierarchical_endpoint_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_endpoint_clusters.size();
+
+ for (uint32_t i = 0; i < total_clusters; i++)
{
- uint64_t best_err = UINT64_MAX;
+ const uint32_t cluster_iter = m_use_hierarchical_endpoint_codebooks ? (*pCluster_indices)[i] : i;
- for (uint32_t r = low_selector; r <= high_selector; r++)
+ color_rgba cluster_etc_base_color(m_endpoint_cluster_etc_params[cluster_iter].m_color_unscaled[0]);
+ uint32_t cluster_etc_inten = m_endpoint_cluster_etc_params[cluster_iter].m_inten_table[0];
+
+ uint64_t total_err = 0;
+
+ const uint32_t low_selector = 0;//subblock_etc_params_vec[j].m_low_selectors[0];
+ const uint32_t high_selector = 3;//subblock_etc_params_vec[j].m_high_selectors[0];
+ color_rgba subblock_colors[4];
+ // Can't assign it here - may result in too much error when selector quant occurs
+ if (cluster_etc_inten > m_endpoint_cluster_etc_params[cluster_index].m_inten_table[0])
{
- uint64_t err = color_distance(m_params.m_perceptual, pSubblock_pixels[p], subblock_colors[r], false);
- best_err = minimum(best_err, err);
- if (!best_err)
- break;
+ total_err = INT64_MAX;
+ goto skip_cluster;
}
- total_err += best_err;
- if (total_err > best_cluster_err)
- break;
- } // p
-#else
- if (m_params.m_perceptual)
- {
- if (!g_cpu_supports_sse41)
+ etc_block::get_block_colors5(subblock_colors, cluster_etc_base_color, cluster_etc_inten);
+
+#if 0
+ for (uint32_t p = 0; p < num_subblock_pixels; p++)
{
- for (uint32_t p = 0; p < num_subblock_pixels; p++)
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t r = low_selector; r <= high_selector; r++)
{
- uint64_t best_err = UINT64_MAX;
+ uint64_t err = color_distance(m_params.m_perceptual, pSubblock_pixels[p], subblock_colors[r], false);
+ best_err = minimum(best_err, err);
+ if (!best_err)
+ break;
+ }
- for (uint32_t r = low_selector; r <= high_selector; r++)
+ total_err += best_err;
+ if (total_err > best_cluster_err)
+ break;
+ } // p
+#else
+ if (m_params.m_perceptual)
+ {
+ if (!g_cpu_supports_sse41)
+ {
+ for (uint32_t p = 0; p < num_subblock_pixels; p++)
{
- uint64_t err = color_distance(true, pSubblock_pixels[p], subblock_colors[r], false);
- best_err = minimum(best_err, err);
- if (!best_err)
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t r = low_selector; r <= high_selector; r++)
+ {
+ uint64_t err = color_distance(true, pSubblock_pixels[p], subblock_colors[r], false);
+ best_err = minimum(best_err, err);
+ if (!best_err)
+ break;
+ }
+
+ total_err += best_err;
+ if (total_err > best_cluster_err)
break;
- }
-
- total_err += best_err;
- if (total_err > best_cluster_err)
- break;
- } // p
- }
- else
- {
+ } // p
+ }
+ else
+ {
#if BASISU_SUPPORT_SSE
- find_lowest_error_perceptual_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
+ find_lowest_error_perceptual_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
#endif
+ }
}
- }
- else
- {
- if (!g_cpu_supports_sse41)
+ else
{
- for (uint32_t p = 0; p < num_subblock_pixels; p++)
+ if (!g_cpu_supports_sse41)
{
- uint64_t best_err = UINT64_MAX;
-
- for (uint32_t r = low_selector; r <= high_selector; r++)
+ for (uint32_t p = 0; p < num_subblock_pixels; p++)
{
- uint64_t err = color_distance(false, pSubblock_pixels[p], subblock_colors[r], false);
- best_err = minimum(best_err, err);
- if (!best_err)
+ uint64_t best_err = UINT64_MAX;
+
+ for (uint32_t r = low_selector; r <= high_selector; r++)
+ {
+ uint64_t err = color_distance(false, pSubblock_pixels[p], subblock_colors[r], false);
+ best_err = minimum(best_err, err);
+ if (!best_err)
+ break;
+ }
+
+ total_err += best_err;
+ if (total_err > best_cluster_err)
break;
- }
-
- total_err += best_err;
- if (total_err > best_cluster_err)
- break;
- } // p
- }
- else
- {
+ } // p
+ }
+ else
+ {
#if BASISU_SUPPORT_SSE
- find_lowest_error_linear_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
+ find_lowest_error_linear_rgb_4_N_sse41((int64_t*)&total_err, subblock_colors, pSubblock_pixels, num_subblock_pixels, best_cluster_err);
#endif
+ }
}
- }
#endif
- skip_cluster:
- if ((total_err < best_cluster_err) ||
- ((cluster_iter == cluster_index) && (total_err == best_cluster_err)))
- {
- best_cluster_err = total_err;
- best_cluster_index = cluster_iter;
-
- if (!best_cluster_err)
- break;
- }
- } // j
-
- best_cluster_indices[block_index] = best_cluster_index;
+ skip_cluster:
+ if ((total_err < best_cluster_err) ||
+ ((cluster_iter == cluster_index) && (total_err == best_cluster_err)))
+ {
+ best_cluster_err = total_err;
+ best_cluster_index = cluster_iter;
- } // block_index
+ if (!best_cluster_err)
+ break;
+ }
+ } // j
+
+ best_cluster_indices[block_index] = best_cluster_index;
+
+ } // block_index
#ifndef __EMSCRIPTEN__
- } );
+ });
#endif
-
- } // block_index_iter
+
+ } // block_index_iter
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
+ m_params.m_pJob_pool->wait_for_all();
#endif
+
+ } // use_cpu
+
+ debug_printf("refine_endpoint_clusterization time: %3.3f secs\n", tm.get_elapsed_secs());
basisu::vector<typename basisu::vector<uint32_t> > optimized_endpoint_clusters(m_endpoint_clusters.size());
uint32_t total_subblocks_reassigned = 0;
@@ -1647,51 +2061,91 @@ namespace basisu
void basisu_frontend::create_initial_packed_texture()
{
debug_printf("create_initial_packed_texture\n");
+
+ interval_timer tm;
+ tm.start();
- const uint32_t N = 4096;
- for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ bool use_cpu = true;
+
+ if ((m_params.m_pOpenCL_context) && (opencl_is_available()))
{
- const uint32_t first_index = block_index_iter;
- const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
+ basisu::vector<color_rgba> block_etc5_color_intens(m_total_blocks);
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ uint32_t cluster0 = m_block_endpoint_clusters_indices[block_index][0];
+
+ const color_rgba& color_unscaled = m_endpoint_cluster_etc_params[cluster0].m_color_unscaled[0];
+ uint32_t inten = m_endpoint_cluster_etc_params[cluster0].m_inten_table[0];
+
+ block_etc5_color_intens[block_index].set(color_unscaled.r, color_unscaled.g, color_unscaled.b, inten);
+ }
+
+ bool status = opencl_determine_selectors(m_params.m_pOpenCL_context, block_etc5_color_intens.data(),
+ m_encoded_blocks.data(),
+ m_params.m_perceptual);
+ if (!status)
+ {
+ error_printf("basisu_frontend::create_initial_packed_texture: opencl_determine_selectors() failed! Using CPU.\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+ else
+ {
+ use_cpu = false;
+ }
+ }
+
+ if (use_cpu)
+ {
+ const uint32_t N = 4096;
+ for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
+ {
+ const uint32_t first_index = block_index_iter;
+ const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index] {
+ m_params.m_pJob_pool->add_job([this, first_index, last_index] {
#endif
-
- for (uint32_t block_index = first_index; block_index < last_index; block_index++)
- {
- uint32_t cluster0 = m_block_endpoint_clusters_indices[block_index][0];
- uint32_t cluster1 = m_block_endpoint_clusters_indices[block_index][1];
- BASISU_FRONTEND_VERIFY(cluster0 == cluster1);
- const color_rgba *pSource_pixels = get_source_pixel_block(block_index).get_ptr();
+ for (uint32_t block_index = first_index; block_index < last_index; block_index++)
+ {
+ uint32_t cluster0 = m_block_endpoint_clusters_indices[block_index][0];
+ uint32_t cluster1 = m_block_endpoint_clusters_indices[block_index][1];
+ BASISU_FRONTEND_VERIFY(cluster0 == cluster1);
- etc_block &blk = m_encoded_blocks[block_index];
+ const color_rgba* pSource_pixels = get_source_pixel_block(block_index).get_ptr();
- color_rgba unscaled[2] = { m_endpoint_cluster_etc_params[cluster0].m_color_unscaled[0], m_endpoint_cluster_etc_params[cluster1].m_color_unscaled[0] };
- uint32_t inten[2] = { m_endpoint_cluster_etc_params[cluster0].m_inten_table[0], m_endpoint_cluster_etc_params[cluster1].m_inten_table[0] };
-
- blk.set_block_color5(unscaled[0], unscaled[1]);
- blk.set_flip_bit(true);
+ etc_block& blk = m_encoded_blocks[block_index];
- blk.set_inten_table(0, inten[0]);
- blk.set_inten_table(1, inten[1]);
+ color_rgba unscaled[2] = { m_endpoint_cluster_etc_params[cluster0].m_color_unscaled[0], m_endpoint_cluster_etc_params[cluster1].m_color_unscaled[0] };
+ uint32_t inten[2] = { m_endpoint_cluster_etc_params[cluster0].m_inten_table[0], m_endpoint_cluster_etc_params[cluster1].m_inten_table[0] };
- blk.determine_selectors(pSource_pixels, m_params.m_perceptual);
-
- } // block_index
+ blk.set_block_color5(unscaled[0], unscaled[1]);
+ blk.set_flip_bit(true);
+
+ blk.set_inten_table(0, inten[0]);
+ blk.set_inten_table(1, inten[1]);
+
+ blk.determine_selectors(pSource_pixels, m_params.m_perceptual);
+
+ } // block_index
#ifndef __EMSCRIPTEN__
- } );
+ });
#endif
- } // block_index_iter
+ } // block_index_iter
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
+ m_params.m_pJob_pool->wait_for_all();
#endif
+ } // use_cpu
+
m_orig_encoded_blocks = m_encoded_blocks;
+
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
}
void basisu_frontend::compute_selector_clusters_within_each_parent_cluster()
@@ -1739,8 +2193,7 @@ namespace basisu
void basisu_frontend::generate_selector_clusters()
{
debug_printf("generate_selector_clusters\n");
-
- typedef vec<16, float> vec16F;
+
typedef tree_vector_quant<vec16F> vec16F_clusterizer;
vec16F_clusterizer::array_of_weighted_training_vecs training_vecs(m_total_blocks);
@@ -1800,12 +2253,14 @@ namespace basisu
uint32_t max_threads = 0;
max_threads = m_params.m_multithreaded ? minimum<int>(std::thread::hardware_concurrency(), cMaxCodebookCreationThreads) : 0;
+ if (m_params.m_pJob_pool)
+ max_threads = minimum<int>((int)m_params.m_pJob_pool->get_total_threads(), max_threads);
bool status = generate_hierarchical_codebook_threaded(selector_clusterizer,
m_params.m_max_selector_clusters, m_use_hierarchical_selector_codebooks ? parent_codebook_size : 0,
m_selector_cluster_block_indices,
m_selector_parent_cluster_block_indices,
- max_threads, m_params.m_pJob_pool);
+ max_threads, m_params.m_pJob_pool, false);
BASISU_FRONTEND_VERIFY(status);
if (m_use_hierarchical_selector_codebooks)
@@ -1864,235 +2319,105 @@ namespace basisu
{
debug_printf("create_optimized_selector_codebook\n");
+ interval_timer tm;
+ tm.start();
+
const uint32_t total_selector_clusters = (uint32_t)m_selector_cluster_block_indices.size();
debug_printf("Total selector clusters (from m_selector_cluster_block_indices.size()): %u\n", (uint32_t)m_selector_cluster_block_indices.size());
m_optimized_cluster_selectors.resize(total_selector_clusters);
+
+ uint32_t total_clusters_processed = 0;
- if ((m_params.m_pGlobal_sel_codebook) && (!m_params.m_use_hybrid_selector_codebooks))
+ // For each selector codebook entry, and for each of the 4x4 selectors, determine which selector minimizes the error across all the blocks that use that quantized selector.
+ const uint32_t N = 256;
+ for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
{
- uint32_t total_clusters_processed = 0;
-
- m_optimized_cluster_selector_global_cb_ids.resize(total_selector_clusters);
+ const uint32_t first_index = cluster_index_iter;
+ const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
- const uint32_t N = 256;
- for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
- {
- const uint32_t first_index = cluster_index_iter;
- const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
-
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index, &total_clusters_processed, &total_selector_clusters] {
-#endif
-
- for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
- {
- const basisu::vector<uint32_t> &cluster_block_indices = m_selector_cluster_block_indices[cluster_index];
-
- if (!cluster_block_indices.size())
- continue;
-
- etc_block_vec etc_blocks;
- pixel_block_vec pixel_blocks;
-
- for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
- {
- const uint32_t block_index = cluster_block_indices[cluster_block_index];
-
- etc_blocks.push_back(m_encoded_blocks[block_index]);
-
- pixel_blocks.push_back(get_source_pixel_block(block_index));
- }
-
- uint32_t palette_index;
- basist::etc1_global_palette_entry_modifier palette_modifier;
-
- #if 0
- m_params.m_pGlobal_sel_codebook->find_best_entry(etc_blocks.size(), pixel_blocks.get_ptr(), etc_blocks.get_ptr(),
- palette_index, palette_modifier,
- m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
- #else
- etc1_global_selector_codebook_find_best_entry(*m_params.m_pGlobal_sel_codebook,
- (uint32_t)etc_blocks.size(), &pixel_blocks[0], &etc_blocks[0],
- palette_index, palette_modifier,
- m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
- #endif
-
- m_optimized_cluster_selector_global_cb_ids[cluster_index].set(palette_index, palette_modifier);
-
- basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(palette_index, palette_modifier));
-
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- m_optimized_cluster_selectors[cluster_index].set_selector(x, y, pal_entry(x, y));
-
- {
- std::lock_guard<std::mutex> lock(m_lock);
-
- total_clusters_processed++;
- if ((total_clusters_processed % 63) == 0)
- debug_printf("Global selector palette optimization: %3.1f%% complete\n", total_clusters_processed * 100.0f / total_selector_clusters);
- }
-
- } // cluster_index
-
-#ifndef __EMSCRIPTEN__
- } );
+#ifndef __EMSCRIPTEN__
+ m_params.m_pJob_pool->add_job([this, first_index, last_index, &total_clusters_processed, &total_selector_clusters] {
#endif
- } // cluster_index_iter
-
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
-#endif
- }
- else
- {
- const bool uses_hybrid_sel_codebook = ((m_params.m_pGlobal_sel_codebook) && (m_params.m_use_hybrid_selector_codebooks));
- if (uses_hybrid_sel_codebook)
- {
- m_selector_cluster_uses_global_cb.resize(total_selector_clusters);
- m_optimized_cluster_selector_global_cb_ids.resize(total_selector_clusters);
- }
+ for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ {
+ const basisu::vector<uint32_t>& cluster_block_indices = m_selector_cluster_block_indices[cluster_index];
- uint32_t total_clusters_processed = 0;
+ if (!cluster_block_indices.size())
+ continue;
- // For each selector codebook entry, and for each of the 4x4 selectors, determine which selector minimizes the error across all the blocks that use that quantized selector.
+ uint64_t overall_best_err = 0;
- const uint32_t N = 256;
- for (uint32_t cluster_index_iter = 0; cluster_index_iter < total_selector_clusters; cluster_index_iter += N)
- {
- const uint32_t first_index = cluster_index_iter;
- const uint32_t last_index = minimum<uint32_t>((uint32_t)total_selector_clusters, cluster_index_iter + N);
+ uint64_t total_err[4][4][4];
+ clear_obj(total_err);
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index, &uses_hybrid_sel_codebook, &total_clusters_processed, &total_selector_clusters] {
-#endif
-
- for (uint32_t cluster_index = first_index; cluster_index < last_index; cluster_index++)
+ for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
{
- const basisu::vector<uint32_t> &cluster_block_indices = m_selector_cluster_block_indices[cluster_index];
+ const uint32_t block_index = cluster_block_indices[cluster_block_index];
- if (!cluster_block_indices.size())
- continue;
+ const etc_block& blk = m_encoded_blocks[block_index];
- uint64_t overall_best_err = 0;
+ color_rgba blk_colors[4];
+ blk.get_block_colors(blk_colors, 0);
for (uint32_t y = 0; y < 4; y++)
{
for (uint32_t x = 0; x < 4; x++)
{
- uint64_t best_err = UINT64_MAX;
- uint32_t best_s = 0;
+ const color_rgba& orig_color = get_source_pixel_block(block_index)(x, y);
- for (uint32_t s = 0; s < 4; s++)
+ if (m_params.m_perceptual)
{
- uint32_t total_err = 0;
-
- for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
- {
- const uint32_t block_index = cluster_block_indices[cluster_block_index];
-
- const etc_block &blk = m_encoded_blocks[block_index];
-
- const color_rgba &orig_color = get_source_pixel_block(block_index)(x, y);
-
- color_rgba block_color;
- blk.get_block_color(block_color, blk.get_subblock_index(x, y), s);
- total_err += color_distance(m_params.m_perceptual, block_color, orig_color, false);
-
- if (total_err > best_err)
- break;
-
- } // block_index
-
- if (total_err < best_err)
- {
- best_err = total_err;
- best_s = s;
- if (!best_err)
- break;
- }
-
- } // s
-
- m_optimized_cluster_selectors[cluster_index].set_selector(x, y, best_s);
-
- overall_best_err += best_err;
-
+ for (uint32_t s = 0; s < 4; s++)
+ total_err[y][x][s] += color_distance(true, blk_colors[s], orig_color, false);
+ }
+ else
+ {
+ for (uint32_t s = 0; s < 4; s++)
+ total_err[y][x][s] += color_distance(false, blk_colors[s], orig_color, false);
+ }
} // x
} // y
- if (uses_hybrid_sel_codebook)
- {
- etc_block_vec etc_blocks;
- pixel_block_vec pixel_blocks;
+ } // cluster_block_index
- for (uint32_t cluster_block_index = 0; cluster_block_index < cluster_block_indices.size(); cluster_block_index++)
- {
- const uint32_t block_index = cluster_block_indices[cluster_block_index];
-
- etc_blocks.push_back(m_encoded_blocks[block_index]);
-
- pixel_blocks.push_back(get_source_pixel_block(block_index));
- }
-
- uint32_t palette_index;
- basist::etc1_global_palette_entry_modifier palette_modifier;
-
- #if 0
- uint64_t best_global_cb_err = m_params.m_pGlobal_sel_codebook->find_best_entry(etc_blocks.size(), pixel_blocks.get_ptr(), etc_blocks.get_ptr(),
- palette_index, palette_modifier,
- m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
- #else
- uint64_t best_global_cb_err = etc1_global_selector_codebook_find_best_entry(*m_params.m_pGlobal_sel_codebook, (uint32_t)etc_blocks.size(), &pixel_blocks[0], &etc_blocks[0],
- palette_index, palette_modifier,
- m_params.m_perceptual, 1 << m_params.m_num_global_sel_codebook_pal_bits, 1 << m_params.m_num_global_sel_codebook_mod_bits);
- #endif
+ for (uint32_t y = 0; y < 4; y++)
+ {
+ for (uint32_t x = 0; x < 4; x++)
+ {
+ uint64_t best_err = total_err[y][x][0];
+ uint8_t best_sel = 0;
- if (best_global_cb_err <= overall_best_err * m_params.m_hybrid_codebook_quality_thresh)
+ for (uint32_t s = 1; s < 4; s++)
{
- m_selector_cluster_uses_global_cb[cluster_index] = true;
-
- m_optimized_cluster_selector_global_cb_ids[cluster_index].set(palette_index, palette_modifier);
-
- basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(palette_index, palette_modifier));
-
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- m_optimized_cluster_selectors[cluster_index].set_selector(x, y, pal_entry(x, y));
+ if (total_err[y][x][s] < best_err)
+ {
+ best_err = total_err[y][x][s];
+ best_sel = (uint8_t)s;
+ }
}
- else
- {
- m_optimized_cluster_selector_global_cb_ids[cluster_index].set(0, basist::etc1_global_palette_entry_modifier(0));
- m_selector_cluster_uses_global_cb[cluster_index] = false;
- }
- }
+ m_optimized_cluster_selectors[cluster_index].set_selector(x, y, best_sel);
- if (uses_hybrid_sel_codebook)
- {
- std::lock_guard<std::mutex> lock(m_lock);
-
- total_clusters_processed++;
- if ((total_clusters_processed % 63) == 0)
- debug_printf("Global selector palette optimization: %3.1f%% complete\n", total_clusters_processed * 100.0f / total_selector_clusters);
- }
+ overall_best_err += best_err;
+ } // x
+ } // y
- } // cluster_index
+ } // cluster_index
#ifndef __EMSCRIPTEN__
- } );
+ });
#endif
- } // cluster_index_iter
+ } // cluster_index_iter
#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->wait_for_all();
+ m_params.m_pJob_pool->wait_for_all();
#endif
- } // if (m_params.m_pGlobal_sel_codebook)
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
if (m_params.m_debug_images)
{
@@ -2133,17 +2458,25 @@ namespace basisu
}
}
+ // For each block: Determine which quantized selectors best encode that block, given its quantized endpoints.
+ // Note that this method may leave some empty clusters (i.e. arrays with no block indices), including at the end.
void basisu_frontend::find_optimal_selector_clusters_for_each_block()
{
debug_printf("find_optimal_selector_clusters_for_each_block\n");
- // Sanity checks
- BASISU_FRONTEND_VERIFY(m_selector_cluster_block_indices.size() == m_optimized_cluster_selectors.size());
- for (uint32_t i = 0; i < m_selector_clusters_within_each_parent_cluster.size(); i++)
+ interval_timer tm;
+ tm.start();
+
+ if (m_params.m_validate)
{
- for (uint32_t j = 0; j < m_selector_clusters_within_each_parent_cluster[i].size(); j++)
+ // Sanity checks
+ BASISU_FRONTEND_VERIFY(m_selector_cluster_block_indices.size() == m_optimized_cluster_selectors.size());
+ for (uint32_t i = 0; i < m_selector_clusters_within_each_parent_cluster.size(); i++)
{
- BASISU_FRONTEND_VERIFY(m_selector_clusters_within_each_parent_cluster[i][j] < m_optimized_cluster_selectors.size());
+ for (uint32_t j = 0; j < m_selector_clusters_within_each_parent_cluster[i].size(); j++)
+ {
+ BASISU_FRONTEND_VERIFY(m_selector_clusters_within_each_parent_cluster[i][j] < m_optimized_cluster_selectors.size());
+ }
}
}
@@ -2151,20 +2484,120 @@ namespace basisu
if (m_params.m_compression_level == 0)
{
- // Don't do anything, just leave the blocks in their original selector clusters.
- for (uint32_t i = 0; i < m_selector_cluster_block_indices.size(); i++)
+ // Just leave the blocks in their original selector clusters.
+ for (uint32_t selector_cluster_index = 0; selector_cluster_index < m_selector_cluster_block_indices.size(); selector_cluster_index++)
{
- for (uint32_t j = 0; j < m_selector_cluster_block_indices[i].size(); j++)
- m_block_selector_cluster_index[m_selector_cluster_block_indices[i][j]] = i;
+ for (uint32_t j = 0; j < m_selector_cluster_block_indices[selector_cluster_index].size(); j++)
+ {
+ const uint32_t block_index = m_selector_cluster_block_indices[selector_cluster_index][j];
+
+ m_block_selector_cluster_index[block_index] = selector_cluster_index;
+
+ etc_block& blk = m_encoded_blocks[block_index];
+ blk.set_raw_selector_bits(m_optimized_cluster_selectors[selector_cluster_index].get_raw_selector_bits());
+ }
}
+
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ return;
}
- else
+
+ bool use_cpu = true;
+
+ if ((m_params.m_pOpenCL_context) && m_use_hierarchical_selector_codebooks)
{
- // Note that this method may leave some empty clusters (i.e. arrays with no block indices), including at the end.
- basisu::vector< basisu::vector<uint32_t> > new_cluster_indices(m_optimized_cluster_selectors.size());
+ const uint32_t num_parent_clusters = m_selector_clusters_within_each_parent_cluster.size();
+
+ basisu::vector<fosc_selector_struct> selector_structs;
+ selector_structs.reserve(m_optimized_cluster_selectors.size());
+
+ uint_vec parent_selector_cluster_offsets(num_parent_clusters);
+
+ uint_vec selector_cluster_indices;
+ selector_cluster_indices.reserve(m_optimized_cluster_selectors.size());
+
+ uint32_t cur_ofs = 0;
+ for (uint32_t parent_index = 0; parent_index < num_parent_clusters; parent_index++)
+ {
+ parent_selector_cluster_offsets[parent_index] = cur_ofs;
+
+ for (uint32_t j = 0; j < m_selector_clusters_within_each_parent_cluster[parent_index].size(); j++)
+ {
+ const uint32_t selector_cluster_index = m_selector_clusters_within_each_parent_cluster[parent_index][j];
+
+ uint32_t sel_bits = 0;
+ for (uint32_t p = 0; p < 16; p++)
+ sel_bits |= (m_optimized_cluster_selectors[selector_cluster_index].get_selector(p & 3, p >> 2) << (p * 2));
+
+ selector_structs.enlarge(1)->m_packed_selectors = sel_bits;
+
+ selector_cluster_indices.push_back(selector_cluster_index);
+ }
+
+ cur_ofs += m_selector_clusters_within_each_parent_cluster[parent_index].size();
+ }
+
+ const uint32_t total_input_selectors = cur_ofs;
- // For each block: Determine which quantized selectors best encode that block, given its quantized endpoints.
+ basisu::vector<fosc_block_struct> block_structs(m_total_blocks);
+ for (uint32_t i = 0; i < m_total_blocks; i++)
+ {
+ const uint32_t parent_selector_cluster = m_block_parent_selector_cluster[i];
+
+ const etc_block& blk = m_encoded_blocks[i];
+ blk.unpack_color5(block_structs[i].m_etc_color5_inten, blk.get_base5_color(), false);
+
+ block_structs[i].m_etc_color5_inten.a = (uint8_t)blk.get_inten_table(0);
+ block_structs[i].m_first_selector = parent_selector_cluster_offsets[parent_selector_cluster];
+ block_structs[i].m_num_selectors = m_selector_clusters_within_each_parent_cluster[parent_selector_cluster].size();
+ }
+
+ uint_vec output_selector_cluster_indices(m_total_blocks);
+
+ bool status = opencl_find_optimal_selector_clusters_for_each_block(
+ m_params.m_pOpenCL_context,
+ block_structs.data(),
+ total_input_selectors,
+ selector_structs.data(),
+ selector_cluster_indices.data(),
+ output_selector_cluster_indices.data(),
+ m_params.m_perceptual);
+
+ if (!status)
+ {
+ error_printf("basisu_frontend::find_optimal_selector_clusters_for_each_block: opencl_find_optimal_selector_clusters_for_each_block() failed! Using CPU.\n");
+ m_params.m_pOpenCL_context = nullptr;
+ m_opencl_failed = true;
+ }
+ else
+ {
+ for (uint32_t i = 0; i < m_selector_cluster_block_indices.size(); i++)
+ {
+ m_selector_cluster_block_indices[i].resize(0);
+ m_selector_cluster_block_indices[i].reserve(128);
+ }
+
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ etc_block& blk = m_encoded_blocks[block_index];
+
+ uint32_t best_cluster_index = output_selector_cluster_indices[block_index];
+
+ blk.set_raw_selector_bits(m_optimized_cluster_selectors[best_cluster_index].get_raw_selector_bits());
+ m_block_selector_cluster_index[block_index] = best_cluster_index;
+
+ vector_ensure_element_is_valid(m_selector_cluster_block_indices, best_cluster_index);
+ m_selector_cluster_block_indices[best_cluster_index].push_back(block_index);
+ }
+
+ use_cpu = false;
+ }
+ }
+
+ if (use_cpu)
+ {
basisu::vector<uint8_t> unpacked_optimized_cluster_selectors(16 * m_optimized_cluster_selectors.size());
for (uint32_t cluster_index = 0; cluster_index < m_optimized_cluster_selectors.size(); cluster_index++)
{
@@ -2176,36 +2609,74 @@ namespace basisu
}
}
}
-
- const uint32_t N = 1024;
+
+ const uint32_t N = 2048;
for (uint32_t block_index_iter = 0; block_index_iter < m_total_blocks; block_index_iter += N)
{
const uint32_t first_index = block_index_iter;
const uint32_t last_index = minimum<uint32_t>(m_total_blocks, first_index + N);
-#ifndef __EMSCRIPTEN__
- m_params.m_pJob_pool->add_job( [this, first_index, last_index, &new_cluster_indices, &unpacked_optimized_cluster_selectors] {
-#endif
+ #ifndef __EMSCRIPTEN__
+ m_params.m_pJob_pool->add_job( [this, first_index, last_index, &unpacked_optimized_cluster_selectors] {
+ #endif
+
+ int prev_best_cluster_index = 0;
for (uint32_t block_index = first_index; block_index < last_index; block_index++)
{
- const color_rgba* pBlock_pixels = get_source_pixel_block(block_index).get_ptr();
-
+ const pixel_block& block = get_source_pixel_block(block_index);
+
etc_block& blk = m_encoded_blocks[block_index];
-
+
+ if ((block_index > first_index) && (block == get_source_pixel_block(block_index - 1)))
+ {
+ blk.set_raw_selector_bits(m_optimized_cluster_selectors[prev_best_cluster_index].get_raw_selector_bits());
+
+ m_block_selector_cluster_index[block_index] = prev_best_cluster_index;
+
+ continue;
+ }
+
+ const color_rgba* pBlock_pixels = block.get_ptr();
+
color_rgba trial_block_colors[4];
- blk.get_block_colors(trial_block_colors, 0);
+ blk.get_block_colors_etc1s(trial_block_colors);
// precompute errors for the i-th block pixel and selector sel: [sel][i]
uint32_t trial_errors[4][16];
-
- for (int sel = 0; sel < 4; ++sel)
+
+ if (m_params.m_perceptual)
{
- for (int i = 0; i < 16; ++i)
- {
- trial_errors[sel][i] = color_distance(m_params.m_perceptual, pBlock_pixels[i], trial_block_colors[sel], false);
- }
+ for (uint32_t sel = 0; sel < 4; ++sel)
+ for (uint32_t i = 0; i < 16; ++i)
+ trial_errors[sel][i] = color_distance(true, pBlock_pixels[i], trial_block_colors[sel], false);
}
+ else
+ {
+ for (uint32_t sel = 0; sel < 4; ++sel)
+ for (uint32_t i = 0; i < 16; ++i)
+ trial_errors[sel][i] = color_distance(false, pBlock_pixels[i], trial_block_colors[sel], false);
+ }
+
+ // Compute the minimum possible errors (given any selectors) for pixels 0-15
+ uint64_t min_possible_error_0_15 = 0;
+ for (uint32_t i = 0; i < 16; i++)
+ min_possible_error_0_15 += basisu::minimum(trial_errors[0][i], trial_errors[1][i], trial_errors[2][i], trial_errors[3][i]);
+
+ // Compute the minimum possible errors (given any selectors) for pixels 4-15
+ uint64_t min_possible_error_4_15 = 0;
+ for (uint32_t i = 4; i < 16; i++)
+ min_possible_error_4_15 += basisu::minimum(trial_errors[0][i], trial_errors[1][i], trial_errors[2][i], trial_errors[3][i]);
+
+ // Compute the minimum possible errors (given any selectors) for pixels 8-15
+ uint64_t min_possible_error_8_15 = 0;
+ for (uint32_t i = 8; i < 16; i++)
+ min_possible_error_8_15 += basisu::minimum(trial_errors[0][i], trial_errors[1][i], trial_errors[2][i], trial_errors[3][i]);
+
+ // Compute the minimum possible errors (given any selectors) for pixels 12-15
+ uint64_t min_possible_error_12_15 = 0;
+ for (uint32_t i = 12; i < 16; i++)
+ min_possible_error_12_15 += basisu::minimum(trial_errors[0][i], trial_errors[1][i], trial_errors[2][i], trial_errors[3][i]);
uint64_t best_cluster_err = INT64_MAX;
uint32_t best_cluster_index = 0;
@@ -2215,7 +2686,7 @@ namespace basisu
const uint32_t total_clusters = m_use_hierarchical_selector_codebooks ? (uint32_t)pCluster_indices->size() : (uint32_t)m_selector_cluster_block_indices.size();
-#if 0
+ #if 0
for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
{
const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
@@ -2246,99 +2717,73 @@ namespace basisu
early_out:
;
}
-#else
- if (m_params.m_perceptual)
- {
- for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
- {
- const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
- //const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
-
- uint64_t trial_err = 0;
-
- for (int i = 0; i < 16; i++)
- {
- const uint32_t sel = unpacked_optimized_cluster_selectors[cluster_index * 16 + i];
-
- trial_err += trial_errors[sel][i];
- if (trial_err > best_cluster_err)
- goto early_out;
- }
-
- if (trial_err < best_cluster_err)
- {
- best_cluster_err = trial_err;
- best_cluster_index = cluster_index;
- if (!best_cluster_err)
- break;
- }
-
- early_out:
- ;
-
- } // cluster_iter
- }
- else
+ #else
+ for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
{
- for (uint32_t cluster_iter = 0; cluster_iter < total_clusters; cluster_iter++)
- {
- const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
- //const etc_block& cluster_blk = m_optimized_cluster_selectors[cluster_index];
+ const uint32_t cluster_index = m_use_hierarchical_selector_codebooks ? (*pCluster_indices)[cluster_iter] : cluster_iter;
+
+ const uint8_t* pSels = &unpacked_optimized_cluster_selectors[cluster_index * 16];
- uint64_t trial_err = 0;
+ uint64_t trial_err = (uint64_t)trial_errors[pSels[0]][0] + trial_errors[pSels[1]][1] + trial_errors[pSels[2]][2] + trial_errors[pSels[3]][3];
+ if ((trial_err + min_possible_error_4_15) >= best_cluster_err)
+ continue;
- for (int i = 0; i < 16; i++)
- {
- const uint32_t sel = unpacked_optimized_cluster_selectors[cluster_index * 16 + i];
+ trial_err += (uint64_t)trial_errors[pSels[4]][4] + trial_errors[pSels[5]][5] + trial_errors[pSels[6]][6] + trial_errors[pSels[7]][7];
+ if ((trial_err + min_possible_error_8_15) >= best_cluster_err)
+ continue;
- trial_err += trial_errors[sel][i];
- if (trial_err > best_cluster_err)
- goto early_out2;
- }
+ trial_err += (uint64_t)trial_errors[pSels[8]][8] + trial_errors[pSels[9]][9] + trial_errors[pSels[10]][10] + trial_errors[pSels[11]][11];
+ if ((trial_err + min_possible_error_12_15) >= best_cluster_err)
+ continue;
- if (trial_err < best_cluster_err)
- {
- best_cluster_err = trial_err;
- best_cluster_index = cluster_index;
- if (!best_cluster_err)
- break;
- }
+ trial_err += (uint64_t)trial_errors[pSels[12]][12] + trial_errors[pSels[13]][13] + trial_errors[pSels[14]][14] + trial_errors[pSels[15]][15];
- early_out2:
- ;
+ if (trial_err < best_cluster_err)
+ {
+ best_cluster_err = trial_err;
+ best_cluster_index = cluster_index;
+ if (best_cluster_err == min_possible_error_0_15)
+ break;
+ }
- } // cluster_iter
- }
-#endif
+ } // cluster_iter
+ #endif
blk.set_raw_selector_bits(m_optimized_cluster_selectors[best_cluster_index].get_raw_selector_bits());
m_block_selector_cluster_index[block_index] = best_cluster_index;
-
- {
- std::lock_guard<std::mutex> lock(m_lock);
- vector_ensure_element_is_valid(new_cluster_indices, best_cluster_index);
- new_cluster_indices[best_cluster_index].push_back(block_index);
- }
+ prev_best_cluster_index = best_cluster_index;
} // block_index
-#ifndef __EMSCRIPTEN__
+ #ifndef __EMSCRIPTEN__
} );
-#endif
+ #endif
} // block_index_iter
-#ifndef __EMSCRIPTEN__
+ #ifndef __EMSCRIPTEN__
m_params.m_pJob_pool->wait_for_all();
-#endif
+ #endif
+
+ for (uint32_t i = 0; i < m_selector_cluster_block_indices.size(); i++)
+ {
+ m_selector_cluster_block_indices[i].resize(0);
+ m_selector_cluster_block_indices[i].reserve(128);
+ }
- m_selector_cluster_block_indices.swap(new_cluster_indices);
- }
+ for (uint32_t block_index = 0; block_index < m_total_blocks; block_index++)
+ {
+ const uint32_t best_cluster_index = m_block_selector_cluster_index[block_index];
- for (uint32_t i = 0; i < m_selector_cluster_block_indices.size(); i++)
- vector_sort(m_selector_cluster_block_indices[i]);
+ vector_ensure_element_is_valid(m_selector_cluster_block_indices, best_cluster_index);
+ m_selector_cluster_block_indices[best_cluster_index].push_back(block_index);
+ }
+
+ } // if (use_cpu)
+
+ debug_printf("Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
}
// TODO: Remove old ETC1 specific stuff, and thread this.
@@ -2837,7 +3282,81 @@ namespace basisu
//debug_printf("validate_output: %u\n", validate_output());
}
-
+
+ // Endpoint clusterization hierarchy integrity checker.
+ // Note this doesn't check for empty clusters.
+ bool basisu_frontend::validate_endpoint_cluster_hierarchy(bool ensure_clusters_have_same_parents) const
+ {
+ if (!m_endpoint_parent_clusters.size())
+ return true;
+
+ int_vec subblock_parent_indices(m_total_blocks * 2);
+ subblock_parent_indices.set_all(-1);
+
+ int_vec subblock_cluster_indices(m_total_blocks * 2);
+ subblock_cluster_indices.set_all(-1);
+
+ for (uint32_t parent_index = 0; parent_index < m_endpoint_parent_clusters.size(); parent_index++)
+ {
+ for (uint32_t i = 0; i < m_endpoint_parent_clusters[parent_index].size(); i++)
+ {
+ uint32_t subblock_index = m_endpoint_parent_clusters[parent_index][i];
+ if (subblock_index >= m_total_blocks * 2)
+ return false;
+
+ // If the endpoint cluster lives in more than one parent node, that's wrong.
+ if (subblock_parent_indices[subblock_index] != -1)
+ return false;
+
+ subblock_parent_indices[subblock_index] = parent_index;
+ }
+ }
+
+ // Make sure all endpoint clusters are present in the parent cluster.
+ for (uint32_t i = 0; i < subblock_parent_indices.size(); i++)
+ {
+ if (subblock_parent_indices[i] == -1)
+ return false;
+ }
+
+ for (uint32_t cluster_index = 0; cluster_index < m_endpoint_clusters.size(); cluster_index++)
+ {
+ int parent_index = 0;
+
+ for (uint32_t i = 0; i < m_endpoint_clusters[cluster_index].size(); i++)
+ {
+ uint32_t subblock_index = m_endpoint_clusters[cluster_index][i];
+ if (subblock_index >= m_total_blocks * 2)
+ return false;
+
+ if (subblock_cluster_indices[subblock_index] != -1)
+ return false;
+
+ subblock_cluster_indices[subblock_index] = cluster_index;
+
+ // There are transformations on the endpoint clusters that can break the strict tree requirement
+ if (ensure_clusters_have_same_parents)
+ {
+ // Make sure all the subblocks are in the same parent cluster
+ if (!i)
+ parent_index = subblock_parent_indices[subblock_index];
+ else if (subblock_parent_indices[subblock_index] != parent_index)
+ return false;
+ }
+ }
+ }
+
+ // Make sure all endpoint clusters are present in the parent cluster.
+ for (uint32_t i = 0; i < subblock_cluster_indices.size(); i++)
+ {
+ if (subblock_cluster_indices[i] == -1)
+ return false;
+ }
+
+ return true;
+ }
+
+ // This is very slow and only intended for debugging/development. It's enabled using the "-validate_etc1s" command line option.
bool basisu_frontend::validate_output() const
{
debug_printf("validate_output\n");
@@ -2889,29 +3408,7 @@ namespace basisu
CHECK(rdo_output_block.get_base5_color() == blk.get_base5_color());
CHECK(rdo_output_block.get_delta3_color() == blk.get_delta3_color());
CHECK(rdo_output_block.get_raw_selector_bits() == blk.get_raw_selector_bits());
-
- if (m_params.m_pGlobal_sel_codebook)
- {
- bool used_global_cb = true;
- if (m_params.m_use_hybrid_selector_codebooks)
- used_global_cb = m_selector_cluster_uses_global_cb[selector_cluster_index];
-
- if (used_global_cb)
- {
- basist::etc1_global_selector_codebook_entry_id pal_id(get_selector_cluster_global_selector_entry_ids()[selector_cluster_index]);
-
- basist::etc1_selector_palette_entry pal_entry(m_params.m_pGlobal_sel_codebook->get_entry(pal_id));
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- CHECK(pal_entry(x, y) == blk.get_selector(x, y));
- }
- }
- }
- }
-
+
#undef CHECK
}
diff --git a/thirdparty/basis_universal/encoder/basisu_frontend.h b/thirdparty/basis_universal/encoder/basisu_frontend.h
index 4ff6d40466..cda73f3984 100644
--- a/thirdparty/basis_universal/encoder/basisu_frontend.h
+++ b/thirdparty/basis_universal/encoder/basisu_frontend.h
@@ -16,12 +16,14 @@
#include "basisu_enc.h"
#include "basisu_etc.h"
#include "basisu_gpu_texture.h"
-#include "basisu_global_selector_palette_helpers.h"
#include "../transcoder/basisu_file_headers.h"
#include "../transcoder/basisu_transcoder.h"
namespace basisu
{
+ struct opencl_context;
+ typedef opencl_context* opencl_context_ptr;
+
struct vec2U
{
uint32_t m_comps[2];
@@ -51,7 +53,8 @@ namespace basisu
m_use_hierarchical_endpoint_codebooks(false),
m_use_hierarchical_selector_codebooks(false),
m_num_endpoint_codebook_iterations(0),
- m_num_selector_codebook_iterations(0)
+ m_num_selector_codebook_iterations(0),
+ m_opencl_failed(false)
{
}
@@ -73,19 +76,12 @@ namespace basisu
m_perceptual(true),
m_debug_stats(false),
m_debug_images(false),
-
m_dump_endpoint_clusterization(true),
m_validate(false),
m_multithreaded(false),
m_disable_hierarchical_endpoint_codebooks(false),
- m_pGlobal_sel_codebook(NULL),
- m_num_global_sel_codebook_pal_bits(0),
- m_num_global_sel_codebook_mod_bits(0),
- m_use_hybrid_selector_codebooks(false),
- m_hybrid_codebook_quality_thresh(0.0f),
m_tex_type(basist::cBASISTexType2D),
- m_pGlobal_codebooks(nullptr),
-
+ m_pOpenCL_context(nullptr),
m_pJob_pool(nullptr)
{
}
@@ -106,13 +102,10 @@ namespace basisu
bool m_multithreaded;
bool m_disable_hierarchical_endpoint_codebooks;
- const basist::etc1_global_selector_codebook *m_pGlobal_sel_codebook;
- uint32_t m_num_global_sel_codebook_pal_bits;
- uint32_t m_num_global_sel_codebook_mod_bits;
- bool m_use_hybrid_selector_codebooks;
- float m_hybrid_codebook_quality_thresh;
basist::basis_texture_type m_tex_type;
const basist::basisu_lowlevel_etc1s_transcoder *m_pGlobal_codebooks;
+
+ opencl_context_ptr m_pOpenCL_context;
job_pool *m_pJob_pool;
};
@@ -150,10 +143,7 @@ namespace basisu
uint32_t get_total_selector_clusters() const { return static_cast<uint32_t>(m_selector_cluster_block_indices.size()); }
uint32_t get_block_selector_cluster_index(uint32_t block_index) const { return m_block_selector_cluster_index[block_index]; }
const etc_block &get_selector_cluster_selector_bits(uint32_t cluster_index) const { return m_optimized_cluster_selectors[cluster_index]; }
-
- const basist::etc1_global_selector_codebook_entry_id_vec &get_selector_cluster_global_selector_entry_ids() const { return m_optimized_cluster_selector_global_cb_ids; }
- const bool_vec &get_selector_cluster_uses_global_cb_vec() const { return m_selector_cluster_uses_global_cb; }
-
+
// Returns block indices using each selector cluster
const uint_vec &get_selector_cluster_block_indices(uint32_t selector_cluster_index) const { return m_selector_cluster_block_indices[selector_cluster_index]; }
@@ -161,6 +151,8 @@ namespace basisu
void reoptimize_remapped_endpoints(const uint_vec &new_block_endpoints, int_vec &old_to_new_endpoint_cluster_indices, bool optimize_final_codebook, uint_vec *pBlock_selector_indices = nullptr);
+ bool get_opencl_failed() const { return m_opencl_failed; }
+
private:
params m_params;
uint32_t m_total_blocks;
@@ -192,13 +184,14 @@ namespace basisu
vec6F_quantizer m_endpoint_clusterizer;
// For each endpoint cluster: An array of which subblock indices (block_index*2+subblock) are located in that cluster.
- // Array of block indices for each endpoint cluster
basisu::vector<uint_vec> m_endpoint_clusters;
- // Array of block indices for each parent endpoint cluster
+ // Array of subblock indices for each parent endpoint cluster
+ // Note: Initially, each endpoint cluster will only live in a single parent cluster, in a shallow tree.
+ // As the endpoint clusters are manipulated this constraint gets broken.
basisu::vector<uint_vec> m_endpoint_parent_clusters;
- // Each block's parent cluster index
+ // Each block's parent endpoint cluster index
uint8_vec m_block_parent_endpoint_cluster;
// Array of endpoint cluster indices for each parent endpoint cluster
@@ -295,10 +288,7 @@ namespace basisu
// Array of selector cluster indices for each parent selector cluster
basisu::vector<uint_vec> m_selector_clusters_within_each_parent_cluster;
-
- basist::etc1_global_selector_codebook_entry_id_vec m_optimized_cluster_selector_global_cb_ids;
- bool_vec m_selector_cluster_uses_global_cb;
-
+
// Each block's selector cluster index
basisu::vector<uint32_t> m_block_selector_cluster_index;
@@ -330,6 +320,8 @@ namespace basisu
std::mutex m_lock;
+ bool m_opencl_failed;
+
//-----------------------------------------------------------------------------
void init_etc1_images();
@@ -351,6 +343,7 @@ namespace basisu
void find_optimal_selector_clusters_for_each_block();
uint32_t refine_block_endpoints_given_selectors();
void finalize();
+ bool validate_endpoint_cluster_hierarchy(bool ensure_clusters_have_same_parents) const;
bool validate_output() const;
void introduce_special_selector_clusters();
void optimize_selector_codebook();
diff --git a/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.cpp b/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.cpp
deleted file mode 100644
index 102fc24980..0000000000
--- a/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// basiu_global_selector_palette_helpers.cpp
-// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#include "basisu_global_selector_palette_helpers.h"
-
-namespace basisu
-{
- uint64_t etc1_global_selector_codebook_find_best_entry(const basist::etc1_global_selector_codebook &codebook,
- uint32_t num_src_pixel_blocks, const pixel_block *pSrc_pixel_blocks, const etc_block *pBlock_endpoints,
- uint32_t &palette_index, basist::etc1_global_palette_entry_modifier &palette_modifier,
- bool perceptual, uint32_t max_pal_entries, uint32_t max_modifiers)
- {
- uint64_t best_err = UINT64_MAX;
- uint32_t best_pal_index = 0;
- basist::etc1_global_palette_entry_modifier best_pal_modifier;
-
- if (!max_pal_entries)
- max_pal_entries = codebook.size();
-
- if (!max_modifiers)
- max_modifiers = basist::etc1_global_palette_entry_modifier::cTotalValues;
-
- for (uint32_t pal_index = 0; pal_index < max_pal_entries; pal_index++)
- {
- for (uint32_t mod_index = 0; mod_index < max_modifiers; mod_index++)
- {
- const basist::etc1_global_palette_entry_modifier pal_modifier(mod_index);
-
- const basist::etc1_selector_palette_entry pal_entry(codebook.get_entry(pal_index, pal_modifier));
-
- uint64_t trial_err = 0;
- for (uint32_t block_index = 0; block_index < num_src_pixel_blocks; block_index++)
- {
- etc_block trial_block(pBlock_endpoints[block_index]);
-
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- trial_block.set_selector(x, y, pal_entry(x, y));
-
- trial_err += trial_block.evaluate_etc1_error(reinterpret_cast<const basisu::color_rgba *>(pSrc_pixel_blocks[block_index].get_ptr()), perceptual);
- if (trial_err >= best_err)
- break;
- }
-
- if (trial_err < best_err)
- {
- best_err = trial_err;
- best_pal_index = pal_index;
- best_pal_modifier = pal_modifier;
- }
- } // mod_index
- } // pal_index
-
- palette_index = best_pal_index;
- palette_modifier = best_pal_modifier;
-
- return best_err;
- }
-
-} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.h b/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.h
deleted file mode 100644
index 7c35439df8..0000000000
--- a/thirdparty/basis_universal/encoder/basisu_global_selector_palette_helpers.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// File: basisu_global_selector_palette_helpers.h
-// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#pragma once
-
-#include "../transcoder/basisu.h"
-#include "basisu_etc.h"
-#include "../transcoder/basisu_global_selector_palette.h"
-
-namespace basisu
-{
- const uint32_t cPixelBlockWidth = 4;
- const uint32_t cPixelBlockHeight = 4;
- const uint32_t cPixelBlockTotalPixels = cPixelBlockWidth * cPixelBlockHeight;
-
- struct pixel_block
- {
- color_rgba m_pixels[cPixelBlockHeight][cPixelBlockWidth]; // [y][x]
-
- const color_rgba &operator() (uint32_t x, uint32_t y) const { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
- color_rgba &operator() (uint32_t x, uint32_t y) { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
-
- const color_rgba *get_ptr() const { return &m_pixels[0][0]; }
- color_rgba *get_ptr() { return &m_pixels[0][0]; }
-
- void clear() { clear_obj(*this); }
- };
- typedef basisu::vector<pixel_block> pixel_block_vec;
-
- uint64_t etc1_global_selector_codebook_find_best_entry(const basist::etc1_global_selector_codebook &codebook,
- uint32_t num_src_pixel_blocks, const pixel_block *pSrc_pixel_blocks, const etc_block *pBlock_endpoints,
- uint32_t &palette_index, basist::etc1_global_palette_entry_modifier &palette_modifier,
- bool perceptual, uint32_t max_pal_entries, uint32_t max_modifiers);
-
-} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
index 3f9fb67bdd..dec769d5ac 100644
--- a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
@@ -15,7 +15,9 @@
#include "basisu_gpu_texture.h"
#include "basisu_enc.h"
#include "basisu_pvrtc1_4.h"
+#if BASISU_USE_ASTC_DECOMPRESS
#include "basisu_astc_decomp.h"
+#endif
#include "basisu_bc7enc.h"
namespace basisu
@@ -1150,8 +1152,12 @@ namespace basisu
}
case texture_format::cASTC4x4:
{
+#if BASISU_USE_ASTC_DECOMPRESS
const bool astc_srgb = false;
basisu_astc::astc::decompress(reinterpret_cast<uint8_t*>(pPixels), static_cast<const uint8_t*>(pBlock), astc_srgb, 4, 4);
+#else
+ memset(pPixels, 255, 16 * sizeof(color_rgba));
+#endif
break;
}
case texture_format::cATC_RGB:
@@ -1498,6 +1504,8 @@ namespace basisu
header.m_pixelWidth = width;
header.m_pixelHeight = height;
+
+ header.m_glTypeSize = 1;
header.m_glInternalFormat = internal_fmt;
header.m_glBaseInternalFormat = base_internal_fmt;
diff --git a/thirdparty/basis_universal/encoder/basisu_kernels_declares.h b/thirdparty/basis_universal/encoder/basisu_kernels_declares.h
index e24bdd7978..b03e2ea6e8 100644
--- a/thirdparty/basis_universal/encoder/basisu_kernels_declares.h
+++ b/thirdparty/basis_universal/encoder/basisu_kernels_declares.h
@@ -22,4 +22,6 @@ void CPPSPMD_NAME(find_selectors_linear_rgb_4_N)(int64_t* pDistance, uint8_t* pS
void CPPSPMD_NAME(find_lowest_error_perceptual_rgb_4_N)(int64_t* pDistance, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error);
void CPPSPMD_NAME(find_lowest_error_linear_rgb_4_N)(int64_t* pDistance, const basisu::color_rgba* pBlock_colors, const basisu::color_rgba* pSrc_pixels, uint32_t n, int64_t early_out_error);
+
+void CPPSPMD_NAME(update_covar_matrix_16x16)(uint32_t num_vecs, const void* pWeighted_vecs, const void *pOrigin, const uint32_t* pVec_indices, void *pMatrix16x16);
#endif
diff --git a/thirdparty/basis_universal/encoder/basisu_kernels_imp.h b/thirdparty/basis_universal/encoder/basisu_kernels_imp.h
index 046880517b..dcf1ce069a 100644
--- a/thirdparty/basis_universal/encoder/basisu_kernels_imp.h
+++ b/thirdparty/basis_universal/encoder/basisu_kernels_imp.h
@@ -548,6 +548,65 @@ namespace CPPSPMD_NAME(basisu_kernels_namespace)
}
};
+ struct update_covar_matrix_16x16 : spmd_kernel
+ {
+ void _call(
+ uint32_t num_vecs, const void* pWeighted_vecs_void, const void* pOrigin_void, const uint32_t* pVec_indices, void* pMatrix16x16_void)
+ {
+ const std::pair<vec16F, uint64_t>* pWeighted_vecs = static_cast< const std::pair<vec16F, uint64_t> *>(pWeighted_vecs_void);
+
+ const float* pOrigin = static_cast<const float*>(pOrigin_void);
+ vfloat org0 = loadu_linear_all(pOrigin), org1 = loadu_linear_all(pOrigin + 4), org2 = loadu_linear_all(pOrigin + 8), org3 = loadu_linear_all(pOrigin + 12);
+
+ vfloat mat[16][4];
+ vfloat vzero(zero_vfloat());
+
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ store_all(mat[i][0], vzero);
+ store_all(mat[i][1], vzero);
+ store_all(mat[i][2], vzero);
+ store_all(mat[i][3], vzero);
+ }
+
+ for (uint32_t k = 0; k < num_vecs; k++)
+ {
+ const uint32_t vec_index = pVec_indices[k];
+
+ const float* pW = pWeighted_vecs[vec_index].first.get_ptr();
+ vfloat weight((float)pWeighted_vecs[vec_index].second);
+
+ vfloat vec[4] = { loadu_linear_all(pW) - org0, loadu_linear_all(pW + 4) - org1, loadu_linear_all(pW + 8) - org2, loadu_linear_all(pW + 12) - org3 };
+
+ vfloat wvec0 = vec[0] * weight, wvec1 = vec[1] * weight, wvec2 = vec[2] * weight, wvec3 = vec[3] * weight;
+
+ for (uint32_t j = 0; j < 16; j++)
+ {
+ vfloat vx = ((const float*)vec)[j];
+
+ store_all(mat[j][0], mat[j][0] + vx * wvec0);
+ store_all(mat[j][1], mat[j][1] + vx * wvec1);
+ store_all(mat[j][2], mat[j][2] + vx * wvec2);
+ store_all(mat[j][3], mat[j][3] + vx * wvec3);
+
+ } // j
+
+ } // k
+
+ float* pMatrix = static_cast<float*>(pMatrix16x16_void);
+
+ float* pDst = pMatrix;
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ storeu_linear_all(pDst, mat[i][0]);
+ storeu_linear_all(pDst + 4, mat[i][1]);
+ storeu_linear_all(pDst + 8, mat[i][2]);
+ storeu_linear_all(pDst + 12, mat[i][3]);
+ pDst += 16;
+ }
+ }
+ };
+
} // namespace
using namespace CPPSPMD_NAME(basisu_kernels_namespace);
@@ -582,3 +641,7 @@ void CPPSPMD_NAME(find_lowest_error_linear_rgb_4_N)(int64_t* pDistance, const co
spmd_call< find_lowest_error_linear_rgb_4_N >(pDistance, pBlock_colors, pSrc_pixels, n, early_out_error);
}
+void CPPSPMD_NAME(update_covar_matrix_16x16)(uint32_t num_vecs, const void* pWeighted_vecs, const void* pOrigin, const uint32_t *pVec_indices, void* pMatrix16x16)
+{
+ spmd_call < update_covar_matrix_16x16 >(num_vecs, pWeighted_vecs, pOrigin, pVec_indices, pMatrix16x16);
+}
diff --git a/thirdparty/basis_universal/encoder/basisu_kernels_sse.cpp b/thirdparty/basis_universal/encoder/basisu_kernels_sse.cpp
index 12d2321f20..4f15a5a12b 100644
--- a/thirdparty/basis_universal/encoder/basisu_kernels_sse.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_kernels_sse.cpp
@@ -32,7 +32,7 @@
#error SSE4.1/SSE3/SSE4.2/SSSE3 cannot be enabled to use this file
#endif
#else
- #if !__SSE4_1__ || !__SSE3__ || __SSE4_2__ || !__SSSE3__
+ #if !__SSE4_1__ || !__SSE3__ || !__SSSE3__
#error Please check your compiler options
#endif
#endif
diff --git a/thirdparty/basis_universal/encoder/basisu_miniz.h b/thirdparty/basis_universal/encoder/basisu_miniz.h
index 8627abe893..18de997232 100644
--- a/thirdparty/basis_universal/encoder/basisu_miniz.h
+++ b/thirdparty/basis_universal/encoder/basisu_miniz.h
@@ -76,6 +76,14 @@
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
#endif
+// Using unaligned loads and stores causes errors when using UBSan. Jam it off.
+#if defined(__has_feature)
+#if __has_feature(undefined_behavior_sanitizer)
+#undef MINIZ_USE_UNALIGNED_LOADS_AND_STORES
+#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
+#endif
+#endif
+
#if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__)
// Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions).
#define MINIZ_HAS_64BIT_REGISTERS 1
@@ -236,6 +244,7 @@ int mz_inflateInit2(mz_streamp pStream, int window_bits);
// MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again
// with more input data, or with more room in the output buffer (except when using single call decompression, described above).
int mz_inflate(mz_streamp pStream, int flush);
+int mz_inflate2(mz_streamp pStream, int flush, int adler32_checking);
// Deinitializes a decompressor.
int mz_inflateEnd(mz_streamp pStream);
@@ -880,10 +889,10 @@ int mz_inflateInit(mz_streamp pStream)
return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
}
-int mz_inflate(mz_streamp pStream, int flush)
+int mz_inflate2(mz_streamp pStream, int flush, int adler32_checking)
{
inflate_state* pState;
- mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
+ mz_uint n, first_call, decomp_flags = adler32_checking ? TINFL_FLAG_COMPUTE_ADLER32 : 0;
size_t in_bytes, out_bytes, orig_avail_in;
tinfl_status status;
@@ -971,6 +980,11 @@ int mz_inflate(mz_streamp pStream, int flush)
return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
}
+int mz_inflate(mz_streamp pStream, int flush)
+{
+ return mz_inflate2(pStream, flush, MZ_TRUE);
+}
+
int mz_inflateEnd(mz_streamp pStream)
{
if (!pStream)
@@ -1348,7 +1362,8 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_nex
common_exit:
r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start;
*pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
- if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
+ //if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
+ if ((decomp_flags & TINFL_FLAG_COMPUTE_ADLER32) && (status >= 0))
{
const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size;
mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552;
@@ -1362,7 +1377,9 @@ common_exit:
for ( ; i < block_len; ++i) s1 += *ptr++, s2 += s1;
s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552;
}
- r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH;
+ r->m_check_adler32 = (s2 << 16) + s1;
+ if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
+ status = TINFL_STATUS_ADLER32_MISMATCH;
}
return status;
}
@@ -2479,7 +2496,7 @@ void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int
// write dummy header
for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf);
// compress image data
- tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
+ tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER | (level <= 3 ? TDEFL_GREEDY_PARSING_FLAG : 0));
for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH); }
if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; }
// write real header
diff --git a/thirdparty/basis_universal/encoder/basisu_ocl_kernels.h b/thirdparty/basis_universal/encoder/basisu_ocl_kernels.h
new file mode 100644
index 0000000000..46db61bf18
--- /dev/null
+++ b/thirdparty/basis_universal/encoder/basisu_ocl_kernels.h
@@ -0,0 +1,1439 @@
+unsigned char ocl_kernels_cl[] = {
+ 0x2f, 0x2f, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x69, 0x66, 0x6e, 0x64, 0x65, 0x66, 0x20, 0x4e, 0x55, 0x4c, 0x4c,
+ 0x0d, 0x0a, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x20, 0x30, 0x4c, 0x0d, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79,
+ 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x75, 0x63, 0x68, 0x61,
+ 0x72, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x31,
+ 0x36, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x75, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x3b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x69,
+ 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x3b, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x75, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x75, 0x63, 0x68, 0x61, 0x72, 0x34, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x3b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x5f, 0x4d, 0x41, 0x58, 0x20, 0x30, 0x78, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x55,
+ 0x4c, 0x0d, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x20, 0x4c, 0x4f, 0x4e, 0x47, 0x5f, 0x4d, 0x41, 0x58, 0x0d, 0x0a, 0x23,
+ 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x20, 0x55, 0x4c, 0x4f, 0x4e, 0x47, 0x5f, 0x4d, 0x41, 0x58, 0x0d, 0x0a, 0x0d, 0x0a, 0x69,
+ 0x6e, 0x74, 0x20, 0x73, 0x71, 0x75, 0x61, 0x72, 0x65, 0x69, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x61, 0x29, 0x20, 0x7b, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x2a, 0x20, 0x61,
+ 0x3b, 0x20, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x69, 0x66, 0x64, 0x65, 0x66, 0x20, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x76, 0x6f,
+ 0x69, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x78, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x61, 0x6e, 0x74, 0x20, 0x63, 0x68, 0x61, 0x72, 0x20, 0x2a, 0x70, 0x4d, 0x73, 0x67, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x69, 0x66, 0x20, 0x28, 0x21, 0x78, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, 0x28, 0x22, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x29, 0x20, 0x66, 0x61,
+ 0x69, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x25, 0x69, 0x3a, 0x20, 0x25, 0x73, 0x5c, 0x6e, 0x22, 0x2c, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x2c, 0x20, 0x70, 0x4d,
+ 0x73, 0x67, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x78, 0x29, 0x20, 0x69, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x78, 0x2c, 0x20, 0x23, 0x78, 0x2c, 0x20, 0x5f, 0x5f, 0x4c, 0x49, 0x4e, 0x45, 0x5f, 0x5f, 0x29, 0x0d, 0x0a, 0x23,
+ 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x78, 0x29, 0x0d, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x69, 0x6e, 0x74, 0x20,
+ 0x78, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x78, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66,
+ 0x6c, 0x61, 0x67, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x2a, 0x70, 0x44, 0x69, 0x64, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x29, 0x0d, 0x0a, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x78, 0x20, 0x3c, 0x20, 0x30, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x2a, 0x70, 0x44, 0x69, 0x64, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x20,
+ 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x20,
+ 0x69, 0x66, 0x20, 0x28, 0x78, 0x20, 0x3e, 0x20, 0x32, 0x35, 0x35, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x2a, 0x70, 0x44, 0x69, 0x64, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x20,
+ 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x32, 0x35, 0x35, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72,
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x28, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65,
+ 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29,
+ 0x29, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d,
+ 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x70, 0x65, 0x72, 0x6d, 0x73, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72,
+ 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75,
+ 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x0d,
+ 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x31, 0x36, 0x5d, 0x3b, 0x20, 0x2f, 0x2f,
+ 0x20, 0x5b, 0x79, 0x2a, 0x34, 0x2b, 0x78, 0x5d, 0x0d, 0x0a, 0x7d, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x65, 0x31, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x65, 0x32, 0x2c, 0x20, 0x62,
+ 0x6f, 0x6f, 0x6c, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x29, 0x0d,
+ 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x23, 0x69, 0x66, 0x20, 0x30, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x67, 0x62, 0x20, 0x3d,
+ 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x29, 0x28, 0x65, 0x31, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x78, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x65, 0x32,
+ 0x2e, 0x79, 0x2c, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x7a, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x64, 0x6f,
+ 0x74, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x67, 0x62, 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x29, 0x28, 0x2e, 0x32, 0x31, 0x32, 0x36, 0x66, 0x2c, 0x20, 0x2e, 0x37,
+ 0x31, 0x35, 0x32, 0x66, 0x2c, 0x20, 0x2e, 0x30, 0x37, 0x32, 0x32, 0x66, 0x29, 0x29, 0x3b, 0x20, 0x2f, 0x2f, 0x20, 0x79, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63,
+ 0x62, 0x63, 0x72, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x67, 0x62, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63,
+ 0x72, 0x2e, 0x78, 0x3b, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x72, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x67, 0x62, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72, 0x2e, 0x78, 0x3b, 0x20, 0x2f, 0x2f, 0x20, 0x63, 0x62,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72, 0x20, 0x2a, 0x3d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72,
+ 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x64, 0x20, 0x3d, 0x20, 0x64, 0x6f, 0x74, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x79, 0x63, 0x62, 0x63, 0x72,
+ 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x29, 0x28, 0x31, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x30, 0x2e, 0x32, 0x30, 0x33, 0x31, 0x32, 0x35, 0x66, 0x2c, 0x20, 0x30, 0x2e, 0x30, 0x32,
+ 0x33, 0x34, 0x33, 0x37, 0x35, 0x66, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x61, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x77, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x09, 0x64, 0x20, 0x2b, 0x3d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x61, 0x20, 0x2a, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x61, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x09, 0x09, 0x64, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x64, 0x20, 0x2a, 0x20, 0x32, 0x35, 0x36, 0x2e, 0x30, 0x66, 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x2c, 0x20,
+ 0x30, 0x2e, 0x30, 0x66, 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x5f, 0x4d, 0x41, 0x58, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x72,
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x64, 0x29, 0x3b, 0x0d, 0x0a, 0x23, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x54, 0x68,
+ 0x69, 0x73, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x50, 0x55, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x69,
+ 0x73, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x72, 0x20,
+ 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x20,
+ 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x7a, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6c, 0x20, 0x3d, 0x20, 0x64, 0x72, 0x20, 0x2a, 0x20, 0x32, 0x37, 0x20, 0x2b, 0x20, 0x64, 0x67,
+ 0x20, 0x2a, 0x20, 0x39, 0x32, 0x20, 0x2b, 0x20, 0x64, 0x62, 0x20, 0x2a, 0x20, 0x39, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x72, 0x20,
+ 0x3d, 0x20, 0x64, 0x72, 0x20, 0x2a, 0x20, 0x31, 0x32, 0x38, 0x20, 0x2d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6c, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x63, 0x62, 0x20, 0x3d, 0x20, 0x64, 0x62, 0x20, 0x2a, 0x20, 0x31, 0x32, 0x38, 0x20, 0x2d, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6c, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09,
+ 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x6c, 0x20, 0x2a, 0x20, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x6c, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x20, 0x2b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x28, 0x28, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x5f, 0x63, 0x72, 0x20, 0x2a, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x72, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x20, 0x2a, 0x20, 0x32, 0x36, 0x55, 0x29, 0x20,
+ 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x20, 0x2b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x28, 0x28, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x62, 0x20,
+ 0x2a, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x63, 0x62, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x20, 0x2a, 0x20, 0x33, 0x55, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x61,
+ 0x20, 0x3d, 0x20, 0x28, 0x65, 0x31, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x77, 0x29, 0x20, 0x3c, 0x3c, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x64, 0x20, 0x2b, 0x3d,
+ 0x20, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x64, 0x61, 0x20, 0x2a, 0x20, 0x64, 0x61, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x37, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x64, 0x3b, 0x0d, 0x0a, 0x23, 0x65, 0x6e, 0x64, 0x69, 0x66, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65,
+ 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x72, 0x20, 0x3d, 0x20, 0x65,
+ 0x31, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x65,
+ 0x32, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x7a, 0x3b, 0x09, 0x0d, 0x0a,
+ 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x61, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x77, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x77, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x20, 0x64, 0x72, 0x20, 0x2a, 0x20, 0x64, 0x72, 0x20, 0x2b, 0x20, 0x64, 0x67, 0x20, 0x2a, 0x20, 0x64, 0x67, 0x20, 0x2b, 0x20, 0x64, 0x62, 0x20, 0x2a, 0x20, 0x64, 0x62, 0x20, 0x2b, 0x20,
+ 0x64, 0x61, 0x20, 0x2a, 0x20, 0x64, 0x61, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64,
+ 0x72, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e,
+ 0x79, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x31, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x65, 0x32, 0x2e,
+ 0x7a, 0x3b, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x72, 0x20, 0x2a, 0x20, 0x64, 0x72, 0x20, 0x2b, 0x20, 0x64, 0x67, 0x20, 0x2a, 0x20, 0x64, 0x67, 0x20,
+ 0x2b, 0x20, 0x64, 0x62, 0x20, 0x2a, 0x20, 0x64, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72,
+ 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x62, 0x69, 0x67, 0x20, 0x65, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x36, 0x34, 0x3a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x62, 0x69, 0x74, 0x20, 0x6f, 0x66, 0x73, 0x3a, 0x20, 0x20, 0x35, 0x36, 0x20, 0x20, 0x34, 0x38, 0x20, 0x20, 0x34, 0x30, 0x20,
+ 0x20, 0x33, 0x32, 0x20, 0x20, 0x32, 0x34, 0x20, 0x20, 0x31, 0x36, 0x20, 0x20, 0x20, 0x38, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x6f, 0x66,
+ 0x73, 0x3a, 0x20, 0x62, 0x30, 0x2c, 0x20, 0x62, 0x31, 0x2c, 0x20, 0x62, 0x32, 0x2c, 0x20, 0x62, 0x33, 0x2c, 0x20, 0x62, 0x34, 0x2c, 0x20, 0x62, 0x35, 0x2c, 0x20, 0x62, 0x36, 0x2c, 0x20, 0x62,
+ 0x37, 0x20, 0x0d, 0x0a, 0x09, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x75, 0x69, 0x6e,
+ 0x74, 0x36, 0x34, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x38, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x7d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x65, 0x6e, 0x75, 0x6d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x61, 0x6e, 0x74, 0x73, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x79, 0x74, 0x65, 0x73, 0x50, 0x65, 0x72, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d,
+ 0x20, 0x38, 0x55, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x42, 0x69, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x32, 0x55, 0x2c,
+ 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x31, 0x55, 0x20, 0x3c, 0x3c, 0x20, 0x63,
+ 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x4d, 0x61, 0x73, 0x6b, 0x20, 0x3d, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x2d, 0x20, 0x31, 0x55,
+ 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x68, 0x69, 0x66, 0x74, 0x20, 0x3d, 0x20, 0x32, 0x55, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45,
+ 0x54, 0x43, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x31, 0x55, 0x20, 0x3c, 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x53,
+ 0x68, 0x69, 0x66, 0x74, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x4c, 0x53, 0x42, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65,
+ 0x73, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x4d, 0x53, 0x42, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x31, 0x36, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54,
+ 0x43, 0x31, 0x46, 0x6c, 0x69, 0x70, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x33, 0x32, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x69, 0x66,
+ 0x66, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x33, 0x33, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x4d,
+ 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x33, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x49, 0x6e, 0x74, 0x65, 0x6e,
+ 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x49, 0x6e, 0x74, 0x65, 0x6e,
+ 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x52, 0x69, 0x67, 0x68, 0x74, 0x49, 0x6e, 0x74,
+ 0x65, 0x6e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x33, 0x34, 0x2c, 0x0d, 0x0a,
+ 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x4c, 0x65, 0x66, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x74, 0x4f,
+ 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x33, 0x37, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x42, 0x61, 0x73, 0x65, 0x2b, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x20, 0x65, 0x6e,
+ 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x35, 0x20, 0x62, 0x69, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2c, 0x20, 0x33, 0x20, 0x62, 0x69, 0x74, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x29, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x20, 0x3d, 0x20,
+ 0x35, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c,
+ 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x33, 0x2c,
+ 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x63, 0x45,
+ 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43,
+ 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44,
+ 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42,
+ 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x35, 0x39, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43,
+ 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x47, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x35, 0x31, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45,
+ 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x34, 0x33, 0x2c, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x35,
+ 0x36, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x47, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20,
+ 0x3d, 0x20, 0x34, 0x38, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73,
+ 0x65, 0x74, 0x20, 0x3d, 0x20, 0x34, 0x30, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x41, 0x62, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x65, 0x20, 0x28, 0x6e, 0x6f, 0x6e, 0x2d, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x29, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x28, 0x74, 0x77, 0x6f, 0x20, 0x34, 0x2d, 0x62, 0x69, 0x74, 0x20, 0x70, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6d,
+ 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x62, 0x61, 0x73, 0x65, 0x73, 0x29, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d,
+ 0x70, 0x4e, 0x75, 0x6d, 0x42, 0x69, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x34, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d,
+ 0x70, 0x4d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x4e, 0x75, 0x6d,
+ 0x42, 0x69, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x52, 0x31, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66,
+ 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x47, 0x31, 0x42, 0x69, 0x74, 0x4f,
+ 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x35, 0x32, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x42, 0x31, 0x42, 0x69,
+ 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x34, 0x34, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34,
+ 0x52, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x35, 0x36, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x34, 0x47, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x34, 0x38, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x34, 0x42, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x34, 0x30, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x43,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x2d, 0x34, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44,
+ 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x20, 0x3d, 0x20, 0x33, 0x2c, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x3a, 0x0d, 0x0a, 0x09, 0x2f, 0x2f,
+ 0x20, 0x30, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x32, 0x20, 0x20, 0x20, 0x33, 0x20, 0x20, 0x20, 0x34, 0x20, 0x20, 0x20, 0x35, 0x20, 0x20, 0x20, 0x36, 0x20, 0x20, 0x20, 0x37, 0x0d, 0x0a,
+ 0x09, 0x2f, 0x2f, 0x20, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0x31, 0x20, 0x30, 0x31, 0x30, 0x20, 0x30, 0x31, 0x31, 0x20, 0x31, 0x30, 0x30, 0x20, 0x31, 0x30, 0x31, 0x20, 0x31, 0x31, 0x30, 0x20,
+ 0x31, 0x31, 0x31, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x30, 0x20, 0x20, 0x20, 0x31, 0x20, 0x20, 0x20, 0x32, 0x20, 0x20, 0x20, 0x33, 0x20, 0x20, 0x20, 0x2d, 0x34, 0x20, 0x20, 0x2d, 0x33, 0x20,
+ 0x20, 0x2d, 0x32, 0x20, 0x20, 0x2d, 0x31, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x20, 0x42, 0x41, 0x53, 0x49, 0x53, 0x55, 0x5f, 0x45, 0x54,
+ 0x43, 0x31, 0x5f, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x46, 0x49, 0x54, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x20,
+ 0x28, 0x31, 0x36, 0x35, 0x29, 0x0d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x7b, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74,
+ 0x20, 0x6d, 0x5f, 0x76, 0x5b, 0x34, 0x5d, 0x3b, 0x20, 0x7d, 0x20, 0x67, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x74,
+ 0x61, 0x62, 0x5b, 0x42, 0x41, 0x53, 0x49, 0x53, 0x55, 0x5f, 0x45, 0x54, 0x43, 0x31, 0x5f, 0x43, 0x4c, 0x55, 0x53, 0x54, 0x45, 0x52, 0x5f, 0x46, 0x49, 0x54, 0x5f, 0x4f, 0x52, 0x44, 0x45, 0x52,
+ 0x5f, 0x54, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x5d, 0x20, 0x3d, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x38, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c,
+ 0x20, 0x36, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c,
+ 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x38, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20,
+ 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20,
+ 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x37, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20,
+ 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20,
+ 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c,
+ 0x20, 0x32, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c,
+ 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20,
+ 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20,
+ 0x31, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20,
+ 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31,
+ 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20,
+ 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20,
+ 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x38, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09,
+ 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x31, 0x2c, 0x20,
+ 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20,
+ 0x32, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d,
+ 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35,
+ 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32,
+ 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b,
+ 0x20, 0x32, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20,
+ 0x36, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b,
+ 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31,
+ 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b,
+ 0x20, 0x34, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20,
+ 0x33, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b,
+ 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x33,
+ 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c,
+ 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20,
+ 0x31, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20,
+ 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x37, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x31,
+ 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20,
+ 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x37, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c,
+ 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20,
+ 0x34, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20,
+ 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20,
+ 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x33,
+ 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20,
+ 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x20,
+ 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x38, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c,
+ 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x35, 0x2c, 0x20,
+ 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20,
+ 0x33, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20,
+ 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20,
+ 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x20,
+ 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09,
+ 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20,
+ 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20,
+ 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d,
+ 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32,
+ 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35,
+ 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b,
+ 0x20, 0x35, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20,
+ 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b,
+ 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x36, 0x2c, 0x20, 0x30,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32,
+ 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b,
+ 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x35, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20,
+ 0x31, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b,
+ 0x20, 0x7b, 0x20, 0x36, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x32,
+ 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d,
+ 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c,
+ 0x20, 0x32, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x34, 0x20, 0x7d,
+ 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20,
+ 0x33, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x37, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20,
+ 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x37, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x33,
+ 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x34, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x31,
+ 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x33, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x34, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20,
+ 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x2c,
+ 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x30, 0x2c,
+ 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x2c, 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x35, 0x20, 0x7d, 0x20, 0x7d, 0x2c,
+ 0x7b, 0x20, 0x7b, 0x20, 0x31, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x36, 0x20, 0x7d, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61,
+ 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x63, 0x45, 0x54, 0x43, 0x31,
+ 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x5b, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x20, 0x3d, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x2d, 0x38, 0x2c, 0x20, 0x20, 0x2d, 0x32, 0x2c, 0x20, 0x20, 0x20, 0x32, 0x2c,
+ 0x20, 0x20, 0x20, 0x38, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x20, 0x2d, 0x31, 0x37, 0x2c, 0x20, 0x20, 0x2d, 0x35, 0x2c, 0x20, 0x20, 0x35, 0x2c, 0x20, 0x20, 0x31, 0x37, 0x20, 0x7d, 0x2c, 0x20, 0x7b,
+ 0x20, 0x2d, 0x32, 0x39, 0x2c, 0x20, 0x20, 0x2d, 0x39, 0x2c, 0x20, 0x20, 0x20, 0x39, 0x2c, 0x20, 0x20, 0x32, 0x39, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x20, 0x20, 0x2d, 0x34, 0x32, 0x2c, 0x20, 0x2d,
+ 0x31, 0x33, 0x2c, 0x20, 0x31, 0x33, 0x2c, 0x20, 0x20, 0x34, 0x32, 0x20, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x2d, 0x36, 0x30, 0x2c, 0x20, 0x2d, 0x31, 0x38, 0x2c, 0x20, 0x31, 0x38, 0x2c,
+ 0x20, 0x20, 0x36, 0x30, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x20, 0x2d, 0x38, 0x30, 0x2c, 0x20, 0x2d, 0x32, 0x34, 0x2c, 0x20, 0x32, 0x34, 0x2c, 0x20, 0x20, 0x38, 0x30, 0x20, 0x7d, 0x2c, 0x20, 0x7b,
+ 0x20, 0x2d, 0x31, 0x30, 0x36, 0x2c, 0x20, 0x2d, 0x33, 0x33, 0x2c, 0x20, 0x33, 0x33, 0x2c, 0x20, 0x31, 0x30, 0x36, 0x20, 0x7d, 0x2c, 0x20, 0x7b, 0x20, 0x2d, 0x31, 0x38, 0x33, 0x2c, 0x20, 0x2d,
+ 0x34, 0x37, 0x2c, 0x20, 0x34, 0x37, 0x2c, 0x20, 0x31, 0x38, 0x33, 0x20, 0x7d, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x74, 0x6f, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5b, 0x63,
+ 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x32, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x31, 0x2c,
+ 0x20, 0x30, 0x20, 0x7d, 0x3b, 0x0d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x67, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5b, 0x63, 0x45, 0x54, 0x43, 0x31, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x56, 0x61,
+ 0x6c, 0x75, 0x65, 0x73, 0x5d, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x33, 0x2c, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x31, 0x20, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6f, 0x66, 0x73, 0x2c, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x6f, 0x66, 0x73, 0x20, 0x2b, 0x20,
+ 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x3c, 0x3d, 0x20, 0x36, 0x34, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6e, 0x75, 0x6d, 0x20, 0x26, 0x26, 0x20, 0x28, 0x6e,
+ 0x75, 0x6d, 0x20, 0x3c, 0x3d, 0x20, 0x38, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x6f, 0x66, 0x73, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x20,
+ 0x3d, 0x3d, 0x20, 0x28, 0x28, 0x6f, 0x66, 0x73, 0x20, 0x2b, 0x20, 0x6e, 0x75, 0x6d, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x37, 0x20, 0x2d, 0x20, 0x28, 0x6f, 0x66, 0x73,
+ 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69,
+ 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x6f, 0x66, 0x73, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x70, 0x2d, 0x3e, 0x6d, 0x5f,
+ 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x73, 0x5d, 0x20, 0x3e, 0x3e, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x29,
+ 0x20, 0x26, 0x20, 0x28, 0x28, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20,
+ 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6f, 0x66, 0x73, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d,
+ 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x74, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x6f, 0x66,
+ 0x73, 0x20, 0x2b, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x3c, 0x3d, 0x20, 0x36, 0x34, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6e, 0x75, 0x6d, 0x20, 0x26,
+ 0x26, 0x20, 0x28, 0x6e, 0x75, 0x6d, 0x20, 0x3c, 0x20, 0x33, 0x32, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x6f, 0x66, 0x73, 0x20, 0x3e, 0x3e,
+ 0x20, 0x33, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x28, 0x28, 0x6f, 0x66, 0x73, 0x20, 0x2b, 0x20, 0x6e, 0x75, 0x6d, 0x20, 0x2d, 0x20, 0x31, 0x29, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x62, 0x69, 0x74, 0x73, 0x20, 0x3c, 0x20, 0x28, 0x31, 0x55, 0x20, 0x3c, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x37, 0x20, 0x2d, 0x20, 0x28, 0x6f,
+ 0x66, 0x73, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f,
+ 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x6f, 0x66, 0x73, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x61, 0x73, 0x6b, 0x20, 0x3d, 0x20, 0x28, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x29, 0x20, 0x2d, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x73, 0x5d, 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x28, 0x6d, 0x61, 0x73, 0x6b, 0x20, 0x3c, 0x3c, 0x20, 0x62,
+ 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x62, 0x79, 0x74, 0x65, 0x5f,
+ 0x6f, 0x66, 0x73, 0x5d, 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x62, 0x69, 0x74, 0x73, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x69,
+ 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x20, 0x28, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x26, 0x20, 0x31, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x66, 0x6c, 0x69, 0x70, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33,
+ 0x5d, 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x28, 0x66, 0x6c, 0x69, 0x70, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c,
+ 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74,
+ 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62,
+ 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x26, 0x20, 0x32, 0x29, 0x20, 0x21, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74,
+ 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a,
+ 0x70, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x64, 0x69, 0x66, 0x66, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d,
+ 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x32, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x28, 0x75, 0x69, 0x6e,
+ 0x74, 0x33, 0x32, 0x5f, 0x74, 0x29, 0x28, 0x64, 0x69, 0x66, 0x66, 0x29, 0x20, 0x3c, 0x3c, 0x20, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x52, 0x65, 0x74,
+ 0x75, 0x72, 0x6e, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x30,
+ 0x2d, 0x37, 0x29, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64,
+ 0x2e, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x3d, 0x30, 0x20, 0x6c, 0x65, 0x66, 0x74, 0x2f, 0x74, 0x6f, 0x70, 0x20, 0x28, 0x43, 0x57,
+ 0x20, 0x31, 0x29, 0x2c, 0x20, 0x31, 0x3d, 0x72, 0x69, 0x67, 0x68, 0x74, 0x2f, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x20, 0x28, 0x43, 0x57, 0x20, 0x32, 0x29, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74,
+ 0x33, 0x32, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x63,
+ 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x75, 0x62, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69,
+ 0x64, 0x20, 0x3c, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x73,
+ 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x20, 0x3f, 0x20, 0x32, 0x20, 0x3a, 0x20, 0x35, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x70, 0x2d,
+ 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3e, 0x3e, 0x20, 0x6f, 0x66, 0x73, 0x29, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f,
+ 0x2f, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20,
+ 0x28, 0x30, 0x2d, 0x37, 0x29, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x69, 0x64, 0x20, 0x28, 0x30, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x29, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32,
+ 0x5f, 0x74, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x74, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x20, 0x3c, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65,
+ 0x72, 0x74, 0x28, 0x74, 0x20, 0x3c, 0x20, 0x38, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6f, 0x66, 0x73, 0x20,
+ 0x3d, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x64, 0x20, 0x3f, 0x20, 0x32, 0x20, 0x3a, 0x20, 0x35, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79,
+ 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x28, 0x37, 0x20, 0x3c, 0x3c, 0x20, 0x6f, 0x66, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79,
+ 0x74, 0x65, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x74, 0x20, 0x3c, 0x3c, 0x20, 0x6f, 0x66, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64,
+ 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x74, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x70, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x28, 0x70, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x74, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32,
+ 0x5f, 0x74, 0x20, 0x79, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x78, 0x20, 0x7c, 0x20, 0x79, 0x29, 0x20, 0x3c, 0x20, 0x34, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20,
+ 0x78, 0x20, 0x2a, 0x20, 0x34, 0x20, 0x2b, 0x20, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74, 0x65,
+ 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b,
+ 0x37, 0x20, 0x2d, 0x20, 0x28, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75,
+ 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6c, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x5b, 0x30, 0x5d, 0x20, 0x3e, 0x3e, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f,
+ 0x6f, 0x66, 0x73, 0x29, 0x20, 0x26, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x73, 0x62, 0x20, 0x3d,
+ 0x20, 0x28, 0x70, 0x5b, 0x2d, 0x32, 0x5d, 0x20, 0x3e, 0x3e, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x29, 0x20, 0x26, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x20, 0x3d, 0x20, 0x6c, 0x73, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x6d, 0x73, 0x62, 0x20,
+ 0x3c, 0x3c, 0x20, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x76, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20,
+ 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x66,
+ 0x72, 0x6f, 0x6d, 0x20, 0x30, 0x2d, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x69, 0x6e,
+ 0x74, 0x6f, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x2e, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f,
+ 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x79, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x74, 0x6f,
+ 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5b, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x61,
+ 0x77, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x78, 0x2c, 0x20, 0x79, 0x29, 0x5d, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x2f, 0x2f, 0x20, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x22, 0x76, 0x61, 0x6c, 0x22, 0x20, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x30,
+ 0x2d, 0x33, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x67, 0x5f,
+ 0x65, 0x74, 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x2e, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x78, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x79, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x76, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x78, 0x20, 0x7c, 0x20, 0x79, 0x20, 0x7c, 0x20, 0x76, 0x61,
+ 0x6c, 0x29, 0x20, 0x3c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x78, 0x20, 0x2a, 0x20, 0x34, 0x20, 0x2b, 0x20, 0x79, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x20,
+ 0x3d, 0x20, 0x26, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x37, 0x20, 0x2d, 0x20, 0x28, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x79, 0x74,
+ 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x61, 0x73, 0x6b, 0x20, 0x3d, 0x20, 0x31, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74,
+ 0x5f, 0x6f, 0x66, 0x73, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x76, 0x61,
+ 0x6c, 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5f, 0x74, 0x6f, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5b, 0x76, 0x61, 0x6c,
+ 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6c, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63,
+ 0x31, 0x5f, 0x76, 0x61, 0x6c, 0x20, 0x26, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x73, 0x62, 0x20,
+ 0x3d, 0x20, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x76, 0x61, 0x6c, 0x20, 0x3e, 0x3e, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x5b, 0x30, 0x5d, 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x6d, 0x61,
+ 0x73, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x5b, 0x30, 0x5d, 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x6c, 0x73, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f,
+ 0x66, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x5b, 0x2d, 0x32, 0x5d, 0x20, 0x26, 0x3d, 0x20, 0x7e, 0x6d, 0x61, 0x73, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x5b, 0x2d, 0x32, 0x5d,
+ 0x20, 0x7c, 0x3d, 0x20, 0x28, 0x6d, 0x73, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x5f, 0x6f, 0x66, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x34, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28,
+ 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x64, 0x78, 0x2c,
+ 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x63, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x64, 0x78, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x52, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x2c, 0x20,
+ 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x38, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x34, 0x47, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x34, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x42, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34,
+ 0x2c, 0x20, 0x63, 0x20, 0x26, 0x20, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54,
+ 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x52, 0x31, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e,
+ 0x20, 0x38, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x47, 0x31, 0x42, 0x69,
+ 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x34, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63,
+ 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x42, 0x31, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x2c, 0x20, 0x63, 0x20, 0x26,
+ 0x20, 0x31, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x34, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x64, 0x78, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x2c, 0x20, 0x67, 0x2c, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x69, 0x64, 0x78, 0x29, 0x0d, 0x0a, 0x09, 0x7b,
+ 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28,
+ 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x52, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65,
+ 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65,
+ 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x47, 0x32, 0x42, 0x69,
+ 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65,
+ 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x34, 0x42, 0x32, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09,
+ 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73,
+ 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x52, 0x31, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73,
+ 0x65, 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74,
+ 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x47, 0x31, 0x42,
+ 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67,
+ 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x41, 0x62, 0x73, 0x43, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x34, 0x42, 0x31, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x34, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
+ 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x34, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3c,
+ 0x3c, 0x20, 0x38, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74,
+ 0x5f, 0x62, 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x63, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62,
+ 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35,
+ 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x31, 0x30, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x47, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x35, 0x2c, 0x20,
+ 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x35, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f,
+ 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x35, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x35, 0x2c, 0x20, 0x63, 0x20, 0x26, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75,
+ 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74,
+ 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x35, 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32,
+ 0x5f, 0x74, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70,
+ 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x47, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74,
+ 0x2c, 0x20, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31,
+ 0x42, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75,
+ 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x35, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72,
+ 0x20, 0x3c, 0x3c, 0x20, 0x31, 0x30, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x63, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
+ 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x36, 0x29, 0x20, 0x26, 0x20, 0x37,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x47, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c,
+ 0x20, 0x33, 0x2c, 0x20, 0x28, 0x63, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x20, 0x26, 0x20, 0x37, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
+ 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x33, 0x2c, 0x20, 0x63, 0x20, 0x26, 0x20, 0x37, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x20, 0x0d,
+ 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c,
+ 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x52, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f,
+ 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x47, 0x42, 0x69,
+ 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x20,
+ 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x2c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x33, 0x42, 0x42, 0x69, 0x74, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x2c, 0x20, 0x33, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20,
+ 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x36, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x2a, 0x70, 0x52, 0x2c, 0x20, 0x69, 0x6e,
+ 0x74, 0x20, 0x2a, 0x70, 0x47, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x2a, 0x70, 0x42, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6c,
+ 0x74, 0x61, 0x33, 0x20, 0x3e, 0x3e, 0x20, 0x36, 0x29, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64,
+ 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x20, 0x3e, 0x3e, 0x20, 0x33, 0x29, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x70, 0x61, 0x63,
+ 0x6b, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x20, 0x26, 0x20, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x20, 0x3e, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x72, 0x20,
+ 0x2d, 0x3d, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x67, 0x20, 0x3e, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x67, 0x20, 0x2d, 0x3d, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66,
+ 0x20, 0x28, 0x62, 0x20, 0x3e, 0x3d, 0x20, 0x34, 0x29, 0x20, 0x62, 0x20, 0x2d, 0x3d, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x2a, 0x70, 0x52, 0x20, 0x3d, 0x20, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x2a,
+ 0x70, 0x47, 0x20, 0x3d, 0x20, 0x67, 0x3b, 0x0d, 0x0a, 0x09, 0x2a, 0x70, 0x42, 0x20, 0x3d, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x65, 0x74,
+ 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65,
+ 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33,
+ 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a,
+ 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x72, 0x2c, 0x20, 0x64, 0x67, 0x2c, 0x20, 0x64, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x26, 0x64, 0x72, 0x2c, 0x20, 0x26, 0x64, 0x67, 0x2c, 0x20, 0x26, 0x64, 0x62, 0x2c, 0x20, 0x70, 0x61, 0x63,
+ 0x6b, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x29, 0x20, 0x2b, 0x20, 0x64, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x28,
+ 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x3e, 0x3e, 0x20, 0x35, 0x55, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x29, 0x20, 0x2b, 0x20, 0x64,
+ 0x67, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x3e, 0x3e, 0x20,
+ 0x31, 0x30, 0x55, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x29, 0x20, 0x2b, 0x20, 0x64, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x29, 0x28, 0x72, 0x20, 0x7c, 0x20,
+ 0x67, 0x20, 0x7c, 0x20, 0x62, 0x29, 0x20, 0x3e, 0x20, 0x33, 0x31, 0x55, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x66,
+ 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x72, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x67, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x67, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61,
+ 0x6d, 0x70, 0x28, 0x62, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x33, 0x31, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64,
+ 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x62, 0x20, 0x3e, 0x3e, 0x20, 0x32,
+ 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x55, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x55, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x2a, 0x70, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28,
+ 0x72, 0x2c, 0x20, 0x67, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20,
+ 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74,
+ 0x33, 0x32, 0x5f, 0x74, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x70, 0x61,
+ 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x67, 0x20,
+ 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x3e, 0x3e, 0x20, 0x35, 0x55, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x20, 0x3e, 0x3e, 0x20,
+ 0x31, 0x30, 0x55, 0x29, 0x20, 0x26, 0x20, 0x33, 0x31, 0x55, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x62, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72,
+ 0x20, 0x3d, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x72, 0x2c, 0x20, 0x67, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x6d,
+ 0x69, 0x6e, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67,
+ 0x62, 0x61, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31,
+ 0x36, 0x5f, 0x74, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x20,
+ 0x3d, 0x20, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x20, 0x26, 0x20, 0x31, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f,
+ 0x74, 0x20, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x20, 0x3e, 0x3e, 0x20, 0x34, 0x55, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35,
+ 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34,
+ 0x20, 0x3e, 0x3e, 0x20, 0x38, 0x55, 0x29, 0x20, 0x26, 0x20, 0x31, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a,
+ 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x34, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x20, 0x3d, 0x20,
+ 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x34, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x67, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x34, 0x55, 0x29, 0x20,
+ 0x7c, 0x20, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29,
+ 0x28, 0x72, 0x2c, 0x20, 0x67, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x64, 0x69, 0x64, 0x6e, 0x27, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x2c, 0x20, 0x74, 0x72, 0x75,
+ 0x65, 0x20, 0x69, 0x66, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x65, 0x64, 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c,
+ 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x28, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x2a,
+ 0x20, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x69, 0x66, 0x20, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x0d,
+ 0x0a, 0x09, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x64, 0x65, 0x6c, 0x74,
+ 0x61, 0x33, 0x28, 0x26, 0x62, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6c, 0x73,
+ 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x35, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x29, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x75, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x34, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c,
+ 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x2a, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x64, 0x63, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61,
+ 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b,
+ 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35,
+ 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63,
+ 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70,
+ 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66,
+ 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c,
+ 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c,
+ 0x65, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61,
+ 0x67, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63,
+ 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
+ 0x32, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49,
+ 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61,
+ 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x33, 0x5d,
+ 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74,
+ 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x5f, 0x66, 0x6c, 0x61, 0x67,
+ 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x26, 0x64, 0x63, 0x29, 0x2c, 0x20, 0x32, 0x35,
+ 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x63, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x67, 0x65, 0x74, 0x5f,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x35, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x42, 0x61, 0x73, 0x65,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x62,
+ 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x20, 0x2f, 0x2a, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x20, 0x2a, 0x2f, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x20, 0x3d, 0x20, 0x2a, 0x70, 0x42, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09,
+ 0x69, 0x66, 0x20, 0x28, 0x21, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x3c,
+ 0x3c, 0x20, 0x33, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x2e, 0x79,
+ 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x62,
+ 0x2e, 0x7a, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63,
+ 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x2a, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x65, 0x74,
+ 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x30, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61,
+ 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x30, 0x5d,
+ 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x30,
+ 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
+ 0x30, 0x5d, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x5d, 0x20, 0x3d, 0x20,
+ 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74,
+ 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x31, 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e,
+ 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x31, 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49,
+ 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x31, 0x5d, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x32, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35,
+ 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x32, 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35,
+ 0x35, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x32, 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32,
+ 0x35, 0x35, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x32, 0x5d, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x33, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62,
+ 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x33,
+ 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b,
+ 0x33, 0x5d, 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x5b, 0x33, 0x5d, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x2a, 0x20, 0x70, 0x53,
+ 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x75,
+ 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x5f, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2f, 0x2a, 0x3d, 0x20, 0x30, 0x2a, 0x2f, 0x2c, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2f, 0x2a, 0x3d, 0x20, 0x32, 0x2a, 0x2f, 0x29, 0x0d, 0x0a,
+ 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x62, 0x65, 0x67, 0x69, 0x6e,
+ 0x5f, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3c, 0x20, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x3b, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62,
+ 0x61, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x67, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x79, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x79, 0x20, 0x3c, 0x20, 0x32, 0x3b, 0x20,
+ 0x79, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x78, 0x20,
+ 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x78, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58,
+ 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x73,
+ 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x73, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34,
+ 0x5f, 0x74, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75,
+ 0x61, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x5d, 0x2c, 0x20, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x69, 0x78,
+ 0x65, 0x6c, 0x73, 0x5b, 0x78, 0x20, 0x2b, 0x20, 0x28, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x20, 0x32, 0x20, 0x2b, 0x20, 0x79, 0x29, 0x20, 0x2a, 0x20, 0x34, 0x5d, 0x2c,
+ 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x65, 0x72, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x65, 0x72, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x3d,
+ 0x20, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x78, 0x2c, 0x20, 0x73,
+ 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x20, 0x32, 0x20, 0x2b, 0x20, 0x79, 0x2c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09,
+ 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x79, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x79, 0x20, 0x3c, 0x20,
+ 0x34, 0x3b, 0x20, 0x79, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74,
+ 0x20, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x32, 0x3b, 0x20, 0x78, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f,
+ 0x4d, 0x41, 0x58, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x30,
+ 0x3b, 0x20, 0x73, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x73, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e,
+ 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65,
+ 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x5d, 0x2c, 0x20, 0x70, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x28, 0x73, 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x20, 0x32, 0x29, 0x20, 0x2b, 0x20, 0x78, 0x20, 0x2b, 0x20, 0x79, 0x20, 0x2a, 0x20,
+ 0x34, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x65, 0x72, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73,
+ 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x65, 0x72, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x73,
+ 0x75, 0x62, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x20, 0x32, 0x20, 0x2b, 0x20, 0x78, 0x2c, 0x20, 0x79, 0x2c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f,
+ 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31,
+ 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x5f, 0x72, 0x67, 0x62, 0x28, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x67, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62,
+ 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x61,
+ 0x73, 0x20, 0x3d, 0x20, 0x31, 0x32, 0x37, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x72, 0x20, 0x3d, 0x20, 0x28, 0x72, 0x20, 0x2a, 0x20, 0x31, 0x35, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x67, 0x20, 0x3d, 0x20, 0x28, 0x67, 0x20, 0x2a, 0x20, 0x31, 0x35, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x62, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x20, 0x2a, 0x20, 0x31, 0x35, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x7d,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x72, 0x2c, 0x20, 0x31, 0x35, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28,
+ 0x67, 0x2c, 0x20, 0x31, 0x35, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x62, 0x2c, 0x20, 0x31, 0x35, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09,
+ 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x34, 0x55, 0x29, 0x20,
+ 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x38, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20,
+ 0x62, 0x69, 0x61, 0x73, 0x20, 0x3d, 0x20, 0x31, 0x32, 0x37, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70,
+ 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x5f, 0x72, 0x67, 0x62, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x2c,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x2c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f,
+ 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x69, 0x6e, 0x74, 0x20, 0x72, 0x2c, 0x20, 0x69,
+ 0x6e, 0x74, 0x20, 0x67, 0x2c, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x72, 0x20, 0x3e, 0x3d, 0x20, 0x63,
+ 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3d, 0x20, 0x63, 0x45, 0x54, 0x43,
+ 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x67, 0x20, 0x3e, 0x3d,
+ 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3d, 0x20, 0x63, 0x45,
+ 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x72, 0x74, 0x28, 0x28, 0x62, 0x20,
+ 0x3e, 0x3d, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x62, 0x20, 0x3c, 0x3d, 0x20,
+ 0x63, 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x20,
+ 0x30, 0x29, 0x20, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x20, 0x30, 0x29, 0x20, 0x67, 0x20, 0x2b, 0x3d, 0x20, 0x38, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x62, 0x20, 0x3c, 0x20, 0x30, 0x29, 0x20, 0x62, 0x20, 0x2b, 0x3d, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75,
+ 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c, 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x36, 0x29,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63,
+ 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64,
+ 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x34, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x30, 0x2c,
+ 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c,
+ 0x65, 0x64, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73,
+ 0x65, 0x34, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61,
+ 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x34, 0x28, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x29, 0x3b, 0x0d,
+ 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x72, 0x67, 0x62, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x72, 0x2c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x67, 0x2c,
+ 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75,
+ 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x61, 0x73, 0x20, 0x3d, 0x20, 0x31, 0x32, 0x37, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x73, 0x63, 0x61, 0x6c,
+ 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x72, 0x20, 0x2a, 0x20, 0x33, 0x31, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20,
+ 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x67, 0x20, 0x2a, 0x20, 0x33, 0x31, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20,
+ 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x20, 0x2a, 0x20, 0x33, 0x31, 0x55, 0x20, 0x2b, 0x20, 0x62, 0x69, 0x61, 0x73, 0x29, 0x20,
+ 0x2f, 0x20, 0x32, 0x35, 0x35, 0x55, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x72, 0x2c, 0x20, 0x33, 0x31, 0x55, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x67, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x67, 0x2c, 0x20, 0x33, 0x31, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x62, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x62, 0x2c,
+ 0x20, 0x33, 0x31, 0x55, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x20, 0x7c,
+ 0x20, 0x28, 0x67, 0x20, 0x3c, 0x3c, 0x20, 0x35, 0x55, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x72, 0x20, 0x3c, 0x3c, 0x20, 0x31, 0x30, 0x55, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x2c, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x72,
+ 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x72, 0x67, 0x62, 0x28,
+ 0x63, 0x2e, 0x78, 0x2c, 0x20, 0x63, 0x2e, 0x79, 0x2c, 0x20, 0x63, 0x2e, 0x7a, 0x2c, 0x20, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f,
+ 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x65, 0x74,
+ 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x30, 0x5f, 0x75,
+ 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29,
+ 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61,
+ 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e,
+ 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x67, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64,
+ 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x62, 0x20, 0x3d, 0x20, 0x63,
+ 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x7a, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x64, 0x72, 0x2c, 0x20, 0x64,
+ 0x67, 0x2c, 0x20, 0x64, 0x62, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65,
+ 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a,
+ 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a,
+ 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62,
+ 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63,
+ 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x63, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30,
+ 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x61, 0x73, 0x65, 0x35, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x42, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x28, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73,
+ 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x5f,
+ 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e,
+ 0x74, 0x20, 0x64, 0x67, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c,
+ 0x65, 0x64, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x31, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x7a, 0x20, 0x2d,
+ 0x20, 0x63, 0x30, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x2e, 0x7a, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x28, 0x28, 0x64, 0x72, 0x20, 0x3c, 0x20, 0x63,
+ 0x45, 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x64, 0x72, 0x20, 0x3e, 0x20, 0x63, 0x45, 0x54, 0x43,
+ 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x20, 0x7c, 0x7c, 0x0d, 0x0a, 0x09, 0x09, 0x28, 0x28, 0x64, 0x67, 0x20, 0x3c, 0x20, 0x63, 0x45,
+ 0x54, 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x64, 0x67, 0x20, 0x3e, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31,
+ 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x20, 0x7c, 0x7c, 0x0d, 0x0a, 0x09, 0x09, 0x28, 0x28, 0x64, 0x62, 0x20, 0x3c, 0x20, 0x63, 0x45, 0x54,
+ 0x43, 0x31, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x69, 0x6e, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x28, 0x64, 0x62, 0x20, 0x3e, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x43,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x78, 0x29, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b,
+ 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28,
+ 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x33, 0x28, 0x64, 0x72,
+ 0x2c, 0x20, 0x64, 0x67, 0x2c, 0x20, 0x64, 0x62, 0x29, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
+ 0x74, 0x6f, 0x72, 0x73, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74,
+ 0x20, 0x77, 0x6f, 0x72, 0x64, 0x33, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x64, 0x32, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x79, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x79, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x79, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x78, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x78, 0x2b, 0x2b,
+ 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x78, 0x20, 0x2a, 0x20, 0x34, 0x20, 0x2b, 0x20, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x78, 0x20, 0x2b, 0x20, 0x79, 0x20, 0x2a, 0x20, 0x34, 0x5d, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6c, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x73, 0x20, 0x26, 0x20,
+ 0x31, 0x2c, 0x20, 0x6d, 0x73, 0x62, 0x20, 0x3d, 0x20, 0x73, 0x20, 0x3e, 0x3e, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x77, 0x6f, 0x72, 0x64, 0x33, 0x20, 0x7c,
+ 0x3d, 0x20, 0x28, 0x6c, 0x73, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x77, 0x6f, 0x72, 0x64, 0x32, 0x20,
+ 0x7c, 0x3d, 0x20, 0x28, 0x6d, 0x73, 0x62, 0x20, 0x3c, 0x3c, 0x20, 0x62, 0x69, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d,
+ 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x37, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f,
+ 0x74, 0x29, 0x28, 0x77, 0x6f, 0x72, 0x64, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x36, 0x5d, 0x20,
+ 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x28, 0x77, 0x6f, 0x72, 0x64, 0x33, 0x20, 0x3e, 0x3e, 0x20, 0x38, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x35, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x28, 0x77, 0x6f, 0x72, 0x64, 0x32, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5b, 0x34, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f,
+ 0x74, 0x29, 0x28, 0x77, 0x6f, 0x72, 0x64, 0x32, 0x20, 0x3e, 0x3e, 0x20, 0x38, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x45, 0x43,
+ 0x31, 0x53, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x2f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6d,
+ 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x67, 0x5f, 0x65, 0x76,
+ 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x38, 0x5d, 0x5b, 0x32, 0x35, 0x36, 0x5d, 0x20, 0x3d, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x2f, 0x2f,
+ 0x20, 0x39, 0x39, 0x25, 0x20, 0x74, 0x68, 0x72, 0x65, 0x73, 0x68, 0x6f, 0x6c, 0x64, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b,
+ 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31,
+ 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c,
+ 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d, 0x0a, 0x09, 0x7b, 0x20, 0x31, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30,
+ 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31,
+ 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x7d, 0x2c, 0x0d,
+ 0x0a, 0x09, 0x7b, 0x20, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c,
+ 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x30, 0x2c, 0x30, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c, 0x31, 0x2c,
+ 0x31, 0x2c, 0x31, 0x2c, 0x7d, 0x0d, 0x0a, 0x7d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73,
+ 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3b,
+ 0x0d, 0x0a, 0x7d, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f,
+ 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6c,
+ 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x29, 0x20, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x72, 0x2c, 0x20, 0x62, 0x67, 0x2c, 0x20, 0x62, 0x62, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x62,
+ 0x72, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x75,
+ 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x62, 0x67, 0x20, 0x3d, 0x20, 0x28, 0x75,
+ 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
+ 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
+ 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x29, 0x20, 0x7c, 0x20, 0x28, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x2e, 0x7a, 0x20, 0x3c, 0x3c, 0x20, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67,
+ 0x62, 0x61, 0x29, 0x28, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x62, 0x72, 0x2c, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x62, 0x67, 0x2c, 0x20, 0x28, 0x75,
+ 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x62, 0x62, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73,
+ 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f,
+ 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d,
+ 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x20, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x75,
+ 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x36, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x62,
+ 0x6f, 0x6f, 0x6c, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d,
+ 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65,
+ 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x62, 0x72, 0x2c, 0x20, 0x6d, 0x5f, 0x62, 0x67, 0x2c, 0x20, 0x6d, 0x5f, 0x62, 0x62, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x6d, 0x61,
+ 0x78, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f, 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72,
+ 0x5f, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+ 0x69, 0x6f, 0x6e, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f,
+ 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74,
+ 0x65, 0x20, 0x2a, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65,
+ 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0d, 0x0a, 0x09,
+ 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+ 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
+ 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63,
+ 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65,
+ 0x73, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x74,
+ 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x20, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e,
+ 0x2c, 0x20, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73,
+ 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x20, 0x70, 0x42, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69,
+ 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x36, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x54,
+ 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e,
+ 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09,
+ 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69,
+ 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3c, 0x20, 0x63, 0x45, 0x54, 0x43, 0x31, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56,
+ 0x61, 0x6c, 0x75, 0x65, 0x73, 0x3b, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x2f, 0x2f, 0x20,
+ 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x69, 0x73, 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x74,
+ 0x6f, 0x20, 0x6d, 0x65, 0x64, 0x69, 0x75, 0x6d, 0x20, 0x71, 0x75, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x21, 0x67, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b,
+ 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5d, 0x5b, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f,
+ 0x73, 0x70, 0x72, 0x65, 0x61, 0x64, 0x5d, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x61, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x2a, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x66,
+ 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x73, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x73, 0x2b, 0x2b, 0x29, 0x0d,
+ 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x79, 0x64, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x73,
+ 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f,
+ 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x79, 0x64,
+ 0x29, 0x2c, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x79, 0x64, 0x29, 0x2c, 0x20,
+ 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x32, 0x35, 0x35, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x79, 0x64, 0x29, 0x2c, 0x20, 0x32, 0x35, 0x35,
+ 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x63, 0x20,
+ 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x63, 0x20, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x20, 0x63, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c,
+ 0x73, 0x5b, 0x63, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x33, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74,
+ 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x50,
+ 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20,
+ 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b,
+ 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x32, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69,
+ 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72,
+ 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61,
+ 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65,
+ 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x33,
+ 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c,
+ 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65,
+ 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x36, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x73, 0x65, 0x6c, 0x65,
+ 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x63, 0x5d, 0x20, 0x3d, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x29, 0x28, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2b, 0x3d, 0x20,
+ 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x3f, 0x20, 0x28, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2a, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34,
+ 0x5f, 0x74, 0x29, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x5b, 0x63, 0x5d, 0x29, 0x20, 0x3a, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3e, 0x3d, 0x20, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c,
+ 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x70, 0x54, 0x72, 0x69,
+ 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x70,
+ 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x63, 0x6f,
+ 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x36, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09,
+ 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f,
+ 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x5f, 0x73, 0x65,
+ 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c,
+ 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d,
+ 0x0a, 0x09, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e,
+ 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70, 0x42, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69,
+ 0x66, 0x20, 0x28, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x70, 0x42,
+ 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09,
+ 0x2a, 0x70, 0x42, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x2a, 0x70, 0x54, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69,
+ 0x6f, 0x6e, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d,
+ 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76,
+ 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x2a, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72,
+ 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78,
+ 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x50,
+ 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20,
+ 0x2a, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20,
+ 0x3d, 0x20, 0x33, 0x31, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x20, 0x3d, 0x20, 0x32, 0x35, 0x35, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d,
+ 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x30, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x3d, 0x20, 0x30,
+ 0x2c, 0x20, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34,
+ 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x0d, 0x0a,
+ 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x63, 0x20, 0x3d, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65,
+ 0x6c, 0x73, 0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x6d, 0x69, 0x6e, 0x5f,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x6d, 0x61,
+ 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x63, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x29, 0x0d,
+ 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x57, 0x65, 0x69, 0x67,
+ 0x68, 0x74, 0x73, 0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2a, 0x20,
+ 0x63, 0x2e, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x2b, 0x3d, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2a, 0x20, 0x63, 0x2e, 0x79, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x2b, 0x3d, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2a, 0x20, 0x63, 0x2e, 0x7a, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x0d, 0x0a,
+ 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x20, 0x2b, 0x3d, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d,
+ 0x0a, 0x09, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x2e, 0x78, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x2e, 0x79, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x2b, 0x3d, 0x20, 0x63, 0x2e,
+ 0x7a, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x2b, 0x2b, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09,
+ 0x7d, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x76,
+ 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x2f, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29,
+ 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x2f, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3b, 0x0d, 0x0a, 0x09, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x2e, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x2f, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x61, 0x76, 0x67,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x5f, 0x73, 0x70, 0x72,
+ 0x65, 0x61, 0x64, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x78, 0x28, 0x6d, 0x61, 0x78, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x2d,
+ 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x29, 0x2c, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x61,
+ 0x78, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x2f, 0x2f, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20,
+ 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6d, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x64, 0x2c, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x44, 0x58, 0x54,
+ 0x31, 0x2f, 0x42, 0x43, 0x31, 0x2e, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69,
+ 0x6e, 0x74, 0x29, 0x28, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30,
+ 0x66, 0x29, 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x62, 0x67, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x2a,
+ 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x66, 0x29, 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d,
+ 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x62, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69, 0x6e, 0x74,
+ 0x29, 0x28, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x2a, 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x66, 0x29,
+ 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x74,
+ 0x28, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x72, 0x79, 0x2c,
+ 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x2a, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65,
+ 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61,
+ 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72,
+ 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e,
+ 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20,
+ 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x3d, 0x20, 0x33, 0x31, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f,
+ 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
+ 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6f,
+ 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72,
+ 0x67, 0x62, 0x61, 0x29, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x72, 0x2c, 0x20, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x67, 0x2c,
+ 0x20, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x62, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74,
+ 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2c,
+ 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70,
+ 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2c, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x26, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x26, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74,
+ 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x30, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x70, 0x65, 0x72, 0x6d, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x74, 0x72, 0x79, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x69,
+ 0x6e, 0x74, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f,
+ 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5b, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d,
+ 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x63, 0x61,
+ 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f,
+ 0x6e, 0x2e, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x4e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x67, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x62, 0x5b, 0x69, 0x5d,
+ 0x2e, 0x6d, 0x5f, 0x76, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x71, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20,
+ 0x71, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x71, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x79,
+ 0x64, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5b, 0x71, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09,
+ 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x70, 0x4e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x71, 0x5d,
+ 0x20, 0x2a, 0x20, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x2b, 0x20, 0x79, 0x64, 0x5f, 0x74, 0x65, 0x6d, 0x70,
+ 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x20, 0x2d, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x64,
+ 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x20, 0x2b, 0x3d, 0x20, 0x70, 0x4e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x71, 0x5d, 0x20,
+ 0x2a, 0x20, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x2b, 0x20, 0x79, 0x64, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x2c,
+ 0x20, 0x30, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x20, 0x2d, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x20, 0x2b, 0x3d, 0x20, 0x70, 0x4e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x71, 0x5d, 0x20, 0x2a,
+ 0x20, 0x28, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x2b, 0x20, 0x79, 0x64, 0x5f, 0x74, 0x65, 0x6d, 0x70, 0x2c, 0x20,
+ 0x30, 0x2c, 0x20, 0x32, 0x35, 0x35, 0x29, 0x20, 0x2d, 0x20, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d,
+ 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x28, 0x21, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x21, 0x64, 0x65, 0x6c, 0x74, 0x61,
+ 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x21, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x64, 0x65,
+ 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x5f, 0x66, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x72, 0x29, 0x20, 0x2f,
+ 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x67, 0x5f, 0x66,
+ 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x67, 0x29, 0x20, 0x2f, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x5f, 0x66, 0x20, 0x3d, 0x20, 0x28, 0x66, 0x6c, 0x6f,
+ 0x61, 0x74, 0x29, 0x28, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x73, 0x75, 0x6d, 0x5f, 0x62, 0x29, 0x20, 0x2f, 0x20, 0x38, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x20, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x72, 0x31, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x78, 0x20, 0x2d, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x72, 0x5f, 0x66, 0x29, 0x20, 0x2a,
+ 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x66, 0x29, 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d,
+ 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x67, 0x31, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69,
+ 0x6e, 0x74, 0x29, 0x28, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x79, 0x20, 0x2d, 0x20, 0x61, 0x76, 0x67,
+ 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x67, 0x5f, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x66, 0x29, 0x20, 0x2b,
+ 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x62,
+ 0x62, 0x31, 0x20, 0x3d, 0x20, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x28, 0x28, 0x69, 0x6e, 0x74, 0x29, 0x28, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x61, 0x76, 0x67, 0x5f,
+ 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x7a, 0x20, 0x2d, 0x20, 0x61, 0x76, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x74, 0x61, 0x5f, 0x62, 0x5f, 0x66, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x4c, 0x49, 0x4d, 0x49,
+ 0x54, 0x20, 0x2f, 0x20, 0x32, 0x35, 0x35, 0x2e, 0x30, 0x66, 0x29, 0x20, 0x2b, 0x20, 0x2e, 0x35, 0x66, 0x29, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x28, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x29, 0x28, 0x62, 0x72, 0x31, 0x2c, 0x20, 0x62, 0x67, 0x31, 0x2c, 0x20, 0x62, 0x62, 0x31, 0x2c, 0x20,
+ 0x32, 0x35, 0x35, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75,
+ 0x61, 0x74, 0x65, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x6e, 0x75,
+ 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2c, 0x20, 0x63, 0x75, 0x72,
+ 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2c, 0x20, 0x26, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x26, 0x70, 0x53, 0x74, 0x61, 0x74,
+ 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70,
+ 0x53, 0x74, 0x61, 0x74, 0x65, 0x2d, 0x3e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d,
+ 0x3d, 0x20, 0x30, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x45, 0x6e, 0x63,
+ 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x45, 0x54, 0x43, 0x31, 0x53, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x34, 0x78, 0x34, 0x20, 0x70,
+ 0x69, 0x78, 0x65, 0x6c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x0d, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f,
+ 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x28, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
+ 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x50, 0x61, 0x72, 0x61,
+ 0x6d, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65,
+ 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63,
+ 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f,
+ 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x49, 0x6e,
+ 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63,
+ 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x26, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73,
+ 0x2c, 0x20, 0x31, 0x36, 0x2c, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x4e, 0x55,
+ 0x4c, 0x4c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f,
+ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x74, 0x28, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x65, 0x72,
+ 0x6d, 0x73, 0x2c, 0x20, 0x26, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x31, 0x36, 0x2c, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x3e, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x62, 0x6c, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70,
+ 0x5f, 0x62, 0x69, 0x74, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65,
+ 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65,
+ 0x2e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63,
+ 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74,
+ 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x5f, 0x62, 0x65,
+ 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62,
+ 0x6c, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x72, 0x61, 0x77, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x73, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x62, 0x6c, 0x6b, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28,
+ 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a,
+ 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74,
+ 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x70, 0x69, 0x78,
+ 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
+ 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x61, 0x6c, 0x20, 0x45, 0x54, 0x43, 0x31, 0x53, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x67,
+ 0x69, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x72, 0x62, 0x69, 0x74, 0x72, 0x61, 0x72, 0x79, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x61, 0x72, 0x72, 0x61, 0x79, 0x20, 0x6f, 0x66,
+ 0x20, 0x34, 0x78, 0x34, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2e, 0x0d, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c,
+ 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x28, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x5f,
+ 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x20, 0x2a, 0x70,
+ 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x0d,
+ 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x2c, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a,
+ 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69,
+ 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75,
+ 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x3e, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x3d, 0x20,
+ 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x3e,
+ 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f,
+ 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x2b, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2d, 0x3e, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73,
+ 0x74, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a,
+ 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31, 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65,
+ 0x72, 0x5f, 0x69, 0x6e, 0x69, 0x74, 0x28, 0x26, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2c, 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x69,
+ 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x31,
+ 0x73, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x66, 0x69, 0x74,
+ 0x28, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2d, 0x3e, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x73, 0x2c, 0x20, 0x26, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2c,
+ 0x20, 0x70, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c, 0x20, 0x70, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x2c,
+ 0x20, 0x70, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x62, 0x6c, 0x6b, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x74,
+ 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x35, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75,
+ 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x74,
+ 0x63, 0x31, 0x73, 0x28, 0x26, 0x62, 0x6c, 0x6b, 0x2c, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x6d, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x2e,
+ 0x6d, 0x5f, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x73, 0x2e, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x62, 0x6c, 0x6b, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x72, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x5f, 0x65,
+ 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20,
+ 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20,
+ 0x72, 0x65, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36,
+ 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36,
+ 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x6d, 0x5f,
+ 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x63,
+ 0x75, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
+ 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f,
+ 0x74, 0x20, 0x6d, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x31, 0x36, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61,
+ 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f,
+ 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x7d, 0x20,
+ 0x72, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x46, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68,
+ 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x65, 0x73, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x70,
+ 0x6f, 0x69, 0x6e, 0x74, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x20, 0x69, 0x74, 0x2e, 0x0d, 0x0a, 0x6b,
+ 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x72, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f,
+ 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61,
+ 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c, 0x0d, 0x0a, 0x09,
+ 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70,
+ 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+ 0x20, 0x72, 0x65, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x49,
+ 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x2c, 0x0d, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64,
+ 0x69, 0x63, 0x65, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20,
+ 0x70, 0x53, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x20, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61,
+ 0x6c, 0x20, 0x3d, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
+ 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x70, 0x72, 0x69, 0x76, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c,
+ 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x76, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d, 0x20, 0x2a, 0x70, 0x49,
+ 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x66,
+ 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x69, 0x6e, 0x66, 0x6f, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x5f, 0x6f, 0x66, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73,
+ 0x74, 0x65, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69,
+ 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d,
+ 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e,
+ 0x6d, 0x5f, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e,
+ 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65,
+ 0x6e, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65,
+ 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x63, 0x75, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a,
+ 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x55, 0x49, 0x4e,
+ 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
+ 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20,
+ 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20,
+ 0x3d, 0x20, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6f, 0x66, 0x73, 0x20, 0x2b, 0x20, 0x69, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63,
+ 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
+ 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x38, 0x5f, 0x74, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e,
+ 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x31,
+ 0x36, 0x5f, 0x74, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f,
+ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x20, 0x3e, 0x20, 0x63, 0x75,
+ 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x63,
+ 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x35, 0x28, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x26, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x65, 0x74,
+ 0x63, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74,
+ 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x63, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x63, 0x20, 0x3c, 0x20, 0x31, 0x36, 0x3b, 0x20, 0x63, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x70, 0x72, 0x69, 0x76, 0x5f,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2e, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x63, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75,
+ 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61,
+ 0x6e, 0x63, 0x65, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32,
+ 0x5f, 0x74, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28,
+ 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x73, 0x5b, 0x31, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f,
+ 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72,
+ 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20,
+ 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73,
+ 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65,
+ 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72,
+ 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64,
+ 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x2c, 0x20, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28,
+ 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62,
+ 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
+ 0x09, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3b,
+ 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3c, 0x20, 0x6f,
+ 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x29, 0x20, 0x7c, 0x7c, 0x0d, 0x0a, 0x09, 0x09, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x28, 0x6f, 0x72,
+ 0x69, 0x67, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x3d, 0x20, 0x63, 0x75, 0x72, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6c,
+ 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x29, 0x20, 0x26, 0x26, 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x3d, 0x20,
+ 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x29, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09,
+ 0x09, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72,
+ 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x6f, 0x72, 0x69, 0x67, 0x5f,
+ 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x21, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x6c, 0x5f,
+ 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x09, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20,
+ 0x3d, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x2d,
+ 0x2d, 0x2d, 0x2d, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65,
+ 0x72, 0x73, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x65, 0x61, 0x63, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72,
+ 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x66, 0x6f, 0x73,
+ 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33,
+ 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x09, 0x2f, 0x2f, 0x20, 0x34, 0x78, 0x34, 0x20, 0x67,
+ 0x72, 0x69, 0x64, 0x20, 0x6f, 0x66, 0x20, 0x32, 0x2d, 0x62, 0x69, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x0d, 0x0a, 0x7d, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x73,
+ 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63,
+ 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61,
+ 0x20, 0x6d, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x20, 0x20, 0x2f, 0x2f, 0x20, 0x75, 0x6e, 0x73, 0x63, 0x61, 0x6c, 0x65,
+ 0x64, 0x20, 0x35, 0x2d, 0x62, 0x69, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x52, 0x47, 0x42, 0x2c, 0x20, 0x61, 0x6c, 0x70, 0x68,
+ 0x61, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x0d, 0x0a, 0x09,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x3b, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x6f,
+ 0x66, 0x66, 0x73, 0x65, 0x74, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74,
+ 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x09, 0x09, 0x2f, 0x2f, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ 0x20, 0x6f, 0x66, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x0d, 0x0a, 0x7d, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x62,
+ 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f,
+ 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f,
+ 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x3b, 0x0d,
+ 0x0a, 0x7d, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20, 0x46, 0x6f, 0x72, 0x20,
+ 0x65, 0x61, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x20, 0x46, 0x69, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x61, 0x6e, 0x74,
+ 0x69, 0x7a, 0x65, 0x64, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x0d, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x66, 0x69,
+ 0x6e, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x66, 0x6f, 0x72,
+ 0x5f, 0x65, 0x61, 0x63, 0x68, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x28, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x70, 0x61, 0x72,
+ 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x2c,
+ 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63,
+ 0x74, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c,
+ 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75,
+ 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74,
+ 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x2c,
+ 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x2a, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x73,
+ 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f,
+ 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67,
+ 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75,
+ 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x0d,
+ 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74,
+ 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e,
+ 0x66, 0x6f, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62,
+ 0x61, 0x6c, 0x20, 0x66, 0x6f, 0x73, 0x63, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x2a, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
+ 0x6f, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x26, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69,
+ 0x6e, 0x66, 0x6f, 0x2d, 0x3e, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x3e, 0x6d, 0x5f, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x3e, 0x6d, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x3b, 0x0d, 0x0a, 0x09,
+ 0x67, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x35, 0x28, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x26, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2e, 0x77, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f,
+ 0x74, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x5b, 0x31, 0x36, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x69, 0x66, 0x20, 0x28, 0x70,
+ 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28,
+ 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x73, 0x65, 0x6c, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x2b, 0x2b, 0x73, 0x65, 0x6c,
+ 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x31,
+ 0x36, 0x3b, 0x20, 0x2b, 0x2b, 0x69, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x65, 0x6c, 0x5d, 0x5b, 0x69,
+ 0x5d, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f,
+ 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x69, 0x5d, 0x2c, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x65,
+ 0x6c, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x65, 0x6c, 0x73, 0x65, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x66, 0x6f,
+ 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x73, 0x65, 0x6c, 0x20, 0x3c, 0x20, 0x34, 0x3b, 0x20, 0x2b, 0x2b,
+ 0x73, 0x65, 0x6c, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20,
+ 0x3c, 0x20, 0x31, 0x36, 0x3b, 0x20, 0x2b, 0x2b, 0x69, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x65, 0x6c,
+ 0x5d, 0x5b, 0x69, 0x5d, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x20, 0x70, 0x42, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x69, 0x5d, 0x2c, 0x20, 0x74, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x73, 0x5b, 0x73, 0x65, 0x6c, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74,
+ 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x5f, 0x4d, 0x41, 0x58, 0x3b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32,
+ 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74,
+ 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x73, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3c, 0x20,
+ 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x20, 0x73, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d,
+ 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x73, 0x65, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x65,
+ 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x2e, 0x6d, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x74, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x66,
+ 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x31, 0x36, 0x3b, 0x20, 0x69, 0x2b, 0x2b, 0x2c,
+ 0x20, 0x73, 0x65, 0x6c, 0x73, 0x20, 0x3e, 0x3e, 0x3d, 0x20, 0x32, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x2b, 0x3d, 0x20, 0x74, 0x72,
+ 0x69, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x5b, 0x73, 0x65, 0x6c, 0x73, 0x20, 0x26, 0x20, 0x33, 0x5d, 0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x69, 0x66,
+ 0x20, 0x28, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09,
+ 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x72, 0x72, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f,
+ 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x69, 0x66, 0x20, 0x28, 0x21, 0x62, 0x65,
+ 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x29, 0x0d, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x7d, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65,
+ 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x70, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74,
+ 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x5b, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x2d, 0x3e, 0x6d, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f,
+ 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x20, 0x2b, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f,
+ 0x20, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x0d, 0x0a, 0x0d, 0x0a, 0x74, 0x79, 0x70, 0x65, 0x64, 0x65, 0x66, 0x20,
+ 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x5f, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x5f, 0x5f, 0x20, 0x28, 0x28, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x29, 0x29, 0x20,
+ 0x64, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f,
+ 0x74, 0x20, 0x6d, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x3b, 0x0d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x20, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70,
+ 0x74, 0x75, 0x61, 0x6c, 0x3b, 0x0d, 0x0a, 0x7d, 0x20, 0x64, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x2f, 0x2f, 0x20,
+ 0x46, 0x6f, 0x72, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3a, 0x20, 0x44, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x45, 0x54, 0x43, 0x31, 0x53, 0x20, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20,
+ 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x73, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2c, 0x20, 0x67, 0x69, 0x76, 0x65, 0x6e, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20,
+ 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x73, 0x20, 0x70, 0x72, 0x65, 0x64, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x64, 0x20, 0x45, 0x54, 0x43, 0x31, 0x53, 0x20, 0x63, 0x6f, 0x6c, 0x6f,
+ 0x72, 0x35, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2e, 0x20, 0x0d, 0x0a, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x20, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x64, 0x65,
+ 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x28, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x64, 0x73,
+ 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x5f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2c, 0x20, 0x0d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x73,
+ 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x73, 0x2c, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a,
+ 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2c, 0x0d, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x2a, 0x70, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63,
+ 0x6b, 0x73, 0x29, 0x0d, 0x0a, 0x7b, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x20, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e,
+ 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x28, 0x30, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6e,
+ 0x73, 0x74, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x2a, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x69, 0x78,
+ 0x65, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d,
+ 0x2e, 0x6d, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x70, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x61,
+ 0x6e, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
+ 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x34, 0x5d, 0x3b, 0x0d, 0x0a, 0x09, 0x67, 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x35, 0x28, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x2c, 0x20, 0x26, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f,
+ 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2e, 0x77, 0x2c, 0x20,
+ 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f,
+ 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x6c, 0x69, 0x70, 0x5f, 0x62, 0x69, 0x74, 0x28, 0x26, 0x6f, 0x75,
+ 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x74, 0x72, 0x75, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
+ 0x65, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x26, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c,
+ 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5f, 0x65, 0x74, 0x63, 0x31, 0x73, 0x28, 0x26, 0x6f, 0x75, 0x74, 0x70,
+ 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x65, 0x74, 0x63, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x35, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x2e, 0x77, 0x29, 0x3b, 0x0d, 0x0a,
+ 0x0d, 0x0a, 0x09, 0x66, 0x6f, 0x72, 0x20, 0x28, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x20, 0x69, 0x20, 0x3c, 0x20, 0x31, 0x36, 0x3b, 0x20,
+ 0x69, 0x2b, 0x2b, 0x29, 0x0d, 0x0a, 0x09, 0x7b, 0x0d, 0x0a, 0x09, 0x09, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x72, 0x67, 0x62, 0x61, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x73, 0x5b, 0x69, 0x5d, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74,
+ 0x20, 0x65, 0x72, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f,
+ 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63,
+ 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x30, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x65, 0x72, 0x72, 0x31, 0x20, 0x3d,
+ 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74,
+ 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x31,
+ 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x65, 0x72, 0x72, 0x32, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f,
+ 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x70, 0x69,
+ 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x32, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73,
+ 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x65, 0x72, 0x72, 0x33, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x5f, 0x64, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x63,
+ 0x65, 0x28, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x2e, 0x6d, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x75, 0x61, 0x6c, 0x2c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x5f, 0x63, 0x6f, 0x6c,
+ 0x6f, 0x72, 0x2c, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 0x5b, 0x33, 0x5d, 0x2c, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a,
+ 0x09, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x69, 0x6e, 0x28, 0x6d, 0x69, 0x6e, 0x28, 0x6d, 0x69, 0x6e, 0x28, 0x65, 0x72,
+ 0x72, 0x30, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x31, 0x29, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x32, 0x29, 0x2c, 0x20, 0x65, 0x72, 0x72, 0x33, 0x29, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x75, 0x69,
+ 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x74, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x65,
+ 0x72, 0x72, 0x32, 0x29, 0x20, 0x3f, 0x20, 0x32, 0x20, 0x3a, 0x20, 0x33, 0x3b, 0x0d, 0x0a, 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x65, 0x73,
+ 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x65, 0x72, 0x72, 0x31, 0x29, 0x20, 0x3f, 0x20, 0x31, 0x20, 0x3a, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x3b, 0x0d, 0x0a,
+ 0x09, 0x09, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x20, 0x3d, 0x20, 0x28, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x20, 0x3d, 0x3d, 0x20, 0x65, 0x72, 0x72, 0x30, 0x29, 0x20,
+ 0x3f, 0x20, 0x30, 0x20, 0x3a, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x3b, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x09, 0x65, 0x74, 0x63, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73,
+ 0x65, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x28, 0x26, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x2c, 0x20, 0x69, 0x20, 0x26, 0x20, 0x33,
+ 0x2c, 0x20, 0x69, 0x20, 0x3e, 0x3e, 0x20, 0x32, 0x2c, 0x20, 0x62, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x29, 0x3b, 0x0d, 0x0a, 0x09, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a, 0x09, 0x70, 0x4f, 0x75,
+ 0x74, 0x70, 0x75, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x5b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x5d, 0x20, 0x3d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75,
+ 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x3b, 0x0d, 0x0a, 0x7d, 0x0d, 0x0a, 0x0d, 0x0a
+};
+unsigned int ocl_kernels_cl_len = 45935;
diff --git a/thirdparty/basis_universal/encoder/basisu_opencl.cpp b/thirdparty/basis_universal/encoder/basisu_opencl.cpp
new file mode 100644
index 0000000000..81e3090a26
--- /dev/null
+++ b/thirdparty/basis_universal/encoder/basisu_opencl.cpp
@@ -0,0 +1,1332 @@
+// basisu_opencl.cpp
+// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "basisu_opencl.h"
+
+// If 1, the kernel source code will come from encoders/ocl_kernels.h. Otherwise, it will be read from the "ocl_kernels.cl" file in the current directory (for development).
+#define BASISU_USE_OCL_KERNELS_HEADER (1)
+#define BASISU_OCL_KERNELS_FILENAME "ocl_kernels.cl"
+
+#if BASISU_SUPPORT_OPENCL
+
+#include "basisu_enc.h"
+
+// We only use OpenCL v1.2 or less.
+#define CL_TARGET_OPENCL_VERSION 120
+
+#ifdef __APPLE__
+#include <OpenCL/opencl.h>
+#else
+#include <CL/cl.h>
+#endif
+
+#define BASISU_OPENCL_ASSERT_ON_ANY_ERRORS (1)
+
+namespace basisu
+{
+#if BASISU_USE_OCL_KERNELS_HEADER
+#include "basisu_ocl_kernels.h"
+#endif
+
+ static void ocl_error_printf(const char* pFmt, ...)
+ {
+ va_list args;
+ va_start(args, pFmt);
+ error_vprintf(pFmt, args);
+ va_end(args);
+
+#if BASISU_OPENCL_ASSERT_ON_ANY_ERRORS
+ assert(0);
+#endif
+ }
+
+ class ocl
+ {
+ public:
+ ocl()
+ {
+ memset(&m_dev_fp_config, 0, sizeof(m_dev_fp_config));
+
+ m_ocl_mutex.lock();
+ m_ocl_mutex.unlock();
+ }
+
+ ~ocl()
+ {
+ }
+
+ bool is_initialized() const { return m_device_id != nullptr; }
+
+ cl_device_id get_device_id() const { return m_device_id; }
+ cl_context get_context() const { return m_context; }
+ cl_command_queue get_command_queue() { return m_command_queue; }
+ cl_program get_program() const { return m_program; }
+
+ bool init(bool force_serialization)
+ {
+ deinit();
+
+ interval_timer tm;
+ tm.start();
+
+ cl_uint num_platforms = 0;
+ cl_int ret = clGetPlatformIDs(0, NULL, &num_platforms);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: clGetPlatformIDs() failed with %i\n", ret);
+ return false;
+ }
+
+ if ((!num_platforms) || (num_platforms > INT_MAX))
+ {
+ ocl_error_printf("ocl::init: clGetPlatformIDs() returned an invalid number of num_platforms\n");
+ return false;
+ }
+
+ std::vector<cl_platform_id> platforms(num_platforms);
+
+ ret = clGetPlatformIDs(num_platforms, platforms.data(), NULL);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: clGetPlatformIDs() failed\n");
+ return false;
+ }
+
+ cl_uint num_devices = 0;
+ ret = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, 1, &m_device_id, &num_devices);
+
+ if (ret == CL_DEVICE_NOT_FOUND)
+ {
+ ocl_error_printf("ocl::init: Couldn't get any GPU device ID's, trying CL_DEVICE_TYPE_CPU\n");
+
+ ret = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_CPU, 1, &m_device_id, &num_devices);
+ }
+
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: Unable to get any device ID's\n");
+
+ m_device_id = nullptr;
+ return false;
+ }
+
+ ret = clGetDeviceInfo(m_device_id,
+ CL_DEVICE_SINGLE_FP_CONFIG,
+ sizeof(m_dev_fp_config),
+ &m_dev_fp_config,
+ nullptr);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: clGetDeviceInfo() failed\n");
+ return false;
+ }
+
+ char plat_vers[256];
+ size_t rv = 0;
+ ret = clGetPlatformInfo(platforms[0], CL_PLATFORM_VERSION, sizeof(plat_vers), plat_vers, &rv);
+ if (ret == CL_SUCCESS)
+ printf("OpenCL platform version: \"%s\"\n", plat_vers);
+
+ // Serialize CL calls with the AMD driver to avoid lockups when multiple command queues per thread are used. This sucks, but what can we do?
+ m_use_mutex = (strstr(plat_vers, "AMD") != nullptr) || force_serialization;
+
+ printf("Serializing OpenCL calls across threads: %u\n", (uint32_t)m_use_mutex);
+
+ m_context = clCreateContext(nullptr, 1, &m_device_id, nullptr, nullptr, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: clCreateContext() failed\n");
+
+ m_device_id = nullptr;
+ m_context = nullptr;
+ return false;
+ }
+
+ m_command_queue = clCreateCommandQueue(m_context, m_device_id, 0, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init: clCreateCommandQueue() failed\n");
+
+ deinit();
+ return false;
+ }
+
+ printf("OpenCL init time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ return true;
+ }
+
+ bool deinit()
+ {
+ if (m_program)
+ {
+ clReleaseProgram(m_program);
+ m_program = nullptr;
+ }
+
+ if (m_command_queue)
+ {
+ clReleaseCommandQueue(m_command_queue);
+ m_command_queue = nullptr;
+ }
+
+ if (m_context)
+ {
+ clReleaseContext(m_context);
+ m_context = nullptr;
+ }
+
+ m_device_id = nullptr;
+
+ return true;
+ }
+
+ cl_command_queue create_command_queue()
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = 0;
+ cl_command_queue p = clCreateCommandQueue(m_context, m_device_id, 0, &ret);
+ if (ret != CL_SUCCESS)
+ return nullptr;
+
+ return p;
+ }
+
+ void destroy_command_queue(cl_command_queue p)
+ {
+ if (p)
+ {
+ cl_serializer serializer(this);
+
+ clReleaseCommandQueue(p);
+ }
+ }
+
+ bool init_program(const char* pSrc, size_t src_size)
+ {
+ cl_int ret;
+
+ if (m_program != nullptr)
+ {
+ clReleaseProgram(m_program);
+ m_program = nullptr;
+ }
+
+ m_program = clCreateProgramWithSource(m_context, 1, (const char**)&pSrc, (const size_t*)&src_size, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init_program: clCreateProgramWithSource() failed!\n");
+ return false;
+ }
+
+ std::string options;
+ if (m_dev_fp_config & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT)
+ {
+ options += "-cl-fp32-correctly-rounded-divide-sqrt";
+ }
+
+ options += " -cl-std=CL1.2";
+ //options += " -cl-opt-disable";
+ //options += " -cl-mad-enable";
+ //options += " -cl-fast-relaxed-math";
+
+ ret = clBuildProgram(m_program, 1, &m_device_id,
+ options.size() ? options.c_str() : nullptr, // options
+ nullptr, // notify
+ nullptr); // user_data
+
+ if (ret != CL_SUCCESS)
+ {
+ const cl_int build_program_result = ret;
+
+ size_t ret_val_size;
+ ret = clGetProgramBuildInfo(m_program, m_device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::init_program: clGetProgramBuildInfo() failed!\n");
+ return false;
+ }
+
+ std::vector<char> build_log(ret_val_size + 1);
+
+ ret = clGetProgramBuildInfo(m_program, m_device_id, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log.data(), NULL);
+
+ ocl_error_printf("\nclBuildProgram() failed with error %i:\n%s", build_program_result, build_log.data());
+
+ return false;
+ }
+
+ return true;
+ }
+
+ cl_kernel create_kernel(const char* pName)
+ {
+ if (!m_program)
+ return nullptr;
+
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_kernel kernel = clCreateKernel(m_program, pName, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::create_kernel: clCreateKernel() failed!\n");
+ return nullptr;
+ }
+
+ return kernel;
+ }
+
+ bool destroy_kernel(cl_kernel k)
+ {
+ if (k)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clReleaseKernel(k);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::destroy_kernel: clReleaseKernel() failed!\n");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ cl_mem alloc_read_buffer(size_t size)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_mem obj = clCreateBuffer(m_context, CL_MEM_READ_ONLY, size, NULL, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::alloc_read_buffer: clCreateBuffer() failed!\n");
+ return nullptr;
+ }
+
+ return obj;
+ }
+
+ cl_mem alloc_and_init_read_buffer(cl_command_queue command_queue, const void *pInit, size_t size)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_mem obj = clCreateBuffer(m_context, CL_MEM_READ_ONLY, size, NULL, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::alloc_and_init_read_buffer: clCreateBuffer() failed!\n");
+ return nullptr;
+ }
+
+#if 0
+ if (!write_to_buffer(command_queue, obj, pInit, size))
+ {
+ destroy_buffer(obj);
+ return nullptr;
+ }
+#else
+ ret = clEnqueueWriteBuffer(command_queue, obj, CL_TRUE, 0, size, pInit, 0, NULL, NULL);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::alloc_and_init_read_buffer: clEnqueueWriteBuffer() failed!\n");
+ return nullptr;
+ }
+#endif
+
+ return obj;
+ }
+
+ cl_mem alloc_write_buffer(size_t size)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_mem obj = clCreateBuffer(m_context, CL_MEM_WRITE_ONLY, size, NULL, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::alloc_write_buffer: clCreateBuffer() failed!\n");
+ return nullptr;
+ }
+
+ return obj;
+ }
+
+ bool destroy_buffer(cl_mem buf)
+ {
+ if (buf)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clReleaseMemObject(buf);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::destroy_buffer: clReleaseMemObject() failed!\n");
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ bool write_to_buffer(cl_command_queue command_queue, cl_mem clmem, const void* d, const size_t m)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clEnqueueWriteBuffer(command_queue, clmem, CL_TRUE, 0, m, d, 0, NULL, NULL);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::write_to_buffer: clEnqueueWriteBuffer() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool read_from_buffer(cl_command_queue command_queue, const cl_mem clmem, void* d, size_t m)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clEnqueueReadBuffer(command_queue, clmem, CL_TRUE, 0, m, d, 0, NULL, NULL);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::read_from_buffer: clEnqueueReadBuffer() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ cl_mem create_read_image_u8(uint32_t width, uint32_t height, const void* pPixels, uint32_t bytes_per_pixel, bool normalized)
+ {
+ cl_image_format fmt = get_image_format(bytes_per_pixel, normalized);
+
+ cl_image_desc desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = width;
+ desc.image_height = height;
+ desc.image_row_pitch = width * bytes_per_pixel;
+
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_mem img = clCreateImage(m_context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &fmt, &desc, (void*)pPixels, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::create_read_image_u8: clCreateImage() failed!\n");
+ return nullptr;
+ }
+
+ return img;
+ }
+
+ cl_mem create_write_image_u8(uint32_t width, uint32_t height, uint32_t bytes_per_pixel, bool normalized)
+ {
+ cl_image_format fmt = get_image_format(bytes_per_pixel, normalized);
+
+ cl_image_desc desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = width;
+ desc.image_height = height;
+
+ cl_serializer serializer(this);
+
+ cl_int ret;
+ cl_mem img = clCreateImage(m_context, CL_MEM_WRITE_ONLY, &fmt, &desc, nullptr, &ret);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::create_write_image_u8: clCreateImage() failed!\n");
+ return nullptr;
+ }
+
+ return img;
+ }
+
+ bool read_from_image(cl_command_queue command_queue, cl_mem img, void* pPixels, uint32_t ofs_x, uint32_t ofs_y, uint32_t width, uint32_t height)
+ {
+ cl_serializer serializer(this);
+
+ size_t origin[3] = { ofs_x, ofs_y, 0 }, region[3] = { width, height, 1 };
+
+ cl_int err = clEnqueueReadImage(command_queue, img, CL_TRUE, origin, region, 0, 0, pPixels, 0, NULL, NULL);
+ if (err != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::read_from_image: clEnqueueReadImage() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool run_1D(cl_command_queue command_queue, const cl_kernel kernel, size_t num_items)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clEnqueueNDRangeKernel(command_queue, kernel,
+ 1, // work_dim
+ nullptr, // global_work_offset
+ &num_items, // global_work_size
+ nullptr, // local_work_size
+ 0, // num_events_in_wait_list
+ nullptr, // event_wait_list
+ nullptr // event
+ );
+
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::run_1D: clEnqueueNDRangeKernel() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool run_2D(cl_command_queue command_queue, const cl_kernel kernel, size_t width, size_t height)
+ {
+ cl_serializer serializer(this);
+
+ size_t num_global_items[2] = { width, height };
+ //size_t num_local_items[2] = { 1, 1 };
+
+ cl_int ret = clEnqueueNDRangeKernel(command_queue, kernel,
+ 2, // work_dim
+ nullptr, // global_work_offset
+ num_global_items, // global_work_size
+ nullptr, // local_work_size
+ 0, // num_events_in_wait_list
+ nullptr, // event_wait_list
+ nullptr // event
+ );
+
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::run_2D: clEnqueueNDRangeKernel() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ bool run_2D(cl_command_queue command_queue, const cl_kernel kernel, size_t ofs_x, size_t ofs_y, size_t width, size_t height)
+ {
+ cl_serializer serializer(this);
+
+ size_t global_ofs[2] = { ofs_x, ofs_y };
+ size_t num_global_items[2] = { width, height };
+ //size_t num_local_items[2] = { 1, 1 };
+
+ cl_int ret = clEnqueueNDRangeKernel(command_queue, kernel,
+ 2, // work_dim
+ global_ofs, // global_work_offset
+ num_global_items, // global_work_size
+ nullptr, // local_work_size
+ 0, // num_events_in_wait_list
+ nullptr, // event_wait_list
+ nullptr // event
+ );
+
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::run_2D: clEnqueueNDRangeKernel() failed!\n");
+ return false;
+ }
+
+ return true;
+ }
+
+ void flush(cl_command_queue command_queue)
+ {
+ cl_serializer serializer(this);
+
+ clFlush(command_queue);
+ clFinish(command_queue);
+ }
+
+ template<typename T>
+ bool set_kernel_arg(cl_kernel kernel, uint32_t index, const T& obj)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clSetKernelArg(kernel, index, sizeof(T), (void*)&obj);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::set_kernel_arg: clSetKernelArg() failed!\n");
+ return false;
+ }
+ return true;
+ }
+
+ template<typename T>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1)
+ {
+ cl_serializer serializer(this);
+
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1);
+ if (ret != CL_SUCCESS)
+ {
+ ocl_error_printf("ocl::set_kernel_arg: clSetKernelArg() failed!\n");
+ return false;
+ }
+ return true;
+ }
+
+#define BASISU_CHECK_ERR if (ret != CL_SUCCESS) { ocl_error_printf("ocl::set_kernel_args: clSetKernelArg() failed!\n"); return false; }
+
+ template<typename T, typename U>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V, typename W>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3, const W& obj4)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 3, sizeof(W), (void*)&obj4); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename X>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3, const W& obj4, const X& obj5)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 3, sizeof(W), (void*)&obj4); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 4, sizeof(X), (void*)&obj5); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename X, typename Y>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3, const W& obj4, const X& obj5, const Y& obj6)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 3, sizeof(W), (void*)&obj4); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 4, sizeof(X), (void*)&obj5); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 5, sizeof(Y), (void*)&obj6); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3, const W& obj4, const X& obj5, const Y& obj6, const Z& obj7)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 3, sizeof(W), (void*)&obj4); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 4, sizeof(X), (void*)&obj5); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 5, sizeof(Y), (void*)&obj6); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 6, sizeof(Z), (void*)&obj7); BASISU_CHECK_ERR
+ return true;
+ }
+
+ template<typename T, typename U, typename V, typename W, typename X, typename Y, typename Z, typename A>
+ bool set_kernel_args(cl_kernel kernel, const T& obj1, const U& obj2, const V& obj3, const W& obj4, const X& obj5, const Y& obj6, const Z& obj7, const A& obj8)
+ {
+ cl_serializer serializer(this);
+ cl_int ret = clSetKernelArg(kernel, 0, sizeof(T), (void*)&obj1); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 1, sizeof(U), (void*)&obj2); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 2, sizeof(V), (void*)&obj3); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 3, sizeof(W), (void*)&obj4); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 4, sizeof(X), (void*)&obj5); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 5, sizeof(Y), (void*)&obj6); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 6, sizeof(Z), (void*)&obj7); BASISU_CHECK_ERR
+ ret = clSetKernelArg(kernel, 7, sizeof(A), (void*)&obj8); BASISU_CHECK_ERR
+ return true;
+ }
+#undef BASISU_CHECK_ERR
+
+ private:
+ cl_device_id m_device_id = nullptr;
+ cl_context m_context = nullptr;
+ cl_command_queue m_command_queue = nullptr;
+ cl_program m_program = nullptr;
+ cl_device_fp_config m_dev_fp_config;
+
+ bool m_use_mutex = false;
+ std::mutex m_ocl_mutex;
+
+ // This helper object is used to optionally serialize all calls to the CL driver after initialization.
+ // Currently this is only used to work around race conditions in the Windows AMD driver.
+ struct cl_serializer
+ {
+ inline cl_serializer(const cl_serializer&);
+ cl_serializer& operator= (const cl_serializer&);
+
+ inline cl_serializer(ocl *p) : m_p(p)
+ {
+ if (m_p->m_use_mutex)
+ m_p->m_ocl_mutex.lock();
+ }
+
+ inline ~cl_serializer()
+ {
+ if (m_p->m_use_mutex)
+ m_p->m_ocl_mutex.unlock();
+ }
+
+ private:
+ ocl* m_p;
+ };
+
+ cl_image_format get_image_format(uint32_t bytes_per_pixel, bool normalized)
+ {
+ cl_image_format fmt;
+ switch (bytes_per_pixel)
+ {
+ case 1: fmt.image_channel_order = CL_LUMINANCE; break;
+ case 2: fmt.image_channel_order = CL_RG; break;
+ case 3: fmt.image_channel_order = CL_RGB; break;
+ case 4: fmt.image_channel_order = CL_RGBA; break;
+ default: assert(0); fmt.image_channel_order = CL_LUMINANCE; break;
+ }
+
+ fmt.image_channel_data_type = normalized ? CL_UNORM_INT8 : CL_UNSIGNED_INT8;
+ return fmt;
+ }
+ };
+
+ // Library blobal state
+ ocl g_ocl;
+
+ bool opencl_init(bool force_serialization)
+ {
+ if (g_ocl.is_initialized())
+ {
+ assert(0);
+ return false;
+ }
+
+ if (!g_ocl.init(force_serialization))
+ {
+ ocl_error_printf("opencl_init: Failed initializing OpenCL\n");
+ return false;
+ }
+
+ const char* pKernel_src = nullptr;
+ size_t kernel_src_size = 0;
+ uint8_vec kernel_src;
+
+#if BASISU_USE_OCL_KERNELS_HEADER
+ pKernel_src = reinterpret_cast<const char*>(ocl_kernels_cl);
+ kernel_src_size = ocl_kernels_cl_len;
+#else
+ if (!read_file_to_vec(BASISU_OCL_KERNELS_FILENAME, kernel_src))
+ {
+ ocl_error_printf("opencl_init: Cannot read OpenCL kernel source file \"%s\"\n", BASISU_OCL_KERNELS_FILENAME);
+ g_ocl.deinit();
+ return false;
+ }
+
+ pKernel_src = (char*)kernel_src.data();
+ kernel_src_size = kernel_src.size();
+#endif
+
+ if (!kernel_src_size)
+ {
+ ocl_error_printf("opencl_init: Invalid OpenCL kernel source file \"%s\"\n", BASISU_OCL_KERNELS_FILENAME);
+ g_ocl.deinit();
+ return false;
+ }
+
+ if (!g_ocl.init_program(pKernel_src, kernel_src_size))
+ {
+ ocl_error_printf("opencl_init: Failed compiling OpenCL program\n");
+ g_ocl.deinit();
+ return false;
+ }
+
+ printf("OpenCL support initialized successfully\n");
+
+ return true;
+ }
+
+ void opencl_deinit()
+ {
+ g_ocl.deinit();
+ }
+
+ bool opencl_is_available()
+ {
+ return g_ocl.is_initialized();
+ }
+
+ struct opencl_context
+ {
+ uint32_t m_ocl_total_pixel_blocks;
+ cl_mem m_ocl_pixel_blocks;
+
+ cl_command_queue m_command_queue;
+
+ cl_kernel m_ocl_encode_etc1s_blocks_kernel;
+ cl_kernel m_ocl_refine_endpoint_clusterization_kernel;
+ cl_kernel m_ocl_encode_etc1s_from_pixel_cluster_kernel;
+ cl_kernel m_ocl_find_optimal_selector_clusters_for_each_block_kernel;
+ cl_kernel m_ocl_determine_selectors_kernel;
+ };
+
+ opencl_context_ptr opencl_create_context()
+ {
+ if (!opencl_is_available())
+ {
+ ocl_error_printf("opencl_create_context: OpenCL not initialized\n");
+ assert(0);
+ return nullptr;
+ }
+
+ interval_timer tm;
+ tm.start();
+
+ opencl_context* pContext = static_cast<opencl_context * >(calloc(sizeof(opencl_context), 1));
+ if (!pContext)
+ return nullptr;
+
+ // To avoid driver bugs in some drivers - serialize this. Likely not necessary, we don't know.
+ // https://community.intel.com/t5/OpenCL-for-CPU/Bug-report-clCreateKernelsInProgram-is-not-thread-safe/td-p/1159771
+
+ pContext->m_command_queue = g_ocl.create_command_queue();
+ if (!pContext->m_command_queue)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL command queue!\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ pContext->m_ocl_encode_etc1s_blocks_kernel = g_ocl.create_kernel("encode_etc1s_blocks");
+ if (!pContext->m_ocl_encode_etc1s_blocks_kernel)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL kernel encode_etc1s_block\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ pContext->m_ocl_refine_endpoint_clusterization_kernel = g_ocl.create_kernel("refine_endpoint_clusterization");
+ if (!pContext->m_ocl_refine_endpoint_clusterization_kernel)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL kernel refine_endpoint_clusterization\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ pContext->m_ocl_encode_etc1s_from_pixel_cluster_kernel = g_ocl.create_kernel("encode_etc1s_from_pixel_cluster");
+ if (!pContext->m_ocl_encode_etc1s_from_pixel_cluster_kernel)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL kernel encode_etc1s_from_pixel_cluster\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ pContext->m_ocl_find_optimal_selector_clusters_for_each_block_kernel = g_ocl.create_kernel("find_optimal_selector_clusters_for_each_block");
+ if (!pContext->m_ocl_find_optimal_selector_clusters_for_each_block_kernel)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL kernel find_optimal_selector_clusters_for_each_block\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ pContext->m_ocl_determine_selectors_kernel = g_ocl.create_kernel("determine_selectors");
+ if (!pContext->m_ocl_determine_selectors_kernel)
+ {
+ ocl_error_printf("opencl_create_context: Failed creating OpenCL kernel determine_selectors\n");
+ opencl_destroy_context(pContext);
+ return nullptr;
+ }
+
+ debug_printf("opencl_create_context: Elapsed time: %f secs\n", tm.get_elapsed_secs());
+
+ return pContext;
+ }
+
+ void opencl_destroy_context(opencl_context_ptr pContext)
+ {
+ if (!pContext)
+ return;
+
+ interval_timer tm;
+ tm.start();
+
+ g_ocl.destroy_buffer(pContext->m_ocl_pixel_blocks);
+
+ g_ocl.destroy_kernel(pContext->m_ocl_determine_selectors_kernel);
+ g_ocl.destroy_kernel(pContext->m_ocl_find_optimal_selector_clusters_for_each_block_kernel);
+ g_ocl.destroy_kernel(pContext->m_ocl_encode_etc1s_from_pixel_cluster_kernel);
+ g_ocl.destroy_kernel(pContext->m_ocl_encode_etc1s_blocks_kernel);
+ g_ocl.destroy_kernel(pContext->m_ocl_refine_endpoint_clusterization_kernel);
+
+ g_ocl.destroy_command_queue(pContext->m_command_queue);
+
+ memset(pContext, 0, sizeof(opencl_context));
+
+ free(pContext);
+
+ debug_printf("opencl_destroy_context: Elapsed time: %f secs\n", tm.get_elapsed_secs());
+ }
+
+#pragma pack(push, 1)
+ struct cl_encode_etc1s_param_struct
+ {
+ int m_total_blocks;
+ int m_perceptual;
+ int m_total_perms;
+ };
+#pragma pack(pop)
+
+ bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ if (pContext->m_ocl_pixel_blocks)
+ {
+ g_ocl.destroy_buffer(pContext->m_ocl_pixel_blocks);
+ pContext->m_ocl_pixel_blocks = nullptr;
+ }
+
+ pContext->m_ocl_pixel_blocks = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pPixel_blocks, sizeof(cl_pixel_block) * total_blocks);
+ if (!pContext->m_ocl_pixel_blocks)
+ return false;
+
+ pContext->m_ocl_total_pixel_blocks = total_blocks;
+
+ return true;
+ }
+
+ bool opencl_encode_etc1s_blocks(opencl_context_ptr pContext, etc_block* pOutput_blocks, bool perceptual, uint32_t total_perms)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ interval_timer tm;
+ tm.start();
+
+ assert(pContext->m_ocl_pixel_blocks);
+ if (!pContext->m_ocl_pixel_blocks)
+ return false;
+
+ cl_encode_etc1s_param_struct ps;
+ ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
+ ps.m_perceptual = perceptual;
+ ps.m_total_perms = total_perms;
+
+ bool status = false;
+
+ cl_mem vars = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue , &ps, sizeof(ps));
+ cl_mem block_buf = g_ocl.alloc_write_buffer(sizeof(etc_block) * pContext->m_ocl_total_pixel_blocks);
+
+ if (!vars || !block_buf)
+ goto exit;
+
+ if (!g_ocl.set_kernel_args(pContext->m_ocl_encode_etc1s_blocks_kernel, vars, pContext->m_ocl_pixel_blocks, block_buf))
+ goto exit;
+
+ if (!g_ocl.run_2D(pContext->m_command_queue, pContext->m_ocl_encode_etc1s_blocks_kernel, pContext->m_ocl_total_pixel_blocks, 1))
+ goto exit;
+
+ if (!g_ocl.read_from_buffer(pContext->m_command_queue, block_buf, pOutput_blocks, pContext->m_ocl_total_pixel_blocks * sizeof(etc_block)))
+ goto exit;
+
+ status = true;
+
+ debug_printf("opencl_encode_etc1s_blocks: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+exit:
+ g_ocl.destroy_buffer(block_buf);
+ g_ocl.destroy_buffer(vars);
+
+ return status;
+ }
+
+ bool opencl_encode_etc1s_pixel_clusters(
+ opencl_context_ptr pContext,
+ etc_block* pOutput_blocks,
+ uint32_t total_clusters,
+ const cl_pixel_cluster* pClusters,
+ uint64_t total_pixels,
+ const color_rgba* pPixels, const uint32_t* pPixel_weights,
+ bool perceptual, uint32_t total_perms)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ interval_timer tm;
+ tm.start();
+
+ cl_encode_etc1s_param_struct ps;
+ ps.m_total_blocks = total_clusters;
+ ps.m_perceptual = perceptual;
+ ps.m_total_perms = total_perms;
+
+ bool status = false;
+
+ if (sizeof(size_t) == sizeof(uint32_t))
+ {
+ if ( ((sizeof(cl_pixel_cluster) * total_clusters) > UINT32_MAX) ||
+ ((sizeof(color_rgba) * total_pixels) > UINT32_MAX) ||
+ ((sizeof(uint32_t) * total_pixels) > UINT32_MAX) )
+ {
+ return false;
+ }
+ }
+
+ cl_mem vars = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue , &ps, sizeof(ps));
+ cl_mem input_clusters = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pClusters, (size_t)(sizeof(cl_pixel_cluster) * total_clusters));
+ cl_mem input_pixels = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pPixels, (size_t)(sizeof(color_rgba) * total_pixels));
+ cl_mem weights_buf = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pPixel_weights, (size_t)(sizeof(uint32_t) * total_pixels));
+ cl_mem block_buf = g_ocl.alloc_write_buffer(sizeof(etc_block) * total_clusters);
+
+ if (!vars || !input_clusters || !input_pixels || !weights_buf || !block_buf)
+ goto exit;
+
+ if (!g_ocl.set_kernel_args(pContext->m_ocl_encode_etc1s_from_pixel_cluster_kernel, vars, input_clusters, input_pixels, weights_buf, block_buf))
+ goto exit;
+
+ if (!g_ocl.run_2D(pContext->m_command_queue, pContext->m_ocl_encode_etc1s_from_pixel_cluster_kernel, total_clusters, 1))
+ goto exit;
+
+ if (!g_ocl.read_from_buffer(pContext->m_command_queue, block_buf, pOutput_blocks, sizeof(etc_block) * total_clusters))
+ goto exit;
+
+ status = true;
+
+ debug_printf("opencl_encode_etc1s_pixel_clusters: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ exit:
+ g_ocl.destroy_buffer(block_buf);
+ g_ocl.destroy_buffer(weights_buf);
+ g_ocl.destroy_buffer(input_pixels);
+ g_ocl.destroy_buffer(input_clusters);
+ g_ocl.destroy_buffer(vars);
+
+ return status;
+ }
+
+#pragma pack(push, 1)
+ struct cl_rec_param_struct
+ {
+ int m_total_blocks;
+ int m_perceptual;
+ };
+#pragma pack(pop)
+
+ bool opencl_refine_endpoint_clusterization(
+ opencl_context_ptr pContext,
+ const cl_block_info_struct* pPixel_block_info,
+ uint32_t total_clusters,
+ const cl_endpoint_cluster_struct* pCluster_info,
+ const uint32_t* pSorted_block_indices,
+ uint32_t* pOutput_cluster_indices,
+ bool perceptual)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ interval_timer tm;
+ tm.start();
+
+ assert(pContext->m_ocl_pixel_blocks);
+ if (!pContext->m_ocl_pixel_blocks)
+ return false;
+
+ cl_rec_param_struct ps;
+ ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
+ ps.m_perceptual = perceptual;
+
+ bool status = false;
+
+ cl_mem pixel_block_info = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pPixel_block_info, sizeof(cl_block_info_struct) * pContext->m_ocl_total_pixel_blocks);
+ cl_mem cluster_info = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pCluster_info, sizeof(cl_endpoint_cluster_struct) * total_clusters);
+ cl_mem sorted_block_indices = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pSorted_block_indices, sizeof(uint32_t) * pContext->m_ocl_total_pixel_blocks);
+ cl_mem output_buf = g_ocl.alloc_write_buffer(sizeof(uint32_t) * pContext->m_ocl_total_pixel_blocks);
+
+ if (!pixel_block_info || !cluster_info || !sorted_block_indices || !output_buf)
+ goto exit;
+
+ if (!g_ocl.set_kernel_args(pContext->m_ocl_refine_endpoint_clusterization_kernel, ps, pContext->m_ocl_pixel_blocks, pixel_block_info, cluster_info, sorted_block_indices, output_buf))
+ goto exit;
+
+ if (!g_ocl.run_2D(pContext->m_command_queue, pContext->m_ocl_refine_endpoint_clusterization_kernel, pContext->m_ocl_total_pixel_blocks, 1))
+ goto exit;
+
+ if (!g_ocl.read_from_buffer(pContext->m_command_queue, output_buf, pOutput_cluster_indices, pContext->m_ocl_total_pixel_blocks * sizeof(uint32_t)))
+ goto exit;
+
+ debug_printf("opencl_refine_endpoint_clusterization: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ status = true;
+
+exit:
+ g_ocl.destroy_buffer(pixel_block_info);
+ g_ocl.destroy_buffer(cluster_info);
+ g_ocl.destroy_buffer(sorted_block_indices);
+ g_ocl.destroy_buffer(output_buf);
+
+ return status;
+ }
+
+ bool opencl_find_optimal_selector_clusters_for_each_block(
+ opencl_context_ptr pContext,
+ const fosc_block_struct* pInput_block_info, // one per block
+ uint32_t total_input_selectors,
+ const fosc_selector_struct* pInput_selectors,
+ const uint32_t* pSelector_cluster_indices,
+ uint32_t* pOutput_selector_cluster_indices, // one per block
+ bool perceptual)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ interval_timer tm;
+ tm.start();
+
+ assert(pContext->m_ocl_pixel_blocks);
+ if (!pContext->m_ocl_pixel_blocks)
+ return false;
+
+ fosc_param_struct ps;
+ ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
+ ps.m_perceptual = perceptual;
+
+ bool status = false;
+
+ cl_mem input_block_info = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pInput_block_info, sizeof(fosc_block_struct) * pContext->m_ocl_total_pixel_blocks);
+ cl_mem input_selectors = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pInput_selectors, sizeof(fosc_selector_struct) * total_input_selectors);
+ cl_mem selector_cluster_indices = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pSelector_cluster_indices, sizeof(uint32_t) * total_input_selectors);
+ cl_mem output_selector_cluster_indices = g_ocl.alloc_write_buffer(sizeof(uint32_t) * pContext->m_ocl_total_pixel_blocks);
+
+ if (!input_block_info || !input_selectors || !selector_cluster_indices || !output_selector_cluster_indices)
+ goto exit;
+
+ if (!g_ocl.set_kernel_args(pContext->m_ocl_find_optimal_selector_clusters_for_each_block_kernel, ps, pContext->m_ocl_pixel_blocks, input_block_info, input_selectors, selector_cluster_indices, output_selector_cluster_indices))
+ goto exit;
+
+ if (!g_ocl.run_2D(pContext->m_command_queue, pContext->m_ocl_find_optimal_selector_clusters_for_each_block_kernel, pContext->m_ocl_total_pixel_blocks, 1))
+ goto exit;
+
+ if (!g_ocl.read_from_buffer(pContext->m_command_queue, output_selector_cluster_indices, pOutput_selector_cluster_indices, pContext->m_ocl_total_pixel_blocks * sizeof(uint32_t)))
+ goto exit;
+
+ debug_printf("opencl_find_optimal_selector_clusters_for_each_block: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ status = true;
+
+ exit:
+ g_ocl.destroy_buffer(input_block_info);
+ g_ocl.destroy_buffer(input_selectors);
+ g_ocl.destroy_buffer(selector_cluster_indices);
+ g_ocl.destroy_buffer(output_selector_cluster_indices);
+
+ return status;
+ }
+
+ bool opencl_determine_selectors(
+ opencl_context_ptr pContext,
+ const color_rgba* pInput_etc_color5_and_inten,
+ etc_block* pOutput_blocks,
+ bool perceptual)
+ {
+ if (!opencl_is_available())
+ return false;
+
+ interval_timer tm;
+ tm.start();
+
+ assert(pContext->m_ocl_pixel_blocks);
+ if (!pContext->m_ocl_pixel_blocks)
+ return false;
+
+ ds_param_struct ps;
+ ps.m_total_blocks = pContext->m_ocl_total_pixel_blocks;
+ ps.m_perceptual = perceptual;
+
+ bool status = false;
+
+ cl_mem input_etc_color5_intens = g_ocl.alloc_and_init_read_buffer(pContext->m_command_queue, pInput_etc_color5_and_inten, sizeof(color_rgba) * pContext->m_ocl_total_pixel_blocks);
+ cl_mem output_blocks = g_ocl.alloc_write_buffer(sizeof(etc_block) * pContext->m_ocl_total_pixel_blocks);
+
+ if (!input_etc_color5_intens || !output_blocks)
+ goto exit;
+
+ if (!g_ocl.set_kernel_args(pContext->m_ocl_determine_selectors_kernel, ps, pContext->m_ocl_pixel_blocks, input_etc_color5_intens, output_blocks))
+ goto exit;
+
+ if (!g_ocl.run_2D(pContext->m_command_queue, pContext->m_ocl_determine_selectors_kernel, pContext->m_ocl_total_pixel_blocks, 1))
+ goto exit;
+
+ if (!g_ocl.read_from_buffer(pContext->m_command_queue, output_blocks, pOutput_blocks, pContext->m_ocl_total_pixel_blocks * sizeof(etc_block)))
+ goto exit;
+
+ debug_printf("opencl_determine_selectors: Elapsed time: %3.3f secs\n", tm.get_elapsed_secs());
+
+ status = true;
+
+ exit:
+ g_ocl.destroy_buffer(input_etc_color5_intens);
+ g_ocl.destroy_buffer(output_blocks);
+
+ return status;
+ }
+
+#else
+namespace basisu
+{
+ // No OpenCL support - all dummy functions that return false;
+ bool opencl_init(bool force_serialization)
+ {
+ BASISU_NOTE_UNUSED(force_serialization);
+
+ return false;
+ }
+
+ void opencl_deinit()
+ {
+ }
+
+ bool opencl_is_available()
+ {
+ return false;
+ }
+
+ opencl_context_ptr opencl_create_context()
+ {
+ return nullptr;
+ }
+
+ void opencl_destroy_context(opencl_context_ptr context)
+ {
+ BASISU_NOTE_UNUSED(context);
+ }
+
+ bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(total_blocks);
+ BASISU_NOTE_UNUSED(pPixel_blocks);
+
+ return false;
+ }
+
+ bool opencl_encode_etc1s_blocks(opencl_context_ptr pContext, etc_block* pOutput_blocks, bool perceptual, uint32_t total_perms)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(pOutput_blocks);
+ BASISU_NOTE_UNUSED(perceptual);
+ BASISU_NOTE_UNUSED(total_perms);
+
+ return false;
+ }
+
+ bool opencl_encode_etc1s_pixel_clusters(
+ opencl_context_ptr pContext,
+ etc_block* pOutput_blocks,
+ uint32_t total_clusters,
+ const cl_pixel_cluster* pClusters,
+ uint64_t total_pixels,
+ const color_rgba* pPixels, const uint32_t *pPixel_weights,
+ bool perceptual, uint32_t total_perms)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(pOutput_blocks);
+ BASISU_NOTE_UNUSED(total_clusters);
+ BASISU_NOTE_UNUSED(pClusters);
+ BASISU_NOTE_UNUSED(total_pixels);
+ BASISU_NOTE_UNUSED(pPixels);
+ BASISU_NOTE_UNUSED(pPixel_weights);
+ BASISU_NOTE_UNUSED(perceptual);
+ BASISU_NOTE_UNUSED(total_perms);
+
+ return false;
+ }
+
+ bool opencl_refine_endpoint_clusterization(
+ opencl_context_ptr pContext,
+ const cl_block_info_struct* pPixel_block_info,
+ uint32_t total_clusters,
+ const cl_endpoint_cluster_struct* pCluster_info,
+ const uint32_t* pSorted_block_indices,
+ uint32_t* pOutput_cluster_indices,
+ bool perceptual)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(pPixel_block_info);
+ BASISU_NOTE_UNUSED(total_clusters);
+ BASISU_NOTE_UNUSED(pCluster_info);
+ BASISU_NOTE_UNUSED(pSorted_block_indices);
+ BASISU_NOTE_UNUSED(pOutput_cluster_indices);
+ BASISU_NOTE_UNUSED(perceptual);
+
+ return false;
+ }
+
+ bool opencl_find_optimal_selector_clusters_for_each_block(
+ opencl_context_ptr pContext,
+ const fosc_block_struct* pInput_block_info, // one per block
+ uint32_t total_input_selectors,
+ const fosc_selector_struct* pInput_selectors,
+ const uint32_t* pSelector_cluster_indices,
+ uint32_t* pOutput_selector_cluster_indices, // one per block
+ bool perceptual)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(pInput_block_info);
+ BASISU_NOTE_UNUSED(total_input_selectors);
+ BASISU_NOTE_UNUSED(pInput_selectors);
+ BASISU_NOTE_UNUSED(pSelector_cluster_indices);
+ BASISU_NOTE_UNUSED(pOutput_selector_cluster_indices);
+ BASISU_NOTE_UNUSED(perceptual);
+
+ return false;
+ }
+
+ bool opencl_determine_selectors(
+ opencl_context_ptr pContext,
+ const color_rgba* pInput_etc_color5_and_inten,
+ etc_block* pOutput_blocks,
+ bool perceptual)
+ {
+ BASISU_NOTE_UNUSED(pContext);
+ BASISU_NOTE_UNUSED(pInput_etc_color5_and_inten);
+ BASISU_NOTE_UNUSED(pOutput_blocks);
+ BASISU_NOTE_UNUSED(perceptual);
+
+ return false;
+ }
+
+#endif // BASISU_SUPPORT_OPENCL
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_opencl.h b/thirdparty/basis_universal/encoder/basisu_opencl.h
new file mode 100644
index 0000000000..4194a08418
--- /dev/null
+++ b/thirdparty/basis_universal/encoder/basisu_opencl.h
@@ -0,0 +1,143 @@
+// basisu_opencl.h
+// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
+//
+// Note: Undefine or set BASISU_SUPPORT_OPENCL to 0 to completely OpenCL support.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#pragma once
+#include "../transcoder/basisu.h"
+#include "basisu_enc.h"
+#include "basisu_etc.h"
+
+namespace basisu
+{
+ bool opencl_init(bool force_serialization);
+ void opencl_deinit();
+ bool opencl_is_available();
+
+ struct opencl_context;
+
+ // Each thread calling OpenCL should have its own opencl_context_ptr. This corresponds to a OpenCL command queue. (Confusingly, we only use a single OpenCL device "context".)
+ typedef opencl_context* opencl_context_ptr;
+
+ opencl_context_ptr opencl_create_context();
+ void opencl_destroy_context(opencl_context_ptr context);
+
+#pragma pack(push, 1)
+ struct cl_pixel_block
+ {
+ color_rgba m_pixels[16]; // [y*4+x]
+ };
+#pragma pack(pop)
+
+ // Must match BASISU_ETC1_CLUSTER_FIT_ORDER_TABLE_SIZE
+ const uint32_t OPENCL_ENCODE_ETC1S_MAX_PERMS = 165;
+
+ bool opencl_set_pixel_blocks(opencl_context_ptr pContext, uint32_t total_blocks, const cl_pixel_block* pPixel_blocks);
+
+ bool opencl_encode_etc1s_blocks(opencl_context_ptr pContext, etc_block* pOutput_blocks, bool perceptual, uint32_t total_perms);
+
+ // opencl_encode_etc1s_pixel_clusters
+
+#pragma pack(push, 1)
+ struct cl_pixel_cluster
+ {
+ uint64_t m_total_pixels;
+ uint64_t m_first_pixel_index;
+ };
+#pragma pack(pop)
+
+ bool opencl_encode_etc1s_pixel_clusters(
+ opencl_context_ptr pContext,
+ etc_block* pOutput_blocks,
+ uint32_t total_clusters,
+ const cl_pixel_cluster *pClusters,
+ uint64_t total_pixels,
+ const color_rgba *pPixels,
+ const uint32_t *pPixel_weights,
+ bool perceptual, uint32_t total_perms);
+
+ // opencl_refine_endpoint_clusterization
+
+#pragma pack(push, 1)
+ struct cl_block_info_struct
+ {
+ uint16_t m_first_cluster_ofs;
+ uint16_t m_num_clusters;
+ uint16_t m_cur_cluster_index;
+ uint8_t m_cur_cluster_etc_inten;
+ };
+
+ struct cl_endpoint_cluster_struct
+ {
+ color_rgba m_unscaled_color;
+ uint8_t m_etc_inten;
+ uint16_t m_cluster_index;
+ };
+#pragma pack(pop)
+
+ bool opencl_refine_endpoint_clusterization(
+ opencl_context_ptr pContext,
+ const cl_block_info_struct *pPixel_block_info,
+ uint32_t total_clusters,
+ const cl_endpoint_cluster_struct *pCluster_info,
+ const uint32_t *pSorted_block_indices,
+ uint32_t* pOutput_cluster_indices,
+ bool perceptual);
+
+ // opencl_find_optimal_selector_clusters_for_each_block
+
+#pragma pack(push, 1)
+ struct fosc_selector_struct
+ {
+ uint32_t m_packed_selectors; // 4x4 grid of 2-bit selectors
+ };
+
+ struct fosc_block_struct
+ {
+ color_rgba m_etc_color5_inten; // unscaled 5-bit block color in RGB, alpha has block's intensity index
+ uint32_t m_first_selector; // offset into selector table
+ uint32_t m_num_selectors; // number of selectors to check
+ };
+
+ struct fosc_param_struct
+ {
+ uint32_t m_total_blocks;
+ int m_perceptual;
+ };
+#pragma pack(pop)
+
+ bool opencl_find_optimal_selector_clusters_for_each_block(
+ opencl_context_ptr pContext,
+ const fosc_block_struct* pInput_block_info, // one per block
+ uint32_t total_input_selectors,
+ const fosc_selector_struct* pInput_selectors,
+ const uint32_t* pSelector_cluster_indices,
+ uint32_t* pOutput_selector_cluster_indices, // one per block
+ bool perceptual);
+
+#pragma pack(push, 1)
+ struct ds_param_struct
+ {
+ uint32_t m_total_blocks;
+ int m_perceptual;
+ };
+#pragma pack(pop)
+
+ bool opencl_determine_selectors(
+ opencl_context_ptr pContext,
+ const color_rgba* pInput_etc_color5_and_inten,
+ etc_block* pOutput_blocks,
+ bool perceptual);
+
+} // namespace basisu
diff --git a/thirdparty/basis_universal/encoder/basisu_uastc_enc.cpp b/thirdparty/basis_universal/encoder/basisu_uastc_enc.cpp
index ca2b325693..271bbc6f1d 100644
--- a/thirdparty/basis_universal/encoder/basisu_uastc_enc.cpp
+++ b/thirdparty/basis_universal/encoder/basisu_uastc_enc.cpp
@@ -13,7 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "basisu_uastc_enc.h"
+
+#if BASISU_USE_ASTC_DECOMPRESS
#include "basisu_astc_decomp.h"
+#endif
+
#include "basisu_gpu_texture.h"
#include "basisu_bc7enc.h"
@@ -509,14 +513,14 @@ namespace basisu
if (pForce_selectors == nullptr)
{
- int s0 = g_astc_unquant[endpoint_range][astc_results.m_endpoints[0]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[2]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[4]].m_unquant;
- int s1 = g_astc_unquant[endpoint_range][astc_results.m_endpoints[1]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[3]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[5]].m_unquant;
- if (s1 < s0)
- {
- std::swap(astc_results.m_endpoints[0], astc_results.m_endpoints[1]);
- std::swap(astc_results.m_endpoints[2], astc_results.m_endpoints[3]);
- std::swap(astc_results.m_endpoints[4], astc_results.m_endpoints[5]);
- invert = true;
+ int s0 = g_astc_unquant[endpoint_range][astc_results.m_endpoints[0]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[2]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[4]].m_unquant;
+ int s1 = g_astc_unquant[endpoint_range][astc_results.m_endpoints[1]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[3]].m_unquant + g_astc_unquant[endpoint_range][astc_results.m_endpoints[5]].m_unquant;
+ if (s1 < s0)
+ {
+ std::swap(astc_results.m_endpoints[0], astc_results.m_endpoints[1]);
+ std::swap(astc_results.m_endpoints[2], astc_results.m_endpoints[3]);
+ std::swap(astc_results.m_endpoints[4], astc_results.m_endpoints[5]);
+ invert = true;
}
}
@@ -3562,7 +3566,8 @@ namespace basisu
basist::color32 temp_block_unpacked[4][4];
success = basist::unpack_uastc(temp_block, (basist::color32 *)temp_block_unpacked, false);
VALIDATE(success);
-
+
+#if BASISU_USE_ASTC_DECOMPRESS
// Now round trip to packed ASTC and back, then decode to pixels.
uint32_t astc_data[4];
@@ -3590,6 +3595,7 @@ namespace basisu
VALIDATE(temp_block_unpacked[y][x].c[3] == decoded_uastc_block[y][x].a);
}
}
+#endif
}
#endif
diff --git a/thirdparty/basis_universal/encoder/cppspmd_sse.h b/thirdparty/basis_universal/encoder/cppspmd_sse.h
index 9a97eeb695..4c61bab7b1 100644
--- a/thirdparty/basis_universal/encoder/cppspmd_sse.h
+++ b/thirdparty/basis_universal/encoder/cppspmd_sse.h
@@ -1,13 +1,5 @@
// cppspmd_sse.h
-// Note for Basis Universal: All of the "cppspmd" code and headers are OPTIONAL to Basis Universal. if BASISU_SUPPORT_SSE is 0, it will never be included and does not impact compilation.
-// SSE 2 or 4.1
-// Originally written by Nicolas Guillemot, Jefferson Amstutz in the "CppSPMD" project.
-// 4/20: Richard Geldreich: Macro control flow, more SIMD instruction sets, optimizations, supports using multiple SIMD instruction sets in same executable. Still a work in progress!
-//
-// Originally Copyright 2016 Nicolas Guillemot
-// Changed from the MIT license to Apache 2.0 with permission from the author.
-//
-// Modifications/enhancements Copyright 2020-2021 Binomial LLC
+// Copyright 2020-2022 Binomial LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -20,6 +12,11 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
+//
+// Notes for Basis Universal:
+// All of the "cppspmd" code and headers are OPTIONAL to Basis Universal. if BASISU_SUPPORT_SSE is 0, it will never be included and does not impact compilation.
+// The techniques used in this code were originally demonstrated for AVX2 by Nicolas Guillemot, Jefferson Amstutz in their "CppSPMD" project.
+// This is new code for use in Basis Universal, although it uses the same general SPMD techniques in SSE 2/4.
#include <stdlib.h>
#include <stdint.h>
@@ -1330,7 +1327,7 @@ struct spmd_kernel
__m128 temp = _mm_add_ps(_mm_shuffle_ps(k3210, k3210, _MM_SHUFFLE(0, 1, 2, 3)), k3210);
return _mm_cvtss_f32(_mm_add_ss(_mm_movehl_ps(temp, temp), temp));
}
-
+
CPPSPMD_FORCE_INLINE int reduce_add(vint v)
{
__m128i k3210 = blendv_mask_epi32(_mm_setzero_si128(), v.m_value, m_exec.m_mask);
@@ -1668,14 +1665,16 @@ CPPSPMD_FORCE_INLINE vint uniform_shift_right_epi16(const vint& a, const vint& b
CPPSPMD_FORCE_INLINE vint undefined_vint() { return vint{ _mm_undefined_si128() }; }
CPPSPMD_FORCE_INLINE vfloat undefined_vfloat() { return vfloat{ _mm_undefined_ps() }; }
+CPPSPMD_FORCE_INLINE vint zero_vint() { return vint{ _mm_setzero_si128() }; }
+CPPSPMD_FORCE_INLINE vfloat zero_vfloat() { return vfloat{ _mm_setzero_ps() }; }
+
CPPSPMD_FORCE_INLINE vint vint_lane_set(int v0, int v1, int v2, int v3) { return vint{ _mm_set_epi32(v3, v2, v1, v0) }; }
CPPSPMD_FORCE_INLINE vfloat vfloat_lane_set(float v0, float v1, float v2, float v3) { return vfloat{ _mm_set_ps(v3, v2, v1, v0) }; }
-
CPPSPMD_FORCE_INLINE vint vint_lane_set_r(int v3, int v2, int v1, int v0) { return vint{ _mm_set_epi32(v3, v2, v1, v0) }; }
CPPSPMD_FORCE_INLINE vfloat vfloat_lane_set_r(float v3, float v2, float v1, float v0) { return vfloat{ _mm_set_ps(v3, v2, v1, v0) }; }
-
// control is an 8-bit immediate value containing 4 2-bit indices which shuffles the int32's in each 128-bit lane.
#define VINT_LANE_SHUFFLE_EPI32(a, control) vint(_mm_shuffle_epi32((a).m_value, control))
+#define VFLOAT_LANE_SHUFFLE_PS(a, b, control) vfloat(_mm_shuffle_ps((a).m_value, (b).m_value, control))
// control is an 8-bit immediate value containing 4 2-bit indices which shuffles the int16's in either the high or low 64-bit lane.
#define VINT_LANE_SHUFFLELO_EPI16(a, control) vint(_mm_shufflelo_epi16((a).m_value, control))
diff --git a/thirdparty/basis_universal/encoder/jpgd.cpp b/thirdparty/basis_universal/encoder/jpgd.cpp
index 460834409d..fec8b71439 100644
--- a/thirdparty/basis_universal/encoder/jpgd.cpp
+++ b/thirdparty/basis_universal/encoder/jpgd.cpp
@@ -23,17 +23,6 @@
// v1.04, May. 19, 2012: Code tweaks to fix VS2008 static code analysis warnings
// v2.00, March 20, 2020: Fuzzed with zzuf and afl. Fixed several issues, converted most assert()'s to run-time checks. Added chroma upsampling. Removed freq. domain upsampling. gcc/clang warnings.
//
-#ifdef _MSC_VER
-#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
-#if defined(_DEBUG) || defined(DEBUG)
-#define _ITERATOR_DEBUG_LEVEL 1
-#define _SECURE_SCL 1
-#else
-#define _SECURE_SCL 0
-#define _ITERATOR_DEBUG_LEVEL 0
-#endif
-#endif
-#endif
#include "jpgd.h"
#include <string.h>
@@ -2085,7 +2074,7 @@ namespace jpgd {
if (setjmp(m_jmp_state))
return JPGD_FAILED;
- const bool chroma_y_filtering = (m_flags & cFlagLinearChromaFiltering) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
+ const bool chroma_y_filtering = (m_flags & cFlagLinearChromaFiltering) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2)) && (m_image_x_size >= 2) && (m_image_y_size >= 2);
if (chroma_y_filtering)
{
std::swap(m_pSample_buf, m_pSample_buf_prev);
@@ -2114,7 +2103,7 @@ namespace jpgd {
if (m_total_lines_left == 0)
return JPGD_DONE;
- const bool chroma_y_filtering = (m_flags & cFlagLinearChromaFiltering) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2));
+ const bool chroma_y_filtering = (m_flags & cFlagLinearChromaFiltering) && ((m_scan_type == JPGD_YH2V2) || (m_scan_type == JPGD_YH1V2)) && (m_image_x_size >= 2) && (m_image_y_size >= 2);
bool get_another_mcu_row = false;
bool got_mcu_early = false;
@@ -2144,7 +2133,7 @@ namespace jpgd {
{
case JPGD_YH2V2:
{
- if (m_flags & cFlagLinearChromaFiltering)
+ if ((m_flags & cFlagLinearChromaFiltering) && (m_image_x_size >= 2) && (m_image_y_size >= 2))
{
if (m_num_buffered_scanlines == 1)
{
@@ -2173,7 +2162,7 @@ namespace jpgd {
}
case JPGD_YH2V1:
{
- if (m_flags & cFlagLinearChromaFiltering)
+ if ((m_flags & cFlagLinearChromaFiltering) && (m_image_x_size >= 2) && (m_image_y_size >= 2))
H2V1ConvertFiltered();
else
H2V1Convert();
diff --git a/thirdparty/basis_universal/encoder/lodepng.cpp b/thirdparty/basis_universal/encoder/lodepng.cpp
deleted file mode 100644
index 63adcf49b6..0000000000
--- a/thirdparty/basis_universal/encoder/lodepng.cpp
+++ /dev/null
@@ -1,6008 +0,0 @@
-/*
-LodePNG version 20190210
-
-Copyright (c) 2005-2019 Lode Vandevenne
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any source
- distribution.
-*/
-
-/*
-The manual and changelog are in the header file "lodepng.h"
-Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C.
-*/
-
-#ifdef _MSC_VER
-#define _CRT_SECURE_NO_DEPRECATE
-#pragma warning (disable : 4201)
-
-#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
-#if defined(_DEBUG) || defined(DEBUG)
-#define _ITERATOR_DEBUG_LEVEL 1
-#define _SECURE_SCL 1
-#else
-#define _SECURE_SCL 0
-#define _ITERATOR_DEBUG_LEVEL 0
-#endif
-#endif
-#endif
-
-#include "lodepng.h"
-
-#include <limits.h> /* LONG_MAX */
-#include <stdio.h> /* file handling */
-#include <stdlib.h> /* allocations */
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/
-#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/
-#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/
-#endif /*_MSC_VER */
-
-const char* LODEPNG_VERSION_STRING = "20190210";
-
-/*
-This source file is built up in the following large parts. The code sections
-with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way.
--Tools for C and common code for PNG and Zlib
--C Code for Zlib (huffman, deflate, ...)
--C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...)
--The C++ wrapper around all of the above
-*/
-
-/*The malloc, realloc and free functions defined here with "lodepng_" in front
-of the name, so that you can easily change them to others related to your
-platform if needed. Everything else in the code calls these. Pass
--DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out
-#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and
-define them in your own project's source files without needing to change
-lodepng source code. Don't forget to remove "static" if you copypaste them
-from here.*/
-
-#ifdef LODEPNG_COMPILE_ALLOCATORS
-static void* lodepng_malloc(size_t size) {
-#ifdef LODEPNG_MAX_ALLOC
- if(size > LODEPNG_MAX_ALLOC) return 0;
-#endif
- return malloc(size);
-}
-
-static void* lodepng_realloc(void* ptr, size_t new_size) {
-#ifdef LODEPNG_MAX_ALLOC
- if(new_size > LODEPNG_MAX_ALLOC) return 0;
-#endif
- return realloc(ptr, new_size);
-}
-
-static void lodepng_free(void* ptr) {
- free(ptr);
-}
-#else /*LODEPNG_COMPILE_ALLOCATORS*/
-void* lodepng_malloc(size_t size);
-void* lodepng_realloc(void* ptr, size_t new_size);
-void lodepng_free(void* ptr);
-#endif /*LODEPNG_COMPILE_ALLOCATORS*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* // Tools for C, and common code for PNG and Zlib. // */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b))
-#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b))
-
-/*
-Often in case of an error a value is assigned to a variable and then it breaks
-out of a loop (to go to the cleanup phase of a function). This macro does that.
-It makes the error handling code shorter and more readable.
-
-Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83);
-*/
-#define CERROR_BREAK(errorvar, code){\
- errorvar = code;\
- break;\
-}
-
-/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/
-#define ERROR_BREAK(code) CERROR_BREAK(error, code)
-
-/*Set error var to the error code, and return it.*/
-#define CERROR_RETURN_ERROR(errorvar, code){\
- errorvar = code;\
- return code;\
-}
-
-/*Try the code, if it returns error, also return the error.*/
-#define CERROR_TRY_RETURN(call){\
- unsigned error = call;\
- if(error) return error;\
-}
-
-/*Set error var to the error code, and return from the void function.*/
-#define CERROR_RETURN(errorvar, code){\
- errorvar = code;\
- return;\
-}
-
-/*
-About uivector, ucvector and string:
--All of them wrap dynamic arrays or text strings in a similar way.
--LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version.
--The string tools are made to avoid problems with compilers that declare things like strncat as deprecated.
--They're not used in the interface, only internally in this file as static functions.
--As with many other structs in this file, the init and cleanup functions serve as ctor and dtor.
-*/
-
-#ifdef LODEPNG_COMPILE_ZLIB
-/*dynamic vector of unsigned ints*/
-typedef struct uivector {
- unsigned* data;
- size_t size; /*size in number of unsigned longs*/
- size_t allocsize; /*allocated size in bytes*/
-} uivector;
-
-static void uivector_cleanup(void* p) {
- ((uivector*)p)->size = ((uivector*)p)->allocsize = 0;
- lodepng_free(((uivector*)p)->data);
- ((uivector*)p)->data = NULL;
-}
-
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned uivector_reserve(uivector* p, size_t allocsize) {
- if(allocsize > p->allocsize) {
- size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
- void* data = lodepng_realloc(p->data, newsize);
- if(data) {
- p->allocsize = newsize;
- p->data = (unsigned*)data;
- }
- else return 0; /*error: not enough memory*/
- }
- return 1;
-}
-
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned uivector_resize(uivector* p, size_t size) {
- if(!uivector_reserve(p, size * sizeof(unsigned))) return 0;
- p->size = size;
- return 1; /*success*/
-}
-
-/*resize and give all new elements the value*/
-static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) {
- size_t oldsize = p->size, i;
- if(!uivector_resize(p, size)) return 0;
- for(i = oldsize; i < size; ++i) p->data[i] = value;
- return 1;
-}
-
-static void uivector_init(uivector* p) {
- p->data = NULL;
- p->size = p->allocsize = 0;
-}
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned uivector_push_back(uivector* p, unsigned c) {
- if(!uivector_resize(p, p->size + 1)) return 0;
- if (!p->data) return 0;
- p->data[p->size - 1] = c;
- return 1;
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-#endif /*LODEPNG_COMPILE_ZLIB*/
-
-/* /////////////////////////////////////////////////////////////////////////// */
-
-/*dynamic vector of unsigned chars*/
-typedef struct ucvector {
- unsigned char* data;
- size_t size; /*used size*/
- size_t allocsize; /*allocated size*/
-} ucvector;
-
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned ucvector_reserve(ucvector* p, size_t allocsize) {
- if(allocsize > p->allocsize) {
- size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2);
- void* data = lodepng_realloc(p->data, newsize);
- if(data) {
- p->allocsize = newsize;
- p->data = (unsigned char*)data;
- }
- else return 0; /*error: not enough memory*/
- }
- return 1;
-}
-
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned ucvector_resize(ucvector* p, size_t size) {
- if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0;
- p->size = size;
- return 1; /*success*/
-}
-
-#ifdef LODEPNG_COMPILE_PNG
-
-static void ucvector_cleanup(void* p) {
- ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0;
- lodepng_free(((ucvector*)p)->data);
- ((ucvector*)p)->data = NULL;
-}
-
-static void ucvector_init(ucvector* p) {
- p->data = NULL;
- p->size = p->allocsize = 0;
-}
-#endif /*LODEPNG_COMPILE_PNG*/
-
-#ifdef LODEPNG_COMPILE_ZLIB
-/*you can both convert from vector to buffer&size and vica versa. If you use
-init_buffer to take over a buffer and size, it is not needed to use cleanup*/
-static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) {
- p->data = buffer;
- p->allocsize = p->size = size;
-}
-#endif /*LODEPNG_COMPILE_ZLIB*/
-
-#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER)
-/*returns 1 if success, 0 if failure ==> nothing done*/
-static unsigned ucvector_push_back(ucvector* p, unsigned char c) {
- if(!ucvector_resize(p, p->size + 1)) return 0;
- p->data[p->size - 1] = c;
- return 1;
-}
-#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
-
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_PNG
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-
-/*free string pointer and set it to NULL*/
-static void string_cleanup(char** out) {
- lodepng_free(*out);
- *out = NULL;
-}
-
-/* dynamically allocates a new string with a copy of the null terminated input text */
-static char* alloc_string(const char* in) {
- size_t insize = strlen(in);
- char* out = (char*)lodepng_malloc(insize + 1);
- if(out) {
- size_t i;
- for(i = 0; i != insize; ++i) {
- out[i] = in[i];
- }
- out[i] = 0;
- }
- return out;
-}
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-#endif /*LODEPNG_COMPILE_PNG*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-unsigned lodepng_read32bitInt(const unsigned char* buffer) {
- return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]);
-}
-
-#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)
-/*buffer must have at least 4 allocated bytes available*/
-static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) {
- buffer[0] = (unsigned char)((value >> 24) & 0xff);
- buffer[1] = (unsigned char)((value >> 16) & 0xff);
- buffer[2] = (unsigned char)((value >> 8) & 0xff);
- buffer[3] = (unsigned char)((value ) & 0xff);
-}
-#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-static void lodepng_add32bitInt(ucvector* buffer, unsigned value) {
- ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/
- lodepng_set32bitInt(&buffer->data[buffer->size - 4], value);
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / File IO / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_DISK
-
-/* returns negative value on error. This should be pure C compatible, so no fstat. */
-static long lodepng_filesize(const char* filename) {
- FILE* file;
- long size;
- file = fopen(filename, "rb");
- if(!file) return -1;
-
- if(fseek(file, 0, SEEK_END) != 0) {
- fclose(file);
- return -1;
- }
-
- size = ftell(file);
- /* It may give LONG_MAX as directory size, this is invalid for us. */
- if(size == LONG_MAX) size = -1;
-
- fclose(file);
- return size;
-}
-
-/* load file into buffer that already has the correct allocated size. Returns error code.*/
-static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) {
- FILE* file;
- size_t readsize;
- file = fopen(filename, "rb");
- if(!file) return 78;
-
- readsize = fread(out, 1, size, file);
- fclose(file);
-
- if (readsize != size) return 78;
- return 0;
-}
-
-unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
- long size = lodepng_filesize(filename);
- if (size < 0) return 78;
- *outsize = (size_t)size;
-
- *out = (unsigned char*)lodepng_malloc((size_t)size);
- if(!(*out) && size > 0) return 83; /*the above malloc failed*/
-
- return lodepng_buffer_file(*out, (size_t)size, filename);
-}
-
-/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
-unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
- FILE* file;
- file = fopen(filename, "wb" );
- if(!file) return 79;
- fwrite(buffer, 1, buffersize, file);
- fclose(file);
- return 0;
-}
-
-#endif /*LODEPNG_COMPILE_DISK*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* // End of common code and tools. Begin of Zlib related code. // */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_ZLIB
-#ifdef LODEPNG_COMPILE_ENCODER
-/*TODO: this ignores potential out of memory errors*/
-#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit){\
- /*add a new byte at the end*/\
- if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\
- /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\
- (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\
- ++(*bitpointer);\
-}
-
-static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) {
- size_t i;
- for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1));
-}
-
-static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) {
- size_t i;
- for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1));
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1)
-
-static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) {
- unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream));
- ++(*bitpointer);
- return result;
-}
-
-static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) {
- unsigned result = 0, i;
- for(i = 0; i != nbits; ++i) {
- result += ((unsigned)READBIT(*bitpointer, bitstream)) << i;
- ++(*bitpointer);
- }
- return result;
-}
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Deflate - Huffman / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#define FIRST_LENGTH_CODE_INDEX 257
-#define LAST_LENGTH_CODE_INDEX 285
-/*256 literals, the end code, some length codes, and 2 unused codes*/
-#define NUM_DEFLATE_CODE_SYMBOLS 288
-/*the distance codes have their own symbols, 30 used, 2 unused*/
-#define NUM_DISTANCE_SYMBOLS 32
-/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/
-#define NUM_CODE_LENGTH_CODES 19
-
-/*the base lengths represented by codes 257-285*/
-static const unsigned LENGTHBASE[29]
- = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59,
- 67, 83, 99, 115, 131, 163, 195, 227, 258};
-
-/*the extra bits used by codes 257-285 (added to base length)*/
-static const unsigned LENGTHEXTRA[29]
- = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 5, 5, 5, 5, 0};
-
-/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/
-static const unsigned DISTANCEBASE[30]
- = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513,
- 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577};
-
-/*the extra bits of backwards distances (added to base)*/
-static const unsigned DISTANCEEXTRA[30]
- = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
- 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13};
-
-/*the order in which "code length alphabet code lengths" are stored, out of this
-the huffman tree of the dynamic huffman tree lengths is generated*/
-static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES]
- = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*
-Huffman tree struct, containing multiple representations of the tree
-*/
-typedef struct HuffmanTree {
- unsigned* tree2d;
- unsigned* tree1d;
- unsigned* lengths; /*the lengths of the codes of the 1d-tree*/
- unsigned maxbitlen; /*maximum number of bits a single code can get*/
- unsigned numcodes; /*number of symbols in the alphabet = number of codes*/
-} HuffmanTree;
-
-/*function used for debug purposes to draw the tree in ascii art with C++*/
-/*
-static void HuffmanTree_draw(HuffmanTree* tree) {
- std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl;
- for(size_t i = 0; i != tree->tree1d.size; ++i) {
- if(tree->lengths.data[i])
- std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl;
- }
- std::cout << std::endl;
-}*/
-
-static void HuffmanTree_init(HuffmanTree* tree) {
- tree->tree2d = 0;
- tree->tree1d = 0;
- tree->lengths = 0;
-}
-
-static void HuffmanTree_cleanup(HuffmanTree* tree) {
- lodepng_free(tree->tree2d);
- lodepng_free(tree->tree1d);
- lodepng_free(tree->lengths);
-}
-
-/*the tree representation used by the decoder. return value is error*/
-static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) {
- unsigned nodefilled = 0; /*up to which node it is filled*/
- unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/
- unsigned n, i;
-
- tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned));
- if(!tree->tree2d) return 83; /*alloc fail*/
-
- /*
- convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means
- uninited, a value >= numcodes is an address to another bit, a value < numcodes
- is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as
- many columns as codes - 1.
- A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes.
- Here, the internal nodes are stored (what their 0 and 1 option point to).
- There is only memory for such good tree currently, if there are more nodes
- (due to too long length codes), error 55 will happen
- */
- for(n = 0; n < tree->numcodes * 2; ++n) {
- tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/
- }
-
- for(n = 0; n < tree->numcodes; ++n) /*the codes*/ {
- for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ {
- unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1);
- /*oversubscribed, see comment in lodepng_error_text*/
- if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55;
- if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ {
- if(i + 1 == tree->lengths[n]) /*last bit*/ {
- tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/
- treepos = 0;
- } else {
- /*put address of the next step in here, first that address has to be found of course
- (it's just nodefilled + 1)...*/
- ++nodefilled;
- /*addresses encoded with numcodes added to it*/
- tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes;
- treepos = nodefilled;
- }
- }
- else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes;
- }
- }
-
- for(n = 0; n < tree->numcodes * 2; ++n) {
- if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/
- }
-
- return 0;
-}
-
-/*
-Second step for the ...makeFromLengths and ...makeFromFrequencies functions.
-numcodes, lengths and maxbitlen must already be filled in correctly. return
-value is error.
-*/
-static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) {
- uivector blcount;
- uivector nextcode;
- unsigned error = 0;
- unsigned bits, n;
-
- uivector_init(&blcount);
- uivector_init(&nextcode);
-
- tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned));
- if(!tree->tree1d) error = 83; /*alloc fail*/
-
- if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0)
- || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0))
- error = 83; /*alloc fail*/
-
- if(!error) {
- /*step 1: count number of instances of each code length*/
- for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]];
- /*step 2: generate the nextcode values*/
- for(bits = 1; bits <= tree->maxbitlen; ++bits) {
- nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1;
- }
- /*step 3: generate all the codes*/
- for(n = 0; n != tree->numcodes; ++n) {
- if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++;
- }
- }
-
- uivector_cleanup(&blcount);
- uivector_cleanup(&nextcode);
-
- if(!error) return HuffmanTree_make2DTree(tree);
- else return error;
-}
-
-/*
-given the code lengths (as stored in the PNG file), generate the tree as defined
-by Deflate. maxbitlen is the maximum bits that a code in the tree can have.
-return value is error.
-*/
-static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen,
- size_t numcodes, unsigned maxbitlen) {
- unsigned i;
- tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned));
- if(!tree->lengths) return 83; /*alloc fail*/
- for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i];
- tree->numcodes = (unsigned)numcodes; /*number of symbols*/
- tree->maxbitlen = maxbitlen;
- return HuffmanTree_makeFromLengths2(tree);
-}
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding",
-Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/
-
-/*chain node for boundary package merge*/
-typedef struct BPMNode {
- int weight; /*the sum of all weights in this chain*/
- unsigned index; /*index of this leaf node (called "count" in the paper)*/
- struct BPMNode* tail; /*the next nodes in this chain (null if last)*/
- int in_use;
-} BPMNode;
-
-/*lists of chains*/
-typedef struct BPMLists {
- /*memory pool*/
- unsigned memsize;
- BPMNode* memory;
- unsigned numfree;
- unsigned nextfree;
- BPMNode** freelist;
- /*two heads of lookahead chains per list*/
- unsigned listsize;
- BPMNode** chains0;
- BPMNode** chains1;
-} BPMLists;
-
-/*creates a new chain node with the given parameters, from the memory in the lists */
-static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) {
- unsigned i;
- BPMNode* result;
-
- /*memory full, so garbage collect*/
- if(lists->nextfree >= lists->numfree) {
- /*mark only those that are in use*/
- for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0;
- for(i = 0; i != lists->listsize; ++i) {
- BPMNode* node;
- for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1;
- for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1;
- }
- /*collect those that are free*/
- lists->numfree = 0;
- for(i = 0; i != lists->memsize; ++i) {
- if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i];
- }
- lists->nextfree = 0;
- }
-
- result = lists->freelist[lists->nextfree++];
- result->weight = weight;
- result->index = index;
- result->tail = tail;
- return result;
-}
-
-/*sort the leaves with stable mergesort*/
-static void bpmnode_sort(BPMNode* leaves, size_t num) {
- BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num);
- size_t width, counter = 0;
- for(width = 1; width < num; width *= 2) {
- BPMNode* a = (counter & 1) ? mem : leaves;
- BPMNode* b = (counter & 1) ? leaves : mem;
- size_t p;
- for(p = 0; p < num; p += 2 * width) {
- size_t q = (p + width > num) ? num : (p + width);
- size_t r = (p + 2 * width > num) ? num : (p + 2 * width);
- size_t i = p, j = q, k;
- for(k = p; k < r; k++) {
- if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++];
- else b[k] = a[j++];
- }
- }
- counter++;
- }
- if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num);
- lodepng_free(mem);
-}
-
-/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/
-static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) {
- unsigned lastindex = lists->chains1[c]->index;
-
- if(c == 0) {
- if(lastindex >= numpresent) return;
- lists->chains0[c] = lists->chains1[c];
- lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0);
- } else {
- /*sum of the weights of the head nodes of the previous lookahead chains.*/
- int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight;
- lists->chains0[c] = lists->chains1[c];
- if(lastindex < numpresent && sum > leaves[lastindex].weight) {
- lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail);
- return;
- }
- lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]);
- /*in the end we are only interested in the chain of the last list, so no
- need to recurse if we're at the last one (this gives measurable speedup)*/
- if(num + 1 < (int)(2 * numpresent - 2)) {
- boundaryPM(lists, leaves, numpresent, c - 1, num);
- boundaryPM(lists, leaves, numpresent, c - 1, num);
- }
- }
-}
-
-unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
- size_t numcodes, unsigned maxbitlen) {
- unsigned error = 0;
- unsigned i;
- size_t numpresent = 0; /*number of symbols with non-zero frequency*/
- BPMNode* leaves; /*the symbols, only those with > 0 frequency*/
-
- if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/
- if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/
-
- leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves));
- if(!leaves) return 83; /*alloc fail*/
-
- for(i = 0; i != numcodes; ++i) {
- if(frequencies[i] > 0) {
- leaves[numpresent].weight = (int)frequencies[i];
- leaves[numpresent].index = i;
- ++numpresent;
- }
- }
-
- for(i = 0; i != numcodes; ++i) lengths[i] = 0;
-
- /*ensure at least two present symbols. There should be at least one symbol
- according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To
- make these work as well ensure there are at least two symbols. The
- Package-Merge code below also doesn't work correctly if there's only one
- symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/
- if(numpresent == 0) {
- lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/
- } else if(numpresent == 1) {
- lengths[leaves[0].index] = 1;
- lengths[leaves[0].index == 0 ? 1 : 0] = 1;
- } else {
- BPMLists lists;
- BPMNode* node;
-
- bpmnode_sort(leaves, numpresent);
-
- lists.listsize = maxbitlen;
- lists.memsize = 2 * maxbitlen * (maxbitlen + 1);
- lists.nextfree = 0;
- lists.numfree = lists.memsize;
- lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory));
- lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*));
- lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
- lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*));
- if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/
-
- if(!error) {
- for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i];
-
- bpmnode_create(&lists, leaves[0].weight, 1, 0);
- bpmnode_create(&lists, leaves[1].weight, 2, 0);
-
- for(i = 0; i != lists.listsize; ++i) {
- lists.chains0[i] = &lists.memory[0];
- lists.chains1[i] = &lists.memory[1];
- }
-
- /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/
- for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i);
-
- for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) {
- for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index];
- }
- }
-
- lodepng_free(lists.memory);
- lodepng_free(lists.freelist);
- lodepng_free(lists.chains0);
- lodepng_free(lists.chains1);
- }
-
- lodepng_free(leaves);
- return error;
-}
-
-/*Create the Huffman tree given the symbol frequencies*/
-static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies,
- size_t mincodes, size_t numcodes, unsigned maxbitlen) {
- unsigned error = 0;
- while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/
- tree->maxbitlen = maxbitlen;
- tree->numcodes = (unsigned)numcodes; /*number of symbols*/
- tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned));
- if(!tree->lengths) return 83; /*alloc fail*/
- /*initialize all lengths to 0*/
- memset(tree->lengths, 0, numcodes * sizeof(unsigned));
-
- error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen);
- if(!error) error = HuffmanTree_makeFromLengths2(tree);
- return error;
-}
-
-static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) {
- return tree->tree1d[index];
-}
-
-static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) {
- return tree->lengths[index];
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/
-static unsigned generateFixedLitLenTree(HuffmanTree* tree) {
- unsigned i, error = 0;
- unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
- if(!bitlen) return 83; /*alloc fail*/
-
- /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/
- for(i = 0; i <= 143; ++i) bitlen[i] = 8;
- for(i = 144; i <= 255; ++i) bitlen[i] = 9;
- for(i = 256; i <= 279; ++i) bitlen[i] = 7;
- for(i = 280; i <= 287; ++i) bitlen[i] = 8;
-
- error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15);
-
- lodepng_free(bitlen);
- return error;
-}
-
-/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/
-static unsigned generateFixedDistanceTree(HuffmanTree* tree) {
- unsigned i, error = 0;
- unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
- if(!bitlen) return 83; /*alloc fail*/
-
- /*there are 32 distance codes, but 30-31 are unused*/
- for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5;
- error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15);
-
- lodepng_free(bitlen);
- return error;
-}
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-/*
-returns the code, or (unsigned)(-1) if error happened
-inbitlength is the length of the complete buffer, in bits (so its byte length times 8)
-*/
-static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp,
- const HuffmanTree* codetree, size_t inbitlength) {
- unsigned treepos = 0, ct;
- for(;;) {
- if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/
- /*
- decode the symbol from the tree. The "readBitFromStream" code is inlined in
- the expression below because this is the biggest bottleneck while decoding
- */
- ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)];
- ++(*bp);
- if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/
- else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/
-
- if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/
- }
-}
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Inflator (Decompressor) / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/
-static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) {
- /*TODO: check for out of memory errors*/
- generateFixedLitLenTree(tree_ll);
- generateFixedDistanceTree(tree_d);
-}
-
-/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/
-static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d,
- const unsigned char* in, size_t* bp, size_t inlength) {
- /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/
- unsigned error = 0;
- unsigned n, HLIT, HDIST, HCLEN, i;
- size_t inbitlength = inlength * 8;
-
- /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/
- unsigned* bitlen_ll = 0; /*lit,len code lengths*/
- unsigned* bitlen_d = 0; /*dist code lengths*/
- /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/
- unsigned* bitlen_cl = 0;
- HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/
-
- if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/
-
- /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/
- HLIT = readBitsFromStream(bp, in, 5) + 257;
- /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/
- HDIST = readBitsFromStream(bp, in, 5) + 1;
- /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/
- HCLEN = readBitsFromStream(bp, in, 4) + 4;
-
- if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/
-
- HuffmanTree_init(&tree_cl);
-
- while(!error) {
- /*read the code length codes out of 3 * (amount of code length codes) bits*/
-
- bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned));
- if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/);
-
- for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i) {
- if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3);
- else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/
- }
-
- error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7);
- if(error) break;
-
- /*now we can use this tree to read the lengths for the tree that this function will return*/
- bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned));
- bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned));
- if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/);
- for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0;
- for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0;
-
- /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/
- i = 0;
- while(i < HLIT + HDIST) {
- unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength);
- if(code <= 15) /*a length code*/ {
- if(i < HLIT) bitlen_ll[i] = code;
- else bitlen_d[i - HLIT] = code;
- ++i;
- } else if(code == 16) /*repeat previous*/ {
- unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/
- unsigned value; /*set value to the previous code*/
-
- if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/
-
- if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
- replength += readBitsFromStream(bp, in, 2);
-
- if(i < HLIT + 1) value = bitlen_ll[i - 1];
- else value = bitlen_d[i - HLIT - 1];
- /*repeat this value in the next lengths*/
- for(n = 0; n < replength; ++n) {
- if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/
- if(i < HLIT) bitlen_ll[i] = value;
- else bitlen_d[i - HLIT] = value;
- ++i;
- }
- } else if(code == 17) /*repeat "0" 3-10 times*/ {
- unsigned replength = 3; /*read in the bits that indicate repeat length*/
- if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
- replength += readBitsFromStream(bp, in, 3);
-
- /*repeat this value in the next lengths*/
- for(n = 0; n < replength; ++n) {
- if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/
-
- if(i < HLIT) bitlen_ll[i] = 0;
- else bitlen_d[i - HLIT] = 0;
- ++i;
- }
- } else if(code == 18) /*repeat "0" 11-138 times*/ {
- unsigned replength = 11; /*read in the bits that indicate repeat length*/
- if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/
- replength += readBitsFromStream(bp, in, 7);
-
- /*repeat this value in the next lengths*/
- for(n = 0; n < replength; ++n) {
- if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/
-
- if(i < HLIT) bitlen_ll[i] = 0;
- else bitlen_d[i - HLIT] = 0;
- ++i;
- }
- } else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
- if(code == (unsigned)(-1)) {
- /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
- (10=no endcode, 11=wrong jump outside of tree)*/
- error = (*bp) > inbitlength ? 10 : 11;
- }
- else error = 16; /*unexisting code, this can never happen*/
- break;
- }
- }
- if(error) break;
-
- if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/
-
- /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/
- error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15);
- if(error) break;
- error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15);
-
- break; /*end of error-while*/
- }
-
- lodepng_free(bitlen_cl);
- lodepng_free(bitlen_ll);
- lodepng_free(bitlen_d);
- HuffmanTree_cleanup(&tree_cl);
-
- return error;
-}
-
-/*inflate a block with dynamic of fixed Huffman tree*/
-static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp,
- size_t* pos, size_t inlength, unsigned btype) {
- unsigned error = 0;
- HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/
- HuffmanTree tree_d; /*the huffman tree for distance codes*/
- size_t inbitlength = inlength * 8;
-
- HuffmanTree_init(&tree_ll);
- HuffmanTree_init(&tree_d);
-
- if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d);
- else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength);
-
- while(!error) /*decode all symbols until end reached, breaks at end code*/ {
- /*code_ll is literal, length or end code*/
- unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength);
- if(code_ll <= 255) /*literal symbol*/ {
- /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/
- if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/);
- out->data[*pos] = (unsigned char)code_ll;
- ++(*pos);
- } else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ {
- unsigned code_d, distance;
- unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/
- size_t start, forward, backward, length;
-
- /*part 1: get length base*/
- length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX];
-
- /*part 2: get extra bits and add the value of that to length*/
- numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX];
- if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
- length += readBitsFromStream(bp, in, numextrabits_l);
-
- /*part 3: get distance code*/
- code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength);
- if(code_d > 29) {
- if(code_d == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
- /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
- (10=no endcode, 11=wrong jump outside of tree)*/
- error = (*bp) > inlength * 8 ? 10 : 11;
- }
- else error = 18; /*error: invalid distance code (30-31 are never used)*/
- break;
- }
- distance = DISTANCEBASE[code_d];
-
- /*part 4: get extra bits from distance*/
- numextrabits_d = DISTANCEEXTRA[code_d];
- if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/
- distance += readBitsFromStream(bp, in, numextrabits_d);
-
- /*part 5: fill in all the out[n] values based on the length and dist*/
- start = (*pos);
- if(distance > start) ERROR_BREAK(52); /*too long backward distance*/
- backward = start - distance;
-
- if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/);
- if (distance < length) {
- for(forward = 0; forward < length; ++forward) {
- out->data[(*pos)++] = out->data[backward++];
- }
- } else {
- memcpy(out->data + *pos, out->data + backward, length);
- *pos += length;
- }
- } else if(code_ll == 256) {
- break; /*end code, break the loop*/
- } else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ {
- /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol
- (10=no endcode, 11=wrong jump outside of tree)*/
- error = ((*bp) > inlength * 8) ? 10 : 11;
- break;
- }
- }
-
- HuffmanTree_cleanup(&tree_ll);
- HuffmanTree_cleanup(&tree_d);
-
- return error;
-}
-
-static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) {
- size_t p;
- unsigned LEN, NLEN, n, error = 0;
-
- /*go to first boundary of byte*/
- while(((*bp) & 0x7) != 0) ++(*bp);
- p = (*bp) / 8; /*byte position*/
-
- /*read LEN (2 bytes) and NLEN (2 bytes)*/
- if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/
- LEN = in[p] + 256u * in[p + 1]; p += 2;
- NLEN = in[p] + 256u * in[p + 1]; p += 2;
-
- /*check if 16-bit NLEN is really the one's complement of LEN*/
- if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/
-
- if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/
-
- /*read the literal data: LEN bytes are now stored in the out buffer*/
- if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/
- for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++];
-
- (*bp) = p * 8;
-
- return error;
-}
-
-static unsigned lodepng_inflatev(ucvector* out,
- const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings* settings) {
- /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/
- size_t bp = 0;
- unsigned BFINAL = 0;
- size_t pos = 0; /*byte position in the out buffer*/
- unsigned error = 0;
-
- (void)settings;
-
- while(!BFINAL) {
- unsigned BTYPE;
- if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/
- BFINAL = readBitFromStream(&bp, in);
- BTYPE = 1u * readBitFromStream(&bp, in);
- BTYPE += 2u * readBitFromStream(&bp, in);
-
- if(BTYPE == 3) return 20; /*error: invalid BTYPE*/
- else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/
- else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/
-
- if(error) return error;
- }
-
- return error;
-}
-
-unsigned lodepng_inflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings* settings) {
- unsigned error;
- ucvector v;
- ucvector_init_buffer(&v, *out, *outsize);
- error = lodepng_inflatev(&v, in, insize, settings);
- *out = v.data;
- *outsize = v.size;
- return error;
-}
-
-static unsigned inflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings* settings) {
- if(settings->custom_inflate) {
- return settings->custom_inflate(out, outsize, in, insize, settings);
- } else {
- return lodepng_inflate(out, outsize, in, insize, settings);
- }
-}
-
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Deflator (Compressor) / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258;
-
-/*bitlen is the size in bits of the code*/
-static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) {
- addBitsToStreamReversed(bp, compressed, code, bitlen);
-}
-
-/*search the index in the array, that has the largest value smaller than or equal to the given value,
-given array must be sorted (if no value is smaller, it returns the size of the given array)*/
-static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) {
- /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/
- size_t left = 1;
- size_t right = array_size - 1;
-
- while(left <= right) {
- size_t mid = (left + right) >> 1;
- if (array[mid] >= value) right = mid - 1;
- else left = mid + 1;
- }
- if(left >= array_size || array[left] > value) left--;
- return left;
-}
-
-static void addLengthDistance(uivector* values, size_t length, size_t distance) {
- /*values in encoded vector are those used by deflate:
- 0-255: literal bytes
- 256: end
- 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits)
- 286-287: invalid*/
-
- unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length);
- unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]);
- unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance);
- unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]);
-
- uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX);
- uivector_push_back(values, extra_length);
- uivector_push_back(values, dist_code);
- uivector_push_back(values, extra_distance);
-}
-
-/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3
-bytes as input because 3 is the minimum match length for deflate*/
-static const unsigned HASH_NUM_VALUES = 65536;
-static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/
-
-typedef struct Hash {
- int* head; /*hash value to head circular pos - can be outdated if went around window*/
- /*circular pos to prev circular pos*/
- unsigned short* chain;
- int* val; /*circular pos to hash value*/
-
- /*TODO: do this not only for zeros but for any repeated byte. However for PNG
- it's always going to be the zeros that dominate, so not important for PNG*/
- int* headz; /*similar to head, but for chainz*/
- unsigned short* chainz; /*those with same amount of zeros*/
- unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/
-} Hash;
-
-static unsigned hash_init(Hash* hash, unsigned windowsize) {
- unsigned i;
- hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES);
- hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize);
- hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
-
- hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
- hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1));
- hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize);
-
- if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) {
- return 83; /*alloc fail*/
- }
-
- /*initialize hash table*/
- for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1;
- for(i = 0; i != windowsize; ++i) hash->val[i] = -1;
- for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/
-
- for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1;
- for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/
-
- return 0;
-}
-
-static void hash_cleanup(Hash* hash) {
- lodepng_free(hash->head);
- lodepng_free(hash->val);
- lodepng_free(hash->chain);
-
- lodepng_free(hash->zeros);
- lodepng_free(hash->headz);
- lodepng_free(hash->chainz);
-}
-
-
-
-static unsigned getHash(const unsigned char* data, size_t size, size_t pos) {
- unsigned result = 0;
- if(pos + 2 < size) {
- /*A simple shift and xor hash is used. Since the data of PNGs is dominated
- by zeroes due to the filters, a better hash does not have a significant
- effect on speed in traversing the chain, and causes more time spend on
- calculating the hash.*/
- result ^= (unsigned)(data[pos + 0] << 0u);
- result ^= (unsigned)(data[pos + 1] << 4u);
- result ^= (unsigned)(data[pos + 2] << 8u);
- } else {
- size_t amount, i;
- if(pos >= size) return 0;
- amount = size - pos;
- for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u));
- }
- return result & HASH_BIT_MASK;
-}
-
-static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) {
- const unsigned char* start = data + pos;
- const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH;
- if(end > data + size) end = data + size;
- data = start;
- while(data != end && *data == 0) ++data;
- /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/
- return (unsigned)(data - start);
-}
-
-/*wpos = pos & (windowsize - 1)*/
-static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) {
- hash->val[wpos] = (int)hashval;
- if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval];
- hash->head[hashval] = (int)wpos;
-
- hash->zeros[wpos] = numzeros;
- if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros];
- hash->headz[numzeros] = (int)wpos;
-}
-
-/*
-LZ77-encode the data. Return value is error code. The input are raw bytes, the output
-is in the form of unsigned integers with codes representing for example literal bytes, or
-length/distance pairs.
-It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a
-sliding window (of windowsize) is used, and all past bytes in that window can be used as
-the "dictionary". A brute force search through all possible distances would be slow, and
-this hash technique is one out of several ways to speed this up.
-*/
-static unsigned encodeLZ77(uivector* out, Hash* hash,
- const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
- unsigned minmatch, unsigned nicematch, unsigned lazymatching) {
- size_t pos;
- unsigned i, error = 0;
- /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
- unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8;
- unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
-
- unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
- unsigned numzeros = 0;
-
- unsigned offset; /*the offset represents the distance in LZ77 terminology*/
- unsigned length;
- unsigned lazy = 0;
- unsigned lazylength = 0, lazyoffset = 0;
- unsigned hashval;
- unsigned current_offset, current_length;
- unsigned prev_offset;
- const unsigned char *lastptr, *foreptr, *backptr;
- unsigned hashpos;
-
- if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
- if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
-
- if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
-
- for(pos = inpos; pos < insize; ++pos) {
- size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
- unsigned chainlength = 0;
-
- hashval = getHash(in, insize, pos);
-
- if(usezeros && hashval == 0) {
- if(numzeros == 0) numzeros = countZeros(in, insize, pos);
- else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
- } else {
- numzeros = 0;
- }
-
- updateHashChain(hash, wpos, hashval, numzeros);
-
- /*the length and offset found for the current position*/
- length = 0;
- offset = 0;
-
- hashpos = hash->chain[wpos];
-
- lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
-
- /*search for the longest string*/
- prev_offset = 0;
- for(;;) {
- if(chainlength++ >= maxchainlength) break;
- current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize);
-
- if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/
- prev_offset = current_offset;
- if(current_offset > 0) {
- /*test the next characters*/
- foreptr = &in[pos];
- backptr = &in[pos - current_offset];
-
- /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/
- if(numzeros >= 3) {
- unsigned skip = hash->zeros[hashpos];
- if(skip > numzeros) skip = numzeros;
- backptr += skip;
- foreptr += skip;
- }
-
- while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ {
- ++backptr;
- ++foreptr;
- }
- current_length = (unsigned)(foreptr - &in[pos]);
-
- if(current_length > length) {
- length = current_length; /*the longest length*/
- offset = current_offset; /*the offset that is related to this longest length*/
- /*jump out once a length of max length is found (speed gain). This also jumps
- out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/
- if(current_length >= nicematch) break;
- }
- }
-
- if(hashpos == hash->chain[hashpos]) break;
-
- if(numzeros >= 3 && length > numzeros) {
- hashpos = hash->chainz[hashpos];
- if(hash->zeros[hashpos] != numzeros) break;
- } else {
- hashpos = hash->chain[hashpos];
- /*outdated hash value, happens if particular value was not encountered in whole last window*/
- if(hash->val[hashpos] != (int)hashval) break;
- }
- }
-
- if(lazymatching) {
- if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) {
- lazy = 1;
- lazylength = length;
- lazyoffset = offset;
- continue; /*try the next byte*/
- }
- if(lazy) {
- lazy = 0;
- if(pos == 0) ERROR_BREAK(81);
- if(length > lazylength + 1) {
- /*push the previous character as literal*/
- if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/);
- } else {
- length = lazylength;
- offset = lazyoffset;
- hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/
- hash->headz[numzeros] = -1; /*idem*/
- --pos;
- }
- }
- }
- if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/);
-
- /*encode it as length/distance pair or literal value*/
- if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ {
- if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
- } else if(length < minmatch || (length == 3 && offset > 4096)) {
- /*compensate for the fact that longer offsets have more extra bits, a
- length of only 3 may be not worth it then*/
- if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/);
- } else {
- addLengthDistance(out, length, offset);
- for(i = 1; i < length; ++i) {
- ++pos;
- wpos = pos & (windowsize - 1);
- hashval = getHash(in, insize, pos);
- if(usezeros && hashval == 0) {
- if(numzeros == 0) numzeros = countZeros(in, insize, pos);
- else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
- } else {
- numzeros = 0;
- }
- updateHashChain(hash, wpos, hashval, numzeros);
- }
- }
- } /*end of the loop through each character of input*/
-
- return error;
-}
-
-/* /////////////////////////////////////////////////////////////////////////// */
-
-static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) {
- /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte,
- 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/
-
- size_t i, j, numdeflateblocks = (datasize + 65534) / 65535;
- unsigned datapos = 0;
- for(i = 0; i != numdeflateblocks; ++i) {
- unsigned BFINAL, BTYPE, LEN, NLEN;
- unsigned char firstbyte;
-
- BFINAL = (i == numdeflateblocks - 1);
- BTYPE = 0;
-
- firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1));
- ucvector_push_back(out, firstbyte);
-
- LEN = 65535;
- if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos;
- NLEN = 65535 - LEN;
-
- ucvector_push_back(out, (unsigned char)(LEN & 255));
- ucvector_push_back(out, (unsigned char)(LEN >> 8));
- ucvector_push_back(out, (unsigned char)(NLEN & 255));
- ucvector_push_back(out, (unsigned char)(NLEN >> 8));
-
- /*Decompressed data*/
- for(j = 0; j < 65535 && datapos < datasize; ++j) {
- ucvector_push_back(out, data[datapos++]);
- }
- }
-
- return 0;
-}
-
-/*
-write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees.
-tree_ll: the tree for lit and len codes.
-tree_d: the tree for distance codes.
-*/
-static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded,
- const HuffmanTree* tree_ll, const HuffmanTree* tree_d) {
- size_t i = 0;
- for(i = 0; i != lz77_encoded->size; ++i) {
- unsigned val = lz77_encoded->data[i];
- addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val));
- if(val > 256) /*for a length code, 3 more things have to be added*/ {
- unsigned length_index = val - FIRST_LENGTH_CODE_INDEX;
- unsigned n_length_extra_bits = LENGTHEXTRA[length_index];
- unsigned length_extra_bits = lz77_encoded->data[++i];
-
- unsigned distance_code = lz77_encoded->data[++i];
-
- unsigned distance_index = distance_code;
- unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index];
- unsigned distance_extra_bits = lz77_encoded->data[++i];
-
- addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits);
- addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code),
- HuffmanTree_getLength(tree_d, distance_code));
- addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits);
- }
- }
-}
-
-/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/
-static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash,
- const unsigned char* data, size_t datapos, size_t dataend,
- const LodePNGCompressSettings* settings, unsigned final) {
- unsigned error = 0;
-
- /*
- A block is compressed as follows: The PNG data is lz77 encoded, resulting in
- literal bytes and length/distance pairs. This is then huffman compressed with
- two huffman trees. One huffman tree is used for the lit and len values ("ll"),
- another huffman tree is used for the dist values ("d"). These two trees are
- stored using their code lengths, and to compress even more these code lengths
- are also run-length encoded and huffman compressed. This gives a huffman tree
- of code lengths "cl". The code lenghts used to describe this third tree are
- the code length code lengths ("clcl").
- */
-
- /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/
- uivector lz77_encoded;
- HuffmanTree tree_ll; /*tree for lit,len values*/
- HuffmanTree tree_d; /*tree for distance codes*/
- HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/
- uivector frequencies_ll; /*frequency of lit,len codes*/
- uivector frequencies_d; /*frequency of dist codes*/
- uivector frequencies_cl; /*frequency of code length codes*/
- uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/
- uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/
- /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl
- (these are written as is in the file, it would be crazy to compress these using yet another huffman
- tree that needs to be represented by yet another set of code lengths)*/
- uivector bitlen_cl;
- size_t datasize = dataend - datapos;
-
- /*
- Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies:
- bitlen_lld is to tree_cl what data is to tree_ll and tree_d.
- bitlen_lld_e is to bitlen_lld what lz77_encoded is to data.
- bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded.
- */
-
- unsigned BFINAL = final;
- size_t numcodes_ll, numcodes_d, i;
- unsigned HLIT, HDIST, HCLEN;
-
- uivector_init(&lz77_encoded);
- HuffmanTree_init(&tree_ll);
- HuffmanTree_init(&tree_d);
- HuffmanTree_init(&tree_cl);
- uivector_init(&frequencies_ll);
- uivector_init(&frequencies_d);
- uivector_init(&frequencies_cl);
- uivector_init(&bitlen_lld);
- uivector_init(&bitlen_lld_e);
- uivector_init(&bitlen_cl);
-
- /*This while loop never loops due to a break at the end, it is here to
- allow breaking out of it to the cleanup phase on error conditions.*/
- while(!error) {
- if(settings->use_lz77) {
- error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
- settings->minmatch, settings->nicematch, settings->lazymatching);
- if(error) break;
- } else {
- if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/);
- for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/
- }
-
- if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/);
- if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/);
-
- /*Count the frequencies of lit, len and dist codes*/
- for(i = 0; i != lz77_encoded.size; ++i) {
- unsigned symbol = lz77_encoded.data[i];
- ++frequencies_ll.data[symbol];
- if(symbol > 256) {
- unsigned dist = lz77_encoded.data[i + 2];
- ++frequencies_d.data[dist];
- i += 3;
- }
- }
- frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/
-
- /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/
- error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15);
- if(error) break;
- /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/
- error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15);
- if(error) break;
-
- numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286;
- numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30;
- /*store the code lengths of both generated trees in bitlen_lld*/
- for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i));
- for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i));
-
- /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times),
- 17 (3-10 zeroes), 18 (11-138 zeroes)*/
- for(i = 0; i != (unsigned)bitlen_lld.size; ++i) {
- unsigned j = 0; /*amount of repititions*/
- while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j;
-
- if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/ {
- ++j; /*include the first zero*/
- if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ {
- uivector_push_back(&bitlen_lld_e, 17);
- uivector_push_back(&bitlen_lld_e, j - 3);
- } else /*repeat code 18 supports max 138 zeroes*/ {
- if(j > 138) j = 138;
- uivector_push_back(&bitlen_lld_e, 18);
- uivector_push_back(&bitlen_lld_e, j - 11);
- }
- i += (j - 1);
- } else if(j >= 3) /*repeat code for value other than zero*/ {
- size_t k;
- unsigned num = j / 6, rest = j % 6;
- uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
- for(k = 0; k < num; ++k) {
- uivector_push_back(&bitlen_lld_e, 16);
- uivector_push_back(&bitlen_lld_e, 6 - 3);
- }
- if(rest >= 3) {
- uivector_push_back(&bitlen_lld_e, 16);
- uivector_push_back(&bitlen_lld_e, rest - 3);
- }
- else j -= rest;
- i += j;
- } else /*too short to benefit from repeat code*/ {
- uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]);
- }
- }
-
- /*generate tree_cl, the huffmantree of huffmantrees*/
-
- if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/);
- for(i = 0; i != bitlen_lld_e.size; ++i) {
- ++frequencies_cl.data[bitlen_lld_e.data[i]];
- /*after a repeat code come the bits that specify the number of repetitions,
- those don't need to be in the frequencies_cl calculation*/
- if(bitlen_lld_e.data[i] >= 16) ++i;
- }
-
- error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data,
- frequencies_cl.size, frequencies_cl.size, 7);
- if(error) break;
-
- if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/);
- for(i = 0; i != tree_cl.numcodes; ++i) {
- /*lenghts of code length tree is in the order as specified by deflate*/
- bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]);
- }
- while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) {
- /*remove zeros at the end, but minimum size must be 4*/
- if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/);
- }
- if(error) break;
-
- /*
- Write everything into the output
-
- After the BFINAL and BTYPE, the dynamic block consists out of the following:
- - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN
- - (HCLEN+4)*3 bits code lengths of code length alphabet
- - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length
- alphabet, + possible repetition codes 16, 17, 18)
- - HDIST + 1 code lengths of distance alphabet (encoded using the code length
- alphabet, + possible repetition codes 16, 17, 18)
- - compressed data
- - 256 (end code)
- */
-
- /*Write block type*/
- addBitToStream(bp, out, BFINAL);
- addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/
- addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/
-
- /*write the HLIT, HDIST and HCLEN values*/
- HLIT = (unsigned)(numcodes_ll - 257);
- HDIST = (unsigned)(numcodes_d - 1);
- HCLEN = (unsigned)bitlen_cl.size - 4;
- /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/
- while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN;
- addBitsToStream(bp, out, HLIT, 5);
- addBitsToStream(bp, out, HDIST, 5);
- addBitsToStream(bp, out, HCLEN, 4);
-
- /*write the code lenghts of the code length alphabet*/
- for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3);
-
- /*write the lenghts of the lit/len AND the dist alphabet*/
- for(i = 0; i != bitlen_lld_e.size; ++i) {
- addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]),
- HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i]));
- /*extra bits of repeat codes*/
- if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2);
- else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3);
- else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7);
- }
-
- /*write the compressed data symbols*/
- writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
- /*error: the length of the end code 256 must be larger than 0*/
- if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64);
-
- /*write the end code*/
- addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
-
- break; /*end of error-while*/
- }
-
- /*cleanup*/
- uivector_cleanup(&lz77_encoded);
- HuffmanTree_cleanup(&tree_ll);
- HuffmanTree_cleanup(&tree_d);
- HuffmanTree_cleanup(&tree_cl);
- uivector_cleanup(&frequencies_ll);
- uivector_cleanup(&frequencies_d);
- uivector_cleanup(&frequencies_cl);
- uivector_cleanup(&bitlen_lld_e);
- uivector_cleanup(&bitlen_lld);
- uivector_cleanup(&bitlen_cl);
-
- return error;
-}
-
-static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash,
- const unsigned char* data,
- size_t datapos, size_t dataend,
- const LodePNGCompressSettings* settings, unsigned final) {
- HuffmanTree tree_ll; /*tree for literal values and length codes*/
- HuffmanTree tree_d; /*tree for distance codes*/
-
- unsigned BFINAL = final;
- unsigned error = 0;
- size_t i;
-
- HuffmanTree_init(&tree_ll);
- HuffmanTree_init(&tree_d);
-
- generateFixedLitLenTree(&tree_ll);
- generateFixedDistanceTree(&tree_d);
-
- addBitToStream(bp, out, BFINAL);
- addBitToStream(bp, out, 1); /*first bit of BTYPE*/
- addBitToStream(bp, out, 0); /*second bit of BTYPE*/
-
- if(settings->use_lz77) /*LZ77 encoded*/ {
- uivector lz77_encoded;
- uivector_init(&lz77_encoded);
- error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize,
- settings->minmatch, settings->nicematch, settings->lazymatching);
- if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d);
- uivector_cleanup(&lz77_encoded);
- } else /*no LZ77, but still will be Huffman compressed*/ {
- for(i = datapos; i < dataend; ++i) {
- addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i]));
- }
- }
- /*add END code*/
- if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256));
-
- /*cleanup*/
- HuffmanTree_cleanup(&tree_ll);
- HuffmanTree_cleanup(&tree_d);
-
- return error;
-}
-
-static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize,
- const LodePNGCompressSettings* settings) {
- unsigned error = 0;
- size_t i, blocksize, numdeflateblocks;
- size_t bp = 0; /*the bit pointer*/
- Hash hash;
-
- if(settings->btype > 2) return 61;
- else if(settings->btype == 0) return deflateNoCompression(out, in, insize);
- else if(settings->btype == 1) blocksize = insize;
- else /*if(settings->btype == 2)*/ {
- /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/
- blocksize = insize / 8 + 8;
- if(blocksize < 65536) blocksize = 65536;
- if(blocksize > 262144) blocksize = 262144;
- }
-
- numdeflateblocks = (insize + blocksize - 1) / blocksize;
- if(numdeflateblocks == 0) numdeflateblocks = 1;
-
- error = hash_init(&hash, settings->windowsize);
- if(error) return error;
-
- for(i = 0; i != numdeflateblocks && !error; ++i) {
- unsigned final = (i == numdeflateblocks - 1);
- size_t start = i * blocksize;
- size_t end = start + blocksize;
- if(end > insize) end = insize;
-
- if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final);
- else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final);
- }
-
- hash_cleanup(&hash);
-
- return error;
-}
-
-unsigned lodepng_deflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGCompressSettings* settings) {
- unsigned error;
- ucvector v;
- ucvector_init_buffer(&v, *out, *outsize);
- error = lodepng_deflatev(&v, in, insize, settings);
- *out = v.data;
- *outsize = v.size;
- return error;
-}
-
-static unsigned deflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGCompressSettings* settings) {
- if(settings->custom_deflate) {
- return settings->custom_deflate(out, outsize, in, insize, settings);
- } else {
- return lodepng_deflate(out, outsize, in, insize, settings);
- }
-}
-
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Adler32 */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) {
- unsigned s1 = adler & 0xffff;
- unsigned s2 = (adler >> 16) & 0xffff;
-
- while(len > 0) {
- /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/
- unsigned amount = len > 5552 ? 5552 : len;
- len -= amount;
- while(amount > 0) {
- s1 += (*data++);
- s2 += s1;
- --amount;
- }
- s1 %= 65521;
- s2 %= 65521;
- }
-
- return (s2 << 16) | s1;
-}
-
-/*Return the adler32 of the bytes data[0..len-1]*/
-static unsigned adler32(const unsigned char* data, unsigned len) {
- return update_adler32(1L, data, len);
-}
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Zlib / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGDecompressSettings* settings) {
- unsigned error = 0;
- unsigned CM, CINFO, FDICT;
-
- if(insize < 2) return 53; /*error, size of zlib data too small*/
- /*read information from zlib header*/
- if((in[0] * 256 + in[1]) % 31 != 0) {
- /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/
- return 24;
- }
-
- CM = in[0] & 15;
- CINFO = (in[0] >> 4) & 15;
- /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/
- FDICT = (in[1] >> 5) & 1;
- /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/
-
- if(CM != 8 || CINFO > 7) {
- /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/
- return 25;
- }
- if(FDICT != 0) {
- /*error: the specification of PNG says about the zlib stream:
- "The additional flags shall not specify a preset dictionary."*/
- return 26;
- }
-
- error = inflate(out, outsize, in + 2, insize - 2, settings);
- if(error) return error;
-
- if(!settings->ignore_adler32) {
- unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]);
- unsigned checksum = adler32(*out, (unsigned)(*outsize));
- if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/
- }
-
- return 0; /*no error*/
-}
-
-static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGDecompressSettings* settings) {
- if(settings->custom_zlib) {
- return settings->custom_zlib(out, outsize, in, insize, settings);
- } else {
- return lodepng_zlib_decompress(out, outsize, in, insize, settings);
- }
-}
-
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGCompressSettings* settings) {
- /*initially, *out must be NULL and outsize 0, if you just give some random *out
- that's pointing to a non allocated buffer, this'll crash*/
- ucvector outv;
- size_t i;
- unsigned error;
- unsigned char* deflatedata = 0;
- size_t deflatesize = 0;
-
- /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/
- unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/
- unsigned FLEVEL = 0;
- unsigned FDICT = 0;
- unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64;
- unsigned FCHECK = 31 - CMFFLG % 31;
- CMFFLG += FCHECK;
-
- /*ucvector-controlled version of the output buffer, for dynamic array*/
- ucvector_init_buffer(&outv, *out, *outsize);
-
- ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8));
- ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255));
-
- error = deflate(&deflatedata, &deflatesize, in, insize, settings);
-
- if(!error) {
- unsigned ADLER32 = adler32(in, (unsigned)insize);
- for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]);
- lodepng_free(deflatedata);
- lodepng_add32bitInt(&outv, ADLER32);
- }
-
- *out = outv.data;
- *outsize = outv.size;
-
- return error;
-}
-
-/* compress using the default or custom zlib function */
-static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGCompressSettings* settings) {
- if(settings->custom_zlib) {
- return settings->custom_zlib(out, outsize, in, insize, settings);
- } else {
- return lodepng_zlib_compress(out, outsize, in, insize, settings);
- }
-}
-
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#else /*no LODEPNG_COMPILE_ZLIB*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGDecompressSettings* settings) {
- if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
- return settings->custom_zlib(out, outsize, in, insize, settings);
-}
-#endif /*LODEPNG_COMPILE_DECODER*/
-#ifdef LODEPNG_COMPILE_ENCODER
-static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in,
- size_t insize, const LodePNGCompressSettings* settings) {
- if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
- return settings->custom_zlib(out, outsize, in, insize, settings);
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#endif /*LODEPNG_COMPILE_ZLIB*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-/*this is a good tradeoff between speed and compression ratio*/
-#define DEFAULT_WINDOWSIZE 2048
-
-void lodepng_compress_settings_init(LodePNGCompressSettings* settings) {
- /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/
- settings->btype = 2;
- settings->use_lz77 = 1;
- settings->windowsize = DEFAULT_WINDOWSIZE;
- settings->minmatch = 3;
- settings->nicematch = 128;
- settings->lazymatching = 1;
-
- settings->custom_zlib = 0;
- settings->custom_deflate = 0;
- settings->custom_context = 0;
-}
-
-const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0};
-
-
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) {
- settings->ignore_adler32 = 0;
-
- settings->custom_zlib = 0;
- settings->custom_inflate = 0;
- settings->custom_context = 0;
-}
-
-const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0};
-
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* // End of Zlib related code. Begin of PNG related code. // */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_PNG
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / CRC32 / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-
-#ifndef LODEPNG_NO_COMPILE_CRC
-/* CRC polynomial: 0xedb88320 */
-static unsigned lodepng_crc32_table[256] = {
- 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u,
- 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u,
- 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u,
- 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u,
- 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u,
- 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u,
- 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u,
- 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u,
- 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u,
- 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u,
- 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u,
- 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u,
- 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u,
- 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u,
- 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u,
- 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u,
- 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u,
- 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u,
- 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u,
- 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u,
- 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u,
- 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u,
- 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u,
- 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u,
- 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u,
- 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u,
- 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u,
- 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u,
- 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u,
- 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u,
- 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u,
- 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u
-};
-
-/*Return the CRC of the bytes buf[0..len-1].*/
-unsigned lodepng_crc32(const unsigned char* data, size_t length) {
- unsigned r = 0xffffffffu;
- size_t i;
- for(i = 0; i < length; ++i) {
- r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8);
- }
- return r ^ 0xffffffffu;
-}
-#else /* !LODEPNG_NO_COMPILE_CRC */
-unsigned lodepng_crc32(const unsigned char* data, size_t length);
-#endif /* !LODEPNG_NO_COMPILE_CRC */
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Reading and writing single bits and bytes from/to stream for LodePNG / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) {
- unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1);
- ++(*bitpointer);
- return result;
-}
-
-static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) {
- unsigned result = 0;
- size_t i;
- for(i = 0 ; i < nbits; ++i) {
- result <<= 1;
- result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream);
- }
- return result;
-}
-
-#ifdef LODEPNG_COMPILE_DECODER
-static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) {
- /*the current bit in bitstream must be 0 for this to work*/
- if(bit) {
- /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/
- bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7)));
- }
- ++(*bitpointer);
-}
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) {
- /*the current bit in bitstream may be 0 or 1 for this to work*/
- if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7))));
- else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7)));
- ++(*bitpointer);
-}
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / PNG chunks / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-unsigned lodepng_chunk_length(const unsigned char* chunk) {
- return lodepng_read32bitInt(&chunk[0]);
-}
-
-void lodepng_chunk_type(char type[5], const unsigned char* chunk) {
- unsigned i;
- for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i];
- type[4] = 0; /*null termination char*/
-}
-
-unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) {
- if(strlen(type) != 4) return 0;
- return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]);
-}
-
-unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) {
- return((chunk[4] & 32) != 0);
-}
-
-unsigned char lodepng_chunk_private(const unsigned char* chunk) {
- return((chunk[6] & 32) != 0);
-}
-
-unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) {
- return((chunk[7] & 32) != 0);
-}
-
-unsigned char* lodepng_chunk_data(unsigned char* chunk) {
- return &chunk[8];
-}
-
-const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) {
- return &chunk[8];
-}
-
-unsigned lodepng_chunk_check_crc(const unsigned char* chunk) {
- unsigned length = lodepng_chunk_length(chunk);
- unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]);
- /*the CRC is taken of the data and the 4 chunk type letters, not the length*/
- unsigned checksum = lodepng_crc32(&chunk[4], length + 4);
- if(CRC != checksum) return 1;
- else return 0;
-}
-
-void lodepng_chunk_generate_crc(unsigned char* chunk) {
- unsigned length = lodepng_chunk_length(chunk);
- unsigned CRC = lodepng_crc32(&chunk[4], length + 4);
- lodepng_set32bitInt(chunk + 8 + length, CRC);
-}
-
-unsigned char* lodepng_chunk_next(unsigned char* chunk) {
- if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
- && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
- /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
- return chunk + 8;
- } else {
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
- return chunk + total_chunk_length;
- }
-}
-
-const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) {
- if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47
- && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) {
- /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */
- return chunk + 8;
- } else {
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
- return chunk + total_chunk_length;
- }
-}
-
-unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]) {
- for(;;) {
- if(chunk + 12 >= end) return 0;
- if(lodepng_chunk_type_equals(chunk, type)) return chunk;
- chunk = lodepng_chunk_next(chunk);
- }
-}
-
-const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) {
- for(;;) {
- if(chunk + 12 >= end) return 0;
- if(lodepng_chunk_type_equals(chunk, type)) return chunk;
- chunk = lodepng_chunk_next_const(chunk);
- }
-}
-
-unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) {
- unsigned i;
- unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12;
- unsigned char *chunk_start, *new_buffer;
- size_t new_length = (*outlength) + total_chunk_length;
- if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/
-
- new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
- if(!new_buffer) return 83; /*alloc fail*/
- (*out) = new_buffer;
- (*outlength) = new_length;
- chunk_start = &(*out)[new_length - total_chunk_length];
-
- for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i];
-
- return 0;
-}
-
-unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
- const char* type, const unsigned char* data) {
- unsigned i;
- unsigned char *chunk, *new_buffer;
- size_t new_length = (*outlength) + length + 12;
- if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/
- new_buffer = (unsigned char*)lodepng_realloc(*out, new_length);
- if(!new_buffer) return 83; /*alloc fail*/
- (*out) = new_buffer;
- (*outlength) = new_length;
- chunk = &(*out)[(*outlength) - length - 12];
-
- /*1: length*/
- lodepng_set32bitInt(chunk, (unsigned)length);
-
- /*2: chunk name (4 letters)*/
- chunk[4] = (unsigned char)type[0];
- chunk[5] = (unsigned char)type[1];
- chunk[6] = (unsigned char)type[2];
- chunk[7] = (unsigned char)type[3];
-
- /*3: the data*/
- for(i = 0; i != length; ++i) chunk[8 + i] = data[i];
-
- /*4: CRC (of the chunkname characters and the data)*/
- lodepng_chunk_generate_crc(chunk);
-
- return 0;
-}
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / Color types and such / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*return type is a LodePNG error code*/
-static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/ {
- switch(colortype) {
- case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*gray*/
- case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/
- case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/
- case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*gray + alpha*/
- case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/
- default: return 31;
- }
- return 0; /*allowed color type / bits combination*/
-}
-
-static unsigned getNumColorChannels(LodePNGColorType colortype) {
- switch(colortype) {
- case 0: return 1; /*gray*/
- case 2: return 3; /*RGB*/
- case 3: return 1; /*palette*/
- case 4: return 2; /*gray + alpha*/
- case 6: return 4; /*RGBA*/
- }
- return 0; /*unexisting color type*/
-}
-
-static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) {
- /*bits per pixel is amount of channels * bits per channel*/
- return getNumColorChannels(colortype) * bitdepth;
-}
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-void lodepng_color_mode_init(LodePNGColorMode* info) {
- info->key_defined = 0;
- info->key_r = info->key_g = info->key_b = 0;
- info->colortype = LCT_RGBA;
- info->bitdepth = 8;
- info->palette = 0;
- info->palettesize = 0;
-}
-
-void lodepng_color_mode_cleanup(LodePNGColorMode* info) {
- lodepng_palette_clear(info);
-}
-
-unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) {
- size_t i;
- lodepng_color_mode_cleanup(dest);
- *dest = *source;
- if(source->palette) {
- dest->palette = (unsigned char*)lodepng_malloc(1024);
- if(!dest->palette && source->palettesize) return 83; /*alloc fail*/
- for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i];
- }
- return 0;
-}
-
-LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) {
- LodePNGColorMode result;
- lodepng_color_mode_init(&result);
- result.colortype = colortype;
- result.bitdepth = bitdepth;
- return result;
-}
-
-static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) {
- size_t i;
- if(a->colortype != b->colortype) return 0;
- if(a->bitdepth != b->bitdepth) return 0;
- if(a->key_defined != b->key_defined) return 0;
- if(a->key_defined) {
- if(a->key_r != b->key_r) return 0;
- if(a->key_g != b->key_g) return 0;
- if(a->key_b != b->key_b) return 0;
- }
- if(a->palettesize != b->palettesize) return 0;
- for(i = 0; i != a->palettesize * 4; ++i) {
- if(a->palette[i] != b->palette[i]) return 0;
- }
- return 1;
-}
-
-void lodepng_palette_clear(LodePNGColorMode* info) {
- if(info->palette) lodepng_free(info->palette);
- info->palette = 0;
- info->palettesize = 0;
-}
-
-unsigned lodepng_palette_add(LodePNGColorMode* info,
- unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
- unsigned char* data;
- /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with
- the max of 256 colors, it'll have the exact alloc size*/
- if(!info->palette) /*allocate palette if empty*/ {
- /*room for 256 colors with 4 bytes each*/
- data = (unsigned char*)lodepng_realloc(info->palette, 1024);
- if(!data) return 83; /*alloc fail*/
- else info->palette = data;
- }
- info->palette[4 * info->palettesize + 0] = r;
- info->palette[4 * info->palettesize + 1] = g;
- info->palette[4 * info->palettesize + 2] = b;
- info->palette[4 * info->palettesize + 3] = a;
- ++info->palettesize;
- return 0;
-}
-
-/*calculate bits per pixel out of colortype and bitdepth*/
-unsigned lodepng_get_bpp(const LodePNGColorMode* info) {
- return lodepng_get_bpp_lct(info->colortype, info->bitdepth);
-}
-
-unsigned lodepng_get_channels(const LodePNGColorMode* info) {
- return getNumColorChannels(info->colortype);
-}
-
-unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) {
- return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA;
-}
-
-unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) {
- return (info->colortype & 4) != 0; /*4 or 6*/
-}
-
-unsigned lodepng_is_palette_type(const LodePNGColorMode* info) {
- return info->colortype == LCT_PALETTE;
-}
-
-unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) {
- size_t i;
- for(i = 0; i != info->palettesize; ++i) {
- if(info->palette[i * 4 + 3] < 255) return 1;
- }
- return 0;
-}
-
-unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) {
- return info->key_defined
- || lodepng_is_alpha_type(info)
- || lodepng_has_palette_alpha(info);
-}
-
-size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
- size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth);
- size_t n = (size_t)w * (size_t)h;
- return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8;
-}
-
-size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) {
- return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth);
-}
-
-
-#ifdef LODEPNG_COMPILE_PNG
-#ifdef LODEPNG_COMPILE_DECODER
-
-/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer,
-and in addition has one extra byte per line: the filter byte. So this gives a larger
-result than lodepng_get_raw_size. */
-static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) {
- size_t bpp = lodepng_get_bpp(color);
- /* + 1 for the filter byte, and possibly plus padding bits per line */
- size_t line = ((size_t)(w / 8) * bpp) + 1 + ((w & 7) * bpp + 7) / 8;
- return (size_t)h * line;
-}
-
-/* Safely check if multiplying two integers will overflow (no undefined
-behavior, compiler removing the code, etc...) and output result. */
-static int lodepng_mulofl(size_t a, size_t b, size_t* result) {
- *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */
- return (a != 0 && *result / a != b);
-}
-
-/* Safely check if adding two integers will overflow (no undefined
-behavior, compiler removing the code, etc...) and output result. */
-static int lodepng_addofl(size_t a, size_t b, size_t* result) {
- *result = a + b; /* Unsigned addition is well defined and safe in C90 */
- return *result < a;
-}
-
-/*Safely checks whether size_t overflow can be caused due to amount of pixels.
-This check is overcautious rather than precise. If this check indicates no overflow,
-you can safely compute in a size_t (but not an unsigned):
--(size_t)w * (size_t)h * 8
--amount of bytes in IDAT (including filter, padding and Adam7 bytes)
--amount of bytes in raw color model
-Returns 1 if overflow possible, 0 if not.
-*/
-static int lodepng_pixel_overflow(unsigned w, unsigned h,
- const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) {
- size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor));
- size_t numpixels, total;
- size_t line; /* bytes per line in worst case */
-
- if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1;
- if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */
-
- /* Bytes per scanline with the expression "(w / 8) * bpp) + ((w & 7) * bpp + 7) / 8" */
- if(lodepng_mulofl((size_t)(w / 8), bpp, &line)) return 1;
- if(lodepng_addofl(line, ((w & 7) * bpp + 7) / 8, &line)) return 1;
-
- if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */
- if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */
-
- return 0; /* no overflow */
-}
-#endif /*LODEPNG_COMPILE_DECODER*/
-#endif /*LODEPNG_COMPILE_PNG*/
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-
-static void LodePNGUnknownChunks_init(LodePNGInfo* info) {
- unsigned i;
- for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0;
- for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0;
-}
-
-static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) {
- unsigned i;
- for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]);
-}
-
-static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) {
- unsigned i;
-
- LodePNGUnknownChunks_cleanup(dest);
-
- for(i = 0; i != 3; ++i) {
- size_t j;
- dest->unknown_chunks_size[i] = src->unknown_chunks_size[i];
- dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]);
- if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/
- for(j = 0; j < src->unknown_chunks_size[i]; ++j) {
- dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j];
- }
- }
-
- return 0;
-}
-
-/******************************************************************************/
-
-static void LodePNGText_init(LodePNGInfo* info) {
- info->text_num = 0;
- info->text_keys = NULL;
- info->text_strings = NULL;
-}
-
-static void LodePNGText_cleanup(LodePNGInfo* info) {
- size_t i;
- for(i = 0; i != info->text_num; ++i) {
- string_cleanup(&info->text_keys[i]);
- string_cleanup(&info->text_strings[i]);
- }
- lodepng_free(info->text_keys);
- lodepng_free(info->text_strings);
-}
-
-static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
- size_t i = 0;
- dest->text_keys = 0;
- dest->text_strings = 0;
- dest->text_num = 0;
- for(i = 0; i != source->text_num; ++i) {
- CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i]));
- }
- return 0;
-}
-
-void lodepng_clear_text(LodePNGInfo* info) {
- LodePNGText_cleanup(info);
-}
-
-unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) {
- char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1)));
- char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1)));
- if(!new_keys || !new_strings) {
- lodepng_free(new_keys);
- lodepng_free(new_strings);
- return 83; /*alloc fail*/
- }
-
- ++info->text_num;
- info->text_keys = new_keys;
- info->text_strings = new_strings;
-
- info->text_keys[info->text_num - 1] = alloc_string(key);
- info->text_strings[info->text_num - 1] = alloc_string(str);
-
- return 0;
-}
-
-/******************************************************************************/
-
-static void LodePNGIText_init(LodePNGInfo* info) {
- info->itext_num = 0;
- info->itext_keys = NULL;
- info->itext_langtags = NULL;
- info->itext_transkeys = NULL;
- info->itext_strings = NULL;
-}
-
-static void LodePNGIText_cleanup(LodePNGInfo* info) {
- size_t i;
- for(i = 0; i != info->itext_num; ++i) {
- string_cleanup(&info->itext_keys[i]);
- string_cleanup(&info->itext_langtags[i]);
- string_cleanup(&info->itext_transkeys[i]);
- string_cleanup(&info->itext_strings[i]);
- }
- lodepng_free(info->itext_keys);
- lodepng_free(info->itext_langtags);
- lodepng_free(info->itext_transkeys);
- lodepng_free(info->itext_strings);
-}
-
-static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
- size_t i = 0;
- dest->itext_keys = 0;
- dest->itext_langtags = 0;
- dest->itext_transkeys = 0;
- dest->itext_strings = 0;
- dest->itext_num = 0;
- for(i = 0; i != source->itext_num; ++i) {
- CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i],
- source->itext_transkeys[i], source->itext_strings[i]));
- }
- return 0;
-}
-
-void lodepng_clear_itext(LodePNGInfo* info) {
- LodePNGIText_cleanup(info);
-}
-
-unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
- const char* transkey, const char* str) {
- char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1)));
- char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1)));
- char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1)));
- char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1)));
- if(!new_keys || !new_langtags || !new_transkeys || !new_strings) {
- lodepng_free(new_keys);
- lodepng_free(new_langtags);
- lodepng_free(new_transkeys);
- lodepng_free(new_strings);
- return 83; /*alloc fail*/
- }
-
- ++info->itext_num;
- info->itext_keys = new_keys;
- info->itext_langtags = new_langtags;
- info->itext_transkeys = new_transkeys;
- info->itext_strings = new_strings;
-
- info->itext_keys[info->itext_num - 1] = alloc_string(key);
- info->itext_langtags[info->itext_num - 1] = alloc_string(langtag);
- info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey);
- info->itext_strings[info->itext_num - 1] = alloc_string(str);
-
- return 0;
-}
-
-/* same as set but does not delete */
-static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
- info->iccp_name = alloc_string(name);
- info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size);
-
- if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/
-
- memcpy(info->iccp_profile, profile, profile_size);
- info->iccp_profile_size = profile_size;
-
- return 0; /*ok*/
-}
-
-unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) {
- if(info->iccp_name) lodepng_clear_icc(info);
- info->iccp_defined = 1;
-
- return lodepng_assign_icc(info, name, profile, profile_size);
-}
-
-void lodepng_clear_icc(LodePNGInfo* info) {
- string_cleanup(&info->iccp_name);
- lodepng_free(info->iccp_profile);
- info->iccp_profile = NULL;
- info->iccp_profile_size = 0;
- info->iccp_defined = 0;
-}
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-void lodepng_info_init(LodePNGInfo* info) {
- lodepng_color_mode_init(&info->color);
- info->interlace_method = 0;
- info->compression_method = 0;
- info->filter_method = 0;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- info->background_defined = 0;
- info->background_r = info->background_g = info->background_b = 0;
-
- LodePNGText_init(info);
- LodePNGIText_init(info);
-
- info->time_defined = 0;
- info->phys_defined = 0;
-
- info->gama_defined = 0;
- info->chrm_defined = 0;
- info->srgb_defined = 0;
- info->iccp_defined = 0;
- info->iccp_name = NULL;
- info->iccp_profile = NULL;
-
- LodePNGUnknownChunks_init(info);
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-}
-
-void lodepng_info_cleanup(LodePNGInfo* info) {
- lodepng_color_mode_cleanup(&info->color);
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- LodePNGText_cleanup(info);
- LodePNGIText_cleanup(info);
-
- lodepng_clear_icc(info);
-
- LodePNGUnknownChunks_cleanup(info);
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-}
-
-unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) {
- lodepng_info_cleanup(dest);
- *dest = *source;
- lodepng_color_mode_init(&dest->color);
- CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color));
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- CERROR_TRY_RETURN(LodePNGText_copy(dest, source));
- CERROR_TRY_RETURN(LodePNGIText_copy(dest, source));
- if(source->iccp_defined) {
- CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size));
- }
-
- LodePNGUnknownChunks_init(dest);
- CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source));
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- return 0;
-}
-
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/
-static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) {
- unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/
- /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/
- unsigned p = index & m;
- in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/
- in = in << (bits * (m - p));
- if(p == 0) out[index * bits / 8] = in;
- else out[index * bits / 8] |= in;
-}
-
-typedef struct ColorTree ColorTree;
-
-/*
-One node of a color tree
-This is the data structure used to count the number of unique colors and to get a palette
-index for a color. It's like an octree, but because the alpha channel is used too, each
-node has 16 instead of 8 children.
-*/
-struct ColorTree {
- ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/
- int index; /*the payload. Only has a meaningful value if this is in the last level*/
-};
-
-static void color_tree_init(ColorTree* tree) {
- int i;
- for(i = 0; i != 16; ++i) tree->children[i] = 0;
- tree->index = -1;
-}
-
-static void color_tree_cleanup(ColorTree* tree) {
- int i;
- for(i = 0; i != 16; ++i) {
- if(tree->children[i]) {
- color_tree_cleanup(tree->children[i]);
- lodepng_free(tree->children[i]);
- }
- }
-}
-
-/*returns -1 if color not present, its index otherwise*/
-static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
- int bit = 0;
- for(bit = 0; bit < 8; ++bit) {
- int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
- if(!tree->children[i]) return -1;
- else tree = tree->children[i];
- }
- return tree ? tree->index : -1;
-}
-
-#ifdef LODEPNG_COMPILE_ENCODER
-static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
- return color_tree_get(tree, r, g, b, a) >= 0;
-}
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-/*color is not allowed to already exist.
-Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/
-static void color_tree_add(ColorTree* tree,
- unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) {
- int bit;
- for(bit = 0; bit < 8; ++bit) {
- int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1);
- if(!tree->children[i]) {
- tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree));
- color_tree_init(tree->children[i]);
- }
- tree = tree->children[i];
- }
- tree->index = (int)index;
-}
-
-/*put a pixel, given its RGBA color, into image of any color type*/
-static unsigned rgba8ToPixel(unsigned char* out, size_t i,
- const LodePNGColorMode* mode, ColorTree* tree /*for palette*/,
- unsigned char r, unsigned char g, unsigned char b, unsigned char a) {
- if(mode->colortype == LCT_GREY) {
- unsigned char gray = r; /*((unsigned short)r + g + b) / 3;*/
- if(mode->bitdepth == 8) out[i] = gray;
- else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = gray;
- else {
- /*take the most significant bits of gray*/
- gray = (gray >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1);
- addColorBits(out, i, mode->bitdepth, gray);
- }
- } else if(mode->colortype == LCT_RGB) {
- if(mode->bitdepth == 8) {
- out[i * 3 + 0] = r;
- out[i * 3 + 1] = g;
- out[i * 3 + 2] = b;
- } else {
- out[i * 6 + 0] = out[i * 6 + 1] = r;
- out[i * 6 + 2] = out[i * 6 + 3] = g;
- out[i * 6 + 4] = out[i * 6 + 5] = b;
- }
- } else if(mode->colortype == LCT_PALETTE) {
- int index = color_tree_get(tree, r, g, b, a);
- if(index < 0) return 82; /*color not in palette*/
- if(mode->bitdepth == 8) out[i] = index;
- else addColorBits(out, i, mode->bitdepth, (unsigned)index);
- } else if(mode->colortype == LCT_GREY_ALPHA) {
- unsigned char gray = r; /*((unsigned short)r + g + b) / 3;*/
- if(mode->bitdepth == 8) {
- out[i * 2 + 0] = gray;
- out[i * 2 + 1] = a;
- } else if(mode->bitdepth == 16) {
- out[i * 4 + 0] = out[i * 4 + 1] = gray;
- out[i * 4 + 2] = out[i * 4 + 3] = a;
- }
- } else if(mode->colortype == LCT_RGBA) {
- if(mode->bitdepth == 8) {
- out[i * 4 + 0] = r;
- out[i * 4 + 1] = g;
- out[i * 4 + 2] = b;
- out[i * 4 + 3] = a;
- } else {
- out[i * 8 + 0] = out[i * 8 + 1] = r;
- out[i * 8 + 2] = out[i * 8 + 3] = g;
- out[i * 8 + 4] = out[i * 8 + 5] = b;
- out[i * 8 + 6] = out[i * 8 + 7] = a;
- }
- }
-
- return 0; /*no error*/
-}
-
-/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/
-static void rgba16ToPixel(unsigned char* out, size_t i,
- const LodePNGColorMode* mode,
- unsigned short r, unsigned short g, unsigned short b, unsigned short a) {
- if(mode->colortype == LCT_GREY) {
- unsigned short gray = r; /*((unsigned)r + g + b) / 3;*/
- out[i * 2 + 0] = (gray >> 8) & 255;
- out[i * 2 + 1] = gray & 255;
- } else if(mode->colortype == LCT_RGB) {
- out[i * 6 + 0] = (r >> 8) & 255;
- out[i * 6 + 1] = r & 255;
- out[i * 6 + 2] = (g >> 8) & 255;
- out[i * 6 + 3] = g & 255;
- out[i * 6 + 4] = (b >> 8) & 255;
- out[i * 6 + 5] = b & 255;
- } else if(mode->colortype == LCT_GREY_ALPHA) {
- unsigned short gray = r; /*((unsigned)r + g + b) / 3;*/
- out[i * 4 + 0] = (gray >> 8) & 255;
- out[i * 4 + 1] = gray & 255;
- out[i * 4 + 2] = (a >> 8) & 255;
- out[i * 4 + 3] = a & 255;
- } else if(mode->colortype == LCT_RGBA) {
- out[i * 8 + 0] = (r >> 8) & 255;
- out[i * 8 + 1] = r & 255;
- out[i * 8 + 2] = (g >> 8) & 255;
- out[i * 8 + 3] = g & 255;
- out[i * 8 + 4] = (b >> 8) & 255;
- out[i * 8 + 5] = b & 255;
- out[i * 8 + 6] = (a >> 8) & 255;
- out[i * 8 + 7] = a & 255;
- }
-}
-
-/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/
-static void getPixelColorRGBA8(unsigned char* r, unsigned char* g,
- unsigned char* b, unsigned char* a,
- const unsigned char* in, size_t i,
- const LodePNGColorMode* mode) {
- if(mode->colortype == LCT_GREY) {
- if(mode->bitdepth == 8) {
- *r = *g = *b = in[i];
- if(mode->key_defined && *r == mode->key_r) *a = 0;
- else *a = 255;
- } else if(mode->bitdepth == 16) {
- *r = *g = *b = in[i * 2 + 0];
- if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
- else *a = 255;
- } else {
- unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
- size_t j = i * mode->bitdepth;
- unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
- *r = *g = *b = (value * 255) / highest;
- if(mode->key_defined && value == mode->key_r) *a = 0;
- else *a = 255;
- }
- } else if(mode->colortype == LCT_RGB) {
- if(mode->bitdepth == 8) {
- *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2];
- if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0;
- else *a = 255;
- } else {
- *r = in[i * 6 + 0];
- *g = in[i * 6 + 2];
- *b = in[i * 6 + 4];
- if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
- && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
- && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
- else *a = 255;
- }
- } else if(mode->colortype == LCT_PALETTE) {
- unsigned index;
- if(mode->bitdepth == 8) index = in[i];
- else {
- size_t j = i * mode->bitdepth;
- index = readBitsFromReversedStream(&j, in, mode->bitdepth);
- }
-
- if(index >= mode->palettesize) {
- /*This is an error according to the PNG spec, but common PNG decoders make it black instead.
- Done here too, slightly faster due to no error handling needed.*/
- *r = *g = *b = 0;
- *a = 255;
- } else {
- *r = mode->palette[index * 4 + 0];
- *g = mode->palette[index * 4 + 1];
- *b = mode->palette[index * 4 + 2];
- *a = mode->palette[index * 4 + 3];
- }
- } else if(mode->colortype == LCT_GREY_ALPHA) {
- if(mode->bitdepth == 8) {
- *r = *g = *b = in[i * 2 + 0];
- *a = in[i * 2 + 1];
- } else {
- *r = *g = *b = in[i * 4 + 0];
- *a = in[i * 4 + 2];
- }
- } else if(mode->colortype == LCT_RGBA) {
- if(mode->bitdepth == 8) {
- *r = in[i * 4 + 0];
- *g = in[i * 4 + 1];
- *b = in[i * 4 + 2];
- *a = in[i * 4 + 3];
- } else {
- *r = in[i * 8 + 0];
- *g = in[i * 8 + 2];
- *b = in[i * 8 + 4];
- *a = in[i * 8 + 6];
- }
- }
-}
-
-/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color
-mode test cases, optimized to convert the colors much faster, when converting
-to RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with
-enough memory, if has_alpha is true the output is RGBA. mode has the color mode
-of the input buffer.*/
-static void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels,
- unsigned has_alpha, const unsigned char* in,
- const LodePNGColorMode* mode) {
- unsigned num_channels = has_alpha ? 4 : 3;
- size_t i;
- if(mode->colortype == LCT_GREY) {
- if(mode->bitdepth == 8) {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = buffer[1] = buffer[2] = in[i];
- if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255;
- }
- } else if(mode->bitdepth == 16) {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = buffer[1] = buffer[2] = in[i * 2];
- if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255;
- }
- } else {
- unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/
- size_t j = 0;
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth);
- buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest;
- if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255;
- }
- }
- } else if(mode->colortype == LCT_RGB) {
- if(mode->bitdepth == 8) {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = in[i * 3 + 0];
- buffer[1] = in[i * 3 + 1];
- buffer[2] = in[i * 3 + 2];
- if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r
- && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255;
- }
- } else {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = in[i * 6 + 0];
- buffer[1] = in[i * 6 + 2];
- buffer[2] = in[i * 6 + 4];
- if(has_alpha) buffer[3] = mode->key_defined
- && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
- && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
- && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255;
- }
- }
- } else if(mode->colortype == LCT_PALETTE) {
- unsigned index;
- size_t j = 0;
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- if(mode->bitdepth == 8) index = in[i];
- else index = readBitsFromReversedStream(&j, in, mode->bitdepth);
-
- if(index >= mode->palettesize) {
- /*This is an error according to the PNG spec, but most PNG decoders make it black instead.
- Done here too, slightly faster due to no error handling needed.*/
- buffer[0] = buffer[1] = buffer[2] = 0;
- if(has_alpha) buffer[3] = 255;
- } else {
- buffer[0] = mode->palette[index * 4 + 0];
- buffer[1] = mode->palette[index * 4 + 1];
- buffer[2] = mode->palette[index * 4 + 2];
- if(has_alpha) buffer[3] = mode->palette[index * 4 + 3];
- }
- }
- } else if(mode->colortype == LCT_GREY_ALPHA) {
- if(mode->bitdepth == 8) {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0];
- if(has_alpha) buffer[3] = in[i * 2 + 1];
- }
- } else {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0];
- if(has_alpha) buffer[3] = in[i * 4 + 2];
- }
- }
- } else if(mode->colortype == LCT_RGBA) {
- if(mode->bitdepth == 8) {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = in[i * 4 + 0];
- buffer[1] = in[i * 4 + 1];
- buffer[2] = in[i * 4 + 2];
- if(has_alpha) buffer[3] = in[i * 4 + 3];
- }
- } else {
- for(i = 0; i != numpixels; ++i, buffer += num_channels) {
- buffer[0] = in[i * 8 + 0];
- buffer[1] = in[i * 8 + 2];
- buffer[2] = in[i * 8 + 4];
- if(has_alpha) buffer[3] = in[i * 8 + 6];
- }
- }
- }
-}
-
-/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with
-given color type, but the given color type must be 16-bit itself.*/
-static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a,
- const unsigned char* in, size_t i, const LodePNGColorMode* mode) {
- if(mode->colortype == LCT_GREY) {
- *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1];
- if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0;
- else *a = 65535;
- } else if(mode->colortype == LCT_RGB) {
- *r = 256u * in[i * 6 + 0] + in[i * 6 + 1];
- *g = 256u * in[i * 6 + 2] + in[i * 6 + 3];
- *b = 256u * in[i * 6 + 4] + in[i * 6 + 5];
- if(mode->key_defined
- && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r
- && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g
- && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0;
- else *a = 65535;
- } else if(mode->colortype == LCT_GREY_ALPHA) {
- *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1];
- *a = 256u * in[i * 4 + 2] + in[i * 4 + 3];
- } else if(mode->colortype == LCT_RGBA) {
- *r = 256u * in[i * 8 + 0] + in[i * 8 + 1];
- *g = 256u * in[i * 8 + 2] + in[i * 8 + 3];
- *b = 256u * in[i * 8 + 4] + in[i * 8 + 5];
- *a = 256u * in[i * 8 + 6] + in[i * 8 + 7];
- }
-}
-
-unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
- const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
- unsigned w, unsigned h) {
- size_t i;
- ColorTree tree;
- size_t numpixels = (size_t)w * (size_t)h;
- unsigned error = 0;
-
- if(lodepng_color_mode_equal(mode_out, mode_in)) {
- size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
- for(i = 0; i != numbytes; ++i) out[i] = in[i];
- return 0;
- }
-
- if(mode_out->colortype == LCT_PALETTE) {
- size_t palettesize = mode_out->palettesize;
- const unsigned char* palette = mode_out->palette;
- size_t palsize = (size_t)1u << mode_out->bitdepth;
- /*if the user specified output palette but did not give the values, assume
- they want the values of the input color type (assuming that one is palette).
- Note that we never create a new palette ourselves.*/
- if(palettesize == 0) {
- palettesize = mode_in->palettesize;
- palette = mode_in->palette;
- /*if the input was also palette with same bitdepth, then the color types are also
- equal, so copy literally. This to preserve the exact indices that were in the PNG
- even in case there are duplicate colors in the palette.*/
- if (mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) {
- size_t numbytes = lodepng_get_raw_size(w, h, mode_in);
- for(i = 0; i != numbytes; ++i) out[i] = in[i];
- return 0;
- }
- }
- if(palettesize < palsize) palsize = palettesize;
- color_tree_init(&tree);
- for(i = 0; i != palsize; ++i) {
- const unsigned char* p = &palette[i * 4];
- color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i);
- }
- }
-
- if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) {
- for(i = 0; i != numpixels; ++i) {
- unsigned short r = 0, g = 0, b = 0, a = 0;
- getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
- rgba16ToPixel(out, i, mode_out, r, g, b, a);
- }
- } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) {
- getPixelColorsRGBA8(out, numpixels, 1, in, mode_in);
- } else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) {
- getPixelColorsRGBA8(out, numpixels, 0, in, mode_in);
- } else {
- unsigned char r = 0, g = 0, b = 0, a = 0;
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
- error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a);
- if (error) break;
- }
- }
-
- if(mode_out->colortype == LCT_PALETTE) {
- color_tree_cleanup(&tree);
- }
-
- return error;
-}
-
-
-/* Converts a single rgb color without alpha from one type to another, color bits truncated to
-their bitdepth. In case of single channel (gray or palette), only the r channel is used. Slow
-function, do not use to process all pixels of an image. Alpha channel not supported on purpose:
-this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the
-specification it looks like bKGD should ignore the alpha values of the palette since it can use
-any palette index but doesn't have an alpha channel. Idem with ignoring color key. */
-unsigned lodepng_convert_rgb(
- unsigned* r_out, unsigned* g_out, unsigned* b_out,
- unsigned r_in, unsigned g_in, unsigned b_in,
- const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) {
- unsigned r = 0, g = 0, b = 0;
- unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/
- unsigned shift = 16 - mode_out->bitdepth;
-
- if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) {
- r = g = b = r_in * mul;
- } else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) {
- r = r_in * mul;
- g = g_in * mul;
- b = b_in * mul;
- } else if(mode_in->colortype == LCT_PALETTE) {
- if(r_in >= mode_in->palettesize) return 82;
- r = mode_in->palette[r_in * 4 + 0] * 257u;
- g = mode_in->palette[r_in * 4 + 1] * 257u;
- b = mode_in->palette[r_in * 4 + 2] * 257u;
- } else {
- return 31;
- }
-
- /* now convert to output format */
- if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) {
- *r_out = r >> shift ;
- } else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) {
- *r_out = r >> shift ;
- *g_out = g >> shift ;
- *b_out = b >> shift ;
- } else if(mode_out->colortype == LCT_PALETTE) {
- unsigned i;
- /* a 16-bit color cannot be in the palette */
- if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82;
- for(i = 0; i < mode_out->palettesize; i++) {
- unsigned j = i * 4;
- if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] &&
- (b >> 8) == mode_out->palette[j + 2]) {
- *r_out = i;
- return 0;
- }
- }
- return 82;
- } else {
- return 31;
- }
-
- return 0;
-}
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-void lodepng_color_profile_init(LodePNGColorProfile* profile) {
- profile->colored = 0;
- profile->key = 0;
- profile->key_r = profile->key_g = profile->key_b = 0;
- profile->alpha = 0;
- profile->numcolors = 0;
- profile->bits = 1;
- profile->numpixels = 0;
-}
-
-/*function used for debug purposes with C++*/
-/*void printColorProfile(LodePNGColorProfile* p) {
- std::cout << "colored: " << (int)p->colored << ", ";
- std::cout << "key: " << (int)p->key << ", ";
- std::cout << "key_r: " << (int)p->key_r << ", ";
- std::cout << "key_g: " << (int)p->key_g << ", ";
- std::cout << "key_b: " << (int)p->key_b << ", ";
- std::cout << "alpha: " << (int)p->alpha << ", ";
- std::cout << "numcolors: " << (int)p->numcolors << ", ";
- std::cout << "bits: " << (int)p->bits << std::endl;
-}*/
-
-/*Returns how many bits needed to represent given value (max 8 bit)*/
-static unsigned getValueRequiredBits(unsigned char value) {
- if(value == 0 || value == 255) return 1;
- /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/
- if(value % 17 == 0) return value % 85 == 0 ? 2 : 4;
- return 8;
-}
-
-/*profile must already have been inited.
-It's ok to set some parameters of profile to done already.*/
-unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
- const unsigned char* in, unsigned w, unsigned h,
- const LodePNGColorMode* mode_in) {
- unsigned error = 0;
- size_t i;
- ColorTree tree;
- size_t numpixels = (size_t)w * (size_t)h;
-
- /* mark things as done already if it would be impossible to have a more expensive case */
- unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0;
- unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1;
- unsigned numcolors_done = 0;
- unsigned bpp = lodepng_get_bpp(mode_in);
- unsigned bits_done = (profile->bits == 1 && bpp == 1) ? 1 : 0;
- unsigned sixteen = 0; /* whether the input image is 16 bit */
- unsigned maxnumcolors = 257;
- if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, profile->numcolors + (1u << bpp));
-
- profile->numpixels += numpixels;
-
- color_tree_init(&tree);
-
- /*If the profile was already filled in from previous data, fill its palette in tree
- and mark things as done already if we know they are the most expensive case already*/
- if(profile->alpha) alpha_done = 1;
- if(profile->colored) colored_done = 1;
- if(profile->bits == 16) numcolors_done = 1;
- if(profile->bits >= bpp) bits_done = 1;
- if(profile->numcolors >= maxnumcolors) numcolors_done = 1;
-
- if(!numcolors_done) {
- for(i = 0; i < profile->numcolors; i++) {
- const unsigned char* color = &profile->palette[i * 4];
- color_tree_add(&tree, color[0], color[1], color[2], color[3], (unsigned int)i);
- }
- }
-
- /*Check if the 16-bit input is truly 16-bit*/
- if(mode_in->bitdepth == 16 && !sixteen) {
- unsigned short r, g, b, a;
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
- if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) ||
- (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ {
- profile->bits = 16;
- sixteen = 1;
- bits_done = 1;
- numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/
- break;
- }
- }
- }
-
- if(sixteen) {
- unsigned short r = 0, g = 0, b = 0, a = 0;
-
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
-
- if(!colored_done && (r != g || r != b)) {
- profile->colored = 1;
- colored_done = 1;
- }
-
- if(!alpha_done) {
- unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);
- if(a != 65535 && (a != 0 || (profile->key && !matchkey))) {
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- } else if(a == 0 && !profile->alpha && !profile->key) {
- profile->key = 1;
- profile->key_r = r;
- profile->key_g = g;
- profile->key_b = b;
- } else if(a == 65535 && profile->key && matchkey) {
- /* Color key cannot be used if an opaque pixel also has that RGB color. */
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- }
- }
- if(alpha_done && numcolors_done && colored_done && bits_done) break;
- }
-
- if(profile->key && !profile->alpha) {
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in);
- if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) {
- /* Color key cannot be used if an opaque pixel also has that RGB color. */
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- }
- }
- }
- } else /* < 16-bit */ {
- unsigned char r = 0, g = 0, b = 0, a = 0;
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
-
- if(!bits_done && profile->bits < 8) {
- /*only r is checked, < 8 bits is only relevant for grayscale*/
- unsigned bits = getValueRequiredBits(r);
- if(bits > profile->bits) profile->bits = bits;
- }
- bits_done = (profile->bits >= bpp);
-
- if(!colored_done && (r != g || r != b)) {
- profile->colored = 1;
- colored_done = 1;
- if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/
- }
-
- if(!alpha_done) {
- unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b);
- if(a != 255 && (a != 0 || (profile->key && !matchkey))) {
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
- } else if(a == 0 && !profile->alpha && !profile->key) {
- profile->key = 1;
- profile->key_r = r;
- profile->key_g = g;
- profile->key_b = b;
- } else if(a == 255 && profile->key && matchkey) {
- /* Color key cannot be used if an opaque pixel also has that RGB color. */
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
- }
- }
-
- if(!numcolors_done) {
- if(!color_tree_has(&tree, r, g, b, a)) {
- color_tree_add(&tree, r, g, b, a, profile->numcolors);
- if(profile->numcolors < 256) {
- unsigned char* p = profile->palette;
- unsigned n = profile->numcolors;
- p[n * 4 + 0] = r;
- p[n * 4 + 1] = g;
- p[n * 4 + 2] = b;
- p[n * 4 + 3] = a;
- }
- ++profile->numcolors;
- numcolors_done = profile->numcolors >= maxnumcolors;
- }
- }
-
- if(alpha_done && numcolors_done && colored_done && bits_done) break;
- }
-
- if(profile->key && !profile->alpha) {
- for(i = 0; i != numpixels; ++i) {
- getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in);
- if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) {
- /* Color key cannot be used if an opaque pixel also has that RGB color. */
- profile->alpha = 1;
- profile->key = 0;
- alpha_done = 1;
- if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
- }
- }
- }
-
- /*make the profile's key always 16-bit for consistency - repeat each byte twice*/
- profile->key_r += (profile->key_r << 8);
- profile->key_g += (profile->key_g << 8);
- profile->key_b += (profile->key_b << 8);
- }
-
- color_tree_cleanup(&tree);
- return error;
-}
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-/*Adds a single color to the color profile. The profile must already have been inited. The color must be given as 16-bit
-(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for
-all pixels of an image but only for a few additional values. */
-static unsigned lodepng_color_profile_add(LodePNGColorProfile* profile,
- unsigned r, unsigned g, unsigned b, unsigned a) {
- unsigned error = 0;
- unsigned char image[8];
- LodePNGColorMode mode;
- lodepng_color_mode_init(&mode);
- image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g;
- image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a;
- mode.bitdepth = 16;
- mode.colortype = LCT_RGBA;
- error = lodepng_get_color_profile(profile, image, 1, 1, &mode);
- lodepng_color_mode_cleanup(&mode);
- return error;
-}
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-/*Autochoose color model given the computed profile. mode_in is to copy palette order from
-when relevant.*/
-static unsigned auto_choose_color_from_profile(LodePNGColorMode* mode_out,
- const LodePNGColorMode* mode_in,
- const LodePNGColorProfile* prof) {
- unsigned error = 0;
- unsigned palettebits, palette_ok;
- size_t i, n;
- size_t numpixels = prof->numpixels;
-
- unsigned alpha = prof->alpha;
- unsigned key = prof->key;
- unsigned bits = prof->bits;
-
- mode_out->key_defined = 0;
-
- if(key && numpixels <= 16) {
- alpha = 1; /*too few pixels to justify tRNS chunk overhead*/
- key = 0;
- if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/
- }
- n = prof->numcolors;
- palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8));
- palette_ok = n <= 256 && bits <= 8;
- if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/
- if(!prof->colored && bits <= palettebits) palette_ok = 0; /*gray is less overhead*/
-
- if(palette_ok) {
- const unsigned char* p = prof->palette;
- lodepng_palette_clear(mode_out); /*remove potential earlier palette*/
- for(i = 0; i != prof->numcolors; ++i) {
- error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]);
- if(error) break;
- }
-
- mode_out->colortype = LCT_PALETTE;
- mode_out->bitdepth = palettebits;
-
- if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize
- && mode_in->bitdepth == mode_out->bitdepth) {
- /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/
- lodepng_color_mode_cleanup(mode_out);
- lodepng_color_mode_copy(mode_out, mode_in);
- }
- } else /*8-bit or 16-bit per channel*/ {
- mode_out->bitdepth = bits;
- mode_out->colortype = alpha ? (prof->colored ? LCT_RGBA : LCT_GREY_ALPHA)
- : (prof->colored ? LCT_RGB : LCT_GREY);
-
- if(key) {
- unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/
- mode_out->key_r = prof->key_r & mask;
- mode_out->key_g = prof->key_g & mask;
- mode_out->key_b = prof->key_b & mask;
- mode_out->key_defined = 1;
- }
- }
-
- return error;
-}
-
-/*Automatically chooses color type that gives smallest amount of bits in the
-output image, e.g. gray if there are only grayscale pixels, palette if there
-are less than 256 colors, color key if only single transparent color, ...
-Updates values of mode with a potentially smaller color model. mode_out should
-contain the user chosen color model, but will be overwritten with the new chosen one.*/
-unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
- const unsigned char* image, unsigned w, unsigned h,
- const LodePNGColorMode* mode_in) {
- unsigned error = 0;
- LodePNGColorProfile prof;
- lodepng_color_profile_init(&prof);
- error = lodepng_get_color_profile(&prof, image, w, h, mode_in);
- if(error) return error;
- return auto_choose_color_from_profile(mode_out, mode_in, &prof);
-}
-
-#endif /* #ifdef LODEPNG_COMPILE_ENCODER */
-
-/*
-Paeth predicter, used by PNG filter type 4
-The parameters are of type short, but should come from unsigned chars, the shorts
-are only needed to make the paeth calculation correct.
-*/
-static unsigned char paethPredictor(short a, short b, short c) {
- short pa = abs(b - c);
- short pb = abs(a - c);
- short pc = abs(a + b - c - c);
-
- if(pc < pa && pc < pb) return (unsigned char)c;
- else if(pb < pa) return (unsigned char)b;
- else return (unsigned char)a;
-}
-
-/*shared values used by multiple Adam7 related functions*/
-
-static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/
-static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/
-static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/
-static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/
-
-/*
-Outputs various dimensions and positions in the image related to the Adam7 reduced images.
-passw: output containing the width of the 7 passes
-passh: output containing the height of the 7 passes
-filter_passstart: output containing the index of the start and end of each
- reduced image with filter bytes
-padded_passstart output containing the index of the start and end of each
- reduced image when without filter bytes but with padded scanlines
-passstart: output containing the index of the start and end of each reduced
- image without padding between scanlines, but still padding between the images
-w, h: width and height of non-interlaced image
-bpp: bits per pixel
-"padded" is only relevant if bpp is less than 8 and a scanline or image does not
- end at a full byte
-*/
-static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8],
- size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) {
- /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/
- unsigned i;
-
- /*calculate width and height in pixels of each pass*/
- for(i = 0; i != 7; ++i) {
- passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i];
- passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i];
- if(passw[i] == 0) passh[i] = 0;
- if(passh[i] == 0) passw[i] = 0;
- }
-
- filter_passstart[0] = padded_passstart[0] = passstart[0] = 0;
- for(i = 0; i != 7; ++i) {
- /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/
- filter_passstart[i + 1] = filter_passstart[i]
- + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0);
- /*bits padded if needed to fill full byte at end of each scanline*/
- padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8);
- /*only padded at end of reduced image*/
- passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8;
- }
-}
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / PNG Decoder / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*read the information from the header and store it in the LodePNGInfo. return value is error*/
-unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state,
- const unsigned char* in, size_t insize) {
- unsigned width, height;
- LodePNGInfo* info = &state->info_png;
- if(insize == 0 || in == 0) {
- CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/
- }
- if(insize < 33) {
- CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/
- }
-
- /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/
- /* TODO: remove this. One should use a new LodePNGState for new sessions */
- lodepng_info_cleanup(info);
- lodepng_info_init(info);
-
- if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71
- || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) {
- CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/
- }
- if(lodepng_chunk_length(in + 8) != 13) {
- CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/
- }
- if(!lodepng_chunk_type_equals(in + 8, "IHDR")) {
- CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/
- }
-
- /*read the values given in the header*/
- width = lodepng_read32bitInt(&in[16]);
- height = lodepng_read32bitInt(&in[20]);
- info->color.bitdepth = in[24];
- info->color.colortype = (LodePNGColorType)in[25];
- info->compression_method = in[26];
- info->filter_method = in[27];
- info->interlace_method = in[28];
-
- if(width == 0 || height == 0) {
- CERROR_RETURN_ERROR(state->error, 93);
- }
-
- if(w) *w = width;
- if(h) *h = height;
-
- if(!state->decoder.ignore_crc) {
- unsigned CRC = lodepng_read32bitInt(&in[29]);
- unsigned checksum = lodepng_crc32(&in[12], 17);
- if(CRC != checksum) {
- CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/
- }
- }
-
- /*error: only compression method 0 is allowed in the specification*/
- if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32);
- /*error: only filter method 0 is allowed in the specification*/
- if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33);
- /*error: only interlace methods 0 and 1 exist in the specification*/
- if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34);
-
- state->error = checkColorValidity(info->color.colortype, info->color.bitdepth);
- return state->error;
-}
-
-static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon,
- size_t bytewidth, unsigned char filterType, size_t length) {
- /*
- For PNG filter method 0
- unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte,
- the filter works byte per byte (bytewidth = 1)
- precon is the previous unfiltered scanline, recon the result, scanline the current one
- the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead
- recon and scanline MAY be the same memory address! precon must be disjoint.
- */
-
- size_t i;
- switch(filterType) {
- case 0:
- for(i = 0; i != length; ++i) recon[i] = scanline[i];
- break;
- case 1:
- for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
- for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth];
- break;
- case 2:
- if(precon) {
- for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i];
- } else {
- for(i = 0; i != length; ++i) recon[i] = scanline[i];
- }
- break;
- case 3:
- if(precon) {
- for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1);
- for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1);
- } else {
- for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i];
- for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1);
- }
- break;
- case 4:
- if(precon) {
- for(i = 0; i != bytewidth; ++i) {
- recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/
- }
- for(i = bytewidth; i < length; ++i) {
- recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth]));
- }
- } else {
- for(i = 0; i != bytewidth; ++i) {
- recon[i] = scanline[i];
- }
- for(i = bytewidth; i < length; ++i) {
- /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/
- recon[i] = (scanline[i] + recon[i - bytewidth]);
- }
- }
- break;
- default: return 36; /*error: unexisting filter type given*/
- }
- return 0;
-}
-
-static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
- /*
- For PNG filter method 0
- this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times)
- out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline
- w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel
- in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes)
- */
-
- unsigned y;
- unsigned char* prevline = 0;
-
- /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
- size_t bytewidth = (bpp + 7) / 8;
- size_t linebytes = (w * bpp + 7) / 8;
-
- for(y = 0; y < h; ++y) {
- size_t outindex = linebytes * y;
- size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
- unsigned char filterType = in[inindex];
-
- CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes));
-
- prevline = &out[outindex];
- }
-
- return 0;
-}
-
-/*
-in: Adam7 interlaced image, with no padding bits between scanlines, but between
- reduced images so that each reduced image starts at a byte.
-out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h
-bpp: bits per pixel
-out has the following size in bits: w * h * bpp.
-in is possibly bigger due to padding bits between reduced images.
-out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation
-(because that's likely a little bit faster)
-NOTE: comments about padding bits are only relevant if bpp < 8
-*/
-static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
- unsigned passw[7], passh[7];
- size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned i;
-
- Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
-
- if(bpp >= 8) {
- for(i = 0; i != 7; ++i) {
- unsigned x, y, b;
- size_t bytewidth = bpp / 8;
- for(y = 0; y < passh[i]; ++y)
- for(x = 0; x < passw[i]; ++x) {
- size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth;
- size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
- for(b = 0; b < bytewidth; ++b) {
- out[pixeloutstart + b] = in[pixelinstart + b];
- }
- }
- }
- } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
- for(i = 0; i != 7; ++i) {
- unsigned x, y, b;
- unsigned ilinebits = bpp * passw[i];
- unsigned olinebits = bpp * w;
- size_t obp, ibp; /*bit pointers (for out and in buffer)*/
- for(y = 0; y < passh[i]; ++y)
- for(x = 0; x < passw[i]; ++x) {
- ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
- obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
- for(b = 0; b < bpp; ++b) {
- unsigned char bit = readBitFromReversedStream(&ibp, in);
- /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/
- setBitOfReversedStream0(&obp, out, bit);
- }
- }
- }
- }
-}
-
-static void removePaddingBits(unsigned char* out, const unsigned char* in,
- size_t olinebits, size_t ilinebits, unsigned h) {
- /*
- After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need
- to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers
- for the Adam7 code, the color convert code and the output to the user.
- in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must
- have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits
- also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7
- only useful if (ilinebits - olinebits) is a value in the range 1..7
- */
- unsigned y;
- size_t diff = ilinebits - olinebits;
- size_t ibp = 0, obp = 0; /*input and output bit pointers*/
- for(y = 0; y < h; ++y) {
- size_t x;
- for(x = 0; x < olinebits; ++x) {
- unsigned char bit = readBitFromReversedStream(&ibp, in);
- setBitOfReversedStream(&obp, out, bit);
- }
- ibp += diff;
- }
-}
-
-/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from
-the IDAT chunks (with filter index bytes and possible padding bits)
-return value is error*/
-static unsigned postProcessScanlines(unsigned char* out, unsigned char* in,
- unsigned w, unsigned h, const LodePNGInfo* info_png) {
- /*
- This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype.
- Steps:
- *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8)
- *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace
- NOTE: the in buffer will be overwritten with intermediate data!
- */
- unsigned bpp = lodepng_get_bpp(&info_png->color);
- if(bpp == 0) return 31; /*error: invalid colortype*/
-
- if(info_png->interlace_method == 0) {
- if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) {
- CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp));
- removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h);
- }
- /*we can immediately filter into the out buffer, no other steps needed*/
- else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp));
- } else /*interlace_method is 1 (Adam7)*/ {
- unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned i;
-
- Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
-
- for(i = 0; i != 7; ++i) {
- CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp));
- /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline,
- move bytes instead of bits or move not at all*/
- if(bpp < 8) {
- /*remove padding bits in scanlines; after this there still may be padding
- bits between the different reduced images: each reduced image still starts nicely at a byte*/
- removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp,
- ((passw[i] * bpp + 7) / 8) * 8, passh[i]);
- }
- }
-
- Adam7_deinterlace(out, in, w, h, bpp);
- }
-
- return 0;
-}
-
-static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
- unsigned pos = 0, i;
- if(color->palette) lodepng_free(color->palette);
- color->palettesize = chunkLength / 3;
- color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize);
- if(!color->palette && color->palettesize) {
- color->palettesize = 0;
- return 83; /*alloc fail*/
- }
- if(color->palettesize > 256) return 38; /*error: palette too big*/
-
- for(i = 0; i != color->palettesize; ++i) {
- color->palette[4 * i + 0] = data[pos++]; /*R*/
- color->palette[4 * i + 1] = data[pos++]; /*G*/
- color->palette[4 * i + 2] = data[pos++]; /*B*/
- color->palette[4 * i + 3] = 255; /*alpha*/
- }
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) {
- unsigned i;
- if(color->colortype == LCT_PALETTE) {
- /*error: more alpha values given than there are palette entries*/
- if(chunkLength > color->palettesize) return 39;
-
- for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i];
- } else if(color->colortype == LCT_GREY) {
- /*error: this chunk must be 2 bytes for grayscale image*/
- if(chunkLength != 2) return 30;
-
- color->key_defined = 1;
- color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1];
- } else if(color->colortype == LCT_RGB) {
- /*error: this chunk must be 6 bytes for RGB image*/
- if(chunkLength != 6) return 41;
-
- color->key_defined = 1;
- color->key_r = 256u * data[0] + data[1];
- color->key_g = 256u * data[2] + data[3];
- color->key_b = 256u * data[4] + data[5];
- }
- else return 42; /*error: tRNS chunk not allowed for other color models*/
-
- return 0; /* OK */
-}
-
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-/*background color chunk (bKGD)*/
-static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(info->color.colortype == LCT_PALETTE) {
- /*error: this chunk must be 1 byte for indexed color image*/
- if(chunkLength != 1) return 43;
-
- /*error: invalid palette index, or maybe this chunk appeared before PLTE*/
- if(data[0] >= info->color.palettesize) return 103;
-
- info->background_defined = 1;
- info->background_r = info->background_g = info->background_b = data[0];
- } else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
- /*error: this chunk must be 2 bytes for grayscale image*/
- if(chunkLength != 2) return 44;
-
- /*the values are truncated to bitdepth in the PNG file*/
- info->background_defined = 1;
- info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1];
- } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
- /*error: this chunk must be 6 bytes for grayscale image*/
- if(chunkLength != 6) return 45;
-
- /*the values are truncated to bitdepth in the PNG file*/
- info->background_defined = 1;
- info->background_r = 256u * data[0] + data[1];
- info->background_g = 256u * data[2] + data[3];
- info->background_b = 256u * data[4] + data[5];
- }
-
- return 0; /* OK */
-}
-
-/*text chunk (tEXt)*/
-static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- unsigned error = 0;
- char *key = 0, *str = 0;
- unsigned i;
-
- while(!error) /*not really a while loop, only used to break on error*/ {
- unsigned length, string2_begin;
-
- length = 0;
- while(length < chunkLength && data[length] != 0) ++length;
- /*even though it's not allowed by the standard, no error is thrown if
- there's no null termination char, if the text is empty*/
- if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
-
- key = (char*)lodepng_malloc(length + 1);
- if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
-
- key[length] = 0;
- for(i = 0; i != length; ++i) key[i] = (char)data[i];
-
- string2_begin = length + 1; /*skip keyword null terminator*/
-
- length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin);
- str = (char*)lodepng_malloc(length + 1);
- if(!str) CERROR_BREAK(error, 83); /*alloc fail*/
-
- str[length] = 0;
- for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i];
-
- error = lodepng_add_text(info, key, str);
-
- break;
- }
-
- lodepng_free(key);
- lodepng_free(str);
-
- return error;
-}
-
-/*compressed text chunk (zTXt)*/
-static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
- const unsigned char* data, size_t chunkLength) {
- unsigned error = 0;
- unsigned i;
-
- unsigned length, string2_begin;
- char *key = 0;
- ucvector decoded;
-
- ucvector_init(&decoded);
-
- while(!error) /*not really a while loop, only used to break on error*/ {
- for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
- if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
- if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
-
- key = (char*)lodepng_malloc(length + 1);
- if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
-
- key[length] = 0;
- for(i = 0; i != length; ++i) key[i] = (char)data[i];
-
- if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
-
- string2_begin = length + 2;
- if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/
-
- length = (unsigned)chunkLength - string2_begin;
- /*will fail if zlib error, e.g. if length is too small*/
- error = zlib_decompress(&decoded.data, &decoded.size,
- (unsigned char*)(&data[string2_begin]),
- length, zlibsettings);
- if(error) break;
- ucvector_push_back(&decoded, 0);
-
- error = lodepng_add_text(info, key, (char*)decoded.data);
-
- break;
- }
-
- lodepng_free(key);
- ucvector_cleanup(&decoded);
-
- return error;
-}
-
-/*international text chunk (iTXt)*/
-static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
- const unsigned char* data, size_t chunkLength) {
- unsigned error = 0;
- unsigned i;
-
- unsigned length, begin, compressed;
- char *key = 0, *langtag = 0, *transkey = 0;
- ucvector decoded;
- ucvector_init(&decoded); /* TODO: only use in case of compressed text */
-
- while(!error) /*not really a while loop, only used to break on error*/ {
- /*Quick check if the chunk length isn't too small. Even without check
- it'd still fail with other error checks below if it's too short. This just gives a different error code.*/
- if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/
-
- /*read the key*/
- for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
- if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/
- if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/
-
- key = (char*)lodepng_malloc(length + 1);
- if(!key) CERROR_BREAK(error, 83); /*alloc fail*/
-
- key[length] = 0;
- for(i = 0; i != length; ++i) key[i] = (char)data[i];
-
- /*read the compression method*/
- compressed = data[length + 1];
- if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/
-
- /*even though it's not allowed by the standard, no error is thrown if
- there's no null termination char, if the text is empty for the next 3 texts*/
-
- /*read the langtag*/
- begin = length + 3;
- length = 0;
- for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
-
- langtag = (char*)lodepng_malloc(length + 1);
- if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/
-
- langtag[length] = 0;
- for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i];
-
- /*read the transkey*/
- begin += length + 1;
- length = 0;
- for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length;
-
- transkey = (char*)lodepng_malloc(length + 1);
- if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/
-
- transkey[length] = 0;
- for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i];
-
- /*read the actual text*/
- begin += length + 1;
-
- length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin;
-
- if(compressed) {
- /*will fail if zlib error, e.g. if length is too small*/
- error = zlib_decompress(&decoded.data, &decoded.size,
- (unsigned char*)(&data[begin]),
- length, zlibsettings);
- if(error) break;
- if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size;
- ucvector_push_back(&decoded, 0);
- } else {
- if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/);
-
- decoded.data[length] = 0;
- for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i];
- }
-
- error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data);
-
- break;
- }
-
- lodepng_free(key);
- lodepng_free(langtag);
- lodepng_free(transkey);
- ucvector_cleanup(&decoded);
-
- return error;
-}
-
-static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(chunkLength != 7) return 73; /*invalid tIME chunk size*/
-
- info->time_defined = 1;
- info->time.year = 256u * data[0] + data[1];
- info->time.month = data[2];
- info->time.day = data[3];
- info->time.hour = data[4];
- info->time.minute = data[5];
- info->time.second = data[6];
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/
-
- info->phys_defined = 1;
- info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
- info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7];
- info->phys_unit = data[8];
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/
-
- info->gama_defined = 1;
- info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3];
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/
-
- info->chrm_defined = 1;
- info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3];
- info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7];
- info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11];
- info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15];
- info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19];
- info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23];
- info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27];
- info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31];
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) {
- if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/
-
- info->srgb_defined = 1;
- info->srgb_intent = data[0];
-
- return 0; /* OK */
-}
-
-static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings,
- const unsigned char* data, size_t chunkLength) {
- unsigned error = 0;
- unsigned i;
-
- unsigned length, string2_begin;
- ucvector decoded;
-
- info->iccp_defined = 1;
- if(info->iccp_name) lodepng_clear_icc(info);
-
- for(length = 0; length < chunkLength && data[length] != 0; ++length) ;
- if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/
- if(length < 1 || length > 79) return 89; /*keyword too short or long*/
-
- info->iccp_name = (char*)lodepng_malloc(length + 1);
- if(!info->iccp_name) return 83; /*alloc fail*/
-
- info->iccp_name[length] = 0;
- for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i];
-
- if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/
-
- string2_begin = length + 2;
- if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/
-
- length = (unsigned)chunkLength - string2_begin;
- ucvector_init(&decoded);
- error = zlib_decompress(&decoded.data, &decoded.size,
- (unsigned char*)(&data[string2_begin]),
- length, zlibsettings);
- if(!error) {
- info->iccp_profile_size = (unsigned int)decoded.size;
- info->iccp_profile = (unsigned char*)lodepng_malloc(decoded.size);
- if(info->iccp_profile) {
- memcpy(info->iccp_profile, decoded.data, decoded.size);
- } else {
- error = 83; /* alloc fail */
- }
- }
- ucvector_cleanup(&decoded);
- return error;
-}
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
- const unsigned char* in, size_t insize) {
- const unsigned char* chunk = in + pos;
- unsigned chunkLength;
- const unsigned char* data;
- unsigned unhandled = 0;
- unsigned error = 0;
-
- if (pos + 4 > insize) return 30;
- chunkLength = lodepng_chunk_length(chunk);
- if(chunkLength > 2147483647) return 63;
- data = lodepng_chunk_data_const(chunk);
- if(data + chunkLength + 4 > in + insize) return 30;
-
- if(lodepng_chunk_type_equals(chunk, "PLTE")) {
- error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
- error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
- error = readChunk_bKGD(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
- error = readChunk_tEXt(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
- error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
- error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
- error = readChunk_tIME(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
- error = readChunk_pHYs(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
- error = readChunk_gAMA(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
- error = readChunk_cHRM(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
- error = readChunk_sRGB(&state->info_png, data, chunkLength);
- } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
- error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- } else {
- /* unhandled chunk is ok (is not an error) */
- unhandled = 1;
- }
-
- if(!error && !unhandled && !state->decoder.ignore_crc) {
- if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/
- }
-
- return error;
-}
-
-/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/
-static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h,
- LodePNGState* state,
- const unsigned char* in, size_t insize) {
- unsigned char IEND = 0;
- const unsigned char* chunk;
- size_t i;
- ucvector idat; /*the data from idat chunks*/
- ucvector scanlines;
- size_t predict;
- size_t outsize = 0;
-
- /*for unknown chunk order*/
- unsigned unknown = 0;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-
- /* safe output values in case error happens */
- *out = 0;
- *w = *h = 0;
-
- state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/
- if(state->error) return;
-
- if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) {
- CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/
- }
-
- ucvector_init(&idat);
- chunk = &in[33]; /*first byte of the first chunk after the header*/
-
- /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk.
- IDAT data is put at the start of the in buffer*/
- while(!IEND && !state->error) {
- unsigned chunkLength;
- const unsigned char* data; /*the data in the chunk*/
-
- /*error: size of the in buffer too small to contain next chunk*/
- if((size_t)((chunk - in) + 12) > insize || chunk < in) {
- if(state->decoder.ignore_end) break; /*other errors may still happen though*/
- CERROR_BREAK(state->error, 30);
- }
-
- /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/
- chunkLength = lodepng_chunk_length(chunk);
- /*error: chunk length larger than the max PNG chunk size*/
- if(chunkLength > 2147483647) {
- if(state->decoder.ignore_end) break; /*other errors may still happen though*/
- CERROR_BREAK(state->error, 63);
- }
-
- if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) {
- CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/
- }
-
- data = lodepng_chunk_data_const(chunk);
-
- unknown = 0;
-
- /*IDAT chunk, containing compressed image data*/
- if(lodepng_chunk_type_equals(chunk, "IDAT")) {
- size_t oldsize = idat.size;
- size_t newsize;
- if(lodepng_addofl(oldsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95);
- if(!ucvector_resize(&idat, newsize)) CERROR_BREAK(state->error, 83 /*alloc fail*/);
- for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i];
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- critical_pos = 3;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- } else if(lodepng_chunk_type_equals(chunk, "IEND")) {
- /*IEND chunk*/
- IEND = 1;
- } else if(lodepng_chunk_type_equals(chunk, "PLTE")) {
- /*palette chunk (PLTE)*/
- state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength);
- if(state->error) break;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- critical_pos = 2;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- } else if(lodepng_chunk_type_equals(chunk, "tRNS")) {
- /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled
- in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that
- affects the alpha channel of pixels. */
- state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength);
- if(state->error) break;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*background color chunk (bKGD)*/
- } else if(lodepng_chunk_type_equals(chunk, "bKGD")) {
- state->error = readChunk_bKGD(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "tEXt")) {
- /*text chunk (tEXt)*/
- if(state->decoder.read_text_chunks) {
- state->error = readChunk_tEXt(&state->info_png, data, chunkLength);
- if(state->error) break;
- }
- } else if(lodepng_chunk_type_equals(chunk, "zTXt")) {
- /*compressed text chunk (zTXt)*/
- if(state->decoder.read_text_chunks) {
- state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
- if(state->error) break;
- }
- } else if(lodepng_chunk_type_equals(chunk, "iTXt")) {
- /*international text chunk (iTXt)*/
- if(state->decoder.read_text_chunks) {
- state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
- if(state->error) break;
- }
- } else if(lodepng_chunk_type_equals(chunk, "tIME")) {
- state->error = readChunk_tIME(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "pHYs")) {
- state->error = readChunk_pHYs(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "gAMA")) {
- state->error = readChunk_gAMA(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "cHRM")) {
- state->error = readChunk_cHRM(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "sRGB")) {
- state->error = readChunk_sRGB(&state->info_png, data, chunkLength);
- if(state->error) break;
- } else if(lodepng_chunk_type_equals(chunk, "iCCP")) {
- state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength);
- if(state->error) break;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- } else /*it's not an implemented chunk type, so ignore it: skip over the data*/ {
- /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/
- if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) {
- CERROR_BREAK(state->error, 69);
- }
-
- unknown = 1;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- if(state->decoder.remember_unknown_chunks) {
- state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1],
- &state->info_png.unknown_chunks_size[critical_pos - 1], chunk);
- if(state->error) break;
- }
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- }
-
- if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ {
- if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/
- }
-
- if(!IEND) chunk = lodepng_chunk_next_const(chunk);
- }
-
- ucvector_init(&scanlines);
- /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation.
- If the decompressed size does not match the prediction, the image must be corrupt.*/
- if(state->info_png.interlace_method == 0) {
- predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color);
- } else {
- /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/
- const LodePNGColorMode* color = &state->info_png.color;
- predict = 0;
- predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color);
- if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color);
- predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color);
- if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color);
- predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color);
- if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color);
- predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color);
- }
- if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/
- if(!state->error) {
- state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data,
- idat.size, &state->decoder.zlibsettings);
- if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/
- }
- ucvector_cleanup(&idat);
-
- if(!state->error) {
- outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);
- *out = (unsigned char*)lodepng_malloc(outsize);
- if(!*out) state->error = 83; /*alloc fail*/
- }
- if(!state->error) {
- for(i = 0; i < outsize; i++) (*out)[i] = 0;
- state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png);
- }
- ucvector_cleanup(&scanlines);
-}
-
-unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
- LodePNGState* state,
- const unsigned char* in, size_t insize) {
- *out = 0;
- decodeGeneric(out, w, h, state, in, insize);
- if(state->error) return state->error;
- if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) {
- /*same color type, no copying or converting of data needed*/
- /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype
- the raw image has to the end user*/
- if(!state->decoder.color_convert) {
- state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color);
- if(state->error) return state->error;
- }
- } else {
- /*color conversion needed; sort of copy of the data*/
- unsigned char* data = *out;
- size_t outsize;
-
- /*TODO: check if this works according to the statement in the documentation: "The converter can convert
- from grayscale input color type, to 8-bit grayscale or grayscale with alpha"*/
- if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA)
- && !(state->info_raw.bitdepth == 8)) {
- return 56; /*unsupported color mode conversion*/
- }
-
- outsize = lodepng_get_raw_size(*w, *h, &state->info_raw);
- *out = (unsigned char*)lodepng_malloc(outsize);
- if(!(*out)) {
- state->error = 83; /*alloc fail*/
- }
- else state->error = lodepng_convert(*out, data, &state->info_raw,
- &state->info_png.color, *w, *h);
- lodepng_free(data);
- }
- return state->error;
-}
-
-unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in,
- size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
- unsigned error;
- LodePNGState state;
- lodepng_state_init(&state);
- state.info_raw.colortype = colortype;
- state.info_raw.bitdepth = bitdepth;
- error = lodepng_decode(out, w, h, &state, in, insize);
- lodepng_state_cleanup(&state);
- return error;
-}
-
-unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
- return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8);
-}
-
-unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) {
- return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8);
-}
-
-#ifdef LODEPNG_COMPILE_DISK
-unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename,
- LodePNGColorType colortype, unsigned bitdepth) {
- unsigned char* buffer = 0;
- size_t buffersize;
- unsigned error;
- /* safe output values in case error happens */
- *out = 0;
- *w = *h = 0;
- error = lodepng_load_file(&buffer, &buffersize, filename);
- if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth);
- lodepng_free(buffer);
- return error;
-}
-
-unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
- return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8);
-}
-
-unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) {
- return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8);
-}
-#endif /*LODEPNG_COMPILE_DISK*/
-
-void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) {
- settings->color_convert = 1;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- settings->read_text_chunks = 1;
- settings->remember_unknown_chunks = 0;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- settings->ignore_crc = 0;
- settings->ignore_critical = 0;
- settings->ignore_end = 0;
- lodepng_decompress_settings_init(&settings->zlibsettings);
-}
-
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
-
-void lodepng_state_init(LodePNGState* state) {
-#ifdef LODEPNG_COMPILE_DECODER
- lodepng_decoder_settings_init(&state->decoder);
-#endif /*LODEPNG_COMPILE_DECODER*/
-#ifdef LODEPNG_COMPILE_ENCODER
- lodepng_encoder_settings_init(&state->encoder);
-#endif /*LODEPNG_COMPILE_ENCODER*/
- lodepng_color_mode_init(&state->info_raw);
- lodepng_info_init(&state->info_png);
- state->error = 1;
-}
-
-void lodepng_state_cleanup(LodePNGState* state) {
- lodepng_color_mode_cleanup(&state->info_raw);
- lodepng_info_cleanup(&state->info_png);
-}
-
-void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) {
- lodepng_state_cleanup(dest);
- *dest = *source;
- lodepng_color_mode_init(&dest->info_raw);
- lodepng_info_init(&dest->info_png);
- dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return;
- dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return;
-}
-
-#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* / PNG Encoder / */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-/*chunkName must be string of 4 characters*/
-static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) {
- CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data));
- out->allocsize = out->size; /*fix the allocsize again*/
- return 0;
-}
-
-static void writeSignature(ucvector* out) {
- /*8 bytes PNG signature, aka the magic bytes*/
- ucvector_push_back(out, 137);
- ucvector_push_back(out, 80);
- ucvector_push_back(out, 78);
- ucvector_push_back(out, 71);
- ucvector_push_back(out, 13);
- ucvector_push_back(out, 10);
- ucvector_push_back(out, 26);
- ucvector_push_back(out, 10);
-}
-
-static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) {
- unsigned error = 0;
- ucvector header;
- ucvector_init(&header);
-
- lodepng_add32bitInt(&header, w); /*width*/
- lodepng_add32bitInt(&header, h); /*height*/
- ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/
- ucvector_push_back(&header, (unsigned char)colortype); /*color type*/
- ucvector_push_back(&header, 0); /*compression method*/
- ucvector_push_back(&header, 0); /*filter method*/
- ucvector_push_back(&header, interlace_method); /*interlace method*/
-
- error = addChunk(out, "IHDR", header.data, header.size);
- ucvector_cleanup(&header);
-
- return error;
-}
-
-static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) {
- unsigned error = 0;
- size_t i;
- ucvector PLTE;
- ucvector_init(&PLTE);
- for(i = 0; i != info->palettesize * 4; ++i) {
- /*add all channels except alpha channel*/
- if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]);
- }
- error = addChunk(out, "PLTE", PLTE.data, PLTE.size);
- ucvector_cleanup(&PLTE);
-
- return error;
-}
-
-static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) {
- unsigned error = 0;
- size_t i;
- ucvector tRNS;
- ucvector_init(&tRNS);
- if(info->colortype == LCT_PALETTE) {
- size_t amount = info->palettesize;
- /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/
- for(i = info->palettesize; i != 0; --i) {
- if(info->palette[4 * (i - 1) + 3] == 255) --amount;
- else break;
- }
- /*add only alpha channel*/
- for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]);
- } else if(info->colortype == LCT_GREY) {
- if(info->key_defined) {
- ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));
- }
- } else if(info->colortype == LCT_RGB) {
- if(info->key_defined) {
- ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8));
- ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255));
- }
- }
-
- error = addChunk(out, "tRNS", tRNS.data, tRNS.size);
- ucvector_cleanup(&tRNS);
-
- return error;
-}
-
-static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize,
- LodePNGCompressSettings* zlibsettings) {
- ucvector zlibdata;
- unsigned error = 0;
-
- /*compress with the Zlib compressor*/
- ucvector_init(&zlibdata);
- error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings);
- if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size);
- ucvector_cleanup(&zlibdata);
-
- return error;
-}
-
-static unsigned addChunk_IEND(ucvector* out) {
- unsigned error = 0;
- error = addChunk(out, "IEND", 0, 0);
- return error;
-}
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-
-static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) {
- unsigned error = 0;
- size_t i;
- ucvector text;
- ucvector_init(&text);
- for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]);
- if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
- ucvector_push_back(&text, 0); /*0 termination char*/
- for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]);
- error = addChunk(out, "tEXt", text.data, text.size);
- ucvector_cleanup(&text);
-
- return error;
-}
-
-static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring,
- LodePNGCompressSettings* zlibsettings) {
- unsigned error = 0;
- ucvector data, compressed;
- size_t i, textsize = strlen(textstring);
-
- ucvector_init(&data);
- ucvector_init(&compressed);
- for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);
- if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
- ucvector_push_back(&data, 0); /*0 termination char*/
- ucvector_push_back(&data, 0); /*compression method: 0*/
-
- error = zlib_compress(&compressed.data, &compressed.size,
- (unsigned char*)textstring, textsize, zlibsettings);
- if(!error) {
- for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);
- error = addChunk(out, "zTXt", data.data, data.size);
- }
-
- ucvector_cleanup(&compressed);
- ucvector_cleanup(&data);
- return error;
-}
-
-static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag,
- const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) {
- unsigned error = 0;
- ucvector data;
- size_t i, textsize = strlen(textstring);
-
- ucvector_init(&data);
-
- for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]);
- if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
- ucvector_push_back(&data, 0); /*null termination char*/
- ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/
- ucvector_push_back(&data, 0); /*compression method*/
- for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]);
- ucvector_push_back(&data, 0); /*null termination char*/
- for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]);
- ucvector_push_back(&data, 0); /*null termination char*/
-
- if(compressed) {
- ucvector compressed_data;
- ucvector_init(&compressed_data);
- error = zlib_compress(&compressed_data.data, &compressed_data.size,
- (unsigned char*)textstring, textsize, zlibsettings);
- if(!error) {
- for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]);
- }
- ucvector_cleanup(&compressed_data);
- } else /*not compressed*/ {
- for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]);
- }
-
- if(!error) error = addChunk(out, "iTXt", data.data, data.size);
- ucvector_cleanup(&data);
- return error;
-}
-
-static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) {
- unsigned error = 0;
- ucvector bKGD;
- ucvector_init(&bKGD);
- if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) {
- ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));
- } else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) {
- ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8));
- ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255));
- } else if(info->color.colortype == LCT_PALETTE) {
- ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/
- }
-
- error = addChunk(out, "bKGD", bKGD.data, bKGD.size);
- ucvector_cleanup(&bKGD);
-
- return error;
-}
-
-static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) {
- unsigned error = 0;
- unsigned char* data = (unsigned char*)lodepng_malloc(7);
- if(!data) return 83; /*alloc fail*/
- data[0] = (unsigned char)(time->year >> 8);
- data[1] = (unsigned char)(time->year & 255);
- data[2] = (unsigned char)time->month;
- data[3] = (unsigned char)time->day;
- data[4] = (unsigned char)time->hour;
- data[5] = (unsigned char)time->minute;
- data[6] = (unsigned char)time->second;
- error = addChunk(out, "tIME", data, 7);
- lodepng_free(data);
- return error;
-}
-
-static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) {
- unsigned error = 0;
- ucvector data;
- ucvector_init(&data);
-
- lodepng_add32bitInt(&data, info->phys_x);
- lodepng_add32bitInt(&data, info->phys_y);
- ucvector_push_back(&data, info->phys_unit);
-
- error = addChunk(out, "pHYs", data.data, data.size);
- ucvector_cleanup(&data);
-
- return error;
-}
-
-static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) {
- unsigned error = 0;
- ucvector data;
- ucvector_init(&data);
-
- lodepng_add32bitInt(&data, info->gama_gamma);
-
- error = addChunk(out, "gAMA", data.data, data.size);
- ucvector_cleanup(&data);
-
- return error;
-}
-
-static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) {
- unsigned error = 0;
- ucvector data;
- ucvector_init(&data);
-
- lodepng_add32bitInt(&data, info->chrm_white_x);
- lodepng_add32bitInt(&data, info->chrm_white_y);
- lodepng_add32bitInt(&data, info->chrm_red_x);
- lodepng_add32bitInt(&data, info->chrm_red_y);
- lodepng_add32bitInt(&data, info->chrm_green_x);
- lodepng_add32bitInt(&data, info->chrm_green_y);
- lodepng_add32bitInt(&data, info->chrm_blue_x);
- lodepng_add32bitInt(&data, info->chrm_blue_y);
-
- error = addChunk(out, "cHRM", data.data, data.size);
- ucvector_cleanup(&data);
-
- return error;
-}
-
-static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) {
- unsigned char data = info->srgb_intent;
- return addChunk(out, "sRGB", &data, 1);
-}
-
-static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) {
- unsigned error = 0;
- ucvector data, compressed;
- size_t i;
-
- ucvector_init(&data);
- ucvector_init(&compressed);
- for(i = 0; info->iccp_name[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)info->iccp_name[i]);
- if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/
- ucvector_push_back(&data, 0); /*0 termination char*/
- ucvector_push_back(&data, 0); /*compression method: 0*/
-
- error = zlib_compress(&compressed.data, &compressed.size,
- info->iccp_profile, info->iccp_profile_size, zlibsettings);
- if(!error) {
- for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]);
- error = addChunk(out, "iCCP", data.data, data.size);
- }
-
- ucvector_cleanup(&compressed);
- ucvector_cleanup(&data);
- return error;
-}
-
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline,
- size_t length, size_t bytewidth, unsigned char filterType) {
- size_t i;
- switch(filterType) {
- case 0: /*None*/
- for(i = 0; i != length; ++i) out[i] = scanline[i];
- break;
- case 1: /*Sub*/
- for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
- for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth];
- break;
- case 2: /*Up*/
- if(prevline) {
- for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i];
- } else {
- for(i = 0; i != length; ++i) out[i] = scanline[i];
- }
- break;
- case 3: /*Average*/
- if(prevline) {
- for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1);
- for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1);
- } else {
- for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
- for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1);
- }
- break;
- case 4: /*Paeth*/
- if(prevline) {
- /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/
- for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]);
- for(i = bytewidth; i < length; ++i) {
- out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth]));
- }
- } else {
- for(i = 0; i != bytewidth; ++i) out[i] = scanline[i];
- /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/
- for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]);
- }
- break;
- default: return; /*unexisting filter type given*/
- }
-}
-
-/* log2 approximation. A slight bit faster than std::log. */
-static float flog2(float f) {
- float result = 0;
- while(f > 32) { result += 4; f /= 16; }
- while(f > 2) { ++result; f /= 2; }
- return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f);
-}
-
-static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h,
- const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) {
- /*
- For PNG filter method 0
- out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are
- the scanlines with 1 extra byte per scanline
- */
-
- unsigned bpp = lodepng_get_bpp(info);
- /*the width of a scanline in bytes, not including the filter type*/
- size_t linebytes = (w * bpp + 7) / 8;
- /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/
- size_t bytewidth = (bpp + 7) / 8;
- const unsigned char* prevline = 0;
- unsigned x, y;
- unsigned error = 0;
- LodePNGFilterStrategy strategy = settings->filter_strategy;
-
- /*
- There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard:
- * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e.
- use fixed filtering, with the filter None).
- * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is
- not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply
- all five filters and select the filter that produces the smallest sum of absolute values per row.
- This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true.
-
- If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed,
- but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum
- heuristic is used.
- */
- if(settings->filter_palette_zero &&
- (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO;
-
- if(bpp == 0) return 31; /*error: invalid color type*/
-
- if(strategy == LFS_ZERO) {
- for(y = 0; y != h; ++y) {
- size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
- size_t inindex = linebytes * y;
- out[outindex] = 0; /*filter type byte*/
- filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0);
- prevline = &in[inindex];
- }
- } else if(strategy == LFS_MINSUM) {
- /*adaptive filtering*/
- size_t sum[5];
- unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
- size_t smallest = 0;
- unsigned char type, bestType = 0;
-
- for(type = 0; type != 5; ++type) {
- attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
- if(!attempt[type]) return 83; /*alloc fail*/
- }
-
- if(!error) {
- for(y = 0; y != h; ++y) {
- /*try the 5 filter types*/
- for(type = 0; type != 5; ++type) {
- filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
-
- /*calculate the sum of the result*/
- sum[type] = 0;
- if(type == 0) {
- for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]);
- } else {
- for(x = 0; x != linebytes; ++x) {
- /*For differences, each byte should be treated as signed, values above 127 are negative
- (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there.
- This means filtertype 0 is almost never chosen, but that is justified.*/
- unsigned char s = attempt[type][x];
- sum[type] += s < 128 ? s : (255U - s);
- }
- }
-
- /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
- if(type == 0 || sum[type] < smallest) {
- bestType = type;
- smallest = sum[type];
- }
- }
-
- prevline = &in[y * linebytes];
-
- /*now fill the out values*/
- out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
- for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
- }
- }
-
- for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
- } else if(strategy == LFS_ENTROPY) {
- float sum[5];
- unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
- float smallest = 0;
- unsigned type, bestType = 0;
- unsigned count[256];
-
- for(type = 0; type != 5; ++type) {
- attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
- if(!attempt[type]) return 83; /*alloc fail*/
- }
-
- for(y = 0; y != h; ++y) {
- /*try the 5 filter types*/
- for(type = 0; type != 5; ++type) {
- filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
- for(x = 0; x != 256; ++x) count[x] = 0;
- for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]];
- ++count[type]; /*the filter type itself is part of the scanline*/
- sum[type] = 0;
- for(x = 0; x != 256; ++x) {
- float p = count[x] / (float)(linebytes + 1);
- sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p;
- }
- /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/
- if(type == 0 || sum[type] < smallest) {
- bestType = type;
- smallest = sum[type];
- }
- }
-
- prevline = &in[y * linebytes];
-
- /*now fill the out values*/
- out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
- for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
- }
-
- for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
- } else if(strategy == LFS_PREDEFINED) {
- for(y = 0; y != h; ++y) {
- size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/
- size_t inindex = linebytes * y;
- unsigned char type = settings->predefined_filters[y];
- out[outindex] = type; /*filter type byte*/
- filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type);
- prevline = &in[inindex];
- }
- } else if(strategy == LFS_BRUTE_FORCE) {
- /*brute force filter chooser.
- deflate the scanline after every filter attempt to see which one deflates best.
- This is very slow and gives only slightly smaller, sometimes even larger, result*/
- size_t size[5];
- unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/
- size_t smallest = 0;
- unsigned type = 0, bestType = 0;
- unsigned char* dummy;
- LodePNGCompressSettings zlibsettings = settings->zlibsettings;
- /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose,
- to simulate the true case where the tree is the same for the whole image. Sometimes it gives
- better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare
- cases better compression. It does make this a bit less slow, so it's worth doing this.*/
- zlibsettings.btype = 1;
- /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG
- images only, so disable it*/
- zlibsettings.custom_zlib = 0;
- zlibsettings.custom_deflate = 0;
- for(type = 0; type != 5; ++type) {
- attempt[type] = (unsigned char*)lodepng_malloc(linebytes);
- if(!attempt[type]) return 83; /*alloc fail*/
- }
- for(y = 0; y != h; ++y) /*try the 5 filter types*/ {
- for(type = 0; type != 5; ++type) {
- unsigned testsize = (unsigned)linebytes;
- /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/
-
- filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type);
- size[type] = 0;
- dummy = 0;
- zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings);
- lodepng_free(dummy);
- /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/
- if(type == 0 || size[type] < smallest) {
- bestType = type;
- smallest = size[type];
- }
- }
- prevline = &in[y * linebytes];
- out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/
- for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x];
- }
- for(type = 0; type != 5; ++type) lodepng_free(attempt[type]);
- }
- else return 88; /* unknown filter strategy */
-
- return error;
-}
-
-static void addPaddingBits(unsigned char* out, const unsigned char* in,
- size_t olinebits, size_t ilinebits, unsigned h) {
- /*The opposite of the removePaddingBits function
- olinebits must be >= ilinebits*/
- unsigned y;
- size_t diff = olinebits - ilinebits;
- size_t obp = 0, ibp = 0; /*bit pointers*/
- for(y = 0; y != h; ++y) {
- size_t x;
- for(x = 0; x < ilinebits; ++x) {
- unsigned char bit = readBitFromReversedStream(&ibp, in);
- setBitOfReversedStream(&obp, out, bit);
- }
- /*obp += diff; --> no, fill in some value in the padding bits too, to avoid
- "Use of uninitialised value of size ###" warning from valgrind*/
- for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0);
- }
-}
-
-/*
-in: non-interlaced image with size w*h
-out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with
- no padding bits between scanlines, but between reduced images so that each
- reduced image starts at a byte.
-bpp: bits per pixel
-there are no padding bits, not between scanlines, not between reduced images
-in has the following size in bits: w * h * bpp.
-out is possibly bigger due to padding bits between reduced images
-NOTE: comments about padding bits are only relevant if bpp < 8
-*/
-static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) {
- unsigned passw[7], passh[7];
- size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned i;
-
- Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
-
- if(bpp >= 8) {
- for(i = 0; i != 7; ++i) {
- unsigned x, y, b;
- size_t bytewidth = bpp / 8;
- for(y = 0; y < passh[i]; ++y)
- for(x = 0; x < passw[i]; ++x) {
- size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth;
- size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth;
- for(b = 0; b < bytewidth; ++b) {
- out[pixeloutstart + b] = in[pixelinstart + b];
- }
- }
- }
- } else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ {
- for(i = 0; i != 7; ++i) {
- unsigned x, y, b;
- unsigned ilinebits = bpp * passw[i];
- unsigned olinebits = bpp * w;
- size_t obp, ibp; /*bit pointers (for out and in buffer)*/
- for(y = 0; y < passh[i]; ++y)
- for(x = 0; x < passw[i]; ++x) {
- ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp;
- obp = (8 * passstart[i]) + (y * ilinebits + x * bpp);
- for(b = 0; b < bpp; ++b) {
- unsigned char bit = readBitFromReversedStream(&ibp, in);
- setBitOfReversedStream(&obp, out, bit);
- }
- }
- }
- }
-}
-
-/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image.
-return value is error**/
-static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in,
- unsigned w, unsigned h,
- const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) {
- /*
- This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps:
- *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter
- *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter
- */
- unsigned bpp = lodepng_get_bpp(&info_png->color);
- unsigned error = 0;
-
- if(info_png->interlace_method == 0) {
- *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/
- *out = (unsigned char*)lodepng_malloc(*outsize);
- if(!(*out) && (*outsize)) error = 83; /*alloc fail*/
-
- if(!error) {
- /*non multiple of 8 bits per scanline, padding bits needed per scanline*/
- if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) {
- unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8));
- if(!padded) error = 83; /*alloc fail*/
- if(!error) {
- addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h);
- error = filter(*out, padded, w, h, &info_png->color, settings);
- }
- lodepng_free(padded);
- } else {
- /*we can immediately filter into the out buffer, no other steps needed*/
- error = filter(*out, in, w, h, &info_png->color, settings);
- }
- }
- } else /*interlace_method is 1 (Adam7)*/ {
- unsigned passw[7], passh[7];
- size_t filter_passstart[8], padded_passstart[8], passstart[8];
- unsigned char* adam7;
-
- Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp);
-
- *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/
- *out = (unsigned char*)lodepng_malloc(*outsize);
- if(!(*out)) error = 83; /*alloc fail*/
-
- adam7 = (unsigned char*)lodepng_malloc(passstart[7]);
- if(!adam7 && passstart[7]) error = 83; /*alloc fail*/
-
- if(!error) {
- unsigned i;
-
- Adam7_interlace(adam7, in, w, h, bpp);
- for(i = 0; i != 7; ++i) {
- if(bpp < 8) {
- unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]);
- if(!padded) ERROR_BREAK(83); /*alloc fail*/
- addPaddingBits(padded, &adam7[passstart[i]],
- ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]);
- error = filter(&(*out)[filter_passstart[i]], padded,
- passw[i], passh[i], &info_png->color, settings);
- lodepng_free(padded);
- } else {
- error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]],
- passw[i], passh[i], &info_png->color, settings);
- }
-
- if(error) break;
- }
- }
-
- lodepng_free(adam7);
- }
-
- return error;
-}
-
-/*
-palette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA...
-returns 0 if the palette is opaque,
-returns 1 if the palette has a single color with alpha 0 ==> color key
-returns 2 if the palette is semi-translucent.
-*/
-static unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize) {
- size_t i;
- unsigned key = 0;
- unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/
- for(i = 0; i != palettesize; ++i) {
- if(!key && palette[4 * i + 3] == 0) {
- r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2];
- key = 1;
- i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/
- }
- else if(palette[4 * i + 3] != 255) return 2;
- /*when key, no opaque RGB may have key's RGB*/
- else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2;
- }
- return key;
-}
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) {
- unsigned char* inchunk = data;
- while((size_t)(inchunk - data) < datasize) {
- CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk));
- out->allocsize = out->size; /*fix the allocsize again*/
- inchunk = lodepng_chunk_next(inchunk);
- }
- return 0;
-}
-
-static unsigned isGrayICCProfile(const unsigned char* profile, unsigned size) {
- /*
- It is a gray profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19
- are "RGB ". We do not perform any full parsing of the ICC profile here, other
- than check those 4 bytes to grayscale profile. Other than that, validity of
- the profile is not checked. This is needed only because the PNG specification
- requires using a non-gray color model if there is an ICC profile with "RGB "
- (sadly limiting compression opportunities if the input data is grayscale RGB
- data), and requires using a gray color model if it is "GRAY".
- */
- if(size < 20) return 0;
- return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y';
-}
-
-static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) {
- /* See comment in isGrayICCProfile*/
- if(size < 20) return 0;
- return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' ';
-}
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-unsigned lodepng_encode(unsigned char** out, size_t* outsize,
- const unsigned char* image, unsigned w, unsigned h,
- LodePNGState* state) {
- unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/
- size_t datasize = 0;
- ucvector outv;
- LodePNGInfo info;
-
- ucvector_init(&outv);
- lodepng_info_init(&info);
-
- /*provide some proper output values if error will happen*/
- *out = 0;
- *outsize = 0;
- state->error = 0;
-
- /*check input values validity*/
- if((state->info_png.color.colortype == LCT_PALETTE || state->encoder.force_palette)
- && (state->info_png.color.palettesize == 0 || state->info_png.color.palettesize > 256)) {
- state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/
- goto cleanup;
- }
- if(state->encoder.zlibsettings.btype > 2) {
- state->error = 61; /*error: unexisting btype*/
- goto cleanup;
- }
- if(state->info_png.interlace_method > 1) {
- state->error = 71; /*error: unexisting interlace mode*/
- goto cleanup;
- }
- state->error = checkColorValidity(state->info_png.color.colortype, state->info_png.color.bitdepth);
- if(state->error) goto cleanup; /*error: unexisting color type given*/
- state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth);
- if(state->error) goto cleanup; /*error: unexisting color type given*/
-
- /* color convert and compute scanline filter types */
- lodepng_info_copy(&info, &state->info_png);
- if(state->encoder.auto_convert) {
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- if(state->info_png.background_defined) {
- unsigned bg_r = state->info_png.background_r;
- unsigned bg_g = state->info_png.background_g;
- unsigned bg_b = state->info_png.background_b;
- unsigned r = 0, g = 0, b = 0;
- LodePNGColorProfile prof;
- LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16);
- lodepng_convert_rgb(&r, &g, &b, bg_r, bg_g, bg_b, &mode16, &state->info_png.color);
- lodepng_color_profile_init(&prof);
- state->error = lodepng_get_color_profile(&prof, image, w, h, &state->info_raw);
- if(state->error) goto cleanup;
- lodepng_color_profile_add(&prof, r, g, b, 65535);
- state->error = auto_choose_color_from_profile(&info.color, &state->info_raw, &prof);
- if(state->error) goto cleanup;
- if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b,
- bg_r, bg_g, bg_b, &info.color, &state->info_png.color)) {
- state->error = 104;
- goto cleanup;
- }
- }
- else
-#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */
- {
- state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw);
- if(state->error) goto cleanup;
- }
- }
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- if(state->info_png.iccp_defined) {
- unsigned gray_icc = isGrayICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size);
- unsigned gray_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA;
- /* TODO: perhaps instead of giving errors or less optimal compression, we can automatically modify
- the ICC profile here to say "GRAY" or "RGB " to match the PNG color type, unless this will require
- non trivial changes to the rest of the ICC profile */
- if(!gray_icc && !isRGBICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size)) {
- state->error = 100; /* Disallowed profile color type for PNG */
- goto cleanup;
- }
- if(!state->encoder.auto_convert && gray_icc != gray_png) {
- /* Non recoverable: encoder not allowed to convert color type, and requested color type not
- compatible with ICC color type */
- state->error = 101;
- goto cleanup;
- }
- if(gray_icc && !gray_png) {
- /* Non recoverable: trying to set grayscale ICC profile while colored pixels were given */
- state->error = 102;
- goto cleanup;
- /* NOTE: this relies on the fact that lodepng_auto_choose_color never returns palette for grayscale pixels */
- }
- if(!gray_icc && gray_png) {
- /* Recoverable but an unfortunate loss in compression density: We have grayscale pixels but
- are forced to store them in more expensive RGB format that will repeat each value 3 times
- because the PNG spec does not allow an RGB ICC profile with internal grayscale color data */
- if(info.color.colortype == LCT_GREY) info.color.colortype = LCT_RGB;
- if(info.color.colortype == LCT_GREY_ALPHA) info.color.colortype = LCT_RGBA;
- if(info.color.bitdepth < 8) info.color.bitdepth = 8;
- }
- }
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) {
- unsigned char* converted;
- size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8;
-
- converted = (unsigned char*)lodepng_malloc(size);
- if(!converted && size) state->error = 83; /*alloc fail*/
- if(!state->error) {
- state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h);
- }
- if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder);
- lodepng_free(converted);
- if(state->error) goto cleanup;
- }
- else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder);
-
- /* output all PNG chunks */ {
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- size_t i;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- /*write signature and chunks*/
- writeSignature(&outv);
- /*IHDR*/
- addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method);
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*unknown chunks between IHDR and PLTE*/
- if(info.unknown_chunks_data[0]) {
- state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]);
- if(state->error) goto cleanup;
- }
- /*color profile chunks must come before PLTE */
- if(info.iccp_defined) addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings);
- if(info.srgb_defined) addChunk_sRGB(&outv, &info);
- if(info.gama_defined) addChunk_gAMA(&outv, &info);
- if(info.chrm_defined) addChunk_cHRM(&outv, &info);
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- /*PLTE*/
- if(info.color.colortype == LCT_PALETTE) {
- addChunk_PLTE(&outv, &info.color);
- }
- if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) {
- addChunk_PLTE(&outv, &info.color);
- }
- /*tRNS*/
- if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0) {
- addChunk_tRNS(&outv, &info.color);
- }
- if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined) {
- addChunk_tRNS(&outv, &info.color);
- }
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*bKGD (must come between PLTE and the IDAt chunks*/
- if(info.background_defined) {
- state->error = addChunk_bKGD(&outv, &info);
- if(state->error) goto cleanup;
- }
- /*pHYs (must come before the IDAT chunks)*/
- if(info.phys_defined) addChunk_pHYs(&outv, &info);
-
- /*unknown chunks between PLTE and IDAT*/
- if(info.unknown_chunks_data[1]) {
- state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]);
- if(state->error) goto cleanup;
- }
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- /*IDAT (multiple IDAT chunks must be consecutive)*/
- state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings);
- if(state->error) goto cleanup;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*tIME*/
- if(info.time_defined) addChunk_tIME(&outv, &info.time);
- /*tEXt and/or zTXt*/
- for(i = 0; i != info.text_num; ++i) {
- if(strlen(info.text_keys[i]) > 79) {
- state->error = 66; /*text chunk too large*/
- goto cleanup;
- }
- if(strlen(info.text_keys[i]) < 1) {
- state->error = 67; /*text chunk too small*/
- goto cleanup;
- }
- if(state->encoder.text_compression) {
- addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings);
- } else {
- addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]);
- }
- }
- /*LodePNG version id in text chunk*/
- if(state->encoder.add_id) {
- unsigned already_added_id_text = 0;
- for(i = 0; i != info.text_num; ++i) {
- if(!strcmp(info.text_keys[i], "LodePNG")) {
- already_added_id_text = 1;
- break;
- }
- }
- if(already_added_id_text == 0) {
- addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
- }
- }
- /*iTXt*/
- for(i = 0; i != info.itext_num; ++i) {
- if(strlen(info.itext_keys[i]) > 79) {
- state->error = 66; /*text chunk too large*/
- goto cleanup;
- }
- if(strlen(info.itext_keys[i]) < 1) {
- state->error = 67; /*text chunk too small*/
- goto cleanup;
- }
- addChunk_iTXt(&outv, state->encoder.text_compression,
- info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i],
- &state->encoder.zlibsettings);
- }
-
- /*unknown chunks between IDAT and IEND*/
- if(info.unknown_chunks_data[2]) {
- state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]);
- if(state->error) goto cleanup;
- }
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
- addChunk_IEND(&outv);
- }
-
-cleanup:
- lodepng_info_cleanup(&info);
- lodepng_free(data);
-
- /*instead of cleaning the vector up, give it to the output*/
- *out = outv.data;
- *outsize = outv.size;
-
- return state->error;
-}
-
-unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image,
- unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) {
- unsigned error;
- LodePNGState state;
- lodepng_state_init(&state);
- state.info_raw.colortype = colortype;
- state.info_raw.bitdepth = bitdepth;
- state.info_png.color.colortype = colortype;
- state.info_png.color.bitdepth = bitdepth;
- lodepng_encode(out, outsize, image, w, h, &state);
- error = state.error;
- lodepng_state_cleanup(&state);
- return error;
-}
-
-unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
- return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8);
-}
-
-unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) {
- return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8);
-}
-
-#ifdef LODEPNG_COMPILE_DISK
-unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth) {
- unsigned char* buffer;
- size_t buffersize;
- unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth);
- if(!error) error = lodepng_save_file(buffer, buffersize, filename);
- lodepng_free(buffer);
- return error;
-}
-
-unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
- return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8);
-}
-
-unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) {
- return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8);
-}
-#endif /*LODEPNG_COMPILE_DISK*/
-
-void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) {
- lodepng_compress_settings_init(&settings->zlibsettings);
- settings->filter_palette_zero = 1;
- settings->filter_strategy = LFS_MINSUM;
- settings->auto_convert = 1;
- settings->force_palette = 0;
- settings->predefined_filters = 0;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- settings->add_id = 0;
- settings->text_compression = 1;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-}
-
-#endif /*LODEPNG_COMPILE_ENCODER*/
-#endif /*LODEPNG_COMPILE_PNG*/
-
-#ifdef LODEPNG_COMPILE_ERROR_TEXT
-/*
-This returns the description of a numerical error code in English. This is also
-the documentation of all the error codes.
-*/
-const char* lodepng_error_text(unsigned code) {
- switch(code) {
- case 0: return "no error, everything went ok";
- case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/
- case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/
- case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/
- case 13: return "problem while processing dynamic deflate block";
- case 14: return "problem while processing dynamic deflate block";
- case 15: return "problem while processing dynamic deflate block";
- case 16: return "unexisting code while processing dynamic deflate block";
- case 17: return "end of out buffer memory reached while inflating";
- case 18: return "invalid distance code while inflating";
- case 19: return "end of out buffer memory reached while inflating";
- case 20: return "invalid deflate block BTYPE encountered while decoding";
- case 21: return "NLEN is not ones complement of LEN in a deflate block";
-
- /*end of out buffer memory reached while inflating:
- This can happen if the inflated deflate data is longer than the amount of bytes required to fill up
- all the pixels of the image, given the color depth and image dimensions. Something that doesn't
- happen in a normal, well encoded, PNG image.*/
- case 22: return "end of out buffer memory reached while inflating";
- case 23: return "end of in buffer memory reached while inflating";
- case 24: return "invalid FCHECK in zlib header";
- case 25: return "invalid compression method in zlib header";
- case 26: return "FDICT encountered in zlib header while it's not used for PNG";
- case 27: return "PNG file is smaller than a PNG header";
- /*Checks the magic file header, the first 8 bytes of the PNG file*/
- case 28: return "incorrect PNG signature, it's no PNG or corrupted";
- case 29: return "first chunk is not the header chunk";
- case 30: return "chunk length too large, chunk broken off at end of file";
- case 31: return "illegal PNG color type or bpp";
- case 32: return "illegal PNG compression method";
- case 33: return "illegal PNG filter method";
- case 34: return "illegal PNG interlace method";
- case 35: return "chunk length of a chunk is too large or the chunk too small";
- case 36: return "illegal PNG filter type encountered";
- case 37: return "illegal bit depth for this color type given";
- case 38: return "the palette is too big"; /*more than 256 colors*/
- case 39: return "tRNS chunk before PLTE or has more entries than palette size";
- case 40: return "tRNS chunk has wrong size for grayscale image";
- case 41: return "tRNS chunk has wrong size for RGB image";
- case 42: return "tRNS chunk appeared while it was not allowed for this color type";
- case 43: return "bKGD chunk has wrong size for palette image";
- case 44: return "bKGD chunk has wrong size for grayscale image";
- case 45: return "bKGD chunk has wrong size for RGB image";
- case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?";
- case 49: return "jumped past memory while generating dynamic huffman tree";
- case 50: return "jumped past memory while generating dynamic huffman tree";
- case 51: return "jumped past memory while inflating huffman block";
- case 52: return "jumped past memory while inflating";
- case 53: return "size of zlib data too small";
- case 54: return "repeat symbol in tree while there was no value symbol yet";
- /*jumped past tree while generating huffman tree, this could be when the
- tree will have more leaves than symbols after generating it out of the
- given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/
- case 55: return "jumped past tree while generating huffman tree";
- case 56: return "given output image colortype or bitdepth not supported for color conversion";
- case 57: return "invalid CRC encountered (checking CRC can be disabled)";
- case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)";
- case 59: return "requested color conversion not supported";
- case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)";
- case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)";
- /*LodePNG leaves the choice of RGB to grayscale conversion formula to the user.*/
- case 62: return "conversion from color to grayscale not supported";
- /*(2^31-1)*/
- case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk";
- /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/
- case 64: return "the length of the END symbol 256 in the Huffman tree is 0";
- case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes";
- case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte";
- case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors";
- case 69: return "unknown chunk type with 'critical' flag encountered by the decoder";
- case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)";
- case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)";
- case 73: return "invalid tIME chunk size";
- case 74: return "invalid pHYs chunk size";
- /*length could be wrong, or data chopped off*/
- case 75: return "no null termination char found while decoding text chunk";
- case 76: return "iTXt chunk too short to contain required bytes";
- case 77: return "integer overflow in buffer size";
- case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/
- case 79: return "failed to open file for writing";
- case 80: return "tried creating a tree of 0 symbols";
- case 81: return "lazy matching at pos 0 is impossible";
- case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds";
- case 83: return "memory allocation failed";
- case 84: return "given image too small to contain all pixels to be encoded";
- case 86: return "impossible offset in lz77 encoding (internal bug)";
- case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined";
- case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy";
- case 89: return "text chunk keyword too short or long: must have size 1-79";
- /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/
- case 90: return "windowsize must be a power of two";
- case 91: return "invalid decompressed idat size";
- case 92: return "integer overflow due to too many pixels";
- case 93: return "zero width or height is invalid";
- case 94: return "header chunk must have a size of 13 bytes";
- case 95: return "integer overflow with combined idat chunk size";
- case 96: return "invalid gAMA chunk size";
- case 97: return "invalid cHRM chunk size";
- case 98: return "invalid sRGB chunk size";
- case 99: return "invalid sRGB rendering intent";
- case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY";
- case 101: return "PNG specification does not allow RGB ICC profile on gray color types and vice versa";
- case 102: return "not allowed to set grayscale ICC profile with colored pixels by PNG specification";
- case 103: return "invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?";
- case 104: return "invalid bKGD color while encoding (e.g. palette index out of range)";
- }
- return "unknown error code";
-}
-#endif /*LODEPNG_COMPILE_ERROR_TEXT*/
-
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* // C++ Wrapper // */
-/* ////////////////////////////////////////////////////////////////////////// */
-/* ////////////////////////////////////////////////////////////////////////// */
-
-#ifdef LODEPNG_COMPILE_CPP
-namespace lodepng {
-
-#ifdef LODEPNG_COMPILE_DISK
-unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename) {
- long size = lodepng_filesize(filename.c_str());
- if(size < 0) return 78;
- buffer.resize((size_t)size);
- return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str());
-}
-
-/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
-unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename) {
- return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str());
-}
-#endif /* LODEPNG_COMPILE_DISK */
-
-#ifdef LODEPNG_COMPILE_ZLIB
-#ifdef LODEPNG_COMPILE_DECODER
-unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings& settings) {
- unsigned char* buffer = 0;
- size_t buffersize = 0;
- unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings);
- if(buffer) {
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- lodepng_free(buffer);
- }
- return error;
-}
-
-unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
- const LodePNGDecompressSettings& settings) {
- return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings);
-}
-#endif /* LODEPNG_COMPILE_DECODER */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
- const LodePNGCompressSettings& settings) {
- unsigned char* buffer = 0;
- size_t buffersize = 0;
- unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings);
- if(buffer) {
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- lodepng_free(buffer);
- }
- return error;
-}
-
-unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
- const LodePNGCompressSettings& settings) {
- return compress(out, in.empty() ? 0 : &in[0], in.size(), settings);
-}
-#endif /* LODEPNG_COMPILE_ENCODER */
-#endif /* LODEPNG_COMPILE_ZLIB */
-
-
-#ifdef LODEPNG_COMPILE_PNG
-
-State::State() {
- lodepng_state_init(this);
-}
-
-State::State(const State& other) {
- lodepng_state_init(this);
- lodepng_state_copy(this, &other);
-}
-
-State::~State() {
- lodepng_state_cleanup(this);
-}
-
-State& State::operator=(const State& other) {
- lodepng_state_copy(this, &other);
- return *this;
-}
-
-#ifdef LODEPNG_COMPILE_DECODER
-
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const unsigned char* in,
- size_t insize, LodePNGColorType colortype, unsigned bitdepth) {
- unsigned char* buffer;
- unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth);
- if(buffer && !error) {
- State state;
- state.info_raw.colortype = colortype;
- state.info_raw.bitdepth = bitdepth;
- size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- lodepng_free(buffer);
- }
- return error;
-}
-
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- const std::vector<unsigned char>& in, LodePNGColorType colortype, unsigned bitdepth) {
- return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth);
-}
-
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- State& state,
- const unsigned char* in, size_t insize) {
- unsigned char* buffer = NULL;
- unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize);
- if(buffer && !error) {
- size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw);
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- }
- lodepng_free(buffer);
- return error;
-}
-
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- State& state,
- const std::vector<unsigned char>& in) {
- return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size());
-}
-
-#ifdef LODEPNG_COMPILE_DISK
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h, const std::string& filename,
- LodePNGColorType colortype, unsigned bitdepth) {
- std::vector<unsigned char> buffer;
- /* safe output values in case error happens */
- w = h = 0;
- unsigned error = load_file(buffer, filename);
- if(error) return error;
- return decode(out, w, h, buffer, colortype, bitdepth);
-}
-#endif /* LODEPNG_COMPILE_DECODER */
-#endif /* LODEPNG_COMPILE_DISK */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-unsigned encode(std::vector<unsigned char>& out, const unsigned char* in, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth) {
- unsigned char* buffer;
- size_t buffersize;
- unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth);
- if(buffer) {
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- lodepng_free(buffer);
- }
- return error;
-}
-
-unsigned encode(std::vector<unsigned char>& out,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth) {
- if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
- return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
-}
-
-unsigned encode(std::vector<unsigned char>& out,
- const unsigned char* in, unsigned w, unsigned h,
- State& state) {
- unsigned char* buffer;
- size_t buffersize;
- unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state);
- if(buffer) {
- out.insert(out.end(), &buffer[0], &buffer[buffersize]);
- lodepng_free(buffer);
- }
- return error;
-}
-
-unsigned encode(std::vector<unsigned char>& out,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- State& state) {
- if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84;
- return encode(out, in.empty() ? 0 : &in[0], w, h, state);
-}
-
-#ifdef LODEPNG_COMPILE_DISK
-unsigned encode(const std::string& filename,
- const unsigned char* in, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth) {
- std::vector<unsigned char> buffer;
- unsigned error = encode(buffer, in, w, h, colortype, bitdepth);
- if(!error) error = save_file(buffer, filename);
- return error;
-}
-
-unsigned encode(const std::string& filename,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth) {
- if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84;
- return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth);
-}
-#endif /* LODEPNG_COMPILE_DISK */
-#endif /* LODEPNG_COMPILE_ENCODER */
-#endif /* LODEPNG_COMPILE_PNG */
-} /* namespace lodepng */
-#endif /*LODEPNG_COMPILE_CPP*/
diff --git a/thirdparty/basis_universal/encoder/lodepng.h b/thirdparty/basis_universal/encoder/lodepng.h
deleted file mode 100644
index 476a2061e2..0000000000
--- a/thirdparty/basis_universal/encoder/lodepng.h
+++ /dev/null
@@ -1,1930 +0,0 @@
-/*
-LodePNG version 20190210
-
-Copyright (c) 2005-2019 Lode Vandevenne
-
-This software is provided 'as-is', without any express or implied
-warranty. In no event will the authors be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
-
- 3. This notice may not be removed or altered from any source
- distribution.
-*/
-
-#ifndef LODEPNG_H
-#define LODEPNG_H
-
-#include <string.h> /*for size_t*/
-
-extern const char* LODEPNG_VERSION_STRING;
-
-/*
-The following #defines are used to create code sections. They can be disabled
-to disable code sections, which can give faster compile time and smaller binary.
-The "NO_COMPILE" defines are designed to be used to pass as defines to the
-compiler command to disable them without modifying this header, e.g.
--DLODEPNG_NO_COMPILE_ZLIB for gcc.
-In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to
-allow implementing a custom lodepng_crc32.
-*/
-/*deflate & zlib. If disabled, you must specify alternative zlib functions in
-the custom_zlib field of the compress and decompress settings*/
-#ifndef LODEPNG_NO_COMPILE_ZLIB
-#define LODEPNG_COMPILE_ZLIB
-#endif
-
-/*png encoder and png decoder*/
-#ifndef LODEPNG_NO_COMPILE_PNG
-#define LODEPNG_COMPILE_PNG
-#endif
-
-/*deflate&zlib decoder and png decoder*/
-#ifndef LODEPNG_NO_COMPILE_DECODER
-#define LODEPNG_COMPILE_DECODER
-#endif
-
-/*deflate&zlib encoder and png encoder*/
-#ifndef LODEPNG_NO_COMPILE_ENCODER
-#define LODEPNG_COMPILE_ENCODER
-#endif
-
-/*the optional built in harddisk file loading and saving functions*/
-#ifndef LODEPNG_NO_COMPILE_DISK
-#define LODEPNG_COMPILE_DISK
-#endif
-
-/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/
-#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS
-#define LODEPNG_COMPILE_ANCILLARY_CHUNKS
-#endif
-
-/*ability to convert error numerical codes to English text string*/
-#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT
-#define LODEPNG_COMPILE_ERROR_TEXT
-#endif
-
-/*Compile the default allocators (C's free, malloc and realloc). If you disable this,
-you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your
-source files with custom allocators.*/
-#ifndef LODEPNG_NO_COMPILE_ALLOCATORS
-#define LODEPNG_COMPILE_ALLOCATORS
-#endif
-
-/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/
-#ifdef __cplusplus
-#ifndef LODEPNG_NO_COMPILE_CPP
-#define LODEPNG_COMPILE_CPP
-#endif
-#endif
-
-#ifdef LODEPNG_COMPILE_CPP
-#include <vector>
-#include <string>
-#endif /*LODEPNG_COMPILE_CPP*/
-
-#ifdef LODEPNG_COMPILE_PNG
-/*The PNG color types (also used for raw).*/
-typedef enum LodePNGColorType {
- LCT_GREY = 0, /*grayscale: 1,2,4,8,16 bit*/
- LCT_RGB = 2, /*RGB: 8,16 bit*/
- LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/
- LCT_GREY_ALPHA = 4, /*grayscale with alpha: 8,16 bit*/
- LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/
-} LodePNGColorType;
-
-#ifdef LODEPNG_COMPILE_DECODER
-/*
-Converts PNG data in memory to raw pixel data.
-out: Output parameter. Pointer to buffer that will contain the raw pixel data.
- After decoding, its size is w * h * (bytes per pixel) bytes larger than
- initially. Bytes per pixel depends on colortype and bitdepth.
- Must be freed after usage with free(*out).
- Note: for 16-bit per channel colors, uses big endian format like PNG does.
-w: Output parameter. Pointer to width of pixel data.
-h: Output parameter. Pointer to height of pixel data.
-in: Memory buffer with the PNG file.
-insize: size of the in buffer.
-colortype: the desired color type for the raw output image. See explanation on PNG color types.
-bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types.
-Return value: LodePNG error code (0 means no error).
-*/
-unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h,
- const unsigned char* in, size_t insize,
- LodePNGColorType colortype, unsigned bitdepth);
-
-/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/
-unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h,
- const unsigned char* in, size_t insize);
-
-/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/
-unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h,
- const unsigned char* in, size_t insize);
-
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Load PNG from disk, from file with given name.
-Same as the other decode functions, but instead takes a filename as input.
-*/
-unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h,
- const char* filename,
- LodePNGColorType colortype, unsigned bitdepth);
-
-/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/
-unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h,
- const char* filename);
-
-/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/
-unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h,
- const char* filename);
-#endif /*LODEPNG_COMPILE_DISK*/
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*
-Converts raw pixel data into a PNG image in memory. The colortype and bitdepth
- of the output PNG image cannot be chosen, they are automatically determined
- by the colortype, bitdepth and content of the input pixel data.
- Note: for 16-bit per channel colors, needs big endian format like PNG does.
-out: Output parameter. Pointer to buffer that will contain the PNG image data.
- Must be freed after usage with free(*out).
-outsize: Output parameter. Pointer to the size in bytes of the out buffer.
-image: The raw pixel data to encode. The size of this buffer should be
- w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth.
-w: width of the raw pixel data in pixels.
-h: height of the raw pixel data in pixels.
-colortype: the color type of the raw input image. See explanation on PNG color types.
-bitdepth: the bit depth of the raw input image. See explanation on PNG color types.
-Return value: LodePNG error code (0 means no error).
-*/
-unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize,
- const unsigned char* image, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth);
-
-/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/
-unsigned lodepng_encode32(unsigned char** out, size_t* outsize,
- const unsigned char* image, unsigned w, unsigned h);
-
-/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/
-unsigned lodepng_encode24(unsigned char** out, size_t* outsize,
- const unsigned char* image, unsigned w, unsigned h);
-
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Converts raw pixel data into a PNG file on disk.
-Same as the other encode functions, but instead takes a filename as output.
-NOTE: This overwrites existing files without warning!
-*/
-unsigned lodepng_encode_file(const char* filename,
- const unsigned char* image, unsigned w, unsigned h,
- LodePNGColorType colortype, unsigned bitdepth);
-
-/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/
-unsigned lodepng_encode32_file(const char* filename,
- const unsigned char* image, unsigned w, unsigned h);
-
-/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/
-unsigned lodepng_encode24_file(const char* filename,
- const unsigned char* image, unsigned w, unsigned h);
-#endif /*LODEPNG_COMPILE_DISK*/
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-
-#ifdef LODEPNG_COMPILE_CPP
-namespace lodepng {
-#ifdef LODEPNG_COMPILE_DECODER
-/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype
-is the format to output the pixels to. Default is RGBA 8-bit per channel.*/
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- const unsigned char* in, size_t insize,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- const std::vector<unsigned char>& in,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Converts PNG file from disk to raw pixel data in memory.
-Same as the other decode functions, but instead takes a filename as input.
-*/
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- const std::string& filename,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-#endif /* LODEPNG_COMPILE_DISK */
-#endif /* LODEPNG_COMPILE_DECODER */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype
-is that of the raw input data. The output PNG color type will be auto chosen.*/
-unsigned encode(std::vector<unsigned char>& out,
- const unsigned char* in, unsigned w, unsigned h,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-unsigned encode(std::vector<unsigned char>& out,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Converts 32-bit RGBA raw pixel data into a PNG file on disk.
-Same as the other encode functions, but instead takes a filename as output.
-NOTE: This overwrites existing files without warning!
-*/
-unsigned encode(const std::string& filename,
- const unsigned char* in, unsigned w, unsigned h,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-unsigned encode(const std::string& filename,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8);
-#endif /* LODEPNG_COMPILE_DISK */
-#endif /* LODEPNG_COMPILE_ENCODER */
-} /* namespace lodepng */
-#endif /*LODEPNG_COMPILE_CPP*/
-#endif /*LODEPNG_COMPILE_PNG*/
-
-#ifdef LODEPNG_COMPILE_ERROR_TEXT
-/*Returns an English description of the numerical error code.*/
-const char* lodepng_error_text(unsigned code);
-#endif /*LODEPNG_COMPILE_ERROR_TEXT*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-/*Settings for zlib decompression*/
-typedef struct LodePNGDecompressSettings LodePNGDecompressSettings;
-struct LodePNGDecompressSettings {
- /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */
- unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/
-
- /*use custom zlib decoder instead of built in one (default: null)*/
- unsigned (*custom_zlib)(unsigned char**, size_t*,
- const unsigned char*, size_t,
- const LodePNGDecompressSettings*);
- /*use custom deflate decoder instead of built in one (default: null)
- if custom_zlib is used, custom_deflate is ignored since only the built in
- zlib function will call custom_deflate*/
- unsigned (*custom_inflate)(unsigned char**, size_t*,
- const unsigned char*, size_t,
- const LodePNGDecompressSettings*);
-
- const void* custom_context; /*optional custom settings for custom functions*/
-};
-
-extern const LodePNGDecompressSettings lodepng_default_decompress_settings;
-void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings);
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*
-Settings for zlib compression. Tweaking these settings tweaks the balance
-between speed and compression ratio.
-*/
-typedef struct LodePNGCompressSettings LodePNGCompressSettings;
-struct LodePNGCompressSettings /*deflate = compress*/ {
- /*LZ77 related settings*/
- unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/
- unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/
- unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/
- unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/
- unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/
- unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/
-
- /*use custom zlib encoder instead of built in one (default: null)*/
- unsigned (*custom_zlib)(unsigned char**, size_t*,
- const unsigned char*, size_t,
- const LodePNGCompressSettings*);
- /*use custom deflate encoder instead of built in one (default: null)
- if custom_zlib is used, custom_deflate is ignored since only the built in
- zlib function will call custom_deflate*/
- unsigned (*custom_deflate)(unsigned char**, size_t*,
- const unsigned char*, size_t,
- const LodePNGCompressSettings*);
-
- const void* custom_context; /*optional custom settings for custom functions*/
-};
-
-extern const LodePNGCompressSettings lodepng_default_compress_settings;
-void lodepng_compress_settings_init(LodePNGCompressSettings* settings);
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#ifdef LODEPNG_COMPILE_PNG
-/*
-Color mode of an image. Contains all information required to decode the pixel
-bits to RGBA colors. This information is the same as used in the PNG file
-format, and is used both for PNG and raw image data in LodePNG.
-*/
-typedef struct LodePNGColorMode {
- /*header (IHDR)*/
- LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/
- unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/
-
- /*
- palette (PLTE and tRNS)
-
- Dynamically allocated with the colors of the palette, including alpha.
- When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use
- lodepng_palette_clear, then for each color use lodepng_palette_add.
- If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette.
-
- When decoding, by default you can ignore this palette, since LodePNG already
- fills the palette colors in the pixels of the raw RGBA output.
-
- The palette is only supported for color type 3.
- */
- unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/
- size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/
-
- /*
- transparent color key (tRNS)
-
- This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit.
- For grayscale PNGs, r, g and b will all 3 be set to the same.
-
- When decoding, by default you can ignore this information, since LodePNG sets
- pixels with this key to transparent already in the raw RGBA output.
-
- The color key is only supported for color types 0 and 2.
- */
- unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/
- unsigned key_r; /*red/grayscale component of color key*/
- unsigned key_g; /*green component of color key*/
- unsigned key_b; /*blue component of color key*/
-} LodePNGColorMode;
-
-/*init, cleanup and copy functions to use with this struct*/
-void lodepng_color_mode_init(LodePNGColorMode* info);
-void lodepng_color_mode_cleanup(LodePNGColorMode* info);
-/*return value is error code (0 means no error)*/
-unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source);
-/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */
-LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth);
-
-void lodepng_palette_clear(LodePNGColorMode* info);
-/*add 1 color to the palette*/
-unsigned lodepng_palette_add(LodePNGColorMode* info,
- unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-
-/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/
-unsigned lodepng_get_bpp(const LodePNGColorMode* info);
-/*get the amount of color channels used, based on colortype in the struct.
-If a palette is used, it counts as 1 channel.*/
-unsigned lodepng_get_channels(const LodePNGColorMode* info);
-/*is it a grayscale type? (only colortype 0 or 4)*/
-unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info);
-/*has it got an alpha channel? (only colortype 2 or 6)*/
-unsigned lodepng_is_alpha_type(const LodePNGColorMode* info);
-/*has it got a palette? (only colortype 3)*/
-unsigned lodepng_is_palette_type(const LodePNGColorMode* info);
-/*only returns true if there is a palette and there is a value in the palette with alpha < 255.
-Loops through the palette to check this.*/
-unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info);
-/*
-Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image.
-Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels).
-Returns false if the image can only have opaque pixels.
-In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values,
-or if "key_defined" is true.
-*/
-unsigned lodepng_can_have_alpha(const LodePNGColorMode* info);
-/*Returns the byte size of a raw image buffer with given width, height and color mode*/
-size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color);
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-/*The information of a Time chunk in PNG.*/
-typedef struct LodePNGTime {
- unsigned year; /*2 bytes used (0-65535)*/
- unsigned month; /*1-12*/
- unsigned day; /*1-31*/
- unsigned hour; /*0-23*/
- unsigned minute; /*0-59*/
- unsigned second; /*0-60 (to allow for leap seconds)*/
-} LodePNGTime;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-/*Information about the PNG image, except pixels, width and height.*/
-typedef struct LodePNGInfo {
- /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/
- unsigned compression_method;/*compression method of the original file. Always 0.*/
- unsigned filter_method; /*filter method of the original file*/
- unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/
- LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*
- Suggested background color chunk (bKGD)
-
- This uses the same color mode and bit depth as the PNG (except no alpha channel),
- with values truncated to the bit depth in the unsigned integer.
-
- For grayscale and palette PNGs, the value is stored in background_r. The values
- in background_g and background_b are then unused.
-
- So when decoding, you may get these in a different color mode than the one you requested
- for the raw pixels.
-
- When encoding with auto_convert, you must use the color model defined in info_png.color for
- these values. The encoder normally ignores info_png.color when auto_convert is on, but will
- use it to interpret these values (and convert copies of them to its chosen color model).
-
- When encoding, avoid setting this to an expensive color, such as a non-gray value
- when the image is gray, or the compression will be worse since it will be forced to
- write the PNG with a more expensive color mode (when auto_convert is on).
-
- The decoder does not use this background color to edit the color of pixels. This is a
- completely optional metadata feature.
- */
- unsigned background_defined; /*is a suggested background color given?*/
- unsigned background_r; /*red/gray/palette component of suggested background color*/
- unsigned background_g; /*green component of suggested background color*/
- unsigned background_b; /*blue component of suggested background color*/
-
- /*
- non-international text chunks (tEXt and zTXt)
-
- The char** arrays each contain num strings. The actual messages are in
- text_strings, while text_keys are keywords that give a short description what
- the actual text represents, e.g. Title, Author, Description, or anything else.
-
- All the string fields below including keys, names and language tags are null terminated.
- The PNG specification uses null characters for the keys, names and tags, and forbids null
- characters to appear in the main text which is why we can use null termination everywhere here.
-
- A keyword is minimum 1 character and maximum 79 characters long. It's
- discouraged to use a single line length longer than 79 characters for texts.
-
- Don't allocate these text buffers yourself. Use the init/cleanup functions
- correctly and use lodepng_add_text and lodepng_clear_text.
- */
- size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/
- char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/
- char** text_strings; /*the actual text*/
-
- /*
- international text chunks (iTXt)
- Similar to the non-international text chunks, but with additional strings
- "langtags" and "transkeys".
- */
- size_t itext_num; /*the amount of international texts in this PNG*/
- char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/
- char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/
- char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/
- char** itext_strings; /*the actual international text - UTF-8 string*/
-
- /*time chunk (tIME)*/
- unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/
- LodePNGTime time;
-
- /*phys chunk (pHYs)*/
- unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/
- unsigned phys_x; /*pixels per unit in x direction*/
- unsigned phys_y; /*pixels per unit in y direction*/
- unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/
-
- /*
- Color profile related chunks: gAMA, cHRM, sRGB, iCPP
-
- LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color
- profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please
- use these values with a color management library.
-
- See the PNG, ICC and sRGB specifications for more information about the meaning of these values.
- */
-
- /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */
- unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */
- unsigned gama_gamma; /* Gamma exponent times 100000 */
-
- /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */
- unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */
- unsigned chrm_white_x; /* White Point x times 100000 */
- unsigned chrm_white_y; /* White Point y times 100000 */
- unsigned chrm_red_x; /* Red x times 100000 */
- unsigned chrm_red_y; /* Red y times 100000 */
- unsigned chrm_green_x; /* Green x times 100000 */
- unsigned chrm_green_y; /* Green y times 100000 */
- unsigned chrm_blue_x; /* Blue x times 100000 */
- unsigned chrm_blue_y; /* Blue y times 100000 */
-
- /*
- sRGB chunk: optional. May not appear at the same time as iCCP.
- If gAMA is also present gAMA must contain value 45455.
- If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000.
- */
- unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */
- unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */
-
- /*
- iCCP chunk: optional. May not appear at the same time as sRGB.
-
- LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a
- separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color
- management and conversions.
-
- For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC
- profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and
- enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile.
-
- For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-gray
- PNG color types and a "GRAY" profile for gray PNG color types. If you disable auto_convert, you must ensure
- the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is
- enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder
- error if the pixel data has non-gray pixels for a GRAY profile, or a silent less-optimal compression of the pixel
- data if the pixels could be encoded as grayscale but the ICC profile is RGB.
-
- To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so
- make sure you compute it carefully to avoid the above problems.
- */
- unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */
- char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */
- /*
- The ICC profile in iccp_profile_size bytes.
- Don't allocate this buffer yourself. Use the init/cleanup functions
- correctly and use lodepng_set_icc and lodepng_clear_icc.
- */
- unsigned char* iccp_profile;
- unsigned iccp_profile_size; /* The size of iccp_profile in bytes */
-
- /* End of color profile related chunks */
-
-
- /*
- unknown chunks: chunks not known by LodePNG, passed on byte for byte.
-
- There are 3 buffers, one for each position in the PNG where unknown chunks can appear.
- Each buffer contains all unknown chunks for that position consecutively.
- The 3 positions are:
- 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND.
-
- For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag
- above in here, since the encoder will blindly follow this and could then encode an invalid PNG file
- (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use
- this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST),
- or any non-standard PNG chunk.
-
- Do not allocate or traverse this data yourself. Use the chunk traversing functions declared
- later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct.
- */
- unsigned char* unknown_chunks_data[3];
- size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-} LodePNGInfo;
-
-/*init, cleanup and copy functions to use with this struct*/
-void lodepng_info_init(LodePNGInfo* info);
-void lodepng_info_cleanup(LodePNGInfo* info);
-/*return value is error code (0 means no error)*/
-unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source);
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
-unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/
-void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/
-
-unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag,
- const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/
-void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/
-
-/*replaces if exists*/
-unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size);
-void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-
-/*
-Converts raw buffer from one color type to another color type, based on
-LodePNGColorMode structs to describe the input and output color type.
-See the reference manual at the end of this header file to see which color conversions are supported.
-return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported)
-The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel
-of the output color type (lodepng_get_bpp).
-For < 8 bpp images, there should not be padding bits at the end of scanlines.
-For 16-bit per channel colors, uses big endian format like PNG does.
-Return value is LodePNG error code
-*/
-unsigned lodepng_convert(unsigned char* out, const unsigned char* in,
- const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in,
- unsigned w, unsigned h);
-
-#ifdef LODEPNG_COMPILE_DECODER
-/*
-Settings for the decoder. This contains settings for the PNG and the Zlib
-decoder, but not the Info settings from the Info structs.
-*/
-typedef struct LodePNGDecoderSettings {
- LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/
-
- /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */
- unsigned ignore_crc; /*ignore CRC checksums*/
- unsigned ignore_critical; /*ignore unknown critical chunks*/
- unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/
- /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable
- errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some
- strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters
- in string keys, etc... */
-
- unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/
-
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/
- /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/
- unsigned remember_unknown_chunks;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-} LodePNGDecoderSettings;
-
-void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings);
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/
-typedef enum LodePNGFilterStrategy {
- /*every filter at zero*/
- LFS_ZERO,
- /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/
- LFS_MINSUM,
- /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending
- on the image, this is better or worse than minsum.*/
- LFS_ENTROPY,
- /*
- Brute-force-search PNG filters by compressing each filter for each scanline.
- Experimental, very slow, and only rarely gives better compression than MINSUM.
- */
- LFS_BRUTE_FORCE,
- /*use predefined_filters buffer: you specify the filter type for each scanline*/
- LFS_PREDEFINED
-} LodePNGFilterStrategy;
-
-/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...),
-which helps decide which color model to use for encoding.
-Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.
-NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/...
-fields in this header file.*/
-typedef struct LodePNGColorProfile {
- unsigned colored; /*not grayscale*/
- unsigned key; /*image is not opaque and color key is possible instead of full alpha*/
- unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/
- unsigned short key_g;
- unsigned short key_b;
- unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/
- unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/
- unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/
- unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for grayscale only. 16 if 16-bit per channel required.*/
- size_t numpixels;
-} LodePNGColorProfile;
-
-void lodepng_color_profile_init(LodePNGColorProfile* profile);
-
-/*Get a LodePNGColorProfile of the image. The profile must already have been inited.
-NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/...
-fields in this header file.*/
-unsigned lodepng_get_color_profile(LodePNGColorProfile* profile,
- const unsigned char* image, unsigned w, unsigned h,
- const LodePNGColorMode* mode_in);
-/*The function LodePNG uses internally to decide the PNG color with auto_convert.
-Chooses an optimal color model, e.g. gray if only gray pixels, palette if < 256 colors, ...*/
-unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out,
- const unsigned char* image, unsigned w, unsigned h,
- const LodePNGColorMode* mode_in);
-
-/*Settings for the encoder.*/
-typedef struct LodePNGEncoderSettings {
- LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/
-
- unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/
-
- /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than
- 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to
- completely follow the official PNG heuristic, filter_palette_zero must be true and
- filter_strategy must be LFS_MINSUM*/
- unsigned filter_palette_zero;
- /*Which filter strategy to use when not using zeroes due to filter_palette_zero.
- Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/
- LodePNGFilterStrategy filter_strategy;
- /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with
- the same length as the amount of scanlines in the image, and each value must <= 5. You
- have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero
- must be set to 0 to ensure this is also used on palette or low bitdepth images.*/
- const unsigned char* predefined_filters;
-
- /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette).
- If colortype is 3, PLTE is _always_ created.*/
- unsigned force_palette;
-#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
- /*add LodePNG identifier and version as a text chunk, for debugging*/
- unsigned add_id;
- /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/
- unsigned text_compression;
-#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
-} LodePNGEncoderSettings;
-
-void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings);
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-
-#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER)
-/*The settings, state and information for extended encoding and decoding.*/
-typedef struct LodePNGState {
-#ifdef LODEPNG_COMPILE_DECODER
- LodePNGDecoderSettings decoder; /*the decoding settings*/
-#endif /*LODEPNG_COMPILE_DECODER*/
-#ifdef LODEPNG_COMPILE_ENCODER
- LodePNGEncoderSettings encoder; /*the encoding settings*/
-#endif /*LODEPNG_COMPILE_ENCODER*/
- LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/
- LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/
- unsigned error;
-#ifdef LODEPNG_COMPILE_CPP
- /* For the lodepng::State subclass. */
- virtual ~LodePNGState(){}
-#endif
-} LodePNGState;
-
-/*init, cleanup and copy functions to use with this struct*/
-void lodepng_state_init(LodePNGState* state);
-void lodepng_state_cleanup(LodePNGState* state);
-void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source);
-#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */
-
-#ifdef LODEPNG_COMPILE_DECODER
-/*
-Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and
-getting much more information about the PNG image and color mode.
-*/
-unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h,
- LodePNGState* state,
- const unsigned char* in, size_t insize);
-
-/*
-Read the PNG header, but not the actual data. This returns only the information
-that is in the IHDR chunk of the PNG, such as width, height and color type. The
-information is placed in the info_png field of the LodePNGState.
-*/
-unsigned lodepng_inspect(unsigned* w, unsigned* h,
- LodePNGState* state,
- const unsigned char* in, size_t insize);
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-/*
-Reads one metadata chunk (other than IHDR) of the PNG file and outputs what it
-read in the state. Returns error code on failure.
-Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const
-to find the desired chunk type, and if non null use lodepng_inspect_chunk (with
-chunk_pointer - start_of_file as pos).
-Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...).
-Ignores unsupported, unknown, non-metadata or IHDR chunks (without error).
-Requirements: &in[pos] must point to start of a chunk, must use regular
-lodepng_inspect first since format of most other chunks depends on IHDR, and if
-there is a PLTE chunk, that one must be inspected before tRNS or bKGD.
-*/
-unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos,
- const unsigned char* in, size_t insize);
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/
-unsigned lodepng_encode(unsigned char** out, size_t* outsize,
- const unsigned char* image, unsigned w, unsigned h,
- LodePNGState* state);
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-/*
-The lodepng_chunk functions are normally not needed, except to traverse the
-unknown chunks stored in the LodePNGInfo struct, or add new ones to it.
-It also allows traversing the chunks of an encoded PNG file yourself.
-
-The chunk pointer always points to the beginning of the chunk itself, that is
-the first byte of the 4 length bytes.
-
-In the PNG file format, chunks have the following format:
--4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer)
--4 bytes chunk type (ASCII a-z,A-Z only, see below)
--length bytes of data (may be 0 bytes if length was 0)
--4 bytes of CRC, computed on chunk name + data
-
-The first chunk starts at the 8th byte of the PNG file, the entire rest of the file
-exists out of concatenated chunks with the above format.
-
-PNG standard chunk ASCII naming conventions:
--First byte: uppercase = critical, lowercase = ancillary
--Second byte: uppercase = public, lowercase = private
--Third byte: must be uppercase
--Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy
-*/
-
-/*
-Gets the length of the data of the chunk. Total chunk length has 12 bytes more.
-There must be at least 4 bytes to read from. If the result value is too large,
-it may be corrupt data.
-*/
-unsigned lodepng_chunk_length(const unsigned char* chunk);
-
-/*puts the 4-byte type in null terminated string*/
-void lodepng_chunk_type(char type[5], const unsigned char* chunk);
-
-/*check if the type is the given type*/
-unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type);
-
-/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/
-unsigned char lodepng_chunk_ancillary(const unsigned char* chunk);
-
-/*0: public, 1: private (see PNG standard)*/
-unsigned char lodepng_chunk_private(const unsigned char* chunk);
-
-/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/
-unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk);
-
-/*get pointer to the data of the chunk, where the input points to the header of the chunk*/
-unsigned char* lodepng_chunk_data(unsigned char* chunk);
-const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk);
-
-/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/
-unsigned lodepng_chunk_check_crc(const unsigned char* chunk);
-
-/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/
-void lodepng_chunk_generate_crc(unsigned char* chunk);
-
-/*
-Iterate to next chunks, allows iterating through all chunks of the PNG file.
-Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call,
-or the 8th byte of a PNG file which always has the first chunk), or alternatively may
-point to the first byte of the PNG file (which is not a chunk but the magic header, the
-function will then skip over it and return the first real chunk).
-Expects at least 8 readable bytes of memory in the input pointer.
-Will output pointer to the start of the next chunk or the end of the file if there
-is no more chunk after this. Start this process at the 8th byte of the PNG file.
-In a non-corrupt PNG file, the last chunk should have name "IEND".
-*/
-unsigned char* lodepng_chunk_next(unsigned char* chunk);
-const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk);
-
-/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/
-unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]);
-const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]);
-
-/*
-Appends chunk to the data in out. The given chunk should already have its chunk header.
-The out variable and outlength are updated to reflect the new reallocated buffer.
-Returns error code (0 if it went ok)
-*/
-unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk);
-
-/*
-Appends new chunk to out. The chunk to append is given by giving its length, type
-and data separately. The type is a 4-letter string.
-The out variable and outlength are updated to reflect the new reallocated buffer.
-Returne error code (0 if it went ok)
-*/
-unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
- const char* type, const unsigned char* data);
-
-
-/*Calculate CRC32 of buffer*/
-unsigned lodepng_crc32(const unsigned char* buf, size_t len);
-#endif /*LODEPNG_COMPILE_PNG*/
-
-
-#ifdef LODEPNG_COMPILE_ZLIB
-/*
-This zlib part can be used independently to zlib compress and decompress a
-buffer. It cannot be used to create gzip files however, and it only supports the
-part of zlib that is required for PNG, it does not support dictionaries.
-*/
-
-#ifdef LODEPNG_COMPILE_DECODER
-/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/
-unsigned lodepng_inflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings* settings);
-
-/*
-Decompresses Zlib data. Reallocates the out buffer and appends the data. The
-data must be according to the zlib specification.
-Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
-buffer and *outsize its size in bytes. out must be freed by user after usage.
-*/
-unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings* settings);
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/*
-Compresses data with Zlib. Reallocates the out buffer and appends the data.
-Zlib adds a small header and trailer around the deflate data.
-The data is output in the format of the zlib specification.
-Either, *out must be NULL and *outsize must be 0, or, *out must be a valid
-buffer and *outsize its size in bytes. out must be freed by user after usage.
-*/
-unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGCompressSettings* settings);
-
-/*
-Find length-limited Huffman code for given frequencies. This function is in the
-public interface only for tests, it's used internally by lodepng_deflate.
-*/
-unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies,
- size_t numcodes, unsigned maxbitlen);
-
-/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/
-unsigned lodepng_deflate(unsigned char** out, size_t* outsize,
- const unsigned char* in, size_t insize,
- const LodePNGCompressSettings* settings);
-
-#endif /*LODEPNG_COMPILE_ENCODER*/
-#endif /*LODEPNG_COMPILE_ZLIB*/
-
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Load a file from disk into buffer. The function allocates the out buffer, and
-after usage you should free it.
-out: output parameter, contains pointer to loaded buffer.
-outsize: output parameter, size of the allocated out buffer
-filename: the path to the file to load
-return value: error code (0 means ok)
-*/
-unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename);
-
-/*
-Save a file from buffer to disk. Warning, if it exists, this function overwrites
-the file without warning!
-buffer: the buffer to write
-buffersize: size of the buffer to write
-filename: the path to the file to save to
-return value: error code (0 means ok)
-*/
-unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename);
-#endif /*LODEPNG_COMPILE_DISK*/
-
-#ifdef LODEPNG_COMPILE_CPP
-/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */
-namespace lodepng {
-#ifdef LODEPNG_COMPILE_PNG
-class State : public LodePNGState {
- public:
- State();
- State(const State& other);
- virtual ~State();
- State& operator=(const State& other);
-};
-
-#ifdef LODEPNG_COMPILE_DECODER
-/* Same as other lodepng::decode, but using a State for more settings and information. */
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- State& state,
- const unsigned char* in, size_t insize);
-unsigned decode(std::vector<unsigned char>& out, unsigned& w, unsigned& h,
- State& state,
- const std::vector<unsigned char>& in);
-#endif /*LODEPNG_COMPILE_DECODER*/
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/* Same as other lodepng::encode, but using a State for more settings and information. */
-unsigned encode(std::vector<unsigned char>& out,
- const unsigned char* in, unsigned w, unsigned h,
- State& state);
-unsigned encode(std::vector<unsigned char>& out,
- const std::vector<unsigned char>& in, unsigned w, unsigned h,
- State& state);
-#endif /*LODEPNG_COMPILE_ENCODER*/
-
-#ifdef LODEPNG_COMPILE_DISK
-/*
-Load a file from disk into an std::vector.
-return value: error code (0 means ok)
-*/
-unsigned load_file(std::vector<unsigned char>& buffer, const std::string& filename);
-
-/*
-Save the binary data in an std::vector to a file on disk. The file is overwritten
-without warning.
-*/
-unsigned save_file(const std::vector<unsigned char>& buffer, const std::string& filename);
-#endif /* LODEPNG_COMPILE_DISK */
-#endif /* LODEPNG_COMPILE_PNG */
-
-#ifdef LODEPNG_COMPILE_ZLIB
-#ifdef LODEPNG_COMPILE_DECODER
-/* Zlib-decompress an unsigned char buffer */
-unsigned decompress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
- const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
-
-/* Zlib-decompress an std::vector */
-unsigned decompress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
- const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings);
-#endif /* LODEPNG_COMPILE_DECODER */
-
-#ifdef LODEPNG_COMPILE_ENCODER
-/* Zlib-compress an unsigned char buffer */
-unsigned compress(std::vector<unsigned char>& out, const unsigned char* in, size_t insize,
- const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
-
-/* Zlib-compress an std::vector */
-unsigned compress(std::vector<unsigned char>& out, const std::vector<unsigned char>& in,
- const LodePNGCompressSettings& settings = lodepng_default_compress_settings);
-#endif /* LODEPNG_COMPILE_ENCODER */
-#endif /* LODEPNG_COMPILE_ZLIB */
-} /* namespace lodepng */
-#endif /*LODEPNG_COMPILE_CPP*/
-
-/*
-TODO:
-[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often
-[.] check compatibility with various compilers - done but needs to be redone for every newer version
-[X] converting color to 16-bit per channel types
-[X] support color profile chunk types (but never let them touch RGB values by default)
-[ ] support all public PNG chunk types (almost done except sBIT, sPLT and hIST)
-[ ] make sure encoder generates no chunks with size > (2^31)-1
-[ ] partial decoding (stream processing)
-[X] let the "isFullyOpaque" function check color keys and transparent palettes too
-[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl"
-[ ] allow treating some errors like warnings, when image is recoverable (e.g. 69, 57, 58)
-[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ...
-[ ] error messages with line numbers (and version)
-[ ] errors in state instead of as return code?
-[ ] new errors/warnings like suspiciously big decompressed ztxt or iccp chunk
-[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes
-[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ...
-[ ] allow user to give data (void*) to custom allocator
-[ ] provide alternatives for C library functions not present on some platforms (memcpy, ...)
-[ ] rename "grey" to "gray" everywhere since "color" also uses US spelling (keep "grey" copies for backwards compatibility)
-*/
-
-#endif /*LODEPNG_H inclusion guard*/
-
-/*
-LodePNG Documentation
----------------------
-
-0. table of contents
---------------------
-
- 1. about
- 1.1. supported features
- 1.2. features not supported
- 2. C and C++ version
- 3. security
- 4. decoding
- 5. encoding
- 6. color conversions
- 6.1. PNG color types
- 6.2. color conversions
- 6.3. padding bits
- 6.4. A note about 16-bits per channel and endianness
- 7. error values
- 8. chunks and PNG editing
- 9. compiler support
- 10. examples
- 10.1. decoder C++ example
- 10.2. decoder C example
- 11. state settings reference
- 12. changes
- 13. contact information
-
-
-1. about
---------
-
-PNG is a file format to store raster images losslessly with good compression,
-supporting different color types and alpha channel.
-
-LodePNG is a PNG codec according to the Portable Network Graphics (PNG)
-Specification (Second Edition) - W3C Recommendation 10 November 2003.
-
-The specifications used are:
-
-*) Portable Network Graphics (PNG) Specification (Second Edition):
- http://www.w3.org/TR/2003/REC-PNG-20031110
-*) RFC 1950 ZLIB Compressed Data Format version 3.3:
- http://www.gzip.org/zlib/rfc-zlib.html
-*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3:
- http://www.gzip.org/zlib/rfc-deflate.html
-
-The most recent version of LodePNG can currently be found at
-http://lodev.org/lodepng/
-
-LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds
-extra functionality.
-
-LodePNG exists out of two files:
--lodepng.h: the header file for both C and C++
--lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage
-
-If you want to start using LodePNG right away without reading this doc, get the
-examples from the LodePNG website to see how to use it in code, or check the
-smaller examples in chapter 13 here.
-
-LodePNG is simple but only supports the basic requirements. To achieve
-simplicity, the following design choices were made: There are no dependencies
-on any external library. There are functions to decode and encode a PNG with
-a single function call, and extended versions of these functions taking a
-LodePNGState struct allowing to specify or get more information. By default
-the colors of the raw image are always RGB or RGBA, no matter what color type
-the PNG file uses. To read and write files, there are simple functions to
-convert the files to/from buffers in memory.
-
-This all makes LodePNG suitable for loading textures in games, demos and small
-programs, ... It's less suitable for full fledged image editors, loading PNGs
-over network (it requires all the image data to be available before decoding can
-begin), life-critical systems, ...
-
-1.1. supported features
------------------------
-
-The following features are supported by the decoder:
-
-*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image,
- or the same color type as the PNG
-*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image
-*) Adam7 interlace and deinterlace for any color type
-*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk
-*) support for alpha channels, including RGBA color model, translucent palettes and color keying
-*) zlib decompression (inflate)
-*) zlib compression (deflate)
-*) CRC32 and ADLER32 checksums
-*) colorimetric color profile conversions: currently experimentally available in lodepng_util.cpp only,
- plus alternatively ability to pass on chroma/gamma/ICC profile information to other color management system.
-*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks.
-*) the following chunks are supported by both encoder and decoder:
- IHDR: header information
- PLTE: color palette
- IDAT: pixel data
- IEND: the final chunk
- tRNS: transparency for palettized images
- tEXt: textual information
- zTXt: compressed textual information
- iTXt: international textual information
- bKGD: suggested background color
- pHYs: physical dimensions
- tIME: modification time
- cHRM: RGB chromaticities
- gAMA: RGB gamma correction
- iCCP: ICC color profile
- sRGB: rendering intent
-
-1.2. features not supported
----------------------------
-
-The following features are _not_ supported:
-
-*) some features needed to make a conformant PNG-Editor might be still missing.
-*) partial loading/stream processing. All data must be available and is processed in one call.
-*) The following public chunks are not (yet) supported but treated as unknown chunks by LodePNG:
- sBIT
- hIST
- sPLT
-
-
-2. C and C++ version
---------------------
-
-The C version uses buffers allocated with alloc that you need to free()
-yourself. You need to use init and cleanup functions for each struct whenever
-using a struct from the C version to avoid exploits and memory leaks.
-
-The C++ version has extra functions with std::vectors in the interface and the
-lodepng::State class which is a LodePNGState with constructor and destructor.
-
-These files work without modification for both C and C++ compilers because all
-the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers
-ignore it, and the C code is made to compile both with strict ISO C90 and C++.
-
-To use the C++ version, you need to rename the source file to lodepng.cpp
-(instead of lodepng.c), and compile it with a C++ compiler.
-
-To use the C version, you need to rename the source file to lodepng.c (instead
-of lodepng.cpp), and compile it with a C compiler.
-
-
-3. Security
------------
-
-Even if carefully designed, it's always possible that LodePNG contains possible
-exploits. If you discover one, please let me know, and it will be fixed.
-
-When using LodePNG, care has to be taken with the C version of LodePNG, as well
-as the C-style structs when working with C++. The following conventions are used
-for all C-style structs:
-
--if a struct has a corresponding init function, always call the init function when making a new one
--if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks
--if a struct has a corresponding copy function, use the copy function instead of "=".
- The destination must also be inited already.
-
-
-4. Decoding
------------
-
-Decoding converts a PNG compressed image to a raw pixel buffer.
-
-Most documentation on using the decoder is at its declarations in the header
-above. For C, simple decoding can be done with functions such as
-lodepng_decode32, and more advanced decoding can be done with the struct
-LodePNGState and lodepng_decode. For C++, all decoding can be done with the
-various lodepng::decode functions, and lodepng::State can be used for advanced
-features.
-
-When using the LodePNGState, it uses the following fields for decoding:
-*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here
-*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get
-*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use
-
-LodePNGInfo info_png
---------------------
-
-After decoding, this contains extra information of the PNG image, except the actual
-pixels, width and height because these are already gotten directly from the decoder
-functions.
-
-It contains for example the original color type of the PNG image, text comments,
-suggested background color, etc... More details about the LodePNGInfo struct are
-at its declaration documentation.
-
-LodePNGColorMode info_raw
--------------------------
-
-When decoding, here you can specify which color type you want
-the resulting raw image to be. If this is different from the colortype of the
-PNG, then the decoder will automatically convert the result. This conversion
-always works, except if you want it to convert a color PNG to grayscale or to
-a palette with missing colors.
-
-By default, 32-bit color is used for the result.
-
-LodePNGDecoderSettings decoder
-------------------------------
-
-The settings can be used to ignore the errors created by invalid CRC and Adler32
-chunks, and to disable the decoding of tEXt chunks.
-
-There's also a setting color_convert, true by default. If false, no conversion
-is done, the resulting data will be as it was in the PNG (after decompression)
-and you'll have to puzzle the colors of the pixels together yourself using the
-color type information in the LodePNGInfo.
-
-
-5. Encoding
------------
-
-Encoding converts a raw pixel buffer to a PNG compressed image.
-
-Most documentation on using the encoder is at its declarations in the header
-above. For C, simple encoding can be done with functions such as
-lodepng_encode32, and more advanced decoding can be done with the struct
-LodePNGState and lodepng_encode. For C++, all encoding can be done with the
-various lodepng::encode functions, and lodepng::State can be used for advanced
-features.
-
-Like the decoder, the encoder can also give errors. However it gives less errors
-since the encoder input is trusted, the decoder input (a PNG image that could
-be forged by anyone) is not trusted.
-
-When using the LodePNGState, it uses the following fields for encoding:
-*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be.
-*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has
-*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use
-
-LodePNGInfo info_png
---------------------
-
-When encoding, you use this the opposite way as when decoding: for encoding,
-you fill in the values you want the PNG to have before encoding. By default it's
-not needed to specify a color type for the PNG since it's automatically chosen,
-but it's possible to choose it yourself given the right settings.
-
-The encoder will not always exactly match the LodePNGInfo struct you give,
-it tries as close as possible. Some things are ignored by the encoder. The
-encoder uses, for example, the following settings from it when applicable:
-colortype and bitdepth, text chunks, time chunk, the color key, the palette, the
-background color, the interlace method, unknown chunks, ...
-
-When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk.
-If the palette contains any colors for which the alpha channel is not 255 (so
-there are translucent colors in the palette), it'll add a tRNS chunk.
-
-LodePNGColorMode info_raw
--------------------------
-
-You specify the color type of the raw image that you give to the input here,
-including a possible transparent color key and palette you happen to be using in
-your raw image data.
-
-By default, 32-bit color is assumed, meaning your input has to be in RGBA
-format with 4 bytes (unsigned chars) per pixel.
-
-LodePNGEncoderSettings encoder
-------------------------------
-
-The following settings are supported (some are in sub-structs):
-*) auto_convert: when this option is enabled, the encoder will
-automatically choose the smallest possible color mode (including color key) that
-can encode the colors of all pixels without information loss.
-*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree,
- 2 = dynamic huffman tree (best compression). Should be 2 for proper
- compression.
-*) use_lz77: whether or not to use LZ77 for compressed block types. Should be
- true for proper compression.
-*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value
- 2048 by default, but can be set to 32768 for better, but slow, compression.
-*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE
- chunk if force_palette is true. This can used as suggested palette to convert
- to by viewers that don't support more than 256 colors (if those still exist)
-*) add_id: add text chunk "Encoder: LodePNG <version>" to the image.
-*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks.
- zTXt chunks use zlib compression on the text. This gives a smaller result on
- large texts but a larger result on small texts (such as a single program name).
- It's all tEXt or all zTXt though, there's no separate setting per text yet.
-
-
-6. color conversions
---------------------
-
-An important thing to note about LodePNG, is that the color type of the PNG, and
-the color type of the raw image, are completely independent. By default, when
-you decode a PNG, you get the result as a raw image in the color type you want,
-no matter whether the PNG was encoded with a palette, grayscale or RGBA color.
-And if you encode an image, by default LodePNG will automatically choose the PNG
-color type that gives good compression based on the values of colors and amount
-of colors in the image. It can be configured to let you control it instead as
-well, though.
-
-To be able to do this, LodePNG does conversions from one color mode to another.
-It can convert from almost any color type to any other color type, except the
-following conversions: RGB to grayscale is not supported, and converting to a
-palette when the palette doesn't have a required color is not supported. This is
-not supported on purpose: this is information loss which requires a color
-reduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to gray
-is easy, but there are multiple ways if you want to give some channels more
-weight).
-
-By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB
-color, no matter what color type the PNG has. And by default when encoding,
-LodePNG automatically picks the best color model for the output PNG, and expects
-the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control
-the color format of the images yourself, you can skip this chapter.
-
-6.1. PNG color types
---------------------
-
-A PNG image can have many color types, ranging from 1-bit color to 64-bit color,
-as well as palettized color modes. After the zlib decompression and unfiltering
-in the PNG image is done, the raw pixel data will have that color type and thus
-a certain amount of bits per pixel. If you want the output raw image after
-decoding to have another color type, a conversion is done by LodePNG.
-
-The PNG specification gives the following color types:
-
-0: grayscale, bit depths 1, 2, 4, 8, 16
-2: RGB, bit depths 8 and 16
-3: palette, bit depths 1, 2, 4 and 8
-4: grayscale with alpha, bit depths 8 and 16
-6: RGBA, bit depths 8 and 16
-
-Bit depth is the amount of bits per pixel per color channel. So the total amount
-of bits per pixel is: amount of channels * bitdepth.
-
-6.2. color conversions
-----------------------
-
-As explained in the sections about the encoder and decoder, you can specify
-color types and bit depths in info_png and info_raw to change the default
-behaviour.
-
-If, when decoding, you want the raw image to be something else than the default,
-you need to set the color type and bit depth you want in the LodePNGColorMode,
-or the parameters colortype and bitdepth of the simple decoding function.
-
-If, when encoding, you use another color type than the default in the raw input
-image, you need to specify its color type and bit depth in the LodePNGColorMode
-of the raw image, or use the parameters colortype and bitdepth of the simple
-encoding function.
-
-If, when encoding, you don't want LodePNG to choose the output PNG color type
-but control it yourself, you need to set auto_convert in the encoder settings
-to false, and specify the color type you want in the LodePNGInfo of the
-encoder (including palette: it can generate a palette if auto_convert is true,
-otherwise not).
-
-If the input and output color type differ (whether user chosen or auto chosen),
-LodePNG will do a color conversion, which follows the rules below, and may
-sometimes result in an error.
-
-To avoid some confusion:
--the decoder converts from PNG to raw image
--the encoder converts from raw image to PNG
--the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image
--the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG
--when encoding, the color type in LodePNGInfo is ignored if auto_convert
- is enabled, it is automatically generated instead
--when decoding, the color type in LodePNGInfo is set by the decoder to that of the original
- PNG image, but it can be ignored since the raw image has the color type you requested instead
--if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion
- between the color types is done if the color types are supported. If it is not
- supported, an error is returned. If the types are the same, no conversion is done.
--even though some conversions aren't supported, LodePNG supports loading PNGs from any
- colortype and saving PNGs to any colortype, sometimes it just requires preparing
- the raw image correctly before encoding.
--both encoder and decoder use the same color converter.
-
-The function lodepng_convert does the color conversion. It is available in the
-interface but normally isn't needed since the encoder and decoder already call
-it.
-
-Non supported color conversions:
--color to grayscale when non-gray pixels are present: no error is thrown, but
-the result will look ugly because only the red channel is taken (it assumes all
-three channels are the same in this case so ignores green and blue). The reason
-no error is given is to allow converting from three-channel grayscale images to
-one-channel even if there are numerical imprecisions.
--anything to palette when the palette does not have an exact match for a from-color
-in it: in this case an error is thrown
-
-Supported color conversions:
--anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA
--any gray or gray+alpha, to gray or gray+alpha
--anything to a palette, as long as the palette has the requested colors in it
--removing alpha channel
--higher to smaller bitdepth, and vice versa
-
-If you want no color conversion to be done (e.g. for speed or control):
--In the encoder, you can make it save a PNG with any color type by giving the
-raw color mode and LodePNGInfo the same color mode, and setting auto_convert to
-false.
--In the decoder, you can make it store the pixel data in the same color type
-as the PNG has, by setting the color_convert setting to false. Settings in
-info_raw are then ignored.
-
-6.3. padding bits
------------------
-
-In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines
-have a bit amount that isn't a multiple of 8, then padding bits are used so that each
-scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output.
-The raw input image you give to the encoder, and the raw output image you get from the decoder
-will NOT have these padding bits, e.g. in the case of a 1-bit image with a width
-of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte,
-not the first bit of a new byte.
-
-6.4. A note about 16-bits per channel and endianness
-----------------------------------------------------
-
-LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like
-for any other color format. The 16-bit values are stored in big endian (most
-significant byte first) in these arrays. This is the opposite order of the
-little endian used by x86 CPU's.
-
-LodePNG always uses big endian because the PNG file format does so internally.
-Conversions to other formats than PNG uses internally are not supported by
-LodePNG on purpose, there are myriads of formats, including endianness of 16-bit
-colors, the order in which you store R, G, B and A, and so on. Supporting and
-converting to/from all that is outside the scope of LodePNG.
-
-This may mean that, depending on your use case, you may want to convert the big
-endian output of LodePNG to little endian with a for loop. This is certainly not
-always needed, many applications and libraries support big endian 16-bit colors
-anyway, but it means you cannot simply cast the unsigned char* buffer to an
-unsigned short* buffer on x86 CPUs.
-
-
-7. error values
----------------
-
-All functions in LodePNG that return an error code, return 0 if everything went
-OK, or a non-zero code if there was an error.
-
-The meaning of the LodePNG error values can be retrieved with the function
-lodepng_error_text: given the numerical error code, it returns a description
-of the error in English as a string.
-
-Check the implementation of lodepng_error_text to see the meaning of each code.
-
-
-8. chunks and PNG editing
--------------------------
-
-If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG
-editor that should follow the rules about handling of unknown chunks, or if your
-program is able to read other types of chunks than the ones handled by LodePNG,
-then that's possible with the chunk functions of LodePNG.
-
-A PNG chunk has the following layout:
-
-4 bytes length
-4 bytes type name
-length bytes data
-4 bytes CRC
-
-8.1. iterating through chunks
------------------------------
-
-If you have a buffer containing the PNG image data, then the first chunk (the
-IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the
-signature of the PNG and are not part of a chunk. But if you start at byte 8
-then you have a chunk, and can check the following things of it.
-
-NOTE: none of these functions check for memory buffer boundaries. To avoid
-exploits, always make sure the buffer contains all the data of the chunks.
-When using lodepng_chunk_next, make sure the returned value is within the
-allocated memory.
-
-unsigned lodepng_chunk_length(const unsigned char* chunk):
-
-Get the length of the chunk's data. The total chunk length is this length + 12.
-
-void lodepng_chunk_type(char type[5], const unsigned char* chunk):
-unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type):
-
-Get the type of the chunk or compare if it's a certain type
-
-unsigned char lodepng_chunk_critical(const unsigned char* chunk):
-unsigned char lodepng_chunk_private(const unsigned char* chunk):
-unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk):
-
-Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are).
-Check if the chunk is private (public chunks are part of the standard, private ones not).
-Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical
-chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your
-program doesn't handle that type of unknown chunk.
-
-unsigned char* lodepng_chunk_data(unsigned char* chunk):
-const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk):
-
-Get a pointer to the start of the data of the chunk.
-
-unsigned lodepng_chunk_check_crc(const unsigned char* chunk):
-void lodepng_chunk_generate_crc(unsigned char* chunk):
-
-Check if the crc is correct or generate a correct one.
-
-unsigned char* lodepng_chunk_next(unsigned char* chunk):
-const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk):
-
-Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these
-functions do no boundary checking of the allocated data whatsoever, so make sure there is enough
-data available in the buffer to be able to go to the next chunk.
-
-unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk):
-unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length,
- const char* type, const unsigned char* data):
-
-These functions are used to create new chunks that are appended to the data in *out that has
-length *outlength. The append function appends an existing chunk to the new data. The create
-function creates a new chunk with the given parameters and appends it. Type is the 4-letter
-name of the chunk.
-
-8.2. chunks in info_png
------------------------
-
-The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3
-buffers (each with size) to contain 3 types of unknown chunks:
-the ones that come before the PLTE chunk, the ones that come between the PLTE
-and the IDAT chunks, and the ones that come after the IDAT chunks.
-It's necessary to make the distionction between these 3 cases because the PNG
-standard forces to keep the ordering of unknown chunks compared to the critical
-chunks, but does not force any other ordering rules.
-
-info_png.unknown_chunks_data[0] is the chunks before PLTE
-info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT
-info_png.unknown_chunks_data[2] is the chunks after IDAT
-
-The chunks in these 3 buffers can be iterated through and read by using the same
-way described in the previous subchapter.
-
-When using the decoder to decode a PNG, you can make it store all unknown chunks
-if you set the option settings.remember_unknown_chunks to 1. By default, this
-option is off (0).
-
-The encoder will always encode unknown chunks that are stored in the info_png.
-If you need it to add a particular chunk that isn't known by LodePNG, you can
-use lodepng_chunk_append or lodepng_chunk_create to the chunk data in
-info_png.unknown_chunks_data[x].
-
-Chunks that are known by LodePNG should not be added in that way. E.g. to make
-LodePNG add a bKGD chunk, set background_defined to true and add the correct
-parameters there instead.
-
-
-9. compiler support
--------------------
-
-No libraries other than the current standard C library are needed to compile
-LodePNG. For the C++ version, only the standard C++ library is needed on top.
-Add the files lodepng.c(pp) and lodepng.h to your project, include
-lodepng.h where needed, and your program can read/write PNG files.
-
-It is compatible with C90 and up, and C++03 and up.
-
-If performance is important, use optimization when compiling! For both the
-encoder and decoder, this makes a large difference.
-
-Make sure that LodePNG is compiled with the same compiler of the same version
-and with the same settings as the rest of the program, or the interfaces with
-std::vectors and std::strings in C++ can be incompatible.
-
-CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets.
-
-*) gcc and g++
-
-LodePNG is developed in gcc so this compiler is natively supported. It gives no
-warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++
-version 4.7.1 on Linux, 32-bit and 64-bit.
-
-*) Clang
-
-Fully supported and warning-free.
-
-*) Mingw
-
-The Mingw compiler (a port of gcc for Windows) should be fully supported by
-LodePNG.
-
-*) Visual Studio and Visual C++ Express Edition
-
-LodePNG should be warning-free with warning level W4. Two warnings were disabled
-with pragmas though: warning 4244 about implicit conversions, and warning 4996
-where it wants to use a non-standard function fopen_s instead of the standard C
-fopen.
-
-Visual Studio may want "stdafx.h" files to be included in each source file and
-give an error "unexpected end of file while looking for precompiled header".
-This is not standard C++ and will not be added to the stock LodePNG. You can
-disable it for lodepng.cpp only by right clicking it, Properties, C/C++,
-Precompiled Headers, and set it to Not Using Precompiled Headers there.
-
-NOTE: Modern versions of VS should be fully supported, but old versions, e.g.
-VS6, are not guaranteed to work.
-
-*) Compilers on Macintosh
-
-LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for
-C and C++.
-
-*) Other Compilers
-
-If you encounter problems on any compilers, feel free to let me know and I may
-try to fix it if the compiler is modern and standards complient.
-
-
-10. examples
-------------
-
-This decoder example shows the most basic usage of LodePNG. More complex
-examples can be found on the LodePNG website.
-
-10.1. decoder C++ example
--------------------------
-
-#include "lodepng.h"
-#include <iostream>
-
-int main(int argc, char *argv[]) {
- const char* filename = argc > 1 ? argv[1] : "test.png";
-
- //load and decode
- std::vector<unsigned char> image;
- unsigned width, height;
- unsigned error = lodepng::decode(image, width, height, filename);
-
- //if there's an error, display it
- if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl;
-
- //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ...
-}
-
-10.2. decoder C example
------------------------
-
-#include "lodepng.h"
-
-int main(int argc, char *argv[]) {
- unsigned error;
- unsigned char* image;
- size_t width, height;
- const char* filename = argc > 1 ? argv[1] : "test.png";
-
- error = lodepng_decode32_file(&image, &width, &height, filename);
-
- if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error));
-
- / * use image here * /
-
- free(image);
- return 0;
-}
-
-11. state settings reference
-----------------------------
-
-A quick reference of some settings to set on the LodePNGState
-
-For decoding:
-
-state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums
-state.decoder.zlibsettings.custom_...: use custom inflate function
-state.decoder.ignore_crc: ignore CRC checksums
-state.decoder.ignore_critical: ignore unknown critical chunks
-state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors
-state.decoder.color_convert: convert internal PNG color to chosen one
-state.decoder.read_text_chunks: whether to read in text metadata chunks
-state.decoder.remember_unknown_chunks: whether to read in unknown chunks
-state.info_raw.colortype: desired color type for decoded image
-state.info_raw.bitdepth: desired bit depth for decoded image
-state.info_raw....: more color settings, see struct LodePNGColorMode
-state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo
-
-For encoding:
-
-state.encoder.zlibsettings.btype: disable compression by setting it to 0
-state.encoder.zlibsettings.use_lz77: use LZ77 in compression
-state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize
-state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match
-state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching
-state.encoder.zlibsettings.lazymatching: try one more LZ77 matching
-state.encoder.zlibsettings.custom_...: use custom deflate function
-state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png
-state.encoder.filter_palette_zero: PNG filter strategy for palette
-state.encoder.filter_strategy: PNG filter strategy to encode with
-state.encoder.force_palette: add palette even if not encoding to one
-state.encoder.add_id: add LodePNG identifier and version as a text chunk
-state.encoder.text_compression: use compressed text chunks for metadata
-state.info_raw.colortype: color type of raw input image you provide
-state.info_raw.bitdepth: bit depth of raw input image you provide
-state.info_raw: more color settings, see struct LodePNGColorMode
-state.info_png.color.colortype: desired color type if auto_convert is false
-state.info_png.color.bitdepth: desired bit depth if auto_convert is false
-state.info_png.color....: more color settings, see struct LodePNGColorMode
-state.info_png....: more PNG related settings, see struct LodePNGInfo
-
-
-12. changes
------------
-
-The version number of LodePNG is the date of the change given in the format
-yyyymmdd.
-
-Some changes aren't backwards compatible. Those are indicated with a (!)
-symbol.
-
-*) 30 dec 2018: code style changes only: removed newlines before opening braces.
-*) 10 sep 2018: added way to inspect metadata chunks without full decoding.
-*) 19 aug 2018 (!): fixed color mode bKGD is encoded with and made it use
- palette index in case of palette.
-*) 10 aug 2018 (!): added support for gAMA, cHRM, sRGB and iCCP chunks. This
- change is backwards compatible unless you relied on unknown_chunks for those.
-*) 11 jun 2018: less restrictive check for pixel size integer overflow
-*) 14 jan 2018: allow optionally ignoring a few more recoverable errors
-*) 17 sep 2017: fix memory leak for some encoder input error cases
-*) 27 nov 2016: grey+alpha auto color model detection bugfix
-*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort).
-*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within
- the limits of pure C90).
-*) 08 dec 2015: Made load_file function return error if file can't be opened.
-*) 24 okt 2015: Bugfix with decoding to palette output.
-*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding.
-*) 23 aug 2014: Reduced needless memory usage of decoder.
-*) 28 jun 2014: Removed fix_png setting, always support palette OOB for
- simplicity. Made ColorProfile public.
-*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization.
-*) 22 dec 2013: Power of two windowsize required for optimization.
-*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key.
-*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png).
-*) 11 mar 2013 (!): Bugfix with custom free. Changed from "my" to "lodepng_"
- prefix for the custom allocators and made it possible with a new #define to
- use custom ones in your project without needing to change lodepng's code.
-*) 28 jan 2013: Bugfix with color key.
-*) 27 okt 2012: Tweaks in text chunk keyword length error handling.
-*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode.
- (no palette). Better deflate tree encoding. New compression tweak settings.
- Faster color conversions while decoding. Some internal cleanups.
-*) 23 sep 2012: Reduced warnings in Visual Studio a little bit.
-*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions
- and made it work with function pointers instead.
-*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc
- and free functions and toggle #defines from compiler flags. Small fixes.
-*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible.
-*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed
- redundant C++ codec classes. Reduced amount of structs. Everything changed,
- but it is cleaner now imho and functionality remains the same. Also fixed
- several bugs and shrunk the implementation code. Made new samples.
-*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best
- PNG color model and bit depth, based on the amount and type of colors of the
- raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color.
-*) 9 okt 2011: simpler hash chain implementation for the encoder.
-*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching.
-*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking.
- A bug with the PNG filtertype heuristic was fixed, so that it chooses much
- better ones (it's quite significant). A setting to do an experimental, slow,
- brute force search for PNG filter types is added.
-*) 17 aug 2011 (!): changed some C zlib related function names.
-*) 16 aug 2011: made the code less wide (max 120 characters per line).
-*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors.
-*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled.
-*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman
- to optimize long sequences of zeros.
-*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and
- LodePNG_InfoColor_canHaveAlpha functions for convenience.
-*) 7 nov 2010: added LodePNG_error_text function to get error code description.
-*) 30 okt 2010: made decoding slightly faster
-*) 26 okt 2010: (!) changed some C function and struct names (more consistent).
- Reorganized the documentation and the declaration order in the header.
-*) 08 aug 2010: only changed some comments and external samples.
-*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version.
-*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers.
-*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could
- read by ignoring the problem but windows apps couldn't.
-*) 06 jun 2008: added more error checks for out of memory cases.
-*) 26 apr 2008: added a few more checks here and there to ensure more safety.
-*) 06 mar 2008: crash with encoding of strings fixed
-*) 02 feb 2008: support for international text chunks added (iTXt)
-*) 23 jan 2008: small cleanups, and #defines to divide code in sections
-*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor.
-*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder.
-*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added
- Also various fixes, such as in the deflate and the padding bits code.
-*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved
- filtering code of encoder.
-*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A
- C++ wrapper around this provides an interface almost identical to before.
- Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code
- are together in these files but it works both for C and C++ compilers.
-*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks
-*) 30 aug 2007: bug fixed which makes this Borland C++ compatible
-*) 09 aug 2007: some VS2005 warnings removed again
-*) 21 jul 2007: deflate code placed in new namespace separate from zlib code
-*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images
-*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing
- invalid std::vector element [0] fixed, and level 3 and 4 warnings removed
-*) 02 jun 2007: made the encoder add a tag with version by default
-*) 27 may 2007: zlib and png code separated (but still in the same file),
- simple encoder/decoder functions added for more simple usage cases
-*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69),
- moved some examples from here to lodepng_examples.cpp
-*) 12 may 2007: palette decoding bug fixed
-*) 24 apr 2007: changed the license from BSD to the zlib license
-*) 11 mar 2007: very simple addition: ability to encode bKGD chunks.
-*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding
- palettized PNG images. Plus little interface change with palette and texts.
-*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes.
- Fixed a bug where the end code of a block had length 0 in the Huffman tree.
-*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented
- and supported by the encoder, resulting in smaller PNGs at the output.
-*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone.
-*) 24 jan 2007: gave encoder an error interface. Added color conversion from any
- greyscale type to 8-bit greyscale with or without alpha.
-*) 21 jan 2007: (!) Totally changed the interface. It allows more color types
- to convert to and is more uniform. See the manual for how it works now.
-*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days:
- encode/decode custom tEXt chunks, separate classes for zlib & deflate, and
- at last made the decoder give errors for incorrect Adler32 or Crc.
-*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel.
-*) 29 dec 2006: Added support for encoding images without alpha channel, and
- cleaned out code as well as making certain parts faster.
-*) 28 dec 2006: Added "Settings" to the encoder.
-*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now.
- Removed some code duplication in the decoder. Fixed little bug in an example.
-*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter.
- Fixed a bug of the decoder with 16-bit per color.
-*) 15 okt 2006: Changed documentation structure
-*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the
- given image buffer, however for now it's not compressed.
-*) 08 sep 2006: (!) Changed to interface with a Decoder class
-*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different
- way. Renamed decodePNG to decodePNGGeneric.
-*) 29 jul 2006: (!) Changed the interface: image info is now returned as a
- struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy.
-*) 28 jul 2006: Cleaned the code and added new error checks.
- Corrected terminology "deflate" into "inflate".
-*) 23 jun 2006: Added SDL example in the documentation in the header, this
- example allows easy debugging by displaying the PNG and its transparency.
-*) 22 jun 2006: (!) Changed way to obtain error value. Added
- loadFile function for convenience. Made decodePNG32 faster.
-*) 21 jun 2006: (!) Changed type of info vector to unsigned.
- Changed position of palette in info vector. Fixed an important bug that
- happened on PNGs with an uncompressed block.
-*) 16 jun 2006: Internally changed unsigned into unsigned where
- needed, and performed some optimizations.
-*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them
- in LodePNG namespace. Changed the order of the parameters. Rewrote the
- documentation in the header. Renamed files to lodepng.cpp and lodepng.h
-*) 22 apr 2006: Optimized and improved some code
-*) 07 sep 2005: (!) Changed to std::vector interface
-*) 12 aug 2005: Initial release (C++, decoder only)
-
-
-13. contact information
------------------------
-
-Feel free to contact me with suggestions, problems, comments, ... concerning
-LodePNG. If you encounter a PNG image that doesn't work properly with this
-decoder, feel free to send it and I'll use it to find and fix the problem.
-
-My email address is (puzzle the account and domain together with an @ symbol):
-Domain: gmail dot com.
-Account: lode dot vandevenne.
-
-
-Copyright (c) 2005-2019 Lode Vandevenne
-*/
diff --git a/thirdparty/basis_universal/encoder/pvpngreader.cpp b/thirdparty/basis_universal/encoder/pvpngreader.cpp
new file mode 100644
index 0000000000..46639f2796
--- /dev/null
+++ b/thirdparty/basis_universal/encoder/pvpngreader.cpp
@@ -0,0 +1,2662 @@
+// pngreader.cpp - Public Domain - see unlicense at bottom of file.
+//
+// Notes:
+// This is ancient code from ~1995 ported to C++. It was originally written for a
+// DOS app with very limited memory. It's not as fast as it should be, but it works.
+// The low-level PNG reader class was written assuming the PNG file could not fit
+// entirely into memory, which dictated how it was written/structured.
+// It has been modified to use either zlib or miniz.
+// It supports all PNG color types/bit depths/interlacing, however 16-bit/component
+// images are converted to 8-bit.
+// TRNS chunks are converted to alpha as needed.
+// GAMA chunk is read, but not applied.
+
+#include "../transcoder/basisu.h"
+
+#define MINIZ_HEADER_FILE_ONLY
+#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES
+#include "basisu_miniz.h"
+
+#include "pvpngreader.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <vector>
+#include <assert.h>
+
+#define PVPNG_IDAT_CRC_CHECKING (1)
+#define PVPNG_ADLER32_CHECKING (1)
+
+namespace pv_png
+{
+
+const uint32_t MIN_PNG_SIZE = 8 + 13 + 8 + 1 + 4 + 12;
+
+template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
+template <typename S> inline S minimum(S a, S b) { return (a < b) ? a : b; }
+
+template <typename T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }
+
+#define MAX_SUPPORTED_RES (32768)
+#define FALSE (0)
+#define TRUE (1)
+#define PNG_MAX_ALLOC_BLOCKS (16)
+
+enum
+{
+ PNG_DECERROR = -3,
+ PNG_ALLDONE = -5,
+ PNG_READPASTEOF = -11,
+ PNG_UNKNOWNTYPE = -16,
+ PNG_FILEREADERROR = -17,
+ PNG_NOTENOUGHMEM = -108,
+ PNG_BAD_CHUNK_CRC32 = -13000,
+ PNG_NO_IHDR = -13001,
+ PNG_BAD_WIDTH = -13002,
+ PNG_BAD_HEIGHT = -13003,
+ PNG_UNS_COMPRESSION = -13004,
+ PNG_UNS_FILTER = -13005,
+ PNG_UNS_ILACE = -13006,
+ PNG_UNS_COLOR_TYPE = -13007,
+ PNG_BAD_BIT_DEPTH = -13008,
+ PNG_BAD_CHUNK_SIZE = -13009,
+ PNG_UNS_CRITICAL_CHUNK = -13010,
+ PNG_BAD_TRNS_CHUNK = -13011,
+ PNG_BAD_PLTE_CHUNK = -13012,
+ PNG_UNS_RESOLUTION = -13013,
+ PNG_INVALID_DATA_STREAM = -13014,
+ PNG_MISSING_PALETTE = -13015,
+ PNG_UNS_PREDICTOR = -13016,
+ PNG_INCOMPLETE_IMAGE = -13017,
+ PNG_TOO_MUCH_DATA = -13018
+};
+
+#define PNG_COLOR_TYPE_PAL_MASK (1)
+#define PNG_COLOR_TYPE_COL_MASK (2)
+#define PNG_COLOR_TYPE_ALP_MASK (4)
+
+#define PNG_INFLATE_SRC_BUF_SIZE (4096)
+
+struct ihdr_struct
+{
+ uint32_t m_width;
+ uint32_t m_height;
+ uint8_t m_bit_depth;
+ uint8_t m_color_type;
+ uint8_t m_comp_type;
+ uint8_t m_filter_type;
+ uint8_t m_ilace_type;
+};
+
+class png_file
+{
+public:
+ png_file() { }
+ virtual ~png_file() { }
+
+ virtual bool resize(uint64_t new_size) = 0;
+ virtual uint64_t get_size() = 0;
+ virtual uint64_t tell() = 0;
+ virtual bool seek(uint64_t ofs) = 0;
+ virtual size_t write(const void* pBuf, size_t len) = 0;
+ virtual size_t read(void* pBuf, size_t len) = 0;
+};
+
+class png_memory_file : public png_file
+{
+public:
+ std::vector<uint8_t> m_buf;
+ uint64_t m_ofs;
+
+ png_memory_file() :
+ png_file(),
+ m_ofs(0)
+ {
+ }
+
+ virtual ~png_memory_file()
+ {
+ }
+
+ std::vector<uint8_t>& get_buf() { return m_buf; }
+ const std::vector<uint8_t>& get_buf() const { return m_buf; }
+
+ void init()
+ {
+ m_ofs = 0;
+ m_buf.resize(0);
+ }
+
+ virtual bool resize(uint64_t new_size)
+ {
+ if ((sizeof(size_t) == sizeof(uint32_t)) && (new_size >= 0x7FFFFFFF))
+ return false;
+
+ m_buf.resize((size_t)new_size);
+ m_ofs = m_buf.size();
+
+ return true;
+ }
+
+ virtual uint64_t get_size()
+ {
+ return m_buf.size();
+ }
+
+ virtual uint64_t tell()
+ {
+ return m_ofs;
+ }
+
+ virtual bool seek(uint64_t ofs)
+ {
+ m_ofs = ofs;
+ return true;
+ }
+
+ virtual size_t write(const void* pBuf, size_t len)
+ {
+ uint64_t new_size = m_ofs + len;
+ if (new_size > m_buf.size())
+ {
+ if ((sizeof(size_t) == sizeof(uint32_t)) && (new_size > 0x7FFFFFFFUL))
+ return 0;
+ m_buf.resize(new_size);
+ }
+
+ memcpy(&m_buf[(size_t)m_ofs], pBuf, len);
+ m_ofs += len;
+
+ return len;
+ }
+
+ virtual size_t read(void* pBuf, size_t len)
+ {
+ if (m_ofs >= m_buf.size())
+ return 0;
+
+ uint64_t max_bytes = minimum<uint64_t>(len, m_buf.size() - m_ofs);
+ memcpy(pBuf, &m_buf[(size_t)m_ofs], max_bytes);
+
+ m_ofs += max_bytes;
+
+ return max_bytes;
+ }
+};
+
+class png_readonly_memory_file : public png_file
+{
+public:
+ const uint8_t* m_pBuf;
+ size_t m_buf_size;
+ uint64_t m_ofs;
+
+ png_readonly_memory_file() :
+ png_file(),
+ m_pBuf(nullptr),
+ m_buf_size(0),
+ m_ofs(0)
+ {
+ }
+
+ virtual ~png_readonly_memory_file()
+ {
+ }
+
+ void init(const void *pBuf, size_t buf_size)
+ {
+ m_pBuf = static_cast<const uint8_t*>(pBuf);
+ m_buf_size = buf_size;
+ m_ofs = 0;
+ }
+
+ virtual bool resize(uint64_t new_size)
+ {
+ (void)new_size;
+ assert(0);
+ return false;
+ }
+
+ virtual uint64_t get_size()
+ {
+ return m_buf_size;
+ }
+
+ virtual uint64_t tell()
+ {
+ return m_ofs;
+ }
+
+ virtual bool seek(uint64_t ofs)
+ {
+ m_ofs = ofs;
+ return true;
+ }
+
+ virtual size_t write(const void* pBuf, size_t len)
+ {
+ (void)pBuf;
+ (void)len;
+ assert(0);
+ return 0;
+ }
+
+ virtual size_t read(void* pBuf, size_t len)
+ {
+ if (m_ofs >= m_buf_size)
+ return 0;
+
+ uint64_t max_bytes = minimum<uint64_t>(len, m_buf_size - m_ofs);
+ memcpy(pBuf, &m_pBuf[(size_t)m_ofs], max_bytes);
+
+ m_ofs += max_bytes;
+
+ return max_bytes;
+ }
+};
+
+#ifdef _MSC_VER
+#define ftell64 _ftelli64
+#define fseek64 _fseeki64
+#else
+#define ftell64 ftello
+#define fseek64 fseeko
+#endif
+
+class png_cfile : public png_file
+{
+public:
+ FILE* m_pFile;
+
+ png_cfile() :
+ png_file(),
+ m_pFile(nullptr)
+ {
+ }
+
+ virtual ~png_cfile()
+ {
+ close();
+ }
+
+ bool init(const char *pFilename, const char *pMode)
+ {
+ close();
+
+ m_pFile = nullptr;
+
+#ifdef _MSC_VER
+ fopen_s(&m_pFile, pFilename, pMode);
+#else
+ m_pFile = fopen(pFilename, pMode);
+#endif
+
+ return m_pFile != nullptr;
+ }
+
+ bool close()
+ {
+ bool status = true;
+ if (m_pFile)
+ {
+ if (fclose(m_pFile) == EOF)
+ status = false;
+ m_pFile = nullptr;
+ }
+ return status;
+ }
+
+ virtual bool resize(uint64_t new_size)
+ {
+ if (new_size)
+ {
+ if (!seek(new_size - 1))
+ return false;
+
+ int v = 0;
+ if (write(&v, 1) != 1)
+ return false;
+ }
+ else
+ {
+ if (!seek(0))
+ return false;
+ }
+
+ return true;
+ }
+
+ virtual uint64_t get_size()
+ {
+ int64_t cur_ofs = ftell64(m_pFile);
+ if (cur_ofs < 0)
+ return 0;
+
+ if (fseek64(m_pFile, 0, SEEK_END) != 0)
+ return 0;
+
+ const int64_t cur_size = ftell64(m_pFile);
+ if (cur_size < 0)
+ return 0;
+
+ if (fseek64(m_pFile, cur_ofs, SEEK_SET) != 0)
+ return 0;
+
+ return cur_size;
+ }
+
+ virtual uint64_t tell()
+ {
+ int64_t cur_ofs = ftell64(m_pFile);
+ if (cur_ofs < 0)
+ return 0;
+
+ return cur_ofs;
+ }
+
+ virtual bool seek(uint64_t ofs)
+ {
+ return fseek64(m_pFile, ofs, SEEK_SET) == 0;
+ }
+
+ virtual size_t write(const void* pBuf, size_t len)
+ {
+ return (size_t)fwrite(pBuf, 1, len, m_pFile);
+ }
+
+ virtual size_t read(void* pBuf, size_t len)
+ {
+ return (size_t)fread(pBuf, 1, len, m_pFile);
+ }
+};
+
+// This low-level helper class handles the actual decoding of PNG files.
+class png_decoder
+{
+public:
+ png_decoder();
+ ~png_decoder();
+
+ // Scans the PNG file, but doesn't decode the IDAT data.
+ // Returns 0 on success, or an error code.
+ // If the returned status is non-zero, or m_img_supported_flag==FALSE the image either the image is corrupted/not PNG or is unsupported in some way.
+ int png_scan(png_file *pFile);
+
+ // Decodes a single scanline of PNG image data.
+ // Returns a pointer to the scanline's pixel data and its size in bytes.
+ // This data is only minimally processed from the internal PNG pixel data.
+ // The caller must use the ihdr, trns_flag and values, and the palette to actually decode the pixel data.
+ //
+ // Possible returned pixel formats is somewhat complex due to the history of this code:
+ // 8-bit RGBA, always 4 bytes/pixel - 24bpp PNG's are converted to 32bpp and TRNS processing is done automatically (8/16bpp RGB or RGBA PNG files)
+ // 1/2/4/8-bit grayscale, 1 byte per pixel - must convert to [0,255] using the palette or some other means, must optionally use the TRNS chunk for alpha (1/2/4/8 Grayscale PNG files - not 16bpp though!)
+ // 1/2/4/8-bit palettized, 1 byte per pixel - must convert to RGB using the 24bpp palette and optionally the TRNS chunk for alpha (1/2/4/8bpp palettized PNG files)
+ // 8-bit grayscale with alpha, 2 bytes per pixel - TRNS processing will be done for you on 16bpp images (there's a special case here for 16bpp Grey files) (8/16bpp Gray-Alpha *or 16bpp Grayscale* PNG files)
+ //
+ // Returns 0 on success, a non-zero error code, or PNG_ALLDONE.
+ int png_decode(void** ppImg_ptr, uint32_t* pImg_len);
+
+ // Starts decoding. Returns 0 on success, otherwise an error code.
+ int png_decode_start();
+
+ // Deinitializes the decoder, freeing all allocations.
+ void png_decode_end();
+
+ png_file* m_pFile;
+
+ // Image's 24bpp palette - 3 bytes per entry
+ uint8_t m_plte_flag;
+ uint8_t m_img_pal[768];
+
+ int m_img_supported_flag;
+
+ ihdr_struct m_ihdr;
+
+ uint8_t m_chunk_flag;
+ uint32_t m_chunk_size;
+ uint32_t m_chunk_left;
+ uint32_t m_chunk_crc32;
+ uint8_t m_chunk_name[4];
+
+ uint8_t m_end_of_idat_chunks;
+
+ void* m_pMalloc_blocks[PNG_MAX_ALLOC_BLOCKS];
+
+ uint32_t m_dec_bytes_per_pixel; // bytes per pixel decoded from the PNG file (minimum 1 for 1/2/4 bpp), factors in the PNG 8/16 bit/component bit depth, may be up to 8 bytes (2*4)
+ uint32_t m_dst_bytes_per_pixel; // bytes per pixel returned to the caller (1-4), always has alpha if the PNG has alpha, 16-bit components always converted to 8-bits/component
+
+ uint32_t m_dec_bytes_per_line; // bytes per line decoded from the PNG file (before 1/2/4 expansion), +1 for the filter byte
+ uint32_t m_src_bytes_per_line; // decoded PNG bytes per line, before 1/2/4 bpp expansion, not counting the filter byte, updated during adam7 deinterlacing
+ uint32_t m_dst_bytes_per_line; // bytes per line returned to the caller (1-4 times width)
+
+ int (*m_pProcess_func)(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi);
+
+ uint8_t* m_pPre_line_buf;
+ uint8_t* m_pCur_line_buf;
+ uint8_t* m_pPro_line_buf;
+
+ uint8_t m_bkgd_flag;
+ uint32_t m_bkgd_value[3];
+
+ uint8_t m_gama_flag;
+ uint32_t m_gama_value;
+
+ uint8_t m_trns_flag;
+ uint32_t m_trns_value[256];
+
+ buminiz::mz_stream m_inflator;
+
+ uint8_t inflate_src_buf[PNG_INFLATE_SRC_BUF_SIZE];
+
+ uint32_t m_inflate_src_buf_ofs;
+ uint32_t m_inflate_src_buf_size;
+ uint32_t m_inflate_dst_buf_ofs;
+
+ int m_inflate_eof_flag;
+
+ uint8_t m_gamma_table[256];
+
+ int m_pass_x_size;
+ int m_pass_y_left;
+
+ int m_adam7_pass_num;
+ int m_adam7_pass_y;
+ int m_adam7_pass_size_x[7];
+ int m_adam7_pass_size_y[7];
+
+ std::vector<uint8_t> m_adam7_image_buf;
+
+ int m_adam7_decoded_flag;
+
+ bool m_scanned_flag;
+
+ int m_terminate_status;
+
+#define TEMP_BUF_SIZE (384)
+ uint8_t m_temp_buf[TEMP_BUF_SIZE * 4];
+
+ void clear();
+ void uninitialize();
+ int terminate(int status);
+ void* png_malloc(uint32_t i);
+ void* png_calloc(uint32_t i);
+ int block_read(void* buf, uint32_t len);
+ int64_t block_read_dword();
+ int fetch_next_chunk_data(uint8_t* buf, int bytes);
+ int fetch_next_chunk_byte();
+ int fetch_next_chunk_word();
+ int64_t fetch_next_chunk_dword();
+ int fetch_next_chunk_init();
+ int unchunk_data(uint8_t* buf, uint32_t bytes, uint32_t* ptr_bytes_read);
+ inline void adam7_write_pixel_8(int x, int y, int c);
+ inline void adam7_write_pixel_16(int x, int y, int r, int g);
+ inline void adam7_write_pixel_24(int x, int y, int r, int g, int b);
+ inline void adam7_write_pixel_32(int x, int y, int r, int g, int b, int a);
+ void unpredict_sub(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
+ void unpredict_up(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
+ void unpredict_average(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
+ inline uint8_t paeth_predictor(int a, int b, int c);
+ void unpredict_paeth(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp);
+ int adam7_pass_size(int size, int start, int step);
+ int decompress_line(uint32_t* bytes_decoded);
+ int find_iend_chunk();
+ void calc_gamma_table();
+ void create_grey_palette();
+ int read_signature();
+ int read_ihdr_chunk();
+ int read_bkgd_chunk();
+ int read_gama_chunk();
+ int read_trns_chunk();
+ int read_plte_chunk();
+ int find_idat_chunk();
+};
+
+void png_decoder::uninitialize()
+{
+ m_pFile = nullptr;
+
+ for (int i = 0; i < PNG_MAX_ALLOC_BLOCKS; i++)
+ {
+ free(m_pMalloc_blocks[i]);
+ m_pMalloc_blocks[i] = nullptr;
+ }
+
+ mz_inflateEnd(&m_inflator);
+}
+
+int png_decoder::terminate(int status)
+{
+ if (m_terminate_status == 0)
+ m_terminate_status = status;
+
+ uninitialize();
+ return status;
+}
+
+void* png_decoder::png_malloc(uint32_t len)
+{
+ if (!len)
+ len++;
+
+ void* p = malloc(len);
+
+ if (!p)
+ return nullptr;
+
+ int j;
+ for (j = 0; j < PNG_MAX_ALLOC_BLOCKS; j++)
+ if (!m_pMalloc_blocks[j])
+ break;
+
+ if (j == PNG_MAX_ALLOC_BLOCKS)
+ return nullptr;
+
+ m_pMalloc_blocks[j] = p;
+
+ return p;
+}
+
+void* png_decoder::png_calloc(uint32_t len)
+{
+ void* p = png_malloc(len);
+ if (!p)
+ return nullptr;
+
+ if (p)
+ memset(p, 0, len);
+
+ return p;
+}
+
+int png_decoder::block_read(void* buf, uint32_t len)
+{
+ size_t bytes_read = m_pFile->read(buf, len);
+ if (bytes_read != len)
+ return terminate(PNG_READPASTEOF);
+ return 0;
+}
+
+int64_t png_decoder::block_read_dword()
+{
+ uint8_t buf[4];
+
+ int status = block_read(buf, 4);
+ if (status != 0)
+ return status;
+
+ uint32_t v = buf[3] + ((uint32_t)buf[2] << 8) + ((uint32_t)buf[1] << 16) + ((uint32_t)buf[0] << 24);
+ return (int64_t)v;
+}
+
+int png_decoder::fetch_next_chunk_data(uint8_t* buf, int bytes)
+{
+ if (!m_chunk_flag)
+ return 0;
+
+ bytes = minimum<int>(bytes, m_chunk_left);
+
+ int status = block_read(buf, bytes);
+ if (status != 0)
+ return status;
+
+#if PVPNG_IDAT_CRC_CHECKING
+ bool check_crc32 = true;
+#else
+ const bool is_idat = (m_chunk_name[0] == 'I') && (m_chunk_name[1] == 'D') && (m_chunk_name[2] == 'A') && (m_chunk_name[3] == 'T');
+ bool check_crc32 = !is_idat;
+#endif
+
+ if (check_crc32)
+ m_chunk_crc32 = buminiz::mz_crc32(m_chunk_crc32, buf, bytes);
+
+ if ((m_chunk_left -= bytes) == 0)
+ {
+ int64_t res = block_read_dword();
+ if (res < 0)
+ return (int)res;
+
+ if (check_crc32)
+ {
+ if (m_chunk_crc32 != (uint32_t)res)
+ return terminate(PNG_BAD_CHUNK_CRC32);
+ }
+
+ m_chunk_flag = FALSE;
+ }
+
+ return bytes;
+}
+
+int png_decoder::fetch_next_chunk_byte()
+{
+ uint8_t buf[1];
+
+ int status = fetch_next_chunk_data(buf, 1);
+ if (status < 0)
+ return status;
+
+ if (status != 1)
+ return terminate(PNG_BAD_CHUNK_SIZE);
+
+ return buf[0];
+}
+
+int png_decoder::fetch_next_chunk_word()
+{
+ uint8_t buf[2];
+
+ int status = fetch_next_chunk_data(buf, 2);
+ if (status < 0)
+ return status;
+
+ if (status != 2)
+ return terminate(PNG_BAD_CHUNK_SIZE);
+
+ return buf[1] + ((uint32_t)buf[0] << 8);
+}
+
+int64_t png_decoder::fetch_next_chunk_dword()
+{
+ uint8_t buf[4];
+
+ int status = fetch_next_chunk_data(buf, 4);
+ if (status < 0)
+ return status;
+
+ if (status != 4)
+ terminate(PNG_BAD_CHUNK_SIZE);
+
+ uint32_t v = buf[3] + ((uint32_t)buf[2] << 8) + ((uint32_t)buf[1] << 16) + ((uint32_t)buf[0] << 24);
+ return (int64_t)v;
+}
+
+int png_decoder::fetch_next_chunk_init()
+{
+ while (m_chunk_flag)
+ {
+ int status = fetch_next_chunk_data(m_temp_buf, TEMP_BUF_SIZE * 4);
+ if (status != 0)
+ return status;
+ }
+
+ int64_t n = block_read_dword();
+ if (n < 0)
+ return (int)n;
+
+ m_chunk_size = (uint32_t)n;
+
+ m_chunk_flag = TRUE;
+ m_chunk_left = m_chunk_size + 4;
+ m_chunk_crc32 = 0;
+
+ int status = fetch_next_chunk_data(m_chunk_name, 4);
+ if (status < 0)
+ return status;
+
+ return 0;
+}
+
+int png_decoder::unchunk_data(uint8_t* buf, uint32_t bytes, uint32_t* ptr_bytes_read)
+{
+ uint32_t bytes_read = 0;
+
+ if ((!bytes) || (m_end_of_idat_chunks))
+ {
+ *ptr_bytes_read = 0;
+ return TRUE;
+ }
+
+ while (bytes_read != bytes)
+ {
+ if (!m_chunk_flag)
+ {
+ int res = fetch_next_chunk_init();
+ if (res < 0)
+ return res;
+
+ if ((m_chunk_name[0] != 'I') ||
+ (m_chunk_name[1] != 'D') ||
+ (m_chunk_name[2] != 'A') ||
+ (m_chunk_name[3] != 'T'))
+ {
+ *ptr_bytes_read = bytes_read;
+ m_end_of_idat_chunks = TRUE;
+ return TRUE;
+ }
+ }
+
+ int res = fetch_next_chunk_data(buf + bytes_read, bytes - bytes_read);
+ if (res < 0)
+ return res;
+
+ bytes_read += (uint32_t)res;
+ }
+
+ *ptr_bytes_read = bytes_read;
+
+ return FALSE;
+}
+
+inline void png_decoder::adam7_write_pixel_8(int x, int y, int c)
+{
+ m_adam7_image_buf[x + y * m_dst_bytes_per_line] = (uint8_t)c;
+}
+
+inline void png_decoder::adam7_write_pixel_16(int x, int y, int r, int g)
+{
+ uint32_t ofs = x * 2 + y * m_dst_bytes_per_line;
+ m_adam7_image_buf[ofs + 0] = (uint8_t)r;
+ m_adam7_image_buf[ofs + 1] = (uint8_t)g;
+}
+
+inline void png_decoder::adam7_write_pixel_24(int x, int y, int r, int g, int b)
+{
+ uint32_t ofs = x * 3 + y * m_dst_bytes_per_line;
+ m_adam7_image_buf[ofs + 0] = (uint8_t)r;
+ m_adam7_image_buf[ofs + 1] = (uint8_t)g;
+ m_adam7_image_buf[ofs + 2] = (uint8_t)b;
+}
+
+inline void png_decoder::adam7_write_pixel_32(int x, int y, int r, int g, int b, int a)
+{
+ uint32_t ofs = x * 4 + y * m_dst_bytes_per_line;
+ m_adam7_image_buf[ofs + 0] = (uint8_t)r;
+ m_adam7_image_buf[ofs + 1] = (uint8_t)g;
+ m_adam7_image_buf[ofs + 2] = (uint8_t)b;
+ m_adam7_image_buf[ofs + 3] = (uint8_t)a;
+}
+
+static void PixelDePack2(void* src, void* dst, int numbytes)
+{
+ uint8_t* src8 = (uint8_t*)src;
+ uint8_t* dst8 = (uint8_t*)dst;
+
+ while (numbytes)
+ {
+ uint8_t v = *src8++;
+
+ for (uint32_t i = 0; i < 8; i++)
+ dst8[7 - i] = (v >> i) & 1;
+
+ dst8 += 8;
+ numbytes--;
+ }
+}
+
+static void PixelDePack16(void* src, void* dst, int numbytes)
+{
+ uint8_t* src8 = (uint8_t*)src;
+ uint8_t* dst8 = (uint8_t*)dst;
+
+ while (numbytes)
+ {
+ uint8_t v = *src8++;
+
+ dst8[0] = (uint8_t)v >> 4;
+ dst8[1] = (uint8_t)v & 0xF;
+ dst8 += 2;
+
+ numbytes--;
+ }
+}
+
+static int unpack_grey_1(uint8_t* src, uint8_t* dst, int pixels, png_decoder *pwi)
+{
+ (void)pwi;
+ PixelDePack2(src, dst, pixels >> 3);
+
+ dst += (pixels & 0xFFF8);
+
+ if ((pixels & 7) != 0)
+ {
+ uint8_t c = src[pixels >> 3];
+
+ pixels &= 7;
+
+ while (pixels--)
+ {
+ *dst++ = ((c & 128) >> 7);
+
+ c <<= 1;
+ }
+ }
+
+ return TRUE;
+}
+
+static int unpack_grey_2(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+ int i = pixels;
+ uint8_t c;
+
+ while (i >= 4)
+ {
+ c = *src++;
+
+ *dst++ = (c >> 6);
+ *dst++ = (c >> 4) & 3;
+ *dst++ = (c >> 2) & 3;
+ *dst++ = (c) & 3;
+
+ i -= 4;
+ }
+
+ if (i)
+ {
+ c = *src;
+
+ while (i--)
+ {
+ *dst++ = (c >> 6);
+
+ c <<= 2;
+ }
+ }
+
+ return TRUE;
+}
+
+static int unpack_grey_4(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+
+ PixelDePack16(src, dst, pixels >> 1);
+
+ if (pixels & 1)
+ dst[pixels & 0xFFFE] = (src[pixels >> 1] >> 4);
+
+ return TRUE;
+}
+
+static int unpack_grey_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)src;
+ (void)dst;
+ (void)pixels;
+ (void)pwi;
+ return FALSE;
+}
+
+static int unpack_grey_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+ while (pixels--)
+ {
+ *dst++ = *src++;
+
+ src++;
+ }
+
+ return TRUE;
+}
+
+static int unpack_grey_16_2(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ if (pwi->m_trns_flag)
+ {
+ while (pixels--)
+ {
+ uint32_t v = (src[0] << 8) + src[1];
+ src += 2;
+
+ *dst++ = (uint8_t)(v >> 8);
+ *dst++ = (v == pwi->m_trns_value[0]) ? 0 : 255;
+ }
+ }
+ else
+ {
+ while (pixels--)
+ {
+ *dst++ = *src++;
+ *dst++ = 0xFF;
+
+ src++;
+ }
+ }
+
+ return TRUE;
+}
+
+static int unpack_true_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ if (pwi->m_trns_flag)
+ {
+ const uint32_t tr = pwi->m_trns_value[0];
+ const uint32_t tg = pwi->m_trns_value[1];
+ const uint32_t tb = pwi->m_trns_value[2];
+
+ for (int i = 0; i < pixels; i++)
+ {
+ uint8_t r = src[i * 3 + 0];
+ uint8_t g = src[i * 3 + 1];
+ uint8_t b = src[i * 3 + 2];
+
+ dst[i * 4 + 0] = r;
+ dst[i * 4 + 1] = g;
+ dst[i * 4 + 2] = b;
+ dst[i * 4 + 3] = ((r == tr) && (g == tg) && (b == tb)) ? 0 : 255;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < pixels; i++)
+ {
+ dst[i * 4 + 0] = src[i * 3 + 0];
+ dst[i * 4 + 1] = src[i * 3 + 1];
+ dst[i * 4 + 2] = src[i * 3 + 2];
+ dst[i * 4 + 3] = 255;
+ }
+ }
+
+ return TRUE;
+}
+
+static int unpack_true_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ if (pwi->m_trns_flag)
+ {
+ const uint32_t tr = pwi->m_trns_value[0];
+ const uint32_t tg = pwi->m_trns_value[1];
+ const uint32_t tb = pwi->m_trns_value[2];
+
+ for (int i = 0; i < pixels; i++)
+ {
+ uint32_t r = (src[i * 6 + 0] << 8) + src[i * 6 + 1];
+ uint32_t g = (src[i * 6 + 2] << 8) + src[i * 6 + 3];
+ uint32_t b = (src[i * 6 + 4] << 8) + src[i * 6 + 5];
+
+ dst[i * 4 + 0] = (uint8_t)(r >> 8);
+ dst[i * 4 + 1] = (uint8_t)(g >> 8);
+ dst[i * 4 + 2] = (uint8_t)(b >> 8);
+ dst[i * 4 + 3] = ((r == tr) && (g == tg) && (b == tb)) ? 0 : 255;
+ }
+ }
+ else
+ {
+ while (pixels--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[2];
+ dst[2] = src[4];
+ dst[3] = 255;
+
+ dst += 4;
+ src += 6;
+ }
+ }
+
+ return TRUE;
+}
+
+static int unpack_grey_alpha_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+ while (pixels--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst += 2;
+ src += 2;
+ }
+
+ return TRUE;
+}
+
+static int unpack_grey_alpha_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+ while (pixels--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[2];
+ dst += 2;
+ src += 4;
+ }
+
+ return TRUE;
+}
+
+static int unpack_true_alpha_8(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)src;
+ (void)dst;
+ (void)pixels;
+ (void)pwi;
+ return FALSE;
+}
+
+static int unpack_true_alpha_16(uint8_t* src, uint8_t* dst, int pixels, png_decoder* pwi)
+{
+ (void)pwi;
+ while (pixels--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[2];
+ dst[2] = src[4];
+ dst[3] = src[6];
+ dst += 4;
+ src += 8;
+ }
+
+ return TRUE;
+}
+
+void png_decoder::unpredict_sub(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
+{
+ (void)lst;
+ if (bytes == (uint32_t)bpp)
+ return;
+
+ cur += bpp;
+ bytes -= bpp;
+
+ while (bytes--)
+ {
+ *cur += *(cur - bpp);
+ cur++;
+ }
+}
+
+void png_decoder::unpredict_up(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
+{
+ (void)bpp;
+ while (bytes--)
+ *cur++ += *lst++;
+}
+
+void png_decoder::unpredict_average(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
+{
+ int i;
+
+ for (i = 0; i < bpp; i++)
+ *cur++ += (*lst++ >> 1);
+
+ if (bytes == (uint32_t)bpp)
+ return;
+
+ bytes -= bpp;
+
+ while (bytes--)
+ {
+ *cur += ((*lst++ + *(cur - bpp)) >> 1);
+ cur++;
+ }
+}
+
+inline uint8_t png_decoder::paeth_predictor(int a, int b, int c)
+{
+ int p, pa, pb, pc;
+
+ /* a = left, b = above, c = upper left */
+
+ p = a + b - c;
+
+ pa = abs(p - a);
+ pb = abs(p - b);
+ pc = abs(p - c);
+
+ if ((pa <= pb) && (pa <= pc))
+ return (uint8_t)a;
+ else if (pb <= pc)
+ return (uint8_t)b;
+ else
+ return (uint8_t)c;
+}
+
+void png_decoder::unpredict_paeth(uint8_t* lst, uint8_t* cur, uint32_t bytes, int bpp)
+{
+ int i;
+
+ for (i = 0; i < bpp; i++)
+ *cur++ += paeth_predictor(0, *lst++, 0);
+
+ if (bytes == (uint32_t)bpp)
+ return;
+
+ bytes -= bpp;
+
+ while (bytes--)
+ {
+ int p, a, b, c, pa, pb, pc;
+
+ a = *(cur - bpp);
+ b = *lst;
+ c = *(lst - bpp);
+
+ p = a + b - c;
+
+ pa = abs(p - a);
+ pb = abs(p - b);
+ pc = abs(p - c);
+
+ if ((pa <= pb) && (pa <= pc))
+ *cur++ += (uint8_t)a;
+ else if (pb <= pc)
+ *cur++ += (uint8_t)b;
+ else
+ *cur++ += (uint8_t)c;
+
+ lst++;
+ }
+}
+
+int png_decoder::adam7_pass_size(int size, int start, int step)
+{
+ if (size > start)
+ return 1 + ((size - 1) - start) / step;
+ else
+ return 0;
+}
+
+// TRUE if no more data, negative on error, FALSE if OK
+int png_decoder::decompress_line(uint32_t* bytes_decoded)
+{
+ int status;
+ uint32_t temp, src_bytes_left, dst_bytes_left;
+
+ m_inflate_dst_buf_ofs = 0;
+
+ for (; ; )
+ {
+ if (m_inflate_src_buf_ofs == PNG_INFLATE_SRC_BUF_SIZE)
+ {
+ int res = unchunk_data(inflate_src_buf, PNG_INFLATE_SRC_BUF_SIZE, &temp);
+ if (res < 0)
+ return res;
+ m_inflate_eof_flag = res;
+
+ m_inflate_src_buf_size = temp;
+
+ m_inflate_src_buf_ofs = 0;
+ }
+
+ for (; ; )
+ {
+ src_bytes_left = m_inflate_src_buf_size - m_inflate_src_buf_ofs;
+ dst_bytes_left = m_dec_bytes_per_line - m_inflate_dst_buf_ofs;
+
+ m_inflator.next_in = inflate_src_buf + m_inflate_src_buf_ofs;
+ m_inflator.avail_in = src_bytes_left;
+
+ m_inflator.next_out = m_pCur_line_buf + m_inflate_dst_buf_ofs;
+ m_inflator.avail_out = dst_bytes_left;
+
+ status = buminiz::mz_inflate2(&m_inflator, buminiz::MZ_NO_FLUSH, PVPNG_ADLER32_CHECKING);
+
+ const uint32_t src_bytes_consumed = src_bytes_left - m_inflator.avail_in;
+ const uint32_t dst_bytes_written = dst_bytes_left - m_inflator.avail_out;
+
+ m_inflate_src_buf_ofs += src_bytes_consumed;
+ m_inflate_dst_buf_ofs += dst_bytes_written;
+
+ if (status != buminiz::MZ_OK)
+ {
+ if (status != buminiz::MZ_STREAM_END)
+ return terminate(PNG_INVALID_DATA_STREAM);
+
+ if (bytes_decoded)
+ *bytes_decoded = m_inflate_dst_buf_ofs;
+
+ return TRUE;
+ }
+
+ if (m_inflate_dst_buf_ofs == m_dec_bytes_per_line)
+ {
+ if (bytes_decoded)
+ *bytes_decoded = m_inflate_dst_buf_ofs;
+
+ return FALSE;
+ }
+
+ if ((m_inflate_src_buf_ofs == m_inflate_src_buf_size) &&
+ (m_inflate_eof_flag == FALSE))
+ break;
+ }
+ }
+}
+
+int png_decoder::find_iend_chunk()
+{
+ uint32_t dummy;
+
+ while (!m_end_of_idat_chunks)
+ {
+ int res = unchunk_data(m_temp_buf, TEMP_BUF_SIZE * 4, &dummy);
+ if (res < 0)
+ return res;
+ }
+
+ for (; ; )
+ {
+ if ((m_chunk_name[0] == 'I') &&
+ (m_chunk_name[1] == 'E') &&
+ (m_chunk_name[2] == 'N') &&
+ (m_chunk_name[3] == 'D'))
+ break;
+
+ int res = fetch_next_chunk_init();
+ if (res < 0)
+ return res;
+ }
+
+ return 0;
+}
+
+int png_decoder::png_decode(void** ppImg_ptr, uint32_t* pImg_len)
+{
+ int status;
+ uint8_t* decoded_line;
+ uint32_t bytes_decoded;
+
+ if (m_adam7_decoded_flag)
+ {
+ if (m_pass_y_left == 0)
+ return PNG_ALLDONE;
+
+ *ppImg_ptr = &m_adam7_image_buf[(m_ihdr.m_height - m_pass_y_left) * m_dst_bytes_per_line];
+ *pImg_len = m_dst_bytes_per_line;
+
+ m_pass_y_left--;
+
+ return 0;
+ }
+
+ if (m_pass_y_left == 0)
+ {
+ if (m_ihdr.m_ilace_type == 0)
+ {
+ status = find_iend_chunk();
+ if (status < 0)
+ return status;
+
+ return PNG_ALLDONE;
+ }
+
+ for (; ; )
+ {
+ if (++m_adam7_pass_num == 7)
+ {
+ status = find_iend_chunk();
+ if (status < 0)
+ return status;
+
+ return PNG_ALLDONE;
+ }
+
+ if (((m_pass_y_left = m_adam7_pass_size_y[m_adam7_pass_num]) != 0) &&
+ ((m_pass_x_size = m_adam7_pass_size_x[m_adam7_pass_num]) != 0))
+ break;
+ }
+
+ switch (m_adam7_pass_num)
+ {
+ case 0:
+ case 1:
+ case 3:
+ case 5:
+ m_adam7_pass_y = 0;
+ break;
+ case 2:
+ m_adam7_pass_y = 4;
+ break;
+ case 4:
+ m_adam7_pass_y = 2;
+ break;
+ case 6:
+ m_adam7_pass_y = 1;
+ break;
+ }
+
+ switch (m_ihdr.m_color_type)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ case PNG_COLOR_TYPE_PALETTIZED:
+ {
+ m_src_bytes_per_line = (((uint32_t)m_pass_x_size * m_ihdr.m_bit_depth) + 7) / 8;
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ {
+ m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
+ break;
+ }
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ {
+ m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ {
+ m_src_bytes_per_line = ((uint32_t)m_pass_x_size * m_dec_bytes_per_pixel);
+ break;
+ }
+ }
+
+ m_dec_bytes_per_line = m_src_bytes_per_line + 1;
+
+ memset(m_pPre_line_buf, 0, m_src_bytes_per_line);
+ }
+
+ int res = decompress_line(&bytes_decoded);
+ if (res < 0)
+ return terminate(res);
+
+ if (res)
+ {
+ if (m_ihdr.m_ilace_type == 0)
+ {
+ if (m_pass_y_left != 1)
+ return terminate(PNG_INCOMPLETE_IMAGE);
+ }
+ else
+ {
+ if ((m_pass_y_left != 1) && (m_adam7_pass_num != 6))
+ return terminate(PNG_INCOMPLETE_IMAGE);
+ }
+ }
+
+ if (bytes_decoded != m_dec_bytes_per_line)
+ return terminate(PNG_INCOMPLETE_IMAGE);
+
+ decoded_line = &m_pCur_line_buf[1];
+
+ switch (m_pCur_line_buf[0])
+ {
+ case 0:
+ break;
+ case 1:
+ {
+ unpredict_sub(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
+ break;
+ }
+ case 2:
+ {
+ unpredict_up(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
+ break;
+ }
+ case 3:
+ {
+ unpredict_average(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
+ break;
+ }
+ case 4:
+ {
+ unpredict_paeth(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line, m_dec_bytes_per_pixel);
+ break;
+ }
+ default:
+ return terminate(PNG_UNS_PREDICTOR);
+ }
+
+ memmove(m_pPre_line_buf, m_pCur_line_buf + 1, m_src_bytes_per_line);
+
+ if (m_pProcess_func)
+ {
+ if ((*m_pProcess_func)(m_pCur_line_buf + 1, m_pPro_line_buf, m_pass_x_size, this))
+ decoded_line = m_pPro_line_buf;
+ }
+
+ if (m_ihdr.m_ilace_type == 0)
+ {
+ *ppImg_ptr = decoded_line;
+ *pImg_len = m_dst_bytes_per_line;
+
+ if (--m_pass_y_left == 0)
+ {
+ res = decompress_line(&bytes_decoded);
+ if (res < 0)
+ return terminate(res);
+
+ if (res == FALSE)
+ return terminate(PNG_TOO_MUCH_DATA);
+
+ if (bytes_decoded)
+ return terminate(PNG_TOO_MUCH_DATA);
+ }
+ }
+ else
+ {
+ int i, x_ofs = 0, y_ofs = 0, x_stp = 0;
+ uint8_t* p = decoded_line;
+
+ switch (m_adam7_pass_num)
+ {
+ case 0: { x_ofs = 0; x_stp = 8; break; }
+ case 1: { x_ofs = 4; x_stp = 8; break; }
+ case 2: { x_ofs = 0; x_stp = 4; break; }
+ case 3: { x_ofs = 2; x_stp = 4; break; }
+ case 4: { x_ofs = 0; x_stp = 2; break; }
+ case 5: { x_ofs = 1; x_stp = 2; break; }
+ case 6: { x_ofs = 0; x_stp = 1; break; }
+ }
+
+ y_ofs = m_adam7_pass_y;
+
+ assert(x_ofs < (int)m_ihdr.m_width);
+ assert(y_ofs < (int)m_ihdr.m_height);
+
+ if (m_dst_bytes_per_pixel == 1)
+ {
+ for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp)
+ adam7_write_pixel_8(x_ofs, y_ofs, *p++);
+ }
+ else if (m_dst_bytes_per_pixel == 2)
+ {
+ for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 2)
+ adam7_write_pixel_16(x_ofs, y_ofs, p[0], p[1]);
+ }
+ else if (m_dst_bytes_per_pixel == 3)
+ {
+ for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 3)
+ adam7_write_pixel_24(x_ofs, y_ofs, p[0], p[1], p[2]);
+ }
+ else if (m_dst_bytes_per_pixel == 4)
+ {
+ for (i = m_pass_x_size; i > 0; i--, x_ofs += x_stp, p += 4)
+ adam7_write_pixel_32(x_ofs, y_ofs, p[0], p[1], p[2], p[3]);
+ }
+ else
+ {
+ assert(0);
+ }
+
+ switch (m_adam7_pass_num)
+ {
+ case 0:
+ case 1:
+ case 2: { m_adam7_pass_y += 8; break; }
+ case 3:
+ case 4: { m_adam7_pass_y += 4; break; }
+ case 5:
+ case 6: { m_adam7_pass_y += 2; break; }
+ }
+
+ if ((--m_pass_y_left == 0) && (m_adam7_pass_num == 6))
+ {
+ res = decompress_line(&bytes_decoded);
+ if (res < 0)
+ return terminate(res);
+
+ if (res == FALSE)
+ return terminate(PNG_TOO_MUCH_DATA);
+
+ if (bytes_decoded)
+ return terminate(PNG_TOO_MUCH_DATA);
+ }
+ }
+
+ return 0;
+}
+
+void png_decoder::png_decode_end()
+{
+ uninitialize();
+}
+
+int png_decoder::png_decode_start()
+{
+ int status;
+
+ if (m_img_supported_flag != TRUE)
+ return terminate(m_img_supported_flag);
+
+ switch (m_ihdr.m_color_type)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ {
+ if (m_ihdr.m_bit_depth == 16)
+ {
+ // This is a special case. We can't pass back 8-bit samples and let the caller decide on transparency because the PNG is 16-bits.
+ // So we expand to 8-bit Gray-Alpha and handle transparency during decoding.
+ // We don't do this with all grayscale cases because that would require more code to deal with 1/2/4bpp expansion.
+ m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
+ m_dst_bytes_per_pixel = 2;
+
+ m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
+ m_dst_bytes_per_line = 2 * m_ihdr.m_width;
+
+ m_pProcess_func = unpack_grey_16_2;
+ }
+ else
+ {
+ m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
+ m_dst_bytes_per_pixel = 1;
+
+ m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
+ m_dst_bytes_per_line = m_ihdr.m_width;
+
+ if (m_ihdr.m_bit_depth == 1)
+ m_pProcess_func = unpack_grey_1;
+ else if (m_ihdr.m_bit_depth == 2)
+ m_pProcess_func = unpack_grey_2;
+ else if (m_ihdr.m_bit_depth == 4)
+ m_pProcess_func = unpack_grey_4;
+ else
+ m_pProcess_func = unpack_grey_8;
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_PALETTIZED:
+ {
+ m_dec_bytes_per_pixel = (m_ihdr.m_bit_depth + 7) / 8;
+ m_dst_bytes_per_pixel = 1;
+
+ m_src_bytes_per_line = (((uint32_t)m_ihdr.m_width * m_ihdr.m_bit_depth) + 7) / 8;
+ m_dst_bytes_per_line = m_ihdr.m_width;
+
+ if (m_ihdr.m_bit_depth == 1)
+ m_pProcess_func = unpack_grey_1;
+ else if (m_ihdr.m_bit_depth == 2)
+ m_pProcess_func = unpack_grey_2;
+ else if (m_ihdr.m_bit_depth == 4)
+ m_pProcess_func = unpack_grey_4;
+ else if (m_ihdr.m_bit_depth == 8)
+ m_pProcess_func = unpack_grey_8;
+ else if (m_ihdr.m_bit_depth == 16)
+ m_pProcess_func = unpack_grey_16;
+
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ {
+ // We always pass back alpha with transparency handling.
+ m_dec_bytes_per_pixel = 3 * (m_ihdr.m_bit_depth / 8);
+ m_dst_bytes_per_pixel = 4;
+
+ m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
+ m_dst_bytes_per_line = 4 * m_ihdr.m_width;
+
+ if (m_ihdr.m_bit_depth == 8)
+ m_pProcess_func = unpack_true_8;
+ else if (m_ihdr.m_bit_depth == 16)
+ m_pProcess_func = unpack_true_16;
+
+ break;
+ }
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ {
+ m_dec_bytes_per_pixel = 2 * (m_ihdr.m_bit_depth / 8);
+ m_dst_bytes_per_pixel = 2;
+
+ m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
+ m_dst_bytes_per_line = m_ihdr.m_width * 2;
+
+ if (m_ihdr.m_bit_depth == 8)
+ m_pProcess_func = unpack_grey_alpha_8;
+ else if (m_ihdr.m_bit_depth == 16)
+ m_pProcess_func = unpack_grey_alpha_16;
+
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ {
+ m_dec_bytes_per_pixel = 4 * (m_ihdr.m_bit_depth / 8);
+ m_dst_bytes_per_pixel = 4;
+
+ m_src_bytes_per_line = ((uint32_t)m_ihdr.m_width * m_dec_bytes_per_pixel);
+ m_dst_bytes_per_line = 4 * m_ihdr.m_width;
+
+ if (m_ihdr.m_bit_depth == 8)
+ m_pProcess_func = unpack_true_alpha_8;
+ else
+ m_pProcess_func = unpack_true_alpha_16;
+
+ break;
+ }
+ }
+
+ m_dec_bytes_per_line = m_src_bytes_per_line + 1;
+
+ m_pPre_line_buf = (uint8_t*)png_calloc(m_src_bytes_per_line);
+ m_pCur_line_buf = (uint8_t*)png_calloc(m_dec_bytes_per_line);
+ m_pPro_line_buf = (uint8_t*)png_calloc(m_dst_bytes_per_line);
+
+ if (!m_pPre_line_buf || !m_pCur_line_buf || !m_pPro_line_buf)
+ return terminate(PNG_NOTENOUGHMEM);
+
+ m_inflate_src_buf_ofs = PNG_INFLATE_SRC_BUF_SIZE;
+
+ int res = mz_inflateInit(&m_inflator);
+ if (res != 0)
+ return terminate(PNG_DECERROR);
+
+ if (m_ihdr.m_ilace_type == 1)
+ {
+ int i;
+ uint32_t total_lines, lines_processed;
+
+ m_adam7_pass_size_x[0] = adam7_pass_size(m_ihdr.m_width, 0, 8);
+ m_adam7_pass_size_x[1] = adam7_pass_size(m_ihdr.m_width, 4, 8);
+ m_adam7_pass_size_x[2] = adam7_pass_size(m_ihdr.m_width, 0, 4);
+ m_adam7_pass_size_x[3] = adam7_pass_size(m_ihdr.m_width, 2, 4);
+ m_adam7_pass_size_x[4] = adam7_pass_size(m_ihdr.m_width, 0, 2);
+ m_adam7_pass_size_x[5] = adam7_pass_size(m_ihdr.m_width, 1, 2);
+ m_adam7_pass_size_x[6] = adam7_pass_size(m_ihdr.m_width, 0, 1);
+
+ m_adam7_pass_size_y[0] = adam7_pass_size(m_ihdr.m_height, 0, 8);
+ m_adam7_pass_size_y[1] = adam7_pass_size(m_ihdr.m_height, 0, 8);
+ m_adam7_pass_size_y[2] = adam7_pass_size(m_ihdr.m_height, 4, 8);
+ m_adam7_pass_size_y[3] = adam7_pass_size(m_ihdr.m_height, 0, 4);
+ m_adam7_pass_size_y[4] = adam7_pass_size(m_ihdr.m_height, 2, 4);
+ m_adam7_pass_size_y[5] = adam7_pass_size(m_ihdr.m_height, 0, 2);
+ m_adam7_pass_size_y[6] = adam7_pass_size(m_ihdr.m_height, 1, 2);
+
+ m_adam7_image_buf.resize(m_dst_bytes_per_line * m_ihdr.m_height);
+
+ m_adam7_pass_num = -1;
+
+ m_pass_y_left = 0;
+
+ total_lines = lines_processed = 0;
+
+ for (i = 0; i < 7; i++)
+ total_lines += m_adam7_pass_size_y[i];
+
+ for (; ; )
+ {
+ void* dummy_ptr = nullptr;
+ uint32_t dummy_len = 0;
+
+ status = png_decode(&dummy_ptr, &dummy_len);
+
+ if (status)
+ {
+ if (status == PNG_ALLDONE)
+ break;
+ else
+ {
+ uninitialize();
+
+ return status;
+ }
+ }
+
+ lines_processed++;
+ }
+
+ m_adam7_decoded_flag = TRUE;
+ m_pass_y_left = m_ihdr.m_height;
+ }
+ else
+ {
+ m_pass_x_size = m_ihdr.m_width;
+ m_pass_y_left = m_ihdr.m_height;
+ }
+
+ return 0;
+}
+
+void png_decoder::calc_gamma_table()
+{
+ if (m_gama_value == 45000)
+ {
+ for (int i = 0; i < 256; i++)
+ m_gamma_table[i] = (uint8_t)i;
+ return;
+ }
+
+ float gamma = (float)(m_gama_value) / 100000.0f;
+
+ gamma = 1.0f / (gamma * 2.2f);
+
+ for (int i = 0; i < 256; i++)
+ {
+ float temp = powf((float)(i) / 255.0f, gamma) * 255.0f;
+
+ int j = (int)(temp + .5f);
+
+ if (j < 0)
+ j = 0;
+ else if (j > 255)
+ j = 255;
+
+ m_gamma_table[i] = (uint8_t)j;
+ }
+}
+
+void png_decoder::create_grey_palette()
+{
+ int i, j;
+ uint8_t* p = m_img_pal;
+
+ const int img_colors = minimum(256, 1 << m_ihdr.m_bit_depth);
+ for (i = 0; i < img_colors; i++)
+ {
+ j = ((uint32_t)255 * (uint32_t)i) / (img_colors - 1);
+
+ *p++ = (uint8_t)j;
+ *p++ = (uint8_t)j;
+ *p++ = (uint8_t)j;
+ }
+}
+
+int png_decoder::read_signature()
+{
+ if (m_pFile->read(m_temp_buf, 8) != 8)
+ return terminate(PNG_UNKNOWNTYPE);
+
+ if ((m_temp_buf[0] != 137) ||
+ (m_temp_buf[1] != 80) ||
+ (m_temp_buf[2] != 78) ||
+ (m_temp_buf[3] != 71) ||
+ (m_temp_buf[4] != 13) ||
+ (m_temp_buf[5] != 10) ||
+ (m_temp_buf[6] != 26) ||
+ (m_temp_buf[7] != 10))
+ {
+ return terminate(PNG_UNKNOWNTYPE);
+ }
+
+ return 0;
+}
+
+int png_decoder::read_ihdr_chunk()
+{
+ int res = fetch_next_chunk_init();
+ if (res < 0)
+ return res;
+
+ if ((m_chunk_name[0] != 'I') || (m_chunk_name[1] != 'H') || (m_chunk_name[2] != 'D') || (m_chunk_name[3] != 'R') || (m_chunk_size != 13))
+ return terminate(PNG_NO_IHDR);
+
+ int64_t v64 = fetch_next_chunk_dword();
+ if (v64 < 0)
+ return (int)v64;
+ m_ihdr.m_width = (uint32_t)v64;
+
+ v64 = fetch_next_chunk_dword();
+ if (v64 < 0)
+ return (int)v64;
+ m_ihdr.m_height = (uint32_t)v64;
+
+ if ((m_ihdr.m_width == 0) || (m_ihdr.m_width > MAX_SUPPORTED_RES))
+ return terminate(PNG_BAD_WIDTH);
+
+ if ((m_ihdr.m_height == 0) || (m_ihdr.m_height > MAX_SUPPORTED_RES))
+ return terminate(PNG_BAD_HEIGHT);
+
+ int v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_ihdr.m_bit_depth = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_ihdr.m_color_type = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_ihdr.m_comp_type = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_ihdr.m_filter_type = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_ihdr.m_ilace_type = (uint8_t)v;
+
+ if (m_ihdr.m_comp_type != 0)
+ m_img_supported_flag = PNG_UNS_COMPRESSION;
+
+ if (m_ihdr.m_filter_type != 0)
+ m_img_supported_flag = PNG_UNS_FILTER;
+
+ if (m_ihdr.m_ilace_type > 1)
+ m_img_supported_flag = PNG_UNS_ILACE;
+
+ switch (m_ihdr.m_color_type)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ {
+ switch (m_ihdr.m_bit_depth)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ {
+ break;
+ }
+ default:
+ return terminate(PNG_BAD_BIT_DEPTH);
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_PALETTIZED:
+ {
+ switch (m_ihdr.m_bit_depth)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ {
+ break;
+ }
+ default:
+ return terminate(PNG_BAD_BIT_DEPTH);
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ {
+ switch (m_ihdr.m_bit_depth)
+ {
+ case 8:
+ case 16:
+ {
+ break;
+ }
+ default:
+ return terminate(PNG_BAD_BIT_DEPTH);
+ }
+
+ break;
+ }
+ default:
+ return terminate(PNG_UNS_COLOR_TYPE);
+ }
+
+ return 0;
+}
+
+int png_decoder::read_bkgd_chunk()
+{
+ m_bkgd_flag = TRUE;
+
+ if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
+ {
+ int v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_bkgd_value[0] = v;
+ }
+ else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
+ {
+ int v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_bkgd_value[0] = v;
+ }
+ else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR_ALPHA))
+ {
+ int v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_bkgd_value[0] = v;
+
+ v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_bkgd_value[1] = v;
+
+ v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_bkgd_value[2] = v;
+ }
+
+ return 0;
+}
+
+int png_decoder::read_gama_chunk()
+{
+ m_gama_flag = TRUE;
+
+ int64_t v = fetch_next_chunk_dword();
+ if (v < 0)
+ return (int)v;
+
+ m_gama_value = (uint32_t)v;
+
+ return 0;
+}
+
+int png_decoder::read_trns_chunk()
+{
+ int i;
+
+ m_trns_flag = TRUE;
+
+ if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
+ {
+ for (i = 0; i < 256; i++)
+ m_trns_value[i] = 255;
+
+ const uint32_t img_colors = 1 << m_ihdr.m_bit_depth;
+ if (m_chunk_size > (uint32_t)img_colors)
+ return terminate(PNG_BAD_TRNS_CHUNK);
+
+ for (i = 0; i < (int)m_chunk_size; i++)
+ {
+ int v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ m_trns_value[i] = v;
+ }
+ }
+ else if (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE)
+ {
+ int v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_trns_value[0] = v;
+ }
+ else if (m_ihdr.m_color_type == PNG_COLOR_TYPE_TRUECOLOR)
+ {
+ int v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_trns_value[0] = v;
+
+ v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_trns_value[1] = v;
+
+ v = fetch_next_chunk_word();
+ if (v < 0)
+ return v;
+ m_trns_value[2] = v;
+ }
+ else
+ {
+ return terminate(PNG_BAD_TRNS_CHUNK);
+ }
+ return 0;
+}
+
+int png_decoder::read_plte_chunk()
+{
+ int i, j;
+ uint8_t* p;
+
+ if (m_plte_flag)
+ return terminate(PNG_BAD_PLTE_CHUNK);
+
+ m_plte_flag = TRUE;
+
+ memset(m_img_pal, 0, 768);
+
+ if (m_chunk_size % 3)
+ return terminate(PNG_BAD_PLTE_CHUNK);
+
+ j = m_chunk_size / 3;
+
+ const int img_colors = minimum(256, 1 << m_ihdr.m_bit_depth);
+ if (j > img_colors)
+ return terminate(PNG_BAD_PLTE_CHUNK);
+
+ if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) ||
+ (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
+ return terminate(PNG_BAD_PLTE_CHUNK);
+
+ p = m_img_pal;
+
+ for (i = 0; i < j; i++)
+ {
+ int v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ *p++ = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ *p++ = (uint8_t)v;
+
+ v = fetch_next_chunk_byte();
+ if (v < 0)
+ return v;
+ *p++ = (uint8_t)v;
+ }
+
+ return 0;
+}
+
+int png_decoder::find_idat_chunk()
+{
+ for (; ; )
+ {
+ int res = fetch_next_chunk_init();
+ if (res < 0)
+ return res;
+
+ if (m_chunk_name[0] & 32) /* ancillary? */
+ {
+ if ((m_chunk_name[0] == 'b') && (m_chunk_name[1] == 'K') && (m_chunk_name[2] == 'G') && (m_chunk_name[3] == 'D'))
+ {
+ res = read_bkgd_chunk();
+ if (res < 0)
+ return res;
+ }
+ else if ((m_chunk_name[0] == 'g') && (m_chunk_name[1] == 'A') && (m_chunk_name[2] == 'M') && (m_chunk_name[3] == 'A'))
+ {
+ res = read_gama_chunk();
+ if (res < 0)
+ return res;
+ }
+ else if ((m_chunk_name[0] == 't') && (m_chunk_name[1] == 'R') && (m_chunk_name[2] == 'N') && (m_chunk_name[3] == 'S'))
+ {
+ res = read_trns_chunk();
+ if (res < 0)
+ return res;
+ }
+ }
+ else
+ {
+ if ((m_chunk_name[0] == 'P') && (m_chunk_name[1] == 'L') && (m_chunk_name[2] == 'T') && (m_chunk_name[3] == 'E'))
+ {
+ res = read_plte_chunk();
+ if (res < 0)
+ return res;
+ }
+ else if ((m_chunk_name[0] == 'I') && (m_chunk_name[1] == 'D') && (m_chunk_name[2] == 'A') && (m_chunk_name[3] == 'T'))
+ {
+ break;
+ }
+ else
+ {
+ m_img_supported_flag = PNG_UNS_CRITICAL_CHUNK;
+ }
+ }
+ }
+
+ return 0;
+}
+
+png_decoder::png_decoder()
+{
+ clear();
+}
+
+png_decoder::~png_decoder()
+{
+ uninitialize();
+}
+
+void png_decoder::clear()
+{
+ clear_obj(m_pMalloc_blocks);
+
+ m_pFile = nullptr;
+
+ clear_obj(m_img_pal);
+
+ m_img_supported_flag = FALSE;
+
+ m_adam7_image_buf.clear();
+
+ clear_obj(m_ihdr);
+
+ m_chunk_flag = FALSE;
+ m_chunk_size = 0;
+ m_chunk_left = 0;
+ m_chunk_crc32 = 0;
+ clear_obj(m_chunk_name);
+
+ m_end_of_idat_chunks = 0;
+
+ m_dec_bytes_per_pixel = 0;
+ m_dst_bytes_per_pixel = 0;
+
+ m_dec_bytes_per_line = 0;
+ m_src_bytes_per_line = 0;
+ m_dst_bytes_per_line = 0;
+
+ m_pProcess_func = nullptr;
+
+ m_pPre_line_buf = nullptr;
+ m_pCur_line_buf = nullptr;
+ m_pPro_line_buf = nullptr;
+
+ m_bkgd_flag = FALSE;
+ clear_obj(m_bkgd_value);
+
+ m_gama_flag = FALSE;
+ m_gama_value = 0;
+
+ m_plte_flag = FALSE;
+
+ m_trns_flag = FALSE;
+ clear_obj(m_trns_value);
+
+ clear_obj(m_inflator);
+
+ m_inflate_src_buf_ofs = 0;
+ m_inflate_src_buf_size = 0;
+ m_inflate_dst_buf_ofs = 0;
+
+ m_inflate_eof_flag = FALSE;
+
+ clear_obj(m_trns_value);
+
+ m_pass_x_size = 0;
+ m_pass_y_left = 0;
+
+ m_adam7_pass_num = 0;
+ m_adam7_pass_y = 0;
+ clear_obj(m_adam7_pass_size_x);
+ clear_obj(m_adam7_pass_size_y);
+
+ m_adam7_decoded_flag = FALSE;
+
+ m_scanned_flag = false;
+
+ m_terminate_status = 0;
+}
+
+int png_decoder::png_scan(png_file *pFile)
+{
+ m_pFile = pFile;
+
+ m_img_supported_flag = TRUE;
+ m_terminate_status = 0;
+
+ int res = read_signature();
+ if (res != 0)
+ return res;
+
+ res = read_ihdr_chunk();
+ if (res != 0)
+ return res;
+
+ res = find_idat_chunk();
+ if (res != 0)
+ return res;
+
+ if (m_gama_flag)
+ calc_gamma_table();
+
+ if (m_ihdr.m_color_type == PNG_COLOR_TYPE_PALETTIZED)
+ {
+ if (!m_plte_flag)
+ return terminate(PNG_MISSING_PALETTE);
+ }
+ else if ((m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE) || (m_ihdr.m_color_type == PNG_COLOR_TYPE_GREYSCALE_ALPHA))
+ {
+ create_grey_palette();
+ }
+
+ m_scanned_flag = true;
+
+ return 0;
+}
+
+static inline uint8_t get_709_luma(uint32_t r, uint32_t g, uint32_t b)
+{
+ return (uint8_t)((13938U * r + 46869U * g + 4729U * b + 32768U) >> 16U);
+}
+
+bool get_png_info(const void* pImage_buf, size_t buf_size, png_info &info)
+{
+ memset(&info, 0, sizeof(info));
+
+ if ((!pImage_buf) || (buf_size < MIN_PNG_SIZE))
+ return false;
+
+ png_readonly_memory_file mf;
+ mf.init(pImage_buf, buf_size);
+
+ png_decoder dec;
+
+ int status = dec.png_scan(&mf);
+ if ((status != 0) || (dec.m_img_supported_flag != TRUE))
+ return false;
+
+ info.m_width = dec.m_ihdr.m_width;
+ info.m_height = dec.m_ihdr.m_height;
+ info.m_bit_depth = dec.m_ihdr.m_bit_depth;
+ info.m_color_type = dec.m_ihdr.m_color_type;
+ info.m_has_gamma = dec.m_gama_flag != 0;
+ info.m_gamma_value = dec.m_gama_value;
+ info.m_has_trns = dec.m_trns_flag != 0;
+
+ switch (dec.m_ihdr.m_color_type)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ info.m_num_chans = dec.m_trns_flag ? 2 : 1;
+ break;
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ info.m_num_chans = 2;
+ break;
+ case PNG_COLOR_TYPE_PALETTIZED:
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ info.m_num_chans = dec.m_trns_flag ? 4 : 3;
+ break;
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ info.m_num_chans = 4;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ return true;
+}
+
+void* load_png(const void* pImage_buf, size_t buf_size, uint32_t desired_chans, uint32_t& width, uint32_t& height, uint32_t& num_chans)
+{
+ width = 0;
+ height = 0;
+ num_chans = 0;
+
+ if ((!pImage_buf) || (buf_size < MIN_PNG_SIZE))
+ {
+ assert(0);
+ return nullptr;
+ }
+
+ if (desired_chans > 4)
+ {
+ assert(0);
+ return nullptr;
+ }
+
+ png_readonly_memory_file mf;
+ mf.init(pImage_buf, buf_size);
+
+ png_decoder dec;
+
+ int status = dec.png_scan(&mf);
+ if ((status != 0) || (dec.m_img_supported_flag != TRUE))
+ return nullptr;
+
+ uint32_t colortype = dec.m_ihdr.m_color_type;
+ switch (colortype)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ num_chans = dec.m_trns_flag ? 2 : 1;
+ break;
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ num_chans = 2;
+ break;
+ case PNG_COLOR_TYPE_PALETTIZED:
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ num_chans = dec.m_trns_flag ? 4 : 3;
+ break;
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ num_chans = 4;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (!desired_chans)
+ desired_chans = num_chans;
+
+#if 0
+ printf("lode_png: %ux%u bitdepth: %u colortype: %u trns: %u ilace: %u\n",
+ dec.m_ihdr.m_width,
+ dec.m_ihdr.m_height,
+ dec.m_ihdr.m_bit_depth,
+ dec.m_ihdr.m_color_type,
+ dec.m_trns_flag,
+ dec.m_ihdr.m_ilace_type);
+#endif
+
+ width = dec.m_ihdr.m_width;
+ height = dec.m_ihdr.m_height;
+ uint32_t bitdepth = dec.m_ihdr.m_bit_depth;
+ uint32_t pitch = width * desired_chans;
+
+ uint64_t total_size = (uint64_t)pitch * height;
+ if (total_size > 0x7FFFFFFFULL)
+ return nullptr;
+
+ uint8_t* pBuf = (uint8_t*)malloc((size_t)total_size);
+ if (!pBuf)
+ return nullptr;
+
+ if (dec.png_decode_start() != 0)
+ {
+ free(pBuf);
+ return nullptr;
+ }
+
+ uint8_t* pDst = pBuf;
+
+ for (uint32_t y = 0; y < height; y++, pDst += pitch)
+ {
+ uint8_t* pLine;
+ uint32_t line_bytes;
+ if (dec.png_decode((void**)&pLine, &line_bytes) != 0)
+ {
+ free(pBuf);
+ return nullptr;
+ }
+
+ // This conversion matrix handles converting RGB->Luma, converting grayscale samples to 8-bit samples, converting palettized images, and PNG transparency.
+ switch (colortype)
+ {
+ case PNG_COLOR_TYPE_GREYSCALE:
+ {
+ uint32_t trans_value = dec.m_trns_value[0];
+
+ switch (desired_chans)
+ {
+ case 1:
+ if (bitdepth == 16)
+ {
+ assert(line_bytes == width * 2);
+
+ for (uint32_t i = 0; i < width; i++)
+ pDst[i] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ }
+ else if (bitdepth == 8)
+ {
+ assert(line_bytes == width);
+ memcpy(pDst, pLine, pitch);
+ }
+ else
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ pDst[i] = dec.m_img_pal[pLine[i] * 3];
+ }
+ break;
+ case 2:
+ if (bitdepth == 16)
+ {
+ assert(line_bytes == width * 2);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ pDst[i * 2 + 0] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 2 + 1] = pLine[i * 2 + 1];
+ }
+ }
+ else if (dec.m_trns_flag)
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ pDst[i * 2 + 0] = dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 2 + 1] = (pLine[i] == trans_value) ? 0 : 255;
+ }
+ }
+ else
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ pDst[i * 2 + 0] = dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 2 + 1] = 255;
+ }
+ }
+ break;
+ case 3:
+ if (bitdepth == 16)
+ {
+ assert(line_bytes == width * 2);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 3 + 0] = c;
+ pDst[i * 3 + 1] = c;
+ pDst[i * 3 + 2] = c;
+ }
+ }
+ else
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 3 + 0] = c;
+ pDst[i * 3 + 1] = c;
+ pDst[i * 3 + 2] = c;
+ }
+ }
+ break;
+ case 4:
+ if (bitdepth == 16)
+ {
+ assert(line_bytes == width * 2);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 4 + 0] = c;
+ pDst[i * 4 + 1] = c;
+ pDst[i * 4 + 2] = c;
+ pDst[i * 4 + 3] = pLine[i * 2 + 1];
+ }
+ }
+ else if (dec.m_trns_flag)
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 4 + 0] = c;
+ pDst[i * 4 + 1] = c;
+ pDst[i * 4 + 2] = c;
+ pDst[i * 4 + 3] = (pLine[i] == trans_value) ? 0 : 255;
+ }
+ }
+ else
+ {
+ assert(line_bytes == width);
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 4 + 0] = c;
+ pDst[i * 4 + 1] = c;
+ pDst[i * 4 + 2] = c;
+ pDst[i * 4 + 3] = 255;
+ }
+ }
+ break;
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_GREYSCALE_ALPHA:
+ {
+ assert(line_bytes == width * 2);
+
+ switch (desired_chans)
+ {
+ case 1:
+ for (uint32_t i = 0; i < width; i++)
+ pDst[i] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ break;
+ case 2:
+ assert(line_bytes == pitch);
+ if (bitdepth >= 8)
+ memcpy(pDst, pLine, pitch);
+ else
+ {
+ for (uint32_t i = 0; i < width; i++)
+ {
+ pDst[i * 2 + 0] = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 2 + 1] = pLine[i * 2 + 1];
+ }
+ }
+ break;
+ case 3:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 3 + 0] = c;
+ pDst[i * 3 + 1] = c;
+ pDst[i * 3 + 2] = c;
+ }
+ break;
+ case 4:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ uint8_t c = dec.m_img_pal[pLine[i * 2 + 0] * 3];
+ pDst[i * 4 + 0] = c;
+ pDst[i * 4 + 1] = c;
+ pDst[i * 4 + 2] = c;
+ pDst[i * 4 + 3] = pLine[i * 2 + 1];
+ }
+ break;
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_PALETTIZED:
+ {
+ assert(line_bytes == width);
+
+ switch (desired_chans)
+ {
+ case 1:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i] = get_709_luma(p[0], p[1], p[2]);
+ }
+ break;
+ case 2:
+ if (dec.m_trns_flag)
+ {
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
+ pDst[i * 2 + 1] = (uint8_t)dec.m_trns_value[pLine[i]];
+ }
+ }
+ else
+ {
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
+ pDst[i * 2 + 1] = 255;
+ }
+ }
+ break;
+ case 3:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 3 + 0] = p[0];
+ pDst[i * 3 + 1] = p[1];
+ pDst[i * 3 + 2] = p[2];
+ }
+ break;
+ case 4:
+ if (dec.m_trns_flag)
+ {
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 4 + 0] = p[0];
+ pDst[i * 4 + 1] = p[1];
+ pDst[i * 4 + 2] = p[2];
+ pDst[i * 4 + 3] = (uint8_t)dec.m_trns_value[pLine[i]];
+ }
+ }
+ else
+ {
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &dec.m_img_pal[pLine[i] * 3];
+ pDst[i * 4 + 0] = p[0];
+ pDst[i * 4 + 1] = p[1];
+ pDst[i * 4 + 2] = p[2];
+ pDst[i * 4 + 3] = 255;
+ }
+ }
+ break;
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_TRUECOLOR:
+ case PNG_COLOR_TYPE_TRUECOLOR_ALPHA:
+ {
+ assert(line_bytes == width * 4);
+
+ switch (desired_chans)
+ {
+ case 1:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &pLine[i * 4];
+ pDst[i] = get_709_luma(p[0], p[1], p[2]);
+ }
+ break;
+ case 2:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &pLine[i * 4];
+ pDst[i * 2 + 0] = get_709_luma(p[0], p[1], p[2]);
+ pDst[i * 2 + 1] = p[3];
+ }
+ break;
+ case 3:
+ for (uint32_t i = 0; i < width; i++)
+ {
+ const uint8_t* p = &pLine[i * 4];
+ pDst[i * 3 + 0] = p[0];
+ pDst[i * 3 + 1] = p[1];
+ pDst[i * 3 + 2] = p[2];
+ }
+ break;
+ case 4:
+ memcpy(pDst, pLine, pitch);
+ break;
+ }
+
+ break;
+ }
+ default:
+ assert(0);
+ break;
+ }
+
+ } // y
+
+ return pBuf;
+}
+
+} // namespace pv_png
+
+/*
+ This is free and unencumbered software released into the public domain.
+
+ Anyone is free to copy, modify, publish, use, compile, sell, or
+ distribute this software, either in source code form or as a compiled
+ binary, for any purpose, commercial or non-commercial, and by any
+ means.
+
+ In jurisdictions that recognize copyright laws, the author or authors
+ of this software dedicate any and all copyright interest in the
+ software to the public domain. We make this dedication for the benefit
+ of the public at large and to the detriment of our heirs and
+ successors. We intend this dedication to be an overt act of
+ relinquishment in perpetuity of all present and future rights to this
+ software under copyright law.
+
+ 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 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.
+
+ For more information, please refer to <http://unlicense.org/>
+
+ Richard Geldreich, Jr.
+ 1/20/2022
+*/
diff --git a/thirdparty/basis_universal/encoder/pvpngreader.h b/thirdparty/basis_universal/encoder/pvpngreader.h
new file mode 100644
index 0000000000..4f3fe46b82
--- /dev/null
+++ b/thirdparty/basis_universal/encoder/pvpngreader.h
@@ -0,0 +1,48 @@
+// pngreader.h - Public Domain - see unlicense at bottom of pvpngreader.cpp
+#pragma once
+#include <stdint.h>
+
+namespace pv_png
+{
+ // PNG color types
+ enum
+ {
+ PNG_COLOR_TYPE_GREYSCALE = 0,
+ PNG_COLOR_TYPE_TRUECOLOR = 2,
+ PNG_COLOR_TYPE_PALETTIZED = 3,
+ PNG_COLOR_TYPE_GREYSCALE_ALPHA = 4,
+ PNG_COLOR_TYPE_TRUECOLOR_ALPHA = 6
+ };
+
+ // PNG file description
+ struct png_info
+ {
+ uint32_t m_width;
+ uint32_t m_height;
+
+ uint32_t m_num_chans; // The number of channels, factoring in transparency. Ranges from [1-4].
+
+ uint32_t m_bit_depth; // PNG ihdr bit depth: 1, 2, 4, 8 or 16
+ uint32_t m_color_type; // PNG ihdr color type, PNG_COLOR_TYPE_GRAYSCALE etc.
+
+ bool m_has_gamma; // true if the PNG file had a GAMA chunk
+ uint32_t m_gamma_value; // PNG GAMA chunk value, scaled by 100000
+
+ bool m_has_trns; // true if the PNG file used colorkey transparency
+ };
+
+ // Retrieved information about the PNG file.
+ // Returns false on any errors.
+ bool get_png_info(const void* pImage_buf, size_t buf_size, png_info& info);
+
+ // Input parameters:
+ // pImage_buf, buf_size - pointer to PNG image data
+ // desired_chans - desired number of output channels. 0=auto, 1=grayscale, 2=grayscale alpha, 3=24bpp RGB, 4=32bpp RGBA
+ //
+ // Output parameters:
+ // width, height - PNG image resolution
+ // num_chans - actual number of channels in PNG, from [1,4] (factoring in transparency)
+ //
+ // Returns nullptr on any errors.
+ void* load_png(const void* pImage_buf, size_t buf_size, uint32_t desired_chans, uint32_t &width, uint32_t &height, uint32_t& num_chans);
+}
diff --git a/thirdparty/basis_universal/transcoder/basisu.h b/thirdparty/basis_universal/transcoder/basisu.h
index f33baf67c8..1230b59ec6 100644
--- a/thirdparty/basis_universal/transcoder/basisu.h
+++ b/thirdparty/basis_universal/transcoder/basisu.h
@@ -21,6 +21,11 @@
#pragma warning (disable : 4127) // warning C4127: conditional expression is constant
#pragma warning (disable : 4530) // C++ exception handler used, but unwind semantics are not enabled.
+ // Slamming this off always for v1.16 because we've gotten rid of most std containers.
+ #ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
+ #define BASISU_NO_ITERATOR_DEBUG_LEVEL (1)
+ #endif
+
#ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL
//#define _HAS_ITERATOR_DEBUGGING 0
@@ -165,6 +170,10 @@ namespace basisu
{
if (n)
{
+ if (vec.size())
+ {
+ assert((pObjs + n) <= vec.begin() || (pObjs >= vec.end()));
+ }
const size_t cur_s = vec.size();
vec.resize(cur_s + n);
memcpy(&vec[cur_s], pObjs, sizeof(R) * n);
@@ -173,6 +182,7 @@ namespace basisu
template<typename T> inline void append_vector(T &vec, const T &other_vec)
{
+ assert(&vec != &other_vec);
if (other_vec.size())
append_vector(vec, &other_vec[0], other_vec.size());
}
diff --git a/thirdparty/basis_universal/transcoder/basisu_containers.h b/thirdparty/basis_universal/transcoder/basisu_containers.h
index 1ca4bab307..d3e14369ba 100644
--- a/thirdparty/basis_universal/transcoder/basisu_containers.h
+++ b/thirdparty/basis_universal/transcoder/basisu_containers.h
@@ -12,6 +12,12 @@
#define HAS_MALLOC_USABLE_SIZE 1
#endif
+// Set to 1 to always check vector operator[], front(), and back() even in release.
+#define BASISU_VECTOR_FORCE_CHECKING 0
+
+// If 1, the vector container will not query the CRT to get the size of resized memory blocks.
+#define BASISU_VECTOR_DETERMINISTIC 1
+
#ifdef _MSC_VER
#define BASISU_FORCE_INLINE __forceinline
#else
@@ -279,7 +285,10 @@ namespace basisu
m_size = other.m_size;
if (BASISU_IS_BITWISE_COPYABLE(T))
- memcpy(m_p, other.m_p, m_size * sizeof(T));
+ {
+ if ((m_p) && (other.m_p))
+ memcpy(m_p, other.m_p, m_size * sizeof(T));
+ }
else
{
T* pDst = m_p;
@@ -320,7 +329,10 @@ namespace basisu
}
if (BASISU_IS_BITWISE_COPYABLE(T))
- memcpy(m_p, other.m_p, other.m_size * sizeof(T));
+ {
+ if ((m_p) && (other.m_p))
+ memcpy(m_p, other.m_p, other.m_size * sizeof(T));
+ }
else
{
T* pDst = m_p;
@@ -348,20 +360,81 @@ namespace basisu
// operator[] will assert on out of range indices, but in final builds there is (and will never be) any range checking on this method.
//BASISU_FORCE_INLINE const T& operator[] (uint32_t i) const { assert(i < m_size); return m_p[i]; }
//BASISU_FORCE_INLINE T& operator[] (uint32_t i) { assert(i < m_size); return m_p[i]; }
-
+
+#if !BASISU_VECTOR_FORCE_CHECKING
BASISU_FORCE_INLINE const T& operator[] (size_t i) const { assert(i < m_size); return m_p[i]; }
BASISU_FORCE_INLINE T& operator[] (size_t i) { assert(i < m_size); return m_p[i]; }
+#else
+ BASISU_FORCE_INLINE const T& operator[] (size_t i) const
+ {
+ if (i >= m_size)
+ {
+ fprintf(stderr, "operator[] invalid index: %u, max entries %u, type size %u\n", (uint32_t)i, m_size, (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[i];
+ }
+ BASISU_FORCE_INLINE T& operator[] (size_t i)
+ {
+ if (i >= m_size)
+ {
+ fprintf(stderr, "operator[] invalid index: %u, max entries %u, type size %u\n", (uint32_t)i, m_size, (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[i];
+ }
+#endif
// at() always includes range checking, even in final builds, unlike operator [].
// The first element is returned if the index is out of range.
BASISU_FORCE_INLINE const T& at(size_t i) const { assert(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; }
BASISU_FORCE_INLINE T& at(size_t i) { assert(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; }
-
+
+#if !BASISU_VECTOR_FORCE_CHECKING
BASISU_FORCE_INLINE const T& front() const { assert(m_size); return m_p[0]; }
BASISU_FORCE_INLINE T& front() { assert(m_size); return m_p[0]; }
BASISU_FORCE_INLINE const T& back() const { assert(m_size); return m_p[m_size - 1]; }
BASISU_FORCE_INLINE T& back() { assert(m_size); return m_p[m_size - 1]; }
+#else
+ BASISU_FORCE_INLINE const T& front() const
+ {
+ if (!m_size)
+ {
+ fprintf(stderr, "front: vector is empty, type size %u\n", (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[0];
+ }
+ BASISU_FORCE_INLINE T& front()
+ {
+ if (!m_size)
+ {
+ fprintf(stderr, "front: vector is empty, type size %u\n", (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[0];
+ }
+
+ BASISU_FORCE_INLINE const T& back() const
+ {
+ if(!m_size)
+ {
+ fprintf(stderr, "back: vector is empty, type size %u\n", (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[m_size - 1];
+ }
+ BASISU_FORCE_INLINE T& back()
+ {
+ if (!m_size)
+ {
+ fprintf(stderr, "back: vector is empty, type size %u\n", (uint32_t)sizeof(T));
+ abort();
+ }
+ return m_p[m_size - 1];
+ }
+#endif
BASISU_FORCE_INLINE const T* get_ptr() const { return m_p; }
BASISU_FORCE_INLINE T* get_ptr() { return m_p; }
@@ -952,6 +1025,8 @@ namespace basisu
// Caller is granting ownership of the indicated heap block.
// Block must have size constructed elements, and have enough room for capacity elements.
+ // The block must have been allocated using malloc().
+ // Important: This method is used in Basis Universal. If you change how this container allocates memory, you'll need to change any users of this method.
inline bool grant_ownership(T* p, uint32_t size, uint32_t capacity)
{
// To to prevent the caller from obviously shooting themselves in the foot.
diff --git a/thirdparty/basis_universal/transcoder/basisu_containers_impl.h b/thirdparty/basis_universal/transcoder/basisu_containers_impl.h
index 6555171419..d5cb61569b 100644
--- a/thirdparty/basis_universal/transcoder/basisu_containers_impl.h
+++ b/thirdparty/basis_universal/transcoder/basisu_containers_impl.h
@@ -55,7 +55,9 @@ namespace basisu
abort();
}
-#ifdef _MSC_VER
+#if BASISU_VECTOR_DETERMINISTIC
+ actual_size = desired_size;
+#elif defined(_MSC_VER)
actual_size = _msize(new_p);
#elif HAS_MALLOC_USABLE_SIZE
actual_size = malloc_usable_size(new_p);
@@ -82,7 +84,9 @@ namespace basisu
abort();
}
-#ifdef _MSC_VER
+#if BASISU_VECTOR_DETERMINISTIC
+ actual_size = desired_size;
+#elif defined(_MSC_VER)
actual_size = _msize(new_p);
#elif HAS_MALLOC_USABLE_SIZE
actual_size = malloc_usable_size(new_p);
diff --git a/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h b/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h
deleted file mode 100644
index 8ab5098898..0000000000
--- a/thirdparty/basis_universal/transcoder/basisu_global_selector_cb.h
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright (C) 2019-2020 Binomial LLC. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-{
-0x0, 0x505, 0x5555, 0x5F5F, 0x5055050, 0x5055F5F, 0x50AAA551, 0xFAA5A5AA, 0x6AAA5095, 0x41E6FBAB, 0x19AE99F5, 0x1057AAA4, 0x54005A1A, 0x4459AEAF, 0x56015B, 0xBAA9A554,
-0x4335E5E0, 0xD9FE5FBB, 0x2525256A, 0x9AE892, 0xC0D5FAF5, 0x5BA5E641, 0x7EDEC8B8, 0xBB671211, 0x4C9844EE, 0xEE042415, 0xE5663EAE, 0x90909091, 0xAAA45AFF, 0x15556E1D, 0xA6959195, 0x4BFF8BF,
-0x5166AAF, 0x15490065, 0x6F5BAFAF, 0xFF00FF00, 0xD96956AA, 0x15AF6B, 0xFF5A00AA, 0xE0E557AA, 0x1A6F19BD, 0x69655555, 0xD0500158, 0xEEEDD894, 0xE4E4FE, 0xC71B7B10, 0x55AA5AAF, 0x50AA59BE,
-0xE4E990E4, 0x5353B63B, 0xFEE5D0E4, 0x96AF051A, 0x3CC95A6, 0x70B5A40D, 0x9504196E, 0x4A0BD7A3, 0x11B89592, 0xAAFF4095, 0x55A5D4E0, 0xBBA55050, 0x1111666, 0xA5544000, 0xED994444, 0x5A56BF,
-0x94A954B9, 0xFB651000, 0x604E633E, 0x14291A15, 0x56965956, 0xB8E0D0C0, 0x5A565A55, 0x65A61A6A, 0xE490F990, 0xCA87AAF5, 0x6060A0B, 0x24C23143, 0x55AA9A40, 0x505E1605, 0xCEC0486E, 0x156E55EA,
-0x79978B0B, 0x4595F53C, 0x405C4AF7, 0xC1897D75, 0xD5F40BA6, 0x95444017, 0x14AD6935, 0x87C7A7BD, 0x4A4E8597, 0xFF1D7E55, 0x451400F9, 0x1112277B, 0x9A0590F8, 0x53E3492E, 0xE590E995, 0x7E730A9A,
-0x929697E7, 0x2E781609, 0xE22317A1, 0xEDE9D884, 0xDDD75CDD, 0xAF1B6F1A, 0xE6909047, 0xA77DAD5D, 0x184C0D5D, 0xFAB56010, 0x5EA4F1D0, 0x11166B6B, 0xF51A7AD6, 0xF79950F4, 0x1B6B1B11, 0x9A6D6469,
-0x441997E, 0x4546869A, 0x95AA6965, 0x155A6A, 0x6E68B0E6, 0x5A55A665, 0x1B051605, 0x601D8BE6, 0xBD2F1B06, 0x409A429B, 0x23272721, 0xB07454A9, 0x7E66A3A1, 0x1B6A5500, 0xA0E0F5A6, 0xBF5A0500,
-0x55A5A9A9, 0x99D9E995, 0xE440566F, 0x6550BE99, 0x2267777B, 0xFA50FE50, 0xA657B441, 0xB4E29343, 0x555090E5, 0x45465B6B, 0xE654E6, 0xEA90469B, 0x2E05D2F4, 0x99594444, 0xF1C20746, 0x295AD2E0,
-0xF990EA95, 0x804459AE, 0xA9999894, 0x1F41E4A5, 0x4040E5E5, 0x5481E1F2, 0x2AFF59F1, 0x6B6B1712, 0xA7131051, 0xF9406F16, 0x1B2B5B9E, 0x587E0F2F, 0x547E1919, 0xD0F5645B, 0xB1B1B1B, 0x5756A4FE,
-0x46A9B965, 0x1529F99D, 0xE490E490, 0x4495FE, 0x985E0B06, 0x5FD2D23A, 0x5D0E95A, 0xF69103F4, 0x4029790, 0x1B062F1B, 0xEE594500, 0xB6539B5A, 0x106165BA, 0xD26B7C8D, 0x8B2A25A5, 0x55EAD5E3,
-0x431FB8E1, 0xBEB4E646, 0x9A5A4545, 0x5015A6B, 0x90D4B83D, 0xDB8A99A4, 0x9E894905, 0xDD7D1101, 0xA95E00BF, 0x579FA5A5, 0xA292D145, 0x93292C96, 0xF9A995A5, 0xBFE8A450, 0xB990D15B, 0x45D1E01A,
-0x4BD3F767, 0xF243479A, 0x7E420927, 0xF9E5E090, 0xA1C869F, 0x253A36, 0x9BAB569A, 0x4147031F, 0xA059AFE, 0xE0D6590F, 0xD5EAD5E6, 0x9A4B4641, 0x5AAA4406, 0x55EA90E4, 0x10179BC4, 0x44485999,
-0x5156253E, 0x1F29E054, 0xCDDAA773, 0x5601AB05, 0x94FC94C0, 0x116166BB, 0xBF964006, 0x414196EB, 0x8498D9ED, 0xB5E08687, 0xBD564150, 0x2B8D9DF8, 0x7F12017E, 0x90904747, 0x50B56AB, 0xDBD19490,
-0xBB5A5659, 0xBAF40E4, 0x6D649014, 0x1D29166F, 0x414F3D75, 0x6F929540, 0x565AAF05, 0xBD9884E5, 0xF5342A25, 0x157915AE, 0x1A055A55, 0x9019A19F, 0x64B96A05, 0x35689CCC, 0x996012E2, 0x5252677B,
-0x156AA401, 0x25BCE483, 0xAA665555, 0xD6AF4B0F, 0x3F4BBDE0, 0x9404A9AF, 0xA590F9E4, 0x8191A5FD, 0x568190B4, 0x591A6616, 0x92C11D3E, 0x97D2E5FC, 0xF5A55A6F, 0xBEE0969B, 0x8918B4CA, 0xE0915397,
-0x5243472F, 0x95EA4055, 0x55E6E0A4, 0x9AEBD181, 0xF4A25357, 0x11115666, 0xFE45FF0A, 0x8BC7D2E1, 0x800556BB, 0x757D6A96, 0xFA909A5B, 0x68962FDB, 0xEB0056AA, 0x69970241, 0xAA58AD64, 0xC4D9DED5,
-0x5A5BF2F0, 0xBD0905B4, 0x197D7801, 0x8987EDC4, 0xFF40565A, 0x460978A4, 0xE4067FE4, 0x5DA23153, 0xB90565AE, 0x5E14B946, 0x4E35879F, 0xC72F8666, 0x1816472F, 0x9A5A4949, 0x64A0D1E5, 0xC7025B1A,
-0x1B061B55, 0xFFAA051B, 0xAF5DEDA1, 0xAA955094, 0x6659965A, 0x99A95DAD, 0x9450A5A5, 0xA550A595, 0x6914B950, 0xEF454944, 0x906BB990, 0xD680944B, 0xE091461B, 0x5363B7BB, 0xF0743906, 0x66566A69,
-0x4B85D0BC, 0x40E494A5, 0x1161B6B6, 0x519BD59, 0x5998401, 0x1651F26B, 0x5709BB1B, 0x6AE1D1B9, 0xD19297BF, 0x1A69FEE4, 0x6066B5A, 0x74A56491, 0xB4661151, 0x559191A4, 0x96756A68, 0xF5C791A6,
-0x20297A15, 0x6B660100, 0x313177A2, 0x55054150, 0x6A969669, 0xF0B82111, 0x555A6996, 0xB666295A, 0x1EA95441, 0x6A166BA5, 0x8C18566D, 0x2797278A, 0x82A552BD, 0xF964BD14, 0x41540668, 0x5078785A,
-0x5754FE, 0xF9E0E5FA, 0x15453D3F, 0x5A9699A9, 0xD9854147, 0x849494E9, 0x1DC39734, 0x67E797B3, 0x107066F, 0xAED9986C, 0xAB564140, 0x9B51A6B7, 0x5FD3E2F4, 0x5A5429F9, 0xF9A05161, 0x5A5A6965,
-0xDDD88484, 0xFA50FA55, 0x90E5E4FA, 0x6BF166B, 0x6566665A, 0xE450A6E5, 0xEB45AA04, 0xDA9A4646, 0xD7A37235, 0x11431B97, 0xD41D6E64, 0xD3D3A1A0, 0x5D540E9, 0x627777BB, 0x5054A4BE, 0x593A05ED,
-0x2EBE454B, 0x1ABA1015, 0x7C64B460, 0xC358B47F, 0x176F4293, 0xA6E417AB, 0xF611756E, 0x1F40D499, 0x84885D5F, 0x2F0B9B9B, 0x14BE05, 0xE5919590, 0x101B146E, 0x7B261190, 0xDC96F8B0, 0xF460257E,
-0x34B0AFC0, 0xEB9140FE, 0xC5C589DD, 0x1F6D6865, 0xF5100195, 0xAF560607, 0x505066B5, 0x7E590999, 0x13E190E4, 0xA56ABD59, 0xC21B68D7, 0xE594E4, 0xF6576E50, 0xFFA751D1, 0x19A179CB, 0x2726797,
-0xA1931C7C, 0xE1D90F1B, 0x7F2B2510, 0x6AF90055, 0x5F1E4C88, 0xE410757A, 0x95702212, 0x7B762100, 0x1B05BF6A, 0x16F05AB, 0xDDC5C9C9, 0x72BE594, 0xE490E555, 0xC5E50106, 0x816DAC16, 0x5540FA90,
-0x156605FF, 0x3B372621, 0x2B57A67D, 0x6C661E16, 0x1E97A917, 0xE6E2D383, 0x1B40F91B, 0xD9A63333, 0x34E18629, 0xA71616E9, 0x84946D99, 0x1B6906AF, 0xEFDE8904, 0x88F52470, 0x50E990F8, 0x4182E1B4,
-0xBAE1865B, 0xF48E4F4, 0x64A0517F, 0xA1F45902, 0x12177BF5, 0x465EBD91, 0x37A747, 0xF0A5106, 0x4C4E8A5, 0x62779E65, 0xDE494989, 0x7B6796D1, 0xC5C5C58A, 0xE4786B07, 0x6F07E0F9, 0x5554A550,
-0x95559333, 0x747A6B5, 0xA4A45500, 0xE998444, 0xF5966371, 0x111116BB, 0x783A679, 0x95409AFF, 0xFF9690E4, 0x60743EBD, 0x1C5A90FD, 0x2B051EE9, 0x5B7A1624, 0xEB415701, 0x1B6B0155, 0x9BCB8586,
-0x599E5C51, 0x510064BE, 0x50FA6060, 0x16066B5B, 0x54DA89D5, 0xA01468B5, 0xC1655E5, 0x55FF6657, 0xE4985E9, 0xD738BE27, 0x6938D450, 0x47D0E4FE, 0x4858986E, 0xE793431E, 0x1A05FFFD, 0x18939141,
-0x15EE4620, 0x79E45151, 0x663AA556, 0xD1266DD9, 0x7E0655E0, 0xB6A7676D, 0x54A96AA5, 0x1664092B, 0x56517AA0, 0xD6402CB8, 0x40A7773C, 0x554F0646, 0x488D5F2F, 0xE4E49095, 0x1C7CB4E0, 0x7C27529A,
-0xF6FAA151, 0xCC7358D6, 0xE8406D15, 0x6E074B5F, 0x638359F7, 0xD4E9A88C, 0xE888050F, 0xE6546A0B, 0xB9904EBD, 0x755061AF, 0xA371285C, 0xE95A1904, 0xCADD042D, 0x757F6ED6, 0xE4A91F06, 0x6D5D0909,
-0xE49559B8, 0xF4B0569B, 0x8454B5B9, 0x2161B5B6, 0x855AADEE, 0x575B0544, 0xBFE4D086, 0xE484CBEB, 0xF9F5426F, 0xCC653366, 0xA3524656, 0x9A5989E4, 0x10451466, 0x71F1655, 0x9B90A4ED, 0x14599FF,
-0x9666AA91, 0x5A99A945, 0x9685CD8F, 0xB8506A91, 0xB427E0F8, 0x50A990FE, 0xA5FA9090, 0x60D4DA80, 0x28E35CB3, 0x55E4AA, 0xD20B55A4, 0xE15F86, 0x36E6995E, 0x54036FFF, 0xA79D2250, 0xBA11A500,
-0x404603AC, 0x641065A0, 0x9DD84A0A, 0x969B061B, 0x36737313, 0x7B65631A, 0xA4E4C099, 0x9590448F, 0xD57F0680, 0x6094D86D, 0x15D8E3BD, 0x757F7DD7, 0xB45B854, 0x6560FA98, 0x7A805637, 0xD68416BB,
-0x7B767131, 0x90F9E8FE, 0xA4E54045, 0xE0411F6E, 0xD57D7DDD, 0x33CB1C33, 0x58ADD010, 0x9B1FA5C6, 0xA401BE95, 0xA950F994, 0xA851971E, 0x33CC33CC, 0x10F0B164, 0x151A6F01, 0x78B5660C, 0x33333225,
-0x41162402, 0x5F0506CB, 0xFD96166F, 0xE4417643, 0x56A51A94, 0x5323BFEA, 0xD12DD12D, 0xA999959A, 0x547C6482, 0x499EE652, 0x4AC7D1E5, 0x2D3DAD07, 0x6B171201, 0xAF065854, 0xD6C4891D, 0xCC739CE7,
-0x9D692663, 0x3E41597C, 0xF38314BB, 0x1150A4F4, 0xE1E50FA, 0xF4D60B6F, 0x5A54E590, 0x227AB5F0, 0x73A3D7FC, 0xD7420A59, 0x12015A59, 0x4F1999D5, 0xA90EE44A, 0x1065B9B5, 0xD10533E3, 0xBA918409,
-0xE5409FEF, 0x4549047F, 0x6B57A6A5, 0xE94691AA, 0x111A6E7E, 0x45496BA, 0x49FD999, 0x414D5B8D, 0xAB10EF5E, 0xE9878505, 0x8C910499, 0xC0C5DA3E, 0x6F1B7298, 0x177D78D0, 0x687B5665, 0x3F470353,
-0x1441A590, 0xE1965F6F, 0x5A5B4A8D, 0x47D7C98, 0xD1404115, 0xB89A053F, 0x8C4095FE, 0x4861E055, 0x3B417607, 0xF9E0E4E0, 0x65B0506, 0x93633236, 0xAA07A5E4, 0x77747080, 0x776160F0, 0x1672B05,
-0xA54E0428, 0x520A9625, 0xE581065, 0x90C76D76, 0x2157B2B3, 0x5C5BE06, 0x151A5A01, 0xA9D5C081, 0xCBCD9854, 0xFDD1061F, 0xB66111B1, 0x9DC3D7B0, 0x650A7642, 0x8095734D, 0xD052011B, 0xE0A1479B,
-0x9501BFF8, 0xE9D9BD0D, 0x7A017925, 0x69A67373, 0x41E0E557, 0x5F844124, 0xEAB0695E, 0x566B5040, 0xCCC9D693, 0xA79684DE, 0x6B5BC3C1, 0x9595667B, 0x9C33CA5C, 0x8984C5C5, 0x459BBDE9, 0x1F10A5F4,
-0x22A55AA, 0x97C3430D, 0xAA569A55, 0x552E1E00, 0xD3C3C78B, 0x82C7521E, 0x5B0605EA, 0x5FF69268, 0xD081460B, 0xE4517F06, 0x4448C9CE, 0x2F69F940, 0x476DA470, 0x9F96FE12, 0x4D8D9E8E, 0x6A6A16B5,
-0x1D05BE66, 0x84F5BD, 0x691E1B41, 0xE0939B17, 0x159059AA, 0x1E5792B9, 0x25A701A5, 0x439162E, 0xE994077C, 0x5CC396AA, 0x1D0D9AA5, 0x4A4A598D, 0x1B6F156B, 0x1A1B0F40, 0x34CB34CB, 0x6F542E,
-0x32CC739C, 0x94EB9669, 0xDA8D4E1D, 0xC6C5C46E, 0x10152B3F, 0x8787F9F9, 0x5E42D064, 0x699B05E9, 0x7030295E, 0x495E09BE, 0xEE191016, 0x801D2D56, 0x3A0099F9, 0xEA09059E, 0x5BAB5100, 0x393D49C,
-0x10E15DC2, 0xB056DD4, 0x3536915, 0xE0C18719, 0xEB964090, 0x6172727, 0xFD5900FA, 0xD10B78D1, 0x33332626, 0x50F990F9, 0x78600A5B, 0xE2B5401B, 0xAE5E9404, 0xF2CF0C0, 0x9E9D8080, 0x84E4F4F9,
-0x41F0E59F, 0x90787E12, 0xE4E19143, 0x761D6706, 0x6560BCE5, 0x134A9BD3, 0x23768995, 0x22ADF6, 0x434A5C72, 0xD4985444, 0x70936BFF, 0xAB54E0E7, 0x45E7A682, 0x7A786D90, 0xF8546A00, 0x5F5E4540,
-0x999A651E, 0xF9E297FD, 0xAF86E5, 0xD00B6E54, 0x5442878A, 0x50E940A5, 0x61F6AF1, 0x479701AA, 0xAE455E5D, 0x6560123E, 0x22D17625, 0x83071B64, 0xF9460251, 0x5F4B064A, 0x8742417C, 0x5F89C51A,
-0x14A29F50, 0x5013BF6B, 0x76395676, 0x54A590F9, 0x40915AA7, 0xEB95E041, 0x7E560504, 0x65B9E4D1, 0x3F63A594, 0x17448216, 0x1A4F87F1, 0xF990E696, 0xECE89A50, 0x2266B17, 0x6A959A98, 0x50F5001A,
-0xBF056A55, 0x74470FFE, 0x65251011, 0x9F7D6597, 0x51BB962, 0xA0D04297, 0xA257F0D1, 0x5B1569D5, 0x4F40959E, 0xEC5D1D0D, 0x51A1A, 0x1DF56462, 0xC4491A6F, 0x4B4A55EF, 0xFD741D5F, 0xE1526713,
-0x875153E2, 0x9752A2E2, 0xEFDA8504, 0xF0E84756, 0xE0A196E9, 0x5FAF5C40, 0x9A3359CC, 0xE056062E, 0xB07B71D7, 0x5966475D, 0x66161100, 0x444A0151, 0xDAC7D6F5, 0xFBE8E314, 0x35098512, 0x1A7F7690,
-0xAF970158, 0x666A6996, 0xD1D10938, 0x742969B, 0x4542A5FE, 0x6EBE50A1, 0x816E7955, 0x64E1D0C1, 0x105156AA, 0x6A9AD0F5, 0xB4909E2E, 0x55A6A959, 0x45B4999F, 0x3266CC26, 0x9B915EE, 0x9769E58B,
-0x2EF59968, 0x3F2F0711, 0x79798469, 0x6161B6B6, 0xA79504B1, 0x9B92A351, 0x61C08573, 0xAB1B656F, 0x37271601, 0xE4840979, 0x45D1C1DA, 0xA4C4961B, 0x59A7F2F0, 0xEA9FC147, 0x635362B0, 0x9561EAF,
-0x6B6762A1, 0x585A43D3, 0x8484819F, 0xD1C30D5D, 0x2123101D, 0xA0F8E4F9, 0x63676220, 0x17EB6A5, 0x90E63F27, 0xDD256045, 0x7B66A1A0, 0x64143F6, 0x41D479D7, 0xF1520F82, 0x12B44687, 0x1504BE1A,
-0x90E45401, 0xC4C98E4F, 0x919097C, 0xA7A52919, 0xB9B62313, 0x9695C089, 0x30C5E6BD, 0xAA55669B, 0xD19F0645, 0x1150E2FF, 0x36213121, 0x1F1F0A05, 0x2A315099, 0x2A1E0414, 0xA3E3D04, 0xD5992851,
-0x19A56A45, 0x5D0669E5, 0xA7C1F8C0, 0x84D1E5AA, 0x7292A464, 0x9040F5E4, 0xF185405, 0x1FAE4509, 0xF91690BE, 0x5540A540, 0xA1D2874B, 0x560B65F8, 0xC207E1E6, 0x646D0F9, 0x5A1440, 0xBB454116,
-0x13597242, 0x413A4504, 0x66E7D2D2, 0x61DA6950, 0x519DF0A0, 0xD2926EB4, 0xA583060B, 0x247E1587, 0xE50590BD, 0xEFF50146, 0x6252B722, 0x4B9AF552, 0x42445A5, 0x5D0844D0, 0xD7C1D18, 0x6B53900,
-0x7DD68434, 0xE6964247, 0xE0A50B5, 0x72635347, 0x669A6B06, 0x91549A65, 0x8F097CA5, 0x849458EC, 0xF9B09275, 0x71390D5A, 0x478BC9D6, 0x5D579AA5, 0x9ED08605, 0xCA1C35D3, 0x1029669, 0x1344FEA7,
-0x5B468B87, 0xA7F29990, 0x60BDB855, 0x3430B574, 0x544461FF, 0xC5C9550E, 0x69E716A7, 0x112336, 0x3F11D2D7, 0x2F0796E4, 0xB5250B00, 0x33CC33DD, 0x20357676, 0x7B6F9272, 0x114B09BB, 0xA7F6C987,
-0x32959833, 0x40D25BB6, 0x13170353, 0xD52E5949, 0x93626538, 0x43449A56, 0x655890BA, 0x2F56811B, 0xE5E4C88, 0xA6079500, 0xA4F90507, 0x6460A055, 0xE990906D, 0x156F56AC, 0x54CF00, 0x181D5A0A,
-0x7C09E947, 0xAD9E898C, 0xFF914212, 0x6933A7CC, 0xB2935B2E, 0x4454D8A2, 0xA6A560B6, 0x519E2075, 0x575FA6A5, 0xB8B06916, 0x598B471B, 0x10686AD1, 0x45EA0170, 0xD0470B9B, 0x3B511E0B, 0x53D79D0,
-0xCBCAC5C5, 0xDAD54CD0, 0x3542EE79, 0xB4AD4FD, 0x642DFF01, 0xB99109B9, 0xE1919B9F, 0x97B84162, 0xE995460A, 0x1060F5F5, 0x166DBCF1, 0x4214957A, 0x6C60626, 0x50FE4F0B, 0xB466470A, 0x808596E2,
-0x70D1440D, 0x818617B6, 0xC8E8DDED, 0x40443474, 0x103E0750, 0x1559A9, 0x16E29FF, 0x54FE0447, 0x34CAB25C, 0x9B30756A, 0xB0E74B05, 0xE19051D, 0x402E7450, 0xF5E0D1AB, 0x87979B5F, 0x8707BA71,
-0x90B4A491, 0x1A2F5301, 0x6C44D318, 0x8AC0A1F4, 0x5A6F0306, 0xE1159090, 0xF9A54183, 0x4CC7321C, 0x7E64868B, 0xFDE60582, 0x4BE77014, 0x1B902D01, 0x104D8FA7, 0x16A7CD, 0x94693912, 0x62E759A,
-0x594BA906, 0x5D023747, 0xDF9757AD, 0x97364CCA, 0xFA011265, 0x12E16116, 0x7A615600, 0x501196F9, 0x5067E247, 0x2A75B070, 0xBC0196BE, 0x19FD8907, 0xCA8511AE, 0x7B671210, 0xB8F0966F, 0x600AE5F4,
-0x4146858E, 0xA579C124, 0x19F26C13, 0x2320776, 0x595BF900, 0xFB059055, 0x6FD6E460, 0x86CAD5D, 0x948153A5, 0xC6C546FF, 0xE199AD5A, 0x656A566A, 0x81256994, 0x7C285400, 0x37CD6A37, 0x4CF4E1B,
-0xD181E0B5, 0x90F89F46, 0x5AD2D072, 0xF1F44D4, 0xB5E091C6, 0xFF90E764, 0x656B9965, 0x833471C7, 0xE6470700, 0x521A517, 0x56620BF, 0x7A6458C9, 0x566959A6, 0x5A5FF3D2, 0xD050063F, 0x9AC17C39,
-0xC1F03D19, 0xE7939343, 0x35312404, 0x76671223, 0xA0D05804, 0x7B773262, 0x5E2E6465, 0xE6860519, 0xDE909B5A, 0xB5C094E4, 0xAF019B15, 0x1A57027F, 0x7874E7D3, 0xB35674A, 0xD0854FB6, 0x916509FD,
-0x431F91FF, 0x9B605420, 0x566978B4, 0xE8D1042D, 0x2533074, 0xEC904443, 0xD404A4D1, 0xB9984945, 0x435181E6, 0xDFD0520A, 0x37FC61D, 0x1540FA94, 0x876DB853, 0x9D686C9D, 0x5D7DE642, 0x556A6669,
-0x6B166F05, 0xF0F06616, 0xE490051F, 0x147B0606, 0xFD76D9D9, 0x3B814E5D, 0x16E6460, 0x91F05406, 0x37444D34, 0x1B17BF00, 0xA8465A05, 0x12429D1C, 0x79753935, 0x639291F4, 0x6761F0F4, 0xBC789460,
-0xF890D79E, 0x54780743, 0x1131367B, 0xD6487C64, 0x8E582E4F, 0x6A972A65, 0x1BA6D0E5, 0x17D6007A, 0x82590727, 0x95D0FA, 0x1540E47E, 0x56B91A0B, 0x8A85C4D4, 0x9F8205E4, 0x80D4C58B, 0x75D3E647,
-0x5956D966, 0x74ED4500, 0x167EA440, 0x255E191, 0x31811515, 0x82999DDF, 0x11670BB8, 0x2BDAD965, 0x5AA5669A, 0x55BF105A, 0x88496E59, 0x5AF56600, 0x4858E751, 0xF4811BB9, 0xB501A7B0, 0x11B26DB,
-0x767C9887, 0x602D7703, 0x1219F8FD, 0x464297D, 0xFF06DB95, 0x156A04BF, 0x5050A39C, 0x35CA4F94, 0x7F00EF1B, 0x68353273, 0x150663B6, 0x79666190, 0xDA650647, 0xA962959A, 0x96E596FF, 0x537E17A3,
-0x57F9E440, 0x101458FF, 0xA4D4E441, 0x1898C4E0, 0x7E189481, 0xB6C71904, 0x9A95EDDD, 0x944449FF, 0x61E4C997, 0x52DF8F5, 0x6A51F46E, 0x9145AD, 0xD9A8DDD2, 0x8784E63D, 0xFF5B906E, 0x2998A559,
-0xCCCC6633, 0xB954C0D0, 0x70B5663B, 0x531C8B25, 0xFFBA0191, 0xF4E35B90, 0x40FF7150, 0x1F075AE5, 0xD0015BFF, 0xDCC3D6DB, 0x4E54A07F, 0x7E9647A, 0xA19D4E1, 0x51504404, 0xE7D68A8A, 0xAF10A450,
-0x71B71184, 0x79940A0E, 0x821B196E, 0x50413A5B, 0x5707962D, 0xD1B63962, 0x819DEDE4, 0xEEC5CB54, 0x251DBAD, 0x50BD6D1D, 0x20976E74, 0xDDC98A4F, 0x451079E9, 0x69146E, 0x68590311, 0x8045A9F4,
-0xEEC58B96, 0x98CCC996, 0x94784451, 0xE6D6015B, 0x3035B95, 0x12E39F6, 0x50EE4058, 0x4D1C74A0, 0xA4291505, 0x936B67D4, 0x2AC1449D, 0xA4015A6D, 0xAFCB4414, 0x74A50038, 0xDED051C8, 0x347B76DA,
-0x817ED01B, 0xDD2D79D2, 0x5A1A011B, 0xA040F556, 0x540246B8, 0xF2B45A06, 0x6A4999B4, 0x4B67D0BF, 0x31614701, 0x456C84C1, 0xB8F4814C, 0xFF009669, 0x4F4A4999, 0x907D95AB, 0xB7A49402, 0x526E61D,
-0x5A9542D3, 0xF8792606, 0xA913569, 0x3193534B, 0x7A61D074, 0x51A452E3, 0x40E490E5, 0x4106377, 0x404A1709, 0x1562727, 0xC0B89996, 0x4440781E, 0x78FA9053, 0x5D1E00E8, 0x1C3C75D0, 0xD581AB05,
-0x85C58A4, 0x44E490E4, 0xCD94CDCA, 0xB252E6D6, 0x1FC345AB, 0x40C5B905, 0x26693851, 0xEC3741D, 0x1B5869B, 0xA161510, 0xE061977B, 0x8A580510, 0xD960D554, 0xB53E091, 0x14B900FA, 0x3E094659,
-0x6090906, 0xE6B47C17, 0xECEC9840, 0xF9A405FA, 0x90F994FA, 0x2B750A5, 0x803B3D25, 0x14AE405F, 0x6F97E0FD, 0xCD34E38C, 0xDED0D4AF, 0x96D1C038, 0x51E78187, 0x93D7CACD, 0xD4D052A7, 0xE6558B4F,
-0xF6025766, 0xE54074B0, 0x6613252C, 0x257A75, 0x1B1266B5, 0xF956E0B6, 0x44D3E3B9, 0xC5C5E9E6, 0xEBD69599, 0x9F91D0F8, 0xB0A05253, 0x6E0F1761, 0x425FE480, 0xA5A051FF, 0xB1384DC7, 0x1CE31CD3,
-0xEBF6701B, 0x6B152998, 0x35A62510, 0xD140E5E6, 0x9070791D, 0x3CA6D1, 0xDAC98985, 0x90917E97, 0x19BCF91, 0xD0C7CBC7, 0xB5466B37, 0xB111D25B, 0x9A29978C, 0x3196C50, 0xCAC5C1FF, 0x4F4A4192,
-0xB14E708B, 0xD5E958D3, 0x73747E24, 0xEDE0D6A2, 0x1B91436E, 0x79252511, 0xCBC58C44, 0x7E64F890, 0x9F05B9F4, 0x1B55E0D0, 0x21D1E969, 0xF4558028, 0xF9E5C3C2, 0x1974325B, 0x6A94E0F0, 0xD101A5BD,
-0x1A17075, 0x5B2D78E1, 0x17194807, 0xF5C24B1D, 0xFA40E655, 0x7A095515, 0xE106F993, 0x565A1103, 0x5A54F6E0, 0xF5E0016E, 0xD6CBC5C1, 0xF940E696, 0xAE316D90, 0x6A146A00, 0x9B96E9E4, 0x6351D86F,
-0x5A466995, 0xD4460B8A, 0x2CC3744E, 0x99666696, 0x20257ABF, 0xA3F2955, 0xD5D0919A, 0x54444859, 0xFC5C606F, 0xA6653749, 0x306E696, 0x2528BD70, 0xA07BCE5, 0xF0A46662, 0xDC649440, 0x99C7874A,
-0x656CBEB, 0x5151A67B, 0x60DB4B05, 0xD1444107, 0x514B74, 0x165025A, 0x5B5A1101, 0x7101179A, 0xD09A070B, 0x50A096BF, 0x47A9521D, 0x4B2D7492, 0x3F0F1B53, 0x1941ABFF, 0x7B666111, 0xD3C345BA,
-0x1CA9D6, 0xE18359B9, 0x1590E6F8, 0xF4285902, 0xBF1B92D0, 0x1BE76D, 0x2A5582C3, 0x8979164B, 0x3C721B40, 0x33C0CF30, 0x2DD21EE1, 0xE9D30707, 0x192DF65, 0x1B92E7C5, 0x33333669, 0x1E0560F4,
-0xFB53034B, 0x966A6699, 0x6F9797A7, 0xEF469BDB, 0x1943F5F6, 0x1DA7C70A, 0x74741E9E, 0xF5709967, 0x520B74F1, 0x4741FBAB, 0xDA6712B9, 0xCBC6C1D0, 0x67E2D64, 0x5E03B625, 0xC088D9D5, 0xF89005FA,
-0x5A2516AA, 0xE5C7D9D6, 0x69FE5096, 0x435BE0D1, 0x7193DB8, 0x9CCC9967, 0x54613301, 0x461211BC, 0x730C6FAB, 0x6050A5B1, 0x7EB91141, 0x6A152F00, 0x69665AE5, 0xAE5780F8, 0x7D06F90, 0x2032D510,
-0x4E0746D1, 0xA69C33CC, 0x1A462616, 0x36C6C6C6, 0xFFA59D1F, 0x9B6D74F1, 0x1197907E, 0x656A9995, 0x91742E48, 0xD00538F5, 0x441542, 0x40D2469B, 0xFF5999, 0x15A9966A, 0x94841EF9, 0xA5651D1F,
-0xCC9C6633, 0x2F7D107E, 0x9B81411F, 0x9E59A669, 0x5E970007, 0x7E2E1F03, 0x29B5F244, 0x86C5D48, 0x548581B4, 0xF955CF44, 0xE35CB2CD, 0xA956B6D7, 0xE0E69125, 0x1969C59D, 0x550099EF, 0x68D99F24,
-0x5FA65010, 0x2B1256FD, 0xF8244147, 0x1D56470C, 0x2162A76, 0x62F16510, 0xAA556995, 0x540669, 0x14C29726, 0x4790FC0, 0x2CC19B44, 0x6CD7759D, 0xD7F64140, 0x425F81E4, 0x5034348D, 0x65095966,
-0x7261B0F5, 0xAF5681D1, 0x935A4051, 0x5262767B, 0x595EC2E8, 0xDB743847, 0x3C60A513, 0xC21F3991, 0xCB34C738, 0xD19AE995, 0xB9171781, 0x1107AB66, 0x5FC0D790, 0x2070F1F6, 0x6E5E1A09, 0xB5407E5E,
-0x505494EA, 0xE4703556, 0xF890999E, 0xA65BF595, 0x2919A7F, 0x49DD3880, 0x94EF960A, 0x183D1906, 0x1500F9F9, 0x9DEE4509, 0xF5FA6313, 0xE0526850, 0xBFE60005, 0xF16E685, 0xF90065A5, 0x916AF859,
-0xFF608454, 0xE6BF5094, 0x81D1E0FA, 0xA19FF91, 0x60D59CD9, 0x39524274, 0xD7994F4, 0x36295C8D, 0xE0503945, 0x2D85C545, 0xD1500658, 0x22172635, 0x338C5626, 0xDE812506, 0xDB57E8D0, 0xE9D955F6,
-0x9F6C94E6, 0x9636CC33, 0x2A1A3542, 0xF95D80F5, 0xD4266F42, 0x1C9E5F9, 0x74A1C30E, 0x6B16A050, 0xFB03506A, 0x4218B469, 0x94D1422D, 0x427D3531, 0xC25BAD40, 0x6692B292, 0x5A50E9A5, 0x717CD4C3,
-0x71938F59, 0x5147400A, 0x41BC6EB5, 0xD4A0D4E4, 0x1D0E5FA, 0xF6869F06, 0xA7E35252, 0xF4D1421B, 0xA4894DE7, 0x2D946B1A, 0xD0FFC684, 0x17C291E4, 0x7F525000, 0x15848139, 0x669669A5, 0xA7A76353,
-0xA996966A, 0x2FE155C0, 0x1E1E42D6, 0x4CB19976, 0x1103BE69, 0x57699082, 0x71624AF, 0xE1445A09, 0x969A4504, 0x5602955E, 0x5A1548E4, 0x5B074314, 0x74A6CE66, 0x9038152E, 0xD8C4554F, 0x3EBB0657,
-0xA8A65669, 0xB9B56010, 0x96B92D86, 0xE9D9CCA4, 0x33DE69A7, 0x5C8CD8E4, 0xF5D1401A, 0x4B59A46B, 0xCD258D07, 0xF3C3A475, 0x105DFC2E, 0xF7929140, 0xA4A450FE, 0x5B4598, 0x17137B75, 0x1B05F082,
-0xD62474D1, 0x673AB500, 0xA9460B5E, 0x47025AD1, 0x6E6695D9, 0x1262B6F6, 0x6AE65190, 0x66A69499, 0xD0993A76, 0x22321727, 0x55C0C56F, 0x6F7D1E43, 0x352F53E, 0x6AD6662F, 0x62713623, 0x948484F9,
-0x27161E04, 0xE996065B, 0xFED0411E, 0x8BC59A4B, 0x689E4B01, 0x40467E7E, 0x550E0F8, 0x1832D78D, 0x6CEC9580, 0x6A9E8F6E, 0x5340D4B1, 0x1449C6D, 0x22163530, 0xB4F6C3C6, 0xAD01DA95, 0x656F051E,
-0x8151167B, 0xA0C3966B, 0x40F85B15, 0xDD4B8D2A, 0x24BB667, 0x52E193F, 0x56A7019B, 0x12625504, 0x11A16297, 0x4B59066C, 0x59E990A0, 0xA45C0B00, 0x92C34B3F, 0xD06F6325, 0xC68D18B9, 0x74783C30,
-0xEA58C5CD, 0x142151F7, 0xDA649E04, 0xDA950602, 0x6E641510, 0xA7249144, 0xF46A1FF, 0xA950F611, 0x752E1FC, 0x7A460551, 0xB8E0D6D1, 0xE9D09151, 0xC745A104, 0x2072E687, 0x9F870105, 0x65A0F1FB,
-0xD0D500F9, 0x1A901FE1, 0x6F4E9401, 0x33322558, 0x52532732, 0xDB16B782, 0xBAA56046, 0xBCA19396, 0x411B39B7, 0xDC847184, 0x31C8B364, 0x6A66906E, 0x3F85D8F0, 0x36EB4393, 0xD518985, 0x34392F47,
-0x1FCF4E96, 0xF4A05E06, 0xBD5B102C, 0xFF056A65, 0x561BB601, 0xACC50A51, 0xA3733235, 0x7E1B53E2, 0x5251A0E5, 0xE078156F, 0x1F56E790, 0xA9965D59, 0xE0949C7D, 0xD87D560A, 0xD0649CED, 0x1065A47E,
-0x257CE4C3, 0xE2409597, 0x71D49220, 0x253929F, 0x47673ECA, 0x716B51F3, 0x4C1C48C5, 0xC7C1520B, 0x7B593060, 0x4F88491E, 0xA566A956, 0x7767A34, 0x65149A00, 0xB6D75A5F, 0x96A757A6, 0xA050617B,
-0xB007D141, 0x12A377B0, 0xC4E8D5F5, 0xE0C74B95, 0xC13C06F9, 0x7996213D, 0x9AC68F45, 0x65460B95, 0x99A7C292, 0x889C9C6C, 0xA4EDD440, 0xB0693DF, 0xFF50E490, 0x507A977, 0xE4147ED0, 0x80F19505,
-0xFCC5066E, 0x74B64319, 0x103A1EC6, 0xB288507E, 0x56A779A0, 0x7C9056AA, 0x381294FD, 0x5D194EC1, 0xF0C19B1F, 0xD60A1DE1, 0x94C0C4DF, 0x7E66824B, 0x69670667, 0x461520C7, 0x7466071F, 0x96FD1A00,
-0x10C4EA65, 0x93DE045, 0x6F01E2E5, 0xB196946, 0x504246AD, 0xB45E0F4, 0xABF1194, 0x84C94D5A, 0x111D27E, 0xF6951BBD, 0xE081166B, 0x56699965, 0xA1F16C54, 0x46107A64, 0x821C3491, 0x88D86E5B,
-0xE5D2C7CB, 0x5203432F, 0xE616332B, 0xF9854938, 0xD2736742, 0x671061F7, 0x9248BDB8, 0x544106E2, 0x6134280D, 0xC65E091D, 0x5599E860, 0xECC245B4, 0xFE4564E0, 0xD500F4F4, 0x59FDC0ED, 0x44530376,
-0xB152767E, 0x6A074351, 0xC565DE, 0xAD995844, 0x57F1D099, 0xB252D484, 0xD1984D8E, 0x5196A66, 0x2C59E167, 0xC0E9055F, 0xFD196F06, 0xF5F0C1C7, 0xFAD05152, 0x2126E0F5, 0xE9F42911, 0xC8339895,
-0x8D405BD, 0x50E94377, 0x443AF945, 0x5011293C, 0x76A297AD, 0x1EE440C5, 0x35DAD9A0, 0xA4419590, 0x165BA619, 0xF60B9A65, 0x1F89444A, 0x71B0255, 0x476DF0A6, 0x61D4A1A, 0x469F9DB0, 0x32355C8C,
-0x86091D46, 0xE795060B, 0x2296305C, 0x6E41F80, 0xF490E594, 0xF4E25699, 0xBF65AC50, 0x4A7E75DB, 0x1015F458, 0xB04ACD9E, 0xEE5478F4, 0x7F630C53, 0x4E49F5F0, 0xCDA3319C, 0xBE116D20, 0x4589D9E9,
-0x7435434B, 0xFDD96656, 0x5F681E4, 0x99AD1C50, 0x552A5401, 0x68F04549, 0x73B66D2, 0x1F86D101, 0xD041160B, 0xF906FFA5, 0x689676DE, 0x5F4780BD, 0xF0939AA5, 0x1F0B5F40, 0x501B3F, 0xA8C193B5,
-0x8C73CC33, 0xE24F7CD3, 0x9090A565, 0xA990D59A, 0xA1C14877, 0x946D8180, 0xF8343124, 0x14C1E915, 0x4919CBA5, 0xFF55D001, 0xF4E152A2, 0x46687EF0, 0xF05ABD48, 0xB7B37460, 0x1474C58, 0x94E490E8,
-0xB9E44183, 0x78D32DE1, 0xC8E4489F, 0x5BDAA45B, 0xB5610147, 0x5162A5F9, 0x5D6191C8, 0x4595C0A6, 0xA57DC996, 0x6D9D0D1E, 0xF58BC767, 0x1A0E5509, 0x409BD2D7, 0xFF5C135, 0x33B7579, 0xEF035600,
-0x779152B, 0x50B091B7, 0x363A3162, 0x491069DB, 0x9C4E0C5F, 0x945A1B12, 0x5490FF00, 0xB5A0B400, 0x1F82D64A, 0xB2C7426, 0x329CDA73, 0xA9995AA5, 0xF65876B4, 0x1E4E890E, 0x857AB576, 0xA52E054,
-0x1D11D88C, 0xA35895B0, 0x6F196890, 0xC7143E70, 0x6BE401FE, 0x111BA961, 0x66070AF5, 0x5F07130F, 0xA15061B6, 0x8C73CD32, 0x6C6481D6, 0x6AD5A6C1, 0x14A5872C, 0x46B90BE4, 0xE5586946, 0x3163C58C,
-0x1431B550, 0x91E94F09, 0x66F5C24B, 0xEE40461E, 0x97593992, 0x19E059F4, 0x94F92E05, 0x8CC445EA, 0x403D64A7, 0xB0FE5D8, 0x9C9B5C00, 0x7EDED9A4, 0x7CD393B5, 0xF1A50DA, 0x372B4077, 0xBF9046E7,
-0x56261E6D, 0x51232570, 0x40153CAB, 0x9B6F6712, 0x51C0160A, 0xB990052F, 0x3788B955, 0x555064A0, 0x6F0B5B05, 0x9776666B, 0xAA069B45, 0xAFF81440, 0x91E4DE1A, 0x80D5C9C6, 0x1E9E5DA4, 0x2B65B450,
-0x1213362B, 0xD766654A, 0x461346C, 0x197B2441, 0x5F9547EB, 0x15AF0506, 0x464C8D9D, 0x4021957A, 0xFE54E413, 0x13295035, 0x145E0D2, 0x4D4854E9, 0xBE50919B, 0xA76CF940, 0x91E1406E, 0x9A655A9A,
-0x3E65005A, 0x1C0B6666, 0x2611AC57, 0xBE7D1442, 0x311E3FC, 0xA4858185, 0x6E54D2A1, 0x9140A5DE, 0x844EC85, 0xF4A81540, 0x1159BF9, 0x2896D07D, 0xD5E690EA, 0x40A47D47, 0x6F672C16, 0xF1611217,
-0xE4096F65, 0x621D05EF, 0x9040979F, 0xC1C5CA46, 0x5B9606B5, 0x5101767A, 0x448C9568, 0xE4983D12, 0xCBC8B5E9, 0x1B15E402, 0xE1C60E15, 0x44E68419, 0x90D48DC, 0x7A9042BB, 0x151285D, 0x676B2613,
-0x121644B4, 0x920F52E3, 0x56DE09E, 0x6E6607A4, 0x5E560B0E, 0xC20B7616, 0xAF464146, 0x8C5C2835, 0x474BC2C6, 0xBC6419CA, 0x5C4353F0, 0x31392547, 0x504295AA, 0xCC593363, 0x1C0C6DBA, 0x4D71B7F,
-0xCC593633, 0xE71A250B, 0xE8CC599D, 0x894FA695, 0x4EC3513E, 0x39C0C645, 0x7B526034, 0xF91E2E06, 0x1A663699, 0x202599EF, 0xC1D1E195, 0x75E600FF, 0xD0D1ECDC, 0xD6DB6050, 0xE0E5016F, 0xF0910B15,
-0xD68C6917, 0x6F1A3D00, 0xF5D61BA6, 0x336D1CA5, 0x7888941D, 0x78D0912D, 0xE1D1C34C, 0x592E4C41, 0x1539F804, 0xFB019650, 0xD5E50609, 0xE8C553F9, 0x411BEBD, 0xE580D1DA, 0x1CACD693, 0xAF15BCE1,
-0x1104909C, 0x4B3B4686, 0xB3A31251, 0x50F5665, 0x1D4EC1D3, 0x2830D712, 0x401F0475, 0xC089D4DD, 0xB2425701, 0x40076F65, 0xA950F5A4, 0x9F9990BF, 0x70214431, 0x22753C31, 0xCC7369D9, 0xE9919061,
-0xF45A1F1, 0xBD0690D0, 0x79A6C180, 0x2FDD105A, 0x584296CA, 0x116F906E, 0x58484C5C, 0xDF9B10E6, 0x5184486D, 0xE9D89D90, 0x69B05ED2, 0xD9841D2B, 0xC2C6C5E6, 0xF88947CD, 0x90696469, 0xC5C0C6DF,
-0x677B0640, 0x4B479BC5, 0x83D1B811, 0x5B47E440, 0x1A419DEA, 0x3DD8D4A9, 0x8752B0F3, 0xD1D18189, 0xCCA632CC, 0x725CCB73, 0x6325CC33, 0x14464A25, 0x5410303F, 0xF8C12F85, 0x39D205E5, 0xFE850549,
-0xC68710B5, 0x471F7842, 0xD34A4C6C, 0x4742D188, 0xBFD50A44, 0x1987777C, 0x5B61C12, 0xB2530677, 0xD995A916, 0x75B496A0, 0x31E61E7, 0x53939DED, 0x51705B00, 0xBA5A4046, 0xFF14A4, 0x2599DCF8,
-0x7D47F02E, 0x9B959064, 0xDCD4E014, 0x38C22DD1, 0x65647C88, 0xD4606066, 0x3551E0D2, 0xD06157FE, 0x1131260B, 0x8B81E454, 0x1E1865FF, 0x1966A524, 0x4B4684D8, 0x3450F1B6, 0xE4FE41D1, 0x1D31F1E6,
-0xC47C1F4A, 0x94656AB, 0x45D101B, 0xB681B712, 0x9BD09215, 0x77924154, 0xFCECD4A0, 0xF0F1C72D, 0x74D0834F, 0xE4908117, 0x65E0365C, 0x955A09EF, 0x6E744349, 0xF4692B13, 0x34750F6E, 0x94D198A9,
-0x839C2DB2, 0xED929580, 0xEA609E65, 0x1A15F8D1, 0xFE00D6AD, 0xD5DC0141, 0xD90D3995, 0x6E6640ED, 0xA9B443CF, 0xE50681D9, 0x3F705659, 0x5F5E4844, 0x9A254A5B, 0x26618195, 0x8B945DAD, 0xDFD4E490,
-0x674352C0, 0x9967C1C0, 0x5990E995, 0xDEC544BA, 0xA7DA444, 0x16457E8, 0x142DFE04, 0xA4D5C084, 0x13172539, 0x84FC3590, 0xA9734748, 0xFE07F451, 0x42119AED, 0x8F087916, 0x13A65D1, 0x82856E75,
-0x3511B1B9, 0xA61BD018, 0x8619B893, 0x40BD89E5, 0x9A15F640, 0x4052464F, 0x9D87C1E0, 0x972C58F0, 0x84D8ED54, 0xE64D9C5D, 0xF421502F, 0xF24864, 0x59B8A154, 0x9A2596DF, 0x1441E6FA, 0x1BE46F90,
-0xA8915051, 0xA5B62611, 0xF582841D, 0x825362B7, 0x55F367E, 0x415263BD, 0x3E463930, 0x68754A06, 0x1117F280, 0x8B16B855, 0xEC75E1C4, 0xA0771117, 0x669DB850, 0x6D171238, 0x47167213, 0x90B21746,
-0xD92649C8, 0xCAC6C6F1, 0xE392C769, 0x60E7939B, 0x14130475, 0x56001A7D, 0xF657028F, 0x6F6819E, 0x29974C33, 0x49A57C5C, 0xD590E890, 0x6FF1116, 0x132B7665, 0xA0C60B56, 0x9844DF41, 0xA1B103E,
-0x44845EEF, 0xA6D2F5D5, 0x55FA4600, 0xBF611264, 0x6AD53610, 0xED594A11, 0xCFC15015, 0x96264247, 0xA4F1D3DA, 0x257EC166, 0xB8D6C114, 0xEA90CF4F, 0x6D5A804, 0x3F0695E8, 0x9C90BCE9, 0xAB4701D1,
-0x136357B5, 0x994D9E0E, 0x121652B2, 0x6D9FD261, 0x5CCC9733, 0x873B95E5, 0x905E9C80, 0xA051BA6F, 0x5F478589, 0x197AD19A, 0x50015DE9, 0x5BAE412F, 0x4111162B, 0x738F386, 0xE4835BAE, 0x5B55A2D0,
-0x5E4B038, 0xF9F91014, 0x8FCBD1E1, 0xD98B4743, 0xB9955DAF, 0xC5373DCD, 0xBD1C8114, 0x250532F1, 0x24504E0E, 0x62D7C50, 0xE8D44154, 0xA8944044, 0x9D669995, 0x530C6FFA, 0x65167BA7, 0xE641BE,
-0x811AB5D2, 0xD18A9D09, 0x6F064045, 0xBF902991, 0xC54F07FF, 0xF6962B11, 0xA4819FDB, 0x60F46A54, 0xE451815B, 0x7C197B, 0x9D44DA0C, 0x869640FF, 0x18C44D18, 0x40247F66, 0x5221F711, 0x510196FF,
-0x353261EF, 0x44490E0E, 0xF994E956, 0x926C45BF, 0x7D96855F, 0x84D4C98A, 0xE06BF456, 0xC21B1641, 0x4B5CB493, 0xDA90D366, 0xE8964D44, 0x197C75DA, 0xD6D46333, 0x465E78A1, 0x1942461E, 0xC1356656,
-0x58D631CC, 0xD773384C, 0x4A9940E5, 0xA0F97414, 0x53532327, 0x78107AB5, 0x3C091BA5, 0xA6469144, 0x44E45841, 0xC50D5842, 0x4A199678, 0x46365DF8, 0x5463E87, 0x8D2C1151, 0xFF5895, 0x2FD231C8,
-0x6C9CD2B3, 0xD74243B2, 0xC4409CDE, 0xB8E0411F, 0x26670F05, 0x5B6697A9, 0x55464A2B, 0x2E0F569A, 0x4660E25B, 0xFE500715, 0x9C683532, 0xCB0C5949, 0x806C6592, 0x679B0156, 0xFE005F15, 0xA540FE50,
-0x1F281510, 0x906D4F00, 0x57052C80, 0xA95BC0B5, 0x6C98C5CB, 0x44581E4E, 0xAD9D4846, 0x8352C7DB, 0xB21E50D9, 0xEB4607B7, 0x99AC9C77, 0x1509D9FC, 0x5460133E, 0x4244EE5A, 0xEF5A259A, 0x3439461B,
-0x6B940B05, 0x59E94484, 0x5062B45E, 0x859B9363, 0xFDE48194, 0x325362D2, 0xE460FB46, 0xD78B98E7, 0x64A3D346, 0xE5B06277, 0x9F655A41, 0x676B5302, 0xEA950B7D, 0xFD158A, 0x775362B4, 0x75C21938,
-0x861EB9D2, 0x589532CC, 0x1025190B, 0xD46B06FF, 0xB50E7C44, 0xCDD7A372, 0xB5B96100, 0xF2B491A1, 0x5E9960F4, 0xF1CC582E, 0x89C99575, 0x7AA1475F, 0x7B66C124, 0xD0D681EF, 0x44156E08, 0x8F1F1056,
-0x6E67D240, 0x9A4C4951, 0xD451E4A7, 0xEA941B13, 0x7E470070, 0x85422E7F, 0x5B9690FE, 0xDE06E626, 0xC8854A15, 0x5A05ED4D, 0x80F46E1B, 0x9011F302, 0x4493D2D8, 0xE50D9D68, 0xFB764400, 0x64D1816F,
-0x9965A616, 0xBF011811, 0x155B0252, 0x3D9DA411, 0x58D96D90, 0x5FAC14F, 0x34E09F47, 0x7470303D, 0x35316E5B, 0x84782D19, 0x6074B114, 0xDF85124F, 0x5B47B723, 0x91327673, 0x31A3C548, 0x6D04F9,
-0x65DA62CC, 0x779B6270, 0x9037699, 0xD59A061B, 0xD140F5D0, 0x546F04E5, 0x197A6193, 0x150F46FA, 0xE0592151, 0x54A9D0DB, 0xAA55D851, 0x50616F64, 0x35307994, 0x1198C72F, 0x472E79D1, 0xFF01981,
-0xF6195AFF, 0x58E66219, 0x69D3D67C, 0x3395C832, 0x5DA31DFF, 0xD66E7583, 0x802979D7, 0x1C419805, 0xA596916A, 0x6A464414, 0x64702547, 0xD31AB704, 0x91E6C21B, 0x41AF55, 0xC600DF64, 0x2D162960,
-0xD0D9AC64, 0x921C6378, 0xD0051C18, 0xCC26969C, 0x3C856899, 0x56A9D3A3, 0xC8CCD966, 0xB42552E2, 0xFF055B5B, 0x4AC7E641, 0xE747D0DD, 0x45A5F75D, 0xFD960205, 0xA60391FD, 0x5EAD8484, 0x13D0E563,
-0x11011BBF, 0xF4A4414, 0xCB5D0939, 0x1D6DE804, 0x2D6DF850, 0xB7E11431, 0x8B253410, 0x24D7A918, 0xA6591F6A, 0xFA0545, 0x10D3421A, 0x4E4CE453, 0x99C48C3D, 0x71D1C0F, 0xB4B94045, 0xE0815D05,
-0x9D854214, 0xF5F06136, 0x1A58FD15, 0x4742A650, 0x7E66464A, 0xCAC5D1F2, 0x99A91441, 0xB06115FB, 0xC0F43522, 0x9CE9CDC8, 0x59EA404E, 0x5B42A707, 0x16914BD, 0x872DF087, 0x4114AE9E, 0x3B1284FE,
-0x5E5E5808, 0x4680D66C, 0x364246C2, 0x65C2462E, 0x421C78A1, 0x1EB8D5EA, 0x28F24C55, 0x5021670B, 0x90BD7875, 0x71385CCA, 0xE7F07411, 0x1F11A366, 0x5FDFB852, 0x4C4DE05A, 0x9E0D9AD6, 0xE0953C84,
-0xE5CC0641, 0xE01BF406, 0x51E4072A, 0x4D66B8B5, 0x272DAD04, 0xF2C3986D, 0x6D680158, 0x464B0755, 0x550047FB, 0x74B41D1, 0xAF58676C, 0x7A655241, 0x64B9505B, 0x4D1D4D8D, 0xFFA5909B, 0x2F0754C1,
-0x4052256D, 0xB9D68609, 0x66615EB, 0x8A3D64D1, 0x2392D1E5, 0xF0A15ABD, 0xF7375B01, 0x699291A1, 0x607D0154, 0x6F19CDC6, 0x869DAC51, 0x11164726, 0xB0B50B1A, 0x9550E320, 0x257FF450, 0x3264669A,
-0xDF5D405B, 0x819855E7, 0x6B97C0A4, 0x88394945, 0xBCF14411, 0x6ED499, 0x570193E3, 0xFA346401, 0xF479095, 0xE6E6850B, 0xB2F1615, 0x95E2160, 0x144D8A3D, 0x3932D186, 0x5B64F801, 0x1F0746E7,
-0x1443EF98, 0xE8444E49, 0x4740EB50, 0xB9035B58, 0xD3D21B3E, 0xB8767699, 0x67D78366, 0xBD1187CB, 0x6C5C0C1C, 0x906D3E13, 0x9E1E6C49, 0x400598ED, 0x529106FD, 0xB4C10D2D, 0x740DC334, 0xE99458A0,
-0x94C8D572, 0xD7D18228, 0x13E566E, 0x1BC3D629, 0x63136172, 0x51A1B10, 0xF305F4E0, 0x679F6813, 0xD38356EA, 0xD669C856, 0xC5CE5A4, 0xC738CB74, 0x567DB480, 0xA65F9440, 0xE207176B, 0x9D5E4A88,
-0x1EFD6440, 0x1095738A, 0xF005646E, 0x19E1870, 0xEC481545, 0x2E598105, 0x55F7439F, 0xDBDB41A1, 0xE64F995, 0x6A9164A9, 0xA5191E04, 0xF4D1413C, 0x646EA056, 0xE3911263, 0x20117A65, 0xF9059304,
-0x48366754, 0x12166B67, 0x868A677, 0x46DB80C0, 0x1878D69A, 0x60D26DC1, 0x405EE804, 0x84D990BF, 0xDAD54606, 0xD93365CC, 0x93B2971B, 0x31269151, 0x5F0E58C2, 0x19B96390, 0xA1AD444, 0x90286D94,
-0xB1D10B7E, 0x40FAA451, 0x8276815E, 0x8669F400, 0xB5A61B12, 0x65FC9B8, 0x446AA55, 0xA11D8378, 0xAD9F4468, 0x21266E1E, 0x868544FC, 0x67520318, 0x858DD0EB, 0x86D4906F, 0x51D3A9A6, 0x9767857E,
-0xD6C99C68, 0x33CC2667, 0x660795F4, 0xD1F10155, 0x86D90D16, 0xE66A1603, 0xF5F86440, 0xE98E4504, 0x17424B9A, 0xB0839F59, 0xE70438F0, 0x432A7560, 0x92D89FC5, 0x37C42399, 0x11617570, 0x249605BE,
-0x101BE265, 0xEE905053, 0x4540DA59, 0x9729A4FF, 0xEE850607, 0x9FD15248, 0x50E5B323, 0x7579F946, 0x498459AF, 0x919C2C1E, 0x6AD78374, 0xB1647421, 0x9EE0B603, 0xA6D35E9, 0x96696C9E, 0x587A5003,
-0x49454A9, 0x6D6D9393, 0xC98677E9, 0x4095C2EF, 0x9C608505, 0x15940C2C, 0x5B60D2DB, 0x1C8151A9, 0x60F491D2, 0x2B670453, 0x4F1964BA, 0xB4430B51, 0xA9860454, 0xB0E41E46, 0x1406B7E3, 0x562701E4,
-0x20D1F6A1, 0x5352A966, 0x64E1D62F, 0x92C6ED07, 0xF882561B, 0x99195A04, 0xC934E3AC, 0xD9B91810, 0x474B04F4, 0x3D9A66, 0xCA9C10AF, 0xE1942916, 0xA125355, 0x32295C8C, 0x675A64E1, 0x9D906494,
-0x6C60EB1F, 0x7874C1BC, 0x1CB53038, 0x56D0F9D1, 0xB1EB954, 0x7C781540, 0x5323619E, 0x6FE055A9, 0xE7440D22, 0x7431A347, 0x6F1BE146, 0x1015BF00, 0x62381905, 0x7025B440, 0x176AF050, 0x5D270EF1,
-0x46AF4C18, 0x4B86D9ED, 0x8B177010, 0xFAD09606, 0xBFA15E50, 0x4701D72D, 0xA298A55E, 0x865CA950, 0x9B5B1227, 0xE0B9175, 0xF481F1FC, 0x7E5D0440, 0x1A697FE5, 0xDE84C5F0, 0xF9975303, 0x4CB46C54,
-0x3ED0D666, 0xE6B07065, 0xF0661263, 0x117C93A0, 0xD56DB4E1, 0x2E5E0E5D, 0x873DE11F, 0x5512413E, 0x5E9CE404, 0xB4C10B7F, 0xF990E956, 0x84C95E95, 0xB5E04B1F, 0x86815BA5, 0x7A5CB26C, 0x42F41F91,
-0xF4592E03, 0xF51F1300, 0x99D7810F, 0xB16051A7, 0x5B57B03E, 0xEE590B55, 0xC014FDD6, 0xF9C04505, 0x1A669669, 0x984C5F84, 0x1A6FD2E3, 0x1A075E5, 0xD80E450C, 0xD66942B6, 0xD050E31F, 0xBA605440,
-0x50E7856A, 0x406E53EF, 0xF01191B, 0xBF055243, 0x9B25E9E7, 0xF892A157, 0x2D598957, 0x85896B6, 0xEF44584B, 0x170667FB, 0xD1017F38, 0xCEC58687, 0x443C6C99, 0xB5B83D3, 0xFD05D91B, 0xA6D72DD3,
-0x6C98D9D0, 0xD66990E0, 0xDE850B0F, 0xE9964609, 0x8605B94B, 0x6DC0D196, 0xB194A5, 0x6F13424D, 0x9ED13215, 0x7064249F, 0x5751E0B0, 0x166F26D6, 0x559EC2F8, 0xE12C5C71, 0x59898D15, 0xBC015A05,
-0x90D18B0F, 0xB0E8649C, 0x170B98D0, 0x8181F491, 0xD990498C, 0x76312925, 0x93B53402, 0xCC1C4B54, 0x2F3F5006, 0x56EC4F10, 0x1AE501E4, 0x6F4D40DB, 0xA3525D69, 0x1329E491, 0x400AF995, 0x2D5C4806,
-0xB091667D, 0xCC6C1627, 0x425CD9EC, 0xF552931A, 0xA6D46580, 0xF4AE50E0, 0x1979909A, 0xF1750058, 0x3365CCD9, 0xBA166500, 0x86779739, 0x67F2611, 0x55109A0B, 0x51016A65, 0x1160BBF, 0x5A6C1401,
-0xC4DC9984, 0x33534244, 0x4057113A, 0xF1F431C1, 0xF8A44BE5, 0x1A976851, 0xB9B5C28F, 0xFE099454, 0xB065B8B5, 0xC0217707, 0xF3831BD1, 0x9757401B, 0x1D293580, 0x7A951200, 0x20615AF5, 0x6272757,
-0xE0FC2907, 0xD860B5C1, 0x985F89C, 0xC25C2C5F, 0x7F941C01, 0xA95A450A, 0x44D89A95, 0xCE1C0C58, 0x194184F9, 0x579BB371, 0x90111F40, 0x5F037075, 0xBB516996, 0x4EC9791, 0xCCEC9C44, 0x5D8404F8,
-0x48FE9D1, 0x4792E3E2, 0x6F35E381, 0x5F0350FB, 0xFF6C56, 0x6050A5F7, 0x589625C9, 0x8F79061D, 0x11D0421F, 0x9061F184, 0x504662BE, 0x8FC7D190, 0xB4404627, 0xEA1F1B03, 0xAF59D0EA, 0x79E50E04,
-0xCF80445D, 0x4191D38B, 0x8F51328, 0x6653E282, 0x8C5C3573, 0x90E05929, 0xC5910D2B, 0xAE479D46, 0x2F7C1610, 0x24B1637E, 0xCB001F55, 0x118384B5, 0xA3421710, 0xAA0725F4, 0xE9C0959A, 0xE5E74114,
-0x4A44CB25, 0x1763BD90, 0x1B095404, 0xCF09D095, 0x5B8344AC, 0xC5C0F9D1, 0xA7615441, 0xE990474B, 0x63536723, 0x1E305BA6, 0xE56B066B, 0xCA817916, 0x9F798578, 0xD7692E06, 0x56F01481, 0x37215100,
-0x17111401, 0xF890F955, 0xA68D68D6, 0xD64A06F0, 0x9F65D9D2, 0xBE90095F, 0x9967072F, 0xE01C947B, 0x12235709, 0x589DFD, 0xBB154A41, 0x2D5DC01F, 0xC58B5C08, 0xCB64DC4C, 0x9F9393AC, 0x7303467E,
-0x599EC984, 0x46E111FC, 0x7A679404, 0xA90647FB, 0x40EE949A, 0x77076E08, 0x10736423, 0x53D90AB, 0x1F510BB, 0x85CC253A, 0xAA905666, 0x45EC0B4, 0x835121F1, 0x2E5A4247, 0x1D8664A0, 0x51442CE0,
-0xDD88451E, 0xE85C0113, 0xFA409601, 0xA4211627, 0x459F50BA, 0x984C458A, 0xE65A60D7, 0x958143B2, 0xD3835BFA, 0xF727F110, 0x4F074354, 0x11113D3D, 0x1558312B, 0xFF08E6D6, 0x89BC5910, 0x99F99287,
-0x40D4183F, 0xDA66A550, 0xA45CE279, 0x7F97A251, 0xB1B025F, 0x70772265, 0xF0E21E16, 0xE79959B5, 0x496669C6, 0xECD00716, 0x5619ECE1, 0x6E5C11F, 0x1101FFF8, 0x55A01DCB, 0xA5053970, 0x3D448855,
-0x9F92E540, 0x35B8A4D0, 0x84119CA7, 0x5429406F, 0x90E05B56, 0x3752E1D8, 0xE1B42D87, 0x9454B0F1, 0xDD382505, 0x1904ED6F, 0xD94D0C58, 0x7C52031F, 0x14B06706, 0x79928799, 0x40149BC7, 0xE9DCD6D0,
-0x104F4D1, 0xD9663448, 0xBD85D003, 0x358CCDA3, 0x66F5412B, 0x6E65066A, 0x6E19B161, 0x55D1AA50, 0x785C9D30, 0x162530BE, 0x7AE64548, 0xA51B9B0E, 0xF9A56400, 0x32CE35DB, 0x17285370, 0xB0117B76,
-0x7CE04741, 0x9D0C51A4, 0xBF004D55, 0xAAD5AC11, 0x6599CB41, 0xFBD09444, 0x936291E5, 0x2D5EA056, 0x1129656A, 0x7FC09506, 0xD44149C8, 0xBA750352, 0xD2431943, 0x7967E182, 0xB813C497, 0x24219465,
-0xC43C9169, 0x6FD81483, 0x6152E3C, 0x59947B6, 0x27F90D12, 0x54046D2A, 0xD521309B, 0xE6653921, 0x9164F4F1, 0x1521FB4A, 0x61C54C38, 0x416484BF, 0x2776B11F, 0x59A9D884, 0xED806B54, 0x1BB0D59B,
-0x4E8D91A1, 0x782FD131, 0xC05A0377, 0x7A121126, 0xDFC5D0E0, 0xEF859E05, 0x7BB60515, 0x5DD26D89, 0x2E291157, 0x9F2F3530, 0xC08156A9, 0x6D91CDC5, 0xF1548117, 0xB52517FE, 0x2053E947, 0xAB5785C5,
-0x479A91E0, 0x9F90FE01, 0x312484DE, 0x441BC1A5, 0x66B501F5, 0xC4617A5B, 0x916BB0F4, 0x20657C7A, 0xE25390FF, 0x1F3861B4, 0x550586AF, 0x6B8599D4, 0x9F4294EC, 0xF4D48147, 0xD0965233, 0x1E05CFED,
-0x59176903, 0x2D2976C, 0xCD33338C, 0x1441E4AD, 0x4196C088, 0xF6079403, 0x969DC030, 0x64990D29, 0x2453F372, 0x8658909B, 0x458046FB, 0x11A185C4, 0x58FC1144, 0x31E641A, 0x8E47709E, 0xF1611277,
-0x61F907A, 0xB7100F5C, 0x5A170B19, 0x160557E, 0x55B39D0, 0xC0C556EF, 0xBBF50299, 0xD1D23E12, 0x69588543, 0x4546890, 0x90FA4115, 0x11C5ED8, 0x68B74789, 0xC06F0117, 0x172790AD, 0x606DAC54,
-0x8D488154, 0x8444EC98, 0x9A6592D3, 0xE5E15040, 0xDB031762, 0x2F099450, 0x404F0F5A, 0x1D09E9F4, 0x56045E1F, 0xF9C99F00, 0x136C6599, 0xB0C36E91, 0x1C2835B0, 0x60BE6B5, 0x462FB4D1, 0xCB19B6D7,
-0x6C48C4D9, 0xD0D19B69, 0xA5E544FC, 0xE4851E31, 0x41E464B8, 0x59C6F9D4, 0xF0A6527E, 0x5333D1E0, 0x4862F606, 0x72370631, 0xC2B490C5, 0x4643DE5C, 0x54F9C489, 0xFC526C40, 0xB0A56895, 0x45C1C134,
-0x768F1981, 0x6E295005, 0x950B6964, 0x4B4CD5E9, 0xEB131245, 0x447F844, 0x131B1D76, 0x99981A7, 0x500B1F0A, 0x91011B1B, 0x64E64709, 0xA45C8145, 0xB53001D1, 0xDB462885, 0xBE06D015, 0x4858541B,
-0x6C86C3B5, 0x70A1967B, 0x969B0414, 0xEF485C04, 0x7FE151C1, 0xEBE7F444, 0x5341990B, 0x71D58060, 0xF5A61E10, 0x79F2C53, 0xE5E41F00, 0xBFF4505, 0xE01BB4E9, 0xBFE3905D, 0xDB7664D0, 0x956A065B,
-0x12894E1, 0xBF14B401, 0x30F7A97, 0xA85C97E0, 0xF40643E9, 0xF8506706, 0x9B9B06AB, 0x5AA05995, 0x45448E3D, 0xE1D1907F, 0x24F4C22C, 0x82C2959A, 0xBF065243, 0x8785812D, 0x9A94A916, 0x315B2C60,
-0x523291D9, 0xF2991609, 0x2830579C, 0x999973CC, 0x4B14C098, 0xC1C5053, 0xD1C1C68A, 0x64B67F3, 0xD09B801D, 0x6A7C1044, 0x48580954, 0x859F095A, 0x46533620, 0x592C852D, 0xA5419141, 0x4D16A1D0,
-0xB0B153B, 0xE1944E4A, 0x21371633, 0xCEC9C4E4, 0xA5D70E08, 0x4E4C4DD, 0x591CAC04, 0x5B021DBC, 0x9967CC33, 0x81C0E5FD, 0xF651C104, 0x966760C9, 0x95E1303C, 0xEC5C6440, 0x50BF9F4, 0x3561C31E,
-0x45A096AD, 0xFF92500B, 0xF6598904, 0x19F9C50B, 0x60C64D18, 0xD640584F, 0x2194E1F3, 0xF031163D, 0x101B56E0, 0xDE5921DA, 0xBF01FD1, 0x706FD94, 0x34CB30CE, 0xB857061C, 0x5225B609, 0xC43C3135,
-0xC03B9350, 0xF001676F, 0xF0C18767, 0x6611391B, 0x4F89A46, 0x1F42441A, 0x649F0F46, 0xB5E0015E, 0x7966830E, 0x9740F4F7, 0xC8CC4451, 0x59BD404B, 0xCC9435E1, 0x3B15B2A0, 0x123C1607, 0x59468D90,
-0x40E0D749, 0x14C1F46E, 0x448BD6A9, 0x659AF556, 0x50E7435B, 0xAED2933C, 0x56051308, 0xCE146E50, 0x1C904F10, 0xEC485E0D, 0x169A936C, 0x51633605, 0xDB57A830, 0x62957AB, 0xF4F14448, 0x45CAD5D,
-0x695CC006, 0x104606B9, 0x81D1D86D, 0x8649F050, 0x20D1DB56, 0xE5E53CC0, 0xCB470256, 0xC629E494, 0x49385F8F, 0x65056E31, 0x9C86F095, 0xC8CC9865, 0x869D8118, 0xD1021F11, 0x87DAD1E2, 0xAF04D500,
-0x4518464, 0xB857B085, 0x4505E834, 0xB1E25F04, 0xD8DD9084, 0x35978C33, 0x11A64257, 0x991A1E41, 0x66B06752, 0xBAF41443, 0xBD4A4544, 0xD6753B66, 0xCAC6C639, 0x154480FD, 0x99D19BC, 0x546EE442,
-0xD0C0193E, 0x7491E21F, 0x24B0B3C7, 0xF981D501, 0x74438B58, 0x54C47391, 0x9EDD1180, 0xE697874F, 0x2E41F8E5, 0x468FDD9, 0x4F1E439C, 0x5542EB81, 0xA554FAE0, 0x1E43E2B0, 0x606D5898, 0x6587C4E8,
-0x6B86C511, 0x6050A6D3, 0x1C523485, 0xF2530396, 0x4A2D5884, 0x6FD09193, 0x29978F84, 0xFE490999, 0x9189675E, 0x99277401, 0xDD6F2494, 0x8CD39344, 0xB5783D9, 0xC859EE, 0xAC701503, 0x8FC1D7E1,
-0xA0854317, 0xD09E8444, 0x4510F2BD, 0xED484CD4, 0xDE5D0C1C, 0xC0854367, 0xD1642134, 0x503876E, 0x7C046A5E, 0xE5644035, 0x3D043173, 0x5DE8991, 0xA603D6D0, 0x70644B1B, 0x41C3F55, 0x799EC50,
-0x5C1D005A, 0xB54027BB, 0x501703FB, 0xCE5E2D84, 0xC248776B, 0x34C31DB1, 0xD08146F6, 0x6194D488, 0x902D95DF, 0x56239699, 0x79566996, 0x46366797, 0x2075B449, 0xE619904B, 0xF1FC491D, 0x4026925F,
-0x85CE994, 0xC62D651B, 0xE0F50B4, 0x60976F55, 0x5B7706A6, 0x49471F41, 0xF6D91352, 0x551A062F, 0x4145CFCA, 0x55B14234, 0xABF12531, 0xB915F0F4, 0x8AC7E275, 0x4679C12F, 0xE21353EC, 0x693602A5,
-0x4BC256AB, 0x463D64A6, 0x5E7C6B8, 0x143983F0, 0x3646871A, 0x601D1FE, 0x4D4601FC, 0xB489D0DF, 0xF7814046, 0xE5A50BA7, 0xB34A116, 0x707C4151, 0x804466BB, 0xCF450C5C, 0x1329B9F4, 0xFE400655,
-0xF4A1431B, 0x51D3202D, 0x74B0A444, 0xA6F1612, 0x6C584C8C, 0xC014F665, 0xD3982957, 0x36C136D1, 0x5C45CCD0, 0x9F459882, 0x91A753A2, 0xA9752C4C, 0x421B4297, 0x776A2313, 0x35397906, 0x48065762,
-0x1129B440, 0xAF410B5D, 0x7F9582D2, 0x4B51E650, 0x891D0D77, 0xE59909E5, 0x705D234B, 0xC3DA9055, 0xF1B11501, 0x44BC94D9, 0x1FA55C48, 0x2A422657, 0xC41091A1, 0x18970E74, 0x7699099, 0x10616AD7,
-0x1AE19F10, 0x475A6C31, 0xA27257E9, 0xC484582C, 0xD699665A, 0x17C94C18, 0xE1569B, 0x11855ABF, 0xA580D607, 0x64C18B7E, 0x7030A605, 0x2B3660D0, 0x165BE103, 0x809E1867, 0x47407FD7, 0x34E4858B,
-0x90ED740B, 0x1B43C2F5, 0xF451527C, 0x5723E1C5, 0xE1D1065B, 0xA51A9DF4, 0x7F099A85, 0x4157030B, 0x1D9F60B8, 0xC11491FD, 0xFE850A55, 0xB990431F, 0xA0C78D16, 0x6F5A4D40, 0xFE4411E, 0x34426B56,
-0x5014FE0F, 0xBD5DC51A, 0xC63637C3, 0xE1B459B2, 0xFA871B05, 0x4544D0AD, 0xE5E5093D, 0x3306C5DD, 0x47C33484, 0x6F1E146, 0xE4974F1, 0xDD48050F, 0xAB151E12, 0x5169FC92, 0x5055B27A, 0xD142AD5C,
-0x4B16B0F4, 0x312BC955, 0x75B10FC, 0x4A9E0458, 0xA65D34CE, 0x90D366CF, 0x10099D29, 0x8B358419, 0x87D2B5DA, 0x31162EF5, 0xF61989C5, 0x1F4341F8, 0xBC4C6D9C, 0x11A759, 0x9553A21, 0xCFC41530,
-0x1F05B610, 0x5B2F64C0, 0x117F1124, 0xF3D24D9, 0x44447874, 0x74351A06, 0x64C48979, 0x63C185B, 0x91F094A4, 0x4E1D1C48, 0x969103AE, 0x9CFC6067, 0x2FC94045, 0xED3844C4, 0x676C935B, 0x6E2091B5,
-0x2D9744EC, 0x6A111227, 0x78DB90E5, 0x8045587E, 0xC4E4591E, 0x479BE1E0, 0x5B667499, 0x50E0493E, 0xFB54819C, 0x431491F8, 0xD3EF50E0, 0x7363926, 0x50FF6440, 0x44DC6C9D, 0xF6D9965A, 0x548499,
-0x150A1403, 0xC7324CC7, 0xAFF0474B, 0xB479966E, 0xAD9E5451, 0xF9913C41, 0x1F09B46, 0x3E35461E, 0xA0C66C10, 0xA4D1D103, 0xA05470B4, 0x6F1A3531, 0x4047B2F5, 0x11472CE0, 0x3AE41631, 0xFD36A905,
-0xF4436F91, 0x4A419766, 0x50699E67, 0x5408D93D, 0x112711AF, 0xF500642F, 0x160BD66A, 0x11B0BFE, 0xC2C55CA1, 0x31CF859, 0xC6C95401, 0xD9C0E5C1, 0xE46056AE, 0xF5E30710, 0xA5FF0150, 0x4454203F,
-0xB6660959, 0x2522776, 0x2D586970, 0x7370757, 0x60953317, 0x81E7072D, 0x68149E6, 0x653834, 0x363D9D81, 0xB429113F, 0x566C0258, 0x51F92F00, 0xE19C5812, 0x11FB150, 0x59A65200, 0x2775E0F4,
-0x106752A3, 0x7574326, 0x5CC34739, 0xDAD54805, 0x5E936BC7, 0xCFCAC5C9, 0x2FC42555, 0xD06994C0, 0x5CAC7400, 0x5D84D074, 0x6D668604, 0xE50B19BD, 0xE7969F55, 0xFF925005, 0x65B266B, 0x4743035E,
-0x972C44C7, 0x5AB47260, 0x77123580, 0xD92DB404, 0x451BB8D1, 0xB94B4447, 0x9B955210, 0xA253815, 0x79AC5184, 0xE3D10C5C, 0x452410FB, 0xDFD3A148, 0xE0336E46, 0x4E287599, 0x12B750A9, 0xDAC0DE47,
-0xC18459A9, 0xC764CD30, 0x2334675E, 0xF6490DB8, 0x49172679, 0x659B6994, 0x7A912691, 0xB2B76074, 0xB9E58704, 0xCC33D9A9, 0x207F6A7, 0xC405F801, 0x560297CF, 0x48140E5F, 0xC44E676A, 0xB191DED,
-0x11035F60, 0x5B1F60B4, 0xA4EB1443, 0x5A6C06E6, 0x1915AE9, 0x33CD2696, 0x879F4444, 0xD442170B, 0xC9C9D9D6, 0xA1D4C124, 0xC40366B7, 0x22497E9, 0xCD18D7F9, 0x99FD111A, 0x9F6B53A1, 0xE051ABFC,
-0xBC10071D, 0xA566A759, 0x6DBC5E5, 0x4A9DA851, 0x2266B15, 0x123D6E9B, 0x66E05449, 0xD10D3870, 0x1706E462, 0xAF0B9B51, 0xE0109D6C, 0xF144861B, 0x813ED01B, 0xB6496C10, 0x1ED00768, 0x60747C10,
-0x46494376, 0x5E4C10B0, 0x573D5906, 0x5A02E5FE, 0xB3E005F2, 0xC05C4F45, 0xDBD58982, 0x6D13171F, 0x9741FA00, 0x61DB852, 0x8D46D299, 0x47421E4D, 0x74A94E6, 0x4DA31CD3, 0x681602FF, 0xC67962D7,
-0x1560BBA, 0xF8849D85, 0x7DD6D5B8, 0x5B6B4640, 0x441A349F, 0x61B3601F, 0xD550E2D3, 0xCF18111B, 0x97673333, 0xC59909E4, 0x57DAE840, 0xBB910E5, 0x144484F9, 0xA85C2511, 0x4092D5EA, 0x89910391,
-0x7D385500, 0x3D1D2176, 0x802FD41B, 0xA5D94890, 0x656E9099, 0xE66906E6, 0x4331A2D5, 0x4478E25B, 0xE78C41D, 0x3565D979, 0x4147133B, 0x89C6C64A, 0x45C9CDCF, 0x532315FA, 0x3E5A0D04, 0xB111DBFC,
-0x63162FF7, 0x9E0B9CD0, 0xA758E46B, 0xA097421F, 0xAE544262, 0xA59A5DDD, 0x3732261D, 0x71736790, 0x8895A173, 0x687470B1, 0x57E564FE, 0x6A765404, 0xF5E21482, 0x667150E1, 0xC0A764D9, 0x89950C14,
-0x3756912B, 0x3913499, 0x6FB553C3, 0x29920995, 0x750EC738, 0xC35C6992, 0xAA55E404, 0xCB4B0753, 0x20396156, 0xDB04F4C1, 0x7876825F, 0xD562319A, 0x592D121B, 0xF9360956, 0x47811B47, 0xD9BD5884,
-0x170A35E, 0x844EE59A, 0x8684EDDA, 0x405F1000, 0x813641A7, 0x176681A2, 0x7DBE6440, 0x87C6A54, 0xC485D905, 0x1AB0811D, 0xDBA59291, 0xFA52817C, 0x3981E5F0, 0x5109FEE5, 0xC1284557, 0x573B2703,
-0x30640659, 0xF1D3E997, 0x906253B7, 0x9076C3FD, 0xCA34D35C, 0xF481491C, 0x5976A4C0, 0x3FF1144, 0x26170649, 0x196B9065, 0x90693D09, 0xF0211A17, 0xAF016DD4, 0x4E449C48, 0x6F9A84F4, 0xB4449818,
-0x606DB144, 0x916B97A6, 0xEBD0FD19, 0xAA08D541, 0xD71BE505, 0x1E6507AF, 0x3E4B1361, 0xF391619, 0x4264BC50, 0x60563321, 0x4A370617, 0x436452E7, 0xBE107604, 0xDDA9C18E, 0xBF5B0371, 0x906F1107,
-0x55C5C83C, 0x31364782, 0x68DD9F1, 0xF99607E6, 0x2996367E, 0x5AF4458, 0x96582D30, 0xC4E4D98A, 0xE68719BE, 0x20C56C64, 0x5A550246, 0xB759B079, 0x64439BFB, 0xB1240D2E, 0x271350B2, 0x4314AF56,
-0xA9998D72, 0x5E8D1481, 0xB65D7253, 0x669392B8, 0xF0919B6C, 0x9F9790DD, 0x60979838, 0x3D625168, 0x12196D58, 0x59E9448A, 0x30547C92, 0x8E317590, 0x7B954843, 0x323D4907, 0x5A4D5308, 0xD10490DB,
-0x92CE4511, 0xB9353125, 0xA91F4050, 0xDC485D08, 0x2F11742, 0xB9B4090F, 0xD09891FF, 0x9503936, 0x80E3505F, 0xED99405F, 0xEA9058DE, 0x55019FC0, 0x9A1F412C, 0x471660DA, 0xF4D0C505, 0x4926666D,
-0x4191C3EF, 0x1A0526F5, 0x55F889C7, 0xD33CC738, 0x7A66C601, 0xF701C662, 0x6E953906, 0x6E6559AD, 0x1626C57A, 0xE0075266, 0x67069A5B, 0xA5F70401, 0x47786090, 0x8111C53B, 0xB4640B1A, 0x269D5DAE,
-0x50C4A474, 0x2A94987D, 0x44C05226, 0x6114423F, 0xB8474F1D, 0x8E0E05D8, 0x87B40FD2, 0x1F4392FD, 0x170E995, 0x1563DE0, 0x6F9AC5CA, 0x752A0D1D, 0xFF0A44D0, 0x7FD0D366, 0x51A62E05, 0xD0D5E8DE,
-0x56113F30, 0xE4056D87, 0xAB3B5100, 0x46539C6, 0x7F676290, 0xB851130D, 0xF5E09183, 0x64AC5D2D, 0x55F9404B, 0xE256F977, 0x70617760, 0xEE48E450, 0xDD5E35C8, 0x94D400F8, 0x446A0667, 0xEA935184,
-0x464B07F8, 0x8C74B6D4, 0x8D9D59A5, 0xCEC6ADD5, 0x2D0956A3, 0xA5BA5103, 0x31353123, 0x55FF4140, 0xA2440F15, 0x89266792, 0x44E1E154, 0xE5B41338, 0x2FCE9901, 0x95E6811B, 0x475C871, 0xAE9E4A44,
-0x5E0D141, 0xE702D66B, 0x474707E2, 0x6486CBC5, 0x7476016E, 0xB1D29B56, 0x7A34C605, 0x51427906, 0xE7967F97, 0x65D29C90, 0x55081AD, 0xD6E64045, 0x67134368, 0x9101E6DD, 0x68957841, 0x3D3D5909,
-0xE0525BAF, 0x134A4D3C, 0xC1B11909, 0x16493B76, 0x6B96D0A0, 0xBF0E79D6, 0x2C7096F9, 0x90FC04D6, 0x1742E472, 0x531CA1AC, 0xDAD08646, 0x9066669, 0xA7588D86, 0x913C54C2, 0x742A4514, 0x17111ABC,
-0xDDD7EDE5, 0x6699C498, 0x75313135, 0xE4995F64, 0x2582667E, 0x9C5C4C48, 0x1D0D10D9, 0x5B4C164, 0x46E616CB, 0xD18444BF, 0xE1D4695C, 0x40095E99, 0xECE02955, 0xFF40A411, 0x54D2421B, 0xE1C7DB05,
-0x80E5095D, 0x6745E907, 0xA6197007, 0x760674F9, 0x1522170A, 0x65181FF, 0xE0FDA45, 0x521C7867, 0x6B91D382, 0x657A83C1, 0x73C98C35, 0xB3CC31D6, 0x164B257B, 0x6F9605F9, 0x52F49EB5, 0x87592907,
-0x1B10D6F8, 0x949FD54, 0x910315BA, 0x40F09B47, 0xB761C144, 0x6D039D5, 0x59B113F, 0xE5C6D9, 0x176990FB, 0x90F8A465, 0x6DB8D144, 0x4552E392, 0xC94396B9, 0x36315A97, 0x7E874215, 0x40116F6F,
-0xDF193401, 0x70689317, 0x7E021740, 0xD5C044BD, 0xF1636E94, 0x5B0D34A1, 0x1027F689, 0x44A45590, 0xD443035F, 0xD7A4418C, 0xD949F480, 0x84C1E154, 0x6090966E, 0x40B56C1E, 0x9669C540, 0xA6305505,
-0x1667E244, 0xC245885D, 0xD504A5E, 0xA4F0C549, 0x358472A8, 0xC414BF20, 0x43369729, 0xB1112711, 0x78644352, 0x811CB856, 0x6F9792F0, 0x1E1E4195, 0x62C58C14, 0x2619D3A2, 0x998056BD, 0x653F3410,
-0x919184E4, 0x64906D6C, 0xE3D7996, 0x47660563, 0x50A91F03, 0x49F8C5CB, 0xFE15235E, 0x9783451, 0x716257B7, 0x1AB5351, 0x1710DC84, 0x3FA01D5A, 0x9844AD64, 0xE4D901BC, 0xEE546352, 0xF9547987,
-0xF6834B47, 0xB651F6D, 0xE09C9045, 0xE491424E, 0x94F9050B, 0x7DA6091D, 0xB5C14D74, 0x123A699D, 0x1F413CC3, 0x9F434158, 0x55D8C8C4, 0x51106FF, 0xD36CB1C, 0x1541FCE1, 0xC3344ED3, 0x3E29D905,
-0x150A6579, 0x502475A, 0x454B0F04, 0x65902722, 0x9EA055, 0x26568CC5, 0x7EB1443, 0x42186F96, 0x132357A9, 0x74091F13, 0xEE55480F, 0x7A0B4A45, 0xF01A8637, 0x937D68D5, 0xE2611115, 0x8A853663,
-0x60D295AB, 0x1946461A, 0xBB5190A1, 0x6D514218, 0x7C6482CF, 0x8759ACC8, 0x7E86C805, 0x42D3755F, 0xF4C10529, 0x471F1400, 0x5394238C, 0x112D54A8, 0x55E450F8, 0xDC2191BA, 0xA5F93011, 0x1A2159F5,
-0x4051A297, 0x66066999, 0xA644C058, 0x54EC9148, 0xFAFB0146, 0x1150FCEC, 0x4141D171, 0xF09F0444, 0x488E5E0E, 0x3D190F10, 0x406E405F, 0xFE9904AD, 0x101F5C6F, 0x454B093B, 0x40946C1F, 0xF0B966D,
-0xC16464DB, 0x91E2D6F9, 0x97789074, 0x537C5C40, 0x44A533C3, 0x74102B33, 0x40D425C1, 0xD748C936, 0x786619C9, 0x40917985, 0x66594C1C, 0x2F05D2D2, 0x8C711B4, 0xF9602757, 0x1013854A, 0x7D6296D0,
-0x3D99B8F0, 0x495D3243, 0x916864BE, 0x4E43B947, 0xE756A110, 0xA8D09D7D, 0xBF625095, 0xC1D48F87, 0x8BD47099, 0xDB631315, 0xE54139A0, 0xE4DC9C63, 0x846C2544, 0x4F0E04D1, 0xE0B15B26, 0x3249499D,
-
-}
diff --git a/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h b/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
deleted file mode 100644
index 8bedf94710..0000000000
--- a/thirdparty/basis_universal/transcoder/basisu_global_selector_palette.h
+++ /dev/null
@@ -1,675 +0,0 @@
-// basisu_global_selector_palette.h
-// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
-//
-// TODO: NONE of this is used in .basis/.ktx2 files. It will be deleted soon.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-#pragma once
-#include "basisu_transcoder_internal.h"
-#include <algorithm>
-
-namespace basist
-{
- class etc1_global_palette_entry_modifier
- {
- public:
- enum { cTotalBits = 15, cTotalValues = 1 << cTotalBits };
-
- etc1_global_palette_entry_modifier(uint32_t index = 0)
- {
-#ifdef _DEBUG
- static bool s_tested;
- if (!s_tested)
- {
- s_tested = true;
- for (uint32_t i = 0; i < cTotalValues; i++)
- {
- etc1_global_palette_entry_modifier m(i);
- etc1_global_palette_entry_modifier n = m;
-
- assert(n.get_index() == i);
- }
- }
-#endif
-
- set_index(index);
- }
-
- void set_index(uint32_t index)
- {
- assert(index < cTotalValues);
- m_rot = index & 3;
- m_flip = (index >> 2) & 1;
- m_inv = (index >> 3) & 1;
- m_contrast = (index >> 4) & 3;
- m_shift = (index >> 6) & 1;
- m_median = (index >> 7) & 1;
- m_div = (index >> 8) & 1;
- m_rand = (index >> 9) & 1;
- m_dilate = (index >> 10) & 1;
- m_shift_x = (index >> 11) & 1;
- m_shift_y = (index >> 12) & 1;
- m_erode = (index >> 13) & 1;
- m_high_pass = (index >> 14) & 1;
- }
-
- uint32_t get_index() const
- {
- return m_rot | (m_flip << 2) | (m_inv << 3) | (m_contrast << 4) | (m_shift << 6) | (m_median << 7) | (m_div << 8) | (m_rand << 9) | (m_dilate << 10) | (m_shift_x << 11) | (m_shift_y << 12) | (m_erode << 13) | (m_high_pass << 14);
- }
-
- void clear()
- {
- basisu::clear_obj(*this);
- }
-
- uint8_t m_contrast;
- bool m_rand;
- bool m_median;
- bool m_div;
- bool m_shift;
- bool m_inv;
- bool m_flip;
- bool m_dilate;
- bool m_shift_x;
- bool m_shift_y;
- bool m_erode;
- bool m_high_pass;
- uint8_t m_rot;
- };
-
- enum modifier_types
- {
- cModifierContrast,
- cModifierRand,
- cModifierMedian,
- cModifierDiv,
- cModifierShift,
- cModifierInv,
- cModifierFlippedAndRotated,
- cModifierDilate,
- cModifierShiftX,
- cModifierShiftY,
- cModifierErode,
- cModifierHighPass,
- cTotalModifiers
- };
-
-#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_MOD_BITS (etc1_global_palette_entry_modifier::cTotalBits)
-
- struct etc1_selector_palette_entry
- {
- etc1_selector_palette_entry()
- {
- clear();
- }
-
- void clear()
- {
- basisu::clear_obj(*this);
- }
-
- uint8_t operator[] (uint32_t i) const { assert(i < 16); return m_selectors[i]; }
- uint8_t&operator[] (uint32_t i) { assert(i < 16); return m_selectors[i]; }
-
- void set_uint32(uint32_t v)
- {
- for (uint32_t byte_index = 0; byte_index < 4; byte_index++)
- {
- uint32_t b = (v >> (byte_index * 8)) & 0xFF;
-
- m_selectors[byte_index * 4 + 0] = b & 3;
- m_selectors[byte_index * 4 + 1] = (b >> 2) & 3;
- m_selectors[byte_index * 4 + 2] = (b >> 4) & 3;
- m_selectors[byte_index * 4 + 3] = (b >> 6) & 3;
- }
- }
-
- uint32_t get_uint32() const
- {
- return get_byte(0) | (get_byte(1) << 8) | (get_byte(2) << 16) | (get_byte(3) << 24);
- }
-
- uint32_t get_byte(uint32_t byte_index) const
- {
- assert(byte_index < 4);
-
- return m_selectors[byte_index * 4 + 0] |
- (m_selectors[byte_index * 4 + 1] << 2) |
- (m_selectors[byte_index * 4 + 2] << 4) |
- (m_selectors[byte_index * 4 + 3] << 6);
- }
-
- uint8_t operator()(uint32_t x, uint32_t y) const { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
- uint8_t&operator()(uint32_t x, uint32_t y) { assert((x < 4) && (y < 4)); return m_selectors[x + y * 4]; }
-
- uint32_t calc_distance(const etc1_selector_palette_entry &other) const
- {
- uint32_t dist = 0;
- for (uint32_t i = 0; i < 8; i++)
- {
- int delta = static_cast<int>(m_selectors[i]) - static_cast<int>(other.m_selectors[i]);
- dist += delta * delta;
- }
- return dist;
- }
-
-#if 0
- uint32_t calc_hamming_dist(const etc1_selector_palette_entry &other) const
- {
- uint32_t dist = 0;
- for (uint32_t i = 0; i < 4; i++)
- dist += g_hamming_dist[get_byte(i) ^ other.get_byte(i)];
- return dist;
- }
-#endif
-
- etc1_selector_palette_entry get_inverted() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = 3 - m_selectors[i];
-
- return result;
- }
-
- etc1_selector_palette_entry get_divided() const
- {
- etc1_selector_palette_entry result;
-
- const uint8_t div_selector[4] = { 2, 0, 3, 1 };
-
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = div_selector[m_selectors[i]];
-
- return result;
- }
-
- etc1_selector_palette_entry get_shifted(int delta) const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t i = 0; i < 16; i++)
- result.m_selectors[i] = static_cast<uint8_t>(basisu::clamp<int>(m_selectors[i] + delta, 0, 3));
-
- return result;
- }
-
- etc1_selector_palette_entry get_randomized() const
- {
- uint32_t seed = get_uint32();
-
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- int s = (*this)(x, y);
-
- // between 0 and 10
- uint32_t i = basisd_urand(seed, 6) + basisd_urand(seed, 6);
- if (i == 0)
- s -= 2;
- else if (i == 10)
- s += 2;
- else if (i < 3)
- s -= 1;
- else if (i > 7)
- s += 1;
-
- result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(s, 0, 3));
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_contrast(int table_index) const
- {
- assert(table_index < 4);
-
- etc1_selector_palette_entry result;
-
- static const uint8_t s_contrast_tables[4][4] =
- {
- { 0, 1, 2, 3 }, // not used
- { 0, 0, 3, 3 },
- { 1, 1, 2, 2 },
- { 1, 1, 3, 3 }
- };
-
- for (uint32_t i = 0; i < 16; i++)
- {
- result[i] = s_contrast_tables[table_index][(*this)[i]];
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_dilated() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- uint32_t max_selector = 0;
-
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
-
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
-
- max_selector = basisu::maximum<uint32_t>(max_selector, (*this)(fx, fy));
- }
- }
-
- result(x, y) = static_cast<uint8_t>(max_selector);
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_eroded() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- uint32_t min_selector = 99;
-
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
-
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
-
- min_selector = basisu::minimum<uint32_t>(min_selector, (*this)(fx, fy));
- }
- }
-
- result(x, y) = static_cast<uint8_t>(min_selector);
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_shift_x() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- int sx = x - 1;
- if (sx < 0)
- sx = 0;
-
- result(x, y) = (*this)(sx, y);
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_shift_y() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- int sy = y - 1;
- if (sy < 0)
- sy = 3;
-
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = (*this)(x, sy);
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_median() const
- {
- etc1_selector_palette_entry result;
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- // ABC
- // D F
- // GHI
-
- uint8_t selectors[8];
- uint32_t n = 0;
-
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- if ((fy < 0) || (fy > 3))
- continue;
-
- for (int xd = -1; xd <= 1; xd++)
- {
- if ((xd | yd) == 0)
- continue;
-
- int fx = x + xd;
- if ((fx < 0) || (fx > 3))
- continue;
-
- selectors[n++] = (*this)(fx, fy);
- }
- }
-
- std::sort(selectors, selectors + n);
-
- result(x, y) = selectors[n / 2];
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_high_pass() const
- {
- etc1_selector_palette_entry result;
-
- static const int kernel[3][3] =
- {
- { 0, -1, 0 },
- { -1, 8, -1 },
- { 0, -1, 0 }
- };
-
- for (uint32_t y = 0; y < 4; y++)
- {
- for (uint32_t x = 0; x < 4; x++)
- {
- // ABC
- // D F
- // GHI
-
- int sum = 0;
-
- for (int yd = -1; yd <= 1; yd++)
- {
- int fy = y + yd;
- fy = basisu::clamp<int>(fy, 0, 3);
-
- for (int xd = -1; xd <= 1; xd++)
- {
- int fx = x + xd;
- fx = basisu::clamp<int>(fx, 0, 3);
-
- int k = (*this)(fx, fy);
- sum += k * kernel[yd + 1][xd + 1];
- }
- }
-
- sum = sum / 4;
-
- result(x, y) = static_cast<uint8_t>(basisu::clamp<int>(sum, 0, 3));
- }
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_flipped_and_rotated(bool flip, uint32_t rotation_index) const
- {
- etc1_selector_palette_entry temp;
-
- if (flip)
- {
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- temp(x, y) = (*this)(x, 3 - y);
- }
- else
- {
- temp = *this;
- }
-
- etc1_selector_palette_entry result;
-
- switch (rotation_index)
- {
- case 0:
- result = temp;
- break;
- case 1:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(y, 3 - x);
- break;
- case 2:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(3 - x, 3 - y);
- break;
- case 3:
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- result(x, y) = temp(3 - y, x);
- break;
- default:
- assert(0);
- break;
- }
-
- return result;
- }
-
- etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier) const
- {
- etc1_selector_palette_entry r(*this);
-
- if (modifier.m_shift_x)
- r = r.get_shift_x();
-
- if (modifier.m_shift_y)
- r = r.get_shift_y();
-
- r = r.get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
-
- if (modifier.m_dilate)
- r = r.get_dilated();
-
- if (modifier.m_erode)
- r = r.get_eroded();
-
- if (modifier.m_high_pass)
- r = r.get_high_pass();
-
- if (modifier.m_rand)
- r = r.get_randomized();
-
- if (modifier.m_div)
- r = r.get_divided();
-
- if (modifier.m_shift)
- r = r.get_shifted(1);
-
- if (modifier.m_contrast)
- r = r.get_contrast(modifier.m_contrast);
-
- if (modifier.m_inv)
- r = r.get_inverted();
-
- if (modifier.m_median)
- r = r.get_median();
-
- return r;
- }
-
- etc1_selector_palette_entry apply_modifier(modifier_types mod_type, const etc1_global_palette_entry_modifier &modifier) const
- {
- switch (mod_type)
- {
- case cModifierContrast:
- return get_contrast(modifier.m_contrast);
- case cModifierRand:
- return get_randomized();
- case cModifierMedian:
- return get_median();
- case cModifierDiv:
- return get_divided();
- case cModifierShift:
- return get_shifted(1);
- case cModifierInv:
- return get_inverted();
- case cModifierFlippedAndRotated:
- return get_flipped_and_rotated(modifier.m_flip != 0, modifier.m_rot);
- case cModifierDilate:
- return get_dilated();
- case cModifierShiftX:
- return get_shift_x();
- case cModifierShiftY:
- return get_shift_y();
- case cModifierErode:
- return get_eroded();
- case cModifierHighPass:
- return get_high_pass();
- default:
- assert(0);
- break;
- }
-
- return *this;
- }
-
- etc1_selector_palette_entry get_modified(const etc1_global_palette_entry_modifier &modifier, uint32_t num_order, const modifier_types *pOrder) const
- {
- etc1_selector_palette_entry r(*this);
-
- for (uint32_t i = 0; i < num_order; i++)
- {
- r = r.apply_modifier(pOrder[i], modifier);
- }
-
- return r;
- }
-
- bool operator< (const etc1_selector_palette_entry &other) const
- {
- for (uint32_t i = 0; i < 16; i++)
- {
- if (m_selectors[i] < other.m_selectors[i])
- return true;
- else if (m_selectors[i] != other.m_selectors[i])
- return false;
- }
-
- return false;
- }
-
- bool operator== (const etc1_selector_palette_entry &other) const
- {
- for (uint32_t i = 0; i < 16; i++)
- {
- if (m_selectors[i] != other.m_selectors[i])
- return false;
- }
-
- return true;
- }
-
- private:
- uint8_t m_selectors[16];
- };
-
- typedef basisu::vector<etc1_selector_palette_entry> etc1_selector_palette_entry_vec;
-
- extern const uint32_t g_global_selector_cb[];
- extern const uint32_t g_global_selector_cb_size;
-
-#define ETC1_GLOBAL_SELECTOR_CODEBOOK_MAX_PAL_BITS (12)
-
- struct etc1_global_selector_codebook_entry_id
- {
- uint32_t m_palette_index;
- etc1_global_palette_entry_modifier m_modifier;
-
- etc1_global_selector_codebook_entry_id(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) : m_palette_index(palette_index), m_modifier(modifier) { }
-
- etc1_global_selector_codebook_entry_id() { }
-
- void set(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) { m_palette_index = palette_index; m_modifier = modifier; }
- };
-
- typedef basisu::vector<etc1_global_selector_codebook_entry_id> etc1_global_selector_codebook_entry_id_vec;
-
- class etc1_global_selector_codebook
- {
- public:
- etc1_global_selector_codebook() { }
- etc1_global_selector_codebook(uint32_t N, const uint32_t *pEntries) { init(N, pEntries); }
-
- void init(uint32_t N, const uint32_t* pEntries);
-
- void print_code(FILE *pFile);
-
- void clear()
- {
- m_palette.clear();
- }
-
- uint32_t size() const { return (uint32_t)m_palette.size(); }
-
- const etc1_selector_palette_entry_vec &get_palette() const
- {
- return m_palette;
- }
-
- etc1_selector_palette_entry get_entry(uint32_t palette_index) const
- {
- return m_palette[palette_index];
- }
-
- etc1_selector_palette_entry get_entry(uint32_t palette_index, const etc1_global_palette_entry_modifier &modifier) const
- {
- return m_palette[palette_index].get_modified(modifier);
- }
-
- etc1_selector_palette_entry get_entry(const etc1_global_selector_codebook_entry_id &id) const
- {
- return m_palette[id.m_palette_index].get_modified(id.m_modifier);
- }
-
- etc1_selector_palette_entry_vec m_palette;
- };
-
-} // namespace basist
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
index 0b3733385d..630731900f 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
@@ -37,6 +37,14 @@
#endif
#endif
+// Using unaligned loads and stores causes errors when using UBSan. Jam it off.
+#if defined(__has_feature)
+#if __has_feature(undefined_behavior_sanitizer)
+#undef BASISD_USE_UNALIGNED_WORD_READS
+#define BASISD_USE_UNALIGNED_WORD_READS 0
+#endif
+#endif
+
#define BASISD_SUPPORTED_BASIS_VERSION (0x13)
#ifndef BASISD_SUPPORT_KTX2
@@ -224,32 +232,7 @@ namespace basist
return static_cast<uint16_t>(~crc);
}
-
- const uint32_t g_global_selector_cb[] =
-#include "basisu_global_selector_cb.h"
- ;
-
- const uint32_t g_global_selector_cb_size = sizeof(g_global_selector_cb) / sizeof(g_global_selector_cb[0]);
-
- void etc1_global_selector_codebook::init(uint32_t N, const uint32_t* pEntries)
- {
- m_palette.resize(N);
- for (uint32_t i = 0; i < N; i++)
- m_palette[i].set_uint32(pEntries[i]);
- }
-
- void etc1_global_selector_codebook::print_code(FILE* pFile)
- {
- fprintf(pFile, "{\n");
- for (uint32_t i = 0; i < m_palette.size(); i++)
- {
- fprintf(pFile, "0x%X,", m_palette[i].get_uint32());
- if ((i & 15) == 15)
- fprintf(pFile, "\n");
- }
- fprintf(pFile, "\n}\n");
- }
-
+
enum etc_constants
{
cETC1BytesPerBlock = 8U,
@@ -7532,9 +7515,8 @@ namespace basist
}
#endif // BASISD_SUPPORT_PVRTC2
- basisu_lowlevel_etc1s_transcoder::basisu_lowlevel_etc1s_transcoder(const etc1_global_selector_codebook* pGlobal_sel_codebook) :
+ basisu_lowlevel_etc1s_transcoder::basisu_lowlevel_etc1s_transcoder() :
m_pGlobal_codebook(nullptr),
- m_pGlobal_sel_codebook(pGlobal_sel_codebook),
m_selector_history_buf_size(0)
{
}
@@ -7641,50 +7623,8 @@ namespace basist
if (used_global_selector_cb)
{
- // global selector palette
- uint32_t pal_bits = sym_codec.get_bits(4);
- uint32_t mod_bits = sym_codec.get_bits(4);
-
- basist::huffman_decoding_table mod_model;
- if (mod_bits)
- {
- if (!sym_codec.read_huffman_table(mod_model))
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 6\n");
- return false;
- }
- if (!mod_model.is_valid())
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 6a\n");
- return false;
- }
- }
-
- for (uint32_t i = 0; i < num_selectors; i++)
- {
- uint32_t pal_index = 0;
- if (pal_bits)
- pal_index = sym_codec.get_bits(pal_bits);
-
- uint32_t mod_index = 0;
- if (mod_bits)
- mod_index = sym_codec.decode_huffman(mod_model);
-
- if (pal_index >= m_pGlobal_sel_codebook->size())
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 7z\n");
- return false;
- }
-
- const etc1_selector_palette_entry e(m_pGlobal_sel_codebook->get_entry(pal_index, etc1_global_palette_entry_modifier(mod_index)));
-
- // TODO: Optimize this
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- m_local_selectors[i].set_selector(x, y, e[x + y * 4]);
-
- m_local_selectors[i].init_flags();
- }
+ BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: global selector codebooks are unsupported\n");
+ return false;
}
else
{
@@ -7692,146 +7632,70 @@ namespace basist
if (used_hybrid_selector_cb)
{
- const uint32_t pal_bits = sym_codec.get_bits(4);
- const uint32_t mod_bits = sym_codec.get_bits(4);
-
- basist::huffman_decoding_table uses_global_cb_bitflags_model;
- if (!sym_codec.read_huffman_table(uses_global_cb_bitflags_model))
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 7\n");
- return false;
- }
- if (!uses_global_cb_bitflags_model.is_valid())
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 7a\n");
- return false;
- }
-
- basist::huffman_decoding_table global_mod_indices_model;
- if (mod_bits)
- {
- if (!sym_codec.read_huffman_table(global_mod_indices_model))
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 8\n");
- return false;
- }
- if (!global_mod_indices_model.is_valid())
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 8a\n");
- return false;
- }
- }
-
- uint32_t cur_uses_global_cb_bitflags = 0;
- uint32_t uses_global_cb_bitflags_remaining = 0;
+ BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: hybrid global selector codebooks are unsupported\n");
+ return false;
+ }
+
+ const bool used_raw_encoding = (sym_codec.get_bits(1) == 1);
- for (uint32_t q = 0; q < num_selectors; q++)
+ if (used_raw_encoding)
+ {
+ for (uint32_t i = 0; i < num_selectors; i++)
{
- if (!uses_global_cb_bitflags_remaining)
+ for (uint32_t j = 0; j < 4; j++)
{
- cur_uses_global_cb_bitflags = sym_codec.decode_huffman(uses_global_cb_bitflags_model);
+ uint32_t cur_byte = sym_codec.get_bits(8);
- uses_global_cb_bitflags_remaining = 8;
+ for (uint32_t k = 0; k < 4; k++)
+ m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
}
- uses_global_cb_bitflags_remaining--;
-
- const bool used_global_cb_flag = (cur_uses_global_cb_bitflags & 1) != 0;
- cur_uses_global_cb_bitflags >>= 1;
- if (used_global_cb_flag)
- {
- const uint32_t pal_index = pal_bits ? sym_codec.get_bits(pal_bits) : 0;
- const uint32_t mod_index = mod_bits ? sym_codec.decode_huffman(global_mod_indices_model) : 0;
-
- if (pal_index >= m_pGlobal_sel_codebook->size())
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 8b\n");
- return false;
- }
-
- const etc1_selector_palette_entry e(m_pGlobal_sel_codebook->get_entry(pal_index, etc1_global_palette_entry_modifier(mod_index)));
-
- for (uint32_t y = 0; y < 4; y++)
- for (uint32_t x = 0; x < 4; x++)
- m_local_selectors[q].set_selector(x, y, e[x + y * 4]);
- }
- else
- {
- for (uint32_t j = 0; j < 4; j++)
- {
- uint32_t cur_byte = sym_codec.get_bits(8);
-
- for (uint32_t k = 0; k < 4; k++)
- m_local_selectors[q].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
- }
- }
-
- m_local_selectors[q].init_flags();
+ m_local_selectors[i].init_flags();
}
}
else
{
- const bool used_raw_encoding = (sym_codec.get_bits(1) == 1);
+ if (!sym_codec.read_huffman_table(delta_selector_pal_model))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10\n");
+ return false;
+ }
+
+ if ((num_selectors > 1) && (!delta_selector_pal_model.is_valid()))
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10a\n");
+ return false;
+ }
+
+ uint8_t prev_bytes[4] = { 0, 0, 0, 0 };
- if (used_raw_encoding)
+ for (uint32_t i = 0; i < num_selectors; i++)
{
- for (uint32_t i = 0; i < num_selectors; i++)
+ if (!i)
{
for (uint32_t j = 0; j < 4; j++)
{
uint32_t cur_byte = sym_codec.get_bits(8);
+ prev_bytes[j] = static_cast<uint8_t>(cur_byte);
for (uint32_t k = 0; k < 4; k++)
m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
}
-
m_local_selectors[i].init_flags();
+ continue;
}
- }
- else
- {
- if (!sym_codec.read_huffman_table(delta_selector_pal_model))
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10\n");
- return false;
- }
-
- if ((num_selectors > 1) && (!delta_selector_pal_model.is_valid()))
- {
- BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10a\n");
- return false;
- }
-
- uint8_t prev_bytes[4] = { 0, 0, 0, 0 };
- for (uint32_t i = 0; i < num_selectors; i++)
+ for (uint32_t j = 0; j < 4; j++)
{
- if (!i)
- {
- for (uint32_t j = 0; j < 4; j++)
- {
- uint32_t cur_byte = sym_codec.get_bits(8);
- prev_bytes[j] = static_cast<uint8_t>(cur_byte);
+ int delta_byte = sym_codec.decode_huffman(delta_selector_pal_model);
- for (uint32_t k = 0; k < 4; k++)
- m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
- }
- m_local_selectors[i].init_flags();
- continue;
- }
-
- for (uint32_t j = 0; j < 4; j++)
- {
- int delta_byte = sym_codec.decode_huffman(delta_selector_pal_model);
-
- uint32_t cur_byte = delta_byte ^ prev_bytes[j];
- prev_bytes[j] = static_cast<uint8_t>(cur_byte);
+ uint32_t cur_byte = delta_byte ^ prev_bytes[j];
+ prev_bytes[j] = static_cast<uint8_t>(cur_byte);
- for (uint32_t k = 0; k < 4; k++)
- m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
- }
- m_local_selectors[i].init_flags();
+ for (uint32_t k = 0; k < 4; k++)
+ m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3);
}
+ m_local_selectors[i].init_flags();
}
}
}
@@ -7899,6 +7763,12 @@ namespace basist
}
m_selector_history_buf_size = sym_codec.get_bits(13);
+ // Check for bogus values.
+ if (!m_selector_history_buf_size)
+ {
+ BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 5\n");
+ return false;
+ }
sym_codec.stop();
@@ -7979,8 +7849,11 @@ namespace basist
decoder_etc_block block;
memset(&block, 0, sizeof(block));
+
+ //block.set_flip_bit(true);
+ // Setting the flip bit to false to be compatible with the Khronos KDFS.
+ block.set_flip_bit(false);
- block.set_flip_bit(true);
block.set_diff_bit(true);
void* pPVRTC_work_mem = nullptr;
@@ -8741,7 +8614,7 @@ namespace basist
if (!output_row_pitch_in_blocks_or_pixels)
output_row_pitch_in_blocks_or_pixels = orig_width;
- if (!output_rows_in_pixels)
+ if (!output_rows_in_pixels)
output_rows_in_pixels = orig_height;
// Now make sure the output buffer is large enough, or we'll overwrite memory.
@@ -9440,6 +9313,12 @@ namespace basist
{
switch (fmt)
{
+ case block_format::cUASTC_4x4:
+ {
+ memcpy(pDst_block, pSource_block, sizeof(uastc_block));
+ status = true;
+ break;
+ }
case block_format::cETC1:
{
if (from_alpha)
@@ -9906,8 +9785,7 @@ namespace basist
return status;
}
- basisu_transcoder::basisu_transcoder(const etc1_global_selector_codebook* pGlobal_sel_codebook) :
- m_lowlevel_etc1s_decoder(pGlobal_sel_codebook),
+ basisu_transcoder::basisu_transcoder() :
m_ready_to_transcode(false)
{
}
@@ -10778,6 +10656,8 @@ namespace basist
return false;
}
+ //const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0;
+
if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2)
{
BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n");
@@ -11001,6 +10881,7 @@ namespace basist
case block_format::cRGB565: return "RGB565";
case block_format::cBGR565: return "BGR565";
case block_format::cRGBA4444: return "RGBA4444";
+ case block_format::cUASTC_4x4: return "UASTC_4x4";
case block_format::cFXT1_RGB: return "FXT1_RGB";
case block_format::cPVRTC2_4_RGB: return "PVRTC2_4_RGB";
case block_format::cPVRTC2_4_RGBA: return "PVRTC2_4_RGBA";
@@ -12567,12 +12448,8 @@ namespace basist
bits = read_bits64(blk.m_bytes, bit_ofs, basisu::minimum<int>(64, 128 - (int)bit_ofs));
else
{
-#ifdef __EMSCRIPTEN__
bits = blk.m_dwords[2];
bits |= (((uint64_t)blk.m_dwords[3]) << 32U);
-#else
- bits = blk.m_qwords[1];
-#endif
if (bit_ofs >= 64U)
bits >>= (bit_ofs - 64U);
@@ -16722,8 +16599,8 @@ namespace basist
#if BASISD_SUPPORT_KTX2
const uint8_t g_ktx2_file_identifier[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
- ktx2_transcoder::ktx2_transcoder(basist::etc1_global_selector_codebook* pGlobal_sel_codebook) :
- m_etc1s_transcoder(pGlobal_sel_codebook)
+ ktx2_transcoder::ktx2_transcoder() :
+ m_etc1s_transcoder()
{
clear();
}
@@ -17334,6 +17211,7 @@ namespace basist
bool ktx2_transcoder::decompress_level_data(uint32_t level_index, basisu::uint8_vec& uncomp_data)
{
+ const uint8_t* pComp_data = m_levels[level_index].m_byte_offset + m_pData;
const uint64_t comp_size = m_levels[level_index].m_byte_length;
const uint64_t uncomp_size = m_levels[level_index].m_uncompressed_byte_length;
@@ -17349,7 +17227,7 @@ namespace basist
return false;
}
- if (!uncomp_data.try_resize(uncomp_size))
+ if (!uncomp_data.try_resize((size_t)uncomp_size))
{
BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Out of memory\n");
return false;
@@ -17358,7 +17236,6 @@ namespace basist
if (m_header.m_supercompression_scheme == KTX2_SS_ZSTANDARD)
{
#if BASISD_SUPPORT_KTX2_ZSTD
- const uint8_t* pComp_data = m_levels[level_index].m_byte_offset + m_pData;
size_t actualUncompSize = ZSTD_decompress(uncomp_data.data(), (size_t)uncomp_size, pComp_data, (size_t)comp_size);
if (ZSTD_isError(actualUncompSize))
{
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.h b/thirdparty/basis_universal/transcoder/basisu_transcoder.h
index bf3aed3dc3..3327e8ddb7 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.h
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.h
@@ -34,7 +34,6 @@
#include "basisu_transcoder_internal.h"
#include "basisu_transcoder_uastc.h"
-#include "basisu_global_selector_palette.h"
#include "basisu_file_headers.h"
namespace basist
@@ -190,7 +189,7 @@ namespace basist
friend class basisu_transcoder;
public:
- basisu_lowlevel_etc1s_transcoder(const basist::etc1_global_selector_codebook* pGlobal_sel_codebook);
+ basisu_lowlevel_etc1s_transcoder();
void set_global_codebooks(const basisu_lowlevel_etc1s_transcoder* pGlobal_codebook) { m_pGlobal_codebook = pGlobal_codebook; }
const basisu_lowlevel_etc1s_transcoder* get_global_codebooks() const { return m_pGlobal_codebook; }
@@ -248,17 +247,13 @@ namespace basist
typedef basisu::vector<selector> selector_vec;
const selector_vec& get_selectors() const { return m_local_selectors; }
-
- const etc1_global_selector_codebook* get_global_sel_codebook() const { return m_pGlobal_sel_codebook; }
-
+
private:
const basisu_lowlevel_etc1s_transcoder* m_pGlobal_codebook;
endpoint_vec m_local_endpoints;
selector_vec m_local_selectors;
-
- const etc1_global_selector_codebook* m_pGlobal_sel_codebook;
-
+
huffman_decoding_table m_endpoint_pred_model, m_delta_endpoint_model, m_selector_model, m_selector_history_buf_rle_model;
uint32_t m_selector_history_buf_size;
@@ -442,7 +437,7 @@ namespace basist
basisu_transcoder& operator= (const basisu_transcoder&);
public:
- basisu_transcoder(const etc1_global_selector_codebook* pGlobal_sel_codebook);
+ basisu_transcoder();
// Validates the .basis file. This computes a crc16 over the entire file, so it's slow.
bool validate_file_checksums(const void* pData, uint32_t data_size, bool full_validation) const;
@@ -770,7 +765,7 @@ namespace basist
class ktx2_transcoder
{
public:
- ktx2_transcoder(basist::etc1_global_selector_codebook* pGlobal_sel_codebook);
+ ktx2_transcoder();
// Frees all allocations, resets object.
void clear();
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h b/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h
index 2422d788a9..776a99861a 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_internal.h
@@ -20,8 +20,8 @@
#pragma warning (disable: 4127) // conditional expression is constant
#endif
-#define BASISD_LIB_VERSION 115
-#define BASISD_VERSION_STRING "01.15"
+#define BASISD_LIB_VERSION 116
+#define BASISD_VERSION_STRING "01.16"
#ifdef _DEBUG
#define BASISD_BUILD_DEBUG
@@ -46,18 +46,18 @@ namespace basist
{
cETC1, // ETC1S RGB
cETC2_RGBA, // full ETC2 EAC RGBA8 block
- cBC1, // DXT1 RGB
- cBC3, // BC4 block followed by a four color BC1 block
- cBC4, // DXT5A (alpha block only)
- cBC5, // two BC4 blocks
+ cBC1, // DXT1 RGB
+ cBC3, // BC4 block followed by a four color BC1 block
+ cBC4, // DXT5A (alpha block only)
+ cBC5, // two BC4 blocks
cPVRTC1_4_RGB, // opaque-only PVRTC1 4bpp
- cPVRTC1_4_RGBA, // PVRTC1 4bpp RGBA
- cBC7, // Full BC7 block, any mode
+ cPVRTC1_4_RGBA, // PVRTC1 4bpp RGBA
+ cBC7, // Full BC7 block, any mode
cBC7_M5_COLOR, // RGB BC7 mode 5 color (writes an opaque mode 5 block)
cBC7_M5_ALPHA, // alpha portion of BC7 mode 5 (cBC7_M5_COLOR output data must have been written to the output buffer first to set the mode/rot fields etc.)
cETC2_EAC_A8, // alpha block of ETC2 EAC (first 8 bytes of the 16-bit ETC2 EAC RGBA format)
cASTC_4x4, // ASTC 4x4 (either color-only or color+alpha). Note that the transcoder always currently assumes sRGB is not enabled when outputting ASTC
- // data. If you use a sRGB ASTC format you'll get ~1 LSB of additional error, because of the different way ASTC decoders scale 8-bit endpoints to 16-bits during unpacking.
+ // data. If you use a sRGB ASTC format you'll get ~1 LSB of additional error, because of the different way ASTC decoders scale 8-bit endpoints to 16-bits during unpacking.
cATC_RGB,
cATC_RGBA_INTERPOLATED_ALPHA,
@@ -72,8 +72,8 @@ namespace basist
cIndices, // Used internally: Write 16-bit endpoint and selector indices directly to output (output block must be at least 32-bits)
cRGB32, // Writes RGB components to 32bpp output pixels
- cRGBA32, // Writes RGB255 components to 32bpp output pixels
- cA32, // Writes alpha component to 32bpp output pixels
+ cRGBA32, // Writes RGB255 components to 32bpp output pixels
+ cA32, // Writes alpha component to 32bpp output pixels
cRGB565,
cBGR565,
@@ -82,6 +82,8 @@ namespace basist
cRGBA4444_ALPHA,
cRGBA4444_COLOR_OPAQUE,
cRGBA4444,
+
+ cUASTC_4x4,
cTotalBlockFormats
};
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h b/thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h
index d501a2af6e..f91314f4ff 100644
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder_uastc.h
@@ -205,10 +205,6 @@ namespace basist
{
uint8_t m_bytes[16];
uint32_t m_dwords[4];
-
-#ifndef __EMSCRIPTEN__
- uint64_t m_qwords[2];
-#endif
};
};
diff --git a/thirdparty/brotli/LICENSE b/thirdparty/brotli/LICENSE
new file mode 100644
index 0000000000..33b7cdd2db
--- /dev/null
+++ b/thirdparty/brotli/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/thirdparty/brotli/common/constants.c b/thirdparty/brotli/common/constants.c
new file mode 100644
index 0000000000..89866b1505
--- /dev/null
+++ b/thirdparty/brotli/common/constants.c
@@ -0,0 +1,15 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include "constants.h"
+
+const BrotliPrefixCodeRange
+ _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {
+ {1, 2}, {5, 2}, {9, 2}, {13, 2}, {17, 3}, {25, 3},
+ {33, 3}, {41, 3}, {49, 4}, {65, 4}, {81, 4}, {97, 4},
+ {113, 5}, {145, 5}, {177, 5}, {209, 5}, {241, 6}, {305, 6},
+ {369, 7}, {497, 8}, {753, 9}, {1265, 10}, {2289, 11}, {4337, 12},
+ {8433, 13}, {16625, 24}};
diff --git a/thirdparty/brotli/common/constants.h b/thirdparty/brotli/common/constants.h
new file mode 100644
index 0000000000..433c7b24d0
--- /dev/null
+++ b/thirdparty/brotli/common/constants.h
@@ -0,0 +1,200 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/**
+ * @file
+ * Common constants used in decoder and encoder API.
+ */
+
+#ifndef BROTLI_COMMON_CONSTANTS_H_
+#define BROTLI_COMMON_CONSTANTS_H_
+
+#include "platform.h"
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+/* Specification: 7.3. Encoding of the context map */
+#define BROTLI_CONTEXT_MAP_MAX_RLE 16
+
+/* Specification: 2. Compressed representation overview */
+#define BROTLI_MAX_NUMBER_OF_BLOCK_TYPES 256
+
+/* Specification: 3.3. Alphabet sizes: insert-and-copy length */
+#define BROTLI_NUM_LITERAL_SYMBOLS 256
+#define BROTLI_NUM_COMMAND_SYMBOLS 704
+#define BROTLI_NUM_BLOCK_LEN_SYMBOLS 26
+#define BROTLI_MAX_CONTEXT_MAP_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + \
+ BROTLI_CONTEXT_MAP_MAX_RLE)
+#define BROTLI_MAX_BLOCK_TYPE_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 2)
+
+/* Specification: 3.5. Complex prefix codes */
+#define BROTLI_REPEAT_PREVIOUS_CODE_LENGTH 16
+#define BROTLI_REPEAT_ZERO_CODE_LENGTH 17
+#define BROTLI_CODE_LENGTH_CODES (BROTLI_REPEAT_ZERO_CODE_LENGTH + 1)
+/* "code length of 8 is repeated" */
+#define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8
+
+/* "Large Window Brotli" */
+
+/**
+ * The theoretical maximum number of distance bits specified for large window
+ * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit
+ * encoders and decoders only support up to 30 max distance bits, the value is
+ * set to 62 because it affects the large window brotli file format.
+ * Specifically, it affects the encoding of simple huffman tree for distances,
+ * see Specification RFC 7932 chapter 3.4.
+ */
+#define BROTLI_LARGE_MAX_DISTANCE_BITS 62U
+#define BROTLI_LARGE_MIN_WBITS 10
+/**
+ * The maximum supported large brotli window bits by the encoder and decoder.
+ * Large window brotli allows up to 62 bits, however the current encoder and
+ * decoder, designed for 32-bit integers, only support up to 30 bits maximum.
+ */
+#define BROTLI_LARGE_MAX_WBITS 30
+
+/* Specification: 4. Encoding of distances */
+#define BROTLI_NUM_DISTANCE_SHORT_CODES 16
+/**
+ * Maximal number of "postfix" bits.
+ *
+ * Number of "postfix" bits is stored as 2 bits in meta-block header.
+ */
+#define BROTLI_MAX_NPOSTFIX 3
+#define BROTLI_MAX_NDIRECT 120
+#define BROTLI_MAX_DISTANCE_BITS 24U
+#define BROTLI_DISTANCE_ALPHABET_SIZE(NPOSTFIX, NDIRECT, MAXNBITS) ( \
+ BROTLI_NUM_DISTANCE_SHORT_CODES + (NDIRECT) + \
+ ((MAXNBITS) << ((NPOSTFIX) + 1)))
+/* BROTLI_NUM_DISTANCE_SYMBOLS == 1128 */
+#define BROTLI_NUM_DISTANCE_SYMBOLS \
+ BROTLI_DISTANCE_ALPHABET_SIZE( \
+ BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS)
+
+/* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932
+ brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and
+ NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */
+#define BROTLI_MAX_DISTANCE 0x3FFFFFC
+
+/* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit
+ allows safe distance calculation without overflows, given the distance
+ alphabet size is limited to corresponding size
+ (see kLargeWindowDistanceCodeLimits). */
+#define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC
+
+
+/* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */
+#define BROTLI_NUM_INS_COPY_CODES 24
+
+/* 7.1. Context modes and context ID lookup for literals */
+/* "context IDs for literals are in the range of 0..63" */
+#define BROTLI_LITERAL_CONTEXT_BITS 6
+
+/* 7.2. Context ID for distances */
+#define BROTLI_DISTANCE_CONTEXT_BITS 2
+
+/* 9.1. Format of the Stream Header */
+/* Number of slack bytes for window size. Don't confuse
+ with BROTLI_NUM_DISTANCE_SHORT_CODES. */
+#define BROTLI_WINDOW_GAP 16
+#define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP)
+
+typedef struct BrotliDistanceCodeLimit {
+ uint32_t max_alphabet_size;
+ uint32_t max_distance;
+} BrotliDistanceCodeLimit;
+
+/* This function calculates maximal size of distance alphabet, such that the
+ distances greater than the given values can not be represented.
+
+ This limits are designed to support fast and safe 32-bit decoders.
+ "32-bit" means that signed integer values up to ((1 << 31) - 1) could be
+ safely expressed.
+
+ Brotli distance alphabet symbols do not represent consecutive distance
+ ranges. Each distance alphabet symbol (excluding direct distances and short
+ codes), represent interleaved (for NPOSTFIX > 0) range of distances.
+ A "group" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved
+ range. Two consecutive groups require the same amount of "extra bits".
+
+ It is important that distance alphabet represents complete "groups".
+ To avoid complex logic on encoder side about interleaved ranges
+ it was decided to restrict both sides to complete distance code "groups".
+ */
+BROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit(
+ uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) {
+ BrotliDistanceCodeLimit result;
+ /* Marking this function as unused, because not all files
+ including "constants.h" use it -> compiler warns about that. */
+ BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit);
+ if (max_distance <= ndirect) {
+ /* This case never happens / exists only for the sake of completeness. */
+ result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES;
+ result.max_distance = max_distance;
+ return result;
+ } else {
+ /* The first prohibited value. */
+ uint32_t forbidden_distance = max_distance + 1;
+ /* Subtract "directly" encoded region. */
+ uint32_t offset = forbidden_distance - ndirect - 1;
+ uint32_t ndistbits = 0;
+ uint32_t tmp;
+ uint32_t half;
+ uint32_t group;
+ /* Postfix for the last dcode in the group. */
+ uint32_t postfix = (1u << npostfix) - 1;
+ uint32_t extra;
+ uint32_t start;
+ /* Remove postfix and "head-start". */
+ offset = (offset >> npostfix) + 4;
+ /* Calculate the number of distance bits. */
+ tmp = offset / 2;
+ /* Poor-man's log2floor, to avoid extra dependencies. */
+ while (tmp != 0) {ndistbits++; tmp = tmp >> 1;}
+ /* One bit is covered with subrange addressing ("half"). */
+ ndistbits--;
+ /* Find subrange. */
+ half = (offset >> ndistbits) & 1;
+ /* Calculate the "group" part of dcode. */
+ group = ((ndistbits - 1) << 1) | half;
+ /* Calculated "group" covers the prohibited distance value. */
+ if (group == 0) {
+ /* This case is added for correctness; does not occur for limit > 128. */
+ result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES;
+ result.max_distance = ndirect;
+ return result;
+ }
+ /* Decrement "group", so it is the last permitted "group". */
+ group--;
+ /* After group was decremented, ndistbits and half must be recalculated. */
+ ndistbits = (group >> 1) + 1;
+ /* The last available distance in the subrange has all extra bits set. */
+ extra = (1u << ndistbits) - 1;
+ /* Calculate region start. NB: ndistbits >= 1. */
+ start = (1u << (ndistbits + 1)) - 4;
+ /* Move to subregion. */
+ start += (group & 1) << ndistbits;
+ /* Calculate the alphabet size. */
+ result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect +
+ BROTLI_NUM_DISTANCE_SHORT_CODES + 1;
+ /* Calculate the maximal distance representable by alphabet. */
+ result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1;
+ return result;
+ }
+}
+
+/* Represents the range of values belonging to a prefix code:
+ [offset, offset + 2^nbits) */
+typedef struct {
+ uint16_t offset;
+ uint8_t nbits;
+} BrotliPrefixCodeRange;
+
+/* "Soft-private", it is exported, but not "advertised" as API. */
+BROTLI_COMMON_API extern const BrotliPrefixCodeRange
+ _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];
+
+#endif /* BROTLI_COMMON_CONSTANTS_H_ */
diff --git a/thirdparty/brotli/common/context.c b/thirdparty/brotli/common/context.c
new file mode 100644
index 0000000000..7f9c958699
--- /dev/null
+++ b/thirdparty/brotli/common/context.c
@@ -0,0 +1,156 @@
+#include "context.h"
+
+#include <brotli/types.h>
+
+/* Common context lookup table for all context modes. */
+const uint8_t _kBrotliContextLookupTable[2048] = {
+ /* CONTEXT_LSB6, last byte. */
+ 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,
+ 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,
+ 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,
+ 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,
+
+ /* CONTEXT_LSB6, second last byte, */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* CONTEXT_MSB6, last byte. */
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7,
+ 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11,
+ 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,
+ 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,
+ 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
+ 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,
+ 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
+ 32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35,
+ 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
+ 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47,
+ 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,
+ 52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55,
+ 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59,
+ 60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63,
+
+ /* CONTEXT_MSB6, second last byte, */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+ /* CONTEXT_UTF8, last byte. */
+ /* ASCII range. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 0, 0, 4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12,
+ 12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48,
+ 52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12,
+ 12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56,
+ 60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12, 0,
+ /* UTF8 continuation byte range. */
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
+ /* UTF8 lead byte range. */
+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+
+ /* CONTEXT_UTF8 second last byte. */
+ /* ASCII range. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,
+ 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
+ 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0,
+ /* UTF8 continuation byte range. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* UTF8 lead byte range. */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+
+ /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */
+ 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56,
+
+ /* CONTEXT_SIGNED, second last byte. */
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
+};
diff --git a/thirdparty/brotli/common/context.h b/thirdparty/brotli/common/context.h
new file mode 100644
index 0000000000..685a279dc0
--- /dev/null
+++ b/thirdparty/brotli/common/context.h
@@ -0,0 +1,113 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Lookup table to map the previous two bytes to a context id.
+
+ There are four different context modeling modes defined here:
+ CONTEXT_LSB6: context id is the least significant 6 bits of the last byte,
+ CONTEXT_MSB6: context id is the most significant 6 bits of the last byte,
+ CONTEXT_UTF8: second-order context model tuned for UTF8-encoded text,
+ CONTEXT_SIGNED: second-order context model tuned for signed integers.
+
+ If |p1| and |p2| are the previous two bytes, and |mode| is current context
+ mode, we calculate the context as:
+
+ context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256].
+
+ For CONTEXT_UTF8 mode, if the previous two bytes are ASCII characters
+ (i.e. < 128), this will be equivalent to
+
+ context = 4 * context1(p1) + context2(p2),
+
+ where context1 is based on the previous byte in the following way:
+
+ 0 : non-ASCII control
+ 1 : \t, \n, \r
+ 2 : space
+ 3 : other punctuation
+ 4 : " '
+ 5 : %
+ 6 : ( < [ {
+ 7 : ) > ] }
+ 8 : , ; :
+ 9 : .
+ 10 : =
+ 11 : number
+ 12 : upper-case vowel
+ 13 : upper-case consonant
+ 14 : lower-case vowel
+ 15 : lower-case consonant
+
+ and context2 is based on the second last byte:
+
+ 0 : control, space
+ 1 : punctuation
+ 2 : upper-case letter, number
+ 3 : lower-case letter
+
+ If the last byte is ASCII, and the second last byte is not (in a valid UTF8
+ stream it will be a continuation byte, value between 128 and 191), the
+ context is the same as if the second last byte was an ASCII control or space.
+
+ If the last byte is a UTF8 lead byte (value >= 192), then the next byte will
+ be a continuation byte and the context id is 2 or 3 depending on the LSB of
+ the last byte and to a lesser extent on the second last byte if it is ASCII.
+
+ If the last byte is a UTF8 continuation byte, the second last byte can be:
+ - continuation byte: the next byte is probably ASCII or lead byte (assuming
+ 4-byte UTF8 characters are rare) and the context id is 0 or 1.
+ - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1
+ - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3
+
+ The possible value combinations of the previous two bytes, the range of
+ context ids and the type of the next byte is summarized in the table below:
+
+ |--------\-----------------------------------------------------------------|
+ | \ Last byte |
+ | Second \---------------------------------------------------------------|
+ | last byte \ ASCII | cont. byte | lead byte |
+ | \ (0-127) | (128-191) | (192-) |
+ |=============|===================|=====================|==================|
+ | ASCII | next: ASCII/lead | not valid | next: cont. |
+ | (0-127) | context: 4 - 63 | | context: 2 - 3 |
+ |-------------|-------------------|---------------------|------------------|
+ | cont. byte | next: ASCII/lead | next: ASCII/lead | next: cont. |
+ | (128-191) | context: 4 - 63 | context: 0 - 1 | context: 2 - 3 |
+ |-------------|-------------------|---------------------|------------------|
+ | lead byte | not valid | next: ASCII/lead | not valid |
+ | (192-207) | | context: 0 - 1 | |
+ |-------------|-------------------|---------------------|------------------|
+ | lead byte | not valid | next: cont. | not valid |
+ | (208-) | | context: 2 - 3 | |
+ |-------------|-------------------|---------------------|------------------|
+*/
+
+#ifndef BROTLI_COMMON_CONTEXT_H_
+#define BROTLI_COMMON_CONTEXT_H_
+
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+typedef enum ContextType {
+ CONTEXT_LSB6 = 0,
+ CONTEXT_MSB6 = 1,
+ CONTEXT_UTF8 = 2,
+ CONTEXT_SIGNED = 3
+} ContextType;
+
+/* "Soft-private", it is exported, but not "advertised" as API. */
+/* Common context lookup table for all context modes. */
+BROTLI_COMMON_API extern const uint8_t _kBrotliContextLookupTable[2048];
+
+typedef const uint8_t* ContextLut;
+
+/* typeof(MODE) == ContextType; returns ContextLut */
+#define BROTLI_CONTEXT_LUT(MODE) (&_kBrotliContextLookupTable[(MODE) << 9])
+
+/* typeof(LUT) == ContextLut */
+#define BROTLI_CONTEXT(P1, P2, LUT) ((LUT)[P1] | ((LUT) + 256)[P2])
+
+#endif /* BROTLI_COMMON_CONTEXT_H_ */
diff --git a/thirdparty/brotli/common/dictionary.c b/thirdparty/brotli/common/dictionary.c
new file mode 100644
index 0000000000..307525788c
--- /dev/null
+++ b/thirdparty/brotli/common/dictionary.c
@@ -0,0 +1,5916 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include "dictionary.h"
+#include "platform.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
+static const uint8_t kBrotliDictionaryData[] =
+/* GENERATED CODE START */
+{
+116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99,
+111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105
+,116,121,111,112,101,110,106,117,115,116,108,105,107,101,102,114,101,101,119,111
+,114,107,116,101,120,116,121,101,97,114,111,118,101,114,98,111,100,121,108,111,
+118,101,102,111,114,109,98,111,111,107,112,108,97,121,108,105,118,101,108,105,
+110,101,104,101,108,112,104,111,109,101,115,105,100,101,109,111,114,101,119,111,
+114,100,108,111,110,103,116,104,101,109,118,105,101,119,102,105,110,100,112,97,
+103,101,100,97,121,115,102,117,108,108,104,101,97,100,116,101,114,109,101,97,99,
+104,97,114,101,97,102,114,111,109,116,114,117,101,109,97,114,107,97,98,108,101,
+117,112,111,110,104,105,103,104,100,97,116,101,108,97,110,100,110,101,119,115,
+101,118,101,110,110,101,120,116,99,97,115,101,98,111,116,104,112,111,115,116,117
+,115,101,100,109,97,100,101,104,97,110,100,104,101,114,101,119,104,97,116,110,97
+,109,101,76,105,110,107,98,108,111,103,115,105,122,101,98,97,115,101,104,101,108
+,100,109,97,107,101,109,97,105,110,117,115,101,114,39,41,32,43,104,111,108,100,
+101,110,100,115,119,105,116,104,78,101,119,115,114,101,97,100,119,101,114,101,
+115,105,103,110,116,97,107,101,104,97,118,101,103,97,109,101,115,101,101,110,99,
+97,108,108,112,97,116,104,119,101,108,108,112,108,117,115,109,101,110,117,102,
+105,108,109,112,97,114,116,106,111,105,110,116,104,105,115,108,105,115,116,103,
+111,111,100,110,101,101,100,119,97,121,115,119,101,115,116,106,111,98,115,109,
+105,110,100,97,108,115,111,108,111,103,111,114,105,99,104,117,115,101,115,108,97
+,115,116,116,101,97,109,97,114,109,121,102,111,111,100,107,105,110,103,119,105,
+108,108,101,97,115,116,119,97,114,100,98,101,115,116,102,105,114,101,80,97,103,
+101,107,110,111,119,97,119,97,121,46,112,110,103,109,111,118,101,116,104,97,110,
+108,111,97,100,103,105,118,101,115,101,108,102,110,111,116,101,109,117,99,104,
+102,101,101,100,109,97,110,121,114,111,99,107,105,99,111,110,111,110,99,101,108,
+111,111,107,104,105,100,101,100,105,101,100,72,111,109,101,114,117,108,101,104,
+111,115,116,97,106,97,120,105,110,102,111,99,108,117,98,108,97,119,115,108,101,
+115,115,104,97,108,102,115,111,109,101,115,117,99,104,122,111,110,101,49,48,48,
+37,111,110,101,115,99,97,114,101,84,105,109,101,114,97,99,101,98,108,117,101,102
+,111,117,114,119,101,101,107,102,97,99,101,104,111,112,101,103,97,118,101,104,97
+,114,100,108,111,115,116,119,104,101,110,112,97,114,107,107,101,112,116,112,97,
+115,115,115,104,105,112,114,111,111,109,72,84,77,76,112,108,97,110,84,121,112,
+101,100,111,110,101,115,97,118,101,107,101,101,112,102,108,97,103,108,105,110,
+107,115,111,108,100,102,105,118,101,116,111,111,107,114,97,116,101,116,111,119,
+110,106,117,109,112,116,104,117,115,100,97,114,107,99,97,114,100,102,105,108,101
+,102,101,97,114,115,116,97,121,107,105,108,108,116,104,97,116,102,97,108,108,97,
+117,116,111,101,118,101,114,46,99,111,109,116,97,108,107,115,104,111,112,118,111
+,116,101,100,101,101,112,109,111,100,101,114,101,115,116,116,117,114,110,98,111,
+114,110,98,97,110,100,102,101,108,108,114,111,115,101,117,114,108,40,115,107,105
+,110,114,111,108,101,99,111,109,101,97,99,116,115,97,103,101,115,109,101,101,116
+,103,111,108,100,46,106,112,103,105,116,101,109,118,97,114,121,102,101,108,116,
+116,104,101,110,115,101,110,100,100,114,111,112,86,105,101,119,99,111,112,121,49
+,46,48,34,60,47,97,62,115,116,111,112,101,108,115,101,108,105,101,115,116,111,
+117,114,112,97,99,107,46,103,105,102,112,97,115,116,99,115,115,63,103,114,97,121
+,109,101,97,110,38,103,116,59,114,105,100,101,115,104,111,116,108,97,116,101,115
+,97,105,100,114,111,97,100,118,97,114,32,102,101,101,108,106,111,104,110,114,105
+,99,107,112,111,114,116,102,97,115,116,39,85,65,45,100,101,97,100,60,47,98,62,
+112,111,111,114,98,105,108,108,116,121,112,101,85,46,83,46,119,111,111,100,109,
+117,115,116,50,112,120,59,73,110,102,111,114,97,110,107,119,105,100,101,119,97,
+110,116,119,97,108,108,108,101,97,100,91,48,93,59,112,97,117,108,119,97,118,101,
+115,117,114,101,36,40,39,35,119,97,105,116,109,97,115,115,97,114,109,115,103,111
+,101,115,103,97,105,110,108,97,110,103,112,97,105,100,33,45,45,32,108,111,99,107
+,117,110,105,116,114,111,111,116,119,97,108,107,102,105,114,109,119,105,102,101,
+120,109,108,34,115,111,110,103,116,101,115,116,50,48,112,120,107,105,110,100,114
+,111,119,115,116,111,111,108,102,111,110,116,109,97,105,108,115,97,102,101,115,
+116,97,114,109,97,112,115,99,111,114,101,114,97,105,110,102,108,111,119,98,97,98
+,121,115,112,97,110,115,97,121,115,52,112,120,59,54,112,120,59,97,114,116,115,
+102,111,111,116,114,101,97,108,119,105,107,105,104,101,97,116,115,116,101,112,
+116,114,105,112,111,114,103,47,108,97,107,101,119,101,97,107,116,111,108,100,70,
+111,114,109,99,97,115,116,102,97,110,115,98,97,110,107,118,101,114,121,114,117,
+110,115,106,117,108,121,116,97,115,107,49,112,120,59,103,111,97,108,103,114,101,
+119,115,108,111,119,101,100,103,101,105,100,61,34,115,101,116,115,53,112,120,59,
+46,106,115,63,52,48,112,120,105,102,32,40,115,111,111,110,115,101,97,116,110,111
+,110,101,116,117,98,101,122,101,114,111,115,101,110,116,114,101,101,100,102,97,
+99,116,105,110,116,111,103,105,102,116,104,97,114,109,49,56,112,120,99,97,109,
+101,104,105,108,108,98,111,108,100,122,111,111,109,118,111,105,100,101,97,115,
+121,114,105,110,103,102,105,108,108,112,101,97,107,105,110,105,116,99,111,115,
+116,51,112,120,59,106,97,99,107,116,97,103,115,98,105,116,115,114,111,108,108,
+101,100,105,116,107,110,101,119,110,101,97,114,60,33,45,45,103,114,111,119,74,83
+,79,78,100,117,116,121,78,97,109,101,115,97,108,101,121,111,117,32,108,111,116,
+115,112,97,105,110,106,97,122,122,99,111,108,100,101,121,101,115,102,105,115,104
+,119,119,119,46,114,105,115,107,116,97,98,115,112,114,101,118,49,48,112,120,114,
+105,115,101,50,53,112,120,66,108,117,101,100,105,110,103,51,48,48,44,98,97,108,
+108,102,111,114,100,101,97,114,110,119,105,108,100,98,111,120,46,102,97,105,114,
+108,97,99,107,118,101,114,115,112,97,105,114,106,117,110,101,116,101,99,104,105,
+102,40,33,112,105,99,107,101,118,105,108,36,40,34,35,119,97,114,109,108,111,114,
+100,100,111,101,115,112,117,108,108,44,48,48,48,105,100,101,97,100,114,97,119,
+104,117,103,101,115,112,111,116,102,117,110,100,98,117,114,110,104,114,101,102,
+99,101,108,108,107,101,121,115,116,105,99,107,104,111,117,114,108,111,115,115,
+102,117,101,108,49,50,112,120,115,117,105,116,100,101,97,108,82,83,83,34,97,103,
+101,100,103,114,101,121,71,69,84,34,101,97,115,101,97,105,109,115,103,105,114,
+108,97,105,100,115,56,112,120,59,110,97,118,121,103,114,105,100,116,105,112,115,
+35,57,57,57,119,97,114,115,108,97,100,121,99,97,114,115,41,59,32,125,112,104,112
+,63,104,101,108,108,116,97,108,108,119,104,111,109,122,104,58,229,42,47,13,10,32
+,49,48,48,104,97,108,108,46,10,10,65,55,112,120,59,112,117,115,104,99,104,97,116
+,48,112,120,59,99,114,101,119,42,47,60,47,104,97,115,104,55,53,112,120,102,108,
+97,116,114,97,114,101,32,38,38,32,116,101,108,108,99,97,109,112,111,110,116,111,
+108,97,105,100,109,105,115,115,115,107,105,112,116,101,110,116,102,105,110,101,
+109,97,108,101,103,101,116,115,112,108,111,116,52,48,48,44,13,10,13,10,99,111,
+111,108,102,101,101,116,46,112,104,112,60,98,114,62,101,114,105,99,109,111,115,
+116,103,117,105,100,98,101,108,108,100,101,115,99,104,97,105,114,109,97,116,104,
+97,116,111,109,47,105,109,103,38,35,56,50,108,117,99,107,99,101,110,116,48,48,48
+,59,116,105,110,121,103,111,110,101,104,116,109,108,115,101,108,108,100,114,117,
+103,70,82,69,69,110,111,100,101,110,105,99,107,63,105,100,61,108,111,115,101,110
+,117,108,108,118,97,115,116,119,105,110,100,82,83,83,32,119,101,97,114,114,101,
+108,121,98,101,101,110,115,97,109,101,100,117,107,101,110,97,115,97,99,97,112,
+101,119,105,115,104,103,117,108,102,84,50,51,58,104,105,116,115,115,108,111,116,
+103,97,116,101,107,105,99,107,98,108,117,114,116,104,101,121,49,53,112,120,39,39
+,41,59,41,59,34,62,109,115,105,101,119,105,110,115,98,105,114,100,115,111,114,
+116,98,101,116,97,115,101,101,107,84,49,56,58,111,114,100,115,116,114,101,101,
+109,97,108,108,54,48,112,120,102,97,114,109,226,128,153,115,98,111,121,115,91,48
+,93,46,39,41,59,34,80,79,83,84,98,101,97,114,107,105,100,115,41,59,125,125,109,
+97,114,121,116,101,110,100,40,85,75,41,113,117,97,100,122,104,58,230,45,115,105,
+122,45,45,45,45,112,114,111,112,39,41,59,13,108,105,102,116,84,49,57,58,118,105,
+99,101,97,110,100,121,100,101,98,116,62,82,83,83,112,111,111,108,110,101,99,107,
+98,108,111,119,84,49,54,58,100,111,111,114,101,118,97,108,84,49,55,58,108,101,
+116,115,102,97,105,108,111,114,97,108,112,111,108,108,110,111,118,97,99,111,108,
+115,103,101,110,101,32,226,128,148,115,111,102,116,114,111,109,101,116,105,108,
+108,114,111,115,115,60,104,51,62,112,111,117,114,102,97,100,101,112,105,110,107,
+60,116,114,62,109,105,110,105,41,124,33,40,109,105,110,101,122,104,58,232,98,97,
+114,115,104,101,97,114,48,48,41,59,109,105,108,107,32,45,45,62,105,114,111,110,
+102,114,101,100,100,105,115,107,119,101,110,116,115,111,105,108,112,117,116,115,
+47,106,115,47,104,111,108,121,84,50,50,58,73,83,66,78,84,50,48,58,97,100,97,109,
+115,101,101,115,60,104,50,62,106,115,111,110,39,44,32,39,99,111,110,116,84,50,49
+,58,32,82,83,83,108,111,111,112,97,115,105,97,109,111,111,110,60,47,112,62,115,
+111,117,108,76,73,78,69,102,111,114,116,99,97,114,116,84,49,52,58,60,104,49,62,
+56,48,112,120,33,45,45,60,57,112,120,59,84,48,52,58,109,105,107,101,58,52,54,90,
+110,105,99,101,105,110,99,104,89,111,114,107,114,105,99,101,122,104,58,228,39,41
+,41,59,112,117,114,101,109,97,103,101,112,97,114,97,116,111,110,101,98,111,110,
+100,58,51,55,90,95,111,102,95,39,93,41,59,48,48,48,44,122,104,58,231,116,97,110,
+107,121,97,114,100,98,111,119,108,98,117,115,104,58,53,54,90,74,97,118,97,51,48,
+112,120,10,124,125,10,37,67,51,37,58,51,52,90,106,101,102,102,69,88,80,73,99,97,
+115,104,118,105,115,97,103,111,108,102,115,110,111,119,122,104,58,233,113,117,
+101,114,46,99,115,115,115,105,99,107,109,101,97,116,109,105,110,46,98,105,110,
+100,100,101,108,108,104,105,114,101,112,105,99,115,114,101,110,116,58,51,54,90,
+72,84,84,80,45,50,48,49,102,111,116,111,119,111,108,102,69,78,68,32,120,98,111,
+120,58,53,52,90,66,79,68,89,100,105,99,107,59,10,125,10,101,120,105,116,58,51,53
+,90,118,97,114,115,98,101,97,116,39,125,41,59,100,105,101,116,57,57,57,59,97,110
+,110,101,125,125,60,47,91,105,93,46,76,97,110,103,107,109,194,178,119,105,114,
+101,116,111,121,115,97,100,100,115,115,101,97,108,97,108,101,120,59,10,9,125,101
+,99,104,111,110,105,110,101,46,111,114,103,48,48,53,41,116,111,110,121,106,101,
+119,115,115,97,110,100,108,101,103,115,114,111,111,102,48,48,48,41,32,50,48,48,
+119,105,110,101,103,101,97,114,100,111,103,115,98,111,111,116,103,97,114,121,99,
+117,116,115,116,121,108,101,116,101,109,112,116,105,111,110,46,120,109,108,99,
+111,99,107,103,97,110,103,36,40,39,46,53,48,112,120,80,104,46,68,109,105,115,99,
+97,108,97,110,108,111,97,110,100,101,115,107,109,105,108,101,114,121,97,110,117,
+110,105,120,100,105,115,99,41,59,125,10,100,117,115,116,99,108,105,112,41,46,10,
+10,55,48,112,120,45,50,48,48,68,86,68,115,55,93,62,60,116,97,112,101,100,101,109
+,111,105,43,43,41,119,97,103,101,101,117,114,111,112,104,105,108,111,112,116,115
+,104,111,108,101,70,65,81,115,97,115,105,110,45,50,54,84,108,97,98,115,112,101,
+116,115,85,82,76,32,98,117,108,107,99,111,111,107,59,125,13,10,72,69,65,68,91,48
+,93,41,97,98,98,114,106,117,97,110,40,49,57,56,108,101,115,104,116,119,105,110,
+60,47,105,62,115,111,110,121,103,117,121,115,102,117,99,107,112,105,112,101,124,
+45,10,33,48,48,50,41,110,100,111,119,91,49,93,59,91,93,59,10,76,111,103,32,115,
+97,108,116,13,10,9,9,98,97,110,103,116,114,105,109,98,97,116,104,41,123,13,10,48
+,48,112,120,10,125,41,59,107,111,58,236,102,101,101,115,97,100,62,13,115,58,47,
+47,32,91,93,59,116,111,108,108,112,108,117,103,40,41,123,10,123,13,10,32,46,106,
+115,39,50,48,48,112,100,117,97,108,98,111,97,116,46,74,80,71,41,59,10,125,113,
+117,111,116,41,59,10,10,39,41,59,10,13,10,125,13,50,48,49,52,50,48,49,53,50,48,
+49,54,50,48,49,55,50,48,49,56,50,48,49,57,50,48,50,48,50,48,50,49,50,48,50,50,50
+,48,50,51,50,48,50,52,50,48,50,53,50,48,50,54,50,48,50,55,50,48,50,56,50,48,50,
+57,50,48,51,48,50,48,51,49,50,48,51,50,50,48,51,51,50,48,51,52,50,48,51,53,50,48
+,51,54,50,48,51,55,50,48,49,51,50,48,49,50,50,48,49,49,50,48,49,48,50,48,48,57,
+50,48,48,56,50,48,48,55,50,48,48,54,50,48,48,53,50,48,48,52,50,48,48,51,50,48,48
+,50,50,48,48,49,50,48,48,48,49,57,57,57,49,57,57,56,49,57,57,55,49,57,57,54,49,
+57,57,53,49,57,57,52,49,57,57,51,49,57,57,50,49,57,57,49,49,57,57,48,49,57,56,57
+,49,57,56,56,49,57,56,55,49,57,56,54,49,57,56,53,49,57,56,52,49,57,56,51,49,57,
+56,50,49,57,56,49,49,57,56,48,49,57,55,57,49,57,55,56,49,57,55,55,49,57,55,54,49
+,57,55,53,49,57,55,52,49,57,55,51,49,57,55,50,49,57,55,49,49,57,55,48,49,57,54,
+57,49,57,54,56,49,57,54,55,49,57,54,54,49,57,54,53,49,57,54,52,49,57,54,51,49,57
+,54,50,49,57,54,49,49,57,54,48,49,57,53,57,49,57,53,56,49,57,53,55,49,57,53,54,
+49,57,53,53,49,57,53,52,49,57,53,51,49,57,53,50,49,57,53,49,49,57,53,48,49,48,48
+,48,49,48,50,52,49,51,57,52,48,48,48,48,57,57,57,57,99,111,109,111,109,195,161,
+115,101,115,116,101,101,115,116,97,112,101,114,111,116,111,100,111,104,97,99,101
+,99,97,100,97,97,195,177,111,98,105,101,110,100,195,173,97,97,115,195,173,118,
+105,100,97,99,97,115,111,111,116,114,111,102,111,114,111,115,111,108,111,111,116
+,114,97,99,117,97,108,100,105,106,111,115,105,100,111,103,114,97,110,116,105,112
+,111,116,101,109,97,100,101,98,101,97,108,103,111,113,117,195,169,101,115,116,
+111,110,97,100,97,116,114,101,115,112,111,99,111,99,97,115,97,98,97,106,111,116,
+111,100,97,115,105,110,111,97,103,117,97,112,117,101,115,117,110,111,115,97,110,
+116,101,100,105,99,101,108,117,105,115,101,108,108,97,109,97,121,111,122,111,110
+,97,97,109,111,114,112,105,115,111,111,98,114,97,99,108,105,99,101,108,108,111,
+100,105,111,115,104,111,114,97,99,97,115,105,208,183,208,176,208,189,208,176,208
+,190,208,188,209,128,208,176,209,128,209,131,209,130,208,176,208,189,208,181,208
+,191,208,190,208,190,209,130,208,184,208,183,208,189,208,190,208,180,208,190,209
+,130,208,190,208,182,208,181,208,190,208,189,208,184,209,133,208,157,208,176,208
+,181,208,181,208,177,209,139,208,188,209,139,208,146,209,139,209,129,208,190,208
+,178,209,139,208,178,208,190,208,157,208,190,208,190,208,177,208,159,208,190,208
+,187,208,184,208,189,208,184,208,160,208,164,208,157,208,181,208,156,209,139,209
+,130,209,139,208,158,208,189,208,184,208,188,208,180,208,176,208,151,208,176,208
+,148,208,176,208,157,209,131,208,158,208,177,209,130,208,181,208,152,208,183,208
+,181,208,185,208,189,209,131,208,188,208,188,208,162,209,139,209,131,208,182,217
+,129,217,138,216,163,217,134,217,133,216,167,217,133,216,185,217,131,217,132,216
+,163,217,136,216,177,216,175,217,138,216,167,217,129,217,137,217,135,217,136,217
+,132,217,133,217,132,217,131,216,167,217,136,217,132,217,135,216,168,216,179,216
+,167,217,132,216,165,217,134,217,135,217,138,216,163,217,138,217,130,216,175,217
+,135,217,132,216,171,217,133,216,168,217,135,217,132,217,136,217,132,217,138,216
+,168,217,132,216,167,217,138,216,168,217,131,216,180,217,138,216,167,217,133,216
+,163,217,133,217,134,216,170,216,168,217,138,217,132,217,134,216,173,216,168,217
+,135,217,133,217,133,216,180,217,136,216,180,102,105,114,115,116,118,105,100,101
+,111,108,105,103,104,116,119,111,114,108,100,109,101,100,105,97,119,104,105,116,
+101,99,108,111,115,101,98,108,97,99,107,114,105,103,104,116,115,109,97,108,108,
+98,111,111,107,115,112,108,97,99,101,109,117,115,105,99,102,105,101,108,100,111,
+114,100,101,114,112,111,105,110,116,118,97,108,117,101,108,101,118,101,108,116,
+97,98,108,101,98,111,97,114,100,104,111,117,115,101,103,114,111,117,112,119,111,
+114,107,115,121,101,97,114,115,115,116,97,116,101,116,111,100,97,121,119,97,116,
+101,114,115,116,97,114,116,115,116,121,108,101,100,101,97,116,104,112,111,119,
+101,114,112,104,111,110,101,110,105,103,104,116,101,114,114,111,114,105,110,112,
+117,116,97,98,111,117,116,116,101,114,109,115,116,105,116,108,101,116,111,111,
+108,115,101,118,101,110,116,108,111,99,97,108,116,105,109,101,115,108,97,114,103
+,101,119,111,114,100,115,103,97,109,101,115,115,104,111,114,116,115,112,97,99,
+101,102,111,99,117,115,99,108,101,97,114,109,111,100,101,108,98,108,111,99,107,
+103,117,105,100,101,114,97,100,105,111,115,104,97,114,101,119,111,109,101,110,97
+,103,97,105,110,109,111,110,101,121,105,109,97,103,101,110,97,109,101,115,121,
+111,117,110,103,108,105,110,101,115,108,97,116,101,114,99,111,108,111,114,103,
+114,101,101,110,102,114,111,110,116,38,97,109,112,59,119,97,116,99,104,102,111,
+114,99,101,112,114,105,99,101,114,117,108,101,115,98,101,103,105,110,97,102,116,
+101,114,118,105,115,105,116,105,115,115,117,101,97,114,101,97,115,98,101,108,111
+,119,105,110,100,101,120,116,111,116,97,108,104,111,117,114,115,108,97,98,101,
+108,112,114,105,110,116,112,114,101,115,115,98,117,105,108,116,108,105,110,107,
+115,115,112,101,101,100,115,116,117,100,121,116,114,97,100,101,102,111,117,110,
+100,115,101,110,115,101,117,110,100,101,114,115,104,111,119,110,102,111,114,109,
+115,114,97,110,103,101,97,100,100,101,100,115,116,105,108,108,109,111,118,101,
+100,116,97,107,101,110,97,98,111,118,101,102,108,97,115,104,102,105,120,101,100,
+111,102,116,101,110,111,116,104,101,114,118,105,101,119,115,99,104,101,99,107,
+108,101,103,97,108,114,105,118,101,114,105,116,101,109,115,113,117,105,99,107,
+115,104,97,112,101,104,117,109,97,110,101,120,105,115,116,103,111,105,110,103,
+109,111,118,105,101,116,104,105,114,100,98,97,115,105,99,112,101,97,99,101,115,
+116,97,103,101,119,105,100,116,104,108,111,103,105,110,105,100,101,97,115,119,
+114,111,116,101,112,97,103,101,115,117,115,101,114,115,100,114,105,118,101,115,
+116,111,114,101,98,114,101,97,107,115,111,117,116,104,118,111,105,99,101,115,105
+,116,101,115,109,111,110,116,104,119,104,101,114,101,98,117,105,108,100,119,104,
+105,99,104,101,97,114,116,104,102,111,114,117,109,116,104,114,101,101,115,112,
+111,114,116,112,97,114,116,121,67,108,105,99,107,108,111,119,101,114,108,105,118
+,101,115,99,108,97,115,115,108,97,121,101,114,101,110,116,114,121,115,116,111,
+114,121,117,115,97,103,101,115,111,117,110,100,99,111,117,114,116,121,111,117,
+114,32,98,105,114,116,104,112,111,112,117,112,116,121,112,101,115,97,112,112,108
+,121,73,109,97,103,101,98,101,105,110,103,117,112,112,101,114,110,111,116,101,
+115,101,118,101,114,121,115,104,111,119,115,109,101,97,110,115,101,120,116,114,
+97,109,97,116,99,104,116,114,97,99,107,107,110,111,119,110,101,97,114,108,121,98
+,101,103,97,110,115,117,112,101,114,112,97,112,101,114,110,111,114,116,104,108,
+101,97,114,110,103,105,118,101,110,110,97,109,101,100,101,110,100,101,100,84,101
+,114,109,115,112,97,114,116,115,71,114,111,117,112,98,114,97,110,100,117,115,105
+,110,103,119,111,109,97,110,102,97,108,115,101,114,101,97,100,121,97,117,100,105
+,111,116,97,107,101,115,119,104,105,108,101,46,99,111,109,47,108,105,118,101,100
+,99,97,115,101,115,100,97,105,108,121,99,104,105,108,100,103,114,101,97,116,106,
+117,100,103,101,116,104,111,115,101,117,110,105,116,115,110,101,118,101,114,98,
+114,111,97,100,99,111,97,115,116,99,111,118,101,114,97,112,112,108,101,102,105,
+108,101,115,99,121,99,108,101,115,99,101,110,101,112,108,97,110,115,99,108,105,
+99,107,119,114,105,116,101,113,117,101,101,110,112,105,101,99,101,101,109,97,105
+,108,102,114,97,109,101,111,108,100,101,114,112,104,111,116,111,108,105,109,105,
+116,99,97,99,104,101,99,105,118,105,108,115,99,97,108,101,101,110,116,101,114,
+116,104,101,109,101,116,104,101,114,101,116,111,117,99,104,98,111,117,110,100,
+114,111,121,97,108,97,115,107,101,100,119,104,111,108,101,115,105,110,99,101,115
+,116,111,99,107,32,110,97,109,101,102,97,105,116,104,104,101,97,114,116,101,109,
+112,116,121,111,102,102,101,114,115,99,111,112,101,111,119,110,101,100,109,105,
+103,104,116,97,108,98,117,109,116,104,105,110,107,98,108,111,111,100,97,114,114,
+97,121,109,97,106,111,114,116,114,117,115,116,99,97,110,111,110,117,110,105,111,
+110,99,111,117,110,116,118,97,108,105,100,115,116,111,110,101,83,116,121,108,101
+,76,111,103,105,110,104,97,112,112,121,111,99,99,117,114,108,101,102,116,58,102,
+114,101,115,104,113,117,105,116,101,102,105,108,109,115,103,114,97,100,101,110,
+101,101,100,115,117,114,98,97,110,102,105,103,104,116,98,97,115,105,115,104,111,
+118,101,114,97,117,116,111,59,114,111,117,116,101,46,104,116,109,108,109,105,120
+,101,100,102,105,110,97,108,89,111,117,114,32,115,108,105,100,101,116,111,112,
+105,99,98,114,111,119,110,97,108,111,110,101,100,114,97,119,110,115,112,108,105,
+116,114,101,97,99,104,82,105,103,104,116,100,97,116,101,115,109,97,114,99,104,
+113,117,111,116,101,103,111,111,100,115,76,105,110,107,115,100,111,117,98,116,97
+,115,121,110,99,116,104,117,109,98,97,108,108,111,119,99,104,105,101,102,121,111
+,117,116,104,110,111,118,101,108,49,48,112,120,59,115,101,114,118,101,117,110,
+116,105,108,104,97,110,100,115,67,104,101,99,107,83,112,97,99,101,113,117,101,
+114,121,106,97,109,101,115,101,113,117,97,108,116,119,105,99,101,48,44,48,48,48,
+83,116,97,114,116,112,97,110,101,108,115,111,110,103,115,114,111,117,110,100,101
+,105,103,104,116,115,104,105,102,116,119,111,114,116,104,112,111,115,116,115,108
+,101,97,100,115,119,101,101,107,115,97,118,111,105,100,116,104,101,115,101,109,
+105,108,101,115,112,108,97,110,101,115,109,97,114,116,97,108,112,104,97,112,108,
+97,110,116,109,97,114,107,115,114,97,116,101,115,112,108,97,121,115,99,108,97,
+105,109,115,97,108,101,115,116,101,120,116,115,115,116,97,114,115,119,114,111,
+110,103,60,47,104,51,62,116,104,105,110,103,46,111,114,103,47,109,117,108,116,
+105,104,101,97,114,100,80,111,119,101,114,115,116,97,110,100,116,111,107,101,110
+,115,111,108,105,100,40,116,104,105,115,98,114,105,110,103,115,104,105,112,115,
+115,116,97,102,102,116,114,105,101,100,99,97,108,108,115,102,117,108,108,121,102
+,97,99,116,115,97,103,101,110,116,84,104,105,115,32,47,47,45,45,62,97,100,109,
+105,110,101,103,121,112,116,69,118,101,110,116,49,53,112,120,59,69,109,97,105,
+108,116,114,117,101,34,99,114,111,115,115,115,112,101,110,116,98,108,111,103,115
+,98,111,120,34,62,110,111,116,101,100,108,101,97,118,101,99,104,105,110,97,115,
+105,122,101,115,103,117,101,115,116,60,47,104,52,62,114,111,98,111,116,104,101,
+97,118,121,116,114,117,101,44,115,101,118,101,110,103,114,97,110,100,99,114,105,
+109,101,115,105,103,110,115,97,119,97,114,101,100,97,110,99,101,112,104,97,115,
+101,62,60,33,45,45,101,110,95,85,83,38,35,51,57,59,50,48,48,112,120,95,110,97,
+109,101,108,97,116,105,110,101,110,106,111,121,97,106,97,120,46,97,116,105,111,
+110,115,109,105,116,104,85,46,83,46,32,104,111,108,100,115,112,101,116,101,114,
+105,110,100,105,97,110,97,118,34,62,99,104,97,105,110,115,99,111,114,101,99,111,
+109,101,115,100,111,105,110,103,112,114,105,111,114,83,104,97,114,101,49,57,57,
+48,115,114,111,109,97,110,108,105,115,116,115,106,97,112,97,110,102,97,108,108,
+115,116,114,105,97,108,111,119,110,101,114,97,103,114,101,101,60,47,104,50,62,97
+,98,117,115,101,97,108,101,114,116,111,112,101,114,97,34,45,47,47,87,99,97,114,
+100,115,104,105,108,108,115,116,101,97,109,115,80,104,111,116,111,116,114,117,
+116,104,99,108,101,97,110,46,112,104,112,63,115,97,105,110,116,109,101,116,97,
+108,108,111,117,105,115,109,101,97,110,116,112,114,111,111,102,98,114,105,101,
+102,114,111,119,34,62,103,101,110,114,101,116,114,117,99,107,108,111,111,107,115
+,86,97,108,117,101,70,114,97,109,101,46,110,101,116,47,45,45,62,10,60,116,114,
+121,32,123,10,118,97,114,32,109,97,107,101,115,99,111,115,116,115,112,108,97,105
+,110,97,100,117,108,116,113,117,101,115,116,116,114,97,105,110,108,97,98,111,114
+,104,101,108,112,115,99,97,117,115,101,109,97,103,105,99,109,111,116,111,114,116
+,104,101,105,114,50,53,48,112,120,108,101,97,115,116,115,116,101,112,115,67,111,
+117,110,116,99,111,117,108,100,103,108,97,115,115,115,105,100,101,115,102,117,
+110,100,115,104,111,116,101,108,97,119,97,114,100,109,111,117,116,104,109,111,
+118,101,115,112,97,114,105,115,103,105,118,101,115,100,117,116,99,104,116,101,
+120,97,115,102,114,117,105,116,110,117,108,108,44,124,124,91,93,59,116,111,112,
+34,62,10,60,33,45,45,80,79,83,84,34,111,99,101,97,110,60,98,114,47,62,102,108,
+111,111,114,115,112,101,97,107,100,101,112,116,104,32,115,105,122,101,98,97,110,
+107,115,99,97,116,99,104,99,104,97,114,116,50,48,112,120,59,97,108,105,103,110,
+100,101,97,108,115,119,111,117,108,100,53,48,112,120,59,117,114,108,61,34,112,97
+,114,107,115,109,111,117,115,101,77,111,115,116,32,46,46,46,60,47,97,109,111,110
+,103,98,114,97,105,110,98,111,100,121,32,110,111,110,101,59,98,97,115,101,100,99
+,97,114,114,121,100,114,97,102,116,114,101,102,101,114,112,97,103,101,95,104,111
+,109,101,46,109,101,116,101,114,100,101,108,97,121,100,114,101,97,109,112,114,
+111,118,101,106,111,105,110,116,60,47,116,114,62,100,114,117,103,115,60,33,45,45
+,32,97,112,114,105,108,105,100,101,97,108,97,108,108,101,110,101,120,97,99,116,
+102,111,114,116,104,99,111,100,101,115,108,111,103,105,99,86,105,101,119,32,115,
+101,101,109,115,98,108,97,110,107,112,111,114,116,115,32,40,50,48,48,115,97,118,
+101,100,95,108,105,110,107,103,111,97,108,115,103,114,97,110,116,103,114,101,101
+,107,104,111,109,101,115,114,105,110,103,115,114,97,116,101,100,51,48,112,120,59
+,119,104,111,115,101,112,97,114,115,101,40,41,59,34,32,66,108,111,99,107,108,105
+,110,117,120,106,111,110,101,115,112,105,120,101,108,39,41,59,34,62,41,59,105,
+102,40,45,108,101,102,116,100,97,118,105,100,104,111,114,115,101,70,111,99,117,
+115,114,97,105,115,101,98,111,120,101,115,84,114,97,99,107,101,109,101,110,116,
+60,47,101,109,62,98,97,114,34,62,46,115,114,99,61,116,111,119,101,114,97,108,116
+,61,34,99,97,98,108,101,104,101,110,114,121,50,52,112,120,59,115,101,116,117,112
+,105,116,97,108,121,115,104,97,114,112,109,105,110,111,114,116,97,115,116,101,
+119,97,110,116,115,116,104,105,115,46,114,101,115,101,116,119,104,101,101,108,
+103,105,114,108,115,47,99,115,115,47,49,48,48,37,59,99,108,117,98,115,115,116,
+117,102,102,98,105,98,108,101,118,111,116,101,115,32,49,48,48,48,107,111,114,101
+,97,125,41,59,13,10,98,97,110,100,115,113,117,101,117,101,61,32,123,125,59,56,48
+,112,120,59,99,107,105,110,103,123,13,10,9,9,97,104,101,97,100,99,108,111,99,107
+,105,114,105,115,104,108,105,107,101,32,114,97,116,105,111,115,116,97,116,115,70
+,111,114,109,34,121,97,104,111,111,41,91,48,93,59,65,98,111,117,116,102,105,110,
+100,115,60,47,104,49,62,100,101,98,117,103,116,97,115,107,115,85,82,76,32,61,99,
+101,108,108,115,125,41,40,41,59,49,50,112,120,59,112,114,105,109,101,116,101,108
+,108,115,116,117,114,110,115,48,120,54,48,48,46,106,112,103,34,115,112,97,105,
+110,98,101,97,99,104,116,97,120,101,115,109,105,99,114,111,97,110,103,101,108,45
+,45,62,60,47,103,105,102,116,115,115,116,101,118,101,45,108,105,110,107,98,111,
+100,121,46,125,41,59,10,9,109,111,117,110,116,32,40,49,57,57,70,65,81,60,47,114,
+111,103,101,114,102,114,97,110,107,67,108,97,115,115,50,56,112,120,59,102,101,
+101,100,115,60,104,49,62,60,115,99,111,116,116,116,101,115,116,115,50,50,112,120
+,59,100,114,105,110,107,41,32,124,124,32,108,101,119,105,115,115,104,97,108,108,
+35,48,51,57,59,32,102,111,114,32,108,111,118,101,100,119,97,115,116,101,48,48,
+112,120,59,106,97,58,227,130,115,105,109,111,110,60,102,111,110,116,114,101,112,
+108,121,109,101,101,116,115,117,110,116,101,114,99,104,101,97,112,116,105,103,
+104,116,66,114,97,110,100,41,32,33,61,32,100,114,101,115,115,99,108,105,112,115,
+114,111,111,109,115,111,110,107,101,121,109,111,98,105,108,109,97,105,110,46,78,
+97,109,101,32,112,108,97,116,101,102,117,110,110,121,116,114,101,101,115,99,111,
+109,47,34,49,46,106,112,103,119,109,111,100,101,112,97,114,97,109,83,84,65,82,84
+,108,101,102,116,32,105,100,100,101,110,44,32,50,48,49,41,59,10,125,10,102,111,
+114,109,46,118,105,114,117,115,99,104,97,105,114,116,114,97,110,115,119,111,114,
+115,116,80,97,103,101,115,105,116,105,111,110,112,97,116,99,104,60,33,45,45,10,
+111,45,99,97,99,102,105,114,109,115,116,111,117,114,115,44,48,48,48,32,97,115,
+105,97,110,105,43,43,41,123,97,100,111,98,101,39,41,91,48,93,105,100,61,49,48,98
+,111,116,104,59,109,101,110,117,32,46,50,46,109,105,46,112,110,103,34,107,101,
+118,105,110,99,111,97,99,104,67,104,105,108,100,98,114,117,99,101,50,46,106,112,
+103,85,82,76,41,43,46,106,112,103,124,115,117,105,116,101,115,108,105,99,101,104
+,97,114,114,121,49,50,48,34,32,115,119,101,101,116,116,114,62,13,10,110,97,109,
+101,61,100,105,101,103,111,112,97,103,101,32,115,119,105,115,115,45,45,62,10,10,
+35,102,102,102,59,34,62,76,111,103,46,99,111,109,34,116,114,101,97,116,115,104,
+101,101,116,41,32,38,38,32,49,52,112,120,59,115,108,101,101,112,110,116,101,110,
+116,102,105,108,101,100,106,97,58,227,131,105,100,61,34,99,78,97,109,101,34,119,
+111,114,115,101,115,104,111,116,115,45,98,111,120,45,100,101,108,116,97,10,38,
+108,116,59,98,101,97,114,115,58,52,56,90,60,100,97,116,97,45,114,117,114,97,108,
+60,47,97,62,32,115,112,101,110,100,98,97,107,101,114,115,104,111,112,115,61,32,
+34,34,59,112,104,112,34,62,99,116,105,111,110,49,51,112,120,59,98,114,105,97,110
+,104,101,108,108,111,115,105,122,101,61,111,61,37,50,70,32,106,111,105,110,109,
+97,121,98,101,60,105,109,103,32,105,109,103,34,62,44,32,102,106,115,105,109,103,
+34,32,34,41,91,48,93,77,84,111,112,66,84,121,112,101,34,110,101,119,108,121,68,
+97,110,115,107,99,122,101,99,104,116,114,97,105,108,107,110,111,119,115,60,47,
+104,53,62,102,97,113,34,62,122,104,45,99,110,49,48,41,59,10,45,49,34,41,59,116,
+121,112,101,61,98,108,117,101,115,116,114,117,108,121,100,97,118,105,115,46,106,
+115,39,59,62,13,10,60,33,115,116,101,101,108,32,121,111,117,32,104,50,62,13,10,
+102,111,114,109,32,106,101,115,117,115,49,48,48,37,32,109,101,110,117,46,13,10,9
+,13,10,119,97,108,101,115,114,105,115,107,115,117,109,101,110,116,100,100,105,
+110,103,98,45,108,105,107,116,101,97,99,104,103,105,102,34,32,118,101,103,97,115
+,100,97,110,115,107,101,101,115,116,105,115,104,113,105,112,115,117,111,109,105,
+115,111,98,114,101,100,101,115,100,101,101,110,116,114,101,116,111,100,111,115,
+112,117,101,100,101,97,195,177,111,115,101,115,116,195,161,116,105,101,110,101,
+104,97,115,116,97,111,116,114,111,115,112,97,114,116,101,100,111,110,100,101,110
+,117,101,118,111,104,97,99,101,114,102,111,114,109,97,109,105,115,109,111,109,
+101,106,111,114,109,117,110,100,111,97,113,117,195,173,100,195,173,97,115,115,
+195,179,108,111,97,121,117,100,97,102,101,99,104,97,116,111,100,97,115,116,97,
+110,116,111,109,101,110,111,115,100,97,116,111,115,111,116,114,97,115,115,105,
+116,105,111,109,117,99,104,111,97,104,111,114,97,108,117,103,97,114,109,97,121,
+111,114,101,115,116,111,115,104,111,114,97,115,116,101,110,101,114,97,110,116,
+101,115,102,111,116,111,115,101,115,116,97,115,112,97,195,173,115,110,117,101,
+118,97,115,97,108,117,100,102,111,114,111,115,109,101,100,105,111,113,117,105,
+101,110,109,101,115,101,115,112,111,100,101,114,99,104,105,108,101,115,101,114,
+195,161,118,101,99,101,115,100,101,99,105,114,106,111,115,195,169,101,115,116,97
+,114,118,101,110,116,97,103,114,117,112,111,104,101,99,104,111,101,108,108,111,
+115,116,101,110,103,111,97,109,105,103,111,99,111,115,97,115,110,105,118,101,108
+,103,101,110,116,101,109,105,115,109,97,97,105,114,101,115,106,117,108,105,111,
+116,101,109,97,115,104,97,99,105,97,102,97,118,111,114,106,117,110,105,111,108,
+105,98,114,101,112,117,110,116,111,98,117,101,110,111,97,117,116,111,114,97,98,
+114,105,108,98,117,101,110,97,116,101,120,116,111,109,97,114,122,111,115,97,98,
+101,114,108,105,115,116,97,108,117,101,103,111,99,195,179,109,111,101,110,101,
+114,111,106,117,101,103,111,112,101,114,195,186,104,97,98,101,114,101,115,116,
+111,121,110,117,110,99,97,109,117,106,101,114,118,97,108,111,114,102,117,101,114
+,97,108,105,98,114,111,103,117,115,116,97,105,103,117,97,108,118,111,116,111,115
+,99,97,115,111,115,103,117,195,173,97,112,117,101,100,111,115,111,109,111,115,97
+,118,105,115,111,117,115,116,101,100,100,101,98,101,110,110,111,99,104,101,98,
+117,115,99,97,102,97,108,116,97,101,117,114,111,115,115,101,114,105,101,100,105,
+99,104,111,99,117,114,115,111,99,108,97,118,101,99,97,115,97,115,108,101,195,179
+,110,112,108,97,122,111,108,97,114,103,111,111,98,114,97,115,118,105,115,116,97,
+97,112,111,121,111,106,117,110,116,111,116,114,97,116,97,118,105,115,116,111,99,
+114,101,97,114,99,97,109,112,111,104,101,109,111,115,99,105,110,99,111,99,97,114
+,103,111,112,105,115,111,115,111,114,100,101,110,104,97,99,101,110,195,161,114,
+101,97,100,105,115,99,111,112,101,100,114,111,99,101,114,99,97,112,117,101,100,
+97,112,97,112,101,108,109,101,110,111,114,195,186,116,105,108,99,108,97,114,111,
+106,111,114,103,101,99,97,108,108,101,112,111,110,101,114,116,97,114,100,101,110
+,97,100,105,101,109,97,114,99,97,115,105,103,117,101,101,108,108,97,115,115,105,
+103,108,111,99,111,99,104,101,109,111,116,111,115,109,97,100,114,101,99,108,97,
+115,101,114,101,115,116,111,110,105,195,177,111,113,117,101,100,97,112,97,115,97
+,114,98,97,110,99,111,104,105,106,111,115,118,105,97,106,101,112,97,98,108,111,
+195,169,115,116,101,118,105,101,110,101,114,101,105,110,111,100,101,106,97,114,
+102,111,110,100,111,99,97,110,97,108,110,111,114,116,101,108,101,116,114,97,99,
+97,117,115,97,116,111,109,97,114,109,97,110,111,115,108,117,110,101,115,97,117,
+116,111,115,118,105,108,108,97,118,101,110,100,111,112,101,115,97,114,116,105,
+112,111,115,116,101,110,103,97,109,97,114,99,111,108,108,101,118,97,112,97,100,
+114,101,117,110,105,100,111,118,97,109,111,115,122,111,110,97,115,97,109,98,111,
+115,98,97,110,100,97,109,97,114,105,97,97,98,117,115,111,109,117,99,104,97,115,
+117,98,105,114,114,105,111,106,97,118,105,118,105,114,103,114,97,100,111,99,104,
+105,99,97,97,108,108,195,173,106,111,118,101,110,100,105,99,104,97,101,115,116,
+97,110,116,97,108,101,115,115,97,108,105,114,115,117,101,108,111,112,101,115,111
+,115,102,105,110,101,115,108,108,97,109,97,98,117,115,99,111,195,169,115,116,97,
+108,108,101,103,97,110,101,103,114,111,112,108,97,122,97,104,117,109,111,114,112
+,97,103,97,114,106,117,110,116,97,100,111,98,108,101,105,115,108,97,115,98,111,
+108,115,97,98,97,195,177,111,104,97,98,108,97,108,117,99,104,97,195,129,114,101,
+97,100,105,99,101,110,106,117,103,97,114,110,111,116,97,115,118,97,108,108,101,
+97,108,108,195,161,99,97,114,103,97,100,111,108,111,114,97,98,97,106,111,101,115
+,116,195,169,103,117,115,116,111,109,101,110,116,101,109,97,114,105,111,102,105,
+114,109,97,99,111,115,116,111,102,105,99,104,97,112,108,97,116,97,104,111,103,97
+,114,97,114,116,101,115,108,101,121,101,115,97,113,117,101,108,109,117,115,101,
+111,98,97,115,101,115,112,111,99,111,115,109,105,116,97,100,99,105,101,108,111,
+99,104,105,99,111,109,105,101,100,111,103,97,110,97,114,115,97,110,116,111,101,
+116,97,112,97,100,101,98,101,115,112,108,97,121,97,114,101,100,101,115,115,105,
+101,116,101,99,111,114,116,101,99,111,114,101,97,100,117,100,97,115,100,101,115,
+101,111,118,105,101,106,111,100,101,115,101,97,97,103,117,97,115,38,113,117,111,
+116,59,100,111,109,97,105,110,99,111,109,109,111,110,115,116,97,116,117,115,101,
+118,101,110,116,115,109,97,115,116,101,114,115,121,115,116,101,109,97,99,116,105
+,111,110,98,97,110,110,101,114,114,101,109,111,118,101,115,99,114,111,108,108,
+117,112,100,97,116,101,103,108,111,98,97,108,109,101,100,105,117,109,102,105,108
+,116,101,114,110,117,109,98,101,114,99,104,97,110,103,101,114,101,115,117,108,
+116,112,117,98,108,105,99,115,99,114,101,101,110,99,104,111,111,115,101,110,111,
+114,109,97,108,116,114,97,118,101,108,105,115,115,117,101,115,115,111,117,114,99
+,101,116,97,114,103,101,116,115,112,114,105,110,103,109,111,100,117,108,101,109,
+111,98,105,108,101,115,119,105,116,99,104,112,104,111,116,111,115,98,111,114,100
+,101,114,114,101,103,105,111,110,105,116,115,101,108,102,115,111,99,105,97,108,
+97,99,116,105,118,101,99,111,108,117,109,110,114,101,99,111,114,100,102,111,108,
+108,111,119,116,105,116,108,101,62,101,105,116,104,101,114,108,101,110,103,116,
+104,102,97,109,105,108,121,102,114,105,101,110,100,108,97,121,111,117,116,97,117
+,116,104,111,114,99,114,101,97,116,101,114,101,118,105,101,119,115,117,109,109,
+101,114,115,101,114,118,101,114,112,108,97,121,101,100,112,108,97,121,101,114,
+101,120,112,97,110,100,112,111,108,105,99,121,102,111,114,109,97,116,100,111,117
+,98,108,101,112,111,105,110,116,115,115,101,114,105,101,115,112,101,114,115,111,
+110,108,105,118,105,110,103,100,101,115,105,103,110,109,111,110,116,104,115,102,
+111,114,99,101,115,117,110,105,113,117,101,119,101,105,103,104,116,112,101,111,
+112,108,101,101,110,101,114,103,121,110,97,116,117,114,101,115,101,97,114,99,104
+,102,105,103,117,114,101,104,97,118,105,110,103,99,117,115,116,111,109,111,102,
+102,115,101,116,108,101,116,116,101,114,119,105,110,100,111,119,115,117,98,109,
+105,116,114,101,110,100,101,114,103,114,111,117,112,115,117,112,108,111,97,100,
+104,101,97,108,116,104,109,101,116,104,111,100,118,105,100,101,111,115,115,99,
+104,111,111,108,102,117,116,117,114,101,115,104,97,100,111,119,100,101,98,97,116
+,101,118,97,108,117,101,115,79,98,106,101,99,116,111,116,104,101,114,115,114,105
+,103,104,116,115,108,101,97,103,117,101,99,104,114,111,109,101,115,105,109,112,
+108,101,110,111,116,105,99,101,115,104,97,114,101,100,101,110,100,105,110,103,
+115,101,97,115,111,110,114,101,112,111,114,116,111,110,108,105,110,101,115,113,
+117,97,114,101,98,117,116,116,111,110,105,109,97,103,101,115,101,110,97,98,108,
+101,109,111,118,105,110,103,108,97,116,101,115,116,119,105,110,116,101,114,70,
+114,97,110,99,101,112,101,114,105,111,100,115,116,114,111,110,103,114,101,112,
+101,97,116,76,111,110,100,111,110,100,101,116,97,105,108,102,111,114,109,101,100
+,100,101,109,97,110,100,115,101,99,117,114,101,112,97,115,115,101,100,116,111,
+103,103,108,101,112,108,97,99,101,115,100,101,118,105,99,101,115,116,97,116,105,
+99,99,105,116,105,101,115,115,116,114,101,97,109,121,101,108,108,111,119,97,116,
+116,97,99,107,115,116,114,101,101,116,102,108,105,103,104,116,104,105,100,100,
+101,110,105,110,102,111,34,62,111,112,101,110,101,100,117,115,101,102,117,108,
+118,97,108,108,101,121,99,97,117,115,101,115,108,101,97,100,101,114,115,101,99,
+114,101,116,115,101,99,111,110,100,100,97,109,97,103,101,115,112,111,114,116,115
+,101,120,99,101,112,116,114,97,116,105,110,103,115,105,103,110,101,100,116,104,
+105,110,103,115,101,102,102,101,99,116,102,105,101,108,100,115,115,116,97,116,
+101,115,111,102,102,105,99,101,118,105,115,117,97,108,101,100,105,116,111,114,
+118,111,108,117,109,101,82,101,112,111,114,116,109,117,115,101,117,109,109,111,
+118,105,101,115,112,97,114,101,110,116,97,99,99,101,115,115,109,111,115,116,108,
+121,109,111,116,104,101,114,34,32,105,100,61,34,109,97,114,107,101,116,103,114,
+111,117,110,100,99,104,97,110,99,101,115,117,114,118,101,121,98,101,102,111,114,
+101,115,121,109,98,111,108,109,111,109,101,110,116,115,112,101,101,99,104,109,
+111,116,105,111,110,105,110,115,105,100,101,109,97,116,116,101,114,67,101,110,
+116,101,114,111,98,106,101,99,116,101,120,105,115,116,115,109,105,100,100,108,
+101,69,117,114,111,112,101,103,114,111,119,116,104,108,101,103,97,99,121,109,97,
+110,110,101,114,101,110,111,117,103,104,99,97,114,101,101,114,97,110,115,119,101
+,114,111,114,105,103,105,110,112,111,114,116,97,108,99,108,105,101,110,116,115,
+101,108,101,99,116,114,97,110,100,111,109,99,108,111,115,101,100,116,111,112,105
+,99,115,99,111,109,105,110,103,102,97,116,104,101,114,111,112,116,105,111,110,
+115,105,109,112,108,121,114,97,105,115,101,100,101,115,99,97,112,101,99,104,111,
+115,101,110,99,104,117,114,99,104,100,101,102,105,110,101,114,101,97,115,111,110
+,99,111,114,110,101,114,111,117,116,112,117,116,109,101,109,111,114,121,105,102,
+114,97,109,101,112,111,108,105,99,101,109,111,100,101,108,115,78,117,109,98,101,
+114,100,117,114,105,110,103,111,102,102,101,114,115,115,116,121,108,101,115,107,
+105,108,108,101,100,108,105,115,116,101,100,99,97,108,108,101,100,115,105,108,
+118,101,114,109,97,114,103,105,110,100,101,108,101,116,101,98,101,116,116,101,
+114,98,114,111,119,115,101,108,105,109,105,116,115,71,108,111,98,97,108,115,105,
+110,103,108,101,119,105,100,103,101,116,99,101,110,116,101,114,98,117,100,103,
+101,116,110,111,119,114,97,112,99,114,101,100,105,116,99,108,97,105,109,115,101,
+110,103,105,110,101,115,97,102,101,116,121,99,104,111,105,99,101,115,112,105,114
+,105,116,45,115,116,121,108,101,115,112,114,101,97,100,109,97,107,105,110,103,
+110,101,101,100,101,100,114,117,115,115,105,97,112,108,101,97,115,101,101,120,
+116,101,110,116,83,99,114,105,112,116,98,114,111,107,101,110,97,108,108,111,119,
+115,99,104,97,114,103,101,100,105,118,105,100,101,102,97,99,116,111,114,109,101,
+109,98,101,114,45,98,97,115,101,100,116,104,101,111,114,121,99,111,110,102,105,
+103,97,114,111,117,110,100,119,111,114,107,101,100,104,101,108,112,101,100,67,
+104,117,114,99,104,105,109,112,97,99,116,115,104,111,117,108,100,97,108,119,97,
+121,115,108,111,103,111,34,32,98,111,116,116,111,109,108,105,115,116,34,62,41,
+123,118,97,114,32,112,114,101,102,105,120,111,114,97,110,103,101,72,101,97,100,
+101,114,46,112,117,115,104,40,99,111,117,112,108,101,103,97,114,100,101,110,98,
+114,105,100,103,101,108,97,117,110,99,104,82,101,118,105,101,119,116,97,107,105,
+110,103,118,105,115,105,111,110,108,105,116,116,108,101,100,97,116,105,110,103,
+66,117,116,116,111,110,98,101,97,117,116,121,116,104,101,109,101,115,102,111,114
+,103,111,116,83,101,97,114,99,104,97,110,99,104,111,114,97,108,109,111,115,116,
+108,111,97,100,101,100,67,104,97,110,103,101,114,101,116,117,114,110,115,116,114
+,105,110,103,114,101,108,111,97,100,77,111,98,105,108,101,105,110,99,111,109,101
+,115,117,112,112,108,121,83,111,117,114,99,101,111,114,100,101,114,115,118,105,
+101,119,101,100,38,110,98,115,112,59,99,111,117,114,115,101,65,98,111,117,116,32
+,105,115,108,97,110,100,60,104,116,109,108,32,99,111,111,107,105,101,110,97,109,
+101,61,34,97,109,97,122,111,110,109,111,100,101,114,110,97,100,118,105,99,101,
+105,110,60,47,97,62,58,32,84,104,101,32,100,105,97,108,111,103,104,111,117,115,
+101,115,66,69,71,73,78,32,77,101,120,105,99,111,115,116,97,114,116,115,99,101,
+110,116,114,101,104,101,105,103,104,116,97,100,100,105,110,103,73,115,108,97,110
+,100,97,115,115,101,116,115,69,109,112,105,114,101,83,99,104,111,111,108,101,102
+,102,111,114,116,100,105,114,101,99,116,110,101,97,114,108,121,109,97,110,117,97
+,108,83,101,108,101,99,116,46,10,10,79,110,101,106,111,105,110,101,100,109,101,
+110,117,34,62,80,104,105,108,105,112,97,119,97,114,100,115,104,97,110,100,108,
+101,105,109,112,111,114,116,79,102,102,105,99,101,114,101,103,97,114,100,115,107
+,105,108,108,115,110,97,116,105,111,110,83,112,111,114,116,115,100,101,103,114,
+101,101,119,101,101,107,108,121,32,40,101,46,103,46,98,101,104,105,110,100,100,
+111,99,116,111,114,108,111,103,103,101,100,117,110,105,116,101,100,60,47,98,62,
+60,47,98,101,103,105,110,115,112,108,97,110,116,115,97,115,115,105,115,116,97,
+114,116,105,115,116,105,115,115,117,101,100,51,48,48,112,120,124,99,97,110,97,
+100,97,97,103,101,110,99,121,115,99,104,101,109,101,114,101,109,97,105,110,66,
+114,97,122,105,108,115,97,109,112,108,101,108,111,103,111,34,62,98,101,121,111,
+110,100,45,115,99,97,108,101,97,99,99,101,112,116,115,101,114,118,101,100,109,97
+,114,105,110,101,70,111,111,116,101,114,99,97,109,101,114,97,60,47,104,49,62,10,
+95,102,111,114,109,34,108,101,97,118,101,115,115,116,114,101,115,115,34,32,47,62
+,13,10,46,103,105,102,34,32,111,110,108,111,97,100,108,111,97,100,101,114,79,120
+,102,111,114,100,115,105,115,116,101,114,115,117,114,118,105,118,108,105,115,116
+,101,110,102,101,109,97,108,101,68,101,115,105,103,110,115,105,122,101,61,34,97,
+112,112,101,97,108,116,101,120,116,34,62,108,101,118,101,108,115,116,104,97,110,
+107,115,104,105,103,104,101,114,102,111,114,99,101,100,97,110,105,109,97,108,97,
+110,121,111,110,101,65,102,114,105,99,97,97,103,114,101,101,100,114,101,99,101,
+110,116,80,101,111,112,108,101,60,98,114,32,47,62,119,111,110,100,101,114,112,
+114,105,99,101,115,116,117,114,110,101,100,124,124,32,123,125,59,109,97,105,110,
+34,62,105,110,108,105,110,101,115,117,110,100,97,121,119,114,97,112,34,62,102,97
+,105,108,101,100,99,101,110,115,117,115,109,105,110,117,116,101,98,101,97,99,111
+,110,113,117,111,116,101,115,49,53,48,112,120,124,101,115,116,97,116,101,114,101
+,109,111,116,101,101,109,97,105,108,34,108,105,110,107,101,100,114,105,103,104,
+116,59,115,105,103,110,97,108,102,111,114,109,97,108,49,46,104,116,109,108,115,
+105,103,110,117,112,112,114,105,110,99,101,102,108,111,97,116,58,46,112,110,103,
+34,32,102,111,114,117,109,46,65,99,99,101,115,115,112,97,112,101,114,115,115,111
+,117,110,100,115,101,120,116,101,110,100,72,101,105,103,104,116,115,108,105,100,
+101,114,85,84,70,45,56,34,38,97,109,112,59,32,66,101,102,111,114,101,46,32,87,
+105,116,104,115,116,117,100,105,111,111,119,110,101,114,115,109,97,110,97,103,
+101,112,114,111,102,105,116,106,81,117,101,114,121,97,110,110,117,97,108,112,97,
+114,97,109,115,98,111,117,103,104,116,102,97,109,111,117,115,103,111,111,103,108
+,101,108,111,110,103,101,114,105,43,43,41,32,123,105,115,114,97,101,108,115,97,
+121,105,110,103,100,101,99,105,100,101,104,111,109,101,34,62,104,101,97,100,101,
+114,101,110,115,117,114,101,98,114,97,110,99,104,112,105,101,99,101,115,98,108,
+111,99,107,59,115,116,97,116,101,100,116,111,112,34,62,60,114,97,99,105,110,103,
+114,101,115,105,122,101,45,45,38,103,116,59,112,97,99,105,116,121,115,101,120,
+117,97,108,98,117,114,101,97,117,46,106,112,103,34,32,49,48,44,48,48,48,111,98,
+116,97,105,110,116,105,116,108,101,115,97,109,111,117,110,116,44,32,73,110,99,46
+,99,111,109,101,100,121,109,101,110,117,34,32,108,121,114,105,99,115,116,111,100
+,97,121,46,105,110,100,101,101,100,99,111,117,110,116,121,95,108,111,103,111,46,
+70,97,109,105,108,121,108,111,111,107,101,100,77,97,114,107,101,116,108,115,101,
+32,105,102,80,108,97,121,101,114,116,117,114,107,101,121,41,59,118,97,114,32,102
+,111,114,101,115,116,103,105,118,105,110,103,101,114,114,111,114,115,68,111,109,
+97,105,110,125,101,108,115,101,123,105,110,115,101,114,116,66,108,111,103,60,47,
+102,111,111,116,101,114,108,111,103,105,110,46,102,97,115,116,101,114,97,103,101
+,110,116,115,60,98,111,100,121,32,49,48,112,120,32,48,112,114,97,103,109,97,102,
+114,105,100,97,121,106,117,110,105,111,114,100,111,108,108,97,114,112,108,97,99,
+101,100,99,111,118,101,114,115,112,108,117,103,105,110,53,44,48,48,48,32,112,97,
+103,101,34,62,98,111,115,116,111,110,46,116,101,115,116,40,97,118,97,116,97,114,
+116,101,115,116,101,100,95,99,111,117,110,116,102,111,114,117,109,115,115,99,104
+,101,109,97,105,110,100,101,120,44,102,105,108,108,101,100,115,104,97,114,101,
+115,114,101,97,100,101,114,97,108,101,114,116,40,97,112,112,101,97,114,83,117,98
+,109,105,116,108,105,110,101,34,62,98,111,100,121,34,62,10,42,32,84,104,101,84,
+104,111,117,103,104,115,101,101,105,110,103,106,101,114,115,101,121,78,101,119,
+115,60,47,118,101,114,105,102,121,101,120,112,101,114,116,105,110,106,117,114,
+121,119,105,100,116,104,61,67,111,111,107,105,101,83,84,65,82,84,32,97,99,114,
+111,115,115,95,105,109,97,103,101,116,104,114,101,97,100,110,97,116,105,118,101,
+112,111,99,107,101,116,98,111,120,34,62,10,83,121,115,116,101,109,32,68,97,118,
+105,100,99,97,110,99,101,114,116,97,98,108,101,115,112,114,111,118,101,100,65,
+112,114,105,108,32,114,101,97,108,108,121,100,114,105,118,101,114,105,116,101,
+109,34,62,109,111,114,101,34,62,98,111,97,114,100,115,99,111,108,111,114,115,99,
+97,109,112,117,115,102,105,114,115,116,32,124,124,32,91,93,59,109,101,100,105,97
+,46,103,117,105,116,97,114,102,105,110,105,115,104,119,105,100,116,104,58,115,
+104,111,119,101,100,79,116,104,101,114,32,46,112,104,112,34,32,97,115,115,117,
+109,101,108,97,121,101,114,115,119,105,108,115,111,110,115,116,111,114,101,115,
+114,101,108,105,101,102,115,119,101,100,101,110,67,117,115,116,111,109,101,97,
+115,105,108,121,32,121,111,117,114,32,83,116,114,105,110,103,10,10,87,104,105,
+108,116,97,121,108,111,114,99,108,101,97,114,58,114,101,115,111,114,116,102,114,
+101,110,99,104,116,104,111,117,103,104,34,41,32,43,32,34,60,98,111,100,121,62,98
+,117,121,105,110,103,98,114,97,110,100,115,77,101,109,98,101,114,110,97,109,101,
+34,62,111,112,112,105,110,103,115,101,99,116,111,114,53,112,120,59,34,62,118,115
+,112,97,99,101,112,111,115,116,101,114,109,97,106,111,114,32,99,111,102,102,101,
+101,109,97,114,116,105,110,109,97,116,117,114,101,104,97,112,112,101,110,60,47,
+110,97,118,62,107,97,110,115,97,115,108,105,110,107,34,62,73,109,97,103,101,115,
+61,102,97,108,115,101,119,104,105,108,101,32,104,115,112,97,99,101,48,38,97,109,
+112,59,32,10,10,73,110,32,32,112,111,119,101,114,80,111,108,115,107,105,45,99,
+111,108,111,114,106,111,114,100,97,110,66,111,116,116,111,109,83,116,97,114,116,
+32,45,99,111,117,110,116,50,46,104,116,109,108,110,101,119,115,34,62,48,49,46,
+106,112,103,79,110,108,105,110,101,45,114,105,103,104,116,109,105,108,108,101,
+114,115,101,110,105,111,114,73,83,66,78,32,48,48,44,48,48,48,32,103,117,105,100,
+101,115,118,97,108,117,101,41,101,99,116,105,111,110,114,101,112,97,105,114,46,
+120,109,108,34,32,32,114,105,103,104,116,115,46,104,116,109,108,45,98,108,111,99
+,107,114,101,103,69,120,112,58,104,111,118,101,114,119,105,116,104,105,110,118,
+105,114,103,105,110,112,104,111,110,101,115,60,47,116,114,62,13,117,115,105,110,
+103,32,10,9,118,97,114,32,62,39,41,59,10,9,60,47,116,100,62,10,60,47,116,114,62,
+10,98,97,104,97,115,97,98,114,97,115,105,108,103,97,108,101,103,111,109,97,103,
+121,97,114,112,111,108,115,107,105,115,114,112,115,107,105,216,177,216,175,217,
+136,228,184,173,230,150,135,231,174,128,228,189,147,231,185,129,233,171,148,228,
+191,161,230,129,175,228,184,173,229,155,189,230,136,145,228,187,172,228,184,128,
+228,184,170,229,133,172,229,143,184,231,174,161,231,144,134,232,174,186,229,157,
+155,229,143,175,228,187,165,230,156,141,229,138,161,230,151,182,233,151,180,228,
+184,170,228,186,186,228,186,167,229,147,129,232,135,170,229,183,177,228,188,129,
+228,184,154,230,159,165,231,156,139,229,183,165,228,189,156,232,129,148,231,179,
+187,230,178,161,230,156,137,231,189,145,231,171,153,230,137,128,230,156,137,232,
+175,132,232,174,186,228,184,173,229,191,131,230,150,135,231,171,160,231,148,168,
+230,136,183,233,166,150,233,161,181,228,189,156,232,128,133,230,138,128,230,156,
+175,233,151,174,233,162,152,231,155,184,229,133,179,228,184,139,232,189,189,230,
+144,156,231,180,162,228,189,191,231,148,168,232,189,175,228,187,182,229,156,168,
+231,186,191,228,184,187,233,162,152,232,181,132,230,150,153,232,167,134,233,162,
+145,229,155,158,229,164,141,230,179,168,229,134,140,231,189,145,231,187,156,230,
+148,182,232,151,143,229,134,133,229,174,185,230,142,168,232,141,144,229,184,130,
+229,156,186,230,182,136,230,129,175,231,169,186,233,151,180,229,143,145,229,184,
+131,228,187,128,228,185,136,229,165,189,229,143,139,231,148,159,230,180,187,229,
+155,190,231,137,135,229,143,145,229,177,149,229,166,130,230,158,156,230,137,139,
+230,156,186,230,150,176,233,151,187,230,156,128,230,150,176,230,150,185,229,188,
+143,229,140,151,228,186,172,230,143,144,228,190,155,229,133,179,228,186,142,230,
+155,180,229,164,154,232,191,153,228,184,170,231,179,187,231,187,159,231,159,165,
+233,129,147,230,184,184,230,136,143,229,185,191,229,145,138,229,133,182,228,187,
+150,229,143,145,232,161,168,229,174,137,229,133,168,231,172,172,228,184,128,228,
+188,154,229,145,152,232,191,155,232,161,140,231,130,185,229,135,187,231,137,136,
+230,157,131,231,148,181,229,173,144,228,184,150,231,149,140,232,174,190,232,174,
+161,229,133,141,232,180,185,230,149,153,232,130,178,229,138,160,229,133,165,230,
+180,187,229,138,168,228,187,150,228,187,172,229,149,134,229,147,129,229,141,154,
+229,174,162,231,142,176,229,156,168,228,184,138,230,181,183,229,166,130,228,189,
+149,229,183,178,231,187,143,231,149,153,232,168,128,232,175,166,231,187,134,231,
+164,190,229,140,186,231,153,187,229,189,149,230,156,172,231,171,153,233,156,128,
+232,166,129,228,187,183,230,160,188,230,148,175,230,140,129,229,155,189,233,153,
+133,233,147,190,230,142,165,229,155,189,229,174,182,229,187,186,232,174,190,230,
+156,139,229,143,139,233,152,133,232,175,187,230,179,149,229,190,139,228,189,141,
+231,189,174,231,187,143,230,181,142,233,128,137,230,139,169,232,191,153,230,160,
+183,229,189,147,229,137,141,229,136,134,231,177,187,230,142,146,232,161,140,229,
+155,160,228,184,186,228,186,164,230,152,147,230,156,128,229,144,142,233,159,179,
+228,185,144,228,184,141,232,131,189,233,128,154,232,191,135,232,161,140,228,184,
+154,231,167,145,230,138,128,229,143,175,232,131,189,232,174,190,229,164,135,229,
+144,136,228,189,156,229,164,167,229,174,182,231,164,190,228,188,154,231,160,148,
+231,169,182,228,184,147,228,184,154,229,133,168,233,131,168,233,161,185,231,155,
+174,232,191,153,233,135,140,232,191,152,230,152,175,229,188,128,229,167,139,230,
+131,133,229,134,181,231,148,181,232,132,145,230,150,135,228,187,182,229,147,129,
+231,137,140,229,184,174,229,138,169,230,150,135,229,140,150,232,181,132,230,186,
+144,229,164,167,229,173,166,229,173,166,228,185,160,229,156,176,229,157,128,230,
+181,143,232,167,136,230,138,149,232,181,132,229,183,165,231,168,139,232,166,129,
+230,177,130,230,128,142,228,185,136,230,151,182,229,128,153,229,138,159,232,131,
+189,228,184,187,232,166,129,231,155,174,229,137,141,232,181,132,232,174,175,229,
+159,142,229,184,130,230,150,185,230,179,149,231,148,181,229,189,177,230,139,155,
+232,129,152,229,163,176,230,152,142,228,187,187,228,189,149,229,129,165,229,186,
+183,230,149,176,230,141,174,231,190,142,229,155,189,230,177,189,232,189,166,228,
+187,139,231,187,141,228,189,134,230,152,175,228,186,164,230,181,129,231,148,159,
+228,186,167,230,137,128,228,187,165,231,148,181,232,175,157,230,152,190,231,164,
+186,228,184,128,228,186,155,229,141,149,228,189,141,228,186,186,229,145,152,229,
+136,134,230,158,144,229,156,176,229,155,190,230,151,133,230,184,184,229,183,165,
+229,133,183,229,173,166,231,148,159,231,179,187,229,136,151,231,189,145,229,143,
+139,229,184,150,229,173,144,229,175,134,231,160,129,233,162,145,233,129,147,230,
+142,167,229,136,182,229,156,176,229,140,186,229,159,186,230,156,172,229,133,168,
+229,155,189,231,189,145,228,184,138,233,135,141,232,166,129,231,172,172,228,186,
+140,229,150,156,230,172,162,232,191,155,229,133,165,229,143,139,230,131,133,232,
+191,153,228,186,155,232,128,131,232,175,149,229,143,145,231,142,176,229,159,185,
+232,174,173,228,187,165,228,184,138,230,148,191,229,186,156,230,136,144,228,184,
+186,231,142,175,229,162,131,233,166,153,230,184,175,229,144,140,230,151,182,229,
+168,177,228,185,144,229,143,145,233,128,129,228,184,128,229,174,154,229,188,128,
+229,143,145,228,189,156,229,147,129,230,160,135,229,135,134,230,172,162,232,191,
+142,232,167,163,229,134,179,229,156,176,230,150,185,228,184,128,228,184,139,228,
+187,165,229,143,138,232,180,163,228,187,187,230,136,150,232,128,133,229,174,162,
+230,136,183,228,187,163,232,161,168,231,167,175,229,136,134,229,165,179,228,186,
+186,230,149,176,231,160,129,233,148,128,229,148,174,229,135,186,231,142,176,231,
+166,187,231,186,191,229,186,148,231,148,168,229,136,151,232,161,168,228,184,141,
+229,144,140,231,188,150,232,190,145,231,187,159,232,174,161,230,159,165,232,175,
+162,228,184,141,232,166,129,230,156,137,229,133,179,230,156,186,230,158,132,229,
+190,136,229,164,154,230,146,173,230,148,190,231,187,132,231,187,135,230,148,191,
+231,173,150,231,155,180,230,142,165,232,131,189,229,138,155,230,157,165,230,186,
+144,230,153,130,233,150,147,231,156,139,229,136,176,231,131,173,233,151,168,229,
+133,179,233,148,174,228,184,147,229,140,186,233,157,158,229,184,184,232,139,177,
+232,175,173,231,153,190,229,186,166,229,184,140,230,156,155,231,190,142,229,165,
+179,230,175,148,232,190,131,231,159,165,232,175,134,232,167,132,229,174,154,229,
+187,186,232,174,174,233,131,168,233,151,168,230,132,143,232,167,129,231,178,190,
+229,189,169,230,151,165,230,156,172,230,143,144,233,171,152,229,143,145,232,168,
+128,230,150,185,233,157,162,229,159,186,233,135,145,229,164,132,231,144,134,230,
+157,131,233,153,144,229,189,177,231,137,135,233,147,182,232,161,140,232,191,152,
+230,156,137,229,136,134,228,186,171,231,137,169,229,147,129,231,187,143,232,144,
+165,230,183,187,229,138,160,228,184,147,229,174,182,232,191,153,231,167,141,232,
+175,157,233,162,152,232,181,183,230,157,165,228,184,154,229,138,161,229,133,172,
+229,145,138,232,174,176,229,189,149,231,174,128,228,187,139,232,180,168,233,135,
+143,231,148,183,228,186,186,229,189,177,229,147,141,229,188,149,231,148,168,230,
+138,165,229,145,138,233,131,168,229,136,134,229,191,171,233,128,159,229,146,168,
+232,175,162,230,151,182,229,176,154,230,179,168,230,132,143,231,148,179,232,175,
+183,229,173,166,230,160,161,229,186,148,232,175,165,229,142,134,229,143,178,229,
+143,170,230,152,175,232,191,148,229,155,158,232,180,173,228,185,176,229,144,141,
+231,167,176,228,184,186,228,186,134,230,136,144,229,138,159,232,175,180,230,152,
+142,228,190,155,229,186,148,229,173,169,229,173,144,228,184,147,233,162,152,231,
+168,139,229,186,143,228,184,128,232,136,172,230,156,131,229,147,161,229,143,170,
+230,156,137,229,133,182,229,174,131,228,191,157,230,138,164,232,128,140,228,184,
+148,228,187,138,229,164,169,231,170,151,229,143,163,229,138,168,230,128,129,231,
+138,182,230,128,129,231,137,185,229,136,171,232,174,164,228,184,186,229,191,133,
+233,161,187,230,155,180,230,150,176,229,176,143,232,175,180,230,136,145,229,128,
+145,228,189,156,228,184,186,229,170,146,228,189,147,229,140,133,230,139,172,233,
+130,163,228,185,136,228,184,128,230,160,183,229,155,189,229,134,133,230,152,175,
+229,144,166,230,160,185,230,141,174,231,148,181,232,167,134,229,173,166,233,153,
+162,229,133,183,230,156,137,232,191,135,231,168,139,231,148,177,228,186,142,228,
+186,186,230,137,141,229,135,186,230,157,165,228,184,141,232,191,135,230,173,163,
+229,156,168,230,152,142,230,152,159,230,149,133,228,186,139,229,133,179,231,179,
+187,230,160,135,233,162,152,229,149,134,229,138,161,232,190,147,229,133,165,228,
+184,128,231,155,180,229,159,186,231,161,128,230,149,153,229,173,166,228,186,134,
+232,167,163,229,187,186,231,173,145,231,187,147,230,158,156,229,133,168,231,144,
+131,233,128,154,231,159,165,232,174,161,229,136,146,229,175,185,228,186,142,232,
+137,186,230,156,175,231,155,184,229,134,140,229,143,145,231,148,159,231,156,159,
+231,154,132,229,187,186,231,171,139,231,173,137,231,186,167,231,177,187,229,158,
+139,231,187,143,233,170,140,229,174,158,231,142,176,229,136,182,228,189,156,230,
+157,165,232,135,170,230,160,135,231,173,190,228,187,165,228,184,139,229,142,159,
+229,136,155,230,151,160,230,179,149,229,133,182,228,184,173,229,128,139,228,186,
+186,228,184,128,229,136,135,230,140,135,229,141,151,229,133,179,233,151,173,233,
+155,134,229,155,162,231,172,172,228,184,137,229,133,179,230,179,168,229,155,160,
+230,173,164,231,133,167,231,137,135,230,183,177,229,156,179,229,149,134,228,184,
+154,229,185,191,229,183,158,230,151,165,230,156,159,233,171,152,231,186,167,230,
+156,128,232,191,145,231,187,188,229,144,136,232,161,168,231,164,186,228,184,147,
+232,190,145,232,161,140,228,184,186,228,186,164,233,128,154,232,175,132,228,187,
+183,232,167,137,229,190,151,231,178,190,229,141,142,229,174,182,229,186,173,229,
+174,140,230,136,144,230,132,159,232,167,137,229,174,137,232,163,133,229,190,151,
+229,136,176,233,130,174,228,187,182,229,136,182,229,186,166,233,163,159,229,147,
+129,232,153,189,231,132,182,232,189,172,232,189,189,230,138,165,228,187,183,232,
+174,176,232,128,133,230,150,185,230,161,136,232,161,140,230,148,191,228,186,186,
+230,176,145,231,148,168,229,147,129,228,184,156,232,165,191,230,143,144,229,135,
+186,233,133,146,229,186,151,231,132,182,229,144,142,228,187,152,230,172,190,231,
+131,173,231,130,185,228,187,165,229,137,141,229,174,140,229,133,168,229,143,145,
+229,184,150,232,174,190,231,189,174,233,162,134,229,175,188,229,183,165,228,184,
+154,229,140,187,233,153,162,231,156,139,231,156,139,231,187,143,229,133,184,229,
+142,159,229,155,160,229,185,179,229,143,176,229,144,132,231,167,141,229,162,158,
+229,138,160,230,157,144,230,150,153,230,150,176,229,162,158,228,185,139,229,144,
+142,232,129,140,228,184,154,230,149,136,230,158,156,228,187,138,229,185,180,232,
+174,186,230,150,135,230,136,145,229,155,189,229,145,138,232,175,137,231,137,136,
+228,184,187,228,191,174,230,148,185,229,143,130,228,184,142,230,137,147,229,141,
+176,229,191,171,228,185,144,230,156,186,230,162,176,232,167,130,231,130,185,229,
+173,152,229,156,168,231,178,190,231,165,158,232,142,183,229,190,151,229,136,169,
+231,148,168,231,187,167,231,187,173,228,189,160,228,187,172,232,191,153,228,185,
+136,230,168,161,229,188,143,232,175,173,232,168,128,232,131,189,229,164,159,233,
+155,133,232,153,142,230,147,141,228,189,156,233,163,142,230,160,188,228,184,128,
+232,181,183,231,167,145,229,173,166,228,189,147,232,130,178,231,159,173,228,191,
+161,230,157,161,228,187,182,230,178,187,231,150,151,232,191,144,229,138,168,228,
+186,167,228,184,154,228,188,154,232,174,174,229,175,188,232,136,170,229,133,136,
+231,148,159,232,129,148,231,155,159,229,143,175,230,152,175,229,149,143,233,161,
+140,231,187,147,230,158,132,228,189,156,231,148,168,232,176,131,230,159,165,232,
+179,135,230,150,153,232,135,170,229,138,168,232,180,159,232,180,163,229,134,156,
+228,184,154,232,174,191,233,151,174,229,174,158,230,150,189,230,142,165,229,143,
+151,232,174,168,232,174,186,233,130,163,228,184,170,229,143,141,233,166,136,229,
+138,160,229,188,186,229,165,179,230,128,167,232,140,131,229,155,180,230,156,141,
+229,139,153,228,188,145,233,151,178,228,187,138,230,151,165,229,174,162,230,156,
+141,232,167,128,231,156,139,229,143,130,229,138,160,231,154,132,232,175,157,228,
+184,128,231,130,185,228,191,157,232,175,129,229,155,190,228,185,166,230,156,137,
+230,149,136,230,181,139,232,175,149,231,167,187,229,138,168,230,137,141,232,131,
+189,229,134,179,229,174,154,232,130,161,231,165,168,228,184,141,230,150,173,233,
+156,128,230,177,130,228,184,141,229,190,151,229,138,158,230,179,149,228,185,139,
+233,151,180,233,135,135,231,148,168,232,144,165,233,148,128,230,138,149,232,175,
+137,231,155,174,230,160,135,231,136,177,230,131,133,230,145,132,229,189,177,230,
+156,137,228,186,155,232,164,135,232,163,189,230,150,135,229,173,166,230,156,186,
+228,188,154,230,149,176,229,173,151,232,163,133,228,191,174,232,180,173,231,137,
+169,229,134,156,230,157,145,229,133,168,233,157,162,231,178,190,229,147,129,229,
+133,182,229,174,158,228,186,139,230,131,133,230,176,180,229,185,179,230,143,144,
+231,164,186,228,184,138,229,184,130,232,176,162,232,176,162,230,153,174,233,128,
+154,230,149,153,229,184,136,228,184,138,228,188,160,231,177,187,229,136,171,230,
+173,140,230,155,178,230,139,165,230,156,137,229,136,155,230,150,176,233,133,141,
+228,187,182,229,143,170,232,166,129,230,151,182,228,187,163,232,179,135,232,168,
+138,232,190,190,229,136,176,228,186,186,231,148,159,232,174,162,233,152,133,232,
+128,129,229,184,136,229,177,149,231,164,186,229,191,131,231,144,134,232,180,180,
+229,173,144,231,182,178,231,171,153,228,184,187,233,161,140,232,135,170,231,132,
+182,231,186,167,229,136,171,231,174,128,229,141,149,230,148,185,233,157,169,233,
+130,163,228,186,155,230,157,165,232,175,180,230,137,147,229,188,128,228,187,163,
+231,160,129,229,136,160,233,153,164,232,175,129,229,136,184,232,138,130,231,155,
+174,233,135,141,231,130,185,230,172,161,230,149,184,229,164,154,229,176,145,232,
+167,132,229,136,146,232,181,132,233,135,145,230,137,190,229,136,176,228,187,165,
+229,144,142,229,164,167,229,133,168,228,184,187,233,161,181,230,156,128,228,189,
+179,229,155,158,231,173,148,229,164,169,228,184,139,228,191,157,233,154,156,231,
+142,176,228,187,163,230,163,128,230,159,165,230,138,149,231,165,168,229,176,143,
+230,151,182,230,178,146,230,156,137,230,173,163,229,184,184,231,148,154,232,135,
+179,228,187,163,231,144,134,231,155,174,229,189,149,229,133,172,229,188,128,229,
+164,141,229,136,182,233,135,145,232,158,141,229,185,184,231,166,143,231,137,136,
+230,156,172,229,189,162,230,136,144,229,135,134,229,164,135,232,161,140,230,131,
+133,229,155,158,229,136,176,230,128,157,230,131,179,230,128,142,230,160,183,229,
+141,143,232,174,174,232,174,164,232,175,129,230,156,128,229,165,189,228,186,167,
+231,148,159,230,140,137,231,133,167,230,156,141,232,163,133,229,185,191,228,184,
+156,229,138,168,230,188,171,233,135,135,232,180,173,230,150,176,230,137,139,231,
+187,132,229,155,190,233,157,162,230,157,191,229,143,130,232,128,131,230,148,191,
+230,178,187,229,174,185,230,152,147,229,164,169,229,156,176,229,138,170,229,138,
+155,228,186,186,228,187,172,229,141,135,231,186,167,233,128,159,229,186,166,228,
+186,186,231,137,169,232,176,131,230,149,180,230,181,129,232,161,140,233,128,160,
+230,136,144,230,150,135,229,173,151,233,159,169,229,155,189,232,180,184,230,152,
+147,229,188,128,229,177,149,231,155,184,233,151,156,232,161,168,231,142,176,229,
+189,177,232,167,134,229,166,130,230,173,164,231,190,142,229,174,185,229,164,167,
+229,176,143,230,138,165,233,129,147,230,157,161,230,172,190,229,191,131,230,131,
+133,232,174,184,229,164,154,230,179,149,232,167,132,229,174,182,229,177,133,228,
+185,166,229,186,151,232,191,158,230,142,165,231,171,139,229,141,179,228,184,190,
+230,138,165,230,138,128,229,183,167,229,165,165,232,191,144,231,153,187,229,133,
+165,228,187,165,230,157,165,231,144,134,232,174,186,228,186,139,228,187,182,232,
+135,170,231,148,177,228,184,173,229,141,142,229,138,158,229,133,172,229,166,136,
+229,166,136,231,156,159,230,173,163,228,184,141,233,148,153,229,133,168,230,150,
+135,229,144,136,229,144,140,228,187,183,229,128,188,229,136,171,228,186,186,231,
+155,145,231,157,163,229,133,183,228,189,147,228,184,150,231,186,170,229,155,162,
+233,152,159,229,136,155,228,184,154,230,137,191,230,139,133,229,162,158,233,149,
+191,230,156,137,228,186,186,228,191,157,230,140,129,229,149,134,229,174,182,231,
+187,180,228,191,174,229,143,176,230,185,190,229,183,166,229,143,179,232,130,161,
+228,187,189,231,173,148,230,161,136,229,174,158,233,153,133,231,148,181,228,191,
+161,231,187,143,231,144,134,231,148,159,229,145,189,229,174,163,228,188,160,228,
+187,187,229,138,161,230,173,163,229,188,143,231,137,185,232,137,178,228,184,139,
+230,157,165,229,141,143,228,188,154,229,143,170,232,131,189,229,189,147,231,132,
+182,233,135,141,230,150,176,229,133,167,229,174,185,230,140,135,229,175,188,232,
+191,144,232,161,140,230,151,165,229,191,151,232,179,163,229,174,182,232,182,133,
+232,191,135,229,156,159,229,156,176,230,181,153,230,177,159,230,148,175,228,187,
+152,230,142,168,229,135,186,231,171,153,233,149,191,230,157,173,229,183,158,230,
+137,167,232,161,140,229,136,182,233,128,160,228,185,139,228,184,128,230,142,168,
+229,185,191,231,142,176,229,156,186,230,143,143,232,191,176,229,143,152,229,140,
+150,228,188,160,231,187,159,230,173,140,230,137,139,228,191,157,233,153,169,232,
+175,190,231,168,139,229,140,187,231,150,151,231,187,143,232,191,135,232,191,135,
+229,142,187,228,185,139,229,137,141,230,148,182,229,133,165,229,185,180,229,186,
+166,230,157,130,229,191,151,231,190,142,228,184,189,230,156,128,233,171,152,231,
+153,187,233,153,134,230,156,170,230,157,165,229,138,160,229,183,165,229,133,141,
+232,180,163,230,149,153,231,168,139,231,137,136,229,157,151,232,186,171,228,189,
+147,233,135,141,229,186,134,229,135,186,229,148,174,230,136,144,230,156,172,229,
+189,162,229,188,143,229,156,159,232,177,134,229,135,186,229,131,185,228,184,156,
+230,150,185,233,130,174,231,174,177,229,141,151,228,186,172,230,177,130,232,129,
+140,229,143,150,229,190,151,232,129,140,228,189,141,231,155,184,228,191,161,233,
+161,181,233,157,162,229,136,134,233,146,159,231,189,145,233,161,181,231,161,174,
+229,174,154,229,155,190,228,190,139,231,189,145,229,157,128,231,167,175,230,158,
+129,233,148,153,232,175,175,231,155,174,231,154,132,229,174,157,232,180,157,230,
+156,186,229,133,179,233,163,142,233,153,169,230,142,136,230,157,131,231,151,133,
+230,175,146,229,174,160,231,137,169,233,153,164,228,186,134,232,169,149,232,171,
+150,231,150,190,231,151,133,229,143,138,230,151,182,230,177,130,232,180,173,231,
+171,153,231,130,185,229,132,191,231,171,165,230,175,143,229,164,169,228,184,173,
+229,164,174,232,174,164,232,175,134,230,175,143,228,184,170,229,164,169,230,180,
+165,229,173,151,228,189,147,229,143,176,231,129,163,231,187,180,230,138,164,230,
+156,172,233,161,181,228,184,170,230,128,167,229,174,152,230,150,185,229,184,184,
+232,167,129,231,155,184,230,156,186,230,136,152,231,149,165,229,186,148,229,189,
+147,229,190,139,229,184,136,230,150,185,228,190,191,230,160,161,229,155,173,232,
+130,161,229,184,130,230,136,191,229,177,139,230,160,143,231,155,174,229,145,152,
+229,183,165,229,175,188,232,135,180,231,170,129,231,132,182,233,129,147,229,133,
+183,230,156,172,231,189,145,231,187,147,229,144,136,230,161,163,230,161,136,229,
+138,179,229,138,168,229,143,166,229,164,150,231,190,142,229,133,131,229,188,149,
+232,181,183,230,148,185,229,143,152,231,172,172,229,155,155,228,188,154,232,174,
+161,232,170,170,230,152,142,233,154,144,231,167,129,229,174,157,229,174,157,232,
+167,132,232,140,131,230,182,136,232,180,185,229,133,177,229,144,140,229,191,152,
+232,174,176,228,189,147,231,179,187,229,184,166,230,157,165,229,144,141,229,173,
+151,231,153,188,232,161,168,229,188,128,230,148,190,229,138,160,231,155,159,229,
+143,151,229,136,176,228,186,140,230,137,139,229,164,167,233,135,143,230,136,144,
+228,186,186,230,149,176,233,135,143,229,133,177,228,186,171,229,140,186,229,159,
+159,229,165,179,229,173,169,229,142,159,229,136,153,230,137,128,229,156,168,231,
+187,147,230,157,159,233,128,154,228,191,161,232,182,133,231,186,167,233,133,141,
+231,189,174,229,189,147,230,151,182,228,188,152,231,167,128,230,128,167,230,132,
+159,230,136,191,228,186,167,233,129,138,230,136,178,229,135,186,229,143,163,230,
+143,144,228,186,164,229,176,177,228,184,154,228,191,157,229,129,165,231,168,139,
+229,186,166,229,143,130,230,149,176,228,186,139,228,184,154,230,149,180,228,184,
+170,229,177,177,228,184,156,230,131,133,230,132,159,231,137,185,230,174,138,229,
+136,134,233,161,158,230,144,156,229,176,139,229,177,158,228,186,142,233,151,168,
+230,136,183,232,180,162,229,138,161,229,163,176,233,159,179,229,143,138,229,133,
+182,232,180,162,231,187,143,229,157,154,230,140,129,229,185,178,233,131,168,230,
+136,144,231,171,139,229,136,169,231,155,138,232,128,131,232,153,145,230,136,144,
+233,131,189,229,140,133,232,163,133,231,148,168,230,136,182,230,175,148,232,181,
+155,230,150,135,230,152,142,230,139,155,229,149,134,229,174,140,230,149,180,231,
+156,159,230,152,175,231,156,188,231,157,155,228,188,153,228,188,180,229,168,129,
+230,156,155,233,162,134,229,159,159,229,141,171,231,148,159,228,188,152,230,131,
+160,232,171,150,229,163,135,229,133,172,229,133,177,232,137,175,229,165,189,229,
+133,133,229,136,134,231,172,166,229,144,136,233,153,132,228,187,182,231,137,185,
+231,130,185,228,184,141,229,143,175,232,139,177,230,150,135,232,181,132,228,186,
+167,230,160,185,230,156,172,230,152,142,230,152,190,229,175,134,231,162,188,229,
+133,172,228,188,151,230,176,145,230,151,143,230,155,180,229,138,160,228,186,171,
+229,143,151,229,144,140,229,173,166,229,144,175,229,138,168,233,128,130,229,144,
+136,229,142,159,230,157,165,233,151,174,231,173,148,230,156,172,230,150,135,231,
+190,142,233,163,159,231,187,191,232,137,178,231,168,179,229,174,154,231,187,136,
+228,186,142,231,148,159,231,137,169,228,190,155,230,177,130,230,144,156,231,139,
+144,229,138,155,233,135,143,228,184,165,233,135,141,230,176,184,232,191,156,229,
+134,153,231,156,159,230,156,137,233,153,144,231,171,158,228,186,137,229,175,185,
+232,177,161,232,180,185,231,148,168,228,184,141,229,165,189,231,187,157,229,175,
+185,229,141,129,229,136,134,228,191,131,232,191,155,231,130,185,232,175,132,229,
+189,177,233,159,179,228,188,152,229,138,191,228,184,141,229,176,145,230,172,163,
+232,181,143,229,185,182,228,184,148,230,156,137,231,130,185,230,150,185,229,144,
+145,229,133,168,230,150,176,228,191,161,231,148,168,232,174,190,230,150,189,229,
+189,162,232,177,161,232,181,132,230,160,188,231,170,129,231,160,180,233,154,143,
+231,157,128,233,135,141,229,164,167,228,186,142,230,152,175,230,175,149,228,184,
+154,230,153,186,232,131,189,229,140,150,229,183,165,229,174,140,231,190,142,229,
+149,134,229,159,142,231,187,159,228,184,128,229,135,186,231,137,136,230,137,147,
+233,128,160,231,148,162,229,147,129,230,166,130,229,134,181,231,148,168,228,186,
+142,228,191,157,231,149,153,229,155,160,231,180,160,228,184,173,229,156,139,229,
+173,152,229,130,168,232,180,180,229,155,190,230,156,128,230,132,155,233,149,191,
+230,156,159,229,143,163,228,187,183,231,144,134,232,180,162,229,159,186,229,156,
+176,229,174,137,230,142,146,230,173,166,230,177,137,233,135,140,233,157,162,229,
+136,155,229,187,186,229,164,169,231,169,186,233,166,150,229,133,136,229,174,140,
+229,150,132,233,169,177,229,138,168,228,184,139,233,157,162,228,184,141,229,134,
+141,232,175,154,228,191,161,230,132,143,228,185,137,233,152,179,229,133,137,232,
+139,177,229,155,189,230,188,130,228,186,174,229,134,155,228,186,139,231,142,169,
+229,174,182,231,190,164,228,188,151,229,134,156,230,176,145,229,141,179,229,143,
+175,229,144,141,231,168,177,229,174,182,229,133,183,229,138,168,231,148,187,230,
+131,179,229,136,176,230,179,168,230,152,142,229,176,143,229,173,166,230,128,167,
+232,131,189,232,128,131,231,160,148,231,161,172,228,187,182,232,167,130,231,156,
+139,230,184,133,230,165,154,230,144,158,231,172,145,233,166,150,233,160,129,233,
+187,132,233,135,145,233,128,130,231,148,168,230,177,159,232,139,143,231,156,159,
+229,174,158,228,184,187,231,174,161,233,152,182,230,174,181,232,168,187,229,134,
+138,231,191,187,232,175,145,230,157,131,229,136,169,229,129,154,229,165,189,228,
+188,188,228,185,142,233,128,154,232,174,175,230,150,189,229,183,165,231,139,128,
+230,133,139,228,185,159,232,174,184,231,142,175,228,191,157,229,159,185,229,133,
+187,230,166,130,229,191,181,229,164,167,229,158,139,230,156,186,231,165,168,231,
+144,134,232,167,163,229,140,191,229,144,141,99,117,97,110,100,111,101,110,118,
+105,97,114,109,97,100,114,105,100,98,117,115,99,97,114,105,110,105,99,105,111,
+116,105,101,109,112,111,112,111,114,113,117,101,99,117,101,110,116,97,101,115,
+116,97,100,111,112,117,101,100,101,110,106,117,101,103,111,115,99,111,110,116,
+114,97,101,115,116,195,161,110,110,111,109,98,114,101,116,105,101,110,101,110,
+112,101,114,102,105,108,109,97,110,101,114,97,97,109,105,103,111,115,99,105,117,
+100,97,100,99,101,110,116,114,111,97,117,110,113,117,101,112,117,101,100,101,115
+,100,101,110,116,114,111,112,114,105,109,101,114,112,114,101,99,105,111,115,101,
+103,195,186,110,98,117,101,110,111,115,118,111,108,118,101,114,112,117,110,116,
+111,115,115,101,109,97,110,97,104,97,98,195,173,97,97,103,111,115,116,111,110,
+117,101,118,111,115,117,110,105,100,111,115,99,97,114,108,111,115,101,113,117,
+105,112,111,110,105,195,177,111,115,109,117,99,104,111,115,97,108,103,117,110,97
+,99,111,114,114,101,111,105,109,97,103,101,110,112,97,114,116,105,114,97,114,114
+,105,98,97,109,97,114,195,173,97,104,111,109,98,114,101,101,109,112,108,101,111,
+118,101,114,100,97,100,99,97,109,98,105,111,109,117,99,104,97,115,102,117,101,
+114,111,110,112,97,115,97,100,111,108,195,173,110,101,97,112,97,114,101,99,101,
+110,117,101,118,97,115,99,117,114,115,111,115,101,115,116,97,98,97,113,117,105,
+101,114,111,108,105,98,114,111,115,99,117,97,110,116,111,97,99,99,101,115,111,
+109,105,103,117,101,108,118,97,114,105,111,115,99,117,97,116,114,111,116,105,101
+,110,101,115,103,114,117,112,111,115,115,101,114,195,161,110,101,117,114,111,112
+,97,109,101,100,105,111,115,102,114,101,110,116,101,97,99,101,114,99,97,100,101,
+109,195,161,115,111,102,101,114,116,97,99,111,99,104,101,115,109,111,100,101,108
+,111,105,116,97,108,105,97,108,101,116,114,97,115,97,108,103,195,186,110,99,111,
+109,112,114,97,99,117,97,108,101,115,101,120,105,115,116,101,99,117,101,114,112,
+111,115,105,101,110,100,111,112,114,101,110,115,97,108,108,101,103,97,114,118,
+105,97,106,101,115,100,105,110,101,114,111,109,117,114,99,105,97,112,111,100,114
+,195,161,112,117,101,115,116,111,100,105,97,114,105,111,112,117,101,98,108,111,
+113,117,105,101,114,101,109,97,110,117,101,108,112,114,111,112,105,111,99,114,
+105,115,105,115,99,105,101,114,116,111,115,101,103,117,114,111,109,117,101,114,
+116,101,102,117,101,110,116,101,99,101,114,114,97,114,103,114,97,110,100,101,101
+,102,101,99,116,111,112,97,114,116,101,115,109,101,100,105,100,97,112,114,111,
+112,105,97,111,102,114,101,99,101,116,105,101,114,114,97,101,45,109,97,105,108,
+118,97,114,105,97,115,102,111,114,109,97,115,102,117,116,117,114,111,111,98,106,
+101,116,111,115,101,103,117,105,114,114,105,101,115,103,111,110,111,114,109,97,
+115,109,105,115,109,111,115,195,186,110,105,99,111,99,97,109,105,110,111,115,105
+,116,105,111,115,114,97,122,195,179,110,100,101,98,105,100,111,112,114,117,101,
+98,97,116,111,108,101,100,111,116,101,110,195,173,97,106,101,115,195,186,115,101
+,115,112,101,114,111,99,111,99,105,110,97,111,114,105,103,101,110,116,105,101,
+110,100,97,99,105,101,110,116,111,99,195,161,100,105,122,104,97,98,108,97,114,
+115,101,114,195,173,97,108,97,116,105,110,97,102,117,101,114,122,97,101,115,116,
+105,108,111,103,117,101,114,114,97,101,110,116,114,97,114,195,169,120,105,116,
+111,108,195,179,112,101,122,97,103,101,110,100,97,118,195,173,100,101,111,101,
+118,105,116,97,114,112,97,103,105,110,97,109,101,116,114,111,115,106,97,118,105,
+101,114,112,97,100,114,101,115,102,195,161,99,105,108,99,97,98,101,122,97,195,
+161,114,101,97,115,115,97,108,105,100,97,101,110,118,195,173,111,106,97,112,195,
+179,110,97,98,117,115,111,115,98,105,101,110,101,115,116,101,120,116,111,115,108
+,108,101,118,97,114,112,117,101,100,97,110,102,117,101,114,116,101,99,111,109,
+195,186,110,99,108,97,115,101,115,104,117,109,97,110,111,116,101,110,105,100,111
+,98,105,108,98,97,111,117,110,105,100,97,100,101,115,116,195,161,115,101,100,105
+,116,97,114,99,114,101,97,100,111,208,180,208,187,209,143,209,135,209,130,208,
+190,208,186,208,176,208,186,208,184,208,187,208,184,209,141,209,130,208,190,208,
+178,209,129,208,181,208,181,208,179,208,190,208,191,209,128,208,184,209,130,208,
+176,208,186,208,181,209,137,208,181,209,131,208,182,208,181,208,154,208,176,208,
+186,208,177,208,181,208,183,208,177,209,139,208,187,208,190,208,189,208,184,208,
+146,209,129,208,181,208,191,208,190,208,180,208,173,209,130,208,190,209,130,208,
+190,208,188,209,135,208,181,208,188,208,189,208,181,209,130,208,187,208,181,209,
+130,209,128,208,176,208,183,208,190,208,189,208,176,208,179,208,180,208,181,208,
+188,208,189,208,181,208,148,208,187,209,143,208,159,209,128,208,184,208,189,208,
+176,209,129,208,189,208,184,209,133,209,130,208,181,208,188,208,186,209,130,208,
+190,208,179,208,190,208,180,208,178,208,190,209,130,209,130,208,176,208,188,208,
+161,208,168,208,144,208,188,208,176,209,143,208,167,209,130,208,190,208,178,208,
+176,209,129,208,178,208,176,208,188,208,181,208,188,209,131,208,162,208,176,208,
+186,208,180,208,178,208,176,208,189,208,176,208,188,209,141,209,130,208,184,209,
+141,209,130,209,131,208,146,208,176,208,188,209,130,208,181,209,133,208,191,209,
+128,208,190,209,130,209,131,209,130,208,189,208,176,208,180,208,180,208,189,209,
+143,208,146,208,190,209,130,209,130,209,128,208,184,208,189,208,181,208,185,208,
+146,208,176,209,129,208,189,208,184,208,188,209,129,208,176,208,188,209,130,208,
+190,209,130,209,128,209,131,208,177,208,158,208,189,208,184,208,188,208,184,209,
+128,208,189,208,181,208,181,208,158,208,158,208,158,208,187,208,184,209,134,209,
+141,209,130,208,176,208,158,208,189,208,176,208,189,208,181,208,188,208,180,208,
+190,208,188,208,188,208,190,208,185,208,180,208,178,208,181,208,190,208,189,208,
+190,209,129,209,131,208,180,224,164,149,224,165,135,224,164,185,224,165,136,224,
+164,149,224,165,128,224,164,184,224,165,135,224,164,149,224,164,190,224,164,149,
+224,165,139,224,164,148,224,164,176,224,164,170,224,164,176,224,164,168,224,165,
+135,224,164,143,224,164,149,224,164,149,224,164,191,224,164,173,224,165,128,224,
+164,135,224,164,184,224,164,149,224,164,176,224,164,164,224,165,139,224,164,185,
+224,165,139,224,164,134,224,164,170,224,164,185,224,165,128,224,164,175,224,164,
+185,224,164,175,224,164,190,224,164,164,224,164,149,224,164,165,224,164,190,106,
+97,103,114,97,110,224,164,134,224,164,156,224,164,156,224,165,139,224,164,133,
+224,164,172,224,164,166,224,165,139,224,164,151,224,164,136,224,164,156,224,164,
+190,224,164,151,224,164,143,224,164,185,224,164,174,224,164,135,224,164,168,224,
+164,181,224,164,185,224,164,175,224,165,135,224,164,165,224,165,135,224,164,165,
+224,165,128,224,164,152,224,164,176,224,164,156,224,164,172,224,164,166,224,165,
+128,224,164,149,224,164,136,224,164,156,224,165,128,224,164,181,224,165,135,224,
+164,168,224,164,136,224,164,168,224,164,143,224,164,185,224,164,176,224,164,137,
+224,164,184,224,164,174,224,165,135,224,164,149,224,164,174,224,164,181,224,165,
+139,224,164,178,224,165,135,224,164,184,224,164,172,224,164,174,224,164,136,224,
+164,166,224,165,135,224,164,147,224,164,176,224,164,134,224,164,174,224,164,172,
+224,164,184,224,164,173,224,164,176,224,164,172,224,164,168,224,164,154,224,164,
+178,224,164,174,224,164,168,224,164,134,224,164,151,224,164,184,224,165,128,224,
+164,178,224,165,128,216,185,217,132,217,137,216,165,217,132,217,137,217,135,216,
+176,216,167,216,162,216,174,216,177,216,185,216,175,216,175,216,167,217,132,217,
+137,217,135,216,176,217,135,216,181,217,136,216,177,216,186,217,138,216,177,217,
+131,216,167,217,134,217,136,217,132,216,167,216,168,217,138,217,134,216,185,216,
+177,216,182,216,176,217,132,217,131,217,135,217,134,216,167,217,138,217,136,217,
+133,217,130,216,167,217,132,216,185,217,132,217,138,216,167,217,134,216,167,217,
+132,217,131,217,134,216,173,216,170,217,137,217,130,216,168,217,132,217,136,216,
+173,216,169,216,167,216,174,216,177,217,129,217,130,216,183,216,185,216,168,216,
+175,216,177,217,131,217,134,216,165,216,176,216,167,217,131,217,133,216,167,216,
+167,216,173,216,175,216,165,217,132,216,167,217,129,217,138,217,135,216,168,216,
+185,216,182,217,131,217,138,217,129,216,168,216,173,216,171,217,136,217,133,217,
+134,217,136,217,135,217,136,216,163,217,134,216,167,216,172,216,175,216,167,217,
+132,217,135,216,167,216,179,217,132,217,133,216,185,217,134,216,175,217,132,217,
+138,216,179,216,185,216,168,216,177,216,181,217,132,217,137,217,133,217,134,216,
+176,216,168,217,135,216,167,216,163,217,134,217,135,217,133,216,171,217,132,217,
+131,217,134,216,170,216,167,217,132,216,167,216,173,217,138,216,171,217,133,216,
+181,216,177,216,180,216,177,216,173,216,173,217,136,217,132,217,136,217,129,217,
+138,216,167,216,176,216,167,217,132,217,131,217,132,217,133,216,177,216,169,216,
+167,217,134,216,170,216,167,217,132,217,129,216,163,216,168,217,136,216,174,216,
+167,216,181,216,163,217,134,216,170,216,167,217,134,217,135,216,167,217,132,217,
+138,216,185,216,182,217,136,217,136,217,130,216,175,216,167,216,168,217,134,216,
+174,217,138,216,177,216,168,217,134,216,170,217,132,217,131,217,133,216,180,216,
+167,216,161,217,136,217,135,217,138,216,167,216,168,217,136,217,130,216,181,216,
+181,217,136,217,133,216,167,216,177,217,130,217,133,216,163,216,173,216,175,217,
+134,216,173,217,134,216,185,216,175,217,133,216,177,216,163,217,138,216,167,216,
+173,216,169,217,131,216,170,216,168,216,175,217,136,217,134,217,138,216,172,216,
+168,217,133,217,134,217,135,216,170,216,173,216,170,216,172,217,135,216,169,216,
+179,217,134,216,169,217,138,216,170,217,133,217,131,216,177,216,169,216,186,216,
+178,216,169,217,134,217,129,216,179,216,168,217,138,216,170,217,132,217,132,217,
+135,217,132,217,134,216,167,216,170,217,132,217,131,217,130,217,132,216,168,217,
+132,217,133,216,167,216,185,217,134,217,135,216,163,217,136,217,132,216,180,217,
+138,216,161,217,134,217,136,216,177,216,163,217,133,216,167,217,129,217,138,217,
+131,216,168,217,131,217,132,216,176,216,167,216,170,216,177,216,170,216,168,216,
+168,216,163,217,134,217,135,217,133,216,179,216,167,217,134,217,131,216,168,217,
+138,216,185,217,129,217,130,216,175,216,173,216,179,217,134,217,132,217,135,217,
+133,216,180,216,185,216,177,216,163,217,135,217,132,216,180,217,135,216,177,217,
+130,216,183,216,177,216,183,217,132,216,168,112,114,111,102,105,108,101,115,101,
+114,118,105,99,101,100,101,102,97,117,108,116,104,105,109,115,101,108,102,100,
+101,116,97,105,108,115,99,111,110,116,101,110,116,115,117,112,112,111,114,116,
+115,116,97,114,116,101,100,109,101,115,115,97,103,101,115,117,99,99,101,115,115,
+102,97,115,104,105,111,110,60,116,105,116,108,101,62,99,111,117,110,116,114,121,
+97,99,99,111,117,110,116,99,114,101,97,116,101,100,115,116,111,114,105,101,115,
+114,101,115,117,108,116,115,114,117,110,110,105,110,103,112,114,111,99,101,115,
+115,119,114,105,116,105,110,103,111,98,106,101,99,116,115,118,105,115,105,98,108
+,101,119,101,108,99,111,109,101,97,114,116,105,99,108,101,117,110,107,110,111,
+119,110,110,101,116,119,111,114,107,99,111,109,112,97,110,121,100,121,110,97,109
+,105,99,98,114,111,119,115,101,114,112,114,105,118,97,99,121,112,114,111,98,108,
+101,109,83,101,114,118,105,99,101,114,101,115,112,101,99,116,100,105,115,112,108
+,97,121,114,101,113,117,101,115,116,114,101,115,101,114,118,101,119,101,98,115,
+105,116,101,104,105,115,116,111,114,121,102,114,105,101,110,100,115,111,112,116,
+105,111,110,115,119,111,114,107,105,110,103,118,101,114,115,105,111,110,109,105,
+108,108,105,111,110,99,104,97,110,110,101,108,119,105,110,100,111,119,46,97,100,
+100,114,101,115,115,118,105,115,105,116,101,100,119,101,97,116,104,101,114,99,
+111,114,114,101,99,116,112,114,111,100,117,99,116,101,100,105,114,101,99,116,102
+,111,114,119,97,114,100,121,111,117,32,99,97,110,114,101,109,111,118,101,100,115
+,117,98,106,101,99,116,99,111,110,116,114,111,108,97,114,99,104,105,118,101,99,
+117,114,114,101,110,116,114,101,97,100,105,110,103,108,105,98,114,97,114,121,108
+,105,109,105,116,101,100,109,97,110,97,103,101,114,102,117,114,116,104,101,114,
+115,117,109,109,97,114,121,109,97,99,104,105,110,101,109,105,110,117,116,101,115
+,112,114,105,118,97,116,101,99,111,110,116,101,120,116,112,114,111,103,114,97,
+109,115,111,99,105,101,116,121,110,117,109,98,101,114,115,119,114,105,116,116,
+101,110,101,110,97,98,108,101,100,116,114,105,103,103,101,114,115,111,117,114,99
+,101,115,108,111,97,100,105,110,103,101,108,101,109,101,110,116,112,97,114,116,
+110,101,114,102,105,110,97,108,108,121,112,101,114,102,101,99,116,109,101,97,110
+,105,110,103,115,121,115,116,101,109,115,107,101,101,112,105,110,103,99,117,108,
+116,117,114,101,38,113,117,111,116,59,44,106,111,117,114,110,97,108,112,114,111,
+106,101,99,116,115,117,114,102,97,99,101,115,38,113,117,111,116,59,101,120,112,
+105,114,101,115,114,101,118,105,101,119,115,98,97,108,97,110,99,101,69,110,103,
+108,105,115,104,67,111,110,116,101,110,116,116,104,114,111,117,103,104,80,108,
+101,97,115,101,32,111,112,105,110,105,111,110,99,111,110,116,97,99,116,97,118,
+101,114,97,103,101,112,114,105,109,97,114,121,118,105,108,108,97,103,101,83,112,
+97,110,105,115,104,103,97,108,108,101,114,121,100,101,99,108,105,110,101,109,101
+,101,116,105,110,103,109,105,115,115,105,111,110,112,111,112,117,108,97,114,113,
+117,97,108,105,116,121,109,101,97,115,117,114,101,103,101,110,101,114,97,108,115
+,112,101,99,105,101,115,115,101,115,115,105,111,110,115,101,99,116,105,111,110,
+119,114,105,116,101,114,115,99,111,117,110,116,101,114,105,110,105,116,105,97,
+108,114,101,112,111,114,116,115,102,105,103,117,114,101,115,109,101,109,98,101,
+114,115,104,111,108,100,105,110,103,100,105,115,112,117,116,101,101,97,114,108,
+105,101,114,101,120,112,114,101,115,115,100,105,103,105,116,97,108,112,105,99,
+116,117,114,101,65,110,111,116,104,101,114,109,97,114,114,105,101,100,116,114,97
+,102,102,105,99,108,101,97,100,105,110,103,99,104,97,110,103,101,100,99,101,110,
+116,114,97,108,118,105,99,116,111,114,121,105,109,97,103,101,115,47,114,101,97,
+115,111,110,115,115,116,117,100,105,101,115,102,101,97,116,117,114,101,108,105,
+115,116,105,110,103,109,117,115,116,32,98,101,115,99,104,111,111,108,115,86,101,
+114,115,105,111,110,117,115,117,97,108,108,121,101,112,105,115,111,100,101,112,
+108,97,121,105,110,103,103,114,111,119,105,110,103,111,98,118,105,111,117,115,
+111,118,101,114,108,97,121,112,114,101,115,101,110,116,97,99,116,105,111,110,115
+,60,47,117,108,62,13,10,119,114,97,112,112,101,114,97,108,114,101,97,100,121,99,
+101,114,116,97,105,110,114,101,97,108,105,116,121,115,116,111,114,97,103,101,97,
+110,111,116,104,101,114,100,101,115,107,116,111,112,111,102,102,101,114,101,100,
+112,97,116,116,101,114,110,117,110,117,115,117,97,108,68,105,103,105,116,97,108,
+99,97,112,105,116,97,108,87,101,98,115,105,116,101,102,97,105,108,117,114,101,99
+,111,110,110,101,99,116,114,101,100,117,99,101,100,65,110,100,114,111,105,100,
+100,101,99,97,100,101,115,114,101,103,117,108,97,114,32,38,97,109,112,59,32,97,
+110,105,109,97,108,115,114,101,108,101,97,115,101,65,117,116,111,109,97,116,103,
+101,116,116,105,110,103,109,101,116,104,111,100,115,110,111,116,104,105,110,103,
+80,111,112,117,108,97,114,99,97,112,116,105,111,110,108,101,116,116,101,114,115,
+99,97,112,116,117,114,101,115,99,105,101,110,99,101,108,105,99,101,110,115,101,
+99,104,97,110,103,101,115,69,110,103,108,97,110,100,61,49,38,97,109,112,59,72,
+105,115,116,111,114,121,32,61,32,110,101,119,32,67,101,110,116,114,97,108,117,
+112,100,97,116,101,100,83,112,101,99,105,97,108,78,101,116,119,111,114,107,114,
+101,113,117,105,114,101,99,111,109,109,101,110,116,119,97,114,110,105,110,103,67
+,111,108,108,101,103,101,116,111,111,108,98,97,114,114,101,109,97,105,110,115,98
+,101,99,97,117,115,101,101,108,101,99,116,101,100,68,101,117,116,115,99,104,102,
+105,110,97,110,99,101,119,111,114,107,101,114,115,113,117,105,99,107,108,121,98,
+101,116,119,101,101,110,101,120,97,99,116,108,121,115,101,116,116,105,110,103,
+100,105,115,101,97,115,101,83,111,99,105,101,116,121,119,101,97,112,111,110,115,
+101,120,104,105,98,105,116,38,108,116,59,33,45,45,67,111,110,116,114,111,108,99,
+108,97,115,115,101,115,99,111,118,101,114,101,100,111,117,116,108,105,110,101,97
+,116,116,97,99,107,115,100,101,118,105,99,101,115,40,119,105,110,100,111,119,112
+,117,114,112,111,115,101,116,105,116,108,101,61,34,77,111,98,105,108,101,32,107,
+105,108,108,105,110,103,115,104,111,119,105,110,103,73,116,97,108,105,97,110,100
+,114,111,112,112,101,100,104,101,97,118,105,108,121,101,102,102,101,99,116,115,
+45,49,39,93,41,59,10,99,111,110,102,105,114,109,67,117,114,114,101,110,116,97,
+100,118,97,110,99,101,115,104,97,114,105,110,103,111,112,101,110,105,110,103,100
+,114,97,119,105,110,103,98,105,108,108,105,111,110,111,114,100,101,114,101,100,
+71,101,114,109,97,110,121,114,101,108,97,116,101,100,60,47,102,111,114,109,62,
+105,110,99,108,117,100,101,119,104,101,116,104,101,114,100,101,102,105,110,101,
+100,83,99,105,101,110,99,101,99,97,116,97,108,111,103,65,114,116,105,99,108,101,
+98,117,116,116,111,110,115,108,97,114,103,101,115,116,117,110,105,102,111,114,
+109,106,111,117,114,110,101,121,115,105,100,101,98,97,114,67,104,105,99,97,103,
+111,104,111,108,105,100,97,121,71,101,110,101,114,97,108,112,97,115,115,97,103,
+101,44,38,113,117,111,116,59,97,110,105,109,97,116,101,102,101,101,108,105,110,
+103,97,114,114,105,118,101,100,112,97,115,115,105,110,103,110,97,116,117,114,97,
+108,114,111,117,103,104,108,121,46,10,10,84,104,101,32,98,117,116,32,110,111,116
+,100,101,110,115,105,116,121,66,114,105,116,97,105,110,67,104,105,110,101,115,
+101,108,97,99,107,32,111,102,116,114,105,98,117,116,101,73,114,101,108,97,110,
+100,34,32,100,97,116,97,45,102,97,99,116,111,114,115,114,101,99,101,105,118,101,
+116,104,97,116,32,105,115,76,105,98,114,97,114,121,104,117,115,98,97,110,100,105
+,110,32,102,97,99,116,97,102,102,97,105,114,115,67,104,97,114,108,101,115,114,97
+,100,105,99,97,108,98,114,111,117,103,104,116,102,105,110,100,105,110,103,108,97
+,110,100,105,110,103,58,108,97,110,103,61,34,114,101,116,117,114,110,32,108,101,
+97,100,101,114,115,112,108,97,110,110,101,100,112,114,101,109,105,117,109,112,97
+,99,107,97,103,101,65,109,101,114,105,99,97,69,100,105,116,105,111,110,93,38,113
+,117,111,116,59,77,101,115,115,97,103,101,110,101,101,100,32,116,111,118,97,108,
+117,101,61,34,99,111,109,112,108,101,120,108,111,111,107,105,110,103,115,116,97,
+116,105,111,110,98,101,108,105,101,118,101,115,109,97,108,108,101,114,45,109,111
+,98,105,108,101,114,101,99,111,114,100,115,119,97,110,116,32,116,111,107,105,110
+,100,32,111,102,70,105,114,101,102,111,120,121,111,117,32,97,114,101,115,105,109
+,105,108,97,114,115,116,117,100,105,101,100,109,97,120,105,109,117,109,104,101,
+97,100,105,110,103,114,97,112,105,100,108,121,99,108,105,109,97,116,101,107,105,
+110,103,100,111,109,101,109,101,114,103,101,100,97,109,111,117,110,116,115,102,
+111,117,110,100,101,100,112,105,111,110,101,101,114,102,111,114,109,117,108,97,
+100,121,110,97,115,116,121,104,111,119,32,116,111,32,83,117,112,112,111,114,116,
+114,101,118,101,110,117,101,101,99,111,110,111,109,121,82,101,115,117,108,116,
+115,98,114,111,116,104,101,114,115,111,108,100,105,101,114,108,97,114,103,101,
+108,121,99,97,108,108,105,110,103,46,38,113,117,111,116,59,65,99,99,111,117,110,
+116,69,100,119,97,114,100,32,115,101,103,109,101,110,116,82,111,98,101,114,116,
+32,101,102,102,111,114,116,115,80,97,99,105,102,105,99,108,101,97,114,110,101,
+100,117,112,32,119,105,116,104,104,101,105,103,104,116,58,119,101,32,104,97,118,
+101,65,110,103,101,108,101,115,110,97,116,105,111,110,115,95,115,101,97,114,99,
+104,97,112,112,108,105,101,100,97,99,113,117,105,114,101,109,97,115,115,105,118,
+101,103,114,97,110,116,101,100,58,32,102,97,108,115,101,116,114,101,97,116,101,
+100,98,105,103,103,101,115,116,98,101,110,101,102,105,116,100,114,105,118,105,
+110,103,83,116,117,100,105,101,115,109,105,110,105,109,117,109,112,101,114,104,
+97,112,115,109,111,114,110,105,110,103,115,101,108,108,105,110,103,105,115,32,
+117,115,101,100,114,101,118,101,114,115,101,118,97,114,105,97,110,116,32,114,111
+,108,101,61,34,109,105,115,115,105,110,103,97,99,104,105,101,118,101,112,114,111
+,109,111,116,101,115,116,117,100,101,110,116,115,111,109,101,111,110,101,101,120
+,116,114,101,109,101,114,101,115,116,111,114,101,98,111,116,116,111,109,58,101,
+118,111,108,118,101,100,97,108,108,32,116,104,101,115,105,116,101,109,97,112,101
+,110,103,108,105,115,104,119,97,121,32,116,111,32,32,65,117,103,117,115,116,115,
+121,109,98,111,108,115,67,111,109,112,97,110,121,109,97,116,116,101,114,115,109,
+117,115,105,99,97,108,97,103,97,105,110,115,116,115,101,114,118,105,110,103,125,
+41,40,41,59,13,10,112,97,121,109,101,110,116,116,114,111,117,98,108,101,99,111,
+110,99,101,112,116,99,111,109,112,97,114,101,112,97,114,101,110,116,115,112,108,
+97,121,101,114,115,114,101,103,105,111,110,115,109,111,110,105,116,111,114,32,39
+,39,84,104,101,32,119,105,110,110,105,110,103,101,120,112,108,111,114,101,97,100
+,97,112,116,101,100,71,97,108,108,101,114,121,112,114,111,100,117,99,101,97,98,
+105,108,105,116,121,101,110,104,97,110,99,101,99,97,114,101,101,114,115,41,46,32
+,84,104,101,32,99,111,108,108,101,99,116,83,101,97,114,99,104,32,97,110,99,105,
+101,110,116,101,120,105,115,116,101,100,102,111,111,116,101,114,32,104,97,110,
+100,108,101,114,112,114,105,110,116,101,100,99,111,110,115,111,108,101,69,97,115
+,116,101,114,110,101,120,112,111,114,116,115,119,105,110,100,111,119,115,67,104,
+97,110,110,101,108,105,108,108,101,103,97,108,110,101,117,116,114,97,108,115,117
+,103,103,101,115,116,95,104,101,97,100,101,114,115,105,103,110,105,110,103,46,
+104,116,109,108,34,62,115,101,116,116,108,101,100,119,101,115,116,101,114,110,99
+,97,117,115,105,110,103,45,119,101,98,107,105,116,99,108,97,105,109,101,100,74,
+117,115,116,105,99,101,99,104,97,112,116,101,114,118,105,99,116,105,109,115,84,
+104,111,109,97,115,32,109,111,122,105,108,108,97,112,114,111,109,105,115,101,112
+,97,114,116,105,101,115,101,100,105,116,105,111,110,111,117,116,115,105,100,101,
+58,102,97,108,115,101,44,104,117,110,100,114,101,100,79,108,121,109,112,105,99,
+95,98,117,116,116,111,110,97,117,116,104,111,114,115,114,101,97,99,104,101,100,
+99,104,114,111,110,105,99,100,101,109,97,110,100,115,115,101,99,111,110,100,115,
+112,114,111,116,101,99,116,97,100,111,112,116,101,100,112,114,101,112,97,114,101
+,110,101,105,116,104,101,114,103,114,101,97,116,108,121,103,114,101,97,116,101,
+114,111,118,101,114,97,108,108,105,109,112,114,111,118,101,99,111,109,109,97,110
+,100,115,112,101,99,105,97,108,115,101,97,114,99,104,46,119,111,114,115,104,105,
+112,102,117,110,100,105,110,103,116,104,111,117,103,104,116,104,105,103,104,101,
+115,116,105,110,115,116,101,97,100,117,116,105,108,105,116,121,113,117,97,114,
+116,101,114,67,117,108,116,117,114,101,116,101,115,116,105,110,103,99,108,101,97
+,114,108,121,101,120,112,111,115,101,100,66,114,111,119,115,101,114,108,105,98,
+101,114,97,108,125,32,99,97,116,99,104,80,114,111,106,101,99,116,101,120,97,109,
+112,108,101,104,105,100,101,40,41,59,70,108,111,114,105,100,97,97,110,115,119,
+101,114,115,97,108,108,111,119,101,100,69,109,112,101,114,111,114,100,101,102,
+101,110,115,101,115,101,114,105,111,117,115,102,114,101,101,100,111,109,83,101,
+118,101,114,97,108,45,98,117,116,116,111,110,70,117,114,116,104,101,114,111,117,
+116,32,111,102,32,33,61,32,110,117,108,108,116,114,97,105,110,101,100,68,101,110
+,109,97,114,107,118,111,105,100,40,48,41,47,97,108,108,46,106,115,112,114,101,
+118,101,110,116,82,101,113,117,101,115,116,83,116,101,112,104,101,110,10,10,87,
+104,101,110,32,111,98,115,101,114,118,101,60,47,104,50,62,13,10,77,111,100,101,
+114,110,32,112,114,111,118,105,100,101,34,32,97,108,116,61,34,98,111,114,100,101
+,114,115,46,10,10,70,111,114,32,10,10,77,97,110,121,32,97,114,116,105,115,116,
+115,112,111,119,101,114,101,100,112,101,114,102,111,114,109,102,105,99,116,105,
+111,110,116,121,112,101,32,111,102,109,101,100,105,99,97,108,116,105,99,107,101,
+116,115,111,112,112,111,115,101,100,67,111,117,110,99,105,108,119,105,116,110,
+101,115,115,106,117,115,116,105,99,101,71,101,111,114,103,101,32,66,101,108,103,
+105,117,109,46,46,46,60,47,97,62,116,119,105,116,116,101,114,110,111,116,97,98,
+108,121,119,97,105,116,105,110,103,119,97,114,102,97,114,101,32,79,116,104,101,
+114,32,114,97,110,107,105,110,103,112,104,114,97,115,101,115,109,101,110,116,105
+,111,110,115,117,114,118,105,118,101,115,99,104,111,108,97,114,60,47,112,62,13,
+10,32,67,111,117,110,116,114,121,105,103,110,111,114,101,100,108,111,115,115,32,
+111,102,106,117,115,116,32,97,115,71,101,111,114,103,105,97,115,116,114,97,110,
+103,101,60,104,101,97,100,62,60,115,116,111,112,112,101,100,49,39,93,41,59,13,10
+,105,115,108,97,110,100,115,110,111,116,97,98,108,101,98,111,114,100,101,114,58,
+108,105,115,116,32,111,102,99,97,114,114,105,101,100,49,48,48,44,48,48,48,60,47,
+104,51,62,10,32,115,101,118,101,114,97,108,98,101,99,111,109,101,115,115,101,108
+,101,99,116,32,119,101,100,100,105,110,103,48,48,46,104,116,109,108,109,111,110,
+97,114,99,104,111,102,102,32,116,104,101,116,101,97,99,104,101,114,104,105,103,
+104,108,121,32,98,105,111,108,111,103,121,108,105,102,101,32,111,102,111,114,32,
+101,118,101,110,114,105,115,101,32,111,102,38,114,97,113,117,111,59,112,108,117,
+115,111,110,101,104,117,110,116,105,110,103,40,116,104,111,117,103,104,68,111,
+117,103,108,97,115,106,111,105,110,105,110,103,99,105,114,99,108,101,115,70,111,
+114,32,116,104,101,65,110,99,105,101,110,116,86,105,101,116,110,97,109,118,101,
+104,105,99,108,101,115,117,99,104,32,97,115,99,114,121,115,116,97,108,118,97,108
+,117,101,32,61,87,105,110,100,111,119,115,101,110,106,111,121,101,100,97,32,115,
+109,97,108,108,97,115,115,117,109,101,100,60,97,32,105,100,61,34,102,111,114,101
+,105,103,110,32,65,108,108,32,114,105,104,111,119,32,116,104,101,68,105,115,112,
+108,97,121,114,101,116,105,114,101,100,104,111,119,101,118,101,114,104,105,100,
+100,101,110,59,98,97,116,116,108,101,115,115,101,101,107,105,110,103,99,97,98,
+105,110,101,116,119,97,115,32,110,111,116,108,111,111,107,32,97,116,99,111,110,
+100,117,99,116,103,101,116,32,116,104,101,74,97,110,117,97,114,121,104,97,112,
+112,101,110,115,116,117,114,110,105,110,103,97,58,104,111,118,101,114,79,110,108
+,105,110,101,32,70,114,101,110,99,104,32,108,97,99,107,105,110,103,116,121,112,
+105,99,97,108,101,120,116,114,97,99,116,101,110,101,109,105,101,115,101,118,101,
+110,32,105,102,103,101,110,101,114,97,116,100,101,99,105,100,101,100,97,114,101,
+32,110,111,116,47,115,101,97,114,99,104,98,101,108,105,101,102,115,45,105,109,97
+,103,101,58,108,111,99,97,116,101,100,115,116,97,116,105,99,46,108,111,103,105,
+110,34,62,99,111,110,118,101,114,116,118,105,111,108,101,110,116,101,110,116,101
+,114,101,100,102,105,114,115,116,34,62,99,105,114,99,117,105,116,70,105,110,108,
+97,110,100,99,104,101,109,105,115,116,115,104,101,32,119,97,115,49,48,112,120,59
+,34,62,97,115,32,115,117,99,104,100,105,118,105,100,101,100,60,47,115,112,97,110
+,62,119,105,108,108,32,98,101,108,105,110,101,32,111,102,97,32,103,114,101,97,
+116,109,121,115,116,101,114,121,47,105,110,100,101,120,46,102,97,108,108,105,110
+,103,100,117,101,32,116,111,32,114,97,105,108,119,97,121,99,111,108,108,101,103,
+101,109,111,110,115,116,101,114,100,101,115,99,101,110,116,105,116,32,119,105,
+116,104,110,117,99,108,101,97,114,74,101,119,105,115,104,32,112,114,111,116,101,
+115,116,66,114,105,116,105,115,104,102,108,111,119,101,114,115,112,114,101,100,
+105,99,116,114,101,102,111,114,109,115,98,117,116,116,111,110,32,119,104,111,32,
+119,97,115,108,101,99,116,117,114,101,105,110,115,116,97,110,116,115,117,105,99,
+105,100,101,103,101,110,101,114,105,99,112,101,114,105,111,100,115,109,97,114,
+107,101,116,115,83,111,99,105,97,108,32,102,105,115,104,105,110,103,99,111,109,
+98,105,110,101,103,114,97,112,104,105,99,119,105,110,110,101,114,115,60,98,114,
+32,47,62,60,98,121,32,116,104,101,32,78,97,116,117,114,97,108,80,114,105,118,97,
+99,121,99,111,111,107,105,101,115,111,117,116,99,111,109,101,114,101,115,111,108
+,118,101,83,119,101,100,105,115,104,98,114,105,101,102,108,121,80,101,114,115,
+105,97,110,115,111,32,109,117,99,104,67,101,110,116,117,114,121,100,101,112,105,
+99,116,115,99,111,108,117,109,110,115,104,111,117,115,105,110,103,115,99,114,105
+,112,116,115,110,101,120,116,32,116,111,98,101,97,114,105,110,103,109,97,112,112
+,105,110,103,114,101,118,105,115,101,100,106,81,117,101,114,121,40,45,119,105,
+100,116,104,58,116,105,116,108,101,34,62,116,111,111,108,116,105,112,83,101,99,
+116,105,111,110,100,101,115,105,103,110,115,84,117,114,107,105,115,104,121,111,
+117,110,103,101,114,46,109,97,116,99,104,40,125,41,40,41,59,10,10,98,117,114,110
+,105,110,103,111,112,101,114,97,116,101,100,101,103,114,101,101,115,115,111,117,
+114,99,101,61,82,105,99,104,97,114,100,99,108,111,115,101,108,121,112,108,97,115
+,116,105,99,101,110,116,114,105,101,115,60,47,116,114,62,13,10,99,111,108,111,
+114,58,35,117,108,32,105,100,61,34,112,111,115,115,101,115,115,114,111,108,108,
+105,110,103,112,104,121,115,105,99,115,102,97,105,108,105,110,103,101,120,101,99
+,117,116,101,99,111,110,116,101,115,116,108,105,110,107,32,116,111,68,101,102,97
+,117,108,116,60,98,114,32,47,62,10,58,32,116,114,117,101,44,99,104,97,114,116,
+101,114,116,111,117,114,105,115,109,99,108,97,115,115,105,99,112,114,111,99,101,
+101,100,101,120,112,108,97,105,110,60,47,104,49,62,13,10,111,110,108,105,110,101
+,46,63,120,109,108,32,118,101,104,101,108,112,105,110,103,100,105,97,109,111,110
+,100,117,115,101,32,116,104,101,97,105,114,108,105,110,101,101,110,100,32,45,45,
+62,41,46,97,116,116,114,40,114,101,97,100,101,114,115,104,111,115,116,105,110,
+103,35,102,102,102,102,102,102,114,101,97,108,105,122,101,86,105,110,99,101,110,
+116,115,105,103,110,97,108,115,32,115,114,99,61,34,47,80,114,111,100,117,99,116,
+100,101,115,112,105,116,101,100,105,118,101,114,115,101,116,101,108,108,105,110,
+103,80,117,98,108,105,99,32,104,101,108,100,32,105,110,74,111,115,101,112,104,32
+,116,104,101,97,116,114,101,97,102,102,101,99,116,115,60,115,116,121,108,101,62,
+97,32,108,97,114,103,101,100,111,101,115,110,39,116,108,97,116,101,114,44,32,69,
+108,101,109,101,110,116,102,97,118,105,99,111,110,99,114,101,97,116,111,114,72,
+117,110,103,97,114,121,65,105,114,112,111,114,116,115,101,101,32,116,104,101,115
+,111,32,116,104,97,116,77,105,99,104,97,101,108,83,121,115,116,101,109,115,80,
+114,111,103,114,97,109,115,44,32,97,110,100,32,32,119,105,100,116,104,61,101,38,
+113,117,111,116,59,116,114,97,100,105,110,103,108,101,102,116,34,62,10,112,101,
+114,115,111,110,115,71,111,108,100,101,110,32,65,102,102,97,105,114,115,103,114,
+97,109,109,97,114,102,111,114,109,105,110,103,100,101,115,116,114,111,121,105,
+100,101,97,32,111,102,99,97,115,101,32,111,102,111,108,100,101,115,116,32,116,
+104,105,115,32,105,115,46,115,114,99,32,61,32,99,97,114,116,111,111,110,114,101,
+103,105,115,116,114,67,111,109,109,111,110,115,77,117,115,108,105,109,115,87,104
+,97,116,32,105,115,105,110,32,109,97,110,121,109,97,114,107,105,110,103,114,101,
+118,101,97,108,115,73,110,100,101,101,100,44,101,113,117,97,108,108,121,47,115,
+104,111,119,95,97,111,117,116,100,111,111,114,101,115,99,97,112,101,40,65,117,
+115,116,114,105,97,103,101,110,101,116,105,99,115,121,115,116,101,109,44,73,110,
+32,116,104,101,32,115,105,116,116,105,110,103,72,101,32,97,108,115,111,73,115,
+108,97,110,100,115,65,99,97,100,101,109,121,10,9,9,60,33,45,45,68,97,110,105,101
+,108,32,98,105,110,100,105,110,103,98,108,111,99,107,34,62,105,109,112,111,115,
+101,100,117,116,105,108,105,122,101,65,98,114,97,104,97,109,40,101,120,99,101,
+112,116,123,119,105,100,116,104,58,112,117,116,116,105,110,103,41,46,104,116,109
+,108,40,124,124,32,91,93,59,10,68,65,84,65,91,32,42,107,105,116,99,104,101,110,
+109,111,117,110,116,101,100,97,99,116,117,97,108,32,100,105,97,108,101,99,116,
+109,97,105,110,108,121,32,95,98,108,97,110,107,39,105,110,115,116,97,108,108,101
+,120,112,101,114,116,115,105,102,40,116,121,112,101,73,116,32,97,108,115,111,38,
+99,111,112,121,59,32,34,62,84,101,114,109,115,98,111,114,110,32,105,110,79,112,
+116,105,111,110,115,101,97,115,116,101,114,110,116,97,108,107,105,110,103,99,111
+,110,99,101,114,110,103,97,105,110,101,100,32,111,110,103,111,105,110,103,106,
+117,115,116,105,102,121,99,114,105,116,105,99,115,102,97,99,116,111,114,121,105,
+116,115,32,111,119,110,97,115,115,97,117,108,116,105,110,118,105,116,101,100,108
+,97,115,116,105,110,103,104,105,115,32,111,119,110,104,114,101,102,61,34,47,34,
+32,114,101,108,61,34,100,101,118,101,108,111,112,99,111,110,99,101,114,116,100,
+105,97,103,114,97,109,100,111,108,108,97,114,115,99,108,117,115,116,101,114,112,
+104,112,63,105,100,61,97,108,99,111,104,111,108,41,59,125,41,40,41,59,117,115,
+105,110,103,32,97,62,60,115,112,97,110,62,118,101,115,115,101,108,115,114,101,
+118,105,118,97,108,65,100,100,114,101,115,115,97,109,97,116,101,117,114,97,110,
+100,114,111,105,100,97,108,108,101,103,101,100,105,108,108,110,101,115,115,119,
+97,108,107,105,110,103,99,101,110,116,101,114,115,113,117,97,108,105,102,121,109
+,97,116,99,104,101,115,117,110,105,102,105,101,100,101,120,116,105,110,99,116,68
+,101,102,101,110,115,101,100,105,101,100,32,105,110,10,9,60,33,45,45,32,99,117,
+115,116,111,109,115,108,105,110,107,105,110,103,76,105,116,116,108,101,32,66,111
+,111,107,32,111,102,101,118,101,110,105,110,103,109,105,110,46,106,115,63,97,114
+,101,32,116,104,101,107,111,110,116,97,107,116,116,111,100,97,121,39,115,46,104,
+116,109,108,34,32,116,97,114,103,101,116,61,119,101,97,114,105,110,103,65,108,
+108,32,82,105,103,59,10,125,41,40,41,59,114,97,105,115,105,110,103,32,65,108,115
+,111,44,32,99,114,117,99,105,97,108,97,98,111,117,116,34,62,100,101,99,108,97,
+114,101,45,45,62,10,60,115,99,102,105,114,101,102,111,120,97,115,32,109,117,99,
+104,97,112,112,108,105,101,115,105,110,100,101,120,44,32,115,44,32,98,117,116,32
+,116,121,112,101,32,61,32,10,13,10,60,33,45,45,116,111,119,97,114,100,115,82,101
+,99,111,114,100,115,80,114,105,118,97,116,101,70,111,114,101,105,103,110,80,114,
+101,109,105,101,114,99,104,111,105,99,101,115,86,105,114,116,117,97,108,114,101,
+116,117,114,110,115,67,111,109,109,101,110,116,80,111,119,101,114,101,100,105,
+110,108,105,110,101,59,112,111,118,101,114,116,121,99,104,97,109,98,101,114,76,
+105,118,105,110,103,32,118,111,108,117,109,101,115,65,110,116,104,111,110,121,
+108,111,103,105,110,34,32,82,101,108,97,116,101,100,69,99,111,110,111,109,121,
+114,101,97,99,104,101,115,99,117,116,116,105,110,103,103,114,97,118,105,116,121,
+108,105,102,101,32,105,110,67,104,97,112,116,101,114,45,115,104,97,100,111,119,
+78,111,116,97,98,108,101,60,47,116,100,62,13,10,32,114,101,116,117,114,110,115,
+116,97,100,105,117,109,119,105,100,103,101,116,115,118,97,114,121,105,110,103,
+116,114,97,118,101,108,115,104,101,108,100,32,98,121,119,104,111,32,97,114,101,
+119,111,114,107,32,105,110,102,97,99,117,108,116,121,97,110,103,117,108,97,114,
+119,104,111,32,104,97,100,97,105,114,112,111,114,116,116,111,119,110,32,111,102,
+10,10,83,111,109,101,32,39,99,108,105,99,107,39,99,104,97,114,103,101,115,107,
+101,121,119,111,114,100,105,116,32,119,105,108,108,99,105,116,121,32,111,102,40,
+116,104,105,115,41,59,65,110,100,114,101,119,32,117,110,105,113,117,101,32,99,
+104,101,99,107,101,100,111,114,32,109,111,114,101,51,48,48,112,120,59,32,114,101
+,116,117,114,110,59,114,115,105,111,110,61,34,112,108,117,103,105,110,115,119,
+105,116,104,105,110,32,104,101,114,115,101,108,102,83,116,97,116,105,111,110,70,
+101,100,101,114,97,108,118,101,110,116,117,114,101,112,117,98,108,105,115,104,
+115,101,110,116,32,116,111,116,101,110,115,105,111,110,97,99,116,114,101,115,115
+,99,111,109,101,32,116,111,102,105,110,103,101,114,115,68,117,107,101,32,111,102
+,112,101,111,112,108,101,44,101,120,112,108,111,105,116,119,104,97,116,32,105,
+115,104,97,114,109,111,110,121,97,32,109,97,106,111,114,34,58,34,104,116,116,112
+,105,110,32,104,105,115,32,109,101,110,117,34,62,10,109,111,110,116,104,108,121,
+111,102,102,105,99,101,114,99,111,117,110,99,105,108,103,97,105,110,105,110,103,
+101,118,101,110,32,105,110,83,117,109,109,97,114,121,100,97,116,101,32,111,102,
+108,111,121,97,108,116,121,102,105,116,110,101,115,115,97,110,100,32,119,97,115,
+101,109,112,101,114,111,114,115,117,112,114,101,109,101,83,101,99,111,110,100,32
+,104,101,97,114,105,110,103,82,117,115,115,105,97,110,108,111,110,103,101,115,
+116,65,108,98,101,114,116,97,108,97,116,101,114,97,108,115,101,116,32,111,102,32
+,115,109,97,108,108,34,62,46,97,112,112,101,110,100,100,111,32,119,105,116,104,
+102,101,100,101,114,97,108,98,97,110,107,32,111,102,98,101,110,101,97,116,104,68
+,101,115,112,105,116,101,67,97,112,105,116,97,108,103,114,111,117,110,100,115,41
+,44,32,97,110,100,32,112,101,114,99,101,110,116,105,116,32,102,114,111,109,99,
+108,111,115,105,110,103,99,111,110,116,97,105,110,73,110,115,116,101,97,100,102,
+105,102,116,101,101,110,97,115,32,119,101,108,108,46,121,97,104,111,111,46,114,
+101,115,112,111,110,100,102,105,103,104,116,101,114,111,98,115,99,117,114,101,
+114,101,102,108,101,99,116,111,114,103,97,110,105,99,61,32,77,97,116,104,46,101,
+100,105,116,105,110,103,111,110,108,105,110,101,32,112,97,100,100,105,110,103,97
+,32,119,104,111,108,101,111,110,101,114,114,111,114,121,101,97,114,32,111,102,
+101,110,100,32,111,102,32,98,97,114,114,105,101,114,119,104,101,110,32,105,116,
+104,101,97,100,101,114,32,104,111,109,101,32,111,102,114,101,115,117,109,101,100
+,114,101,110,97,109,101,100,115,116,114,111,110,103,62,104,101,97,116,105,110,
+103,114,101,116,97,105,110,115,99,108,111,117,100,102,114,119,97,121,32,111,102,
+32,77,97,114,99,104,32,49,107,110,111,119,105,110,103,105,110,32,112,97,114,116,
+66,101,116,119,101,101,110,108,101,115,115,111,110,115,99,108,111,115,101,115,
+116,118,105,114,116,117,97,108,108,105,110,107,115,34,62,99,114,111,115,115,101,
+100,69,78,68,32,45,45,62,102,97,109,111,117,115,32,97,119,97,114,100,101,100,76,
+105,99,101,110,115,101,72,101,97,108,116,104,32,102,97,105,114,108,121,32,119,
+101,97,108,116,104,121,109,105,110,105,109,97,108,65,102,114,105,99,97,110,99,
+111,109,112,101,116,101,108,97,98,101,108,34,62,115,105,110,103,105,110,103,102,
+97,114,109,101,114,115,66,114,97,115,105,108,41,100,105,115,99,117,115,115,114,
+101,112,108,97,99,101,71,114,101,103,111,114,121,102,111,110,116,32,99,111,112,
+117,114,115,117,101,100,97,112,112,101,97,114,115,109,97,107,101,32,117,112,114,
+111,117,110,100,101,100,98,111,116,104,32,111,102,98,108,111,99,107,101,100,115,
+97,119,32,116,104,101,111,102,102,105,99,101,115,99,111,108,111,117,114,115,105,
+102,40,100,111,99,117,119,104,101,110,32,104,101,101,110,102,111,114,99,101,112,
+117,115,104,40,102,117,65,117,103,117,115,116,32,85,84,70,45,56,34,62,70,97,110,
+116,97,115,121,105,110,32,109,111,115,116,105,110,106,117,114,101,100,85,115,117
+,97,108,108,121,102,97,114,109,105,110,103,99,108,111,115,117,114,101,111,98,106
+,101,99,116,32,100,101,102,101,110,99,101,117,115,101,32,111,102,32,77,101,100,
+105,99,97,108,60,98,111,100,121,62,10,101,118,105,100,101,110,116,98,101,32,117,
+115,101,100,107,101,121,67,111,100,101,115,105,120,116,101,101,110,73,115,108,97
+,109,105,99,35,48,48,48,48,48,48,101,110,116,105,114,101,32,119,105,100,101,108,
+121,32,97,99,116,105,118,101,32,40,116,121,112,101,111,102,111,110,101,32,99,97,
+110,99,111,108,111,114,32,61,115,112,101,97,107,101,114,101,120,116,101,110,100,
+115,80,104,121,115,105,99,115,116,101,114,114,97,105,110,60,116,98,111,100,121,
+62,102,117,110,101,114,97,108,118,105,101,119,105,110,103,109,105,100,100,108,
+101,32,99,114,105,99,107,101,116,112,114,111,112,104,101,116,115,104,105,102,116
+,101,100,100,111,99,116,111,114,115,82,117,115,115,101,108,108,32,116,97,114,103
+,101,116,99,111,109,112,97,99,116,97,108,103,101,98,114,97,115,111,99,105,97,108
+,45,98,117,108,107,32,111,102,109,97,110,32,97,110,100,60,47,116,100,62,10,32,
+104,101,32,108,101,102,116,41,46,118,97,108,40,41,102,97,108,115,101,41,59,108,
+111,103,105,99,97,108,98,97,110,107,105,110,103,104,111,109,101,32,116,111,110,
+97,109,105,110,103,32,65,114,105,122,111,110,97,99,114,101,100,105,116,115,41,59
+,10,125,41,59,10,102,111,117,110,100,101,114,105,110,32,116,117,114,110,67,111,
+108,108,105,110,115,98,101,102,111,114,101,32,66,117,116,32,116,104,101,99,104,
+97,114,103,101,100,84,105,116,108,101,34,62,67,97,112,116,97,105,110,115,112,101
+,108,108,101,100,103,111,100,100,101,115,115,84,97,103,32,45,45,62,65,100,100,
+105,110,103,58,98,117,116,32,119,97,115,82,101,99,101,110,116,32,112,97,116,105,
+101,110,116,98,97,99,107,32,105,110,61,102,97,108,115,101,38,76,105,110,99,111,
+108,110,119,101,32,107,110,111,119,67,111,117,110,116,101,114,74,117,100,97,105,
+115,109,115,99,114,105,112,116,32,97,108,116,101,114,101,100,39,93,41,59,10,32,
+32,104,97,115,32,116,104,101,117,110,99,108,101,97,114,69,118,101,110,116,39,44,
+98,111,116,104,32,105,110,110,111,116,32,97,108,108,10,10,60,33,45,45,32,112,108
+,97,99,105,110,103,104,97,114,100,32,116,111,32,99,101,110,116,101,114,115,111,
+114,116,32,111,102,99,108,105,101,110,116,115,115,116,114,101,101,116,115,66,101
+,114,110,97,114,100,97,115,115,101,114,116,115,116,101,110,100,32,116,111,102,97
+,110,116,97,115,121,100,111,119,110,32,105,110,104,97,114,98,111,117,114,70,114,
+101,101,100,111,109,106,101,119,101,108,114,121,47,97,98,111,117,116,46,46,115,
+101,97,114,99,104,108,101,103,101,110,100,115,105,115,32,109,97,100,101,109,111,
+100,101,114,110,32,111,110,108,121,32,111,110,111,110,108,121,32,116,111,105,109
+,97,103,101,34,32,108,105,110,101,97,114,32,112,97,105,110,116,101,114,97,110,
+100,32,110,111,116,114,97,114,101,108,121,32,97,99,114,111,110,121,109,100,101,
+108,105,118,101,114,115,104,111,114,116,101,114,48,48,38,97,109,112,59,97,115,32
+,109,97,110,121,119,105,100,116,104,61,34,47,42,32,60,33,91,67,116,105,116,108,
+101,32,61,111,102,32,116,104,101,32,108,111,119,101,115,116,32,112,105,99,107,
+101,100,32,101,115,99,97,112,101,100,117,115,101,115,32,111,102,112,101,111,112,
+108,101,115,32,80,117,98,108,105,99,77,97,116,116,104,101,119,116,97,99,116,105,
+99,115,100,97,109,97,103,101,100,119,97,121,32,102,111,114,108,97,119,115,32,111
+,102,101,97,115,121,32,116,111,32,119,105,110,100,111,119,115,116,114,111,110,
+103,32,32,115,105,109,112,108,101,125,99,97,116,99,104,40,115,101,118,101,110,
+116,104,105,110,102,111,98,111,120,119,101,110,116,32,116,111,112,97,105,110,116
+,101,100,99,105,116,105,122,101,110,73,32,100,111,110,39,116,114,101,116,114,101
+,97,116,46,32,83,111,109,101,32,119,119,46,34,41,59,10,98,111,109,98,105,110,103
+,109,97,105,108,116,111,58,109,97,100,101,32,105,110,46,32,77,97,110,121,32,99,
+97,114,114,105,101,115,124,124,123,125,59,119,105,119,111,114,107,32,111,102,115
+,121,110,111,110,121,109,100,101,102,101,97,116,115,102,97,118,111,114,101,100,
+111,112,116,105,99,97,108,112,97,103,101,84,114,97,117,110,108,101,115,115,32,
+115,101,110,100,105,110,103,108,101,102,116,34,62,60,99,111,109,83,99,111,114,65
+,108,108,32,116,104,101,106,81,117,101,114,121,46,116,111,117,114,105,115,116,67
+,108,97,115,115,105,99,102,97,108,115,101,34,32,87,105,108,104,101,108,109,115,
+117,98,117,114,98,115,103,101,110,117,105,110,101,98,105,115,104,111,112,115,46,
+115,112,108,105,116,40,103,108,111,98,97,108,32,102,111,108,108,111,119,115,98,
+111,100,121,32,111,102,110,111,109,105,110,97,108,67,111,110,116,97,99,116,115,
+101,99,117,108,97,114,108,101,102,116,32,116,111,99,104,105,101,102,108,121,45,
+104,105,100,100,101,110,45,98,97,110,110,101,114,60,47,108,105,62,10,10,46,32,87
+,104,101,110,32,105,110,32,98,111,116,104,100,105,115,109,105,115,115,69,120,112
+,108,111,114,101,97,108,119,97,121,115,32,118,105,97,32,116,104,101,115,112,97,
+195,177,111,108,119,101,108,102,97,114,101,114,117,108,105,110,103,32,97,114,114
+,97,110,103,101,99,97,112,116,97,105,110,104,105,115,32,115,111,110,114,117,108,
+101,32,111,102,104,101,32,116,111,111,107,105,116,115,101,108,102,44,61,48,38,97
+,109,112,59,40,99,97,108,108,101,100,115,97,109,112,108,101,115,116,111,32,109,
+97,107,101,99,111,109,47,112,97,103,77,97,114,116,105,110,32,75,101,110,110,101,
+100,121,97,99,99,101,112,116,115,102,117,108,108,32,111,102,104,97,110,100,108,
+101,100,66,101,115,105,100,101,115,47,47,45,45,62,60,47,97,98,108,101,32,116,111
+,116,97,114,103,101,116,115,101,115,115,101,110,99,101,104,105,109,32,116,111,32
+,105,116,115,32,98,121,32,99,111,109,109,111,110,46,109,105,110,101,114,97,108,
+116,111,32,116,97,107,101,119,97,121,115,32,116,111,115,46,111,114,103,47,108,97
+,100,118,105,115,101,100,112,101,110,97,108,116,121,115,105,109,112,108,101,58,
+105,102,32,116,104,101,121,76,101,116,116,101,114,115,97,32,115,104,111,114,116,
+72,101,114,98,101,114,116,115,116,114,105,107,101,115,32,103,114,111,117,112,115
+,46,108,101,110,103,116,104,102,108,105,103,104,116,115,111,118,101,114,108,97,
+112,115,108,111,119,108,121,32,108,101,115,115,101,114,32,115,111,99,105,97,108,
+32,60,47,112,62,10,9,9,105,116,32,105,110,116,111,114,97,110,107,101,100,32,114,
+97,116,101,32,111,102,117,108,62,13,10,32,32,97,116,116,101,109,112,116,112,97,
+105,114,32,111,102,109,97,107,101,32,105,116,75,111,110,116,97,107,116,65,110,
+116,111,110,105,111,104,97,118,105,110,103,32,114,97,116,105,110,103,115,32,97,
+99,116,105,118,101,115,116,114,101,97,109,115,116,114,97,112,112,101,100,34,41,
+46,99,115,115,40,104,111,115,116,105,108,101,108,101,97,100,32,116,111,108,105,
+116,116,108,101,32,103,114,111,117,112,115,44,80,105,99,116,117,114,101,45,45,62
+,13,10,13,10,32,114,111,119,115,61,34,32,111,98,106,101,99,116,105,110,118,101,
+114,115,101,60,102,111,111,116,101,114,67,117,115,116,111,109,86,62,60,92,47,115
+,99,114,115,111,108,118,105,110,103,67,104,97,109,98,101,114,115,108,97,118,101,
+114,121,119,111,117,110,100,101,100,119,104,101,114,101,97,115,33,61,32,39,117,
+110,100,102,111,114,32,97,108,108,112,97,114,116,108,121,32,45,114,105,103,104,
+116,58,65,114,97,98,105,97,110,98,97,99,107,101,100,32,99,101,110,116,117,114,
+121,117,110,105,116,32,111,102,109,111,98,105,108,101,45,69,117,114,111,112,101,
+44,105,115,32,104,111,109,101,114,105,115,107,32,111,102,100,101,115,105,114,101
+,100,67,108,105,110,116,111,110,99,111,115,116,32,111,102,97,103,101,32,111,102,
+32,98,101,99,111,109,101,32,110,111,110,101,32,111,102,112,38,113,117,111,116,59
+,77,105,100,100,108,101,32,101,97,100,39,41,91,48,67,114,105,116,105,99,115,115,
+116,117,100,105,111,115,62,38,99,111,112,121,59,103,114,111,117,112,34,62,97,115
+,115,101,109,98,108,109,97,107,105,110,103,32,112,114,101,115,115,101,100,119,
+105,100,103,101,116,46,112,115,58,34,32,63,32,114,101,98,117,105,108,116,98,121,
+32,115,111,109,101,70,111,114,109,101,114,32,101,100,105,116,111,114,115,100,101
+,108,97,121,101,100,67,97,110,111,110,105,99,104,97,100,32,116,104,101,112,117,
+115,104,105,110,103,99,108,97,115,115,61,34,98,117,116,32,97,114,101,112,97,114,
+116,105,97,108,66,97,98,121,108,111,110,98,111,116,116,111,109,32,99,97,114,114,
+105,101,114,67,111,109,109,97,110,100,105,116,115,32,117,115,101,65,115,32,119,
+105,116,104,99,111,117,114,115,101,115,97,32,116,104,105,114,100,100,101,110,111
+,116,101,115,97,108,115,111,32,105,110,72,111,117,115,116,111,110,50,48,112,120,
+59,34,62,97,99,99,117,115,101,100,100,111,117,98,108,101,32,103,111,97,108,32,
+111,102,70,97,109,111,117,115,32,41,46,98,105,110,100,40,112,114,105,101,115,116
+,115,32,79,110,108,105,110,101,105,110,32,74,117,108,121,115,116,32,43,32,34,103
+,99,111,110,115,117,108,116,100,101,99,105,109,97,108,104,101,108,112,102,117,
+108,114,101,118,105,118,101,100,105,115,32,118,101,114,121,114,39,43,39,105,112,
+116,108,111,115,105,110,103,32,102,101,109,97,108,101,115,105,115,32,97,108,115,
+111,115,116,114,105,110,103,115,100,97,121,115,32,111,102,97,114,114,105,118,97,
+108,102,117,116,117,114,101,32,60,111,98,106,101,99,116,102,111,114,99,105,110,
+103,83,116,114,105,110,103,40,34,32,47,62,10,9,9,104,101,114,101,32,105,115,101,
+110,99,111,100,101,100,46,32,32,84,104,101,32,98,97,108,108,111,111,110,100,111,
+110,101,32,98,121,47,99,111,109,109,111,110,98,103,99,111,108,111,114,108,97,119
+,32,111,102,32,73,110,100,105,97,110,97,97,118,111,105,100,101,100,98,117,116,32
+,116,104,101,50,112,120,32,51,112,120,106,113,117,101,114,121,46,97,102,116,101,
+114,32,97,112,111,108,105,99,121,46,109,101,110,32,97,110,100,102,111,111,116,
+101,114,45,61,32,116,114,117,101,59,102,111,114,32,117,115,101,115,99,114,101,
+101,110,46,73,110,100,105,97,110,32,105,109,97,103,101,32,61,102,97,109,105,108,
+121,44,104,116,116,112,58,47,47,32,38,110,98,115,112,59,100,114,105,118,101,114,
+115,101,116,101,114,110,97,108,115,97,109,101,32,97,115,110,111,116,105,99,101,
+100,118,105,101,119,101,114,115,125,41,40,41,59,10,32,105,115,32,109,111,114,101
+,115,101,97,115,111,110,115,102,111,114,109,101,114,32,116,104,101,32,110,101,
+119,105,115,32,106,117,115,116,99,111,110,115,101,110,116,32,83,101,97,114,99,
+104,119,97,115,32,116,104,101,119,104,121,32,116,104,101,115,104,105,112,112,101
+,100,98,114,62,60,98,114,62,119,105,100,116,104,58,32,104,101,105,103,104,116,61
+,109,97,100,101,32,111,102,99,117,105,115,105,110,101,105,115,32,116,104,97,116,
+97,32,118,101,114,121,32,65,100,109,105,114,97,108,32,102,105,120,101,100,59,110
+,111,114,109,97,108,32,77,105,115,115,105,111,110,80,114,101,115,115,44,32,111,
+110,116,97,114,105,111,99,104,97,114,115,101,116,116,114,121,32,116,111,32,105,
+110,118,97,100,101,100,61,34,116,114,117,101,34,115,112,97,99,105,110,103,105,
+115,32,109,111,115,116,97,32,109,111,114,101,32,116,111,116,97,108,108,121,102,
+97,108,108,32,111,102,125,41,59,13,10,32,32,105,109,109,101,110,115,101,116,105,
+109,101,32,105,110,115,101,116,32,111,117,116,115,97,116,105,115,102,121,116,111
+,32,102,105,110,100,100,111,119,110,32,116,111,108,111,116,32,111,102,32,80,108,
+97,121,101,114,115,105,110,32,74,117,110,101,113,117,97,110,116,117,109,110,111,
+116,32,116,104,101,116,105,109,101,32,116,111,100,105,115,116,97,110,116,70,105,
+110,110,105,115,104,115,114,99,32,61,32,40,115,105,110,103,108,101,32,104,101,
+108,112,32,111,102,71,101,114,109,97,110,32,108,97,119,32,97,110,100,108,97,98,
+101,108,101,100,102,111,114,101,115,116,115,99,111,111,107,105,110,103,115,112,
+97,99,101,34,62,104,101,97,100,101,114,45,119,101,108,108,32,97,115,83,116,97,
+110,108,101,121,98,114,105,100,103,101,115,47,103,108,111,98,97,108,67,114,111,
+97,116,105,97,32,65,98,111,117,116,32,91,48,93,59,10,32,32,105,116,44,32,97,110,
+100,103,114,111,117,112,101,100,98,101,105,110,103,32,97,41,123,116,104,114,111,
+119,104,101,32,109,97,100,101,108,105,103,104,116,101,114,101,116,104,105,99,97,
+108,70,70,70,70,70,70,34,98,111,116,116,111,109,34,108,105,107,101,32,97,32,101,
+109,112,108,111,121,115,108,105,118,101,32,105,110,97,115,32,115,101,101,110,112
+,114,105,110,116,101,114,109,111,115,116,32,111,102,117,98,45,108,105,110,107,
+114,101,106,101,99,116,115,97,110,100,32,117,115,101,105,109,97,103,101,34,62,
+115,117,99,99,101,101,100,102,101,101,100,105,110,103,78,117,99,108,101,97,114,
+105,110,102,111,114,109,97,116,111,32,104,101,108,112,87,111,109,101,110,39,115,
+78,101,105,116,104,101,114,77,101,120,105,99,97,110,112,114,111,116,101,105,110,
+60,116,97,98,108,101,32,98,121,32,109,97,110,121,104,101,97,108,116,104,121,108,
+97,119,115,117,105,116,100,101,118,105,115,101,100,46,112,117,115,104,40,123,115
+,101,108,108,101,114,115,115,105,109,112,108,121,32,84,104,114,111,117,103,104,
+46,99,111,111,107,105,101,32,73,109,97,103,101,40,111,108,100,101,114,34,62,117,
+115,46,106,115,34,62,32,83,105,110,99,101,32,117,110,105,118,101,114,115,108,97,
+114,103,101,114,32,111,112,101,110,32,116,111,33,45,45,32,101,110,100,108,105,
+101,115,32,105,110,39,93,41,59,13,10,32,32,109,97,114,107,101,116,119,104,111,32
+,105,115,32,40,34,68,79,77,67,111,109,97,110,97,103,101,100,111,110,101,32,102,
+111,114,116,121,112,101,111,102,32,75,105,110,103,100,111,109,112,114,111,102,
+105,116,115,112,114,111,112,111,115,101,116,111,32,115,104,111,119,99,101,110,
+116,101,114,59,109,97,100,101,32,105,116,100,114,101,115,115,101,100,119,101,114
+,101,32,105,110,109,105,120,116,117,114,101,112,114,101,99,105,115,101,97,114,
+105,115,105,110,103,115,114,99,32,61,32,39,109,97,107,101,32,97,32,115,101,99,
+117,114,101,100,66,97,112,116,105,115,116,118,111,116,105,110,103,32,10,9,9,118,
+97,114,32,77,97,114,99,104,32,50,103,114,101,119,32,117,112,67,108,105,109,97,
+116,101,46,114,101,109,111,118,101,115,107,105,108,108,101,100,119,97,121,32,116
+,104,101,60,47,104,101,97,100,62,102,97,99,101,32,111,102,97,99,116,105,110,103,
+32,114,105,103,104,116,34,62,116,111,32,119,111,114,107,114,101,100,117,99,101,
+115,104,97,115,32,104,97,100,101,114,101,99,116,101,100,115,104,111,119,40,41,59
+,97,99,116,105,111,110,61,98,111,111,107,32,111,102,97,110,32,97,114,101,97,61,
+61,32,34,104,116,116,60,104,101,97,100,101,114,10,60,104,116,109,108,62,99,111,
+110,102,111,114,109,102,97,99,105,110,103,32,99,111,111,107,105,101,46,114,101,
+108,121,32,111,110,104,111,115,116,101,100,32,46,99,117,115,116,111,109,104,101,
+32,119,101,110,116,98,117,116,32,102,111,114,115,112,114,101,97,100,32,70,97,109
+,105,108,121,32,97,32,109,101,97,110,115,111,117,116,32,116,104,101,102,111,114,
+117,109,115,46,102,111,111,116,97,103,101,34,62,77,111,98,105,108,67,108,101,109
+,101,110,116,115,34,32,105,100,61,34,97,115,32,104,105,103,104,105,110,116,101,
+110,115,101,45,45,62,60,33,45,45,102,101,109,97,108,101,32,105,115,32,115,101,
+101,110,105,109,112,108,105,101,100,115,101,116,32,116,104,101,97,32,115,116,97,
+116,101,97,110,100,32,104,105,115,102,97,115,116,101,115,116,98,101,115,105,100,
+101,115,98,117,116,116,111,110,95,98,111,117,110,100,101,100,34,62,60,105,109,
+103,32,73,110,102,111,98,111,120,101,118,101,110,116,115,44,97,32,121,111,117,
+110,103,97,110,100,32,97,114,101,78,97,116,105,118,101,32,99,104,101,97,112,101,
+114,84,105,109,101,111,117,116,97,110,100,32,104,97,115,101,110,103,105,110,101,
+115,119,111,110,32,116,104,101,40,109,111,115,116,108,121,114,105,103,104,116,58
+,32,102,105,110,100,32,97,32,45,98,111,116,116,111,109,80,114,105,110,99,101,32,
+97,114,101,97,32,111,102,109,111,114,101,32,111,102,115,101,97,114,99,104,95,110
+,97,116,117,114,101,44,108,101,103,97,108,108,121,112,101,114,105,111,100,44,108
+,97,110,100,32,111,102,111,114,32,119,105,116,104,105,110,100,117,99,101,100,112
+,114,111,118,105,110,103,109,105,115,115,105,108,101,108,111,99,97,108,108,121,
+65,103,97,105,110,115,116,116,104,101,32,119,97,121,107,38,113,117,111,116,59,
+112,120,59,34,62,13,10,112,117,115,104,101,100,32,97,98,97,110,100,111,110,110,
+117,109,101,114,97,108,67,101,114,116,97,105,110,73,110,32,116,104,105,115,109,
+111,114,101,32,105,110,111,114,32,115,111,109,101,110,97,109,101,32,105,115,97,
+110,100,44,32,105,110,99,114,111,119,110,101,100,73,83,66,78,32,48,45,99,114,101
+,97,116,101,115,79,99,116,111,98,101,114,109,97,121,32,110,111,116,99,101,110,
+116,101,114,32,108,97,116,101,32,105,110,68,101,102,101,110,99,101,101,110,97,99
+,116,101,100,119,105,115,104,32,116,111,98,114,111,97,100,108,121,99,111,111,108
+,105,110,103,111,110,108,111,97,100,61,105,116,46,32,84,104,101,114,101,99,111,
+118,101,114,77,101,109,98,101,114,115,104,101,105,103,104,116,32,97,115,115,117,
+109,101,115,60,104,116,109,108,62,10,112,101,111,112,108,101,46,105,110,32,111,
+110,101,32,61,119,105,110,100,111,119,102,111,111,116,101,114,95,97,32,103,111,
+111,100,32,114,101,107,108,97,109,97,111,116,104,101,114,115,44,116,111,32,116,
+104,105,115,95,99,111,111,107,105,101,112,97,110,101,108,34,62,76,111,110,100,
+111,110,44,100,101,102,105,110,101,115,99,114,117,115,104,101,100,98,97,112,116,
+105,115,109,99,111,97,115,116,97,108,115,116,97,116,117,115,32,116,105,116,108,
+101,34,32,109,111,118,101,32,116,111,108,111,115,116,32,105,110,98,101,116,116,
+101,114,32,105,109,112,108,105,101,115,114,105,118,97,108,114,121,115,101,114,
+118,101,114,115,32,83,121,115,116,101,109,80,101,114,104,97,112,115,101,115,32,
+97,110,100,32,99,111,110,116,101,110,100,102,108,111,119,105,110,103,108,97,115,
+116,101,100,32,114,105,115,101,32,105,110,71,101,110,101,115,105,115,118,105,101
+,119,32,111,102,114,105,115,105,110,103,32,115,101,101,109,32,116,111,98,117,116
+,32,105,110,32,98,97,99,107,105,110,103,104,101,32,119,105,108,108,103,105,118,
+101,110,32,97,103,105,118,105,110,103,32,99,105,116,105,101,115,46,102,108,111,
+119,32,111,102,32,76,97,116,101,114,32,97,108,108,32,98,117,116,72,105,103,104,
+119,97,121,111,110,108,121,32,98,121,115,105,103,110,32,111,102,104,101,32,100,
+111,101,115,100,105,102,102,101,114,115,98,97,116,116,101,114,121,38,97,109,112,
+59,108,97,115,105,110,103,108,101,115,116,104,114,101,97,116,115,105,110,116,101
+,103,101,114,116,97,107,101,32,111,110,114,101,102,117,115,101,100,99,97,108,108
+,101,100,32,61,85,83,38,97,109,112,83,101,101,32,116,104,101,110,97,116,105,118,
+101,115,98,121,32,116,104,105,115,115,121,115,116,101,109,46,104,101,97,100,32,
+111,102,58,104,111,118,101,114,44,108,101,115,98,105,97,110,115,117,114,110,97,
+109,101,97,110,100,32,97,108,108,99,111,109,109,111,110,47,104,101,97,100,101,
+114,95,95,112,97,114,97,109,115,72,97,114,118,97,114,100,47,112,105,120,101,108,
+46,114,101,109,111,118,97,108,115,111,32,108,111,110,103,114,111,108,101,32,111,
+102,106,111,105,110,116,108,121,115,107,121,115,99,114,97,85,110,105,99,111,100,
+101,98,114,32,47,62,13,10,65,116,108,97,110,116,97,110,117,99,108,101,117,115,67
+,111,117,110,116,121,44,112,117,114,101,108,121,32,99,111,117,110,116,34,62,101,
+97,115,105,108,121,32,98,117,105,108,100,32,97,111,110,99,108,105,99,107,97,32,
+103,105,118,101,110,112,111,105,110,116,101,114,104,38,113,117,111,116,59,101,
+118,101,110,116,115,32,101,108,115,101,32,123,10,100,105,116,105,111,110,115,110
+,111,119,32,116,104,101,44,32,119,105,116,104,32,109,97,110,32,119,104,111,111,
+114,103,47,87,101,98,111,110,101,32,97,110,100,99,97,118,97,108,114,121,72,101,
+32,100,105,101,100,115,101,97,116,116,108,101,48,48,44,48,48,48,32,123,119,105,
+110,100,111,119,104,97,118,101,32,116,111,105,102,40,119,105,110,100,97,110,100,
+32,105,116,115,115,111,108,101,108,121,32,109,38,113,117,111,116,59,114,101,110,
+101,119,101,100,68,101,116,114,111,105,116,97,109,111,110,103,115,116,101,105,
+116,104,101,114,32,116,104,101,109,32,105,110,83,101,110,97,116,111,114,85,115,
+60,47,97,62,60,75,105,110,103,32,111,102,70,114,97,110,99,105,115,45,112,114,111
+,100,117,99,104,101,32,117,115,101,100,97,114,116,32,97,110,100,104,105,109,32,
+97,110,100,117,115,101,100,32,98,121,115,99,111,114,105,110,103,97,116,32,104,
+111,109,101,116,111,32,104,97,118,101,114,101,108,97,116,101,115,105,98,105,108,
+105,116,121,102,97,99,116,105,111,110,66,117,102,102,97,108,111,108,105,110,107,
+34,62,60,119,104,97,116,32,104,101,102,114,101,101,32,116,111,67,105,116,121,32,
+111,102,99,111,109,101,32,105,110,115,101,99,116,111,114,115,99,111,117,110,116,
+101,100,111,110,101,32,100,97,121,110,101,114,118,111,117,115,115,113,117,97,114
+,101,32,125,59,105,102,40,103,111,105,110,32,119,104,97,116,105,109,103,34,32,97
+,108,105,115,32,111,110,108,121,115,101,97,114,99,104,47,116,117,101,115,100,97,
+121,108,111,111,115,101,108,121,83,111,108,111,109,111,110,115,101,120,117,97,
+108,32,45,32,60,97,32,104,114,109,101,100,105,117,109,34,68,79,32,78,79,84,32,70
+,114,97,110,99,101,44,119,105,116,104,32,97,32,119,97,114,32,97,110,100,115,101,
+99,111,110,100,32,116,97,107,101,32,97,32,62,13,10,13,10,13,10,109,97,114,107,
+101,116,46,104,105,103,104,119,97,121,100,111,110,101,32,105,110,99,116,105,118,
+105,116,121,34,108,97,115,116,34,62,111,98,108,105,103,101,100,114,105,115,101,
+32,116,111,34,117,110,100,101,102,105,109,97,100,101,32,116,111,32,69,97,114,108
+,121,32,112,114,97,105,115,101,100,105,110,32,105,116,115,32,102,111,114,32,104,
+105,115,97,116,104,108,101,116,101,74,117,112,105,116,101,114,89,97,104,111,111,
+33,32,116,101,114,109,101,100,32,115,111,32,109,97,110,121,114,101,97,108,108,
+121,32,115,46,32,84,104,101,32,97,32,119,111,109,97,110,63,118,97,108,117,101,61
+,100,105,114,101,99,116,32,114,105,103,104,116,34,32,98,105,99,121,99,108,101,97
+,99,105,110,103,61,34,100,97,121,32,97,110,100,115,116,97,116,105,110,103,82,97,
+116,104,101,114,44,104,105,103,104,101,114,32,79,102,102,105,99,101,32,97,114,
+101,32,110,111,119,116,105,109,101,115,44,32,119,104,101,110,32,97,32,112,97,121
+,32,102,111,114,111,110,32,116,104,105,115,45,108,105,110,107,34,62,59,98,111,
+114,100,101,114,97,114,111,117,110,100,32,97,110,110,117,97,108,32,116,104,101,
+32,78,101,119,112,117,116,32,116,104,101,46,99,111,109,34,32,116,97,107,105,110,
+32,116,111,97,32,98,114,105,101,102,40,105,110,32,116,104,101,103,114,111,117,
+112,115,46,59,32,119,105,100,116,104,101,110,122,121,109,101,115,115,105,109,112
+,108,101,32,105,110,32,108,97,116,101,123,114,101,116,117,114,110,116,104,101,
+114,97,112,121,97,32,112,111,105,110,116,98,97,110,110,105,110,103,105,110,107,
+115,34,62,10,40,41,59,34,32,114,101,97,32,112,108,97,99,101,92,117,48,48,51,67,
+97,97,98,111,117,116,32,97,116,114,62,13,10,9,9,99,99,111,117,110,116,32,103,105
+,118,101,115,32,97,60,83,67,82,73,80,84,82,97,105,108,119,97,121,116,104,101,109
+,101,115,47,116,111,111,108,98,111,120,66,121,73,100,40,34,120,104,117,109,97,
+110,115,44,119,97,116,99,104,101,115,105,110,32,115,111,109,101,32,105,102,32,40
+,119,105,99,111,109,105,110,103,32,102,111,114,109,97,116,115,32,85,110,100,101,
+114,32,98,117,116,32,104,97,115,104,97,110,100,101,100,32,109,97,100,101,32,98,
+121,116,104,97,110,32,105,110,102,101,97,114,32,111,102,100,101,110,111,116,101,
+100,47,105,102,114,97,109,101,108,101,102,116,32,105,110,118,111,108,116,97,103,
+101,105,110,32,101,97,99,104,97,38,113,117,111,116,59,98,97,115,101,32,111,102,
+73,110,32,109,97,110,121,117,110,100,101,114,103,111,114,101,103,105,109,101,115
+,97,99,116,105,111,110,32,60,47,112,62,13,10,60,117,115,116,111,109,86,97,59,38,
+103,116,59,60,47,105,109,112,111,114,116,115,111,114,32,116,104,97,116,109,111,
+115,116,108,121,32,38,97,109,112,59,114,101,32,115,105,122,101,61,34,60,47,97,62
+,60,47,104,97,32,99,108,97,115,115,112,97,115,115,105,118,101,72,111,115,116,32,
+61,32,87,104,101,116,104,101,114,102,101,114,116,105,108,101,86,97,114,105,111,
+117,115,61,91,93,59,40,102,117,99,97,109,101,114,97,115,47,62,60,47,116,100,62,
+97,99,116,115,32,97,115,73,110,32,115,111,109,101,62,13,10,13,10,60,33,111,114,
+103,97,110,105,115,32,60,98,114,32,47,62,66,101,105,106,105,110,103,99,97,116,97
+,108,195,160,100,101,117,116,115,99,104,101,117,114,111,112,101,117,101,117,115,
+107,97,114,97,103,97,101,105,108,103,101,115,118,101,110,115,107,97,101,115,112,
+97,195,177,97,109,101,110,115,97,106,101,117,115,117,97,114,105,111,116,114,97,
+98,97,106,111,109,195,169,120,105,99,111,112,195,161,103,105,110,97,115,105,101,
+109,112,114,101,115,105,115,116,101,109,97,111,99,116,117,98,114,101,100,117,114
+,97,110,116,101,97,195,177,97,100,105,114,101,109,112,114,101,115,97,109,111,109
+,101,110,116,111,110,117,101,115,116,114,111,112,114,105,109,101,114,97,116,114,
+97,118,195,169,115,103,114,97,99,105,97,115,110,117,101,115,116,114,97,112,114,
+111,99,101,115,111,101,115,116,97,100,111,115,99,97,108,105,100,97,100,112,101,
+114,115,111,110,97,110,195,186,109,101,114,111,97,99,117,101,114,100,111,109,195
+,186,115,105,99,97,109,105,101,109,98,114,111,111,102,101,114,116,97,115,97,108,
+103,117,110,111,115,112,97,195,173,115,101,115,101,106,101,109,112,108,111,100,
+101,114,101,99,104,111,97,100,101,109,195,161,115,112,114,105,118,97,100,111,97,
+103,114,101,103,97,114,101,110,108,97,99,101,115,112,111,115,105,98,108,101,104,
+111,116,101,108,101,115,115,101,118,105,108,108,97,112,114,105,109,101,114,111,
+195,186,108,116,105,109,111,101,118,101,110,116,111,115,97,114,99,104,105,118,
+111,99,117,108,116,117,114,97,109,117,106,101,114,101,115,101,110,116,114,97,100
+,97,97,110,117,110,99,105,111,101,109,98,97,114,103,111,109,101,114,99,97,100,
+111,103,114,97,110,100,101,115,101,115,116,117,100,105,111,109,101,106,111,114,
+101,115,102,101,98,114,101,114,111,100,105,115,101,195,177,111,116,117,114,105,
+115,109,111,99,195,179,100,105,103,111,112,111,114,116,97,100,97,101,115,112,97,
+99,105,111,102,97,109,105,108,105,97,97,110,116,111,110,105,111,112,101,114,109,
+105,116,101,103,117,97,114,100,97,114,97,108,103,117,110,97,115,112,114,101,99,
+105,111,115,97,108,103,117,105,101,110,115,101,110,116,105,100,111,118,105,115,
+105,116,97,115,116,195,173,116,117,108,111,99,111,110,111,99,101,114,115,101,103
+,117,110,100,111,99,111,110,115,101,106,111,102,114,97,110,99,105,97,109,105,110
+,117,116,111,115,115,101,103,117,110,100,97,116,101,110,101,109,111,115,101,102,
+101,99,116,111,115,109,195,161,108,97,103,97,115,101,115,105,195,179,110,114,101
+,118,105,115,116,97,103,114,97,110,97,100,97,99,111,109,112,114,97,114,105,110,
+103,114,101,115,111,103,97,114,99,195,173,97,97,99,99,105,195,179,110,101,99,117
+,97,100,111,114,113,117,105,101,110,101,115,105,110,99,108,117,115,111,100,101,
+98,101,114,195,161,109,97,116,101,114,105,97,104,111,109,98,114,101,115,109,117,
+101,115,116,114,97,112,111,100,114,195,173,97,109,97,195,177,97,110,97,195,186,
+108,116,105,109,97,101,115,116,97,109,111,115,111,102,105,99,105,97,108,116,97,
+109,98,105,101,110,110,105,110,103,195,186,110,115,97,108,117,100,111,115,112,
+111,100,101,109,111,115,109,101,106,111,114,97,114,112,111,115,105,116,105,111,
+110,98,117,115,105,110,101,115,115,104,111,109,101,112,97,103,101,115,101,99,117
+,114,105,116,121,108,97,110,103,117,97,103,101,115,116,97,110,100,97,114,100,99,
+97,109,112,97,105,103,110,102,101,97,116,117,114,101,115,99,97,116,101,103,111,
+114,121,101,120,116,101,114,110,97,108,99,104,105,108,100,114,101,110,114,101,
+115,101,114,118,101,100,114,101,115,101,97,114,99,104,101,120,99,104,97,110,103,
+101,102,97,118,111,114,105,116,101,116,101,109,112,108,97,116,101,109,105,108,
+105,116,97,114,121,105,110,100,117,115,116,114,121,115,101,114,118,105,99,101,
+115,109,97,116,101,114,105,97,108,112,114,111,100,117,99,116,115,122,45,105,110,
+100,101,120,58,99,111,109,109,101,110,116,115,115,111,102,116,119,97,114,101,99,
+111,109,112,108,101,116,101,99,97,108,101,110,100,97,114,112,108,97,116,102,111,
+114,109,97,114,116,105,99,108,101,115,114,101,113,117,105,114,101,100,109,111,
+118,101,109,101,110,116,113,117,101,115,116,105,111,110,98,117,105,108,100,105,
+110,103,112,111,108,105,116,105,99,115,112,111,115,115,105,98,108,101,114,101,
+108,105,103,105,111,110,112,104,121,115,105,99,97,108,102,101,101,100,98,97,99,
+107,114,101,103,105,115,116,101,114,112,105,99,116,117,114,101,115,100,105,115,
+97,98,108,101,100,112,114,111,116,111,99,111,108,97,117,100,105,101,110,99,101,
+115,101,116,116,105,110,103,115,97,99,116,105,118,105,116,121,101,108,101,109,
+101,110,116,115,108,101,97,114,110,105,110,103,97,110,121,116,104,105,110,103,97
+,98,115,116,114,97,99,116,112,114,111,103,114,101,115,115,111,118,101,114,118,
+105,101,119,109,97,103,97,122,105,110,101,101,99,111,110,111,109,105,99,116,114,
+97,105,110,105,110,103,112,114,101,115,115,117,114,101,118,97,114,105,111,117,
+115,32,60,115,116,114,111,110,103,62,112,114,111,112,101,114,116,121,115,104,111
+,112,112,105,110,103,116,111,103,101,116,104,101,114,97,100,118,97,110,99,101,
+100,98,101,104,97,118,105,111,114,100,111,119,110,108,111,97,100,102,101,97,116,
+117,114,101,100,102,111,111,116,98,97,108,108,115,101,108,101,99,116,101,100,76,
+97,110,103,117,97,103,101,100,105,115,116,97,110,99,101,114,101,109,101,109,98,
+101,114,116,114,97,99,107,105,110,103,112,97,115,115,119,111,114,100,109,111,100
+,105,102,105,101,100,115,116,117,100,101,110,116,115,100,105,114,101,99,116,108,
+121,102,105,103,104,116,105,110,103,110,111,114,116,104,101,114,110,100,97,116,
+97,98,97,115,101,102,101,115,116,105,118,97,108,98,114,101,97,107,105,110,103,
+108,111,99,97,116,105,111,110,105,110,116,101,114,110,101,116,100,114,111,112,
+100,111,119,110,112,114,97,99,116,105,99,101,101,118,105,100,101,110,99,101,102,
+117,110,99,116,105,111,110,109,97,114,114,105,97,103,101,114,101,115,112,111,110
+,115,101,112,114,111,98,108,101,109,115,110,101,103,97,116,105,118,101,112,114,
+111,103,114,97,109,115,97,110,97,108,121,115,105,115,114,101,108,101,97,115,101,
+100,98,97,110,110,101,114,34,62,112,117,114,99,104,97,115,101,112,111,108,105,99
+,105,101,115,114,101,103,105,111,110,97,108,99,114,101,97,116,105,118,101,97,114
+,103,117,109,101,110,116,98,111,111,107,109,97,114,107,114,101,102,101,114,114,
+101,114,99,104,101,109,105,99,97,108,100,105,118,105,115,105,111,110,99,97,108,
+108,98,97,99,107,115,101,112,97,114,97,116,101,112,114,111,106,101,99,116,115,99
+,111,110,102,108,105,99,116,104,97,114,100,119,97,114,101,105,110,116,101,114,
+101,115,116,100,101,108,105,118,101,114,121,109,111,117,110,116,97,105,110,111,
+98,116,97,105,110,101,100,61,32,102,97,108,115,101,59,102,111,114,40,118,97,114,
+32,97,99,99,101,112,116,101,100,99,97,112,97,99,105,116,121,99,111,109,112,117,
+116,101,114,105,100,101,110,116,105,116,121,97,105,114,99,114,97,102,116,101,109
+,112,108,111,121,101,100,112,114,111,112,111,115,101,100,100,111,109,101,115,116
+,105,99,105,110,99,108,117,100,101,115,112,114,111,118,105,100,101,100,104,111,
+115,112,105,116,97,108,118,101,114,116,105,99,97,108,99,111,108,108,97,112,115,
+101,97,112,112,114,111,97,99,104,112,97,114,116,110,101,114,115,108,111,103,111,
+34,62,60,97,100,97,117,103,104,116,101,114,97,117,116,104,111,114,34,32,99,117,
+108,116,117,114,97,108,102,97,109,105,108,105,101,115,47,105,109,97,103,101,115,
+47,97,115,115,101,109,98,108,121,112,111,119,101,114,102,117,108,116,101,97,99,
+104,105,110,103,102,105,110,105,115,104,101,100,100,105,115,116,114,105,99,116,
+99,114,105,116,105,99,97,108,99,103,105,45,98,105,110,47,112,117,114,112,111,115
+,101,115,114,101,113,117,105,114,101,115,101,108,101,99,116,105,111,110,98,101,
+99,111,109,105,110,103,112,114,111,118,105,100,101,115,97,99,97,100,101,109,105,
+99,101,120,101,114,99,105,115,101,97,99,116,117,97,108,108,121,109,101,100,105,
+99,105,110,101,99,111,110,115,116,97,110,116,97,99,99,105,100,101,110,116,77,97,
+103,97,122,105,110,101,100,111,99,117,109,101,110,116,115,116,97,114,116,105,110
+,103,98,111,116,116,111,109,34,62,111,98,115,101,114,118,101,100,58,32,38,113,
+117,111,116,59,101,120,116,101,110,100,101,100,112,114,101,118,105,111,117,115,
+83,111,102,116,119,97,114,101,99,117,115,116,111,109,101,114,100,101,99,105,115,
+105,111,110,115,116,114,101,110,103,116,104,100,101,116,97,105,108,101,100,115,
+108,105,103,104,116,108,121,112,108,97,110,110,105,110,103,116,101,120,116,97,
+114,101,97,99,117,114,114,101,110,99,121,101,118,101,114,121,111,110,101,115,116
+,114,97,105,103,104,116,116,114,97,110,115,102,101,114,112,111,115,105,116,105,
+118,101,112,114,111,100,117,99,101,100,104,101,114,105,116,97,103,101,115,104,
+105,112,112,105,110,103,97,98,115,111,108,117,116,101,114,101,99,101,105,118,101
+,100,114,101,108,101,118,97,110,116,98,117,116,116,111,110,34,32,118,105,111,108
+,101,110,99,101,97,110,121,119,104,101,114,101,98,101,110,101,102,105,116,115,
+108,97,117,110,99,104,101,100,114,101,99,101,110,116,108,121,97,108,108,105,97,
+110,99,101,102,111,108,108,111,119,101,100,109,117,108,116,105,112,108,101,98,
+117,108,108,101,116,105,110,105,110,99,108,117,100,101,100,111,99,99,117,114,114
+,101,100,105,110,116,101,114,110,97,108,36,40,116,104,105,115,41,46,114,101,112,
+117,98,108,105,99,62,60,116,114,62,60,116,100,99,111,110,103,114,101,115,115,114
+,101,99,111,114,100,101,100,117,108,116,105,109,97,116,101,115,111,108,117,116,
+105,111,110,60,117,108,32,105,100,61,34,100,105,115,99,111,118,101,114,72,111,
+109,101,60,47,97,62,119,101,98,115,105,116,101,115,110,101,116,119,111,114,107,
+115,97,108,116,104,111,117,103,104,101,110,116,105,114,101,108,121,109,101,109,
+111,114,105,97,108,109,101,115,115,97,103,101,115,99,111,110,116,105,110,117,101
+,97,99,116,105,118,101,34,62,115,111,109,101,119,104,97,116,118,105,99,116,111,
+114,105,97,87,101,115,116,101,114,110,32,32,116,105,116,108,101,61,34,76,111,99,
+97,116,105,111,110,99,111,110,116,114,97,99,116,118,105,115,105,116,111,114,115,
+68,111,119,110,108,111,97,100,119,105,116,104,111,117,116,32,114,105,103,104,116
+,34,62,10,109,101,97,115,117,114,101,115,119,105,100,116,104,32,61,32,118,97,114
+,105,97,98,108,101,105,110,118,111,108,118,101,100,118,105,114,103,105,110,105,
+97,110,111,114,109,97,108,108,121,104,97,112,112,101,110,101,100,97,99,99,111,
+117,110,116,115,115,116,97,110,100,105,110,103,110,97,116,105,111,110,97,108,82,
+101,103,105,115,116,101,114,112,114,101,112,97,114,101,100,99,111,110,116,114,
+111,108,115,97,99,99,117,114,97,116,101,98,105,114,116,104,100,97,121,115,116,
+114,97,116,101,103,121,111,102,102,105,99,105,97,108,103,114,97,112,104,105,99,
+115,99,114,105,109,105,110,97,108,112,111,115,115,105,98,108,121,99,111,110,115,
+117,109,101,114,80,101,114,115,111,110,97,108,115,112,101,97,107,105,110,103,118
+,97,108,105,100,97,116,101,97,99,104,105,101,118,101,100,46,106,112,103,34,32,47
+,62,109,97,99,104,105,110,101,115,60,47,104,50,62,10,32,32,107,101,121,119,111,
+114,100,115,102,114,105,101,110,100,108,121,98,114,111,116,104,101,114,115,99,
+111,109,98,105,110,101,100,111,114,105,103,105,110,97,108,99,111,109,112,111,115
+,101,100,101,120,112,101,99,116,101,100,97,100,101,113,117,97,116,101,112,97,107
+,105,115,116,97,110,102,111,108,108,111,119,34,32,118,97,108,117,97,98,108,101,
+60,47,108,97,98,101,108,62,114,101,108,97,116,105,118,101,98,114,105,110,103,105
+,110,103,105,110,99,114,101,97,115,101,103,111,118,101,114,110,111,114,112,108,
+117,103,105,110,115,47,76,105,115,116,32,111,102,32,72,101,97,100,101,114,34,62,
+34,32,110,97,109,101,61,34,32,40,38,113,117,111,116,59,103,114,97,100,117,97,116
+,101,60,47,104,101,97,100,62,10,99,111,109,109,101,114,99,101,109,97,108,97,121,
+115,105,97,100,105,114,101,99,116,111,114,109,97,105,110,116,97,105,110,59,104,
+101,105,103,104,116,58,115,99,104,101,100,117,108,101,99,104,97,110,103,105,110,
+103,98,97,99,107,32,116,111,32,99,97,116,104,111,108,105,99,112,97,116,116,101,
+114,110,115,99,111,108,111,114,58,32,35,103,114,101,97,116,101,115,116,115,117,
+112,112,108,105,101,115,114,101,108,105,97,98,108,101,60,47,117,108,62,10,9,9,60
+,115,101,108,101,99,116,32,99,105,116,105,122,101,110,115,99,108,111,116,104,105
+,110,103,119,97,116,99,104,105,110,103,60,108,105,32,105,100,61,34,115,112,101,
+99,105,102,105,99,99,97,114,114,121,105,110,103,115,101,110,116,101,110,99,101,
+60,99,101,110,116,101,114,62,99,111,110,116,114,97,115,116,116,104,105,110,107,
+105,110,103,99,97,116,99,104,40,101,41,115,111,117,116,104,101,114,110,77,105,99
+,104,97,101,108,32,109,101,114,99,104,97,110,116,99,97,114,111,117,115,101,108,
+112,97,100,100,105,110,103,58,105,110,116,101,114,105,111,114,46,115,112,108,105
+,116,40,34,108,105,122,97,116,105,111,110,79,99,116,111,98,101,114,32,41,123,114
+,101,116,117,114,110,105,109,112,114,111,118,101,100,45,45,38,103,116,59,10,10,
+99,111,118,101,114,97,103,101,99,104,97,105,114,109,97,110,46,112,110,103,34,32,
+47,62,115,117,98,106,101,99,116,115,82,105,99,104,97,114,100,32,119,104,97,116,
+101,118,101,114,112,114,111,98,97,98,108,121,114,101,99,111,118,101,114,121,98,
+97,115,101,98,97,108,108,106,117,100,103,109,101,110,116,99,111,110,110,101,99,
+116,46,46,99,115,115,34,32,47,62,32,119,101,98,115,105,116,101,114,101,112,111,
+114,116,101,100,100,101,102,97,117,108,116,34,47,62,60,47,97,62,13,10,101,108,
+101,99,116,114,105,99,115,99,111,116,108,97,110,100,99,114,101,97,116,105,111,
+110,113,117,97,110,116,105,116,121,46,32,73,83,66,78,32,48,100,105,100,32,110,
+111,116,32,105,110,115,116,97,110,99,101,45,115,101,97,114,99,104,45,34,32,108,
+97,110,103,61,34,115,112,101,97,107,101,114,115,67,111,109,112,117,116,101,114,
+99,111,110,116,97,105,110,115,97,114,99,104,105,118,101,115,109,105,110,105,115,
+116,101,114,114,101,97,99,116,105,111,110,100,105,115,99,111,117,110,116,73,116,
+97,108,105,97,110,111,99,114,105,116,101,114,105,97,115,116,114,111,110,103,108,
+121,58,32,39,104,116,116,112,58,39,115,99,114,105,112,116,39,99,111,118,101,114,
+105,110,103,111,102,102,101,114,105,110,103,97,112,112,101,97,114,101,100,66,114
+,105,116,105,115,104,32,105,100,101,110,116,105,102,121,70,97,99,101,98,111,111,
+107,110,117,109,101,114,111,117,115,118,101,104,105,99,108,101,115,99,111,110,99
+,101,114,110,115,65,109,101,114,105,99,97,110,104,97,110,100,108,105,110,103,100
+,105,118,32,105,100,61,34,87,105,108,108,105,97,109,32,112,114,111,118,105,100,
+101,114,95,99,111,110,116,101,110,116,97,99,99,117,114,97,99,121,115,101,99,116,
+105,111,110,32,97,110,100,101,114,115,111,110,102,108,101,120,105,98,108,101,67,
+97,116,101,103,111,114,121,108,97,119,114,101,110,99,101,60,115,99,114,105,112,
+116,62,108,97,121,111,117,116,61,34,97,112,112,114,111,118,101,100,32,109,97,120
+,105,109,117,109,104,101,97,100,101,114,34,62,60,47,116,97,98,108,101,62,83,101,
+114,118,105,99,101,115,104,97,109,105,108,116,111,110,99,117,114,114,101,110,116
+,32,99,97,110,97,100,105,97,110,99,104,97,110,110,101,108,115,47,116,104,101,109
+,101,115,47,47,97,114,116,105,99,108,101,111,112,116,105,111,110,97,108,112,111,
+114,116,117,103,97,108,118,97,108,117,101,61,34,34,105,110,116,101,114,118,97,
+108,119,105,114,101,108,101,115,115,101,110,116,105,116,108,101,100,97,103,101,
+110,99,105,101,115,83,101,97,114,99,104,34,32,109,101,97,115,117,114,101,100,116
+,104,111,117,115,97,110,100,115,112,101,110,100,105,110,103,38,104,101,108,108,
+105,112,59,110,101,119,32,68,97,116,101,34,32,115,105,122,101,61,34,112,97,103,
+101,78,97,109,101,109,105,100,100,108,101,34,32,34,32,47,62,60,47,97,62,104,105,
+100,100,101,110,34,62,115,101,113,117,101,110,99,101,112,101,114,115,111,110,97,
+108,111,118,101,114,102,108,111,119,111,112,105,110,105,111,110,115,105,108,108,
+105,110,111,105,115,108,105,110,107,115,34,62,10,9,60,116,105,116,108,101,62,118
+,101,114,115,105,111,110,115,115,97,116,117,114,100,97,121,116,101,114,109,105,
+110,97,108,105,116,101,109,112,114,111,112,101,110,103,105,110,101,101,114,115,
+101,99,116,105,111,110,115,100,101,115,105,103,110,101,114,112,114,111,112,111,
+115,97,108,61,34,102,97,108,115,101,34,69,115,112,97,195,177,111,108,114,101,108
+,101,97,115,101,115,115,117,98,109,105,116,34,32,101,114,38,113,117,111,116,59,
+97,100,100,105,116,105,111,110,115,121,109,112,116,111,109,115,111,114,105,101,
+110,116,101,100,114,101,115,111,117,114,99,101,114,105,103,104,116,34,62,60,112,
+108,101,97,115,117,114,101,115,116,97,116,105,111,110,115,104,105,115,116,111,
+114,121,46,108,101,97,118,105,110,103,32,32,98,111,114,100,101,114,61,99,111,110
+,116,101,110,116,115,99,101,110,116,101,114,34,62,46,10,10,83,111,109,101,32,100
+,105,114,101,99,116,101,100,115,117,105,116,97,98,108,101,98,117,108,103,97,114,
+105,97,46,115,104,111,119,40,41,59,100,101,115,105,103,110,101,100,71,101,110,
+101,114,97,108,32,99,111,110,99,101,112,116,115,69,120,97,109,112,108,101,115,
+119,105,108,108,105,97,109,115,79,114,105,103,105,110,97,108,34,62,60,115,112,97
+,110,62,115,101,97,114,99,104,34,62,111,112,101,114,97,116,111,114,114,101,113,
+117,101,115,116,115,97,32,38,113,117,111,116,59,97,108,108,111,119,105,110,103,
+68,111,99,117,109,101,110,116,114,101,118,105,115,105,111,110,46,32,10,10,84,104
+,101,32,121,111,117,114,115,101,108,102,67,111,110,116,97,99,116,32,109,105,99,
+104,105,103,97,110,69,110,103,108,105,115,104,32,99,111,108,117,109,98,105,97,
+112,114,105,111,114,105,116,121,112,114,105,110,116,105,110,103,100,114,105,110,
+107,105,110,103,102,97,99,105,108,105,116,121,114,101,116,117,114,110,101,100,67
+,111,110,116,101,110,116,32,111,102,102,105,99,101,114,115,82,117,115,115,105,97
+,110,32,103,101,110,101,114,97,116,101,45,56,56,53,57,45,49,34,105,110,100,105,
+99,97,116,101,102,97,109,105,108,105,97,114,32,113,117,97,108,105,116,121,109,97
+,114,103,105,110,58,48,32,99,111,110,116,101,110,116,118,105,101,119,112,111,114
+,116,99,111,110,116,97,99,116,115,45,116,105,116,108,101,34,62,112,111,114,116,
+97,98,108,101,46,108,101,110,103,116,104,32,101,108,105,103,105,98,108,101,105,
+110,118,111,108,118,101,115,97,116,108,97,110,116,105,99,111,110,108,111,97,100,
+61,34,100,101,102,97,117,108,116,46,115,117,112,112,108,105,101,100,112,97,121,
+109,101,110,116,115,103,108,111,115,115,97,114,121,10,10,65,102,116,101,114,32,
+103,117,105,100,97,110,99,101,60,47,116,100,62,60,116,100,101,110,99,111,100,105
+,110,103,109,105,100,100,108,101,34,62,99,97,109,101,32,116,111,32,100,105,115,
+112,108,97,121,115,115,99,111,116,116,105,115,104,106,111,110,97,116,104,97,110,
+109,97,106,111,114,105,116,121,119,105,100,103,101,116,115,46,99,108,105,110,105
+,99,97,108,116,104,97,105,108,97,110,100,116,101,97,99,104,101,114,115,60,104,
+101,97,100,62,10,9,97,102,102,101,99,116,101,100,115,117,112,112,111,114,116,115
+,112,111,105,110,116,101,114,59,116,111,83,116,114,105,110,103,60,47,115,109,97,
+108,108,62,111,107,108,97,104,111,109,97,119,105,108,108,32,98,101,32,105,110,
+118,101,115,116,111,114,48,34,32,97,108,116,61,34,104,111,108,105,100,97,121,115
+,82,101,115,111,117,114,99,101,108,105,99,101,110,115,101,100,32,40,119,104,105,
+99,104,32,46,32,65,102,116,101,114,32,99,111,110,115,105,100,101,114,118,105,115
+,105,116,105,110,103,101,120,112,108,111,114,101,114,112,114,105,109,97,114,121,
+32,115,101,97,114,99,104,34,32,97,110,100,114,111,105,100,34,113,117,105,99,107,
+108,121,32,109,101,101,116,105,110,103,115,101,115,116,105,109,97,116,101,59,114
+,101,116,117,114,110,32,59,99,111,108,111,114,58,35,32,104,101,105,103,104,116,
+61,97,112,112,114,111,118,97,108,44,32,38,113,117,111,116,59,32,99,104,101,99,
+107,101,100,46,109,105,110,46,106,115,34,109,97,103,110,101,116,105,99,62,60,47,
+97,62,60,47,104,102,111,114,101,99,97,115,116,46,32,87,104,105,108,101,32,116,
+104,117,114,115,100,97,121,100,118,101,114,116,105,115,101,38,101,97,99,117,116,
+101,59,104,97,115,67,108,97,115,115,101,118,97,108,117,97,116,101,111,114,100,
+101,114,105,110,103,101,120,105,115,116,105,110,103,112,97,116,105,101,110,116,
+115,32,79,110,108,105,110,101,32,99,111,108,111,114,97,100,111,79,112,116,105,
+111,110,115,34,99,97,109,112,98,101,108,108,60,33,45,45,32,101,110,100,60,47,115
+,112,97,110,62,60,60,98,114,32,47,62,13,10,95,112,111,112,117,112,115,124,115,99
+,105,101,110,99,101,115,44,38,113,117,111,116,59,32,113,117,97,108,105,116,121,
+32,87,105,110,100,111,119,115,32,97,115,115,105,103,110,101,100,104,101,105,103,
+104,116,58,32,60,98,32,99,108,97,115,115,108,101,38,113,117,111,116,59,32,118,97
+,108,117,101,61,34,32,67,111,109,112,97,110,121,101,120,97,109,112,108,101,115,
+60,105,102,114,97,109,101,32,98,101,108,105,101,118,101,115,112,114,101,115,101,
+110,116,115,109,97,114,115,104,97,108,108,112,97,114,116,32,111,102,32,112,114,
+111,112,101,114,108,121,41,46,10,10,84,104,101,32,116,97,120,111,110,111,109,121
+,109,117,99,104,32,111,102,32,60,47,115,112,97,110,62,10,34,32,100,97,116,97,45,
+115,114,116,117,103,117,195,170,115,115,99,114,111,108,108,84,111,32,112,114,111
+,106,101,99,116,60,104,101,97,100,62,13,10,97,116,116,111,114,110,101,121,101,
+109,112,104,97,115,105,115,115,112,111,110,115,111,114,115,102,97,110,99,121,98,
+111,120,119,111,114,108,100,39,115,32,119,105,108,100,108,105,102,101,99,104,101
+,99,107,101,100,61,115,101,115,115,105,111,110,115,112,114,111,103,114,97,109,
+109,112,120,59,102,111,110,116,45,32,80,114,111,106,101,99,116,106,111,117,114,
+110,97,108,115,98,101,108,105,101,118,101,100,118,97,99,97,116,105,111,110,116,
+104,111,109,112,115,111,110,108,105,103,104,116,105,110,103,97,110,100,32,116,
+104,101,32,115,112,101,99,105,97,108,32,98,111,114,100,101,114,61,48,99,104,101,
+99,107,105,110,103,60,47,116,98,111,100,121,62,60,98,117,116,116,111,110,32,67,
+111,109,112,108,101,116,101,99,108,101,97,114,102,105,120,10,60,104,101,97,100,
+62,10,97,114,116,105,99,108,101,32,60,115,101,99,116,105,111,110,102,105,110,100
+,105,110,103,115,114,111,108,101,32,105,110,32,112,111,112,117,108,97,114,32,32,
+79,99,116,111,98,101,114,119,101,98,115,105,116,101,32,101,120,112,111,115,117,
+114,101,117,115,101,100,32,116,111,32,32,99,104,97,110,103,101,115,111,112,101,
+114,97,116,101,100,99,108,105,99,107,105,110,103,101,110,116,101,114,105,110,103
+,99,111,109,109,97,110,100,115,105,110,102,111,114,109,101,100,32,110,117,109,98
+,101,114,115,32,32,60,47,100,105,118,62,99,114,101,97,116,105,110,103,111,110,83
+,117,98,109,105,116,109,97,114,121,108,97,110,100,99,111,108,108,101,103,101,115
+,97,110,97,108,121,116,105,99,108,105,115,116,105,110,103,115,99,111,110,116,97,
+99,116,46,108,111,103,103,101,100,73,110,97,100,118,105,115,111,114,121,115,105,
+98,108,105,110,103,115,99,111,110,116,101,110,116,34,115,38,113,117,111,116,59,
+41,115,46,32,84,104,105,115,32,112,97,99,107,97,103,101,115,99,104,101,99,107,98
+,111,120,115,117,103,103,101,115,116,115,112,114,101,103,110,97,110,116,116,111,
+109,111,114,114,111,119,115,112,97,99,105,110,103,61,105,99,111,110,46,112,110,
+103,106,97,112,97,110,101,115,101,99,111,100,101,98,97,115,101,98,117,116,116,
+111,110,34,62,103,97,109,98,108,105,110,103,115,117,99,104,32,97,115,32,44,32,
+119,104,105,108,101,32,60,47,115,112,97,110,62,32,109,105,115,115,111,117,114,
+105,115,112,111,114,116,105,110,103,116,111,112,58,49,112,120,32,46,60,47,115,
+112,97,110,62,116,101,110,115,105,111,110,115,119,105,100,116,104,61,34,50,108,
+97,122,121,108,111,97,100,110,111,118,101,109,98,101,114,117,115,101,100,32,105,
+110,32,104,101,105,103,104,116,61,34,99,114,105,112,116,34,62,10,38,110,98,115,
+112,59,60,47,60,116,114,62,60,116,100,32,104,101,105,103,104,116,58,50,47,112,
+114,111,100,117,99,116,99,111,117,110,116,114,121,32,105,110,99,108,117,100,101,
+32,102,111,111,116,101,114,34,32,38,108,116,59,33,45,45,32,116,105,116,108,101,
+34,62,60,47,106,113,117,101,114,121,46,60,47,102,111,114,109,62,10,40,231,174,
+128,228,189,147,41,40,231,185,129,233,171,148,41,104,114,118,97,116,115,107,105,
+105,116,97,108,105,97,110,111,114,111,109,195,162,110,196,131,116,195,188,114,
+107,195,167,101,216,167,216,177,216,175,217,136,116,97,109,98,105,195,169,110,
+110,111,116,105,99,105,97,115,109,101,110,115,97,106,101,115,112,101,114,115,111
+,110,97,115,100,101,114,101,99,104,111,115,110,97,99,105,111,110,97,108,115,101,
+114,118,105,99,105,111,99,111,110,116,97,99,116,111,117,115,117,97,114,105,111,
+115,112,114,111,103,114,97,109,97,103,111,98,105,101,114,110,111,101,109,112,114
+,101,115,97,115,97,110,117,110,99,105,111,115,118,97,108,101,110,99,105,97,99,
+111,108,111,109,98,105,97,100,101,115,112,117,195,169,115,100,101,112,111,114,
+116,101,115,112,114,111,121,101,99,116,111,112,114,111,100,117,99,116,111,112,
+195,186,98,108,105,99,111,110,111,115,111,116,114,111,115,104,105,115,116,111,
+114,105,97,112,114,101,115,101,110,116,101,109,105,108,108,111,110,101,115,109,
+101,100,105,97,110,116,101,112,114,101,103,117,110,116,97,97,110,116,101,114,105
+,111,114,114,101,99,117,114,115,111,115,112,114,111,98,108,101,109,97,115,97,110
+,116,105,97,103,111,110,117,101,115,116,114,111,115,111,112,105,110,105,195,179,
+110,105,109,112,114,105,109,105,114,109,105,101,110,116,114,97,115,97,109,195,
+169,114,105,99,97,118,101,110,100,101,100,111,114,115,111,99,105,101,100,97,100,
+114,101,115,112,101,99,116,111,114,101,97,108,105,122,97,114,114,101,103,105,115
+,116,114,111,112,97,108,97,98,114,97,115,105,110,116,101,114,195,169,115,101,110
+,116,111,110,99,101,115,101,115,112,101,99,105,97,108,109,105,101,109,98,114,111
+,115,114,101,97,108,105,100,97,100,99,195,179,114,100,111,98,97,122,97,114,97,
+103,111,122,97,112,195,161,103,105,110,97,115,115,111,99,105,97,108,101,115,98,
+108,111,113,117,101,97,114,103,101,115,116,105,195,179,110,97,108,113,117,105,
+108,101,114,115,105,115,116,101,109,97,115,99,105,101,110,99,105,97,115,99,111,
+109,112,108,101,116,111,118,101,114,115,105,195,179,110,99,111,109,112,108,101,
+116,97,101,115,116,117,100,105,111,115,112,195,186,98,108,105,99,97,111,98,106,
+101,116,105,118,111,97,108,105,99,97,110,116,101,98,117,115,99,97,100,111,114,99
+,97,110,116,105,100,97,100,101,110,116,114,97,100,97,115,97,99,99,105,111,110,
+101,115,97,114,99,104,105,118,111,115,115,117,112,101,114,105,111,114,109,97,121
+,111,114,195,173,97,97,108,101,109,97,110,105,97,102,117,110,99,105,195,179,110,
+195,186,108,116,105,109,111,115,104,97,99,105,101,110,100,111,97,113,117,101,108
+,108,111,115,101,100,105,99,105,195,179,110,102,101,114,110,97,110,100,111,97,
+109,98,105,101,110,116,101,102,97,99,101,98,111,111,107,110,117,101,115,116,114,
+97,115,99,108,105,101,110,116,101,115,112,114,111,99,101,115,111,115,98,97,115,
+116,97,110,116,101,112,114,101,115,101,110,116,97,114,101,112,111,114,116,97,114
+,99,111,110,103,114,101,115,111,112,117,98,108,105,99,97,114,99,111,109,101,114,
+99,105,111,99,111,110,116,114,97,116,111,106,195,179,118,101,110,101,115,100,105
+,115,116,114,105,116,111,116,195,169,99,110,105,99,97,99,111,110,106,117,110,116
+,111,101,110,101,114,103,195,173,97,116,114,97,98,97,106,97,114,97,115,116,117,
+114,105,97,115,114,101,99,105,101,110,116,101,117,116,105,108,105,122,97,114,98,
+111,108,101,116,195,173,110,115,97,108,118,97,100,111,114,99,111,114,114,101,99,
+116,97,116,114,97,98,97,106,111,115,112,114,105,109,101,114,111,115,110,101,103,
+111,99,105,111,115,108,105,98,101,114,116,97,100,100,101,116,97,108,108,101,115,
+112,97,110,116,97,108,108,97,112,114,195,179,120,105,109,111,97,108,109,101,114,
+195,173,97,97,110,105,109,97,108,101,115,113,117,105,195,169,110,101,115,99,111,
+114,97,122,195,179,110,115,101,99,99,105,195,179,110,98,117,115,99,97,110,100,
+111,111,112,99,105,111,110,101,115,101,120,116,101,114,105,111,114,99,111,110,99
+,101,112,116,111,116,111,100,97,118,195,173,97,103,97,108,101,114,195,173,97,101
+,115,99,114,105,98,105,114,109,101,100,105,99,105,110,97,108,105,99,101,110,99,
+105,97,99,111,110,115,117,108,116,97,97,115,112,101,99,116,111,115,99,114,195,
+173,116,105,99,97,100,195,179,108,97,114,101,115,106,117,115,116,105,99,105,97,
+100,101,98,101,114,195,161,110,112,101,114,195,173,111,100,111,110,101,99,101,
+115,105,116,97,109,97,110,116,101,110,101,114,112,101,113,117,101,195,177,111,
+114,101,99,105,98,105,100,97,116,114,105,98,117,110,97,108,116,101,110,101,114,
+105,102,101,99,97,110,99,105,195,179,110,99,97,110,97,114,105,97,115,100,101,115
+,99,97,114,103,97,100,105,118,101,114,115,111,115,109,97,108,108,111,114,99,97,
+114,101,113,117,105,101,114,101,116,195,169,99,110,105,99,111,100,101,98,101,114
+,195,173,97,118,105,118,105,101,110,100,97,102,105,110,97,110,122,97,115,97,100,
+101,108,97,110,116,101,102,117,110,99,105,111,110,97,99,111,110,115,101,106,111,
+115,100,105,102,195,173,99,105,108,99,105,117,100,97,100,101,115,97,110,116,105,
+103,117,97,115,97,118,97,110,122,97,100,97,116,195,169,114,109,105,110,111,117,
+110,105,100,97,100,101,115,115,195,161,110,99,104,101,122,99,97,109,112,97,195,
+177,97,115,111,102,116,111,110,105,99,114,101,118,105,115,116,97,115,99,111,110,
+116,105,101,110,101,115,101,99,116,111,114,101,115,109,111,109,101,110,116,111,
+115,102,97,99,117,108,116,97,100,99,114,195,169,100,105,116,111,100,105,118,101,
+114,115,97,115,115,117,112,117,101,115,116,111,102,97,99,116,111,114,101,115,115
+,101,103,117,110,100,111,115,112,101,113,117,101,195,177,97,208,179,208,190,208,
+180,208,176,208,181,209,129,208,187,208,184,208,181,209,129,209,130,209,140,208,
+177,209,139,208,187,208,190,208,177,209,139,209,130,209,140,209,141,209,130,208,
+190,208,188,208,149,209,129,208,187,208,184,209,130,208,190,208,179,208,190,208,
+188,208,181,208,189,209,143,208,178,209,129,208,181,209,133,209,141,209,130,208,
+190,208,185,208,180,208,176,208,182,208,181,208,177,209,139,208,187,208,184,208,
+179,208,190,208,180,209,131,208,180,208,181,208,189,209,140,209,141,209,130,208,
+190,209,130,208,177,209,139,208,187,208,176,209,129,208,181,208,177,209,143,208,
+190,208,180,208,184,208,189,209,129,208,181,208,177,208,181,208,189,208,176,208,
+180,208,190,209,129,208,176,208,185,209,130,209,132,208,190,209,130,208,190,208,
+189,208,181,208,179,208,190,209,129,208,178,208,190,208,184,209,129,208,178,208,
+190,208,185,208,184,208,179,209,128,209,139,209,130,208,190,208,182,208,181,208,
+178,209,129,208,181,208,188,209,129,208,178,208,190,209,142,208,187,208,184,209,
+136,209,140,209,141,209,130,208,184,209,133,208,191,208,190,208,186,208,176,208,
+180,208,189,208,181,208,185,208,180,208,190,208,188,208,176,208,188,208,184,209,
+128,208,176,208,187,208,184,208,177,208,190,209,130,208,181,208,188,209,131,209,
+133,208,190,209,130,209,143,208,180,208,178,209,131,209,133,209,129,208,181,209,
+130,208,184,208,187,209,142,208,180,208,184,208,180,208,181,208,187,208,190,208,
+188,208,184,209,128,208,181,209,130,208,181,208,177,209,143,209,129,208,178,208,
+190,208,181,208,178,208,184,208,180,208,181,209,135,208,181,208,179,208,190,209,
+141,209,130,208,184,208,188,209,129,209,135,208,181,209,130,209,130,208,181,208,
+188,209,139,209,134,208,181,208,189,209,139,209,129,209,130,208,176,208,187,208,
+178,208,181,208,180,209,140,209,130,208,181,208,188,208,181,208,178,208,190,208,
+180,209,139,209,130,208,181,208,177,208,181,208,178,209,139,209,136,208,181,208,
+189,208,176,208,188,208,184,209,130,208,184,208,191,208,176,209,130,208,190,208,
+188,209,131,208,191,209,128,208,176,208,178,208,187,208,184,209,134,208,176,208,
+190,208,180,208,189,208,176,208,179,208,190,208,180,209,139,208,183,208,189,208,
+176,209,142,208,188,208,190,208,179,209,131,208,180,209,128,209,131,208,179,208,
+178,209,129,208,181,208,185,208,184,208,180,208,181,209,130,208,186,208,184,208,
+189,208,190,208,190,208,180,208,189,208,190,208,180,208,181,208,187,208,176,208,
+180,208,181,208,187,208,181,209,129,209,128,208,190,208,186,208,184,209,142,208,
+189,209,143,208,178,208,181,209,129,209,140,208,149,209,129,209,130,209,140,209,
+128,208,176,208,183,208,176,208,189,208,176,209,136,208,184,216,167,217,132,217,
+132,217,135,216,167,217,132,216,170,217,138,216,172,217,133,217,138,216,185,216,
+174,216,167,216,181,216,169,216,167,217,132,216,176,217,138,216,185,217,132,217,
+138,217,135,216,172,216,175,217,138,216,175,216,167,217,132,216,162,217,134,216,
+167,217,132,216,177,216,175,216,170,216,173,217,131,217,133,216,181,217,129,216,
+173,216,169,217,131,216,167,217,134,216,170,216,167,217,132,217,132,217,138,217,
+138,217,131,217,136,217,134,216,180,216,168,217,131,216,169,217,129,217,138,217,
+135,216,167,216,168,217,134,216,167,216,170,216,173,217,136,216,167,216,161,216,
+163,217,131,216,171,216,177,216,174,217,132,216,167,217,132,216,167,217,132,216,
+173,216,168,216,175,217,132,217,138,217,132,216,175,216,177,217,136,216,179,216,
+167,216,182,216,186,216,183,216,170,217,131,217,136,217,134,217,135,217,134,216,
+167,217,131,216,179,216,167,216,173,216,169,217,134,216,167,216,175,217,138,216,
+167,217,132,216,183,216,168,216,185,217,132,217,138,217,131,216,180,217,131,216,
+177,216,167,217,138,217,133,217,131,217,134,217,133,217,134,217,135,216,167,216,
+180,216,177,217,131,216,169,216,177,216,166,217,138,216,179,217,134,216,180,217,
+138,216,183,217,133,216,167,216,176,216,167,216,167,217,132,217,129,217,134,216,
+180,216,168,216,167,216,168,216,170,216,185,216,168,216,177,216,177,216,173,217,
+133,216,169,217,131,216,167,217,129,216,169,217,138,217,130,217,136,217,132,217,
+133,216,177,217,131,216,178,217,131,217,132,217,133,216,169,216,163,216,173,217,
+133,216,175,217,130,217,132,216,168,217,138,217,138,216,185,217,134,217,138,216,
+181,217,136,216,177,216,169,216,183,216,177,217,138,217,130,216,180,216,167,216,
+177,217,131,216,172,217,136,216,167,217,132,216,163,216,174,216,177,217,137,217,
+133,216,185,217,134,216,167,216,167,216,168,216,173,216,171,216,185,216,177,217,
+136,216,182,216,168,216,180,217,131,217,132,217,133,216,179,216,172,217,132,216,
+168,217,134,216,167,217,134,216,174,216,167,217,132,216,175,217,131,216,170,216,
+167,216,168,217,131,217,132,217,138,216,169,216,168,216,175,217,136,217,134,216,
+163,217,138,216,182,216,167,217,138,217,136,216,172,216,175,217,129,216,177,217,
+138,217,130,217,131,216,170,216,168,216,170,216,163,217,129,216,182,217,132,217,
+133,216,183,216,168,216,174,216,167,217,131,216,171,216,177,216,168,216,167,216,
+177,217,131,216,167,217,129,216,182,217,132,216,167,216,173,217,132,217,137,217,
+134,217,129,216,179,217,135,216,163,217,138,216,167,217,133,216,177,216,175,217,
+136,216,175,216,163,217,134,217,135,216,167,216,175,217,138,217,134,216,167,216,
+167,217,132,216,167,217,134,217,133,216,185,216,177,216,182,216,170,216,185,217,
+132,217,133,216,175,216,167,216,174,217,132,217,133,217,133,217,131,217,134,0,0,
+0,0,0,0,0,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,4,0,4,0,4,0,4,0,0,1,2,3,4,5,6,7,7,6,
+5,4,3,2,1,0,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,16,17,18,19,20,21,22,23,
+23,22,21,20,19,18,17,16,24,25,26,27,28,29,30,31,31,30,29,28,27,26,25,24,255,255,
+255,255,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0,
+3,0,0,0,255,255,0,1,0,0,0,1,0,0,255,255,0,1,0,0,0,8,0,8,0,8,0,8,0,0,0,1,0,2,0,3,
+0,4,0,5,0,6,0,7,114,101,115,111,117,114,99,101,115,99,111,117,110,116,114,105,
+101,115,113,117,101,115,116,105,111,110,115,101,113,117,105,112,109,101,110,116,
+99,111,109,109,117,110,105,116,121,97,118,97,105,108,97,98,108,101,104,105,103,
+104,108,105,103,104,116,68,84,68,47,120,104,116,109,108,109,97,114,107,101,116,
+105,110,103,107,110,111,119,108,101,100,103,101,115,111,109,101,116,104,105,110,
+103,99,111,110,116,97,105,110,101,114,100,105,114,101,99,116,105,111,110,115,117
+,98,115,99,114,105,98,101,97,100,118,101,114,116,105,115,101,99,104,97,114,97,99
+,116,101,114,34,32,118,97,108,117,101,61,34,60,47,115,101,108,101,99,116,62,65,
+117,115,116,114,97,108,105,97,34,32,99,108,97,115,115,61,34,115,105,116,117,97,
+116,105,111,110,97,117,116,104,111,114,105,116,121,102,111,108,108,111,119,105,
+110,103,112,114,105,109,97,114,105,108,121,111,112,101,114,97,116,105,111,110,99
+,104,97,108,108,101,110,103,101,100,101,118,101,108,111,112,101,100,97,110,111,
+110,121,109,111,117,115,102,117,110,99,116,105,111,110,32,102,117,110,99,116,105
+,111,110,115,99,111,109,112,97,110,105,101,115,115,116,114,117,99,116,117,114,
+101,97,103,114,101,101,109,101,110,116,34,32,116,105,116,108,101,61,34,112,111,
+116,101,110,116,105,97,108,101,100,117,99,97,116,105,111,110,97,114,103,117,109,
+101,110,116,115,115,101,99,111,110,100,97,114,121,99,111,112,121,114,105,103,104
+,116,108,97,110,103,117,97,103,101,115,101,120,99,108,117,115,105,118,101,99,111
+,110,100,105,116,105,111,110,60,47,102,111,114,109,62,13,10,115,116,97,116,101,
+109,101,110,116,97,116,116,101,110,116,105,111,110,66,105,111,103,114,97,112,104
+,121,125,32,101,108,115,101,32,123,10,115,111,108,117,116,105,111,110,115,119,
+104,101,110,32,116,104,101,32,65,110,97,108,121,116,105,99,115,116,101,109,112,
+108,97,116,101,115,100,97,110,103,101,114,111,117,115,115,97,116,101,108,108,105
+,116,101,100,111,99,117,109,101,110,116,115,112,117,98,108,105,115,104,101,114,
+105,109,112,111,114,116,97,110,116,112,114,111,116,111,116,121,112,101,105,110,
+102,108,117,101,110,99,101,38,114,97,113,117,111,59,60,47,101,102,102,101,99,116
+,105,118,101,103,101,110,101,114,97,108,108,121,116,114,97,110,115,102,111,114,
+109,98,101,97,117,116,105,102,117,108,116,114,97,110,115,112,111,114,116,111,114
+,103,97,110,105,122,101,100,112,117,98,108,105,115,104,101,100,112,114,111,109,
+105,110,101,110,116,117,110,116,105,108,32,116,104,101,116,104,117,109,98,110,97
+,105,108,78,97,116,105,111,110,97,108,32,46,102,111,99,117,115,40,41,59,111,118,
+101,114,32,116,104,101,32,109,105,103,114,97,116,105,111,110,97,110,110,111,117,
+110,99,101,100,102,111,111,116,101,114,34,62,10,101,120,99,101,112,116,105,111,
+110,108,101,115,115,32,116,104,97,110,101,120,112,101,110,115,105,118,101,102,
+111,114,109,97,116,105,111,110,102,114,97,109,101,119,111,114,107,116,101,114,
+114,105,116,111,114,121,110,100,105,99,97,116,105,111,110,99,117,114,114,101,110
+,116,108,121,99,108,97,115,115,78,97,109,101,99,114,105,116,105,99,105,115,109,
+116,114,97,100,105,116,105,111,110,101,108,115,101,119,104,101,114,101,65,108,
+101,120,97,110,100,101,114,97,112,112,111,105,110,116,101,100,109,97,116,101,114
+,105,97,108,115,98,114,111,97,100,99,97,115,116,109,101,110,116,105,111,110,101,
+100,97,102,102,105,108,105,97,116,101,60,47,111,112,116,105,111,110,62,116,114,
+101,97,116,109,101,110,116,100,105,102,102,101,114,101,110,116,47,100,101,102,97
+,117,108,116,46,80,114,101,115,105,100,101,110,116,111,110,99,108,105,99,107,61,
+34,98,105,111,103,114,97,112,104,121,111,116,104,101,114,119,105,115,101,112,101
+,114,109,97,110,101,110,116,70,114,97,110,195,167,97,105,115,72,111,108,108,121,
+119,111,111,100,101,120,112,97,110,115,105,111,110,115,116,97,110,100,97,114,100
+,115,60,47,115,116,121,108,101,62,10,114,101,100,117,99,116,105,111,110,68,101,
+99,101,109,98,101,114,32,112,114,101,102,101,114,114,101,100,67,97,109,98,114,
+105,100,103,101,111,112,112,111,110,101,110,116,115,66,117,115,105,110,101,115,
+115,32,99,111,110,102,117,115,105,111,110,62,10,60,116,105,116,108,101,62,112,
+114,101,115,101,110,116,101,100,101,120,112,108,97,105,110,101,100,100,111,101,
+115,32,110,111,116,32,119,111,114,108,100,119,105,100,101,105,110,116,101,114,
+102,97,99,101,112,111,115,105,116,105,111,110,115,110,101,119,115,112,97,112,101
+,114,60,47,116,97,98,108,101,62,10,109,111,117,110,116,97,105,110,115,108,105,
+107,101,32,116,104,101,32,101,115,115,101,110,116,105,97,108,102,105,110,97,110,
+99,105,97,108,115,101,108,101,99,116,105,111,110,97,99,116,105,111,110,61,34,47,
+97,98,97,110,100,111,110,101,100,69,100,117,99,97,116,105,111,110,112,97,114,115
+,101,73,110,116,40,115,116,97,98,105,108,105,116,121,117,110,97,98,108,101,32,
+116,111,60,47,116,105,116,108,101,62,10,114,101,108,97,116,105,111,110,115,78,
+111,116,101,32,116,104,97,116,101,102,102,105,99,105,101,110,116,112,101,114,102
+,111,114,109,101,100,116,119,111,32,121,101,97,114,115,83,105,110,99,101,32,116,
+104,101,116,104,101,114,101,102,111,114,101,119,114,97,112,112,101,114,34,62,97,
+108,116,101,114,110,97,116,101,105,110,99,114,101,97,115,101,100,66,97,116,116,
+108,101,32,111,102,112,101,114,99,101,105,118,101,100,116,114,121,105,110,103,32
+,116,111,110,101,99,101,115,115,97,114,121,112,111,114,116,114,97,121,101,100,
+101,108,101,99,116,105,111,110,115,69,108,105,122,97,98,101,116,104,60,47,105,
+102,114,97,109,101,62,100,105,115,99,111,118,101,114,121,105,110,115,117,114,97,
+110,99,101,115,46,108,101,110,103,116,104,59,108,101,103,101,110,100,97,114,121,
+71,101,111,103,114,97,112,104,121,99,97,110,100,105,100,97,116,101,99,111,114,
+112,111,114,97,116,101,115,111,109,101,116,105,109,101,115,115,101,114,118,105,
+99,101,115,46,105,110,104,101,114,105,116,101,100,60,47,115,116,114,111,110,103,
+62,67,111,109,109,117,110,105,116,121,114,101,108,105,103,105,111,117,115,108,
+111,99,97,116,105,111,110,115,67,111,109,109,105,116,116,101,101,98,117,105,108,
+100,105,110,103,115,116,104,101,32,119,111,114,108,100,110,111,32,108,111,110,
+103,101,114,98,101,103,105,110,110,105,110,103,114,101,102,101,114,101,110,99,
+101,99,97,110,110,111,116,32,98,101,102,114,101,113,117,101,110,99,121,116,121,
+112,105,99,97,108,108,121,105,110,116,111,32,116,104,101,32,114,101,108,97,116,
+105,118,101,59,114,101,99,111,114,100,105,110,103,112,114,101,115,105,100,101,
+110,116,105,110,105,116,105,97,108,108,121,116,101,99,104,110,105,113,117,101,
+116,104,101,32,111,116,104,101,114,105,116,32,99,97,110,32,98,101,101,120,105,
+115,116,101,110,99,101,117,110,100,101,114,108,105,110,101,116,104,105,115,32,
+116,105,109,101,116,101,108,101,112,104,111,110,101,105,116,101,109,115,99,111,
+112,101,112,114,97,99,116,105,99,101,115,97,100,118,97,110,116,97,103,101,41,59,
+114,101,116,117,114,110,32,70,111,114,32,111,116,104,101,114,112,114,111,118,105
+,100,105,110,103,100,101,109,111,99,114,97,99,121,98,111,116,104,32,116,104,101,
+32,101,120,116,101,110,115,105,118,101,115,117,102,102,101,114,105,110,103,115,
+117,112,112,111,114,116,101,100,99,111,109,112,117,116,101,114,115,32,102,117,
+110,99,116,105,111,110,112,114,97,99,116,105,99,97,108,115,97,105,100,32,116,104
+,97,116,105,116,32,109,97,121,32,98,101,69,110,103,108,105,115,104,60,47,102,114
+,111,109,32,116,104,101,32,115,99,104,101,100,117,108,101,100,100,111,119,110,
+108,111,97,100,115,60,47,108,97,98,101,108,62,10,115,117,115,112,101,99,116,101,
+100,109,97,114,103,105,110,58,32,48,115,112,105,114,105,116,117,97,108,60,47,104
+,101,97,100,62,10,10,109,105,99,114,111,115,111,102,116,103,114,97,100,117,97,
+108,108,121,100,105,115,99,117,115,115,101,100,104,101,32,98,101,99,97,109,101,
+101,120,101,99,117,116,105,118,101,106,113,117,101,114,121,46,106,115,104,111,
+117,115,101,104,111,108,100,99,111,110,102,105,114,109,101,100,112,117,114,99,
+104,97,115,101,100,108,105,116,101,114,97,108,108,121,100,101,115,116,114,111,
+121,101,100,117,112,32,116,111,32,116,104,101,118,97,114,105,97,116,105,111,110,
+114,101,109,97,105,110,105,110,103,105,116,32,105,115,32,110,111,116,99,101,110,
+116,117,114,105,101,115,74,97,112,97,110,101,115,101,32,97,109,111,110,103,32,
+116,104,101,99,111,109,112,108,101,116,101,100,97,108,103,111,114,105,116,104,
+109,105,110,116,101,114,101,115,116,115,114,101,98,101,108,108,105,111,110,117,
+110,100,101,102,105,110,101,100,101,110,99,111,117,114,97,103,101,114,101,115,
+105,122,97,98,108,101,105,110,118,111,108,118,105,110,103,115,101,110,115,105,
+116,105,118,101,117,110,105,118,101,114,115,97,108,112,114,111,118,105,115,105,
+111,110,40,97,108,116,104,111,117,103,104,102,101,97,116,117,114,105,110,103,99,
+111,110,100,117,99,116,101,100,41,44,32,119,104,105,99,104,32,99,111,110,116,105
+,110,117,101,100,45,104,101,97,100,101,114,34,62,70,101,98,114,117,97,114,121,32
+,110,117,109,101,114,111,117,115,32,111,118,101,114,102,108,111,119,58,99,111,
+109,112,111,110,101,110,116,102,114,97,103,109,101,110,116,115,101,120,99,101,
+108,108,101,110,116,99,111,108,115,112,97,110,61,34,116,101,99,104,110,105,99,97
+,108,110,101,97,114,32,116,104,101,32,65,100,118,97,110,99,101,100,32,115,111,
+117,114,99,101,32,111,102,101,120,112,114,101,115,115,101,100,72,111,110,103,32,
+75,111,110,103,32,70,97,99,101,98,111,111,107,109,117,108,116,105,112,108,101,32
+,109,101,99,104,97,110,105,115,109,101,108,101,118,97,116,105,111,110,111,102,
+102,101,110,115,105,118,101,60,47,102,111,114,109,62,10,9,115,112,111,110,115,
+111,114,101,100,100,111,99,117,109,101,110,116,46,111,114,32,38,113,117,111,116,
+59,116,104,101,114,101,32,97,114,101,116,104,111,115,101,32,119,104,111,109,111,
+118,101,109,101,110,116,115,112,114,111,99,101,115,115,101,115,100,105,102,102,
+105,99,117,108,116,115,117,98,109,105,116,116,101,100,114,101,99,111,109,109,101
+,110,100,99,111,110,118,105,110,99,101,100,112,114,111,109,111,116,105,110,103,
+34,32,119,105,100,116,104,61,34,46,114,101,112,108,97,99,101,40,99,108,97,115,
+115,105,99,97,108,99,111,97,108,105,116,105,111,110,104,105,115,32,102,105,114,
+115,116,100,101,99,105,115,105,111,110,115,97,115,115,105,115,116,97,110,116,105
+,110,100,105,99,97,116,101,100,101,118,111,108,117,116,105,111,110,45,119,114,97
+,112,112,101,114,34,101,110,111,117,103,104,32,116,111,97,108,111,110,103,32,116
+,104,101,100,101,108,105,118,101,114,101,100,45,45,62,13,10,60,33,45,45,65,109,
+101,114,105,99,97,110,32,112,114,111,116,101,99,116,101,100,78,111,118,101,109,
+98,101,114,32,60,47,115,116,121,108,101,62,60,102,117,114,110,105,116,117,114,
+101,73,110,116,101,114,110,101,116,32,32,111,110,98,108,117,114,61,34,115,117,
+115,112,101,110,100,101,100,114,101,99,105,112,105,101,110,116,98,97,115,101,100
+,32,111,110,32,77,111,114,101,111,118,101,114,44,97,98,111,108,105,115,104,101,
+100,99,111,108,108,101,99,116,101,100,119,101,114,101,32,109,97,100,101,101,109,
+111,116,105,111,110,97,108,101,109,101,114,103,101,110,99,121,110,97,114,114,97,
+116,105,118,101,97,100,118,111,99,97,116,101,115,112,120,59,98,111,114,100,101,
+114,99,111,109,109,105,116,116,101,100,100,105,114,61,34,108,116,114,34,101,109,
+112,108,111,121,101,101,115,114,101,115,101,97,114,99,104,46,32,115,101,108,101,
+99,116,101,100,115,117,99,99,101,115,115,111,114,99,117,115,116,111,109,101,114,
+115,100,105,115,112,108,97,121,101,100,83,101,112,116,101,109,98,101,114,97,100,
+100,67,108,97,115,115,40,70,97,99,101,98,111,111,107,32,115,117,103,103,101,115,
+116,101,100,97,110,100,32,108,97,116,101,114,111,112,101,114,97,116,105,110,103,
+101,108,97,98,111,114,97,116,101,83,111,109,101,116,105,109,101,115,73,110,115,
+116,105,116,117,116,101,99,101,114,116,97,105,110,108,121,105,110,115,116,97,108
+,108,101,100,102,111,108,108,111,119,101,114,115,74,101,114,117,115,97,108,101,
+109,116,104,101,121,32,104,97,118,101,99,111,109,112,117,116,105,110,103,103,101
+,110,101,114,97,116,101,100,112,114,111,118,105,110,99,101,115,103,117,97,114,97
+,110,116,101,101,97,114,98,105,116,114,97,114,121,114,101,99,111,103,110,105,122
+,101,119,97,110,116,101,100,32,116,111,112,120,59,119,105,100,116,104,58,116,104
+,101,111,114,121,32,111,102,98,101,104,97,118,105,111,117,114,87,104,105,108,101
+,32,116,104,101,101,115,116,105,109,97,116,101,100,98,101,103,97,110,32,116,111,
+32,105,116,32,98,101,99,97,109,101,109,97,103,110,105,116,117,100,101,109,117,
+115,116,32,104,97,118,101,109,111,114,101,32,116,104,97,110,68,105,114,101,99,
+116,111,114,121,101,120,116,101,110,115,105,111,110,115,101,99,114,101,116,97,
+114,121,110,97,116,117,114,97,108,108,121,111,99,99,117,114,114,105,110,103,118,
+97,114,105,97,98,108,101,115,103,105,118,101,110,32,116,104,101,112,108,97,116,
+102,111,114,109,46,60,47,108,97,98,101,108,62,60,102,97,105,108,101,100,32,116,
+111,99,111,109,112,111,117,110,100,115,107,105,110,100,115,32,111,102,32,115,111
+,99,105,101,116,105,101,115,97,108,111,110,103,115,105,100,101,32,45,45,38,103,
+116,59,10,10,115,111,117,116,104,119,101,115,116,116,104,101,32,114,105,103,104,
+116,114,97,100,105,97,116,105,111,110,109,97,121,32,104,97,118,101,32,117,110,
+101,115,99,97,112,101,40,115,112,111,107,101,110,32,105,110,34,32,104,114,101,
+102,61,34,47,112,114,111,103,114,97,109,109,101,111,110,108,121,32,116,104,101,
+32,99,111,109,101,32,102,114,111,109,100,105,114,101,99,116,111,114,121,98,117,
+114,105,101,100,32,105,110,97,32,115,105,109,105,108,97,114,116,104,101,121,32,
+119,101,114,101,60,47,102,111,110,116,62,60,47,78,111,114,119,101,103,105,97,110
+,115,112,101,99,105,102,105,101,100,112,114,111,100,117,99,105,110,103,112,97,
+115,115,101,110,103,101,114,40,110,101,119,32,68,97,116,101,116,101,109,112,111,
+114,97,114,121,102,105,99,116,105,111,110,97,108,65,102,116,101,114,32,116,104,
+101,101,113,117,97,116,105,111,110,115,100,111,119,110,108,111,97,100,46,114,101
+,103,117,108,97,114,108,121,100,101,118,101,108,111,112,101,114,97,98,111,118,
+101,32,116,104,101,108,105,110,107,101,100,32,116,111,112,104,101,110,111,109,
+101,110,97,112,101,114,105,111,100,32,111,102,116,111,111,108,116,105,112,34,62,
+115,117,98,115,116,97,110,99,101,97,117,116,111,109,97,116,105,99,97,115,112,101
+,99,116,32,111,102,65,109,111,110,103,32,116,104,101,99,111,110,110,101,99,116,
+101,100,101,115,116,105,109,97,116,101,115,65,105,114,32,70,111,114,99,101,115,
+121,115,116,101,109,32,111,102,111,98,106,101,99,116,105,118,101,105,109,109,101
+,100,105,97,116,101,109,97,107,105,110,103,32,105,116,112,97,105,110,116,105,110
+,103,115,99,111,110,113,117,101,114,101,100,97,114,101,32,115,116,105,108,108,
+112,114,111,99,101,100,117,114,101,103,114,111,119,116,104,32,111,102,104,101,97
+,100,101,100,32,98,121,69,117,114,111,112,101,97,110,32,100,105,118,105,115,105,
+111,110,115,109,111,108,101,99,117,108,101,115,102,114,97,110,99,104,105,115,101
+,105,110,116,101,110,116,105,111,110,97,116,116,114,97,99,116,101,100,99,104,105
+,108,100,104,111,111,100,97,108,115,111,32,117,115,101,100,100,101,100,105,99,97
+,116,101,100,115,105,110,103,97,112,111,114,101,100,101,103,114,101,101,32,111,
+102,102,97,116,104,101,114,32,111,102,99,111,110,102,108,105,99,116,115,60,47,97
+,62,60,47,112,62,10,99,97,109,101,32,102,114,111,109,119,101,114,101,32,117,115,
+101,100,110,111,116,101,32,116,104,97,116,114,101,99,101,105,118,105,110,103,69,
+120,101,99,117,116,105,118,101,101,118,101,110,32,109,111,114,101,97,99,99,101,
+115,115,32,116,111,99,111,109,109,97,110,100,101,114,80,111,108,105,116,105,99,
+97,108,109,117,115,105,99,105,97,110,115,100,101,108,105,99,105,111,117,115,112,
+114,105,115,111,110,101,114,115,97,100,118,101,110,116,32,111,102,85,84,70,45,56
+,34,32,47,62,60,33,91,67,68,65,84,65,91,34,62,67,111,110,116,97,99,116,83,111,
+117,116,104,101,114,110,32,98,103,99,111,108,111,114,61,34,115,101,114,105,101,
+115,32,111,102,46,32,73,116,32,119,97,115,32,105,110,32,69,117,114,111,112,101,
+112,101,114,109,105,116,116,101,100,118,97,108,105,100,97,116,101,46,97,112,112,
+101,97,114,105,110,103,111,102,102,105,99,105,97,108,115,115,101,114,105,111,117
+,115,108,121,45,108,97,110,103,117,97,103,101,105,110,105,116,105,97,116,101,100
+,101,120,116,101,110,100,105,110,103,108,111,110,103,45,116,101,114,109,105,110,
+102,108,97,116,105,111,110,115,117,99,104,32,116,104,97,116,103,101,116,67,111,
+111,107,105,101,109,97,114,107,101,100,32,98,121,60,47,98,117,116,116,111,110,62
+,105,109,112,108,101,109,101,110,116,98,117,116,32,105,116,32,105,115,105,110,99
+,114,101,97,115,101,115,100,111,119,110,32,116,104,101,32,114,101,113,117,105,
+114,105,110,103,100,101,112,101,110,100,101,110,116,45,45,62,10,60,33,45,45,32,
+105,110,116,101,114,118,105,101,119,87,105,116,104,32,116,104,101,32,99,111,112,
+105,101,115,32,111,102,99,111,110,115,101,110,115,117,115,119,97,115,32,98,117,
+105,108,116,86,101,110,101,122,117,101,108,97,40,102,111,114,109,101,114,108,121
+,116,104,101,32,115,116,97,116,101,112,101,114,115,111,110,110,101,108,115,116,
+114,97,116,101,103,105,99,102,97,118,111,117,114,32,111,102,105,110,118,101,110,
+116,105,111,110,87,105,107,105,112,101,100,105,97,99,111,110,116,105,110,101,110
+,116,118,105,114,116,117,97,108,108,121,119,104,105,99,104,32,119,97,115,112,114
+,105,110,99,105,112,108,101,67,111,109,112,108,101,116,101,32,105,100,101,110,
+116,105,99,97,108,115,104,111,119,32,116,104,97,116,112,114,105,109,105,116,105,
+118,101,97,119,97,121,32,102,114,111,109,109,111,108,101,99,117,108,97,114,112,
+114,101,99,105,115,101,108,121,100,105,115,115,111,108,118,101,100,85,110,100,
+101,114,32,116,104,101,118,101,114,115,105,111,110,61,34,62,38,110,98,115,112,59
+,60,47,73,116,32,105,115,32,116,104,101,32,84,104,105,115,32,105,115,32,119,105,
+108,108,32,104,97,118,101,111,114,103,97,110,105,115,109,115,115,111,109,101,32,
+116,105,109,101,70,114,105,101,100,114,105,99,104,119,97,115,32,102,105,114,115,
+116,116,104,101,32,111,110,108,121,32,102,97,99,116,32,116,104,97,116,102,111,
+114,109,32,105,100,61,34,112,114,101,99,101,100,105,110,103,84,101,99,104,110,
+105,99,97,108,112,104,121,115,105,99,105,115,116,111,99,99,117,114,115,32,105,
+110,110,97,118,105,103,97,116,111,114,115,101,99,116,105,111,110,34,62,115,112,
+97,110,32,105,100,61,34,115,111,117,103,104,116,32,116,111,98,101,108,111,119,32
+,116,104,101,115,117,114,118,105,118,105,110,103,125,60,47,115,116,121,108,101,
+62,104,105,115,32,100,101,97,116,104,97,115,32,105,110,32,116,104,101,99,97,117,
+115,101,100,32,98,121,112,97,114,116,105,97,108,108,121,101,120,105,115,116,105,
+110,103,32,117,115,105,110,103,32,116,104,101,119,97,115,32,103,105,118,101,110,
+97,32,108,105,115,116,32,111,102,108,101,118,101,108,115,32,111,102,110,111,116,
+105,111,110,32,111,102,79,102,102,105,99,105,97,108,32,100,105,115,109,105,115,
+115,101,100,115,99,105,101,110,116,105,115,116,114,101,115,101,109,98,108,101,
+115,100,117,112,108,105,99,97,116,101,101,120,112,108,111,115,105,118,101,114,
+101,99,111,118,101,114,101,100,97,108,108,32,111,116,104,101,114,103,97,108,108,
+101,114,105,101,115,123,112,97,100,100,105,110,103,58,112,101,111,112,108,101,32
+,111,102,114,101,103,105,111,110,32,111,102,97,100,100,114,101,115,115,101,115,
+97,115,115,111,99,105,97,116,101,105,109,103,32,97,108,116,61,34,105,110,32,109,
+111,100,101,114,110,115,104,111,117,108,100,32,98,101,109,101,116,104,111,100,32
+,111,102,114,101,112,111,114,116,105,110,103,116,105,109,101,115,116,97,109,112,
+110,101,101,100,101,100,32,116,111,116,104,101,32,71,114,101,97,116,114,101,103,
+97,114,100,105,110,103,115,101,101,109,101,100,32,116,111,118,105,101,119,101,
+100,32,97,115,105,109,112,97,99,116,32,111,110,105,100,101,97,32,116,104,97,116,
+116,104,101,32,87,111,114,108,100,104,101,105,103,104,116,32,111,102,101,120,112
+,97,110,100,105,110,103,84,104,101,115,101,32,97,114,101,99,117,114,114,101,110,
+116,34,62,99,97,114,101,102,117,108,108,121,109,97,105,110,116,97,105,110,115,99
+,104,97,114,103,101,32,111,102,67,108,97,115,115,105,99,97,108,97,100,100,114,
+101,115,115,101,100,112,114,101,100,105,99,116,101,100,111,119,110,101,114,115,
+104,105,112,60,100,105,118,32,105,100,61,34,114,105,103,104,116,34,62,13,10,114,
+101,115,105,100,101,110,99,101,108,101,97,118,101,32,116,104,101,99,111,110,116,
+101,110,116,34,62,97,114,101,32,111,102,116,101,110,32,32,125,41,40,41,59,13,10,
+112,114,111,98,97,98,108,121,32,80,114,111,102,101,115,115,111,114,45,98,117,116
+,116,111,110,34,32,114,101,115,112,111,110,100,101,100,115,97,121,115,32,116,104
+,97,116,104,97,100,32,116,111,32,98,101,112,108,97,99,101,100,32,105,110,72,117,
+110,103,97,114,105,97,110,115,116,97,116,117,115,32,111,102,115,101,114,118,101,
+115,32,97,115,85,110,105,118,101,114,115,97,108,101,120,101,99,117,116,105,111,
+110,97,103,103,114,101,103,97,116,101,102,111,114,32,119,104,105,99,104,105,110,
+102,101,99,116,105,111,110,97,103,114,101,101,100,32,116,111,104,111,119,101,118
+,101,114,44,32,112,111,112,117,108,97,114,34,62,112,108,97,99,101,100,32,111,110
+,99,111,110,115,116,114,117,99,116,101,108,101,99,116,111,114,97,108,115,121,109
+,98,111,108,32,111,102,105,110,99,108,117,100,105,110,103,114,101,116,117,114,
+110,32,116,111,97,114,99,104,105,116,101,99,116,67,104,114,105,115,116,105,97,
+110,112,114,101,118,105,111,117,115,32,108,105,118,105,110,103,32,105,110,101,97
+,115,105,101,114,32,116,111,112,114,111,102,101,115,115,111,114,10,38,108,116,59
+,33,45,45,32,101,102,102,101,99,116,32,111,102,97,110,97,108,121,116,105,99,115,
+119,97,115,32,116,97,107,101,110,119,104,101,114,101,32,116,104,101,116,111,111,
+107,32,111,118,101,114,98,101,108,105,101,102,32,105,110,65,102,114,105,107,97,
+97,110,115,97,115,32,102,97,114,32,97,115,112,114,101,118,101,110,116,101,100,
+119,111,114,107,32,119,105,116,104,97,32,115,112,101,99,105,97,108,60,102,105,
+101,108,100,115,101,116,67,104,114,105,115,116,109,97,115,82,101,116,114,105,101
+,118,101,100,10,10,73,110,32,116,104,101,32,98,97,99,107,32,105,110,116,111,110,
+111,114,116,104,101,97,115,116,109,97,103,97,122,105,110,101,115,62,60,115,116,
+114,111,110,103,62,99,111,109,109,105,116,116,101,101,103,111,118,101,114,110,
+105,110,103,103,114,111,117,112,115,32,111,102,115,116,111,114,101,100,32,105,
+110,101,115,116,97,98,108,105,115,104,97,32,103,101,110,101,114,97,108,105,116,
+115,32,102,105,114,115,116,116,104,101,105,114,32,111,119,110,112,111,112,117,
+108,97,116,101,100,97,110,32,111,98,106,101,99,116,67,97,114,105,98,98,101,97,
+110,97,108,108,111,119,32,116,104,101,100,105,115,116,114,105,99,116,115,119,105
+,115,99,111,110,115,105,110,108,111,99,97,116,105,111,110,46,59,32,119,105,100,
+116,104,58,32,105,110,104,97,98,105,116,101,100,83,111,99,105,97,108,105,115,116
+,74,97,110,117,97,114,121,32,49,60,47,102,111,111,116,101,114,62,115,105,109,105
+,108,97,114,108,121,99,104,111,105,99,101,32,111,102,116,104,101,32,115,97,109,
+101,32,115,112,101,99,105,102,105,99,32,98,117,115,105,110,101,115,115,32,84,104
+,101,32,102,105,114,115,116,46,108,101,110,103,116,104,59,32,100,101,115,105,114
+,101,32,116,111,100,101,97,108,32,119,105,116,104,115,105,110,99,101,32,116,104,
+101,117,115,101,114,65,103,101,110,116,99,111,110,99,101,105,118,101,100,105,110
+,100,101,120,46,112,104,112,97,115,32,38,113,117,111,116,59,101,110,103,97,103,
+101,32,105,110,114,101,99,101,110,116,108,121,44,102,101,119,32,121,101,97,114,
+115,119,101,114,101,32,97,108,115,111,10,60,104,101,97,100,62,10,60,101,100,105,
+116,101,100,32,98,121,97,114,101,32,107,110,111,119,110,99,105,116,105,101,115,
+32,105,110,97,99,99,101,115,115,107,101,121,99,111,110,100,101,109,110,101,100,
+97,108,115,111,32,104,97,118,101,115,101,114,118,105,99,101,115,44,102,97,109,
+105,108,121,32,111,102,83,99,104,111,111,108,32,111,102,99,111,110,118,101,114,
+116,101,100,110,97,116,117,114,101,32,111,102,32,108,97,110,103,117,97,103,101,
+109,105,110,105,115,116,101,114,115,60,47,111,98,106,101,99,116,62,116,104,101,
+114,101,32,105,115,32,97,32,112,111,112,117,108,97,114,115,101,113,117,101,110,
+99,101,115,97,100,118,111,99,97,116,101,100,84,104,101,121,32,119,101,114,101,97
+,110,121,32,111,116,104,101,114,108,111,99,97,116,105,111,110,61,101,110,116,101
+,114,32,116,104,101,109,117,99,104,32,109,111,114,101,114,101,102,108,101,99,116
+,101,100,119,97,115,32,110,97,109,101,100,111,114,105,103,105,110,97,108,32,97,
+32,116,121,112,105,99,97,108,119,104,101,110,32,116,104,101,121,101,110,103,105,
+110,101,101,114,115,99,111,117,108,100,32,110,111,116,114,101,115,105,100,101,
+110,116,115,119,101,100,110,101,115,100,97,121,116,104,101,32,116,104,105,114,
+100,32,112,114,111,100,117,99,116,115,74,97,110,117,97,114,121,32,50,119,104,97,
+116,32,116,104,101,121,97,32,99,101,114,116,97,105,110,114,101,97,99,116,105,111
+,110,115,112,114,111,99,101,115,115,111,114,97,102,116,101,114,32,104,105,115,
+116,104,101,32,108,97,115,116,32,99,111,110,116,97,105,110,101,100,34,62,60,47,
+100,105,118,62,10,60,47,97,62,60,47,116,100,62,100,101,112,101,110,100,32,111,
+110,115,101,97,114,99,104,34,62,10,112,105,101,99,101,115,32,111,102,99,111,109,
+112,101,116,105,110,103,82,101,102,101,114,101,110,99,101,116,101,110,110,101,
+115,115,101,101,119,104,105,99,104,32,104,97,115,32,118,101,114,115,105,111,110,
+61,60,47,115,112,97,110,62,32,60,60,47,104,101,97,100,101,114,62,103,105,118,101
+,115,32,116,104,101,104,105,115,116,111,114,105,97,110,118,97,108,117,101,61,34,
+34,62,112,97,100,100,105,110,103,58,48,118,105,101,119,32,116,104,97,116,116,111
+,103,101,116,104,101,114,44,116,104,101,32,109,111,115,116,32,119,97,115,32,102,
+111,117,110,100,115,117,98,115,101,116,32,111,102,97,116,116,97,99,107,32,111,
+110,99,104,105,108,100,114,101,110,44,112,111,105,110,116,115,32,111,102,112,101
+,114,115,111,110,97,108,32,112,111,115,105,116,105,111,110,58,97,108,108,101,103
+,101,100,108,121,67,108,101,118,101,108,97,110,100,119,97,115,32,108,97,116,101,
+114,97,110,100,32,97,102,116,101,114,97,114,101,32,103,105,118,101,110,119,97,
+115,32,115,116,105,108,108,115,99,114,111,108,108,105,110,103,100,101,115,105,
+103,110,32,111,102,109,97,107,101,115,32,116,104,101,109,117,99,104,32,108,101,
+115,115,65,109,101,114,105,99,97,110,115,46,10,10,65,102,116,101,114,32,44,32,98
+,117,116,32,116,104,101,77,117,115,101,117,109,32,111,102,108,111,117,105,115,
+105,97,110,97,40,102,114,111,109,32,116,104,101,109,105,110,110,101,115,111,116,
+97,112,97,114,116,105,99,108,101,115,97,32,112,114,111,99,101,115,115,68,111,109
+,105,110,105,99,97,110,118,111,108,117,109,101,32,111,102,114,101,116,117,114,
+110,105,110,103,100,101,102,101,110,115,105,118,101,48,48,112,120,124,114,105,
+103,104,109,97,100,101,32,102,114,111,109,109,111,117,115,101,111,118,101,114,34
+,32,115,116,121,108,101,61,34,115,116,97,116,101,115,32,111,102,40,119,104,105,
+99,104,32,105,115,99,111,110,116,105,110,117,101,115,70,114,97,110,99,105,115,99
+,111,98,117,105,108,100,105,110,103,32,119,105,116,104,111,117,116,32,97,119,105
+,116,104,32,115,111,109,101,119,104,111,32,119,111,117,108,100,97,32,102,111,114
+,109,32,111,102,97,32,112,97,114,116,32,111,102,98,101,102,111,114,101,32,105,
+116,107,110,111,119,110,32,97,115,32,32,83,101,114,118,105,99,101,115,108,111,99
+,97,116,105,111,110,32,97,110,100,32,111,102,116,101,110,109,101,97,115,117,114,
+105,110,103,97,110,100,32,105,116,32,105,115,112,97,112,101,114,98,97,99,107,118
+,97,108,117,101,115,32,111,102,13,10,60,116,105,116,108,101,62,61,32,119,105,110
+,100,111,119,46,100,101,116,101,114,109,105,110,101,101,114,38,113,117,111,116,
+59,32,112,108,97,121,101,100,32,98,121,97,110,100,32,101,97,114,108,121,60,47,99
+,101,110,116,101,114,62,102,114,111,109,32,116,104,105,115,116,104,101,32,116,
+104,114,101,101,112,111,119,101,114,32,97,110,100,111,102,32,38,113,117,111,116,
+59,105,110,110,101,114,72,84,77,76,60,97,32,104,114,101,102,61,34,121,58,105,110
+,108,105,110,101,59,67,104,117,114,99,104,32,111,102,116,104,101,32,101,118,101,
+110,116,118,101,114,121,32,104,105,103,104,111,102,102,105,99,105,97,108,32,45,
+104,101,105,103,104,116,58,32,99,111,110,116,101,110,116,61,34,47,99,103,105,45,
+98,105,110,47,116,111,32,99,114,101,97,116,101,97,102,114,105,107,97,97,110,115,
+101,115,112,101,114,97,110,116,111,102,114,97,110,195,167,97,105,115,108,97,116,
+118,105,101,197,161,117,108,105,101,116,117,118,105,197,179,196,140,101,197,161,
+116,105,110,97,196,141,101,197,161,116,105,110,97,224,185,132,224,184,151,224,
+184,162,230,151,165,230,156,172,232,170,158,231,174,128,228,189,147,229,173,151,
+231,185,129,233,171,148,229,173,151,237,149,156,234,181,173,236,150,180,228,184,
+186,228,187,128,228,185,136,232,174,161,231,174,151,230,156,186,231,172,148,232,
+174,176,230,156,172,232,168,142,232,171,150,229,141,128,230,156,141,229,138,161,
+229,153,168,228,186,146,232,129,148,231,189,145,230,136,191,229,156,176,228,186,
+167,228,191,177,228,185,144,233,131,168,229,135,186,231,137,136,231,164,190,230,
+142,146,232,161,140,230,166,156,233,131,168,232,144,189,230,160,188,232,191,155,
+228,184,128,230,173,165,230,148,175,228,187,152,229,174,157,233,170,140,232,175,
+129,231,160,129,229,167,148,229,145,152,228,188,154,230,149,176,230,141,174,229,
+186,147,230,182,136,232,180,185,232,128,133,229,138,158,229,133,172,229,174,164,
+232,174,168,232,174,186,229,140,186,230,183,177,229,156,179,229,184,130,230,146,
+173,230,148,190,229,153,168,229,140,151,228,186,172,229,184,130,229,164,167,229,
+173,166,231,148,159,232,182,138,230,157,165,232,182,138,231,174,161,231,144,134,
+229,145,152,228,191,161,230,129,175,231,189,145,115,101,114,118,105,99,105,111,
+115,97,114,116,195,173,99,117,108,111,97,114,103,101,110,116,105,110,97,98,97,
+114,99,101,108,111,110,97,99,117,97,108,113,117,105,101,114,112,117,98,108,105,
+99,97,100,111,112,114,111,100,117,99,116,111,115,112,111,108,195,173,116,105,99,
+97,114,101,115,112,117,101,115,116,97,119,105,107,105,112,101,100,105,97,115,105
+,103,117,105,101,110,116,101,98,195,186,115,113,117,101,100,97,99,111,109,117,
+110,105,100,97,100,115,101,103,117,114,105,100,97,100,112,114,105,110,99,105,112
+,97,108,112,114,101,103,117,110,116,97,115,99,111,110,116,101,110,105,100,111,
+114,101,115,112,111,110,100,101,114,118,101,110,101,122,117,101,108,97,112,114,
+111,98,108,101,109,97,115,100,105,99,105,101,109,98,114,101,114,101,108,97,99,
+105,195,179,110,110,111,118,105,101,109,98,114,101,115,105,109,105,108,97,114,
+101,115,112,114,111,121,101,99,116,111,115,112,114,111,103,114,97,109,97,115,105
+,110,115,116,105,116,117,116,111,97,99,116,105,118,105,100,97,100,101,110,99,117
+,101,110,116,114,97,101,99,111,110,111,109,195,173,97,105,109,195,161,103,101,
+110,101,115,99,111,110,116,97,99,116,97,114,100,101,115,99,97,114,103,97,114,110
+,101,99,101,115,97,114,105,111,97,116,101,110,99,105,195,179,110,116,101,108,195
+,169,102,111,110,111,99,111,109,105,115,105,195,179,110,99,97,110,99,105,111,110
+,101,115,99,97,112,97,99,105,100,97,100,101,110,99,111,110,116,114,97,114,97,110
+,195,161,108,105,115,105,115,102,97,118,111,114,105,116,111,115,116,195,169,114,
+109,105,110,111,115,112,114,111,118,105,110,99,105,97,101,116,105,113,117,101,
+116,97,115,101,108,101,109,101,110,116,111,115,102,117,110,99,105,111,110,101,
+115,114,101,115,117,108,116,97,100,111,99,97,114,195,161,99,116,101,114,112,114,
+111,112,105,101,100,97,100,112,114,105,110,99,105,112,105,111,110,101,99,101,115
+,105,100,97,100,109,117,110,105,99,105,112,97,108,99,114,101,97,99,105,195,179,
+110,100,101,115,99,97,114,103,97,115,112,114,101,115,101,110,99,105,97,99,111,
+109,101,114,99,105,97,108,111,112,105,110,105,111,110,101,115,101,106,101,114,99
+,105,99,105,111,101,100,105,116,111,114,105,97,108,115,97,108,97,109,97,110,99,
+97,103,111,110,122,195,161,108,101,122,100,111,99,117,109,101,110,116,111,112,
+101,108,195,173,99,117,108,97,114,101,99,105,101,110,116,101,115,103,101,110,101
+,114,97,108,101,115,116,97,114,114,97,103,111,110,97,112,114,195,161,99,116,105,
+99,97,110,111,118,101,100,97,100,101,115,112,114,111,112,117,101,115,116,97,112,
+97,99,105,101,110,116,101,115,116,195,169,99,110,105,99,97,115,111,98,106,101,
+116,105,118,111,115,99,111,110,116,97,99,116,111,115,224,164,174,224,165,135,224
+,164,130,224,164,178,224,164,191,224,164,143,224,164,185,224,165,136,224,164,130
+,224,164,151,224,164,175,224,164,190,224,164,184,224,164,190,224,164,165,224,164
+,143,224,164,181,224,164,130,224,164,176,224,164,185,224,165,135,224,164,149,224
+,165,139,224,164,136,224,164,149,224,165,129,224,164,155,224,164,176,224,164,185
+,224,164,190,224,164,172,224,164,190,224,164,166,224,164,149,224,164,185,224,164
+,190,224,164,184,224,164,173,224,165,128,224,164,185,224,165,129,224,164,143,224
+,164,176,224,164,185,224,165,128,224,164,174,224,165,136,224,164,130,224,164,166
+,224,164,191,224,164,168,224,164,172,224,164,190,224,164,164,100,105,112,108,111
+,100,111,99,115,224,164,184,224,164,174,224,164,175,224,164,176,224,165,130,224,
+164,170,224,164,168,224,164,190,224,164,174,224,164,170,224,164,164,224,164,190,
+224,164,171,224,164,191,224,164,176,224,164,148,224,164,184,224,164,164,224,164,
+164,224,164,176,224,164,185,224,164,178,224,165,139,224,164,151,224,164,185,224,
+165,129,224,164,134,224,164,172,224,164,190,224,164,176,224,164,166,224,165,135,
+224,164,182,224,164,185,224,165,129,224,164,136,224,164,150,224,165,135,224,164,
+178,224,164,175,224,164,166,224,164,191,224,164,149,224,164,190,224,164,174,224,
+164,181,224,165,135,224,164,172,224,164,164,224,165,128,224,164,168,224,164,172,
+224,165,128,224,164,154,224,164,174,224,165,140,224,164,164,224,164,184,224,164,
+190,224,164,178,224,164,178,224,165,135,224,164,150,224,164,156,224,165,137,224,
+164,172,224,164,174,224,164,166,224,164,166,224,164,164,224,164,165,224,164,190,
+224,164,168,224,164,185,224,165,128,224,164,182,224,164,185,224,164,176,224,164,
+133,224,164,178,224,164,151,224,164,149,224,164,173,224,165,128,224,164,168,224,
+164,151,224,164,176,224,164,170,224,164,190,224,164,184,224,164,176,224,164,190,
+224,164,164,224,164,149,224,164,191,224,164,143,224,164,137,224,164,184,224,165,
+135,224,164,151,224,164,175,224,165,128,224,164,185,224,165,130,224,164,129,224,
+164,134,224,164,151,224,165,135,224,164,159,224,165,128,224,164,174,224,164,150,
+224,165,139,224,164,156,224,164,149,224,164,190,224,164,176,224,164,133,224,164,
+173,224,165,128,224,164,151,224,164,175,224,165,135,224,164,164,224,165,129,224,
+164,174,224,164,181,224,165,139,224,164,159,224,164,166,224,165,135,224,164,130,
+224,164,133,224,164,151,224,164,176,224,164,144,224,164,184,224,165,135,224,164,
+174,224,165,135,224,164,178,224,164,178,224,164,151,224,164,190,224,164,185,224,
+164,190,224,164,178,224,164,138,224,164,170,224,164,176,224,164,154,224,164,190,
+224,164,176,224,164,144,224,164,184,224,164,190,224,164,166,224,165,135,224,164,
+176,224,164,156,224,164,191,224,164,184,224,164,166,224,164,191,224,164,178,224,
+164,172,224,164,130,224,164,166,224,164,172,224,164,168,224,164,190,224,164,185,
+224,165,130,224,164,130,224,164,178,224,164,190,224,164,150,224,164,156,224,165,
+128,224,164,164,224,164,172,224,164,159,224,164,168,224,164,174,224,164,191,224,
+164,178,224,164,135,224,164,184,224,165,135,224,164,134,224,164,168,224,165,135,
+224,164,168,224,164,175,224,164,190,224,164,149,224,165,129,224,164,178,224,164,
+178,224,165,137,224,164,151,224,164,173,224,164,190,224,164,151,224,164,176,224,
+165,135,224,164,178,224,164,156,224,164,151,224,164,185,224,164,176,224,164,190,
+224,164,174,224,164,178,224,164,151,224,165,135,224,164,170,224,165,135,224,164,
+156,224,164,185,224,164,190,224,164,165,224,164,135,224,164,184,224,165,128,224,
+164,184,224,164,185,224,165,128,224,164,149,224,164,178,224,164,190,224,164,160,
+224,165,128,224,164,149,224,164,185,224,164,190,224,164,129,224,164,166,224,165,
+130,224,164,176,224,164,164,224,164,185,224,164,164,224,164,184,224,164,190,224,
+164,164,224,164,175,224,164,190,224,164,166,224,164,134,224,164,175,224,164,190,
+224,164,170,224,164,190,224,164,149,224,164,149,224,165,140,224,164,168,224,164,
+182,224,164,190,224,164,174,224,164,166,224,165,135,224,164,150,224,164,175,224,
+164,185,224,165,128,224,164,176,224,164,190,224,164,175,224,164,150,224,165,129,
+224,164,166,224,164,178,224,164,151,224,165,128,99,97,116,101,103,111,114,105,
+101,115,101,120,112,101,114,105,101,110,99,101,60,47,116,105,116,108,101,62,13,
+10,67,111,112,121,114,105,103,104,116,32,106,97,118,97,115,99,114,105,112,116,99
+,111,110,100,105,116,105,111,110,115,101,118,101,114,121,116,104,105,110,103,60,
+112,32,99,108,97,115,115,61,34,116,101,99,104,110,111,108,111,103,121,98,97,99,
+107,103,114,111,117,110,100,60,97,32,99,108,97,115,115,61,34,109,97,110,97,103,
+101,109,101,110,116,38,99,111,112,121,59,32,50,48,49,106,97,118,97,83,99,114,105
+,112,116,99,104,97,114,97,99,116,101,114,115,98,114,101,97,100,99,114,117,109,98
+,116,104,101,109,115,101,108,118,101,115,104,111,114,105,122,111,110,116,97,108,
+103,111,118,101,114,110,109,101,110,116,67,97,108,105,102,111,114,110,105,97,97,
+99,116,105,118,105,116,105,101,115,100,105,115,99,111,118,101,114,101,100,78,97,
+118,105,103,97,116,105,111,110,116,114,97,110,115,105,116,105,111,110,99,111,110
+,110,101,99,116,105,111,110,110,97,118,105,103,97,116,105,111,110,97,112,112,101
+,97,114,97,110,99,101,60,47,116,105,116,108,101,62,60,109,99,104,101,99,107,98,
+111,120,34,32,116,101,99,104,110,105,113,117,101,115,112,114,111,116,101,99,116,
+105,111,110,97,112,112,97,114,101,110,116,108,121,97,115,32,119,101,108,108,32,
+97,115,117,110,116,39,44,32,39,85,65,45,114,101,115,111,108,117,116,105,111,110,
+111,112,101,114,97,116,105,111,110,115,116,101,108,101,118,105,115,105,111,110,
+116,114,97,110,115,108,97,116,101,100,87,97,115,104,105,110,103,116,111,110,110,
+97,118,105,103,97,116,111,114,46,32,61,32,119,105,110,100,111,119,46,105,109,112
+,114,101,115,115,105,111,110,38,108,116,59,98,114,38,103,116,59,108,105,116,101,
+114,97,116,117,114,101,112,111,112,117,108,97,116,105,111,110,98,103,99,111,108,
+111,114,61,34,35,101,115,112,101,99,105,97,108,108,121,32,99,111,110,116,101,110
+,116,61,34,112,114,111,100,117,99,116,105,111,110,110,101,119,115,108,101,116,
+116,101,114,112,114,111,112,101,114,116,105,101,115,100,101,102,105,110,105,116,
+105,111,110,108,101,97,100,101,114,115,104,105,112,84,101,99,104,110,111,108,111
+,103,121,80,97,114,108,105,97,109,101,110,116,99,111,109,112,97,114,105,115,111,
+110,117,108,32,99,108,97,115,115,61,34,46,105,110,100,101,120,79,102,40,34,99,
+111,110,99,108,117,115,105,111,110,100,105,115,99,117,115,115,105,111,110,99,111
+,109,112,111,110,101,110,116,115,98,105,111,108,111,103,105,99,97,108,82,101,118
+,111,108,117,116,105,111,110,95,99,111,110,116,97,105,110,101,114,117,110,100,
+101,114,115,116,111,111,100,110,111,115,99,114,105,112,116,62,60,112,101,114,109
+,105,115,115,105,111,110,101,97,99,104,32,111,116,104,101,114,97,116,109,111,115
+,112,104,101,114,101,32,111,110,102,111,99,117,115,61,34,60,102,111,114,109,32,
+105,100,61,34,112,114,111,99,101,115,115,105,110,103,116,104,105,115,46,118,97,
+108,117,101,103,101,110,101,114,97,116,105,111,110,67,111,110,102,101,114,101,
+110,99,101,115,117,98,115,101,113,117,101,110,116,119,101,108,108,45,107,110,111
+,119,110,118,97,114,105,97,116,105,111,110,115,114,101,112,117,116,97,116,105,
+111,110,112,104,101,110,111,109,101,110,111,110,100,105,115,99,105,112,108,105,
+110,101,108,111,103,111,46,112,110,103,34,32,40,100,111,99,117,109,101,110,116,
+44,98,111,117,110,100,97,114,105,101,115,101,120,112,114,101,115,115,105,111,110
+,115,101,116,116,108,101,109,101,110,116,66,97,99,107,103,114,111,117,110,100,
+111,117,116,32,111,102,32,116,104,101,101,110,116,101,114,112,114,105,115,101,40
+,34,104,116,116,112,115,58,34,32,117,110,101,115,99,97,112,101,40,34,112,97,115,
+115,119,111,114,100,34,32,100,101,109,111,99,114,97,116,105,99,60,97,32,104,114,
+101,102,61,34,47,119,114,97,112,112,101,114,34,62,10,109,101,109,98,101,114,115,
+104,105,112,108,105,110,103,117,105,115,116,105,99,112,120,59,112,97,100,100,105
+,110,103,112,104,105,108,111,115,111,112,104,121,97,115,115,105,115,116,97,110,
+99,101,117,110,105,118,101,114,115,105,116,121,102,97,99,105,108,105,116,105,101
+,115,114,101,99,111,103,110,105,122,101,100,112,114,101,102,101,114,101,110,99,
+101,105,102,32,40,116,121,112,101,111,102,109,97,105,110,116,97,105,110,101,100,
+118,111,99,97,98,117,108,97,114,121,104,121,112,111,116,104,101,115,105,115,46,
+115,117,98,109,105,116,40,41,59,38,97,109,112,59,110,98,115,112,59,97,110,110,
+111,116,97,116,105,111,110,98,101,104,105,110,100,32,116,104,101,70,111,117,110,
+100,97,116,105,111,110,112,117,98,108,105,115,104,101,114,34,97,115,115,117,109,
+112,116,105,111,110,105,110,116,114,111,100,117,99,101,100,99,111,114,114,117,
+112,116,105,111,110,115,99,105,101,110,116,105,115,116,115,101,120,112,108,105,
+99,105,116,108,121,105,110,115,116,101,97,100,32,111,102,100,105,109,101,110,115
+,105,111,110,115,32,111,110,67,108,105,99,107,61,34,99,111,110,115,105,100,101,
+114,101,100,100,101,112,97,114,116,109,101,110,116,111,99,99,117,112,97,116,105,
+111,110,115,111,111,110,32,97,102,116,101,114,105,110,118,101,115,116,109,101,
+110,116,112,114,111,110,111,117,110,99,101,100,105,100,101,110,116,105,102,105,
+101,100,101,120,112,101,114,105,109,101,110,116,77,97,110,97,103,101,109,101,110
+,116,103,101,111,103,114,97,112,104,105,99,34,32,104,101,105,103,104,116,61,34,
+108,105,110,107,32,114,101,108,61,34,46,114,101,112,108,97,99,101,40,47,100,101,
+112,114,101,115,115,105,111,110,99,111,110,102,101,114,101,110,99,101,112,117,
+110,105,115,104,109,101,110,116,101,108,105,109,105,110,97,116,101,100,114,101,
+115,105,115,116,97,110,99,101,97,100,97,112,116,97,116,105,111,110,111,112,112,
+111,115,105,116,105,111,110,119,101,108,108,32,107,110,111,119,110,115,117,112,
+112,108,101,109,101,110,116,100,101,116,101,114,109,105,110,101,100,104,49,32,99
+,108,97,115,115,61,34,48,112,120,59,109,97,114,103,105,110,109,101,99,104,97,110
+,105,99,97,108,115,116,97,116,105,115,116,105,99,115,99,101,108,101,98,114,97,
+116,101,100,71,111,118,101,114,110,109,101,110,116,10,10,68,117,114,105,110,103,
+32,116,100,101,118,101,108,111,112,101,114,115,97,114,116,105,102,105,99,105,97,
+108,101,113,117,105,118,97,108,101,110,116,111,114,105,103,105,110,97,116,101,
+100,67,111,109,109,105,115,115,105,111,110,97,116,116,97,99,104,109,101,110,116,
+60,115,112,97,110,32,105,100,61,34,116,104,101,114,101,32,119,101,114,101,78,101
+,100,101,114,108,97,110,100,115,98,101,121,111,110,100,32,116,104,101,114,101,
+103,105,115,116,101,114,101,100,106,111,117,114,110,97,108,105,115,116,102,114,
+101,113,117,101,110,116,108,121,97,108,108,32,111,102,32,116,104,101,108,97,110,
+103,61,34,101,110,34,32,60,47,115,116,121,108,101,62,13,10,97,98,115,111,108,117
+,116,101,59,32,115,117,112,112,111,114,116,105,110,103,101,120,116,114,101,109,
+101,108,121,32,109,97,105,110,115,116,114,101,97,109,60,47,115,116,114,111,110,
+103,62,32,112,111,112,117,108,97,114,105,116,121,101,109,112,108,111,121,109,101
+,110,116,60,47,116,97,98,108,101,62,13,10,32,99,111,108,115,112,97,110,61,34,60,
+47,102,111,114,109,62,10,32,32,99,111,110,118,101,114,115,105,111,110,97,98,111,
+117,116,32,116,104,101,32,60,47,112,62,60,47,100,105,118,62,105,110,116,101,103,
+114,97,116,101,100,34,32,108,97,110,103,61,34,101,110,80,111,114,116,117,103,117
+,101,115,101,115,117,98,115,116,105,116,117,116,101,105,110,100,105,118,105,100,
+117,97,108,105,109,112,111,115,115,105,98,108,101,109,117,108,116,105,109,101,
+100,105,97,97,108,109,111,115,116,32,97,108,108,112,120,32,115,111,108,105,100,
+32,35,97,112,97,114,116,32,102,114,111,109,115,117,98,106,101,99,116,32,116,111,
+105,110,32,69,110,103,108,105,115,104,99,114,105,116,105,99,105,122,101,100,101,
+120,99,101,112,116,32,102,111,114,103,117,105,100,101,108,105,110,101,115,111,
+114,105,103,105,110,97,108,108,121,114,101,109,97,114,107,97,98,108,101,116,104,
+101,32,115,101,99,111,110,100,104,50,32,99,108,97,115,115,61,34,60,97,32,116,105
+,116,108,101,61,34,40,105,110,99,108,117,100,105,110,103,112,97,114,97,109,101,
+116,101,114,115,112,114,111,104,105,98,105,116,101,100,61,32,34,104,116,116,112,
+58,47,47,100,105,99,116,105,111,110,97,114,121,112,101,114,99,101,112,116,105,
+111,110,114,101,118,111,108,117,116,105,111,110,102,111,117,110,100,97,116,105,
+111,110,112,120,59,104,101,105,103,104,116,58,115,117,99,99,101,115,115,102,117,
+108,115,117,112,112,111,114,116,101,114,115,109,105,108,108,101,110,110,105,117,
+109,104,105,115,32,102,97,116,104,101,114,116,104,101,32,38,113,117,111,116,59,
+110,111,45,114,101,112,101,97,116,59,99,111,109,109,101,114,99,105,97,108,105,
+110,100,117,115,116,114,105,97,108,101,110,99,111,117,114,97,103,101,100,97,109,
+111,117,110,116,32,111,102,32,117,110,111,102,102,105,99,105,97,108,101,102,102,
+105,99,105,101,110,99,121,82,101,102,101,114,101,110,99,101,115,99,111,111,114,
+100,105,110,97,116,101,100,105,115,99,108,97,105,109,101,114,101,120,112,101,100
+,105,116,105,111,110,100,101,118,101,108,111,112,105,110,103,99,97,108,99,117,
+108,97,116,101,100,115,105,109,112,108,105,102,105,101,100,108,101,103,105,116,
+105,109,97,116,101,115,117,98,115,116,114,105,110,103,40,48,34,32,99,108,97,115,
+115,61,34,99,111,109,112,108,101,116,101,108,121,105,108,108,117,115,116,114,97,
+116,101,102,105,118,101,32,121,101,97,114,115,105,110,115,116,114,117,109,101,
+110,116,80,117,98,108,105,115,104,105,110,103,49,34,32,99,108,97,115,115,61,34,
+112,115,121,99,104,111,108,111,103,121,99,111,110,102,105,100,101,110,99,101,110
+,117,109,98,101,114,32,111,102,32,97,98,115,101,110,99,101,32,111,102,102,111,99
+,117,115,101,100,32,111,110,106,111,105,110,101,100,32,116,104,101,115,116,114,
+117,99,116,117,114,101,115,112,114,101,118,105,111,117,115,108,121,62,60,47,105,
+102,114,97,109,101,62,111,110,99,101,32,97,103,97,105,110,98,117,116,32,114,97,
+116,104,101,114,105,109,109,105,103,114,97,110,116,115,111,102,32,99,111,117,114
+,115,101,44,97,32,103,114,111,117,112,32,111,102,76,105,116,101,114,97,116,117,
+114,101,85,110,108,105,107,101,32,116,104,101,60,47,97,62,38,110,98,115,112,59,
+10,102,117,110,99,116,105,111,110,32,105,116,32,119,97,115,32,116,104,101,67,111
+,110,118,101,110,116,105,111,110,97,117,116,111,109,111,98,105,108,101,80,114,
+111,116,101,115,116,97,110,116,97,103,103,114,101,115,115,105,118,101,97,102,116
+,101,114,32,116,104,101,32,83,105,109,105,108,97,114,108,121,44,34,32,47,62,60,
+47,100,105,118,62,99,111,108,108,101,99,116,105,111,110,13,10,102,117,110,99,116
+,105,111,110,118,105,115,105,98,105,108,105,116,121,116,104,101,32,117,115,101,
+32,111,102,118,111,108,117,110,116,101,101,114,115,97,116,116,114,97,99,116,105,
+111,110,117,110,100,101,114,32,116,104,101,32,116,104,114,101,97,116,101,110,101
+,100,42,60,33,91,67,68,65,84,65,91,105,109,112,111,114,116,97,110,99,101,105,110
+,32,103,101,110,101,114,97,108,116,104,101,32,108,97,116,116,101,114,60,47,102,
+111,114,109,62,10,60,47,46,105,110,100,101,120,79,102,40,39,105,32,61,32,48,59,
+32,105,32,60,100,105,102,102,101,114,101,110,99,101,100,101,118,111,116,101,100,
+32,116,111,116,114,97,100,105,116,105,111,110,115,115,101,97,114,99,104,32,102,
+111,114,117,108,116,105,109,97,116,101,108,121,116,111,117,114,110,97,109,101,
+110,116,97,116,116,114,105,98,117,116,101,115,115,111,45,99,97,108,108,101,100,
+32,125,10,60,47,115,116,121,108,101,62,101,118,97,108,117,97,116,105,111,110,101
+,109,112,104,97,115,105,122,101,100,97,99,99,101,115,115,105,98,108,101,60,47,
+115,101,99,116,105,111,110,62,115,117,99,99,101,115,115,105,111,110,97,108,111,
+110,103,32,119,105,116,104,77,101,97,110,119,104,105,108,101,44,105,110,100,117,
+115,116,114,105,101,115,60,47,97,62,60,98,114,32,47,62,104,97,115,32,98,101,99,
+111,109,101,97,115,112,101,99,116,115,32,111,102,84,101,108,101,118,105,115,105,
+111,110,115,117,102,102,105,99,105,101,110,116,98,97,115,107,101,116,98,97,108,
+108,98,111,116,104,32,115,105,100,101,115,99,111,110,116,105,110,117,105,110,103
+,97,110,32,97,114,116,105,99,108,101,60,105,109,103,32,97,108,116,61,34,97,100,
+118,101,110,116,117,114,101,115,104,105,115,32,109,111,116,104,101,114,109,97,
+110,99,104,101,115,116,101,114,112,114,105,110,99,105,112,108,101,115,112,97,114
+,116,105,99,117,108,97,114,99,111,109,109,101,110,116,97,114,121,101,102,102,101
+,99,116,115,32,111,102,100,101,99,105,100,101,100,32,116,111,34,62,60,115,116,
+114,111,110,103,62,112,117,98,108,105,115,104,101,114,115,74,111,117,114,110,97,
+108,32,111,102,100,105,102,102,105,99,117,108,116,121,102,97,99,105,108,105,116,
+97,116,101,97,99,99,101,112,116,97,98,108,101,115,116,121,108,101,46,99,115,115,
+34,9,102,117,110,99,116,105,111,110,32,105,110,110,111,118,97,116,105,111,110,62
+,67,111,112,121,114,105,103,104,116,115,105,116,117,97,116,105,111,110,115,119,
+111,117,108,100,32,104,97,118,101,98,117,115,105,110,101,115,115,101,115,68,105,
+99,116,105,111,110,97,114,121,115,116,97,116,101,109,101,110,116,115,111,102,116
+,101,110,32,117,115,101,100,112,101,114,115,105,115,116,101,110,116,105,110,32,
+74,97,110,117,97,114,121,99,111,109,112,114,105,115,105,110,103,60,47,116,105,
+116,108,101,62,10,9,100,105,112,108,111,109,97,116,105,99,99,111,110,116,97,105,
+110,105,110,103,112,101,114,102,111,114,109,105,110,103,101,120,116,101,110,115,
+105,111,110,115,109,97,121,32,110,111,116,32,98,101,99,111,110,99,101,112,116,32
+,111,102,32,111,110,99,108,105,99,107,61,34,73,116,32,105,115,32,97,108,115,111,
+102,105,110,97,110,99,105,97,108,32,109,97,107,105,110,103,32,116,104,101,76,117
+,120,101,109,98,111,117,114,103,97,100,100,105,116,105,111,110,97,108,97,114,101
+,32,99,97,108,108,101,100,101,110,103,97,103,101,100,32,105,110,34,115,99,114,
+105,112,116,34,41,59,98,117,116,32,105,116,32,119,97,115,101,108,101,99,116,114,
+111,110,105,99,111,110,115,117,98,109,105,116,61,34,10,60,33,45,45,32,69,110,100
+,32,101,108,101,99,116,114,105,99,97,108,111,102,102,105,99,105,97,108,108,121,
+115,117,103,103,101,115,116,105,111,110,116,111,112,32,111,102,32,116,104,101,
+117,110,108,105,107,101,32,116,104,101,65,117,115,116,114,97,108,105,97,110,79,
+114,105,103,105,110,97,108,108,121,114,101,102,101,114,101,110,99,101,115,10,60,
+47,104,101,97,100,62,13,10,114,101,99,111,103,110,105,115,101,100,105,110,105,
+116,105,97,108,105,122,101,108,105,109,105,116,101,100,32,116,111,65,108,101,120
+,97,110,100,114,105,97,114,101,116,105,114,101,109,101,110,116,65,100,118,101,
+110,116,117,114,101,115,102,111,117,114,32,121,101,97,114,115,10,10,38,108,116,
+59,33,45,45,32,105,110,99,114,101,97,115,105,110,103,100,101,99,111,114,97,116,
+105,111,110,104,51,32,99,108,97,115,115,61,34,111,114,105,103,105,110,115,32,111
+,102,111,98,108,105,103,97,116,105,111,110,114,101,103,117,108,97,116,105,111,
+110,99,108,97,115,115,105,102,105,101,100,40,102,117,110,99,116,105,111,110,40,
+97,100,118,97,110,116,97,103,101,115,98,101,105,110,103,32,116,104,101,32,104,
+105,115,116,111,114,105,97,110,115,60,98,97,115,101,32,104,114,101,102,114,101,
+112,101,97,116,101,100,108,121,119,105,108,108,105,110,103,32,116,111,99,111,109
+,112,97,114,97,98,108,101,100,101,115,105,103,110,97,116,101,100,110,111,109,105
+,110,97,116,105,111,110,102,117,110,99,116,105,111,110,97,108,105,110,115,105,
+100,101,32,116,104,101,114,101,118,101,108,97,116,105,111,110,101,110,100,32,111
+,102,32,116,104,101,115,32,102,111,114,32,116,104,101,32,97,117,116,104,111,114,
+105,122,101,100,114,101,102,117,115,101,100,32,116,111,116,97,107,101,32,112,108
+,97,99,101,97,117,116,111,110,111,109,111,117,115,99,111,109,112,114,111,109,105
+,115,101,112,111,108,105,116,105,99,97,108,32,114,101,115,116,97,117,114,97,110,
+116,116,119,111,32,111,102,32,116,104,101,70,101,98,114,117,97,114,121,32,50,113
+,117,97,108,105,116,121,32,111,102,115,119,102,111,98,106,101,99,116,46,117,110,
+100,101,114,115,116,97,110,100,110,101,97,114,108,121,32,97,108,108,119,114,105,
+116,116,101,110,32,98,121,105,110,116,101,114,118,105,101,119,115,34,32,119,105,
+100,116,104,61,34,49,119,105,116,104,100,114,97,119,97,108,102,108,111,97,116,58
+,108,101,102,116,105,115,32,117,115,117,97,108,108,121,99,97,110,100,105,100,97,
+116,101,115,110,101,119,115,112,97,112,101,114,115,109,121,115,116,101,114,105,
+111,117,115,68,101,112,97,114,116,109,101,110,116,98,101,115,116,32,107,110,111,
+119,110,112,97,114,108,105,97,109,101,110,116,115,117,112,112,114,101,115,115,
+101,100,99,111,110,118,101,110,105,101,110,116,114,101,109,101,109,98,101,114,
+101,100,100,105,102,102,101,114,101,110,116,32,115,121,115,116,101,109,97,116,
+105,99,104,97,115,32,108,101,100,32,116,111,112,114,111,112,97,103,97,110,100,97
+,99,111,110,116,114,111,108,108,101,100,105,110,102,108,117,101,110,99,101,115,
+99,101,114,101,109,111,110,105,97,108,112,114,111,99,108,97,105,109,101,100,80,
+114,111,116,101,99,116,105,111,110,108,105,32,99,108,97,115,115,61,34,83,99,105,
+101,110,116,105,102,105,99,99,108,97,115,115,61,34,110,111,45,116,114,97,100,101
+,109,97,114,107,115,109,111,114,101,32,116,104,97,110,32,119,105,100,101,115,112
+,114,101,97,100,76,105,98,101,114,97,116,105,111,110,116,111,111,107,32,112,108,
+97,99,101,100,97,121,32,111,102,32,116,104,101,97,115,32,108,111,110,103,32,97,
+115,105,109,112,114,105,115,111,110,101,100,65,100,100,105,116,105,111,110,97,
+108,10,60,104,101,97,100,62,10,60,109,76,97,98,111,114,97,116,111,114,121,78,111
+,118,101,109,98,101,114,32,50,101,120,99,101,112,116,105,111,110,115,73,110,100,
+117,115,116,114,105,97,108,118,97,114,105,101,116,121,32,111,102,102,108,111,97,
+116,58,32,108,101,102,68,117,114,105,110,103,32,116,104,101,97,115,115,101,115,
+115,109,101,110,116,104,97,118,101,32,98,101,101,110,32,100,101,97,108,115,32,
+119,105,116,104,83,116,97,116,105,115,116,105,99,115,111,99,99,117,114,114,101,
+110,99,101,47,117,108,62,60,47,100,105,118,62,99,108,101,97,114,102,105,120,34,
+62,116,104,101,32,112,117,98,108,105,99,109,97,110,121,32,121,101,97,114,115,119
+,104,105,99,104,32,119,101,114,101,111,118,101,114,32,116,105,109,101,44,115,121
+,110,111,110,121,109,111,117,115,99,111,110,116,101,110,116,34,62,10,112,114,101
+,115,117,109,97,98,108,121,104,105,115,32,102,97,109,105,108,121,117,115,101,114
+,65,103,101,110,116,46,117,110,101,120,112,101,99,116,101,100,105,110,99,108,117
+,100,105,110,103,32,99,104,97,108,108,101,110,103,101,100,97,32,109,105,110,111,
+114,105,116,121,117,110,100,101,102,105,110,101,100,34,98,101,108,111,110,103,
+115,32,116,111,116,97,107,101,110,32,102,114,111,109,105,110,32,79,99,116,111,98
+,101,114,112,111,115,105,116,105,111,110,58,32,115,97,105,100,32,116,111,32,98,
+101,114,101,108,105,103,105,111,117,115,32,70,101,100,101,114,97,116,105,111,110
+,32,114,111,119,115,112,97,110,61,34,111,110,108,121,32,97,32,102,101,119,109,
+101,97,110,116,32,116,104,97,116,108,101,100,32,116,111,32,116,104,101,45,45,62,
+13,10,60,100,105,118,32,60,102,105,101,108,100,115,101,116,62,65,114,99,104,98,
+105,115,104,111,112,32,99,108,97,115,115,61,34,110,111,98,101,105,110,103,32,117
+,115,101,100,97,112,112,114,111,97,99,104,101,115,112,114,105,118,105,108,101,
+103,101,115,110,111,115,99,114,105,112,116,62,10,114,101,115,117,108,116,115,32,
+105,110,109,97,121,32,98,101,32,116,104,101,69,97,115,116,101,114,32,101,103,103
+,109,101,99,104,97,110,105,115,109,115,114,101,97,115,111,110,97,98,108,101,80,
+111,112,117,108,97,116,105,111,110,67,111,108,108,101,99,116,105,111,110,115,101
+,108,101,99,116,101,100,34,62,110,111,115,99,114,105,112,116,62,13,47,105,110,
+100,101,120,46,112,104,112,97,114,114,105,118,97,108,32,111,102,45,106,115,115,
+100,107,39,41,41,59,109,97,110,97,103,101,100,32,116,111,105,110,99,111,109,112,
+108,101,116,101,99,97,115,117,97,108,116,105,101,115,99,111,109,112,108,101,116,
+105,111,110,67,104,114,105,115,116,105,97,110,115,83,101,112,116,101,109,98,101,
+114,32,97,114,105,116,104,109,101,116,105,99,112,114,111,99,101,100,117,114,101,
+115,109,105,103,104,116,32,104,97,118,101,80,114,111,100,117,99,116,105,111,110,
+105,116,32,97,112,112,101,97,114,115,80,104,105,108,111,115,111,112,104,121,102,
+114,105,101,110,100,115,104,105,112,108,101,97,100,105,110,103,32,116,111,103,
+105,118,105,110,103,32,116,104,101,116,111,119,97,114,100,32,116,104,101,103,117
+,97,114,97,110,116,101,101,100,100,111,99,117,109,101,110,116,101,100,99,111,108
+,111,114,58,35,48,48,48,118,105,100,101,111,32,103,97,109,101,99,111,109,109,105
+,115,115,105,111,110,114,101,102,108,101,99,116,105,110,103,99,104,97,110,103,
+101,32,116,104,101,97,115,115,111,99,105,97,116,101,100,115,97,110,115,45,115,
+101,114,105,102,111,110,107,101,121,112,114,101,115,115,59,32,112,97,100,100,105
+,110,103,58,72,101,32,119,97,115,32,116,104,101,117,110,100,101,114,108,121,105,
+110,103,116,121,112,105,99,97,108,108,121,32,44,32,97,110,100,32,116,104,101,32,
+115,114,99,69,108,101,109,101,110,116,115,117,99,99,101,115,115,105,118,101,115,
+105,110,99,101,32,116,104,101,32,115,104,111,117,108,100,32,98,101,32,110,101,
+116,119,111,114,107,105,110,103,97,99,99,111,117,110,116,105,110,103,117,115,101
+,32,111,102,32,116,104,101,108,111,119,101,114,32,116,104,97,110,115,104,111,119
+,115,32,116,104,97,116,60,47,115,112,97,110,62,10,9,9,99,111,109,112,108,97,105,
+110,116,115,99,111,110,116,105,110,117,111,117,115,113,117,97,110,116,105,116,
+105,101,115,97,115,116,114,111,110,111,109,101,114,104,101,32,100,105,100,32,110
+,111,116,100,117,101,32,116,111,32,105,116,115,97,112,112,108,105,101,100,32,116
+,111,97,110,32,97,118,101,114,97,103,101,101,102,102,111,114,116,115,32,116,111,
+116,104,101,32,102,117,116,117,114,101,97,116,116,101,109,112,116,32,116,111,84,
+104,101,114,101,102,111,114,101,44,99,97,112,97,98,105,108,105,116,121,82,101,
+112,117,98,108,105,99,97,110,119,97,115,32,102,111,114,109,101,100,69,108,101,99
+,116,114,111,110,105,99,107,105,108,111,109,101,116,101,114,115,99,104,97,108,
+108,101,110,103,101,115,112,117,98,108,105,115,104,105,110,103,116,104,101,32,
+102,111,114,109,101,114,105,110,100,105,103,101,110,111,117,115,100,105,114,101,
+99,116,105,111,110,115,115,117,98,115,105,100,105,97,114,121,99,111,110,115,112,
+105,114,97,99,121,100,101,116,97,105,108,115,32,111,102,97,110,100,32,105,110,32
+,116,104,101,97,102,102,111,114,100,97,98,108,101,115,117,98,115,116,97,110,99,
+101,115,114,101,97,115,111,110,32,102,111,114,99,111,110,118,101,110,116,105,111
+,110,105,116,101,109,116,121,112,101,61,34,97,98,115,111,108,117,116,101,108,121
+,115,117,112,112,111,115,101,100,108,121,114,101,109,97,105,110,101,100,32,97,97
+,116,116,114,97,99,116,105,118,101,116,114,97,118,101,108,108,105,110,103,115,
+101,112,97,114,97,116,101,108,121,102,111,99,117,115,101,115,32,111,110,101,108,
+101,109,101,110,116,97,114,121,97,112,112,108,105,99,97,98,108,101,102,111,117,
+110,100,32,116,104,97,116,115,116,121,108,101,115,104,101,101,116,109,97,110,117
+,115,99,114,105,112,116,115,116,97,110,100,115,32,102,111,114,32,110,111,45,114,
+101,112,101,97,116,40,115,111,109,101,116,105,109,101,115,67,111,109,109,101,114
+,99,105,97,108,105,110,32,65,109,101,114,105,99,97,117,110,100,101,114,116,97,
+107,101,110,113,117,97,114,116,101,114,32,111,102,97,110,32,101,120,97,109,112,
+108,101,112,101,114,115,111,110,97,108,108,121,105,110,100,101,120,46,112,104,
+112,63,60,47,98,117,116,116,111,110,62,10,112,101,114,99,101,110,116,97,103,101,
+98,101,115,116,45,107,110,111,119,110,99,114,101,97,116,105,110,103,32,97,34,32,
+100,105,114,61,34,108,116,114,76,105,101,117,116,101,110,97,110,116,10,60,100,
+105,118,32,105,100,61,34,116,104,101,121,32,119,111,117,108,100,97,98,105,108,
+105,116,121,32,111,102,109,97,100,101,32,117,112,32,111,102,110,111,116,101,100,
+32,116,104,97,116,99,108,101,97,114,32,116,104,97,116,97,114,103,117,101,32,116,
+104,97,116,116,111,32,97,110,111,116,104,101,114,99,104,105,108,100,114,101,110,
+39,115,112,117,114,112,111,115,101,32,111,102,102,111,114,109,117,108,97,116,101
+,100,98,97,115,101,100,32,117,112,111,110,116,104,101,32,114,101,103,105,111,110
+,115,117,98,106,101,99,116,32,111,102,112,97,115,115,101,110,103,101,114,115,112
+,111,115,115,101,115,115,105,111,110,46,10,10,73,110,32,116,104,101,32,66,101,
+102,111,114,101,32,116,104,101,97,102,116,101,114,119,97,114,100,115,99,117,114,
+114,101,110,116,108,121,32,97,99,114,111,115,115,32,116,104,101,115,99,105,101,
+110,116,105,102,105,99,99,111,109,109,117,110,105,116,121,46,99,97,112,105,116,
+97,108,105,115,109,105,110,32,71,101,114,109,97,110,121,114,105,103,104,116,45,
+119,105,110,103,116,104,101,32,115,121,115,116,101,109,83,111,99,105,101,116,121
+,32,111,102,112,111,108,105,116,105,99,105,97,110,100,105,114,101,99,116,105,111
+,110,58,119,101,110,116,32,111,110,32,116,111,114,101,109,111,118,97,108,32,111,
+102,32,78,101,119,32,89,111,114,107,32,97,112,97,114,116,109,101,110,116,115,105
+,110,100,105,99,97,116,105,111,110,100,117,114,105,110,103,32,116,104,101,117,
+110,108,101,115,115,32,116,104,101,104,105,115,116,111,114,105,99,97,108,104,97,
+100,32,98,101,101,110,32,97,100,101,102,105,110,105,116,105,118,101,105,110,103,
+114,101,100,105,101,110,116,97,116,116,101,110,100,97,110,99,101,67,101,110,116,
+101,114,32,102,111,114,112,114,111,109,105,110,101,110,99,101,114,101,97,100,121
+,83,116,97,116,101,115,116,114,97,116,101,103,105,101,115,98,117,116,32,105,110,
+32,116,104,101,97,115,32,112,97,114,116,32,111,102,99,111,110,115,116,105,116,
+117,116,101,99,108,97,105,109,32,116,104,97,116,108,97,98,111,114,97,116,111,114
+,121,99,111,109,112,97,116,105,98,108,101,102,97,105,108,117,114,101,32,111,102,
+44,32,115,117,99,104,32,97,115,32,98,101,103,97,110,32,119,105,116,104,117,115,
+105,110,103,32,116,104,101,32,116,111,32,112,114,111,118,105,100,101,102,101,97,
+116,117,114,101,32,111,102,102,114,111,109,32,119,104,105,99,104,47,34,32,99,108
+,97,115,115,61,34,103,101,111,108,111,103,105,99,97,108,115,101,118,101,114,97,
+108,32,111,102,100,101,108,105,98,101,114,97,116,101,105,109,112,111,114,116,97,
+110,116,32,104,111,108,100,115,32,116,104,97,116,105,110,103,38,113,117,111,116,
+59,32,118,97,108,105,103,110,61,116,111,112,116,104,101,32,71,101,114,109,97,110
+,111,117,116,115,105,100,101,32,111,102,110,101,103,111,116,105,97,116,101,100,
+104,105,115,32,99,97,114,101,101,114,115,101,112,97,114,97,116,105,111,110,105,
+100,61,34,115,101,97,114,99,104,119,97,115,32,99,97,108,108,101,100,116,104,101,
+32,102,111,117,114,116,104,114,101,99,114,101,97,116,105,111,110,111,116,104,101
+,114,32,116,104,97,110,112,114,101,118,101,110,116,105,111,110,119,104,105,108,
+101,32,116,104,101,32,101,100,117,99,97,116,105,111,110,44,99,111,110,110,101,99
+,116,105,110,103,97,99,99,117,114,97,116,101,108,121,119,101,114,101,32,98,117,
+105,108,116,119,97,115,32,107,105,108,108,101,100,97,103,114,101,101,109,101,110
+,116,115,109,117,99,104,32,109,111,114,101,32,68,117,101,32,116,111,32,116,104,
+101,119,105,100,116,104,58,32,49,48,48,115,111,109,101,32,111,116,104,101,114,75
+,105,110,103,100,111,109,32,111,102,116,104,101,32,101,110,116,105,114,101,102,
+97,109,111,117,115,32,102,111,114,116,111,32,99,111,110,110,101,99,116,111,98,
+106,101,99,116,105,118,101,115,116,104,101,32,70,114,101,110,99,104,112,101,111,
+112,108,101,32,97,110,100,102,101,97,116,117,114,101,100,34,62,105,115,32,115,97
+,105,100,32,116,111,115,116,114,117,99,116,117,114,97,108,114,101,102,101,114,
+101,110,100,117,109,109,111,115,116,32,111,102,116,101,110,97,32,115,101,112,97,
+114,97,116,101,45,62,10,60,100,105,118,32,105,100,32,79,102,102,105,99,105,97,
+108,32,119,111,114,108,100,119,105,100,101,46,97,114,105,97,45,108,97,98,101,108
+,116,104,101,32,112,108,97,110,101,116,97,110,100,32,105,116,32,119,97,115,100,
+34,32,118,97,108,117,101,61,34,108,111,111,107,105,110,103,32,97,116,98,101,110,
+101,102,105,99,105,97,108,97,114,101,32,105,110,32,116,104,101,109,111,110,105,
+116,111,114,105,110,103,114,101,112,111,114,116,101,100,108,121,116,104,101,32,
+109,111,100,101,114,110,119,111,114,107,105,110,103,32,111,110,97,108,108,111,
+119,101,100,32,116,111,119,104,101,114,101,32,116,104,101,32,105,110,110,111,118
+,97,116,105,118,101,60,47,97,62,60,47,100,105,118,62,115,111,117,110,100,116,114
+,97,99,107,115,101,97,114,99,104,70,111,114,109,116,101,110,100,32,116,111,32,98
+,101,105,110,112,117,116,32,105,100,61,34,111,112,101,110,105,110,103,32,111,102
+,114,101,115,116,114,105,99,116,101,100,97,100,111,112,116,101,100,32,98,121,97,
+100,100,114,101,115,115,105,110,103,116,104,101,111,108,111,103,105,97,110,109,
+101,116,104,111,100,115,32,111,102,118,97,114,105,97,110,116,32,111,102,67,104,
+114,105,115,116,105,97,110,32,118,101,114,121,32,108,97,114,103,101,97,117,116,
+111,109,111,116,105,118,101,98,121,32,102,97,114,32,116,104,101,114,97,110,103,
+101,32,102,114,111,109,112,117,114,115,117,105,116,32,111,102,102,111,108,108,
+111,119,32,116,104,101,98,114,111,117,103,104,116,32,116,111,105,110,32,69,110,
+103,108,97,110,100,97,103,114,101,101,32,116,104,97,116,97,99,99,117,115,101,100
+,32,111,102,99,111,109,101,115,32,102,114,111,109,112,114,101,118,101,110,116,
+105,110,103,100,105,118,32,115,116,121,108,101,61,104,105,115,32,111,114,32,104,
+101,114,116,114,101,109,101,110,100,111,117,115,102,114,101,101,100,111,109,32,
+111,102,99,111,110,99,101,114,110,105,110,103,48,32,49,101,109,32,49,101,109,59,
+66,97,115,107,101,116,98,97,108,108,47,115,116,121,108,101,46,99,115,115,97,110,
+32,101,97,114,108,105,101,114,101,118,101,110,32,97,102,116,101,114,47,34,32,116
+,105,116,108,101,61,34,46,99,111,109,47,105,110,100,101,120,116,97,107,105,110,
+103,32,116,104,101,112,105,116,116,115,98,117,114,103,104,99,111,110,116,101,110
+,116,34,62,13,60,115,99,114,105,112,116,62,40,102,116,117,114,110,101,100,32,111
+,117,116,104,97,118,105,110,103,32,116,104,101,60,47,115,112,97,110,62,13,10,32,
+111,99,99,97,115,105,111,110,97,108,98,101,99,97,117,115,101,32,105,116,115,116,
+97,114,116,101,100,32,116,111,112,104,121,115,105,99,97,108,108,121,62,60,47,100
+,105,118,62,10,32,32,99,114,101,97,116,101,100,32,98,121,67,117,114,114,101,110,
+116,108,121,44,32,98,103,99,111,108,111,114,61,34,116,97,98,105,110,100,101,120,
+61,34,100,105,115,97,115,116,114,111,117,115,65,110,97,108,121,116,105,99,115,32
+,97,108,115,111,32,104,97,115,32,97,62,60,100,105,118,32,105,100,61,34,60,47,115
+,116,121,108,101,62,10,60,99,97,108,108,101,100,32,102,111,114,115,105,110,103,
+101,114,32,97,110,100,46,115,114,99,32,61,32,34,47,47,118,105,111,108,97,116,105
+,111,110,115,116,104,105,115,32,112,111,105,110,116,99,111,110,115,116,97,110,
+116,108,121,105,115,32,108,111,99,97,116,101,100,114,101,99,111,114,100,105,110,
+103,115,100,32,102,114,111,109,32,116,104,101,110,101,100,101,114,108,97,110,100
+,115,112,111,114,116,117,103,117,195,170,115,215,162,215,145,215,168,215,153,215
+,170,217,129,216,167,216,177,216,179,219,140,100,101,115,97,114,114,111,108,108,
+111,99,111,109,101,110,116,97,114,105,111,101,100,117,99,97,99,105,195,179,110,
+115,101,112,116,105,101,109,98,114,101,114,101,103,105,115,116,114,97,100,111,
+100,105,114,101,99,99,105,195,179,110,117,98,105,99,97,99,105,195,179,110,112,
+117,98,108,105,99,105,100,97,100,114,101,115,112,117,101,115,116,97,115,114,101,
+115,117,108,116,97,100,111,115,105,109,112,111,114,116,97,110,116,101,114,101,
+115,101,114,118,97,100,111,115,97,114,116,195,173,99,117,108,111,115,100,105,102
+,101,114,101,110,116,101,115,115,105,103,117,105,101,110,116,101,115,114,101,112
+,195,186,98,108,105,99,97,115,105,116,117,97,99,105,195,179,110,109,105,110,105,
+115,116,101,114,105,111,112,114,105,118,97,99,105,100,97,100,100,105,114,101,99,
+116,111,114,105,111,102,111,114,109,97,99,105,195,179,110,112,111,98,108,97,99,
+105,195,179,110,112,114,101,115,105,100,101,110,116,101,99,111,110,116,101,110,
+105,100,111,115,97,99,99,101,115,111,114,105,111,115,116,101,99,104,110,111,114,
+97,116,105,112,101,114,115,111,110,97,108,101,115,99,97,116,101,103,111,114,195,
+173,97,101,115,112,101,99,105,97,108,101,115,100,105,115,112,111,110,105,98,108,
+101,97,99,116,117,97,108,105,100,97,100,114,101,102,101,114,101,110,99,105,97,
+118,97,108,108,97,100,111,108,105,100,98,105,98,108,105,111,116,101,99,97,114,
+101,108,97,99,105,111,110,101,115,99,97,108,101,110,100,97,114,105,111,112,111,
+108,195,173,116,105,99,97,115,97,110,116,101,114,105,111,114,101,115,100,111,99,
+117,109,101,110,116,111,115,110,97,116,117,114,97,108,101,122,97,109,97,116,101,
+114,105,97,108,101,115,100,105,102,101,114,101,110,99,105,97,101,99,111,110,195,
+179,109,105,99,97,116,114,97,110,115,112,111,114,116,101,114,111,100,114,195,173
+,103,117,101,122,112,97,114,116,105,99,105,112,97,114,101,110,99,117,101,110,116
+,114,97,110,100,105,115,99,117,115,105,195,179,110,101,115,116,114,117,99,116,
+117,114,97,102,117,110,100,97,99,105,195,179,110,102,114,101,99,117,101,110,116,
+101,115,112,101,114,109,97,110,101,110,116,101,116,111,116,97,108,109,101,110,
+116,101,208,188,208,190,208,182,208,189,208,190,208,177,209,131,208,180,208,181,
+209,130,208,188,208,190,208,182,208,181,209,130,208,178,209,128,208,181,208,188,
+209,143,209,130,208,176,208,186,208,182,208,181,209,135,209,130,208,190,208,177,
+209,139,208,177,208,190,208,187,208,181,208,181,208,190,209,135,208,181,208,189,
+209,140,209,141,209,130,208,190,208,179,208,190,208,186,208,190,208,179,208,180,
+208,176,208,191,208,190,209,129,208,187,208,181,208,178,209,129,208,181,208,179,
+208,190,209,129,208,176,208,185,209,130,208,181,209,135,208,181,209,128,208,181,
+208,183,208,188,208,190,208,179,209,131,209,130,209,129,208,176,208,185,209,130,
+208,176,208,182,208,184,208,183,208,189,208,184,208,188,208,181,208,182,208,180,
+209,131,208,177,209,131,208,180,209,131,209,130,208,159,208,190,208,184,209,129,
+208,186,208,183,208,180,208,181,209,129,209,140,208,178,208,184,208,180,208,181,
+208,190,209,129,208,178,209,143,208,183,208,184,208,189,209,131,208,182,208,189,
+208,190,209,129,208,178,208,190,208,181,208,185,208,187,209,142,208,180,208,181,
+208,185,208,191,208,190,209,128,208,189,208,190,208,188,208,189,208,190,208,179,
+208,190,208,180,208,181,209,130,208,181,208,185,209,129,208,178,208,190,208,184,
+209,133,208,191,209,128,208,176,208,178,208,176,209,130,208,176,208,186,208,190,
+208,185,208,188,208,181,209,129,209,130,208,190,208,184,208,188,208,181,208,181,
+209,130,208,182,208,184,208,183,208,189,209,140,208,190,208,180,208,189,208,190,
+208,185,208,187,209,131,209,135,209,136,208,181,208,191,208,181,209,128,208,181,
+208,180,209,135,208,176,209,129,209,130,208,184,209,135,208,176,209,129,209,130,
+209,140,209,128,208,176,208,177,208,190,209,130,208,189,208,190,208,178,209,139,
+209,133,208,191,209,128,208,176,208,178,208,190,209,129,208,190,208,177,208,190,
+208,185,208,191,208,190,209,130,208,190,208,188,208,188,208,181,208,189,208,181,
+208,181,209,135,208,184,209,129,208,187,208,181,208,189,208,190,208,178,209,139,
+208,181,209,131,209,129,208,187,209,131,208,179,208,190,208,186,208,190,208,187,
+208,190,208,189,208,176,208,183,208,176,208,180,209,130,208,176,208,186,208,190,
+208,181,209,130,208,190,208,179,208,180,208,176,208,191,208,190,209,135,209,130,
+208,184,208,159,208,190,209,129,208,187,208,181,209,130,208,176,208,186,208,184,
+208,181,208,189,208,190,208,178,209,139,208,185,209,129,209,130,208,190,208,184,
+209,130,209,130,208,176,208,186,208,184,209,133,209,129,209,128,208,176,208,183,
+209,131,208,161,208,176,208,189,208,186,209,130,209,132,208,190,209,128,209,131,
+208,188,208,154,208,190,208,179,208,180,208,176,208,186,208,189,208,184,208,179,
+208,184,209,129,208,187,208,190,208,178,208,176,208,189,208,176,209,136,208,181,
+208,185,208,189,208,176,208,185,209,130,208,184,209,129,208,178,208,190,208,184,
+208,188,209,129,208,178,209,143,208,183,209,140,208,187,209,142,208,177,208,190,
+208,185,209,135,208,176,209,129,209,130,208,190,209,129,209,128,208,181,208,180,
+208,184,208,154,209,128,208,190,208,188,208,181,208,164,208,190,209,128,209,131,
+208,188,209,128,209,139,208,189,208,186,208,181,209,129,209,130,208,176,208,187,
+208,184,208,191,208,190,208,184,209,129,208,186,209,130,209,139,209,129,209,143,
+209,135,208,188,208,181,209,129,209,143,209,134,209,134,208,181,208,189,209,130,
+209,128,209,130,209,128,209,131,208,180,208,176,209,129,208,176,208,188,209,139,
+209,133,209,128,209,139,208,189,208,186,208,176,208,157,208,190,208,178,209,139,
+208,185,209,135,208,176,209,129,208,190,208,178,208,188,208,181,209,129,209,130,
+208,176,209,132,208,184,208,187,209,140,208,188,208,188,208,176,209,128,209,130,
+208,176,209,129,209,130,209,128,208,176,208,189,208,188,208,181,209,129,209,130,
+208,181,209,130,208,181,208,186,209,129,209,130,208,189,208,176,209,136,208,184,
+209,133,208,188,208,184,208,189,209,131,209,130,208,184,208,188,208,181,208,189,
+208,184,208,184,208,188,208,181,209,142,209,130,208,189,208,190,208,188,208,181,
+209,128,208,179,208,190,209,128,208,190,208,180,209,129,208,176,208,188,208,190,
+208,188,209,141,209,130,208,190,208,188,209,131,208,186,208,190,208,189,209,134,
+208,181,209,129,208,178,208,190,208,181,208,188,208,186,208,176,208,186,208,190,
+208,185,208,144,209,128,209,133,208,184,208,178,217,133,217,134,216,170,216,175,
+217,137,216,165,216,177,216,179,216,167,217,132,216,177,216,179,216,167,217,132,
+216,169,216,167,217,132,216,185,216,167,217,133,217,131,216,170,216,168,217,135,
+216,167,216,168,216,177,216,167,217,133,216,172,216,167,217,132,217,138,217,136,
+217,133,216,167,217,132,216,181,217,136,216,177,216,172,216,175,217,138,216,175,
+216,169,216,167,217,132,216,185,216,182,217,136,216,165,216,182,216,167,217,129,
+216,169,216,167,217,132,217,130,216,179,217,133,216,167,217,132,216,185,216,167,
+216,168,216,170,216,173,217,133,217,138,217,132,217,133,217,132,217,129,216,167,
+216,170,217,133,217,132,216,170,217,130,217,137,216,170,216,185,216,175,217,138,
+217,132,216,167,217,132,216,180,216,185,216,177,216,163,216,174,216,168,216,167,
+216,177,216,170,216,183,217,136,217,138,216,177,216,185,217,132,217,138,217,131,
+217,133,216,165,216,177,217,129,216,167,217,130,216,183,217,132,216,168,216,167,
+216,170,216,167,217,132,217,132,216,186,216,169,216,170,216,177,216,170,217,138,
+216,168,216,167,217,132,217,134,216,167,216,179,216,167,217,132,216,180,217,138,
+216,174,217,133,217,134,216,170,216,175,217,138,216,167,217,132,216,185,216,177,
+216,168,216,167,217,132,217,130,216,181,216,181,216,167,217,129,217,132,216,167,
+217,133,216,185,217,132,217,138,217,135,216,167,216,170,216,173,216,175,217,138,
+216,171,216,167,217,132,217,132,217,135,217,133,216,167,217,132,216,185,217,133,
+217,132,217,133,217,131,216,170,216,168,216,169,217,138,217,133,217,131,217,134,
+217,131,216,167,217,132,216,183,217,129,217,132,217,129,217,138,216,175,217,138,
+217,136,216,165,216,175,216,167,216,177,216,169,216,170,216,167,216,177,217,138,
+216,174,216,167,217,132,216,181,216,173,216,169,216,170,216,179,216,172,217,138,
+217,132,216,167,217,132,217,136,217,130,216,170,216,185,217,134,216,175,217,133,
+216,167,217,133,216,175,217,138,217,134,216,169,216,170,216,181,217,133,217,138,
+217,133,216,163,216,177,216,180,217,138,217,129,216,167,217,132,216,176,217,138,
+217,134,216,185,216,177,216,168,217,138,216,169,216,168,217,136,216,167,216,168,
+216,169,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,179,217,129,
+216,177,217,133,216,180,216,167,217,131,217,132,216,170,216,185,216,167,217,132,
+217,137,216,167,217,132,216,163,217,136,217,132,216,167,217,132,216,179,217,134,
+216,169,216,172,216,167,217,133,216,185,216,169,216,167,217,132,216,181,216,173,
+217,129,216,167,217,132,216,175,217,138,217,134,217,131,217,132,217,133,216,167,
+216,170,216,167,217,132,216,174,216,167,216,181,216,167,217,132,217,133,217,132,
+217,129,216,163,216,185,216,182,216,167,216,161,217,131,216,170,216,167,216,168,
+216,169,216,167,217,132,216,174,217,138,216,177,216,177,216,179,216,167,216,166,
+217,132,216,167,217,132,217,130,217,132,216,168,216,167,217,132,216,163,216,175,
+216,168,217,133,217,130,216,167,216,183,216,185,217,133,216,177,216,167,216,179,
+217,132,217,133,217,134,216,183,217,130,216,169,216,167,217,132,217,131,216,170,
+216,168,216,167,217,132,216,177,216,172,217,132,216,167,216,180,216,170,216,177,
+217,131,216,167,217,132,217,130,216,175,217,133,217,138,216,185,216,183,217,138,
+217,131,115,66,121,84,97,103,78,97,109,101,40,46,106,112,103,34,32,97,108,116,61
+,34,49,112,120,32,115,111,108,105,100,32,35,46,103,105,102,34,32,97,108,116,61,
+34,116,114,97,110,115,112,97,114,101,110,116,105,110,102,111,114,109,97,116,105,
+111,110,97,112,112,108,105,99,97,116,105,111,110,34,32,111,110,99,108,105,99,107
+,61,34,101,115,116,97,98,108,105,115,104,101,100,97,100,118,101,114,116,105,115,
+105,110,103,46,112,110,103,34,32,97,108,116,61,34,101,110,118,105,114,111,110,
+109,101,110,116,112,101,114,102,111,114,109,97,110,99,101,97,112,112,114,111,112
+,114,105,97,116,101,38,97,109,112,59,109,100,97,115,104,59,105,109,109,101,100,
+105,97,116,101,108,121,60,47,115,116,114,111,110,103,62,60,47,114,97,116,104,101
+,114,32,116,104,97,110,116,101,109,112,101,114,97,116,117,114,101,100,101,118,
+101,108,111,112,109,101,110,116,99,111,109,112,101,116,105,116,105,111,110,112,
+108,97,99,101,104,111,108,100,101,114,118,105,115,105,98,105,108,105,116,121,58,
+99,111,112,121,114,105,103,104,116,34,62,48,34,32,104,101,105,103,104,116,61,34,
+101,118,101,110,32,116,104,111,117,103,104,114,101,112,108,97,99,101,109,101,110
+,116,100,101,115,116,105,110,97,116,105,111,110,67,111,114,112,111,114,97,116,
+105,111,110,60,117,108,32,99,108,97,115,115,61,34,65,115,115,111,99,105,97,116,
+105,111,110,105,110,100,105,118,105,100,117,97,108,115,112,101,114,115,112,101,
+99,116,105,118,101,115,101,116,84,105,109,101,111,117,116,40,117,114,108,40,104,
+116,116,112,58,47,47,109,97,116,104,101,109,97,116,105,99,115,109,97,114,103,105
+,110,45,116,111,112,58,101,118,101,110,116,117,97,108,108,121,32,100,101,115,99,
+114,105,112,116,105,111,110,41,32,110,111,45,114,101,112,101,97,116,99,111,108,
+108,101,99,116,105,111,110,115,46,74,80,71,124,116,104,117,109,98,124,112,97,114
+,116,105,99,105,112,97,116,101,47,104,101,97,100,62,60,98,111,100,121,102,108,
+111,97,116,58,108,101,102,116,59,60,108,105,32,99,108,97,115,115,61,34,104,117,
+110,100,114,101,100,115,32,111,102,10,10,72,111,119,101,118,101,114,44,32,99,111
+,109,112,111,115,105,116,105,111,110,99,108,101,97,114,58,98,111,116,104,59,99,
+111,111,112,101,114,97,116,105,111,110,119,105,116,104,105,110,32,116,104,101,32
+,108,97,98,101,108,32,102,111,114,61,34,98,111,114,100,101,114,45,116,111,112,58
+,78,101,119,32,90,101,97,108,97,110,100,114,101,99,111,109,109,101,110,100,101,
+100,112,104,111,116,111,103,114,97,112,104,121,105,110,116,101,114,101,115,116,
+105,110,103,38,108,116,59,115,117,112,38,103,116,59,99,111,110,116,114,111,118,
+101,114,115,121,78,101,116,104,101,114,108,97,110,100,115,97,108,116,101,114,110
+,97,116,105,118,101,109,97,120,108,101,110,103,116,104,61,34,115,119,105,116,122
+,101,114,108,97,110,100,68,101,118,101,108,111,112,109,101,110,116,101,115,115,
+101,110,116,105,97,108,108,121,10,10,65,108,116,104,111,117,103,104,32,60,47,116
+,101,120,116,97,114,101,97,62,116,104,117,110,100,101,114,98,105,114,100,114,101
+,112,114,101,115,101,110,116,101,100,38,97,109,112,59,110,100,97,115,104,59,115,
+112,101,99,117,108,97,116,105,111,110,99,111,109,109,117,110,105,116,105,101,115
+,108,101,103,105,115,108,97,116,105,111,110,101,108,101,99,116,114,111,110,105,
+99,115,10,9,60,100,105,118,32,105,100,61,34,105,108,108,117,115,116,114,97,116,
+101,100,101,110,103,105,110,101,101,114,105,110,103,116,101,114,114,105,116,111,
+114,105,101,115,97,117,116,104,111,114,105,116,105,101,115,100,105,115,116,114,
+105,98,117,116,101,100,54,34,32,104,101,105,103,104,116,61,34,115,97,110,115,45,
+115,101,114,105,102,59,99,97,112,97,98,108,101,32,111,102,32,100,105,115,97,112,
+112,101,97,114,101,100,105,110,116,101,114,97,99,116,105,118,101,108,111,111,107
+,105,110,103,32,102,111,114,105,116,32,119,111,117,108,100,32,98,101,65,102,103,
+104,97,110,105,115,116,97,110,119,97,115,32,99,114,101,97,116,101,100,77,97,116,
+104,46,102,108,111,111,114,40,115,117,114,114,111,117,110,100,105,110,103,99,97,
+110,32,97,108,115,111,32,98,101,111,98,115,101,114,118,97,116,105,111,110,109,97
+,105,110,116,101,110,97,110,99,101,101,110,99,111,117,110,116,101,114,101,100,60
+,104,50,32,99,108,97,115,115,61,34,109,111,114,101,32,114,101,99,101,110,116,105
+,116,32,104,97,115,32,98,101,101,110,105,110,118,97,115,105,111,110,32,111,102,
+41,46,103,101,116,84,105,109,101,40,41,102,117,110,100,97,109,101,110,116,97,108
+,68,101,115,112,105,116,101,32,116,104,101,34,62,60,100,105,118,32,105,100,61,34
+,105,110,115,112,105,114,97,116,105,111,110,101,120,97,109,105,110,97,116,105,
+111,110,112,114,101,112,97,114,97,116,105,111,110,101,120,112,108,97,110,97,116,
+105,111,110,60,105,110,112,117,116,32,105,100,61,34,60,47,97,62,60,47,115,112,97
+,110,62,118,101,114,115,105,111,110,115,32,111,102,105,110,115,116,114,117,109,
+101,110,116,115,98,101,102,111,114,101,32,116,104,101,32,32,61,32,39,104,116,116
+,112,58,47,47,68,101,115,99,114,105,112,116,105,111,110,114,101,108,97,116,105,
+118,101,108,121,32,46,115,117,98,115,116,114,105,110,103,40,101,97,99,104,32,111
+,102,32,116,104,101,101,120,112,101,114,105,109,101,110,116,115,105,110,102,108,
+117,101,110,116,105,97,108,105,110,116,101,103,114,97,116,105,111,110,109,97,110
+,121,32,112,101,111,112,108,101,100,117,101,32,116,111,32,116,104,101,32,99,111,
+109,98,105,110,97,116,105,111,110,100,111,32,110,111,116,32,104,97,118,101,77,
+105,100,100,108,101,32,69,97,115,116,60,110,111,115,99,114,105,112,116,62,60,99,
+111,112,121,114,105,103,104,116,34,32,112,101,114,104,97,112,115,32,116,104,101,
+105,110,115,116,105,116,117,116,105,111,110,105,110,32,68,101,99,101,109,98,101,
+114,97,114,114,97,110,103,101,109,101,110,116,109,111,115,116,32,102,97,109,111,
+117,115,112,101,114,115,111,110,97,108,105,116,121,99,114,101,97,116,105,111,110
+,32,111,102,108,105,109,105,116,97,116,105,111,110,115,101,120,99,108,117,115,
+105,118,101,108,121,115,111,118,101,114,101,105,103,110,116,121,45,99,111,110,
+116,101,110,116,34,62,10,60,116,100,32,99,108,97,115,115,61,34,117,110,100,101,
+114,103,114,111,117,110,100,112,97,114,97,108,108,101,108,32,116,111,100,111,99,
+116,114,105,110,101,32,111,102,111,99,99,117,112,105,101,100,32,98,121,116,101,
+114,109,105,110,111,108,111,103,121,82,101,110,97,105,115,115,97,110,99,101,97,
+32,110,117,109,98,101,114,32,111,102,115,117,112,112,111,114,116,32,102,111,114,
+101,120,112,108,111,114,97,116,105,111,110,114,101,99,111,103,110,105,116,105,
+111,110,112,114,101,100,101,99,101,115,115,111,114,60,105,109,103,32,115,114,99,
+61,34,47,60,104,49,32,99,108,97,115,115,61,34,112,117,98,108,105,99,97,116,105,
+111,110,109,97,121,32,97,108,115,111,32,98,101,115,112,101,99,105,97,108,105,122
+,101,100,60,47,102,105,101,108,100,115,101,116,62,112,114,111,103,114,101,115,
+115,105,118,101,109,105,108,108,105,111,110,115,32,111,102,115,116,97,116,101,
+115,32,116,104,97,116,101,110,102,111,114,99,101,109,101,110,116,97,114,111,117,
+110,100,32,116,104,101,32,111,110,101,32,97,110,111,116,104,101,114,46,112,97,
+114,101,110,116,78,111,100,101,97,103,114,105,99,117,108,116,117,114,101,65,108,
+116,101,114,110,97,116,105,118,101,114,101,115,101,97,114,99,104,101,114,115,116
+,111,119,97,114,100,115,32,116,104,101,77,111,115,116,32,111,102,32,116,104,101,
+109,97,110,121,32,111,116,104,101,114,32,40,101,115,112,101,99,105,97,108,108,
+121,60,116,100,32,119,105,100,116,104,61,34,59,119,105,100,116,104,58,49,48,48,
+37,105,110,100,101,112,101,110,100,101,110,116,60,104,51,32,99,108,97,115,115,61
+,34,32,111,110,99,104,97,110,103,101,61,34,41,46,97,100,100,67,108,97,115,115,40
+,105,110,116,101,114,97,99,116,105,111,110,79,110,101,32,111,102,32,116,104,101,
+32,100,97,117,103,104,116,101,114,32,111,102,97,99,99,101,115,115,111,114,105,
+101,115,98,114,97,110,99,104,101,115,32,111,102,13,10,60,100,105,118,32,105,100,
+61,34,116,104,101,32,108,97,114,103,101,115,116,100,101,99,108,97,114,97,116,105
+,111,110,114,101,103,117,108,97,116,105,111,110,115,73,110,102,111,114,109,97,
+116,105,111,110,116,114,97,110,115,108,97,116,105,111,110,100,111,99,117,109,101
+,110,116,97,114,121,105,110,32,111,114,100,101,114,32,116,111,34,62,10,60,104,
+101,97,100,62,10,60,34,32,104,101,105,103,104,116,61,34,49,97,99,114,111,115,115
+,32,116,104,101,32,111,114,105,101,110,116,97,116,105,111,110,41,59,60,47,115,99
+,114,105,112,116,62,105,109,112,108,101,109,101,110,116,101,100,99,97,110,32,98,
+101,32,115,101,101,110,116,104,101,114,101,32,119,97,115,32,97,100,101,109,111,
+110,115,116,114,97,116,101,99,111,110,116,97,105,110,101,114,34,62,99,111,110,
+110,101,99,116,105,111,110,115,116,104,101,32,66,114,105,116,105,115,104,119,97,
+115,32,119,114,105,116,116,101,110,33,105,109,112,111,114,116,97,110,116,59,112,
+120,59,32,109,97,114,103,105,110,45,102,111,108,108,111,119,101,100,32,98,121,97
+,98,105,108,105,116,121,32,116,111,32,99,111,109,112,108,105,99,97,116,101,100,
+100,117,114,105,110,103,32,116,104,101,32,105,109,109,105,103,114,97,116,105,111
+,110,97,108,115,111,32,99,97,108,108,101,100,60,104,52,32,99,108,97,115,115,61,
+34,100,105,115,116,105,110,99,116,105,111,110,114,101,112,108,97,99,101,100,32,
+98,121,103,111,118,101,114,110,109,101,110,116,115,108,111,99,97,116,105,111,110
+,32,111,102,105,110,32,78,111,118,101,109,98,101,114,119,104,101,116,104,101,114
+,32,116,104,101,60,47,112,62,10,60,47,100,105,118,62,97,99,113,117,105,115,105,
+116,105,111,110,99,97,108,108,101,100,32,116,104,101,32,112,101,114,115,101,99,
+117,116,105,111,110,100,101,115,105,103,110,97,116,105,111,110,123,102,111,110,
+116,45,115,105,122,101,58,97,112,112,101,97,114,101,100,32,105,110,105,110,118,
+101,115,116,105,103,97,116,101,101,120,112,101,114,105,101,110,99,101,100,109,
+111,115,116,32,108,105,107,101,108,121,119,105,100,101,108,121,32,117,115,101,
+100,100,105,115,99,117,115,115,105,111,110,115,112,114,101,115,101,110,99,101,32
+,111,102,32,40,100,111,99,117,109,101,110,116,46,101,120,116,101,110,115,105,118
+,101,108,121,73,116,32,104,97,115,32,98,101,101,110,105,116,32,100,111,101,115,
+32,110,111,116,99,111,110,116,114,97,114,121,32,116,111,105,110,104,97,98,105,
+116,97,110,116,115,105,109,112,114,111,118,101,109,101,110,116,115,99,104,111,
+108,97,114,115,104,105,112,99,111,110,115,117,109,112,116,105,111,110,105,110,
+115,116,114,117,99,116,105,111,110,102,111,114,32,101,120,97,109,112,108,101,111
+,110,101,32,111,114,32,109,111,114,101,112,120,59,32,112,97,100,100,105,110,103,
+116,104,101,32,99,117,114,114,101,110,116,97,32,115,101,114,105,101,115,32,111,
+102,97,114,101,32,117,115,117,97,108,108,121,114,111,108,101,32,105,110,32,116,
+104,101,112,114,101,118,105,111,117,115,108,121,32,100,101,114,105,118,97,116,
+105,118,101,115,101,118,105,100,101,110,99,101,32,111,102,101,120,112,101,114,
+105,101,110,99,101,115,99,111,108,111,114,115,99,104,101,109,101,115,116,97,116,
+101,100,32,116,104,97,116,99,101,114,116,105,102,105,99,97,116,101,60,47,97,62,
+60,47,100,105,118,62,10,32,115,101,108,101,99,116,101,100,61,34,104,105,103,104,
+32,115,99,104,111,111,108,114,101,115,112,111,110,115,101,32,116,111,99,111,109,
+102,111,114,116,97,98,108,101,97,100,111,112,116,105,111,110,32,111,102,116,104,
+114,101,101,32,121,101,97,114,115,116,104,101,32,99,111,117,110,116,114,121,105,
+110,32,70,101,98,114,117,97,114,121,115,111,32,116,104,97,116,32,116,104,101,112
+,101,111,112,108,101,32,119,104,111,32,112,114,111,118,105,100,101,100,32,98,121
+,60,112,97,114,97,109,32,110,97,109,101,97,102,102,101,99,116,101,100,32,98,121,
+105,110,32,116,101,114,109,115,32,111,102,97,112,112,111,105,110,116,109,101,110
+,116,73,83,79,45,56,56,53,57,45,49,34,119,97,115,32,98,111,114,110,32,105,110,
+104,105,115,116,111,114,105,99,97,108,32,114,101,103,97,114,100,101,100,32,97,
+115,109,101,97,115,117,114,101,109,101,110,116,105,115,32,98,97,115,101,100,32,
+111,110,32,97,110,100,32,111,116,104,101,114,32,58,32,102,117,110,99,116,105,111
+,110,40,115,105,103,110,105,102,105,99,97,110,116,99,101,108,101,98,114,97,116,
+105,111,110,116,114,97,110,115,109,105,116,116,101,100,47,106,115,47,106,113,117
+,101,114,121,46,105,115,32,107,110,111,119,110,32,97,115,116,104,101,111,114,101
+,116,105,99,97,108,32,116,97,98,105,110,100,101,120,61,34,105,116,32,99,111,117,
+108,100,32,98,101,60,110,111,115,99,114,105,112,116,62,10,104,97,118,105,110,103
+,32,98,101,101,110,13,10,60,104,101,97,100,62,13,10,60,32,38,113,117,111,116,59,
+84,104,101,32,99,111,109,112,105,108,97,116,105,111,110,104,101,32,104,97,100,32
+,98,101,101,110,112,114,111,100,117,99,101,100,32,98,121,112,104,105,108,111,115
+,111,112,104,101,114,99,111,110,115,116,114,117,99,116,101,100,105,110,116,101,
+110,100,101,100,32,116,111,97,109,111,110,103,32,111,116,104,101,114,99,111,109,
+112,97,114,101,100,32,116,111,116,111,32,115,97,121,32,116,104,97,116,69,110,103
+,105,110,101,101,114,105,110,103,97,32,100,105,102,102,101,114,101,110,116,114,
+101,102,101,114,114,101,100,32,116,111,100,105,102,102,101,114,101,110,99,101,
+115,98,101,108,105,101,102,32,116,104,97,116,112,104,111,116,111,103,114,97,112,
+104,115,105,100,101,110,116,105,102,121,105,110,103,72,105,115,116,111,114,121,
+32,111,102,32,82,101,112,117,98,108,105,99,32,111,102,110,101,99,101,115,115,97,
+114,105,108,121,112,114,111,98,97,98,105,108,105,116,121,116,101,99,104,110,105,
+99,97,108,108,121,108,101,97,118,105,110,103,32,116,104,101,115,112,101,99,116,
+97,99,117,108,97,114,102,114,97,99,116,105,111,110,32,111,102,101,108,101,99,116
+,114,105,99,105,116,121,104,101,97,100,32,111,102,32,116,104,101,114,101,115,116
+,97,117,114,97,110,116,115,112,97,114,116,110,101,114,115,104,105,112,101,109,
+112,104,97,115,105,115,32,111,110,109,111,115,116,32,114,101,99,101,110,116,115,
+104,97,114,101,32,119,105,116,104,32,115,97,121,105,110,103,32,116,104,97,116,
+102,105,108,108,101,100,32,119,105,116,104,100,101,115,105,103,110,101,100,32,
+116,111,105,116,32,105,115,32,111,102,116,101,110,34,62,60,47,105,102,114,97,109
+,101,62,97,115,32,102,111,108,108,111,119,115,58,109,101,114,103,101,100,32,119,
+105,116,104,116,104,114,111,117,103,104,32,116,104,101,99,111,109,109,101,114,99
+,105,97,108,32,112,111,105,110,116,101,100,32,111,117,116,111,112,112,111,114,
+116,117,110,105,116,121,118,105,101,119,32,111,102,32,116,104,101,114,101,113,
+117,105,114,101,109,101,110,116,100,105,118,105,115,105,111,110,32,111,102,112,
+114,111,103,114,97,109,109,105,110,103,104,101,32,114,101,99,101,105,118,101,100
+,115,101,116,73,110,116,101,114,118,97,108,34,62,60,47,115,112,97,110,62,60,47,
+105,110,32,78,101,119,32,89,111,114,107,97,100,100,105,116,105,111,110,97,108,32
+,99,111,109,112,114,101,115,115,105,111,110,10,10,60,100,105,118,32,105,100,61,
+34,105,110,99,111,114,112,111,114,97,116,101,59,60,47,115,99,114,105,112,116,62,
+60,97,116,116,97,99,104,69,118,101,110,116,98,101,99,97,109,101,32,116,104,101,
+32,34,32,116,97,114,103,101,116,61,34,95,99,97,114,114,105,101,100,32,111,117,
+116,83,111,109,101,32,111,102,32,116,104,101,115,99,105,101,110,99,101,32,97,110
+,100,116,104,101,32,116,105,109,101,32,111,102,67,111,110,116,97,105,110,101,114
+,34,62,109,97,105,110,116,97,105,110,105,110,103,67,104,114,105,115,116,111,112,
+104,101,114,77,117,99,104,32,111,102,32,116,104,101,119,114,105,116,105,110,103,
+115,32,111,102,34,32,104,101,105,103,104,116,61,34,50,115,105,122,101,32,111,102
+,32,116,104,101,118,101,114,115,105,111,110,32,111,102,32,109,105,120,116,117,
+114,101,32,111,102,32,98,101,116,119,101,101,110,32,116,104,101,69,120,97,109,
+112,108,101,115,32,111,102,101,100,117,99,97,116,105,111,110,97,108,99,111,109,
+112,101,116,105,116,105,118,101,32,111,110,115,117,98,109,105,116,61,34,100,105,
+114,101,99,116,111,114,32,111,102,100,105,115,116,105,110,99,116,105,118,101,47,
+68,84,68,32,88,72,84,77,76,32,114,101,108,97,116,105,110,103,32,116,111,116,101,
+110,100,101,110,99,121,32,116,111,112,114,111,118,105,110,99,101,32,111,102,119,
+104,105,99,104,32,119,111,117,108,100,100,101,115,112,105,116,101,32,116,104,101
+,115,99,105,101,110,116,105,102,105,99,32,108,101,103,105,115,108,97,116,117,114
+,101,46,105,110,110,101,114,72,84,77,76,32,97,108,108,101,103,97,116,105,111,110
+,115,65,103,114,105,99,117,108,116,117,114,101,119,97,115,32,117,115,101,100,32,
+105,110,97,112,112,114,111,97,99,104,32,116,111,105,110,116,101,108,108,105,103,
+101,110,116,121,101,97,114,115,32,108,97,116,101,114,44,115,97,110,115,45,115,
+101,114,105,102,100,101,116,101,114,109,105,110,105,110,103,80,101,114,102,111,
+114,109,97,110,99,101,97,112,112,101,97,114,97,110,99,101,115,44,32,119,104,105,
+99,104,32,105,115,32,102,111,117,110,100,97,116,105,111,110,115,97,98,98,114,101
+,118,105,97,116,101,100,104,105,103,104,101,114,32,116,104,97,110,115,32,102,114
+,111,109,32,116,104,101,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109,
+112,111,115,101,100,32,111,102,115,117,112,112,111,115,101,100,32,116,111,99,108
+,97,105,109,115,32,116,104,97,116,97,116,116,114,105,98,117,116,105,111,110,102,
+111,110,116,45,115,105,122,101,58,49,101,108,101,109,101,110,116,115,32,111,102,
+72,105,115,116,111,114,105,99,97,108,32,104,105,115,32,98,114,111,116,104,101,
+114,97,116,32,116,104,101,32,116,105,109,101,97,110,110,105,118,101,114,115,97,
+114,121,103,111,118,101,114,110,101,100,32,98,121,114,101,108,97,116,101,100,32,
+116,111,32,117,108,116,105,109,97,116,101,108,121,32,105,110,110,111,118,97,116,
+105,111,110,115,105,116,32,105,115,32,115,116,105,108,108,99,97,110,32,111,110,
+108,121,32,98,101,100,101,102,105,110,105,116,105,111,110,115,116,111,71,77,84,
+83,116,114,105,110,103,65,32,110,117,109,98,101,114,32,111,102,105,109,103,32,99
+,108,97,115,115,61,34,69,118,101,110,116,117,97,108,108,121,44,119,97,115,32,99,
+104,97,110,103,101,100,111,99,99,117,114,114,101,100,32,105,110,110,101,105,103,
+104,98,111,114,105,110,103,100,105,115,116,105,110,103,117,105,115,104,119,104,
+101,110,32,104,101,32,119,97,115,105,110,116,114,111,100,117,99,105,110,103,116,
+101,114,114,101,115,116,114,105,97,108,77,97,110,121,32,111,102,32,116,104,101,
+97,114,103,117,101,115,32,116,104,97,116,97,110,32,65,109,101,114,105,99,97,110,
+99,111,110,113,117,101,115,116,32,111,102,119,105,100,101,115,112,114,101,97,100
+,32,119,101,114,101,32,107,105,108,108,101,100,115,99,114,101,101,110,32,97,110,
+100,32,73,110,32,111,114,100,101,114,32,116,111,101,120,112,101,99,116,101,100,
+32,116,111,100,101,115,99,101,110,100,97,110,116,115,97,114,101,32,108,111,99,97
+,116,101,100,108,101,103,105,115,108,97,116,105,118,101,103,101,110,101,114,97,
+116,105,111,110,115,32,98,97,99,107,103,114,111,117,110,100,109,111,115,116,32,
+112,101,111,112,108,101,121,101,97,114,115,32,97,102,116,101,114,116,104,101,114
+,101,32,105,115,32,110,111,116,104,101,32,104,105,103,104,101,115,116,102,114,
+101,113,117,101,110,116,108,121,32,116,104,101,121,32,100,111,32,110,111,116,97,
+114,103,117,101,100,32,116,104,97,116,115,104,111,119,101,100,32,116,104,97,116,
+112,114,101,100,111,109,105,110,97,110,116,116,104,101,111,108,111,103,105,99,97
+,108,98,121,32,116,104,101,32,116,105,109,101,99,111,110,115,105,100,101,114,105
+,110,103,115,104,111,114,116,45,108,105,118,101,100,60,47,115,112,97,110,62,60,
+47,97,62,99,97,110,32,98,101,32,117,115,101,100,118,101,114,121,32,108,105,116,
+116,108,101,111,110,101,32,111,102,32,116,104,101,32,104,97,100,32,97,108,114,
+101,97,100,121,105,110,116,101,114,112,114,101,116,101,100,99,111,109,109,117,
+110,105,99,97,116,101,102,101,97,116,117,114,101,115,32,111,102,103,111,118,101,
+114,110,109,101,110,116,44,60,47,110,111,115,99,114,105,112,116,62,101,110,116,
+101,114,101,100,32,116,104,101,34,32,104,101,105,103,104,116,61,34,51,73,110,100
+,101,112,101,110,100,101,110,116,112,111,112,117,108,97,116,105,111,110,115,108,
+97,114,103,101,45,115,99,97,108,101,46,32,65,108,116,104,111,117,103,104,32,117,
+115,101,100,32,105,110,32,116,104,101,100,101,115,116,114,117,99,116,105,111,110
+,112,111,115,115,105,98,105,108,105,116,121,115,116,97,114,116,105,110,103,32,
+105,110,116,119,111,32,111,114,32,109,111,114,101,101,120,112,114,101,115,115,
+105,111,110,115,115,117,98,111,114,100,105,110,97,116,101,108,97,114,103,101,114
+,32,116,104,97,110,104,105,115,116,111,114,121,32,97,110,100,60,47,111,112,116,
+105,111,110,62,13,10,67,111,110,116,105,110,101,110,116,97,108,101,108,105,109,
+105,110,97,116,105,110,103,119,105,108,108,32,110,111,116,32,98,101,112,114,97,
+99,116,105,99,101,32,111,102,105,110,32,102,114,111,110,116,32,111,102,115,105,
+116,101,32,111,102,32,116,104,101,101,110,115,117,114,101,32,116,104,97,116,116,
+111,32,99,114,101,97,116,101,32,97,109,105,115,115,105,115,115,105,112,112,105,
+112,111,116,101,110,116,105,97,108,108,121,111,117,116,115,116,97,110,100,105,
+110,103,98,101,116,116,101,114,32,116,104,97,110,119,104,97,116,32,105,115,32,
+110,111,119,115,105,116,117,97,116,101,100,32,105,110,109,101,116,97,32,110,97,
+109,101,61,34,84,114,97,100,105,116,105,111,110,97,108,115,117,103,103,101,115,
+116,105,111,110,115,84,114,97,110,115,108,97,116,105,111,110,116,104,101,32,102,
+111,114,109,32,111,102,97,116,109,111,115,112,104,101,114,105,99,105,100,101,111
+,108,111,103,105,99,97,108,101,110,116,101,114,112,114,105,115,101,115,99,97,108
+,99,117,108,97,116,105,110,103,101,97,115,116,32,111,102,32,116,104,101,114,101,
+109,110,97,110,116,115,32,111,102,112,108,117,103,105,110,115,112,97,103,101,47,
+105,110,100,101,120,46,112,104,112,63,114,101,109,97,105,110,101,100,32,105,110,
+116,114,97,110,115,102,111,114,109,101,100,72,101,32,119,97,115,32,97,108,115,
+111,119,97,115,32,97,108,114,101,97,100,121,115,116,97,116,105,115,116,105,99,97
+,108,105,110,32,102,97,118,111,114,32,111,102,77,105,110,105,115,116,114,121,32,
+111,102,109,111,118,101,109,101,110,116,32,111,102,102,111,114,109,117,108,97,
+116,105,111,110,105,115,32,114,101,113,117,105,114,101,100,60,108,105,110,107,32
+,114,101,108,61,34,84,104,105,115,32,105,115,32,116,104,101,32,60,97,32,104,114,
+101,102,61,34,47,112,111,112,117,108,97,114,105,122,101,100,105,110,118,111,108,
+118,101,100,32,105,110,97,114,101,32,117,115,101,100,32,116,111,97,110,100,32,
+115,101,118,101,114,97,108,109,97,100,101,32,98,121,32,116,104,101,115,101,101,
+109,115,32,116,111,32,98,101,108,105,107,101,108,121,32,116,104,97,116,80,97,108
+,101,115,116,105,110,105,97,110,110,97,109,101,100,32,97,102,116,101,114,105,116
+,32,104,97,100,32,98,101,101,110,109,111,115,116,32,99,111,109,109,111,110,116,
+111,32,114,101,102,101,114,32,116,111,98,117,116,32,116,104,105,115,32,105,115,
+99,111,110,115,101,99,117,116,105,118,101,116,101,109,112,111,114,97,114,105,108
+,121,73,110,32,103,101,110,101,114,97,108,44,99,111,110,118,101,110,116,105,111,
+110,115,116,97,107,101,115,32,112,108,97,99,101,115,117,98,100,105,118,105,115,
+105,111,110,116,101,114,114,105,116,111,114,105,97,108,111,112,101,114,97,116,
+105,111,110,97,108,112,101,114,109,97,110,101,110,116,108,121,119,97,115,32,108,
+97,114,103,101,108,121,111,117,116,98,114,101,97,107,32,111,102,105,110,32,116,
+104,101,32,112,97,115,116,102,111,108,108,111,119,105,110,103,32,97,32,120,109,
+108,110,115,58,111,103,61,34,62,60,97,32,99,108,97,115,115,61,34,99,108,97,115,
+115,61,34,116,101,120,116,67,111,110,118,101,114,115,105,111,110,32,109,97,121,
+32,98,101,32,117,115,101,100,109,97,110,117,102,97,99,116,117,114,101,97,102,116
+,101,114,32,98,101,105,110,103,99,108,101,97,114,102,105,120,34,62,10,113,117,
+101,115,116,105,111,110,32,111,102,119,97,115,32,101,108,101,99,116,101,100,116,
+111,32,98,101,99,111,109,101,32,97,98,101,99,97,117,115,101,32,111,102,32,115,
+111,109,101,32,112,101,111,112,108,101,105,110,115,112,105,114,101,100,32,98,121
+,115,117,99,99,101,115,115,102,117,108,32,97,32,116,105,109,101,32,119,104,101,
+110,109,111,114,101,32,99,111,109,109,111,110,97,109,111,110,103,115,116,32,116,
+104,101,97,110,32,111,102,102,105,99,105,97,108,119,105,100,116,104,58,49,48,48,
+37,59,116,101,99,104,110,111,108,111,103,121,44,119,97,115,32,97,100,111,112,116
+,101,100,116,111,32,107,101,101,112,32,116,104,101,115,101,116,116,108,101,109,
+101,110,116,115,108,105,118,101,32,98,105,114,116,104,115,105,110,100,101,120,46
+,104,116,109,108,34,67,111,110,110,101,99,116,105,99,117,116,97,115,115,105,103,
+110,101,100,32,116,111,38,97,109,112,59,116,105,109,101,115,59,97,99,99,111,117,
+110,116,32,102,111,114,97,108,105,103,110,61,114,105,103,104,116,116,104,101,32,
+99,111,109,112,97,110,121,97,108,119,97,121,115,32,98,101,101,110,114,101,116,
+117,114,110,101,100,32,116,111,105,110,118,111,108,118,101,109,101,110,116,66,
+101,99,97,117,115,101,32,116,104,101,116,104,105,115,32,112,101,114,105,111,100,
+34,32,110,97,109,101,61,34,113,34,32,99,111,110,102,105,110,101,100,32,116,111,
+97,32,114,101,115,117,108,116,32,111,102,118,97,108,117,101,61,34,34,32,47,62,
+105,115,32,97,99,116,117,97,108,108,121,69,110,118,105,114,111,110,109,101,110,
+116,13,10,60,47,104,101,97,100,62,13,10,67,111,110,118,101,114,115,101,108,121,
+44,62,10,60,100,105,118,32,105,100,61,34,48,34,32,119,105,100,116,104,61,34,49,
+105,115,32,112,114,111,98,97,98,108,121,104,97,118,101,32,98,101,99,111,109,101,
+99,111,110,116,114,111,108,108,105,110,103,116,104,101,32,112,114,111,98,108,101
+,109,99,105,116,105,122,101,110,115,32,111,102,112,111,108,105,116,105,99,105,97
+,110,115,114,101,97,99,104,101,100,32,116,104,101,97,115,32,101,97,114,108,121,
+32,97,115,58,110,111,110,101,59,32,111,118,101,114,60,116,97,98,108,101,32,99,
+101,108,108,118,97,108,105,100,105,116,121,32,111,102,100,105,114,101,99,116,108
+,121,32,116,111,111,110,109,111,117,115,101,100,111,119,110,119,104,101,114,101,
+32,105,116,32,105,115,119,104,101,110,32,105,116,32,119,97,115,109,101,109,98,
+101,114,115,32,111,102,32,114,101,108,97,116,105,111,110,32,116,111,97,99,99,111
+,109,109,111,100,97,116,101,97,108,111,110,103,32,119,105,116,104,32,73,110,32,
+116,104,101,32,108,97,116,101,116,104,101,32,69,110,103,108,105,115,104,100,101,
+108,105,99,105,111,117,115,34,62,116,104,105,115,32,105,115,32,110,111,116,116,
+104,101,32,112,114,101,115,101,110,116,105,102,32,116,104,101,121,32,97,114,101,
+97,110,100,32,102,105,110,97,108,108,121,97,32,109,97,116,116,101,114,32,111,102
+,13,10,9,60,47,100,105,118,62,13,10,13,10,60,47,115,99,114,105,112,116,62,102,97
+,115,116,101,114,32,116,104,97,110,109,97,106,111,114,105,116,121,32,111,102,97,
+102,116,101,114,32,119,104,105,99,104,99,111,109,112,97,114,97,116,105,118,101,
+116,111,32,109,97,105,110,116,97,105,110,105,109,112,114,111,118,101,32,116,104,
+101,97,119,97,114,100,101,100,32,116,104,101,101,114,34,32,99,108,97,115,115,61,
+34,102,114,97,109,101,98,111,114,100,101,114,114,101,115,116,111,114,97,116,105,
+111,110,105,110,32,116,104,101,32,115,97,109,101,97,110,97,108,121,115,105,115,
+32,111,102,116,104,101,105,114,32,102,105,114,115,116,68,117,114,105,110,103,32,
+116,104,101,32,99,111,110,116,105,110,101,110,116,97,108,115,101,113,117,101,110
+,99,101,32,111,102,102,117,110,99,116,105,111,110,40,41,123,102,111,110,116,45,
+115,105,122,101,58,32,119,111,114,107,32,111,110,32,116,104,101,60,47,115,99,114
+,105,112,116,62,10,60,98,101,103,105,110,115,32,119,105,116,104,106,97,118,97,
+115,99,114,105,112,116,58,99,111,110,115,116,105,116,117,101,110,116,119,97,115,
+32,102,111,117,110,100,101,100,101,113,117,105,108,105,98,114,105,117,109,97,115
+,115,117,109,101,32,116,104,97,116,105,115,32,103,105,118,101,110,32,98,121,110,
+101,101,100,115,32,116,111,32,98,101,99,111,111,114,100,105,110,97,116,101,115,
+116,104,101,32,118,97,114,105,111,117,115,97,114,101,32,112,97,114,116,32,111,
+102,111,110,108,121,32,105,110,32,116,104,101,115,101,99,116,105,111,110,115,32,
+111,102,105,115,32,97,32,99,111,109,109,111,110,116,104,101,111,114,105,101,115,
+32,111,102,100,105,115,99,111,118,101,114,105,101,115,97,115,115,111,99,105,97,
+116,105,111,110,101,100,103,101,32,111,102,32,116,104,101,115,116,114,101,110,
+103,116,104,32,111,102,112,111,115,105,116,105,111,110,32,105,110,112,114,101,
+115,101,110,116,45,100,97,121,117,110,105,118,101,114,115,97,108,108,121,116,111
+,32,102,111,114,109,32,116,104,101,98,117,116,32,105,110,115,116,101,97,100,99,
+111,114,112,111,114,97,116,105,111,110,97,116,116,97,99,104,101,100,32,116,111,
+105,115,32,99,111,109,109,111,110,108,121,114,101,97,115,111,110,115,32,102,111,
+114,32,38,113,117,111,116,59,116,104,101,32,99,97,110,32,98,101,32,109,97,100,
+101,119,97,115,32,97,98,108,101,32,116,111,119,104,105,99,104,32,109,101,97,110,
+115,98,117,116,32,100,105,100,32,110,111,116,111,110,77,111,117,115,101,79,118,
+101,114,97,115,32,112,111,115,115,105,98,108,101,111,112,101,114,97,116,101,100,
+32,98,121,99,111,109,105,110,103,32,102,114,111,109,116,104,101,32,112,114,105,
+109,97,114,121,97,100,100,105,116,105,111,110,32,111,102,102,111,114,32,115,101,
+118,101,114,97,108,116,114,97,110,115,102,101,114,114,101,100,97,32,112,101,114,
+105,111,100,32,111,102,97,114,101,32,97,98,108,101,32,116,111,104,111,119,101,
+118,101,114,44,32,105,116,115,104,111,117,108,100,32,104,97,118,101,109,117,99,
+104,32,108,97,114,103,101,114,10,9,60,47,115,99,114,105,112,116,62,97,100,111,
+112,116,101,100,32,116,104,101,112,114,111,112,101,114,116,121,32,111,102,100,
+105,114,101,99,116,101,100,32,98,121,101,102,102,101,99,116,105,118,101,108,121,
+119,97,115,32,98,114,111,117,103,104,116,99,104,105,108,100,114,101,110,32,111,
+102,80,114,111,103,114,97,109,109,105,110,103,108,111,110,103,101,114,32,116,104
+,97,110,109,97,110,117,115,99,114,105,112,116,115,119,97,114,32,97,103,97,105,
+110,115,116,98,121,32,109,101,97,110,115,32,111,102,97,110,100,32,109,111,115,
+116,32,111,102,115,105,109,105,108,97,114,32,116,111,32,112,114,111,112,114,105,
+101,116,97,114,121,111,114,105,103,105,110,97,116,105,110,103,112,114,101,115,
+116,105,103,105,111,117,115,103,114,97,109,109,97,116,105,99,97,108,101,120,112,
+101,114,105,101,110,99,101,46,116,111,32,109,97,107,101,32,116,104,101,73,116,32
+,119,97,115,32,97,108,115,111,105,115,32,102,111,117,110,100,32,105,110,99,111,
+109,112,101,116,105,116,111,114,115,105,110,32,116,104,101,32,85,46,83,46,114,
+101,112,108,97,99,101,32,116,104,101,98,114,111,117,103,104,116,32,116,104,101,
+99,97,108,99,117,108,97,116,105,111,110,102,97,108,108,32,111,102,32,116,104,101
+,116,104,101,32,103,101,110,101,114,97,108,112,114,97,99,116,105,99,97,108,108,
+121,105,110,32,104,111,110,111,114,32,111,102,114,101,108,101,97,115,101,100,32,
+105,110,114,101,115,105,100,101,110,116,105,97,108,97,110,100,32,115,111,109,101
+,32,111,102,107,105,110,103,32,111,102,32,116,104,101,114,101,97,99,116,105,111,
+110,32,116,111,49,115,116,32,69,97,114,108,32,111,102,99,117,108,116,117,114,101
+,32,97,110,100,112,114,105,110,99,105,112,97,108,108,121,60,47,116,105,116,108,
+101,62,10,32,32,116,104,101,121,32,99,97,110,32,98,101,98,97,99,107,32,116,111,
+32,116,104,101,115,111,109,101,32,111,102,32,104,105,115,101,120,112,111,115,117
+,114,101,32,116,111,97,114,101,32,115,105,109,105,108,97,114,102,111,114,109,32,
+111,102,32,116,104,101,97,100,100,70,97,118,111,114,105,116,101,99,105,116,105,
+122,101,110,115,104,105,112,112,97,114,116,32,105,110,32,116,104,101,112,101,111
+,112,108,101,32,119,105,116,104,105,110,32,112,114,97,99,116,105,99,101,116,111,
+32,99,111,110,116,105,110,117,101,38,97,109,112,59,109,105,110,117,115,59,97,112
+,112,114,111,118,101,100,32,98,121,32,116,104,101,32,102,105,114,115,116,32,97,
+108,108,111,119,101,100,32,116,104,101,97,110,100,32,102,111,114,32,116,104,101,
+102,117,110,99,116,105,111,110,105,110,103,112,108,97,121,105,110,103,32,116,104
+,101,115,111,108,117,116,105,111,110,32,116,111,104,101,105,103,104,116,61,34,48
+,34,32,105,110,32,104,105,115,32,98,111,111,107,109,111,114,101,32,116,104,97,
+110,32,97,102,111,108,108,111,119,115,32,116,104,101,99,114,101,97,116,101,100,
+32,116,104,101,112,114,101,115,101,110,99,101,32,105,110,38,110,98,115,112,59,60
+,47,116,100,62,110,97,116,105,111,110,97,108,105,115,116,116,104,101,32,105,100,
+101,97,32,111,102,97,32,99,104,97,114,97,99,116,101,114,119,101,114,101,32,102,
+111,114,99,101,100,32,99,108,97,115,115,61,34,98,116,110,100,97,121,115,32,111,
+102,32,116,104,101,102,101,97,116,117,114,101,100,32,105,110,115,104,111,119,105
+,110,103,32,116,104,101,105,110,116,101,114,101,115,116,32,105,110,105,110,32,
+112,108,97,99,101,32,111,102,116,117,114,110,32,111,102,32,116,104,101,116,104,
+101,32,104,101,97,100,32,111,102,76,111,114,100,32,111,102,32,116,104,101,112,
+111,108,105,116,105,99,97,108,108,121,104,97,115,32,105,116,115,32,111,119,110,
+69,100,117,99,97,116,105,111,110,97,108,97,112,112,114,111,118,97,108,32,111,102
+,115,111,109,101,32,111,102,32,116,104,101,101,97,99,104,32,111,116,104,101,114,
+44,98,101,104,97,118,105,111,114,32,111,102,97,110,100,32,98,101,99,97,117,115,
+101,97,110,100,32,97,110,111,116,104,101,114,97,112,112,101,97,114,101,100,32,
+111,110,114,101,99,111,114,100,101,100,32,105,110,98,108,97,99,107,38,113,117,
+111,116,59,109,97,121,32,105,110,99,108,117,100,101,116,104,101,32,119,111,114,
+108,100,39,115,99,97,110,32,108,101,97,100,32,116,111,114,101,102,101,114,115,32
+,116,111,32,97,98,111,114,100,101,114,61,34,48,34,32,103,111,118,101,114,110,109
+,101,110,116,32,119,105,110,110,105,110,103,32,116,104,101,114,101,115,117,108,
+116,101,100,32,105,110,32,119,104,105,108,101,32,116,104,101,32,87,97,115,104,
+105,110,103,116,111,110,44,116,104,101,32,115,117,98,106,101,99,116,99,105,116,
+121,32,105,110,32,116,104,101,62,60,47,100,105,118,62,13,10,9,9,114,101,102,108,
+101,99,116,32,116,104,101,116,111,32,99,111,109,112,108,101,116,101,98,101,99,97
+,109,101,32,109,111,114,101,114,97,100,105,111,97,99,116,105,118,101,114,101,106
+,101,99,116,101,100,32,98,121,119,105,116,104,111,117,116,32,97,110,121,104,105,
+115,32,102,97,116,104,101,114,44,119,104,105,99,104,32,99,111,117,108,100,99,111
+,112,121,32,111,102,32,116,104,101,116,111,32,105,110,100,105,99,97,116,101,97,
+32,112,111,108,105,116,105,99,97,108,97,99,99,111,117,110,116,115,32,111,102,99,
+111,110,115,116,105,116,117,116,101,115,119,111,114,107,101,100,32,119,105,116,
+104,101,114,60,47,97,62,60,47,108,105,62,111,102,32,104,105,115,32,108,105,102,
+101,97,99,99,111,109,112,97,110,105,101,100,99,108,105,101,110,116,87,105,100,
+116,104,112,114,101,118,101,110,116,32,116,104,101,76,101,103,105,115,108,97,116
+,105,118,101,100,105,102,102,101,114,101,110,116,108,121,116,111,103,101,116,104
+,101,114,32,105,110,104,97,115,32,115,101,118,101,114,97,108,102,111,114,32,97,
+110,111,116,104,101,114,116,101,120,116,32,111,102,32,116,104,101,102,111,117,
+110,100,101,100,32,116,104,101,101,32,119,105,116,104,32,116,104,101,32,105,115,
+32,117,115,101,100,32,102,111,114,99,104,97,110,103,101,100,32,116,104,101,117,
+115,117,97,108,108,121,32,116,104,101,112,108,97,99,101,32,119,104,101,114,101,
+119,104,101,114,101,97,115,32,116,104,101,62,32,60,97,32,104,114,101,102,61,34,
+34,62,60,97,32,104,114,101,102,61,34,116,104,101,109,115,101,108,118,101,115,44,
+97,108,116,104,111,117,103,104,32,104,101,116,104,97,116,32,99,97,110,32,98,101,
+116,114,97,100,105,116,105,111,110,97,108,114,111,108,101,32,111,102,32,116,104,
+101,97,115,32,97,32,114,101,115,117,108,116,114,101,109,111,118,101,67,104,105,
+108,100,100,101,115,105,103,110,101,100,32,98,121,119,101,115,116,32,111,102,32,
+116,104,101,83,111,109,101,32,112,101,111,112,108,101,112,114,111,100,117,99,116
+,105,111,110,44,115,105,100,101,32,111,102,32,116,104,101,110,101,119,115,108,
+101,116,116,101,114,115,117,115,101,100,32,98,121,32,116,104,101,100,111,119,110
+,32,116,111,32,116,104,101,97,99,99,101,112,116,101,100,32,98,121,108,105,118,
+101,32,105,110,32,116,104,101,97,116,116,101,109,112,116,115,32,116,111,111,117,
+116,115,105,100,101,32,116,104,101,102,114,101,113,117,101,110,99,105,101,115,72
+,111,119,101,118,101,114,44,32,105,110,112,114,111,103,114,97,109,109,101,114,
+115,97,116,32,108,101,97,115,116,32,105,110,97,112,112,114,111,120,105,109,97,
+116,101,97,108,116,104,111,117,103,104,32,105,116,119,97,115,32,112,97,114,116,
+32,111,102,97,110,100,32,118,97,114,105,111,117,115,71,111,118,101,114,110,111,
+114,32,111,102,116,104,101,32,97,114,116,105,99,108,101,116,117,114,110,101,100,
+32,105,110,116,111,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,101,99,
+111,110,111,109,121,105,115,32,116,104,101,32,109,111,115,116,109,111,115,116,32
+,119,105,100,101,108,121,119,111,117,108,100,32,108,97,116,101,114,97,110,100,32
+,112,101,114,104,97,112,115,114,105,115,101,32,116,111,32,116,104,101,111,99,99,
+117,114,115,32,119,104,101,110,117,110,100,101,114,32,119,104,105,99,104,99,111,
+110,100,105,116,105,111,110,115,46,116,104,101,32,119,101,115,116,101,114,110,
+116,104,101,111,114,121,32,116,104,97,116,105,115,32,112,114,111,100,117,99,101,
+100,116,104,101,32,99,105,116,121,32,111,102,105,110,32,119,104,105,99,104,32,
+104,101,115,101,101,110,32,105,110,32,116,104,101,116,104,101,32,99,101,110,116,
+114,97,108,98,117,105,108,100,105,110,103,32,111,102,109,97,110,121,32,111,102,
+32,104,105,115,97,114,101,97,32,111,102,32,116,104,101,105,115,32,116,104,101,32
+,111,110,108,121,109,111,115,116,32,111,102,32,116,104,101,109,97,110,121,32,111
+,102,32,116,104,101,116,104,101,32,87,101,115,116,101,114,110,84,104,101,114,101
+,32,105,115,32,110,111,101,120,116,101,110,100,101,100,32,116,111,83,116,97,116,
+105,115,116,105,99,97,108,99,111,108,115,112,97,110,61,50,32,124,115,104,111,114
+,116,32,115,116,111,114,121,112,111,115,115,105,98,108,101,32,116,111,116,111,
+112,111,108,111,103,105,99,97,108,99,114,105,116,105,99,97,108,32,111,102,114,
+101,112,111,114,116,101,100,32,116,111,97,32,67,104,114,105,115,116,105,97,110,
+100,101,99,105,115,105,111,110,32,116,111,105,115,32,101,113,117,97,108,32,116,
+111,112,114,111,98,108,101,109,115,32,111,102,84,104,105,115,32,99,97,110,32,98,
+101,109,101,114,99,104,97,110,100,105,115,101,102,111,114,32,109,111,115,116,32,
+111,102,110,111,32,101,118,105,100,101,110,99,101,101,100,105,116,105,111,110,
+115,32,111,102,101,108,101,109,101,110,116,115,32,105,110,38,113,117,111,116,59,
+46,32,84,104,101,99,111,109,47,105,109,97,103,101,115,47,119,104,105,99,104,32,
+109,97,107,101,115,116,104,101,32,112,114,111,99,101,115,115,114,101,109,97,105,
+110,115,32,116,104,101,108,105,116,101,114,97,116,117,114,101,44,105,115,32,97,
+32,109,101,109,98,101,114,116,104,101,32,112,111,112,117,108,97,114,116,104,101,
+32,97,110,99,105,101,110,116,112,114,111,98,108,101,109,115,32,105,110,116,105,
+109,101,32,111,102,32,116,104,101,100,101,102,101,97,116,101,100,32,98,121,98,
+111,100,121,32,111,102,32,116,104,101,97,32,102,101,119,32,121,101,97,114,115,
+109,117,99,104,32,111,102,32,116,104,101,116,104,101,32,119,111,114,107,32,111,
+102,67,97,108,105,102,111,114,110,105,97,44,115,101,114,118,101,100,32,97,115,32
+,97,103,111,118,101,114,110,109,101,110,116,46,99,111,110,99,101,112,116,115,32,
+111,102,109,111,118,101,109,101,110,116,32,105,110,9,9,60,100,105,118,32,105,100
+,61,34,105,116,34,32,118,97,108,117,101,61,34,108,97,110,103,117,97,103,101,32,
+111,102,97,115,32,116,104,101,121,32,97,114,101,112,114,111,100,117,99,101,100,
+32,105,110,105,115,32,116,104,97,116,32,116,104,101,101,120,112,108,97,105,110,
+32,116,104,101,100,105,118,62,60,47,100,105,118,62,10,72,111,119,101,118,101,114
+,32,116,104,101,108,101,97,100,32,116,111,32,116,104,101,9,60,97,32,104,114,101,
+102,61,34,47,119,97,115,32,103,114,97,110,116,101,100,112,101,111,112,108,101,32
+,104,97,118,101,99,111,110,116,105,110,117,97,108,108,121,119,97,115,32,115,101,
+101,110,32,97,115,97,110,100,32,114,101,108,97,116,101,100,116,104,101,32,114,
+111,108,101,32,111,102,112,114,111,112,111,115,101,100,32,98,121,111,102,32,116,
+104,101,32,98,101,115,116,101,97,99,104,32,111,116,104,101,114,46,67,111,110,115
+,116,97,110,116,105,110,101,112,101,111,112,108,101,32,102,114,111,109,100,105,
+97,108,101,99,116,115,32,111,102,116,111,32,114,101,118,105,115,105,111,110,119,
+97,115,32,114,101,110,97,109,101,100,97,32,115,111,117,114,99,101,32,111,102,116
+,104,101,32,105,110,105,116,105,97,108,108,97,117,110,99,104,101,100,32,105,110,
+112,114,111,118,105,100,101,32,116,104,101,116,111,32,116,104,101,32,119,101,115
+,116,119,104,101,114,101,32,116,104,101,114,101,97,110,100,32,115,105,109,105,
+108,97,114,98,101,116,119,101,101,110,32,116,119,111,105,115,32,97,108,115,111,
+32,116,104,101,69,110,103,108,105,115,104,32,97,110,100,99,111,110,100,105,116,
+105,111,110,115,44,116,104,97,116,32,105,116,32,119,97,115,101,110,116,105,116,
+108,101,100,32,116,111,116,104,101,109,115,101,108,118,101,115,46,113,117,97,110
+,116,105,116,121,32,111,102,114,97,110,115,112,97,114,101,110,99,121,116,104,101
+,32,115,97,109,101,32,97,115,116,111,32,106,111,105,110,32,116,104,101,99,111,
+117,110,116,114,121,32,97,110,100,116,104,105,115,32,105,115,32,116,104,101,84,
+104,105,115,32,108,101,100,32,116,111,97,32,115,116,97,116,101,109,101,110,116,
+99,111,110,116,114,97,115,116,32,116,111,108,97,115,116,73,110,100,101,120,79,
+102,116,104,114,111,117,103,104,32,104,105,115,105,115,32,100,101,115,105,103,
+110,101,100,116,104,101,32,116,101,114,109,32,105,115,105,115,32,112,114,111,118
+,105,100,101,100,112,114,111,116,101,99,116,32,116,104,101,110,103,60,47,97,62,
+60,47,108,105,62,84,104,101,32,99,117,114,114,101,110,116,116,104,101,32,115,105
+,116,101,32,111,102,115,117,98,115,116,97,110,116,105,97,108,101,120,112,101,114
+,105,101,110,99,101,44,105,110,32,116,104,101,32,87,101,115,116,116,104,101,121,
+32,115,104,111,117,108,100,115,108,111,118,101,110,196,141,105,110,97,99,111,109
+,101,110,116,97,114,105,111,115,117,110,105,118,101,114,115,105,100,97,100,99,
+111,110,100,105,99,105,111,110,101,115,97,99,116,105,118,105,100,97,100,101,115,
+101,120,112,101,114,105,101,110,99,105,97,116,101,99,110,111,108,111,103,195,173
+,97,112,114,111,100,117,99,99,105,195,179,110,112,117,110,116,117,97,99,105,195,
+179,110,97,112,108,105,99,97,99,105,195,179,110,99,111,110,116,114,97,115,101,
+195,177,97,99,97,116,101,103,111,114,195,173,97,115,114,101,103,105,115,116,114,
+97,114,115,101,112,114,111,102,101,115,105,111,110,97,108,116,114,97,116,97,109,
+105,101,110,116,111,114,101,103,195,173,115,116,114,97,116,101,115,101,99,114,
+101,116,97,114,195,173,97,112,114,105,110,99,105,112,97,108,101,115,112,114,111,
+116,101,99,99,105,195,179,110,105,109,112,111,114,116,97,110,116,101,115,105,109
+,112,111,114,116,97,110,99,105,97,112,111,115,105,98,105,108,105,100,97,100,105,
+110,116,101,114,101,115,97,110,116,101,99,114,101,99,105,109,105,101,110,116,111
+,110,101,99,101,115,105,100,97,100,101,115,115,117,115,99,114,105,98,105,114,115
+,101,97,115,111,99,105,97,99,105,195,179,110,100,105,115,112,111,110,105,98,108,
+101,115,101,118,97,108,117,97,99,105,195,179,110,101,115,116,117,100,105,97,110,
+116,101,115,114,101,115,112,111,110,115,97,98,108,101,114,101,115,111,108,117,99
+,105,195,179,110,103,117,97,100,97,108,97,106,97,114,97,114,101,103,105,115,116,
+114,97,100,111,115,111,112,111,114,116,117,110,105,100,97,100,99,111,109,101,114
+,99,105,97,108,101,115,102,111,116,111,103,114,97,102,195,173,97,97,117,116,111,
+114,105,100,97,100,101,115,105,110,103,101,110,105,101,114,195,173,97,116,101,
+108,101,118,105,115,105,195,179,110,99,111,109,112,101,116,101,110,99,105,97,111
+,112,101,114,97,99,105,111,110,101,115,101,115,116,97,98,108,101,99,105,100,111,
+115,105,109,112,108,101,109,101,110,116,101,97,99,116,117,97,108,109,101,110,116
+,101,110,97,118,101,103,97,99,105,195,179,110,99,111,110,102,111,114,109,105,100
+,97,100,108,105,110,101,45,104,101,105,103,104,116,58,102,111,110,116,45,102,97,
+109,105,108,121,58,34,32,58,32,34,104,116,116,112,58,47,47,97,112,112,108,105,99
+,97,116,105,111,110,115,108,105,110,107,34,32,104,114,101,102,61,34,115,112,101,
+99,105,102,105,99,97,108,108,121,47,47,60,33,91,67,68,65,84,65,91,10,79,114,103,
+97,110,105,122,97,116,105,111,110,100,105,115,116,114,105,98,117,116,105,111,110
+,48,112,120,59,32,104,101,105,103,104,116,58,114,101,108,97,116,105,111,110,115,
+104,105,112,100,101,118,105,99,101,45,119,105,100,116,104,60,100,105,118,32,99,
+108,97,115,115,61,34,60,108,97,98,101,108,32,102,111,114,61,34,114,101,103,105,
+115,116,114,97,116,105,111,110,60,47,110,111,115,99,114,105,112,116,62,10,47,105
+,110,100,101,120,46,104,116,109,108,34,119,105,110,100,111,119,46,111,112,101,
+110,40,32,33,105,109,112,111,114,116,97,110,116,59,97,112,112,108,105,99,97,116,
+105,111,110,47,105,110,100,101,112,101,110,100,101,110,99,101,47,47,119,119,119,
+46,103,111,111,103,108,101,111,114,103,97,110,105,122,97,116,105,111,110,97,117,
+116,111,99,111,109,112,108,101,116,101,114,101,113,117,105,114,101,109,101,110,
+116,115,99,111,110,115,101,114,118,97,116,105,118,101,60,102,111,114,109,32,110,
+97,109,101,61,34,105,110,116,101,108,108,101,99,116,117,97,108,109,97,114,103,
+105,110,45,108,101,102,116,58,49,56,116,104,32,99,101,110,116,117,114,121,97,110
+,32,105,109,112,111,114,116,97,110,116,105,110,115,116,105,116,117,116,105,111,
+110,115,97,98,98,114,101,118,105,97,116,105,111,110,60,105,109,103,32,99,108,97,
+115,115,61,34,111,114,103,97,110,105,115,97,116,105,111,110,99,105,118,105,108,
+105,122,97,116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,97,114,99
+,104,105,116,101,99,116,117,114,101,105,110,99,111,114,112,111,114,97,116,101,
+100,50,48,116,104,32,99,101,110,116,117,114,121,45,99,111,110,116,97,105,110,101
+,114,34,62,109,111,115,116,32,110,111,116,97,98,108,121,47,62,60,47,97,62,60,47,
+100,105,118,62,110,111,116,105,102,105,99,97,116,105,111,110,39,117,110,100,101,
+102,105,110,101,100,39,41,70,117,114,116,104,101,114,109,111,114,101,44,98,101,
+108,105,101,118,101,32,116,104,97,116,105,110,110,101,114,72,84,77,76,32,61,32,
+112,114,105,111,114,32,116,111,32,116,104,101,100,114,97,109,97,116,105,99,97,
+108,108,121,114,101,102,101,114,114,105,110,103,32,116,111,110,101,103,111,116,
+105,97,116,105,111,110,115,104,101,97,100,113,117,97,114,116,101,114,115,83,111,
+117,116,104,32,65,102,114,105,99,97,117,110,115,117,99,99,101,115,115,102,117,
+108,80,101,110,110,115,121,108,118,97,110,105,97,65,115,32,97,32,114,101,115,117
+,108,116,44,60,104,116,109,108,32,108,97,110,103,61,34,38,108,116,59,47,115,117,
+112,38,103,116,59,100,101,97,108,105,110,103,32,119,105,116,104,112,104,105,108,
+97,100,101,108,112,104,105,97,104,105,115,116,111,114,105,99,97,108,108,121,41,
+59,60,47,115,99,114,105,112,116,62,10,112,97,100,100,105,110,103,45,116,111,112,
+58,101,120,112,101,114,105,109,101,110,116,97,108,103,101,116,65,116,116,114,105
+,98,117,116,101,105,110,115,116,114,117,99,116,105,111,110,115,116,101,99,104,
+110,111,108,111,103,105,101,115,112,97,114,116,32,111,102,32,116,104,101,32,61,
+102,117,110,99,116,105,111,110,40,41,123,115,117,98,115,99,114,105,112,116,105,
+111,110,108,46,100,116,100,34,62,13,10,60,104,116,103,101,111,103,114,97,112,104
+,105,99,97,108,67,111,110,115,116,105,116,117,116,105,111,110,39,44,32,102,117,
+110,99,116,105,111,110,40,115,117,112,112,111,114,116,101,100,32,98,121,97,103,
+114,105,99,117,108,116,117,114,97,108,99,111,110,115,116,114,117,99,116,105,111,
+110,112,117,98,108,105,99,97,116,105,111,110,115,102,111,110,116,45,115,105,122,
+101,58,32,49,97,32,118,97,114,105,101,116,121,32,111,102,60,100,105,118,32,115,
+116,121,108,101,61,34,69,110,99,121,99,108,111,112,101,100,105,97,105,102,114,97
+,109,101,32,115,114,99,61,34,100,101,109,111,110,115,116,114,97,116,101,100,97,
+99,99,111,109,112,108,105,115,104,101,100,117,110,105,118,101,114,115,105,116,
+105,101,115,68,101,109,111,103,114,97,112,104,105,99,115,41,59,60,47,115,99,114,
+105,112,116,62,60,100,101,100,105,99,97,116,101,100,32,116,111,107,110,111,119,
+108,101,100,103,101,32,111,102,115,97,116,105,115,102,97,99,116,105,111,110,112,
+97,114,116,105,99,117,108,97,114,108,121,60,47,100,105,118,62,60,47,100,105,118,
+62,69,110,103,108,105,115,104,32,40,85,83,41,97,112,112,101,110,100,67,104,105,
+108,100,40,116,114,97,110,115,109,105,115,115,105,111,110,115,46,32,72,111,119,
+101,118,101,114,44,32,105,110,116,101,108,108,105,103,101,110,99,101,34,32,116,
+97,98,105,110,100,101,120,61,34,102,108,111,97,116,58,114,105,103,104,116,59,67,
+111,109,109,111,110,119,101,97,108,116,104,114,97,110,103,105,110,103,32,102,114
+,111,109,105,110,32,119,104,105,99,104,32,116,104,101,97,116,32,108,101,97,115,
+116,32,111,110,101,114,101,112,114,111,100,117,99,116,105,111,110,101,110,99,121
+,99,108,111,112,101,100,105,97,59,102,111,110,116,45,115,105,122,101,58,49,106,
+117,114,105,115,100,105,99,116,105,111,110,97,116,32,116,104,97,116,32,116,105,
+109,101,34,62,60,97,32,99,108,97,115,115,61,34,73,110,32,97,100,100,105,116,105,
+111,110,44,100,101,115,99,114,105,112,116,105,111,110,43,99,111,110,118,101,114,
+115,97,116,105,111,110,99,111,110,116,97,99,116,32,119,105,116,104,105,115,32,
+103,101,110,101,114,97,108,108,121,114,34,32,99,111,110,116,101,110,116,61,34,
+114,101,112,114,101,115,101,110,116,105,110,103,38,108,116,59,109,97,116,104,38,
+103,116,59,112,114,101,115,101,110,116,97,116,105,111,110,111,99,99,97,115,105,
+111,110,97,108,108,121,60,105,109,103,32,119,105,100,116,104,61,34,110,97,118,
+105,103,97,116,105,111,110,34,62,99,111,109,112,101,110,115,97,116,105,111,110,
+99,104,97,109,112,105,111,110,115,104,105,112,109,101,100,105,97,61,34,97,108,
+108,34,32,118,105,111,108,97,116,105,111,110,32,111,102,114,101,102,101,114,101,
+110,99,101,32,116,111,114,101,116,117,114,110,32,116,114,117,101,59,83,116,114,
+105,99,116,47,47,69,78,34,32,116,114,97,110,115,97,99,116,105,111,110,115,105,
+110,116,101,114,118,101,110,116,105,111,110,118,101,114,105,102,105,99,97,116,
+105,111,110,73,110,102,111,114,109,97,116,105,111,110,32,100,105,102,102,105,99,
+117,108,116,105,101,115,67,104,97,109,112,105,111,110,115,104,105,112,99,97,112,
+97,98,105,108,105,116,105,101,115,60,33,91,101,110,100,105,102,93,45,45,62,125,
+10,60,47,115,99,114,105,112,116,62,10,67,104,114,105,115,116,105,97,110,105,116,
+121,102,111,114,32,101,120,97,109,112,108,101,44,80,114,111,102,101,115,115,105,
+111,110,97,108,114,101,115,116,114,105,99,116,105,111,110,115,115,117,103,103,
+101,115,116,32,116,104,97,116,119,97,115,32,114,101,108,101,97,115,101,100,40,
+115,117,99,104,32,97,115,32,116,104,101,114,101,109,111,118,101,67,108,97,115,
+115,40,117,110,101,109,112,108,111,121,109,101,110,116,116,104,101,32,65,109,101
+,114,105,99,97,110,115,116,114,117,99,116,117,114,101,32,111,102,47,105,110,100,
+101,120,46,104,116,109,108,32,112,117,98,108,105,115,104,101,100,32,105,110,115,
+112,97,110,32,99,108,97,115,115,61,34,34,62,60,97,32,104,114,101,102,61,34,47,
+105,110,116,114,111,100,117,99,116,105,111,110,98,101,108,111,110,103,105,110,
+103,32,116,111,99,108,97,105,109,101,100,32,116,104,97,116,99,111,110,115,101,
+113,117,101,110,99,101,115,60,109,101,116,97,32,110,97,109,101,61,34,71,117,105,
+100,101,32,116,111,32,116,104,101,111,118,101,114,119,104,101,108,109,105,110,
+103,97,103,97,105,110,115,116,32,116,104,101,32,99,111,110,99,101,110,116,114,97
+,116,101,100,44,10,46,110,111,110,116,111,117,99,104,32,111,98,115,101,114,118,
+97,116,105,111,110,115,60,47,97,62,10,60,47,100,105,118,62,10,102,32,40,100,111,
+99,117,109,101,110,116,46,98,111,114,100,101,114,58,32,49,112,120,32,123,102,111
+,110,116,45,115,105,122,101,58,49,116,114,101,97,116,109,101,110,116,32,111,102,
+48,34,32,104,101,105,103,104,116,61,34,49,109,111,100,105,102,105,99,97,116,105,
+111,110,73,110,100,101,112,101,110,100,101,110,99,101,100,105,118,105,100,101,
+100,32,105,110,116,111,103,114,101,97,116,101,114,32,116,104,97,110,97,99,104,
+105,101,118,101,109,101,110,116,115,101,115,116,97,98,108,105,115,104,105,110,
+103,74,97,118,97,83,99,114,105,112,116,34,32,110,101,118,101,114,116,104,101,108
+,101,115,115,115,105,103,110,105,102,105,99,97,110,99,101,66,114,111,97,100,99,
+97,115,116,105,110,103,62,38,110,98,115,112,59,60,47,116,100,62,99,111,110,116,
+97,105,110,101,114,34,62,10,115,117,99,104,32,97,115,32,116,104,101,32,105,110,
+102,108,117,101,110,99,101,32,111,102,97,32,112,97,114,116,105,99,117,108,97,114
+,115,114,99,61,39,104,116,116,112,58,47,47,110,97,118,105,103,97,116,105,111,110
+,34,32,104,97,108,102,32,111,102,32,116,104,101,32,115,117,98,115,116,97,110,116
+,105,97,108,32,38,110,98,115,112,59,60,47,100,105,118,62,97,100,118,97,110,116,
+97,103,101,32,111,102,100,105,115,99,111,118,101,114,121,32,111,102,102,117,110,
+100,97,109,101,110,116,97,108,32,109,101,116,114,111,112,111,108,105,116,97,110,
+116,104,101,32,111,112,112,111,115,105,116,101,34,32,120,109,108,58,108,97,110,
+103,61,34,100,101,108,105,98,101,114,97,116,101,108,121,97,108,105,103,110,61,99
+,101,110,116,101,114,101,118,111,108,117,116,105,111,110,32,111,102,112,114,101,
+115,101,114,118,97,116,105,111,110,105,109,112,114,111,118,101,109,101,110,116,
+115,98,101,103,105,110,110,105,110,103,32,105,110,74,101,115,117,115,32,67,104,
+114,105,115,116,80,117,98,108,105,99,97,116,105,111,110,115,100,105,115,97,103,
+114,101,101,109,101,110,116,116,101,120,116,45,97,108,105,103,110,58,114,44,32,
+102,117,110,99,116,105,111,110,40,41,115,105,109,105,108,97,114,105,116,105,101,
+115,98,111,100,121,62,60,47,104,116,109,108,62,105,115,32,99,117,114,114,101,110
+,116,108,121,97,108,112,104,97,98,101,116,105,99,97,108,105,115,32,115,111,109,
+101,116,105,109,101,115,116,121,112,101,61,34,105,109,97,103,101,47,109,97,110,
+121,32,111,102,32,116,104,101,32,102,108,111,119,58,104,105,100,100,101,110,59,
+97,118,97,105,108,97,98,108,101,32,105,110,100,101,115,99,114,105,98,101,32,116,
+104,101,101,120,105,115,116,101,110,99,101,32,111,102,97,108,108,32,111,118,101,
+114,32,116,104,101,116,104,101,32,73,110,116,101,114,110,101,116,9,60,117,108,32
+,99,108,97,115,115,61,34,105,110,115,116,97,108,108,97,116,105,111,110,110,101,
+105,103,104,98,111,114,104,111,111,100,97,114,109,101,100,32,102,111,114,99,101,
+115,114,101,100,117,99,105,110,103,32,116,104,101,99,111,110,116,105,110,117,101
+,115,32,116,111,78,111,110,101,116,104,101,108,101,115,115,44,116,101,109,112,
+101,114,97,116,117,114,101,115,10,9,9,60,97,32,104,114,101,102,61,34,99,108,111,
+115,101,32,116,111,32,116,104,101,101,120,97,109,112,108,101,115,32,111,102,32,
+105,115,32,97,98,111,117,116,32,116,104,101,40,115,101,101,32,98,101,108,111,119
+,41,46,34,32,105,100,61,34,115,101,97,114,99,104,112,114,111,102,101,115,115,105
+,111,110,97,108,105,115,32,97,118,97,105,108,97,98,108,101,116,104,101,32,111,
+102,102,105,99,105,97,108,9,9,60,47,115,99,114,105,112,116,62,10,10,9,9,60,100,
+105,118,32,105,100,61,34,97,99,99,101,108,101,114,97,116,105,111,110,116,104,114
+,111,117,103,104,32,116,104,101,32,72,97,108,108,32,111,102,32,70,97,109,101,100
+,101,115,99,114,105,112,116,105,111,110,115,116,114,97,110,115,108,97,116,105,
+111,110,115,105,110,116,101,114,102,101,114,101,110,99,101,32,116,121,112,101,61
+,39,116,101,120,116,47,114,101,99,101,110,116,32,121,101,97,114,115,105,110,32,
+116,104,101,32,119,111,114,108,100,118,101,114,121,32,112,111,112,117,108,97,114
+,123,98,97,99,107,103,114,111,117,110,100,58,116,114,97,100,105,116,105,111,110,
+97,108,32,115,111,109,101,32,111,102,32,116,104,101,32,99,111,110,110,101,99,116
+,101,100,32,116,111,101,120,112,108,111,105,116,97,116,105,111,110,101,109,101,
+114,103,101,110,99,101,32,111,102,99,111,110,115,116,105,116,117,116,105,111,110
+,65,32,72,105,115,116,111,114,121,32,111,102,115,105,103,110,105,102,105,99,97,
+110,116,32,109,97,110,117,102,97,99,116,117,114,101,100,101,120,112,101,99,116,
+97,116,105,111,110,115,62,60,110,111,115,99,114,105,112,116,62,60,99,97,110,32,
+98,101,32,102,111,117,110,100,98,101,99,97,117,115,101,32,116,104,101,32,104,97,
+115,32,110,111,116,32,98,101,101,110,110,101,105,103,104,98,111,117,114,105,110,
+103,119,105,116,104,111,117,116,32,116,104,101,32,97,100,100,101,100,32,116,111,
+32,116,104,101,9,60,108,105,32,99,108,97,115,115,61,34,105,110,115,116,114,117,
+109,101,110,116,97,108,83,111,118,105,101,116,32,85,110,105,111,110,97,99,107,
+110,111,119,108,101,100,103,101,100,119,104,105,99,104,32,99,97,110,32,98,101,
+110,97,109,101,32,102,111,114,32,116,104,101,97,116,116,101,110,116,105,111,110,
+32,116,111,97,116,116,101,109,112,116,115,32,116,111,32,100,101,118,101,108,111,
+112,109,101,110,116,115,73,110,32,102,97,99,116,44,32,116,104,101,60,108,105,32,
+99,108,97,115,115,61,34,97,105,109,112,108,105,99,97,116,105,111,110,115,115,117
+,105,116,97,98,108,101,32,102,111,114,109,117,99,104,32,111,102,32,116,104,101,
+32,99,111,108,111,110,105,122,97,116,105,111,110,112,114,101,115,105,100,101,110
+,116,105,97,108,99,97,110,99,101,108,66,117,98,98,108,101,32,73,110,102,111,114,
+109,97,116,105,111,110,109,111,115,116,32,111,102,32,116,104,101,32,105,115,32,
+100,101,115,99,114,105,98,101,100,114,101,115,116,32,111,102,32,116,104,101,32,
+109,111,114,101,32,111,114,32,108,101,115,115,105,110,32,83,101,112,116,101,109,
+98,101,114,73,110,116,101,108,108,105,103,101,110,99,101,115,114,99,61,34,104,
+116,116,112,58,47,47,112,120,59,32,104,101,105,103,104,116,58,32,97,118,97,105,
+108,97,98,108,101,32,116,111,109,97,110,117,102,97,99,116,117,114,101,114,104,
+117,109,97,110,32,114,105,103,104,116,115,108,105,110,107,32,104,114,101,102,61,
+34,47,97,118,97,105,108,97,98,105,108,105,116,121,112,114,111,112,111,114,116,
+105,111,110,97,108,111,117,116,115,105,100,101,32,116,104,101,32,97,115,116,114,
+111,110,111,109,105,99,97,108,104,117,109,97,110,32,98,101,105,110,103,115,110,
+97,109,101,32,111,102,32,116,104,101,32,97,114,101,32,102,111,117,110,100,32,105
+,110,97,114,101,32,98,97,115,101,100,32,111,110,115,109,97,108,108,101,114,32,
+116,104,97,110,97,32,112,101,114,115,111,110,32,119,104,111,101,120,112,97,110,
+115,105,111,110,32,111,102,97,114,103,117,105,110,103,32,116,104,97,116,110,111,
+119,32,107,110,111,119,110,32,97,115,73,110,32,116,104,101,32,101,97,114,108,121
+,105,110,116,101,114,109,101,100,105,97,116,101,100,101,114,105,118,101,100,32,
+102,114,111,109,83,99,97,110,100,105,110,97,118,105,97,110,60,47,97,62,60,47,100
+,105,118,62,13,10,99,111,110,115,105,100,101,114,32,116,104,101,97,110,32,101,
+115,116,105,109,97,116,101,100,116,104,101,32,78,97,116,105,111,110,97,108,60,
+100,105,118,32,105,100,61,34,112,97,103,114,101,115,117,108,116,105,110,103,32,
+105,110,99,111,109,109,105,115,115,105,111,110,101,100,97,110,97,108,111,103,111
+,117,115,32,116,111,97,114,101,32,114,101,113,117,105,114,101,100,47,117,108,62,
+10,60,47,100,105,118,62,10,119,97,115,32,98,97,115,101,100,32,111,110,97,110,100
+,32,98,101,99,97,109,101,32,97,38,110,98,115,112,59,38,110,98,115,112,59,116,34,
+32,118,97,108,117,101,61,34,34,32,119,97,115,32,99,97,112,116,117,114,101,100,
+110,111,32,109,111,114,101,32,116,104,97,110,114,101,115,112,101,99,116,105,118,
+101,108,121,99,111,110,116,105,110,117,101,32,116,111,32,62,13,10,60,104,101,97,
+100,62,13,10,60,119,101,114,101,32,99,114,101,97,116,101,100,109,111,114,101,32,
+103,101,110,101,114,97,108,105,110,102,111,114,109,97,116,105,111,110,32,117,115
+,101,100,32,102,111,114,32,116,104,101,105,110,100,101,112,101,110,100,101,110,
+116,32,116,104,101,32,73,109,112,101,114,105,97,108,99,111,109,112,111,110,101,
+110,116,32,111,102,116,111,32,116,104,101,32,110,111,114,116,104,105,110,99,108,
+117,100,101,32,116,104,101,32,67,111,110,115,116,114,117,99,116,105,111,110,115,
+105,100,101,32,111,102,32,116,104,101,32,119,111,117,108,100,32,110,111,116,32,
+98,101,102,111,114,32,105,110,115,116,97,110,99,101,105,110,118,101,110,116,105,
+111,110,32,111,102,109,111,114,101,32,99,111,109,112,108,101,120,99,111,108,108,
+101,99,116,105,118,101,108,121,98,97,99,107,103,114,111,117,110,100,58,32,116,
+101,120,116,45,97,108,105,103,110,58,32,105,116,115,32,111,114,105,103,105,110,
+97,108,105,110,116,111,32,97,99,99,111,117,110,116,116,104,105,115,32,112,114,
+111,99,101,115,115,97,110,32,101,120,116,101,110,115,105,118,101,104,111,119,101
+,118,101,114,44,32,116,104,101,116,104,101,121,32,97,114,101,32,110,111,116,114,
+101,106,101,99,116,101,100,32,116,104,101,99,114,105,116,105,99,105,115,109,32,
+111,102,100,117,114,105,110,103,32,119,104,105,99,104,112,114,111,98,97,98,108,
+121,32,116,104,101,116,104,105,115,32,97,114,116,105,99,108,101,40,102,117,110,
+99,116,105,111,110,40,41,123,73,116,32,115,104,111,117,108,100,32,98,101,97,110,
+32,97,103,114,101,101,109,101,110,116,97,99,99,105,100,101,110,116,97,108,108,
+121,100,105,102,102,101,114,115,32,102,114,111,109,65,114,99,104,105,116,101,99,
+116,117,114,101,98,101,116,116,101,114,32,107,110,111,119,110,97,114,114,97,110,
+103,101,109,101,110,116,115,105,110,102,108,117,101,110,99,101,32,111,110,97,116
+,116,101,110,100,101,100,32,116,104,101,105,100,101,110,116,105,99,97,108,32,116
+,111,115,111,117,116,104,32,111,102,32,116,104,101,112,97,115,115,32,116,104,114
+,111,117,103,104,120,109,108,34,32,116,105,116,108,101,61,34,119,101,105,103,104
+,116,58,98,111,108,100,59,99,114,101,97,116,105,110,103,32,116,104,101,100,105,
+115,112,108,97,121,58,110,111,110,101,114,101,112,108,97,99,101,100,32,116,104,
+101,60,105,109,103,32,115,114,99,61,34,47,105,104,116,116,112,115,58,47,47,119,
+119,119,46,87,111,114,108,100,32,87,97,114,32,73,73,116,101,115,116,105,109,111,
+110,105,97,108,115,102,111,117,110,100,32,105,110,32,116,104,101,114,101,113,117
+,105,114,101,100,32,116,111,32,97,110,100,32,116,104,97,116,32,116,104,101,98,
+101,116,119,101,101,110,32,116,104,101,32,119,97,115,32,100,101,115,105,103,110,
+101,100,99,111,110,115,105,115,116,115,32,111,102,32,99,111,110,115,105,100,101,
+114,97,98,108,121,112,117,98,108,105,115,104,101,100,32,98,121,116,104,101,32,
+108,97,110,103,117,97,103,101,67,111,110,115,101,114,118,97,116,105,111,110,99,
+111,110,115,105,115,116,101,100,32,111,102,114,101,102,101,114,32,116,111,32,116
+,104,101,98,97,99,107,32,116,111,32,116,104,101,32,99,115,115,34,32,109,101,100,
+105,97,61,34,80,101,111,112,108,101,32,102,114,111,109,32,97,118,97,105,108,97,
+98,108,101,32,111,110,112,114,111,118,101,100,32,116,111,32,98,101,115,117,103,
+103,101,115,116,105,111,110,115,34,119,97,115,32,107,110,111,119,110,32,97,115,
+118,97,114,105,101,116,105,101,115,32,111,102,108,105,107,101,108,121,32,116,111
+,32,98,101,99,111,109,112,114,105,115,101,100,32,111,102,115,117,112,112,111,114
+,116,32,116,104,101,32,104,97,110,100,115,32,111,102,32,116,104,101,99,111,117,
+112,108,101,100,32,119,105,116,104,99,111,110,110,101,99,116,32,97,110,100,32,98
+,111,114,100,101,114,58,110,111,110,101,59,112,101,114,102,111,114,109,97,110,99
+,101,115,98,101,102,111,114,101,32,98,101,105,110,103,108,97,116,101,114,32,98,
+101,99,97,109,101,99,97,108,99,117,108,97,116,105,111,110,115,111,102,116,101,
+110,32,99,97,108,108,101,100,114,101,115,105,100,101,110,116,115,32,111,102,109,
+101,97,110,105,110,103,32,116,104,97,116,62,60,108,105,32,99,108,97,115,115,61,
+34,101,118,105,100,101,110,99,101,32,102,111,114,101,120,112,108,97,110,97,116,
+105,111,110,115,101,110,118,105,114,111,110,109,101,110,116,115,34,62,60,47,97,
+62,60,47,100,105,118,62,119,104,105,99,104,32,97,108,108,111,119,115,73,110,116,
+114,111,100,117,99,116,105,111,110,100,101,118,101,108,111,112,101,100,32,98,121
+,97,32,119,105,100,101,32,114,97,110,103,101,111,110,32,98,101,104,97,108,102,32
+,111,102,118,97,108,105,103,110,61,34,116,111,112,34,112,114,105,110,99,105,112,
+108,101,32,111,102,97,116,32,116,104,101,32,116,105,109,101,44,60,47,110,111,115
+,99,114,105,112,116,62,13,115,97,105,100,32,116,111,32,104,97,118,101,105,110,32
+,116,104,101,32,102,105,114,115,116,119,104,105,108,101,32,111,116,104,101,114,
+115,104,121,112,111,116,104,101,116,105,99,97,108,112,104,105,108,111,115,111,
+112,104,101,114,115,112,111,119,101,114,32,111,102,32,116,104,101,99,111,110,116
+,97,105,110,101,100,32,105,110,112,101,114,102,111,114,109,101,100,32,98,121,105
+,110,97,98,105,108,105,116,121,32,116,111,119,101,114,101,32,119,114,105,116,116
+,101,110,115,112,97,110,32,115,116,121,108,101,61,34,105,110,112,117,116,32,110,
+97,109,101,61,34,116,104,101,32,113,117,101,115,116,105,111,110,105,110,116,101,
+110,100,101,100,32,102,111,114,114,101,106,101,99,116,105,111,110,32,111,102,105
+,109,112,108,105,101,115,32,116,104,97,116,105,110,118,101,110,116,101,100,32,
+116,104,101,116,104,101,32,115,116,97,110,100,97,114,100,119,97,115,32,112,114,
+111,98,97,98,108,121,108,105,110,107,32,98,101,116,119,101,101,110,112,114,111,
+102,101,115,115,111,114,32,111,102,105,110,116,101,114,97,99,116,105,111,110,115
+,99,104,97,110,103,105,110,103,32,116,104,101,73,110,100,105,97,110,32,79,99,101
+,97,110,32,99,108,97,115,115,61,34,108,97,115,116,119,111,114,107,105,110,103,32
+,119,105,116,104,39,104,116,116,112,58,47,47,119,119,119,46,121,101,97,114,115,
+32,98,101,102,111,114,101,84,104,105,115,32,119,97,115,32,116,104,101,114,101,99
+,114,101,97,116,105,111,110,97,108,101,110,116,101,114,105,110,103,32,116,104,
+101,109,101,97,115,117,114,101,109,101,110,116,115,97,110,32,101,120,116,114,101
+,109,101,108,121,118,97,108,117,101,32,111,102,32,116,104,101,115,116,97,114,116
+,32,111,102,32,116,104,101,10,60,47,115,99,114,105,112,116,62,10,10,97,110,32,
+101,102,102,111,114,116,32,116,111,105,110,99,114,101,97,115,101,32,116,104,101,
+116,111,32,116,104,101,32,115,111,117,116,104,115,112,97,99,105,110,103,61,34,48
+,34,62,115,117,102,102,105,99,105,101,110,116,108,121,116,104,101,32,69,117,114,
+111,112,101,97,110,99,111,110,118,101,114,116,101,100,32,116,111,99,108,101,97,
+114,84,105,109,101,111,117,116,100,105,100,32,110,111,116,32,104,97,118,101,99,
+111,110,115,101,113,117,101,110,116,108,121,102,111,114,32,116,104,101,32,110,
+101,120,116,101,120,116,101,110,115,105,111,110,32,111,102,101,99,111,110,111,
+109,105,99,32,97,110,100,97,108,116,104,111,117,103,104,32,116,104,101,97,114,
+101,32,112,114,111,100,117,99,101,100,97,110,100,32,119,105,116,104,32,116,104,
+101,105,110,115,117,102,102,105,99,105,101,110,116,103,105,118,101,110,32,98,121
+,32,116,104,101,115,116,97,116,105,110,103,32,116,104,97,116,101,120,112,101,110
+,100,105,116,117,114,101,115,60,47,115,112,97,110,62,60,47,97,62,10,116,104,111,
+117,103,104,116,32,116,104,97,116,111,110,32,116,104,101,32,98,97,115,105,115,99
+,101,108,108,112,97,100,100,105,110,103,61,105,109,97,103,101,32,111,102,32,116,
+104,101,114,101,116,117,114,110,105,110,103,32,116,111,105,110,102,111,114,109,
+97,116,105,111,110,44,115,101,112,97,114,97,116,101,100,32,98,121,97,115,115,97,
+115,115,105,110,97,116,101,100,115,34,32,99,111,110,116,101,110,116,61,34,97,117
+,116,104,111,114,105,116,121,32,111,102,110,111,114,116,104,119,101,115,116,101,
+114,110,60,47,100,105,118,62,10,60,100,105,118,32,34,62,60,47,100,105,118,62,13,
+10,32,32,99,111,110,115,117,108,116,97,116,105,111,110,99,111,109,109,117,110,
+105,116,121,32,111,102,116,104,101,32,110,97,116,105,111,110,97,108,105,116,32,
+115,104,111,117,108,100,32,98,101,112,97,114,116,105,99,105,112,97,110,116,115,
+32,97,108,105,103,110,61,34,108,101,102,116,116,104,101,32,103,114,101,97,116,
+101,115,116,115,101,108,101,99,116,105,111,110,32,111,102,115,117,112,101,114,
+110,97,116,117,114,97,108,100,101,112,101,110,100,101,110,116,32,111,110,105,115
+,32,109,101,110,116,105,111,110,101,100,97,108,108,111,119,105,110,103,32,116,
+104,101,119,97,115,32,105,110,118,101,110,116,101,100,97,99,99,111,109,112,97,
+110,121,105,110,103,104,105,115,32,112,101,114,115,111,110,97,108,97,118,97,105,
+108,97,98,108,101,32,97,116,115,116,117,100,121,32,111,102,32,116,104,101,111,
+110,32,116,104,101,32,111,116,104,101,114,101,120,101,99,117,116,105,111,110,32,
+111,102,72,117,109,97,110,32,82,105,103,104,116,115,116,101,114,109,115,32,111,
+102,32,116,104,101,97,115,115,111,99,105,97,116,105,111,110,115,114,101,115,101,
+97,114,99,104,32,97,110,100,115,117,99,99,101,101,100,101,100,32,98,121,100,101,
+102,101,97,116,101,100,32,116,104,101,97,110,100,32,102,114,111,109,32,116,104,
+101,98,117,116,32,116,104,101,121,32,97,114,101,99,111,109,109,97,110,100,101,
+114,32,111,102,115,116,97,116,101,32,111,102,32,116,104,101,121,101,97,114,115,
+32,111,102,32,97,103,101,116,104,101,32,115,116,117,100,121,32,111,102,60,117,
+108,32,99,108,97,115,115,61,34,115,112,108,97,99,101,32,105,110,32,116,104,101,
+119,104,101,114,101,32,104,101,32,119,97,115,60,108,105,32,99,108,97,115,115,61,
+34,102,116,104,101,114,101,32,97,114,101,32,110,111,119,104,105,99,104,32,98,101
+,99,97,109,101,104,101,32,112,117,98,108,105,115,104,101,100,101,120,112,114,101
+,115,115,101,100,32,105,110,116,111,32,119,104,105,99,104,32,116,104,101,99,111,
+109,109,105,115,115,105,111,110,101,114,102,111,110,116,45,119,101,105,103,104,
+116,58,116,101,114,114,105,116,111,114,121,32,111,102,101,120,116,101,110,115,
+105,111,110,115,34,62,82,111,109,97,110,32,69,109,112,105,114,101,101,113,117,97
+,108,32,116,111,32,116,104,101,73,110,32,99,111,110,116,114,97,115,116,44,104,
+111,119,101,118,101,114,44,32,97,110,100,105,115,32,116,121,112,105,99,97,108,
+108,121,97,110,100,32,104,105,115,32,119,105,102,101,40,97,108,115,111,32,99,97,
+108,108,101,100,62,60,117,108,32,99,108,97,115,115,61,34,101,102,102,101,99,116,
+105,118,101,108,121,32,101,118,111,108,118,101,100,32,105,110,116,111,115,101,
+101,109,32,116,111,32,104,97,118,101,119,104,105,99,104,32,105,115,32,116,104,
+101,116,104,101,114,101,32,119,97,115,32,110,111,97,110,32,101,120,99,101,108,
+108,101,110,116,97,108,108,32,111,102,32,116,104,101,115,101,100,101,115,99,114,
+105,98,101,100,32,98,121,73,110,32,112,114,97,99,116,105,99,101,44,98,114,111,97
+,100,99,97,115,116,105,110,103,99,104,97,114,103,101,100,32,119,105,116,104,114,
+101,102,108,101,99,116,101,100,32,105,110,115,117,98,106,101,99,116,101,100,32,
+116,111,109,105,108,105,116,97,114,121,32,97,110,100,116,111,32,116,104,101,32,
+112,111,105,110,116,101,99,111,110,111,109,105,99,97,108,108,121,115,101,116,84,
+97,114,103,101,116,105,110,103,97,114,101,32,97,99,116,117,97,108,108,121,118,
+105,99,116,111,114,121,32,111,118,101,114,40,41,59,60,47,115,99,114,105,112,116,
+62,99,111,110,116,105,110,117,111,117,115,108,121,114,101,113,117,105,114,101,
+100,32,102,111,114,101,118,111,108,117,116,105,111,110,97,114,121,97,110,32,101,
+102,102,101,99,116,105,118,101,110,111,114,116,104,32,111,102,32,116,104,101,44,
+32,119,104,105,99,104,32,119,97,115,32,102,114,111,110,116,32,111,102,32,116,104
+,101,111,114,32,111,116,104,101,114,119,105,115,101,115,111,109,101,32,102,111,
+114,109,32,111,102,104,97,100,32,110,111,116,32,98,101,101,110,103,101,110,101,
+114,97,116,101,100,32,98,121,105,110,102,111,114,109,97,116,105,111,110,46,112,
+101,114,109,105,116,116,101,100,32,116,111,105,110,99,108,117,100,101,115,32,116
+,104,101,100,101,118,101,108,111,112,109,101,110,116,44,101,110,116,101,114,101,
+100,32,105,110,116,111,116,104,101,32,112,114,101,118,105,111,117,115,99,111,110
+,115,105,115,116,101,110,116,108,121,97,114,101,32,107,110,111,119,110,32,97,115
+,116,104,101,32,102,105,101,108,100,32,111,102,116,104,105,115,32,116,121,112,
+101,32,111,102,103,105,118,101,110,32,116,111,32,116,104,101,116,104,101,32,116,
+105,116,108,101,32,111,102,99,111,110,116,97,105,110,115,32,116,104,101,105,110,
+115,116,97,110,99,101,115,32,111,102,105,110,32,116,104,101,32,110,111,114,116,
+104,100,117,101,32,116,111,32,116,104,101,105,114,97,114,101,32,100,101,115,105,
+103,110,101,100,99,111,114,112,111,114,97,116,105,111,110,115,119,97,115,32,116,
+104,97,116,32,116,104,101,111,110,101,32,111,102,32,116,104,101,115,101,109,111,
+114,101,32,112,111,112,117,108,97,114,115,117,99,99,101,101,100,101,100,32,105,
+110,115,117,112,112,111,114,116,32,102,114,111,109,105,110,32,100,105,102,102,
+101,114,101,110,116,100,111,109,105,110,97,116,101,100,32,98,121,100,101,115,105
+,103,110,101,100,32,102,111,114,111,119,110,101,114,115,104,105,112,32,111,102,
+97,110,100,32,112,111,115,115,105,98,108,121,115,116,97,110,100,97,114,100,105,
+122,101,100,114,101,115,112,111,110,115,101,84,101,120,116,119,97,115,32,105,110
+,116,101,110,100,101,100,114,101,99,101,105,118,101,100,32,116,104,101,97,115,
+115,117,109,101,100,32,116,104,97,116,97,114,101,97,115,32,111,102,32,116,104,
+101,112,114,105,109,97,114,105,108,121,32,105,110,116,104,101,32,98,97,115,105,
+115,32,111,102,105,110,32,116,104,101,32,115,101,110,115,101,97,99,99,111,117,
+110,116,115,32,102,111,114,100,101,115,116,114,111,121,101,100,32,98,121,97,116,
+32,108,101,97,115,116,32,116,119,111,119,97,115,32,100,101,99,108,97,114,101,100
+,99,111,117,108,100,32,110,111,116,32,98,101,83,101,99,114,101,116,97,114,121,32
+,111,102,97,112,112,101,97,114,32,116,111,32,98,101,109,97,114,103,105,110,45,
+116,111,112,58,49,47,94,92,115,43,124,92,115,43,36,47,103,101,41,123,116,104,114
+,111,119,32,101,125,59,116,104,101,32,115,116,97,114,116,32,111,102,116,119,111,
+32,115,101,112,97,114,97,116,101,108,97,110,103,117,97,103,101,32,97,110,100,119
+,104,111,32,104,97,100,32,98,101,101,110,111,112,101,114,97,116,105,111,110,32,
+111,102,100,101,97,116,104,32,111,102,32,116,104,101,114,101,97,108,32,110,117,
+109,98,101,114,115,9,60,108,105,110,107,32,114,101,108,61,34,112,114,111,118,105
+,100,101,100,32,116,104,101,116,104,101,32,115,116,111,114,121,32,111,102,99,111
+,109,112,101,116,105,116,105,111,110,115,101,110,103,108,105,115,104,32,40,85,75
+,41,101,110,103,108,105,115,104,32,40,85,83,41,208,156,208,190,208,189,208,179,
+208,190,208,187,208,161,209,128,208,191,209,129,208,186,208,184,209,129,209,128,
+208,191,209,129,208,186,208,184,209,129,209,128,208,191,209,129,208,186,208,190,
+217,132,216,185,216,177,216,168,217,138,216,169,230,173,163,233,171,148,228,184,
+173,230,150,135,231,174,128,228,189,147,228,184,173,230,150,135,231,185,129,228,
+189,147,228,184,173,230,150,135,230,156,137,233,153,144,229,133,172,229,143,184,
+228,186,186,230,176,145,230,148,191,229,186,156,233,152,191,233,135,140,229,183,
+180,229,183,180,231,164,190,228,188,154,228,184,187,228,185,137,230,147,141,228,
+189,156,231,179,187,231,187,159,230,148,191,231,173,150,230,179,149,232,167,132,
+105,110,102,111,114,109,97,99,105,195,179,110,104,101,114,114,97,109,105,101,110
+,116,97,115,101,108,101,99,116,114,195,179,110,105,99,111,100,101,115,99,114,105
+,112,99,105,195,179,110,99,108,97,115,105,102,105,99,97,100,111,115,99,111,110,
+111,99,105,109,105,101,110,116,111,112,117,98,108,105,99,97,99,105,195,179,110,
+114,101,108,97,99,105,111,110,97,100,97,115,105,110,102,111,114,109,195,161,116,
+105,99,97,114,101,108,97,99,105,111,110,97,100,111,115,100,101,112,97,114,116,97
+,109,101,110,116,111,116,114,97,98,97,106,97,100,111,114,101,115,100,105,114,101
+,99,116,97,109,101,110,116,101,97,121,117,110,116,97,109,105,101,110,116,111,109
+,101,114,99,97,100,111,76,105,98,114,101,99,111,110,116,195,161,99,116,101,110,
+111,115,104,97,98,105,116,97,99,105,111,110,101,115,99,117,109,112,108,105,109,
+105,101,110,116,111,114,101,115,116,97,117,114,97,110,116,101,115,100,105,115,
+112,111,115,105,99,105,195,179,110,99,111,110,115,101,99,117,101,110,99,105,97,
+101,108,101,99,116,114,195,179,110,105,99,97,97,112,108,105,99,97,99,105,111,110
+,101,115,100,101,115,99,111,110,101,99,116,97,100,111,105,110,115,116,97,108,97,
+99,105,195,179,110,114,101,97,108,105,122,97,99,105,195,179,110,117,116,105,108,
+105,122,97,99,105,195,179,110,101,110,99,105,99,108,111,112,101,100,105,97,101,
+110,102,101,114,109,101,100,97,100,101,115,105,110,115,116,114,117,109,101,110,
+116,111,115,101,120,112,101,114,105,101,110,99,105,97,115,105,110,115,116,105,
+116,117,99,105,195,179,110,112,97,114,116,105,99,117,108,97,114,101,115,115,117,
+98,99,97,116,101,103,111,114,105,97,209,130,208,190,208,187,209,140,208,186,208,
+190,208,160,208,190,209,129,209,129,208,184,208,184,209,128,208,176,208,177,208,
+190,209,130,209,139,208,177,208,190,208,187,209,140,209,136,208,181,208,191,209,
+128,208,190,209,129,209,130,208,190,208,188,208,190,208,182,208,181,209,130,208,
+181,208,180,209,128,209,131,208,179,208,184,209,133,209,129,208,187,209,131,209,
+135,208,176,208,181,209,129,208,181,208,185,209,135,208,176,209,129,208,178,209,
+129,208,181,208,179,208,180,208,176,208,160,208,190,209,129,209,129,208,184,209,
+143,208,156,208,190,209,129,208,186,208,178,208,181,208,180,209,128,209,131,208,
+179,208,184,208,181,208,179,208,190,209,128,208,190,208,180,208,176,208,178,208,
+190,208,191,209,128,208,190,209,129,208,180,208,176,208,189,208,189,209,139,209,
+133,208,180,208,190,208,187,208,182,208,189,209,139,208,184,208,188,208,181,208,
+189,208,189,208,190,208,156,208,190,209,129,208,186,208,178,209,139,209,128,209,
+131,208,177,208,187,208,181,208,185,208,156,208,190,209,129,208,186,208,178,208,
+176,209,129,209,130,209,128,208,176,208,189,209,139,208,189,208,184,209,135,208,
+181,208,179,208,190,209,128,208,176,208,177,208,190,209,130,208,181,208,180,208,
+190,208,187,208,182,208,181,208,189,209,131,209,129,208,187,209,131,208,179,208,
+184,209,130,208,181,208,191,208,181,209,128,209,140,208,158,208,180,208,189,208,
+176,208,186,208,190,208,191,208,190,209,130,208,190,208,188,209,131,209,128,208,
+176,208,177,208,190,209,130,209,131,208,176,208,191,209,128,208,181,208,187,209,
+143,208,178,208,190,208,190,208,177,209,137,208,181,208,190,208,180,208,189,208,
+190,208,179,208,190,209,129,208,178,208,190,208,181,208,179,208,190,209,129,209,
+130,208,176,209,130,209,140,208,184,208,180,209,128,209,131,208,179,208,190,208,
+185,209,132,208,190,209,128,209,131,208,188,208,181,209,133,208,190,209,128,208,
+190,209,136,208,190,208,191,209,128,208,190,209,130,208,184,208,178,209,129,209,
+129,209,139,208,187,208,186,208,176,208,186,208,176,208,182,208,180,209,139,208,
+185,208,178,208,187,208,176,209,129,209,130,208,184,208,179,209,128,209,131,208,
+191,208,191,209,139,208,178,208,188,208,181,209,129,209,130,208,181,209,128,208,
+176,208,177,208,190,209,130,208,176,209,129,208,186,208,176,208,183,208,176,208,
+187,208,191,208,181,209,128,208,178,209,139,208,185,208,180,208,181,208,187,208,
+176,209,130,209,140,208,180,208,181,208,189,209,140,208,179,208,184,208,191,208,
+181,209,128,208,184,208,190,208,180,208,177,208,184,208,183,208,189,208,181,209,
+129,208,190,209,129,208,189,208,190,208,178,208,181,208,188,208,190,208,188,208,
+181,208,189,209,130,208,186,209,131,208,191,208,184,209,130,209,140,208,180,208,
+190,208,187,208,182,208,189,208,176,209,128,208,176,208,188,208,186,208,176,209,
+133,208,189,208,176,209,135,208,176,208,187,208,190,208,160,208,176,208,177,208,
+190,209,130,208,176,208,162,208,190,208,187,209,140,208,186,208,190,209,129,208,
+190,208,178,209,129,208,181,208,188,208,178,209,130,208,190,209,128,208,190,208,
+185,208,189,208,176,209,135,208,176,208,187,208,176,209,129,208,191,208,184,209,
+129,208,190,208,186,209,129,208,187,209,131,208,182,208,177,209,139,209,129,208,
+184,209,129,209,130,208,181,208,188,208,191,208,181,209,135,208,176,209,130,208,
+184,208,189,208,190,208,178,208,190,208,179,208,190,208,191,208,190,208,188,208,
+190,209,137,208,184,209,129,208,176,208,185,209,130,208,190,208,178,208,191,208,
+190,209,135,208,181,208,188,209,131,208,191,208,190,208,188,208,190,209,137,209,
+140,208,180,208,190,208,187,208,182,208,189,208,190,209,129,209,129,209,139,208,
+187,208,186,208,184,208,177,209,139,209,129,209,130,209,128,208,190,208,180,208,
+176,208,189,208,189,209,139,208,181,208,188,208,189,208,190,208,179,208,184,208,
+181,208,191,209,128,208,190,208,181,208,186,209,130,208,161,208,181,208,185,209,
+135,208,176,209,129,208,188,208,190,208,180,208,181,208,187,208,184,209,130,208,
+176,208,186,208,190,208,179,208,190,208,190,208,189,208,187,208,176,208,185,208,
+189,208,179,208,190,209,128,208,190,208,180,208,181,208,178,208,181,209,128,209,
+129,208,184,209,143,209,129,209,130,209,128,208,176,208,189,208,181,209,132,208,
+184,208,187,209,140,208,188,209,139,209,131,209,128,208,190,208,178,208,189,209,
+143,209,128,208,176,208,183,208,189,209,139,209,133,208,184,209,129,208,186,208,
+176,209,130,209,140,208,189,208,181,208,180,208,181,208,187,209,142,209,143,208,
+189,208,178,208,176,209,128,209,143,208,188,208,181,208,189,209,140,209,136,208,
+181,208,188,208,189,208,190,208,179,208,184,209,133,208,180,208,176,208,189,208,
+189,208,190,208,185,208,183,208,189,208,176,209,135,208,184,209,130,208,189,208,
+181,208,187,209,140,208,183,209,143,209,132,208,190,209,128,209,131,208,188,208,
+176,208,162,208,181,208,191,208,181,209,128,209,140,208,188,208,181,209,129,209,
+143,209,134,208,176,208,183,208,176,209,137,208,184,209,130,209,139,208,155,209,
+131,209,135,209,136,208,184,208,181,224,164,168,224,164,185,224,165,128,224,164,
+130,224,164,149,224,164,176,224,164,168,224,165,135,224,164,133,224,164,170,224,
+164,168,224,165,135,224,164,149,224,164,191,224,164,175,224,164,190,224,164,149,
+224,164,176,224,165,135,224,164,130,224,164,133,224,164,168,224,165,141,224,164,
+175,224,164,149,224,165,141,224,164,175,224,164,190,224,164,151,224,164,190,224,
+164,135,224,164,161,224,164,172,224,164,190,224,164,176,224,165,135,224,164,149,
+224,164,191,224,164,184,224,165,128,224,164,166,224,164,191,224,164,175,224,164,
+190,224,164,170,224,164,185,224,164,178,224,165,135,224,164,184,224,164,191,224,
+164,130,224,164,185,224,164,173,224,164,190,224,164,176,224,164,164,224,164,133,
+224,164,170,224,164,168,224,165,128,224,164,181,224,164,190,224,164,178,224,165,
+135,224,164,184,224,165,135,224,164,181,224,164,190,224,164,149,224,164,176,224,
+164,164,224,165,135,224,164,174,224,165,135,224,164,176,224,165,135,224,164,185,
+224,165,139,224,164,168,224,165,135,224,164,184,224,164,149,224,164,164,224,165,
+135,224,164,172,224,164,185,224,165,129,224,164,164,224,164,184,224,164,190,224,
+164,135,224,164,159,224,164,185,224,165,139,224,164,151,224,164,190,224,164,156,
+224,164,190,224,164,168,224,165,135,224,164,174,224,164,191,224,164,168,224,164,
+159,224,164,149,224,164,176,224,164,164,224,164,190,224,164,149,224,164,176,224,
+164,168,224,164,190,224,164,137,224,164,168,224,164,149,224,165,135,224,164,175,
+224,164,185,224,164,190,224,164,129,224,164,184,224,164,172,224,164,184,224,165,
+135,224,164,173,224,164,190,224,164,183,224,164,190,224,164,134,224,164,170,224,
+164,149,224,165,135,224,164,178,224,164,191,224,164,175,224,165,135,224,164,182,
+224,165,129,224,164,176,224,165,130,224,164,135,224,164,184,224,164,149,224,165,
+135,224,164,152,224,164,130,224,164,159,224,165,135,224,164,174,224,165,135,224,
+164,176,224,165,128,224,164,184,224,164,149,224,164,164,224,164,190,224,164,174,
+224,165,135,224,164,176,224,164,190,224,164,178,224,165,135,224,164,149,224,164,
+176,224,164,133,224,164,167,224,164,191,224,164,149,224,164,133,224,164,170,224,
+164,168,224,164,190,224,164,184,224,164,174,224,164,190,224,164,156,224,164,174,
+224,165,129,224,164,157,224,165,135,224,164,149,224,164,190,224,164,176,224,164,
+163,224,164,185,224,165,139,224,164,164,224,164,190,224,164,149,224,164,161,224,
+164,188,224,165,128,224,164,175,224,164,185,224,164,190,224,164,130,224,164,185,
+224,165,139,224,164,159,224,164,178,224,164,182,224,164,172,224,165,141,224,164,
+166,224,164,178,224,164,191,224,164,175,224,164,190,224,164,156,224,165,128,224,
+164,181,224,164,168,224,164,156,224,164,190,224,164,164,224,164,190,224,164,149,
+224,165,136,224,164,184,224,165,135,224,164,134,224,164,170,224,164,149,224,164,
+190,224,164,181,224,164,190,224,164,178,224,165,128,224,164,166,224,165,135,224,
+164,168,224,165,135,224,164,170,224,165,130,224,164,176,224,165,128,224,164,170,
+224,164,190,224,164,168,224,165,128,224,164,137,224,164,184,224,164,149,224,165,
+135,224,164,185,224,165,139,224,164,151,224,165,128,224,164,172,224,165,136,224,
+164,160,224,164,149,224,164,134,224,164,170,224,164,149,224,165,128,224,164,181,
+224,164,176,224,165,141,224,164,183,224,164,151,224,164,190,224,164,130,224,164,
+181,224,164,134,224,164,170,224,164,149,224,165,139,224,164,156,224,164,191,224,
+164,178,224,164,190,224,164,156,224,164,190,224,164,168,224,164,190,224,164,184,
+224,164,185,224,164,174,224,164,164,224,164,185,224,164,174,224,165,135,224,164,
+130,224,164,137,224,164,168,224,164,149,224,165,128,224,164,175,224,164,190,224,
+164,185,224,165,130,224,164,166,224,164,176,224,165,141,224,164,156,224,164,184,
+224,165,130,224,164,154,224,165,128,224,164,170,224,164,184,224,164,130,224,164,
+166,224,164,184,224,164,181,224,164,190,224,164,178,224,164,185,224,165,139,224,
+164,168,224,164,190,224,164,185,224,165,139,224,164,164,224,165,128,224,164,156,
+224,165,136,224,164,184,224,165,135,224,164,181,224,164,190,224,164,170,224,164,
+184,224,164,156,224,164,168,224,164,164,224,164,190,224,164,168,224,165,135,224,
+164,164,224,164,190,224,164,156,224,164,190,224,164,176,224,165,128,224,164,152,
+224,164,190,224,164,175,224,164,178,224,164,156,224,164,191,224,164,178,224,165,
+135,224,164,168,224,165,128,224,164,154,224,165,135,224,164,156,224,164,190,224,
+164,130,224,164,154,224,164,170,224,164,164,224,165,141,224,164,176,224,164,151,
+224,165,130,224,164,151,224,164,178,224,164,156,224,164,190,224,164,164,224,165,
+135,224,164,172,224,164,190,224,164,185,224,164,176,224,164,134,224,164,170,224,
+164,168,224,165,135,224,164,181,224,164,190,224,164,185,224,164,168,224,164,135,
+224,164,184,224,164,149,224,164,190,224,164,184,224,165,129,224,164,172,224,164,
+185,224,164,176,224,164,185,224,164,168,224,165,135,224,164,135,224,164,184,224,
+164,184,224,165,135,224,164,184,224,164,185,224,164,191,224,164,164,224,164,172,
+224,164,161,224,164,188,224,165,135,224,164,152,224,164,159,224,164,168,224,164,
+190,224,164,164,224,164,178,224,164,190,224,164,182,224,164,170,224,164,190,224,
+164,130,224,164,154,224,164,182,224,165,141,224,164,176,224,165,128,224,164,172,
+224,164,161,224,164,188,224,165,128,224,164,185,224,165,139,224,164,164,224,165,
+135,224,164,184,224,164,190,224,164,136,224,164,159,224,164,182,224,164,190,224,
+164,175,224,164,166,224,164,184,224,164,149,224,164,164,224,165,128,224,164,156,
+224,164,190,224,164,164,224,165,128,224,164,181,224,164,190,224,164,178,224,164,
+190,224,164,185,224,164,156,224,164,190,224,164,176,224,164,170,224,164,159,224,
+164,168,224,164,190,224,164,176,224,164,150,224,164,168,224,165,135,224,164,184,
+224,164,161,224,164,188,224,164,149,224,164,174,224,164,191,224,164,178,224,164,
+190,224,164,137,224,164,184,224,164,149,224,165,128,224,164,149,224,165,135,224,
+164,181,224,164,178,224,164,178,224,164,151,224,164,164,224,164,190,224,164,150,
+224,164,190,224,164,168,224,164,190,224,164,133,224,164,176,224,165,141,224,164,
+165,224,164,156,224,164,185,224,164,190,224,164,130,224,164,166,224,165,135,224,
+164,150,224,164,190,224,164,170,224,164,185,224,164,178,224,165,128,224,164,168,
+224,164,191,224,164,175,224,164,174,224,164,172,224,164,191,224,164,168,224,164,
+190,224,164,172,224,165,136,224,164,130,224,164,149,224,164,149,224,164,185,224,
+165,128,224,164,130,224,164,149,224,164,185,224,164,168,224,164,190,224,164,166,
+224,165,135,224,164,164,224,164,190,224,164,185,224,164,174,224,164,178,224,165,
+135,224,164,149,224,164,190,224,164,171,224,165,128,224,164,156,224,164,172,224,
+164,149,224,164,191,224,164,164,224,165,129,224,164,176,224,164,164,224,164,174,
+224,164,190,224,164,130,224,164,151,224,164,181,224,164,185,224,165,128,224,164,
+130,224,164,176,224,165,139,224,164,156,224,164,188,224,164,174,224,164,191,224,
+164,178,224,165,128,224,164,134,224,164,176,224,165,139,224,164,170,224,164,184,
+224,165,135,224,164,168,224,164,190,224,164,175,224,164,190,224,164,166,224,164,
+181,224,164,178,224,165,135,224,164,168,224,165,135,224,164,150,224,164,190,224,
+164,164,224,164,190,224,164,149,224,164,176,224,165,128,224,164,172,224,164,137,
+224,164,168,224,164,149,224,164,190,224,164,156,224,164,181,224,164,190,224,164,
+172,224,164,170,224,165,130,224,164,176,224,164,190,224,164,172,224,164,161,224,
+164,188,224,164,190,224,164,184,224,165,140,224,164,166,224,164,190,224,164,182,
+224,165,135,224,164,175,224,164,176,224,164,149,224,164,191,224,164,175,224,165,
+135,224,164,149,224,164,185,224,164,190,224,164,130,224,164,133,224,164,149,224,
+164,184,224,164,176,224,164,172,224,164,168,224,164,190,224,164,143,224,164,181,
+224,164,185,224,164,190,224,164,130,224,164,184,224,165,141,224,164,165,224,164,
+178,224,164,174,224,164,191,224,164,178,224,165,135,224,164,178,224,165,135,224,
+164,150,224,164,149,224,164,181,224,164,191,224,164,183,224,164,175,224,164,149,
+224,165,141,224,164,176,224,164,130,224,164,184,224,164,174,224,165,130,224,164,
+185,224,164,165,224,164,190,224,164,168,224,164,190,216,170,216,179,216,170,216,
+183,217,138,216,185,217,133,216,180,216,167,216,177,217,131,216,169,216,168,217,
+136,216,167,216,179,216,183,216,169,216,167,217,132,216,181,217,129,216,173,216,
+169,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,174,216,
+167,216,181,216,169,216,167,217,132,217,133,216,178,217,138,216,175,216,167,217,
+132,216,185,216,167,217,133,216,169,216,167,217,132,217,131,216,167,216,170,216,
+168,216,167,217,132,216,177,216,175,217,136,216,175,216,168,216,177,217,134,216,
+167,217,133,216,172,216,167,217,132,216,175,217,136,217,132,216,169,216,167,217,
+132,216,185,216,167,217,132,217,133,216,167,217,132,217,133,217,136,217,130,216,
+185,216,167,217,132,216,185,216,177,216,168,217,138,216,167,217,132,216,179,216,
+177,217,138,216,185,216,167,217,132,216,172,217,136,216,167,217,132,216,167,217,
+132,216,176,217,135,216,167,216,168,216,167,217,132,216,173,217,138,216,167,216,
+169,216,167,217,132,216,173,217,130,217,136,217,130,216,167,217,132,217,131,216,
+177,217,138,217,133,216,167,217,132,216,185,216,177,216,167,217,130,217,133,216,
+173,217,129,217,136,216,184,216,169,216,167,217,132,216,171,216,167,217,134,217,
+138,217,133,216,180,216,167,217,135,216,175,216,169,216,167,217,132,217,133,216,
+177,216,163,216,169,216,167,217,132,217,130,216,177,216,162,217,134,216,167,217,
+132,216,180,216,168,216,167,216,168,216,167,217,132,216,173,217,136,216,167,216,
+177,216,167,217,132,216,172,216,175,217,138,216,175,216,167,217,132,216,163,216,
+179,216,177,216,169,216,167,217,132,216,185,217,132,217,136,217,133,217,133,216,
+172,217,133,217,136,216,185,216,169,216,167,217,132,216,177,216,173,217,133,217,
+134,216,167,217,132,217,134,217,130,216,167,216,183,217,129,217,132,216,179,216,
+183,217,138,217,134,216,167,217,132,217,131,217,136,217,138,216,170,216,167,217,
+132,216,175,217,134,217,138,216,167,216,168,216,177,217,131,216,167,216,170,217,
+135,216,167,217,132,216,177,217,138,216,167,216,182,216,170,216,173,217,138,216,
+167,216,170,217,138,216,168,216,170,217,136,217,130,217,138,216,170,216,167,217,
+132,216,163,217,136,217,132,217,137,216,167,217,132,216,168,216,177,217,138,216,
+175,216,167,217,132,217,131,217,132,216,167,217,133,216,167,217,132,216,177,216,
+167,216,168,216,183,216,167,217,132,216,180,216,174,216,181,217,138,216,179,217,
+138,216,167,216,177,216,167,216,170,216,167,217,132,216,171,216,167,217,132,216,
+171,216,167,217,132,216,181,217,132,216,167,216,169,216,167,217,132,216,173,216,
+175,217,138,216,171,216,167,217,132,216,178,217,136,216,167,216,177,216,167,217,
+132,216,174,217,132,217,138,216,172,216,167,217,132,216,172,217,133,217,138,216,
+185,216,167,217,132,216,185,216,167,217,133,217,135,216,167,217,132,216,172,217,
+133,216,167,217,132,216,167,217,132,216,179,216,167,216,185,216,169,217,133,216,
+180,216,167,217,135,216,175,217,135,216,167,217,132,216,177,216,166,217,138,216,
+179,216,167,217,132,216,175,216,174,217,136,217,132,216,167,217,132,217,129,217,
+134,217,138,216,169,216,167,217,132,217,131,216,170,216,167,216,168,216,167,217,
+132,216,175,217,136,216,177,217,138,216,167,217,132,216,175,216,177,217,136,216,
+179,216,167,216,179,216,170,216,186,216,177,217,130,216,170,216,181,216,167,217,
+133,217,138,217,133,216,167,217,132,216,168,217,134,216,167,216,170,216,167,217,
+132,216,185,216,184,217,138,217,133,101,110,116,101,114,116,97,105,110,109,101,
+110,116,117,110,100,101,114,115,116,97,110,100,105,110,103,32,61,32,102,117,110,
+99,116,105,111,110,40,41,46,106,112,103,34,32,119,105,100,116,104,61,34,99,111,
+110,102,105,103,117,114,97,116,105,111,110,46,112,110,103,34,32,119,105,100,116,
+104,61,34,60,98,111,100,121,32,99,108,97,115,115,61,34,77,97,116,104,46,114,97,
+110,100,111,109,40,41,99,111,110,116,101,109,112,111,114,97,114,121,32,85,110,
+105,116,101,100,32,83,116,97,116,101,115,99,105,114,99,117,109,115,116,97,110,99
+,101,115,46,97,112,112,101,110,100,67,104,105,108,100,40,111,114,103,97,110,105,
+122,97,116,105,111,110,115,60,115,112,97,110,32,99,108,97,115,115,61,34,34,62,60
+,105,109,103,32,115,114,99,61,34,47,100,105,115,116,105,110,103,117,105,115,104,
+101,100,116,104,111,117,115,97,110,100,115,32,111,102,32,99,111,109,109,117,110,
+105,99,97,116,105,111,110,99,108,101,97,114,34,62,60,47,100,105,118,62,105,110,
+118,101,115,116,105,103,97,116,105,111,110,102,97,118,105,99,111,110,46,105,99,
+111,34,32,109,97,114,103,105,110,45,114,105,103,104,116,58,98,97,115,101,100,32,
+111,110,32,116,104,101,32,77,97,115,115,97,99,104,117,115,101,116,116,115,116,97
+,98,108,101,32,98,111,114,100,101,114,61,105,110,116,101,114,110,97,116,105,111,
+110,97,108,97,108,115,111,32,107,110,111,119,110,32,97,115,112,114,111,110,117,
+110,99,105,97,116,105,111,110,98,97,99,107,103,114,111,117,110,100,58,35,102,112
+,97,100,100,105,110,103,45,108,101,102,116,58,70,111,114,32,101,120,97,109,112,
+108,101,44,32,109,105,115,99,101,108,108,97,110,101,111,117,115,38,108,116,59,47
+,109,97,116,104,38,103,116,59,112,115,121,99,104,111,108,111,103,105,99,97,108,
+105,110,32,112,97,114,116,105,99,117,108,97,114,101,97,114,99,104,34,32,116,121,
+112,101,61,34,102,111,114,109,32,109,101,116,104,111,100,61,34,97,115,32,111,112
+,112,111,115,101,100,32,116,111,83,117,112,114,101,109,101,32,67,111,117,114,116
+,111,99,99,97,115,105,111,110,97,108,108,121,32,65,100,100,105,116,105,111,110,
+97,108,108,121,44,78,111,114,116,104,32,65,109,101,114,105,99,97,112,120,59,98,
+97,99,107,103,114,111,117,110,100,111,112,112,111,114,116,117,110,105,116,105,
+101,115,69,110,116,101,114,116,97,105,110,109,101,110,116,46,116,111,76,111,119,
+101,114,67,97,115,101,40,109,97,110,117,102,97,99,116,117,114,105,110,103,112,
+114,111,102,101,115,115,105,111,110,97,108,32,99,111,109,98,105,110,101,100,32,
+119,105,116,104,70,111,114,32,105,110,115,116,97,110,99,101,44,99,111,110,115,
+105,115,116,105,110,103,32,111,102,34,32,109,97,120,108,101,110,103,116,104,61,
+34,114,101,116,117,114,110,32,102,97,108,115,101,59,99,111,110,115,99,105,111,
+117,115,110,101,115,115,77,101,100,105,116,101,114,114,97,110,101,97,110,101,120
+,116,114,97,111,114,100,105,110,97,114,121,97,115,115,97,115,115,105,110,97,116,
+105,111,110,115,117,98,115,101,113,117,101,110,116,108,121,32,98,117,116,116,111
+,110,32,116,121,112,101,61,34,116,104,101,32,110,117,109,98,101,114,32,111,102,
+116,104,101,32,111,114,105,103,105,110,97,108,32,99,111,109,112,114,101,104,101,
+110,115,105,118,101,114,101,102,101,114,115,32,116,111,32,116,104,101,60,47,117,
+108,62,10,60,47,100,105,118,62,10,112,104,105,108,111,115,111,112,104,105,99,97,
+108,108,111,99,97,116,105,111,110,46,104,114,101,102,119,97,115,32,112,117,98,
+108,105,115,104,101,100,83,97,110,32,70,114,97,110,99,105,115,99,111,40,102,117,
+110,99,116,105,111,110,40,41,123,10,60,100,105,118,32,105,100,61,34,109,97,105,
+110,115,111,112,104,105,115,116,105,99,97,116,101,100,109,97,116,104,101,109,97,
+116,105,99,97,108,32,47,104,101,97,100,62,13,10,60,98,111,100,121,115,117,103,
+103,101,115,116,115,32,116,104,97,116,100,111,99,117,109,101,110,116,97,116,105,
+111,110,99,111,110,99,101,110,116,114,97,116,105,111,110,114,101,108,97,116,105,
+111,110,115,104,105,112,115,109,97,121,32,104,97,118,101,32,98,101,101,110,40,
+102,111,114,32,101,120,97,109,112,108,101,44,84,104,105,115,32,97,114,116,105,99
+,108,101,32,105,110,32,115,111,109,101,32,99,97,115,101,115,112,97,114,116,115,
+32,111,102,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,
+71,114,101,97,116,32,66,114,105,116,97,105,110,32,99,101,108,108,112,97,100,100,
+105,110,103,61,101,113,117,105,118,97,108,101,110,116,32,116,111,112,108,97,99,
+101,104,111,108,100,101,114,61,34,59,32,102,111,110,116,45,115,105,122,101,58,32
+,106,117,115,116,105,102,105,99,97,116,105,111,110,98,101,108,105,101,118,101,
+100,32,116,104,97,116,115,117,102,102,101,114,101,100,32,102,114,111,109,97,116,
+116,101,109,112,116,101,100,32,116,111,32,108,101,97,100,101,114,32,111,102,32,
+116,104,101,99,114,105,112,116,34,32,115,114,99,61,34,47,40,102,117,110,99,116,
+105,111,110,40,41,32,123,97,114,101,32,97,118,97,105,108,97,98,108,101,10,9,60,
+108,105,110,107,32,114,101,108,61,34,32,115,114,99,61,39,104,116,116,112,58,47,
+47,105,110,116,101,114,101,115,116,101,100,32,105,110,99,111,110,118,101,110,116
+,105,111,110,97,108,32,34,32,97,108,116,61,34,34,32,47,62,60,47,97,114,101,32,
+103,101,110,101,114,97,108,108,121,104,97,115,32,97,108,115,111,32,98,101,101,
+110,109,111,115,116,32,112,111,112,117,108,97,114,32,99,111,114,114,101,115,112,
+111,110,100,105,110,103,99,114,101,100,105,116,101,100,32,119,105,116,104,116,
+121,108,101,61,34,98,111,114,100,101,114,58,60,47,97,62,60,47,115,112,97,110,62,
+60,47,46,103,105,102,34,32,119,105,100,116,104,61,34,60,105,102,114,97,109,101,
+32,115,114,99,61,34,116,97,98,108,101,32,99,108,97,115,115,61,34,105,110,108,105
+,110,101,45,98,108,111,99,107,59,97,99,99,111,114,100,105,110,103,32,116,111,32,
+116,111,103,101,116,104,101,114,32,119,105,116,104,97,112,112,114,111,120,105,
+109,97,116,101,108,121,112,97,114,108,105,97,109,101,110,116,97,114,121,109,111,
+114,101,32,97,110,100,32,109,111,114,101,100,105,115,112,108,97,121,58,110,111,
+110,101,59,116,114,97,100,105,116,105,111,110,97,108,108,121,112,114,101,100,111
+,109,105,110,97,110,116,108,121,38,110,98,115,112,59,124,38,110,98,115,112,59,38
+,110,98,115,112,59,60,47,115,112,97,110,62,32,99,101,108,108,115,112,97,99,105,
+110,103,61,60,105,110,112,117,116,32,110,97,109,101,61,34,111,114,34,32,99,111,
+110,116,101,110,116,61,34,99,111,110,116,114,111,118,101,114,115,105,97,108,112,
+114,111,112,101,114,116,121,61,34,111,103,58,47,120,45,115,104,111,99,107,119,97
+,118,101,45,100,101,109,111,110,115,116,114,97,116,105,111,110,115,117,114,114,
+111,117,110,100,101,100,32,98,121,78,101,118,101,114,116,104,101,108,101,115,115
+,44,119,97,115,32,116,104,101,32,102,105,114,115,116,99,111,110,115,105,100,101,
+114,97,98,108,101,32,65,108,116,104,111,117,103,104,32,116,104,101,32,99,111,108
+,108,97,98,111,114,97,116,105,111,110,115,104,111,117,108,100,32,110,111,116,32,
+98,101,112,114,111,112,111,114,116,105,111,110,32,111,102,60,115,112,97,110,32,
+115,116,121,108,101,61,34,107,110,111,119,110,32,97,115,32,116,104,101,32,115,
+104,111,114,116,108,121,32,97,102,116,101,114,102,111,114,32,105,110,115,116,97,
+110,99,101,44,100,101,115,99,114,105,98,101,100,32,97,115,32,47,104,101,97,100,
+62,10,60,98,111,100,121,32,115,116,97,114,116,105,110,103,32,119,105,116,104,105
+,110,99,114,101,97,115,105,110,103,108,121,32,116,104,101,32,102,97,99,116,32,
+116,104,97,116,100,105,115,99,117,115,115,105,111,110,32,111,102,109,105,100,100
+,108,101,32,111,102,32,116,104,101,97,110,32,105,110,100,105,118,105,100,117,97,
+108,100,105,102,102,105,99,117,108,116,32,116,111,32,112,111,105,110,116,32,111,
+102,32,118,105,101,119,104,111,109,111,115,101,120,117,97,108,105,116,121,97,99,
+99,101,112,116,97,110,99,101,32,111,102,60,47,115,112,97,110,62,60,47,100,105,
+118,62,109,97,110,117,102,97,99,116,117,114,101,114,115,111,114,105,103,105,110,
+32,111,102,32,116,104,101,99,111,109,109,111,110,108,121,32,117,115,101,100,105,
+109,112,111,114,116,97,110,99,101,32,111,102,100,101,110,111,109,105,110,97,116,
+105,111,110,115,98,97,99,107,103,114,111,117,110,100,58,32,35,108,101,110,103,
+116,104,32,111,102,32,116,104,101,100,101,116,101,114,109,105,110,97,116,105,111
+,110,97,32,115,105,103,110,105,102,105,99,97,110,116,34,32,98,111,114,100,101,
+114,61,34,48,34,62,114,101,118,111,108,117,116,105,111,110,97,114,121,112,114,
+105,110,99,105,112,108,101,115,32,111,102,105,115,32,99,111,110,115,105,100,101,
+114,101,100,119,97,115,32,100,101,118,101,108,111,112,101,100,73,110,100,111,45,
+69,117,114,111,112,101,97,110,118,117,108,110,101,114,97,98,108,101,32,116,111,
+112,114,111,112,111,110,101,110,116,115,32,111,102,97,114,101,32,115,111,109,101
+,116,105,109,101,115,99,108,111,115,101,114,32,116,111,32,116,104,101,78,101,119
+,32,89,111,114,107,32,67,105,116,121,32,110,97,109,101,61,34,115,101,97,114,99,
+104,97,116,116,114,105,98,117,116,101,100,32,116,111,99,111,117,114,115,101,32,
+111,102,32,116,104,101,109,97,116,104,101,109,97,116,105,99,105,97,110,98,121,32
+,116,104,101,32,101,110,100,32,111,102,97,116,32,116,104,101,32,101,110,100,32,
+111,102,34,32,98,111,114,100,101,114,61,34,48,34,32,116,101,99,104,110,111,108,
+111,103,105,99,97,108,46,114,101,109,111,118,101,67,108,97,115,115,40,98,114,97,
+110,99,104,32,111,102,32,116,104,101,101,118,105,100,101,110,99,101,32,116,104,
+97,116,33,91,101,110,100,105,102,93,45,45,62,13,10,73,110,115,116,105,116,117,
+116,101,32,111,102,32,105,110,116,111,32,97,32,115,105,110,103,108,101,114,101,
+115,112,101,99,116,105,118,101,108,121,46,97,110,100,32,116,104,101,114,101,102,
+111,114,101,112,114,111,112,101,114,116,105,101,115,32,111,102,105,115,32,108,
+111,99,97,116,101,100,32,105,110,115,111,109,101,32,111,102,32,119,104,105,99,
+104,84,104,101,114,101,32,105,115,32,97,108,115,111,99,111,110,116,105,110,117,
+101,100,32,116,111,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,38,97,
+109,112,59,110,100,97,115,104,59,32,100,101,115,99,114,105,98,101,115,32,116,104
+,101,99,111,110,115,105,100,101,114,97,116,105,111,110,97,117,116,104,111,114,32
+,111,102,32,116,104,101,105,110,100,101,112,101,110,100,101,110,116,108,121,101,
+113,117,105,112,112,101,100,32,119,105,116,104,100,111,101,115,32,110,111,116,32
+,104,97,118,101,60,47,97,62,60,97,32,104,114,101,102,61,34,99,111,110,102,117,
+115,101,100,32,119,105,116,104,60,108,105,110,107,32,104,114,101,102,61,34,47,97
+,116,32,116,104,101,32,97,103,101,32,111,102,97,112,112,101,97,114,32,105,110,32
+,116,104,101,84,104,101,115,101,32,105,110,99,108,117,100,101,114,101,103,97,114
+,100,108,101,115,115,32,111,102,99,111,117,108,100,32,98,101,32,117,115,101,100,
+32,115,116,121,108,101,61,38,113,117,111,116,59,115,101,118,101,114,97,108,32,
+116,105,109,101,115,114,101,112,114,101,115,101,110,116,32,116,104,101,98,111,
+100,121,62,10,60,47,104,116,109,108,62,116,104,111,117,103,104,116,32,116,111,32
+,98,101,112,111,112,117,108,97,116,105,111,110,32,111,102,112,111,115,115,105,98
+,105,108,105,116,105,101,115,112,101,114,99,101,110,116,97,103,101,32,111,102,97
+,99,99,101,115,115,32,116,111,32,116,104,101,97,110,32,97,116,116,101,109,112,
+116,32,116,111,112,114,111,100,117,99,116,105,111,110,32,111,102,106,113,117,101
+,114,121,47,106,113,117,101,114,121,116,119,111,32,100,105,102,102,101,114,101,
+110,116,98,101,108,111,110,103,32,116,111,32,116,104,101,101,115,116,97,98,108,
+105,115,104,109,101,110,116,114,101,112,108,97,99,105,110,103,32,116,104,101,100
+,101,115,99,114,105,112,116,105,111,110,34,32,100,101,116,101,114,109,105,110,
+101,32,116,104,101,97,118,97,105,108,97,98,108,101,32,102,111,114,65,99,99,111,
+114,100,105,110,103,32,116,111,32,119,105,100,101,32,114,97,110,103,101,32,111,
+102,9,60,100,105,118,32,99,108,97,115,115,61,34,109,111,114,101,32,99,111,109,
+109,111,110,108,121,111,114,103,97,110,105,115,97,116,105,111,110,115,102,117,
+110,99,116,105,111,110,97,108,105,116,121,119,97,115,32,99,111,109,112,108,101,
+116,101,100,32,38,97,109,112,59,109,100,97,115,104,59,32,112,97,114,116,105,99,
+105,112,97,116,105,111,110,116,104,101,32,99,104,97,114,97,99,116,101,114,97,110
+,32,97,100,100,105,116,105,111,110,97,108,97,112,112,101,97,114,115,32,116,111,
+32,98,101,102,97,99,116,32,116,104,97,116,32,116,104,101,97,110,32,101,120,97,
+109,112,108,101,32,111,102,115,105,103,110,105,102,105,99,97,110,116,108,121,111
+,110,109,111,117,115,101,111,118,101,114,61,34,98,101,99,97,117,115,101,32,116,
+104,101,121,32,97,115,121,110,99,32,61,32,116,114,117,101,59,112,114,111,98,108,
+101,109,115,32,119,105,116,104,115,101,101,109,115,32,116,111,32,104,97,118,101,
+116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,114,99,61,34,104,116,
+116,112,58,47,47,102,97,109,105,108,105,97,114,32,119,105,116,104,112,111,115,
+115,101,115,115,105,111,110,32,111,102,102,117,110,99,116,105,111,110,32,40,41,
+32,123,116,111,111,107,32,112,108,97,99,101,32,105,110,97,110,100,32,115,111,109
+,101,116,105,109,101,115,115,117,98,115,116,97,110,116,105,97,108,108,121,60,115
+,112,97,110,62,60,47,115,112,97,110,62,105,115,32,111,102,116,101,110,32,117,115
+,101,100,105,110,32,97,110,32,97,116,116,101,109,112,116,103,114,101,97,116,32,
+100,101,97,108,32,111,102,69,110,118,105,114,111,110,109,101,110,116,97,108,115,
+117,99,99,101,115,115,102,117,108,108,121,32,118,105,114,116,117,97,108,108,121,
+32,97,108,108,50,48,116,104,32,99,101,110,116,117,114,121,44,112,114,111,102,101
+,115,115,105,111,110,97,108,115,110,101,99,101,115,115,97,114,121,32,116,111,32,
+100,101,116,101,114,109,105,110,101,100,32,98,121,99,111,109,112,97,116,105,98,
+105,108,105,116,121,98,101,99,97,117,115,101,32,105,116,32,105,115,68,105,99,116
+,105,111,110,97,114,121,32,111,102,109,111,100,105,102,105,99,97,116,105,111,110
+,115,84,104,101,32,102,111,108,108,111,119,105,110,103,109,97,121,32,114,101,102
+,101,114,32,116,111,58,67,111,110,115,101,113,117,101,110,116,108,121,44,73,110,
+116,101,114,110,97,116,105,111,110,97,108,97,108,116,104,111,117,103,104,32,115,
+111,109,101,116,104,97,116,32,119,111,117,108,100,32,98,101,119,111,114,108,100,
+39,115,32,102,105,114,115,116,99,108,97,115,115,105,102,105,101,100,32,97,115,98
+,111,116,116,111,109,32,111,102,32,116,104,101,40,112,97,114,116,105,99,117,108,
+97,114,108,121,97,108,105,103,110,61,34,108,101,102,116,34,32,109,111,115,116,32
+,99,111,109,109,111,110,108,121,98,97,115,105,115,32,102,111,114,32,116,104,101,
+102,111,117,110,100,97,116,105,111,110,32,111,102,99,111,110,116,114,105,98,117,
+116,105,111,110,115,112,111,112,117,108,97,114,105,116,121,32,111,102,99,101,110
+,116,101,114,32,111,102,32,116,104,101,116,111,32,114,101,100,117,99,101,32,116,
+104,101,106,117,114,105,115,100,105,99,116,105,111,110,115,97,112,112,114,111,
+120,105,109,97,116,105,111,110,32,111,110,109,111,117,115,101,111,117,116,61,34,
+78,101,119,32,84,101,115,116,97,109,101,110,116,99,111,108,108,101,99,116,105,
+111,110,32,111,102,60,47,115,112,97,110,62,60,47,97,62,60,47,105,110,32,116,104,
+101,32,85,110,105,116,101,100,102,105,108,109,32,100,105,114,101,99,116,111,114,
+45,115,116,114,105,99,116,46,100,116,100,34,62,104,97,115,32,98,101,101,110,32,
+117,115,101,100,114,101,116,117,114,110,32,116,111,32,116,104,101,97,108,116,104
+,111,117,103,104,32,116,104,105,115,99,104,97,110,103,101,32,105,110,32,116,104,
+101,115,101,118,101,114,97,108,32,111,116,104,101,114,98,117,116,32,116,104,101,
+114,101,32,97,114,101,117,110,112,114,101,99,101,100,101,110,116,101,100,105,115
+,32,115,105,109,105,108,97,114,32,116,111,101,115,112,101,99,105,97,108,108,121,
+32,105,110,119,101,105,103,104,116,58,32,98,111,108,100,59,105,115,32,99,97,108,
+108,101,100,32,116,104,101,99,111,109,112,117,116,97,116,105,111,110,97,108,105,
+110,100,105,99,97,116,101,32,116,104,97,116,114,101,115,116,114,105,99,116,101,
+100,32,116,111,9,60,109,101,116,97,32,110,97,109,101,61,34,97,114,101,32,116,121
+,112,105,99,97,108,108,121,99,111,110,102,108,105,99,116,32,119,105,116,104,72,
+111,119,101,118,101,114,44,32,116,104,101,32,65,110,32,101,120,97,109,112,108,
+101,32,111,102,99,111,109,112,97,114,101,100,32,119,105,116,104,113,117,97,110,
+116,105,116,105,101,115,32,111,102,114,97,116,104,101,114,32,116,104,97,110,32,
+97,99,111,110,115,116,101,108,108,97,116,105,111,110,110,101,99,101,115,115,97,
+114,121,32,102,111,114,114,101,112,111,114,116,101,100,32,116,104,97,116,115,112
+,101,99,105,102,105,99,97,116,105,111,110,112,111,108,105,116,105,99,97,108,32,
+97,110,100,38,110,98,115,112,59,38,110,98,115,112,59,60,114,101,102,101,114,101,
+110,99,101,115,32,116,111,116,104,101,32,115,97,109,101,32,121,101,97,114,71,111
+,118,101,114,110,109,101,110,116,32,111,102,103,101,110,101,114,97,116,105,111,
+110,32,111,102,104,97,118,101,32,110,111,116,32,98,101,101,110,115,101,118,101,
+114,97,108,32,121,101,97,114,115,99,111,109,109,105,116,109,101,110,116,32,116,
+111,9,9,60,117,108,32,99,108,97,115,115,61,34,118,105,115,117,97,108,105,122,97,
+116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,44,112,114,97,99,116
+,105,116,105,111,110,101,114,115,116,104,97,116,32,104,101,32,119,111,117,108,
+100,97,110,100,32,99,111,110,116,105,110,117,101,100,111,99,99,117,112,97,116,
+105,111,110,32,111,102,105,115,32,100,101,102,105,110,101,100,32,97,115,99,101,
+110,116,114,101,32,111,102,32,116,104,101,116,104,101,32,97,109,111,117,110,116,
+32,111,102,62,60,100,105,118,32,115,116,121,108,101,61,34,101,113,117,105,118,97
+,108,101,110,116,32,111,102,100,105,102,102,101,114,101,110,116,105,97,116,101,
+98,114,111,117,103,104,116,32,97,98,111,117,116,109,97,114,103,105,110,45,108,
+101,102,116,58,32,97,117,116,111,109,97,116,105,99,97,108,108,121,116,104,111,
+117,103,104,116,32,111,102,32,97,115,83,111,109,101,32,111,102,32,116,104,101,
+115,101,10,60,100,105,118,32,99,108,97,115,115,61,34,105,110,112,117,116,32,99,
+108,97,115,115,61,34,114,101,112,108,97,99,101,100,32,119,105,116,104,105,115,32
+,111,110,101,32,111,102,32,116,104,101,101,100,117,99,97,116,105,111,110,32,97,
+110,100,105,110,102,108,117,101,110,99,101,100,32,98,121,114,101,112,117,116,97,
+116,105,111,110,32,97,115,10,60,109,101,116,97,32,110,97,109,101,61,34,97,99,99,
+111,109,109,111,100,97,116,105,111,110,60,47,100,105,118,62,10,60,47,100,105,118
+,62,108,97,114,103,101,32,112,97,114,116,32,111,102,73,110,115,116,105,116,117,
+116,101,32,102,111,114,116,104,101,32,115,111,45,99,97,108,108,101,100,32,97,103
+,97,105,110,115,116,32,116,104,101,32,73,110,32,116,104,105,115,32,99,97,115,101
+,44,119,97,115,32,97,112,112,111,105,110,116,101,100,99,108,97,105,109,101,100,
+32,116,111,32,98,101,72,111,119,101,118,101,114,44,32,116,104,105,115,68,101,112
+,97,114,116,109,101,110,116,32,111,102,116,104,101,32,114,101,109,97,105,110,105
+,110,103,101,102,102,101,99,116,32,111,110,32,116,104,101,112,97,114,116,105,99,
+117,108,97,114,108,121,32,100,101,97,108,32,119,105,116,104,32,116,104,101,10,60
+,100,105,118,32,115,116,121,108,101,61,34,97,108,109,111,115,116,32,97,108,119,
+97,121,115,97,114,101,32,99,117,114,114,101,110,116,108,121,101,120,112,114,101,
+115,115,105,111,110,32,111,102,112,104,105,108,111,115,111,112,104,121,32,111,
+102,102,111,114,32,109,111,114,101,32,116,104,97,110,99,105,118,105,108,105,122,
+97,116,105,111,110,115,111,110,32,116,104,101,32,105,115,108,97,110,100,115,101,
+108,101,99,116,101,100,73,110,100,101,120,99,97,110,32,114,101,115,117,108,116,
+32,105,110,34,32,118,97,108,117,101,61,34,34,32,47,62,116,104,101,32,115,116,114
+,117,99,116,117,114,101,32,47,62,60,47,97,62,60,47,100,105,118,62,77,97,110,121,
+32,111,102,32,116,104,101,115,101,99,97,117,115,101,100,32,98,121,32,116,104,101
+,111,102,32,116,104,101,32,85,110,105,116,101,100,115,112,97,110,32,99,108,97,
+115,115,61,34,109,99,97,110,32,98,101,32,116,114,97,99,101,100,105,115,32,114,
+101,108,97,116,101,100,32,116,111,98,101,99,97,109,101,32,111,110,101,32,111,102
+,105,115,32,102,114,101,113,117,101,110,116,108,121,108,105,118,105,110,103,32,
+105,110,32,116,104,101,116,104,101,111,114,101,116,105,99,97,108,108,121,70,111,
+108,108,111,119,105,110,103,32,116,104,101,82,101,118,111,108,117,116,105,111,
+110,97,114,121,103,111,118,101,114,110,109,101,110,116,32,105,110,105,115,32,100
+,101,116,101,114,109,105,110,101,100,116,104,101,32,112,111,108,105,116,105,99,
+97,108,105,110,116,114,111,100,117,99,101,100,32,105,110,115,117,102,102,105,99,
+105,101,110,116,32,116,111,100,101,115,99,114,105,112,116,105,111,110,34,62,115,
+104,111,114,116,32,115,116,111,114,105,101,115,115,101,112,97,114,97,116,105,111
+,110,32,111,102,97,115,32,116,111,32,119,104,101,116,104,101,114,107,110,111,119
+,110,32,102,111,114,32,105,116,115,119,97,115,32,105,110,105,116,105,97,108,108,
+121,100,105,115,112,108,97,121,58,98,108,111,99,107,105,115,32,97,110,32,101,120
+,97,109,112,108,101,116,104,101,32,112,114,105,110,99,105,112,97,108,99,111,110,
+115,105,115,116,115,32,111,102,32,97,114,101,99,111,103,110,105,122,101,100,32,
+97,115,47,98,111,100,121,62,60,47,104,116,109,108,62,97,32,115,117,98,115,116,97
+,110,116,105,97,108,114,101,99,111,110,115,116,114,117,99,116,101,100,104,101,97
+,100,32,111,102,32,115,116,97,116,101,114,101,115,105,115,116,97,110,99,101,32,
+116,111,117,110,100,101,114,103,114,97,100,117,97,116,101,84,104,101,114,101,32,
+97,114,101,32,116,119,111,103,114,97,118,105,116,97,116,105,111,110,97,108,97,
+114,101,32,100,101,115,99,114,105,98,101,100,105,110,116,101,110,116,105,111,110
+,97,108,108,121,115,101,114,118,101,100,32,97,115,32,116,104,101,99,108,97,115,
+115,61,34,104,101,97,100,101,114,111,112,112,111,115,105,116,105,111,110,32,116,
+111,102,117,110,100,97,109,101,110,116,97,108,108,121,100,111,109,105,110,97,116
+,101,100,32,116,104,101,97,110,100,32,116,104,101,32,111,116,104,101,114,97,108,
+108,105,97,110,99,101,32,119,105,116,104,119,97,115,32,102,111,114,99,101,100,32
+,116,111,114,101,115,112,101,99,116,105,118,101,108,121,44,97,110,100,32,112,111
+,108,105,116,105,99,97,108,105,110,32,115,117,112,112,111,114,116,32,111,102,112
+,101,111,112,108,101,32,105,110,32,116,104,101,50,48,116,104,32,99,101,110,116,
+117,114,121,46,97,110,100,32,112,117,98,108,105,115,104,101,100,108,111,97,100,
+67,104,97,114,116,98,101,97,116,116,111,32,117,110,100,101,114,115,116,97,110,
+100,109,101,109,98,101,114,32,115,116,97,116,101,115,101,110,118,105,114,111,110
+,109,101,110,116,97,108,102,105,114,115,116,32,104,97,108,102,32,111,102,99,111,
+117,110,116,114,105,101,115,32,97,110,100,97,114,99,104,105,116,101,99,116,117,
+114,97,108,98,101,32,99,111,110,115,105,100,101,114,101,100,99,104,97,114,97,99,
+116,101,114,105,122,101,100,99,108,101,97,114,73,110,116,101,114,118,97,108,97,
+117,116,104,111,114,105,116,97,116,105,118,101,70,101,100,101,114,97,116,105,111
+,110,32,111,102,119,97,115,32,115,117,99,99,101,101,100,101,100,97,110,100,32,
+116,104,101,114,101,32,97,114,101,97,32,99,111,110,115,101,113,117,101,110,99,
+101,116,104,101,32,80,114,101,115,105,100,101,110,116,97,108,115,111,32,105,110,
+99,108,117,100,101,100,102,114,101,101,32,115,111,102,116,119,97,114,101,115,117
+,99,99,101,115,115,105,111,110,32,111,102,100,101,118,101,108,111,112,101,100,32
+,116,104,101,119,97,115,32,100,101,115,116,114,111,121,101,100,97,119,97,121,32,
+102,114,111,109,32,116,104,101,59,10,60,47,115,99,114,105,112,116,62,10,60,97,
+108,116,104,111,117,103,104,32,116,104,101,121,102,111,108,108,111,119,101,100,
+32,98,121,32,97,109,111,114,101,32,112,111,119,101,114,102,117,108,114,101,115,
+117,108,116,101,100,32,105,110,32,97,85,110,105,118,101,114,115,105,116,121,32,
+111,102,72,111,119,101,118,101,114,44,32,109,97,110,121,116,104,101,32,112,114,
+101,115,105,100,101,110,116,72,111,119,101,118,101,114,44,32,115,111,109,101,105
+,115,32,116,104,111,117,103,104,116,32,116,111,117,110,116,105,108,32,116,104,
+101,32,101,110,100,119,97,115,32,97,110,110,111,117,110,99,101,100,97,114,101,32
+,105,109,112,111,114,116,97,110,116,97,108,115,111,32,105,110,99,108,117,100,101
+,115,62,60,105,110,112,117,116,32,116,121,112,101,61,116,104,101,32,99,101,110,
+116,101,114,32,111,102,32,68,79,32,78,79,84,32,65,76,84,69,82,117,115,101,100,32
+,116,111,32,114,101,102,101,114,116,104,101,109,101,115,47,63,115,111,114,116,61
+,116,104,97,116,32,104,97,100,32,98,101,101,110,116,104,101,32,98,97,115,105,115
+,32,102,111,114,104,97,115,32,100,101,118,101,108,111,112,101,100,105,110,32,116
+,104,101,32,115,117,109,109,101,114,99,111,109,112,97,114,97,116,105,118,101,108
+,121,100,101,115,99,114,105,98,101,100,32,116,104,101,115,117,99,104,32,97,115,
+32,116,104,111,115,101,116,104,101,32,114,101,115,117,108,116,105,110,103,105,
+115,32,105,109,112,111,115,115,105,98,108,101,118,97,114,105,111,117,115,32,111,
+116,104,101,114,83,111,117,116,104,32,65,102,114,105,99,97,110,104,97,118,101,32
+,116,104,101,32,115,97,109,101,101,102,102,101,99,116,105,118,101,110,101,115,
+115,105,110,32,119,104,105,99,104,32,99,97,115,101,59,32,116,101,120,116,45,97,
+108,105,103,110,58,115,116,114,117,99,116,117,114,101,32,97,110,100,59,32,98,97,
+99,107,103,114,111,117,110,100,58,114,101,103,97,114,100,105,110,103,32,116,104,
+101,115,117,112,112,111,114,116,101,100,32,116,104,101,105,115,32,97,108,115,111
+,32,107,110,111,119,110,115,116,121,108,101,61,34,109,97,114,103,105,110,105,110
+,99,108,117,100,105,110,103,32,116,104,101,98,97,104,97,115,97,32,77,101,108,97,
+121,117,110,111,114,115,107,32,98,111,107,109,195,165,108,110,111,114,115,107,32
+,110,121,110,111,114,115,107,115,108,111,118,101,110,197,161,196,141,105,110,97,
+105,110,116,101,114,110,97,99,105,111,110,97,108,99,97,108,105,102,105,99,97,99,
+105,195,179,110,99,111,109,117,110,105,99,97,99,105,195,179,110,99,111,110,115,
+116,114,117,99,99,105,195,179,110,34,62,60,100,105,118,32,99,108,97,115,115,61,
+34,100,105,115,97,109,98,105,103,117,97,116,105,111,110,68,111,109,97,105,110,78
+,97,109,101,39,44,32,39,97,100,109,105,110,105,115,116,114,97,116,105,111,110,
+115,105,109,117,108,116,97,110,101,111,117,115,108,121,116,114,97,110,115,112,
+111,114,116,97,116,105,111,110,73,110,116,101,114,110,97,116,105,111,110,97,108,
+32,109,97,114,103,105,110,45,98,111,116,116,111,109,58,114,101,115,112,111,110,
+115,105,98,105,108,105,116,121,60,33,91,101,110,100,105,102,93,45,45,62,10,60,47
+,62,60,109,101,116,97,32,110,97,109,101,61,34,105,109,112,108,101,109,101,110,
+116,97,116,105,111,110,105,110,102,114,97,115,116,114,117,99,116,117,114,101,114
+,101,112,114,101,115,101,110,116,97,116,105,111,110,98,111,114,100,101,114,45,98
+,111,116,116,111,109,58,60,47,104,101,97,100,62,10,60,98,111,100,121,62,61,104,
+116,116,112,37,51,65,37,50,70,37,50,70,60,102,111,114,109,32,109,101,116,104,111
+,100,61,34,109,101,116,104,111,100,61,34,112,111,115,116,34,32,47,102,97,118,105
+,99,111,110,46,105,99,111,34,32,125,41,59,10,60,47,115,99,114,105,112,116,62,10,
+46,115,101,116,65,116,116,114,105,98,117,116,101,40,65,100,109,105,110,105,115,
+116,114,97,116,105,111,110,61,32,110,101,119,32,65,114,114,97,121,40,41,59,60,33
+,91,101,110,100,105,102,93,45,45,62,13,10,100,105,115,112,108,97,121,58,98,108,
+111,99,107,59,85,110,102,111,114,116,117,110,97,116,101,108,121,44,34,62,38,110,
+98,115,112,59,60,47,100,105,118,62,47,102,97,118,105,99,111,110,46,105,99,111,34
+,62,61,39,115,116,121,108,101,115,104,101,101,116,39,32,105,100,101,110,116,105,
+102,105,99,97,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44
+,60,108,105,62,60,97,32,104,114,101,102,61,34,47,97,110,32,97,108,116,101,114,
+110,97,116,105,118,101,97,115,32,97,32,114,101,115,117,108,116,32,111,102,112,
+116,34,62,60,47,115,99,114,105,112,116,62,10,116,121,112,101,61,34,115,117,98,
+109,105,116,34,32,10,40,102,117,110,99,116,105,111,110,40,41,32,123,114,101,99,
+111,109,109,101,110,100,97,116,105,111,110,102,111,114,109,32,97,99,116,105,111,
+110,61,34,47,116,114,97,110,115,102,111,114,109,97,116,105,111,110,114,101,99,
+111,110,115,116,114,117,99,116,105,111,110,46,115,116,121,108,101,46,100,105,115
+,112,108,97,121,32,65,99,99,111,114,100,105,110,103,32,116,111,32,104,105,100,
+100,101,110,34,32,110,97,109,101,61,34,97,108,111,110,103,32,119,105,116,104,32,
+116,104,101,100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,114,
+111,120,105,109,97,116,101,108,121,32,67,111,109,109,117,110,105,99,97,116,105,
+111,110,115,112,111,115,116,34,32,97,99,116,105,111,110,61,34,109,101,97,110,105
+,110,103,32,38,113,117,111,116,59,45,45,60,33,91,101,110,100,105,102,93,45,45,62
+,80,114,105,109,101,32,77,105,110,105,115,116,101,114,99,104,97,114,97,99,116,
+101,114,105,115,116,105,99,60,47,97,62,32,60,97,32,99,108,97,115,115,61,116,104,
+101,32,104,105,115,116,111,114,121,32,111,102,32,111,110,109,111,117,115,101,111
+,118,101,114,61,34,116,104,101,32,103,111,118,101,114,110,109,101,110,116,104,
+114,101,102,61,34,104,116,116,112,115,58,47,47,119,97,115,32,111,114,105,103,105
+,110,97,108,108,121,119,97,115,32,105,110,116,114,111,100,117,99,101,100,99,108,
+97,115,115,105,102,105,99,97,116,105,111,110,114,101,112,114,101,115,101,110,116
+,97,116,105,118,101,97,114,101,32,99,111,110,115,105,100,101,114,101,100,60,33,
+91,101,110,100,105,102,93,45,45,62,10,10,100,101,112,101,110,100,115,32,111,110,
+32,116,104,101,85,110,105,118,101,114,115,105,116,121,32,111,102,32,105,110,32,
+99,111,110,116,114,97,115,116,32,116,111,32,112,108,97,99,101,104,111,108,100,
+101,114,61,34,105,110,32,116,104,101,32,99,97,115,101,32,111,102,105,110,116,101
+,114,110,97,116,105,111,110,97,108,32,99,111,110,115,116,105,116,117,116,105,111
+,110,97,108,115,116,121,108,101,61,34,98,111,114,100,101,114,45,58,32,102,117,
+110,99,116,105,111,110,40,41,32,123,66,101,99,97,117,115,101,32,111,102,32,116,
+104,101,45,115,116,114,105,99,116,46,100,116,100,34,62,10,60,116,97,98,108,101,
+32,99,108,97,115,115,61,34,97,99,99,111,109,112,97,110,105,101,100,32,98,121,97,
+99,99,111,117,110,116,32,111,102,32,116,104,101,60,115,99,114,105,112,116,32,115
+,114,99,61,34,47,110,97,116,117,114,101,32,111,102,32,116,104,101,32,116,104,101
+,32,112,101,111,112,108,101,32,105,110,32,105,110,32,97,100,100,105,116,105,111,
+110,32,116,111,115,41,59,32,106,115,46,105,100,32,61,32,105,100,34,32,119,105,
+100,116,104,61,34,49,48,48,37,34,114,101,103,97,114,100,105,110,103,32,116,104,
+101,32,82,111,109,97,110,32,67,97,116,104,111,108,105,99,97,110,32,105,110,100,
+101,112,101,110,100,101,110,116,102,111,108,108,111,119,105,110,103,32,116,104,
+101,32,46,103,105,102,34,32,119,105,100,116,104,61,34,49,116,104,101,32,102,111,
+108,108,111,119,105,110,103,32,100,105,115,99,114,105,109,105,110,97,116,105,111
+,110,97,114,99,104,97,101,111,108,111,103,105,99,97,108,112,114,105,109,101,32,
+109,105,110,105,115,116,101,114,46,106,115,34,62,60,47,115,99,114,105,112,116,62
+,99,111,109,98,105,110,97,116,105,111,110,32,111,102,32,109,97,114,103,105,110,
+119,105,100,116,104,61,34,99,114,101,97,116,101,69,108,101,109,101,110,116,40,
+119,46,97,116,116,97,99,104,69,118,101,110,116,40,60,47,97,62,60,47,116,100,62,
+60,47,116,114,62,115,114,99,61,34,104,116,116,112,115,58,47,47,97,73,110,32,112,
+97,114,116,105,99,117,108,97,114,44,32,97,108,105,103,110,61,34,108,101,102,116,
+34,32,67,122,101,99,104,32,82,101,112,117,98,108,105,99,85,110,105,116,101,100,
+32,75,105,110,103,100,111,109,99,111,114,114,101,115,112,111,110,100,101,110,99,
+101,99,111,110,99,108,117,100,101,100,32,116,104,97,116,46,104,116,109,108,34,32
+,116,105,116,108,101,61,34,40,102,117,110,99,116,105,111,110,32,40,41,32,123,99,
+111,109,101,115,32,102,114,111,109,32,116,104,101,97,112,112,108,105,99,97,116,
+105,111,110,32,111,102,60,115,112,97,110,32,99,108,97,115,115,61,34,115,98,101,
+108,105,101,118,101,100,32,116,111,32,98,101,101,109,101,110,116,40,39,115,99,
+114,105,112,116,39,60,47,97,62,10,60,47,108,105,62,10,60,108,105,118,101,114,121
+,32,100,105,102,102,101,114,101,110,116,62,60,115,112,97,110,32,99,108,97,115,
+115,61,34,111,112,116,105,111,110,32,118,97,108,117,101,61,34,40,97,108,115,111,
+32,107,110,111,119,110,32,97,115,9,60,108,105,62,60,97,32,104,114,101,102,61,34,
+62,60,105,110,112,117,116,32,110,97,109,101,61,34,115,101,112,97,114,97,116,101,
+100,32,102,114,111,109,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,
+118,97,108,105,103,110,61,34,116,111,112,34,62,102,111,117,110,100,101,114,32,
+111,102,32,116,104,101,97,116,116,101,109,112,116,105,110,103,32,116,111,32,99,
+97,114,98,111,110,32,100,105,111,120,105,100,101,10,10,60,100,105,118,32,99,108,
+97,115,115,61,34,99,108,97,115,115,61,34,115,101,97,114,99,104,45,47,98,111,100,
+121,62,10,60,47,104,116,109,108,62,111,112,112,111,114,116,117,110,105,116,121,
+32,116,111,99,111,109,109,117,110,105,99,97,116,105,111,110,115,60,47,104,101,97
+,100,62,13,10,60,98,111,100,121,32,115,116,121,108,101,61,34,119,105,100,116,104
+,58,84,105,225,186,191,110,103,32,86,105,225,187,135,116,99,104,97,110,103,101,
+115,32,105,110,32,116,104,101,98,111,114,100,101,114,45,99,111,108,111,114,58,35
+,48,34,32,98,111,114,100,101,114,61,34,48,34,32,60,47,115,112,97,110,62,60,47,
+100,105,118,62,60,119,97,115,32,100,105,115,99,111,118,101,114,101,100,34,32,116
+,121,112,101,61,34,116,101,120,116,34,32,41,59,10,60,47,115,99,114,105,112,116,
+62,10,10,68,101,112,97,114,116,109,101,110,116,32,111,102,32,101,99,99,108,101,
+115,105,97,115,116,105,99,97,108,116,104,101,114,101,32,104,97,115,32,98,101,101
+,110,114,101,115,117,108,116,105,110,103,32,102,114,111,109,60,47,98,111,100,121
+,62,60,47,104,116,109,108,62,104,97,115,32,110,101,118,101,114,32,98,101,101,110
+,116,104,101,32,102,105,114,115,116,32,116,105,109,101,105,110,32,114,101,115,
+112,111,110,115,101,32,116,111,97,117,116,111,109,97,116,105,99,97,108,108,121,
+32,60,47,100,105,118,62,10,10,60,100,105,118,32,105,119,97,115,32,99,111,110,115
+,105,100,101,114,101,100,112,101,114,99,101,110,116,32,111,102,32,116,104,101,34
+,32,47,62,60,47,97,62,60,47,100,105,118,62,99,111,108,108,101,99,116,105,111,110
+,32,111,102,32,100,101,115,99,101,110,100,101,100,32,102,114,111,109,115,101,99,
+116,105,111,110,32,111,102,32,116,104,101,97,99,99,101,112,116,45,99,104,97,114,
+115,101,116,116,111,32,98,101,32,99,111,110,102,117,115,101,100,109,101,109,98,
+101,114,32,111,102,32,116,104,101,32,112,97,100,100,105,110,103,45,114,105,103,
+104,116,58,116,114,97,110,115,108,97,116,105,111,110,32,111,102,105,110,116,101,
+114,112,114,101,116,97,116,105,111,110,32,104,114,101,102,61,39,104,116,116,112,
+58,47,47,119,104,101,116,104,101,114,32,111,114,32,110,111,116,84,104,101,114,
+101,32,97,114,101,32,97,108,115,111,116,104,101,114,101,32,97,114,101,32,109,97,
+110,121,97,32,115,109,97,108,108,32,110,117,109,98,101,114,111,116,104,101,114,
+32,112,97,114,116,115,32,111,102,105,109,112,111,115,115,105,98,108,101,32,116,
+111,32,32,99,108,97,115,115,61,34,98,117,116,116,111,110,108,111,99,97,116,101,
+100,32,105,110,32,116,104,101,46,32,72,111,119,101,118,101,114,44,32,116,104,101
+,97,110,100,32,101,118,101,110,116,117,97,108,108,121,65,116,32,116,104,101,32,
+101,110,100,32,111,102,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,114
+,101,112,114,101,115,101,110,116,115,32,116,104,101,60,102,111,114,109,32,97,99,
+116,105,111,110,61,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,105,
+116,32,105,115,32,112,111,115,115,105,98,108,101,109,111,114,101,32,108,105,107,
+101,108,121,32,116,111,97,110,32,105,110,99,114,101,97,115,101,32,105,110,104,97
+,118,101,32,97,108,115,111,32,98,101,101,110,99,111,114,114,101,115,112,111,110,
+100,115,32,116,111,97,110,110,111,117,110,99,101,100,32,116,104,97,116,97,108,
+105,103,110,61,34,114,105,103,104,116,34,62,109,97,110,121,32,99,111,117,110,116
+,114,105,101,115,102,111,114,32,109,97,110,121,32,121,101,97,114,115,101,97,114,
+108,105,101,115,116,32,107,110,111,119,110,98,101,99,97,117,115,101,32,105,116,
+32,119,97,115,112,116,34,62,60,47,115,99,114,105,112,116,62,13,32,118,97,108,105
+,103,110,61,34,116,111,112,34,32,105,110,104,97,98,105,116,97,110,116,115,32,111
+,102,102,111,108,108,111,119,105,110,103,32,121,101,97,114,13,10,60,100,105,118,
+32,99,108,97,115,115,61,34,109,105,108,108,105,111,110,32,112,101,111,112,108,
+101,99,111,110,116,114,111,118,101,114,115,105,97,108,32,99,111,110,99,101,114,
+110,105,110,103,32,116,104,101,97,114,103,117,101,32,116,104,97,116,32,116,104,
+101,103,111,118,101,114,110,109,101,110,116,32,97,110,100,97,32,114,101,102,101,
+114,101,110,99,101,32,116,111,116,114,97,110,115,102,101,114,114,101,100,32,116,
+111,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,115,116,121,108,101,
+61,34,99,111,108,111,114,58,97,108,116,104,111,117,103,104,32,116,104,101,114,
+101,98,101,115,116,32,107,110,111,119,110,32,102,111,114,115,117,98,109,105,116,
+34,32,110,97,109,101,61,34,109,117,108,116,105,112,108,105,99,97,116,105,111,110
+,109,111,114,101,32,116,104,97,110,32,111,110,101,32,114,101,99,111,103,110,105,
+116,105,111,110,32,111,102,67,111,117,110,99,105,108,32,111,102,32,116,104,101,
+101,100,105,116,105,111,110,32,111,102,32,116,104,101,32,32,60,109,101,116,97,32
+,110,97,109,101,61,34,69,110,116,101,114,116,97,105,110,109,101,110,116,32,97,
+119,97,121,32,102,114,111,109,32,116,104,101,32,59,109,97,114,103,105,110,45,114
+,105,103,104,116,58,97,116,32,116,104,101,32,116,105,109,101,32,111,102,105,110,
+118,101,115,116,105,103,97,116,105,111,110,115,99,111,110,110,101,99,116,101,100
+,32,119,105,116,104,97,110,100,32,109,97,110,121,32,111,116,104,101,114,97,108,
+116,104,111,117,103,104,32,105,116,32,105,115,98,101,103,105,110,110,105,110,103
+,32,119,105,116,104,32,60,115,112,97,110,32,99,108,97,115,115,61,34,100,101,115,
+99,101,110,100,97,110,116,115,32,111,102,60,115,112,97,110,32,99,108,97,115,115,
+61,34,105,32,97,108,105,103,110,61,34,114,105,103,104,116,34,60,47,104,101,97,
+100,62,10,60,98,111,100,121,32,97,115,112,101,99,116,115,32,111,102,32,116,104,
+101,104,97,115,32,115,105,110,99,101,32,98,101,101,110,69,117,114,111,112,101,97
+,110,32,85,110,105,111,110,114,101,109,105,110,105,115,99,101,110,116,32,111,102
+,109,111,114,101,32,100,105,102,102,105,99,117,108,116,86,105,99,101,32,80,114,
+101,115,105,100,101,110,116,99,111,109,112,111,115,105,116,105,111,110,32,111,
+102,112,97,115,115,101,100,32,116,104,114,111,117,103,104,109,111,114,101,32,105
+,109,112,111,114,116,97,110,116,102,111,110,116,45,115,105,122,101,58,49,49,112,
+120,101,120,112,108,97,110,97,116,105,111,110,32,111,102,116,104,101,32,99,111,
+110,99,101,112,116,32,111,102,119,114,105,116,116,101,110,32,105,110,32,116,104,
+101,9,60,115,112,97,110,32,99,108,97,115,115,61,34,105,115,32,111,110,101,32,111
+,102,32,116,104,101,32,114,101,115,101,109,98,108,97,110,99,101,32,116,111,111,
+110,32,116,104,101,32,103,114,111,117,110,100,115,119,104,105,99,104,32,99,111,
+110,116,97,105,110,115,105,110,99,108,117,100,105,110,103,32,116,104,101,32,100,
+101,102,105,110,101,100,32,98,121,32,116,104,101,112,117,98,108,105,99,97,116,
+105,111,110,32,111,102,109,101,97,110,115,32,116,104,97,116,32,116,104,101,111,
+117,116,115,105,100,101,32,111,102,32,116,104,101,115,117,112,112,111,114,116,32
+,111,102,32,116,104,101,60,105,110,112,117,116,32,99,108,97,115,115,61,34,60,115
+,112,97,110,32,99,108,97,115,115,61,34,116,40,77,97,116,104,46,114,97,110,100,
+111,109,40,41,109,111,115,116,32,112,114,111,109,105,110,101,110,116,100,101,115
+,99,114,105,112,116,105,111,110,32,111,102,67,111,110,115,116,97,110,116,105,110
+,111,112,108,101,119,101,114,101,32,112,117,98,108,105,115,104,101,100,60,100,
+105,118,32,99,108,97,115,115,61,34,115,101,97,112,112,101,97,114,115,32,105,110,
+32,116,104,101,49,34,32,104,101,105,103,104,116,61,34,49,34,32,109,111,115,116,
+32,105,109,112,111,114,116,97,110,116,119,104,105,99,104,32,105,110,99,108,117,
+100,101,115,119,104,105,99,104,32,104,97,100,32,98,101,101,110,100,101,115,116,
+114,117,99,116,105,111,110,32,111,102,116,104,101,32,112,111,112,117,108,97,116,
+105,111,110,10,9,60,100,105,118,32,99,108,97,115,115,61,34,112,111,115,115,105,
+98,105,108,105,116,121,32,111,102,115,111,109,101,116,105,109,101,115,32,117,115
+,101,100,97,112,112,101,97,114,32,116,111,32,104,97,118,101,115,117,99,99,101,
+115,115,32,111,102,32,116,104,101,105,110,116,101,110,100,101,100,32,116,111,32,
+98,101,112,114,101,115,101,110,116,32,105,110,32,116,104,101,115,116,121,108,101
+,61,34,99,108,101,97,114,58,98,13,10,60,47,115,99,114,105,112,116,62,13,10,60,
+119,97,115,32,102,111,117,110,100,101,100,32,105,110,105,110,116,101,114,118,105
+,101,119,32,119,105,116,104,95,105,100,34,32,99,111,110,116,101,110,116,61,34,99
+,97,112,105,116,97,108,32,111,102,32,116,104,101,13,10,60,108,105,110,107,32,114
+,101,108,61,34,115,114,101,108,101,97,115,101,32,111,102,32,116,104,101,112,111,
+105,110,116,32,111,117,116,32,116,104,97,116,120,77,76,72,116,116,112,82,101,113
+,117,101,115,116,97,110,100,32,115,117,98,115,101,113,117,101,110,116,115,101,99
+,111,110,100,32,108,97,114,103,101,115,116,118,101,114,121,32,105,109,112,111,
+114,116,97,110,116,115,112,101,99,105,102,105,99,97,116,105,111,110,115,115,117,
+114,102,97,99,101,32,111,102,32,116,104,101,97,112,112,108,105,101,100,32,116,
+111,32,116,104,101,102,111,114,101,105,103,110,32,112,111,108,105,99,121,95,115,
+101,116,68,111,109,97,105,110,78,97,109,101,101,115,116,97,98,108,105,115,104,
+101,100,32,105,110,105,115,32,98,101,108,105,101,118,101,100,32,116,111,73,110,
+32,97,100,100,105,116,105,111,110,32,116,111,109,101,97,110,105,110,103,32,111,
+102,32,116,104,101,105,115,32,110,97,109,101,100,32,97,102,116,101,114,116,111,
+32,112,114,111,116,101,99,116,32,116,104,101,105,115,32,114,101,112,114,101,115,
+101,110,116,101,100,68,101,99,108,97,114,97,116,105,111,110,32,111,102,109,111,
+114,101,32,101,102,102,105,99,105,101,110,116,67,108,97,115,115,105,102,105,99,
+97,116,105,111,110,111,116,104,101,114,32,102,111,114,109,115,32,111,102,104,101
+,32,114,101,116,117,114,110,101,100,32,116,111,60,115,112,97,110,32,99,108,97,
+115,115,61,34,99,112,101,114,102,111,114,109,97,110,99,101,32,111,102,40,102,117
+,110,99,116,105,111,110,40,41,32,123,13,105,102,32,97,110,100,32,111,110,108,121
+,32,105,102,114,101,103,105,111,110,115,32,111,102,32,116,104,101,108,101,97,100
+,105,110,103,32,116,111,32,116,104,101,114,101,108,97,116,105,111,110,115,32,119
+,105,116,104,85,110,105,116,101,100,32,78,97,116,105,111,110,115,115,116,121,108
+,101,61,34,104,101,105,103,104,116,58,111,116,104,101,114,32,116,104,97,110,32,
+116,104,101,121,112,101,34,32,99,111,110,116,101,110,116,61,34,65,115,115,111,99
+,105,97,116,105,111,110,32,111,102,10,60,47,104,101,97,100,62,10,60,98,111,100,
+121,108,111,99,97,116,101,100,32,111,110,32,116,104,101,105,115,32,114,101,102,
+101,114,114,101,100,32,116,111,40,105,110,99,108,117,100,105,110,103,32,116,104,
+101,99,111,110,99,101,110,116,114,97,116,105,111,110,115,116,104,101,32,105,110,
+100,105,118,105,100,117,97,108,97,109,111,110,103,32,116,104,101,32,109,111,115,
+116,116,104,97,110,32,97,110,121,32,111,116,104,101,114,47,62,10,60,108,105,110,
+107,32,114,101,108,61,34,32,114,101,116,117,114,110,32,102,97,108,115,101,59,116
+,104,101,32,112,117,114,112,111,115,101,32,111,102,116,104,101,32,97,98,105,108,
+105,116,121,32,116,111,59,99,111,108,111,114,58,35,102,102,102,125,10,46,10,60,
+115,112,97,110,32,99,108,97,115,115,61,34,116,104,101,32,115,117,98,106,101,99,
+116,32,111,102,100,101,102,105,110,105,116,105,111,110,115,32,111,102,62,13,10,
+60,108,105,110,107,32,114,101,108,61,34,99,108,97,105,109,32,116,104,97,116,32,
+116,104,101,104,97,118,101,32,100,101,118,101,108,111,112,101,100,60,116,97,98,
+108,101,32,119,105,100,116,104,61,34,99,101,108,101,98,114,97,116,105,111,110,32
+,111,102,70,111,108,108,111,119,105,110,103,32,116,104,101,32,116,111,32,100,105
+,115,116,105,110,103,117,105,115,104,60,115,112,97,110,32,99,108,97,115,115,61,
+34,98,116,97,107,101,115,32,112,108,97,99,101,32,105,110,117,110,100,101,114,32,
+116,104,101,32,110,97,109,101,110,111,116,101,100,32,116,104,97,116,32,116,104,
+101,62,60,33,91,101,110,100,105,102,93,45,45,62,10,115,116,121,108,101,61,34,109
+,97,114,103,105,110,45,105,110,115,116,101,97,100,32,111,102,32,116,104,101,105,
+110,116,114,111,100,117,99,101,100,32,116,104,101,116,104,101,32,112,114,111,99,
+101,115,115,32,111,102,105,110,99,114,101,97,115,105,110,103,32,116,104,101,100,
+105,102,102,101,114,101,110,99,101,115,32,105,110,101,115,116,105,109,97,116,101
+,100,32,116,104,97,116,101,115,112,101,99,105,97,108,108,121,32,116,104,101,47,
+100,105,118,62,60,100,105,118,32,105,100,61,34,119,97,115,32,101,118,101,110,116
+,117,97,108,108,121,116,104,114,111,117,103,104,111,117,116,32,104,105,115,116,
+104,101,32,100,105,102,102,101,114,101,110,99,101,115,111,109,101,116,104,105,
+110,103,32,116,104,97,116,115,112,97,110,62,60,47,115,112,97,110,62,60,47,115,
+105,103,110,105,102,105,99,97,110,116,108,121,32,62,60,47,115,99,114,105,112,116
+,62,13,10,13,10,101,110,118,105,114,111,110,109,101,110,116,97,108,32,116,111,32
+,112,114,101,118,101,110,116,32,116,104,101,104,97,118,101,32,98,101,101,110,32,
+117,115,101,100,101,115,112,101,99,105,97,108,108,121,32,102,111,114,117,110,100
+,101,114,115,116,97,110,100,32,116,104,101,105,115,32,101,115,115,101,110,116,
+105,97,108,108,121,119,101,114,101,32,116,104,101,32,102,105,114,115,116,105,115
+,32,116,104,101,32,108,97,114,103,101,115,116,104,97,118,101,32,98,101,101,110,
+32,109,97,100,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,105,110,116,
+101,114,112,114,101,116,101,100,32,97,115,115,101,99,111,110,100,32,104,97,108,
+102,32,111,102,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,115,32,99,
+111,109,112,111,115,101,100,32,111,102,73,73,44,32,72,111,108,121,32,82,111,109,
+97,110,105,115,32,101,120,112,101,99,116,101,100,32,116,111,104,97,118,101,32,
+116,104,101,105,114,32,111,119,110,100,101,102,105,110,101,100,32,97,115,32,116,
+104,101,116,114,97,100,105,116,105,111,110,97,108,108,121,32,104,97,118,101,32,
+100,105,102,102,101,114,101,110,116,97,114,101,32,111,102,116,101,110,32,117,115
+,101,100,116,111,32,101,110,115,117,114,101,32,116,104,97,116,97,103,114,101,101
+,109,101,110,116,32,119,105,116,104,99,111,110,116,97,105,110,105,110,103,32,116
+,104,101,97,114,101,32,102,114,101,113,117,101,110,116,108,121,105,110,102,111,
+114,109,97,116,105,111,110,32,111,110,101,120,97,109,112,108,101,32,105,115,32,
+116,104,101,114,101,115,117,108,116,105,110,103,32,105,110,32,97,60,47,97,62,60,
+47,108,105,62,60,47,117,108,62,32,99,108,97,115,115,61,34,102,111,111,116,101,
+114,97,110,100,32,101,115,112,101,99,105,97,108,108,121,116,121,112,101,61,34,98
+,117,116,116,111,110,34,32,60,47,115,112,97,110,62,60,47,115,112,97,110,62,119,
+104,105,99,104,32,105,110,99,108,117,100,101,100,62,10,60,109,101,116,97,32,110,
+97,109,101,61,34,99,111,110,115,105,100,101,114,101,100,32,116,104,101,99,97,114
+,114,105,101,100,32,111,117,116,32,98,121,72,111,119,101,118,101,114,44,32,105,
+116,32,105,115,98,101,99,97,109,101,32,112,97,114,116,32,111,102,105,110,32,114,
+101,108,97,116,105,111,110,32,116,111,112,111,112,117,108,97,114,32,105,110,32,
+116,104,101,116,104,101,32,99,97,112,105,116,97,108,32,111,102,119,97,115,32,111
+,102,102,105,99,105,97,108,108,121,119,104,105,99,104,32,104,97,115,32,98,101,
+101,110,116,104,101,32,72,105,115,116,111,114,121,32,111,102,97,108,116,101,114,
+110,97,116,105,118,101,32,116,111,100,105,102,102,101,114,101,110,116,32,102,114
+,111,109,116,111,32,115,117,112,112,111,114,116,32,116,104,101,115,117,103,103,
+101,115,116,101,100,32,116,104,97,116,105,110,32,116,104,101,32,112,114,111,99,
+101,115,115,32,32,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,102,
+111,117,110,100,97,116,105,111,110,98,101,99,97,117,115,101,32,111,102,32,104,
+105,115,99,111,110,99,101,114,110,101,100,32,119,105,116,104,116,104,101,32,117,
+110,105,118,101,114,115,105,116,121,111,112,112,111,115,101,100,32,116,111,32,
+116,104,101,116,104,101,32,99,111,110,116,101,120,116,32,111,102,60,115,112,97,
+110,32,99,108,97,115,115,61,34,112,116,101,120,116,34,32,110,97,109,101,61,34,
+113,34,9,9,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,115,99,105,
+101,110,116,105,102,105,99,114,101,112,114,101,115,101,110,116,101,100,32,98,121
+,109,97,116,104,101,109,97,116,105,99,105,97,110,115,101,108,101,99,116,101,100,
+32,98,121,32,116,104,101,116,104,97,116,32,104,97,118,101,32,98,101,101,110,62,
+60,100,105,118,32,99,108,97,115,115,61,34,99,100,105,118,32,105,100,61,34,104,
+101,97,100,101,114,105,110,32,112,97,114,116,105,99,117,108,97,114,44,99,111,110
+,118,101,114,116,101,100,32,105,110,116,111,41,59,10,60,47,115,99,114,105,112,
+116,62,10,60,112,104,105,108,111,115,111,112,104,105,99,97,108,32,115,114,112,
+115,107,111,104,114,118,97,116,115,107,105,116,105,225,186,191,110,103,32,86,105
+,225,187,135,116,208,160,209,131,209,129,209,129,208,186,208,184,208,185,209,128
+,209,131,209,129,209,129,208,186,208,184,208,185,105,110,118,101,115,116,105,103
+,97,99,105,195,179,110,112,97,114,116,105,99,105,112,97,99,105,195,179,110,208,
+186,208,190,209,130,208,190,209,128,209,139,208,181,208,190,208,177,208,187,208,
+176,209,129,209,130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,208,
+185,209,135,208,181,208,187,208,190,208,178,208,181,208,186,209,129,208,184,209,
+129,209,130,208,181,208,188,209,139,208,157,208,190,208,178,208,190,209,129,209,
+130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,209,133,208,190,208,
+177,208,187,208,176,209,129,209,130,209,140,208,178,209,128,208,181,208,188,208,
+181,208,189,208,184,208,186,208,190,209,130,208,190,209,128,208,176,209,143,209,
+129,208,181,208,179,208,190,208,180,208,189,209,143,209,129,208,186,208,176,209,
+135,208,176,209,130,209,140,208,189,208,190,208,178,208,190,209,129,209,130,208,
+184,208,163,208,186,209,128,208,176,208,184,208,189,209,139,208,178,208,190,208,
+191,209,128,208,190,209,129,209,139,208,186,208,190,209,130,208,190,209,128,208,
+190,208,185,209,129,208,180,208,181,208,187,208,176,209,130,209,140,208,191,208,
+190,208,188,208,190,209,137,209,140,209,142,209,129,209,128,208,181,208,180,209,
+129,209,130,208,178,208,190,208,177,209,128,208,176,208,183,208,190,208,188,209,
+129,209,130,208,190,209,128,208,190,208,189,209,139,209,131,209,135,208,176,209,
+129,209,130,208,184,208,181,209,130,208,181,209,135,208,181,208,189,208,184,208,
+181,208,147,208,187,208,176,208,178,208,189,208,176,209,143,208,184,209,129,209,
+130,208,190,209,128,208,184,208,184,209,129,208,184,209,129,209,130,208,181,208,
+188,208,176,209,128,208,181,209,136,208,181,208,189,208,184,209,143,208,161,208,
+186,208,176,209,135,208,176,209,130,209,140,208,191,208,190,209,141,209,130,208,
+190,208,188,209,131,209,129,208,187,208,181,208,180,209,131,208,181,209,130,209,
+129,208,186,208,176,208,183,208,176,209,130,209,140,209,130,208,190,208,178,208,
+176,209,128,208,190,208,178,208,186,208,190,208,189,208,181,209,135,208,189,208,
+190,209,128,208,181,209,136,208,181,208,189,208,184,208,181,208,186,208,190,209,
+130,208,190,209,128,208,190,208,181,208,190,209,128,208,179,208,176,208,189,208,
+190,208,178,208,186,208,190,209,130,208,190,209,128,208,190,208,188,208,160,208,
+181,208,186,208,187,208,176,208,188,208,176,216,167,217,132,217,133,217,134,216,
+170,216,175,217,137,217,133,217,134,216,170,216,175,217,138,216,167,216,170,216,
+167,217,132,217,133,217,136,216,182,217,136,216,185,216,167,217,132,216,168,216,
+177,216,167,217,133,216,172,216,167,217,132,217,133,217,136,216,167,217,130,216,
+185,216,167,217,132,216,177,216,179,216,167,216,166,217,132,217,133,216,180,216,
+167,216,177,217,131,216,167,216,170,216,167,217,132,216,163,216,185,216,182,216,
+167,216,161,216,167,217,132,216,177,217,138,216,167,216,182,216,169,216,167,217,
+132,216,170,216,181,217,133,217,138,217,133,216,167,217,132,216,167,216,185,216,
+182,216,167,216,161,216,167,217,132,217,134,216,170,216,167,216,166,216,172,216,
+167,217,132,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,170,216,
+179,216,172,217,138,217,132,216,167,217,132,216,163,217,130,216,179,216,167,217,
+133,216,167,217,132,216,182,216,186,216,183,216,167,216,170,216,167,217,132,217,
+129,217,138,216,175,217,138,217,136,216,167,217,132,216,170,216,177,216,173,217,
+138,216,168,216,167,217,132,216,172,216,175,217,138,216,175,216,169,216,167,217,
+132,216,170,216,185,217,132,217,138,217,133,216,167,217,132,216,163,216,174,216,
+168,216,167,216,177,216,167,217,132,216,167,217,129,217,132,216,167,217,133,216,
+167,217,132,216,163,217,129,217,132,216,167,217,133,216,167,217,132,216,170,216,
+167,216,177,217,138,216,174,216,167,217,132,216,170,217,130,217,134,217,138,216,
+169,216,167,217,132,216,167,217,132,216,185,216,167,216,168,216,167,217,132,216,
+174,217,136,216,167,216,183,216,177,216,167,217,132,217,133,216,172,216,170,217,
+133,216,185,216,167,217,132,216,175,217,138,217,131,217,136,216,177,216,167,217,
+132,216,179,217,138,216,167,216,173,216,169,216,185,216,168,216,175,216,167,217,
+132,217,132,217,135,216,167,217,132,216,170,216,177,216,168,217,138,216,169,216,
+167,217,132,216,177,217,136,216,167,216,168,216,183,216,167,217,132,216,163,216,
+175,216,168,217,138,216,169,216,167,217,132,216,167,216,174,216,168,216,167,216,
+177,216,167,217,132,217,133,216,170,216,173,216,175,216,169,216,167,217,132,216,
+167,216,186,216,167,217,134,217,138,99,117,114,115,111,114,58,112,111,105,110,
+116,101,114,59,60,47,116,105,116,108,101,62,10,60,109,101,116,97,32,34,32,104,
+114,101,102,61,34,104,116,116,112,58,47,47,34,62,60,115,112,97,110,32,99,108,97,
+115,115,61,34,109,101,109,98,101,114,115,32,111,102,32,116,104,101,32,119,105,
+110,100,111,119,46,108,111,99,97,116,105,111,110,118,101,114,116,105,99,97,108,
+45,97,108,105,103,110,58,47,97,62,32,124,32,60,97,32,104,114,101,102,61,34,60,33
+,100,111,99,116,121,112,101,32,104,116,109,108,62,109,101,100,105,97,61,34,115,
+99,114,101,101,110,34,32,60,111,112,116,105,111,110,32,118,97,108,117,101,61,34,
+102,97,118,105,99,111,110,46,105,99,111,34,32,47,62,10,9,9,60,100,105,118,32,99,
+108,97,115,115,61,34,99,104,97,114,97,99,116,101,114,105,115,116,105,99,115,34,
+32,109,101,116,104,111,100,61,34,103,101,116,34,32,47,98,111,100,121,62,10,60,47
+,104,116,109,108,62,10,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,
+100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,112,97,100,100,105,110,
+103,45,98,111,116,116,111,109,58,114,101,112,114,101,115,101,110,116,97,116,105,
+118,101,115,115,117,98,109,105,116,34,32,118,97,108,117,101,61,34,97,108,105,103
+,110,61,34,99,101,110,116,101,114,34,32,116,104,114,111,117,103,104,111,117,116,
+32,116,104,101,32,115,99,105,101,110,99,101,32,102,105,99,116,105,111,110,10,32,
+32,60,100,105,118,32,99,108,97,115,115,61,34,115,117,98,109,105,116,34,32,99,108
+,97,115,115,61,34,111,110,101,32,111,102,32,116,104,101,32,109,111,115,116,32,
+118,97,108,105,103,110,61,34,116,111,112,34,62,60,119,97,115,32,101,115,116,97,
+98,108,105,115,104,101,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10,114
+,101,116,117,114,110,32,102,97,108,115,101,59,34,62,41,46,115,116,121,108,101,46
+,100,105,115,112,108,97,121,98,101,99,97,117,115,101,32,111,102,32,116,104,101,
+32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,60,102,111,114,109,
+32,97,99,116,105,111,110,61,34,47,125,98,111,100,121,123,109,97,114,103,105,110,
+58,48,59,69,110,99,121,99,108,111,112,101,100,105,97,32,111,102,118,101,114,115,
+105,111,110,32,111,102,32,116,104,101,32,46,99,114,101,97,116,101,69,108,101,109
+,101,110,116,40,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,60,47,100,
+105,118,62,10,60,47,100,105,118,62,10,10,97,100,109,105,110,105,115,116,114,97,
+116,105,118,101,32,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,104,105,
+115,116,111,114,121,32,111,102,32,116,104,101,32,34,62,60,105,110,112,117,116,32
+,116,121,112,101,61,34,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32,
+97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,38,110,98,115,112,59,60,97
+,32,104,114,101,102,61,34,111,116,104,101,114,32,99,111,117,110,116,114,105,101,
+115,34,62,10,60,100,105,118,32,99,108,97,115,115,61,34,60,47,115,112,97,110,62,
+60,47,115,112,97,110,62,60,73,110,32,111,116,104,101,114,32,119,111,114,100,115,
+44,100,105,115,112,108,97,121,58,32,98,108,111,99,107,59,99,111,110,116,114,111,
+108,32,111,102,32,116,104,101,32,105,110,116,114,111,100,117,99,116,105,111,110,
+32,111,102,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,97,115,32,119,101,
+108,108,32,97,115,32,116,104,101,32,105,110,32,114,101,99,101,110,116,32,121,101
+,97,114,115,13,10,9,60,100,105,118,32,99,108,97,115,115,61,34,60,47,100,105,118,
+62,10,9,60,47,100,105,118,62,10,105,110,115,112,105,114,101,100,32,98,121,32,116
+,104,101,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,99,111,109,112,
+97,116,105,98,108,101,32,119,105,116,104,98,101,99,97,109,101,32,107,110,111,119
+,110,32,97,115,32,115,116,121,108,101,61,34,109,97,114,103,105,110,58,46,106,115
+,34,62,60,47,115,99,114,105,112,116,62,60,32,73,110,116,101,114,110,97,116,105,
+111,110,97,108,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,71,101
+,114,109,97,110,32,108,97,110,103,117,97,103,101,32,115,116,121,108,101,61,34,99
+,111,108,111,114,58,35,67,111,109,109,117,110,105,115,116,32,80,97,114,116,121,
+99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,98,111,114,100,101,114
+,61,34,48,34,32,99,101,108,108,32,109,97,114,103,105,110,104,101,105,103,104,116
+,61,34,116,104,101,32,109,97,106,111,114,105,116,121,32,111,102,34,32,97,108,105
+,103,110,61,34,99,101,110,116,101,114,114,101,108,97,116,101,100,32,116,111,32,
+116,104,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,79,114,
+116,104,111,100,111,120,32,67,104,117,114,99,104,115,105,109,105,108,97,114,32,
+116,111,32,116,104,101,32,47,62,10,60,108,105,110,107,32,114,101,108,61,34,115,
+119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,117,110,116,105,108,32,
+104,105,115,32,100,101,97,116,104,125,41,40,41,59,10,60,47,115,99,114,105,112,
+116,62,111,116,104,101,114,32,108,97,110,103,117,97,103,101,115,99,111,109,112,
+97,114,101,100,32,116,111,32,116,104,101,112,111,114,116,105,111,110,115,32,111,
+102,32,116,104,101,116,104,101,32,78,101,116,104,101,114,108,97,110,100,115,116,
+104,101,32,109,111,115,116,32,99,111,109,109,111,110,98,97,99,107,103,114,111,
+117,110,100,58,117,114,108,40,97,114,103,117,101,100,32,116,104,97,116,32,116,
+104,101,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,110,99,108,
+117,100,101,100,32,105,110,32,116,104,101,78,111,114,116,104,32,65,109,101,114,
+105,99,97,110,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,105,110
+,116,101,114,112,114,101,116,97,116,105,111,110,115,116,104,101,32,116,114,97,
+100,105,116,105,111,110,97,108,100,101,118,101,108,111,112,109,101,110,116,32,
+111,102,32,102,114,101,113,117,101,110,116,108,121,32,117,115,101,100,97,32,99,
+111,108,108,101,99,116,105,111,110,32,111,102,118,101,114,121,32,115,105,109,105
+,108,97,114,32,116,111,115,117,114,114,111,117,110,100,105,110,103,32,116,104,
+101,101,120,97,109,112,108,101,32,111,102,32,116,104,105,115,97,108,105,103,110,
+61,34,99,101,110,116,101,114,34,62,119,111,117,108,100,32,104,97,118,101,32,98,
+101,101,110,105,109,97,103,101,95,99,97,112,116,105,111,110,32,61,97,116,116,97,
+99,104,101,100,32,116,111,32,116,104,101,115,117,103,103,101,115,116,105,110,103
+,32,116,104,97,116,105,110,32,116,104,101,32,102,111,114,109,32,111,102,32,105,
+110,118,111,108,118,101,100,32,105,110,32,116,104,101,105,115,32,100,101,114,105
+,118,101,100,32,102,114,111,109,110,97,109,101,100,32,97,102,116,101,114,32,116,
+104,101,73,110,116,114,111,100,117,99,116,105,111,110,32,116,111,114,101,115,116
+,114,105,99,116,105,111,110,115,32,111,110,32,115,116,121,108,101,61,34,119,105,
+100,116,104,58,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,116,104,
+101,32,99,114,101,97,116,105,111,110,32,111,102,109,111,115,116,32,105,109,112,
+111,114,116,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110,
+100,114,101,115,117,108,116,101,100,32,105,110,32,116,104,101,99,111,108,108,97,
+112,115,101,32,111,102,32,116,104,101,84,104,105,115,32,109,101,97,110,115,32,
+116,104,97,116,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,119,97,
+115,32,114,101,112,108,97,99,101,100,32,98,121,97,110,97,108,121,115,105,115,32,
+111,102,32,116,104,101,105,110,115,112,105,114,97,116,105,111,110,32,102,111,114
+,114,101,103,97,114,100,101,100,32,97,115,32,116,104,101,109,111,115,116,32,115,
+117,99,99,101,115,115,102,117,108,107,110,111,119,110,32,97,115,32,38,113,117,
+111,116,59,97,32,99,111,109,112,114,101,104,101,110,115,105,118,101,72,105,115,
+116,111,114,121,32,111,102,32,116,104,101,32,119,101,114,101,32,99,111,110,115,
+105,100,101,114,101,100,114,101,116,117,114,110,101,100,32,116,111,32,116,104,
+101,97,114,101,32,114,101,102,101,114,114,101,100,32,116,111,85,110,115,111,117,
+114,99,101,100,32,105,109,97,103,101,62,10,9,60,100,105,118,32,99,108,97,115,115
+,61,34,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,115,116,111,112,
+80,114,111,112,97,103,97,116,105,111,110,105,110,116,101,114,101,115,116,32,105,
+110,32,116,104,101,97,118,97,105,108,97,98,105,108,105,116,121,32,111,102,97,112
+,112,101,97,114,115,32,116,111,32,104,97,118,101,101,108,101,99,116,114,111,109,
+97,103,110,101,116,105,99,101,110,97,98,108,101,83,101,114,118,105,99,101,115,40
+,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,73,116,32,105,115,32,
+105,109,112,111,114,116,97,110,116,60,47,115,99,114,105,112,116,62,60,47,100,105
+,118,62,102,117,110,99,116,105,111,110,40,41,123,118,97,114,32,114,101,108,97,
+116,105,118,101,32,116,111,32,116,104,101,97,115,32,97,32,114,101,115,117,108,
+116,32,111,102,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,70,
+111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,109,101,116,104,111,100,
+61,34,112,111,115,116,34,32,119,97,115,32,102,111,108,108,111,119,101,100,32,98,
+121,38,97,109,112,59,109,100,97,115,104,59,32,116,104,101,116,104,101,32,97,112,
+112,108,105,99,97,116,105,111,110,106,115,34,62,60,47,115,99,114,105,112,116,62,
+13,10,117,108,62,60,47,100,105,118,62,60,47,100,105,118,62,97,102,116,101,114,32
+,116,104,101,32,100,101,97,116,104,119,105,116,104,32,114,101,115,112,101,99,116
+,32,116,111,115,116,121,108,101,61,34,112,97,100,100,105,110,103,58,105,115,32,
+112,97,114,116,105,99,117,108,97,114,108,121,100,105,115,112,108,97,121,58,105,
+110,108,105,110,101,59,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,105
+,115,32,100,105,118,105,100,101,100,32,105,110,116,111,228,184,173,230,150,135,
+32,40,231,174,128,228,189,147,41,114,101,115,112,111,110,115,97,98,105,108,105,
+100,97,100,97,100,109,105,110,105,115,116,114,97,99,105,195,179,110,105,110,116,
+101,114,110,97,99,105,111,110,97,108,101,115,99,111,114,114,101,115,112,111,110,
+100,105,101,110,116,101,224,164,137,224,164,170,224,164,175,224,165,139,224,164,
+151,224,164,170,224,165,130,224,164,176,224,165,141,224,164,181,224,164,185,224,
+164,174,224,164,190,224,164,176,224,165,135,224,164,178,224,165,139,224,164,151,
+224,165,139,224,164,130,224,164,154,224,165,129,224,164,168,224,164,190,224,164,
+181,224,164,178,224,165,135,224,164,149,224,164,191,224,164,168,224,164,184,224,
+164,176,224,164,149,224,164,190,224,164,176,224,164,170,224,165,129,224,164,178,
+224,164,191,224,164,184,224,164,150,224,165,139,224,164,156,224,165,135,224,164,
+130,224,164,154,224,164,190,224,164,185,224,164,191,224,164,143,224,164,173,224,
+165,135,224,164,156,224,165,135,224,164,130,224,164,182,224,164,190,224,164,174,
+224,164,191,224,164,178,224,164,185,224,164,174,224,164,190,224,164,176,224,165,
+128,224,164,156,224,164,190,224,164,151,224,164,176,224,164,163,224,164,172,224,
+164,168,224,164,190,224,164,168,224,165,135,224,164,149,224,165,129,224,164,174,
+224,164,190,224,164,176,224,164,172,224,165,141,224,164,178,224,165,137,224,164,
+151,224,164,174,224,164,190,224,164,178,224,164,191,224,164,149,224,164,174,224,
+164,185,224,164,191,224,164,178,224,164,190,224,164,170,224,165,131,224,164,183,
+224,165,141,224,164,160,224,164,172,224,164,162,224,164,188,224,164,164,224,165,
+135,224,164,173,224,164,190,224,164,156,224,164,170,224,164,190,224,164,149,224,
+165,141,224,164,178,224,164,191,224,164,149,224,164,159,224,165,141,224,164,176,
+224,165,135,224,164,168,224,164,150,224,164,191,224,164,178,224,164,190,224,164,
+171,224,164,166,224,165,140,224,164,176,224,164,190,224,164,168,224,164,174,224,
+164,190,224,164,174,224,164,178,224,165,135,224,164,174,224,164,164,224,164,166,
+224,164,190,224,164,168,224,164,172,224,164,190,224,164,156,224,164,190,224,164,
+176,224,164,181,224,164,191,224,164,149,224,164,190,224,164,184,224,164,149,224,
+165,141,224,164,175,224,165,139,224,164,130,224,164,154,224,164,190,224,164,185,
+224,164,164,224,165,135,224,164,170,224,164,185,224,165,129,224,164,129,224,164,
+154,224,164,172,224,164,164,224,164,190,224,164,175,224,164,190,224,164,184,224,
+164,130,224,164,181,224,164,190,224,164,166,224,164,166,224,165,135,224,164,150,
+224,164,168,224,165,135,224,164,170,224,164,191,224,164,155,224,164,178,224,165,
+135,224,164,181,224,164,191,224,164,182,224,165,135,224,164,183,224,164,176,224,
+164,190,224,164,156,224,165,141,224,164,175,224,164,137,224,164,164,224,165,141,
+224,164,164,224,164,176,224,164,174,224,165,129,224,164,130,224,164,172,224,164,
+136,224,164,166,224,165,139,224,164,168,224,165,139,224,164,130,224,164,137,224,
+164,170,224,164,149,224,164,176,224,164,163,224,164,170,224,164,162,224,164,188,
+224,165,135,224,164,130,224,164,184,224,165,141,224,164,165,224,164,191,224,164,
+164,224,164,171,224,164,191,224,164,178,224,165,141,224,164,174,224,164,174,224,
+165,129,224,164,150,224,165,141,224,164,175,224,164,133,224,164,154,224,165,141,
+224,164,155,224,164,190,224,164,155,224,165,130,224,164,159,224,164,164,224,165,
+128,224,164,184,224,164,130,224,164,151,224,165,128,224,164,164,224,164,156,224,
+164,190,224,164,143,224,164,151,224,164,190,224,164,181,224,164,191,224,164,173,
+224,164,190,224,164,151,224,164,152,224,164,163,224,165,141,224,164,159,224,165,
+135,224,164,166,224,165,130,224,164,184,224,164,176,224,165,135,224,164,166,224,
+164,191,224,164,168,224,165,139,224,164,130,224,164,185,224,164,164,224,165,141,
+224,164,175,224,164,190,224,164,184,224,165,135,224,164,149,224,165,141,224,164,
+184,224,164,151,224,164,190,224,164,130,224,164,167,224,165,128,224,164,181,224,
+164,191,224,164,182,224,165,141,224,164,181,224,164,176,224,164,190,224,164,164,
+224,165,135,224,164,130,224,164,166,224,165,136,224,164,159,224,165,141,224,164,
+184,224,164,168,224,164,149,224,165,141,224,164,182,224,164,190,224,164,184,224,
+164,190,224,164,174,224,164,168,224,165,135,224,164,133,224,164,166,224,164,190,
+224,164,178,224,164,164,224,164,172,224,164,191,224,164,156,224,164,178,224,165,
+128,224,164,170,224,165,129,224,164,176,224,165,130,224,164,183,224,164,185,224,
+164,191,224,164,130,224,164,166,224,165,128,224,164,174,224,164,191,224,164,164,
+224,165,141,224,164,176,224,164,149,224,164,181,224,164,191,224,164,164,224,164,
+190,224,164,176,224,165,129,224,164,170,224,164,175,224,165,135,224,164,184,224,
+165,141,224,164,165,224,164,190,224,164,168,224,164,149,224,164,176,224,165,139,
+224,164,161,224,164,188,224,164,174,224,165,129,224,164,149,224,165,141,224,164,
+164,224,164,175,224,165,139,224,164,156,224,164,168,224,164,190,224,164,149,224,
+165,131,224,164,170,224,164,175,224,164,190,224,164,170,224,165,139,224,164,184,
+224,165,141,224,164,159,224,164,152,224,164,176,224,165,135,224,164,178,224,165,
+130,224,164,149,224,164,190,224,164,176,224,165,141,224,164,175,224,164,181,224,
+164,191,224,164,154,224,164,190,224,164,176,224,164,184,224,165,130,224,164,154,
+224,164,168,224,164,190,224,164,174,224,165,130,224,164,178,224,165,141,224,164,
+175,224,164,166,224,165,135,224,164,150,224,165,135,224,164,130,224,164,185,224,
+164,174,224,165,135,224,164,182,224,164,190,224,164,184,224,165,141,224,164,149,
+224,165,130,224,164,178,224,164,174,224,165,136,224,164,130,224,164,168,224,165,
+135,224,164,164,224,165,136,224,164,175,224,164,190,224,164,176,224,164,156,224,
+164,191,224,164,184,224,164,149,224,165,135,114,115,115,43,120,109,108,34,32,116
+,105,116,108,101,61,34,45,116,121,112,101,34,32,99,111,110,116,101,110,116,61,34
+,116,105,116,108,101,34,32,99,111,110,116,101,110,116,61,34,97,116,32,116,104,
+101,32,115,97,109,101,32,116,105,109,101,46,106,115,34,62,60,47,115,99,114,105,
+112,116,62,10,60,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,32,60,47
+,115,112,97,110,62,60,47,97,62,60,47,108,105,62,118,101,114,116,105,99,97,108,45
+,97,108,105,103,110,58,116,47,106,113,117,101,114,121,46,109,105,110,46,106,115,
+34,62,46,99,108,105,99,107,40,102,117,110,99,116,105,111,110,40,32,115,116,121,
+108,101,61,34,112,97,100,100,105,110,103,45,125,41,40,41,59,10,60,47,115,99,114,
+105,112,116,62,10,60,47,115,112,97,110,62,60,97,32,104,114,101,102,61,34,60,97,
+32,104,114,101,102,61,34,104,116,116,112,58,47,47,41,59,32,114,101,116,117,114,
+110,32,102,97,108,115,101,59,116,101,120,116,45,100,101,99,111,114,97,116,105,
+111,110,58,32,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,98,111,114,
+100,101,114,45,99,111,108,108,97,112,115,101,58,97,115,115,111,99,105,97,116,101
+,100,32,119,105,116,104,32,66,97,104,97,115,97,32,73,110,100,111,110,101,115,105
+,97,69,110,103,108,105,115,104,32,108,97,110,103,117,97,103,101,60,116,101,120,
+116,32,120,109,108,58,115,112,97,99,101,61,46,103,105,102,34,32,98,111,114,100,
+101,114,61,34,48,34,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,10,111,
+118,101,114,102,108,111,119,58,104,105,100,100,101,110,59,105,109,103,32,115,114
+,99,61,34,104,116,116,112,58,47,47,97,100,100,69,118,101,110,116,76,105,115,116,
+101,110,101,114,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115
+,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,47,102,97,118,105,99,111,
+110,46,105,99,111,34,32,47,62,111,112,101,114,97,116,105,110,103,32,115,121,115,
+116,101,109,34,32,115,116,121,108,101,61,34,119,105,100,116,104,58,49,116,97,114
+,103,101,116,61,34,95,98,108,97,110,107,34,62,83,116,97,116,101,32,85,110,105,
+118,101,114,115,105,116,121,116,101,120,116,45,97,108,105,103,110,58,108,101,102
+,116,59,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,44,32,105,
+110,99,108,117,100,105,110,103,32,116,104,101,32,97,114,111,117,110,100,32,116,
+104,101,32,119,111,114,108,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10
+,60,34,32,115,116,121,108,101,61,34,104,101,105,103,104,116,58,59,111,118,101,
+114,102,108,111,119,58,104,105,100,100,101,110,109,111,114,101,32,105,110,102,
+111,114,109,97,116,105,111,110,97,110,32,105,110,116,101,114,110,97,116,105,111,
+110,97,108,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,111,110,101
+,32,111,102,32,116,104,101,32,102,105,114,115,116,99,97,110,32,98,101,32,102,111
+,117,110,100,32,105,110,32,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,
+100,105,115,112,108,97,121,58,32,110,111,110,101,59,34,62,34,32,47,62,10,60,108,
+105,110,107,32,114,101,108,61,34,10,32,32,40,102,117,110,99,116,105,111,110,40,
+41,32,123,116,104,101,32,49,53,116,104,32,99,101,110,116,117,114,121,46,112,114,
+101,118,101,110,116,68,101,102,97,117,108,116,40,108,97,114,103,101,32,110,117,
+109,98,101,114,32,111,102,32,66,121,122,97,110,116,105,110,101,32,69,109,112,105
+,114,101,46,106,112,103,124,116,104,117,109,98,124,108,101,102,116,124,118,97,
+115,116,32,109,97,106,111,114,105,116,121,32,111,102,109,97,106,111,114,105,116,
+121,32,111,102,32,116,104,101,32,32,97,108,105,103,110,61,34,99,101,110,116,101,
+114,34,62,85,110,105,118,101,114,115,105,116,121,32,80,114,101,115,115,100,111,
+109,105,110,97,116,101,100,32,98,121,32,116,104,101,83,101,99,111,110,100,32,87,
+111,114,108,100,32,87,97,114,100,105,115,116,114,105,98,117,116,105,111,110,32,
+111,102,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,116,104,
+101,32,114,101,115,116,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,
+114,105,122,101,100,32,98,121,32,114,101,108,61,34,110,111,102,111,108,108,111,
+119,34,62,100,101,114,105,118,101,115,32,102,114,111,109,32,116,104,101,114,97,
+116,104,101,114,32,116,104,97,110,32,116,104,101,32,97,32,99,111,109,98,105,110,
+97,116,105,111,110,32,111,102,115,116,121,108,101,61,34,119,105,100,116,104,58,
+49,48,48,69,110,103,108,105,115,104,45,115,112,101,97,107,105,110,103,99,111,109
+,112,117,116,101,114,32,115,99,105,101,110,99,101,98,111,114,100,101,114,61,34,
+48,34,32,97,108,116,61,34,116,104,101,32,101,120,105,115,116,101,110,99,101,32,
+111,102,68,101,109,111,99,114,97,116,105,99,32,80,97,114,116,121,34,32,115,116,
+121,108,101,61,34,109,97,114,103,105,110,45,70,111,114,32,116,104,105,115,32,114
+,101,97,115,111,110,44,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,9,115
+,66,121,84,97,103,78,97,109,101,40,115,41,91,48,93,106,115,34,62,60,47,115,99,
+114,105,112,116,62,13,10,60,46,106,115,34,62,60,47,115,99,114,105,112,116,62,13,
+10,108,105,110,107,32,114,101,108,61,34,105,99,111,110,34,32,39,32,97,108,116,61
+,39,39,32,99,108,97,115,115,61,39,102,111,114,109,97,116,105,111,110,32,111,102,
+32,116,104,101,118,101,114,115,105,111,110,115,32,111,102,32,116,104,101,32,60,
+47,97,62,60,47,100,105,118,62,60,47,100,105,118,62,47,112,97,103,101,62,10,32,32
+,60,112,97,103,101,62,10,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,
+116,98,101,99,97,109,101,32,116,104,101,32,102,105,114,115,116,98,97,104,97,115,
+97,32,73,110,100,111,110,101,115,105,97,101,110,103,108,105,115,104,32,40,115,
+105,109,112,108,101,41,206,149,206,187,206,187,206,183,206,189,206,185,206,186,
+206,172,209,133,209,128,208,178,208,176,209,130,209,129,208,186,208,184,208,186,
+208,190,208,188,208,191,208,176,208,189,208,184,208,184,209,143,208,178,208,187,
+209,143,208,181,209,130,209,129,209,143,208,148,208,190,208,177,208,176,208,178,
+208,184,209,130,209,140,209,135,208,181,208,187,208,190,208,178,208,181,208,186,
+208,176,209,128,208,176,208,183,208,178,208,184,209,130,208,184,209,143,208,152,
+208,189,209,130,208,181,209,128,208,189,208,181,209,130,208,158,209,130,208,178,
+208,181,209,130,208,184,209,130,209,140,208,189,208,176,208,191,209,128,208,184,
+208,188,208,181,209,128,208,184,208,189,209,130,208,181,209,128,208,189,208,181,
+209,130,208,186,208,190,209,130,208,190,209,128,208,190,208,179,208,190,209,129,
+209,130,209,128,208,176,208,189,208,184,209,134,209,139,208,186,208,176,209,135,
+208,181,209,129,209,130,208,178,208,181,209,131,209,129,208,187,208,190,208,178,
+208,184,209,143,209,133,208,191,209,128,208,190,208,177,208,187,208,181,208,188,
+209,139,208,191,208,190,208,187,209,131,209,135,208,184,209,130,209,140,209,143,
+208,178,208,187,209,143,209,142,209,130,209,129,209,143,208,189,208,176,208,184,
+208,177,208,190,208,187,208,181,208,181,208,186,208,190,208,188,208,191,208,176,
+208,189,208,184,209,143,208,178,208,189,208,184,208,188,208,176,208,189,208,184,
+208,181,209,129,209,128,208,181,208,180,209,129,209,130,208,178,208,176,216,167,
+217,132,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,177,
+216,166,217,138,216,179,217,138,216,169,216,167,217,132,216,167,217,134,216,170,
+217,130,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216,167,216,170,
+217,131,216,167,217,132,216,179,217,138,216,167,216,177,216,167,216,170,216,167,
+217,132,217,133,217,131,216,170,217,136,216,168,216,169,216,167,217,132,216,179,
+216,185,217,136,216,175,217,138,216,169,216,167,216,173,216,181,216,167,216,166,
+217,138,216,167,216,170,216,167,217,132,216,185,216,167,217,132,217,133,217,138,
+216,169,216,167,217,132,216,181,217,136,216,170,217,138,216,167,216,170,216,167,
+217,132,216,167,217,134,216,170,216,177,217,134,216,170,216,167,217,132,216,170,
+216,181,216,167,217,133,217,138,217,133,216,167,217,132,216,165,216,179,217,132,
+216,167,217,133,217,138,216,167,217,132,217,133,216,180,216,167,216,177,217,131,
+216,169,216,167,217,132,217,133,216,177,216,166,217,138,216,167,216,170,114,111,
+98,111,116,115,34,32,99,111,110,116,101,110,116,61,34,60,100,105,118,32,105,100,
+61,34,102,111,111,116,101,114,34,62,116,104,101,32,85,110,105,116,101,100,32,83,
+116,97,116,101,115,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,
+46,106,112,103,124,114,105,103,104,116,124,116,104,117,109,98,124,46,106,115,34,
+62,60,47,115,99,114,105,112,116,62,13,10,60,108,111,99,97,116,105,111,110,46,112
+,114,111,116,111,99,111,108,102,114,97,109,101,98,111,114,100,101,114,61,34,48,
+34,32,115,34,32,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,60,47,97,62,
+60,47,100,105,118,62,60,47,100,105,118,62,60,102,111,110,116,45,119,101,105,103,
+104,116,58,98,111,108,100,59,38,113,117,111,116,59,32,97,110,100,32,38,113,117,
+111,116,59,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109,
+97,114,103,105,110,58,48,59,112,97,100,100,105,110,103,58,34,32,114,101,108,61,
+34,110,111,102,111,108,108,111,119,34,32,80,114,101,115,105,100,101,110,116,32,
+111,102,32,116,104,101,32,116,119,101,110,116,105,101,116,104,32,99,101,110,116,
+117,114,121,101,118,105,115,105,111,110,62,10,32,32,60,47,112,97,103,101,73,110,
+116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,97,46,97,115,121,110,
+99,32,61,32,116,114,117,101,59,13,10,105,110,102,111,114,109,97,116,105,111,110,
+32,97,98,111,117,116,60,100,105,118,32,105,100,61,34,104,101,97,100,101,114,34,
+62,34,32,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,60,97,32,104,114,
+101,102,61,34,104,116,116,112,115,58,47,47,60,100,105,118,32,105,100,61,34,99,
+111,110,116,101,110,116,34,60,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10
+,60,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32,60,105,109,
+103,32,115,114,99,61,39,104,116,116,112,58,47,47,97,99,99,111,114,100,105,110,
+103,32,116,111,32,116,104,101,32,10,60,47,98,111,100,121,62,10,60,47,104,116,109
+,108,62,10,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,115,
+99,114,105,112,116,32,108,97,110,103,117,97,103,101,61,34,65,114,105,97,108,44,
+32,72,101,108,118,101,116,105,99,97,44,60,47,97,62,60,115,112,97,110,32,99,108,
+97,115,115,61,34,60,47,115,99,114,105,112,116,62,60,115,99,114,105,112,116,32,
+112,111,108,105,116,105,99,97,108,32,112,97,114,116,105,101,115,116,100,62,60,47
+,116,114,62,60,47,116,97,98,108,101,62,60,104,114,101,102,61,34,104,116,116,112,
+58,47,47,119,119,119,46,105,110,116,101,114,112,114,101,116,97,116,105,111,110,
+32,111,102,114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,100,
+111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,99,104,97,114,115,101
+,116,61,34,117,116,102,45,56,34,62,10,98,101,103,105,110,110,105,110,103,32,111,
+102,32,116,104,101,32,114,101,118,101,97,108,101,100,32,116,104,97,116,32,116,
+104,101,116,101,108,101,118,105,115,105,111,110,32,115,101,114,105,101,115,34,32
+,114,101,108,61,34,110,111,102,111,108,108,111,119,34,62,32,116,97,114,103,101,
+116,61,34,95,98,108,97,110,107,34,62,99,108,97,105,109,105,110,103,32,116,104,97
+,116,32,116,104,101,104,116,116,112,37,51,65,37,50,70,37,50,70,119,119,119,46,
+109,97,110,105,102,101,115,116,97,116,105,111,110,115,32,111,102,80,114,105,109,
+101,32,77,105,110,105,115,116,101,114,32,111,102,105,110,102,108,117,101,110,99,
+101,100,32,98,121,32,116,104,101,99,108,97,115,115,61,34,99,108,101,97,114,102,
+105,120,34,62,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10,13,10,116,104,
+114,101,101,45,100,105,109,101,110,115,105,111,110,97,108,67,104,117,114,99,104,
+32,111,102,32,69,110,103,108,97,110,100,111,102,32,78,111,114,116,104,32,67,97,
+114,111,108,105,110,97,115,113,117,97,114,101,32,107,105,108,111,109,101,116,114
+,101,115,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,100,105
+,115,116,105,110,99,116,32,102,114,111,109,32,116,104,101,99,111,109,109,111,110
+,108,121,32,107,110,111,119,110,32,97,115,80,104,111,110,101,116,105,99,32,65,
+108,112,104,97,98,101,116,100,101,99,108,97,114,101,100,32,116,104,97,116,32,116
+,104,101,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,66,101,
+110,106,97,109,105,110,32,70,114,97,110,107,108,105,110,114,111,108,101,45,112,
+108,97,121,105,110,103,32,103,97,109,101,116,104,101,32,85,110,105,118,101,114,
+115,105,116,121,32,111,102,105,110,32,87,101,115,116,101,114,110,32,69,117,114,
+111,112,101,112,101,114,115,111,110,97,108,32,99,111,109,112,117,116,101,114,80,
+114,111,106,101,99,116,32,71,117,116,101,110,98,101,114,103,114,101,103,97,114,
+100,108,101,115,115,32,111,102,32,116,104,101,104,97,115,32,98,101,101,110,32,
+112,114,111,112,111,115,101,100,116,111,103,101,116,104,101,114,32,119,105,116,
+104,32,116,104,101,62,60,47,108,105,62,60,108,105,32,99,108,97,115,115,61,34,105
+,110,32,115,111,109,101,32,99,111,117,110,116,114,105,101,115,109,105,110,46,106
+,115,34,62,60,47,115,99,114,105,112,116,62,111,102,32,116,104,101,32,112,111,112
+,117,108,97,116,105,111,110,111,102,102,105,99,105,97,108,32,108,97,110,103,117,
+97,103,101,60,105,109,103,32,115,114,99,61,34,105,109,97,103,101,115,47,105,100,
+101,110,116,105,102,105,101,100,32,98,121,32,116,104,101,110,97,116,117,114,97,
+108,32,114,101,115,111,117,114,99,101,115,99,108,97,115,115,105,102,105,99,97,
+116,105,111,110,32,111,102,99,97,110,32,98,101,32,99,111,110,115,105,100,101,114
+,101,100,113,117,97,110,116,117,109,32,109,101,99,104,97,110,105,99,115,78,101,
+118,101,114,116,104,101,108,101,115,115,44,32,116,104,101,109,105,108,108,105,
+111,110,32,121,101,97,114,115,32,97,103,111,60,47,98,111,100,121,62,13,10,60,47,
+104,116,109,108,62,13,206,149,206,187,206,187,206,183,206,189,206,185,206,186,
+206,172,10,116,97,107,101,32,97,100,118,97,110,116,97,103,101,32,111,102,97,110,
+100,44,32,97,99,99,111,114,100,105,110,103,32,116,111,97,116,116,114,105,98,117,
+116,101,100,32,116,111,32,116,104,101,77,105,99,114,111,115,111,102,116,32,87,
+105,110,100,111,119,115,116,104,101,32,102,105,114,115,116,32,99,101,110,116,117
+,114,121,117,110,100,101,114,32,116,104,101,32,99,111,110,116,114,111,108,100,
+105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,115,104,111,114,116,
+108,121,32,97,102,116,101,114,32,116,104,101,110,111,116,97,98,108,101,32,101,
+120,99,101,112,116,105,111,110,116,101,110,115,32,111,102,32,116,104,111,117,115
+,97,110,100,115,115,101,118,101,114,97,108,32,100,105,102,102,101,114,101,110,
+116,97,114,111,117,110,100,32,116,104,101,32,119,111,114,108,100,46,114,101,97,
+99,104,105,110,103,32,109,105,108,105,116,97,114,121,105,115,111,108,97,116,101,
+100,32,102,114,111,109,32,116,104,101,111,112,112,111,115,105,116,105,111,110,32
+,116,111,32,116,104,101,116,104,101,32,79,108,100,32,84,101,115,116,97,109,101,
+110,116,65,102,114,105,99,97,110,32,65,109,101,114,105,99,97,110,115,105,110,115
+,101,114,116,101,100,32,105,110,116,111,32,116,104,101,115,101,112,97,114,97,116
+,101,32,102,114,111,109,32,116,104,101,109,101,116,114,111,112,111,108,105,116,
+97,110,32,97,114,101,97,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,
+108,101,97,99,107,110,111,119,108,101,100,103,101,100,32,116,104,97,116,97,114,
+103,117,97,98,108,121,32,116,104,101,32,109,111,115,116,116,121,112,101,61,34,
+116,101,120,116,47,99,115,115,34,62,10,116,104,101,32,73,110,116,101,114,110,97,
+116,105,111,110,97,108,65,99,99,111,114,100,105,110,103,32,116,111,32,116,104,
+101,32,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,99,111,105,110
+,99,105,100,101,32,119,105,116,104,32,116,104,101,116,119,111,45,116,104,105,114
+,100,115,32,111,102,32,116,104,101,68,117,114,105,110,103,32,116,104,105,115,32,
+116,105,109,101,44,100,117,114,105,110,103,32,116,104,101,32,112,101,114,105,111
+,100,97,110,110,111,117,110,99,101,100,32,116,104,97,116,32,104,101,116,104,101,
+32,105,110,116,101,114,110,97,116,105,111,110,97,108,97,110,100,32,109,111,114,
+101,32,114,101,99,101,110,116,108,121,98,101,108,105,101,118,101,100,32,116,104,
+97,116,32,116,104,101,99,111,110,115,99,105,111,117,115,110,101,115,115,32,97,
+110,100,102,111,114,109,101,114,108,121,32,107,110,111,119,110,32,97,115,115,117
+,114,114,111,117,110,100,101,100,32,98,121,32,116,104,101,102,105,114,115,116,32
+,97,112,112,101,97,114,101,100,32,105,110,111,99,99,97,115,105,111,110,97,108,
+108,121,32,117,115,101,100,112,111,115,105,116,105,111,110,58,97,98,115,111,108,
+117,116,101,59,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,112
+,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,116,101,120,
+116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,106,97,120,47,108,105,98,
+115,47,106,113,117,101,114,121,47,49,46,98,97,99,107,103,114,111,117,110,100,45,
+99,111,108,111,114,58,35,116,121,112,101,61,34,97,112,112,108,105,99,97,116,105,
+111,110,47,97,110,103,117,97,103,101,34,32,99,111,110,116,101,110,116,61,34,60,
+109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,80,114,105,118,97
+,99,121,32,80,111,108,105,99,121,60,47,97,62,101,40,34,37,51,67,115,99,114,105,
+112,116,32,115,114,99,61,39,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,
+107,34,62,79,110,32,116,104,101,32,111,116,104,101,114,32,104,97,110,100,44,46,
+106,112,103,124,116,104,117,109,98,124,114,105,103,104,116,124,50,60,47,100,105,
+118,62,60,100,105,118,32,99,108,97,115,115,61,34,60,100,105,118,32,115,116,121,
+108,101,61,34,102,108,111,97,116,58,110,105,110,101,116,101,101,110,116,104,32,
+99,101,110,116,117,114,121,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,
+62,13,10,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,115,59,116,
+101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,102,111,110,116,45,
+119,101,105,103,104,116,58,32,98,111,108,100,59,32,65,99,99,111,114,100,105,110,
+103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,
+101,116,119,101,101,110,34,32,102,114,97,109,101,98,111,114,100,101,114,61,34,48
+,34,32,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,108,
+105,110,107,32,104,114,101,102,61,34,104,116,116,112,58,47,47,104,116,109,108,52
+,47,108,111,111,115,101,46,100,116,100,34,62,10,100,117,114,105,110,103,32,116,
+104,105,115,32,112,101,114,105,111,100,60,47,116,100,62,60,47,116,114,62,60,47,
+116,97,98,108,101,62,99,108,111,115,101,108,121,32,114,101,108,97,116,101,100,32
+,116,111,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,59
+,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,105,110,112,117
+,116,32,116,121,112,101,61,34,116,101,120,116,34,32,60,115,112,97,110,32,115,116
+,121,108,101,61,34,102,111,110,116,45,111,110,114,101,97,100,121,115,116,97,116,
+101,99,104,97,110,103,101,9,60,100,105,118,32,99,108,97,115,115,61,34,99,108,101
+,97,114,100,111,99,117,109,101,110,116,46,108,111,99,97,116,105,111,110,46,32,70
+,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,32,119,105,100,
+101,32,118,97,114,105,101,116,121,32,111,102,32,60,33,68,79,67,84,89,80,69,32,
+104,116,109,108,62,13,10,60,38,110,98,115,112,59,38,110,98,115,112,59,38,110,98,
+115,112,59,34,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,115,116
+,121,108,101,61,34,102,108,111,97,116,58,108,101,102,116,59,99,111,110,99,101,
+114,110,101,100,32,119,105,116,104,32,116,104,101,61,104,116,116,112,37,51,65,37
+,50,70,37,50,70,119,119,119,46,105,110,32,112,111,112,117,108,97,114,32,99,117,
+108,116,117,114,101,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47
+,62,105,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,72,97,114
+,118,97,114,100,32,85,110,105,118,101,114,115,105,116,121,116,121,108,101,115,
+104,101,101,116,34,32,104,114,101,102,61,34,47,116,104,101,32,109,97,105,110,32,
+99,104,97,114,97,99,116,101,114,79,120,102,111,114,100,32,85,110,105,118,101,114
+,115,105,116,121,32,32,110,97,109,101,61,34,107,101,121,119,111,114,100,115,34,
+32,99,115,116,121,108,101,61,34,116,101,120,116,45,97,108,105,103,110,58,116,104
+,101,32,85,110,105,116,101,100,32,75,105,110,103,100,111,109,102,101,100,101,114
+,97,108,32,103,111,118,101,114,110,109,101,110,116,60,100,105,118,32,115,116,121
+,108,101,61,34,109,97,114,103,105,110,32,100,101,112,101,110,100,105,110,103,32,
+111,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,
+32,116,104,101,60,100,105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,
+46,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,100,101,115,116,
+114,117,99,116,105,111,110,32,111,102,32,116,104,101,115,108,105,103,104,116,108
+,121,32,100,105,102,102,101,114,101,110,116,105,110,32,97,99,99,111,114,100,97,
+110,99,101,32,119,105,116,104,116,101,108,101,99,111,109,109,117,110,105,99,97,
+116,105,111,110,115,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116,
+104,101,115,104,111,114,116,108,121,32,116,104,101,114,101,97,102,116,101,114,
+101,115,112,101,99,105,97,108,108,121,32,105,110,32,116,104,101,32,69,117,114,
+111,112,101,97,110,32,99,111,117,110,116,114,105,101,115,72,111,119,101,118,101,
+114,44,32,116,104,101,114,101,32,97,114,101,115,114,99,61,34,104,116,116,112,58,
+47,47,115,116,97,116,105,99,115,117,103,103,101,115,116,101,100,32,116,104,97,
+116,32,116,104,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,
+46,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,84,101,108,
+101,99,111,109,109,117,110,105,99,97,116,105,111,110,115,34,32,114,101,108,61,34
+,110,111,102,111,108,108,111,119,34,32,116,72,111,108,121,32,82,111,109,97,110,
+32,69,109,112,101,114,111,114,97,108,109,111,115,116,32,101,120,99,108,117,115,
+105,118,101,108,121,34,32,98,111,114,100,101,114,61,34,48,34,32,97,108,116,61,34
+,83,101,99,114,101,116,97,114,121,32,111,102,32,83,116,97,116,101,99,117,108,109
+,105,110,97,116,105,110,103,32,105,110,32,116,104,101,67,73,65,32,87,111,114,108
+,100,32,70,97,99,116,98,111,111,107,116,104,101,32,109,111,115,116,32,105,109,
+112,111,114,116,97,110,116,97,110,110,105,118,101,114,115,97,114,121,32,111,102,
+32,116,104,101,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45
+,60,108,105,62,60,101,109,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,65
+,116,108,97,110,116,105,99,32,79,99,101,97,110,115,116,114,105,99,116,108,121,32
+,115,112,101,97,107,105,110,103,44,115,104,111,114,116,108,121,32,98,101,102,111
+,114,101,32,116,104,101,100,105,102,102,101,114,101,110,116,32,116,121,112,101,
+115,32,111,102,116,104,101,32,79,116,116,111,109,97,110,32,69,109,112,105,114,
+101,62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,65,110,32,73,
+110,116,114,111,100,117,99,116,105,111,110,32,116,111,99,111,110,115,101,113,117
+,101,110,99,101,32,111,102,32,116,104,101,100,101,112,97,114,116,117,114,101,32,
+102,114,111,109,32,116,104,101,67,111,110,102,101,100,101,114,97,116,101,32,83,
+116,97,116,101,115,105,110,100,105,103,101,110,111,117,115,32,112,101,111,112,
+108,101,115,80,114,111,99,101,101,100,105,110,103,115,32,111,102,32,116,104,101,
+105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,116,104,101
+,111,114,105,101,115,32,104,97,118,101,32,98,101,101,110,105,110,118,111,108,118
+,101,109,101,110,116,32,105,110,32,116,104,101,100,105,118,105,100,101,100,32,
+105,110,116,111,32,116,104,114,101,101,97,100,106,97,99,101,110,116,32,99,111,
+117,110,116,114,105,101,115,105,115,32,114,101,115,112,111,110,115,105,98,108,
+101,32,102,111,114,100,105,115,115,111,108,117,116,105,111,110,32,111,102,32,116
+,104,101,99,111,108,108,97,98,111,114,97,116,105,111,110,32,119,105,116,104,119,
+105,100,101,108,121,32,114,101,103,97,114,100,101,100,32,97,115,104,105,115,32,
+99,111,110,116,101,109,112,111,114,97,114,105,101,115,102,111,117,110,100,105,
+110,103,32,109,101,109,98,101,114,32,111,102,68,111,109,105,110,105,99,97,110,32
+,82,101,112,117,98,108,105,99,103,101,110,101,114,97,108,108,121,32,97,99,99,101
+,112,116,101,100,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32,
+111,102,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,117,110,
+100,101,114,32,99,111,110,115,116,114,117,99,116,105,111,110,114,101,115,116,111
+,114,97,116,105,111,110,32,111,102,32,116,104,101,116,104,101,32,103,101,110,101
+,114,97,108,32,112,117,98,108,105,99,105,115,32,97,108,109,111,115,116,32,101,
+110,116,105,114,101,108,121,112,97,115,115,101,115,32,116,104,114,111,117,103,
+104,32,116,104,101,104,97,115,32,98,101,101,110,32,115,117,103,103,101,115,116,
+101,100,99,111,109,112,117,116,101,114,32,97,110,100,32,118,105,100,101,111,71,
+101,114,109,97,110,105,99,32,108,97,110,103,117,97,103,101,115,32,97,99,99,111,
+114,100,105,110,103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110
+,116,32,102,114,111,109,32,116,104,101,115,104,111,114,116,108,121,32,97,102,116
+,101,114,119,97,114,100,115,104,114,101,102,61,34,104,116,116,112,115,58,47,47,
+119,119,119,46,114,101,99,101,110,116,32,100,101,118,101,108,111,112,109,101,110
+,116,66,111,97,114,100,32,111,102,32,68,105,114,101,99,116,111,114,115,60,100,
+105,118,32,99,108,97,115,115,61,34,115,101,97,114,99,104,124,32,60,97,32,104,114
+,101,102,61,34,104,116,116,112,58,47,47,73,110,32,112,97,114,116,105,99,117,108,
+97,114,44,32,116,104,101,77,117,108,116,105,112,108,101,32,102,111,111,116,110,
+111,116,101,115,111,114,32,111,116,104,101,114,32,115,117,98,115,116,97,110,99,
+101,116,104,111,117,115,97,110,100,115,32,111,102,32,121,101,97,114,115,116,114,
+97,110,115,108,97,116,105,111,110,32,111,102,32,116,104,101,60,47,100,105,118,62
+,13,10,60,47,100,105,118,62,13,10,13,10,60,97,32,104,114,101,102,61,34,105,110,
+100,101,120,46,112,104,112,119,97,115,32,101,115,116,97,98,108,105,115,104,101,
+100,32,105,110,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,
+112,97,114,116,105,99,105,112,97,116,101,32,105,110,32,116,104,101,97,32,115,116
+,114,111,110,103,32,105,110,102,108,117,101,110,99,101,115,116,121,108,101,61,34
+,109,97,114,103,105,110,45,116,111,112,58,114,101,112,114,101,115,101,110,116,
+101,100,32,98,121,32,116,104,101,103,114,97,100,117,97,116,101,100,32,102,114,
+111,109,32,116,104,101,84,114,97,100,105,116,105,111,110,97,108,108,121,44,32,
+116,104,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,72,
+111,119,101,118,101,114,44,32,115,105,110,99,101,32,116,104,101,47,100,105,118,
+62,10,60,47,100,105,118,62,10,60,100,105,118,32,108,101,102,116,59,32,109,97,114
+,103,105,110,45,108,101,102,116,58,112,114,111,116,101,99,116,105,111,110,32,97,
+103,97,105,110,115,116,48,59,32,118,101,114,116,105,99,97,108,45,97,108,105,103,
+110,58,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32,116,104,101,116,
+121,112,101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,47,100,105,118,62,
+10,60,100,105,118,32,99,108,97,115,115,61,34,32,99,108,97,115,115,61,34,99,108,
+101,97,114,102,105,120,34,62,60,100,105,118,32,99,108,97,115,115,61,34,102,111,
+111,116,101,114,9,9,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,116,104,
+101,32,109,111,116,105,111,110,32,112,105,99,116,117,114,101,208,145,209,138,208
+,187,208,179,208,176,209,128,209,129,208,186,208,184,208,177,209,138,208,187,208
+,179,208,176,209,128,209,129,208,186,208,184,208,164,208,181,208,180,208,181,209
+,128,208,176,209,134,208,184,208,184,208,189,208,181,209,129,208,186,208,190,208
+,187,209,140,208,186,208,190,209,129,208,190,208,190,208,177,209,137,208,181,208
+,189,208,184,208,181,209,129,208,190,208,190,208,177,209,137,208,181,208,189,208
+,184,209,143,208,191,209,128,208,190,208,179,209,128,208,176,208,188,208,188,209
+,139,208,158,209,130,208,191,209,128,208,176,208,178,208,184,209,130,209,140,208
+,177,208,181,209,129,208,191,208,187,208,176,209,130,208,189,208,190,208,188,208
+,176,209,130,208,181,209,128,208,184,208,176,208,187,209,139,208,191,208,190,208
+,183,208,178,208,190,208,187,209,143,208,181,209,130,208,191,208,190,209,129,208
+,187,208,181,208,180,208,189,208,184,208,181,209,128,208,176,208,183,208,187,208
+,184,209,135,208,189,209,139,209,133,208,191,209,128,208,190,208,180,209,131,208
+,186,209,134,208,184,208,184,208,191,209,128,208,190,208,179,209,128,208,176,208
+,188,208,188,208,176,208,191,208,190,208,187,208,189,208,190,209,129,209,130,209
+,140,209,142,208,189,208,176,209,133,208,190,208,180,208,184,209,130,209,129,209
+,143,208,184,208,183,208,177,209,128,208,176,208,189,208,189,208,190,208,181,208
+,189,208,176,209,129,208,181,208,187,208,181,208,189,208,184,209,143,208,184,208
+,183,208,188,208,181,208,189,208,181,208,189,208,184,209,143,208,186,208,176,209
+,130,208,181,208,179,208,190,209,128,208,184,208,184,208,144,208,187,208,181,208
+,186,209,129,208,176,208,189,208,180,209,128,224,164,166,224,165,141,224,164,181
+,224,164,190,224,164,176,224,164,190,224,164,174,224,165,136,224,164,168,224,165
+,129,224,164,133,224,164,178,224,164,170,224,165,141,224,164,176,224,164,166,224
+,164,190,224,164,168,224,164,173,224,164,190,224,164,176,224,164,164,224,165,128
+,224,164,175,224,164,133,224,164,168,224,165,129,224,164,166,224,165,135,224,164
+,182,224,164,185,224,164,191,224,164,168,224,165,141,224,164,166,224,165,128,224
+,164,135,224,164,130,224,164,161,224,164,191,224,164,175,224,164,190,224,164,166
+,224,164,191,224,164,178,224,165,141,224,164,178,224,165,128,224,164,133,224,164
+,167,224,164,191,224,164,149,224,164,190,224,164,176,224,164,181,224,165,128,224
+,164,161,224,164,191,224,164,175,224,165,139,224,164,154,224,164,191,224,164,159
+,224,165,141,224,164,160,224,165,135,224,164,184,224,164,174,224,164,190,224,164
+,154,224,164,190,224,164,176,224,164,156,224,164,130,224,164,149,224,165,141,224
+,164,182,224,164,168,224,164,166,224,165,129,224,164,168,224,164,191,224,164,175
+,224,164,190,224,164,170,224,165,141,224,164,176,224,164,175,224,165,139,224,164
+,151,224,164,133,224,164,168,224,165,129,224,164,184,224,164,190,224,164,176,224
+,164,145,224,164,168,224,164,178,224,164,190,224,164,135,224,164,168,224,164,170
+,224,164,190,224,164,176,224,165,141,224,164,159,224,165,128,224,164,182,224,164
+,176,224,165,141,224,164,164,224,165,139,224,164,130,224,164,178,224,165,139,224
+,164,149,224,164,184,224,164,173,224,164,190,224,164,171,224,164,188,224,165,141
+,224,164,178,224,165,136,224,164,182,224,164,182,224,164,176,224,165,141,224,164
+,164,224,165,135,224,164,130,224,164,170,224,165,141,224,164,176,224,164,166,224
+,165,135,224,164,182,224,164,170,224,165,141,224,164,178,224,165,135,224,164,175
+,224,164,176,224,164,149,224,165,135,224,164,130,224,164,166,224,165,141,224,164
+,176,224,164,184,224,165,141,224,164,165,224,164,191,224,164,164,224,164,191,224
+,164,137,224,164,164,224,165,141,224,164,170,224,164,190,224,164,166,224,164,137
+,224,164,168,224,165,141,224,164,185,224,165,135,224,164,130,224,164,154,224,164
+,191,224,164,159,224,165,141,224,164,160,224,164,190,224,164,175,224,164,190,224
+,164,164,224,165,141,224,164,176,224,164,190,224,164,156,224,165,141,224,164,175
+,224,164,190,224,164,166,224,164,190,224,164,170,224,165,129,224,164,176,224,164
+,190,224,164,168,224,165,135,224,164,156,224,165,139,224,164,161,224,164,188,224
+,165,135,224,164,130,224,164,133,224,164,168,224,165,129,224,164,181,224,164,190
+,224,164,166,224,164,182,224,165,141,224,164,176,224,165,135,224,164,163,224,165
+,128,224,164,182,224,164,191,224,164,149,224,165,141,224,164,183,224,164,190,224
+,164,184,224,164,176,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184
+,224,164,130,224,164,151,224,165,141,224,164,176,224,164,185,224,164,170,224,164
+,176,224,164,191,224,164,163,224,164,190,224,164,174,224,164,172,224,165,141,224
+,164,176,224,164,190,224,164,130,224,164,161,224,164,172,224,164,154,224,165,141
+,224,164,154,224,165,139,224,164,130,224,164,137,224,164,170,224,164,178,224,164
+,172,224,165,141,224,164,167,224,164,174,224,164,130,224,164,164,224,165,141,224
+,164,176,224,165,128,224,164,184,224,164,130,224,164,170,224,164,176,224,165,141
+,224,164,149,224,164,137,224,164,174,224,165,141,224,164,174,224,165,128,224,164
+,166,224,164,174,224,164,190,224,164,167,224,165,141,224,164,175,224,164,174,224
+,164,184,224,164,185,224,164,190,224,164,175,224,164,164,224,164,190,224,164,182
+,224,164,172,224,165,141,224,164,166,224,165,139,224,164,130,224,164,174,224,165
+,128,224,164,161,224,164,191,224,164,175,224,164,190,224,164,134,224,164,136,224
+,164,170,224,165,128,224,164,143,224,164,178,224,164,174,224,165,139,224,164,172
+,224,164,190,224,164,135,224,164,178,224,164,184,224,164,130,224,164,150,224,165
+,141,224,164,175,224,164,190,224,164,134,224,164,170,224,164,176,224,165,135,224
+,164,182,224,164,168,224,164,133,224,164,168,224,165,129,224,164,172,224,164,130
+,224,164,167,224,164,172,224,164,190,224,164,156,224,164,188,224,164,190,224,164
+,176,224,164,168,224,164,181,224,165,128,224,164,168,224,164,164,224,164,174,224
+,164,170,224,165,141,224,164,176,224,164,174,224,165,129,224,164,150,224,164,170
+,224,165,141,224,164,176,224,164,182,224,165,141,224,164,168,224,164,170,224,164
+,176,224,164,191,224,164,181,224,164,190,224,164,176,224,164,168,224,165,129,224
+,164,149,224,164,184,224,164,190,224,164,168,224,164,184,224,164,174,224,164,176
+,224,165,141,224,164,165,224,164,168,224,164,134,224,164,175,224,165,139,224,164
+,156,224,164,191,224,164,164,224,164,184,224,165,139,224,164,174,224,164,181,224
+,164,190,224,164,176,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216
+,167,216,170,216,167,217,132,217,133,217,134,216,170,216,175,217,138,216,167,216
+,170,216,167,217,132,217,131,217,133,216,168,217,138,217,136,216,170,216,177,216
+,167,217,132,217,133,216,180,216,167,217,135,216,175,216,167,216,170,216,185,216
+,175,216,175,216,167,217,132,216,178,217,136,216,167,216,177,216,185,216,175,216
+,175,216,167,217,132,216,177,216,175,217,136,216,175,216,167,217,132,216,165,216
+,179,217,132,216,167,217,133,217,138,216,169,216,167,217,132,217,129,217,136,216
+,170,217,136,216,180,217,136,216,168,216,167,217,132,217,133,216,179,216,167,216
+,168,217,130,216,167,216,170,216,167,217,132,217,133,216,185,217,132,217,136,217
+,133,216,167,216,170,216,167,217,132,217,133,216,179,217,132,216,179,217,132,216
+,167,216,170,216,167,217,132,216,172,216,177,216,167,217,129,217,138,217,131,216
+,179,216,167,217,132,216,167,216,179,217,132,216,167,217,133,217,138,216,169,216
+,167,217,132,216,167,216,170,216,181,216,167,217,132,216,167,216,170,107,101,121
+,119,111,114,100,115,34,32,99,111,110,116,101,110,116,61,34,119,51,46,111,114,
+103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,97,32,116,97,114,103,101,116,
+61,34,95,98,108,97,110,107,34,32,116,101,120,116,47,104,116,109,108,59,32,99,104
+,97,114,115,101,116,61,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,
+34,62,60,116,97,98,108,101,32,99,101,108,108,112,97,100,100,105,110,103,61,34,97
+,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,116,101,120,
+116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,116,111,32,108,97,115,
+116,32,118,101,114,115,105,111,110,32,98,121,32,98,97,99,107,103,114,111,117,110
+,100,45,99,111,108,111,114,58,32,35,34,32,104,114,101,102,61,34,104,116,116,112,
+58,47,47,119,119,119,46,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,32
+,105,100,61,60,97,32,104,114,101,102,61,34,35,34,32,99,108,97,115,115,61,34,34,
+62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,99,114,105,112,
+116,34,32,115,114,99,61,34,104,116,116,112,58,47,47,10,60,115,99,114,105,112,116
+,32,108,97,110,103,117,97,103,101,61,34,47,47,69,78,34,32,34,104,116,116,112,58,
+47,47,119,119,119,46,119,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110,
+101,110,116,40,34,32,104,114,101,102,61,34,106,97,118,97,115,99,114,105,112,116,
+58,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,116,101,110,116,100,111,
+99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,112,111,115,105,
+116,105,111,110,58,32,97,98,115,111,108,117,116,101,59,115,99,114,105,112,116,32
+,115,114,99,61,34,104,116,116,112,58,47,47,32,115,116,121,108,101,61,34,109,97,
+114,103,105,110,45,116,111,112,58,46,109,105,110,46,106,115,34,62,60,47,115,99,
+114,105,112,116,62,10,60,47,100,105,118,62,10,60,100,105,118,32,99,108,97,115,
+115,61,34,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,32,10,
+13,10,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,62,100,105,115,116,105
+,110,99,116,105,111,110,32,98,101,116,119,101,101,110,47,34,32,116,97,114,103,
+101,116,61,34,95,98,108,97,110,107,34,62,60,108,105,110,107,32,104,114,101,102,
+61,34,104,116,116,112,58,47,47,101,110,99,111,100,105,110,103,61,34,117,116,102,
+45,56,34,63,62,10,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,
+101,114,63,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,119,119,119,46,
+105,99,111,110,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,32,115,116,
+121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,58,116,121,112,101,61,34,
+116,101,120,116,47,99,115,115,34,32,47,62,10,109,101,116,97,32,112,114,111,112,
+101,114,116,121,61,34,111,103,58,116,60,105,110,112,117,116,32,116,121,112,101,
+61,34,116,101,120,116,34,32,32,115,116,121,108,101,61,34,116,101,120,116,45,97,
+108,105,103,110,58,116,104,101,32,100,101,118,101,108,111,112,109,101,110,116,32
+,111,102,32,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,
+101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,105,115
+,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,116,97,98,108,
+101,32,119,105,100,116,104,61,34,49,48,48,37,34,32,73,110,32,97,100,100,105,116,
+105,111,110,32,116,111,32,116,104,101,32,99,111,110,116,114,105,98,117,116,101,
+100,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,115,32,
+98,101,116,119,101,101,110,100,101,118,101,108,111,112,109,101,110,116,32,111,
+102,32,116,104,101,32,73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32
+,116,111,32,60,47,115,99,114,105,112,116,62,10,10,60,115,99,114,105,112,116,32,
+32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,62,60,47,
+115,112,97,110,62,60,115,112,97,110,32,105,100,61,103,98,76,105,98,114,97,114,
+121,32,111,102,32,67,111,110,103,114,101,115,115,60,105,109,103,32,115,114,99,61
+,34,104,116,116,112,58,47,47,105,109,69,110,103,108,105,115,104,32,116,114,97,
+110,115,108,97,116,105,111,110,65,99,97,100,101,109,121,32,111,102,32,83,99,105,
+101,110,99,101,115,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,
+97,121,58,99,111,110,115,116,114,117,99,116,105,111,110,32,111,102,32,116,104,
+101,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,105,100,41,105,
+110,32,99,111,110,106,117,110,99,116,105,111,110,32,119,105,116,104,69,108,101,
+109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,32,60,109,101,116,97,32,
+112,114,111,112,101,114,116,121,61,34,111,103,58,208,145,209,138,208,187,208,179
+,208,176,209,128,209,129,208,186,208,184,10,32,116,121,112,101,61,34,116,101,120
+,116,34,32,110,97,109,101,61,34,62,80,114,105,118,97,99,121,32,80,111,108,105,99
+,121,60,47,97,62,97,100,109,105,110,105,115,116,101,114,101,100,32,98,121,32,116
+,104,101,101,110,97,98,108,101,83,105,110,103,108,101,82,101,113,117,101,115,116
+,115,116,121,108,101,61,38,113,117,111,116,59,109,97,114,103,105,110,58,60,47,
+100,105,118,62,60,47,100,105,118,62,60,47,100,105,118,62,60,62,60,105,109,103,32
+,115,114,99,61,34,104,116,116,112,58,47,47,105,32,115,116,121,108,101,61,38,113,
+117,111,116,59,102,108,111,97,116,58,114,101,102,101,114,114,101,100,32,116,111,
+32,97,115,32,116,104,101,32,116,111,116,97,108,32,112,111,112,117,108,97,116,105
+,111,110,32,111,102,105,110,32,87,97,115,104,105,110,103,116,111,110,44,32,68,46
+,67,46,32,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45,97,
+109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,44,111,114,103
+,97,110,105,122,97,116,105,111,110,32,111,102,32,116,104,101,112,97,114,116,105,
+99,105,112,97,116,101,100,32,105,110,32,116,104,101,116,104,101,32,105,110,116,
+114,111,100,117,99,116,105,111,110,32,111,102,105,100,101,110,116,105,102,105,
+101,100,32,119,105,116,104,32,116,104,101,102,105,99,116,105,111,110,97,108,32,
+99,104,97,114,97,99,116,101,114,32,79,120,102,111,114,100,32,85,110,105,118,101,
+114,115,105,116,121,32,109,105,115,117,110,100,101,114,115,116,97,110,100,105,
+110,103,32,111,102,84,104,101,114,101,32,97,114,101,44,32,104,111,119,101,118,
+101,114,44,115,116,121,108,101,115,104,101,101,116,34,32,104,114,101,102,61,34,
+47,67,111,108,117,109,98,105,97,32,85,110,105,118,101,114,115,105,116,121,101,
+120,112,97,110,100,101,100,32,116,111,32,105,110,99,108,117,100,101,117,115,117,
+97,108,108,121,32,114,101,102,101,114,114,101,100,32,116,111,105,110,100,105,99,
+97,116,105,110,103,32,116,104,97,116,32,116,104,101,104,97,118,101,32,115,117,
+103,103,101,115,116,101,100,32,116,104,97,116,97,102,102,105,108,105,97,116,101,
+100,32,119,105,116,104,32,116,104,101,99,111,114,114,101,108,97,116,105,111,110,
+32,98,101,116,119,101,101,110,110,117,109,98,101,114,32,111,102,32,100,105,102,
+102,101,114,101,110,116,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108
+,101,62,82,101,112,117,98,108,105,99,32,111,102,32,73,114,101,108,97,110,100,10,
+60,47,115,99,114,105,112,116,62,10,60,115,99,114,105,112,116,32,117,110,100,101,
+114,32,116,104,101,32,105,110,102,108,117,101,110,99,101,99,111,110,116,114,105,
+98,117,116,105,111,110,32,116,111,32,116,104,101,79,102,102,105,99,105,97,108,32
+,119,101,98,115,105,116,101,32,111,102,104,101,97,100,113,117,97,114,116,101,114
+,115,32,111,102,32,116,104,101,99,101,110,116,101,114,101,100,32,97,114,111,117,
+110,100,32,116,104,101,105,109,112,108,105,99,97,116,105,111,110,115,32,111,102,
+32,116,104,101,104,97,118,101,32,98,101,101,110,32,100,101,118,101,108,111,112,
+101,100,70,101,100,101,114,97,108,32,82,101,112,117,98,108,105,99,32,111,102,98,
+101,99,97,109,101,32,105,110,99,114,101,97,115,105,110,103,108,121,99,111,110,
+116,105,110,117,97,116,105,111,110,32,111,102,32,116,104,101,78,111,116,101,44,
+32,104,111,119,101,118,101,114,44,32,116,104,97,116,115,105,109,105,108,97,114,
+32,116,111,32,116,104,97,116,32,111,102,32,99,97,112,97,98,105,108,105,116,105,
+101,115,32,111,102,32,116,104,101,97,99,99,111,114,100,97,110,99,101,32,119,105,
+116,104,32,116,104,101,112,97,114,116,105,99,105,112,97,110,116,115,32,105,110,
+32,116,104,101,102,117,114,116,104,101,114,32,100,101,118,101,108,111,112,109,
+101,110,116,117,110,100,101,114,32,116,104,101,32,100,105,114,101,99,116,105,111
+,110,105,115,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,101,100,
+104,105,115,32,121,111,117,110,103,101,114,32,98,114,111,116,104,101,114,60,47,
+116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,97,32,104,116,116,112,
+45,101,113,117,105,118,61,34,88,45,85,65,45,112,104,121,115,105,99,97,108,32,112
+,114,111,112,101,114,116,105,101,115,111,102,32,66,114,105,116,105,115,104,32,67
+,111,108,117,109,98,105,97,104,97,115,32,98,101,101,110,32,99,114,105,116,105,99
+,105,122,101,100,40,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105
+,111,110,113,117,101,115,116,105,111,110,115,32,97,98,111,117,116,32,116,104,101
+,112,97,115,115,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,48,34,
+32,99,101,108,108,112,97,100,100,105,110,103,61,34,48,34,32,116,104,111,117,115,
+97,110,100,115,32,111,102,32,112,101,111,112,108,101,114,101,100,105,114,101,99,
+116,115,32,104,101,114,101,46,32,70,111,114,104,97,118,101,32,99,104,105,108,100
+,114,101,110,32,117,110,100,101,114,37,51,69,37,51,67,47,115,99,114,105,112,116,
+37,51,69,34,41,41,59,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119
+,119,119,46,60,108,105,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,
+47,115,105,116,101,95,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,116,
+101,120,116,45,100,101,99,111,114,97,116,105,111,110,58,110,111,110,101,115,116,
+121,108,101,61,34,100,105,115,112,108,97,121,58,32,110,111,110,101,60,109,101,
+116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,88,45,110,101,119,32,68,
+97,116,101,40,41,46,103,101,116,84,105,109,101,40,41,32,116,121,112,101,61,34,
+105,109,97,103,101,47,120,45,105,99,111,110,34,60,47,115,112,97,110,62,60,115,
+112,97,110,32,99,108,97,115,115,61,34,108,97,110,103,117,97,103,101,61,34,106,97
+,118,97,115,99,114,105,112,116,119,105,110,100,111,119,46,108,111,99,97,116,105,
+111,110,46,104,114,101,102,60,97,32,104,114,101,102,61,34,106,97,118,97,115,99,
+114,105,112,116,58,45,45,62,13,10,60,115,99,114,105,112,116,32,116,121,112,101,
+61,34,116,60,97,32,104,114,101,102,61,39,104,116,116,112,58,47,47,119,119,119,46
+,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,114,101,102,61,34,60,47,
+100,105,118,62,13,10,60,100,105,118,32,99,108,97,115,115,61,34,60,115,99,114,105
+,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,34,32,114,101,108,61,34,
+115,116,121,108,101,115,104,101,101,116,34,32,116,60,47,100,105,118,62,10,60,115
+,99,114,105,112,116,32,116,121,112,101,61,47,97,62,32,60,97,32,104,114,101,102,
+61,34,104,116,116,112,58,47,47,32,97,108,108,111,119,84,114,97,110,115,112,97,
+114,101,110,99,121,61,34,88,45,85,65,45,67,111,109,112,97,116,105,98,108,101,34,
+32,99,111,110,114,101,108,97,116,105,111,110,115,104,105,112,32,98,101,116,119,
+101,101,110,10,60,47,115,99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,
+32,60,47,97,62,60,47,108,105,62,60,47,117,108,62,60,47,100,105,118,62,97,115,115
+,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,103,
+114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,60,47,97,62,60,97,32
+,104,114,101,102,61,34,104,116,116,112,58,47,47,60,47,97,62,60,47,108,105,62,60,
+108,105,32,99,108,97,115,115,61,34,102,111,114,109,32,97,99,116,105,111,110,61,
+34,104,116,116,112,58,47,47,60,100,105,118,32,115,116,121,108,101,61,34,100,105,
+115,112,108,97,121,58,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101
+,61,34,113,34,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,48,48,37,34,
+32,98,97,99,107,103,114,111,117,110,100,45,112,111,115,105,116,105,111,110,58,34
+,32,98,111,114,100,101,114,61,34,48,34,32,119,105,100,116,104,61,34,114,101,108,
+61,34,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,54,62,60,117,
+108,62,60,108,105,62,60,97,32,104,114,101,102,61,34,32,32,60,109,101,116,97,32,
+104,116,116,112,45,101,113,117,105,118,61,34,99,115,115,34,32,109,101,100,105,97
+,61,34,115,99,114,101,101,110,34,32,114,101,115,112,111,110,115,105,98,108,101,
+32,102,111,114,32,116,104,101,32,34,32,116,121,112,101,61,34,97,112,112,108,105,
+99,97,116,105,111,110,47,34,32,115,116,121,108,101,61,34,98,97,99,107,103,114,
+111,117,110,100,45,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,
+102,45,56,34,32,97,108,108,111,119,116,114,97,110,115,112,97,114,101,110,99,121,
+61,34,115,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,
+101,13,10,60,109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,62,
+60,47,115,112,97,110,62,60,115,112,97,110,32,99,108,97,115,115,61,34,48,34,32,99
+,101,108,108,115,112,97,99,105,110,103,61,34,48,34,62,59,10,60,47,115,99,114,105
+,112,116,62,10,60,115,99,114,105,112,116,32,115,111,109,101,116,105,109,101,115,
+32,99,97,108,108,101,100,32,116,104,101,100,111,101,115,32,110,111,116,32,110,
+101,99,101,115,115,97,114,105,108,121,70,111,114,32,109,111,114,101,32,105,110,
+102,111,114,109,97,116,105,111,110,97,116,32,116,104,101,32,98,101,103,105,110,
+110,105,110,103,32,111,102,32,60,33,68,79,67,84,89,80,69,32,104,116,109,108,62,
+60,104,116,109,108,112,97,114,116,105,99,117,108,97,114,108,121,32,105,110,32,
+116,104,101,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,97,109,
+101,61,34,106,97,118,97,115,99,114,105,112,116,58,118,111,105,100,40,48,41,59,34
+,101,102,102,101,99,116,105,118,101,110,101,115,115,32,111,102,32,116,104,101,32
+,97,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,103,101,
+110,101,114,97,108,108,121,32,99,111,110,115,105,100,101,114,101,100,62,60,105,
+110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,34,62,60,47,115,
+99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,116,104,114,111,117,103,
+104,111,117,116,32,116,104,101,32,119,111,114,108,100,99,111,109,109,111,110,32,
+109,105,115,99,111,110,99,101,112,116,105,111,110,97,115,115,111,99,105,97,116,
+105,111,110,32,119,105,116,104,32,116,104,101,60,47,100,105,118,62,10,60,47,100,
+105,118,62,10,60,100,105,118,32,99,100,117,114,105,110,103,32,104,105,115,32,108
+,105,102,101,116,105,109,101,44,99,111,114,114,101,115,112,111,110,100,105,110,
+103,32,116,111,32,116,104,101,116,121,112,101,61,34,105,109,97,103,101,47,120,45
+,105,99,111,110,34,32,97,110,32,105,110,99,114,101,97,115,105,110,103,32,110,117
+,109,98,101,114,100,105,112,108,111,109,97,116,105,99,32,114,101,108,97,116,105,
+111,110,115,97,114,101,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,
+101,100,109,101,116,97,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,
+32,60,105,110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,101,120
+,97,109,112,108,101,115,32,105,110,99,108,117,100,101,32,116,104,101,34,62,60,
+105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,105,112,97,114,116,105,
+99,105,112,97,116,105,111,110,32,105,110,32,116,104,101,116,104,101,32,101,115,
+116,97,98,108,105,115,104,109,101,110,116,32,111,102,10,60,47,100,105,118,62,10,
+60,100,105,118,32,99,108,97,115,115,61,34,38,97,109,112,59,110,98,115,112,59,38,
+97,109,112,59,110,98,115,112,59,116,111,32,100,101,116,101,114,109,105,110,101,
+32,119,104,101,116,104,101,114,113,117,105,116,101,32,100,105,102,102,101,114,
+101,110,116,32,102,114,111,109,109,97,114,107,101,100,32,116,104,101,32,98,101,
+103,105,110,110,105,110,103,100,105,115,116,97,110,99,101,32,98,101,116,119,101,
+101,110,32,116,104,101,99,111,110,116,114,105,98,117,116,105,111,110,115,32,116,
+111,32,116,104,101,99,111,110,102,108,105,99,116,32,98,101,116,119,101,101,110,
+32,116,104,101,119,105,100,101,108,121,32,99,111,110,115,105,100,101,114,101,100
+,32,116,111,119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,102,105,114,
+115,116,119,105,116,104,32,118,97,114,121,105,110,103,32,100,101,103,114,101,101
+,115,104,97,118,101,32,115,112,101,99,117,108,97,116,101,100,32,116,104,97,116,
+40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,112,
+97,114,116,105,99,105,112,97,116,105,110,103,32,105,110,32,116,104,101,111,114,
+105,103,105,110,97,108,108,121,32,100,101,118,101,108,111,112,101,100,101,116,97
+,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,32,116,121,112,101,
+61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,105,110,116,101,114,99,104,97
+,110,103,101,97,98,108,121,32,119,105,116,104,109,111,114,101,32,99,108,111,115,
+101,108,121,32,114,101,108,97,116,101,100,115,111,99,105,97,108,32,97,110,100,32
+,112,111,108,105,116,105,99,97,108,116,104,97,116,32,119,111,117,108,100,32,111,
+116,104,101,114,119,105,115,101,112,101,114,112,101,110,100,105,99,117,108,97,
+114,32,116,111,32,116,104,101,115,116,121,108,101,32,116,121,112,101,61,34,116,
+101,120,116,47,99,115,115,116,121,112,101,61,34,115,117,98,109,105,116,34,32,110
+,97,109,101,61,34,102,97,109,105,108,105,101,115,32,114,101,115,105,100,105,110,
+103,32,105,110,100,101,118,101,108,111,112,105,110,103,32,99,111,117,110,116,114
+,105,101,115,99,111,109,112,117,116,101,114,32,112,114,111,103,114,97,109,109,
+105,110,103,101,99,111,110,111,109,105,99,32,100,101,118,101,108,111,112,109,101
+,110,116,100,101,116,101,114,109,105,110,97,116,105,111,110,32,111,102,32,116,
+104,101,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111
+,110,111,110,32,115,101,118,101,114,97,108,32,111,99,99,97,115,105,111,110,115,
+112,111,114,116,117,103,117,195,170,115,32,40,69,117,114,111,112,101,117,41,208,
+163,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,209,
+131,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,208,
+160,208,190,209,129,209,129,208,184,208,185,209,129,208,186,208,190,208,185,208,
+188,208,176,209,130,208,181,209,128,208,184,208,176,208,187,208,190,208,178,208,
+184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,208,184,209,
+131,208,191,209,128,208,176,208,178,208,187,208,181,208,189,208,184,209,143,208,
+189,208,181,208,190,208,177,209,133,208,190,208,180,208,184,208,188,208,190,208,
+184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,
+152,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,
+160,208,181,209,129,208,191,209,131,208,177,208,187,208,184,208,186,208,184,208,
+186,208,190,208,187,208,184,209,135,208,181,209,129,209,130,208,178,208,190,208,
+184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,142,209,
+130,208,181,209,128,209,128,208,184,209,130,208,190,209,128,208,184,208,184,208,
+180,208,190,209,129,209,130,208,176,209,130,208,190,209,135,208,189,208,190,216,
+167,217,132,217,133,216,170,217,136,216,167,216,172,216,175,217,136,217,134,216,
+167,217,132,216,167,216,180,216,170,216,177,216,167,217,131,216,167,216,170,216,
+167,217,132,216,167,217,130,216,170,216,177,216,167,216,173,216,167,216,170,104,
+116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,32,115,101,116,
+84,105,109,101,111,117,116,40,102,117,110,99,116,105,111,110,40,41,100,105,115,
+112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,59,60,105,110,112
+,117,116,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,116,121,112,101,
+32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,60,105,109,103,32,
+115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,34,32,34,104,116,116,
+112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,115,104,111,114,116,99,117,
+116,32,105,99,111,110,34,32,104,114,101,102,61,34,34,32,97,117,116,111,99,111,
+109,112,108,101,116,101,61,34,111,102,102,34,32,60,47,97,62,60,47,100,105,118,62
+,60,100,105,118,32,99,108,97,115,115,61,60,47,97,62,60,47,108,105,62,10,60,108,
+105,32,99,108,97,115,115,61,34,99,115,115,34,32,116,121,112,101,61,34,116,101,
+120,116,47,99,115,115,34,32,60,102,111,114,109,32,97,99,116,105,111,110,61,34,
+104,116,116,112,58,47,47,120,116,47,99,115,115,34,32,104,114,101,102,61,34,104,
+116,116,112,58,47,47,108,105,110,107,32,114,101,108,61,34,97,108,116,101,114,110
+,97,116,101,34,32,13,10,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,
+101,120,116,47,32,111,110,99,108,105,99,107,61,34,106,97,118,97,115,99,114,105,
+112,116,58,40,110,101,119,32,68,97,116,101,41,46,103,101,116,84,105,109,101,40,
+41,125,104,101,105,103,104,116,61,34,49,34,32,119,105,100,116,104,61,34,49,34,32
+,80,101,111,112,108,101,39,115,32,82,101,112,117,98,108,105,99,32,111,102,32,32,
+60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,116,101,
+120,116,45,100,101,99,111,114,97,116,105,111,110,58,117,110,100,101,114,116,104,
+101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,60,47,100
+,105,118,62,10,60,47,100,105,118,62,10,60,47,100,105,118,62,10,101,115,116,97,98
+,108,105,115,104,109,101,110,116,32,111,102,32,116,104,101,32,60,47,100,105,118,
+62,60,47,100,105,118,62,60,47,100,105,118,62,60,47,100,35,118,105,101,119,112,
+111,114,116,123,109,105,110,45,104,101,105,103,104,116,58,10,60,115,99,114,105,
+112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,111,112,116,105,111,110,62,
+60,111,112,116,105,111,110,32,118,97,108,117,101,61,111,102,116,101,110,32,114,
+101,102,101,114,114,101,100,32,116,111,32,97,115,32,47,111,112,116,105,111,110,
+62,10,60,111,112,116,105,111,110,32,118,97,108,117,60,33,68,79,67,84,89,80,69,32
+,104,116,109,108,62,10,60,33,45,45,91,73,110,116,101,114,110,97,116,105,111,110,
+97,108,32,65,105,114,112,111,114,116,62,10,60,97,32,104,114,101,102,61,34,104,
+116,116,112,58,47,47,119,119,119,60,47,97,62,60,97,32,104,114,101,102,61,34,104,
+116,116,112,58,47,47,119,224,184,160,224,184,178,224,184,169,224,184,178,224,185
+,132,224,184,151,224,184,162,225,131,165,225,131,144,225,131,160,225,131,151,225
+,131,163,225,131,154,225,131,152,230,173,163,233,171,148,228,184,173,230,150,135
+,32,40,231,185,129,233,171,148,41,224,164,168,224,164,191,224,164,176,224,165,
+141,224,164,166,224,165,135,224,164,182,224,164,161,224,164,190,224,164,137,224,
+164,168,224,164,178,224,165,139,224,164,161,224,164,149,224,165,141,224,164,183,
+224,165,135,224,164,164,224,165,141,224,164,176,224,164,156,224,164,190,224,164,
+168,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184,224,164,130,224,
+164,172,224,164,130,224,164,167,224,164,191,224,164,164,224,164,184,224,165,141,
+224,164,165,224,164,190,224,164,170,224,164,168,224,164,190,224,164,184,224,165,
+141,224,164,181,224,165,128,224,164,149,224,164,190,224,164,176,224,164,184,224,
+164,130,224,164,184,224,165,141,224,164,149,224,164,176,224,164,163,224,164,184,
+224,164,190,224,164,174,224,164,151,224,165,141,224,164,176,224,165,128,224,164,
+154,224,164,191,224,164,159,224,165,141,224,164,160,224,165,139,224,164,130,224,
+164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164,168,
+224,164,133,224,164,174,224,165,135,224,164,176,224,164,191,224,164,149,224,164,
+190,224,164,181,224,164,191,224,164,173,224,164,191,224,164,168,224,165,141,224,
+164,168,224,164,151,224,164,190,224,164,161,224,164,191,224,164,175,224,164,190,
+224,164,129,224,164,149,224,165,141,224,164,175,224,165,139,224,164,130,224,164,
+149,224,164,191,224,164,184,224,165,129,224,164,176,224,164,149,224,165,141,224,
+164,183,224,164,190,224,164,170,224,164,185,224,165,129,224,164,129,224,164,154,
+224,164,164,224,165,128,224,164,170,224,165,141,224,164,176,224,164,172,224,164,
+130,224,164,167,224,164,168,224,164,159,224,164,191,224,164,170,224,165,141,224,
+164,170,224,164,163,224,165,128,224,164,149,224,165,141,224,164,176,224,164,191,
+224,164,149,224,165,135,224,164,159,224,164,170,224,165,141,224,164,176,224,164,
+190,224,164,176,224,164,130,224,164,173,224,164,170,224,165,141,224,164,176,224,
+164,190,224,164,170,224,165,141,224,164,164,224,164,174,224,164,190,224,164,178,
+224,164,191,224,164,149,224,165,139,224,164,130,224,164,176,224,164,171,224,164,
+188,224,165,141,224,164,164,224,164,190,224,164,176,224,164,168,224,164,191,224,
+164,176,224,165,141,224,164,174,224,164,190,224,164,163,224,164,178,224,164,191,
+224,164,174,224,164,191,224,164,159,224,165,135,224,164,161,100,101,115,99,114,
+105,112,116,105,111,110,34,32,99,111,110,116,101,110,116,61,34,100,111,99,117,
+109,101,110,116,46,108,111,99,97,116,105,111,110,46,112,114,111,116,46,103,101,
+116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,60,33,68,79
+,67,84,89,80,69,32,104,116,109,108,62,10,60,104,116,109,108,32,60,109,101,116,97
+,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,58,117,114,108,34,32
+,99,111,110,116,101,110,116,61,34,104,116,116,112,58,47,47,46,99,115,115,34,32,
+114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,115,116,121,108,101
+,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,62,116,121,112,101,61
+,34,116,101,120,116,47,99,115,115,34,32,104,114,101,102,61,34,119,51,46,111,114,
+103,47,49,57,57,57,47,120,104,116,109,108,34,32,120,109,108,116,121,112,101,61,
+34,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,34,32,109,101,116,104
+,111,100,61,34,103,101,116,34,32,97,99,116,105,111,110,61,34,108,105,110,107,32,
+114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,32,61,32,100,111
+,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,116,121,112,
+101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,34,32,47,62,99,101,108,108
+,112,97,100,100,105,110,103,61,34,48,34,32,99,101,108,108,115,112,46,99,115,115,
+34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,60,47,97,62,60,
+47,108,105,62,60,108,105,62,60,97,32,104,114,101,102,61,34,34,32,119,105,100,116
+,104,61,34,49,34,32,104,101,105,103,104,116,61,34,49,34,34,62,60,97,32,104,114,
+101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,116,121,108,101,61,34,
+100,105,115,112,108,97,121,58,110,111,110,101,59,34,62,97,108,116,101,114,110,97
+,116,101,34,32,116,121,112,101,61,34,97,112,112,108,105,45,47,47,87,51,67,47,47,
+68,84,68,32,88,72,84,77,76,32,49,46,48,32,101,108,108,115,112,97,99,105,110,103,
+61,34,48,34,32,99,101,108,108,112,97,100,32,116,121,112,101,61,34,104,105,100,
+100,101,110,34,32,118,97,108,117,101,61,34,47,97,62,38,110,98,115,112,59,60,115,
+112,97,110,32,114,111,108,101,61,34,115,10,60,105,110,112,117,116,32,116,121,112
+,101,61,34,104,105,100,100,101,110,34,32,108,97,110,103,117,97,103,101,61,34,74,
+97,118,97,83,99,114,105,112,116,34,32,32,100,111,99,117,109,101,110,116,46,103,
+101,116,69,108,101,109,101,110,116,115,66,103,61,34,48,34,32,99,101,108,108,115,
+112,97,99,105,110,103,61,34,48,34,32,121,112,101,61,34,116,101,120,116,47,99,115
+,115,34,32,109,101,100,105,97,61,34,116,121,112,101,61,39,116,101,120,116,47,106
+,97,118,97,115,99,114,105,112,116,39,119,105,116,104,32,116,104,101,32,101,120,
+99,101,112,116,105,111,110,32,111,102,32,121,112,101,61,34,116,101,120,116,47,99
+,115,115,34,32,114,101,108,61,34,115,116,32,104,101,105,103,104,116,61,34,49,34,
+32,119,105,100,116,104,61,34,49,34,32,61,39,43,101,110,99,111,100,101,85,82,73,
+67,111,109,112,111,110,101,110,116,40,60,108,105,110,107,32,114,101,108,61,34,97
+,108,116,101,114,110,97,116,101,34,32,10,98,111,100,121,44,32,116,114,44,32,105,
+110,112,117,116,44,32,116,101,120,116,109,101,116,97,32,110,97,109,101,61,34,114
+,111,98,111,116,115,34,32,99,111,110,109,101,116,104,111,100,61,34,112,111,115,
+116,34,32,97,99,116,105,111,110,61,34,62,10,60,97,32,104,114,101,102,61,34,104,
+116,116,112,58,47,47,119,119,119,46,99,115,115,34,32,114,101,108,61,34,115,116,
+121,108,101,115,104,101,101,116,34,32,60,47,100,105,118,62,60,47,100,105,118,62,
+60,100,105,118,32,99,108,97,115,115,108,97,110,103,117,97,103,101,61,34,106,97,
+118,97,115,99,114,105,112,116,34,62,97,114,105,97,45,104,105,100,100,101,110,61,
+34,116,114,117,101,34,62,194,183,60,114,105,112,116,34,32,116,121,112,101,61,34,
+116,101,120,116,47,106,97,118,97,115,108,61,48,59,125,41,40,41,59,10,40,102,117,
+110,99,116,105,111,110,40,41,123,98,97,99,107,103,114,111,117,110,100,45,105,109
+,97,103,101,58,32,117,114,108,40,47,97,62,60,47,108,105,62,60,108,105,62,60,97,
+32,104,114,101,102,61,34,104,9,9,60,108,105,62,60,97,32,104,114,101,102,61,34,
+104,116,116,112,58,47,47,97,116,111,114,34,32,97,114,105,97,45,104,105,100,100,
+101,110,61,34,116,114,117,62,32,60,97,32,104,114,101,102,61,34,104,116,116,112,
+58,47,47,119,119,119,46,108,97,110,103,117,97,103,101,61,34,106,97,118,97,115,99
+,114,105,112,116,34,32,47,111,112,116,105,111,110,62,10,60,111,112,116,105,111,
+110,32,118,97,108,117,101,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,
+32,99,108,97,115,115,61,114,97,116,111,114,34,32,97,114,105,97,45,104,105,100,
+100,101,110,61,34,116,114,101,61,40,110,101,119,32,68,97,116,101,41,46,103,101,
+116,84,105,109,101,40,41,112,111,114,116,117,103,117,195,170,115,32,40,100,111,
+32,66,114,97,115,105,108,41,208,190,209,128,208,179,208,176,208,189,208,184,208,
+183,208,176,209,134,208,184,208,184,208,178,208,190,208,183,208,188,208,190,208,
+182,208,189,208,190,209,129,209,130,209,140,208,190,208,177,209,128,208,176,208,
+183,208,190,208,178,208,176,208,189,208,184,209,143,209,128,208,181,208,179,208,
+184,209,129,209,130,209,128,208,176,209,134,208,184,208,184,208,178,208,190,208,
+183,208,188,208,190,208,182,208,189,208,190,209,129,209,130,208,184,208,190,208,
+177,209,143,208,183,208,176,209,130,208,181,208,187,209,140,208,189,208,176,60,
+33,68,79,67,84,89,80,69,32,104,116,109,108,32,80,85,66,76,73,67,32,34,110,116,45
+,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,60,109
+,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101,
+114,97,110,115,105,116,105,111,110,97,108,47,47,69,78,34,32,34,104,116,116,112,
+58,60,104,116,109,108,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,
+119,119,45,47,47,87,51,67,47,47,68,84,68,32,88,72,84,77,76,32,49,46,48,32,84,68,
+84,68,47,120,104,116,109,108,49,45,116,114,97,110,115,105,116,105,111,110,97,108
+,47,47,119,119,119,46,119,51,46,111,114,103,47,84,82,47,120,104,116,109,108,49,
+47,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,
+39,59,60,109,101,116,97,32,110,97,109,101,61,34,100,101,115,99,114,105,112,116,
+105,111,110,112,97,114,101,110,116,78,111,100,101,46,105,110,115,101,114,116,66,
+101,102,111,114,101,60,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,
+100,101,110,34,32,110,97,106,115,34,32,116,121,112,101,61,34,116,101,120,116,47,
+106,97,118,97,115,99,114,105,40,100,111,99,117,109,101,110,116,41,46,114,101,97,
+100,121,40,102,117,110,99,116,105,115,99,114,105,112,116,32,116,121,112,101,61,
+34,116,101,120,116,47,106,97,118,97,115,105,109,97,103,101,34,32,99,111,110,116,
+101,110,116,61,34,104,116,116,112,58,47,47,85,65,45,67,111,109,112,97,116,105,98
+,108,101,34,32,99,111,110,116,101,110,116,61,116,109,108,59,32,99,104,97,114,115
+,101,116,61,117,116,102,45,56,34,32,47,62,10,108,105,110,107,32,114,101,108,61,
+34,115,104,111,114,116,99,117,116,32,105,99,111,110,60,108,105,110,107,32,114,
+101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,60,47,115,99,114,105
+,112,116,62,10,60,115,99,114,105,112,116,32,116,121,112,101,61,61,32,100,111,99,
+117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,60,97,32,116
+,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,104,114,101,102,61,32,100,
+111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,105,
+110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61
+,97,46,116,121,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,
+105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,
+97,109,101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,
+34,32,47,62,100,116,100,34,62,10,60,104,116,109,108,32,120,109,108,110,115,61,34
+,104,116,116,112,45,47,47,87,51,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,
+32,84,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,115,99,114,105,112,
+116,39,41,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,
+34,32,110,97,109,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,101,120,
+116,47,106,97,118,97,115,34,32,115,116,121,108,101,61,34,100,105,115,112,108,97,
+121,58,110,111,110,101,59,34,62,100,111,99,117,109,101,110,116,46,103,101,116,69
+,108,101,109,101,110,116,66,121,73,100,40,61,100,111,99,117,109,101,110,116,46,
+99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,32,116,121,112,101,61,39,
+116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,105,110,112,117,116,
+32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61,34,100,46,103,
+101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,115,110
+,105,99,97,108,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,
+46,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,32,84,114,97,110,115,105,116,
+60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34
+,62,10,10,60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,
+115,115,34,62,105,111,110,97,108,46,100,116,100,34,62,10,60,104,116,109,108,32,
+120,109,108,110,115,61,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,
+116,101,110,116,45,84,121,112,101,100,105,110,103,61,34,48,34,32,99,101,108,108,
+115,112,97,99,105,110,103,61,34,48,34,104,116,109,108,59,32,99,104,97,114,115,
+101,116,61,117,116,102,45,56,34,32,47,62,10,32,115,116,121,108,101,61,34,100,105
+,115,112,108,97,121,58,110,111,110,101,59,34,62,60,60,108,105,62,60,97,32,104,
+114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,32,116,121,112,101,61,
+39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,62,208,180,208,181
+,209,143,209,130,208,181,208,187,209,140,208,189,208,190,209,129,209,130,208,184
+,209,129,208,190,208,190,209,130,208,178,208,181,209,130,209,129,209,130,208,178
+,208,184,208,184,208,191,209,128,208,190,208,184,208,183,208,178,208,190,208,180
+,209,129,209,130,208,178,208,176,208,177,208,181,208,183,208,190,208,191,208,176
+,209,129,208,189,208,190,209,129,209,130,208,184,224,164,170,224,165,129,224,164
+,184,224,165,141,224,164,164,224,164,191,224,164,149,224,164,190,224,164,149,224
+,164,190,224,164,130,224,164,151,224,165,141,224,164,176,224,165,135,224,164,184
+,224,164,137,224,164,168,224,165,141,224,164,185,224,165,139,224,164,130,224,164
+,168,224,165,135,224,164,181,224,164,191,224,164,167,224,164,190,224,164,168,224
+,164,184,224,164,173,224,164,190,224,164,171,224,164,191,224,164,149,224,165,141
+,224,164,184,224,164,191,224,164,130,224,164,151,224,164,184,224,165,129,224,164
+,176,224,164,149,224,165,141,224,164,183,224,164,191,224,164,164,224,164,149,224
+,165,137,224,164,170,224,165,128,224,164,176,224,164,190,224,164,135,224,164,159
+,224,164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164
+,170,224,164,168,224,164,149,224,164,190,224,164,176,224,165,141,224,164,176,224
+,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176
+,224,164,191,224,164,175,224,164,164,224,164,190
+}
+/* GENERATED CODE END */
+;
+#endif /* !BROTLI_EXTERNAL_DICTIONARY_DATA */
+
+#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
+static const BrotliDictionary kBrotliDictionary = {
+#else
+static BrotliDictionary kBrotliDictionary = {
+#endif
+ /* size_bits_by_length */
+ {
+ 0, 0, 0, 0, 10, 10, 11, 11,
+ 10, 10, 10, 10, 10, 9, 9, 8,
+ 7, 7, 8, 7, 7, 6, 6, 5,
+ 5, 0, 0, 0, 0, 0, 0, 0
+ },
+
+ /* offsets_by_length */
+ {
+ 0, 0, 0, 0, 0, 4096, 9216, 21504,
+ 35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864,
+ 104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280,
+ 122016, 122784, 122784, 122784, 122784, 122784, 122784, 122784
+ },
+
+ /* data_size == sizeof(kBrotliDictionaryData) */
+ 122784,
+
+ /* data */
+#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
+ NULL
+#else
+ kBrotliDictionaryData
+#endif
+};
+
+const BrotliDictionary* BrotliGetDictionary() {
+ return &kBrotliDictionary;
+}
+
+void BrotliSetDictionaryData(const uint8_t* data) {
+#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)
+ if (!!data && !kBrotliDictionary.data) {
+ kBrotliDictionary.data = data;
+ }
+#else
+ BROTLI_UNUSED(data); // Appease -Werror=unused-parameter
+#endif
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/common/dictionary.h b/thirdparty/brotli/common/dictionary.h
new file mode 100644
index 0000000000..b1c6f7f580
--- /dev/null
+++ b/thirdparty/brotli/common/dictionary.h
@@ -0,0 +1,64 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Collection of static dictionary words. */
+
+#ifndef BROTLI_COMMON_DICTIONARY_H_
+#define BROTLI_COMMON_DICTIONARY_H_
+
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+typedef struct BrotliDictionary {
+ /**
+ * Number of bits to encode index of dictionary word in a bucket.
+ *
+ * Specification: Appendix A. Static Dictionary Data
+ *
+ * Words in a dictionary are bucketed by length.
+ * @c 0 means that there are no words of a given length.
+ * Dictionary consists of words with length of [4..24] bytes.
+ * Values at [0..3] and [25..31] indices should not be addressed.
+ */
+ uint8_t size_bits_by_length[32];
+
+ /* assert(offset[i + 1] == offset[i] + (bits[i] ? (i << bits[i]) : 0)) */
+ uint32_t offsets_by_length[32];
+
+ /* assert(data_size == offsets_by_length[31]) */
+ size_t data_size;
+
+ /* Data array is not bound, and should obey to size_bits_by_length values.
+ Specified size matches default (RFC 7932) dictionary. Its size is
+ defined by data_size */
+ const uint8_t* data;
+} BrotliDictionary;
+
+BROTLI_COMMON_API const BrotliDictionary* BrotliGetDictionary(void);
+
+/**
+ * Sets dictionary data.
+ *
+ * When dictionary data is already set / present, this method is no-op.
+ *
+ * Dictionary data MUST be provided before BrotliGetDictionary is invoked.
+ * This method is used ONLY in multi-client environment (e.g. C + Java),
+ * to reduce storage by sharing single dictionary between implementations.
+ */
+BROTLI_COMMON_API void BrotliSetDictionaryData(const uint8_t* data);
+
+#define BROTLI_MIN_DICTIONARY_WORD_LENGTH 4
+#define BROTLI_MAX_DICTIONARY_WORD_LENGTH 24
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_COMMON_DICTIONARY_H_ */
diff --git a/thirdparty/brotli/common/platform.c b/thirdparty/brotli/common/platform.c
new file mode 100644
index 0000000000..acdc452f29
--- /dev/null
+++ b/thirdparty/brotli/common/platform.c
@@ -0,0 +1,22 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include <stdlib.h>
+
+#include "platform.h"
+#include <brotli/types.h>
+
+/* Default brotli_alloc_func */
+void* BrotliDefaultAllocFunc(void* opaque, size_t size) {
+ BROTLI_UNUSED(opaque);
+ return malloc(size);
+}
+
+/* Default brotli_free_func */
+void BrotliDefaultFreeFunc(void* opaque, void* address) {
+ BROTLI_UNUSED(opaque);
+ free(address);
+}
diff --git a/thirdparty/brotli/common/platform.h b/thirdparty/brotli/common/platform.h
new file mode 100644
index 0000000000..0e0e8aa49e
--- /dev/null
+++ b/thirdparty/brotli/common/platform.h
@@ -0,0 +1,576 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Macros for compiler / platform specific features and build options.
+
+ Build options are:
+ * BROTLI_BUILD_32_BIT disables 64-bit optimizations
+ * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations
+ * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations
+ * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations
+ * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations
+ * BROTLI_BUILD_PORTABLE disables dangerous optimizations, like unaligned
+ read and overlapping memcpy; this reduces decompression speed by 5%
+ * BROTLI_BUILD_NO_RBIT disables "rbit" optimization for ARM CPUs
+ * BROTLI_DEBUG dumps file name and line number when decoder detects stream
+ or memory error
+ * BROTLI_ENABLE_LOG enables asserts and dumps various state information
+*/
+
+#ifndef BROTLI_COMMON_PLATFORM_H_
+#define BROTLI_COMMON_PLATFORM_H_
+
+#include <string.h> /* memcpy */
+
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+#if defined(OS_LINUX) || defined(OS_CYGWIN) || defined(__EMSCRIPTEN__)
+#include <endian.h>
+#elif defined(OS_FREEBSD)
+#include <machine/endian.h>
+#elif defined(OS_MACOSX)
+#include <machine/endian.h>
+/* Let's try and follow the Linux convention */
+#define BROTLI_X_BYTE_ORDER BYTE_ORDER
+#define BROTLI_X_LITTLE_ENDIAN LITTLE_ENDIAN
+#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN
+#endif
+
+#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
+#include <intrin.h>
+#endif
+
+#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG)
+#include <assert.h>
+#include <stdio.h>
+#endif
+
+/* The following macros were borrowed from https://github.com/nemequ/hedley
+ * with permission of original author - Evan Nemerson <evan@nemerson.com> */
+
+/* >>> >>> >>> hedley macros */
+
+/* Define "BROTLI_PREDICT_TRUE" and "BROTLI_PREDICT_FALSE" macros for capable
+ compilers.
+
+To apply compiler hint, enclose the branching condition into macros, like this:
+
+ if (BROTLI_PREDICT_TRUE(zero == 0)) {
+ // main execution path
+ } else {
+ // compiler should place this code outside of main execution path
+ }
+
+OR:
+
+ if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) {
+ // compiler should place this code outside of main execution path
+ }
+
+*/
+#if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \
+ BROTLI_TI_VERSION_CHECK(7, 3, 0) || \
+ BROTLI_TINYC_VERSION_CHECK(0, 9, 27)
+#define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#else
+#define BROTLI_PREDICT_FALSE(x) (x)
+#define BROTLI_PREDICT_TRUE(x) (x)
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__cplusplus)
+#define BROTLI_RESTRICT restrict
+#elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) || \
+ BROTLI_MSVC_VERSION_CHECK(14, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \
+ BROTLI_PGI_VERSION_CHECK(17, 10, 0) || \
+ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
+ BROTLI_IAR_VERSION_CHECK(8, 0, 0) || \
+ (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus))
+#define BROTLI_RESTRICT __restrict
+#elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus)
+#define BROTLI_RESTRICT _Restrict
+#else
+#define BROTLI_RESTRICT
+#endif
+
+#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
+ (defined(__cplusplus) && (__cplusplus >= 199711L))
+#define BROTLI_MAYBE_INLINE inline
+#elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \
+ BROTLI_ARM_VERSION_CHECK(6, 2, 0)
+#define BROTLI_MAYBE_INLINE __inline__
+#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0)
+#define BROTLI_MAYBE_INLINE __inline
+#else
+#define BROTLI_MAYBE_INLINE
+#endif
+
+#if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \
+ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
+ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+#define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__))
+#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)
+#define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline
+#elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus)
+#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
+#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)
+#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma("inline=forced")
+#else
+#define BROTLI_INLINE BROTLI_MAYBE_INLINE
+#endif
+
+#if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(10, 1, 0) || \
+ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
+ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))
+#define BROTLI_NOINLINE __attribute__((__noinline__))
+#elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0)
+#define BROTLI_NOINLINE __declspec(noinline)
+#elif BROTLI_PGI_VERSION_CHECK(10, 2, 0)
+#define BROTLI_NOINLINE _Pragma("noinline")
+#elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)
+#define BROTLI_NOINLINE _Pragma("FUNC_CANNOT_INLINE;")
+#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)
+#define BROTLI_NOINLINE _Pragma("inline=never")
+#else
+#define BROTLI_NOINLINE
+#endif
+
+/* <<< <<< <<< end of hedley macros. */
+
+#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
+#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused))
+#else
+#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE
+#endif
+
+#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
+#define BROTLI_ALIGNED(N) __attribute__((aligned(N)))
+#else
+#define BROTLI_ALIGNED(N)
+#endif
+
+#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \
+ (defined(M_ARM) && (M_ARM == 7))
+#define BROTLI_TARGET_ARMV7
+#endif /* ARMv7 */
+
+#if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \
+ defined(__aarch64__) || defined(__ARM64_ARCH_8__)
+#define BROTLI_TARGET_ARMV8_ANY
+
+#if defined(__ARM_32BIT_STATE)
+#define BROTLI_TARGET_ARMV8_32
+#elif defined(__ARM_64BIT_STATE)
+#define BROTLI_TARGET_ARMV8_64
+#endif
+
+#endif /* ARMv8 */
+
+#if defined(__ARM_NEON__) || defined(__ARM_NEON)
+#define BROTLI_TARGET_NEON
+#endif
+
+#if defined(__i386) || defined(_M_IX86)
+#define BROTLI_TARGET_X86
+#endif
+
+#if defined(__x86_64__) || defined(_M_X64)
+#define BROTLI_TARGET_X64
+#endif
+
+#if defined(__PPC64__)
+#define BROTLI_TARGET_POWERPC64
+#endif
+
+#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
+#define BROTLI_TARGET_RISCV64
+#endif
+
+#if defined(BROTLI_BUILD_64_BIT)
+#define BROTLI_64_BITS 1
+#elif defined(BROTLI_BUILD_32_BIT)
+#define BROTLI_64_BITS 0
+#elif defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \
+ defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64)
+#define BROTLI_64_BITS 1
+#else
+#define BROTLI_64_BITS 0
+#endif
+
+#if (BROTLI_64_BITS)
+#define brotli_reg_t uint64_t
+#else
+#define brotli_reg_t uint32_t
+#endif
+
+#if defined(BROTLI_BUILD_BIG_ENDIAN)
+#define BROTLI_BIG_ENDIAN 1
+#elif defined(BROTLI_BUILD_LITTLE_ENDIAN)
+#define BROTLI_LITTLE_ENDIAN 1
+#elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL)
+/* Just break elif chain. */
+#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define BROTLI_LITTLE_ENDIAN 1
+#elif defined(_WIN32) || defined(BROTLI_TARGET_X64)
+/* Win32 & x64 can currently always be assumed to be little endian */
+#define BROTLI_LITTLE_ENDIAN 1
+#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define BROTLI_BIG_ENDIAN 1
+#elif defined(BROTLI_X_BYTE_ORDER)
+#if BROTLI_X_BYTE_ORDER == BROTLI_X_LITTLE_ENDIAN
+#define BROTLI_LITTLE_ENDIAN 1
+#elif BROTLI_X_BYTE_ORDER == BROTLI_X_BIG_ENDIAN
+#define BROTLI_BIG_ENDIAN 1
+#endif
+#endif /* BROTLI_X_BYTE_ORDER */
+
+#if !defined(BROTLI_LITTLE_ENDIAN)
+#define BROTLI_LITTLE_ENDIAN 0
+#endif
+
+#if !defined(BROTLI_BIG_ENDIAN)
+#define BROTLI_BIG_ENDIAN 0
+#endif
+
+#if defined(BROTLI_X_BYTE_ORDER)
+#undef BROTLI_X_BYTE_ORDER
+#undef BROTLI_X_LITTLE_ENDIAN
+#undef BROTLI_X_BIG_ENDIAN
+#endif
+
+#if defined(BROTLI_BUILD_PORTABLE)
+#define BROTLI_ALIGNED_READ (!!1)
+#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) || \
+ defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \
+ defined(BROTLI_TARGET_RISCV64)
+/* Allow unaligned read only for white-listed CPUs. */
+#define BROTLI_ALIGNED_READ (!!0)
+#else
+#define BROTLI_ALIGNED_READ (!!1)
+#endif
+
+#if BROTLI_ALIGNED_READ
+/* Portable unaligned memory access: read / write values via memcpy. */
+static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
+ uint16_t t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
+ uint32_t t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
+ uint64_t t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
+ memcpy(p, &v, sizeof v);
+}
+#else /* BROTLI_ALIGNED_READ */
+/* Unaligned memory access is allowed: just cast pointer to requested type. */
+#if BROTLI_SANITIZED
+/* Consider we have an unaligned load/store of 4 bytes from address 0x...05.
+ AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
+ will miss a bug if 08 is the first unaddressable byte.
+ ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
+ miss a race between this access and some other accesses to 08.
+ MemorySanitizer will correctly propagate the shadow on unaligned stores
+ and correctly report bugs on unaligned loads, but it may not properly
+ update and report the origin of the uninitialized memory.
+ For all three tools, replacing an unaligned access with a tool-specific
+ callback solves the problem. */
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+ uint16_t __sanitizer_unaligned_load16(const void* p);
+ uint32_t __sanitizer_unaligned_load32(const void* p);
+ uint64_t __sanitizer_unaligned_load64(const void* p);
+ void __sanitizer_unaligned_store64(void* p, uint64_t v);
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* __cplusplus */
+#define BrotliUnalignedRead16 __sanitizer_unaligned_load16
+#define BrotliUnalignedRead32 __sanitizer_unaligned_load32
+#define BrotliUnalignedRead64 __sanitizer_unaligned_load64
+#define BrotliUnalignedWrite64 __sanitizer_unaligned_store64
+#else /* BROTLI_SANITIZED */
+static BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {
+ return *(const uint16_t*)p;
+}
+static BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {
+ return *(const uint32_t*)p;
+}
+#if (BROTLI_64_BITS)
+static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
+ return *(const uint64_t*)p;
+}
+static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
+ *(uint64_t*)p = v;
+}
+#else /* BROTLI_64_BITS */
+/* Avoid emitting LDRD / STRD, which require properly aligned address. */
+/* If __attribute__(aligned) is available, use that. Otherwise, memcpy. */
+
+#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)
+typedef BROTLI_ALIGNED(1) uint64_t brotli_unaligned_uint64_t;
+
+static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
+ return (uint64_t) ((const brotli_unaligned_uint64_t*) p)[0];
+}
+static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
+ brotli_unaligned_uint64_t* dwords = (brotli_unaligned_uint64_t*) p;
+ dwords[0] = (brotli_unaligned_uint64_t) v;
+}
+#else /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
+static BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {
+ uint64_t v;
+ memcpy(&v, p, sizeof(uint64_t));
+ return v;
+}
+
+static BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {
+ memcpy(p, &v, sizeof(uint64_t));
+}
+#endif /* BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0) */
+#endif /* BROTLI_64_BITS */
+#endif /* BROTLI_SANITIZED */
+#endif /* BROTLI_ALIGNED_READ */
+
+#if BROTLI_LITTLE_ENDIAN
+/* Straight endianness. Just read / write values. */
+#define BROTLI_UNALIGNED_LOAD16LE BrotliUnalignedRead16
+#define BROTLI_UNALIGNED_LOAD32LE BrotliUnalignedRead32
+#define BROTLI_UNALIGNED_LOAD64LE BrotliUnalignedRead64
+#define BROTLI_UNALIGNED_STORE64LE BrotliUnalignedWrite64
+#elif BROTLI_BIG_ENDIAN /* BROTLI_LITTLE_ENDIAN */
+/* Explain compiler to byte-swap values. */
+#define BROTLI_BSWAP16_(V) ((uint16_t)( \
+ (((V) & 0xFFU) << 8) | \
+ (((V) >> 8) & 0xFFU)))
+static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {
+ uint16_t value = BrotliUnalignedRead16(p);
+ return BROTLI_BSWAP16_(value);
+}
+#define BROTLI_BSWAP32_(V) ( \
+ (((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \
+ (((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU))
+static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {
+ uint32_t value = BrotliUnalignedRead32(p);
+ return BROTLI_BSWAP32_(value);
+}
+#define BROTLI_BSWAP64_(V) ( \
+ (((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \
+ (((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \
+ (((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \
+ (((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU))
+static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {
+ uint64_t value = BrotliUnalignedRead64(p);
+ return BROTLI_BSWAP64_(value);
+}
+static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
+ uint64_t value = BROTLI_BSWAP64_(v);
+ BrotliUnalignedWrite64(p, value);
+}
+#else /* BROTLI_LITTLE_ENDIAN */
+/* Read / store values byte-wise; hopefully compiler will understand. */
+static BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {
+ const uint8_t* in = (const uint8_t*)p;
+ return (uint16_t)(in[0] | (in[1] << 8));
+}
+static BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {
+ const uint8_t* in = (const uint8_t*)p;
+ uint32_t value = (uint32_t)(in[0]);
+ value |= (uint32_t)(in[1]) << 8;
+ value |= (uint32_t)(in[2]) << 16;
+ value |= (uint32_t)(in[3]) << 24;
+ return value;
+}
+static BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {
+ const uint8_t* in = (const uint8_t*)p;
+ uint64_t value = (uint64_t)(in[0]);
+ value |= (uint64_t)(in[1]) << 8;
+ value |= (uint64_t)(in[2]) << 16;
+ value |= (uint64_t)(in[3]) << 24;
+ value |= (uint64_t)(in[4]) << 32;
+ value |= (uint64_t)(in[5]) << 40;
+ value |= (uint64_t)(in[6]) << 48;
+ value |= (uint64_t)(in[7]) << 56;
+ return value;
+}
+static BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {
+ uint8_t* out = (uint8_t*)p;
+ out[0] = (uint8_t)v;
+ out[1] = (uint8_t)(v >> 8);
+ out[2] = (uint8_t)(v >> 16);
+ out[3] = (uint8_t)(v >> 24);
+ out[4] = (uint8_t)(v >> 32);
+ out[5] = (uint8_t)(v >> 40);
+ out[6] = (uint8_t)(v >> 48);
+ out[7] = (uint8_t)(v >> 56);
+}
+#endif /* BROTLI_LITTLE_ENDIAN */
+
+/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */
+#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
+#define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x))
+#else
+#define BROTLI_IS_CONSTANT(x) (!!0)
+#endif
+
+#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
+#define BROTLI_HAS_UBFX (!!1)
+#else
+#define BROTLI_HAS_UBFX (!!0)
+#endif
+
+#if defined(BROTLI_ENABLE_LOG)
+#define BROTLI_LOG(x) printf x
+#else
+#define BROTLI_LOG(x)
+#endif
+
+#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
+#define BROTLI_DCHECK(x) assert(x)
+static BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {
+ fprintf(stderr, "%s:%d (%s)\n", f, l, fn);
+ fflush(stderr);
+}
+#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)
+#else
+#define BROTLI_DCHECK(x)
+#define BROTLI_DUMP() (void)(0)
+#endif
+
+/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */
+#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \
+ !defined(BROTLI_BUILD_NO_RBIT)
+#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)
+/* TODO(eustas): detect ARMv6T2 and enable this code for it. */
+static BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {
+ brotli_reg_t output;
+ __asm__("rbit %0, %1\n" : "=r"(output) : "r"(input));
+ return output;
+}
+#define BROTLI_RBIT(x) BrotliRBit(x)
+#endif /* armv7 / armv8 */
+#endif /* gcc || clang */
+#if !defined(BROTLI_RBIT)
+static BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }
+#endif /* BROTLI_RBIT */
+
+#define BROTLI_REPEAT(N, X) { \
+ if ((N & 1) != 0) {X;} \
+ if ((N & 2) != 0) {X; X;} \
+ if ((N & 4) != 0) {X; X; X; X;} \
+}
+
+#define BROTLI_UNUSED(X) (void)(X)
+
+#define BROTLI_MIN_MAX(T) \
+ static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \
+ static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; }
+BROTLI_MIN_MAX(double) BROTLI_MIN_MAX(float) BROTLI_MIN_MAX(int)
+BROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)
+#undef BROTLI_MIN_MAX
+#define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B)))
+#define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B)))
+
+#define BROTLI_SWAP(T, A, I, J) { \
+ T __brotli_swap_tmp = (A)[(I)]; \
+ (A)[(I)] = (A)[(J)]; \
+ (A)[(J)] = __brotli_swap_tmp; \
+}
+
+#if BROTLI_64_BITS
+#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
+#define BROTLI_TZCNT64 __builtin_ctzll
+#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
+#if defined(BROTLI_TARGET_X64)
+#define BROTLI_TZCNT64 _tzcnt_u64
+#else /* BROTLI_TARGET_X64 */
+static BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {
+ uint32_t lsb;
+ _BitScanForward64(&lsb, x);
+ return lsb;
+}
+#define BROTLI_TZCNT64 BrotliBsf64Msvc
+#endif /* BROTLI_TARGET_X64 */
+#endif /* __builtin_ctzll */
+#endif /* BROTLI_64_BITS */
+
+#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0)
+#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x))
+#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)
+static BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) {
+ unsigned long msb;
+ _BitScanReverse(&msb, x);
+ return (uint32_t)msb;
+}
+#define BROTLI_BSR32 BrotliBsr32Msvc
+#endif /* __builtin_clz */
+
+/* Default brotli_alloc_func */
+BROTLI_COMMON_API void* BrotliDefaultAllocFunc(void* opaque, size_t size);
+
+/* Default brotli_free_func */
+BROTLI_COMMON_API void BrotliDefaultFreeFunc(void* opaque, void* address);
+
+BROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {
+ BROTLI_UNUSED(&BrotliSuppressUnusedFunctions);
+ BROTLI_UNUSED(&BrotliUnalignedRead16);
+ BROTLI_UNUSED(&BrotliUnalignedRead32);
+ BROTLI_UNUSED(&BrotliUnalignedRead64);
+ BROTLI_UNUSED(&BrotliUnalignedWrite64);
+ BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE);
+ BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);
+ BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);
+ BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);
+ BROTLI_UNUSED(&BrotliRBit);
+ BROTLI_UNUSED(&brotli_min_double);
+ BROTLI_UNUSED(&brotli_max_double);
+ BROTLI_UNUSED(&brotli_min_float);
+ BROTLI_UNUSED(&brotli_max_float);
+ BROTLI_UNUSED(&brotli_min_int);
+ BROTLI_UNUSED(&brotli_max_int);
+ BROTLI_UNUSED(&brotli_min_size_t);
+ BROTLI_UNUSED(&brotli_max_size_t);
+ BROTLI_UNUSED(&brotli_min_uint32_t);
+ BROTLI_UNUSED(&brotli_max_uint32_t);
+ BROTLI_UNUSED(&brotli_min_uint8_t);
+ BROTLI_UNUSED(&brotli_max_uint8_t);
+ BROTLI_UNUSED(&BrotliDefaultAllocFunc);
+ BROTLI_UNUSED(&BrotliDefaultFreeFunc);
+#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)
+ BROTLI_UNUSED(&BrotliDump);
+#endif
+}
+
+#endif /* BROTLI_COMMON_PLATFORM_H_ */
diff --git a/thirdparty/brotli/common/shared_dictionary.c b/thirdparty/brotli/common/shared_dictionary.c
new file mode 100644
index 0000000000..3ca40c0698
--- /dev/null
+++ b/thirdparty/brotli/common/shared_dictionary.c
@@ -0,0 +1,515 @@
+/* Copyright 2017 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Shared Dictionary definition and utilities. */
+
+#include <brotli/shared_dictionary.h>
+
+#include <memory.h>
+#include <stdlib.h> /* malloc, free */
+#include <stdio.h>
+
+#include "dictionary.h"
+#include "platform.h"
+#include "shared_dictionary_internal.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \
+ - SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1)
+
+/* Max allowed by spec */
+#define BROTLI_MAX_SIZE_BITS 15u
+
+/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
+static BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos,
+ BROTLI_BOOL* result) {
+ uint8_t value;
+ size_t position = *pos;
+ if (position >= size) return BROTLI_FALSE; /* past file end */
+ value = encoded[position++];
+ if (value > 1) return BROTLI_FALSE; /* invalid bool */
+ *result = TO_BROTLI_BOOL(value);
+ *pos = position;
+ return BROTLI_TRUE; /* success */
+}
+
+/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
+static BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos,
+ uint8_t* result) {
+ size_t position = *pos;
+ if (position + sizeof(uint8_t) > size) return BROTLI_FALSE;
+ *result = encoded[position++];
+ *pos = position;
+ return BROTLI_TRUE;
+}
+
+/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
+static BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos,
+ uint16_t* result) {
+ size_t position = *pos;
+ if (position + sizeof(uint16_t) > size) return BROTLI_FALSE;
+ *result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]);
+ position += 2;
+ *pos = position;
+ return BROTLI_TRUE;
+}
+
+/* Reads a varint into a uint32_t, and returns error if it's too large */
+/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */
+static BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size,
+ size_t* pos, uint32_t* result) {
+ int num = 0;
+ uint8_t byte;
+ *result = 0;
+ for (;;) {
+ if (*pos >= size) return BROTLI_FALSE;
+ byte = encoded[(*pos)++];
+ if (num == 4 && byte > 15) return BROTLI_FALSE;
+ *result |= (uint32_t)(byte & 127) << (num * 7);
+ if (byte < 128) return BROTLI_TRUE;
+ num++;
+ }
+}
+
+/* Returns the total length of word list. */
+static size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length,
+ uint32_t* offsets_by_length) {
+ uint32_t pos = 0;
+ uint32_t i;
+ for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
+ offsets_by_length[i] = pos;
+ if (size_bits_by_length[i] != 0) {
+ pos += i << size_bits_by_length[i];
+ }
+ }
+ return pos;
+}
+
+static BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded,
+ size_t* pos, BrotliDictionary* out) {
+ size_t offset;
+ size_t i;
+ size_t position = *pos;
+ if (position + BROTLI_NUM_ENCODED_LENGTHS > size) {
+ return BROTLI_FALSE;
+ }
+
+ memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH);
+ memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH,
+ &encoded[position], BROTLI_NUM_ENCODED_LENGTHS);
+ for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;
+ i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {
+ if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) {
+ return BROTLI_FALSE;
+ }
+ }
+ position += BROTLI_NUM_ENCODED_LENGTHS;
+ offset = BrotliSizeBitsToOffsets(
+ out->size_bits_by_length, out->offsets_by_length);
+
+ out->data = &encoded[position];
+ out->data_size = offset;
+ position += offset;
+ if (position > size) return BROTLI_FALSE;
+ *pos = position;
+ return BROTLI_TRUE;
+}
+
+/* Computes the cutOffTransforms of a BrotliTransforms which already has the
+ transforms data correctly filled in. */
+static void ComputeCutoffTransforms(BrotliTransforms* transforms) {
+ uint32_t i;
+ for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {
+ transforms->cutOffTransforms[i] = -1;
+ }
+ for (i = 0; i < transforms->num_transforms; i++) {
+ const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i);
+ uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i);
+ const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i);
+ if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 &&
+ transforms->cutOffTransforms[type] == -1) {
+ transforms->cutOffTransforms[type] = (int16_t)i;
+ }
+ }
+}
+
+static BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded,
+ size_t* pos, BrotliTransforms* out, uint16_t* out_table,
+ size_t* out_table_size) {
+ size_t position = *pos;
+ size_t offset = 0;
+ size_t stringlet_count = 0; /* NUM_PREFIX_SUFFIX */
+ size_t data_length = 0;
+
+ /* PREFIX_SUFFIX_LENGTH */
+ if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) {
+ return BROTLI_FALSE;
+ }
+ data_length = out->prefix_suffix_size;
+
+ /* Must at least have space for null terminator. */
+ if (data_length < 1) return BROTLI_FALSE;
+ out->prefix_suffix = &encoded[position];
+ if (position + data_length >= size) return BROTLI_FALSE;
+ while (BROTLI_TRUE) {
+ /* STRING_LENGTH */
+ size_t stringlet_len = encoded[position + offset];
+ out_table[stringlet_count] = (uint16_t)offset;
+ stringlet_count++;
+ offset++;
+ if (stringlet_len == 0) {
+ if (offset == data_length) {
+ break;
+ } else {
+ return BROTLI_FALSE;
+ }
+ }
+ if (stringlet_count > 255) return BROTLI_FALSE;
+ offset += stringlet_len;
+ if (offset >= data_length) return BROTLI_FALSE;
+ }
+
+ position += data_length;
+ *pos = position;
+ *out_table_size = (uint16_t)stringlet_count;
+ return BROTLI_TRUE;
+}
+
+static BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded,
+ size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table,
+ size_t* prefix_suffix_count) {
+ uint32_t i;
+ BROTLI_BOOL has_params = BROTLI_FALSE;
+ BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE;
+ size_t position = *pos;
+ size_t stringlet_cnt = 0;
+ if (position >= size) return BROTLI_FALSE;
+
+ prefix_suffix_ok = ParsePrefixSuffixTable(
+ size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt);
+ if (!prefix_suffix_ok) return BROTLI_FALSE;
+ out->prefix_suffix_map = prefix_suffix_table;
+ *prefix_suffix_count = stringlet_cnt;
+
+ out->num_transforms = encoded[position++];
+ out->transforms = &encoded[position];
+ position += (size_t)out->num_transforms * 3;
+ if (position > size) return BROTLI_FALSE;
+ /* Check for errors and read extra parameters. */
+ for (i = 0; i < out->num_transforms; i++) {
+ uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i);
+ uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
+ uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i);
+ if (prefix_id >= stringlet_cnt) return BROTLI_FALSE;
+ if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE;
+ if (suffix_id >= stringlet_cnt) return BROTLI_FALSE;
+ if (type == BROTLI_TRANSFORM_SHIFT_FIRST ||
+ type == BROTLI_TRANSFORM_SHIFT_ALL) {
+ has_params = BROTLI_TRUE;
+ }
+ }
+ if (has_params) {
+ out->params = &encoded[position];
+ position += (size_t)out->num_transforms * 2;
+ if (position > size) return BROTLI_FALSE;
+ for (i = 0; i < out->num_transforms; i++) {
+ uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);
+ if (type != BROTLI_TRANSFORM_SHIFT_FIRST &&
+ type != BROTLI_TRANSFORM_SHIFT_ALL) {
+ if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) {
+ return BROTLI_FALSE;
+ }
+ }
+ }
+ } else {
+ out->params = NULL;
+ }
+ ComputeCutoffTransforms(out);
+ *pos = position;
+ return BROTLI_TRUE;
+}
+
+static BROTLI_BOOL DryParseDictionary(const uint8_t* encoded,
+ size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) {
+ size_t pos = 0;
+ uint32_t chunk_size = 0;
+ uint8_t num_word_lists;
+ uint8_t num_transform_lists;
+ *is_custom_static_dict = BROTLI_FALSE;
+ *num_prefix = 0;
+
+ /* Skip magic header bytes. */
+ pos += 2;
+
+ /* LZ77_DICTIONARY_LENGTH */
+ if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
+ if (chunk_size != 0) {
+ /* This limitation is not specified but the 32-bit Brotli decoder for now */
+ if (chunk_size > 1073741823) return BROTLI_FALSE;
+ *num_prefix = 1;
+ if (pos + chunk_size > size) return BROTLI_FALSE;
+ pos += chunk_size;
+ }
+
+ if (!ReadUint8(encoded, size, &pos, &num_word_lists)) {
+ return BROTLI_FALSE;
+ }
+ if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) {
+ return BROTLI_FALSE;
+ }
+
+ if (num_word_lists > 0 || num_transform_lists > 0) {
+ *is_custom_static_dict = BROTLI_TRUE;
+ }
+
+ return BROTLI_TRUE;
+}
+
+static BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size,
+ BrotliSharedDictionary* dict) {
+ uint32_t i;
+ size_t pos = 0;
+ uint32_t chunk_size = 0;
+ size_t total_prefix_suffix_count = 0;
+ size_t trasform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
+ uint16_t temporary_prefix_suffix_table[256];
+
+ /* Skip magic header bytes. */
+ pos += 2;
+
+ /* LZ77_DICTIONARY_LENGTH */
+ if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;
+ if (chunk_size != 0) {
+ if (pos + chunk_size > size) return BROTLI_FALSE;
+ dict->prefix_size[dict->num_prefix] = chunk_size;
+ dict->prefix[dict->num_prefix] = &encoded[pos];
+ dict->num_prefix++;
+ /* LZ77_DICTIONARY_LENGTH bytes. */
+ pos += chunk_size;
+ }
+
+ /* NUM_WORD_LISTS */
+ if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) {
+ return BROTLI_FALSE;
+ }
+ if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
+ return BROTLI_FALSE;
+ }
+
+ if (dict->num_word_lists != 0) {
+ dict->words_instances = (BrotliDictionary*)dict->alloc_func(
+ dict->memory_manager_opaque,
+ dict->num_word_lists * sizeof(*dict->words_instances));
+ if (!dict->words_instances) return BROTLI_FALSE; /* OOM */
+ }
+ for (i = 0; i < dict->num_word_lists; i++) {
+ if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) {
+ return BROTLI_FALSE;
+ }
+ }
+
+ /* NUM_TRANSFORM_LISTS */
+ if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) {
+ return BROTLI_FALSE;
+ }
+ if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
+ return BROTLI_FALSE;
+ }
+
+ if (dict->num_transform_lists != 0) {
+ dict->transforms_instances = (BrotliTransforms*)dict->alloc_func(
+ dict->memory_manager_opaque,
+ dict->num_transform_lists * sizeof(*dict->transforms_instances));
+ if (!dict->transforms_instances) return BROTLI_FALSE; /* OOM */
+ }
+ for (i = 0; i < dict->num_transform_lists; i++) {
+ BROTLI_BOOL ok = BROTLI_FALSE;
+ size_t prefix_suffix_count = 0;
+ trasform_list_start[i] = pos;
+ dict->transforms_instances[i].prefix_suffix_map =
+ temporary_prefix_suffix_table;
+ ok = ParseTransformsList(
+ size, encoded, &pos, &dict->transforms_instances[i],
+ temporary_prefix_suffix_table, &prefix_suffix_count);
+ if (!ok) return BROTLI_FALSE;
+ total_prefix_suffix_count += prefix_suffix_count;
+ }
+ if (total_prefix_suffix_count != 0) {
+ dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func(
+ dict->memory_manager_opaque,
+ total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps));
+ if (!dict->prefix_suffix_maps) return BROTLI_FALSE; /* OOM */
+ }
+ total_prefix_suffix_count = 0;
+ for (i = 0; i < dict->num_transform_lists; i++) {
+ size_t prefix_suffix_count = 0;
+ size_t position = trasform_list_start[i];
+ uint16_t* prefix_suffix_map =
+ &dict->prefix_suffix_maps[total_prefix_suffix_count];
+ BROTLI_BOOL ok = ParsePrefixSuffixTable(
+ size, encoded, &position, &dict->transforms_instances[i],
+ prefix_suffix_map, &prefix_suffix_count);
+ if (!ok) return BROTLI_FALSE;
+ dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map;
+ total_prefix_suffix_count += prefix_suffix_count;
+ }
+
+ if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) {
+ if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) {
+ return BROTLI_FALSE;
+ }
+ if (dict->num_dictionaries == 0 ||
+ dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {
+ return BROTLI_FALSE;
+ }
+ for (i = 0; i < dict->num_dictionaries; i++) {
+ uint8_t words_index;
+ uint8_t transforms_index;
+ if (!ReadUint8(encoded, size, &pos, &words_index)) {
+ return BROTLI_FALSE;
+ }
+ if (words_index > dict->num_word_lists) return BROTLI_FALSE;
+ if (!ReadUint8(encoded, size, &pos, &transforms_index)) {
+ return BROTLI_FALSE;
+ }
+ if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE;
+ dict->words[i] = words_index == dict->num_word_lists ?
+ BrotliGetDictionary() : &dict->words_instances[words_index];
+ dict->transforms[i] = transforms_index == dict->num_transform_lists ?
+ BrotliGetTransforms(): &dict->transforms_instances[transforms_index];
+ }
+ /* CONTEXT_ENABLED */
+ if (!ReadBool(encoded, size, &pos, &dict->context_based)) {
+ return BROTLI_FALSE;
+ }
+
+ /* CONTEXT_MAP */
+ if (dict->context_based) {
+ for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) {
+ if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) {
+ return BROTLI_FALSE;
+ }
+ if (dict->context_map[i] >= dict->num_dictionaries) {
+ return BROTLI_FALSE;
+ }
+ }
+ }
+ } else {
+ dict->context_based = BROTLI_FALSE;
+ dict->num_dictionaries = 1;
+ dict->words[0] = BrotliGetDictionary();
+ dict->transforms[0] = BrotliGetTransforms();
+ }
+
+ return BROTLI_TRUE;
+}
+
+/* Decodes shared dictionary and verifies correctness.
+ Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise.
+ The BrotliSharedDictionary must already have been initialized. If the
+ BrotliSharedDictionary already contains data, compound dictionaries
+ will be appended, but an error will be returned if it already has
+ custom words or transforms.
+ TODO(lode): link to RFC for shared brotli once published. */
+static BROTLI_BOOL DecodeSharedDictionary(
+ const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) {
+ uint32_t num_prefix = 0;
+ BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE;
+ BROTLI_BOOL has_custom_static_dict =
+ dict->num_word_lists > 0 || dict->num_transform_lists > 0;
+
+ /* Check magic header bytes. */
+ if (size < 2) return BROTLI_FALSE;
+ if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE;
+
+ if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) {
+ return BROTLI_FALSE;
+ }
+
+ if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) {
+ return BROTLI_FALSE;
+ }
+
+ /* Cannot combine different static dictionaries, only prefix dictionaries */
+ if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE;
+
+ return ParseDictionary(encoded, size, dict);
+}
+
+void BrotliSharedDictionaryDestroyInstance(
+ BrotliSharedDictionary* dict) {
+ if (!dict) {
+ return;
+ } else {
+ brotli_free_func free_func = dict->free_func;
+ void* opaque = dict->memory_manager_opaque;
+ /* Cleanup. */
+ free_func(opaque, dict->words_instances);
+ free_func(opaque, dict->transforms_instances);
+ free_func(opaque, dict->prefix_suffix_maps);
+ /* Self-destruction. */
+ free_func(opaque, dict);
+ }
+}
+
+BROTLI_BOOL BrotliSharedDictionaryAttach(
+ BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,
+ size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {
+ if (!dict) {
+ return BROTLI_FALSE;
+ }
+ if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {
+ return DecodeSharedDictionary(data, data_size, dict);
+ } else if (type == BROTLI_SHARED_DICTIONARY_RAW) {
+ if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) {
+ return BROTLI_FALSE;
+ }
+ dict->prefix_size[dict->num_prefix] = data_size;
+ dict->prefix[dict->num_prefix] = data;
+ dict->num_prefix++;
+ return BROTLI_TRUE;
+ } else {
+ return BROTLI_FALSE;
+ }
+}
+
+BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
+ BrotliSharedDictionary* dict = 0;
+ if (!alloc_func && !free_func) {
+ dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary));
+ } else if (alloc_func && free_func) {
+ dict = (BrotliSharedDictionary*)alloc_func(
+ opaque, sizeof(BrotliSharedDictionary));
+ }
+ if (dict == 0) {
+ return 0;
+ }
+
+ /* TODO(eustas): explicitly initialize all the fields? */
+ memset(dict, 0, sizeof(BrotliSharedDictionary));
+
+ dict->context_based = BROTLI_FALSE;
+ dict->num_dictionaries = 1;
+ dict->num_word_lists = 0;
+ dict->num_transform_lists = 0;
+
+ dict->words[0] = BrotliGetDictionary();
+ dict->transforms[0] = BrotliGetTransforms();
+
+ dict->alloc_func = alloc_func ? alloc_func : BrotliDefaultAllocFunc;
+ dict->free_func = free_func ? free_func : BrotliDefaultFreeFunc;
+ dict->memory_manager_opaque = opaque;
+
+ return dict;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/common/shared_dictionary_internal.h b/thirdparty/brotli/common/shared_dictionary_internal.h
new file mode 100644
index 0000000000..87ab13b24b
--- /dev/null
+++ b/thirdparty/brotli/common/shared_dictionary_internal.h
@@ -0,0 +1,74 @@
+/* Copyright 2017 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* (Transparent) Shared Dictionary definition. */
+
+#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
+#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_
+
+#include "dictionary.h"
+#include <brotli/shared_dictionary.h>
+#include "transform.h"
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+struct BrotliSharedDictionaryStruct {
+ /* LZ77 prefixes (compound dictionary). */
+ uint32_t num_prefix; /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */
+ size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS];
+ const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS];
+
+ /* If set, the context map is used to select word and transform list from 64
+ contexts, if not set, the context map is not used and only words[0] and
+ transforms[0] are to be used. */
+ BROTLI_BOOL context_based;
+
+ uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
+
+ /* Amount of word_list+transform_list combinations. */
+ uint8_t num_dictionaries;
+
+ /* Must use num_dictionaries values. */
+ const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
+
+ /* Must use num_dictionaries values. */
+ const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];
+
+ /* Amount of custom word lists. May be 0 if only Brotli's built-in is used */
+ uint8_t num_word_lists;
+
+ /* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */
+ BrotliDictionary* words_instances;
+
+ /* Amount of custom transform lists. May be 0 if only Brotli's built-in is
+ used */
+ uint8_t num_transform_lists;
+
+ /* Contents of the custom transform lists. Must be NULL if num_transform_lists
+ is 0. */
+ BrotliTransforms* transforms_instances;
+
+ /* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL
+ if num_transform_lists is 0. */
+ uint16_t* prefix_suffix_maps;
+
+ /* Memory management */
+ brotli_alloc_func alloc_func;
+ brotli_free_func free_func;
+ void* memory_manager_opaque;
+};
+
+typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal;
+#define BrotliSharedDictionary BrotliSharedDictionaryInternal
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */
diff --git a/thirdparty/brotli/common/transform.c b/thirdparty/brotli/common/transform.c
new file mode 100644
index 0000000000..49455fc496
--- /dev/null
+++ b/thirdparty/brotli/common/transform.c
@@ -0,0 +1,291 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include "transform.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* RFC 7932 transforms string data */
+static const char kPrefixSuffix[217] =
+ "\1 \2, \10 of the \4 of \2s \1.\5 and \4 "
+/* 0x _0 _2 __5 _E _3 _6 _8 _E */
+ "in \1\"\4 to \2\">\1\n\2. \1]\5 for \3 a \6 "
+/* 2x _3_ _5 _A_ _D_ _F _2 _4 _A _E */
+ "that \1\'\6 with \6 from \4 by \1(\6. T"
+/* 4x _5_ _7 _E _5 _A _C */
+ "he \4 on \4 as \4 is \4ing \2\n\t\1:\3ed "
+/* 6x _3 _8 _D _2 _7_ _ _A _C */
+ "\2=\"\4 at \3ly \1,\2=\'\5.com/\7. This \5"
+/* 8x _0 _ _3 _8 _C _E _ _1 _7 _F */
+ " not \3er \3al \4ful \4ive \5less \4es"
+/* Ax _5 _9 _D _2 _7 _D */
+ "t \4ize \2\xc2\xa0\4ous \5 the \2e "; /* \0 - implicit trailing zero. */
+/* Cx _2 _7___ ___ _A _F _5 _8 */
+
+static const uint16_t kPrefixSuffixMap[50] = {
+ 0x00, 0x02, 0x05, 0x0E, 0x13, 0x16, 0x18, 0x1E, 0x23, 0x25,
+ 0x2A, 0x2D, 0x2F, 0x32, 0x34, 0x3A, 0x3E, 0x45, 0x47, 0x4E,
+ 0x55, 0x5A, 0x5C, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7A, 0x7C,
+ 0x80, 0x83, 0x88, 0x8C, 0x8E, 0x91, 0x97, 0x9F, 0xA5, 0xA9,
+ 0xAD, 0xB2, 0xB7, 0xBD, 0xC2, 0xC7, 0xCA, 0xCF, 0xD5, 0xD8
+};
+
+/* RFC 7932 transforms */
+static const uint8_t kTransformsData[] = {
+ 49, BROTLI_TRANSFORM_IDENTITY, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 0,
+ 0, BROTLI_TRANSFORM_IDENTITY, 0,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_1, 49,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 47,
+ 0, BROTLI_TRANSFORM_IDENTITY, 49,
+ 4, BROTLI_TRANSFORM_IDENTITY, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 3,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 6,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_2, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_1, 49,
+ 1, BROTLI_TRANSFORM_IDENTITY, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 1,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 7,
+ 49, BROTLI_TRANSFORM_IDENTITY, 9,
+ 48, BROTLI_TRANSFORM_IDENTITY, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 8,
+ 49, BROTLI_TRANSFORM_IDENTITY, 5,
+ 49, BROTLI_TRANSFORM_IDENTITY, 10,
+ 49, BROTLI_TRANSFORM_IDENTITY, 11,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_3, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 13,
+ 49, BROTLI_TRANSFORM_IDENTITY, 14,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_3, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_2, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 15,
+ 49, BROTLI_TRANSFORM_IDENTITY, 16,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 12,
+ 5, BROTLI_TRANSFORM_IDENTITY, 49,
+ 0, BROTLI_TRANSFORM_IDENTITY, 1,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_4, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 18,
+ 49, BROTLI_TRANSFORM_IDENTITY, 17,
+ 49, BROTLI_TRANSFORM_IDENTITY, 19,
+ 49, BROTLI_TRANSFORM_IDENTITY, 20,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_5, 49,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_6, 49,
+ 47, BROTLI_TRANSFORM_IDENTITY, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_4, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 22,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 23,
+ 49, BROTLI_TRANSFORM_IDENTITY, 24,
+ 49, BROTLI_TRANSFORM_IDENTITY, 25,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_7, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_1, 26,
+ 49, BROTLI_TRANSFORM_IDENTITY, 27,
+ 49, BROTLI_TRANSFORM_IDENTITY, 28,
+ 0, BROTLI_TRANSFORM_IDENTITY, 12,
+ 49, BROTLI_TRANSFORM_IDENTITY, 29,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_9, 49,
+ 49, BROTLI_TRANSFORM_OMIT_FIRST_7, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_6, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 21,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_8, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 31,
+ 49, BROTLI_TRANSFORM_IDENTITY, 32,
+ 47, BROTLI_TRANSFORM_IDENTITY, 3,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_5, 49,
+ 49, BROTLI_TRANSFORM_OMIT_LAST_9, 49,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 8,
+ 5, BROTLI_TRANSFORM_IDENTITY, 21,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 10,
+ 49, BROTLI_TRANSFORM_IDENTITY, 30,
+ 0, BROTLI_TRANSFORM_IDENTITY, 5,
+ 35, BROTLI_TRANSFORM_IDENTITY, 49,
+ 47, BROTLI_TRANSFORM_IDENTITY, 2,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 17,
+ 49, BROTLI_TRANSFORM_IDENTITY, 36,
+ 49, BROTLI_TRANSFORM_IDENTITY, 33,
+ 5, BROTLI_TRANSFORM_IDENTITY, 0,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 21,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,
+ 49, BROTLI_TRANSFORM_IDENTITY, 37,
+ 0, BROTLI_TRANSFORM_IDENTITY, 30,
+ 49, BROTLI_TRANSFORM_IDENTITY, 38,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,
+ 49, BROTLI_TRANSFORM_IDENTITY, 39,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,
+ 49, BROTLI_TRANSFORM_IDENTITY, 34,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 8,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,
+ 0, BROTLI_TRANSFORM_IDENTITY, 21,
+ 49, BROTLI_TRANSFORM_IDENTITY, 40,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,
+ 49, BROTLI_TRANSFORM_IDENTITY, 41,
+ 49, BROTLI_TRANSFORM_IDENTITY, 42,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 17,
+ 49, BROTLI_TRANSFORM_IDENTITY, 43,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 10,
+ 0, BROTLI_TRANSFORM_IDENTITY, 34,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,
+ 49, BROTLI_TRANSFORM_IDENTITY, 44,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,
+ 45, BROTLI_TRANSFORM_IDENTITY, 49,
+ 0, BROTLI_TRANSFORM_IDENTITY, 33,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,
+ 49, BROTLI_TRANSFORM_IDENTITY, 46,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,
+ 49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 33,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 21,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,
+ 49, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,
+ 0, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,
+ 0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,
+};
+
+static const BrotliTransforms kBrotliTransforms = {
+ sizeof(kPrefixSuffix),
+ (const uint8_t*)kPrefixSuffix,
+ kPrefixSuffixMap,
+ sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])),
+ kTransformsData,
+ NULL, /* no extra parameters */
+ {0, 12, 27, 23, 42, 63, 56, 48, 59, 64}
+};
+
+const BrotliTransforms* BrotliGetTransforms(void) {
+ return &kBrotliTransforms;
+}
+
+static int ToUpperCase(uint8_t* p) {
+ if (p[0] < 0xC0) {
+ if (p[0] >= 'a' && p[0] <= 'z') {
+ p[0] ^= 32;
+ }
+ return 1;
+ }
+ /* An overly simplified uppercasing model for UTF-8. */
+ if (p[0] < 0xE0) {
+ p[1] ^= 32;
+ return 2;
+ }
+ /* An arbitrary transform for three byte characters. */
+ p[2] ^= 5;
+ return 3;
+}
+
+static int Shift(uint8_t* word, int word_len, uint16_t parameter) {
+ /* Limited sign extension: scalar < (1 << 24). */
+ uint32_t scalar =
+ (parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u));
+ if (word[0] < 0x80) {
+ /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */
+ scalar += (uint32_t)word[0];
+ word[0] = (uint8_t)(scalar & 0x7Fu);
+ return 1;
+ } else if (word[0] < 0xC0) {
+ /* Continuation / 10AAAAAA. */
+ return 1;
+ } else if (word[0] < 0xE0) {
+ /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */
+ if (word_len < 2) return 1;
+ scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u));
+ word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F));
+ word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F));
+ return 2;
+ } else if (word[0] < 0xF0) {
+ /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */
+ if (word_len < 3) return word_len;
+ scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) |
+ ((word[0] & 0x0Fu) << 12u));
+ word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F));
+ word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F));
+ word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F));
+ return 3;
+ } else if (word[0] < 0xF8) {
+ /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */
+ if (word_len < 4) return word_len;
+ scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) |
+ ((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u));
+ word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07));
+ word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F));
+ word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F));
+ word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F));
+ return 4;
+ }
+ return 1;
+}
+
+int BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,
+ const BrotliTransforms* transforms, int transform_idx) {
+ int idx = 0;
+ const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx);
+ uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx);
+ const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx);
+ {
+ int prefix_len = *prefix++;
+ while (prefix_len--) { dst[idx++] = *prefix++; }
+ }
+ {
+ const int t = type;
+ int i = 0;
+ if (t <= BROTLI_TRANSFORM_OMIT_LAST_9) {
+ len -= t;
+ } else if (t >= BROTLI_TRANSFORM_OMIT_FIRST_1
+ && t <= BROTLI_TRANSFORM_OMIT_FIRST_9) {
+ int skip = t - (BROTLI_TRANSFORM_OMIT_FIRST_1 - 1);
+ word += skip;
+ len -= skip;
+ }
+ while (i < len) { dst[idx++] = word[i++]; }
+ if (t == BROTLI_TRANSFORM_UPPERCASE_FIRST) {
+ ToUpperCase(&dst[idx - len]);
+ } else if (t == BROTLI_TRANSFORM_UPPERCASE_ALL) {
+ uint8_t* uppercase = &dst[idx - len];
+ while (len > 0) {
+ int step = ToUpperCase(uppercase);
+ uppercase += step;
+ len -= step;
+ }
+ } else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) {
+ uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]
+ + (transforms->params[transform_idx * 2 + 1] << 8u));
+ Shift(&dst[idx - len], len, param);
+ } else if (t == BROTLI_TRANSFORM_SHIFT_ALL) {
+ uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]
+ + (transforms->params[transform_idx * 2 + 1] << 8u));
+ uint8_t* shift = &dst[idx - len];
+ while (len > 0) {
+ int step = Shift(shift, len, param);
+ shift += step;
+ len -= step;
+ }
+ }
+ }
+ {
+ int suffix_len = *suffix++;
+ while (suffix_len--) { dst[idx++] = *suffix++; }
+ return idx;
+ }
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/common/transform.h b/thirdparty/brotli/common/transform.h
new file mode 100644
index 0000000000..b6f86cc7d5
--- /dev/null
+++ b/thirdparty/brotli/common/transform.h
@@ -0,0 +1,85 @@
+/* transforms is a part of ABI, but not API.
+
+ It means that there are some functions that are supposed to be in "common"
+ library, but header itself is not placed into include/brotli. This way,
+ aforementioned functions will be available only to brotli internals.
+ */
+
+#ifndef BROTLI_COMMON_TRANSFORM_H_
+#define BROTLI_COMMON_TRANSFORM_H_
+
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+enum BrotliWordTransformType {
+ BROTLI_TRANSFORM_IDENTITY = 0,
+ BROTLI_TRANSFORM_OMIT_LAST_1 = 1,
+ BROTLI_TRANSFORM_OMIT_LAST_2 = 2,
+ BROTLI_TRANSFORM_OMIT_LAST_3 = 3,
+ BROTLI_TRANSFORM_OMIT_LAST_4 = 4,
+ BROTLI_TRANSFORM_OMIT_LAST_5 = 5,
+ BROTLI_TRANSFORM_OMIT_LAST_6 = 6,
+ BROTLI_TRANSFORM_OMIT_LAST_7 = 7,
+ BROTLI_TRANSFORM_OMIT_LAST_8 = 8,
+ BROTLI_TRANSFORM_OMIT_LAST_9 = 9,
+ BROTLI_TRANSFORM_UPPERCASE_FIRST = 10,
+ BROTLI_TRANSFORM_UPPERCASE_ALL = 11,
+ BROTLI_TRANSFORM_OMIT_FIRST_1 = 12,
+ BROTLI_TRANSFORM_OMIT_FIRST_2 = 13,
+ BROTLI_TRANSFORM_OMIT_FIRST_3 = 14,
+ BROTLI_TRANSFORM_OMIT_FIRST_4 = 15,
+ BROTLI_TRANSFORM_OMIT_FIRST_5 = 16,
+ BROTLI_TRANSFORM_OMIT_FIRST_6 = 17,
+ BROTLI_TRANSFORM_OMIT_FIRST_7 = 18,
+ BROTLI_TRANSFORM_OMIT_FIRST_8 = 19,
+ BROTLI_TRANSFORM_OMIT_FIRST_9 = 20,
+ BROTLI_TRANSFORM_SHIFT_FIRST = 21,
+ BROTLI_TRANSFORM_SHIFT_ALL = 22,
+ BROTLI_NUM_TRANSFORM_TYPES /* Counts transforms, not a transform itself. */
+};
+
+#define BROTLI_TRANSFORMS_MAX_CUT_OFF BROTLI_TRANSFORM_OMIT_LAST_9
+
+typedef struct BrotliTransforms {
+ uint16_t prefix_suffix_size;
+ /* Last character must be null, so prefix_suffix_size must be at least 1. */
+ const uint8_t* prefix_suffix;
+ const uint16_t* prefix_suffix_map;
+ uint32_t num_transforms;
+ /* Each entry is a [prefix_id, transform, suffix_id] triplet. */
+ const uint8_t* transforms;
+ /* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL,
+ must be NULL if and only if no such transforms are present. */
+ const uint8_t* params;
+ /* Indices of transforms like ["", BROTLI_TRANSFORM_OMIT_LAST_#, ""].
+ 0-th element corresponds to ["", BROTLI_TRANSFORM_IDENTITY, ""].
+ -1, if cut-off transform does not exist. */
+ int16_t cutOffTransforms[BROTLI_TRANSFORMS_MAX_CUT_OFF + 1];
+} BrotliTransforms;
+
+/* T is BrotliTransforms*; result is uint8_t. */
+#define BROTLI_TRANSFORM_PREFIX_ID(T, I) ((T)->transforms[((I) * 3) + 0])
+#define BROTLI_TRANSFORM_TYPE(T, I) ((T)->transforms[((I) * 3) + 1])
+#define BROTLI_TRANSFORM_SUFFIX_ID(T, I) ((T)->transforms[((I) * 3) + 2])
+
+/* T is BrotliTransforms*; result is const uint8_t*. */
+#define BROTLI_TRANSFORM_PREFIX(T, I) (&(T)->prefix_suffix[ \
+ (T)->prefix_suffix_map[BROTLI_TRANSFORM_PREFIX_ID(T, I)]])
+#define BROTLI_TRANSFORM_SUFFIX(T, I) (&(T)->prefix_suffix[ \
+ (T)->prefix_suffix_map[BROTLI_TRANSFORM_SUFFIX_ID(T, I)]])
+
+BROTLI_COMMON_API const BrotliTransforms* BrotliGetTransforms(void);
+
+BROTLI_COMMON_API int BrotliTransformDictionaryWord(
+ uint8_t* dst, const uint8_t* word, int len,
+ const BrotliTransforms* transforms, int transform_idx);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_COMMON_TRANSFORM_H_ */
diff --git a/thirdparty/brotli/common/version.h b/thirdparty/brotli/common/version.h
new file mode 100644
index 0000000000..01b2998e25
--- /dev/null
+++ b/thirdparty/brotli/common/version.h
@@ -0,0 +1,26 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Version definition. */
+
+#ifndef BROTLI_COMMON_VERSION_H_
+#define BROTLI_COMMON_VERSION_H_
+
+/* This macro should only be used when library is compiled together with client.
+ If library is dynamically linked, use BrotliDecoderVersion and
+ BrotliEncoderVersion methods. */
+
+/* Semantic version, calculated as (MAJOR << 24) | (MINOR << 12) | PATCH */
+#define BROTLI_VERSION 0x1000009
+
+/* This macro is used by build system to produce Libtool-friendly soname. See
+ https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
+ */
+
+/* ABI version, calculated as (CURRENT << 24) | (REVISION << 12) | AGE */
+#define BROTLI_ABI_VERSION 0x1009000
+
+#endif /* BROTLI_COMMON_VERSION_H_ */
diff --git a/thirdparty/brotli/dec/bit_reader.c b/thirdparty/brotli/dec/bit_reader.c
new file mode 100644
index 0000000000..3dc848b7dc
--- /dev/null
+++ b/thirdparty/brotli/dec/bit_reader.c
@@ -0,0 +1,76 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Bit reading helpers */
+
+#include "bit_reader.h"
+
+#include "../common/platform.h"
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+const uint32_t kBrotliBitMask[33] = { 0x00000000,
+ 0x00000001, 0x00000003, 0x00000007, 0x0000000F,
+ 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
+ 0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
+ 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
+ 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
+ 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
+ 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
+ 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
+};
+
+void BrotliInitBitReader(BrotliBitReader* const br) {
+ br->val_ = 0;
+ br->bit_pos_ = sizeof(br->val_) << 3;
+}
+
+BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {
+ size_t aligned_read_mask = (sizeof(br->val_) >> 1) - 1;
+ /* Fixing alignment after unaligned BrotliFillWindow would result accumulator
+ overflow. If unalignment is caused by BrotliSafeReadBits, then there is
+ enough space in accumulator to fix alignment. */
+ if (!BROTLI_ALIGNED_READ) {
+ aligned_read_mask = 0;
+ }
+ if (BrotliGetAvailableBits(br) == 0) {
+ if (!BrotliPullByte(br)) {
+ return BROTLI_FALSE;
+ }
+ }
+
+ while ((((size_t)br->next_in) & aligned_read_mask) != 0) {
+ if (!BrotliPullByte(br)) {
+ /* If we consumed all the input, we don't care about the alignment. */
+ return BROTLI_TRUE;
+ }
+ }
+ return BROTLI_TRUE;
+}
+
+BROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,
+ uint32_t n_bits, uint32_t* val) {
+ uint32_t low_val;
+ uint32_t high_val;
+ BrotliBitReaderState memento;
+ BROTLI_DCHECK(n_bits <= 32);
+ BROTLI_DCHECK(n_bits > 24);
+ BrotliBitReaderSaveState(br, &memento);
+ if (!BrotliSafeReadBits(br, 16, &low_val) ||
+ !BrotliSafeReadBits(br, n_bits - 16, &high_val)) {
+ BrotliBitReaderRestoreState(br, &memento);
+ return BROTLI_FALSE;
+ }
+ *val = low_val | (high_val << 16);
+ return BROTLI_TRUE;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/dec/bit_reader.h b/thirdparty/brotli/dec/bit_reader.h
new file mode 100644
index 0000000000..3906455103
--- /dev/null
+++ b/thirdparty/brotli/dec/bit_reader.h
@@ -0,0 +1,361 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Bit reading helpers */
+
+#ifndef BROTLI_DEC_BIT_READER_H_
+#define BROTLI_DEC_BIT_READER_H_
+
+#include <string.h> /* memcpy */
+
+#include "../common/constants.h"
+#include "../common/platform.h"
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)
+
+BROTLI_INTERNAL extern const uint32_t kBrotliBitMask[33];
+
+static BROTLI_INLINE uint32_t BitMask(uint32_t n) {
+ if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {
+ /* Masking with this expression turns to a single
+ "Unsigned Bit Field Extract" UBFX instruction on ARM. */
+ return ~((0xFFFFFFFFu) << n);
+ } else {
+ return kBrotliBitMask[n];
+ }
+}
+
+typedef struct {
+ brotli_reg_t val_; /* pre-fetched bits */
+ uint32_t bit_pos_; /* current bit-reading position in val_ */
+ const uint8_t* next_in; /* the byte we're reading from */
+ size_t avail_in;
+} BrotliBitReader;
+
+typedef struct {
+ brotli_reg_t val_;
+ uint32_t bit_pos_;
+ const uint8_t* next_in;
+ size_t avail_in;
+} BrotliBitReaderState;
+
+/* Initializes the BrotliBitReader fields. */
+BROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* const br);
+
+/* Ensures that accumulator is not empty.
+ May consume up to sizeof(brotli_reg_t) - 1 bytes of input.
+ Returns BROTLI_FALSE if data is required but there is no input available.
+ For BROTLI_ALIGNED_READ this function also prepares bit reader for aligned
+ reading. */
+BROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br);
+
+/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden
+ the main code-path. Never called for RFC brotli streams, required only for
+ "large-window" mode and other extensions. */
+BROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val);
+
+static BROTLI_INLINE void BrotliBitReaderSaveState(
+ BrotliBitReader* const from, BrotliBitReaderState* to) {
+ to->val_ = from->val_;
+ to->bit_pos_ = from->bit_pos_;
+ to->next_in = from->next_in;
+ to->avail_in = from->avail_in;
+}
+
+static BROTLI_INLINE void BrotliBitReaderRestoreState(
+ BrotliBitReader* const to, BrotliBitReaderState* from) {
+ to->val_ = from->val_;
+ to->bit_pos_ = from->bit_pos_;
+ to->next_in = from->next_in;
+ to->avail_in = from->avail_in;
+}
+
+static BROTLI_INLINE uint32_t BrotliGetAvailableBits(
+ const BrotliBitReader* br) {
+ return (BROTLI_64_BITS ? 64 : 32) - br->bit_pos_;
+}
+
+/* Returns amount of unread bytes the bit reader still has buffered from the
+ BrotliInput, including whole bytes in br->val_. Result is capped with
+ maximal ring-buffer size (larger number won't be utilized anyway). */
+static BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {
+ static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;
+ if (br->avail_in > kCap) return kCap;
+ return br->avail_in + (BrotliGetAvailableBits(br) >> 3);
+}
+
+/* Checks if there is at least |num| bytes left in the input ring-buffer
+ (excluding the bits remaining in br->val_). */
+static BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(
+ BrotliBitReader* const br, size_t num) {
+ return TO_BROTLI_BOOL(br->avail_in >= num);
+}
+
+/* Guarantees that there are at least |n_bits| + 1 bits in accumulator.
+ Precondition: accumulator contains at least 1 bit.
+ |n_bits| should be in the range [1..24] for regular build. For portable
+ non-64-bit little-endian build only 16 bits are safe to request. */
+static BROTLI_INLINE void BrotliFillBitWindow(
+ BrotliBitReader* const br, uint32_t n_bits) {
+#if (BROTLI_64_BITS)
+ if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
+ uint32_t bit_pos = br->bit_pos_;
+ if (bit_pos >= 56) {
+ br->val_ =
+ (br->val_ >> 56) | (BROTLI_UNALIGNED_LOAD64LE(br->next_in) << 8);
+ br->bit_pos_ =
+ bit_pos ^ 56; /* here same as -= 56 because of the if condition */
+ br->avail_in -= 7;
+ br->next_in += 7;
+ }
+ } else if (
+ !BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 16)) {
+ uint32_t bit_pos = br->bit_pos_;
+ if (bit_pos >= 48) {
+ br->val_ =
+ (br->val_ >> 48) | (BROTLI_UNALIGNED_LOAD64LE(br->next_in) << 16);
+ br->bit_pos_ =
+ bit_pos ^ 48; /* here same as -= 48 because of the if condition */
+ br->avail_in -= 6;
+ br->next_in += 6;
+ }
+ } else {
+ uint32_t bit_pos = br->bit_pos_;
+ if (bit_pos >= 32) {
+ br->val_ = (br->val_ >> 32) |
+ (((uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in)) << 32);
+ br->bit_pos_ =
+ bit_pos ^ 32; /* here same as -= 32 because of the if condition */
+ br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
+ br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
+ }
+ }
+#else
+ if (!BROTLI_ALIGNED_READ && BROTLI_IS_CONSTANT(n_bits) && (n_bits <= 8)) {
+ uint32_t bit_pos = br->bit_pos_;
+ if (bit_pos >= 24) {
+ br->val_ =
+ (br->val_ >> 24) | (BROTLI_UNALIGNED_LOAD32LE(br->next_in) << 8);
+ br->bit_pos_ =
+ bit_pos ^ 24; /* here same as -= 24 because of the if condition */
+ br->avail_in -= 3;
+ br->next_in += 3;
+ }
+ } else {
+ uint32_t bit_pos = br->bit_pos_;
+ if (bit_pos >= 16) {
+ br->val_ = (br->val_ >> 16) |
+ (((uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in)) << 16);
+ br->bit_pos_ =
+ bit_pos ^ 16; /* here same as -= 16 because of the if condition */
+ br->avail_in -= BROTLI_SHORT_FILL_BIT_WINDOW_READ;
+ br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;
+ }
+ }
+#endif
+}
+
+/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no
+ more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */
+static BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {
+ BrotliFillBitWindow(br, 17);
+}
+
+/* Tries to pull one byte of input to accumulator.
+ Returns BROTLI_FALSE if there is no input available. */
+static BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {
+ if (br->avail_in == 0) {
+ return BROTLI_FALSE;
+ }
+ br->val_ >>= 8;
+#if (BROTLI_64_BITS)
+ br->val_ |= ((uint64_t)*br->next_in) << 56;
+#else
+ br->val_ |= ((uint32_t)*br->next_in) << 24;
+#endif
+ br->bit_pos_ -= 8;
+ --br->avail_in;
+ ++br->next_in;
+ return BROTLI_TRUE;
+}
+
+/* Returns currently available bits.
+ The number of valid bits could be calculated by BrotliGetAvailableBits. */
+static BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked(
+ BrotliBitReader* const br) {
+ return br->val_ >> br->bit_pos_;
+}
+
+/* Like BrotliGetBits, but does not mask the result.
+ The result contains at least 16 valid bits. */
+static BROTLI_INLINE uint32_t BrotliGet16BitsUnmasked(
+ BrotliBitReader* const br) {
+ BrotliFillBitWindow(br, 16);
+ return (uint32_t)BrotliGetBitsUnmasked(br);
+}
+
+/* Returns the specified number of bits from |br| without advancing bit
+ position. */
+static BROTLI_INLINE uint32_t BrotliGetBits(
+ BrotliBitReader* const br, uint32_t n_bits) {
+ BrotliFillBitWindow(br, n_bits);
+ return (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
+}
+
+/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there
+ is not enough input. */
+static BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ while (BrotliGetAvailableBits(br) < n_bits) {
+ if (!BrotliPullByte(br)) {
+ return BROTLI_FALSE;
+ }
+ }
+ *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
+ return BROTLI_TRUE;
+}
+
+/* Advances the bit pos by |n_bits|. */
+static BROTLI_INLINE void BrotliDropBits(
+ BrotliBitReader* const br, uint32_t n_bits) {
+ br->bit_pos_ += n_bits;
+}
+
+static BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {
+ uint32_t unused_bytes = BrotliGetAvailableBits(br) >> 3;
+ uint32_t unused_bits = unused_bytes << 3;
+ br->avail_in += unused_bytes;
+ br->next_in -= unused_bytes;
+ if (unused_bits == sizeof(br->val_) << 3) {
+ br->val_ = 0;
+ } else {
+ br->val_ <<= unused_bits;
+ }
+ br->bit_pos_ += unused_bits;
+}
+
+/* Reads the specified number of bits from |br| and advances the bit pos.
+ Precondition: accumulator MUST contain at least |n_bits|. */
+static BROTLI_INLINE void BrotliTakeBits(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ *val = (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(n_bits);
+ BROTLI_LOG(("[BrotliTakeBits] %d %d %d val: %6x\n",
+ (int)br->avail_in, (int)br->bit_pos_, (int)n_bits, (int)*val));
+ BrotliDropBits(br, n_bits);
+}
+
+/* Reads the specified number of bits from |br| and advances the bit pos.
+ Assumes that there is enough input to perform BrotliFillBitWindow.
+ Up to 24 bits are allowed to be requested from this method. */
+static BROTLI_INLINE uint32_t BrotliReadBits24(
+ BrotliBitReader* const br, uint32_t n_bits) {
+ BROTLI_DCHECK(n_bits <= 24);
+ if (BROTLI_64_BITS || (n_bits <= 16)) {
+ uint32_t val;
+ BrotliFillBitWindow(br, n_bits);
+ BrotliTakeBits(br, n_bits, &val);
+ return val;
+ } else {
+ uint32_t low_val;
+ uint32_t high_val;
+ BrotliFillBitWindow(br, 16);
+ BrotliTakeBits(br, 16, &low_val);
+ BrotliFillBitWindow(br, 8);
+ BrotliTakeBits(br, n_bits - 16, &high_val);
+ return low_val | (high_val << 16);
+ }
+}
+
+/* Same as BrotliReadBits24, but allows reading up to 32 bits. */
+static BROTLI_INLINE uint32_t BrotliReadBits32(
+ BrotliBitReader* const br, uint32_t n_bits) {
+ BROTLI_DCHECK(n_bits <= 32);
+ if (BROTLI_64_BITS || (n_bits <= 16)) {
+ uint32_t val;
+ BrotliFillBitWindow(br, n_bits);
+ BrotliTakeBits(br, n_bits, &val);
+ return val;
+ } else {
+ uint32_t low_val;
+ uint32_t high_val;
+ BrotliFillBitWindow(br, 16);
+ BrotliTakeBits(br, 16, &low_val);
+ BrotliFillBitWindow(br, 16);
+ BrotliTakeBits(br, n_bits - 16, &high_val);
+ return low_val | (high_val << 16);
+ }
+}
+
+/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there
+ is not enough input. |n_bits| MUST be positive.
+ Up to 24 bits are allowed to be requested from this method. */
+static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ BROTLI_DCHECK(n_bits <= 24);
+ while (BrotliGetAvailableBits(br) < n_bits) {
+ if (!BrotliPullByte(br)) {
+ return BROTLI_FALSE;
+ }
+ }
+ BrotliTakeBits(br, n_bits, val);
+ return BROTLI_TRUE;
+}
+
+/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */
+static BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ BROTLI_DCHECK(n_bits <= 32);
+ if (BROTLI_64_BITS || (n_bits <= 24)) {
+ while (BrotliGetAvailableBits(br) < n_bits) {
+ if (!BrotliPullByte(br)) {
+ return BROTLI_FALSE;
+ }
+ }
+ BrotliTakeBits(br, n_bits, val);
+ return BROTLI_TRUE;
+ } else {
+ return BrotliSafeReadBits32Slow(br, n_bits, val);
+ }
+}
+
+/* Advances the bit reader position to the next byte boundary and verifies
+ that any skipped bits are set to zero. */
+static BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {
+ uint32_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;
+ uint32_t pad_bits = 0;
+ if (pad_bits_count != 0) {
+ BrotliTakeBits(br, pad_bits_count, &pad_bits);
+ }
+ return TO_BROTLI_BOOL(pad_bits == 0);
+}
+
+/* Copies remaining input bytes stored in the bit reader to the output. Value
+ |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be
+ warmed up again after this. */
+static BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,
+ BrotliBitReader* br, size_t num) {
+ while (BrotliGetAvailableBits(br) >= 8 && num > 0) {
+ *dest = (uint8_t)BrotliGetBitsUnmasked(br);
+ BrotliDropBits(br, 8);
+ ++dest;
+ --num;
+ }
+ memcpy(dest, br->next_in, num);
+ br->avail_in -= num;
+ br->next_in += num;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_DEC_BIT_READER_H_ */
diff --git a/thirdparty/brotli/dec/decode.c b/thirdparty/brotli/dec/decode.c
new file mode 100644
index 0000000000..2fe58a7b2f
--- /dev/null
+++ b/thirdparty/brotli/dec/decode.c
@@ -0,0 +1,2802 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include <brotli/decode.h>
+
+#include <stdlib.h> /* free, malloc */
+#include <string.h> /* memcpy, memset */
+
+#include "../common/constants.h"
+#include "../common/context.h"
+#include "../common/dictionary.h"
+#include "../common/platform.h"
+#include "../common/shared_dictionary_internal.h"
+#include "../common/transform.h"
+#include "../common/version.h"
+#include "bit_reader.h"
+#include "huffman.h"
+#include "prefix.h"
+#include "state.h"
+
+#if defined(BROTLI_TARGET_NEON)
+#include <arm_neon.h>
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)
+
+#define BROTLI_LOG_UINT(name) \
+ BROTLI_LOG(("[%s] %s = %lu\n", __func__, #name, (unsigned long)(name)))
+#define BROTLI_LOG_ARRAY_INDEX(array_name, idx) \
+ BROTLI_LOG(("[%s] %s[%lu] = %lu\n", __func__, #array_name, \
+ (unsigned long)(idx), (unsigned long)array_name[idx]))
+
+#define HUFFMAN_TABLE_BITS 8U
+#define HUFFMAN_TABLE_MASK 0xFF
+
+/* We need the slack region for the following reasons:
+ - doing up to two 16-byte copies for fast backward copying
+ - inserting transformed dictionary word:
+ 255 prefix + 32 base + 255 suffix */
+static const uint32_t kRingBufferWriteAheadSlack = 542;
+
+static const uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {
+ 1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+};
+
+/* Static prefix code for the complex code length code lengths. */
+static const uint8_t kCodeLengthPrefixLength[16] = {
+ 2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4,
+};
+
+static const uint8_t kCodeLengthPrefixValue[16] = {
+ 0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,
+};
+
+BROTLI_BOOL BrotliDecoderSetParameter(
+ BrotliDecoderState* state, BrotliDecoderParameter p, uint32_t value) {
+ if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
+ switch (p) {
+ case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:
+ state->canny_ringbuffer_allocation = !!value ? 0 : 1;
+ return BROTLI_TRUE;
+
+ case BROTLI_DECODER_PARAM_LARGE_WINDOW:
+ state->large_window = TO_BROTLI_BOOL(!!value);
+ return BROTLI_TRUE;
+
+ default: return BROTLI_FALSE;
+ }
+}
+
+BrotliDecoderState* BrotliDecoderCreateInstance(
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
+ BrotliDecoderState* state = 0;
+ if (!alloc_func && !free_func) {
+ state = (BrotliDecoderState*)malloc(sizeof(BrotliDecoderState));
+ } else if (alloc_func && free_func) {
+ state = (BrotliDecoderState*)alloc_func(opaque, sizeof(BrotliDecoderState));
+ }
+ if (state == 0) {
+ BROTLI_DUMP();
+ return 0;
+ }
+ if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) {
+ BROTLI_DUMP();
+ if (!alloc_func && !free_func) {
+ free(state);
+ } else if (alloc_func && free_func) {
+ free_func(opaque, state);
+ }
+ return 0;
+ }
+ return state;
+}
+
+/* Deinitializes and frees BrotliDecoderState instance. */
+void BrotliDecoderDestroyInstance(BrotliDecoderState* state) {
+ if (!state) {
+ return;
+ } else {
+ brotli_free_func free_func = state->free_func;
+ void* opaque = state->memory_manager_opaque;
+ BrotliDecoderStateCleanup(state);
+ free_func(opaque, state);
+ }
+}
+
+/* Saves error code and converts it to BrotliDecoderResult. */
+static BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(
+ BrotliDecoderState* s, BrotliDecoderErrorCode e) {
+ s->error_code = (int)e;
+ switch (e) {
+ case BROTLI_DECODER_SUCCESS:
+ return BROTLI_DECODER_RESULT_SUCCESS;
+
+ case BROTLI_DECODER_NEEDS_MORE_INPUT:
+ return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
+
+ case BROTLI_DECODER_NEEDS_MORE_OUTPUT:
+ return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
+
+ default:
+ return BROTLI_DECODER_RESULT_ERROR;
+ }
+}
+
+/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for "Large Window Brotli".
+ Precondition: bit-reader accumulator has at least 8 bits. */
+static BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,
+ BrotliBitReader* br) {
+ uint32_t n;
+ BROTLI_BOOL large_window = s->large_window;
+ s->large_window = BROTLI_FALSE;
+ BrotliTakeBits(br, 1, &n);
+ if (n == 0) {
+ s->window_bits = 16;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ BrotliTakeBits(br, 3, &n);
+ if (n != 0) {
+ s->window_bits = 17 + n;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ BrotliTakeBits(br, 3, &n);
+ if (n == 1) {
+ if (large_window) {
+ BrotliTakeBits(br, 1, &n);
+ if (n == 1) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
+ }
+ s->large_window = BROTLI_TRUE;
+ return BROTLI_DECODER_SUCCESS;
+ } else {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
+ }
+ }
+ if (n != 0) {
+ s->window_bits = 8 + n;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ s->window_bits = 17;
+ return BROTLI_DECODER_SUCCESS;
+}
+
+static BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {
+#if defined(BROTLI_TARGET_NEON)
+ vst1q_u8(dst, vld1q_u8(src));
+#else
+ uint32_t buffer[4];
+ memcpy(buffer, src, 16);
+ memcpy(dst, buffer, 16);
+#endif
+}
+
+/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */
+static BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(
+ BrotliDecoderState* s, BrotliBitReader* br, uint32_t* value) {
+ uint32_t bits;
+ switch (s->substate_decode_uint8) {
+ case BROTLI_STATE_DECODE_UINT8_NONE:
+ if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits == 0) {
+ *value = 0;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_DECODE_UINT8_SHORT:
+ if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {
+ s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits == 0) {
+ *value = 1;
+ s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ /* Use output value as a temporary storage. It MUST be persisted. */
+ *value = bits;
+ /* Fall through. */
+
+ case BROTLI_STATE_DECODE_UINT8_LONG:
+ if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {
+ s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ *value = (1U << *value) + bits;
+ s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
+ return BROTLI_DECODER_SUCCESS;
+
+ default:
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
+ }
+}
+
+/* Decodes a metablock length and flags by reading 2 - 31 bits. */
+static BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(
+ BrotliDecoderState* s, BrotliBitReader* br) {
+ uint32_t bits;
+ int i;
+ for (;;) {
+ switch (s->substate_metablock_header) {
+ case BROTLI_STATE_METABLOCK_HEADER_NONE:
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ s->is_last_metablock = bits ? 1 : 0;
+ s->meta_block_remaining_len = 0;
+ s->is_uncompressed = 0;
+ s->is_metadata = 0;
+ if (!s->is_last_metablock) {
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
+ break;
+ }
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_EMPTY:
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits) {
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:
+ if (!BrotliSafeReadBits(br, 2, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ s->size_nibbles = (uint8_t)(bits + 4);
+ s->loop_counter = 0;
+ if (bits == 3) {
+ s->is_metadata = 1;
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED;
+ break;
+ }
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_SIZE:
+ i = s->loop_counter;
+ for (; i < (int)s->size_nibbles; ++i) {
+ if (!BrotliSafeReadBits(br, 4, &bits)) {
+ s->loop_counter = i;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&
+ bits == 0) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);
+ }
+ s->meta_block_remaining_len |= (int)(bits << (i * 4));
+ }
+ s->substate_metablock_header =
+ BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:
+ if (!s->is_last_metablock) {
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ s->is_uncompressed = bits ? 1 : 0;
+ }
+ ++s->meta_block_remaining_len;
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
+ return BROTLI_DECODER_SUCCESS;
+
+ case BROTLI_STATE_METABLOCK_HEADER_RESERVED:
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits != 0) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED);
+ }
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_BYTES:
+ if (!BrotliSafeReadBits(br, 2, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits == 0) {
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+ s->size_nibbles = (uint8_t)bits;
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER_METADATA:
+ i = s->loop_counter;
+ for (; i < (int)s->size_nibbles; ++i) {
+ if (!BrotliSafeReadBits(br, 8, &bits)) {
+ s->loop_counter = i;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&
+ bits == 0) {
+ return BROTLI_FAILURE(
+ BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);
+ }
+ s->meta_block_remaining_len |= (int)(bits << (i * 8));
+ }
+ ++s->meta_block_remaining_len;
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
+ return BROTLI_DECODER_SUCCESS;
+
+ default:
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
+ }
+ }
+}
+
+/* Decodes the Huffman code.
+ This method doesn't read data from the bit reader, BUT drops the amount of
+ bits that correspond to the decoded symbol.
+ bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */
+static BROTLI_INLINE uint32_t DecodeSymbol(uint32_t bits,
+ const HuffmanCode* table,
+ BrotliBitReader* br) {
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);
+ if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {
+ uint32_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;
+ BrotliDropBits(br, HUFFMAN_TABLE_BITS);
+ BROTLI_HC_ADJUST_TABLE_INDEX(table,
+ BROTLI_HC_FAST_LOAD_VALUE(table) +
+ ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));
+ }
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
+ return BROTLI_HC_FAST_LOAD_VALUE(table);
+}
+
+/* Reads and decodes the next Huffman code from bit-stream.
+ This method peeks 16 bits of input and drops 0 - 15 of them. */
+static BROTLI_INLINE uint32_t ReadSymbol(const HuffmanCode* table,
+ BrotliBitReader* br) {
+ return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br);
+}
+
+/* Same as DecodeSymbol, but it is known that there is less than 15 bits of
+ input are currently available. */
+static BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(
+ const HuffmanCode* table, BrotliBitReader* br, uint32_t* result) {
+ uint32_t val;
+ uint32_t available_bits = BrotliGetAvailableBits(br);
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
+ if (available_bits == 0) {
+ if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
+ return BROTLI_TRUE;
+ }
+ return BROTLI_FALSE; /* No valid bits at all. */
+ }
+ val = (uint32_t)BrotliGetBitsUnmasked(br);
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);
+ if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {
+ if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
+ return BROTLI_TRUE;
+ } else {
+ return BROTLI_FALSE; /* Not enough bits for the first level. */
+ }
+ }
+ if (available_bits <= HUFFMAN_TABLE_BITS) {
+ return BROTLI_FALSE; /* Not enough bits to move to the second level. */
+ }
+
+ /* Speculatively drop HUFFMAN_TABLE_BITS. */
+ val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;
+ available_bits -= HUFFMAN_TABLE_BITS;
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);
+ if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {
+ return BROTLI_FALSE; /* Not enough bits for the second level. */
+ }
+
+ BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));
+ *result = BROTLI_HC_FAST_LOAD_VALUE(table);
+ return BROTLI_TRUE;
+}
+
+static BROTLI_INLINE BROTLI_BOOL SafeReadSymbol(
+ const HuffmanCode* table, BrotliBitReader* br, uint32_t* result) {
+ uint32_t val;
+ if (BROTLI_PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) {
+ *result = DecodeSymbol(val, table, br);
+ return BROTLI_TRUE;
+ }
+ return SafeDecodeSymbol(table, br, result);
+}
+
+/* Makes a look-up in first level Huffman table. Peeks 8 bits. */
+static BROTLI_INLINE void PreloadSymbol(int safe,
+ const HuffmanCode* table,
+ BrotliBitReader* br,
+ uint32_t* bits,
+ uint32_t* value) {
+ if (safe) {
+ return;
+ }
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
+ BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));
+ *bits = BROTLI_HC_FAST_LOAD_BITS(table);
+ *value = BROTLI_HC_FAST_LOAD_VALUE(table);
+}
+
+/* Decodes the next Huffman code using data prepared by PreloadSymbol.
+ Reads 0 - 15 bits. Also peeks 8 following bits. */
+static BROTLI_INLINE uint32_t ReadPreloadedSymbol(const HuffmanCode* table,
+ BrotliBitReader* br,
+ uint32_t* bits,
+ uint32_t* value) {
+ uint32_t result = *value;
+ if (BROTLI_PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) {
+ uint32_t val = BrotliGet16BitsUnmasked(br);
+ const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;
+ uint32_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);
+ BrotliDropBits(br, HUFFMAN_TABLE_BITS);
+ BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));
+ result = BROTLI_HC_FAST_LOAD_VALUE(ext);
+ } else {
+ BrotliDropBits(br, *bits);
+ }
+ PreloadSymbol(0, table, br, bits, value);
+ return result;
+}
+
+static BROTLI_INLINE uint32_t Log2Floor(uint32_t x) {
+ uint32_t result = 0;
+ while (x) {
+ x >>= 1;
+ ++result;
+ }
+ return result;
+}
+
+/* Reads (s->symbol + 1) symbols.
+ Totally 1..4 symbols are read, 1..11 bits each.
+ The list of symbols MUST NOT contain duplicates. */
+static BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(
+ uint32_t alphabet_size_max, uint32_t alphabet_size_limit,
+ BrotliDecoderState* s) {
+ /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */
+ BrotliBitReader* br = &s->br;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ uint32_t max_bits = Log2Floor(alphabet_size_max - 1);
+ uint32_t i = h->sub_loop_counter;
+ uint32_t num_symbols = h->symbol;
+ while (i <= num_symbols) {
+ uint32_t v;
+ if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {
+ h->sub_loop_counter = i;
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (v >= alphabet_size_limit) {
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);
+ }
+ h->symbols_lists_array[i] = (uint16_t)v;
+ BROTLI_LOG_UINT(h->symbols_lists_array[i]);
+ ++i;
+ }
+
+ for (i = 0; i < num_symbols; ++i) {
+ uint32_t k = i + 1;
+ for (; k <= num_symbols; ++k) {
+ if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);
+ }
+ }
+ }
+
+ return BROTLI_DECODER_SUCCESS;
+}
+
+/* Process single decoded symbol code length:
+ A) reset the repeat variable
+ B) remember code length (if it is not 0)
+ C) extend corresponding index-chain
+ D) reduce the Huffman space
+ E) update the histogram */
+static BROTLI_INLINE void ProcessSingleCodeLength(uint32_t code_len,
+ uint32_t* symbol, uint32_t* repeat, uint32_t* space,
+ uint32_t* prev_code_len, uint16_t* symbol_lists,
+ uint16_t* code_length_histo, int* next_symbol) {
+ *repeat = 0;
+ if (code_len != 0) { /* code_len == 1..15 */
+ symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);
+ next_symbol[code_len] = (int)(*symbol);
+ *prev_code_len = code_len;
+ *space -= 32768U >> code_len;
+ code_length_histo[code_len]++;
+ BROTLI_LOG(("[ReadHuffmanCode] code_length[%d] = %d\n",
+ (int)*symbol, (int)code_len));
+ }
+ (*symbol)++;
+}
+
+/* Process repeated symbol code length.
+ A) Check if it is the extension of previous repeat sequence; if the decoded
+ value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new
+ symbol-skip
+ B) Update repeat variable
+ C) Check if operation is feasible (fits alphabet)
+ D) For each symbol do the same operations as in ProcessSingleCodeLength
+
+ PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or
+ code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */
+static BROTLI_INLINE void ProcessRepeatedCodeLength(uint32_t code_len,
+ uint32_t repeat_delta, uint32_t alphabet_size, uint32_t* symbol,
+ uint32_t* repeat, uint32_t* space, uint32_t* prev_code_len,
+ uint32_t* repeat_code_len, uint16_t* symbol_lists,
+ uint16_t* code_length_histo, int* next_symbol) {
+ uint32_t old_repeat;
+ uint32_t extra_bits = 3; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */
+ uint32_t new_len = 0; /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */
+ if (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
+ new_len = *prev_code_len;
+ extra_bits = 2;
+ }
+ if (*repeat_code_len != new_len) {
+ *repeat = 0;
+ *repeat_code_len = new_len;
+ }
+ old_repeat = *repeat;
+ if (*repeat > 0) {
+ *repeat -= 2;
+ *repeat <<= extra_bits;
+ }
+ *repeat += repeat_delta + 3U;
+ repeat_delta = *repeat - old_repeat;
+ if (*symbol + repeat_delta > alphabet_size) {
+ BROTLI_DUMP();
+ *symbol = alphabet_size;
+ *space = 0xFFFFF;
+ return;
+ }
+ BROTLI_LOG(("[ReadHuffmanCode] code_length[%d..%d] = %d\n",
+ (int)*symbol, (int)(*symbol + repeat_delta - 1), (int)*repeat_code_len));
+ if (*repeat_code_len != 0) {
+ unsigned last = *symbol + repeat_delta;
+ int next = next_symbol[*repeat_code_len];
+ do {
+ symbol_lists[next] = (uint16_t)*symbol;
+ next = (int)*symbol;
+ } while (++(*symbol) != last);
+ next_symbol[*repeat_code_len] = next;
+ *space -= repeat_delta << (15 - *repeat_code_len);
+ code_length_histo[*repeat_code_len] =
+ (uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta);
+ } else {
+ *symbol += repeat_delta;
+ }
+}
+
+/* Reads and decodes symbol codelengths. */
+static BrotliDecoderErrorCode ReadSymbolCodeLengths(
+ uint32_t alphabet_size, BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ uint32_t symbol = h->symbol;
+ uint32_t repeat = h->repeat;
+ uint32_t space = h->space;
+ uint32_t prev_code_len = h->prev_code_len;
+ uint32_t repeat_code_len = h->repeat_code_len;
+ uint16_t* symbol_lists = h->symbol_lists;
+ uint16_t* code_length_histo = h->code_length_histo;
+ int* next_symbol = h->next_symbol;
+ if (!BrotliWarmupBitReader(br)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ while (symbol < alphabet_size && space > 0) {
+ const HuffmanCode* p = h->table;
+ uint32_t code_len;
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
+ if (!BrotliCheckInputAmount(br, BROTLI_SHORT_FILL_BIT_WINDOW_READ)) {
+ h->symbol = symbol;
+ h->repeat = repeat;
+ h->prev_code_len = prev_code_len;
+ h->repeat_code_len = repeat_code_len;
+ h->space = space;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ BrotliFillBitWindow16(br);
+ BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &
+ BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p)); /* Use 1..5 bits. */
+ code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
+ if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
+ ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,
+ &prev_code_len, symbol_lists, code_length_histo, next_symbol);
+ } else { /* code_len == 16..17, extra_bits == 2..3 */
+ uint32_t extra_bits =
+ (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3;
+ uint32_t repeat_delta =
+ (uint32_t)BrotliGetBitsUnmasked(br) & BitMask(extra_bits);
+ BrotliDropBits(br, extra_bits);
+ ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
+ &symbol, &repeat, &space, &prev_code_len, &repeat_code_len,
+ symbol_lists, code_length_histo, next_symbol);
+ }
+ }
+ h->space = space;
+ return BROTLI_DECODER_SUCCESS;
+}
+
+static BrotliDecoderErrorCode SafeReadSymbolCodeLengths(
+ uint32_t alphabet_size, BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ BROTLI_BOOL get_byte = BROTLI_FALSE;
+ while (h->symbol < alphabet_size && h->space > 0) {
+ const HuffmanCode* p = h->table;
+ uint32_t code_len;
+ uint32_t available_bits;
+ uint32_t bits = 0;
+ BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);
+ if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ get_byte = BROTLI_FALSE;
+ available_bits = BrotliGetAvailableBits(br);
+ if (available_bits != 0) {
+ bits = (uint32_t)BrotliGetBitsUnmasked(br);
+ }
+ BROTLI_HC_ADJUST_TABLE_INDEX(p,
+ bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));
+ if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {
+ get_byte = BROTLI_TRUE;
+ continue;
+ }
+ code_len = BROTLI_HC_FAST_LOAD_VALUE(p); /* code_len == 0..17 */
+ if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));
+ ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,
+ &h->prev_code_len, h->symbol_lists, h->code_length_histo,
+ h->next_symbol);
+ } else { /* code_len == 16..17, extra_bits == 2..3 */
+ uint32_t extra_bits = code_len - 14U;
+ uint32_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &
+ BitMask(extra_bits);
+ if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {
+ get_byte = BROTLI_TRUE;
+ continue;
+ }
+ BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);
+ ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,
+ &h->symbol, &h->repeat, &h->space, &h->prev_code_len,
+ &h->repeat_code_len, h->symbol_lists, h->code_length_histo,
+ h->next_symbol);
+ }
+ }
+ return BROTLI_DECODER_SUCCESS;
+}
+
+/* Reads and decodes 15..18 codes using static prefix code.
+ Each code is 2..4 bits long. In total 30..72 bits are used. */
+static BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ uint32_t num_codes = h->repeat;
+ unsigned space = h->space;
+ uint32_t i = h->sub_loop_counter;
+ for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {
+ const uint8_t code_len_idx = kCodeLengthCodeOrder[i];
+ uint32_t ix;
+ uint32_t v;
+ if (BROTLI_PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) {
+ uint32_t available_bits = BrotliGetAvailableBits(br);
+ if (available_bits != 0) {
+ ix = BrotliGetBitsUnmasked(br) & 0xF;
+ } else {
+ ix = 0;
+ }
+ if (kCodeLengthPrefixLength[ix] > available_bits) {
+ h->sub_loop_counter = i;
+ h->repeat = num_codes;
+ h->space = space;
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ }
+ v = kCodeLengthPrefixValue[ix];
+ BrotliDropBits(br, kCodeLengthPrefixLength[ix]);
+ h->code_length_code_lengths[code_len_idx] = (uint8_t)v;
+ BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);
+ if (v != 0) {
+ space = space - (32U >> v);
+ ++num_codes;
+ ++h->code_length_histo[v];
+ if (space - 1U >= 32U) {
+ /* space is 0 or wrapped around. */
+ break;
+ }
+ }
+ }
+ if (!(num_codes == 1 || space == 0)) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CL_SPACE);
+ }
+ return BROTLI_DECODER_SUCCESS;
+}
+
+/* Decodes the Huffman tables.
+ There are 2 scenarios:
+ A) Huffman code contains only few symbols (1..4). Those symbols are read
+ directly; their code lengths are defined by the number of symbols.
+ For this scenario 4 - 49 bits will be read.
+
+ B) 2-phase decoding:
+ B.1) Small Huffman table is decoded; it is specified with code lengths
+ encoded with predefined entropy code. 32 - 74 bits are used.
+ B.2) Decoded table is used to decode code lengths of symbols in resulting
+ Huffman table. In worst case 3520 bits are read. */
+static BrotliDecoderErrorCode ReadHuffmanCode(uint32_t alphabet_size_max,
+ uint32_t alphabet_size_limit,
+ HuffmanCode* table,
+ uint32_t* opt_table_size,
+ BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ /* State machine. */
+ for (;;) {
+ switch (h->substate_huffman) {
+ case BROTLI_STATE_HUFFMAN_NONE:
+ if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ BROTLI_LOG_UINT(h->sub_loop_counter);
+ /* The value is used as follows:
+ 1 for simple code;
+ 0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */
+ if (h->sub_loop_counter != 1) {
+ h->space = 32;
+ h->repeat = 0; /* num_codes */
+ memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *
+ (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));
+ memset(&h->code_length_code_lengths[0], 0,
+ sizeof(h->code_length_code_lengths));
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;
+ continue;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:
+ /* Read symbols, codes & code lengths directly. */
+ if (!BrotliSafeReadBits(br, 2, &h->symbol)) { /* num_symbols */
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ h->sub_loop_counter = 0;
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {
+ BrotliDecoderErrorCode result =
+ ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ return result;
+ }
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {
+ uint32_t table_size;
+ if (h->symbol == 3) {
+ uint32_t bits;
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ h->symbol += bits;
+ }
+ BROTLI_LOG_UINT(h->symbol);
+ table_size = BrotliBuildSimpleHuffmanTable(
+ table, HUFFMAN_TABLE_BITS, h->symbols_lists_array, h->symbol);
+ if (opt_table_size) {
+ *opt_table_size = table_size;
+ }
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+
+ /* Decode Huffman-coded code lengths. */
+ case BROTLI_STATE_HUFFMAN_COMPLEX: {
+ uint32_t i;
+ BrotliDecoderErrorCode result = ReadCodeLengthCodeLengths(s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ return result;
+ }
+ BrotliBuildCodeLengthsHuffmanTable(h->table,
+ h->code_length_code_lengths,
+ h->code_length_histo);
+ memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));
+ for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {
+ h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
+ h->symbol_lists[h->next_symbol[i]] = 0xFFFF;
+ }
+
+ h->symbol = 0;
+ h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;
+ h->repeat = 0;
+ h->repeat_code_len = 0;
+ h->space = 32768;
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {
+ uint32_t table_size;
+ BrotliDecoderErrorCode result = ReadSymbolCodeLengths(
+ alphabet_size_limit, s);
+ if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
+ result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);
+ }
+ if (result != BROTLI_DECODER_SUCCESS) {
+ return result;
+ }
+
+ if (h->space != 0) {
+ BROTLI_LOG(("[ReadHuffmanCode] space = %d\n", (int)h->space));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);
+ }
+ table_size = BrotliBuildHuffmanTable(
+ table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);
+ if (opt_table_size) {
+ *opt_table_size = table_size;
+ }
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+
+ default:
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
+ }
+ }
+}
+
+/* Decodes a block length by reading 3..39 bits. */
+static BROTLI_INLINE uint32_t ReadBlockLength(const HuffmanCode* table,
+ BrotliBitReader* br) {
+ uint32_t code;
+ uint32_t nbits;
+ code = ReadSymbol(table, br);
+ nbits = _kBrotliPrefixCodeRanges[code].nbits; /* nbits == 2..24 */
+ return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);
+}
+
+/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then
+ reading can't be continued with ReadBlockLength. */
+static BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(
+ BrotliDecoderState* s, uint32_t* result, const HuffmanCode* table,
+ BrotliBitReader* br) {
+ uint32_t index;
+ if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) {
+ if (!SafeReadSymbol(table, br, &index)) {
+ return BROTLI_FALSE;
+ }
+ } else {
+ index = s->block_length_index;
+ }
+ {
+ uint32_t bits;
+ uint32_t nbits = _kBrotliPrefixCodeRanges[index].nbits;
+ uint32_t offset = _kBrotliPrefixCodeRanges[index].offset;
+ if (!BrotliSafeReadBits(br, nbits, &bits)) {
+ s->block_length_index = index;
+ s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;
+ return BROTLI_FALSE;
+ }
+ *result = offset + bits;
+ s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
+ return BROTLI_TRUE;
+ }
+}
+
+/* Transform:
+ 1) initialize list L with values 0, 1,... 255
+ 2) For each input element X:
+ 2.1) let Y = L[X]
+ 2.2) remove X-th element from L
+ 2.3) prepend Y to L
+ 2.4) append Y to output
+
+ In most cases max(Y) <= 7, so most of L remains intact.
+ To reduce the cost of initialization, we reuse L, remember the upper bound
+ of Y values, and reinitialize only first elements in L.
+
+ Most of input values are 0 and 1. To reduce number of branches, we replace
+ inner for loop with do-while. */
+static BROTLI_NOINLINE void InverseMoveToFrontTransform(
+ uint8_t* v, uint32_t v_len, BrotliDecoderState* state) {
+ /* Reinitialize elements that could have been changed. */
+ uint32_t i = 1;
+ uint32_t upper_bound = state->mtf_upper_bound;
+ uint32_t* mtf = &state->mtf[1]; /* Make mtf[-1] addressable. */
+ uint8_t* mtf_u8 = (uint8_t*)mtf;
+ /* Load endian-aware constant. */
+ const uint8_t b0123[4] = {0, 1, 2, 3};
+ uint32_t pattern;
+ memcpy(&pattern, &b0123, 4);
+
+ /* Initialize list using 4 consequent values pattern. */
+ mtf[0] = pattern;
+ do {
+ pattern += 0x04040404; /* Advance all 4 values by 4. */
+ mtf[i] = pattern;
+ i++;
+ } while (i <= upper_bound);
+
+ /* Transform the input. */
+ upper_bound = 0;
+ for (i = 0; i < v_len; ++i) {
+ int index = v[i];
+ uint8_t value = mtf_u8[index];
+ upper_bound |= v[i];
+ v[i] = value;
+ mtf_u8[-1] = value;
+ do {
+ index--;
+ mtf_u8[index + 1] = mtf_u8[index];
+ } while (index >= 0);
+ }
+ /* Remember amount of elements to be reinitialized. */
+ state->mtf_upper_bound = upper_bound >> 2;
+}
+
+/* Decodes a series of Huffman table using ReadHuffmanCode function. */
+static BrotliDecoderErrorCode HuffmanTreeGroupDecode(
+ HuffmanTreeGroup* group, BrotliDecoderState* s) {
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {
+ h->next = group->codes;
+ h->htree_index = 0;
+ h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;
+ }
+ while (h->htree_index < group->num_htrees) {
+ uint32_t table_size;
+ BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,
+ group->alphabet_size_limit, h->next, &table_size, s);
+ if (result != BROTLI_DECODER_SUCCESS) return result;
+ group->htrees[h->htree_index] = h->next;
+ h->next += table_size;
+ ++h->htree_index;
+ }
+ h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
+ return BROTLI_DECODER_SUCCESS;
+}
+
+/* Decodes a context map.
+ Decoding is done in 4 phases:
+ 1) Read auxiliary information (6..16 bits) and allocate memory.
+ In case of trivial context map, decoding is finished at this phase.
+ 2) Decode Huffman table using ReadHuffmanCode function.
+ This table will be used for reading context map items.
+ 3) Read context map items; "0" values could be run-length encoded.
+ 4) Optionally, apply InverseMoveToFront transform to the resulting map. */
+static BrotliDecoderErrorCode DecodeContextMap(uint32_t context_map_size,
+ uint32_t* num_htrees,
+ uint8_t** context_map_arg,
+ BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+
+ switch ((int)h->substate_context_map) {
+ case BROTLI_STATE_CONTEXT_MAP_NONE:
+ result = DecodeVarLenUint8(s, br, num_htrees);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ return result;
+ }
+ (*num_htrees)++;
+ h->context_index = 0;
+ BROTLI_LOG_UINT(context_map_size);
+ BROTLI_LOG_UINT(*num_htrees);
+ *context_map_arg =
+ (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size);
+ if (*context_map_arg == 0) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);
+ }
+ if (*num_htrees <= 1) {
+ memset(*context_map_arg, 0, (size_t)context_map_size);
+ return BROTLI_DECODER_SUCCESS;
+ }
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {
+ uint32_t bits;
+ /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe
+ to peek 4 bits ahead. */
+ if (!BrotliSafeGetBits(br, 5, &bits)) {
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if ((bits & 1) != 0) { /* Use RLE for zeros. */
+ h->max_run_length_prefix = (bits >> 1) + 1;
+ BrotliDropBits(br, 5);
+ } else {
+ h->max_run_length_prefix = 0;
+ BrotliDropBits(br, 1);
+ }
+ BROTLI_LOG_UINT(h->max_run_length_prefix);
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {
+ uint32_t alphabet_size = *num_htrees + h->max_run_length_prefix;
+ result = ReadHuffmanCode(alphabet_size, alphabet_size,
+ h->context_map_table, NULL, s);
+ if (result != BROTLI_DECODER_SUCCESS) return result;
+ h->code = 0xFFFF;
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_DECODE: {
+ uint32_t context_index = h->context_index;
+ uint32_t max_run_length_prefix = h->max_run_length_prefix;
+ uint8_t* context_map = *context_map_arg;
+ uint32_t code = h->code;
+ BROTLI_BOOL skip_preamble = (code != 0xFFFF);
+ while (context_index < context_map_size || skip_preamble) {
+ if (!skip_preamble) {
+ if (!SafeReadSymbol(h->context_map_table, br, &code)) {
+ h->code = 0xFFFF;
+ h->context_index = context_index;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ BROTLI_LOG_UINT(code);
+
+ if (code == 0) {
+ context_map[context_index++] = 0;
+ continue;
+ }
+ if (code > max_run_length_prefix) {
+ context_map[context_index++] =
+ (uint8_t)(code - max_run_length_prefix);
+ continue;
+ }
+ } else {
+ skip_preamble = BROTLI_FALSE;
+ }
+ /* RLE sub-stage. */
+ {
+ uint32_t reps;
+ if (!BrotliSafeReadBits(br, code, &reps)) {
+ h->code = code;
+ h->context_index = context_index;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ reps += 1U << code;
+ BROTLI_LOG_UINT(reps);
+ if (context_index + reps > context_map_size) {
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT);
+ }
+ do {
+ context_map[context_index++] = 0;
+ } while (--reps);
+ }
+ }
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {
+ uint32_t bits;
+ if (!BrotliSafeReadBits(br, 1, &bits)) {
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ if (bits != 0) {
+ InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);
+ }
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
+ return BROTLI_DECODER_SUCCESS;
+ }
+
+ default:
+ return
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
+ }
+}
+
+/* Decodes a command or literal and updates block type ring-buffer.
+ Reads 3..54 bits. */
+static BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(
+ int safe, BrotliDecoderState* s, int tree_type) {
+ uint32_t max_block_type = s->num_block_types[tree_type];
+ const HuffmanCode* type_tree = &s->block_type_trees[
+ tree_type * BROTLI_HUFFMAN_MAX_SIZE_258];
+ const HuffmanCode* len_tree = &s->block_len_trees[
+ tree_type * BROTLI_HUFFMAN_MAX_SIZE_26];
+ BrotliBitReader* br = &s->br;
+ uint32_t* ringbuffer = &s->block_type_rb[tree_type * 2];
+ uint32_t block_type;
+ if (max_block_type <= 1) {
+ return BROTLI_FALSE;
+ }
+
+ /* Read 0..15 + 3..39 bits. */
+ if (!safe) {
+ block_type = ReadSymbol(type_tree, br);
+ s->block_length[tree_type] = ReadBlockLength(len_tree, br);
+ } else {
+ BrotliBitReaderState memento;
+ BrotliBitReaderSaveState(br, &memento);
+ if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;
+ if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {
+ s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
+ BrotliBitReaderRestoreState(br, &memento);
+ return BROTLI_FALSE;
+ }
+ }
+
+ if (block_type == 1) {
+ block_type = ringbuffer[1] + 1;
+ } else if (block_type == 0) {
+ block_type = ringbuffer[0];
+ } else {
+ block_type -= 2;
+ }
+ if (block_type >= max_block_type) {
+ block_type -= max_block_type;
+ }
+ ringbuffer[0] = ringbuffer[1];
+ ringbuffer[1] = block_type;
+ return BROTLI_TRUE;
+}
+
+static BROTLI_INLINE void DetectTrivialLiteralBlockTypes(
+ BrotliDecoderState* s) {
+ size_t i;
+ for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;
+ for (i = 0; i < s->num_block_types[0]; i++) {
+ size_t offset = i << BROTLI_LITERAL_CONTEXT_BITS;
+ size_t error = 0;
+ size_t sample = s->context_map[offset];
+ size_t j;
+ for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) {
+ BROTLI_REPEAT(4, error |= s->context_map[offset + j++] ^ sample;)
+ }
+ if (error == 0) {
+ s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);
+ }
+ }
+}
+
+static BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {
+ uint8_t context_mode;
+ size_t trivial;
+ uint32_t block_type = s->block_type_rb[1];
+ uint32_t context_offset = block_type << BROTLI_LITERAL_CONTEXT_BITS;
+ s->context_map_slice = s->context_map + context_offset;
+ trivial = s->trivial_literal_contexts[block_type >> 5];
+ s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;
+ s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];
+ context_mode = s->context_modes[block_type] & 3;
+ s->context_lookup = BROTLI_CONTEXT_LUT(context_mode);
+}
+
+/* Decodes the block type and updates the state for literal context.
+ Reads 3..54 bits. */
+static BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+ if (!DecodeBlockTypeAndLength(safe, s, 0)) {
+ return BROTLI_FALSE;
+ }
+ PrepareLiteralDecoding(s);
+ return BROTLI_TRUE;
+}
+
+static void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {
+ DecodeLiteralBlockSwitchInternal(0, s);
+}
+
+static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(
+ BrotliDecoderState* s) {
+ return DecodeLiteralBlockSwitchInternal(1, s);
+}
+
+/* Block switch for insert/copy length.
+ Reads 3..54 bits. */
+static BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+ if (!DecodeBlockTypeAndLength(safe, s, 1)) {
+ return BROTLI_FALSE;
+ }
+ s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];
+ return BROTLI_TRUE;
+}
+
+static void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {
+ DecodeCommandBlockSwitchInternal(0, s);
+}
+
+static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(
+ BrotliDecoderState* s) {
+ return DecodeCommandBlockSwitchInternal(1, s);
+}
+
+/* Block switch for distance codes.
+ Reads 3..54 bits. */
+static BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(
+ int safe, BrotliDecoderState* s) {
+ if (!DecodeBlockTypeAndLength(safe, s, 2)) {
+ return BROTLI_FALSE;
+ }
+ s->dist_context_map_slice = s->dist_context_map +
+ (s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);
+ s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
+ return BROTLI_TRUE;
+}
+
+static void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {
+ DecodeDistanceBlockSwitchInternal(0, s);
+}
+
+static BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(
+ BrotliDecoderState* s) {
+ return DecodeDistanceBlockSwitchInternal(1, s);
+}
+
+static size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {
+ size_t pos = wrap && s->pos > s->ringbuffer_size ?
+ (size_t)s->ringbuffer_size : (size_t)(s->pos);
+ size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;
+ return partial_pos_rb - s->partial_pos_out;
+}
+
+/* Dumps output.
+ Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push
+ and either ring-buffer is as big as window size, or |force| is true. */
+static BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(
+ BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,
+ size_t* total_out, BROTLI_BOOL force) {
+ uint8_t* start =
+ s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);
+ size_t to_write = UnwrittenBytes(s, BROTLI_TRUE);
+ size_t num_written = *available_out;
+ if (num_written > to_write) {
+ num_written = to_write;
+ }
+ if (s->meta_block_remaining_len < 0) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1);
+ }
+ if (next_out && !*next_out) {
+ *next_out = start;
+ } else {
+ if (next_out) {
+ memcpy(*next_out, start, num_written);
+ *next_out += num_written;
+ }
+ }
+ *available_out -= num_written;
+ BROTLI_LOG_UINT(to_write);
+ BROTLI_LOG_UINT(num_written);
+ s->partial_pos_out += num_written;
+ if (total_out) {
+ *total_out = s->partial_pos_out;
+ }
+ if (num_written < to_write) {
+ if (s->ringbuffer_size == (1 << s->window_bits) || force) {
+ return BROTLI_DECODER_NEEDS_MORE_OUTPUT;
+ } else {
+ return BROTLI_DECODER_SUCCESS;
+ }
+ }
+ /* Wrap ring buffer only if it has reached its maximal size. */
+ if (s->ringbuffer_size == (1 << s->window_bits) &&
+ s->pos >= s->ringbuffer_size) {
+ s->pos -= s->ringbuffer_size;
+ s->rb_roundtrips++;
+ s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0;
+ }
+ return BROTLI_DECODER_SUCCESS;
+}
+
+static void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {
+ if (s->should_wrap_ringbuffer) {
+ memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);
+ s->should_wrap_ringbuffer = 0;
+ }
+}
+
+/* Allocates ring-buffer.
+
+ s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before
+ this function is called.
+
+ Last two bytes of ring-buffer are initialized to 0, so context calculation
+ could be done uniformly for the first two and all other positions. */
+static BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(
+ BrotliDecoderState* s) {
+ uint8_t* old_ringbuffer = s->ringbuffer;
+ if (s->ringbuffer_size == s->new_ringbuffer_size) {
+ return BROTLI_TRUE;
+ }
+
+ s->ringbuffer = (uint8_t*)BROTLI_DECODER_ALLOC(s,
+ (size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack);
+ if (s->ringbuffer == 0) {
+ /* Restore previous value. */
+ s->ringbuffer = old_ringbuffer;
+ return BROTLI_FALSE;
+ }
+ s->ringbuffer[s->new_ringbuffer_size - 2] = 0;
+ s->ringbuffer[s->new_ringbuffer_size - 1] = 0;
+
+ if (!!old_ringbuffer) {
+ memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);
+ BROTLI_DECODER_FREE(s, old_ringbuffer);
+ }
+
+ s->ringbuffer_size = s->new_ringbuffer_size;
+ s->ringbuffer_mask = s->new_ringbuffer_size - 1;
+ s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;
+
+ return BROTLI_TRUE;
+}
+
+static BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(
+ size_t* available_out, uint8_t** next_out, size_t* total_out,
+ BrotliDecoderState* s) {
+ /* TODO(eustas): avoid allocation for single uncompressed block. */
+ if (!BrotliEnsureRingBuffer(s)) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);
+ }
+
+ /* State machine */
+ for (;;) {
+ switch (s->substate_uncompressed) {
+ case BROTLI_STATE_UNCOMPRESSED_NONE: {
+ int nbytes = (int)BrotliGetRemainingBytes(&s->br);
+ if (nbytes > s->meta_block_remaining_len) {
+ nbytes = s->meta_block_remaining_len;
+ }
+ if (s->pos + nbytes > s->ringbuffer_size) {
+ nbytes = s->ringbuffer_size - s->pos;
+ }
+ /* Copy remaining bytes from s->br.buf_ to ring-buffer. */
+ BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);
+ s->pos += nbytes;
+ s->meta_block_remaining_len -= nbytes;
+ if (s->pos < 1 << s->window_bits) {
+ if (s->meta_block_remaining_len == 0) {
+ return BROTLI_DECODER_SUCCESS;
+ }
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_UNCOMPRESSED_WRITE: {
+ BrotliDecoderErrorCode result;
+ result = WriteRingBuffer(
+ s, available_out, next_out, total_out, BROTLI_FALSE);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ return result;
+ }
+ if (s->ringbuffer_size == 1 << s->window_bits) {
+ s->max_distance = s->max_backward_distance;
+ }
+ s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
+ break;
+ }
+ }
+ }
+ BROTLI_DCHECK(0); /* Unreachable */
+}
+
+static BROTLI_BOOL AttachCompoundDictionary(
+ BrotliDecoderState* state, const uint8_t* data, size_t size) {
+ BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
+ if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
+ if (!addon) {
+ addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC(
+ state, sizeof(BrotliDecoderCompoundDictionary));
+ if (!addon) return BROTLI_FALSE;
+ addon->num_chunks = 0;
+ addon->total_size = 0;
+ addon->br_length = 0;
+ addon->br_copied = 0;
+ addon->block_bits = -1;
+ addon->chunk_offsets[0] = 0;
+ state->compound_dictionary = addon;
+ }
+ if (addon->num_chunks == 15) return BROTLI_FALSE;
+ addon->chunks[addon->num_chunks] = data;
+ addon->num_chunks++;
+ addon->total_size += (int)size;
+ addon->chunk_offsets[addon->num_chunks] = addon->total_size;
+ return BROTLI_TRUE;
+}
+
+static void EnsureCoumpoundDictionaryInitialized(BrotliDecoderState* state) {
+ BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;
+ /* 256 = (1 << 8) slots in block map. */
+ int block_bits = 8;
+ int cursor = 0;
+ int index = 0;
+ if (addon->block_bits != -1) return;
+ while (((addon->total_size - 1) >> block_bits) != 0) block_bits++;
+ block_bits -= 8;
+ addon->block_bits = block_bits;
+ while (cursor < addon->total_size) {
+ while (addon->chunk_offsets[index + 1] < cursor) index++;
+ addon->block_map[cursor >> block_bits] = (uint8_t)index;
+ cursor += 1 << block_bits;
+ }
+}
+
+static BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState* s,
+ int address, int length) {
+ BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
+ int index;
+ EnsureCoumpoundDictionaryInitialized(s);
+ index = addon->block_map[address >> addon->block_bits];
+ while (address >= addon->chunk_offsets[index + 1]) index++;
+ if (addon->total_size < address + length) return BROTLI_FALSE;
+ /* Update the recent distances cache. */
+ s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
+ ++s->dist_rb_idx;
+ s->meta_block_remaining_len -= length;
+ addon->br_index = index;
+ addon->br_offset = address - addon->chunk_offsets[index];
+ addon->br_length = length;
+ addon->br_copied = 0;
+ return BROTLI_TRUE;
+}
+
+static int GetCompoundDictionarySize(BrotliDecoderState* s) {
+ return s->compound_dictionary ? s->compound_dictionary->total_size : 0;
+}
+
+static int CopyFromCompoundDictionary(BrotliDecoderState* s, int pos) {
+ BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
+ int orig_pos = pos;
+ while (addon->br_length != addon->br_copied) {
+ uint8_t* copy_dst = &s->ringbuffer[pos];
+ const uint8_t* copy_src =
+ addon->chunks[addon->br_index] + addon->br_offset;
+ int space = s->ringbuffer_size - pos;
+ int rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -
+ addon->chunk_offsets[addon->br_index]) - addon->br_offset;
+ int length = addon->br_length - addon->br_copied;
+ if (length > rem_chunk_length) length = rem_chunk_length;
+ if (length > space) length = space;
+ memcpy(copy_dst, copy_src, (size_t)length);
+ pos += length;
+ addon->br_offset += length;
+ addon->br_copied += length;
+ if (length == rem_chunk_length) {
+ addon->br_index++;
+ addon->br_offset = 0;
+ }
+ if (pos == s->ringbuffer_size) break;
+ }
+ return pos - orig_pos;
+}
+
+BROTLI_BOOL BrotliDecoderAttachDictionary(
+ BrotliDecoderState* state, BrotliSharedDictionaryType type,
+ size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {
+ uint32_t i;
+ uint32_t num_prefix_before = state->dictionary->num_prefix;
+ if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;
+ if (!BrotliSharedDictionaryAttach(state->dictionary, type, data_size, data)) {
+ return BROTLI_FALSE;
+ }
+ for (i = num_prefix_before; i < state->dictionary->num_prefix; i++) {
+ if (!AttachCompoundDictionary(
+ state, state->dictionary->prefix[i],
+ state->dictionary->prefix_size[i])) {
+ return BROTLI_FALSE;
+ }
+ }
+ return BROTLI_TRUE;
+}
+
+/* Calculates the smallest feasible ring buffer.
+
+ If we know the data size is small, do not allocate more ring buffer
+ size than needed to reduce memory usage.
+
+ When this method is called, metablock size and flags MUST be decoded. */
+static void BROTLI_NOINLINE BrotliCalculateRingBufferSize(
+ BrotliDecoderState* s) {
+ int window_size = 1 << s->window_bits;
+ int new_ringbuffer_size = window_size;
+ /* We need at least 2 bytes of ring buffer size to get the last two
+ bytes for context from there */
+ int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024;
+ int output_size;
+
+ /* If maximum is already reached, no further extension is retired. */
+ if (s->ringbuffer_size == window_size) {
+ return;
+ }
+
+ /* Metadata blocks does not touch ring buffer. */
+ if (s->is_metadata) {
+ return;
+ }
+
+ if (!s->ringbuffer) {
+ output_size = 0;
+ } else {
+ output_size = s->pos;
+ }
+ output_size += s->meta_block_remaining_len;
+ min_size = min_size < output_size ? output_size : min_size;
+
+ if (!!s->canny_ringbuffer_allocation) {
+ /* Reduce ring buffer size to save memory when server is unscrupulous.
+ In worst case memory usage might be 1.5x bigger for a short period of
+ ring buffer reallocation. */
+ while ((new_ringbuffer_size >> 1) >= min_size) {
+ new_ringbuffer_size >>= 1;
+ }
+ }
+
+ s->new_ringbuffer_size = new_ringbuffer_size;
+}
+
+/* Reads 1..256 2-bit context modes. */
+static BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {
+ BrotliBitReader* br = &s->br;
+ int i = s->loop_counter;
+
+ while (i < (int)s->num_block_types[0]) {
+ uint32_t bits;
+ if (!BrotliSafeReadBits(br, 2, &bits)) {
+ s->loop_counter = i;
+ return BROTLI_DECODER_NEEDS_MORE_INPUT;
+ }
+ s->context_modes[i] = (uint8_t)bits;
+ BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);
+ i++;
+ }
+ return BROTLI_DECODER_SUCCESS;
+}
+
+static BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {
+ int offset = s->distance_code - 3;
+ if (s->distance_code <= 3) {
+ /* Compensate double distance-ring-buffer roll for dictionary items. */
+ s->distance_context = 1 >> s->distance_code;
+ s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];
+ s->dist_rb_idx -= s->distance_context;
+ } else {
+ int index_delta = 3;
+ int delta;
+ int base = s->distance_code - 10;
+ if (s->distance_code < 10) {
+ base = s->distance_code - 4;
+ } else {
+ index_delta = 2;
+ }
+ /* Unpack one of six 4-bit values. */
+ delta = ((0x605142 >> (4 * base)) & 0xF) - 3;
+ s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;
+ if (s->distance_code <= 0) {
+ /* A huge distance will cause a BROTLI_FAILURE() soon.
+ This is a little faster than failing here. */
+ s->distance_code = 0x7FFFFFFF;
+ }
+ }
+}
+
+static BROTLI_INLINE BROTLI_BOOL SafeReadBits(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ if (n_bits != 0) {
+ return BrotliSafeReadBits(br, n_bits, val);
+ } else {
+ *val = 0;
+ return BROTLI_TRUE;
+ }
+}
+
+static BROTLI_INLINE BROTLI_BOOL SafeReadBits32(
+ BrotliBitReader* const br, uint32_t n_bits, uint32_t* val) {
+ if (n_bits != 0) {
+ return BrotliSafeReadBits32(br, n_bits, val);
+ } else {
+ *val = 0;
+ return BROTLI_TRUE;
+ }
+}
+
+/*
+ RFC 7932 Section 4 with "..." shortenings and "[]" emendations.
+
+ Each distance ... is represented with a pair <distance code, extra bits>...
+ The distance code is encoded using a prefix code... The number of extra bits
+ can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...
+ NDIRECT (0..120) ... are encoded in the meta-block header...
+
+ The first 16 distance symbols ... reference past distances... ring buffer ...
+ Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...
+ [For] distance symbols 16 + NDIRECT and greater ... the number of extra bits
+ ... is given by the following formula:
+
+ [ xcode = dcode - NDIRECT - 16 ]
+ ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)
+
+ ...
+*/
+
+/*
+ RFC 7932 Section 9.2 with "..." shortenings and "[]" emendations.
+
+ ... to get the actual value of the parameter NDIRECT, left-shift this
+ four-bit number by NPOSTFIX bits ...
+*/
+
+/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:
+
+ alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))
+
+ half = ((xcode >> NPOSTFIX) & 1) << ndistbits
+ postfix = xcode & ((1 << NPOSTFIX) - 1)
+ range_start = 2 * (1 << ndistbits - 1 - 1)
+
+ distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1
+
+ NB: ndistbits >= 1 -> range_start >= 0
+ NB: range_start has factor 2, as the range is covered by 2 "halves"
+ NB: extra -1 offset in range_start formula covers the absence of
+ ndistbits = 0 case
+ NB: when NPOSTFIX = 0, NDIRECT is not greater than 15
+
+ In other words, xcode has the following binary structure - XXXHPPP:
+ - XXX represent the number of extra distance bits
+ - H selects upper / lower range of distances
+ - PPP represent "postfix"
+
+ "Regular" distance encoding has NPOSTFIX = 0; omitting the postfix part
+ simplifies distance calculation.
+
+ Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where
+ most of distances have the same reminder of division by 2/4/8. For example,
+ the table of int32_t values that come from different sources; if it is likely
+ that 3 highest bytes of values from the same source are the same, then
+ copy distance often looks like 4x + y.
+
+ Distance calculation could be rewritten to:
+
+ ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]
+ distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX
+
+ NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could
+ change only once per meta-block.
+*/
+
+/* Calculates distance lookup table.
+ NB: it is possible to have all 64 tables precalculated. */
+static void CalculateDistanceLut(BrotliDecoderState* s) {
+ BrotliMetablockBodyArena* b = &s->arena.body;
+ uint32_t npostfix = s->distance_postfix_bits;
+ uint32_t ndirect = s->num_direct_distance_codes;
+ uint32_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;
+ uint32_t postfix = 1u << npostfix;
+ uint32_t j;
+ uint32_t bits = 1;
+ uint32_t half = 0;
+
+ /* Skip short codes. */
+ uint32_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;
+
+ /* Fill direct codes. */
+ for (j = 0; j < ndirect; ++j) {
+ b->dist_extra_bits[i] = 0;
+ b->dist_offset[i] = j + 1;
+ ++i;
+ }
+
+ /* Fill regular distance codes. */
+ while (i < alphabet_size_limit) {
+ uint32_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;
+ /* Always fill the complete group. */
+ for (j = 0; j < postfix; ++j) {
+ b->dist_extra_bits[i] = (uint8_t)bits;
+ b->dist_offset[i] = base + j;
+ ++i;
+ }
+ bits = bits + half;
+ half = half ^ 1;
+ }
+}
+
+/* Precondition: s->distance_code < 0. */
+static BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(
+ int safe, BrotliDecoderState* s, BrotliBitReader* br) {
+ BrotliMetablockBodyArena* b = &s->arena.body;
+ uint32_t code;
+ uint32_t bits;
+ BrotliBitReaderState memento;
+ HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];
+ if (!safe) {
+ code = ReadSymbol(distance_tree, br);
+ } else {
+ BrotliBitReaderSaveState(br, &memento);
+ if (!SafeReadSymbol(distance_tree, br, &code)) {
+ return BROTLI_FALSE;
+ }
+ }
+ --s->block_length[2];
+ /* Convert the distance code to the actual distance by possibly
+ looking up past distances from the s->dist_rb. */
+ s->distance_context = 0;
+ if ((code & ~0xFu) == 0) {
+ s->distance_code = (int)code;
+ TakeDistanceFromRingBuffer(s);
+ return BROTLI_TRUE;
+ }
+ if (!safe) {
+ bits = BrotliReadBits32(br, b->dist_extra_bits[code]);
+ } else {
+ if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {
+ ++s->block_length[2];
+ BrotliBitReaderRestoreState(br, &memento);
+ return BROTLI_FALSE;
+ }
+ }
+ s->distance_code =
+ (int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));
+ return BROTLI_TRUE;
+}
+
+static BROTLI_INLINE void ReadDistance(
+ BrotliDecoderState* s, BrotliBitReader* br) {
+ ReadDistanceInternal(0, s, br);
+}
+
+static BROTLI_INLINE BROTLI_BOOL SafeReadDistance(
+ BrotliDecoderState* s, BrotliBitReader* br) {
+ return ReadDistanceInternal(1, s, br);
+}
+
+static BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(
+ int safe, BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
+ uint32_t cmd_code;
+ uint32_t insert_len_extra = 0;
+ uint32_t copy_length;
+ CmdLutElement v;
+ BrotliBitReaderState memento;
+ if (!safe) {
+ cmd_code = ReadSymbol(s->htree_command, br);
+ } else {
+ BrotliBitReaderSaveState(br, &memento);
+ if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) {
+ return BROTLI_FALSE;
+ }
+ }
+ v = kCmdLut[cmd_code];
+ s->distance_code = v.distance_code;
+ s->distance_context = v.context;
+ s->dist_htree_index = s->dist_context_map_slice[s->distance_context];
+ *insert_length = v.insert_len_offset;
+ if (!safe) {
+ if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {
+ insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);
+ }
+ copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);
+ } else {
+ if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||
+ !SafeReadBits(br, v.copy_len_extra_bits, &copy_length)) {
+ BrotliBitReaderRestoreState(br, &memento);
+ return BROTLI_FALSE;
+ }
+ }
+ s->copy_length = (int)copy_length + v.copy_len_offset;
+ --s->block_length[1];
+ *insert_length += (int)insert_len_extra;
+ return BROTLI_TRUE;
+}
+
+static BROTLI_INLINE void ReadCommand(
+ BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
+ ReadCommandInternal(0, s, br, insert_length);
+}
+
+static BROTLI_INLINE BROTLI_BOOL SafeReadCommand(
+ BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {
+ return ReadCommandInternal(1, s, br, insert_length);
+}
+
+static BROTLI_INLINE BROTLI_BOOL CheckInputAmount(
+ int safe, BrotliBitReader* const br, size_t num) {
+ if (safe) {
+ return BROTLI_TRUE;
+ }
+ return BrotliCheckInputAmount(br, num);
+}
+
+#define BROTLI_SAFE(METHOD) \
+ { \
+ if (safe) { \
+ if (!Safe##METHOD) { \
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT; \
+ goto saveStateAndReturn; \
+ } \
+ } else { \
+ METHOD; \
+ } \
+ }
+
+static BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(
+ int safe, BrotliDecoderState* s) {
+ int pos = s->pos;
+ int i = s->loop_counter;
+ BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
+ BrotliBitReader* br = &s->br;
+ int compound_dictionary_size = GetCompoundDictionarySize(s);
+
+ if (!CheckInputAmount(safe, br, 28)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ if (!safe) {
+ BROTLI_UNUSED(BrotliWarmupBitReader(br));
+ }
+
+ /* Jump into state machine. */
+ if (s->state == BROTLI_STATE_COMMAND_BEGIN) {
+ goto CommandBegin;
+ } else if (s->state == BROTLI_STATE_COMMAND_INNER) {
+ goto CommandInner;
+ } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) {
+ goto CommandPostDecodeLiterals;
+ } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {
+ goto CommandPostWrapCopy;
+ } else {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE); /* COV_NF_LINE */
+ }
+
+CommandBegin:
+ if (safe) {
+ s->state = BROTLI_STATE_COMMAND_BEGIN;
+ }
+ if (!CheckInputAmount(safe, br, 28)) { /* 156 bits + 7 bytes */
+ s->state = BROTLI_STATE_COMMAND_BEGIN;
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {
+ BROTLI_SAFE(DecodeCommandBlockSwitch(s));
+ goto CommandBegin;
+ }
+ /* Read the insert/copy length in the command. */
+ BROTLI_SAFE(ReadCommand(s, br, &i));
+ BROTLI_LOG(("[ProcessCommandsInternal] pos = %d insert = %d copy = %d\n",
+ pos, i, s->copy_length));
+ if (i == 0) {
+ goto CommandPostDecodeLiterals;
+ }
+ s->meta_block_remaining_len -= i;
+
+CommandInner:
+ if (safe) {
+ s->state = BROTLI_STATE_COMMAND_INNER;
+ }
+ /* Read the literals in the command. */
+ if (s->trivial_literal_context) {
+ uint32_t bits;
+ uint32_t value;
+ PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
+ do {
+ if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
+ s->state = BROTLI_STATE_COMMAND_INNER;
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
+ BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
+ PreloadSymbol(safe, s->literal_htree, br, &bits, &value);
+ if (!s->trivial_literal_context) goto CommandInner;
+ }
+ if (!safe) {
+ s->ringbuffer[pos] =
+ (uint8_t)ReadPreloadedSymbol(s->literal_htree, br, &bits, &value);
+ } else {
+ uint32_t literal;
+ if (!SafeReadSymbol(s->literal_htree, br, &literal)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ s->ringbuffer[pos] = (uint8_t)literal;
+ }
+ --s->block_length[0];
+ BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);
+ ++pos;
+ if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {
+ s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
+ --i;
+ goto saveStateAndReturn;
+ }
+ } while (--i != 0);
+ } else {
+ uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
+ uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];
+ do {
+ const HuffmanCode* hc;
+ uint8_t context;
+ if (!CheckInputAmount(safe, br, 28)) { /* 162 bits + 7 bytes */
+ s->state = BROTLI_STATE_COMMAND_INNER;
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {
+ BROTLI_SAFE(DecodeLiteralBlockSwitch(s));
+ if (s->trivial_literal_context) goto CommandInner;
+ }
+ context = BROTLI_CONTEXT(p1, p2, s->context_lookup);
+ BROTLI_LOG_UINT(context);
+ hc = s->literal_hgroup.htrees[s->context_map_slice[context]];
+ p2 = p1;
+ if (!safe) {
+ p1 = (uint8_t)ReadSymbol(hc, br);
+ } else {
+ uint32_t literal;
+ if (!SafeReadSymbol(hc, br, &literal)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ goto saveStateAndReturn;
+ }
+ p1 = (uint8_t)literal;
+ }
+ s->ringbuffer[pos] = p1;
+ --s->block_length[0];
+ BROTLI_LOG_UINT(s->context_map_slice[context]);
+ BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask);
+ ++pos;
+ if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {
+ s->state = BROTLI_STATE_COMMAND_INNER_WRITE;
+ --i;
+ goto saveStateAndReturn;
+ }
+ } while (--i != 0);
+ }
+ BROTLI_LOG_UINT(s->meta_block_remaining_len);
+ if (BROTLI_PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ goto saveStateAndReturn;
+ }
+
+CommandPostDecodeLiterals:
+ if (safe) {
+ s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
+ }
+ if (s->distance_code >= 0) {
+ /* Implicit distance case. */
+ s->distance_context = s->distance_code ? 0 : 1;
+ --s->dist_rb_idx;
+ s->distance_code = s->dist_rb[s->dist_rb_idx & 3];
+ } else {
+ /* Read distance code in the command, unless it was implicitly zero. */
+ if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {
+ BROTLI_SAFE(DecodeDistanceBlockSwitch(s));
+ }
+ BROTLI_SAFE(ReadDistance(s, br));
+ }
+ BROTLI_LOG(("[ProcessCommandsInternal] pos = %d distance = %d\n",
+ pos, s->distance_code));
+ if (s->max_distance != s->max_backward_distance) {
+ s->max_distance =
+ (pos < s->max_backward_distance) ? pos : s->max_backward_distance;
+ }
+ i = s->copy_length;
+ /* Apply copy of LZ77 back-reference, or static dictionary reference if
+ the distance is larger than the max LZ77 distance */
+ if (s->distance_code > s->max_distance) {
+ /* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.
+ With this choice, no signed overflow can occur after decoding
+ a special distance code (e.g., after adding 3 to the last distance). */
+ if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) {
+ BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
+ "len: %d bytes left: %d\n",
+ pos, s->distance_code, i, s->meta_block_remaining_len));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);
+ }
+ if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) {
+ int address = compound_dictionary_size -
+ (s->distance_code - s->max_distance);
+ if (!InitializeCompoundDictionaryCopy(s, address, i)) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY);
+ }
+ pos += CopyFromCompoundDictionary(s, pos);
+ if (pos >= s->ringbuffer_size) {
+ s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
+ goto saveStateAndReturn;
+ }
+ } else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH &&
+ i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) {
+ uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];
+ uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];
+ uint8_t dict_id = s->dictionary->context_based ?
+ s->dictionary->context_map[BROTLI_CONTEXT(p1, p2, s->context_lookup)]
+ : 0;
+ const BrotliDictionary* words = s->dictionary->words[dict_id];
+ const BrotliTransforms* transforms = s->dictionary->transforms[dict_id];
+ int offset = (int)words->offsets_by_length[i];
+ uint32_t shift = words->size_bits_by_length[i];
+ int address =
+ s->distance_code - s->max_distance - 1 - compound_dictionary_size;
+ int mask = (int)BitMask(shift);
+ int word_idx = address & mask;
+ int transform_idx = address >> shift;
+ /* Compensate double distance-ring-buffer roll. */
+ s->dist_rb_idx += s->distance_context;
+ offset += word_idx * i;
+ /* If the distance is out of bound, select a next static dictionary if
+ there exist multiple. */
+ if ((transform_idx >= (int)transforms->num_transforms ||
+ words->size_bits_by_length[i] == 0) &&
+ s->dictionary->num_dictionaries > 1) {
+ uint8_t dict_id2;
+ int dist_remaining = address -
+ (int)(((1u << shift) & ~1u)) * (int)transforms->num_transforms;
+ for (dict_id2 = 0; dict_id2 < s->dictionary->num_dictionaries;
+ dict_id2++) {
+ const BrotliDictionary* words2 = s->dictionary->words[dict_id2];
+ if (dict_id2 != dict_id && words2->size_bits_by_length[i] != 0) {
+ const BrotliTransforms* transforms2 =
+ s->dictionary->transforms[dict_id2];
+ uint32_t shift2 = words2->size_bits_by_length[i];
+ int num = (int)((1u << shift2) & ~1u) *
+ (int)transforms2->num_transforms;
+ if (dist_remaining < num) {
+ dict_id = dict_id2;
+ words = words2;
+ transforms = transforms2;
+ address = dist_remaining;
+ shift = shift2;
+ mask = (int)BitMask(shift);
+ word_idx = address & mask;
+ transform_idx = address >> shift;
+ offset = (int)words->offsets_by_length[i] + word_idx * i;
+ break;
+ }
+ dist_remaining -= num;
+ }
+ }
+ }
+ if (BROTLI_PREDICT_FALSE(words->size_bits_by_length[i] == 0)) {
+ BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
+ "len: %d bytes left: %d\n",
+ pos, s->distance_code, i, s->meta_block_remaining_len));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);
+ }
+ if (BROTLI_PREDICT_FALSE(!words->data)) {
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);
+ }
+ if (transform_idx < (int)transforms->num_transforms) {
+ const uint8_t* word = &words->data[offset];
+ int len = i;
+ if (transform_idx == transforms->cutOffTransforms[0]) {
+ memcpy(&s->ringbuffer[pos], word, (size_t)len);
+ BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s]\n",
+ len, word));
+ } else {
+ len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len,
+ transforms, transform_idx);
+ BROTLI_LOG(("[ProcessCommandsInternal] dictionary word: [%.*s],"
+ " transform_idx = %d, transformed: [%.*s]\n",
+ i, word, transform_idx, len, &s->ringbuffer[pos]));
+ if (len == 0 && s->distance_code <= 120) {
+ BROTLI_LOG(("Invalid length-0 dictionary word after transform\n"));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);
+ }
+ }
+ pos += len;
+ s->meta_block_remaining_len -= len;
+ if (pos >= s->ringbuffer_size) {
+ s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;
+ goto saveStateAndReturn;
+ }
+ } else {
+ BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
+ "len: %d bytes left: %d\n",
+ pos, s->distance_code, i, s->meta_block_remaining_len));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);
+ }
+ } else {
+ BROTLI_LOG(("Invalid backward reference. pos: %d distance: %d "
+ "len: %d bytes left: %d\n",
+ pos, s->distance_code, i, s->meta_block_remaining_len));
+ return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);
+ }
+ } else {
+ int src_start = (pos - s->distance_code) & s->ringbuffer_mask;
+ uint8_t* copy_dst = &s->ringbuffer[pos];
+ uint8_t* copy_src = &s->ringbuffer[src_start];
+ int dst_end = pos + i;
+ int src_end = src_start + i;
+ /* Update the recent distances cache. */
+ s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;
+ ++s->dist_rb_idx;
+ s->meta_block_remaining_len -= i;
+ /* There are 32+ bytes of slack in the ring-buffer allocation.
+ Also, we have 16 short codes, that make these 16 bytes irrelevant
+ in the ring-buffer. Let's copy over them as a first guess. */
+ memmove16(copy_dst, copy_src);
+ if (src_end > pos && dst_end > src_start) {
+ /* Regions intersect. */
+ goto CommandPostWrapCopy;
+ }
+ if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) {
+ /* At least one region wraps. */
+ goto CommandPostWrapCopy;
+ }
+ pos += i;
+ if (i > 16) {
+ if (i > 32) {
+ memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16));
+ } else {
+ /* This branch covers about 45% cases.
+ Fixed size short copy allows more compiler optimizations. */
+ memmove16(copy_dst + 16, copy_src + 16);
+ }
+ }
+ }
+ BROTLI_LOG_UINT(s->meta_block_remaining_len);
+ if (s->meta_block_remaining_len <= 0) {
+ /* Next metablock, if any. */
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ goto saveStateAndReturn;
+ } else {
+ goto CommandBegin;
+ }
+CommandPostWrapCopy:
+ {
+ int wrap_guard = s->ringbuffer_size - pos;
+ while (--i >= 0) {
+ s->ringbuffer[pos] =
+ s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask];
+ ++pos;
+ if (BROTLI_PREDICT_FALSE(--wrap_guard == 0)) {
+ s->state = BROTLI_STATE_COMMAND_POST_WRITE_2;
+ goto saveStateAndReturn;
+ }
+ }
+ }
+ if (s->meta_block_remaining_len <= 0) {
+ /* Next metablock, if any. */
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ goto saveStateAndReturn;
+ } else {
+ goto CommandBegin;
+ }
+
+saveStateAndReturn:
+ s->pos = pos;
+ s->loop_counter = i;
+ return result;
+}
+
+#undef BROTLI_SAFE
+
+static BROTLI_NOINLINE BrotliDecoderErrorCode ProcessCommands(
+ BrotliDecoderState* s) {
+ return ProcessCommandsInternal(0, s);
+}
+
+static BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(
+ BrotliDecoderState* s) {
+ return ProcessCommandsInternal(1, s);
+}
+
+BrotliDecoderResult BrotliDecoderDecompress(
+ size_t encoded_size,
+ const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
+ size_t* decoded_size,
+ uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]) {
+ BrotliDecoderState s;
+ BrotliDecoderResult result;
+ size_t total_out = 0;
+ size_t available_in = encoded_size;
+ const uint8_t* next_in = encoded_buffer;
+ size_t available_out = *decoded_size;
+ uint8_t* next_out = decoded_buffer;
+ if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {
+ return BROTLI_DECODER_RESULT_ERROR;
+ }
+ result = BrotliDecoderDecompressStream(
+ &s, &available_in, &next_in, &available_out, &next_out, &total_out);
+ *decoded_size = total_out;
+ BrotliDecoderStateCleanup(&s);
+ if (result != BROTLI_DECODER_RESULT_SUCCESS) {
+ result = BROTLI_DECODER_RESULT_ERROR;
+ }
+ return result;
+}
+
+/* Invariant: input stream is never overconsumed:
+ - invalid input implies that the whole stream is invalid -> any amount of
+ input could be read and discarded
+ - when result is "needs more input", then at least one more byte is REQUIRED
+ to complete decoding; all input data MUST be consumed by decoder, so
+ client could swap the input buffer
+ - when result is "needs more output" decoder MUST ensure that it doesn't
+ hold more than 7 bits in bit reader; this saves client from swapping input
+ buffer ahead of time
+ - when result is "success" decoder MUST return all unused data back to input
+ buffer; this is possible because the invariant is held on enter */
+BrotliDecoderResult BrotliDecoderDecompressStream(
+ BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,
+ size_t* available_out, uint8_t** next_out, size_t* total_out) {
+ BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;
+ BrotliBitReader* br = &s->br;
+ /* Ensure that |total_out| is set, even if no data will ever be pushed out. */
+ if (total_out) {
+ *total_out = s->partial_pos_out;
+ }
+ /* Do not try to process further in a case of unrecoverable error. */
+ if ((int)s->error_code < 0) {
+ return BROTLI_DECODER_RESULT_ERROR;
+ }
+ if (*available_out && (!next_out || !*next_out)) {
+ return SaveErrorCode(
+ s, BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));
+ }
+ if (!*available_out) next_out = 0;
+ if (s->buffer_length == 0) { /* Just connect bit reader to input stream. */
+ br->avail_in = *available_in;
+ br->next_in = *next_in;
+ } else {
+ /* At least one byte of input is required. More than one byte of input may
+ be required to complete the transaction -> reading more data must be
+ done in a loop -> do it in a main loop. */
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ br->next_in = &s->buffer.u8[0];
+ }
+ /* State machine */
+ for (;;) {
+ if (result != BROTLI_DECODER_SUCCESS) {
+ /* Error, needs more input/output. */
+ if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
+ if (s->ringbuffer != 0) { /* Pro-actively push output. */
+ BrotliDecoderErrorCode intermediate_result = WriteRingBuffer(s,
+ available_out, next_out, total_out, BROTLI_TRUE);
+ /* WriteRingBuffer checks s->meta_block_remaining_len validity. */
+ if ((int)intermediate_result < 0) {
+ result = intermediate_result;
+ break;
+ }
+ }
+ if (s->buffer_length != 0) { /* Used with internal buffer. */
+ if (br->avail_in == 0) {
+ /* Successfully finished read transaction.
+ Accumulator contains less than 8 bits, because internal buffer
+ is expanded byte-by-byte until it is enough to complete read. */
+ s->buffer_length = 0;
+ /* Switch to input stream and restart. */
+ result = BROTLI_DECODER_SUCCESS;
+ br->avail_in = *available_in;
+ br->next_in = *next_in;
+ continue;
+ } else if (*available_in != 0) {
+ /* Not enough data in buffer, but can take one more byte from
+ input stream. */
+ result = BROTLI_DECODER_SUCCESS;
+ s->buffer.u8[s->buffer_length] = **next_in;
+ s->buffer_length++;
+ br->avail_in = s->buffer_length;
+ (*next_in)++;
+ (*available_in)--;
+ /* Retry with more data in buffer. */
+ continue;
+ }
+ /* Can't finish reading and no more input. */
+ break;
+ } else { /* Input stream doesn't contain enough input. */
+ /* Copy tail to internal buffer and return. */
+ *next_in = br->next_in;
+ *available_in = br->avail_in;
+ while (*available_in) {
+ s->buffer.u8[s->buffer_length] = **next_in;
+ s->buffer_length++;
+ (*next_in)++;
+ (*available_in)--;
+ }
+ break;
+ }
+ /* Unreachable. */
+ }
+
+ /* Fail or needs more output. */
+
+ if (s->buffer_length != 0) {
+ /* Just consumed the buffered input and produced some output. Otherwise
+ it would result in "needs more input". Reset internal buffer. */
+ s->buffer_length = 0;
+ } else {
+ /* Using input stream in last iteration. When decoder switches to input
+ stream it has less than 8 bits in accumulator, so it is safe to
+ return unused accumulator bits there. */
+ BrotliBitReaderUnload(br);
+ *available_in = br->avail_in;
+ *next_in = br->next_in;
+ }
+ break;
+ }
+ switch (s->state) {
+ case BROTLI_STATE_UNINITED:
+ /* Prepare to the first read. */
+ if (!BrotliWarmupBitReader(br)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ break;
+ }
+ /* Decode window size. */
+ result = DecodeWindowBits(s, br); /* Reads 1..8 bits. */
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ if (s->large_window) {
+ s->state = BROTLI_STATE_LARGE_WINDOW_BITS;
+ break;
+ }
+ s->state = BROTLI_STATE_INITIALIZE;
+ break;
+
+ case BROTLI_STATE_LARGE_WINDOW_BITS:
+ if (!BrotliSafeReadBits(br, 6, &s->window_bits)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ break;
+ }
+ if (s->window_bits < BROTLI_LARGE_MIN_WBITS ||
+ s->window_bits > BROTLI_LARGE_MAX_WBITS) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);
+ break;
+ }
+ s->state = BROTLI_STATE_INITIALIZE;
+ /* Fall through. */
+
+ case BROTLI_STATE_INITIALIZE:
+ BROTLI_LOG_UINT(s->window_bits);
+ /* Maximum distance, see section 9.1. of the spec. */
+ s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP;
+
+ /* Allocate memory for both block_type_trees and block_len_trees. */
+ s->block_type_trees = (HuffmanCode*)BROTLI_DECODER_ALLOC(s,
+ sizeof(HuffmanCode) * 3 *
+ (BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));
+ if (s->block_type_trees == 0) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES);
+ break;
+ }
+ s->block_len_trees =
+ s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258;
+
+ s->state = BROTLI_STATE_METABLOCK_BEGIN;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_BEGIN:
+ BrotliDecoderStateMetablockBegin(s);
+ BROTLI_LOG_UINT(s->pos);
+ s->state = BROTLI_STATE_METABLOCK_HEADER;
+ /* Fall through. */
+
+ case BROTLI_STATE_METABLOCK_HEADER:
+ result = DecodeMetaBlockLength(s, br); /* Reads 2 - 31 bits. */
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ BROTLI_LOG_UINT(s->is_last_metablock);
+ BROTLI_LOG_UINT(s->meta_block_remaining_len);
+ BROTLI_LOG_UINT(s->is_metadata);
+ BROTLI_LOG_UINT(s->is_uncompressed);
+ if (s->is_metadata || s->is_uncompressed) {
+ if (!BrotliJumpToByteBoundary(br)) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_1);
+ break;
+ }
+ }
+ if (s->is_metadata) {
+ s->state = BROTLI_STATE_METADATA;
+ break;
+ }
+ if (s->meta_block_remaining_len == 0) {
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ break;
+ }
+ BrotliCalculateRingBufferSize(s);
+ if (s->is_uncompressed) {
+ s->state = BROTLI_STATE_UNCOMPRESSED;
+ break;
+ }
+ s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;
+ /* Fall through. */
+
+ case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {
+ BrotliMetablockHeaderArena* h = &s->arena.header;
+ s->loop_counter = 0;
+ /* Initialize compressed metablock header arena. */
+ h->sub_loop_counter = 0;
+ /* Make small negative indexes addressable. */
+ h->symbol_lists =
+ &h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
+ h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
+ h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
+ h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
+ s->state = BROTLI_STATE_HUFFMAN_CODE_0;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_CODE_0:
+ if (s->loop_counter >= 3) {
+ s->state = BROTLI_STATE_METABLOCK_HEADER_2;
+ break;
+ }
+ /* Reads 1..11 bits. */
+ result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ s->num_block_types[s->loop_counter]++;
+ BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]);
+ if (s->num_block_types[s->loop_counter] < 2) {
+ s->loop_counter++;
+ break;
+ }
+ s->state = BROTLI_STATE_HUFFMAN_CODE_1;
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_CODE_1: {
+ uint32_t alphabet_size = s->num_block_types[s->loop_counter] + 2;
+ int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;
+ result = ReadHuffmanCode(alphabet_size, alphabet_size,
+ &s->block_type_trees[tree_offset], NULL, s);
+ if (result != BROTLI_DECODER_SUCCESS) break;
+ s->state = BROTLI_STATE_HUFFMAN_CODE_2;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_CODE_2: {
+ uint32_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS;
+ int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
+ result = ReadHuffmanCode(alphabet_size, alphabet_size,
+ &s->block_len_trees[tree_offset], NULL, s);
+ if (result != BROTLI_DECODER_SUCCESS) break;
+ s->state = BROTLI_STATE_HUFFMAN_CODE_3;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_HUFFMAN_CODE_3: {
+ int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;
+ if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],
+ &s->block_len_trees[tree_offset], br)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ break;
+ }
+ BROTLI_LOG_UINT(s->block_length[s->loop_counter]);
+ s->loop_counter++;
+ s->state = BROTLI_STATE_HUFFMAN_CODE_0;
+ break;
+ }
+
+ case BROTLI_STATE_UNCOMPRESSED: {
+ result = CopyUncompressedBlockToOutput(
+ available_out, next_out, total_out, s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ break;
+ }
+
+ case BROTLI_STATE_METADATA:
+ for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) {
+ uint32_t bits;
+ /* Read one byte and ignore it. */
+ if (!BrotliSafeReadBits(br, 8, &bits)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ break;
+ }
+ }
+ if (result == BROTLI_DECODER_SUCCESS) {
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ }
+ break;
+
+ case BROTLI_STATE_METABLOCK_HEADER_2: {
+ uint32_t bits;
+ if (!BrotliSafeReadBits(br, 6, &bits)) {
+ result = BROTLI_DECODER_NEEDS_MORE_INPUT;
+ break;
+ }
+ s->distance_postfix_bits = bits & BitMask(2);
+ bits >>= 2;
+ s->num_direct_distance_codes = bits << s->distance_postfix_bits;
+ BROTLI_LOG_UINT(s->num_direct_distance_codes);
+ BROTLI_LOG_UINT(s->distance_postfix_bits);
+ s->context_modes =
+ (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);
+ if (s->context_modes == 0) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);
+ break;
+ }
+ s->loop_counter = 0;
+ s->state = BROTLI_STATE_CONTEXT_MODES;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MODES:
+ result = ReadContextModes(s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ s->state = BROTLI_STATE_CONTEXT_MAP_1;
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_1:
+ result = DecodeContextMap(
+ s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS,
+ &s->num_literal_htrees, &s->context_map, s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ DetectTrivialLiteralBlockTypes(s);
+ s->state = BROTLI_STATE_CONTEXT_MAP_2;
+ /* Fall through. */
+
+ case BROTLI_STATE_CONTEXT_MAP_2: {
+ uint32_t npostfix = s->distance_postfix_bits;
+ uint32_t ndirect = s->num_direct_distance_codes;
+ uint32_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
+ npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);
+ uint32_t distance_alphabet_size_limit = distance_alphabet_size_max;
+ BROTLI_BOOL allocation_success = BROTLI_TRUE;
+ if (s->large_window) {
+ BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(
+ BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);
+ distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(
+ npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);
+ distance_alphabet_size_limit = limit.max_alphabet_size;
+ }
+ result = DecodeContextMap(
+ s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,
+ &s->num_dist_htrees, &s->dist_context_map, s);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
+ s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS,
+ BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees);
+ allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
+ s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,
+ BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);
+ allocation_success &= BrotliDecoderHuffmanTreeGroupInit(
+ s, &s->distance_hgroup, distance_alphabet_size_max,
+ distance_alphabet_size_limit, s->num_dist_htrees);
+ if (!allocation_success) {
+ return SaveErrorCode(s,
+ BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));
+ }
+ s->loop_counter = 0;
+ s->state = BROTLI_STATE_TREE_GROUP;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_TREE_GROUP: {
+ HuffmanTreeGroup* hgroup = NULL;
+ switch (s->loop_counter) {
+ case 0: hgroup = &s->literal_hgroup; break;
+ case 1: hgroup = &s->insert_copy_hgroup; break;
+ case 2: hgroup = &s->distance_hgroup; break;
+ default: return SaveErrorCode(s, BROTLI_FAILURE(
+ BROTLI_DECODER_ERROR_UNREACHABLE)); /* COV_NF_LINE */
+ }
+ result = HuffmanTreeGroupDecode(hgroup, s);
+ if (result != BROTLI_DECODER_SUCCESS) break;
+ s->loop_counter++;
+ if (s->loop_counter < 3) {
+ break;
+ }
+ s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;
+ }
+ /* Fall through. */
+
+ case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:
+ PrepareLiteralDecoding(s);
+ s->dist_context_map_slice = s->dist_context_map;
+ s->htree_command = s->insert_copy_hgroup.htrees[0];
+ if (!BrotliEnsureRingBuffer(s)) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);
+ break;
+ }
+ CalculateDistanceLut(s);
+ s->state = BROTLI_STATE_COMMAND_BEGIN;
+ /* Fall through. */
+
+ case BROTLI_STATE_COMMAND_BEGIN:
+ /* Fall through. */
+ case BROTLI_STATE_COMMAND_INNER:
+ /* Fall through. */
+ case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:
+ /* Fall through. */
+ case BROTLI_STATE_COMMAND_POST_WRAP_COPY:
+ result = ProcessCommands(s);
+ if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {
+ result = SafeProcessCommands(s);
+ }
+ break;
+
+ case BROTLI_STATE_COMMAND_INNER_WRITE:
+ /* Fall through. */
+ case BROTLI_STATE_COMMAND_POST_WRITE_1:
+ /* Fall through. */
+ case BROTLI_STATE_COMMAND_POST_WRITE_2:
+ result = WriteRingBuffer(
+ s, available_out, next_out, total_out, BROTLI_FALSE);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ WrapRingBuffer(s);
+ if (s->ringbuffer_size == 1 << s->window_bits) {
+ s->max_distance = s->max_backward_distance;
+ }
+ if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {
+ BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;
+ if (addon && (addon->br_length != addon->br_copied)) {
+ s->pos += CopyFromCompoundDictionary(s, s->pos);
+ if (s->pos >= s->ringbuffer_size) continue;
+ }
+ if (s->meta_block_remaining_len == 0) {
+ /* Next metablock, if any. */
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ } else {
+ s->state = BROTLI_STATE_COMMAND_BEGIN;
+ }
+ break;
+ } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) {
+ s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY;
+ } else { /* BROTLI_STATE_COMMAND_INNER_WRITE */
+ if (s->loop_counter == 0) {
+ if (s->meta_block_remaining_len == 0) {
+ s->state = BROTLI_STATE_METABLOCK_DONE;
+ } else {
+ s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;
+ }
+ break;
+ }
+ s->state = BROTLI_STATE_COMMAND_INNER;
+ }
+ break;
+
+ case BROTLI_STATE_METABLOCK_DONE:
+ if (s->meta_block_remaining_len < 0) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);
+ break;
+ }
+ BrotliDecoderStateCleanupAfterMetablock(s);
+ if (!s->is_last_metablock) {
+ s->state = BROTLI_STATE_METABLOCK_BEGIN;
+ break;
+ }
+ if (!BrotliJumpToByteBoundary(br)) {
+ result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_2);
+ break;
+ }
+ if (s->buffer_length == 0) {
+ BrotliBitReaderUnload(br);
+ *available_in = br->avail_in;
+ *next_in = br->next_in;
+ }
+ s->state = BROTLI_STATE_DONE;
+ /* Fall through. */
+
+ case BROTLI_STATE_DONE:
+ if (s->ringbuffer != 0) {
+ result = WriteRingBuffer(
+ s, available_out, next_out, total_out, BROTLI_TRUE);
+ if (result != BROTLI_DECODER_SUCCESS) {
+ break;
+ }
+ }
+ return SaveErrorCode(s, result);
+ }
+ }
+ return SaveErrorCode(s, result);
+}
+
+BROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s) {
+ /* After unrecoverable error remaining output is considered nonsensical. */
+ if ((int)s->error_code < 0) {
+ return BROTLI_FALSE;
+ }
+ return TO_BROTLI_BOOL(
+ s->ringbuffer != 0 && UnwrittenBytes(s, BROTLI_FALSE) != 0);
+}
+
+const uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {
+ uint8_t* result = 0;
+ size_t available_out = *size ? *size : 1u << 24;
+ size_t requested_out = available_out;
+ BrotliDecoderErrorCode status;
+ if ((s->ringbuffer == 0) || ((int)s->error_code < 0)) {
+ *size = 0;
+ return 0;
+ }
+ WrapRingBuffer(s);
+ status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE);
+ /* Either WriteRingBuffer returns those "success" codes... */
+ if (status == BROTLI_DECODER_SUCCESS ||
+ status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) {
+ *size = requested_out - available_out;
+ } else {
+ /* ... or stream is broken. Normally this should be caught by
+ BrotliDecoderDecompressStream, this is just a safeguard. */
+ if ((int)status < 0) SaveErrorCode(s, status);
+ *size = 0;
+ result = 0;
+ }
+ return result;
+}
+
+BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) {
+ return TO_BROTLI_BOOL(s->state != BROTLI_STATE_UNINITED ||
+ BrotliGetAvailableBits(&s->br) != 0);
+}
+
+BROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) {
+ return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) &&
+ !BrotliDecoderHasMoreOutput(s);
+}
+
+BrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState* s) {
+ return (BrotliDecoderErrorCode)s->error_code;
+}
+
+const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {
+ switch (c) {
+#define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \
+ case BROTLI_DECODER ## PREFIX ## NAME: return #NAME;
+#define BROTLI_NOTHING_
+ BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_)
+#undef BROTLI_ERROR_CODE_CASE_
+#undef BROTLI_NOTHING_
+ default: return "INVALID";
+ }
+}
+
+uint32_t BrotliDecoderVersion() {
+ return BROTLI_VERSION;
+}
+
+/* Escalate internal functions visibility; for testing purposes only. */
+#if defined(BROTLI_TEST)
+BROTLI_BOOL SafeReadSymbolForTest(
+ const HuffmanCode*, BrotliBitReader*, uint32_t*);
+BROTLI_BOOL SafeReadSymbolForTest(
+ const HuffmanCode* table, BrotliBitReader* br, uint32_t* result) {
+ return SafeReadSymbol(table, br, result);
+}
+
+void InverseMoveToFrontTransformForTest(
+ uint8_t*, uint32_t, BrotliDecoderState*);
+void InverseMoveToFrontTransformForTest(
+ uint8_t* v, uint32_t l, BrotliDecoderState* s) {
+ InverseMoveToFrontTransform(v, l, s);
+}
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/dec/huffman.c b/thirdparty/brotli/dec/huffman.c
new file mode 100644
index 0000000000..8f127d7b6f
--- /dev/null
+++ b/thirdparty/brotli/dec/huffman.c
@@ -0,0 +1,339 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Utilities for building Huffman decoding tables. */
+
+#include "huffman.h"
+
+#include <string.h> /* memcpy, memset */
+
+#include "../common/constants.h"
+#include "../common/platform.h"
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BROTLI_REVERSE_BITS_MAX 8
+
+#if defined(BROTLI_RBIT)
+#define BROTLI_REVERSE_BITS_BASE \
+ ((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX)
+#else
+#define BROTLI_REVERSE_BITS_BASE 0
+static uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
+ 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
+ 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
+ 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
+ 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
+ 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
+ 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
+ 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
+ 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
+ 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
+ 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
+ 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
+ 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
+ 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
+ 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
+ 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
+ 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+#endif /* BROTLI_RBIT */
+
+#define BROTLI_REVERSE_BITS_LOWEST \
+ ((brotli_reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))
+
+/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),
+ where reverse(value, len) is the bit-wise reversal of the len least
+ significant bits of value. */
+static BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) {
+#if defined(BROTLI_RBIT)
+ return BROTLI_RBIT(num);
+#else
+ return kReverseBits[num];
+#endif
+}
+
+/* Stores code in table[0], table[step], table[2*step], ..., table[end] */
+/* Assumes that end is an integer multiple of step */
+static BROTLI_INLINE void ReplicateValue(HuffmanCode* table,
+ int step, int end,
+ HuffmanCode code) {
+ do {
+ end -= step;
+ table[end] = code;
+ } while (end > 0);
+}
+
+/* Returns the table width of the next 2nd level table. |count| is the histogram
+ of bit lengths for the remaining symbols, |len| is the code length of the
+ next processed symbol. */
+static BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,
+ int len, int root_bits) {
+ int left = 1 << (len - root_bits);
+ while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) {
+ left -= count[len];
+ if (left <= 0) break;
+ ++len;
+ left <<= 1;
+ }
+ return len - root_bits;
+}
+
+void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,
+ const uint8_t* const code_lengths,
+ uint16_t* count) {
+ HuffmanCode code; /* current table entry */
+ int symbol; /* symbol index in original or sorted table */
+ brotli_reg_t key; /* prefix code */
+ brotli_reg_t key_step; /* prefix code addend */
+ int step; /* step size to replicate values in current table */
+ int table_size; /* size of current table */
+ int sorted[BROTLI_CODE_LENGTH_CODES]; /* symbols sorted by code length */
+ /* offsets in sorted table for each length */
+ int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];
+ int bits;
+ int bits_count;
+ BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=
+ BROTLI_REVERSE_BITS_MAX);
+
+ /* Generate offsets into sorted symbol table by code length. */
+ symbol = -1;
+ bits = 1;
+ BROTLI_REPEAT(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH, {
+ symbol += count[bits];
+ offset[bits] = symbol;
+ bits++;
+ });
+ /* Symbols with code length 0 are placed after all other symbols. */
+ offset[0] = BROTLI_CODE_LENGTH_CODES - 1;
+
+ /* Sort symbols by length, by symbol order within each length. */
+ symbol = BROTLI_CODE_LENGTH_CODES;
+ do {
+ BROTLI_REPEAT(6, {
+ symbol--;
+ sorted[offset[code_lengths[symbol]]--] = symbol;
+ });
+ } while (symbol != 0);
+
+ table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH;
+
+ /* Special case: all symbols but one have 0 code length. */
+ if (offset[0] == 0) {
+ code = ConstructHuffmanCode(0, (uint16_t)sorted[0]);
+ for (key = 0; key < (brotli_reg_t)table_size; ++key) {
+ table[key] = code;
+ }
+ return;
+ }
+
+ /* Fill in table. */
+ key = 0;
+ key_step = BROTLI_REVERSE_BITS_LOWEST;
+ symbol = 0;
+ bits = 1;
+ step = 2;
+ do {
+ for (bits_count = count[bits]; bits_count != 0; --bits_count) {
+ code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]);
+ ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
+ key += key_step;
+ }
+ step <<= 1;
+ key_step >>= 1;
+ } while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);
+}
+
+uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
+ int root_bits,
+ const uint16_t* const symbol_lists,
+ uint16_t* count) {
+ HuffmanCode code; /* current table entry */
+ HuffmanCode* table; /* next available space in table */
+ int len; /* current code length */
+ int symbol; /* symbol index in original or sorted table */
+ brotli_reg_t key; /* prefix code */
+ brotli_reg_t key_step; /* prefix code addend */
+ brotli_reg_t sub_key; /* 2nd level table prefix code */
+ brotli_reg_t sub_key_step; /* 2nd level table prefix code addend */
+ int step; /* step size to replicate values in current table */
+ int table_bits; /* key length of current table */
+ int table_size; /* size of current table */
+ int total_size; /* sum of root table size and 2nd level table sizes */
+ int max_length = -1;
+ int bits;
+ int bits_count;
+
+ BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX);
+ BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <=
+ BROTLI_REVERSE_BITS_MAX);
+
+ while (symbol_lists[max_length] == 0xFFFF) max_length--;
+ max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;
+
+ table = root_table;
+ table_bits = root_bits;
+ table_size = 1 << table_bits;
+ total_size = table_size;
+
+ /* Fill in the root table. Reduce the table size to if possible,
+ and create the repetitions by memcpy. */
+ if (table_bits > max_length) {
+ table_bits = max_length;
+ table_size = 1 << table_bits;
+ }
+ key = 0;
+ key_step = BROTLI_REVERSE_BITS_LOWEST;
+ bits = 1;
+ step = 2;
+ do {
+ symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
+ for (bits_count = count[bits]; bits_count != 0; --bits_count) {
+ symbol = symbol_lists[symbol];
+ code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol);
+ ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);
+ key += key_step;
+ }
+ step <<= 1;
+ key_step >>= 1;
+ } while (++bits <= table_bits);
+
+ /* If root_bits != table_bits then replicate to fill the remaining slots. */
+ while (total_size != table_size) {
+ memcpy(&table[table_size], &table[0],
+ (size_t)table_size * sizeof(table[0]));
+ table_size <<= 1;
+ }
+
+ /* Fill in 2nd level tables and add pointers to root table. */
+ key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1);
+ sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1);
+ sub_key_step = BROTLI_REVERSE_BITS_LOWEST;
+ for (len = root_bits + 1, step = 2; len <= max_length; ++len) {
+ symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);
+ for (; count[len] != 0; --count[len]) {
+ if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) {
+ table += table_size;
+ table_bits = NextTableBitSize(count, len, root_bits);
+ table_size = 1 << table_bits;
+ total_size += table_size;
+ sub_key = BrotliReverseBits(key);
+ key += key_step;
+ root_table[sub_key] = ConstructHuffmanCode(
+ (uint8_t)(table_bits + root_bits),
+ (uint16_t)(((size_t)(table - root_table)) - sub_key));
+ sub_key = 0;
+ }
+ symbol = symbol_lists[symbol];
+ code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol);
+ ReplicateValue(
+ &table[BrotliReverseBits(sub_key)], step, table_size, code);
+ sub_key += sub_key_step;
+ }
+ step <<= 1;
+ sub_key_step >>= 1;
+ }
+ return (uint32_t)total_size;
+}
+
+uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
+ int root_bits,
+ uint16_t* val,
+ uint32_t num_symbols) {
+ uint32_t table_size = 1;
+ const uint32_t goal_size = 1U << root_bits;
+ switch (num_symbols) {
+ case 0:
+ table[0] = ConstructHuffmanCode(0, val[0]);
+ break;
+ case 1:
+ if (val[1] > val[0]) {
+ table[0] = ConstructHuffmanCode(1, val[0]);
+ table[1] = ConstructHuffmanCode(1, val[1]);
+ } else {
+ table[0] = ConstructHuffmanCode(1, val[1]);
+ table[1] = ConstructHuffmanCode(1, val[0]);
+ }
+ table_size = 2;
+ break;
+ case 2:
+ table[0] = ConstructHuffmanCode(1, val[0]);
+ table[2] = ConstructHuffmanCode(1, val[0]);
+ if (val[2] > val[1]) {
+ table[1] = ConstructHuffmanCode(2, val[1]);
+ table[3] = ConstructHuffmanCode(2, val[2]);
+ } else {
+ table[1] = ConstructHuffmanCode(2, val[2]);
+ table[3] = ConstructHuffmanCode(2, val[1]);
+ }
+ table_size = 4;
+ break;
+ case 3: {
+ int i, k;
+ for (i = 0; i < 3; ++i) {
+ for (k = i + 1; k < 4; ++k) {
+ if (val[k] < val[i]) {
+ uint16_t t = val[k];
+ val[k] = val[i];
+ val[i] = t;
+ }
+ }
+ }
+ table[0] = ConstructHuffmanCode(2, val[0]);
+ table[2] = ConstructHuffmanCode(2, val[1]);
+ table[1] = ConstructHuffmanCode(2, val[2]);
+ table[3] = ConstructHuffmanCode(2, val[3]);
+ table_size = 4;
+ break;
+ }
+ case 4: {
+ if (val[3] < val[2]) {
+ uint16_t t = val[3];
+ val[3] = val[2];
+ val[2] = t;
+ }
+ table[0] = ConstructHuffmanCode(1, val[0]);
+ table[1] = ConstructHuffmanCode(2, val[1]);
+ table[2] = ConstructHuffmanCode(1, val[0]);
+ table[3] = ConstructHuffmanCode(3, val[2]);
+ table[4] = ConstructHuffmanCode(1, val[0]);
+ table[5] = ConstructHuffmanCode(2, val[1]);
+ table[6] = ConstructHuffmanCode(1, val[0]);
+ table[7] = ConstructHuffmanCode(3, val[3]);
+ table_size = 8;
+ break;
+ }
+ }
+ while (table_size != goal_size) {
+ memcpy(&table[table_size], &table[0],
+ (size_t)table_size * sizeof(table[0]));
+ table_size <<= 1;
+ }
+ return goal_size;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/dec/huffman.h b/thirdparty/brotli/dec/huffman.h
new file mode 100644
index 0000000000..a8fbc45347
--- /dev/null
+++ b/thirdparty/brotli/dec/huffman.h
@@ -0,0 +1,121 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Utilities for building Huffman decoding tables. */
+
+#ifndef BROTLI_DEC_HUFFMAN_H_
+#define BROTLI_DEC_HUFFMAN_H_
+
+#include "../common/platform.h"
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15
+
+/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */
+#define BROTLI_HUFFMAN_MAX_SIZE_26 396
+/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */
+#define BROTLI_HUFFMAN_MAX_SIZE_258 632
+/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */
+#define BROTLI_HUFFMAN_MAX_SIZE_272 646
+
+#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5
+
+#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \
+ BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))
+#define BROTLI_HUFFMAN_CODE_FAST_LOAD
+#endif
+
+#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)
+/* Do not create this struct directly - use the ConstructHuffmanCode
+ * constructor below! */
+typedef struct {
+ uint8_t bits; /* number of bits used for this symbol */
+ uint16_t value; /* symbol value or table offset */
+} HuffmanCode;
+
+static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
+ const uint16_t value) {
+ HuffmanCode h;
+ h.bits = bits;
+ h.value = value;
+ return h;
+}
+
+/* Please use the following macros to optimize HuffmanCode accesses in hot
+ * paths.
+ *
+ * For example, assuming |table| contains a HuffmanCode pointer:
+ *
+ * BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);
+ * BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);
+ * *bits = BROTLI_HC_GET_BITS(table);
+ * *value = BROTLI_HC_GET_VALUE(table);
+ * BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);
+ * *bits2 = BROTLI_HC_GET_BITS(table);
+ * *value2 = BROTLI_HC_GET_VALUE(table);
+ *
+ */
+
+#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)
+#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)
+
+/* These must be given a HuffmanCode pointer! */
+#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)
+#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)
+
+#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
+
+typedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;
+
+static BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,
+ const uint16_t value) {
+ return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);
+}
+
+#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)
+#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)
+
+/* These must be given a HuffmanCode pointer! */
+#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)
+#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)
+#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */
+
+/* Builds Huffman lookup table assuming code lengths are in symbol order. */
+BROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,
+ const uint8_t* const code_lengths, uint16_t* count);
+
+/* Builds Huffman lookup table assuming code lengths are in symbol order.
+ Returns size of resulting table. */
+BROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,
+ int root_bits, const uint16_t* const symbol_lists, uint16_t* count);
+
+/* Builds a simple Huffman table. The |num_symbols| parameter is to be
+ interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,
+ 2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2],
+ 4 means 4 symbols with lengths [1, 2, 3, 3]. */
+BROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,
+ int root_bits, uint16_t* symbols, uint32_t num_symbols);
+
+/* Contains a collection of Huffman trees with the same alphabet size. */
+/* alphabet_size_limit is needed due to simple codes, since
+ log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */
+typedef struct {
+ HuffmanCode** htrees;
+ HuffmanCode* codes;
+ uint16_t alphabet_size_max;
+ uint16_t alphabet_size_limit;
+ uint16_t num_htrees;
+} HuffmanTreeGroup;
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_DEC_HUFFMAN_H_ */
diff --git a/thirdparty/brotli/dec/prefix.h b/thirdparty/brotli/dec/prefix.h
new file mode 100644
index 0000000000..481a2c7917
--- /dev/null
+++ b/thirdparty/brotli/dec/prefix.h
@@ -0,0 +1,732 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Lookup tables to map prefix codes to value ranges. This is used during
+ decoding of the block lengths, literal insertion lengths and copy lengths. */
+
+#ifndef BROTLI_DEC_PREFIX_H_
+#define BROTLI_DEC_PREFIX_H_
+
+#include "../common/constants.h"
+#include <brotli/types.h>
+
+typedef struct CmdLutElement {
+ uint8_t insert_len_extra_bits;
+ uint8_t copy_len_extra_bits;
+ int8_t distance_code;
+ uint8_t context;
+ uint16_t insert_len_offset;
+ uint16_t copy_len_offset;
+} CmdLutElement;
+
+static const CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS] = {
+ { 0x00, 0x00, 0, 0x00, 0x0000, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0000, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0000, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0000, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0000, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0000, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0000, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0000, 0x0009 },
+ { 0x00, 0x00, 0, 0x00, 0x0001, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0001, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0001, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0001, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0001, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0001, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0001, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0001, 0x0009 },
+ { 0x00, 0x00, 0, 0x00, 0x0002, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0002, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0002, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0002, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0002, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0002, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0002, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0002, 0x0009 },
+ { 0x00, 0x00, 0, 0x00, 0x0003, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0003, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0003, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0003, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0003, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0003, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0003, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0003, 0x0009 },
+ { 0x00, 0x00, 0, 0x00, 0x0004, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0004, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0004, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0004, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0004, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0004, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0004, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0004, 0x0009 },
+ { 0x00, 0x00, 0, 0x00, 0x0005, 0x0002 },
+ { 0x00, 0x00, 0, 0x01, 0x0005, 0x0003 },
+ { 0x00, 0x00, 0, 0x02, 0x0005, 0x0004 },
+ { 0x00, 0x00, 0, 0x03, 0x0005, 0x0005 },
+ { 0x00, 0x00, 0, 0x03, 0x0005, 0x0006 },
+ { 0x00, 0x00, 0, 0x03, 0x0005, 0x0007 },
+ { 0x00, 0x00, 0, 0x03, 0x0005, 0x0008 },
+ { 0x00, 0x00, 0, 0x03, 0x0005, 0x0009 },
+ { 0x01, 0x00, 0, 0x00, 0x0006, 0x0002 },
+ { 0x01, 0x00, 0, 0x01, 0x0006, 0x0003 },
+ { 0x01, 0x00, 0, 0x02, 0x0006, 0x0004 },
+ { 0x01, 0x00, 0, 0x03, 0x0006, 0x0005 },
+ { 0x01, 0x00, 0, 0x03, 0x0006, 0x0006 },
+ { 0x01, 0x00, 0, 0x03, 0x0006, 0x0007 },
+ { 0x01, 0x00, 0, 0x03, 0x0006, 0x0008 },
+ { 0x01, 0x00, 0, 0x03, 0x0006, 0x0009 },
+ { 0x01, 0x00, 0, 0x00, 0x0008, 0x0002 },
+ { 0x01, 0x00, 0, 0x01, 0x0008, 0x0003 },
+ { 0x01, 0x00, 0, 0x02, 0x0008, 0x0004 },
+ { 0x01, 0x00, 0, 0x03, 0x0008, 0x0005 },
+ { 0x01, 0x00, 0, 0x03, 0x0008, 0x0006 },
+ { 0x01, 0x00, 0, 0x03, 0x0008, 0x0007 },
+ { 0x01, 0x00, 0, 0x03, 0x0008, 0x0008 },
+ { 0x01, 0x00, 0, 0x03, 0x0008, 0x0009 },
+ { 0x00, 0x01, 0, 0x03, 0x0000, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0000, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0000, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0000, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0000, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0000, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0000, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0000, 0x0036 },
+ { 0x00, 0x01, 0, 0x03, 0x0001, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0001, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0001, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0001, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0001, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0001, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0001, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0001, 0x0036 },
+ { 0x00, 0x01, 0, 0x03, 0x0002, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0002, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0002, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0002, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0002, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0002, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0002, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0002, 0x0036 },
+ { 0x00, 0x01, 0, 0x03, 0x0003, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0003, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0003, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0003, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0003, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0003, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0003, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0003, 0x0036 },
+ { 0x00, 0x01, 0, 0x03, 0x0004, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0004, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0004, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0004, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0004, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0004, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0004, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0004, 0x0036 },
+ { 0x00, 0x01, 0, 0x03, 0x0005, 0x000a },
+ { 0x00, 0x01, 0, 0x03, 0x0005, 0x000c },
+ { 0x00, 0x02, 0, 0x03, 0x0005, 0x000e },
+ { 0x00, 0x02, 0, 0x03, 0x0005, 0x0012 },
+ { 0x00, 0x03, 0, 0x03, 0x0005, 0x0016 },
+ { 0x00, 0x03, 0, 0x03, 0x0005, 0x001e },
+ { 0x00, 0x04, 0, 0x03, 0x0005, 0x0026 },
+ { 0x00, 0x04, 0, 0x03, 0x0005, 0x0036 },
+ { 0x01, 0x01, 0, 0x03, 0x0006, 0x000a },
+ { 0x01, 0x01, 0, 0x03, 0x0006, 0x000c },
+ { 0x01, 0x02, 0, 0x03, 0x0006, 0x000e },
+ { 0x01, 0x02, 0, 0x03, 0x0006, 0x0012 },
+ { 0x01, 0x03, 0, 0x03, 0x0006, 0x0016 },
+ { 0x01, 0x03, 0, 0x03, 0x0006, 0x001e },
+ { 0x01, 0x04, 0, 0x03, 0x0006, 0x0026 },
+ { 0x01, 0x04, 0, 0x03, 0x0006, 0x0036 },
+ { 0x01, 0x01, 0, 0x03, 0x0008, 0x000a },
+ { 0x01, 0x01, 0, 0x03, 0x0008, 0x000c },
+ { 0x01, 0x02, 0, 0x03, 0x0008, 0x000e },
+ { 0x01, 0x02, 0, 0x03, 0x0008, 0x0012 },
+ { 0x01, 0x03, 0, 0x03, 0x0008, 0x0016 },
+ { 0x01, 0x03, 0, 0x03, 0x0008, 0x001e },
+ { 0x01, 0x04, 0, 0x03, 0x0008, 0x0026 },
+ { 0x01, 0x04, 0, 0x03, 0x0008, 0x0036 },
+ { 0x00, 0x00, -1, 0x00, 0x0000, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0000, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0000, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0000, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0000, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0000, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0000, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0000, 0x0009 },
+ { 0x00, 0x00, -1, 0x00, 0x0001, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0001, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0001, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0001, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0001, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0001, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0001, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0001, 0x0009 },
+ { 0x00, 0x00, -1, 0x00, 0x0002, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0002, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0002, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0002, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0002, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0002, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0002, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0002, 0x0009 },
+ { 0x00, 0x00, -1, 0x00, 0x0003, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0003, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0003, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0003, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0003, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0003, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0003, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0003, 0x0009 },
+ { 0x00, 0x00, -1, 0x00, 0x0004, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0004, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0004, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0004, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0004, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0004, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0004, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0004, 0x0009 },
+ { 0x00, 0x00, -1, 0x00, 0x0005, 0x0002 },
+ { 0x00, 0x00, -1, 0x01, 0x0005, 0x0003 },
+ { 0x00, 0x00, -1, 0x02, 0x0005, 0x0004 },
+ { 0x00, 0x00, -1, 0x03, 0x0005, 0x0005 },
+ { 0x00, 0x00, -1, 0x03, 0x0005, 0x0006 },
+ { 0x00, 0x00, -1, 0x03, 0x0005, 0x0007 },
+ { 0x00, 0x00, -1, 0x03, 0x0005, 0x0008 },
+ { 0x00, 0x00, -1, 0x03, 0x0005, 0x0009 },
+ { 0x01, 0x00, -1, 0x00, 0x0006, 0x0002 },
+ { 0x01, 0x00, -1, 0x01, 0x0006, 0x0003 },
+ { 0x01, 0x00, -1, 0x02, 0x0006, 0x0004 },
+ { 0x01, 0x00, -1, 0x03, 0x0006, 0x0005 },
+ { 0x01, 0x00, -1, 0x03, 0x0006, 0x0006 },
+ { 0x01, 0x00, -1, 0x03, 0x0006, 0x0007 },
+ { 0x01, 0x00, -1, 0x03, 0x0006, 0x0008 },
+ { 0x01, 0x00, -1, 0x03, 0x0006, 0x0009 },
+ { 0x01, 0x00, -1, 0x00, 0x0008, 0x0002 },
+ { 0x01, 0x00, -1, 0x01, 0x0008, 0x0003 },
+ { 0x01, 0x00, -1, 0x02, 0x0008, 0x0004 },
+ { 0x01, 0x00, -1, 0x03, 0x0008, 0x0005 },
+ { 0x01, 0x00, -1, 0x03, 0x0008, 0x0006 },
+ { 0x01, 0x00, -1, 0x03, 0x0008, 0x0007 },
+ { 0x01, 0x00, -1, 0x03, 0x0008, 0x0008 },
+ { 0x01, 0x00, -1, 0x03, 0x0008, 0x0009 },
+ { 0x00, 0x01, -1, 0x03, 0x0000, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0000, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0000, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0000, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0000, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0000, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0000, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0000, 0x0036 },
+ { 0x00, 0x01, -1, 0x03, 0x0001, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0001, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0001, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0001, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0001, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0001, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0001, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0001, 0x0036 },
+ { 0x00, 0x01, -1, 0x03, 0x0002, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0002, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0002, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0002, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0002, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0002, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0002, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0002, 0x0036 },
+ { 0x00, 0x01, -1, 0x03, 0x0003, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0003, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0003, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0003, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0003, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0003, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0003, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0003, 0x0036 },
+ { 0x00, 0x01, -1, 0x03, 0x0004, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0004, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0004, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0004, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0004, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0004, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0004, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0004, 0x0036 },
+ { 0x00, 0x01, -1, 0x03, 0x0005, 0x000a },
+ { 0x00, 0x01, -1, 0x03, 0x0005, 0x000c },
+ { 0x00, 0x02, -1, 0x03, 0x0005, 0x000e },
+ { 0x00, 0x02, -1, 0x03, 0x0005, 0x0012 },
+ { 0x00, 0x03, -1, 0x03, 0x0005, 0x0016 },
+ { 0x00, 0x03, -1, 0x03, 0x0005, 0x001e },
+ { 0x00, 0x04, -1, 0x03, 0x0005, 0x0026 },
+ { 0x00, 0x04, -1, 0x03, 0x0005, 0x0036 },
+ { 0x01, 0x01, -1, 0x03, 0x0006, 0x000a },
+ { 0x01, 0x01, -1, 0x03, 0x0006, 0x000c },
+ { 0x01, 0x02, -1, 0x03, 0x0006, 0x000e },
+ { 0x01, 0x02, -1, 0x03, 0x0006, 0x0012 },
+ { 0x01, 0x03, -1, 0x03, 0x0006, 0x0016 },
+ { 0x01, 0x03, -1, 0x03, 0x0006, 0x001e },
+ { 0x01, 0x04, -1, 0x03, 0x0006, 0x0026 },
+ { 0x01, 0x04, -1, 0x03, 0x0006, 0x0036 },
+ { 0x01, 0x01, -1, 0x03, 0x0008, 0x000a },
+ { 0x01, 0x01, -1, 0x03, 0x0008, 0x000c },
+ { 0x01, 0x02, -1, 0x03, 0x0008, 0x000e },
+ { 0x01, 0x02, -1, 0x03, 0x0008, 0x0012 },
+ { 0x01, 0x03, -1, 0x03, 0x0008, 0x0016 },
+ { 0x01, 0x03, -1, 0x03, 0x0008, 0x001e },
+ { 0x01, 0x04, -1, 0x03, 0x0008, 0x0026 },
+ { 0x01, 0x04, -1, 0x03, 0x0008, 0x0036 },
+ { 0x02, 0x00, -1, 0x00, 0x000a, 0x0002 },
+ { 0x02, 0x00, -1, 0x01, 0x000a, 0x0003 },
+ { 0x02, 0x00, -1, 0x02, 0x000a, 0x0004 },
+ { 0x02, 0x00, -1, 0x03, 0x000a, 0x0005 },
+ { 0x02, 0x00, -1, 0x03, 0x000a, 0x0006 },
+ { 0x02, 0x00, -1, 0x03, 0x000a, 0x0007 },
+ { 0x02, 0x00, -1, 0x03, 0x000a, 0x0008 },
+ { 0x02, 0x00, -1, 0x03, 0x000a, 0x0009 },
+ { 0x02, 0x00, -1, 0x00, 0x000e, 0x0002 },
+ { 0x02, 0x00, -1, 0x01, 0x000e, 0x0003 },
+ { 0x02, 0x00, -1, 0x02, 0x000e, 0x0004 },
+ { 0x02, 0x00, -1, 0x03, 0x000e, 0x0005 },
+ { 0x02, 0x00, -1, 0x03, 0x000e, 0x0006 },
+ { 0x02, 0x00, -1, 0x03, 0x000e, 0x0007 },
+ { 0x02, 0x00, -1, 0x03, 0x000e, 0x0008 },
+ { 0x02, 0x00, -1, 0x03, 0x000e, 0x0009 },
+ { 0x03, 0x00, -1, 0x00, 0x0012, 0x0002 },
+ { 0x03, 0x00, -1, 0x01, 0x0012, 0x0003 },
+ { 0x03, 0x00, -1, 0x02, 0x0012, 0x0004 },
+ { 0x03, 0x00, -1, 0x03, 0x0012, 0x0005 },
+ { 0x03, 0x00, -1, 0x03, 0x0012, 0x0006 },
+ { 0x03, 0x00, -1, 0x03, 0x0012, 0x0007 },
+ { 0x03, 0x00, -1, 0x03, 0x0012, 0x0008 },
+ { 0x03, 0x00, -1, 0x03, 0x0012, 0x0009 },
+ { 0x03, 0x00, -1, 0x00, 0x001a, 0x0002 },
+ { 0x03, 0x00, -1, 0x01, 0x001a, 0x0003 },
+ { 0x03, 0x00, -1, 0x02, 0x001a, 0x0004 },
+ { 0x03, 0x00, -1, 0x03, 0x001a, 0x0005 },
+ { 0x03, 0x00, -1, 0x03, 0x001a, 0x0006 },
+ { 0x03, 0x00, -1, 0x03, 0x001a, 0x0007 },
+ { 0x03, 0x00, -1, 0x03, 0x001a, 0x0008 },
+ { 0x03, 0x00, -1, 0x03, 0x001a, 0x0009 },
+ { 0x04, 0x00, -1, 0x00, 0x0022, 0x0002 },
+ { 0x04, 0x00, -1, 0x01, 0x0022, 0x0003 },
+ { 0x04, 0x00, -1, 0x02, 0x0022, 0x0004 },
+ { 0x04, 0x00, -1, 0x03, 0x0022, 0x0005 },
+ { 0x04, 0x00, -1, 0x03, 0x0022, 0x0006 },
+ { 0x04, 0x00, -1, 0x03, 0x0022, 0x0007 },
+ { 0x04, 0x00, -1, 0x03, 0x0022, 0x0008 },
+ { 0x04, 0x00, -1, 0x03, 0x0022, 0x0009 },
+ { 0x04, 0x00, -1, 0x00, 0x0032, 0x0002 },
+ { 0x04, 0x00, -1, 0x01, 0x0032, 0x0003 },
+ { 0x04, 0x00, -1, 0x02, 0x0032, 0x0004 },
+ { 0x04, 0x00, -1, 0x03, 0x0032, 0x0005 },
+ { 0x04, 0x00, -1, 0x03, 0x0032, 0x0006 },
+ { 0x04, 0x00, -1, 0x03, 0x0032, 0x0007 },
+ { 0x04, 0x00, -1, 0x03, 0x0032, 0x0008 },
+ { 0x04, 0x00, -1, 0x03, 0x0032, 0x0009 },
+ { 0x05, 0x00, -1, 0x00, 0x0042, 0x0002 },
+ { 0x05, 0x00, -1, 0x01, 0x0042, 0x0003 },
+ { 0x05, 0x00, -1, 0x02, 0x0042, 0x0004 },
+ { 0x05, 0x00, -1, 0x03, 0x0042, 0x0005 },
+ { 0x05, 0x00, -1, 0x03, 0x0042, 0x0006 },
+ { 0x05, 0x00, -1, 0x03, 0x0042, 0x0007 },
+ { 0x05, 0x00, -1, 0x03, 0x0042, 0x0008 },
+ { 0x05, 0x00, -1, 0x03, 0x0042, 0x0009 },
+ { 0x05, 0x00, -1, 0x00, 0x0062, 0x0002 },
+ { 0x05, 0x00, -1, 0x01, 0x0062, 0x0003 },
+ { 0x05, 0x00, -1, 0x02, 0x0062, 0x0004 },
+ { 0x05, 0x00, -1, 0x03, 0x0062, 0x0005 },
+ { 0x05, 0x00, -1, 0x03, 0x0062, 0x0006 },
+ { 0x05, 0x00, -1, 0x03, 0x0062, 0x0007 },
+ { 0x05, 0x00, -1, 0x03, 0x0062, 0x0008 },
+ { 0x05, 0x00, -1, 0x03, 0x0062, 0x0009 },
+ { 0x02, 0x01, -1, 0x03, 0x000a, 0x000a },
+ { 0x02, 0x01, -1, 0x03, 0x000a, 0x000c },
+ { 0x02, 0x02, -1, 0x03, 0x000a, 0x000e },
+ { 0x02, 0x02, -1, 0x03, 0x000a, 0x0012 },
+ { 0x02, 0x03, -1, 0x03, 0x000a, 0x0016 },
+ { 0x02, 0x03, -1, 0x03, 0x000a, 0x001e },
+ { 0x02, 0x04, -1, 0x03, 0x000a, 0x0026 },
+ { 0x02, 0x04, -1, 0x03, 0x000a, 0x0036 },
+ { 0x02, 0x01, -1, 0x03, 0x000e, 0x000a },
+ { 0x02, 0x01, -1, 0x03, 0x000e, 0x000c },
+ { 0x02, 0x02, -1, 0x03, 0x000e, 0x000e },
+ { 0x02, 0x02, -1, 0x03, 0x000e, 0x0012 },
+ { 0x02, 0x03, -1, 0x03, 0x000e, 0x0016 },
+ { 0x02, 0x03, -1, 0x03, 0x000e, 0x001e },
+ { 0x02, 0x04, -1, 0x03, 0x000e, 0x0026 },
+ { 0x02, 0x04, -1, 0x03, 0x000e, 0x0036 },
+ { 0x03, 0x01, -1, 0x03, 0x0012, 0x000a },
+ { 0x03, 0x01, -1, 0x03, 0x0012, 0x000c },
+ { 0x03, 0x02, -1, 0x03, 0x0012, 0x000e },
+ { 0x03, 0x02, -1, 0x03, 0x0012, 0x0012 },
+ { 0x03, 0x03, -1, 0x03, 0x0012, 0x0016 },
+ { 0x03, 0x03, -1, 0x03, 0x0012, 0x001e },
+ { 0x03, 0x04, -1, 0x03, 0x0012, 0x0026 },
+ { 0x03, 0x04, -1, 0x03, 0x0012, 0x0036 },
+ { 0x03, 0x01, -1, 0x03, 0x001a, 0x000a },
+ { 0x03, 0x01, -1, 0x03, 0x001a, 0x000c },
+ { 0x03, 0x02, -1, 0x03, 0x001a, 0x000e },
+ { 0x03, 0x02, -1, 0x03, 0x001a, 0x0012 },
+ { 0x03, 0x03, -1, 0x03, 0x001a, 0x0016 },
+ { 0x03, 0x03, -1, 0x03, 0x001a, 0x001e },
+ { 0x03, 0x04, -1, 0x03, 0x001a, 0x0026 },
+ { 0x03, 0x04, -1, 0x03, 0x001a, 0x0036 },
+ { 0x04, 0x01, -1, 0x03, 0x0022, 0x000a },
+ { 0x04, 0x01, -1, 0x03, 0x0022, 0x000c },
+ { 0x04, 0x02, -1, 0x03, 0x0022, 0x000e },
+ { 0x04, 0x02, -1, 0x03, 0x0022, 0x0012 },
+ { 0x04, 0x03, -1, 0x03, 0x0022, 0x0016 },
+ { 0x04, 0x03, -1, 0x03, 0x0022, 0x001e },
+ { 0x04, 0x04, -1, 0x03, 0x0022, 0x0026 },
+ { 0x04, 0x04, -1, 0x03, 0x0022, 0x0036 },
+ { 0x04, 0x01, -1, 0x03, 0x0032, 0x000a },
+ { 0x04, 0x01, -1, 0x03, 0x0032, 0x000c },
+ { 0x04, 0x02, -1, 0x03, 0x0032, 0x000e },
+ { 0x04, 0x02, -1, 0x03, 0x0032, 0x0012 },
+ { 0x04, 0x03, -1, 0x03, 0x0032, 0x0016 },
+ { 0x04, 0x03, -1, 0x03, 0x0032, 0x001e },
+ { 0x04, 0x04, -1, 0x03, 0x0032, 0x0026 },
+ { 0x04, 0x04, -1, 0x03, 0x0032, 0x0036 },
+ { 0x05, 0x01, -1, 0x03, 0x0042, 0x000a },
+ { 0x05, 0x01, -1, 0x03, 0x0042, 0x000c },
+ { 0x05, 0x02, -1, 0x03, 0x0042, 0x000e },
+ { 0x05, 0x02, -1, 0x03, 0x0042, 0x0012 },
+ { 0x05, 0x03, -1, 0x03, 0x0042, 0x0016 },
+ { 0x05, 0x03, -1, 0x03, 0x0042, 0x001e },
+ { 0x05, 0x04, -1, 0x03, 0x0042, 0x0026 },
+ { 0x05, 0x04, -1, 0x03, 0x0042, 0x0036 },
+ { 0x05, 0x01, -1, 0x03, 0x0062, 0x000a },
+ { 0x05, 0x01, -1, 0x03, 0x0062, 0x000c },
+ { 0x05, 0x02, -1, 0x03, 0x0062, 0x000e },
+ { 0x05, 0x02, -1, 0x03, 0x0062, 0x0012 },
+ { 0x05, 0x03, -1, 0x03, 0x0062, 0x0016 },
+ { 0x05, 0x03, -1, 0x03, 0x0062, 0x001e },
+ { 0x05, 0x04, -1, 0x03, 0x0062, 0x0026 },
+ { 0x05, 0x04, -1, 0x03, 0x0062, 0x0036 },
+ { 0x00, 0x05, -1, 0x03, 0x0000, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0000, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0000, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0000, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0000, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0000, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0000, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0000, 0x0846 },
+ { 0x00, 0x05, -1, 0x03, 0x0001, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0001, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0001, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0001, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0001, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0001, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0001, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0001, 0x0846 },
+ { 0x00, 0x05, -1, 0x03, 0x0002, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0002, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0002, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0002, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0002, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0002, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0002, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0002, 0x0846 },
+ { 0x00, 0x05, -1, 0x03, 0x0003, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0003, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0003, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0003, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0003, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0003, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0003, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0003, 0x0846 },
+ { 0x00, 0x05, -1, 0x03, 0x0004, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0004, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0004, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0004, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0004, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0004, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0004, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0004, 0x0846 },
+ { 0x00, 0x05, -1, 0x03, 0x0005, 0x0046 },
+ { 0x00, 0x05, -1, 0x03, 0x0005, 0x0066 },
+ { 0x00, 0x06, -1, 0x03, 0x0005, 0x0086 },
+ { 0x00, 0x07, -1, 0x03, 0x0005, 0x00c6 },
+ { 0x00, 0x08, -1, 0x03, 0x0005, 0x0146 },
+ { 0x00, 0x09, -1, 0x03, 0x0005, 0x0246 },
+ { 0x00, 0x0a, -1, 0x03, 0x0005, 0x0446 },
+ { 0x00, 0x18, -1, 0x03, 0x0005, 0x0846 },
+ { 0x01, 0x05, -1, 0x03, 0x0006, 0x0046 },
+ { 0x01, 0x05, -1, 0x03, 0x0006, 0x0066 },
+ { 0x01, 0x06, -1, 0x03, 0x0006, 0x0086 },
+ { 0x01, 0x07, -1, 0x03, 0x0006, 0x00c6 },
+ { 0x01, 0x08, -1, 0x03, 0x0006, 0x0146 },
+ { 0x01, 0x09, -1, 0x03, 0x0006, 0x0246 },
+ { 0x01, 0x0a, -1, 0x03, 0x0006, 0x0446 },
+ { 0x01, 0x18, -1, 0x03, 0x0006, 0x0846 },
+ { 0x01, 0x05, -1, 0x03, 0x0008, 0x0046 },
+ { 0x01, 0x05, -1, 0x03, 0x0008, 0x0066 },
+ { 0x01, 0x06, -1, 0x03, 0x0008, 0x0086 },
+ { 0x01, 0x07, -1, 0x03, 0x0008, 0x00c6 },
+ { 0x01, 0x08, -1, 0x03, 0x0008, 0x0146 },
+ { 0x01, 0x09, -1, 0x03, 0x0008, 0x0246 },
+ { 0x01, 0x0a, -1, 0x03, 0x0008, 0x0446 },
+ { 0x01, 0x18, -1, 0x03, 0x0008, 0x0846 },
+ { 0x06, 0x00, -1, 0x00, 0x0082, 0x0002 },
+ { 0x06, 0x00, -1, 0x01, 0x0082, 0x0003 },
+ { 0x06, 0x00, -1, 0x02, 0x0082, 0x0004 },
+ { 0x06, 0x00, -1, 0x03, 0x0082, 0x0005 },
+ { 0x06, 0x00, -1, 0x03, 0x0082, 0x0006 },
+ { 0x06, 0x00, -1, 0x03, 0x0082, 0x0007 },
+ { 0x06, 0x00, -1, 0x03, 0x0082, 0x0008 },
+ { 0x06, 0x00, -1, 0x03, 0x0082, 0x0009 },
+ { 0x07, 0x00, -1, 0x00, 0x00c2, 0x0002 },
+ { 0x07, 0x00, -1, 0x01, 0x00c2, 0x0003 },
+ { 0x07, 0x00, -1, 0x02, 0x00c2, 0x0004 },
+ { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0005 },
+ { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0006 },
+ { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0007 },
+ { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0008 },
+ { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0009 },
+ { 0x08, 0x00, -1, 0x00, 0x0142, 0x0002 },
+ { 0x08, 0x00, -1, 0x01, 0x0142, 0x0003 },
+ { 0x08, 0x00, -1, 0x02, 0x0142, 0x0004 },
+ { 0x08, 0x00, -1, 0x03, 0x0142, 0x0005 },
+ { 0x08, 0x00, -1, 0x03, 0x0142, 0x0006 },
+ { 0x08, 0x00, -1, 0x03, 0x0142, 0x0007 },
+ { 0x08, 0x00, -1, 0x03, 0x0142, 0x0008 },
+ { 0x08, 0x00, -1, 0x03, 0x0142, 0x0009 },
+ { 0x09, 0x00, -1, 0x00, 0x0242, 0x0002 },
+ { 0x09, 0x00, -1, 0x01, 0x0242, 0x0003 },
+ { 0x09, 0x00, -1, 0x02, 0x0242, 0x0004 },
+ { 0x09, 0x00, -1, 0x03, 0x0242, 0x0005 },
+ { 0x09, 0x00, -1, 0x03, 0x0242, 0x0006 },
+ { 0x09, 0x00, -1, 0x03, 0x0242, 0x0007 },
+ { 0x09, 0x00, -1, 0x03, 0x0242, 0x0008 },
+ { 0x09, 0x00, -1, 0x03, 0x0242, 0x0009 },
+ { 0x0a, 0x00, -1, 0x00, 0x0442, 0x0002 },
+ { 0x0a, 0x00, -1, 0x01, 0x0442, 0x0003 },
+ { 0x0a, 0x00, -1, 0x02, 0x0442, 0x0004 },
+ { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0005 },
+ { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0006 },
+ { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0007 },
+ { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0008 },
+ { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0009 },
+ { 0x0c, 0x00, -1, 0x00, 0x0842, 0x0002 },
+ { 0x0c, 0x00, -1, 0x01, 0x0842, 0x0003 },
+ { 0x0c, 0x00, -1, 0x02, 0x0842, 0x0004 },
+ { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0005 },
+ { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0006 },
+ { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0007 },
+ { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0008 },
+ { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0009 },
+ { 0x0e, 0x00, -1, 0x00, 0x1842, 0x0002 },
+ { 0x0e, 0x00, -1, 0x01, 0x1842, 0x0003 },
+ { 0x0e, 0x00, -1, 0x02, 0x1842, 0x0004 },
+ { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0005 },
+ { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0006 },
+ { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0007 },
+ { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0008 },
+ { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0009 },
+ { 0x18, 0x00, -1, 0x00, 0x5842, 0x0002 },
+ { 0x18, 0x00, -1, 0x01, 0x5842, 0x0003 },
+ { 0x18, 0x00, -1, 0x02, 0x5842, 0x0004 },
+ { 0x18, 0x00, -1, 0x03, 0x5842, 0x0005 },
+ { 0x18, 0x00, -1, 0x03, 0x5842, 0x0006 },
+ { 0x18, 0x00, -1, 0x03, 0x5842, 0x0007 },
+ { 0x18, 0x00, -1, 0x03, 0x5842, 0x0008 },
+ { 0x18, 0x00, -1, 0x03, 0x5842, 0x0009 },
+ { 0x02, 0x05, -1, 0x03, 0x000a, 0x0046 },
+ { 0x02, 0x05, -1, 0x03, 0x000a, 0x0066 },
+ { 0x02, 0x06, -1, 0x03, 0x000a, 0x0086 },
+ { 0x02, 0x07, -1, 0x03, 0x000a, 0x00c6 },
+ { 0x02, 0x08, -1, 0x03, 0x000a, 0x0146 },
+ { 0x02, 0x09, -1, 0x03, 0x000a, 0x0246 },
+ { 0x02, 0x0a, -1, 0x03, 0x000a, 0x0446 },
+ { 0x02, 0x18, -1, 0x03, 0x000a, 0x0846 },
+ { 0x02, 0x05, -1, 0x03, 0x000e, 0x0046 },
+ { 0x02, 0x05, -1, 0x03, 0x000e, 0x0066 },
+ { 0x02, 0x06, -1, 0x03, 0x000e, 0x0086 },
+ { 0x02, 0x07, -1, 0x03, 0x000e, 0x00c6 },
+ { 0x02, 0x08, -1, 0x03, 0x000e, 0x0146 },
+ { 0x02, 0x09, -1, 0x03, 0x000e, 0x0246 },
+ { 0x02, 0x0a, -1, 0x03, 0x000e, 0x0446 },
+ { 0x02, 0x18, -1, 0x03, 0x000e, 0x0846 },
+ { 0x03, 0x05, -1, 0x03, 0x0012, 0x0046 },
+ { 0x03, 0x05, -1, 0x03, 0x0012, 0x0066 },
+ { 0x03, 0x06, -1, 0x03, 0x0012, 0x0086 },
+ { 0x03, 0x07, -1, 0x03, 0x0012, 0x00c6 },
+ { 0x03, 0x08, -1, 0x03, 0x0012, 0x0146 },
+ { 0x03, 0x09, -1, 0x03, 0x0012, 0x0246 },
+ { 0x03, 0x0a, -1, 0x03, 0x0012, 0x0446 },
+ { 0x03, 0x18, -1, 0x03, 0x0012, 0x0846 },
+ { 0x03, 0x05, -1, 0x03, 0x001a, 0x0046 },
+ { 0x03, 0x05, -1, 0x03, 0x001a, 0x0066 },
+ { 0x03, 0x06, -1, 0x03, 0x001a, 0x0086 },
+ { 0x03, 0x07, -1, 0x03, 0x001a, 0x00c6 },
+ { 0x03, 0x08, -1, 0x03, 0x001a, 0x0146 },
+ { 0x03, 0x09, -1, 0x03, 0x001a, 0x0246 },
+ { 0x03, 0x0a, -1, 0x03, 0x001a, 0x0446 },
+ { 0x03, 0x18, -1, 0x03, 0x001a, 0x0846 },
+ { 0x04, 0x05, -1, 0x03, 0x0022, 0x0046 },
+ { 0x04, 0x05, -1, 0x03, 0x0022, 0x0066 },
+ { 0x04, 0x06, -1, 0x03, 0x0022, 0x0086 },
+ { 0x04, 0x07, -1, 0x03, 0x0022, 0x00c6 },
+ { 0x04, 0x08, -1, 0x03, 0x0022, 0x0146 },
+ { 0x04, 0x09, -1, 0x03, 0x0022, 0x0246 },
+ { 0x04, 0x0a, -1, 0x03, 0x0022, 0x0446 },
+ { 0x04, 0x18, -1, 0x03, 0x0022, 0x0846 },
+ { 0x04, 0x05, -1, 0x03, 0x0032, 0x0046 },
+ { 0x04, 0x05, -1, 0x03, 0x0032, 0x0066 },
+ { 0x04, 0x06, -1, 0x03, 0x0032, 0x0086 },
+ { 0x04, 0x07, -1, 0x03, 0x0032, 0x00c6 },
+ { 0x04, 0x08, -1, 0x03, 0x0032, 0x0146 },
+ { 0x04, 0x09, -1, 0x03, 0x0032, 0x0246 },
+ { 0x04, 0x0a, -1, 0x03, 0x0032, 0x0446 },
+ { 0x04, 0x18, -1, 0x03, 0x0032, 0x0846 },
+ { 0x05, 0x05, -1, 0x03, 0x0042, 0x0046 },
+ { 0x05, 0x05, -1, 0x03, 0x0042, 0x0066 },
+ { 0x05, 0x06, -1, 0x03, 0x0042, 0x0086 },
+ { 0x05, 0x07, -1, 0x03, 0x0042, 0x00c6 },
+ { 0x05, 0x08, -1, 0x03, 0x0042, 0x0146 },
+ { 0x05, 0x09, -1, 0x03, 0x0042, 0x0246 },
+ { 0x05, 0x0a, -1, 0x03, 0x0042, 0x0446 },
+ { 0x05, 0x18, -1, 0x03, 0x0042, 0x0846 },
+ { 0x05, 0x05, -1, 0x03, 0x0062, 0x0046 },
+ { 0x05, 0x05, -1, 0x03, 0x0062, 0x0066 },
+ { 0x05, 0x06, -1, 0x03, 0x0062, 0x0086 },
+ { 0x05, 0x07, -1, 0x03, 0x0062, 0x00c6 },
+ { 0x05, 0x08, -1, 0x03, 0x0062, 0x0146 },
+ { 0x05, 0x09, -1, 0x03, 0x0062, 0x0246 },
+ { 0x05, 0x0a, -1, 0x03, 0x0062, 0x0446 },
+ { 0x05, 0x18, -1, 0x03, 0x0062, 0x0846 },
+ { 0x06, 0x01, -1, 0x03, 0x0082, 0x000a },
+ { 0x06, 0x01, -1, 0x03, 0x0082, 0x000c },
+ { 0x06, 0x02, -1, 0x03, 0x0082, 0x000e },
+ { 0x06, 0x02, -1, 0x03, 0x0082, 0x0012 },
+ { 0x06, 0x03, -1, 0x03, 0x0082, 0x0016 },
+ { 0x06, 0x03, -1, 0x03, 0x0082, 0x001e },
+ { 0x06, 0x04, -1, 0x03, 0x0082, 0x0026 },
+ { 0x06, 0x04, -1, 0x03, 0x0082, 0x0036 },
+ { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000a },
+ { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000c },
+ { 0x07, 0x02, -1, 0x03, 0x00c2, 0x000e },
+ { 0x07, 0x02, -1, 0x03, 0x00c2, 0x0012 },
+ { 0x07, 0x03, -1, 0x03, 0x00c2, 0x0016 },
+ { 0x07, 0x03, -1, 0x03, 0x00c2, 0x001e },
+ { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0026 },
+ { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0036 },
+ { 0x08, 0x01, -1, 0x03, 0x0142, 0x000a },
+ { 0x08, 0x01, -1, 0x03, 0x0142, 0x000c },
+ { 0x08, 0x02, -1, 0x03, 0x0142, 0x000e },
+ { 0x08, 0x02, -1, 0x03, 0x0142, 0x0012 },
+ { 0x08, 0x03, -1, 0x03, 0x0142, 0x0016 },
+ { 0x08, 0x03, -1, 0x03, 0x0142, 0x001e },
+ { 0x08, 0x04, -1, 0x03, 0x0142, 0x0026 },
+ { 0x08, 0x04, -1, 0x03, 0x0142, 0x0036 },
+ { 0x09, 0x01, -1, 0x03, 0x0242, 0x000a },
+ { 0x09, 0x01, -1, 0x03, 0x0242, 0x000c },
+ { 0x09, 0x02, -1, 0x03, 0x0242, 0x000e },
+ { 0x09, 0x02, -1, 0x03, 0x0242, 0x0012 },
+ { 0x09, 0x03, -1, 0x03, 0x0242, 0x0016 },
+ { 0x09, 0x03, -1, 0x03, 0x0242, 0x001e },
+ { 0x09, 0x04, -1, 0x03, 0x0242, 0x0026 },
+ { 0x09, 0x04, -1, 0x03, 0x0242, 0x0036 },
+ { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000a },
+ { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000c },
+ { 0x0a, 0x02, -1, 0x03, 0x0442, 0x000e },
+ { 0x0a, 0x02, -1, 0x03, 0x0442, 0x0012 },
+ { 0x0a, 0x03, -1, 0x03, 0x0442, 0x0016 },
+ { 0x0a, 0x03, -1, 0x03, 0x0442, 0x001e },
+ { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0026 },
+ { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0036 },
+ { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000a },
+ { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000c },
+ { 0x0c, 0x02, -1, 0x03, 0x0842, 0x000e },
+ { 0x0c, 0x02, -1, 0x03, 0x0842, 0x0012 },
+ { 0x0c, 0x03, -1, 0x03, 0x0842, 0x0016 },
+ { 0x0c, 0x03, -1, 0x03, 0x0842, 0x001e },
+ { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0026 },
+ { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0036 },
+ { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000a },
+ { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000c },
+ { 0x0e, 0x02, -1, 0x03, 0x1842, 0x000e },
+ { 0x0e, 0x02, -1, 0x03, 0x1842, 0x0012 },
+ { 0x0e, 0x03, -1, 0x03, 0x1842, 0x0016 },
+ { 0x0e, 0x03, -1, 0x03, 0x1842, 0x001e },
+ { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0026 },
+ { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0036 },
+ { 0x18, 0x01, -1, 0x03, 0x5842, 0x000a },
+ { 0x18, 0x01, -1, 0x03, 0x5842, 0x000c },
+ { 0x18, 0x02, -1, 0x03, 0x5842, 0x000e },
+ { 0x18, 0x02, -1, 0x03, 0x5842, 0x0012 },
+ { 0x18, 0x03, -1, 0x03, 0x5842, 0x0016 },
+ { 0x18, 0x03, -1, 0x03, 0x5842, 0x001e },
+ { 0x18, 0x04, -1, 0x03, 0x5842, 0x0026 },
+ { 0x18, 0x04, -1, 0x03, 0x5842, 0x0036 },
+ { 0x06, 0x05, -1, 0x03, 0x0082, 0x0046 },
+ { 0x06, 0x05, -1, 0x03, 0x0082, 0x0066 },
+ { 0x06, 0x06, -1, 0x03, 0x0082, 0x0086 },
+ { 0x06, 0x07, -1, 0x03, 0x0082, 0x00c6 },
+ { 0x06, 0x08, -1, 0x03, 0x0082, 0x0146 },
+ { 0x06, 0x09, -1, 0x03, 0x0082, 0x0246 },
+ { 0x06, 0x0a, -1, 0x03, 0x0082, 0x0446 },
+ { 0x06, 0x18, -1, 0x03, 0x0082, 0x0846 },
+ { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0046 },
+ { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0066 },
+ { 0x07, 0x06, -1, 0x03, 0x00c2, 0x0086 },
+ { 0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6 },
+ { 0x07, 0x08, -1, 0x03, 0x00c2, 0x0146 },
+ { 0x07, 0x09, -1, 0x03, 0x00c2, 0x0246 },
+ { 0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446 },
+ { 0x07, 0x18, -1, 0x03, 0x00c2, 0x0846 },
+ { 0x08, 0x05, -1, 0x03, 0x0142, 0x0046 },
+ { 0x08, 0x05, -1, 0x03, 0x0142, 0x0066 },
+ { 0x08, 0x06, -1, 0x03, 0x0142, 0x0086 },
+ { 0x08, 0x07, -1, 0x03, 0x0142, 0x00c6 },
+ { 0x08, 0x08, -1, 0x03, 0x0142, 0x0146 },
+ { 0x08, 0x09, -1, 0x03, 0x0142, 0x0246 },
+ { 0x08, 0x0a, -1, 0x03, 0x0142, 0x0446 },
+ { 0x08, 0x18, -1, 0x03, 0x0142, 0x0846 },
+ { 0x09, 0x05, -1, 0x03, 0x0242, 0x0046 },
+ { 0x09, 0x05, -1, 0x03, 0x0242, 0x0066 },
+ { 0x09, 0x06, -1, 0x03, 0x0242, 0x0086 },
+ { 0x09, 0x07, -1, 0x03, 0x0242, 0x00c6 },
+ { 0x09, 0x08, -1, 0x03, 0x0242, 0x0146 },
+ { 0x09, 0x09, -1, 0x03, 0x0242, 0x0246 },
+ { 0x09, 0x0a, -1, 0x03, 0x0242, 0x0446 },
+ { 0x09, 0x18, -1, 0x03, 0x0242, 0x0846 },
+ { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0046 },
+ { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0066 },
+ { 0x0a, 0x06, -1, 0x03, 0x0442, 0x0086 },
+ { 0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6 },
+ { 0x0a, 0x08, -1, 0x03, 0x0442, 0x0146 },
+ { 0x0a, 0x09, -1, 0x03, 0x0442, 0x0246 },
+ { 0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446 },
+ { 0x0a, 0x18, -1, 0x03, 0x0442, 0x0846 },
+ { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0046 },
+ { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0066 },
+ { 0x0c, 0x06, -1, 0x03, 0x0842, 0x0086 },
+ { 0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6 },
+ { 0x0c, 0x08, -1, 0x03, 0x0842, 0x0146 },
+ { 0x0c, 0x09, -1, 0x03, 0x0842, 0x0246 },
+ { 0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446 },
+ { 0x0c, 0x18, -1, 0x03, 0x0842, 0x0846 },
+ { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0046 },
+ { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0066 },
+ { 0x0e, 0x06, -1, 0x03, 0x1842, 0x0086 },
+ { 0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6 },
+ { 0x0e, 0x08, -1, 0x03, 0x1842, 0x0146 },
+ { 0x0e, 0x09, -1, 0x03, 0x1842, 0x0246 },
+ { 0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446 },
+ { 0x0e, 0x18, -1, 0x03, 0x1842, 0x0846 },
+ { 0x18, 0x05, -1, 0x03, 0x5842, 0x0046 },
+ { 0x18, 0x05, -1, 0x03, 0x5842, 0x0066 },
+ { 0x18, 0x06, -1, 0x03, 0x5842, 0x0086 },
+ { 0x18, 0x07, -1, 0x03, 0x5842, 0x00c6 },
+ { 0x18, 0x08, -1, 0x03, 0x5842, 0x0146 },
+ { 0x18, 0x09, -1, 0x03, 0x5842, 0x0246 },
+ { 0x18, 0x0a, -1, 0x03, 0x5842, 0x0446 },
+ { 0x18, 0x18, -1, 0x03, 0x5842, 0x0846 },
+};
+
+#endif /* BROTLI_DEC_PREFIX_H_ */
diff --git a/thirdparty/brotli/dec/state.c b/thirdparty/brotli/dec/state.c
new file mode 100644
index 0000000000..e3170c1386
--- /dev/null
+++ b/thirdparty/brotli/dec/state.c
@@ -0,0 +1,165 @@
+/* Copyright 2015 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+#include "state.h"
+
+#include <stdlib.h> /* free, malloc */
+
+#include "../common/dictionary.h"
+#include <brotli/types.h>
+#include "huffman.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
+ if (!alloc_func) {
+ s->alloc_func = BrotliDefaultAllocFunc;
+ s->free_func = BrotliDefaultFreeFunc;
+ s->memory_manager_opaque = 0;
+ } else {
+ s->alloc_func = alloc_func;
+ s->free_func = free_func;
+ s->memory_manager_opaque = opaque;
+ }
+
+ s->error_code = 0; /* BROTLI_DECODER_NO_ERROR */
+
+ BrotliInitBitReader(&s->br);
+ s->state = BROTLI_STATE_UNINITED;
+ s->large_window = 0;
+ s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
+ s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
+ s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
+ s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
+
+ s->buffer_length = 0;
+ s->loop_counter = 0;
+ s->pos = 0;
+ s->rb_roundtrips = 0;
+ s->partial_pos_out = 0;
+
+ s->block_type_trees = NULL;
+ s->block_len_trees = NULL;
+ s->ringbuffer = NULL;
+ s->ringbuffer_size = 0;
+ s->new_ringbuffer_size = 0;
+ s->ringbuffer_mask = 0;
+
+ s->context_map = NULL;
+ s->context_modes = NULL;
+ s->dist_context_map = NULL;
+ s->context_map_slice = NULL;
+ s->dist_context_map_slice = NULL;
+
+ s->literal_hgroup.codes = NULL;
+ s->literal_hgroup.htrees = NULL;
+ s->insert_copy_hgroup.codes = NULL;
+ s->insert_copy_hgroup.htrees = NULL;
+ s->distance_hgroup.codes = NULL;
+ s->distance_hgroup.htrees = NULL;
+
+ s->is_last_metablock = 0;
+ s->is_uncompressed = 0;
+ s->is_metadata = 0;
+ s->should_wrap_ringbuffer = 0;
+ s->canny_ringbuffer_allocation = 1;
+
+ s->window_bits = 0;
+ s->max_distance = 0;
+ s->dist_rb[0] = 16;
+ s->dist_rb[1] = 15;
+ s->dist_rb[2] = 11;
+ s->dist_rb[3] = 4;
+ s->dist_rb_idx = 0;
+ s->block_type_trees = NULL;
+ s->block_len_trees = NULL;
+
+ s->mtf_upper_bound = 63;
+
+ s->compound_dictionary = NULL;
+ s->dictionary =
+ BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);
+ if (!s->dictionary) return BROTLI_FALSE;
+
+ return BROTLI_TRUE;
+}
+
+void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) {
+ s->meta_block_remaining_len = 0;
+ s->block_length[0] = 1U << 24;
+ s->block_length[1] = 1U << 24;
+ s->block_length[2] = 1U << 24;
+ s->num_block_types[0] = 1;
+ s->num_block_types[1] = 1;
+ s->num_block_types[2] = 1;
+ s->block_type_rb[0] = 1;
+ s->block_type_rb[1] = 0;
+ s->block_type_rb[2] = 1;
+ s->block_type_rb[3] = 0;
+ s->block_type_rb[4] = 1;
+ s->block_type_rb[5] = 0;
+ s->context_map = NULL;
+ s->context_modes = NULL;
+ s->dist_context_map = NULL;
+ s->context_map_slice = NULL;
+ s->literal_htree = NULL;
+ s->dist_context_map_slice = NULL;
+ s->dist_htree_index = 0;
+ s->context_lookup = NULL;
+ s->literal_hgroup.codes = NULL;
+ s->literal_hgroup.htrees = NULL;
+ s->insert_copy_hgroup.codes = NULL;
+ s->insert_copy_hgroup.htrees = NULL;
+ s->distance_hgroup.codes = NULL;
+ s->distance_hgroup.htrees = NULL;
+}
+
+void BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {
+ BROTLI_DECODER_FREE(s, s->context_modes);
+ BROTLI_DECODER_FREE(s, s->context_map);
+ BROTLI_DECODER_FREE(s, s->dist_context_map);
+ BROTLI_DECODER_FREE(s, s->literal_hgroup.htrees);
+ BROTLI_DECODER_FREE(s, s->insert_copy_hgroup.htrees);
+ BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);
+}
+
+void BrotliDecoderStateCleanup(BrotliDecoderState* s) {
+ BrotliDecoderStateCleanupAfterMetablock(s);
+
+ BROTLI_DECODER_FREE(s, s->compound_dictionary);
+ BrotliSharedDictionaryDestroyInstance(s->dictionary);
+ s->dictionary = NULL;
+ BROTLI_DECODER_FREE(s, s->ringbuffer);
+ BROTLI_DECODER_FREE(s, s->block_type_trees);
+}
+
+BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,
+ HuffmanTreeGroup* group, uint32_t alphabet_size_max,
+ uint32_t alphabet_size_limit, uint32_t ntrees) {
+ /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)
+ This number is discovered "unlimited" "enough" calculator; it is actually
+ a wee bigger than required in several cases (especially for alphabets with
+ less than 16 symbols). */
+ const size_t max_table_size = alphabet_size_limit + 376;
+ const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
+ const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
+ /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */
+ HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,
+ code_size + htree_size);
+ group->alphabet_size_max = (uint16_t)alphabet_size_max;
+ group->alphabet_size_limit = (uint16_t)alphabet_size_limit;
+ group->num_htrees = (uint16_t)ntrees;
+ group->htrees = p;
+ group->codes = (HuffmanCode*)(&p[ntrees]);
+ return !!p;
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
diff --git a/thirdparty/brotli/dec/state.h b/thirdparty/brotli/dec/state.h
new file mode 100644
index 0000000000..81e6bb6779
--- /dev/null
+++ b/thirdparty/brotli/dec/state.h
@@ -0,0 +1,380 @@
+/* Copyright 2015 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Brotli state for partial streaming decoding. */
+
+#ifndef BROTLI_DEC_STATE_H_
+#define BROTLI_DEC_STATE_H_
+
+#include "../common/constants.h"
+#include "../common/dictionary.h"
+#include "../common/platform.h"
+#include <brotli/shared_dictionary.h>
+#include "../common/transform.h"
+#include <brotli/types.h>
+#include "bit_reader.h"
+#include "huffman.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* Graphviz diagram that describes state transitions:
+
+digraph States {
+ graph [compound=true]
+ concentrate=true
+ node [shape="box"]
+
+ UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}
+ subgraph cluster_metablock_workflow {
+ style="rounded"
+ label=< <B>METABLOCK CYCLE</B> >
+ METABLOCK_BEGIN -> METABLOCK_HEADER
+ METABLOCK_HEADER:sw -> METADATA
+ METABLOCK_HEADER:s -> UNCOMPRESSED
+ METABLOCK_HEADER:se -> METABLOCK_DONE:ne
+ METADATA:s -> METABLOCK_DONE:w
+ UNCOMPRESSED:s -> METABLOCK_DONE:n
+ METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint="false"]
+ }
+ INITIALIZE -> METABLOCK_BEGIN
+ METABLOCK_DONE -> DONE
+
+ subgraph cluster_compressed_metablock {
+ style="rounded"
+ label=< <B>COMPRESSED METABLOCK</B> >
+
+ subgraph cluster_command {
+ style="rounded"
+ label=< <B>HOT LOOP</B> >
+
+ _METABLOCK_DONE_PORT_ [shape=point style=invis]
+
+ {
+ // Set different shape for nodes returning from "compressed metablock".
+ node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;
+ CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;
+ }
+
+ CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY
+
+ // IO ("write") nodes are not in the hot loop!
+ CMD_INNER_WRITE [style=dashed]
+ CMD_INNER -> CMD_INNER_WRITE
+ CMD_POST_WRITE_1 [style=dashed]
+ CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1
+ CMD_POST_WRITE_2 [style=dashed]
+ CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2
+
+ CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint="false"]
+ CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}
+ [constraint="false"]
+ CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint="false"]
+ CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint="false"]
+ CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint="false"]
+ CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint="false"]
+ {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;
+ CMD_POST_WRAP_COPY}
+ {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}
+
+ {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->
+ _METABLOCK_DONE_PORT_ [style=invis]
+ {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_
+ [constraint="false" style=invis]
+ }
+
+ BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n
+ HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3
+ HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1
+ CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP
+ TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e
+ BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n
+
+ HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint="false"]
+ {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}
+ {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;
+ TREE_GROUP}
+ }
+ METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n
+
+ _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se
+ [constraint="false" ltail=cluster_command]
+
+ UNINITED [shape=Mdiamond];
+ DONE [shape=Msquare];
+}
+
+
+ */
+
+typedef enum {
+ BROTLI_STATE_UNINITED,
+ BROTLI_STATE_LARGE_WINDOW_BITS,
+ BROTLI_STATE_INITIALIZE,
+ BROTLI_STATE_METABLOCK_BEGIN,
+ BROTLI_STATE_METABLOCK_HEADER,
+ BROTLI_STATE_METABLOCK_HEADER_2,
+ BROTLI_STATE_CONTEXT_MODES,
+ BROTLI_STATE_COMMAND_BEGIN,
+ BROTLI_STATE_COMMAND_INNER,
+ BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
+ BROTLI_STATE_COMMAND_POST_WRAP_COPY,
+ BROTLI_STATE_UNCOMPRESSED,
+ BROTLI_STATE_METADATA,
+ BROTLI_STATE_COMMAND_INNER_WRITE,
+ BROTLI_STATE_METABLOCK_DONE,
+ BROTLI_STATE_COMMAND_POST_WRITE_1,
+ BROTLI_STATE_COMMAND_POST_WRITE_2,
+ BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,
+ BROTLI_STATE_HUFFMAN_CODE_0,
+ BROTLI_STATE_HUFFMAN_CODE_1,
+ BROTLI_STATE_HUFFMAN_CODE_2,
+ BROTLI_STATE_HUFFMAN_CODE_3,
+ BROTLI_STATE_CONTEXT_MAP_1,
+ BROTLI_STATE_CONTEXT_MAP_2,
+ BROTLI_STATE_TREE_GROUP,
+ BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,
+ BROTLI_STATE_DONE
+} BrotliRunningState;
+
+typedef enum {
+ BROTLI_STATE_METABLOCK_HEADER_NONE,
+ BROTLI_STATE_METABLOCK_HEADER_EMPTY,
+ BROTLI_STATE_METABLOCK_HEADER_NIBBLES,
+ BROTLI_STATE_METABLOCK_HEADER_SIZE,
+ BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,
+ BROTLI_STATE_METABLOCK_HEADER_RESERVED,
+ BROTLI_STATE_METABLOCK_HEADER_BYTES,
+ BROTLI_STATE_METABLOCK_HEADER_METADATA
+} BrotliRunningMetablockHeaderState;
+
+typedef enum {
+ BROTLI_STATE_UNCOMPRESSED_NONE,
+ BROTLI_STATE_UNCOMPRESSED_WRITE
+} BrotliRunningUncompressedState;
+
+typedef enum {
+ BROTLI_STATE_TREE_GROUP_NONE,
+ BROTLI_STATE_TREE_GROUP_LOOP
+} BrotliRunningTreeGroupState;
+
+typedef enum {
+ BROTLI_STATE_CONTEXT_MAP_NONE,
+ BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
+ BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
+ BROTLI_STATE_CONTEXT_MAP_DECODE,
+ BROTLI_STATE_CONTEXT_MAP_TRANSFORM
+} BrotliRunningContextMapState;
+
+typedef enum {
+ BROTLI_STATE_HUFFMAN_NONE,
+ BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
+ BROTLI_STATE_HUFFMAN_SIMPLE_READ,
+ BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
+ BROTLI_STATE_HUFFMAN_COMPLEX,
+ BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS
+} BrotliRunningHuffmanState;
+
+typedef enum {
+ BROTLI_STATE_DECODE_UINT8_NONE,
+ BROTLI_STATE_DECODE_UINT8_SHORT,
+ BROTLI_STATE_DECODE_UINT8_LONG
+} BrotliRunningDecodeUint8State;
+
+typedef enum {
+ BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
+ BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
+} BrotliRunningReadBlockLengthState;
+
+/* BrotliDecoderState addon, used for Compound Dictionary functionality. */
+typedef struct BrotliDecoderCompoundDictionary {
+ int num_chunks;
+ int total_size;
+ int br_index;
+ int br_offset;
+ int br_length;
+ int br_copied;
+ const uint8_t* chunks[16];
+ int chunk_offsets[16];
+ int block_bits;
+ uint8_t block_map[256];
+} BrotliDecoderCompoundDictionary;
+
+typedef struct BrotliMetablockHeaderArena {
+ BrotliRunningTreeGroupState substate_tree_group;
+ BrotliRunningContextMapState substate_context_map;
+ BrotliRunningHuffmanState substate_huffman;
+
+ uint32_t sub_loop_counter;
+
+ uint32_t repeat_code_len;
+ uint32_t prev_code_len;
+
+ /* For ReadHuffmanCode. */
+ uint32_t symbol;
+ uint32_t repeat;
+ uint32_t space;
+
+ /* Huffman table for "histograms". */
+ HuffmanCode table[32];
+ /* List of heads of symbol chains. */
+ uint16_t* symbol_lists;
+ /* Storage from symbol_lists. */
+ uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +
+ BROTLI_NUM_COMMAND_SYMBOLS];
+ /* Tails of symbol chains. */
+ int next_symbol[32];
+ uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];
+ /* Population counts for the code lengths. */
+ uint16_t code_length_histo[16];
+
+ /* For HuffmanTreeGroupDecode. */
+ int htree_index;
+ HuffmanCode* next;
+
+ /* For DecodeContextMap. */
+ uint32_t context_index;
+ uint32_t max_run_length_prefix;
+ uint32_t code;
+ HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
+} BrotliMetablockHeaderArena;
+
+typedef struct BrotliMetablockBodyArena {
+ uint8_t dist_extra_bits[544];
+ uint32_t dist_offset[544];
+} BrotliMetablockBodyArena;
+
+struct BrotliDecoderStateStruct {
+ BrotliRunningState state;
+
+ /* This counter is reused for several disjoint loops. */
+ int loop_counter;
+
+ BrotliBitReader br;
+
+ brotli_alloc_func alloc_func;
+ brotli_free_func free_func;
+ void* memory_manager_opaque;
+
+ /* Temporary storage for remaining input. Brotli stream format is designed in
+ a way, that 64 bits are enough to make progress in decoding. */
+ union {
+ uint64_t u64;
+ uint8_t u8[8];
+ } buffer;
+ uint32_t buffer_length;
+
+ int pos;
+ int max_backward_distance;
+ int max_distance;
+ int ringbuffer_size;
+ int ringbuffer_mask;
+ int dist_rb_idx;
+ int dist_rb[4];
+ int error_code;
+ uint8_t* ringbuffer;
+ uint8_t* ringbuffer_end;
+ HuffmanCode* htree_command;
+ const uint8_t* context_lookup;
+ uint8_t* context_map_slice;
+ uint8_t* dist_context_map_slice;
+
+ /* This ring buffer holds a few past copy distances that will be used by
+ some special distance codes. */
+ HuffmanTreeGroup literal_hgroup;
+ HuffmanTreeGroup insert_copy_hgroup;
+ HuffmanTreeGroup distance_hgroup;
+ HuffmanCode* block_type_trees;
+ HuffmanCode* block_len_trees;
+ /* This is true if the literal context map histogram type always matches the
+ block type. It is then not needed to keep the context (faster decoding). */
+ int trivial_literal_context;
+ /* Distance context is actual after command is decoded and before distance is
+ computed. After distance computation it is used as a temporary variable. */
+ int distance_context;
+ int meta_block_remaining_len;
+ uint32_t block_length_index;
+ uint32_t block_length[3];
+ uint32_t num_block_types[3];
+ uint32_t block_type_rb[6];
+ uint32_t distance_postfix_bits;
+ uint32_t num_direct_distance_codes;
+ uint32_t num_dist_htrees;
+ uint8_t* dist_context_map;
+ HuffmanCode* literal_htree;
+ uint8_t dist_htree_index;
+
+ int copy_length;
+ int distance_code;
+
+ /* For partial write operations. */
+ size_t rb_roundtrips; /* how many times we went around the ring-buffer */
+ size_t partial_pos_out; /* how much output to the user in total */
+
+ /* For InverseMoveToFrontTransform. */
+ uint32_t mtf_upper_bound;
+ uint32_t mtf[64 + 1];
+
+ /* Less used attributes are at the end of this struct. */
+
+ /* States inside function calls. */
+ BrotliRunningMetablockHeaderState substate_metablock_header;
+ BrotliRunningUncompressedState substate_uncompressed;
+ BrotliRunningDecodeUint8State substate_decode_uint8;
+ BrotliRunningReadBlockLengthState substate_read_block_length;
+
+ unsigned int is_last_metablock : 1;
+ unsigned int is_uncompressed : 1;
+ unsigned int is_metadata : 1;
+ unsigned int should_wrap_ringbuffer : 1;
+ unsigned int canny_ringbuffer_allocation : 1;
+ unsigned int large_window : 1;
+ unsigned int size_nibbles : 8;
+ uint32_t window_bits;
+
+ int new_ringbuffer_size;
+
+ uint32_t num_literal_htrees;
+ uint8_t* context_map;
+ uint8_t* context_modes;
+
+ BrotliSharedDictionary* dictionary;
+ BrotliDecoderCompoundDictionary* compound_dictionary;
+
+ uint32_t trivial_literal_contexts[8]; /* 256 bits */
+
+ union {
+ BrotliMetablockHeaderArena header;
+ BrotliMetablockBodyArena body;
+ } arena;
+};
+
+typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;
+#define BrotliDecoderState BrotliDecoderStateInternal
+
+BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
+BROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState* s);
+BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);
+BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(
+ BrotliDecoderState* s);
+BROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(
+ BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size_max,
+ uint32_t alphabet_size_limit, uint32_t ntrees);
+
+#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)
+
+#define BROTLI_DECODER_FREE(S, X) { \
+ S->free_func(S->memory_manager_opaque, X); \
+ X = NULL; \
+}
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_DEC_STATE_H_ */
diff --git a/thirdparty/brotli/include/brotli/decode.h b/thirdparty/brotli/include/brotli/decode.h
new file mode 100644
index 0000000000..9b580d22a0
--- /dev/null
+++ b/thirdparty/brotli/include/brotli/decode.h
@@ -0,0 +1,368 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/**
+ * @file
+ * API for Brotli decompression.
+ */
+
+#ifndef BROTLI_DEC_DECODE_H_
+#define BROTLI_DEC_DECODE_H_
+
+#include <brotli/port.h>
+#include <brotli/shared_dictionary.h>
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/**
+ * Opaque structure that holds decoder state.
+ *
+ * Allocated and initialized with ::BrotliDecoderCreateInstance.
+ * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance.
+ */
+typedef struct BrotliDecoderStateStruct BrotliDecoderState;
+
+/**
+ * Result type for ::BrotliDecoderDecompress and
+ * ::BrotliDecoderDecompressStream functions.
+ */
+typedef enum {
+ /** Decoding error, e.g. corrupted input or memory allocation problem. */
+ BROTLI_DECODER_RESULT_ERROR = 0,
+ /** Decoding successfully completed. */
+ BROTLI_DECODER_RESULT_SUCCESS = 1,
+ /** Partially done; should be called again with more input. */
+ BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2,
+ /** Partially done; should be called again with more output. */
+ BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3
+} BrotliDecoderResult;
+
+/**
+ * Template that evaluates items of ::BrotliDecoderErrorCode.
+ *
+ * Example: @code {.cpp}
+ * // Log Brotli error code.
+ * switch (brotliDecoderErrorCode) {
+ * #define CASE_(PREFIX, NAME, CODE) \
+ * case BROTLI_DECODER ## PREFIX ## NAME: \
+ * LOG(INFO) << "error code:" << #NAME; \
+ * break;
+ * #define NEWLINE_
+ * BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_)
+ * #undef CASE_
+ * #undef NEWLINE_
+ * default: LOG(FATAL) << "unknown brotli error code";
+ * }
+ * @endcode
+ */
+#define BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR) \
+ BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR \
+ /* Same as BrotliDecoderResult values */ \
+ BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR \
+ BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR \
+ BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR \
+ \
+ /* Errors caused by invalid input */ \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR \
+ \
+ /* -17 code is reserved */ \
+ \
+ BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR \
+ \
+ /* Memory allocation problems */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR \
+ /* Literal, insert and distance trees together */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR \
+ /* -23..-24 codes are reserved for distinct tree groups */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR \
+ /* -28..-29 codes are reserved for dynamic ring-buffer allocation */ \
+ BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR \
+ \
+ /* "Impossible" states */ \
+ BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31)
+
+/**
+ * Error code for detailed logging / production debugging.
+ *
+ * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE.
+ */
+typedef enum {
+#define BROTLI_COMMA_ ,
+#define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \
+ BROTLI_DECODER ## PREFIX ## NAME = CODE
+ BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_)
+} BrotliDecoderErrorCode;
+#undef BROTLI_ERROR_CODE_ENUM_ITEM_
+#undef BROTLI_COMMA_
+
+/**
+ * The value of the last error code, negative integer.
+ *
+ * All other error code values are in the range from ::BROTLI_LAST_ERROR_CODE
+ * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in
+ * ::BrotliDecoderErrorCode enumeration.
+ */
+#define BROTLI_LAST_ERROR_CODE BROTLI_DECODER_ERROR_UNREACHABLE
+
+/** Options to be used with ::BrotliDecoderSetParameter. */
+typedef enum BrotliDecoderParameter {
+ /**
+ * Disable "canny" ring buffer allocation strategy.
+ *
+ * Ring buffer is allocated according to window size, despite the real size of
+ * the content.
+ */
+ BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0,
+ /**
+ * Flag that determines if "Large Window Brotli" is used.
+ */
+ BROTLI_DECODER_PARAM_LARGE_WINDOW = 1
+} BrotliDecoderParameter;
+
+/**
+ * Sets the specified parameter to the given decoder instance.
+ *
+ * @param state decoder instance
+ * @param param parameter to set
+ * @param value new parameter value
+ * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid
+ * @returns ::BROTLI_TRUE if value is accepted
+ */
+BROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(
+ BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value);
+
+/**
+ * Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and
+ * transforms.
+ *
+ * Attached dictionary ownership is not transferred.
+ * Data provided to this method should be kept accessible until
+ * decoding is finished and decoder instance is destroyed.
+ *
+ * @note Dictionaries can NOT be attached after actual decoding is started.
+ *
+ * @param state decoder instance
+ * @param type dictionary data format
+ * @param data_size length of memory region pointed by @p data
+ * @param data dictionary data in format corresponding to @p type
+ * @returns ::BROTLI_FALSE if dictionary is corrupted,
+ * or dictionary count limit is reached
+ * @returns ::BROTLI_TRUE if dictionary is accepted / attached
+ */
+BROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary(
+ BrotliDecoderState* state, BrotliSharedDictionaryType type,
+ size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);
+
+/**
+ * Creates an instance of ::BrotliDecoderState and initializes it.
+ *
+ * The instance can be used once for decoding and should then be destroyed with
+ * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding
+ * session.
+ *
+ * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
+ * case they are both zero, default memory allocators are used. @p opaque is
+ * passed to @p alloc_func and @p free_func when they are called. @p free_func
+ * has to return without doing anything when asked to free a NULL pointer.
+ *
+ * @param alloc_func custom memory allocation function
+ * @param free_func custom memory free function
+ * @param opaque custom memory manager handle
+ * @returns @c 0 if instance can not be allocated or initialized
+ * @returns pointer to initialized ::BrotliDecoderState otherwise
+ */
+BROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance(
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
+
+/**
+ * Deinitializes and frees ::BrotliDecoderState instance.
+ *
+ * @param state decoder instance to be cleaned up and deallocated
+ */
+BROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state);
+
+/**
+ * Performs one-shot memory-to-memory decompression.
+ *
+ * Decompresses the data in @p encoded_buffer into @p decoded_buffer, and sets
+ * @p *decoded_size to the decompressed length.
+ *
+ * @param encoded_size size of @p encoded_buffer
+ * @param encoded_buffer compressed data buffer with at least @p encoded_size
+ * addressable bytes
+ * @param[in, out] decoded_size @b in: size of @p decoded_buffer; \n
+ * @b out: length of decompressed data written to
+ * @p decoded_buffer
+ * @param decoded_buffer decompressed data destination buffer
+ * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory
+ * allocation failed, or @p decoded_buffer is not large enough;
+ * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise
+ */
+BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress(
+ size_t encoded_size,
+ const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],
+ size_t* decoded_size,
+ uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);
+
+/**
+ * Decompresses the input stream to the output stream.
+ *
+ * The values @p *available_in and @p *available_out must specify the number of
+ * bytes addressable at @p *next_in and @p *next_out respectively.
+ * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.
+ *
+ * After each call, @p *available_in will be decremented by the amount of input
+ * bytes consumed, and the @p *next_in pointer will be incremented by that
+ * amount. Similarly, @p *available_out will be decremented by the amount of
+ * output bytes written, and the @p *next_out pointer will be incremented by
+ * that amount.
+ *
+ * @p total_out, if it is not a null-pointer, will be set to the number
+ * of bytes decompressed since the last @p state initialization.
+ *
+ * @note Input is never overconsumed, so @p next_in and @p available_in could be
+ * passed to the next consumer after decoding is complete.
+ *
+ * @param state decoder instance
+ * @param[in, out] available_in @b in: amount of available input; \n
+ * @b out: amount of unused input
+ * @param[in, out] next_in pointer to the next compressed byte
+ * @param[in, out] available_out @b in: length of output buffer; \n
+ * @b out: remaining size of output buffer
+ * @param[in, out] next_out output buffer cursor;
+ * can be @c NULL if @p available_out is @c 0
+ * @param[out] total_out number of bytes decompressed so far; can be @c NULL
+ * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory
+ * allocation failed, arguments were invalid, etc.;
+ * use ::BrotliDecoderGetErrorCode to get detailed error code
+ * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT decoding is blocked until
+ * more input data is provided
+ * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT decoding is blocked until
+ * more output space is provided
+ * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more
+ * input might be consumed and no more output will be produced
+ */
+BROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream(
+ BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in,
+ size_t* available_out, uint8_t** next_out, size_t* total_out);
+
+/**
+ * Checks if decoder has more output.
+ *
+ * @param state decoder instance
+ * @returns ::BROTLI_TRUE, if decoder has some unconsumed output
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput(
+ const BrotliDecoderState* state);
+
+/**
+ * Acquires pointer to internal output buffer.
+ *
+ * This method is used to make language bindings easier and more efficient:
+ * -# push data to ::BrotliDecoderDecompressStream,
+ * until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported
+ * -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific
+ * entity
+ *
+ * Also this could be useful if there is an output stream that is able to
+ * consume all the provided data (e.g. when data is saved to file system).
+ *
+ * @attention After every call to ::BrotliDecoderTakeOutput @p *size bytes of
+ * output are considered consumed for all consecutive calls to the
+ * instance methods; returned pointer becomes invalidated as well.
+ *
+ * @note Decoder output is not guaranteed to be contiguous. This means that
+ * after the size-unrestricted call to ::BrotliDecoderTakeOutput,
+ * immediate next call to ::BrotliDecoderTakeOutput may return more data.
+ *
+ * @param state decoder instance
+ * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if
+ * any amount could be handled; \n
+ * @b out: amount of data pointed by returned pointer and
+ * considered consumed; \n
+ * out value is never greater than in value, unless it is @c 0
+ * @returns pointer to output data
+ */
+BROTLI_DEC_API const uint8_t* BrotliDecoderTakeOutput(
+ BrotliDecoderState* state, size_t* size);
+
+/**
+ * Checks if instance has already consumed input.
+ *
+ * Instance that returns ::BROTLI_FALSE is considered "fresh" and could be
+ * reused.
+ *
+ * @param state decoder instance
+ * @returns ::BROTLI_TRUE if decoder has already used some input bytes
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state);
+
+/**
+ * Checks if decoder instance reached the final state.
+ *
+ * @param state decoder instance
+ * @returns ::BROTLI_TRUE if decoder is in a state where it reached the end of
+ * the input and produced all of the output
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished(
+ const BrotliDecoderState* state);
+
+/**
+ * Acquires a detailed error code.
+ *
+ * Should be used only after ::BrotliDecoderDecompressStream returns
+ * ::BROTLI_DECODER_RESULT_ERROR.
+ *
+ * See also ::BrotliDecoderErrorString
+ *
+ * @param state decoder instance
+ * @returns last saved error code
+ */
+BROTLI_DEC_API BrotliDecoderErrorCode BrotliDecoderGetErrorCode(
+ const BrotliDecoderState* state);
+
+/**
+ * Converts error code to a c-string.
+ */
+BROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);
+
+/**
+ * Gets a decoder library version.
+ *
+ * Look at BROTLI_VERSION for more information.
+ */
+BROTLI_DEC_API uint32_t BrotliDecoderVersion(void);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_DEC_DECODE_H_ */
diff --git a/thirdparty/brotli/include/brotli/encode.h b/thirdparty/brotli/include/brotli/encode.h
new file mode 100644
index 0000000000..b2c6f61e0f
--- /dev/null
+++ b/thirdparty/brotli/include/brotli/encode.h
@@ -0,0 +1,501 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/**
+ * @file
+ * API for Brotli compression.
+ */
+
+#ifndef BROTLI_ENC_ENCODE_H_
+#define BROTLI_ENC_ENCODE_H_
+
+#include <brotli/port.h>
+#include <brotli/shared_dictionary.h>
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/** Minimal value for ::BROTLI_PARAM_LGWIN parameter. */
+#define BROTLI_MIN_WINDOW_BITS 10
+/**
+ * Maximal value for ::BROTLI_PARAM_LGWIN parameter.
+ *
+ * @note equal to @c BROTLI_MAX_DISTANCE_BITS constant.
+ */
+#define BROTLI_MAX_WINDOW_BITS 24
+/**
+ * Maximal value for ::BROTLI_PARAM_LGWIN parameter
+ * in "Large Window Brotli" (32-bit).
+ */
+#define BROTLI_LARGE_MAX_WINDOW_BITS 30
+/** Minimal value for ::BROTLI_PARAM_LGBLOCK parameter. */
+#define BROTLI_MIN_INPUT_BLOCK_BITS 16
+/** Maximal value for ::BROTLI_PARAM_LGBLOCK parameter. */
+#define BROTLI_MAX_INPUT_BLOCK_BITS 24
+/** Minimal value for ::BROTLI_PARAM_QUALITY parameter. */
+#define BROTLI_MIN_QUALITY 0
+/** Maximal value for ::BROTLI_PARAM_QUALITY parameter. */
+#define BROTLI_MAX_QUALITY 11
+
+/** Options for ::BROTLI_PARAM_MODE parameter. */
+typedef enum BrotliEncoderMode {
+ /**
+ * Default compression mode.
+ *
+ * In this mode compressor does not know anything in advance about the
+ * properties of the input.
+ */
+ BROTLI_MODE_GENERIC = 0,
+ /** Compression mode for UTF-8 formatted text input. */
+ BROTLI_MODE_TEXT = 1,
+ /** Compression mode used in WOFF 2.0. */
+ BROTLI_MODE_FONT = 2
+} BrotliEncoderMode;
+
+/** Default value for ::BROTLI_PARAM_QUALITY parameter. */
+#define BROTLI_DEFAULT_QUALITY 11
+/** Default value for ::BROTLI_PARAM_LGWIN parameter. */
+#define BROTLI_DEFAULT_WINDOW 22
+/** Default value for ::BROTLI_PARAM_MODE parameter. */
+#define BROTLI_DEFAULT_MODE BROTLI_MODE_GENERIC
+
+/** Operations that can be performed by streaming encoder. */
+typedef enum BrotliEncoderOperation {
+ /**
+ * Process input.
+ *
+ * Encoder may postpone producing output, until it has processed enough input.
+ */
+ BROTLI_OPERATION_PROCESS = 0,
+ /**
+ * Produce output for all processed input.
+ *
+ * Actual flush is performed when input stream is depleted and there is enough
+ * space in output stream. This means that client should repeat
+ * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and
+ * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
+ * via ::BrotliEncoderTakeOutput, then operation should be repeated after
+ * output buffer is drained.
+ *
+ * @warning Until flush is complete, client @b SHOULD @b NOT swap,
+ * reduce or extend input stream.
+ *
+ * When flush is complete, output data will be sufficient for decoder to
+ * reproduce all the given input.
+ */
+ BROTLI_OPERATION_FLUSH = 1,
+ /**
+ * Finalize the stream.
+ *
+ * Actual finalization is performed when input stream is depleted and there is
+ * enough space in output stream. This means that client should repeat
+ * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and
+ * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired
+ * via ::BrotliEncoderTakeOutput, then operation should be repeated after
+ * output buffer is drained.
+ *
+ * @warning Until finalization is complete, client @b SHOULD @b NOT swap,
+ * reduce or extend input stream.
+ *
+ * Helper function ::BrotliEncoderIsFinished checks if stream is finalized and
+ * output fully dumped.
+ *
+ * Adding more input data to finalized stream is impossible.
+ */
+ BROTLI_OPERATION_FINISH = 2,
+ /**
+ * Emit metadata block to stream.
+ *
+ * Metadata is opaque to Brotli: neither encoder, nor decoder processes this
+ * data or relies on it. It may be used to pass some extra information from
+ * encoder client to decoder client without interfering with main data stream.
+ *
+ * @note Encoder may emit empty metadata blocks internally, to pad encoded
+ * stream to byte boundary.
+ *
+ * @warning Until emitting metadata is complete client @b SHOULD @b NOT swap,
+ * reduce or extend input stream.
+ *
+ * @warning The whole content of input buffer is considered to be the content
+ * of metadata block. Do @b NOT @e append metadata to input stream,
+ * before it is depleted with other operations.
+ *
+ * Stream is soft-flushed before metadata block is emitted. Metadata block
+ * @b MUST be no longer than than 16MiB.
+ */
+ BROTLI_OPERATION_EMIT_METADATA = 3
+} BrotliEncoderOperation;
+
+/** Options to be used with ::BrotliEncoderSetParameter. */
+typedef enum BrotliEncoderParameter {
+ /**
+ * Tune encoder for specific input.
+ *
+ * ::BrotliEncoderMode enumerates all available values.
+ */
+ BROTLI_PARAM_MODE = 0,
+ /**
+ * The main compression speed-density lever.
+ *
+ * The higher the quality, the slower the compression. Range is
+ * from ::BROTLI_MIN_QUALITY to ::BROTLI_MAX_QUALITY.
+ */
+ BROTLI_PARAM_QUALITY = 1,
+ /**
+ * Recommended sliding LZ77 window size.
+ *
+ * Encoder may reduce this value, e.g. if input is much smaller than
+ * window size.
+ *
+ * Window size is `(1 << value) - 16`.
+ *
+ * Range is from ::BROTLI_MIN_WINDOW_BITS to ::BROTLI_MAX_WINDOW_BITS.
+ */
+ BROTLI_PARAM_LGWIN = 2,
+ /**
+ * Recommended input block size.
+ *
+ * Encoder may reduce this value, e.g. if input is much smaller than input
+ * block size.
+ *
+ * Range is from ::BROTLI_MIN_INPUT_BLOCK_BITS to
+ * ::BROTLI_MAX_INPUT_BLOCK_BITS.
+ *
+ * @note Bigger input block size allows better compression, but consumes more
+ * memory. \n The rough formula of memory used for temporary input
+ * storage is `3 << lgBlock`.
+ */
+ BROTLI_PARAM_LGBLOCK = 3,
+ /**
+ * Flag that affects usage of "literal context modeling" format feature.
+ *
+ * This flag is a "decoding-speed vs compression ratio" trade-off.
+ */
+ BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4,
+ /**
+ * Estimated total input size for all ::BrotliEncoderCompressStream calls.
+ *
+ * The default value is 0, which means that the total input size is unknown.
+ */
+ BROTLI_PARAM_SIZE_HINT = 5,
+ /**
+ * Flag that determines if "Large Window Brotli" is used.
+ */
+ BROTLI_PARAM_LARGE_WINDOW = 6,
+ /**
+ * Recommended number of postfix bits (NPOSTFIX).
+ *
+ * Encoder may change this value.
+ *
+ * Range is from 0 to ::BROTLI_MAX_NPOSTFIX.
+ */
+ BROTLI_PARAM_NPOSTFIX = 7,
+ /**
+ * Recommended number of direct distance codes (NDIRECT).
+ *
+ * Encoder may change this value.
+ *
+ * Range is from 0 to (15 << NPOSTFIX) in steps of (1 << NPOSTFIX).
+ */
+ BROTLI_PARAM_NDIRECT = 8,
+ /**
+ * Number of bytes of input stream already processed by a different instance.
+ *
+ * @note It is important to configure all the encoder instances with same
+ * parameters (except this one) in order to allow all the encoded parts
+ * obey the same restrictions implied by header.
+ *
+ * If offset is not 0, then stream header is omitted.
+ * In any case output start is byte aligned, so for proper streams stitching
+ * "predecessor" stream must be flushed.
+ *
+ * Range is not artificially limited, but all the values greater or equal to
+ * maximal window size have the same effect. Values greater than 2**30 are not
+ * allowed.
+ */
+ BROTLI_PARAM_STREAM_OFFSET = 9
+} BrotliEncoderParameter;
+
+/**
+ * Opaque structure that holds encoder state.
+ *
+ * Allocated and initialized with ::BrotliEncoderCreateInstance.
+ * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance.
+ */
+typedef struct BrotliEncoderStateStruct BrotliEncoderState;
+
+/**
+ * Sets the specified parameter to the given encoder instance.
+ *
+ * @param state encoder instance
+ * @param param parameter to set
+ * @param value new parameter value
+ * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid
+ * @returns ::BROTLI_FALSE if value of parameter can not be changed at current
+ * encoder state (e.g. when encoding is started, window size might be
+ * already encoded and therefore it is impossible to change it)
+ * @returns ::BROTLI_TRUE if value is accepted
+ * @warning invalid values might be accepted in case they would not break
+ * encoding process.
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(
+ BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value);
+
+/**
+ * Creates an instance of ::BrotliEncoderState and initializes it.
+ *
+ * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
+ * case they are both zero, default memory allocators are used. @p opaque is
+ * passed to @p alloc_func and @p free_func when they are called. @p free_func
+ * has to return without doing anything when asked to free a NULL pointer.
+ *
+ * @param alloc_func custom memory allocation function
+ * @param free_func custom memory free function
+ * @param opaque custom memory manager handle
+ * @returns @c 0 if instance can not be allocated or initialized
+ * @returns pointer to initialized ::BrotliEncoderState otherwise
+ */
+BROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
+
+/**
+ * Deinitializes and frees ::BrotliEncoderState instance.
+ *
+ * @param state decoder instance to be cleaned up and deallocated
+ */
+BROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state);
+
+/* Opaque type for pointer to different possible internal structures containing
+ dictionary prepared for the encoder */
+typedef struct BrotliEncoderPreparedDictionaryStruct
+ BrotliEncoderPreparedDictionary;
+
+/**
+ * Prepares a shared dictionary from the given file format for the encoder.
+ *
+ * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
+ * case they are both zero, default memory allocators are used. @p opaque is
+ * passed to @p alloc_func and @p free_func when they are called. @p free_func
+ * has to return without doing anything when asked to free a NULL pointer.
+ *
+ * @param type type of dictionary stored in data
+ * @param data_size size of @p data buffer
+ * @param data pointer to the dictionary data
+ * @param quality the maximum Brotli quality to prepare the dictionary for,
+ * use BROTLI_MAX_QUALITY by default
+ * @param alloc_func custom memory allocation function
+ * @param free_func custom memory free function
+ * @param opaque custom memory manager handle
+ */
+BROTLI_ENC_API BrotliEncoderPreparedDictionary*
+BrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type,
+ size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)],
+ int quality,
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
+
+BROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary(
+ BrotliEncoderPreparedDictionary* dictionary);
+
+/**
+ * Attaches a prepared dictionary of any type to the encoder. Can be used
+ * multiple times to attach multiple dictionaries. The dictionary type was
+ * determined by BrotliEncoderPrepareDictionary. Multiple raw prefix
+ * dictionaries and/or max 1 serialized dictionary with custom words can be
+ * attached.
+ *
+ * @returns ::BROTLI_FALSE in case of error
+ * @returns ::BROTLI_TRUE otherwise
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(
+ BrotliEncoderState* state,
+ const BrotliEncoderPreparedDictionary* dictionary);
+
+/**
+ * Calculates the output size bound for the given @p input_size.
+ *
+ * @warning Result is only valid if quality is at least @c 2 and, in
+ * case ::BrotliEncoderCompressStream was used, no flushes
+ * (::BROTLI_OPERATION_FLUSH) were performed.
+ *
+ * @param input_size size of projected input
+ * @returns @c 0 if result does not fit @c size_t
+ */
+BROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size);
+
+/**
+ * Performs one-shot memory-to-memory compression.
+ *
+ * Compresses the data in @p input_buffer into @p encoded_buffer, and sets
+ * @p *encoded_size to the compressed length.
+ *
+ * @note If ::BrotliEncoderMaxCompressedSize(@p input_size) returns non-zero
+ * value, then output is guaranteed to be no longer than that.
+ *
+ * @note If @p lgwin is greater than ::BROTLI_MAX_WINDOW_BITS then resulting
+ * stream might be incompatible with RFC 7932; to decode such streams,
+ * decoder should be configured with
+ * ::BROTLI_DECODER_PARAM_LARGE_WINDOW = @c 1
+ *
+ * @param quality quality parameter value, e.g. ::BROTLI_DEFAULT_QUALITY
+ * @param lgwin lgwin parameter value, e.g. ::BROTLI_DEFAULT_WINDOW
+ * @param mode mode parameter value, e.g. ::BROTLI_DEFAULT_MODE
+ * @param input_size size of @p input_buffer
+ * @param input_buffer input data buffer with at least @p input_size
+ * addressable bytes
+ * @param[in, out] encoded_size @b in: size of @p encoded_buffer; \n
+ * @b out: length of compressed data written to
+ * @p encoded_buffer, or @c 0 if compression fails
+ * @param encoded_buffer compressed data destination buffer
+ * @returns ::BROTLI_FALSE in case of compression error
+ * @returns ::BROTLI_FALSE if output buffer is too small
+ * @returns ::BROTLI_TRUE otherwise
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(
+ int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,
+ const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],
+ size_t* encoded_size,
+ uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]);
+
+/**
+ * Compresses input stream to output stream.
+ *
+ * The values @p *available_in and @p *available_out must specify the number of
+ * bytes addressable at @p *next_in and @p *next_out respectively.
+ * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.
+ *
+ * After each call, @p *available_in will be decremented by the amount of input
+ * bytes consumed, and the @p *next_in pointer will be incremented by that
+ * amount. Similarly, @p *available_out will be decremented by the amount of
+ * output bytes written, and the @p *next_out pointer will be incremented by
+ * that amount.
+ *
+ * @p total_out, if it is not a null-pointer, will be set to the number
+ * of bytes compressed since the last @p state initialization.
+ *
+ *
+ *
+ * Internally workflow consists of 3 tasks:
+ * -# (optionally) copy input data to internal buffer
+ * -# actually compress data and (optionally) store it to internal buffer
+ * -# (optionally) copy compressed bytes from internal buffer to output stream
+ *
+ * Whenever all 3 tasks can't move forward anymore, or error occurs, this
+ * method returns the control flow to caller.
+ *
+ * @p op is used to perform flush, finish the stream, or inject metadata block.
+ * See ::BrotliEncoderOperation for more information.
+ *
+ * Flushing the stream means forcing encoding of all input passed to encoder and
+ * completing the current output block, so it could be fully decoded by stream
+ * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH.
+ * Under some circumstances (e.g. lack of output stream capacity) this operation
+ * would require several calls to ::BrotliEncoderCompressStream. The method must
+ * be called again until both input stream is depleted and encoder has no more
+ * output (see ::BrotliEncoderHasMoreOutput) after the method is called.
+ *
+ * Finishing the stream means encoding of all input passed to encoder and
+ * adding specific "final" marks, so stream decoder could determine that stream
+ * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH.
+ * Under some circumstances (e.g. lack of output stream capacity) this operation
+ * would require several calls to ::BrotliEncoderCompressStream. The method must
+ * be called again until both input stream is depleted and encoder has no more
+ * output (see ::BrotliEncoderHasMoreOutput) after the method is called.
+ *
+ * @warning When flushing and finishing, @p op should not change until operation
+ * is complete; input stream should not be swapped, reduced or
+ * extended as well.
+ *
+ * @param state encoder instance
+ * @param op requested operation
+ * @param[in, out] available_in @b in: amount of available input; \n
+ * @b out: amount of unused input
+ * @param[in, out] next_in pointer to the next input byte
+ * @param[in, out] available_out @b in: length of output buffer; \n
+ * @b out: remaining size of output buffer
+ * @param[in, out] next_out compressed output buffer cursor;
+ * can be @c NULL if @p available_out is @c 0
+ * @param[out] total_out number of bytes produced so far; can be @c NULL
+ * @returns ::BROTLI_FALSE if there was an error
+ * @returns ::BROTLI_TRUE otherwise
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream(
+ BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in,
+ const uint8_t** next_in, size_t* available_out, uint8_t** next_out,
+ size_t* total_out);
+
+/**
+ * Checks if encoder instance reached the final state.
+ *
+ * @param state encoder instance
+ * @returns ::BROTLI_TRUE if encoder is in a state where it reached the end of
+ * the input and produced all of the output
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state);
+
+/**
+ * Checks if encoder has more output.
+ *
+ * @param state encoder instance
+ * @returns ::BROTLI_TRUE, if encoder has some unconsumed output
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(
+ BrotliEncoderState* state);
+
+/**
+ * Acquires pointer to internal output buffer.
+ *
+ * This method is used to make language bindings easier and more efficient:
+ * -# push data to ::BrotliEncoderCompressStream,
+ * until ::BrotliEncoderHasMoreOutput returns BROTL_TRUE
+ * -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific
+ * entity
+ *
+ * Also this could be useful if there is an output stream that is able to
+ * consume all the provided data (e.g. when data is saved to file system).
+ *
+ * @attention After every call to ::BrotliEncoderTakeOutput @p *size bytes of
+ * output are considered consumed for all consecutive calls to the
+ * instance methods; returned pointer becomes invalidated as well.
+ *
+ * @note Encoder output is not guaranteed to be contiguous. This means that
+ * after the size-unrestricted call to ::BrotliEncoderTakeOutput,
+ * immediate next call to ::BrotliEncoderTakeOutput may return more data.
+ *
+ * @param state encoder instance
+ * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if
+ * any amount could be handled; \n
+ * @b out: amount of data pointed by returned pointer and
+ * considered consumed; \n
+ * out value is never greater than in value, unless it is @c 0
+ * @returns pointer to output data
+ */
+BROTLI_ENC_API const uint8_t* BrotliEncoderTakeOutput(
+ BrotliEncoderState* state, size_t* size);
+
+/* Returns the estimated peak memory usage (in bytes) of the BrotliCompress()
+ function, not counting the memory needed for the input and output. */
+BROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage(
+ int quality, int lgwin, size_t input_size);
+/* Returns 0 if dictionary is not valid; otherwise returns allocation size. */
+BROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize(
+ const BrotliEncoderPreparedDictionary* dictionary);
+
+/**
+ * Gets an encoder library version.
+ *
+ * Look at BROTLI_VERSION for more information.
+ */
+BROTLI_ENC_API uint32_t BrotliEncoderVersion(void);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_ENC_ENCODE_H_ */
diff --git a/thirdparty/brotli/include/brotli/port.h b/thirdparty/brotli/include/brotli/port.h
new file mode 100644
index 0000000000..a681ac4864
--- /dev/null
+++ b/thirdparty/brotli/include/brotli/port.h
@@ -0,0 +1,313 @@
+/* Copyright 2016 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Macros for compiler / platform specific API declarations. */
+
+#ifndef BROTLI_COMMON_PORT_H_
+#define BROTLI_COMMON_PORT_H_
+
+/* The following macros were borrowed from https://github.com/nemequ/hedley
+ * with permission of original author - Evan Nemerson <evan@nemerson.com> */
+
+/* >>> >>> >>> hedley macros */
+
+#define BROTLI_MAKE_VERSION(major, minor, revision) \
+ (((major) * 1000000) + ((minor) * 1000) + (revision))
+
+#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
+#define BROTLI_GNUC_VERSION \
+ BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
+#elif defined(__GNUC__)
+#define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0)
+#endif
+
+#if defined(BROTLI_GNUC_VERSION)
+#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)
+#define BROTLI_MSVC_VERSION \
+ BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000), \
+ (_MSC_FULL_VER % 10000000) / 100000, \
+ (_MSC_FULL_VER % 100000) / 100)
+#elif defined(_MSC_FULL_VER)
+#define BROTLI_MSVC_VERSION \
+ BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000), \
+ (_MSC_FULL_VER % 1000000) / 10000, \
+ (_MSC_FULL_VER % 10000) / 10)
+#elif defined(_MSC_VER)
+#define BROTLI_MSVC_VERSION \
+ BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0)
+#endif
+
+#if !defined(_MSC_VER)
+#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0)
+#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \
+ (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
+#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
+#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \
+ (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
+#else
+#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \
+ (_MSC_VER >= ((major * 100) + (minor)))
+#endif
+
+#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)
+#define BROTLI_INTEL_VERSION \
+ BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, \
+ __INTEL_COMPILER % 100, \
+ __INTEL_COMPILER_UPDATE)
+#elif defined(__INTEL_COMPILER)
+#define BROTLI_INTEL_VERSION \
+ BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
+#endif
+
+#if defined(BROTLI_INTEL_VERSION)
+#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__PGI) && \
+ defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
+#define BROTLI_PGI_VERSION \
+ BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
+#endif
+
+#if defined(BROTLI_PGI_VERSION)
+#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
+#define BROTLI_SUNPRO_VERSION \
+ BROTLI_MAKE_VERSION( \
+ (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \
+ (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), \
+ (__SUNPRO_C & 0xf) * 10)
+#elif defined(__SUNPRO_C)
+#define BROTLI_SUNPRO_VERSION \
+ BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \
+ (__SUNPRO_C >> 4) & 0xf, \
+ (__SUNPRO_C) & 0xf)
+#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
+#define BROTLI_SUNPRO_VERSION \
+ BROTLI_MAKE_VERSION( \
+ (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \
+ (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), \
+ (__SUNPRO_CC & 0xf) * 10)
+#elif defined(__SUNPRO_CC)
+#define BROTLI_SUNPRO_VERSION \
+ BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \
+ (__SUNPRO_CC >> 4) & 0xf, \
+ (__SUNPRO_CC) & 0xf)
+#endif
+
+#if defined(BROTLI_SUNPRO_VERSION)
+#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
+#define BROTLI_ARM_VERSION \
+ BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000), \
+ (__ARMCOMPILER_VERSION % 1000000) / 10000, \
+ (__ARMCOMPILER_VERSION % 10000) / 100)
+#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
+#define BROTLI_ARM_VERSION \
+ BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000), \
+ (__ARMCC_VERSION % 1000000) / 10000, \
+ (__ARMCC_VERSION % 10000) / 100)
+#endif
+
+#if defined(BROTLI_ARM_VERSION)
+#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__ibmxl__)
+#define BROTLI_IBM_VERSION \
+ BROTLI_MAKE_VERSION(__ibmxl_version__, \
+ __ibmxl_release__, \
+ __ibmxl_modification__)
+#elif defined(__xlC__) && defined(__xlC_ver__)
+#define BROTLI_IBM_VERSION \
+ BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
+#elif defined(__xlC__)
+#define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0)
+#endif
+
+#if defined(BROTLI_IBM_VERSION)
+#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__TI_COMPILER_VERSION__)
+#define BROTLI_TI_VERSION \
+ BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000), \
+ (__TI_COMPILER_VERSION__ % 1000000) / 1000, \
+ (__TI_COMPILER_VERSION__ % 1000))
+#endif
+
+#if defined(BROTLI_TI_VERSION)
+#define BROTLI_TI_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__IAR_SYSTEMS_ICC__)
+#if __VER__ > 1000
+#define BROTLI_IAR_VERSION \
+ BROTLI_MAKE_VERSION((__VER__ / 1000000), \
+ (__VER__ / 1000) % 1000, \
+ (__VER__ % 1000))
+#else
+#define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0)
+#endif
+#endif
+
+#if defined(BROTLI_IAR_VERSION)
+#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__TINYC__)
+#define BROTLI_TINYC_VERSION \
+ BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
+#endif
+
+#if defined(BROTLI_TINYC_VERSION)
+#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \
+ (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))
+#else
+#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0)
+#endif
+
+#if defined(__has_attribute)
+#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
+ __has_attribute(attribute)
+#else
+#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \
+ BROTLI_GNUC_VERSION_CHECK(major, minor, patch)
+#endif
+
+#if defined(__has_builtin)
+#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \
+ __has_builtin(builtin)
+#else
+#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \
+ BROTLI_GNUC_VERSION_CHECK(major, minor, patch)
+#endif
+
+#if defined(__has_feature)
+#define BROTLI_HAS_FEATURE(feature) __has_feature(feature)
+#else
+#define BROTLI_HAS_FEATURE(feature) (0)
+#endif
+
+#if defined(ADDRESS_SANITIZER) || BROTLI_HAS_FEATURE(address_sanitizer) || \
+ defined(THREAD_SANITIZER) || BROTLI_HAS_FEATURE(thread_sanitizer) || \
+ defined(MEMORY_SANITIZER) || BROTLI_HAS_FEATURE(memory_sanitizer)
+#define BROTLI_SANITIZED 1
+#else
+#define BROTLI_SANITIZED 0
+#endif
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define BROTLI_PUBLIC
+#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
+ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \
+ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
+ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \
+ defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))
+#define BROTLI_PUBLIC __attribute__ ((visibility ("default")))
+#else
+#define BROTLI_PUBLIC
+#endif
+
+/* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */
+#if !defined(BROTLI_INTERNAL)
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define BROTLI_INTERNAL
+#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) || \
+ BROTLI_TI_VERSION_CHECK(8, 0, 0) || \
+ BROTLI_INTEL_VERSION_CHECK(16, 0, 0) || \
+ BROTLI_ARM_VERSION_CHECK(4, 1, 0) || \
+ BROTLI_IBM_VERSION_CHECK(13, 1, 0) || \
+ BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) || \
+ (BROTLI_TI_VERSION_CHECK(7, 3, 0) && \
+ defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))
+#define BROTLI_INTERNAL __attribute__ ((visibility ("hidden")))
+#else
+#define BROTLI_INTERNAL
+#endif
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
+ !defined(__STDC_NO_VLA__) && !defined(__cplusplus) && \
+ !defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) && \
+ !defined(__clang__)
+#define BROTLI_ARRAY_PARAM(name) (name)
+#else
+#define BROTLI_ARRAY_PARAM(name)
+#endif
+
+/* <<< <<< <<< end of hedley macros. */
+
+#if defined(BROTLI_SHARED_COMPILATION)
+#if defined(_WIN32)
+#if defined(BROTLICOMMON_SHARED_COMPILATION)
+#define BROTLI_COMMON_API __declspec(dllexport)
+#else
+#define BROTLI_COMMON_API __declspec(dllimport)
+#endif /* BROTLICOMMON_SHARED_COMPILATION */
+#if defined(BROTLIDEC_SHARED_COMPILATION)
+#define BROTLI_DEC_API __declspec(dllexport)
+#else
+#define BROTLI_DEC_API __declspec(dllimport)
+#endif /* BROTLIDEC_SHARED_COMPILATION */
+#if defined(BROTLIENC_SHARED_COMPILATION)
+#define BROTLI_ENC_API __declspec(dllexport)
+#else
+#define BROTLI_ENC_API __declspec(dllimport)
+#endif /* BROTLIENC_SHARED_COMPILATION */
+#else /* _WIN32 */
+#define BROTLI_COMMON_API BROTLI_PUBLIC
+#define BROTLI_DEC_API BROTLI_PUBLIC
+#define BROTLI_ENC_API BROTLI_PUBLIC
+#endif /* _WIN32 */
+#else /* BROTLI_SHARED_COMPILATION */
+#define BROTLI_COMMON_API
+#define BROTLI_DEC_API
+#define BROTLI_ENC_API
+#endif
+
+#if defined(BROTLI_BUILD_ENC_EXTRA_API)
+#define BROTLI_ENC_EXTRA_API BROTLI_ENC_API
+#else
+#define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL
+#endif
+
+#endif /* BROTLI_COMMON_PORT_H_ */
diff --git a/thirdparty/brotli/include/brotli/shared_dictionary.h b/thirdparty/brotli/include/brotli/shared_dictionary.h
new file mode 100644
index 0000000000..ceb6cf1cd2
--- /dev/null
+++ b/thirdparty/brotli/include/brotli/shared_dictionary.h
@@ -0,0 +1,97 @@
+/* Copyright 2017 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* (Opaque) Shared Dictionary definition and utilities. */
+
+#ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_
+#define BROTLI_COMMON_SHARED_DICTIONARY_H_
+
+#include <brotli/port.h>
+#include <brotli/types.h>
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+#define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4
+#define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31
+#define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64
+#define SHARED_BROTLI_MAX_COMPOUND_DICTS 15
+
+/**
+ * Opaque structure that holds shared dictionary data.
+ *
+ * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance.
+ * Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance.
+ */
+typedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary;
+
+/**
+ * Input data type for ::BrotliSharedDictionaryAttach.
+ */
+typedef enum BrotliSharedDictionaryType {
+ /** Raw LZ77 prefix dictionary. */
+ BROTLI_SHARED_DICTIONARY_RAW = 0,
+ /** Serialized shared dictionary. */
+ BROTLI_SHARED_DICTIONARY_SERIALIZED = 1
+} BrotliSharedDictionaryType;
+
+/**
+ * Creates an instance of ::BrotliSharedDictionary.
+ *
+ * Fresh instance has default word dictionary and transforms
+ * and no LZ77 prefix dictionary.
+ *
+ * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the
+ * case they are both zero, default memory allocators are used. @p opaque is
+ * passed to @p alloc_func and @p free_func when they are called. @p free_func
+ * has to return without doing anything when asked to free a NULL pointer.
+ *
+ * @param alloc_func custom memory allocation function
+ * @param free_func custom memory free function
+ * @param opaque custom memory manager handle
+ * @returns @c 0 if instance can not be allocated or initialized
+ * @returns pointer to initialized ::BrotliSharedDictionary otherwise
+ */
+BROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(
+ brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);
+
+/**
+ * Deinitializes and frees ::BrotliSharedDictionary instance.
+ *
+ * @param dict shared dictionary instance to be cleaned up and deallocated
+ */
+BROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance(
+ BrotliSharedDictionary* dict);
+
+/**
+ * Attaches dictionary to a given instance of ::BrotliSharedDictionary.
+ *
+ * Dictionary to be attached is represented in a serialized format as a region
+ * of memory.
+ *
+ * Provided data it partially referenced by a resulting (compound) dictionary,
+ * and should be kept untouched, while at least one compound dictionary uses it.
+ * This way memory overhead is kept minimal by the cost of additional resource
+ * management.
+ *
+ * @param dict dictionary to extend
+ * @param type type of dictionary to attach
+ * @param data_size size of @p data
+ * @param data serialized dictionary of type @p type, with at least @p data_size
+ * addressable bytes
+ * @returns ::BROTLI_TRUE if provided dictionary is successfully attached
+ * @returns ::BROTLI_FALSE otherwise
+ */
+BROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach(
+ BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,
+ size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);
+
+#if defined(__cplusplus) || defined(c_plusplus)
+} /* extern "C" */
+#endif
+
+#endif /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */
diff --git a/thirdparty/brotli/include/brotli/types.h b/thirdparty/brotli/include/brotli/types.h
new file mode 100644
index 0000000000..eff1a3cd07
--- /dev/null
+++ b/thirdparty/brotli/include/brotli/types.h
@@ -0,0 +1,83 @@
+/* Copyright 2013 Google Inc. All Rights Reserved.
+
+ Distributed under MIT license.
+ See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/**
+ * @file
+ * Common types used in decoder and encoder API.
+ */
+
+#ifndef BROTLI_COMMON_TYPES_H_
+#define BROTLI_COMMON_TYPES_H_
+
+#include <stddef.h> /* for size_t */
+
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+typedef __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+typedef __int64 int64_t;
+#else
+#include <stdint.h>
+#endif /* defined(_MSC_VER) && (_MSC_VER < 1600) */
+
+/**
+ * A portable @c bool replacement.
+ *
+ * ::BROTLI_BOOL is a "documentation" type: actually it is @c int, but in API it
+ * denotes a type, whose only values are ::BROTLI_TRUE and ::BROTLI_FALSE.
+ *
+ * ::BROTLI_BOOL values passed to Brotli should either be ::BROTLI_TRUE or
+ * ::BROTLI_FALSE, or be a result of ::TO_BROTLI_BOOL macros.
+ *
+ * ::BROTLI_BOOL values returned by Brotli should not be tested for equality
+ * with @c true, @c false, ::BROTLI_TRUE, ::BROTLI_FALSE, but rather should be
+ * evaluated, for example: @code{.cpp}
+ * if (SomeBrotliFunction(encoder, BROTLI_TRUE) &&
+ * !OtherBrotliFunction(decoder, BROTLI_FALSE)) {
+ * bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4));
+ * DoSomething(x);
+ * }
+ * @endcode
+ */
+#define BROTLI_BOOL int
+/** Portable @c true replacement. */
+#define BROTLI_TRUE 1
+/** Portable @c false replacement. */
+#define BROTLI_FALSE 0
+/** @c bool to ::BROTLI_BOOL conversion macros. */
+#define TO_BROTLI_BOOL(X) (!!(X) ? BROTLI_TRUE : BROTLI_FALSE)
+
+#define BROTLI_MAKE_UINT64_T(high, low) ((((uint64_t)(high)) << 32) | low)
+
+#define BROTLI_UINT32_MAX (~((uint32_t)0))
+#define BROTLI_SIZE_MAX (~((size_t)0))
+
+/**
+ * Allocating function pointer type.
+ *
+ * @param opaque custom memory manager handle provided by client
+ * @param size requested memory region size; can not be @c 0
+ * @returns @c 0 in the case of failure
+ * @returns a valid pointer to a memory region of at least @p size bytes
+ * long otherwise
+ */
+typedef void* (*brotli_alloc_func)(void* opaque, size_t size);
+
+/**
+ * Deallocating function pointer type.
+ *
+ * This function @b SHOULD do nothing if @p address is @c 0.
+ *
+ * @param opaque custom memory manager handle provided by client
+ * @param address memory region pointer returned by ::brotli_alloc_func, or @c 0
+ */
+typedef void (*brotli_free_func)(void* opaque, void* address);
+
+#endif /* BROTLI_COMMON_TYPES_H_ */
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
deleted file mode 100644
index bec0800a6f..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3BroadphaseCallback.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_BROADPHASE_CALLBACK_H
-#define B3_BROADPHASE_CALLBACK_H
-
-#include "Bullet3Common/b3Vector3.h"
-struct b3BroadphaseProxy;
-
-struct b3BroadphaseAabbCallback
-{
- virtual ~b3BroadphaseAabbCallback() {}
- virtual bool process(const b3BroadphaseProxy* proxy) = 0;
-};
-
-struct b3BroadphaseRayCallback : public b3BroadphaseAabbCallback
-{
- ///added some cached data to accelerate ray-AABB tests
- b3Vector3 m_rayDirectionInverse;
- unsigned int m_signs[3];
- b3Scalar m_lambda_max;
-
- virtual ~b3BroadphaseRayCallback() {}
-};
-
-#endif //B3_BROADPHASE_CALLBACK_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
deleted file mode 100644
index a0dc1da95d..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.cpp
+++ /dev/null
@@ -1,1352 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///b3DynamicBvh implementation by Nathanael Presson
-
-#include "b3DynamicBvh.h"
-
-//
-typedef b3AlignedObjectArray<b3DbvtNode*> b3NodeArray;
-typedef b3AlignedObjectArray<const b3DbvtNode*> b3ConstNodeArray;
-
-//
-struct b3DbvtNodeEnumerator : b3DynamicBvh::ICollide
-{
- b3ConstNodeArray nodes;
- void Process(const b3DbvtNode* n) { nodes.push_back(n); }
-};
-
-//
-static B3_DBVT_INLINE int b3IndexOf(const b3DbvtNode* node)
-{
- return (node->parent->childs[1] == node);
-}
-
-//
-static B3_DBVT_INLINE b3DbvtVolume b3Merge(const b3DbvtVolume& a,
- const b3DbvtVolume& b)
-{
-#if (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE)
- B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtAabbMm)]);
- b3DbvtVolume& res = *(b3DbvtVolume*)locals;
-#else
- b3DbvtVolume res;
-#endif
- b3Merge(a, b, res);
- return (res);
-}
-
-// volume+edge lengths
-static B3_DBVT_INLINE b3Scalar b3Size(const b3DbvtVolume& a)
-{
- const b3Vector3 edges = a.Lengths();
- return (edges.x * edges.y * edges.z +
- edges.x + edges.y + edges.z);
-}
-
-//
-static void b3GetMaxDepth(const b3DbvtNode* node, int depth, int& maxdepth)
-{
- if (node->isinternal())
- {
- b3GetMaxDepth(node->childs[0], depth + 1, maxdepth);
- b3GetMaxDepth(node->childs[1], depth + 1, maxdepth);
- }
- else
- maxdepth = b3Max(maxdepth, depth);
-}
-
-//
-static B3_DBVT_INLINE void b3DeleteNode(b3DynamicBvh* pdbvt,
- b3DbvtNode* node)
-{
- b3AlignedFree(pdbvt->m_free);
- pdbvt->m_free = node;
-}
-
-//
-static void b3RecurseDeleteNode(b3DynamicBvh* pdbvt,
- b3DbvtNode* node)
-{
- if (!node->isleaf())
- {
- b3RecurseDeleteNode(pdbvt, node->childs[0]);
- b3RecurseDeleteNode(pdbvt, node->childs[1]);
- }
- if (node == pdbvt->m_root) pdbvt->m_root = 0;
- b3DeleteNode(pdbvt, node);
-}
-
-//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- void* data)
-{
- b3DbvtNode* node;
- if (pdbvt->m_free)
- {
- node = pdbvt->m_free;
- pdbvt->m_free = 0;
- }
- else
- {
- node = new (b3AlignedAlloc(sizeof(b3DbvtNode), 16)) b3DbvtNode();
- }
- node->parent = parent;
- node->data = data;
- node->childs[1] = 0;
- return (node);
-}
-
-//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- const b3DbvtVolume& volume,
- void* data)
-{
- b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
- node->volume = volume;
- return (node);
-}
-
-//
-static B3_DBVT_INLINE b3DbvtNode* b3CreateNode(b3DynamicBvh* pdbvt,
- b3DbvtNode* parent,
- const b3DbvtVolume& volume0,
- const b3DbvtVolume& volume1,
- void* data)
-{
- b3DbvtNode* node = b3CreateNode(pdbvt, parent, data);
- b3Merge(volume0, volume1, node->volume);
- return (node);
-}
-
-//
-static void b3InsertLeaf(b3DynamicBvh* pdbvt,
- b3DbvtNode* root,
- b3DbvtNode* leaf)
-{
- if (!pdbvt->m_root)
- {
- pdbvt->m_root = leaf;
- leaf->parent = 0;
- }
- else
- {
- if (!root->isleaf())
- {
- do
- {
- root = root->childs[b3Select(leaf->volume,
- root->childs[0]->volume,
- root->childs[1]->volume)];
- } while (!root->isleaf());
- }
- b3DbvtNode* prev = root->parent;
- b3DbvtNode* node = b3CreateNode(pdbvt, prev, leaf->volume, root->volume, 0);
- if (prev)
- {
- prev->childs[b3IndexOf(root)] = node;
- node->childs[0] = root;
- root->parent = node;
- node->childs[1] = leaf;
- leaf->parent = node;
- do
- {
- if (!prev->volume.Contain(node->volume))
- b3Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
- else
- break;
- node = prev;
- } while (0 != (prev = node->parent));
- }
- else
- {
- node->childs[0] = root;
- root->parent = node;
- node->childs[1] = leaf;
- leaf->parent = node;
- pdbvt->m_root = node;
- }
- }
-}
-
-//
-static b3DbvtNode* b3RemoveLeaf(b3DynamicBvh* pdbvt,
- b3DbvtNode* leaf)
-{
- if (leaf == pdbvt->m_root)
- {
- pdbvt->m_root = 0;
- return (0);
- }
- else
- {
- b3DbvtNode* parent = leaf->parent;
- b3DbvtNode* prev = parent->parent;
- b3DbvtNode* sibling = parent->childs[1 - b3IndexOf(leaf)];
- if (prev)
- {
- prev->childs[b3IndexOf(parent)] = sibling;
- sibling->parent = prev;
- b3DeleteNode(pdbvt, parent);
- while (prev)
- {
- const b3DbvtVolume pb = prev->volume;
- b3Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
- if (b3NotEqual(pb, prev->volume))
- {
- prev = prev->parent;
- }
- else
- break;
- }
- return (prev ? prev : pdbvt->m_root);
- }
- else
- {
- pdbvt->m_root = sibling;
- sibling->parent = 0;
- b3DeleteNode(pdbvt, parent);
- return (pdbvt->m_root);
- }
- }
-}
-
-//
-static void b3FetchLeaves(b3DynamicBvh* pdbvt,
- b3DbvtNode* root,
- b3NodeArray& leaves,
- int depth = -1)
-{
- if (root->isinternal() && depth)
- {
- b3FetchLeaves(pdbvt, root->childs[0], leaves, depth - 1);
- b3FetchLeaves(pdbvt, root->childs[1], leaves, depth - 1);
- b3DeleteNode(pdbvt, root);
- }
- else
- {
- leaves.push_back(root);
- }
-}
-
-static bool b3LeftOfAxis(const b3DbvtNode* node,
- const b3Vector3& org,
- const b3Vector3& axis)
-{
- return b3Dot(axis, node->volume.Center() - org) <= 0;
-}
-
-// Partitions leaves such that leaves[0, n) are on the
-// left of axis, and leaves[n, count) are on the right
-// of axis. returns N.
-static int b3Split(b3DbvtNode** leaves,
- int count,
- const b3Vector3& org,
- const b3Vector3& axis)
-{
- int begin = 0;
- int end = count;
- for (;;)
- {
- while (begin != end && b3LeftOfAxis(leaves[begin], org, axis))
- {
- ++begin;
- }
-
- if (begin == end)
- {
- break;
- }
-
- while (begin != end && !b3LeftOfAxis(leaves[end - 1], org, axis))
- {
- --end;
- }
-
- if (begin == end)
- {
- break;
- }
-
- // swap out of place nodes
- --end;
- b3DbvtNode* temp = leaves[begin];
- leaves[begin] = leaves[end];
- leaves[end] = temp;
- ++begin;
- }
-
- return begin;
-}
-
-//
-static b3DbvtVolume b3Bounds(b3DbvtNode** leaves,
- int count)
-{
-#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
- B3_ATTRIBUTE_ALIGNED16(char locals[sizeof(b3DbvtVolume)]);
- b3DbvtVolume& volume = *(b3DbvtVolume*)locals;
- volume = leaves[0]->volume;
-#else
- b3DbvtVolume volume = leaves[0]->volume;
-#endif
- for (int i = 1, ni = count; i < ni; ++i)
- {
- b3Merge(volume, leaves[i]->volume, volume);
- }
- return (volume);
-}
-
-//
-static void b3BottomUp(b3DynamicBvh* pdbvt,
- b3DbvtNode** leaves,
- int count)
-{
- while (count > 1)
- {
- b3Scalar minsize = B3_INFINITY;
- int minidx[2] = {-1, -1};
- for (int i = 0; i < count; ++i)
- {
- for (int j = i + 1; j < count; ++j)
- {
- const b3Scalar sz = b3Size(b3Merge(leaves[i]->volume, leaves[j]->volume));
- if (sz < minsize)
- {
- minsize = sz;
- minidx[0] = i;
- minidx[1] = j;
- }
- }
- }
- b3DbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
- b3DbvtNode* p = b3CreateNode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
- p->childs[0] = n[0];
- p->childs[1] = n[1];
- n[0]->parent = p;
- n[1]->parent = p;
- leaves[minidx[0]] = p;
- leaves[minidx[1]] = leaves[count - 1];
- --count;
- }
-}
-
-//
-static b3DbvtNode* b3TopDown(b3DynamicBvh* pdbvt,
- b3DbvtNode** leaves,
- int count,
- int bu_treshold)
-{
- static const b3Vector3 axis[] = {b3MakeVector3(1, 0, 0),
- b3MakeVector3(0, 1, 0),
- b3MakeVector3(0, 0, 1)};
- b3Assert(bu_treshold > 1);
- if (count > 1)
- {
- if (count > bu_treshold)
- {
- const b3DbvtVolume vol = b3Bounds(leaves, count);
- const b3Vector3 org = vol.Center();
- int partition;
- int bestaxis = -1;
- int bestmidp = count;
- int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
- int i;
- for (i = 0; i < count; ++i)
- {
- const b3Vector3 x = leaves[i]->volume.Center() - org;
- for (int j = 0; j < 3; ++j)
- {
- ++splitcount[j][b3Dot(x, axis[j]) > 0 ? 1 : 0];
- }
- }
- for (i = 0; i < 3; ++i)
- {
- if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
- {
- const int midp = (int)b3Fabs(b3Scalar(splitcount[i][0] - splitcount[i][1]));
- if (midp < bestmidp)
- {
- bestaxis = i;
- bestmidp = midp;
- }
- }
- }
- if (bestaxis >= 0)
- {
- partition = b3Split(leaves, count, org, axis[bestaxis]);
- b3Assert(partition != 0 && partition != count);
- }
- else
- {
- partition = count / 2 + 1;
- }
- b3DbvtNode* node = b3CreateNode(pdbvt, 0, vol, 0);
- node->childs[0] = b3TopDown(pdbvt, &leaves[0], partition, bu_treshold);
- node->childs[1] = b3TopDown(pdbvt, &leaves[partition], count - partition, bu_treshold);
- node->childs[0]->parent = node;
- node->childs[1]->parent = node;
- return (node);
- }
- else
- {
- b3BottomUp(pdbvt, leaves, count);
- return (leaves[0]);
- }
- }
- return (leaves[0]);
-}
-
-//
-static B3_DBVT_INLINE b3DbvtNode* b3Sort(b3DbvtNode* n, b3DbvtNode*& r)
-{
- b3DbvtNode* p = n->parent;
- b3Assert(n->isinternal());
- if (p > n)
- {
- const int i = b3IndexOf(n);
- const int j = 1 - i;
- b3DbvtNode* s = p->childs[j];
- b3DbvtNode* q = p->parent;
- b3Assert(n == p->childs[i]);
- if (q)
- q->childs[b3IndexOf(p)] = n;
- else
- r = n;
- s->parent = n;
- p->parent = n;
- n->parent = q;
- p->childs[0] = n->childs[0];
- p->childs[1] = n->childs[1];
- n->childs[0]->parent = p;
- n->childs[1]->parent = p;
- n->childs[i] = p;
- n->childs[j] = s;
- b3Swap(p->volume, n->volume);
- return (p);
- }
- return (n);
-}
-
-#if 0
-static B3_DBVT_INLINE b3DbvtNode* walkup(b3DbvtNode* n,int count)
-{
- while(n&&(count--)) n=n->parent;
- return(n);
-}
-#endif
-
-//
-// Api
-//
-
-//
-b3DynamicBvh::b3DynamicBvh()
-{
- m_root = 0;
- m_free = 0;
- m_lkhd = -1;
- m_leaves = 0;
- m_opath = 0;
-}
-
-//
-b3DynamicBvh::~b3DynamicBvh()
-{
- clear();
-}
-
-//
-void b3DynamicBvh::clear()
-{
- if (m_root)
- b3RecurseDeleteNode(this, m_root);
- b3AlignedFree(m_free);
- m_free = 0;
- m_lkhd = -1;
- m_stkStack.clear();
- m_opath = 0;
-}
-
-//
-void b3DynamicBvh::optimizeBottomUp()
-{
- if (m_root)
- {
- b3NodeArray leaves;
- leaves.reserve(m_leaves);
- b3FetchLeaves(this, m_root, leaves);
- b3BottomUp(this, &leaves[0], leaves.size());
- m_root = leaves[0];
- }
-}
-
-//
-void b3DynamicBvh::optimizeTopDown(int bu_treshold)
-{
- if (m_root)
- {
- b3NodeArray leaves;
- leaves.reserve(m_leaves);
- b3FetchLeaves(this, m_root, leaves);
- m_root = b3TopDown(this, &leaves[0], leaves.size(), bu_treshold);
- }
-}
-
-//
-void b3DynamicBvh::optimizeIncremental(int passes)
-{
- if (passes < 0) passes = m_leaves;
- if (m_root && (passes > 0))
- {
- do
- {
- b3DbvtNode* node = m_root;
- unsigned bit = 0;
- while (node->isinternal())
- {
- node = b3Sort(node, m_root)->childs[(m_opath >> bit) & 1];
- bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
- }
- update(node);
- ++m_opath;
- } while (--passes);
- }
-}
-
-//
-b3DbvtNode* b3DynamicBvh::insert(const b3DbvtVolume& volume, void* data)
-{
- b3DbvtNode* leaf = b3CreateNode(this, 0, volume, data);
- b3InsertLeaf(this, m_root, leaf);
- ++m_leaves;
- return (leaf);
-}
-
-//
-void b3DynamicBvh::update(b3DbvtNode* leaf, int lookahead)
-{
- b3DbvtNode* root = b3RemoveLeaf(this, leaf);
- if (root)
- {
- if (lookahead >= 0)
- {
- for (int i = 0; (i < lookahead) && root->parent; ++i)
- {
- root = root->parent;
- }
- }
- else
- root = m_root;
- }
- b3InsertLeaf(this, root, leaf);
-}
-
-//
-void b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume)
-{
- b3DbvtNode* root = b3RemoveLeaf(this, leaf);
- if (root)
- {
- if (m_lkhd >= 0)
- {
- for (int i = 0; (i < m_lkhd) && root->parent; ++i)
- {
- root = root->parent;
- }
- }
- else
- root = m_root;
- }
- leaf->volume = volume;
- b3InsertLeaf(this, root, leaf);
-}
-
-//
-bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.Expand(b3MakeVector3(margin, margin, margin));
- volume.SignedExpand(velocity);
- update(leaf, volume);
- return (true);
-}
-
-//
-bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.SignedExpand(velocity);
- update(leaf, volume);
- return (true);
-}
-
-//
-bool b3DynamicBvh::update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.Expand(b3MakeVector3(margin, margin, margin));
- update(leaf, volume);
- return (true);
-}
-
-//
-void b3DynamicBvh::remove(b3DbvtNode* leaf)
-{
- b3RemoveLeaf(this, leaf);
- b3DeleteNode(this, leaf);
- --m_leaves;
-}
-
-//
-void b3DynamicBvh::write(IWriter* iwriter) const
-{
- b3DbvtNodeEnumerator nodes;
- nodes.nodes.reserve(m_leaves * 2);
- enumNodes(m_root, nodes);
- iwriter->Prepare(m_root, nodes.nodes.size());
- for (int i = 0; i < nodes.nodes.size(); ++i)
- {
- const b3DbvtNode* n = nodes.nodes[i];
- int p = -1;
- if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
- if (n->isinternal())
- {
- const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
- const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
- iwriter->WriteNode(n, i, p, c0, c1);
- }
- else
- {
- iwriter->WriteLeaf(n, i, p);
- }
- }
-}
-
-//
-void b3DynamicBvh::clone(b3DynamicBvh& dest, IClone* iclone) const
-{
- dest.clear();
- if (m_root != 0)
- {
- b3AlignedObjectArray<sStkCLN> stack;
- stack.reserve(m_leaves);
- stack.push_back(sStkCLN(m_root, 0));
- do
- {
- const int i = stack.size() - 1;
- const sStkCLN e = stack[i];
- b3DbvtNode* n = b3CreateNode(&dest, e.parent, e.node->volume, e.node->data);
- stack.pop_back();
- if (e.parent != 0)
- e.parent->childs[i & 1] = n;
- else
- dest.m_root = n;
- if (e.node->isinternal())
- {
- stack.push_back(sStkCLN(e.node->childs[0], n));
- stack.push_back(sStkCLN(e.node->childs[1], n));
- }
- else
- {
- iclone->CloneLeaf(n);
- }
- } while (stack.size() > 0);
- }
-}
-
-//
-int b3DynamicBvh::maxdepth(const b3DbvtNode* node)
-{
- int depth = 0;
- if (node) b3GetMaxDepth(node, 1, depth);
- return (depth);
-}
-
-//
-int b3DynamicBvh::countLeaves(const b3DbvtNode* node)
-{
- if (node->isinternal())
- return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
- else
- return (1);
-}
-
-//
-void b3DynamicBvh::extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves)
-{
- if (node->isinternal())
- {
- extractLeaves(node->childs[0], leaves);
- extractLeaves(node->childs[1], leaves);
- }
- else
- {
- leaves.push_back(node);
- }
-}
-
-//
-#if B3_DBVT_ENABLE_BENCHMARK
-
-#include <stdio.h>
-#include <stdlib.h>
-
-/*
-q6600,2.4ghz
-
-/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
-/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
-/Fo"..\..\out\release8\build\libbulletcollision\\"
-/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
-/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
-
-Benchmarking dbvt...
-World scale: 100.000000
-Extents base: 1.000000
-Extents range: 4.000000
-Leaves: 8192
-sizeof(b3DbvtVolume): 32 bytes
-sizeof(b3DbvtNode): 44 bytes
-[1] b3DbvtVolume intersections: 3499 ms (-1%)
-[2] b3DbvtVolume merges: 1934 ms (0%)
-[3] b3DynamicBvh::collideTT: 5485 ms (-21%)
-[4] b3DynamicBvh::collideTT self: 2814 ms (-20%)
-[5] b3DynamicBvh::collideTT xform: 7379 ms (-1%)
-[6] b3DynamicBvh::collideTT xform,self: 7270 ms (-2%)
-[7] b3DynamicBvh::rayTest: 6314 ms (0%),(332143 r/s)
-[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
-[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
-[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
-[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
-[12] b3DbvtVolume notequal: 3659 ms (0%)
-[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
-[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
-[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
-[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
-[17] b3DbvtVolume select: 3419 ms (0%)
-*/
-
-struct b3DbvtBenchmark
-{
- struct NilPolicy : b3DynamicBvh::ICollide
- {
- NilPolicy() : m_pcount(0), m_depth(-B3_INFINITY), m_checksort(true) {}
- void Process(const b3DbvtNode*, const b3DbvtNode*) { ++m_pcount; }
- void Process(const b3DbvtNode*) { ++m_pcount; }
- void Process(const b3DbvtNode*, b3Scalar depth)
- {
- ++m_pcount;
- if (m_checksort)
- {
- if (depth >= m_depth)
- m_depth = depth;
- else
- printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
- }
- }
- int m_pcount;
- b3Scalar m_depth;
- bool m_checksort;
- };
- struct P14 : b3DynamicBvh::ICollide
- {
- struct Node
- {
- const b3DbvtNode* leaf;
- b3Scalar depth;
- };
- void Process(const b3DbvtNode* leaf, b3Scalar depth)
- {
- Node n;
- n.leaf = leaf;
- n.depth = depth;
- }
- static int sortfnc(const Node& a, const Node& b)
- {
- if (a.depth < b.depth) return (+1);
- if (a.depth > b.depth) return (-1);
- return (0);
- }
- b3AlignedObjectArray<Node> m_nodes;
- };
- struct P15 : b3DynamicBvh::ICollide
- {
- struct Node
- {
- const b3DbvtNode* leaf;
- b3Scalar depth;
- };
- void Process(const b3DbvtNode* leaf)
- {
- Node n;
- n.leaf = leaf;
- n.depth = dot(leaf->volume.Center(), m_axis);
- }
- static int sortfnc(const Node& a, const Node& b)
- {
- if (a.depth < b.depth) return (+1);
- if (a.depth > b.depth) return (-1);
- return (0);
- }
- b3AlignedObjectArray<Node> m_nodes;
- b3Vector3 m_axis;
- };
- static b3Scalar RandUnit()
- {
- return (rand() / (b3Scalar)RAND_MAX);
- }
- static b3Vector3 RandVector3()
- {
- return (b3Vector3(RandUnit(), RandUnit(), RandUnit()));
- }
- static b3Vector3 RandVector3(b3Scalar cs)
- {
- return (RandVector3() * cs - b3Vector3(cs, cs, cs) / 2);
- }
- static b3DbvtVolume RandVolume(b3Scalar cs, b3Scalar eb, b3Scalar es)
- {
- return (b3DbvtVolume::FromCE(RandVector3(cs), b3Vector3(eb, eb, eb) + RandVector3() * es));
- }
- static b3Transform RandTransform(b3Scalar cs)
- {
- b3Transform t;
- t.setOrigin(RandVector3(cs));
- t.setRotation(b3Quaternion(RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2, RandUnit() * B3_PI * 2).normalized());
- return (t);
- }
- static void RandTree(b3Scalar cs, b3Scalar eb, b3Scalar es, int leaves, b3DynamicBvh& dbvt)
- {
- dbvt.clear();
- for (int i = 0; i < leaves; ++i)
- {
- dbvt.insert(RandVolume(cs, eb, es), 0);
- }
- }
-};
-
-void b3DynamicBvh::benchmark()
-{
- static const b3Scalar cfgVolumeCenterScale = 100;
- static const b3Scalar cfgVolumeExentsBase = 1;
- static const b3Scalar cfgVolumeExentsScale = 4;
- static const int cfgLeaves = 8192;
- static const bool cfgEnable = true;
-
- //[1] b3DbvtVolume intersections
- bool cfgBenchmark1_Enable = cfgEnable;
- static const int cfgBenchmark1_Iterations = 8;
- static const int cfgBenchmark1_Reference = 3499;
- //[2] b3DbvtVolume merges
- bool cfgBenchmark2_Enable = cfgEnable;
- static const int cfgBenchmark2_Iterations = 4;
- static const int cfgBenchmark2_Reference = 1945;
- //[3] b3DynamicBvh::collideTT
- bool cfgBenchmark3_Enable = cfgEnable;
- static const int cfgBenchmark3_Iterations = 512;
- static const int cfgBenchmark3_Reference = 5485;
- //[4] b3DynamicBvh::collideTT self
- bool cfgBenchmark4_Enable = cfgEnable;
- static const int cfgBenchmark4_Iterations = 512;
- static const int cfgBenchmark4_Reference = 2814;
- //[5] b3DynamicBvh::collideTT xform
- bool cfgBenchmark5_Enable = cfgEnable;
- static const int cfgBenchmark5_Iterations = 512;
- static const b3Scalar cfgBenchmark5_OffsetScale = 2;
- static const int cfgBenchmark5_Reference = 7379;
- //[6] b3DynamicBvh::collideTT xform,self
- bool cfgBenchmark6_Enable = cfgEnable;
- static const int cfgBenchmark6_Iterations = 512;
- static const b3Scalar cfgBenchmark6_OffsetScale = 2;
- static const int cfgBenchmark6_Reference = 7270;
- //[7] b3DynamicBvh::rayTest
- bool cfgBenchmark7_Enable = cfgEnable;
- static const int cfgBenchmark7_Passes = 32;
- static const int cfgBenchmark7_Iterations = 65536;
- static const int cfgBenchmark7_Reference = 6307;
- //[8] insert/remove
- bool cfgBenchmark8_Enable = cfgEnable;
- static const int cfgBenchmark8_Passes = 32;
- static const int cfgBenchmark8_Iterations = 65536;
- static const int cfgBenchmark8_Reference = 2105;
- //[9] updates (teleport)
- bool cfgBenchmark9_Enable = cfgEnable;
- static const int cfgBenchmark9_Passes = 32;
- static const int cfgBenchmark9_Iterations = 65536;
- static const int cfgBenchmark9_Reference = 1879;
- //[10] updates (jitter)
- bool cfgBenchmark10_Enable = cfgEnable;
- static const b3Scalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
- static const int cfgBenchmark10_Passes = 32;
- static const int cfgBenchmark10_Iterations = 65536;
- static const int cfgBenchmark10_Reference = 1244;
- //[11] optimize (incremental)
- bool cfgBenchmark11_Enable = cfgEnable;
- static const int cfgBenchmark11_Passes = 64;
- static const int cfgBenchmark11_Iterations = 65536;
- static const int cfgBenchmark11_Reference = 2510;
- //[12] b3DbvtVolume notequal
- bool cfgBenchmark12_Enable = cfgEnable;
- static const int cfgBenchmark12_Iterations = 32;
- static const int cfgBenchmark12_Reference = 3677;
- //[13] culling(OCL+fullsort)
- bool cfgBenchmark13_Enable = cfgEnable;
- static const int cfgBenchmark13_Iterations = 1024;
- static const int cfgBenchmark13_Reference = 2231;
- //[14] culling(OCL+qsort)
- bool cfgBenchmark14_Enable = cfgEnable;
- static const int cfgBenchmark14_Iterations = 8192;
- static const int cfgBenchmark14_Reference = 3500;
- //[15] culling(KDOP+qsort)
- bool cfgBenchmark15_Enable = cfgEnable;
- static const int cfgBenchmark15_Iterations = 8192;
- static const int cfgBenchmark15_Reference = 1151;
- //[16] insert/remove batch
- bool cfgBenchmark16_Enable = cfgEnable;
- static const int cfgBenchmark16_BatchCount = 256;
- static const int cfgBenchmark16_Passes = 16384;
- static const int cfgBenchmark16_Reference = 5138;
- //[17] select
- bool cfgBenchmark17_Enable = cfgEnable;
- static const int cfgBenchmark17_Iterations = 4;
- static const int cfgBenchmark17_Reference = 3390;
-
- b3Clock wallclock;
- printf("Benchmarking dbvt...\r\n");
- printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
- printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
- printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
- printf("\tLeaves: %u\r\n", cfgLeaves);
- printf("\tsizeof(b3DbvtVolume): %u bytes\r\n", sizeof(b3DbvtVolume));
- printf("\tsizeof(b3DbvtNode): %u bytes\r\n", sizeof(b3DbvtNode));
- if (cfgBenchmark1_Enable)
- { // Benchmark 1
- srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<bool> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[1] b3DbvtVolume intersections: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- results[k] = Intersect(volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
- }
- if (cfgBenchmark2_Enable)
- { // Benchmark 2
- srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<b3DbvtVolume> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[2] b3DbvtVolume merges: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- Merge(volumes[j], volumes[k], results[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
- }
- if (cfgBenchmark3_Enable)
- { // Benchmark 3
- srand(380843);
- b3DynamicBvh dbvt[2];
- b3DbvtBenchmark::NilPolicy policy;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
- dbvt[0].optimizeTopDown();
- dbvt[1].optimizeTopDown();
- printf("[3] b3DynamicBvh::collideTT: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
- {
- b3DynamicBvh::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
- }
- if (cfgBenchmark4_Enable)
- { // Benchmark 4
- srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::NilPolicy policy;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[4] b3DynamicBvh::collideTT self: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
- {
- b3DynamicBvh::collideTT(dbvt.m_root, dbvt.m_root, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
- }
- if (cfgBenchmark5_Enable)
- { // Benchmark 5
- srand(380843);
- b3DynamicBvh dbvt[2];
- b3AlignedObjectArray<b3Transform> transforms;
- b3DbvtBenchmark::NilPolicy policy;
- transforms.resize(cfgBenchmark5_Iterations);
- for (int i = 0; i < transforms.size(); ++i)
- {
- transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
- dbvt[0].optimizeTopDown();
- dbvt[1].optimizeTopDown();
- printf("[5] b3DynamicBvh::collideTT xform: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
- {
- b3DynamicBvh::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
- }
- if (cfgBenchmark6_Enable)
- { // Benchmark 6
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Transform> transforms;
- b3DbvtBenchmark::NilPolicy policy;
- transforms.resize(cfgBenchmark6_Iterations);
- for (int i = 0; i < transforms.size(); ++i)
- {
- transforms[i] = b3DbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[6] b3DynamicBvh::collideTT xform,self: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
- {
- b3DynamicBvh::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
- }
- if (cfgBenchmark7_Enable)
- { // Benchmark 7
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> rayorg;
- b3AlignedObjectArray<b3Vector3> raydir;
- b3DbvtBenchmark::NilPolicy policy;
- rayorg.resize(cfgBenchmark7_Iterations);
- raydir.resize(cfgBenchmark7_Iterations);
- for (int i = 0; i < rayorg.size(); ++i)
- {
- rayorg[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
- raydir[i] = b3DbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[7] b3DynamicBvh::rayTest: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark7_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
- {
- b3DynamicBvh::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
- printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
- }
- if (cfgBenchmark8_Enable)
- { // Benchmark 8
- srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[8] insert/remove: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark8_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
- {
- dbvt.remove(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
- printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
- }
- if (cfgBenchmark9_Enable)
- { // Benchmark 9
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<const b3DbvtNode*> leaves;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root, leaves);
- printf("[9] updates (teleport): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark9_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
- {
- dbvt.update(const_cast<b3DbvtNode*>(leaves[rand() % cfgLeaves]),
- b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
- }
- if (cfgBenchmark10_Enable)
- { // Benchmark 10
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<const b3DbvtNode*> leaves;
- b3AlignedObjectArray<b3Vector3> vectors;
- vectors.resize(cfgBenchmark10_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)) * cfgBenchmark10_Scale;
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root, leaves);
- printf("[10] updates (jitter): ");
- wallclock.reset();
-
- for (int i = 0; i < cfgBenchmark10_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
- {
- const b3Vector3& d = vectors[j];
- b3DbvtNode* l = const_cast<b3DbvtNode*>(leaves[rand() % cfgLeaves]);
- b3DbvtVolume v = b3DbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
- dbvt.update(l, v);
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
- }
- if (cfgBenchmark11_Enable)
- { // Benchmark 11
- srand(380843);
- b3DynamicBvh dbvt;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[11] optimize (incremental): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark11_Passes; ++i)
- {
- dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
- printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
- }
- if (cfgBenchmark12_Enable)
- { // Benchmark 12
- srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<bool> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[12] b3DbvtVolume notequal: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- results[k] = NotEqual(volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
- }
- if (cfgBenchmark13_Enable)
- { // Benchmark 13
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::NilPolicy policy;
- vectors.resize(cfgBenchmark13_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[13] culling(OCL+fullsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
- {
- static const b3Scalar offset = 0;
- policy.m_depth = -B3_INFINITY;
- dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark13_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark14_Enable)
- { // Benchmark 14
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::P14 policy;
- vectors.resize(cfgBenchmark14_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- policy.m_nodes.reserve(cfgLeaves);
- printf("[14] culling(OCL+qsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
- {
- static const b3Scalar offset = 0;
- policy.m_nodes.resize(0);
- dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
- policy.m_nodes.quickSort(b3DbvtBenchmark::P14::sortfnc);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark14_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark15_Enable)
- { // Benchmark 15
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3Vector3> vectors;
- b3DbvtBenchmark::P15 policy;
- vectors.resize(cfgBenchmark15_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (b3DbvtBenchmark::RandVector3() * 2 - b3Vector3(1, 1, 1)).normalized();
- }
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- policy.m_nodes.reserve(cfgLeaves);
- printf("[15] culling(KDOP+qsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
- {
- static const b3Scalar offset = 0;
- policy.m_nodes.resize(0);
- policy.m_axis = vectors[i];
- dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
- policy.m_nodes.quickSort(b3DbvtBenchmark::P15::sortfnc);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark15_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark16_Enable)
- { // Benchmark 16
- srand(380843);
- b3DynamicBvh dbvt;
- b3AlignedObjectArray<b3DbvtNode*> batch;
- b3DbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- batch.reserve(cfgBenchmark16_BatchCount);
- printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark16_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
- {
- batch.push_back(dbvt.insert(b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
- }
- for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
- {
- dbvt.remove(batch[j]);
- }
- batch.resize(0);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
- printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
- }
- if (cfgBenchmark17_Enable)
- { // Benchmark 17
- srand(380843);
- b3AlignedObjectArray<b3DbvtVolume> volumes;
- b3AlignedObjectArray<int> results;
- b3AlignedObjectArray<int> indices;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- indices.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- indices[i] = i;
- volumes[i] = b3DbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- for (int i = 0; i < cfgLeaves; ++i)
- {
- b3Swap(indices[i], indices[rand() % cfgLeaves]);
- }
- printf("[17] b3DbvtVolume select: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- const int idx = indices[k];
- results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);
- }
- printf("\r\n\r\n");
-}
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
deleted file mode 100644
index f44e3377fe..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h
+++ /dev/null
@@ -1,1332 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///b3DynamicBvh implementation by Nathanael Presson
-
-#ifndef B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
-#define B3_DYNAMIC_BOUNDING_VOLUME_TREE_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-//
-// Compile time configuration
-//
-
-// Implementation profiles
-#define B3_DBVT_IMPL_GENERIC 0 // Generic implementation
-#define B3_DBVT_IMPL_SSE 1 // SSE
-
-// Template implementation of ICollide
-#ifdef _WIN32
-#if (defined(_MSC_VER) && _MSC_VER >= 1400)
-#define B3_DBVT_USE_TEMPLATE 1
-#else
-#define B3_DBVT_USE_TEMPLATE 0
-#endif
-#else
-#define B3_DBVT_USE_TEMPLATE 0
-#endif
-
-// Use only intrinsics instead of inline asm
-#define B3_DBVT_USE_INTRINSIC_SSE 1
-
-// Using memmov for collideOCL
-#define B3_DBVT_USE_MEMMOVE 1
-
-// Enable benchmarking code
-#define B3_DBVT_ENABLE_BENCHMARK 0
-
-// Inlining
-#define B3_DBVT_INLINE B3_FORCE_INLINE
-
-// Specific methods implementation
-
-//SSE gives errors on a MSVC 7.1
-#if defined(B3_USE_SSE) //&& defined (_WIN32)
-#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_SSE
-#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_SSE
-#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_SSE
-#else
-#define B3_DBVT_SELECT_IMPL B3_DBVT_IMPL_GENERIC
-#define B3_DBVT_MERGE_IMPL B3_DBVT_IMPL_GENERIC
-#define B3_DBVT_INT0_IMPL B3_DBVT_IMPL_GENERIC
-#endif
-
-#if (B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE) || \
- (B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE) || \
- (B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE)
-#include <emmintrin.h>
-#endif
-
-//
-// Auto config and checks
-//
-
-#if B3_DBVT_USE_TEMPLATE
-#define B3_DBVT_VIRTUAL
-#define B3_DBVT_VIRTUAL_DTOR(a)
-#define B3_DBVT_PREFIX template <typename T>
-#define B3_DBVT_IPOLICY T& policy
-#define B3_DBVT_CHECKTYPE \
- static const ICollide& typechecker = *(T*)1; \
- (void)typechecker;
-#else
-#define B3_DBVT_VIRTUAL_DTOR(a) \
- virtual ~a() {}
-#define B3_DBVT_VIRTUAL virtual
-#define B3_DBVT_PREFIX
-#define B3_DBVT_IPOLICY ICollide& policy
-#define B3_DBVT_CHECKTYPE
-#endif
-
-#if B3_DBVT_USE_MEMMOVE
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-#endif
-
-#ifndef B3_DBVT_USE_TEMPLATE
-#error "B3_DBVT_USE_TEMPLATE undefined"
-#endif
-
-#ifndef B3_DBVT_USE_MEMMOVE
-#error "B3_DBVT_USE_MEMMOVE undefined"
-#endif
-
-#ifndef B3_DBVT_ENABLE_BENCHMARK
-#error "B3_DBVT_ENABLE_BENCHMARK undefined"
-#endif
-
-#ifndef B3_DBVT_SELECT_IMPL
-#error "B3_DBVT_SELECT_IMPL undefined"
-#endif
-
-#ifndef B3_DBVT_MERGE_IMPL
-#error "B3_DBVT_MERGE_IMPL undefined"
-#endif
-
-#ifndef B3_DBVT_INT0_IMPL
-#error "B3_DBVT_INT0_IMPL undefined"
-#endif
-
-//
-// Defaults volumes
-//
-
-/* b3DbvtAabbMm */
-struct b3DbvtAabbMm
-{
- B3_DBVT_INLINE b3Vector3 Center() const { return ((mi + mx) / 2); }
- B3_DBVT_INLINE b3Vector3 Lengths() const { return (mx - mi); }
- B3_DBVT_INLINE b3Vector3 Extents() const { return ((mx - mi) / 2); }
- B3_DBVT_INLINE const b3Vector3& Mins() const { return (mi); }
- B3_DBVT_INLINE const b3Vector3& Maxs() const { return (mx); }
- static inline b3DbvtAabbMm FromCE(const b3Vector3& c, const b3Vector3& e);
- static inline b3DbvtAabbMm FromCR(const b3Vector3& c, b3Scalar r);
- static inline b3DbvtAabbMm FromMM(const b3Vector3& mi, const b3Vector3& mx);
- static inline b3DbvtAabbMm FromPoints(const b3Vector3* pts, int n);
- static inline b3DbvtAabbMm FromPoints(const b3Vector3** ppts, int n);
- B3_DBVT_INLINE void Expand(const b3Vector3& e);
- B3_DBVT_INLINE void SignedExpand(const b3Vector3& e);
- B3_DBVT_INLINE bool Contain(const b3DbvtAabbMm& a) const;
- B3_DBVT_INLINE int Classify(const b3Vector3& n, b3Scalar o, int s) const;
- B3_DBVT_INLINE b3Scalar ProjectMinimum(const b3Vector3& v, unsigned signs) const;
- B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
-
- B3_DBVT_INLINE friend bool b3Intersect(const b3DbvtAabbMm& a,
- const b3Vector3& b);
-
- B3_DBVT_INLINE friend b3Scalar b3Proximity(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
- B3_DBVT_INLINE friend int b3Select(const b3DbvtAabbMm& o,
- const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
- B3_DBVT_INLINE friend void b3Merge(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b,
- b3DbvtAabbMm& r);
- B3_DBVT_INLINE friend bool b3NotEqual(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b);
-
- B3_DBVT_INLINE b3Vector3& tMins() { return (mi); }
- B3_DBVT_INLINE b3Vector3& tMaxs() { return (mx); }
-
-private:
- B3_DBVT_INLINE void AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& smx) const;
-
-private:
- b3Vector3 mi, mx;
-};
-
-// Types
-typedef b3DbvtAabbMm b3DbvtVolume;
-
-/* b3DbvtNode */
-struct b3DbvtNode
-{
- b3DbvtVolume volume;
- b3DbvtNode* parent;
- B3_DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
- B3_DBVT_INLINE bool isinternal() const { return (!isleaf()); }
- union {
- b3DbvtNode* childs[2];
- void* data;
- int dataAsInt;
- };
-};
-
-///The b3DynamicBvh class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
-///This b3DynamicBvh is used for soft body collision detection and for the b3DynamicBvhBroadphase. It has a fast insert, remove and update of nodes.
-///Unlike the b3QuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
-struct b3DynamicBvh
-{
- /* Stack element */
- struct sStkNN
- {
- const b3DbvtNode* a;
- const b3DbvtNode* b;
- sStkNN() {}
- sStkNN(const b3DbvtNode* na, const b3DbvtNode* nb) : a(na), b(nb) {}
- };
- struct sStkNP
- {
- const b3DbvtNode* node;
- int mask;
- sStkNP(const b3DbvtNode* n, unsigned m) : node(n), mask(m) {}
- };
- struct sStkNPS
- {
- const b3DbvtNode* node;
- int mask;
- b3Scalar value;
- sStkNPS() {}
- sStkNPS(const b3DbvtNode* n, unsigned m, b3Scalar v) : node(n), mask(m), value(v) {}
- };
- struct sStkCLN
- {
- const b3DbvtNode* node;
- b3DbvtNode* parent;
- sStkCLN(const b3DbvtNode* n, b3DbvtNode* p) : node(n), parent(p) {}
- };
- // Policies/Interfaces
-
- /* ICollide */
- struct ICollide
- {
- B3_DBVT_VIRTUAL_DTOR(ICollide)
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode*, const b3DbvtNode*) {}
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode*) {}
- B3_DBVT_VIRTUAL void Process(const b3DbvtNode* n, b3Scalar) { Process(n); }
- B3_DBVT_VIRTUAL bool Descent(const b3DbvtNode*) { return (true); }
- B3_DBVT_VIRTUAL bool AllLeaves(const b3DbvtNode*) { return (true); }
- };
- /* IWriter */
- struct IWriter
- {
- virtual ~IWriter() {}
- virtual void Prepare(const b3DbvtNode* root, int numnodes) = 0;
- virtual void WriteNode(const b3DbvtNode*, int index, int parent, int child0, int child1) = 0;
- virtual void WriteLeaf(const b3DbvtNode*, int index, int parent) = 0;
- };
- /* IClone */
- struct IClone
- {
- virtual ~IClone() {}
- virtual void CloneLeaf(b3DbvtNode*) {}
- };
-
- // Constants
- enum
- {
- B3_SIMPLE_STACKSIZE = 64,
- B3_DOUBLE_STACKSIZE = B3_SIMPLE_STACKSIZE * 2
- };
-
- // Fields
- b3DbvtNode* m_root;
- b3DbvtNode* m_free;
- int m_lkhd;
- int m_leaves;
- unsigned m_opath;
-
- b3AlignedObjectArray<sStkNN> m_stkStack;
- mutable b3AlignedObjectArray<const b3DbvtNode*> m_rayTestStack;
-
- // Methods
- b3DynamicBvh();
- ~b3DynamicBvh();
- void clear();
- bool empty() const { return (0 == m_root); }
- void optimizeBottomUp();
- void optimizeTopDown(int bu_treshold = 128);
- void optimizeIncremental(int passes);
- b3DbvtNode* insert(const b3DbvtVolume& box, void* data);
- void update(b3DbvtNode* leaf, int lookahead = -1);
- void update(b3DbvtNode* leaf, b3DbvtVolume& volume);
- bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity, b3Scalar margin);
- bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, const b3Vector3& velocity);
- bool update(b3DbvtNode* leaf, b3DbvtVolume& volume, b3Scalar margin);
- void remove(b3DbvtNode* leaf);
- void write(IWriter* iwriter) const;
- void clone(b3DynamicBvh& dest, IClone* iclone = 0) const;
- static int maxdepth(const b3DbvtNode* node);
- static int countLeaves(const b3DbvtNode* node);
- static void extractLeaves(const b3DbvtNode* node, b3AlignedObjectArray<const b3DbvtNode*>& leaves);
-#if B3_DBVT_ENABLE_BENCHMARK
- static void benchmark();
-#else
- static void benchmark()
- {
- }
-#endif
- // B3_DBVT_IPOLICY must support ICollide policy/interface
- B3_DBVT_PREFIX
- static void enumNodes(const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
- B3_DBVT_PREFIX
- static void enumLeaves(const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
- B3_DBVT_PREFIX
- void collideTT(const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY);
-
- B3_DBVT_PREFIX
- void collideTTpersistentStack(const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY);
-#if 0
- B3_DBVT_PREFIX
- void collideTT( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- const b3Transform& xform,
- B3_DBVT_IPOLICY);
- B3_DBVT_PREFIX
- void collideTT( const b3DbvtNode* root0,
- const b3Transform& xform0,
- const b3DbvtNode* root1,
- const b3Transform& xform1,
- B3_DBVT_IPOLICY);
-#endif
-
- B3_DBVT_PREFIX
- void collideTV(const b3DbvtNode* root,
- const b3DbvtVolume& volume,
- B3_DBVT_IPOLICY) const;
- ///rayTest is a re-entrant ray test, and can be called in parallel as long as the b3AlignedAlloc is thread-safe (uses locking etc)
- ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
- B3_DBVT_PREFIX
- static void rayTest(const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- B3_DBVT_IPOLICY);
- ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
- ///rayTestInternal is used by b3DynamicBvhBroadphase to accelerate world ray casts
- B3_DBVT_PREFIX
- void rayTestInternal(const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& rayDirectionInverse,
- unsigned int signs[3],
- b3Scalar lambda_max,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- B3_DBVT_IPOLICY) const;
-
- B3_DBVT_PREFIX
- static void collideKDOP(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- int count,
- B3_DBVT_IPOLICY);
- B3_DBVT_PREFIX
- static void collideOCL(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- const b3Vector3& sortaxis,
- int count,
- B3_DBVT_IPOLICY,
- bool fullsort = true);
- B3_DBVT_PREFIX
- static void collideTU(const b3DbvtNode* root,
- B3_DBVT_IPOLICY);
- // Helpers
- static B3_DBVT_INLINE int nearest(const int* i, const b3DynamicBvh::sStkNPS* a, b3Scalar v, int l, int h)
- {
- int m = 0;
- while (l < h)
- {
- m = (l + h) >> 1;
- if (a[i[m]].value >= v)
- l = m + 1;
- else
- h = m;
- }
- return (h);
- }
- static B3_DBVT_INLINE int allocate(b3AlignedObjectArray<int>& ifree,
- b3AlignedObjectArray<sStkNPS>& stock,
- const sStkNPS& value)
- {
- int i;
- if (ifree.size() > 0)
- {
- i = ifree[ifree.size() - 1];
- ifree.pop_back();
- stock[i] = value;
- }
- else
- {
- i = stock.size();
- stock.push_back(value);
- }
- return (i);
- }
- //
-private:
- b3DynamicBvh(const b3DynamicBvh&) {}
-};
-
-//
-// Inline's
-//
-
-//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromCE(const b3Vector3& c, const b3Vector3& e)
-{
- b3DbvtAabbMm box;
- box.mi = c - e;
- box.mx = c + e;
- return (box);
-}
-
-//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromCR(const b3Vector3& c, b3Scalar r)
-{
- return (FromCE(c, b3MakeVector3(r, r, r)));
-}
-
-//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromMM(const b3Vector3& mi, const b3Vector3& mx)
-{
- b3DbvtAabbMm box;
- box.mi = mi;
- box.mx = mx;
- return (box);
-}
-
-//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3* pts, int n)
-{
- b3DbvtAabbMm box;
- box.mi = box.mx = pts[0];
- for (int i = 1; i < n; ++i)
- {
- box.mi.setMin(pts[i]);
- box.mx.setMax(pts[i]);
- }
- return (box);
-}
-
-//
-inline b3DbvtAabbMm b3DbvtAabbMm::FromPoints(const b3Vector3** ppts, int n)
-{
- b3DbvtAabbMm box;
- box.mi = box.mx = *ppts[0];
- for (int i = 1; i < n; ++i)
- {
- box.mi.setMin(*ppts[i]);
- box.mx.setMax(*ppts[i]);
- }
- return (box);
-}
-
-//
-B3_DBVT_INLINE void b3DbvtAabbMm::Expand(const b3Vector3& e)
-{
- mi -= e;
- mx += e;
-}
-
-//
-B3_DBVT_INLINE void b3DbvtAabbMm::SignedExpand(const b3Vector3& e)
-{
- if (e.x > 0)
- mx.setX(mx.x + e[0]);
- else
- mi.setX(mi.x + e[0]);
- if (e.y > 0)
- mx.setY(mx.y + e[1]);
- else
- mi.setY(mi.y + e[1]);
- if (e.z > 0)
- mx.setZ(mx.z + e[2]);
- else
- mi.setZ(mi.z + e[2]);
-}
-
-//
-B3_DBVT_INLINE bool b3DbvtAabbMm::Contain(const b3DbvtAabbMm& a) const
-{
- return ((mi.x <= a.mi.x) &&
- (mi.y <= a.mi.y) &&
- (mi.z <= a.mi.z) &&
- (mx.x >= a.mx.x) &&
- (mx.y >= a.mx.y) &&
- (mx.z >= a.mx.z));
-}
-
-//
-B3_DBVT_INLINE int b3DbvtAabbMm::Classify(const b3Vector3& n, b3Scalar o, int s) const
-{
- b3Vector3 pi, px;
- switch (s)
- {
- case (0 + 0 + 0):
- px = b3MakeVector3(mi.x, mi.y, mi.z);
- pi = b3MakeVector3(mx.x, mx.y, mx.z);
- break;
- case (1 + 0 + 0):
- px = b3MakeVector3(mx.x, mi.y, mi.z);
- pi = b3MakeVector3(mi.x, mx.y, mx.z);
- break;
- case (0 + 2 + 0):
- px = b3MakeVector3(mi.x, mx.y, mi.z);
- pi = b3MakeVector3(mx.x, mi.y, mx.z);
- break;
- case (1 + 2 + 0):
- px = b3MakeVector3(mx.x, mx.y, mi.z);
- pi = b3MakeVector3(mi.x, mi.y, mx.z);
- break;
- case (0 + 0 + 4):
- px = b3MakeVector3(mi.x, mi.y, mx.z);
- pi = b3MakeVector3(mx.x, mx.y, mi.z);
- break;
- case (1 + 0 + 4):
- px = b3MakeVector3(mx.x, mi.y, mx.z);
- pi = b3MakeVector3(mi.x, mx.y, mi.z);
- break;
- case (0 + 2 + 4):
- px = b3MakeVector3(mi.x, mx.y, mx.z);
- pi = b3MakeVector3(mx.x, mi.y, mi.z);
- break;
- case (1 + 2 + 4):
- px = b3MakeVector3(mx.x, mx.y, mx.z);
- pi = b3MakeVector3(mi.x, mi.y, mi.z);
- break;
- }
- if ((b3Dot(n, px) + o) < 0) return (-1);
- if ((b3Dot(n, pi) + o) >= 0) return (+1);
- return (0);
-}
-
-//
-B3_DBVT_INLINE b3Scalar b3DbvtAabbMm::ProjectMinimum(const b3Vector3& v, unsigned signs) const
-{
- const b3Vector3* b[] = {&mx, &mi};
- const b3Vector3 p = b3MakeVector3(b[(signs >> 0) & 1]->x,
- b[(signs >> 1) & 1]->y,
- b[(signs >> 2) & 1]->z);
- return (b3Dot(p, v));
-}
-
-//
-B3_DBVT_INLINE void b3DbvtAabbMm::AddSpan(const b3Vector3& d, b3Scalar& smi, b3Scalar& smx) const
-{
- for (int i = 0; i < 3; ++i)
- {
- if (d[i] < 0)
- {
- smi += mx[i] * d[i];
- smx += mi[i] * d[i];
- }
- else
- {
- smi += mi[i] * d[i];
- smx += mx[i] * d[i];
- }
- }
-}
-
-//
-B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
-{
-#if B3_DBVT_INT0_IMPL == B3_DBVT_IMPL_SSE
- const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
- _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
-#if defined(_WIN32)
- const __int32* pu((const __int32*)&rt);
-#else
- const int* pu((const int*)&rt);
-#endif
- return ((pu[0] | pu[1] | pu[2]) == 0);
-#else
- return ((a.mi.x <= b.mx.x) &&
- (a.mx.x >= b.mi.x) &&
- (a.mi.y <= b.mx.y) &&
- (a.mx.y >= b.mi.y) &&
- (a.mi.z <= b.mx.z) &&
- (a.mx.z >= b.mi.z));
-#endif
-}
-
-//
-B3_DBVT_INLINE bool b3Intersect(const b3DbvtAabbMm& a,
- const b3Vector3& b)
-{
- return ((b.x >= a.mi.x) &&
- (b.y >= a.mi.y) &&
- (b.z >= a.mi.z) &&
- (b.x <= a.mx.x) &&
- (b.y <= a.mx.y) &&
- (b.z <= a.mx.z));
-}
-
-//////////////////////////////////////
-
-//
-B3_DBVT_INLINE b3Scalar b3Proximity(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
-{
- const b3Vector3 d = (a.mi + a.mx) - (b.mi + b.mx);
- return (b3Fabs(d.x) + b3Fabs(d.y) + b3Fabs(d.z));
-}
-
-//
-B3_DBVT_INLINE int b3Select(const b3DbvtAabbMm& o,
- const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
-{
-#if B3_DBVT_SELECT_IMPL == B3_DBVT_IMPL_SSE
-
-#if defined(_WIN32)
- static B3_ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
-#else
- static B3_ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
-#endif
- ///@todo: the intrinsic version is 11% slower
-#if B3_DBVT_USE_INTRINSIC_SSE
-
- union b3SSEUnion ///NOTE: if we use more intrinsics, move b3SSEUnion into the LinearMath directory
- {
- __m128 ssereg;
- float floats[4];
- int ints[4];
- };
-
- __m128 omi(_mm_load_ps(o.mi));
- omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
- __m128 ami(_mm_load_ps(a.mi));
- ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
- ami = _mm_sub_ps(ami, omi);
- ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
- __m128 bmi(_mm_load_ps(b.mi));
- bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
- bmi = _mm_sub_ps(bmi, omi);
- bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
- __m128 t0(_mm_movehl_ps(ami, ami));
- ami = _mm_add_ps(ami, t0);
- ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
- __m128 t1(_mm_movehl_ps(bmi, bmi));
- bmi = _mm_add_ps(bmi, t1);
- bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
-
- b3SSEUnion tmp;
- tmp.ssereg = _mm_cmple_ss(bmi, ami);
- return tmp.ints[0] & 1;
-
-#else
- B3_ATTRIBUTE_ALIGNED16(__int32 r[1]);
- __asm
- {
- mov eax,o
- mov ecx,a
- mov edx,b
- movaps xmm0,[eax]
- movaps xmm5,mask
- addps xmm0,[eax+16]
- movaps xmm1,[ecx]
- movaps xmm2,[edx]
- addps xmm1,[ecx+16]
- addps xmm2,[edx+16]
- subps xmm1,xmm0
- subps xmm2,xmm0
- andps xmm1,xmm5
- andps xmm2,xmm5
- movhlps xmm3,xmm1
- movhlps xmm4,xmm2
- addps xmm1,xmm3
- addps xmm2,xmm4
- pshufd xmm3,xmm1,1
- pshufd xmm4,xmm2,1
- addss xmm1,xmm3
- addss xmm2,xmm4
- cmpless xmm2,xmm1
- movss r,xmm2
- }
- return (r[0] & 1);
-#endif
-#else
- return (b3Proximity(o, a) < b3Proximity(o, b) ? 0 : 1);
-#endif
-}
-
-//
-B3_DBVT_INLINE void b3Merge(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b,
- b3DbvtAabbMm& r)
-{
-#if B3_DBVT_MERGE_IMPL == B3_DBVT_IMPL_SSE
- __m128 ami(_mm_load_ps(a.mi));
- __m128 amx(_mm_load_ps(a.mx));
- __m128 bmi(_mm_load_ps(b.mi));
- __m128 bmx(_mm_load_ps(b.mx));
- ami = _mm_min_ps(ami, bmi);
- amx = _mm_max_ps(amx, bmx);
- _mm_store_ps(r.mi, ami);
- _mm_store_ps(r.mx, amx);
-#else
- for (int i = 0; i < 3; ++i)
- {
- if (a.mi[i] < b.mi[i])
- r.mi[i] = a.mi[i];
- else
- r.mi[i] = b.mi[i];
- if (a.mx[i] > b.mx[i])
- r.mx[i] = a.mx[i];
- else
- r.mx[i] = b.mx[i];
- }
-#endif
-}
-
-//
-B3_DBVT_INLINE bool b3NotEqual(const b3DbvtAabbMm& a,
- const b3DbvtAabbMm& b)
-{
- return ((a.mi.x != b.mi.x) ||
- (a.mi.y != b.mi.y) ||
- (a.mi.z != b.mi.z) ||
- (a.mx.x != b.mx.x) ||
- (a.mx.y != b.mx.y) ||
- (a.mx.z != b.mx.z));
-}
-
-//
-// Inline's
-//
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::enumNodes(const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- policy.Process(root);
- if (root->isinternal())
- {
- enumNodes(root->childs[0], policy);
- enumNodes(root->childs[1], policy);
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::enumLeaves(const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root->isinternal())
- {
- enumLeaves(root->childs[0], policy);
- enumLeaves(root->childs[1], policy);
- }
- else
- {
- policy.Process(root);
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTT(const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root0 && root1)
- {
- int depth = 1;
- int treshold = B3_DOUBLE_STACKSIZE - 4;
- b3AlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(B3_DOUBLE_STACKSIZE);
- stkStack[0] = sStkNN(root0, root1);
- do
- {
- sStkNN p = stkStack[--depth];
- if (depth > treshold)
- {
- stkStack.resize(stkStack.size() * 2);
- treshold = stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (b3Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTTpersistentStack(const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root0 && root1)
- {
- int depth = 1;
- int treshold = B3_DOUBLE_STACKSIZE - 4;
-
- m_stkStack.resize(B3_DOUBLE_STACKSIZE);
- m_stkStack[0] = sStkNN(root0, root1);
- do
- {
- sStkNN p = m_stkStack[--depth];
- if (depth > treshold)
- {
- m_stkStack.resize(m_stkStack.size() * 2);
- treshold = m_stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (b3Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-#if 0
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
- const b3DbvtNode* root1,
- const b3Transform& xform,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if(root0&&root1)
- {
- int depth=1;
- int treshold=B3_DOUBLE_STACKSIZE-4;
- b3AlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(B3_DOUBLE_STACKSIZE);
- stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=stkStack[--depth];
- if(b3Intersect(p.a->volume,p.b->volume,xform))
- {
- if(depth>treshold)
- {
- stkStack.resize(stkStack.size()*2);
- treshold=stkStack.size()-4;
- }
- if(p.a->isinternal())
- {
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
- }
- else
- {
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
- }
- }
- } while(depth);
- }
-}
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTT( const b3DbvtNode* root0,
- const b3Transform& xform0,
- const b3DbvtNode* root1,
- const b3Transform& xform1,
- B3_DBVT_IPOLICY)
-{
- const b3Transform xform=xform0.inverse()*xform1;
- collideTT(root0,root1,xform,policy);
-}
-#endif
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTV(const b3DbvtNode* root,
- const b3DbvtVolume& vol,
- B3_DBVT_IPOLICY) const
-{
- B3_DBVT_CHECKTYPE
- if (root)
- {
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
- volume(vol);
- b3AlignedObjectArray<const b3DbvtNode*> stack;
- stack.resize(0);
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(root);
- do
- {
- const b3DbvtNode* n = stack[stack.size() - 1];
- stack.pop_back();
- if (b3Intersect(n->volume, volume))
- {
- if (n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
- }
- } while (stack.size() > 0);
- }
-}
-
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::rayTestInternal(const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& rayDirectionInverse,
- unsigned int signs[3],
- b3Scalar lambda_max,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- B3_DBVT_IPOLICY) const
-{
- (void)rayTo;
- B3_DBVT_CHECKTYPE
- if (root)
- {
- int depth = 1;
- int treshold = B3_DOUBLE_STACKSIZE - 2;
- b3AlignedObjectArray<const b3DbvtNode*>& stack = m_rayTestStack;
- stack.resize(B3_DOUBLE_STACKSIZE);
- stack[0] = root;
- b3Vector3 bounds[2];
- do
- {
- const b3DbvtNode* node = stack[--depth];
- bounds[0] = node->volume.Mins() - aabbMax;
- bounds[1] = node->volume.Maxs() - aabbMin;
- b3Scalar tmin = 1.f, lambda_min = 0.f;
- unsigned int result1 = false;
- result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
- if (result1)
- {
- if (node->isinternal())
- {
- if (depth > treshold)
- {
- stack.resize(stack.size() * 2);
- treshold = stack.size() - 2;
- }
- stack[depth++] = node->childs[0];
- stack[depth++] = node->childs[1];
- }
- else
- {
- policy.Process(node);
- }
- }
- } while (depth);
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::rayTest(const b3DbvtNode* root,
- const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root)
- {
- b3Vector3 rayDir = (rayTo - rayFrom);
- rayDir.normalize();
-
- ///what about division by zero? --> just set rayDirection[i] to INF/B3_LARGE_FLOAT
- b3Vector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
- unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
-
- b3Scalar lambda_max = rayDir.dot(rayTo - rayFrom);
-#ifdef COMPARE_BTRAY_AABB2
- b3Vector3 resultNormal;
-#endif //COMPARE_BTRAY_AABB2
-
- b3AlignedObjectArray<const b3DbvtNode*> stack;
-
- int depth = 1;
- int treshold = B3_DOUBLE_STACKSIZE - 2;
-
- stack.resize(B3_DOUBLE_STACKSIZE);
- stack[0] = root;
- b3Vector3 bounds[2];
- do
- {
- const b3DbvtNode* node = stack[--depth];
-
- bounds[0] = node->volume.Mins();
- bounds[1] = node->volume.Maxs();
-
- b3Scalar tmin = 1.f, lambda_min = 0.f;
- unsigned int result1 = b3RayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
-
-#ifdef COMPARE_BTRAY_AABB2
- b3Scalar param = 1.f;
- bool result2 = b3RayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
- b3Assert(result1 == result2);
-#endif //TEST_BTRAY_AABB2
-
- if (result1)
- {
- if (node->isinternal())
- {
- if (depth > treshold)
- {
- stack.resize(stack.size() * 2);
- treshold = stack.size() - 2;
- }
- stack[depth++] = node->childs[0];
- stack[depth++] = node->childs[1];
- }
- else
- {
- policy.Process(node);
- }
- }
- } while (depth);
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideKDOP(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- int count,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root)
- {
- const int inside = (1 << count) - 1;
- b3AlignedObjectArray<sStkNP> stack;
- int signs[sizeof(unsigned) * 8];
- b3Assert(count < int(sizeof(signs) / sizeof(signs[0])));
- for (int i = 0; i < count; ++i)
- {
- signs[i] = ((normals[i].x >= 0) ? 1 : 0) +
- ((normals[i].y >= 0) ? 2 : 0) +
- ((normals[i].z >= 0) ? 4 : 0);
- }
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(sStkNP(root, 0));
- do
- {
- sStkNP se = stack[stack.size() - 1];
- bool out = false;
- stack.pop_back();
- for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
- {
- if (0 == (se.mask & j))
- {
- const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
- switch (side)
- {
- case -1:
- out = true;
- break;
- case +1:
- se.mask |= j;
- break;
- }
- }
- }
- if (!out)
- {
- if ((se.mask != inside) && (se.node->isinternal()))
- {
- stack.push_back(sStkNP(se.node->childs[0], se.mask));
- stack.push_back(sStkNP(se.node->childs[1], se.mask));
- }
- else
- {
- if (policy.AllLeaves(se.node)) enumLeaves(se.node, policy);
- }
- }
- } while (stack.size());
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideOCL(const b3DbvtNode* root,
- const b3Vector3* normals,
- const b3Scalar* offsets,
- const b3Vector3& sortaxis,
- int count,
- B3_DBVT_IPOLICY,
- bool fsort)
-{
- B3_DBVT_CHECKTYPE
- if (root)
- {
- const unsigned srtsgns = (sortaxis[0] >= 0 ? 1 : 0) +
- (sortaxis[1] >= 0 ? 2 : 0) +
- (sortaxis[2] >= 0 ? 4 : 0);
- const int inside = (1 << count) - 1;
- b3AlignedObjectArray<sStkNPS> stock;
- b3AlignedObjectArray<int> ifree;
- b3AlignedObjectArray<int> stack;
- int signs[sizeof(unsigned) * 8];
- b3Assert(count < int(sizeof(signs) / sizeof(signs[0])));
- for (int i = 0; i < count; ++i)
- {
- signs[i] = ((normals[i].x >= 0) ? 1 : 0) +
- ((normals[i].y >= 0) ? 2 : 0) +
- ((normals[i].z >= 0) ? 4 : 0);
- }
- stock.reserve(B3_SIMPLE_STACKSIZE);
- stack.reserve(B3_SIMPLE_STACKSIZE);
- ifree.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(allocate(ifree, stock, sStkNPS(root, 0, root->volume.ProjectMinimum(sortaxis, srtsgns))));
- do
- {
- const int id = stack[stack.size() - 1];
- sStkNPS se = stock[id];
- stack.pop_back();
- ifree.push_back(id);
- if (se.mask != inside)
- {
- bool out = false;
- for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
- {
- if (0 == (se.mask & j))
- {
- const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
- switch (side)
- {
- case -1:
- out = true;
- break;
- case +1:
- se.mask |= j;
- break;
- }
- }
- }
- if (out) continue;
- }
- if (policy.Descent(se.node))
- {
- if (se.node->isinternal())
- {
- const b3DbvtNode* pns[] = {se.node->childs[0], se.node->childs[1]};
- sStkNPS nes[] = {sStkNPS(pns[0], se.mask, pns[0]->volume.ProjectMinimum(sortaxis, srtsgns)),
- sStkNPS(pns[1], se.mask, pns[1]->volume.ProjectMinimum(sortaxis, srtsgns))};
- const int q = nes[0].value < nes[1].value ? 1 : 0;
- int j = stack.size();
- if (fsort && (j > 0))
- {
- /* Insert 0 */
- j = nearest(&stack[0], &stock[0], nes[q].value, 0, stack.size());
- stack.push_back(0);
-#if B3_DBVT_USE_MEMMOVE
- memmove(&stack[j + 1], &stack[j], sizeof(int) * (stack.size() - j - 1));
-#else
- for (int k = stack.size() - 1; k > j; --k) stack[k] = stack[k - 1];
-#endif
- stack[j] = allocate(ifree, stock, nes[q]);
- /* Insert 1 */
- j = nearest(&stack[0], &stock[0], nes[1 - q].value, j, stack.size());
- stack.push_back(0);
-#if B3_DBVT_USE_MEMMOVE
- memmove(&stack[j + 1], &stack[j], sizeof(int) * (stack.size() - j - 1));
-#else
- for (int k = stack.size() - 1; k > j; --k) stack[k] = stack[k - 1];
-#endif
- stack[j] = allocate(ifree, stock, nes[1 - q]);
- }
- else
- {
- stack.push_back(allocate(ifree, stock, nes[q]));
- stack.push_back(allocate(ifree, stock, nes[1 - q]));
- }
- }
- else
- {
- policy.Process(se.node, se.value);
- }
- }
- } while (stack.size());
- }
-}
-
-//
-B3_DBVT_PREFIX
-inline void b3DynamicBvh::collideTU(const b3DbvtNode* root,
- B3_DBVT_IPOLICY)
-{
- B3_DBVT_CHECKTYPE
- if (root)
- {
- b3AlignedObjectArray<const b3DbvtNode*> stack;
- stack.reserve(B3_SIMPLE_STACKSIZE);
- stack.push_back(root);
- do
- {
- const b3DbvtNode* n = stack[stack.size() - 1];
- stack.pop_back();
- if (policy.Descent(n))
- {
- if (n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
- }
- } while (stack.size() > 0);
- }
-}
-
-//
-// PP Cleanup
-//
-
-#undef B3_DBVT_USE_MEMMOVE
-#undef B3_DBVT_USE_TEMPLATE
-#undef B3_DBVT_VIRTUAL_DTOR
-#undef B3_DBVT_VIRTUAL
-#undef B3_DBVT_PREFIX
-#undef B3_DBVT_IPOLICY
-#undef B3_DBVT_CHECKTYPE
-#undef B3_DBVT_IMPL_GENERIC
-#undef B3_DBVT_IMPL_SSE
-#undef B3_DBVT_USE_INTRINSIC_SSE
-#undef B3_DBVT_SELECT_IMPL
-#undef B3_DBVT_MERGE_IMPL
-#undef B3_DBVT_INT0_IMPL
-
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
deleted file mode 100644
index dea2ddb0f2..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.cpp
+++ /dev/null
@@ -1,808 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///b3DynamicBvhBroadphase implementation by Nathanael Presson
-
-#include "b3DynamicBvhBroadphase.h"
-#include "b3OverlappingPair.h"
-
-//
-// Profiling
-//
-
-#if B3_DBVT_BP_PROFILE || B3_DBVT_BP_ENABLE_BENCHMARK
-#include <stdio.h>
-#endif
-
-#if B3_DBVT_BP_PROFILE
-struct b3ProfileScope
-{
- __forceinline b3ProfileScope(b3Clock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
- {
- }
- __forceinline ~b3ProfileScope()
- {
- (*m_value) += m_clock->getTimeMicroseconds() - m_base;
- }
- b3Clock* m_clock;
- unsigned long* m_value;
- unsigned long m_base;
-};
-#define b3SPC(_value_) b3ProfileScope spc_scope(m_clock, _value_)
-#else
-#define b3SPC(_value_)
-#endif
-
-//
-// Helpers
-//
-
-//
-template <typename T>
-static inline void b3ListAppend(T* item, T*& list)
-{
- item->links[0] = 0;
- item->links[1] = list;
- if (list) list->links[0] = item;
- list = item;
-}
-
-//
-template <typename T>
-static inline void b3ListRemove(T* item, T*& list)
-{
- if (item->links[0])
- item->links[0]->links[1] = item->links[1];
- else
- list = item->links[1];
- if (item->links[1]) item->links[1]->links[0] = item->links[0];
-}
-
-//
-template <typename T>
-static inline int b3ListCount(T* root)
-{
- int n = 0;
- while (root)
- {
- ++n;
- root = root->links[1];
- }
- return (n);
-}
-
-//
-template <typename T>
-static inline void b3Clear(T& value)
-{
- static const struct ZeroDummy : T
- {
- } zerodummy;
- value = zerodummy;
-}
-
-//
-// Colliders
-//
-
-/* Tree collider */
-struct b3DbvtTreeCollider : b3DynamicBvh::ICollide
-{
- b3DynamicBvhBroadphase* pbp;
- b3DbvtProxy* proxy;
- b3DbvtTreeCollider(b3DynamicBvhBroadphase* p) : pbp(p) {}
- void Process(const b3DbvtNode* na, const b3DbvtNode* nb)
- {
- if (na != nb)
- {
- b3DbvtProxy* pa = (b3DbvtProxy*)na->data;
- b3DbvtProxy* pb = (b3DbvtProxy*)nb->data;
-#if B3_DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- b3Swap(pa, pb);
-#endif
- pbp->m_paircache->addOverlappingPair(pa->getUid(), pb->getUid());
- ++pbp->m_newpairs;
- }
- }
- void Process(const b3DbvtNode* n)
- {
- Process(n, proxy->leaf);
- }
-};
-
-//
-// b3DynamicBvhBroadphase
-//
-
-//
-b3DynamicBvhBroadphase::b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache)
-{
- m_deferedcollide = false;
- m_needcleanup = true;
- m_releasepaircache = (paircache != 0) ? false : true;
- m_prediction = 0;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_paircache = paircache ? paircache : new (b3AlignedAlloc(sizeof(b3HashedOverlappingPairCache), 16)) b3HashedOverlappingPairCache();
-
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
-#if B3_DBVT_BP_PROFILE
- b3Clear(m_profiling);
-#endif
- m_proxies.resize(proxyCapacity);
-}
-
-//
-b3DynamicBvhBroadphase::~b3DynamicBvhBroadphase()
-{
- if (m_releasepaircache)
- {
- m_paircache->~b3OverlappingPairCache();
- b3AlignedFree(m_paircache);
- }
-}
-
-//
-b3BroadphaseProxy* b3DynamicBvhBroadphase::createProxy(const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- int objectId,
- void* userPtr,
- int collisionFilterGroup,
- int collisionFilterMask)
-{
- b3DbvtProxy* mem = &m_proxies[objectId];
- b3DbvtProxy* proxy = new (mem) b3DbvtProxy(aabbMin, aabbMax, userPtr,
- collisionFilterGroup,
- collisionFilterMask);
-
- b3DbvtAabbMm aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
-
- //bproxy->aabb = b3DbvtVolume::FromMM(aabbMin,aabbMax);
- proxy->stage = m_stageCurrent;
- proxy->m_uniqueId = objectId;
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
- if (!m_deferedcollide)
- {
- b3DbvtTreeCollider collider(this);
- collider.proxy = proxy;
- m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
- m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
- }
- return (proxy);
-}
-
-//
-void b3DynamicBvhBroadphase::destroyProxy(b3BroadphaseProxy* absproxy,
- b3Dispatcher* dispatcher)
-{
- b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
- if (proxy->stage == STAGECOUNT)
- m_sets[1].remove(proxy->leaf);
- else
- m_sets[0].remove(proxy->leaf);
- b3ListRemove(proxy, m_stageRoots[proxy->stage]);
- m_paircache->removeOverlappingPairsContainingProxy(proxy->getUid(), dispatcher);
-
- m_needcleanup = true;
-}
-
-void b3DynamicBvhBroadphase::getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const
-{
- const b3DbvtProxy* proxy = &m_proxies[objectId];
- aabbMin = proxy->m_aabbMin;
- aabbMax = proxy->m_aabbMax;
-}
-/*
-void b3DynamicBvhBroadphase::getAabb(b3BroadphaseProxy* absproxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const
-{
- b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
- aabbMin = proxy->m_aabbMin;
- aabbMax = proxy->m_aabbMax;
-}
-*/
-
-struct BroadphaseRayTester : b3DynamicBvh::ICollide
-{
- b3BroadphaseRayCallback& m_rayCallback;
- BroadphaseRayTester(b3BroadphaseRayCallback& orgCallback)
- : m_rayCallback(orgCallback)
- {
- }
- void Process(const b3DbvtNode* leaf)
- {
- b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
- m_rayCallback.process(proxy);
- }
-};
-
-void b3DynamicBvhBroadphase::rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
-{
- BroadphaseRayTester callback(rayCallback);
-
- m_sets[0].rayTestInternal(m_sets[0].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- callback);
-
- m_sets[1].rayTestInternal(m_sets[1].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- callback);
-}
-
-struct BroadphaseAabbTester : b3DynamicBvh::ICollide
-{
- b3BroadphaseAabbCallback& m_aabbCallback;
- BroadphaseAabbTester(b3BroadphaseAabbCallback& orgCallback)
- : m_aabbCallback(orgCallback)
- {
- }
- void Process(const b3DbvtNode* leaf)
- {
- b3DbvtProxy* proxy = (b3DbvtProxy*)leaf->data;
- m_aabbCallback.process(proxy);
- }
-};
-
-void b3DynamicBvhBroadphase::aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& aabbCallback)
-{
- BroadphaseAabbTester callback(aabbCallback);
-
- const B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume) bounds = b3DbvtVolume::FromMM(aabbMin, aabbMax);
- //process all children, that overlap with the given AABB bounds
- m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
- m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
-}
-
-//
-void b3DynamicBvhBroadphase::setAabb(int objectId,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Dispatcher* /*dispatcher*/)
-{
- b3DbvtProxy* proxy = &m_proxies[objectId];
- // b3DbvtProxy* proxy=(b3DbvtProxy*)absproxy;
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
- aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
-#if B3_DBVT_BP_PREVENTFALSEUPDATE
- if (b3NotEqual(aabb, proxy->leaf->volume))
-#endif
- {
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- if (b3Intersect(proxy->leaf->volume, aabb))
- { /* Moving */
-
- const b3Vector3 delta = aabbMin - proxy->m_aabbMin;
- b3Vector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
- if (delta[0] < 0) velocity[0] = -velocity[0];
- if (delta[1] < 0) velocity[1] = -velocity[1];
- if (delta[2] < 0) velocity[2] = -velocity[2];
- if (
-#ifdef B3_DBVT_BP_MARGIN
- m_sets[0].update(proxy->leaf, aabb, velocity, B3_DBVT_BP_MARGIN)
-#else
- m_sets[0].update(proxy->leaf, aabb, velocity)
-#endif
- )
- {
- ++m_updates_done;
- docollide = true;
- }
- }
- else
- { /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- }
- b3ListRemove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- b3DbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
- }
-}
-
-//
-void b3DynamicBvhBroadphase::setAabbForceUpdate(b3BroadphaseProxy* absproxy,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Dispatcher* /*dispatcher*/)
-{
- b3DbvtProxy* proxy = (b3DbvtProxy*)absproxy;
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
- aabb = b3DbvtVolume::FromMM(aabbMin, aabbMax);
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- b3ListRemove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- b3ListAppend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- b3DbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
-}
-
-//
-void b3DynamicBvhBroadphase::calculateOverlappingPairs(b3Dispatcher* dispatcher)
-{
- collide(dispatcher);
-#if B3_DBVT_BP_PROFILE
- if (0 == (m_pid % B3_DBVT_BP_PROFILING_RATE))
- {
- printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
- unsigned int total = m_profiling.m_total;
- if (total <= 0) total = 1;
- printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / B3_DBVT_BP_PROFILING_RATE);
- printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / B3_DBVT_BP_PROFILING_RATE);
- printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / B3_DBVT_BP_PROFILING_RATE);
- printf("total: %uus\r\n", total / B3_DBVT_BP_PROFILING_RATE);
- const unsigned long sum = m_profiling.m_ddcollide +
- m_profiling.m_fdcollide +
- m_profiling.m_cleanup;
- printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / B3_DBVT_BP_PROFILING_RATE);
- printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * B3_DBVT_BP_PROFILING_RATE));
- b3Clear(m_profiling);
- m_clock.reset();
- }
-#endif
-
- performDeferredRemoval(dispatcher);
-}
-
-void b3DynamicBvhBroadphase::performDeferredRemoval(b3Dispatcher* dispatcher)
-{
- if (m_paircache->hasDeferredRemoval())
- {
- b3BroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
-
- int invalidPair = 0;
-
- int i;
-
- b3BroadphasePair previousPair = b3MakeBroadphasePair(-1, -1);
-
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- b3BroadphasePair& pair = overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- //important to perform AABB check that is consistent with the broadphase
- b3DbvtProxy* pa = &m_proxies[pair.x];
- b3DbvtProxy* pb = &m_proxies[pair.y];
- bool hasOverlap = b3Intersect(pa->leaf->volume, pb->leaf->volume);
-
- if (hasOverlap)
- {
- needsRemoval = false;
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- }
-
- if (needsRemoval)
- {
- m_paircache->cleanOverlappingPair(pair, dispatcher);
-
- pair.x = -1;
- pair.y = -1;
- invalidPair++;
- }
- }
-
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(b3BroadphasePairSortPredicate());
- overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
- }
-}
-
-//
-void b3DynamicBvhBroadphase::collide(b3Dispatcher* dispatcher)
-{
- /*printf("---------------------------------------------------------\n");
- printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
- printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
- printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
- {
- int i;
- for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
- {
- printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
- getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
- }
- printf("\n");
- }
-*/
-
- b3SPC(m_profiling.m_total);
- /* optimize */
- m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
- if (m_fixedleft)
- {
- const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
- m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
- m_fixedleft = b3Max<int>(0, m_fixedleft - count);
- }
- /* dynamic -> fixed set */
- m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
- b3DbvtProxy* current = m_stageRoots[m_stageCurrent];
- if (current)
- {
- b3DbvtTreeCollider collider(this);
- do
- {
- b3DbvtProxy* next = current->links[1];
- b3ListRemove(current, m_stageRoots[current->stage]);
- b3ListAppend(current, m_stageRoots[STAGECOUNT]);
-#if B3_DBVT_BP_ACCURATESLEEPING
- m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
- collider.proxy = current;
- b3DynamicBvh::collideTV(m_sets[0].m_root, current->aabb, collider);
- b3DynamicBvh::collideTV(m_sets[1].m_root, current->aabb, collider);
-#endif
- m_sets[0].remove(current->leaf);
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
- curAabb = b3DbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
- current->leaf = m_sets[1].insert(curAabb, current);
- current->stage = STAGECOUNT;
- current = next;
- } while (current);
- m_fixedleft = m_sets[1].m_leaves;
- m_needcleanup = true;
- }
- /* collide dynamics */
- {
- b3DbvtTreeCollider collider(this);
- if (m_deferedcollide)
- {
- b3SPC(m_profiling.m_fdcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
- }
- if (m_deferedcollide)
- {
- b3SPC(m_profiling.m_ddcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
- }
- }
- /* clean up */
- if (m_needcleanup)
- {
- b3SPC(m_profiling.m_cleanup);
- b3BroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
- if (pairs.size() > 0)
- {
- int ni = b3Min(pairs.size(), b3Max<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
- for (int i = 0; i < ni; ++i)
- {
- b3BroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
- b3DbvtProxy* pa = &m_proxies[p.x];
- b3DbvtProxy* pb = &m_proxies[p.y];
- if (!b3Intersect(pa->leaf->volume, pb->leaf->volume))
- {
-#if B3_DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- b3Swap(pa, pb);
-#endif
- m_paircache->removeOverlappingPair(pa->getUid(), pb->getUid(), dispatcher);
- --ni;
- --i;
- }
- }
- if (pairs.size() > 0)
- m_cid = (m_cid + ni) % pairs.size();
- else
- m_cid = 0;
- }
- }
- ++m_pid;
- m_newpairs = 1;
- m_needcleanup = false;
- if (m_updates_call > 0)
- {
- m_updates_ratio = m_updates_done / (b3Scalar)m_updates_call;
- }
- else
- {
- m_updates_ratio = 0;
- }
- m_updates_done /= 2;
- m_updates_call /= 2;
-}
-
-//
-void b3DynamicBvhBroadphase::optimize()
-{
- m_sets[0].optimizeTopDown();
- m_sets[1].optimizeTopDown();
-}
-
-//
-b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache()
-{
- return (m_paircache);
-}
-
-//
-const b3OverlappingPairCache* b3DynamicBvhBroadphase::getOverlappingPairCache() const
-{
- return (m_paircache);
-}
-
-//
-void b3DynamicBvhBroadphase::getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const
-{
- B3_ATTRIBUTE_ALIGNED16(b3DbvtVolume)
- bounds;
-
- if (!m_sets[0].empty())
- if (!m_sets[1].empty())
- b3Merge(m_sets[0].m_root->volume,
- m_sets[1].m_root->volume, bounds);
- else
- bounds = m_sets[0].m_root->volume;
- else if (!m_sets[1].empty())
- bounds = m_sets[1].m_root->volume;
- else
- bounds = b3DbvtVolume::FromCR(b3MakeVector3(0, 0, 0), 0);
- aabbMin = bounds.Mins();
- aabbMax = bounds.Maxs();
-}
-
-void b3DynamicBvhBroadphase::resetPool(b3Dispatcher* dispatcher)
-{
- int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
- if (!totalObjects)
- {
- //reset internal dynamic tree data structures
- m_sets[0].clear();
- m_sets[1].clear();
-
- m_deferedcollide = false;
- m_needcleanup = true;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
-
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
- }
-}
-
-//
-void b3DynamicBvhBroadphase::printStats()
-{
-}
-
-//
-#if B3_DBVT_BP_ENABLE_BENCHMARK
-
-struct b3BroadphaseBenchmark
-{
- struct Experiment
- {
- const char* name;
- int object_count;
- int update_count;
- int spawn_count;
- int iterations;
- b3Scalar speed;
- b3Scalar amplitude;
- };
- struct Object
- {
- b3Vector3 center;
- b3Vector3 extents;
- b3BroadphaseProxy* proxy;
- b3Scalar time;
- void update(b3Scalar speed, b3Scalar amplitude, b3BroadphaseInterface* pbi)
- {
- time += speed;
- center[0] = b3Cos(time * (b3Scalar)2.17) * amplitude +
- b3Sin(time) * amplitude / 2;
- center[1] = b3Cos(time * (b3Scalar)1.38) * amplitude +
- b3Sin(time) * amplitude;
- center[2] = b3Sin(time * (b3Scalar)0.777) * amplitude;
- pbi->setAabb(proxy, center - extents, center + extents, 0);
- }
- };
- static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
- static b3Scalar UnitRand() { return (UnsignedRand(16384) / (b3Scalar)16384); }
- static void OutputTime(const char* name, b3Clock& c, unsigned count = 0)
- {
- const unsigned long us = c.getTimeMicroseconds();
- const unsigned long ms = (us + 500) / 1000;
- const b3Scalar sec = us / (b3Scalar)(1000 * 1000);
- if (count > 0)
- printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
- else
- printf("%s : %u us (%u ms)\r\n", name, us, ms);
- }
-};
-
-void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface* pbi)
-{
- static const b3BroadphaseBenchmark::Experiment experiments[] =
- {
- {"1024o.10%", 1024, 10, 0, 8192, (b3Scalar)0.005, (b3Scalar)100},
- /*{"4096o.10%",4096,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},
- {"8192o.10%",8192,10,0,8192,(b3Scalar)0.005,(b3Scalar)100},*/
- };
- static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
- b3AlignedObjectArray<b3BroadphaseBenchmark::Object*> objects;
- b3Clock wallclock;
- /* Begin */
- for (int iexp = 0; iexp < nexperiments; ++iexp)
- {
- const b3BroadphaseBenchmark::Experiment& experiment = experiments[iexp];
- const int object_count = experiment.object_count;
- const int update_count = (object_count * experiment.update_count) / 100;
- const int spawn_count = (object_count * experiment.spawn_count) / 100;
- const b3Scalar speed = experiment.speed;
- const b3Scalar amplitude = experiment.amplitude;
- printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
- printf("\tObjects: %u\r\n", object_count);
- printf("\tUpdate: %u\r\n", update_count);
- printf("\tSpawn: %u\r\n", spawn_count);
- printf("\tSpeed: %f\r\n", speed);
- printf("\tAmplitude: %f\r\n", amplitude);
- srand(180673);
- /* Create objects */
- wallclock.reset();
- objects.reserve(object_count);
- for (int i = 0; i < object_count; ++i)
- {
- b3BroadphaseBenchmark::Object* po = new b3BroadphaseBenchmark::Object();
- po->center[0] = b3BroadphaseBenchmark::UnitRand() * 50;
- po->center[1] = b3BroadphaseBenchmark::UnitRand() * 50;
- po->center[2] = b3BroadphaseBenchmark::UnitRand() * 50;
- po->extents[0] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[1] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[2] = b3BroadphaseBenchmark::UnitRand() * 2 + 2;
- po->time = b3BroadphaseBenchmark::UnitRand() * 2000;
- po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
- objects.push_back(po);
- }
- b3BroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
- /* First update */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- objects[i]->update(speed, amplitude, pbi);
- }
- b3BroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
- /* Updates */
- wallclock.reset();
- for (int i = 0; i < experiment.iterations; ++i)
- {
- for (int j = 0; j < update_count; ++j)
- {
- objects[j]->update(speed, amplitude, pbi);
- }
- pbi->calculateOverlappingPairs(0);
- }
- b3BroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
- /* Clean up */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- pbi->destroyProxy(objects[i]->proxy, 0);
- delete objects[i];
- }
- objects.resize(0);
- b3BroadphaseBenchmark::OutputTime("\tRelease", wallclock);
- }
-}
-#else
-/*void b3DynamicBvhBroadphase::benchmark(b3BroadphaseInterface*)
-{}
-*/
-#endif
-
-#if B3_DBVT_BP_PROFILE
-#undef b3SPC
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
deleted file mode 100644
index c235e40148..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///b3DynamicBvhBroadphase implementation by Nathanael Presson
-#ifndef B3_DBVT_BROADPHASE_H
-#define B3_DBVT_BROADPHASE_H
-
-#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvh.h"
-#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-#include "b3BroadphaseCallback.h"
-
-//
-// Compile time config
-//
-
-#define B3_DBVT_BP_PROFILE 0
-//#define B3_DBVT_BP_SORTPAIRS 1
-#define B3_DBVT_BP_PREVENTFALSEUPDATE 0
-#define B3_DBVT_BP_ACCURATESLEEPING 0
-#define B3_DBVT_BP_ENABLE_BENCHMARK 0
-#define B3_DBVT_BP_MARGIN (b3Scalar)0.05
-
-#if B3_DBVT_BP_PROFILE
-#define B3_DBVT_BP_PROFILING_RATE 256
-
-#endif
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3BroadphaseProxy
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- ///optional filtering to cull potential collisions
- enum CollisionFilterGroups
- {
- DefaultFilter = 1,
- StaticFilter = 2,
- KinematicFilter = 4,
- DebrisFilter = 8,
- SensorTrigger = 16,
- CharacterFilter = 32,
- AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
- };
-
- //Usually the client b3CollisionObject or Rigidbody class
- void* m_clientObject;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
-
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
-
- B3_FORCE_INLINE int getUid() const
- {
- return m_uniqueId;
- }
-
- //used for memory pools
- b3BroadphaseProxy() : m_clientObject(0)
- {
- }
-
- b3BroadphaseProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- : m_clientObject(userPtr),
- m_collisionFilterGroup(collisionFilterGroup),
- m_collisionFilterMask(collisionFilterMask),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
- {
- }
-};
-
-//
-// b3DbvtProxy
-//
-struct b3DbvtProxy : b3BroadphaseProxy
-{
- /* Fields */
- //b3DbvtAabbMm aabb;
- b3DbvtNode* leaf;
- b3DbvtProxy* links[2];
- int stage;
- /* ctor */
-
- explicit b3DbvtProxy() {}
- b3DbvtProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : b3BroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
- {
- links[0] = links[1] = 0;
- }
-};
-
-typedef b3AlignedObjectArray<b3DbvtProxy*> b3DbvtProxyArray;
-
-///The b3DynamicBvhBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see b3DynamicBvh).
-///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
-///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases b3AxisSweep3 and b332BitAxisSweep3.
-struct b3DynamicBvhBroadphase
-{
- /* Config */
- enum
- {
- DYNAMIC_SET = 0, /* Dynamic set index */
- FIXED_SET = 1, /* Fixed set index */
- STAGECOUNT = 2 /* Number of stages */
- };
- /* Fields */
- b3DynamicBvh m_sets[2]; // Dbvt sets
- b3DbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
-
- b3AlignedObjectArray<b3DbvtProxy> m_proxies;
- b3OverlappingPairCache* m_paircache; // Pair cache
- b3Scalar m_prediction; // Velocity prediction
- int m_stageCurrent; // Current stage
- int m_fupdates; // % of fixed updates per frame
- int m_dupdates; // % of dynamic updates per frame
- int m_cupdates; // % of cleanup updates per frame
- int m_newpairs; // Number of pairs created
- int m_fixedleft; // Fixed optimization left
- unsigned m_updates_call; // Number of updates call
- unsigned m_updates_done; // Number of updates done
- b3Scalar m_updates_ratio; // m_updates_done/m_updates_call
- int m_pid; // Parse id
- int m_cid; // Cleanup index
- bool m_releasepaircache; // Release pair cache on delete
- bool m_deferedcollide; // Defere dynamic/static collision to collide call
- bool m_needcleanup; // Need to run cleanup?
-#if B3_DBVT_BP_PROFILE
- b3Clock m_clock;
- struct
- {
- unsigned long m_total;
- unsigned long m_ddcollide;
- unsigned long m_fdcollide;
- unsigned long m_cleanup;
- unsigned long m_jobcount;
- } m_profiling;
-#endif
- /* Methods */
- b3DynamicBvhBroadphase(int proxyCapacity, b3OverlappingPairCache* paircache = 0);
- virtual ~b3DynamicBvhBroadphase();
- void collide(b3Dispatcher* dispatcher);
- void optimize();
-
- /* b3BroadphaseInterface Implementation */
- b3BroadphaseProxy* createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int objectIndex, void* userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void destroyProxy(b3BroadphaseProxy* proxy, b3Dispatcher* dispatcher);
- virtual void setAabb(int objectId, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* dispatcher);
- virtual void rayTest(const b3Vector3& rayFrom, const b3Vector3& rayTo, b3BroadphaseRayCallback& rayCallback, const b3Vector3& aabbMin = b3MakeVector3(0, 0, 0), const b3Vector3& aabbMax = b3MakeVector3(0, 0, 0));
- virtual void aabbTest(const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3BroadphaseAabbCallback& callback);
-
- //virtual void getAabb(b3BroadphaseProxy* proxy,b3Vector3& aabbMin, b3Vector3& aabbMax ) const;
- virtual void getAabb(int objectId, b3Vector3& aabbMin, b3Vector3& aabbMax) const;
- virtual void calculateOverlappingPairs(b3Dispatcher* dispatcher = 0);
- virtual b3OverlappingPairCache* getOverlappingPairCache();
- virtual const b3OverlappingPairCache* getOverlappingPairCache() const;
- virtual void getBroadphaseAabb(b3Vector3& aabbMin, b3Vector3& aabbMax) const;
- virtual void printStats();
-
- ///reset broadphase internal structures, to ensure determinism/reproducability
- virtual void resetPool(b3Dispatcher* dispatcher);
-
- void performDeferredRemoval(b3Dispatcher* dispatcher);
-
- void setVelocityPrediction(b3Scalar prediction)
- {
- m_prediction = prediction;
- }
- b3Scalar getVelocityPrediction() const
- {
- return m_prediction;
- }
-
- ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
- ///it is not part of the b3BroadphaseInterface but specific to b3DynamicBvhBroadphase.
- ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
- ///http://code.google.com/p/bullet/issues/detail?id=223
- void setAabbForceUpdate(b3BroadphaseProxy* absproxy, const b3Vector3& aabbMin, const b3Vector3& aabbMax, b3Dispatcher* /*dispatcher*/);
-
- //static void benchmark(b3BroadphaseInterface*);
-};
-
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
deleted file mode 100644
index 4ff9ebae81..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_OVERLAPPING_PAIR_H
-#define B3_OVERLAPPING_PAIR_H
-
-#include "Bullet3Common/shared/b3Int4.h"
-
-#define B3_NEW_PAIR_MARKER -1
-#define B3_REMOVED_PAIR_MARKER -2
-
-typedef b3Int4 b3BroadphasePair;
-
-inline b3Int4 b3MakeBroadphasePair(int xx, int yy)
-{
- b3Int4 pair;
-
- if (xx < yy)
- {
- pair.x = xx;
- pair.y = yy;
- }
- else
- {
- pair.x = yy;
- pair.y = xx;
- }
- pair.z = B3_NEW_PAIR_MARKER;
- pair.w = B3_NEW_PAIR_MARKER;
- return pair;
-}
-
-/*struct b3BroadphasePair : public b3Int4
-{
- explicit b3BroadphasePair(){}
-
-};
-*/
-
-class b3BroadphasePairSortPredicate
-{
-public:
- bool operator()(const b3BroadphasePair& a, const b3BroadphasePair& b) const
- {
- const int uidA0 = a.x;
- const int uidB0 = b.x;
- const int uidA1 = a.y;
- const int uidB1 = b.y;
- return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
- }
-};
-
-B3_FORCE_INLINE bool operator==(const b3BroadphasePair& a, const b3BroadphasePair& b)
-{
- return (a.x == b.x) && (a.y == b.y);
-}
-
-#endif //B3_OVERLAPPING_PAIR_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
deleted file mode 100644
index 19773244be..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.cpp
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3OverlappingPairCache.h"
-
-//#include "b3Dispatcher.h"
-//#include "b3CollisionAlgorithm.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-#include <stdio.h>
-
-int b3g_overlappingPairs = 0;
-int b3g_removePairs = 0;
-int b3g_addedPairs = 0;
-int b3g_findPairs = 0;
-
-b3HashedOverlappingPairCache::b3HashedOverlappingPairCache() : m_overlapFilterCallback(0)
-//, m_blockedForChanges(false)
-{
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
- growTables();
-}
-
-b3HashedOverlappingPairCache::~b3HashedOverlappingPairCache()
-{
-}
-
-void b3HashedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
-{
- /* if (pair.m_algorithm)
- {
- {
- pair.m_algorithm->~b3CollisionAlgorithm();
- dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm=0;
- }
- }
- */
-}
-
-void b3HashedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
-{
- class CleanPairCallback : public b3OverlapCallback
- {
- int m_cleanProxy;
- b3OverlappingPairCache* m_pairCache;
- b3Dispatcher* m_dispatcher;
-
- public:
- CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
- : m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
- virtual bool processOverlap(b3BroadphasePair& pair)
- {
- if ((pair.x == m_cleanProxy) ||
- (pair.y == m_cleanProxy))
- {
- m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
- }
- return false;
- }
- };
-
- CleanPairCallback cleanPairs(proxy, this, dispatcher);
-
- processAllOverlappingPairs(&cleanPairs, dispatcher);
-}
-
-void b3HashedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
-{
- class RemovePairCallback : public b3OverlapCallback
- {
- int m_obsoleteProxy;
-
- public:
- RemovePairCallback(int obsoleteProxy)
- : m_obsoleteProxy(obsoleteProxy)
- {
- }
- virtual bool processOverlap(b3BroadphasePair& pair)
- {
- return ((pair.x == m_obsoleteProxy) ||
- (pair.y == m_obsoleteProxy));
- }
- };
-
- RemovePairCallback removeCallback(proxy);
-
- processAllOverlappingPairs(&removeCallback, dispatcher);
-}
-
-b3BroadphasePair* b3HashedOverlappingPairCache::findPair(int proxy0, int proxy1)
-{
- b3g_findPairs++;
- if (proxy0 > proxy1)
- b3Swap(proxy0, proxy1);
- int proxyId1 = proxy0;
- int proxyId2 = proxy1;
-
- /*if (proxyId1 > proxyId2)
- b3Swap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
-
- if (hash >= m_hashTable.size())
- {
- return NULL;
- }
-
- int index = m_hashTable[hash];
- while (index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
- {
- index = m_next[index];
- }
-
- if (index == B3_NULL_PAIR)
- {
- return NULL;
- }
-
- b3Assert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
-}
-
-//#include <stdio.h>
-
-void b3HashedOverlappingPairCache::growTables()
-{
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
-
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
-
- int i;
-
- for (i = 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = B3_NULL_PAIR;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = B3_NULL_PAIR;
- }
-
- for (i = 0; i < curHashtableSize; i++)
- {
- const b3BroadphasePair& pair = m_overlappingPairArray[i];
- int proxyId1 = pair.x;
- int proxyId2 = pair.y;
- /*if (proxyId1 > proxyId2)
- b3Swap(proxyId1, proxyId2);*/
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
-}
-
-b3BroadphasePair* b3HashedOverlappingPairCache::internalAddPair(int proxy0, int proxy1)
-{
- if (proxy0 > proxy1)
- b3Swap(proxy0, proxy1);
- int proxyId1 = proxy0;
- int proxyId2 = proxy1;
-
- /*if (proxyId1 > proxyId2)
- b3Swap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
-
- b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
- if (pair != NULL)
- {
- return pair;
- }
- /*for(int i=0;i<m_overlappingPairArray.size();++i)
- {
- if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
- (m_overlappingPairArray[i].m_pProxy1==proxy1))
- {
- printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
- internalFindPair(proxy0, proxy1, hash);
- }
- }*/
- int count = m_overlappingPairArray.size();
- int oldCapacity = m_overlappingPairArray.capacity();
- pair = &m_overlappingPairArray.expandNonInitializing();
-
- //this is where we add an actual pair, so also call the 'ghost'
- // if (m_ghostPairCallback)
- // m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
-
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (oldCapacity < newCapacity)
- {
- growTables();
- //hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
- }
-
- *pair = b3MakeBroadphasePair(proxy0, proxy1);
-
- // pair->m_pProxy0 = proxy0;
- // pair->m_pProxy1 = proxy1;
- //pair->m_algorithm = 0;
- //pair->m_internalTmpValue = 0;
-
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
-
- return pair;
-}
-
-void* b3HashedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
-{
- b3g_removePairs++;
- if (proxy0 > proxy1)
- b3Swap(proxy0, proxy1);
- int proxyId1 = proxy0;
- int proxyId2 = proxy1;
-
- /*if (proxyId1 > proxyId2)
- b3Swap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
-
- b3BroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
- if (pair == NULL)
- {
- return 0;
- }
-
- cleanOverlappingPair(*pair, dispatcher);
-
- int pairIndex = int(pair - &m_overlappingPairArray[0]);
- b3Assert(pairIndex < m_overlappingPairArray.size());
-
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- b3Assert(index != B3_NULL_PAIR);
-
- int previous = B3_NULL_PAIR;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != B3_NULL_PAIR)
- {
- b3Assert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
-
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
-
- int lastPairIndex = m_overlappingPairArray.size() - 1;
-
- //if (m_ghostPairCallback)
- // m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
-
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_overlappingPairArray.pop_back();
- return 0;
- }
-
- // Remove the last pair from the hash table.
- const b3BroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->x), static_cast<unsigned int>(last->y)) & (m_overlappingPairArray.capacity() - 1));
-
- index = m_hashTable[lastHash];
- b3Assert(index != B3_NULL_PAIR);
-
- previous = B3_NULL_PAIR;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != B3_NULL_PAIR)
- {
- b3Assert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
-
- // Copy the last pair into the remove pair's spot.
- m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
-
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
-
- m_overlappingPairArray.pop_back();
-
- return 0;
-}
-//#include <stdio.h>
-
-void b3HashedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
-{
- int i;
-
- // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
- for (i = 0; i < m_overlappingPairArray.size();)
- {
- b3BroadphasePair* pair = &m_overlappingPairArray[i];
- if (callback->processOverlap(*pair))
- {
- removeOverlappingPair(pair->x, pair->y, dispatcher);
-
- b3g_overlappingPairs--;
- }
- else
- {
- i++;
- }
- }
-}
-
-void b3HashedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
-{
- ///need to keep hashmap in sync with pair address, so rebuild all
- b3BroadphasePairArray tmpPairs;
- int i;
- for (i = 0; i < m_overlappingPairArray.size(); i++)
- {
- tmpPairs.push_back(m_overlappingPairArray[i]);
- }
-
- for (i = 0; i < tmpPairs.size(); i++)
- {
- removeOverlappingPair(tmpPairs[i].x, tmpPairs[i].y, dispatcher);
- }
-
- for (i = 0; i < m_next.size(); i++)
- {
- m_next[i] = B3_NULL_PAIR;
- }
-
- tmpPairs.quickSort(b3BroadphasePairSortPredicate());
-
- for (i = 0; i < tmpPairs.size(); i++)
- {
- addOverlappingPair(tmpPairs[i].x, tmpPairs[i].y);
- }
-}
-
-void* b3SortedOverlappingPairCache::removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher)
-{
- if (!hasDeferredRemoval())
- {
- b3BroadphasePair findPair = b3MakeBroadphasePair(proxy0, proxy1);
-
- int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
- if (findIndex < m_overlappingPairArray.size())
- {
- b3g_overlappingPairs--;
- b3BroadphasePair& pair = m_overlappingPairArray[findIndex];
-
- cleanOverlappingPair(pair, dispatcher);
- //if (m_ghostPairCallback)
- // m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
-
- m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
- m_overlappingPairArray.pop_back();
- return 0;
- }
- }
-
- return 0;
-}
-
-b3BroadphasePair* b3SortedOverlappingPairCache::addOverlappingPair(int proxy0, int proxy1)
-{
- //don't add overlap with own
- b3Assert(proxy0 != proxy1);
-
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- b3BroadphasePair* pair = &m_overlappingPairArray.expandNonInitializing();
- *pair = b3MakeBroadphasePair(proxy0, proxy1);
-
- b3g_overlappingPairs++;
- b3g_addedPairs++;
-
- // if (m_ghostPairCallback)
- // m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
- return pair;
-}
-
-///this findPair becomes really slow. Either sort the list to speedup the query, or
-///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
-///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
-///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
-b3BroadphasePair* b3SortedOverlappingPairCache::findPair(int proxy0, int proxy1)
-{
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- b3BroadphasePair tmpPair = b3MakeBroadphasePair(proxy0, proxy1);
- int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
-
- if (findIndex < m_overlappingPairArray.size())
- {
- //b3Assert(it != m_overlappingPairSet.end());
- b3BroadphasePair* pair = &m_overlappingPairArray[findIndex];
- return pair;
- }
- return 0;
-}
-
-//#include <stdio.h>
-
-void b3SortedOverlappingPairCache::processAllOverlappingPairs(b3OverlapCallback* callback, b3Dispatcher* dispatcher)
-{
- int i;
-
- for (i = 0; i < m_overlappingPairArray.size();)
- {
- b3BroadphasePair* pair = &m_overlappingPairArray[i];
- if (callback->processOverlap(*pair))
- {
- cleanOverlappingPair(*pair, dispatcher);
- pair->x = -1;
- pair->y = -1;
- m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
- m_overlappingPairArray.pop_back();
- b3g_overlappingPairs--;
- }
- else
- {
- i++;
- }
- }
-}
-
-b3SortedOverlappingPairCache::b3SortedOverlappingPairCache() : m_blockedForChanges(false),
- m_hasDeferredRemoval(true),
- m_overlapFilterCallback(0)
-
-{
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
-}
-
-b3SortedOverlappingPairCache::~b3SortedOverlappingPairCache()
-{
-}
-
-void b3SortedOverlappingPairCache::cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher)
-{
- /* if (pair.m_algorithm)
- {
- {
- pair.m_algorithm->~b3CollisionAlgorithm();
- dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm=0;
- b3g_removePairs--;
- }
- }
- */
-}
-
-void b3SortedOverlappingPairCache::cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher)
-{
- class CleanPairCallback : public b3OverlapCallback
- {
- int m_cleanProxy;
- b3OverlappingPairCache* m_pairCache;
- b3Dispatcher* m_dispatcher;
-
- public:
- CleanPairCallback(int cleanProxy, b3OverlappingPairCache* pairCache, b3Dispatcher* dispatcher)
- : m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
- virtual bool processOverlap(b3BroadphasePair& pair)
- {
- if ((pair.x == m_cleanProxy) ||
- (pair.y == m_cleanProxy))
- {
- m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
- }
- return false;
- }
- };
-
- CleanPairCallback cleanPairs(proxy, this, dispatcher);
-
- processAllOverlappingPairs(&cleanPairs, dispatcher);
-}
-
-void b3SortedOverlappingPairCache::removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher)
-{
- class RemovePairCallback : public b3OverlapCallback
- {
- int m_obsoleteProxy;
-
- public:
- RemovePairCallback(int obsoleteProxy)
- : m_obsoleteProxy(obsoleteProxy)
- {
- }
- virtual bool processOverlap(b3BroadphasePair& pair)
- {
- return ((pair.x == m_obsoleteProxy) ||
- (pair.y == m_obsoleteProxy));
- }
- };
-
- RemovePairCallback removeCallback(proxy);
-
- processAllOverlappingPairs(&removeCallback, dispatcher);
-}
-
-void b3SortedOverlappingPairCache::sortOverlappingPairs(b3Dispatcher* dispatcher)
-{
- //should already be sorted
-}
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
deleted file mode 100644
index f1de1d94eb..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/b3OverlappingPairCache.h
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_OVERLAPPING_PAIR_CACHE_H
-#define B3_OVERLAPPING_PAIR_CACHE_H
-
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-class b3Dispatcher;
-#include "b3OverlappingPair.h"
-
-typedef b3AlignedObjectArray<b3BroadphasePair> b3BroadphasePairArray;
-
-struct b3OverlapCallback
-{
- virtual ~b3OverlapCallback()
- {
- }
- //return true for deletion of the pair
- virtual bool processOverlap(b3BroadphasePair& pair) = 0;
-};
-
-struct b3OverlapFilterCallback
-{
- virtual ~b3OverlapFilterCallback()
- {
- }
- // return true when pairs need collision
- virtual bool needBroadphaseCollision(int proxy0, int proxy1) const = 0;
-};
-
-extern int b3g_removePairs;
-extern int b3g_addedPairs;
-extern int b3g_findPairs;
-
-const int B3_NULL_PAIR = 0xffffffff;
-
-///The b3OverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the b3BroadphaseInterface broadphases.
-///The b3HashedOverlappingPairCache and b3SortedOverlappingPairCache classes are two implementations.
-class b3OverlappingPairCache
-{
-public:
- virtual ~b3OverlappingPairCache() {} // this is needed so we can get to the derived class destructor
-
- virtual b3BroadphasePair* getOverlappingPairArrayPtr() = 0;
-
- virtual const b3BroadphasePair* getOverlappingPairArrayPtr() const = 0;
-
- virtual b3BroadphasePairArray& getOverlappingPairArray() = 0;
-
- virtual void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher) = 0;
-
- virtual int getNumOverlappingPairs() const = 0;
-
- virtual void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher) = 0;
-
- virtual void setOverlapFilterCallback(b3OverlapFilterCallback* callback) = 0;
-
- virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher) = 0;
-
- virtual b3BroadphasePair* findPair(int proxy0, int proxy1) = 0;
-
- virtual bool hasDeferredRemoval() = 0;
-
- //virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)=0;
-
- virtual b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1) = 0;
- virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher) = 0;
- virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/) = 0;
-
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher) = 0;
-};
-
-/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
-class b3HashedOverlappingPairCache : public b3OverlappingPairCache
-{
- b3BroadphasePairArray m_overlappingPairArray;
- b3OverlapFilterCallback* m_overlapFilterCallback;
- // bool m_blockedForChanges;
-
-public:
- b3HashedOverlappingPairCache();
- virtual ~b3HashedOverlappingPairCache();
-
- virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
-
- virtual void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
-
- B3_FORCE_INLINE bool needsBroadphaseCollision(int proxy0, int proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
- bool collides = true; //(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- // Add a pair and return the new pair. If the pair already exists,
- // no new pair is created and the old one is returned.
- virtual b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1)
- {
- b3g_addedPairs++;
-
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- return internalAddPair(proxy0, proxy1);
- }
-
- void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
-
- virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
-
- virtual b3BroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
-
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
-
- b3BroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- const b3BroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
-
- void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
-
- b3BroadphasePair* findPair(int proxy0, int proxy1);
-
- int GetCount() const { return m_overlappingPairArray.size(); }
- // b3BroadphasePair* GetPairs() { return m_pairs; }
-
- b3OverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
-
- void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
- {
- m_overlapFilterCallback = callback;
- }
-
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
-private:
- b3BroadphasePair* internalAddPair(int proxy0, int proxy1);
-
- void growTables();
-
- B3_FORCE_INLINE bool equalsPair(const b3BroadphasePair& pair, int proxyId1, int proxyId2)
- {
- return pair.x == proxyId1 && pair.y == proxyId2;
- }
-
- /*
- // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
- // This assumes proxyId1 and proxyId2 are 16-bit.
- B3_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
- {
- int key = (proxyId2 << 16) | proxyId1;
- key = ~key + (key << 15);
- key = key ^ (key >> 12);
- key = key + (key << 2);
- key = key ^ (key >> 4);
- key = key * 2057;
- key = key ^ (key >> 16);
- return key;
- }
- */
-
- B3_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
- {
- int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) << 16));
- // Thomas Wang's hash
-
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return static_cast<unsigned int>(key);
- }
-
- B3_FORCE_INLINE b3BroadphasePair* internalFindPair(int proxy0, int proxy1, int hash)
- {
- int proxyId1 = proxy0;
- int proxyId2 = proxy1;
-#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
- if (proxyId1 > proxyId2)
- b3Swap(proxyId1, proxyId2);
-#endif
-
- int index = m_hashTable[hash];
-
- while (index != B3_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
- {
- index = m_next[index];
- }
-
- if (index == B3_NULL_PAIR)
- {
- return NULL;
- }
-
- b3Assert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
- }
-
- virtual bool hasDeferredRemoval()
- {
- return false;
- }
-
- /* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
- {
- m_ghostPairCallback = ghostPairCallback;
- }
- */
-
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
-
-protected:
- b3AlignedObjectArray<int> m_hashTable;
- b3AlignedObjectArray<int> m_next;
- // b3OverlappingPairCallback* m_ghostPairCallback;
-};
-
-///b3SortedOverlappingPairCache maintains the objects with overlapping AABB
-///Typically managed by the Broadphase, Axis3Sweep or b3SimpleBroadphase
-class b3SortedOverlappingPairCache : public b3OverlappingPairCache
-{
-protected:
- //avoid brute-force finding all the time
- b3BroadphasePairArray m_overlappingPairArray;
-
- //during the dispatch, check that user doesn't destroy/create proxy
- bool m_blockedForChanges;
-
- ///by default, do the removal during the pair traversal
- bool m_hasDeferredRemoval;
-
- //if set, use the callback instead of the built in filter in needBroadphaseCollision
- b3OverlapFilterCallback* m_overlapFilterCallback;
-
- // b3OverlappingPairCallback* m_ghostPairCallback;
-
-public:
- b3SortedOverlappingPairCache();
- virtual ~b3SortedOverlappingPairCache();
-
- virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* dispatcher);
-
- void* removeOverlappingPair(int proxy0, int proxy1, b3Dispatcher* dispatcher);
-
- void cleanOverlappingPair(b3BroadphasePair& pair, b3Dispatcher* dispatcher);
-
- b3BroadphasePair* addOverlappingPair(int proxy0, int proxy1);
-
- b3BroadphasePair* findPair(int proxy0, int proxy1);
-
- void cleanProxyFromPairs(int proxy, b3Dispatcher* dispatcher);
-
- virtual void removeOverlappingPairsContainingProxy(int proxy, b3Dispatcher* dispatcher);
-
- inline bool needsBroadphaseCollision(int proxy0, int proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
- bool collides = true; //(proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- //collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- b3BroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- const b3BroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
-
- b3BroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
-
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
-
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
- b3OverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
-
- void setOverlapFilterCallback(b3OverlapFilterCallback* callback)
- {
- m_overlapFilterCallback = callback;
- }
-
- virtual bool hasDeferredRemoval()
- {
- return m_hasDeferredRemoval;
- }
-
- /* virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* ghostPairCallback)
- {
- m_ghostPairCallback = ghostPairCallback;
- }
- */
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher);
-};
-
-///b3NullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
-class b3NullPairCache : public b3OverlappingPairCache
-{
- b3BroadphasePairArray m_overlappingPairArray;
-
-public:
- virtual b3BroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
- const b3BroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
- b3BroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- virtual void cleanOverlappingPair(b3BroadphasePair& /*pair*/, b3Dispatcher* /*dispatcher*/)
- {
- }
-
- virtual int getNumOverlappingPairs() const
- {
- return 0;
- }
-
- virtual void cleanProxyFromPairs(int /*proxy*/, b3Dispatcher* /*dispatcher*/)
- {
- }
-
- virtual void setOverlapFilterCallback(b3OverlapFilterCallback* /*callback*/)
- {
- }
-
- virtual void processAllOverlappingPairs(b3OverlapCallback*, b3Dispatcher* /*dispatcher*/)
- {
- }
-
- virtual b3BroadphasePair* findPair(int /*proxy0*/, int /*proxy1*/)
- {
- return 0;
- }
-
- virtual bool hasDeferredRemoval()
- {
- return true;
- }
-
- // virtual void setInternalGhostPairCallback(b3OverlappingPairCallback* /* ghostPairCallback */)
- // {
- //
- // }
-
- virtual b3BroadphasePair* addOverlappingPair(int /*proxy0*/, int /*proxy1*/)
- {
- return 0;
- }
-
- virtual void* removeOverlappingPair(int /*proxy0*/, int /*proxy1*/, b3Dispatcher* /*dispatcher*/)
- {
- return 0;
- }
-
- virtual void removeOverlappingPairsContainingProxy(int /*proxy0*/, b3Dispatcher* /*dispatcher*/)
- {
- }
-
- virtual void sortOverlappingPairs(b3Dispatcher* dispatcher)
- {
- (void)dispatcher;
- }
-};
-
-#endif //B3_OVERLAPPING_PAIR_CACHE_H
diff --git a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h b/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
deleted file mode 100644
index 343a2c0e21..0000000000
--- a/thirdparty/bullet/Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-#ifndef B3_AABB_H
-#define B3_AABB_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Common/shared/b3Mat3x3.h"
-
-typedef struct b3Aabb b3Aabb_t;
-
-struct b3Aabb
-{
- union {
- float m_min[4];
- b3Float4 m_minVec;
- int m_minIndices[4];
- };
- union {
- float m_max[4];
- b3Float4 m_maxVec;
- int m_signedMaxIndices[4];
- };
-};
-
-inline void b3TransformAabb2(b3Float4ConstArg localAabbMin, b3Float4ConstArg localAabbMax, float margin,
- b3Float4ConstArg pos,
- b3QuatConstArg orn,
- b3Float4* aabbMinOut, b3Float4* aabbMaxOut)
-{
- b3Float4 localHalfExtents = 0.5f * (localAabbMax - localAabbMin);
- localHalfExtents += b3MakeFloat4(margin, margin, margin, 0.f);
- b3Float4 localCenter = 0.5f * (localAabbMax + localAabbMin);
- b3Mat3x3 m;
- m = b3QuatGetRotationMatrix(orn);
- b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);
- b3Float4 center = b3TransformPoint(localCenter, pos, orn);
-
- b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 0)),
- b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 1)),
- b3Dot3F4(localHalfExtents, b3GetRow(abs_b, 2)),
- 0.f);
- *aabbMinOut = center - extent;
- *aabbMaxOut = center + extent;
-}
-
-/// conservative test for overlap between two aabbs
-inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1, b3Float4ConstArg aabbMax1,
- b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;
- overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;
- overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;
- return overlap;
-}
-
-#endif //B3_AABB_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h
deleted file mode 100644
index 518da89c54..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Config.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef B3_CONFIG_H
-#define B3_CONFIG_H
-
-struct b3Config
-{
- int m_maxConvexBodies;
- int m_maxConvexShapes;
- int m_maxBroadphasePairs;
- int m_maxContactCapacity;
- int m_compoundPairCapacity;
-
- int m_maxVerticesPerFace;
- int m_maxFacesPerShape;
- int m_maxConvexVertices;
- int m_maxConvexIndices;
- int m_maxConvexUniqueEdges;
-
- int m_maxCompoundChildShapes;
-
- int m_maxTriConvexPairCapacity;
-
- b3Config()
- : m_maxConvexBodies(128 * 1024),
- m_maxVerticesPerFace(64),
- m_maxFacesPerShape(12),
- m_maxConvexVertices(8192),
- m_maxConvexIndices(81920),
- m_maxConvexUniqueEdges(8192),
- m_maxCompoundChildShapes(8192),
- m_maxTriConvexPairCapacity(256 * 1024)
- {
- m_maxConvexShapes = m_maxConvexBodies;
- m_maxBroadphasePairs = 16 * m_maxConvexBodies;
- m_maxContactCapacity = m_maxBroadphasePairs;
- m_compoundPairCapacity = 1024 * 1024;
- }
-};
-
-#endif //B3_CONFIG_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
deleted file mode 100644
index c2cd3c729b..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3Contact4.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_CONTACT4_H
-#define B3_CONTACT4_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3Contact4 : public b3Contact4Data
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- int getBodyA() const { return abs(m_bodyAPtrAndSignBit); }
- int getBodyB() const { return abs(m_bodyBPtrAndSignBit); }
- bool isBodyAFixed() const { return m_bodyAPtrAndSignBit < 0; }
- bool isBodyBFixed() const { return m_bodyBPtrAndSignBit < 0; }
- // todo. make it safer
- int& getBatchIdx() { return m_batchIdx; }
- const int& getBatchIdx() const { return m_batchIdx; }
- float getRestituitionCoeff() const { return ((float)m_restituitionCoeffCmp / (float)0xffff); }
- void setRestituitionCoeff(float c)
- {
- b3Assert(c >= 0.f && c <= 1.f);
- m_restituitionCoeffCmp = (unsigned short)(c * 0xffff);
- }
- float getFrictionCoeff() const { return ((float)m_frictionCoeffCmp / (float)0xffff); }
- void setFrictionCoeff(float c)
- {
- b3Assert(c >= 0.f && c <= 1.f);
- m_frictionCoeffCmp = (unsigned short)(c * 0xffff);
- }
-
- //float& getNPoints() { return m_worldNormal[3]; }
- int getNPoints() const { return (int)m_worldNormalOnB.w; }
-
- float getPenetration(int idx) const { return m_worldPosB[idx].w; }
-
- bool isInvalid() const { return (getBodyA() == 0 || getBodyB() == 0); }
-};
-
-#endif //B3_CONTACT4_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
deleted file mode 100644
index a5dab74a34..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "b3ConvexUtility.h"
-#include "Bullet3Geometry/b3ConvexHullComputer.h"
-#include "Bullet3Geometry/b3GrahamScan2dConvexHull.h"
-#include "Bullet3Common/b3Quaternion.h"
-#include "Bullet3Common/b3HashMap.h"
-
-b3ConvexUtility::~b3ConvexUtility()
-{
-}
-
-bool b3ConvexUtility::initializePolyhedralFeatures(const b3Vector3* orgVertices, int numPoints, bool mergeCoplanarTriangles)
-{
- b3ConvexHullComputer conv;
- conv.compute(&orgVertices[0].getX(), sizeof(b3Vector3), numPoints, 0.f, 0.f);
-
- b3AlignedObjectArray<b3Vector3> faceNormals;
- int numFaces = conv.faces.size();
- faceNormals.resize(numFaces);
- b3ConvexHullComputer* convexUtil = &conv;
-
- b3AlignedObjectArray<b3MyFace> tmpFaces;
- tmpFaces.resize(numFaces);
-
- int numVertices = convexUtil->vertices.size();
- m_vertices.resize(numVertices);
- for (int p = 0; p < numVertices; p++)
- {
- m_vertices[p] = convexUtil->vertices[p];
- }
-
- for (int i = 0; i < numFaces; i++)
- {
- int face = convexUtil->faces[i];
- //printf("face=%d\n",face);
- const b3ConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
- const b3ConvexHullComputer::Edge* edge = firstEdge;
-
- b3Vector3 edges[3];
- int numEdges = 0;
- //compute face normals
-
- do
- {
- int src = edge->getSourceVertex();
- tmpFaces[i].m_indices.push_back(src);
- int targ = edge->getTargetVertex();
- b3Vector3 wa = convexUtil->vertices[src];
-
- b3Vector3 wb = convexUtil->vertices[targ];
- b3Vector3 newEdge = wb - wa;
- newEdge.normalize();
- if (numEdges < 2)
- edges[numEdges++] = newEdge;
-
- edge = edge->getNextEdgeOfFace();
- } while (edge != firstEdge);
-
- b3Scalar planeEq = 1e30f;
-
- if (numEdges == 2)
- {
- faceNormals[i] = edges[0].cross(edges[1]);
- faceNormals[i].normalize();
- tmpFaces[i].m_plane[0] = faceNormals[i].getX();
- tmpFaces[i].m_plane[1] = faceNormals[i].getY();
- tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
- tmpFaces[i].m_plane[3] = planeEq;
- }
- else
- {
- b3Assert(0); //degenerate?
- faceNormals[i].setZero();
- }
-
- for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
- {
- b3Scalar eq = m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
- if (planeEq > eq)
- {
- planeEq = eq;
- }
- }
- tmpFaces[i].m_plane[3] = -planeEq;
- }
-
- //merge coplanar faces and copy them to m_polyhedron
-
- b3Scalar faceWeldThreshold = 0.999f;
- b3AlignedObjectArray<int> todoFaces;
- for (int i = 0; i < tmpFaces.size(); i++)
- todoFaces.push_back(i);
-
- while (todoFaces.size())
- {
- b3AlignedObjectArray<int> coplanarFaceGroup;
- int refFace = todoFaces[todoFaces.size() - 1];
-
- coplanarFaceGroup.push_back(refFace);
- b3MyFace& faceA = tmpFaces[refFace];
- todoFaces.pop_back();
-
- b3Vector3 faceNormalA = b3MakeVector3(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
- for (int j = todoFaces.size() - 1; j >= 0; j--)
- {
- int i = todoFaces[j];
- b3MyFace& faceB = tmpFaces[i];
- b3Vector3 faceNormalB = b3MakeVector3(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
- if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
- {
- coplanarFaceGroup.push_back(i);
- todoFaces.remove(i);
- }
- }
-
- bool did_merge = false;
- if (coplanarFaceGroup.size() > 1)
- {
- //do the merge: use Graham Scan 2d convex hull
-
- b3AlignedObjectArray<b3GrahamVector3> orgpoints;
- b3Vector3 averageFaceNormal = b3MakeVector3(0, 0, 0);
-
- for (int i = 0; i < coplanarFaceGroup.size(); i++)
- {
- // m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
-
- b3MyFace& face = tmpFaces[coplanarFaceGroup[i]];
- b3Vector3 faceNormal = b3MakeVector3(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
- averageFaceNormal += faceNormal;
- for (int f = 0; f < face.m_indices.size(); f++)
- {
- int orgIndex = face.m_indices[f];
- b3Vector3 pt = m_vertices[orgIndex];
-
- bool found = false;
-
- for (int i = 0; i < orgpoints.size(); i++)
- {
- //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
- if (orgpoints[i].m_orgIndex == orgIndex)
- {
- found = true;
- break;
- }
- }
- if (!found)
- orgpoints.push_back(b3GrahamVector3(pt, orgIndex));
- }
- }
-
- b3MyFace combinedFace;
- for (int i = 0; i < 4; i++)
- combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
-
- b3AlignedObjectArray<b3GrahamVector3> hull;
-
- averageFaceNormal.normalize();
- b3GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
-
- for (int i = 0; i < hull.size(); i++)
- {
- combinedFace.m_indices.push_back(hull[i].m_orgIndex);
- for (int k = 0; k < orgpoints.size(); k++)
- {
- if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
- {
- orgpoints[k].m_orgIndex = -1; // invalidate...
- break;
- }
- }
- }
-
- // are there rejected vertices?
- bool reject_merge = false;
-
- for (int i = 0; i < orgpoints.size(); i++)
- {
- if (orgpoints[i].m_orgIndex == -1)
- continue; // this is in the hull...
- // this vertex is rejected -- is anybody else using this vertex?
- for (int j = 0; j < tmpFaces.size(); j++)
- {
- b3MyFace& face = tmpFaces[j];
- // is this a face of the current coplanar group?
- bool is_in_current_group = false;
- for (int k = 0; k < coplanarFaceGroup.size(); k++)
- {
- if (coplanarFaceGroup[k] == j)
- {
- is_in_current_group = true;
- break;
- }
- }
- if (is_in_current_group) // ignore this face...
- continue;
- // does this face use this rejected vertex?
- for (int v = 0; v < face.m_indices.size(); v++)
- {
- if (face.m_indices[v] == orgpoints[i].m_orgIndex)
- {
- // this rejected vertex is used in another face -- reject merge
- reject_merge = true;
- break;
- }
- }
- if (reject_merge)
- break;
- }
- if (reject_merge)
- break;
- }
-
- if (!reject_merge)
- {
- // do this merge!
- did_merge = true;
- m_faces.push_back(combinedFace);
- }
- }
- if (!did_merge)
- {
- for (int i = 0; i < coplanarFaceGroup.size(); i++)
- {
- b3MyFace face = tmpFaces[coplanarFaceGroup[i]];
- m_faces.push_back(face);
- }
- }
- }
-
- initialize();
-
- return true;
-}
-
-inline bool IsAlmostZero(const b3Vector3& v)
-{
- if (fabsf(v.getX()) > 1e-6 || fabsf(v.getY()) > 1e-6 || fabsf(v.getZ()) > 1e-6) return false;
- return true;
-}
-
-struct b3InternalVertexPair
-{
- b3InternalVertexPair(short int v0, short int v1)
- : m_v0(v0),
- m_v1(v1)
- {
- if (m_v1 > m_v0)
- b3Swap(m_v0, m_v1);
- }
- short int m_v0;
- short int m_v1;
- int getHash() const
- {
- return m_v0 + (m_v1 << 16);
- }
- bool equals(const b3InternalVertexPair& other) const
- {
- return m_v0 == other.m_v0 && m_v1 == other.m_v1;
- }
-};
-
-struct b3InternalEdge
-{
- b3InternalEdge()
- : m_face0(-1),
- m_face1(-1)
- {
- }
- short int m_face0;
- short int m_face1;
-};
-
-//
-
-#ifdef TEST_INTERNAL_OBJECTS
-bool b3ConvexUtility::testContainment() const
-{
- for (int p = 0; p < 8; p++)
- {
- b3Vector3 LocalPt;
- if (p == 0)
- LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], m_extents[2]);
- else if (p == 1)
- LocalPt = m_localCenter + b3Vector3(m_extents[0], m_extents[1], -m_extents[2]);
- else if (p == 2)
- LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], m_extents[2]);
- else if (p == 3)
- LocalPt = m_localCenter + b3Vector3(m_extents[0], -m_extents[1], -m_extents[2]);
- else if (p == 4)
- LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], m_extents[2]);
- else if (p == 5)
- LocalPt = m_localCenter + b3Vector3(-m_extents[0], m_extents[1], -m_extents[2]);
- else if (p == 6)
- LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], m_extents[2]);
- else if (p == 7)
- LocalPt = m_localCenter + b3Vector3(-m_extents[0], -m_extents[1], -m_extents[2]);
-
- for (int i = 0; i < m_faces.size(); i++)
- {
- const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
- const b3Scalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
- if (d > 0.0f)
- return false;
- }
- }
- return true;
-}
-#endif
-
-void b3ConvexUtility::initialize()
-{
- b3HashMap<b3InternalVertexPair, b3InternalEdge> edges;
-
- b3Scalar TotalArea = 0.0f;
-
- m_localCenter.setValue(0, 0, 0);
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices;
- for (int j = 0; j < NbTris; j++)
- {
- int k = (j + 1) % numVertices;
- b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
- b3InternalEdge* edptr = edges.find(vp);
- b3Vector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
- edge.normalize();
-
- bool found = false;
- b3Vector3 diff, diff2;
-
- for (int p = 0; p < m_uniqueEdges.size(); p++)
- {
- diff = m_uniqueEdges[p] - edge;
- diff2 = m_uniqueEdges[p] + edge;
-
- // if ((diff.length2()==0.f) ||
- // (diff2.length2()==0.f))
-
- if (IsAlmostZero(diff) ||
- IsAlmostZero(diff2))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- m_uniqueEdges.push_back(edge);
- }
-
- if (edptr)
- {
- //TBD: figure out why I added this assert
- // b3Assert(edptr->m_face0>=0);
- // b3Assert(edptr->m_face1<0);
- edptr->m_face1 = i;
- }
- else
- {
- b3InternalEdge ed;
- ed.m_face0 = i;
- edges.insert(vp, ed);
- }
- }
- }
-
-#ifdef USE_CONNECTED_FACES
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- m_faces[i].m_connectedFaces.resize(numVertices);
-
- for (int j = 0; j < numVertices; j++)
- {
- int k = (j + 1) % numVertices;
- b3InternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
- b3InternalEdge* edptr = edges.find(vp);
- b3Assert(edptr);
- b3Assert(edptr->m_face0 >= 0);
- b3Assert(edptr->m_face1 >= 0);
-
- int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
- m_faces[i].m_connectedFaces[j] = connectedFace;
- }
- }
-#endif //USE_CONNECTED_FACES
-
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices - 2;
-
- const b3Vector3& p0 = m_vertices[m_faces[i].m_indices[0]];
- for (int j = 1; j <= NbTris; j++)
- {
- int k = (j + 1) % numVertices;
- const b3Vector3& p1 = m_vertices[m_faces[i].m_indices[j]];
- const b3Vector3& p2 = m_vertices[m_faces[i].m_indices[k]];
- b3Scalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
- b3Vector3 Center = (p0 + p1 + p2) / 3.0f;
- m_localCenter += Area * Center;
- TotalArea += Area;
- }
- }
- m_localCenter /= TotalArea;
-
-#ifdef TEST_INTERNAL_OBJECTS
- if (1)
- {
- m_radius = FLT_MAX;
- for (int i = 0; i < m_faces.size(); i++)
- {
- const b3Vector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
- const b3Scalar dist = b3Fabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
- if (dist < m_radius)
- m_radius = dist;
- }
-
- b3Scalar MinX = FLT_MAX;
- b3Scalar MinY = FLT_MAX;
- b3Scalar MinZ = FLT_MAX;
- b3Scalar MaxX = -FLT_MAX;
- b3Scalar MaxY = -FLT_MAX;
- b3Scalar MaxZ = -FLT_MAX;
- for (int i = 0; i < m_vertices.size(); i++)
- {
- const b3Vector3& pt = m_vertices[i];
- if (pt.getX() < MinX) MinX = pt.getX();
- if (pt.getX() > MaxX) MaxX = pt.getX();
- if (pt.getY() < MinY) MinY = pt.getY();
- if (pt.getY() > MaxY) MaxY = pt.getY();
- if (pt.getZ() < MinZ) MinZ = pt.getZ();
- if (pt.getZ() > MaxZ) MaxZ = pt.getZ();
- }
- mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
- mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
-
- // const b3Scalar r = m_radius / sqrtf(2.0f);
- const b3Scalar r = m_radius / sqrtf(3.0f);
- const int LargestExtent = mE.maxAxis();
- const b3Scalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
- m_extents[0] = m_extents[1] = m_extents[2] = r;
- m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
- bool FoundBox = false;
- for (int j = 0; j < 1024; j++)
- {
- if (testContainment())
- {
- FoundBox = true;
- break;
- }
-
- m_extents[LargestExtent] -= Step;
- }
- if (!FoundBox)
- {
- m_extents[0] = m_extents[1] = m_extents[2] = r;
- }
- else
- {
- // Refine the box
- const b3Scalar Step = (m_radius - r) / 1024.0f;
- const int e0 = (1 << LargestExtent) & 3;
- const int e1 = (1 << e0) & 3;
-
- for (int j = 0; j < 1024; j++)
- {
- const b3Scalar Saved0 = m_extents[e0];
- const b3Scalar Saved1 = m_extents[e1];
- m_extents[e0] += Step;
- m_extents[e1] += Step;
-
- if (!testContainment())
- {
- m_extents[e0] = Saved0;
- m_extents[e1] = Saved1;
- break;
- }
- }
- }
- }
-#endif
-}
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
deleted file mode 100644
index 4c8a88cbda..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h
+++ /dev/null
@@ -1,55 +0,0 @@
-
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef _BT_CONVEX_UTILITY_H
-#define _BT_CONVEX_UTILITY_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Transform.h"
-
-struct b3MyFace
-{
- b3AlignedObjectArray<int> m_indices;
- b3Scalar m_plane[4];
-};
-
-B3_ATTRIBUTE_ALIGNED16(class)
-b3ConvexUtility
-{
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3Vector3 m_localCenter;
- b3Vector3 m_extents;
- b3Vector3 mC;
- b3Vector3 mE;
- b3Scalar m_radius;
-
- b3AlignedObjectArray<b3Vector3> m_vertices;
- b3AlignedObjectArray<b3MyFace> m_faces;
- b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
-
- b3ConvexUtility()
- {
- }
- virtual ~b3ConvexUtility();
-
- bool initializePolyhedralFeatures(const b3Vector3* orgVertices, int numVertices, bool mergeCoplanarTriangles = true);
-
- void initialize();
- bool testContainment() const;
-};
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
deleted file mode 100644
index e0b2161100..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.cpp
+++ /dev/null
@@ -1,297 +0,0 @@
-#include "b3CpuNarrowPhase.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h"
-
-struct b3CpuNarrowPhaseInternalData
-{
- b3AlignedObjectArray<b3Aabb> m_localShapeAABBCPU;
- b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
- b3AlignedObjectArray<b3ConvexUtility*> m_convexData;
- b3Config m_config;
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
- b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
- b3AlignedObjectArray<b3Vector3> m_convexVertices;
- b3AlignedObjectArray<int> m_convexIndices;
- b3AlignedObjectArray<b3GpuFace> m_convexFaces;
-
- b3AlignedObjectArray<b3Contact4Data> m_contacts;
-
- int m_numAcceleratedShapes;
-};
-
-const b3AlignedObjectArray<b3Contact4Data>& b3CpuNarrowPhase::getContacts() const
-{
- return m_data->m_contacts;
-}
-
-b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex)
-{
- return m_data->m_collidablesCPU[collidableIndex];
-}
-
-const b3Collidable& b3CpuNarrowPhase::getCollidableCpu(int collidableIndex) const
-{
- return m_data->m_collidablesCPU[collidableIndex];
-}
-
-b3CpuNarrowPhase::b3CpuNarrowPhase(const struct b3Config& config)
-{
- m_data = new b3CpuNarrowPhaseInternalData;
- m_data->m_config = config;
- m_data->m_numAcceleratedShapes = 0;
-}
-
-b3CpuNarrowPhase::~b3CpuNarrowPhase()
-{
- delete m_data;
-}
-
-void b3CpuNarrowPhase::computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies)
-{
- int nPairs = pairs.size();
- int numContacts = 0;
- int maxContactCapacity = m_data->m_config.m_maxContactCapacity;
- m_data->m_contacts.resize(maxContactCapacity);
-
- for (int i = 0; i < nPairs; i++)
- {
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
- int collidableIndexA = bodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = bodies[bodyIndexB].m_collidableIdx;
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- // computeContactSphereConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
- // computeContactSphereConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- //printf("convex-sphere\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
- // computeContactPlaneConvex(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- // printf("convex-plane\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- // computeContactPlaneConvex(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- // printf("plane-convex\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- // computeContactCompoundCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], hostAabbsWorldSpace,hostAabbsLocalSpace,hostVertices,hostUniqueEdges,hostIndices,hostFaces,&hostContacts[0],
- // nContacts,maxContactCapacity,treeNodesCPU,subTreesCPU,bvhInfoCPU);
- // printf("convex-plane\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
- // computeContactPlaneCompound(i,bodyIndexB,bodyIndexA,collidableIndexB,collidableIndexA,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0], &hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- // printf("convex-plane\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- // computeContactPlaneCompound(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,&bodies[0],
- // &m_data->m_collidablesCPU[0],&hostConvexData[0],&cpuChildShapes[0],&hostVertices[0],&hostIndices[0],&hostFaces[0],&hostContacts[0],nContacts,maxContactCapacity);
- // printf("plane-convex\n");
- }
-
- if (m_data->m_collidablesCPU[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- m_data->m_collidablesCPU[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- //printf("pairs[i].z=%d\n",pairs[i].z);
- //int contactIndex = computeContactConvexConvex2(i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,bodies,
- // m_data->m_collidablesCPU,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
- int contactIndex = b3ContactConvexConvexSAT(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, bodies,
- m_data->m_collidablesCPU, m_data->m_convexPolyhedra, m_data->m_convexVertices, m_data->m_uniqueEdges, m_data->m_convexIndices, m_data->m_convexFaces, m_data->m_contacts, numContacts, maxContactCapacity);
-
- if (contactIndex >= 0)
- {
- pairs[i].z = contactIndex;
- }
- // printf("plane-convex\n");
- }
- }
-
- m_data->m_contacts.resize(numContacts);
-}
-
-int b3CpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
-{
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = m_data->m_collidablesCPU[collidableIndex];
- col.m_shapeType = SHAPE_CONVEX_HULL;
- col.m_shapeIndex = -1;
-
- {
- b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
- for (int i = 0; i < utilPtr->m_vertices.size(); i++)
- localCenter += utilPtr->m_vertices[i];
- localCenter *= (1.f / utilPtr->m_vertices.size());
- utilPtr->m_localCenter = localCenter;
-
- col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
- }
-
- if (col.m_shapeIndex >= 0)
- {
- b3Aabb aabb;
-
- b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
- b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
-
- for (int i = 0; i < utilPtr->m_vertices.size(); i++)
- {
- myAabbMin.setMin(utilPtr->m_vertices[i]);
- myAabbMax.setMax(utilPtr->m_vertices[i]);
- }
- aabb.m_min[0] = myAabbMin[0];
- aabb.m_min[1] = myAabbMin[1];
- aabb.m_min[2] = myAabbMin[2];
- aabb.m_minIndices[3] = 0;
-
- aabb.m_max[0] = myAabbMax[0];
- aabb.m_max[1] = myAabbMax[1];
- aabb.m_max[2] = myAabbMax[2];
- aabb.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU.push_back(aabb);
- }
-
- return collidableIndex;
-}
-
-int b3CpuNarrowPhase::allocateCollidable()
-{
- int curSize = m_data->m_collidablesCPU.size();
- if (curSize < m_data->m_config.m_maxConvexShapes)
- {
- m_data->m_collidablesCPU.expand();
- return curSize;
- }
- else
- {
- b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
- }
- return -1;
-}
-
-int b3CpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
-{
- b3AlignedObjectArray<b3Vector3> verts;
-
- unsigned char* vts = (unsigned char*)vertices;
- for (int i = 0; i < numVertices; i++)
- {
- float* vertex = (float*)&vts[i * strideInBytes];
- verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
- }
-
- b3ConvexUtility* utilPtr = new b3ConvexUtility();
- bool merge = true;
- if (numVertices)
- {
- utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
- }
-
- int collidableIndex = registerConvexHullShape(utilPtr);
-
- delete utilPtr;
- return collidableIndex;
-}
-
-int b3CpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
-{
- m_data->m_convexData.resize(m_data->m_numAcceleratedShapes + 1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
- convex.mC = convexPtr->mC;
- convex.mE = convexPtr->mE;
- convex.m_extents = convexPtr->m_extents;
- convex.m_localCenter = convexPtr->m_localCenter;
- convex.m_radius = convexPtr->m_radius;
-
- convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
- int edgeOffset = m_data->m_uniqueEdges.size();
- convex.m_uniqueEdgesOffset = edgeOffset;
-
- m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
-
- //convex data here
- int i;
- for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
- {
- m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
- }
-
- int faceOffset = m_data->m_convexFaces.size();
- convex.m_faceOffset = faceOffset;
- convex.m_numFaces = convexPtr->m_faces.size();
-
- m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
-
- for (i = 0; i < convexPtr->m_faces.size(); i++)
- {
- m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
- convexPtr->m_faces[i].m_plane[1],
- convexPtr->m_faces[i].m_plane[2],
- convexPtr->m_faces[i].m_plane[3]);
-
- int indexOffset = m_data->m_convexIndices.size();
- int numIndices = convexPtr->m_faces[i].m_indices.size();
- m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset + numIndices);
- for (int p = 0; p < numIndices; p++)
- {
- m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
- }
- }
-
- convex.m_numVertices = convexPtr->m_vertices.size();
- int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset = vertexOffset;
-
- m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
- for (int i = 0; i < convexPtr->m_vertices.size(); i++)
- {
- m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
- }
-
- (m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
-
- return m_data->m_numAcceleratedShapes++;
-}
-
-const b3Aabb& b3CpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
-{
- return m_data->m_localShapeAABBCPU[collidableIndex];
-}
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
deleted file mode 100644
index f02353c265..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef B3_CPU_NARROWPHASE_H
-#define B3_CPU_NARROWPHASE_H
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-class b3CpuNarrowPhase
-{
-protected:
- struct b3CpuNarrowPhaseInternalData* m_data;
- int m_acceleratedCompanionShapeIndex;
- int m_planeBodyIndex;
- int m_static0Index;
-
- int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
- int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
-
-public:
- b3CpuNarrowPhase(const struct b3Config& config);
-
- virtual ~b3CpuNarrowPhase(void);
-
- int registerSphereShape(float radius);
- int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
-
- int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
- int registerFace(const b3Vector3& faceNormal, float faceConstant);
-
- int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
-
- //do they need to be merged?
-
- int registerConvexHullShape(b3ConvexUtility* utilPtr);
- int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
-
- //int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax,bool writeToGpu);
- void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
-
- void writeAllBodiesToGpu();
- void reset();
- void readbackAllBodiesToCpu();
- bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
-
- void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
- void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
-
- //virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
- virtual void computeContacts(b3AlignedObjectArray<b3Int4>& pairs, b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace, b3AlignedObjectArray<b3RigidBodyData>& bodies);
-
- const struct b3RigidBodyData* getBodiesCpu() const;
- //struct b3RigidBodyData* getBodiesCpu();
-
- int getNumBodiesGpu() const;
-
- int getNumBodyInertiasGpu() const;
-
- const struct b3Collidable* getCollidablesCpu() const;
- int getNumCollidablesGpu() const;
-
- /*const struct b3Contact4* getContactsCPU() const;
-
-
- int getNumContactsGpu() const;
- */
-
- const b3AlignedObjectArray<b3Contact4Data>& getContacts() const;
-
- int getNumRigidBodies() const;
-
- int allocateCollidable();
-
- int getStatic0Index() const
- {
- return m_static0Index;
- }
- b3Collidable& getCollidableCpu(int collidableIndex);
- const b3Collidable& getCollidableCpu(int collidableIndex) const;
-
- const b3CpuNarrowPhaseInternalData* getInternalData() const
- {
- return m_data;
- }
-
- const struct b3Aabb& getLocalSpaceAabb(int collidableIndex) const;
-};
-
-#endif //B3_CPU_NARROWPHASE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
deleted file mode 100644
index b50c0eca4f..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#ifndef B3_RAYCAST_INFO_H
-#define B3_RAYCAST_INFO_H
-
-#include "Bullet3Common/b3Vector3.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3RayInfo
-{
- b3Vector3 m_from;
- b3Vector3 m_to;
-};
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3RayHit
-{
- b3Scalar m_hitFraction;
- int m_hitBody;
- int m_hitResult1;
- int m_hitResult2;
- b3Vector3 m_hitPoint;
- b3Vector3 m_hitNormal;
-};
-
-#endif //B3_RAYCAST_INFO_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
deleted file mode 100644
index be1be57f05..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/b3RigidBodyCL.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_RIGID_BODY_CL
-#define B3_RIGID_BODY_CL
-
-#include "Bullet3Common/b3Scalar.h"
-#include "Bullet3Common/b3Matrix3x3.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-inline float b3GetInvMass(const b3RigidBodyData& body)
-{
- return body.m_invMass;
-}
-
-#endif //B3_RIGID_BODY_CL
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
deleted file mode 100644
index d6beb662b5..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h
+++ /dev/null
@@ -1,19 +0,0 @@
-
-#ifndef B3_BVH_SUBTREE_INFO_DATA_H
-#define B3_BVH_SUBTREE_INFO_DATA_H
-
-typedef struct b3BvhSubtreeInfoData b3BvhSubtreeInfoData_t;
-
-struct b3BvhSubtreeInfoData
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
- //4 bytes
- int m_subtreeSize;
- int m_padding[3];
-};
-
-#endif //B3_BVH_SUBTREE_INFO_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
deleted file mode 100644
index 7c2507cc98..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
-
-// work-in-progress
-void b3BvhTraversal(__global const b3Int4* pairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global b3Aabb* aabbs,
- __global b3Int4* concavePairsOut,
- __global volatile int* numConcavePairsOut,
- __global const b3BvhSubtreeInfo* subtreeHeadersRoot,
- __global const b3QuantizedBvhNode* quantizedNodesRoot,
- __global const b3BvhInfo* bvhInfos,
- int numPairs,
- int maxNumConcavePairsCapacity,
- int id)
-{
- int bodyIndexA = pairs[id].x;
- int bodyIndexB = pairs[id].y;
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
- {
- return;
- }
-
- if (collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH)
- return;
-
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
- if (shapeTypeB != SHAPE_CONVEX_HULL &&
- shapeTypeB != SHAPE_SPHERE &&
- shapeTypeB != SHAPE_COMPOUND_OF_CONVEX_HULLS)
- return;
-
- b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
-
- b3Float4 bvhAabbMin = bvhInfo.m_aabbMin;
- b3Float4 bvhAabbMax = bvhInfo.m_aabbMax;
- b3Float4 bvhQuantization = bvhInfo.m_quantization;
- int numSubtreeHeaders = bvhInfo.m_numSubTrees;
- __global const b3BvhSubtreeInfoData* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
- __global const b3QuantizedBvhNodeData* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
-
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- b3QuantizeWithClamp(quantizedQueryAabbMin, aabbs[bodyIndexB].m_minVec, false, bvhAabbMin, bvhAabbMax, bvhQuantization);
- b3QuantizeWithClamp(quantizedQueryAabbMax, aabbs[bodyIndexB].m_maxVec, true, bvhAabbMin, bvhAabbMax, bvhQuantization);
-
- for (int i = 0; i < numSubtreeHeaders; i++)
- {
- b3BvhSubtreeInfoData subtree = subtreeHeaders[i];
-
- int overlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- int startNodeIndex = subtree.m_rootNodeIndex;
- int endNodeIndex = subtree.m_rootNodeIndex + subtree.m_subtreeSize;
- int curIndex = startNodeIndex;
- int escapeIndex;
- int isLeafNode;
- int aabbOverlap;
- while (curIndex < endNodeIndex)
- {
- b3QuantizedBvhNodeData rootNode = quantizedNodes[curIndex];
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabbSlow(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode.m_quantizedAabbMin, rootNode.m_quantizedAabbMax);
- isLeafNode = b3IsLeaf(&rootNode);
- if (aabbOverlap)
- {
- if (isLeafNode)
- {
- int triangleIndex = b3GetTriangleIndex(&rootNode);
- if (shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- int pairIdx = b3AtomicAdd(numConcavePairsOut, numChildrenB);
- for (int b = 0; b < numChildrenB; b++)
- {
- if ((pairIdx + b) < maxNumConcavePairsCapacity)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
- b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, childShapeIndexB);
- concavePairsOut[pairIdx + b] = newPair;
- }
- }
- }
- else
- {
- int pairIdx = b3AtomicInc(numConcavePairsOut);
- if (pairIdx < maxNumConcavePairsCapacity)
- {
- b3Int4 newPair = b3MakeInt4(bodyIndexA, bodyIndexB, triangleIndex, 0);
- concavePairsOut[pairIdx] = newPair;
- }
- }
- }
- curIndex++;
- }
- else
- {
- if (isLeafNode)
- {
- curIndex++;
- }
- else
- {
- escapeIndex = b3GetEscapeIndex(&rootNode);
- curIndex += escapeIndex;
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
deleted file mode 100644
index 0d9b13f1d6..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h
+++ /dev/null
@@ -1,171 +0,0 @@
-#ifndef B3_CLIP_FACES_H
-#define B3_CLIP_FACES_H
-
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-inline b3Float4 b3Lerp3(b3Float4ConstArg a, b3Float4ConstArg b, float t)
-{
- return b3MakeFloat4(a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
-}
-
-// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFaceGlobal(__global const b3Float4* pVtxIn, int numVertsIn, b3Float4ConstArg planeNormalWS, float planeEqWS, __global b3Float4* ppVtxOut)
-{
- int ve;
- float ds, de;
- int numVertsOut = 0;
- //double-check next test
- // if (numVertsIn < 2)
- // return 0;
-
- b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
- b3Float4 endVertex = pVtxIn[0];
-
- ds = b3Dot(planeNormalWS, firstVertex) + planeEqWS;
-
- for (ve = 0; ve < numVertsIn; ve++)
- {
- endVertex = pVtxIn[ve];
- de = b3Dot(planeNormalWS, endVertex) + planeEqWS;
- if (ds < 0)
- {
- if (de < 0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut[numVertsOut++] = endVertex;
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- }
- }
- else
- {
- if (de < 0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- ppVtxOut[numVertsOut++] = endVertex;
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
- return numVertsOut;
-}
-
-__kernel void clipFacesAndFindContactsKernel(__global const b3Float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global b3Int4* clippingFacesOut,
- __global b3Float4* worldVertsA1,
- __global b3Float4* worldNormalsA1,
- __global b3Float4* worldVertsB1,
- __global b3Float4* worldVertsB2,
- int vertexFaceCapacity,
- int pairIndex)
-{
- // int i = get_global_id(0);
- //int pairIndex = i;
- int i = pairIndex;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- // if (i<numPairs)
- {
- if (hasSeparatingAxis[i])
- {
- // int bodyIndexA = pairs[i].x;
- // int bodyIndexB = pairs[i].y;
-
- int numLocalContactsOut = 0;
-
- int capacityWorldVertsB2 = vertexFaceCapacity;
-
- __global b3Float4* pVtxIn = &worldVertsB1[pairIndex * capacityWorldVertsB2];
- __global b3Float4* pVtxOut = &worldVertsB2[pairIndex * capacityWorldVertsB2];
-
- {
- __global b3Int4* clippingFaces = clippingFacesOut;
-
- int closestFaceA = clippingFaces[pairIndex].x;
- // int closestFaceB = clippingFaces[pairIndex].y;
- int numVertsInA = clippingFaces[pairIndex].z;
- int numVertsInB = clippingFaces[pairIndex].w;
-
- int numVertsOut = 0;
-
- if (closestFaceA >= 0)
- {
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
-
- for (int e0 = 0; e0 < numVertsInA; e0++)
- {
- const b3Float4 aw = worldVertsA1[pairIndex * capacityWorldVertsB2 + e0];
- const b3Float4 bw = worldVertsA1[pairIndex * capacityWorldVertsB2 + ((e0 + 1) % numVertsInA)];
- const b3Float4 WorldEdge0 = aw - bw;
- b3Float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
- b3Float4 planeNormalWS1 = -b3Cross(WorldEdge0, worldPlaneAnormal1);
- b3Float4 worldA1 = aw;
- float planeEqWS1 = -b3Dot(worldA1, planeNormalWS1);
- b3Float4 planeNormalWS = planeNormalWS1;
- float planeEqWS = planeEqWS1;
- numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS, planeEqWS, pVtxOut);
- __global b3Float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsInB = numVertsOut;
- numVertsOut = 0;
- }
-
- b3Float4 planeNormalWS = worldNormalsA1[pairIndex];
- float planeEqWS = -b3Dot(planeNormalWS, worldVertsA1[pairIndex * capacityWorldVertsB2]);
-
- for (int i = 0; i < numVertsInB; i++)
- {
- float depth = b3Dot(planeNormalWS, pVtxIn[i]) + planeEqWS;
- if (depth <= minDist)
- {
- depth = minDist;
- }
- /*
- static float maxDepth = 0.f;
- if (depth < maxDepth)
- {
- maxDepth = depth;
- if (maxDepth < -10)
- {
- printf("error at framecount %d?\n",myframecount);
- }
- printf("maxDepth = %f\n", maxDepth);
-
- }
-*/
- if (depth <= maxDist)
- {
- b3Float4 pointInWorld = pVtxIn[i];
- pVtxOut[numLocalContactsOut++] = b3MakeFloat4(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
- }
- }
- }
- clippingFaces[pairIndex].w = numLocalContactsOut;
- }
-
- for (int i = 0; i < numLocalContactsOut; i++)
- pVtxIn[i] = pVtxOut[i];
-
- } // if (hasSeparatingAxis[i])
- } // if (i<numPairs)
-}
-
-#endif //B3_CLIP_FACES_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
deleted file mode 100644
index 9a8c668af2..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h
+++ /dev/null
@@ -1,69 +0,0 @@
-
-#ifndef B3_COLLIDABLE_H
-#define B3_COLLIDABLE_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Common/shared/b3Quat.h"
-
-enum b3ShapeTypes
-{
- SHAPE_HEIGHT_FIELD = 1,
-
- SHAPE_CONVEX_HULL = 3,
- SHAPE_PLANE = 4,
- SHAPE_CONCAVE_TRIMESH = 5,
- SHAPE_COMPOUND_OF_CONVEX_HULLS = 6,
- SHAPE_SPHERE = 7,
- MAX_NUM_SHAPE_TYPES,
-};
-
-typedef struct b3Collidable b3Collidable_t;
-
-struct b3Collidable
-{
- union {
- int m_numChildShapes;
- int m_bvhIndex;
- };
- union {
- float m_radius;
- int m_compoundBvhIndex;
- };
-
- int m_shapeType;
- union {
- int m_shapeIndex;
- float m_height;
- };
-};
-
-typedef struct b3GpuChildShape b3GpuChildShape_t;
-struct b3GpuChildShape
-{
- b3Float4 m_childPosition;
- b3Quat m_childOrientation;
- union {
- int m_shapeIndex; //used for SHAPE_COMPOUND_OF_CONVEX_HULLS
- int m_capsuleAxis;
- };
- union {
- float m_radius; //used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES
- int m_numChildShapes; //used for compound shape
- };
- union {
- float m_height; //used for childshape of SHAPE_COMPOUND_OF_CAPSULES
- int m_collidableShapeIndex;
- };
- int m_shapeType;
-};
-
-struct b3CompoundOverlappingPair
-{
- int m_bodyIndexA;
- int m_bodyIndexB;
- // int m_pairType;
- int m_childShapeIndexA;
- int m_childShapeIndexB;
-};
-
-#endif //B3_COLLIDABLE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
deleted file mode 100644
index d5f6daa993..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef B3_CONTACT4DATA_H
-#define B3_CONTACT4DATA_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-
-typedef struct b3Contact4Data b3Contact4Data_t;
-
-struct b3Contact4Data
-{
- b3Float4 m_worldPosB[4];
- // b3Float4 m_localPosA[4];
- // b3Float4 m_localPosB[4];
- b3Float4 m_worldNormalOnB; // w: m_nPoints
- unsigned short m_restituitionCoeffCmp;
- unsigned short m_frictionCoeffCmp;
- int m_batchIdx;
- int m_bodyAPtrAndSignBit; //x:m_bodyAPtr, y:m_bodyBPtr
- int m_bodyBPtrAndSignBit;
-
- int m_childIndexA;
- int m_childIndexB;
- int m_unused1;
- int m_unused2;
-};
-
-inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)
-{
- return (int)contact->m_worldNormalOnB.w;
-};
-
-inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)
-{
- contact->m_worldNormalOnB.w = (float)numPoints;
-};
-
-#endif //B3_CONTACT4DATA_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
deleted file mode 100644
index ca68f4bc4e..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactConvexConvexSAT.h
+++ /dev/null
@@ -1,486 +0,0 @@
-
-#ifndef B3_CONTACT_CONVEX_CONVEX_SAT_H
-#define B3_CONTACT_CONVEX_CONVEX_SAT_H
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h"
-
-#define B3_MAX_VERTS 1024
-
-inline b3Float4 b3Lerp3(const b3Float4& a, const b3Float4& b, float t)
-{
- return b3MakeVector3(a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
-}
-
-// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-inline int b3ClipFace(const b3Float4* pVtxIn, int numVertsIn, b3Float4& planeNormalWS, float planeEqWS, b3Float4* ppVtxOut)
-{
- int ve;
- float ds, de;
- int numVertsOut = 0;
- if (numVertsIn < 2)
- return 0;
-
- b3Float4 firstVertex = pVtxIn[numVertsIn - 1];
- b3Float4 endVertex = pVtxIn[0];
-
- ds = b3Dot3F4(planeNormalWS, firstVertex) + planeEqWS;
-
- for (ve = 0; ve < numVertsIn; ve++)
- {
- endVertex = pVtxIn[ve];
-
- de = b3Dot3F4(planeNormalWS, endVertex) + planeEqWS;
-
- if (ds < 0)
- {
- if (de < 0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut[numVertsOut++] = endVertex;
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- }
- }
- else
- {
- if (de < 0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = b3Lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- ppVtxOut[numVertsOut++] = endVertex;
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
- return numVertsOut;
-}
-
-inline int b3ClipFaceAgainstHull(const b3Float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
- const b3Float4& posA, const b3Quaternion& ornA, b3Float4* worldVertsB1, int numWorldVertsB1,
- b3Float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- //const b3Float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
- b3Float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
-
- b3Float4* pVtxIn = worldVertsB1;
- b3Float4* pVtxOut = worldVertsB2;
-
- int numVertsIn = numWorldVertsB1;
- int numVertsOut = 0;
-
- int closestFaceA = -1;
- {
- float dmin = FLT_MAX;
- for (int face = 0; face < hullA->m_numFaces; face++)
- {
- const b3Float4 Normal = b3MakeVector3(
- facesA[hullA->m_faceOffset + face].m_plane.x,
- facesA[hullA->m_faceOffset + face].m_plane.y,
- facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
- const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
-
- float d = b3Dot3F4(faceANormalWS, separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- }
- }
- }
- if (closestFaceA < 0)
- return numContactsOut;
-
- b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- //int numContacts = numWorldVertsB1;
- int numVerticesA = polyA.m_numIndices;
- for (int e0 = 0; e0 < numVerticesA; e0++)
- {
- const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
- const b3Float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
- const b3Float4 edge0 = a - b;
- const b3Float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
- b3Float4 planeNormalA = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
- b3Float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
-
- b3Float4 planeNormalWS1 = -b3Cross3(WorldEdge0, worldPlaneAnormal1);
- b3Float4 worldA1 = b3TransformPoint(a, posA, ornA);
- float planeEqWS1 = -b3Dot3F4(worldA1, planeNormalWS1);
-
- b3Float4 planeNormalWS = planeNormalWS1;
- float planeEqWS = planeEqWS1;
-
- //clip face
- //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = b3ClipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
-
- //btSwap(pVtxIn,pVtxOut);
- b3Float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsIn = numVertsOut;
- numVertsOut = 0;
- }
-
- // only keep points that are behind the witness face
- {
- b3Float4 localPlaneNormal = b3MakeFloat4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
- float localPlaneEq = polyA.m_plane.w;
- b3Float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
- float planeEqWS = localPlaneEq - b3Dot3F4(planeNormalWS, posA);
- for (int i = 0; i < numVertsIn; i++)
- {
- float depth = b3Dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
- if (depth <= minDist)
- {
- depth = minDist;
- }
- if (numContactsOut < contactCapacity)
- {
- if (depth <= maxDist)
- {
- b3Float4 pointInWorld = pVtxIn[i];
- //resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
- //printf("depth=%f\n",depth);
- }
- }
- else
- {
- b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
- }
- }
- }
-
- return numContactsOut;
-}
-
-inline int b3ClipHullAgainstHull(const b3Float4& separatingNormal,
- const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA, const b3Quaternion& ornA, const b3Float4& posB, const b3Quaternion& ornB,
- b3Float4* worldVertsB1, b3Float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<b3Float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
- b3Float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
- int numWorldVertsB1 = 0;
-
- B3_PROFILE("clipHullAgainstHull");
-
- //float curMaxDist=maxDist;
- int closestFaceB = -1;
- float dmax = -FLT_MAX;
-
- {
- //B3_PROFILE("closestFaceB");
- if (hullB.m_numFaces != 1)
- {
- //printf("wtf\n");
- }
- static bool once = true;
- //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
-
- for (int face = 0; face < hullB.m_numFaces; face++)
- {
-#ifdef BT_DEBUG_SAT_FACE
- if (once)
- printf("face %d\n", face);
- const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
- if (once)
- {
- for (int i = 0; i < faceB->m_numIndices; i++)
- {
- b3Float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
- printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
- }
- }
-#endif //BT_DEBUG_SAT_FACE \
- //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
- {
- const b3Float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
- facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
- const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
-#ifdef BT_DEBUG_SAT_FACE
- if (once)
- printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
-#endif
- float d = b3Dot3F4(WorldNormal, separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
- once = false;
- }
-
- b3Assert(closestFaceB >= 0);
- {
- //B3_PROFILE("worldVertsB1");
- const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for (int e0 = 0; e0 < numVertices; e0++)
- {
- const b3Float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
- worldVertsB1[numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
- }
- }
-
- if (closestFaceB >= 0)
- {
- //B3_PROFILE("clipFaceAgainstHull");
- numContactsOut = b3ClipFaceAgainstHull((b3Float4&)separatingNormal, &hullA,
- posA, ornA,
- worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
- verticesA, facesA, indicesA,
- contactsOut, contactCapacity);
- }
-
- return numContactsOut;
-}
-
-inline int b3ClipHullHullSingle(
- int bodyIndexA, int bodyIndexB,
- const b3Float4& posA,
- const b3Quaternion& ornA,
- const b3Float4& posB,
- const b3Quaternion& ornB,
-
- int collidableIndexA, int collidableIndexB,
-
- const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
- b3AlignedObjectArray<b3Contact4Data>* globalContactOut,
- int& nContacts,
-
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
-
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
-
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
- const b3Vector3& sepNormalWorldSpace,
- int maxContactCapacity)
-{
- int contactIndex = -1;
- b3ConvexPolyhedronData hullA, hullB;
-
- b3Collidable colA = hostCollidablesA[collidableIndexA];
- hullA = hostConvexDataA[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
- b3Collidable colB = hostCollidablesB[collidableIndexB];
- hullB = hostConvexDataB[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
- b3Float4 contactsOut[B3_MAX_VERTS];
- int localContactCapacity = B3_MAX_VERTS;
-
-#ifdef _WIN32
- b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
- b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
-#endif
-
- {
- b3Float4 worldVertsB1[B3_MAX_VERTS];
- b3Float4 worldVertsB2[B3_MAX_VERTS];
- int capacityWorldVerts = B3_MAX_VERTS;
-
- b3Float4 hostNormal = b3MakeFloat4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
- int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
- int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
-
- b3Scalar minDist = -1;
- b3Scalar maxDist = 0.;
-
- b3Transform trA, trB;
- {
- //B3_PROFILE("b3TransformPoint computation");
- //trA.setIdentity();
- trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
- trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
-
- //trB.setIdentity();
- trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
- trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
- }
-
- b3Quaternion trAorn = trA.getRotation();
- b3Quaternion trBorn = trB.getRotation();
-
- int numContactsOut = b3ClipHullAgainstHull(hostNormal,
- hostConvexDataA.at(shapeA),
- hostConvexDataB.at(shapeB),
- (b3Float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
- (b3Float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
- worldVertsB1, worldVertsB2, capacityWorldVerts,
- minDist, maxDist,
- verticesA, facesA, indicesA,
- verticesB, facesB, indicesB,
-
- contactsOut, localContactCapacity);
-
- if (numContactsOut > 0)
- {
- B3_PROFILE("overlap");
-
- b3Float4 normalOnSurfaceB = (b3Float4&)hostNormal;
- // b3Float4 centerOut;
-
- b3Int4 contactIdx;
- contactIdx.x = 0;
- contactIdx.y = 1;
- contactIdx.z = 2;
- contactIdx.w = 3;
-
- int numPoints = 0;
-
- {
- B3_PROFILE("extractManifold");
- numPoints = b3ReduceContacts(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
- }
-
- b3Assert(numPoints);
-
- if (nContacts < maxContactCapacity)
- {
- contactIndex = nContacts;
- globalContactOut->expand();
- b3Contact4Data& contact = globalContactOut->at(nContacts);
- contact.m_batchIdx = 0; //i;
- contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
- contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
-
- contact.m_frictionCoeffCmp = 45874;
- contact.m_restituitionCoeffCmp = 0;
-
- // float distance = 0.f;
- for (int p = 0; p < numPoints; p++)
- {
- contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]]; //check if it is actually on B
- contact.m_worldNormalOnB = normalOnSurfaceB;
- }
- //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
- contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
- nContacts++;
- }
- else
- {
- b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
- }
- }
- }
- return contactIndex;
-}
-
-inline int b3ContactConvexConvexSAT(
- int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
- const b3AlignedObjectArray<b3Collidable>& collidables,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
- const b3AlignedObjectArray<b3Float4>& convexVertices,
- const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
- b3AlignedObjectArray<b3Contact4Data>& globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
-{
- int contactIndex = -1;
-
- b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
- b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
- b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
-
- b3ConvexPolyhedronData hullA, hullB;
-
- b3Float4 sepNormalWorldSpace;
-
- b3Collidable colA = collidables[collidableIndexA];
- hullA = convexShapes[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
- b3Collidable colB = collidables[collidableIndexB];
- hullB = convexShapes[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
-#ifdef _WIN32
- b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
- b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
-#endif
-
- bool foundSepAxis = b3FindSeparatingAxis(hullA, hullB,
- posA,
- ornA,
- posB,
- ornB,
-
- convexVertices, uniqueEdges, faces, convexIndices,
- convexVertices, uniqueEdges, faces, convexIndices,
-
- sepNormalWorldSpace);
-
- if (foundSepAxis)
- {
- contactIndex = b3ClipHullHullSingle(
- bodyIndexA, bodyIndexB,
- posA, ornA,
- posB, ornB,
- collidableIndexA, collidableIndexB,
- &rigidBodies,
- &globalContactsOut,
- nGlobalContactsOut,
-
- convexShapes,
- convexShapes,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- collidables,
- collidables,
- sepNormalWorldSpace,
- maxContactCapacity);
- }
-
- return contactIndex;
-}
-
-#endif //B3_CONTACT_CONVEX_CONVEX_SAT_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
deleted file mode 100644
index acf7c1b180..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ContactSphereSphere.h
+++ /dev/null
@@ -1,153 +0,0 @@
-
-#ifndef B3_CONTACT_SPHERE_SPHERE_H
-#define B3_CONTACT_SPHERE_SPHERE_H
-
-void computeContactSphereConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
-{
- float radius = collidables[collidableIndexA].m_radius;
- float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
-
- float4 pos = rigidBodies[bodyIndexB].m_pos;
-
- b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
-
- b3Transform tr;
- tr.setIdentity();
- tr.setOrigin(pos);
- tr.setRotation(quat);
- b3Transform trInv = tr.inverse();
-
- float4 spherePos = trInv(spherePos1);
-
- int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
- int shapeIndex = collidables[collidableIndex].m_shapeIndex;
- int numFaces = convexShapes[shapeIndex].m_numFaces;
- float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
- float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
- float minDist = -1000000.f; // TODO: What is the largest/smallest float?
- bool bCollide = true;
- int region = -1;
- float4 localHitNormal;
- for (int f = 0; f < numFaces; f++)
- {
- b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
- float4 planeEqn;
- float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
- float4 n1 = localPlaneNormal; //quatRotate(quat,localPlaneNormal);
- planeEqn = n1;
- planeEqn[3] = face.m_plane.w;
-
- float4 pntReturn;
- float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
-
- if (dist > radius)
- {
- bCollide = false;
- break;
- }
-
- if (dist > 0)
- {
- //might hit an edge or vertex
- b3Vector3 out;
-
- bool isInPoly = IsPointInPolygon(spherePos,
- &face,
- &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
- convexIndices,
- &out);
- if (isInPoly)
- {
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = pntReturn;
- localHitNormal = planeEqn;
- region = 1;
- }
- }
- else
- {
- b3Vector3 tmp = spherePos - out;
- b3Scalar l2 = tmp.length2();
- if (l2 < radius * radius)
- {
- dist = b3Sqrt(l2);
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = out;
- localHitNormal = tmp / dist;
- region = 2;
- }
- }
- else
- {
- bCollide = false;
- break;
- }
- }
- }
- else
- {
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = pntReturn;
- localHitNormal = planeEqn;
- region = 3;
- }
- }
- }
- static int numChecks = 0;
- numChecks++;
-
- if (bCollide && minDist > -10000)
- {
- float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal; //-hitNormalWorld;
- float4 pOnB1 = tr(closestPnt);
- //printf("dist ,%f,",minDist);
- float actualDepth = minDist - radius;
- if (actualDepth < 0)
- {
- //printf("actualDepth = ,%f,", actualDepth);
- //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
- //printf("region=,%d,\n", region);
- pOnB1[3] = actualDepth;
-
- int dstIdx;
- // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (nGlobalContactsOut < maxContactCapacity)
- {
- dstIdx = nGlobalContactsOut;
- nGlobalContactsOut++;
-
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = normalOnSurfaceB1;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
-
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- int numPoints = 1;
- c->m_worldNormalOnB.w = (b3Scalar)numPoints;
- } //if (dstIdx < numPairs)
- }
- } //if (hasCollision)
-}
-#endif //B3_CONTACT_SPHERE_SPHERE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
deleted file mode 100644
index d5a73bd4f5..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-#ifndef B3_CONVEX_POLYHEDRON_DATA_H
-#define B3_CONVEX_POLYHEDRON_DATA_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Common/shared/b3Quat.h"
-
-typedef struct b3GpuFace b3GpuFace_t;
-struct b3GpuFace
-{
- b3Float4 m_plane;
- int m_indexOffset;
- int m_numIndices;
- int m_unusedPadding1;
- int m_unusedPadding2;
-};
-
-typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;
-
-struct b3ConvexPolyhedronData
-{
- b3Float4 m_localCenter;
- b3Float4 m_extents;
- b3Float4 mC;
- b3Float4 mE;
-
- float m_radius;
- int m_faceOffset;
- int m_numFaces;
- int m_numVertices;
-
- int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
- int m_unused;
-};
-
-#endif //B3_CONVEX_POLYHEDRON_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
deleted file mode 100644
index 983554eb2e..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h
+++ /dev/null
@@ -1,797 +0,0 @@
-#ifndef B3_FIND_CONCAVE_SEPARATING_AXIS_H
-#define B3_FIND_CONCAVE_SEPARATING_AXIS_H
-
-#define B3_TRIANGLE_NUM_CONVEX_FACES 5
-
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-inline void b3Project(__global const b3ConvexPolyhedronData* hull, b3Float4ConstArg pos, b3QuatConstArg orn,
- const b3Float4* dir, __global const b3Float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), *dir);
- float offset = b3Dot(pos, *dir);
- for (int i = 0; i < numVerts; i++)
- {
- float dp = b3Dot(vertices[hull->m_vertexOffset + i], localDir);
- if (dp < min[0])
- min[0] = dp;
- if (dp > max[0])
- max[0] = dp;
- }
- if (min[0] > max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-inline bool b3TestSepAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA, b3QuatConstArg ornA,
- b3Float4ConstArg posB, b3QuatConstArg ornB,
- b3Float4* sep_axis, const b3Float4* verticesA, __global const b3Float4* verticesB, float* depth)
-{
- float Min0, Max0;
- float Min1, Max1;
- b3Project(hullA, posA, ornA, sep_axis, verticesA, &Min0, &Max0);
- b3Project(hullB, posB, ornB, sep_axis, verticesB, &Min1, &Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- *depth = d0 < d1 ? d0 : d1;
- return true;
-}
-
-bool b3FindSeparatingAxis(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA1,
- b3QuatConstArg ornA,
- b3Float4ConstArg posB1,
- b3QuatConstArg ornB,
- b3Float4ConstArg DeltaC2,
-
- const b3Float4* verticesA,
- const b3Float4* uniqueEdgesA,
- const b3GpuFace* facesA,
- const int* indicesA,
-
- __global const b3Float4* verticesB,
- __global const b3Float4* uniqueEdgesB,
- __global const b3GpuFace* facesB,
- __global const int* indicesB,
- b3Float4* sep,
- float* dmin)
-{
- b3Float4 posA = posA1;
- posA.w = 0.f;
- b3Float4 posB = posB1;
- posB.w = 0.f;
- /*
- static int maxFaceVertex = 0;
-
- int curFaceVertexAB = hullA->m_numFaces*hullB->m_numVertices;
- curFaceVertexAB+= hullB->m_numFaces*hullA->m_numVertices;
-
- if (curFaceVertexAB>maxFaceVertex)
- {
- maxFaceVertex = curFaceVertexAB;
- printf("curFaceVertexAB = %d\n",curFaceVertexAB);
- printf("hullA->m_numFaces = %d\n",hullA->m_numFaces);
- printf("hullA->m_numVertices = %d\n",hullA->m_numVertices);
- printf("hullB->m_numVertices = %d\n",hullB->m_numVertices);
- }
-*/
-
- int curPlaneTests = 0;
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for (int i = 0; i < numFacesA; i++)
- {
- const b3Float4 normal = facesA[hullA->m_faceOffset + i].m_plane;
- b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
- if (b3Dot(DeltaC2, faceANormalWS) < 0)
- faceANormalWS *= -1.f;
- curPlaneTests++;
- float d;
- if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, &faceANormalWS, verticesA, verticesB, &d))
- return false;
- if (d < *dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
- if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-b3Vector3 unitSphere162[] =
- {
- b3MakeVector3(0.000000, -1.000000, 0.000000),
- b3MakeVector3(0.203181, -0.967950, 0.147618),
- b3MakeVector3(-0.077607, -0.967950, 0.238853),
- b3MakeVector3(0.723607, -0.447220, 0.525725),
- b3MakeVector3(0.609547, -0.657519, 0.442856),
- b3MakeVector3(0.812729, -0.502301, 0.295238),
- b3MakeVector3(-0.251147, -0.967949, 0.000000),
- b3MakeVector3(-0.077607, -0.967950, -0.238853),
- b3MakeVector3(0.203181, -0.967950, -0.147618),
- b3MakeVector3(0.860698, -0.251151, 0.442858),
- b3MakeVector3(-0.276388, -0.447220, 0.850649),
- b3MakeVector3(-0.029639, -0.502302, 0.864184),
- b3MakeVector3(-0.155215, -0.251152, 0.955422),
- b3MakeVector3(-0.894426, -0.447216, 0.000000),
- b3MakeVector3(-0.831051, -0.502299, 0.238853),
- b3MakeVector3(-0.956626, -0.251149, 0.147618),
- b3MakeVector3(-0.276388, -0.447220, -0.850649),
- b3MakeVector3(-0.483971, -0.502302, -0.716565),
- b3MakeVector3(-0.436007, -0.251152, -0.864188),
- b3MakeVector3(0.723607, -0.447220, -0.525725),
- b3MakeVector3(0.531941, -0.502302, -0.681712),
- b3MakeVector3(0.687159, -0.251152, -0.681715),
- b3MakeVector3(0.687159, -0.251152, 0.681715),
- b3MakeVector3(-0.436007, -0.251152, 0.864188),
- b3MakeVector3(-0.956626, -0.251149, -0.147618),
- b3MakeVector3(-0.155215, -0.251152, -0.955422),
- b3MakeVector3(0.860698, -0.251151, -0.442858),
- b3MakeVector3(0.276388, 0.447220, 0.850649),
- b3MakeVector3(0.483971, 0.502302, 0.716565),
- b3MakeVector3(0.232822, 0.657519, 0.716563),
- b3MakeVector3(-0.723607, 0.447220, 0.525725),
- b3MakeVector3(-0.531941, 0.502302, 0.681712),
- b3MakeVector3(-0.609547, 0.657519, 0.442856),
- b3MakeVector3(-0.723607, 0.447220, -0.525725),
- b3MakeVector3(-0.812729, 0.502301, -0.295238),
- b3MakeVector3(-0.609547, 0.657519, -0.442856),
- b3MakeVector3(0.276388, 0.447220, -0.850649),
- b3MakeVector3(0.029639, 0.502302, -0.864184),
- b3MakeVector3(0.232822, 0.657519, -0.716563),
- b3MakeVector3(0.894426, 0.447216, 0.000000),
- b3MakeVector3(0.831051, 0.502299, -0.238853),
- b3MakeVector3(0.753442, 0.657515, 0.000000),
- b3MakeVector3(-0.232822, -0.657519, 0.716563),
- b3MakeVector3(-0.162456, -0.850654, 0.499995),
- b3MakeVector3(0.052790, -0.723612, 0.688185),
- b3MakeVector3(0.138199, -0.894429, 0.425321),
- b3MakeVector3(0.262869, -0.525738, 0.809012),
- b3MakeVector3(0.361805, -0.723611, 0.587779),
- b3MakeVector3(0.531941, -0.502302, 0.681712),
- b3MakeVector3(0.425323, -0.850654, 0.309011),
- b3MakeVector3(0.812729, -0.502301, -0.295238),
- b3MakeVector3(0.609547, -0.657519, -0.442856),
- b3MakeVector3(0.850648, -0.525736, 0.000000),
- b3MakeVector3(0.670817, -0.723611, -0.162457),
- b3MakeVector3(0.670817, -0.723610, 0.162458),
- b3MakeVector3(0.425323, -0.850654, -0.309011),
- b3MakeVector3(0.447211, -0.894428, 0.000001),
- b3MakeVector3(-0.753442, -0.657515, 0.000000),
- b3MakeVector3(-0.525730, -0.850652, 0.000000),
- b3MakeVector3(-0.638195, -0.723609, 0.262864),
- b3MakeVector3(-0.361801, -0.894428, 0.262864),
- b3MakeVector3(-0.688189, -0.525736, 0.499997),
- b3MakeVector3(-0.447211, -0.723610, 0.525729),
- b3MakeVector3(-0.483971, -0.502302, 0.716565),
- b3MakeVector3(-0.232822, -0.657519, -0.716563),
- b3MakeVector3(-0.162456, -0.850654, -0.499995),
- b3MakeVector3(-0.447211, -0.723611, -0.525727),
- b3MakeVector3(-0.361801, -0.894429, -0.262863),
- b3MakeVector3(-0.688189, -0.525736, -0.499997),
- b3MakeVector3(-0.638195, -0.723609, -0.262863),
- b3MakeVector3(-0.831051, -0.502299, -0.238853),
- b3MakeVector3(0.361804, -0.723612, -0.587779),
- b3MakeVector3(0.138197, -0.894429, -0.425321),
- b3MakeVector3(0.262869, -0.525738, -0.809012),
- b3MakeVector3(0.052789, -0.723611, -0.688186),
- b3MakeVector3(-0.029639, -0.502302, -0.864184),
- b3MakeVector3(0.956626, 0.251149, 0.147618),
- b3MakeVector3(0.956626, 0.251149, -0.147618),
- b3MakeVector3(0.951058, -0.000000, 0.309013),
- b3MakeVector3(1.000000, 0.000000, 0.000000),
- b3MakeVector3(0.947213, -0.276396, 0.162458),
- b3MakeVector3(0.951058, 0.000000, -0.309013),
- b3MakeVector3(0.947213, -0.276396, -0.162458),
- b3MakeVector3(0.155215, 0.251152, 0.955422),
- b3MakeVector3(0.436007, 0.251152, 0.864188),
- b3MakeVector3(-0.000000, -0.000000, 1.000000),
- b3MakeVector3(0.309017, 0.000000, 0.951056),
- b3MakeVector3(0.138199, -0.276398, 0.951055),
- b3MakeVector3(0.587786, 0.000000, 0.809017),
- b3MakeVector3(0.447216, -0.276398, 0.850648),
- b3MakeVector3(-0.860698, 0.251151, 0.442858),
- b3MakeVector3(-0.687159, 0.251152, 0.681715),
- b3MakeVector3(-0.951058, -0.000000, 0.309013),
- b3MakeVector3(-0.809018, 0.000000, 0.587783),
- b3MakeVector3(-0.861803, -0.276396, 0.425324),
- b3MakeVector3(-0.587786, 0.000000, 0.809017),
- b3MakeVector3(-0.670819, -0.276397, 0.688191),
- b3MakeVector3(-0.687159, 0.251152, -0.681715),
- b3MakeVector3(-0.860698, 0.251151, -0.442858),
- b3MakeVector3(-0.587786, -0.000000, -0.809017),
- b3MakeVector3(-0.809018, -0.000000, -0.587783),
- b3MakeVector3(-0.670819, -0.276397, -0.688191),
- b3MakeVector3(-0.951058, 0.000000, -0.309013),
- b3MakeVector3(-0.861803, -0.276396, -0.425324),
- b3MakeVector3(0.436007, 0.251152, -0.864188),
- b3MakeVector3(0.155215, 0.251152, -0.955422),
- b3MakeVector3(0.587786, -0.000000, -0.809017),
- b3MakeVector3(0.309017, -0.000000, -0.951056),
- b3MakeVector3(0.447216, -0.276398, -0.850648),
- b3MakeVector3(0.000000, 0.000000, -1.000000),
- b3MakeVector3(0.138199, -0.276398, -0.951055),
- b3MakeVector3(0.670820, 0.276396, 0.688190),
- b3MakeVector3(0.809019, -0.000002, 0.587783),
- b3MakeVector3(0.688189, 0.525736, 0.499997),
- b3MakeVector3(0.861804, 0.276394, 0.425323),
- b3MakeVector3(0.831051, 0.502299, 0.238853),
- b3MakeVector3(-0.447216, 0.276397, 0.850649),
- b3MakeVector3(-0.309017, -0.000001, 0.951056),
- b3MakeVector3(-0.262869, 0.525738, 0.809012),
- b3MakeVector3(-0.138199, 0.276397, 0.951055),
- b3MakeVector3(0.029639, 0.502302, 0.864184),
- b3MakeVector3(-0.947213, 0.276396, -0.162458),
- b3MakeVector3(-1.000000, 0.000001, 0.000000),
- b3MakeVector3(-0.850648, 0.525736, -0.000000),
- b3MakeVector3(-0.947213, 0.276397, 0.162458),
- b3MakeVector3(-0.812729, 0.502301, 0.295238),
- b3MakeVector3(-0.138199, 0.276397, -0.951055),
- b3MakeVector3(-0.309016, -0.000000, -0.951057),
- b3MakeVector3(-0.262869, 0.525738, -0.809012),
- b3MakeVector3(-0.447215, 0.276397, -0.850649),
- b3MakeVector3(-0.531941, 0.502302, -0.681712),
- b3MakeVector3(0.861804, 0.276396, -0.425322),
- b3MakeVector3(0.809019, 0.000000, -0.587782),
- b3MakeVector3(0.688189, 0.525736, -0.499997),
- b3MakeVector3(0.670821, 0.276397, -0.688189),
- b3MakeVector3(0.483971, 0.502302, -0.716565),
- b3MakeVector3(0.077607, 0.967950, 0.238853),
- b3MakeVector3(0.251147, 0.967949, 0.000000),
- b3MakeVector3(0.000000, 1.000000, 0.000000),
- b3MakeVector3(0.162456, 0.850654, 0.499995),
- b3MakeVector3(0.361800, 0.894429, 0.262863),
- b3MakeVector3(0.447209, 0.723612, 0.525728),
- b3MakeVector3(0.525730, 0.850652, 0.000000),
- b3MakeVector3(0.638194, 0.723610, 0.262864),
- b3MakeVector3(-0.203181, 0.967950, 0.147618),
- b3MakeVector3(-0.425323, 0.850654, 0.309011),
- b3MakeVector3(-0.138197, 0.894430, 0.425320),
- b3MakeVector3(-0.361804, 0.723612, 0.587778),
- b3MakeVector3(-0.052790, 0.723612, 0.688185),
- b3MakeVector3(-0.203181, 0.967950, -0.147618),
- b3MakeVector3(-0.425323, 0.850654, -0.309011),
- b3MakeVector3(-0.447210, 0.894429, 0.000000),
- b3MakeVector3(-0.670817, 0.723611, -0.162457),
- b3MakeVector3(-0.670817, 0.723611, 0.162457),
- b3MakeVector3(0.077607, 0.967950, -0.238853),
- b3MakeVector3(0.162456, 0.850654, -0.499995),
- b3MakeVector3(-0.138197, 0.894430, -0.425320),
- b3MakeVector3(-0.052790, 0.723612, -0.688185),
- b3MakeVector3(-0.361804, 0.723612, -0.587778),
- b3MakeVector3(0.361800, 0.894429, -0.262863),
- b3MakeVector3(0.638194, 0.723610, -0.262864),
- b3MakeVector3(0.447209, 0.723612, -0.525728)};
-
-bool b3FindSeparatingAxisEdgeEdge(const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- b3Float4ConstArg posA1,
- b3QuatConstArg ornA,
- b3Float4ConstArg posB1,
- b3QuatConstArg ornB,
- b3Float4ConstArg DeltaC2,
- const b3Float4* verticesA,
- const b3Float4* uniqueEdgesA,
- const b3GpuFace* facesA,
- const int* indicesA,
- __global const b3Float4* verticesB,
- __global const b3Float4* uniqueEdgesB,
- __global const b3GpuFace* facesB,
- __global const int* indicesB,
- b3Float4* sep,
- float* dmin,
- bool searchAllEdgeEdge)
-{
- b3Float4 posA = posA1;
- posA.w = 0.f;
- b3Float4 posB = posB1;
- posB.w = 0.f;
-
- // int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test edges
- static int maxEdgeTests = 0;
- int curEdgeTests = hullA->m_numUniqueEdges * hullB->m_numUniqueEdges;
- if (curEdgeTests > maxEdgeTests)
- {
- maxEdgeTests = curEdgeTests;
- printf("maxEdgeTests = %d\n", maxEdgeTests);
- printf("hullA->m_numUniqueEdges = %d\n", hullA->m_numUniqueEdges);
- printf("hullB->m_numUniqueEdges = %d\n", hullB->m_numUniqueEdges);
- }
-
- if (searchAllEdgeEdge)
- {
- for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
- {
- const b3Float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset + e0];
- b3Float4 edge0World = b3QuatRotate(ornA, edge0);
-
- for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
- {
- const b3Float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset + e1];
- b3Float4 edge1World = b3QuatRotate(ornB, edge1);
-
- b3Float4 crossje = b3Cross(edge0World, edge1World);
-
- curEdgeEdge++;
- if (!b3IsAlmostZero(crossje))
- {
- crossje = b3Normalized(crossje);
- if (b3Dot(DeltaC2, crossje) < 0)
- crossje *= -1.f;
-
- float dist;
- bool result = true;
- {
- float Min0, Max0;
- float Min1, Max1;
- b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
- b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0 < d1 ? d0 : d1;
- result = true;
- }
-
- if (dist < *dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
- }
- }
- else
- {
- int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
- //printf("numDirections =%d\n",numDirections );
-
- for (int i = 0; i < numDirections; i++)
- {
- b3Float4 crossje = unitSphere162[i];
- {
- //if (b3Dot(DeltaC2,crossje)>0)
- {
- float dist;
- bool result = true;
- {
- float Min0, Max0;
- float Min1, Max1;
- b3Project(hullA, posA, ornA, &crossje, verticesA, &Min0, &Max0);
- b3Project(hullB, posB, ornB, &crossje, verticesB, &Min1, &Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0 < d1 ? d0 : d1;
- result = true;
- }
-
- if (dist < *dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
- }
- }
-
- if ((b3Dot(-DeltaC2, *sep)) > 0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-inline int b3FindClippingFaces(b3Float4ConstArg separatingNormal,
- __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- b3Float4ConstArg posA, b3QuatConstArg ornA, b3Float4ConstArg posB, b3QuatConstArg ornB,
- __global b3Float4* worldVertsA1,
- __global b3Float4* worldNormalsA1,
- __global b3Float4* worldVertsB1,
- int capacityWorldVerts,
- const float minDist, float maxDist,
- __global const b3Float4* verticesA,
- __global const b3GpuFace_t* facesA,
- __global const int* indicesA,
- __global const b3Float4* verticesB,
- __global const b3GpuFace_t* facesB,
- __global const int* indicesB,
-
- __global b3Int4* clippingFaces, int pairIndex)
-{
- int numContactsOut = 0;
- int numWorldVertsB1 = 0;
-
- int closestFaceB = -1;
- float dmax = -FLT_MAX;
-
- {
- for (int face = 0; face < hullB->m_numFaces; face++)
- {
- const b3Float4 Normal = b3MakeFloat4(facesB[hullB->m_faceOffset + face].m_plane.x,
- facesB[hullB->m_faceOffset + face].m_plane.y, facesB[hullB->m_faceOffset + face].m_plane.z, 0.f);
- const b3Float4 WorldNormal = b3QuatRotate(ornB, Normal);
- float d = b3Dot(WorldNormal, separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const b3GpuFace_t polyB = facesB[hullB->m_faceOffset + closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for (int e0 = 0; e0 < numVertices; e0++)
- {
- const b3Float4 b = verticesB[hullB->m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
- worldVertsB1[pairIndex * capacityWorldVerts + numWorldVertsB1++] = b3TransformPoint(b, posB, ornB);
- }
- }
-
- int closestFaceA = -1;
- {
- float dmin = FLT_MAX;
- for (int face = 0; face < hullA->m_numFaces; face++)
- {
- const b3Float4 Normal = b3MakeFloat4(
- facesA[hullA->m_faceOffset + face].m_plane.x,
- facesA[hullA->m_faceOffset + face].m_plane.y,
- facesA[hullA->m_faceOffset + face].m_plane.z,
- 0.f);
- const b3Float4 faceANormalWS = b3QuatRotate(ornA, Normal);
-
- float d = b3Dot(faceANormalWS, separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- worldNormalsA1[pairIndex] = faceANormalWS;
- }
- }
- }
-
- int numVerticesA = facesA[hullA->m_faceOffset + closestFaceA].m_numIndices;
- for (int e0 = 0; e0 < numVerticesA; e0++)
- {
- const b3Float4 a = verticesA[hullA->m_vertexOffset + indicesA[facesA[hullA->m_faceOffset + closestFaceA].m_indexOffset + e0]];
- worldVertsA1[pairIndex * capacityWorldVerts + e0] = b3TransformPoint(a, posA, ornA);
- }
-
- clippingFaces[pairIndex].x = closestFaceA;
- clippingFaces[pairIndex].y = closestFaceB;
- clippingFaces[pairIndex].z = numVerticesA;
- clippingFaces[pairIndex].w = numWorldVertsB1;
-
- return numContactsOut;
-}
-
-__kernel void b3FindConcaveSeparatingAxisKernel(__global b3Int4* concavePairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3Float4* vertices,
- __global const b3Float4* uniqueEdges,
- __global const b3GpuFace* faces,
- __global const int* indices,
- __global const b3GpuChildShape* gpuChildShapes,
- __global b3Aabb* aabbs,
- __global b3Float4* concaveSeparatingNormalsOut,
- __global b3Int4* clippingFacesOut,
- __global b3Vector3* worldVertsA1Out,
- __global b3Vector3* worldNormalsA1Out,
- __global b3Vector3* worldVertsB1Out,
- __global int* hasSeparatingNormals,
- int vertexFaceCapacity,
- int numConcavePairs,
- int pairIdx)
-{
- int i = pairIdx;
- /* int i = get_global_id(0);
- if (i>=numConcavePairs)
- return;
- int pairIdx = i;
- */
-
- int bodyIndexA = concavePairs[i].x;
- int bodyIndexB = concavePairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- if (collidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL &&
- collidables[collidableIndexB].m_shapeType != SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- concavePairs[pairIdx].w = -1;
- return;
- }
-
- hasSeparatingNormals[i] = 0;
-
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- int numActualConcaveConvexTests = 0;
-
- int f = concavePairs[i].z;
-
- bool overlap = false;
-
- b3ConvexPolyhedronData convexPolyhedronA;
-
- //add 3 vertices of the triangle
- convexPolyhedronA.m_numVertices = 3;
- convexPolyhedronA.m_vertexOffset = 0;
- b3Float4 localCenter = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
-
- b3GpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset + f];
- b3Aabb triAabb;
- triAabb.m_minVec = b3MakeFloat4(1e30f, 1e30f, 1e30f, 0.f);
- triAabb.m_maxVec = b3MakeFloat4(-1e30f, -1e30f, -1e30f, 0.f);
-
- b3Float4 verticesA[3];
- for (int i = 0; i < 3; i++)
- {
- int index = indices[face.m_indexOffset + i];
- b3Float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset + index];
- verticesA[i] = vert;
- localCenter += vert;
-
- triAabb.m_minVec = b3MinFloat4(triAabb.m_minVec, vert);
- triAabb.m_maxVec = b3MaxFloat4(triAabb.m_maxVec, vert);
- }
-
- overlap = true;
- overlap = (triAabb.m_minVec.x > aabbs[bodyIndexB].m_maxVec.x || triAabb.m_maxVec.x < aabbs[bodyIndexB].m_minVec.x) ? false : overlap;
- overlap = (triAabb.m_minVec.z > aabbs[bodyIndexB].m_maxVec.z || triAabb.m_maxVec.z < aabbs[bodyIndexB].m_minVec.z) ? false : overlap;
- overlap = (triAabb.m_minVec.y > aabbs[bodyIndexB].m_maxVec.y || triAabb.m_maxVec.y < aabbs[bodyIndexB].m_minVec.y) ? false : overlap;
-
- if (overlap)
- {
- float dmin = FLT_MAX;
- int hasSeparatingAxis = 5;
- b3Float4 sepAxis = b3MakeFloat4(1, 2, 3, 4);
-
- // int localCC=0;
- numActualConcaveConvexTests++;
-
- //a triangle has 3 unique edges
- convexPolyhedronA.m_numUniqueEdges = 3;
- convexPolyhedronA.m_uniqueEdgesOffset = 0;
- b3Float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1] - verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2] - verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0] - verticesA[2]);
-
- convexPolyhedronA.m_faceOffset = 0;
-
- b3Float4 normal = b3MakeFloat4(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
-
- b3GpuFace facesA[B3_TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3 + 3 + 2 + 2 + 2];
- int curUsedIndices = 0;
- int fidx = 0;
-
- //front size of triangle
- {
- facesA[fidx].m_indexOffset = curUsedIndices;
- indicesA[0] = 0;
- indicesA[1] = 1;
- indicesA[2] = 2;
- curUsedIndices += 3;
- float c = face.m_plane.w;
- facesA[fidx].m_plane.x = normal.x;
- facesA[fidx].m_plane.y = normal.y;
- facesA[fidx].m_plane.z = normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices = 3;
- }
- fidx++;
- //back size of triangle
- {
- facesA[fidx].m_indexOffset = curUsedIndices;
- indicesA[3] = 2;
- indicesA[4] = 1;
- indicesA[5] = 0;
- curUsedIndices += 3;
- float c = b3Dot(normal, verticesA[0]);
- // float c1 = -face.m_plane.w;
- facesA[fidx].m_plane.x = -normal.x;
- facesA[fidx].m_plane.y = -normal.y;
- facesA[fidx].m_plane.z = -normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices = 3;
- }
- fidx++;
-
- bool addEdgePlanes = true;
- if (addEdgePlanes)
- {
- int numVertices = 3;
- int prevVertex = numVertices - 1;
- for (int i = 0; i < numVertices; i++)
- {
- b3Float4 v0 = verticesA[i];
- b3Float4 v1 = verticesA[prevVertex];
-
- b3Float4 edgeNormal = b3Normalized(b3Cross(normal, v1 - v0));
- float c = -b3Dot(edgeNormal, v0);
-
- facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset = curUsedIndices;
- indicesA[curUsedIndices++] = i;
- indicesA[curUsedIndices++] = prevVertex;
-
- facesA[fidx].m_plane.x = edgeNormal.x;
- facesA[fidx].m_plane.y = edgeNormal.y;
- facesA[fidx].m_plane.z = edgeNormal.z;
- facesA[fidx].m_plane.w = c;
- fidx++;
- prevVertex = i;
- }
- }
- convexPolyhedronA.m_numFaces = B3_TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter * (1.f / 3.f);
-
- b3Float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- b3Float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
-
- b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
- b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
-
- ///////////////////
- ///compound shape support
-
- if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int compoundChild = concavePairs[pairIdx].w;
- int childShapeIndexB = compoundChild; //collidables[collidableIndexB].m_shapeIndex+compoundChild;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- b3Float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quaternion childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- b3Float4 newPosB = b3TransformPoint(childPosB, posB, ornB);
- b3Quaternion newOrnB = b3QuatMul(ornB, childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- }
- //////////////////
-
- b3Float4 c0local = convexPolyhedronA.m_localCenter;
- b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
- b3Float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
- const b3Float4 DeltaC2 = c0 - c1;
-
- bool sepA = b3FindSeparatingAxis(&convexPolyhedronA, &convexShapes[shapeIndexB],
- posA, ornA,
- posB, ornB,
- DeltaC2,
- verticesA, uniqueEdgesA, facesA, indicesA,
- vertices, uniqueEdges, faces, indices,
- &sepAxis, &dmin);
- hasSeparatingAxis = 4;
- if (!sepA)
- {
- hasSeparatingAxis = 0;
- }
- else
- {
- bool sepB = b3FindSeparatingAxis(&convexShapes[shapeIndexB], &convexPolyhedronA,
- posB, ornB,
- posA, ornA,
- DeltaC2,
- vertices, uniqueEdges, faces, indices,
- verticesA, uniqueEdgesA, facesA, indicesA,
- &sepAxis, &dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis = 0;
- }
- else
- {
- bool sepEE = b3FindSeparatingAxisEdgeEdge(&convexPolyhedronA, &convexShapes[shapeIndexB],
- posA, ornA,
- posB, ornB,
- DeltaC2,
- verticesA, uniqueEdgesA, facesA, indicesA,
- vertices, uniqueEdges, faces, indices,
- &sepAxis, &dmin, true);
-
- if (!sepEE)
- {
- hasSeparatingAxis = 0;
- }
- else
- {
- hasSeparatingAxis = 1;
- }
- }
- }
-
- if (hasSeparatingAxis)
- {
- hasSeparatingNormals[i] = 1;
- sepAxis.w = dmin;
- concaveSeparatingNormalsOut[pairIdx] = sepAxis;
-
- //now compute clipping faces A and B, and world-space clipping vertices A and B...
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- b3FindClippingFaces(sepAxis,
- &convexPolyhedronA,
- &convexShapes[shapeIndexB],
- posA, ornA,
- posB, ornB,
- worldVertsA1Out,
- worldNormalsA1Out,
- worldVertsB1Out,
- vertexFaceCapacity,
- minDist, maxDist,
- verticesA,
- facesA,
- indicesA,
-
- vertices,
- faces,
- indices,
- clippingFacesOut, pairIdx);
- }
- else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
- }
- else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
-}
-
-#endif //B3_FIND_CONCAVE_SEPARATING_AXIS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
deleted file mode 100644
index b4981ae654..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3FindSeparatingAxis.h
+++ /dev/null
@@ -1,197 +0,0 @@
-#ifndef B3_FIND_SEPARATING_AXIS_H
-#define B3_FIND_SEPARATING_AXIS_H
-
-inline void b3ProjectAxis(const b3ConvexPolyhedronData& hull, const b3Float4& pos, const b3Quaternion& orn, const b3Float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
-{
- min = FLT_MAX;
- max = -FLT_MAX;
- int numVerts = hull.m_numVertices;
-
- const b3Float4 localDir = b3QuatRotate(orn.inverse(), dir);
-
- b3Scalar offset = b3Dot3F4(pos, dir);
-
- for (int i = 0; i < numVerts; i++)
- {
- //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
- //b3Scalar dp = pt.dot(dir);
- //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
- b3Scalar dp = b3Dot3F4((b3Float4&)vertices[hull.m_vertexOffset + i], localDir);
- //b3Assert(dp==dpL);
- if (dp < min) min = dp;
- if (dp > max) max = dp;
- }
- if (min > max)
- {
- b3Scalar tmp = min;
- min = max;
- max = tmp;
- }
- min += offset;
- max += offset;
-}
-
-inline bool b3TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA, const b3Quaternion& ornA,
- const b3Float4& posB, const b3Quaternion& ornB,
- const b3Float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
-{
- b3Scalar Min0, Max0;
- b3Scalar Min1, Max1;
- b3ProjectAxis(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
- b3ProjectAxis(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- b3Scalar d0 = Max0 - Min1;
- b3Assert(d0 >= 0.0f);
- b3Scalar d1 = Max1 - Min0;
- b3Assert(d1 >= 0.0f);
- depth = d0 < d1 ? d0 : d1;
- return true;
-}
-
-inline bool b3FindSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const b3Float4& posA1,
- const b3Quaternion& ornA,
- const b3Float4& posB1,
- const b3Quaternion& ornB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- b3Vector3& sep)
-{
- B3_PROFILE("findSeparatingAxis");
-
- b3Float4 posA = posA1;
- posA.w = 0.f;
- b3Float4 posB = posB1;
- posB.w = 0.f;
- //#ifdef TEST_INTERNAL_OBJECTS
- b3Float4 c0local = (b3Float4&)hullA.m_localCenter;
-
- b3Float4 c0 = b3TransformPoint(c0local, posA, ornA);
- b3Float4 c1local = (b3Float4&)hullB.m_localCenter;
- b3Float4 c1 = b3TransformPoint(c1local, posB, ornB);
- const b3Float4 deltaC2 = c0 - c1;
- //#endif
-
- b3Scalar dmin = FLT_MAX;
- int curPlaneTests = 0;
-
- int numFacesA = hullA.m_numFaces;
- // Test normals from hullA
- for (int i = 0; i < numFacesA; i++)
- {
- const b3Float4& normal = (b3Float4&)facesA[hullA.m_faceOffset + i].m_plane;
- b3Float4 faceANormalWS = b3QuatRotate(ornA, normal);
-
- if (b3Dot3F4(deltaC2, faceANormalWS) < 0)
- faceANormalWS *= -1.f;
-
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar d;
- if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = (b3Vector3&)faceANormalWS;
- }
- }
-
- int numFacesB = hullB.m_numFaces;
- // Test normals from hullB
- for (int i = 0; i < numFacesB; i++)
- {
- b3Float4 normal = (b3Float4&)facesB[hullB.m_faceOffset + i].m_plane;
- b3Float4 WorldNormal = b3QuatRotate(ornB, normal);
-
- if (b3Dot3F4(deltaC2, WorldNormal) < 0)
- {
- WorldNormal *= -1.f;
- }
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar d;
- if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = (b3Vector3&)WorldNormal;
- }
- }
-
- // b3Vector3 edgeAstart,edgeAend,edgeBstart,edgeBend;
-
- int curEdgeEdge = 0;
- // Test edges
- for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
- {
- const b3Float4& edge0 = (b3Float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
- b3Float4 edge0World = b3QuatRotate(ornA, (b3Float4&)edge0);
-
- for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
- {
- const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
- b3Float4 edge1World = b3QuatRotate(ornB, (b3Float4&)edge1);
-
- b3Float4 crossje = b3Cross3(edge0World, edge1World);
-
- curEdgeEdge++;
- if (!b3IsAlmostZero((b3Vector3&)crossje))
- {
- crossje = b3FastNormalized3(crossje);
- if (b3Dot3F4(deltaC2, crossje) < 0)
- crossje *= -1.f;
-
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar dist;
- if (!b3TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
- return false;
-
- if (dist < dmin)
- {
- dmin = dist;
- sep = (b3Vector3&)crossje;
- }
- }
- }
- }
-
- if ((b3Dot3F4(-deltaC2, (b3Float4&)sep)) > 0.0f)
- sep = -sep;
-
- return true;
-}
-
-#endif //B3_FIND_SEPARATING_AXIS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
deleted file mode 100644
index a3bfbf2995..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h
+++ /dev/null
@@ -1,888 +0,0 @@
-
-/***
- * ---------------------------------
- * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
- *
- * This file was ported from mpr.c file, part of libccd.
- * The Minkoski Portal Refinement implementation was ported
- * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
- * at http://github.com/erwincoumans/bullet3
- *
- * Distributed under the OSI-approved BSD License (the "License");
- * see <http://www.opensource.org/licenses/bsd-license.php>.
- * This software is distributed WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the License for more information.
- */
-
-#ifndef B3_MPR_PENETRATION_H
-#define B3_MPR_PENETRATION_H
-
-#include "Bullet3Common/shared/b3PlatformDefinitions.h"
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-
-#ifdef __cplusplus
-#define B3_MPR_SQRT sqrtf
-#else
-#define B3_MPR_SQRT sqrt
-#endif
-#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
-#define B3_MPR_FABS fabs
-
-#define B3_MPR_TOLERANCE 1E-6f
-#define B3_MPR_MAX_ITERATIONS 1000
-
-struct _b3MprSupport_t
-{
- b3Float4 v; //!< Support point in minkowski sum
- b3Float4 v1; //!< Support point in obj1
- b3Float4 v2; //!< Support point in obj2
-};
-typedef struct _b3MprSupport_t b3MprSupport_t;
-
-struct _b3MprSimplex_t
-{
- b3MprSupport_t ps[4];
- int last; //!< index of last added point
-};
-typedef struct _b3MprSimplex_t b3MprSimplex_t;
-
-inline b3MprSupport_t *b3MprSimplexPointW(b3MprSimplex_t *s, int idx)
-{
- return &s->ps[idx];
-}
-
-inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)
-{
- s->last = size - 1;
-}
-
-inline int b3MprSimplexSize(const b3MprSimplex_t *s)
-{
- return s->last + 1;
-}
-
-inline const b3MprSupport_t *b3MprSimplexPoint(const b3MprSimplex_t *s, int idx)
-{
- // here is no check on boundaries
- return &s->ps[idx];
-}
-
-inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)
-{
- *d = *s;
-}
-
-inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)
-{
- b3MprSupportCopy(s->ps + pos, a);
-}
-
-inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)
-{
- b3MprSupport_t supp;
-
- b3MprSupportCopy(&supp, &s->ps[pos1]);
- b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
- b3MprSupportCopy(&s->ps[pos2], &supp);
-}
-
-inline int b3MprIsZero(float val)
-{
- return B3_MPR_FABS(val) < FLT_EPSILON;
-}
-
-inline int b3MprEq(float _a, float _b)
-{
- float ab;
- float a, b;
-
- ab = B3_MPR_FABS(_a - _b);
- if (B3_MPR_FABS(ab) < FLT_EPSILON)
- return 1;
-
- a = B3_MPR_FABS(_a);
- b = B3_MPR_FABS(_b);
- if (b > a)
- {
- return ab < FLT_EPSILON * b;
- }
- else
- {
- return ab < FLT_EPSILON * a;
- }
-}
-
-inline int b3MprVec3Eq(const b3Float4 *a, const b3Float4 *b)
-{
- return b3MprEq((*a).x, (*b).x) && b3MprEq((*a).y, (*b).y) && b3MprEq((*a).z, (*b).z);
-}
-
-inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec, __global const b3ConvexPolyhedronData_t *hull, b3ConstArray(b3Float4) verticesA)
-{
- b3Float4 supVec = b3MakeFloat4(0, 0, 0, 0);
- float maxDot = -B3_LARGE_FLOAT;
-
- if (0 < hull->m_numVertices)
- {
- const b3Float4 scaled = supportVec;
- int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
- return verticesA[hull->m_vertexOffset + index];
- }
-
- return supVec;
-}
-
-B3_STATIC void b3MprConvexSupport(int pairIndex, int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- const b3Float4 *_dir, b3Float4 *outp, int logme)
-{
- //dir is in worldspace, move to local space
-
- b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;
- b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;
-
- b3Float4 dir = b3MakeFloat4((*_dir).x, (*_dir).y, (*_dir).z, 0.f);
-
- const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn), dir);
-
- //find local support vertex
- int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;
-
- b3Assert(cpuCollidables[colIndex].m_shapeType == SHAPE_CONVEX_HULL);
- __global const b3ConvexPolyhedronData_t *hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];
-
- b3Float4 pInA;
- if (logme)
- {
- // b3Float4 supVec = b3MakeFloat4(0,0,0,0);
- float maxDot = -B3_LARGE_FLOAT;
-
- if (0 < hull->m_numVertices)
- {
- const b3Float4 scaled = localDir;
- int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);
- pInA = cpuVertices[hull->m_vertexOffset + index];
- }
- }
- else
- {
- pInA = b3LocalGetSupportVertex(localDir, hull, cpuVertices);
- }
-
- //move vertex to world space
- *outp = b3TransformPoint(pInA, pos, orn);
-}
-
-inline void b3MprSupport(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- const b3Float4 *_dir, b3MprSupport_t *supp)
-{
- b3Float4 dir;
- dir = *_dir;
- b3MprConvexSupport(pairIndex, bodyIndexA, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v1, 0);
- dir = *_dir * -1.f;
- b3MprConvexSupport(pairIndex, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &supp->v2, 0);
- supp->v = supp->v1 - supp->v2;
-}
-
-inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)
-{
- center->v1 = cpuBodyBuf[bodyIndexA].m_pos;
- center->v2 = cpuBodyBuf[bodyIndexB].m_pos;
- center->v = center->v1 - center->v2;
-}
-
-inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)
-{
- (*v).x = x;
- (*v).y = y;
- (*v).z = z;
- (*v).w = 0.f;
-}
-
-inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)
-{
- (*v).x += (*w).x;
- (*v).y += (*w).y;
- (*v).z += (*w).z;
-}
-
-inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)
-{
- *v = *w;
-}
-
-inline void b3MprVec3Scale(b3Float4 *d, float k)
-{
- *d *= k;
-}
-
-inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)
-{
- float dot;
-
- dot = b3Dot3F4(*a, *b);
- return dot;
-}
-
-inline float b3MprVec3Len2(const b3Float4 *v)
-{
- return b3MprVec3Dot(v, v);
-}
-
-inline void b3MprVec3Normalize(b3Float4 *d)
-{
- float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));
- b3MprVec3Scale(d, k);
-}
-
-inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)
-{
- *d = b3Cross3(*a, *b);
-}
-
-inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)
-{
- *d = *v - *w;
-}
-
-inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)
-{
- b3Float4 v2v1, v3v1;
-
- b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b3MprVec3Cross(dir, &v2v1, &v3v1);
- b3MprVec3Normalize(dir);
-}
-
-inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,
- const b3Float4 *dir)
-{
- float dot;
- dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);
- return b3MprIsZero(dot) || dot > 0.f;
-}
-
-inline int portalReachTolerance(const b3MprSimplex_t *portal,
- const b3MprSupport_t *v4,
- const b3Float4 *dir)
-{
- float dv1, dv2, dv3, dv4;
- float dot1, dot2, dot3;
-
- // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
-
- dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);
- dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);
- dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);
- dv4 = b3MprVec3Dot(&v4->v, dir);
-
- dot1 = dv4 - dv1;
- dot2 = dv4 - dv2;
- dot3 = dv4 - dv3;
-
- dot1 = B3_MPR_FMIN(dot1, dot2);
- dot1 = B3_MPR_FMIN(dot1, dot3);
-
- return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;
-}
-
-inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal,
- const b3MprSupport_t *v4,
- const b3Float4 *dir)
-{
- float dot;
- dot = b3MprVec3Dot(&v4->v, dir);
- return b3MprIsZero(dot) || dot > 0.f;
-}
-
-inline void b3ExpandPortal(b3MprSimplex_t *portal,
- const b3MprSupport_t *v4)
-{
- float dot;
- b3Float4 v4v0;
-
- b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);
- if (dot > 0.f)
- {
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);
- if (dot > 0.f)
- {
- b3MprSimplexSet(portal, 1, v4);
- }
- else
- {
- b3MprSimplexSet(portal, 3, v4);
- }
- }
- else
- {
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);
- if (dot > 0.f)
- {
- b3MprSimplexSet(portal, 2, v4);
- }
- else
- {
- b3MprSimplexSet(portal, 1, v4);
- }
- }
-}
-
-B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- __global int *hasSepAxis,
- b3MprSimplex_t *portal)
-{
- b3Float4 dir, va, vb;
- float dot;
- int cont;
-
- // vertex 0 is center of portal
- b3FindOrigin(bodyIndexA, bodyIndexB, cpuBodyBuf, b3MprSimplexPointW(portal, 0));
- // vertex 0 is center of portal
- b3MprSimplexSetSize(portal, 1);
-
- b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
- b3Float4 *b3mpr_vec3_origin = &zero;
-
- if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin))
- {
- // Portal's center lies on origin (0,0,0) => we know that objects
- // intersect but we would need to know penetration info.
- // So move center little bit...
- b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
- b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);
- }
-
- // vertex 1 = support in direction of origin
- b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Scale(&dir, -1.f);
- b3MprVec3Normalize(&dir);
-
- b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 1));
-
- b3MprSimplexSetSize(portal, 2);
-
- // test if origin isn't outside of v1
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);
-
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
- // vertex 2
- b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- if (b3MprIsZero(b3MprVec3Len2(&dir)))
- {
- if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin))
- {
- // origin lies on v1
- return 1;
- }
- else
- {
- // origin lies on v0-v1 segment
- return 2;
- }
- }
-
- b3MprVec3Normalize(&dir);
- b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 2));
-
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
- b3MprSimplexSetSize(portal, 3);
-
- // vertex 3 direction
- b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Cross(&dir, &va, &vb);
- b3MprVec3Normalize(&dir);
-
- // it is better to form portal faces to be oriented "outside" origin
- dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);
- if (dot > 0.f)
- {
- b3MprSimplexSwap(portal, 1, 2);
- b3MprVec3Scale(&dir, -1.f);
- }
-
- while (b3MprSimplexSize(portal) < 4)
- {
- b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, b3MprSimplexPointW(portal, 3));
-
- dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);
- if (b3MprIsZero(dot) || dot < 0.f)
- return -1;
-
- cont = 0;
-
- // test if origin is outside (v1, v0, v3) - set v2 as v3 and
- // continue
- b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 3)->v);
- dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !b3MprIsZero(dot))
- {
- b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));
- cont = 1;
- }
-
- if (!cont)
- {
- // test if origin is outside (v3, v0, v2) - set v1 as v3 and
- // continue
- b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !b3MprIsZero(dot))
- {
- b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));
- cont = 1;
- }
- }
-
- if (cont)
- {
- b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 0)->v);
- b3MprVec3Cross(&dir, &va, &vb);
- b3MprVec3Normalize(&dir);
- }
- else
- {
- b3MprSimplexSetSize(portal, 4);
- }
- }
-
- return 0;
-}
-
-B3_STATIC int b3RefinePortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- b3MprSimplex_t *portal)
-{
- b3Float4 dir;
- b3MprSupport_t v4;
-
- for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
- //while (1)
- {
- // compute direction outside the portal (from v0 throught v1,v2,v3
- // face)
- b3PortalDir(portal, &dir);
-
- // test if origin is inside the portal
- if (portalEncapsulesOrigin(portal, &dir))
- return 0;
-
- // get next support point
-
- b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
-
- // test if v4 can expand portal to contain origin and if portal
- // expanding doesn't reach given tolerance
- if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir))
- {
- return -1;
- }
-
- // v1-v2-v3 triangle must be rearranged to face outside Minkowski
- // difference (direction from v0).
- b3ExpandPortal(portal, &v4);
- }
-
- return -1;
-}
-
-B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)
-{
- b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
- b3Float4 *b3mpr_vec3_origin = &zero;
-
- b3Float4 dir;
- size_t i;
- float b[4], sum, inv;
- b3Float4 vec, p1, p2;
-
- b3PortalDir(portal, &dir);
-
- // use barycentric coordinates of tetrahedron to find origin
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
-
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
-
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);
-
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);
-
- sum = b[0] + b[1] + b[2] + b[3];
-
- if (b3MprIsZero(sum) || sum < 0.f)
- {
- b[0] = 0.f;
-
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,
- &b3MprSimplexPoint(portal, 3)->v);
- b[1] = b3MprVec3Dot(&vec, &dir);
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,
- &b3MprSimplexPoint(portal, 1)->v);
- b[2] = b3MprVec3Dot(&vec, &dir);
- b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,
- &b3MprSimplexPoint(portal, 2)->v);
- b[3] = b3MprVec3Dot(&vec, &dir);
-
- sum = b[1] + b[2] + b[3];
- }
-
- inv = 1.f / sum;
-
- b3MprVec3Copy(&p1, b3mpr_vec3_origin);
- b3MprVec3Copy(&p2, b3mpr_vec3_origin);
- for (i = 0; i < 4; i++)
- {
- b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);
- b3MprVec3Scale(&vec, b[i]);
- b3MprVec3Add(&p1, &vec);
-
- b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);
- b3MprVec3Scale(&vec, b[i]);
- b3MprVec3Add(&p2, &vec);
- }
- b3MprVec3Scale(&p1, inv);
- b3MprVec3Scale(&p2, inv);
-
- b3MprVec3Copy(pos, &p1);
- b3MprVec3Add(pos, &p2);
- b3MprVec3Scale(pos, 0.5);
-}
-
-inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)
-{
- b3Float4 ab;
- b3MprVec3Sub2(&ab, a, b);
- return b3MprVec3Len2(&ab);
-}
-
-inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,
- const b3Float4 *x0,
- const b3Float4 *b,
- b3Float4 *witness)
-{
- // The computation comes from solving equation of segment:
- // S(t) = x0 + t.d
- // where - x0 is initial point of segment
- // - d is direction of segment from x0 (|d| > 0)
- // - t belongs to <0, 1> interval
- //
- // Than, distance from a segment to some point P can be expressed:
- // D(t) = |x0 + t.d - P|^2
- // which is distance from any point on segment. Minimization
- // of this function brings distance from P to segment.
- // Minimization of D(t) leads to simple quadratic equation that's
- // solving is straightforward.
- //
- // Bonus of this method is witness point for free.
-
- float dist, t;
- b3Float4 d, a;
-
- // direction of segment
- b3MprVec3Sub2(&d, b, x0);
-
- // precompute vector from P to x0
- b3MprVec3Sub2(&a, x0, P);
-
- t = -1.f * b3MprVec3Dot(&a, &d);
- t /= b3MprVec3Len2(&d);
-
- if (t < 0.f || b3MprIsZero(t))
- {
- dist = b3MprVec3Dist2(x0, P);
- if (witness)
- b3MprVec3Copy(witness, x0);
- }
- else if (t > 1.f || b3MprEq(t, 1.f))
- {
- dist = b3MprVec3Dist2(b, P);
- if (witness)
- b3MprVec3Copy(witness, b);
- }
- else
- {
- if (witness)
- {
- b3MprVec3Copy(witness, &d);
- b3MprVec3Scale(witness, t);
- b3MprVec3Add(witness, x0);
- dist = b3MprVec3Dist2(witness, P);
- }
- else
- {
- // recycling variables
- b3MprVec3Scale(&d, t);
- b3MprVec3Add(&d, &a);
- dist = b3MprVec3Len2(&d);
- }
- }
-
- return dist;
-}
-
-inline float b3MprVec3PointTriDist2(const b3Float4 *P,
- const b3Float4 *x0, const b3Float4 *B,
- const b3Float4 *C,
- b3Float4 *witness)
-{
- // Computation comes from analytic expression for triangle (x0, B, C)
- // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
- // Then equation for distance is:
- // D(s, t) = | T(s, t) - P |^2
- // This leads to minimization of quadratic function of two variables.
- // The solution from is taken only if s is between 0 and 1, t is
- // between 0 and 1 and t + s < 1, otherwise distance from segment is
- // computed.
-
- b3Float4 d1, d2, a;
- float u, v, w, p, q, r;
- float s, t, dist, dist2;
- b3Float4 witness2;
-
- b3MprVec3Sub2(&d1, B, x0);
- b3MprVec3Sub2(&d2, C, x0);
- b3MprVec3Sub2(&a, x0, P);
-
- u = b3MprVec3Dot(&a, &a);
- v = b3MprVec3Dot(&d1, &d1);
- w = b3MprVec3Dot(&d2, &d2);
- p = b3MprVec3Dot(&a, &d1);
- q = b3MprVec3Dot(&a, &d2);
- r = b3MprVec3Dot(&d1, &d2);
-
- s = (q * r - w * p) / (w * v - r * r);
- t = (-s * r - q) / w;
-
- if ((b3MprIsZero(s) || s > 0.f) && (b3MprEq(s, 1.f) || s < 1.f) && (b3MprIsZero(t) || t > 0.f) && (b3MprEq(t, 1.f) || t < 1.f) && (b3MprEq(t + s, 1.f) || t + s < 1.f))
- {
- if (witness)
- {
- b3MprVec3Scale(&d1, s);
- b3MprVec3Scale(&d2, t);
- b3MprVec3Copy(witness, x0);
- b3MprVec3Add(witness, &d1);
- b3MprVec3Add(witness, &d2);
-
- dist = b3MprVec3Dist2(witness, P);
- }
- else
- {
- dist = s * s * v;
- dist += t * t * w;
- dist += 2.f * s * t * r;
- dist += 2.f * s * p;
- dist += 2.f * t * q;
- dist += u;
- }
- }
- else
- {
- dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);
-
- dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- b3MprVec3Copy(witness, &witness2);
- }
-
- dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- b3MprVec3Copy(witness, &witness2);
- }
- }
-
- return dist;
-}
-
-B3_STATIC void b3FindPenetr(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- b3MprSimplex_t *portal,
- float *depth, b3Float4 *pdir, b3Float4 *pos)
-{
- b3Float4 dir;
- b3MprSupport_t v4;
- unsigned long iterations;
-
- b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
- b3Float4 *b3mpr_vec3_origin = &zero;
-
- iterations = 1UL;
- for (int i = 0; i < B3_MPR_MAX_ITERATIONS; i++)
- //while (1)
- {
- // compute portal direction and obtain next support point
- b3PortalDir(portal, &dir);
-
- b3MprSupport(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &dir, &v4);
-
- // reached tolerance -> find penetration info
- if (portalReachTolerance(portal, &v4, &dir) || iterations == B3_MPR_MAX_ITERATIONS)
- {
- *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin, &b3MprSimplexPoint(portal, 1)->v, &b3MprSimplexPoint(portal, 2)->v, &b3MprSimplexPoint(portal, 3)->v, pdir);
- *depth = B3_MPR_SQRT(*depth);
-
- if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))
- {
- *pdir = dir;
- }
- b3MprVec3Normalize(pdir);
-
- // barycentric coordinates:
- b3FindPos(portal, pos);
-
- return;
- }
-
- b3ExpandPortal(portal, &v4);
-
- iterations++;
- }
-}
-
-B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal, float *depth, b3Float4 *dir, b3Float4 *pos)
-{
- // Touching contact on portal's v1 - so depth is zero and direction
- // is unimportant and pos can be guessed
- *depth = 0.f;
- b3Float4 zero = b3MakeFloat4(0, 0, 0, 0);
- b3Float4 *b3mpr_vec3_origin = &zero;
-
- b3MprVec3Copy(dir, b3mpr_vec3_origin);
-
- b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
- b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
- b3MprVec3Scale(pos, 0.5);
-}
-
-B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,
- float *depth, b3Float4 *dir, b3Float4 *pos)
-{
- // Origin lies on v0-v1 segment.
- // Depth is distance to v1, direction also and position must be
- // computed
-
- b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);
- b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);
- b3MprVec3Scale(pos, 0.5f);
-
- b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);
- *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));
- b3MprVec3Normalize(dir);
-}
-
-inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,
- b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,
- b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData,
- b3ConstArray(b3Collidable_t) cpuCollidables,
- b3ConstArray(b3Float4) cpuVertices,
- __global b3Float4 *sepAxis,
- __global int *hasSepAxis,
- float *depthOut, b3Float4 *dirOut, b3Float4 *posOut)
-{
- b3MprSimplex_t portal;
-
- // if (!hasSepAxis[pairIndex])
- // return -1;
-
- hasSepAxis[pairIndex] = 0;
- int res;
-
- // Phase 1: Portal discovery
- res = b3DiscoverPortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, hasSepAxis, &portal);
-
- //sepAxis[pairIndex] = *pdir;//or -dir?
-
- switch (res)
- {
- case 0:
- {
- // Phase 2: Portal refinement
-
- res = b3RefinePortal(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal);
- if (res < 0)
- return -1;
-
- // Phase 3. Penetration info
- b3FindPenetr(pairIndex, bodyIndexA, bodyIndexB, cpuBodyBuf, cpuConvexData, cpuCollidables, cpuVertices, sepAxis, &portal, depthOut, dirOut, posOut);
- hasSepAxis[pairIndex] = 1;
- sepAxis[pairIndex] = -*dirOut;
- break;
- }
- case 1:
- {
- // Touching contact on portal's v1.
- b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);
- break;
- }
- case 2:
- {
- b3FindPenetrSegment(&portal, depthOut, dirOut, posOut);
- break;
- }
- default:
- {
- hasSepAxis[pairIndex] = 0;
- //if (res < 0)
- //{
- // Origin isn't inside portal - no collision.
- return -1;
- //}
- }
- };
-
- return 0;
-};
-
-#endif //B3_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
deleted file mode 100644
index 6e991e14b0..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h
+++ /dev/null
@@ -1,175 +0,0 @@
-
-#ifndef B3_NEW_CONTACT_REDUCTION_H
-#define B3_NEW_CONTACT_REDUCTION_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
-
-int b3ExtractManifoldSequentialGlobal(__global const b3Float4* p, int nPoints, b3Float4ConstArg nearNormal, b3Int4* contactIdx)
-{
- if (nPoints == 0)
- return 0;
-
- if (nPoints <= 4)
- return nPoints;
-
- if (nPoints > 64)
- nPoints = 64;
-
- b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
- {
- for (int i = 0; i < nPoints; i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
- // sample 4 directions
-
- b3Float4 aVector = p[0] - center;
- b3Float4 u = b3Cross(nearNormal, aVector);
- b3Float4 v = b3Cross(nearNormal, u);
- u = b3Normalized(u);
- v = b3Normalized(v);
-
- //keep point with deepest penetration
- float minW = FLT_MAX;
-
- int minIndex = -1;
-
- b3Float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for (int ie = 0; ie < nPoints; ie++)
- {
- if (p[ie].w < minW)
- {
- minW = p[ie].w;
- minIndex = ie;
- }
- float f;
- b3Float4 r = p[ie] - center;
- f = b3Dot(u, r);
- if (f < maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = b3Dot(-u, r);
- if (f < maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
- f = b3Dot(v, r);
- if (f < maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = b3Dot(-v, r);
- if (f < maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-}
-
-__kernel void b3NewContactReductionKernel(__global b3Int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global struct b3Contact4Data* globalContactsOut,
- __global b3Int4* clippingFaces,
- __global b3Float4* worldVertsB2,
- volatile __global int* nGlobalContactsOut,
- int vertexFaceCapacity,
- int contactCapacity,
- int numPairs,
- int pairIndex)
-{
- // int i = get_global_id(0);
- //int pairIndex = i;
- int i = pairIndex;
-
- b3Int4 contactIdx;
- contactIdx = b3MakeInt4(0, 1, 2, 3);
-
- if (i < numPairs)
- {
- if (hasSeparatingAxis[i])
- {
- int nPoints = clippingFaces[pairIndex].w;
-
- if (nPoints > 0)
- {
- __global b3Float4* pointsIn = &worldVertsB2[pairIndex * vertexFaceCapacity];
- b3Float4 normal = -separatingNormals[i];
-
- int nReducedContacts = b3ExtractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
-
- int dstIdx;
- dstIdx = b3AtomicInc(nGlobalContactsOut);
-
- //#if 0
- b3Assert(dstIdx < contactCapacity);
- if (dstIdx < contactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f * 0xffff);
- c->m_frictionCoeffCmp = (0.7f * 0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
-
- pairs[pairIndex].w = dstIdx;
-
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
-
- switch (nReducedContacts)
- {
- case 4:
- c->m_worldPosB[3] = pointsIn[contactIdx.w];
- case 3:
- c->m_worldPosB[2] = pointsIn[contactIdx.z];
- case 2:
- c->m_worldPosB[1] = pointsIn[contactIdx.y];
- case 1:
- c->m_worldPosB[0] = pointsIn[contactIdx.x];
- default:
- {
- }
- };
-
- GET_NPOINTS(*c) = nReducedContacts;
- }
-
- //#endif
-
- } // if (numContactsOut>0)
- } // if (hasSeparatingAxis[i])
- } // if (i<numPairs)
-}
-#endif
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
deleted file mode 100644
index ba796eac72..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-#ifndef B3_QUANTIZED_BVH_NODE_H
-#define B3_QUANTIZED_BVH_NODE_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-
-#define B3_MAX_NUM_PARTS_IN_BITS 10
-
-///b3QuantizedBvhNodeData is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-typedef struct b3QuantizedBvhNodeData b3QuantizedBvhNodeData_t;
-
-struct b3QuantizedBvhNodeData
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrTriangleIndex;
-};
-
-inline int b3GetTriangleIndex(const b3QuantizedBvhNodeData* rootNode)
-{
- unsigned int x = 0;
- unsigned int y = (~(x & 0)) << (31 - B3_MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex & ~(y));
-}
-
-inline int b3IsLeaf(const b3QuantizedBvhNodeData* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0) ? 1 : 0;
-}
-
-inline int b3GetEscapeIndex(const b3QuantizedBvhNodeData* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-inline void b3QuantizeWithClamp(unsigned short* out, b3Float4ConstArg point2, int isMax, b3Float4ConstArg bvhAabbMin, b3Float4ConstArg bvhAabbMax, b3Float4ConstArg bvhQuantization)
-{
- b3Float4 clampedPoint = b3MaxFloat4(point2, bvhAabbMin);
- clampedPoint = b3MinFloat4(clampedPoint, bvhAabbMax);
-
- b3Float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
- if (isMax)
- {
- out[0] = (unsigned short)(((unsigned short)(v.x + 1.f) | 1));
- out[1] = (unsigned short)(((unsigned short)(v.y + 1.f) | 1));
- out[2] = (unsigned short)(((unsigned short)(v.z + 1.f) | 1));
- }
- else
- {
- out[0] = (unsigned short)(((unsigned short)(v.x) & 0xfffe));
- out[1] = (unsigned short)(((unsigned short)(v.y) & 0xfffe));
- out[2] = (unsigned short)(((unsigned short)(v.z) & 0xfffe));
- }
-}
-
-inline int b3TestQuantizedAabbAgainstQuantizedAabbSlow(
- const unsigned short int* aabbMin1,
- const unsigned short int* aabbMax1,
- const unsigned short int* aabbMin2,
- const unsigned short int* aabbMax2)
-{
- //int overlap = 1;
- if (aabbMin1[0] > aabbMax2[0])
- return 0;
- if (aabbMax1[0] < aabbMin2[0])
- return 0;
- if (aabbMin1[1] > aabbMax2[1])
- return 0;
- if (aabbMax1[1] < aabbMin2[1])
- return 0;
- if (aabbMin1[2] > aabbMax2[2])
- return 0;
- if (aabbMax1[2] < aabbMin2[2])
- return 0;
- return 1;
- //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
- //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
- //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
- //return overlap;
-}
-
-#endif //B3_QUANTIZED_BVH_NODE_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
deleted file mode 100644
index c108255b9f..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3ReduceContacts.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef B3_REDUCE_CONTACTS_H
-#define B3_REDUCE_CONTACTS_H
-
-inline int b3ReduceContacts(const b3Float4* p, int nPoints, const b3Float4& nearNormal, b3Int4* contactIdx)
-{
- if (nPoints == 0)
- return 0;
-
- if (nPoints <= 4)
- return nPoints;
-
- if (nPoints > 64)
- nPoints = 64;
-
- b3Float4 center = b3MakeFloat4(0, 0, 0, 0);
- {
- for (int i = 0; i < nPoints; i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
- // sample 4 directions
-
- b3Float4 aVector = p[0] - center;
- b3Float4 u = b3Cross3(nearNormal, aVector);
- b3Float4 v = b3Cross3(nearNormal, u);
- u = b3FastNormalized3(u);
- v = b3FastNormalized3(v);
-
- //keep point with deepest penetration
- float minW = FLT_MAX;
-
- int minIndex = -1;
-
- b3Float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for (int ie = 0; ie < nPoints; ie++)
- {
- if (p[ie].w < minW)
- {
- minW = p[ie].w;
- minIndex = ie;
- }
- float f;
- b3Float4 r = p[ie] - center;
- f = b3Dot3F4(u, r);
- if (f < maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = b3Dot3F4(-u, r);
- if (f < maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
- f = b3Dot3F4(v, r);
- if (f < maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = b3Dot3F4(-v, r);
- if (f < maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-}
-
-#endif //B3_REDUCE_CONTACTS_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
deleted file mode 100644
index 663e946fc1..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef B3_RIGIDBODY_DATA_H
-#define B3_RIGIDBODY_DATA_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-#include "Bullet3Common/shared/b3Quat.h"
-#include "Bullet3Common/shared/b3Mat3x3.h"
-
-typedef struct b3RigidBodyData b3RigidBodyData_t;
-
-struct b3RigidBodyData
-{
- b3Float4 m_pos;
- b3Quat m_quat;
- b3Float4 m_linVel;
- b3Float4 m_angVel;
-
- int m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-};
-
-typedef struct b3InertiaData b3InertiaData_t;
-
-struct b3InertiaData
-{
- b3Mat3x3 m_invInertiaWorld;
- b3Mat3x3 m_initInvInertia;
-};
-
-#endif //B3_RIGIDBODY_DATA_H
diff --git a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h b/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
deleted file mode 100644
index e0c3a5cf97..0000000000
--- a/thirdparty/bullet/Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef B3_UPDATE_AABBS_H
-#define B3_UPDATE_AABBS_H
-
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-void b3ComputeWorldAabb(int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)
-{
- __global const b3RigidBodyData_t* body = &bodies[bodyId];
-
- b3Float4 position = body->m_pos;
- b3Quat orientation = body->m_quat;
-
- int collidableIndex = body->m_collidableIdx;
- int shapeIndex = collidables[collidableIndex].m_shapeIndex;
-
- if (shapeIndex >= 0)
- {
- b3Aabb_t localAabb = localShapeAABB[collidableIndex];
- b3Aabb_t worldAabb;
-
- b3Float4 aabbAMinOut, aabbAMaxOut;
- float margin = 0.f;
- b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &aabbAMinOut, &aabbAMaxOut);
-
- worldAabb.m_minVec = aabbAMinOut;
- worldAabb.m_minIndices[3] = bodyId;
- worldAabb.m_maxVec = aabbAMaxOut;
- worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass == 0.f ? 0 : 1;
- worldAabbs[bodyId] = worldAabb;
- }
-}
-
-#endif //B3_UPDATE_AABBS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp
deleted file mode 100644
index d546d5e066..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3AlignedAllocator.h"
-
-#ifdef B3_ALLOCATOR_STATISTICS
-int b3g_numAlignedAllocs = 0;
-int b3g_numAlignedFree = 0;
-int b3g_totalBytesAlignedAllocs = 0; //detect memory leaks
-#endif
-
-static void *b3AllocDefault(size_t size)
-{
- return malloc(size);
-}
-
-static void b3FreeDefault(void *ptr)
-{
- free(ptr);
-}
-
-static b3AllocFunc *b3s_allocFunc = b3AllocDefault;
-static b3FreeFunc *b3s_freeFunc = b3FreeDefault;
-
-#if defined(B3_HAS_ALIGNED_ALLOCATOR)
-#include <malloc.h>
-static void *b3AlignedAllocDefault(size_t size, int alignment)
-{
- return _aligned_malloc(size, (size_t)alignment);
-}
-
-static void b3AlignedFreeDefault(void *ptr)
-{
- _aligned_free(ptr);
-}
-#elif defined(__CELLOS_LV2__)
-#include <stdlib.h>
-
-static inline void *b3AlignedAllocDefault(size_t size, int alignment)
-{
- return memalign(alignment, size);
-}
-
-static inline void b3AlignedFreeDefault(void *ptr)
-{
- free(ptr);
-}
-#else
-
-static inline void *b3AlignedAllocDefault(size_t size, int alignment)
-{
- void *ret;
- char *real;
- real = (char *)b3s_allocFunc(size + sizeof(void *) + (alignment - 1));
- if (real)
- {
- ret = b3AlignPointer(real + sizeof(void *), alignment);
- *((void **)(ret)-1) = (void *)(real);
- }
- else
- {
- ret = (void *)(real);
- }
- return (ret);
-}
-
-static inline void b3AlignedFreeDefault(void *ptr)
-{
- void *real;
-
- if (ptr)
- {
- real = *((void **)(ptr)-1);
- b3s_freeFunc(real);
- }
-}
-#endif
-
-static b3AlignedAllocFunc *b3s_alignedAllocFunc = b3AlignedAllocDefault;
-static b3AlignedFreeFunc *b3s_alignedFreeFunc = b3AlignedFreeDefault;
-
-void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc *allocFunc, b3AlignedFreeFunc *freeFunc)
-{
- b3s_alignedAllocFunc = allocFunc ? allocFunc : b3AlignedAllocDefault;
- b3s_alignedFreeFunc = freeFunc ? freeFunc : b3AlignedFreeDefault;
-}
-
-void b3AlignedAllocSetCustom(b3AllocFunc *allocFunc, b3FreeFunc *freeFunc)
-{
- b3s_allocFunc = allocFunc ? allocFunc : b3AllocDefault;
- b3s_freeFunc = freeFunc ? freeFunc : b3FreeDefault;
-}
-
-#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
-//this generic allocator provides the total allocated number of bytes
-#include <stdio.h>
-
-void *b3AlignedAllocInternal(size_t size, int alignment, int line, char *filename)
-{
- void *ret;
- char *real;
-#ifdef B3_ALLOCATOR_STATISTICS
- b3g_totalBytesAlignedAllocs += size;
- b3g_numAlignedAllocs++;
-#endif
- real = (char *)b3s_allocFunc(size + 2 * sizeof(void *) + (alignment - 1));
- if (real)
- {
- ret = (void *)b3AlignPointer(real + 2 * sizeof(void *), alignment);
- *((void **)(ret)-1) = (void *)(real);
- *((int *)(ret)-2) = size;
- }
- else
- {
- ret = (void *)(real); //??
- }
-
- b3Printf("allocation#%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedAllocs, real, filename, line, size);
-
- int *ptr = (int *)ret;
- *ptr = 12;
- return (ret);
-}
-
-void b3AlignedFreeInternal(void *ptr, int line, char *filename)
-{
- void *real;
-#ifdef B3_ALLOCATOR_STATISTICS
- b3g_numAlignedFree++;
-#endif
- if (ptr)
- {
- real = *((void **)(ptr)-1);
- int size = *((int *)(ptr)-2);
-#ifdef B3_ALLOCATOR_STATISTICS
- b3g_totalBytesAlignedAllocs -= size;
-#endif
- b3Printf("free #%d at address %x, from %s,line %d, size %d\n", b3g_numAlignedFree, real, filename, line, size);
-
- b3s_freeFunc(real);
- }
- else
- {
- b3Printf("NULL ptr\n");
- }
-}
-
-#else //B3_DEBUG_MEMORY_ALLOCATIONS
-
-void *b3AlignedAllocInternal(size_t size, int alignment)
-{
-#ifdef B3_ALLOCATOR_STATISTICS
- b3g_numAlignedAllocs++;
-#endif
- void *ptr;
- ptr = b3s_alignedAllocFunc(size, alignment);
- // b3Printf("b3AlignedAllocInternal %d, %x\n",size,ptr);
- return ptr;
-}
-
-void b3AlignedFreeInternal(void *ptr)
-{
- if (!ptr)
- {
- return;
- }
-#ifdef B3_ALLOCATOR_STATISTICS
- b3g_numAlignedFree++;
-#endif
- // b3Printf("b3AlignedFreeInternal %x\n",ptr);
- b3s_alignedFreeFunc(ptr);
-}
-
-#endif //B3_DEBUG_MEMORY_ALLOCATIONS
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h b/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h
deleted file mode 100644
index bcff9f128e..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3AlignedAllocator.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_ALIGNED_ALLOCATOR
-#define B3_ALIGNED_ALLOCATOR
-
-///we probably replace this with our own aligned memory allocator
-///so we replace _aligned_malloc and _aligned_free with our own
-///that is better portable and more predictable
-
-#include "b3Scalar.h"
-//#define B3_DEBUG_MEMORY_ALLOCATIONS 1
-#ifdef B3_DEBUG_MEMORY_ALLOCATIONS
-
-#define b3AlignedAlloc(a, b) \
- b3AlignedAllocInternal(a, b, __LINE__, __FILE__)
-
-#define b3AlignedFree(ptr) \
- b3AlignedFreeInternal(ptr, __LINE__, __FILE__)
-
-void* b3AlignedAllocInternal(size_t size, int alignment, int line, char* filename);
-
-void b3AlignedFreeInternal(void* ptr, int line, char* filename);
-
-#else
-void* b3AlignedAllocInternal(size_t size, int alignment);
-void b3AlignedFreeInternal(void* ptr);
-
-#define b3AlignedAlloc(size, alignment) b3AlignedAllocInternal(size, alignment)
-#define b3AlignedFree(ptr) b3AlignedFreeInternal(ptr)
-
-#endif
-typedef int btSizeType;
-
-typedef void*(b3AlignedAllocFunc)(size_t size, int alignment);
-typedef void(b3AlignedFreeFunc)(void* memblock);
-typedef void*(b3AllocFunc)(size_t size);
-typedef void(b3FreeFunc)(void* memblock);
-
-///The developer can let all Bullet memory allocations go through a custom memory allocator, using b3AlignedAllocSetCustom
-void b3AlignedAllocSetCustom(b3AllocFunc* allocFunc, b3FreeFunc* freeFunc);
-///If the developer has already an custom aligned allocator, then b3AlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
-void b3AlignedAllocSetCustomAligned(b3AlignedAllocFunc* allocFunc, b3AlignedFreeFunc* freeFunc);
-
-///The b3AlignedAllocator is a portable class for aligned memory allocations.
-///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using b3AlignedAllocSetCustom and b3AlignedAllocSetCustomAligned.
-template <typename T, unsigned Alignment>
-class b3AlignedAllocator
-{
- typedef b3AlignedAllocator<T, Alignment> self_type;
-
-public:
- //just going down a list:
- b3AlignedAllocator() {}
- /*
- b3AlignedAllocator( const self_type & ) {}
- */
-
- template <typename Other>
- b3AlignedAllocator(const b3AlignedAllocator<Other, Alignment>&)
- {
- }
-
- typedef const T* const_pointer;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef T& reference;
- typedef T value_type;
-
- pointer address(reference ref) const { return &ref; }
- const_pointer address(const_reference ref) const { return &ref; }
- pointer allocate(btSizeType n, const_pointer* hint = 0)
- {
- (void)hint;
- return reinterpret_cast<pointer>(b3AlignedAlloc(sizeof(value_type) * n, Alignment));
- }
- void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
- void deallocate(pointer ptr)
- {
- b3AlignedFree(reinterpret_cast<void*>(ptr));
- }
- void destroy(pointer ptr) { ptr->~value_type(); }
-
- template <typename O>
- struct rebind
- {
- typedef b3AlignedAllocator<O, Alignment> other;
- };
- template <typename O>
- self_type& operator=(const b3AlignedAllocator<O, Alignment>&)
- {
- return *this;
- }
-
- friend bool operator==(const self_type&, const self_type&) { return true; }
-};
-
-#endif //B3_ALIGNED_ALLOCATOR
diff --git a/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h b/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h
deleted file mode 100644
index 249e381bf1..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3AlignedObjectArray.h
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_OBJECT_ARRAY__
-#define B3_OBJECT_ARRAY__
-
-#include "b3Scalar.h" // has definitions like B3_FORCE_INLINE
-#include "b3AlignedAllocator.h"
-
-///If the platform doesn't support placement new, you can disable B3_USE_PLACEMENT_NEW
-///then the b3AlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
-///You can enable B3_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
-///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
-///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
-
-#define B3_USE_PLACEMENT_NEW 1
-//#define B3_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
-#define B3_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
-
-#ifdef B3_USE_MEMCPY
-#include <memory.h>
-#include <string.h>
-#endif //B3_USE_MEMCPY
-
-#ifdef B3_USE_PLACEMENT_NEW
-#include <new> //for placement new
-#endif //B3_USE_PLACEMENT_NEW
-
-///The b3AlignedObjectArray template class uses a subset of the stl::vector interface for its methods
-///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
-template <typename T>
-//template <class T>
-class b3AlignedObjectArray
-{
- b3AlignedAllocator<T, 16> m_allocator;
-
- int m_size;
- int m_capacity;
- T* m_data;
- //PCK: added this line
- bool m_ownsMemory;
-
-#ifdef B3_ALLOW_ARRAY_COPY_OPERATOR
-public:
- B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other)
- {
- copyFromArray(other);
- return *this;
- }
-#else //B3_ALLOW_ARRAY_COPY_OPERATOR
-private:
- B3_FORCE_INLINE b3AlignedObjectArray<T>& operator=(const b3AlignedObjectArray<T>& other);
-#endif //B3_ALLOW_ARRAY_COPY_OPERATOR
-
-protected:
- B3_FORCE_INLINE int allocSize(int size)
- {
- return (size ? size * 2 : 1);
- }
- B3_FORCE_INLINE void copy(int start, int end, T* dest) const
- {
- int i;
- for (i = start; i < end; ++i)
-#ifdef B3_USE_PLACEMENT_NEW
- new (&dest[i]) T(m_data[i]);
-#else
- dest[i] = m_data[i];
-#endif //B3_USE_PLACEMENT_NEW
- }
-
- B3_FORCE_INLINE void init()
- {
- //PCK: added this line
- m_ownsMemory = true;
- m_data = 0;
- m_size = 0;
- m_capacity = 0;
- }
- B3_FORCE_INLINE void destroy(int first, int last)
- {
- int i;
- for (i = first; i < last; i++)
- {
- m_data[i].~T();
- }
- }
-
- B3_FORCE_INLINE void* allocate(int size)
- {
- if (size)
- return m_allocator.allocate(size);
- return 0;
- }
-
- B3_FORCE_INLINE void deallocate()
- {
- if (m_data)
- {
- //PCK: enclosed the deallocation in this block
- if (m_ownsMemory)
- {
- m_allocator.deallocate(m_data);
- }
- m_data = 0;
- }
- }
-
-public:
- b3AlignedObjectArray()
- {
- init();
- }
-
- ~b3AlignedObjectArray()
- {
- clear();
- }
-
- ///Generally it is best to avoid using the copy constructor of an b3AlignedObjectArray, and use a (const) reference to the array instead.
- b3AlignedObjectArray(const b3AlignedObjectArray& otherArray)
- {
- init();
-
- int otherSize = otherArray.size();
- resize(otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
-
- /// return the number of elements in the array
- B3_FORCE_INLINE int size() const
- {
- return m_size;
- }
-
- B3_FORCE_INLINE const T& at(int n) const
- {
- b3Assert(n >= 0);
- b3Assert(n < size());
- return m_data[n];
- }
-
- B3_FORCE_INLINE T& at(int n)
- {
- b3Assert(n >= 0);
- b3Assert(n < size());
- return m_data[n];
- }
-
- B3_FORCE_INLINE const T& operator[](int n) const
- {
- b3Assert(n >= 0);
- b3Assert(n < size());
- return m_data[n];
- }
-
- B3_FORCE_INLINE T& operator[](int n)
- {
- b3Assert(n >= 0);
- b3Assert(n < size());
- return m_data[n];
- }
-
- ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
- B3_FORCE_INLINE void clear()
- {
- destroy(0, size());
-
- deallocate();
-
- init();
- }
-
- B3_FORCE_INLINE void pop_back()
- {
- b3Assert(m_size > 0);
- m_size--;
- m_data[m_size].~T();
- }
-
- ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
- ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
- B3_FORCE_INLINE void resizeNoInitialize(int newsize)
- {
- int curSize = size();
-
- if (newsize < curSize)
- {
- }
- else
- {
- if (newsize > size())
- {
- reserve(newsize);
- }
- //leave this uninitialized
- }
- m_size = newsize;
- }
-
- B3_FORCE_INLINE void resize(int newsize, const T& fillData = T())
- {
- int curSize = size();
-
- if (newsize < curSize)
- {
- for (int i = newsize; i < curSize; i++)
- {
- m_data[i].~T();
- }
- }
- else
- {
- if (newsize > size())
- {
- reserve(newsize);
- }
-#ifdef B3_USE_PLACEMENT_NEW
- for (int i = curSize; i < newsize; i++)
- {
- new (&m_data[i]) T(fillData);
- }
-#endif //B3_USE_PLACEMENT_NEW
- }
-
- m_size = newsize;
- }
- B3_FORCE_INLINE T& expandNonInitializing()
- {
- int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
- m_size++;
-
- return m_data[sz];
- }
-
- B3_FORCE_INLINE T& expand(const T& fillValue = T())
- {
- int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
- m_size++;
-#ifdef B3_USE_PLACEMENT_NEW
- new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
-#endif
-
- return m_data[sz];
- }
-
- B3_FORCE_INLINE void push_back(const T& _Val)
- {
- int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
-
-#ifdef B3_USE_PLACEMENT_NEW
- new (&m_data[m_size]) T(_Val);
-#else
- m_data[size()] = _Val;
-#endif //B3_USE_PLACEMENT_NEW
-
- m_size++;
- }
-
- /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
- B3_FORCE_INLINE int capacity() const
- {
- return m_capacity;
- }
-
- B3_FORCE_INLINE void reserve(int _Count)
- { // determine new minimum length of allocated storage
- if (capacity() < _Count)
- { // not enough room, reallocate
- T* s = (T*)allocate(_Count);
- b3Assert(s);
- if (s == 0)
- {
- b3Error("b3AlignedObjectArray reserve out-of-memory\n");
- _Count = 0;
- m_size = 0;
- }
- copy(0, size(), s);
-
- destroy(0, size());
-
- deallocate();
-
- //PCK: added this line
- m_ownsMemory = true;
-
- m_data = s;
-
- m_capacity = _Count;
- }
- }
-
- class less
- {
- public:
- bool operator()(const T& a, const T& b)
- {
- return (a < b);
- }
- };
-
- template <typename L>
- void quickSortInternal(const L& CompareFunc, int lo, int hi)
- {
- // lo is the lower index, hi is the upper index
- // of the region of array a that is to be sorted
- int i = lo, j = hi;
- T x = m_data[(lo + hi) / 2];
-
- // partition
- do
- {
- while (CompareFunc(m_data[i], x))
- i++;
- while (CompareFunc(x, m_data[j]))
- j--;
- if (i <= j)
- {
- swap(i, j);
- i++;
- j--;
- }
- } while (i <= j);
-
- // recursion
- if (lo < j)
- quickSortInternal(CompareFunc, lo, j);
- if (i < hi)
- quickSortInternal(CompareFunc, i, hi);
- }
-
- template <typename L>
- void quickSort(const L& CompareFunc)
- {
- //don't sort 0 or 1 elements
- if (size() > 1)
- {
- quickSortInternal(CompareFunc, 0, size() - 1);
- }
- }
-
- ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
- template <typename L>
- void downHeap(T* pArr, int k, int n, const L& CompareFunc)
- {
- /* PRE: a[k+1..N] is a heap */
- /* POST: a[k..N] is a heap */
-
- T temp = pArr[k - 1];
- /* k has child(s) */
- while (k <= n / 2)
- {
- int child = 2 * k;
-
- if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
- {
- child++;
- }
- /* pick larger child */
- if (CompareFunc(temp, pArr[child - 1]))
- {
- /* move child up */
- pArr[k - 1] = pArr[child - 1];
- k = child;
- }
- else
- {
- break;
- }
- }
- pArr[k - 1] = temp;
- } /*downHeap*/
-
- void swap(int index0, int index1)
- {
-#ifdef B3_USE_MEMCPY
- char temp[sizeof(T)];
- memcpy(temp, &m_data[index0], sizeof(T));
- memcpy(&m_data[index0], &m_data[index1], sizeof(T));
- memcpy(&m_data[index1], temp, sizeof(T));
-#else
- T temp = m_data[index0];
- m_data[index0] = m_data[index1];
- m_data[index1] = temp;
-#endif //B3_USE_PLACEMENT_NEW
- }
-
- template <typename L>
- void heapSort(const L& CompareFunc)
- {
- /* sort a[0..N-1], N.B. 0 to N-1 */
- int k;
- int n = m_size;
- for (k = n / 2; k > 0; k--)
- {
- downHeap(m_data, k, n, CompareFunc);
- }
-
- /* a[1..N] is now a heap */
- while (n >= 1)
- {
- swap(0, n - 1); /* largest of a[0..n-1] */
-
- n = n - 1;
- /* restore a[1..i-1] heap */
- downHeap(m_data, 1, n, CompareFunc);
- }
- }
-
- ///non-recursive binary search, assumes sorted array
- int findBinarySearch(const T& key) const
- {
- int first = 0;
- int last = size() - 1;
-
- //assume sorted array
- while (first <= last)
- {
- int mid = (first + last) / 2; // compute mid point.
- if (key > m_data[mid])
- first = mid + 1; // repeat search in top half.
- else if (key < m_data[mid])
- last = mid - 1; // repeat search in bottom half.
- else
- return mid; // found it. return position /////
- }
- return size(); // failed to find key
- }
-
- int findLinearSearch(const T& key) const
- {
- int index = size();
- int i;
-
- for (i = 0; i < size(); i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- int findLinearSearch2(const T& key) const
- {
- int index = -1;
- int i;
-
- for (i = 0; i < size(); i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- void remove(const T& key)
- {
- int findIndex = findLinearSearch(key);
- if (findIndex < size())
- {
- swap(findIndex, size() - 1);
- pop_back();
- }
- }
-
- //PCK: whole function
- void initializeFromBuffer(void* buffer, int size, int capacity)
- {
- clear();
- m_ownsMemory = false;
- m_data = (T*)buffer;
- m_size = size;
- m_capacity = capacity;
- }
-
- void copyFromArray(const b3AlignedObjectArray& otherArray)
- {
- int otherSize = otherArray.size();
- resize(otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
-
- void removeAtIndex(int index)
- {
- if (index < size())
- {
- swap(index, size() - 1);
- pop_back();
- }
- }
-};
-
-#endif //B3_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h b/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h
deleted file mode 100644
index 5fe4f25f8d..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3CommandLineArgs.h
+++ /dev/null
@@ -1,106 +0,0 @@
-#ifndef COMMAND_LINE_ARGS_H
-#define COMMAND_LINE_ARGS_H
-
-/******************************************************************************
- * Command-line parsing
- ******************************************************************************/
-#include <map>
-#include <algorithm>
-#include <string>
-#include <cstring>
-#include <sstream>
-class b3CommandLineArgs
-{
-protected:
- std::map<std::string, std::string> pairs;
-
-public:
- // Constructor
- b3CommandLineArgs(int argc, char **argv)
- {
- addArgs(argc, argv);
- }
-
- void addArgs(int argc, char **argv)
- {
- for (int i = 1; i < argc; i++)
- {
- std::string arg = argv[i];
-
- if ((arg.length() < 2) || (arg[0] != '-') || (arg[1] != '-'))
- {
- continue;
- }
-
- std::string::size_type pos;
- std::string key, val;
- if ((pos = arg.find('=')) == std::string::npos)
- {
- key = std::string(arg, 2, arg.length() - 2);
- val = "";
- }
- else
- {
- key = std::string(arg, 2, pos - 2);
- val = std::string(arg, pos + 1, arg.length() - 1);
- }
-
- //only add new keys, don't replace existing
- if (pairs.find(key) == pairs.end())
- {
- pairs[key] = val;
- }
- }
- }
-
- bool CheckCmdLineFlag(const char *arg_name)
- {
- std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end())
- {
- return true;
- }
- return false;
- }
-
- template <typename T>
- bool GetCmdLineArgument(const char *arg_name, T &val);
-
- int ParsedArgc()
- {
- return pairs.size();
- }
-};
-
-template <typename T>
-inline bool b3CommandLineArgs::GetCmdLineArgument(const char *arg_name, T &val)
-{
- std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end())
- {
- std::istringstream strstream(itr->second);
- strstream >> val;
- return true;
- }
- return false;
-}
-
-template <>
-inline bool b3CommandLineArgs::GetCmdLineArgument<char *>(const char *arg_name, char *&val)
-{
- std::map<std::string, std::string>::iterator itr;
- if ((itr = pairs.find(arg_name)) != pairs.end())
- {
- std::string s = itr->second;
- val = (char *)malloc(sizeof(char) * (s.length() + 1));
- std::strcpy(val, s.c_str());
- return true;
- }
- else
- {
- val = NULL;
- }
- return false;
-}
-
-#endif //COMMAND_LINE_ARGS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3FileUtils.h b/thirdparty/bullet/Bullet3Common/b3FileUtils.h
deleted file mode 100644
index 9ded17eaaf..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3FileUtils.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef B3_FILE_UTILS_H
-#define B3_FILE_UTILS_H
-
-#include <stdio.h>
-#include "b3Scalar.h"
-#include <stddef.h> //ptrdiff_h
-#include <string.h>
-
-struct b3FileUtils
-{
- b3FileUtils()
- {
- }
- virtual ~b3FileUtils()
- {
- }
-
- static bool findFile(const char* orgFileName, char* relativeFileName, int maxRelativeFileNameMaxLen)
- {
- FILE* f = 0;
- f = fopen(orgFileName, "rb");
- if (f)
- {
- //printf("original file found: [%s]\n", orgFileName);
- sprintf(relativeFileName, "%s", orgFileName);
- fclose(f);
- return true;
- }
-
- //printf("Trying various directories, relative to current working directory\n");
- const char* prefix[] = {"./", "./data/", "../data/", "../../data/", "../../../data/", "../../../../data/"};
- int numPrefixes = sizeof(prefix) / sizeof(const char*);
-
- f = 0;
- bool fileFound = false;
-
- for (int i = 0; !f && i < numPrefixes; i++)
- {
-#ifdef _MSC_VER
- sprintf_s(relativeFileName, maxRelativeFileNameMaxLen, "%s%s", prefix[i], orgFileName);
-#else
- sprintf(relativeFileName, "%s%s", prefix[i], orgFileName);
-#endif
- f = fopen(relativeFileName, "rb");
- if (f)
- {
- fileFound = true;
- break;
- }
- }
- if (f)
- {
- fclose(f);
- }
-
- return fileFound;
- }
-
- static const char* strip2(const char* name, const char* pattern)
- {
- size_t const patlen = strlen(pattern);
- size_t patcnt = 0;
- const char* oriptr;
- const char* patloc;
- // find how many times the pattern occurs in the original string
- for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
- {
- patcnt++;
- }
- return oriptr;
- }
-
- static int extractPath(const char* fileName, char* path, int maxPathLength)
- {
- const char* stripped = strip2(fileName, "/");
- stripped = strip2(stripped, "\\");
-
- ptrdiff_t len = stripped - fileName;
- b3Assert((len + 1) < maxPathLength);
-
- if (len && ((len + 1) < maxPathLength))
- {
- for (int i = 0; i < len; i++)
- {
- path[i] = fileName[i];
- }
- path[len] = 0;
- }
- else
- {
- len = 0;
- b3Assert(maxPathLength > 0);
- if (maxPathLength > 0)
- {
- path[len] = 0;
- }
- }
- return len;
- }
-
- static char toLowerChar(const char t)
- {
- if (t >= (char)'A' && t <= (char)'Z')
- return t + ((char)'a' - (char)'A');
- else
- return t;
- }
-
- static void toLower(char* str)
- {
- int len = strlen(str);
- for (int i = 0; i < len; i++)
- {
- str[i] = toLowerChar(str[i]);
- }
- }
-
- /*static const char* strip2(const char* name, const char* pattern)
- {
- size_t const patlen = strlen(pattern);
- size_t patcnt = 0;
- const char * oriptr;
- const char * patloc;
- // find how many times the pattern occurs in the original string
- for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)
- {
- patcnt++;
- }
- return oriptr;
- }
- */
-};
-#endif //B3_FILE_UTILS_H
diff --git a/thirdparty/bullet/Bullet3Common/b3HashMap.h b/thirdparty/bullet/Bullet3Common/b3HashMap.h
deleted file mode 100644
index 3009e2cf2f..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3HashMap.h
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_HASH_MAP_H
-#define B3_HASH_MAP_H
-
-#include "b3AlignedObjectArray.h"
-
-#include <string>
-
-///very basic hashable string implementation, compatible with b3HashMap
-struct b3HashString
-{
- std::string m_string;
- unsigned int m_hash;
-
- B3_FORCE_INLINE unsigned int getHash() const
- {
- return m_hash;
- }
-
- b3HashString(const char* name)
- : m_string(name)
- {
- /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
- static const unsigned int InitialFNV = 2166136261u;
- static const unsigned int FNVMultiple = 16777619u;
-
- /* Fowler / Noll / Vo (FNV) Hash */
- unsigned int hash = InitialFNV;
- int len = m_string.length();
- for (int i = 0; i < len; i++)
- {
- hash = hash ^ (m_string[i]); /* xor the low 8 bits */
- hash = hash * FNVMultiple; /* multiply by the magic number */
- }
- m_hash = hash;
- }
-
- int portableStringCompare(const char* src, const char* dst) const
- {
- int ret = 0;
-
- while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
- ++src, ++dst;
-
- if (ret < 0)
- ret = -1;
- else if (ret > 0)
- ret = 1;
-
- return (ret);
- }
-
- bool equals(const b3HashString& other) const
- {
- return (m_string == other.m_string);
- }
-};
-
-const int B3_HASH_NULL = 0xffffffff;
-
-class b3HashInt
-{
- int m_uid;
-
-public:
- b3HashInt(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- void setUid1(int uid)
- {
- m_uid = uid;
- }
-
- bool equals(const b3HashInt& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- B3_FORCE_INLINE unsigned int getHash() const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-class b3HashPtr
-{
- union {
- const void* m_pointer;
- int m_hashValues[2];
- };
-
-public:
- b3HashPtr(const void* ptr)
- : m_pointer(ptr)
- {
- }
-
- const void* getPointer() const
- {
- return m_pointer;
- }
-
- bool equals(const b3HashPtr& other) const
- {
- return getPointer() == other.getPointer();
- }
-
- //to our success
- B3_FORCE_INLINE unsigned int getHash() const
- {
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
- int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
-
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-template <class Value>
-class b3HashKeyPtr
-{
- int m_uid;
-
-public:
- b3HashKeyPtr(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const b3HashKeyPtr<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
-
- //to our success
- B3_FORCE_INLINE unsigned int getHash() const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-template <class Value>
-class b3HashKey
-{
- int m_uid;
-
-public:
- b3HashKey(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const b3HashKey<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- B3_FORCE_INLINE unsigned int getHash() const
- {
- int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-///The b3HashMap template class implements a generic and lightweight hashmap.
-///A basic sample of how to use b3HashMap is located in Demos\BasicDemo\main.cpp
-template <class Key, class Value>
-class b3HashMap
-{
-protected:
- b3AlignedObjectArray<int> m_hashTable;
- b3AlignedObjectArray<int> m_next;
-
- b3AlignedObjectArray<Value> m_valueArray;
- b3AlignedObjectArray<Key> m_keyArray;
-
- void growTables(const Key& /*key*/)
- {
- int newCapacity = m_valueArray.capacity();
-
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
-
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
-
- int i;
-
- for (i = 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = B3_HASH_NULL;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = B3_HASH_NULL;
- }
-
- for (i = 0; i < curHashtableSize; i++)
- {
- //const Value& value = m_valueArray[i];
- //const Key& key = m_keyArray[i];
-
- int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
- }
-
-public:
- void insert(const Key& key, const Value& value)
- {
- int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- //replace value if the key is already there
- int index = findIndex(key);
- if (index != B3_HASH_NULL)
- {
- m_valueArray[index] = value;
- return;
- }
-
- int count = m_valueArray.size();
- int oldCapacity = m_valueArray.capacity();
- m_valueArray.push_back(value);
- m_keyArray.push_back(key);
-
- int newCapacity = m_valueArray.capacity();
- if (oldCapacity < newCapacity)
- {
- growTables(key);
- //hash with new capacity
- hash = key.getHash() & (m_valueArray.capacity() - 1);
- }
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
- }
-
- void remove(const Key& key)
- {
- int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- int pairIndex = findIndex(key);
-
- if (pairIndex == B3_HASH_NULL)
- {
- return;
- }
-
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- b3Assert(index != B3_HASH_NULL);
-
- int previous = B3_HASH_NULL;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != B3_HASH_NULL)
- {
- b3Assert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
-
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
-
- int lastPairIndex = m_valueArray.size() - 1;
-
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- return;
- }
-
- // Remove the last pair from the hash table.
- int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
-
- index = m_hashTable[lastHash];
- b3Assert(index != B3_HASH_NULL);
-
- previous = B3_HASH_NULL;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != B3_HASH_NULL)
- {
- b3Assert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
-
- // Copy the last pair into the remove pair's spot.
- m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
- m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
-
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
-
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- }
-
- int size() const
- {
- return m_valueArray.size();
- }
-
- const Value* getAtIndex(int index) const
- {
- b3Assert(index < m_valueArray.size());
-
- return &m_valueArray[index];
- }
-
- Value* getAtIndex(int index)
- {
- b3Assert(index < m_valueArray.size());
-
- return &m_valueArray[index];
- }
-
- Key getKeyAtIndex(int index)
- {
- b3Assert(index < m_keyArray.size());
- return m_keyArray[index];
- }
-
- const Key getKeyAtIndex(int index) const
- {
- b3Assert(index < m_keyArray.size());
- return m_keyArray[index];
- }
-
- Value* operator[](const Key& key)
- {
- return find(key);
- }
-
- const Value* find(const Key& key) const
- {
- int index = findIndex(key);
- if (index == B3_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
-
- Value* find(const Key& key)
- {
- int index = findIndex(key);
- if (index == B3_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
-
- int findIndex(const Key& key) const
- {
- unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- if (hash >= (unsigned int)m_hashTable.size())
- {
- return B3_HASH_NULL;
- }
-
- int index = m_hashTable[hash];
- while ((index != B3_HASH_NULL) && key.equals(m_keyArray[index]) == false)
- {
- index = m_next[index];
- }
- return index;
- }
-
- void clear()
- {
- m_hashTable.clear();
- m_next.clear();
- m_valueArray.clear();
- m_keyArray.clear();
- }
-};
-
-#endif //B3_HASH_MAP_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.cpp b/thirdparty/bullet/Bullet3Common/b3Logging.cpp
deleted file mode 100644
index 9c9f7c09ea..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Logging.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "b3Logging.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#endif //_WIN32
-
-void b3PrintfFuncDefault(const char* msg)
-{
-#ifdef _WIN32
- OutputDebugStringA(msg);
-#endif
- printf("%s", msg);
- //is this portable?
- fflush(stdout);
-}
-
-void b3WarningMessageFuncDefault(const char* msg)
-{
-#ifdef _WIN32
- OutputDebugStringA(msg);
-#endif
- printf("%s", msg);
- //is this portable?
- fflush(stdout);
-}
-
-void b3ErrorMessageFuncDefault(const char* msg)
-{
-#ifdef _WIN32
- OutputDebugStringA(msg);
-#endif
- printf("%s", msg);
-
- //is this portable?
- fflush(stdout);
-}
-
-static b3PrintfFunc* b3s_printfFunc = b3PrintfFuncDefault;
-static b3WarningMessageFunc* b3s_warningMessageFunc = b3WarningMessageFuncDefault;
-static b3ErrorMessageFunc* b3s_errorMessageFunc = b3ErrorMessageFuncDefault;
-
-///The developer can route b3Printf output using their own implementation
-void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc)
-{
- b3s_printfFunc = printfFunc;
-}
-void b3SetCustomWarningMessageFunc(b3PrintfFunc* warningMessageFunc)
-{
- b3s_warningMessageFunc = warningMessageFunc;
-}
-void b3SetCustomErrorMessageFunc(b3PrintfFunc* errorMessageFunc)
-{
- b3s_errorMessageFunc = errorMessageFunc;
-}
-
-//#define B3_MAX_DEBUG_STRING_LENGTH 2048
-#define B3_MAX_DEBUG_STRING_LENGTH 32768
-
-void b3OutputPrintfVarArgsInternal(const char* str, ...)
-{
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
- va_list argList;
- va_start(argList, str);
-#ifdef _MSC_VER
- vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#else
- vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#endif
- (b3s_printfFunc)(strDebug);
- va_end(argList);
-}
-void b3OutputWarningMessageVarArgsInternal(const char* str, ...)
-{
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
- va_list argList;
- va_start(argList, str);
-#ifdef _MSC_VER
- vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#else
- vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#endif
- (b3s_warningMessageFunc)(strDebug);
- va_end(argList);
-}
-void b3OutputErrorMessageVarArgsInternal(const char* str, ...)
-{
- char strDebug[B3_MAX_DEBUG_STRING_LENGTH] = {0};
- va_list argList;
- va_start(argList, str);
-#ifdef _MSC_VER
- vsprintf_s(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#else
- vsnprintf(strDebug, B3_MAX_DEBUG_STRING_LENGTH, str, argList);
-#endif
- (b3s_errorMessageFunc)(strDebug);
- va_end(argList);
-}
-
-void b3EnterProfileZoneDefault(const char* name)
-{
-}
-void b3LeaveProfileZoneDefault()
-{
-}
-static b3EnterProfileZoneFunc* b3s_enterFunc = b3EnterProfileZoneDefault;
-static b3LeaveProfileZoneFunc* b3s_leaveFunc = b3LeaveProfileZoneDefault;
-void b3EnterProfileZone(const char* name)
-{
- (b3s_enterFunc)(name);
-}
-void b3LeaveProfileZone()
-{
- (b3s_leaveFunc)();
-}
-
-void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc)
-{
- b3s_enterFunc = enterFunc;
-}
-void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc)
-{
- b3s_leaveFunc = leaveFunc;
-}
-
-#ifndef _MSC_VER
-#undef vsprintf_s
-#endif
diff --git a/thirdparty/bullet/Bullet3Common/b3Logging.h b/thirdparty/bullet/Bullet3Common/b3Logging.h
deleted file mode 100644
index f61149de77..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Logging.h
+++ /dev/null
@@ -1,74 +0,0 @@
-
-#ifndef B3_LOGGING_H
-#define B3_LOGGING_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-///We add the do/while so that the statement "if (condition) b3Printf("test"); else {...}" would fail
-///You can also customize the message by uncommenting out a different line below
-#define b3Printf(...) b3OutputPrintfVarArgsInternal(__VA_ARGS__)
- //#define b3Printf(...) do {b3OutputPrintfVarArgsInternal("b3Printf[%s,%d]:",__FILE__,__LINE__);b3OutputPrintfVarArgsInternal(__VA_ARGS__); } while(0)
- //#define b3Printf b3OutputPrintfVarArgsInternal
- //#define b3Printf(...) printf(__VA_ARGS__)
- //#define b3Printf(...)
-#define b3Warning(...) do{ b3OutputWarningMessageVarArgsInternal("b3Warning[%s,%d]:\n", __FILE__, __LINE__);b3OutputWarningMessageVarArgsInternal(__VA_ARGS__);} while (0)
-#define b3Error(...)do {b3OutputErrorMessageVarArgsInternal("b3Error[%s,%d]:\n", __FILE__, __LINE__);b3OutputErrorMessageVarArgsInternal(__VA_ARGS__);} while (0)
-#ifndef B3_NO_PROFILE
-
- void b3EnterProfileZone(const char* name);
- void b3LeaveProfileZone();
-#ifdef __cplusplus
-
- class b3ProfileZone
- {
- public:
- b3ProfileZone(const char* name)
- {
- b3EnterProfileZone(name);
- }
-
- ~b3ProfileZone()
- {
- b3LeaveProfileZone();
- }
- };
-
-#define B3_PROFILE(name) b3ProfileZone __profile(name)
-#endif
-
-#else //B3_NO_PROFILE
-
-#define B3_PROFILE(name)
-#define b3StartProfile(a)
-#define b3StopProfile
-
-#endif //#ifndef B3_NO_PROFILE
-
- typedef void(b3PrintfFunc)(const char* msg);
- typedef void(b3WarningMessageFunc)(const char* msg);
- typedef void(b3ErrorMessageFunc)(const char* msg);
- typedef void(b3EnterProfileZoneFunc)(const char* msg);
- typedef void(b3LeaveProfileZoneFunc)();
-
- ///The developer can route b3Printf output using their own implementation
- void b3SetCustomPrintfFunc(b3PrintfFunc* printfFunc);
- void b3SetCustomWarningMessageFunc(b3WarningMessageFunc* warningMsgFunc);
- void b3SetCustomErrorMessageFunc(b3ErrorMessageFunc* errorMsgFunc);
-
- ///Set custom profile zone functions (zones can be nested)
- void b3SetCustomEnterProfileZoneFunc(b3EnterProfileZoneFunc* enterFunc);
- void b3SetCustomLeaveProfileZoneFunc(b3LeaveProfileZoneFunc* leaveFunc);
-
- ///Don't use those internal functions directly, use the b3Printf or b3SetCustomPrintfFunc instead (or warning/error version)
- void b3OutputPrintfVarArgsInternal(const char* str, ...);
- void b3OutputWarningMessageVarArgsInternal(const char* str, ...);
- void b3OutputErrorMessageVarArgsInternal(const char* str, ...);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //B3_LOGGING_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h b/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h
deleted file mode 100644
index 6c46536a81..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Matrix3x3.h
+++ /dev/null
@@ -1,1354 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_MATRIX3x3_H
-#define B3_MATRIX3x3_H
-
-#include "b3Vector3.h"
-#include "b3Quaternion.h"
-#include <stdio.h>
-
-#ifdef B3_USE_SSE
-//const __m128 B3_ATTRIBUTE_ALIGNED16(b3v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
-#endif
-
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
-const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
-const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
-#endif
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define b3Matrix3x3Data b3Matrix3x3DoubleData
-#else
-#define b3Matrix3x3Data b3Matrix3x3FloatData
-#endif //B3_USE_DOUBLE_PRECISION
-
-/**@brief The b3Matrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with b3Quaternion, b3Transform and b3Vector3.
-* Make sure to only include a pure orthogonal matrix without scaling. */
-B3_ATTRIBUTE_ALIGNED16(class)
-b3Matrix3x3
-{
- ///Data storage for the matrix, each vector is a row of the matrix
- b3Vector3 m_el[3];
-
-public:
- /** @brief No initializaion constructor */
- b3Matrix3x3() {}
-
- // explicit b3Matrix3x3(const b3Scalar *m) { setFromOpenGLSubMatrix(m); }
-
- /**@brief Constructor from Quaternion */
- explicit b3Matrix3x3(const b3Quaternion& q) { setRotation(q); }
- /*
- template <typename b3Scalar>
- Matrix3x3(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
- {
- setEulerYPR(yaw, pitch, roll);
- }
- */
- /** @brief Constructor with row major formatting */
- b3Matrix3x3(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
- const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
- const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
- {
- setValue(xx, xy, xz,
- yx, yy, yz,
- zx, zy, zz);
- }
-
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- B3_FORCE_INLINE b3Matrix3x3(const b3SimdFloat4 v0, const b3SimdFloat4 v1, const b3SimdFloat4 v2)
- {
- m_el[0].mVec128 = v0;
- m_el[1].mVec128 = v1;
- m_el[2].mVec128 = v2;
- }
-
- B3_FORCE_INLINE b3Matrix3x3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2)
- {
- m_el[0] = v0;
- m_el[1] = v1;
- m_el[2] = v2;
- }
-
- // Copy constructor
- B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& rhs)
- {
- m_el[0].mVec128 = rhs.m_el[0].mVec128;
- m_el[1].mVec128 = rhs.m_el[1].mVec128;
- m_el[2].mVec128 = rhs.m_el[2].mVec128;
- }
-
- // Assignment Operator
- B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& m)
- {
- m_el[0].mVec128 = m.m_el[0].mVec128;
- m_el[1].mVec128 = m.m_el[1].mVec128;
- m_el[2].mVec128 = m.m_el[2].mVec128;
-
- return *this;
- }
-
-#else
-
- /** @brief Copy constructor */
- B3_FORCE_INLINE b3Matrix3x3(const b3Matrix3x3& other)
- {
- m_el[0] = other.m_el[0];
- m_el[1] = other.m_el[1];
- m_el[2] = other.m_el[2];
- }
-
- /** @brief Assignment Operator */
- B3_FORCE_INLINE b3Matrix3x3& operator=(const b3Matrix3x3& other)
- {
- m_el[0] = other.m_el[0];
- m_el[1] = other.m_el[1];
- m_el[2] = other.m_el[2];
- return *this;
- }
-
-#endif
-
- /** @brief Get a column of the matrix as a vector
- * @param i Column number 0 indexed */
- B3_FORCE_INLINE b3Vector3 getColumn(int i) const
- {
- return b3MakeVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
- }
-
- /** @brief Get a row of the matrix as a vector
- * @param i Row number 0 indexed */
- B3_FORCE_INLINE const b3Vector3& getRow(int i) const
- {
- b3FullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Get a mutable reference to a row of the matrix as a vector
- * @param i Row number 0 indexed */
- B3_FORCE_INLINE b3Vector3& operator[](int i)
- {
- b3FullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Get a const reference to a row of the matrix as a vector
- * @param i Row number 0 indexed */
- B3_FORCE_INLINE const b3Vector3& operator[](int i) const
- {
- b3FullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Multiply by the target matrix on the right
- * @param m Rotation matrix to be applied
- * Equivilant to this = this * m */
- b3Matrix3x3& operator*=(const b3Matrix3x3& m);
-
- /** @brief Adds by the target matrix on the right
- * @param m matrix to be applied
- * Equivilant to this = this + m */
- b3Matrix3x3& operator+=(const b3Matrix3x3& m);
-
- /** @brief Substractss by the target matrix on the right
- * @param m matrix to be applied
- * Equivilant to this = this - m */
- b3Matrix3x3& operator-=(const b3Matrix3x3& m);
-
- /** @brief Set from the rotational part of a 4x4 OpenGL matrix
- * @param m A pointer to the beginning of the array of scalars*/
- void setFromOpenGLSubMatrix(const b3Scalar* m)
- {
- m_el[0].setValue(m[0], m[4], m[8]);
- m_el[1].setValue(m[1], m[5], m[9]);
- m_el[2].setValue(m[2], m[6], m[10]);
- }
- /** @brief Set the values of the matrix explicitly (row major)
- * @param xx Top left
- * @param xy Top Middle
- * @param xz Top Right
- * @param yx Middle Left
- * @param yy Middle Middle
- * @param yz Middle Right
- * @param zx Bottom Left
- * @param zy Bottom Middle
- * @param zz Bottom Right*/
- void setValue(const b3Scalar& xx, const b3Scalar& xy, const b3Scalar& xz,
- const b3Scalar& yx, const b3Scalar& yy, const b3Scalar& yz,
- const b3Scalar& zx, const b3Scalar& zy, const b3Scalar& zz)
- {
- m_el[0].setValue(xx, xy, xz);
- m_el[1].setValue(yx, yy, yz);
- m_el[2].setValue(zx, zy, zz);
- }
-
- /** @brief Set the matrix from a quaternion
- * @param q The Quaternion to match */
- void setRotation(const b3Quaternion& q)
- {
- b3Scalar d = q.length2();
- b3FullAssert(d != b3Scalar(0.0));
- b3Scalar s = b3Scalar(2.0) / d;
-
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vs, Q = q.get128();
- __m128i Qi = b3CastfTo128i(Q);
- __m128 Y, Z;
- __m128 V1, V2, V3;
- __m128 V11, V21, V31;
- __m128 NQ = _mm_xor_ps(Q, b3vMzeroMask);
- __m128i NQi = b3CastfTo128i(NQ);
-
- V1 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 2, 3))); // Y X Z W
- V2 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(0, 0, 1, 3)); // -X -X Y W
- V3 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(2, 1, 0, 3))); // Z Y X W
- V1 = _mm_xor_ps(V1, b3vMPPP); // change the sign of the first element
-
- V11 = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 1, 0, 3))); // Y Y X W
- V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
- V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(0, 2, 0, 3)); // X Z -X -W
-
- V2 = V2 * V1; //
- V1 = V1 * V11; //
- V3 = V3 * V31; //
-
- V11 = _mm_shuffle_ps(NQ, Q, B3_SHUFFLE(2, 3, 1, 3)); // -Z -W Y W
- V11 = V11 * V21; //
- V21 = _mm_xor_ps(V21, b3vMPPP); // change the sign of the first element
- V31 = _mm_shuffle_ps(Q, NQ, B3_SHUFFLE(3, 3, 1, 3)); // W W -Y -W
- V31 = _mm_xor_ps(V31, b3vMPPP); // change the sign of the first element
- Y = b3CastiTo128f(_mm_shuffle_epi32(NQi, B3_SHUFFLE(3, 2, 0, 3))); // -W -Z -X -W
- Z = b3CastiTo128f(_mm_shuffle_epi32(Qi, B3_SHUFFLE(1, 0, 1, 3))); // Y X Y W
-
- vs = _mm_load_ss(&s);
- V21 = V21 * Y;
- V31 = V31 * Z;
-
- V1 = V1 + V11;
- V2 = V2 + V21;
- V3 = V3 + V31;
-
- vs = b3_splat3_ps(vs, 0);
- // s ready
- V1 = V1 * vs;
- V2 = V2 * vs;
- V3 = V3 * vs;
-
- V1 = V1 + b3v1000;
- V2 = V2 + b3v0100;
- V3 = V3 + b3v0010;
-
- m_el[0] = b3MakeVector3(V1);
- m_el[1] = b3MakeVector3(V2);
- m_el[2] = b3MakeVector3(V3);
-#else
- b3Scalar xs = q.getX() * s, ys = q.getY() * s, zs = q.getZ() * s;
- b3Scalar wx = q.getW() * xs, wy = q.getW() * ys, wz = q.getW() * zs;
- b3Scalar xx = q.getX() * xs, xy = q.getX() * ys, xz = q.getX() * zs;
- b3Scalar yy = q.getY() * ys, yz = q.getY() * zs, zz = q.getZ() * zs;
- setValue(
- b3Scalar(1.0) - (yy + zz), xy - wz, xz + wy,
- xy + wz, b3Scalar(1.0) - (xx + zz), yz - wx,
- xz - wy, yz + wx, b3Scalar(1.0) - (xx + yy));
-#endif
- }
-
- /** @brief Set the matrix from euler angles using YPR around YXZ respectively
- * @param yaw Yaw about Y axis
- * @param pitch Pitch about X axis
- * @param roll Roll about Z axis
- */
- void setEulerYPR(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
- {
- setEulerZYX(roll, pitch, yaw);
- }
-
- /** @brief Set the matrix from euler angles YPR around ZYX axes
- * @param eulerX Roll about X axis
- * @param eulerY Pitch around Y axis
- * @param eulerZ Yaw aboud Z axis
- *
- * These angles are used to produce a rotation matrix. The euler
- * angles are applied in ZYX order. I.e a vector is first rotated
- * about X then Y and then Z
- **/
- void setEulerZYX(b3Scalar eulerX, b3Scalar eulerY, b3Scalar eulerZ)
- {
- ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
- b3Scalar ci(b3Cos(eulerX));
- b3Scalar cj(b3Cos(eulerY));
- b3Scalar ch(b3Cos(eulerZ));
- b3Scalar si(b3Sin(eulerX));
- b3Scalar sj(b3Sin(eulerY));
- b3Scalar sh(b3Sin(eulerZ));
- b3Scalar cc = ci * ch;
- b3Scalar cs = ci * sh;
- b3Scalar sc = si * ch;
- b3Scalar ss = si * sh;
-
- setValue(cj * ch, sj * sc - cs, sj * cc + ss,
- cj * sh, sj * ss + cc, sj * cs - sc,
- -sj, cj * si, cj * ci);
- }
-
- /**@brief Set the matrix to the identity */
- void setIdentity()
- {
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- m_el[0] = b3MakeVector3(b3v1000);
- m_el[1] = b3MakeVector3(b3v0100);
- m_el[2] = b3MakeVector3(b3v0010);
-#else
- setValue(b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
-#endif
- }
-
- static const b3Matrix3x3& getIdentity()
- {
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- static const b3Matrix3x3
- identityMatrix(b3v1000, b3v0100, b3v0010);
-#else
- static const b3Matrix3x3
- identityMatrix(
- b3Scalar(1.0), b3Scalar(0.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(1.0), b3Scalar(0.0),
- b3Scalar(0.0), b3Scalar(0.0), b3Scalar(1.0));
-#endif
- return identityMatrix;
- }
-
- /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
- * @param m The array to be filled */
- void getOpenGLSubMatrix(b3Scalar * m) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128* vm = (__m128*)m;
- __m128 vT;
-
- v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
- v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
-#elif defined(B3_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
- float32x4_t* vm = (float32x4_t*)m;
- float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
- float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
- float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
- float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
-#else
- m[0] = b3Scalar(m_el[0].getX());
- m[1] = b3Scalar(m_el[1].getX());
- m[2] = b3Scalar(m_el[2].getX());
- m[3] = b3Scalar(0.0);
- m[4] = b3Scalar(m_el[0].getY());
- m[5] = b3Scalar(m_el[1].getY());
- m[6] = b3Scalar(m_el[2].getY());
- m[7] = b3Scalar(0.0);
- m[8] = b3Scalar(m_el[0].getZ());
- m[9] = b3Scalar(m_el[1].getZ());
- m[10] = b3Scalar(m_el[2].getZ());
- m[11] = b3Scalar(0.0);
-#endif
- }
-
- /**@brief Get the matrix represented as a quaternion
- * @param q The quaternion which will be set */
- void getRotation(b3Quaternion & q) const
- {
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
- b3Scalar s, x;
-
- union {
- b3SimdFloat4 vec;
- b3Scalar f[4];
- } temp;
-
- if (trace > b3Scalar(0.0))
- {
- x = trace + b3Scalar(1.0);
-
- temp.f[0] = m_el[2].getY() - m_el[1].getZ();
- temp.f[1] = m_el[0].getZ() - m_el[2].getX();
- temp.f[2] = m_el[1].getX() - m_el[0].getY();
- temp.f[3] = x;
- //temp.f[3]= s * b3Scalar(0.5);
- }
- else
- {
- int i, j, k;
- if (m_el[0].getX() < m_el[1].getY())
- {
- if (m_el[1].getY() < m_el[2].getZ())
- {
- i = 2;
- j = 0;
- k = 1;
- }
- else
- {
- i = 1;
- j = 2;
- k = 0;
- }
- }
- else
- {
- if (m_el[0].getX() < m_el[2].getZ())
- {
- i = 2;
- j = 0;
- k = 1;
- }
- else
- {
- i = 0;
- j = 1;
- k = 2;
- }
- }
-
- x = m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0);
-
- temp.f[3] = (m_el[k][j] - m_el[j][k]);
- temp.f[j] = (m_el[j][i] + m_el[i][j]);
- temp.f[k] = (m_el[k][i] + m_el[i][k]);
- temp.f[i] = x;
- //temp.f[i] = s * b3Scalar(0.5);
- }
-
- s = b3Sqrt(x);
- q.set128(temp.vec);
- s = b3Scalar(0.5) / s;
-
- q *= s;
-#else
- b3Scalar trace = m_el[0].getX() + m_el[1].getY() + m_el[2].getZ();
-
- b3Scalar temp[4];
-
- if (trace > b3Scalar(0.0))
- {
- b3Scalar s = b3Sqrt(trace + b3Scalar(1.0));
- temp[3] = (s * b3Scalar(0.5));
- s = b3Scalar(0.5) / s;
-
- temp[0] = ((m_el[2].getY() - m_el[1].getZ()) * s);
- temp[1] = ((m_el[0].getZ() - m_el[2].getX()) * s);
- temp[2] = ((m_el[1].getX() - m_el[0].getY()) * s);
- }
- else
- {
- int i = m_el[0].getX() < m_el[1].getY() ? (m_el[1].getY() < m_el[2].getZ() ? 2 : 1) : (m_el[0].getX() < m_el[2].getZ() ? 2 : 0);
- int j = (i + 1) % 3;
- int k = (i + 2) % 3;
-
- b3Scalar s = b3Sqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + b3Scalar(1.0));
- temp[i] = s * b3Scalar(0.5);
- s = b3Scalar(0.5) / s;
-
- temp[3] = (m_el[k][j] - m_el[j][k]) * s;
- temp[j] = (m_el[j][i] + m_el[i][j]) * s;
- temp[k] = (m_el[k][i] + m_el[i][k]) * s;
- }
- q.setValue(temp[0], temp[1], temp[2], temp[3]);
-#endif
- }
-
- /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
- * @param yaw Yaw around Y axis
- * @param pitch Pitch around X axis
- * @param roll around Z axis */
- void getEulerYPR(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll) const
- {
- // first use the normal calculus
- yaw = b3Scalar(b3Atan2(m_el[1].getX(), m_el[0].getX()));
- pitch = b3Scalar(b3Asin(-m_el[2].getX()));
- roll = b3Scalar(b3Atan2(m_el[2].getY(), m_el[2].getZ()));
-
- // on pitch = +/-HalfPI
- if (b3Fabs(pitch) == B3_HALF_PI)
- {
- if (yaw > 0)
- yaw -= B3_PI;
- else
- yaw += B3_PI;
-
- if (roll > 0)
- roll -= B3_PI;
- else
- roll += B3_PI;
- }
- };
-
- /**@brief Get the matrix represented as euler angles around ZYX
- * @param yaw Yaw around X axis
- * @param pitch Pitch around Y axis
- * @param roll around X axis
- * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
- void getEulerZYX(b3Scalar & yaw, b3Scalar & pitch, b3Scalar & roll, unsigned int solution_number = 1) const
- {
- struct Euler
- {
- b3Scalar yaw;
- b3Scalar pitch;
- b3Scalar roll;
- };
-
- Euler euler_out;
- Euler euler_out2; //second solution
- //get the pointer to the raw data
-
- // Check that pitch is not at a singularity
- if (b3Fabs(m_el[2].getX()) >= 1)
- {
- euler_out.yaw = 0;
- euler_out2.yaw = 0;
-
- // From difference of angles formula
- b3Scalar delta = b3Atan2(m_el[0].getX(), m_el[0].getZ());
- if (m_el[2].getX() > 0) //gimbal locked up
- {
- euler_out.pitch = B3_PI / b3Scalar(2.0);
- euler_out2.pitch = B3_PI / b3Scalar(2.0);
- euler_out.roll = euler_out.pitch + delta;
- euler_out2.roll = euler_out.pitch + delta;
- }
- else // gimbal locked down
- {
- euler_out.pitch = -B3_PI / b3Scalar(2.0);
- euler_out2.pitch = -B3_PI / b3Scalar(2.0);
- euler_out.roll = -euler_out.pitch + delta;
- euler_out2.roll = -euler_out.pitch + delta;
- }
- }
- else
- {
- euler_out.pitch = -b3Asin(m_el[2].getX());
- euler_out2.pitch = B3_PI - euler_out.pitch;
-
- euler_out.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out.pitch),
- m_el[2].getZ() / b3Cos(euler_out.pitch));
- euler_out2.roll = b3Atan2(m_el[2].getY() / b3Cos(euler_out2.pitch),
- m_el[2].getZ() / b3Cos(euler_out2.pitch));
-
- euler_out.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out.pitch),
- m_el[0].getX() / b3Cos(euler_out.pitch));
- euler_out2.yaw = b3Atan2(m_el[1].getX() / b3Cos(euler_out2.pitch),
- m_el[0].getX() / b3Cos(euler_out2.pitch));
- }
-
- if (solution_number == 1)
- {
- yaw = euler_out.yaw;
- pitch = euler_out.pitch;
- roll = euler_out.roll;
- }
- else
- {
- yaw = euler_out2.yaw;
- pitch = euler_out2.pitch;
- roll = euler_out2.roll;
- }
- }
-
- /**@brief Create a scaled copy of the matrix
- * @param s Scaling vector The elements of the vector will scale each column */
-
- b3Matrix3x3 scaled(const b3Vector3& s) const
- {
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- return b3Matrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
-#else
- return b3Matrix3x3(
- m_el[0].getX() * s.getX(), m_el[0].getY() * s.getY(), m_el[0].getZ() * s.getZ(),
- m_el[1].getX() * s.getX(), m_el[1].getY() * s.getY(), m_el[1].getZ() * s.getZ(),
- m_el[2].getX() * s.getX(), m_el[2].getY() * s.getY(), m_el[2].getZ() * s.getZ());
-#endif
- }
-
- /**@brief Return the determinant of the matrix */
- b3Scalar determinant() const;
- /**@brief Return the adjoint of the matrix */
- b3Matrix3x3 adjoint() const;
- /**@brief Return the matrix with all values non negative */
- b3Matrix3x3 absolute() const;
- /**@brief Return the transpose of the matrix */
- b3Matrix3x3 transpose() const;
- /**@brief Return the inverse of the matrix */
- b3Matrix3x3 inverse() const;
-
- b3Matrix3x3 transposeTimes(const b3Matrix3x3& m) const;
- b3Matrix3x3 timesTranspose(const b3Matrix3x3& m) const;
-
- B3_FORCE_INLINE b3Scalar tdotx(const b3Vector3& v) const
- {
- return m_el[0].getX() * v.getX() + m_el[1].getX() * v.getY() + m_el[2].getX() * v.getZ();
- }
- B3_FORCE_INLINE b3Scalar tdoty(const b3Vector3& v) const
- {
- return m_el[0].getY() * v.getX() + m_el[1].getY() * v.getY() + m_el[2].getY() * v.getZ();
- }
- B3_FORCE_INLINE b3Scalar tdotz(const b3Vector3& v) const
- {
- return m_el[0].getZ() * v.getX() + m_el[1].getZ() * v.getY() + m_el[2].getZ() * v.getZ();
- }
-
- /**@brief diagonalizes this matrix by the Jacobi method.
- * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
- * coordinate system, i.e., old_this = rot * new_this * rot^T.
- * @param threshold See iteration
- * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied
- * by the sum of the absolute values of the diagonal, or when maxSteps have been executed.
- *
- * Note that this matrix is assumed to be symmetric.
- */
- void diagonalize(b3Matrix3x3 & rot, b3Scalar threshold, int maxSteps)
- {
- rot.setIdentity();
- for (int step = maxSteps; step > 0; step--)
- {
- // find off-diagonal element [p][q] with largest magnitude
- int p = 0;
- int q = 1;
- int r = 2;
- b3Scalar max = b3Fabs(m_el[0][1]);
- b3Scalar v = b3Fabs(m_el[0][2]);
- if (v > max)
- {
- q = 2;
- r = 1;
- max = v;
- }
- v = b3Fabs(m_el[1][2]);
- if (v > max)
- {
- p = 1;
- q = 2;
- r = 0;
- max = v;
- }
-
- b3Scalar t = threshold * (b3Fabs(m_el[0][0]) + b3Fabs(m_el[1][1]) + b3Fabs(m_el[2][2]));
- if (max <= t)
- {
- if (max <= B3_EPSILON * t)
- {
- return;
- }
- step = 1;
- }
-
- // compute Jacobi rotation J which leads to a zero for element [p][q]
- b3Scalar mpq = m_el[p][q];
- b3Scalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
- b3Scalar theta2 = theta * theta;
- b3Scalar cos;
- b3Scalar sin;
- if (theta2 * theta2 < b3Scalar(10 / B3_EPSILON))
- {
- t = (theta >= 0) ? 1 / (theta + b3Sqrt(1 + theta2))
- : 1 / (theta - b3Sqrt(1 + theta2));
- cos = 1 / b3Sqrt(1 + t * t);
- sin = cos * t;
- }
- else
- {
- // approximation for large theta-value, i.e., a nearly diagonal matrix
- t = 1 / (theta * (2 + b3Scalar(0.5) / theta2));
- cos = 1 - b3Scalar(0.5) * t * t;
- sin = cos * t;
- }
-
- // apply rotation to matrix (this = J^T * this * J)
- m_el[p][q] = m_el[q][p] = 0;
- m_el[p][p] -= t * mpq;
- m_el[q][q] += t * mpq;
- b3Scalar mrp = m_el[r][p];
- b3Scalar mrq = m_el[r][q];
- m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
- m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
-
- // apply rotation to rot (rot = rot * J)
- for (int i = 0; i < 3; i++)
- {
- b3Vector3& row = rot[i];
- mrp = row[p];
- mrq = row[q];
- row[p] = cos * mrp - sin * mrq;
- row[q] = cos * mrq + sin * mrp;
- }
- }
- }
-
- /**@brief Calculate the matrix cofactor
- * @param r1 The first row to use for calculating the cofactor
- * @param c1 The first column to use for calculating the cofactor
- * @param r1 The second row to use for calculating the cofactor
- * @param c1 The second column to use for calculating the cofactor
- * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
- */
- b3Scalar cofac(int r1, int c1, int r2, int c2) const
- {
- return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
- }
-
- void serialize(struct b3Matrix3x3Data & dataOut) const;
-
- void serializeFloat(struct b3Matrix3x3FloatData & dataOut) const;
-
- void deSerialize(const struct b3Matrix3x3Data& dataIn);
-
- void deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn);
-
- void deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn);
-};
-
-B3_FORCE_INLINE b3Matrix3x3&
-b3Matrix3x3::operator*=(const b3Matrix3x3& m)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 rv00, rv01, rv02;
- __m128 rv10, rv11, rv12;
- __m128 rv20, rv21, rv22;
- __m128 mv0, mv1, mv2;
-
- rv02 = m_el[0].mVec128;
- rv12 = m_el[1].mVec128;
- rv22 = m_el[2].mVec128;
-
- mv0 = _mm_and_ps(m[0].mVec128, b3vFFF0fMask);
- mv1 = _mm_and_ps(m[1].mVec128, b3vFFF0fMask);
- mv2 = _mm_and_ps(m[2].mVec128, b3vFFF0fMask);
-
- // rv0
- rv00 = b3_splat_ps(rv02, 0);
- rv01 = b3_splat_ps(rv02, 1);
- rv02 = b3_splat_ps(rv02, 2);
-
- rv00 = _mm_mul_ps(rv00, mv0);
- rv01 = _mm_mul_ps(rv01, mv1);
- rv02 = _mm_mul_ps(rv02, mv2);
-
- // rv1
- rv10 = b3_splat_ps(rv12, 0);
- rv11 = b3_splat_ps(rv12, 1);
- rv12 = b3_splat_ps(rv12, 2);
-
- rv10 = _mm_mul_ps(rv10, mv0);
- rv11 = _mm_mul_ps(rv11, mv1);
- rv12 = _mm_mul_ps(rv12, mv2);
-
- // rv2
- rv20 = b3_splat_ps(rv22, 0);
- rv21 = b3_splat_ps(rv22, 1);
- rv22 = b3_splat_ps(rv22, 2);
-
- rv20 = _mm_mul_ps(rv20, mv0);
- rv21 = _mm_mul_ps(rv21, mv1);
- rv22 = _mm_mul_ps(rv22, mv2);
-
- rv00 = _mm_add_ps(rv00, rv01);
- rv10 = _mm_add_ps(rv10, rv11);
- rv20 = _mm_add_ps(rv20, rv21);
-
- m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
- m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
- m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m_el[0].mVec128;
- v1 = m_el[1].mVec128;
- v2 = m_el[2].mVec128;
-
- mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
- mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
- mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- m_el[0].mVec128 = rv0;
- m_el[1].mVec128 = rv1;
- m_el[2].mVec128 = rv2;
-#else
- setValue(
- m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
- m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
- m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
-#endif
- return *this;
-}
-
-B3_FORCE_INLINE b3Matrix3x3&
-b3Matrix3x3::operator+=(const b3Matrix3x3& m)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
-#else
- setValue(
- m_el[0][0] + m.m_el[0][0],
- m_el[0][1] + m.m_el[0][1],
- m_el[0][2] + m.m_el[0][2],
- m_el[1][0] + m.m_el[1][0],
- m_el[1][1] + m.m_el[1][1],
- m_el[1][2] + m.m_el[1][2],
- m_el[2][0] + m.m_el[2][0],
- m_el[2][1] + m.m_el[2][1],
- m_el[2][2] + m.m_el[2][2]);
-#endif
- return *this;
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-operator*(const b3Matrix3x3& m, const b3Scalar& k)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- __m128 vk = b3_splat_ps(_mm_load_ss((float*)&k), 0x80);
- return b3Matrix3x3(
- _mm_mul_ps(m[0].mVec128, vk),
- _mm_mul_ps(m[1].mVec128, vk),
- _mm_mul_ps(m[2].mVec128, vk));
-#elif defined(B3_USE_NEON)
- return b3Matrix3x3(
- vmulq_n_f32(m[0].mVec128, k),
- vmulq_n_f32(m[1].mVec128, k),
- vmulq_n_f32(m[2].mVec128, k));
-#else
- return b3Matrix3x3(
- m[0].getX() * k, m[0].getY() * k, m[0].getZ() * k,
- m[1].getX() * k, m[1].getY() * k, m[1].getZ() * k,
- m[2].getX() * k, m[2].getY() * k, m[2].getZ() * k);
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-operator+(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- return b3Matrix3x3(
- m1[0].mVec128 + m2[0].mVec128,
- m1[1].mVec128 + m2[1].mVec128,
- m1[2].mVec128 + m2[2].mVec128);
-#else
- return b3Matrix3x3(
- m1[0][0] + m2[0][0],
- m1[0][1] + m2[0][1],
- m1[0][2] + m2[0][2],
-
- m1[1][0] + m2[1][0],
- m1[1][1] + m2[1][1],
- m1[1][2] + m2[1][2],
-
- m1[2][0] + m2[2][0],
- m1[2][1] + m2[2][1],
- m1[2][2] + m2[2][2]);
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-operator-(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- return b3Matrix3x3(
- m1[0].mVec128 - m2[0].mVec128,
- m1[1].mVec128 - m2[1].mVec128,
- m1[2].mVec128 - m2[2].mVec128);
-#else
- return b3Matrix3x3(
- m1[0][0] - m2[0][0],
- m1[0][1] - m2[0][1],
- m1[0][2] - m2[0][2],
-
- m1[1][0] - m2[1][0],
- m1[1][1] - m2[1][1],
- m1[1][2] - m2[1][2],
-
- m1[2][0] - m2[2][0],
- m1[2][1] - m2[2][1],
- m1[2][2] - m2[2][2]);
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3&
-b3Matrix3x3::operator-=(const b3Matrix3x3& m)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
-#else
- setValue(
- m_el[0][0] - m.m_el[0][0],
- m_el[0][1] - m.m_el[0][1],
- m_el[0][2] - m.m_el[0][2],
- m_el[1][0] - m.m_el[1][0],
- m_el[1][1] - m.m_el[1][1],
- m_el[1][2] - m.m_el[1][2],
- m_el[2][0] - m.m_el[2][0],
- m_el[2][1] - m.m_el[2][1],
- m_el[2][2] - m.m_el[2][2]);
-#endif
- return *this;
-}
-
-B3_FORCE_INLINE b3Scalar
-b3Matrix3x3::determinant() const
-{
- return b3Triple((*this)[0], (*this)[1], (*this)[2]);
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::absolute() const
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- return b3Matrix3x3(
- _mm_and_ps(m_el[0].mVec128, b3vAbsfMask),
- _mm_and_ps(m_el[1].mVec128, b3vAbsfMask),
- _mm_and_ps(m_el[2].mVec128, b3vAbsfMask));
-#elif defined(B3_USE_NEON)
- return b3Matrix3x3(
- (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, b3v3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, b3v3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, b3v3AbsMask));
-#else
- return b3Matrix3x3(
- b3Fabs(m_el[0].getX()), b3Fabs(m_el[0].getY()), b3Fabs(m_el[0].getZ()),
- b3Fabs(m_el[1].getX()), b3Fabs(m_el[1].getY()), b3Fabs(m_el[1].getZ()),
- b3Fabs(m_el[2].getX()), b3Fabs(m_el[2].getY()), b3Fabs(m_el[2].getZ()));
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::transpose() const
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 vT;
-
- v2 = _mm_and_ps(v2, b3vFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, B3_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
- v2 = b3CastdTo128f(_mm_move_sd(b3CastfTo128d(v2), b3CastfTo128d(vT))); // z0 z1 z2 0
-
- return b3Matrix3x3(v0, v1, v2);
-#elif defined(B3_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t){-1, 0};
- float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
- float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
- float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
- float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
- return b3Matrix3x3(v0, v1, v2);
-#else
- return b3Matrix3x3(m_el[0].getX(), m_el[1].getX(), m_el[2].getX(),
- m_el[0].getY(), m_el[1].getY(), m_el[2].getY(),
- m_el[0].getZ(), m_el[1].getZ(), m_el[2].getZ());
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::adjoint() const
-{
- return b3Matrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
- cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
- cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::inverse() const
-{
- b3Vector3 co = b3MakeVector3(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
- b3Scalar det = (*this)[0].dot(co);
- b3FullAssert(det != b3Scalar(0.0));
- b3Scalar s = b3Scalar(1.0) / det;
- return b3Matrix3x3(co.getX() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
- co.getY() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
- co.getZ() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::transposeTimes(const b3Matrix3x3& m) const
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- // zeros w
- // static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
- __m128 row = m_el[0].mVec128;
- __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, b3vFFF0fMask);
- __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, b3vFFF0fMask);
- __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, b3vFFF0fMask);
- __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
- __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
- __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
- row = m_el[1].mVec128;
- r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
- row = m_el[2].mVec128;
- r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
- return b3Matrix3x3(r0, r1, r2);
-
-#elif defined B3_USE_NEON
- // zeros w
- static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
- float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
- float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
- float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
- float32x4_t row = m_el[0].mVec128;
- float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
- float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
- float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
- row = m_el[1].mVec128;
- r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
- row = m_el[2].mVec128;
- r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
- return b3Matrix3x3(r0, r1, r2);
-#else
- return b3Matrix3x3(
- m_el[0].getX() * m[0].getX() + m_el[1].getX() * m[1].getX() + m_el[2].getX() * m[2].getX(),
- m_el[0].getX() * m[0].getY() + m_el[1].getX() * m[1].getY() + m_el[2].getX() * m[2].getY(),
- m_el[0].getX() * m[0].getZ() + m_el[1].getX() * m[1].getZ() + m_el[2].getX() * m[2].getZ(),
- m_el[0].getY() * m[0].getX() + m_el[1].getY() * m[1].getX() + m_el[2].getY() * m[2].getX(),
- m_el[0].getY() * m[0].getY() + m_el[1].getY() * m[1].getY() + m_el[2].getY() * m[2].getY(),
- m_el[0].getY() * m[0].getZ() + m_el[1].getY() * m[1].getZ() + m_el[2].getY() * m[2].getZ(),
- m_el[0].getZ() * m[0].getX() + m_el[1].getZ() * m[1].getX() + m_el[2].getZ() * m[2].getX(),
- m_el[0].getZ() * m[0].getY() + m_el[1].getZ() * m[1].getY() + m_el[2].getZ() * m[2].getY(),
- m_el[0].getZ() * m[0].getZ() + m_el[1].getZ() * m[1].getZ() + m_el[2].getZ() * m[2].getZ());
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-b3Matrix3x3::timesTranspose(const b3Matrix3x3& m) const
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- __m128 a0 = m_el[0].mVec128;
- __m128 a1 = m_el[1].mVec128;
- __m128 a2 = m_el[2].mVec128;
-
- b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- __m128 mx = mT[0].mVec128;
- __m128 my = mT[1].mVec128;
- __m128 mz = mT[2].mVec128;
-
- __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
- __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
- __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
- r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
- r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
- return b3Matrix3x3(r0, r1, r2);
-
-#elif defined B3_USE_NEON
- float32x4_t a0 = m_el[0].mVec128;
- float32x4_t a1 = m_el[1].mVec128;
- float32x4_t a2 = m_el[2].mVec128;
-
- b3Matrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- float32x4_t mx = mT[0].mVec128;
- float32x4_t my = mT[1].mVec128;
- float32x4_t mz = mT[2].mVec128;
-
- float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
- float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
- float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
- r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
- r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
- r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
- r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
- r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
- r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
- return b3Matrix3x3(r0, r1, r2);
-
-#else
- return b3Matrix3x3(
- m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
- m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
- m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
-#endif
-}
-
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Matrix3x3& m, const b3Vector3& v)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- return v.dot3(m[0], m[1], m[2]);
-#else
- return b3MakeVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
-#endif
-}
-
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Vector3& v, const b3Matrix3x3& m)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
-
- const __m128 vv = v.mVec128;
-
- __m128 c0 = b3_splat_ps(vv, 0);
- __m128 c1 = b3_splat_ps(vv, 1);
- __m128 c2 = b3_splat_ps(vv, 2);
-
- c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, b3vFFF0fMask));
- c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, b3vFFF0fMask));
- c0 = _mm_add_ps(c0, c1);
- c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, b3vFFF0fMask));
-
- return b3MakeVector3(_mm_add_ps(c0, c2));
-#elif defined(B3_USE_NEON)
- const float32x4_t vv = v.mVec128;
- const float32x2_t vlo = vget_low_f32(vv);
- const float32x2_t vhi = vget_high_f32(vv);
-
- float32x4_t c0, c1, c2;
-
- c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, b3vFFF0Mask);
- c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, b3vFFF0Mask);
- c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, b3vFFF0Mask);
-
- c0 = vmulq_lane_f32(c0, vlo, 0);
- c1 = vmulq_lane_f32(c1, vlo, 1);
- c2 = vmulq_lane_f32(c2, vhi, 0);
- c0 = vaddq_f32(c0, c1);
- c0 = vaddq_f32(c0, c2);
-
- return b3MakeVector3(c0);
-#else
- return b3MakeVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
-#endif
-}
-
-B3_FORCE_INLINE b3Matrix3x3
-operator*(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
-
- __m128 m10 = m1[0].mVec128;
- __m128 m11 = m1[1].mVec128;
- __m128 m12 = m1[2].mVec128;
-
- __m128 m2v = _mm_and_ps(m2[0].mVec128, b3vFFF0fMask);
-
- __m128 c0 = b3_splat_ps(m10, 0);
- __m128 c1 = b3_splat_ps(m11, 0);
- __m128 c2 = b3_splat_ps(m12, 0);
-
- c0 = _mm_mul_ps(c0, m2v);
- c1 = _mm_mul_ps(c1, m2v);
- c2 = _mm_mul_ps(c2, m2v);
-
- m2v = _mm_and_ps(m2[1].mVec128, b3vFFF0fMask);
-
- __m128 c0_1 = b3_splat_ps(m10, 1);
- __m128 c1_1 = b3_splat_ps(m11, 1);
- __m128 c2_1 = b3_splat_ps(m12, 1);
-
- c0_1 = _mm_mul_ps(c0_1, m2v);
- c1_1 = _mm_mul_ps(c1_1, m2v);
- c2_1 = _mm_mul_ps(c2_1, m2v);
-
- m2v = _mm_and_ps(m2[2].mVec128, b3vFFF0fMask);
-
- c0 = _mm_add_ps(c0, c0_1);
- c1 = _mm_add_ps(c1, c1_1);
- c2 = _mm_add_ps(c2, c2_1);
-
- m10 = b3_splat_ps(m10, 2);
- m11 = b3_splat_ps(m11, 2);
- m12 = b3_splat_ps(m12, 2);
-
- m10 = _mm_mul_ps(m10, m2v);
- m11 = _mm_mul_ps(m11, m2v);
- m12 = _mm_mul_ps(m12, m2v);
-
- c0 = _mm_add_ps(c0, m10);
- c1 = _mm_add_ps(c1, m11);
- c2 = _mm_add_ps(c2, m12);
-
- return b3Matrix3x3(c0, c1, c2);
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m1[0].mVec128;
- v1 = m1[1].mVec128;
- v2 = m1[2].mVec128;
-
- mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, b3vFFF0Mask);
- mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, b3vFFF0Mask);
- mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, b3vFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- return b3Matrix3x3(rv0, rv1, rv2);
-
-#else
- return b3Matrix3x3(
- m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
- m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
- m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
-#endif
-}
-
-/*
-B3_FORCE_INLINE b3Matrix3x3 b3MultTransposeLeft(const b3Matrix3x3& m1, const b3Matrix3x3& m2) {
-return b3Matrix3x3(
-m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
-m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
-m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
-m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
-m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
-m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
-m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
-m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
-m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
-}
-*/
-
-/**@brief Equality operator between two matrices
-* It will test all elements are equal. */
-B3_FORCE_INLINE bool operator==(const b3Matrix3x3& m1, const b3Matrix3x3& m2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
-
- __m128 c0, c1, c2;
-
- c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
- c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
- c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
-
- c0 = _mm_and_ps(c0, c1);
- c0 = _mm_and_ps(c0, c2);
-
- return (0x7 == _mm_movemask_ps((__m128)c0));
-#else
- return (m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
- m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
- m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2]);
-#endif
-}
-
-///for serialization
-struct b3Matrix3x3FloatData
-{
- b3Vector3FloatData m_el[3];
-};
-
-///for serialization
-struct b3Matrix3x3DoubleData
-{
- b3Vector3DoubleData m_el[3];
-};
-
-B3_FORCE_INLINE void b3Matrix3x3::serialize(struct b3Matrix3x3Data& dataOut) const
-{
- for (int i = 0; i < 3; i++)
- m_el[i].serialize(dataOut.m_el[i]);
-}
-
-B3_FORCE_INLINE void b3Matrix3x3::serializeFloat(struct b3Matrix3x3FloatData& dataOut) const
-{
- for (int i = 0; i < 3; i++)
- m_el[i].serializeFloat(dataOut.m_el[i]);
-}
-
-B3_FORCE_INLINE void b3Matrix3x3::deSerialize(const struct b3Matrix3x3Data& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerialize(dataIn.m_el[i]);
-}
-
-B3_FORCE_INLINE void b3Matrix3x3::deSerializeFloat(const struct b3Matrix3x3FloatData& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerializeFloat(dataIn.m_el[i]);
-}
-
-B3_FORCE_INLINE void b3Matrix3x3::deSerializeDouble(const struct b3Matrix3x3DoubleData& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerializeDouble(dataIn.m_el[i]);
-}
-
-#endif //B3_MATRIX3x3_H
diff --git a/thirdparty/bullet/Bullet3Common/b3MinMax.h b/thirdparty/bullet/Bullet3Common/b3MinMax.h
deleted file mode 100644
index c09c3db3f5..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3MinMax.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_GEN_MINMAX_H
-#define B3_GEN_MINMAX_H
-
-#include "b3Scalar.h"
-
-template <class T>
-B3_FORCE_INLINE const T& b3Min(const T& a, const T& b)
-{
- return a < b ? a : b;
-}
-
-template <class T>
-B3_FORCE_INLINE const T& b3Max(const T& a, const T& b)
-{
- return a > b ? a : b;
-}
-
-template <class T>
-B3_FORCE_INLINE const T& b3Clamped(const T& a, const T& lb, const T& ub)
-{
- return a < lb ? lb : (ub < a ? ub : a);
-}
-
-template <class T>
-B3_FORCE_INLINE void b3SetMin(T& a, const T& b)
-{
- if (b < a)
- {
- a = b;
- }
-}
-
-template <class T>
-B3_FORCE_INLINE void b3SetMax(T& a, const T& b)
-{
- if (a < b)
- {
- a = b;
- }
-}
-
-template <class T>
-B3_FORCE_INLINE void b3Clamp(T& a, const T& lb, const T& ub)
-{
- if (a < lb)
- {
- a = lb;
- }
- else if (ub < a)
- {
- a = ub;
- }
-}
-
-#endif //B3_GEN_MINMAX_H
diff --git a/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h b/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h
deleted file mode 100644
index ed56bc627d..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3PoolAllocator.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef _BT_POOL_ALLOCATOR_H
-#define _BT_POOL_ALLOCATOR_H
-
-#include "b3Scalar.h"
-#include "b3AlignedAllocator.h"
-
-///The b3PoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
-class b3PoolAllocator
-{
- int m_elemSize;
- int m_maxElements;
- int m_freeCount;
- void* m_firstFree;
- unsigned char* m_pool;
-
-public:
- b3PoolAllocator(int elemSize, int maxElements)
- : m_elemSize(elemSize),
- m_maxElements(maxElements)
- {
- m_pool = (unsigned char*)b3AlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
-
- unsigned char* p = m_pool;
- m_firstFree = p;
- m_freeCount = m_maxElements;
- int count = m_maxElements;
- while (--count)
- {
- *(void**)p = (p + m_elemSize);
- p += m_elemSize;
- }
- *(void**)p = 0;
- }
-
- ~b3PoolAllocator()
- {
- b3AlignedFree(m_pool);
- }
-
- int getFreeCount() const
- {
- return m_freeCount;
- }
-
- int getUsedCount() const
- {
- return m_maxElements - m_freeCount;
- }
-
- int getMaxCount() const
- {
- return m_maxElements;
- }
-
- void* allocate(int size)
- {
- // release mode fix
- (void)size;
- b3Assert(!size || size <= m_elemSize);
- b3Assert(m_freeCount > 0);
- void* result = m_firstFree;
- m_firstFree = *(void**)m_firstFree;
- --m_freeCount;
- return result;
- }
-
- bool validPtr(void* ptr)
- {
- if (ptr)
- {
- if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
- {
- return true;
- }
- }
- return false;
- }
-
- void freeMemory(void* ptr)
- {
- if (ptr)
- {
- b3Assert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
-
- *(void**)ptr = m_firstFree;
- m_firstFree = ptr;
- ++m_freeCount;
- }
- }
-
- int getElementSize() const
- {
- return m_elemSize;
- }
-
- unsigned char* getPoolAddress()
- {
- return m_pool;
- }
-
- const unsigned char* getPoolAddress() const
- {
- return m_pool;
- }
-};
-
-#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/Bullet3Common/b3QuadWord.h b/thirdparty/bullet/Bullet3Common/b3QuadWord.h
deleted file mode 100644
index 0def305fac..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3QuadWord.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SIMD_QUADWORD_H
-#define B3_SIMD_QUADWORD_H
-
-#include "b3Scalar.h"
-#include "b3MinMax.h"
-
-#if defined(__CELLOS_LV2) && defined(__SPU__)
-#include <altivec.h>
-#endif
-
-/**@brief The b3QuadWord class is base class for b3Vector3 and b3Quaternion.
- * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
- */
-#ifndef USE_LIBSPE2
-B3_ATTRIBUTE_ALIGNED16(class)
-b3QuadWord
-#else
-class b3QuadWord
-#endif
-{
-protected:
-#if defined(__SPU__) && defined(__CELLOS_LV2__)
- union {
- vec_float4 mVec128;
- b3Scalar m_floats[4];
- };
-
-public:
- vec_float4 get128() const
- {
- return mVec128;
- }
-
-#else //__CELLOS_LV2__ __SPU__
-
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-public:
- union {
- b3SimdFloat4 mVec128;
- b3Scalar m_floats[4];
- struct
- {
- b3Scalar x, y, z, w;
- };
- };
-
-public:
- B3_FORCE_INLINE b3SimdFloat4 get128() const
- {
- return mVec128;
- }
- B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
- {
- mVec128 = v128;
- }
-#else
-public:
- union {
- b3Scalar m_floats[4];
- struct
- {
- b3Scalar x, y, z, w;
- };
- };
-#endif // B3_USE_SSE
-
-#endif //__CELLOS_LV2__ __SPU__
-
-public:
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-
- // Set Vector
- B3_FORCE_INLINE b3QuadWord(const b3SimdFloat4 vec)
- {
- mVec128 = vec;
- }
-
- // Copy constructor
- B3_FORCE_INLINE b3QuadWord(const b3QuadWord& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- // Assignment Operator
- B3_FORCE_INLINE b3QuadWord&
- operator=(const b3QuadWord& v)
- {
- mVec128 = v.mVec128;
-
- return *this;
- }
-
-#endif
-
- /**@brief Return the x value */
- B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
- /**@brief Set the y value */
- B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
- /**@brief Set the z value */
- B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
- /**@brief Set the w value */
- B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
- /**@brief Return the x value */
-
- //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
- //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
- ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
- B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
-
- B3_FORCE_INLINE bool operator==(const b3QuadWord& other) const
- {
-#ifdef B3_USE_SSE
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3] == other.m_floats[3]) &&
- (m_floats[2] == other.m_floats[2]) &&
- (m_floats[1] == other.m_floats[1]) &&
- (m_floats[0] == other.m_floats[0]));
-#endif
- }
-
- B3_FORCE_INLINE bool operator!=(const b3QuadWord& other) const
- {
- return !(*this == other);
- }
-
- /**@brief Set x,y,z and zero w
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = 0.f;
- }
-
- /* void getValue(b3Scalar *m) const
- {
- m[0] = m_floats[0];
- m[1] = m_floats[1];
- m[2] = m_floats[2];
- }
-*/
- /**@brief Set the values
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = _w;
- }
- /**@brief No initialization constructor */
- B3_FORCE_INLINE b3QuadWord()
- // :m_floats[0](b3Scalar(0.)),m_floats[1](b3Scalar(0.)),m_floats[2](b3Scalar(0.)),m_floats[3](b3Scalar(0.))
- {
- }
-
- /**@brief Three argument constructor (zeros w)
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
- B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
- }
-
- /**@brief Initializing constructor
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- B3_FORCE_INLINE b3QuadWord(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
- }
-
- /**@brief Set each element to the max of the current values and the values of another b3QuadWord
- * @param other The other b3QuadWord to compare with
- */
- B3_FORCE_INLINE void setMax(const b3QuadWord& other)
- {
-#ifdef B3_USE_SSE
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
-#else
- b3SetMax(m_floats[0], other.m_floats[0]);
- b3SetMax(m_floats[1], other.m_floats[1]);
- b3SetMax(m_floats[2], other.m_floats[2]);
- b3SetMax(m_floats[3], other.m_floats[3]);
-#endif
- }
- /**@brief Set each element to the min of the current values and the values of another b3QuadWord
- * @param other The other b3QuadWord to compare with
- */
- B3_FORCE_INLINE void setMin(const b3QuadWord& other)
- {
-#ifdef B3_USE_SSE
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
-#else
- b3SetMin(m_floats[0], other.m_floats[0]);
- b3SetMin(m_floats[1], other.m_floats[1]);
- b3SetMin(m_floats[2], other.m_floats[2]);
- b3SetMin(m_floats[3], other.m_floats[3]);
-#endif
- }
-};
-
-#endif //B3_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Quaternion.h b/thirdparty/bullet/Bullet3Common/b3Quaternion.h
deleted file mode 100644
index 4fdd72dcc4..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Quaternion.h
+++ /dev/null
@@ -1,908 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SIMD__QUATERNION_H_
-#define B3_SIMD__QUATERNION_H_
-
-#include "b3Vector3.h"
-#include "b3QuadWord.h"
-
-#ifdef B3_USE_SSE
-
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
-
-#endif
-
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-
-const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
-const b3SimdFloat4 B3_ATTRIBUTE_ALIGNED16(b3vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
-
-#endif
-
-/**@brief The b3Quaternion implements quaternion to perform linear algebra rotations in combination with b3Matrix3x3, b3Vector3 and b3Transform. */
-class b3Quaternion : public b3QuadWord
-{
-public:
- /**@brief No initialization constructor */
- b3Quaternion() {}
-
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)) || defined(B3_USE_NEON)
- // Set Vector
- B3_FORCE_INLINE b3Quaternion(const b3SimdFloat4 vec)
- {
- mVec128 = vec;
- }
-
- // Copy constructor
- B3_FORCE_INLINE b3Quaternion(const b3Quaternion& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- // Assignment Operator
- B3_FORCE_INLINE b3Quaternion&
- operator=(const b3Quaternion& v)
- {
- mVec128 = v.mVec128;
-
- return *this;
- }
-
-#endif
-
- // template <typename b3Scalar>
- // explicit Quaternion(const b3Scalar *v) : Tuple4<b3Scalar>(v) {}
- /**@brief Constructor from scalars */
- b3Quaternion(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
- : b3QuadWord(_x, _y, _z, _w)
- {
- //b3Assert(!((_x==1.f) && (_y==0.f) && (_z==0.f) && (_w==0.f)));
- }
- /**@brief Axis angle Constructor
- * @param axis The axis which the rotation is around
- * @param angle The magnitude of the rotation around the angle (Radians) */
- b3Quaternion(const b3Vector3& _axis, const b3Scalar& _angle)
- {
- setRotation(_axis, _angle);
- }
- /**@brief Constructor from Euler angles
- * @param yaw Angle around Y unless B3_EULER_DEFAULT_ZYX defined then Z
- * @param pitch Angle around X unless B3_EULER_DEFAULT_ZYX defined then Y
- * @param roll Angle around Z unless B3_EULER_DEFAULT_ZYX defined then X */
- b3Quaternion(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
- {
-#ifndef B3_EULER_DEFAULT_ZYX
- setEuler(yaw, pitch, roll);
-#else
- setEulerZYX(yaw, pitch, roll);
-#endif
- }
- /**@brief Set the rotation using axis angle notation
- * @param axis The axis around which to rotate
- * @param angle The magnitude of the rotation in Radians */
- void setRotation(const b3Vector3& axis1, const b3Scalar& _angle)
- {
- b3Vector3 axis = axis1;
- axis.safeNormalize();
-
- b3Scalar d = axis.length();
- b3Assert(d != b3Scalar(0.0));
- if (d < B3_EPSILON)
- {
- setValue(0, 0, 0, 1);
- }
- else
- {
- b3Scalar s = b3Sin(_angle * b3Scalar(0.5)) / d;
- setValue(axis.getX() * s, axis.getY() * s, axis.getZ() * s,
- b3Cos(_angle * b3Scalar(0.5)));
- }
- }
- /**@brief Set the quaternion using Euler angles
- * @param yaw Angle around Y
- * @param pitch Angle around X
- * @param roll Angle around Z */
- void setEuler(const b3Scalar& yaw, const b3Scalar& pitch, const b3Scalar& roll)
- {
- b3Scalar halfYaw = b3Scalar(yaw) * b3Scalar(0.5);
- b3Scalar halfPitch = b3Scalar(pitch) * b3Scalar(0.5);
- b3Scalar halfRoll = b3Scalar(roll) * b3Scalar(0.5);
- b3Scalar cosYaw = b3Cos(halfYaw);
- b3Scalar sinYaw = b3Sin(halfYaw);
- b3Scalar cosPitch = b3Cos(halfPitch);
- b3Scalar sinPitch = b3Sin(halfPitch);
- b3Scalar cosRoll = b3Cos(halfRoll);
- b3Scalar sinRoll = b3Sin(halfRoll);
- setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
- sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
- }
-
- /**@brief Set the quaternion using euler angles
- * @param yaw Angle around Z
- * @param pitch Angle around Y
- * @param roll Angle around X */
- void setEulerZYX(const b3Scalar& yawZ, const b3Scalar& pitchY, const b3Scalar& rollX)
- {
- b3Scalar halfYaw = b3Scalar(yawZ) * b3Scalar(0.5);
- b3Scalar halfPitch = b3Scalar(pitchY) * b3Scalar(0.5);
- b3Scalar halfRoll = b3Scalar(rollX) * b3Scalar(0.5);
- b3Scalar cosYaw = b3Cos(halfYaw);
- b3Scalar sinYaw = b3Sin(halfYaw);
- b3Scalar cosPitch = b3Cos(halfPitch);
- b3Scalar sinPitch = b3Sin(halfPitch);
- b3Scalar cosRoll = b3Cos(halfRoll);
- b3Scalar sinRoll = b3Sin(halfRoll);
- setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
- cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
- normalize();
- }
-
- /**@brief Get the euler angles from this quaternion
- * @param yaw Angle around Z
- * @param pitch Angle around Y
- * @param roll Angle around X */
- void getEulerZYX(b3Scalar& yawZ, b3Scalar& pitchY, b3Scalar& rollX) const
- {
- b3Scalar squ;
- b3Scalar sqx;
- b3Scalar sqy;
- b3Scalar sqz;
- b3Scalar sarg;
- sqx = m_floats[0] * m_floats[0];
- sqy = m_floats[1] * m_floats[1];
- sqz = m_floats[2] * m_floats[2];
- squ = m_floats[3] * m_floats[3];
- rollX = b3Atan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
- sarg = b3Scalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
- pitchY = sarg <= b3Scalar(-1.0) ? b3Scalar(-0.5) * B3_PI : (sarg >= b3Scalar(1.0) ? b3Scalar(0.5) * B3_PI : b3Asin(sarg));
- yawZ = b3Atan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
- }
-
- /**@brief Add two quaternions
- * @param q The quaternion to add to this one */
- B3_FORCE_INLINE b3Quaternion& operator+=(const b3Quaternion& q)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_add_ps(mVec128, q.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vaddq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] += q.getX();
- m_floats[1] += q.getY();
- m_floats[2] += q.getZ();
- m_floats[3] += q.m_floats[3];
-#endif
- return *this;
- }
-
- /**@brief Subtract out a quaternion
- * @param q The quaternion to subtract from this one */
- b3Quaternion& operator-=(const b3Quaternion& q)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_sub_ps(mVec128, q.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vsubq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] -= q.getX();
- m_floats[1] -= q.getY();
- m_floats[2] -= q.getZ();
- m_floats[3] -= q.m_floats[3];
-#endif
- return *this;
- }
-
- /**@brief Scale this quaternion
- * @param s The scalar to scale by */
- b3Quaternion& operator*=(const b3Scalar& s)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0); // (S S S S)
- mVec128 = _mm_mul_ps(mVec128, vs);
-#elif defined(B3_USE_NEON)
- mVec128 = vmulq_n_f32(mVec128, s);
-#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
- m_floats[3] *= s;
-#endif
- return *this;
- }
-
- /**@brief Multiply this quaternion by q on the right
- * @param q The other quaternion
- * Equivilant to this = this * q */
- b3Quaternion& operator*=(const b3Quaternion& q)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vQ2 = q.get128();
-
- __m128 A1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(0, 1, 2, 0));
- __m128 B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0));
-
- A1 = A1 * B1;
-
- __m128 A2 = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 1));
- __m128 B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- B1 = b3_pshufd_ps(mVec128, B3_SHUFFLE(2, 0, 1, 2));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
-
- B1 = B1 * B2; // A3 *= B3
-
- mVec128 = b3_splat_ps(mVec128, 3); // A0
- mVec128 = mVec128 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- mVec128 = mVec128 + A1; // AB03 + AB12
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t vQ1 = mVec128;
- float32x4_t vQ2 = q.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- mVec128 = A0;
-#else
- setValue(
- m_floats[3] * q.getX() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.getZ() - m_floats[2] * q.getY(),
- m_floats[3] * q.getY() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.getX() - m_floats[0] * q.getZ(),
- m_floats[3] * q.getZ() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.getY() - m_floats[1] * q.getX(),
- m_floats[3] * q.m_floats[3] - m_floats[0] * q.getX() - m_floats[1] * q.getY() - m_floats[2] * q.getZ());
-#endif
- return *this;
- }
- /**@brief Return the dot product between this quaternion and another
- * @param q The other quaternion */
- b3Scalar dot(const b3Quaternion& q) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vd;
-
- vd = _mm_mul_ps(mVec128, q.mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
- vd = _mm_add_ps(vd, t);
- t = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, t);
-
- return _mm_cvtss_f32(vd);
-#elif defined(B3_USE_NEON)
- float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
- x = vpadd_f32(x, x);
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * q.getX() +
- m_floats[1] * q.getY() +
- m_floats[2] * q.getZ() +
- m_floats[3] * q.m_floats[3];
-#endif
- }
-
- /**@brief Return the length squared of the quaternion */
- b3Scalar length2() const
- {
- return dot(*this);
- }
-
- /**@brief Return the length of the quaternion */
- b3Scalar length() const
- {
- return b3Sqrt(length2());
- }
-
- /**@brief Normalize the quaternion
- * Such that x^2 + y^2 + z^2 +w^2 = 1 */
- b3Quaternion& normalize()
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vd;
-
- vd = _mm_mul_ps(mVec128, mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
- vd = _mm_add_ps(vd, t);
- t = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, t);
-
- vd = _mm_sqrt_ss(vd);
- vd = _mm_div_ss(b3vOnes, vd);
- vd = b3_pshufd_ps(vd, 0); // splat
- mVec128 = _mm_mul_ps(mVec128, vd);
-
- return *this;
-#else
- return *this /= length();
-#endif
- }
-
- /**@brief Return a scaled version of this quaternion
- * @param s The scale factor */
- B3_FORCE_INLINE b3Quaternion
- operator*(const b3Scalar& s) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
-
- return b3Quaternion(_mm_mul_ps(mVec128, vs));
-#elif defined(B3_USE_NEON)
- return b3Quaternion(vmulq_n_f32(mVec128, s));
-#else
- return b3Quaternion(getX() * s, getY() * s, getZ() * s, m_floats[3] * s);
-#endif
- }
-
- /**@brief Return an inversely scaled versionof this quaternion
- * @param s The inverse scale factor */
- b3Quaternion operator/(const b3Scalar& s) const
- {
- b3Assert(s != b3Scalar(0.0));
- return *this * (b3Scalar(1.0) / s);
- }
-
- /**@brief Inversely scale this quaternion
- * @param s The scale factor */
- b3Quaternion& operator/=(const b3Scalar& s)
- {
- b3Assert(s != b3Scalar(0.0));
- return *this *= b3Scalar(1.0) / s;
- }
-
- /**@brief Return a normalized version of this quaternion */
- b3Quaternion normalized() const
- {
- return *this / length();
- }
- /**@brief Return the angle between this quaternion and the other
- * @param q The other quaternion */
- b3Scalar angle(const b3Quaternion& q) const
- {
- b3Scalar s = b3Sqrt(length2() * q.length2());
- b3Assert(s != b3Scalar(0.0));
- return b3Acos(dot(q) / s);
- }
- /**@brief Return the angle of rotation represented by this quaternion */
- b3Scalar getAngle() const
- {
- b3Scalar s = b3Scalar(2.) * b3Acos(m_floats[3]);
- return s;
- }
-
- /**@brief Return the axis of the rotation represented by this quaternion */
- b3Vector3 getAxis() const
- {
- b3Scalar s_squared = 1.f - m_floats[3] * m_floats[3];
-
- if (s_squared < b3Scalar(10.) * B3_EPSILON) //Check for divide by zero
- return b3MakeVector3(1.0, 0.0, 0.0); // Arbitrary
- b3Scalar s = 1.f / b3Sqrt(s_squared);
- return b3MakeVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
- }
-
- /**@brief Return the inverse of this quaternion */
- b3Quaternion inverse() const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3Quaternion(_mm_xor_ps(mVec128, b3vQInv));
-#elif defined(B3_USE_NEON)
- return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vQInv));
-#else
- return b3Quaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
-#endif
- }
-
- /**@brief Return the sum of this quaternion and the other
- * @param q2 The other quaternion */
- B3_FORCE_INLINE b3Quaternion
- operator+(const b3Quaternion& q2) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3Quaternion(_mm_add_ps(mVec128, q2.mVec128));
-#elif defined(B3_USE_NEON)
- return b3Quaternion(vaddq_f32(mVec128, q2.mVec128));
-#else
- const b3Quaternion& q1 = *this;
- return b3Quaternion(q1.getX() + q2.getX(), q1.getY() + q2.getY(), q1.getZ() + q2.getZ(), q1.m_floats[3] + q2.m_floats[3]);
-#endif
- }
-
- /**@brief Return the difference between this quaternion and the other
- * @param q2 The other quaternion */
- B3_FORCE_INLINE b3Quaternion
- operator-(const b3Quaternion& q2) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3Quaternion(_mm_sub_ps(mVec128, q2.mVec128));
-#elif defined(B3_USE_NEON)
- return b3Quaternion(vsubq_f32(mVec128, q2.mVec128));
-#else
- const b3Quaternion& q1 = *this;
- return b3Quaternion(q1.getX() - q2.getX(), q1.getY() - q2.getY(), q1.getZ() - q2.getZ(), q1.m_floats[3] - q2.m_floats[3]);
-#endif
- }
-
- /**@brief Return the negative of this quaternion
- * This simply negates each element */
- B3_FORCE_INLINE b3Quaternion operator-() const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3Quaternion(_mm_xor_ps(mVec128, b3vMzeroMask));
-#elif defined(B3_USE_NEON)
- return b3Quaternion((b3SimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)b3vMzeroMask));
-#else
- const b3Quaternion& q2 = *this;
- return b3Quaternion(-q2.getX(), -q2.getY(), -q2.getZ(), -q2.m_floats[3]);
-#endif
- }
- /**@todo document this and it's use */
- B3_FORCE_INLINE b3Quaternion farthest(const b3Quaternion& qd) const
- {
- b3Quaternion diff, sum;
- diff = *this - qd;
- sum = *this + qd;
- if (diff.dot(diff) > sum.dot(sum))
- return qd;
- return (-qd);
- }
-
- /**@todo document this and it's use */
- B3_FORCE_INLINE b3Quaternion nearest(const b3Quaternion& qd) const
- {
- b3Quaternion diff, sum;
- diff = *this - qd;
- sum = *this + qd;
- if (diff.dot(diff) < sum.dot(sum))
- return qd;
- return (-qd);
- }
-
- /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
- * @param q The other quaternion to interpolate with
- * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
- * Slerp interpolates assuming constant velocity. */
- b3Quaternion slerp(const b3Quaternion& q, const b3Scalar& t) const
- {
- b3Scalar magnitude = b3Sqrt(length2() * q.length2());
- b3Assert(magnitude > b3Scalar(0));
-
- b3Scalar product = dot(q) / magnitude;
- if (b3Fabs(product) < b3Scalar(1))
- {
- // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
- const b3Scalar sign = (product < 0) ? b3Scalar(-1) : b3Scalar(1);
-
- const b3Scalar theta = b3Acos(sign * product);
- const b3Scalar s1 = b3Sin(sign * t * theta);
- const b3Scalar d = b3Scalar(1.0) / b3Sin(theta);
- const b3Scalar s0 = b3Sin((b3Scalar(1.0) - t) * theta);
-
- return b3Quaternion(
- (m_floats[0] * s0 + q.getX() * s1) * d,
- (m_floats[1] * s0 + q.getY() * s1) * d,
- (m_floats[2] * s0 + q.getZ() * s1) * d,
- (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
- }
- else
- {
- return *this;
- }
- }
-
- static const b3Quaternion& getIdentity()
- {
- static const b3Quaternion identityQuat(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.), b3Scalar(1.));
- return identityQuat;
- }
-
- B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
-};
-
-/**@brief Return the product of two quaternions */
-B3_FORCE_INLINE b3Quaternion
-operator*(const b3Quaternion& q1, const b3Quaternion& q2)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vQ1 = q1.get128();
- __m128 vQ2 = q2.get128();
- __m128 A0, A1, B1, A2, B2;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0)); // X Y z x // vtrn
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0)); // W W W X // vdup vext
-
- A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1)); // Y Z X Y // vext
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1)); // z x Y Y // vtrn vdup
-
- A2 = A2 * B2;
-
- B1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2)); // z x Y Z // vtrn vext
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2)); // Y Z x z // vext vtrn
-
- B1 = B1 * B2; // A3 *= B3
-
- A0 = b3_splat_ps(vQ1, 3); // A0
- A0 = A0 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- A0 = A0 - B1; // AB03 = AB0 - AB3
-
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A0 = A0 + A1; // AB03 + AB12
-
- return b3Quaternion(A0);
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t vQ1 = q1.get128();
- float32x4_t vQ2 = q2.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- return b3Quaternion(A0);
-
-#else
- return b3Quaternion(
- q1.getW() * q2.getX() + q1.getX() * q2.getW() + q1.getY() * q2.getZ() - q1.getZ() * q2.getY(),
- q1.getW() * q2.getY() + q1.getY() * q2.getW() + q1.getZ() * q2.getX() - q1.getX() * q2.getZ(),
- q1.getW() * q2.getZ() + q1.getZ() * q2.getW() + q1.getX() * q2.getY() - q1.getY() * q2.getX(),
- q1.getW() * q2.getW() - q1.getX() * q2.getX() - q1.getY() * q2.getY() - q1.getZ() * q2.getZ());
-#endif
-}
-
-B3_FORCE_INLINE b3Quaternion
-operator*(const b3Quaternion& q, const b3Vector3& w)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vQ1 = q.get128();
- __m128 vQ2 = w.get128();
- __m128 A1, B1, A2, B2, A3, B3;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(3, 3, 3, 0));
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(0, 1, 2, 0));
-
- A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
- B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
-
- A3 = A3 * B3; // A3 *= B3
-
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
- return b3Quaternion(A1);
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t vQ1 = q.get128();
- float32x4_t vQ2 = w.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
-
- vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
- }
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
- B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
- return b3Quaternion(A1);
-
-#else
- return b3Quaternion(
- q.getW() * w.getX() + q.getY() * w.getZ() - q.getZ() * w.getY(),
- q.getW() * w.getY() + q.getZ() * w.getX() - q.getX() * w.getZ(),
- q.getW() * w.getZ() + q.getX() * w.getY() - q.getY() * w.getX(),
- -q.getX() * w.getX() - q.getY() * w.getY() - q.getZ() * w.getZ());
-#endif
-}
-
-B3_FORCE_INLINE b3Quaternion
-operator*(const b3Vector3& w, const b3Quaternion& q)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vQ1 = w.get128();
- __m128 vQ2 = q.get128();
- __m128 A1, B1, A2, B2, A3, B3;
-
- A1 = b3_pshufd_ps(vQ1, B3_SHUFFLE(0, 1, 2, 0)); // X Y z x
- B1 = b3_pshufd_ps(vQ2, B3_SHUFFLE(3, 3, 3, 0)); // W W W X
-
- A1 = A1 * B1;
-
- A2 = b3_pshufd_ps(vQ1, B3_SHUFFLE(1, 2, 0, 1));
- B2 = b3_pshufd_ps(vQ2, B3_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- A3 = b3_pshufd_ps(vQ1, B3_SHUFFLE(2, 0, 1, 2));
- B3 = b3_pshufd_ps(vQ2, B3_SHUFFLE(1, 2, 0, 2));
-
- A3 = A3 * B3; // A3 *= B3
-
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, b3vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
- return b3Quaternion(A1);
-
-#elif defined(B3_USE_NEON)
-
- float32x4_t vQ1 = w.get128();
- float32x4_t vQ2 = q.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (b3SimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)b3vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
- return b3Quaternion(A1);
-
-#else
- return b3Quaternion(
- +w.getX() * q.getW() + w.getY() * q.getZ() - w.getZ() * q.getY(),
- +w.getY() * q.getW() + w.getZ() * q.getX() - w.getX() * q.getZ(),
- +w.getZ() * q.getW() + w.getX() * q.getY() - w.getY() * q.getX(),
- -w.getX() * q.getX() - w.getY() * q.getY() - w.getZ() * q.getZ());
-#endif
-}
-
-/**@brief Calculate the dot product between two quaternions */
-B3_FORCE_INLINE b3Scalar
-b3Dot(const b3Quaternion& q1, const b3Quaternion& q2)
-{
- return q1.dot(q2);
-}
-
-/**@brief Return the length of a quaternion */
-B3_FORCE_INLINE b3Scalar
-b3Length(const b3Quaternion& q)
-{
- return q.length();
-}
-
-/**@brief Return the angle between two quaternions*/
-B3_FORCE_INLINE b3Scalar
-b3Angle(const b3Quaternion& q1, const b3Quaternion& q2)
-{
- return q1.angle(q2);
-}
-
-/**@brief Return the inverse of a quaternion*/
-B3_FORCE_INLINE b3Quaternion
-b3Inverse(const b3Quaternion& q)
-{
- return q.inverse();
-}
-
-/**@brief Return the result of spherical linear interpolation betwen two quaternions
- * @param q1 The first quaternion
- * @param q2 The second quaternion
- * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
- * Slerp assumes constant velocity between positions. */
-B3_FORCE_INLINE b3Quaternion
-b3Slerp(const b3Quaternion& q1, const b3Quaternion& q2, const b3Scalar& t)
-{
- return q1.slerp(q2, t);
-}
-
-B3_FORCE_INLINE b3Quaternion
-b3QuatMul(const b3Quaternion& rot0, const b3Quaternion& rot1)
-{
- return rot0 * rot1;
-}
-
-B3_FORCE_INLINE b3Quaternion
-b3QuatNormalized(const b3Quaternion& orn)
-{
- return orn.normalized();
-}
-
-B3_FORCE_INLINE b3Vector3
-b3QuatRotate(const b3Quaternion& rotation, const b3Vector3& v)
-{
- b3Quaternion q = rotation * v;
- q *= rotation.inverse();
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3MakeVector3(_mm_and_ps(q.get128(), b3vFFF0fMask));
-#elif defined(B3_USE_NEON)
- return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), b3vFFF0Mask));
-#else
- return b3MakeVector3(q.getX(), q.getY(), q.getZ());
-#endif
-}
-
-B3_FORCE_INLINE b3Quaternion
-b3ShortestArcQuat(const b3Vector3& v0, const b3Vector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
-{
- b3Vector3 c = v0.cross(v1);
- b3Scalar d = v0.dot(v1);
-
- if (d < -1.0 + B3_EPSILON)
- {
- b3Vector3 n, unused;
- b3PlaneSpace1(v0, n, unused);
- return b3Quaternion(n.getX(), n.getY(), n.getZ(), 0.0f); // just pick any vector that is orthogonal to v0
- }
-
- b3Scalar s = b3Sqrt((1.0f + d) * 2.0f);
- b3Scalar rs = 1.0f / s;
-
- return b3Quaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
-}
-
-B3_FORCE_INLINE b3Quaternion
-b3ShortestArcQuatNormalize2(b3Vector3& v0, b3Vector3& v1)
-{
- v0.normalize();
- v1.normalize();
- return b3ShortestArcQuat(v0, v1);
-}
-
-#endif //B3_SIMD__QUATERNION_H_
diff --git a/thirdparty/bullet/Bullet3Common/b3Random.h b/thirdparty/bullet/Bullet3Common/b3Random.h
deleted file mode 100644
index c2e21496c7..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Random.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_GEN_RANDOM_H
-#define B3_GEN_RANDOM_H
-
-#include "b3Scalar.h"
-
-#ifdef MT19937
-
-#include <limits.h>
-#include <mt19937.h>
-
-#define B3_RAND_MAX UINT_MAX
-
-B3_FORCE_INLINE void b3Srand(unsigned int seed) { init_genrand(seed); }
-B3_FORCE_INLINE unsigned int b3rand() { return genrand_int32(); }
-
-#else
-
-#include <stdlib.h>
-
-#define B3_RAND_MAX RAND_MAX
-
-B3_FORCE_INLINE void b3Srand(unsigned int seed) { srand(seed); }
-B3_FORCE_INLINE unsigned int b3rand() { return rand(); }
-
-#endif
-
-inline b3Scalar b3RandRange(b3Scalar minRange, b3Scalar maxRange)
-{
- return (b3rand() / (b3Scalar(B3_RAND_MAX) + b3Scalar(1.0))) * (maxRange - minRange) + minRange;
-}
-
-#endif //B3_GEN_RANDOM_H
diff --git a/thirdparty/bullet/Bullet3Common/b3ResizablePool.h b/thirdparty/bullet/Bullet3Common/b3ResizablePool.h
deleted file mode 100644
index cafe3ff396..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3ResizablePool.h
+++ /dev/null
@@ -1,171 +0,0 @@
-
-#ifndef B3_RESIZABLE_POOL_H
-#define B3_RESIZABLE_POOL_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-enum
-{
- B3_POOL_HANDLE_TERMINAL_FREE = -1,
- B3_POOL_HANDLE_TERMINAL_USED = -2
-};
-
-template <typename U>
-struct b3PoolBodyHandle : public U
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_nextFreeHandle;
- void setNextFree(int next)
- {
- m_nextFreeHandle = next;
- }
- int getNextFree() const
- {
- return m_nextFreeHandle;
- }
-};
-
-template <typename T>
-class b3ResizablePool
-{
-protected:
- b3AlignedObjectArray<T> m_bodyHandles;
- int m_numUsedHandles; // number of active handles
- int m_firstFreeHandle; // free handles list
-
- T* getHandleInternal(int handle)
- {
- return &m_bodyHandles[handle];
- }
- const T* getHandleInternal(int handle) const
- {
- return &m_bodyHandles[handle];
- }
-
-public:
- b3ResizablePool()
- {
- initHandles();
- }
-
- virtual ~b3ResizablePool()
- {
- exitHandles();
- }
- ///handle management
-
- int getNumHandles() const
- {
- return m_bodyHandles.size();
- }
-
- void getUsedHandles(b3AlignedObjectArray<int>& usedHandles) const
- {
- for (int i = 0; i < m_bodyHandles.size(); i++)
- {
- if (m_bodyHandles[i].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
- {
- usedHandles.push_back(i);
- }
- }
- }
-
- T* getHandle(int handle)
- {
- b3Assert(handle >= 0);
- b3Assert(handle < m_bodyHandles.size());
- if ((handle < 0) || (handle >= m_bodyHandles.size()))
- {
- return 0;
- }
-
- if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
- {
- return &m_bodyHandles[handle];
- }
- return 0;
- }
- const T* getHandle(int handle) const
- {
- b3Assert(handle >= 0);
- b3Assert(handle < m_bodyHandles.size());
- if ((handle < 0) || (handle >= m_bodyHandles.size()))
- {
- return 0;
- }
-
- if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
- {
- return &m_bodyHandles[handle];
- }
- return 0;
- }
-
- void increaseHandleCapacity(int extraCapacity)
- {
- int curCapacity = m_bodyHandles.size();
- //b3Assert(curCapacity == m_numUsedHandles);
- int newCapacity = curCapacity + extraCapacity;
- m_bodyHandles.resize(newCapacity);
-
- {
- for (int i = curCapacity; i < newCapacity; i++)
- m_bodyHandles[i].setNextFree(i + 1);
-
- m_bodyHandles[newCapacity - 1].setNextFree(-1);
- }
- m_firstFreeHandle = curCapacity;
- }
- void initHandles()
- {
- m_numUsedHandles = 0;
- m_firstFreeHandle = -1;
-
- increaseHandleCapacity(1);
- }
-
- void exitHandles()
- {
- m_bodyHandles.resize(0);
- m_firstFreeHandle = -1;
- m_numUsedHandles = 0;
- }
-
- int allocHandle()
- {
- b3Assert(m_firstFreeHandle >= 0);
-
- int handle = m_firstFreeHandle;
- m_firstFreeHandle = getHandleInternal(handle)->getNextFree();
- m_numUsedHandles++;
-
- if (m_firstFreeHandle < 0)
- {
- //int curCapacity = m_bodyHandles.size();
- int additionalCapacity = m_bodyHandles.size();
- increaseHandleCapacity(additionalCapacity);
-
- getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
- }
- getHandleInternal(handle)->setNextFree(B3_POOL_HANDLE_TERMINAL_USED);
- getHandleInternal(handle)->clear();
- return handle;
- }
-
- void freeHandle(int handle)
- {
- b3Assert(handle >= 0);
-
- if (m_bodyHandles[handle].getNextFree() == B3_POOL_HANDLE_TERMINAL_USED)
- {
- getHandleInternal(handle)->clear();
- getHandleInternal(handle)->setNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
- m_numUsedHandles--;
- }
- }
-};
-///end handle management
-
-#endif //B3_RESIZABLE_POOL_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Scalar.h b/thirdparty/bullet/Bullet3Common/b3Scalar.h
deleted file mode 100644
index eeb70ed632..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Scalar.h
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SCALAR_H
-#define B3_SCALAR_H
-
-#ifdef B3_MANAGED_CODE
-//Aligned data types not supported in managed code
-#pragma unmanaged
-#endif
-
-#include <math.h>
-#include <stdlib.h> //size_t for MSVC 6.0
-#include <float.h>
-
-//Original repository is at http://github.com/erwincoumans/bullet3
-#define B3_BULLET_VERSION 300
-
-inline int b3GetVersion()
-{
- return B3_BULLET_VERSION;
-}
-
-#if defined(DEBUG) || defined(_DEBUG)
-#define B3_DEBUG
-#endif
-
-#include "b3Logging.h" //for b3Error
-
-#ifdef _WIN32
-
-#if defined(__GNUC__) // it should handle both MINGW and CYGWIN
-#define B3_FORCE_INLINE __inline__ __attribute__((always_inline))
-#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
-#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
-#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
-#elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
-#define B3_FORCE_INLINE inline
-#define B3_ATTRIBUTE_ALIGNED16(a) a
-#define B3_ATTRIBUTE_ALIGNED64(a) a
-#define B3_ATTRIBUTE_ALIGNED128(a) a
-#else
-//#define B3_HAS_ALIGNED_ALLOCATOR
-#pragma warning(disable : 4324) // disable padding warning
-// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
-#pragma warning(disable : 4996) //Turn off warnings about deprecated C routines
-// #pragma warning(disable:4786) // Disable the "debug name too long" warning
-
-#define B3_FORCE_INLINE __forceinline
-#define B3_ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
-#define B3_ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
-#define B3_ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
-#ifdef _XBOX
-#define B3_USE_VMX128
-
-#include <ppcintrinsics.h>
-#define B3_HAVE_NATIVE_FSEL
-#define b3Fsel(a, b, c) __fsel((a), (b), (c))
-#else
-
-#if (defined(_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined(B3_USE_DOUBLE_PRECISION))
-#if (defined(_M_IX86) || defined(_M_X64))
-
-
-#ifdef __clang__
-//#define B3_NO_SIMD_OPERATOR_OVERLOADS
-#define B3_DISABLE_SSE
-#endif //__clang__
-
-#ifndef B3_DISABLE_SSE
-#define B3_USE_SSE
-#endif //B3_DISABLE_SSE
-
-#ifdef B3_USE_SSE
-//B3_USE_SSE_IN_API is disabled under Windows by default, because
-//it makes it harder to integrate Bullet into your application under Windows
-//(structured embedding Bullet structs/classes need to be 16-byte aligned)
-//with relatively little performance gain
-//If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
-//you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
-//#define B3_USE_SSE_IN_API
-#endif //B3_USE_SSE
-#include <emmintrin.h>
-#endif
-#endif
-
-#endif //_XBOX
-
-#endif //__MINGW32__
-
-#ifdef B3_DEBUG
-#ifdef _MSC_VER
-#include <stdio.h>
-#define b3Assert(x) { if(!(x)){b3Error("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
-#else //_MSC_VER
-#include <assert.h>
-#define b3Assert assert
-#endif //_MSC_VER
-#else
-#define b3Assert(x)
-#endif
-//b3FullAssert is optional, slows down a lot
-#define b3FullAssert(x)
-
-#define b3Likely(_c) _c
-#define b3Unlikely(_c) _c
-
-#else
-
-#if defined(__CELLOS_LV2__)
-#define B3_FORCE_INLINE inline __attribute__((always_inline))
-#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
-#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
-#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
-#ifndef assert
-#include <assert.h>
-#endif
-#ifdef B3_DEBUG
-#ifdef __SPU__
-#include <spu_printf.h>
-#define printf spu_printf
-#define b3Assert(x) \
- { \
- if (!(x)) \
- { \
- b3Error( \
- "Assert "__FILE__ \
- ":%u (" #x ")\n", \
- __LINE__); \
- spu_hcmpeq(0, 0); \
- } \
- }
-#else
-#define b3Assert assert
-#endif
-
-#else
-#define b3Assert(x)
-#endif
-//b3FullAssert is optional, slows down a lot
-#define b3FullAssert(x)
-
-#define b3Likely(_c) _c
-#define b3Unlikely(_c) _c
-
-#else
-
-#ifdef USE_LIBSPE2
-
-#define B3_FORCE_INLINE __inline
-#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
-#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
-#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
-#ifndef assert
-#include <assert.h>
-#endif
-#ifdef B3_DEBUG
-#define b3Assert assert
-#else
-#define b3Assert(x)
-#endif
-//b3FullAssert is optional, slows down a lot
-#define b3FullAssert(x)
-
-#define b3Likely(_c) __builtin_expect((_c), 1)
-#define b3Unlikely(_c) __builtin_expect((_c), 0)
-
-#else
-//non-windows systems
-
-#if (defined(__APPLE__) && (!defined(B3_USE_DOUBLE_PRECISION)))
-#if defined(__i386__) || defined(__x86_64__)
-#define B3_USE_SSE
-//B3_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
-//if apps run into issues, we will disable the next line
-#define B3_USE_SSE_IN_API
-#ifdef B3_USE_SSE
-// include appropriate SSE level
-#if defined(__SSE4_1__)
-#include <smmintrin.h>
-#elif defined(__SSSE3__)
-#include <tmmintrin.h>
-#elif defined(__SSE3__)
-#include <pmmintrin.h>
-#else
-#include <emmintrin.h>
-#endif
-#endif //B3_USE_SSE
-#elif defined(__armv7__)
-#ifdef __clang__
-#define B3_USE_NEON 1
-
-#if defined B3_USE_NEON && defined(__clang__)
-#include <arm_neon.h>
-#endif //B3_USE_NEON
-#endif //__clang__
-#endif //__arm__
-
-#define B3_FORCE_INLINE inline __attribute__((always_inline))
-///@todo: check out alignment methods for other platforms/compilers
-#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
-#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
-#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
-#ifndef assert
-#include <assert.h>
-#endif
-
-#if defined(DEBUG) || defined(_DEBUG)
-#if defined(__i386__) || defined(__x86_64__)
-#include <stdio.h>
-#define b3Assert(x) \
- { \
- if (!(x)) \
- { \
- b3Error("Assert %s in line %d, file %s\n", #x, __LINE__, __FILE__); \
- asm volatile("int3"); \
- } \
- }
-#else //defined (__i386__) || defined (__x86_64__)
-#define b3Assert assert
-#endif //defined (__i386__) || defined (__x86_64__)
-#else //defined(DEBUG) || defined (_DEBUG)
-#define b3Assert(x)
-#endif //defined(DEBUG) || defined (_DEBUG)
-
-//b3FullAssert is optional, slows down a lot
-#define b3FullAssert(x)
-#define b3Likely(_c) _c
-#define b3Unlikely(_c) _c
-
-#else
-
-#define B3_FORCE_INLINE inline
-///@todo: check out alignment methods for other platforms/compilers
-#define B3_ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
-#define B3_ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
-#define B3_ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
-///#define B3_ATTRIBUTE_ALIGNED16(a) a
-///#define B3_ATTRIBUTE_ALIGNED64(a) a
-///#define B3_ATTRIBUTE_ALIGNED128(a) a
-#ifndef assert
-#include <assert.h>
-#endif
-
-#if defined(DEBUG) || defined(_DEBUG)
-#define b3Assert assert
-#else
-#define b3Assert(x)
-#endif
-
-//b3FullAssert is optional, slows down a lot
-#define b3FullAssert(x)
-#define b3Likely(_c) _c
-#define b3Unlikely(_c) _c
-#endif //__APPLE__
-
-#endif // LIBSPE2
-
-#endif //__CELLOS_LV2__
-#endif
-
-///The b3Scalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
-#if defined(B3_USE_DOUBLE_PRECISION)
-typedef double b3Scalar;
-//this number could be bigger in double precision
-#define B3_LARGE_FLOAT 1e30
-#else
-typedef float b3Scalar;
-//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
-#define B3_LARGE_FLOAT 1e18f
-#endif
-
-#ifdef B3_USE_SSE
-typedef __m128 b3SimdFloat4;
-#endif //B3_USE_SSE
-
-#if defined B3_USE_SSE_IN_API && defined(B3_USE_SSE)
-#ifdef _WIN32
-
-#ifndef B3_NAN
-static int b3NanMask = 0x7F800001;
-#define B3_NAN (*(float *)&b3NanMask)
-#endif
-
-#ifndef B3_INFINITY_MASK
-static int b3InfinityMask = 0x7F800000;
-#define B3_INFINITY_MASK (*(float *)&b3InfinityMask)
-#endif
-#ifndef B3_NO_SIMD_OPERATOR_OVERLOADS
-inline __m128 operator+(const __m128 A, const __m128 B)
-{
- return _mm_add_ps(A, B);
-}
-
-inline __m128 operator-(const __m128 A, const __m128 B)
-{
- return _mm_sub_ps(A, B);
-}
-
-inline __m128 operator*(const __m128 A, const __m128 B)
-{
- return _mm_mul_ps(A, B);
-}
-#endif //B3_NO_SIMD_OPERATOR_OVERLOADS
-#define b3CastfTo128i(a) (_mm_castps_si128(a))
-#define b3CastfTo128d(a) (_mm_castps_pd(a))
-#define b3CastiTo128f(a) (_mm_castsi128_ps(a))
-#define b3CastdTo128f(a) (_mm_castpd_ps(a))
-#define b3CastdTo128i(a) (_mm_castpd_si128(a))
-#define b3Assign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
-
-#else //_WIN32
-
-#define b3CastfTo128i(a) ((__m128i)(a))
-#define b3CastfTo128d(a) ((__m128d)(a))
-#define b3CastiTo128f(a) ((__m128)(a))
-#define b3CastdTo128f(a) ((__m128)(a))
-#define b3CastdTo128i(a) ((__m128i)(a))
-#define b3Assign128(r0, r1, r2, r3) \
- (__m128) { r0, r1, r2, r3 }
-#endif //_WIN32
-#endif //B3_USE_SSE_IN_API
-
-#ifdef B3_USE_NEON
-#include <arm_neon.h>
-
-typedef float32x4_t b3SimdFloat4;
-#define B3_INFINITY INFINITY
-#define B3_NAN NAN
-#define b3Assign128(r0, r1, r2, r3) \
- (float32x4_t) { r0, r1, r2, r3 }
-#endif
-
-#define B3_DECLARE_ALIGNED_ALLOCATOR() \
- B3_FORCE_INLINE void *operator new(size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); } \
- B3_FORCE_INLINE void operator delete(void *ptr) { b3AlignedFree(ptr); } \
- B3_FORCE_INLINE void *operator new(size_t, void *ptr) { return ptr; } \
- B3_FORCE_INLINE void operator delete(void *, void *) {} \
- B3_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return b3AlignedAlloc(sizeInBytes, 16); } \
- B3_FORCE_INLINE void operator delete[](void *ptr) { b3AlignedFree(ptr); } \
- B3_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; } \
- B3_FORCE_INLINE void operator delete[](void *, void *) {}
-
-#if defined(B3_USE_DOUBLE_PRECISION) || defined(B3_FORCE_DOUBLE_FUNCTIONS)
-
-B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar x)
-{
- return sqrt(x);
-}
-B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabs(x); }
-B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cos(x); }
-B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sin(x); }
-B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tan(x); }
-B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
-{
- if (x < b3Scalar(-1)) x = b3Scalar(-1);
- if (x > b3Scalar(1)) x = b3Scalar(1);
- return acos(x);
-}
-B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
-{
- if (x < b3Scalar(-1)) x = b3Scalar(-1);
- if (x > b3Scalar(1)) x = b3Scalar(1);
- return asin(x);
-}
-B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atan(x); }
-B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2(x, y); }
-B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return exp(x); }
-B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return log(x); }
-B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return pow(x, y); }
-B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmod(x, y); }
-
-#else
-
-B3_FORCE_INLINE b3Scalar b3Sqrt(b3Scalar y)
-{
-#ifdef USE_APPROXIMATION
- double x, z, tempf;
- unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
-
- tempf = y;
- *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
- x = tempf;
- z = y * b3Scalar(0.5);
- x = (b3Scalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
- x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
- x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
- x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
- x = (b3Scalar(1.5) * x) - (x * x) * (x * z);
- return x * y;
-#else
- return sqrtf(y);
-#endif
-}
-B3_FORCE_INLINE b3Scalar b3Fabs(b3Scalar x) { return fabsf(x); }
-B3_FORCE_INLINE b3Scalar b3Cos(b3Scalar x) { return cosf(x); }
-B3_FORCE_INLINE b3Scalar b3Sin(b3Scalar x) { return sinf(x); }
-B3_FORCE_INLINE b3Scalar b3Tan(b3Scalar x) { return tanf(x); }
-B3_FORCE_INLINE b3Scalar b3Acos(b3Scalar x)
-{
- if (x < b3Scalar(-1))
- x = b3Scalar(-1);
- if (x > b3Scalar(1))
- x = b3Scalar(1);
- return acosf(x);
-}
-B3_FORCE_INLINE b3Scalar b3Asin(b3Scalar x)
-{
- if (x < b3Scalar(-1))
- x = b3Scalar(-1);
- if (x > b3Scalar(1))
- x = b3Scalar(1);
- return asinf(x);
-}
-B3_FORCE_INLINE b3Scalar b3Atan(b3Scalar x) { return atanf(x); }
-B3_FORCE_INLINE b3Scalar b3Atan2(b3Scalar x, b3Scalar y) { return atan2f(x, y); }
-B3_FORCE_INLINE b3Scalar b3Exp(b3Scalar x) { return expf(x); }
-B3_FORCE_INLINE b3Scalar b3Log(b3Scalar x) { return logf(x); }
-B3_FORCE_INLINE b3Scalar b3Pow(b3Scalar x, b3Scalar y) { return powf(x, y); }
-B3_FORCE_INLINE b3Scalar b3Fmod(b3Scalar x, b3Scalar y) { return fmodf(x, y); }
-
-#endif
-
-#define B3_2_PI b3Scalar(6.283185307179586232)
-#define B3_PI (B3_2_PI * b3Scalar(0.5))
-#define B3_HALF_PI (B3_2_PI * b3Scalar(0.25))
-#define B3_RADS_PER_DEG (B3_2_PI / b3Scalar(360.0))
-#define B3_DEGS_PER_RAD (b3Scalar(360.0) / B3_2_PI)
-#define B3_SQRT12 b3Scalar(0.7071067811865475244008443621048490)
-
-#define b3RecipSqrt(x) ((b3Scalar)(b3Scalar(1.0) / b3Sqrt(b3Scalar(x)))) /* reciprocal square root */
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define B3_EPSILON DBL_EPSILON
-#define B3_INFINITY DBL_MAX
-#else
-#define B3_EPSILON FLT_EPSILON
-#define B3_INFINITY FLT_MAX
-#endif
-
-B3_FORCE_INLINE b3Scalar b3Atan2Fast(b3Scalar y, b3Scalar x)
-{
- b3Scalar coeff_1 = B3_PI / 4.0f;
- b3Scalar coeff_2 = 3.0f * coeff_1;
- b3Scalar abs_y = b3Fabs(y);
- b3Scalar angle;
- if (x >= 0.0f)
- {
- b3Scalar r = (x - abs_y) / (x + abs_y);
- angle = coeff_1 - coeff_1 * r;
- }
- else
- {
- b3Scalar r = (x + abs_y) / (abs_y - x);
- angle = coeff_2 - coeff_1 * r;
- }
- return (y < 0.0f) ? -angle : angle;
-}
-
-B3_FORCE_INLINE bool b3FuzzyZero(b3Scalar x) { return b3Fabs(x) < B3_EPSILON; }
-
-B3_FORCE_INLINE bool b3Equal(b3Scalar a, b3Scalar eps)
-{
- return (((a) <= eps) && !((a) < -eps));
-}
-B3_FORCE_INLINE bool b3GreaterEqual(b3Scalar a, b3Scalar eps)
-{
- return (!((a) <= eps));
-}
-
-B3_FORCE_INLINE int b3IsNegative(b3Scalar x)
-{
- return x < b3Scalar(0.0) ? 1 : 0;
-}
-
-B3_FORCE_INLINE b3Scalar b3Radians(b3Scalar x) { return x * B3_RADS_PER_DEG; }
-B3_FORCE_INLINE b3Scalar b3Degrees(b3Scalar x) { return x * B3_DEGS_PER_RAD; }
-
-#define B3_DECLARE_HANDLE(name) \
- typedef struct name##__ \
- { \
- int unused; \
- } * name
-
-#ifndef b3Fsel
-B3_FORCE_INLINE b3Scalar b3Fsel(b3Scalar a, b3Scalar b, b3Scalar c)
-{
- return a >= 0 ? b : c;
-}
-#endif
-#define b3Fsels(a, b, c) (b3Scalar) b3Fsel(a, b, c)
-
-B3_FORCE_INLINE bool b3MachineIsLittleEndian()
-{
- long int i = 1;
- const char *p = (const char *)&i;
- if (p[0] == 1) // Lowest address contains the least significant byte
- return true;
- else
- return false;
-}
-
-///b3Select avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
-///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
-B3_FORCE_INLINE unsigned b3Select(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
-{
- // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
- // Rely on positive value or'ed with its negative having sign bit on
- // and zero value or'ed with its negative (which is still zero) having sign bit off
- // Use arithmetic shift right, shifting the sign bit through all 32 bits
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
-}
-B3_FORCE_INLINE int b3Select(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
-{
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
-}
-B3_FORCE_INLINE float b3Select(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
-{
-#ifdef B3_HAVE_NATIVE_FSEL
- return (float)b3Fsel((b3Scalar)condition - b3Scalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
-#else
- return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
-#endif
-}
-
-template <typename T>
-B3_FORCE_INLINE void b3Swap(T &a, T &b)
-{
- T tmp = a;
- a = b;
- b = tmp;
-}
-
-//PCK: endian swapping functions
-B3_FORCE_INLINE unsigned b3SwapEndian(unsigned val)
-{
- return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
-}
-
-B3_FORCE_INLINE unsigned short b3SwapEndian(unsigned short val)
-{
- return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
-}
-
-B3_FORCE_INLINE unsigned b3SwapEndian(int val)
-{
- return b3SwapEndian((unsigned)val);
-}
-
-B3_FORCE_INLINE unsigned short b3SwapEndian(short val)
-{
- return b3SwapEndian((unsigned short)val);
-}
-
-///b3SwapFloat uses using char pointers to swap the endianness
-////b3SwapFloat/b3SwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
-///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
-///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
-///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
-///so instead of returning a float/double, we return integer/long long integer
-B3_FORCE_INLINE unsigned int b3SwapEndianFloat(float d)
-{
- unsigned int a = 0;
- unsigned char *dst = (unsigned char *)&a;
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
- return a;
-}
-
-// unswap using char pointers
-B3_FORCE_INLINE float b3UnswapEndianFloat(unsigned int a)
-{
- float d = 0.0f;
- unsigned char *src = (unsigned char *)&a;
- unsigned char *dst = (unsigned char *)&d;
-
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
-
- return d;
-}
-
-// swap using char pointers
-B3_FORCE_INLINE void b3SwapEndianDouble(double d, unsigned char *dst)
-{
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
-}
-
-// unswap using char pointers
-B3_FORCE_INLINE double b3UnswapEndianDouble(const unsigned char *src)
-{
- double d = 0.0;
- unsigned char *dst = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
-
- return d;
-}
-
-// returns normalized value in range [-B3_PI, B3_PI]
-B3_FORCE_INLINE b3Scalar b3NormalizeAngle(b3Scalar angleInRadians)
-{
- angleInRadians = b3Fmod(angleInRadians, B3_2_PI);
- if (angleInRadians < -B3_PI)
- {
- return angleInRadians + B3_2_PI;
- }
- else if (angleInRadians > B3_PI)
- {
- return angleInRadians - B3_2_PI;
- }
- else
- {
- return angleInRadians;
- }
-}
-
-///rudimentary class to provide type info
-struct b3TypedObject
-{
- b3TypedObject(int objectType)
- : m_objectType(objectType)
- {
- }
- int m_objectType;
- inline int getObjectType() const
- {
- return m_objectType;
- }
-};
-
-///align a pointer to the provided alignment, upwards
-template <typename T>
-T *b3AlignPointer(T *unalignedPtr, size_t alignment)
-{
- struct b3ConvertPointerSizeT
- {
- union {
- T *ptr;
- size_t integer;
- };
- };
- b3ConvertPointerSizeT converter;
-
- const size_t bit_mask = ~(alignment - 1);
- converter.ptr = unalignedPtr;
- converter.integer += alignment - 1;
- converter.integer &= bit_mask;
- return converter.ptr;
-}
-
-#endif //B3_SCALAR_H
diff --git a/thirdparty/bullet/Bullet3Common/b3StackAlloc.h b/thirdparty/bullet/Bullet3Common/b3StackAlloc.h
deleted file mode 100644
index 4972236ac7..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3StackAlloc.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
-Nov.2006
-*/
-
-#ifndef B3_STACK_ALLOC
-#define B3_STACK_ALLOC
-
-#include "b3Scalar.h" //for b3Assert
-#include "b3AlignedAllocator.h"
-
-///The b3Block class is an internal structure for the b3StackAlloc memory allocator.
-struct b3Block
-{
- b3Block* previous;
- unsigned char* address;
-};
-
-///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
-class b3StackAlloc
-{
-public:
- b3StackAlloc(unsigned int size)
- {
- ctor();
- create(size);
- }
- ~b3StackAlloc() { destroy(); }
-
- inline void create(unsigned int size)
- {
- destroy();
- data = (unsigned char*)b3AlignedAlloc(size, 16);
- totalsize = size;
- }
- inline void destroy()
- {
- b3Assert(usedsize == 0);
- //Raise(L"StackAlloc is still in use");
-
- if (usedsize == 0)
- {
- if (!ischild && data)
- b3AlignedFree(data);
-
- data = 0;
- usedsize = 0;
- }
- }
-
- int getAvailableMemory() const
- {
- return static_cast<int>(totalsize - usedsize);
- }
-
- unsigned char* allocate(unsigned int size)
- {
- const unsigned int nus(usedsize + size);
- if (nus < totalsize)
- {
- usedsize = nus;
- return (data + (usedsize - size));
- }
- b3Assert(0);
- //&& (L"Not enough memory"));
-
- return (0);
- }
- B3_FORCE_INLINE b3Block* beginBlock()
- {
- b3Block* pb = (b3Block*)allocate(sizeof(b3Block));
- pb->previous = current;
- pb->address = data + usedsize;
- current = pb;
- return (pb);
- }
- B3_FORCE_INLINE void endBlock(b3Block* block)
- {
- b3Assert(block == current);
- //Raise(L"Unmatched blocks");
- if (block == current)
- {
- current = block->previous;
- usedsize = (unsigned int)((block->address - data) - sizeof(b3Block));
- }
- }
-
-private:
- void ctor()
- {
- data = 0;
- totalsize = 0;
- usedsize = 0;
- current = 0;
- ischild = false;
- }
- unsigned char* data;
- unsigned int totalsize;
- unsigned int usedsize;
- b3Block* current;
- bool ischild;
-};
-
-#endif //B3_STACK_ALLOC
diff --git a/thirdparty/bullet/Bullet3Common/b3Transform.h b/thirdparty/bullet/Bullet3Common/b3Transform.h
deleted file mode 100644
index 149da9d148..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Transform.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_TRANSFORM_H
-#define B3_TRANSFORM_H
-
-#include "b3Matrix3x3.h"
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define b3TransformData b3TransformDoubleData
-#else
-#define b3TransformData b3TransformFloatData
-#endif
-
-/**@brief The b3Transform class supports rigid transforms with only translation and rotation and no scaling/shear.
- *It can be used in combination with b3Vector3, b3Quaternion and b3Matrix3x3 linear algebra classes. */
-B3_ATTRIBUTE_ALIGNED16(class)
-b3Transform
-{
- ///Storage for the rotation
- b3Matrix3x3 m_basis;
- ///Storage for the translation
- b3Vector3 m_origin;
-
-public:
- /**@brief No initialization constructor */
- b3Transform() {}
- /**@brief Constructor from b3Quaternion (optional b3Vector3 )
- * @param q Rotation from quaternion
- * @param c Translation from Vector (default 0,0,0) */
- explicit B3_FORCE_INLINE b3Transform(const b3Quaternion& q,
- const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
- : m_basis(q),
- m_origin(c)
- {
- }
-
- /**@brief Constructor from b3Matrix3x3 (optional b3Vector3)
- * @param b Rotation from Matrix
- * @param c Translation from Vector default (0,0,0)*/
- explicit B3_FORCE_INLINE b3Transform(const b3Matrix3x3& b,
- const b3Vector3& c = b3MakeVector3(b3Scalar(0), b3Scalar(0), b3Scalar(0)))
- : m_basis(b),
- m_origin(c)
- {
- }
- /**@brief Copy constructor */
- B3_FORCE_INLINE b3Transform(const b3Transform& other)
- : m_basis(other.m_basis),
- m_origin(other.m_origin)
- {
- }
- /**@brief Assignment Operator */
- B3_FORCE_INLINE b3Transform& operator=(const b3Transform& other)
- {
- m_basis = other.m_basis;
- m_origin = other.m_origin;
- return *this;
- }
-
- /**@brief Set the current transform as the value of the product of two transforms
- * @param t1 Transform 1
- * @param t2 Transform 2
- * This = Transform1 * Transform2 */
- B3_FORCE_INLINE void mult(const b3Transform& t1, const b3Transform& t2)
- {
- m_basis = t1.m_basis * t2.m_basis;
- m_origin = t1(t2.m_origin);
- }
-
- /* void multInverseLeft(const b3Transform& t1, const b3Transform& t2) {
- b3Vector3 v = t2.m_origin - t1.m_origin;
- m_basis = b3MultTransposeLeft(t1.m_basis, t2.m_basis);
- m_origin = v * t1.m_basis;
- }
- */
-
- /**@brief Return the transform of the vector */
- B3_FORCE_INLINE b3Vector3 operator()(const b3Vector3& x) const
- {
- return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
- }
-
- /**@brief Return the transform of the vector */
- B3_FORCE_INLINE b3Vector3 operator*(const b3Vector3& x) const
- {
- return (*this)(x);
- }
-
- /**@brief Return the transform of the b3Quaternion */
- B3_FORCE_INLINE b3Quaternion operator*(const b3Quaternion& q) const
- {
- return getRotation() * q;
- }
-
- /**@brief Return the basis matrix for the rotation */
- B3_FORCE_INLINE b3Matrix3x3& getBasis() { return m_basis; }
- /**@brief Return the basis matrix for the rotation */
- B3_FORCE_INLINE const b3Matrix3x3& getBasis() const { return m_basis; }
-
- /**@brief Return the origin vector translation */
- B3_FORCE_INLINE b3Vector3& getOrigin() { return m_origin; }
- /**@brief Return the origin vector translation */
- B3_FORCE_INLINE const b3Vector3& getOrigin() const { return m_origin; }
-
- /**@brief Return a quaternion representing the rotation */
- b3Quaternion getRotation() const
- {
- b3Quaternion q;
- m_basis.getRotation(q);
- return q;
- }
-
- /**@brief Set from an array
- * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void setFromOpenGLMatrix(const b3Scalar* m)
- {
- m_basis.setFromOpenGLSubMatrix(m);
- m_origin.setValue(m[12], m[13], m[14]);
- }
-
- /**@brief Fill an array representation
- * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void getOpenGLMatrix(b3Scalar * m) const
- {
- m_basis.getOpenGLSubMatrix(m);
- m[12] = m_origin.getX();
- m[13] = m_origin.getY();
- m[14] = m_origin.getZ();
- m[15] = b3Scalar(1.0);
- }
-
- /**@brief Set the translational element
- * @param origin The vector to set the translation to */
- B3_FORCE_INLINE void setOrigin(const b3Vector3& origin)
- {
- m_origin = origin;
- }
-
- B3_FORCE_INLINE b3Vector3 invXform(const b3Vector3& inVec) const;
-
- /**@brief Set the rotational element by b3Matrix3x3 */
- B3_FORCE_INLINE void setBasis(const b3Matrix3x3& basis)
- {
- m_basis = basis;
- }
-
- /**@brief Set the rotational element by b3Quaternion */
- B3_FORCE_INLINE void setRotation(const b3Quaternion& q)
- {
- m_basis.setRotation(q);
- }
-
- /**@brief Set this transformation to the identity */
- void setIdentity()
- {
- m_basis.setIdentity();
- m_origin.setValue(b3Scalar(0.0), b3Scalar(0.0), b3Scalar(0.0));
- }
-
- /**@brief Multiply this Transform by another(this = this * another)
- * @param t The other transform */
- b3Transform& operator*=(const b3Transform& t)
- {
- m_origin += m_basis * t.m_origin;
- m_basis *= t.m_basis;
- return *this;
- }
-
- /**@brief Return the inverse of this transform */
- b3Transform inverse() const
- {
- b3Matrix3x3 inv = m_basis.transpose();
- return b3Transform(inv, inv * -m_origin);
- }
-
- /**@brief Return the inverse of this transform times the other transform
- * @param t The other transform
- * return this.inverse() * the other */
- b3Transform inverseTimes(const b3Transform& t) const;
-
- /**@brief Return the product of this transform and the other */
- b3Transform operator*(const b3Transform& t) const;
-
- /**@brief Return an identity transform */
- static const b3Transform& getIdentity()
- {
- static const b3Transform identityTransform(b3Matrix3x3::getIdentity());
- return identityTransform;
- }
-
- void serialize(struct b3TransformData & dataOut) const;
-
- void serializeFloat(struct b3TransformFloatData & dataOut) const;
-
- void deSerialize(const struct b3TransformData& dataIn);
-
- void deSerializeDouble(const struct b3TransformDoubleData& dataIn);
-
- void deSerializeFloat(const struct b3TransformFloatData& dataIn);
-};
-
-B3_FORCE_INLINE b3Vector3
-b3Transform::invXform(const b3Vector3& inVec) const
-{
- b3Vector3 v = inVec - m_origin;
- return (m_basis.transpose() * v);
-}
-
-B3_FORCE_INLINE b3Transform
-b3Transform::inverseTimes(const b3Transform& t) const
-{
- b3Vector3 v = t.getOrigin() - m_origin;
- return b3Transform(m_basis.transposeTimes(t.m_basis),
- v * m_basis);
-}
-
-B3_FORCE_INLINE b3Transform
- b3Transform::operator*(const b3Transform& t) const
-{
- return b3Transform(m_basis * t.m_basis,
- (*this)(t.m_origin));
-}
-
-/**@brief Test if two transforms have all elements equal */
-B3_FORCE_INLINE bool operator==(const b3Transform& t1, const b3Transform& t2)
-{
- return (t1.getBasis() == t2.getBasis() &&
- t1.getOrigin() == t2.getOrigin());
-}
-
-///for serialization
-struct b3TransformFloatData
-{
- b3Matrix3x3FloatData m_basis;
- b3Vector3FloatData m_origin;
-};
-
-struct b3TransformDoubleData
-{
- b3Matrix3x3DoubleData m_basis;
- b3Vector3DoubleData m_origin;
-};
-
-B3_FORCE_INLINE void b3Transform::serialize(b3TransformData& dataOut) const
-{
- m_basis.serialize(dataOut.m_basis);
- m_origin.serialize(dataOut.m_origin);
-}
-
-B3_FORCE_INLINE void b3Transform::serializeFloat(b3TransformFloatData& dataOut) const
-{
- m_basis.serializeFloat(dataOut.m_basis);
- m_origin.serializeFloat(dataOut.m_origin);
-}
-
-B3_FORCE_INLINE void b3Transform::deSerialize(const b3TransformData& dataIn)
-{
- m_basis.deSerialize(dataIn.m_basis);
- m_origin.deSerialize(dataIn.m_origin);
-}
-
-B3_FORCE_INLINE void b3Transform::deSerializeFloat(const b3TransformFloatData& dataIn)
-{
- m_basis.deSerializeFloat(dataIn.m_basis);
- m_origin.deSerializeFloat(dataIn.m_origin);
-}
-
-B3_FORCE_INLINE void b3Transform::deSerializeDouble(const b3TransformDoubleData& dataIn)
-{
- m_basis.deSerializeDouble(dataIn.m_basis);
- m_origin.deSerializeDouble(dataIn.m_origin);
-}
-
-#endif //B3_TRANSFORM_H
diff --git a/thirdparty/bullet/Bullet3Common/b3TransformUtil.h b/thirdparty/bullet/Bullet3Common/b3TransformUtil.h
deleted file mode 100644
index 1850a9be5f..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3TransformUtil.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_TRANSFORM_UTIL_H
-#define B3_TRANSFORM_UTIL_H
-
-#include "b3Transform.h"
-#define B3_ANGULAR_MOTION_THRESHOLD b3Scalar(0.5) * B3_HALF_PI
-
-B3_FORCE_INLINE b3Vector3 b3AabbSupport(const b3Vector3& halfExtents, const b3Vector3& supportDir)
-{
- return b3MakeVector3(supportDir.getX() < b3Scalar(0.0) ? -halfExtents.getX() : halfExtents.getX(),
- supportDir.getY() < b3Scalar(0.0) ? -halfExtents.getY() : halfExtents.getY(),
- supportDir.getZ() < b3Scalar(0.0) ? -halfExtents.getZ() : halfExtents.getZ());
-}
-
-/// Utils related to temporal transforms
-class b3TransformUtil
-{
-public:
- static void integrateTransform(const b3Transform& curTrans, const b3Vector3& linvel, const b3Vector3& angvel, b3Scalar timeStep, b3Transform& predictedTransform)
- {
- predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
- // #define QUATERNION_DERIVATIVE
-#ifdef QUATERNION_DERIVATIVE
- b3Quaternion predictedOrn = curTrans.getRotation();
- predictedOrn += (angvel * predictedOrn) * (timeStep * b3Scalar(0.5));
- predictedOrn.normalize();
-#else
- //Exponential map
- //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
-
- b3Vector3 axis;
- b3Scalar fAngle = angvel.length();
- //limit the angular motion
- if (fAngle * timeStep > B3_ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = B3_ANGULAR_MOTION_THRESHOLD / timeStep;
- }
-
- if (fAngle < b3Scalar(0.001))
- {
- // use Taylor's expansions of sync function
- axis = angvel * (b3Scalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (b3Scalar(0.020833333333)) * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (b3Sin(b3Scalar(0.5) * fAngle * timeStep) / fAngle);
- }
- b3Quaternion dorn(axis.getX(), axis.getY(), axis.getZ(), b3Cos(fAngle * timeStep * b3Scalar(0.5)));
- b3Quaternion orn0 = curTrans.getRotation();
-
- b3Quaternion predictedOrn = dorn * orn0;
- predictedOrn.normalize();
-#endif
- predictedTransform.setRotation(predictedOrn);
- }
-
- static void calculateVelocityQuaternion(const b3Vector3& pos0, const b3Vector3& pos1, const b3Quaternion& orn0, const b3Quaternion& orn1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
- {
- linVel = (pos1 - pos0) / timeStep;
- b3Vector3 axis;
- b3Scalar angle;
- if (orn0 != orn1)
- {
- calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
- angVel = axis * angle / timeStep;
- }
- else
- {
- angVel.setValue(0, 0, 0);
- }
- }
-
- static void calculateDiffAxisAngleQuaternion(const b3Quaternion& orn0, const b3Quaternion& orn1a, b3Vector3& axis, b3Scalar& angle)
- {
- b3Quaternion orn1 = orn0.nearest(orn1a);
- b3Quaternion dorn = orn1 * orn0.inverse();
- angle = dorn.getAngle();
- axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
- axis[3] = b3Scalar(0.);
- //check for axis length
- b3Scalar len = axis.length2();
- if (len < B3_EPSILON * B3_EPSILON)
- axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
- else
- axis /= b3Sqrt(len);
- }
-
- static void calculateVelocity(const b3Transform& transform0, const b3Transform& transform1, b3Scalar timeStep, b3Vector3& linVel, b3Vector3& angVel)
- {
- linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
- b3Vector3 axis;
- b3Scalar angle;
- calculateDiffAxisAngle(transform0, transform1, axis, angle);
- angVel = axis * angle / timeStep;
- }
-
- static void calculateDiffAxisAngle(const b3Transform& transform0, const b3Transform& transform1, b3Vector3& axis, b3Scalar& angle)
- {
- b3Matrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
- b3Quaternion dorn;
- dmat.getRotation(dorn);
-
- ///floating point inaccuracy can lead to w component > 1..., which breaks
- dorn.normalize();
-
- angle = dorn.getAngle();
- axis = b3MakeVector3(dorn.getX(), dorn.getY(), dorn.getZ());
- axis[3] = b3Scalar(0.);
- //check for axis length
- b3Scalar len = axis.length2();
- if (len < B3_EPSILON * B3_EPSILON)
- axis = b3MakeVector3(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.));
- else
- axis /= b3Sqrt(len);
- }
-};
-
-///The b3ConvexSeparatingDistanceUtil can help speed up convex collision detection
-///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
-class b3ConvexSeparatingDistanceUtil
-{
- b3Quaternion m_ornA;
- b3Quaternion m_ornB;
- b3Vector3 m_posA;
- b3Vector3 m_posB;
-
- b3Vector3 m_separatingNormal;
-
- b3Scalar m_boundingRadiusA;
- b3Scalar m_boundingRadiusB;
- b3Scalar m_separatingDistance;
-
-public:
- b3ConvexSeparatingDistanceUtil(b3Scalar boundingRadiusA, b3Scalar boundingRadiusB)
- : m_boundingRadiusA(boundingRadiusA),
- m_boundingRadiusB(boundingRadiusB),
- m_separatingDistance(0.f)
- {
- }
-
- b3Scalar getConservativeSeparatingDistance()
- {
- return m_separatingDistance;
- }
-
- void updateSeparatingDistance(const b3Transform& transA, const b3Transform& transB)
- {
- const b3Vector3& toPosA = transA.getOrigin();
- const b3Vector3& toPosB = transB.getOrigin();
- b3Quaternion toOrnA = transA.getRotation();
- b3Quaternion toOrnB = transB.getRotation();
-
- if (m_separatingDistance > 0.f)
- {
- b3Vector3 linVelA, angVelA, linVelB, angVelB;
- b3TransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, b3Scalar(1.), linVelA, angVelA);
- b3TransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, b3Scalar(1.), linVelB, angVelB);
- b3Scalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
- b3Vector3 relLinVel = (linVelB - linVelA);
- b3Scalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
- if (relLinVelocLength < 0.f)
- {
- relLinVelocLength = 0.f;
- }
-
- b3Scalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
- m_separatingDistance -= projectedMotion;
- }
-
- m_posA = toPosA;
- m_posB = toPosB;
- m_ornA = toOrnA;
- m_ornB = toOrnB;
- }
-
- void initSeparatingDistance(const b3Vector3& separatingVector, b3Scalar separatingDistance, const b3Transform& transA, const b3Transform& transB)
- {
- m_separatingDistance = separatingDistance;
-
- if (m_separatingDistance > 0.f)
- {
- m_separatingNormal = separatingVector;
-
- const b3Vector3& toPosA = transA.getOrigin();
- const b3Vector3& toPosB = transB.getOrigin();
- b3Quaternion toOrnA = transA.getRotation();
- b3Quaternion toOrnB = transB.getRotation();
- m_posA = toPosA;
- m_posB = toPosB;
- m_ornA = toOrnA;
- m_ornB = toOrnB;
- }
- }
-};
-
-#endif //B3_TRANSFORM_UTIL_H
diff --git a/thirdparty/bullet/Bullet3Common/b3Vector3.cpp b/thirdparty/bullet/Bullet3Common/b3Vector3.cpp
deleted file mode 100644
index 100fb774c1..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Vector3.cpp
+++ /dev/null
@@ -1,1637 +0,0 @@
-/*
- Copyright (c) 2011-213 Apple Inc. http://bulletphysics.org
-
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- This source version has been altered.
- */
-
-#if defined(_WIN32) || defined(__i386__)
-#define B3_USE_SSE_IN_API
-#endif
-
-#include "b3Vector3.h"
-
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-
-#ifdef __APPLE__
-#include <stdint.h>
-typedef float float4 __attribute__((vector_size(16)));
-#else
-#define float4 __m128
-#endif
-//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
-
-#if defined B3_USE_SSE || defined _WIN32
-
-#define LOG2_ARRAY_SIZE 6
-#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
-
-#include <emmintrin.h>
-
-long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-long b3_maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- const float4 *vertices = (const float4 *)vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
- float4 dotMax = b3Assign128(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
- float4 vvec = _mm_loadu_ps(vec);
- float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa)); /// zzzz
- float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
-
- long maxIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[STACK_ARRAY_COUNT];
-
-#if DEBUG
- // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
-#endif
-
- size_t index;
- float4 max;
- // Faster loop without cleanup code for full tiles
- for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
- {
- max = dotMax;
-
- for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new max
- if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
- {
- // copy the new max across all lanes of our max accumulator
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
-
- dotMax = max;
-
- // find first occurrence of that max
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
- {
- }
- // record where it is.
- maxIndex = 4 * index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- max = dotMax;
- index = 0;
-
- if (b3Unlikely(count > 16))
- {
- for (; index + 4 <= count / 4; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4 * index;
- if (localCount)
- {
-#ifdef __APPLE__
- float4 t0, t1, t2, t3, t4;
- float4 *sap = &stack_array[index + localCount / 4];
- vertices += localCount; // counter the offset
- size_t byteIndex = -(localCount) * sizeof(float);
- //AT&T Code style assembly
- asm volatile(
- ".align 4 \n\
- 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
- movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
- movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
- movaps %[t0], %[max] // vertices[0] \n\
- movlhps %[t1], %[max] // x0y0x1y1 \n\
- movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
- movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
- mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\
- movhlps %[t0], %[t1] // z0w0z1w1 \n\
- movaps %[t3], %[t0] // vertices[2] \n\
- movlhps %[t4], %[t0] // x2y2x3y3 \n\
- mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
- movhlps %[t3], %[t4] // z2w2z3w3 \n\
- shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
- mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
- movaps %[max], %[t3] // x0y0x1y1 * vLo \n\
- shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\
- shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
- addps %[t3], %[max] // x + y \n\
- addps %[t1], %[max] // x + y + z \n\
- movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
- maxps %[t2], %[max] // record max, restore max \n\
- add $16, %[byteIndex] // advance loop counter\n\
- jnz 0b \n\
- "
- : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
- : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
- : "memory", "cc");
- index += localCount / 4;
-#else
- {
- for (unsigned int i = 0; i < localCount / 4; i++, index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
- }
- }
-#endif //__APPLE__
- }
-
- // process the last few points
- if (count & 3)
- {
- float4 v0, v1, v2, x, y, z;
- switch (count & 3)
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
- lo0 = lo0 * vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
- z = z * vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1 * vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy * vLo;
- z = _mm_shuffle_ps(z, z, 0xa8);
- x = _mm_shuffle_ps(xy, xy, 0xa8);
- y = _mm_shuffle_ps(xy, xy, 0xfd);
- z = z * vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps(xy, xy, 0xaa);
- xy = xy * vLo;
- z = z * vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
- index++;
- }
-
- // if we found a new max.
- if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
- { // we found a new max. Search for it
- // find max across the max vector, place in all elements of max -- big latency hit here
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotMax = max;
-
- // scan for the first occurence of max in the array
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
- {
- }
- maxIndex = 4 * index + segment + indexTable[test];
- }
-
- _mm_store_ss(dotResult, dotMax);
- return maxIndex;
-}
-
-long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-
-long b3_mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- const float4 *vertices = (const float4 *)vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
-
- float4 dotmin = b3Assign128(B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY);
- float4 vvec = _mm_loadu_ps(vec);
- float4 vHi = b3CastiTo128f(_mm_shuffle_epi32(b3CastfTo128i(vvec), 0xaa)); /// zzzz
- float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
-
- long minIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[STACK_ARRAY_COUNT];
-
-#if DEBUG
- // memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
-#endif
-
- size_t index;
- float4 min;
- // Faster loop without cleanup code for full tiles
- for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
- {
- min = dotmin;
-
- for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new min
- if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
- {
- // copy the new min across all lanes of our min accumulator
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
-
- dotmin = min;
-
- // find first occurrence of that min
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
- {
- }
- // record where it is.
- minIndex = 4 * index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- min = dotmin;
- index = 0;
-
- if (b3Unlikely(count > 16))
- {
- for (; index + 4 <= count / 4; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4 * index;
- if (localCount)
- {
-#ifdef __APPLE__
- vertices += localCount; // counter the offset
- float4 t0, t1, t2, t3, t4;
- size_t byteIndex = -(localCount) * sizeof(float);
- float4 *sap = &stack_array[index + localCount / 4];
-
- asm volatile(
- ".align 4 \n\
- 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
- movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
- movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
- movaps %[t0], %[min] // vertices[0] \n\
- movlhps %[t1], %[min] // x0y0x1y1 \n\
- movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
- movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
- mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\
- movhlps %[t0], %[t1] // z0w0z1w1 \n\
- movaps %[t3], %[t0] // vertices[2] \n\
- movlhps %[t4], %[t0] // x2y2x3y3 \n\
- movhlps %[t3], %[t4] // z2w2z3w3 \n\
- mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
- shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
- mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
- movaps %[min], %[t3] // x0y0x1y1 * vLo \n\
- shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\
- shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
- addps %[t3], %[min] // x + y \n\
- addps %[t1], %[min] // x + y + z \n\
- movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
- minps %[t2], %[min] // record min, restore min \n\
- add $16, %[byteIndex] // advance loop counter\n\
- jnz 0b \n\
- "
- : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
- : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
- : "memory", "cc");
- index += localCount / 4;
-#else
- {
- for (unsigned int i = 0; i < localCount / 4; i++, index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that max is never NaN even if x is nan
- }
- }
-
-#endif
- }
-
- // process the last few points
- if (count & 3)
- {
- float4 v0, v1, v2, x, y, z;
- switch (count & 3)
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
- lo0 = lo0 * vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
- z = z * vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1 * vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy * vLo;
- z = _mm_shuffle_ps(z, z, 0xa8);
- x = _mm_shuffle_ps(xy, xy, 0xa8);
- y = _mm_shuffle_ps(xy, xy, 0xfd);
- z = z * vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps(xy, xy, 0xaa);
- xy = xy * vLo;
- z = z * vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
- index++;
- }
-
- // if we found a new min.
- if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
- { // we found a new min. Search for it
- // find min across the min vector, place in all elements of min -- big latency hit here
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotmin = min;
-
- // scan for the first occurence of min in the array
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
- {
- }
- minIndex = 4 * index + segment + indexTable[test];
- }
-
- _mm_store_ss(dotResult, dotmin);
- return minIndex;
-}
-
-#elif defined B3_USE_NEON
-#define ARM_NEON_GCC_COMPATIBILITY 1
-#include <arm_neon.h>
-
-static long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-
-long (*b3_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_maxdot_large_sel;
-long (*b3_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = b3_mindot_large_sel;
-
-extern "C"
-{
- int _get_cpu_capabilities(void);
-}
-
-static long b3_maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- if (_get_cpu_capabilities() & 0x2000)
- b3_maxdot_large = _maxdot_large_v1;
- else
- b3_maxdot_large = _maxdot_large_v0;
-
- return b3_maxdot_large(vv, vec, count, dotResult);
-}
-
-static long b3_mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- if (_get_cpu_capabilities() & 0x2000)
- b3_mindot_large = _mindot_large_v1;
- else
- b3_mindot_large = _mindot_large_v0;
-
- return b3_mindot_large(vv, vec, count, dotResult);
-}
-
-#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
-
-long b3_maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMaxLo = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
- float32x2_t dotMaxHi = (float32x2_t){-B3_INFINITY, -B3_INFINITY};
- uint32x2_t indexLo = (uint32x2_t){0, 1};
- uint32x2_t indexHi = (uint32x2_t){2, 3};
- uint32x2_t iLo = (uint32x2_t){-1, -1};
- uint32x2_t iHi = (uint32x2_t){-1, -1};
- const uint32x2_t four = (uint32x2_t){4, 4};
-
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- xy0 = vmul_f32(vget_low_f32(v0), vLo);
- xy1 = vmul_f32(vget_low_f32(v1), vLo);
- xy2 = vmul_f32(vget_low_f32(v2), vLo);
- xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32(z0.val[0], vHi);
- zHi = vmul_f32(z1.val[0], vHi);
-
- rLo = vpadd_f32(xy0, xy1);
- rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vcgt_f32(rLo, dotMaxLo);
- maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32(z0, vHi);
- float32x2_t rLo = vpadd_f32(xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vcgt_f32(dotMaxHi, dotMaxLo);
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32(dotMaxLo, 0);
- return vget_lane_u32(iLo, 0);
-}
-
-long b3_maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
- uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
- float32x4_t maxDot = (float32x4_t){-B3_INFINITY, -B3_INFINITY, -B3_INFINITY, -B3_INFINITY};
-
- unsigned long i = 0;
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32(z0, z1);
- z = vmulq_f32(zb.val[0], vHi);
- xy = vuzpq_f32(xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z0);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32(z, vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
- float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vcgt_f32(maxDotO, maxDot2);
- maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32(maxDot2, 0);
- return vget_lane_u32(index2, 0);
-}
-
-long b3_mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMinLo = (float32x2_t){B3_INFINITY, B3_INFINITY};
- float32x2_t dotMinHi = (float32x2_t){B3_INFINITY, B3_INFINITY};
- uint32x2_t indexLo = (uint32x2_t){0, 1};
- uint32x2_t indexHi = (uint32x2_t){2, 3};
- uint32x2_t iLo = (uint32x2_t){-1, -1};
- uint32x2_t iHi = (uint32x2_t){-1, -1};
- const uint32x2_t four = (uint32x2_t){4, 4};
-
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- xy0 = vmul_f32(vget_low_f32(v0), vLo);
- xy1 = vmul_f32(vget_low_f32(v1), vLo);
- xy2 = vmul_f32(vget_low_f32(v2), vLo);
- xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32(z0.val[0], vHi);
- zHi = vmul_f32(z1.val[0], vHi);
-
- rLo = vpadd_f32(xy0, xy1);
- rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vclt_f32(rLo, dotMinLo);
- maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32(z0, vHi);
- float32x2_t rLo = vpadd_f32(xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMinHi = vdup_lane_f32(dotMinLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vclt_f32(dotMinHi, dotMinLo);
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32(dotMinLo, 0);
- return vget_lane_u32(iLo, 0);
-}
-
-long b3_mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
- uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t){-1, -1, -1, -1};
- float32x4_t minDot = (float32x4_t){B3_INFINITY, B3_INFINITY, B3_INFINITY, B3_INFINITY};
-
- unsigned long i = 0;
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32(z0, z1);
- z = vmulq_f32(zb.val[0], vHi);
- xy = vuzpq_f32(xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z0);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32(z, vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
- float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vclt_f32(minDotO, minDot2);
- minDot2 = vbsl_f32(mask, minDotO, minDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32(minDot2, 0);
- return vget_lane_u32(index2, 0);
-}
-
-#else
-#error Unhandled __APPLE__ arch
-#endif
-
-#endif /* __APPLE__ */
diff --git a/thirdparty/bullet/Bullet3Common/b3Vector3.h b/thirdparty/bullet/Bullet3Common/b3Vector3.h
deleted file mode 100644
index a70d68d6e1..0000000000
--- a/thirdparty/bullet/Bullet3Common/b3Vector3.h
+++ /dev/null
@@ -1,1303 +0,0 @@
-/*
-Copyright (c) 2003-2013 Gino van den Bergen / Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_VECTOR3_H
-#define B3_VECTOR3_H
-
-//#include <stdint.h>
-#include "b3Scalar.h"
-#include "b3MinMax.h"
-#include "b3AlignedAllocator.h"
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define b3Vector3Data b3Vector3DoubleData
-#define b3Vector3DataName "b3Vector3DoubleData"
-#else
-#define b3Vector3Data b3Vector3FloatData
-#define b3Vector3DataName "b3Vector3FloatData"
-#endif //B3_USE_DOUBLE_PRECISION
-
-#if defined B3_USE_SSE
-
-//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
-
-#ifdef _MSC_VER
-#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
-#endif
-
-#define B3_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
-//#define b3_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
-#define b3_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
-#define b3_splat3_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, 3))
-#define b3_splat_ps(_a, _i) b3_pshufd_ps((_a), B3_SHUFFLE(_i, _i, _i, _i))
-
-#define b3v3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define b3vAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define b3vFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
-#define b3v3AbsfMask b3CastiTo128f(b3v3AbsiMask)
-#define b3vFFF0fMask b3CastiTo128f(b3vFFF0Mask)
-#define b3vxyzMaskf b3vFFF0fMask
-#define b3vAbsfMask b3CastiTo128f(b3vAbsMask)
-
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
-const __m128 B3_ATTRIBUTE_ALIGNED16(b3v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
-
-#endif
-
-#ifdef B3_USE_NEON
-
-const float32x4_t B3_ATTRIBUTE_ALIGNED16(b3vMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
-const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vFFF0Mask) = (int32x4_t){0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x0};
-const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3vAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
-const int32x4_t B3_ATTRIBUTE_ALIGNED16(b3v3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
-
-#endif
-
-class b3Vector3;
-class b3Vector4;
-
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-//#if defined (B3_USE_SSE) || defined (B3_USE_NEON)
-inline b3Vector3 b3MakeVector3(b3SimdFloat4 v);
-inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec);
-#endif
-
-inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z);
-inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
-inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w);
-
-/**@brief b3Vector3 can be used to represent 3D points and vectors.
- * It has an un-used w component to suit 16-byte alignment when b3Vector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
- * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
- */
-B3_ATTRIBUTE_ALIGNED16(class)
-b3Vector3
-{
-public:
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
- union {
- b3SimdFloat4 mVec128;
- float m_floats[4];
- struct
- {
- float x, y, z, w;
- };
- };
-#else
- union {
- float m_floats[4];
- struct
- {
- float x, y, z, w;
- };
- };
-#endif
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON) // _WIN32 || ARM
-
- /*B3_FORCE_INLINE b3Vector3()
- {
- }
- */
-
- B3_FORCE_INLINE b3SimdFloat4 get128() const
- {
- return mVec128;
- }
- B3_FORCE_INLINE void set128(b3SimdFloat4 v128)
- {
- mVec128 = v128;
- }
-#endif
-
-public:
- /**@brief Add a vector to this one
- * @param The vector to add to this one */
- B3_FORCE_INLINE b3Vector3& operator+=(const b3Vector3& v)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_add_ps(mVec128, v.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vaddq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] += v.m_floats[0];
- m_floats[1] += v.m_floats[1];
- m_floats[2] += v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Subtract a vector from this one
- * @param The vector to subtract */
- B3_FORCE_INLINE b3Vector3& operator-=(const b3Vector3& v)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_sub_ps(mVec128, v.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vsubq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] -= v.m_floats[0];
- m_floats[1] -= v.m_floats[1];
- m_floats[2] -= v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Scale the vector
- * @param s Scale factor */
- B3_FORCE_INLINE b3Vector3& operator*=(const b3Scalar& s)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
- mVec128 = _mm_mul_ps(mVec128, vs);
-#elif defined(B3_USE_NEON)
- mVec128 = vmulq_n_f32(mVec128, s);
-#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
-#endif
- return *this;
- }
-
- /**@brief Inversely scale the vector
- * @param s Scale factor to divide by */
- B3_FORCE_INLINE b3Vector3& operator/=(const b3Scalar& s)
- {
- b3FullAssert(s != b3Scalar(0.0));
-
-#if 0 //defined(B3_USE_SSE_IN_API)
-// this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(b3v1110, vs);
- vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
-
- mVec128 = _mm_mul_ps(mVec128, vs);
-
- return *this;
-#else
- return *this *= b3Scalar(1.0) / s;
-#endif
- }
-
- /**@brief Return the dot product
- * @param v The other vector in the dot product */
- B3_FORCE_INLINE b3Scalar dot(const b3Vector3& v) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
- return _mm_cvtss_f32(vd);
-#elif defined(B3_USE_NEON)
- float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
- x = vadd_f32(x, vget_high_f32(vd));
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * v.m_floats[0] +
- m_floats[1] * v.m_floats[1] +
- m_floats[2] * v.m_floats[2];
-#endif
- }
-
- /**@brief Return the length of the vector squared */
- B3_FORCE_INLINE b3Scalar length2() const
- {
- return dot(*this);
- }
-
- /**@brief Return the length of the vector */
- B3_FORCE_INLINE b3Scalar length() const
- {
- return b3Sqrt(length2());
- }
-
- /**@brief Return the distance squared between the ends of this and another vector
- * This is symantically treating the vector like a point */
- B3_FORCE_INLINE b3Scalar distance2(const b3Vector3& v) const;
-
- /**@brief Return the distance between the ends of this and another vector
- * This is symantically treating the vector like a point */
- B3_FORCE_INLINE b3Scalar distance(const b3Vector3& v) const;
-
- B3_FORCE_INLINE b3Vector3& safeNormalize()
- {
- b3Scalar l2 = length2();
- //triNormal.normalize();
- if (l2 >= B3_EPSILON * B3_EPSILON)
- {
- (*this) /= b3Sqrt(l2);
- }
- else
- {
- setValue(1, 0, 0);
- }
- return *this;
- }
-
- /**@brief Normalize this vector
- * x^2 + y^2 + z^2 = 1 */
- B3_FORCE_INLINE b3Vector3& normalize()
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- // dot product first
- __m128 vd = _mm_mul_ps(mVec128, mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
-
-#if 0
- vd = _mm_sqrt_ss(vd);
- vd = _mm_div_ss(b3v1110, vd);
- vd = b3_splat_ps(vd, 0x80);
- mVec128 = _mm_mul_ps(mVec128, vd);
-#else
-
- // NR step 1/sqrt(x) - vd is x, y is output
- y = _mm_rsqrt_ss(vd); // estimate
-
- // one step NR
- z = b3v1_5;
- vd = _mm_mul_ss(vd, b3vHalf); // vd * 0.5
- //x2 = vd;
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
- z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
-
- y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
-
- y = b3_splat_ps(y, 0x80);
- mVec128 = _mm_mul_ps(mVec128, y);
-
-#endif
-
- return *this;
-#else
- return *this /= length();
-#endif
- }
-
- /**@brief Return a normalized version of this vector */
- B3_FORCE_INLINE b3Vector3 normalized() const;
-
- /**@brief Return a rotated version of this vector
- * @param wAxis The axis to rotate about
- * @param angle The angle to rotate by */
- B3_FORCE_INLINE b3Vector3 rotate(const b3Vector3& wAxis, const b3Scalar angle) const;
-
- /**@brief Return the angle between this and another vector
- * @param v The other vector */
- B3_FORCE_INLINE b3Scalar angle(const b3Vector3& v) const
- {
- b3Scalar s = b3Sqrt(length2() * v.length2());
- b3FullAssert(s != b3Scalar(0.0));
- return b3Acos(dot(v) / s);
- }
-
- /**@brief Return a vector will the absolute values of each element */
- B3_FORCE_INLINE b3Vector3 absolute() const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3MakeVector3(_mm_and_ps(mVec128, b3v3AbsfMask));
-#elif defined(B3_USE_NEON)
- return b3Vector3(vabsq_f32(mVec128));
-#else
- return b3MakeVector3(
- b3Fabs(m_floats[0]),
- b3Fabs(m_floats[1]),
- b3Fabs(m_floats[2]));
-#endif
- }
-
- /**@brief Return the cross product between this and another vector
- * @param v The other vector */
- B3_FORCE_INLINE b3Vector3 cross(const b3Vector3& v) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 T, V;
-
- T = b3_pshufd_ps(mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = b3_pshufd_ps(v.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
- V = _mm_mul_ps(V, mVec128);
- T = _mm_mul_ps(T, v.mVec128);
- V = _mm_sub_ps(V, T);
-
- V = b3_pshufd_ps(V, B3_SHUFFLE(1, 2, 0, 3));
- return b3MakeVector3(V);
-#elif defined(B3_USE_NEON)
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(mVec128);
- float32x2_t Vlow = vget_low_f32(v.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
-
- V = vmulq_f32(V, mVec128);
- T = vmulq_f32(T, v.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
- V = (float32x4_t)vandq_s32((int32x4_t)V, b3vFFF0Mask);
-
- return b3Vector3(V);
-#else
- return b3MakeVector3(
- m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
- m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
- m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
-#endif
- }
-
- B3_FORCE_INLINE b3Scalar triple(const b3Vector3& v1, const b3Vector3& v2) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- // cross:
- __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, B3_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
- V = _mm_mul_ps(V, v1.mVec128);
- T = _mm_mul_ps(T, v2.mVec128);
- V = _mm_sub_ps(V, T);
-
- V = _mm_shuffle_ps(V, V, B3_SHUFFLE(1, 2, 0, 3));
-
- // dot:
- V = _mm_mul_ps(V, mVec128);
- __m128 z = _mm_movehl_ps(V, V);
- __m128 y = _mm_shuffle_ps(V, V, 0x55);
- V = _mm_add_ss(V, y);
- V = _mm_add_ss(V, z);
- return _mm_cvtss_f32(V);
-
-#elif defined(B3_USE_NEON)
- // cross:
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(v1.mVec128);
- float32x2_t Vlow = vget_low_f32(v2.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
-
- V = vmulq_f32(V, v1.mVec128);
- T = vmulq_f32(T, v2.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
-
- // dot:
- V = vmulq_f32(mVec128, V);
- float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
- x = vadd_f32(x, vget_high_f32(V));
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
- m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
- m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
-#endif
- }
-
- /**@brief Return the axis with the smallest value
- * Note return values are 0,1,2 for x, y, or z */
- B3_FORCE_INLINE int minAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
- }
-
- /**@brief Return the axis with the largest value
- * Note return values are 0,1,2 for x, y, or z */
- B3_FORCE_INLINE int maxAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
- }
-
- B3_FORCE_INLINE int furthestAxis() const
- {
- return absolute().minAxis();
- }
-
- B3_FORCE_INLINE int closestAxis() const
- {
- return absolute().maxAxis();
- }
-
- B3_FORCE_INLINE void setInterpolate3(const b3Vector3& v0, const b3Vector3& v1, b3Scalar rt)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
- b3Scalar s = b3Scalar(1.0) - rt;
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
- __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
- vrt = b3_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
- __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
- __m128 tmp3 = _mm_add_ps(r0, r1);
- mVec128 = tmp3;
-#elif defined(B3_USE_NEON)
- float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
- vl = vmulq_n_f32(vl, rt);
- mVec128 = vaddq_f32(vl, v0.mVec128);
-#else
- b3Scalar s = b3Scalar(1.0) - rt;
- m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
- m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
- m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
- //don't do the unused w component
- // m_co[3] = s * v0[3] + rt * v1[3];
-#endif
- }
-
- /**@brief Return the linear interpolation between this and another vector
- * @param v The other vector
- * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
- B3_FORCE_INLINE b3Vector3 lerp(const b3Vector3& v, const b3Scalar& t) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
- vt = b3_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
- __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
- vl = _mm_mul_ps(vl, vt);
- vl = _mm_add_ps(vl, mVec128);
-
- return b3MakeVector3(vl);
-#elif defined(B3_USE_NEON)
- float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
- vl = vmulq_n_f32(vl, t);
- vl = vaddq_f32(vl, mVec128);
-
- return b3Vector3(vl);
-#else
- return b3MakeVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
-#endif
- }
-
- /**@brief Elementwise multiply this vector by the other
- * @param v The other vector */
- B3_FORCE_INLINE b3Vector3& operator*=(const b3Vector3& v)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_mul_ps(mVec128, v.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vmulq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] *= v.m_floats[0];
- m_floats[1] *= v.m_floats[1];
- m_floats[2] *= v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Return the x value */
- B3_FORCE_INLINE const b3Scalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- B3_FORCE_INLINE const b3Scalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- B3_FORCE_INLINE const b3Scalar& getZ() const { return m_floats[2]; }
- /**@brief Return the w value */
- B3_FORCE_INLINE const b3Scalar& getW() const { return m_floats[3]; }
-
- /**@brief Set the x value */
- B3_FORCE_INLINE void setX(b3Scalar _x) { m_floats[0] = _x; };
- /**@brief Set the y value */
- B3_FORCE_INLINE void setY(b3Scalar _y) { m_floats[1] = _y; };
- /**@brief Set the z value */
- B3_FORCE_INLINE void setZ(b3Scalar _z) { m_floats[2] = _z; };
- /**@brief Set the w value */
- B3_FORCE_INLINE void setW(b3Scalar _w) { m_floats[3] = _w; };
-
- //B3_FORCE_INLINE b3Scalar& operator[](int i) { return (&m_floats[0])[i]; }
- //B3_FORCE_INLINE const b3Scalar& operator[](int i) const { return (&m_floats[0])[i]; }
- ///operator b3Scalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- B3_FORCE_INLINE operator b3Scalar*() { return &m_floats[0]; }
- B3_FORCE_INLINE operator const b3Scalar*() const { return &m_floats[0]; }
-
- B3_FORCE_INLINE bool operator==(const b3Vector3& other) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3] == other.m_floats[3]) &&
- (m_floats[2] == other.m_floats[2]) &&
- (m_floats[1] == other.m_floats[1]) &&
- (m_floats[0] == other.m_floats[0]));
-#endif
- }
-
- B3_FORCE_INLINE bool operator!=(const b3Vector3& other) const
- {
- return !(*this == other);
- }
-
- /**@brief Set each element to the max of the current values and the values of another b3Vector3
- * @param other The other b3Vector3 to compare with
- */
- B3_FORCE_INLINE void setMax(const b3Vector3& other)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
-#else
- b3SetMax(m_floats[0], other.m_floats[0]);
- b3SetMax(m_floats[1], other.m_floats[1]);
- b3SetMax(m_floats[2], other.m_floats[2]);
- b3SetMax(m_floats[3], other.m_floats[3]);
-#endif
- }
-
- /**@brief Set each element to the min of the current values and the values of another b3Vector3
- * @param other The other b3Vector3 to compare with
- */
- B3_FORCE_INLINE void setMin(const b3Vector3& other)
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
-#elif defined(B3_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
-#else
- b3SetMin(m_floats[0], other.m_floats[0]);
- b3SetMin(m_floats[1], other.m_floats[1]);
- b3SetMin(m_floats[2], other.m_floats[2]);
- b3SetMin(m_floats[3], other.m_floats[3]);
-#endif
- }
-
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = b3Scalar(0.f);
- }
-
- void getSkewSymmetricMatrix(b3Vector3 * v0, b3Vector3 * v1, b3Vector3 * v2) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-
- __m128 V = _mm_and_ps(mVec128, b3vFFF0fMask);
- __m128 V0 = _mm_xor_ps(b3vMzeroMask, V);
- __m128 V2 = _mm_movelh_ps(V0, V);
-
- __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
-
- V0 = _mm_shuffle_ps(V0, V, 0xDB);
- V2 = _mm_shuffle_ps(V2, V, 0xF9);
-
- v0->mVec128 = V0;
- v1->mVec128 = V1;
- v2->mVec128 = V2;
-#else
- v0->setValue(0., -getZ(), getY());
- v1->setValue(getZ(), 0., -getX());
- v2->setValue(-getY(), getX(), 0.);
-#endif
- }
-
- void setZero()
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
-#elif defined(B3_USE_NEON)
- int32x4_t vi = vdupq_n_s32(0);
- mVec128 = vreinterpretq_f32_s32(vi);
-#else
- setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
-#endif
- }
-
- B3_FORCE_INLINE bool isZero() const
- {
- return m_floats[0] == b3Scalar(0) && m_floats[1] == b3Scalar(0) && m_floats[2] == b3Scalar(0);
- }
-
- B3_FORCE_INLINE bool fuzzyZero() const
- {
- return length2() < B3_EPSILON;
- }
-
- B3_FORCE_INLINE void serialize(struct b3Vector3Data & dataOut) const;
-
- B3_FORCE_INLINE void deSerialize(const struct b3Vector3Data& dataIn);
-
- B3_FORCE_INLINE void serializeFloat(struct b3Vector3FloatData & dataOut) const;
-
- B3_FORCE_INLINE void deSerializeFloat(const struct b3Vector3FloatData& dataIn);
-
- B3_FORCE_INLINE void serializeDouble(struct b3Vector3DoubleData & dataOut) const;
-
- B3_FORCE_INLINE void deSerializeDouble(const struct b3Vector3DoubleData& dataIn);
-
- /**@brief returns index of maximum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The maximum dot product */
- B3_FORCE_INLINE long maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
-
- /**@brief returns index of minimum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The minimum dot product */
- B3_FORCE_INLINE long minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const;
-
- /* create a vector as b3Vector3( this->dot( b3Vector3 v0 ), this->dot( b3Vector3 v1), this->dot( b3Vector3 v2 )) */
- B3_FORCE_INLINE b3Vector3 dot3(const b3Vector3& v0, const b3Vector3& v1, const b3Vector3& v2) const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-
- __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
- __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
- __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
- __m128 b0 = _mm_unpacklo_ps(a0, a1);
- __m128 b1 = _mm_unpackhi_ps(a0, a1);
- __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
- __m128 r = _mm_movelh_ps(b0, b2);
- r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
- a2 = _mm_and_ps(a2, b3vxyzMaskf);
- r = _mm_add_ps(r, b3CastdTo128f(_mm_move_sd(b3CastfTo128d(a2), b3CastfTo128d(b1))));
- return b3MakeVector3(r);
-
-#elif defined(B3_USE_NEON)
- static const uint32x4_t xyzMask = (const uint32x4_t){-1, -1, -1, 0};
- float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
- float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
- float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
- float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
- a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
- float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
- float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
- return b3Vector3(vcombine_f32(b0, b1));
-#else
- return b3MakeVector3(dot(v0), dot(v1), dot(v2));
-#endif
- }
-};
-
-/**@brief Return the sum of two vectors (Point symantics)*/
-B3_FORCE_INLINE b3Vector3
-operator+(const b3Vector3& v1, const b3Vector3& v2)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3MakeVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
-#elif defined(B3_USE_NEON)
- return b3MakeVector3(vaddq_f32(v1.mVec128, v2.mVec128));
-#else
- return b3MakeVector3(
- v1.m_floats[0] + v2.m_floats[0],
- v1.m_floats[1] + v2.m_floats[1],
- v1.m_floats[2] + v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the elementwise product of two vectors */
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Vector3& v1, const b3Vector3& v2)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3MakeVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
-#elif defined(B3_USE_NEON)
- return b3MakeVector3(vmulq_f32(v1.mVec128, v2.mVec128));
-#else
- return b3MakeVector3(
- v1.m_floats[0] * v2.m_floats[0],
- v1.m_floats[1] * v2.m_floats[1],
- v1.m_floats[2] * v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the difference between two vectors */
-B3_FORCE_INLINE b3Vector3
-operator-(const b3Vector3& v1, const b3Vector3& v2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
-
- // without _mm_and_ps this code causes slowdown in Concave moving
- __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
- return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
-#elif defined(B3_USE_NEON)
- float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
- return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
-#else
- return b3MakeVector3(
- v1.m_floats[0] - v2.m_floats[0],
- v1.m_floats[1] - v2.m_floats[1],
- v1.m_floats[2] - v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the negative of the vector */
-B3_FORCE_INLINE b3Vector3
-operator-(const b3Vector3& v)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- __m128 r = _mm_xor_ps(v.mVec128, b3vMzeroMask);
- return b3MakeVector3(_mm_and_ps(r, b3vFFF0fMask));
-#elif defined(B3_USE_NEON)
- return b3MakeVector3((b3SimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)b3vMzeroMask));
-#else
- return b3MakeVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
-#endif
-}
-
-/**@brief Return the vector scaled by s */
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Vector3& v, const b3Scalar& s)
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = b3_pshufd_ps(vs, 0x80); // (S S S 0.0)
- return b3MakeVector3(_mm_mul_ps(v.mVec128, vs));
-#elif defined(B3_USE_NEON)
- float32x4_t r = vmulq_n_f32(v.mVec128, s);
- return b3MakeVector3((float32x4_t)vandq_s32((int32x4_t)r, b3vFFF0Mask));
-#else
- return b3MakeVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
-#endif
-}
-
-/**@brief Return the vector scaled by s */
-B3_FORCE_INLINE b3Vector3
-operator*(const b3Scalar& s, const b3Vector3& v)
-{
- return v * s;
-}
-
-/**@brief Return the vector inversely scaled by s */
-B3_FORCE_INLINE b3Vector3
-operator/(const b3Vector3& v, const b3Scalar& s)
-{
- b3FullAssert(s != b3Scalar(0.0));
-#if 0 //defined(B3_USE_SSE_IN_API)
-// this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(b3v1110, vs);
- vs = b3_pshufd_ps(vs, 0x00); // (S S S S)
-
- return b3Vector3(_mm_mul_ps(v.mVec128, vs));
-#else
- return v * (b3Scalar(1.0) / s);
-#endif
-}
-
-/**@brief Return the vector inversely scaled by s */
-B3_FORCE_INLINE b3Vector3
-operator/(const b3Vector3& v1, const b3Vector3& v2)
-{
-#if (defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE))
- __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
- vec = _mm_and_ps(vec, b3vFFF0fMask);
- return b3MakeVector3(vec);
-#elif defined(B3_USE_NEON)
- float32x4_t x, y, v, m;
-
- x = v1.mVec128;
- y = v2.mVec128;
-
- v = vrecpeq_f32(y); // v ~ 1/y
- m = vrecpsq_f32(y, v); // m = (2-v*y)
- v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
- m = vrecpsq_f32(y, v); // mm = (2-vv*y)
- v = vmulq_f32(v, x); // x*vv
- v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
-
- return b3Vector3(v);
-#else
- return b3MakeVector3(
- v1.m_floats[0] / v2.m_floats[0],
- v1.m_floats[1] / v2.m_floats[1],
- v1.m_floats[2] / v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the dot product between two vectors */
-B3_FORCE_INLINE b3Scalar
-b3Dot(const b3Vector3& v1, const b3Vector3& v2)
-{
- return v1.dot(v2);
-}
-
-/**@brief Return the distance squared between two vectors */
-B3_FORCE_INLINE b3Scalar
-b3Distance2(const b3Vector3& v1, const b3Vector3& v2)
-{
- return v1.distance2(v2);
-}
-
-/**@brief Return the distance between two vectors */
-B3_FORCE_INLINE b3Scalar
-b3Distance(const b3Vector3& v1, const b3Vector3& v2)
-{
- return v1.distance(v2);
-}
-
-/**@brief Return the angle between two vectors */
-B3_FORCE_INLINE b3Scalar
-b3Angle(const b3Vector3& v1, const b3Vector3& v2)
-{
- return v1.angle(v2);
-}
-
-/**@brief Return the cross product of two vectors */
-B3_FORCE_INLINE b3Vector3
-b3Cross(const b3Vector3& v1, const b3Vector3& v2)
-{
- return v1.cross(v2);
-}
-
-B3_FORCE_INLINE b3Scalar
-b3Triple(const b3Vector3& v1, const b3Vector3& v2, const b3Vector3& v3)
-{
- return v1.triple(v2, v3);
-}
-
-/**@brief Return the linear interpolation between two vectors
- * @param v1 One vector
- * @param v2 The other vector
- * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
-B3_FORCE_INLINE b3Vector3
-b3Lerp(const b3Vector3& v1, const b3Vector3& v2, const b3Scalar& t)
-{
- return v1.lerp(v2, t);
-}
-
-B3_FORCE_INLINE b3Scalar b3Vector3::distance2(const b3Vector3& v) const
-{
- return (v - *this).length2();
-}
-
-B3_FORCE_INLINE b3Scalar b3Vector3::distance(const b3Vector3& v) const
-{
- return (v - *this).length();
-}
-
-B3_FORCE_INLINE b3Vector3 b3Vector3::normalized() const
-{
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- b3Vector3 norm = *this;
-
- return norm.normalize();
-#else
- return *this / length();
-#endif
-}
-
-B3_FORCE_INLINE b3Vector3 b3Vector3::rotate(const b3Vector3& wAxis, const b3Scalar _angle) const
-{
- // wAxis must be a unit lenght vector
-
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-
- __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
- b3Scalar ssin = b3Sin(_angle);
- __m128 C = wAxis.cross(b3MakeVector3(mVec128)).mVec128;
- O = _mm_and_ps(O, b3vFFF0fMask);
- b3Scalar scos = b3Cos(_angle);
-
- __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
- __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
-
- __m128 Y = b3_pshufd_ps(O, 0xC9); // (Y Z X 0)
- __m128 Z = b3_pshufd_ps(O, 0xD2); // (Z X Y 0)
- O = _mm_add_ps(O, Y);
- vsin = b3_pshufd_ps(vsin, 0x80); // (S S S 0)
- O = _mm_add_ps(O, Z);
- vcos = b3_pshufd_ps(vcos, 0x80); // (S S S 0)
-
- vsin = vsin * C;
- O = O * wAxis.mVec128;
- __m128 X = mVec128 - O;
-
- O = O + vsin;
- vcos = vcos * X;
- O = O + vcos;
-
- return b3MakeVector3(O);
-#else
- b3Vector3 o = wAxis * wAxis.dot(*this);
- b3Vector3 _x = *this - o;
- b3Vector3 _y;
-
- _y = wAxis.cross(*this);
-
- return (o + _x * b3Cos(_angle) + _y * b3Sin(_angle));
-#endif
-}
-
-B3_FORCE_INLINE long b3Vector3::maxDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
-{
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-#if defined _WIN32 || defined(B3_USE_SSE)
- const long scalar_cutoff = 10;
- long b3_maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#elif defined B3_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#endif
- if (array_count < scalar_cutoff)
-#else
-
-#endif //B3_USE_SSE || B3_USE_NEON
- {
- b3Scalar maxDot = -B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for (i = 0; i < array_count; i++)
- {
- b3Scalar dot = array[i].dot(*this);
-
- if (dot > maxDot)
- {
- maxDot = dot;
- ptIndex = i;
- }
- }
-
- b3Assert(ptIndex >= 0);
- if (ptIndex < 0)
- {
- ptIndex = 0;
- }
- dotOut = maxDot;
- return ptIndex;
- }
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
- return b3_maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
-#endif
-}
-
-B3_FORCE_INLINE long b3Vector3::minDot(const b3Vector3* array, long array_count, b3Scalar& dotOut) const
-{
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
-#if defined B3_USE_SSE
- const long scalar_cutoff = 10;
- long b3_mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#elif defined B3_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*b3_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#else
-#error unhandled arch!
-#endif
-
- if (array_count < scalar_cutoff)
-#endif //B3_USE_SSE || B3_USE_NEON
- {
- b3Scalar minDot = B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
-
- for (i = 0; i < array_count; i++)
- {
- b3Scalar dot = array[i].dot(*this);
-
- if (dot < minDot)
- {
- minDot = dot;
- ptIndex = i;
- }
- }
-
- dotOut = minDot;
-
- return ptIndex;
- }
-#if defined(B3_USE_SSE) || defined(B3_USE_NEON)
- return b3_mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
-#endif
-}
-
-class b3Vector4 : public b3Vector3
-{
-public:
- B3_FORCE_INLINE b3Vector4 absolute4() const
- {
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
- return b3MakeVector4(_mm_and_ps(mVec128, b3vAbsfMask));
-#elif defined(B3_USE_NEON)
- return b3Vector4(vabsq_f32(mVec128));
-#else
- return b3MakeVector4(
- b3Fabs(m_floats[0]),
- b3Fabs(m_floats[1]),
- b3Fabs(m_floats[2]),
- b3Fabs(m_floats[3]));
-#endif
- }
-
- b3Scalar getW() const { return m_floats[3]; }
-
- B3_FORCE_INLINE int maxAxis4() const
- {
- int maxIndex = -1;
- b3Scalar maxVal = b3Scalar(-B3_LARGE_FLOAT);
- if (m_floats[0] > maxVal)
- {
- maxIndex = 0;
- maxVal = m_floats[0];
- }
- if (m_floats[1] > maxVal)
- {
- maxIndex = 1;
- maxVal = m_floats[1];
- }
- if (m_floats[2] > maxVal)
- {
- maxIndex = 2;
- maxVal = m_floats[2];
- }
- if (m_floats[3] > maxVal)
- {
- maxIndex = 3;
- }
-
- return maxIndex;
- }
-
- B3_FORCE_INLINE int minAxis4() const
- {
- int minIndex = -1;
- b3Scalar minVal = b3Scalar(B3_LARGE_FLOAT);
- if (m_floats[0] < minVal)
- {
- minIndex = 0;
- minVal = m_floats[0];
- }
- if (m_floats[1] < minVal)
- {
- minIndex = 1;
- minVal = m_floats[1];
- }
- if (m_floats[2] < minVal)
- {
- minIndex = 2;
- minVal = m_floats[2];
- }
- if (m_floats[3] < minVal)
- {
- minIndex = 3;
- minVal = m_floats[3];
- }
-
- return minIndex;
- }
-
- B3_FORCE_INLINE int closestAxis4() const
- {
- return absolute4().maxAxis4();
- }
-
- /**@brief Set x,y,z and zero w
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
-
- /* void getValue(b3Scalar *m) const
- {
- m[0] = m_floats[0];
- m[1] = m_floats[1];
- m[2] =m_floats[2];
- }
-*/
- /**@brief Set the values
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- B3_FORCE_INLINE void setValue(const b3Scalar& _x, const b3Scalar& _y, const b3Scalar& _z, const b3Scalar& _w)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = _w;
- }
-};
-
-///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3SwapScalarEndian(const b3Scalar& sourceVal, b3Scalar& destVal)
-{
-#ifdef B3_USE_DOUBLE_PRECISION
- unsigned char* dest = (unsigned char*)&destVal;
- unsigned char* src = (unsigned char*)&sourceVal;
- dest[0] = src[7];
- dest[1] = src[6];
- dest[2] = src[5];
- dest[3] = src[4];
- dest[4] = src[3];
- dest[5] = src[2];
- dest[6] = src[1];
- dest[7] = src[0];
-#else
- unsigned char* dest = (unsigned char*)&destVal;
- unsigned char* src = (unsigned char*)&sourceVal;
- dest[0] = src[3];
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
-#endif //B3_USE_DOUBLE_PRECISION
-}
-///b3SwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3SwapVector3Endian(const b3Vector3& sourceVec, b3Vector3& destVec)
-{
- for (int i = 0; i < 4; i++)
- {
- b3SwapScalarEndian(sourceVec[i], destVec[i]);
- }
-}
-
-///b3UnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-B3_FORCE_INLINE void b3UnSwapVector3Endian(b3Vector3& vector)
-{
- b3Vector3 swappedVec;
- for (int i = 0; i < 4; i++)
- {
- b3SwapScalarEndian(vector[i], swappedVec[i]);
- }
- vector = swappedVec;
-}
-
-template <class T>
-B3_FORCE_INLINE void b3PlaneSpace1(const T& n, T& p, T& q)
-{
- if (b3Fabs(n[2]) > B3_SQRT12)
- {
- // choose p in y-z plane
- b3Scalar a = n[1] * n[1] + n[2] * n[2];
- b3Scalar k = b3RecipSqrt(a);
- p[0] = 0;
- p[1] = -n[2] * k;
- p[2] = n[1] * k;
- // set q = n x p
- q[0] = a * k;
- q[1] = -n[0] * p[2];
- q[2] = n[0] * p[1];
- }
- else
- {
- // choose p in x-y plane
- b3Scalar a = n[0] * n[0] + n[1] * n[1];
- b3Scalar k = b3RecipSqrt(a);
- p[0] = -n[1] * k;
- p[1] = n[0] * k;
- p[2] = 0;
- // set q = n x p
- q[0] = -n[2] * p[1];
- q[1] = n[2] * p[0];
- q[2] = a * k;
- }
-}
-
-struct b3Vector3FloatData
-{
- float m_floats[4];
-};
-
-struct b3Vector3DoubleData
-{
- double m_floats[4];
-};
-
-B3_FORCE_INLINE void b3Vector3::serializeFloat(struct b3Vector3FloatData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = float(m_floats[i]);
-}
-
-B3_FORCE_INLINE void b3Vector3::deSerializeFloat(const struct b3Vector3FloatData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = b3Scalar(dataIn.m_floats[i]);
-}
-
-B3_FORCE_INLINE void b3Vector3::serializeDouble(struct b3Vector3DoubleData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = double(m_floats[i]);
-}
-
-B3_FORCE_INLINE void b3Vector3::deSerializeDouble(const struct b3Vector3DoubleData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = b3Scalar(dataIn.m_floats[i]);
-}
-
-B3_FORCE_INLINE void b3Vector3::serialize(struct b3Vector3Data& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = m_floats[i];
-}
-
-B3_FORCE_INLINE void b3Vector3::deSerialize(const struct b3Vector3Data& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = dataIn.m_floats[i];
-}
-
-inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z)
-{
- b3Vector3 tmp;
- tmp.setValue(x, y, z);
- return tmp;
-}
-
-inline b3Vector3 b3MakeVector3(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
-{
- b3Vector3 tmp;
- tmp.setValue(x, y, z);
- tmp.w = w;
- return tmp;
-}
-
-inline b3Vector4 b3MakeVector4(b3Scalar x, b3Scalar y, b3Scalar z, b3Scalar w)
-{
- b3Vector4 tmp;
- tmp.setValue(x, y, z, w);
- return tmp;
-}
-
-#if defined(B3_USE_SSE_IN_API) && defined(B3_USE_SSE)
-
-inline b3Vector3 b3MakeVector3(b3SimdFloat4 v)
-{
- b3Vector3 tmp;
- tmp.set128(v);
- return tmp;
-}
-
-inline b3Vector4 b3MakeVector4(b3SimdFloat4 vec)
-{
- b3Vector4 tmp;
- tmp.set128(vec);
- return tmp;
-}
-
-#endif
-
-#endif //B3_VECTOR3_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Float4.h b/thirdparty/bullet/Bullet3Common/shared/b3Float4.h
deleted file mode 100644
index d8a9f47411..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3Float4.h
+++ /dev/null
@@ -1,90 +0,0 @@
-#ifndef B3_FLOAT4_H
-#define B3_FLOAT4_H
-
-#include "Bullet3Common/shared/b3PlatformDefinitions.h"
-
-#ifdef __cplusplus
-#include "Bullet3Common/b3Vector3.h"
-#define b3Float4 b3Vector3
-#define b3Float4ConstArg const b3Vector3&
-#define b3Dot3F4 b3Dot
-#define b3Cross3 b3Cross
-#define b3MakeFloat4 b3MakeVector3
-inline b3Vector3 b3Normalized(const b3Vector3& vec)
-{
- return vec.normalized();
-}
-
-inline b3Float4 b3FastNormalized3(b3Float4ConstArg v)
-{
- return v.normalized();
-}
-
-inline b3Float4 b3MaxFloat4(const b3Float4& a, const b3Float4& b)
-{
- b3Float4 tmp = a;
- tmp.setMax(b);
- return tmp;
-}
-inline b3Float4 b3MinFloat4(const b3Float4& a, const b3Float4& b)
-{
- b3Float4 tmp = a;
- tmp.setMin(b);
- return tmp;
-}
-
-#else
-typedef float4 b3Float4;
-#define b3Float4ConstArg const b3Float4
-#define b3MakeFloat4 (float4)
-float b3Dot3F4(b3Float4ConstArg v0, b3Float4ConstArg v1)
-{
- float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
- float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
- return dot(a1, b1);
-}
-b3Float4 b3Cross3(b3Float4ConstArg v0, b3Float4ConstArg v1)
-{
- float4 a1 = b3MakeFloat4(v0.xyz, 0.f);
- float4 b1 = b3MakeFloat4(v1.xyz, 0.f);
- return cross(a1, b1);
-}
-#define b3MinFloat4 min
-#define b3MaxFloat4 max
-
-#define b3Normalized(a) normalize(a)
-
-#endif
-
-inline bool b3IsAlmostZero(b3Float4ConstArg v)
-{
- if (b3Fabs(v.x) > 1e-6 || b3Fabs(v.y) > 1e-6 || b3Fabs(v.z) > 1e-6)
- return false;
- return true;
-}
-
-inline int b3MaxDot(b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut)
-{
- float maxDot = -B3_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for (i = 0; i < vecLen; i++)
- {
- float dot = b3Dot3F4(vecArray[i], vec);
-
- if (dot > maxDot)
- {
- maxDot = dot;
- ptIndex = i;
- }
- }
- b3Assert(ptIndex >= 0);
- if (ptIndex < 0)
- {
- ptIndex = 0;
- }
- *dotOut = maxDot;
- return ptIndex;
-}
-
-#endif //B3_FLOAT4_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Int2.h b/thirdparty/bullet/Bullet3Common/shared/b3Int2.h
deleted file mode 100644
index 7b84de4436..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3Int2.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_INT2_H
-#define B3_INT2_H
-
-#ifdef __cplusplus
-
-struct b3UnsignedInt2
-{
- union {
- struct
- {
- unsigned int x, y;
- };
- struct
- {
- unsigned int s[2];
- };
- };
-};
-
-struct b3Int2
-{
- union {
- struct
- {
- int x, y;
- };
- struct
- {
- int s[2];
- };
- };
-};
-
-inline b3Int2 b3MakeInt2(int x, int y)
-{
- b3Int2 v;
- v.s[0] = x;
- v.s[1] = y;
- return v;
-}
-#else
-
-#define b3UnsignedInt2 uint2
-#define b3Int2 int2
-#define b3MakeInt2 (int2)
-
-#endif //__cplusplus
-#endif \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Int4.h b/thirdparty/bullet/Bullet3Common/shared/b3Int4.h
deleted file mode 100644
index f6a1754245..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3Int4.h
+++ /dev/null
@@ -1,71 +0,0 @@
-#ifndef B3_INT4_H
-#define B3_INT4_H
-
-#ifdef __cplusplus
-
-#include "Bullet3Common/b3Scalar.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3UnsignedInt4
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- union {
- struct
- {
- unsigned int x, y, z, w;
- };
- struct
- {
- unsigned int s[4];
- };
- };
-};
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3Int4
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- union {
- struct
- {
- int x, y, z, w;
- };
- struct
- {
- int s[4];
- };
- };
-};
-
-B3_FORCE_INLINE b3Int4 b3MakeInt4(int x, int y, int z, int w = 0)
-{
- b3Int4 v;
- v.s[0] = x;
- v.s[1] = y;
- v.s[2] = z;
- v.s[3] = w;
- return v;
-}
-
-B3_FORCE_INLINE b3UnsignedInt4 b3MakeUnsignedInt4(unsigned int x, unsigned int y, unsigned int z, unsigned int w = 0)
-{
- b3UnsignedInt4 v;
- v.s[0] = x;
- v.s[1] = y;
- v.s[2] = z;
- v.s[3] = w;
- return v;
-}
-
-#else
-
-#define b3UnsignedInt4 uint4
-#define b3Int4 int4
-#define b3MakeInt4 (int4)
-#define b3MakeUnsignedInt4 (uint4)
-
-#endif //__cplusplus
-
-#endif //B3_INT4_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h b/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h
deleted file mode 100644
index ce6482b5a6..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3Mat3x3.h
+++ /dev/null
@@ -1,157 +0,0 @@
-
-#ifndef B3_MAT3x3_H
-#define B3_MAT3x3_H
-
-#include "Bullet3Common/shared/b3Quat.h"
-
-#ifdef __cplusplus
-
-#include "Bullet3Common/b3Matrix3x3.h"
-
-#define b3Mat3x3 b3Matrix3x3
-#define b3Mat3x3ConstArg const b3Matrix3x3&
-
-inline b3Mat3x3 b3QuatGetRotationMatrix(b3QuatConstArg quat)
-{
- return b3Mat3x3(quat);
-}
-
-inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg mat)
-{
- return mat.absolute();
-}
-
-#define b3GetRow(m, row) m.getRow(row)
-
-__inline b3Float4 mtMul3(b3Float4ConstArg a, b3Mat3x3ConstArg b)
-{
- return b * a;
-}
-
-#else
-
-typedef struct
-{
- b3Float4 m_row[3];
-} b3Mat3x3;
-
-#define b3Mat3x3ConstArg const b3Mat3x3
-#define b3GetRow(m, row) (m.m_row[row])
-
-inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)
-{
- b3Float4 quat2 = (b3Float4)(quat.x * quat.x, quat.y * quat.y, quat.z * quat.z, 0.f);
- b3Mat3x3 out;
-
- out.m_row[0].x = 1 - 2 * quat2.y - 2 * quat2.z;
- out.m_row[0].y = 2 * quat.x * quat.y - 2 * quat.w * quat.z;
- out.m_row[0].z = 2 * quat.x * quat.z + 2 * quat.w * quat.y;
- out.m_row[0].w = 0.f;
-
- out.m_row[1].x = 2 * quat.x * quat.y + 2 * quat.w * quat.z;
- out.m_row[1].y = 1 - 2 * quat2.x - 2 * quat2.z;
- out.m_row[1].z = 2 * quat.y * quat.z - 2 * quat.w * quat.x;
- out.m_row[1].w = 0.f;
-
- out.m_row[2].x = 2 * quat.x * quat.z - 2 * quat.w * quat.y;
- out.m_row[2].y = 2 * quat.y * quat.z + 2 * quat.w * quat.x;
- out.m_row[2].z = 1 - 2 * quat2.x - 2 * quat2.y;
- out.m_row[2].w = 0.f;
-
- return out;
-}
-
-inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)
-{
- b3Mat3x3 out;
- out.m_row[0] = fabs(matIn.m_row[0]);
- out.m_row[1] = fabs(matIn.m_row[1]);
- out.m_row[2] = fabs(matIn.m_row[2]);
- return out;
-}
-
-__inline b3Mat3x3 mtZero();
-
-__inline b3Mat3x3 mtIdentity();
-
-__inline b3Mat3x3 mtTranspose(b3Mat3x3 m);
-
-__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);
-
-__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);
-
-__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);
-
-__inline b3Mat3x3 mtZero()
-{
- b3Mat3x3 m;
- m.m_row[0] = (b3Float4)(0.f);
- m.m_row[1] = (b3Float4)(0.f);
- m.m_row[2] = (b3Float4)(0.f);
- return m;
-}
-
-__inline b3Mat3x3 mtIdentity()
-{
- b3Mat3x3 m;
- m.m_row[0] = (b3Float4)(1, 0, 0, 0);
- m.m_row[1] = (b3Float4)(0, 1, 0, 0);
- m.m_row[2] = (b3Float4)(0, 0, 1, 0);
- return m;
-}
-
-__inline b3Mat3x3 mtTranspose(b3Mat3x3 m)
-{
- b3Mat3x3 out;
- out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
- out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
- out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
- return out;
-}
-
-__inline b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)
-{
- b3Mat3x3 transB;
- transB = mtTranspose(b);
- b3Mat3x3 ans;
- // why this doesn't run when 0ing in the for{}
- a.m_row[0].w = 0.f;
- a.m_row[1].w = 0.f;
- a.m_row[2].w = 0.f;
- for (int i = 0; i < 3; i++)
- {
- // a.m_row[i].w = 0.f;
- ans.m_row[i].x = b3Dot3F4(a.m_row[i], transB.m_row[0]);
- ans.m_row[i].y = b3Dot3F4(a.m_row[i], transB.m_row[1]);
- ans.m_row[i].z = b3Dot3F4(a.m_row[i], transB.m_row[2]);
- ans.m_row[i].w = 0.f;
- }
- return ans;
-}
-
-__inline b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)
-{
- b3Float4 ans;
- ans.x = b3Dot3F4(a.m_row[0], b);
- ans.y = b3Dot3F4(a.m_row[1], b);
- ans.z = b3Dot3F4(a.m_row[2], b);
- ans.w = 0.f;
- return ans;
-}
-
-__inline b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)
-{
- b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- b3Float4 ans;
- ans.x = b3Dot3F4(a, colx);
- ans.y = b3Dot3F4(a, coly);
- ans.z = b3Dot3F4(a, colz);
- return ans;
-}
-
-#endif
-
-#endif //B3_MAT3x3_H
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h b/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h
deleted file mode 100644
index b72bee9310..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3PlatformDefinitions.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef B3_PLATFORM_DEFINITIONS_H
-#define B3_PLATFORM_DEFINITIONS_H
-
-struct MyTest
-{
- int bla;
-};
-
-#ifdef __cplusplus
-//#define b3ConstArray(a) const b3AlignedObjectArray<a>&
-#define b3ConstArray(a) const a *
-#define b3AtomicInc(a) ((*a)++)
-
-inline int b3AtomicAdd(volatile int *p, int val)
-{
- int oldValue = *p;
- int newValue = oldValue + val;
- *p = newValue;
- return oldValue;
-}
-
-#define __global
-
-#define B3_STATIC static
-#else
-//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX
-#define B3_LARGE_FLOAT 1e18f
-#define B3_INFINITY 1e18f
-#define b3Assert(a)
-#define b3ConstArray(a) __global const a *
-#define b3AtomicInc atomic_inc
-#define b3AtomicAdd atomic_add
-#define b3Fabs fabs
-#define b3Sqrt native_sqrt
-#define b3Sin native_sin
-#define b3Cos native_cos
-
-#define B3_STATIC
-#endif
-
-#endif
diff --git a/thirdparty/bullet/Bullet3Common/shared/b3Quat.h b/thirdparty/bullet/Bullet3Common/shared/b3Quat.h
deleted file mode 100644
index 940610c77b..0000000000
--- a/thirdparty/bullet/Bullet3Common/shared/b3Quat.h
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef B3_QUAT_H
-#define B3_QUAT_H
-
-#include "Bullet3Common/shared/b3PlatformDefinitions.h"
-#include "Bullet3Common/shared/b3Float4.h"
-
-#ifdef __cplusplus
-#include "Bullet3Common/b3Quaternion.h"
-#include "Bullet3Common/b3Transform.h"
-
-#define b3Quat b3Quaternion
-#define b3QuatConstArg const b3Quaternion&
-inline b3Quat b3QuatInverse(b3QuatConstArg orn)
-{
- return orn.inverse();
-}
-
-inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
-{
- b3Transform tr;
- tr.setOrigin(translation);
- tr.setRotation(orientation);
- return tr(point);
-}
-
-#else
-typedef float4 b3Quat;
-#define b3QuatConstArg const b3Quat
-
-inline float4 b3FastNormalize4(float4 v)
-{
- v = (float4)(v.xyz, 0.f);
- return fast_normalize(v);
-}
-
-inline b3Quat b3QuatMul(b3Quat a, b3Quat b);
-inline b3Quat b3QuatNormalized(b3QuatConstArg in);
-inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);
-inline b3Quat b3QuatInvert(b3QuatConstArg q);
-inline b3Quat b3QuatInverse(b3QuatConstArg q);
-
-inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)
-{
- b3Quat ans;
- ans = b3Cross3(a, b);
- ans += a.w * b + b.w * a;
- // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w * b.w - b3Dot3F4(a, b);
- return ans;
-}
-
-inline b3Quat b3QuatNormalized(b3QuatConstArg in)
-{
- b3Quat q;
- q = in;
- //return b3FastNormalize4(in);
- float len = native_sqrt(dot(q, q));
- if (len > 0.f)
- {
- q *= 1.f / len;
- }
- else
- {
- q.x = q.y = q.z = 0.f;
- q.w = 1.f;
- }
- return q;
-}
-inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)
-{
- b3Quat qInv = b3QuatInvert(q);
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = b3QuatMul(b3QuatMul(q, vcpy), qInv);
- return out;
-}
-
-inline b3Quat b3QuatInverse(b3QuatConstArg q)
-{
- return (b3Quat)(-q.xyz, q.w);
-}
-
-inline b3Quat b3QuatInvert(b3QuatConstArg q)
-{
- return (b3Quat)(-q.xyz, q.w);
-}
-
-inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)
-{
- return b3QuatRotate(b3QuatInvert(q), vec);
-}
-
-inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)
-{
- return b3QuatRotate(orientation, point) + (translation);
-}
-
-#endif
-
-#endif //B3_QUAT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
deleted file mode 100644
index 049c9116fd..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_CONTACT_SOLVER_INFO
-#define B3_CONTACT_SOLVER_INFO
-
-#include "Bullet3Common/b3Scalar.h"
-
-enum b3SolverMode
-{
- B3_SOLVER_RANDMIZE_ORDER = 1,
- B3_SOLVER_FRICTION_SEPARATE = 2,
- B3_SOLVER_USE_WARMSTARTING = 4,
- B3_SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
- B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
- B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
- B3_SOLVER_CACHE_FRIENDLY = 128,
- B3_SOLVER_SIMD = 256,
- B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
- B3_SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024
-};
-
-struct b3ContactSolverInfoData
-{
- b3Scalar m_tau;
- b3Scalar m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- b3Scalar m_friction;
- b3Scalar m_timeStep;
- b3Scalar m_restitution;
- int m_numIterations;
- b3Scalar m_maxErrorReduction;
- b3Scalar m_sor;
- b3Scalar m_erp; //used as Baumgarte factor
- b3Scalar m_erp2; //used in Split Impulse
- b3Scalar m_globalCfm; //constraint force mixing
- int m_splitImpulse;
- b3Scalar m_splitImpulsePenetrationThreshold;
- b3Scalar m_splitImpulseTurnErp;
- b3Scalar m_linearSlop;
- b3Scalar m_warmstartingFactor;
-
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- b3Scalar m_maxGyroscopicForce;
- b3Scalar m_singleAxisRollingFrictionThreshold;
-};
-
-struct b3ContactSolverInfo : public b3ContactSolverInfoData
-{
- inline b3ContactSolverInfo()
- {
- m_tau = b3Scalar(0.6);
- m_damping = b3Scalar(1.0);
- m_friction = b3Scalar(0.3);
- m_timeStep = b3Scalar(1.f / 60.f);
- m_restitution = b3Scalar(0.);
- m_maxErrorReduction = b3Scalar(20.);
- m_numIterations = 10;
- m_erp = b3Scalar(0.2);
- m_erp2 = b3Scalar(0.8);
- m_globalCfm = b3Scalar(0.);
- m_sor = b3Scalar(1.);
- m_splitImpulse = true;
- m_splitImpulsePenetrationThreshold = -.04f;
- m_splitImpulseTurnErp = 0.1f;
- m_linearSlop = b3Scalar(0.0);
- m_warmstartingFactor = b3Scalar(0.85);
- //m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD | B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | B3_SOLVER_RANDMIZE_ORDER;
- m_solverMode = B3_SOLVER_USE_WARMSTARTING | B3_SOLVER_SIMD; // | B3_SOLVER_RANDMIZE_ORDER;
- m_restingContactRestitutionThreshold = 2; //unused as of 2.81
- m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
- m_maxGyroscopicForce = 100.f; ///only used to clamp forces for bodies that have their B3_ENABLE_GYROPSCOPIC_FORCE flag set (using b3RigidBody::setFlag)
- m_singleAxisRollingFrictionThreshold = 1e30f; ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
- }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3ContactSolverInfoDoubleData
-{
- double m_tau;
- double m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp; //used as Baumgarte factor
- double m_erp2; //used in Split Impulse
- double m_globalCfm; //constraint force mixing
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_maxGyroscopicForce;
- double m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-};
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3ContactSolverInfoFloatData
-{
- float m_tau;
- float m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- float m_friction;
- float m_timeStep;
-
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp; //used as Baumgarte factor
-
- float m_erp2; //used in Split Impulse
- float m_globalCfm; //constraint force mixing
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
-
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
-
- int m_splitImpulse;
- char m_padding[4];
-};
-
-#endif //B3_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
deleted file mode 100644
index ace4b18388..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-
-#include "b3FixedConstraint.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Common/b3TransformUtil.h"
-#include <new>
-
-b3FixedConstraint::b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB)
- : b3TypedConstraint(B3_FIXED_CONSTRAINT_TYPE, rbA, rbB)
-{
- m_pivotInA = frameInA.getOrigin();
- m_pivotInB = frameInB.getOrigin();
- m_relTargetAB = frameInA.getRotation() * frameInB.getRotation().inverse();
-}
-
-b3FixedConstraint::~b3FixedConstraint()
-{
-}
-
-void b3FixedConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
-{
- info->m_numConstraintRows = 6;
- info->nub = 6;
-}
-
-void b3FixedConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
-{
- //fix the 3 linear degrees of freedom
-
- const b3Vector3& worldPosA = bodies[m_rbA].m_pos;
- const b3Quaternion& worldOrnA = bodies[m_rbA].m_quat;
- const b3Vector3& worldPosB = bodies[m_rbB].m_pos;
- const b3Quaternion& worldOrnB = bodies[m_rbB].m_quat;
-
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip + 1] = 1;
- info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
-
- b3Vector3 a1 = b3QuatRotate(worldOrnA, m_pivotInA);
- {
- b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
- b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- if (info->m_J2linearAxis)
- {
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip + 1] = -1;
- info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
- }
-
- b3Vector3 a2 = b3QuatRotate(worldOrnB, m_pivotInB);
-
- {
- // b3Vector3 a2n = -a2;
- b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- // set right hand side for the linear dofs
- b3Scalar k = info->fps * info->erp;
- b3Vector3 linearError = k * (a2 + worldPosB - a1 - worldPosA);
- int j;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[j * info->rowskip] = linearError[j];
- //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
-
- //fix the 3 angular degrees of freedom
-
- int start_row = 3;
- int s = info->rowskip;
- int start_index = start_row * s;
-
- // 3 rows to make body rotations equal
- info->m_J1angularAxis[start_index] = 1;
- info->m_J1angularAxis[start_index + s + 1] = 1;
- info->m_J1angularAxis[start_index + s * 2 + 2] = 1;
- if (info->m_J2angularAxis)
- {
- info->m_J2angularAxis[start_index] = -1;
- info->m_J2angularAxis[start_index + s + 1] = -1;
- info->m_J2angularAxis[start_index + s * 2 + 2] = -1;
- }
-
- // set right hand side for the angular dofs
-
- b3Vector3 diff;
- b3Scalar angle;
- b3Quaternion qrelCur = worldOrnA * worldOrnB.inverse();
-
- b3TransformUtil::calculateDiffAxisAngleQuaternion(m_relTargetAB, qrelCur, diff, angle);
- diff *= -angle;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[(3 + j) * info->rowskip] = k * diff[j];
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
deleted file mode 100644
index 64809666e4..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3FixedConstraint.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#ifndef B3_FIXED_CONSTRAINT_H
-#define B3_FIXED_CONSTRAINT_H
-
-#include "b3TypedConstraint.h"
-
-B3_ATTRIBUTE_ALIGNED16(class)
-b3FixedConstraint : public b3TypedConstraint
-{
- b3Vector3 m_pivotInA;
- b3Vector3 m_pivotInB;
- b3Quaternion m_relTargetAB;
-
-public:
- b3FixedConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB);
-
- virtual ~b3FixedConstraint();
-
- virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
-
- virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
-
- virtual void setParam(int num, b3Scalar value, int axis = -1)
- {
- b3Assert(0);
- }
- virtual b3Scalar getParam(int num, int axis = -1) const
- {
- b3Assert(0);
- return 0.f;
- }
-};
-
-#endif //B3_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
deleted file mode 100644
index 0d5bb2014b..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.cpp
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-/*
-2007-09-09
-Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#include "b3Generic6DofConstraint.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include "Bullet3Common/b3TransformUtil.h"
-#include "Bullet3Common/b3TransformUtil.h"
-#include <new>
-
-#define D6_USE_OBSOLETE_METHOD false
-#define D6_USE_FRAME_OFFSET true
-
-b3Generic6DofConstraint::b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies)
- : b3TypedConstraint(B3_D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0)
-{
- calculateTransforms(bodies);
-}
-
-#define GENERIC_D6_DISABLE_WARMSTARTING 1
-
-b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index);
-b3Scalar btGetMatrixElem(const b3Matrix3x3& mat, int index)
-{
- int i = index % 3;
- int j = index / 3;
- return mat[i][j];
-}
-
-///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz);
-bool matrixToEulerXYZ(const b3Matrix3x3& mat, b3Vector3& xyz)
-{
- // // rot = cy*cz -cy*sz sy
- // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
- //
-
- b3Scalar fi = btGetMatrixElem(mat, 2);
- if (fi < b3Scalar(1.0f))
- {
- if (fi > b3Scalar(-1.0f))
- {
- xyz[0] = b3Atan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
- xyz[1] = b3Asin(btGetMatrixElem(mat, 2));
- xyz[2] = b3Atan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
- return true;
- }
- else
- {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = -B3_HALF_PI;
- xyz[2] = b3Scalar(0.0);
- return false;
- }
- }
- else
- {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = b3Atan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = B3_HALF_PI;
- xyz[2] = 0.0;
- }
- return false;
-}
-
-//////////////////////////// b3RotationalLimitMotor ////////////////////////////////////
-
-int b3RotationalLimitMotor::testLimitValue(b3Scalar test_value)
-{
- if (m_loLimit > m_hiLimit)
- {
- m_currentLimit = 0; //Free from violation
- return 0;
- }
- if (test_value < m_loLimit)
- {
- m_currentLimit = 1; //low limit violation
- m_currentLimitError = test_value - m_loLimit;
- if (m_currentLimitError > B3_PI)
- m_currentLimitError -= B3_2_PI;
- else if (m_currentLimitError < -B3_PI)
- m_currentLimitError += B3_2_PI;
- return 1;
- }
- else if (test_value > m_hiLimit)
- {
- m_currentLimit = 2; //High limit violation
- m_currentLimitError = test_value - m_hiLimit;
- if (m_currentLimitError > B3_PI)
- m_currentLimitError -= B3_2_PI;
- else if (m_currentLimitError < -B3_PI)
- m_currentLimitError += B3_2_PI;
- return 2;
- };
-
- m_currentLimit = 0; //Free from violation
- return 0;
-}
-
-//////////////////////////// End b3RotationalLimitMotor ////////////////////////////////////
-
-//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
-
-int b3TranslationalLimitMotor::testLimitValue(int limitIndex, b3Scalar test_value)
-{
- b3Scalar loLimit = m_lowerLimit[limitIndex];
- b3Scalar hiLimit = m_upperLimit[limitIndex];
- if (loLimit > hiLimit)
- {
- m_currentLimit[limitIndex] = 0; //Free from violation
- m_currentLimitError[limitIndex] = b3Scalar(0.f);
- return 0;
- }
-
- if (test_value < loLimit)
- {
- m_currentLimit[limitIndex] = 2; //low limit violation
- m_currentLimitError[limitIndex] = test_value - loLimit;
- return 2;
- }
- else if (test_value > hiLimit)
- {
- m_currentLimit[limitIndex] = 1; //High limit violation
- m_currentLimitError[limitIndex] = test_value - hiLimit;
- return 1;
- };
-
- m_currentLimit[limitIndex] = 0; //Free from violation
- m_currentLimitError[limitIndex] = b3Scalar(0.f);
- return 0;
-}
-
-//////////////////////////// b3TranslationalLimitMotor ////////////////////////////////////
-
-void b3Generic6DofConstraint::calculateAngleInfo()
-{
- b3Matrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
- matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
- // in euler angle mode we do not actually constrain the angular velocity
- // along the axes axis[0] and axis[2] (although we do use axis[1]) :
- //
- // to get constrain w2-w1 along ...not
- // ------ --------------------- ------
- // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
- // d(angle[1])/dt = 0 ax[1]
- // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
- //
- // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
- // to prove the result for angle[0], write the expression for angle[0] from
- // GetInfo1 then take the derivative. to prove this for angle[2] it is
- // easier to take the euler rate expression for d(angle[2])/dt with respect
- // to the components of w and set that to 0.
- b3Vector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
- b3Vector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
-
- m_calculatedAxis[1] = axis2.cross(axis0);
- m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
- m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
-
- m_calculatedAxis[0].normalize();
- m_calculatedAxis[1].normalize();
- m_calculatedAxis[2].normalize();
-}
-
-static b3Transform getCenterOfMassTransform(const b3RigidBodyData& body)
-{
- b3Transform tr(body.m_quat, body.m_pos);
- return tr;
-}
-
-void b3Generic6DofConstraint::calculateTransforms(const b3RigidBodyData* bodies)
-{
- b3Transform transA;
- b3Transform transB;
- transA = getCenterOfMassTransform(bodies[m_rbA]);
- transB = getCenterOfMassTransform(bodies[m_rbB]);
- calculateTransforms(transA, transB, bodies);
-}
-
-void b3Generic6DofConstraint::calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies)
-{
- m_calculatedTransformA = transA * m_frameInA;
- m_calculatedTransformB = transB * m_frameInB;
- calculateLinearInfo();
- calculateAngleInfo();
- if (m_useOffsetForConstraintFrame)
- { // get weight factors depending on masses
- b3Scalar miA = bodies[m_rbA].m_invMass;
- b3Scalar miB = bodies[m_rbB].m_invMass;
- m_hasStaticBody = (miA < B3_EPSILON) || (miB < B3_EPSILON);
- b3Scalar miS = miA + miB;
- if (miS > b3Scalar(0.f))
- {
- m_factA = miB / miS;
- }
- else
- {
- m_factA = b3Scalar(0.5f);
- }
- m_factB = b3Scalar(1.0f) - m_factA;
- }
-}
-
-bool b3Generic6DofConstraint::testAngularLimitMotor(int axis_index)
-{
- b3Scalar angle = m_calculatedAxisAngleDiff[axis_index];
- angle = b3AdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
- m_angularLimits[axis_index].m_currentPosition = angle;
- //test limits
- m_angularLimits[axis_index].testLimitValue(angle);
- return m_angularLimits[axis_index].needApplyTorques();
-}
-
-void b3Generic6DofConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
-{
- //prepare constraint
- calculateTransforms(getCenterOfMassTransform(bodies[m_rbA]), getCenterOfMassTransform(bodies[m_rbB]), bodies);
- info->m_numConstraintRows = 0;
- info->nub = 6;
- int i;
- //test linear limits
- for (i = 0; i < 3; i++)
- {
- if (m_linearLimits.needApplyForce(i))
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
- //test angular limits
- for (i = 0; i < 3; i++)
- {
- if (testAngularLimitMotor(i))
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
- // printf("info->m_numConstraintRows=%d\n",info->m_numConstraintRows);
-}
-
-void b3Generic6DofConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
-{
- //pre-allocate all 6
- info->m_numConstraintRows = 6;
- info->nub = 0;
-}
-
-void b3Generic6DofConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
-{
- b3Transform transA = getCenterOfMassTransform(bodies[m_rbA]);
- b3Transform transB = getCenterOfMassTransform(bodies[m_rbB]);
- const b3Vector3& linVelA = bodies[m_rbA].m_linVel;
- const b3Vector3& linVelB = bodies[m_rbB].m_linVel;
- const b3Vector3& angVelA = bodies[m_rbA].m_angVel;
- const b3Vector3& angVelB = bodies[m_rbB].m_angVel;
-
- if (m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
- else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
-}
-
-void b3Generic6DofConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies)
-{
- //prepare constraint
- calculateTransforms(transA, transB, bodies);
-
- int i;
- for (i = 0; i < 3; i++)
- {
- testAngularLimitMotor(i);
- }
-
- if (m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
- else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
-}
-
-int b3Generic6DofConstraint::setLinearLimits(b3ConstraintInfo2* info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
-{
- // int row = 0;
- //solve linear limits
- b3RotationalLimitMotor limot;
- for (int i = 0; i < 3; i++)
- {
- if (m_linearLimits.needApplyForce(i))
- { // re-use rotational motor code
- limot.m_bounce = b3Scalar(0.f);
- limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
- limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_damping = m_linearLimits.m_damping;
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxLimitForce = b3Scalar(0.f);
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
- b3Vector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
- int flags = m_flags >> (i * B3_6DOF_FLAGS_AXIS_SHIFT);
- limot.m_normalCFM = (flags & B3_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
- limot.m_stopCFM = (flags & B3_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & B3_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
- if (m_useOffsetForConstraintFrame)
- {
- int indx1 = (i + 1) % 3;
- int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis
- if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
- {
- rotAllowed = 0;
- }
- row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
- }
- else
- {
- row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
- }
- }
- }
- return row;
-}
-
-int b3Generic6DofConstraint::setAngularLimits(b3ConstraintInfo2* info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB)
-{
- b3Generic6DofConstraint* d6constraint = this;
- int row = row_offset;
- //solve angular limits
- for (int i = 0; i < 3; i++)
- {
- if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
- {
- b3Vector3 axis = d6constraint->getAxis(i);
- int flags = m_flags >> ((i + 3) * B3_6DOF_FLAGS_AXIS_SHIFT);
- if (!(flags & B3_6DOF_FLAGS_CFM_NORM))
- {
- m_angularLimits[i].m_normalCFM = info->cfm[0];
- }
- if (!(flags & B3_6DOF_FLAGS_CFM_STOP))
- {
- m_angularLimits[i].m_stopCFM = info->cfm[0];
- }
- if (!(flags & B3_6DOF_FLAGS_ERP_STOP))
- {
- m_angularLimits[i].m_stopERP = info->erp;
- }
- row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
- transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
- }
- }
-
- return row;
-}
-
-void b3Generic6DofConstraint::updateRHS(b3Scalar timeStep)
-{
- (void)timeStep;
-}
-
-void b3Generic6DofConstraint::setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies)
-{
- m_frameInA = frameA;
- m_frameInB = frameB;
-
- calculateTransforms(bodies);
-}
-
-b3Vector3 b3Generic6DofConstraint::getAxis(int axis_index) const
-{
- return m_calculatedAxis[axis_index];
-}
-
-b3Scalar b3Generic6DofConstraint::getRelativePivotPosition(int axisIndex) const
-{
- return m_calculatedLinearDiff[axisIndex];
-}
-
-b3Scalar b3Generic6DofConstraint::getAngle(int axisIndex) const
-{
- return m_calculatedAxisAngleDiff[axisIndex];
-}
-
-void b3Generic6DofConstraint::calcAnchorPos(const b3RigidBodyData* bodies)
-{
- b3Scalar imA = bodies[m_rbA].m_invMass;
- b3Scalar imB = bodies[m_rbB].m_invMass;
- b3Scalar weight;
- if (imB == b3Scalar(0.0))
- {
- weight = b3Scalar(1.0);
- }
- else
- {
- weight = imA / (imA + imB);
- }
- const b3Vector3& pA = m_calculatedTransformA.getOrigin();
- const b3Vector3& pB = m_calculatedTransformB.getOrigin();
- m_AnchorPos = pA * weight + pB * (b3Scalar(1.0) - weight);
- return;
-}
-
-void b3Generic6DofConstraint::calculateLinearInfo()
-{
- m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
- m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for (int i = 0; i < 3; i++)
- {
- m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
- m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
- }
-}
-
-int b3Generic6DofConstraint::get_limit_motor_info2(
- b3RotationalLimitMotor* limot,
- const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
- b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed)
-{
- int srow = row * info->rowskip;
- bool powered = limot->m_enableMotor;
- int limit = limot->m_currentLimit;
- if (powered || limit)
- { // if the joint is powered, or has joint limits, add in the extra row
- b3Scalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- b3Scalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
- if (J1)
- {
- J1[srow + 0] = ax1[0];
- J1[srow + 1] = ax1[1];
- J1[srow + 2] = ax1[2];
- }
- if (J2)
- {
- J2[srow + 0] = -ax1[0];
- J2[srow + 1] = -ax1[1];
- J2[srow + 2] = -ax1[2];
- }
- if ((!rotational))
- {
- if (m_useOffsetForConstraintFrame)
- {
- b3Vector3 tmpA, tmpB, relA, relB;
- // get vector from bodyB to frameB in WCS
- relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
- // get its projection to constraint axis
- b3Vector3 projB = ax1 * relB.dot(ax1);
- // get vector directed from bodyB to constraint axis (and orthogonal to it)
- b3Vector3 orthoB = relB - projB;
- // same for bodyA
- relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
- b3Vector3 projA = ax1 * relA.dot(ax1);
- b3Vector3 orthoA = relA - projA;
- // get desired offset between frames A and B along constraint axis
- b3Scalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
- // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
- b3Vector3 totalDist = projA + ax1 * desiredOffs - projB;
- // get offset vectors relA and relB
- relA = orthoA + totalDist * m_factA;
- relB = orthoB - totalDist * m_factB;
- tmpA = relA.cross(ax1);
- tmpB = relB.cross(ax1);
- if (m_hasStaticBody && (!rotAllowed))
- {
- tmpA *= m_factA;
- tmpB *= m_factB;
- }
- int i;
- for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
- }
- else
- {
- b3Vector3 ltd; // Linear Torque Decoupling vector
- b3Vector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
- ltd = c.cross(ax1);
- info->m_J1angularAxis[srow + 0] = ltd[0];
- info->m_J1angularAxis[srow + 1] = ltd[1];
- info->m_J1angularAxis[srow + 2] = ltd[2];
-
- c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
- ltd = -c.cross(ax1);
- info->m_J2angularAxis[srow + 0] = ltd[0];
- info->m_J2angularAxis[srow + 1] = ltd[1];
- info->m_J2angularAxis[srow + 2] = ltd[2];
- }
- }
- // if we're limited low and high simultaneously, the joint motor is
- // ineffective
- if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
- info->m_constraintError[srow] = b3Scalar(0.f);
- if (powered)
- {
- info->cfm[srow] = limot->m_normalCFM;
- if (!limit)
- {
- b3Scalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
-
- b3Scalar mot_fact = getMotorFactor(limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_stopERP);
- info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- }
- }
- if (limit)
- {
- b3Scalar k = info->fps * limot->m_stopERP;
- if (!rotational)
- {
- info->m_constraintError[srow] += k * limot->m_currentLimitError;
- }
- else
- {
- info->m_constraintError[srow] += -k * limot->m_currentLimitError;
- }
- info->cfm[srow] = limot->m_stopCFM;
- if (limot->m_loLimit == limot->m_hiLimit)
- { // limited low and high simultaneously
- info->m_lowerLimit[srow] = -B3_INFINITY;
- info->m_upperLimit[srow] = B3_INFINITY;
- }
- else
- {
- if (limit == 1)
- {
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = B3_INFINITY;
- }
- else
- {
- info->m_lowerLimit[srow] = -B3_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // deal with bounce
- if (limot->m_bounce > 0)
- {
- // calculate joint velocity
- b3Scalar vel;
- if (rotational)
- {
- vel = angVelA.dot(ax1);
- //make sure that if no body -> angVelB == zero vec
- // if (body1)
- vel -= angVelB.dot(ax1);
- }
- else
- {
- vel = linVelA.dot(ax1);
- //make sure that if no body -> angVelB == zero vec
- // if (body1)
- vel -= linVelB.dot(ax1);
- }
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- {
- if (vel < 0)
- {
- b3Scalar newc = -limot->m_bounce * vel;
- if (newc > info->m_constraintError[srow])
- info->m_constraintError[srow] = newc;
- }
- }
- else
- {
- if (vel > 0)
- {
- b3Scalar newc = -limot->m_bounce * vel;
- if (newc < info->m_constraintError[srow])
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- }
- return 1;
- }
- else
- return 0;
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void b3Generic6DofConstraint::setParam(int num, b3Scalar value, int axis)
-{
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case B3_CONSTRAINT_STOP_ERP:
- m_linearLimits.m_stopERP[axis] = value;
- m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case B3_CONSTRAINT_STOP_CFM:
- m_linearLimits.m_stopCFM[axis] = value;
- m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case B3_CONSTRAINT_CFM:
- m_linearLimits.m_normalCFM[axis] = value;
- m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case B3_CONSTRAINT_STOP_ERP:
- m_angularLimits[axis - 3].m_stopERP = value;
- m_flags |= B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case B3_CONSTRAINT_STOP_CFM:
- m_angularLimits[axis - 3].m_stopCFM = value;
- m_flags |= B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case B3_CONSTRAINT_CFM:
- m_angularLimits[axis - 3].m_normalCFM = value;
- m_flags |= B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT);
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
- else
- {
- b3AssertConstrParams(0);
- }
-}
-
-///return the local value of parameter
-b3Scalar b3Generic6DofConstraint::getParam(int num, int axis) const
-{
- b3Scalar retVal = 0;
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case B3_CONSTRAINT_STOP_ERP:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_stopERP[axis];
- break;
- case B3_CONSTRAINT_STOP_CFM:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_stopCFM[axis];
- break;
- case B3_CONSTRAINT_CFM:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_normalCFM[axis];
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case B3_CONSTRAINT_STOP_ERP:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_ERP_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_stopERP;
- break;
- case B3_CONSTRAINT_STOP_CFM:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_STOP << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_stopCFM;
- break;
- case B3_CONSTRAINT_CFM:
- b3AssertConstrParams(m_flags & (B3_6DOF_FLAGS_CFM_NORM << (axis * B3_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_normalCFM;
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
- else
- {
- b3AssertConstrParams(0);
- }
- return retVal;
-}
-
-void b3Generic6DofConstraint::setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies)
-{
- b3Vector3 zAxis = axis1.normalized();
- b3Vector3 yAxis = axis2.normalized();
- b3Vector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
- b3Transform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
- // now get constraint frame in local coordinate systems
- m_frameInA = getCenterOfMassTransform(bodies[m_rbA]).inverse() * frameInW;
- m_frameInB = getCenterOfMassTransform(bodies[m_rbB]).inverse() * frameInW;
-
- calculateTransforms(bodies);
-}
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
deleted file mode 100644
index 1597809db3..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Generic6DofConstraint.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// 2009 March: b3Generic6DofConstraint refactored by Roman Ponomarev
-/// Added support for generic constraint solver through getInfo1/getInfo2 methods
-
-/*
-2007-09-09
-b3Generic6DofConstraint Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#ifndef B3_GENERIC_6DOF_CONSTRAINT_H
-#define B3_GENERIC_6DOF_CONSTRAINT_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "b3JacobianEntry.h"
-#include "b3TypedConstraint.h"
-
-struct b3RigidBodyData;
-
-//! Rotation Limit structure for generic joints
-class b3RotationalLimitMotor
-{
-public:
- //! limit_parameters
- //!@{
- b3Scalar m_loLimit; //!< joint limit
- b3Scalar m_hiLimit; //!< joint limit
- b3Scalar m_targetVelocity; //!< target motor velocity
- b3Scalar m_maxMotorForce; //!< max force on motor
- b3Scalar m_maxLimitForce; //!< max force on limit
- b3Scalar m_damping; //!< Damping.
- b3Scalar m_limitSoftness; //! Relaxation factor
- b3Scalar m_normalCFM; //!< Constraint force mixing factor
- b3Scalar m_stopERP; //!< Error tolerance factor when joint is at limit
- b3Scalar m_stopCFM; //!< Constraint force mixing factor when joint is at limit
- b3Scalar m_bounce; //!< restitution factor
- bool m_enableMotor;
-
- //!@}
-
- //! temp_variables
- //!@{
- b3Scalar m_currentLimitError; //! How much is violated this limit
- b3Scalar m_currentPosition; //! current value of angle
- int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
- b3Scalar m_accumulatedImpulse;
- //!@}
-
- b3RotationalLimitMotor()
- {
- m_accumulatedImpulse = 0.f;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_maxLimitForce = 300.0f;
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
- m_normalCFM = 0.f;
- m_stopERP = 0.2f;
- m_stopCFM = 0.f;
- m_bounce = 0.0f;
- m_damping = 1.0f;
- m_limitSoftness = 0.5f;
- m_currentLimit = 0;
- m_currentLimitError = 0;
- m_enableMotor = false;
- }
-
- b3RotationalLimitMotor(const b3RotationalLimitMotor& limot)
- {
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_limitSoftness = limot.m_limitSoftness;
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
- m_normalCFM = limot.m_normalCFM;
- m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_bounce = limot.m_bounce;
- m_currentLimit = limot.m_currentLimit;
- m_currentLimitError = limot.m_currentLimitError;
- m_enableMotor = limot.m_enableMotor;
- }
-
- //! Is limited
- bool isLimited()
- {
- if (m_loLimit > m_hiLimit) return false;
- return true;
- }
-
- //! Need apply correction
- bool needApplyTorques()
- {
- if (m_currentLimit == 0 && m_enableMotor == false) return false;
- return true;
- }
-
- //! calculates error
- /*!
- calculates m_currentLimit and m_currentLimitError.
- */
- int testLimitValue(b3Scalar test_value);
-
- //! apply the correction impulses for two bodies
- b3Scalar solveAngularLimits(b3Scalar timeStep, b3Vector3& axis, b3Scalar jacDiagABInv, b3RigidBodyData* body0, b3RigidBodyData* body1);
-};
-
-class b3TranslationalLimitMotor
-{
-public:
- b3Vector3 m_lowerLimit; //!< the constraint lower limits
- b3Vector3 m_upperLimit; //!< the constraint upper limits
- b3Vector3 m_accumulatedImpulse;
- //! Linear_Limit_parameters
- //!@{
- b3Vector3 m_normalCFM; //!< Constraint force mixing factor
- b3Vector3 m_stopERP; //!< Error tolerance factor when joint is at limit
- b3Vector3 m_stopCFM; //!< Constraint force mixing factor when joint is at limit
- b3Vector3 m_targetVelocity; //!< target motor velocity
- b3Vector3 m_maxMotorForce; //!< max force on motor
- b3Vector3 m_currentLimitError; //! How much is violated this limit
- b3Vector3 m_currentLinearDiff; //! Current relative offset of constraint frames
- b3Scalar m_limitSoftness; //!< Softness for linear limit
- b3Scalar m_damping; //!< Damping for linear limit
- b3Scalar m_restitution; //! Bounce parameter for linear limit
- //!@}
- bool m_enableMotor[3];
- int m_currentLimit[3]; //!< 0=free, 1=at lower limit, 2=at upper limit
-
- b3TranslationalLimitMotor()
- {
- m_lowerLimit.setValue(0.f, 0.f, 0.f);
- m_upperLimit.setValue(0.f, 0.f, 0.f);
- m_accumulatedImpulse.setValue(0.f, 0.f, 0.f);
- m_normalCFM.setValue(0.f, 0.f, 0.f);
- m_stopERP.setValue(0.2f, 0.2f, 0.2f);
- m_stopCFM.setValue(0.f, 0.f, 0.f);
-
- m_limitSoftness = 0.7f;
- m_damping = b3Scalar(1.0f);
- m_restitution = b3Scalar(0.5f);
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = false;
- m_targetVelocity[i] = b3Scalar(0.f);
- m_maxMotorForce[i] = b3Scalar(0.f);
- }
- }
-
- b3TranslationalLimitMotor(const b3TranslationalLimitMotor& other)
- {
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_accumulatedImpulse = other.m_accumulatedImpulse;
-
- m_limitSoftness = other.m_limitSoftness;
- m_damping = other.m_damping;
- m_restitution = other.m_restitution;
- m_normalCFM = other.m_normalCFM;
- m_stopERP = other.m_stopERP;
- m_stopCFM = other.m_stopCFM;
-
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = other.m_enableMotor[i];
- m_targetVelocity[i] = other.m_targetVelocity[i];
- m_maxMotorForce[i] = other.m_maxMotorForce[i];
- }
- }
-
- //! Test limit
- /*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
- inline bool isLimited(int limitIndex)
- {
- return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
- }
- inline bool needApplyForce(int limitIndex)
- {
- if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
- return true;
- }
- int testLimitValue(int limitIndex, b3Scalar test_value);
-
- b3Scalar solveLinearAxis(
- b3Scalar timeStep,
- b3Scalar jacDiagABInv,
- b3RigidBodyData& body1, const b3Vector3& pointInA,
- b3RigidBodyData& body2, const b3Vector3& pointInB,
- int limit_index,
- const b3Vector3& axis_normal_on_a,
- const b3Vector3& anchorPos);
-};
-
-enum b36DofFlags
-{
- B3_6DOF_FLAGS_CFM_NORM = 1,
- B3_6DOF_FLAGS_CFM_STOP = 2,
- B3_6DOF_FLAGS_ERP_STOP = 4
-};
-#define B3_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
-
-/// b3Generic6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
-/*!
-b3Generic6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
-currently this limit supports rotational motors<br>
-<ul>
-<li> For Linear limits, use b3Generic6DofConstraint.setLinearUpperLimit, b3Generic6DofConstraint.setLinearLowerLimit. You can set the parameters with the b3TranslationalLimitMotor structure accsesible through the b3Generic6DofConstraint.getTranslationalLimitMotor method.
-At this moment translational motors are not supported. May be in the future. </li>
-
-<li> For Angular limits, use the b3RotationalLimitMotor structure for configuring the limit.
-This is accessible through b3Generic6DofConstraint.getLimitMotor method,
-This brings support for limit parameters and motors. </li>
-
-<li> Angulars limits have these possible ranges:
-<table border=1 >
-<tr>
- <td><b>AXIS</b></td>
- <td><b>MIN ANGLE</b></td>
- <td><b>MAX ANGLE</b></td>
-</tr><tr>
- <td>X</td>
- <td>-PI</td>
- <td>PI</td>
-</tr><tr>
- <td>Y</td>
- <td>-PI/2</td>
- <td>PI/2</td>
-</tr><tr>
- <td>Z</td>
- <td>-PI</td>
- <td>PI</td>
-</tr>
-</table>
-</li>
-</ul>
-
-*/
-B3_ATTRIBUTE_ALIGNED16(class)
-b3Generic6DofConstraint : public b3TypedConstraint
-{
-protected:
- //! relative_frames
- //!@{
- b3Transform m_frameInA; //!< the constraint space w.r.t body A
- b3Transform m_frameInB; //!< the constraint space w.r.t body B
- //!@}
-
- //! Jacobians
- //!@{
- // b3JacobianEntry m_jacLinear[3];//!< 3 orthogonal linear constraints
- // b3JacobianEntry m_jacAng[3];//!< 3 orthogonal angular constraints
- //!@}
-
- //! Linear_Limit_parameters
- //!@{
- b3TranslationalLimitMotor m_linearLimits;
- //!@}
-
- //! hinge_parameters
- //!@{
- b3RotationalLimitMotor m_angularLimits[3];
- //!@}
-
-protected:
- //! temporal variables
- //!@{
- b3Transform m_calculatedTransformA;
- b3Transform m_calculatedTransformB;
- b3Vector3 m_calculatedAxisAngleDiff;
- b3Vector3 m_calculatedAxis[3];
- b3Vector3 m_calculatedLinearDiff;
- b3Scalar m_timeStep;
- b3Scalar m_factA;
- b3Scalar m_factB;
- bool m_hasStaticBody;
-
- b3Vector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
-
- bool m_useLinearReferenceFrameA;
- bool m_useOffsetForConstraintFrame;
-
- int m_flags;
-
- //!@}
-
- b3Generic6DofConstraint& operator=(b3Generic6DofConstraint& other)
- {
- b3Assert(0);
- (void)other;
- return *this;
- }
-
- int setAngularLimits(b3ConstraintInfo2 * info, int row_offset, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
-
- int setLinearLimits(b3ConstraintInfo2 * info, int row, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB);
-
- // tests linear limits
- void calculateLinearInfo();
-
- //! calcs the euler angles between the two bodies.
- void calculateAngleInfo();
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3Generic6DofConstraint(int rbA, int rbB, const b3Transform& frameInA, const b3Transform& frameInB, bool useLinearReferenceFrameA, const b3RigidBodyData* bodies);
-
- //! Calcs global transform of the offsets
- /*!
- Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
- \sa b3Generic6DofConstraint.getCalculatedTransformA , b3Generic6DofConstraint.getCalculatedTransformB, b3Generic6DofConstraint.calculateAngleInfo
- */
- void calculateTransforms(const b3Transform& transA, const b3Transform& transB, const b3RigidBodyData* bodies);
-
- void calculateTransforms(const b3RigidBodyData* bodies);
-
- //! Gets the global transform of the offset for body A
- /*!
- \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
- */
- const b3Transform& getCalculatedTransformA() const
- {
- return m_calculatedTransformA;
- }
-
- //! Gets the global transform of the offset for body B
- /*!
- \sa b3Generic6DofConstraint.getFrameOffsetA, b3Generic6DofConstraint.getFrameOffsetB, b3Generic6DofConstraint.calculateAngleInfo.
- */
- const b3Transform& getCalculatedTransformB() const
- {
- return m_calculatedTransformB;
- }
-
- const b3Transform& getFrameOffsetA() const
- {
- return m_frameInA;
- }
-
- const b3Transform& getFrameOffsetB() const
- {
- return m_frameInB;
- }
-
- b3Transform& getFrameOffsetA()
- {
- return m_frameInA;
- }
-
- b3Transform& getFrameOffsetB()
- {
- return m_frameInB;
- }
-
- virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
-
- void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
-
- virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
-
- void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB, const b3RigidBodyData* bodies);
-
- void updateRHS(b3Scalar timeStep);
-
- //! Get the rotation axis in global coordinates
- b3Vector3 getAxis(int axis_index) const;
-
- //! Get the relative Euler angle
- /*!
- \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
- */
- b3Scalar getAngle(int axis_index) const;
-
- //! Get the relative position of the constraint pivot
- /*!
- \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
- */
- b3Scalar getRelativePivotPosition(int axis_index) const;
-
- void setFrames(const b3Transform& frameA, const b3Transform& frameB, const b3RigidBodyData* bodies);
-
- //! Test angular limit.
- /*!
- Calculates angular correction and returns true if limit needs to be corrected.
- \pre b3Generic6DofConstraint::calculateTransforms() must be called previously.
- */
- bool testAngularLimitMotor(int axis_index);
-
- void setLinearLowerLimit(const b3Vector3& linearLower)
- {
- m_linearLimits.m_lowerLimit = linearLower;
- }
-
- void getLinearLowerLimit(b3Vector3 & linearLower)
- {
- linearLower = m_linearLimits.m_lowerLimit;
- }
-
- void setLinearUpperLimit(const b3Vector3& linearUpper)
- {
- m_linearLimits.m_upperLimit = linearUpper;
- }
-
- void getLinearUpperLimit(b3Vector3 & linearUpper)
- {
- linearUpper = m_linearLimits.m_upperLimit;
- }
-
- void setAngularLowerLimit(const b3Vector3& angularLower)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_loLimit = b3NormalizeAngle(angularLower[i]);
- }
-
- void getAngularLowerLimit(b3Vector3 & angularLower)
- {
- for (int i = 0; i < 3; i++)
- angularLower[i] = m_angularLimits[i].m_loLimit;
- }
-
- void setAngularUpperLimit(const b3Vector3& angularUpper)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_hiLimit = b3NormalizeAngle(angularUpper[i]);
- }
-
- void getAngularUpperLimit(b3Vector3 & angularUpper)
- {
- for (int i = 0; i < 3; i++)
- angularUpper[i] = m_angularLimits[i].m_hiLimit;
- }
-
- //! Retrieves the angular limit informacion
- b3RotationalLimitMotor* getRotationalLimitMotor(int index)
- {
- return &m_angularLimits[index];
- }
-
- //! Retrieves the limit informacion
- b3TranslationalLimitMotor* getTranslationalLimitMotor()
- {
- return &m_linearLimits;
- }
-
- //first 3 are linear, next 3 are angular
- void setLimit(int axis, b3Scalar lo, b3Scalar hi)
- {
- if (axis < 3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
- lo = b3NormalizeAngle(lo);
- hi = b3NormalizeAngle(hi);
- m_angularLimits[axis - 3].m_loLimit = lo;
- m_angularLimits[axis - 3].m_hiLimit = hi;
- }
- }
-
- //! Test limit
- /*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
- bool isLimited(int limitIndex)
- {
- if (limitIndex < 3)
- {
- return m_linearLimits.isLimited(limitIndex);
- }
- return m_angularLimits[limitIndex - 3].isLimited();
- }
-
- virtual void calcAnchorPos(const b3RigidBodyData* bodies); // overridable
-
- int get_limit_motor_info2(b3RotationalLimitMotor * limot,
- const b3Transform& transA, const b3Transform& transB, const b3Vector3& linVelA, const b3Vector3& linVelB, const b3Vector3& angVelA, const b3Vector3& angVelB,
- b3ConstraintInfo2* info, int row, b3Vector3& ax1, int rotational, int rotAllowed = false);
-
- // access for UseFrameOffset
- bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
- void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1);
- ///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const;
-
- void setAxis(const b3Vector3& axis1, const b3Vector3& axis2, const b3RigidBodyData* bodies);
-};
-
-#endif //B3_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
deleted file mode 100644
index 13269debf6..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3JacobianEntry.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_JACOBIAN_ENTRY_H
-#define B3_JACOBIAN_ENTRY_H
-
-#include "Bullet3Common/b3Matrix3x3.h"
-
-//notes:
-// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
-// which makes the b3JacobianEntry memory layout 16 bytes
-// if you only are interested in angular part, just feed massInvA and massInvB zero
-
-/// Jacobian entry is an abstraction that allows to describe constraints
-/// it can be used in combination with a constraint solver
-/// Can be used to relate the effect of an impulse to the constraint error
-B3_ATTRIBUTE_ALIGNED16(class)
-b3JacobianEntry
-{
-public:
- b3JacobianEntry(){};
- //constraint between two different rigidbodies
- b3JacobianEntry(
- const b3Matrix3x3& world2A,
- const b3Matrix3x3& world2B,
- const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
- const b3Vector3& jointAxis,
- const b3Vector3& inertiaInvA,
- const b3Scalar massInvA,
- const b3Vector3& inertiaInvB,
- const b3Scalar massInvB)
- : m_linearJointAxis(jointAxis)
- {
- m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
- m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
-
- b3Assert(m_Adiag > b3Scalar(0.0));
- }
-
- //angular constraint between two different rigidbodies
- b3JacobianEntry(const b3Vector3& jointAxis,
- const b3Matrix3x3& world2A,
- const b3Matrix3x3& world2B,
- const b3Vector3& inertiaInvA,
- const b3Vector3& inertiaInvB)
- : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.)))
- {
- m_aJ = world2A * jointAxis;
- m_bJ = world2B * -jointAxis;
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
-
- b3Assert(m_Adiag > b3Scalar(0.0));
- }
-
- //angular constraint between two different rigidbodies
- b3JacobianEntry(const b3Vector3& axisInA,
- const b3Vector3& axisInB,
- const b3Vector3& inertiaInvA,
- const b3Vector3& inertiaInvB)
- : m_linearJointAxis(b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
- {
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
-
- b3Assert(m_Adiag > b3Scalar(0.0));
- }
-
- //constraint on one rigidbody
- b3JacobianEntry(
- const b3Matrix3x3& world2A,
- const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
- const b3Vector3& jointAxis,
- const b3Vector3& inertiaInvA,
- const b3Scalar massInvA)
- : m_linearJointAxis(jointAxis)
- {
- m_aJ = world2A * (rel_pos1.cross(jointAxis));
- m_bJ = world2A * (rel_pos2.cross(-jointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
-
- b3Assert(m_Adiag > b3Scalar(0.0));
- }
-
- b3Scalar getDiagonal() const { return m_Adiag; }
-
- // for two constraints on the same rigidbody (for example vehicle friction)
- b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA) const
- {
- const b3JacobianEntry& jacA = *this;
- b3Scalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
- b3Scalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
- return lin + ang;
- }
-
- // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
- b3Scalar getNonDiagonal(const b3JacobianEntry& jacB, const b3Scalar massInvA, const b3Scalar massInvB) const
- {
- const b3JacobianEntry& jacA = *this;
- b3Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
- b3Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
- b3Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
- b3Vector3 lin0 = massInvA * lin;
- b3Vector3 lin1 = massInvB * lin;
- b3Vector3 sum = ang0 + ang1 + lin0 + lin1;
- return sum[0] + sum[1] + sum[2];
- }
-
- b3Scalar getRelativeVelocity(const b3Vector3& linvelA, const b3Vector3& angvelA, const b3Vector3& linvelB, const b3Vector3& angvelB)
- {
- b3Vector3 linrel = linvelA - linvelB;
- b3Vector3 angvela = angvelA * m_aJ;
- b3Vector3 angvelb = angvelB * m_bJ;
- linrel *= m_linearJointAxis;
- angvela += angvelb;
- angvela += linrel;
- b3Scalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
- return rel_vel2 + B3_EPSILON;
- }
- //private:
-
- b3Vector3 m_linearJointAxis;
- b3Vector3 m_aJ;
- b3Vector3 m_bJ;
- b3Vector3 m_0MinvJt;
- b3Vector3 m_1MinvJt;
- //Optimization: can be stored in the w/last component of one of the vectors
- b3Scalar m_Adiag;
-};
-
-#endif //B3_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
deleted file mode 100644
index b7050b1070..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.cpp
+++ /dev/null
@@ -1,1696 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2012 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//enable B3_SOLVER_DEBUG if you experience solver crashes
-//#define B3_SOLVER_DEBUG
-//#define COMPUTE_IMPULSE_DENOM 1
-//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
-
-//#define DISABLE_JOINTS
-
-#include "b3PgsJacobiSolver.h"
-#include "Bullet3Common/b3MinMax.h"
-#include "b3TypedConstraint.h"
-#include <new>
-#include "Bullet3Common/b3StackAlloc.h"
-
-//#include "b3SolverBody.h"
-//#include "b3SolverConstraint.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include <string.h> //for memset
-//#include "../../dynamics/basic_demo/Stubs/AdlContact4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-static b3Transform getWorldTransform(b3RigidBodyData* rb)
-{
- b3Transform newTrans;
- newTrans.setOrigin(rb->m_pos);
- newTrans.setRotation(rb->m_quat);
- return newTrans;
-}
-
-static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
-{
- return inertia->m_invInertiaWorld;
-}
-
-static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
-{
- return rb->m_linVel;
-}
-
-static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
-{
- return rb->m_angVel;
-}
-
-static b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
-{
- //we also calculate lin/ang velocity for kinematic objects
- return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
-}
-
-struct b3ContactPoint
-{
- b3Vector3 m_positionWorldOnA;
- b3Vector3 m_positionWorldOnB;
- b3Vector3 m_normalWorldOnB;
- b3Scalar m_appliedImpulse;
- b3Scalar m_distance;
- b3Scalar m_combinedRestitution;
-
- ///information related to friction
- b3Scalar m_combinedFriction;
- b3Vector3 m_lateralFrictionDir1;
- b3Vector3 m_lateralFrictionDir2;
- b3Scalar m_appliedImpulseLateral1;
- b3Scalar m_appliedImpulseLateral2;
- b3Scalar m_combinedRollingFriction;
- b3Scalar m_contactMotion1;
- b3Scalar m_contactMotion2;
- b3Scalar m_contactCFM1;
- b3Scalar m_contactCFM2;
-
- bool m_lateralFrictionInitialized;
-
- b3Vector3 getPositionWorldOnA()
- {
- return m_positionWorldOnA;
- }
- b3Vector3 getPositionWorldOnB()
- {
- return m_positionWorldOnB;
- }
- b3Scalar getDistance()
- {
- return m_distance;
- }
-};
-
-void getContactPoint(b3Contact4* contact, int contactIndex, b3ContactPoint& pointOut)
-{
- pointOut.m_appliedImpulse = 0.f;
- pointOut.m_appliedImpulseLateral1 = 0.f;
- pointOut.m_appliedImpulseLateral2 = 0.f;
- pointOut.m_combinedFriction = contact->getFrictionCoeff();
- pointOut.m_combinedRestitution = contact->getRestituitionCoeff();
- pointOut.m_combinedRollingFriction = 0.f;
- pointOut.m_contactCFM1 = 0.f;
- pointOut.m_contactCFM2 = 0.f;
- pointOut.m_contactMotion1 = 0.f;
- pointOut.m_contactMotion2 = 0.f;
- pointOut.m_distance = contact->getPenetration(contactIndex); //??0.01f
- b3Vector3 normalOnB = contact->m_worldNormalOnB;
- normalOnB.normalize(); //is this needed?
-
- b3Vector3 l1, l2;
- b3PlaneSpace1(normalOnB, l1, l2);
-
- pointOut.m_normalWorldOnB = normalOnB;
- //printf("normalOnB = %f,%f,%f\n",normalOnB.getX(),normalOnB.getY(),normalOnB.getZ());
- pointOut.m_lateralFrictionDir1 = l1;
- pointOut.m_lateralFrictionDir2 = l2;
- pointOut.m_lateralFrictionInitialized = true;
-
- b3Vector3 worldPosB = contact->m_worldPosB[contactIndex];
- pointOut.m_positionWorldOnB = worldPosB;
- pointOut.m_positionWorldOnA = worldPosB + normalOnB * pointOut.m_distance;
-}
-
-int getNumContacts(b3Contact4* contact)
-{
- return contact->getNPoints();
-}
-
-b3PgsJacobiSolver::b3PgsJacobiSolver(bool usePgs)
- : m_usePgs(usePgs),
- m_numSplitImpulseRecoveries(0),
- m_btSeed2(0)
-{
-}
-
-b3PgsJacobiSolver::~b3PgsJacobiSolver()
-{
-}
-
-void b3PgsJacobiSolver::solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints)
-{
- b3ContactSolverInfo infoGlobal;
- infoGlobal.m_splitImpulse = false;
- infoGlobal.m_timeStep = 1.f / 60.f;
- infoGlobal.m_numIterations = 4; //4;
- // infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
- //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
- infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
-
- //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
-
- solveGroup(bodies, inertias, numBodies, contacts, numContacts, constraints, numConstraints, infoGlobal);
-
- if (!numContacts)
- return;
-}
-
-/// b3PgsJacobiSolver Sequentially applies impulses
-b3Scalar b3PgsJacobiSolver::solveGroup(b3RigidBodyData* bodies,
- b3InertiaData* inertias,
- int numBodies,
- b3Contact4* manifoldPtr,
- int numManifolds,
- b3TypedConstraint** constraints,
- int numConstraints,
- const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveGroup");
- //you need to provide at least some bodies
-
- solveGroupCacheFriendlySetup(bodies, inertias, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal);
-
- solveGroupCacheFriendlyIterations(constraints, numConstraints, infoGlobal);
-
- solveGroupCacheFriendlyFinish(bodies, inertias, numBodies, infoGlobal);
-
- return 0.f;
-}
-
-#ifdef USE_SIMD
-#include <emmintrin.h>
-#define b3VecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
-static inline __m128 b3SimdDot3(__m128 vec0, __m128 vec1)
-{
- __m128 result = _mm_mul_ps(vec0, vec1);
- return _mm_add_ps(b3VecSplat(result, 0), _mm_add_ps(b3VecSplat(result, 1), b3VecSplat(result, 2)));
-}
-#endif //USE_SIMD
-
-// Project Gauss Seidel or the equivalent Sequential Impulse
-void b3PgsJacobiSolver::resolveSingleConstraintRowGenericSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
-{
-#ifdef USE_SIMD
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- b3SimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
-#else
- resolveSingleConstraintRowGeneric(body1, body2, c);
-#endif
-}
-
-// Project Gauss Seidel or the equivalent Sequential Impulse
-void b3PgsJacobiSolver::resolveSingleConstraintRowGeneric(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
-{
- b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
-
- // const b3Scalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
-
- const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else if (sum > c.m_upperLimit)
- {
- deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_upperLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
-
- body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
-}
-
-void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
-{
-#ifdef USE_SIMD
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetDeltaLinearVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetDeltaAngularVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetDeltaLinearVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- b3SimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- body1.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body1.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- body2.internalGetDeltaLinearVelocity().mVec128 = _mm_sub_ps(body2.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- body2.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(body2.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
-#else
- resolveSingleConstraintRowLowerLimit(body1, body2, c);
-#endif
-}
-
-// Project Gauss Seidel or the equivalent Sequential Impulse
-void b3PgsJacobiSolver::resolveSingleConstraintRowLowerLimit(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
-{
- b3Scalar deltaImpulse = c.m_rhs - b3Scalar(c.m_appliedImpulse) * c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetDeltaAngularVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetDeltaAngularVelocity());
-
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
- const b3Scalar sum = b3Scalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
- body1.internalApplyImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- body2.internalApplyImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
-}
-
-void b3PgsJacobiSolver::resolveSplitPenetrationImpulseCacheFriendly(
- b3SolverBody& body1,
- b3SolverBody& body2,
- const b3SolverConstraint& c)
-{
- if (c.m_rhsPenetration)
- {
- m_numSplitImpulseRecoveries++;
- b3Scalar deltaImpulse = c.m_rhsPenetration - b3Scalar(c.m_appliedPushImpulse) * c.m_cfm;
- const b3Scalar deltaVel1Dotn = c.m_contactNormal.dot(body1.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(body1.internalGetTurnVelocity());
- const b3Scalar deltaVel2Dotn = -c.m_contactNormal.dot(body2.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(body2.internalGetTurnVelocity());
-
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
- const b3Scalar sum = b3Scalar(c.m_appliedPushImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
- c.m_appliedPushImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedPushImpulse = sum;
- }
- body1.internalApplyPushImpulse(c.m_contactNormal * body1.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- body2.internalApplyPushImpulse(-c.m_contactNormal * body2.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- }
-}
-
-void b3PgsJacobiSolver::resolveSplitPenetrationSIMD(b3SolverBody& body1, b3SolverBody& body2, const b3SolverConstraint& c)
-{
-#ifdef USE_SIMD
- if (!c.m_rhsPenetration)
- return;
-
- m_numSplitImpulseRecoveries++;
-
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(b3SimdDot3(c.m_contactNormal.mVec128, body1.internalGetPushVelocity().mVec128), b3SimdDot3(c.m_relpos1CrossNormal.mVec128, body1.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_sub_ps(b3SimdDot3(c.m_relpos2CrossNormal.mVec128, body2.internalGetTurnVelocity().mVec128), b3SimdDot3((c.m_contactNormal).mVec128, body2.internalGetPushVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- b3SimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- b3SimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal.mVec128, body1.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal).mVec128, body2.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- body1.internalGetPushVelocity().mVec128 = _mm_add_ps(body1.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- body1.internalGetTurnVelocity().mVec128 = _mm_add_ps(body1.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- body2.internalGetPushVelocity().mVec128 = _mm_sub_ps(body2.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- body2.internalGetTurnVelocity().mVec128 = _mm_add_ps(body2.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
-#else
- resolveSplitPenetrationImpulseCacheFriendly(body1, body2, c);
-#endif
-}
-
-unsigned long b3PgsJacobiSolver::b3Rand2()
-{
- m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
- return m_btSeed2;
-}
-
-//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
-int b3PgsJacobiSolver::b3RandInt2(int n)
-{
- // seems good; xor-fold and modulus
- const unsigned long un = static_cast<unsigned long>(n);
- unsigned long r = b3Rand2();
-
- // note: probably more aggressive than it needs to be -- might be
- // able to get away without one or two of the innermost branches.
- if (un <= 0x00010000UL)
- {
- r ^= (r >> 16);
- if (un <= 0x00000100UL)
- {
- r ^= (r >> 8);
- if (un <= 0x00000010UL)
- {
- r ^= (r >> 4);
- if (un <= 0x00000004UL)
- {
- r ^= (r >> 2);
- if (un <= 0x00000002UL)
- {
- r ^= (r >> 1);
- }
- }
- }
- }
- }
-
- return (int)(r % un);
-}
-
-void b3PgsJacobiSolver::initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* rb)
-{
- solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
- solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
- solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- if (rb)
- {
- solverBody->m_worldTransform = getWorldTransform(rb);
- solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
- solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
- solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
- solverBody->m_linearVelocity = getLinearVelocity(rb);
- solverBody->m_angularVelocity = getAngularVelocity(rb);
- }
- else
- {
- solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(b3MakeVector3(0, 0, 0));
- solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor.setValue(1, 1, 1);
- solverBody->m_linearFactor.setValue(1, 1, 1);
- solverBody->m_linearVelocity.setValue(0, 0, 0);
- solverBody->m_angularVelocity.setValue(0, 0, 0);
- }
-}
-
-b3Scalar b3PgsJacobiSolver::restitutionCurve(b3Scalar rel_vel, b3Scalar restitution)
-{
- b3Scalar rest = restitution * -rel_vel;
- return rest;
-}
-
-void b3PgsJacobiSolver::setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
-{
- solverConstraint.m_contactNormal = normalAxis;
- b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
-
- b3RigidBodyData* body0 = &bodies[solverBodyA.m_originalBodyIndex];
- b3RigidBodyData* body1 = &bodies[solverBodyB.m_originalBodyIndex];
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_friction = cp.m_combinedFriction;
- solverConstraint.m_originalContactPoint = 0;
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- b3Vector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal);
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
- }
- {
- b3Vector3 ftorqueAxis1 = rel_pos2.cross(-solverConstraint.m_contactNormal);
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
- }
-
- b3Scalar scaledDenom;
-
- {
- b3Vector3 vec;
- b3Scalar denom0 = 0.f;
- b3Scalar denom1 = 0.f;
- if (body0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = body0->m_invMass + normalAxis.dot(vec);
- }
- if (body1)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = body1->m_invMass + normalAxis.dot(vec);
- }
-
- b3Scalar denom;
- if (m_usePgs)
- {
- scaledDenom = denom = relaxation / (denom0 + denom1);
- }
- else
- {
- denom = relaxation / (denom0 + denom1);
- b3Scalar countA = body0->m_invMass ? b3Scalar(m_bodyCount[solverBodyA.m_originalBodyIndex]) : 1.f;
- b3Scalar countB = body1->m_invMass ? b3Scalar(m_bodyCount[solverBodyB.m_originalBodyIndex]) : 1.f;
-
- scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
- }
-
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- {
- b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- // b3Scalar positionalError = 0.f;
-
- b3SimdScalar velocityError = desiredVelocity - rel_vel;
- b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(scaledDenom); //solverConstraint.m_jacDiagABInv);
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
-}
-
-b3SolverConstraint& b3PgsJacobiSolver::addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
-{
- b3SolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-void b3PgsJacobiSolver::setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity, b3Scalar cfmSlip)
-
-{
- b3Vector3 normalAxis = b3MakeVector3(0, 0, 0);
-
- solverConstraint.m_contactNormal = normalAxis;
- b3SolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
-
- b3RigidBodyData* body0 = &bodies[m_tmpSolverBodyPool[solverBodyIdA].m_originalBodyIndex];
- b3RigidBodyData* body1 = &bodies[m_tmpSolverBodyPool[solverBodyIdB].m_originalBodyIndex];
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_friction = cp.m_combinedRollingFriction;
- solverConstraint.m_originalContactPoint = 0;
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- b3Vector3 ftorqueAxis1 = -normalAxis1;
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
- }
- {
- b3Vector3 ftorqueAxis1 = normalAxis1;
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * ftorqueAxis1 : b3MakeVector3(0, 0, 0);
- }
-
- {
- b3Vector3 iMJaA = body0 ? getInvInertiaTensorWorld(&inertias[solverBodyA.m_originalBodyIndex]) * solverConstraint.m_relpos1CrossNormal : b3MakeVector3(0, 0, 0);
- b3Vector3 iMJaB = body1 ? getInvInertiaTensorWorld(&inertias[solverBodyB.m_originalBodyIndex]) * solverConstraint.m_relpos2CrossNormal : b3MakeVector3(0, 0, 0);
- b3Scalar sum = 0;
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- solverConstraint.m_jacDiagABInv = b3Scalar(1.) / sum;
- }
-
- {
- b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(body0 ? solverBodyA.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : b3MakeVector3(0, 0, 0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(body1 ? solverBodyB.m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(body1 ? solverBodyB.m_angularVelocity : b3MakeVector3(0, 0, 0));
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- // b3Scalar positionalError = 0.f;
-
- b3SimdScalar velocityError = desiredVelocity - rel_vel;
- b3SimdScalar velocityImpulse = velocityError * b3SimdScalar(solverConstraint.m_jacDiagABInv);
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
-}
-
-b3SolverConstraint& b3PgsJacobiSolver::addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity, b3Scalar cfmSlip)
-{
- b3SolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupRollingFrictionConstraint(bodies, inertias, solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-int b3PgsJacobiSolver::getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias)
-{
- //b3Assert(bodyIndex< m_tmpSolverBodyPool.size());
-
- b3RigidBodyData& body = bodies[bodyIndex];
- int curIndex = -1;
- if (m_usePgs || body.m_invMass == 0.f)
- {
- if (m_bodyCount[bodyIndex] < 0)
- {
- curIndex = m_tmpSolverBodyPool.size();
- b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(bodyIndex, &solverBody, &body);
- solverBody.m_originalBodyIndex = bodyIndex;
- m_bodyCount[bodyIndex] = curIndex;
- }
- else
- {
- curIndex = m_bodyCount[bodyIndex];
- }
- }
- else
- {
- b3Assert(m_bodyCount[bodyIndex] > 0);
- m_bodyCountCheck[bodyIndex]++;
- curIndex = m_tmpSolverBodyPool.size();
- b3SolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(bodyIndex, &solverBody, &body);
- solverBody.m_originalBodyIndex = bodyIndex;
- }
-
- b3Assert(curIndex >= 0);
- return curIndex;
-}
-#include <stdio.h>
-
-void b3PgsJacobiSolver::setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal,
- b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
- b3Vector3& rel_pos1, b3Vector3& rel_pos2)
-{
- const b3Vector3& pos1 = cp.getPositionWorldOnA();
- const b3Vector3& pos2 = cp.getPositionWorldOnB();
-
- b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- b3RigidBodyData* rb0 = &bodies[bodyA->m_originalBodyIndex];
- b3RigidBodyData* rb1 = &bodies[bodyB->m_originalBodyIndex];
-
- // b3Vector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- // b3Vector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = 1.f;
-
- b3Vector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentA = rb0 ? getInvInertiaTensorWorld(&inertias[bodyA->m_originalBodyIndex]) * torqueAxis0 : b3MakeVector3(0, 0, 0);
- b3Vector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentB = rb1 ? getInvInertiaTensorWorld(&inertias[bodyB->m_originalBodyIndex]) * -torqueAxis1 : b3MakeVector3(0, 0, 0);
-
- b3Scalar scaledDenom;
- {
-#ifdef COMPUTE_IMPULSE_DENOM
- b3Scalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
- b3Scalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
-#else
- b3Vector3 vec;
- b3Scalar denom0 = 0.f;
- b3Scalar denom1 = 0.f;
- if (rb0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->m_invMass + cp.m_normalWorldOnB.dot(vec);
- }
- if (rb1)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->m_invMass + cp.m_normalWorldOnB.dot(vec);
- }
-#endif //COMPUTE_IMPULSE_DENOM
-
- b3Scalar denom;
- if (m_usePgs)
- {
- scaledDenom = denom = relaxation / (denom0 + denom1);
- }
- else
- {
- denom = relaxation / (denom0 + denom1);
-
- b3Scalar countA = rb0->m_invMass ? b3Scalar(m_bodyCount[bodyA->m_originalBodyIndex]) : 1.f;
- b3Scalar countB = rb1->m_invMass ? b3Scalar(m_bodyCount[bodyB->m_originalBodyIndex]) : 1.f;
- scaledDenom = relaxation / (denom0 * countA + denom1 * countB);
- }
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- solverConstraint.m_contactNormal = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
-
- b3Scalar restitution = 0.f;
- b3Scalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
-
- {
- b3Vector3 vel1, vel2;
-
- vel1 = rb0 ? getVelocityInLocalPoint(rb0, rel_pos1) : b3MakeVector3(0, 0, 0);
- vel2 = rb1 ? getVelocityInLocalPoint(rb1, rel_pos2) : b3MakeVector3(0, 0, 0);
-
- // b3Vector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : b3Vector3(0,0,0);
- vel = vel1 - vel2;
- rel_vel = cp.m_normalWorldOnB.dot(vel);
-
- solverConstraint.m_friction = cp.m_combinedFriction;
-
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution);
- if (restitution <= b3Scalar(0.))
- {
- restitution = 0.f;
- };
- }
-
- ///warm starting (or zero if disabled)
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(solverConstraint.m_contactNormal * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(b3Scalar)solverConstraint.m_appliedImpulse);
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
-
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rb0 ? bodyA->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? bodyA->m_angularVelocity : b3MakeVector3(0, 0, 0));
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rb1 ? bodyB->m_linearVelocity : b3MakeVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? bodyB->m_angularVelocity : b3MakeVector3(0, 0, 0));
- b3Scalar rel_vel = vel1Dotn + vel2Dotn;
-
- b3Scalar positionalError = 0.f;
- b3Scalar velocityError = restitution - rel_vel; // * damping;
-
- b3Scalar erp = infoGlobal.m_erp2;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- erp = infoGlobal.m_erp;
- }
-
- if (penetration > 0)
- {
- positionalError = 0;
-
- velocityError -= penetration / infoGlobal.m_timeStep;
- }
- else
- {
- positionalError = -penetration * erp / infoGlobal.m_timeStep;
- }
-
- b3Scalar penetrationImpulse = positionalError * scaledDenom; //solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError * scaledDenom; //solverConstraint.m_jacDiagABInv;
-
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- }
- else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- solverConstraint.m_cfm = 0.f;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
-}
-
-void b3PgsJacobiSolver::setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal)
-{
- b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- {
- b3SolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint1.m_appliedImpulse = cp.m_appliedImpulseLateral1 * infoGlobal.m_warmstartingFactor;
- if (bodies[bodyA->m_originalBodyIndex].m_invMass)
- bodyA->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint1.m_angularComponentA, frictionConstraint1.m_appliedImpulse);
- if (bodies[bodyB->m_originalBodyIndex].m_invMass)
- bodyB->internalApplyImpulse(frictionConstraint1.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint1.m_angularComponentB, -(b3Scalar)frictionConstraint1.m_appliedImpulse);
- }
- else
- {
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
- }
-
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- b3SolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
- {
- frictionConstraint2.m_appliedImpulse = cp.m_appliedImpulseLateral2 * infoGlobal.m_warmstartingFactor;
- if (bodies[bodyA->m_originalBodyIndex].m_invMass)
- bodyA->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyA->m_originalBodyIndex].m_invMass, frictionConstraint2.m_angularComponentA, frictionConstraint2.m_appliedImpulse);
- if (bodies[bodyB->m_originalBodyIndex].m_invMass)
- bodyB->internalApplyImpulse(frictionConstraint2.m_contactNormal * bodies[bodyB->m_originalBodyIndex].m_invMass, -frictionConstraint2.m_angularComponentB, -(b3Scalar)frictionConstraint2.m_appliedImpulse);
- }
- else
- {
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
- }
-}
-
-void b3PgsJacobiSolver::convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal)
-{
- b3RigidBodyData *colObj0 = 0, *colObj1 = 0;
-
- int solverBodyIdA = getOrInitSolverBody(manifold->getBodyA(), bodies, inertias);
- int solverBodyIdB = getOrInitSolverBody(manifold->getBodyB(), bodies, inertias);
-
- // b3RigidBody* bodyA = b3RigidBody::upcast(colObj0);
- // b3RigidBody* bodyB = b3RigidBody::upcast(colObj1);
-
- b3SolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- ///avoid collision response between two static objects
- if (solverBodyA->m_invMass.isZero() && solverBodyB->m_invMass.isZero())
- return;
-
- int rollingFriction = 1;
- int numContacts = getNumContacts(manifold);
- for (int j = 0; j < numContacts; j++)
- {
- b3ContactPoint cp;
- getContactPoint(manifold, j, cp);
-
- if (cp.getDistance() <= getContactProcessingThreshold(manifold))
- {
- b3Vector3 rel_pos1;
- b3Vector3 rel_pos2;
- b3Scalar relaxation;
- b3Scalar rel_vel;
- b3Vector3 vel;
-
- int frictionIndex = m_tmpSolverContactConstraintPool.size();
- b3SolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
- // b3RigidBody* rb0 = b3RigidBody::upcast(colObj0);
- // b3RigidBody* rb1 = b3RigidBody::upcast(colObj1);
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- setupContactConstraint(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, vel, rel_vel, relaxation, rel_pos1, rel_pos2);
-
- // const b3Vector3& pos1 = cp.getPositionWorldOnA();
- // const b3Vector3& pos2 = cp.getPositionWorldOnB();
-
- /////setup the friction constraints
-
- solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
-
- b3Vector3 angVelA, angVelB;
- solverBodyA->getAngularVelocity(angVelA);
- solverBodyB->getAngularVelocity(angVelB);
- b3Vector3 relAngVel = angVelB - angVelA;
-
- if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
- {
- //only a single rollingFriction per manifold
- rollingFriction--;
- if (relAngVel.length() > infoGlobal.m_singleAxisRollingFrictionThreshold)
- {
- relAngVel.normalize();
- if (relAngVel.length() > 0.001)
- addRollingFrictionConstraint(bodies, inertias, relAngVel, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
- else
- {
- addRollingFrictionConstraint(bodies, inertias, cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- b3Vector3 axis0, axis1;
- b3PlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
- if (axis0.length() > 0.001)
- addRollingFrictionConstraint(bodies, inertias, axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- if (axis1.length() > 0.001)
- addRollingFrictionConstraint(bodies, inertias, axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
- }
-
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
-
- ///You can also enable two friction directions, using the B3_SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
- if (!(infoGlobal.m_solverMode & B3_SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !cp.m_lateralFrictionInitialized)
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- b3Scalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > B3_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f / b3Sqrt(lat_rel_vel);
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize(); //??
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
-
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
- else
- {
- b3PlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
-
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
-
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
-
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_lateralFrictionInitialized = true;
- }
- }
- }
- else
- {
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion1, cp.m_contactCFM1);
-
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(bodies, inertias, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, cp.m_contactMotion2, cp.m_contactCFM2);
-
- setFrictionConstraintImpulse(bodies, inertias, solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- }
- }
- }
-}
-
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveGroupCacheFriendlySetup");
-
- m_maxOverrideNumSolverIterations = 0;
-
- m_tmpSolverBodyPool.resize(0);
-
- m_bodyCount.resize(0);
- m_bodyCount.resize(numBodies, 0);
- m_bodyCountCheck.resize(0);
- m_bodyCountCheck.resize(numBodies, 0);
-
- m_deltaLinearVelocities.resize(0);
- m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
- m_deltaAngularVelocities.resize(0);
- m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
-
- //int totalBodies = 0;
-
- for (int i = 0; i < numConstraints; i++)
- {
- int bodyIndexA = constraints[i]->getRigidBodyA();
- int bodyIndexB = constraints[i]->getRigidBodyB();
- if (m_usePgs)
- {
- m_bodyCount[bodyIndexA] = -1;
- m_bodyCount[bodyIndexB] = -1;
- }
- else
- {
- //didn't implement joints with Jacobi version yet
- b3Assert(0);
- }
- }
- for (int i = 0; i < numManifolds; i++)
- {
- int bodyIndexA = manifoldPtr[i].getBodyA();
- int bodyIndexB = manifoldPtr[i].getBodyB();
- if (m_usePgs)
- {
- m_bodyCount[bodyIndexA] = -1;
- m_bodyCount[bodyIndexB] = -1;
- }
- else
- {
- if (bodies[bodyIndexA].m_invMass)
- {
- //m_bodyCount[bodyIndexA]+=manifoldPtr[i].getNPoints();
- m_bodyCount[bodyIndexA]++;
- }
- else
- m_bodyCount[bodyIndexA] = -1;
-
- if (bodies[bodyIndexB].m_invMass)
- // m_bodyCount[bodyIndexB]+=manifoldPtr[i].getNPoints();
- m_bodyCount[bodyIndexB]++;
- else
- m_bodyCount[bodyIndexB] = -1;
- }
- }
-
- if (1)
- {
- int j;
- for (j = 0; j < numConstraints; j++)
- {
- b3TypedConstraint* constraint = constraints[j];
-
- constraint->internalSetAppliedImpulse(0.0f);
- }
- }
-
- //b3RigidBody* rb0=0,*rb1=0;
- //if (1)
- {
- {
- int totalNumRows = 0;
- int i;
-
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- //calculate the total number of contraint rows
- for (i = 0; i < numConstraints; i++)
- {
- b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- b3JointFeedback* fb = constraints[i]->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
-
- if (constraints[i]->isEnabled())
- {
- }
- if (constraints[i]->isEnabled())
- {
- constraints[i]->getInfo1(&info1, bodies);
- }
- else
- {
- info1.m_numConstraintRows = 0;
- info1.nub = 0;
- }
- totalNumRows += info1.m_numConstraintRows;
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
-
-#ifndef DISABLE_JOINTS
- ///setup the b3SolverConstraints
- int currentRow = 0;
-
- for (i = 0; i < numConstraints; i++)
- {
- const b3TypedConstraint::b3ConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
-
- if (info1.m_numConstraintRows)
- {
- b3Assert(currentRow < totalNumRows);
-
- b3SolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
- b3TypedConstraint* constraint = constraints[i];
-
- b3RigidBodyData& rbA = bodies[constraint->getRigidBodyA()];
- //b3RigidBody& rbA = constraint->getRigidBodyA();
- // b3RigidBody& rbB = constraint->getRigidBodyB();
- b3RigidBodyData& rbB = bodies[constraint->getRigidBodyB()];
-
- int solverBodyIdA = getOrInitSolverBody(constraint->getRigidBodyA(), bodies, inertias);
- int solverBodyIdB = getOrInitSolverBody(constraint->getRigidBodyB(), bodies, inertias);
-
- b3SolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- b3SolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
-
- int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
- m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
- int j;
- for (j = 0; j < info1.m_numConstraintRows; j++)
- {
- memset(&currentConstraintRow[j], 0, sizeof(b3SolverConstraint));
- currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
- currentConstraintRow[j].m_upperLimit = B3_INFINITY;
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
- currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
- currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
- }
-
- bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- b3TypedConstraint::b3ConstraintInfo2 info2;
- info2.fps = 1.f / infoGlobal.m_timeStep;
- info2.erp = infoGlobal.m_erp;
- info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
- info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxis = 0;
- info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(b3SolverConstraint) / sizeof(b3Scalar); //check this
- ///the size of b3SolverConstraint needs be a multiple of b3Scalar
- b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3SolverConstraint));
- info2.m_constraintError = &currentConstraintRow->m_rhs;
- currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
- info2.m_damping = infoGlobal.m_damping;
- info2.cfm = &currentConstraintRow->m_cfm;
- info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
- info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
- info2.m_numIterations = infoGlobal.m_numIterations;
- constraints[i]->getInfo2(&info2, bodies);
-
- ///finalize the constraint setup
- for (j = 0; j < info1.m_numConstraintRows; j++)
- {
- b3SolverConstraint& solverConstraint = currentConstraintRow[j];
-
- if (solverConstraint.m_upperLimit >= constraints[i]->getBreakingImpulseThreshold())
- {
- solverConstraint.m_upperLimit = constraints[i]->getBreakingImpulseThreshold();
- }
-
- if (solverConstraint.m_lowerLimit <= -constraints[i]->getBreakingImpulseThreshold())
- {
- solverConstraint.m_lowerLimit = -constraints[i]->getBreakingImpulseThreshold();
- }
-
- solverConstraint.m_originalContactPoint = constraint;
-
- b3Matrix3x3& invInertiaWorldA = inertias[constraint->getRigidBodyA()].m_invInertiaWorld;
- {
- //b3Vector3 angularFactorA(1,1,1);
- const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1; //*angularFactorA;
- }
-
- b3Matrix3x3& invInertiaWorldB = inertias[constraint->getRigidBodyB()].m_invInertiaWorld;
- {
- const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2; //*constraint->getRigidBodyB().getAngularFactor();
- }
-
- {
- //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
- //because it gets multiplied iMJlB
- b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
- b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
- b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass; //sign of normal?
- b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
-
- b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJlB.dot(solverConstraint.m_contactNormal);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- b3Scalar fsum = b3Fabs(sum);
- b3Assert(fsum > B3_EPSILON);
- solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
- }
-
- ///fix rhs
- ///todo: add force/torque accelerators
- {
- b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- b3Scalar restitution = 0.f;
- b3Scalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
- b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
- b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_appliedImpulse = 0.f;
- }
- }
- }
- currentRow += m_tmpConstraintSizesPool[i].m_numConstraintRows;
- }
-#endif //DISABLE_JOINTS
- }
-
- {
- int i;
-
- for (i = 0; i < numManifolds; i++)
- {
- b3Contact4& manifold = manifoldPtr[i];
- convertContact(bodies, inertias, &manifold, infoGlobal);
- }
- }
- }
-
- // b3ContactSolverInfo info = infoGlobal;
-
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
- m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
- else
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
-
- m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
- {
- int i;
- for (i = 0; i < numNonContactPool; i++)
- {
- m_orderNonContactConstraintPool[i] = i;
- }
- for (i = 0; i < numConstraintPool; i++)
- {
- m_orderTmpConstraintPool[i] = i;
- }
- for (i = 0; i < numFrictionPool; i++)
- {
- m_orderFrictionConstraintPool[i] = i;
- }
- }
-
- return 0.f;
-}
-
-b3Scalar b3PgsJacobiSolver::solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- if (infoGlobal.m_solverMode & B3_SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- for (int j = 0; j < numNonContactPool; ++j)
- {
- int tmp = m_orderNonContactConstraintPool[j];
- int swapi = b3RandInt2(j + 1);
- m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
- m_orderNonContactConstraintPool[swapi] = tmp;
- }
-
- //contact/friction constraints are not solved more than
- if (iteration < infoGlobal.m_numIterations)
- {
- for (int j = 0; j < numConstraintPool; ++j)
- {
- int tmp = m_orderTmpConstraintPool[j];
- int swapi = b3RandInt2(j + 1);
- m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
- m_orderTmpConstraintPool[swapi] = tmp;
- }
-
- for (int j = 0; j < numFrictionPool; ++j)
- {
- int tmp = m_orderFrictionConstraintPool[j];
- int swapi = b3RandInt2(j + 1);
- m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
- m_orderFrictionConstraintPool[swapi] = tmp;
- }
- }
- }
- }
-
- if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
- {
- ///solve all joint constraints, using SIMD, if available
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
- }
-
- if (iteration < infoGlobal.m_numIterations)
- {
- ///solve all contact constraints using SIMD, if available
- if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
-
- for (int c = 0; c < numPoolConstraints; c++)
- {
- b3Scalar totalImpulse = 0;
-
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- bool applyFriction = true;
- if (applyFriction)
- {
- {
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
-
- if (totalImpulse > b3Scalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
-
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
-
- if (totalImpulse > b3Scalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
- }
- }
- }
- else //B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- //solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
-
- for (j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimitSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
-
- if (!m_usePgs)
- averageVelocities();
-
- ///solve all friction constraints, using SIMD, if available
-
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j = 0; j < numFrictionPoolConstraints; j++)
- {
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
-
- if (totalImpulse > b3Scalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
-
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > b3Scalar(0))
- {
- b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- }
- }
- }
- }
- }
- else
- {
- //non-SIMD version
- ///solve all joint constraints
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- b3SolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
- }
-
- if (iteration < infoGlobal.m_numIterations)
- {
- ///solve all contact constraints
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- for (int j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- ///solve all friction constraints
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (int j = 0; j < numFrictionPoolConstraints; j++)
- {
- b3SolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
-
- if (totalImpulse > b3Scalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
-
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- b3SolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- b3Scalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > b3Scalar(0))
- {
- b3Scalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- }
- }
- }
- }
- return 0.f;
-}
-
-void b3PgsJacobiSolver::solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- int iteration;
- if (infoGlobal.m_splitImpulse)
- {
- if (infoGlobal.m_solverMode & B3_SOLVER_SIMD)
- {
- for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
-
- resolveSplitPenetrationSIMD(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
- }
- }
- else
- {
- for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
-
- resolveSplitPenetrationImpulseCacheFriendly(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- }
- }
- }
- }
- }
-}
-
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveGroupCacheFriendlyIterations");
-
- {
- ///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(constraints, numConstraints, infoGlobal);
-
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
-
- for (int iteration = 0; iteration < maxIterations; iteration++)
- //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
- {
- solveSingleIteration(iteration, constraints, numConstraints, infoGlobal);
-
- if (!m_usePgs)
- {
- averageVelocities();
- }
- }
- }
- return 0.f;
-}
-
-void b3PgsJacobiSolver::averageVelocities()
-{
- B3_PROFILE("averaging");
- //average the velocities
- int numBodies = m_bodyCount.size();
-
- m_deltaLinearVelocities.resize(0);
- m_deltaLinearVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
- m_deltaAngularVelocities.resize(0);
- m_deltaAngularVelocities.resize(numBodies, b3MakeVector3(0, 0, 0));
-
- for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
- {
- if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
- {
- int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
- m_deltaLinearVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaLinearVelocity();
- m_deltaAngularVelocities[orgBodyIndex] += m_tmpSolverBodyPool[i].getDeltaAngularVelocity();
- }
- }
-
- for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
- {
- int orgBodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
-
- if (!m_tmpSolverBodyPool[i].m_invMass.isZero())
- {
- b3Assert(m_bodyCount[orgBodyIndex] == m_bodyCountCheck[orgBodyIndex]);
-
- b3Scalar factor = 1.f / b3Scalar(m_bodyCount[orgBodyIndex]);
-
- m_tmpSolverBodyPool[i].m_deltaLinearVelocity = m_deltaLinearVelocities[orgBodyIndex] * factor;
- m_tmpSolverBodyPool[i].m_deltaAngularVelocity = m_deltaAngularVelocities[orgBodyIndex] * factor;
- }
- }
-}
-
-b3Scalar b3PgsJacobiSolver::solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveGroupCacheFriendlyFinish");
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int i, j;
-
- if (infoGlobal.m_solverMode & B3_SOLVER_USE_WARMSTARTING)
- {
- for (j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- b3ContactPoint* pt = (b3ContactPoint*)solveManifold.m_originalContactPoint;
- b3Assert(pt);
- pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
- // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
- if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
- }
- //do a callback here?
- }
- }
-
- numPoolConstraints = m_tmpSolverNonContactConstraintPool.size();
- for (j = 0; j < numPoolConstraints; j++)
- {
- const b3SolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
- b3TypedConstraint* constr = (b3TypedConstraint*)solverConstr.m_originalContactPoint;
- b3JointFeedback* fb = constr->getJointFeedback();
- if (fb)
- {
- b3SolverBody* bodyA = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdA];
- b3SolverBody* bodyB = &m_tmpSolverBodyPool[solverConstr.m_solverBodyIdB];
-
- fb->m_appliedForceBodyA += solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyA->m_linearFactor / infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += -solverConstr.m_contactNormal * solverConstr.m_appliedImpulse * bodyB->m_linearFactor / infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * bodyA->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += -solverConstr.m_relpos1CrossNormal * bodyB->m_angularFactor * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
- }
-
- constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
- if (b3Fabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
- {
- constr->setEnabled(false);
- }
- }
-
- {
- B3_PROFILE("write back velocities and transforms");
- for (i = 0; i < m_tmpSolverBodyPool.size(); i++)
- {
- int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
- //b3Assert(i==bodyIndex);
-
- b3RigidBodyData* body = &bodies[bodyIndex];
- if (body->m_invMass)
- {
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
- else
- m_tmpSolverBodyPool[i].writebackVelocity();
-
- if (m_usePgs)
- {
- body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
- body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
- }
- else
- {
- b3Scalar factor = 1.f / b3Scalar(m_bodyCount[bodyIndex]);
-
- b3Vector3 deltaLinVel = m_deltaLinearVelocities[bodyIndex] * factor;
- b3Vector3 deltaAngVel = m_deltaAngularVelocities[bodyIndex] * factor;
- //printf("body %d\n",bodyIndex);
- //printf("deltaLinVel = %f,%f,%f\n",deltaLinVel.getX(),deltaLinVel.getY(),deltaLinVel.getZ());
- //printf("deltaAngVel = %f,%f,%f\n",deltaAngVel.getX(),deltaAngVel.getY(),deltaAngVel.getZ());
-
- body->m_linVel += deltaLinVel;
- body->m_angVel += deltaAngVel;
- }
-
- if (infoGlobal.m_splitImpulse)
- {
- body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
- b3Quaternion orn;
- orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
- body->m_quat = orn;
- }
- }
- }
- }
-
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
-
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
-}
-
-void b3PgsJacobiSolver::reset()
-{
- m_btSeed2 = 0;
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
deleted file mode 100644
index 5b616541d9..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef B3_PGS_JACOBI_SOLVER
-#define B3_PGS_JACOBI_SOLVER
-
-struct b3Contact4;
-struct b3ContactPoint;
-
-class b3Dispatcher;
-
-#include "b3TypedConstraint.h"
-#include "b3ContactSolverInfo.h"
-#include "b3SolverBody.h"
-#include "b3SolverConstraint.h"
-
-struct b3RigidBodyData;
-struct b3InertiaData;
-
-class b3PgsJacobiSolver
-{
-protected:
- b3AlignedObjectArray<b3SolverBody> m_tmpSolverBodyPool;
- b3ConstraintArray m_tmpSolverContactConstraintPool;
- b3ConstraintArray m_tmpSolverNonContactConstraintPool;
- b3ConstraintArray m_tmpSolverContactFrictionConstraintPool;
- b3ConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
-
- b3AlignedObjectArray<int> m_orderTmpConstraintPool;
- b3AlignedObjectArray<int> m_orderNonContactConstraintPool;
- b3AlignedObjectArray<int> m_orderFrictionConstraintPool;
- b3AlignedObjectArray<b3TypedConstraint::b3ConstraintInfo1> m_tmpConstraintSizesPool;
-
- b3AlignedObjectArray<int> m_bodyCount;
- b3AlignedObjectArray<int> m_bodyCountCheck;
-
- b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocities;
- b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocities;
-
- bool m_usePgs;
- void averageVelocities();
-
- int m_maxOverrideNumSolverIterations;
-
- int m_numSplitImpulseRecoveries;
-
- b3Scalar getContactProcessingThreshold(b3Contact4* contact)
- {
- return 0.02f;
- }
- void setupFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
-
- void setupRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2,
- b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation,
- b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
-
- b3SolverConstraint& addFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0., b3Scalar cfmSlip = 0.);
- b3SolverConstraint& addRollingFrictionConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias, const b3Vector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, b3ContactPoint& cp, const b3Vector3& rel_pos1, const b3Vector3& rel_pos2, b3RigidBodyData* colObj0, b3RigidBodyData* colObj1, b3Scalar relaxation, b3Scalar desiredVelocity = 0, b3Scalar cfmSlip = 0.f);
-
- void setupContactConstraint(b3RigidBodyData* bodies, b3InertiaData* inertias,
- b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB, b3ContactPoint& cp,
- const b3ContactSolverInfo& infoGlobal, b3Vector3& vel, b3Scalar& rel_vel, b3Scalar& relaxation,
- b3Vector3& rel_pos1, b3Vector3& rel_pos2);
-
- void setFrictionConstraintImpulse(b3RigidBodyData* bodies, b3InertiaData* inertias, b3SolverConstraint& solverConstraint, int solverBodyIdA, int solverBodyIdB,
- b3ContactPoint& cp, const b3ContactSolverInfo& infoGlobal);
-
- ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
- unsigned long m_btSeed2;
-
- b3Scalar restitutionCurve(b3Scalar rel_vel, b3Scalar restitution);
-
- void convertContact(b3RigidBodyData* bodies, b3InertiaData* inertias, b3Contact4* manifold, const b3ContactSolverInfo& infoGlobal);
-
- void resolveSplitPenetrationSIMD(
- b3SolverBody& bodyA, b3SolverBody& bodyB,
- const b3SolverConstraint& contactConstraint);
-
- void resolveSplitPenetrationImpulseCacheFriendly(
- b3SolverBody& bodyA, b3SolverBody& bodyB,
- const b3SolverConstraint& contactConstraint);
-
- //internal method
- int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies, b3InertiaData* inertias);
- void initSolverBody(int bodyIndex, b3SolverBody* solverBody, b3RigidBodyData* collisionObject);
-
- void resolveSingleConstraintRowGeneric(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowGenericSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowLowerLimit(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
-
- void resolveSingleConstraintRowLowerLimitSIMD(b3SolverBody& bodyA, b3SolverBody& bodyB, const b3SolverConstraint& contactConstraint);
-
-protected:
- virtual b3Scalar solveGroupCacheFriendlySetup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
-
- virtual b3Scalar solveGroupCacheFriendlyIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- virtual void solveGroupCacheFriendlySplitImpulseIterations(b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- b3Scalar solveSingleIteration(int iteration, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
-
- virtual b3Scalar solveGroupCacheFriendlyFinish(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, const b3ContactSolverInfo& infoGlobal);
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3PgsJacobiSolver(bool usePgs);
- virtual ~b3PgsJacobiSolver();
-
- // void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts);
- void solveContacts(int numBodies, b3RigidBodyData* bodies, b3InertiaData* inertias, int numContacts, b3Contact4* contacts, int numConstraints, b3TypedConstraint** constraints);
-
- b3Scalar solveGroup(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, b3TypedConstraint** constraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
-
- ///clear internal cached data and reset random seed
- virtual void reset();
-
- unsigned long b3Rand2();
-
- int b3RandInt2(int n);
-
- void setRandSeed(unsigned long seed)
- {
- m_btSeed2 = seed;
- }
- unsigned long getRandSeed() const
- {
- return m_btSeed2;
- }
-};
-
-#endif //B3_PGS_JACOBI_SOLVER
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
deleted file mode 100644
index cfa7c7dd11..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3Point2PointConstraint.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include <new>
-
-b3Point2PointConstraint::b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB)
- : b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0)
-{
-}
-
-/*
-b3Point2PointConstraint::b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA)
-:b3TypedConstraint(B3_POINT2POINT_CONSTRAINT_TYPE,rbA),m_pivotInA(pivotInA),m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)),
-m_flags(0),
-m_useSolveConstraintObsolete(false)
-{
-
-}
-*/
-
-void b3Point2PointConstraint::getInfo1(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
-{
- getInfo1NonVirtual(info, bodies);
-}
-
-void b3Point2PointConstraint::getInfo1NonVirtual(b3ConstraintInfo1* info, const b3RigidBodyData* bodies)
-{
- info->m_numConstraintRows = 3;
- info->nub = 3;
-}
-
-void b3Point2PointConstraint::getInfo2(b3ConstraintInfo2* info, const b3RigidBodyData* bodies)
-{
- b3Transform trA;
- trA.setIdentity();
- trA.setOrigin(bodies[m_rbA].m_pos);
- trA.setRotation(bodies[m_rbA].m_quat);
-
- b3Transform trB;
- trB.setIdentity();
- trB.setOrigin(bodies[m_rbB].m_pos);
- trB.setRotation(bodies[m_rbB].m_quat);
-
- getInfo2NonVirtual(info, trA, trB);
-}
-
-void b3Point2PointConstraint::getInfo2NonVirtual(b3ConstraintInfo2* info, const b3Transform& body0_trans, const b3Transform& body1_trans)
-{
- //retrieve matrices
-
- // anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip + 1] = 1;
- info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
-
- b3Vector3 a1 = body0_trans.getBasis() * getPivotInA();
- //b3Vector3 a1a = b3QuatRotate(body0_trans.getRotation(),getPivotInA());
-
- {
- b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
- b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- if (info->m_J2linearAxis)
- {
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip + 1] = -1;
- info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
- }
-
- b3Vector3 a2 = body1_trans.getBasis() * getPivotInB();
-
- {
- // b3Vector3 a2n = -a2;
- b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- // set right hand side
- b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
- b3Scalar k = info->fps * currERP;
- int j;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
- //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
- if (m_flags & B3_P2P_FLAGS_CFM)
- {
- for (j = 0; j < 3; j++)
- {
- info->cfm[j * info->rowskip] = m_cfm;
- }
- }
-
- b3Scalar impulseClamp = m_setting.m_impulseClamp; //
- for (j = 0; j < 3; j++)
- {
- if (m_setting.m_impulseClamp > 0)
- {
- info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
- info->m_upperLimit[j * info->rowskip] = impulseClamp;
- }
- }
- info->m_damping = m_setting.m_damping;
-}
-
-void b3Point2PointConstraint::updateRHS(b3Scalar timeStep)
-{
- (void)timeStep;
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void b3Point2PointConstraint::setParam(int num, b3Scalar value, int axis)
-{
- if (axis != -1)
- {
- b3AssertConstrParams(0);
- }
- else
- {
- switch (num)
- {
- case B3_CONSTRAINT_ERP:
- case B3_CONSTRAINT_STOP_ERP:
- m_erp = value;
- m_flags |= B3_P2P_FLAGS_ERP;
- break;
- case B3_CONSTRAINT_CFM:
- case B3_CONSTRAINT_STOP_CFM:
- m_cfm = value;
- m_flags |= B3_P2P_FLAGS_CFM;
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
-}
-
-///return the local value of parameter
-b3Scalar b3Point2PointConstraint::getParam(int num, int axis) const
-{
- b3Scalar retVal(B3_INFINITY);
- if (axis != -1)
- {
- b3AssertConstrParams(0);
- }
- else
- {
- switch (num)
- {
- case B3_CONSTRAINT_ERP:
- case B3_CONSTRAINT_STOP_ERP:
- b3AssertConstrParams(m_flags & B3_P2P_FLAGS_ERP);
- retVal = m_erp;
- break;
- case B3_CONSTRAINT_CFM:
- case B3_CONSTRAINT_STOP_CFM:
- b3AssertConstrParams(m_flags & B3_P2P_FLAGS_CFM);
- retVal = m_cfm;
- break;
- default:
- b3AssertConstrParams(0);
- }
- }
- return retVal;
-}
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
deleted file mode 100644
index 14762a3e35..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_POINT2POINTCONSTRAINT_H
-#define B3_POINT2POINTCONSTRAINT_H
-
-#include "Bullet3Common/b3Vector3.h"
-//#include "b3JacobianEntry.h"
-#include "b3TypedConstraint.h"
-
-class b3RigidBody;
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define b3Point2PointConstraintData b3Point2PointConstraintDoubleData
-#define b3Point2PointConstraintDataName "b3Point2PointConstraintDoubleData"
-#else
-#define b3Point2PointConstraintData b3Point2PointConstraintFloatData
-#define b3Point2PointConstraintDataName "b3Point2PointConstraintFloatData"
-#endif //B3_USE_DOUBLE_PRECISION
-
-struct b3ConstraintSetting
-{
- b3ConstraintSetting() : m_tau(b3Scalar(0.3)),
- m_damping(b3Scalar(1.)),
- m_impulseClamp(b3Scalar(0.))
- {
- }
- b3Scalar m_tau;
- b3Scalar m_damping;
- b3Scalar m_impulseClamp;
-};
-
-enum b3Point2PointFlags
-{
- B3_P2P_FLAGS_ERP = 1,
- B3_P2P_FLAGS_CFM = 2
-};
-
-/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
-B3_ATTRIBUTE_ALIGNED16(class)
-b3Point2PointConstraint : public b3TypedConstraint
-{
-#ifdef IN_PARALLELL_SOLVER
-public:
-#endif
-
- b3Vector3 m_pivotInA;
- b3Vector3 m_pivotInB;
-
- int m_flags;
- b3Scalar m_erp;
- b3Scalar m_cfm;
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3ConstraintSetting m_setting;
-
- b3Point2PointConstraint(int rbA, int rbB, const b3Vector3& pivotInA, const b3Vector3& pivotInB);
-
- //b3Point2PointConstraint(int rbA,const b3Vector3& pivotInA);
-
- virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
-
- void getInfo1NonVirtual(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies);
-
- virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies);
-
- void getInfo2NonVirtual(b3ConstraintInfo2 * info, const b3Transform& body0_trans, const b3Transform& body1_trans);
-
- void updateRHS(b3Scalar timeStep);
-
- void setPivotA(const b3Vector3& pivotA)
- {
- m_pivotInA = pivotA;
- }
-
- void setPivotB(const b3Vector3& pivotB)
- {
- m_pivotInB = pivotB;
- }
-
- const b3Vector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- const b3Vector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1);
- ///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const;
-
- // virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- // virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3Point2PointConstraintFloatData
-{
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3FloatData m_pivotInA;
- b3Vector3FloatData m_pivotInB;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3Point2PointConstraintDoubleData
-{
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3DoubleData m_pivotInA;
- b3Vector3DoubleData m_pivotInB;
-};
-
-/*
-B3_FORCE_INLINE int b3Point2PointConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(b3Point2PointConstraintData);
-
-}
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
-B3_FORCE_INLINE const char* b3Point2PointConstraint::serialize(void* dataBuffer, b3Serializer* serializer) const
-{
- b3Point2PointConstraintData* p2pData = (b3Point2PointConstraintData*)dataBuffer;
-
- b3TypedConstraint::serialize(&p2pData->m_typeConstraintData,serializer);
- m_pivotInA.serialize(p2pData->m_pivotInA);
- m_pivotInB.serialize(p2pData->m_pivotInB);
-
- return b3Point2PointConstraintDataName;
-}
-*/
-
-#endif //B3_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
deleted file mode 100644
index 196d0e5793..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverBody.h
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SOLVER_BODY_H
-#define B3_SOLVER_BODY_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Matrix3x3.h"
-
-#include "Bullet3Common/b3AlignedAllocator.h"
-#include "Bullet3Common/b3TransformUtil.h"
-
-///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
-#ifdef B3_USE_SSE
-#define USE_SIMD 1
-#endif //
-
-#ifdef USE_SIMD
-
-struct b3SimdScalar
-{
- B3_FORCE_INLINE b3SimdScalar()
- {
- }
-
- B3_FORCE_INLINE b3SimdScalar(float fl)
- : m_vec128(_mm_set1_ps(fl))
- {
- }
-
- B3_FORCE_INLINE b3SimdScalar(__m128 v128)
- : m_vec128(v128)
- {
- }
- union {
- __m128 m_vec128;
- float m_floats[4];
- float x, y, z, w;
- int m_ints[4];
- b3Scalar m_unusedPadding;
- };
- B3_FORCE_INLINE __m128 get128()
- {
- return m_vec128;
- }
-
- B3_FORCE_INLINE const __m128 get128() const
- {
- return m_vec128;
- }
-
- B3_FORCE_INLINE void set128(__m128 v128)
- {
- m_vec128 = v128;
- }
-
- B3_FORCE_INLINE operator __m128()
- {
- return m_vec128;
- }
- B3_FORCE_INLINE operator const __m128() const
- {
- return m_vec128;
- }
-
- B3_FORCE_INLINE operator float() const
- {
- return m_floats[0];
- }
-};
-
-///@brief Return the elementwise product of two b3SimdScalar
-B3_FORCE_INLINE b3SimdScalar
-operator*(const b3SimdScalar& v1, const b3SimdScalar& v2)
-{
- return b3SimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
-}
-
-///@brief Return the elementwise product of two b3SimdScalar
-B3_FORCE_INLINE b3SimdScalar
-operator+(const b3SimdScalar& v1, const b3SimdScalar& v2)
-{
- return b3SimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
-}
-
-#else
-#define b3SimdScalar b3Scalar
-#endif
-
-///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3SolverBody
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
- b3Transform m_worldTransform;
- b3Vector3 m_deltaLinearVelocity;
- b3Vector3 m_deltaAngularVelocity;
- b3Vector3 m_angularFactor;
- b3Vector3 m_linearFactor;
- b3Vector3 m_invMass;
- b3Vector3 m_pushVelocity;
- b3Vector3 m_turnVelocity;
- b3Vector3 m_linearVelocity;
- b3Vector3 m_angularVelocity;
-
- union {
- void* m_originalBody;
- int m_originalBodyIndex;
- };
-
- int padding[3];
-
- void setWorldTransform(const b3Transform& worldTransform)
- {
- m_worldTransform = worldTransform;
- }
-
- const b3Transform& getWorldTransform() const
- {
- return m_worldTransform;
- }
-
- B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
- {
- if (m_originalBody)
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- else
- velocity.setValue(0, 0, 0);
- }
-
- B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
- {
- if (m_originalBody)
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- else
- angVel.setValue(0, 0, 0);
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- const b3Vector3& getDeltaLinearVelocity() const
- {
- return m_deltaLinearVelocity;
- }
-
- const b3Vector3& getDeltaAngularVelocity() const
- {
- return m_deltaAngularVelocity;
- }
-
- const b3Vector3& getPushVelocity() const
- {
- return m_pushVelocity;
- }
-
- const b3Vector3& getTurnVelocity() const
- {
- return m_turnVelocity;
- }
-
- ////////////////////////////////////////////////
- ///some internal methods, don't use them
-
- b3Vector3& internalGetDeltaLinearVelocity()
- {
- return m_deltaLinearVelocity;
- }
-
- b3Vector3& internalGetDeltaAngularVelocity()
- {
- return m_deltaAngularVelocity;
- }
-
- const b3Vector3& internalGetAngularFactor() const
- {
- return m_angularFactor;
- }
-
- const b3Vector3& internalGetInvMass() const
- {
- return m_invMass;
- }
-
- void internalSetInvMass(const b3Vector3& invMass)
- {
- m_invMass = invMass;
- }
-
- b3Vector3& internalGetPushVelocity()
- {
- return m_pushVelocity;
- }
-
- b3Vector3& internalGetTurnVelocity()
- {
- return m_turnVelocity;
- }
-
- B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
- {
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- }
-
- B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
- {
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
- {
- //if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- void writebackVelocity()
- {
- //if (m_originalBody>=0)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //m_originalBody->setCompanionId(-1);
- }
- }
-
- void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
- {
- (void)timeStep;
- if (m_originalBody)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //correct the position/orientation based on push/turn recovery
- b3Transform newTransform;
- if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
- {
- // b3Quaternion orn = m_worldTransform.getRotation();
- b3TransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
- m_worldTransform = newTransform;
- }
- //m_worldTransform.setRotation(orn);
- //m_originalBody->setCompanionId(-1);
- }
- }
-};
-
-#endif //B3_SOLVER_BODY_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
deleted file mode 100644
index 4927ae4288..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3SolverConstraint.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SOLVER_CONSTRAINT_H
-#define B3_SOLVER_CONSTRAINT_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Matrix3x3.h"
-//#include "b3JacobianEntry.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-//#define NO_FRICTION_TANGENTIALS 1
-#include "b3SolverBody.h"
-
-///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3SolverConstraint
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3Vector3 m_relpos1CrossNormal;
- b3Vector3 m_contactNormal;
-
- b3Vector3 m_relpos2CrossNormal;
- //b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
-
- b3Vector3 m_angularComponentA;
- b3Vector3 m_angularComponentB;
-
- mutable b3SimdScalar m_appliedPushImpulse;
- mutable b3SimdScalar m_appliedImpulse;
- int m_padding1;
- int m_padding2;
- b3Scalar m_friction;
- b3Scalar m_jacDiagABInv;
- b3Scalar m_rhs;
- b3Scalar m_cfm;
-
- b3Scalar m_lowerLimit;
- b3Scalar m_upperLimit;
- b3Scalar m_rhsPenetration;
- union {
- void* m_originalContactPoint;
- b3Scalar m_unusedPadding4;
- };
-
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
- int m_solverBodyIdA;
- int m_solverBodyIdB;
-
- enum b3SolverConstraintType
- {
- B3_SOLVER_CONTACT_1D = 0,
- B3_SOLVER_FRICTION_1D
- };
-};
-
-typedef b3AlignedObjectArray<b3SolverConstraint> b3ConstraintArray;
-
-#endif //B3_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
deleted file mode 100644
index 885e277d8c..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3TypedConstraint.h"
-//#include "Bullet3Common/b3Serializer.h"
-
-#define B3_DEFAULT_DEBUGDRAW_SIZE b3Scalar(0.3f)
-
-b3TypedConstraint::b3TypedConstraint(b3TypedConstraintType type, int rbA, int rbB)
- : b3TypedObject(type),
- m_userConstraintType(-1),
- m_userConstraintPtr((void*)-1),
- m_breakingImpulseThreshold(B3_INFINITY),
- m_isEnabled(true),
- m_needsFeedback(false),
- m_overrideNumSolverIterations(-1),
- m_rbA(rbA),
- m_rbB(rbB),
- m_appliedImpulse(b3Scalar(0.)),
- m_dbgDrawSize(B3_DEFAULT_DEBUGDRAW_SIZE),
- m_jointFeedback(0)
-{
-}
-
-b3Scalar b3TypedConstraint::getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact)
-{
- if (lowLim > uppLim)
- {
- return b3Scalar(1.0f);
- }
- else if (lowLim == uppLim)
- {
- return b3Scalar(0.0f);
- }
- b3Scalar lim_fact = b3Scalar(1.0f);
- b3Scalar delta_max = vel / timeFact;
- if (delta_max < b3Scalar(0.0f))
- {
- if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
- {
- lim_fact = (lowLim - pos) / delta_max;
- }
- else if (pos < lowLim)
- {
- lim_fact = b3Scalar(0.0f);
- }
- else
- {
- lim_fact = b3Scalar(1.0f);
- }
- }
- else if (delta_max > b3Scalar(0.0f))
- {
- if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
- {
- lim_fact = (uppLim - pos) / delta_max;
- }
- else if (pos > uppLim)
- {
- lim_fact = b3Scalar(0.0f);
- }
- else
- {
- lim_fact = b3Scalar(1.0f);
- }
- }
- else
- {
- lim_fact = b3Scalar(0.0f);
- }
- return lim_fact;
-}
-
-void b3AngularLimit::set(b3Scalar low, b3Scalar high, b3Scalar _softness, b3Scalar _biasFactor, b3Scalar _relaxationFactor)
-{
- m_halfRange = (high - low) / 2.0f;
- m_center = b3NormalizeAngle(low + m_halfRange);
- m_softness = _softness;
- m_biasFactor = _biasFactor;
- m_relaxationFactor = _relaxationFactor;
-}
-
-void b3AngularLimit::test(const b3Scalar angle)
-{
- m_correction = 0.0f;
- m_sign = 0.0f;
- m_solveLimit = false;
-
- if (m_halfRange >= 0.0f)
- {
- b3Scalar deviation = b3NormalizeAngle(angle - m_center);
- if (deviation < -m_halfRange)
- {
- m_solveLimit = true;
- m_correction = -(deviation + m_halfRange);
- m_sign = +1.0f;
- }
- else if (deviation > m_halfRange)
- {
- m_solveLimit = true;
- m_correction = m_halfRange - deviation;
- m_sign = -1.0f;
- }
- }
-}
-
-b3Scalar b3AngularLimit::getError() const
-{
- return m_correction * m_sign;
-}
-
-void b3AngularLimit::fit(b3Scalar& angle) const
-{
- if (m_halfRange > 0.0f)
- {
- b3Scalar relativeAngle = b3NormalizeAngle(angle - m_center);
- if (!b3Equal(relativeAngle, m_halfRange))
- {
- if (relativeAngle > 0.0f)
- {
- angle = getHigh();
- }
- else
- {
- angle = getLow();
- }
- }
- }
-}
-
-b3Scalar b3AngularLimit::getLow() const
-{
- return b3NormalizeAngle(m_center - m_halfRange);
-}
-
-b3Scalar b3AngularLimit::getHigh() const
-{
- return b3NormalizeAngle(m_center + m_halfRange);
-}
diff --git a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h b/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
deleted file mode 100644
index f74aec4d3c..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_TYPED_CONSTRAINT_H
-#define B3_TYPED_CONSTRAINT_H
-
-#include "Bullet3Common/b3Scalar.h"
-#include "b3SolverConstraint.h"
-
-class b3Serializer;
-
-//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
-enum b3TypedConstraintType
-{
- B3_POINT2POINT_CONSTRAINT_TYPE = 3,
- B3_HINGE_CONSTRAINT_TYPE,
- B3_CONETWIST_CONSTRAINT_TYPE,
- B3_D6_CONSTRAINT_TYPE,
- B3_SLIDER_CONSTRAINT_TYPE,
- B3_CONTACT_CONSTRAINT_TYPE,
- B3_D6_SPRING_CONSTRAINT_TYPE,
- B3_GEAR_CONSTRAINT_TYPE,
- B3_FIXED_CONSTRAINT_TYPE,
- B3_MAX_CONSTRAINT_TYPE
-};
-
-enum b3ConstraintParams
-{
- B3_CONSTRAINT_ERP = 1,
- B3_CONSTRAINT_STOP_ERP,
- B3_CONSTRAINT_CFM,
- B3_CONSTRAINT_STOP_CFM
-};
-
-#if 1
-#define b3AssertConstrParams(_par) b3Assert(_par)
-#else
-#define b3AssertConstrParams(_par)
-#endif
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3JointFeedback
-{
- b3Vector3 m_appliedForceBodyA;
- b3Vector3 m_appliedTorqueBodyA;
- b3Vector3 m_appliedForceBodyB;
- b3Vector3 m_appliedTorqueBodyB;
-};
-
-struct b3RigidBodyData;
-
-///TypedConstraint is the baseclass for Bullet constraints and vehicles
-B3_ATTRIBUTE_ALIGNED16(class)
-b3TypedConstraint : public b3TypedObject
-{
- int m_userConstraintType;
-
- union {
- int m_userConstraintId;
- void* m_userConstraintPtr;
- };
-
- b3Scalar m_breakingImpulseThreshold;
- bool m_isEnabled;
- bool m_needsFeedback;
- int m_overrideNumSolverIterations;
-
- b3TypedConstraint& operator=(b3TypedConstraint& other)
- {
- b3Assert(0);
- (void)other;
- return *this;
- }
-
-protected:
- int m_rbA;
- int m_rbB;
- b3Scalar m_appliedImpulse;
- b3Scalar m_dbgDrawSize;
- b3JointFeedback* m_jointFeedback;
-
- ///internal method used by the constraint solver, don't use them directly
- b3Scalar getMotorFactor(b3Scalar pos, b3Scalar lowLim, b3Scalar uppLim, b3Scalar vel, b3Scalar timeFact);
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- virtual ~b3TypedConstraint(){};
- b3TypedConstraint(b3TypedConstraintType type, int bodyA, int bodyB);
-
- struct b3ConstraintInfo1
- {
- int m_numConstraintRows, nub;
- };
-
- struct b3ConstraintInfo2
- {
- // integrator parameters: frames per second (1/stepsize), default error
- // reduction parameter (0..1).
- b3Scalar fps, erp;
-
- // for the first and second body, pointers to two (linear and angular)
- // n*3 jacobian sub matrices, stored by rows. these matrices will have
- // been initialized to 0 on entry. if the second body is zero then the
- // J2xx pointers may be 0.
- b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
-
- // elements to jump from one row to the next in J's
- int rowskip;
-
- // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
- // "constraint force mixing" vector. c is set to zero on entry, cfm is
- // set to a constant value (typically very small or zero) value on entry.
- b3Scalar *m_constraintError, *cfm;
-
- // lo and hi limits for variables (set to -/+ infinity on entry).
- b3Scalar *m_lowerLimit, *m_upperLimit;
-
- // findex vector for variables. see the LCP solver interface for a
- // description of what this does. this is set to -1 on entry.
- // note that the returned indexes are relative to the first index of
- // the constraint.
- int* findex;
- // number of solver iterations
- int m_numIterations;
-
- //damping of the velocity
- b3Scalar m_damping;
- };
-
- int getOverrideNumSolverIterations() const
- {
- return m_overrideNumSolverIterations;
- }
-
- ///override the number of constraint solver iterations used to solve this constraint
- ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
- void setOverrideNumSolverIterations(int overideNumIterations)
- {
- m_overrideNumSolverIterations = overideNumIterations;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void setupSolverConstraint(b3ConstraintArray & ca, int solverBodyA, int solverBodyB, b3Scalar timeStep)
- {
- (void)ca;
- (void)solverBodyA;
- (void)solverBodyB;
- (void)timeStep;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1(b3ConstraintInfo1 * info, const b3RigidBodyData* bodies) = 0;
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2(b3ConstraintInfo2 * info, const b3RigidBodyData* bodies) = 0;
-
- ///internal method used by the constraint solver, don't use them directly
- void internalSetAppliedImpulse(b3Scalar appliedImpulse)
- {
- m_appliedImpulse = appliedImpulse;
- }
- ///internal method used by the constraint solver, don't use them directly
- b3Scalar internalGetAppliedImpulse()
- {
- return m_appliedImpulse;
- }
-
- b3Scalar getBreakingImpulseThreshold() const
- {
- return m_breakingImpulseThreshold;
- }
-
- void setBreakingImpulseThreshold(b3Scalar threshold)
- {
- m_breakingImpulseThreshold = threshold;
- }
-
- bool isEnabled() const
- {
- return m_isEnabled;
- }
-
- void setEnabled(bool enabled)
- {
- m_isEnabled = enabled;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void solveConstraintObsolete(b3SolverBody& /*bodyA*/, b3SolverBody& /*bodyB*/, b3Scalar /*timeStep*/){};
-
- int getRigidBodyA() const
- {
- return m_rbA;
- }
- int getRigidBodyB() const
- {
- return m_rbB;
- }
-
- int getRigidBodyA()
- {
- return m_rbA;
- }
- int getRigidBodyB()
- {
- return m_rbB;
- }
-
- int getUserConstraintType() const
- {
- return m_userConstraintType;
- }
-
- void setUserConstraintType(int userConstraintType)
- {
- m_userConstraintType = userConstraintType;
- };
-
- void setUserConstraintId(int uid)
- {
- m_userConstraintId = uid;
- }
-
- int getUserConstraintId() const
- {
- return m_userConstraintId;
- }
-
- void setUserConstraintPtr(void* ptr)
- {
- m_userConstraintPtr = ptr;
- }
-
- void* getUserConstraintPtr()
- {
- return m_userConstraintPtr;
- }
-
- void setJointFeedback(b3JointFeedback * jointFeedback)
- {
- m_jointFeedback = jointFeedback;
- }
-
- const b3JointFeedback* getJointFeedback() const
- {
- return m_jointFeedback;
- }
-
- b3JointFeedback* getJointFeedback()
- {
- return m_jointFeedback;
- }
-
- int getUid() const
- {
- return m_userConstraintId;
- }
-
- bool needsFeedback() const
- {
- return m_needsFeedback;
- }
-
- ///enableFeedback will allow to read the applied linear and angular impulse
- ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
- void enableFeedback(bool needsFeedback)
- {
- m_needsFeedback = needsFeedback;
- }
-
- ///getAppliedImpulse is an estimated total applied impulse.
- ///This feedback could be used to determine breaking constraints or playing sounds.
- b3Scalar getAppliedImpulse() const
- {
- b3Assert(m_needsFeedback);
- return m_appliedImpulse;
- }
-
- b3TypedConstraintType getConstraintType() const
- {
- return b3TypedConstraintType(m_objectType);
- }
-
- void setDbgDrawSize(b3Scalar dbgDrawSize)
- {
- m_dbgDrawSize = dbgDrawSize;
- }
- b3Scalar getDbgDrawSize()
- {
- return m_dbgDrawSize;
- }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, b3Scalar value, int axis = -1) = 0;
-
- ///return the local value of parameter
- virtual b3Scalar getParam(int num, int axis = -1) const = 0;
-
- // virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-};
-
-// returns angle in range [-B3_2_PI, B3_2_PI], closest to one of the limits
-// all arguments should be normalized angles (i.e. in range [-B3_PI, B3_PI])
-B3_FORCE_INLINE b3Scalar b3AdjustAngleToLimits(b3Scalar angleInRadians, b3Scalar angleLowerLimitInRadians, b3Scalar angleUpperLimitInRadians)
-{
- if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
- {
- return angleInRadians;
- }
- else if (angleInRadians < angleLowerLimitInRadians)
- {
- b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleLowerLimitInRadians - angleInRadians));
- b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleUpperLimitInRadians - angleInRadians));
- return (diffLo < diffHi) ? angleInRadians : (angleInRadians + B3_2_PI);
- }
- else if (angleInRadians > angleUpperLimitInRadians)
- {
- b3Scalar diffHi = b3Fabs(b3NormalizeAngle(angleInRadians - angleUpperLimitInRadians));
- b3Scalar diffLo = b3Fabs(b3NormalizeAngle(angleInRadians - angleLowerLimitInRadians));
- return (diffLo < diffHi) ? (angleInRadians - B3_2_PI) : angleInRadians;
- }
- else
- {
- return angleInRadians;
- }
-}
-
-// clang-format off
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3TypedConstraintData
-{
- int m_bodyA;
- int m_bodyB;
- char *m_name;
-
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
-
- float m_appliedImpulse;
- float m_dbgDrawSize;
-
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
-
- float m_breakingImpulseThreshold;
- int m_isEnabled;
-
-};
-
-// clang-format on
-
-/*B3_FORCE_INLINE int b3TypedConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(b3TypedConstraintData);
-}
-*/
-
-class b3AngularLimit
-{
-private:
- b3Scalar
- m_center,
- m_halfRange,
- m_softness,
- m_biasFactor,
- m_relaxationFactor,
- m_correction,
- m_sign;
-
- bool
- m_solveLimit;
-
-public:
- /// Default constructor initializes limit as inactive, allowing free constraint movement
- b3AngularLimit()
- : m_center(0.0f),
- m_halfRange(-1.0f),
- m_softness(0.9f),
- m_biasFactor(0.3f),
- m_relaxationFactor(1.0f),
- m_correction(0.0f),
- m_sign(0.0f),
- m_solveLimit(false)
- {
- }
-
- /// Sets all limit's parameters.
- /// When low > high limit becomes inactive.
- /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
- void set(b3Scalar low, b3Scalar high, b3Scalar _softness = 0.9f, b3Scalar _biasFactor = 0.3f, b3Scalar _relaxationFactor = 1.0f);
-
- /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
- /// correction is calculated.
- void test(const b3Scalar angle);
-
- /// Returns limit's softness
- inline b3Scalar getSoftness() const
- {
- return m_softness;
- }
-
- /// Returns limit's bias factor
- inline b3Scalar getBiasFactor() const
- {
- return m_biasFactor;
- }
-
- /// Returns limit's relaxation factor
- inline b3Scalar getRelaxationFactor() const
- {
- return m_relaxationFactor;
- }
-
- /// Returns correction value evaluated when test() was invoked
- inline b3Scalar getCorrection() const
- {
- return m_correction;
- }
-
- /// Returns sign value evaluated when test() was invoked
- inline b3Scalar getSign() const
- {
- return m_sign;
- }
-
- /// Gives half of the distance between min and max limit angle
- inline b3Scalar getHalfRange() const
- {
- return m_halfRange;
- }
-
- /// Returns true when the last test() invocation recognized limit violation
- inline bool isLimit() const
- {
- return m_solveLimit;
- }
-
- /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
- /// returned is modified so it equals to the limit closest to given angle.
- void fit(b3Scalar& angle) const;
-
- /// Returns correction value multiplied by sign value
- b3Scalar getError() const;
-
- b3Scalar getLow() const;
-
- b3Scalar getHigh() const;
-};
-
-#endif //B3_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
deleted file mode 100644
index f1080d9d5e..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-#include "b3CpuRigidBodyPipeline.h"
-
-#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3CpuNarrowPhase.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
-#include "Bullet3Dynamics/shared/b3Inertia.h"
-
-struct b3CpuRigidBodyPipelineInternalData
-{
- b3AlignedObjectArray<b3RigidBodyData> m_rigidBodies;
- b3AlignedObjectArray<b3Inertia> m_inertias;
- b3AlignedObjectArray<b3Aabb> m_aabbWorldSpace;
-
- b3DynamicBvhBroadphase* m_bp;
- b3CpuNarrowPhase* m_np;
- b3Config m_config;
-};
-
-b3CpuRigidBodyPipeline::b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
-{
- m_data = new b3CpuRigidBodyPipelineInternalData;
- m_data->m_np = narrowphase;
- m_data->m_bp = broadphaseDbvt;
- m_data->m_config = config;
-}
-
-b3CpuRigidBodyPipeline::~b3CpuRigidBodyPipeline()
-{
- delete m_data;
-}
-
-void b3CpuRigidBodyPipeline::updateAabbWorldSpace()
-{
- for (int i = 0; i < this->getNumBodies(); i++)
- {
- b3RigidBodyData* body = &m_data->m_rigidBodies[i];
- b3Float4 position = body->m_pos;
- b3Quat orientation = body->m_quat;
-
- int collidableIndex = body->m_collidableIdx;
- b3Collidable& collidable = m_data->m_np->getCollidableCpu(collidableIndex);
- int shapeIndex = collidable.m_shapeIndex;
-
- if (shapeIndex >= 0)
- {
- b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(shapeIndex);
- b3Aabb& worldAabb = m_data->m_aabbWorldSpace[i];
- float margin = 0.f;
- b3TransformAabb2(localAabb.m_minVec, localAabb.m_maxVec, margin, position, orientation, &worldAabb.m_minVec, &worldAabb.m_maxVec);
- m_data->m_bp->setAabb(i, worldAabb.m_minVec, worldAabb.m_maxVec, 0);
- }
- }
-}
-
-void b3CpuRigidBodyPipeline::computeOverlappingPairs()
-{
- int numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
- m_data->m_bp->calculateOverlappingPairs();
- numPairs = m_data->m_bp->getOverlappingPairCache()->getNumOverlappingPairs();
- printf("numPairs=%d\n", numPairs);
-}
-
-void b3CpuRigidBodyPipeline::computeContactPoints()
-{
- b3AlignedObjectArray<b3Int4>& pairs = m_data->m_bp->getOverlappingPairCache()->getOverlappingPairArray();
-
- m_data->m_np->computeContacts(pairs, m_data->m_aabbWorldSpace, m_data->m_rigidBodies);
-}
-void b3CpuRigidBodyPipeline::stepSimulation(float deltaTime)
-{
- //update world space aabb's
- updateAabbWorldSpace();
-
- //compute overlapping pairs
- computeOverlappingPairs();
-
- //compute contacts
- computeContactPoints();
-
- //solve contacts
-
- //update transforms
- integrate(deltaTime);
-}
-
-static inline float b3CalcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
- const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
-{
- return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
-}
-
-static inline void b3SetLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
- b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
-{
- linear = -n;
- angular0 = -b3Cross(r0, n);
- angular1 = b3Cross(r1, n);
-}
-
-static inline void b3SolveContact(b3ContactConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
-{
- b3Vector3 dLinVelA;
- dLinVelA.setZero();
- b3Vector3 dAngVelA;
- dAngVelA.setZero();
- b3Vector3 dLinVelB;
- dLinVelB.setZero();
- b3Vector3 dAngVelB;
- dAngVelB.setZero();
-
- for (int ic = 0; ic < 4; ic++)
- {
- // dont necessary because this makes change to 0
- if (cs.m_jacCoeffInv[ic] == 0.f) continue;
-
- {
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
- b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- b3SetLinearAndAngular((const b3Vector3&)-cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
-
- float rambdaDt = b3CalcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB) +
- cs.m_b[ic];
- rambdaDt *= cs.m_jacCoeffInv[ic];
-
- {
- float prevSum = cs.m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[ic]);
- updated = b3Min(updated, maxRambdaDt[ic]);
- rambdaDt = updated - prevSum;
- cs.m_appliedRambdaDt[ic] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
- {
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
- }
- }
-}
-
-static inline void b3SolveFriction(b3ContactConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
-{
- if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
- const b3Vector3& center = (const b3Vector3&)cs.m_center;
-
- b3Vector3 n = -(const b3Vector3&)cs.m_linear;
-
- b3Vector3 tangent[2];
-
- b3PlaneSpace1(n, tangent[0], tangent[1]);
-
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = center - posA;
- b3Vector3 r1 = center - posB;
- for (int i = 0; i < 2; i++)
- {
- b3SetLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
- float rambdaDt = b3CalcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
- rambdaDt *= cs.m_fJacCoeffInv[i];
-
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[i]);
- updated = b3Min(updated, maxRambdaDt[i]);
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
-
- { // angular damping for point constraint
- b3Vector3 ab = (posB - posA).normalized();
- b3Vector3 ac = (center - posA).normalized();
- if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = b3Dot(n, angVelA);
- float angNB = b3Dot(n, angVelB);
-
- angVelA -= (angNA * 0.1f) * n;
- angVelB -= (angNB * 0.1f) * n;
- }
- }
-}
-
-struct b3SolveTask // : public ThreadPool::Task
-{
- b3SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies,
- b3AlignedObjectArray<b3Inertia>& shapes,
- b3AlignedObjectArray<b3ContactConstraint4>& constraints,
- int start, int nConstraints,
- int maxNumBatches,
- b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx)
- : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_wgUsedBodies(wgUsedBodies), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
- {
- }
-
- unsigned short int getType() { return 0; }
-
- void run(int tIdx)
- {
- b3AlignedObjectArray<int> usedBodies;
- //printf("run..............\n");
-
- for (int bb = 0; bb < m_maxNumBatches; bb++)
- {
- usedBodies.resize(0);
- for (int ic = m_nConstraints - 1; ic >= 0; ic--)
- //for(int ic=0; ic<m_nConstraints; ic++)
- {
- int i = m_start + ic;
- if (m_constraints[i].m_batchIdx != bb)
- continue;
-
- float frictionCoeff = b3GetFrictionCoeff(&m_constraints[i]);
- int aIdx = (int)m_constraints[i].m_bodyA;
- int bIdx = (int)m_constraints[i].m_bodyB;
- //int localBatch = m_constraints[i].m_batchIdx;
- b3RigidBodyData& bodyA = m_bodies[aIdx];
- b3RigidBodyData& bodyB = m_bodies[bIdx];
-
-#if 0
- if ((bodyA.m_invMass) && (bodyB.m_invMass))
- {
- // printf("aIdx=%d, bIdx=%d\n", aIdx,bIdx);
- }
- if (bIdx==10)
- {
- //printf("ic(b)=%d, localBatch=%d\n",ic,localBatch);
- }
-#endif
- if (aIdx == 10)
- {
- //printf("ic(a)=%d, localBatch=%d\n",ic,localBatch);
- }
- if (usedBodies.size() < (aIdx + 1))
- {
- usedBodies.resize(aIdx + 1, 0);
- }
-
- if (usedBodies.size() < (bIdx + 1))
- {
- usedBodies.resize(bIdx + 1, 0);
- }
-
- if (bodyA.m_invMass)
- {
- b3Assert(usedBodies[aIdx] == 0);
- usedBodies[aIdx]++;
- }
-
- if (bodyB.m_invMass)
- {
- b3Assert(usedBodies[bIdx] == 0);
- usedBodies[bIdx]++;
- }
-
- if (!m_solveFriction)
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
-
- b3SolveContact(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt);
- }
- else
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
-
- float sum = 0;
- for (int j = 0; j < 4; j++)
- {
- sum += m_constraints[i].m_appliedRambdaDt[j];
- }
- frictionCoeff = 0.7f;
- for (int j = 0; j < 4; j++)
- {
- maxRambdaDt[j] = frictionCoeff * sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
-
- b3SolveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt);
- }
- }
-
- if (m_wgUsedBodies)
- {
- if (m_wgUsedBodies[m_curWgidx].size() < usedBodies.size())
- {
- m_wgUsedBodies[m_curWgidx].resize(usedBodies.size());
- }
- for (int i = 0; i < usedBodies.size(); i++)
- {
- if (usedBodies[i])
- {
- //printf("cell %d uses body %d\n", m_curWgidx,i);
- m_wgUsedBodies[m_curWgidx][i] = 1;
- }
- }
- }
- }
- }
-
- b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
- b3AlignedObjectArray<b3Inertia>& m_shapes;
- b3AlignedObjectArray<b3ContactConstraint4>& m_constraints;
- b3AlignedObjectArray<int>* m_wgUsedBodies;
- int m_curWgidx;
- int m_start;
- int m_nConstraints;
- bool m_solveFriction;
- int m_maxNumBatches;
-};
-
-void b3CpuRigidBodyPipeline::solveContactConstraints()
-{
- int m_nIterations = 4;
-
- b3AlignedObjectArray<b3ContactConstraint4> contactConstraints;
- // const b3AlignedObjectArray<b3Contact4Data>& contacts = m_data->m_np->getContacts();
- int n = contactConstraints.size();
- //convert contacts...
-
- int maxNumBatches = 250;
-
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
- task.m_solveFriction = false;
- task.run(0);
- }
-
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- b3SolveTask task(m_data->m_rigidBodies, m_data->m_inertias, contactConstraints, 0, n, maxNumBatches, 0, 0);
- task.m_solveFriction = true;
- task.run(0);
- }
-}
-
-void b3CpuRigidBodyPipeline::integrate(float deltaTime)
-{
- float angDamping = 0.f;
- b3Vector3 gravityAcceleration = b3MakeVector3(0, -9, 0);
-
- //integrate transforms (external forces/gravity should be moved into constraint solver)
- for (int i = 0; i < m_data->m_rigidBodies.size(); i++)
- {
- b3IntegrateTransform(&m_data->m_rigidBodies[i], deltaTime, angDamping, gravityAcceleration);
- }
-}
-
-int b3CpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userData)
-{
- b3RigidBodyData body;
- int bodyIndex = m_data->m_rigidBodies.size();
- body.m_invMass = mass ? 1.f / mass : 0.f;
- body.m_angVel.setValue(0, 0, 0);
- body.m_collidableIdx = collidableIndex;
- body.m_frictionCoeff = 0.3f;
- body.m_linVel.setValue(0, 0, 0);
- body.m_pos.setValue(position[0], position[1], position[2]);
- body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
- body.m_restituitionCoeff = 0.f;
-
- m_data->m_rigidBodies.push_back(body);
-
- if (collidableIndex >= 0)
- {
- b3Aabb& worldAabb = m_data->m_aabbWorldSpace.expand();
-
- b3Aabb localAabb = m_data->m_np->getLocalSpaceAabb(collidableIndex);
- b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
- b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
-
- b3Scalar margin = 0.01f;
- b3Transform t;
- t.setIdentity();
- t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
- t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
- b3TransformAabb(localAabbMin, localAabbMax, margin, t, worldAabb.m_minVec, worldAabb.m_maxVec);
-
- m_data->m_bp->createProxy(worldAabb.m_minVec, worldAabb.m_maxVec, bodyIndex, 0, 1, 1);
- // b3Vector3 aabbMin,aabbMax;
- // m_data->m_bp->getAabb(bodyIndex,aabbMin,aabbMax);
- }
- else
- {
- b3Error("registerPhysicsInstance using invalid collidableIndex\n");
- }
-
- return bodyIndex;
-}
-
-const struct b3RigidBodyData* b3CpuRigidBodyPipeline::getBodyBuffer() const
-{
- return m_data->m_rigidBodies.size() ? &m_data->m_rigidBodies[0] : 0;
-}
-
-int b3CpuRigidBodyPipeline::getNumBodies() const
-{
- return m_data->m_rigidBodies.size();
-}
diff --git a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h b/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
deleted file mode 100644
index 9c65419f26..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/b3CpuRigidBodyPipeline.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_CPU_RIGIDBODY_PIPELINE_H
-#define B3_CPU_RIGIDBODY_PIPELINE_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
-
-class b3CpuRigidBodyPipeline
-{
-protected:
- struct b3CpuRigidBodyPipelineInternalData* m_data;
-
- int allocateCollidable();
-
-public:
- b3CpuRigidBodyPipeline(class b3CpuNarrowPhase* narrowphase, struct b3DynamicBvhBroadphase* broadphaseDbvt, const struct b3Config& config);
- virtual ~b3CpuRigidBodyPipeline();
-
- virtual void stepSimulation(float deltaTime);
- virtual void integrate(float timeStep);
- virtual void updateAabbWorldSpace();
- virtual void computeOverlappingPairs();
- virtual void computeContactPoints();
- virtual void solveContactConstraints();
-
- int registerConvexPolyhedron(class b3ConvexUtility* convex);
-
- int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData);
- void writeAllInstancesToGpu();
- void copyConstraintsToHost();
- void setGravity(const float* grav);
- void reset();
-
- int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
- int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
- void removeConstraintByUid(int uid);
-
- void addConstraint(class b3TypedConstraint* constraint);
- void removeConstraint(b3TypedConstraint* constraint);
-
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
-
- const struct b3RigidBodyData* getBodyBuffer() const;
-
- int getNumBodies() const;
-};
-
-#endif //B3_CPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h
deleted file mode 100644
index cf2eed0e7c..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3ContactConstraint4.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef B3_CONTACT_CONSTRAINT5_H
-#define B3_CONTACT_CONSTRAINT5_H
-
-#include "Bullet3Common/shared/b3Float4.h"
-
-typedef struct b3ContactConstraint4 b3ContactConstraint4_t;
-
-struct b3ContactConstraint4
-{
- b3Float4 m_linear; //normal?
- b3Float4 m_worldPos[4];
- b3Float4 m_center; // friction
- float m_jacCoeffInv[4];
- float m_b[4];
- float m_appliedRambdaDt[4];
- float m_fJacCoeffInv[2]; // friction
- float m_fAppliedRambdaDt[2]; // friction
-
- unsigned int m_bodyA;
- unsigned int m_bodyB;
- int m_batchIdx;
- unsigned int m_paddings;
-};
-
-//inline void setFrictionCoeff(float value) { m_linear[3] = value; }
-inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint)
-{
- return constraint->m_linear.w;
-}
-
-#endif //B3_CONTACT_CONSTRAINT5_H
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h
deleted file mode 100644
index 3e72f1c3f2..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3ConvertConstraint4.h
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q);
-void b3PlaneSpace1(b3Float4ConstArg n, b3Float4* p, b3Float4* q)
-{
- if (b3Fabs(n.z) > 0.70710678f)
- {
- // choose p in y-z plane
- float a = n.y * n.y + n.z * n.z;
- float k = 1.f / sqrt(a);
- p[0].x = 0;
- p[0].y = -n.z * k;
- p[0].z = n.y * k;
- // set q = n x p
- q[0].x = a * k;
- q[0].y = -n.x * p[0].z;
- q[0].z = n.x * p[0].y;
- }
- else
- {
- // choose p in x-y plane
- float a = n.x * n.x + n.y * n.y;
- float k = 1.f / sqrt(a);
- p[0].x = -n.y * k;
- p[0].y = n.x * k;
- p[0].z = 0;
- // set q = n x p
- q[0].x = -n.z * p[0].y;
- q[0].y = n.z * p[0].x;
- q[0].z = a * k;
- }
-}
-
-void setLinearAndAngular(b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)
-{
- *linear = b3MakeFloat4(n.x, n.y, n.z, 0.f);
- *angular0 = b3Cross3(r0, n);
- *angular1 = -b3Cross3(r1, n);
-}
-
-float calcRelVel(b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,
- b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1)
-{
- return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);
-}
-
-float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,
- float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)
-{
- // linear0,1 are normlized
- float jmj0 = invMass0; //b3Dot3F4(linear0, linear0)*invMass0;
- float jmj1 = b3Dot3F4(mtMul3(angular0, *invInertia0), angular0);
- float jmj2 = invMass1; //b3Dot3F4(linear1, linear1)*invMass1;
- float jmj3 = b3Dot3F4(mtMul3(angular1, *invInertia1), angular1);
- return -1.f / (jmj0 + jmj1 + jmj2 + jmj3);
-}
-
-void setConstraint4(b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,
- b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB,
- __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,
- b3ContactConstraint4_t* dstC)
-{
- dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
- dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
-
- float dtInv = 1.f / dt;
- for (int ic = 0; ic < 4; ic++)
- {
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
-
- dstC->m_linear = src->m_worldNormalOnB;
- dstC->m_linear.w = 0.7f; //src->getFrictionCoeff() );
- for (int ic = 0; ic < 4; ic++)
- {
- b3Float4 r0 = src->m_worldPosB[ic] - posA;
- b3Float4 r1 = src->m_worldPosB[ic] - posB;
-
- if (ic >= src->m_worldNormalOnB.w) //npoints
- {
- dstC->m_jacCoeffInv[ic] = 0.f;
- continue;
- }
-
- float relVelN;
- {
- b3Float4 linear, angular0, angular1;
- setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
-
- dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB);
-
- relVelN = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
-
- float e = 0.f; //src->getRestituitionCoeff();
- if (relVelN * relVelN < 0.004f) e = 0.f;
-
- dstC->m_b[ic] = e * relVelN;
- //float penetration = src->m_worldPosB[ic].w;
- dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift) * positionConstraintCoeff * dtInv;
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- }
-
- if (src->m_worldNormalOnB.w > 0) //npoints
- { // prepare friction
- b3Float4 center = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
- for (int i = 0; i < src->m_worldNormalOnB.w; i++)
- center += src->m_worldPosB[i];
- center /= (float)src->m_worldNormalOnB.w;
-
- b3Float4 tangent[2];
- b3PlaneSpace1(src->m_worldNormalOnB, &tangent[0], &tangent[1]);
-
- b3Float4 r[2];
- r[0] = center - posA;
- r[1] = center - posB;
-
- for (int i = 0; i < 2; i++)
- {
- b3Float4 linear, angular0, angular1;
- setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
-
- dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB);
- dstC->m_fAppliedRambdaDt[i] = 0.f;
- }
- dstC->m_center = center;
- }
-
- for (int i = 0; i < 4; i++)
- {
- if (i < src->m_worldNormalOnB.w)
- {
- dstC->m_worldPos[i] = src->m_worldPosB[i];
- }
- else
- {
- dstC->m_worldPos[i] = b3MakeFloat4(0.f, 0.f, 0.f, 0.f);
- }
- }
-}
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h
deleted file mode 100644
index 602a1335aa..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3Inertia.h
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-#ifndef B3_INERTIA_H
-#define B3_INERTIA_H
-
-#include "Bullet3Common/shared/b3Mat3x3.h"
-
-struct b3Inertia
-{
- b3Mat3x3 m_invInertiaWorld;
- b3Mat3x3 m_initInvInertia;
-};
-
-#endif //B3_INERTIA_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h b/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h
deleted file mode 100644
index 56d9118f95..0000000000
--- a/thirdparty/bullet/Bullet3Dynamics/shared/b3IntegrateTransforms.h
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-inline void integrateSingleTransform(__global b3RigidBodyData_t* bodies, int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
-{
- if (bodies[nodeID].m_invMass != 0.f)
- {
- float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
-
- //angular velocity
- {
- b3Float4 axis;
- //add some hardcoded angular damping
- bodies[nodeID].m_angVel.x *= angularDamping;
- bodies[nodeID].m_angVel.y *= angularDamping;
- bodies[nodeID].m_angVel.z *= angularDamping;
-
- b3Float4 angvel = bodies[nodeID].m_angVel;
-
- float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
-
- //limit the angular motion
- if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
- }
- if (fAngle < 0.001f)
- {
- // use Taylor's expansions of sync function
- axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
- }
-
- b3Quat dorn;
- dorn.x = axis.x;
- dorn.y = axis.y;
- dorn.z = axis.z;
- dorn.w = b3Cos(fAngle * timeStep * 0.5f);
- b3Quat orn0 = bodies[nodeID].m_quat;
- b3Quat predictedOrn = b3QuatMul(dorn, orn0);
- predictedOrn = b3QuatNormalized(predictedOrn);
- bodies[nodeID].m_quat = predictedOrn;
- }
- //linear velocity
- bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;
-
- //apply gravity
- bodies[nodeID].m_linVel += gravityAcceleration * timeStep;
- }
-}
-
-inline void b3IntegrateTransform(__global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)
-{
- float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);
-
- if ((body->m_invMass != 0.f))
- {
- //angular velocity
- {
- b3Float4 axis;
- //add some hardcoded angular damping
- body->m_angVel.x *= angularDamping;
- body->m_angVel.y *= angularDamping;
- body->m_angVel.z *= angularDamping;
-
- b3Float4 angvel = body->m_angVel;
- float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));
- //limit the angular motion
- if (fAngle * timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;
- }
- if (fAngle < 0.001f)
- {
- // use Taylor's expansions of sync function
- axis = angvel * (0.5f * timeStep - (timeStep * timeStep * timeStep) * 0.020833333333f * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (b3Sin(0.5f * fAngle * timeStep) / fAngle);
- }
- b3Quat dorn;
- dorn.x = axis.x;
- dorn.y = axis.y;
- dorn.z = axis.z;
- dorn.w = b3Cos(fAngle * timeStep * 0.5f);
- b3Quat orn0 = body->m_quat;
-
- b3Quat predictedOrn = b3QuatMul(dorn, orn0);
- predictedOrn = b3QuatNormalized(predictedOrn);
- body->m_quat = predictedOrn;
- }
-
- //apply gravity
- body->m_linVel += gravityAcceleration * timeStep;
-
- //linear velocity
- body->m_pos += body->m_linVel * timeStep;
- }
-}
diff --git a/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h b/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h
deleted file mode 100644
index 396a401450..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3AabbUtil.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_AABB_UTIL2
-#define B3_AABB_UTIL2
-
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3MinMax.h"
-
-B3_FORCE_INLINE void b3AabbExpand(b3Vector3& aabbMin,
- b3Vector3& aabbMax,
- const b3Vector3& expansionMin,
- const b3Vector3& expansionMax)
-{
- aabbMin = aabbMin + expansionMin;
- aabbMax = aabbMax + expansionMax;
-}
-
-/// conservative test for overlap between two aabbs
-B3_FORCE_INLINE bool b3TestPointAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
- const b3Vector3& point)
-{
- bool overlap = true;
- overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
- overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
- overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
- return overlap;
-}
-
-/// conservative test for overlap between two aabbs
-B3_FORCE_INLINE bool b3TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
- const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
- overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
- overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
- return overlap;
-}
-
-/// conservative test for overlap between triangle and aabb
-B3_FORCE_INLINE bool b3TestTriangleAgainstAabb2(const b3Vector3* vertices,
- const b3Vector3& aabbMin, const b3Vector3& aabbMax)
-{
- const b3Vector3& p1 = vertices[0];
- const b3Vector3& p2 = vertices[1];
- const b3Vector3& p3 = vertices[2];
-
- if (b3Min(b3Min(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
- if (b3Max(b3Max(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
-
- if (b3Min(b3Min(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
- if (b3Max(b3Max(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
-
- if (b3Min(b3Min(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
- if (b3Max(b3Max(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
- return true;
-}
-
-B3_FORCE_INLINE int b3Outcode(const b3Vector3& p, const b3Vector3& halfExtent)
-{
- return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
- (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
- (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
- (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
- (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
- (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
-}
-
-B3_FORCE_INLINE bool b3RayAabb2(const b3Vector3& rayFrom,
- const b3Vector3& rayInvDirection,
- const unsigned int raySign[3],
- const b3Vector3 bounds[2],
- b3Scalar& tmin,
- b3Scalar lambda_min,
- b3Scalar lambda_max)
-{
- b3Scalar tmax, tymin, tymax, tzmin, tzmax;
- tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
-
- if ((tmin > tymax) || (tymin > tmax))
- return false;
-
- if (tymin > tmin)
- tmin = tymin;
-
- if (tymax < tmax)
- tmax = tymax;
-
- tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
-
- if ((tmin > tzmax) || (tzmin > tmax))
- return false;
- if (tzmin > tmin)
- tmin = tzmin;
- if (tzmax < tmax)
- tmax = tzmax;
- return ((tmin < lambda_max) && (tmax > lambda_min));
-}
-
-B3_FORCE_INLINE bool b3RayAabb(const b3Vector3& rayFrom,
- const b3Vector3& rayTo,
- const b3Vector3& aabbMin,
- const b3Vector3& aabbMax,
- b3Scalar& param, b3Vector3& normal)
-{
- b3Vector3 aabbHalfExtent = (aabbMax - aabbMin) * b3Scalar(0.5);
- b3Vector3 aabbCenter = (aabbMax + aabbMin) * b3Scalar(0.5);
- b3Vector3 source = rayFrom - aabbCenter;
- b3Vector3 target = rayTo - aabbCenter;
- int sourceOutcode = b3Outcode(source, aabbHalfExtent);
- int targetOutcode = b3Outcode(target, aabbHalfExtent);
- if ((sourceOutcode & targetOutcode) == 0x0)
- {
- b3Scalar lambda_enter = b3Scalar(0.0);
- b3Scalar lambda_exit = param;
- b3Vector3 r = target - source;
- int i;
- b3Scalar normSign = 1;
- b3Vector3 hitNormal = b3MakeVector3(0, 0, 0);
- int bit = 1;
-
- for (int j = 0; j < 2; j++)
- {
- for (i = 0; i != 3; ++i)
- {
- if (sourceOutcode & bit)
- {
- b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
- if (lambda_enter <= lambda)
- {
- lambda_enter = lambda;
- hitNormal.setValue(0, 0, 0);
- hitNormal[i] = normSign;
- }
- }
- else if (targetOutcode & bit)
- {
- b3Scalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
- b3SetMin(lambda_exit, lambda);
- }
- bit <<= 1;
- }
- normSign = b3Scalar(-1.);
- }
- if (lambda_enter <= lambda_exit)
- {
- param = lambda_enter;
- normal = hitNormal;
- return true;
- }
- }
- return false;
-}
-
-B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& halfExtents, b3Scalar margin, const b3Transform& t, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
-{
- b3Vector3 halfExtentsWithMargin = halfExtents + b3MakeVector3(margin, margin, margin);
- b3Matrix3x3 abs_b = t.getBasis().absolute();
- b3Vector3 center = t.getOrigin();
- b3Vector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMinOut = center - extent;
- aabbMaxOut = center + extent;
-}
-
-B3_FORCE_INLINE void b3TransformAabb(const b3Vector3& localAabbMin, const b3Vector3& localAabbMax, b3Scalar margin, const b3Transform& trans, b3Vector3& aabbMinOut, b3Vector3& aabbMaxOut)
-{
- //b3Assert(localAabbMin.getX() <= localAabbMax.getX());
- //b3Assert(localAabbMin.getY() <= localAabbMax.getY());
- //b3Assert(localAabbMin.getZ() <= localAabbMax.getZ());
- b3Vector3 localHalfExtents = b3Scalar(0.5) * (localAabbMax - localAabbMin);
- localHalfExtents += b3MakeVector3(margin, margin, margin);
-
- b3Vector3 localCenter = b3Scalar(0.5) * (localAabbMax + localAabbMin);
- b3Matrix3x3 abs_b = trans.getBasis().absolute();
- b3Vector3 center = trans(localCenter);
- b3Vector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMinOut = center - extent;
- aabbMaxOut = center + extent;
-}
-
-#define B3_USE_BANCHLESS 1
-#ifdef B3_USE_BANCHLESS
-//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
-B3_FORCE_INLINE unsigned b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
-{
- return static_cast<unsigned int>(b3Select((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
- 1, 0));
-}
-#else
-B3_FORCE_INLINE bool b3TestQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
- overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
- overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
- return overlap;
-}
-#endif //B3_USE_BANCHLESS
-
-#endif //B3_AABB_UTIL2
diff --git a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp
deleted file mode 100644
index b37652456e..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.cpp
+++ /dev/null
@@ -1,2745 +0,0 @@
-/*
-Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include <string.h>
-
-#include "b3ConvexHullComputer.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3MinMax.h"
-#include "Bullet3Common/b3Vector3.h"
-
-#ifdef __GNUC__
-#include <stdint.h>
-typedef int32_t btInt32_t;
-typedef int64_t btInt64_t;
-typedef uint32_t btUint32_t;
-typedef uint64_t btUint64_t;
-#elif defined(_MSC_VER)
-typedef __int32 btInt32_t;
-typedef __int64 btInt64_t;
-typedef unsigned __int32 btUint32_t;
-typedef unsigned __int64 btUint64_t;
-#else
-typedef int btInt32_t;
-typedef long long int btInt64_t;
-typedef unsigned int btUint32_t;
-typedef unsigned long long int btUint64_t;
-#endif
-
-//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
-//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
-// #define USE_X86_64_ASM
-//#endif
-
-//#define DEBUG_CONVEX_HULL
-//#define SHOW_ITERATIONS
-
-#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
-#include <stdio.h>
-#endif
-
-// Convex hull implementation based on Preparata and Hong
-// Ole Kniemeyer, MAXON Computer GmbH
-class b3ConvexHullInternal
-{
-public:
- class Point64
- {
- public:
- btInt64_t x;
- btInt64_t y;
- btInt64_t z;
-
- Point64(btInt64_t x, btInt64_t y, btInt64_t z) : x(x), y(y), z(z)
- {
- }
-
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
-
- btInt64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
- };
-
- class Point32
- {
- public:
- btInt32_t x;
- btInt32_t y;
- btInt32_t z;
- int index;
-
- Point32()
- {
- }
-
- Point32(btInt32_t x, btInt32_t y, btInt32_t z) : x(x), y(y), z(z), index(-1)
- {
- }
-
- bool operator==(const Point32& b) const
- {
- return (x == b.x) && (y == b.y) && (z == b.z);
- }
-
- bool operator!=(const Point32& b) const
- {
- return (x != b.x) || (y != b.y) || (z != b.z);
- }
-
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
-
- Point64 cross(const Point32& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
-
- Point64 cross(const Point64& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
-
- btInt64_t dot(const Point32& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
-
- btInt64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
-
- Point32 operator+(const Point32& b) const
- {
- return Point32(x + b.x, y + b.y, z + b.z);
- }
-
- Point32 operator-(const Point32& b) const
- {
- return Point32(x - b.x, y - b.y, z - b.z);
- }
- };
-
- class Int128
- {
- public:
- btUint64_t low;
- btUint64_t high;
-
- Int128()
- {
- }
-
- Int128(btUint64_t low, btUint64_t high) : low(low), high(high)
- {
- }
-
- Int128(btUint64_t low) : low(low), high(0)
- {
- }
-
- Int128(btInt64_t value) : low(value), high((value >= 0) ? 0 : (btUint64_t)-1LL)
- {
- }
-
- static Int128 mul(btInt64_t a, btInt64_t b);
-
- static Int128 mul(btUint64_t a, btUint64_t b);
-
- Int128 operator-() const
- {
- return Int128((btUint64_t) - (btInt64_t)low, ~high + (low == 0));
- }
-
- Int128 operator+(const Int128& b) const
- {
-#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__(
- "addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r"(result.low), [rh] "=r"(result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
- return result;
-#else
- btUint64_t lo = low + b.low;
- return Int128(lo, high + b.high + (lo < low));
-#endif
- }
-
- Int128 operator-(const Int128& b) const
- {
-#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__(
- "subq %[bl], %[rl]\n\t"
- "sbbq %[bh], %[rh]\n\t"
- : [rl] "=r"(result.low), [rh] "=r"(result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
- return result;
-#else
- return *this + -b;
-#endif
- }
-
- Int128& operator+=(const Int128& b)
- {
-#ifdef USE_X86_64_ASM
- __asm__(
- "addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r"(low), [rh] "=r"(high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
-#else
- btUint64_t lo = low + b.low;
- if (lo < low)
- {
- ++high;
- }
- low = lo;
- high += b.high;
-#endif
- return *this;
- }
-
- Int128& operator++()
- {
- if (++low == 0)
- {
- ++high;
- }
- return *this;
- }
-
- Int128 operator*(btInt64_t b) const;
-
- b3Scalar toScalar() const
- {
- return ((btInt64_t)high >= 0) ? b3Scalar(high) * (b3Scalar(0x100000000LL) * b3Scalar(0x100000000LL)) + b3Scalar(low)
- : -(-*this).toScalar();
- }
-
- int getSign() const
- {
- return ((btInt64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
- }
-
- bool operator<(const Int128& b) const
- {
- return (high < b.high) || ((high == b.high) && (low < b.low));
- }
-
- int ucmp(const Int128& b) const
- {
- if (high < b.high)
- {
- return -1;
- }
- if (high > b.high)
- {
- return 1;
- }
- if (low < b.low)
- {
- return -1;
- }
- if (low > b.low)
- {
- return 1;
- }
- return 0;
- }
- };
-
- class Rational64
- {
- private:
- btUint64_t m_numerator;
- btUint64_t m_denominator;
- int sign;
-
- public:
- Rational64(btInt64_t numerator, btInt64_t denominator)
- {
- if (numerator > 0)
- {
- sign = 1;
- m_numerator = (btUint64_t)numerator;
- }
- else if (numerator < 0)
- {
- sign = -1;
- m_numerator = (btUint64_t)-numerator;
- }
- else
- {
- sign = 0;
- m_numerator = 0;
- }
- if (denominator > 0)
- {
- m_denominator = (btUint64_t)denominator;
- }
- else if (denominator < 0)
- {
- sign = -sign;
- m_denominator = (btUint64_t)-denominator;
- }
- else
- {
- m_denominator = 0;
- }
- }
-
- bool isNegativeInfinity() const
- {
- return (sign < 0) && (m_denominator == 0);
- }
-
- bool isNaN() const
- {
- return (sign == 0) && (m_denominator == 0);
- }
-
- int compare(const Rational64& b) const;
-
- b3Scalar toScalar() const
- {
- return sign * ((m_denominator == 0) ? B3_INFINITY : (b3Scalar)m_numerator / m_denominator);
- }
- };
-
- class Rational128
- {
- private:
- Int128 numerator;
- Int128 denominator;
- int sign;
- bool isInt64;
-
- public:
- Rational128(btInt64_t value)
- {
- if (value > 0)
- {
- sign = 1;
- this->numerator = value;
- }
- else if (value < 0)
- {
- sign = -1;
- this->numerator = -value;
- }
- else
- {
- sign = 0;
- this->numerator = (btUint64_t)0;
- }
- this->denominator = (btUint64_t)1;
- isInt64 = true;
- }
-
- Rational128(const Int128& numerator, const Int128& denominator)
- {
- sign = numerator.getSign();
- if (sign >= 0)
- {
- this->numerator = numerator;
- }
- else
- {
- this->numerator = -numerator;
- }
- int dsign = denominator.getSign();
- if (dsign >= 0)
- {
- this->denominator = denominator;
- }
- else
- {
- sign = -sign;
- this->denominator = -denominator;
- }
- isInt64 = false;
- }
-
- int compare(const Rational128& b) const;
-
- int compare(btInt64_t b) const;
-
- b3Scalar toScalar() const
- {
- return sign * ((denominator.getSign() == 0) ? B3_INFINITY : numerator.toScalar() / denominator.toScalar());
- }
- };
-
- class PointR128
- {
- public:
- Int128 x;
- Int128 y;
- Int128 z;
- Int128 denominator;
-
- PointR128()
- {
- }
-
- PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
- {
- }
-
- b3Scalar xvalue() const
- {
- return x.toScalar() / denominator.toScalar();
- }
-
- b3Scalar yvalue() const
- {
- return y.toScalar() / denominator.toScalar();
- }
-
- b3Scalar zvalue() const
- {
- return z.toScalar() / denominator.toScalar();
- }
- };
-
- class Edge;
- class Face;
-
- class Vertex
- {
- public:
- Vertex* next;
- Vertex* prev;
- Edge* edges;
- Face* firstNearbyFace;
- Face* lastNearbyFace;
- PointR128 point128;
- Point32 point;
- int copy;
-
- Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
- {
- }
-
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- b3Printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
- }
-
- void printGraph();
-#endif
-
- Point32 operator-(const Vertex& b) const
- {
- return point - b.point;
- }
-
- Rational128 dot(const Point64& b) const
- {
- return (point.index >= 0) ? Rational128(point.dot(b))
- : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
- }
-
- b3Scalar xvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.x) : point128.xvalue();
- }
-
- b3Scalar yvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.y) : point128.yvalue();
- }
-
- b3Scalar zvalue() const
- {
- return (point.index >= 0) ? b3Scalar(point.z) : point128.zvalue();
- }
-
- void receiveNearbyFaces(Vertex* src)
- {
- if (lastNearbyFace)
- {
- lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
- }
- else
- {
- firstNearbyFace = src->firstNearbyFace;
- }
- if (src->lastNearbyFace)
- {
- lastNearbyFace = src->lastNearbyFace;
- }
- for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
- {
- b3Assert(f->nearbyVertex == src);
- f->nearbyVertex = this;
- }
- src->firstNearbyFace = NULL;
- src->lastNearbyFace = NULL;
- }
- };
-
- class Edge
- {
- public:
- Edge* next;
- Edge* prev;
- Edge* reverse;
- Vertex* target;
- Face* face;
- int copy;
-
- ~Edge()
- {
- next = NULL;
- prev = NULL;
- reverse = NULL;
- target = NULL;
- face = NULL;
- }
-
- void link(Edge* n)
- {
- b3Assert(reverse->target == n->reverse->target);
- next = n;
- n->prev = this;
- }
-
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- b3Printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
- reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
- }
-#endif
- };
-
- class Face
- {
- public:
- Face* next;
- Vertex* nearbyVertex;
- Face* nextWithSameNearbyVertex;
- Point32 origin;
- Point32 dir0;
- Point32 dir1;
-
- Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
- {
- }
-
- void init(Vertex* a, Vertex* b, Vertex* c)
- {
- nearbyVertex = a;
- origin = a->point;
- dir0 = *b - *a;
- dir1 = *c - *a;
- if (a->lastNearbyFace)
- {
- a->lastNearbyFace->nextWithSameNearbyVertex = this;
- }
- else
- {
- a->firstNearbyFace = this;
- }
- a->lastNearbyFace = this;
- }
-
- Point64 getNormal()
- {
- return dir0.cross(dir1);
- }
- };
-
- template <typename UWord, typename UHWord>
- class DMul
- {
- private:
- static btUint32_t high(btUint64_t value)
- {
- return (btUint32_t)(value >> 32);
- }
-
- static btUint32_t low(btUint64_t value)
- {
- return (btUint32_t)value;
- }
-
- static btUint64_t mul(btUint32_t a, btUint32_t b)
- {
- return (btUint64_t)a * (btUint64_t)b;
- }
-
- static void shlHalf(btUint64_t& value)
- {
- value <<= 32;
- }
-
- static btUint64_t high(Int128 value)
- {
- return value.high;
- }
-
- static btUint64_t low(Int128 value)
- {
- return value.low;
- }
-
- static Int128 mul(btUint64_t a, btUint64_t b)
- {
- return Int128::mul(a, b);
- }
-
- static void shlHalf(Int128& value)
- {
- value.high = value.low;
- value.low = 0;
- }
-
- public:
- static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
- {
- UWord p00 = mul(low(a), low(b));
- UWord p01 = mul(low(a), high(b));
- UWord p10 = mul(high(a), low(b));
- UWord p11 = mul(high(a), high(b));
- UWord p0110 = UWord(low(p01)) + UWord(low(p10));
- p11 += high(p01);
- p11 += high(p10);
- p11 += high(p0110);
- shlHalf(p0110);
- p00 += p0110;
- if (p00 < p0110)
- {
- ++p11;
- }
- resLow = p00;
- resHigh = p11;
- }
- };
-
-private:
- class IntermediateHull
- {
- public:
- Vertex* minXy;
- Vertex* maxXy;
- Vertex* minYx;
- Vertex* maxYx;
-
- IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
- {
- }
-
- void print();
- };
-
- enum Orientation
- {
- NONE,
- CLOCKWISE,
- COUNTER_CLOCKWISE
- };
-
- template <typename T>
- class PoolArray
- {
- private:
- T* array;
- int size;
-
- public:
- PoolArray<T>* next;
-
- PoolArray(int size) : size(size), next(NULL)
- {
- array = (T*)b3AlignedAlloc(sizeof(T) * size, 16);
- }
-
- ~PoolArray()
- {
- b3AlignedFree(array);
- }
-
- T* init()
- {
- T* o = array;
- for (int i = 0; i < size; i++, o++)
- {
- o->next = (i + 1 < size) ? o + 1 : NULL;
- }
- return array;
- }
- };
-
- template <typename T>
- class Pool
- {
- private:
- PoolArray<T>* arrays;
- PoolArray<T>* nextArray;
- T* freeObjects;
- int arraySize;
-
- public:
- Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
- {
- }
-
- ~Pool()
- {
- while (arrays)
- {
- PoolArray<T>* p = arrays;
- arrays = p->next;
- p->~PoolArray<T>();
- b3AlignedFree(p);
- }
- }
-
- void reset()
- {
- nextArray = arrays;
- freeObjects = NULL;
- }
-
- void setArraySize(int arraySize)
- {
- this->arraySize = arraySize;
- }
-
- T* newObject()
- {
- T* o = freeObjects;
- if (!o)
- {
- PoolArray<T>* p = nextArray;
- if (p)
- {
- nextArray = p->next;
- }
- else
- {
- p = new (b3AlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
- p->next = arrays;
- arrays = p;
- }
- o = p->init();
- }
- freeObjects = o->next;
- return new (o) T();
- };
-
- void freeObject(T* object)
- {
- object->~T();
- object->next = freeObjects;
- freeObjects = object;
- }
- };
-
- b3Vector3 scaling;
- b3Vector3 center;
- Pool<Vertex> vertexPool;
- Pool<Edge> edgePool;
- Pool<Face> facePool;
- b3AlignedObjectArray<Vertex*> originalVertices;
- int mergeStamp;
- int minAxis;
- int medAxis;
- int maxAxis;
- int usedEdgePairs;
- int maxUsedEdgePairs;
-
- static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
- Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
- void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
-
- Edge* newEdgePair(Vertex* from, Vertex* to);
-
- void removeEdgePair(Edge* edge)
- {
- Edge* n = edge->next;
- Edge* r = edge->reverse;
-
- b3Assert(edge->target && r->target);
-
- if (n != edge)
- {
- n->prev = edge->prev;
- edge->prev->next = n;
- r->target->edges = n;
- }
- else
- {
- r->target->edges = NULL;
- }
-
- n = r->next;
-
- if (n != r)
- {
- n->prev = r->prev;
- r->prev->next = n;
- edge->target->edges = n;
- }
- else
- {
- edge->target->edges = NULL;
- }
-
- edgePool.freeObject(edge);
- edgePool.freeObject(r);
- usedEdgePairs--;
- }
-
- void computeInternal(int start, int end, IntermediateHull& result);
-
- bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
-
- void merge(IntermediateHull& h0, IntermediateHull& h1);
-
- b3Vector3 toBtVector(const Point32& v);
-
- b3Vector3 getBtNormal(Face* face);
-
- bool shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack);
-
-public:
- Vertex* vertexList;
-
- void compute(const void* coords, bool doubleCoords, int stride, int count);
-
- b3Vector3 getCoordinates(const Vertex* v);
-
- b3Scalar shrink(b3Scalar amount, b3Scalar clampAmount);
-};
-
-b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::operator*(btInt64_t b) const
-{
- bool negative = (btInt64_t)high < 0;
- Int128 a = negative ? -*this : *this;
- if (b < 0)
- {
- negative = !negative;
- b = -b;
- }
- Int128 result = mul(a.low, (btUint64_t)b);
- result.high += a.high * (btUint64_t)b;
- return negative ? -result : result;
-}
-
-b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btInt64_t a, btInt64_t b)
-{
- Int128 result;
-
-#ifdef USE_X86_64_ASM
- __asm__("imulq %[b]"
- : "=a"(result.low), "=d"(result.high)
- : "0"(a), [b] "r"(b)
- : "cc");
- return result;
-
-#else
- bool negative = a < 0;
- if (negative)
- {
- a = -a;
- }
- if (b < 0)
- {
- negative = !negative;
- b = -b;
- }
- DMul<btUint64_t, btUint32_t>::mul((btUint64_t)a, (btUint64_t)b, result.low, result.high);
- return negative ? -result : result;
-#endif
-}
-
-b3ConvexHullInternal::Int128 b3ConvexHullInternal::Int128::mul(btUint64_t a, btUint64_t b)
-{
- Int128 result;
-
-#ifdef USE_X86_64_ASM
- __asm__("mulq %[b]"
- : "=a"(result.low), "=d"(result.high)
- : "0"(a), [b] "r"(b)
- : "cc");
-
-#else
- DMul<btUint64_t, btUint32_t>::mul(a, b, result.low, result.high);
-#endif
-
- return result;
-}
-
-int b3ConvexHullInternal::Rational64::compare(const Rational64& b) const
-{
- if (sign != b.sign)
- {
- return sign - b.sign;
- }
- else if (sign == 0)
- {
- return 0;
- }
-
- // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
-
-#ifdef USE_X86_64_ASM
-
- int result;
- btInt64_t tmp;
- btInt64_t dummy;
- __asm__(
- "mulq %[bn]\n\t"
- "movq %%rax, %[tmp]\n\t"
- "movq %%rdx, %%rbx\n\t"
- "movq %[tn], %%rax\n\t"
- "mulq %[bd]\n\t"
- "subq %[tmp], %%rax\n\t"
- "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
- "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
- "orq %%rdx, %%rax\n\t"
- "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
- "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
- "shll $16, %%ebx\n\t" // ebx has same sign as difference
- : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
- : "a"(denominator), [bn] "g"(b.numerator), [tn] "g"(numerator), [bd] "g"(b.denominator)
- : "%rdx", "cc");
- return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
- // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
- : 0;
-
-#else
-
- return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
-
-#endif
-}
-
-int b3ConvexHullInternal::Rational128::compare(const Rational128& b) const
-{
- if (sign != b.sign)
- {
- return sign - b.sign;
- }
- else if (sign == 0)
- {
- return 0;
- }
- if (isInt64)
- {
- return -b.compare(sign * (btInt64_t)numerator.low);
- }
-
- Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
- DMul<Int128, btUint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
- DMul<Int128, btUint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
-
- int cmp = nbdHigh.ucmp(dbnHigh);
- if (cmp)
- {
- return cmp * sign;
- }
- return nbdLow.ucmp(dbnLow) * sign;
-}
-
-int b3ConvexHullInternal::Rational128::compare(btInt64_t b) const
-{
- if (isInt64)
- {
- btInt64_t a = sign * (btInt64_t)numerator.low;
- return (a > b) ? 1 : (a < b) ? -1 : 0;
- }
- if (b > 0)
- {
- if (sign <= 0)
- {
- return -1;
- }
- }
- else if (b < 0)
- {
- if (sign >= 0)
- {
- return 1;
- }
- b = -b;
- }
- else
- {
- return sign;
- }
-
- return numerator.ucmp(denominator * b) * sign;
-}
-
-b3ConvexHullInternal::Edge* b3ConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
-{
- b3Assert(from && to);
- Edge* e = edgePool.newObject();
- Edge* r = edgePool.newObject();
- e->reverse = r;
- r->reverse = e;
- e->copy = mergeStamp;
- r->copy = mergeStamp;
- e->target = to;
- r->target = from;
- e->face = NULL;
- r->face = NULL;
- usedEdgePairs++;
- if (usedEdgePairs > maxUsedEdgePairs)
- {
- maxUsedEdgePairs = usedEdgePairs;
- }
- return e;
-}
-
-bool b3ConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
-{
- Vertex* v0 = h0.maxYx;
- Vertex* v1 = h1.minYx;
- if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
- {
- b3Assert(v0->point.z < v1->point.z);
- Vertex* v1p = v1->prev;
- if (v1p == v1)
- {
- c0 = v0;
- if (v1->edges)
- {
- b3Assert(v1->edges->next == v1->edges);
- v1 = v1->edges->target;
- b3Assert(v1->edges->next == v1->edges);
- }
- c1 = v1;
- return false;
- }
- Vertex* v1n = v1->next;
- v1p->next = v1n;
- v1n->prev = v1p;
- if (v1 == h1.minXy)
- {
- if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
- {
- h1.minXy = v1n;
- }
- else
- {
- h1.minXy = v1p;
- }
- }
- if (v1 == h1.maxXy)
- {
- if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
- {
- h1.maxXy = v1n;
- }
- else
- {
- h1.maxXy = v1p;
- }
- }
- }
-
- v0 = h0.maxXy;
- v1 = h1.maxXy;
- Vertex* v00 = NULL;
- Vertex* v10 = NULL;
- btInt32_t sign = 1;
-
- for (int side = 0; side <= 1; side++)
- {
- btInt32_t dx = (v1->point.x - v0->point.x) * sign;
- if (dx > 0)
- {
- while (true)
- {
- btInt32_t dy = v1->point.y - v0->point.y;
-
- Vertex* w0 = side ? v0->next : v0->prev;
- if (w0 != v0)
- {
- btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
- btInt32_t dy0 = w0->point.y - v0->point.y;
- if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
- {
- v0 = w0;
- dx = (v1->point.x - v0->point.x) * sign;
- continue;
- }
- }
-
- Vertex* w1 = side ? v1->next : v1->prev;
- if (w1 != v1)
- {
- btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
- btInt32_t dy1 = w1->point.y - v1->point.y;
- btInt32_t dxn = (w1->point.x - v0->point.x) * sign;
- if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
- {
- v1 = w1;
- dx = dxn;
- continue;
- }
- }
-
- break;
- }
- }
- else if (dx < 0)
- {
- while (true)
- {
- btInt32_t dy = v1->point.y - v0->point.y;
-
- Vertex* w1 = side ? v1->prev : v1->next;
- if (w1 != v1)
- {
- btInt32_t dx1 = (w1->point.x - v1->point.x) * sign;
- btInt32_t dy1 = w1->point.y - v1->point.y;
- if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
- {
- v1 = w1;
- dx = (v1->point.x - v0->point.x) * sign;
- continue;
- }
- }
-
- Vertex* w0 = side ? v0->prev : v0->next;
- if (w0 != v0)
- {
- btInt32_t dx0 = (w0->point.x - v0->point.x) * sign;
- btInt32_t dy0 = w0->point.y - v0->point.y;
- btInt32_t dxn = (v1->point.x - w0->point.x) * sign;
- if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
- {
- v0 = w0;
- dx = dxn;
- continue;
- }
- }
-
- break;
- }
- }
- else
- {
- btInt32_t x = v0->point.x;
- btInt32_t y0 = v0->point.y;
- Vertex* w0 = v0;
- Vertex* t;
- while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
- {
- w0 = t;
- y0 = t->point.y;
- }
- v0 = w0;
-
- btInt32_t y1 = v1->point.y;
- Vertex* w1 = v1;
- while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
- {
- w1 = t;
- y1 = t->point.y;
- }
- v1 = w1;
- }
-
- if (side == 0)
- {
- v00 = v0;
- v10 = v1;
-
- v0 = h0.minXy;
- v1 = h1.minXy;
- sign = -1;
- }
- }
-
- v0->prev = v1;
- v1->next = v0;
-
- v00->next = v10;
- v10->prev = v00;
-
- if (h1.minXy->point.x < h0.minXy->point.x)
- {
- h0.minXy = h1.minXy;
- }
- if (h1.maxXy->point.x >= h0.maxXy->point.x)
- {
- h0.maxXy = h1.maxXy;
- }
-
- h0.maxYx = h1.maxYx;
-
- c0 = v00;
- c1 = v10;
-
- return true;
-}
-
-void b3ConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
-{
- int n = end - start;
- switch (n)
- {
- case 0:
- result.minXy = NULL;
- result.maxXy = NULL;
- result.minYx = NULL;
- result.maxYx = NULL;
- return;
- case 2:
- {
- Vertex* v = originalVertices[start];
- Vertex* w = v + 1;
- if (v->point != w->point)
- {
- btInt32_t dx = v->point.x - w->point.x;
- btInt32_t dy = v->point.y - w->point.y;
-
- if ((dx == 0) && (dy == 0))
- {
- if (v->point.z > w->point.z)
- {
- Vertex* t = w;
- w = v;
- v = t;
- }
- b3Assert(v->point.z < w->point.z);
- v->next = v;
- v->prev = v;
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
- }
- else
- {
- v->next = w;
- v->prev = w;
- w->next = v;
- w->prev = v;
-
- if ((dx < 0) || ((dx == 0) && (dy < 0)))
- {
- result.minXy = v;
- result.maxXy = w;
- }
- else
- {
- result.minXy = w;
- result.maxXy = v;
- }
-
- if ((dy < 0) || ((dy == 0) && (dx < 0)))
- {
- result.minYx = v;
- result.maxYx = w;
- }
- else
- {
- result.minYx = w;
- result.maxYx = v;
- }
- }
-
- Edge* e = newEdgePair(v, w);
- e->link(e);
- v->edges = e;
-
- e = e->reverse;
- e->link(e);
- w->edges = e;
-
- return;
- }
- }
- // lint -fallthrough
- case 1:
- {
- Vertex* v = originalVertices[start];
- v->edges = NULL;
- v->next = v;
- v->prev = v;
-
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
-
- return;
- }
- }
-
- int split0 = start + n / 2;
- Point32 p = originalVertices[split0 - 1]->point;
- int split1 = split0;
- while ((split1 < end) && (originalVertices[split1]->point == p))
- {
- split1++;
- }
- computeInternal(start, split0, result);
- IntermediateHull hull1;
- computeInternal(split1, end, hull1);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("\n\nMerge\n");
- result.print();
- hull1.print();
-#endif
- merge(result, hull1);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("\n Result\n");
- result.print();
-#endif
-}
-
-#ifdef DEBUG_CONVEX_HULL
-void b3ConvexHullInternal::IntermediateHull::print()
-{
- b3Printf(" Hull\n");
- for (Vertex* v = minXy; v;)
- {
- b3Printf(" ");
- v->print();
- if (v == maxXy)
- {
- b3Printf(" maxXy");
- }
- if (v == minYx)
- {
- b3Printf(" minYx");
- }
- if (v == maxYx)
- {
- b3Printf(" maxYx");
- }
- if (v->next->prev != v)
- {
- b3Printf(" Inconsistency");
- }
- b3Printf("\n");
- v = v->next;
- if (v == minXy)
- {
- break;
- }
- }
- if (minXy)
- {
- minXy->copy = (minXy->copy == -1) ? -2 : -1;
- minXy->printGraph();
- }
-}
-
-void b3ConvexHullInternal::Vertex::printGraph()
-{
- print();
- b3Printf("\nEdges\n");
- Edge* e = edges;
- if (e)
- {
- do
- {
- e->print();
- b3Printf("\n");
- e = e->next;
- } while (e != edges);
- do
- {
- Vertex* v = e->target;
- if (v->copy != copy)
- {
- v->copy = copy;
- v->printGraph();
- }
- e = e->next;
- } while (e != edges);
- }
-}
-#endif
-
-b3ConvexHullInternal::Orientation b3ConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
-{
- b3Assert(prev->reverse->target == next->reverse->target);
- if (prev->next == next)
- {
- if (prev->prev == next)
- {
- Point64 n = t.cross(s);
- Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
- b3Assert(!m.isZero());
- btInt64_t dot = n.dot(m);
- b3Assert(dot != 0);
- return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
- }
- return COUNTER_CLOCKWISE;
- }
- else if (prev->prev == next)
- {
- return CLOCKWISE;
- }
- else
- {
- return NONE;
- }
-}
-
-b3ConvexHullInternal::Edge* b3ConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
-{
- Edge* minEdge = NULL;
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("find max edge for %d\n", start->point.index);
-#endif
- Edge* e = start->edges;
- if (e)
- {
- do
- {
- if (e->copy > mergeStamp)
- {
- Point32 t = *e->target - *start;
- Rational64 cot(t.dot(sxrxs), t.dot(rxs));
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Angle is %f (%d) for ", (float)b3Atan(cot.toScalar()), (int)cot.isNaN());
- e->print();
-#endif
- if (cot.isNaN())
- {
- b3Assert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
- }
- else
- {
- int cmp;
- if (minEdge == NULL)
- {
- minCot = cot;
- minEdge = e;
- }
- else if ((cmp = cot.compare(minCot)) < 0)
- {
- minCot = cot;
- minEdge = e;
- }
- else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
- {
- minEdge = e;
- }
- }
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("\n");
-#endif
- }
- e = e->next;
- } while (e != start->edges);
- }
- return minEdge;
-}
-
-void b3ConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
-{
- Edge* start0 = e0;
- Edge* start1 = e1;
- Point32 et0 = start0 ? start0->target->point : c0->point;
- Point32 et1 = start1 ? start1->target->point : c1->point;
- Point32 s = c1->point - c0->point;
- Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
- btInt64_t dist = c0->point.dot(normal);
- b3Assert(!start1 || (start1->target->point.dot(normal) == dist));
- Point64 perp = s.cross(normal);
- b3Assert(!perp.isZero());
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
-#endif
-
- btInt64_t maxDot0 = et0.dot(perp);
- if (e0)
- {
- while (e0->target != stop0)
- {
- Edge* e = e0->reverse->prev;
- if (e->target->point.dot(normal) < dist)
- {
- break;
- }
- b3Assert(e->target->point.dot(normal) == dist);
- if (e->copy == mergeStamp)
- {
- break;
- }
- btInt64_t dot = e->target->point.dot(perp);
- if (dot <= maxDot0)
- {
- break;
- }
- maxDot0 = dot;
- e0 = e;
- et0 = e->target->point;
- }
- }
-
- btInt64_t maxDot1 = et1.dot(perp);
- if (e1)
- {
- while (e1->target != stop1)
- {
- Edge* e = e1->reverse->next;
- if (e->target->point.dot(normal) < dist)
- {
- break;
- }
- b3Assert(e->target->point.dot(normal) == dist);
- if (e->copy == mergeStamp)
- {
- break;
- }
- btInt64_t dot = e->target->point.dot(perp);
- if (dot <= maxDot1)
- {
- break;
- }
- maxDot1 = dot;
- e1 = e;
- et1 = e->target->point;
- }
- }
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Starting at %d %d\n", et0.index, et1.index);
-#endif
-
- btInt64_t dx = maxDot1 - maxDot0;
- if (dx > 0)
- {
- while (true)
- {
- btInt64_t dy = (et1 - et0).dot(s);
-
- if (e0 && (e0->target != stop0))
- {
- Edge* f0 = e0->next->reverse;
- if (f0->copy > mergeStamp)
- {
- btInt64_t dx0 = (f0->target->point - et0).dot(perp);
- btInt64_t dy0 = (f0->target->point - et0).dot(s);
- if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
- {
- et0 = f0->target->point;
- dx = (et1 - et0).dot(perp);
- e0 = (e0 == start0) ? NULL : f0;
- continue;
- }
- }
- }
-
- if (e1 && (e1->target != stop1))
- {
- Edge* f1 = e1->reverse->next;
- if (f1->copy > mergeStamp)
- {
- Point32 d1 = f1->target->point - et1;
- if (d1.dot(normal) == 0)
- {
- btInt64_t dx1 = d1.dot(perp);
- btInt64_t dy1 = d1.dot(s);
- btInt64_t dxn = (f1->target->point - et0).dot(perp);
- if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
- {
- e1 = f1;
- et1 = e1->target->point;
- dx = dxn;
- continue;
- }
- }
- else
- {
- b3Assert((e1 == start1) && (d1.dot(normal) < 0));
- }
- }
- }
-
- break;
- }
- }
- else if (dx < 0)
- {
- while (true)
- {
- btInt64_t dy = (et1 - et0).dot(s);
-
- if (e1 && (e1->target != stop1))
- {
- Edge* f1 = e1->prev->reverse;
- if (f1->copy > mergeStamp)
- {
- btInt64_t dx1 = (f1->target->point - et1).dot(perp);
- btInt64_t dy1 = (f1->target->point - et1).dot(s);
- if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
- {
- et1 = f1->target->point;
- dx = (et1 - et0).dot(perp);
- e1 = (e1 == start1) ? NULL : f1;
- continue;
- }
- }
- }
-
- if (e0 && (e0->target != stop0))
- {
- Edge* f0 = e0->reverse->prev;
- if (f0->copy > mergeStamp)
- {
- Point32 d0 = f0->target->point - et0;
- if (d0.dot(normal) == 0)
- {
- btInt64_t dx0 = d0.dot(perp);
- btInt64_t dy0 = d0.dot(s);
- btInt64_t dxn = (et1 - f0->target->point).dot(perp);
- if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
- {
- e0 = f0;
- et0 = e0->target->point;
- dx = dxn;
- continue;
- }
- }
- else
- {
- b3Assert((e0 == start0) && (d0.dot(normal) < 0));
- }
- }
- }
-
- break;
- }
- }
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Advanced edges to %d %d\n", et0.index, et1.index);
-#endif
-}
-
-void b3ConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
-{
- if (!h1.maxXy)
- {
- return;
- }
- if (!h0.maxXy)
- {
- h0 = h1;
- return;
- }
-
- mergeStamp--;
-
- Vertex* c0 = NULL;
- Edge* toPrev0 = NULL;
- Edge* firstNew0 = NULL;
- Edge* pendingHead0 = NULL;
- Edge* pendingTail0 = NULL;
- Vertex* c1 = NULL;
- Edge* toPrev1 = NULL;
- Edge* firstNew1 = NULL;
- Edge* pendingHead1 = NULL;
- Edge* pendingTail1 = NULL;
- Point32 prevPoint;
-
- if (mergeProjection(h0, h1, c0, c1))
- {
- Point32 s = *c1 - *c0;
- Point64 normal = Point32(0, 0, -1).cross(s);
- Point64 t = s.cross(normal);
- b3Assert(!t.isZero());
-
- Edge* e = c0->edges;
- Edge* start0 = NULL;
- if (e)
- {
- do
- {
- btInt64_t dot = (*e->target - *c0).dot(normal);
- b3Assert(dot <= 0);
- if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
- {
- if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
- {
- start0 = e;
- }
- }
- e = e->next;
- } while (e != c0->edges);
- }
-
- e = c1->edges;
- Edge* start1 = NULL;
- if (e)
- {
- do
- {
- btInt64_t dot = (*e->target - *c1).dot(normal);
- b3Assert(dot <= 0);
- if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
- {
- if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
- {
- start1 = e;
- }
- }
- e = e->next;
- } while (e != c1->edges);
- }
-
- if (start0 || start1)
- {
- findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
- if (start0)
- {
- c0 = start0->target;
- }
- if (start1)
- {
- c1 = start1->target;
- }
- }
-
- prevPoint = c1->point;
- prevPoint.z++;
- }
- else
- {
- prevPoint = c1->point;
- prevPoint.x++;
- }
-
- Vertex* first0 = c0;
- Vertex* first1 = c1;
- bool firstRun = true;
-
- while (true)
- {
- Point32 s = *c1 - *c0;
- Point32 r = prevPoint - c0->point;
- Point64 rxs = r.cross(s);
- Point64 sxrxs = s.cross(rxs);
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
-#endif
- Rational64 minCot0(0, 0);
- Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
- Rational64 minCot1(0, 0);
- Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
- if (!min0 && !min1)
- {
- Edge* e = newEdgePair(c0, c1);
- e->link(e);
- c0->edges = e;
-
- e = e->reverse;
- e->link(e);
- c1->edges = e;
- return;
- }
- else
- {
- int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" -> Result %d\n", cmp);
-#endif
- if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
- {
- Edge* e = newEdgePair(c0, c1);
- if (pendingTail0)
- {
- pendingTail0->prev = e;
- }
- else
- {
- pendingHead0 = e;
- }
- e->next = pendingTail0;
- pendingTail0 = e;
-
- e = e->reverse;
- if (pendingTail1)
- {
- pendingTail1->next = e;
- }
- else
- {
- pendingHead1 = e;
- }
- e->prev = pendingTail1;
- pendingTail1 = e;
- }
-
- Edge* e0 = min0;
- Edge* e1 = min1;
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
-#endif
-
- if (cmp == 0)
- {
- findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
- }
-
- if ((cmp >= 0) && e1)
- {
- if (toPrev1)
- {
- for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
- {
- n = e->next;
- removeEdgePair(e);
- }
- }
-
- if (pendingTail1)
- {
- if (toPrev1)
- {
- toPrev1->link(pendingHead1);
- }
- else
- {
- min1->prev->link(pendingHead1);
- firstNew1 = pendingHead1;
- }
- pendingTail1->link(min1);
- pendingHead1 = NULL;
- pendingTail1 = NULL;
- }
- else if (!toPrev1)
- {
- firstNew1 = min1;
- }
-
- prevPoint = c1->point;
- c1 = e1->target;
- toPrev1 = e1->reverse;
- }
-
- if ((cmp <= 0) && e0)
- {
- if (toPrev0)
- {
- for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
- {
- n = e->prev;
- removeEdgePair(e);
- }
- }
-
- if (pendingTail0)
- {
- if (toPrev0)
- {
- pendingHead0->link(toPrev0);
- }
- else
- {
- pendingHead0->link(min0->next);
- firstNew0 = pendingHead0;
- }
- min0->link(pendingTail0);
- pendingHead0 = NULL;
- pendingTail0 = NULL;
- }
- else if (!toPrev0)
- {
- firstNew0 = min0;
- }
-
- prevPoint = c0->point;
- c0 = e0->target;
- toPrev0 = e0->reverse;
- }
- }
-
- if ((c0 == first0) && (c1 == first1))
- {
- if (toPrev0 == NULL)
- {
- pendingHead0->link(pendingTail0);
- c0->edges = pendingTail0;
- }
- else
- {
- for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
- {
- n = e->prev;
- removeEdgePair(e);
- }
- if (pendingTail0)
- {
- pendingHead0->link(toPrev0);
- firstNew0->link(pendingTail0);
- }
- }
-
- if (toPrev1 == NULL)
- {
- pendingTail1->link(pendingHead1);
- c1->edges = pendingTail1;
- }
- else
- {
- for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
- {
- n = e->next;
- removeEdgePair(e);
- }
- if (pendingTail1)
- {
- toPrev1->link(pendingHead1);
- pendingTail1->link(firstNew1);
- }
- }
-
- return;
- }
-
- firstRun = false;
- }
-}
-
-static bool b3PointCmp(const b3ConvexHullInternal::Point32& p, const b3ConvexHullInternal::Point32& q)
-{
- return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
-}
-
-void b3ConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
-{
- b3Vector3 min = b3MakeVector3(b3Scalar(1e30), b3Scalar(1e30), b3Scalar(1e30)), max = b3MakeVector3(b3Scalar(-1e30), b3Scalar(-1e30), b3Scalar(-1e30));
- const char* ptr = (const char*)coords;
- if (doubleCoords)
- {
- for (int i = 0; i < count; i++)
- {
- const double* v = (const double*)ptr;
- b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
- ptr += stride;
- min.setMin(p);
- max.setMax(p);
- }
- }
- else
- {
- for (int i = 0; i < count; i++)
- {
- const float* v = (const float*)ptr;
- b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
- ptr += stride;
- min.setMin(p);
- max.setMax(p);
- }
- }
-
- b3Vector3 s = max - min;
- maxAxis = s.maxAxis();
- minAxis = s.minAxis();
- if (minAxis == maxAxis)
- {
- minAxis = (maxAxis + 1) % 3;
- }
- medAxis = 3 - maxAxis - minAxis;
-
- s /= b3Scalar(10216);
- if (((medAxis + 1) % 3) != maxAxis)
- {
- s *= -1;
- }
- scaling = s;
-
- if (s[0] != 0)
- {
- s[0] = b3Scalar(1) / s[0];
- }
- if (s[1] != 0)
- {
- s[1] = b3Scalar(1) / s[1];
- }
- if (s[2] != 0)
- {
- s[2] = b3Scalar(1) / s[2];
- }
-
- center = (min + max) * b3Scalar(0.5);
-
- b3AlignedObjectArray<Point32> points;
- points.resize(count);
- ptr = (const char*)coords;
- if (doubleCoords)
- {
- for (int i = 0; i < count; i++)
- {
- const double* v = (const double*)ptr;
- b3Vector3 p = b3MakeVector3((b3Scalar)v[0], (b3Scalar)v[1], (b3Scalar)v[2]);
- ptr += stride;
- p = (p - center) * s;
- points[i].x = (btInt32_t)p[medAxis];
- points[i].y = (btInt32_t)p[maxAxis];
- points[i].z = (btInt32_t)p[minAxis];
- points[i].index = i;
- }
- }
- else
- {
- for (int i = 0; i < count; i++)
- {
- const float* v = (const float*)ptr;
- b3Vector3 p = b3MakeVector3(v[0], v[1], v[2]);
- ptr += stride;
- p = (p - center) * s;
- points[i].x = (btInt32_t)p[medAxis];
- points[i].y = (btInt32_t)p[maxAxis];
- points[i].z = (btInt32_t)p[minAxis];
- points[i].index = i;
- }
- }
- points.quickSort(b3PointCmp);
-
- vertexPool.reset();
- vertexPool.setArraySize(count);
- originalVertices.resize(count);
- for (int i = 0; i < count; i++)
- {
- Vertex* v = vertexPool.newObject();
- v->edges = NULL;
- v->point = points[i];
- v->copy = -1;
- originalVertices[i] = v;
- }
-
- points.clear();
-
- edgePool.reset();
- edgePool.setArraySize(6 * count);
-
- usedEdgePairs = 0;
- maxUsedEdgePairs = 0;
-
- mergeStamp = -3;
-
- IntermediateHull hull;
- computeInternal(0, count, hull);
- vertexList = hull.minXy;
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
-#endif
-}
-
-b3Vector3 b3ConvexHullInternal::toBtVector(const Point32& v)
-{
- b3Vector3 p;
- p[medAxis] = b3Scalar(v.x);
- p[maxAxis] = b3Scalar(v.y);
- p[minAxis] = b3Scalar(v.z);
- return p * scaling;
-}
-
-b3Vector3 b3ConvexHullInternal::getBtNormal(Face* face)
-{
- return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
-}
-
-b3Vector3 b3ConvexHullInternal::getCoordinates(const Vertex* v)
-{
- b3Vector3 p;
- p[medAxis] = v->xvalue();
- p[maxAxis] = v->yvalue();
- p[minAxis] = v->zvalue();
- return p * scaling + center;
-}
-
-b3Scalar b3ConvexHullInternal::shrink(b3Scalar amount, b3Scalar clampAmount)
-{
- if (!vertexList)
- {
- return 0;
- }
- int stamp = --mergeStamp;
- b3AlignedObjectArray<Vertex*> stack;
- vertexList->copy = stamp;
- stack.push_back(vertexList);
- b3AlignedObjectArray<Face*> faces;
-
- Point32 ref = vertexList->point;
- Int128 hullCenterX(0, 0);
- Int128 hullCenterY(0, 0);
- Int128 hullCenterZ(0, 0);
- Int128 volume(0, 0);
-
- while (stack.size() > 0)
- {
- Vertex* v = stack[stack.size() - 1];
- stack.pop_back();
- Edge* e = v->edges;
- if (e)
- {
- do
- {
- if (e->target->copy != stamp)
- {
- e->target->copy = stamp;
- stack.push_back(e->target);
- }
- if (e->copy != stamp)
- {
- Face* face = facePool.newObject();
- face->init(e->target, e->reverse->prev->target, v);
- faces.push_back(face);
- Edge* f = e;
-
- Vertex* a = NULL;
- Vertex* b = NULL;
- do
- {
- if (a && b)
- {
- btInt64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
- b3Assert(vol >= 0);
- Point32 c = v->point + a->point + b->point + ref;
- hullCenterX += vol * c.x;
- hullCenterY += vol * c.y;
- hullCenterZ += vol * c.z;
- volume += vol;
- }
-
- b3Assert(f->copy != stamp);
- f->copy = stamp;
- f->face = face;
-
- a = b;
- b = f->target;
-
- f = f->reverse->prev;
- } while (f != e);
- }
- e = e->next;
- } while (e != v->edges);
- }
- }
-
- if (volume.getSign() <= 0)
- {
- return 0;
- }
-
- b3Vector3 hullCenter;
- hullCenter[medAxis] = hullCenterX.toScalar();
- hullCenter[maxAxis] = hullCenterY.toScalar();
- hullCenter[minAxis] = hullCenterZ.toScalar();
- hullCenter /= 4 * volume.toScalar();
- hullCenter *= scaling;
-
- int faceCount = faces.size();
-
- if (clampAmount > 0)
- {
- b3Scalar minDist = B3_INFINITY;
- for (int i = 0; i < faceCount; i++)
- {
- b3Vector3 normal = getBtNormal(faces[i]);
- b3Scalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
- if (dist < minDist)
- {
- minDist = dist;
- }
- }
-
- if (minDist <= 0)
- {
- return 0;
- }
-
- amount = b3Min(amount, minDist * clampAmount);
- }
-
- unsigned int seed = 243703;
- for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
- {
- b3Swap(faces[i], faces[seed % faceCount]);
- }
-
- for (int i = 0; i < faceCount; i++)
- {
- if (!shiftFace(faces[i], amount, stack))
- {
- return -amount;
- }
- }
-
- return amount;
-}
-
-bool b3ConvexHullInternal::shiftFace(Face* face, b3Scalar amount, b3AlignedObjectArray<Vertex*> stack)
-{
- b3Vector3 origShift = getBtNormal(face) * -amount;
- if (scaling[0] != 0)
- {
- origShift[0] /= scaling[0];
- }
- if (scaling[1] != 0)
- {
- origShift[1] /= scaling[1];
- }
- if (scaling[2] != 0)
- {
- origShift[2] /= scaling[2];
- }
- Point32 shift((btInt32_t)origShift[medAxis], (btInt32_t)origShift[maxAxis], (btInt32_t)origShift[minAxis]);
- if (shift.isZero())
- {
- return true;
- }
- Point64 normal = face->getNormal();
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
- face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
-#endif
- btInt64_t origDot = face->origin.dot(normal);
- Point32 shiftedOrigin = face->origin + shift;
- btInt64_t shiftedDot = shiftedOrigin.dot(normal);
- b3Assert(shiftedDot <= origDot);
- if (shiftedDot >= origDot)
- {
- return false;
- }
-
- Edge* intersection = NULL;
-
- Edge* startEdge = face->nearbyVertex->edges;
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Start edge is ");
- startEdge->print();
- b3Printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
-#endif
- Rational128 optDot = face->nearbyVertex->dot(normal);
- int cmp = optDot.compare(shiftedDot);
-#ifdef SHOW_ITERATIONS
- int n = 0;
-#endif
- if (cmp >= 0)
- {
- Edge* e = startEdge;
- do
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- Rational128 dot = e->target->dot(normal);
- b3Assert(dot.compare(origDot) <= 0);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Moving downwards, edge is ");
- e->print();
- b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
-#endif
- if (dot.compare(optDot) < 0)
- {
- int c = dot.compare(shiftedDot);
- optDot = dot;
- e = e->reverse;
- startEdge = e;
- if (c < 0)
- {
- intersection = e;
- break;
- }
- cmp = c;
- }
- e = e->prev;
- } while (e != startEdge);
-
- if (!intersection)
- {
- return false;
- }
- }
- else
- {
- Edge* e = startEdge;
- do
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- Rational128 dot = e->target->dot(normal);
- b3Assert(dot.compare(origDot) <= 0);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Moving upwards, edge is ");
- e->print();
- b3Printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
-#endif
- if (dot.compare(optDot) > 0)
- {
- cmp = dot.compare(shiftedDot);
- if (cmp >= 0)
- {
- intersection = e;
- break;
- }
- optDot = dot;
- e = e->reverse;
- startEdge = e;
- }
- e = e->prev;
- } while (e != startEdge);
-
- if (!intersection)
- {
- return true;
- }
- }
-
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to find initial intersection\n", n);
-#endif
-
- if (cmp == 0)
- {
- Edge* e = intersection->reverse->next;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (e->target->dot(normal).compare(shiftedDot) <= 0)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- e = e->next;
- if (e == intersection->reverse)
- {
- return true;
- }
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Checking for outwards edge, current edge is ");
- e->print();
- b3Printf("\n");
-#endif
- }
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to check for complete containment\n", n);
-#endif
- }
-
- Edge* firstIntersection = NULL;
- Edge* faceEdge = NULL;
- Edge* firstFaceEdge = NULL;
-
-#ifdef SHOW_ITERATIONS
- int m = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- m++;
-#endif
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Intersecting edge is ");
- intersection->print();
- b3Printf("\n");
-#endif
- if (cmp == 0)
- {
- Edge* e = intersection->reverse->next;
- startEdge = e;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- if (e->target->dot(normal).compare(shiftedDot) >= 0)
- {
- break;
- }
- intersection = e->reverse;
- e = e->next;
- if (e == startEdge)
- {
- return true;
- }
- }
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to advance intersection\n", n);
-#endif
- }
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Advanced intersecting edge to ");
- intersection->print();
- b3Printf(", cmp = %d\n", cmp);
-#endif
-
- if (!firstIntersection)
- {
- firstIntersection = intersection;
- }
- else if (intersection == firstIntersection)
- {
- break;
- }
-
- int prevCmp = cmp;
- Edge* prevIntersection = intersection;
- Edge* prevFaceEdge = faceEdge;
-
- Edge* e = intersection->reverse;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- e = e->reverse->prev;
- b3Assert(e != intersection->reverse);
- cmp = e->target->dot(normal).compare(shiftedDot);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Testing edge ");
- e->print();
- b3Printf(" -> cmp = %d\n", cmp);
-#endif
- if (cmp >= 0)
- {
- intersection = e;
- break;
- }
- }
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to find other intersection of face\n", n);
-#endif
-
- if (cmp > 0)
- {
- Vertex* removed = intersection->target;
- e = intersection->reverse;
- if (e->prev == e)
- {
- removed->edges = NULL;
- }
- else
- {
- removed->edges = e->prev;
- e->prev->link(e->next);
- e->link(e);
- }
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
-
- Point64 n0 = intersection->face->getNormal();
- Point64 n1 = intersection->reverse->face->getNormal();
- btInt64_t m00 = face->dir0.dot(n0);
- btInt64_t m01 = face->dir1.dot(n0);
- btInt64_t m10 = face->dir0.dot(n1);
- btInt64_t m11 = face->dir1.dot(n1);
- btInt64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
- btInt64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
- Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
- b3Assert(det.getSign() != 0);
- Vertex* v = vertexPool.newObject();
- v->point.index = -1;
- v->copy = -1;
- v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
- Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
- Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
- det);
- v->point.x = (btInt32_t)v->point128.xvalue();
- v->point.y = (btInt32_t)v->point128.yvalue();
- v->point.z = (btInt32_t)v->point128.zvalue();
- intersection->target = v;
- v->edges = e;
-
- stack.push_back(v);
- stack.push_back(removed);
- stack.push_back(NULL);
- }
-
- if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
- {
- faceEdge = newEdgePair(prevIntersection->target, intersection->target);
- if (prevCmp == 0)
- {
- faceEdge->link(prevIntersection->reverse->next);
- }
- if ((prevCmp == 0) || prevFaceEdge)
- {
- prevIntersection->reverse->link(faceEdge);
- }
- if (cmp == 0)
- {
- intersection->reverse->prev->link(faceEdge->reverse);
- }
- faceEdge->reverse->link(intersection->reverse);
- }
- else
- {
- faceEdge = prevIntersection->reverse->next;
- }
-
- if (prevFaceEdge)
- {
- if (prevCmp > 0)
- {
- faceEdge->link(prevFaceEdge->reverse);
- }
- else if (faceEdge != prevFaceEdge->reverse)
- {
- stack.push_back(prevFaceEdge->target);
- while (faceEdge->next != prevFaceEdge->reverse)
- {
- Vertex* removed = faceEdge->next->target;
- removeEdgePair(faceEdge->next);
- stack.push_back(removed);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
- }
- stack.push_back(NULL);
- }
- }
- faceEdge->face = face;
- faceEdge->reverse->face = intersection->face;
-
- if (!firstFaceEdge)
- {
- firstFaceEdge = faceEdge;
- }
- }
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to process all intersections\n", m);
-#endif
-
- if (cmp > 0)
- {
- firstFaceEdge->reverse->target = faceEdge->target;
- firstIntersection->reverse->link(firstFaceEdge);
- firstFaceEdge->link(faceEdge->reverse);
- }
- else if (firstFaceEdge != faceEdge->reverse)
- {
- stack.push_back(faceEdge->target);
- while (firstFaceEdge->next != faceEdge->reverse)
- {
- Vertex* removed = firstFaceEdge->next->target;
- removeEdgePair(firstFaceEdge->next);
- stack.push_back(removed);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
- }
- stack.push_back(NULL);
- }
-
- b3Assert(stack.size() > 0);
- vertexList = stack[0];
-
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Removing part\n");
-#endif
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- int pos = 0;
- while (pos < stack.size())
- {
- int end = stack.size();
- while (pos < end)
- {
- Vertex* kept = stack[pos++];
-#ifdef DEBUG_CONVEX_HULL
- kept->print();
-#endif
- bool deeper = false;
- Vertex* removed;
- while ((removed = stack[pos++]) != NULL)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- kept->receiveNearbyFaces(removed);
- while (removed->edges)
- {
- if (!deeper)
- {
- deeper = true;
- stack.push_back(kept);
- }
- stack.push_back(removed->edges->target);
- removeEdgePair(removed->edges);
- }
- }
- if (deeper)
- {
- stack.push_back(NULL);
- }
- }
- }
-#ifdef SHOW_ITERATIONS
- b3Printf("Needed %d iterations to remove part\n", n);
-#endif
-
- stack.resize(0);
- face->origin = shiftedOrigin;
-
- return true;
-}
-
-static int getVertexCopy(b3ConvexHullInternal::Vertex* vertex, b3AlignedObjectArray<b3ConvexHullInternal::Vertex*>& vertices)
-{
- int index = vertex->copy;
- if (index < 0)
- {
- index = vertices.size();
- vertex->copy = index;
- vertices.push_back(vertex);
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Vertex %d gets index *%d\n", vertex->point.index, index);
-#endif
- }
- return index;
-}
-
-b3Scalar b3ConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
-{
- if (count <= 0)
- {
- vertices.clear();
- edges.clear();
- faces.clear();
- return 0;
- }
-
- b3ConvexHullInternal hull;
- hull.compute(coords, doubleCoords, stride, count);
-
- b3Scalar shift = 0;
- if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
- {
- vertices.clear();
- edges.clear();
- faces.clear();
- return shift;
- }
-
- vertices.resize(0);
- edges.resize(0);
- faces.resize(0);
-
- b3AlignedObjectArray<b3ConvexHullInternal::Vertex*> oldVertices;
- getVertexCopy(hull.vertexList, oldVertices);
- int copied = 0;
- while (copied < oldVertices.size())
- {
- b3ConvexHullInternal::Vertex* v = oldVertices[copied];
- vertices.push_back(hull.getCoordinates(v));
- b3ConvexHullInternal::Edge* firstEdge = v->edges;
- if (firstEdge)
- {
- int firstCopy = -1;
- int prevCopy = -1;
- b3ConvexHullInternal::Edge* e = firstEdge;
- do
- {
- if (e->copy < 0)
- {
- int s = edges.size();
- edges.push_back(Edge());
- edges.push_back(Edge());
- Edge* c = &edges[s];
- Edge* r = &edges[s + 1];
- e->copy = s;
- e->reverse->copy = s + 1;
- c->reverse = 1;
- r->reverse = -1;
- c->targetVertex = getVertexCopy(e->target, oldVertices);
- r->targetVertex = copied;
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
-#endif
- }
- if (prevCopy >= 0)
- {
- edges[e->copy].next = prevCopy - e->copy;
- }
- else
- {
- firstCopy = e->copy;
- }
- prevCopy = e->copy;
- e = e->next;
- } while (e != firstEdge);
- edges[firstCopy].next = prevCopy - firstCopy;
- }
- copied++;
- }
-
- for (int i = 0; i < copied; i++)
- {
- b3ConvexHullInternal::Vertex* v = oldVertices[i];
- b3ConvexHullInternal::Edge* firstEdge = v->edges;
- if (firstEdge)
- {
- b3ConvexHullInternal::Edge* e = firstEdge;
- do
- {
- if (e->copy >= 0)
- {
-#ifdef DEBUG_CONVEX_HULL
- b3Printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
-#endif
- faces.push_back(e->copy);
- b3ConvexHullInternal::Edge* f = e;
- do
- {
-#ifdef DEBUG_CONVEX_HULL
- b3Printf(" Face *%d\n", edges[f->copy].getTargetVertex());
-#endif
- f->copy = -1;
- f = f->reverse->prev;
- } while (f != e);
- }
- e = e->next;
- } while (e != firstEdge);
- }
- }
-
- return shift;
-}
diff --git a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h b/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h
deleted file mode 100644
index 8852c5a524..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3ConvexHullComputer.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_CONVEX_HULL_COMPUTER_H
-#define B3_CONVEX_HULL_COMPUTER_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-/// Convex hull implementation based on Preparata and Hong
-/// See http://code.google.com/p/bullet/issues/detail?id=275
-/// Ole Kniemeyer, MAXON Computer GmbH
-class b3ConvexHullComputer
-{
-private:
- b3Scalar compute(const void* coords, bool doubleCoords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp);
-
-public:
- class Edge
- {
- private:
- int next;
- int reverse;
- int targetVertex;
-
- friend class b3ConvexHullComputer;
-
- public:
- int getSourceVertex() const
- {
- return (this + reverse)->targetVertex;
- }
-
- int getTargetVertex() const
- {
- return targetVertex;
- }
-
- const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
- {
- return this + next;
- }
-
- const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
- {
- return (this + reverse)->getNextEdgeOfVertex();
- }
-
- const Edge* getReverseEdge() const
- {
- return this + reverse;
- }
- };
-
- // Vertices of the output hull
- b3AlignedObjectArray<b3Vector3> vertices;
-
- // Edges of the output hull
- b3AlignedObjectArray<Edge> edges;
-
- // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
- b3AlignedObjectArray<int> faces;
-
- /*
- Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
- between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
- by that amount (each face is moved by "shrink" length units towards the center along its normal).
- If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
- is the minimum distance of a face to the center of the convex hull.
-
- The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
- that the resulting convex hull is empty.
-
- The output convex hull can be found in the member variables "vertices", "edges", "faces".
- */
- b3Scalar compute(const float* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
- {
- return compute(coords, false, stride, count, shrink, shrinkClamp);
- }
-
- // same as above, but double precision
- b3Scalar compute(const double* coords, int stride, int count, b3Scalar shrink, b3Scalar shrinkClamp)
- {
- return compute(coords, true, stride, count, shrink, shrinkClamp);
- }
-};
-
-#endif //B3_CONVEX_HULL_COMPUTER_H
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp
deleted file mode 100644
index c4041003ca..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3GeometryUtil.h"
-
-/*
- Make sure this dummy function never changes so that it
- can be used by probes that are checking whether the
- library is actually installed.
-*/
-extern "C"
-{
- void b3BulletMathProbe();
-
- void b3BulletMathProbe() {}
-}
-
-bool b3GeometryUtil::isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin)
-{
- int numbrushes = planeEquations.size();
- for (int i = 0; i < numbrushes; i++)
- {
- const b3Vector3& N1 = planeEquations[i];
- b3Scalar dist = b3Scalar(N1.dot(point)) + b3Scalar(N1[3]) - margin;
- if (dist > b3Scalar(0.))
- {
- return false;
- }
- }
- return true;
-}
-
-bool b3GeometryUtil::areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin)
-{
- int numvertices = vertices.size();
- for (int i = 0; i < numvertices; i++)
- {
- const b3Vector3& N1 = vertices[i];
- b3Scalar dist = b3Scalar(planeNormal.dot(N1)) + b3Scalar(planeNormal[3]) - margin;
- if (dist > b3Scalar(0.))
- {
- return false;
- }
- }
- return true;
-}
-
-bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations);
-
-bool notExist(const b3Vector3& planeEquation, const b3AlignedObjectArray<b3Vector3>& planeEquations)
-{
- int numbrushes = planeEquations.size();
- for (int i = 0; i < numbrushes; i++)
- {
- const b3Vector3& N1 = planeEquations[i];
- if (planeEquation.dot(N1) > b3Scalar(0.999))
- {
- return false;
- }
- }
- return true;
-}
-
-void b3GeometryUtil::getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut)
-{
- const int numvertices = vertices.size();
- // brute force:
- for (int i = 0; i < numvertices; i++)
- {
- const b3Vector3& N1 = vertices[i];
-
- for (int j = i + 1; j < numvertices; j++)
- {
- const b3Vector3& N2 = vertices[j];
-
- for (int k = j + 1; k < numvertices; k++)
- {
- const b3Vector3& N3 = vertices[k];
-
- b3Vector3 planeEquation, edge0, edge1;
- edge0 = N2 - N1;
- edge1 = N3 - N1;
- b3Scalar normalSign = b3Scalar(1.);
- for (int ww = 0; ww < 2; ww++)
- {
- planeEquation = normalSign * edge0.cross(edge1);
- if (planeEquation.length2() > b3Scalar(0.0001))
- {
- planeEquation.normalize();
- if (notExist(planeEquation, planeEquationsOut))
- {
- planeEquation[3] = -planeEquation.dot(N1);
-
- //check if inside, and replace supportingVertexOut if needed
- if (areVerticesBehindPlane(planeEquation, vertices, b3Scalar(0.01)))
- {
- planeEquationsOut.push_back(planeEquation);
- }
- }
- }
- normalSign = b3Scalar(-1.);
- }
- }
- }
- }
-}
-
-void b3GeometryUtil::getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut)
-{
- const int numbrushes = planeEquations.size();
- // brute force:
- for (int i = 0; i < numbrushes; i++)
- {
- const b3Vector3& N1 = planeEquations[i];
-
- for (int j = i + 1; j < numbrushes; j++)
- {
- const b3Vector3& N2 = planeEquations[j];
-
- for (int k = j + 1; k < numbrushes; k++)
- {
- const b3Vector3& N3 = planeEquations[k];
-
- b3Vector3 n2n3;
- n2n3 = N2.cross(N3);
- b3Vector3 n3n1;
- n3n1 = N3.cross(N1);
- b3Vector3 n1n2;
- n1n2 = N1.cross(N2);
-
- if ((n2n3.length2() > b3Scalar(0.0001)) &&
- (n3n1.length2() > b3Scalar(0.0001)) &&
- (n1n2.length2() > b3Scalar(0.0001)))
- {
- //point P out of 3 plane equations:
-
- // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
- //P = -------------------------------------------------------------------------
- // N1 . ( N2 * N3 )
-
- b3Scalar quotient = (N1.dot(n2n3));
- if (b3Fabs(quotient) > b3Scalar(0.000001))
- {
- quotient = b3Scalar(-1.) / quotient;
- n2n3 *= N1[3];
- n3n1 *= N2[3];
- n1n2 *= N3[3];
- b3Vector3 potentialVertex = n2n3;
- potentialVertex += n3n1;
- potentialVertex += n1n2;
- potentialVertex *= quotient;
-
- //check if inside, and replace supportingVertexOut if needed
- if (isPointInsidePlanes(planeEquations, potentialVertex, b3Scalar(0.01)))
- {
- verticesOut.push_back(potentialVertex);
- }
- }
- }
- }
- }
- }
-}
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h b/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h
deleted file mode 100644
index 967c8d67e9..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3GeometryUtil.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_GEOMETRY_UTIL_H
-#define B3_GEOMETRY_UTIL_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-///The b3GeometryUtil helper class provides a few methods to convert between plane equations and vertices.
-class b3GeometryUtil
-{
-public:
- static void getPlaneEquationsFromVertices(b3AlignedObjectArray<b3Vector3>& vertices, b3AlignedObjectArray<b3Vector3>& planeEquationsOut);
-
- static void getVerticesFromPlaneEquations(const b3AlignedObjectArray<b3Vector3>& planeEquations, b3AlignedObjectArray<b3Vector3>& verticesOut);
-
- static bool isInside(const b3AlignedObjectArray<b3Vector3>& vertices, const b3Vector3& planeNormal, b3Scalar margin);
-
- static bool isPointInsidePlanes(const b3AlignedObjectArray<b3Vector3>& planeEquations, const b3Vector3& point, b3Scalar margin);
-
- static bool areVerticesBehindPlane(const b3Vector3& planeNormal, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar margin);
-};
-
-#endif //B3_GEOMETRY_UTIL_H
diff --git a/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h b/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h
deleted file mode 100644
index 8881c9a638..0000000000
--- a/thirdparty/bullet/Bullet3Geometry/b3GrahamScan2dConvexHull.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
-#define B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-struct b3GrahamVector3 : public b3Vector3
-{
- b3GrahamVector3(const b3Vector3& org, int orgIndex)
- : b3Vector3(org),
- m_orgIndex(orgIndex)
- {
- }
- b3Scalar m_angle;
- int m_orgIndex;
-};
-
-struct b3AngleCompareFunc
-{
- b3Vector3 m_anchor;
- b3AngleCompareFunc(const b3Vector3& anchor)
- : m_anchor(anchor)
- {
- }
- bool operator()(const b3GrahamVector3& a, const b3GrahamVector3& b) const
- {
- if (a.m_angle != b.m_angle)
- return a.m_angle < b.m_angle;
- else
- {
- b3Scalar al = (a - m_anchor).length2();
- b3Scalar bl = (b - m_anchor).length2();
- if (al != bl)
- return al < bl;
- else
- {
- return a.m_orgIndex < b.m_orgIndex;
- }
- }
- }
-};
-
-inline void b3GrahamScanConvexHull2D(b3AlignedObjectArray<b3GrahamVector3>& originalPoints, b3AlignedObjectArray<b3GrahamVector3>& hull, const b3Vector3& normalAxis)
-{
- b3Vector3 axis0, axis1;
- b3PlaneSpace1(normalAxis, axis0, axis1);
-
- if (originalPoints.size() <= 1)
- {
- for (int i = 0; i < originalPoints.size(); i++)
- hull.push_back(originalPoints[0]);
- return;
- }
- //step1 : find anchor point with smallest projection on axis0 and move it to first location
- for (int i = 0; i < originalPoints.size(); i++)
- {
- // const b3Vector3& left = originalPoints[i];
- // const b3Vector3& right = originalPoints[0];
- b3Scalar projL = originalPoints[i].dot(axis0);
- b3Scalar projR = originalPoints[0].dot(axis0);
- if (projL < projR)
- {
- originalPoints.swap(0, i);
- }
- }
-
- //also precompute angles
- originalPoints[0].m_angle = -1e30f;
- for (int i = 1; i < originalPoints.size(); i++)
- {
- b3Vector3 xvec = axis0;
- b3Vector3 ar = originalPoints[i] - originalPoints[0];
- originalPoints[i].m_angle = b3Cross(xvec, ar).dot(normalAxis) / ar.length();
- }
-
- //step 2: sort all points, based on 'angle' with this anchor
- b3AngleCompareFunc comp(originalPoints[0]);
- originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
-
- int i;
- for (i = 0; i < 2; i++)
- hull.push_back(originalPoints[i]);
-
- //step 3: keep all 'convex' points and discard concave points (using back tracking)
- for (; i != originalPoints.size(); i++)
- {
- bool isConvex = false;
- while (!isConvex && hull.size() > 1)
- {
- b3Vector3& a = hull[hull.size() - 2];
- b3Vector3& b = hull[hull.size() - 1];
- isConvex = b3Cross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
- if (!isConvex)
- hull.pop_back();
- else
- hull.push_back(originalPoints[i]);
- }
- }
-}
-
-#endif //B3_GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
deleted file mode 100644
index b296992525..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-#ifndef B3_GPU_BROADPHASE_INTERFACE_H
-#define B3_GPU_BROADPHASE_INTERFACE_H
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "b3SapAabb.h"
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-
-class b3GpuBroadphaseInterface
-{
-public:
- typedef class b3GpuBroadphaseInterface*(CreateFunc)(cl_context ctx, cl_device_id device, cl_command_queue q);
-
- virtual ~b3GpuBroadphaseInterface()
- {
- }
-
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask) = 0;
-
- virtual void calculateOverlappingPairs(int maxPairs) = 0;
- virtual void calculateOverlappingPairsHost(int maxPairs) = 0;
-
- //call writeAabbsToGpu after done making all changes (createProxy etc)
- virtual void writeAabbsToGpu() = 0;
-
- virtual cl_mem getAabbBufferWS() = 0;
- virtual int getNumOverlap() = 0;
- virtual cl_mem getOverlappingPairBuffer() = 0;
-
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() = 0;
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() = 0;
-
- virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() = 0;
- virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() = 0;
- virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() = 0;
-};
-
-#endif //B3_GPU_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
deleted file mode 100644
index e714fadac3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-
-#include "b3GpuGridBroadphase.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-#include "kernels/gridBroadphaseKernels.h"
-#include "kernels/sapKernels.h"
-//#include "kernels/gridBroadphase.cl"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-
-#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
-#define B3_GRID_BROADPHASE_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl"
-
-cl_kernel kCalcHashAABB;
-cl_kernel kClearCellStart;
-cl_kernel kFindCellStart;
-cl_kernel kFindOverlappingPairs;
-cl_kernel m_copyAabbsKernel;
-cl_kernel m_sap2Kernel;
-
-//int maxPairsPerBody = 64;
-int maxBodiesPerCell = 256; //??
-
-b3GpuGridBroadphase::b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q)
- : m_context(ctx),
- m_device(device),
- m_queue(q),
- m_allAabbsGPU1(ctx, q),
- m_smallAabbsMappingGPU(ctx, q),
- m_largeAabbsMappingGPU(ctx, q),
- m_gpuPairs(ctx, q),
-
- m_hashGpu(ctx, q),
-
- m_cellStartGpu(ctx, q),
- m_paramsGPU(ctx, q)
-{
- b3Vector3 gridSize = b3MakeVector3(3, 3, 3);
- b3Vector3 invGridSize = b3MakeVector3(1.f / gridSize[0], 1.f / gridSize[1], 1.f / gridSize[2]);
-
- m_paramsCPU.m_gridSize[0] = 128;
- m_paramsCPU.m_gridSize[1] = 128;
- m_paramsCPU.m_gridSize[2] = 128;
- m_paramsCPU.m_gridSize[3] = maxBodiesPerCell;
- m_paramsCPU.setMaxBodiesPerCell(maxBodiesPerCell);
- m_paramsCPU.m_invCellSize[0] = invGridSize[0];
- m_paramsCPU.m_invCellSize[1] = invGridSize[1];
- m_paramsCPU.m_invCellSize[2] = invGridSize[2];
- m_paramsCPU.m_invCellSize[3] = 0.f;
- m_paramsGPU.push_back(m_paramsCPU);
-
- cl_int errNum = 0;
-
- {
- const char* sapSrc = sapCL;
- cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
- b3Assert(errNum == CL_SUCCESS);
- m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
- m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
- b3Assert(errNum == CL_SUCCESS);
- }
-
- {
- cl_program gridProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, gridBroadphaseCL, &errNum, "", B3_GRID_BROADPHASE_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- kCalcHashAABB = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kCalcHashAABB", &errNum, gridProg);
- b3Assert(errNum == CL_SUCCESS);
-
- kClearCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kClearCellStart", &errNum, gridProg);
- b3Assert(errNum == CL_SUCCESS);
-
- kFindCellStart = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindCellStart", &errNum, gridProg);
- b3Assert(errNum == CL_SUCCESS);
-
- kFindOverlappingPairs = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, gridBroadphaseCL, "kFindOverlappingPairs", &errNum, gridProg);
- b3Assert(errNum == CL_SUCCESS);
- }
-
- m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
-}
-b3GpuGridBroadphase::~b3GpuGridBroadphase()
-{
- clReleaseKernel(kCalcHashAABB);
- clReleaseKernel(kClearCellStart);
- clReleaseKernel(kFindCellStart);
- clReleaseKernel(kFindOverlappingPairs);
- clReleaseKernel(m_sap2Kernel);
- clReleaseKernel(m_copyAabbsKernel);
-
- delete m_sorter;
-}
-
-void b3GpuGridBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- b3SapAabb aabb;
- aabb.m_minVec = aabbMin;
- aabb.m_maxVec = aabbMax;
- aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size(); //NOT userPtr;
- m_smallAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
-
- m_allAabbsCPU1.push_back(aabb);
-}
-void b3GpuGridBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- b3SapAabb aabb;
- aabb.m_minVec = aabbMin;
- aabb.m_maxVec = aabbMax;
- aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU1.size(); //NOT userPtr;
- m_largeAabbsMappingCPU.push_back(m_allAabbsCPU1.size());
-
- m_allAabbsCPU1.push_back(aabb);
-}
-
-void b3GpuGridBroadphase::calculateOverlappingPairs(int maxPairs)
-{
- B3_PROFILE("b3GpuGridBroadphase::calculateOverlappingPairs");
-
- if (0)
- {
- calculateOverlappingPairsHost(maxPairs);
- /*
- b3AlignedObjectArray<b3Int4> cpuPairs;
- m_gpuPairs.copyToHost(cpuPairs);
- printf("host m_gpuPairs.size()=%d\n",m_gpuPairs.size());
- for (int i=0;i<m_gpuPairs.size();i++)
- {
- printf("host pair %d = %d,%d\n",i,cpuPairs[i].x,cpuPairs[i].y);
- }
- */
- return;
- }
-
- int numSmallAabbs = m_smallAabbsMappingGPU.size();
-
- b3OpenCLArray<int> pairCount(m_context, m_queue);
- pairCount.push_back(0);
- m_gpuPairs.resize(maxPairs); //numSmallAabbs*maxPairsPerBody);
-
- {
- int numLargeAabbs = m_largeAabbsMappingGPU.size();
- if (numLargeAabbs && numSmallAabbs)
- {
- B3_PROFILE("sap2Kernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_allAabbsGPU1.getBufferCL()),
- b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
- b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
- b3BufferInfoCL(m_gpuPairs.getBufferCL()),
- b3BufferInfoCL(pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLargeAabbs);
- launcher.setConst(numSmallAabbs);
- launcher.setConst(0); //axis is not used
- launcher.setConst(maxPairs);
- //@todo: use actual maximum work item sizes of the device instead of hardcoded values
- launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
-
- int numPairs = pairCount.at(0);
-
- if (numPairs > maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- }
- }
- }
-
- if (numSmallAabbs)
- {
- B3_PROFILE("gridKernel");
- m_hashGpu.resize(numSmallAabbs);
- {
- B3_PROFILE("kCalcHashAABB");
- b3LauncherCL launch(m_queue, kCalcHashAABB, "kCalcHashAABB");
- launch.setConst(numSmallAabbs);
- launch.setBuffer(m_allAabbsGPU1.getBufferCL());
- launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
- launch.setBuffer(m_hashGpu.getBufferCL());
- launch.setBuffer(this->m_paramsGPU.getBufferCL());
- launch.launch1D(numSmallAabbs);
- }
-
- m_sorter->execute(m_hashGpu);
-
- int numCells = this->m_paramsCPU.m_gridSize[0] * this->m_paramsCPU.m_gridSize[1] * this->m_paramsCPU.m_gridSize[2];
- m_cellStartGpu.resize(numCells);
- //b3AlignedObjectArray<int > cellStartCpu;
-
- {
- B3_PROFILE("kClearCellStart");
- b3LauncherCL launch(m_queue, kClearCellStart, "kClearCellStart");
- launch.setConst(numCells);
- launch.setBuffer(m_cellStartGpu.getBufferCL());
- launch.launch1D(numCells);
- //m_cellStartGpu.copyToHost(cellStartCpu);
- //printf("??\n");
- }
-
- {
- B3_PROFILE("kFindCellStart");
- b3LauncherCL launch(m_queue, kFindCellStart, "kFindCellStart");
- launch.setConst(numSmallAabbs);
- launch.setBuffer(m_hashGpu.getBufferCL());
- launch.setBuffer(m_cellStartGpu.getBufferCL());
- launch.launch1D(numSmallAabbs);
- //m_cellStartGpu.copyToHost(cellStartCpu);
- //printf("??\n");
- }
-
- {
- B3_PROFILE("kFindOverlappingPairs");
-
- b3LauncherCL launch(m_queue, kFindOverlappingPairs, "kFindOverlappingPairs");
- launch.setConst(numSmallAabbs);
- launch.setBuffer(m_allAabbsGPU1.getBufferCL());
- launch.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
- launch.setBuffer(m_hashGpu.getBufferCL());
- launch.setBuffer(m_cellStartGpu.getBufferCL());
-
- launch.setBuffer(m_paramsGPU.getBufferCL());
- //launch.setBuffer(0);
- launch.setBuffer(pairCount.getBufferCL());
- launch.setBuffer(m_gpuPairs.getBufferCL());
-
- launch.setConst(maxPairs);
- launch.launch1D(numSmallAabbs);
-
- int numPairs = pairCount.at(0);
- if (numPairs > maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- }
-
- m_gpuPairs.resize(numPairs);
-
- if (0)
- {
- b3AlignedObjectArray<b3Int4> pairsCpu;
- m_gpuPairs.copyToHost(pairsCpu);
-
- int sz = m_gpuPairs.size();
- printf("m_gpuPairs.size()=%d\n", sz);
- for (int i = 0; i < m_gpuPairs.size(); i++)
- {
- printf("pair %d = %d,%d\n", i, pairsCpu[i].x, pairsCpu[i].y);
- }
-
- printf("?!?\n");
- }
- }
- }
-
- //calculateOverlappingPairsHost(maxPairs);
-}
-void b3GpuGridBroadphase::calculateOverlappingPairsHost(int maxPairs)
-{
- m_hostPairs.resize(0);
- m_allAabbsGPU1.copyToHost(m_allAabbsCPU1);
- for (int i = 0; i < m_allAabbsCPU1.size(); i++)
- {
- for (int j = i + 1; j < m_allAabbsCPU1.size(); j++)
- {
- if (b3TestAabbAgainstAabb2(m_allAabbsCPU1[i].m_minVec, m_allAabbsCPU1[i].m_maxVec,
- m_allAabbsCPU1[j].m_minVec, m_allAabbsCPU1[j].m_maxVec))
- {
- b3Int4 pair;
- int a = m_allAabbsCPU1[j].m_minIndices[3];
- int b = m_allAabbsCPU1[i].m_minIndices[3];
- if (a <= b)
- {
- pair.x = a;
- pair.y = b; //store the original index in the unsorted aabb array
- }
- else
- {
- pair.x = b;
- pair.y = a; //store the original index in the unsorted aabb array
- }
-
- if (m_hostPairs.size() < maxPairs)
- {
- m_hostPairs.push_back(pair);
- }
- }
- }
- }
-
- m_gpuPairs.copyFromHost(m_hostPairs);
-}
-
-//call writeAabbsToGpu after done making all changes (createProxy etc)
-void b3GpuGridBroadphase::writeAabbsToGpu()
-{
- m_allAabbsGPU1.copyFromHost(m_allAabbsCPU1);
- m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
- m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
-}
-
-cl_mem b3GpuGridBroadphase::getAabbBufferWS()
-{
- return this->m_allAabbsGPU1.getBufferCL();
-}
-int b3GpuGridBroadphase::getNumOverlap()
-{
- return m_gpuPairs.size();
-}
-cl_mem b3GpuGridBroadphase::getOverlappingPairBuffer()
-{
- return m_gpuPairs.getBufferCL();
-}
-
-b3OpenCLArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsGPU()
-{
- return m_allAabbsGPU1;
-}
-
-b3AlignedObjectArray<b3SapAabb>& b3GpuGridBroadphase::getAllAabbsCPU()
-{
- return m_allAabbsCPU1;
-}
-
-b3OpenCLArray<b3Int4>& b3GpuGridBroadphase::getOverlappingPairsGPU()
-{
- return m_gpuPairs;
-}
-b3OpenCLArray<int>& b3GpuGridBroadphase::getSmallAabbIndicesGPU()
-{
- return m_smallAabbsMappingGPU;
-}
-b3OpenCLArray<int>& b3GpuGridBroadphase::getLargeAabbIndicesGPU()
-{
- return m_largeAabbsMappingGPU;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
deleted file mode 100644
index b76cb43b68..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuGridBroadphase.h
+++ /dev/null
@@ -1,80 +0,0 @@
-#ifndef B3_GPU_GRID_BROADPHASE_H
-#define B3_GPU_GRID_BROADPHASE_H
-
-#include "b3GpuBroadphaseInterface.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-
-struct b3ParamsGridBroadphaseCL
-{
- float m_invCellSize[4];
- int m_gridSize[4];
-
- int getMaxBodiesPerCell() const
- {
- return m_gridSize[3];
- }
-
- void setMaxBodiesPerCell(int maxOverlap)
- {
- m_gridSize[3] = maxOverlap;
- }
-};
-
-class b3GpuGridBroadphase : public b3GpuBroadphaseInterface
-{
-protected:
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- b3OpenCLArray<b3SapAabb> m_allAabbsGPU1;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU1;
-
- b3OpenCLArray<int> m_smallAabbsMappingGPU;
- b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
-
- b3OpenCLArray<int> m_largeAabbsMappingGPU;
- b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
-
- b3AlignedObjectArray<b3Int4> m_hostPairs;
- b3OpenCLArray<b3Int4> m_gpuPairs;
-
- b3OpenCLArray<b3SortData> m_hashGpu;
- b3OpenCLArray<int> m_cellStartGpu;
-
- b3ParamsGridBroadphaseCL m_paramsCPU;
- b3OpenCLArray<b3ParamsGridBroadphaseCL> m_paramsGPU;
-
- class b3RadixSort32CL* m_sorter;
-
-public:
- b3GpuGridBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q);
- virtual ~b3GpuGridBroadphase();
-
- static b3GpuBroadphaseInterface* CreateFunc(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuGridBroadphase(ctx, device, q);
- }
-
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
-
- virtual void calculateOverlappingPairs(int maxPairs);
- virtual void calculateOverlappingPairsHost(int maxPairs);
-
- //call writeAabbsToGpu after done making all changes (createProxy etc)
- virtual void writeAabbsToGpu();
-
- virtual cl_mem getAabbBufferWS();
- virtual int getNumOverlap();
- virtual cl_mem getOverlappingPairBuffer();
-
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU();
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU();
-
- virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
- virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
- virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
-};
-
-#endif //B3_GPU_GRID_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
deleted file mode 100644
index 616fc34f3a..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.cpp
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Initial Author Jackson Lee, 2014
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-
-#include "b3GpuParallelLinearBvh.h"
-
-b3GpuParallelLinearBvh::b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue) : m_queue(queue),
- m_radixSorter(context, device, queue),
-
- m_rootNodeIndex(context, queue),
- m_maxDistanceFromRoot(context, queue),
- m_temp(context, queue),
-
- m_internalNodeAabbs(context, queue),
- m_internalNodeLeafIndexRanges(context, queue),
- m_internalNodeChildNodes(context, queue),
- m_internalNodeParentNodes(context, queue),
-
- m_commonPrefixes(context, queue),
- m_commonPrefixLengths(context, queue),
- m_distanceFromRoot(context, queue),
-
- m_leafNodeParentNodes(context, queue),
- m_mortonCodesAndAabbIndicies(context, queue),
- m_mergedAabb(context, queue),
- m_leafNodeAabbs(context, queue),
-
- m_largeAabbs(context, queue)
-{
- m_rootNodeIndex.resize(1);
- m_maxDistanceFromRoot.resize(1);
- m_temp.resize(1);
-
- //
- const char CL_PROGRAM_PATH[] = "src/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl";
-
- const char* kernelSource = parallelLinearBvhCL; //parallelLinearBvhCL.h
- cl_int error;
- char* additionalMacros = 0;
- m_parallelLinearBvhProgram = b3OpenCLUtils::compileCLProgramFromString(context, device, kernelSource, &error, additionalMacros, CL_PROGRAM_PATH);
- b3Assert(m_parallelLinearBvhProgram);
-
- m_separateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "separateAabbs", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_separateAabbsKernel);
- m_findAllNodesMergedAabbKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findAllNodesMergedAabb", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_findAllNodesMergedAabbKernel);
- m_assignMortonCodesAndAabbIndiciesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "assignMortonCodesAndAabbIndicies", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_assignMortonCodesAndAabbIndiciesKernel);
-
- m_computeAdjacentPairCommonPrefixKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "computeAdjacentPairCommonPrefix", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_computeAdjacentPairCommonPrefixKernel);
- m_buildBinaryRadixTreeLeafNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeLeafNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_buildBinaryRadixTreeLeafNodesKernel);
- m_buildBinaryRadixTreeInternalNodesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeInternalNodes", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_buildBinaryRadixTreeInternalNodesKernel);
- m_findDistanceFromRootKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findDistanceFromRoot", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_findDistanceFromRootKernel);
- m_buildBinaryRadixTreeAabbsRecursiveKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "buildBinaryRadixTreeAabbsRecursive", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_buildBinaryRadixTreeAabbsRecursiveKernel);
-
- m_findLeafIndexRangesKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "findLeafIndexRanges", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_findLeafIndexRangesKernel);
-
- m_plbvhCalculateOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhCalculateOverlappingPairs", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_plbvhCalculateOverlappingPairsKernel);
- m_plbvhRayTraverseKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhRayTraverse", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_plbvhRayTraverseKernel);
- m_plbvhLargeAabbAabbTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbAabbTest", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_plbvhLargeAabbAabbTestKernel);
- m_plbvhLargeAabbRayTestKernel = b3OpenCLUtils::compileCLKernelFromString(context, device, kernelSource, "plbvhLargeAabbRayTest", &error, m_parallelLinearBvhProgram, additionalMacros);
- b3Assert(m_plbvhLargeAabbRayTestKernel);
-}
-
-b3GpuParallelLinearBvh::~b3GpuParallelLinearBvh()
-{
- clReleaseKernel(m_separateAabbsKernel);
- clReleaseKernel(m_findAllNodesMergedAabbKernel);
- clReleaseKernel(m_assignMortonCodesAndAabbIndiciesKernel);
-
- clReleaseKernel(m_computeAdjacentPairCommonPrefixKernel);
- clReleaseKernel(m_buildBinaryRadixTreeLeafNodesKernel);
- clReleaseKernel(m_buildBinaryRadixTreeInternalNodesKernel);
- clReleaseKernel(m_findDistanceFromRootKernel);
- clReleaseKernel(m_buildBinaryRadixTreeAabbsRecursiveKernel);
-
- clReleaseKernel(m_findLeafIndexRangesKernel);
-
- clReleaseKernel(m_plbvhCalculateOverlappingPairsKernel);
- clReleaseKernel(m_plbvhRayTraverseKernel);
- clReleaseKernel(m_plbvhLargeAabbAabbTestKernel);
- clReleaseKernel(m_plbvhLargeAabbRayTestKernel);
-
- clReleaseProgram(m_parallelLinearBvhProgram);
-}
-
-void b3GpuParallelLinearBvh::build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
- const b3OpenCLArray<int>& largeAabbIndices)
-{
- B3_PROFILE("b3ParallelLinearBvh::build()");
-
- int numLargeAabbs = largeAabbIndices.size();
- int numSmallAabbs = smallAabbIndices.size();
-
- //Since all AABBs(both large and small) are input as a contiguous array,
- //with 2 additional arrays used to indicate the indices of large and small AABBs,
- //it is necessary to separate the AABBs so that the large AABBs will not degrade the quality of the BVH.
- {
- B3_PROFILE("Separate large and small AABBs");
-
- m_largeAabbs.resize(numLargeAabbs);
- m_leafNodeAabbs.resize(numSmallAabbs);
-
- //Write large AABBs into m_largeAabbs
- {
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
- b3BufferInfoCL(largeAabbIndices.getBufferCL()),
-
- b3BufferInfoCL(m_largeAabbs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLargeAabbs);
-
- launcher.launch1D(numLargeAabbs);
- }
-
- //Write small AABBs into m_leafNodeAabbs
- {
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(worldSpaceAabbs.getBufferCL()),
- b3BufferInfoCL(smallAabbIndices.getBufferCL()),
-
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_separateAabbsKernel, "m_separateAabbsKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numSmallAabbs);
-
- launcher.launch1D(numSmallAabbs);
- }
-
- clFinish(m_queue);
- }
-
- //
- int numLeaves = numSmallAabbs; //Number of leaves in the BVH == Number of rigid bodies with small AABBs
- int numInternalNodes = numLeaves - 1;
-
- if (numLeaves < 2)
- {
- //Number of leaf nodes is checked in calculateOverlappingPairs() and testRaysAgainstBvhAabbs(),
- //so it does not matter if numLeaves == 0 and rootNodeIndex == -1
- int rootNodeIndex = numLeaves - 1;
- m_rootNodeIndex.copyFromHostPointer(&rootNodeIndex, 1);
-
- //Since the AABBs need to be rearranged(sorted) for the BVH construction algorithm,
- //m_mortonCodesAndAabbIndicies.m_value is used to map a sorted AABB index to the unsorted AABB index
- //instead of directly moving the AABBs. It needs to be set for the ray cast traversal kernel to work.
- //( m_mortonCodesAndAabbIndicies[].m_value == unsorted index == index of m_leafNodeAabbs )
- if (numLeaves == 1)
- {
- b3SortData leaf;
- leaf.m_value = 0; //1 leaf so index is always 0; leaf.m_key does not need to be set
-
- m_mortonCodesAndAabbIndicies.resize(1);
- m_mortonCodesAndAabbIndicies.copyFromHostPointer(&leaf, 1);
- }
-
- return;
- }
-
- //
- {
- m_internalNodeAabbs.resize(numInternalNodes);
- m_internalNodeLeafIndexRanges.resize(numInternalNodes);
- m_internalNodeChildNodes.resize(numInternalNodes);
- m_internalNodeParentNodes.resize(numInternalNodes);
-
- m_commonPrefixes.resize(numInternalNodes);
- m_commonPrefixLengths.resize(numInternalNodes);
- m_distanceFromRoot.resize(numInternalNodes);
-
- m_leafNodeParentNodes.resize(numLeaves);
- m_mortonCodesAndAabbIndicies.resize(numLeaves);
- m_mergedAabb.resize(numLeaves);
- }
-
- //Find the merged AABB of all small AABBs; this is used to define the size of
- //each cell in the virtual grid for the next kernel(2^10 cells in each dimension).
- {
- B3_PROFILE("Find AABB of merged nodes");
-
- m_mergedAabb.copyFromOpenCLArray(m_leafNodeAabbs); //Need to make a copy since the kernel modifies the array
-
- for (int numAabbsNeedingMerge = numLeaves; numAabbsNeedingMerge >= 2;
- numAabbsNeedingMerge = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2)
- {
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_mergedAabb.getBufferCL()) //Resulting AABB is stored in m_mergedAabb[0]
- };
-
- b3LauncherCL launcher(m_queue, m_findAllNodesMergedAabbKernel, "m_findAllNodesMergedAabbKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numAabbsNeedingMerge);
-
- launcher.launch1D(numAabbsNeedingMerge);
- }
-
- clFinish(m_queue);
- }
-
- //Insert the center of the AABBs into a virtual grid,
- //then convert the discrete grid coordinates into a morton code
- //For each element in m_mortonCodesAndAabbIndicies, set
- // m_key == morton code (value to sort by)
- // m_value == small AABB index
- {
- B3_PROFILE("Assign morton codes");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
- b3BufferInfoCL(m_mergedAabb.getBufferCL()),
- b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_assignMortonCodesAndAabbIndiciesKernel, "m_assignMortonCodesAndAabbIndiciesKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLeaves);
-
- launcher.launch1D(numLeaves);
- clFinish(m_queue);
- }
-
- //
- {
- B3_PROFILE("Sort leaves by morton codes");
-
- m_radixSorter.execute(m_mortonCodesAndAabbIndicies);
- clFinish(m_queue);
- }
-
- //
- constructBinaryRadixTree();
-
- //Since it is a sorted binary radix tree, each internal node contains a contiguous subset of leaf node indices.
- //The root node contains leaf node indices in the range [0, numLeafNodes - 1].
- //The child nodes of each node split their parent's index range into 2 contiguous halves.
- //
- //For example, if the root has indices [0, 31], its children might partition that range into [0, 11] and [12, 31].
- //The next level in the tree could then split those ranges into [0, 2], [3, 11], [12, 22], and [23, 31].
- //
- //This property can be used for optimizing calculateOverlappingPairs(), to avoid testing each AABB pair twice
- {
- B3_PROFILE("m_findLeafIndexRangesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
- b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findLeafIndexRangesKernel, "m_findLeafIndexRangesKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numInternalNodes);
-
- launcher.launch1D(numInternalNodes);
- clFinish(m_queue);
- }
-}
-
-void b3GpuParallelLinearBvh::calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs)
-{
- int maxPairs = out_overlappingPairs.size();
- b3OpenCLArray<int>& numPairsGpu = m_temp;
-
- int reset = 0;
- numPairsGpu.copyFromHostPointer(&reset, 1);
-
- //
- if (m_leafNodeAabbs.size() > 1)
- {
- B3_PROFILE("PLBVH small-small AABB test");
-
- int numQueryAabbs = m_leafNodeAabbs.size();
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
-
- b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
- b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
- b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
- b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
-
- b3BufferInfoCL(numPairsGpu.getBufferCL()),
- b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_plbvhCalculateOverlappingPairsKernel, "m_plbvhCalculateOverlappingPairsKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(maxPairs);
- launcher.setConst(numQueryAabbs);
-
- launcher.launch1D(numQueryAabbs);
- clFinish(m_queue);
- }
-
- int numLargeAabbRigids = m_largeAabbs.size();
- if (numLargeAabbRigids > 0 && m_leafNodeAabbs.size() > 0)
- {
- B3_PROFILE("PLBVH large-small AABB test");
-
- int numQueryAabbs = m_leafNodeAabbs.size();
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
- b3BufferInfoCL(m_largeAabbs.getBufferCL()),
-
- b3BufferInfoCL(numPairsGpu.getBufferCL()),
- b3BufferInfoCL(out_overlappingPairs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_plbvhLargeAabbAabbTestKernel, "m_plbvhLargeAabbAabbTestKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(maxPairs);
- launcher.setConst(numLargeAabbRigids);
- launcher.setConst(numQueryAabbs);
-
- launcher.launch1D(numQueryAabbs);
- clFinish(m_queue);
- }
-
- //
- int numPairs = -1;
- numPairsGpu.copyToHostPointer(&numPairs, 1);
- if (numPairs > maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- numPairsGpu.copyFromHostPointer(&maxPairs, 1);
- }
-
- out_overlappingPairs.resize(numPairs);
-}
-
-void b3GpuParallelLinearBvh::testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
- b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs)
-{
- B3_PROFILE("PLBVH testRaysAgainstBvhAabbs()");
-
- int numRays = rays.size();
- int maxRayRigidPairs = out_rayRigidPairs.size();
-
- int reset = 0;
- out_numRayRigidPairs.copyFromHostPointer(&reset, 1);
-
- //
- if (m_leafNodeAabbs.size() > 0)
- {
- B3_PROFILE("PLBVH ray test small AABB");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
-
- b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
- b3BufferInfoCL(m_internalNodeAabbs.getBufferCL()),
- b3BufferInfoCL(m_internalNodeLeafIndexRanges.getBufferCL()),
- b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
-
- b3BufferInfoCL(rays.getBufferCL()),
-
- b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
- b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_plbvhRayTraverseKernel, "m_plbvhRayTraverseKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(maxRayRigidPairs);
- launcher.setConst(numRays);
-
- launcher.launch1D(numRays);
- clFinish(m_queue);
- }
-
- int numLargeAabbRigids = m_largeAabbs.size();
- if (numLargeAabbRigids > 0)
- {
- B3_PROFILE("PLBVH ray test large AABB");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_largeAabbs.getBufferCL()),
- b3BufferInfoCL(rays.getBufferCL()),
-
- b3BufferInfoCL(out_numRayRigidPairs.getBufferCL()),
- b3BufferInfoCL(out_rayRigidPairs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_plbvhLargeAabbRayTestKernel, "m_plbvhLargeAabbRayTestKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLargeAabbRigids);
- launcher.setConst(maxRayRigidPairs);
- launcher.setConst(numRays);
-
- launcher.launch1D(numRays);
- clFinish(m_queue);
- }
-
- //
- int numRayRigidPairs = -1;
- out_numRayRigidPairs.copyToHostPointer(&numRayRigidPairs, 1);
-
- if (numRayRigidPairs > maxRayRigidPairs)
- b3Error("Error running out of rayRigid pairs: numRayRigidPairs = %d, maxRayRigidPairs = %d.\n", numRayRigidPairs, maxRayRigidPairs);
-}
-
-void b3GpuParallelLinearBvh::constructBinaryRadixTree()
-{
- B3_PROFILE("b3GpuParallelLinearBvh::constructBinaryRadixTree()");
-
- int numLeaves = m_leafNodeAabbs.size();
- int numInternalNodes = numLeaves - 1;
-
- //Each internal node is placed in between 2 leaf nodes.
- //By using this arrangement and computing the common prefix between
- //these 2 adjacent leaf nodes, it is possible to quickly construct a binary radix tree.
- {
- B3_PROFILE("m_computeAdjacentPairCommonPrefixKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
- b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
- b3BufferInfoCL(m_commonPrefixLengths.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_computeAdjacentPairCommonPrefixKernel, "m_computeAdjacentPairCommonPrefixKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numInternalNodes);
-
- launcher.launch1D(numInternalNodes);
- clFinish(m_queue);
- }
-
- //For each leaf node, select its parent node by
- //comparing the 2 nearest internal nodes and assign child node indices
- {
- B3_PROFILE("m_buildBinaryRadixTreeLeafNodesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
- b3BufferInfoCL(m_leafNodeParentNodes.getBufferCL()),
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeLeafNodesKernel, "m_buildBinaryRadixTreeLeafNodesKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLeaves);
-
- launcher.launch1D(numLeaves);
- clFinish(m_queue);
- }
-
- //For each internal node, perform 2 binary searches among the other internal nodes
- //to its left and right to find its potential parent nodes and assign child node indices
- {
- B3_PROFILE("m_buildBinaryRadixTreeInternalNodesKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_commonPrefixes.getBufferCL()),
- b3BufferInfoCL(m_commonPrefixLengths.getBufferCL()),
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
- b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
- b3BufferInfoCL(m_rootNodeIndex.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeInternalNodesKernel, "m_buildBinaryRadixTreeInternalNodesKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numInternalNodes);
-
- launcher.launch1D(numInternalNodes);
- clFinish(m_queue);
- }
-
- //Find the number of nodes separating each internal node and the root node
- //so that the AABBs can be set using the next kernel.
- //Also determine the maximum number of nodes separating an internal node and the root node.
- {
- B3_PROFILE("m_findDistanceFromRootKernel");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_rootNodeIndex.getBufferCL()),
- b3BufferInfoCL(m_internalNodeParentNodes.getBufferCL()),
- b3BufferInfoCL(m_maxDistanceFromRoot.getBufferCL()),
- b3BufferInfoCL(m_distanceFromRoot.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findDistanceFromRootKernel, "m_findDistanceFromRootKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numInternalNodes);
-
- launcher.launch1D(numInternalNodes);
- clFinish(m_queue);
- }
-
- //Starting from the internal nodes nearest to the leaf nodes, recursively move up
- //the tree towards the root to set the AABBs of each internal node; each internal node
- //checks its children and merges their AABBs
- {
- B3_PROFILE("m_buildBinaryRadixTreeAabbsRecursiveKernel");
-
- int maxDistanceFromRoot = -1;
- {
- B3_PROFILE("copy maxDistanceFromRoot to CPU");
- m_maxDistanceFromRoot.copyToHostPointer(&maxDistanceFromRoot, 1);
- clFinish(m_queue);
- }
-
- for (int distanceFromRoot = maxDistanceFromRoot; distanceFromRoot >= 0; --distanceFromRoot)
- {
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_distanceFromRoot.getBufferCL()),
- b3BufferInfoCL(m_mortonCodesAndAabbIndicies.getBufferCL()),
- b3BufferInfoCL(m_internalNodeChildNodes.getBufferCL()),
- b3BufferInfoCL(m_leafNodeAabbs.getBufferCL()),
- b3BufferInfoCL(m_internalNodeAabbs.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_buildBinaryRadixTreeAabbsRecursiveKernel, "m_buildBinaryRadixTreeAabbsRecursiveKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(maxDistanceFromRoot);
- launcher.setConst(distanceFromRoot);
- launcher.setConst(numInternalNodes);
-
- //It may seem inefficent to launch a thread for each internal node when a
- //much smaller number of nodes is actually processed, but this is actually
- //faster than determining the exact nodes that are ready to merge their child AABBs.
- launcher.launch1D(numInternalNodes);
- }
-
- clFinish(m_queue);
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
deleted file mode 100644
index b390775129..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Initial Author Jackson Lee, 2014
-
-#ifndef B3_GPU_PARALLEL_LINEAR_BVH_H
-#define B3_GPU_PARALLEL_LINEAR_BVH_H
-
-//#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-
-#include "Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h"
-
-#define b3Int64 cl_long
-
-///@brief GPU Parallel Linearized Bounding Volume Heirarchy(LBVH) that is reconstructed every frame
-///@remarks
-///See presentation in docs/b3GpuParallelLinearBvh.pdf for algorithm details.
-///@par
-///Related papers: \n
-///"Fast BVH Construction on GPUs" [Lauterbach et al. 2009] \n
-///"Maximizing Parallelism in the Construction of BVHs, Octrees, and k-d trees" [Karras 2012] \n
-///@par
-///The basic algorithm for building the BVH as presented in [Lauterbach et al. 2009] consists of 4 stages:
-/// - [fully parallel] Assign morton codes for each AABB using its center (after quantizing the AABB centers into a virtual grid)
-/// - [fully parallel] Sort morton codes
-/// - [somewhat parallel] Build binary radix tree (assign parent/child pointers for internal nodes of the BVH)
-/// - [somewhat parallel] Set internal node AABBs
-///@par
-///[Karras 2012] improves on the algorithm by introducing fully parallel methods for the last 2 stages.
-///The BVH implementation here shares many concepts with [Karras 2012], but a different method is used for constructing the tree.
-///Instead of searching for the child nodes of each internal node, we search for the parent node of each node.
-///Additionally, a non-atomic traversal that starts from the leaf nodes and moves towards the root node is used to set the AABBs.
-class b3GpuParallelLinearBvh
-{
- cl_command_queue m_queue;
-
- cl_program m_parallelLinearBvhProgram;
-
- cl_kernel m_separateAabbsKernel;
- cl_kernel m_findAllNodesMergedAabbKernel;
- cl_kernel m_assignMortonCodesAndAabbIndiciesKernel;
-
- //Binary radix tree construction kernels
- cl_kernel m_computeAdjacentPairCommonPrefixKernel;
- cl_kernel m_buildBinaryRadixTreeLeafNodesKernel;
- cl_kernel m_buildBinaryRadixTreeInternalNodesKernel;
- cl_kernel m_findDistanceFromRootKernel;
- cl_kernel m_buildBinaryRadixTreeAabbsRecursiveKernel;
-
- cl_kernel m_findLeafIndexRangesKernel;
-
- //Traversal kernels
- cl_kernel m_plbvhCalculateOverlappingPairsKernel;
- cl_kernel m_plbvhRayTraverseKernel;
- cl_kernel m_plbvhLargeAabbAabbTestKernel;
- cl_kernel m_plbvhLargeAabbRayTestKernel;
-
- b3RadixSort32CL m_radixSorter;
-
- //1 element
- b3OpenCLArray<int> m_rootNodeIndex; //Most significant bit(0x80000000) is set to indicate internal node
- b3OpenCLArray<int> m_maxDistanceFromRoot; //Max number of internal nodes between an internal node and the root node
- b3OpenCLArray<int> m_temp; //Used to hold the number of pairs in calculateOverlappingPairs()
-
- //1 element per internal node (number_of_internal_nodes == number_of_leaves - 1)
- b3OpenCLArray<b3SapAabb> m_internalNodeAabbs;
- b3OpenCLArray<b3Int2> m_internalNodeLeafIndexRanges; //x == min leaf index, y == max leaf index
- b3OpenCLArray<b3Int2> m_internalNodeChildNodes; //x == left child, y == right child; msb(0x80000000) is set to indicate internal node
- b3OpenCLArray<int> m_internalNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
-
- //1 element per internal node; for binary radix tree construction
- b3OpenCLArray<b3Int64> m_commonPrefixes;
- b3OpenCLArray<int> m_commonPrefixLengths;
- b3OpenCLArray<int> m_distanceFromRoot; //Number of internal nodes between this node and the root
-
- //1 element per leaf node (leaf nodes only include small AABBs)
- b3OpenCLArray<int> m_leafNodeParentNodes; //For parent node index, msb(0x80000000) is not set since it is always internal
- b3OpenCLArray<b3SortData> m_mortonCodesAndAabbIndicies; //m_key == morton code, m_value == aabb index in m_leafNodeAabbs
- b3OpenCLArray<b3SapAabb> m_mergedAabb; //m_mergedAabb[0] contains the merged AABB of all leaf nodes
- b3OpenCLArray<b3SapAabb> m_leafNodeAabbs; //Contains only small AABBs
-
- //1 element per large AABB, which is not stored in the BVH
- b3OpenCLArray<b3SapAabb> m_largeAabbs;
-
-public:
- b3GpuParallelLinearBvh(cl_context context, cl_device_id device, cl_command_queue queue);
- virtual ~b3GpuParallelLinearBvh();
-
- ///Must be called before any other function
- void build(const b3OpenCLArray<b3SapAabb>& worldSpaceAabbs, const b3OpenCLArray<int>& smallAabbIndices,
- const b3OpenCLArray<int>& largeAabbIndices);
-
- ///calculateOverlappingPairs() uses the worldSpaceAabbs parameter of b3GpuParallelLinearBvh::build() as the query AABBs.
- ///@param out_overlappingPairs The size() of this array is used to determine the max number of pairs.
- ///If the number of overlapping pairs is < out_overlappingPairs.size(), out_overlappingPairs is resized.
- void calculateOverlappingPairs(b3OpenCLArray<b3Int4>& out_overlappingPairs);
-
- ///@param out_numRigidRayPairs Array of length 1; contains the number of detected ray-rigid AABB intersections;
- ///this value may be greater than out_rayRigidPairs.size() if out_rayRigidPairs is not large enough.
- ///@param out_rayRigidPairs Contains an array of rays intersecting rigid AABBs; x == ray index, y == rigid body index.
- ///If the size of this array is insufficient to hold all ray-rigid AABB intersections, additional intersections are discarded.
- void testRaysAgainstBvhAabbs(const b3OpenCLArray<b3RayInfo>& rays,
- b3OpenCLArray<int>& out_numRayRigidPairs, b3OpenCLArray<b3Int2>& out_rayRigidPairs);
-
-private:
- void constructBinaryRadixTree();
-};
-
-#endif
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
deleted file mode 100644
index 62ea7a32df..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Initial Author Jackson Lee, 2014
-
-#include "b3GpuParallelLinearBvhBroadphase.h"
-
-b3GpuParallelLinearBvhBroadphase::b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue) : m_plbvh(context, device, queue),
-
- m_overlappingPairsGpu(context, queue),
-
- m_aabbsGpu(context, queue),
- m_smallAabbsMappingGpu(context, queue),
- m_largeAabbsMappingGpu(context, queue)
-{
-}
-
-void b3GpuParallelLinearBvhBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- int newAabbIndex = m_aabbsCpu.size();
-
- b3SapAabb aabb;
- aabb.m_minVec = aabbMin;
- aabb.m_maxVec = aabbMax;
-
- aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = newAabbIndex;
-
- m_smallAabbsMappingCpu.push_back(newAabbIndex);
-
- m_aabbsCpu.push_back(aabb);
-}
-void b3GpuParallelLinearBvhBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- int newAabbIndex = m_aabbsCpu.size();
-
- b3SapAabb aabb;
- aabb.m_minVec = aabbMin;
- aabb.m_maxVec = aabbMax;
-
- aabb.m_minIndices[3] = userPtr;
- aabb.m_signedMaxIndices[3] = newAabbIndex;
-
- m_largeAabbsMappingCpu.push_back(newAabbIndex);
-
- m_aabbsCpu.push_back(aabb);
-}
-
-void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairs(int maxPairs)
-{
- //Reconstruct BVH
- m_plbvh.build(m_aabbsGpu, m_smallAabbsMappingGpu, m_largeAabbsMappingGpu);
-
- //
- m_overlappingPairsGpu.resize(maxPairs);
- m_plbvh.calculateOverlappingPairs(m_overlappingPairsGpu);
-}
-void b3GpuParallelLinearBvhBroadphase::calculateOverlappingPairsHost(int maxPairs)
-{
- b3Assert(0); //CPU version not implemented
-}
-
-void b3GpuParallelLinearBvhBroadphase::writeAabbsToGpu()
-{
- m_aabbsGpu.copyFromHost(m_aabbsCpu);
- m_smallAabbsMappingGpu.copyFromHost(m_smallAabbsMappingCpu);
- m_largeAabbsMappingGpu.copyFromHost(m_largeAabbsMappingCpu);
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
deleted file mode 100644
index dda0eea7be..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvhBroadphase.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Initial Author Jackson Lee, 2014
-
-#ifndef B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
-#define B3_GPU_PARALLEL_LINEAR_BVH_BROADPHASE_H
-
-#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
-
-#include "b3GpuParallelLinearBvh.h"
-
-class b3GpuParallelLinearBvhBroadphase : public b3GpuBroadphaseInterface
-{
- b3GpuParallelLinearBvh m_plbvh;
-
- b3OpenCLArray<b3Int4> m_overlappingPairsGpu;
-
- b3OpenCLArray<b3SapAabb> m_aabbsGpu;
- b3OpenCLArray<int> m_smallAabbsMappingGpu;
- b3OpenCLArray<int> m_largeAabbsMappingGpu;
-
- b3AlignedObjectArray<b3SapAabb> m_aabbsCpu;
- b3AlignedObjectArray<int> m_smallAabbsMappingCpu;
- b3AlignedObjectArray<int> m_largeAabbsMappingCpu;
-
-public:
- b3GpuParallelLinearBvhBroadphase(cl_context context, cl_device_id device, cl_command_queue queue);
- virtual ~b3GpuParallelLinearBvhBroadphase() {}
-
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
-
- virtual void calculateOverlappingPairs(int maxPairs);
- virtual void calculateOverlappingPairsHost(int maxPairs);
-
- //call writeAabbsToGpu after done making all changes (createProxy etc)
- virtual void writeAabbsToGpu();
-
- virtual int getNumOverlap() { return m_overlappingPairsGpu.size(); }
- virtual cl_mem getOverlappingPairBuffer() { return m_overlappingPairsGpu.getBufferCL(); }
-
- virtual cl_mem getAabbBufferWS() { return m_aabbsGpu.getBufferCL(); }
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU() { return m_aabbsGpu; }
-
- virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU() { return m_overlappingPairsGpu; }
- virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU() { return m_smallAabbsMappingGpu; }
- virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU() { return m_largeAabbsMappingGpu; }
-
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU() { return m_aabbsCpu; }
-
- static b3GpuBroadphaseInterface* CreateFunc(cl_context context, cl_device_id device, cl_command_queue queue)
- {
- return new b3GpuParallelLinearBvhBroadphase(context, device, queue);
- }
-};
-
-#endif
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
deleted file mode 100644
index 4126d03ed0..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.cpp
+++ /dev/null
@@ -1,1298 +0,0 @@
-
-bool searchIncremental3dSapOnGpu = true;
-#include <limits.h>
-#include "b3GpuSapBroadphase.h"
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "kernels/sapKernels.h"
-
-#include "Bullet3Common/b3MinMax.h"
-
-#define B3_BROADPHASE_SAP_PATH "src/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl"
-
-/*
-
-
-
-
-
-
- b3OpenCLArray<int> m_pairCount;
-
-
- b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
-
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
- {
- return m_allAabbsGPU;
- }
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
- {
- return m_allAabbsCPU;
- }
-
- b3OpenCLArray<b3Vector3> m_sum;
- b3OpenCLArray<b3Vector3> m_sum2;
- b3OpenCLArray<b3Vector3> m_dst;
-
- b3OpenCLArray<int> m_smallAabbsMappingGPU;
- b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
-
- b3OpenCLArray<int> m_largeAabbsMappingGPU;
- b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
-
-
- b3OpenCLArray<b3Int4> m_overlappingPairs;
-
- //temporary gpu work memory
- b3OpenCLArray<b3SortData> m_gpuSmallSortData;
- b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
-
- class b3PrefixScanFloat4CL* m_prefixScanFloat4;
- */
-
-b3GpuSapBroadphase::b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType)
- : m_context(ctx),
- m_device(device),
- m_queue(q),
-
- m_objectMinMaxIndexGPUaxis0(ctx, q),
- m_objectMinMaxIndexGPUaxis1(ctx, q),
- m_objectMinMaxIndexGPUaxis2(ctx, q),
- m_objectMinMaxIndexGPUaxis0prev(ctx, q),
- m_objectMinMaxIndexGPUaxis1prev(ctx, q),
- m_objectMinMaxIndexGPUaxis2prev(ctx, q),
- m_sortedAxisGPU0(ctx, q),
- m_sortedAxisGPU1(ctx, q),
- m_sortedAxisGPU2(ctx, q),
- m_sortedAxisGPU0prev(ctx, q),
- m_sortedAxisGPU1prev(ctx, q),
- m_sortedAxisGPU2prev(ctx, q),
- m_addedHostPairsGPU(ctx, q),
- m_removedHostPairsGPU(ctx, q),
- m_addedCountGPU(ctx, q),
- m_removedCountGPU(ctx, q),
- m_currentBuffer(-1),
- m_pairCount(ctx, q),
- m_allAabbsGPU(ctx, q),
- m_sum(ctx, q),
- m_sum2(ctx, q),
- m_dst(ctx, q),
- m_smallAabbsMappingGPU(ctx, q),
- m_largeAabbsMappingGPU(ctx, q),
- m_overlappingPairs(ctx, q),
- m_gpuSmallSortData(ctx, q),
- m_gpuSmallSortedAabbs(ctx, q)
-{
- const char* sapSrc = sapCL;
-
- cl_int errNum = 0;
-
- b3Assert(m_context);
- b3Assert(m_device);
- cl_program sapProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, sapSrc, &errNum, "", B3_BROADPHASE_SAP_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- b3Assert(errNum == CL_SUCCESS);
-#ifndef __APPLE__
- m_prefixScanFloat4 = new b3PrefixScanFloat4CL(m_context, m_device, m_queue);
-#else
- m_prefixScanFloat4 = 0;
-#endif
- m_sapKernel = 0;
-
- switch (kernelType)
- {
- case B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU:
- {
- m_sapKernel = 0;
- break;
- }
- case B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU:
- {
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBruteForce", &errNum, sapProg);
- break;
- }
-
- case B3_GPU_SAP_KERNEL_ORIGINAL:
- {
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelOriginal", &errNum, sapProg);
- break;
- }
- case B3_GPU_SAP_KERNEL_BARRIER:
- {
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelBarrier", &errNum, sapProg);
- break;
- }
- case B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY:
- {
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
- break;
- }
-
- default:
- {
- m_sapKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelLocalSharedMemory", &errNum, sapProg);
- b3Error("Unknown 3D GPU SAP provided, fallback to computePairsKernelLocalSharedMemory");
- }
- };
-
- m_sap2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "computePairsKernelTwoArrays", &errNum, sapProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_prepareSumVarianceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "prepareSumVarianceKernel", &errNum, sapProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_flipFloatKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "flipFloatKernel", &errNum, sapProg);
-
- m_copyAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "copyAabbsKernel", &errNum, sapProg);
-
- m_scatterKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, sapSrc, "scatterKernel", &errNum, sapProg);
-
- m_sorter = new b3RadixSort32CL(m_context, m_device, m_queue);
-}
-
-b3GpuSapBroadphase::~b3GpuSapBroadphase()
-{
- delete m_sorter;
- delete m_prefixScanFloat4;
-
- clReleaseKernel(m_scatterKernel);
- clReleaseKernel(m_flipFloatKernel);
- clReleaseKernel(m_copyAabbsKernel);
- clReleaseKernel(m_sapKernel);
- clReleaseKernel(m_sap2Kernel);
- clReleaseKernel(m_prepareSumVarianceKernel);
-}
-
-/// conservative test for overlap between two aabbs
-static bool TestAabbAgainstAabb2(const b3Vector3& aabbMin1, const b3Vector3& aabbMax1,
- const b3Vector3& aabbMin2, const b3Vector3& aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
- overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
- overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
- return overlap;
-}
-
-//http://stereopsis.com/radix.html
-static unsigned int FloatFlip(float fl)
-{
- unsigned int f = *(unsigned int*)&fl;
- unsigned int mask = -(int)(f >> 31) | 0x80000000;
- return f ^ mask;
-};
-
-void b3GpuSapBroadphase::init3dSap()
-{
- if (m_currentBuffer < 0)
- {
- m_allAabbsGPU.copyToHost(m_allAabbsCPU);
-
- m_currentBuffer = 0;
- for (int axis = 0; axis < 3; axis++)
- {
- for (int buf = 0; buf < 2; buf++)
- {
- int totalNumAabbs = m_allAabbsCPU.size();
- int numEndPoints = 2 * totalNumAabbs;
- m_sortedAxisCPU[axis][buf].resize(numEndPoints);
-
- if (buf == m_currentBuffer)
- {
- for (int i = 0; i < totalNumAabbs; i++)
- {
- m_sortedAxisCPU[axis][buf][i * 2].m_key = FloatFlip(m_allAabbsCPU[i].m_min[axis]) - 1;
- m_sortedAxisCPU[axis][buf][i * 2].m_value = i * 2;
- m_sortedAxisCPU[axis][buf][i * 2 + 1].m_key = FloatFlip(m_allAabbsCPU[i].m_max[axis]) + 1;
- m_sortedAxisCPU[axis][buf][i * 2 + 1].m_value = i * 2 + 1;
- }
- }
- }
- }
-
- for (int axis = 0; axis < 3; axis++)
- {
- m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
- }
-
- for (int axis = 0; axis < 3; axis++)
- {
- //int totalNumAabbs = m_allAabbsCPU.size();
- int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
- m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(numEndPoints);
- for (int i = 0; i < numEndPoints; i++)
- {
- int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
- int newDest = destIndex / 2;
- if (destIndex & 1)
- {
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
- }
- else
- {
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
- }
- }
- }
- }
-}
-
-static bool b3PairCmp(const b3Int4& p, const b3Int4& q)
-{
- return ((p.x < q.x) || ((p.x == q.x) && (p.y < q.y)));
-}
-
-static bool operator==(const b3Int4& a, const b3Int4& b)
-{
- return a.x == b.x && a.y == b.y;
-};
-
-static bool operator<(const b3Int4& a, const b3Int4& b)
-{
- return a.x < b.x || (a.x == b.x && a.y < b.y);
-};
-
-static bool operator>(const b3Int4& a, const b3Int4& b)
-{
- return a.x > b.x || (a.x == b.x && a.y > b.y);
-};
-
-b3AlignedObjectArray<b3Int4> addedHostPairs;
-b3AlignedObjectArray<b3Int4> removedHostPairs;
-
-b3AlignedObjectArray<b3SapAabb> preAabbs;
-
-void b3GpuSapBroadphase::calculateOverlappingPairsHostIncremental3Sap()
-{
- //static int framepje = 0;
- //printf("framepje=%d\n",framepje++);
-
- B3_PROFILE("calculateOverlappingPairsHostIncremental3Sap");
-
- addedHostPairs.resize(0);
- removedHostPairs.resize(0);
-
- b3Assert(m_currentBuffer >= 0);
-
- {
- preAabbs.resize(m_allAabbsCPU.size());
- for (int i = 0; i < preAabbs.size(); i++)
- {
- preAabbs[i] = m_allAabbsCPU[i];
- }
- }
-
- if (m_currentBuffer < 0)
- return;
- {
- B3_PROFILE("m_allAabbsGPU.copyToHost");
- m_allAabbsGPU.copyToHost(m_allAabbsCPU);
- }
-
- b3AlignedObjectArray<b3Int4> allPairs;
- {
- B3_PROFILE("m_overlappingPairs.copyToHost");
- m_overlappingPairs.copyToHost(allPairs);
- }
- if (0)
- {
- {
- printf("ab[40].min=%f,%f,%f,ab[40].max=%f,%f,%f\n",
- m_allAabbsCPU[40].m_min[0], m_allAabbsCPU[40].m_min[1], m_allAabbsCPU[40].m_min[2],
- m_allAabbsCPU[40].m_max[0], m_allAabbsCPU[40].m_max[1], m_allAabbsCPU[40].m_max[2]);
- }
-
- {
- printf("ab[53].min=%f,%f,%f,ab[53].max=%f,%f,%f\n",
- m_allAabbsCPU[53].m_min[0], m_allAabbsCPU[53].m_min[1], m_allAabbsCPU[53].m_min[2],
- m_allAabbsCPU[53].m_max[0], m_allAabbsCPU[53].m_max[1], m_allAabbsCPU[53].m_max[2]);
- }
-
- {
- b3Int4 newPair;
- newPair.x = 40;
- newPair.y = 53;
- int index = allPairs.findBinarySearch(newPair);
- printf("hasPair(40,53)=%d out of %d\n", index, allPairs.size());
-
- {
- int overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[40].m_min, (const b3Vector3&)m_allAabbsCPU[40].m_max, (const b3Vector3&)m_allAabbsCPU[53].m_min, (const b3Vector3&)m_allAabbsCPU[53].m_max);
- printf("overlap=%d\n", overlap);
- }
-
- if (preAabbs.size())
- {
- int prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[40].m_min, (const b3Vector3&)preAabbs[40].m_max, (const b3Vector3&)preAabbs[53].m_min, (const b3Vector3&)preAabbs[53].m_max);
- printf("prevoverlap=%d\n", prevOverlap);
- }
- else
- {
- printf("unknown prevoverlap\n");
- }
- }
- }
-
- if (0)
- {
- for (int i = 0; i < m_allAabbsCPU.size(); i++)
- {
- //printf("aabb[%d] min=%f,%f,%f max=%f,%f,%f\n",i,m_allAabbsCPU[i].m_min[0],m_allAabbsCPU[i].m_min[1],m_allAabbsCPU[i].m_min[2], m_allAabbsCPU[i].m_max[0],m_allAabbsCPU[i].m_max[1],m_allAabbsCPU[i].m_max[2]);
- }
-
- for (int axis = 0; axis < 3; axis++)
- {
- for (int buf = 0; buf < 2; buf++)
- {
- b3Assert(m_sortedAxisCPU[axis][buf].size() == m_allAabbsCPU.size() * 2);
- }
- }
- }
-
- m_currentBuffer = 1 - m_currentBuffer;
-
- int totalNumAabbs = m_allAabbsCPU.size();
-
- {
- B3_PROFILE("assign m_sortedAxisCPU(FloatFlip)");
- for (int i = 0; i < totalNumAabbs; i++)
- {
- unsigned int keyMin[3];
- unsigned int keyMax[3];
- for (int axis = 0; axis < 3; axis++)
- {
- float vmin = m_allAabbsCPU[i].m_min[axis];
- float vmax = m_allAabbsCPU[i].m_max[axis];
- keyMin[axis] = FloatFlip(vmin);
- keyMax[axis] = FloatFlip(vmax);
-
- m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_key = keyMin[axis] - 1;
- m_sortedAxisCPU[axis][m_currentBuffer][i * 2].m_value = i * 2;
- m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_key = keyMax[axis] + 1;
- m_sortedAxisCPU[axis][m_currentBuffer][i * 2 + 1].m_value = i * 2 + 1;
- }
- //printf("aabb[%d] min=%u,%u,%u max %u,%u,%u\n", i,keyMin[0],keyMin[1],keyMin[2],keyMax[0],keyMax[1],keyMax[2]);
- }
- }
-
- {
- B3_PROFILE("sort m_sortedAxisCPU");
- for (int axis = 0; axis < 3; axis++)
- m_sorter->executeHost(m_sortedAxisCPU[axis][m_currentBuffer]);
- }
-
-#if 0
- if (0)
- {
- for (int axis=0;axis<3;axis++)
- {
- //printf("axis %d\n",axis);
- for (int i=0;i<m_sortedAxisCPU[axis][m_currentBuffer].size();i++)
- {
- //int key = m_sortedAxisCPU[axis][m_currentBuffer][i].m_key;
- //int value = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
- //printf("[%d]=%d\n",i,value);
- }
-
- }
- }
-#endif
-
- {
- B3_PROFILE("assign m_objectMinMaxIndexCPU");
- for (int axis = 0; axis < 3; axis++)
- {
- int totalNumAabbs = m_allAabbsCPU.size();
- int numEndPoints = m_sortedAxisCPU[axis][m_currentBuffer].size();
- m_objectMinMaxIndexCPU[axis][m_currentBuffer].resize(totalNumAabbs);
- for (int i = 0; i < numEndPoints; i++)
- {
- int destIndex = m_sortedAxisCPU[axis][m_currentBuffer][i].m_value;
- int newDest = destIndex / 2;
- if (destIndex & 1)
- {
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].y = i;
- }
- else
- {
- m_objectMinMaxIndexCPU[axis][m_currentBuffer][newDest].x = i;
- }
- }
- }
- }
-
-#if 0
- if (0)
- {
- printf("==========================\n");
- for (int axis=0;axis<3;axis++)
- {
- unsigned int curMinIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].x;
- unsigned int curMaxIndex40 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][40].y;
- unsigned int prevMaxIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].y;
- unsigned int prevMinIndex40 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][40].x;
-
- int dmin40 = curMinIndex40 - prevMinIndex40;
- int dmax40 = curMinIndex40 - prevMinIndex40;
- printf("axis %d curMinIndex40=%d prevMinIndex40=%d\n",axis,curMinIndex40, prevMinIndex40);
- printf("axis %d curMaxIndex40=%d prevMaxIndex40=%d\n",axis,curMaxIndex40, prevMaxIndex40);
- }
- printf(".........................\n");
- for (int axis=0;axis<3;axis++)
- {
- unsigned int curMinIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].x;
- unsigned int curMaxIndex53 = m_objectMinMaxIndexCPU[axis][m_currentBuffer][53].y;
- unsigned int prevMaxIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].y;
- unsigned int prevMinIndex53 = m_objectMinMaxIndexCPU[axis][1-m_currentBuffer][53].x;
-
- int dmin40 = curMinIndex53 - prevMinIndex53;
- int dmax40 = curMinIndex53 - prevMinIndex53;
- printf("axis %d curMinIndex53=%d prevMinIndex53=%d\n",axis,curMinIndex53, prevMinIndex53);
- printf("axis %d curMaxIndex53=%d prevMaxIndex53=%d\n",axis,curMaxIndex53, prevMaxIndex53);
- }
-
- }
-#endif
-
- int a = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
- int b = m_objectMinMaxIndexCPU[1][m_currentBuffer].size();
- int c = m_objectMinMaxIndexCPU[2][m_currentBuffer].size();
- b3Assert(a == b);
- b3Assert(b == c);
- /*
- if (searchIncremental3dSapOnGpu)
- {
- B3_PROFILE("computePairsIncremental3dSapKernelGPU");
- int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
- int maxCapacity = 1024*1024;
- {
- B3_PROFILE("copy from host");
- m_objectMinMaxIndexGPUaxis0.copyFromHost(m_objectMinMaxIndexCPU[0][m_currentBuffer]);
- m_objectMinMaxIndexGPUaxis1.copyFromHost(m_objectMinMaxIndexCPU[1][m_currentBuffer]);
- m_objectMinMaxIndexGPUaxis2.copyFromHost(m_objectMinMaxIndexCPU[2][m_currentBuffer]);
- m_objectMinMaxIndexGPUaxis0prev.copyFromHost(m_objectMinMaxIndexCPU[0][1-m_currentBuffer]);
- m_objectMinMaxIndexGPUaxis1prev.copyFromHost(m_objectMinMaxIndexCPU[1][1-m_currentBuffer]);
- m_objectMinMaxIndexGPUaxis2prev.copyFromHost(m_objectMinMaxIndexCPU[2][1-m_currentBuffer]);
-
- m_sortedAxisGPU0.copyFromHost(m_sortedAxisCPU[0][m_currentBuffer]);
- m_sortedAxisGPU1.copyFromHost(m_sortedAxisCPU[1][m_currentBuffer]);
- m_sortedAxisGPU2.copyFromHost(m_sortedAxisCPU[2][m_currentBuffer]);
- m_sortedAxisGPU0prev.copyFromHost(m_sortedAxisCPU[0][1-m_currentBuffer]);
- m_sortedAxisGPU1prev.copyFromHost(m_sortedAxisCPU[1][1-m_currentBuffer]);
- m_sortedAxisGPU2prev.copyFromHost(m_sortedAxisCPU[2][1-m_currentBuffer]);
-
-
- m_addedHostPairsGPU.resize(maxCapacity);
- m_removedHostPairsGPU.resize(maxCapacity);
-
- m_addedCountGPU.resize(0);
- m_addedCountGPU.push_back(0);
- m_removedCountGPU.resize(0);
- m_removedCountGPU.push_back(0);
- }
-
- {
- B3_PROFILE("launch1D");
- b3LauncherCL launcher(m_queue, m_computePairsIncremental3dSapKernel,"m_computePairsIncremental3dSapKernel");
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis0.getBufferCL());
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis1.getBufferCL());
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis2.getBufferCL());
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis0prev.getBufferCL());
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis1prev.getBufferCL());
- launcher.setBuffer(m_objectMinMaxIndexGPUaxis2prev.getBufferCL());
-
- launcher.setBuffer(m_sortedAxisGPU0.getBufferCL());
- launcher.setBuffer(m_sortedAxisGPU1.getBufferCL());
- launcher.setBuffer(m_sortedAxisGPU2.getBufferCL());
- launcher.setBuffer(m_sortedAxisGPU0prev.getBufferCL());
- launcher.setBuffer(m_sortedAxisGPU1prev.getBufferCL());
- launcher.setBuffer(m_sortedAxisGPU2prev.getBufferCL());
-
-
- launcher.setBuffer(m_addedHostPairsGPU.getBufferCL());
- launcher.setBuffer(m_removedHostPairsGPU.getBufferCL());
- launcher.setBuffer(m_addedCountGPU.getBufferCL());
- launcher.setBuffer(m_removedCountGPU.getBufferCL());
- launcher.setConst(maxCapacity);
- launcher.setConst( numObjects);
- launcher.launch1D( numObjects);
- clFinish(m_queue);
- }
-
- {
- B3_PROFILE("copy to host");
- int addedCountGPU = m_addedCountGPU.at(0);
- m_addedHostPairsGPU.resize(addedCountGPU);
- m_addedHostPairsGPU.copyToHost(addedHostPairs);
-
- //printf("addedCountGPU=%d\n",addedCountGPU);
- int removedCountGPU = m_removedCountGPU.at(0);
- m_removedHostPairsGPU.resize(removedCountGPU);
- m_removedHostPairsGPU.copyToHost(removedHostPairs);
- //printf("removedCountGPU=%d\n",removedCountGPU);
-
- }
-
-
-
- }
- else
- */
- {
- int numObjects = m_objectMinMaxIndexCPU[0][m_currentBuffer].size();
-
- B3_PROFILE("actual search");
- for (int i = 0; i < numObjects; i++)
- {
- //int numObjects = m_objectMinMaxIndexCPU[axis][m_currentBuffer].size();
- //int checkObjects[]={40,53};
- //int numCheckObjects = sizeof(checkObjects)/sizeof(int);
-
- //for (int a=0;a<numCheckObjects ;a++)
-
- for (int axis = 0; axis < 3; axis++)
- {
- //int i = checkObjects[a];
-
- unsigned int curMinIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].x;
- unsigned int curMaxIndex = m_objectMinMaxIndexCPU[axis][m_currentBuffer][i].y;
- unsigned int prevMinIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].x;
- int dmin = curMinIndex - prevMinIndex;
-
- unsigned int prevMaxIndex = m_objectMinMaxIndexCPU[axis][1 - m_currentBuffer][i].y;
-
- int dmax = curMaxIndex - prevMaxIndex;
- if (dmin != 0)
- {
- //printf("for object %d, dmin=%d\n",i,dmin);
- }
- if (dmax != 0)
- {
- //printf("for object %d, dmax=%d\n",i,dmax);
- }
- for (int otherbuffer = 0; otherbuffer < 2; otherbuffer++)
- {
- if (dmin != 0)
- {
- int stepMin = dmin < 0 ? -1 : 1;
- for (int j = prevMinIndex; j != curMinIndex; j += stepMin)
- {
- int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
- int otherIndex = otherIndex2 / 2;
- if (otherIndex != i)
- {
- bool otherIsMax = ((otherIndex2 & 1) != 0);
-
- if (otherIsMax)
- {
- //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
- //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
-
- bool overlap = true;
-
- for (int ax = 0; ax < 3; ax++)
- {
- if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
- overlap = false;
- }
-
- // b3Assert(overlap2==overlap);
-
- bool prevOverlap = true;
-
- for (int ax = 0; ax < 3; ax++)
- {
- if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
- prevOverlap = false;
- }
-
- //b3Assert(overlap==overlap2);
-
- if (dmin < 0)
- {
- if (overlap && !prevOverlap)
- {
- //add a pair
- b3Int4 newPair;
- if (i <= otherIndex)
- {
- newPair.x = i;
- newPair.y = otherIndex;
- }
- else
- {
- newPair.x = otherIndex;
- newPair.y = i;
- }
- addedHostPairs.push_back(newPair);
- }
- }
- else
- {
- if (!overlap && prevOverlap)
- {
- //remove a pair
- b3Int4 removedPair;
- if (i <= otherIndex)
- {
- removedPair.x = i;
- removedPair.y = otherIndex;
- }
- else
- {
- removedPair.x = otherIndex;
- removedPair.y = i;
- }
- removedHostPairs.push_back(removedPair);
- }
- } //otherisMax
- } //if (dmin<0)
- } //if (otherIndex!=i)
- } //for (int j=
- }
-
- if (dmax != 0)
- {
- int stepMax = dmax < 0 ? -1 : 1;
- for (int j = prevMaxIndex; j != curMaxIndex; j += stepMax)
- {
- int otherIndex2 = m_sortedAxisCPU[axis][otherbuffer][j].y;
- int otherIndex = otherIndex2 / 2;
- if (otherIndex != i)
- {
- //bool otherIsMin = ((otherIndex2&1)==0);
- //if (otherIsMin)
- {
- //bool overlap = TestAabbAgainstAabb2((const b3Vector3&)m_allAabbsCPU[i].m_min, (const b3Vector3&)m_allAabbsCPU[i].m_max,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_min,(const b3Vector3&)m_allAabbsCPU[otherIndex].m_max);
- //bool prevOverlap = TestAabbAgainstAabb2((const b3Vector3&)preAabbs[i].m_min, (const b3Vector3&)preAabbs[i].m_max,(const b3Vector3&)preAabbs[otherIndex].m_min,(const b3Vector3&)preAabbs[otherIndex].m_max);
-
- bool overlap = true;
-
- for (int ax = 0; ax < 3; ax++)
- {
- if ((m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][m_currentBuffer][otherIndex].x))
- overlap = false;
- }
- //b3Assert(overlap2==overlap);
-
- bool prevOverlap = true;
-
- for (int ax = 0; ax < 3; ax++)
- {
- if ((m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].x > m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].y) ||
- (m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][i].y < m_objectMinMaxIndexCPU[ax][1 - m_currentBuffer][otherIndex].x))
- prevOverlap = false;
- }
-
- if (dmax > 0)
- {
- if (overlap && !prevOverlap)
- {
- //add a pair
- b3Int4 newPair;
- if (i <= otherIndex)
- {
- newPair.x = i;
- newPair.y = otherIndex;
- }
- else
- {
- newPair.x = otherIndex;
- newPair.y = i;
- }
- addedHostPairs.push_back(newPair);
- }
- }
- else
- {
- if (!overlap && prevOverlap)
- {
- //if (otherIndex2&1==0) -> min?
- //remove a pair
- b3Int4 removedPair;
- if (i <= otherIndex)
- {
- removedPair.x = i;
- removedPair.y = otherIndex;
- }
- else
- {
- removedPair.x = otherIndex;
- removedPair.y = i;
- }
- removedHostPairs.push_back(removedPair);
- }
- }
-
- } //if (dmin<0)
- } //if (otherIndex!=i)
- } //for (int j=
- }
- } //for (int otherbuffer
- } //for (int axis=0;
- } //for (int i=0;i<numObjects
- }
-
- //remove duplicates and add/remove then to existing m_overlappingPairs
-
- {
- {
- B3_PROFILE("sort allPairs");
- allPairs.quickSort(b3PairCmp);
- }
- {
- B3_PROFILE("sort addedHostPairs");
- addedHostPairs.quickSort(b3PairCmp);
- }
- {
- B3_PROFILE("sort removedHostPairs");
- removedHostPairs.quickSort(b3PairCmp);
- }
- }
-
- b3Int4 prevPair;
- prevPair.x = -1;
- prevPair.y = -1;
-
- int uniqueRemovedPairs = 0;
-
- b3AlignedObjectArray<int> removedPositions;
-
- {
- B3_PROFILE("actual removing");
- for (int i = 0; i < removedHostPairs.size(); i++)
- {
- b3Int4 removedPair = removedHostPairs[i];
- if ((removedPair.x != prevPair.x) || (removedPair.y != prevPair.y))
- {
- int index1 = allPairs.findBinarySearch(removedPair);
-
- //#ifdef _DEBUG
-
- int index2 = allPairs.findLinearSearch(removedPair);
- b3Assert(index1 == index2);
-
- //b3Assert(index1!=allPairs.size());
- if (index1 < allPairs.size())
- //#endif//_DEBUG
- {
- uniqueRemovedPairs++;
- removedPositions.push_back(index1);
- {
- //printf("framepje(%d) remove pair(%d):%d,%d\n",framepje,i,removedPair.x,removedPair.y);
- }
- }
- }
- prevPair = removedPair;
- }
-
- if (uniqueRemovedPairs)
- {
- for (int i = 0; i < removedPositions.size(); i++)
- {
- allPairs[removedPositions[i]].x = INT_MAX;
- allPairs[removedPositions[i]].y = INT_MAX;
- }
- allPairs.quickSort(b3PairCmp);
- allPairs.resize(allPairs.size() - uniqueRemovedPairs);
- }
- }
- //if (uniqueRemovedPairs)
- // printf("uniqueRemovedPairs=%d\n",uniqueRemovedPairs);
- //printf("removedHostPairs.size = %d\n",removedHostPairs.size());
-
- prevPair.x = -1;
- prevPair.y = -1;
-
- int uniqueAddedPairs = 0;
- b3AlignedObjectArray<b3Int4> actualAddedPairs;
-
- {
- B3_PROFILE("actual adding");
- for (int i = 0; i < addedHostPairs.size(); i++)
- {
- b3Int4 newPair = addedHostPairs[i];
- if ((newPair.x != prevPair.x) || (newPair.y != prevPair.y))
- {
- //#ifdef _DEBUG
- int index1 = allPairs.findBinarySearch(newPair);
-
- int index2 = allPairs.findLinearSearch(newPair);
- b3Assert(index1 == index2);
-
- b3Assert(index1 == allPairs.size());
- if (index1 != allPairs.size())
- {
- printf("??\n");
- }
-
- if (index1 == allPairs.size())
- //#endif //_DEBUG
- {
- uniqueAddedPairs++;
- actualAddedPairs.push_back(newPair);
- }
- }
- prevPair = newPair;
- }
- for (int i = 0; i < actualAddedPairs.size(); i++)
- {
- //printf("framepje (%d), new pair(%d):%d,%d\n",framepje,i,actualAddedPairs[i].x,actualAddedPairs[i].y);
- allPairs.push_back(actualAddedPairs[i]);
- }
- }
-
- //if (uniqueAddedPairs)
- // printf("uniqueAddedPairs=%d\n", uniqueAddedPairs);
-
- {
- B3_PROFILE("m_overlappingPairs.copyFromHost");
- m_overlappingPairs.copyFromHost(allPairs);
- }
-}
-
-void b3GpuSapBroadphase::calculateOverlappingPairsHost(int maxPairs)
-{
- //test
- // if (m_currentBuffer>=0)
- // return calculateOverlappingPairsHostIncremental3Sap();
-
- b3Assert(m_allAabbsCPU.size() == m_allAabbsGPU.size());
- m_allAabbsGPU.copyToHost(m_allAabbsCPU);
-
- int axis = 0;
- {
- B3_PROFILE("CPU compute best variance axis");
- b3Vector3 s = b3MakeVector3(0, 0, 0), s2 = b3MakeVector3(0, 0, 0);
- int numRigidBodies = m_smallAabbsMappingCPU.size();
-
- for (int i = 0; i < numRigidBodies; i++)
- {
- b3SapAabb aabb = this->m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
-
- b3Vector3 maxAabb = b3MakeVector3(aabb.m_max[0], aabb.m_max[1], aabb.m_max[2]);
- b3Vector3 minAabb = b3MakeVector3(aabb.m_min[0], aabb.m_min[1], aabb.m_min[2]);
- b3Vector3 centerAabb = (maxAabb + minAabb) * 0.5f;
-
- s += centerAabb;
- s2 += centerAabb * centerAabb;
- }
- b3Vector3 v = s2 - (s * s) / (float)numRigidBodies;
-
- if (v[1] > v[0])
- axis = 1;
- if (v[2] > v[axis])
- axis = 2;
- }
-
- b3AlignedObjectArray<b3Int4> hostPairs;
-
- {
- int numSmallAabbs = m_smallAabbsMappingCPU.size();
- for (int i = 0; i < numSmallAabbs; i++)
- {
- b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
- //float reference = smallAabbi.m_max[axis];
-
- for (int j = i + 1; j < numSmallAabbs; j++)
- {
- b3SapAabb smallAabbj = m_allAabbsCPU[m_smallAabbsMappingCPU[j]];
-
- if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
- (b3Vector3&)smallAabbj.m_min, (b3Vector3&)smallAabbj.m_max))
- {
- b3Int4 pair;
- int a = smallAabbi.m_minIndices[3];
- int b = smallAabbj.m_minIndices[3];
- if (a <= b)
- {
- pair.x = a; //store the original index in the unsorted aabb array
- pair.y = b;
- }
- else
- {
- pair.x = b; //store the original index in the unsorted aabb array
- pair.y = a;
- }
- hostPairs.push_back(pair);
- }
- }
- }
- }
-
- {
- int numSmallAabbs = m_smallAabbsMappingCPU.size();
- for (int i = 0; i < numSmallAabbs; i++)
- {
- b3SapAabb smallAabbi = m_allAabbsCPU[m_smallAabbsMappingCPU[i]];
-
- //float reference = smallAabbi.m_max[axis];
- int numLargeAabbs = m_largeAabbsMappingCPU.size();
-
- for (int j = 0; j < numLargeAabbs; j++)
- {
- b3SapAabb largeAabbj = m_allAabbsCPU[m_largeAabbsMappingCPU[j]];
- if (TestAabbAgainstAabb2((b3Vector3&)smallAabbi.m_min, (b3Vector3&)smallAabbi.m_max,
- (b3Vector3&)largeAabbj.m_min, (b3Vector3&)largeAabbj.m_max))
- {
- b3Int4 pair;
- int a = largeAabbj.m_minIndices[3];
- int b = smallAabbi.m_minIndices[3];
- if (a <= b)
- {
- pair.x = a;
- pair.y = b; //store the original index in the unsorted aabb array
- }
- else
- {
- pair.x = b;
- pair.y = a; //store the original index in the unsorted aabb array
- }
-
- hostPairs.push_back(pair);
- }
- }
- }
- }
-
- if (hostPairs.size() > maxPairs)
- {
- hostPairs.resize(maxPairs);
- }
-
- if (hostPairs.size())
- {
- m_overlappingPairs.copyFromHost(hostPairs);
- }
- else
- {
- m_overlappingPairs.resize(0);
- }
-
- //init3dSap();
-}
-
-void b3GpuSapBroadphase::reset()
-{
- m_allAabbsGPU.resize(0);
- m_allAabbsCPU.resize(0);
-
- m_smallAabbsMappingGPU.resize(0);
- m_smallAabbsMappingCPU.resize(0);
-
- m_pairCount.resize(0);
-
- m_largeAabbsMappingGPU.resize(0);
- m_largeAabbsMappingCPU.resize(0);
-}
-
-void b3GpuSapBroadphase::calculateOverlappingPairs(int maxPairs)
-{
- if (m_sapKernel == 0)
- {
- calculateOverlappingPairsHost(maxPairs);
- return;
- }
-
- //if (m_currentBuffer>=0)
- // return calculateOverlappingPairsHostIncremental3Sap();
-
- //calculateOverlappingPairsHost(maxPairs);
-
- B3_PROFILE("GPU 1-axis SAP calculateOverlappingPairs");
-
- int axis = 0;
-
- {
- //bool syncOnHost = false;
-
- int numSmallAabbs = m_smallAabbsMappingCPU.size();
- if (m_prefixScanFloat4 && numSmallAabbs)
- {
- B3_PROFILE("GPU compute best variance axis");
-
- if (m_dst.size() != (numSmallAabbs + 1))
- {
- m_dst.resize(numSmallAabbs + 128);
- m_sum.resize(numSmallAabbs + 128);
- m_sum2.resize(numSmallAabbs + 128);
- m_sum.at(numSmallAabbs) = b3MakeVector3(0, 0, 0); //slow?
- m_sum2.at(numSmallAabbs) = b3MakeVector3(0, 0, 0); //slow?
- }
-
- b3LauncherCL launcher(m_queue, m_prepareSumVarianceKernel, "m_prepareSumVarianceKernel");
- launcher.setBuffer(m_allAabbsGPU.getBufferCL());
-
- launcher.setBuffer(m_smallAabbsMappingGPU.getBufferCL());
- launcher.setBuffer(m_sum.getBufferCL());
- launcher.setBuffer(m_sum2.getBufferCL());
- launcher.setConst(numSmallAabbs);
- int num = numSmallAabbs;
- launcher.launch1D(num);
-
- b3Vector3 s;
- b3Vector3 s2;
- m_prefixScanFloat4->execute(m_sum, m_dst, numSmallAabbs + 1, &s);
- m_prefixScanFloat4->execute(m_sum2, m_dst, numSmallAabbs + 1, &s2);
-
- b3Vector3 v = s2 - (s * s) / (float)numSmallAabbs;
-
- if (v[1] > v[0])
- axis = 1;
- if (v[2] > v[axis])
- axis = 2;
- }
-
- m_gpuSmallSortData.resize(numSmallAabbs);
-
-#if 1
- if (m_smallAabbsMappingGPU.size())
- {
- B3_PROFILE("flipFloatKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
- b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
- b3BufferInfoCL(m_gpuSmallSortData.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_flipFloatKernel, "m_flipFloatKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numSmallAabbs);
- launcher.setConst(axis);
-
- int num = numSmallAabbs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- if (m_gpuSmallSortData.size())
- {
- B3_PROFILE("gpu radix sort");
- m_sorter->execute(m_gpuSmallSortData);
- clFinish(m_queue);
- }
-
- m_gpuSmallSortedAabbs.resize(numSmallAabbs);
- if (numSmallAabbs)
- {
- B3_PROFILE("scatterKernel");
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_allAabbsGPU.getBufferCL(), true),
- b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL(), true),
- b3BufferInfoCL(m_gpuSmallSortData.getBufferCL(), true),
- b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_scatterKernel, "m_scatterKernel ");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numSmallAabbs);
- int num = numSmallAabbs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- m_overlappingPairs.resize(maxPairs);
-
- m_pairCount.resize(0);
- m_pairCount.push_back(0);
- int numPairs = 0;
-
- {
- int numLargeAabbs = m_largeAabbsMappingGPU.size();
- if (numLargeAabbs && numSmallAabbs)
- {
- //@todo
- B3_PROFILE("sap2Kernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_allAabbsGPU.getBufferCL()),
- b3BufferInfoCL(m_largeAabbsMappingGPU.getBufferCL()),
- b3BufferInfoCL(m_smallAabbsMappingGPU.getBufferCL()),
- b3BufferInfoCL(m_overlappingPairs.getBufferCL()),
- b3BufferInfoCL(m_pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sap2Kernel, "m_sap2Kernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numLargeAabbs);
- launcher.setConst(numSmallAabbs);
- launcher.setConst(axis);
- launcher.setConst(maxPairs);
- //@todo: use actual maximum work item sizes of the device instead of hardcoded values
- launcher.launch2D(numLargeAabbs, numSmallAabbs, 4, 64);
-
- numPairs = m_pairCount.at(0);
- if (numPairs > maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- }
- }
- }
- if (m_gpuSmallSortedAabbs.size())
- {
- B3_PROFILE("sapKernel");
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_gpuSmallSortedAabbs.getBufferCL()), b3BufferInfoCL(m_overlappingPairs.getBufferCL()), b3BufferInfoCL(m_pairCount.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_sapKernel, "m_sapKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numSmallAabbs);
- launcher.setConst(axis);
- launcher.setConst(maxPairs);
-
- int num = numSmallAabbs;
-#if 0
- int buffSize = launcher.getSerializationBufferSize();
- unsigned char* buf = new unsigned char[buffSize+sizeof(int)];
- for (int i=0;i<buffSize+1;i++)
- {
- unsigned char* ptr = (unsigned char*)&buf[i];
- *ptr = 0xff;
- }
- int actualWrite = launcher.serializeArguments(buf,buffSize);
-
- unsigned char* cptr = (unsigned char*)&buf[buffSize];
- // printf("buf[buffSize] = %d\n",*cptr);
-
- assert(buf[buffSize]==0xff);//check for buffer overrun
- int* ptr = (int*)&buf[buffSize];
-
- *ptr = num;
-
- FILE* f = fopen("m_sapKernelArgs.bin","wb");
- fwrite(buf,buffSize+sizeof(int),1,f);
- fclose(f);
-#endif //
-
- launcher.launch1D(num);
- clFinish(m_queue);
-
- numPairs = m_pairCount.at(0);
- if (numPairs > maxPairs)
- {
- b3Error("Error running out of pairs: numPairs = %d, maxPairs = %d.\n", numPairs, maxPairs);
- numPairs = maxPairs;
- m_pairCount.resize(0);
- m_pairCount.push_back(maxPairs);
- }
- }
-
-#else
- int numPairs = 0;
-
- b3LauncherCL launcher(m_queue, m_sapKernel);
-
- const char* fileName = "m_sapKernelArgs.bin";
- FILE* f = fopen(fileName, "rb");
- if (f)
- {
- int sizeInBytes = 0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
- fread(buf, sizeInBytes, 1, f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
- int num = *(int*)&buf[serializedBytes];
- launcher.launch1D(num);
-
- b3OpenCLArray<int> pairCount(m_context, m_queue);
- int numElements = launcher.m_arrays[2]->size() / sizeof(int);
- pairCount.setFromOpenCLBuffer(launcher.m_arrays[2]->getBufferCL(), numElements);
- numPairs = pairCount.at(0);
- //printf("overlapping pairs = %d\n",numPairs);
- b3AlignedObjectArray<b3Int4> hostOoverlappingPairs;
- b3OpenCLArray<b3Int4> tmpGpuPairs(m_context, m_queue);
- tmpGpuPairs.setFromOpenCLBuffer(launcher.m_arrays[1]->getBufferCL(), numPairs);
-
- tmpGpuPairs.copyToHost(hostOoverlappingPairs);
- m_overlappingPairs.copyFromHost(hostOoverlappingPairs);
- //printf("hello %d\n", m_overlappingPairs.size());
- free(buf);
- fclose(f);
- }
- else
- {
- printf("error: cannot find file %s\n", fileName);
- }
-
- clFinish(m_queue);
-
-#endif
-
- m_overlappingPairs.resize(numPairs);
-
- } //B3_PROFILE("GPU_RADIX SORT");
- //init3dSap();
-}
-
-void b3GpuSapBroadphase::writeAabbsToGpu()
-{
- m_smallAabbsMappingGPU.copyFromHost(m_smallAabbsMappingCPU);
- m_largeAabbsMappingGPU.copyFromHost(m_largeAabbsMappingCPU);
-
- m_allAabbsGPU.copyFromHost(m_allAabbsCPU); //might not be necessary, the 'setupGpuAabbsFull' already takes care of this
-}
-
-void b3GpuSapBroadphase::createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- int index = userPtr;
- b3SapAabb aabb;
- for (int i = 0; i < 4; i++)
- {
- aabb.m_min[i] = aabbMin[i];
- aabb.m_max[i] = aabbMax[i];
- }
- aabb.m_minIndices[3] = index;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
- m_largeAabbsMappingCPU.push_back(m_allAabbsCPU.size());
-
- m_allAabbsCPU.push_back(aabb);
-}
-
-void b3GpuSapBroadphase::createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask)
-{
- int index = userPtr;
- b3SapAabb aabb;
- for (int i = 0; i < 4; i++)
- {
- aabb.m_min[i] = aabbMin[i];
- aabb.m_max[i] = aabbMax[i];
- }
- aabb.m_minIndices[3] = index;
- aabb.m_signedMaxIndices[3] = m_allAabbsCPU.size();
- m_smallAabbsMappingCPU.push_back(m_allAabbsCPU.size());
-
- m_allAabbsCPU.push_back(aabb);
-}
-
-cl_mem b3GpuSapBroadphase::getAabbBufferWS()
-{
- return m_allAabbsGPU.getBufferCL();
-}
-
-int b3GpuSapBroadphase::getNumOverlap()
-{
- return m_overlappingPairs.size();
-}
-cl_mem b3GpuSapBroadphase::getOverlappingPairBuffer()
-{
- return m_overlappingPairs.getBufferCL();
-}
-
-b3OpenCLArray<b3Int4>& b3GpuSapBroadphase::getOverlappingPairsGPU()
-{
- return m_overlappingPairs;
-}
-b3OpenCLArray<int>& b3GpuSapBroadphase::getSmallAabbIndicesGPU()
-{
- return m_smallAabbsMappingGPU;
-}
-b3OpenCLArray<int>& b3GpuSapBroadphase::getLargeAabbIndicesGPU()
-{
- return m_largeAabbsMappingGPU;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
deleted file mode 100644
index d17590b14a..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3GpuSapBroadphase.h
+++ /dev/null
@@ -1,143 +0,0 @@
-#ifndef B3_GPU_SAP_BROADPHASE_H
-#define B3_GPU_SAP_BROADPHASE_H
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
-class b3Vector3;
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-
-#include "b3SapAabb.h"
-#include "Bullet3Common/shared/b3Int2.h"
-
-#include "b3GpuBroadphaseInterface.h"
-
-class b3GpuSapBroadphase : public b3GpuBroadphaseInterface
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
- cl_kernel m_flipFloatKernel;
- cl_kernel m_scatterKernel;
- cl_kernel m_copyAabbsKernel;
- cl_kernel m_sapKernel;
- cl_kernel m_sap2Kernel;
- cl_kernel m_prepareSumVarianceKernel;
-
- class b3RadixSort32CL* m_sorter;
-
- ///test for 3d SAP
- b3AlignedObjectArray<b3SortData> m_sortedAxisCPU[3][2];
- b3AlignedObjectArray<b3UnsignedInt2> m_objectMinMaxIndexCPU[3][2];
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis0prev;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis1prev;
- b3OpenCLArray<b3UnsignedInt2> m_objectMinMaxIndexGPUaxis2prev;
-
- b3OpenCLArray<b3SortData> m_sortedAxisGPU0;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU1;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU2;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU0prev;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU1prev;
- b3OpenCLArray<b3SortData> m_sortedAxisGPU2prev;
-
- b3OpenCLArray<b3Int4> m_addedHostPairsGPU;
- b3OpenCLArray<b3Int4> m_removedHostPairsGPU;
- b3OpenCLArray<int> m_addedCountGPU;
- b3OpenCLArray<int> m_removedCountGPU;
-
- int m_currentBuffer;
-
-public:
- b3OpenCLArray<int> m_pairCount;
-
- b3OpenCLArray<b3SapAabb> m_allAabbsGPU;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
-
- virtual b3OpenCLArray<b3SapAabb>& getAllAabbsGPU()
- {
- return m_allAabbsGPU;
- }
- virtual b3AlignedObjectArray<b3SapAabb>& getAllAabbsCPU()
- {
- return m_allAabbsCPU;
- }
-
- b3OpenCLArray<b3Vector3> m_sum;
- b3OpenCLArray<b3Vector3> m_sum2;
- b3OpenCLArray<b3Vector3> m_dst;
-
- b3OpenCLArray<int> m_smallAabbsMappingGPU;
- b3AlignedObjectArray<int> m_smallAabbsMappingCPU;
-
- b3OpenCLArray<int> m_largeAabbsMappingGPU;
- b3AlignedObjectArray<int> m_largeAabbsMappingCPU;
-
- b3OpenCLArray<b3Int4> m_overlappingPairs;
-
- //temporary gpu work memory
- b3OpenCLArray<b3SortData> m_gpuSmallSortData;
- b3OpenCLArray<b3SapAabb> m_gpuSmallSortedAabbs;
-
- class b3PrefixScanFloat4CL* m_prefixScanFloat4;
-
- enum b3GpuSapKernelType
- {
- B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU = 1,
- B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU,
- B3_GPU_SAP_KERNEL_ORIGINAL,
- B3_GPU_SAP_KERNEL_BARRIER,
- B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY
- };
-
- b3GpuSapBroadphase(cl_context ctx, cl_device_id device, cl_command_queue q, b3GpuSapKernelType kernelType = B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
- virtual ~b3GpuSapBroadphase();
-
- static b3GpuBroadphaseInterface* CreateFuncBruteForceCpu(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_CPU);
- }
-
- static b3GpuBroadphaseInterface* CreateFuncBruteForceGpu(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BRUTE_FORCE_GPU);
- }
-
- static b3GpuBroadphaseInterface* CreateFuncOriginal(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_ORIGINAL);
- }
- static b3GpuBroadphaseInterface* CreateFuncBarrier(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_BARRIER);
- }
- static b3GpuBroadphaseInterface* CreateFuncLocalMemory(cl_context ctx, cl_device_id device, cl_command_queue q)
- {
- return new b3GpuSapBroadphase(ctx, device, q, B3_GPU_SAP_KERNEL_LOCAL_SHARED_MEMORY);
- }
-
- virtual void calculateOverlappingPairs(int maxPairs);
- virtual void calculateOverlappingPairsHost(int maxPairs);
-
- void reset();
-
- void init3dSap();
- virtual void calculateOverlappingPairsHostIncremental3Sap();
-
- virtual void createProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
- virtual void createLargeProxy(const b3Vector3& aabbMin, const b3Vector3& aabbMax, int userPtr, int collisionFilterGroup, int collisionFilterMask);
-
- //call writeAabbsToGpu after done making all changes (createProxy etc)
- virtual void writeAabbsToGpu();
-
- virtual cl_mem getAabbBufferWS();
- virtual int getNumOverlap();
- virtual cl_mem getOverlappingPairBuffer();
-
- virtual b3OpenCLArray<b3Int4>& getOverlappingPairsGPU();
- virtual b3OpenCLArray<int>& getSmallAabbIndicesGPU();
- virtual b3OpenCLArray<int>& getLargeAabbIndicesGPU();
-};
-
-#endif //B3_GPU_SAP_BROADPHASE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
deleted file mode 100644
index 60570f2605..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef B3_SAP_AABB_H
-#define B3_SAP_AABB_H
-
-#include "Bullet3Common/b3Scalar.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-
-///just make sure that the b3Aabb is 16-byte aligned
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3SapAabb : public b3Aabb{
-
- };
-
-#endif //B3_SAP_AABB_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl
deleted file mode 100644
index ded4796d33..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphase.cl
+++ /dev/null
@@ -1,216 +0,0 @@
-
-
-int getPosHash(int4 gridPos, __global float4* pParams)
-{
- int4 gridDim = *((__global int4*)(pParams + 1));
- gridPos.x &= gridDim.x - 1;
- gridPos.y &= gridDim.y - 1;
- gridPos.z &= gridDim.z - 1;
- int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;
- return hash;
-}
-
-int4 getGridPos(float4 worldPos, __global float4* pParams)
-{
- int4 gridPos;
- int4 gridDim = *((__global int4*)(pParams + 1));
- gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);
- gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);
- gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);
- return gridPos;
-}
-
-
-// calculate grid hash value for each body using its AABB
-__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )
-{
- int index = get_global_id(0);
- if(index >= numObjects)
- {
- return;
- }
- float4 bbMin = allpAABB[smallAabbMapping[index]*2];
- float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];
- float4 pos;
- pos.x = (bbMin.x + bbMax.x) * 0.5f;
- pos.y = (bbMin.y + bbMax.y) * 0.5f;
- pos.z = (bbMin.z + bbMax.z) * 0.5f;
- pos.w = 0.f;
- // get address in grid
- int4 gridPos = getGridPos(pos, pParams);
- int gridHash = getPosHash(gridPos, pParams);
- // store grid hash and body index
- int2 hashVal;
- hashVal.x = gridHash;
- hashVal.y = index;
- pHash[index] = hashVal;
-}
-
-__kernel void kClearCellStart( int numCells,
- __global int* pCellStart )
-{
- int index = get_global_id(0);
- if(index >= numCells)
- {
- return;
- }
- pCellStart[index] = -1;
-}
-
-__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )
-{
- __local int sharedHash[513];
- int index = get_global_id(0);
- int2 sortedData;
-
- if(index < numObjects)
- {
- sortedData = pHash[index];
- // Load hash data into shared memory so that we can look
- // at neighboring body's hash value without loading
- // two hash values per thread
- sharedHash[get_local_id(0) + 1] = sortedData.x;
- if((index > 0) && (get_local_id(0) == 0))
- {
- // first thread in block must load neighbor body hash
- sharedHash[0] = pHash[index-1].x;
- }
- }
- barrier(CLK_LOCAL_MEM_FENCE);
- if(index < numObjects)
- {
- if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))
- {
- cellStart[sortedData.x] = index;
- }
- }
-}
-
-int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)
-{
- return (min0.x <= max1.x)&& (min1.x <= max0.x) &&
- (min0.y <= max1.y)&& (min1.y <= max0.y) &&
- (min0.z <= max1.z)&& (min1.z <= max0.z);
-}
-
-
-
-
-//search for AABB 'index' against other AABBs' in this cell
-void findPairsInCell( int numObjects,
- int4 gridPos,
- int index,
- __global int2* pHash,
- __global int* pCellStart,
- __global float4* allpAABB,
- __global const int* smallAabbMapping,
- __global float4* pParams,
- volatile __global int* pairCount,
- __global int4* pPairBuff2,
- int maxPairs
- )
-{
- int4 pGridDim = *((__global int4*)(pParams + 1));
- int maxBodiesPerCell = pGridDim.w;
- int gridHash = getPosHash(gridPos, pParams);
- // get start of bucket for this cell
- int bucketStart = pCellStart[gridHash];
- if (bucketStart == -1)
- {
- return; // cell empty
- }
- // iterate over bodies in this cell
- int2 sortedData = pHash[index];
- int unsorted_indx = sortedData.y;
- float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];
- float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
- int handleIndex = as_int(min0.w);
-
- int bucketEnd = bucketStart + maxBodiesPerCell;
- bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;
- for(int index2 = bucketStart; index2 < bucketEnd; index2++)
- {
- int2 cellData = pHash[index2];
- if (cellData.x != gridHash)
- {
- break; // no longer in same bucket
- }
- int unsorted_indx2 = cellData.y;
- //if (unsorted_indx2 < unsorted_indx) // check not colliding with self
- if (unsorted_indx2 != unsorted_indx) // check not colliding with self
- {
- float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];
- float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];
- if(testAABBOverlap(min0, max0, min1, max1))
- {
- if (pairCount)
- {
- int handleIndex2 = as_int(min1.w);
- if (handleIndex<handleIndex2)
- {
- int curPair = atomic_add(pairCount,1);
- if (curPair<maxPairs)
- {
- int4 newpair;
- newpair.x = handleIndex;
- newpair.y = handleIndex2;
- newpair.z = -1;
- newpair.w = -1;
- pPairBuff2[curPair] = newpair;
- }
- }
-
- }
- }
- }
- }
-}
-
-__kernel void kFindOverlappingPairs( int numObjects,
- __global float4* allpAABB,
- __global const int* smallAabbMapping,
- __global int2* pHash,
- __global int* pCellStart,
- __global float4* pParams ,
- volatile __global int* pairCount,
- __global int4* pPairBuff2,
- int maxPairs
- )
-
-{
- int index = get_global_id(0);
- if(index >= numObjects)
- {
- return;
- }
- int2 sortedData = pHash[index];
- int unsorted_indx = sortedData.y;
- float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];
- float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];
- float4 pos;
- pos.x = (bbMin.x + bbMax.x) * 0.5f;
- pos.y = (bbMin.y + bbMax.y) * 0.5f;
- pos.z = (bbMin.z + bbMax.z) * 0.5f;
- // get address in grid
- int4 gridPosA = getGridPos(pos, pParams);
- int4 gridPosB;
- // examine only neighbouring cells
- for(int z=-1; z<=1; z++)
- {
- gridPosB.z = gridPosA.z + z;
- for(int y=-1; y<=1; y++)
- {
- gridPosB.y = gridPosA.y + y;
- for(int x=-1; x<=1; x++)
- {
- gridPosB.x = gridPosA.x + x;
- findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);
- }
- }
- }
-}
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
deleted file mode 100644
index 0185417786..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/gridBroadphaseKernels.h
+++ /dev/null
@@ -1,198 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* gridBroadphaseCL =
- "int getPosHash(int4 gridPos, __global float4* pParams)\n"
- "{\n"
- " int4 gridDim = *((__global int4*)(pParams + 1));\n"
- " gridPos.x &= gridDim.x - 1;\n"
- " gridPos.y &= gridDim.y - 1;\n"
- " gridPos.z &= gridDim.z - 1;\n"
- " int hash = gridPos.z * gridDim.y * gridDim.x + gridPos.y * gridDim.x + gridPos.x;\n"
- " return hash;\n"
- "} \n"
- "int4 getGridPos(float4 worldPos, __global float4* pParams)\n"
- "{\n"
- " int4 gridPos;\n"
- " int4 gridDim = *((__global int4*)(pParams + 1));\n"
- " gridPos.x = (int)floor(worldPos.x * pParams[0].x) & (gridDim.x - 1);\n"
- " gridPos.y = (int)floor(worldPos.y * pParams[0].y) & (gridDim.y - 1);\n"
- " gridPos.z = (int)floor(worldPos.z * pParams[0].z) & (gridDim.z - 1);\n"
- " return gridPos;\n"
- "}\n"
- "// calculate grid hash value for each body using its AABB\n"
- "__kernel void kCalcHashAABB(int numObjects, __global float4* allpAABB, __global const int* smallAabbMapping, __global int2* pHash, __global float4* pParams )\n"
- "{\n"
- " int index = get_global_id(0);\n"
- " if(index >= numObjects)\n"
- " {\n"
- " return;\n"
- " }\n"
- " float4 bbMin = allpAABB[smallAabbMapping[index]*2];\n"
- " float4 bbMax = allpAABB[smallAabbMapping[index]*2 + 1];\n"
- " float4 pos;\n"
- " pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
- " pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
- " pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
- " pos.w = 0.f;\n"
- " // get address in grid\n"
- " int4 gridPos = getGridPos(pos, pParams);\n"
- " int gridHash = getPosHash(gridPos, pParams);\n"
- " // store grid hash and body index\n"
- " int2 hashVal;\n"
- " hashVal.x = gridHash;\n"
- " hashVal.y = index;\n"
- " pHash[index] = hashVal;\n"
- "}\n"
- "__kernel void kClearCellStart( int numCells, \n"
- " __global int* pCellStart )\n"
- "{\n"
- " int index = get_global_id(0);\n"
- " if(index >= numCells)\n"
- " {\n"
- " return;\n"
- " }\n"
- " pCellStart[index] = -1;\n"
- "}\n"
- "__kernel void kFindCellStart(int numObjects, __global int2* pHash, __global int* cellStart )\n"
- "{\n"
- " __local int sharedHash[513];\n"
- " int index = get_global_id(0);\n"
- " int2 sortedData;\n"
- " if(index < numObjects)\n"
- " {\n"
- " sortedData = pHash[index];\n"
- " // Load hash data into shared memory so that we can look \n"
- " // at neighboring body's hash value without loading\n"
- " // two hash values per thread\n"
- " sharedHash[get_local_id(0) + 1] = sortedData.x;\n"
- " if((index > 0) && (get_local_id(0) == 0))\n"
- " {\n"
- " // first thread in block must load neighbor body hash\n"
- " sharedHash[0] = pHash[index-1].x;\n"
- " }\n"
- " }\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " if(index < numObjects)\n"
- " {\n"
- " if((index == 0) || (sortedData.x != sharedHash[get_local_id(0)]))\n"
- " {\n"
- " cellStart[sortedData.x] = index;\n"
- " }\n"
- " }\n"
- "}\n"
- "int testAABBOverlap(float4 min0, float4 max0, float4 min1, float4 max1)\n"
- "{\n"
- " return (min0.x <= max1.x)&& (min1.x <= max0.x) && \n"
- " (min0.y <= max1.y)&& (min1.y <= max0.y) && \n"
- " (min0.z <= max1.z)&& (min1.z <= max0.z); \n"
- "}\n"
- "//search for AABB 'index' against other AABBs' in this cell\n"
- "void findPairsInCell( int numObjects,\n"
- " int4 gridPos,\n"
- " int index,\n"
- " __global int2* pHash,\n"
- " __global int* pCellStart,\n"
- " __global float4* allpAABB, \n"
- " __global const int* smallAabbMapping,\n"
- " __global float4* pParams,\n"
- " volatile __global int* pairCount,\n"
- " __global int4* pPairBuff2,\n"
- " int maxPairs\n"
- " )\n"
- "{\n"
- " int4 pGridDim = *((__global int4*)(pParams + 1));\n"
- " int maxBodiesPerCell = pGridDim.w;\n"
- " int gridHash = getPosHash(gridPos, pParams);\n"
- " // get start of bucket for this cell\n"
- " int bucketStart = pCellStart[gridHash];\n"
- " if (bucketStart == -1)\n"
- " {\n"
- " return; // cell empty\n"
- " }\n"
- " // iterate over bodies in this cell\n"
- " int2 sortedData = pHash[index];\n"
- " int unsorted_indx = sortedData.y;\n"
- " float4 min0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0]; \n"
- " float4 max0 = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
- " int handleIndex = as_int(min0.w);\n"
- " \n"
- " int bucketEnd = bucketStart + maxBodiesPerCell;\n"
- " bucketEnd = (bucketEnd > numObjects) ? numObjects : bucketEnd;\n"
- " for(int index2 = bucketStart; index2 < bucketEnd; index2++) \n"
- " {\n"
- " int2 cellData = pHash[index2];\n"
- " if (cellData.x != gridHash)\n"
- " {\n"
- " break; // no longer in same bucket\n"
- " }\n"
- " int unsorted_indx2 = cellData.y;\n"
- " //if (unsorted_indx2 < unsorted_indx) // check not colliding with self\n"
- " if (unsorted_indx2 != unsorted_indx) // check not colliding with self\n"
- " { \n"
- " float4 min1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 0];\n"
- " float4 max1 = allpAABB[smallAabbMapping[unsorted_indx2]*2 + 1];\n"
- " if(testAABBOverlap(min0, max0, min1, max1))\n"
- " {\n"
- " if (pairCount)\n"
- " {\n"
- " int handleIndex2 = as_int(min1.w);\n"
- " if (handleIndex<handleIndex2)\n"
- " {\n"
- " int curPair = atomic_add(pairCount,1);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " int4 newpair;\n"
- " newpair.x = handleIndex;\n"
- " newpair.y = handleIndex2;\n"
- " newpair.z = -1;\n"
- " newpair.w = -1;\n"
- " pPairBuff2[curPair] = newpair;\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void kFindOverlappingPairs( int numObjects,\n"
- " __global float4* allpAABB, \n"
- " __global const int* smallAabbMapping,\n"
- " __global int2* pHash, \n"
- " __global int* pCellStart, \n"
- " __global float4* pParams ,\n"
- " volatile __global int* pairCount,\n"
- " __global int4* pPairBuff2,\n"
- " int maxPairs\n"
- " )\n"
- "{\n"
- " int index = get_global_id(0);\n"
- " if(index >= numObjects)\n"
- " {\n"
- " return;\n"
- " }\n"
- " int2 sortedData = pHash[index];\n"
- " int unsorted_indx = sortedData.y;\n"
- " float4 bbMin = allpAABB[smallAabbMapping[unsorted_indx]*2 + 0];\n"
- " float4 bbMax = allpAABB[smallAabbMapping[unsorted_indx]*2 + 1];\n"
- " float4 pos;\n"
- " pos.x = (bbMin.x + bbMax.x) * 0.5f;\n"
- " pos.y = (bbMin.y + bbMax.y) * 0.5f;\n"
- " pos.z = (bbMin.z + bbMax.z) * 0.5f;\n"
- " // get address in grid\n"
- " int4 gridPosA = getGridPos(pos, pParams);\n"
- " int4 gridPosB; \n"
- " // examine only neighbouring cells\n"
- " for(int z=-1; z<=1; z++) \n"
- " {\n"
- " gridPosB.z = gridPosA.z + z;\n"
- " for(int y=-1; y<=1; y++) \n"
- " {\n"
- " gridPosB.y = gridPosA.y + y;\n"
- " for(int x=-1; x<=1; x++) \n"
- " {\n"
- " gridPosB.x = gridPosA.x + x;\n"
- " findPairsInCell(numObjects, gridPosB, index, pHash, pCellStart, allpAABB,smallAabbMapping, pParams, pairCount,pPairBuff2, maxPairs);\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl
deleted file mode 100644
index c375b9bf37..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvh.cl
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Initial Author Jackson Lee, 2014
-
-typedef float b3Scalar;
-typedef float4 b3Vector3;
-#define b3Max max
-#define b3Min min
-#define b3Sqrt sqrt
-
-typedef struct
-{
- unsigned int m_key;
- unsigned int m_value;
-} SortDataCL;
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} b3AabbCL;
-
-
-unsigned int interleaveBits(unsigned int x)
-{
- //........ ........ ......12 3456789A //x
- //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits
-
- //......12 3456789A ......12 3456789A //x ^ (x << 16)
- //11111111 ........ ........ 11111111 //0x FF 00 00 FF
- //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;
-
- //......12 ........ 3456789A 3456789A //x ^ (x << 8)
- //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F
- //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;
-
- //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)
- //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3
- //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;
-
- //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)
- //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49
- //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;
-
- //........ ........ ......11 11111111 //0x000003FF
- x &= 0x000003FF; //Clear all bits above bit 10
-
- x = (x ^ (x << 16)) & 0xFF0000FF;
- x = (x ^ (x << 8)) & 0x0300F00F;
- x = (x ^ (x << 4)) & 0x030C30C3;
- x = (x ^ (x << 2)) & 0x09249249;
-
- return x;
-}
-unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)
-{
- return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;
-}
-
-__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)
-{
- int separatedAabbIndex = get_global_id(0);
- if(separatedAabbIndex >= numAabbsToSeparate) return;
-
- int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];
- out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];
-}
-
-//Should replace with an optimized parallel reduction
-__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)
-{
- //Each time this kernel is added to the command queue,
- //the number of AABBs needing to be merged is halved
- //
- //Example with 159 AABBs:
- // numRemainingAabbs == 159 / 2 + 159 % 2 == 80
- // numMergedAabbs == 159 - 80 == 79
- //So, indices [0, 78] are merged with [0 + 80, 78 + 80]
-
- int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;
- int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;
-
- int aabbIndex = get_global_id(0);
- if(aabbIndex >= numMergedAabbs) return;
-
- int otherAabbIndex = aabbIndex + numRemainingAabbs;
-
- b3AabbCL aabb = out_mergedAabb[aabbIndex];
- b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];
-
- b3AabbCL mergedAabb;
- mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);
- mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);
- out_mergedAabb[aabbIndex] = mergedAabb;
-}
-
-__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes,
- __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)
-{
- int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index
- if(leafNodeIndex >= numAabbs) return;
-
- b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];
- b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;
- b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;
-
- b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];
- b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;
- b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;
-
- //Quantize into integer coordinates
- //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size
- b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;
-
- int4 discretePosition;
- discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );
- discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );
- discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );
-
- //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]
- discretePosition = b3Max( -512, b3Min(discretePosition, 511) );
- discretePosition += 512;
-
- //Interleave bits(assign a morton code, also known as a z-curve)
- unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);
-
- //
- SortDataCL mortonCodeIndexPair;
- mortonCodeIndexPair.m_key = mortonCode;
- mortonCodeIndexPair.m_value = leafNodeIndex;
-
- out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;
-}
-
-#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128
-
-//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.
-//If it is set, then the index is for an internal node; otherwise, it is a leaf node.
-//In both cases, the bit should be cleared to access the actual node index.
-int isLeafNode(int index) { return (index >> 31 == 0); }
-int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }
-int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }
-
-//From sap.cl
-#define NEW_PAIR_MARKER -1
-
-bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)
-{
- bool overlap = true;
- overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
- overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
- overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
- return overlap;
-}
-//From sap.cl
-
-__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs,
-
- __global int* rootNodeIndex,
- __global int2* internalNodeChildIndices,
- __global b3AabbCL* internalNodeAabbs,
- __global int2* internalNodeLeafIndexRanges,
-
- __global SortDataCL* mortonCodesAndAabbIndices,
- __global int* out_numPairs, __global int4* out_overlappingPairs,
- int maxPairs, int numQueryAabbs)
-{
- //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since
- //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)
- int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
- if(queryBvhNodeIndex >= numQueryAabbs) return;
-
- int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;
- b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];
-
- int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
-
- int stackSize = 1;
- stack[0] = *rootNodeIndex;
-
- while(stackSize)
- {
- int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
- --stackSize;
-
- int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false
- int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
-
- //Optimization - if the BVH is structured as a binary radix tree, then
- //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).
- //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.
- {
- int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;
- if(highestLeafIndex <= queryBvhNodeIndex) continue;
- }
-
- //bvhRigidIndex is not used if internal node
- int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
-
- b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
- if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )
- {
- if(isLeaf)
- {
- int4 pair;
- pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];
- pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
- pair.z = NEW_PAIR_MARKER;
- pair.w = NEW_PAIR_MARKER;
-
- int pairIndex = atomic_inc(out_numPairs);
- if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
- }
-
- if(!isLeaf) //Internal node
- {
- if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
- {
- //Error
- }
- else
- {
- stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
- stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
- }
- }
- }
-
- }
-}
-
-
-//From rayCastKernels.cl
-typedef struct
-{
- float4 m_from;
- float4 m_to;
-} b3RayInfo;
-//From rayCastKernels.cl
-
-b3Vector3 b3Vector3_normalize(b3Vector3 v)
-{
- b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};
- return normalize(normal); //OpenCL normalize == vector4 normalize
-}
-b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }
-b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }
-
-int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)
-{
- //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).
- //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.
- //
- //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane
- //and min.x will be the far plane; otherwise, it is reversed.
- //
- //In order for there to be a collision, the t_min and t_max of each pair must overlap.
- //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.
-
- int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)
-
- //When using vector types, the select() function checks the most signficant bit,
- //but isless() sets the least significant bit.
- isNegative <<= 31;
-
- //select(b, a, condition) == condition ? a : b
- //When using select() with vector types, (condition[i]) is true if its most significant bit is 1
- b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;
- b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;
-
- b3Scalar t_min_final = 0.0f;
- b3Scalar t_max_final = rayLength;
-
- //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned.
- //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])
- //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.
- t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );
- t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );
-
- return (t_min_final <= t_max_final);
-}
-
-__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,
-
- __global int* rootNodeIndex,
- __global int2* internalNodeChildIndices,
- __global b3AabbCL* internalNodeAabbs,
- __global int2* internalNodeLeafIndexRanges,
- __global SortDataCL* mortonCodesAndAabbIndices,
-
- __global b3RayInfo* rays,
-
- __global int* out_numRayRigidPairs,
- __global int2* out_rayRigidPairs,
- int maxRayRigidPairs, int numRays)
-{
- int rayIndex = get_global_id(0);
- if(rayIndex >= numRays) return;
-
- //
- b3Vector3 rayFrom = rays[rayIndex].m_from;
- b3Vector3 rayTo = rays[rayIndex].m_to;
- b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
- b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
-
- //
- int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];
-
- int stackSize = 1;
- stack[0] = *rootNodeIndex;
-
- while(stackSize)
- {
- int internalOrLeafNodeIndex = stack[ stackSize - 1 ];
- --stackSize;
-
- int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false
- int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);
-
- //bvhRigidIndex is not used if internal node
- int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;
-
- b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];
- if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )
- {
- if(isLeaf)
- {
- int2 rayRigidPair;
- rayRigidPair.x = rayIndex;
- rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];
-
- int pairIndex = atomic_inc(out_numRayRigidPairs);
- if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
- }
-
- if(!isLeaf) //Internal node
- {
- if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)
- {
- //Error
- }
- else
- {
- stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;
- stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;
- }
- }
- }
- }
-}
-
-__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs,
- __global int* out_numPairs, __global int4* out_overlappingPairs,
- int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)
-{
- int smallAabbIndex = get_global_id(0);
- if(smallAabbIndex >= numSmallAabbRigids) return;
-
- b3AabbCL smallAabb = smallAabbs[smallAabbIndex];
- for(int i = 0; i < numLargeAabbRigids; ++i)
- {
- b3AabbCL largeAabb = largeAabbs[i];
- if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )
- {
- int4 pair;
- pair.x = largeAabb.m_minIndices[3];
- pair.y = smallAabb.m_minIndices[3];
- pair.z = NEW_PAIR_MARKER;
- pair.w = NEW_PAIR_MARKER;
-
- int pairIndex = atomic_inc(out_numPairs);
- if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;
- }
- }
-}
-__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,
- __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,
- int numLargeAabbRigids, int maxRayRigidPairs, int numRays)
-{
- int rayIndex = get_global_id(0);
- if(rayIndex >= numRays) return;
-
- b3Vector3 rayFrom = rays[rayIndex].m_from;
- b3Vector3 rayTo = rays[rayIndex].m_to;
- b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);
- b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );
-
- for(int i = 0; i < numLargeAabbRigids; ++i)
- {
- b3AabbCL rigidAabb = largeRigidAabbs[i];
- if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )
- {
- int2 rayRigidPair;
- rayRigidPair.x = rayIndex;
- rayRigidPair.y = rigidAabb.m_minIndices[3];
-
- int pairIndex = atomic_inc(out_numRayRigidPairs);
- if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;
- }
- }
-}
-
-
-//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.
-//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.
-//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.
-//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).
-#define B3_PLBVH_INVALID_COMMON_PREFIX 128
-
-#define B3_PLBVH_ROOT_NODE_MARKER -1
-
-#define b3Int64 long
-
-int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }
-b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j)
-{
- //This function only needs to return (i & j) in order for the algorithm to work,
- //but it may help with debugging to mask out the lower bits.
-
- b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);
-
- b3Int64 sharedBits = i & j;
- b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0
-
- return sharedBits & bitmask;
-}
-
-//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths
-int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)
-{
- return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );
-}
-
-__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,
- __global b3Int64* out_commonPrefixes,
- __global int* out_commonPrefixLengths,
- int numInternalNodes)
-{
- int internalNodeIndex = get_global_id(0);
- if (internalNodeIndex >= numInternalNodes) return;
-
- //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,
- //and the number of internal nodes is always numLeafNodes - 1
- int leftLeafIndex = internalNodeIndex;
- int rightLeafIndex = internalNodeIndex + 1;
-
- int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;
- int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;
-
- //Binary radix tree construction algorithm does not work if there are duplicate morton codes.
- //Append the index of each leaf node to each morton code so that there are no duplicates.
- //The algorithm also requires that the morton codes are sorted in ascending order; this requirement
- //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.
- //
- //upsample(a, b) == ( ((b3Int64)a) << 32) | b
- b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);
- b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);
-
- out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
- out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);
-}
-
-
-__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,
- __global int2* out_childNodes, int numLeafNodes)
-{
- int leafNodeIndex = get_global_id(0);
- if (leafNodeIndex >= numLeafNodes) return;
-
- int numInternalNodes = numLeafNodes - 1;
-
- int leftSplitIndex = leafNodeIndex - 1;
- int rightSplitIndex = leafNodeIndex;
-
- int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
- int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
-
- //Parent node is the highest adjacent common prefix that is lower than the node's common prefix
- //Leaf nodes are considered as having the highest common prefix
- int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);
-
- //Handle cases for the edge nodes; the first and last node
- //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX
- if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;
- if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;
-
- int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;
- out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;
-
- int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa
-
- //out_childNodesAsInt[0] == int2.x == left child
- //out_childNodesAsInt[1] == int2.y == right child
- int isLeaf = 1;
- __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
- out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);
-}
-
-__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,
- __global int2* out_childNodes,
- __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,
- int numInternalNodes)
-{
- int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);
- if(internalNodeIndex >= numInternalNodes) return;
-
- b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];
- int nodePrefixLength = commonPrefixLengths[internalNodeIndex];
-
-//#define USE_LINEAR_SEARCH
-#ifdef USE_LINEAR_SEARCH
- int leftIndex = -1;
- int rightIndex = -1;
-
- //Find nearest element to left with a lower common prefix
- for(int i = internalNodeIndex - 1; i >= 0; --i)
- {
- int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
- if(nodeLeftSharedPrefixLength < nodePrefixLength)
- {
- leftIndex = i;
- break;
- }
- }
-
- //Find nearest element to right with a lower common prefix
- for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)
- {
- int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);
- if(nodeRightSharedPrefixLength < nodePrefixLength)
- {
- rightIndex = i;
- break;
- }
- }
-
-#else //Use binary search
-
- //Find nearest element to left with a lower common prefix
- int leftIndex = -1;
- {
- int lower = 0;
- int upper = internalNodeIndex - 1;
-
- while(lower <= upper)
- {
- int mid = (lower + upper) / 2;
- b3Int64 midPrefix = commonPrefixes[mid];
- int midPrefixLength = commonPrefixLengths[mid];
-
- int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
- if(nodeMidSharedPrefixLength < nodePrefixLength)
- {
- int right = mid + 1;
- if(right < internalNodeIndex)
- {
- b3Int64 rightPrefix = commonPrefixes[right];
- int rightPrefixLength = commonPrefixLengths[right];
-
- int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);
- if(nodeRightSharedPrefixLength < nodePrefixLength)
- {
- lower = right;
- leftIndex = right;
- }
- else
- {
- leftIndex = mid;
- break;
- }
- }
- else
- {
- leftIndex = mid;
- break;
- }
- }
- else upper = mid - 1;
- }
- }
-
- //Find nearest element to right with a lower common prefix
- int rightIndex = -1;
- {
- int lower = internalNodeIndex + 1;
- int upper = numInternalNodes - 1;
-
- while(lower <= upper)
- {
- int mid = (lower + upper) / 2;
- b3Int64 midPrefix = commonPrefixes[mid];
- int midPrefixLength = commonPrefixLengths[mid];
-
- int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);
- if(nodeMidSharedPrefixLength < nodePrefixLength)
- {
- int left = mid - 1;
- if(left > internalNodeIndex)
- {
- b3Int64 leftPrefix = commonPrefixes[left];
- int leftPrefixLength = commonPrefixLengths[left];
-
- int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);
- if(nodeLeftSharedPrefixLength < nodePrefixLength)
- {
- upper = left;
- rightIndex = left;
- }
- else
- {
- rightIndex = mid;
- break;
- }
- }
- else
- {
- rightIndex = mid;
- break;
- }
- }
- else lower = mid + 1;
- }
- }
-#endif
-
- //Select parent
- {
- int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
- int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;
-
- int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);
-
- if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;
- else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;
-
- int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;
-
- int isRootNode = (leftIndex == -1 && rightIndex == -1);
- out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;
-
- int isLeaf = 0;
- if(!isRootNode)
- {
- int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa
-
- //out_childNodesAsInt[0] == int2.x == left child
- //out_childNodesAsInt[1] == int2.y == right child
- __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);
- out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
- }
- else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);
- }
-}
-
-__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,
- __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)
-{
- if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);
-
- int internalNodeIndex = get_global_id(0);
- if(internalNodeIndex >= numInternalNodes) return;
-
- //
- int distanceFromRoot = 0;
- {
- int parentIndex = internalNodeParentNodes[internalNodeIndex];
- while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)
- {
- parentIndex = internalNodeParentNodes[parentIndex];
- ++distanceFromRoot;
- }
- }
- out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;
-
- //
- __local int localMaxDistanceFromRoot;
- if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;
- barrier(CLK_LOCAL_MEM_FENCE);
-
- atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);
-}
-
-__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,
- __global int2* childNodes,
- __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,
- int maxDistanceFromRoot, int processedDistance, int numInternalNodes)
-{
- int internalNodeIndex = get_global_id(0);
- if(internalNodeIndex >= numInternalNodes) return;
-
- int distance = distanceFromRoot[internalNodeIndex];
-
- if(distance == processedDistance)
- {
- int leftChildIndex = childNodes[internalNodeIndex].x;
- int rightChildIndex = childNodes[internalNodeIndex].y;
-
- int isLeftChildLeaf = isLeafNode(leftChildIndex);
- int isRightChildLeaf = isLeafNode(rightChildIndex);
-
- leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);
- rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);
-
- //leftRigidIndex/rightRigidIndex is not used if internal node
- int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;
- int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;
-
- b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];
- b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];
-
- b3AabbCL mergedAabb;
- mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);
- mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);
- internalNodeAabbs[internalNodeIndex] = mergedAabb;
- }
-}
-
-__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)
-{
- int internalNodeIndex = get_global_id(0);
- if(internalNodeIndex >= numInternalNodes) return;
-
- int numLeafNodes = numInternalNodes + 1;
-
- int2 childNodes = internalNodeChildNodes[internalNodeIndex];
-
- int2 leafIndexRange; //x == min leaf index, y == max leaf index
-
- //Find lowest leaf index covered by this internal node
- {
- int lowestIndex = childNodes.x; //childNodes.x == Left child
- while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;
- leafIndexRange.x = lowestIndex;
- }
-
- //Find highest leaf index covered by this internal node
- {
- int highestIndex = childNodes.y; //childNodes.y == Right child
- while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;
- leafIndexRange.y = highestIndex;
- }
-
- //
- out_leafIndexRanges[internalNodeIndex] = leafIndexRange;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
deleted file mode 100644
index c02877dde9..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/parallelLinearBvhKernels.h
+++ /dev/null
@@ -1,728 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* parallelLinearBvhCL =
- "/*\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose,\n"
- "including commercial applications, and to alter it and redistribute it freely,\n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Initial Author Jackson Lee, 2014\n"
- "typedef float b3Scalar;\n"
- "typedef float4 b3Vector3;\n"
- "#define b3Max max\n"
- "#define b3Min min\n"
- "#define b3Sqrt sqrt\n"
- "typedef struct\n"
- "{\n"
- " unsigned int m_key;\n"
- " unsigned int m_value;\n"
- "} SortDataCL;\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} b3AabbCL;\n"
- "unsigned int interleaveBits(unsigned int x)\n"
- "{\n"
- " //........ ........ ......12 3456789A //x\n"
- " //....1..2 ..3..4.. 5..6..7. .8..9..A //x after interleaving bits\n"
- " \n"
- " //......12 3456789A ......12 3456789A //x ^ (x << 16)\n"
- " //11111111 ........ ........ 11111111 //0x FF 00 00 FF\n"
- " //......12 ........ ........ 3456789A //x = (x ^ (x << 16)) & 0xFF0000FF;\n"
- " \n"
- " //......12 ........ 3456789A 3456789A //x ^ (x << 8)\n"
- " //......11 ........ 1111.... ....1111 //0x 03 00 F0 0F\n"
- " //......12 ........ 3456.... ....789A //x = (x ^ (x << 8)) & 0x0300F00F;\n"
- " \n"
- " //..12..12 ....3456 3456.... 789A789A //x ^ (x << 4)\n"
- " //......11 ....11.. ..11.... 11....11 //0x 03 0C 30 C3\n"
- " //......12 ....34.. ..56.... 78....9A //x = (x ^ (x << 4)) & 0x030C30C3;\n"
- " \n"
- " //....1212 ..3434.. 5656..78 78..9A9A //x ^ (x << 2)\n"
- " //....1..1 ..1..1.. 1..1..1. .1..1..1 //0x 09 24 92 49\n"
- " //....1..2 ..3..4.. 5..6..7. .8..9..A //x = (x ^ (x << 2)) & 0x09249249;\n"
- " \n"
- " //........ ........ ......11 11111111 //0x000003FF\n"
- " x &= 0x000003FF; //Clear all bits above bit 10\n"
- " \n"
- " x = (x ^ (x << 16)) & 0xFF0000FF;\n"
- " x = (x ^ (x << 8)) & 0x0300F00F;\n"
- " x = (x ^ (x << 4)) & 0x030C30C3;\n"
- " x = (x ^ (x << 2)) & 0x09249249;\n"
- " \n"
- " return x;\n"
- "}\n"
- "unsigned int getMortonCode(unsigned int x, unsigned int y, unsigned int z)\n"
- "{\n"
- " return interleaveBits(x) << 0 | interleaveBits(y) << 1 | interleaveBits(z) << 2;\n"
- "}\n"
- "__kernel void separateAabbs(__global b3AabbCL* unseparatedAabbs, __global int* aabbIndices, __global b3AabbCL* out_aabbs, int numAabbsToSeparate)\n"
- "{\n"
- " int separatedAabbIndex = get_global_id(0);\n"
- " if(separatedAabbIndex >= numAabbsToSeparate) return;\n"
- " int unseparatedAabbIndex = aabbIndices[separatedAabbIndex];\n"
- " out_aabbs[separatedAabbIndex] = unseparatedAabbs[unseparatedAabbIndex];\n"
- "}\n"
- "//Should replace with an optimized parallel reduction\n"
- "__kernel void findAllNodesMergedAabb(__global b3AabbCL* out_mergedAabb, int numAabbsNeedingMerge)\n"
- "{\n"
- " //Each time this kernel is added to the command queue, \n"
- " //the number of AABBs needing to be merged is halved\n"
- " //\n"
- " //Example with 159 AABBs:\n"
- " // numRemainingAabbs == 159 / 2 + 159 % 2 == 80\n"
- " // numMergedAabbs == 159 - 80 == 79\n"
- " //So, indices [0, 78] are merged with [0 + 80, 78 + 80]\n"
- " \n"
- " int numRemainingAabbs = numAabbsNeedingMerge / 2 + numAabbsNeedingMerge % 2;\n"
- " int numMergedAabbs = numAabbsNeedingMerge - numRemainingAabbs;\n"
- " \n"
- " int aabbIndex = get_global_id(0);\n"
- " if(aabbIndex >= numMergedAabbs) return;\n"
- " \n"
- " int otherAabbIndex = aabbIndex + numRemainingAabbs;\n"
- " \n"
- " b3AabbCL aabb = out_mergedAabb[aabbIndex];\n"
- " b3AabbCL otherAabb = out_mergedAabb[otherAabbIndex];\n"
- " \n"
- " b3AabbCL mergedAabb;\n"
- " mergedAabb.m_min = b3Min(aabb.m_min, otherAabb.m_min);\n"
- " mergedAabb.m_max = b3Max(aabb.m_max, otherAabb.m_max);\n"
- " out_mergedAabb[aabbIndex] = mergedAabb;\n"
- "}\n"
- "__kernel void assignMortonCodesAndAabbIndicies(__global b3AabbCL* worldSpaceAabbs, __global b3AabbCL* mergedAabbOfAllNodes, \n"
- " __global SortDataCL* out_mortonCodesAndAabbIndices, int numAabbs)\n"
- "{\n"
- " int leafNodeIndex = get_global_id(0); //Leaf node index == AABB index\n"
- " if(leafNodeIndex >= numAabbs) return;\n"
- " \n"
- " b3AabbCL mergedAabb = mergedAabbOfAllNodes[0];\n"
- " b3Vector3 gridCenter = (mergedAabb.m_min + mergedAabb.m_max) * 0.5f;\n"
- " b3Vector3 gridCellSize = (mergedAabb.m_max - mergedAabb.m_min) / (float)1024;\n"
- " \n"
- " b3AabbCL aabb = worldSpaceAabbs[leafNodeIndex];\n"
- " b3Vector3 aabbCenter = (aabb.m_min + aabb.m_max) * 0.5f;\n"
- " b3Vector3 aabbCenterRelativeToGrid = aabbCenter - gridCenter;\n"
- " \n"
- " //Quantize into integer coordinates\n"
- " //floor() is needed to prevent the center cell, at (0,0,0) from being twice the size\n"
- " b3Vector3 gridPosition = aabbCenterRelativeToGrid / gridCellSize;\n"
- " \n"
- " int4 discretePosition;\n"
- " discretePosition.x = (int)( (gridPosition.x >= 0.0f) ? gridPosition.x : floor(gridPosition.x) );\n"
- " discretePosition.y = (int)( (gridPosition.y >= 0.0f) ? gridPosition.y : floor(gridPosition.y) );\n"
- " discretePosition.z = (int)( (gridPosition.z >= 0.0f) ? gridPosition.z : floor(gridPosition.z) );\n"
- " \n"
- " //Clamp coordinates into [-512, 511], then convert range from [-512, 511] to [0, 1023]\n"
- " discretePosition = b3Max( -512, b3Min(discretePosition, 511) );\n"
- " discretePosition += 512;\n"
- " \n"
- " //Interleave bits(assign a morton code, also known as a z-curve)\n"
- " unsigned int mortonCode = getMortonCode(discretePosition.x, discretePosition.y, discretePosition.z);\n"
- " \n"
- " //\n"
- " SortDataCL mortonCodeIndexPair;\n"
- " mortonCodeIndexPair.m_key = mortonCode;\n"
- " mortonCodeIndexPair.m_value = leafNodeIndex;\n"
- " \n"
- " out_mortonCodesAndAabbIndices[leafNodeIndex] = mortonCodeIndexPair;\n"
- "}\n"
- "#define B3_PLVBH_TRAVERSE_MAX_STACK_SIZE 128\n"
- "//The most significant bit(0x80000000) of a int32 is used to distinguish between leaf and internal nodes.\n"
- "//If it is set, then the index is for an internal node; otherwise, it is a leaf node. \n"
- "//In both cases, the bit should be cleared to access the actual node index.\n"
- "int isLeafNode(int index) { return (index >> 31 == 0); }\n"
- "int getIndexWithInternalNodeMarkerRemoved(int index) { return index & (~0x80000000); }\n"
- "int getIndexWithInternalNodeMarkerSet(int isLeaf, int index) { return (isLeaf) ? index : (index | 0x80000000); }\n"
- "//From sap.cl\n"
- "#define NEW_PAIR_MARKER -1\n"
- "bool TestAabbAgainstAabb2(const b3AabbCL* aabb1, const b3AabbCL* aabb2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
- " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
- " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "//From sap.cl\n"
- "__kernel void plbvhCalculateOverlappingPairs(__global b3AabbCL* rigidAabbs, \n"
- " __global int* rootNodeIndex, \n"
- " __global int2* internalNodeChildIndices, \n"
- " __global b3AabbCL* internalNodeAabbs,\n"
- " __global int2* internalNodeLeafIndexRanges,\n"
- " \n"
- " __global SortDataCL* mortonCodesAndAabbIndices,\n"
- " __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
- " int maxPairs, int numQueryAabbs)\n"
- "{\n"
- " //Using get_group_id()/get_local_id() is Faster than get_global_id(0) since\n"
- " //mortonCodesAndAabbIndices[] contains rigid body indices sorted along the z-curve (more spatially coherent)\n"
- " int queryBvhNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
- " if(queryBvhNodeIndex >= numQueryAabbs) return;\n"
- " \n"
- " int queryRigidIndex = mortonCodesAndAabbIndices[queryBvhNodeIndex].m_value;\n"
- " b3AabbCL queryAabb = rigidAabbs[queryRigidIndex];\n"
- " \n"
- " int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
- " \n"
- " int stackSize = 1;\n"
- " stack[0] = *rootNodeIndex;\n"
- " \n"
- " while(stackSize)\n"
- " {\n"
- " int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
- " --stackSize;\n"
- " \n"
- " int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
- " int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
- " \n"
- " //Optimization - if the BVH is structured as a binary radix tree, then\n"
- " //each internal node corresponds to a contiguous range of leaf nodes(internalNodeLeafIndexRanges[]).\n"
- " //This can be used to avoid testing each AABB-AABB pair twice, including preventing each node from colliding with itself.\n"
- " {\n"
- " int highestLeafIndex = (isLeaf) ? bvhNodeIndex : internalNodeLeafIndexRanges[bvhNodeIndex].y;\n"
- " if(highestLeafIndex <= queryBvhNodeIndex) continue;\n"
- " }\n"
- " \n"
- " //bvhRigidIndex is not used if internal node\n"
- " int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
- " \n"
- " b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
- " if( TestAabbAgainstAabb2(&queryAabb, &bvhNodeAabb) )\n"
- " {\n"
- " if(isLeaf)\n"
- " {\n"
- " int4 pair;\n"
- " pair.x = rigidAabbs[queryRigidIndex].m_minIndices[3];\n"
- " pair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
- " pair.z = NEW_PAIR_MARKER;\n"
- " pair.w = NEW_PAIR_MARKER;\n"
- " \n"
- " int pairIndex = atomic_inc(out_numPairs);\n"
- " if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
- " }\n"
- " \n"
- " if(!isLeaf) //Internal node\n"
- " {\n"
- " if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
- " {\n"
- " //Error\n"
- " }\n"
- " else\n"
- " {\n"
- " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
- " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- "}\n"
- "//From rayCastKernels.cl\n"
- "typedef struct\n"
- "{\n"
- " float4 m_from;\n"
- " float4 m_to;\n"
- "} b3RayInfo;\n"
- "//From rayCastKernels.cl\n"
- "b3Vector3 b3Vector3_normalize(b3Vector3 v)\n"
- "{\n"
- " b3Vector3 normal = (b3Vector3){v.x, v.y, v.z, 0.f};\n"
- " return normalize(normal); //OpenCL normalize == vector4 normalize\n"
- "}\n"
- "b3Scalar b3Vector3_length2(b3Vector3 v) { return v.x*v.x + v.y*v.y + v.z*v.z; }\n"
- "b3Scalar b3Vector3_dot(b3Vector3 a, b3Vector3 b) { return a.x*b.x + a.y*b.y + a.z*b.z; }\n"
- "int rayIntersectsAabb(b3Vector3 rayOrigin, b3Scalar rayLength, b3Vector3 rayNormalizedDirection, b3AabbCL aabb)\n"
- "{\n"
- " //AABB is considered as 3 pairs of 2 planes( {x_min, x_max}, {y_min, y_max}, {z_min, z_max} ).\n"
- " //t_min is the point of intersection with the closer plane, t_max is the point of intersection with the farther plane.\n"
- " //\n"
- " //if (rayNormalizedDirection.x < 0.0f), then max.x will be the near plane \n"
- " //and min.x will be the far plane; otherwise, it is reversed.\n"
- " //\n"
- " //In order for there to be a collision, the t_min and t_max of each pair must overlap.\n"
- " //This can be tested for by selecting the highest t_min and lowest t_max and comparing them.\n"
- " \n"
- " int4 isNegative = isless( rayNormalizedDirection, ((b3Vector3){0.0f, 0.0f, 0.0f, 0.0f}) ); //isless(x,y) returns (x < y)\n"
- " \n"
- " //When using vector types, the select() function checks the most signficant bit, \n"
- " //but isless() sets the least significant bit.\n"
- " isNegative <<= 31;\n"
- " //select(b, a, condition) == condition ? a : b\n"
- " //When using select() with vector types, (condition[i]) is true if its most significant bit is 1\n"
- " b3Vector3 t_min = ( select(aabb.m_min, aabb.m_max, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
- " b3Vector3 t_max = ( select(aabb.m_max, aabb.m_min, isNegative) - rayOrigin ) / rayNormalizedDirection;\n"
- " \n"
- " b3Scalar t_min_final = 0.0f;\n"
- " b3Scalar t_max_final = rayLength;\n"
- " \n"
- " //Must use fmin()/fmax(); if one of the parameters is NaN, then the parameter that is not NaN is returned. \n"
- " //Behavior of min()/max() with NaNs is undefined. (See OpenCL Specification 1.2 [6.12.2] and [6.12.4])\n"
- " //Since the innermost fmin()/fmax() is always not NaN, this should never return NaN.\n"
- " t_min_final = fmax( t_min.z, fmax(t_min.y, fmax(t_min.x, t_min_final)) );\n"
- " t_max_final = fmin( t_max.z, fmin(t_max.y, fmin(t_max.x, t_max_final)) );\n"
- " \n"
- " return (t_min_final <= t_max_final);\n"
- "}\n"
- "__kernel void plbvhRayTraverse(__global b3AabbCL* rigidAabbs,\n"
- " __global int* rootNodeIndex, \n"
- " __global int2* internalNodeChildIndices, \n"
- " __global b3AabbCL* internalNodeAabbs,\n"
- " __global int2* internalNodeLeafIndexRanges,\n"
- " __global SortDataCL* mortonCodesAndAabbIndices,\n"
- " \n"
- " __global b3RayInfo* rays,\n"
- " \n"
- " __global int* out_numRayRigidPairs, \n"
- " __global int2* out_rayRigidPairs,\n"
- " int maxRayRigidPairs, int numRays)\n"
- "{\n"
- " int rayIndex = get_global_id(0);\n"
- " if(rayIndex >= numRays) return;\n"
- " \n"
- " //\n"
- " b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
- " b3Vector3 rayTo = rays[rayIndex].m_to;\n"
- " b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
- " b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
- " \n"
- " //\n"
- " int stack[B3_PLVBH_TRAVERSE_MAX_STACK_SIZE];\n"
- " \n"
- " int stackSize = 1;\n"
- " stack[0] = *rootNodeIndex;\n"
- " \n"
- " while(stackSize)\n"
- " {\n"
- " int internalOrLeafNodeIndex = stack[ stackSize - 1 ];\n"
- " --stackSize;\n"
- " \n"
- " int isLeaf = isLeafNode(internalOrLeafNodeIndex); //Internal node if false\n"
- " int bvhNodeIndex = getIndexWithInternalNodeMarkerRemoved(internalOrLeafNodeIndex);\n"
- " \n"
- " //bvhRigidIndex is not used if internal node\n"
- " int bvhRigidIndex = (isLeaf) ? mortonCodesAndAabbIndices[bvhNodeIndex].m_value : -1;\n"
- " \n"
- " b3AabbCL bvhNodeAabb = (isLeaf) ? rigidAabbs[bvhRigidIndex] : internalNodeAabbs[bvhNodeIndex];\n"
- " if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, bvhNodeAabb) )\n"
- " {\n"
- " if(isLeaf)\n"
- " {\n"
- " int2 rayRigidPair;\n"
- " rayRigidPair.x = rayIndex;\n"
- " rayRigidPair.y = rigidAabbs[bvhRigidIndex].m_minIndices[3];\n"
- " \n"
- " int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
- " if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
- " }\n"
- " \n"
- " if(!isLeaf) //Internal node\n"
- " {\n"
- " if(stackSize + 2 > B3_PLVBH_TRAVERSE_MAX_STACK_SIZE)\n"
- " {\n"
- " //Error\n"
- " }\n"
- " else\n"
- " {\n"
- " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].x;\n"
- " stack[ stackSize++ ] = internalNodeChildIndices[bvhNodeIndex].y;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void plbvhLargeAabbAabbTest(__global b3AabbCL* smallAabbs, __global b3AabbCL* largeAabbs, \n"
- " __global int* out_numPairs, __global int4* out_overlappingPairs, \n"
- " int maxPairs, int numLargeAabbRigids, int numSmallAabbRigids)\n"
- "{\n"
- " int smallAabbIndex = get_global_id(0);\n"
- " if(smallAabbIndex >= numSmallAabbRigids) return;\n"
- " \n"
- " b3AabbCL smallAabb = smallAabbs[smallAabbIndex];\n"
- " for(int i = 0; i < numLargeAabbRigids; ++i)\n"
- " {\n"
- " b3AabbCL largeAabb = largeAabbs[i];\n"
- " if( TestAabbAgainstAabb2(&smallAabb, &largeAabb) )\n"
- " {\n"
- " int4 pair;\n"
- " pair.x = largeAabb.m_minIndices[3];\n"
- " pair.y = smallAabb.m_minIndices[3];\n"
- " pair.z = NEW_PAIR_MARKER;\n"
- " pair.w = NEW_PAIR_MARKER;\n"
- " \n"
- " int pairIndex = atomic_inc(out_numPairs);\n"
- " if(pairIndex < maxPairs) out_overlappingPairs[pairIndex] = pair;\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void plbvhLargeAabbRayTest(__global b3AabbCL* largeRigidAabbs, __global b3RayInfo* rays,\n"
- " __global int* out_numRayRigidPairs, __global int2* out_rayRigidPairs,\n"
- " int numLargeAabbRigids, int maxRayRigidPairs, int numRays)\n"
- "{\n"
- " int rayIndex = get_global_id(0);\n"
- " if(rayIndex >= numRays) return;\n"
- " \n"
- " b3Vector3 rayFrom = rays[rayIndex].m_from;\n"
- " b3Vector3 rayTo = rays[rayIndex].m_to;\n"
- " b3Vector3 rayNormalizedDirection = b3Vector3_normalize(rayTo - rayFrom);\n"
- " b3Scalar rayLength = b3Sqrt( b3Vector3_length2(rayTo - rayFrom) );\n"
- " \n"
- " for(int i = 0; i < numLargeAabbRigids; ++i)\n"
- " {\n"
- " b3AabbCL rigidAabb = largeRigidAabbs[i];\n"
- " if( rayIntersectsAabb(rayFrom, rayLength, rayNormalizedDirection, rigidAabb) )\n"
- " {\n"
- " int2 rayRigidPair;\n"
- " rayRigidPair.x = rayIndex;\n"
- " rayRigidPair.y = rigidAabb.m_minIndices[3];\n"
- " \n"
- " int pairIndex = atomic_inc(out_numRayRigidPairs);\n"
- " if(pairIndex < maxRayRigidPairs) out_rayRigidPairs[pairIndex] = rayRigidPair;\n"
- " }\n"
- " }\n"
- "}\n"
- "//Set so that it is always greater than the actual common prefixes, and never selected as a parent node.\n"
- "//If there are no duplicates, then the highest common prefix is 32 or 64, depending on the number of bits used for the z-curve.\n"
- "//Duplicate common prefixes increase the highest common prefix at most by the number of bits used to index the leaf node.\n"
- "//Since 32 bit ints are used to index leaf nodes, the max prefix is 64(32 + 32 bit z-curve) or 96(32 + 64 bit z-curve).\n"
- "#define B3_PLBVH_INVALID_COMMON_PREFIX 128\n"
- "#define B3_PLBVH_ROOT_NODE_MARKER -1\n"
- "#define b3Int64 long\n"
- "int computeCommonPrefixLength(b3Int64 i, b3Int64 j) { return (int)clz(i ^ j); }\n"
- "b3Int64 computeCommonPrefix(b3Int64 i, b3Int64 j) \n"
- "{\n"
- " //This function only needs to return (i & j) in order for the algorithm to work,\n"
- " //but it may help with debugging to mask out the lower bits.\n"
- " b3Int64 commonPrefixLength = (b3Int64)computeCommonPrefixLength(i, j);\n"
- " b3Int64 sharedBits = i & j;\n"
- " b3Int64 bitmask = ((b3Int64)(~0)) << (64 - commonPrefixLength); //Set all bits after the common prefix to 0\n"
- " \n"
- " return sharedBits & bitmask;\n"
- "}\n"
- "//Same as computeCommonPrefixLength(), but allows for prefixes with different lengths\n"
- "int getSharedPrefixLength(b3Int64 prefixA, int prefixLengthA, b3Int64 prefixB, int prefixLengthB)\n"
- "{\n"
- " return b3Min( computeCommonPrefixLength(prefixA, prefixB), b3Min(prefixLengthA, prefixLengthB) );\n"
- "}\n"
- "__kernel void computeAdjacentPairCommonPrefix(__global SortDataCL* mortonCodesAndAabbIndices,\n"
- " __global b3Int64* out_commonPrefixes,\n"
- " __global int* out_commonPrefixLengths,\n"
- " int numInternalNodes)\n"
- "{\n"
- " int internalNodeIndex = get_global_id(0);\n"
- " if (internalNodeIndex >= numInternalNodes) return;\n"
- " \n"
- " //Here, (internalNodeIndex + 1) is never out of bounds since it is a leaf node index,\n"
- " //and the number of internal nodes is always numLeafNodes - 1\n"
- " int leftLeafIndex = internalNodeIndex;\n"
- " int rightLeafIndex = internalNodeIndex + 1;\n"
- " \n"
- " int leftLeafMortonCode = mortonCodesAndAabbIndices[leftLeafIndex].m_key;\n"
- " int rightLeafMortonCode = mortonCodesAndAabbIndices[rightLeafIndex].m_key;\n"
- " \n"
- " //Binary radix tree construction algorithm does not work if there are duplicate morton codes.\n"
- " //Append the index of each leaf node to each morton code so that there are no duplicates.\n"
- " //The algorithm also requires that the morton codes are sorted in ascending order; this requirement\n"
- " //is also satisfied with this method, as (leftLeafIndex < rightLeafIndex) is always true.\n"
- " //\n"
- " //upsample(a, b) == ( ((b3Int64)a) << 32) | b\n"
- " b3Int64 nonduplicateLeftMortonCode = upsample(leftLeafMortonCode, leftLeafIndex);\n"
- " b3Int64 nonduplicateRightMortonCode = upsample(rightLeafMortonCode, rightLeafIndex);\n"
- " \n"
- " out_commonPrefixes[internalNodeIndex] = computeCommonPrefix(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
- " out_commonPrefixLengths[internalNodeIndex] = computeCommonPrefixLength(nonduplicateLeftMortonCode, nonduplicateRightMortonCode);\n"
- "}\n"
- "__kernel void buildBinaryRadixTreeLeafNodes(__global int* commonPrefixLengths, __global int* out_leafNodeParentNodes,\n"
- " __global int2* out_childNodes, int numLeafNodes)\n"
- "{\n"
- " int leafNodeIndex = get_global_id(0);\n"
- " if (leafNodeIndex >= numLeafNodes) return;\n"
- " \n"
- " int numInternalNodes = numLeafNodes - 1;\n"
- " \n"
- " int leftSplitIndex = leafNodeIndex - 1;\n"
- " int rightSplitIndex = leafNodeIndex;\n"
- " \n"
- " int leftCommonPrefix = (leftSplitIndex >= 0) ? commonPrefixLengths[leftSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
- " int rightCommonPrefix = (rightSplitIndex < numInternalNodes) ? commonPrefixLengths[rightSplitIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
- " \n"
- " //Parent node is the highest adjacent common prefix that is lower than the node's common prefix\n"
- " //Leaf nodes are considered as having the highest common prefix\n"
- " int isLeftHigherCommonPrefix = (leftCommonPrefix > rightCommonPrefix);\n"
- " \n"
- " //Handle cases for the edge nodes; the first and last node\n"
- " //For leaf nodes, leftCommonPrefix and rightCommonPrefix should never both be B3_PLBVH_INVALID_COMMON_PREFIX\n"
- " if(leftCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = false;\n"
- " if(rightCommonPrefix == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherCommonPrefix = true;\n"
- " \n"
- " int parentNodeIndex = (isLeftHigherCommonPrefix) ? leftSplitIndex : rightSplitIndex;\n"
- " out_leafNodeParentNodes[leafNodeIndex] = parentNodeIndex;\n"
- " \n"
- " int isRightChild = (isLeftHigherCommonPrefix); //If the left node is the parent, then this node is its right child and vice versa\n"
- " \n"
- " //out_childNodesAsInt[0] == int2.x == left child\n"
- " //out_childNodesAsInt[1] == int2.y == right child\n"
- " int isLeaf = 1;\n"
- " __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
- " out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, leafNodeIndex);\n"
- "}\n"
- "__kernel void buildBinaryRadixTreeInternalNodes(__global b3Int64* commonPrefixes, __global int* commonPrefixLengths,\n"
- " __global int2* out_childNodes,\n"
- " __global int* out_internalNodeParentNodes, __global int* out_rootNodeIndex,\n"
- " int numInternalNodes)\n"
- "{\n"
- " int internalNodeIndex = get_group_id(0) * get_local_size(0) + get_local_id(0);\n"
- " if(internalNodeIndex >= numInternalNodes) return;\n"
- " \n"
- " b3Int64 nodePrefix = commonPrefixes[internalNodeIndex];\n"
- " int nodePrefixLength = commonPrefixLengths[internalNodeIndex];\n"
- " \n"
- "//#define USE_LINEAR_SEARCH\n"
- "#ifdef USE_LINEAR_SEARCH\n"
- " int leftIndex = -1;\n"
- " int rightIndex = -1;\n"
- " \n"
- " //Find nearest element to left with a lower common prefix\n"
- " for(int i = internalNodeIndex - 1; i >= 0; --i)\n"
- " {\n"
- " int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
- " if(nodeLeftSharedPrefixLength < nodePrefixLength)\n"
- " {\n"
- " leftIndex = i;\n"
- " break;\n"
- " }\n"
- " }\n"
- " \n"
- " //Find nearest element to right with a lower common prefix\n"
- " for(int i = internalNodeIndex + 1; i < numInternalNodes; ++i)\n"
- " {\n"
- " int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, commonPrefixes[i], commonPrefixLengths[i]);\n"
- " if(nodeRightSharedPrefixLength < nodePrefixLength)\n"
- " {\n"
- " rightIndex = i;\n"
- " break;\n"
- " }\n"
- " }\n"
- " \n"
- "#else //Use binary search\n"
- " //Find nearest element to left with a lower common prefix\n"
- " int leftIndex = -1;\n"
- " {\n"
- " int lower = 0;\n"
- " int upper = internalNodeIndex - 1;\n"
- " \n"
- " while(lower <= upper)\n"
- " {\n"
- " int mid = (lower + upper) / 2;\n"
- " b3Int64 midPrefix = commonPrefixes[mid];\n"
- " int midPrefixLength = commonPrefixLengths[mid];\n"
- " \n"
- " int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
- " if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
- " {\n"
- " int right = mid + 1;\n"
- " if(right < internalNodeIndex)\n"
- " {\n"
- " b3Int64 rightPrefix = commonPrefixes[right];\n"
- " int rightPrefixLength = commonPrefixLengths[right];\n"
- " \n"
- " int nodeRightSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, rightPrefix, rightPrefixLength);\n"
- " if(nodeRightSharedPrefixLength < nodePrefixLength) \n"
- " {\n"
- " lower = right;\n"
- " leftIndex = right;\n"
- " }\n"
- " else \n"
- " {\n"
- " leftIndex = mid;\n"
- " break;\n"
- " }\n"
- " }\n"
- " else \n"
- " {\n"
- " leftIndex = mid;\n"
- " break;\n"
- " }\n"
- " }\n"
- " else upper = mid - 1;\n"
- " }\n"
- " }\n"
- " \n"
- " //Find nearest element to right with a lower common prefix\n"
- " int rightIndex = -1;\n"
- " {\n"
- " int lower = internalNodeIndex + 1;\n"
- " int upper = numInternalNodes - 1;\n"
- " \n"
- " while(lower <= upper)\n"
- " {\n"
- " int mid = (lower + upper) / 2;\n"
- " b3Int64 midPrefix = commonPrefixes[mid];\n"
- " int midPrefixLength = commonPrefixLengths[mid];\n"
- " \n"
- " int nodeMidSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, midPrefix, midPrefixLength);\n"
- " if(nodeMidSharedPrefixLength < nodePrefixLength) \n"
- " {\n"
- " int left = mid - 1;\n"
- " if(left > internalNodeIndex)\n"
- " {\n"
- " b3Int64 leftPrefix = commonPrefixes[left];\n"
- " int leftPrefixLength = commonPrefixLengths[left];\n"
- " \n"
- " int nodeLeftSharedPrefixLength = getSharedPrefixLength(nodePrefix, nodePrefixLength, leftPrefix, leftPrefixLength);\n"
- " if(nodeLeftSharedPrefixLength < nodePrefixLength) \n"
- " {\n"
- " upper = left;\n"
- " rightIndex = left;\n"
- " }\n"
- " else \n"
- " {\n"
- " rightIndex = mid;\n"
- " break;\n"
- " }\n"
- " }\n"
- " else \n"
- " {\n"
- " rightIndex = mid;\n"
- " break;\n"
- " }\n"
- " }\n"
- " else lower = mid + 1;\n"
- " }\n"
- " }\n"
- "#endif\n"
- " \n"
- " //Select parent\n"
- " {\n"
- " int leftPrefixLength = (leftIndex != -1) ? commonPrefixLengths[leftIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
- " int rightPrefixLength = (rightIndex != -1) ? commonPrefixLengths[rightIndex] : B3_PLBVH_INVALID_COMMON_PREFIX;\n"
- " \n"
- " int isLeftHigherPrefixLength = (leftPrefixLength > rightPrefixLength);\n"
- " \n"
- " if(leftPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = false;\n"
- " else if(rightPrefixLength == B3_PLBVH_INVALID_COMMON_PREFIX) isLeftHigherPrefixLength = true;\n"
- " \n"
- " int parentNodeIndex = (isLeftHigherPrefixLength) ? leftIndex : rightIndex;\n"
- " \n"
- " int isRootNode = (leftIndex == -1 && rightIndex == -1);\n"
- " out_internalNodeParentNodes[internalNodeIndex] = (!isRootNode) ? parentNodeIndex : B3_PLBVH_ROOT_NODE_MARKER;\n"
- " \n"
- " int isLeaf = 0;\n"
- " if(!isRootNode)\n"
- " {\n"
- " int isRightChild = (isLeftHigherPrefixLength); //If the left node is the parent, then this node is its right child and vice versa\n"
- " \n"
- " //out_childNodesAsInt[0] == int2.x == left child\n"
- " //out_childNodesAsInt[1] == int2.y == right child\n"
- " __global int* out_childNodesAsInt = (__global int*)(&out_childNodes[parentNodeIndex]);\n"
- " out_childNodesAsInt[isRightChild] = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
- " }\n"
- " else *out_rootNodeIndex = getIndexWithInternalNodeMarkerSet(isLeaf, internalNodeIndex);\n"
- " }\n"
- "}\n"
- "__kernel void findDistanceFromRoot(__global int* rootNodeIndex, __global int* internalNodeParentNodes,\n"
- " __global int* out_maxDistanceFromRoot, __global int* out_distanceFromRoot, int numInternalNodes)\n"
- "{\n"
- " if( get_global_id(0) == 0 ) atomic_xchg(out_maxDistanceFromRoot, 0);\n"
- " int internalNodeIndex = get_global_id(0);\n"
- " if(internalNodeIndex >= numInternalNodes) return;\n"
- " \n"
- " //\n"
- " int distanceFromRoot = 0;\n"
- " {\n"
- " int parentIndex = internalNodeParentNodes[internalNodeIndex];\n"
- " while(parentIndex != B3_PLBVH_ROOT_NODE_MARKER)\n"
- " {\n"
- " parentIndex = internalNodeParentNodes[parentIndex];\n"
- " ++distanceFromRoot;\n"
- " }\n"
- " }\n"
- " out_distanceFromRoot[internalNodeIndex] = distanceFromRoot;\n"
- " \n"
- " //\n"
- " __local int localMaxDistanceFromRoot;\n"
- " if( get_local_id(0) == 0 ) localMaxDistanceFromRoot = 0;\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " atomic_max(&localMaxDistanceFromRoot, distanceFromRoot);\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if( get_local_id(0) == 0 ) atomic_max(out_maxDistanceFromRoot, localMaxDistanceFromRoot);\n"
- "}\n"
- "__kernel void buildBinaryRadixTreeAabbsRecursive(__global int* distanceFromRoot, __global SortDataCL* mortonCodesAndAabbIndices,\n"
- " __global int2* childNodes,\n"
- " __global b3AabbCL* leafNodeAabbs, __global b3AabbCL* internalNodeAabbs,\n"
- " int maxDistanceFromRoot, int processedDistance, int numInternalNodes)\n"
- "{\n"
- " int internalNodeIndex = get_global_id(0);\n"
- " if(internalNodeIndex >= numInternalNodes) return;\n"
- " \n"
- " int distance = distanceFromRoot[internalNodeIndex];\n"
- " \n"
- " if(distance == processedDistance)\n"
- " {\n"
- " int leftChildIndex = childNodes[internalNodeIndex].x;\n"
- " int rightChildIndex = childNodes[internalNodeIndex].y;\n"
- " \n"
- " int isLeftChildLeaf = isLeafNode(leftChildIndex);\n"
- " int isRightChildLeaf = isLeafNode(rightChildIndex);\n"
- " \n"
- " leftChildIndex = getIndexWithInternalNodeMarkerRemoved(leftChildIndex);\n"
- " rightChildIndex = getIndexWithInternalNodeMarkerRemoved(rightChildIndex);\n"
- " \n"
- " //leftRigidIndex/rightRigidIndex is not used if internal node\n"
- " int leftRigidIndex = (isLeftChildLeaf) ? mortonCodesAndAabbIndices[leftChildIndex].m_value : -1;\n"
- " int rightRigidIndex = (isRightChildLeaf) ? mortonCodesAndAabbIndices[rightChildIndex].m_value : -1;\n"
- " \n"
- " b3AabbCL leftChildAabb = (isLeftChildLeaf) ? leafNodeAabbs[leftRigidIndex] : internalNodeAabbs[leftChildIndex];\n"
- " b3AabbCL rightChildAabb = (isRightChildLeaf) ? leafNodeAabbs[rightRigidIndex] : internalNodeAabbs[rightChildIndex];\n"
- " \n"
- " b3AabbCL mergedAabb;\n"
- " mergedAabb.m_min = b3Min(leftChildAabb.m_min, rightChildAabb.m_min);\n"
- " mergedAabb.m_max = b3Max(leftChildAabb.m_max, rightChildAabb.m_max);\n"
- " internalNodeAabbs[internalNodeIndex] = mergedAabb;\n"
- " }\n"
- "}\n"
- "__kernel void findLeafIndexRanges(__global int2* internalNodeChildNodes, __global int2* out_leafIndexRanges, int numInternalNodes)\n"
- "{\n"
- " int internalNodeIndex = get_global_id(0);\n"
- " if(internalNodeIndex >= numInternalNodes) return;\n"
- " \n"
- " int numLeafNodes = numInternalNodes + 1;\n"
- " \n"
- " int2 childNodes = internalNodeChildNodes[internalNodeIndex];\n"
- " \n"
- " int2 leafIndexRange; //x == min leaf index, y == max leaf index\n"
- " \n"
- " //Find lowest leaf index covered by this internal node\n"
- " {\n"
- " int lowestIndex = childNodes.x; //childNodes.x == Left child\n"
- " while( !isLeafNode(lowestIndex) ) lowestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(lowestIndex) ].x;\n"
- " leafIndexRange.x = lowestIndex;\n"
- " }\n"
- " \n"
- " //Find highest leaf index covered by this internal node\n"
- " {\n"
- " int highestIndex = childNodes.y; //childNodes.y == Right child\n"
- " while( !isLeafNode(highestIndex) ) highestIndex = internalNodeChildNodes[ getIndexWithInternalNodeMarkerRemoved(highestIndex) ].y;\n"
- " leafIndexRange.y = highestIndex;\n"
- " }\n"
- " \n"
- " //\n"
- " out_leafIndexRanges[internalNodeIndex] = leafIndexRange;\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl
deleted file mode 100644
index 93f77a6433..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sap.cl
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#define NEW_PAIR_MARKER -1
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} btAabbCL;
-
-
-/// conservative test for overlap between two aabbs
-bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);
-bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)
-{
- bool overlap = true;
- overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
- overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
- overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
- return overlap;
-}
-bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);
-bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)
-{
- bool overlap = true;
- overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
- overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
- overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
- return overlap;
-}
-
-bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);
-bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)
-{
- bool overlap = true;
- overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;
- overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;
- overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;
- return overlap;
-}
-
-
-__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)
-{
- int i = get_global_id(0);
- if (i>=numUnsortedAabbs)
- return;
-
- int j = get_global_id(1);
- if (j>=numUnSortedAabbs2)
- return;
-
-
- __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];
- __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];
-
- if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))
- {
- int4 myPair;
-
- int xIndex = unsortedAabbPtr[0].m_minIndices[3];
- int yIndex = unsortedAabbPtr2[0].m_minIndices[3];
- if (xIndex>yIndex)
- {
- int tmp = xIndex;
- xIndex=yIndex;
- yIndex=tmp;
- }
-
- myPair.x = xIndex;
- myPair.y = yIndex;
- myPair.z = NEW_PAIR_MARKER;
- myPair.w = NEW_PAIR_MARKER;
-
-
- int curPair = atomic_inc (pairCount);
- if (curPair<maxPairs)
- {
- pairsOut[curPair] = myPair; //flush to main memory
- }
- }
-}
-
-
-
-__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
-{
- int i = get_global_id(0);
- if (i>=numObjects)
- return;
- for (int j=i+1;j<numObjects;j++)
- {
- if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
- {
- int4 myPair;
- myPair.x = aabbs[i].m_minIndices[3];
- myPair.y = aabbs[j].m_minIndices[3];
- myPair.z = NEW_PAIR_MARKER;
- myPair.w = NEW_PAIR_MARKER;
-
- int curPair = atomic_inc (pairCount);
- if (curPair<maxPairs)
- {
- pairsOut[curPair] = myPair; //flush to main memory
- }
- }
- }
-}
-
-__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
-{
- int i = get_global_id(0);
- if (i>=numObjects)
- return;
- for (int j=i+1;j<numObjects;j++)
- {
- if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis]))
- {
- break;
- }
- if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
- {
- int4 myPair;
- myPair.x = aabbs[i].m_minIndices[3];
- myPair.y = aabbs[j].m_minIndices[3];
- myPair.z = NEW_PAIR_MARKER;
- myPair.w = NEW_PAIR_MARKER;
-
- int curPair = atomic_inc (pairCount);
- if (curPair<maxPairs)
- {
- pairsOut[curPair] = myPair; //flush to main memory
- }
- }
- }
-}
-
-
-
-
-__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
-{
- int i = get_global_id(0);
- int localId = get_local_id(0);
-
- __local int numActiveWgItems[1];
- __local int breakRequest[1];
-
- if (localId==0)
- {
- numActiveWgItems[0] = 0;
- breakRequest[0] = 0;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
- atomic_inc(numActiveWgItems);
- barrier(CLK_LOCAL_MEM_FENCE);
- int localBreak = 0;
-
- int j=i+1;
- do
- {
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (j<numObjects)
- {
- if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis]))
- {
- if (!localBreak)
- {
- atomic_inc(breakRequest);
- localBreak = 1;
- }
- }
- }
-
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (j>=numObjects && !localBreak)
- {
- atomic_inc(breakRequest);
- localBreak = 1;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (!localBreak)
- {
- if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))
- {
- int4 myPair;
- myPair.x = aabbs[i].m_minIndices[3];
- myPair.y = aabbs[j].m_minIndices[3];
- myPair.z = NEW_PAIR_MARKER;
- myPair.w = NEW_PAIR_MARKER;
-
- int curPair = atomic_inc (pairCount);
- if (curPair<maxPairs)
- {
- pairsOut[curPair] = myPair; //flush to main memory
- }
- }
- }
- j++;
-
- } while (breakRequest[0]<numActiveWgItems[0]);
-}
-
-
-__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)
-{
- int i = get_global_id(0);
- int localId = get_local_id(0);
-
- __local int numActiveWgItems[1];
- __local int breakRequest[1];
- __local btAabbCL localAabbs[128];// = aabbs[i];
-
- btAabbCL myAabb;
-
- myAabb = (i<numObjects)? aabbs[i]:aabbs[0];
- float testValue = myAabb.m_maxElems[axis];
-
- if (localId==0)
- {
- numActiveWgItems[0] = 0;
- breakRequest[0] = 0;
- }
- int localCount=0;
- int block=0;
- localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];
- localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];
-
- barrier(CLK_LOCAL_MEM_FENCE);
- atomic_inc(numActiveWgItems);
- barrier(CLK_LOCAL_MEM_FENCE);
- int localBreak = 0;
-
- int j=i+1;
- do
- {
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (j<numObjects)
- {
- if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis]))
- {
- if (!localBreak)
- {
- atomic_inc(breakRequest);
- localBreak = 1;
- }
- }
- }
-
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (j>=numObjects && !localBreak)
- {
- atomic_inc(breakRequest);
- localBreak = 1;
- }
- barrier(CLK_LOCAL_MEM_FENCE);
-
- if (!localBreak)
- {
- if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))
- {
- int4 myPair;
- myPair.x = myAabb.m_minIndices[3];
- myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];
- myPair.z = NEW_PAIR_MARKER;
- myPair.w = NEW_PAIR_MARKER;
-
- int curPair = atomic_inc (pairCount);
- if (curPair<maxPairs)
- {
- pairsOut[curPair] = myPair; //flush to main memory
- }
- }
- }
-
- barrier(CLK_LOCAL_MEM_FENCE);
-
- localCount++;
- if (localCount==64)
- {
- localCount = 0;
- block+=64;
- localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];
- localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];
- }
- j++;
-
- } while (breakRequest[0]<numActiveWgItems[0]);
-
-}
-
-
-
-
-//http://stereopsis.com/radix.html
-unsigned int FloatFlip(float fl);
-unsigned int FloatFlip(float fl)
-{
- unsigned int f = *(unsigned int*)&fl;
- unsigned int mask = -(int)(f >> 31) | 0x80000000;
- return f ^ mask;
-}
-float IFloatFlip(unsigned int f);
-float IFloatFlip(unsigned int f)
-{
- unsigned int mask = ((f >> 31) - 1) | 0x80000000;
- unsigned int fl = f ^ mask;
- return *(float*)&fl;
-}
-
-
-
-
-__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)
-{
- int i = get_global_id(0);
- if (i>=numObjects)
- return;
- int src = destAabbs[i].m_maxIndices[3];
- destAabbs[i] = allAabbs[src];
- destAabbs[i].m_maxIndices[3] = src;
-}
-
-
-__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)
-{
- int i = get_global_id(0);
- if (i>=numObjects)
- return;
-
-
- sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);
- sortData[i].y = i;
-
-}
-
-
-__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)
-{
- int i = get_global_id(0);
- if (i>=numObjects)
- return;
-
- sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];
-}
-
-
-
-__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)
-{
- int i = get_global_id(0);
- if (i>=numAabbs)
- return;
-
- btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];
-
- float4 s;
- s = (smallAabb.m_max+smallAabb.m_min)*0.5f;
- sum[i]=s;
- sum2[i]=s*s;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h b/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
deleted file mode 100644
index d6999b94cb..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/BroadphaseCollision/kernels/sapKernels.h
+++ /dev/null
@@ -1,341 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* sapCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Erwin Coumans\n"
- "#define NEW_PAIR_MARKER -1\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} btAabbCL;\n"
- "/// conservative test for overlap between two aabbs\n"
- "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2);\n"
- "bool TestAabbAgainstAabb2(const btAabbCL* aabb1, __local const btAabbCL* aabb2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
- " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
- " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
- "bool TestAabbAgainstAabb2GlobalGlobal(__global const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
- " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
- " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2);\n"
- "bool TestAabbAgainstAabb2Global(const btAabbCL* aabb1, __global const btAabbCL* aabb2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabb1->m_min.x > aabb2->m_max.x || aabb1->m_max.x < aabb2->m_min.x) ? false : overlap;\n"
- " overlap = (aabb1->m_min.z > aabb2->m_max.z || aabb1->m_max.z < aabb2->m_min.z) ? false : overlap;\n"
- " overlap = (aabb1->m_min.y > aabb2->m_max.y || aabb1->m_max.y < aabb2->m_min.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "__kernel void computePairsKernelTwoArrays( __global const btAabbCL* unsortedAabbs, __global const int* unsortedAabbMapping, __global const int* unsortedAabbMapping2, volatile __global int4* pairsOut,volatile __global int* pairCount, int numUnsortedAabbs, int numUnSortedAabbs2, int axis, int maxPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numUnsortedAabbs)\n"
- " return;\n"
- " int j = get_global_id(1);\n"
- " if (j>=numUnSortedAabbs2)\n"
- " return;\n"
- " __global const btAabbCL* unsortedAabbPtr = &unsortedAabbs[unsortedAabbMapping[i]];\n"
- " __global const btAabbCL* unsortedAabbPtr2 = &unsortedAabbs[unsortedAabbMapping2[j]];\n"
- " if (TestAabbAgainstAabb2GlobalGlobal(unsortedAabbPtr,unsortedAabbPtr2))\n"
- " {\n"
- " int4 myPair;\n"
- " \n"
- " int xIndex = unsortedAabbPtr[0].m_minIndices[3];\n"
- " int yIndex = unsortedAabbPtr2[0].m_minIndices[3];\n"
- " if (xIndex>yIndex)\n"
- " {\n"
- " int tmp = xIndex;\n"
- " xIndex=yIndex;\n"
- " yIndex=tmp;\n"
- " }\n"
- " \n"
- " myPair.x = xIndex;\n"
- " myPair.y = yIndex;\n"
- " myPair.z = NEW_PAIR_MARKER;\n"
- " myPair.w = NEW_PAIR_MARKER;\n"
- " int curPair = atomic_inc (pairCount);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " pairsOut[curPair] = myPair; //flush to main memory\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void computePairsKernelBruteForce( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numObjects)\n"
- " return;\n"
- " for (int j=i+1;j<numObjects;j++)\n"
- " {\n"
- " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
- " {\n"
- " int4 myPair;\n"
- " myPair.x = aabbs[i].m_minIndices[3];\n"
- " myPair.y = aabbs[j].m_minIndices[3];\n"
- " myPair.z = NEW_PAIR_MARKER;\n"
- " myPair.w = NEW_PAIR_MARKER;\n"
- " int curPair = atomic_inc (pairCount);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " pairsOut[curPair] = myPair; //flush to main memory\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void computePairsKernelOriginal( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numObjects)\n"
- " return;\n"
- " for (int j=i+1;j<numObjects;j++)\n"
- " {\n"
- " if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
- " {\n"
- " break;\n"
- " }\n"
- " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
- " {\n"
- " int4 myPair;\n"
- " myPair.x = aabbs[i].m_minIndices[3];\n"
- " myPair.y = aabbs[j].m_minIndices[3];\n"
- " myPair.z = NEW_PAIR_MARKER;\n"
- " myPair.w = NEW_PAIR_MARKER;\n"
- " int curPair = atomic_inc (pairCount);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " pairsOut[curPair] = myPair; //flush to main memory\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void computePairsKernelBarrier( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int localId = get_local_id(0);\n"
- " __local int numActiveWgItems[1];\n"
- " __local int breakRequest[1];\n"
- " if (localId==0)\n"
- " {\n"
- " numActiveWgItems[0] = 0;\n"
- " breakRequest[0] = 0;\n"
- " }\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " atomic_inc(numActiveWgItems);\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " int localBreak = 0;\n"
- " int j=i+1;\n"
- " do\n"
- " {\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (j<numObjects)\n"
- " {\n"
- " if(aabbs[i].m_maxElems[axis] < (aabbs[j].m_minElems[axis])) \n"
- " {\n"
- " if (!localBreak)\n"
- " {\n"
- " atomic_inc(breakRequest);\n"
- " localBreak = 1;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (j>=numObjects && !localBreak)\n"
- " {\n"
- " atomic_inc(breakRequest);\n"
- " localBreak = 1;\n"
- " }\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (!localBreak)\n"
- " {\n"
- " if (TestAabbAgainstAabb2GlobalGlobal(&aabbs[i],&aabbs[j]))\n"
- " {\n"
- " int4 myPair;\n"
- " myPair.x = aabbs[i].m_minIndices[3];\n"
- " myPair.y = aabbs[j].m_minIndices[3];\n"
- " myPair.z = NEW_PAIR_MARKER;\n"
- " myPair.w = NEW_PAIR_MARKER;\n"
- " int curPair = atomic_inc (pairCount);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " pairsOut[curPair] = myPair; //flush to main memory\n"
- " }\n"
- " }\n"
- " }\n"
- " j++;\n"
- " } while (breakRequest[0]<numActiveWgItems[0]);\n"
- "}\n"
- "__kernel void computePairsKernelLocalSharedMemory( __global const btAabbCL* aabbs, volatile __global int4* pairsOut,volatile __global int* pairCount, int numObjects, int axis, int maxPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int localId = get_local_id(0);\n"
- " __local int numActiveWgItems[1];\n"
- " __local int breakRequest[1];\n"
- " __local btAabbCL localAabbs[128];// = aabbs[i];\n"
- " \n"
- " btAabbCL myAabb;\n"
- " \n"
- " myAabb = (i<numObjects)? aabbs[i]:aabbs[0];\n"
- " float testValue = myAabb.m_maxElems[axis];\n"
- " \n"
- " if (localId==0)\n"
- " {\n"
- " numActiveWgItems[0] = 0;\n"
- " breakRequest[0] = 0;\n"
- " }\n"
- " int localCount=0;\n"
- " int block=0;\n"
- " localAabbs[localId] = (i+block)<numObjects? aabbs[i+block] : aabbs[0];\n"
- " localAabbs[localId+64] = (i+block+64)<numObjects? aabbs[i+block+64]: aabbs[0];\n"
- " \n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " atomic_inc(numActiveWgItems);\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " int localBreak = 0;\n"
- " \n"
- " int j=i+1;\n"
- " do\n"
- " {\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (j<numObjects)\n"
- " {\n"
- " if(testValue < (localAabbs[localCount+localId+1].m_minElems[axis])) \n"
- " {\n"
- " if (!localBreak)\n"
- " {\n"
- " atomic_inc(breakRequest);\n"
- " localBreak = 1;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (j>=numObjects && !localBreak)\n"
- " {\n"
- " atomic_inc(breakRequest);\n"
- " localBreak = 1;\n"
- " }\n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " \n"
- " if (!localBreak)\n"
- " {\n"
- " if (TestAabbAgainstAabb2(&myAabb,&localAabbs[localCount+localId+1]))\n"
- " {\n"
- " int4 myPair;\n"
- " myPair.x = myAabb.m_minIndices[3];\n"
- " myPair.y = localAabbs[localCount+localId+1].m_minIndices[3];\n"
- " myPair.z = NEW_PAIR_MARKER;\n"
- " myPair.w = NEW_PAIR_MARKER;\n"
- " int curPair = atomic_inc (pairCount);\n"
- " if (curPair<maxPairs)\n"
- " {\n"
- " pairsOut[curPair] = myPair; //flush to main memory\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " barrier(CLK_LOCAL_MEM_FENCE);\n"
- " localCount++;\n"
- " if (localCount==64)\n"
- " {\n"
- " localCount = 0;\n"
- " block+=64; \n"
- " localAabbs[localId] = ((i+block)<numObjects) ? aabbs[i+block] : aabbs[0];\n"
- " localAabbs[localId+64] = ((i+64+block)<numObjects) ? aabbs[i+block+64] : aabbs[0];\n"
- " }\n"
- " j++;\n"
- " \n"
- " } while (breakRequest[0]<numActiveWgItems[0]);\n"
- " \n"
- "}\n"
- "//http://stereopsis.com/radix.html\n"
- "unsigned int FloatFlip(float fl);\n"
- "unsigned int FloatFlip(float fl)\n"
- "{\n"
- " unsigned int f = *(unsigned int*)&fl;\n"
- " unsigned int mask = -(int)(f >> 31) | 0x80000000;\n"
- " return f ^ mask;\n"
- "}\n"
- "float IFloatFlip(unsigned int f);\n"
- "float IFloatFlip(unsigned int f)\n"
- "{\n"
- " unsigned int mask = ((f >> 31) - 1) | 0x80000000;\n"
- " unsigned int fl = f ^ mask;\n"
- " return *(float*)&fl;\n"
- "}\n"
- "__kernel void copyAabbsKernel( __global const btAabbCL* allAabbs, __global btAabbCL* destAabbs, int numObjects)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numObjects)\n"
- " return;\n"
- " int src = destAabbs[i].m_maxIndices[3];\n"
- " destAabbs[i] = allAabbs[src];\n"
- " destAabbs[i].m_maxIndices[3] = src;\n"
- "}\n"
- "__kernel void flipFloatKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global int2* sortData, int numObjects, int axis)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numObjects)\n"
- " return;\n"
- " \n"
- " \n"
- " sortData[i].x = FloatFlip(allAabbs[smallAabbMapping[i]].m_minElems[axis]);\n"
- " sortData[i].y = i;\n"
- " \n"
- "}\n"
- "__kernel void scatterKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, volatile __global const int2* sortData, __global btAabbCL* sortedAabbs, int numObjects)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numObjects)\n"
- " return;\n"
- " \n"
- " sortedAabbs[i] = allAabbs[smallAabbMapping[sortData[i].y]];\n"
- "}\n"
- "__kernel void prepareSumVarianceKernel( __global const btAabbCL* allAabbs, __global const int* smallAabbMapping, __global float4* sum, __global float4* sum2,int numAabbs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numAabbs)\n"
- " return;\n"
- " \n"
- " btAabbCL smallAabb = allAabbs[smallAabbMapping[i]];\n"
- " \n"
- " float4 s;\n"
- " s = (smallAabb.m_max+smallAabb.m_min)*0.5f;\n"
- " sum[i]=s;\n"
- " sum2[i]=s*s; \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
deleted file mode 100644
index 6146538263..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLInclude.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_OPENCL_INCLUDE_H
-#define B3_OPENCL_INCLUDE_H
-
-#ifdef B3_USE_CLEW
-#include "clew/clew.h"
-#else
-
-#ifdef __APPLE__
-#ifdef USE_MINICL
-#include <MiniCL/cl.h>
-#else
-#include <OpenCL/cl.h>
-#include <OpenCL/cl_ext.h> //clLogMessagesToStderrAPPLE
-#endif
-#else
-#ifdef USE_MINICL
-#include <MiniCL/cl.h>
-#else
-#include <CL/cl.h>
-#ifdef _WIN32
-#include "CL/cl_gl.h"
-#endif //_WIN32
-#endif
-#endif //__APPLE__
-#endif //B3_USE_CLEW
-
-#include <assert.h>
-#include <stdio.h>
-#define oclCHECKERROR(a, b) \
- if ((a) != (b)) \
- { \
- printf("OCL Error : %d\n", (a)); \
- assert((a) == (b)); \
- }
-
-#endif //B3_OPENCL_INCLUDE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
deleted file mode 100644
index fe54ea5ec9..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.cpp
+++ /dev/null
@@ -1,963 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//Original author: Roman Ponomarev
-//Mostly Reimplemented by Erwin Coumans
-
-bool gDebugForceLoadingFromSource = false;
-bool gDebugSkipLoadingBinary = false;
-
-#include "Bullet3Common/b3Logging.h"
-
-#include <string.h>
-
-#ifdef _WIN32
-#pragma warning(disable : 4996)
-#endif
-#include "b3OpenCLUtils.h"
-//#include "b3OpenCLInclude.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define B3_MAX_CL_DEVICES 16 //who needs 16 devices?
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include <assert.h>
-#define b3Assert assert
-#ifndef _WIN32
-#include <sys/stat.h>
-
-#endif
-
-static const char* sCachedBinaryPath = "cache";
-
-//Set the preferred platform vendor using the OpenCL SDK
-static const char* spPlatformVendor =
-#if defined(CL_PLATFORM_MINI_CL)
- "MiniCL, SCEA";
-#elif defined(CL_PLATFORM_AMD)
- "Advanced Micro Devices, Inc.";
-#elif defined(CL_PLATFORM_NVIDIA)
- "NVIDIA Corporation";
-#elif defined(CL_PLATFORM_INTEL)
- "Intel(R) Corporation";
-#elif defined(B3_USE_CLEW)
- "clew (OpenCL Extension Wrangler library)";
-#else
- "Unknown Vendor";
-#endif
-
-#ifndef CL_PLATFORM_MINI_CL
-#ifdef _WIN32
-#ifndef B3_USE_CLEW
-#include "CL/cl_gl.h"
-#endif //B3_USE_CLEW
-#endif //_WIN32
-#endif
-
-void MyFatalBreakAPPLE(const char* errstr,
- const void* private_info,
- size_t cb,
- void* user_data)
-{
- const char* patloc = strstr(errstr, "Warning");
- //find out if it is a warning or error, exit if error
-
- if (patloc)
- {
- b3Warning("Warning: %s\n", errstr);
- }
- else
- {
- b3Error("Error: %s\n", errstr);
- b3Assert(0);
- }
-}
-
-#ifdef B3_USE_CLEW
-
-int b3OpenCLUtils_clewInit()
-{
- int result = -1;
-
-#ifdef _WIN32
- const char* cl = "OpenCL.dll";
-#elif defined __APPLE__
- const char* cl = "/System/Library/Frameworks/OpenCL.framework/Versions/Current/OpenCL";
-#else //presumable Linux? \
- //linux (tested on Ubuntu 12.10 with Catalyst 13.4 beta drivers, not that there is no symbolic link from libOpenCL.so
- const char* cl = "libOpenCL.so.1";
- result = clewInit(cl);
- if (result != CLEW_SUCCESS)
- {
- cl = "libOpenCL.so";
- }
- else
- {
- clewExit();
- }
-#endif
- result = clewInit(cl);
- if (result != CLEW_SUCCESS)
- {
- b3Error("clewInit failed with error code %d\n", result);
- }
- else
- {
- b3Printf("clewInit succesfull using %s\n", cl);
- }
- return result;
-}
-#endif
-
-int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum)
-{
-#ifdef B3_USE_CLEW
- b3OpenCLUtils_clewInit();
-#endif
-
- cl_platform_id pPlatforms[10] = {0};
-
- cl_uint numPlatforms = 0;
- cl_int ciErrNum = clGetPlatformIDs(10, pPlatforms, &numPlatforms);
- //cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
-
- if (ciErrNum != CL_SUCCESS)
- {
- if (pErrNum != NULL)
- *pErrNum = ciErrNum;
- }
- return numPlatforms;
-}
-
-const char* b3OpenCLUtils_getSdkVendorName()
-{
- return spPlatformVendor;
-}
-
-void b3OpenCLUtils_setCachePath(const char* path)
-{
- sCachedBinaryPath = path;
-}
-
-cl_platform_id b3OpenCLUtils_getPlatform(int platformIndex0, cl_int* pErrNum)
-{
-#ifdef B3_USE_CLEW
- b3OpenCLUtils_clewInit();
-#endif
-
- cl_platform_id platform = 0;
- unsigned int platformIndex = (unsigned int)platformIndex0;
- cl_uint numPlatforms;
- cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
-
- if (platformIndex < numPlatforms)
- {
- cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
- ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
- if (ciErrNum != CL_SUCCESS)
- {
- if (pErrNum != NULL)
- *pErrNum = ciErrNum;
- return platform;
- }
-
- platform = platforms[platformIndex];
-
- free(platforms);
- }
-
- return platform;
-}
-
-void b3OpenCLUtils::getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo)
-{
- b3Assert(platform);
- cl_int ciErrNum;
- ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, B3_MAX_STRING_LENGTH, platformInfo->m_platformVendor, NULL);
- oclCHECKERROR(ciErrNum, CL_SUCCESS);
- ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_NAME, B3_MAX_STRING_LENGTH, platformInfo->m_platformName, NULL);
- oclCHECKERROR(ciErrNum, CL_SUCCESS);
- ciErrNum = clGetPlatformInfo(platform, CL_PLATFORM_VERSION, B3_MAX_STRING_LENGTH, platformInfo->m_platformVersion, NULL);
- oclCHECKERROR(ciErrNum, CL_SUCCESS);
-}
-
-void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform)
-{
- b3OpenCLPlatformInfo platformInfo;
- b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
- b3Printf("Platform info:\n");
- b3Printf(" CL_PLATFORM_VENDOR: \t\t\t%s\n", platformInfo.m_platformVendor);
- b3Printf(" CL_PLATFORM_NAME: \t\t\t%s\n", platformInfo.m_platformName);
- b3Printf(" CL_PLATFORM_VERSION: \t\t\t%s\n", platformInfo.m_platformVersion);
-}
-
-cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex)
-{
- cl_context retContext = 0;
- cl_int ciErrNum = 0;
- cl_uint num_entries;
- cl_device_id devices[B3_MAX_CL_DEVICES];
- cl_uint num_devices;
- cl_context_properties* cprops;
-
- /*
- * If we could find our platform, use it. Otherwise pass a NULL and get whatever the
- * implementation thinks we should be using.
- */
- cl_context_properties cps[7] = {0, 0, 0, 0, 0, 0, 0};
- cps[0] = CL_CONTEXT_PLATFORM;
- cps[1] = (cl_context_properties)platform;
-#ifdef _WIN32
-#ifndef B3_USE_CLEW
- if (pGLContext && pGLDC)
- {
- cps[2] = CL_GL_CONTEXT_KHR;
- cps[3] = (cl_context_properties)pGLContext;
- cps[4] = CL_WGL_HDC_KHR;
- cps[5] = (cl_context_properties)pGLDC;
- }
-#endif //B3_USE_CLEW
-#endif //_WIN32
- num_entries = B3_MAX_CL_DEVICES;
-
- num_devices = -1;
-
- ciErrNum = clGetDeviceIDs(
- platform,
- deviceType,
- num_entries,
- devices,
- &num_devices);
-
- if (ciErrNum < 0)
- {
- b3Printf("clGetDeviceIDs returned %d\n", ciErrNum);
- return 0;
- }
- cprops = (NULL == platform) ? NULL : cps;
-
- if (!num_devices)
- return 0;
-
- if (pGLContext)
- {
- //search for the GPU that relates to the OpenCL context
- unsigned int i;
- for (i = 0; i < num_devices; i++)
- {
- retContext = clCreateContext(cprops, 1, &devices[i], NULL, NULL, &ciErrNum);
- if (ciErrNum == CL_SUCCESS)
- break;
- }
- }
- else
- {
- if (preferredDeviceIndex >= 0 && (unsigned int)preferredDeviceIndex < num_devices)
- {
- //create a context of the preferred device index
- retContext = clCreateContext(cprops, 1, &devices[preferredDeviceIndex], NULL, NULL, &ciErrNum);
- }
- else
- {
- //create a context of all devices
-#if defined(__APPLE__)
- retContext = clCreateContext(cprops, num_devices, devices, MyFatalBreakAPPLE, NULL, &ciErrNum);
-#else
- b3Printf("numDevices=%d\n", num_devices);
-
- retContext = clCreateContext(cprops, num_devices, devices, NULL, NULL, &ciErrNum);
-#endif
- }
- }
- if (pErrNum != NULL)
- {
- *pErrNum = ciErrNum;
- };
-
- return retContext;
-}
-
-cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* retPlatformId)
-{
-#ifdef B3_USE_CLEW
- b3OpenCLUtils_clewInit();
-#endif
-
- cl_uint numPlatforms;
- cl_context retContext = 0;
- unsigned int i;
-
- cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);
- if (ciErrNum != CL_SUCCESS)
- {
- if (pErrNum != NULL) *pErrNum = ciErrNum;
- return NULL;
- }
- if (numPlatforms > 0)
- {
- cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * numPlatforms);
- ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);
- if (ciErrNum != CL_SUCCESS)
- {
- if (pErrNum != NULL)
- *pErrNum = ciErrNum;
- free(platforms);
- return NULL;
- }
-
- for (i = 0; i < numPlatforms; ++i)
- {
- char pbuf[128];
- ciErrNum = clGetPlatformInfo(platforms[i],
- CL_PLATFORM_VENDOR,
- sizeof(pbuf),
- pbuf,
- NULL);
- if (ciErrNum != CL_SUCCESS)
- {
- if (pErrNum != NULL) *pErrNum = ciErrNum;
- return NULL;
- }
-
- if (preferredPlatformIndex >= 0 && i == preferredPlatformIndex)
- {
- cl_platform_id tmpPlatform = platforms[0];
- platforms[0] = platforms[i];
- platforms[i] = tmpPlatform;
- break;
- }
- else
- {
- if (!strcmp(pbuf, spPlatformVendor))
- {
- cl_platform_id tmpPlatform = platforms[0];
- platforms[0] = platforms[i];
- platforms[i] = tmpPlatform;
- }
- }
- }
-
- for (i = 0; i < numPlatforms; ++i)
- {
- cl_platform_id platform = platforms[i];
- assert(platform);
-
- retContext = b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLContext, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
-
- if (retContext)
- {
- // printf("OpenCL platform details:\n");
- b3OpenCLPlatformInfo platformInfo;
-
- b3OpenCLUtils::getPlatformInfo(platform, &platformInfo);
-
- if (retPlatformId)
- *retPlatformId = platform;
-
- break;
- }
- }
-
- free(platforms);
- }
- return retContext;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//! Gets the id of the nth device from the context
-//!
-//! @return the id or -1 when out of range
-//! @param cxMainContext OpenCL context
-//! @param device_idx index of the device of interest
-//////////////////////////////////////////////////////////////////////////////
-cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int deviceIndex)
-{
- assert(cxMainContext);
-
- size_t szParmDataBytes;
- cl_device_id* cdDevices;
- cl_device_id device;
-
- // get the list of devices associated with context
- clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
-
- if (szParmDataBytes / sizeof(cl_device_id) < (unsigned int)deviceIndex)
- {
- return (cl_device_id)-1;
- }
-
- cdDevices = (cl_device_id*)malloc(szParmDataBytes);
-
- clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
-
- device = cdDevices[deviceIndex];
- free(cdDevices);
-
- return device;
-}
-
-int b3OpenCLUtils_getNumDevices(cl_context cxMainContext)
-{
- size_t szParamDataBytes;
- int device_count;
- clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes);
- device_count = (int)szParamDataBytes / sizeof(cl_device_id);
- return device_count;
-}
-
-void b3OpenCLUtils::getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info)
-{
- // CL_DEVICE_NAME
- clGetDeviceInfo(device, CL_DEVICE_NAME, B3_MAX_STRING_LENGTH, &info->m_deviceName, NULL);
-
- // CL_DEVICE_VENDOR
- clGetDeviceInfo(device, CL_DEVICE_VENDOR, B3_MAX_STRING_LENGTH, &info->m_deviceVendor, NULL);
-
- // CL_DRIVER_VERSION
- clGetDeviceInfo(device, CL_DRIVER_VERSION, B3_MAX_STRING_LENGTH, &info->m_driverVersion, NULL);
-
- // CL_DEVICE_INFO
- clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info->m_deviceType, NULL);
-
- // CL_DEVICE_MAX_COMPUTE_UNITS
- clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info->m_computeUnits), &info->m_computeUnits, NULL);
-
- // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS
- clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info->m_workitemDims), &info->m_workitemDims, NULL);
-
- // CL_DEVICE_MAX_WORK_ITEM_SIZES
- clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info->m_workItemSize), &info->m_workItemSize, NULL);
-
- // CL_DEVICE_MAX_WORK_GROUP_SIZE
- clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info->m_workgroupSize), &info->m_workgroupSize, NULL);
-
- // CL_DEVICE_MAX_CLOCK_FREQUENCY
- clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info->m_clockFrequency), &info->m_clockFrequency, NULL);
-
- // CL_DEVICE_ADDRESS_BITS
- clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info->m_addressBits), &info->m_addressBits, NULL);
-
- // CL_DEVICE_MAX_MEM_ALLOC_SIZE
- clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info->m_maxMemAllocSize), &info->m_maxMemAllocSize, NULL);
-
- // CL_DEVICE_GLOBAL_MEM_SIZE
- clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info->m_globalMemSize), &info->m_globalMemSize, NULL);
-
- // CL_DEVICE_ERROR_CORRECTION_SUPPORT
- clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info->m_errorCorrectionSupport), &info->m_errorCorrectionSupport, NULL);
-
- // CL_DEVICE_LOCAL_MEM_TYPE
- clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info->m_localMemType), &info->m_localMemType, NULL);
-
- // CL_DEVICE_LOCAL_MEM_SIZE
- clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info->m_localMemSize), &info->m_localMemSize, NULL);
-
- // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE
- clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info->m_constantBufferSize), &info->m_constantBufferSize, NULL);
-
- // CL_DEVICE_QUEUE_PROPERTIES
- clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info->m_queueProperties), &info->m_queueProperties, NULL);
-
- // CL_DEVICE_IMAGE_SUPPORT
- clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info->m_imageSupport), &info->m_imageSupport, NULL);
-
- // CL_DEVICE_MAX_READ_IMAGE_ARGS
- clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info->m_maxReadImageArgs), &info->m_maxReadImageArgs, NULL);
-
- // CL_DEVICE_MAX_WRITE_IMAGE_ARGS
- clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info->m_maxWriteImageArgs), &info->m_maxWriteImageArgs, NULL);
-
- // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH
- clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info->m_image2dMaxWidth, NULL);
- clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info->m_image2dMaxHeight, NULL);
- clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info->m_image3dMaxWidth, NULL);
- clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info->m_image3dMaxHeight, NULL);
- clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info->m_image3dMaxDepth, NULL);
-
- // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines
- clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, B3_MAX_STRING_LENGTH, &info->m_deviceExtensions, NULL);
-
- // CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type>
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info->m_vecWidthChar, NULL);
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info->m_vecWidthShort, NULL);
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info->m_vecWidthInt, NULL);
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info->m_vecWidthLong, NULL);
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info->m_vecWidthFloat, NULL);
- clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info->m_vecWidthDouble, NULL);
-}
-
-void b3OpenCLUtils_printDeviceInfo(cl_device_id device)
-{
- b3OpenCLDeviceInfo info;
- b3OpenCLUtils::getDeviceInfo(device, &info);
- b3Printf("Device Info:\n");
- b3Printf(" CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName);
- b3Printf(" CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor);
- b3Printf(" CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion);
-
- if (info.m_deviceType & CL_DEVICE_TYPE_CPU)
- b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");
- if (info.m_deviceType & CL_DEVICE_TYPE_GPU)
- b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");
- if (info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR)
- b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");
- if (info.m_deviceType & CL_DEVICE_TYPE_DEFAULT)
- b3Printf(" CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");
-
- b3Printf(" CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits);
- b3Printf(" CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%u\n", info.m_workitemDims);
- b3Printf(" CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%u / %u / %u \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]);
- b3Printf(" CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%u\n", info.m_workgroupSize);
- b3Printf(" CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency);
- b3Printf(" CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits);
- b3Printf(" CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize / (1024 * 1024)));
- b3Printf(" CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize / (1024 * 1024)));
- b3Printf(" CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport == CL_TRUE ? "yes" : "no");
- b3Printf(" CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global");
- b3Printf(" CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024));
- b3Printf(" CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024));
- if (info.m_queueProperties & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE)
- b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");
- if (info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE)
- b3Printf(" CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");
-
- b3Printf(" CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport);
-
- b3Printf(" CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs);
- b3Printf(" CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs);
- b3Printf("\n CL_DEVICE_IMAGE <dim>");
- b3Printf("\t\t\t2D_MAX_WIDTH\t %u\n", info.m_image2dMaxWidth);
- b3Printf("\t\t\t\t\t2D_MAX_HEIGHT\t %u\n", info.m_image2dMaxHeight);
- b3Printf("\t\t\t\t\t3D_MAX_WIDTH\t %u\n", info.m_image3dMaxWidth);
- b3Printf("\t\t\t\t\t3D_MAX_HEIGHT\t %u\n", info.m_image3dMaxHeight);
- b3Printf("\t\t\t\t\t3D_MAX_DEPTH\t %u\n", info.m_image3dMaxDepth);
- if (*info.m_deviceExtensions != 0)
- {
- b3Printf("\n CL_DEVICE_EXTENSIONS:%s\n", info.m_deviceExtensions);
- }
- else
- {
- b3Printf(" CL_DEVICE_EXTENSIONS: None\n");
- }
- b3Printf(" CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t");
- b3Printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n",
- info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong, info.m_vecWidthFloat, info.m_vecWidthDouble);
-}
-
-static const char* strip2(const char* name, const char* pattern)
-{
- size_t const patlen = strlen(pattern);
- size_t patcnt = 0;
- const char* oriptr;
- const char* patloc;
- // find how many times the pattern occurs in the original string
- for (oriptr = name; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
- {
- patcnt++;
- }
- return oriptr;
-}
-
-cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSourceOrg, cl_int* pErrNum, const char* additionalMacrosArg, const char* clFileNameForCaching, bool disableBinaryCaching)
-{
- const char* additionalMacros = additionalMacrosArg ? additionalMacrosArg : "";
-
- if (disableBinaryCaching)
- {
- //kernelSourceOrg = 0;
- }
-
- cl_program m_cpProgram = 0;
- cl_int status;
-
- char binaryFileName[B3_MAX_STRING_LENGTH];
-
- char deviceName[256];
- char driverVersion[256];
- const char* strippedName;
- int fileUpToDate = 0;
-#ifdef _WIN32
- int binaryFileValid = 0;
-#endif
- if (!disableBinaryCaching && clFileNameForCaching)
- {
- clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL);
- clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL);
-
- strippedName = strip2(clFileNameForCaching, "\\");
- strippedName = strip2(strippedName, "/");
-
-#ifdef _MSC_VER
- sprintf_s(binaryFileName, B3_MAX_STRING_LENGTH, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
-#else
- sprintf(binaryFileName, "%s/%s.%s.%s.bin", sCachedBinaryPath, strippedName, deviceName, driverVersion);
-#endif
- }
- if (clFileNameForCaching && !(disableBinaryCaching || gDebugSkipLoadingBinary || gDebugForceLoadingFromSource))
- {
-#ifdef _WIN32
- char* bla = 0;
-
- //printf("searching for %s\n", binaryFileName);
-
- FILETIME modtimeBinary;
- CreateDirectoryA(sCachedBinaryPath, 0);
- {
- HANDLE binaryFileHandle = CreateFileA(binaryFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- if (binaryFileHandle == INVALID_HANDLE_VALUE)
- {
- DWORD errorCode;
- errorCode = GetLastError();
- switch (errorCode)
- {
- case ERROR_FILE_NOT_FOUND:
- {
- b3Warning("\nCached file not found %s\n", binaryFileName);
- break;
- }
- case ERROR_PATH_NOT_FOUND:
- {
- b3Warning("\nCached file path not found %s\n", binaryFileName);
- break;
- }
- default:
- {
- b3Warning("\nFailed reading cached file with errorCode = %d\n", errorCode);
- }
- }
- }
- else
- {
- if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary) == 0)
- {
- DWORD errorCode;
- errorCode = GetLastError();
- b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
- }
- else
- {
- binaryFileValid = 1;
- }
- CloseHandle(binaryFileHandle);
- }
-
- if (binaryFileValid)
- {
- HANDLE srcFileHandle = CreateFileA(clFileNameForCaching, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
-
- if (srcFileHandle == INVALID_HANDLE_VALUE)
- {
- const char* prefix[] = {"./", "../", "../../", "../../../", "../../../../"};
- for (int i = 0; (srcFileHandle == INVALID_HANDLE_VALUE) && i < 5; i++)
- {
- char relativeFileName[1024];
- sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
- srcFileHandle = CreateFileA(relativeFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
- }
- }
-
- if (srcFileHandle != INVALID_HANDLE_VALUE)
- {
- FILETIME modtimeSrc;
- if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc) == 0)
- {
- DWORD errorCode;
- errorCode = GetLastError();
- b3Warning("\nGetFileTime errorCode = %d\n", errorCode);
- }
- if ((modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime) || ((modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime) && (modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))
- {
- fileUpToDate = 1;
- }
- else
- {
- b3Warning("\nCached binary file out-of-date (%s)\n", binaryFileName);
- }
- CloseHandle(srcFileHandle);
- }
- else
- {
-#ifdef _DEBUG
- DWORD errorCode;
- errorCode = GetLastError();
- switch (errorCode)
- {
- case ERROR_FILE_NOT_FOUND:
- {
- b3Warning("\nSrc file not found %s\n", clFileNameForCaching);
- break;
- }
- case ERROR_PATH_NOT_FOUND:
- {
- b3Warning("\nSrc path not found %s\n", clFileNameForCaching);
- break;
- }
- default:
- {
- b3Warning("\nnSrc file reading errorCode = %d\n", errorCode);
- }
- }
-
- //we should make sure the src file exists so we can verify the timestamp with binary
- // assert(0);
- b3Warning("Warning: cannot find OpenCL kernel %s to verify timestamp of binary cached kernel %s\n", clFileNameForCaching, binaryFileName);
- fileUpToDate = true;
-#else
- //if we cannot find the source, assume it is OK in release builds
- fileUpToDate = true;
-#endif
- }
- }
- }
-
-#else
- fileUpToDate = true;
- if (mkdir(sCachedBinaryPath, 0777) == -1)
- {
- }
- else
- {
- b3Printf("Succesfully created cache directory: %s\n", sCachedBinaryPath);
- }
-#endif //_WIN32
- }
-
- if (fileUpToDate)
- {
-#ifdef _MSC_VER
- FILE* file;
- if (fopen_s(&file, binaryFileName, "rb") != 0)
- file = 0;
-#else
- FILE* file = fopen(binaryFileName, "rb");
-#endif
-
- if (file)
- {
- size_t binarySize = 0;
- char* binary = 0;
-
- fseek(file, 0L, SEEK_END);
- binarySize = ftell(file);
- rewind(file);
- binary = (char*)malloc(sizeof(char) * binarySize);
- int bytesRead;
- bytesRead = fread(binary, sizeof(char), binarySize, file);
- fclose(file);
-
- m_cpProgram = clCreateProgramWithBinary(clContext, 1, &device, &binarySize, (const unsigned char**)&binary, 0, &status);
- b3Assert(status == CL_SUCCESS);
- status = clBuildProgram(m_cpProgram, 1, &device, additionalMacros, 0, 0);
- b3Assert(status == CL_SUCCESS);
-
- if (status != CL_SUCCESS)
- {
- char* build_log;
- size_t ret_val_size;
- clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
- clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
- build_log[ret_val_size] = '\0';
- b3Error("%s\n", build_log);
- free(build_log);
- b3Assert(0);
- m_cpProgram = 0;
-
- b3Warning("clBuildProgram reported failure on cached binary: %s\n", binaryFileName);
- }
- else
- {
- b3Printf("clBuildProgram successfully compiled cached binary: %s\n", binaryFileName);
- }
- free(binary);
- }
- else
- {
- b3Warning("Cannot open cached binary: %s\n", binaryFileName);
- }
- }
-
- if (!m_cpProgram)
- {
- cl_int localErrNum;
- char* compileFlags;
- int flagsize;
-
- const char* kernelSource = kernelSourceOrg;
-
- if (!kernelSourceOrg || gDebugForceLoadingFromSource)
- {
- if (clFileNameForCaching)
- {
- FILE* file = fopen(clFileNameForCaching, "rb");
- //in many cases the relative path is a few levels up the directory hierarchy, so try it
- if (!file)
- {
- const char* prefix[] = {"../", "../../", "../../../", "../../../../"};
- for (int i = 0; !file && i < 3; i++)
- {
- char relativeFileName[1024];
- sprintf(relativeFileName, "%s%s", prefix[i], clFileNameForCaching);
- file = fopen(relativeFileName, "rb");
- }
- }
-
- if (file)
- {
- char* kernelSrc = 0;
- fseek(file, 0L, SEEK_END);
- int kernelSize = ftell(file);
- rewind(file);
- kernelSrc = (char*)malloc(kernelSize + 1);
- int readBytes;
- readBytes = fread((void*)kernelSrc, 1, kernelSize, file);
- kernelSrc[kernelSize] = 0;
- fclose(file);
- kernelSource = kernelSrc;
- }
- }
- }
-
- size_t program_length = kernelSource ? strlen(kernelSource) : 0;
-#ifdef MAC //or __APPLE__?
- char* flags = "-cl-mad-enable -DMAC ";
-#else
- const char* flags = "";
-#endif
-
- m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum);
- if (localErrNum != CL_SUCCESS)
- {
- if (pErrNum)
- *pErrNum = localErrNum;
- return 0;
- }
-
- // Build the program with 'mad' Optimization option
-
- flagsize = sizeof(char) * (strlen(additionalMacros) + strlen(flags) + 5);
- compileFlags = (char*)malloc(flagsize);
-#ifdef _MSC_VER
- sprintf_s(compileFlags, flagsize, "%s %s", flags, additionalMacros);
-#else
- sprintf(compileFlags, "%s %s", flags, additionalMacros);
-#endif
- localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL);
- if (localErrNum != CL_SUCCESS)
- {
- char* build_log;
- size_t ret_val_size;
- clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);
- build_log = (char*)malloc(sizeof(char) * (ret_val_size + 1));
- clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);
-
- // to be carefully, terminate with \0
- // there's no information in the reference whether the string is 0 terminated or not
- build_log[ret_val_size] = '\0';
-
- b3Error("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);
- free(build_log);
- if (pErrNum)
- *pErrNum = localErrNum;
- return 0;
- }
-
- if (!disableBinaryCaching && clFileNameForCaching)
- { // write to binary
-
- cl_uint numAssociatedDevices;
- status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0);
- b3Assert(status == CL_SUCCESS);
- if (numAssociatedDevices == 1)
- {
- size_t binarySize;
- char* binary;
-
- status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0);
- b3Assert(status == CL_SUCCESS);
-
- binary = (char*)malloc(sizeof(char) * binarySize);
-
- status = clGetProgramInfo(m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0);
- b3Assert(status == CL_SUCCESS);
-
- {
- FILE* file = 0;
-#ifdef _MSC_VER
- if (fopen_s(&file, binaryFileName, "wb") != 0)
- file = 0;
-#else
- file = fopen(binaryFileName, "wb");
-#endif
- if (file)
- {
- fwrite(binary, sizeof(char), binarySize, file);
- fclose(file);
- }
- else
- {
- b3Warning("cannot write file %s\n", binaryFileName);
- }
- }
-
- free(binary);
- }
- }
-
- free(compileFlags);
- }
- return m_cpProgram;
-}
-
-cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros)
-{
- cl_kernel kernel;
- cl_int localErrNum;
-
- cl_program m_cpProgram = prog;
-
- b3Printf("compiling kernel %s ", kernelName);
-
- if (!m_cpProgram)
- {
- m_cpProgram = b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, 0, false);
- }
-
- // Create the kernel
- kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum);
- if (localErrNum != CL_SUCCESS)
- {
- b3Error("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName);
- assert(0);
- if (pErrNum)
- *pErrNum = localErrNum;
- return 0;
- }
-
- if (!prog && m_cpProgram)
- {
- clReleaseProgram(m_cpProgram);
- }
- b3Printf("ready. \n");
-
- if (pErrNum)
- *pErrNum = CL_SUCCESS;
- return kernel;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h b/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
deleted file mode 100644
index 6c82eed2a6..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Initialize/b3OpenCLUtils.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//original author: Roman Ponomarev
-//cleanup by Erwin Coumans
-
-#ifndef B3_OPENCL_UTILS_H
-#define B3_OPENCL_UTILS_H
-
-#include "b3OpenCLInclude.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
- ///C API for OpenCL utilities: convenience functions, see below for C++ API
-
- /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
- /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
- cl_context b3OpenCLUtils_createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex, cl_platform_id* platformId);
-
- int b3OpenCLUtils_getNumDevices(cl_context cxMainContext);
-
- cl_device_id b3OpenCLUtils_getDevice(cl_context cxMainContext, int nr);
-
- void b3OpenCLUtils_printDeviceInfo(cl_device_id device);
-
- cl_kernel b3OpenCLUtils_compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros);
-
- //optional
- cl_program b3OpenCLUtils_compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros, const char* srcFileNameForCaching, bool disableBinaryCaching);
-
- //the following optional APIs provide access using specific platform information
- int b3OpenCLUtils_getNumPlatforms(cl_int* pErrNum);
-
- ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
- cl_platform_id b3OpenCLUtils_getPlatform(int nr, cl_int* pErrNum);
-
- void b3OpenCLUtils_printPlatformInfo(cl_platform_id platform);
-
- const char* b3OpenCLUtils_getSdkVendorName();
-
- ///set the path (directory/folder) where the compiled OpenCL kernel are stored
- void b3OpenCLUtils_setCachePath(const char* path);
-
- cl_context b3OpenCLUtils_createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex);
-
-#ifdef __cplusplus
-}
-
-#define B3_MAX_STRING_LENGTH 1024
-
-typedef struct
-{
- char m_deviceName[B3_MAX_STRING_LENGTH];
- char m_deviceVendor[B3_MAX_STRING_LENGTH];
- char m_driverVersion[B3_MAX_STRING_LENGTH];
- char m_deviceExtensions[B3_MAX_STRING_LENGTH];
-
- cl_device_type m_deviceType;
- cl_uint m_computeUnits;
- size_t m_workitemDims;
- size_t m_workItemSize[3];
- size_t m_image2dMaxWidth;
- size_t m_image2dMaxHeight;
- size_t m_image3dMaxWidth;
- size_t m_image3dMaxHeight;
- size_t m_image3dMaxDepth;
- size_t m_workgroupSize;
- cl_uint m_clockFrequency;
- cl_ulong m_constantBufferSize;
- cl_ulong m_localMemSize;
- cl_ulong m_globalMemSize;
- cl_bool m_errorCorrectionSupport;
- cl_device_local_mem_type m_localMemType;
- cl_uint m_maxReadImageArgs;
- cl_uint m_maxWriteImageArgs;
-
- cl_uint m_addressBits;
- cl_ulong m_maxMemAllocSize;
- cl_command_queue_properties m_queueProperties;
- cl_bool m_imageSupport;
- cl_uint m_vecWidthChar;
- cl_uint m_vecWidthShort;
- cl_uint m_vecWidthInt;
- cl_uint m_vecWidthLong;
- cl_uint m_vecWidthFloat;
- cl_uint m_vecWidthDouble;
-
-} b3OpenCLDeviceInfo;
-
-struct b3OpenCLPlatformInfo
-{
- char m_platformVendor[B3_MAX_STRING_LENGTH];
- char m_platformName[B3_MAX_STRING_LENGTH];
- char m_platformVersion[B3_MAX_STRING_LENGTH];
-
- b3OpenCLPlatformInfo()
- {
- m_platformVendor[0] = 0;
- m_platformName[0] = 0;
- m_platformVersion[0] = 0;
- }
-};
-
-///C++ API for OpenCL utilities: convenience functions
-struct b3OpenCLUtils
-{
- /// CL Context optionally takes a GL context. This is a generic type because we don't really want this code
- /// to have to understand GL types. It is a HGLRC in _WIN32 or a GLXContext otherwise.
- static inline cl_context createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1, cl_platform_id* platformId = 0)
- {
- return b3OpenCLUtils_createContextFromType(deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex, platformId);
- }
-
- static inline int getNumDevices(cl_context cxMainContext)
- {
- return b3OpenCLUtils_getNumDevices(cxMainContext);
- }
- static inline cl_device_id getDevice(cl_context cxMainContext, int nr)
- {
- return b3OpenCLUtils_getDevice(cxMainContext, nr);
- }
-
- static void getDeviceInfo(cl_device_id device, b3OpenCLDeviceInfo* info);
-
- static inline void printDeviceInfo(cl_device_id device)
- {
- b3OpenCLUtils_printDeviceInfo(device);
- }
-
- static inline cl_kernel compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum = 0, cl_program prog = 0, const char* additionalMacros = "")
- {
- return b3OpenCLUtils_compileCLKernelFromString(clContext, device, kernelSource, kernelName, pErrNum, prog, additionalMacros);
- }
-
- //optional
- static inline cl_program compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum = 0, const char* additionalMacros = "", const char* srcFileNameForCaching = 0, bool disableBinaryCaching = false)
- {
- return b3OpenCLUtils_compileCLProgramFromString(clContext, device, kernelSource, pErrNum, additionalMacros, srcFileNameForCaching, disableBinaryCaching);
- }
-
- //the following optional APIs provide access using specific platform information
- static inline int getNumPlatforms(cl_int* pErrNum = 0)
- {
- return b3OpenCLUtils_getNumPlatforms(pErrNum);
- }
- ///get the nr'th platform, where nr is in the range [0..getNumPlatforms)
- static inline cl_platform_id getPlatform(int nr, cl_int* pErrNum = 0)
- {
- return b3OpenCLUtils_getPlatform(nr, pErrNum);
- }
-
- static void getPlatformInfo(cl_platform_id platform, b3OpenCLPlatformInfo* platformInfo);
-
- static inline void printPlatformInfo(cl_platform_id platform)
- {
- b3OpenCLUtils_printPlatformInfo(platform);
- }
-
- static inline const char* getSdkVendorName()
- {
- return b3OpenCLUtils_getSdkVendorName();
- }
- static inline cl_context createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLCtx = 0, void* pGLDC = 0, int preferredDeviceIndex = -1, int preferredPlatformIndex = -1)
- {
- return b3OpenCLUtils_createContextFromPlatform(platform, deviceType, pErrNum, pGLCtx, pGLDC, preferredDeviceIndex, preferredPlatformIndex);
- }
- static void setCachePath(const char* path)
- {
- b3OpenCLUtils_setCachePath(path);
- }
-};
-
-#endif //__cplusplus
-
-#endif // B3_OPENCL_UTILS_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
deleted file mode 100644
index 27835bb747..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef B3_BVH_INFO_H
-#define B3_BVH_INFO_H
-
-#include "Bullet3Common/b3Vector3.h"
-
-struct b3BvhInfo
-{
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
- b3Vector3 m_quantization;
- int m_numNodes;
- int m_numSubTrees;
- int m_nodeOffset;
- int m_subTreeOffset;
-};
-
-#endif //B3_BVH_INFO_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
deleted file mode 100644
index 4db717f8c3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-
-#if 0
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3ContactCache.h"
-#include "Bullet3Common/b3Transform.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-b3Scalar gContactBreakingThreshold = b3Scalar(0.02);
-
-///gContactCalcArea3Points will approximate the convex hull area using 3 points
-///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
-bool gContactCalcArea3Points = true;
-
-
-
-
-static inline b3Scalar calcArea4Points(const b3Vector3 &p0,const b3Vector3 &p1,const b3Vector3 &p2,const b3Vector3 &p3)
-{
- // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
-
- b3Vector3 a[3],b[3];
- a[0] = p0 - p1;
- a[1] = p0 - p2;
- a[2] = p0 - p3;
- b[0] = p2 - p3;
- b[1] = p1 - p3;
- b[2] = p1 - p2;
-
- //todo: Following 3 cross production can be easily optimized by SIMD.
- b3Vector3 tmp0 = a[0].cross(b[0]);
- b3Vector3 tmp1 = a[1].cross(b[1]);
- b3Vector3 tmp2 = a[2].cross(b[2]);
-
- return b3Max(b3Max(tmp0.length2(),tmp1.length2()),tmp2.length2());
-}
-#if 0
-
-//using localPointA for all points
-int b3ContactCache::sortCachedPoints(const b3Vector3& pt)
-{
- //calculate 4 possible cases areas, and take biggest area
- //also need to keep 'deepest'
-
- int maxPenetrationIndex = -1;
-#define KEEP_DEEPEST_POINT 1
-#ifdef KEEP_DEEPEST_POINT
- b3Scalar maxPenetration = pt.getDistance();
- for (int i=0;i<4;i++)
- {
- if (m_pointCache[i].getDistance() < maxPenetration)
- {
- maxPenetrationIndex = i;
- maxPenetration = m_pointCache[i].getDistance();
- }
- }
-#endif //KEEP_DEEPEST_POINT
-
- b3Scalar res0(b3Scalar(0.)),res1(b3Scalar(0.)),res2(b3Scalar(0.)),res3(b3Scalar(0.));
-
- if (gContactCalcArea3Points)
- {
- if (maxPenetrationIndex != 0)
- {
- b3Vector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
- b3Vector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
- b3Vector3 cross = a0.cross(b0);
- res0 = cross.length2();
- }
- if (maxPenetrationIndex != 1)
- {
- b3Vector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- b3Vector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
- b3Vector3 cross = a1.cross(b1);
- res1 = cross.length2();
- }
-
- if (maxPenetrationIndex != 2)
- {
- b3Vector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- b3Vector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
- b3Vector3 cross = a2.cross(b2);
- res2 = cross.length2();
- }
-
- if (maxPenetrationIndex != 3)
- {
- b3Vector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
- b3Vector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
- b3Vector3 cross = a3.cross(b3);
- res3 = cross.length2();
- }
- }
- else
- {
- if(maxPenetrationIndex != 0) {
- res0 = calcArea4Points(pt.m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
- }
-
- if(maxPenetrationIndex != 1) {
- res1 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[2].m_localPointA,m_pointCache[3].m_localPointA);
- }
-
- if(maxPenetrationIndex != 2) {
- res2 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[3].m_localPointA);
- }
-
- if(maxPenetrationIndex != 3) {
- res3 = calcArea4Points(pt.m_localPointA,m_pointCache[0].m_localPointA,m_pointCache[1].m_localPointA,m_pointCache[2].m_localPointA);
- }
- }
- b3Vector4 maxvec(res0,res1,res2,res3);
- int biggestarea = maxvec.closestAxis4();
- return biggestarea;
-
-}
-
-
-int b3ContactCache::getCacheEntry(const b3Vector3& newPoint) const
-{
- b3Scalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
- int size = getNumContacts();
- int nearestPoint = -1;
- for( int i = 0; i < size; i++ )
- {
- const b3Vector3 &mp = m_pointCache[i];
-
- b3Vector3 diffA = mp.m_localPointA- newPoint.m_localPointA;
- const b3Scalar distToManiPoint = diffA.dot(diffA);
- if( distToManiPoint < shortestDist )
- {
- shortestDist = distToManiPoint;
- nearestPoint = i;
- }
- }
- return nearestPoint;
-}
-
-int b3ContactCache::addManifoldPoint(const b3Vector3& newPoint)
-{
- b3Assert(validContactDistance(newPoint));
-
- int insertIndex = getNumContacts();
- if (insertIndex == MANIFOLD_CACHE_SIZE)
- {
-#if MANIFOLD_CACHE_SIZE >= 4
- //sort cache so best points come first, based on area
- insertIndex = sortCachedPoints(newPoint);
-#else
- insertIndex = 0;
-#endif
- clearUserCache(m_pointCache[insertIndex]);
-
- } else
- {
- m_cachedPoints++;
-
-
- }
- if (insertIndex<0)
- insertIndex=0;
-
- //b3Assert(m_pointCache[insertIndex].m_userPersistentData==0);
- m_pointCache[insertIndex] = newPoint;
- return insertIndex;
-}
-
-#endif
-
-bool b3ContactCache::validContactDistance(const b3Vector3& pt)
-{
- return pt.w <= gContactBreakingThreshold;
-}
-
-void b3ContactCache::removeContactPoint(struct b3Contact4Data& newContactCache,int i)
-{
- int numContacts = b3Contact4Data_getNumPoints(&newContactCache);
- if (i!=(numContacts-1))
- {
- b3Swap(newContactCache.m_localPosA[i],newContactCache.m_localPosA[numContacts-1]);
- b3Swap(newContactCache.m_localPosB[i],newContactCache.m_localPosB[numContacts-1]);
- b3Swap(newContactCache.m_worldPosB[i],newContactCache.m_worldPosB[numContacts-1]);
- }
- b3Contact4Data_setNumPoints(&newContactCache,numContacts-1);
-
-}
-
-
-void b3ContactCache::refreshContactPoints(const b3Transform& trA,const b3Transform& trB, struct b3Contact4Data& contacts)
-{
-
- int numContacts = b3Contact4Data_getNumPoints(&contacts);
-
-
- int i;
- /// first refresh worldspace positions and distance
- for (i=numContacts-1;i>=0;i--)
- {
- b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
- b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
- contacts.m_worldPosB[i] = worldPosB;
- float distance = (worldPosA - worldPosB).dot(contacts.m_worldNormalOnB);
- contacts.m_worldPosB[i].w = distance;
- }
-
- /// then
- b3Scalar distance2d;
- b3Vector3 projectedDifference,projectedPoint;
- for (i=numContacts-1;i>=0;i--)
- {
- b3Vector3 worldPosA = trA( contacts.m_localPosA[i]);
- b3Vector3 worldPosB = trB( contacts.m_localPosB[i]);
- b3Vector3&pt = contacts.m_worldPosB[i];
- //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
- if (!validContactDistance(pt))
- {
- removeContactPoint(contacts,i);
- } else
- {
- //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
- projectedPoint = worldPosA - contacts.m_worldNormalOnB * contacts.m_worldPosB[i].w;
- projectedDifference = contacts.m_worldPosB[i] - projectedPoint;
- distance2d = projectedDifference.dot(projectedDifference);
- if (distance2d > gContactBreakingThreshold*gContactBreakingThreshold )
- {
- removeContactPoint(contacts,i);
- } else
- {
- ////contact point processed callback
- //if (gContactProcessedCallback)
- // (*gContactProcessedCallback)(manifoldPoint,(void*)m_body0,(void*)m_body1);
- }
- }
- }
-
-
-}
-
-#endif
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
deleted file mode 100644
index a15fd0b2a9..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h
+++ /dev/null
@@ -1,62 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_CONTACT_CACHE_H
-#define B3_CONTACT_CACHE_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Common/b3AlignedAllocator.h"
-
-///maximum contact breaking and merging threshold
-extern b3Scalar gContactBreakingThreshold;
-
-#define MANIFOLD_CACHE_SIZE 4
-
-///b3ContactCache is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
-///Those contact points are created by the collision narrow phase.
-///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
-///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
-///reduces the cache to 4 points, when more then 4 points are added, using following rules:
-///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
-///note that some pairs of objects might have more then one contact manifold.
-B3_ATTRIBUTE_ALIGNED16(class)
-b3ContactCache
-{
- /// sort cached points so most isolated points come first
- int sortCachedPoints(const b3Vector3& pt);
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- int addManifoldPoint(const b3Vector3& newPoint);
-
- /*void replaceContactPoint(const b3Vector3& newPoint,int insertIndex)
- {
- b3Assert(validContactDistance(newPoint));
- m_pointCache[insertIndex] = newPoint;
- }
- */
-
- static bool validContactDistance(const b3Vector3& pt);
-
- /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
- static void refreshContactPoints(const b3Transform& trA, const b3Transform& trB, struct b3Contact4Data& newContactCache);
-
- static void removeContactPoint(struct b3Contact4Data & newContactCache, int i);
-};
-
-#endif //B3_CONTACT_CACHE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
deleted file mode 100644
index 54a104c5c8..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.cpp
+++ /dev/null
@@ -1,4408 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-bool findSeparatingAxisOnGpu = true;
-bool splitSearchSepAxisConcave = false;
-bool splitSearchSepAxisConvex = true;
-bool useMprGpu = true; //use mpr for edge-edge (+contact point) or sat. Needs testing on main OpenCL platforms, before enabling...
-bool bvhTraversalKernelGPU = true;
-bool findConcaveSeparatingAxisKernelGPU = true;
-bool clipConcaveFacesAndFindContactsCPU = false; //false;//true;
-bool clipConvexFacesAndFindContactsCPU = false; //false;//true;
-bool reduceConcaveContactsOnGPU = true; //false;
-bool reduceConvexContactsOnGPU = true; //false;
-bool findConvexClippingFacesGPU = true;
-bool useGjk = false; ///option for CPU/host testing, when findSeparatingAxisOnGpu = false
-bool useGjkContacts = false; //////option for CPU/host testing when findSeparatingAxisOnGpu = false
-
-static int myframecount = 0; ///for testing
-
-///This file was written by Erwin Coumans
-///Separating axis rest based on work from Pierre Terdiman, see
-///And contact clipping based on work from Simon Hobbs
-
-//#define B3_DEBUG_SAT_FACE
-
-//#define CHECK_ON_HOST
-
-#ifdef CHECK_ON_HOST
-//#define PERSISTENT_CONTACTS_HOST
-#endif
-
-int b3g_actualSATPairTests = 0;
-
-#include "b3ConvexHullContact.h"
-#include <string.h> //memcpy
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
-
-#include "Bullet3OpenCL/NarrowphaseCollision/b3ContactCache.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-typedef b3AlignedObjectArray<b3Vector3> b3VertexArray;
-
-#include <float.h> //for FLT_MAX
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-//#include "AdlQuaternion.h"
-
-#include "kernels/satKernels.h"
-#include "kernels/mprKernels.h"
-
-#include "kernels/satConcaveKernels.h"
-
-#include "kernels/satClipHullContacts.h"
-#include "kernels/bvhTraversal.h"
-#include "kernels/primitiveContacts.h"
-
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-#define BT_NARROWPHASE_SAT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl"
-#define BT_NARROWPHASE_SAT_CONCAVE_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl"
-
-#define BT_NARROWPHASE_MPR_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl"
-
-#define BT_NARROWPHASE_CLIPHULL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl"
-#define BT_NARROWPHASE_BVH_TRAVERSAL_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl"
-#define BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH "src/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl"
-
-#ifndef __global
-#define __global
-#endif
-
-#ifndef __kernel
-#define __kernel
-#endif
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhTraversal.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3FindConcaveSatAxis.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ClipFaces.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3NewContactReduction.h"
-
-#define dot3F4 b3Dot
-
-GpuSatCollision::GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q)
- : m_context(ctx),
- m_device(device),
- m_queue(q),
-
- m_findSeparatingAxisKernel(0),
- m_findSeparatingAxisVertexFaceKernel(0),
- m_findSeparatingAxisEdgeEdgeKernel(0),
- m_unitSphereDirections(m_context, m_queue),
-
- m_totalContactsOut(m_context, m_queue),
- m_sepNormals(m_context, m_queue),
- m_dmins(m_context, m_queue),
-
- m_hasSeparatingNormals(m_context, m_queue),
- m_concaveSepNormals(m_context, m_queue),
- m_concaveHasSeparatingNormals(m_context, m_queue),
- m_numConcavePairsOut(m_context, m_queue),
-
- m_gpuCompoundPairs(m_context, m_queue),
-
- m_gpuCompoundSepNormals(m_context, m_queue),
- m_gpuHasCompoundSepNormals(m_context, m_queue),
-
- m_numCompoundPairsOut(m_context, m_queue)
-{
- m_totalContactsOut.push_back(0);
-
- cl_int errNum = 0;
-
- if (1)
- {
- const char* mprSrc = mprKernelsCL;
-
- const char* srcConcave = satConcaveKernelsCL;
- char flags[1024] = {0};
- //#ifdef CL_PLATFORM_INTEL
- // sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/sat.cl");
- //#endif
- m_mprPenetrationKernel = 0;
- m_findSeparatingAxisUnitSphereKernel = 0;
-
- if (useMprGpu)
- {
- cl_program mprProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, mprSrc, &errNum, flags, BT_NARROWPHASE_MPR_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- m_mprPenetrationKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "mprPenetrationKernel", &errNum, mprProg);
- b3Assert(m_mprPenetrationKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findSeparatingAxisUnitSphereKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, mprSrc, "findSeparatingAxisUnitSphereKernel", &errNum, mprProg);
- b3Assert(m_findSeparatingAxisUnitSphereKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
- m_unitSphereDirections.resize(numDirections);
- m_unitSphereDirections.copyFromHostPointer(unitSphere162, numDirections, 0, true);
- }
-
- cl_program satProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, satKernelsCL, &errNum, flags, BT_NARROWPHASE_SAT_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- cl_program satConcaveProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcConcave, &errNum, flags, BT_NARROWPHASE_SAT_CONCAVE_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisKernel", &errNum, satProg);
- b3Assert(m_findSeparatingAxisKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisVertexFaceKernel", &errNum, satProg);
- b3Assert(m_findSeparatingAxisVertexFaceKernel);
-
- m_findSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findSeparatingAxisEdgeEdgeKernel", &errNum, satProg);
- b3Assert(m_findSeparatingAxisVertexFaceKernel);
-
- m_findConcaveSeparatingAxisKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findConcaveSeparatingAxisKernel", &errNum, satProg);
- b3Assert(m_findConcaveSeparatingAxisKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findConcaveSeparatingAxisVertexFaceKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisVertexFaceKernel", &errNum, satConcaveProg);
- b3Assert(m_findConcaveSeparatingAxisVertexFaceKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findConcaveSeparatingAxisEdgeEdgeKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcConcave, "findConcaveSeparatingAxisEdgeEdgeKernel", &errNum, satConcaveProg);
- b3Assert(m_findConcaveSeparatingAxisEdgeEdgeKernel);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "findCompoundPairsKernel", &errNum, satProg);
- b3Assert(m_findCompoundPairsKernel);
- b3Assert(errNum == CL_SUCCESS);
- m_processCompoundPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, satKernelsCL, "processCompoundPairsKernel", &errNum, satProg);
- b3Assert(m_processCompoundPairsKernel);
- b3Assert(errNum == CL_SUCCESS);
- }
-
- if (1)
- {
- const char* srcClip = satClipKernelsCL;
-
- char flags[1024] = {0};
- //#ifdef CL_PLATFORM_INTEL
- // sprintf(flags,"-g -s \"%s\"","C:/develop/bullet3_experiments2/opencl/gpu_narrowphase/kernels/satClipHullContacts.cl");
- //#endif
-
- cl_program satClipContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcClip, &errNum, flags, BT_NARROWPHASE_CLIPHULL_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- m_clipHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_clipCompoundsHullHullKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipCompoundsHullHullKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_findClippingFacesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "findClippingFacesKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_clipFacesAndFindContacts = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipFacesAndFindContactsKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
-
- m_clipHullHullConcaveConvexKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip, "clipHullHullConcaveConvexKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
-
- // m_extractManifoldAndAddContactKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device,srcClip, "extractManifoldAndAddContactKernel",&errNum,satClipContactsProg);
- // b3Assert(errNum==CL_SUCCESS);
-
- m_newContactReductionKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcClip,
- "newContactReductionKernel", &errNum, satClipContactsProg);
- b3Assert(errNum == CL_SUCCESS);
- }
- else
- {
- m_clipHullHullKernel = 0;
- m_clipCompoundsHullHullKernel = 0;
- m_findClippingFacesKernel = 0;
- m_newContactReductionKernel = 0;
- m_clipFacesAndFindContacts = 0;
- m_clipHullHullConcaveConvexKernel = 0;
- // m_extractManifoldAndAddContactKernel = 0;
- }
-
- if (1)
- {
- const char* srcBvh = bvhTraversalKernelCL;
- cl_program bvhTraversalProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, srcBvh, &errNum, "", BT_NARROWPHASE_BVH_TRAVERSAL_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- m_bvhTraversalKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, srcBvh, "bvhTraversalKernel", &errNum, bvhTraversalProg, "");
- b3Assert(errNum == CL_SUCCESS);
- }
-
- {
- const char* primitiveContactsSrc = primitiveContactsKernelsCL;
- cl_program primitiveContactsProg = b3OpenCLUtils::compileCLProgramFromString(m_context, m_device, primitiveContactsSrc, &errNum, "", BT_NARROWPHASE_PRIMITIVE_CONTACT_PATH);
- b3Assert(errNum == CL_SUCCESS);
-
- m_primitiveContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "primitiveContactsKernel", &errNum, primitiveContactsProg, "");
- b3Assert(errNum == CL_SUCCESS);
-
- m_findConcaveSphereContactsKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "findConcaveSphereContactsKernel", &errNum, primitiveContactsProg);
- b3Assert(errNum == CL_SUCCESS);
- b3Assert(m_findConcaveSphereContactsKernel);
-
- m_processCompoundPairsPrimitivesKernel = b3OpenCLUtils::compileCLKernelFromString(m_context, m_device, primitiveContactsSrc, "processCompoundPairsPrimitivesKernel", &errNum, primitiveContactsProg, "");
- b3Assert(errNum == CL_SUCCESS);
- b3Assert(m_processCompoundPairsPrimitivesKernel);
- }
-}
-
-GpuSatCollision::~GpuSatCollision()
-{
- if (m_findSeparatingAxisVertexFaceKernel)
- clReleaseKernel(m_findSeparatingAxisVertexFaceKernel);
-
- if (m_findSeparatingAxisEdgeEdgeKernel)
- clReleaseKernel(m_findSeparatingAxisEdgeEdgeKernel);
-
- if (m_findSeparatingAxisUnitSphereKernel)
- clReleaseKernel(m_findSeparatingAxisUnitSphereKernel);
-
- if (m_mprPenetrationKernel)
- clReleaseKernel(m_mprPenetrationKernel);
-
- if (m_findSeparatingAxisKernel)
- clReleaseKernel(m_findSeparatingAxisKernel);
-
- if (m_findConcaveSeparatingAxisVertexFaceKernel)
- clReleaseKernel(m_findConcaveSeparatingAxisVertexFaceKernel);
-
- if (m_findConcaveSeparatingAxisEdgeEdgeKernel)
- clReleaseKernel(m_findConcaveSeparatingAxisEdgeEdgeKernel);
-
- if (m_findConcaveSeparatingAxisKernel)
- clReleaseKernel(m_findConcaveSeparatingAxisKernel);
-
- if (m_findCompoundPairsKernel)
- clReleaseKernel(m_findCompoundPairsKernel);
-
- if (m_processCompoundPairsKernel)
- clReleaseKernel(m_processCompoundPairsKernel);
-
- if (m_findClippingFacesKernel)
- clReleaseKernel(m_findClippingFacesKernel);
-
- if (m_clipFacesAndFindContacts)
- clReleaseKernel(m_clipFacesAndFindContacts);
- if (m_newContactReductionKernel)
- clReleaseKernel(m_newContactReductionKernel);
- if (m_primitiveContactsKernel)
- clReleaseKernel(m_primitiveContactsKernel);
-
- if (m_findConcaveSphereContactsKernel)
- clReleaseKernel(m_findConcaveSphereContactsKernel);
-
- if (m_processCompoundPairsPrimitivesKernel)
- clReleaseKernel(m_processCompoundPairsPrimitivesKernel);
-
- if (m_clipHullHullKernel)
- clReleaseKernel(m_clipHullHullKernel);
- if (m_clipCompoundsHullHullKernel)
- clReleaseKernel(m_clipCompoundsHullHullKernel);
-
- if (m_clipHullHullConcaveConvexKernel)
- clReleaseKernel(m_clipHullHullConcaveConvexKernel);
- // if (m_extractManifoldAndAddContactKernel)
- // clReleaseKernel(m_extractManifoldAndAddContactKernel);
-
- if (m_bvhTraversalKernel)
- clReleaseKernel(m_bvhTraversalKernel);
-}
-
-struct MyTriangleCallback : public b3NodeOverlapCallback
-{
- int m_bodyIndexA;
- int m_bodyIndexB;
-
- virtual void processNode(int subPart, int triangleIndex)
- {
- printf("bodyIndexA %d, bodyIndexB %d\n", m_bodyIndexA, m_bodyIndexB);
- printf("triangleIndex %d\n", triangleIndex);
- }
-};
-
-#define float4 b3Vector3
-#define make_float4(x, y, z, w) b3MakeVector3(x, y, z, w)
-
-float signedDistanceFromPointToPlane(const float4& point, const float4& planeEqn, float4* closestPointOnFace)
-{
- float4 n = planeEqn;
- n[3] = 0.f;
- float dist = dot3F4(n, point) + planeEqn[3];
- *closestPointOnFace = point - dist * n;
- return dist;
-}
-
-#define cross3(a, b) (a.cross(b))
-b3Vector3 transform(const b3Vector3* v, const b3Vector3* pos, const b3Quaternion* orn)
-{
- b3Transform tr;
- tr.setIdentity();
- tr.setOrigin(*pos);
- tr.setRotation(*orn);
- b3Vector3 res = tr(*v);
- return res;
-}
-
-inline bool IsPointInPolygon(const float4& p,
- const b3GpuFace* face,
- const float4* baseVertex,
- const int* convexIndices,
- float4* out)
-{
- float4 a;
- float4 b;
- float4 ab;
- float4 ap;
- float4 v;
-
- float4 plane = b3MakeVector3(face->m_plane.x, face->m_plane.y, face->m_plane.z, 0.f);
-
- if (face->m_numIndices < 2)
- return false;
-
- float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices - 1]];
- b = v0;
-
- for (unsigned i = 0; i != face->m_numIndices; ++i)
- {
- a = b;
- float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
- b = vi;
- ab = b - a;
- ap = p - a;
- v = cross3(ab, plane);
-
- if (b3Dot(ap, v) > 0.f)
- {
- float ab_m2 = b3Dot(ab, ab);
- float rt = ab_m2 != 0.f ? b3Dot(ab, ap) / ab_m2 : 0.f;
- if (rt <= 0.f)
- {
- *out = a;
- }
- else if (rt >= 1.f)
- {
- *out = b;
- }
- else
- {
- float s = 1.f - rt;
- out[0].x = s * a.x + rt * b.x;
- out[0].y = s * a.y + rt * b.y;
- out[0].z = s * a.z + rt * b.z;
- }
- return false;
- }
- }
- return true;
-}
-
-#define normalize3(a) (a.normalize())
-
-int extractManifoldSequentialGlobal(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
-{
- if (nPoints == 0)
- return 0;
-
- if (nPoints <= 4)
- return nPoints;
-
- if (nPoints > 64)
- nPoints = 64;
-
- float4 center = b3MakeVector3(0, 0, 0, 0);
- {
- for (int i = 0; i < nPoints; i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
- // sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3(nearNormal, aVector);
- float4 v = cross3(nearNormal, u);
- u = normalize3(u);
- v = normalize3(v);
-
- //keep point with deepest penetration
- float minW = FLT_MAX;
-
- int minIndex = -1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for (int ie = 0; ie < nPoints; ie++)
- {
- if (p[ie].w < minW)
- {
- minW = p[ie].w;
- minIndex = ie;
- }
- float f;
- float4 r = p[ie] - center;
- f = dot3F4(u, r);
- if (f < maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4(-u, r);
- if (f < maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
- f = dot3F4(v, r);
- if (f < maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4(-v, r);
- if (f < maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-}
-
-#define MAX_VERTS 1024
-
-inline void project(const b3ConvexPolyhedronData& hull, const float4& pos, const b3Quaternion& orn, const float4& dir, const b3AlignedObjectArray<b3Vector3>& vertices, b3Scalar& min, b3Scalar& max)
-{
- min = FLT_MAX;
- max = -FLT_MAX;
- int numVerts = hull.m_numVertices;
-
- const float4 localDir = b3QuatRotate(orn.inverse(), dir);
-
- b3Scalar offset = dot3F4(pos, dir);
-
- for (int i = 0; i < numVerts; i++)
- {
- //b3Vector3 pt = trans * vertices[m_vertexOffset+i];
- //b3Scalar dp = pt.dot(dir);
- //b3Vector3 vertex = vertices[hull.m_vertexOffset+i];
- b3Scalar dp = dot3F4((float4&)vertices[hull.m_vertexOffset + i], localDir);
- //b3Assert(dp==dpL);
- if (dp < min) min = dp;
- if (dp > max) max = dp;
- }
- if (min > max)
- {
- b3Scalar tmp = min;
- min = max;
- max = tmp;
- }
- min += offset;
- max += offset;
-}
-
-static bool TestSepAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA, const b3Quaternion& ornA,
- const float4& posB, const b3Quaternion& ornB,
- const float4& sep_axis, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB, b3Scalar& depth)
-{
- b3Scalar Min0, Max0;
- b3Scalar Min1, Max1;
- project(hullA, posA, ornA, sep_axis, verticesA, Min0, Max0);
- project(hullB, posB, ornB, sep_axis, verticesB, Min1, Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- b3Scalar d0 = Max0 - Min1;
- assert(d0 >= 0.0f);
- b3Scalar d1 = Max1 - Min0;
- assert(d1 >= 0.0f);
- depth = d0 < d1 ? d0 : d1;
- return true;
-}
-
-inline bool IsAlmostZero(const b3Vector3& v)
-{
- if (fabsf(v.x) > 1e-6 || fabsf(v.y) > 1e-6 || fabsf(v.z) > 1e-6) return false;
- return true;
-}
-
-static bool findSeparatingAxis(const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA1,
- const b3Quaternion& ornA,
- const float4& posB1,
- const b3Quaternion& ornB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- b3Vector3& sep)
-{
- B3_PROFILE("findSeparatingAxis");
-
- b3g_actualSATPairTests++;
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
- //#ifdef TEST_INTERNAL_OBJECTS
- float4 c0local = (float4&)hullA.m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = (float4&)hullB.m_localCenter;
- float4 c1 = transform(&c1local, &posB, &ornB);
- const float4 deltaC2 = c0 - c1;
- //#endif
-
- b3Scalar dmin = FLT_MAX;
- int curPlaneTests = 0;
-
- int numFacesA = hullA.m_numFaces;
- // Test normals from hullA
- for (int i = 0; i < numFacesA; i++)
- {
- const float4& normal = (float4&)facesA[hullA.m_faceOffset + i].m_plane;
- float4 faceANormalWS = b3QuatRotate(ornA, normal);
-
- if (dot3F4(deltaC2, faceANormalWS) < 0)
- faceANormalWS *= -1.f;
-
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar d;
- if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, faceANormalWS, verticesA, verticesB, d))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = (b3Vector3&)faceANormalWS;
- }
- }
-
- int numFacesB = hullB.m_numFaces;
- // Test normals from hullB
- for (int i = 0; i < numFacesB; i++)
- {
- float4 normal = (float4&)facesB[hullB.m_faceOffset + i].m_plane;
- float4 WorldNormal = b3QuatRotate(ornB, normal);
-
- if (dot3F4(deltaC2, WorldNormal) < 0)
- {
- WorldNormal *= -1.f;
- }
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar d;
- if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, WorldNormal, verticesA, verticesB, d))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = (b3Vector3&)WorldNormal;
- }
- }
-
- int curEdgeEdge = 0;
- // Test edges
- for (int e0 = 0; e0 < hullA.m_numUniqueEdges; e0++)
- {
- const float4& edge0 = (float4&)uniqueEdgesA[hullA.m_uniqueEdgesOffset + e0];
- float4 edge0World = b3QuatRotate(ornA, (float4&)edge0);
-
- for (int e1 = 0; e1 < hullB.m_numUniqueEdges; e1++)
- {
- const b3Vector3 edge1 = uniqueEdgesB[hullB.m_uniqueEdgesOffset + e1];
- float4 edge1World = b3QuatRotate(ornB, (float4&)edge1);
-
- float4 crossje = cross3(edge0World, edge1World);
-
- curEdgeEdge++;
- if (!IsAlmostZero((b3Vector3&)crossje))
- {
- crossje = normalize3(crossje);
- if (dot3F4(deltaC2, crossje) < 0)
- crossje *= -1.f;
-
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- b3Scalar dist;
- if (!TestSepAxis(hullA, hullB, posA, ornA, posB, ornB, crossje, verticesA, verticesB, dist))
- return false;
-
- if (dist < dmin)
- {
- dmin = dist;
- sep = (b3Vector3&)crossje;
- }
- }
- }
- }
-
- if ((dot3F4(-deltaC2, (float4&)sep)) > 0.0f)
- sep = -sep;
-
- return true;
-}
-
-bool findSeparatingAxisEdgeEdge(__global const b3ConvexPolyhedronData* hullA, __global const b3ConvexPolyhedronData* hullB,
- const b3Float4& posA1,
- const b3Quat& ornA,
- const b3Float4& posB1,
- const b3Quat& ornB,
- const b3Float4& DeltaC2,
- __global const b3AlignedObjectArray<float4>& vertices,
- __global const b3AlignedObjectArray<float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- float4* sep,
- float* dmin)
-{
- // int i = get_global_id(0);
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- //int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test edges
- for (int e0 = 0; e0 < hullA->m_numUniqueEdges; e0++)
- {
- const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset + e0];
- float4 edge0World = b3QuatRotate(ornA, edge0);
-
- for (int e1 = 0; e1 < hullB->m_numUniqueEdges; e1++)
- {
- const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset + e1];
- float4 edge1World = b3QuatRotate(ornB, edge1);
-
- float4 crossje = cross3(edge0World, edge1World);
-
- curEdgeEdge++;
- if (!IsAlmostZero(crossje))
- {
- crossje = normalize3(crossje);
- if (dot3F4(DeltaC2, crossje) < 0)
- crossje *= -1.f;
-
- float dist;
- bool result = true;
- {
- float Min0, Max0;
- float Min1, Max1;
- project(*hullA, posA, ornA, crossje, vertices, Min0, Max0);
- project(*hullB, posB, ornB, crossje, vertices, Min1, Max1);
-
- if (Max0 < Min1 || Max1 < Min0)
- result = false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0 < d1 ? d0 : d1;
- result = true;
- }
-
- if (dist < *dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
- }
-
- if ((dot3F4(-DeltaC2, *sep)) > 0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-__inline float4 lerp3(const float4& a, const float4& b, float t)
-{
- return b3MakeVector3(a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
-}
-
-// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFace(const float4* pVtxIn, int numVertsIn, float4& planeNormalWS, float planeEqWS, float4* ppVtxOut)
-{
- int ve;
- float ds, de;
- int numVertsOut = 0;
- if (numVertsIn < 2)
- return 0;
-
- float4 firstVertex = pVtxIn[numVertsIn - 1];
- float4 endVertex = pVtxIn[0];
-
- ds = dot3F4(planeNormalWS, firstVertex) + planeEqWS;
-
- for (ve = 0; ve < numVertsIn; ve++)
- {
- endVertex = pVtxIn[ve];
-
- de = dot3F4(planeNormalWS, endVertex) + planeEqWS;
-
- if (ds < 0)
- {
- if (de < 0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut[numVertsOut++] = endVertex;
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- }
- }
- else
- {
- if (de < 0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex, (ds * 1.f / (ds - de)));
- ppVtxOut[numVertsOut++] = endVertex;
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
- return numVertsOut;
-}
-
-int clipFaceAgainstHull(const float4& separatingNormal, const b3ConvexPolyhedronData* hullA,
- const float4& posA, const b3Quaternion& ornA, float4* worldVertsB1, int numWorldVertsB1,
- float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- //const float4* verticesB, const b3GpuFace* facesB, const int* indicesB,
- float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
-
- float4* pVtxIn = worldVertsB1;
- float4* pVtxOut = worldVertsB2;
-
- int numVertsIn = numWorldVertsB1;
- int numVertsOut = 0;
-
- int closestFaceA = -1;
- {
- float dmin = FLT_MAX;
- for (int face = 0; face < hullA->m_numFaces; face++)
- {
- const float4 Normal = b3MakeVector3(
- facesA[hullA->m_faceOffset + face].m_plane.x,
- facesA[hullA->m_faceOffset + face].m_plane.y,
- facesA[hullA->m_faceOffset + face].m_plane.z, 0.f);
- const float4 faceANormalWS = b3QuatRotate(ornA, Normal);
-
- float d = dot3F4(faceANormalWS, separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- }
- }
- }
- if (closestFaceA < 0)
- return numContactsOut;
-
- b3GpuFace polyA = facesA[hullA->m_faceOffset + closestFaceA];
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- // int numContacts = numWorldVertsB1;
- int numVerticesA = polyA.m_numIndices;
- for (int e0 = 0; e0 < numVerticesA; e0++)
- {
- const float4 a = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + e0]];
- const float4 b = verticesA[hullA->m_vertexOffset + indicesA[polyA.m_indexOffset + ((e0 + 1) % numVerticesA)]];
- const float4 edge0 = a - b;
- const float4 WorldEdge0 = b3QuatRotate(ornA, edge0);
- float4 planeNormalA = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
- float4 worldPlaneAnormal1 = b3QuatRotate(ornA, planeNormalA);
-
- float4 planeNormalWS1 = -cross3(WorldEdge0, worldPlaneAnormal1);
- float4 worldA1 = transform(&a, &posA, &ornA);
- float planeEqWS1 = -dot3F4(worldA1, planeNormalWS1);
-
- float4 planeNormalWS = planeNormalWS1;
- float planeEqWS = planeEqWS1;
-
- //clip face
- //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS, planeEqWS, pVtxOut);
-
- //btSwap(pVtxIn,pVtxOut);
- float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsIn = numVertsOut;
- numVertsOut = 0;
- }
-
- // only keep points that are behind the witness face
- {
- float4 localPlaneNormal = make_float4(polyA.m_plane.x, polyA.m_plane.y, polyA.m_plane.z, 0.f);
- float localPlaneEq = polyA.m_plane.w;
- float4 planeNormalWS = b3QuatRotate(ornA, localPlaneNormal);
- float planeEqWS = localPlaneEq - dot3F4(planeNormalWS, posA);
- for (int i = 0; i < numVertsIn; i++)
- {
- float depth = dot3F4(planeNormalWS, pVtxIn[i]) + planeEqWS;
- if (depth <= minDist)
- {
- depth = minDist;
- }
- if (numContactsOut < contactCapacity)
- {
- if (depth <= maxDist)
- {
- float4 pointInWorld = pVtxIn[i];
- //resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = b3MakeVector3(pointInWorld.x, pointInWorld.y, pointInWorld.z, depth);
- //printf("depth=%f\n",depth);
- }
- }
- else
- {
- b3Error("exceeding contact capacity (%d,%df)\n", numContactsOut, contactCapacity);
- }
- }
- }
-
- return numContactsOut;
-}
-
-static int clipHullAgainstHull(const float4& separatingNormal,
- const b3ConvexPolyhedronData& hullA, const b3ConvexPolyhedronData& hullB,
- const float4& posA, const b3Quaternion& ornA, const float4& posB, const b3Quaternion& ornB,
- float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- const b3AlignedObjectArray<float4>& verticesA, const b3AlignedObjectArray<b3GpuFace>& facesA, const b3AlignedObjectArray<int>& indicesA,
- const b3AlignedObjectArray<float4>& verticesB, const b3AlignedObjectArray<b3GpuFace>& facesB, const b3AlignedObjectArray<int>& indicesB,
-
- float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
- int numWorldVertsB1 = 0;
-
- B3_PROFILE("clipHullAgainstHull");
-
- // float curMaxDist=maxDist;
- int closestFaceB = -1;
- float dmax = -FLT_MAX;
-
- {
- //B3_PROFILE("closestFaceB");
- if (hullB.m_numFaces != 1)
- {
- //printf("wtf\n");
- }
- static bool once = true;
- //printf("separatingNormal=%f,%f,%f\n",separatingNormal.x,separatingNormal.y,separatingNormal.z);
-
- for (int face = 0; face < hullB.m_numFaces; face++)
- {
-#ifdef BT_DEBUG_SAT_FACE
- if (once)
- printf("face %d\n", face);
- const b3GpuFace* faceB = &facesB[hullB.m_faceOffset + face];
- if (once)
- {
- for (int i = 0; i < faceB->m_numIndices; i++)
- {
- float4 vert = verticesB[hullB.m_vertexOffset + indicesB[faceB->m_indexOffset + i]];
- printf("vert[%d] = %f,%f,%f\n", i, vert.x, vert.y, vert.z);
- }
- }
-#endif //BT_DEBUG_SAT_FACE \
- //if (facesB[hullB.m_faceOffset+face].m_numIndices>2)
- {
- const float4 Normal = b3MakeVector3(facesB[hullB.m_faceOffset + face].m_plane.x,
- facesB[hullB.m_faceOffset + face].m_plane.y, facesB[hullB.m_faceOffset + face].m_plane.z, 0.f);
- const float4 WorldNormal = b3QuatRotate(ornB, Normal);
-#ifdef BT_DEBUG_SAT_FACE
- if (once)
- printf("faceNormal = %f,%f,%f\n", Normal.x, Normal.y, Normal.z);
-#endif
- float d = dot3F4(WorldNormal, separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
- once = false;
- }
-
- b3Assert(closestFaceB >= 0);
- {
- //B3_PROFILE("worldVertsB1");
- const b3GpuFace& polyB = facesB[hullB.m_faceOffset + closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for (int e0 = 0; e0 < numVertices; e0++)
- {
- const float4& b = verticesB[hullB.m_vertexOffset + indicesB[polyB.m_indexOffset + e0]];
- worldVertsB1[numWorldVertsB1++] = transform(&b, &posB, &ornB);
- }
- }
-
- if (closestFaceB >= 0)
- {
- //B3_PROFILE("clipFaceAgainstHull");
- numContactsOut = clipFaceAgainstHull((float4&)separatingNormal, &hullA,
- posA, ornA,
- worldVertsB1, numWorldVertsB1, worldVertsB2, capacityWorldVerts, minDist, maxDist,
- verticesA, facesA, indicesA,
- contactsOut, contactCapacity);
- }
-
- return numContactsOut;
-}
-
-#define PARALLEL_SUM(v, n) \
- for (int j = 1; j < n; j++) v[0] += v[j];
-#define PARALLEL_DO(execution, n) \
- for (int ie = 0; ie < n; ie++) \
- { \
- execution; \
- }
-#define REDUCE_MAX(v, n) \
- { \
- int i = 0; \
- for (int offset = 0; offset < n; offset++) v[i] = (v[i].y > v[i + offset].y) ? v[i] : v[i + offset]; \
- }
-#define REDUCE_MIN(v, n) \
- { \
- int i = 0; \
- for (int offset = 0; offset < n; offset++) v[i] = (v[i].y < v[i + offset].y) ? v[i] : v[i + offset]; \
- }
-
-int extractManifold(const float4* p, int nPoints, const float4& nearNormal, b3Int4* contactIdx)
-{
- if (nPoints == 0)
- return 0;
-
- if (nPoints <= 4)
- return nPoints;
-
- if (nPoints > 64)
- nPoints = 64;
-
- float4 center = make_float4(0, 0, 0, 0);
- {
- for (int i = 0; i < nPoints; i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
- // sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3(nearNormal, aVector);
- float4 v = cross3(nearNormal, u);
- u = normalize3(u);
- v = normalize3(v);
-
- //keep point with deepest penetration
- float minW = FLT_MAX;
-
- int minIndex = -1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for (int ie = 0; ie < nPoints; ie++)
- {
- if (p[ie].w < minW)
- {
- minW = p[ie].w;
- minIndex = ie;
- }
- float f;
- float4 r = p[ie] - center;
- f = dot3F4(u, r);
- if (f < maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4(-u, r);
- if (f < maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
- f = dot3F4(v, r);
- if (f < maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4(-v, r);
- if (f < maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-}
-
-int clipHullHullSingle(
- int bodyIndexA, int bodyIndexB,
- const float4& posA,
- const b3Quaternion& ornA,
- const float4& posB,
- const b3Quaternion& ornB,
-
- int collidableIndexA, int collidableIndexB,
-
- const b3AlignedObjectArray<b3RigidBodyData>* bodyBuf,
- b3AlignedObjectArray<b3Contact4>* globalContactOut,
- int& nContacts,
-
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataA,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& hostConvexDataB,
-
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesA,
- const b3AlignedObjectArray<b3GpuFace>& facesA,
- const b3AlignedObjectArray<int>& indicesA,
-
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdgesB,
- const b3AlignedObjectArray<b3GpuFace>& facesB,
- const b3AlignedObjectArray<int>& indicesB,
-
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesA,
- const b3AlignedObjectArray<b3Collidable>& hostCollidablesB,
- const b3Vector3& sepNormalWorldSpace,
- int maxContactCapacity)
-{
- int contactIndex = -1;
- b3ConvexPolyhedronData hullA, hullB;
-
- b3Collidable colA = hostCollidablesA[collidableIndexA];
- hullA = hostConvexDataA[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
- b3Collidable colB = hostCollidablesB[collidableIndexB];
- hullB = hostConvexDataB[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
- float4 contactsOut[MAX_VERTS];
- int localContactCapacity = MAX_VERTS;
-
-#ifdef _WIN32
- b3Assert(_finite(bodyBuf->at(bodyIndexA).m_pos.x));
- b3Assert(_finite(bodyBuf->at(bodyIndexB).m_pos.x));
-#endif
-
- {
- float4 worldVertsB1[MAX_VERTS];
- float4 worldVertsB2[MAX_VERTS];
- int capacityWorldVerts = MAX_VERTS;
-
- float4 hostNormal = make_float4(sepNormalWorldSpace.x, sepNormalWorldSpace.y, sepNormalWorldSpace.z, 0.f);
- int shapeA = hostCollidablesA[collidableIndexA].m_shapeIndex;
- int shapeB = hostCollidablesB[collidableIndexB].m_shapeIndex;
-
- b3Scalar minDist = -1;
- b3Scalar maxDist = 0.;
-
- b3Transform trA, trB;
- {
- //B3_PROFILE("transform computation");
- //trA.setIdentity();
- trA.setOrigin(b3MakeVector3(posA.x, posA.y, posA.z));
- trA.setRotation(b3Quaternion(ornA.x, ornA.y, ornA.z, ornA.w));
-
- //trB.setIdentity();
- trB.setOrigin(b3MakeVector3(posB.x, posB.y, posB.z));
- trB.setRotation(b3Quaternion(ornB.x, ornB.y, ornB.z, ornB.w));
- }
-
- b3Quaternion trAorn = trA.getRotation();
- b3Quaternion trBorn = trB.getRotation();
-
- int numContactsOut = clipHullAgainstHull(hostNormal,
- hostConvexDataA.at(shapeA),
- hostConvexDataB.at(shapeB),
- (float4&)trA.getOrigin(), (b3Quaternion&)trAorn,
- (float4&)trB.getOrigin(), (b3Quaternion&)trBorn,
- worldVertsB1, worldVertsB2, capacityWorldVerts,
- minDist, maxDist,
- verticesA, facesA, indicesA,
- verticesB, facesB, indicesB,
-
- contactsOut, localContactCapacity);
-
- if (numContactsOut > 0)
- {
- B3_PROFILE("overlap");
-
- float4 normalOnSurfaceB = (float4&)hostNormal;
-
- b3Int4 contactIdx;
- contactIdx.x = 0;
- contactIdx.y = 1;
- contactIdx.z = 2;
- contactIdx.w = 3;
-
- int numPoints = 0;
-
- {
- // B3_PROFILE("extractManifold");
- numPoints = extractManifold(contactsOut, numContactsOut, normalOnSurfaceB, &contactIdx);
- }
-
- b3Assert(numPoints);
-
- if (nContacts < maxContactCapacity)
- {
- contactIndex = nContacts;
- globalContactOut->expand();
- b3Contact4& contact = globalContactOut->at(nContacts);
- contact.m_batchIdx = 0; //i;
- contact.m_bodyAPtrAndSignBit = (bodyBuf->at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
- contact.m_bodyBPtrAndSignBit = (bodyBuf->at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
-
- contact.m_frictionCoeffCmp = 45874;
- contact.m_restituitionCoeffCmp = 0;
-
- // float distance = 0.f;
- for (int p = 0; p < numPoints; p++)
- {
- contact.m_worldPosB[p] = contactsOut[contactIdx.s[p]]; //check if it is actually on B
- contact.m_worldNormalOnB = normalOnSurfaceB;
- }
- //printf("bodyIndexA %d,bodyIndexB %d,normal=%f,%f,%f numPoints %d\n",bodyIndexA,bodyIndexB,normalOnSurfaceB.x,normalOnSurfaceB.y,normalOnSurfaceB.z,numPoints);
- contact.m_worldNormalOnB.w = (b3Scalar)numPoints;
- nContacts++;
- }
- else
- {
- b3Error("Error: exceeding contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
- }
- }
- }
- return contactIndex;
-}
-
-void computeContactPlaneConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
-{
- int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
- const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndex];
-
- b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
- b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
- b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
-
- // int numContactsOut = 0;
- // int numWorldVertsB1= 0;
-
- b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
- b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
- float planeConstant = planeEq.w;
- b3Transform convexWorldTransform;
- convexWorldTransform.setIdentity();
- convexWorldTransform.setOrigin(posB);
- convexWorldTransform.setRotation(ornB);
- b3Transform planeTransform;
- planeTransform.setIdentity();
- planeTransform.setOrigin(posA);
- planeTransform.setRotation(ornA);
-
- b3Transform planeInConvex;
- planeInConvex = convexWorldTransform.inverse() * planeTransform;
- b3Transform convexInPlane;
- convexInPlane = planeTransform.inverse() * convexWorldTransform;
-
- b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
- float maxDot = -1e30;
- int hitVertex = -1;
- b3Vector3 hitVtx;
-
-#define MAX_PLANE_CONVEX_POINTS 64
-
- b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
- int numPoints = 0;
-
- b3Int4 contactIdx;
- contactIdx.s[0] = 0;
- contactIdx.s[1] = 1;
- contactIdx.s[2] = 2;
- contactIdx.s[3] = 3;
-
- for (int i = 0; i < hullB->m_numVertices; i++)
- {
- b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
- float curDot = vtx.dot(planeNormalInConvex);
-
- if (curDot > maxDot)
- {
- hitVertex = i;
- maxDot = curDot;
- hitVtx = vtx;
- //make sure the deepest points is always included
- if (numPoints == MAX_PLANE_CONVEX_POINTS)
- numPoints--;
- }
-
- if (numPoints < MAX_PLANE_CONVEX_POINTS)
- {
- b3Vector3 vtxWorld = convexWorldTransform * vtx;
- b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
- float dist = planeNormal.dot(vtxInPlane) - planeConstant;
- if (dist < 0.f)
- {
- vtxWorld.w = dist;
- contactPoints[numPoints] = vtxWorld;
- numPoints++;
- }
- }
- }
-
- int numReducedPoints = 0;
-
- numReducedPoints = numPoints;
-
- if (numPoints > 4)
- {
- numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
- }
- int dstIdx;
- // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (numReducedPoints > 0)
- {
- if (nGlobalContactsOut < maxContactCapacity)
- {
- dstIdx = nGlobalContactsOut;
- nGlobalContactsOut++;
-
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -planeNormalWorld;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
-
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
- for (int i = 0; i < numReducedPoints; i++)
- {
- b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
- c->m_worldPosB[i] = pOnB1;
- }
- c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
- } //if (dstIdx < numPairs)
- }
-
- // printf("computeContactPlaneConvex\n");
-}
-
-B3_FORCE_INLINE b3Vector3 MyUnQuantize(const unsigned short* vecIn, const b3Vector3& quantization, const b3Vector3& bvhAabbMin)
-{
- b3Vector3 vecOut;
- vecOut.setValue(
- (b3Scalar)(vecIn[0]) / (quantization.x),
- (b3Scalar)(vecIn[1]) / (quantization.y),
- (b3Scalar)(vecIn[2]) / (quantization.z));
- vecOut += bvhAabbMin;
- return vecOut;
-}
-
-void traverseTreeTree()
-{
-}
-
-#include "Bullet3Common/shared/b3Mat3x3.h"
-
-int numAabbChecks = 0;
-int maxNumAabbChecks = 0;
-int maxDepth = 0;
-
-// work-in-progress
-__kernel void findCompoundPairsKernel(
- int pairIndex,
- int bodyIndexA,
- int bodyIndexB,
- int collidableIndexA,
- int collidableIndexB,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3AlignedObjectArray<b3Float4>& vertices,
- __global const b3AlignedObjectArray<b3Aabb>& aabbsWorldSpace,
- __global const b3AlignedObjectArray<b3Aabb>& aabbsLocalSpace,
- __global const b3GpuChildShape* gpuChildShapes,
- __global b3Int4* gpuCompoundPairsOut,
- __global int* numCompoundPairsOut,
- int maxNumCompoundPairsCapacity,
- b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
- b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
- b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
-{
- numAabbChecks = 0;
- maxNumAabbChecks = 0;
- // int i = pairIndex;
- {
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass == 0) && (rigidBodies[bodyIndexB].m_invMass == 0))
- {
- return;
- }
-
- if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
- int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
- int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
- int numSubTreesA = bvhInfoCPU[bvhA].m_numSubTrees;
- int subTreesOffsetA = bvhInfoCPU[bvhA].m_subTreeOffset;
- int subTreesOffsetB = bvhInfoCPU[bvhB].m_subTreeOffset;
-
- int numSubTreesB = bvhInfoCPU[bvhB].m_numSubTrees;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
-
- b3Transform transA;
- transA.setIdentity();
- transA.setOrigin(posA);
- transA.setRotation(ornA);
-
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- b3Transform transB;
- transB.setIdentity();
- transB.setOrigin(posB);
- transB.setRotation(ornB);
-
- for (int p = 0; p < numSubTreesA; p++)
- {
- b3BvhSubtreeInfo subtreeA = subTreesCPU[subTreesOffsetA + p];
- //bvhInfoCPU[bvhA].m_quantization
- b3Vector3 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
-
- b3Vector3 aabbAMinOut, aabbAMaxOut;
- float margin = 0.f;
- b3TransformAabb2(treeAminLocal, treeAmaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
-
- for (int q = 0; q < numSubTreesB; q++)
- {
- b3BvhSubtreeInfo subtreeB = subTreesCPU[subTreesOffsetB + q];
-
- b3Vector3 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
-
- b3Vector3 aabbBMinOut, aabbBMaxOut;
- float margin = 0.f;
- b3TransformAabb2(treeBminLocal, treeBmaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
-
- numAabbChecks = 0;
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
- if (aabbOverlap)
- {
- int startNodeIndexA = subtreeA.m_rootNodeIndex + bvhInfoCPU[bvhA].m_nodeOffset;
- // int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
-
- int startNodeIndexB = subtreeB.m_rootNodeIndex + bvhInfoCPU[bvhB].m_nodeOffset;
- // int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
-
- b3AlignedObjectArray<b3Int2> nodeStack;
- b3Int2 node0;
- node0.x = startNodeIndexA;
- node0.y = startNodeIndexB;
-
- int maxStackDepth = 1024;
- nodeStack.resize(maxStackDepth);
- int depth = 0;
- nodeStack[depth++] = node0;
-
- do
- {
- if (depth > maxDepth)
- {
- maxDepth = depth;
- printf("maxDepth=%d\n", maxDepth);
- }
- b3Int2 node = nodeStack[--depth];
-
- b3Vector3 aMinLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMin, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
- b3Vector3 aMaxLocal = MyUnQuantize(treeNodesCPU[node.x].m_quantizedAabbMax, bvhInfoCPU[bvhA].m_quantization, bvhInfoCPU[bvhA].m_aabbMin);
-
- b3Vector3 bMinLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMin, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
- b3Vector3 bMaxLocal = MyUnQuantize(treeNodesCPU[node.y].m_quantizedAabbMax, bvhInfoCPU[bvhB].m_quantization, bvhInfoCPU[bvhB].m_aabbMin);
-
- float margin = 0.f;
- b3Vector3 aabbAMinOut, aabbAMaxOut;
- b3TransformAabb2(aMinLocal, aMaxLocal, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
-
- b3Vector3 aabbBMinOut, aabbBMaxOut;
- b3TransformAabb2(bMinLocal, bMaxLocal, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
-
- numAabbChecks++;
- bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
- if (nodeOverlap)
- {
- bool isLeafA = treeNodesCPU[node.x].isLeafNode();
- bool isLeafB = treeNodesCPU[node.y].isLeafNode();
- bool isInternalA = !isLeafA;
- bool isInternalB = !isLeafB;
-
- //fail, even though it might hit two leaf nodes
- if (depth + 4 > maxStackDepth && !(isLeafA && isLeafB))
- {
- b3Error("Error: traversal exceeded maxStackDepth\n");
- continue;
- }
-
- if (isInternalA)
- {
- int nodeAleftChild = node.x + 1;
- bool isNodeALeftChildLeaf = treeNodesCPU[node.x + 1].isLeafNode();
- int nodeArightChild = isNodeALeftChildLeaf ? node.x + 2 : node.x + 1 + treeNodesCPU[node.x + 1].getEscapeIndex();
-
- if (isInternalB)
- {
- int nodeBleftChild = node.y + 1;
- bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
- int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
-
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
- }
- else
- {
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild, node.y);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild, node.y);
- }
- }
- else
- {
- if (isInternalB)
- {
- int nodeBleftChild = node.y + 1;
- bool isNodeBLeftChildLeaf = treeNodesCPU[node.y + 1].isLeafNode();
- int nodeBrightChild = isNodeBLeftChildLeaf ? node.y + 2 : node.y + 1 + treeNodesCPU[node.y + 1].getEscapeIndex();
- nodeStack[depth++] = b3MakeInt2(node.x, nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(node.x, nodeBrightChild);
- }
- else
- {
- int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx < maxNumCompoundPairsCapacity)
- {
- int childShapeIndexA = treeNodesCPU[node.x].getTriangleIndex();
- int childShapeIndexB = treeNodesCPU[node.y].getTriangleIndex();
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
- }
- }
- }
- }
- } while (depth);
- maxNumAabbChecks = b3Max(numAabbChecks, maxNumAabbChecks);
- }
- }
- }
-
- return;
- }
-
- if ((collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS) || (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
- if (collidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
- for (int c = 0; c < numChildrenA; c++)
- {
- int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex + c;
- int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
- b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
-
- b3Aabb aabbA = aabbsLocalSpace[childColIndexA];
-
- b3Transform transA;
- transA.setIdentity();
- transA.setOrigin(newPosA);
- transA.setRotation(newOrnA);
- b3Scalar margin = 0.0f;
-
- b3Vector3 aabbAMinOut, aabbAMaxOut;
-
- b3TransformAabb2((const b3Float4&)aabbA.m_min, (const b3Float4&)aabbA.m_max, margin, transA.getOrigin(), transA.getRotation(), &aabbAMinOut, &aabbAMaxOut);
-
- if (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b = 0; b < numChildrenB; b++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB, &posB, &ornB);
- b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
-
- b3Aabb aabbB = aabbsLocalSpace[childColIndexB];
-
- b3Transform transB;
- transB.setIdentity();
- transB.setOrigin(newPosB);
- transB.setRotation(newOrnB);
-
- b3Vector3 aabbBMinOut, aabbBMaxOut;
- b3TransformAabb2((const b3Float4&)aabbB.m_min, (const b3Float4&)aabbB.m_max, margin, transB.getOrigin(), transB.getRotation(), &aabbBMinOut, &aabbBMaxOut);
-
- numAabbChecks++;
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut, aabbAMaxOut, aabbBMinOut, aabbBMaxOut);
- if (aabbOverlap)
- {
- /*
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- float4 posA = newPosA;
- posA.w = 0.f;
- float4 posB = newPosB;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- b3Quat ornA = newOrnA;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Quat ornB =newOrnB;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- */
- { //
- int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx < maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, childShapeIndexB);
- }
- } //
- } //fi(1)
- } //for (int b=0
- } //if (collidables[collidableIndexB].
- else //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- if (1)
- {
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- // float dmin = FLT_MAX;
- float4 posA = newPosA;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- b3Quat ornA = newOrnA;
- float4 c0;
- c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 c1;
- c1 = transform(&c1local, &posB, &ornB);
- // const float4 DeltaC2 = c0 - c1;
-
- {
- int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx < maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, childShapeIndexA, -1);
- } //if (compoundPairIdx<maxNumCompoundPairsCapacity)
- } //
- } //fi (1)
- } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- } //for (int b=0;b<numChildrenB;b++)
- return;
- } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- if ((collidables[collidableIndexA].m_shapeType != SHAPE_CONCAVE_TRIMESH) && (collidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b = 0; b < numChildrenB; b++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + b;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
- b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
-
- int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
-
- //////////////////////////////////////
-
- if (1)
- {
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- // float dmin = FLT_MAX;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = newPosB;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0;
- c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- b3Quat ornB = newOrnB;
- float4 c1;
- c1 = transform(&c1local, &posB, &ornB);
- // const float4 DeltaC2 = c0 - c1;
- { //
- int compoundPairIdx = b3AtomicInc(numCompoundPairsOut);
- if (compoundPairIdx < maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = b3MakeInt4(bodyIndexA, bodyIndexB, -1, childShapeIndexB);
- } //fi (compoundPairIdx<maxNumCompoundPairsCapacity)
- } //
- } //fi (1)
- } //for (int b=0;b<numChildrenB;b++)
- return;
- } //if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- return;
- } //fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- } //i<numPairs
-}
-
-__kernel void processCompoundPairsKernel(__global const b3Int4* gpuCompoundPairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3AlignedObjectArray<b3Float4>& vertices,
- __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- __global b3Aabb* aabbs,
- __global const b3GpuChildShape* gpuChildShapes,
- __global b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
- __global b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
- int numCompoundPairs,
- int i)
-{
- // int i = get_global_id(0);
- if (i < numCompoundPairs)
- {
- int bodyIndexA = gpuCompoundPairs[i].x;
- int bodyIndexB = gpuCompoundPairs[i].y;
-
- int childShapeIndexA = gpuCompoundPairs[i].z;
- int childShapeIndexB = gpuCompoundPairs[i].w;
-
- int collidableIndexA = -1;
- int collidableIndexB = -1;
-
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
-
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- if (childShapeIndexA >= 0)
- {
- collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
- b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
- posA = newPosA;
- ornA = newOrnA;
- }
- else
- {
- collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- }
-
- if (childShapeIndexB >= 0)
- {
- collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
- b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- }
- else
- {
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
- }
-
- gpuHasCompoundSepNormalsOut[i] = 0;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- int shapeTypeA = collidables[collidableIndexA].m_shapeType;
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
- if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
- {
- return;
- }
-
- int hasSeparatingAxis = 5;
-
- // int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- posA.w = 0.f;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local, &posB, &ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal = make_float4(1, 0, 0, 0);
- // bool sepA = findSeparatingAxis( convexShapes[shapeIndexA], convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
- bool sepA = findSeparatingAxis(convexShapes[shapeIndexA], convexShapes[shapeIndexB], posA, ornA, posB, ornB, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal); //,&dmin);
-
- hasSeparatingAxis = 4;
- if (!sepA)
- {
- hasSeparatingAxis = 0;
- }
- else
- {
- bool sepB = findSeparatingAxis(convexShapes[shapeIndexB], convexShapes[shapeIndexA], posB, ornB, posA, ornA, vertices, uniqueEdges, faces, indices, vertices, uniqueEdges, faces, indices, sepNormal); //,&dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis = 0;
- }
- else //(!sepB)
- {
- bool sepEE = findSeparatingAxisEdgeEdge(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB], posA, ornA, posB, ornB, DeltaC2, vertices, uniqueEdges, faces, indices, &sepNormal, &dmin);
- if (sepEE)
- {
- gpuCompoundSepNormalsOut[i] = sepNormal; //fastNormalize4(sepNormal);
- gpuHasCompoundSepNormalsOut[i] = 1;
- } //sepEE
- } //(!sepB)
- } //(!sepA)
- }
-}
-
-__kernel void clipCompoundsHullHullKernel(__global const b3Int4* gpuCompoundPairs,
- __global const b3RigidBodyData* rigidBodies,
- __global const b3Collidable* collidables,
- __global const b3ConvexPolyhedronData* convexShapes,
- __global const b3AlignedObjectArray<b3Float4>& vertices,
- __global const b3AlignedObjectArray<b3Float4>& uniqueEdges,
- __global const b3AlignedObjectArray<b3GpuFace>& faces,
- __global const b3AlignedObjectArray<int>& indices,
- __global const b3GpuChildShape* gpuChildShapes,
- __global const b3AlignedObjectArray<b3Float4>& gpuCompoundSepNormalsOut,
- __global const b3AlignedObjectArray<int>& gpuHasCompoundSepNormalsOut,
- __global struct b3Contact4Data* globalContactsOut,
- int* nGlobalContactsOut,
- int numCompoundPairs, int maxContactCapacity, int i)
-{
- // int i = get_global_id(0);
- int pairIndex = i;
-
- float4 worldVertsB1[64];
- float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
-
- float4 localContactsOut[64];
- int localContactCapacity = 64;
-
- float minDist = -1e30f;
- float maxDist = 0.0f;
-
- if (i < numCompoundPairs)
- {
- if (gpuHasCompoundSepNormalsOut[i])
- {
- int bodyIndexA = gpuCompoundPairs[i].x;
- int bodyIndexB = gpuCompoundPairs[i].y;
-
- int childShapeIndexA = gpuCompoundPairs[i].z;
- int childShapeIndexB = gpuCompoundPairs[i].w;
-
- int collidableIndexA = -1;
- int collidableIndexB = -1;
-
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
-
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- if (childShapeIndexA >= 0)
- {
- collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA, childPosA) + posA;
- b3Quat newOrnA = b3QuatMul(ornA, childOrnA);
- posA = newPosA;
- ornA = newOrnA;
- }
- else
- {
- collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- }
-
- if (childShapeIndexB >= 0)
- {
- collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quat childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = b3QuatRotate(ornB, childPosB) + posB;
- b3Quat newOrnB = b3QuatMul(ornB, childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- }
- else
- {
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
- }
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
- convexShapes[shapeIndexA], convexShapes[shapeIndexB],
- posA, ornA,
- posB, ornB,
- worldVertsB1, worldVertsB2, capacityWorldVerts,
- minDist, maxDist,
- vertices, faces, indices,
- vertices, faces, indices,
- localContactsOut, localContactCapacity);
-
- if (numLocalContactsOut > 0)
- {
- float4 normal = -gpuCompoundSepNormalsOut[i];
- int nPoints = numLocalContactsOut;
- float4* pointsIn = localContactsOut;
- b3Int4 contactIdx; // = {-1,-1,-1,-1};
-
- contactIdx.s[0] = 0;
- contactIdx.s[1] = 1;
- contactIdx.s[2] = 2;
- contactIdx.s[3] = 3;
-
- int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
-
- int dstIdx;
- dstIdx = b3AtomicInc(nGlobalContactsOut);
- if ((dstIdx + nReducedContacts) < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f * 0xffff);
- c->m_frictionCoeffCmp = (0.7f * 0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = gpuCompoundPairs[pairIndex].x;
- int bodyB = gpuCompoundPairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass == 0 ? -bodyA : bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass == 0 ? -bodyB : bodyB;
- c->m_childIndexA = childShapeIndexA;
- c->m_childIndexB = childShapeIndexB;
- for (int i = 0; i < nReducedContacts; i++)
- {
- c->m_worldPosB[i] = pointsIn[contactIdx.s[i]];
- }
- b3Contact4Data_setNumPoints(c, nReducedContacts);
- }
-
- } // if (numContactsOut>0)
- } // if (gpuHasCompoundSepNormalsOut[i])
- } // if (i<numCompoundPairs)
-}
-
-void computeContactCompoundCompound(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3GpuChildShape* cpuChildShapes,
- const b3AlignedObjectArray<b3Aabb>& hostAabbsWorldSpace,
- const b3AlignedObjectArray<b3Aabb>& hostAabbsLocalSpace,
-
- const b3AlignedObjectArray<b3Vector3>& convexVertices,
- const b3AlignedObjectArray<b3Vector3>& hostUniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
-
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity,
- b3AlignedObjectArray<b3QuantizedBvhNode>& treeNodesCPU,
- b3AlignedObjectArray<b3BvhSubtreeInfo>& subTreesCPU,
- b3AlignedObjectArray<b3BvhInfo>& bvhInfoCPU)
-{
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
- b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
-
- b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
- int numCompoundPairsOut = 0;
- int maxNumCompoundPairsCapacity = 8192; //1024;
- cpuCompoundPairsOut.resize(maxNumCompoundPairsCapacity);
-
- // work-in-progress
- findCompoundPairsKernel(
- pairIndex,
- bodyIndexA, bodyIndexB,
- collidableIndexA, collidableIndexB,
- rigidBodies,
- collidables,
- convexShapes,
- convexVertices,
- hostAabbsWorldSpace,
- hostAabbsLocalSpace,
- cpuChildShapes,
- &cpuCompoundPairsOut[0],
- &numCompoundPairsOut,
- maxNumCompoundPairsCapacity,
- treeNodesCPU,
- subTreesCPU,
- bvhInfoCPU);
-
- printf("maxNumAabbChecks=%d\n", maxNumAabbChecks);
- if (numCompoundPairsOut > maxNumCompoundPairsCapacity)
- {
- b3Error("numCompoundPairsOut exceeded maxNumCompoundPairsCapacity (%d)\n", maxNumCompoundPairsCapacity);
- numCompoundPairsOut = maxNumCompoundPairsCapacity;
- }
- b3AlignedObjectArray<b3Float4> cpuCompoundSepNormalsOut;
- b3AlignedObjectArray<int> cpuHasCompoundSepNormalsOut;
- cpuCompoundSepNormalsOut.resize(numCompoundPairsOut);
- cpuHasCompoundSepNormalsOut.resize(numCompoundPairsOut);
-
- for (int i = 0; i < numCompoundPairsOut; i++)
- {
- processCompoundPairsKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, 0, cpuChildShapes,
- cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, numCompoundPairsOut, i);
- }
-
- for (int i = 0; i < numCompoundPairsOut; i++)
- {
- clipCompoundsHullHullKernel(&cpuCompoundPairsOut[0], rigidBodies, collidables, convexShapes, convexVertices, hostUniqueEdges, faces, convexIndices, cpuChildShapes,
- cpuCompoundSepNormalsOut, cpuHasCompoundSepNormalsOut, globalContactsOut, &nGlobalContactsOut, numCompoundPairsOut, maxContactCapacity, i);
- }
- /*
- int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- b3Quat childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = b3QuatRotate(ornA,childPosA)+posA;
- b3Quat newOrnA = b3QuatMul(ornA,childOrnA);
-
- int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
-
-
- bool foundSepAxis = findSeparatingAxis(hullA,hullB,
- posA,
- ornA,
- posB,
- ornB,
-
- convexVertices,uniqueEdges,faces,convexIndices,
- convexVertices,uniqueEdges,faces,convexIndices,
-
- sepNormalWorldSpace
- );
- */
-
- /*
- if (foundSepAxis)
- {
-
-
- contactIndex = clipHullHullSingle(
- bodyIndexA, bodyIndexB,
- posA,ornA,
- posB,ornB,
- collidableIndexA, collidableIndexB,
- &rigidBodies,
- &globalContactsOut,
- nGlobalContactsOut,
-
- convexShapes,
- convexShapes,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- collidables,
- collidables,
- sepNormalWorldSpace,
- maxContactCapacity);
-
- }
- */
-
- // return contactIndex;
-
- /*
-
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int c=0;c<numChildrenB;c++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+c;
- int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
-
- float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
- b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
- b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 posB = b3QuatRotate(rootOrnB,childPosB)+rootPosB;
- b3Quaternion ornB = b3QuatMul(rootOrnB,childOrnB);//b3QuatMul(ornB,childOrnB);
-
- int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
-
- const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
-
- }
- */
-}
-
-void computeContactPlaneCompound(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3GpuChildShape* cpuChildShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
-
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
-{
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
- b3Assert(shapeTypeB == SHAPE_COMPOUND_OF_CONVEX_HULLS);
-
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int c = 0; c < numChildrenB; c++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex + c;
- int childColIndexB = cpuChildShapes[childShapeIndexB].m_shapeIndex;
-
- float4 rootPosB = rigidBodies[bodyIndexB].m_pos;
- b3Quaternion rootOrnB = rigidBodies[bodyIndexB].m_quat;
- b3Vector3 childPosB = cpuChildShapes[childShapeIndexB].m_childPosition;
- b3Quaternion childOrnB = cpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 posB = b3QuatRotate(rootOrnB, childPosB) + rootPosB;
- b3Quaternion ornB = rootOrnB * childOrnB; //b3QuatMul(ornB,childOrnB);
-
- int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
-
- const b3ConvexPolyhedronData* hullB = &convexShapes[shapeIndexB];
-
- b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
-
- // int numContactsOut = 0;
- // int numWorldVertsB1= 0;
-
- b3Vector3 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- b3Vector3 planeNormal = b3MakeVector3(planeEq.x, planeEq.y, planeEq.z);
- b3Vector3 planeNormalWorld = b3QuatRotate(ornA, planeNormal);
- float planeConstant = planeEq.w;
- b3Transform convexWorldTransform;
- convexWorldTransform.setIdentity();
- convexWorldTransform.setOrigin(posB);
- convexWorldTransform.setRotation(ornB);
- b3Transform planeTransform;
- planeTransform.setIdentity();
- planeTransform.setOrigin(posA);
- planeTransform.setRotation(ornA);
-
- b3Transform planeInConvex;
- planeInConvex = convexWorldTransform.inverse() * planeTransform;
- b3Transform convexInPlane;
- convexInPlane = planeTransform.inverse() * convexWorldTransform;
-
- b3Vector3 planeNormalInConvex = planeInConvex.getBasis() * -planeNormal;
- float maxDot = -1e30;
- int hitVertex = -1;
- b3Vector3 hitVtx;
-
-#define MAX_PLANE_CONVEX_POINTS 64
-
- b3Vector3 contactPoints[MAX_PLANE_CONVEX_POINTS];
- int numPoints = 0;
-
- b3Int4 contactIdx;
- contactIdx.s[0] = 0;
- contactIdx.s[1] = 1;
- contactIdx.s[2] = 2;
- contactIdx.s[3] = 3;
-
- for (int i = 0; i < hullB->m_numVertices; i++)
- {
- b3Vector3 vtx = convexVertices[hullB->m_vertexOffset + i];
- float curDot = vtx.dot(planeNormalInConvex);
-
- if (curDot > maxDot)
- {
- hitVertex = i;
- maxDot = curDot;
- hitVtx = vtx;
- //make sure the deepest points is always included
- if (numPoints == MAX_PLANE_CONVEX_POINTS)
- numPoints--;
- }
-
- if (numPoints < MAX_PLANE_CONVEX_POINTS)
- {
- b3Vector3 vtxWorld = convexWorldTransform * vtx;
- b3Vector3 vtxInPlane = planeTransform.inverse() * vtxWorld;
- float dist = planeNormal.dot(vtxInPlane) - planeConstant;
- if (dist < 0.f)
- {
- vtxWorld.w = dist;
- contactPoints[numPoints] = vtxWorld;
- numPoints++;
- }
- }
- }
-
- int numReducedPoints = 0;
-
- numReducedPoints = numPoints;
-
- if (numPoints > 4)
- {
- numReducedPoints = extractManifoldSequentialGlobal(contactPoints, numPoints, planeNormalInConvex, &contactIdx);
- }
- int dstIdx;
- // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (numReducedPoints > 0)
- {
- if (nGlobalContactsOut < maxContactCapacity)
- {
- dstIdx = nGlobalContactsOut;
- nGlobalContactsOut++;
-
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -planeNormalWorld;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
-
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
- for (int i = 0; i < numReducedPoints; i++)
- {
- b3Vector3 pOnB1 = contactPoints[contactIdx.s[i]];
- c->m_worldPosB[i] = pOnB1;
- }
- c->m_worldNormalOnB.w = (b3Scalar)numReducedPoints;
- } //if (dstIdx < numPairs)
- }
- }
-}
-
-void computeContactSphereConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3RigidBodyData* rigidBodies,
- const b3Collidable* collidables,
- const b3ConvexPolyhedronData* convexShapes,
- const b3Vector3* convexVertices,
- const int* convexIndices,
- const b3GpuFace* faces,
- b3Contact4* globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity)
-{
- float radius = collidables[collidableIndexA].m_radius;
- float4 spherePos1 = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion sphereOrn = rigidBodies[bodyIndexA].m_quat;
-
- float4 pos = rigidBodies[bodyIndexB].m_pos;
-
- b3Quaternion quat = rigidBodies[bodyIndexB].m_quat;
-
- b3Transform tr;
- tr.setIdentity();
- tr.setOrigin(pos);
- tr.setRotation(quat);
- b3Transform trInv = tr.inverse();
-
- float4 spherePos = trInv(spherePos1);
-
- int collidableIndex = rigidBodies[bodyIndexB].m_collidableIdx;
- int shapeIndex = collidables[collidableIndex].m_shapeIndex;
- int numFaces = convexShapes[shapeIndex].m_numFaces;
- float4 closestPnt = b3MakeVector3(0, 0, 0, 0);
- // float4 hitNormalWorld = b3MakeVector3(0, 0, 0, 0);
- float minDist = -1000000.f; // TODO: What is the largest/smallest float?
- bool bCollide = true;
- int region = -1;
- float4 localHitNormal;
- for (int f = 0; f < numFaces; f++)
- {
- b3GpuFace face = faces[convexShapes[shapeIndex].m_faceOffset + f];
- float4 planeEqn;
- float4 localPlaneNormal = b3MakeVector3(face.m_plane.x, face.m_plane.y, face.m_plane.z, 0.f);
- float4 n1 = localPlaneNormal; //quatRotate(quat,localPlaneNormal);
- planeEqn = n1;
- planeEqn[3] = face.m_plane.w;
-
- float4 pntReturn;
- float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
-
- if (dist > radius)
- {
- bCollide = false;
- break;
- }
-
- if (dist > 0)
- {
- //might hit an edge or vertex
- b3Vector3 out;
-
- bool isInPoly = IsPointInPolygon(spherePos,
- &face,
- &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
- convexIndices,
- &out);
- if (isInPoly)
- {
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = pntReturn;
- localHitNormal = planeEqn;
- region = 1;
- }
- }
- else
- {
- b3Vector3 tmp = spherePos - out;
- b3Scalar l2 = tmp.length2();
- if (l2 < radius * radius)
- {
- dist = b3Sqrt(l2);
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = out;
- localHitNormal = tmp / dist;
- region = 2;
- }
- }
- else
- {
- bCollide = false;
- break;
- }
- }
- }
- else
- {
- if (dist > minDist)
- {
- minDist = dist;
- closestPnt = pntReturn;
- localHitNormal = planeEqn;
- region = 3;
- }
- }
- }
- static int numChecks = 0;
- numChecks++;
-
- if (bCollide && minDist > -10000)
- {
- float4 normalOnSurfaceB1 = tr.getBasis() * localHitNormal; //-hitNormalWorld;
- float4 pOnB1 = tr(closestPnt);
- //printf("dist ,%f,",minDist);
- float actualDepth = minDist - radius;
- if (actualDepth < 0)
- {
- //printf("actualDepth = ,%f,", actualDepth);
- //printf("normalOnSurfaceB1 = ,%f,%f,%f,", normalOnSurfaceB1.x,normalOnSurfaceB1.y,normalOnSurfaceB1.z);
- //printf("region=,%d,\n", region);
- pOnB1[3] = actualDepth;
-
- int dstIdx;
- // dstIdx = nGlobalContactsOut++;//AppendInc( nGlobalContactsOut, dstIdx );
-
- if (nGlobalContactsOut < maxContactCapacity)
- {
- dstIdx = nGlobalContactsOut;
- nGlobalContactsOut++;
-
- b3Contact4* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = normalOnSurfaceB1;
- c->setFrictionCoeff(0.7);
- c->setRestituitionCoeff(0.f);
-
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass == 0 ? -bodyIndexA : bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass == 0 ? -bodyIndexB : bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- int numPoints = 1;
- c->m_worldNormalOnB.w = (b3Scalar)numPoints;
- } //if (dstIdx < numPairs)
- }
- } //if (hasCollision)
-}
-
-int computeContactConvexConvex2(
- int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- const b3AlignedObjectArray<b3RigidBodyData>& rigidBodies,
- const b3AlignedObjectArray<b3Collidable>& collidables,
- const b3AlignedObjectArray<b3ConvexPolyhedronData>& convexShapes,
- const b3AlignedObjectArray<b3Vector3>& convexVertices,
- const b3AlignedObjectArray<b3Vector3>& uniqueEdges,
- const b3AlignedObjectArray<int>& convexIndices,
- const b3AlignedObjectArray<b3GpuFace>& faces,
- b3AlignedObjectArray<b3Contact4>& globalContactsOut,
- int& nGlobalContactsOut,
- int maxContactCapacity,
- const b3AlignedObjectArray<b3Contact4>& oldContacts)
-{
- int contactIndex = -1;
- b3Vector3 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quaternion ornA = rigidBodies[bodyIndexA].m_quat;
- b3Vector3 posB = rigidBodies[bodyIndexB].m_pos;
- b3Quaternion ornB = rigidBodies[bodyIndexB].m_quat;
-
- b3ConvexPolyhedronData hullA, hullB;
-
- b3Vector3 sepNormalWorldSpace;
-
- b3Collidable colA = collidables[collidableIndexA];
- hullA = convexShapes[colA.m_shapeIndex];
- //printf("numvertsA = %d\n",hullA.m_numVertices);
-
- b3Collidable colB = collidables[collidableIndexB];
- hullB = convexShapes[colB.m_shapeIndex];
- //printf("numvertsB = %d\n",hullB.m_numVertices);
-
- // int contactCapacity = MAX_VERTS;
- //int numContactsOut=0;
-
-#ifdef _WIN32
- b3Assert(_finite(rigidBodies[bodyIndexA].m_pos.x));
- b3Assert(_finite(rigidBodies[bodyIndexB].m_pos.x));
-#endif
-
- bool foundSepAxis = findSeparatingAxis(hullA, hullB,
- posA,
- ornA,
- posB,
- ornB,
-
- convexVertices, uniqueEdges, faces, convexIndices,
- convexVertices, uniqueEdges, faces, convexIndices,
-
- sepNormalWorldSpace);
-
- if (foundSepAxis)
- {
- contactIndex = clipHullHullSingle(
- bodyIndexA, bodyIndexB,
- posA, ornA,
- posB, ornB,
- collidableIndexA, collidableIndexB,
- &rigidBodies,
- &globalContactsOut,
- nGlobalContactsOut,
-
- convexShapes,
- convexShapes,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- convexVertices,
- uniqueEdges,
- faces,
- convexIndices,
-
- collidables,
- collidables,
- sepNormalWorldSpace,
- maxContactCapacity);
- }
-
- return contactIndex;
-}
-
-void GpuSatCollision::computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
- const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
- const b3OpenCLArray<b3Contact4>* oldContacts,
- int maxContactCapacity,
- int compoundPairCapacity,
- const b3OpenCLArray<b3ConvexPolyhedronData>& convexData,
- const b3OpenCLArray<b3Vector3>& gpuVertices,
- const b3OpenCLArray<b3Vector3>& gpuUniqueEdges,
- const b3OpenCLArray<b3GpuFace>& gpuFaces,
- const b3OpenCLArray<int>& gpuIndices,
- const b3OpenCLArray<b3Collidable>& gpuCollidables,
- const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
-
- const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
- const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
-
- b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
- b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
- b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
- b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
- b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
- b3AlignedObjectArray<class b3OptimizedBvh*>& bvhDataUnused,
- b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
- b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
- b3OpenCLArray<b3BvhInfo>* bvhInfo,
-
- int numObjects,
- int maxTriConvexPairCapacity,
- b3OpenCLArray<b3Int4>& triangleConvexPairsOut,
- int& numTriConvexPairsOut)
-{
- myframecount++;
-
- if (!nPairs)
- return;
-
-#ifdef CHECK_ON_HOST
-
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
- treeNodesGPU->copyToHost(treeNodesCPU);
-
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
- subTreesGPU->copyToHost(subTreesCPU);
-
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
- bvhInfo->copyToHost(bvhInfoCPU);
-
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
-
- b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
- clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
-
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
-
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
-
- b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
- gpuUniqueEdges.copyToHost(hostUniqueEdges);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
-
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
-
- b3AlignedObjectArray<b3Int4> hostTriangleConvexPairs;
-
- b3AlignedObjectArray<b3Contact4> hostContacts;
- if (nContacts)
- {
- contactOut->copyToHost(hostContacts);
- }
-
- b3AlignedObjectArray<b3Contact4> oldHostContacts;
-
- if (oldContacts->size())
- {
- oldContacts->copyToHost(oldHostContacts);
- }
-
- hostContacts.resize(maxContactCapacity);
-
- for (int i = 0; i < nPairs; i++)
- {
- int bodyIndexA = hostPairs[i].x;
- int bodyIndexB = hostPairs[i].y;
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- computeContactSphereConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
- computeContactSphereConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- //printf("convex-sphere\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
- computeContactPlaneConvex(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- // printf("convex-plane\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- computeContactPlaneConvex(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- // printf("plane-convex\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- computeContactCompoundCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], hostAabbsWorldSpace, hostAabbsLocalSpace, hostVertices, hostUniqueEdges, hostIndices, hostFaces, &hostContacts[0],
- nContacts, maxContactCapacity, treeNodesCPU, subTreesCPU, bvhInfoCPU);
- // printf("convex-plane\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
- computeContactPlaneCompound(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- // printf("convex-plane\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- computeContactPlaneCompound(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, &hostBodyBuf[0],
- &hostCollidables[0], &hostConvexData[0], &cpuChildShapes[0], &hostVertices[0], &hostIndices[0], &hostFaces[0], &hostContacts[0], nContacts, maxContactCapacity);
- // printf("plane-convex\n");
- }
-
- if (hostCollidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- hostCollidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
- //printf("hostPairs[i].z=%d\n",hostPairs[i].z);
- int contactIndex = computeContactConvexConvex2(i, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, hostBodyBuf, hostCollidables, hostConvexData, hostVertices, hostUniqueEdges, hostIndices, hostFaces, hostContacts, nContacts, maxContactCapacity, oldHostContacts);
- //int contactIndex = computeContactConvexConvex(hostPairs,i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf,hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
-
- if (contactIndex >= 0)
- {
- // printf("convex convex contactIndex = %d\n",contactIndex);
- hostPairs[i].z = contactIndex;
- }
- // printf("plane-convex\n");
- }
- }
-
- if (hostPairs.size())
- {
- pairs->copyFromHost(hostPairs);
- }
-
- hostContacts.resize(nContacts);
- if (nContacts)
- {
- contactOut->copyFromHost(hostContacts);
- }
- else
- {
- contactOut->resize(0);
- }
-
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
- //printf("(HOST) nContacts = %d\n",nContacts);
-
-#else
-
- {
- if (nPairs)
- {
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
-
- B3_PROFILE("primitiveContactsKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_primitiveContactsKernel, "m_primitiveContactsKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nPairs);
- launcher.setConst(maxContactCapacity);
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
-
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
- }
- }
-
-#endif //CHECK_ON_HOST
-
- B3_PROFILE("computeConvexConvexContactsGPUSAT");
- // printf("nContacts = %d\n",nContacts);
-
- m_sepNormals.resize(nPairs);
- m_hasSeparatingNormals.resize(nPairs);
-
- int concaveCapacity = maxTriConvexPairCapacity;
- m_concaveSepNormals.resize(concaveCapacity);
- m_concaveHasSeparatingNormals.resize(concaveCapacity);
- m_numConcavePairsOut.resize(0);
- m_numConcavePairsOut.push_back(0);
-
- m_gpuCompoundPairs.resize(compoundPairCapacity);
-
- m_gpuCompoundSepNormals.resize(compoundPairCapacity);
-
- m_gpuHasCompoundSepNormals.resize(compoundPairCapacity);
-
- m_numCompoundPairsOut.resize(0);
- m_numCompoundPairsOut.push_back(0);
-
- int numCompoundPairs = 0;
-
- int numConcavePairs = 0;
-
- {
- clFinish(m_queue);
- if (findSeparatingAxisOnGpu)
- {
- m_dmins.resize(nPairs);
- if (splitSearchSepAxisConvex)
- {
- if (useMprGpu)
- {
- nContacts = m_totalContactsOut.at(0);
- {
- B3_PROFILE("mprPenetrationKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_mprPenetrationKernel, "mprPenetrationKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
-
- launcher.setConst(maxContactCapacity);
- launcher.setConst(nPairs);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- /*
- b3AlignedObjectArray<int>hostHasSepAxis;
- m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
- b3AlignedObjectArray<b3Vector3>hostSepAxis;
- m_sepNormals.copyToHost(hostSepAxis);
- */
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
- // printf("nContacts (after mprPenetrationKernel) = %d\n",nContacts);
- if (nContacts > maxContactCapacity)
- {
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- }
- }
-
- if (1)
- {
- if (1)
- {
- {
- B3_PROFILE("findSeparatingAxisVertexFaceKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisVertexFaceKernel, "findSeparatingAxisVertexFaceKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nPairs);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
-
- {
- B3_PROFILE("findSeparatingAxisEdgeEdgeKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL()),
- b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true)
-
- };
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisEdgeEdgeKernel, "findSeparatingAxisEdgeEdgeKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numDirections);
- launcher.setConst(nPairs);
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- }
- if (useMprGpu)
- {
- B3_PROFILE("findSeparatingAxisUnitSphereKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(m_unitSphereDirections.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisUnitSphereKernel, "findSeparatingAxisUnitSphereKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- int numDirections = sizeof(unitSphere162) / sizeof(b3Vector3);
- launcher.setConst(numDirections);
-
- launcher.setConst(nPairs);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- }
- }
- else
- {
- B3_PROFILE("findSeparatingAxisKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findSeparatingAxisKernel, "m_findSeparatingAxisKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nPairs);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- }
- else
- {
- B3_PROFILE("findSeparatingAxisKernel CPU");
-
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
-
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexShapeData;
- convexData.copyToHost(hostConvexShapeData);
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
-
- b3AlignedObjectArray<int> hostHasSepAxis;
- hostHasSepAxis.resize(nPairs);
- b3AlignedObjectArray<b3Vector3> hostSepAxis;
- hostSepAxis.resize(nPairs);
-
- b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
- gpuUniqueEdges.copyToHost(hostUniqueEdges);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
-
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
-
- b3AlignedObjectArray<b3Contact4> hostContacts;
- if (nContacts)
- {
- contactOut->copyToHost(hostContacts);
- }
- hostContacts.resize(maxContactCapacity);
- int nGlobalContactsOut = nContacts;
-
- for (int i = 0; i < nPairs; i++)
- {
- int bodyIndexA = hostPairs[i].x;
- int bodyIndexB = hostPairs[i].y;
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
-
- hostHasSepAxis[i] = 0;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((hostBodyBuf[bodyIndexA].m_invMass == 0) && (hostBodyBuf[bodyIndexB].m_invMass == 0))
- {
- continue;
- }
-
- if ((hostCollidables[collidableIndexA].m_shapeType != SHAPE_CONVEX_HULL) || (hostCollidables[collidableIndexB].m_shapeType != SHAPE_CONVEX_HULL))
- {
- continue;
- }
-
- float dmin = FLT_MAX;
-
- b3ConvexPolyhedronData* convexShapeA = &hostConvexShapeData[shapeIndexA];
- b3ConvexPolyhedronData* convexShapeB = &hostConvexShapeData[shapeIndexB];
- b3Vector3 posA = hostBodyBuf[bodyIndexA].m_pos;
- b3Vector3 posB = hostBodyBuf[bodyIndexB].m_pos;
- b3Quaternion ornA = hostBodyBuf[bodyIndexA].m_quat;
- b3Quaternion ornB = hostBodyBuf[bodyIndexB].m_quat;
-
- if (useGjk)
- {
- //first approximate the separating axis, to 'fail-proof' GJK+EPA or MPR
- {
- b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
- b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
- b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
- b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
- b3Vector3 DeltaC2 = c0 - c1;
-
- b3Vector3 sepAxis;
-
- bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
-
- if (hasSepAxisA)
- {
- bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
- if (hasSepAxisB)
- {
- bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin, false);
-
- if (hasEdgeEdge)
- {
- hostHasSepAxis[i] = 1;
- hostSepAxis[i] = sepAxis;
- hostSepAxis[i].w = dmin;
- }
- }
- }
- }
-
- if (hostHasSepAxis[i])
- {
- int pairIndex = i;
-
- bool useMpr = true;
- if (useMpr)
- {
- int res = 0;
- float depth = 0.f;
- b3Vector3 sepAxis2 = b3MakeVector3(1, 0, 0);
- b3Vector3 resultPointOnBWorld = b3MakeVector3(0, 0, 0);
-
- float depthOut;
- b3Vector3 dirOut;
- b3Vector3 posOut;
-
- //res = b3MprPenetration(bodyIndexA,bodyIndexB,hostBodyBuf,hostConvexShapeData,hostCollidables,hostVertices,&mprConfig,&depthOut,&dirOut,&posOut);
- res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB, &hostBodyBuf[0], &hostConvexShapeData[0], &hostCollidables[0], &hostVertices[0], &hostSepAxis[0], &hostHasSepAxis[0], &depthOut, &dirOut, &posOut);
- depth = depthOut;
- sepAxis2 = b3MakeVector3(-dirOut.x, -dirOut.y, -dirOut.z);
- resultPointOnBWorld = posOut;
- //hostHasSepAxis[i] = 0;
-
- if (res == 0)
- {
- //add point?
- //printf("depth = %f\n",depth);
- //printf("normal = %f,%f,%f\n",dir.v[0],dir.v[1],dir.v[2]);
- //qprintf("pos = %f,%f,%f\n",pos.v[0],pos.v[1],pos.v[2]);
-
- float dist = 0.f;
-
- const b3ConvexPolyhedronData& hullA = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexA].m_collidableIdx].m_shapeIndex];
- const b3ConvexPolyhedronData& hullB = hostConvexShapeData[hostCollidables[hostBodyBuf[bodyIndexB].m_collidableIdx].m_shapeIndex];
-
- if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
- {
- if (depth > dist)
- {
- float diff = depth - dist;
-
- static float maxdiff = 0.f;
- if (maxdiff < diff)
- {
- maxdiff = diff;
- printf("maxdiff = %20.10f\n", maxdiff);
- }
- }
- }
- if (depth > dmin)
- {
- b3Vector3 oldAxis = hostSepAxis[i];
- depth = dmin;
- sepAxis2 = oldAxis;
- }
-
- if (b3TestSepAxis(&hullA, &hullB, posA, ornA, posB, ornB, &sepAxis2, &hostVertices[0], &hostVertices[0], &dist))
- {
- if (depth > dist)
- {
- float diff = depth - dist;
- //printf("?diff = %f\n",diff );
- static float maxdiff = 0.f;
- if (maxdiff < diff)
- {
- maxdiff = diff;
- printf("maxdiff = %20.10f\n", maxdiff);
- }
- }
- //this is used for SAT
- //hostHasSepAxis[i] = 1;
- //hostSepAxis[i] = sepAxis2;
-
- //add contact point
-
- //int contactIndex = nGlobalContactsOut;
- b3Contact4& newContact = hostContacts.at(nGlobalContactsOut);
- nGlobalContactsOut++;
- newContact.m_batchIdx = 0; //i;
- newContact.m_bodyAPtrAndSignBit = (hostBodyBuf.at(bodyIndexA).m_invMass == 0) ? -bodyIndexA : bodyIndexA;
- newContact.m_bodyBPtrAndSignBit = (hostBodyBuf.at(bodyIndexB).m_invMass == 0) ? -bodyIndexB : bodyIndexB;
-
- newContact.m_frictionCoeffCmp = 45874;
- newContact.m_restituitionCoeffCmp = 0;
-
- static float maxDepth = 0.f;
-
- if (depth > maxDepth)
- {
- maxDepth = depth;
- printf("MPR maxdepth = %f\n", maxDepth);
- }
-
- resultPointOnBWorld.w = -depth;
- newContact.m_worldPosB[0] = resultPointOnBWorld;
- //b3Vector3 resultPointOnAWorld = resultPointOnBWorld+depth*sepAxis2;
- newContact.m_worldNormalOnB = sepAxis2;
- newContact.m_worldNormalOnB.w = (b3Scalar)1;
- }
- else
- {
- printf("rejected\n");
- }
- }
- }
- else
- {
- //int contactIndex = computeContactConvexConvex2( i,bodyIndexA,bodyIndexB,collidableIndexA,collidableIndexB,hostBodyBuf, hostCollidables,hostConvexData,hostVertices,hostUniqueEdges,hostIndices,hostFaces,hostContacts,nContacts,maxContactCapacity,oldHostContacts);
- b3AlignedObjectArray<b3Contact4> oldHostContacts;
- int result;
- result = computeContactConvexConvex2( //hostPairs,
- pairIndex,
- bodyIndexA, bodyIndexB,
- collidableIndexA, collidableIndexB,
- hostBodyBuf,
- hostCollidables,
- hostConvexShapeData,
- hostVertices,
- hostUniqueEdges,
- hostIndices,
- hostFaces,
- hostContacts,
- nGlobalContactsOut,
- maxContactCapacity,
- oldHostContacts
- //hostHasSepAxis,
- //hostSepAxis
-
- );
- } //mpr
- } //hostHasSepAxis[i] = 1;
- }
- else
- {
- b3Vector3 c0local = hostConvexShapeData[shapeIndexA].m_localCenter;
- b3Vector3 c0 = b3TransformPoint(c0local, posA, ornA);
- b3Vector3 c1local = hostConvexShapeData[shapeIndexB].m_localCenter;
- b3Vector3 c1 = b3TransformPoint(c1local, posB, ornB);
- b3Vector3 DeltaC2 = c0 - c1;
-
- b3Vector3 sepAxis;
-
- bool hasSepAxisA = b3FindSeparatingAxis(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
-
- if (hasSepAxisA)
- {
- bool hasSepAxisB = b3FindSeparatingAxis(convexShapeB, convexShapeA, posB, ornB, posA, ornA, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin);
- if (hasSepAxisB)
- {
- bool hasEdgeEdge = b3FindSeparatingAxisEdgeEdge(convexShapeA, convexShapeB, posA, ornA, posB, ornB, DeltaC2,
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &hostVertices.at(0), &hostUniqueEdges.at(0), &hostFaces.at(0), &hostIndices.at(0),
- &sepAxis, &dmin, true);
-
- if (hasEdgeEdge)
- {
- hostHasSepAxis[i] = 1;
- hostSepAxis[i] = sepAxis;
- }
- }
- }
- }
- }
-
- if (useGjkContacts) //nGlobalContactsOut>0)
- {
- //printf("nGlobalContactsOut=%d\n",nGlobalContactsOut);
- nContacts = nGlobalContactsOut;
- contactOut->copyFromHost(hostContacts);
-
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
- }
-
- m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
- m_sepNormals.copyFromHost(hostSepAxis);
-
- /*
- //double-check results from GPU (comment-out the 'else' so both paths are executed
- b3AlignedObjectArray<int> checkHasSepAxis;
- m_hasSeparatingNormals.copyToHost(checkHasSepAxis);
- static int frameCount = 0;
- frameCount++;
- for (int i=0;i<nPairs;i++)
- {
- if (hostHasSepAxis[i] != checkHasSepAxis[i])
- {
- printf("at frameCount %d hostHasSepAxis[%d] = %d but checkHasSepAxis[i] = %d\n",
- frameCount,i,hostHasSepAxis[i],checkHasSepAxis[i]);
- }
- }
- //m_hasSeparatingNormals.copyFromHost(hostHasSepAxis);
- // m_sepNormals.copyFromHost(hostSepAxis);
- */
- }
-
- numCompoundPairs = m_numCompoundPairsOut.at(0);
- bool useGpuFindCompoundPairs = true;
- if (useGpuFindCompoundPairs)
- {
- B3_PROFILE("findCompoundPairsKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsLocalSpace.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL()),
- b3BufferInfoCL(m_numCompoundPairsOut.getBufferCL()),
- b3BufferInfoCL(subTreesGPU->getBufferCL()),
- b3BufferInfoCL(treeNodesGPU->getBufferCL()),
- b3BufferInfoCL(bvhInfo->getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findCompoundPairsKernel, "m_findCompoundPairsKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nPairs);
- launcher.setConst(compoundPairCapacity);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
-
- numCompoundPairs = m_numCompoundPairsOut.at(0);
- //printf("numCompoundPairs =%d\n",numCompoundPairs );
- if (numCompoundPairs)
- {
- //printf("numCompoundPairs=%d\n",numCompoundPairs);
- }
- }
- else
- {
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
- treeNodesGPU->copyToHost(treeNodesCPU);
-
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
- subTreesGPU->copyToHost(subTreesCPU);
-
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
- bvhInfo->copyToHost(bvhInfoCPU);
-
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
-
- b3AlignedObjectArray<b3Aabb> hostAabbsLocalSpace;
- clAabbsLocalSpace.copyToHost(hostAabbsLocalSpace);
-
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
-
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- b3AlignedObjectArray<b3Int4> cpuCompoundPairsOut;
- cpuCompoundPairsOut.resize(compoundPairCapacity);
-
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
-
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
-
- for (int pairIndex = 0; pairIndex < nPairs; pairIndex++)
- {
- int bodyIndexA = hostPairs[pairIndex].x;
- int bodyIndexB = hostPairs[pairIndex].y;
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
- if (cpuChildShapes.size())
- {
- findCompoundPairsKernel(
- pairIndex,
- bodyIndexA,
- bodyIndexB,
- collidableIndexA,
- collidableIndexB,
- &hostBodyBuf[0],
- &hostCollidables[0],
- &hostConvexData[0],
- hostVertices,
- hostAabbsWorldSpace,
- hostAabbsLocalSpace,
- &cpuChildShapes[0],
- &cpuCompoundPairsOut[0],
- &numCompoundPairs,
- compoundPairCapacity,
- treeNodesCPU,
- subTreesCPU,
- bvhInfoCPU);
- }
- }
-
- m_numCompoundPairsOut.copyFromHostPointer(&numCompoundPairs, 1, 0, true);
- if (numCompoundPairs)
- {
- b3CompoundOverlappingPair* ptr = (b3CompoundOverlappingPair*)&cpuCompoundPairsOut[0];
- m_gpuCompoundPairs.copyFromHostPointer(ptr, numCompoundPairs, 0, true);
- }
- //cpuCompoundPairsOut
- }
- if (numCompoundPairs)
- {
- printf("numCompoundPairs=%d\n", numCompoundPairs);
- }
-
- if (numCompoundPairs > compoundPairCapacity)
- {
- b3Error("Exceeded compound pair capacity (%d/%d)\n", numCompoundPairs, compoundPairCapacity);
- numCompoundPairs = compoundPairCapacity;
- }
-
- m_gpuCompoundPairs.resize(numCompoundPairs);
- m_gpuHasCompoundSepNormals.resize(numCompoundPairs);
- m_gpuCompoundSepNormals.resize(numCompoundPairs);
-
- if (numCompoundPairs)
- {
- B3_PROFILE("processCompoundPairsPrimitivesKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_processCompoundPairsPrimitivesKernel, "m_processCompoundPairsPrimitivesKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numCompoundPairs);
- launcher.setConst(maxContactCapacity);
-
- int num = numCompoundPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- nContacts = m_totalContactsOut.at(0);
- //printf("nContacts (after processCompoundPairsPrimitivesKernel) = %d\n",nContacts);
- if (nContacts > maxContactCapacity)
- {
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- }
-
- if (numCompoundPairs)
- {
- B3_PROFILE("processCompoundPairsKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL()),
- b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_processCompoundPairsKernel, "m_processCompoundPairsKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numCompoundPairs);
-
- int num = numCompoundPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- //printf("numConcave = %d\n",numConcave);
-
- // printf("hostNormals.size()=%d\n",hostNormals.size());
- //int numPairs = pairCount.at(0);
- }
- int vertexFaceCapacity = 64;
-
- {
- //now perform the tree query on GPU
-
- if (treeNodesGPU->size() && treeNodesGPU->size())
- {
- if (bvhTraversalKernelGPU)
- {
- B3_PROFILE("m_bvhTraversalKernel");
-
- numConcavePairs = m_numConcavePairsOut.at(0);
-
- b3LauncherCL launcher(m_queue, m_bvhTraversalKernel, "m_bvhTraversalKernel");
- launcher.setBuffer(pairs->getBufferCL());
- launcher.setBuffer(bodyBuf->getBufferCL());
- launcher.setBuffer(gpuCollidables.getBufferCL());
- launcher.setBuffer(clAabbsWorldSpace.getBufferCL());
- launcher.setBuffer(triangleConvexPairsOut.getBufferCL());
- launcher.setBuffer(m_numConcavePairsOut.getBufferCL());
- launcher.setBuffer(subTreesGPU->getBufferCL());
- launcher.setBuffer(treeNodesGPU->getBufferCL());
- launcher.setBuffer(bvhInfo->getBufferCL());
-
- launcher.setConst(nPairs);
- launcher.setConst(maxTriConvexPairCapacity);
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- numConcavePairs = m_numConcavePairsOut.at(0);
- }
- else
- {
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
-
- //int maxTriConvexPairCapacity,
- b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
- triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
-
- //int numTriConvexPairsOutHost=0;
- numConcavePairs = 0;
- //m_numConcavePairsOut
-
- b3AlignedObjectArray<b3QuantizedBvhNode> treeNodesCPU;
- treeNodesGPU->copyToHost(treeNodesCPU);
- b3AlignedObjectArray<b3BvhSubtreeInfo> subTreesCPU;
- subTreesGPU->copyToHost(subTreesCPU);
- b3AlignedObjectArray<b3BvhInfo> bvhInfoCPU;
- bvhInfo->copyToHost(bvhInfoCPU);
- //compute it...
-
- volatile int hostNumConcavePairsOut = 0;
-
- //
- for (int i = 0; i < nPairs; i++)
- {
- b3BvhTraversal(&hostPairs.at(0),
- &hostBodyBuf.at(0),
- &hostCollidables.at(0),
- &hostAabbsWorldSpace.at(0),
- &triangleConvexPairsOutHost.at(0),
- &hostNumConcavePairsOut,
- &subTreesCPU.at(0),
- &treeNodesCPU.at(0),
- &bvhInfoCPU.at(0),
- nPairs,
- maxTriConvexPairCapacity,
- i);
- }
- numConcavePairs = hostNumConcavePairsOut;
-
- if (hostNumConcavePairsOut)
- {
- triangleConvexPairsOutHost.resize(hostNumConcavePairsOut);
- triangleConvexPairsOut.copyFromHost(triangleConvexPairsOutHost);
- }
- //
-
- m_numConcavePairsOut.resize(0);
- m_numConcavePairsOut.push_back(numConcavePairs);
- }
-
- //printf("numConcavePairs=%d (max = %d\n",numConcavePairs,maxTriConvexPairCapacity);
-
- if (numConcavePairs > maxTriConvexPairCapacity)
- {
- static int exceeded_maxTriConvexPairCapacity_count = 0;
- b3Error("Exceeded the maxTriConvexPairCapacity (found %d but max is %d, it happened %d times)\n",
- numConcavePairs, maxTriConvexPairCapacity, exceeded_maxTriConvexPairCapacity_count++);
- numConcavePairs = maxTriConvexPairCapacity;
- }
- triangleConvexPairsOut.resize(numConcavePairs);
-
- if (numConcavePairs)
- {
- clippingFacesOutGPU.resize(numConcavePairs);
- worldNormalsAGPU.resize(numConcavePairs);
- worldVertsA1GPU.resize(vertexFaceCapacity * (numConcavePairs));
- worldVertsB1GPU.resize(vertexFaceCapacity * (numConcavePairs));
-
- if (findConcaveSeparatingAxisKernelGPU)
- {
- /*
- m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
- worldNormalsAGPU.copyFromHost(worldNormalsACPU);
- worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
- */
-
- //now perform a SAT test for each triangle-convex element (stored in triangleConvexPairsOut)
- if (splitSearchSepAxisConcave)
- {
- //printf("numConcavePairs = %d\n",numConcavePairs);
- m_dmins.resize(numConcavePairs);
- {
- B3_PROFILE("findConcaveSeparatingAxisVertexFaceKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisVertexFaceKernel, "m_findConcaveSeparatingAxisVertexFaceKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(numConcavePairs);
-
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- // numConcavePairs = 0;
- if (1)
- {
- B3_PROFILE("findConcaveSeparatingAxisEdgeEdgeKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(m_dmins.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisEdgeEdgeKernel, "m_findConcaveSeparatingAxisEdgeEdgeKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(numConcavePairs);
-
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- // numConcavePairs = 0;
- }
- else
- {
- B3_PROFILE("findConcaveSeparatingAxisKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findConcaveSeparatingAxisKernel, "m_findConcaveSeparatingAxisKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(numConcavePairs);
-
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- }
- else
- {
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
-
- b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
- triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
- //triangleConvexPairsOutHost.resize(maxTriConvexPairCapacity);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
- b3AlignedObjectArray<b3Aabb> hostAabbsWorldSpace;
- clAabbsWorldSpace.copyToHost(hostAabbsWorldSpace);
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
-
- b3AlignedObjectArray<b3Vector3> hostUniqueEdges;
- gpuUniqueEdges.copyToHost(hostUniqueEdges);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
- b3AlignedObjectArray<b3GpuChildShape> cpuChildShapes;
- gpuChildShapes.copyToHost(cpuChildShapes);
-
- b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
- m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
- concaveHasSeparatingNormalsCPU.resize(concaveSepNormalsHost.size());
-
- b3GpuChildShape* childShapePointerCPU = 0;
- if (cpuChildShapes.size())
- childShapePointerCPU = &cpuChildShapes.at(0);
-
- clippingFacesOutCPU.resize(clippingFacesOutGPU.size());
- worldVertsA1CPU.resize(worldVertsA1GPU.size());
- worldNormalsACPU.resize(worldNormalsAGPU.size());
- worldVertsB1CPU.resize(worldVertsB1GPU.size());
-
- for (int i = 0; i < numConcavePairs; i++)
- {
- b3FindConcaveSeparatingAxisKernel(&triangleConvexPairsOutHost.at(0),
- &hostBodyBuf.at(0),
- &hostCollidables.at(0),
- &hostConvexData.at(0), &hostVertices.at(0), &hostUniqueEdges.at(0),
- &hostFaces.at(0), &hostIndices.at(0), childShapePointerCPU,
- &hostAabbsWorldSpace.at(0),
- &concaveSepNormalsHost.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- vertexFaceCapacity,
- numConcavePairs, i);
- };
-
- m_concaveSepNormals.copyFromHost(concaveSepNormalsHost);
- m_concaveHasSeparatingNormals.copyFromHost(concaveHasSeparatingNormalsCPU);
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
- worldNormalsAGPU.copyFromHost(worldNormalsACPU);
- worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
- }
- // b3AlignedObjectArray<b3Vector3> cpuCompoundSepNormals;
- // m_concaveSepNormals.copyToHost(cpuCompoundSepNormals);
- // b3AlignedObjectArray<b3Int4> cpuConcavePairs;
- // triangleConvexPairsOut.copyToHost(cpuConcavePairs);
- }
- }
- }
-
- if (numConcavePairs)
- {
- if (numConcavePairs)
- {
- B3_PROFILE("findConcaveSphereContactsKernel");
- nContacts = m_totalContactsOut.at(0);
- // printf("nContacts1 = %d\n",nContacts);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL()),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(clAabbsWorldSpace.getBufferCL(), true),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findConcaveSphereContactsKernel, "m_findConcaveSphereContactsKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
-
- launcher.setConst(numConcavePairs);
- launcher.setConst(maxContactCapacity);
-
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- nContacts = m_totalContactsOut.at(0);
- //printf("nContacts (after findConcaveSphereContactsKernel) = %d\n",nContacts);
-
- //printf("nContacts2 = %d\n",nContacts);
-
- if (nContacts >= maxContactCapacity)
- {
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- }
- }
-
-#ifdef __APPLE__
- bool contactClippingOnGpu = true;
-#else
- bool contactClippingOnGpu = true;
-#endif
-
- if (contactClippingOnGpu)
- {
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
- // printf("nContacts3 = %d\n",nContacts);
-
- //B3_PROFILE("clipHullHullKernel");
-
- bool breakupConcaveConvexKernel = true;
-
-#ifdef __APPLE__
- //actually, some Apple OpenCL platform/device combinations work fine...
- breakupConcaveConvexKernel = true;
-#endif
- //concave-convex contact clipping
- if (numConcavePairs)
- {
- // printf("numConcavePairs = %d\n", numConcavePairs);
- // nContacts = m_totalContactsOut.at(0);
- // printf("nContacts before = %d\n", nContacts);
-
- if (breakupConcaveConvexKernel)
- {
- worldVertsB2GPU.resize(vertexFaceCapacity * numConcavePairs);
-
- //clipFacesAndFindContacts
-
- if (clipConcaveFacesAndFindContactsCPU)
- {
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
-
- clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyToHost(worldVertsA1CPU);
- worldNormalsAGPU.copyToHost(worldNormalsACPU);
- worldVertsB1GPU.copyToHost(worldVertsB1CPU);
-
- b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
- m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
-
- b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
- m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
-
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
- worldVertsB2CPU.resize(worldVertsB2GPU.size());
-
- for (int i = 0; i < numConcavePairs; i++)
- {
- clipFacesAndFindContactsKernel(&concaveSepNormalsHost.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &worldVertsB2CPU.at(0),
- vertexFaceCapacity,
- i);
- }
-
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
- }
- else
- {
- if (1)
- {
- B3_PROFILE("clipFacesAndFindContacts");
- //nContacts = m_totalContactsOut.at(0);
- //int h = m_hasSeparatingNormals.at(0);
- //int4 p = clippingFacesOutGPU.at(0);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
-
- launcher.setConst(numConcavePairs);
- int debugMode = 0;
- launcher.setConst(debugMode);
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- //int bla = m_totalContactsOut.at(0);
- }
- }
- //contactReduction
- {
- int newContactCapacity = nContacts + numConcavePairs;
- contactOut->reserve(newContactCapacity);
- if (reduceConcaveContactsOnGPU)
- {
- // printf("newReservation = %d\n",newReservation);
- {
- B3_PROFILE("newContactReductionKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(m_concaveHasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(newContactCapacity);
- launcher.setConst(numConcavePairs);
- int num = numConcavePairs;
-
- launcher.launch1D(num);
- }
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
-
- //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
- }
- else
- {
- volatile int nGlobalContactsOut = nContacts;
- b3AlignedObjectArray<b3Int4> triangleConvexPairsOutHost;
- triangleConvexPairsOut.copyToHost(triangleConvexPairsOutHost);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- b3AlignedObjectArray<int> concaveHasSeparatingNormalsCPU;
- m_concaveHasSeparatingNormals.copyToHost(concaveHasSeparatingNormalsCPU);
-
- b3AlignedObjectArray<b3Vector3> concaveSepNormalsHost;
- m_concaveSepNormals.copyToHost(concaveSepNormalsHost);
-
- b3AlignedObjectArray<b3Contact4> hostContacts;
- if (nContacts)
- {
- contactOut->copyToHost(hostContacts);
- }
- hostContacts.resize(newContactCapacity);
-
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
-
- clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
- worldVertsB2GPU.copyToHost(worldVertsB2CPU);
-
- for (int i = 0; i < numConcavePairs; i++)
- {
- b3NewContactReductionKernel(&triangleConvexPairsOutHost.at(0),
- &hostBodyBuf.at(0),
- &concaveSepNormalsHost.at(0),
- &concaveHasSeparatingNormalsCPU.at(0),
- &hostContacts.at(0),
- &clippingFacesOutCPU.at(0),
- &worldVertsB2CPU.at(0),
- &nGlobalContactsOut,
- vertexFaceCapacity,
- newContactCapacity,
- numConcavePairs,
- i);
- }
-
- nContacts = nGlobalContactsOut;
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
- // nContacts = m_totalContactsOut.at(0);
- //contactOut->resize(nContacts);
- hostContacts.resize(nContacts);
- //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
- contactOut->copyFromHost(hostContacts);
- }
- }
- //re-use?
- }
- else
- {
- B3_PROFILE("clipHullHullConcaveConvexKernel");
- nContacts = m_totalContactsOut.at(0);
- int newContactCapacity = contactOut->capacity();
-
- //printf("contactOut5 = %d\n",nContacts);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(triangleConvexPairsOut.getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(m_concaveSepNormals.getBufferCL()),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_clipHullHullConcaveConvexKernel, "m_clipHullHullConcaveConvexKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(newContactCapacity);
- launcher.setConst(numConcavePairs);
- int num = numConcavePairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
- //printf("contactOut6 = %d\n",nContacts);
- b3AlignedObjectArray<b3Contact4> cpuContacts;
- contactOut->copyToHost(cpuContacts);
- }
- // printf("nContacts after = %d\n", nContacts);
- } //numConcavePairs
-
- //convex-convex contact clipping
-
- bool breakupKernel = false;
-
-#ifdef __APPLE__
- breakupKernel = true;
-#endif
-
-#ifdef CHECK_ON_HOST
- bool computeConvexConvex = false;
-#else
- bool computeConvexConvex = true;
-#endif //CHECK_ON_HOST
- if (computeConvexConvex)
- {
- B3_PROFILE("clipHullHullKernel");
- if (breakupKernel)
- {
- worldVertsB1GPU.resize(vertexFaceCapacity * nPairs);
- clippingFacesOutGPU.resize(nPairs);
- worldNormalsAGPU.resize(nPairs);
- worldVertsA1GPU.resize(vertexFaceCapacity * nPairs);
- worldVertsB2GPU.resize(vertexFaceCapacity * nPairs);
-
- if (findConvexClippingFacesGPU)
- {
- B3_PROFILE("findClippingFacesKernel");
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_findClippingFacesKernel, "m_findClippingFacesKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(nPairs);
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
- else
- {
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> hostConvexData;
- convexData.copyToHost(hostConvexData);
- b3AlignedObjectArray<b3Collidable> hostCollidables;
- gpuCollidables.copyToHost(hostCollidables);
-
- b3AlignedObjectArray<int> hostHasSepNormals;
- m_hasSeparatingNormals.copyToHost(hostHasSepNormals);
- b3AlignedObjectArray<b3Vector3> cpuSepNormals;
- m_sepNormals.copyToHost(cpuSepNormals);
-
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
-
- //worldVertsB1GPU.resize(vertexFaceCapacity*nPairs);
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- worldVertsB1GPU.copyToHost(worldVertsB1CPU);
-
- b3AlignedObjectArray<b3Int4> clippingFacesOutCPU;
- clippingFacesOutGPU.copyToHost(clippingFacesOutCPU);
-
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- worldNormalsACPU.resize(nPairs);
-
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- worldVertsA1CPU.resize(worldVertsA1GPU.size());
-
- b3AlignedObjectArray<b3Vector3> hostVertices;
- gpuVertices.copyToHost(hostVertices);
- b3AlignedObjectArray<b3GpuFace> hostFaces;
- gpuFaces.copyToHost(hostFaces);
- b3AlignedObjectArray<int> hostIndices;
- gpuIndices.copyToHost(hostIndices);
-
- for (int i = 0; i < nPairs; i++)
- {
- int bodyIndexA = hostPairs[i].x;
- int bodyIndexB = hostPairs[i].y;
-
- int collidableIndexA = hostBodyBuf[bodyIndexA].m_collidableIdx;
- int collidableIndexB = hostBodyBuf[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = hostCollidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = hostCollidables[collidableIndexB].m_shapeIndex;
-
- if (hostHasSepNormals[i])
- {
- b3FindClippingFaces(cpuSepNormals[i],
- &hostConvexData[shapeIndexA],
- &hostConvexData[shapeIndexB],
- hostBodyBuf[bodyIndexA].m_pos, hostBodyBuf[bodyIndexA].m_quat,
- hostBodyBuf[bodyIndexB].m_pos, hostBodyBuf[bodyIndexB].m_quat,
- &worldVertsA1CPU.at(0), &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- vertexFaceCapacity, minDist, maxDist,
- &hostVertices.at(0), &hostFaces.at(0),
- &hostIndices.at(0),
- &hostVertices.at(0), &hostFaces.at(0),
- &hostIndices.at(0), &clippingFacesOutCPU.at(0), i);
- }
- }
-
- clippingFacesOutGPU.copyFromHost(clippingFacesOutCPU);
- worldVertsA1GPU.copyFromHost(worldVertsA1CPU);
- worldNormalsAGPU.copyFromHost(worldNormalsACPU);
- worldVertsB1GPU.copyFromHost(worldVertsB1CPU);
- }
-
- ///clip face B against face A, reduce contacts and append them to a global contact array
- if (1)
- {
- if (clipConvexFacesAndFindContactsCPU)
- {
- //b3AlignedObjectArray<b3Int4> hostPairs;
- //pairs->copyToHost(hostPairs);
-
- b3AlignedObjectArray<b3Vector3> hostSepNormals;
- m_sepNormals.copyToHost(hostSepNormals);
- b3AlignedObjectArray<int> hostHasSepAxis;
- m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
-
- b3AlignedObjectArray<b3Int4> hostClippingFaces;
- clippingFacesOutGPU.copyToHost(hostClippingFaces);
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
- worldVertsB2CPU.resize(vertexFaceCapacity * nPairs);
-
- b3AlignedObjectArray<b3Vector3> worldVertsA1CPU;
- worldVertsA1GPU.copyToHost(worldVertsA1CPU);
- b3AlignedObjectArray<b3Vector3> worldNormalsACPU;
- worldNormalsAGPU.copyToHost(worldNormalsACPU);
-
- b3AlignedObjectArray<b3Vector3> worldVertsB1CPU;
- worldVertsB1GPU.copyToHost(worldVertsB1CPU);
-
- /*
- __global const b3Float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global b3Int4* clippingFacesOut,
- __global b3Float4* worldVertsA1,
- __global b3Float4* worldNormalsA1,
- __global b3Float4* worldVertsB1,
- __global b3Float4* worldVertsB2,
- int vertexFaceCapacity,
- int pairIndex
- */
- for (int i = 0; i < nPairs; i++)
- {
- clipFacesAndFindContactsKernel(
- &hostSepNormals.at(0),
- &hostHasSepAxis.at(0),
- &hostClippingFaces.at(0),
- &worldVertsA1CPU.at(0),
- &worldNormalsACPU.at(0),
- &worldVertsB1CPU.at(0),
- &worldVertsB2CPU.at(0),
-
- vertexFaceCapacity,
- i);
- }
-
- clippingFacesOutGPU.copyFromHost(hostClippingFaces);
- worldVertsB2GPU.copyFromHost(worldVertsB2CPU);
- }
- else
- {
- B3_PROFILE("clipFacesAndFindContacts");
- //nContacts = m_totalContactsOut.at(0);
- //int h = m_hasSeparatingNormals.at(0);
- //int4 p = clippingFacesOutGPU.at(0);
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsA1GPU.getBufferCL()),
- b3BufferInfoCL(worldNormalsAGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB1GPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB2GPU.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_clipFacesAndFindContacts, "m_clipFacesAndFindContacts");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
-
- launcher.setConst(nPairs);
- int debugMode = 0;
- launcher.setConst(debugMode);
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
- }
-
- {
- nContacts = m_totalContactsOut.at(0);
- //printf("nContacts = %d\n",nContacts);
-
- int newContactCapacity = nContacts + nPairs;
- contactOut->reserve(newContactCapacity);
-
- if (reduceConvexContactsOnGPU)
- {
- {
- B3_PROFILE("newContactReductionKernel");
- b3BufferInfoCL bInfo[] =
- {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(clippingFacesOutGPU.getBufferCL()),
- b3BufferInfoCL(worldVertsB2GPU.getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_newContactReductionKernel, "m_newContactReductionKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(vertexFaceCapacity);
- launcher.setConst(newContactCapacity);
- launcher.setConst(nPairs);
- int num = nPairs;
-
- launcher.launch1D(num);
- }
- nContacts = m_totalContactsOut.at(0);
- contactOut->resize(nContacts);
- }
- else
- {
- volatile int nGlobalContactsOut = nContacts;
- b3AlignedObjectArray<b3Int4> hostPairs;
- pairs->copyToHost(hostPairs);
- b3AlignedObjectArray<b3RigidBodyData> hostBodyBuf;
- bodyBuf->copyToHost(hostBodyBuf);
- b3AlignedObjectArray<b3Vector3> hostSepNormals;
- m_sepNormals.copyToHost(hostSepNormals);
- b3AlignedObjectArray<int> hostHasSepAxis;
- m_hasSeparatingNormals.copyToHost(hostHasSepAxis);
- b3AlignedObjectArray<b3Contact4> hostContactsOut;
- contactOut->copyToHost(hostContactsOut);
- hostContactsOut.resize(newContactCapacity);
-
- b3AlignedObjectArray<b3Int4> hostClippingFaces;
- clippingFacesOutGPU.copyToHost(hostClippingFaces);
- b3AlignedObjectArray<b3Vector3> worldVertsB2CPU;
- worldVertsB2GPU.copyToHost(worldVertsB2CPU);
-
- for (int i = 0; i < nPairs; i++)
- {
- b3NewContactReductionKernel(&hostPairs.at(0),
- &hostBodyBuf.at(0),
- &hostSepNormals.at(0),
- &hostHasSepAxis.at(0),
- &hostContactsOut.at(0),
- &hostClippingFaces.at(0),
- &worldVertsB2CPU.at(0),
- &nGlobalContactsOut,
- vertexFaceCapacity,
- newContactCapacity,
- nPairs,
- i);
- }
-
- nContacts = nGlobalContactsOut;
- m_totalContactsOut.copyFromHostPointer(&nContacts, 1, 0, true);
- hostContactsOut.resize(nContacts);
- //printf("contactOut4 (after newContactReductionKernel) = %d\n",nContacts);
- contactOut->copyFromHost(hostContactsOut);
- }
- // b3Contact4 pt = contactOut->at(0);
- // printf("nContacts = %d\n",nContacts);
- }
- }
- }
- else //breakupKernel
- {
- if (nPairs)
- {
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(pairs->getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(m_sepNormals.getBufferCL()),
- b3BufferInfoCL(m_hasSeparatingNormals.getBufferCL()),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_clipHullHullKernel, "m_clipHullHullKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nPairs);
- launcher.setConst(maxContactCapacity);
-
- int num = nPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
-
- nContacts = m_totalContactsOut.at(0);
- if (nContacts >= maxContactCapacity)
- {
- b3Error("Exceeded contact capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- contactOut->resize(nContacts);
- }
- }
-
- int nCompoundsPairs = m_gpuCompoundPairs.size();
-
- if (nCompoundsPairs)
- {
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_gpuCompoundPairs.getBufferCL(), true),
- b3BufferInfoCL(bodyBuf->getBufferCL(), true),
- b3BufferInfoCL(gpuCollidables.getBufferCL(), true),
- b3BufferInfoCL(convexData.getBufferCL(), true),
- b3BufferInfoCL(gpuVertices.getBufferCL(), true),
- b3BufferInfoCL(gpuUniqueEdges.getBufferCL(), true),
- b3BufferInfoCL(gpuFaces.getBufferCL(), true),
- b3BufferInfoCL(gpuIndices.getBufferCL(), true),
- b3BufferInfoCL(gpuChildShapes.getBufferCL(), true),
- b3BufferInfoCL(m_gpuCompoundSepNormals.getBufferCL(), true),
- b3BufferInfoCL(m_gpuHasCompoundSepNormals.getBufferCL(), true),
- b3BufferInfoCL(contactOut->getBufferCL()),
- b3BufferInfoCL(m_totalContactsOut.getBufferCL())};
- b3LauncherCL launcher(m_queue, m_clipCompoundsHullHullKernel, "m_clipCompoundsHullHullKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nCompoundsPairs);
- launcher.setConst(maxContactCapacity);
-
- int num = nCompoundsPairs;
- launcher.launch1D(num);
- clFinish(m_queue);
-
- nContacts = m_totalContactsOut.at(0);
- if (nContacts > maxContactCapacity)
- {
- b3Error("Error: contacts exceeds capacity (%d/%d)\n", nContacts, maxContactCapacity);
- nContacts = maxContactCapacity;
- }
- contactOut->resize(nContacts);
- } //if nCompoundsPairs
- }
- } //contactClippingOnGpu
-
- //printf("nContacts end = %d\n",nContacts);
-
- //printf("frameCount = %d\n",frameCount++);
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
deleted file mode 100644
index 53e8c4ed4d..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h
+++ /dev/null
@@ -1,106 +0,0 @@
-
-#ifndef _CONVEX_HULL_CONTACT_H
-#define _CONVEX_HULL_CONTACT_H
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#include "b3OptimizedBvh.h"
-#include "b3BvhInfo.h"
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-
-//#include "../../dynamics/basic_demo/Stubs/ChNarrowPhase.h"
-
-struct GpuSatCollision
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
- cl_kernel m_findSeparatingAxisKernel;
- cl_kernel m_mprPenetrationKernel;
- cl_kernel m_findSeparatingAxisUnitSphereKernel;
-
- cl_kernel m_findSeparatingAxisVertexFaceKernel;
- cl_kernel m_findSeparatingAxisEdgeEdgeKernel;
-
- cl_kernel m_findConcaveSeparatingAxisKernel;
- cl_kernel m_findConcaveSeparatingAxisVertexFaceKernel;
- cl_kernel m_findConcaveSeparatingAxisEdgeEdgeKernel;
-
- cl_kernel m_findCompoundPairsKernel;
- cl_kernel m_processCompoundPairsKernel;
-
- cl_kernel m_clipHullHullKernel;
- cl_kernel m_clipCompoundsHullHullKernel;
-
- cl_kernel m_clipFacesAndFindContacts;
- cl_kernel m_findClippingFacesKernel;
-
- cl_kernel m_clipHullHullConcaveConvexKernel;
- // cl_kernel m_extractManifoldAndAddContactKernel;
- cl_kernel m_newContactReductionKernel;
-
- cl_kernel m_bvhTraversalKernel;
- cl_kernel m_primitiveContactsKernel;
- cl_kernel m_findConcaveSphereContactsKernel;
-
- cl_kernel m_processCompoundPairsPrimitivesKernel;
-
- b3OpenCLArray<b3Vector3> m_unitSphereDirections;
-
- b3OpenCLArray<int> m_totalContactsOut;
-
- b3OpenCLArray<b3Vector3> m_sepNormals;
- b3OpenCLArray<float> m_dmins;
-
- b3OpenCLArray<int> m_hasSeparatingNormals;
- b3OpenCLArray<b3Vector3> m_concaveSepNormals;
- b3OpenCLArray<int> m_concaveHasSeparatingNormals;
- b3OpenCLArray<int> m_numConcavePairsOut;
- b3OpenCLArray<b3CompoundOverlappingPair> m_gpuCompoundPairs;
- b3OpenCLArray<b3Vector3> m_gpuCompoundSepNormals;
- b3OpenCLArray<int> m_gpuHasCompoundSepNormals;
- b3OpenCLArray<int> m_numCompoundPairsOut;
-
- GpuSatCollision(cl_context ctx, cl_device_id device, cl_command_queue q);
- virtual ~GpuSatCollision();
-
- void computeConvexConvexContactsGPUSAT(b3OpenCLArray<b3Int4>* pairs, int nPairs,
- const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- b3OpenCLArray<b3Contact4>* contactOut, int& nContacts,
- const b3OpenCLArray<b3Contact4>* oldContacts,
- int maxContactCapacity,
- int compoundPairCapacity,
- const b3OpenCLArray<b3ConvexPolyhedronData>& hostConvexData,
- const b3OpenCLArray<b3Vector3>& vertices,
- const b3OpenCLArray<b3Vector3>& uniqueEdges,
- const b3OpenCLArray<b3GpuFace>& faces,
- const b3OpenCLArray<int>& indices,
- const b3OpenCLArray<b3Collidable>& gpuCollidables,
- const b3OpenCLArray<b3GpuChildShape>& gpuChildShapes,
-
- const b3OpenCLArray<b3Aabb>& clAabbsWorldSpace,
- const b3OpenCLArray<b3Aabb>& clAabbsLocalSpace,
-
- b3OpenCLArray<b3Vector3>& worldVertsB1GPU,
- b3OpenCLArray<b3Int4>& clippingFacesOutGPU,
- b3OpenCLArray<b3Vector3>& worldNormalsAGPU,
- b3OpenCLArray<b3Vector3>& worldVertsA1GPU,
- b3OpenCLArray<b3Vector3>& worldVertsB2GPU,
- b3AlignedObjectArray<class b3OptimizedBvh*>& bvhData,
- b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU,
- b3OpenCLArray<b3BvhSubtreeInfo>* subTreesGPU,
- b3OpenCLArray<b3BvhInfo>* bvhInfo,
- int numObjects,
- int maxTriConvexPairCapacity,
- b3OpenCLArray<b3Int4>& triangleConvexPairs,
- int& numTriConvexPairsOut);
-};
-
-#endif //_CONVEX_HULL_CONTACT_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
deleted file mode 100644
index c4cf700076..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3ConvexPolyhedronCL.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef CONVEX_POLYHEDRON_CL
-#define CONVEX_POLYHEDRON_CL
-
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-#endif //CONVEX_POLYHEDRON_CL
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
deleted file mode 100644
index 974b246f03..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.cpp
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the
-use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software in a
-product, an acknowledgment in the product documentation would be appreciated
-but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-GJK-EPA collision solver by Nathanael Presson, 2008
-*/
-
-#include "b3GjkEpa.h"
-
-#include "b3SupportMappings.h"
-
-namespace gjkepa2_impl2
-{
-// Config
-
-/* GJK */
-#define GJK_MAX_ITERATIONS 128
-#define GJK_ACCURACY ((b3Scalar)0.0001)
-#define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
-#define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
-#define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
-#define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
-#define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
-
-/* EPA */
-#define EPA_MAX_VERTICES 64
-#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
-#define EPA_MAX_ITERATIONS 255
-#define EPA_ACCURACY ((b3Scalar)0.0001)
-#define EPA_FALLBACK (10 * EPA_ACCURACY)
-#define EPA_PLANE_EPS ((b3Scalar)0.00001)
-#define EPA_INSIDE_EPS ((b3Scalar)0.01)
-
-// Shorthands
-
-// MinkowskiDiff
-struct b3MinkowskiDiff
-{
- const b3ConvexPolyhedronData* m_shapes[2];
-
- b3Matrix3x3 m_toshape1;
- b3Transform m_toshape0;
-
- bool m_enableMargin;
-
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
- {
- if (m_enableMargin)
- {
- return localGetSupportVertexWithMargin(d, m_shapes[0], verticesA, 0.f);
- }
- else
- {
- return localGetSupportVertexWithoutMargin(d, m_shapes[0], verticesA);
- }
- }
- inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
- {
- if (m_enableMargin)
- {
- return m_toshape0 * (localGetSupportVertexWithMargin(m_toshape1 * d, m_shapes[1], verticesB, 0.f));
- }
- else
- {
- return m_toshape0 * (localGetSupportVertexWithoutMargin(m_toshape1 * d, m_shapes[1], verticesB));
- }
- }
-
- inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
- {
- return (Support0(d, verticesA) - Support1(-d, verticesB));
- }
- b3Vector3 Support(const b3Vector3& d, unsigned int index, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
- {
- if (index)
- return (Support1(d, verticesA));
- else
- return (Support0(d, verticesB));
- }
-};
-
-typedef b3MinkowskiDiff tShape;
-
-// GJK
-struct b3GJK
-{
- /* Types */
- struct sSV
- {
- b3Vector3 d, w;
- };
- struct sSimplex
- {
- sSV* c[4];
- b3Scalar p[4];
- unsigned int rank;
- };
- struct eStatus
- {
- enum _
- {
- Valid,
- Inside,
- Failed
- };
- };
- /* Fields */
- tShape m_shape;
- const b3AlignedObjectArray<b3Vector3>& m_verticesA;
- const b3AlignedObjectArray<b3Vector3>& m_verticesB;
- b3Vector3 m_ray;
- b3Scalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- unsigned int m_nfree;
- unsigned int m_current;
- sSimplex* m_simplex;
- eStatus::_ m_status;
- /* Methods */
- b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB)
- : m_verticesA(verticesA), m_verticesB(verticesB)
- {
- Initialize();
- }
- void Initialize()
- {
- m_ray = b3MakeVector3(0, 0, 0);
- m_nfree = 0;
- m_status = eStatus::Failed;
- m_current = 0;
- m_distance = 0;
- }
- eStatus::_ Evaluate(const tShape& shapearg, const b3Vector3& guess)
- {
- unsigned int iterations = 0;
- b3Scalar sqdist = 0;
- b3Scalar alpha = 0;
- b3Vector3 lastw[4];
- unsigned int clastw = 0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eStatus::Valid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const b3Scalar sqrl = m_ray.length2();
- appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : b3MakeVector3(1, 0, 0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do
- {
- const unsigned int next = 1 - m_current;
- sSimplex& cs = m_simplices[m_current];
- sSimplex& ns = m_simplices[next];
- /* Check zero */
- const b3Scalar rl = m_ray.length();
- if (rl < GJK_MIN_DISTANCE)
- { /* Touching or inside */
- m_status = eStatus::Inside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs, -m_ray);
- const b3Vector3& w = cs.c[cs.rank - 1]->w;
- bool found = false;
- for (unsigned int i = 0; i < 4; ++i)
- {
- if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
- {
- found = true;
- break;
- }
- }
- if (found)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- else
- { /* Update lastw */
- lastw[clastw = (clastw + 1) & 3] = w;
- }
- /* Check for termination */
- const b3Scalar omega = b3Dot(m_ray, w) / rl;
- alpha = b3Max(omega, alpha);
- if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- b3Scalar weights[4];
- unsigned int mask = 0;
- switch (cs.rank)
- {
- case 2:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- weights, mask);
- break;
- case 3:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights, mask);
- break;
- case 4:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights, mask);
- break;
- }
- if (sqdist >= 0)
- { /* Valid */
- ns.rank = 0;
- m_ray = b3MakeVector3(0, 0, 0);
- m_current = next;
- for (unsigned int i = 0, ni = cs.rank; i < ni; ++i)
- {
- if (mask & (1 << i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w * weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if (mask == 15) m_status = eStatus::Inside;
- }
- else
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
- } while (m_status == eStatus::Valid);
- m_simplex = &m_simplices[m_current];
- switch (m_status)
- {
- case eStatus::Valid:
- m_distance = m_ray.length();
- break;
- case eStatus::Inside:
- m_distance = 0;
- break;
- default:
- {
- }
- }
- return (m_status);
- }
- bool EncloseOrigin()
- {
- switch (m_simplex->rank)
- {
- case 1:
- {
- for (unsigned int i = 0; i < 3; ++i)
- {
- b3Vector3 axis = b3MakeVector3(0, 0, 0);
- axis[i] = 1;
- appendvertice(*m_simplex, axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 2:
- {
- const b3Vector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
- for (unsigned int i = 0; i < 3; ++i)
- {
- b3Vector3 axis = b3MakeVector3(0, 0, 0);
- axis[i] = 1;
- const b3Vector3 p = b3Cross(d, axis);
- if (p.length2() > 0)
- {
- appendvertice(*m_simplex, p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const b3Vector3 n = b3Cross(m_simplex->c[1]->w - m_simplex->c[0]->w,
- m_simplex->c[2]->w - m_simplex->c[0]->w);
- if (n.length2() > 0)
- {
- appendvertice(*m_simplex, n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
- {
- if (b3Fabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
- m_simplex->c[1]->w - m_simplex->c[3]->w,
- m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
- return (true);
- }
- break;
- }
- return (false);
- }
- /* Internals */
- void getsupport(const b3Vector3& d, sSV& sv) const
- {
- sv.d = d / d.length();
- sv.w = m_shape.Support(sv.d, m_verticesA, m_verticesB);
- }
- void removevertice(sSimplex& simplex)
- {
- m_free[m_nfree++] = simplex.c[--simplex.rank];
- }
- void appendvertice(sSimplex& simplex, const b3Vector3& v)
- {
- simplex.p[simplex.rank] = 0;
- simplex.c[simplex.rank] = m_free[--m_nfree];
- getsupport(v, *simplex.c[simplex.rank++]);
- }
- static b3Scalar det(const b3Vector3& a, const b3Vector3& b, const b3Vector3& c)
- {
- return (a.y * b.z * c.x + a.z * b.x * c.y -
- a.x * b.z * c.y - a.y * b.x * c.z +
- a.x * b.y * c.z - a.z * b.y * c.x);
- }
- static b3Scalar projectorigin(const b3Vector3& a,
- const b3Vector3& b,
- b3Scalar* w, unsigned int& m)
- {
- const b3Vector3 d = b - a;
- const b3Scalar l = d.length2();
- if (l > GJK_SIMPLEX2_EPS)
- {
- const b3Scalar t(l > 0 ? -b3Dot(a, d) / l : 0);
- if (t >= 1)
- {
- w[0] = 0;
- w[1] = 1;
- m = 2;
- return (b.length2());
- }
- else if (t <= 0)
- {
- w[0] = 1;
- w[1] = 0;
- m = 1;
- return (a.length2());
- }
- else
- {
- w[0] = 1 - (w[1] = t);
- m = 3;
- return ((a + d * t).length2());
- }
- }
- return (-1);
- }
- static b3Scalar projectorigin(const b3Vector3& a,
- const b3Vector3& b,
- const b3Vector3& c,
- b3Scalar* w, unsigned int& m)
- {
- static const unsigned int imd3[] = {1, 2, 0};
- const b3Vector3* vt[] = {&a, &b, &c};
- const b3Vector3 dl[] = {a - b, b - c, c - a};
- const b3Vector3 n = b3Cross(dl[0], dl[1]);
- const b3Scalar l = n.length2();
- if (l > GJK_SIMPLEX3_EPS)
- {
- b3Scalar mindist = -1;
- b3Scalar subw[2] = {0.f, 0.f};
- unsigned int subm(0);
- for (unsigned int i = 0; i < 3; ++i)
- {
- if (b3Dot(*vt[i], b3Cross(dl[i], n)) > 0)
- {
- const unsigned int j = imd3[i];
- const b3Scalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<unsigned int>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
- }
- if (mindist < 0)
- {
- const b3Scalar d = b3Dot(a, n);
- const b3Scalar s = b3Sqrt(l);
- const b3Vector3 p = n * (d / l);
- mindist = p.length2();
- m = 7;
- w[0] = (b3Cross(dl[1], b - p)).length() / s;
- w[1] = (b3Cross(dl[2], c - p)).length() / s;
- w[2] = 1 - (w[0] + w[1]);
- }
- return (mindist);
- }
- return (-1);
- }
- static b3Scalar projectorigin(const b3Vector3& a,
- const b3Vector3& b,
- const b3Vector3& c,
- const b3Vector3& d,
- b3Scalar* w, unsigned int& m)
- {
- static const unsigned int imd3[] = {1, 2, 0};
- const b3Vector3* vt[] = {&a, &b, &c, &d};
- const b3Vector3 dl[] = {a - d, b - d, c - d};
- const b3Scalar vl = det(dl[0], dl[1], dl[2]);
- const bool ng = (vl * b3Dot(a, b3Cross(b - c, a - b))) <= 0;
- if (ng && (b3Fabs(vl) > GJK_SIMPLEX4_EPS))
- {
- b3Scalar mindist = -1;
- b3Scalar subw[3] = {0.f, 0.f, 0.f};
- unsigned int subm(0);
- for (unsigned int i = 0; i < 3; ++i)
- {
- const unsigned int j = imd3[i];
- const b3Scalar s = vl * b3Dot(d, b3Cross(dl[i], dl[j]));
- if (s > 0)
- {
- const b3Scalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<unsigned int>((subm & 1 ? 1 << i : 0) +
- (subm & 2 ? 1 << j : 0) +
- (subm & 4 ? 8 : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
- }
- if (mindist < 0)
- {
- mindist = 0;
- m = 15;
- w[0] = det(c, b, d) / vl;
- w[1] = det(a, c, d) / vl;
- w[2] = det(b, a, d) / vl;
- w[3] = 1 - (w[0] + w[1] + w[2]);
- }
- return (mindist);
- }
- return (-1);
- }
-};
-
-// EPA
-struct b3EPA
-{
- /* Types */
- typedef b3GJK::sSV sSV;
- struct sFace
- {
- b3Vector3 n;
- b3Scalar d;
- sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- unsigned char e[3];
- unsigned char pass;
- };
- struct sList
- {
- sFace* root;
- unsigned int count;
- sList() : root(0), count(0) {}
- };
- struct sHorizon
- {
- sFace* cf;
- sFace* ff;
- unsigned int nf;
- sHorizon() : cf(0), ff(0), nf(0) {}
- };
- struct eStatus
- {
- enum _
- {
- Valid,
- Touching,
- Degenerated,
- NonConvex,
- InvalidHull,
- OutOfFaces,
- OutOfVertices,
- AccuraryReached,
- FallBack,
- Failed
- };
- };
- /* Fields */
- eStatus::_ m_status;
- b3GJK::sSimplex m_result;
- b3Vector3 m_normal;
- b3Scalar m_depth;
- sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- unsigned int m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- b3EPA()
- {
- Initialize();
- }
-
- static inline void bind(sFace* fa, unsigned int ea, sFace* fb, unsigned int eb)
- {
- fa->e[ea] = (unsigned char)eb;
- fa->f[ea] = fb;
- fb->e[eb] = (unsigned char)ea;
- fb->f[eb] = fa;
- }
- static inline void append(sList& list, sFace* face)
- {
- face->l[0] = 0;
- face->l[1] = list.root;
- if (list.root) list.root->l[0] = face;
- list.root = face;
- ++list.count;
- }
- static inline void remove(sList& list, sFace* face)
- {
- if (face->l[1]) face->l[1]->l[0] = face->l[0];
- if (face->l[0]) face->l[0]->l[1] = face->l[1];
- if (face == list.root) list.root = face->l[1];
- --list.count;
- }
-
- void Initialize()
- {
- m_status = eStatus::Failed;
- m_normal = b3MakeVector3(0, 0, 0);
- m_depth = 0;
- m_nextsv = 0;
- for (unsigned int i = 0; i < EPA_MAX_FACES; ++i)
- {
- append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
- }
- }
- eStatus::_ Evaluate(b3GJK& gjk, const b3Vector3& guess)
- {
- b3GJK::sSimplex& simplex = *gjk.m_simplex;
- if ((simplex.rank > 1) && gjk.EncloseOrigin())
- {
- /* Clean up */
- while (m_hull.root)
- {
- sFace* f = m_hull.root;
- remove(m_hull, f);
- append(m_stock, f);
- }
- m_status = eStatus::Valid;
- m_nextsv = 0;
- /* Orient simplex */
- if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
- simplex.c[1]->w - simplex.c[3]->w,
- simplex.c[2]->w - simplex.c[3]->w) < 0)
- {
- b3Swap(simplex.c[0], simplex.c[1]);
- b3Swap(simplex.p[0], simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
- newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
- newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
- newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
- if (m_hull.count == 4)
- {
- sFace* best = findbest();
- sFace outer = *best;
- unsigned int pass = 0;
- unsigned int iterations = 0;
- bind(tetra[0], 0, tetra[1], 0);
- bind(tetra[0], 1, tetra[2], 0);
- bind(tetra[0], 2, tetra[3], 0);
- bind(tetra[1], 1, tetra[3], 2);
- bind(tetra[1], 2, tetra[2], 1);
- bind(tetra[2], 2, tetra[3], 1);
- m_status = eStatus::Valid;
- for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
- {
- if (m_nextsv < EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- sSV* w = &m_sv_store[m_nextsv++];
- bool valid = true;
- best->pass = (unsigned char)(++pass);
- gjk.getsupport(best->n, *w);
- const b3Scalar wdist = b3Dot(best->n, w->w) - best->d;
- if (wdist > EPA_ACCURACY)
- {
- for (unsigned int j = 0; (j < 3) && valid; ++j)
- {
- valid &= expand(pass, w,
- best->f[j], best->e[j],
- horizon);
- }
- if (valid && (horizon.nf >= 3))
- {
- bind(horizon.cf, 1, horizon.ff, 2);
- remove(m_hull, best);
- append(m_stock, best);
- best = findbest();
- outer = *best;
- }
- else
- {
- m_status = eStatus::Failed;
- //m_status=eStatus::InvalidHull;
- break;
- }
- }
- else
- {
- m_status = eStatus::AccuraryReached;
- break;
- }
- }
- else
- {
- m_status = eStatus::OutOfVertices;
- break;
- }
- }
- const b3Vector3 projection = outer.n * outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = b3Cross(outer.c[1]->w - projection,
- outer.c[2]->w - projection)
- .length();
- m_result.p[1] = b3Cross(outer.c[2]->w - projection,
- outer.c[0]->w - projection)
- .length();
- m_result.p[2] = b3Cross(outer.c[0]->w - projection,
- outer.c[1]->w - projection)
- .length();
- const b3Scalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return (m_status);
- }
- }
- /* Fallback */
- m_status = eStatus::FallBack;
- m_normal = -guess;
- const b3Scalar nl = m_normal.length();
- if (nl > 0)
- m_normal = m_normal / nl;
- else
- m_normal = b3MakeVector3(1, 0, 0);
- m_depth = 0;
- m_result.rank = 1;
- m_result.c[0] = simplex.c[0];
- m_result.p[0] = 1;
- return (m_status);
- }
- bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
- {
- const b3Vector3 ba = b->w - a->w;
- const b3Vector3 n_ab = b3Cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const b3Scalar a_dot_nab = b3Dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if (a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const b3Scalar ba_l2 = ba.length2();
- const b3Scalar a_dot_ba = b3Dot(a->w, ba);
- const b3Scalar b_dot_ba = b3Dot(b->w, ba);
-
- if (a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if (b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
- }
- else
- {
- // Pick distance to edge a->b
- const b3Scalar a_dot_b = b3Dot(a->w, b->w);
- dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
- }
-
- return true;
- }
-
- return false;
- }
- sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
- {
- if (m_stock.root)
- {
- sFace* face = m_stock.root;
- remove(m_stock, face);
- append(m_hull, face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = b3Cross(b->w - a->w, c->w - a->w);
- const b3Scalar l = face->n.length();
- const bool v = l > EPA_ACCURACY;
-
- if (v)
- {
- if (!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = b3Dot(a->w, face->n) / l;
- }
-
- face->n /= l;
- if (forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status = eStatus::NonConvex;
- }
- else
- m_status = eStatus::Degenerated;
-
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
- }
- m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
- return 0;
- }
- sFace* findbest()
- {
- sFace* minf = m_hull.root;
- b3Scalar mind = minf->d * minf->d;
- for (sFace* f = minf->l[1]; f; f = f->l[1])
- {
- const b3Scalar sqd = f->d * f->d;
- if (sqd < mind)
- {
- minf = f;
- mind = sqd;
- }
- }
- return (minf);
- }
- bool expand(unsigned int pass, sSV* w, sFace* f, unsigned int e, sHorizon& horizon)
- {
- static const unsigned int i1m3[] = {1, 2, 0};
- static const unsigned int i2m3[] = {2, 0, 1};
- if (f->pass != pass)
- {
- const unsigned int e1 = i1m3[e];
- if ((b3Dot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
- {
- sFace* nf = newface(f->c[e1], f->c[e], w, false);
- if (nf)
- {
- bind(nf, 0, f, e);
- if (horizon.cf)
- bind(horizon.cf, 1, nf, 2);
- else
- horizon.ff = nf;
- horizon.cf = nf;
- ++horizon.nf;
- return (true);
- }
- }
- else
- {
- const unsigned int e2 = i2m3[e];
- f->pass = (unsigned char)pass;
- if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
- expand(pass, w, f->f[e2], f->e[e2], horizon))
- {
- remove(m_hull, f);
- append(m_stock, f);
- return (true);
- }
- }
- }
- return (false);
- }
-};
-
-//
-static void Initialize(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- b3GjkEpaSolver2::sResults& results,
- tShape& shape,
- bool withmargins)
-{
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = b3MakeVector3(0, 0, 0);
- results.status = b3GjkEpaSolver2::sResults::Separated;
- /* Shape */
- shape.m_shapes[0] = hullA;
- shape.m_shapes[1] = hullB;
- shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
- shape.m_toshape0 = transA.inverseTimes(transB);
- shape.EnableMargin(withmargins);
-}
-
-} // namespace gjkepa2_impl2
-
-//
-// Api
-//
-
-using namespace gjkepa2_impl2;
-
-//
-int b3GjkEpaSolver2::StackSizeRequirement()
-{
- return (sizeof(b3GJK) + sizeof(b3EPA));
-}
-
-//
-bool b3GjkEpaSolver2::Distance(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results)
-{
- tShape shape;
- Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, false);
- b3GJK gjk(verticesA, verticesB);
- b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
- if (gjk_status == b3GJK::eStatus::Valid)
- {
- b3Vector3 w0 = b3MakeVector3(0, 0, 0);
- b3Vector3 w1 = b3MakeVector3(0, 0, 0);
- for (unsigned int i = 0; i < gjk.m_simplex->rank; ++i)
- {
- const b3Scalar p = gjk.m_simplex->p[i];
- w0 += shape.Support(gjk.m_simplex->c[i]->d, 0, verticesA, verticesB) * p;
- w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1, verticesA, verticesB) * p;
- }
- results.witnesses[0] = transA * w0;
- results.witnesses[1] = transA * w1;
- results.normal = w0 - w1;
- results.distance = results.normal.length();
- results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
- return (true);
- }
- else
- {
- results.status = gjk_status == b3GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
- return (false);
- }
-}
-
-//
-bool b3GjkEpaSolver2::Penetration(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results,
- bool usemargins)
-{
- tShape shape;
- Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, usemargins);
- b3GJK gjk(verticesA, verticesB);
- b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
- switch (gjk_status)
- {
- case b3GJK::eStatus::Inside:
- {
- b3EPA epa;
- b3EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
- if (epa_status != b3EPA::eStatus::Failed)
- {
- b3Vector3 w0 = b3MakeVector3(0, 0, 0);
- for (unsigned int i = 0; i < epa.m_result.rank; ++i)
- {
- w0 += shape.Support(epa.m_result.c[i]->d, 0, verticesA, verticesB) * epa.m_result.p[i];
- }
- results.status = sResults::Penetrating;
- results.witnesses[0] = transA * w0;
- results.witnesses[1] = transA * (w0 - epa.m_normal * epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return (true);
- }
- else
- results.status = sResults::EPA_Failed;
- }
- break;
- case b3GJK::eStatus::Failed:
- results.status = sResults::GJK_Failed;
- break;
- default:
- {
- }
- }
- return (false);
-}
-
-#if 0
-//
-b3Scalar b3GjkEpaSolver2::SignedDistance(const b3Vector3& position,
- b3Scalar margin,
- const b3Transform& transA,
- const b3ConvexPolyhedronData& hullA,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- sResults& results)
-{
- tShape shape;
- btSphereShape shape1(margin);
- b3Transform wtrs1(b3Quaternion(0,0,0,1),position);
- Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
- GJK gjk;
- GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,b3Vector3(1,1,1));
- if(gjk_status==GJK::eStatus::Valid)
- {
- b3Vector3 w0=b3Vector3(0,0,0);
- b3Vector3 w1=b3Vector3(0,0,0);
- for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
- {
- const b3Scalar p=gjk.m_simplex->p[i];
- w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
- w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
- }
- results.witnesses[0] = wtrs0*w0;
- results.witnesses[1] = wtrs0*w1;
- const b3Vector3 delta= results.witnesses[1]-
- results.witnesses[0];
- const b3Scalar margin= shape0->getMarginNonVirtual()+
- shape1.getMarginNonVirtual();
- const b3Scalar length= delta.length();
- results.normal = delta/length;
- results.witnesses[0] += results.normal*margin;
- return(length-margin);
- }
- else
- {
- if(gjk_status==GJK::eStatus::Inside)
- {
- if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
- {
- const b3Vector3 delta= results.witnesses[0]-
- results.witnesses[1];
- const b3Scalar length= delta.length();
- if (length >= B3_EPSILON)
- results.normal = delta/length;
- return(-length);
- }
- }
- }
- return(B3_INFINITY);
-}
-
-//
-bool b3GjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
- const b3Transform& wtrs0,
- const btConvexShape* shape1,
- const b3Transform& wtrs1,
- const b3Vector3& guess,
- sResults& results)
-{
- if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
- return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
- else
- return(true);
-}
-#endif
-
-/* Symbols cleanup */
-
-#undef GJK_MAX_ITERATIONS
-#undef GJK_ACCURACY
-#undef GJK_MIN_DISTANCE
-#undef GJK_DUPLICATED_EPS
-#undef GJK_SIMPLEX2_EPS
-#undef GJK_SIMPLEX3_EPS
-#undef GJK_SIMPLEX4_EPS
-
-#undef EPA_MAX_VERTICES
-#undef EPA_MAX_FACES
-#undef EPA_MAX_ITERATIONS
-#undef EPA_ACCURACY
-#undef EPA_FALLBACK
-#undef EPA_PLANE_EPS
-#undef EPA_INSIDE_EPS
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
deleted file mode 100644
index 7db32c6309..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3GjkEpa.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the
-use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software in a
-product, an acknowledgment in the product documentation would be appreciated
-but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-GJK-EPA collision solver by Nathanael Presson, 2008
-*/
-#ifndef B3_GJK_EPA2_H
-#define B3_GJK_EPA2_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-
-///btGjkEpaSolver contributed under zlib by Nathanael Presson
-struct b3GjkEpaSolver2
-{
- struct sResults
- {
- enum eStatus
- {
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- b3Vector3 witnesses[2];
- b3Vector3 normal;
- b3Scalar distance;
- };
-
- static int StackSizeRequirement();
-
- static bool Distance(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results);
-
- static bool Penetration(const b3Transform& transA, const b3Transform& transB,
- const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
- const b3AlignedObjectArray<b3Vector3>& verticesA,
- const b3AlignedObjectArray<b3Vector3>& verticesB,
- const b3Vector3& guess,
- sResults& results,
- bool usemargins = true);
-#if 0
-static b3Scalar SignedDistance( const b3Vector3& position,
- b3Scalar margin,
- const btConvexShape* shape,
- const btTransform& wtrs,
- sResults& results);
-
-static bool SignedDistance( const btConvexShape* shape0,const btTransform& wtrs0,
- const btConvexShape* shape1,const btTransform& wtrs1,
- const b3Vector3& guess,
- sResults& results);
-#endif
-};
-
-#endif //B3_GJK_EPA2_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
deleted file mode 100644
index 4938fa17af..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3OptimizedBvh.h"
-#include "b3StridingMeshInterface.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-b3OptimizedBvh::b3OptimizedBvh()
-{
-}
-
-b3OptimizedBvh::~b3OptimizedBvh()
-{
-}
-
-void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
-{
- m_useQuantization = useQuantizedAabbCompression;
-
- // NodeArray triangleNodes;
-
- struct NodeTriangleCallback : public b3InternalTriangleIndexCallback
- {
- NodeArray& m_triangleNodes;
-
- NodeTriangleCallback& operator=(NodeTriangleCallback& other)
- {
- m_triangleNodes.copyFromArray(other.m_triangleNodes);
- return *this;
- }
-
- NodeTriangleCallback(NodeArray& triangleNodes)
- : m_triangleNodes(triangleNodes)
- {
- }
-
- virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
- {
- b3OptimizedBvhNode node;
- b3Vector3 aabbMin, aabbMax;
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- //with quantization?
- node.m_aabbMinOrg = aabbMin;
- node.m_aabbMaxOrg = aabbMax;
-
- node.m_escapeIndex = -1;
-
- //for child nodes
- node.m_subPart = partId;
- node.m_triangleIndex = triangleIndex;
- m_triangleNodes.push_back(node);
- }
- };
- struct QuantizedNodeTriangleCallback : public b3InternalTriangleIndexCallback
- {
- QuantizedNodeArray& m_triangleNodes;
- const b3QuantizedBvh* m_optimizedTree; // for quantization
-
- QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
- {
- m_triangleNodes.copyFromArray(other.m_triangleNodes);
- m_optimizedTree = other.m_optimizedTree;
- return *this;
- }
-
- QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const b3QuantizedBvh* tree)
- : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
- {
- }
-
- virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
- {
- // The partId and triangle index must fit in the same (positive) integer
- b3Assert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
- b3Assert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
- //negative indices are reserved for escapeIndex
- b3Assert(triangleIndex >= 0);
-
- b3QuantizedBvhNode node;
- b3Vector3 aabbMin, aabbMax;
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- //PCK: add these checks for zero dimensions of aabb
- const b3Scalar MIN_AABB_DIMENSION = b3Scalar(0.002);
- const b3Scalar MIN_AABB_HALF_DIMENSION = b3Scalar(0.001);
- if (aabbMax.getX() - aabbMin.getX() < MIN_AABB_DIMENSION)
- {
- aabbMax.setX(aabbMax.getX() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setX(aabbMin.getX() - MIN_AABB_HALF_DIMENSION);
- }
- if (aabbMax.getY() - aabbMin.getY() < MIN_AABB_DIMENSION)
- {
- aabbMax.setY(aabbMax.getY() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setY(aabbMin.getY() - MIN_AABB_HALF_DIMENSION);
- }
- if (aabbMax.getZ() - aabbMin.getZ() < MIN_AABB_DIMENSION)
- {
- aabbMax.setZ(aabbMax.getZ() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setZ(aabbMin.getZ() - MIN_AABB_HALF_DIMENSION);
- }
-
- m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
- m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
-
- node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
-
- m_triangleNodes.push_back(node);
- }
- };
-
- int numLeafNodes = 0;
-
- if (m_useQuantization)
- {
- //initialize quantization values
- setQuantizationValues(bvhAabbMin, bvhAabbMax);
-
- QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
-
- triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
-
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2 * numLeafNodes);
- }
- else
- {
- NodeTriangleCallback callback(m_leafNodes);
-
- b3Vector3 aabbMin = b3MakeVector3(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- b3Vector3 aabbMax = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
-
- triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
-
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_leafNodes.size();
-
- m_contiguousNodes.resize(2 * numLeafNodes);
- }
-
- m_curNodeIndex = 0;
-
- buildTree(0, numLeafNodes);
-
- ///if the entire tree is small then subtree size, we need to create a header info for the tree
- if (m_useQuantization && !m_SubtreeHeaders.size())
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
- subtree.m_rootNodeIndex = 0;
- subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
- m_quantizedLeafNodes.clear();
- m_leafNodes.clear();
-}
-
-void b3OptimizedBvh::refit(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
-{
- if (m_useQuantization)
- {
- setQuantizationValues(aabbMin, aabbMax);
-
- updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
-
- ///now update all subtree headers
-
- int i;
- for (i = 0; i < m_SubtreeHeaders.size(); i++)
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
- }
- }
- else
- {
- }
-}
-
-void b3OptimizedBvh::refitPartial(b3StridingMeshInterface* meshInterface, const b3Vector3& aabbMin, const b3Vector3& aabbMax)
-{
- //incrementally initialize quantization values
- b3Assert(m_useQuantization);
-
- b3Assert(aabbMin.getX() > m_bvhAabbMin.getX());
- b3Assert(aabbMin.getY() > m_bvhAabbMin.getY());
- b3Assert(aabbMin.getZ() > m_bvhAabbMin.getZ());
-
- b3Assert(aabbMax.getX() < m_bvhAabbMax.getX());
- b3Assert(aabbMax.getY() < m_bvhAabbMax.getY());
- b3Assert(aabbMax.getZ() < m_bvhAabbMax.getZ());
-
- ///we should update all quantization values, using updateBvhNodes(meshInterface);
- ///but we only update chunks that overlap the given aabb
-
- unsigned short quantizedQueryAabbMin[3];
- unsigned short quantizedQueryAabbMax[3];
-
- quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
- quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
-
- int i;
- for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
-
- //PCK: unsigned instead of bool
- unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
-
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
- }
- }
-}
-
-void b3OptimizedBvh::updateBvhNodes(b3StridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
-{
- (void)index;
-
- b3Assert(m_useQuantization);
-
- int curNodeSubPart = -1;
-
- //get access info to trianglemesh data
- const unsigned char* vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char* indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
-
- b3Vector3 triangleVerts[3];
- b3Vector3 aabbMin, aabbMax;
- const b3Vector3& meshScaling = meshInterface->getScaling();
-
- int i;
- for (i = endNode - 1; i >= firstNode; i--)
- {
- b3QuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
- if (curNode.isLeafNode())
- {
- //recalc aabb from triangle data
- int nodeSubPart = curNode.getPartId();
- int nodeTriangleIndex = curNode.getTriangleIndex();
- if (nodeSubPart != curNodeSubPart)
- {
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
-
- curNodeSubPart = nodeSubPart;
- }
- //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
-
- unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
-
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: b3Assert(0);
- }
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = b3MakeVector3(
- graphicsbase[0] * meshScaling.getX(),
- graphicsbase[1] * meshScaling.getY(),
- graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = b3MakeVector3(b3Scalar(graphicsbase[0] * meshScaling.getX()), b3Scalar(graphicsbase[1] * meshScaling.getY()), b3Scalar(graphicsbase[2] * meshScaling.getZ()));
- }
- }
-
- aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
- quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
- }
- else
- {
- //combine aabb from both children
-
- b3QuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
-
- b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
-
- {
- for (int i = 0; i < 3; i++)
- {
- curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
- if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
- curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
-
- curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
- if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
- curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
- }
- }
- }
- }
-
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
-}
-
-///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
-b3OptimizedBvh* b3OptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
-{
- b3QuantizedBvh* bvh = b3QuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
-
- //we don't add additional data so just do a static upcast
- return static_cast<b3OptimizedBvh*>(bvh);
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
deleted file mode 100644
index 1286552939..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///Contains contributions from Disney Studio's
-
-#ifndef B3_OPTIMIZED_BVH_H
-#define B3_OPTIMIZED_BVH_H
-
-#include "b3QuantizedBvh.h"
-
-class b3StridingMeshInterface;
-
-///The b3OptimizedBvh extends the b3QuantizedBvh to create AABB tree for triangle meshes, through the b3StridingMeshInterface.
-B3_ATTRIBUTE_ALIGNED16(class)
-b3OptimizedBvh : public b3QuantizedBvh
-{
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
-protected:
-public:
- b3OptimizedBvh();
-
- virtual ~b3OptimizedBvh();
-
- void build(b3StridingMeshInterface * triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax);
-
- void refit(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
-
- void refitPartial(b3StridingMeshInterface * triangles, const b3Vector3& aabbMin, const b3Vector3& aabbMax);
-
- void updateBvhNodes(b3StridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
-
- /// Data buffer MUST be 16 byte aligned
- virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
- {
- return b3QuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
- }
-
- ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static b3OptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-};
-
-#endif //B3_OPTIMIZED_BVH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
deleted file mode 100644
index 9a448495f3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.cpp
+++ /dev/null
@@ -1,1254 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3QuantizedBvh.h"
-
-#include "Bullet3Geometry/b3AabbUtil.h"
-
-#define RAYAABB2
-
-b3QuantizedBvh::b3QuantizedBvh() : m_bulletVersion(B3_BULLET_VERSION),
- m_useQuantization(false),
- m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- //m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
- ,
- m_subtreeHeaderCount(0) //PCK: add this line
-{
- m_bvhAabbMin.setValue(-B3_INFINITY, -B3_INFINITY, -B3_INFINITY);
- m_bvhAabbMax.setValue(B3_INFINITY, B3_INFINITY, B3_INFINITY);
-}
-
-void b3QuantizedBvh::buildInternal()
-{
- ///assumes that caller filled in the m_quantizedLeafNodes
- m_useQuantization = true;
- int numLeafNodes = 0;
-
- if (m_useQuantization)
- {
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2 * numLeafNodes);
- }
-
- m_curNodeIndex = 0;
-
- buildTree(0, numLeafNodes);
-
- ///if the entire tree is small then subtree size, we need to create a header info for the tree
- if (m_useQuantization && !m_SubtreeHeaders.size())
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
- subtree.m_rootNodeIndex = 0;
- subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
- m_quantizedLeafNodes.clear();
- m_leafNodes.clear();
-}
-
-///just for debugging, to visualize the individual patches/subtrees
-#ifdef DEBUG_PATCH_COLORS
-b3Vector3 color[4] =
- {
- b3Vector3(1, 0, 0),
- b3Vector3(0, 1, 0),
- b3Vector3(0, 0, 1),
- b3Vector3(0, 1, 1)};
-#endif //DEBUG_PATCH_COLORS
-
-void b3QuantizedBvh::setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin)
-{
- //enlarge the AABB to avoid division by zero when initializing the quantization values
- b3Vector3 clampValue = b3MakeVector3(quantizationMargin, quantizationMargin, quantizationMargin);
- m_bvhAabbMin = bvhAabbMin - clampValue;
- m_bvhAabbMax = bvhAabbMax + clampValue;
- b3Vector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = b3MakeVector3(b3Scalar(65533.0), b3Scalar(65533.0), b3Scalar(65533.0)) / aabbSize;
- m_useQuantization = true;
-}
-
-b3QuantizedBvh::~b3QuantizedBvh()
-{
-}
-
-#ifdef DEBUG_TREE_BUILDING
-int gStackDepth = 0;
-int gMaxStackDepth = 0;
-#endif //DEBUG_TREE_BUILDING
-
-void b3QuantizedBvh::buildTree(int startIndex, int endIndex)
-{
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth++;
- if (gStackDepth > gMaxStackDepth)
- gMaxStackDepth = gStackDepth;
-#endif //DEBUG_TREE_BUILDING
-
- int splitAxis, splitIndex, i;
- int numIndices = endIndex - startIndex;
- int curIndex = m_curNodeIndex;
-
- b3Assert(numIndices > 0);
-
- if (numIndices == 1)
- {
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- assignInternalNodeFromLeafNode(m_curNodeIndex, startIndex);
-
- m_curNodeIndex++;
- return;
- }
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- splitAxis = calcSplittingAxis(startIndex, endIndex);
-
- splitIndex = sortAndCalcSplittingIndex(startIndex, endIndex, splitAxis);
-
- int internalNodeIndex = m_curNodeIndex;
-
- //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
- //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
- setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax); //can't use b3Vector3(B3_INFINITY,B3_INFINITY,B3_INFINITY)) because of quantization
- setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin); //can't use b3Vector3(-B3_INFINITY,-B3_INFINITY,-B3_INFINITY)) because of quantization
-
- for (i = startIndex; i < endIndex; i++)
- {
- mergeInternalNodeAabb(m_curNodeIndex, getAabbMin(i), getAabbMax(i));
- }
-
- m_curNodeIndex++;
-
- //internalNode->m_escapeIndex;
-
- int leftChildNodexIndex = m_curNodeIndex;
-
- //build left child tree
- buildTree(startIndex, splitIndex);
-
- int rightChildNodexIndex = m_curNodeIndex;
- //build right child tree
- buildTree(splitIndex, endIndex);
-
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- int escapeIndex = m_curNodeIndex - curIndex;
-
- if (m_useQuantization)
- {
- //escapeIndex is the number of nodes of this subtree
- const int sizeQuantizedNode = sizeof(b3QuantizedBvhNode);
- const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
- if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
- {
- updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
- }
- }
- else
- {
- }
-
- setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
-}
-
-void b3QuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
-{
- b3Assert(m_useQuantization);
-
- b3QuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
- int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
- int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
-
- b3QuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
- int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
- int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(b3QuantizedBvhNode));
-
- if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(leftChildNode);
- subtree.m_rootNodeIndex = leftChildNodexIndex;
- subtree.m_subtreeSize = leftSubTreeSize;
- }
-
- if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- b3BvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(rightChildNode);
- subtree.m_rootNodeIndex = rightChildNodexIndex;
- subtree.m_subtreeSize = rightSubTreeSize;
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-}
-
-int b3QuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
-{
- int i;
- int splitIndex = startIndex;
- int numIndices = endIndex - startIndex;
- b3Scalar splitValue;
-
- b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- for (i = startIndex; i < endIndex; i++)
- {
- b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (b3Scalar(1.) / (b3Scalar)numIndices);
-
- splitValue = means[splitAxis];
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- if (center[splitAxis] > splitValue)
- {
- //swap
- swapLeafNodes(i, splitIndex);
- splitIndex++;
- }
- }
-
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
-
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
-
- //this should be safe too:
- int rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
-
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
-
- bool unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
- (void)unbal;
- b3Assert(!unbal);
-
- return splitIndex;
-}
-
-int b3QuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
-{
- int i;
-
- b3Vector3 means = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- b3Vector3 variance = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- int numIndices = endIndex - startIndex;
-
- for (i = startIndex; i < endIndex; i++)
- {
- b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (b3Scalar(1.) / (b3Scalar)numIndices);
-
- for (i = startIndex; i < endIndex; i++)
- {
- b3Vector3 center = b3Scalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- b3Vector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (b3Scalar(1.) / ((b3Scalar)numIndices - 1));
-
- return variance.maxAxis();
-}
-
-void b3QuantizedBvh::reportAabbOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
-{
- //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
-
- if (m_useQuantization)
- {
- ///quantize query AABB
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, aabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, aabbMax, 1);
-
- switch (m_traversalMode)
- {
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax, 0, m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
- {
- const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- break;
- default:
- //unsupported
- b3Assert(0);
- }
- }
- else
- {
- walkStacklessTree(nodeCallback, aabbMin, aabbMax);
- }
-}
-
-static int b3s_maxIterations = 0;
-
-void b3QuantizedBvh::walkStacklessTree(b3NodeOverlapCallback* nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
-{
- b3Assert(!m_useQuantization);
-
- const b3OptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- while (curIndex < m_curNodeIndex)
- {
- //catch bugs in tree data
- b3Assert(walkIterations < m_curNodeIndex);
-
- walkIterations++;
- aabbOverlap = b3TestAabbAgainstAabb2(aabbMin, aabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- isLeafNode = rootNode->m_escapeIndex == -1;
-
- //PCK: unsigned instead of bool
- if (isLeafNode && (aabbOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
-
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- if (b3s_maxIterations < walkIterations)
- b3s_maxIterations = walkIterations;
-}
-
-/*
-///this was the original recursive traversal, before we optimized towards stackless traversal
-void b3QuantizedBvh::walkTree(b3OptimizedBvhNode* rootNode,b3NodeOverlapCallback* nodeCallback,const b3Vector3& aabbMin,const b3Vector3& aabbMax) const
-{
- bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
- if (aabbOverlap)
- {
- isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
- if (isLeafNode)
- {
- nodeCallback->processNode(rootNode);
- } else
- {
- walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
- walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
- }
- }
-
-}
-*/
-
-void b3QuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
-{
- b3Assert(m_useQuantization);
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- //PCK: unsigned instead of bool
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, currentNode->m_quantizedAabbMin, currentNode->m_quantizedAabbMax);
- isLeafNode = currentNode->isLeafNode();
-
- //PCK: unsigned instead of bool
- if (aabbOverlap != 0)
- {
- if (isLeafNode)
- {
- nodeCallback->processNode(currentNode->getPartId(), currentNode->getTriangleIndex());
- }
- else
- {
- //process left and right children
- const b3QuantizedBvhNode* leftChildNode = currentNode + 1;
- walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
-
- const b3QuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
- walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- }
-}
-
-void b3QuantizedBvh::walkStacklessTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
-{
- b3Assert(!m_useQuantization);
-
- const b3OptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap = 0;
- unsigned rayBoxOverlap = 0;
- b3Scalar lambda_max = 1.0;
-
- /* Quick pruning by quantized box */
- b3Vector3 rayAabbMin = raySource;
- b3Vector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
-
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
-
-#ifdef RAYAABB2
- b3Vector3 rayDir = (rayTarget - raySource);
- rayDir.normalize();
- lambda_max = rayDir.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- b3Vector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDir[2];
- unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
-#endif
-
- b3Vector3 bounds[2];
-
- while (curIndex < m_curNodeIndex)
- {
- b3Scalar param = 1.0;
- //catch bugs in tree data
- b3Assert(walkIterations < m_curNodeIndex);
-
- walkIterations++;
-
- bounds[0] = rootNode->m_aabbMinOrg;
- bounds[1] = rootNode->m_aabbMaxOrg;
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
-
- aabbOverlap = b3TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- //perhaps profile if it is worth doing the aabbOverlap test first
-
-#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- rayBoxOverlap = aabbOverlap ? b3RayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
-
-#else
- b3Vector3 normal;
- rayBoxOverlap = b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
-#endif
-
- isLeafNode = rootNode->m_escapeIndex == -1;
-
- //PCK: unsigned instead of bool
- if (isLeafNode && (rayBoxOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
-
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- if (b3s_maxIterations < walkIterations)
- b3s_maxIterations = walkIterations;
-}
-
-void b3QuantizedBvh::walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const
-{
- b3Assert(m_useQuantization);
-
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
-
- const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned boxBoxOverlap = 0;
- unsigned rayBoxOverlap = 0;
-
- b3Scalar lambda_max = 1.0;
-
-#ifdef RAYAABB2
- b3Vector3 rayDirection = (rayTarget - raySource);
- rayDirection.normalize();
- lambda_max = rayDirection.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- rayDirection[0] = rayDirection[0] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[0];
- rayDirection[1] = rayDirection[1] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[1];
- rayDirection[2] = rayDirection[2] == b3Scalar(0.0) ? b3Scalar(B3_LARGE_FLOAT) : b3Scalar(1.0) / rayDirection[2];
- unsigned int sign[3] = {rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
-#endif
-
- /* Quick pruning by quantized box */
- b3Vector3 rayAabbMin = raySource;
- b3Vector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
-
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
-
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, rayAabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, rayAabbMax, 1);
-
- while (curIndex < endNodeIndex)
- {
-//#define VISUALLY_ANALYZE_BVH 1
-#ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern b3IDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- b3Vector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- b3Vector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
-#endif //VISUALLY_ANALYZE_BVH
-
- //catch bugs in tree data
- b3Assert(walkIterations < subTreeSize);
-
- walkIterations++;
- //PCK: unsigned instead of bool
- // only interested if this is closer than any previous hit
- b3Scalar param = 1.0;
- rayBoxOverlap = 0;
- boxBoxOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
- if (boxBoxOverlap)
- {
- b3Vector3 bounds[2];
- bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
- bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
-#if 0
- b3Vector3 normal;
- bool ra2 = b3RayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
- bool ra = b3RayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
- if (ra2 != ra)
- {
- printf("functions don't match\n");
- }
-#endif
-#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
-
- //B3_PROFILE("b3RayAabb2");
- rayBoxOverlap = b3RayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
-
-#else
- rayBoxOverlap = true; //b3RayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
-#endif
- }
-
- if (isLeafNode && rayBoxOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
-
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- if (b3s_maxIterations < walkIterations)
- b3s_maxIterations = walkIterations;
-}
-
-void b3QuantizedBvh::walkStacklessQuantizedTree(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
-{
- b3Assert(m_useQuantization);
-
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
-
- const b3QuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- while (curIndex < endNodeIndex)
- {
-//#define VISUALLY_ANALYZE_BVH 1
-#ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern b3IDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- b3Vector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- b3Vector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
-#endif //VISUALLY_ANALYZE_BVH
-
- //catch bugs in tree data
- b3Assert(walkIterations < subTreeSize);
-
- walkIterations++;
- //PCK: unsigned instead of bool
- aabbOverlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
-
- if (isLeafNode && aabbOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
-
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
- if (b3s_maxIterations < walkIterations)
- b3s_maxIterations = walkIterations;
-}
-
-//This traversal can be called from Playstation 3 SPU
-void b3QuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
-{
- b3Assert(m_useQuantization);
-
- int i;
-
- for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
- {
- const b3BvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
-
- //PCK: unsigned instead of bool
- unsigned overlap = b3TestQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax,
- subtree.m_rootNodeIndex,
- subtree.m_rootNodeIndex + subtree.m_subtreeSize);
- }
- }
-}
-
-void b3QuantizedBvh::reportRayOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const
-{
- reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, b3MakeVector3(0, 0, 0), b3MakeVector3(0, 0, 0));
-}
-
-void b3QuantizedBvh::reportBoxCastOverlappingNodex(b3NodeOverlapCallback* nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
-{
- //always use stackless
-
- if (m_useQuantization)
- {
- walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- else
- {
- walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- /*
- {
- //recursive traversal
- b3Vector3 qaabbMin = raySource;
- b3Vector3 qaabbMax = raySource;
- qaabbMin.setMin(rayTarget);
- qaabbMax.setMax(rayTarget);
- qaabbMin += aabbMin;
- qaabbMax += aabbMax;
- reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
- }
- */
-}
-
-void b3QuantizedBvh::swapLeafNodes(int i, int splitIndex)
-{
- if (m_useQuantization)
- {
- b3QuantizedBvhNode tmp = m_quantizedLeafNodes[i];
- m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
- m_quantizedLeafNodes[splitIndex] = tmp;
- }
- else
- {
- b3OptimizedBvhNode tmp = m_leafNodes[i];
- m_leafNodes[i] = m_leafNodes[splitIndex];
- m_leafNodes[splitIndex] = tmp;
- }
-}
-
-void b3QuantizedBvh::assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex)
-{
- if (m_useQuantization)
- {
- m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
- }
- else
- {
- m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
- }
-}
-
-//PCK: include
-#include <new>
-
-#if 0
-//PCK: consts
-static const unsigned BVH_ALIGNMENT = 16;
-static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
-
-static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
-#endif
-
-unsigned int b3QuantizedBvh::getAlignmentSerializationPadding()
-{
- // I changed this to 0 since the extra padding is not needed or used.
- return 0; //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
-}
-
-unsigned b3QuantizedBvh::calculateSerializeBufferSize() const
-{
- unsigned baseSize = sizeof(b3QuantizedBvh) + getAlignmentSerializationPadding();
- baseSize += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
- if (m_useQuantization)
- {
- return baseSize + m_curNodeIndex * sizeof(b3QuantizedBvhNode);
- }
- return baseSize + m_curNodeIndex * sizeof(b3OptimizedBvhNode);
-}
-
-bool b3QuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
-{
- b3Assert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- ///check alignedment for buffer?
- b3Assert(0);
- return false;
- }
-*/
-
- b3QuantizedBvh* targetBvh = (b3QuantizedBvh*)o_alignedDataBuffer;
-
- // construct the class so the virtual function table, etc will be set up
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (targetBvh) b3QuantizedBvh;
-
- if (i_swapEndian)
- {
- targetBvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(m_curNodeIndex));
-
- b3SwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
- b3SwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
- b3SwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
-
- targetBvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(m_traversalMode);
- targetBvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(m_subtreeHeaderCount));
- }
- else
- {
- targetBvh->m_curNodeIndex = m_curNodeIndex;
- targetBvh->m_bvhAabbMin = m_bvhAabbMin;
- targetBvh->m_bvhAabbMax = m_bvhAabbMax;
- targetBvh->m_bvhQuantization = m_bvhQuantization;
- targetBvh->m_traversalMode = m_traversalMode;
- targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
- }
-
- targetBvh->m_useQuantization = m_useQuantization;
-
- unsigned char* nodeData = (unsigned char*)targetBvh;
- nodeData += sizeof(b3QuantizedBvh);
-
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- int nodeCount = m_curNodeIndex;
-
- if (m_useQuantization)
- {
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
- }
- }
- nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
- else
- {
- targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- b3SwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
-
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
- }
- }
- nodeData += sizeof(b3OptimizedBvhNode) * nodeCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
-
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- // Now serialize the subtree headers
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
- else
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
-
- // need to clear padding in destination buffer
- targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
- }
- }
- nodeData += sizeof(b3BvhSubtreeInfo) * m_subtreeHeaderCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
-
- // this wipes the virtual function table pointer at the start of the buffer for the class
- *((void**)o_alignedDataBuffer) = NULL;
-
- return true;
-}
-
-b3QuantizedBvh* b3QuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
-{
- if (i_alignedDataBuffer == NULL) // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- return NULL;
- }
- b3QuantizedBvh* bvh = (b3QuantizedBvh*)i_alignedDataBuffer;
-
- if (i_swapEndian)
- {
- bvh->m_curNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_curNodeIndex));
-
- b3UnSwapVector3Endian(bvh->m_bvhAabbMin);
- b3UnSwapVector3Endian(bvh->m_bvhAabbMax);
- b3UnSwapVector3Endian(bvh->m_bvhQuantization);
-
- bvh->m_traversalMode = (b3TraversalMode)b3SwapEndian(bvh->m_traversalMode);
- bvh->m_subtreeHeaderCount = static_cast<int>(b3SwapEndian(bvh->m_subtreeHeaderCount));
- }
-
- unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
- b3Assert(calculatedBufSize <= i_dataBufferSize);
-
- if (calculatedBufSize > i_dataBufferSize)
- {
- return NULL;
- }
-
- unsigned char* nodeData = (unsigned char*)bvh;
- nodeData += sizeof(b3QuantizedBvh);
-
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- int nodeCount = bvh->m_curNodeIndex;
-
- // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (bvh) b3QuantizedBvh(*bvh, false);
-
- if (bvh->m_useQuantization)
- {
- bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
-
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
-
- bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(b3SwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- nodeData += sizeof(b3QuantizedBvhNode) * nodeCount;
- }
- else
- {
- bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- b3UnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
- bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
- bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
- bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(b3SwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- nodeData += sizeof(b3OptimizedBvhNode) * nodeCount;
- }
-
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- // Now serialize the subtree headers
- bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
- {
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = b3SwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
- bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(b3SwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
-
- return bvh;
-}
-
-// Constructor that prevents b3Vector3's default constructor from being called
-b3QuantizedBvh::b3QuantizedBvh(b3QuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
- m_bvhAabbMax(self.m_bvhAabbMax),
- m_bvhQuantization(self.m_bvhQuantization),
- m_bulletVersion(B3_BULLET_VERSION)
-{
-}
-
-void b3QuantizedBvh::deSerializeFloat(struct b3QuantizedBvhFloatData& quantizedBvhFloatData)
-{
- m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
-
- m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
- m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
-
- {
- int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
-
- if (numElem)
- {
- b3OptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
-
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
-
- {
- int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
-
- if (numElem)
- {
- b3QuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
-
- m_traversalMode = b3TraversalMode(quantizedBvhFloatData.m_traversalMode);
-
- {
- int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- b3BvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
-}
-
-void b3QuantizedBvh::deSerializeDouble(struct b3QuantizedBvhDoubleData& quantizedBvhDoubleData)
-{
- m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
-
- m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
- m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
-
- {
- int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
-
- if (numElem)
- {
- b3OptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
-
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
-
- {
- int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
-
- if (numElem)
- {
- b3QuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
-
- m_traversalMode = b3TraversalMode(quantizedBvhDoubleData.m_traversalMode);
-
- {
- int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- b3BvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* b3QuantizedBvh::serialize(void* dataBuffer, b3Serializer* serializer) const
-{
- b3Assert(0);
- return 0;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
deleted file mode 100644
index 48b41abcad..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_QUANTIZED_BVH_H
-#define B3_QUANTIZED_BVH_H
-
-class b3Serializer;
-
-//#define DEBUG_CHECK_DEQUANTIZATION 1
-#ifdef DEBUG_CHECK_DEQUANTIZATION
-#ifdef __SPU__
-#define printf spu_printf
-#endif //__SPU__
-
-#include <stdio.h>
-#include <stdlib.h>
-#endif //DEBUG_CHECK_DEQUANTIZATION
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3AlignedAllocator.h"
-
-#ifdef B3_USE_DOUBLE_PRECISION
-#define b3QuantizedBvhData b3QuantizedBvhDoubleData
-#define b3OptimizedBvhNodeData b3OptimizedBvhNodeDoubleData
-#define b3QuantizedBvhDataName "b3QuantizedBvhDoubleData"
-#else
-#define b3QuantizedBvhData b3QuantizedBvhFloatData
-#define b3OptimizedBvhNodeData b3OptimizedBvhNodeFloatData
-#define b3QuantizedBvhDataName "b3QuantizedBvhFloatData"
-#endif
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3QuantizedBvhNodeData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3BvhSubtreeInfoData.h"
-
-//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
-
-//Note: currently we have 16 bytes per quantized node
-#define MAX_SUBTREE_SIZE_IN_BYTES 2048
-
-// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
-// actually) triangles each (since the sign bit is reserved
-#define MAX_NUM_PARTS_IN_BITS 10
-
-///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3QuantizedBvhNode : public b3QuantizedBvhNodeData
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- bool isLeafNode() const
- {
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrTriangleIndex >= 0);
- }
- int getEscapeIndex() const
- {
- b3Assert(!isLeafNode());
- return -m_escapeIndexOrTriangleIndex;
- }
- int getTriangleIndex() const
- {
- b3Assert(isLeafNode());
- unsigned int x = 0;
- unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (m_escapeIndexOrTriangleIndex & ~(y));
- }
- int getPartId() const
- {
- b3Assert(isLeafNode());
- // Get only the highest bits where the part index is stored
- return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
- }
-};
-
-/// b3OptimizedBvhNode contains both internal and leaf node information.
-/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3OptimizedBvhNode
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- //32 bytes
- b3Vector3 m_aabbMinOrg;
- b3Vector3 m_aabbMaxOrg;
-
- //4
- int m_escapeIndex;
-
- //8
- //for child nodes
- int m_subPart;
- int m_triangleIndex;
-
- //pad the size to 64 bytes
- char m_padding[20];
-};
-
-///b3BvhSubtreeInfo provides info to gather a subtree of limited size
-B3_ATTRIBUTE_ALIGNED16(class)
-b3BvhSubtreeInfo : public b3BvhSubtreeInfoData
-{
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3BvhSubtreeInfo()
- {
- //memset(&m_padding[0], 0, sizeof(m_padding));
- }
-
- void setAabbFromQuantizeNode(const b3QuantizedBvhNode& quantizedNode)
- {
- m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
- m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
- m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
- m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
- m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
- m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
- }
-};
-
-class b3NodeOverlapCallback
-{
-public:
- virtual ~b3NodeOverlapCallback(){};
-
- virtual void processNode(int subPart, int triangleIndex) = 0;
-};
-
-#include "Bullet3Common/b3AlignedAllocator.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-///for code readability:
-typedef b3AlignedObjectArray<b3OptimizedBvhNode> NodeArray;
-typedef b3AlignedObjectArray<b3QuantizedBvhNode> QuantizedNodeArray;
-typedef b3AlignedObjectArray<b3BvhSubtreeInfo> BvhSubtreeInfoArray;
-
-///The b3QuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
-///It is used by the b3BvhTriangleMeshShape as midphase
-///It is recommended to use quantization for better performance and lower memory requirements.
-B3_ATTRIBUTE_ALIGNED16(class)
-b3QuantizedBvh
-{
-public:
- enum b3TraversalMode
- {
- TRAVERSAL_STACKLESS = 0,
- TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
- TRAVERSAL_RECURSIVE
- };
-
- b3Vector3 m_bvhAabbMin;
- b3Vector3 m_bvhAabbMax;
- b3Vector3 m_bvhQuantization;
-
-protected:
- int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
-
- int m_curNodeIndex;
- //quantization data
- bool m_useQuantization;
-
- NodeArray m_leafNodes;
- NodeArray m_contiguousNodes;
- QuantizedNodeArray m_quantizedLeafNodes;
- QuantizedNodeArray m_quantizedContiguousNodes;
-
- b3TraversalMode m_traversalMode;
- BvhSubtreeInfoArray m_SubtreeHeaders;
-
- //This is only used for serialization so we don't have to add serialization directly to b3AlignedObjectArray
- mutable int m_subtreeHeaderCount;
-
- ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
- ///this might be refactored into a virtual, it is usually not calculated at run-time
- void setInternalNodeAabbMin(int nodeIndex, const b3Vector3& aabbMin)
- {
- if (m_useQuantization)
- {
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
- }
- }
- void setInternalNodeAabbMax(int nodeIndex, const b3Vector3& aabbMax)
- {
- if (m_useQuantization)
- {
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
- }
- }
-
- b3Vector3 getAabbMin(int nodeIndex) const
- {
- if (m_useQuantization)
- {
- return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
- }
- //non-quantized
- return m_leafNodes[nodeIndex].m_aabbMinOrg;
- }
- b3Vector3 getAabbMax(int nodeIndex) const
- {
- if (m_useQuantization)
- {
- return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
- }
- //non-quantized
- return m_leafNodes[nodeIndex].m_aabbMaxOrg;
- }
-
- void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
- {
- if (m_useQuantization)
- {
- m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
- }
- }
-
- void mergeInternalNodeAabb(int nodeIndex, const b3Vector3& newAabbMin, const b3Vector3& newAabbMax)
- {
- if (m_useQuantization)
- {
- unsigned short int quantizedAabbMin[3];
- unsigned short int quantizedAabbMax[3];
- quantize(quantizedAabbMin, newAabbMin, 0);
- quantize(quantizedAabbMax, newAabbMax, 1);
- for (int i = 0; i < 3; i++)
- {
- if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
- m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
-
- if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
- m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
- }
- }
- else
- {
- //non-quantized
- m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
- }
- }
-
- void swapLeafNodes(int firstIndex, int secondIndex);
-
- void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
-
-protected:
- void buildTree(int startIndex, int endIndex);
-
- int calcSplittingAxis(int startIndex, int endIndex);
-
- int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
-
- void walkStacklessTree(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
-
- void walkStacklessQuantizedTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
- void walkStacklessQuantizedTree(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
- void walkStacklessTreeAgainstRay(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
-
- ///tree traversal designed for small-memory processors like PS3 SPU
- void walkStacklessQuantizedTreeCacheFriendly(b3NodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
-
- ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQueryAabb(const b3QuantizedBvhNode* currentNode, b3NodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
-
- ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQuantizedTree(const b3QuantizedBvhNode* treeNodeA, const b3QuantizedBvhNode* treeNodeB, b3NodeOverlapCallback* nodeCallback) const;
-
- void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3QuantizedBvh();
-
- virtual ~b3QuantizedBvh();
-
- ///***************************************** expert/internal use only *************************
- void setQuantizationValues(const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax, b3Scalar quantizationMargin = b3Scalar(1.0));
- QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
- ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
- void buildInternal();
- ///***************************************** expert/internal use only *************************
-
- void reportAabbOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
- void reportRayOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget) const;
- void reportBoxCastOverlappingNodex(b3NodeOverlapCallback * nodeCallback, const b3Vector3& raySource, const b3Vector3& rayTarget, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
-
- B3_FORCE_INLINE void quantize(unsigned short* out, const b3Vector3& point, int isMax) const
- {
- b3Assert(m_useQuantization);
-
- b3Assert(point.getX() <= m_bvhAabbMax.getX());
- b3Assert(point.getY() <= m_bvhAabbMax.getY());
- b3Assert(point.getZ() <= m_bvhAabbMax.getZ());
-
- b3Assert(point.getX() >= m_bvhAabbMin.getX());
- b3Assert(point.getY() >= m_bvhAabbMin.getY());
- b3Assert(point.getZ() >= m_bvhAabbMin.getZ());
-
- b3Vector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
- ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
- ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
- ///@todo: double-check this
- if (isMax)
- {
- out[0] = (unsigned short)(((unsigned short)(v.getX() + b3Scalar(1.)) | 1));
- out[1] = (unsigned short)(((unsigned short)(v.getY() + b3Scalar(1.)) | 1));
- out[2] = (unsigned short)(((unsigned short)(v.getZ() + b3Scalar(1.)) | 1));
- }
- else
- {
- out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
- out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
- out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
- }
-
-#ifdef DEBUG_CHECK_DEQUANTIZATION
- b3Vector3 newPoint = unQuantize(out);
- if (isMax)
- {
- if (newPoint.getX() < point.getX())
- {
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
- }
- if (newPoint.getY() < point.getY())
- {
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
- }
- if (newPoint.getZ() < point.getZ())
- {
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
- }
- }
- else
- {
- if (newPoint.getX() > point.getX())
- {
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
- }
- if (newPoint.getY() > point.getY())
- {
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
- }
- if (newPoint.getZ() > point.getZ())
- {
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
- }
- }
-#endif //DEBUG_CHECK_DEQUANTIZATION
- }
-
- B3_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const b3Vector3& point2, int isMax) const
- {
- b3Assert(m_useQuantization);
-
- b3Vector3 clampedPoint(point2);
- clampedPoint.setMax(m_bvhAabbMin);
- clampedPoint.setMin(m_bvhAabbMax);
-
- quantize(out, clampedPoint, isMax);
- }
-
- B3_FORCE_INLINE b3Vector3 unQuantize(const unsigned short* vecIn) const
- {
- b3Vector3 vecOut;
- vecOut.setValue(
- (b3Scalar)(vecIn[0]) / (m_bvhQuantization.getX()),
- (b3Scalar)(vecIn[1]) / (m_bvhQuantization.getY()),
- (b3Scalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
- vecOut += m_bvhAabbMin;
- return vecOut;
- }
-
- ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
- void setTraversalMode(b3TraversalMode traversalMode)
- {
- m_traversalMode = traversalMode;
- }
-
- B3_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
- {
- return m_quantizedContiguousNodes;
- }
-
- B3_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
- {
- return m_SubtreeHeaders;
- }
-
- ////////////////////////////////////////////////////////////////////
-
- /////Calculate space needed to store BVH for serialization
- unsigned calculateSerializeBufferSize() const;
-
- /// Data buffer MUST be 16 byte aligned
- virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
-
- ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static b3QuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-
- static unsigned int getAlignmentSerializationPadding();
- //////////////////////////////////////////////////////////////////////
-
- virtual int calculateSerializeBufferSizeNew() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-
- virtual void deSerializeFloat(struct b3QuantizedBvhFloatData & quantizedBvhFloatData);
-
- virtual void deSerializeDouble(struct b3QuantizedBvhDoubleData & quantizedBvhDoubleData);
-
- ////////////////////////////////////////////////////////////////////
-
- B3_FORCE_INLINE bool isQuantized()
- {
- return m_useQuantization;
- }
-
-private:
- // Special "copy" constructor that allows for in-place deserialization
- // Prevents b3Vector3's default constructor from being called, but doesn't inialize much else
- // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
- b3QuantizedBvh(b3QuantizedBvh & other, bool ownsMemory);
-};
-
-struct b3OptimizedBvhNodeFloatData
-{
- b3Vector3FloatData m_aabbMinOrg;
- b3Vector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-struct b3OptimizedBvhNodeDoubleData
-{
- b3Vector3DoubleData m_aabbMinOrg;
- b3Vector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-struct b3QuantizedBvhFloatData
-{
- b3Vector3FloatData m_bvhAabbMin;
- b3Vector3FloatData m_bvhAabbMax;
- b3Vector3FloatData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeFloatData* m_contiguousNodesPtr;
- b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
- b3BvhSubtreeInfoData* m_subTreeInfoPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
-};
-
-struct b3QuantizedBvhDoubleData
-{
- b3Vector3DoubleData m_bvhAabbMin;
- b3Vector3DoubleData m_bvhAabbMax;
- b3Vector3DoubleData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeDoubleData* m_contiguousNodesPtr;
- b3QuantizedBvhNodeData* m_quantizedContiguousNodesPtr;
-
- int m_traversalMode;
- int m_numSubtreeHeaders;
- b3BvhSubtreeInfoData* m_subTreeInfoPtr;
-};
-
-B3_FORCE_INLINE int b3QuantizedBvh::calculateSerializeBufferSizeNew() const
-{
- return sizeof(b3QuantizedBvhData);
-}
-
-#endif //B3_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
deleted file mode 100644
index 6b0c941f23..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3StridingMeshInterface.h"
-
-b3StridingMeshInterface::~b3StridingMeshInterface()
-{
-}
-
-void b3StridingMeshInterface::InternalProcessAllTriangles(b3InternalTriangleIndexCallback* callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
-{
- (void)aabbMin;
- (void)aabbMax;
- int numtotalphysicsverts = 0;
- int part, graphicssubparts = getNumSubParts();
- const unsigned char* vertexbase;
- const unsigned char* indexbase;
- int indexstride;
- PHY_ScalarType type;
- PHY_ScalarType gfxindextype;
- int stride, numverts, numtriangles;
- int gfxindex;
- b3Vector3 triangle[3];
-
- b3Vector3 meshScaling = getScaling();
-
- ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part = 0; part < graphicssubparts; part++)
- {
- getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
- numtotalphysicsverts += numtriangles * 3; //upper bound
-
- ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
- ///so disable this feature by default
- ///see patch http://code.google.com/p/bullet/issues/detail?id=213
-
- switch (type)
- {
- case PHY_FLOAT:
- {
- float* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- default:
- b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
-
- case PHY_DOUBLE:
- {
- double* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((b3Scalar)graphicsbase[0] * meshScaling.getX(), (b3Scalar)graphicsbase[1] * meshScaling.getY(), (b3Scalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- default:
- b3Assert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
- default:
- b3Assert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
- }
-
- unLockReadOnlyVertexBase(part);
- }
-}
-
-void b3StridingMeshInterface::calculateAabbBruteForce(b3Vector3& aabbMin, b3Vector3& aabbMax)
-{
- struct AabbCalculationCallback : public b3InternalTriangleIndexCallback
- {
- b3Vector3 m_aabbMin;
- b3Vector3 m_aabbMax;
-
- AabbCalculationCallback()
- {
- m_aabbMin.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- m_aabbMax.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- }
-
- virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
-
- m_aabbMin.setMin(triangle[0]);
- m_aabbMax.setMax(triangle[0]);
- m_aabbMin.setMin(triangle[1]);
- m_aabbMax.setMax(triangle[1]);
- m_aabbMin.setMin(triangle[2]);
- m_aabbMax.setMax(triangle[2]);
- }
- };
-
- //first calculate the total aabb for all triangles
- AabbCalculationCallback aabbCallback;
- aabbMin.setValue(b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT), b3Scalar(-B3_LARGE_FLOAT));
- aabbMax.setValue(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
-
- aabbMin = aabbCallback.m_aabbMin;
- aabbMax = aabbCallback.m_aabbMax;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
deleted file mode 100644
index 2b1e63be75..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3StridingMeshInterface.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_STRIDING_MESHINTERFACE_H
-#define B3_STRIDING_MESHINTERFACE_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "b3TriangleCallback.h"
-//#include "b3ConcaveShape.h"
-
-enum PHY_ScalarType
-{
- PHY_FLOAT,
- PHY_DOUBLE,
- PHY_INTEGER,
- PHY_SHORT,
- PHY_FIXEDPOINT88,
- PHY_UCHAR
-};
-
-/// The b3StridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with b3BvhTriangleMeshShape and some other collision shapes.
-/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
-/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
-B3_ATTRIBUTE_ALIGNED16(class)
-b3StridingMeshInterface
-{
-protected:
- b3Vector3 m_scaling;
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3StridingMeshInterface() : m_scaling(b3MakeVector3(b3Scalar(1.), b3Scalar(1.), b3Scalar(1.)))
- {
- }
-
- virtual ~b3StridingMeshInterface();
-
- virtual void InternalProcessAllTriangles(b3InternalTriangleIndexCallback * callback, const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
-
- ///brute force method to calculate aabb
- void calculateAabbBruteForce(b3Vector3 & aabbMin, b3Vector3 & aabbMax);
-
- /// get read and write access to a subpart of a triangle mesh
- /// this subpart has a continuous array of vertices and indices
- /// in this way the mesh can be handled as chunks of memory with striding
- /// very similar to OpenGL vertexarray support
- /// make a call to unLockVertexBase when the read and write access is finished
- virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) = 0;
-
- virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
-
- /// getNumSubParts returns the number of separate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const = 0;
-
- virtual void preallocateVertices(int numverts) = 0;
- virtual void preallocateIndices(int numindices) = 0;
-
- virtual bool hasPremadeAabb() const { return false; }
- virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
- {
- (void)aabbMin;
- (void)aabbMax;
- }
- virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const
- {
- (void)aabbMin;
- (void)aabbMax;
- }
-
- const b3Vector3& getScaling() const
- {
- return m_scaling;
- }
- void setScaling(const b3Vector3& scaling)
- {
- m_scaling = scaling;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- //virtual const char* serialize(void* dataBuffer, b3Serializer* serializer) const;
-};
-
-struct b3IntIndexData
-{
- int m_value;
-};
-
-struct b3ShortIntIndexData
-{
- short m_value;
- char m_pad[2];
-};
-
-struct b3ShortIntIndexTripletData
-{
- short m_values[3];
- char m_pad[2];
-};
-
-struct b3CharIndexTripletData
-{
- unsigned char m_values[3];
- char m_pad;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3MeshPartData
-{
- b3Vector3FloatData* m_vertices3f;
- b3Vector3DoubleData* m_vertices3d;
-
- b3IntIndexData* m_indices32;
- b3ShortIntIndexTripletData* m_3indices16;
- b3CharIndexTripletData* m_3indices8;
-
- b3ShortIntIndexData* m_indices16; //backwards compatibility
-
- int m_numTriangles; //length of m_indices = m_numTriangles
- int m_numVertices;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct b3StridingMeshInterfaceData
-{
- b3MeshPartData* m_meshPartsPtr;
- b3Vector3FloatData m_scaling;
- int m_numMeshParts;
- char m_padding[4];
-};
-
-B3_FORCE_INLINE int b3StridingMeshInterface::calculateSerializeBufferSize() const
-{
- return sizeof(b3StridingMeshInterfaceData);
-}
-
-#endif //B3_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
deleted file mode 100644
index 9ca1e22949..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3SupportMappings.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-#ifndef B3_SUPPORT_MAPPINGS_H
-#define B3_SUPPORT_MAPPINGS_H
-
-#include "Bullet3Common/b3Transform.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "b3VectorFloat4.h"
-
-struct b3GjkPairDetector;
-
-inline b3Vector3 localGetSupportVertexWithMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
- const b3AlignedObjectArray<b3Vector3>& verticesA, b3Scalar margin)
-{
- b3Vector3 supVec = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- b3Scalar maxDot = b3Scalar(-B3_LARGE_FLOAT);
-
- // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
- if (0 < hull->m_numVertices)
- {
- const b3Vector3 scaled = supportVec;
- int index = (int)scaled.maxDot(&verticesA[hull->m_vertexOffset], hull->m_numVertices, maxDot);
- return verticesA[hull->m_vertexOffset + index];
- }
-
- return supVec;
-}
-
-inline b3Vector3 localGetSupportVertexWithoutMargin(const float4& supportVec, const struct b3ConvexPolyhedronData* hull,
- const b3AlignedObjectArray<b3Vector3>& verticesA)
-{
- return localGetSupportVertexWithMargin(supportVec, hull, verticesA, 0.f);
-}
-
-#endif //B3_SUPPORT_MAPPINGS_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
deleted file mode 100644
index 3908c6de89..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3TriangleCallback.h"
-
-b3TriangleCallback::~b3TriangleCallback()
-{
-}
-
-b3InternalTriangleIndexCallback::~b3InternalTriangleIndexCallback()
-{
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
deleted file mode 100644
index a0fd3e7ac7..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleCallback.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_TRIANGLE_CALLBACK_H
-#define B3_TRIANGLE_CALLBACK_H
-
-#include "Bullet3Common/b3Vector3.h"
-
-///The b3TriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
-///This callback is called by processAllTriangles for all b3ConcaveShape derived class, such as b3BvhTriangleMeshShape, b3StaticPlaneShape and b3HeightfieldTerrainShape.
-class b3TriangleCallback
-{
-public:
- virtual ~b3TriangleCallback();
- virtual void processTriangle(b3Vector3* triangle, int partId, int triangleIndex) = 0;
-};
-
-class b3InternalTriangleIndexCallback
-{
-public:
- virtual ~b3InternalTriangleIndexCallback();
- virtual void internalProcessTriangleIndex(b3Vector3* triangle, int partId, int triangleIndex) = 0;
-};
-
-#endif //B3_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
deleted file mode 100644
index 73faadbdd0..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3TriangleIndexVertexArray.h"
-
-b3TriangleIndexVertexArray::b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride)
- : m_hasAabb(0)
-{
- b3IndexedMesh mesh;
-
- mesh.m_numTriangles = numTriangles;
- mesh.m_triangleIndexBase = (const unsigned char*)triangleIndexBase;
- mesh.m_triangleIndexStride = triangleIndexStride;
- mesh.m_numVertices = numVertices;
- mesh.m_vertexBase = (const unsigned char*)vertexBase;
- mesh.m_vertexStride = vertexStride;
-
- addIndexedMesh(mesh);
-}
-
-b3TriangleIndexVertexArray::~b3TriangleIndexVertexArray()
-{
-}
-
-void b3TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
-{
- b3Assert(subpart < getNumSubParts());
-
- b3IndexedMesh& mesh = m_indexedMeshes[subpart];
-
- numverts = mesh.m_numVertices;
- (*vertexbase) = (unsigned char*)mesh.m_vertexBase;
-
- type = mesh.m_vertexType;
-
- vertexStride = mesh.m_vertexStride;
-
- numfaces = mesh.m_numTriangles;
-
- (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
- indexstride = mesh.m_triangleIndexStride;
- indicestype = mesh.m_indexType;
-}
-
-void b3TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
-{
- const b3IndexedMesh& mesh = m_indexedMeshes[subpart];
-
- numverts = mesh.m_numVertices;
- (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
-
- type = mesh.m_vertexType;
-
- vertexStride = mesh.m_vertexStride;
-
- numfaces = mesh.m_numTriangles;
- (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
- indexstride = mesh.m_triangleIndexStride;
- indicestype = mesh.m_indexType;
-}
-
-bool b3TriangleIndexVertexArray::hasPremadeAabb() const
-{
- return (m_hasAabb == 1);
-}
-
-void b3TriangleIndexVertexArray::setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const
-{
- m_aabbMin = aabbMin;
- m_aabbMax = aabbMax;
- m_hasAabb = 1; // this is intentionally an int see notes in header
-}
-
-void b3TriangleIndexVertexArray::getPremadeAabb(b3Vector3* aabbMin, b3Vector3* aabbMax) const
-{
- *aabbMin = m_aabbMin;
- *aabbMax = m_aabbMax;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
deleted file mode 100644
index 57cbf03dc2..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
-#define B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
-
-#include "b3StridingMeshInterface.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Scalar.h"
-
-///The b3IndexedMesh indexes a single vertex and index array. Multiple b3IndexedMesh objects can be passed into a b3TriangleIndexVertexArray using addIndexedMesh.
-///Instead of the number of indices, we pass the number of triangles.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3IndexedMesh
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_numTriangles;
- const unsigned char* m_triangleIndexBase;
- // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
- int m_triangleIndexStride;
- int m_numVertices;
- const unsigned char* m_vertexBase;
- // Size of a vertex, in bytes
- int m_vertexStride;
-
- // The index type is set when adding an indexed mesh to the
- // b3TriangleIndexVertexArray, do not set it manually
- PHY_ScalarType m_indexType;
-
- // The vertex type has a default type similar to Bullet's precision mode (float or double)
- // but can be set manually if you for example run Bullet with double precision but have
- // mesh data in single precision..
- PHY_ScalarType m_vertexType;
-
- b3IndexedMesh()
- : m_indexType(PHY_INTEGER),
-#ifdef B3_USE_DOUBLE_PRECISION
- m_vertexType(PHY_DOUBLE)
-#else // B3_USE_DOUBLE_PRECISION
- m_vertexType(PHY_FLOAT)
-#endif // B3_USE_DOUBLE_PRECISION
- {
- }
-};
-
-typedef b3AlignedObjectArray<b3IndexedMesh> IndexedMeshArray;
-
-///The b3TriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
-///Additional meshes can be added using addIndexedMesh
-///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
-///So keep those arrays around during the lifetime of this b3TriangleIndexVertexArray.
-B3_ATTRIBUTE_ALIGNED16(class)
-b3TriangleIndexVertexArray : public b3StridingMeshInterface
-{
-protected:
- IndexedMeshArray m_indexedMeshes;
- int m_pad[2];
- mutable int m_hasAabb; // using int instead of bool to maintain alignment
- mutable b3Vector3 m_aabbMin;
- mutable b3Vector3 m_aabbMax;
-
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3TriangleIndexVertexArray() : m_hasAabb(0)
- {
- }
-
- virtual ~b3TriangleIndexVertexArray();
-
- //just to be backwards compatible
- b3TriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, b3Scalar* vertexBase, int vertexStride);
-
- void addIndexedMesh(const b3IndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
- {
- m_indexedMeshes.push_back(mesh);
- m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
- }
-
- virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) { (void)subpart; }
-
- virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
-
- /// getNumSubParts returns the number of separate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const
- {
- return (int)m_indexedMeshes.size();
- }
-
- IndexedMeshArray& getIndexedMeshArray()
- {
- return m_indexedMeshes;
- }
-
- const IndexedMeshArray& getIndexedMeshArray() const
- {
- return m_indexedMeshes;
- }
-
- virtual void preallocateVertices(int numverts) { (void)numverts; }
- virtual void preallocateIndices(int numindices) { (void)numindices; }
-
- virtual bool hasPremadeAabb() const;
- virtual void setPremadeAabb(const b3Vector3& aabbMin, const b3Vector3& aabbMax) const;
- virtual void getPremadeAabb(b3Vector3 * aabbMin, b3Vector3 * aabbMax) const;
-};
-
-#endif //B3_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
deleted file mode 100644
index 5cc4b5a626..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VectorFloat4.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef B3_VECTOR_FLOAT4_H
-#define B3_VECTOR_FLOAT4_H
-
-#include "Bullet3Common/b3Transform.h"
-
-//#define cross3(a,b) (a.cross(b))
-#define float4 b3Vector3
-//#define make_float4(x,y,z,w) b3Vector4(x,y,z,w)
-
-#endif //B3_VECTOR_FLOAT4_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
deleted file mode 100644
index 8b0a834efe..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.cpp
+++ /dev/null
@@ -1,574 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
- Elsevier CDROM license agreements grants nonexclusive license to use the software
- for any purpose, commercial or non-commercial as long as the following credit is included
- identifying the original source of the software:
-
- Parts of the source are "from the book Real-Time Collision Detection by
- Christer Ericson, published by Morgan Kaufmann Publishers,
- (c) 2005 Elsevier Inc."
-
-*/
-
-#include "b3VoronoiSimplexSolver.h"
-
-#define VERTA 0
-#define VERTB 1
-#define VERTC 2
-#define VERTD 3
-
-#define B3_CATCH_DEGENERATE_TETRAHEDRON 1
-void b3VoronoiSimplexSolver::removeVertex(int index)
-{
- b3Assert(m_numVertices > 0);
- m_numVertices--;
- m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
- m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
- m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
-}
-
-void b3VoronoiSimplexSolver::reduceVertices(const b3UsageBitfield& usedVerts)
-{
- if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
- removeVertex(3);
-
- if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
- removeVertex(2);
-
- if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
- removeVertex(1);
-
- if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
- removeVertex(0);
-}
-
-//clear the simplex, remove all the vertices
-void b3VoronoiSimplexSolver::reset()
-{
- m_cachedValidClosest = false;
- m_numVertices = 0;
- m_needsUpdate = true;
- m_lastW = b3MakeVector3(b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT), b3Scalar(B3_LARGE_FLOAT));
- m_cachedBC.reset();
-}
-
-//add a vertex
-void b3VoronoiSimplexSolver::addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q)
-{
- m_lastW = w;
- m_needsUpdate = true;
-
- m_simplexVectorW[m_numVertices] = w;
- m_simplexPointsP[m_numVertices] = p;
- m_simplexPointsQ[m_numVertices] = q;
-
- m_numVertices++;
-}
-
-bool b3VoronoiSimplexSolver::updateClosestVectorAndPoints()
-{
- if (m_needsUpdate)
- {
- m_cachedBC.reset();
-
- m_needsUpdate = false;
-
- switch (numVertices())
- {
- case 0:
- m_cachedValidClosest = false;
- break;
- case 1:
- {
- m_cachedP1 = m_simplexPointsP[0];
- m_cachedP2 = m_simplexPointsQ[0];
- m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
- m_cachedBC.reset();
- m_cachedBC.setBarycentricCoordinates(b3Scalar(1.), b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
- };
- case 2:
- {
- //closest point origin from line segment
- const b3Vector3& from = m_simplexVectorW[0];
- const b3Vector3& to = m_simplexVectorW[1];
- b3Vector3 nearest;
-
- b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- b3Vector3 diff = p - from;
- b3Vector3 v = to - from;
- b3Scalar t = v.dot(diff);
-
- if (t > 0)
- {
- b3Scalar dotVV = v.dot(v);
- if (t < dotVV)
- {
- t /= dotVV;
- diff -= t * v;
- m_cachedBC.m_usedVertices.usedVertexA = true;
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- else
- {
- t = 1;
- diff -= v;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- }
- else
- {
- t = 0;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexA = true;
- }
- m_cachedBC.setBarycentricCoordinates(1 - t, t);
- nearest = from + t * v;
-
- m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
- m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
-
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
- }
- case 3:
- {
- //closest point origin from triangle
- b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
-
- const b3Vector3& a = m_simplexVectorW[0];
- const b3Vector3& b = m_simplexVectorW[1];
- const b3Vector3& c = m_simplexVectorW[2];
-
- closestPtPointTriangle(p, a, b, c, m_cachedBC);
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
-
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
-
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
- m_cachedValidClosest = m_cachedBC.isValid();
-
- break;
- }
- case 4:
- {
- b3Vector3 p = b3MakeVector3(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
-
- const b3Vector3& a = m_simplexVectorW[0];
- const b3Vector3& b = m_simplexVectorW[1];
- const b3Vector3& c = m_simplexVectorW[2];
- const b3Vector3& d = m_simplexVectorW[3];
-
- bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
-
- if (hasSeparation)
- {
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
-
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
-
- m_cachedV = m_cachedP1 - m_cachedP2;
- reduceVertices(m_cachedBC.m_usedVertices);
- }
- else
- {
- // printf("sub distance got penetration\n");
-
- if (m_cachedBC.m_degenerate)
- {
- m_cachedValidClosest = false;
- }
- else
- {
- m_cachedValidClosest = true;
- //degenerate case == false, penetration = true + zero
- m_cachedV.setValue(b3Scalar(0.), b3Scalar(0.), b3Scalar(0.));
- }
- break;
- }
-
- m_cachedValidClosest = m_cachedBC.isValid();
-
- //closest point origin from tetrahedron
- break;
- }
- default:
- {
- m_cachedValidClosest = false;
- }
- };
- }
-
- return m_cachedValidClosest;
-}
-
-//return/calculate the closest vertex
-bool b3VoronoiSimplexSolver::closest(b3Vector3& v)
-{
- bool succes = updateClosestVectorAndPoints();
- v = m_cachedV;
- return succes;
-}
-
-b3Scalar b3VoronoiSimplexSolver::maxVertex()
-{
- int i, numverts = numVertices();
- b3Scalar maxV = b3Scalar(0.);
- for (i = 0; i < numverts; i++)
- {
- b3Scalar curLen2 = m_simplexVectorW[i].length2();
- if (maxV < curLen2)
- maxV = curLen2;
- }
- return maxV;
-}
-
-//return the current simplex
-int b3VoronoiSimplexSolver::getSimplex(b3Vector3* pBuf, b3Vector3* qBuf, b3Vector3* yBuf) const
-{
- int i;
- for (i = 0; i < numVertices(); i++)
- {
- yBuf[i] = m_simplexVectorW[i];
- pBuf[i] = m_simplexPointsP[i];
- qBuf[i] = m_simplexPointsQ[i];
- }
- return numVertices();
-}
-
-bool b3VoronoiSimplexSolver::inSimplex(const b3Vector3& w)
-{
- bool found = false;
- int i, numverts = numVertices();
- //b3Scalar maxV = b3Scalar(0.);
-
- //w is in the current (reduced) simplex
- for (i = 0; i < numverts; i++)
- {
-#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
- if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
-#else
- if (m_simplexVectorW[i] == w)
-#endif
- found = true;
- }
-
- //check in case lastW is already removed
- if (w == m_lastW)
- return true;
-
- return found;
-}
-
-void b3VoronoiSimplexSolver::backup_closest(b3Vector3& v)
-{
- v = m_cachedV;
-}
-
-bool b3VoronoiSimplexSolver::emptySimplex() const
-{
- return (numVertices() == 0);
-}
-
-void b3VoronoiSimplexSolver::compute_points(b3Vector3& p1, b3Vector3& p2)
-{
- updateClosestVectorAndPoints();
- p1 = m_cachedP1;
- p2 = m_cachedP2;
-}
-
-bool b3VoronoiSimplexSolver::closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result)
-{
- result.m_usedVertices.reset();
-
- // Check if P in vertex region outside A
- b3Vector3 ab = b - a;
- b3Vector3 ac = c - a;
- b3Vector3 ap = p - a;
- b3Scalar d1 = ab.dot(ap);
- b3Scalar d2 = ac.dot(ap);
- if (d1 <= b3Scalar(0.0) && d2 <= b3Scalar(0.0))
- {
- result.m_closestPointOnSimplex = a;
- result.m_usedVertices.usedVertexA = true;
- result.setBarycentricCoordinates(1, 0, 0);
- return true; // a; // barycentric coordinates (1,0,0)
- }
-
- // Check if P in vertex region outside B
- b3Vector3 bp = p - b;
- b3Scalar d3 = ab.dot(bp);
- b3Scalar d4 = ac.dot(bp);
- if (d3 >= b3Scalar(0.0) && d4 <= d3)
- {
- result.m_closestPointOnSimplex = b;
- result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(0, 1, 0);
-
- return true; // b; // barycentric coordinates (0,1,0)
- }
- // Check if P in edge region of AB, if so return projection of P onto AB
- b3Scalar vc = d1 * d4 - d3 * d2;
- if (vc <= b3Scalar(0.0) && d1 >= b3Scalar(0.0) && d3 <= b3Scalar(0.0))
- {
- b3Scalar v = d1 / (d1 - d3);
- result.m_closestPointOnSimplex = a + v * ab;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(1 - v, v, 0);
- return true;
- //return a + v * ab; // barycentric coordinates (1-v,v,0)
- }
-
- // Check if P in vertex region outside C
- b3Vector3 cp = p - c;
- b3Scalar d5 = ab.dot(cp);
- b3Scalar d6 = ac.dot(cp);
- if (d6 >= b3Scalar(0.0) && d5 <= d6)
- {
- result.m_closestPointOnSimplex = c;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0, 0, 1);
- return true; //c; // barycentric coordinates (0,0,1)
- }
-
- // Check if P in edge region of AC, if so return projection of P onto AC
- b3Scalar vb = d5 * d2 - d1 * d6;
- if (vb <= b3Scalar(0.0) && d2 >= b3Scalar(0.0) && d6 <= b3Scalar(0.0))
- {
- b3Scalar w = d2 / (d2 - d6);
- result.m_closestPointOnSimplex = a + w * ac;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1 - w, 0, w);
- return true;
- //return a + w * ac; // barycentric coordinates (1-w,0,w)
- }
-
- // Check if P in edge region of BC, if so return projection of P onto BC
- b3Scalar va = d3 * d6 - d5 * d4;
- if (va <= b3Scalar(0.0) && (d4 - d3) >= b3Scalar(0.0) && (d5 - d6) >= b3Scalar(0.0))
- {
- b3Scalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
-
- result.m_closestPointOnSimplex = b + w * (c - b);
- result.m_usedVertices.usedVertexB = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0, 1 - w, w);
- return true;
- // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
- }
-
- // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
- b3Scalar denom = b3Scalar(1.0) / (va + vb + vc);
- b3Scalar v = vb * denom;
- b3Scalar w = vc * denom;
-
- result.m_closestPointOnSimplex = a + ab * v + ac * w;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexB = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1 - v - w, v, w);
-
- return true;
- // return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = b3Scalar(1.0) - v - w
-}
-
-/// Test if point p and d lie on opposite sides of plane through abc
-int b3VoronoiSimplexSolver::pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d)
-{
- b3Vector3 normal = (b - a).cross(c - a);
-
- b3Scalar signp = (p - a).dot(normal); // [AP AB AC]
- b3Scalar signd = (d - a).dot(normal); // [AD AB AC]
-
-#ifdef B3_CATCH_DEGENERATE_TETRAHEDRON
-#ifdef BT_USE_DOUBLE_PRECISION
- if (signd * signd < (b3Scalar(1e-8) * b3Scalar(1e-8)))
- {
- return -1;
- }
-#else
- if (signd * signd < (b3Scalar(1e-4) * b3Scalar(1e-4)))
- {
- // printf("affine dependent/degenerate\n");//
- return -1;
- }
-#endif
-
-#endif
- // Points on opposite sides if expression signs are opposite
- return signp * signd < b3Scalar(0.);
-}
-
-bool b3VoronoiSimplexSolver::closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult)
-{
- b3SubSimplexClosestResult tempResult;
-
- // Start out assuming point inside all halfspaces, so closest to itself
- finalResult.m_closestPointOnSimplex = p;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = true;
- finalResult.m_usedVertices.usedVertexB = true;
- finalResult.m_usedVertices.usedVertexC = true;
- finalResult.m_usedVertices.usedVertexD = true;
-
- int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
- int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
- int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
- int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
-
- if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
- {
- finalResult.m_degenerate = true;
- return false;
- }
-
- if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
- {
- return false;
- }
-
- b3Scalar bestSqDist = FLT_MAX;
- // If point outside face abc then compute closest point on abc
- if (pointOutsideABC)
- {
- closestPtPointTriangle(p, a, b, c, tempResult);
- b3Vector3 q = tempResult.m_closestPointOnSimplex;
-
- b3Scalar sqDist = (q - p).dot(q - p);
- // Update best closest point if (squared) distance is less than current best
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- //convert result bitmask!
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC],
- 0);
- }
- }
-
- // Repeat test for face acd
- if (pointOutsideACD)
- {
- closestPtPointTriangle(p, a, c, d, tempResult);
- b3Vector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
-
- b3Scalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
-
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- 0,
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC]);
- }
- }
- // Repeat test for face adb
-
- if (pointOutsideADB)
- {
- closestPtPointTriangle(p, a, d, b, tempResult);
- b3Vector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
-
- b3Scalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
-
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- 0,
- tempResult.m_barycentricCoords[VERTB]);
- }
- }
- // Repeat test for face bdc
-
- if (pointOutsideBDC)
- {
- closestPtPointTriangle(p, b, d, c, tempResult);
- b3Vector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
- b3Scalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- //
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
-
- finalResult.setBarycentricCoordinates(
- 0,
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- tempResult.m_barycentricCoords[VERTB]);
- }
- }
-
- //help! we ended up full !
-
- if (finalResult.m_usedVertices.usedVertexA &&
- finalResult.m_usedVertices.usedVertexB &&
- finalResult.m_usedVertices.usedVertexC &&
- finalResult.m_usedVertices.usedVertexD)
- {
- return true;
- }
-
- return true;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
deleted file mode 100644
index b40b169978..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/b3VoronoiSimplexSolver.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_VORONOI_SIMPLEX_SOLVER_H
-#define B3_VORONOI_SIMPLEX_SOLVER_H
-
-#include "Bullet3Common/b3Vector3.h"
-
-#define VORONOI_SIMPLEX_MAX_VERTS 5
-
-///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
-//#define BT_USE_EQUAL_VERTEX_THRESHOLD
-#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
-
-struct b3UsageBitfield
-{
- b3UsageBitfield()
- {
- reset();
- }
-
- void reset()
- {
- usedVertexA = false;
- usedVertexB = false;
- usedVertexC = false;
- usedVertexD = false;
- }
- unsigned short usedVertexA : 1;
- unsigned short usedVertexB : 1;
- unsigned short usedVertexC : 1;
- unsigned short usedVertexD : 1;
- unsigned short unused1 : 1;
- unsigned short unused2 : 1;
- unsigned short unused3 : 1;
- unsigned short unused4 : 1;
-};
-
-struct b3SubSimplexClosestResult
-{
- b3Vector3 m_closestPointOnSimplex;
- //MASK for m_usedVertices
- //stores the simplex vertex-usage, using the MASK,
- // if m_usedVertices & MASK then the related vertex is used
- b3UsageBitfield m_usedVertices;
- b3Scalar m_barycentricCoords[4];
- bool m_degenerate;
-
- void reset()
- {
- m_degenerate = false;
- setBarycentricCoordinates();
- m_usedVertices.reset();
- }
- bool isValid()
- {
- bool valid = (m_barycentricCoords[0] >= b3Scalar(0.)) &&
- (m_barycentricCoords[1] >= b3Scalar(0.)) &&
- (m_barycentricCoords[2] >= b3Scalar(0.)) &&
- (m_barycentricCoords[3] >= b3Scalar(0.));
-
- return valid;
- }
- void setBarycentricCoordinates(b3Scalar a = b3Scalar(0.), b3Scalar b = b3Scalar(0.), b3Scalar c = b3Scalar(0.), b3Scalar d = b3Scalar(0.))
- {
- m_barycentricCoords[0] = a;
- m_barycentricCoords[1] = b;
- m_barycentricCoords[2] = c;
- m_barycentricCoords[3] = d;
- }
-};
-
-/// b3VoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
-/// Can be used with GJK, as an alternative to Johnson distance algorithm.
-
-B3_ATTRIBUTE_ALIGNED16(class)
-b3VoronoiSimplexSolver
-{
-public:
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_numVertices;
-
- b3Vector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
- b3Vector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
- b3Vector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
-
- b3Vector3 m_cachedP1;
- b3Vector3 m_cachedP2;
- b3Vector3 m_cachedV;
- b3Vector3 m_lastW;
-
- b3Scalar m_equalVertexThreshold;
- bool m_cachedValidClosest;
-
- b3SubSimplexClosestResult m_cachedBC;
-
- bool m_needsUpdate;
-
- void removeVertex(int index);
- void reduceVertices(const b3UsageBitfield& usedVerts);
- bool updateClosestVectorAndPoints();
-
- bool closestPtPointTetrahedron(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d, b3SubSimplexClosestResult& finalResult);
- int pointOutsideOfPlane(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, const b3Vector3& d);
- bool closestPtPointTriangle(const b3Vector3& p, const b3Vector3& a, const b3Vector3& b, const b3Vector3& c, b3SubSimplexClosestResult& result);
-
-public:
- b3VoronoiSimplexSolver()
- : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
- {
- }
- void reset();
-
- void addVertex(const b3Vector3& w, const b3Vector3& p, const b3Vector3& q);
-
- void setEqualVertexThreshold(b3Scalar threshold)
- {
- m_equalVertexThreshold = threshold;
- }
-
- b3Scalar getEqualVertexThreshold() const
- {
- return m_equalVertexThreshold;
- }
-
- bool closest(b3Vector3 & v);
-
- b3Scalar maxVertex();
-
- bool fullSimplex() const
- {
- return (m_numVertices == 4);
- }
-
- int getSimplex(b3Vector3 * pBuf, b3Vector3 * qBuf, b3Vector3 * yBuf) const;
-
- bool inSimplex(const b3Vector3& w);
-
- void backup_closest(b3Vector3 & v);
-
- bool emptySimplex() const;
-
- void compute_points(b3Vector3 & p1, b3Vector3 & p2);
-
- int numVertices() const
- {
- return m_numVertices;
- }
-};
-
-#endif //B3_VORONOI_SIMPLEX_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl
deleted file mode 100644
index faa413441c..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.cl
+++ /dev/null
@@ -1,283 +0,0 @@
-//keep this enum in sync with the CPU version (in btCollidable.h)
-//written by Erwin Coumans
-
-#define SHAPE_CONVEX_HULL 3
-#define SHAPE_CONCAVE_TRIMESH 5
-#define TRIANGLE_NUM_CONVEX_FACES 5
-#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
-#define SHAPE_SPHERE 7
-
-typedef unsigned int u32;
-
-#define MAX_NUM_PARTS_IN_BITS 10
-
-///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrTriangleIndex;
-} btQuantizedBvhNode;
-
-typedef struct
-{
- float4 m_aabbMin;
- float4 m_aabbMax;
- float4 m_quantization;
- int m_numNodes;
- int m_numSubTrees;
- int m_nodeOffset;
- int m_subTreeOffset;
-
-} b3BvhInfo;
-
-int getTriangleIndex(const btQuantizedBvhNode* rootNode)
-{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
-}
-
-int isLeaf(const btQuantizedBvhNode* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
-}
-
-int getEscapeIndex(const btQuantizedBvhNode* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
- //4 bytes
- int m_subtreeSize;
- int m_padding[3];
-} btBvhSubtreeInfo;
-
-///keep this in sync with btCollidable.h
-typedef struct
-{
- int m_numChildShapes;
- int blaat2;
- int m_shapeType;
- int m_shapeIndex;
-
-} btCollidableGpu;
-
-typedef struct
-{
- float4 m_childPosition;
- float4 m_childOrientation;
- int m_shapeIndex;
- int m_unused0;
- int m_unused1;
- int m_unused2;
-} btGpuChildShape;
-
-
-typedef struct
-{
- float4 m_pos;
- float4 m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} BodyData;
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} btAabbCL;
-
-
-int testQuantizedAabbAgainstQuantizedAabb(
- const unsigned short int* aabbMin1,
- const unsigned short int* aabbMax1,
- const unsigned short int* aabbMin2,
- const unsigned short int* aabbMax2)
-{
- //int overlap = 1;
- if (aabbMin1[0] > aabbMax2[0])
- return 0;
- if (aabbMax1[0] < aabbMin2[0])
- return 0;
- if (aabbMin1[1] > aabbMax2[1])
- return 0;
- if (aabbMax1[1] < aabbMin2[1])
- return 0;
- if (aabbMin1[2] > aabbMax2[2])
- return 0;
- if (aabbMax1[2] < aabbMin2[2])
- return 0;
- return 1;
- //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;
- //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;
- //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;
- //return overlap;
-}
-
-
-void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)
-{
- float4 clampedPoint = max(point2,bvhAabbMin);
- clampedPoint = min (clampedPoint, bvhAabbMax);
-
- float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;
- if (isMax)
- {
- out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));
- out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));
- out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));
- } else
- {
- out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));
- out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));
- out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));
- }
-
-}
-
-
-// work-in-progress
-__kernel void bvhTraversalKernel( __global const int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global btAabbCL* aabbs,
- __global int4* concavePairsOut,
- __global volatile int* numConcavePairsOut,
- __global const btBvhSubtreeInfo* subtreeHeadersRoot,
- __global const btQuantizedBvhNode* quantizedNodesRoot,
- __global const b3BvhInfo* bvhInfos,
- int numPairs,
- int maxNumConcavePairsCapacity)
-{
- int id = get_global_id(0);
- if (id>=numPairs)
- return;
-
- int bodyIndexA = pairs[id].x;
- int bodyIndexB = pairs[id].y;
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
- {
- return;
- }
-
- if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
- return;
-
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
- if (shapeTypeB!=SHAPE_CONVEX_HULL &&
- shapeTypeB!=SHAPE_SPHERE &&
- shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS
- )
- return;
-
- b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];
-
- float4 bvhAabbMin = bvhInfo.m_aabbMin;
- float4 bvhAabbMax = bvhInfo.m_aabbMax;
- float4 bvhQuantization = bvhInfo.m_quantization;
- int numSubtreeHeaders = bvhInfo.m_numSubTrees;
- __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];
- __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];
-
-
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);
- quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);
-
- for (int i=0;i<numSubtreeHeaders;i++)
- {
- btBvhSubtreeInfo subtree = subtreeHeaders[i];
-
- int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- int startNodeIndex = subtree.m_rootNodeIndex;
- int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;
- int curIndex = startNodeIndex;
- int escapeIndex;
- int isLeafNode;
- int aabbOverlap;
- while (curIndex < endNodeIndex)
- {
- btQuantizedBvhNode rootNode = quantizedNodes[curIndex];
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);
- isLeafNode = isLeaf(&rootNode);
- if (aabbOverlap)
- {
- if (isLeafNode)
- {
- int triangleIndex = getTriangleIndex(&rootNode);
- if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);
- for (int b=0;b<numChildrenB;b++)
- {
- if ((pairIdx+b)<maxNumConcavePairsCapacity)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
- int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);
- concavePairsOut[pairIdx+b] = newPair;
- }
- }
- } else
- {
- int pairIdx = atomic_inc(numConcavePairsOut);
- if (pairIdx<maxNumConcavePairsCapacity)
- {
- int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);
- concavePairsOut[pairIdx] = newPair;
- }
- }
- }
- curIndex++;
- } else
- {
- if (isLeafNode)
- {
- curIndex++;
- } else
- {
- escapeIndex = getEscapeIndex(&rootNode);
- curIndex += escapeIndex;
- }
- }
- }
- }
- }
-
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
deleted file mode 100644
index f1df8a6970..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/bvhTraversal.h
+++ /dev/null
@@ -1,257 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* bvhTraversalKernelCL =
- "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
- "//written by Erwin Coumans\n"
- "#define SHAPE_CONVEX_HULL 3\n"
- "#define SHAPE_CONCAVE_TRIMESH 5\n"
- "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
- "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
- "#define SHAPE_SPHERE 7\n"
- "typedef unsigned int u32;\n"
- "#define MAX_NUM_PARTS_IN_BITS 10\n"
- "///btQuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
- "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes\n"
- " int m_escapeIndexOrTriangleIndex;\n"
- "} btQuantizedBvhNode;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_aabbMin;\n"
- " float4 m_aabbMax;\n"
- " float4 m_quantization;\n"
- " int m_numNodes;\n"
- " int m_numSubTrees;\n"
- " int m_nodeOffset;\n"
- " int m_subTreeOffset;\n"
- "} b3BvhInfo;\n"
- "int getTriangleIndex(const btQuantizedBvhNode* rootNode)\n"
- "{\n"
- " unsigned int x=0;\n"
- " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
- " // Get only the lower bits where the triangle index is stored\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
- "}\n"
- "int isLeaf(const btQuantizedBvhNode* rootNode)\n"
- "{\n"
- " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
- "}\n"
- " \n"
- "int getEscapeIndex(const btQuantizedBvhNode* rootNode)\n"
- "{\n"
- " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes, points to the root of the subtree\n"
- " int m_rootNodeIndex;\n"
- " //4 bytes\n"
- " int m_subtreeSize;\n"
- " int m_padding[3];\n"
- "} btBvhSubtreeInfo;\n"
- "///keep this in sync with btCollidable.h\n"
- "typedef struct\n"
- "{\n"
- " int m_numChildShapes;\n"
- " int blaat2;\n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- " \n"
- "} btCollidableGpu;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_childPosition;\n"
- " float4 m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "} btGpuChildShape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " float4 m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} BodyData;\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} btAabbCL;\n"
- "int testQuantizedAabbAgainstQuantizedAabb(\n"
- " const unsigned short int* aabbMin1,\n"
- " const unsigned short int* aabbMax1,\n"
- " const unsigned short int* aabbMin2,\n"
- " const unsigned short int* aabbMax2)\n"
- "{\n"
- " //int overlap = 1;\n"
- " if (aabbMin1[0] > aabbMax2[0])\n"
- " return 0;\n"
- " if (aabbMax1[0] < aabbMin2[0])\n"
- " return 0;\n"
- " if (aabbMin1[1] > aabbMax2[1])\n"
- " return 0;\n"
- " if (aabbMax1[1] < aabbMin2[1])\n"
- " return 0;\n"
- " if (aabbMin1[2] > aabbMax2[2])\n"
- " return 0;\n"
- " if (aabbMax1[2] < aabbMin2[2])\n"
- " return 0;\n"
- " return 1;\n"
- " //overlap = ((aabbMin1[0] > aabbMax2[0]) || (aabbMax1[0] < aabbMin2[0])) ? 0 : overlap;\n"
- " //overlap = ((aabbMin1[2] > aabbMax2[2]) || (aabbMax1[2] < aabbMin2[2])) ? 0 : overlap;\n"
- " //overlap = ((aabbMin1[1] > aabbMax2[1]) || (aabbMax1[1] < aabbMin2[1])) ? 0 : overlap;\n"
- " //return overlap;\n"
- "}\n"
- "void quantizeWithClamp(unsigned short* out, float4 point2,int isMax, float4 bvhAabbMin, float4 bvhAabbMax, float4 bvhQuantization)\n"
- "{\n"
- " float4 clampedPoint = max(point2,bvhAabbMin);\n"
- " clampedPoint = min (clampedPoint, bvhAabbMax);\n"
- " float4 v = (clampedPoint - bvhAabbMin) * bvhQuantization;\n"
- " if (isMax)\n"
- " {\n"
- " out[0] = (unsigned short) (((unsigned short)(v.x+1.f) | 1));\n"
- " out[1] = (unsigned short) (((unsigned short)(v.y+1.f) | 1));\n"
- " out[2] = (unsigned short) (((unsigned short)(v.z+1.f) | 1));\n"
- " } else\n"
- " {\n"
- " out[0] = (unsigned short) (((unsigned short)(v.x) & 0xfffe));\n"
- " out[1] = (unsigned short) (((unsigned short)(v.y) & 0xfffe));\n"
- " out[2] = (unsigned short) (((unsigned short)(v.z) & 0xfffe));\n"
- " }\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void bvhTraversalKernel( __global const int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global btAabbCL* aabbs,\n"
- " __global int4* concavePairsOut,\n"
- " __global volatile int* numConcavePairsOut,\n"
- " __global const btBvhSubtreeInfo* subtreeHeadersRoot,\n"
- " __global const btQuantizedBvhNode* quantizedNodesRoot,\n"
- " __global const b3BvhInfo* bvhInfos,\n"
- " int numPairs,\n"
- " int maxNumConcavePairsCapacity)\n"
- "{\n"
- " int id = get_global_id(0);\n"
- " if (id>=numPairs)\n"
- " return;\n"
- " \n"
- " int bodyIndexA = pairs[id].x;\n"
- " int bodyIndexB = pairs[id].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " //once the broadphase avoids static-static pairs, we can remove this test\n"
- " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
- " {\n"
- " return;\n"
- " }\n"
- " \n"
- " if (collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)\n"
- " return;\n"
- " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
- " \n"
- " if (shapeTypeB!=SHAPE_CONVEX_HULL &&\n"
- " shapeTypeB!=SHAPE_SPHERE &&\n"
- " shapeTypeB!=SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
- " )\n"
- " return;\n"
- " b3BvhInfo bvhInfo = bvhInfos[collidables[collidableIndexA].m_numChildShapes];\n"
- " float4 bvhAabbMin = bvhInfo.m_aabbMin;\n"
- " float4 bvhAabbMax = bvhInfo.m_aabbMax;\n"
- " float4 bvhQuantization = bvhInfo.m_quantization;\n"
- " int numSubtreeHeaders = bvhInfo.m_numSubTrees;\n"
- " __global const btBvhSubtreeInfo* subtreeHeaders = &subtreeHeadersRoot[bvhInfo.m_subTreeOffset];\n"
- " __global const btQuantizedBvhNode* quantizedNodes = &quantizedNodesRoot[bvhInfo.m_nodeOffset];\n"
- " \n"
- " unsigned short int quantizedQueryAabbMin[3];\n"
- " unsigned short int quantizedQueryAabbMax[3];\n"
- " quantizeWithClamp(quantizedQueryAabbMin,aabbs[bodyIndexB].m_min,false,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
- " quantizeWithClamp(quantizedQueryAabbMax,aabbs[bodyIndexB].m_max,true ,bvhAabbMin, bvhAabbMax,bvhQuantization);\n"
- " \n"
- " for (int i=0;i<numSubtreeHeaders;i++)\n"
- " {\n"
- " btBvhSubtreeInfo subtree = subtreeHeaders[i];\n"
- " \n"
- " int overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);\n"
- " if (overlap != 0)\n"
- " {\n"
- " int startNodeIndex = subtree.m_rootNodeIndex;\n"
- " int endNodeIndex = subtree.m_rootNodeIndex+subtree.m_subtreeSize;\n"
- " int curIndex = startNodeIndex;\n"
- " int escapeIndex;\n"
- " int isLeafNode;\n"
- " int aabbOverlap;\n"
- " while (curIndex < endNodeIndex)\n"
- " {\n"
- " btQuantizedBvhNode rootNode = quantizedNodes[curIndex];\n"
- " aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode.m_quantizedAabbMin,rootNode.m_quantizedAabbMax);\n"
- " isLeafNode = isLeaf(&rootNode);\n"
- " if (aabbOverlap)\n"
- " {\n"
- " if (isLeafNode)\n"
- " {\n"
- " int triangleIndex = getTriangleIndex(&rootNode);\n"
- " if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
- " int pairIdx = atomic_add(numConcavePairsOut,numChildrenB);\n"
- " for (int b=0;b<numChildrenB;b++)\n"
- " {\n"
- " if ((pairIdx+b)<maxNumConcavePairsCapacity)\n"
- " {\n"
- " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
- " int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,childShapeIndexB);\n"
- " concavePairsOut[pairIdx+b] = newPair;\n"
- " }\n"
- " }\n"
- " } else\n"
- " {\n"
- " int pairIdx = atomic_inc(numConcavePairsOut);\n"
- " if (pairIdx<maxNumConcavePairsCapacity)\n"
- " {\n"
- " int4 newPair = (int4)(bodyIndexA,bodyIndexB,triangleIndex,0);\n"
- " concavePairsOut[pairIdx] = newPair;\n"
- " }\n"
- " }\n"
- " } \n"
- " curIndex++;\n"
- " } else\n"
- " {\n"
- " if (isLeafNode)\n"
- " {\n"
- " curIndex++;\n"
- " } else\n"
- " {\n"
- " escapeIndex = getEscapeIndex(&rootNode);\n"
- " curIndex += escapeIndex;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl
deleted file mode 100644
index e754f4e1da..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mpr.cl
+++ /dev/null
@@ -1,311 +0,0 @@
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3MprPenetration.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#define AppendInc(x, out) out = atomic_inc(x)
-#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
-#ifdef cl_ext_atomic_counters_32
- #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
- #define counter32_t volatile __global int*
-#endif
-
-
-__kernel void mprPenetrationKernel( __global int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global float4* separatingNormals,
- __global int* hasSeparatingAxis,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int contactCapacity,
- int numPairs)
-{
- int i = get_global_id(0);
- int pairIndex = i;
- if (i<numPairs)
- {
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
- {
- return;
- }
-
-
- if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
- {
- return;
- }
-
- float depthOut;
- b3Float4 dirOut;
- b3Float4 posOut;
-
-
- int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);
-
-
-
-
-
- if (res==0)
- {
- //add a contact
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
- if (dstIdx<contactCapacity)
- {
- pairs[pairIndex].z = dstIdx;
- __global struct b3Contact4Data* c = globalContactsOut + dstIdx;
- c->m_worldNormalOnB = -dirOut;//normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
- //for (int i=0;i<nContacts;i++)
- posOut.w = -depthOut;
- c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];
- GET_NPOINTS(*c) = 1;//nContacts;
- }
- }
-
- }
-}
-
-typedef float4 Quaternion;
-#define make_float4 (float4)
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
-{
- return qtRotate( *orientation, *p ) + (*translation);
-}
-
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-
-inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn,
-const float4* dir, __global const float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const float4 localDir = qtInvRotate(orn,*dir);
- float offset = dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
- {
- float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
- min[0] = dp;
- if(dp > max[0])
- max[0] = dp;
- }
- if(min[0]>max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-
-bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* vertices,
- __global const float4* unitSphereDirections,
- int numUnitSphereDirections,
- float4* sep,
- float* dmin)
-{
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test unit sphere directions
- for (int i=0;i<numUnitSphereDirections;i++)
- {
-
- float4 crossje;
- crossje = unitSphereDirections[i];
-
- if (dot3F4(DeltaC2,crossje)>0)
- crossje *= -1.f;
- {
- float dist;
- bool result = true;
- float Min0,Max0;
- float Min1,Max1;
- project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
- project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
- result = true;
-
- if(dist<*dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-
-__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global const float4* unitSphereDirections,
- __global float4* separatingNormals,
- __global int* hasSeparatingAxis,
- __global float* dmins,
- int numUnitSphereDirections,
- int numPairs
- )
-{
-
- int i = get_global_id(0);
-
- if (i<numPairs)
- {
-
- if (hasSeparatingAxis[i])
- {
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
-
- float dmin = dmins[i];
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal = separatingNormals[i];
-
- int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
- if (numEdgeEdgeDirections>numUnitSphereDirections)
- {
- bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);
- if (!sepEE)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- hasSeparatingAxis[i] = 1;
- separatingNormals[i] = sepNormal;
- }
- }
- } //if (hasSeparatingAxis[i])
- }//(i<numPairs)
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
deleted file mode 100644
index 74959a931c..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/mprKernels.h
+++ /dev/null
@@ -1,1445 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* mprKernelsCL =
- "/***\n"
- " * ---------------------------------\n"
- " * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>\n"
- " *\n"
- " * This file was ported from mpr.c file, part of libccd.\n"
- " * The Minkoski Portal Refinement implementation was ported \n"
- " * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.\n"
- " * at http://github.com/erwincoumans/bullet3\n"
- " *\n"
- " * Distributed under the OSI-approved BSD License (the \"License\");\n"
- " * see <http://www.opensource.org/licenses/bsd-license.php>.\n"
- " * This software is distributed WITHOUT ANY WARRANTY; without even the\n"
- " * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
- " * See the License for more information.\n"
- " */\n"
- "#ifndef B3_MPR_PENETRATION_H\n"
- "#define B3_MPR_PENETRATION_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#define B3_RIGIDBODY_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
- "struct b3RigidBodyData\n"
- "{\n"
- " b3Float4 m_pos;\n"
- " b3Quat m_quat;\n"
- " b3Float4 m_linVel;\n"
- " b3Float4 m_angVel;\n"
- " int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "};\n"
- "typedef struct b3InertiaData b3InertiaData_t;\n"
- "struct b3InertiaData\n"
- "{\n"
- " b3Mat3x3 m_invInertiaWorld;\n"
- " b3Mat3x3 m_initInvInertia;\n"
- "};\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "typedef struct b3GpuFace b3GpuFace_t;\n"
- "struct b3GpuFace\n"
- "{\n"
- " b3Float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- " int m_unusedPadding1;\n"
- " int m_unusedPadding2;\n"
- "};\n"
- "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
- "struct b3ConvexPolyhedronData\n"
- "{\n"
- " b3Float4 m_localCenter;\n"
- " b3Float4 m_extents;\n"
- " b3Float4 mC;\n"
- " b3Float4 mE;\n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "};\n"
- "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#ifndef B3_COLLIDABLE_H\n"
- "#define B3_COLLIDABLE_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "enum b3ShapeTypes\n"
- "{\n"
- " SHAPE_HEIGHT_FIELD=1,\n"
- " SHAPE_CONVEX_HULL=3,\n"
- " SHAPE_PLANE=4,\n"
- " SHAPE_CONCAVE_TRIMESH=5,\n"
- " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
- " SHAPE_SPHERE=7,\n"
- " MAX_NUM_SHAPE_TYPES,\n"
- "};\n"
- "typedef struct b3Collidable b3Collidable_t;\n"
- "struct b3Collidable\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_radius;\n"
- " int m_compoundBvhIndex;\n"
- " };\n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- "};\n"
- "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
- "struct b3GpuChildShape\n"
- "{\n"
- " b3Float4 m_childPosition;\n"
- " b3Quat m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "struct b3CompoundOverlappingPair\n"
- "{\n"
- " int m_bodyIndexA;\n"
- " int m_bodyIndexB;\n"
- "// int m_pairType;\n"
- " int m_childShapeIndexA;\n"
- " int m_childShapeIndexB;\n"
- "};\n"
- "#endif //B3_COLLIDABLE_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#define B3_MPR_SQRT sqrt\n"
- "#endif\n"
- "#define B3_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))\n"
- "#define B3_MPR_FABS fabs\n"
- "#define B3_MPR_TOLERANCE 1E-6f\n"
- "#define B3_MPR_MAX_ITERATIONS 1000\n"
- "struct _b3MprSupport_t \n"
- "{\n"
- " b3Float4 v; //!< Support point in minkowski sum\n"
- " b3Float4 v1; //!< Support point in obj1\n"
- " b3Float4 v2; //!< Support point in obj2\n"
- "};\n"
- "typedef struct _b3MprSupport_t b3MprSupport_t;\n"
- "struct _b3MprSimplex_t \n"
- "{\n"
- " b3MprSupport_t ps[4];\n"
- " int last; //!< index of last added point\n"
- "};\n"
- "typedef struct _b3MprSimplex_t b3MprSimplex_t;\n"
- "inline b3MprSupport_t* b3MprSimplexPointW(b3MprSimplex_t *s, int idx)\n"
- "{\n"
- " return &s->ps[idx];\n"
- "}\n"
- "inline void b3MprSimplexSetSize(b3MprSimplex_t *s, int size)\n"
- "{\n"
- " s->last = size - 1;\n"
- "}\n"
- "inline int b3MprSimplexSize(const b3MprSimplex_t *s)\n"
- "{\n"
- " return s->last + 1;\n"
- "}\n"
- "inline const b3MprSupport_t* b3MprSimplexPoint(const b3MprSimplex_t* s, int idx)\n"
- "{\n"
- " // here is no check on boundaries\n"
- " return &s->ps[idx];\n"
- "}\n"
- "inline void b3MprSupportCopy(b3MprSupport_t *d, const b3MprSupport_t *s)\n"
- "{\n"
- " *d = *s;\n"
- "}\n"
- "inline void b3MprSimplexSet(b3MprSimplex_t *s, size_t pos, const b3MprSupport_t *a)\n"
- "{\n"
- " b3MprSupportCopy(s->ps + pos, a);\n"
- "}\n"
- "inline void b3MprSimplexSwap(b3MprSimplex_t *s, size_t pos1, size_t pos2)\n"
- "{\n"
- " b3MprSupport_t supp;\n"
- " b3MprSupportCopy(&supp, &s->ps[pos1]);\n"
- " b3MprSupportCopy(&s->ps[pos1], &s->ps[pos2]);\n"
- " b3MprSupportCopy(&s->ps[pos2], &supp);\n"
- "}\n"
- "inline int b3MprIsZero(float val)\n"
- "{\n"
- " return B3_MPR_FABS(val) < FLT_EPSILON;\n"
- "}\n"
- "inline int b3MprEq(float _a, float _b)\n"
- "{\n"
- " float ab;\n"
- " float a, b;\n"
- " ab = B3_MPR_FABS(_a - _b);\n"
- " if (B3_MPR_FABS(ab) < FLT_EPSILON)\n"
- " return 1;\n"
- " a = B3_MPR_FABS(_a);\n"
- " b = B3_MPR_FABS(_b);\n"
- " if (b > a){\n"
- " return ab < FLT_EPSILON * b;\n"
- " }else{\n"
- " return ab < FLT_EPSILON * a;\n"
- " }\n"
- "}\n"
- "inline int b3MprVec3Eq(const b3Float4* a, const b3Float4 *b)\n"
- "{\n"
- " return b3MprEq((*a).x, (*b).x)\n"
- " && b3MprEq((*a).y, (*b).y)\n"
- " && b3MprEq((*a).z, (*b).z);\n"
- "}\n"
- "inline b3Float4 b3LocalGetSupportVertex(b3Float4ConstArg supportVec,__global const b3ConvexPolyhedronData_t* hull, b3ConstArray(b3Float4) verticesA)\n"
- "{\n"
- " b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
- " float maxDot = -B3_LARGE_FLOAT;\n"
- " if( 0 < hull->m_numVertices )\n"
- " {\n"
- " const b3Float4 scaled = supportVec;\n"
- " int index = b3MaxDot(scaled, &verticesA[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
- " return verticesA[hull->m_vertexOffset+index];\n"
- " }\n"
- " return supVec;\n"
- "}\n"
- "B3_STATIC void b3MprConvexSupport(int pairIndex,int bodyIndex, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " const b3Float4* _dir, b3Float4* outp, int logme)\n"
- "{\n"
- " //dir is in worldspace, move to local space\n"
- " \n"
- " b3Float4 pos = cpuBodyBuf[bodyIndex].m_pos;\n"
- " b3Quat orn = cpuBodyBuf[bodyIndex].m_quat;\n"
- " \n"
- " b3Float4 dir = b3MakeFloat4((*_dir).x,(*_dir).y,(*_dir).z,0.f);\n"
- " \n"
- " const b3Float4 localDir = b3QuatRotate(b3QuatInverse(orn),dir);\n"
- " \n"
- " //find local support vertex\n"
- " int colIndex = cpuBodyBuf[bodyIndex].m_collidableIdx;\n"
- " \n"
- " b3Assert(cpuCollidables[colIndex].m_shapeType==SHAPE_CONVEX_HULL);\n"
- " __global const b3ConvexPolyhedronData_t* hull = &cpuConvexData[cpuCollidables[colIndex].m_shapeIndex];\n"
- " \n"
- " b3Float4 pInA;\n"
- " if (logme)\n"
- " {\n"
- " b3Float4 supVec = b3MakeFloat4(0,0,0,0);\n"
- " float maxDot = -B3_LARGE_FLOAT;\n"
- " if( 0 < hull->m_numVertices )\n"
- " {\n"
- " const b3Float4 scaled = localDir;\n"
- " int index = b3MaxDot(scaled, &cpuVertices[hull->m_vertexOffset], hull->m_numVertices, &maxDot);\n"
- " pInA = cpuVertices[hull->m_vertexOffset+index];\n"
- " \n"
- " }\n"
- " } else\n"
- " {\n"
- " pInA = b3LocalGetSupportVertex(localDir,hull,cpuVertices);\n"
- " }\n"
- " //move vertex to world space\n"
- " *outp = b3TransformPoint(pInA,pos,orn);\n"
- " \n"
- "}\n"
- "inline void b3MprSupport(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " const b3Float4* _dir, b3MprSupport_t *supp)\n"
- "{\n"
- " b3Float4 dir;\n"
- " dir = *_dir;\n"
- " b3MprConvexSupport(pairIndex,bodyIndexA,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v1,0);\n"
- " dir = *_dir*-1.f;\n"
- " b3MprConvexSupport(pairIndex,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,&dir, &supp->v2,0);\n"
- " supp->v = supp->v1 - supp->v2;\n"
- "}\n"
- "inline void b3FindOrigin(int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, b3MprSupport_t *center)\n"
- "{\n"
- " center->v1 = cpuBodyBuf[bodyIndexA].m_pos;\n"
- " center->v2 = cpuBodyBuf[bodyIndexB].m_pos;\n"
- " center->v = center->v1 - center->v2;\n"
- "}\n"
- "inline void b3MprVec3Set(b3Float4 *v, float x, float y, float z)\n"
- "{\n"
- " (*v).x = x;\n"
- " (*v).y = y;\n"
- " (*v).z = z;\n"
- " (*v).w = 0.f;\n"
- "}\n"
- "inline void b3MprVec3Add(b3Float4 *v, const b3Float4 *w)\n"
- "{\n"
- " (*v).x += (*w).x;\n"
- " (*v).y += (*w).y;\n"
- " (*v).z += (*w).z;\n"
- "}\n"
- "inline void b3MprVec3Copy(b3Float4 *v, const b3Float4 *w)\n"
- "{\n"
- " *v = *w;\n"
- "}\n"
- "inline void b3MprVec3Scale(b3Float4 *d, float k)\n"
- "{\n"
- " *d *= k;\n"
- "}\n"
- "inline float b3MprVec3Dot(const b3Float4 *a, const b3Float4 *b)\n"
- "{\n"
- " float dot;\n"
- " dot = b3Dot3F4(*a,*b);\n"
- " return dot;\n"
- "}\n"
- "inline float b3MprVec3Len2(const b3Float4 *v)\n"
- "{\n"
- " return b3MprVec3Dot(v, v);\n"
- "}\n"
- "inline void b3MprVec3Normalize(b3Float4 *d)\n"
- "{\n"
- " float k = 1.f / B3_MPR_SQRT(b3MprVec3Len2(d));\n"
- " b3MprVec3Scale(d, k);\n"
- "}\n"
- "inline void b3MprVec3Cross(b3Float4 *d, const b3Float4 *a, const b3Float4 *b)\n"
- "{\n"
- " *d = b3Cross3(*a,*b);\n"
- " \n"
- "}\n"
- "inline void b3MprVec3Sub2(b3Float4 *d, const b3Float4 *v, const b3Float4 *w)\n"
- "{\n"
- " *d = *v - *w;\n"
- "}\n"
- "inline void b3PortalDir(const b3MprSimplex_t *portal, b3Float4 *dir)\n"
- "{\n"
- " b3Float4 v2v1, v3v1;\n"
- " b3MprVec3Sub2(&v2v1, &b3MprSimplexPoint(portal, 2)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " b3MprVec3Sub2(&v3v1, &b3MprSimplexPoint(portal, 3)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " b3MprVec3Cross(dir, &v2v1, &v3v1);\n"
- " b3MprVec3Normalize(dir);\n"
- "}\n"
- "inline int portalEncapsulesOrigin(const b3MprSimplex_t *portal,\n"
- " const b3Float4 *dir)\n"
- "{\n"
- " float dot;\n"
- " dot = b3MprVec3Dot(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
- " return b3MprIsZero(dot) || dot > 0.f;\n"
- "}\n"
- "inline int portalReachTolerance(const b3MprSimplex_t *portal,\n"
- " const b3MprSupport_t *v4,\n"
- " const b3Float4 *dir)\n"
- "{\n"
- " float dv1, dv2, dv3, dv4;\n"
- " float dot1, dot2, dot3;\n"
- " // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}\n"
- " dv1 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, dir);\n"
- " dv2 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, dir);\n"
- " dv3 = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, dir);\n"
- " dv4 = b3MprVec3Dot(&v4->v, dir);\n"
- " dot1 = dv4 - dv1;\n"
- " dot2 = dv4 - dv2;\n"
- " dot3 = dv4 - dv3;\n"
- " dot1 = B3_MPR_FMIN(dot1, dot2);\n"
- " dot1 = B3_MPR_FMIN(dot1, dot3);\n"
- " return b3MprEq(dot1, B3_MPR_TOLERANCE) || dot1 < B3_MPR_TOLERANCE;\n"
- "}\n"
- "inline int portalCanEncapsuleOrigin(const b3MprSimplex_t *portal, \n"
- " const b3MprSupport_t *v4,\n"
- " const b3Float4 *dir)\n"
- "{\n"
- " float dot;\n"
- " dot = b3MprVec3Dot(&v4->v, dir);\n"
- " return b3MprIsZero(dot) || dot > 0.f;\n"
- "}\n"
- "inline void b3ExpandPortal(b3MprSimplex_t *portal,\n"
- " const b3MprSupport_t *v4)\n"
- "{\n"
- " float dot;\n"
- " b3Float4 v4v0;\n"
- " b3MprVec3Cross(&v4v0, &v4->v, &b3MprSimplexPoint(portal, 0)->v);\n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &v4v0);\n"
- " if (dot > 0.f){\n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &v4v0);\n"
- " if (dot > 0.f){\n"
- " b3MprSimplexSet(portal, 1, v4);\n"
- " }else{\n"
- " b3MprSimplexSet(portal, 3, v4);\n"
- " }\n"
- " }else{\n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &v4v0);\n"
- " if (dot > 0.f){\n"
- " b3MprSimplexSet(portal, 2, v4);\n"
- " }else{\n"
- " b3MprSimplexSet(portal, 1, v4);\n"
- " }\n"
- " }\n"
- "}\n"
- "B3_STATIC int b3DiscoverPortal(int pairIndex, int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " __global int* hasSepAxis,\n"
- " b3MprSimplex_t *portal)\n"
- "{\n"
- " b3Float4 dir, va, vb;\n"
- " float dot;\n"
- " int cont;\n"
- " \n"
- " \n"
- " // vertex 0 is center of portal\n"
- " b3FindOrigin(bodyIndexA,bodyIndexB,cpuBodyBuf, b3MprSimplexPointW(portal, 0));\n"
- " // vertex 0 is center of portal\n"
- " b3MprSimplexSetSize(portal, 1);\n"
- " \n"
- " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
- " b3Float4* b3mpr_vec3_origin = &zero;\n"
- " if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 0)->v, b3mpr_vec3_origin)){\n"
- " // Portal's center lies on origin (0,0,0) => we know that objects\n"
- " // intersect but we would need to know penetration info.\n"
- " // So move center little bit...\n"
- " b3MprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);\n"
- " b3MprVec3Add(&b3MprSimplexPointW(portal, 0)->v, &va);\n"
- " }\n"
- " // vertex 1 = support in direction of origin\n"
- " b3MprVec3Copy(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Scale(&dir, -1.f);\n"
- " b3MprVec3Normalize(&dir);\n"
- " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 1));\n"
- " b3MprSimplexSetSize(portal, 2);\n"
- " // test if origin isn't outside of v1\n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 1)->v, &dir);\n"
- " \n"
- " if (b3MprIsZero(dot) || dot < 0.f)\n"
- " return -1;\n"
- " // vertex 2\n"
- " b3MprVec3Cross(&dir, &b3MprSimplexPoint(portal, 0)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " if (b3MprIsZero(b3MprVec3Len2(&dir))){\n"
- " if (b3MprVec3Eq(&b3MprSimplexPoint(portal, 1)->v, b3mpr_vec3_origin)){\n"
- " // origin lies on v1\n"
- " return 1;\n"
- " }else{\n"
- " // origin lies on v0-v1 segment\n"
- " return 2;\n"
- " }\n"
- " }\n"
- " b3MprVec3Normalize(&dir);\n"
- " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 2));\n"
- " \n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 2)->v, &dir);\n"
- " if (b3MprIsZero(dot) || dot < 0.f)\n"
- " return -1;\n"
- " b3MprSimplexSetSize(portal, 3);\n"
- " // vertex 3 direction\n"
- " b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
- " &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
- " &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Cross(&dir, &va, &vb);\n"
- " b3MprVec3Normalize(&dir);\n"
- " // it is better to form portal faces to be oriented \"outside\" origin\n"
- " dot = b3MprVec3Dot(&dir, &b3MprSimplexPoint(portal, 0)->v);\n"
- " if (dot > 0.f){\n"
- " b3MprSimplexSwap(portal, 1, 2);\n"
- " b3MprVec3Scale(&dir, -1.f);\n"
- " }\n"
- " while (b3MprSimplexSize(portal) < 4){\n"
- " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, b3MprSimplexPointW(portal, 3));\n"
- " \n"
- " dot = b3MprVec3Dot(&b3MprSimplexPoint(portal, 3)->v, &dir);\n"
- " if (b3MprIsZero(dot) || dot < 0.f)\n"
- " return -1;\n"
- " cont = 0;\n"
- " // test if origin is outside (v1, v0, v3) - set v2 as v3 and\n"
- " // continue\n"
- " b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
- " &b3MprSimplexPoint(portal, 3)->v);\n"
- " dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
- " if (dot < 0.f && !b3MprIsZero(dot)){\n"
- " b3MprSimplexSet(portal, 2, b3MprSimplexPoint(portal, 3));\n"
- " cont = 1;\n"
- " }\n"
- " if (!cont){\n"
- " // test if origin is outside (v3, v0, v2) - set v1 as v3 and\n"
- " // continue\n"
- " b3MprVec3Cross(&va, &b3MprSimplexPoint(portal, 3)->v,\n"
- " &b3MprSimplexPoint(portal, 2)->v);\n"
- " dot = b3MprVec3Dot(&va, &b3MprSimplexPoint(portal, 0)->v);\n"
- " if (dot < 0.f && !b3MprIsZero(dot)){\n"
- " b3MprSimplexSet(portal, 1, b3MprSimplexPoint(portal, 3));\n"
- " cont = 1;\n"
- " }\n"
- " }\n"
- " if (cont){\n"
- " b3MprVec3Sub2(&va, &b3MprSimplexPoint(portal, 1)->v,\n"
- " &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Sub2(&vb, &b3MprSimplexPoint(portal, 2)->v,\n"
- " &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Cross(&dir, &va, &vb);\n"
- " b3MprVec3Normalize(&dir);\n"
- " }else{\n"
- " b3MprSimplexSetSize(portal, 4);\n"
- " }\n"
- " }\n"
- " return 0;\n"
- "}\n"
- "B3_STATIC int b3RefinePortal(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " b3MprSimplex_t *portal)\n"
- "{\n"
- " b3Float4 dir;\n"
- " b3MprSupport_t v4;\n"
- " for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
- " //while (1)\n"
- " {\n"
- " // compute direction outside the portal (from v0 throught v1,v2,v3\n"
- " // face)\n"
- " b3PortalDir(portal, &dir);\n"
- " // test if origin is inside the portal\n"
- " if (portalEncapsulesOrigin(portal, &dir))\n"
- " return 0;\n"
- " // get next support point\n"
- " \n"
- " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
- " // test if v4 can expand portal to contain origin and if portal\n"
- " // expanding doesn't reach given tolerance\n"
- " if (!portalCanEncapsuleOrigin(portal, &v4, &dir)\n"
- " || portalReachTolerance(portal, &v4, &dir))\n"
- " {\n"
- " return -1;\n"
- " }\n"
- " // v1-v2-v3 triangle must be rearranged to face outside Minkowski\n"
- " // difference (direction from v0).\n"
- " b3ExpandPortal(portal, &v4);\n"
- " }\n"
- " return -1;\n"
- "}\n"
- "B3_STATIC void b3FindPos(const b3MprSimplex_t *portal, b3Float4 *pos)\n"
- "{\n"
- " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
- " b3Float4* b3mpr_vec3_origin = &zero;\n"
- " b3Float4 dir;\n"
- " size_t i;\n"
- " float b[4], sum, inv;\n"
- " b3Float4 vec, p1, p2;\n"
- " b3PortalDir(portal, &dir);\n"
- " // use barycentric coordinates of tetrahedron to find origin\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
- " &b3MprSimplexPoint(portal, 2)->v);\n"
- " b[0] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
- " &b3MprSimplexPoint(portal, 2)->v);\n"
- " b[1] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 0)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " b[2] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 3)->v);\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " b[3] = b3MprVec3Dot(&vec, &b3MprSimplexPoint(portal, 0)->v);\n"
- " sum = b[0] + b[1] + b[2] + b[3];\n"
- " if (b3MprIsZero(sum) || sum < 0.f){\n"
- " b[0] = 0.f;\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 2)->v,\n"
- " &b3MprSimplexPoint(portal, 3)->v);\n"
- " b[1] = b3MprVec3Dot(&vec, &dir);\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 3)->v,\n"
- " &b3MprSimplexPoint(portal, 1)->v);\n"
- " b[2] = b3MprVec3Dot(&vec, &dir);\n"
- " b3MprVec3Cross(&vec, &b3MprSimplexPoint(portal, 1)->v,\n"
- " &b3MprSimplexPoint(portal, 2)->v);\n"
- " b[3] = b3MprVec3Dot(&vec, &dir);\n"
- " sum = b[1] + b[2] + b[3];\n"
- " }\n"
- " inv = 1.f / sum;\n"
- " b3MprVec3Copy(&p1, b3mpr_vec3_origin);\n"
- " b3MprVec3Copy(&p2, b3mpr_vec3_origin);\n"
- " for (i = 0; i < 4; i++){\n"
- " b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v1);\n"
- " b3MprVec3Scale(&vec, b[i]);\n"
- " b3MprVec3Add(&p1, &vec);\n"
- " b3MprVec3Copy(&vec, &b3MprSimplexPoint(portal, i)->v2);\n"
- " b3MprVec3Scale(&vec, b[i]);\n"
- " b3MprVec3Add(&p2, &vec);\n"
- " }\n"
- " b3MprVec3Scale(&p1, inv);\n"
- " b3MprVec3Scale(&p2, inv);\n"
- " b3MprVec3Copy(pos, &p1);\n"
- " b3MprVec3Add(pos, &p2);\n"
- " b3MprVec3Scale(pos, 0.5);\n"
- "}\n"
- "inline float b3MprVec3Dist2(const b3Float4 *a, const b3Float4 *b)\n"
- "{\n"
- " b3Float4 ab;\n"
- " b3MprVec3Sub2(&ab, a, b);\n"
- " return b3MprVec3Len2(&ab);\n"
- "}\n"
- "inline float _b3MprVec3PointSegmentDist2(const b3Float4 *P,\n"
- " const b3Float4 *x0,\n"
- " const b3Float4 *b,\n"
- " b3Float4 *witness)\n"
- "{\n"
- " // The computation comes from solving equation of segment:\n"
- " // S(t) = x0 + t.d\n"
- " // where - x0 is initial point of segment\n"
- " // - d is direction of segment from x0 (|d| > 0)\n"
- " // - t belongs to <0, 1> interval\n"
- " // \n"
- " // Than, distance from a segment to some point P can be expressed:\n"
- " // D(t) = |x0 + t.d - P|^2\n"
- " // which is distance from any point on segment. Minimization\n"
- " // of this function brings distance from P to segment.\n"
- " // Minimization of D(t) leads to simple quadratic equation that's\n"
- " // solving is straightforward.\n"
- " //\n"
- " // Bonus of this method is witness point for free.\n"
- " float dist, t;\n"
- " b3Float4 d, a;\n"
- " // direction of segment\n"
- " b3MprVec3Sub2(&d, b, x0);\n"
- " // precompute vector from P to x0\n"
- " b3MprVec3Sub2(&a, x0, P);\n"
- " t = -1.f * b3MprVec3Dot(&a, &d);\n"
- " t /= b3MprVec3Len2(&d);\n"
- " if (t < 0.f || b3MprIsZero(t)){\n"
- " dist = b3MprVec3Dist2(x0, P);\n"
- " if (witness)\n"
- " b3MprVec3Copy(witness, x0);\n"
- " }else if (t > 1.f || b3MprEq(t, 1.f)){\n"
- " dist = b3MprVec3Dist2(b, P);\n"
- " if (witness)\n"
- " b3MprVec3Copy(witness, b);\n"
- " }else{\n"
- " if (witness){\n"
- " b3MprVec3Copy(witness, &d);\n"
- " b3MprVec3Scale(witness, t);\n"
- " b3MprVec3Add(witness, x0);\n"
- " dist = b3MprVec3Dist2(witness, P);\n"
- " }else{\n"
- " // recycling variables\n"
- " b3MprVec3Scale(&d, t);\n"
- " b3MprVec3Add(&d, &a);\n"
- " dist = b3MprVec3Len2(&d);\n"
- " }\n"
- " }\n"
- " return dist;\n"
- "}\n"
- "inline float b3MprVec3PointTriDist2(const b3Float4 *P,\n"
- " const b3Float4 *x0, const b3Float4 *B,\n"
- " const b3Float4 *C,\n"
- " b3Float4 *witness)\n"
- "{\n"
- " // Computation comes from analytic expression for triangle (x0, B, C)\n"
- " // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and\n"
- " // Then equation for distance is:\n"
- " // D(s, t) = | T(s, t) - P |^2\n"
- " // This leads to minimization of quadratic function of two variables.\n"
- " // The solution from is taken only if s is between 0 and 1, t is\n"
- " // between 0 and 1 and t + s < 1, otherwise distance from segment is\n"
- " // computed.\n"
- " b3Float4 d1, d2, a;\n"
- " float u, v, w, p, q, r;\n"
- " float s, t, dist, dist2;\n"
- " b3Float4 witness2;\n"
- " b3MprVec3Sub2(&d1, B, x0);\n"
- " b3MprVec3Sub2(&d2, C, x0);\n"
- " b3MprVec3Sub2(&a, x0, P);\n"
- " u = b3MprVec3Dot(&a, &a);\n"
- " v = b3MprVec3Dot(&d1, &d1);\n"
- " w = b3MprVec3Dot(&d2, &d2);\n"
- " p = b3MprVec3Dot(&a, &d1);\n"
- " q = b3MprVec3Dot(&a, &d2);\n"
- " r = b3MprVec3Dot(&d1, &d2);\n"
- " s = (q * r - w * p) / (w * v - r * r);\n"
- " t = (-s * r - q) / w;\n"
- " if ((b3MprIsZero(s) || s > 0.f)\n"
- " && (b3MprEq(s, 1.f) || s < 1.f)\n"
- " && (b3MprIsZero(t) || t > 0.f)\n"
- " && (b3MprEq(t, 1.f) || t < 1.f)\n"
- " && (b3MprEq(t + s, 1.f) || t + s < 1.f)){\n"
- " if (witness){\n"
- " b3MprVec3Scale(&d1, s);\n"
- " b3MprVec3Scale(&d2, t);\n"
- " b3MprVec3Copy(witness, x0);\n"
- " b3MprVec3Add(witness, &d1);\n"
- " b3MprVec3Add(witness, &d2);\n"
- " dist = b3MprVec3Dist2(witness, P);\n"
- " }else{\n"
- " dist = s * s * v;\n"
- " dist += t * t * w;\n"
- " dist += 2.f * s * t * r;\n"
- " dist += 2.f * s * p;\n"
- " dist += 2.f * t * q;\n"
- " dist += u;\n"
- " }\n"
- " }else{\n"
- " dist = _b3MprVec3PointSegmentDist2(P, x0, B, witness);\n"
- " dist2 = _b3MprVec3PointSegmentDist2(P, x0, C, &witness2);\n"
- " if (dist2 < dist){\n"
- " dist = dist2;\n"
- " if (witness)\n"
- " b3MprVec3Copy(witness, &witness2);\n"
- " }\n"
- " dist2 = _b3MprVec3PointSegmentDist2(P, B, C, &witness2);\n"
- " if (dist2 < dist){\n"
- " dist = dist2;\n"
- " if (witness)\n"
- " b3MprVec3Copy(witness, &witness2);\n"
- " }\n"
- " }\n"
- " return dist;\n"
- "}\n"
- "B3_STATIC void b3FindPenetr(int pairIndex,int bodyIndexA, int bodyIndexB, b3ConstArray(b3RigidBodyData_t) cpuBodyBuf, \n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " b3MprSimplex_t *portal,\n"
- " float *depth, b3Float4 *pdir, b3Float4 *pos)\n"
- "{\n"
- " b3Float4 dir;\n"
- " b3MprSupport_t v4;\n"
- " unsigned long iterations;\n"
- " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
- " b3Float4* b3mpr_vec3_origin = &zero;\n"
- " iterations = 1UL;\n"
- " for (int i=0;i<B3_MPR_MAX_ITERATIONS;i++)\n"
- " //while (1)\n"
- " {\n"
- " // compute portal direction and obtain next support point\n"
- " b3PortalDir(portal, &dir);\n"
- " \n"
- " b3MprSupport(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&dir, &v4);\n"
- " // reached tolerance -> find penetration info\n"
- " if (portalReachTolerance(portal, &v4, &dir)\n"
- " || iterations ==B3_MPR_MAX_ITERATIONS)\n"
- " {\n"
- " *depth = b3MprVec3PointTriDist2(b3mpr_vec3_origin,&b3MprSimplexPoint(portal, 1)->v,&b3MprSimplexPoint(portal, 2)->v,&b3MprSimplexPoint(portal, 3)->v,pdir);\n"
- " *depth = B3_MPR_SQRT(*depth);\n"
- " \n"
- " if (b3MprIsZero((*pdir).x) && b3MprIsZero((*pdir).y) && b3MprIsZero((*pdir).z))\n"
- " {\n"
- " \n"
- " *pdir = dir;\n"
- " } \n"
- " b3MprVec3Normalize(pdir);\n"
- " \n"
- " // barycentric coordinates:\n"
- " b3FindPos(portal, pos);\n"
- " return;\n"
- " }\n"
- " b3ExpandPortal(portal, &v4);\n"
- " iterations++;\n"
- " }\n"
- "}\n"
- "B3_STATIC void b3FindPenetrTouch(b3MprSimplex_t *portal,float *depth, b3Float4 *dir, b3Float4 *pos)\n"
- "{\n"
- " // Touching contact on portal's v1 - so depth is zero and direction\n"
- " // is unimportant and pos can be guessed\n"
- " *depth = 0.f;\n"
- " b3Float4 zero = b3MakeFloat4(0,0,0,0);\n"
- " b3Float4* b3mpr_vec3_origin = &zero;\n"
- " b3MprVec3Copy(dir, b3mpr_vec3_origin);\n"
- " b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
- " b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
- " b3MprVec3Scale(pos, 0.5);\n"
- "}\n"
- "B3_STATIC void b3FindPenetrSegment(b3MprSimplex_t *portal,\n"
- " float *depth, b3Float4 *dir, b3Float4 *pos)\n"
- "{\n"
- " \n"
- " // Origin lies on v0-v1 segment.\n"
- " // Depth is distance to v1, direction also and position must be\n"
- " // computed\n"
- " b3MprVec3Copy(pos, &b3MprSimplexPoint(portal, 1)->v1);\n"
- " b3MprVec3Add(pos, &b3MprSimplexPoint(portal, 1)->v2);\n"
- " b3MprVec3Scale(pos, 0.5f);\n"
- " \n"
- " b3MprVec3Copy(dir, &b3MprSimplexPoint(portal, 1)->v);\n"
- " *depth = B3_MPR_SQRT(b3MprVec3Len2(dir));\n"
- " b3MprVec3Normalize(dir);\n"
- "}\n"
- "inline int b3MprPenetration(int pairIndex, int bodyIndexA, int bodyIndexB,\n"
- " b3ConstArray(b3RigidBodyData_t) cpuBodyBuf,\n"
- " b3ConstArray(b3ConvexPolyhedronData_t) cpuConvexData, \n"
- " b3ConstArray(b3Collidable_t) cpuCollidables,\n"
- " b3ConstArray(b3Float4) cpuVertices,\n"
- " __global b3Float4* sepAxis,\n"
- " __global int* hasSepAxis,\n"
- " float *depthOut, b3Float4* dirOut, b3Float4* posOut)\n"
- "{\n"
- " \n"
- " b3MprSimplex_t portal;\n"
- " \n"
- "// if (!hasSepAxis[pairIndex])\n"
- " // return -1;\n"
- " \n"
- " hasSepAxis[pairIndex] = 0;\n"
- " int res;\n"
- " // Phase 1: Portal discovery\n"
- " res = b3DiscoverPortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices,sepAxis,hasSepAxis, &portal);\n"
- " \n"
- " \n"
- " //sepAxis[pairIndex] = *pdir;//or -dir?\n"
- " switch (res)\n"
- " {\n"
- " case 0:\n"
- " {\n"
- " // Phase 2: Portal refinement\n"
- " \n"
- " res = b3RefinePortal(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal);\n"
- " if (res < 0)\n"
- " return -1;\n"
- " // Phase 3. Penetration info\n"
- " b3FindPenetr(pairIndex,bodyIndexA,bodyIndexB,cpuBodyBuf,cpuConvexData,cpuCollidables,cpuVertices, sepAxis,&portal, depthOut, dirOut, posOut);\n"
- " hasSepAxis[pairIndex] = 1;\n"
- " sepAxis[pairIndex] = -*dirOut;\n"
- " break;\n"
- " }\n"
- " case 1:\n"
- " {\n"
- " // Touching contact on portal's v1.\n"
- " b3FindPenetrTouch(&portal, depthOut, dirOut, posOut);\n"
- " break;\n"
- " }\n"
- " case 2:\n"
- " {\n"
- " \n"
- " b3FindPenetrSegment( &portal, depthOut, dirOut, posOut);\n"
- " break;\n"
- " }\n"
- " default:\n"
- " {\n"
- " hasSepAxis[pairIndex]=0;\n"
- " //if (res < 0)\n"
- " //{\n"
- " // Origin isn't inside portal - no collision.\n"
- " return -1;\n"
- " //}\n"
- " }\n"
- " };\n"
- " \n"
- " return 0;\n"
- "};\n"
- "#endif //B3_MPR_PENETRATION_H\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- " #pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- " #define counter32_t volatile __global int*\n"
- "#endif\n"
- "__kernel void mprPenetrationKernel( __global int4* pairs,\n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global float4* separatingNormals,\n"
- " __global int* hasSeparatingAxis,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int contactCapacity,\n"
- " int numPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " if (i<numPairs)\n"
- " {\n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " //once the broadphase avoids static-static pairs, we can remove this test\n"
- " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
- " {\n"
- " return;\n"
- " }\n"
- " \n"
- " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
- " {\n"
- " return;\n"
- " }\n"
- " float depthOut;\n"
- " b3Float4 dirOut;\n"
- " b3Float4 posOut;\n"
- " int res = b3MprPenetration(pairIndex, bodyIndexA, bodyIndexB,rigidBodies,convexShapes,collidables,vertices,separatingNormals,hasSeparatingAxis,&depthOut, &dirOut, &posOut);\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " if (res==0)\n"
- " {\n"
- " //add a contact\n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " if (dstIdx<contactCapacity)\n"
- " {\n"
- " pairs[pairIndex].z = dstIdx;\n"
- " __global struct b3Contact4Data* c = globalContactsOut + dstIdx;\n"
- " c->m_worldNormalOnB = -dirOut;//normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " //for (int i=0;i<nContacts;i++)\n"
- " posOut.w = -depthOut;\n"
- " c->m_worldPosB[0] = posOut;//localPoints[contactIdx[i]];\n"
- " GET_NPOINTS(*c) = 1;//nContacts;\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "typedef float4 Quaternion;\n"
- "#define make_float4 (float4)\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
- "{\n"
- " return qtRotate( *orientation, *p ) + (*translation);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "inline void project(__global const b3ConvexPolyhedronData_t* hull, const float4 pos, const float4 orn, \n"
- "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
- "{\n"
- " min[0] = FLT_MAX;\n"
- " max[0] = -FLT_MAX;\n"
- " int numVerts = hull->m_numVertices;\n"
- " const float4 localDir = qtInvRotate(orn,*dir);\n"
- " float offset = dot(pos,*dir);\n"
- " for(int i=0;i<numVerts;i++)\n"
- " {\n"
- " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
- " if(dp < min[0]) \n"
- " min[0] = dp;\n"
- " if(dp > max[0]) \n"
- " max[0] = dp;\n"
- " }\n"
- " if(min[0]>max[0])\n"
- " {\n"
- " float tmp = min[0];\n"
- " min[0] = max[0];\n"
- " max[0] = tmp;\n"
- " }\n"
- " min[0] += offset;\n"
- " max[0] += offset;\n"
- "}\n"
- "bool findSeparatingAxisUnitSphere( __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* vertices,\n"
- " __global const float4* unitSphereDirections,\n"
- " int numUnitSphereDirections,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " int curEdgeEdge = 0;\n"
- " // Test unit sphere directions\n"
- " for (int i=0;i<numUnitSphereDirections;i++)\n"
- " {\n"
- " float4 crossje;\n"
- " crossje = unitSphereDirections[i]; \n"
- " if (dot3F4(DeltaC2,crossje)>0)\n"
- " crossje *= -1.f;\n"
- " {\n"
- " float dist;\n"
- " bool result = true;\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
- " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
- " \n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " \n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " dist = d0<d1 ? d0:d1;\n"
- " result = true;\n"
- " \n"
- " if(dist<*dmin)\n"
- " {\n"
- " *dmin = dist;\n"
- " *sep = crossje;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "__kernel void findSeparatingAxisUnitSphereKernel( __global const int4* pairs, \n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* unitSphereDirections,\n"
- " __global float4* separatingNormals,\n"
- " __global int* hasSeparatingAxis,\n"
- " __global float* dmins,\n"
- " int numUnitSphereDirections,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " \n"
- " float dmin = dmins[i];\n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " float4 sepNormal = separatingNormals[i];\n"
- " \n"
- " int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
- " if (numEdgeEdgeDirections>numUnitSphereDirections)\n"
- " {\n"
- " bool sepEE = findSeparatingAxisUnitSphere( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,unitSphereDirections,numUnitSphereDirections,&sepNormal,&dmin);\n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis[i] = 1;\n"
- " separatingNormals[i] = sepNormal;\n"
- " }\n"
- " }\n"
- " } //if (hasSeparatingAxis[i])\n"
- " }//(i<numPairs)\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl
deleted file mode 100644
index 9c9e920f13..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.cl
+++ /dev/null
@@ -1,1374 +0,0 @@
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#define SHAPE_CONVEX_HULL 3
-#define SHAPE_PLANE 4
-#define SHAPE_CONCAVE_TRIMESH 5
-#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
-#define SHAPE_SPHERE 7
-
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile __global int*
-#endif
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-#define max2 max
-#define min2 min
-
-typedef unsigned int u32;
-
-
-
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} btAabbCL;
-
-///keep this in sync with btCollidable.h
-typedef struct
-{
- int m_numChildShapes;
- float m_radius;
- int m_shapeType;
- int m_shapeIndex;
-
-} btCollidableGpu;
-
-typedef struct
-{
- float4 m_childPosition;
- float4 m_childOrientation;
- int m_shapeIndex;
- int m_unused0;
- int m_unused1;
- int m_unused2;
-} btGpuChildShape;
-
-#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
-
-typedef struct
-{
- float4 m_pos;
- float4 m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} BodyData;
-
-
-typedef struct
-{
- float4 m_localCenter;
- float4 m_extents;
- float4 mC;
- float4 mE;
-
- float m_radius;
- int m_faceOffset;
- int m_numFaces;
- int m_numVertices;
-
- int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
- int m_unused;
-
-} ConvexPolyhedronCL;
-
-typedef struct
-{
- float4 m_plane;
- int m_indexOffset;
- int m_numIndices;
-} btGpuFace;
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-__inline
-float fastDiv(float numerator, float denominator)
-{
- return native_divide(numerator, denominator);
-// return numerator/denominator;
-}
-
-__inline
-float4 fastDiv4(float4 numerator, float4 denominator)
-{
- return native_divide(numerator, denominator);
-}
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-//#define dot3F4 dot
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-__inline
-float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
-{
- return qtRotate( *orientation, *p ) + (*translation);
-}
-
-void trInverse(float4 translationIn, Quaternion orientationIn,
- float4* translationOut, Quaternion* orientationOut)
-{
- *orientationOut = qtInvert(orientationIn);
- *translationOut = qtRotate(*orientationOut, -translationIn);
-}
-
-void trMul(float4 translationA, Quaternion orientationA,
- float4 translationB, Quaternion orientationB,
- float4* translationOut, Quaternion* orientationOut)
-{
- *orientationOut = qtMul(orientationA,orientationB);
- *translationOut = transform(&translationB,&translationA,&orientationA);
-}
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-}
-
-
-__inline float4 lerp3(const float4 a,const float4 b, float t)
-{
- return make_float4( a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
-}
-
-
-float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)
-{
- float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);
- float dist = dot3F4(n, point) + planeEqn.w;
- *closestPointOnFace = point - dist * n;
- return dist;
-}
-
-
-
-inline bool IsPointInPolygon(float4 p,
- const btGpuFace* face,
- __global const float4* baseVertex,
- __global const int* convexIndices,
- float4* out)
-{
- float4 a;
- float4 b;
- float4 ab;
- float4 ap;
- float4 v;
-
- float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);
-
- if (face->m_numIndices<2)
- return false;
-
-
- float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];
-
- b = v0;
-
- for(unsigned i=0; i != face->m_numIndices; ++i)
- {
- a = b;
- float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];
- b = vi;
- ab = b-a;
- ap = p-a;
- v = cross3(ab,plane);
-
- if (dot(ap, v) > 0.f)
- {
- float ab_m2 = dot(ab, ab);
- float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;
- if (rt <= 0.f)
- {
- *out = a;
- }
- else if (rt >= 1.f)
- {
- *out = b;
- }
- else
- {
- float s = 1.f - rt;
- out[0].x = s * a.x + rt * b.x;
- out[0].y = s * a.y + rt * b.y;
- out[0].z = s * a.z + rt * b.z;
- }
- return false;
- }
- }
- return true;
-}
-
-
-
-
-void computeContactSphereConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* convexVertices,
- __global const int* convexIndices,
- __global const btGpuFace* faces,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int maxContactCapacity,
- float4 spherePos2,
- float radius,
- float4 pos,
- float4 quat
- )
-{
-
- float4 invPos;
- float4 invOrn;
-
- trInverse(pos,quat, &invPos,&invOrn);
-
- float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
-
- int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
- int numFaces = convexShapes[shapeIndex].m_numFaces;
- float4 closestPnt = (float4)(0, 0, 0, 0);
- float4 hitNormalWorld = (float4)(0, 0, 0, 0);
- float minDist = -1000000.f;
- bool bCollide = true;
-
- for ( int f = 0; f < numFaces; f++ )
- {
- btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];
-
- // set up a plane equation
- float4 planeEqn;
- float4 n1 = face.m_plane;
- n1.w = 0.f;
- planeEqn = n1;
- planeEqn.w = face.m_plane.w;
-
-
- // compute a signed distance from the vertex in cloth to the face of rigidbody.
- float4 pntReturn;
- float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);
-
- // If the distance is positive, the plane is a separating plane.
- if ( dist > radius )
- {
- bCollide = false;
- break;
- }
-
-
- if (dist>0)
- {
- //might hit an edge or vertex
- float4 out;
- float4 zeroPos = make_float4(0,0,0,0);
-
- bool isInPoly = IsPointInPolygon(spherePos,
- &face,
- &convexVertices[convexShapes[shapeIndex].m_vertexOffset],
- convexIndices,
- &out);
- if (isInPoly)
- {
- if (dist>minDist)
- {
- minDist = dist;
- closestPnt = pntReturn;
- hitNormalWorld = planeEqn;
-
- }
- } else
- {
- float4 tmp = spherePos-out;
- float l2 = dot(tmp,tmp);
- if (l2<radius*radius)
- {
- dist = sqrt(l2);
- if (dist>minDist)
- {
- minDist = dist;
- closestPnt = out;
- hitNormalWorld = tmp/dist;
-
- }
-
- } else
- {
- bCollide = false;
- break;
- }
- }
- } else
- {
- if ( dist > minDist )
- {
- minDist = dist;
- closestPnt = pntReturn;
- hitNormalWorld.xyz = planeEqn.xyz;
- }
- }
-
- }
-
-
-
- if (bCollide && minDist > -10000)
- {
- float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
- float4 pOnB1 = transform(&closestPnt,&pos,&quat);
-
- float actualDepth = minDist-radius;
- if (actualDepth<=0.f)
- {
-
-
- pOnB1.w = actualDepth;
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
-
-
- if (1)//dstIdx < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normalOnSurfaceB1;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
-
- GET_NPOINTS(*c) = 1;
- }
-
- }
- }//if (hasCollision)
-
-}
-
-
-
-int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
-{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- float4 center = make_float4(0.f);
- {
-
- for (int i=0;i<nPoints;i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
-
-
- // sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3( nearNormal, aVector );
- float4 v = cross3( nearNormal, u );
- u = normalize3( u );
- v = normalize3( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- float4 r = p[ie]-center;
- f = dot3F4( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = dot3F4( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
-}
-
-#define MAX_PLANE_CONVEX_POINTS 64
-
-int computeContactPlaneConvex(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu*collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* convexVertices,
- __global const int* convexIndices,
- __global const btGpuFace* faces,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int maxContactCapacity,
- float4 posB,
- Quaternion ornB
- )
-{
- int resultIndex=-1;
-
- int shapeIndex = collidables[collidableIndexB].m_shapeIndex;
- __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];
-
- float4 posA;
- posA = rigidBodies[bodyIndexA].m_pos;
- Quaternion ornA;
- ornA = rigidBodies[bodyIndexA].m_quat;
-
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
- float4 planeEq;
- planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
- float4 planeNormalWorld;
- planeNormalWorld = qtRotate(ornA,planeNormal);
- float planeConstant = planeEq.w;
-
- float4 invPosA;Quaternion invOrnA;
- float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
- {
-
- trInverse(posA,ornA,&invPosA,&invOrnA);
- trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
- }
- float4 invPosB;Quaternion invOrnB;
- float4 planeInConvexPos1; Quaternion planeInConvexOrn1;
- {
-
- trInverse(posB,ornB,&invPosB,&invOrnB);
- trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1);
- }
-
-
- float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);
- float maxDot = -1e30;
- int hitVertex=-1;
- float4 hitVtx;
-
-
-
- float4 contactPoints[MAX_PLANE_CONVEX_POINTS];
- int numPoints = 0;
-
- int4 contactIdx;
- contactIdx=make_int4(0,1,2,3);
-
-
- for (int i=0;i<hullB->m_numVertices;i++)
- {
- float4 vtx = convexVertices[hullB->m_vertexOffset+i];
- float curDot = dot(vtx,planeNormalInConvex);
-
-
- if (curDot>maxDot)
- {
- hitVertex=i;
- maxDot=curDot;
- hitVtx = vtx;
- //make sure the deepest points is always included
- if (numPoints==MAX_PLANE_CONVEX_POINTS)
- numPoints--;
- }
-
- if (numPoints<MAX_PLANE_CONVEX_POINTS)
- {
- float4 vtxWorld = transform(&vtx, &posB, &ornB);
- float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;
- float dist = dot(planeNormal,vtxInPlane)-planeConstant;
- if (dist<0.f)
- {
- vtxWorld.w = dist;
- contactPoints[numPoints] = vtxWorld;
- numPoints++;
- }
- }
-
- }
-
- int numReducedPoints = numPoints;
- if (numPoints>4)
- {
- numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);
- }
-
- if (numReducedPoints>0)
- {
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
-
- if (dstIdx < maxContactCapacity)
- {
- resultIndex = dstIdx;
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -planeNormalWorld;
- //c->setFrictionCoeff(0.7);
- //c->setRestituitionCoeff(0.f);
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
-
- switch (numReducedPoints)
- {
- case 4:
- c->m_worldPosB[3] = contactPoints[contactIdx.w];
- case 3:
- c->m_worldPosB[2] = contactPoints[contactIdx.z];
- case 2:
- c->m_worldPosB[1] = contactPoints[contactIdx.y];
- case 1:
- c->m_worldPosB[0] = contactPoints[contactIdx.x];
- default:
- {
- }
- };
-
- GET_NPOINTS(*c) = numReducedPoints;
- }//if (dstIdx < numPairs)
- }
-
- return resultIndex;
-}
-
-
-void computeContactPlaneSphere(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const btGpuFace* faces,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int maxContactCapacity)
-{
- float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;
- float radius = collidables[collidableIndexB].m_radius;
- float4 posA1 = rigidBodies[bodyIndexA].m_pos;
- float4 ornA1 = rigidBodies[bodyIndexA].m_quat;
- float4 posB1 = rigidBodies[bodyIndexB].m_pos;
- float4 ornB1 = rigidBodies[bodyIndexB].m_quat;
-
- bool hasCollision = false;
- float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);
- float planeConstant = planeEq.w;
- float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;
- {
- float4 invPosA;Quaternion invOrnA;
- trInverse(posA1,ornA1,&invPosA,&invOrnA);
- trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
- }
- float4 planeInConvexPos1; Quaternion planeInConvexOrn1;
- {
- float4 invPosB;Quaternion invOrnB;
- trInverse(posB1,ornB1,&invPosB,&invOrnB);
- trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1);
- }
- float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;
- float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);
- float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;
- hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();
- if (hasCollision)
- {
- float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;
- float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);
- float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);
- float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;
- pOnB1.w = distance;
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
-
- if (dstIdx < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normalOnSurfaceB1;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
- GET_NPOINTS(*c) = 1;
- }//if (dstIdx < numPairs)
- }//if (hasCollision)
-}
-
-
-__kernel void primitiveContactsKernel( __global int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int numPairs, int maxContactCapacity)
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
- float4 worldVertsB1[64];
- float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
-
- float4 localContactsOut[64];
- int localContactCapacity=64;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numPairs)
- {
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
-
- float4 posB;
- posB = rigidBodies[bodyIndexB].m_pos;
- Quaternion ornB;
- ornB = rigidBodies[bodyIndexB].m_quat;
- int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
- rigidBodies,collidables,convexShapes,vertices,indices,
- faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);
- if (contactIndex>=0)
- pairs[pairIndex].z = contactIndex;
-
- return;
- }
-
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
-
- float4 posA;
- posA = rigidBodies[bodyIndexA].m_pos;
- Quaternion ornA;
- ornA = rigidBodies[bodyIndexA].m_quat;
-
-
- int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
- rigidBodies,collidables,convexShapes,vertices,indices,
- faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
-
- if (contactIndex>=0)
- pairs[pairIndex].z = contactIndex;
-
- return;
- }
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
- computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
- rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);
- return;
- }
-
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)
- {
-
-
- computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
- rigidBodies,collidables,
- faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);
-
- return;
- }
-
-
-
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)
- {
-
- float4 spherePos = rigidBodies[bodyIndexA].m_pos;
- float sphereRadius = collidables[collidableIndexA].m_radius;
- float4 convexPos = rigidBodies[bodyIndexB].m_pos;
- float4 convexOrn = rigidBodies[bodyIndexB].m_quat;
-
- computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
- rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
- spherePos,sphereRadius,convexPos,convexOrn);
-
- return;
- }
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&
- collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
-
- float4 spherePos = rigidBodies[bodyIndexB].m_pos;
- float sphereRadius = collidables[collidableIndexB].m_radius;
- float4 convexPos = rigidBodies[bodyIndexA].m_pos;
- float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
-
- computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA,
- rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
- spherePos,sphereRadius,convexPos,convexOrn);
- return;
- }
-
-
-
-
-
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
- //sphere-sphere
- float radiusA = collidables[collidableIndexA].m_radius;
- float radiusB = collidables[collidableIndexB].m_radius;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- float4 diff = posA-posB;
- float len = length(diff);
-
- ///iff distance positive, don't generate a new contact
- if ( len <= (radiusA+radiusB))
- {
- ///distance (negative means penetration)
- float dist = len - (radiusA+radiusB);
- float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
- if (len > 0.00001)
- {
- normalOnSurfaceB = diff / len;
- }
- float4 contactPosB = posB + normalOnSurfaceB*radiusB;
- contactPosB.w = dist;
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
-
- if (dstIdx < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = normalOnSurfaceB;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_worldPosB[0] = contactPosB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
- GET_NPOINTS(*c) = 1;
- }//if (dstIdx < numPairs)
- }//if ( len <= (radiusA+radiusB))
-
- return;
- }//SHAPE_SPHERE SHAPE_SPHERE
-
- }// if (i<numPairs)
-
-}
-
-
-// work-in-progress
-__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global const btGpuChildShape* gpuChildShapes,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int numCompoundPairs, int maxContactCapacity
- )
-{
-
- int i = get_global_id(0);
- if (i<numCompoundPairs)
- {
- int bodyIndexA = gpuCompoundPairs[i].x;
- int bodyIndexB = gpuCompoundPairs[i].y;
-
- int childShapeIndexA = gpuCompoundPairs[i].z;
- int childShapeIndexB = gpuCompoundPairs[i].w;
-
- int collidableIndexA = -1;
- int collidableIndexB = -1;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
-
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- if (childShapeIndexA >= 0)
- {
- collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = qtRotate(ornA,childPosA)+posA;
- float4 newOrnA = qtMul(ornA,childOrnA);
- posA = newPosA;
- ornA = newOrnA;
- } else
- {
- collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- }
-
- if (childShapeIndexB>=0)
- {
- collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- } else
- {
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
- }
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- int shapeTypeA = collidables[collidableIndexA].m_shapeType;
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
- int pairIndex = i;
- if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))
- {
-
- computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB,
- rigidBodies,collidables,convexShapes,vertices,indices,
- faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);
- return;
- }
-
- if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))
- {
-
- computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA,
- rigidBodies,collidables,convexShapes,vertices,indices,
- faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);
- return;
- }
-
- if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))
- {
- float4 spherePos = rigidBodies[bodyIndexB].m_pos;
- float sphereRadius = collidables[collidableIndexB].m_radius;
- float4 convexPos = posA;
- float4 convexOrn = ornA;
-
- computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA,
- rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
- spherePos,sphereRadius,convexPos,convexOrn);
-
- return;
- }
-
- if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))
- {
-
- float4 spherePos = rigidBodies[bodyIndexA].m_pos;
- float sphereRadius = collidables[collidableIndexA].m_radius;
- float4 convexPos = posB;
- float4 convexOrn = ornB;
-
-
- computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB,
- rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,
- spherePos,sphereRadius,convexPos,convexOrn);
-
- return;
- }
- }// if (i<numCompoundPairs)
-}
-
-
-bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )
-{
-
- const float4* p1 = &vertices[0];
- const float4* p2 = &vertices[1];
- const float4* p3 = &vertices[2];
-
- float4 edge1; edge1 = (*p2 - *p1);
- float4 edge2; edge2 = ( *p3 - *p2 );
- float4 edge3; edge3 = ( *p1 - *p3 );
-
-
- float4 p1_to_p; p1_to_p = ( *p - *p1 );
- float4 p2_to_p; p2_to_p = ( *p - *p2 );
- float4 p3_to_p; p3_to_p = ( *p - *p3 );
-
- float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));
- float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));
- float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));
-
-
-
- float r1, r2, r3;
- r1 = dot(edge1_normal,p1_to_p );
- r2 = dot(edge2_normal,p2_to_p );
- r3 = dot(edge3_normal,p3_to_p );
-
- if ( r1 > 0 && r2 > 0 && r3 > 0 )
- return true;
- if ( r1 <= 0 && r2 <= 0 && r3 <= 0 )
- return true;
- return false;
-
-}
-
-
-float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest)
-{
- float4 diff = p - from;
- float4 v = to - from;
- float t = dot(v,diff);
-
- if (t > 0)
- {
- float dotVV = dot(v,v);
- if (t < dotVV)
- {
- t /= dotVV;
- diff -= t*v;
- } else
- {
- t = 1;
- diff -= v;
- }
- } else
- {
- t = 0;
- }
- *nearest = from + t*v;
- return dot(diff,diff);
-}
-
-
-void computeContactSphereTriangle(int pairIndex,
- int bodyIndexA, int bodyIndexB,
- int collidableIndexA, int collidableIndexB,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- const float4* triangleVertices,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int maxContactCapacity,
- float4 spherePos2,
- float radius,
- float4 pos,
- float4 quat,
- int faceIndex
- )
-{
-
- float4 invPos;
- float4 invOrn;
-
- trInverse(pos,quat, &invPos,&invOrn);
- float4 spherePos = transform(&spherePos2,&invPos,&invOrn);
- int numFaces = 3;
- float4 closestPnt = (float4)(0, 0, 0, 0);
- float4 hitNormalWorld = (float4)(0, 0, 0, 0);
- float minDist = -1000000.f;
- bool bCollide = false;
-
-
- //////////////////////////////////////
-
- float4 sphereCenter;
- sphereCenter = spherePos;
-
- const float4* vertices = triangleVertices;
- float contactBreakingThreshold = 0.f;//todo?
- float radiusWithThreshold = radius + contactBreakingThreshold;
- float4 edge10;
- edge10 = vertices[1]-vertices[0];
- edge10.w = 0.f;//is this needed?
- float4 edge20;
- edge20 = vertices[2]-vertices[0];
- edge20.w = 0.f;//is this needed?
- float4 normal = cross3(edge10,edge20);
- normal = normalize(normal);
- float4 p1ToCenter;
- p1ToCenter = sphereCenter - vertices[0];
-
- float distanceFromPlane = dot(p1ToCenter,normal);
-
- if (distanceFromPlane < 0.f)
- {
- //triangle facing the other way
- distanceFromPlane *= -1.f;
- normal *= -1.f;
- }
- hitNormalWorld = normal;
-
- bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
-
- // Check for contact / intersection
- bool hasContact = false;
- float4 contactPoint;
- if (isInsideContactPlane)
- {
-
- if (pointInTriangle(vertices,&normal, &sphereCenter))
- {
- // Inside the contact wedge - touches a point on the shell plane
- hasContact = true;
- contactPoint = sphereCenter - normal*distanceFromPlane;
-
- } else {
- // Could be inside one of the contact capsules
- float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;
- float4 nearestOnEdge;
- int numEdges = 3;
- for (int i = 0; i < numEdges; i++)
- {
- float4 pa =vertices[i];
- float4 pb = vertices[(i+1)%3];
-
- float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);
- if (distanceSqr < contactCapsuleRadiusSqr)
- {
- // Yep, we're inside a capsule
- hasContact = true;
- contactPoint = nearestOnEdge;
-
- }
-
- }
- }
- }
-
- if (hasContact)
- {
-
- closestPnt = contactPoint;
- float4 contactToCenter = sphereCenter - contactPoint;
- minDist = length(contactToCenter);
- if (minDist>FLT_EPSILON)
- {
- hitNormalWorld = normalize(contactToCenter);//*(1./minDist);
- bCollide = true;
- }
-
- }
-
-
- /////////////////////////////////////
-
- if (bCollide && minDist > -10000)
- {
-
- float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);
- float4 pOnB1 = transform(&closestPnt,&pos,&quat);
- float actualDepth = minDist-radius;
-
-
- if (actualDepth<=0.f)
- {
- pOnB1.w = actualDepth;
- int dstIdx;
-
-
- float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);
- if (lenSqr>FLT_EPSILON)
- {
- AppendInc( nGlobalContactsOut, dstIdx );
-
- if (dstIdx < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normalOnSurfaceB1;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;
- c->m_worldPosB[0] = pOnB1;
-
- c->m_childIndexA = -1;
- c->m_childIndexB = faceIndex;
-
- GET_NPOINTS(*c) = 1;
- }
- }
-
- }
- }//if (hasCollision)
-
-}
-
-
-
-// work-in-progress
-__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int numConcavePairs, int maxContactCapacity
- )
-{
-
- int i = get_global_id(0);
- if (i>=numConcavePairs)
- return;
- int pairIdx = i;
-
- int bodyIndexA = concavePairs[i].x;
- int bodyIndexB = concavePairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)
- {
- int f = concavePairs[i].z;
- btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
-
- float4 verticesA[3];
- for (int i=0;i<3;i++)
- {
- int index = indices[face.m_indexOffset+i];
- float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
- verticesA[i] = vert;
- }
-
- float4 spherePos = rigidBodies[bodyIndexB].m_pos;
- float sphereRadius = collidables[collidableIndexB].m_radius;
- float4 convexPos = rigidBodies[bodyIndexA].m_pos;
- float4 convexOrn = rigidBodies[bodyIndexA].m_quat;
-
- computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA,
- rigidBodies,collidables,
- verticesA,
- globalContactsOut, nGlobalContactsOut,maxContactCapacity,
- spherePos,sphereRadius,convexPos,convexOrn, f);
-
- return;
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
deleted file mode 100644
index b2e0a2dd47..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/primitiveContacts.h
+++ /dev/null
@@ -1,1288 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* primitiveContactsKernelsCL =
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#define SHAPE_CONVEX_HULL 3\n"
- "#define SHAPE_PLANE 4\n"
- "#define SHAPE_CONCAVE_TRIMESH 5\n"
- "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
- "#define SHAPE_SPHERE 7\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile __global int*\n"
- "#endif\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "typedef unsigned int u32;\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} btAabbCL;\n"
- "///keep this in sync with btCollidable.h\n"
- "typedef struct\n"
- "{\n"
- " int m_numChildShapes;\n"
- " float m_radius;\n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- " \n"
- "} btCollidableGpu;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_childPosition;\n"
- " float4 m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "} btGpuChildShape;\n"
- "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " float4 m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_collidableIdx; \n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} BodyData;\n"
- "typedef struct \n"
- "{\n"
- " float4 m_localCenter;\n"
- " float4 m_extents;\n"
- " float4 mC;\n"
- " float4 mE;\n"
- " \n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " \n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "} ConvexPolyhedronCL;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- "} btGpuFace;\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "__inline\n"
- "float fastDiv(float numerator, float denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "// return numerator/denominator; \n"
- "}\n"
- "__inline\n"
- "float4 fastDiv4(float4 numerator, float4 denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "//#define dot3F4 dot\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "__inline\n"
- "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
- "{\n"
- " return qtRotate( *orientation, *p ) + (*translation);\n"
- "}\n"
- "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
- " float4* translationOut, Quaternion* orientationOut)\n"
- "{\n"
- " *orientationOut = qtInvert(orientationIn);\n"
- " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
- "}\n"
- "void trMul(float4 translationA, Quaternion orientationA,\n"
- " float4 translationB, Quaternion orientationB,\n"
- " float4* translationOut, Quaternion* orientationOut)\n"
- "{\n"
- " *orientationOut = qtMul(orientationA,orientationB);\n"
- " *translationOut = transform(&translationB,&translationA,&orientationA);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "}\n"
- "__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
- "{\n"
- " return make_float4( a.x + (b.x - a.x) * t,\n"
- " a.y + (b.y - a.y) * t,\n"
- " a.z + (b.z - a.z) * t,\n"
- " 0.f);\n"
- "}\n"
- "float signedDistanceFromPointToPlane(float4 point, float4 planeEqn, float4* closestPointOnFace)\n"
- "{\n"
- " float4 n = (float4)(planeEqn.x, planeEqn.y, planeEqn.z, 0);\n"
- " float dist = dot3F4(n, point) + planeEqn.w;\n"
- " *closestPointOnFace = point - dist * n;\n"
- " return dist;\n"
- "}\n"
- "inline bool IsPointInPolygon(float4 p, \n"
- " const btGpuFace* face,\n"
- " __global const float4* baseVertex,\n"
- " __global const int* convexIndices,\n"
- " float4* out)\n"
- "{\n"
- " float4 a;\n"
- " float4 b;\n"
- " float4 ab;\n"
- " float4 ap;\n"
- " float4 v;\n"
- " float4 plane = make_float4(face->m_plane.x,face->m_plane.y,face->m_plane.z,0.f);\n"
- " \n"
- " if (face->m_numIndices<2)\n"
- " return false;\n"
- " \n"
- " float4 v0 = baseVertex[convexIndices[face->m_indexOffset + face->m_numIndices-1]];\n"
- " \n"
- " b = v0;\n"
- " for(unsigned i=0; i != face->m_numIndices; ++i)\n"
- " {\n"
- " a = b;\n"
- " float4 vi = baseVertex[convexIndices[face->m_indexOffset + i]];\n"
- " b = vi;\n"
- " ab = b-a;\n"
- " ap = p-a;\n"
- " v = cross3(ab,plane);\n"
- " if (dot(ap, v) > 0.f)\n"
- " {\n"
- " float ab_m2 = dot(ab, ab);\n"
- " float rt = ab_m2 != 0.f ? dot(ab, ap) / ab_m2 : 0.f;\n"
- " if (rt <= 0.f)\n"
- " {\n"
- " *out = a;\n"
- " }\n"
- " else if (rt >= 1.f) \n"
- " {\n"
- " *out = b;\n"
- " }\n"
- " else\n"
- " {\n"
- " float s = 1.f - rt;\n"
- " out[0].x = s * a.x + rt * b.x;\n"
- " out[0].y = s * a.y + rt * b.y;\n"
- " out[0].z = s * a.z + rt * b.z;\n"
- " }\n"
- " return false;\n"
- " }\n"
- " }\n"
- " return true;\n"
- "}\n"
- "void computeContactSphereConvex(int pairIndex,\n"
- " int bodyIndexA, int bodyIndexB, \n"
- " int collidableIndexA, int collidableIndexB, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes,\n"
- " __global const float4* convexVertices,\n"
- " __global const int* convexIndices,\n"
- " __global const btGpuFace* faces,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int maxContactCapacity,\n"
- " float4 spherePos2,\n"
- " float radius,\n"
- " float4 pos,\n"
- " float4 quat\n"
- " )\n"
- "{\n"
- " float4 invPos;\n"
- " float4 invOrn;\n"
- " trInverse(pos,quat, &invPos,&invOrn);\n"
- " float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
- " int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
- " int numFaces = convexShapes[shapeIndex].m_numFaces;\n"
- " float4 closestPnt = (float4)(0, 0, 0, 0);\n"
- " float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
- " float minDist = -1000000.f;\n"
- " bool bCollide = true;\n"
- " for ( int f = 0; f < numFaces; f++ )\n"
- " {\n"
- " btGpuFace face = faces[convexShapes[shapeIndex].m_faceOffset+f];\n"
- " // set up a plane equation \n"
- " float4 planeEqn;\n"
- " float4 n1 = face.m_plane;\n"
- " n1.w = 0.f;\n"
- " planeEqn = n1;\n"
- " planeEqn.w = face.m_plane.w;\n"
- " \n"
- " \n"
- " // compute a signed distance from the vertex in cloth to the face of rigidbody.\n"
- " float4 pntReturn;\n"
- " float dist = signedDistanceFromPointToPlane(spherePos, planeEqn, &pntReturn);\n"
- " // If the distance is positive, the plane is a separating plane. \n"
- " if ( dist > radius )\n"
- " {\n"
- " bCollide = false;\n"
- " break;\n"
- " }\n"
- " if (dist>0)\n"
- " {\n"
- " //might hit an edge or vertex\n"
- " float4 out;\n"
- " float4 zeroPos = make_float4(0,0,0,0);\n"
- " bool isInPoly = IsPointInPolygon(spherePos,\n"
- " &face,\n"
- " &convexVertices[convexShapes[shapeIndex].m_vertexOffset],\n"
- " convexIndices,\n"
- " &out);\n"
- " if (isInPoly)\n"
- " {\n"
- " if (dist>minDist)\n"
- " {\n"
- " minDist = dist;\n"
- " closestPnt = pntReturn;\n"
- " hitNormalWorld = planeEqn;\n"
- " \n"
- " }\n"
- " } else\n"
- " {\n"
- " float4 tmp = spherePos-out;\n"
- " float l2 = dot(tmp,tmp);\n"
- " if (l2<radius*radius)\n"
- " {\n"
- " dist = sqrt(l2);\n"
- " if (dist>minDist)\n"
- " {\n"
- " minDist = dist;\n"
- " closestPnt = out;\n"
- " hitNormalWorld = tmp/dist;\n"
- " \n"
- " }\n"
- " \n"
- " } else\n"
- " {\n"
- " bCollide = false;\n"
- " break;\n"
- " }\n"
- " }\n"
- " } else\n"
- " {\n"
- " if ( dist > minDist )\n"
- " {\n"
- " minDist = dist;\n"
- " closestPnt = pntReturn;\n"
- " hitNormalWorld.xyz = planeEqn.xyz;\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- " \n"
- " if (bCollide && minDist > -10000)\n"
- " {\n"
- " float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
- " float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
- " \n"
- " float actualDepth = minDist-radius;\n"
- " if (actualDepth<=0.f)\n"
- " {\n"
- " \n"
- " pOnB1.w = actualDepth;\n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " \n"
- " \n"
- " if (1)//dstIdx < maxContactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
- " c->m_worldPosB[0] = pOnB1;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " GET_NPOINTS(*c) = 1;\n"
- " } \n"
- " }\n"
- " }//if (hasCollision)\n"
- "}\n"
- " \n"
- "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
- "{\n"
- " if( nPoints == 0 )\n"
- " return 0;\n"
- " \n"
- " if (nPoints <=4)\n"
- " return nPoints;\n"
- " \n"
- " \n"
- " if (nPoints >64)\n"
- " nPoints = 64;\n"
- " \n"
- " float4 center = make_float4(0.f);\n"
- " {\n"
- " \n"
- " for (int i=0;i<nPoints;i++)\n"
- " center += p[i];\n"
- " center /= (float)nPoints;\n"
- " }\n"
- " \n"
- " \n"
- " \n"
- " // sample 4 directions\n"
- " \n"
- " float4 aVector = p[0] - center;\n"
- " float4 u = cross3( nearNormal, aVector );\n"
- " float4 v = cross3( nearNormal, u );\n"
- " u = normalize3( u );\n"
- " v = normalize3( v );\n"
- " \n"
- " \n"
- " //keep point with deepest penetration\n"
- " float minW= FLT_MAX;\n"
- " \n"
- " int minIndex=-1;\n"
- " \n"
- " float4 maxDots;\n"
- " maxDots.x = FLT_MIN;\n"
- " maxDots.y = FLT_MIN;\n"
- " maxDots.z = FLT_MIN;\n"
- " maxDots.w = FLT_MIN;\n"
- " \n"
- " // idx, distance\n"
- " for(int ie = 0; ie<nPoints; ie++ )\n"
- " {\n"
- " if (p[ie].w<minW)\n"
- " {\n"
- " minW = p[ie].w;\n"
- " minIndex=ie;\n"
- " }\n"
- " float f;\n"
- " float4 r = p[ie]-center;\n"
- " f = dot3F4( u, r );\n"
- " if (f<maxDots.x)\n"
- " {\n"
- " maxDots.x = f;\n"
- " contactIdx[0].x = ie;\n"
- " }\n"
- " \n"
- " f = dot3F4( -u, r );\n"
- " if (f<maxDots.y)\n"
- " {\n"
- " maxDots.y = f;\n"
- " contactIdx[0].y = ie;\n"
- " }\n"
- " \n"
- " \n"
- " f = dot3F4( v, r );\n"
- " if (f<maxDots.z)\n"
- " {\n"
- " maxDots.z = f;\n"
- " contactIdx[0].z = ie;\n"
- " }\n"
- " \n"
- " f = dot3F4( -v, r );\n"
- " if (f<maxDots.w)\n"
- " {\n"
- " maxDots.w = f;\n"
- " contactIdx[0].w = ie;\n"
- " }\n"
- " \n"
- " }\n"
- " \n"
- " if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
- " {\n"
- " //replace the first contact with minimum (todo: replace contact with least penetration)\n"
- " contactIdx[0].x = minIndex;\n"
- " }\n"
- " \n"
- " return 4;\n"
- " \n"
- "}\n"
- "#define MAX_PLANE_CONVEX_POINTS 64\n"
- "int computeContactPlaneConvex(int pairIndex,\n"
- " int bodyIndexA, int bodyIndexB, \n"
- " int collidableIndexA, int collidableIndexB, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu*collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes,\n"
- " __global const float4* convexVertices,\n"
- " __global const int* convexIndices,\n"
- " __global const btGpuFace* faces,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int maxContactCapacity,\n"
- " float4 posB,\n"
- " Quaternion ornB\n"
- " )\n"
- "{\n"
- " int resultIndex=-1;\n"
- " int shapeIndex = collidables[collidableIndexB].m_shapeIndex;\n"
- " __global const ConvexPolyhedronCL* hullB = &convexShapes[shapeIndex];\n"
- " \n"
- " float4 posA;\n"
- " posA = rigidBodies[bodyIndexA].m_pos;\n"
- " Quaternion ornA;\n"
- " ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " float4 planeEq;\n"
- " planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
- " float4 planeNormal = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
- " float4 planeNormalWorld;\n"
- " planeNormalWorld = qtRotate(ornA,planeNormal);\n"
- " float planeConstant = planeEq.w;\n"
- " \n"
- " float4 invPosA;Quaternion invOrnA;\n"
- " float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
- " {\n"
- " \n"
- " trInverse(posA,ornA,&invPosA,&invOrnA);\n"
- " trMul(invPosA,invOrnA,posB,ornB,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
- " }\n"
- " float4 invPosB;Quaternion invOrnB;\n"
- " float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
- " {\n"
- " \n"
- " trInverse(posB,ornB,&invPosB,&invOrnB);\n"
- " trMul(invPosB,invOrnB,posA,ornA,&planeInConvexPos1,&planeInConvexOrn1); \n"
- " }\n"
- " \n"
- " float4 planeNormalInConvex = qtRotate(planeInConvexOrn1,-planeNormal);\n"
- " float maxDot = -1e30;\n"
- " int hitVertex=-1;\n"
- " float4 hitVtx;\n"
- " float4 contactPoints[MAX_PLANE_CONVEX_POINTS];\n"
- " int numPoints = 0;\n"
- " int4 contactIdx;\n"
- " contactIdx=make_int4(0,1,2,3);\n"
- " \n"
- " \n"
- " for (int i=0;i<hullB->m_numVertices;i++)\n"
- " {\n"
- " float4 vtx = convexVertices[hullB->m_vertexOffset+i];\n"
- " float curDot = dot(vtx,planeNormalInConvex);\n"
- " if (curDot>maxDot)\n"
- " {\n"
- " hitVertex=i;\n"
- " maxDot=curDot;\n"
- " hitVtx = vtx;\n"
- " //make sure the deepest points is always included\n"
- " if (numPoints==MAX_PLANE_CONVEX_POINTS)\n"
- " numPoints--;\n"
- " }\n"
- " if (numPoints<MAX_PLANE_CONVEX_POINTS)\n"
- " {\n"
- " float4 vtxWorld = transform(&vtx, &posB, &ornB);\n"
- " float4 vtxInPlane = transform(&vtxWorld, &invPosA, &invOrnA);//oplaneTransform.inverse()*vtxWorld;\n"
- " float dist = dot(planeNormal,vtxInPlane)-planeConstant;\n"
- " if (dist<0.f)\n"
- " {\n"
- " vtxWorld.w = dist;\n"
- " contactPoints[numPoints] = vtxWorld;\n"
- " numPoints++;\n"
- " }\n"
- " }\n"
- " }\n"
- " int numReducedPoints = numPoints;\n"
- " if (numPoints>4)\n"
- " {\n"
- " numReducedPoints = extractManifoldSequential( contactPoints, numPoints, planeNormalInConvex, &contactIdx);\n"
- " }\n"
- " if (numReducedPoints>0)\n"
- " {\n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " if (dstIdx < maxContactCapacity)\n"
- " {\n"
- " resultIndex = dstIdx;\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -planeNormalWorld;\n"
- " //c->setFrictionCoeff(0.7);\n"
- " //c->setRestituitionCoeff(0.f);\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " switch (numReducedPoints)\n"
- " {\n"
- " case 4:\n"
- " c->m_worldPosB[3] = contactPoints[contactIdx.w];\n"
- " case 3:\n"
- " c->m_worldPosB[2] = contactPoints[contactIdx.z];\n"
- " case 2:\n"
- " c->m_worldPosB[1] = contactPoints[contactIdx.y];\n"
- " case 1:\n"
- " c->m_worldPosB[0] = contactPoints[contactIdx.x];\n"
- " default:\n"
- " {\n"
- " }\n"
- " };\n"
- " \n"
- " GET_NPOINTS(*c) = numReducedPoints;\n"
- " }//if (dstIdx < numPairs)\n"
- " } \n"
- " return resultIndex;\n"
- "}\n"
- "void computeContactPlaneSphere(int pairIndex,\n"
- " int bodyIndexA, int bodyIndexB, \n"
- " int collidableIndexA, int collidableIndexB, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const btGpuFace* faces,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int maxContactCapacity)\n"
- "{\n"
- " float4 planeEq = faces[collidables[collidableIndexA].m_shapeIndex].m_plane;\n"
- " float radius = collidables[collidableIndexB].m_radius;\n"
- " float4 posA1 = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 ornA1 = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 posB1 = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 ornB1 = rigidBodies[bodyIndexB].m_quat;\n"
- " \n"
- " bool hasCollision = false;\n"
- " float4 planeNormal1 = make_float4(planeEq.x,planeEq.y,planeEq.z,0.f);\n"
- " float planeConstant = planeEq.w;\n"
- " float4 convexInPlaneTransPos1; Quaternion convexInPlaneTransOrn1;\n"
- " {\n"
- " float4 invPosA;Quaternion invOrnA;\n"
- " trInverse(posA1,ornA1,&invPosA,&invOrnA);\n"
- " trMul(invPosA,invOrnA,posB1,ornB1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
- " }\n"
- " float4 planeInConvexPos1; Quaternion planeInConvexOrn1;\n"
- " {\n"
- " float4 invPosB;Quaternion invOrnB;\n"
- " trInverse(posB1,ornB1,&invPosB,&invOrnB);\n"
- " trMul(invPosB,invOrnB,posA1,ornA1,&planeInConvexPos1,&planeInConvexOrn1); \n"
- " }\n"
- " float4 vtx1 = qtRotate(planeInConvexOrn1,-planeNormal1)*radius;\n"
- " float4 vtxInPlane1 = transform(&vtx1,&convexInPlaneTransPos1,&convexInPlaneTransOrn1);\n"
- " float distance = dot3F4(planeNormal1,vtxInPlane1) - planeConstant;\n"
- " hasCollision = distance < 0.f;//m_manifoldPtr->getContactBreakingThreshold();\n"
- " if (hasCollision)\n"
- " {\n"
- " float4 vtxInPlaneProjected1 = vtxInPlane1 - distance*planeNormal1;\n"
- " float4 vtxInPlaneWorld1 = transform(&vtxInPlaneProjected1,&posA1,&ornA1);\n"
- " float4 normalOnSurfaceB1 = qtRotate(ornA1,planeNormal1);\n"
- " float4 pOnB1 = vtxInPlaneWorld1+normalOnSurfaceB1*distance;\n"
- " pOnB1.w = distance;\n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " \n"
- " if (dstIdx < maxContactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
- " c->m_worldPosB[0] = pOnB1;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " GET_NPOINTS(*c) = 1;\n"
- " }//if (dstIdx < numPairs)\n"
- " }//if (hasCollision)\n"
- "}\n"
- "__kernel void primitiveContactsKernel( __global int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int numPairs, int maxContactCapacity)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " float4 worldVertsB1[64];\n"
- " float4 worldVertsB2[64];\n"
- " int capacityWorldVerts = 64; \n"
- " float4 localContactsOut[64];\n"
- " int localContactCapacity=64;\n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " if (i<numPairs)\n"
- " {\n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
- " {\n"
- " float4 posB;\n"
- " posB = rigidBodies[bodyIndexB].m_pos;\n"
- " Quaternion ornB;\n"
- " ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " int contactIndex = computeContactPlaneConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,\n"
- " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity, posB,ornB);\n"
- " if (contactIndex>=0)\n"
- " pairs[pairIndex].z = contactIndex;\n"
- " return;\n"
- " }\n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
- " {\n"
- " float4 posA;\n"
- " posA = rigidBodies[bodyIndexA].m_pos;\n"
- " Quaternion ornA;\n"
- " ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " int contactIndex = computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,\n"
- " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
- " if (contactIndex>=0)\n"
- " pairs[pairIndex].z = contactIndex;\n"
- " return;\n"
- " }\n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_PLANE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " computeContactPlaneSphere(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
- " rigidBodies,collidables,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
- " return;\n"
- " }\n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_PLANE)\n"
- " {\n"
- " computeContactPlaneSphere( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
- " rigidBodies,collidables,\n"
- " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity);\n"
- " return;\n"
- " }\n"
- " \n"
- " \n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_CONVEX_HULL)\n"
- " {\n"
- " \n"
- " float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
- " float sphereRadius = collidables[collidableIndexA].m_radius;\n"
- " float4 convexPos = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 convexOrn = rigidBodies[bodyIndexB].m_quat;\n"
- " computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
- " spherePos,sphereRadius,convexPos,convexOrn);\n"
- " return;\n"
- " }\n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_CONVEX_HULL &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " \n"
- " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
- " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
- " float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
- " computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
- " spherePos,sphereRadius,convexPos,convexOrn);\n"
- " return;\n"
- " }\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " \n"
- " \n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " //sphere-sphere\n"
- " float radiusA = collidables[collidableIndexA].m_radius;\n"
- " float radiusB = collidables[collidableIndexB].m_radius;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 diff = posA-posB;\n"
- " float len = length(diff);\n"
- " \n"
- " ///iff distance positive, don't generate a new contact\n"
- " if ( len <= (radiusA+radiusB))\n"
- " {\n"
- " ///distance (negative means penetration)\n"
- " float dist = len - (radiusA+radiusB);\n"
- " float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
- " if (len > 0.00001)\n"
- " {\n"
- " normalOnSurfaceB = diff / len;\n"
- " }\n"
- " float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
- " contactPosB.w = dist;\n"
- " \n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " \n"
- " if (dstIdx < maxContactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = normalOnSurfaceB;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_worldPosB[0] = contactPosB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " GET_NPOINTS(*c) = 1;\n"
- " }//if (dstIdx < numPairs)\n"
- " }//if ( len <= (radiusA+radiusB))\n"
- " return;\n"
- " }//SHAPE_SPHERE SHAPE_SPHERE\n"
- " }// if (i<numPairs)\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void processCompoundPairsPrimitivesKernel( __global const int4* gpuCompoundPairs,\n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int numCompoundPairs, int maxContactCapacity\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i<numCompoundPairs)\n"
- " {\n"
- " int bodyIndexA = gpuCompoundPairs[i].x;\n"
- " int bodyIndexB = gpuCompoundPairs[i].y;\n"
- " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
- " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
- " \n"
- " int collidableIndexA = -1;\n"
- " int collidableIndexB = -1;\n"
- " \n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " \n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " \n"
- " if (childShapeIndexA >= 0)\n"
- " {\n"
- " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
- " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
- " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
- " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
- " float4 newOrnA = qtMul(ornA,childOrnA);\n"
- " posA = newPosA;\n"
- " ornA = newOrnA;\n"
- " } else\n"
- " {\n"
- " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " }\n"
- " \n"
- " if (childShapeIndexB>=0)\n"
- " {\n"
- " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " } else\n"
- " {\n"
- " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
- " }\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
- " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
- " int pairIndex = i;\n"
- " if ((shapeTypeA == SHAPE_PLANE) && (shapeTypeB==SHAPE_CONVEX_HULL))\n"
- " {\n"
- " computeContactPlaneConvex( pairIndex, bodyIndexA,bodyIndexB, collidableIndexA,collidableIndexB, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,\n"
- " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posB,ornB);\n"
- " return;\n"
- " }\n"
- " if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB==SHAPE_PLANE))\n"
- " {\n"
- " computeContactPlaneConvex( pairIndex, bodyIndexB,bodyIndexA, collidableIndexB,collidableIndexA, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,\n"
- " faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,posA,ornA);\n"
- " return;\n"
- " }\n"
- " if ((shapeTypeA == SHAPE_CONVEX_HULL) && (shapeTypeB == SHAPE_SPHERE))\n"
- " {\n"
- " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
- " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
- " float4 convexPos = posA;\n"
- " float4 convexOrn = ornA;\n"
- " \n"
- " computeContactSphereConvex(pairIndex, bodyIndexB, bodyIndexA , collidableIndexB,collidableIndexA, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
- " spherePos,sphereRadius,convexPos,convexOrn);\n"
- " \n"
- " return;\n"
- " }\n"
- " if ((shapeTypeA == SHAPE_SPHERE) && (shapeTypeB == SHAPE_CONVEX_HULL))\n"
- " {\n"
- " float4 spherePos = rigidBodies[bodyIndexA].m_pos;\n"
- " float sphereRadius = collidables[collidableIndexA].m_radius;\n"
- " float4 convexPos = posB;\n"
- " float4 convexOrn = ornB;\n"
- " \n"
- " computeContactSphereConvex(pairIndex, bodyIndexA, bodyIndexB, collidableIndexA, collidableIndexB, \n"
- " rigidBodies,collidables,convexShapes,vertices,indices,faces, globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
- " spherePos,sphereRadius,convexPos,convexOrn);\n"
- " \n"
- " return;\n"
- " }\n"
- " }// if (i<numCompoundPairs)\n"
- "}\n"
- "bool pointInTriangle(const float4* vertices, const float4* normal, float4 *p )\n"
- "{\n"
- " const float4* p1 = &vertices[0];\n"
- " const float4* p2 = &vertices[1];\n"
- " const float4* p3 = &vertices[2];\n"
- " float4 edge1; edge1 = (*p2 - *p1);\n"
- " float4 edge2; edge2 = ( *p3 - *p2 );\n"
- " float4 edge3; edge3 = ( *p1 - *p3 );\n"
- " \n"
- " float4 p1_to_p; p1_to_p = ( *p - *p1 );\n"
- " float4 p2_to_p; p2_to_p = ( *p - *p2 );\n"
- " float4 p3_to_p; p3_to_p = ( *p - *p3 );\n"
- " float4 edge1_normal; edge1_normal = ( cross(edge1,*normal));\n"
- " float4 edge2_normal; edge2_normal = ( cross(edge2,*normal));\n"
- " float4 edge3_normal; edge3_normal = ( cross(edge3,*normal));\n"
- " \n"
- " \n"
- " float r1, r2, r3;\n"
- " r1 = dot(edge1_normal,p1_to_p );\n"
- " r2 = dot(edge2_normal,p2_to_p );\n"
- " r3 = dot(edge3_normal,p3_to_p );\n"
- " \n"
- " if ( r1 > 0 && r2 > 0 && r3 > 0 )\n"
- " return true;\n"
- " if ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) \n"
- " return true;\n"
- " return false;\n"
- "}\n"
- "float segmentSqrDistance(float4 from, float4 to,float4 p, float4* nearest) \n"
- "{\n"
- " float4 diff = p - from;\n"
- " float4 v = to - from;\n"
- " float t = dot(v,diff);\n"
- " \n"
- " if (t > 0) \n"
- " {\n"
- " float dotVV = dot(v,v);\n"
- " if (t < dotVV) \n"
- " {\n"
- " t /= dotVV;\n"
- " diff -= t*v;\n"
- " } else \n"
- " {\n"
- " t = 1;\n"
- " diff -= v;\n"
- " }\n"
- " } else\n"
- " {\n"
- " t = 0;\n"
- " }\n"
- " *nearest = from + t*v;\n"
- " return dot(diff,diff); \n"
- "}\n"
- "void computeContactSphereTriangle(int pairIndex,\n"
- " int bodyIndexA, int bodyIndexB,\n"
- " int collidableIndexA, int collidableIndexB, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " const float4* triangleVertices,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int maxContactCapacity,\n"
- " float4 spherePos2,\n"
- " float radius,\n"
- " float4 pos,\n"
- " float4 quat,\n"
- " int faceIndex\n"
- " )\n"
- "{\n"
- " float4 invPos;\n"
- " float4 invOrn;\n"
- " trInverse(pos,quat, &invPos,&invOrn);\n"
- " float4 spherePos = transform(&spherePos2,&invPos,&invOrn);\n"
- " int numFaces = 3;\n"
- " float4 closestPnt = (float4)(0, 0, 0, 0);\n"
- " float4 hitNormalWorld = (float4)(0, 0, 0, 0);\n"
- " float minDist = -1000000.f;\n"
- " bool bCollide = false;\n"
- " \n"
- " //////////////////////////////////////\n"
- " float4 sphereCenter;\n"
- " sphereCenter = spherePos;\n"
- " const float4* vertices = triangleVertices;\n"
- " float contactBreakingThreshold = 0.f;//todo?\n"
- " float radiusWithThreshold = radius + contactBreakingThreshold;\n"
- " float4 edge10;\n"
- " edge10 = vertices[1]-vertices[0];\n"
- " edge10.w = 0.f;//is this needed?\n"
- " float4 edge20;\n"
- " edge20 = vertices[2]-vertices[0];\n"
- " edge20.w = 0.f;//is this needed?\n"
- " float4 normal = cross3(edge10,edge20);\n"
- " normal = normalize(normal);\n"
- " float4 p1ToCenter;\n"
- " p1ToCenter = sphereCenter - vertices[0];\n"
- " \n"
- " float distanceFromPlane = dot(p1ToCenter,normal);\n"
- " if (distanceFromPlane < 0.f)\n"
- " {\n"
- " //triangle facing the other way\n"
- " distanceFromPlane *= -1.f;\n"
- " normal *= -1.f;\n"
- " }\n"
- " hitNormalWorld = normal;\n"
- " bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;\n"
- " \n"
- " // Check for contact / intersection\n"
- " bool hasContact = false;\n"
- " float4 contactPoint;\n"
- " if (isInsideContactPlane) \n"
- " {\n"
- " \n"
- " if (pointInTriangle(vertices,&normal, &sphereCenter)) \n"
- " {\n"
- " // Inside the contact wedge - touches a point on the shell plane\n"
- " hasContact = true;\n"
- " contactPoint = sphereCenter - normal*distanceFromPlane;\n"
- " \n"
- " } else {\n"
- " // Could be inside one of the contact capsules\n"
- " float contactCapsuleRadiusSqr = radiusWithThreshold*radiusWithThreshold;\n"
- " float4 nearestOnEdge;\n"
- " int numEdges = 3;\n"
- " for (int i = 0; i < numEdges; i++) \n"
- " {\n"
- " float4 pa =vertices[i];\n"
- " float4 pb = vertices[(i+1)%3];\n"
- " float distanceSqr = segmentSqrDistance(pa,pb,sphereCenter, &nearestOnEdge);\n"
- " if (distanceSqr < contactCapsuleRadiusSqr) \n"
- " {\n"
- " // Yep, we're inside a capsule\n"
- " hasContact = true;\n"
- " contactPoint = nearestOnEdge;\n"
- " \n"
- " }\n"
- " \n"
- " }\n"
- " }\n"
- " }\n"
- " if (hasContact) \n"
- " {\n"
- " closestPnt = contactPoint;\n"
- " float4 contactToCenter = sphereCenter - contactPoint;\n"
- " minDist = length(contactToCenter);\n"
- " if (minDist>FLT_EPSILON)\n"
- " {\n"
- " hitNormalWorld = normalize(contactToCenter);//*(1./minDist);\n"
- " bCollide = true;\n"
- " }\n"
- " \n"
- " }\n"
- " /////////////////////////////////////\n"
- " if (bCollide && minDist > -10000)\n"
- " {\n"
- " \n"
- " float4 normalOnSurfaceB1 = qtRotate(quat,-hitNormalWorld);\n"
- " float4 pOnB1 = transform(&closestPnt,&pos,&quat);\n"
- " float actualDepth = minDist-radius;\n"
- " \n"
- " if (actualDepth<=0.f)\n"
- " {\n"
- " pOnB1.w = actualDepth;\n"
- " int dstIdx;\n"
- " \n"
- " float lenSqr = dot3F4(normalOnSurfaceB1,normalOnSurfaceB1);\n"
- " if (lenSqr>FLT_EPSILON)\n"
- " {\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " \n"
- " if (dstIdx < maxContactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -normalOnSurfaceB1;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyIndexA].m_invMass==0?-bodyIndexA:bodyIndexA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyIndexB].m_invMass==0?-bodyIndexB:bodyIndexB;\n"
- " c->m_worldPosB[0] = pOnB1;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = faceIndex;\n"
- " GET_NPOINTS(*c) = 1;\n"
- " } \n"
- " }\n"
- " }\n"
- " }//if (hasCollision)\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findConcaveSphereContactsKernel( __global int4* concavePairs,\n"
- " __global const BodyData* rigidBodies,\n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int numConcavePairs, int maxContactCapacity\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numConcavePairs)\n"
- " return;\n"
- " int pairIdx = i;\n"
- " int bodyIndexA = concavePairs[i].x;\n"
- " int bodyIndexB = concavePairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " if (collidables[collidableIndexB].m_shapeType==SHAPE_SPHERE)\n"
- " {\n"
- " int f = concavePairs[i].z;\n"
- " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
- " \n"
- " float4 verticesA[3];\n"
- " for (int i=0;i<3;i++)\n"
- " {\n"
- " int index = indices[face.m_indexOffset+i];\n"
- " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
- " verticesA[i] = vert;\n"
- " }\n"
- " float4 spherePos = rigidBodies[bodyIndexB].m_pos;\n"
- " float sphereRadius = collidables[collidableIndexB].m_radius;\n"
- " float4 convexPos = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 convexOrn = rigidBodies[bodyIndexA].m_quat;\n"
- " computeContactSphereTriangle(i, bodyIndexB, bodyIndexA, collidableIndexB, collidableIndexA, \n"
- " rigidBodies,collidables,\n"
- " verticesA,\n"
- " globalContactsOut, nGlobalContactsOut,maxContactCapacity,\n"
- " spherePos,sphereRadius,convexPos,convexOrn, f);\n"
- " return;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl
deleted file mode 100644
index a6565fd6fa..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/sat.cl
+++ /dev/null
@@ -1,2018 +0,0 @@
-//keep this enum in sync with the CPU version (in btCollidable.h)
-//written by Erwin Coumans
-
-
-#define SHAPE_CONVEX_HULL 3
-#define SHAPE_CONCAVE_TRIMESH 5
-#define TRIANGLE_NUM_CONVEX_FACES 5
-#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
-
-#define B3_MAX_STACK_DEPTH 256
-
-
-typedef unsigned int u32;
-
-///keep this in sync with btCollidable.h
-typedef struct
-{
- union {
- int m_numChildShapes;
- int m_bvhIndex;
- };
- union
- {
- float m_radius;
- int m_compoundBvhIndex;
- };
-
- int m_shapeType;
- int m_shapeIndex;
-
-} btCollidableGpu;
-
-#define MAX_NUM_PARTS_IN_BITS 10
-
-///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrTriangleIndex;
-} b3QuantizedBvhNode;
-
-typedef struct
-{
- float4 m_aabbMin;
- float4 m_aabbMax;
- float4 m_quantization;
- int m_numNodes;
- int m_numSubTrees;
- int m_nodeOffset;
- int m_subTreeOffset;
-
-} b3BvhInfo;
-
-
-int getTriangleIndex(const b3QuantizedBvhNode* rootNode)
-{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
-}
-
-int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
-}
-
-int isLeafNode(const b3QuantizedBvhNode* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
-}
-
-int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
-}
-
-int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
- //4 bytes
- int m_subtreeSize;
- int m_padding[3];
-} b3BvhSubtreeInfo;
-
-
-
-
-
-
-
-typedef struct
-{
- float4 m_childPosition;
- float4 m_childOrientation;
- int m_shapeIndex;
- int m_unused0;
- int m_unused1;
- int m_unused2;
-} btGpuChildShape;
-
-
-typedef struct
-{
- float4 m_pos;
- float4 m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} BodyData;
-
-
-typedef struct
-{
- float4 m_localCenter;
- float4 m_extents;
- float4 mC;
- float4 mE;
-
- float m_radius;
- int m_faceOffset;
- int m_numFaces;
- int m_numVertices;
-
- int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
- int m_unused;
-} ConvexPolyhedronCL;
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} btAabbCL;
-
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Common/shared/b3Int2.h"
-
-
-
-typedef struct
-{
- float4 m_plane;
- int m_indexOffset;
- int m_numIndices;
-} btGpuFace;
-
-#define make_float4 (float4)
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-
-
-// float4 a1 = make_float4(a.xyz,0.f);
-// float4 b1 = make_float4(b.xyz,0.f);
-
-// return cross(a1,b1);
-
-//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
-
- // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
-
- //return c;
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- v = make_float4(v.xyz,0.f);
- return fast_normalize(v);
-}
-
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-__inline
-float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
-{
- return qtRotate( *orientation, *p ) + (*translation);
-}
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-}
-
-inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
-const float4* dir, const float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const float4 localDir = qtInvRotate(orn,*dir);
- float offset = dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
- {
- float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
- min[0] = dp;
- if(dp > max[0])
- max[0] = dp;
- }
- if(min[0]>max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
-const float4* dir, __global const float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const float4 localDir = qtInvRotate(orn,*dir);
- float offset = dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
- {
- float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
- min[0] = dp;
- if(dp > max[0])
- max[0] = dp;
- }
- if(min[0]>max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA,const float4 ornA,
- const float4 posB,const float4 ornB,
- float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
-{
- float Min0,Max0;
- float Min1,Max1;
- projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
- project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- *depth = d0<d1 ? d0:d1;
- return true;
-}
-
-
-
-
-inline bool IsAlmostZero(const float4 v)
-{
- if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
- return false;
- return true;
-}
-
-
-
-bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
-
- const float4* verticesA,
- const float4* uniqueEdgesA,
- const btGpuFace* facesA,
- const int* indicesA,
-
- __global const float4* verticesB,
- __global const float4* uniqueEdgesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
- int curPlaneTests=0;
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for(int i=0;i<numFacesA;i++)
- {
- const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
- float4 faceANormalWS = qtRotate(ornA,normal);
- if (dot3F4(DeltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
- curPlaneTests++;
- float d;
- if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
- return false;
- if(d<*dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* verticesA,
- __global const float4* uniqueEdgesA,
- __global const btGpuFace* facesA,
- __global const int* indicesA,
- const float4* verticesB,
- const float4* uniqueEdgesB,
- const btGpuFace* facesB,
- const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
- int curPlaneTests=0;
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for(int i=0;i<numFacesA;i++)
- {
- const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
- float4 faceANormalWS = qtRotate(ornA,normal);
- if (dot3F4(DeltaC2,faceANormalWS)<0)
- faceANormalWS *= -1.f;
- curPlaneTests++;
- float d;
- if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
- return false;
- if(d<*dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-
-bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- const float4* verticesA,
- const float4* uniqueEdgesA,
- const btGpuFace* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const float4* uniqueEdgesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test edges
- for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
- {
- const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
- float4 edge0World = qtRotate(ornA,edge0);
-
- for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
- {
- const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
- float4 edge1World = qtRotate(ornB,edge1);
-
-
- float4 crossje = cross3(edge0World,edge1World);
-
- curEdgeEdge++;
- if(!IsAlmostZero(crossje))
- {
- crossje = normalize3(crossje);
- if (dot3F4(DeltaC2,crossje)<0)
- crossje *= -1.f;
-
- float dist;
- bool result = true;
- {
- float Min0,Max0;
- float Min1,Max1;
- projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
- project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- result = false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
- result = true;
-
- }
-
-
- if(dist<*dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
-
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA,const float4 ornA,
- const float4 posB,const float4 ornB,
- float4* sep_axis, __global const float4* vertices,float* depth)
-{
- float Min0,Max0;
- float Min1,Max1;
- project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);
- project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- *depth = d0<d1 ? d0:d1;
- return true;
-}
-
-
-bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for(int i=0;i<numFacesA;i++)
- {
- const float4 normal = faces[hullA->m_faceOffset+i].m_plane;
- float4 faceANormalWS = qtRotate(ornA,normal);
-
- if (dot3F4(DeltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
-
- curPlaneTests++;
-
- float d;
- if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))
- return false;
-
- if(d<*dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
-
- return true;
-}
-
-
-
-
-bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* vertices,
- __global const float4* unitSphereDirections,
- int numUnitSphereDirections,
- float4* sep,
- float* dmin)
-{
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test unit sphere directions
- for (int i=0;i<numUnitSphereDirections;i++)
- {
-
- float4 crossje;
- crossje = unitSphereDirections[i];
-
- if (dot3F4(DeltaC2,crossje)>0)
- crossje *= -1.f;
- {
- float dist;
- bool result = true;
- float Min0,Max0;
- float Min1,Max1;
- project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
- project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
- result = true;
-
- if(dist<*dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test edges
- for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
- {
- const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];
- float4 edge0World = qtRotate(ornA,edge0);
-
- for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
- {
- const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];
- float4 edge1World = qtRotate(ornB,edge1);
-
-
- float4 crossje = cross3(edge0World,edge1World);
-
- curEdgeEdge++;
- if(!IsAlmostZero(crossje))
- {
- crossje = normalize3(crossje);
- if (dot3F4(DeltaC2,crossje)<0)
- crossje*=-1.f;
-
- float dist;
- bool result = true;
- {
- float Min0,Max0;
- float Min1,Max1;
- project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);
- project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
- result = true;
-
- }
-
-
- if(dist<*dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
-
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-// work-in-progress
-__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global const btGpuChildShape* gpuChildShapes,
- __global volatile float4* gpuCompoundSepNormalsOut,
- __global volatile int* gpuHasCompoundSepNormalsOut,
- int numCompoundPairs
- )
-{
-
- int i = get_global_id(0);
- if (i<numCompoundPairs)
- {
- int bodyIndexA = gpuCompoundPairs[i].x;
- int bodyIndexB = gpuCompoundPairs[i].y;
-
- int childShapeIndexA = gpuCompoundPairs[i].z;
- int childShapeIndexB = gpuCompoundPairs[i].w;
-
- int collidableIndexA = -1;
- int collidableIndexB = -1;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
-
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- if (childShapeIndexA >= 0)
- {
- collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = qtRotate(ornA,childPosA)+posA;
- float4 newOrnA = qtMul(ornA,childOrnA);
- posA = newPosA;
- ornA = newOrnA;
- } else
- {
- collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- }
-
- if (childShapeIndexB>=0)
- {
- collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- } else
- {
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
- }
-
- gpuHasCompoundSepNormalsOut[i] = 0;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- int shapeTypeA = collidables[collidableIndexA].m_shapeType;
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
-
-
- if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))
- {
- return;
- }
-
- int hasSeparatingAxis = 5;
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- posA.w = 0.f;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal = make_float4(1,0,0,0);
- bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
- hasSeparatingAxis = 4;
- if (!sepA)
- {
- hasSeparatingAxis = 0;
- } else
- {
- bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis = 0;
- } else//(!sepB)
- {
- bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);
- if (sepEE)
- {
- gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);
- gpuHasCompoundSepNormalsOut[i] = 1;
- }//sepEE
- }//(!sepB)
- }//(!sepA)
-
-
- }
-
-}
-
-
-inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
-{
- b3Float4 vecOut;
- vecOut = b3MakeFloat4(
- (float)(vecIn[0]) / (quantization.x),
- (float)(vecIn[1]) / (quantization.y),
- (float)(vecIn[2]) / (quantization.z),
- 0.f);
-
- vecOut += bvhAabbMin;
- return vecOut;
-}
-
-inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)
-{
- b3Float4 vecOut;
- vecOut = b3MakeFloat4(
- (float)(vecIn[0]) / (quantization.x),
- (float)(vecIn[1]) / (quantization.y),
- (float)(vecIn[2]) / (quantization.z),
- 0.f);
-
- vecOut += bvhAabbMin;
- return vecOut;
-}
-
-
-// work-in-progress
-__kernel void findCompoundPairsKernel( __global const int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global b3Aabb_t* aabbLocalSpace,
- __global const btGpuChildShape* gpuChildShapes,
- __global volatile int4* gpuCompoundPairsOut,
- __global volatile int* numCompoundPairsOut,
- __global const b3BvhSubtreeInfo* subtrees,
- __global const b3QuantizedBvhNode* quantizedNodes,
- __global const b3BvhInfo* bvhInfos,
- int numPairs,
- int maxNumCompoundPairsCapacity
- )
-{
-
- int i = get_global_id(0);
-
- if (i<numPairs)
- {
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
- {
- return;
- }
-
- if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
- int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;
- int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;
- int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;
- int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;
- int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;
-
-
- int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- b3Quat ornA = rigidBodies[bodyIndexA].m_quat;
-
- b3Quat ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
-
- for (int p=0;p<numSubTreesA;p++)
- {
- b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];
- //bvhInfos[bvhA].m_quantization
- b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
- b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
-
- b3Float4 aabbAMinOut,aabbAMaxOut;
- float margin=0.f;
- b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
-
- for (int q=0;q<numSubTreesB;q++)
- {
- b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];
-
- b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
- b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
-
- b3Float4 aabbBMinOut,aabbBMaxOut;
- float margin=0.f;
- b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
-
-
-
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
- if (aabbOverlap)
- {
-
- int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;
- int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;
-
- int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;
- int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;
-
-
- b3Int2 nodeStack[B3_MAX_STACK_DEPTH];
- b3Int2 node0;
- node0.x = startNodeIndexA;
- node0.y = startNodeIndexB;
- int maxStackDepth = B3_MAX_STACK_DEPTH;
- int depth=0;
- nodeStack[depth++]=node0;
-
- do
- {
- b3Int2 node = nodeStack[--depth];
-
- b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
- b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);
-
- b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
- b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);
-
- float margin=0.f;
- b3Float4 aabbAMinOut,aabbAMaxOut;
- b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);
-
- b3Float4 aabbBMinOut,aabbBMaxOut;
- b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);
-
-
- bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);
- if (nodeOverlap)
- {
- bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);
- bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);
- bool isInternalA = !isLeafA;
- bool isInternalB = !isLeafB;
-
- //fail, even though it might hit two leaf nodes
- if (depth+4>maxStackDepth && !(isLeafA && isLeafB))
- {
- //printf("Error: traversal exceeded maxStackDepth");
- continue;
- }
-
- if(isInternalA)
- {
- int nodeAleftChild = node.x+1;
- bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);
- int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);
-
- if(isInternalB)
- {
- int nodeBleftChild = node.y+1;
- bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
- int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
-
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);
- }
- else
- {
- nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);
- nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);
- }
- }
- else
- {
- if(isInternalB)
- {
- int nodeBleftChild = node.y+1;
- bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);
- int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);
- nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);
- nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);
- }
- else
- {
- int compoundPairIdx = atomic_inc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
- {
- int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);
- int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);
- gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
- }
- }
- }
- }
- } while (depth);
- }
- }
- }
-
- return;
- }
-
-
-
-
-
- if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
-
- if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
-
- int numChildrenA = collidables[collidableIndexA].m_numChildShapes;
- for (int c=0;c<numChildrenA;c++)
- {
- int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;
- int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = qtRotate(ornA,childPosA)+posA;
- float4 newOrnA = qtMul(ornA,childOrnA);
-
- int shapeIndexA = collidables[childColIndexA].m_shapeIndex;
- b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];
- float margin = 0.f;
-
- b3Float4 aabbAMinWS;
- b3Float4 aabbAMaxWS;
-
- b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,
- newPosA,
- newOrnA,
- &aabbAMinWS,&aabbAMaxWS);
-
-
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b=0;b<numChildrenB;b++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
-
- int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];
-
- b3Float4 aabbBMinWS;
- b3Float4 aabbBMaxWS;
-
- b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,
- newPosB,
- newOrnB,
- &aabbBMinWS,&aabbBMaxWS);
-
-
-
- bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);
- if (aabbOverlap)
- {
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- float4 posA = newPosA;
- posA.w = 0.f;
- float4 posB = newPosB;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = newOrnA;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =newOrnB;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
-
- {//
- int compoundPairIdx = atomic_inc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);
- }
- }//
- }//fi(1)
- } //for (int b=0
- }//if (collidables[collidableIndexB].
- else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- if (1)
- {
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- float4 posA = newPosA;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = newOrnA;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
-
- {
- int compoundPairIdx = atomic_inc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);
- }//if (compoundPairIdx<maxNumCompoundPairsCapacity)
- }//
- }//fi (1)
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- }//for (int b=0;b<numChildrenB;b++)
- return;
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH)
- && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- {
- int numChildrenB = collidables[collidableIndexB].m_numChildShapes;
- for (int b=0;b<numChildrenB;b++)
- {
- int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = qtRotate(ornB,childPosB)+posB;
- float4 newOrnB = qtMul(ornB,childOrnB);
-
- int shapeIndexB = collidables[childColIndexB].m_shapeIndex;
-
-
- //////////////////////////////////////
-
- if (1)
- {
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- float dmin = FLT_MAX;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = newPosB;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =newOrnB;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- {//
- int compoundPairIdx = atomic_inc(numCompoundPairsOut);
- if (compoundPairIdx<maxNumCompoundPairsCapacity)
- {
- gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);
- }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)
- }//
- }//fi (1)
- }//for (int b=0;b<numChildrenB;b++)
- return;
- }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- return;
- }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))
- }//i<numPairs
-}
-
-// work-in-progress
-__kernel void findSeparatingAxisKernel( __global const int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global volatile float4* separatingNormals,
- __global volatile int* hasSeparatingAxis,
- int numPairs
- )
-{
-
- int i = get_global_id(0);
-
- if (i<numPairs)
- {
-
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
- {
- hasSeparatingAxis[i] = 0;
- return;
- }
-
-
- if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
- {
- hasSeparatingAxis[i] = 0;
- return;
- }
-
- if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))
- {
- hasSeparatingAxis[i] = 0;
- return;
- }
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
-
- float dmin = FLT_MAX;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal;
-
- bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
- hasSeparatingAxis[i] = 4;
- if (!sepA)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
- posA,ornA,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
- if (!sepEE)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- hasSeparatingAxis[i] = 1;
- separatingNormals[i] = sepNormal;
- }
- }
- }
-
- }
-
-}
-
-
-__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global volatile float4* separatingNormals,
- __global volatile int* hasSeparatingAxis,
- __global float* dmins,
- int numPairs
- )
-{
-
- int i = get_global_id(0);
-
- if (i<numPairs)
- {
-
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- hasSeparatingAxis[i] = 0;
-
- //once the broadphase avoids static-static pairs, we can remove this test
- if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))
- {
- return;
- }
-
-
- if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))
- {
- return;
- }
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
-
- float dmin = FLT_MAX;
-
- dmins[i] = dmin;
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal;
-
- bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
- hasSeparatingAxis[i] = 4;
- if (!sepA)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,
- posA,ornA,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
-
- if (sepB)
- {
- dmins[i] = dmin;
- hasSeparatingAxis[i] = 1;
- separatingNormals[i] = sepNormal;
- }
- }
-
- }
-
-}
-
-
-__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global btAabbCL* aabbs,
- __global float4* separatingNormals,
- __global int* hasSeparatingAxis,
- __global float* dmins,
- __global const float4* unitSphereDirections,
- int numUnitSphereDirections,
- int numPairs
- )
-{
-
- int i = get_global_id(0);
-
- if (i<numPairs)
- {
-
- if (hasSeparatingAxis[i])
- {
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
-
- float dmin = dmins[i];
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 c0local = convexShapes[shapeIndexA].m_localCenter;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
- float4 sepNormal = separatingNormals[i];
-
-
-
- bool sepEE = false;
- int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;
- if (numEdgeEdgeDirections<=numUnitSphereDirections)
- {
- sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,uniqueEdges,faces,
- indices,&sepNormal,&dmin);
-
- if (!sepEE)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- hasSeparatingAxis[i] = 1;
- separatingNormals[i] = sepNormal;
- }
- }
- /*
- ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy
- else
- {
- sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,
- posB,ornB,
- DeltaC2,
- vertices,unitSphereDirections,numUnitSphereDirections,
- &sepNormal,&dmin);
- if (!sepEE)
- {
- hasSeparatingAxis[i] = 0;
- } else
- {
- hasSeparatingAxis[i] = 1;
- separatingNormals[i] = sepNormal;
- }
- }
- */
- } //if (hasSeparatingAxis[i])
- }//(i<numPairs)
-}
-
-
-
-
-
-inline int findClippingFaces(const float4 separatingNormal,
- const ConvexPolyhedronCL* hullA,
- __global const ConvexPolyhedronCL* hullB,
- const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
- __global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- int capacityWorldVerts,
- const float minDist, float maxDist,
- const float4* verticesA,
- const btGpuFace* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- __global int4* clippingFaces, int pairIndex)
-{
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=0;
- float dmax = -FLT_MAX;
-
- {
- for(int face=0;face<hullB->m_numFaces;face++)
- {
- const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
- facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
- const float4 WorldNormal = qtRotate(ornB, Normal);
- float d = dot3F4(WorldNormal,separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
- int numVertices = polyB.m_numIndices;
- if (numVertices>capacityWorldVerts)
- numVertices = capacityWorldVerts;
-
- for(int e0=0;e0<numVertices;e0++)
- {
- if (e0<capacityWorldVerts)
- {
- const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
- }
- }
- }
-
- int closestFaceA=0;
- {
- float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
- {
- const float4 Normal = make_float4(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,
- 0.f);
- const float4 faceANormalWS = qtRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- worldNormalsA1[pairIndex] = faceANormalWS;
- }
- }
- }
-
- int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
- if (numVerticesA>capacityWorldVerts)
- numVerticesA = capacityWorldVerts;
-
- for(int e0=0;e0<numVerticesA;e0++)
- {
- if (e0<capacityWorldVerts)
- {
- const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
- worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
- }
- }
-
- clippingFaces[pairIndex].x = closestFaceA;
- clippingFaces[pairIndex].y = closestFaceB;
- clippingFaces[pairIndex].z = numVerticesA;
- clippingFaces[pairIndex].w = numWorldVertsB1;
-
-
- return numContactsOut;
-}
-
-
-
-
-// work-in-progress
-__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global const btGpuChildShape* gpuChildShapes,
- __global btAabbCL* aabbs,
- __global float4* concaveSeparatingNormalsOut,
- __global int* concaveHasSeparatingNormals,
- __global int4* clippingFacesOut,
- __global float4* worldVertsA1GPU,
- __global float4* worldNormalsAGPU,
- __global float4* worldVertsB1GPU,
- int vertexFaceCapacity,
- int numConcavePairs
- )
-{
-
- int i = get_global_id(0);
- if (i>=numConcavePairs)
- return;
-
- concaveHasSeparatingNormals[i] = 0;
-
- int pairIdx = i;
-
- int bodyIndexA = concavePairs[i].x;
- int bodyIndexB = concavePairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
- collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- concavePairs[pairIdx].w = -1;
- return;
- }
-
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- int numActualConcaveConvexTests = 0;
-
- int f = concavePairs[i].z;
-
- bool overlap = false;
-
- ConvexPolyhedronCL convexPolyhedronA;
-
- //add 3 vertices of the triangle
- convexPolyhedronA.m_numVertices = 3;
- convexPolyhedronA.m_vertexOffset = 0;
- float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
-
- btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
- float4 triMinAabb, triMaxAabb;
- btAabbCL triAabb;
- triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
- triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
-
- float4 verticesA[3];
- for (int i=0;i<3;i++)
- {
- int index = indices[face.m_indexOffset+i];
- float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
- verticesA[i] = vert;
- localCenter += vert;
-
- triAabb.m_min = min(triAabb.m_min,vert);
- triAabb.m_max = max(triAabb.m_max,vert);
-
- }
-
- overlap = true;
- overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
- overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
- overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
-
- if (overlap)
- {
- float dmin = FLT_MAX;
- int hasSeparatingAxis=5;
- float4 sepAxis=make_float4(1,2,3,4);
-
- int localCC=0;
- numActualConcaveConvexTests++;
-
- //a triangle has 3 unique edges
- convexPolyhedronA.m_numUniqueEdges = 3;
- convexPolyhedronA.m_uniqueEdgesOffset = 0;
- float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
-
-
- convexPolyhedronA.m_faceOffset = 0;
-
- float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
-
- btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3+3+2+2+2];
- int curUsedIndices=0;
- int fidx=0;
-
- //front size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[0] = 0;
- indicesA[1] = 1;
- indicesA[2] = 2;
- curUsedIndices+=3;
- float c = face.m_plane.w;
- facesA[fidx].m_plane.x = normal.x;
- facesA[fidx].m_plane.y = normal.y;
- facesA[fidx].m_plane.z = normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
- //back size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[3]=2;
- indicesA[4]=1;
- indicesA[5]=0;
- curUsedIndices+=3;
- float c = dot(normal,verticesA[0]);
- float c1 = -face.m_plane.w;
- facesA[fidx].m_plane.x = -normal.x;
- facesA[fidx].m_plane.y = -normal.y;
- facesA[fidx].m_plane.z = -normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
-
- bool addEdgePlanes = true;
- if (addEdgePlanes)
- {
- int numVertices=3;
- int prevVertex = numVertices-1;
- for (int i=0;i<numVertices;i++)
- {
- float4 v0 = verticesA[i];
- float4 v1 = verticesA[prevVertex];
-
- float4 edgeNormal = normalize(cross(normal,v1-v0));
- float c = -dot(edgeNormal,v0);
-
- facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[curUsedIndices++]=i;
- indicesA[curUsedIndices++]=prevVertex;
-
- facesA[fidx].m_plane.x = edgeNormal.x;
- facesA[fidx].m_plane.y = edgeNormal.y;
- facesA[fidx].m_plane.z = edgeNormal.z;
- facesA[fidx].m_plane.w = c;
- fidx++;
- prevVertex = i;
- }
- }
- convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
-
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
-
-
-
-
- ///////////////////
- ///compound shape support
-
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int compoundChild = concavePairs[pairIdx].w;
- int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- }
- //////////////////
-
- float4 c0local = convexPolyhedronA.m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
-
-
- bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin);
- hasSeparatingAxis = 4;
- if (!sepA)
- {
- hasSeparatingAxis = 0;
- } else
- {
- bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,
- posB,ornB,
- posA,ornA,
- DeltaC2,
- vertices,uniqueEdges,faces,indices,
- verticesA,uniqueEdgesA,facesA,indicesA,
- &sepAxis,&dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis = 0;
- } else
- {
- bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin);
-
- if (!sepEE)
- {
- hasSeparatingAxis = 0;
- } else
- {
- hasSeparatingAxis = 1;
- }
- }
- }
-
- if (hasSeparatingAxis)
- {
- sepAxis.w = dmin;
- concaveSeparatingNormalsOut[pairIdx]=sepAxis;
- concaveHasSeparatingNormals[i]=1;
-
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
-
-
- findClippingFaces(sepAxis,
- &convexPolyhedronA,
- &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsA1GPU,
- worldNormalsAGPU,
- worldVertsB1GPU,
- vertexFaceCapacity,
- minDist, maxDist,
- verticesA,
- facesA,
- indicesA,
- vertices,
- faces,
- indices,
- clippingFacesOut, pairIdx);
-
-
- } else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
- }
- else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
-
- concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts
-}
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl
deleted file mode 100644
index f433971741..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.cl
+++ /dev/null
@@ -1,1888 +0,0 @@
-
-#define TRIANGLE_NUM_CONVEX_FACES 5
-
-
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile __global int*
-#endif
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-#define max2 max
-#define min2 min
-
-typedef unsigned int u32;
-
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-
-
-#define GET_NPOINTS(x) (x).m_worldNormalOnB.w
-
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-__inline
-float fastDiv(float numerator, float denominator)
-{
- return native_divide(numerator, denominator);
-// return numerator/denominator;
-}
-
-__inline
-float4 fastDiv4(float4 numerator, float4 denominator)
-{
- return native_divide(numerator, denominator);
-}
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-//#define dot3F4 dot
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-__inline
-float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
-{
- return qtRotate( *orientation, *p ) + (*translation);
-}
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-}
-
-
-__inline float4 lerp3(const float4 a,const float4 b, float t)
-{
- return make_float4( a.x + (b.x - a.x) * t,
- a.y + (b.y - a.y) * t,
- a.z + (b.z - a.z) * t,
- 0.f);
-}
-
-
-
-// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)
-{
-
- int ve;
- float ds, de;
- int numVertsOut = 0;
- //double-check next test
- if (numVertsIn < 2)
- return 0;
-
- float4 firstVertex=pVtxIn[numVertsIn-1];
- float4 endVertex = pVtxIn[0];
-
- ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
-
- for (ve = 0; ve < numVertsIn; ve++)
- {
- endVertex=pVtxIn[ve];
- de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
- if (ds<0)
- {
- if (de<0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut[numVertsOut++] = endVertex;
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
- }
- }
- else
- {
- if (de<0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
- ppVtxOut[numVertsOut++] = endVertex;
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
- return numVertsOut;
-}
-
-
-
-// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut
-int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)
-{
-
- int ve;
- float ds, de;
- int numVertsOut = 0;
-//double-check next test
- if (numVertsIn < 2)
- return 0;
-
- float4 firstVertex=pVtxIn[numVertsIn-1];
- float4 endVertex = pVtxIn[0];
-
- ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;
-
- for (ve = 0; ve < numVertsIn; ve++)
- {
- endVertex=pVtxIn[ve];
-
- de = dot3F4(planeNormalWS,endVertex)+planeEqWS;
-
- if (ds<0)
- {
- if (de<0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut[numVertsOut++] = endVertex;
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
- }
- }
- else
- {
- if (de<0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );
- ppVtxOut[numVertsOut++] = endVertex;
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
- return numVertsOut;
-}
-
-
-int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA,
- const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
- float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- __global const float4* vertices,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
-
- float4* pVtxIn = worldVertsB1;
- float4* pVtxOut = worldVertsB2;
-
- int numVertsIn = numWorldVertsB1;
- int numVertsOut = 0;
-
- int closestFaceA=-1;
- {
- float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
- {
- const float4 Normal = make_float4(
- faces[hullA->m_faceOffset+face].m_plane.x,
- faces[hullA->m_faceOffset+face].m_plane.y,
- faces[hullA->m_faceOffset+face].m_plane.z,0.f);
- const float4 faceANormalWS = qtRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- }
- }
- }
- if (closestFaceA<0)
- return numContactsOut;
-
- b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- int numVerticesA = polyA.m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
- {
- const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];
- const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
- const float4 edge0 = a - b;
- const float4 WorldEdge0 = qtRotate(ornA,edge0);
- float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
-
- float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
- float4 worldA1 = transform(&a,&posA,&ornA);
- float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
-
- float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
-
- //clip face
- //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
-
- //btSwap(pVtxIn,pVtxOut);
- float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsIn = numVertsOut;
- numVertsOut = 0;
- }
-
-
- // only keep points that are behind the witness face
- {
- float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- float localPlaneEq = polyA.m_plane.w;
- float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
- float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
- for (int i=0;i<numVertsIn;i++)
- {
- float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
- {
- depth = minDist;
- }
-
- if (depth <=maxDist)
- {
- float4 pointInWorld = pVtxIn[i];
- //resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
- }
- }
- }
-
- return numContactsOut;
-}
-
-
-
-int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA,
- const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,
- float4* worldVertsB2, int capacityWorldVertsB2,
- const float minDist, float maxDist,
- const float4* verticesA,
- const b3GpuFace_t* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const b3GpuFace_t* facesB,
- __global const int* indicesB,
- float4* contactsOut,
- int contactCapacity)
-{
- int numContactsOut = 0;
-
- float4* pVtxIn = worldVertsB1;
- float4* pVtxOut = worldVertsB2;
-
- int numVertsIn = numWorldVertsB1;
- int numVertsOut = 0;
-
- int closestFaceA=-1;
- {
- float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
- {
- const float4 Normal = make_float4(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,0.f);
- const float4 faceANormalWS = qtRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- }
- }
- }
- if (closestFaceA<0)
- return numContactsOut;
-
- b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- int numVerticesA = polyA.m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
- {
- const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];
- const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];
- const float4 edge0 = a - b;
- const float4 WorldEdge0 = qtRotate(ornA,edge0);
- float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);
-
- float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
- float4 worldA1 = transform(&a,&posA,&ornA);
- float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
-
- float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
-
- //clip face
- //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);
- numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);
-
- //btSwap(pVtxIn,pVtxOut);
- float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsIn = numVertsOut;
- numVertsOut = 0;
- }
-
-
- // only keep points that are behind the witness face
- {
- float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);
- float localPlaneEq = polyA.m_plane.w;
- float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);
- float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);
- for (int i=0;i<numVertsIn;i++)
- {
- float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
- {
- depth = minDist;
- }
-
- if (depth <=maxDist)
- {
- float4 pointInWorld = pVtxIn[i];
- //resultOut.addContactPoint(separatingNormal,point,depth);
- contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
- }
- }
- }
-
- return numContactsOut;
-}
-
-int clipHullAgainstHull(const float4 separatingNormal,
- __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
- float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- __global const float4* vertices,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- float4* localContactsOut,
- int localContactCapacity)
-{
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=-1;
- float dmax = -FLT_MAX;
-
- {
- for(int face=0;face<hullB->m_numFaces;face++)
- {
- const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,
- faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
- const float4 WorldNormal = qtRotate(ornB, Normal);
- float d = dot3F4(WorldNormal,separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
- {
- const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
- worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
- }
- }
-
- if (closestFaceB>=0)
- {
- numContactsOut = clipFaceAgainstHull(separatingNormal, hullA,
- posA,ornA,
- worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,
- faces,
- indices,localContactsOut,localContactCapacity);
- }
-
- return numContactsOut;
-}
-
-
-int clipHullAgainstHullLocalA(const float4 separatingNormal,
- const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
- float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,
- const float minDist, float maxDist,
- const float4* verticesA,
- const b3GpuFace_t* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const b3GpuFace_t* facesB,
- __global const int* indicesB,
- float4* localContactsOut,
- int localContactCapacity)
-{
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=-1;
- float dmax = -FLT_MAX;
-
- {
- for(int face=0;face<hullB->m_numFaces;face++)
- {
- const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
- facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
- const float4 WorldNormal = qtRotate(ornB, Normal);
- float d = dot3F4(WorldNormal,separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
- {
- const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);
- }
- }
-
- if (closestFaceB>=0)
- {
- numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA,
- posA,ornA,
- worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,
- verticesA,facesA,indicesA,
- verticesB,facesB,indicesB,
- localContactsOut,localContactCapacity);
- }
-
- return numContactsOut;
-}
-
-#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];
-#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}
-#define REDUCE_MAX(v, n) {int i=0;\
-for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }
-#define REDUCE_MIN(v, n) {int i=0;\
-for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }
-
-int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)
-{
- if( nPoints == 0 )
- return 0;
-
- if (nPoints <=4)
- return nPoints;
-
-
- if (nPoints >64)
- nPoints = 64;
-
- float4 center = make_float4(0.f);
- {
-
- for (int i=0;i<nPoints;i++)
- center += p[i];
- center /= (float)nPoints;
- }
-
-
-
- // sample 4 directions
-
- float4 aVector = p[0] - center;
- float4 u = cross3( nearNormal, aVector );
- float4 v = cross3( nearNormal, u );
- u = normalize3( u );
- v = normalize3( v );
-
-
- //keep point with deepest penetration
- float minW= FLT_MAX;
-
- int minIndex=-1;
-
- float4 maxDots;
- maxDots.x = FLT_MIN;
- maxDots.y = FLT_MIN;
- maxDots.z = FLT_MIN;
- maxDots.w = FLT_MIN;
-
- // idx, distance
- for(int ie = 0; ie<nPoints; ie++ )
- {
- if (p[ie].w<minW)
- {
- minW = p[ie].w;
- minIndex=ie;
- }
- float f;
- float4 r = p[ie]-center;
- f = dot3F4( u, r );
- if (f<maxDots.x)
- {
- maxDots.x = f;
- contactIdx[0].x = ie;
- }
-
- f = dot3F4( -u, r );
- if (f<maxDots.y)
- {
- maxDots.y = f;
- contactIdx[0].y = ie;
- }
-
-
- f = dot3F4( v, r );
- if (f<maxDots.z)
- {
- maxDots.z = f;
- contactIdx[0].z = ie;
- }
-
- f = dot3F4( -v, r );
- if (f<maxDots.w)
- {
- maxDots.w = f;
- contactIdx[0].w = ie;
- }
-
- }
-
- if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)
- {
- //replace the first contact with minimum (todo: replace contact with least penetration)
- contactIdx[0].x = minIndex;
- }
-
- return 4;
-
-}
-
-
-int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
-{
- contactIdx[0] = 0;
- contactIdx[1] = 1;
- contactIdx[2] = 2;
- contactIdx[3] = 3;
-
- if( nPoints == 0 ) return 0;
-
- nPoints = min2( nPoints, 4 );
- return nPoints;
-
-}
-
-
-
-int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)
-{
- if( nPoints == 0 ) return 0;
-
- nPoints = min2( nPoints, 64 );
-
- float4 center = make_float4(0.f);
- {
- float4 v[64];
- for (int i=0;i<nPoints;i++)
- v[i] = p[i];
- //memcpy( v, p, nPoints*sizeof(float4) );
- PARALLEL_SUM( v, nPoints );
- center = v[0]/(float)nPoints;
- }
-
-
-
- { // sample 4 directions
- if( nPoints < 4 )
- {
- for(int i=0; i<nPoints; i++)
- contactIdx[i] = i;
- return nPoints;
- }
-
- float4 aVector = p[0] - center;
- float4 u = cross3( nearNormal, aVector );
- float4 v = cross3( nearNormal, u );
- u = normalize3( u );
- v = normalize3( v );
-
- int idx[4];
-
- float2 max00 = make_float2(0,FLT_MAX);
- {
- // idx, distance
- {
- {
- int4 a[64];
- for(int ie = 0; ie<nPoints; ie++ )
- {
-
-
- float f;
- float4 r = p[ie]-center;
- f = dot3F4( u, r );
- a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
-
- f = dot3F4( -u, r );
- a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
-
- f = dot3F4( v, r );
- a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
-
- f = dot3F4( -v, r );
- a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);
- }
-
- for(int ie=0; ie<nPoints; ie++)
- {
- a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;
- a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;
- a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;
- a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;
- }
-
- idx[0] = (int)a[0].x & 0xff;
- idx[1] = (int)a[0].y & 0xff;
- idx[2] = (int)a[0].z & 0xff;
- idx[3] = (int)a[0].w & 0xff;
- }
- }
-
- {
- float2 h[64];
- PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );
- REDUCE_MIN( h, nPoints );
- max00 = h[0];
- }
- }
-
- contactIdx[0] = idx[0];
- contactIdx[1] = idx[1];
- contactIdx[2] = idx[2];
- contactIdx[3] = idx[3];
-
-
- return 4;
- }
-}
-
-
-
-__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const float4* closestPointsWorld,
- __global const float4* separatingNormalsWorld,
- __global const int* contactCounts,
- __global const int* contactOffsets,
- __global struct b3Contact4Data* restrict contactsOut,
- counter32_t nContactsOut,
- int contactCapacity,
- int numPairs,
- int pairIndex
- )
-{
- int idx = get_global_id(0);
-
- if (idx<numPairs)
- {
- float4 normal = separatingNormalsWorld[idx];
- int nPoints = contactCounts[idx];
- __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];
- float4 localPoints[64];
- for (int i=0;i<nPoints;i++)
- {
- localPoints[i] = pointsIn[i];
- }
-
- int contactIdx[4];// = {-1,-1,-1,-1};
- contactIdx[0] = -1;
- contactIdx[1] = -1;
- contactIdx[2] = -1;
- contactIdx[3] = -1;
-
- int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);
-
- int dstIdx;
- AppendInc( nContactsOut, dstIdx );
- if (dstIdx<contactCapacity)
- {
- __global struct b3Contact4Data* c = contactsOut + dstIdx;
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = idx;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
- for (int i=0;i<nContacts;i++)
- {
- c->m_worldPosB[i] = localPoints[contactIdx[i]];
- }
- GET_NPOINTS(*c) = nContacts;
- }
- }
-}
-
-
-void trInverse(float4 translationIn, Quaternion orientationIn,
- float4* translationOut, Quaternion* orientationOut)
-{
- *orientationOut = qtInvert(orientationIn);
- *translationOut = qtRotate(*orientationOut, -translationIn);
-}
-
-void trMul(float4 translationA, Quaternion orientationA,
- float4 translationB, Quaternion orientationB,
- float4* translationOut, Quaternion* orientationOut)
-{
- *orientationOut = qtMul(orientationA,orientationB);
- *translationOut = transform(&translationB,&translationA,&orientationA);
-}
-
-
-
-
-__kernel void clipHullHullKernel( __global int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- __global const float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int numPairs,
- int contactCapacity)
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
- float4 worldVertsB1[64];
- float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
-
- float4 localContactsOut[64];
- int localContactCapacity=64;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numPairs)
- {
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- if (hasSeparatingAxis[i])
- {
-
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
-
-
- int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],
- &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
- rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
- rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- vertices,faces,indices,
- localContactsOut,localContactCapacity);
-
- if (numLocalContactsOut>0)
- {
- float4 normal = -separatingNormals[i];
- int nPoints = numLocalContactsOut;
- float4* pointsIn = localContactsOut;
- int contactIdx[4];// = {-1,-1,-1,-1};
-
- contactIdx[0] = -1;
- contactIdx[1] = -1;
- contactIdx[2] = -1;
- contactIdx[3] = -1;
-
- int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
-
-
- int mprContactIndex = pairs[pairIndex].z;
-
- int dstIdx = mprContactIndex;
- if (dstIdx<0)
- {
- AppendInc( nGlobalContactsOut, dstIdx );
- }
-
- if (dstIdx<contactCapacity)
- {
- pairs[pairIndex].z = dstIdx;
-
- __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
-
- for (int i=0;i<nReducedContacts;i++)
- {
- //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact
- if (i>0||(mprContactIndex<0))
- {
- c->m_worldPosB[i] = pointsIn[contactIdx[i]];
- }
- }
- GET_NPOINTS(*c) = nReducedContacts;
- }
-
- }// if (numContactsOut>0)
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-}
-
-
-__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- __global const b3GpuChildShape_t* gpuChildShapes,
- __global const float4* gpuCompoundSepNormalsOut,
- __global const int* gpuHasCompoundSepNormalsOut,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int numCompoundPairs, int maxContactCapacity)
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
- float4 worldVertsB1[64];
- float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
-
- float4 localContactsOut[64];
- int localContactCapacity=64;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numCompoundPairs)
- {
-
- if (gpuHasCompoundSepNormalsOut[i])
- {
-
- int bodyIndexA = gpuCompoundPairs[i].x;
- int bodyIndexB = gpuCompoundPairs[i].y;
-
- int childShapeIndexA = gpuCompoundPairs[i].z;
- int childShapeIndexB = gpuCompoundPairs[i].w;
-
- int collidableIndexA = -1;
- int collidableIndexB = -1;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
-
- float4 ornB = rigidBodies[bodyIndexB].m_quat;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- if (childShapeIndexA >= 0)
- {
- collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;
- float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;
- float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;
- float4 newPosA = qtRotate(ornA,childPosA)+posA;
- float4 newOrnA = qtMul(ornA,childOrnA);
- posA = newPosA;
- ornA = newOrnA;
- } else
- {
- collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- }
-
- if (childShapeIndexB>=0)
- {
- collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- } else
- {
- collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
- }
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],
- &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- vertices,faces,indices,
- localContactsOut,localContactCapacity);
-
- if (numLocalContactsOut>0)
- {
- float4 normal = -gpuCompoundSepNormalsOut[i];
- int nPoints = numLocalContactsOut;
- float4* pointsIn = localContactsOut;
- int contactIdx[4];// = {-1,-1,-1,-1};
-
- contactIdx[0] = -1;
- contactIdx[1] = -1;
- contactIdx[2] = -1;
- contactIdx[3] = -1;
-
- int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
- if ((dstIdx+nReducedContacts) < maxContactCapacity)
- {
- __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = gpuCompoundPairs[pairIndex].x;
- int bodyB = gpuCompoundPairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_childIndexA = childShapeIndexA;
- c->m_childIndexB = childShapeIndexB;
- for (int i=0;i<nReducedContacts;i++)
- {
- c->m_worldPosB[i] = pointsIn[contactIdx[i]];
- }
- GET_NPOINTS(*c) = nReducedContacts;
- }
-
- }// if (numContactsOut>0)
- }// if (gpuHasCompoundSepNormalsOut[i])
- }// if (i<numCompoundPairs)
-
-}
-
-
-
-__kernel void sphereSphereCollisionKernel( __global const int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int contactCapacity,
- int numPairs)
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
- if (i<numPairs)
- {
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&
- collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)
- {
- //sphere-sphere
- float radiusA = collidables[collidableIndexA].m_radius;
- float radiusB = collidables[collidableIndexB].m_radius;
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
-
- float4 diff = posA-posB;
- float len = length(diff);
-
- ///iff distance positive, don't generate a new contact
- if ( len <= (radiusA+radiusB))
- {
- ///distance (negative means penetration)
- float dist = len - (radiusA+radiusB);
- float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);
- if (len > 0.00001)
- {
- normalOnSurfaceB = diff / len;
- }
- float4 contactPosB = posB + normalOnSurfaceB*radiusB;
- contactPosB.w = dist;
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
- if (dstIdx < contactCapacity)
- {
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normalOnSurfaceB;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_worldPosB[0] = contactPosB;
- c->m_childIndexA = -1;
- c->m_childIndexB = -1;
-
- GET_NPOINTS(*c) = 1;
- }//if (dstIdx < numPairs)
- }//if ( len <= (radiusA+radiusB))
- }//SHAPE_SPHERE SHAPE_SPHERE
- }//if (i<numPairs)
-}
-
-__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- __global const b3GpuChildShape_t* gpuChildShapes,
- __global const float4* separatingNormals,
- __global struct b3Contact4Data* restrict globalContactsOut,
- counter32_t nGlobalContactsOut,
- int contactCapacity,
- int numConcavePairs)
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
- float4 worldVertsB1[64];
- float4 worldVertsB2[64];
- int capacityWorldVerts = 64;
-
- float4 localContactsOut[64];
- int localContactCapacity=64;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numConcavePairs)
- {
- //negative value means that the pair is invalid
- if (concavePairsIn[i].w<0)
- return;
-
- int bodyIndexA = concavePairsIn[i].x;
- int bodyIndexB = concavePairsIn[i].y;
- int f = concavePairsIn[i].z;
- int childShapeIndexA = f;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- ///////////////////////////////////////////////////////////////
-
-
- bool overlap = false;
-
- b3ConvexPolyhedronData_t convexPolyhedronA;
-
- //add 3 vertices of the triangle
- convexPolyhedronA.m_numVertices = 3;
- convexPolyhedronA.m_vertexOffset = 0;
- float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
-
- b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
-
- float4 verticesA[3];
- for (int i=0;i<3;i++)
- {
- int index = indices[face.m_indexOffset+i];
- float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
- verticesA[i] = vert;
- localCenter += vert;
- }
-
- float dmin = FLT_MAX;
-
- int localCC=0;
-
- //a triangle has 3 unique edges
- convexPolyhedronA.m_numUniqueEdges = 3;
- convexPolyhedronA.m_uniqueEdgesOffset = 0;
- float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
-
-
- convexPolyhedronA.m_faceOffset = 0;
-
- float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
-
- b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3+3+2+2+2];
- int curUsedIndices=0;
- int fidx=0;
-
- //front size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[0] = 0;
- indicesA[1] = 1;
- indicesA[2] = 2;
- curUsedIndices+=3;
- float c = face.m_plane.w;
- facesA[fidx].m_plane.x = normal.x;
- facesA[fidx].m_plane.y = normal.y;
- facesA[fidx].m_plane.z = normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
- //back size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[3]=2;
- indicesA[4]=1;
- indicesA[5]=0;
- curUsedIndices+=3;
- float c = dot3F4(normal,verticesA[0]);
- float c1 = -face.m_plane.w;
- facesA[fidx].m_plane.x = -normal.x;
- facesA[fidx].m_plane.y = -normal.y;
- facesA[fidx].m_plane.z = -normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
-
- bool addEdgePlanes = true;
- if (addEdgePlanes)
- {
- int numVertices=3;
- int prevVertex = numVertices-1;
- for (int i=0;i<numVertices;i++)
- {
- float4 v0 = verticesA[i];
- float4 v1 = verticesA[prevVertex];
-
- float4 edgeNormal = normalize(cross(normal,v1-v0));
- float c = -dot3F4(edgeNormal,v0);
-
- facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[curUsedIndices++]=i;
- indicesA[curUsedIndices++]=prevVertex;
-
- facesA[fidx].m_plane.x = edgeNormal.x;
- facesA[fidx].m_plane.y = edgeNormal.y;
- facesA[fidx].m_plane.z = edgeNormal.z;
- facesA[fidx].m_plane.w = c;
- fidx++;
- prevVertex = i;
- }
- }
- convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
-
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
-
-
- float4 sepAxis = separatingNormals[i];
-
- int shapeTypeB = collidables[collidableIndexB].m_shapeType;
- int childShapeIndexB =-1;
- if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- ///////////////////
- ///compound shape support
-
- childShapeIndexB = concavePairsIn[pairIndex].w;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
-
- }
-
- ////////////////////////////////////////
-
-
-
- int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,
- &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsB1,worldVertsB2,capacityWorldVerts,
- minDist, maxDist,
- &verticesA,&facesA,&indicesA,
- vertices,faces,indices,
- localContactsOut,localContactCapacity);
-
- if (numLocalContactsOut>0)
- {
- float4 normal = -separatingNormals[i];
- int nPoints = numLocalContactsOut;
- float4* pointsIn = localContactsOut;
- int contactIdx[4];// = {-1,-1,-1,-1};
-
- contactIdx[0] = -1;
- contactIdx[1] = -1;
- contactIdx[2] = -1;
- contactIdx[3] = -1;
-
- int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);
-
- int dstIdx;
- AppendInc( nGlobalContactsOut, dstIdx );
- if (dstIdx<contactCapacity)
- {
- __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = concavePairsIn[pairIndex].x;
- int bodyB = concavePairsIn[pairIndex].y;
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_childIndexA = childShapeIndexA;
- c->m_childIndexB = childShapeIndexB;
- for (int i=0;i<nReducedContacts;i++)
- {
- c->m_worldPosB[i] = pointsIn[contactIdx[i]];
- }
- GET_NPOINTS(*c) = nReducedContacts;
- }
-
- }// if (numContactsOut>0)
- }// if (i<numPairs)
-}
-
-
-
-
-
-
-int findClippingFaces(const float4 separatingNormal,
- __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,
- const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
- __global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- int capacityWorldVerts,
- const float minDist, float maxDist,
- __global const float4* vertices,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- __global int4* clippingFaces, int pairIndex)
-{
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=-1;
- float dmax = -FLT_MAX;
-
- {
- for(int face=0;face<hullB->m_numFaces;face++)
- {
- const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,
- faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);
- const float4 WorldNormal = qtRotate(ornB, Normal);
- float d = dot3F4(WorldNormal,separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];
- const int numVertices = polyB.m_numIndices;
- for(int e0=0;e0<numVertices;e0++)
- {
- const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];
- worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
- }
- }
-
- int closestFaceA=-1;
- {
- float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
- {
- const float4 Normal = make_float4(
- faces[hullA->m_faceOffset+face].m_plane.x,
- faces[hullA->m_faceOffset+face].m_plane.y,
- faces[hullA->m_faceOffset+face].m_plane.z,
- 0.f);
- const float4 faceANormalWS = qtRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- worldNormalsA1[pairIndex] = faceANormalWS;
- }
- }
- }
-
- int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;
- for(int e0=0;e0<numVerticesA;e0++)
- {
- const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
- worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
- }
-
- clippingFaces[pairIndex].x = closestFaceA;
- clippingFaces[pairIndex].y = closestFaceB;
- clippingFaces[pairIndex].z = numVerticesA;
- clippingFaces[pairIndex].w = numWorldVertsB1;
-
-
- return numContactsOut;
-}
-
-
-
-int clipFaces(__global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- __global float4* worldVertsB2,
- int capacityWorldVertsB2,
- const float minDist, float maxDist,
- __global int4* clippingFaces,
- int pairIndex)
-{
- int numContactsOut = 0;
-
- int closestFaceA = clippingFaces[pairIndex].x;
- int closestFaceB = clippingFaces[pairIndex].y;
- int numVertsInA = clippingFaces[pairIndex].z;
- int numVertsInB = clippingFaces[pairIndex].w;
-
- int numVertsOut = 0;
-
- if (closestFaceA<0)
- return numContactsOut;
-
- __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
- __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
-
-
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
-
- for(int e0=0;e0<numVertsInA;e0++)
- {
- const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
- const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
- const float4 WorldEdge0 = aw - bw;
- float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
- float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
- float4 worldA1 = aw;
- float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
- float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
- numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
- __global float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsInB = numVertsOut;
- numVertsOut = 0;
- }
-
- //float4 planeNormalWS = worldNormalsA1[pairIndex];
- //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
-
-
-
- /*for (int i=0;i<numVertsInB;i++)
- {
- pVtxOut[i] = pVtxIn[i];
- }*/
-
-
-
-
- //numVertsInB=0;
-
- float4 planeNormalWS = worldNormalsA1[pairIndex];
- float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
-
- for (int i=0;i<numVertsInB;i++)
- {
- float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
- {
- depth = minDist;
- }
-
- if (depth <=maxDist)
- {
- float4 pointInWorld = pVtxIn[i];
- pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
- }
- }
-
- clippingFaces[pairIndex].w =numContactsOut;
-
-
- return numContactsOut;
-
-}
-
-
-
-
-__kernel void findClippingFacesKernel( __global const int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const b3Collidable_t* collidables,
- __global const b3ConvexPolyhedronData_t* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const b3GpuFace_t* faces,
- __global const int* indices,
- __global const float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global int4* clippingFacesOut,
- __global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- int capacityWorldVerts,
- int numPairs
- )
-{
-
- int i = get_global_id(0);
- int pairIndex = i;
-
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numPairs)
- {
-
- if (hasSeparatingAxis[i])
- {
-
- int bodyIndexA = pairs[i].x;
- int bodyIndexB = pairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
-
- int numLocalContactsOut = findClippingFaces(separatingNormals[i],
- &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],
- rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,
- rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,
- worldVertsA1,
- worldNormalsA1,
- worldVertsB1,capacityWorldVerts,
- minDist, maxDist,
- vertices,faces,indices,
- clippingFacesOut,i);
-
-
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-}
-
-
-
-
-__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global int4* clippingFacesOut,
- __global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- __global float4* worldVertsB2,
- int vertexFaceCapacity,
- int numPairs,
- int debugMode
- )
-{
- int i = get_global_id(0);
- int pairIndex = i;
-
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
- if (i<numPairs)
- {
-
- if (hasSeparatingAxis[i])
- {
-
-// int bodyIndexA = pairs[i].x;
- // int bodyIndexB = pairs[i].y;
-
- int numLocalContactsOut = 0;
-
- int capacityWorldVertsB2 = vertexFaceCapacity;
-
- __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];
- __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];
-
-
- {
- __global int4* clippingFaces = clippingFacesOut;
-
-
- int closestFaceA = clippingFaces[pairIndex].x;
- int closestFaceB = clippingFaces[pairIndex].y;
- int numVertsInA = clippingFaces[pairIndex].z;
- int numVertsInB = clippingFaces[pairIndex].w;
-
- int numVertsOut = 0;
-
- if (closestFaceA>=0)
- {
-
-
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
-
- for(int e0=0;e0<numVertsInA;e0++)
- {
- const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];
- const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];
- const float4 WorldEdge0 = aw - bw;
- float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];
- float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);
- float4 worldA1 = aw;
- float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);
- float4 planeNormalWS = planeNormalWS1;
- float planeEqWS=planeEqWS1;
- numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);
- __global float4* tmp = pVtxOut;
- pVtxOut = pVtxIn;
- pVtxIn = tmp;
- numVertsInB = numVertsOut;
- numVertsOut = 0;
- }
-
- float4 planeNormalWS = worldNormalsA1[pairIndex];
- float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);
-
- for (int i=0;i<numVertsInB;i++)
- {
- float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;
- if (depth <=minDist)
- {
- depth = minDist;
- }
-
- if (depth <=maxDist)
- {
- float4 pointInWorld = pVtxIn[i];
- pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);
- }
- }
-
- }
- clippingFaces[pairIndex].w =numLocalContactsOut;
-
-
- }
-
- for (int i=0;i<numLocalContactsOut;i++)
- pVtxIn[i] = pVtxOut[i];
-
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-}
-
-
-
-
-
-__kernel void newContactReductionKernel( __global int4* pairs,
- __global const b3RigidBodyData_t* rigidBodies,
- __global const float4* separatingNormals,
- __global const int* hasSeparatingAxis,
- __global struct b3Contact4Data* globalContactsOut,
- __global int4* clippingFaces,
- __global float4* worldVertsB2,
- volatile __global int* nGlobalContactsOut,
- int vertexFaceCapacity,
- int contactCapacity,
- int numPairs
- )
-{
- int i = get_global_id(0);
- int pairIndex = i;
-
- int4 contactIdx;
- contactIdx=make_int4(0,1,2,3);
-
- if (i<numPairs)
- {
-
- if (hasSeparatingAxis[i])
- {
-
-
-
-
- int nPoints = clippingFaces[pairIndex].w;
-
- if (nPoints>0)
- {
-
- __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];
- float4 normal = -separatingNormals[i];
-
- int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);
-
- int mprContactIndex = pairs[pairIndex].z;
-
- int dstIdx = mprContactIndex;
-
- if (dstIdx<0)
- {
- AppendInc( nGlobalContactsOut, dstIdx );
- }
-//#if 0
-
- if (dstIdx < contactCapacity)
- {
-
- __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];
- c->m_worldNormalOnB = -normal;
- c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);
- c->m_batchIdx = pairIndex;
- int bodyA = pairs[pairIndex].x;
- int bodyB = pairs[pairIndex].y;
-
- pairs[pairIndex].w = dstIdx;
-
- c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;
- c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;
- c->m_childIndexA =-1;
- c->m_childIndexB =-1;
-
- switch (nReducedContacts)
- {
- case 4:
- c->m_worldPosB[3] = pointsIn[contactIdx.w];
- case 3:
- c->m_worldPosB[2] = pointsIn[contactIdx.z];
- case 2:
- c->m_worldPosB[1] = pointsIn[contactIdx.y];
- case 1:
- if (mprContactIndex<0)//test
- c->m_worldPosB[0] = pointsIn[contactIdx.x];
- default:
- {
- }
- };
-
- GET_NPOINTS(*c) = nReducedContacts;
-
- }
-
-
-//#endif
-
- }// if (numContactsOut>0)
- }// if (hasSeparatingAxis[i])
- }// if (i<numPairs)
-
-
-
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
deleted file mode 100644
index 907809d8bd..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satClipHullContacts.h
+++ /dev/null
@@ -1,2098 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satClipKernelsCL =
- "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile __global int*\n"
- "#endif\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "typedef unsigned int u32;\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#ifndef B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#define B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "typedef struct b3GpuFace b3GpuFace_t;\n"
- "struct b3GpuFace\n"
- "{\n"
- " b3Float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- " int m_unusedPadding1;\n"
- " int m_unusedPadding2;\n"
- "};\n"
- "typedef struct b3ConvexPolyhedronData b3ConvexPolyhedronData_t;\n"
- "struct b3ConvexPolyhedronData\n"
- "{\n"
- " b3Float4 m_localCenter;\n"
- " b3Float4 m_extents;\n"
- " b3Float4 mC;\n"
- " b3Float4 mE;\n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "};\n"
- "#endif //B3_CONVEX_POLYHEDRON_DATA_H\n"
- "#ifndef B3_COLLIDABLE_H\n"
- "#define B3_COLLIDABLE_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "enum b3ShapeTypes\n"
- "{\n"
- " SHAPE_HEIGHT_FIELD=1,\n"
- " SHAPE_CONVEX_HULL=3,\n"
- " SHAPE_PLANE=4,\n"
- " SHAPE_CONCAVE_TRIMESH=5,\n"
- " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
- " SHAPE_SPHERE=7,\n"
- " MAX_NUM_SHAPE_TYPES,\n"
- "};\n"
- "typedef struct b3Collidable b3Collidable_t;\n"
- "struct b3Collidable\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_radius;\n"
- " int m_compoundBvhIndex;\n"
- " };\n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- "};\n"
- "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
- "struct b3GpuChildShape\n"
- "{\n"
- " b3Float4 m_childPosition;\n"
- " b3Quat m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "struct b3CompoundOverlappingPair\n"
- "{\n"
- " int m_bodyIndexA;\n"
- " int m_bodyIndexB;\n"
- "// int m_pairType;\n"
- " int m_childShapeIndexA;\n"
- " int m_childShapeIndexB;\n"
- "};\n"
- "#endif //B3_COLLIDABLE_H\n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#define B3_RIGIDBODY_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
- "struct b3RigidBodyData\n"
- "{\n"
- " b3Float4 m_pos;\n"
- " b3Quat m_quat;\n"
- " b3Float4 m_linVel;\n"
- " b3Float4 m_angVel;\n"
- " int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "};\n"
- "typedef struct b3InertiaData b3InertiaData_t;\n"
- "struct b3InertiaData\n"
- "{\n"
- " b3Mat3x3 m_invInertiaWorld;\n"
- " b3Mat3x3 m_initInvInertia;\n"
- "};\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "#define GET_NPOINTS(x) (x).m_worldNormalOnB.w\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "__inline\n"
- "float fastDiv(float numerator, float denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "// return numerator/denominator; \n"
- "}\n"
- "__inline\n"
- "float4 fastDiv4(float4 numerator, float4 denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "//#define dot3F4 dot\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "__inline\n"
- "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
- "{\n"
- " return qtRotate( *orientation, *p ) + (*translation);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "}\n"
- "__inline float4 lerp3(const float4 a,const float4 b, float t)\n"
- "{\n"
- " return make_float4( a.x + (b.x - a.x) * t,\n"
- " a.y + (b.y - a.y) * t,\n"
- " a.z + (b.z - a.z) * t,\n"
- " 0.f);\n"
- "}\n"
- "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
- "int clipFaceGlobal(__global const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, __global float4* ppVtxOut)\n"
- "{\n"
- " \n"
- " int ve;\n"
- " float ds, de;\n"
- " int numVertsOut = 0;\n"
- " //double-check next test\n"
- " if (numVertsIn < 2)\n"
- " return 0;\n"
- " \n"
- " float4 firstVertex=pVtxIn[numVertsIn-1];\n"
- " float4 endVertex = pVtxIn[0];\n"
- " \n"
- " ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
- " \n"
- " for (ve = 0; ve < numVertsIn; ve++)\n"
- " {\n"
- " endVertex=pVtxIn[ve];\n"
- " de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
- " if (ds<0)\n"
- " {\n"
- " if (de<0)\n"
- " {\n"
- " // Start < 0, end < 0, so output endVertex\n"
- " ppVtxOut[numVertsOut++] = endVertex;\n"
- " }\n"
- " else\n"
- " {\n"
- " // Start < 0, end >= 0, so output intersection\n"
- " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
- " }\n"
- " }\n"
- " else\n"
- " {\n"
- " if (de<0)\n"
- " {\n"
- " // Start >= 0, end < 0 so output intersection and end\n"
- " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
- " ppVtxOut[numVertsOut++] = endVertex;\n"
- " }\n"
- " }\n"
- " firstVertex = endVertex;\n"
- " ds = de;\n"
- " }\n"
- " return numVertsOut;\n"
- "}\n"
- "// Clips a face to the back of a plane, return the number of vertices out, stored in ppVtxOut\n"
- "int clipFace(const float4* pVtxIn, int numVertsIn, float4 planeNormalWS,float planeEqWS, float4* ppVtxOut)\n"
- "{\n"
- " \n"
- " int ve;\n"
- " float ds, de;\n"
- " int numVertsOut = 0;\n"
- "//double-check next test\n"
- " if (numVertsIn < 2)\n"
- " return 0;\n"
- " float4 firstVertex=pVtxIn[numVertsIn-1];\n"
- " float4 endVertex = pVtxIn[0];\n"
- " \n"
- " ds = dot3F4(planeNormalWS,firstVertex)+planeEqWS;\n"
- " for (ve = 0; ve < numVertsIn; ve++)\n"
- " {\n"
- " endVertex=pVtxIn[ve];\n"
- " de = dot3F4(planeNormalWS,endVertex)+planeEqWS;\n"
- " if (ds<0)\n"
- " {\n"
- " if (de<0)\n"
- " {\n"
- " // Start < 0, end < 0, so output endVertex\n"
- " ppVtxOut[numVertsOut++] = endVertex;\n"
- " }\n"
- " else\n"
- " {\n"
- " // Start < 0, end >= 0, so output intersection\n"
- " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
- " }\n"
- " }\n"
- " else\n"
- " {\n"
- " if (de<0)\n"
- " {\n"
- " // Start >= 0, end < 0 so output intersection and end\n"
- " ppVtxOut[numVertsOut++] = lerp3(firstVertex, endVertex,(ds * 1.f/(ds - de)) );\n"
- " ppVtxOut[numVertsOut++] = endVertex;\n"
- " }\n"
- " }\n"
- " firstVertex = endVertex;\n"
- " ds = de;\n"
- " }\n"
- " return numVertsOut;\n"
- "}\n"
- "int clipFaceAgainstHull(const float4 separatingNormal, __global const b3ConvexPolyhedronData_t* hullA, \n"
- " const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
- " float4* worldVertsB2, int capacityWorldVertsB2,\n"
- " const float minDist, float maxDist,\n"
- " __global const float4* vertices,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " float4* contactsOut,\n"
- " int contactCapacity)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " float4* pVtxIn = worldVertsB1;\n"
- " float4* pVtxOut = worldVertsB2;\n"
- " \n"
- " int numVertsIn = numWorldVertsB1;\n"
- " int numVertsOut = 0;\n"
- " int closestFaceA=-1;\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " for(int face=0;face<hullA->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(\n"
- " faces[hullA->m_faceOffset+face].m_plane.x, \n"
- " faces[hullA->m_faceOffset+face].m_plane.y, \n"
- " faces[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
- " \n"
- " float d = dot3F4(faceANormalWS,separatingNormal);\n"
- " if (d < dmin)\n"
- " {\n"
- " dmin = d;\n"
- " closestFaceA = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " if (closestFaceA<0)\n"
- " return numContactsOut;\n"
- " b3GpuFace_t polyA = faces[hullA->m_faceOffset+closestFaceA];\n"
- " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
- " int numVerticesA = polyA.m_numIndices;\n"
- " for(int e0=0;e0<numVerticesA;e0++)\n"
- " {\n"
- " const float4 a = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+e0]];\n"
- " const float4 b = vertices[hullA->m_vertexOffset+indices[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
- " const float4 edge0 = a - b;\n"
- " const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
- " float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
- " float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
- " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
- " float4 worldA1 = transform(&a,&posA,&ornA);\n"
- " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
- " \n"
- " float4 planeNormalWS = planeNormalWS1;\n"
- " float planeEqWS=planeEqWS1;\n"
- " \n"
- " //clip face\n"
- " //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
- " numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
- " //btSwap(pVtxIn,pVtxOut);\n"
- " float4* tmp = pVtxOut;\n"
- " pVtxOut = pVtxIn;\n"
- " pVtxIn = tmp;\n"
- " numVertsIn = numVertsOut;\n"
- " numVertsOut = 0;\n"
- " }\n"
- " \n"
- " // only keep points that are behind the witness face\n"
- " {\n"
- " float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
- " float localPlaneEq = polyA.m_plane.w;\n"
- " float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
- " float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
- " for (int i=0;i<numVertsIn;i++)\n"
- " {\n"
- " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
- " if (depth <=minDist)\n"
- " {\n"
- " depth = minDist;\n"
- " }\n"
- " if (depth <=maxDist)\n"
- " {\n"
- " float4 pointInWorld = pVtxIn[i];\n"
- " //resultOut.addContactPoint(separatingNormal,point,depth);\n"
- " contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
- " }\n"
- " }\n"
- " }\n"
- " return numContactsOut;\n"
- "}\n"
- "int clipFaceAgainstHullLocalA(const float4 separatingNormal, const b3ConvexPolyhedronData_t* hullA, \n"
- " const float4 posA, const Quaternion ornA, float4* worldVertsB1, int numWorldVertsB1,\n"
- " float4* worldVertsB2, int capacityWorldVertsB2,\n"
- " const float minDist, float maxDist,\n"
- " const float4* verticesA,\n"
- " const b3GpuFace_t* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB,\n"
- " __global const b3GpuFace_t* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* contactsOut,\n"
- " int contactCapacity)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " float4* pVtxIn = worldVertsB1;\n"
- " float4* pVtxOut = worldVertsB2;\n"
- " \n"
- " int numVertsIn = numWorldVertsB1;\n"
- " int numVertsOut = 0;\n"
- " int closestFaceA=-1;\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " for(int face=0;face<hullA->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(\n"
- " facesA[hullA->m_faceOffset+face].m_plane.x, \n"
- " facesA[hullA->m_faceOffset+face].m_plane.y, \n"
- " facesA[hullA->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
- " \n"
- " float d = dot3F4(faceANormalWS,separatingNormal);\n"
- " if (d < dmin)\n"
- " {\n"
- " dmin = d;\n"
- " closestFaceA = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " if (closestFaceA<0)\n"
- " return numContactsOut;\n"
- " b3GpuFace_t polyA = facesA[hullA->m_faceOffset+closestFaceA];\n"
- " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
- " int numVerticesA = polyA.m_numIndices;\n"
- " for(int e0=0;e0<numVerticesA;e0++)\n"
- " {\n"
- " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+e0]];\n"
- " const float4 b = verticesA[hullA->m_vertexOffset+indicesA[polyA.m_indexOffset+((e0+1)%numVerticesA)]];\n"
- " const float4 edge0 = a - b;\n"
- " const float4 WorldEdge0 = qtRotate(ornA,edge0);\n"
- " float4 planeNormalA = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
- " float4 worldPlaneAnormal1 = qtRotate(ornA,planeNormalA);\n"
- " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
- " float4 worldA1 = transform(&a,&posA,&ornA);\n"
- " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
- " \n"
- " float4 planeNormalWS = planeNormalWS1;\n"
- " float planeEqWS=planeEqWS1;\n"
- " \n"
- " //clip face\n"
- " //clipFace(*pVtxIn, *pVtxOut,planeNormalWS,planeEqWS);\n"
- " numVertsOut = clipFace(pVtxIn, numVertsIn, planeNormalWS,planeEqWS, pVtxOut);\n"
- " //btSwap(pVtxIn,pVtxOut);\n"
- " float4* tmp = pVtxOut;\n"
- " pVtxOut = pVtxIn;\n"
- " pVtxIn = tmp;\n"
- " numVertsIn = numVertsOut;\n"
- " numVertsOut = 0;\n"
- " }\n"
- " \n"
- " // only keep points that are behind the witness face\n"
- " {\n"
- " float4 localPlaneNormal = make_float4(polyA.m_plane.x,polyA.m_plane.y,polyA.m_plane.z,0.f);\n"
- " float localPlaneEq = polyA.m_plane.w;\n"
- " float4 planeNormalWS = qtRotate(ornA,localPlaneNormal);\n"
- " float planeEqWS=localPlaneEq-dot3F4(planeNormalWS,posA);\n"
- " for (int i=0;i<numVertsIn;i++)\n"
- " {\n"
- " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
- " if (depth <=minDist)\n"
- " {\n"
- " depth = minDist;\n"
- " }\n"
- " if (depth <=maxDist)\n"
- " {\n"
- " float4 pointInWorld = pVtxIn[i];\n"
- " //resultOut.addContactPoint(separatingNormal,point,depth);\n"
- " contactsOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
- " }\n"
- " }\n"
- " }\n"
- " return numContactsOut;\n"
- "}\n"
- "int clipHullAgainstHull(const float4 separatingNormal,\n"
- " __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
- " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
- " float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
- " const float minDist, float maxDist,\n"
- " __global const float4* vertices,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " float4* localContactsOut,\n"
- " int localContactCapacity)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " int closestFaceB=-1;\n"
- " float dmax = -FLT_MAX;\n"
- " {\n"
- " for(int face=0;face<hullB->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x, \n"
- " faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
- " float d = dot3F4(WorldNormal,separatingNormal);\n"
- " if (d > dmax)\n"
- " {\n"
- " dmax = d;\n"
- " closestFaceB = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " {\n"
- " const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
- " const int numVertices = polyB.m_numIndices;\n"
- " for(int e0=0;e0<numVertices;e0++)\n"
- " {\n"
- " const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
- " worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
- " }\n"
- " }\n"
- " if (closestFaceB>=0)\n"
- " {\n"
- " numContactsOut = clipFaceAgainstHull(separatingNormal, hullA, \n"
- " posA,ornA,\n"
- " worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,vertices,\n"
- " faces,\n"
- " indices,localContactsOut,localContactCapacity);\n"
- " }\n"
- " return numContactsOut;\n"
- "}\n"
- "int clipHullAgainstHullLocalA(const float4 separatingNormal,\n"
- " const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB, \n"
- " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB, \n"
- " float4* worldVertsB1, float4* worldVertsB2, int capacityWorldVerts,\n"
- " const float minDist, float maxDist,\n"
- " const float4* verticesA,\n"
- " const b3GpuFace_t* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB,\n"
- " __global const b3GpuFace_t* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* localContactsOut,\n"
- " int localContactCapacity)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " int closestFaceB=-1;\n"
- " float dmax = -FLT_MAX;\n"
- " {\n"
- " for(int face=0;face<hullB->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x, \n"
- " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
- " float d = dot3F4(WorldNormal,separatingNormal);\n"
- " if (d > dmax)\n"
- " {\n"
- " dmax = d;\n"
- " closestFaceB = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " {\n"
- " const b3GpuFace_t polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
- " const int numVertices = polyB.m_numIndices;\n"
- " for(int e0=0;e0<numVertices;e0++)\n"
- " {\n"
- " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
- " worldVertsB1[numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
- " }\n"
- " }\n"
- " if (closestFaceB>=0)\n"
- " {\n"
- " numContactsOut = clipFaceAgainstHullLocalA(separatingNormal, hullA, \n"
- " posA,ornA,\n"
- " worldVertsB1,numWorldVertsB1,worldVertsB2,capacityWorldVerts, minDist, maxDist,\n"
- " verticesA,facesA,indicesA,\n"
- " verticesB,facesB,indicesB,\n"
- " localContactsOut,localContactCapacity);\n"
- " }\n"
- " return numContactsOut;\n"
- "}\n"
- "#define PARALLEL_SUM(v, n) for(int j=1; j<n; j++) v[0] += v[j];\n"
- "#define PARALLEL_DO(execution, n) for(int ie=0; ie<n; ie++){execution;}\n"
- "#define REDUCE_MAX(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y > v[i+offset].y)? v[i]: v[i+offset]; }\n"
- "#define REDUCE_MIN(v, n) {int i=0; for(int offset=0; offset<n; offset++) v[i] = (v[i].y < v[i+offset].y)? v[i]: v[i+offset]; }\n"
- "int extractManifoldSequentialGlobal(__global const float4* p, int nPoints, float4 nearNormal, int4* contactIdx)\n"
- "{\n"
- " if( nPoints == 0 )\n"
- " return 0;\n"
- " \n"
- " if (nPoints <=4)\n"
- " return nPoints;\n"
- " \n"
- " \n"
- " if (nPoints >64)\n"
- " nPoints = 64;\n"
- " \n"
- " float4 center = make_float4(0.f);\n"
- " {\n"
- " \n"
- " for (int i=0;i<nPoints;i++)\n"
- " center += p[i];\n"
- " center /= (float)nPoints;\n"
- " }\n"
- " \n"
- " \n"
- " \n"
- " // sample 4 directions\n"
- " \n"
- " float4 aVector = p[0] - center;\n"
- " float4 u = cross3( nearNormal, aVector );\n"
- " float4 v = cross3( nearNormal, u );\n"
- " u = normalize3( u );\n"
- " v = normalize3( v );\n"
- " \n"
- " \n"
- " //keep point with deepest penetration\n"
- " float minW= FLT_MAX;\n"
- " \n"
- " int minIndex=-1;\n"
- " \n"
- " float4 maxDots;\n"
- " maxDots.x = FLT_MIN;\n"
- " maxDots.y = FLT_MIN;\n"
- " maxDots.z = FLT_MIN;\n"
- " maxDots.w = FLT_MIN;\n"
- " \n"
- " // idx, distance\n"
- " for(int ie = 0; ie<nPoints; ie++ )\n"
- " {\n"
- " if (p[ie].w<minW)\n"
- " {\n"
- " minW = p[ie].w;\n"
- " minIndex=ie;\n"
- " }\n"
- " float f;\n"
- " float4 r = p[ie]-center;\n"
- " f = dot3F4( u, r );\n"
- " if (f<maxDots.x)\n"
- " {\n"
- " maxDots.x = f;\n"
- " contactIdx[0].x = ie;\n"
- " }\n"
- " \n"
- " f = dot3F4( -u, r );\n"
- " if (f<maxDots.y)\n"
- " {\n"
- " maxDots.y = f;\n"
- " contactIdx[0].y = ie;\n"
- " }\n"
- " \n"
- " \n"
- " f = dot3F4( v, r );\n"
- " if (f<maxDots.z)\n"
- " {\n"
- " maxDots.z = f;\n"
- " contactIdx[0].z = ie;\n"
- " }\n"
- " \n"
- " f = dot3F4( -v, r );\n"
- " if (f<maxDots.w)\n"
- " {\n"
- " maxDots.w = f;\n"
- " contactIdx[0].w = ie;\n"
- " }\n"
- " \n"
- " }\n"
- " \n"
- " if (contactIdx[0].x != minIndex && contactIdx[0].y != minIndex && contactIdx[0].z != minIndex && contactIdx[0].w != minIndex)\n"
- " {\n"
- " //replace the first contact with minimum (todo: replace contact with least penetration)\n"
- " contactIdx[0].x = minIndex;\n"
- " }\n"
- " \n"
- " return 4;\n"
- " \n"
- "}\n"
- "int extractManifoldSequentialGlobalFake(__global const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
- "{\n"
- " contactIdx[0] = 0;\n"
- " contactIdx[1] = 1;\n"
- " contactIdx[2] = 2;\n"
- " contactIdx[3] = 3;\n"
- " \n"
- " if( nPoints == 0 ) return 0;\n"
- " \n"
- " nPoints = min2( nPoints, 4 );\n"
- " return nPoints;\n"
- " \n"
- "}\n"
- "int extractManifoldSequential(const float4* p, int nPoints, float4 nearNormal, int* contactIdx)\n"
- "{\n"
- " if( nPoints == 0 ) return 0;\n"
- " nPoints = min2( nPoints, 64 );\n"
- " float4 center = make_float4(0.f);\n"
- " {\n"
- " float4 v[64];\n"
- " for (int i=0;i<nPoints;i++)\n"
- " v[i] = p[i];\n"
- " //memcpy( v, p, nPoints*sizeof(float4) );\n"
- " PARALLEL_SUM( v, nPoints );\n"
- " center = v[0]/(float)nPoints;\n"
- " }\n"
- " \n"
- " { // sample 4 directions\n"
- " if( nPoints < 4 )\n"
- " {\n"
- " for(int i=0; i<nPoints; i++) \n"
- " contactIdx[i] = i;\n"
- " return nPoints;\n"
- " }\n"
- " float4 aVector = p[0] - center;\n"
- " float4 u = cross3( nearNormal, aVector );\n"
- " float4 v = cross3( nearNormal, u );\n"
- " u = normalize3( u );\n"
- " v = normalize3( v );\n"
- " int idx[4];\n"
- " float2 max00 = make_float2(0,FLT_MAX);\n"
- " {\n"
- " // idx, distance\n"
- " {\n"
- " {\n"
- " int4 a[64];\n"
- " for(int ie = 0; ie<nPoints; ie++ )\n"
- " {\n"
- " \n"
- " \n"
- " float f;\n"
- " float4 r = p[ie]-center;\n"
- " f = dot3F4( u, r );\n"
- " a[ie].x = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
- " f = dot3F4( -u, r );\n"
- " a[ie].y = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
- " f = dot3F4( v, r );\n"
- " a[ie].z = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
- " f = dot3F4( -v, r );\n"
- " a[ie].w = ((*(u32*)&f) & 0xffffff00) | (0xff & ie);\n"
- " }\n"
- " for(int ie=0; ie<nPoints; ie++)\n"
- " {\n"
- " a[0].x = (a[0].x > a[ie].x )? a[0].x: a[ie].x;\n"
- " a[0].y = (a[0].y > a[ie].y )? a[0].y: a[ie].y;\n"
- " a[0].z = (a[0].z > a[ie].z )? a[0].z: a[ie].z;\n"
- " a[0].w = (a[0].w > a[ie].w )? a[0].w: a[ie].w;\n"
- " }\n"
- " idx[0] = (int)a[0].x & 0xff;\n"
- " idx[1] = (int)a[0].y & 0xff;\n"
- " idx[2] = (int)a[0].z & 0xff;\n"
- " idx[3] = (int)a[0].w & 0xff;\n"
- " }\n"
- " }\n"
- " {\n"
- " float2 h[64];\n"
- " PARALLEL_DO( h[ie] = make_float2((float)ie, p[ie].w), nPoints );\n"
- " REDUCE_MIN( h, nPoints );\n"
- " max00 = h[0];\n"
- " }\n"
- " }\n"
- " contactIdx[0] = idx[0];\n"
- " contactIdx[1] = idx[1];\n"
- " contactIdx[2] = idx[2];\n"
- " contactIdx[3] = idx[3];\n"
- " return 4;\n"
- " }\n"
- "}\n"
- "__kernel void extractManifoldAndAddContactKernel(__global const int4* pairs, \n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const float4* closestPointsWorld,\n"
- " __global const float4* separatingNormalsWorld,\n"
- " __global const int* contactCounts,\n"
- " __global const int* contactOffsets,\n"
- " __global struct b3Contact4Data* restrict contactsOut,\n"
- " counter32_t nContactsOut,\n"
- " int contactCapacity,\n"
- " int numPairs,\n"
- " int pairIndex\n"
- " )\n"
- "{\n"
- " int idx = get_global_id(0);\n"
- " \n"
- " if (idx<numPairs)\n"
- " {\n"
- " float4 normal = separatingNormalsWorld[idx];\n"
- " int nPoints = contactCounts[idx];\n"
- " __global const float4* pointsIn = &closestPointsWorld[contactOffsets[idx]];\n"
- " float4 localPoints[64];\n"
- " for (int i=0;i<nPoints;i++)\n"
- " {\n"
- " localPoints[i] = pointsIn[i];\n"
- " }\n"
- " int contactIdx[4];// = {-1,-1,-1,-1};\n"
- " contactIdx[0] = -1;\n"
- " contactIdx[1] = -1;\n"
- " contactIdx[2] = -1;\n"
- " contactIdx[3] = -1;\n"
- " int nContacts = extractManifoldSequential(localPoints, nPoints, normal, contactIdx);\n"
- " int dstIdx;\n"
- " AppendInc( nContactsOut, dstIdx );\n"
- " if (dstIdx<contactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = contactsOut + dstIdx;\n"
- " c->m_worldNormalOnB = -normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = idx;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0 ? -bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0 ? -bodyB:bodyB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " for (int i=0;i<nContacts;i++)\n"
- " {\n"
- " c->m_worldPosB[i] = localPoints[contactIdx[i]];\n"
- " }\n"
- " GET_NPOINTS(*c) = nContacts;\n"
- " }\n"
- " }\n"
- "}\n"
- "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
- " float4* translationOut, Quaternion* orientationOut)\n"
- "{\n"
- " *orientationOut = qtInvert(orientationIn);\n"
- " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
- "}\n"
- "void trMul(float4 translationA, Quaternion orientationA,\n"
- " float4 translationB, Quaternion orientationB,\n"
- " float4* translationOut, Quaternion* orientationOut)\n"
- "{\n"
- " *orientationOut = qtMul(orientationA,orientationB);\n"
- " *translationOut = transform(&translationB,&translationA,&orientationA);\n"
- "}\n"
- "__kernel void clipHullHullKernel( __global int4* pairs, \n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " __global const float4* separatingNormals,\n"
- " __global const int* hasSeparatingAxis,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int numPairs,\n"
- " int contactCapacity)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " float4 worldVertsB1[64];\n"
- " float4 worldVertsB2[64];\n"
- " int capacityWorldVerts = 64; \n"
- " float4 localContactsOut[64];\n"
- " int localContactCapacity=64;\n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " if (i<numPairs)\n"
- " {\n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " int numLocalContactsOut = clipHullAgainstHull(separatingNormals[i],\n"
- " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
- " rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
- " rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
- " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
- " minDist, maxDist,\n"
- " vertices,faces,indices,\n"
- " localContactsOut,localContactCapacity);\n"
- " \n"
- " if (numLocalContactsOut>0)\n"
- " {\n"
- " float4 normal = -separatingNormals[i];\n"
- " int nPoints = numLocalContactsOut;\n"
- " float4* pointsIn = localContactsOut;\n"
- " int contactIdx[4];// = {-1,-1,-1,-1};\n"
- " contactIdx[0] = -1;\n"
- " contactIdx[1] = -1;\n"
- " contactIdx[2] = -1;\n"
- " contactIdx[3] = -1;\n"
- " \n"
- " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
- " \n"
- " \n"
- " int mprContactIndex = pairs[pairIndex].z;\n"
- " int dstIdx = mprContactIndex;\n"
- " if (dstIdx<0)\n"
- " {\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " }\n"
- " if (dstIdx<contactCapacity)\n"
- " {\n"
- " pairs[pairIndex].z = dstIdx;\n"
- " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
- " c->m_worldNormalOnB = -normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " for (int i=0;i<nReducedContacts;i++)\n"
- " {\n"
- " //this condition means: overwrite contact point, unless at index i==0 we have a valid 'mpr' contact\n"
- " if (i>0||(mprContactIndex<0))\n"
- " {\n"
- " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
- " }\n"
- " }\n"
- " GET_NPOINTS(*c) = nReducedContacts;\n"
- " }\n"
- " \n"
- " }// if (numContactsOut>0)\n"
- " }// if (hasSeparatingAxis[i])\n"
- " }// if (i<numPairs)\n"
- "}\n"
- "__kernel void clipCompoundsHullHullKernel( __global const int4* gpuCompoundPairs, \n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " __global const b3GpuChildShape_t* gpuChildShapes,\n"
- " __global const float4* gpuCompoundSepNormalsOut,\n"
- " __global const int* gpuHasCompoundSepNormalsOut,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int numCompoundPairs, int maxContactCapacity)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " float4 worldVertsB1[64];\n"
- " float4 worldVertsB2[64];\n"
- " int capacityWorldVerts = 64; \n"
- " float4 localContactsOut[64];\n"
- " int localContactCapacity=64;\n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " if (i<numCompoundPairs)\n"
- " {\n"
- " if (gpuHasCompoundSepNormalsOut[i])\n"
- " {\n"
- " int bodyIndexA = gpuCompoundPairs[i].x;\n"
- " int bodyIndexB = gpuCompoundPairs[i].y;\n"
- " \n"
- " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
- " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
- " \n"
- " int collidableIndexA = -1;\n"
- " int collidableIndexB = -1;\n"
- " \n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " \n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " \n"
- " if (childShapeIndexA >= 0)\n"
- " {\n"
- " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
- " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
- " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
- " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
- " float4 newOrnA = qtMul(ornA,childOrnA);\n"
- " posA = newPosA;\n"
- " ornA = newOrnA;\n"
- " } else\n"
- " {\n"
- " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " }\n"
- " \n"
- " if (childShapeIndexB>=0)\n"
- " {\n"
- " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " } else\n"
- " {\n"
- " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
- " }\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " int numLocalContactsOut = clipHullAgainstHull(gpuCompoundSepNormalsOut[i],\n"
- " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
- " minDist, maxDist,\n"
- " vertices,faces,indices,\n"
- " localContactsOut,localContactCapacity);\n"
- " \n"
- " if (numLocalContactsOut>0)\n"
- " {\n"
- " float4 normal = -gpuCompoundSepNormalsOut[i];\n"
- " int nPoints = numLocalContactsOut;\n"
- " float4* pointsIn = localContactsOut;\n"
- " int contactIdx[4];// = {-1,-1,-1,-1};\n"
- " contactIdx[0] = -1;\n"
- " contactIdx[1] = -1;\n"
- " contactIdx[2] = -1;\n"
- " contactIdx[3] = -1;\n"
- " \n"
- " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
- " \n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " if ((dstIdx+nReducedContacts) < maxContactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
- " c->m_worldNormalOnB = -normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = gpuCompoundPairs[pairIndex].x;\n"
- " int bodyB = gpuCompoundPairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_childIndexA = childShapeIndexA;\n"
- " c->m_childIndexB = childShapeIndexB;\n"
- " for (int i=0;i<nReducedContacts;i++)\n"
- " {\n"
- " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
- " }\n"
- " GET_NPOINTS(*c) = nReducedContacts;\n"
- " }\n"
- " \n"
- " }// if (numContactsOut>0)\n"
- " }// if (gpuHasCompoundSepNormalsOut[i])\n"
- " }// if (i<numCompoundPairs)\n"
- "}\n"
- "__kernel void sphereSphereCollisionKernel( __global const int4* pairs, \n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const float4* separatingNormals,\n"
- " __global const int* hasSeparatingAxis,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int contactCapacity,\n"
- " int numPairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " if (collidables[collidableIndexA].m_shapeType == SHAPE_SPHERE &&\n"
- " collidables[collidableIndexB].m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " //sphere-sphere\n"
- " float radiusA = collidables[collidableIndexA].m_radius;\n"
- " float radiusB = collidables[collidableIndexB].m_radius;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 diff = posA-posB;\n"
- " float len = length(diff);\n"
- " \n"
- " ///iff distance positive, don't generate a new contact\n"
- " if ( len <= (radiusA+radiusB))\n"
- " {\n"
- " ///distance (negative means penetration)\n"
- " float dist = len - (radiusA+radiusB);\n"
- " float4 normalOnSurfaceB = make_float4(1.f,0.f,0.f,0.f);\n"
- " if (len > 0.00001)\n"
- " {\n"
- " normalOnSurfaceB = diff / len;\n"
- " }\n"
- " float4 contactPosB = posB + normalOnSurfaceB*radiusB;\n"
- " contactPosB.w = dist;\n"
- " \n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " if (dstIdx < contactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -normalOnSurfaceB;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_worldPosB[0] = contactPosB;\n"
- " c->m_childIndexA = -1;\n"
- " c->m_childIndexB = -1;\n"
- " GET_NPOINTS(*c) = 1;\n"
- " }//if (dstIdx < numPairs)\n"
- " }//if ( len <= (radiusA+radiusB))\n"
- " }//SHAPE_SPHERE SHAPE_SPHERE\n"
- " }//if (i<numPairs)\n"
- "} \n"
- "__kernel void clipHullHullConcaveConvexKernel( __global int4* concavePairsIn,\n"
- " __global const b3RigidBodyData_t* rigidBodies, \n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " __global const b3GpuChildShape_t* gpuChildShapes,\n"
- " __global const float4* separatingNormals,\n"
- " __global struct b3Contact4Data* restrict globalContactsOut,\n"
- " counter32_t nGlobalContactsOut,\n"
- " int contactCapacity,\n"
- " int numConcavePairs)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " float4 worldVertsB1[64];\n"
- " float4 worldVertsB2[64];\n"
- " int capacityWorldVerts = 64; \n"
- " float4 localContactsOut[64];\n"
- " int localContactCapacity=64;\n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " if (i<numConcavePairs)\n"
- " {\n"
- " //negative value means that the pair is invalid\n"
- " if (concavePairsIn[i].w<0)\n"
- " return;\n"
- " int bodyIndexA = concavePairsIn[i].x;\n"
- " int bodyIndexB = concavePairsIn[i].y;\n"
- " int f = concavePairsIn[i].z;\n"
- " int childShapeIndexA = f;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " ///////////////////////////////////////////////////////////////\n"
- " \n"
- " \n"
- " bool overlap = false;\n"
- " \n"
- " b3ConvexPolyhedronData_t convexPolyhedronA;\n"
- " //add 3 vertices of the triangle\n"
- " convexPolyhedronA.m_numVertices = 3;\n"
- " convexPolyhedronA.m_vertexOffset = 0;\n"
- " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
- " b3GpuFace_t face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
- " \n"
- " float4 verticesA[3];\n"
- " for (int i=0;i<3;i++)\n"
- " {\n"
- " int index = indices[face.m_indexOffset+i];\n"
- " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
- " verticesA[i] = vert;\n"
- " localCenter += vert;\n"
- " }\n"
- " float dmin = FLT_MAX;\n"
- " int localCC=0;\n"
- " //a triangle has 3 unique edges\n"
- " convexPolyhedronA.m_numUniqueEdges = 3;\n"
- " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
- " float4 uniqueEdgesA[3];\n"
- " \n"
- " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
- " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
- " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
- " convexPolyhedronA.m_faceOffset = 0;\n"
- " \n"
- " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
- " \n"
- " b3GpuFace_t facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
- " int indicesA[3+3+2+2+2];\n"
- " int curUsedIndices=0;\n"
- " int fidx=0;\n"
- " //front size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[0] = 0;\n"
- " indicesA[1] = 1;\n"
- " indicesA[2] = 2;\n"
- " curUsedIndices+=3;\n"
- " float c = face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = normal.x;\n"
- " facesA[fidx].m_plane.y = normal.y;\n"
- " facesA[fidx].m_plane.z = normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " //back size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[3]=2;\n"
- " indicesA[4]=1;\n"
- " indicesA[5]=0;\n"
- " curUsedIndices+=3;\n"
- " float c = dot3F4(normal,verticesA[0]);\n"
- " float c1 = -face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = -normal.x;\n"
- " facesA[fidx].m_plane.y = -normal.y;\n"
- " facesA[fidx].m_plane.z = -normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " bool addEdgePlanes = true;\n"
- " if (addEdgePlanes)\n"
- " {\n"
- " int numVertices=3;\n"
- " int prevVertex = numVertices-1;\n"
- " for (int i=0;i<numVertices;i++)\n"
- " {\n"
- " float4 v0 = verticesA[i];\n"
- " float4 v1 = verticesA[prevVertex];\n"
- " \n"
- " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
- " float c = -dot3F4(edgeNormal,v0);\n"
- " facesA[fidx].m_numIndices = 2;\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[curUsedIndices++]=i;\n"
- " indicesA[curUsedIndices++]=prevVertex;\n"
- " \n"
- " facesA[fidx].m_plane.x = edgeNormal.x;\n"
- " facesA[fidx].m_plane.y = edgeNormal.y;\n"
- " facesA[fidx].m_plane.z = edgeNormal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " fidx++;\n"
- " prevVertex = i;\n"
- " }\n"
- " }\n"
- " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
- " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " float4 sepAxis = separatingNormals[i];\n"
- " \n"
- " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
- " int childShapeIndexB =-1;\n"
- " if (shapeTypeB==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " ///////////////////\n"
- " ///compound shape support\n"
- " \n"
- " childShapeIndexB = concavePairsIn[pairIndex].w;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " \n"
- " }\n"
- " \n"
- " ////////////////////////////////////////\n"
- " \n"
- " \n"
- " \n"
- " int numLocalContactsOut = clipHullAgainstHullLocalA(sepAxis,\n"
- " &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " worldVertsB1,worldVertsB2,capacityWorldVerts,\n"
- " minDist, maxDist,\n"
- " &verticesA,&facesA,&indicesA,\n"
- " vertices,faces,indices,\n"
- " localContactsOut,localContactCapacity);\n"
- " \n"
- " if (numLocalContactsOut>0)\n"
- " {\n"
- " float4 normal = -separatingNormals[i];\n"
- " int nPoints = numLocalContactsOut;\n"
- " float4* pointsIn = localContactsOut;\n"
- " int contactIdx[4];// = {-1,-1,-1,-1};\n"
- " contactIdx[0] = -1;\n"
- " contactIdx[1] = -1;\n"
- " contactIdx[2] = -1;\n"
- " contactIdx[3] = -1;\n"
- " \n"
- " int nReducedContacts = extractManifoldSequential(pointsIn, nPoints, normal, contactIdx);\n"
- " \n"
- " int dstIdx;\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " if (dstIdx<contactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = globalContactsOut+ dstIdx;\n"
- " c->m_worldNormalOnB = -normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = concavePairsIn[pairIndex].x;\n"
- " int bodyB = concavePairsIn[pairIndex].y;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_childIndexA = childShapeIndexA;\n"
- " c->m_childIndexB = childShapeIndexB;\n"
- " for (int i=0;i<nReducedContacts;i++)\n"
- " {\n"
- " c->m_worldPosB[i] = pointsIn[contactIdx[i]];\n"
- " }\n"
- " GET_NPOINTS(*c) = nReducedContacts;\n"
- " }\n"
- " \n"
- " }// if (numContactsOut>0)\n"
- " }// if (i<numPairs)\n"
- "}\n"
- "int findClippingFaces(const float4 separatingNormal,\n"
- " __global const b3ConvexPolyhedronData_t* hullA, __global const b3ConvexPolyhedronData_t* hullB,\n"
- " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
- " __global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " int capacityWorldVerts,\n"
- " const float minDist, float maxDist,\n"
- " __global const float4* vertices,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " __global int4* clippingFaces, int pairIndex)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " \n"
- " \n"
- " int closestFaceB=-1;\n"
- " float dmax = -FLT_MAX;\n"
- " \n"
- " {\n"
- " for(int face=0;face<hullB->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(faces[hullB->m_faceOffset+face].m_plane.x,\n"
- " faces[hullB->m_faceOffset+face].m_plane.y, faces[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
- " float d = dot3F4(WorldNormal,separatingNormal);\n"
- " if (d > dmax)\n"
- " {\n"
- " dmax = d;\n"
- " closestFaceB = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " {\n"
- " const b3GpuFace_t polyB = faces[hullB->m_faceOffset+closestFaceB];\n"
- " const int numVertices = polyB.m_numIndices;\n"
- " for(int e0=0;e0<numVertices;e0++)\n"
- " {\n"
- " const float4 b = vertices[hullB->m_vertexOffset+indices[polyB.m_indexOffset+e0]];\n"
- " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
- " }\n"
- " }\n"
- " \n"
- " int closestFaceA=-1;\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " for(int face=0;face<hullA->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(\n"
- " faces[hullA->m_faceOffset+face].m_plane.x,\n"
- " faces[hullA->m_faceOffset+face].m_plane.y,\n"
- " faces[hullA->m_faceOffset+face].m_plane.z,\n"
- " 0.f);\n"
- " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
- " \n"
- " float d = dot3F4(faceANormalWS,separatingNormal);\n"
- " if (d < dmin)\n"
- " {\n"
- " dmin = d;\n"
- " closestFaceA = face;\n"
- " worldNormalsA1[pairIndex] = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " int numVerticesA = faces[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
- " for(int e0=0;e0<numVerticesA;e0++)\n"
- " {\n"
- " const float4 a = vertices[hullA->m_vertexOffset+indices[faces[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
- " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
- " }\n"
- " \n"
- " clippingFaces[pairIndex].x = closestFaceA;\n"
- " clippingFaces[pairIndex].y = closestFaceB;\n"
- " clippingFaces[pairIndex].z = numVerticesA;\n"
- " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
- " \n"
- " \n"
- " return numContactsOut;\n"
- "}\n"
- "int clipFaces(__global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " __global float4* worldVertsB2, \n"
- " int capacityWorldVertsB2,\n"
- " const float minDist, float maxDist,\n"
- " __global int4* clippingFaces,\n"
- " int pairIndex)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " \n"
- " int closestFaceA = clippingFaces[pairIndex].x;\n"
- " int closestFaceB = clippingFaces[pairIndex].y;\n"
- " int numVertsInA = clippingFaces[pairIndex].z;\n"
- " int numVertsInB = clippingFaces[pairIndex].w;\n"
- " \n"
- " int numVertsOut = 0;\n"
- " \n"
- " if (closestFaceA<0)\n"
- " return numContactsOut;\n"
- " \n"
- " __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
- " __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
- " \n"
- " \n"
- " \n"
- " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
- " \n"
- " for(int e0=0;e0<numVertsInA;e0++)\n"
- " {\n"
- " const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
- " const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
- " const float4 WorldEdge0 = aw - bw;\n"
- " float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
- " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
- " float4 worldA1 = aw;\n"
- " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
- " float4 planeNormalWS = planeNormalWS1;\n"
- " float planeEqWS=planeEqWS1;\n"
- " numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
- " __global float4* tmp = pVtxOut;\n"
- " pVtxOut = pVtxIn;\n"
- " pVtxIn = tmp;\n"
- " numVertsInB = numVertsOut;\n"
- " numVertsOut = 0;\n"
- " }\n"
- " \n"
- " //float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
- " //float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
- " \n"
- " /*for (int i=0;i<numVertsInB;i++)\n"
- " {\n"
- " pVtxOut[i] = pVtxIn[i];\n"
- " }*/\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " //numVertsInB=0;\n"
- " \n"
- " float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
- " float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
- " for (int i=0;i<numVertsInB;i++)\n"
- " {\n"
- " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
- " if (depth <=minDist)\n"
- " {\n"
- " depth = minDist;\n"
- " }\n"
- " \n"
- " if (depth <=maxDist)\n"
- " {\n"
- " float4 pointInWorld = pVtxIn[i];\n"
- " pVtxOut[numContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
- " }\n"
- " }\n"
- " \n"
- " clippingFaces[pairIndex].w =numContactsOut;\n"
- " \n"
- " \n"
- " return numContactsOut;\n"
- "}\n"
- "__kernel void findClippingFacesKernel( __global const int4* pairs,\n"
- " __global const b3RigidBodyData_t* rigidBodies,\n"
- " __global const b3Collidable_t* collidables,\n"
- " __global const b3ConvexPolyhedronData_t* convexShapes,\n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const b3GpuFace_t* faces,\n"
- " __global const int* indices,\n"
- " __global const float4* separatingNormals,\n"
- " __global const int* hasSeparatingAxis,\n"
- " __global int4* clippingFacesOut,\n"
- " __global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " int capacityWorldVerts,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " \n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " \n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " \n"
- " int numLocalContactsOut = findClippingFaces(separatingNormals[i],\n"
- " &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],\n"
- " rigidBodies[bodyIndexA].m_pos,rigidBodies[bodyIndexA].m_quat,\n"
- " rigidBodies[bodyIndexB].m_pos,rigidBodies[bodyIndexB].m_quat,\n"
- " worldVertsA1,\n"
- " worldNormalsA1,\n"
- " worldVertsB1,capacityWorldVerts,\n"
- " minDist, maxDist,\n"
- " vertices,faces,indices,\n"
- " clippingFacesOut,i);\n"
- " \n"
- " \n"
- " }// if (hasSeparatingAxis[i])\n"
- " }// if (i<numPairs)\n"
- " \n"
- "}\n"
- "__kernel void clipFacesAndFindContactsKernel( __global const float4* separatingNormals,\n"
- " __global const int* hasSeparatingAxis,\n"
- " __global int4* clippingFacesOut,\n"
- " __global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " __global float4* worldVertsB2,\n"
- " int vertexFaceCapacity,\n"
- " int numPairs,\n"
- " int debugMode\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " \n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- "// int bodyIndexA = pairs[i].x;\n"
- " // int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int numLocalContactsOut = 0;\n"
- " int capacityWorldVertsB2 = vertexFaceCapacity;\n"
- " \n"
- " __global float4* pVtxIn = &worldVertsB1[pairIndex*capacityWorldVertsB2];\n"
- " __global float4* pVtxOut = &worldVertsB2[pairIndex*capacityWorldVertsB2];\n"
- " \n"
- " {\n"
- " __global int4* clippingFaces = clippingFacesOut;\n"
- " \n"
- " \n"
- " int closestFaceA = clippingFaces[pairIndex].x;\n"
- " int closestFaceB = clippingFaces[pairIndex].y;\n"
- " int numVertsInA = clippingFaces[pairIndex].z;\n"
- " int numVertsInB = clippingFaces[pairIndex].w;\n"
- " \n"
- " int numVertsOut = 0;\n"
- " \n"
- " if (closestFaceA>=0)\n"
- " {\n"
- " \n"
- " \n"
- " \n"
- " // clip polygon to back of planes of all faces of hull A that are adjacent to witness face\n"
- " \n"
- " for(int e0=0;e0<numVertsInA;e0++)\n"
- " {\n"
- " const float4 aw = worldVertsA1[pairIndex*capacityWorldVertsB2+e0];\n"
- " const float4 bw = worldVertsA1[pairIndex*capacityWorldVertsB2+((e0+1)%numVertsInA)];\n"
- " const float4 WorldEdge0 = aw - bw;\n"
- " float4 worldPlaneAnormal1 = worldNormalsA1[pairIndex];\n"
- " float4 planeNormalWS1 = -cross3(WorldEdge0,worldPlaneAnormal1);\n"
- " float4 worldA1 = aw;\n"
- " float planeEqWS1 = -dot3F4(worldA1,planeNormalWS1);\n"
- " float4 planeNormalWS = planeNormalWS1;\n"
- " float planeEqWS=planeEqWS1;\n"
- " numVertsOut = clipFaceGlobal(pVtxIn, numVertsInB, planeNormalWS,planeEqWS, pVtxOut);\n"
- " __global float4* tmp = pVtxOut;\n"
- " pVtxOut = pVtxIn;\n"
- " pVtxIn = tmp;\n"
- " numVertsInB = numVertsOut;\n"
- " numVertsOut = 0;\n"
- " }\n"
- " \n"
- " float4 planeNormalWS = worldNormalsA1[pairIndex];\n"
- " float planeEqWS=-dot3F4(planeNormalWS,worldVertsA1[pairIndex*capacityWorldVertsB2]);\n"
- " \n"
- " for (int i=0;i<numVertsInB;i++)\n"
- " {\n"
- " float depth = dot3F4(planeNormalWS,pVtxIn[i])+planeEqWS;\n"
- " if (depth <=minDist)\n"
- " {\n"
- " depth = minDist;\n"
- " }\n"
- " \n"
- " if (depth <=maxDist)\n"
- " {\n"
- " float4 pointInWorld = pVtxIn[i];\n"
- " pVtxOut[numLocalContactsOut++] = make_float4(pointInWorld.x,pointInWorld.y,pointInWorld.z,depth);\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- " clippingFaces[pairIndex].w =numLocalContactsOut;\n"
- " \n"
- " }\n"
- " \n"
- " for (int i=0;i<numLocalContactsOut;i++)\n"
- " pVtxIn[i] = pVtxOut[i];\n"
- " \n"
- " }// if (hasSeparatingAxis[i])\n"
- " }// if (i<numPairs)\n"
- " \n"
- "}\n"
- "__kernel void newContactReductionKernel( __global int4* pairs,\n"
- " __global const b3RigidBodyData_t* rigidBodies,\n"
- " __global const float4* separatingNormals,\n"
- " __global const int* hasSeparatingAxis,\n"
- " __global struct b3Contact4Data* globalContactsOut,\n"
- " __global int4* clippingFaces,\n"
- " __global float4* worldVertsB2,\n"
- " volatile __global int* nGlobalContactsOut,\n"
- " int vertexFaceCapacity,\n"
- " int contactCapacity,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " int pairIndex = i;\n"
- " \n"
- " int4 contactIdx;\n"
- " contactIdx=make_int4(0,1,2,3);\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " \n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " int nPoints = clippingFaces[pairIndex].w;\n"
- " \n"
- " if (nPoints>0)\n"
- " {\n"
- " __global float4* pointsIn = &worldVertsB2[pairIndex*vertexFaceCapacity];\n"
- " float4 normal = -separatingNormals[i];\n"
- " \n"
- " int nReducedContacts = extractManifoldSequentialGlobal(pointsIn, nPoints, normal, &contactIdx);\n"
- " \n"
- " int mprContactIndex = pairs[pairIndex].z;\n"
- " int dstIdx = mprContactIndex;\n"
- " if (dstIdx<0)\n"
- " {\n"
- " AppendInc( nGlobalContactsOut, dstIdx );\n"
- " }\n"
- "//#if 0\n"
- " \n"
- " if (dstIdx < contactCapacity)\n"
- " {\n"
- " __global struct b3Contact4Data* c = &globalContactsOut[dstIdx];\n"
- " c->m_worldNormalOnB = -normal;\n"
- " c->m_restituitionCoeffCmp = (0.f*0xffff);c->m_frictionCoeffCmp = (0.7f*0xffff);\n"
- " c->m_batchIdx = pairIndex;\n"
- " int bodyA = pairs[pairIndex].x;\n"
- " int bodyB = pairs[pairIndex].y;\n"
- " pairs[pairIndex].w = dstIdx;\n"
- " c->m_bodyAPtrAndSignBit = rigidBodies[bodyA].m_invMass==0?-bodyA:bodyA;\n"
- " c->m_bodyBPtrAndSignBit = rigidBodies[bodyB].m_invMass==0?-bodyB:bodyB;\n"
- " c->m_childIndexA =-1;\n"
- " c->m_childIndexB =-1;\n"
- " switch (nReducedContacts)\n"
- " {\n"
- " case 4:\n"
- " c->m_worldPosB[3] = pointsIn[contactIdx.w];\n"
- " case 3:\n"
- " c->m_worldPosB[2] = pointsIn[contactIdx.z];\n"
- " case 2:\n"
- " c->m_worldPosB[1] = pointsIn[contactIdx.y];\n"
- " case 1:\n"
- " if (mprContactIndex<0)//test\n"
- " c->m_worldPosB[0] = pointsIn[contactIdx.x];\n"
- " default:\n"
- " {\n"
- " }\n"
- " };\n"
- " \n"
- " GET_NPOINTS(*c) = nReducedContacts;\n"
- " \n"
- " }\n"
- " \n"
- " \n"
- "//#endif\n"
- " \n"
- " }// if (numContactsOut>0)\n"
- " }// if (hasSeparatingAxis[i])\n"
- " }// if (i<numPairs)\n"
- " \n"
- " \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl
deleted file mode 100644
index 31ca43b8cd..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcave.cl
+++ /dev/null
@@ -1,1220 +0,0 @@
-
-//keep this enum in sync with the CPU version (in btCollidable.h)
-//written by Erwin Coumans
-
-
-#define SHAPE_CONVEX_HULL 3
-#define SHAPE_CONCAVE_TRIMESH 5
-#define TRIANGLE_NUM_CONVEX_FACES 5
-#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
-
-#define B3_MAX_STACK_DEPTH 256
-
-
-typedef unsigned int u32;
-
-///keep this in sync with btCollidable.h
-typedef struct
-{
- union {
- int m_numChildShapes;
- int m_bvhIndex;
- };
- union
- {
- float m_radius;
- int m_compoundBvhIndex;
- };
-
- int m_shapeType;
- int m_shapeIndex;
-
-} btCollidableGpu;
-
-#define MAX_NUM_PARTS_IN_BITS 10
-
-///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrTriangleIndex;
-} b3QuantizedBvhNode;
-
-typedef struct
-{
- float4 m_aabbMin;
- float4 m_aabbMax;
- float4 m_quantization;
- int m_numNodes;
- int m_numSubTrees;
- int m_nodeOffset;
- int m_subTreeOffset;
-
-} b3BvhInfo;
-
-
-int getTriangleIndex(const b3QuantizedBvhNode* rootNode)
-{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
-}
-
-int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- unsigned int x=0;
- unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (rootNode->m_escapeIndexOrTriangleIndex&~(y));
-}
-
-int isLeafNode(const b3QuantizedBvhNode* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
-}
-
-int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;
-}
-
-int getEscapeIndex(const b3QuantizedBvhNode* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)
-{
- return -rootNode->m_escapeIndexOrTriangleIndex;
-}
-
-
-typedef struct
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
- //4 bytes
- int m_subtreeSize;
- int m_padding[3];
-} b3BvhSubtreeInfo;
-
-
-
-
-
-
-
-typedef struct
-{
- float4 m_childPosition;
- float4 m_childOrientation;
- int m_shapeIndex;
- int m_unused0;
- int m_unused1;
- int m_unused2;
-} btGpuChildShape;
-
-
-typedef struct
-{
- float4 m_pos;
- float4 m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} BodyData;
-
-
-typedef struct
-{
- float4 m_localCenter;
- float4 m_extents;
- float4 mC;
- float4 mE;
-
- float m_radius;
- int m_faceOffset;
- int m_numFaces;
- int m_numVertices;
-
- int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
- int m_unused;
-} ConvexPolyhedronCL;
-
-typedef struct
-{
- union
- {
- float4 m_min;
- float m_minElems[4];
- int m_minIndices[4];
- };
- union
- {
- float4 m_max;
- float m_maxElems[4];
- int m_maxIndices[4];
- };
-} btAabbCL;
-
-#include "Bullet3Collision/BroadPhaseCollision/shared/b3Aabb.h"
-#include "Bullet3Common/shared/b3Int2.h"
-
-
-
-typedef struct
-{
- float4 m_plane;
- int m_indexOffset;
- int m_numIndices;
-} btGpuFace;
-
-#define make_float4 (float4)
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-
-
-// float4 a1 = make_float4(a.xyz,0.f);
-// float4 b1 = make_float4(b.xyz,0.f);
-
-// return cross(a1,b1);
-
-//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);
-
- // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);
-
- //return c;
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- v = make_float4(v.xyz,0.f);
- return fast_normalize(v);
-}
-
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-__inline
-float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)
-{
- return qtRotate( *orientation, *p ) + (*translation);
-}
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-}
-
-inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
-const float4* dir, const float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const float4 localDir = qtInvRotate(orn,*dir);
- float offset = dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
- {
- float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
- min[0] = dp;
- if(dp > max[0])
- max[0] = dp;
- }
- if(min[0]>max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn,
-const float4* dir, __global const float4* vertices, float* min, float* max)
-{
- min[0] = FLT_MAX;
- max[0] = -FLT_MAX;
- int numVerts = hull->m_numVertices;
-
- const float4 localDir = qtInvRotate(orn,*dir);
- float offset = dot(pos,*dir);
- for(int i=0;i<numVerts;i++)
- {
- float dp = dot(vertices[hull->m_vertexOffset+i],localDir);
- if(dp < min[0])
- min[0] = dp;
- if(dp > max[0])
- max[0] = dp;
- }
- if(min[0]>max[0])
- {
- float tmp = min[0];
- min[0] = max[0];
- max[0] = tmp;
- }
- min[0] += offset;
- max[0] += offset;
-}
-
-inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA,const float4 ornA,
- const float4 posB,const float4 ornB,
- float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)
-{
- float Min0,Max0;
- float Min1,Max1;
- projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);
- project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- return false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- *depth = d0<d1 ? d0:d1;
- return true;
-}
-
-
-
-
-inline bool IsAlmostZero(const float4 v)
-{
- if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)
- return false;
- return true;
-}
-
-
-
-bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
-
- const float4* verticesA,
- const float4* uniqueEdgesA,
- const btGpuFace* facesA,
- const int* indicesA,
-
- __global const float4* verticesB,
- __global const float4* uniqueEdgesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
- int curPlaneTests=0;
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for(int i=0;i<numFacesA;i++)
- {
- const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
- float4 faceANormalWS = qtRotate(ornA,normal);
- if (dot3F4(DeltaC2,faceANormalWS)<0)
- faceANormalWS*=-1.f;
- curPlaneTests++;
- float d;
- if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))
- return false;
- if(d<*dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- __global const float4* verticesA,
- __global const float4* uniqueEdgesA,
- __global const btGpuFace* facesA,
- __global const int* indicesA,
- const float4* verticesB,
- const float4* uniqueEdgesB,
- const btGpuFace* facesB,
- const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
- int curPlaneTests=0;
- {
- int numFacesA = hullA->m_numFaces;
- // Test normals from hullA
- for(int i=0;i<numFacesA;i++)
- {
- const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;
- float4 faceANormalWS = qtRotate(ornA,normal);
- if (dot3F4(DeltaC2,faceANormalWS)<0)
- faceANormalWS *= -1.f;
- curPlaneTests++;
- float d;
- if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))
- return false;
- if(d<*dmin)
- {
- *dmin = d;
- *sep = faceANormalWS;
- }
- }
- }
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-
-bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB,
- const float4 posA1,
- const float4 ornA,
- const float4 posB1,
- const float4 ornB,
- const float4 DeltaC2,
- const float4* verticesA,
- const float4* uniqueEdgesA,
- const btGpuFace* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const float4* uniqueEdgesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- float4* sep,
- float* dmin)
-{
-
-
- float4 posA = posA1;
- posA.w = 0.f;
- float4 posB = posB1;
- posB.w = 0.f;
-
- int curPlaneTests=0;
-
- int curEdgeEdge = 0;
- // Test edges
- for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)
- {
- const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];
- float4 edge0World = qtRotate(ornA,edge0);
-
- for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)
- {
- const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];
- float4 edge1World = qtRotate(ornB,edge1);
-
-
- float4 crossje = cross3(edge0World,edge1World);
-
- curEdgeEdge++;
- if(!IsAlmostZero(crossje))
- {
- crossje = normalize3(crossje);
- if (dot3F4(DeltaC2,crossje)<0)
- crossje *= -1.f;
-
- float dist;
- bool result = true;
- {
- float Min0,Max0;
- float Min1,Max1;
- projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);
- project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);
-
- if(Max0<Min1 || Max1<Min0)
- result = false;
-
- float d0 = Max0 - Min1;
- float d1 = Max1 - Min0;
- dist = d0<d1 ? d0:d1;
- result = true;
-
- }
-
-
- if(dist<*dmin)
- {
- *dmin = dist;
- *sep = crossje;
- }
- }
- }
-
- }
-
-
- if((dot3F4(-DeltaC2,*sep))>0.0f)
- {
- *sep = -(*sep);
- }
- return true;
-}
-
-
-
-inline int findClippingFaces(const float4 separatingNormal,
- const ConvexPolyhedronCL* hullA,
- __global const ConvexPolyhedronCL* hullB,
- const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,
- __global float4* worldVertsA1,
- __global float4* worldNormalsA1,
- __global float4* worldVertsB1,
- int capacityWorldVerts,
- const float minDist, float maxDist,
- const float4* verticesA,
- const btGpuFace* facesA,
- const int* indicesA,
- __global const float4* verticesB,
- __global const btGpuFace* facesB,
- __global const int* indicesB,
- __global int4* clippingFaces, int pairIndex)
-{
- int numContactsOut = 0;
- int numWorldVertsB1= 0;
-
-
- int closestFaceB=0;
- float dmax = -FLT_MAX;
-
- {
- for(int face=0;face<hullB->m_numFaces;face++)
- {
- const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,
- facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);
- const float4 WorldNormal = qtRotate(ornB, Normal);
- float d = dot3F4(WorldNormal,separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
-
- {
- const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];
- int numVertices = polyB.m_numIndices;
- if (numVertices>capacityWorldVerts)
- numVertices = capacityWorldVerts;
- if (numVertices<0)
- numVertices = 0;
-
- for(int e0=0;e0<numVertices;e0++)
- {
- if (e0<capacityWorldVerts)
- {
- const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];
- worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);
- }
- }
- }
-
- int closestFaceA=0;
- {
- float dmin = FLT_MAX;
- for(int face=0;face<hullA->m_numFaces;face++)
- {
- const float4 Normal = make_float4(
- facesA[hullA->m_faceOffset+face].m_plane.x,
- facesA[hullA->m_faceOffset+face].m_plane.y,
- facesA[hullA->m_faceOffset+face].m_plane.z,
- 0.f);
- const float4 faceANormalWS = qtRotate(ornA,Normal);
-
- float d = dot3F4(faceANormalWS,separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- worldNormalsA1[pairIndex] = faceANormalWS;
- }
- }
- }
-
- int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;
- if (numVerticesA>capacityWorldVerts)
- numVerticesA = capacityWorldVerts;
- if (numVerticesA<0)
- numVerticesA=0;
-
- for(int e0=0;e0<numVerticesA;e0++)
- {
- if (e0<capacityWorldVerts)
- {
- const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];
- worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);
- }
- }
-
- clippingFaces[pairIndex].x = closestFaceA;
- clippingFaces[pairIndex].y = closestFaceB;
- clippingFaces[pairIndex].z = numVerticesA;
- clippingFaces[pairIndex].w = numWorldVertsB1;
-
-
- return numContactsOut;
-}
-
-
-
-
-// work-in-progress
-__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global const btGpuChildShape* gpuChildShapes,
- __global btAabbCL* aabbs,
- __global float4* concaveSeparatingNormalsOut,
- __global int* concaveHasSeparatingNormals,
- __global int4* clippingFacesOut,
- __global float4* worldVertsA1GPU,
- __global float4* worldNormalsAGPU,
- __global float4* worldVertsB1GPU,
- __global float* dmins,
- int vertexFaceCapacity,
- int numConcavePairs
- )
-{
-
- int i = get_global_id(0);
- if (i>=numConcavePairs)
- return;
-
- concaveHasSeparatingNormals[i] = 0;
-
- int pairIdx = i;
-
- int bodyIndexA = concavePairs[i].x;
- int bodyIndexB = concavePairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
- if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&
- collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- concavePairs[pairIdx].w = -1;
- return;
- }
-
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- int numActualConcaveConvexTests = 0;
-
- int f = concavePairs[i].z;
-
- bool overlap = false;
-
- ConvexPolyhedronCL convexPolyhedronA;
-
- //add 3 vertices of the triangle
- convexPolyhedronA.m_numVertices = 3;
- convexPolyhedronA.m_vertexOffset = 0;
- float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
-
- btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
- float4 triMinAabb, triMaxAabb;
- btAabbCL triAabb;
- triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
- triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
-
- float4 verticesA[3];
- for (int i=0;i<3;i++)
- {
- int index = indices[face.m_indexOffset+i];
- float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
- verticesA[i] = vert;
- localCenter += vert;
-
- triAabb.m_min = min(triAabb.m_min,vert);
- triAabb.m_max = max(triAabb.m_max,vert);
-
- }
-
- overlap = true;
- overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
- overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
- overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
-
- if (overlap)
- {
- float dmin = FLT_MAX;
- int hasSeparatingAxis=5;
- float4 sepAxis=make_float4(1,2,3,4);
-
- int localCC=0;
- numActualConcaveConvexTests++;
-
- //a triangle has 3 unique edges
- convexPolyhedronA.m_numUniqueEdges = 3;
- convexPolyhedronA.m_uniqueEdgesOffset = 0;
- float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
-
-
- convexPolyhedronA.m_faceOffset = 0;
-
- float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
-
- btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3+3+2+2+2];
- int curUsedIndices=0;
- int fidx=0;
-
- //front size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[0] = 0;
- indicesA[1] = 1;
- indicesA[2] = 2;
- curUsedIndices+=3;
- float c = face.m_plane.w;
- facesA[fidx].m_plane.x = normal.x;
- facesA[fidx].m_plane.y = normal.y;
- facesA[fidx].m_plane.z = normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
- //back size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[3]=2;
- indicesA[4]=1;
- indicesA[5]=0;
- curUsedIndices+=3;
- float c = dot(normal,verticesA[0]);
- float c1 = -face.m_plane.w;
- facesA[fidx].m_plane.x = -normal.x;
- facesA[fidx].m_plane.y = -normal.y;
- facesA[fidx].m_plane.z = -normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
-
- bool addEdgePlanes = true;
- if (addEdgePlanes)
- {
- int numVertices=3;
- int prevVertex = numVertices-1;
- for (int i=0;i<numVertices;i++)
- {
- float4 v0 = verticesA[i];
- float4 v1 = verticesA[prevVertex];
-
- float4 edgeNormal = normalize(cross(normal,v1-v0));
- float c = -dot(edgeNormal,v0);
-
- facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[curUsedIndices++]=i;
- indicesA[curUsedIndices++]=prevVertex;
-
- facesA[fidx].m_plane.x = edgeNormal.x;
- facesA[fidx].m_plane.y = edgeNormal.y;
- facesA[fidx].m_plane.z = edgeNormal.z;
- facesA[fidx].m_plane.w = c;
- fidx++;
- prevVertex = i;
- }
- }
- convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
-
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
-
-
-
-
- ///////////////////
- ///compound shape support
-
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int compoundChild = concavePairs[pairIdx].w;
- int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- }
- //////////////////
-
- float4 c0local = convexPolyhedronA.m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
-
-
- bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin);
- hasSeparatingAxis = 4;
- if (!sepA)
- {
- hasSeparatingAxis = 0;
- } else
- {
- bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,
- posB,ornB,
- posA,ornA,
- DeltaC2,
- vertices,uniqueEdges,faces,indices,
- verticesA,uniqueEdgesA,facesA,indicesA,
- &sepAxis,&dmin);
-
- if (!sepB)
- {
- hasSeparatingAxis = 0;
- } else
- {
- hasSeparatingAxis = 1;
- }
- }
-
- if (hasSeparatingAxis)
- {
- dmins[i] = dmin;
- concaveSeparatingNormalsOut[pairIdx]=sepAxis;
- concaveHasSeparatingNormals[i]=1;
-
- } else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
- }
- else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
-}
-
-
-
-
-// work-in-progress
-__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,
- __global const BodyData* rigidBodies,
- __global const btCollidableGpu* collidables,
- __global const ConvexPolyhedronCL* convexShapes,
- __global const float4* vertices,
- __global const float4* uniqueEdges,
- __global const btGpuFace* faces,
- __global const int* indices,
- __global const btGpuChildShape* gpuChildShapes,
- __global btAabbCL* aabbs,
- __global float4* concaveSeparatingNormalsOut,
- __global int* concaveHasSeparatingNormals,
- __global int4* clippingFacesOut,
- __global float4* worldVertsA1GPU,
- __global float4* worldNormalsAGPU,
- __global float4* worldVertsB1GPU,
- __global float* dmins,
- int vertexFaceCapacity,
- int numConcavePairs
- )
-{
-
- int i = get_global_id(0);
- if (i>=numConcavePairs)
- return;
-
- if (!concaveHasSeparatingNormals[i])
- return;
-
- int pairIdx = i;
-
- int bodyIndexA = concavePairs[i].x;
- int bodyIndexB = concavePairs[i].y;
-
- int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;
- int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;
-
- int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;
- int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;
-
-
- int numFacesA = convexShapes[shapeIndexA].m_numFaces;
- int numActualConcaveConvexTests = 0;
-
- int f = concavePairs[i].z;
-
- bool overlap = false;
-
- ConvexPolyhedronCL convexPolyhedronA;
-
- //add 3 vertices of the triangle
- convexPolyhedronA.m_numVertices = 3;
- convexPolyhedronA.m_vertexOffset = 0;
- float4 localCenter = make_float4(0.f,0.f,0.f,0.f);
-
- btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];
- float4 triMinAabb, triMaxAabb;
- btAabbCL triAabb;
- triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);
- triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);
-
- float4 verticesA[3];
- for (int i=0;i<3;i++)
- {
- int index = indices[face.m_indexOffset+i];
- float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];
- verticesA[i] = vert;
- localCenter += vert;
-
- triAabb.m_min = min(triAabb.m_min,vert);
- triAabb.m_max = max(triAabb.m_max,vert);
-
- }
-
- overlap = true;
- overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;
- overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;
- overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;
-
- if (overlap)
- {
- float dmin = dmins[i];
- int hasSeparatingAxis=5;
- float4 sepAxis=make_float4(1,2,3,4);
- sepAxis = concaveSeparatingNormalsOut[pairIdx];
-
- int localCC=0;
- numActualConcaveConvexTests++;
-
- //a triangle has 3 unique edges
- convexPolyhedronA.m_numUniqueEdges = 3;
- convexPolyhedronA.m_uniqueEdgesOffset = 0;
- float4 uniqueEdgesA[3];
-
- uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);
- uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);
- uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);
-
-
- convexPolyhedronA.m_faceOffset = 0;
-
- float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);
-
- btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];
- int indicesA[3+3+2+2+2];
- int curUsedIndices=0;
- int fidx=0;
-
- //front size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[0] = 0;
- indicesA[1] = 1;
- indicesA[2] = 2;
- curUsedIndices+=3;
- float c = face.m_plane.w;
- facesA[fidx].m_plane.x = normal.x;
- facesA[fidx].m_plane.y = normal.y;
- facesA[fidx].m_plane.z = normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
- //back size of triangle
- {
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[3]=2;
- indicesA[4]=1;
- indicesA[5]=0;
- curUsedIndices+=3;
- float c = dot(normal,verticesA[0]);
- float c1 = -face.m_plane.w;
- facesA[fidx].m_plane.x = -normal.x;
- facesA[fidx].m_plane.y = -normal.y;
- facesA[fidx].m_plane.z = -normal.z;
- facesA[fidx].m_plane.w = c;
- facesA[fidx].m_numIndices=3;
- }
- fidx++;
-
- bool addEdgePlanes = true;
- if (addEdgePlanes)
- {
- int numVertices=3;
- int prevVertex = numVertices-1;
- for (int i=0;i<numVertices;i++)
- {
- float4 v0 = verticesA[i];
- float4 v1 = verticesA[prevVertex];
-
- float4 edgeNormal = normalize(cross(normal,v1-v0));
- float c = -dot(edgeNormal,v0);
-
- facesA[fidx].m_numIndices = 2;
- facesA[fidx].m_indexOffset=curUsedIndices;
- indicesA[curUsedIndices++]=i;
- indicesA[curUsedIndices++]=prevVertex;
-
- facesA[fidx].m_plane.x = edgeNormal.x;
- facesA[fidx].m_plane.y = edgeNormal.y;
- facesA[fidx].m_plane.z = edgeNormal.z;
- facesA[fidx].m_plane.w = c;
- fidx++;
- prevVertex = i;
- }
- }
- convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;
- convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);
-
-
- float4 posA = rigidBodies[bodyIndexA].m_pos;
- posA.w = 0.f;
- float4 posB = rigidBodies[bodyIndexB].m_pos;
- posB.w = 0.f;
-
- float4 ornA = rigidBodies[bodyIndexA].m_quat;
- float4 ornB =rigidBodies[bodyIndexB].m_quat;
-
-
-
-
- ///////////////////
- ///compound shape support
-
- if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)
- {
- int compoundChild = concavePairs[pairIdx].w;
- int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;
- int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;
- float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;
- float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;
- float4 newPosB = transform(&childPosB,&posB,&ornB);
- float4 newOrnB = qtMul(ornB,childOrnB);
- posB = newPosB;
- ornB = newOrnB;
- shapeIndexB = collidables[childColIndexB].m_shapeIndex;
- }
- //////////////////
-
- float4 c0local = convexPolyhedronA.m_localCenter;
- float4 c0 = transform(&c0local, &posA, &ornA);
- float4 c1local = convexShapes[shapeIndexB].m_localCenter;
- float4 c1 = transform(&c1local,&posB,&ornB);
- const float4 DeltaC2 = c0 - c1;
-
-
- {
- bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- DeltaC2,
- verticesA,uniqueEdgesA,facesA,indicesA,
- vertices,uniqueEdges,faces,indices,
- &sepAxis,&dmin);
-
- if (!sepEE)
- {
- hasSeparatingAxis = 0;
- } else
- {
- hasSeparatingAxis = 1;
- }
- }
-
-
- if (hasSeparatingAxis)
- {
- sepAxis.w = dmin;
- dmins[i] = dmin;
- concaveSeparatingNormalsOut[pairIdx]=sepAxis;
- concaveHasSeparatingNormals[i]=1;
-
- float minDist = -1e30f;
- float maxDist = 0.02f;
-
-
- findClippingFaces(sepAxis,
- &convexPolyhedronA,
- &convexShapes[shapeIndexB],
- posA,ornA,
- posB,ornB,
- worldVertsA1GPU,
- worldNormalsAGPU,
- worldVertsB1GPU,
- vertexFaceCapacity,
- minDist, maxDist,
- verticesA,
- facesA,
- indicesA,
- vertices,
- faces,
- indices,
- clippingFacesOut, pairIdx);
-
-
- } else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
- }
- else
- {
- //mark this pair as in-active
- concavePairs[pairIdx].w = -1;
- }
-
- concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points
-}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
deleted file mode 100644
index a60702ca62..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satConcaveKernels.h
+++ /dev/null
@@ -1,1456 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satConcaveKernelsCL =
- "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
- "//written by Erwin Coumans\n"
- "#define SHAPE_CONVEX_HULL 3\n"
- "#define SHAPE_CONCAVE_TRIMESH 5\n"
- "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
- "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
- "#define B3_MAX_STACK_DEPTH 256\n"
- "typedef unsigned int u32;\n"
- "///keep this in sync with btCollidable.h\n"
- "typedef struct\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_radius;\n"
- " int m_compoundBvhIndex;\n"
- " };\n"
- " \n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- " \n"
- "} btCollidableGpu;\n"
- "#define MAX_NUM_PARTS_IN_BITS 10\n"
- "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
- "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes\n"
- " int m_escapeIndexOrTriangleIndex;\n"
- "} b3QuantizedBvhNode;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_aabbMin;\n"
- " float4 m_aabbMax;\n"
- " float4 m_quantization;\n"
- " int m_numNodes;\n"
- " int m_numSubTrees;\n"
- " int m_nodeOffset;\n"
- " int m_subTreeOffset;\n"
- "} b3BvhInfo;\n"
- "int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " unsigned int x=0;\n"
- " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
- " // Get only the lower bits where the triangle index is stored\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
- "}\n"
- "int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " unsigned int x=0;\n"
- " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
- " // Get only the lower bits where the triangle index is stored\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
- "}\n"
- "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
- "}\n"
- "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
- "}\n"
- " \n"
- "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
- "}\n"
- "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes, points to the root of the subtree\n"
- " int m_rootNodeIndex;\n"
- " //4 bytes\n"
- " int m_subtreeSize;\n"
- " int m_padding[3];\n"
- "} b3BvhSubtreeInfo;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_childPosition;\n"
- " float4 m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "} btGpuChildShape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " float4 m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} BodyData;\n"
- "typedef struct \n"
- "{\n"
- " float4 m_localCenter;\n"
- " float4 m_extents;\n"
- " float4 mC;\n"
- " float4 mE;\n"
- " \n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "} ConvexPolyhedronCL;\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} btAabbCL;\n"
- "#ifndef B3_AABB_H\n"
- "#define B3_AABB_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3Aabb b3Aabb_t;\n"
- "struct b3Aabb\n"
- "{\n"
- " union\n"
- " {\n"
- " float m_min[4];\n"
- " b3Float4 m_minVec;\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_max[4];\n"
- " b3Float4 m_maxVec;\n"
- " int m_signedMaxIndices[4];\n"
- " };\n"
- "};\n"
- "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
- " b3Float4ConstArg pos,\n"
- " b3QuatConstArg orn,\n"
- " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
- "{\n"
- " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
- " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
- " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
- " b3Mat3x3 m;\n"
- " m = b3QuatGetRotationMatrix(orn);\n"
- " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
- " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
- " \n"
- " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
- " 0.f);\n"
- " *aabbMinOut = center-extent;\n"
- " *aabbMaxOut = center+extent;\n"
- "}\n"
- "/// conservative test for overlap between two aabbs\n"
- "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
- " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
- " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
- " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "#endif //B3_AABB_H\n"
- "/*\n"
- "Bullet Continuous Collision Detection and Physics Library\n"
- "Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose,\n"
- "including commercial applications, and to alter it and redistribute it freely,\n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "#ifndef B3_INT2_H\n"
- "#define B3_INT2_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#define b3UnsignedInt2 uint2\n"
- "#define b3Int2 int2\n"
- "#define b3MakeInt2 (int2)\n"
- "#endif //__cplusplus\n"
- "#endif\n"
- "typedef struct\n"
- "{\n"
- " float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- "} btGpuFace;\n"
- "#define make_float4 (float4)\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- " \n"
- "// float4 a1 = make_float4(a.xyz,0.f);\n"
- "// float4 b1 = make_float4(b.xyz,0.f);\n"
- "// return cross(a1,b1);\n"
- "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
- " \n"
- " // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
- " \n"
- " //return c;\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " v = make_float4(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "__inline\n"
- "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
- "{\n"
- " return qtRotate( *orientation, *p ) + (*translation);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "}\n"
- "inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
- "const float4* dir, const float4* vertices, float* min, float* max)\n"
- "{\n"
- " min[0] = FLT_MAX;\n"
- " max[0] = -FLT_MAX;\n"
- " int numVerts = hull->m_numVertices;\n"
- " const float4 localDir = qtInvRotate(orn,*dir);\n"
- " float offset = dot(pos,*dir);\n"
- " for(int i=0;i<numVerts;i++)\n"
- " {\n"
- " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
- " if(dp < min[0]) \n"
- " min[0] = dp;\n"
- " if(dp > max[0]) \n"
- " max[0] = dp;\n"
- " }\n"
- " if(min[0]>max[0])\n"
- " {\n"
- " float tmp = min[0];\n"
- " min[0] = max[0];\n"
- " max[0] = tmp;\n"
- " }\n"
- " min[0] += offset;\n"
- " max[0] += offset;\n"
- "}\n"
- "inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
- "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
- "{\n"
- " min[0] = FLT_MAX;\n"
- " max[0] = -FLT_MAX;\n"
- " int numVerts = hull->m_numVertices;\n"
- " const float4 localDir = qtInvRotate(orn,*dir);\n"
- " float offset = dot(pos,*dir);\n"
- " for(int i=0;i<numVerts;i++)\n"
- " {\n"
- " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
- " if(dp < min[0]) \n"
- " min[0] = dp;\n"
- " if(dp > max[0]) \n"
- " max[0] = dp;\n"
- " }\n"
- " if(min[0]>max[0])\n"
- " {\n"
- " float tmp = min[0];\n"
- " min[0] = max[0];\n"
- " max[0] = tmp;\n"
- " }\n"
- " min[0] += offset;\n"
- " max[0] += offset;\n"
- "}\n"
- "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA,const float4 ornA,\n"
- " const float4 posB,const float4 ornB,\n"
- " float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
- "{\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
- " project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " *depth = d0<d1 ? d0:d1;\n"
- " return true;\n"
- "}\n"
- "inline bool IsAlmostZero(const float4 v)\n"
- "{\n"
- " if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " \n"
- " const float4* verticesA, \n"
- " const float4* uniqueEdgesA, \n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB, \n"
- " __global const float4* uniqueEdgesB, \n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " {\n"
- " int numFacesA = hullA->m_numFaces;\n"
- " // Test normals from hullA\n"
- " for(int i=0;i<numFacesA;i++)\n"
- " {\n"
- " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
- " float4 faceANormalWS = qtRotate(ornA,normal);\n"
- " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
- " faceANormalWS*=-1.f;\n"
- " curPlaneTests++;\n"
- " float d;\n"
- " if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
- " return false;\n"
- " if(d<*dmin)\n"
- " {\n"
- " *dmin = d;\n"
- " *sep = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* verticesA, \n"
- " __global const float4* uniqueEdgesA, \n"
- " __global const btGpuFace* facesA,\n"
- " __global const int* indicesA,\n"
- " const float4* verticesB,\n"
- " const float4* uniqueEdgesB, \n"
- " const btGpuFace* facesB,\n"
- " const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " {\n"
- " int numFacesA = hullA->m_numFaces;\n"
- " // Test normals from hullA\n"
- " for(int i=0;i<numFacesA;i++)\n"
- " {\n"
- " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
- " float4 faceANormalWS = qtRotate(ornA,normal);\n"
- " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
- " faceANormalWS *= -1.f;\n"
- " curPlaneTests++;\n"
- " float d;\n"
- " if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
- " return false;\n"
- " if(d<*dmin)\n"
- " {\n"
- " *dmin = d;\n"
- " *sep = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " const float4* verticesA, \n"
- " const float4* uniqueEdgesA, \n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB, \n"
- " __global const float4* uniqueEdgesB, \n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " int curEdgeEdge = 0;\n"
- " // Test edges\n"
- " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
- " {\n"
- " const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
- " float4 edge0World = qtRotate(ornA,edge0);\n"
- " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
- " {\n"
- " const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
- " float4 edge1World = qtRotate(ornB,edge1);\n"
- " float4 crossje = cross3(edge0World,edge1World);\n"
- " curEdgeEdge++;\n"
- " if(!IsAlmostZero(crossje))\n"
- " {\n"
- " crossje = normalize3(crossje);\n"
- " if (dot3F4(DeltaC2,crossje)<0)\n"
- " crossje *= -1.f;\n"
- " float dist;\n"
- " bool result = true;\n"
- " {\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
- " project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
- " \n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " result = false;\n"
- " \n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " dist = d0<d1 ? d0:d1;\n"
- " result = true;\n"
- " }\n"
- " \n"
- " if(dist<*dmin)\n"
- " {\n"
- " *dmin = dist;\n"
- " *sep = crossje;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "inline int findClippingFaces(const float4 separatingNormal,\n"
- " const ConvexPolyhedronCL* hullA, \n"
- " __global const ConvexPolyhedronCL* hullB,\n"
- " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
- " __global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " int capacityWorldVerts,\n"
- " const float minDist, float maxDist,\n"
- " const float4* verticesA,\n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB,\n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " __global int4* clippingFaces, int pairIndex)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " \n"
- " \n"
- " int closestFaceB=0;\n"
- " float dmax = -FLT_MAX;\n"
- " \n"
- " {\n"
- " for(int face=0;face<hullB->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
- " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
- " float d = dot3F4(WorldNormal,separatingNormal);\n"
- " if (d > dmax)\n"
- " {\n"
- " dmax = d;\n"
- " closestFaceB = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " {\n"
- " const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
- " int numVertices = polyB.m_numIndices;\n"
- " if (numVertices>capacityWorldVerts)\n"
- " numVertices = capacityWorldVerts;\n"
- " if (numVertices<0)\n"
- " numVertices = 0;\n"
- " \n"
- " for(int e0=0;e0<numVertices;e0++)\n"
- " {\n"
- " if (e0<capacityWorldVerts)\n"
- " {\n"
- " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
- " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " int closestFaceA=0;\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " for(int face=0;face<hullA->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(\n"
- " facesA[hullA->m_faceOffset+face].m_plane.x,\n"
- " facesA[hullA->m_faceOffset+face].m_plane.y,\n"
- " facesA[hullA->m_faceOffset+face].m_plane.z,\n"
- " 0.f);\n"
- " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
- " \n"
- " float d = dot3F4(faceANormalWS,separatingNormal);\n"
- " if (d < dmin)\n"
- " {\n"
- " dmin = d;\n"
- " closestFaceA = face;\n"
- " worldNormalsA1[pairIndex] = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
- " if (numVerticesA>capacityWorldVerts)\n"
- " numVerticesA = capacityWorldVerts;\n"
- " if (numVerticesA<0)\n"
- " numVerticesA=0;\n"
- " \n"
- " for(int e0=0;e0<numVerticesA;e0++)\n"
- " {\n"
- " if (e0<capacityWorldVerts)\n"
- " {\n"
- " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
- " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
- " }\n"
- " }\n"
- " \n"
- " clippingFaces[pairIndex].x = closestFaceA;\n"
- " clippingFaces[pairIndex].y = closestFaceB;\n"
- " clippingFaces[pairIndex].z = numVerticesA;\n"
- " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
- " \n"
- " \n"
- " return numContactsOut;\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findConcaveSeparatingAxisVertexFaceKernel( __global int4* concavePairs,\n"
- " __global const BodyData* rigidBodies,\n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes,\n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global btAabbCL* aabbs,\n"
- " __global float4* concaveSeparatingNormalsOut,\n"
- " __global int* concaveHasSeparatingNormals,\n"
- " __global int4* clippingFacesOut,\n"
- " __global float4* worldVertsA1GPU,\n"
- " __global float4* worldNormalsAGPU,\n"
- " __global float4* worldVertsB1GPU,\n"
- " __global float* dmins,\n"
- " int vertexFaceCapacity,\n"
- " int numConcavePairs\n"
- " )\n"
- "{\n"
- " \n"
- " int i = get_global_id(0);\n"
- " if (i>=numConcavePairs)\n"
- " return;\n"
- " \n"
- " concaveHasSeparatingNormals[i] = 0;\n"
- " \n"
- " int pairIdx = i;\n"
- " \n"
- " int bodyIndexA = concavePairs[i].x;\n"
- " int bodyIndexB = concavePairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
- " collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " concavePairs[pairIdx].w = -1;\n"
- " return;\n"
- " }\n"
- " \n"
- " \n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " int numActualConcaveConvexTests = 0;\n"
- " \n"
- " int f = concavePairs[i].z;\n"
- " \n"
- " bool overlap = false;\n"
- " \n"
- " ConvexPolyhedronCL convexPolyhedronA;\n"
- " \n"
- " //add 3 vertices of the triangle\n"
- " convexPolyhedronA.m_numVertices = 3;\n"
- " convexPolyhedronA.m_vertexOffset = 0;\n"
- " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
- " \n"
- " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
- " float4 triMinAabb, triMaxAabb;\n"
- " btAabbCL triAabb;\n"
- " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
- " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
- " \n"
- " float4 verticesA[3];\n"
- " for (int i=0;i<3;i++)\n"
- " {\n"
- " int index = indices[face.m_indexOffset+i];\n"
- " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
- " verticesA[i] = vert;\n"
- " localCenter += vert;\n"
- " \n"
- " triAabb.m_min = min(triAabb.m_min,vert);\n"
- " triAabb.m_max = max(triAabb.m_max,vert);\n"
- " \n"
- " }\n"
- " \n"
- " overlap = true;\n"
- " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
- " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
- " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
- " \n"
- " if (overlap)\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " int hasSeparatingAxis=5;\n"
- " float4 sepAxis=make_float4(1,2,3,4);\n"
- " \n"
- " int localCC=0;\n"
- " numActualConcaveConvexTests++;\n"
- " \n"
- " //a triangle has 3 unique edges\n"
- " convexPolyhedronA.m_numUniqueEdges = 3;\n"
- " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
- " float4 uniqueEdgesA[3];\n"
- " \n"
- " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
- " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
- " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
- " \n"
- " \n"
- " convexPolyhedronA.m_faceOffset = 0;\n"
- " \n"
- " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
- " \n"
- " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
- " int indicesA[3+3+2+2+2];\n"
- " int curUsedIndices=0;\n"
- " int fidx=0;\n"
- " \n"
- " //front size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[0] = 0;\n"
- " indicesA[1] = 1;\n"
- " indicesA[2] = 2;\n"
- " curUsedIndices+=3;\n"
- " float c = face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = normal.x;\n"
- " facesA[fidx].m_plane.y = normal.y;\n"
- " facesA[fidx].m_plane.z = normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " //back size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[3]=2;\n"
- " indicesA[4]=1;\n"
- " indicesA[5]=0;\n"
- " curUsedIndices+=3;\n"
- " float c = dot(normal,verticesA[0]);\n"
- " float c1 = -face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = -normal.x;\n"
- " facesA[fidx].m_plane.y = -normal.y;\n"
- " facesA[fidx].m_plane.z = -normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " \n"
- " bool addEdgePlanes = true;\n"
- " if (addEdgePlanes)\n"
- " {\n"
- " int numVertices=3;\n"
- " int prevVertex = numVertices-1;\n"
- " for (int i=0;i<numVertices;i++)\n"
- " {\n"
- " float4 v0 = verticesA[i];\n"
- " float4 v1 = verticesA[prevVertex];\n"
- " \n"
- " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
- " float c = -dot(edgeNormal,v0);\n"
- " \n"
- " facesA[fidx].m_numIndices = 2;\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[curUsedIndices++]=i;\n"
- " indicesA[curUsedIndices++]=prevVertex;\n"
- " \n"
- " facesA[fidx].m_plane.x = edgeNormal.x;\n"
- " facesA[fidx].m_plane.y = edgeNormal.y;\n"
- " facesA[fidx].m_plane.z = edgeNormal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " fidx++;\n"
- " prevVertex = i;\n"
- " }\n"
- " }\n"
- " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
- " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
- " \n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " \n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " ///////////////////\n"
- " ///compound shape support\n"
- " \n"
- " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " int compoundChild = concavePairs[pairIdx].w;\n"
- " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " }\n"
- " //////////////////\n"
- " \n"
- " float4 c0local = convexPolyhedronA.m_localCenter;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " \n"
- " \n"
- " bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " &sepAxis,&dmin);\n"
- " hasSeparatingAxis = 4;\n"
- " if (!sepA)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
- " posB,ornB,\n"
- " posA,ornA,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " &sepAxis,&dmin);\n"
- " \n"
- " if (!sepB)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis = 1;\n"
- " }\n"
- " } \n"
- " \n"
- " if (hasSeparatingAxis)\n"
- " {\n"
- " dmins[i] = dmin;\n"
- " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
- " concaveHasSeparatingNormals[i]=1;\n"
- " \n"
- " } else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- " }\n"
- " else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findConcaveSeparatingAxisEdgeEdgeKernel( __global int4* concavePairs,\n"
- " __global const BodyData* rigidBodies,\n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes,\n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global btAabbCL* aabbs,\n"
- " __global float4* concaveSeparatingNormalsOut,\n"
- " __global int* concaveHasSeparatingNormals,\n"
- " __global int4* clippingFacesOut,\n"
- " __global float4* worldVertsA1GPU,\n"
- " __global float4* worldNormalsAGPU,\n"
- " __global float4* worldVertsB1GPU,\n"
- " __global float* dmins,\n"
- " int vertexFaceCapacity,\n"
- " int numConcavePairs\n"
- " )\n"
- "{\n"
- " \n"
- " int i = get_global_id(0);\n"
- " if (i>=numConcavePairs)\n"
- " return;\n"
- " \n"
- " if (!concaveHasSeparatingNormals[i])\n"
- " return;\n"
- " \n"
- " int pairIdx = i;\n"
- " \n"
- " int bodyIndexA = concavePairs[i].x;\n"
- " int bodyIndexB = concavePairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " int numActualConcaveConvexTests = 0;\n"
- " \n"
- " int f = concavePairs[i].z;\n"
- " \n"
- " bool overlap = false;\n"
- " \n"
- " ConvexPolyhedronCL convexPolyhedronA;\n"
- " \n"
- " //add 3 vertices of the triangle\n"
- " convexPolyhedronA.m_numVertices = 3;\n"
- " convexPolyhedronA.m_vertexOffset = 0;\n"
- " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
- " \n"
- " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
- " float4 triMinAabb, triMaxAabb;\n"
- " btAabbCL triAabb;\n"
- " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
- " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
- " \n"
- " float4 verticesA[3];\n"
- " for (int i=0;i<3;i++)\n"
- " {\n"
- " int index = indices[face.m_indexOffset+i];\n"
- " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
- " verticesA[i] = vert;\n"
- " localCenter += vert;\n"
- " \n"
- " triAabb.m_min = min(triAabb.m_min,vert);\n"
- " triAabb.m_max = max(triAabb.m_max,vert);\n"
- " \n"
- " }\n"
- " \n"
- " overlap = true;\n"
- " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
- " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
- " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
- " \n"
- " if (overlap)\n"
- " {\n"
- " float dmin = dmins[i];\n"
- " int hasSeparatingAxis=5;\n"
- " float4 sepAxis=make_float4(1,2,3,4);\n"
- " sepAxis = concaveSeparatingNormalsOut[pairIdx];\n"
- " \n"
- " int localCC=0;\n"
- " numActualConcaveConvexTests++;\n"
- " \n"
- " //a triangle has 3 unique edges\n"
- " convexPolyhedronA.m_numUniqueEdges = 3;\n"
- " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
- " float4 uniqueEdgesA[3];\n"
- " \n"
- " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
- " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
- " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
- " \n"
- " \n"
- " convexPolyhedronA.m_faceOffset = 0;\n"
- " \n"
- " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
- " \n"
- " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
- " int indicesA[3+3+2+2+2];\n"
- " int curUsedIndices=0;\n"
- " int fidx=0;\n"
- " \n"
- " //front size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[0] = 0;\n"
- " indicesA[1] = 1;\n"
- " indicesA[2] = 2;\n"
- " curUsedIndices+=3;\n"
- " float c = face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = normal.x;\n"
- " facesA[fidx].m_plane.y = normal.y;\n"
- " facesA[fidx].m_plane.z = normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " //back size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[3]=2;\n"
- " indicesA[4]=1;\n"
- " indicesA[5]=0;\n"
- " curUsedIndices+=3;\n"
- " float c = dot(normal,verticesA[0]);\n"
- " float c1 = -face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = -normal.x;\n"
- " facesA[fidx].m_plane.y = -normal.y;\n"
- " facesA[fidx].m_plane.z = -normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " \n"
- " bool addEdgePlanes = true;\n"
- " if (addEdgePlanes)\n"
- " {\n"
- " int numVertices=3;\n"
- " int prevVertex = numVertices-1;\n"
- " for (int i=0;i<numVertices;i++)\n"
- " {\n"
- " float4 v0 = verticesA[i];\n"
- " float4 v1 = verticesA[prevVertex];\n"
- " \n"
- " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
- " float c = -dot(edgeNormal,v0);\n"
- " \n"
- " facesA[fidx].m_numIndices = 2;\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[curUsedIndices++]=i;\n"
- " indicesA[curUsedIndices++]=prevVertex;\n"
- " \n"
- " facesA[fidx].m_plane.x = edgeNormal.x;\n"
- " facesA[fidx].m_plane.y = edgeNormal.y;\n"
- " facesA[fidx].m_plane.z = edgeNormal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " fidx++;\n"
- " prevVertex = i;\n"
- " }\n"
- " }\n"
- " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
- " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
- " \n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " \n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " ///////////////////\n"
- " ///compound shape support\n"
- " \n"
- " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " int compoundChild = concavePairs[pairIdx].w;\n"
- " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " }\n"
- " //////////////////\n"
- " \n"
- " float4 c0local = convexPolyhedronA.m_localCenter;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " \n"
- " \n"
- " {\n"
- " bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " &sepAxis,&dmin);\n"
- " \n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis = 1;\n"
- " }\n"
- " }\n"
- " \n"
- " \n"
- " if (hasSeparatingAxis)\n"
- " {\n"
- " sepAxis.w = dmin;\n"
- " dmins[i] = dmin;\n"
- " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
- " concaveHasSeparatingNormals[i]=1;\n"
- " \n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " \n"
- " findClippingFaces(sepAxis,\n"
- " &convexPolyhedronA,\n"
- " &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " worldVertsA1GPU,\n"
- " worldNormalsAGPU,\n"
- " worldVertsB1GPU,\n"
- " vertexFaceCapacity,\n"
- " minDist, maxDist,\n"
- " verticesA,\n"
- " facesA,\n"
- " indicesA,\n"
- " vertices,\n"
- " faces,\n"
- " indices,\n"
- " clippingFacesOut, pairIdx);\n"
- " \n"
- " \n"
- " } else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- " }\n"
- " else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- " \n"
- " concavePairs[i].z = -1;//for the next stage, z is used to determine existing contact points\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h b/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
deleted file mode 100644
index e627af2799..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/NarrowphaseCollision/kernels/satKernels.h
+++ /dev/null
@@ -1,2103 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* satKernelsCL =
- "//keep this enum in sync with the CPU version (in btCollidable.h)\n"
- "//written by Erwin Coumans\n"
- "#define SHAPE_CONVEX_HULL 3\n"
- "#define SHAPE_CONCAVE_TRIMESH 5\n"
- "#define TRIANGLE_NUM_CONVEX_FACES 5\n"
- "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
- "#define B3_MAX_STACK_DEPTH 256\n"
- "typedef unsigned int u32;\n"
- "///keep this in sync with btCollidable.h\n"
- "typedef struct\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_radius;\n"
- " int m_compoundBvhIndex;\n"
- " };\n"
- " \n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- " \n"
- "} btCollidableGpu;\n"
- "#define MAX_NUM_PARTS_IN_BITS 10\n"
- "///b3QuantizedBvhNode is a compressed aabb node, 16 bytes.\n"
- "///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes\n"
- " int m_escapeIndexOrTriangleIndex;\n"
- "} b3QuantizedBvhNode;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_aabbMin;\n"
- " float4 m_aabbMax;\n"
- " float4 m_quantization;\n"
- " int m_numNodes;\n"
- " int m_numSubTrees;\n"
- " int m_nodeOffset;\n"
- " int m_subTreeOffset;\n"
- "} b3BvhInfo;\n"
- "int getTriangleIndex(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " unsigned int x=0;\n"
- " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
- " // Get only the lower bits where the triangle index is stored\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
- "}\n"
- "int getTriangleIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " unsigned int x=0;\n"
- " unsigned int y = (~(x&0))<<(31-MAX_NUM_PARTS_IN_BITS);\n"
- " // Get only the lower bits where the triangle index is stored\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex&~(y));\n"
- "}\n"
- "int isLeafNode(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
- "}\n"
- "int isLeafNodeGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " //skipindex is negative (internal node), triangleindex >=0 (leafnode)\n"
- " return (rootNode->m_escapeIndexOrTriangleIndex >= 0)? 1 : 0;\n"
- "}\n"
- " \n"
- "int getEscapeIndex(const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
- "}\n"
- "int getEscapeIndexGlobal(__global const b3QuantizedBvhNode* rootNode)\n"
- "{\n"
- " return -rootNode->m_escapeIndexOrTriangleIndex;\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " //12 bytes\n"
- " unsigned short int m_quantizedAabbMin[3];\n"
- " unsigned short int m_quantizedAabbMax[3];\n"
- " //4 bytes, points to the root of the subtree\n"
- " int m_rootNodeIndex;\n"
- " //4 bytes\n"
- " int m_subtreeSize;\n"
- " int m_padding[3];\n"
- "} b3BvhSubtreeInfo;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_childPosition;\n"
- " float4 m_childOrientation;\n"
- " int m_shapeIndex;\n"
- " int m_unused0;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "} btGpuChildShape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " float4 m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} BodyData;\n"
- "typedef struct \n"
- "{\n"
- " float4 m_localCenter;\n"
- " float4 m_extents;\n"
- " float4 mC;\n"
- " float4 mE;\n"
- " \n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "} ConvexPolyhedronCL;\n"
- "typedef struct \n"
- "{\n"
- " union\n"
- " {\n"
- " float4 m_min;\n"
- " float m_minElems[4];\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float4 m_max;\n"
- " float m_maxElems[4];\n"
- " int m_maxIndices[4];\n"
- " };\n"
- "} btAabbCL;\n"
- "#ifndef B3_AABB_H\n"
- "#define B3_AABB_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3Aabb b3Aabb_t;\n"
- "struct b3Aabb\n"
- "{\n"
- " union\n"
- " {\n"
- " float m_min[4];\n"
- " b3Float4 m_minVec;\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_max[4];\n"
- " b3Float4 m_maxVec;\n"
- " int m_signedMaxIndices[4];\n"
- " };\n"
- "};\n"
- "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
- " b3Float4ConstArg pos,\n"
- " b3QuatConstArg orn,\n"
- " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
- "{\n"
- " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
- " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
- " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
- " b3Mat3x3 m;\n"
- " m = b3QuatGetRotationMatrix(orn);\n"
- " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
- " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
- " \n"
- " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
- " 0.f);\n"
- " *aabbMinOut = center-extent;\n"
- " *aabbMaxOut = center+extent;\n"
- "}\n"
- "/// conservative test for overlap between two aabbs\n"
- "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
- " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
- " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
- " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "#endif //B3_AABB_H\n"
- "/*\n"
- "Bullet Continuous Collision Detection and Physics Library\n"
- "Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose,\n"
- "including commercial applications, and to alter it and redistribute it freely,\n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "#ifndef B3_INT2_H\n"
- "#define B3_INT2_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#define b3UnsignedInt2 uint2\n"
- "#define b3Int2 int2\n"
- "#define b3MakeInt2 (int2)\n"
- "#endif //__cplusplus\n"
- "#endif\n"
- "typedef struct\n"
- "{\n"
- " float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- "} btGpuFace;\n"
- "#define make_float4 (float4)\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- " \n"
- "// float4 a1 = make_float4(a.xyz,0.f);\n"
- "// float4 b1 = make_float4(b.xyz,0.f);\n"
- "// return cross(a1,b1);\n"
- "//float4 c = make_float4(a.y*b.z - a.z*b.y,a.z*b.x - a.x*b.z,a.x*b.y - a.y*b.x,0.f);\n"
- " \n"
- " // float4 c = make_float4(a.y*b.z - a.z*b.y,1.f,a.x*b.y - a.y*b.x,0.f);\n"
- " \n"
- " //return c;\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " v = make_float4(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "__inline\n"
- "float4 transform(const float4* p, const float4* translation, const Quaternion* orientation)\n"
- "{\n"
- " return qtRotate( *orientation, *p ) + (*translation);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "}\n"
- "inline void projectLocal(const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
- "const float4* dir, const float4* vertices, float* min, float* max)\n"
- "{\n"
- " min[0] = FLT_MAX;\n"
- " max[0] = -FLT_MAX;\n"
- " int numVerts = hull->m_numVertices;\n"
- " const float4 localDir = qtInvRotate(orn,*dir);\n"
- " float offset = dot(pos,*dir);\n"
- " for(int i=0;i<numVerts;i++)\n"
- " {\n"
- " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
- " if(dp < min[0]) \n"
- " min[0] = dp;\n"
- " if(dp > max[0]) \n"
- " max[0] = dp;\n"
- " }\n"
- " if(min[0]>max[0])\n"
- " {\n"
- " float tmp = min[0];\n"
- " min[0] = max[0];\n"
- " max[0] = tmp;\n"
- " }\n"
- " min[0] += offset;\n"
- " max[0] += offset;\n"
- "}\n"
- "inline void project(__global const ConvexPolyhedronCL* hull, const float4 pos, const float4 orn, \n"
- "const float4* dir, __global const float4* vertices, float* min, float* max)\n"
- "{\n"
- " min[0] = FLT_MAX;\n"
- " max[0] = -FLT_MAX;\n"
- " int numVerts = hull->m_numVertices;\n"
- " const float4 localDir = qtInvRotate(orn,*dir);\n"
- " float offset = dot(pos,*dir);\n"
- " for(int i=0;i<numVerts;i++)\n"
- " {\n"
- " float dp = dot(vertices[hull->m_vertexOffset+i],localDir);\n"
- " if(dp < min[0]) \n"
- " min[0] = dp;\n"
- " if(dp > max[0]) \n"
- " max[0] = dp;\n"
- " }\n"
- " if(min[0]>max[0])\n"
- " {\n"
- " float tmp = min[0];\n"
- " min[0] = max[0];\n"
- " max[0] = tmp;\n"
- " }\n"
- " min[0] += offset;\n"
- " max[0] += offset;\n"
- "}\n"
- "inline bool TestSepAxisLocalA(const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA,const float4 ornA,\n"
- " const float4 posB,const float4 ornB,\n"
- " float4* sep_axis, const float4* verticesA, __global const float4* verticesB,float* depth)\n"
- "{\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " projectLocal(hullA,posA,ornA,sep_axis,verticesA, &Min0, &Max0);\n"
- " project(hullB,posB,ornB, sep_axis,verticesB, &Min1, &Max1);\n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " *depth = d0<d1 ? d0:d1;\n"
- " return true;\n"
- "}\n"
- "inline bool IsAlmostZero(const float4 v)\n"
- "{\n"
- " if(fabs(v.x)>1e-6f || fabs(v.y)>1e-6f || fabs(v.z)>1e-6f)\n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " \n"
- " const float4* verticesA, \n"
- " const float4* uniqueEdgesA, \n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB, \n"
- " __global const float4* uniqueEdgesB, \n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " {\n"
- " int numFacesA = hullA->m_numFaces;\n"
- " // Test normals from hullA\n"
- " for(int i=0;i<numFacesA;i++)\n"
- " {\n"
- " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
- " float4 faceANormalWS = qtRotate(ornA,normal);\n"
- " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
- " faceANormalWS*=-1.f;\n"
- " curPlaneTests++;\n"
- " float d;\n"
- " if(!TestSepAxisLocalA( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, verticesA, verticesB,&d))\n"
- " return false;\n"
- " if(d<*dmin)\n"
- " {\n"
- " *dmin = d;\n"
- " *sep = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisLocalB( __global const ConvexPolyhedronCL* hullA, const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* verticesA, \n"
- " __global const float4* uniqueEdgesA, \n"
- " __global const btGpuFace* facesA,\n"
- " __global const int* indicesA,\n"
- " const float4* verticesB,\n"
- " const float4* uniqueEdgesB, \n"
- " const btGpuFace* facesB,\n"
- " const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " {\n"
- " int numFacesA = hullA->m_numFaces;\n"
- " // Test normals from hullA\n"
- " for(int i=0;i<numFacesA;i++)\n"
- " {\n"
- " const float4 normal = facesA[hullA->m_faceOffset+i].m_plane;\n"
- " float4 faceANormalWS = qtRotate(ornA,normal);\n"
- " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
- " faceANormalWS *= -1.f;\n"
- " curPlaneTests++;\n"
- " float d;\n"
- " if(!TestSepAxisLocalA( hullB, hullA, posB,ornB,posA,ornA, &faceANormalWS, verticesB,verticesA, &d))\n"
- " return false;\n"
- " if(d<*dmin)\n"
- " {\n"
- " *dmin = d;\n"
- " *sep = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisEdgeEdgeLocalA( const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " const float4* verticesA, \n"
- " const float4* uniqueEdgesA, \n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB, \n"
- " __global const float4* uniqueEdgesB, \n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " int curEdgeEdge = 0;\n"
- " // Test edges\n"
- " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
- " {\n"
- " const float4 edge0 = uniqueEdgesA[hullA->m_uniqueEdgesOffset+e0];\n"
- " float4 edge0World = qtRotate(ornA,edge0);\n"
- " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
- " {\n"
- " const float4 edge1 = uniqueEdgesB[hullB->m_uniqueEdgesOffset+e1];\n"
- " float4 edge1World = qtRotate(ornB,edge1);\n"
- " float4 crossje = cross3(edge0World,edge1World);\n"
- " curEdgeEdge++;\n"
- " if(!IsAlmostZero(crossje))\n"
- " {\n"
- " crossje = normalize3(crossje);\n"
- " if (dot3F4(DeltaC2,crossje)<0)\n"
- " crossje *= -1.f;\n"
- " float dist;\n"
- " bool result = true;\n"
- " {\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " projectLocal(hullA,posA,ornA,&crossje,verticesA, &Min0, &Max0);\n"
- " project(hullB,posB,ornB,&crossje,verticesB, &Min1, &Max1);\n"
- " \n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " result = false;\n"
- " \n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " dist = d0<d1 ? d0:d1;\n"
- " result = true;\n"
- " }\n"
- " \n"
- " if(dist<*dmin)\n"
- " {\n"
- " *dmin = dist;\n"
- " *sep = crossje;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "inline bool TestSepAxis(__global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA,const float4 ornA,\n"
- " const float4 posB,const float4 ornB,\n"
- " float4* sep_axis, __global const float4* vertices,float* depth)\n"
- "{\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " project(hullA,posA,ornA,sep_axis,vertices, &Min0, &Max0);\n"
- " project(hullB,posB,ornB, sep_axis,vertices, &Min1, &Max1);\n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " *depth = d0<d1 ? d0:d1;\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxis( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* vertices, \n"
- " __global const float4* uniqueEdges, \n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " \n"
- " int curPlaneTests=0;\n"
- " {\n"
- " int numFacesA = hullA->m_numFaces;\n"
- " // Test normals from hullA\n"
- " for(int i=0;i<numFacesA;i++)\n"
- " {\n"
- " const float4 normal = faces[hullA->m_faceOffset+i].m_plane;\n"
- " float4 faceANormalWS = qtRotate(ornA,normal);\n"
- " \n"
- " if (dot3F4(DeltaC2,faceANormalWS)<0)\n"
- " faceANormalWS*=-1.f;\n"
- " \n"
- " curPlaneTests++;\n"
- " \n"
- " float d;\n"
- " if(!TestSepAxis( hullA, hullB, posA,ornA,posB,ornB,&faceANormalWS, vertices,&d))\n"
- " return false;\n"
- " \n"
- " if(d<*dmin)\n"
- " {\n"
- " *dmin = d;\n"
- " *sep = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " \n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisUnitSphere( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* vertices,\n"
- " __global const float4* unitSphereDirections,\n"
- " int numUnitSphereDirections,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " int curEdgeEdge = 0;\n"
- " // Test unit sphere directions\n"
- " for (int i=0;i<numUnitSphereDirections;i++)\n"
- " {\n"
- " float4 crossje;\n"
- " crossje = unitSphereDirections[i]; \n"
- " if (dot3F4(DeltaC2,crossje)>0)\n"
- " crossje *= -1.f;\n"
- " {\n"
- " float dist;\n"
- " bool result = true;\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
- " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
- " \n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " \n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " dist = d0<d1 ? d0:d1;\n"
- " result = true;\n"
- " \n"
- " if(dist<*dmin)\n"
- " {\n"
- " *dmin = dist;\n"
- " *sep = crossje;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "bool findSeparatingAxisEdgeEdge( __global const ConvexPolyhedronCL* hullA, __global const ConvexPolyhedronCL* hullB, \n"
- " const float4 posA1,\n"
- " const float4 ornA,\n"
- " const float4 posB1,\n"
- " const float4 ornB,\n"
- " const float4 DeltaC2,\n"
- " __global const float4* vertices, \n"
- " __global const float4* uniqueEdges, \n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " float4* sep,\n"
- " float* dmin)\n"
- "{\n"
- " \n"
- " float4 posA = posA1;\n"
- " posA.w = 0.f;\n"
- " float4 posB = posB1;\n"
- " posB.w = 0.f;\n"
- " int curPlaneTests=0;\n"
- " int curEdgeEdge = 0;\n"
- " // Test edges\n"
- " for(int e0=0;e0<hullA->m_numUniqueEdges;e0++)\n"
- " {\n"
- " const float4 edge0 = uniqueEdges[hullA->m_uniqueEdgesOffset+e0];\n"
- " float4 edge0World = qtRotate(ornA,edge0);\n"
- " for(int e1=0;e1<hullB->m_numUniqueEdges;e1++)\n"
- " {\n"
- " const float4 edge1 = uniqueEdges[hullB->m_uniqueEdgesOffset+e1];\n"
- " float4 edge1World = qtRotate(ornB,edge1);\n"
- " float4 crossje = cross3(edge0World,edge1World);\n"
- " curEdgeEdge++;\n"
- " if(!IsAlmostZero(crossje))\n"
- " {\n"
- " crossje = normalize3(crossje);\n"
- " if (dot3F4(DeltaC2,crossje)<0)\n"
- " crossje*=-1.f;\n"
- " \n"
- " float dist;\n"
- " bool result = true;\n"
- " {\n"
- " float Min0,Max0;\n"
- " float Min1,Max1;\n"
- " project(hullA,posA,ornA,&crossje,vertices, &Min0, &Max0);\n"
- " project(hullB,posB,ornB,&crossje,vertices, &Min1, &Max1);\n"
- " \n"
- " if(Max0<Min1 || Max1<Min0)\n"
- " return false;\n"
- " \n"
- " float d0 = Max0 - Min1;\n"
- " float d1 = Max1 - Min0;\n"
- " dist = d0<d1 ? d0:d1;\n"
- " result = true;\n"
- " }\n"
- " \n"
- " if(dist<*dmin)\n"
- " {\n"
- " *dmin = dist;\n"
- " *sep = crossje;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if((dot3F4(-DeltaC2,*sep))>0.0f)\n"
- " {\n"
- " *sep = -(*sep);\n"
- " }\n"
- " return true;\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void processCompoundPairsKernel( __global const int4* gpuCompoundPairs,\n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global volatile float4* gpuCompoundSepNormalsOut,\n"
- " __global volatile int* gpuHasCompoundSepNormalsOut,\n"
- " int numCompoundPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i<numCompoundPairs)\n"
- " {\n"
- " int bodyIndexA = gpuCompoundPairs[i].x;\n"
- " int bodyIndexB = gpuCompoundPairs[i].y;\n"
- " int childShapeIndexA = gpuCompoundPairs[i].z;\n"
- " int childShapeIndexB = gpuCompoundPairs[i].w;\n"
- " \n"
- " int collidableIndexA = -1;\n"
- " int collidableIndexB = -1;\n"
- " \n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " \n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " \n"
- " if (childShapeIndexA >= 0)\n"
- " {\n"
- " collidableIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
- " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
- " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
- " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
- " float4 newOrnA = qtMul(ornA,childOrnA);\n"
- " posA = newPosA;\n"
- " ornA = newOrnA;\n"
- " } else\n"
- " {\n"
- " collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " }\n"
- " \n"
- " if (childShapeIndexB>=0)\n"
- " {\n"
- " collidableIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " } else\n"
- " {\n"
- " collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx; \n"
- " }\n"
- " \n"
- " gpuHasCompoundSepNormalsOut[i] = 0;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " int shapeTypeA = collidables[collidableIndexA].m_shapeType;\n"
- " int shapeTypeB = collidables[collidableIndexB].m_shapeType;\n"
- " \n"
- " if ((shapeTypeA != SHAPE_CONVEX_HULL) || (shapeTypeB != SHAPE_CONVEX_HULL))\n"
- " {\n"
- " return;\n"
- " }\n"
- " int hasSeparatingAxis = 5;\n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " posA.w = 0.f;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " float4 sepNormal = make_float4(1,0,0,0);\n"
- " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
- " hasSeparatingAxis = 4;\n"
- " if (!sepA)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,posA,ornA,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
- " if (!sepB)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else//(!sepB)\n"
- " {\n"
- " bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,posB,ornB,DeltaC2,vertices,uniqueEdges,faces,indices,&sepNormal,&dmin);\n"
- " if (sepEE)\n"
- " {\n"
- " gpuCompoundSepNormalsOut[i] = sepNormal;//fastNormalize4(sepNormal);\n"
- " gpuHasCompoundSepNormalsOut[i] = 1;\n"
- " }//sepEE\n"
- " }//(!sepB)\n"
- " }//(!sepA)\n"
- " \n"
- " \n"
- " }\n"
- " \n"
- "}\n"
- "inline b3Float4 MyUnQuantize(const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
- "{\n"
- " b3Float4 vecOut;\n"
- " vecOut = b3MakeFloat4(\n"
- " (float)(vecIn[0]) / (quantization.x),\n"
- " (float)(vecIn[1]) / (quantization.y),\n"
- " (float)(vecIn[2]) / (quantization.z),\n"
- " 0.f);\n"
- " vecOut += bvhAabbMin;\n"
- " return vecOut;\n"
- "}\n"
- "inline b3Float4 MyUnQuantizeGlobal(__global const unsigned short* vecIn, b3Float4 quantization, b3Float4 bvhAabbMin)\n"
- "{\n"
- " b3Float4 vecOut;\n"
- " vecOut = b3MakeFloat4(\n"
- " (float)(vecIn[0]) / (quantization.x),\n"
- " (float)(vecIn[1]) / (quantization.y),\n"
- " (float)(vecIn[2]) / (quantization.z),\n"
- " 0.f);\n"
- " vecOut += bvhAabbMin;\n"
- " return vecOut;\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findCompoundPairsKernel( __global const int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global b3Aabb_t* aabbLocalSpace,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global volatile int4* gpuCompoundPairsOut,\n"
- " __global volatile int* numCompoundPairsOut,\n"
- " __global const b3BvhSubtreeInfo* subtrees,\n"
- " __global const b3QuantizedBvhNode* quantizedNodes,\n"
- " __global const b3BvhInfo* bvhInfos,\n"
- " int numPairs,\n"
- " int maxNumCompoundPairsCapacity\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i<numPairs)\n"
- " {\n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " //once the broadphase avoids static-static pairs, we can remove this test\n"
- " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
- " {\n"
- " return;\n"
- " }\n"
- " if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) &&(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
- " {\n"
- " int bvhA = collidables[collidableIndexA].m_compoundBvhIndex;\n"
- " int bvhB = collidables[collidableIndexB].m_compoundBvhIndex;\n"
- " int numSubTreesA = bvhInfos[bvhA].m_numSubTrees;\n"
- " int subTreesOffsetA = bvhInfos[bvhA].m_subTreeOffset;\n"
- " int subTreesOffsetB = bvhInfos[bvhB].m_subTreeOffset;\n"
- " int numSubTreesB = bvhInfos[bvhB].m_numSubTrees;\n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " b3Quat ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " b3Quat ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " \n"
- " for (int p=0;p<numSubTreesA;p++)\n"
- " {\n"
- " b3BvhSubtreeInfo subtreeA = subtrees[subTreesOffsetA+p];\n"
- " //bvhInfos[bvhA].m_quantization\n"
- " b3Float4 treeAminLocal = MyUnQuantize(subtreeA.m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
- " b3Float4 treeAmaxLocal = MyUnQuantize(subtreeA.m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
- " b3Float4 aabbAMinOut,aabbAMaxOut;\n"
- " float margin=0.f;\n"
- " b3TransformAabb2(treeAminLocal,treeAmaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
- " \n"
- " for (int q=0;q<numSubTreesB;q++)\n"
- " {\n"
- " b3BvhSubtreeInfo subtreeB = subtrees[subTreesOffsetB+q];\n"
- " b3Float4 treeBminLocal = MyUnQuantize(subtreeB.m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
- " b3Float4 treeBmaxLocal = MyUnQuantize(subtreeB.m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
- " b3Float4 aabbBMinOut,aabbBMaxOut;\n"
- " float margin=0.f;\n"
- " b3TransformAabb2(treeBminLocal,treeBmaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
- " \n"
- " \n"
- " bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
- " if (aabbOverlap)\n"
- " {\n"
- " \n"
- " int startNodeIndexA = subtreeA.m_rootNodeIndex+bvhInfos[bvhA].m_nodeOffset;\n"
- " int endNodeIndexA = startNodeIndexA+subtreeA.m_subtreeSize;\n"
- " int startNodeIndexB = subtreeB.m_rootNodeIndex+bvhInfos[bvhB].m_nodeOffset;\n"
- " int endNodeIndexB = startNodeIndexB+subtreeB.m_subtreeSize;\n"
- " b3Int2 nodeStack[B3_MAX_STACK_DEPTH];\n"
- " b3Int2 node0;\n"
- " node0.x = startNodeIndexA;\n"
- " node0.y = startNodeIndexB;\n"
- " int maxStackDepth = B3_MAX_STACK_DEPTH;\n"
- " int depth=0;\n"
- " nodeStack[depth++]=node0;\n"
- " do\n"
- " {\n"
- " b3Int2 node = nodeStack[--depth];\n"
- " b3Float4 aMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMin,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
- " b3Float4 aMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.x].m_quantizedAabbMax,bvhInfos[bvhA].m_quantization,bvhInfos[bvhA].m_aabbMin);\n"
- " b3Float4 bMinLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMin,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
- " b3Float4 bMaxLocal = MyUnQuantizeGlobal(quantizedNodes[node.y].m_quantizedAabbMax,bvhInfos[bvhB].m_quantization,bvhInfos[bvhB].m_aabbMin);\n"
- " float margin=0.f;\n"
- " b3Float4 aabbAMinOut,aabbAMaxOut;\n"
- " b3TransformAabb2(aMinLocal,aMaxLocal, margin,posA,ornA,&aabbAMinOut,&aabbAMaxOut);\n"
- " b3Float4 aabbBMinOut,aabbBMaxOut;\n"
- " b3TransformAabb2(bMinLocal,bMaxLocal, margin,posB,ornB,&aabbBMinOut,&aabbBMaxOut);\n"
- " \n"
- " bool nodeOverlap = b3TestAabbAgainstAabb(aabbAMinOut,aabbAMaxOut,aabbBMinOut,aabbBMaxOut);\n"
- " if (nodeOverlap)\n"
- " {\n"
- " bool isLeafA = isLeafNodeGlobal(&quantizedNodes[node.x]);\n"
- " bool isLeafB = isLeafNodeGlobal(&quantizedNodes[node.y]);\n"
- " bool isInternalA = !isLeafA;\n"
- " bool isInternalB = !isLeafB;\n"
- " //fail, even though it might hit two leaf nodes\n"
- " if (depth+4>maxStackDepth && !(isLeafA && isLeafB))\n"
- " {\n"
- " //printf(\"Error: traversal exceeded maxStackDepth\");\n"
- " continue;\n"
- " }\n"
- " if(isInternalA)\n"
- " {\n"
- " int nodeAleftChild = node.x+1;\n"
- " bool isNodeALeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.x+1]);\n"
- " int nodeArightChild = isNodeALeftChildLeaf? node.x+2 : node.x+1 + getEscapeIndexGlobal(&quantizedNodes[node.x+1]);\n"
- " if(isInternalB)\n"
- " { \n"
- " int nodeBleftChild = node.y+1;\n"
- " bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
- " int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
- " nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBleftChild);\n"
- " nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBleftChild);\n"
- " nodeStack[depth++] = b3MakeInt2(nodeAleftChild, nodeBrightChild);\n"
- " nodeStack[depth++] = b3MakeInt2(nodeArightChild, nodeBrightChild);\n"
- " }\n"
- " else\n"
- " {\n"
- " nodeStack[depth++] = b3MakeInt2(nodeAleftChild,node.y);\n"
- " nodeStack[depth++] = b3MakeInt2(nodeArightChild,node.y);\n"
- " }\n"
- " }\n"
- " else\n"
- " {\n"
- " if(isInternalB)\n"
- " {\n"
- " int nodeBleftChild = node.y+1;\n"
- " bool isNodeBLeftChildLeaf = isLeafNodeGlobal(&quantizedNodes[node.y+1]);\n"
- " int nodeBrightChild = isNodeBLeftChildLeaf? node.y+2 : node.y+1 + getEscapeIndexGlobal(&quantizedNodes[node.y+1]);\n"
- " nodeStack[depth++] = b3MakeInt2(node.x,nodeBleftChild);\n"
- " nodeStack[depth++] = b3MakeInt2(node.x,nodeBrightChild);\n"
- " }\n"
- " else\n"
- " {\n"
- " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
- " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " {\n"
- " int childShapeIndexA = getTriangleIndexGlobal(&quantizedNodes[node.x]);\n"
- " int childShapeIndexB = getTriangleIndexGlobal(&quantizedNodes[node.y]);\n"
- " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " } while (depth);\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " return;\n"
- " }\n"
- " if ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
- " {\n"
- " if (collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) \n"
- " {\n"
- " int numChildrenA = collidables[collidableIndexA].m_numChildShapes;\n"
- " for (int c=0;c<numChildrenA;c++)\n"
- " {\n"
- " int childShapeIndexA = collidables[collidableIndexA].m_shapeIndex+c;\n"
- " int childColIndexA = gpuChildShapes[childShapeIndexA].m_shapeIndex;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 childPosA = gpuChildShapes[childShapeIndexA].m_childPosition;\n"
- " float4 childOrnA = gpuChildShapes[childShapeIndexA].m_childOrientation;\n"
- " float4 newPosA = qtRotate(ornA,childPosA)+posA;\n"
- " float4 newOrnA = qtMul(ornA,childOrnA);\n"
- " int shapeIndexA = collidables[childColIndexA].m_shapeIndex;\n"
- " b3Aabb_t aabbAlocal = aabbLocalSpace[shapeIndexA];\n"
- " float margin = 0.f;\n"
- " \n"
- " b3Float4 aabbAMinWS;\n"
- " b3Float4 aabbAMaxWS;\n"
- " \n"
- " b3TransformAabb2(aabbAlocal.m_minVec,aabbAlocal.m_maxVec,margin,\n"
- " newPosA,\n"
- " newOrnA,\n"
- " &aabbAMinWS,&aabbAMaxWS);\n"
- " \n"
- " \n"
- " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
- " for (int b=0;b<numChildrenB;b++)\n"
- " {\n"
- " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " b3Aabb_t aabbBlocal = aabbLocalSpace[shapeIndexB];\n"
- " \n"
- " b3Float4 aabbBMinWS;\n"
- " b3Float4 aabbBMaxWS;\n"
- " \n"
- " b3TransformAabb2(aabbBlocal.m_minVec,aabbBlocal.m_maxVec,margin,\n"
- " newPosB,\n"
- " newOrnB,\n"
- " &aabbBMinWS,&aabbBMaxWS);\n"
- " \n"
- " \n"
- " \n"
- " bool aabbOverlap = b3TestAabbAgainstAabb(aabbAMinWS,aabbAMaxWS,aabbBMinWS,aabbBMaxWS);\n"
- " if (aabbOverlap)\n"
- " {\n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " float4 posA = newPosA;\n"
- " posA.w = 0.f;\n"
- " float4 posB = newPosB;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = newOrnA;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =newOrnB;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " {//\n"
- " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
- " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " {\n"
- " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,childShapeIndexB);\n"
- " }\n"
- " }//\n"
- " }//fi(1)\n"
- " } //for (int b=0\n"
- " }//if (collidables[collidableIndexB].\n"
- " else//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " if (1)\n"
- " {\n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " float4 posA = newPosA;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = newOrnA;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " {\n"
- " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
- " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " {\n"
- " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,childShapeIndexA,-1);\n"
- " }//if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " }//\n"
- " }//fi (1)\n"
- " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " }//for (int b=0;b<numChildrenB;b++) \n"
- " return;\n"
- " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONCAVE_TRIMESH) \n"
- " && (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
- " {\n"
- " int numChildrenB = collidables[collidableIndexB].m_numChildShapes;\n"
- " for (int b=0;b<numChildrenB;b++)\n"
- " {\n"
- " int childShapeIndexB = collidables[collidableIndexB].m_shapeIndex+b;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 ornB = rigidBodies[bodyIndexB].m_quat;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = qtRotate(ornB,childPosB)+posB;\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " int shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " //////////////////////////////////////\n"
- " if (1)\n"
- " {\n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = newPosB;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =newOrnB;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " {//\n"
- " int compoundPairIdx = atomic_inc(numCompoundPairsOut);\n"
- " if (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " {\n"
- " gpuCompoundPairsOut[compoundPairIdx] = (int4)(bodyIndexA,bodyIndexB,-1,childShapeIndexB);\n"
- " }//fi (compoundPairIdx<maxNumCompoundPairsCapacity)\n"
- " }//\n"
- " }//fi (1) \n"
- " }//for (int b=0;b<numChildrenB;b++)\n"
- " return;\n"
- " }//if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " return;\n"
- " }//fi ((collidables[collidableIndexA].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS) ||(collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS))\n"
- " }//i<numPairs\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findSeparatingAxisKernel( __global const int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global volatile float4* separatingNormals,\n"
- " __global volatile int* hasSeparatingAxis,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " \n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " //once the broadphase avoids static-static pairs, we can remove this test\n"
- " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " return;\n"
- " }\n"
- " \n"
- " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " return;\n"
- " }\n"
- " \n"
- " if ((collidables[collidableIndexA].m_shapeType==SHAPE_CONCAVE_TRIMESH))\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " return;\n"
- " }\n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " float4 sepNormal;\n"
- " \n"
- " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " hasSeparatingAxis[i] = 4;\n"
- " if (!sepA)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
- " posA,ornA,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " if (!sepB)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " bool sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis[i] = 1;\n"
- " separatingNormals[i] = sepNormal;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- "}\n"
- "__kernel void findSeparatingAxisVertexFaceKernel( __global const int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global volatile float4* separatingNormals,\n"
- " __global volatile int* hasSeparatingAxis,\n"
- " __global float* dmins,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " \n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " hasSeparatingAxis[i] = 0; \n"
- " \n"
- " //once the broadphase avoids static-static pairs, we can remove this test\n"
- " if ((rigidBodies[bodyIndexA].m_invMass==0) &&(rigidBodies[bodyIndexB].m_invMass==0))\n"
- " {\n"
- " return;\n"
- " }\n"
- " \n"
- " if ((collidables[collidableIndexA].m_shapeType!=SHAPE_CONVEX_HULL) ||(collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL))\n"
- " {\n"
- " return;\n"
- " }\n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " float dmin = FLT_MAX;\n"
- " dmins[i] = dmin;\n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " float4 sepNormal;\n"
- " \n"
- " bool sepA = findSeparatingAxis( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " hasSeparatingAxis[i] = 4;\n"
- " if (!sepA)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " bool sepB = findSeparatingAxis( &convexShapes[shapeIndexB],&convexShapes[shapeIndexA],posB,ornB,\n"
- " posA,ornA,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " if (sepB)\n"
- " {\n"
- " dmins[i] = dmin;\n"
- " hasSeparatingAxis[i] = 1;\n"
- " separatingNormals[i] = sepNormal;\n"
- " }\n"
- " }\n"
- " \n"
- " }\n"
- "}\n"
- "__kernel void findSeparatingAxisEdgeEdgeKernel( __global const int4* pairs, \n"
- " __global const BodyData* rigidBodies, \n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global btAabbCL* aabbs,\n"
- " __global float4* separatingNormals,\n"
- " __global int* hasSeparatingAxis,\n"
- " __global float* dmins,\n"
- " __global const float4* unitSphereDirections,\n"
- " int numUnitSphereDirections,\n"
- " int numPairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " \n"
- " if (i<numPairs)\n"
- " {\n"
- " if (hasSeparatingAxis[i])\n"
- " {\n"
- " \n"
- " int bodyIndexA = pairs[i].x;\n"
- " int bodyIndexB = pairs[i].y;\n"
- " \n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " \n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " \n"
- " \n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " \n"
- " float dmin = dmins[i];\n"
- " \n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 c0local = convexShapes[shapeIndexA].m_localCenter;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " float4 sepNormal = separatingNormals[i];\n"
- " \n"
- " \n"
- " \n"
- " bool sepEE = false;\n"
- " int numEdgeEdgeDirections = convexShapes[shapeIndexA].m_numUniqueEdges*convexShapes[shapeIndexB].m_numUniqueEdges;\n"
- " if (numEdgeEdgeDirections<=numUnitSphereDirections)\n"
- " {\n"
- " sepEE = findSeparatingAxisEdgeEdge( &convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,\n"
- " indices,&sepNormal,&dmin);\n"
- " \n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis[i] = 1;\n"
- " separatingNormals[i] = sepNormal;\n"
- " }\n"
- " }\n"
- " /*\n"
- " ///else case is a separate kernel, to make Mac OSX OpenCL compiler happy\n"
- " else\n"
- " {\n"
- " sepEE = findSeparatingAxisUnitSphere(&convexShapes[shapeIndexA], &convexShapes[shapeIndexB],posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " vertices,unitSphereDirections,numUnitSphereDirections,\n"
- " &sepNormal,&dmin);\n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis[i] = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis[i] = 1;\n"
- " separatingNormals[i] = sepNormal;\n"
- " }\n"
- " }\n"
- " */\n"
- " } //if (hasSeparatingAxis[i])\n"
- " }//(i<numPairs)\n"
- "}\n"
- "inline int findClippingFaces(const float4 separatingNormal,\n"
- " const ConvexPolyhedronCL* hullA, \n"
- " __global const ConvexPolyhedronCL* hullB,\n"
- " const float4 posA, const Quaternion ornA,const float4 posB, const Quaternion ornB,\n"
- " __global float4* worldVertsA1,\n"
- " __global float4* worldNormalsA1,\n"
- " __global float4* worldVertsB1,\n"
- " int capacityWorldVerts,\n"
- " const float minDist, float maxDist,\n"
- " const float4* verticesA,\n"
- " const btGpuFace* facesA,\n"
- " const int* indicesA,\n"
- " __global const float4* verticesB,\n"
- " __global const btGpuFace* facesB,\n"
- " __global const int* indicesB,\n"
- " __global int4* clippingFaces, int pairIndex)\n"
- "{\n"
- " int numContactsOut = 0;\n"
- " int numWorldVertsB1= 0;\n"
- " \n"
- " \n"
- " int closestFaceB=0;\n"
- " float dmax = -FLT_MAX;\n"
- " \n"
- " {\n"
- " for(int face=0;face<hullB->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(facesB[hullB->m_faceOffset+face].m_plane.x,\n"
- " facesB[hullB->m_faceOffset+face].m_plane.y, facesB[hullB->m_faceOffset+face].m_plane.z,0.f);\n"
- " const float4 WorldNormal = qtRotate(ornB, Normal);\n"
- " float d = dot3F4(WorldNormal,separatingNormal);\n"
- " if (d > dmax)\n"
- " {\n"
- " dmax = d;\n"
- " closestFaceB = face;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " {\n"
- " const btGpuFace polyB = facesB[hullB->m_faceOffset+closestFaceB];\n"
- " int numVertices = polyB.m_numIndices;\n"
- " if (numVertices>capacityWorldVerts)\n"
- " numVertices = capacityWorldVerts;\n"
- " \n"
- " for(int e0=0;e0<numVertices;e0++)\n"
- " {\n"
- " if (e0<capacityWorldVerts)\n"
- " {\n"
- " const float4 b = verticesB[hullB->m_vertexOffset+indicesB[polyB.m_indexOffset+e0]];\n"
- " worldVertsB1[pairIndex*capacityWorldVerts+numWorldVertsB1++] = transform(&b,&posB,&ornB);\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " int closestFaceA=0;\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " for(int face=0;face<hullA->m_numFaces;face++)\n"
- " {\n"
- " const float4 Normal = make_float4(\n"
- " facesA[hullA->m_faceOffset+face].m_plane.x,\n"
- " facesA[hullA->m_faceOffset+face].m_plane.y,\n"
- " facesA[hullA->m_faceOffset+face].m_plane.z,\n"
- " 0.f);\n"
- " const float4 faceANormalWS = qtRotate(ornA,Normal);\n"
- " \n"
- " float d = dot3F4(faceANormalWS,separatingNormal);\n"
- " if (d < dmin)\n"
- " {\n"
- " dmin = d;\n"
- " closestFaceA = face;\n"
- " worldNormalsA1[pairIndex] = faceANormalWS;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " int numVerticesA = facesA[hullA->m_faceOffset+closestFaceA].m_numIndices;\n"
- " if (numVerticesA>capacityWorldVerts)\n"
- " numVerticesA = capacityWorldVerts;\n"
- " \n"
- " for(int e0=0;e0<numVerticesA;e0++)\n"
- " {\n"
- " if (e0<capacityWorldVerts)\n"
- " {\n"
- " const float4 a = verticesA[hullA->m_vertexOffset+indicesA[facesA[hullA->m_faceOffset+closestFaceA].m_indexOffset+e0]];\n"
- " worldVertsA1[pairIndex*capacityWorldVerts+e0] = transform(&a, &posA,&ornA);\n"
- " }\n"
- " }\n"
- " \n"
- " clippingFaces[pairIndex].x = closestFaceA;\n"
- " clippingFaces[pairIndex].y = closestFaceB;\n"
- " clippingFaces[pairIndex].z = numVerticesA;\n"
- " clippingFaces[pairIndex].w = numWorldVertsB1;\n"
- " \n"
- " \n"
- " return numContactsOut;\n"
- "}\n"
- "// work-in-progress\n"
- "__kernel void findConcaveSeparatingAxisKernel( __global int4* concavePairs,\n"
- " __global const BodyData* rigidBodies,\n"
- " __global const btCollidableGpu* collidables,\n"
- " __global const ConvexPolyhedronCL* convexShapes, \n"
- " __global const float4* vertices,\n"
- " __global const float4* uniqueEdges,\n"
- " __global const btGpuFace* faces,\n"
- " __global const int* indices,\n"
- " __global const btGpuChildShape* gpuChildShapes,\n"
- " __global btAabbCL* aabbs,\n"
- " __global float4* concaveSeparatingNormalsOut,\n"
- " __global int* concaveHasSeparatingNormals,\n"
- " __global int4* clippingFacesOut,\n"
- " __global float4* worldVertsA1GPU,\n"
- " __global float4* worldNormalsAGPU,\n"
- " __global float4* worldVertsB1GPU,\n"
- " int vertexFaceCapacity,\n"
- " int numConcavePairs\n"
- " )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numConcavePairs)\n"
- " return;\n"
- " concaveHasSeparatingNormals[i] = 0;\n"
- " int pairIdx = i;\n"
- " int bodyIndexA = concavePairs[i].x;\n"
- " int bodyIndexB = concavePairs[i].y;\n"
- " int collidableIndexA = rigidBodies[bodyIndexA].m_collidableIdx;\n"
- " int collidableIndexB = rigidBodies[bodyIndexB].m_collidableIdx;\n"
- " int shapeIndexA = collidables[collidableIndexA].m_shapeIndex;\n"
- " int shapeIndexB = collidables[collidableIndexB].m_shapeIndex;\n"
- " if (collidables[collidableIndexB].m_shapeType!=SHAPE_CONVEX_HULL&&\n"
- " collidables[collidableIndexB].m_shapeType!=SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " concavePairs[pairIdx].w = -1;\n"
- " return;\n"
- " }\n"
- " int numFacesA = convexShapes[shapeIndexA].m_numFaces;\n"
- " int numActualConcaveConvexTests = 0;\n"
- " \n"
- " int f = concavePairs[i].z;\n"
- " \n"
- " bool overlap = false;\n"
- " \n"
- " ConvexPolyhedronCL convexPolyhedronA;\n"
- " //add 3 vertices of the triangle\n"
- " convexPolyhedronA.m_numVertices = 3;\n"
- " convexPolyhedronA.m_vertexOffset = 0;\n"
- " float4 localCenter = make_float4(0.f,0.f,0.f,0.f);\n"
- " btGpuFace face = faces[convexShapes[shapeIndexA].m_faceOffset+f];\n"
- " float4 triMinAabb, triMaxAabb;\n"
- " btAabbCL triAabb;\n"
- " triAabb.m_min = make_float4(1e30f,1e30f,1e30f,0.f);\n"
- " triAabb.m_max = make_float4(-1e30f,-1e30f,-1e30f,0.f);\n"
- " \n"
- " float4 verticesA[3];\n"
- " for (int i=0;i<3;i++)\n"
- " {\n"
- " int index = indices[face.m_indexOffset+i];\n"
- " float4 vert = vertices[convexShapes[shapeIndexA].m_vertexOffset+index];\n"
- " verticesA[i] = vert;\n"
- " localCenter += vert;\n"
- " \n"
- " triAabb.m_min = min(triAabb.m_min,vert); \n"
- " triAabb.m_max = max(triAabb.m_max,vert); \n"
- " }\n"
- " overlap = true;\n"
- " overlap = (triAabb.m_min.x > aabbs[bodyIndexB].m_max.x || triAabb.m_max.x < aabbs[bodyIndexB].m_min.x) ? false : overlap;\n"
- " overlap = (triAabb.m_min.z > aabbs[bodyIndexB].m_max.z || triAabb.m_max.z < aabbs[bodyIndexB].m_min.z) ? false : overlap;\n"
- " overlap = (triAabb.m_min.y > aabbs[bodyIndexB].m_max.y || triAabb.m_max.y < aabbs[bodyIndexB].m_min.y) ? false : overlap;\n"
- " \n"
- " if (overlap)\n"
- " {\n"
- " float dmin = FLT_MAX;\n"
- " int hasSeparatingAxis=5;\n"
- " float4 sepAxis=make_float4(1,2,3,4);\n"
- " int localCC=0;\n"
- " numActualConcaveConvexTests++;\n"
- " //a triangle has 3 unique edges\n"
- " convexPolyhedronA.m_numUniqueEdges = 3;\n"
- " convexPolyhedronA.m_uniqueEdgesOffset = 0;\n"
- " float4 uniqueEdgesA[3];\n"
- " \n"
- " uniqueEdgesA[0] = (verticesA[1]-verticesA[0]);\n"
- " uniqueEdgesA[1] = (verticesA[2]-verticesA[1]);\n"
- " uniqueEdgesA[2] = (verticesA[0]-verticesA[2]);\n"
- " convexPolyhedronA.m_faceOffset = 0;\n"
- " \n"
- " float4 normal = make_float4(face.m_plane.x,face.m_plane.y,face.m_plane.z,0.f);\n"
- " \n"
- " btGpuFace facesA[TRIANGLE_NUM_CONVEX_FACES];\n"
- " int indicesA[3+3+2+2+2];\n"
- " int curUsedIndices=0;\n"
- " int fidx=0;\n"
- " //front size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[0] = 0;\n"
- " indicesA[1] = 1;\n"
- " indicesA[2] = 2;\n"
- " curUsedIndices+=3;\n"
- " float c = face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = normal.x;\n"
- " facesA[fidx].m_plane.y = normal.y;\n"
- " facesA[fidx].m_plane.z = normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " //back size of triangle\n"
- " {\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[3]=2;\n"
- " indicesA[4]=1;\n"
- " indicesA[5]=0;\n"
- " curUsedIndices+=3;\n"
- " float c = dot(normal,verticesA[0]);\n"
- " float c1 = -face.m_plane.w;\n"
- " facesA[fidx].m_plane.x = -normal.x;\n"
- " facesA[fidx].m_plane.y = -normal.y;\n"
- " facesA[fidx].m_plane.z = -normal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " facesA[fidx].m_numIndices=3;\n"
- " }\n"
- " fidx++;\n"
- " bool addEdgePlanes = true;\n"
- " if (addEdgePlanes)\n"
- " {\n"
- " int numVertices=3;\n"
- " int prevVertex = numVertices-1;\n"
- " for (int i=0;i<numVertices;i++)\n"
- " {\n"
- " float4 v0 = verticesA[i];\n"
- " float4 v1 = verticesA[prevVertex];\n"
- " \n"
- " float4 edgeNormal = normalize(cross(normal,v1-v0));\n"
- " float c = -dot(edgeNormal,v0);\n"
- " facesA[fidx].m_numIndices = 2;\n"
- " facesA[fidx].m_indexOffset=curUsedIndices;\n"
- " indicesA[curUsedIndices++]=i;\n"
- " indicesA[curUsedIndices++]=prevVertex;\n"
- " \n"
- " facesA[fidx].m_plane.x = edgeNormal.x;\n"
- " facesA[fidx].m_plane.y = edgeNormal.y;\n"
- " facesA[fidx].m_plane.z = edgeNormal.z;\n"
- " facesA[fidx].m_plane.w = c;\n"
- " fidx++;\n"
- " prevVertex = i;\n"
- " }\n"
- " }\n"
- " convexPolyhedronA.m_numFaces = TRIANGLE_NUM_CONVEX_FACES;\n"
- " convexPolyhedronA.m_localCenter = localCenter*(1.f/3.f);\n"
- " float4 posA = rigidBodies[bodyIndexA].m_pos;\n"
- " posA.w = 0.f;\n"
- " float4 posB = rigidBodies[bodyIndexB].m_pos;\n"
- " posB.w = 0.f;\n"
- " float4 ornA = rigidBodies[bodyIndexA].m_quat;\n"
- " float4 ornB =rigidBodies[bodyIndexB].m_quat;\n"
- " \n"
- " ///////////////////\n"
- " ///compound shape support\n"
- " if (collidables[collidableIndexB].m_shapeType==SHAPE_COMPOUND_OF_CONVEX_HULLS)\n"
- " {\n"
- " int compoundChild = concavePairs[pairIdx].w;\n"
- " int childShapeIndexB = compoundChild;//collidables[collidableIndexB].m_shapeIndex+compoundChild;\n"
- " int childColIndexB = gpuChildShapes[childShapeIndexB].m_shapeIndex;\n"
- " float4 childPosB = gpuChildShapes[childShapeIndexB].m_childPosition;\n"
- " float4 childOrnB = gpuChildShapes[childShapeIndexB].m_childOrientation;\n"
- " float4 newPosB = transform(&childPosB,&posB,&ornB);\n"
- " float4 newOrnB = qtMul(ornB,childOrnB);\n"
- " posB = newPosB;\n"
- " ornB = newOrnB;\n"
- " shapeIndexB = collidables[childColIndexB].m_shapeIndex;\n"
- " }\n"
- " //////////////////\n"
- " float4 c0local = convexPolyhedronA.m_localCenter;\n"
- " float4 c0 = transform(&c0local, &posA, &ornA);\n"
- " float4 c1local = convexShapes[shapeIndexB].m_localCenter;\n"
- " float4 c1 = transform(&c1local,&posB,&ornB);\n"
- " const float4 DeltaC2 = c0 - c1;\n"
- " bool sepA = findSeparatingAxisLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " &sepAxis,&dmin);\n"
- " hasSeparatingAxis = 4;\n"
- " if (!sepA)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " bool sepB = findSeparatingAxisLocalB( &convexShapes[shapeIndexB],&convexPolyhedronA,\n"
- " posB,ornB,\n"
- " posA,ornA,\n"
- " DeltaC2,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " &sepAxis,&dmin);\n"
- " if (!sepB)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " bool sepEE = findSeparatingAxisEdgeEdgeLocalA( &convexPolyhedronA, &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " DeltaC2,\n"
- " verticesA,uniqueEdgesA,facesA,indicesA,\n"
- " vertices,uniqueEdges,faces,indices,\n"
- " &sepAxis,&dmin);\n"
- " \n"
- " if (!sepEE)\n"
- " {\n"
- " hasSeparatingAxis = 0;\n"
- " } else\n"
- " {\n"
- " hasSeparatingAxis = 1;\n"
- " }\n"
- " }\n"
- " } \n"
- " \n"
- " if (hasSeparatingAxis)\n"
- " {\n"
- " sepAxis.w = dmin;\n"
- " concaveSeparatingNormalsOut[pairIdx]=sepAxis;\n"
- " concaveHasSeparatingNormals[i]=1;\n"
- " float minDist = -1e30f;\n"
- " float maxDist = 0.02f;\n"
- " \n"
- " findClippingFaces(sepAxis,\n"
- " &convexPolyhedronA,\n"
- " &convexShapes[shapeIndexB],\n"
- " posA,ornA,\n"
- " posB,ornB,\n"
- " worldVertsA1GPU,\n"
- " worldNormalsAGPU,\n"
- " worldVertsB1GPU,\n"
- " vertexFaceCapacity,\n"
- " minDist, maxDist,\n"
- " verticesA,\n"
- " facesA,\n"
- " indicesA,\n"
- " vertices,\n"
- " faces,\n"
- " indices,\n"
- " clippingFacesOut, pairIdx);\n"
- " } else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- " }\n"
- " else\n"
- " { \n"
- " //mark this pair as in-active\n"
- " concavePairs[pairIdx].w = -1;\n"
- " }\n"
- " \n"
- " concavePairs[pairIdx].z = -1;//now z is used for existing/persistent contacts\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
deleted file mode 100644
index c0e11bfb26..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-//Host-code rewritten by Erwin Coumans
-
-#define BOUNDSEARCH_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl"
-#define KERNEL0 "SearchSortDataLowerKernel"
-#define KERNEL1 "SearchSortDataUpperKernel"
-#define KERNEL2 "SubtractKernel"
-
-#include "b3BoundSearchCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "b3LauncherCL.h"
-#include "kernels/BoundSearchKernelsCL.h"
-
-b3BoundSearchCL::b3BoundSearchCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int maxSize)
- : m_context(ctx),
- m_device(device),
- m_queue(queue)
-{
- const char* additionalMacros = "";
- //const char* srcFileNameForCaching="";
-
- cl_int pErrNum;
- const char* kernelSource = boundSearchKernelsCL;
-
- cl_program boundSearchProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, BOUNDSEARCH_PATH);
- b3Assert(boundSearchProg);
-
- m_lowerSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataLowerKernel", &pErrNum, boundSearchProg, additionalMacros);
- b3Assert(m_lowerSortDataKernel);
-
- m_upperSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SearchSortDataUpperKernel", &pErrNum, boundSearchProg, additionalMacros);
- b3Assert(m_upperSortDataKernel);
-
- m_subtractKernel = 0;
-
- if (maxSize)
- {
- m_subtractKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SubtractKernel", &pErrNum, boundSearchProg, additionalMacros);
- b3Assert(m_subtractKernel);
- }
-
- //m_constBuffer = new b3OpenCLArray<b3Int4>( device, 1, BufferBase::BUFFER_CONST );
-
- m_lower = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
- m_upper = (maxSize == 0) ? 0 : new b3OpenCLArray<unsigned int>(ctx, queue, maxSize);
-
- m_filler = new b3FillCL(ctx, device, queue);
-}
-
-b3BoundSearchCL::~b3BoundSearchCL()
-{
- delete m_lower;
- delete m_upper;
- delete m_filler;
-
- clReleaseKernel(m_lowerSortDataKernel);
- clReleaseKernel(m_upperSortDataKernel);
- clReleaseKernel(m_subtractKernel);
-}
-
-void b3BoundSearchCL::execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option)
-{
- b3Int4 constBuffer;
- constBuffer.x = nSrc;
- constBuffer.y = nDst;
-
- if (option == BOUND_LOWER)
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_lowerSortDataKernel, "m_lowerSortDataKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nSrc);
- launcher.setConst(nDst);
-
- launcher.launch1D(nSrc, 64);
- }
- else if (option == BOUND_UPPER)
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_upperSortDataKernel, "m_upperSortDataKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nSrc);
- launcher.setConst(nDst);
-
- launcher.launch1D(nSrc, 64);
- }
- else if (option == COUNT)
- {
- b3Assert(m_lower);
- b3Assert(m_upper);
- b3Assert(m_lower->capacity() <= (int)nDst);
- b3Assert(m_upper->capacity() <= (int)nDst);
-
- int zero = 0;
- m_filler->execute(*m_lower, zero, nDst);
- m_filler->execute(*m_upper, zero, nDst);
-
- execute(src, nSrc, *m_lower, nDst, BOUND_LOWER);
- execute(src, nSrc, *m_upper, nDst, BOUND_UPPER);
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_upper->getBufferCL(), true), b3BufferInfoCL(m_lower->getBufferCL(), true), b3BufferInfoCL(dst.getBufferCL())};
-
- b3LauncherCL launcher(m_queue, m_subtractKernel, "m_subtractKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(nSrc);
- launcher.setConst(nDst);
-
- launcher.launch1D(nDst, 64);
- }
- }
- else
- {
- b3Assert(0);
- }
-}
-
-void b3BoundSearchCL::executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc,
- b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option)
-{
- for (int i = 0; i < nSrc - 1; i++)
- b3Assert(src[i].m_key <= src[i + 1].m_key);
-
- b3SortData minData, zeroData, maxData;
- minData.m_key = -1;
- minData.m_value = -1;
- zeroData.m_key = 0;
- zeroData.m_value = 0;
- maxData.m_key = nDst;
- maxData.m_value = nDst;
-
- if (option == BOUND_LOWER)
- {
- for (int i = 0; i < nSrc; i++)
- {
- b3SortData& iData = (i == 0) ? minData : src[i - 1];
- b3SortData& jData = (i == nSrc) ? maxData : src[i];
-
- if (iData.m_key != jData.m_key)
- {
- int k = jData.m_key;
- {
- dst[k] = i;
- }
- }
- }
- }
- else if (option == BOUND_UPPER)
- {
- for (int i = 1; i < nSrc + 1; i++)
- {
- b3SortData& iData = src[i - 1];
- b3SortData& jData = (i == nSrc) ? maxData : src[i];
-
- if (iData.m_key != jData.m_key)
- {
- int k = iData.m_key;
- {
- dst[k] = i;
- }
- }
- }
- }
- else if (option == COUNT)
- {
- b3AlignedObjectArray<unsigned int> lower;
- lower.resize(nDst);
- b3AlignedObjectArray<unsigned int> upper;
- upper.resize(nDst);
-
- for (int i = 0; i < nDst; i++)
- {
- lower[i] = upper[i] = 0;
- }
-
- executeHost(src, nSrc, lower, nDst, BOUND_LOWER);
- executeHost(src, nSrc, upper, nDst, BOUND_UPPER);
-
- for (int i = 0; i < nDst; i++)
- {
- dst[i] = upper[i] - lower[i];
- }
- }
- else
- {
- b3Assert(0);
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
deleted file mode 100644
index 0d633e3d23..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#ifndef B3_BOUNDSEARCH_H
-#define B3_BOUNDSEARCH_H
-
-#pragma once
-
-/*#include <Adl/Adl.h>
-#include <AdlPrimitives/Math/Math.h>
-#include <AdlPrimitives/Sort/SortData.h>
-#include <AdlPrimitives/Fill/Fill.h>
-*/
-
-#include "b3OpenCLArray.h"
-#include "b3FillCL.h"
-#include "b3RadixSort32CL.h" //for b3SortData (perhaps move it?)
-class b3BoundSearchCL
-{
-public:
- enum Option
- {
- BOUND_LOWER,
- BOUND_UPPER,
- COUNT,
- };
-
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- cl_kernel m_lowerSortDataKernel;
- cl_kernel m_upperSortDataKernel;
- cl_kernel m_subtractKernel;
-
- b3OpenCLArray<b3Int4>* m_constbtOpenCLArray;
- b3OpenCLArray<unsigned int>* m_lower;
- b3OpenCLArray<unsigned int>* m_upper;
-
- b3FillCL* m_filler;
-
- b3BoundSearchCL(cl_context context, cl_device_id device, cl_command_queue queue, int size);
-
- virtual ~b3BoundSearchCL();
-
- // src has to be src[i].m_key <= src[i+1].m_key
- void execute(b3OpenCLArray<b3SortData>& src, int nSrc, b3OpenCLArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
-
- void executeHost(b3AlignedObjectArray<b3SortData>& src, int nSrc, b3AlignedObjectArray<unsigned int>& dst, int nDst, Option option = BOUND_LOWER);
-};
-
-#endif //B3_BOUNDSEARCH_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
deleted file mode 100644
index 35fc467b20..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3BufferInfoCL.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef B3_BUFFER_INFO_CL_H
-#define B3_BUFFER_INFO_CL_H
-
-#include "b3OpenCLArray.h"
-
-struct b3BufferInfoCL
-{
- //b3BufferInfoCL(){}
-
- // template<typename T>
- b3BufferInfoCL(cl_mem buff, bool isReadOnly = false) : m_clBuffer(buff), m_isReadOnly(isReadOnly) {}
-
- cl_mem m_clBuffer;
- bool m_isReadOnly;
-};
-
-#endif //B3_BUFFER_INFO_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
deleted file mode 100644
index bd25bb2101..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#include "b3FillCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "b3BufferInfoCL.h"
-#include "b3LauncherCL.h"
-
-#define FILL_CL_PROGRAM_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl"
-
-#include "kernels/FillKernelsCL.h"
-
-b3FillCL::b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue)
- : m_commandQueue(queue)
-{
- const char* kernelSource = fillKernelsCL;
- cl_int pErrNum;
- const char* additionalMacros = "";
-
- cl_program fillProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, FILL_CL_PROGRAM_PATH);
- b3Assert(fillProg);
-
- m_fillIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillIntKernel", &pErrNum, fillProg, additionalMacros);
- b3Assert(m_fillIntKernel);
-
- m_fillUnsignedIntKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillUnsignedIntKernel", &pErrNum, fillProg, additionalMacros);
- b3Assert(m_fillIntKernel);
-
- m_fillFloatKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillFloatKernel", &pErrNum, fillProg, additionalMacros);
- b3Assert(m_fillFloatKernel);
-
- m_fillKernelInt2 = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "FillInt2Kernel", &pErrNum, fillProg, additionalMacros);
- b3Assert(m_fillKernelInt2);
-}
-
-b3FillCL::~b3FillCL()
-{
- clReleaseKernel(m_fillKernelInt2);
- clReleaseKernel(m_fillIntKernel);
- clReleaseKernel(m_fillUnsignedIntKernel);
- clReleaseKernel(m_fillFloatKernel);
-}
-
-void b3FillCL::execute(b3OpenCLArray<float>& src, const float value, int n, int offset)
-{
- b3Assert(n > 0);
-
- {
- b3LauncherCL launcher(m_commandQueue, m_fillFloatKernel, "m_fillFloatKernel");
- launcher.setBuffer(src.getBufferCL());
- launcher.setConst(n);
- launcher.setConst(value);
- launcher.setConst(offset);
-
- launcher.launch1D(n);
- }
-}
-
-void b3FillCL::execute(b3OpenCLArray<int>& src, const int value, int n, int offset)
-{
- b3Assert(n > 0);
-
- {
- b3LauncherCL launcher(m_commandQueue, m_fillIntKernel, "m_fillIntKernel");
- launcher.setBuffer(src.getBufferCL());
- launcher.setConst(n);
- launcher.setConst(value);
- launcher.setConst(offset);
- launcher.launch1D(n);
- }
-}
-
-void b3FillCL::execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset)
-{
- b3Assert(n > 0);
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_fillUnsignedIntKernel, "m_fillUnsignedIntKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(n);
- launcher.setConst(value);
- launcher.setConst(offset);
-
- launcher.launch1D(n);
- }
-}
-
-void b3FillCL::executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset)
-{
- for (int i = 0; i < n; i++)
- {
- src[i + offset] = value;
- }
-}
-
-void b3FillCL::executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset)
-{
- for (int i = 0; i < n; i++)
- {
- src[i + offset] = value;
- }
-}
-
-void b3FillCL::execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset)
-{
- b3Assert(n > 0);
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src.getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_fillKernelInt2, "m_fillKernelInt2");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(n);
- launcher.setConst(value);
- launcher.setConst(offset);
-
- //( constBuffer );
- launcher.launch1D(n);
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
deleted file mode 100644
index c92c3e5119..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3FillCL.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef B3_FILL_CL_H
-#define B3_FILL_CL_H
-
-#include "b3OpenCLArray.h"
-#include "Bullet3Common/b3Scalar.h"
-
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/shared/b3Int4.h"
-
-class b3FillCL
-{
- cl_command_queue m_commandQueue;
-
- cl_kernel m_fillKernelInt2;
- cl_kernel m_fillIntKernel;
- cl_kernel m_fillUnsignedIntKernel;
- cl_kernel m_fillFloatKernel;
-
-public:
- struct b3ConstData
- {
- union {
- b3Int4 m_data;
- b3UnsignedInt4 m_UnsignedData;
- };
- int m_offset;
- int m_n;
- int m_padding[2];
- };
-
-protected:
-public:
- b3FillCL(cl_context ctx, cl_device_id device, cl_command_queue queue);
-
- virtual ~b3FillCL();
-
- void execute(b3OpenCLArray<unsigned int>& src, const unsigned int value, int n, int offset = 0);
-
- void execute(b3OpenCLArray<int>& src, const int value, int n, int offset = 0);
-
- void execute(b3OpenCLArray<float>& src, const float value, int n, int offset = 0);
-
- void execute(b3OpenCLArray<b3Int2>& src, const b3Int2& value, int n, int offset = 0);
-
- void executeHost(b3AlignedObjectArray<b3Int2>& src, const b3Int2& value, int n, int offset);
-
- void executeHost(b3AlignedObjectArray<int>& src, const int value, int n, int offset);
-
- // void execute(b3OpenCLArray<b3Int4>& src, const b3Int4& value, int n, int offset = 0);
-};
-
-#endif //B3_FILL_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
deleted file mode 100644
index c97d02eb45..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-#include "b3LauncherCL.h"
-
-bool gDebugLauncherCL = false;
-
-b3LauncherCL::b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name)
- : m_commandQueue(queue),
- m_kernel(kernel),
- m_idx(0),
- m_enableSerialization(false),
- m_name(name)
-{
- if (gDebugLauncherCL)
- {
- static int counter = 0;
- printf("[%d] Prepare to launch OpenCL kernel %s\n", counter++, name);
- }
-
- m_serializationSizeInBytes = sizeof(int);
-}
-
-b3LauncherCL::~b3LauncherCL()
-{
- for (int i = 0; i < m_arrays.size(); i++)
- {
- delete (m_arrays[i]);
- }
-
- m_arrays.clear();
- if (gDebugLauncherCL)
- {
- static int counter = 0;
- printf("[%d] Finished launching OpenCL kernel %s\n", counter++, m_name);
- }
-}
-
-void b3LauncherCL::setBuffer(cl_mem clBuffer)
-{
- if (m_enableSerialization)
- {
- b3KernelArgData kernelArg;
- kernelArg.m_argIndex = m_idx;
- kernelArg.m_isBuffer = 1;
- kernelArg.m_clBuffer = clBuffer;
-
- cl_mem_info param_name = CL_MEM_SIZE;
- size_t param_value;
- size_t sizeInBytes = sizeof(size_t);
- size_t actualSizeInBytes;
- cl_int err;
- err = clGetMemObjectInfo(kernelArg.m_clBuffer,
- param_name,
- sizeInBytes,
- &param_value,
- &actualSizeInBytes);
-
- b3Assert(err == CL_SUCCESS);
- kernelArg.m_argSizeInBytes = param_value;
-
- m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes += sizeof(b3KernelArgData);
- m_serializationSizeInBytes += param_value;
- }
- cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &clBuffer);
- b3Assert(status == CL_SUCCESS);
-}
-
-void b3LauncherCL::setBuffers(b3BufferInfoCL* buffInfo, int n)
-{
- for (int i = 0; i < n; i++)
- {
- if (m_enableSerialization)
- {
- b3KernelArgData kernelArg;
- kernelArg.m_argIndex = m_idx;
- kernelArg.m_isBuffer = 1;
- kernelArg.m_clBuffer = buffInfo[i].m_clBuffer;
-
- cl_mem_info param_name = CL_MEM_SIZE;
- size_t param_value;
- size_t sizeInBytes = sizeof(size_t);
- size_t actualSizeInBytes;
- cl_int err;
- err = clGetMemObjectInfo(kernelArg.m_clBuffer,
- param_name,
- sizeInBytes,
- &param_value,
- &actualSizeInBytes);
-
- b3Assert(err == CL_SUCCESS);
- kernelArg.m_argSizeInBytes = param_value;
-
- m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes += sizeof(b3KernelArgData);
- m_serializationSizeInBytes += param_value;
- }
- cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &buffInfo[i].m_clBuffer);
- b3Assert(status == CL_SUCCESS);
- }
-}
-
-struct b3KernelArgDataUnaligned
-{
- int m_isBuffer;
- int m_argIndex;
- int m_argSizeInBytes;
- int m_unusedPadding;
- union {
- cl_mem m_clBuffer;
- unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
- };
-};
-#include <string.h>
-
-int b3LauncherCL::deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx)
-{
- int index = 0;
-
- int numArguments = *(int*)&buf[index];
- index += sizeof(int);
-
- for (int i = 0; i < numArguments; i++)
- {
- b3KernelArgDataUnaligned* arg = (b3KernelArgDataUnaligned*)&buf[index];
-
- index += sizeof(b3KernelArgData);
- if (arg->m_isBuffer)
- {
- b3OpenCLArray<unsigned char>* clData = new b3OpenCLArray<unsigned char>(ctx, m_commandQueue, arg->m_argSizeInBytes);
- clData->resize(arg->m_argSizeInBytes);
-
- clData->copyFromHostPointer(&buf[index], arg->m_argSizeInBytes);
-
- arg->m_clBuffer = clData->getBufferCL();
-
- m_arrays.push_back(clData);
-
- cl_int status = clSetKernelArg(m_kernel, m_idx++, sizeof(cl_mem), &arg->m_clBuffer);
- b3Assert(status == CL_SUCCESS);
- index += arg->m_argSizeInBytes;
- }
- else
- {
- cl_int status = clSetKernelArg(m_kernel, m_idx++, arg->m_argSizeInBytes, &arg->m_argData);
- b3Assert(status == CL_SUCCESS);
- }
- b3KernelArgData b;
- memcpy(&b, arg, sizeof(b3KernelArgDataUnaligned));
- m_kernelArguments.push_back(b);
- }
- m_serializationSizeInBytes = index;
- return index;
-}
-
-int b3LauncherCL::validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx)
-{
- int index = 0;
-
- int numArguments = *(int*)&goldBuffer[index];
- index += sizeof(int);
-
- if (numArguments != m_kernelArguments.size())
- {
- printf("failed validation: expected %d arguments, found %d\n", numArguments, m_kernelArguments.size());
- return -1;
- }
-
- for (int ii = 0; ii < numArguments; ii++)
- {
- b3KernelArgData* argGold = (b3KernelArgData*)&goldBuffer[index];
-
- if (m_kernelArguments[ii].m_argSizeInBytes != argGold->m_argSizeInBytes)
- {
- printf("failed validation: argument %d sizeInBytes expected: %d, found %d\n", ii, argGold->m_argSizeInBytes, m_kernelArguments[ii].m_argSizeInBytes);
- return -2;
- }
-
- {
- int expected = argGold->m_isBuffer;
- int found = m_kernelArguments[ii].m_isBuffer;
-
- if (expected != found)
- {
- printf("failed validation: argument %d isBuffer expected: %d, found %d\n", ii, expected, found);
- return -3;
- }
- }
- index += sizeof(b3KernelArgData);
-
- if (argGold->m_isBuffer)
- {
- unsigned char* memBuf = (unsigned char*)malloc(m_kernelArguments[ii].m_argSizeInBytes);
- unsigned char* goldBuf = &goldBuffer[index];
- for (int j = 0; j < m_kernelArguments[j].m_argSizeInBytes; j++)
- {
- memBuf[j] = 0xaa;
- }
-
- cl_int status = 0;
- status = clEnqueueReadBuffer(m_commandQueue, m_kernelArguments[ii].m_clBuffer, CL_TRUE, 0, m_kernelArguments[ii].m_argSizeInBytes,
- memBuf, 0, 0, 0);
- b3Assert(status == CL_SUCCESS);
- clFinish(m_commandQueue);
-
- for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
- {
- int expected = goldBuf[b];
- int found = memBuf[b];
- if (expected != found)
- {
- printf("failed validation: argument %d OpenCL data at byte position %d expected: %d, found %d\n",
- ii, b, expected, found);
- return -4;
- }
- }
-
- index += argGold->m_argSizeInBytes;
- }
- else
- {
- //compare content
- for (int b = 0; b < m_kernelArguments[ii].m_argSizeInBytes; b++)
- {
- int expected = argGold->m_argData[b];
- int found = m_kernelArguments[ii].m_argData[b];
- if (expected != found)
- {
- printf("failed validation: argument %d const data at byte position %d expected: %d, found %d\n",
- ii, b, expected, found);
- return -5;
- }
- }
- }
- }
- return index;
-}
-
-int b3LauncherCL::serializeArguments(unsigned char* destBuffer, int destBufferCapacity)
-{
- //initialize to known values
- for (int i = 0; i < destBufferCapacity; i++)
- destBuffer[i] = 0xec;
-
- assert(destBufferCapacity >= m_serializationSizeInBytes);
-
- //todo: use the b3Serializer for this to allow for 32/64bit, endianness etc
- int numArguments = m_kernelArguments.size();
- int curBufferSize = 0;
- int* dest = (int*)&destBuffer[curBufferSize];
- *dest = numArguments;
- curBufferSize += sizeof(int);
-
- for (int i = 0; i < this->m_kernelArguments.size(); i++)
- {
- b3KernelArgData* arg = (b3KernelArgData*)&destBuffer[curBufferSize];
- *arg = m_kernelArguments[i];
- curBufferSize += sizeof(b3KernelArgData);
- if (arg->m_isBuffer == 1)
- {
- //copy the OpenCL buffer content
- cl_int status = 0;
- status = clEnqueueReadBuffer(m_commandQueue, arg->m_clBuffer, 0, 0, arg->m_argSizeInBytes,
- &destBuffer[curBufferSize], 0, 0, 0);
- b3Assert(status == CL_SUCCESS);
- clFinish(m_commandQueue);
- curBufferSize += arg->m_argSizeInBytes;
- }
- }
- return curBufferSize;
-}
-
-void b3LauncherCL::serializeToFile(const char* fileName, int numWorkItems)
-{
- int num = numWorkItems;
- int buffSize = getSerializationBufferSize();
- unsigned char* buf = new unsigned char[buffSize + sizeof(int)];
- for (int i = 0; i < buffSize + 1; i++)
- {
- unsigned char* ptr = (unsigned char*)&buf[i];
- *ptr = 0xff;
- }
- // int actualWrite = serializeArguments(buf,buffSize);
-
- // unsigned char* cptr = (unsigned char*)&buf[buffSize];
- // printf("buf[buffSize] = %d\n",*cptr);
-
- assert(buf[buffSize] == 0xff); //check for buffer overrun
- int* ptr = (int*)&buf[buffSize];
-
- *ptr = num;
-
- FILE* f = fopen(fileName, "wb");
- fwrite(buf, buffSize + sizeof(int), 1, f);
- fclose(f);
-
- delete[] buf;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
deleted file mode 100644
index 18e9c1db2b..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h
+++ /dev/null
@@ -1,128 +0,0 @@
-
-#ifndef B3_LAUNCHER_CL_H
-#define B3_LAUNCHER_CL_H
-
-#include "b3BufferInfoCL.h"
-#include "Bullet3Common/b3MinMax.h"
-#include "b3OpenCLArray.h"
-#include <stdio.h>
-
-#define B3_DEBUG_SERIALIZE_CL
-
-#ifdef _WIN32
-#pragma warning(disable : 4996)
-#endif
-#define B3_CL_MAX_ARG_SIZE 16
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3KernelArgData
-{
- int m_isBuffer;
- int m_argIndex;
- int m_argSizeInBytes;
- int m_unusedPadding;
- union {
- cl_mem m_clBuffer;
- unsigned char m_argData[B3_CL_MAX_ARG_SIZE];
- };
-};
-
-class b3LauncherCL
-{
- cl_command_queue m_commandQueue;
- cl_kernel m_kernel;
- int m_idx;
-
- b3AlignedObjectArray<b3KernelArgData> m_kernelArguments;
- int m_serializationSizeInBytes;
- bool m_enableSerialization;
-
- const char* m_name;
-
-public:
- b3AlignedObjectArray<b3OpenCLArray<unsigned char>*> m_arrays;
-
- b3LauncherCL(cl_command_queue queue, cl_kernel kernel, const char* name);
-
- virtual ~b3LauncherCL();
-
- void setBuffer(cl_mem clBuffer);
-
- void setBuffers(b3BufferInfoCL* buffInfo, int n);
-
- int getSerializationBufferSize() const
- {
- return m_serializationSizeInBytes;
- }
-
- int deserializeArgs(unsigned char* buf, int bufSize, cl_context ctx);
-
- inline int validateResults(unsigned char* goldBuffer, int goldBufferCapacity, cl_context ctx);
-
- int serializeArguments(unsigned char* destBuffer, int destBufferCapacity);
-
- int getNumArguments() const
- {
- return m_kernelArguments.size();
- }
-
- b3KernelArgData getArgument(int index)
- {
- return m_kernelArguments[index];
- }
-
- void serializeToFile(const char* fileName, int numWorkItems);
-
- template <typename T>
- inline void setConst(const T& consts)
- {
- int sz = sizeof(T);
- b3Assert(sz <= B3_CL_MAX_ARG_SIZE);
-
- if (m_enableSerialization)
- {
- b3KernelArgData kernelArg;
- kernelArg.m_argIndex = m_idx;
- kernelArg.m_isBuffer = 0;
- T* destArg = (T*)kernelArg.m_argData;
- *destArg = consts;
- kernelArg.m_argSizeInBytes = sizeof(T);
- m_kernelArguments.push_back(kernelArg);
- m_serializationSizeInBytes += sizeof(b3KernelArgData);
- }
-
- cl_int status = clSetKernelArg(m_kernel, m_idx++, sz, &consts);
- b3Assert(status == CL_SUCCESS);
- }
-
- inline void launch1D(int numThreads, int localSize = 64)
- {
- launch2D(numThreads, 1, localSize, 1);
- }
-
- inline void launch2D(int numThreadsX, int numThreadsY, int localSizeX, int localSizeY)
- {
- size_t gRange[3] = {1, 1, 1};
- size_t lRange[3] = {1, 1, 1};
- lRange[0] = localSizeX;
- lRange[1] = localSizeY;
- gRange[0] = b3Max((size_t)1, (numThreadsX / lRange[0]) + (!(numThreadsX % lRange[0]) ? 0 : 1));
- gRange[0] *= lRange[0];
- gRange[1] = b3Max((size_t)1, (numThreadsY / lRange[1]) + (!(numThreadsY % lRange[1]) ? 0 : 1));
- gRange[1] *= lRange[1];
-
- cl_int status = clEnqueueNDRangeKernel(m_commandQueue,
- m_kernel, 2, NULL, gRange, lRange, 0, 0, 0);
- if (status != CL_SUCCESS)
- {
- printf("Error: OpenCL status = %d\n", status);
- }
- b3Assert(status == CL_SUCCESS);
- }
-
- void enableSerialization(bool serialize)
- {
- m_enableSerialization = serialize;
- }
-};
-
-#endif //B3_LAUNCHER_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
deleted file mode 100644
index e837cceb66..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h
+++ /dev/null
@@ -1,300 +0,0 @@
-#ifndef B3_OPENCL_ARRAY_H
-#define B3_OPENCL_ARRAY_H
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-
-template <typename T>
-class b3OpenCLArray
-{
- size_t m_size;
- size_t m_capacity;
- cl_mem m_clBuffer;
-
- cl_context m_clContext;
- cl_command_queue m_commandQueue;
-
- bool m_ownsMemory;
-
- bool m_allowGrowingCapacity;
-
- void deallocate()
- {
- if (m_clBuffer && m_ownsMemory)
- {
- clReleaseMemObject(m_clBuffer);
- }
- m_clBuffer = 0;
- m_capacity = 0;
- }
-
- b3OpenCLArray<T>& operator=(const b3OpenCLArray<T>& src);
-
- B3_FORCE_INLINE size_t allocSize(size_t size)
- {
- return (size ? size * 2 : 1);
- }
-
-public:
- b3OpenCLArray(cl_context ctx, cl_command_queue queue, size_t initialCapacity = 0, bool allowGrowingCapacity = true)
- : m_size(0), m_capacity(0), m_clBuffer(0), m_clContext(ctx), m_commandQueue(queue), m_ownsMemory(true), m_allowGrowingCapacity(true)
- {
- if (initialCapacity)
- {
- reserve(initialCapacity);
- }
- m_allowGrowingCapacity = allowGrowingCapacity;
- }
-
- ///this is an error-prone method with no error checking, be careful!
- void setFromOpenCLBuffer(cl_mem buffer, size_t sizeInElements)
- {
- deallocate();
- m_ownsMemory = false;
- m_allowGrowingCapacity = false;
- m_clBuffer = buffer;
- m_size = sizeInElements;
- m_capacity = sizeInElements;
- }
-
- // we could enable this assignment, but need to make sure to avoid accidental deep copies
- // b3OpenCLArray<T>& operator=(const b3AlignedObjectArray<T>& src)
- // {
- // copyFromArray(src);
- // return *this;
- // }
-
- cl_mem getBufferCL() const
- {
- return m_clBuffer;
- }
-
- virtual ~b3OpenCLArray()
- {
- deallocate();
- m_size = 0;
- m_capacity = 0;
- }
-
- B3_FORCE_INLINE bool push_back(const T& _Val, bool waitForCompletion = true)
- {
- bool result = true;
- size_t sz = size();
- if (sz == capacity())
- {
- result = reserve(allocSize(size()));
- }
- copyFromHostPointer(&_Val, 1, sz, waitForCompletion);
- m_size++;
- return result;
- }
-
- B3_FORCE_INLINE T forcedAt(size_t n) const
- {
- b3Assert(n >= 0);
- b3Assert(n < capacity());
- T elem;
- copyToHostPointer(&elem, 1, n, true);
- return elem;
- }
-
- B3_FORCE_INLINE T at(size_t n) const
- {
- b3Assert(n >= 0);
- b3Assert(n < size());
- T elem;
- copyToHostPointer(&elem, 1, n, true);
- return elem;
- }
-
- B3_FORCE_INLINE bool resize(size_t newsize, bool copyOldContents = true)
- {
- bool result = true;
- size_t curSize = size();
-
- if (newsize < curSize)
- {
- //leave the OpenCL memory for now
- }
- else
- {
- if (newsize > size())
- {
- result = reserve(newsize, copyOldContents);
- }
-
- //leave new data uninitialized (init in debug mode?)
- //for (size_t i=curSize;i<newsize;i++) ...
- }
-
- if (result)
- {
- m_size = newsize;
- }
- else
- {
- m_size = 0;
- }
- return result;
- }
-
- B3_FORCE_INLINE size_t size() const
- {
- return m_size;
- }
-
- B3_FORCE_INLINE size_t capacity() const
- {
- return m_capacity;
- }
-
- B3_FORCE_INLINE bool reserve(size_t _Count, bool copyOldContents = true)
- {
- bool result = true;
- // determine new minimum length of allocated storage
- if (capacity() < _Count)
- { // not enough room, reallocate
-
- if (m_allowGrowingCapacity)
- {
- cl_int ciErrNum;
- //create a new OpenCL buffer
- size_t memSizeInBytes = sizeof(T) * _Count;
- cl_mem buf = clCreateBuffer(m_clContext, CL_MEM_READ_WRITE, memSizeInBytes, NULL, &ciErrNum);
- if (ciErrNum != CL_SUCCESS)
- {
- b3Error("OpenCL out-of-memory\n");
- _Count = 0;
- result = false;
- }
-//#define B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
-#ifdef B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
- unsigned char* src = (unsigned char*)malloc(memSizeInBytes);
- for (size_t i = 0; i < memSizeInBytes; i++)
- src[i] = 0xbb;
- ciErrNum = clEnqueueWriteBuffer(m_commandQueue, buf, CL_TRUE, 0, memSizeInBytes, src, 0, 0, 0);
- b3Assert(ciErrNum == CL_SUCCESS);
- clFinish(m_commandQueue);
- free(src);
-#endif //B3_ALWAYS_INITIALIZE_OPENCL_BUFFERS
-
- if (result)
- {
- if (copyOldContents)
- copyToCL(buf, size());
- }
-
- //deallocate the old buffer
- deallocate();
-
- m_clBuffer = buf;
-
- m_capacity = _Count;
- }
- else
- {
- //fail: assert and
- b3Assert(0);
- deallocate();
- result = false;
- }
- }
- return result;
- }
-
- void copyToCL(cl_mem destination, size_t numElements, size_t firstElem = 0, size_t dstOffsetInElems = 0) const
- {
- if (numElements <= 0)
- return;
-
- b3Assert(m_clBuffer);
- b3Assert(destination);
-
- //likely some error, destination is same as source
- b3Assert(m_clBuffer != destination);
-
- b3Assert((firstElem + numElements) <= m_size);
-
- cl_int status = 0;
-
- b3Assert(numElements > 0);
- b3Assert(numElements <= m_size);
-
- size_t srcOffsetBytes = sizeof(T) * firstElem;
- size_t dstOffsetInBytes = sizeof(T) * dstOffsetInElems;
-
- status = clEnqueueCopyBuffer(m_commandQueue, m_clBuffer, destination,
- srcOffsetBytes, dstOffsetInBytes, sizeof(T) * numElements, 0, 0, 0);
-
- b3Assert(status == CL_SUCCESS);
- }
-
- void copyFromHost(const b3AlignedObjectArray<T>& srcArray, bool waitForCompletion = true)
- {
- size_t newSize = srcArray.size();
-
- bool copyOldContents = false;
- resize(newSize, copyOldContents);
- if (newSize)
- copyFromHostPointer(&srcArray[0], newSize, 0, waitForCompletion);
- }
-
- void copyFromHostPointer(const T* src, size_t numElems, size_t destFirstElem = 0, bool waitForCompletion = true)
- {
- b3Assert(numElems + destFirstElem <= capacity());
-
- if (numElems + destFirstElem)
- {
- cl_int status = 0;
- size_t sizeInBytes = sizeof(T) * numElems;
- status = clEnqueueWriteBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * destFirstElem, sizeInBytes,
- src, 0, 0, 0);
- b3Assert(status == CL_SUCCESS);
- if (waitForCompletion)
- clFinish(m_commandQueue);
- }
- else
- {
- b3Error("copyFromHostPointer invalid range\n");
- }
- }
-
- void copyToHost(b3AlignedObjectArray<T>& destArray, bool waitForCompletion = true) const
- {
- destArray.resize(this->size());
- if (size())
- copyToHostPointer(&destArray[0], size(), 0, waitForCompletion);
- }
-
- void copyToHostPointer(T* destPtr, size_t numElem, size_t srcFirstElem = 0, bool waitForCompletion = true) const
- {
- b3Assert(numElem + srcFirstElem <= capacity());
-
- if (numElem + srcFirstElem <= capacity())
- {
- cl_int status = 0;
- status = clEnqueueReadBuffer(m_commandQueue, m_clBuffer, 0, sizeof(T) * srcFirstElem, sizeof(T) * numElem,
- destPtr, 0, 0, 0);
- b3Assert(status == CL_SUCCESS);
-
- if (waitForCompletion)
- clFinish(m_commandQueue);
- }
- else
- {
- b3Error("copyToHostPointer invalid range\n");
- }
- }
-
- void copyFromOpenCLArray(const b3OpenCLArray& src)
- {
- size_t newSize = src.size();
- resize(newSize);
- if (size())
- {
- src.copyToCL(m_clBuffer, size());
- }
- }
-};
-
-#endif //B3_OPENCL_ARRAY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
deleted file mode 100644
index 822b511633..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include "b3PrefixScanCL.h"
-#include "b3FillCL.h"
-#define B3_PREFIXSCAN_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl"
-
-#include "b3LauncherCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "kernels/PrefixScanKernelsCL.h"
-
-b3PrefixScanCL::b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
- : m_commandQueue(queue)
-{
- const char* scanKernelSource = prefixScanKernelsCL;
- cl_int pErrNum;
- char* additionalMacros = 0;
-
- m_workBuffer = new b3OpenCLArray<unsigned int>(ctx, queue, size);
- cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_PROG_PATH);
- b3Assert(scanProg);
-
- m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_localScanKernel);
- m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_blockSumKernel);
- m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_propagationKernel);
-}
-
-b3PrefixScanCL::~b3PrefixScanCL()
-{
- delete m_workBuffer;
- clReleaseKernel(m_localScanKernel);
- clReleaseKernel(m_blockSumKernel);
- clReleaseKernel(m_propagationKernel);
-}
-
-template <class T>
-T b3NextPowerOf2(T n)
-{
- n -= 1;
- for (int i = 0; i < sizeof(T) * 8; i++)
- n = n | (n >> i);
- return n + 1;
-}
-
-void b3PrefixScanCL::execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum)
-{
- // b3Assert( data->m_option == EXCLUSIVE );
- const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
-
- dst.resize(src.size());
- m_workBuffer->resize(src.size());
-
- b3Int4 constBuffer;
- constBuffer.x = n;
- constBuffer.y = numBlocks;
- constBuffer.z = (int)b3NextPowerOf2(numBlocks);
-
- b3OpenCLArray<unsigned int>* srcNative = &src;
- b3OpenCLArray<unsigned int>* dstNative = &dst;
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
- }
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
- }
-
- if (numBlocks > 1)
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
- }
-
- if (sum)
- {
- clFinish(m_commandQueue);
- dstNative->copyToHostPointer(sum, 1, n - 1, true);
- }
-}
-
-void b3PrefixScanCL::executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum)
-{
- unsigned int s = 0;
- //if( data->m_option == EXCLUSIVE )
- {
- for (int i = 0; i < n; i++)
- {
- dst[i] = s;
- s += src[i];
- }
- }
- /*else
- {
- for(int i=0; i<n; i++)
- {
- s += hSrc[i];
- hDst[i] = s;
- }
- }
- */
-
- if (sum)
- {
- *sum = dst[n - 1];
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
deleted file mode 100644
index 346efa0c73..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h
+++ /dev/null
@@ -1,35 +0,0 @@
-
-#ifndef B3_PREFIX_SCAN_CL_H
-#define B3_PREFIX_SCAN_CL_H
-
-#include "b3OpenCLArray.h"
-#include "b3BufferInfoCL.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-class b3PrefixScanCL
-{
- enum
- {
- BLOCK_SIZE = 128
- };
-
- // Option m_option;
-
- cl_command_queue m_commandQueue;
-
- cl_kernel m_localScanKernel;
- cl_kernel m_blockSumKernel;
- cl_kernel m_propagationKernel;
-
- b3OpenCLArray<unsigned int>* m_workBuffer;
-
-public:
- b3PrefixScanCL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
-
- virtual ~b3PrefixScanCL();
-
- void execute(b3OpenCLArray<unsigned int>& src, b3OpenCLArray<unsigned int>& dst, int n, unsigned int* sum = 0);
- void executeHost(b3AlignedObjectArray<unsigned int>& src, b3AlignedObjectArray<unsigned int>& dst, int n, unsigned int* sum = 0);
-};
-
-#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
deleted file mode 100644
index 1cac97c988..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-#include "b3PrefixScanFloat4CL.h"
-#include "b3FillCL.h"
-#define B3_PREFIXSCAN_FLOAT4_PROG_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl"
-
-#include "b3LauncherCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "kernels/PrefixScanKernelsFloat4CL.h"
-
-b3PrefixScanFloat4CL::b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size)
- : m_commandQueue(queue)
-{
- const char* scanKernelSource = prefixScanKernelsFloat4CL;
- cl_int pErrNum;
- char* additionalMacros = 0;
-
- m_workBuffer = new b3OpenCLArray<b3Vector3>(ctx, queue, size);
- cl_program scanProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, scanKernelSource, &pErrNum, additionalMacros, B3_PREFIXSCAN_FLOAT4_PROG_PATH);
- b3Assert(scanProg);
-
- m_localScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "LocalScanKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_localScanKernel);
- m_blockSumKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "TopLevelScanKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_blockSumKernel);
- m_propagationKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, scanKernelSource, "AddOffsetKernel", &pErrNum, scanProg, additionalMacros);
- b3Assert(m_propagationKernel);
-}
-
-b3PrefixScanFloat4CL::~b3PrefixScanFloat4CL()
-{
- delete m_workBuffer;
- clReleaseKernel(m_localScanKernel);
- clReleaseKernel(m_blockSumKernel);
- clReleaseKernel(m_propagationKernel);
-}
-
-template <class T>
-T b3NextPowerOf2(T n)
-{
- n -= 1;
- for (int i = 0; i < sizeof(T) * 8; i++)
- n = n | (n >> i);
- return n + 1;
-}
-
-void b3PrefixScanFloat4CL::execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum)
-{
- // b3Assert( data->m_option == EXCLUSIVE );
- const unsigned int numBlocks = (const unsigned int)((n + BLOCK_SIZE * 2 - 1) / (BLOCK_SIZE * 2));
-
- dst.resize(src.size());
- m_workBuffer->resize(src.size());
-
- b3Int4 constBuffer;
- constBuffer.x = n;
- constBuffer.y = numBlocks;
- constBuffer.z = (int)b3NextPowerOf2(numBlocks);
-
- b3OpenCLArray<b3Vector3>* srcNative = &src;
- b3OpenCLArray<b3Vector3>* dstNative = &dst;
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(srcNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_localScanKernel, "m_localScanKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D(numBlocks * BLOCK_SIZE, BLOCK_SIZE);
- }
-
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_workBuffer->getBufferCL())};
-
- b3LauncherCL launcher(m_commandQueue, m_blockSumKernel, "m_blockSumKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D(BLOCK_SIZE, BLOCK_SIZE);
- }
-
- if (numBlocks > 1)
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(dstNative->getBufferCL()), b3BufferInfoCL(m_workBuffer->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_propagationKernel, "m_propagationKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(constBuffer);
- launcher.launch1D((numBlocks - 1) * BLOCK_SIZE, BLOCK_SIZE);
- }
-
- if (sum)
- {
- clFinish(m_commandQueue);
- dstNative->copyToHostPointer(sum, 1, n - 1, true);
- }
-}
-
-void b3PrefixScanFloat4CL::executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum)
-{
- b3Vector3 s = b3MakeVector3(0, 0, 0);
- //if( data->m_option == EXCLUSIVE )
- {
- for (int i = 0; i < n; i++)
- {
- dst[i] = s;
- s += src[i];
- }
- }
- /*else
- {
- for(int i=0; i<n; i++)
- {
- s += hSrc[i];
- hDst[i] = s;
- }
- }
- */
-
- if (sum)
- {
- *sum = dst[n - 1];
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
deleted file mode 100644
index 122b0bfd68..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3PrefixScanFloat4CL.h
+++ /dev/null
@@ -1,36 +0,0 @@
-
-#ifndef B3_PREFIX_SCAN_CL_H
-#define B3_PREFIX_SCAN_CL_H
-
-#include "b3OpenCLArray.h"
-#include "b3BufferInfoCL.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Vector3.h"
-
-class b3PrefixScanFloat4CL
-{
- enum
- {
- BLOCK_SIZE = 128
- };
-
- // Option m_option;
-
- cl_command_queue m_commandQueue;
-
- cl_kernel m_localScanKernel;
- cl_kernel m_blockSumKernel;
- cl_kernel m_propagationKernel;
-
- b3OpenCLArray<b3Vector3>* m_workBuffer;
-
-public:
- b3PrefixScanFloat4CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int size = 0);
-
- virtual ~b3PrefixScanFloat4CL();
-
- void execute(b3OpenCLArray<b3Vector3>& src, b3OpenCLArray<b3Vector3>& dst, int n, b3Vector3* sum = 0);
- void executeHost(b3AlignedObjectArray<b3Vector3>& src, b3AlignedObjectArray<b3Vector3>& dst, int n, b3Vector3* sum);
-};
-
-#endif //B3_PREFIX_SCAN_CL_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
deleted file mode 100644
index e86af6583f..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.cpp
+++ /dev/null
@@ -1,646 +0,0 @@
-
-#include "b3RadixSort32CL.h"
-#include "b3LauncherCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "b3PrefixScanCL.h"
-#include "b3FillCL.h"
-
-#define RADIXSORT32_PATH "src/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl"
-
-#include "kernels/RadixSort32KernelsCL.h"
-
-b3RadixSort32CL::b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity)
- : m_commandQueue(queue)
-{
- b3OpenCLDeviceInfo info;
- b3OpenCLUtils::getDeviceInfo(device, &info);
- m_deviceCPU = (info.m_deviceType & CL_DEVICE_TYPE_CPU) != 0;
-
- m_workBuffer1 = new b3OpenCLArray<unsigned int>(ctx, queue);
- m_workBuffer2 = new b3OpenCLArray<unsigned int>(ctx, queue);
- m_workBuffer3 = new b3OpenCLArray<b3SortData>(ctx, queue);
- m_workBuffer3a = new b3OpenCLArray<unsigned int>(ctx, queue);
- m_workBuffer4 = new b3OpenCLArray<b3SortData>(ctx, queue);
- m_workBuffer4a = new b3OpenCLArray<unsigned int>(ctx, queue);
-
- if (initialCapacity > 0)
- {
- m_workBuffer1->resize(initialCapacity);
- m_workBuffer3->resize(initialCapacity);
- m_workBuffer3a->resize(initialCapacity);
- m_workBuffer4->resize(initialCapacity);
- m_workBuffer4a->resize(initialCapacity);
- }
-
- m_scan = new b3PrefixScanCL(ctx, device, queue);
- m_fill = new b3FillCL(ctx, device, queue);
-
- const char* additionalMacros = "";
-
- cl_int pErrNum;
- const char* kernelSource = radixSort32KernelsCL;
-
- cl_program sortProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, kernelSource, &pErrNum, additionalMacros, RADIXSORT32_PATH);
- b3Assert(sortProg);
-
- m_streamCountSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountSortDataKernel", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_streamCountSortDataKernel);
-
- m_streamCountKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "StreamCountKernel", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_streamCountKernel);
-
- if (m_deviceCPU)
- {
- m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernelSerial", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_sortAndScatterSortDataKernel);
- m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernelSerial", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_sortAndScatterKernel);
- }
- else
- {
- m_sortAndScatterSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterSortDataKernel", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_sortAndScatterSortDataKernel);
- m_sortAndScatterKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "SortAndScatterKernel", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_sortAndScatterKernel);
- }
-
- m_prefixScanKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, kernelSource, "PrefixScanKernel", &pErrNum, sortProg, additionalMacros);
- b3Assert(m_prefixScanKernel);
-}
-
-b3RadixSort32CL::~b3RadixSort32CL()
-{
- delete m_scan;
- delete m_fill;
- delete m_workBuffer1;
- delete m_workBuffer2;
- delete m_workBuffer3;
- delete m_workBuffer3a;
- delete m_workBuffer4;
- delete m_workBuffer4a;
-
- clReleaseKernel(m_streamCountSortDataKernel);
- clReleaseKernel(m_streamCountKernel);
- clReleaseKernel(m_sortAndScatterSortDataKernel);
- clReleaseKernel(m_sortAndScatterKernel);
- clReleaseKernel(m_prefixScanKernel);
-}
-
-void b3RadixSort32CL::executeHost(b3AlignedObjectArray<b3SortData>& inout, int sortBits /* = 32 */)
-{
- int n = inout.size();
- const int BITS_PER_PASS = 8;
- const int NUM_TABLES = (1 << BITS_PER_PASS);
-
- int tables[NUM_TABLES];
- int counter[NUM_TABLES];
-
- b3SortData* src = &inout[0];
- b3AlignedObjectArray<b3SortData> workbuffer;
- workbuffer.resize(inout.size());
- b3SortData* dst = &workbuffer[0];
-
- int count = 0;
- for (int startBit = 0; startBit < sortBits; startBit += BITS_PER_PASS)
- {
- for (int i = 0; i < NUM_TABLES; i++)
- {
- tables[i] = 0;
- }
-
- for (int i = 0; i < n; i++)
- {
- int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
- tables[tableIdx]++;
- }
-//#define TEST
-#ifdef TEST
- printf("histogram size=%d\n", NUM_TABLES);
- for (int i = 0; i < NUM_TABLES; i++)
- {
- if (tables[i] != 0)
- {
- printf("tables[%d]=%d]\n", i, tables[i]);
- }
- }
-#endif //TEST \
- // prefix scan
- int sum = 0;
- for (int i = 0; i < NUM_TABLES; i++)
- {
- int iData = tables[i];
- tables[i] = sum;
- sum += iData;
- counter[i] = 0;
- }
-
- // distribute
- for (int i = 0; i < n; i++)
- {
- int tableIdx = (src[i].m_key >> startBit) & (NUM_TABLES - 1);
-
- dst[tables[tableIdx] + counter[tableIdx]] = src[i];
- counter[tableIdx]++;
- }
-
- b3Swap(src, dst);
- count++;
- }
-
- if (count & 1)
- {
- b3Assert(0); //need to copy
- }
-}
-
-void b3RadixSort32CL::executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
-{
- b3AlignedObjectArray<b3SortData> inout;
- keyValuesInOut.copyToHost(inout);
-
- executeHost(inout, sortBits);
-
- keyValuesInOut.copyFromHost(inout);
-}
-
-void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
- b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits)
-{
-}
-
-//#define DEBUG_RADIXSORT
-//#define DEBUG_RADIXSORT2
-
-void b3RadixSort32CL::execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits /* = 32 */)
-{
- int originalSize = keyValuesInOut.size();
- int workingSize = originalSize;
-
- int dataAlignment = DATA_ALIGNMENT;
-
-#ifdef DEBUG_RADIXSORT2
- b3AlignedObjectArray<b3SortData> test2;
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n", test2.size());
- for (int i = 0; i < test2.size(); i++)
- {
- printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
- printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
- }
-#endif //DEBUG_RADIXSORT2
-
- b3OpenCLArray<b3SortData>* src = 0;
-
- if (workingSize % dataAlignment)
- {
- workingSize += dataAlignment - (workingSize % dataAlignment);
- m_workBuffer4->copyFromOpenCLArray(keyValuesInOut);
- m_workBuffer4->resize(workingSize);
- b3SortData fillValue;
- fillValue.m_key = 0xffffffff;
- fillValue.m_value = 0xffffffff;
-
-#define USE_BTFILL
-#ifdef USE_BTFILL
- m_fill->execute((b3OpenCLArray<b3Int2>&)*m_workBuffer4, (b3Int2&)fillValue, workingSize - originalSize, originalSize);
-#else
- //fill the remaining bits (very slow way, todo: fill on GPU/OpenCL side)
-
- for (int i = originalSize; i < workingSize; i++)
- {
- m_workBuffer4->copyFromHostPointer(&fillValue, 1, i);
- }
-#endif //USE_BTFILL
-
- src = m_workBuffer4;
- }
- else
- {
- src = &keyValuesInOut;
- m_workBuffer4->resize(0);
- }
-
- b3Assert(workingSize % DATA_ALIGNMENT == 0);
- int minCap = NUM_BUCKET * NUM_WGS;
-
- int n = workingSize;
-
- m_workBuffer1->resize(minCap);
- m_workBuffer3->resize(workingSize);
-
- // ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
- b3Assert(BITS_PER_PASS == 4);
- b3Assert(WG_SIZE == 64);
- b3Assert((sortBits & 0x3) == 0);
-
- b3OpenCLArray<b3SortData>* dst = m_workBuffer3;
-
- b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
- b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
-
- int nWGs = NUM_WGS;
- b3ConstData cdata;
-
- {
- int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE; //set at 256
- int nBlocks = (n + blockSize - 1) / (blockSize);
- cdata.m_n = n;
- cdata.m_nWGs = NUM_WGS;
- cdata.m_startBit = 0;
- cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
- if (nBlocks < NUM_WGS)
- {
- cdata.m_nBlocksPerWG = 1;
- nWGs = nBlocks;
- }
- }
-
- int count = 0;
- for (int ib = 0; ib < sortBits; ib += 4)
- {
-#ifdef DEBUG_RADIXSORT2
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n", test2.size());
- for (int i = 0; i < test2.size(); i++)
- {
- if (test2[i].m_key != test2[i].m_value)
- {
- printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
- printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
- }
- }
-#endif //DEBUG_RADIXSORT2
-
- cdata.m_startBit = ib;
-
- if (src->size())
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_streamCountSortDataKernel, "m_streamCountSortDataKernel");
-
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
-
- int num = NUM_WGS * WG_SIZE;
- launcher.launch1D(num, WG_SIZE);
- }
-
-#ifdef DEBUG_RADIXSORT
- b3AlignedObjectArray<unsigned int> testHist;
- srcHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
- for (int i = 0; i < testHist.size(); i++)
- {
- if (testHist[i] != 0)
- printf("testHist[%d]=%d\n", i, testHist[i]);
- }
-#endif //DEBUG_RADIXSORT
-
-//fast prefix scan is not working properly on Mac OSX yet
-#ifdef __APPLE__
- bool fastScan = false;
-#else
- bool fastScan = !m_deviceCPU; //only use fast scan on GPU
-#endif
-
- if (fastScan)
- { // prefix scan group histogram
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(128, 128);
- destHisto = srcHisto;
- }
- else
- {
- //unsigned int sum; //for debugging
- m_scan->execute(*srcHisto, *destHisto, 1920, 0); //,&sum);
- }
-
-#ifdef DEBUG_RADIXSORT
- destHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
- for (int i = 0; i < testHist.size(); i++)
- {
- if (testHist[i] != 0)
- printf("testHist[%d]=%d\n", i, testHist[i]);
- }
-
- for (int i = 0; i < testHist.size(); i += NUM_WGS)
- {
- printf("testHist[%d]=%d\n", i / NUM_WGS, testHist[i]);
- }
-
-#endif //DEBUG_RADIXSORT
-
-#define USE_GPU
-#ifdef USE_GPU
-
- if (src->size())
- { // local sort and distribute
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_sortAndScatterSortDataKernel, "m_sortAndScatterSortDataKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
- }
-#else
- {
-#define NUM_TABLES 16
-//#define SEQUENTIAL
-#ifdef SEQUENTIAL
- int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- int tables[NUM_TABLES];
- int startBit = ib;
-
- destHisto->copyToHost(testHist);
- b3AlignedObjectArray<b3SortData> srcHost;
- b3AlignedObjectArray<b3SortData> dstHost;
- dstHost.resize(src->size());
-
- src->copyToHost(srcHost);
-
- for (int i = 0; i < NUM_TABLES; i++)
- {
- tables[i] = testHist[i * NUM_WGS];
- }
-
- // distribute
- for (int i = 0; i < n; i++)
- {
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
-
- dstHost[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
- counter2[tableIdx]++;
- }
-
-#else
-
- int counter2[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- int tables[NUM_TABLES];
- b3AlignedObjectArray<b3SortData> dstHostOK;
- dstHostOK.resize(src->size());
-
- destHisto->copyToHost(testHist);
- b3AlignedObjectArray<b3SortData> srcHost;
- src->copyToHost(srcHost);
-
- int blockSize = 256;
- int nBlocksPerWG = cdata.m_nBlocksPerWG;
- int startBit = ib;
-
- {
- for (int i = 0; i < NUM_TABLES; i++)
- {
- tables[i] = testHist[i * NUM_WGS];
- }
-
- // distribute
- for (int i = 0; i < n; i++)
- {
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
-
- dstHostOK[tables[tableIdx] + counter2[tableIdx]] = srcHost[i];
- counter2[tableIdx]++;
- }
- }
-
- b3AlignedObjectArray<b3SortData> dstHost;
- dstHost.resize(src->size());
-
- int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- for (int wgIdx = 0; wgIdx < NUM_WGS; wgIdx++)
- {
- int counter[NUM_TABLES] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
- int nBlocks = (n) / blockSize - nBlocksPerWG * wgIdx;
-
- for (int iblock = 0; iblock < b3Min(cdata.m_nBlocksPerWG, nBlocks); iblock++)
- {
- for (int lIdx = 0; lIdx < 64; lIdx++)
- {
- int addr = iblock * blockSize + blockSize * cdata.m_nBlocksPerWG * wgIdx + ELEMENTS_PER_WORK_ITEM * lIdx;
-
- // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
- // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
- // AMD: AtomInc performs better while NV prefers ++
- for (int j = 0; j < ELEMENTS_PER_WORK_ITEM; j++)
- {
- if (addr + j < n)
- {
- // printf ("addr+j=%d\n", addr+j);
-
- int i = addr + j;
-
- int tableIdx = (srcHost[i].m_key >> startBit) & (NUM_TABLES - 1);
-
- int destIndex = testHist[tableIdx * NUM_WGS + wgIdx] + counter[tableIdx];
-
- b3SortData ok = dstHostOK[destIndex];
-
- if (ok.m_key != srcHost[i].m_key)
- {
- printf("ok.m_key = %d, srcHost[i].m_key = %d\n", ok.m_key, srcHost[i].m_key);
- printf("(ok.m_value = %d, srcHost[i].m_value = %d)\n", ok.m_value, srcHost[i].m_value);
- }
- if (ok.m_value != srcHost[i].m_value)
- {
- printf("ok.m_value = %d, srcHost[i].m_value = %d\n", ok.m_value, srcHost[i].m_value);
- printf("(ok.m_key = %d, srcHost[i].m_key = %d)\n", ok.m_key, srcHost[i].m_key);
- }
-
- dstHost[destIndex] = srcHost[i];
- counter[tableIdx]++;
- }
- }
- }
- }
- }
-
-#endif //SEQUENTIAL
-
- dst->copyFromHost(dstHost);
- }
-#endif //USE_GPU
-
-#ifdef DEBUG_RADIXSORT
- destHisto->copyToHost(testHist);
- printf("ib = %d, testHist size = %d, non zero elements:\n", ib, testHist.size());
- for (int i = 0; i < testHist.size(); i++)
- {
- if (testHist[i] != 0)
- printf("testHist[%d]=%d\n", i, testHist[i]);
- }
-#endif //DEBUG_RADIXSORT
- b3Swap(src, dst);
- b3Swap(srcHisto, destHisto);
-
-#ifdef DEBUG_RADIXSORT2
- keyValuesInOut.copyToHost(test2);
- printf("numElem = %d\n", test2.size());
- for (int i = 0; i < test2.size(); i++)
- {
- if (test2[i].m_key != test2[i].m_value)
- {
- printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
- printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
- }
- }
-#endif //DEBUG_RADIXSORT2
-
- count++;
- }
-
- if (count & 1)
- {
- b3Assert(0); //need to copy from workbuffer to keyValuesInOut
- }
-
- if (m_workBuffer4->size())
- {
- m_workBuffer4->resize(originalSize);
- keyValuesInOut.copyFromOpenCLArray(*m_workBuffer4);
- }
-
-#ifdef DEBUG_RADIXSORT
- keyValuesInOut.copyToHost(test2);
-
- printf("numElem = %d\n", test2.size());
- for (int i = 0; i < test2.size(); i++)
- {
- printf("test2[%d].m_key=%d\n", i, test2[i].m_key);
- printf("test2[%d].m_value=%d\n", i, test2[i].m_value);
- }
-#endif
-}
-
-void b3RadixSort32CL::execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits /* = 32 */)
-{
- int originalSize = keysInOut.size();
- int workingSize = originalSize;
-
- int dataAlignment = DATA_ALIGNMENT;
-
- b3OpenCLArray<unsigned int>* src = 0;
-
- if (workingSize % dataAlignment)
- {
- workingSize += dataAlignment - (workingSize % dataAlignment);
- m_workBuffer4a->copyFromOpenCLArray(keysInOut);
- m_workBuffer4a->resize(workingSize);
- unsigned int fillValue = 0xffffffff;
-
- m_fill->execute(*m_workBuffer4a, fillValue, workingSize - originalSize, originalSize);
-
- src = m_workBuffer4a;
- }
- else
- {
- src = &keysInOut;
- m_workBuffer4a->resize(0);
- }
-
- b3Assert(workingSize % DATA_ALIGNMENT == 0);
- int minCap = NUM_BUCKET * NUM_WGS;
-
- int n = workingSize;
-
- m_workBuffer1->resize(minCap);
- m_workBuffer3->resize(workingSize);
- m_workBuffer3a->resize(workingSize);
-
- // ADLASSERT( ELEMENTS_PER_WORK_ITEM == 4 );
- b3Assert(BITS_PER_PASS == 4);
- b3Assert(WG_SIZE == 64);
- b3Assert((sortBits & 0x3) == 0);
-
- b3OpenCLArray<unsigned int>* dst = m_workBuffer3a;
-
- b3OpenCLArray<unsigned int>* srcHisto = m_workBuffer1;
- b3OpenCLArray<unsigned int>* destHisto = m_workBuffer2;
-
- int nWGs = NUM_WGS;
- b3ConstData cdata;
-
- {
- int blockSize = ELEMENTS_PER_WORK_ITEM * WG_SIZE; //set at 256
- int nBlocks = (n + blockSize - 1) / (blockSize);
- cdata.m_n = n;
- cdata.m_nWGs = NUM_WGS;
- cdata.m_startBit = 0;
- cdata.m_nBlocksPerWG = (nBlocks + cdata.m_nWGs - 1) / cdata.m_nWGs;
- if (nBlocks < NUM_WGS)
- {
- cdata.m_nBlocksPerWG = 1;
- nWGs = nBlocks;
- }
- }
-
- int count = 0;
- for (int ib = 0; ib < sortBits; ib += 4)
- {
- cdata.m_startBit = ib;
-
- if (src->size())
- {
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(srcHisto->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_streamCountKernel, "m_streamCountKernel");
-
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
-
- int num = NUM_WGS * WG_SIZE;
- launcher.launch1D(num, WG_SIZE);
- }
-
-//fast prefix scan is not working properly on Mac OSX yet
-#ifdef __APPLE__
- bool fastScan = false;
-#else
- bool fastScan = !m_deviceCPU;
-#endif
-
- if (fastScan)
- { // prefix scan group histogram
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(srcHisto->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_prefixScanKernel, "m_prefixScanKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(128, 128);
- destHisto = srcHisto;
- }
- else
- {
- //unsigned int sum; //for debugging
- m_scan->execute(*srcHisto, *destHisto, 1920, 0); //,&sum);
- }
-
- if (src->size())
- { // local sort and distribute
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(src->getBufferCL(), true), b3BufferInfoCL(destHisto->getBufferCL(), true), b3BufferInfoCL(dst->getBufferCL())};
- b3LauncherCL launcher(m_commandQueue, m_sortAndScatterKernel, "m_sortAndScatterKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(nWGs * WG_SIZE, WG_SIZE);
- }
-
- b3Swap(src, dst);
- b3Swap(srcHisto, destHisto);
-
- count++;
- }
-
- if (count & 1)
- {
- b3Assert(0); //need to copy from workbuffer to keyValuesInOut
- }
-
- if (m_workBuffer4a->size())
- {
- m_workBuffer4a->resize(originalSize);
- keysInOut.copyFromOpenCLArray(*m_workBuffer4a);
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
deleted file mode 100644
index 69caf182d7..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h
+++ /dev/null
@@ -1,84 +0,0 @@
-
-#ifndef B3_RADIXSORT32_H
-#define B3_RADIXSORT32_H
-
-#include "b3OpenCLArray.h"
-
-struct b3SortData
-{
- union {
- unsigned int m_key;
- unsigned int x;
- };
-
- union {
- unsigned int m_value;
- unsigned int y;
- };
-};
-#include "b3BufferInfoCL.h"
-
-class b3RadixSort32CL
-{
- b3OpenCLArray<unsigned int>* m_workBuffer1;
- b3OpenCLArray<unsigned int>* m_workBuffer2;
-
- b3OpenCLArray<b3SortData>* m_workBuffer3;
- b3OpenCLArray<b3SortData>* m_workBuffer4;
-
- b3OpenCLArray<unsigned int>* m_workBuffer3a;
- b3OpenCLArray<unsigned int>* m_workBuffer4a;
-
- cl_command_queue m_commandQueue;
-
- cl_kernel m_streamCountSortDataKernel;
- cl_kernel m_streamCountKernel;
-
- cl_kernel m_prefixScanKernel;
- cl_kernel m_sortAndScatterSortDataKernel;
- cl_kernel m_sortAndScatterKernel;
-
- bool m_deviceCPU;
-
- class b3PrefixScanCL* m_scan;
- class b3FillCL* m_fill;
-
-public:
- struct b3ConstData
- {
- int m_n;
- int m_nWGs;
- int m_startBit;
- int m_nBlocksPerWG;
- };
- enum
- {
- DATA_ALIGNMENT = 256,
- WG_SIZE = 64,
- BLOCK_SIZE = 256,
- ELEMENTS_PER_WORK_ITEM = (BLOCK_SIZE / WG_SIZE),
- BITS_PER_PASS = 4,
- NUM_BUCKET = (1 << BITS_PER_PASS),
- // if you change this, change nPerWI in kernel as well
- NUM_WGS = 20 * 6, // cypress
- // NUM_WGS = 24*6, // cayman
- // NUM_WGS = 32*4, // nv
- };
-
-private:
-public:
- b3RadixSort32CL(cl_context ctx, cl_device_id device, cl_command_queue queue, int initialCapacity = 0);
-
- virtual ~b3RadixSort32CL();
-
- void execute(b3OpenCLArray<unsigned int>& keysIn, b3OpenCLArray<unsigned int>& keysOut, b3OpenCLArray<unsigned int>& valuesIn,
- b3OpenCLArray<unsigned int>& valuesOut, int n, int sortBits = 32);
-
- ///keys only
- void execute(b3OpenCLArray<unsigned int>& keysInOut, int sortBits = 32);
-
- void execute(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
- void executeHost(b3OpenCLArray<b3SortData>& keyValuesInOut, int sortBits = 32);
- void executeHost(b3AlignedObjectArray<b3SortData>& keyValuesInOut, int sortBits = 32);
-};
-#endif //B3_RADIXSORT32_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl
deleted file mode 100644
index f3b4a1e8a7..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernels.cl
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-
-typedef struct
-{
- u32 m_key;
- u32 m_value;
-}SortData;
-
-
-
-typedef struct
-{
- u32 m_nSrc;
- u32 m_nDst;
- u32 m_padding[2];
-} ConstBuffer;
-
-
-
-__attribute__((reqd_work_group_size(64,1,1)))
-__kernel
-void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst,
- unsigned int nSrc, unsigned int nDst)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nSrc )
- {
- SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);
- SortData end; end.m_key = nDst; end.m_value = nDst;
-
- SortData iData = (gIdx==0)? first: src[gIdx-1];
- SortData jData = (gIdx==nSrc)? end: src[gIdx];
-
- if( iData.m_key != jData.m_key )
- {
-// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)
- u32 k = jData.m_key;
- {
- dst[k] = gIdx;
- }
- }
- }
-}
-
-
-__attribute__((reqd_work_group_size(64,1,1)))
-__kernel
-void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst,
- unsigned int nSrc, unsigned int nDst)
-{
- int gIdx = GET_GLOBAL_IDX+1;
-
- if( gIdx < nSrc+1 )
- {
- SortData first; first.m_key = 0; first.m_value = 0;
- SortData end; end.m_key = nDst; end.m_value = nDst;
-
- SortData iData = src[gIdx-1];
- SortData jData = (gIdx==nSrc)? end: src[gIdx];
-
- if( iData.m_key != jData.m_key )
- {
- u32 k = iData.m_key;
- {
- dst[k] = gIdx;
- }
- }
- }
-}
-
-__attribute__((reqd_work_group_size(64,1,1)))
-__kernel
-void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C,
- unsigned int nSrc, unsigned int nDst)
-{
- int gIdx = GET_GLOBAL_IDX;
-
-
- if( gIdx < nDst )
- {
- C[gIdx] = A[gIdx] - B[gIdx];
- }
-}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
deleted file mode 100644
index 1758dd41e3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/BoundSearchKernelsCL.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* boundSearchKernelsCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "typedef struct\n"
- "{\n"
- " u32 m_key; \n"
- " u32 m_value;\n"
- "}SortData;\n"
- "typedef struct\n"
- "{\n"
- " u32 m_nSrc;\n"
- " u32 m_nDst;\n"
- " u32 m_padding[2];\n"
- "} ConstBuffer;\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "__kernel\n"
- "void SearchSortDataLowerKernel(__global SortData* src, __global u32 *dst, \n"
- " unsigned int nSrc, unsigned int nDst)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nSrc )\n"
- " {\n"
- " SortData first; first.m_key = (u32)(-1); first.m_value = (u32)(-1);\n"
- " SortData end; end.m_key = nDst; end.m_value = nDst;\n"
- " SortData iData = (gIdx==0)? first: src[gIdx-1];\n"
- " SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
- " if( iData.m_key != jData.m_key )\n"
- " {\n"
- "// for(u32 k=iData.m_key+1; k<=min(jData.m_key, nDst-1); k++)\n"
- " u32 k = jData.m_key;\n"
- " {\n"
- " dst[k] = gIdx;\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "__kernel\n"
- "void SearchSortDataUpperKernel(__global SortData* src, __global u32 *dst, \n"
- " unsigned int nSrc, unsigned int nDst)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX+1;\n"
- " if( gIdx < nSrc+1 )\n"
- " {\n"
- " SortData first; first.m_key = 0; first.m_value = 0;\n"
- " SortData end; end.m_key = nDst; end.m_value = nDst;\n"
- " SortData iData = src[gIdx-1];\n"
- " SortData jData = (gIdx==nSrc)? end: src[gIdx];\n"
- " if( iData.m_key != jData.m_key )\n"
- " {\n"
- " u32 k = iData.m_key;\n"
- " {\n"
- " dst[k] = gIdx;\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "__kernel\n"
- "void SubtractKernel(__global u32* A, __global u32 *B, __global u32 *C, \n"
- " unsigned int nSrc, unsigned int nDst)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " \n"
- " if( gIdx < nDst )\n"
- " {\n"
- " C[gIdx] = A[gIdx] - B[gIdx];\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl
deleted file mode 100644
index 2eee5752ec..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernels.cl
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-
-#define make_uint4 (uint4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-typedef struct
-{
- int m_n;
- int m_padding[3];
-} ConstBuffer;
-
-
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void Copy1F4Kernel(__global float4* dst, __global float4* src,
- ConstBuffer cb)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < cb.m_n )
- {
- float4 a0 = src[gIdx];
-
- dst[ gIdx ] = a0;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void Copy2F4Kernel(__global float4* dst, __global float4* src,
- ConstBuffer cb)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( 2*gIdx <= cb.m_n )
- {
- float4 a0 = src[gIdx*2+0];
- float4 a1 = src[gIdx*2+1];
-
- dst[ gIdx*2+0 ] = a0;
- dst[ gIdx*2+1 ] = a1;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void Copy4F4Kernel(__global float4* dst, __global float4* src,
- ConstBuffer cb)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( 4*gIdx <= cb.m_n )
- {
- int idx0 = gIdx*4+0;
- int idx1 = gIdx*4+1;
- int idx2 = gIdx*4+2;
- int idx3 = gIdx*4+3;
-
- float4 a0 = src[idx0];
- float4 a1 = src[idx1];
- float4 a2 = src[idx2];
- float4 a3 = src[idx3];
-
- dst[ idx0 ] = a0;
- dst[ idx1 ] = a1;
- dst[ idx2 ] = a2;
- dst[ idx3 ] = a3;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void CopyF1Kernel(__global float* dstF1, __global float* srcF1,
- ConstBuffer cb)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < cb.m_n )
- {
- float a0 = srcF1[gIdx];
-
- dstF1[ gIdx ] = a0;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2,
- ConstBuffer cb)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < cb.m_n )
- {
- float2 a0 = srcF2[gIdx];
-
- dstF2[ gIdx ] = a0;
- }
-}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
deleted file mode 100644
index 33c9279462..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/CopyKernelsCL.h
+++ /dev/null
@@ -1,131 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* copyKernelsCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "\n"
- "#define make_uint4 (uint4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "\n"
- "typedef struct\n"
- "{\n"
- " int m_n;\n"
- " int m_padding[3];\n"
- "} ConstBuffer;\n"
- "\n"
- "\n"
- "\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void Copy1F4Kernel(__global float4* dst, __global float4* src, \n"
- " ConstBuffer cb)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- "\n"
- " if( gIdx < cb.m_n )\n"
- " {\n"
- " float4 a0 = src[gIdx];\n"
- "\n"
- " dst[ gIdx ] = a0;\n"
- " }\n"
- "}\n"
- "\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void Copy2F4Kernel(__global float4* dst, __global float4* src, \n"
- " ConstBuffer cb)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- "\n"
- " if( 2*gIdx <= cb.m_n )\n"
- " {\n"
- " float4 a0 = src[gIdx*2+0];\n"
- " float4 a1 = src[gIdx*2+1];\n"
- "\n"
- " dst[ gIdx*2+0 ] = a0;\n"
- " dst[ gIdx*2+1 ] = a1;\n"
- " }\n"
- "}\n"
- "\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void Copy4F4Kernel(__global float4* dst, __global float4* src, \n"
- " ConstBuffer cb)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- "\n"
- " if( 4*gIdx <= cb.m_n )\n"
- " {\n"
- " int idx0 = gIdx*4+0;\n"
- " int idx1 = gIdx*4+1;\n"
- " int idx2 = gIdx*4+2;\n"
- " int idx3 = gIdx*4+3;\n"
- "\n"
- " float4 a0 = src[idx0];\n"
- " float4 a1 = src[idx1];\n"
- " float4 a2 = src[idx2];\n"
- " float4 a3 = src[idx3];\n"
- "\n"
- " dst[ idx0 ] = a0;\n"
- " dst[ idx1 ] = a1;\n"
- " dst[ idx2 ] = a2;\n"
- " dst[ idx3 ] = a3;\n"
- " }\n"
- "}\n"
- "\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void CopyF1Kernel(__global float* dstF1, __global float* srcF1, \n"
- " ConstBuffer cb)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- "\n"
- " if( gIdx < cb.m_n )\n"
- " {\n"
- " float a0 = srcF1[gIdx];\n"
- "\n"
- " dstF1[ gIdx ] = a0;\n"
- " }\n"
- "}\n"
- "\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void CopyF2Kernel(__global float2* dstF2, __global float2* srcF2, \n"
- " ConstBuffer cb)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- "\n"
- " if( gIdx < cb.m_n )\n"
- " {\n"
- " float2 a0 = srcF2[gIdx];\n"
- "\n"
- " dstF2[ gIdx ] = a0;\n"
- " }\n"
- "}\n"
- "\n"
- "\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl
deleted file mode 100644
index 71c31075dd..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernels.cl
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-
-#define make_uint4 (uint4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-typedef struct
-{
- union
- {
- int4 m_data;
- uint4 m_unsignedData;
- float m_floatData;
- };
- int m_offset;
- int m_n;
- int m_padding[2];
-} ConstBuffer;
-
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < num_elements )
- {
- dstInt[ offset+gIdx ] = value;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < num_elements )
- {
- dstFloat[ offset+gIdx ] = value;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < num )
- {
- dstInt[ offset+gIdx ] = value;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < num )
- {
- dstInt2[ gIdx + offset] = make_int2( value.x, value.y );
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(64,1,1)))
-void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < num )
- {
- dstInt4[ offset+gIdx ] = value;
- }
-}
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
deleted file mode 100644
index 983e652270..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/FillKernelsCL.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* fillKernelsCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define make_uint4 (uint4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "typedef struct\n"
- "{\n"
- " union\n"
- " {\n"
- " int4 m_data;\n"
- " uint4 m_unsignedData;\n"
- " float m_floatData;\n"
- " };\n"
- " int m_offset;\n"
- " int m_n;\n"
- " int m_padding[2];\n"
- "} ConstBuffer;\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void FillIntKernel(__global int* dstInt, int num_elements, int value, const int offset)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < num_elements )\n"
- " {\n"
- " dstInt[ offset+gIdx ] = value;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void FillFloatKernel(__global float* dstFloat, int num_elements, float value, const int offset)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < num_elements )\n"
- " {\n"
- " dstFloat[ offset+gIdx ] = value;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void FillUnsignedIntKernel(__global unsigned int* dstInt, const int num, const unsigned int value, const int offset)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < num )\n"
- " {\n"
- " dstInt[ offset+gIdx ] = value;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void FillInt2Kernel(__global int2* dstInt2, const int num, const int2 value, const int offset)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < num )\n"
- " {\n"
- " dstInt2[ gIdx + offset] = make_int2( value.x, value.y );\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(64,1,1)))\n"
- "void FillInt4Kernel(__global int4* dstInt4, const int num, const int4 value, const int offset)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < num )\n"
- " {\n"
- " dstInt4[ offset+gIdx ] = value;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl
deleted file mode 100644
index c9da79854a..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanFloat4Kernels.cl
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-
-// takahiro end
-#define WG_SIZE 128
-#define m_numElems x
-#define m_numBlocks y
-#define m_numScanBlocks z
-
-/*typedef struct
-{
- uint m_numElems;
- uint m_numBlocks;
- uint m_numScanBlocks;
- uint m_padding[1];
-} ConstBuffer;
-*/
-
-float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)
-{
- float4 blocksum;
- int offset = 1;
- for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
- {
- GROUP_LDS_BARRIER;
- for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
- {
- int ai = offset*(2*iIdx+1)-1;
- int bi = offset*(2*iIdx+2)-1;
- data[bi] += data[ai];
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx == 0 )
- {
- blocksum = data[ n-1 ];
- data[ n-1 ] = 0;
- }
-
- GROUP_LDS_BARRIER;
-
- offset >>= 1;
- for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
- {
- GROUP_LDS_BARRIER;
- for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
- {
- int ai = offset*(2*iIdx+1)-1;
- int bi = offset*(2*iIdx+2)-1;
- float4 temp = data[ai];
- data[ai] = data[bi];
- data[bi] += temp;
- }
- }
- GROUP_LDS_BARRIER;
-
- return blocksum;
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)
-{
- __local float4 ldsData[WG_SIZE*2];
-
- int gIdx = GET_GLOBAL_IDX;
- int lIdx = GET_LOCAL_IDX;
-
- ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
- ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
-
- float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
-
- if( lIdx == 0 )
- sumBuffer[GET_GROUP_IDX] = sum;
-
- if( (2*gIdx) < cb.m_numElems )
- {
- dst[2*gIdx] = ldsData[2*lIdx];
- }
- if( (2*gIdx + 1) < cb.m_numElems )
- {
- dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
- }
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)
-{
- const u32 blockSize = WG_SIZE*2;
-
- int myIdx = GET_GROUP_IDX+1;
- int lIdx = GET_LOCAL_IDX;
-
- float4 iBlockSum = blockSum[myIdx];
-
- int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
- for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
- {
- dst[i] += iBlockSum;
- }
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void TopLevelScanKernel(__global float4* dst, uint4 cb)
-{
- __local float4 ldsData[2048];
- int gIdx = GET_GLOBAL_IDX;
- int lIdx = GET_LOCAL_IDX;
- int lSize = GET_GROUP_SIZE;
-
- for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
- {
- ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
- }
-
- GROUP_LDS_BARRIER;
-
- float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
-
- for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
- {
- dst[i] = ldsData[i];
- }
-
- if( gIdx == 0 )
- {
- dst[cb.m_numBlocks] = sum;
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl
deleted file mode 100644
index 963cc1e48e..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernels.cl
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-
-// takahiro end
-#define WG_SIZE 128
-#define m_numElems x
-#define m_numBlocks y
-#define m_numScanBlocks z
-
-/*typedef struct
-{
- uint m_numElems;
- uint m_numBlocks;
- uint m_numScanBlocks;
- uint m_padding[1];
-} ConstBuffer;
-*/
-
-u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)
-{
- u32 blocksum;
- int offset = 1;
- for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)
- {
- GROUP_LDS_BARRIER;
- for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)
- {
- int ai = offset*(2*iIdx+1)-1;
- int bi = offset*(2*iIdx+2)-1;
- data[bi] += data[ai];
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx == 0 )
- {
- blocksum = data[ n-1 ];
- data[ n-1 ] = 0;
- }
-
- GROUP_LDS_BARRIER;
-
- offset >>= 1;
- for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )
- {
- GROUP_LDS_BARRIER;
- for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )
- {
- int ai = offset*(2*iIdx+1)-1;
- int bi = offset*(2*iIdx+2)-1;
- u32 temp = data[ai];
- data[ai] = data[bi];
- data[bi] += temp;
- }
- }
- GROUP_LDS_BARRIER;
-
- return blocksum;
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,
- uint4 cb)
-{
- __local u32 ldsData[WG_SIZE*2];
-
- int gIdx = GET_GLOBAL_IDX;
- int lIdx = GET_LOCAL_IDX;
-
- ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;
- ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;
-
- u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);
-
- if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;
-
- if( (2*gIdx) < cb.m_numElems )
- {
- dst[2*gIdx] = ldsData[2*lIdx];
- }
- if( (2*gIdx + 1) < cb.m_numElems )
- {
- dst[2*gIdx + 1] = ldsData[2*lIdx + 1];
- }
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)
-{
- const u32 blockSize = WG_SIZE*2;
-
- int myIdx = GET_GROUP_IDX+1;
- int lIdx = GET_LOCAL_IDX;
-
- u32 iBlockSum = blockSum[myIdx];
-
- int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);
- for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)
- {
- dst[i] += iBlockSum;
- }
-}
-
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-__kernel
-void TopLevelScanKernel(__global u32* dst, uint4 cb)
-{
- __local u32 ldsData[2048];
- int gIdx = GET_GLOBAL_IDX;
- int lIdx = GET_LOCAL_IDX;
- int lSize = GET_GROUP_SIZE;
-
- for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )
- {
- ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;
- }
-
- GROUP_LDS_BARRIER;
-
- u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);
-
- for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )
- {
- dst[i] = ldsData[i];
- }
-
- if( gIdx == 0 )
- {
- dst[cb.m_numBlocks] = sum;
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
deleted file mode 100644
index fc5e7b865c..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsCL.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* prefixScanKernelsCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "// takahiro end\n"
- "#define WG_SIZE 128 \n"
- "#define m_numElems x\n"
- "#define m_numBlocks y\n"
- "#define m_numScanBlocks z\n"
- "/*typedef struct\n"
- "{\n"
- " uint m_numElems;\n"
- " uint m_numBlocks;\n"
- " uint m_numScanBlocks;\n"
- " uint m_padding[1];\n"
- "} ConstBuffer;\n"
- "*/\n"
- "u32 ScanExclusive(__local u32* data, u32 n, int lIdx, int lSize)\n"
- "{\n"
- " u32 blocksum;\n"
- " int offset = 1;\n"
- " for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
- " {\n"
- " GROUP_LDS_BARRIER;\n"
- " for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
- " {\n"
- " int ai = offset*(2*iIdx+1)-1;\n"
- " int bi = offset*(2*iIdx+2)-1;\n"
- " data[bi] += data[ai];\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx == 0 )\n"
- " {\n"
- " blocksum = data[ n-1 ];\n"
- " data[ n-1 ] = 0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " offset >>= 1;\n"
- " for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
- " {\n"
- " GROUP_LDS_BARRIER;\n"
- " for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
- " {\n"
- " int ai = offset*(2*iIdx+1)-1;\n"
- " int bi = offset*(2*iIdx+2)-1;\n"
- " u32 temp = data[ai];\n"
- " data[ai] = data[bi];\n"
- " data[bi] += temp;\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " return blocksum;\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void LocalScanKernel(__global u32* dst, __global u32 *src, __global u32 *sumBuffer,\n"
- " uint4 cb)\n"
- "{\n"
- " __local u32 ldsData[WG_SIZE*2];\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
- " ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
- " u32 sum = ScanExclusive(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
- " if( lIdx == 0 ) sumBuffer[GET_GROUP_IDX] = sum;\n"
- " if( (2*gIdx) < cb.m_numElems )\n"
- " {\n"
- " dst[2*gIdx] = ldsData[2*lIdx];\n"
- " }\n"
- " if( (2*gIdx + 1) < cb.m_numElems )\n"
- " {\n"
- " dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void AddOffsetKernel(__global u32 *dst, __global u32 *blockSum, uint4 cb)\n"
- "{\n"
- " const u32 blockSize = WG_SIZE*2;\n"
- " int myIdx = GET_GROUP_IDX+1;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " u32 iBlockSum = blockSum[myIdx];\n"
- " int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
- " for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
- " {\n"
- " dst[i] += iBlockSum;\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void TopLevelScanKernel(__global u32* dst, uint4 cb)\n"
- "{\n"
- " __local u32 ldsData[2048];\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " int lSize = GET_GROUP_SIZE;\n"
- " for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
- " {\n"
- " ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " u32 sum = ScanExclusive(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
- " for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
- " {\n"
- " dst[i] = ldsData[i];\n"
- " }\n"
- " if( gIdx == 0 )\n"
- " {\n"
- " dst[cb.m_numBlocks] = sum;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
deleted file mode 100644
index 15d1bc5195..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/PrefixScanKernelsFloat4CL.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* prefixScanKernelsFloat4CL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "// takahiro end\n"
- "#define WG_SIZE 128 \n"
- "#define m_numElems x\n"
- "#define m_numBlocks y\n"
- "#define m_numScanBlocks z\n"
- "/*typedef struct\n"
- "{\n"
- " uint m_numElems;\n"
- " uint m_numBlocks;\n"
- " uint m_numScanBlocks;\n"
- " uint m_padding[1];\n"
- "} ConstBuffer;\n"
- "*/\n"
- "float4 ScanExclusiveFloat4(__local float4* data, u32 n, int lIdx, int lSize)\n"
- "{\n"
- " float4 blocksum;\n"
- " int offset = 1;\n"
- " for(int nActive=n>>1; nActive>0; nActive>>=1, offset<<=1)\n"
- " {\n"
- " GROUP_LDS_BARRIER;\n"
- " for(int iIdx=lIdx; iIdx<nActive; iIdx+=lSize)\n"
- " {\n"
- " int ai = offset*(2*iIdx+1)-1;\n"
- " int bi = offset*(2*iIdx+2)-1;\n"
- " data[bi] += data[ai];\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx == 0 )\n"
- " {\n"
- " blocksum = data[ n-1 ];\n"
- " data[ n-1 ] = 0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " offset >>= 1;\n"
- " for(int nActive=1; nActive<n; nActive<<=1, offset>>=1 )\n"
- " {\n"
- " GROUP_LDS_BARRIER;\n"
- " for( int iIdx = lIdx; iIdx<nActive; iIdx += lSize )\n"
- " {\n"
- " int ai = offset*(2*iIdx+1)-1;\n"
- " int bi = offset*(2*iIdx+2)-1;\n"
- " float4 temp = data[ai];\n"
- " data[ai] = data[bi];\n"
- " data[bi] += temp;\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " return blocksum;\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void LocalScanKernel(__global float4* dst, __global float4* src, __global float4* sumBuffer, uint4 cb)\n"
- "{\n"
- " __local float4 ldsData[WG_SIZE*2];\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " ldsData[2*lIdx] = ( 2*gIdx < cb.m_numElems )? src[2*gIdx]: 0;\n"
- " ldsData[2*lIdx + 1] = ( 2*gIdx+1 < cb.m_numElems )? src[2*gIdx + 1]: 0;\n"
- " float4 sum = ScanExclusiveFloat4(ldsData, WG_SIZE*2, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
- " if( lIdx == 0 ) \n"
- " sumBuffer[GET_GROUP_IDX] = sum;\n"
- " if( (2*gIdx) < cb.m_numElems )\n"
- " {\n"
- " dst[2*gIdx] = ldsData[2*lIdx];\n"
- " }\n"
- " if( (2*gIdx + 1) < cb.m_numElems )\n"
- " {\n"
- " dst[2*gIdx + 1] = ldsData[2*lIdx + 1];\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void AddOffsetKernel(__global float4* dst, __global float4* blockSum, uint4 cb)\n"
- "{\n"
- " const u32 blockSize = WG_SIZE*2;\n"
- " int myIdx = GET_GROUP_IDX+1;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " float4 iBlockSum = blockSum[myIdx];\n"
- " int endValue = min((myIdx+1)*(blockSize), cb.m_numElems);\n"
- " for(int i=myIdx*blockSize+lIdx; i<endValue; i+=GET_GROUP_SIZE)\n"
- " {\n"
- " dst[i] += iBlockSum;\n"
- " }\n"
- "}\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "__kernel\n"
- "void TopLevelScanKernel(__global float4* dst, uint4 cb)\n"
- "{\n"
- " __local float4 ldsData[2048];\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " int lSize = GET_GROUP_SIZE;\n"
- " for(int i=lIdx; i<cb.m_numScanBlocks; i+=lSize )\n"
- " {\n"
- " ldsData[i] = (i<cb.m_numBlocks)? dst[i]:0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " float4 sum = ScanExclusiveFloat4(ldsData, cb.m_numScanBlocks, GET_LOCAL_IDX, GET_GROUP_SIZE);\n"
- " for(int i=lIdx; i<cb.m_numBlocks; i+=lSize )\n"
- " {\n"
- " dst[i] = ldsData[i];\n"
- " }\n"
- " if( gIdx == 0 )\n"
- " {\n"
- " dst[cb.m_numBlocks] = sum;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl
deleted file mode 100644
index 7402e2f3b3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32Kernels.cl
+++ /dev/null
@@ -1,1071 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Author Takahiro Harada
-
-
-//#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-
-typedef unsigned int u32;
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AtomAdd(x, value) atom_add(&(x), value)
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-
-#define make_uint4 (uint4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-#define WG_SIZE 64
-#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)
-#define BITS_PER_PASS 4
-#define NUM_BUCKET (1<<BITS_PER_PASS)
-typedef uchar u8;
-
-// this isn't optimization for VLIW. But just reducing writes.
-#define USE_2LEVEL_REDUCE 1
-
-//#define CHECK_BOUNDARY 1
-
-//#define NV_GPU 1
-
-
-// Cypress
-#define nPerWI 16
-// Cayman
-//#define nPerWI 20
-
-#define m_n x
-#define m_nWGs y
-#define m_startBit z
-#define m_nBlocksPerWG w
-
-/*
-typedef struct
-{
- int m_n;
- int m_nWGs;
- int m_startBit;
- int m_nBlocksPerWG;
-} ConstBuffer;
-*/
-
-typedef struct
-{
- unsigned int m_key;
- unsigned int m_value;
-} SortDataCL;
-
-
-uint prefixScanVectorEx( uint4* data )
-{
- u32 sum = 0;
- u32 tmp = data[0].x;
- data[0].x = sum;
- sum += tmp;
- tmp = data[0].y;
- data[0].y = sum;
- sum += tmp;
- tmp = data[0].z;
- data[0].z = sum;
- sum += tmp;
- tmp = data[0].w;
- data[0].w = sum;
- sum += tmp;
- return sum;
-}
-
-u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )
-{
- { // Set data
- sorterSharedMemory[lIdx] = 0;
- sorterSharedMemory[lIdx+wgSize] = pData;
- }
-
- GROUP_LDS_BARRIER;
-
- { // Prefix sum
- int idx = 2*lIdx + (wgSize+1);
-#if defined(USE_2LEVEL_REDUCE)
- if( lIdx < 64 )
- {
- u32 u0, u1, u2;
- u0 = sorterSharedMemory[idx-3];
- u1 = sorterSharedMemory[idx-2];
- u2 = sorterSharedMemory[idx-1];
- AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
- GROUP_MEM_FENCE;
-
- u0 = sorterSharedMemory[idx-12];
- u1 = sorterSharedMemory[idx-8];
- u2 = sorterSharedMemory[idx-4];
- AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
- GROUP_MEM_FENCE;
-
- u0 = sorterSharedMemory[idx-48];
- u1 = sorterSharedMemory[idx-32];
- u2 = sorterSharedMemory[idx-16];
- AtomAdd( sorterSharedMemory[idx], u0+u1+u2 );
- GROUP_MEM_FENCE;
- if( wgSize > 64 )
- {
- sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
- GROUP_MEM_FENCE;
- }
-
- sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
- GROUP_MEM_FENCE;
- }
-#else
- if( lIdx < 64 )
- {
- sorterSharedMemory[idx] += sorterSharedMemory[idx-1];
- GROUP_MEM_FENCE;
- sorterSharedMemory[idx] += sorterSharedMemory[idx-2];
- GROUP_MEM_FENCE;
- sorterSharedMemory[idx] += sorterSharedMemory[idx-4];
- GROUP_MEM_FENCE;
- sorterSharedMemory[idx] += sorterSharedMemory[idx-8];
- GROUP_MEM_FENCE;
- sorterSharedMemory[idx] += sorterSharedMemory[idx-16];
- GROUP_MEM_FENCE;
- sorterSharedMemory[idx] += sorterSharedMemory[idx-32];
- GROUP_MEM_FENCE;
- if( wgSize > 64 )
- {
- sorterSharedMemory[idx] += sorterSharedMemory[idx-64];
- GROUP_MEM_FENCE;
- }
-
- sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];
- GROUP_MEM_FENCE;
- }
-#endif
- }
-
- GROUP_LDS_BARRIER;
-
- *totalSum = sorterSharedMemory[wgSize*2-1];
- u32 addValue = sorterSharedMemory[lIdx+wgSize-1];
- return addValue;
-}
-
-//__attribute__((reqd_work_group_size(128,1,1)))
-uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
-{
- u32 s4 = prefixScanVectorEx( &pData );
- u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );
- return pData + make_uint4( rank, rank, rank, rank );
-}
-
-
-//__attribute__((reqd_work_group_size(64,1,1)))
-uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )
-{
- u32 s4 = prefixScanVectorEx( &pData );
- u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );
- return pData + make_uint4( rank, rank, rank, rank );
-}
-
-u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}
-
-u32 bit8Scan(u32 v)
-{
- return (v<<8) + (v<<16) + (v<<24);
-}
-
-//===
-
-
-
-
-#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )
-{
- __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 lIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
- const int startBit = cb.m_startBit;
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- for(int i=0; i<NUM_BUCKET; i++)
- {
- MY_HISTOGRAM(i) = 0;
- }
-
- GROUP_LDS_BARRIER;
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
- u32 localKey;
-
- int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
-
- int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
- {
- // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
- // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
- // AMD: AtomInc performs better while NV prefers ++
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
- {
-#if defined(CHECK_BOUNDARY)
- if( addr+i < n )
-#endif
- {
- localKey = (gSrc[addr+i]>>startBit) & 0xf;
-#if defined(NV_GPU)
- MY_HISTOGRAM( localKey )++;
-#else
- AtomInc( MY_HISTOGRAM( localKey ) );
-#endif
- }
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx < NUM_BUCKET )
- {
- u32 sum = 0;
- for(int i=0; i<GET_GROUP_SIZE; i++)
- {
- sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
- }
- histogramOut[lIdx*nWGs+wgIdx] = sum;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )
-{
- __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 lIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
- const int startBit = cb.m_startBit;
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- for(int i=0; i<NUM_BUCKET; i++)
- {
- MY_HISTOGRAM(i) = 0;
- }
-
- GROUP_LDS_BARRIER;
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
- u32 localKey;
-
- int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
-
- int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
- {
- // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD
- // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops
- // AMD: AtomInc performs better while NV prefers ++
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
- {
-#if defined(CHECK_BOUNDARY)
- if( addr+i < n )
-#endif
- {
- localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;
-#if defined(NV_GPU)
- MY_HISTOGRAM( localKey )++;
-#else
- AtomInc( MY_HISTOGRAM( localKey ) );
-#endif
- }
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx < NUM_BUCKET )
- {
- u32 sum = 0;
- for(int i=0; i<GET_GROUP_SIZE; i++)
- {
- sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];
- }
- histogramOut[lIdx*nWGs+wgIdx] = sum;
- }
-}
-
-#define nPerLane (nPerWI/4)
-
-// NUM_BUCKET*nWGs < 128*nPerWI
-__kernel
-__attribute__((reqd_work_group_size(128,1,1)))
-void PrefixScanKernel( __global u32* wHistogram1, int4 cb )
-{
- __local u32 ldsTopScanData[128*2];
-
- u32 lIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- const int nWGs = cb.m_nWGs;
-
- u32 data[nPerWI];
- for(int i=0; i<nPerWI; i++)
- {
- data[i] = 0;
- if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )
- data[i] = wHistogram1[nPerWI*lIdx+i];
- }
-
- uint4 myData = make_uint4(0,0,0,0);
-
- for(int i=0; i<nPerLane; i++)
- {
- myData.x += data[nPerLane*0+i];
- myData.y += data[nPerLane*1+i];
- myData.z += data[nPerLane*2+i];
- myData.w += data[nPerLane*3+i];
- }
-
- uint totalSum;
- uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );
-
-// for(int j=0; j<4; j++) // somehow it introduces a lot of branches
- { int j = 0;
- u32 sum = 0;
- for(int i=0; i<nPerLane; i++)
- {
- u32 tmp = data[nPerLane*j+i];
- data[nPerLane*j+i] = sum;
- sum += tmp;
- }
- }
- { int j = 1;
- u32 sum = 0;
- for(int i=0; i<nPerLane; i++)
- {
- u32 tmp = data[nPerLane*j+i];
- data[nPerLane*j+i] = sum;
- sum += tmp;
- }
- }
- { int j = 2;
- u32 sum = 0;
- for(int i=0; i<nPerLane; i++)
- {
- u32 tmp = data[nPerLane*j+i];
- data[nPerLane*j+i] = sum;
- sum += tmp;
- }
- }
- { int j = 3;
- u32 sum = 0;
- for(int i=0; i<nPerLane; i++)
- {
- u32 tmp = data[nPerLane*j+i];
- data[nPerLane*j+i] = sum;
- sum += tmp;
- }
- }
-
- for(int i=0; i<nPerLane; i++)
- {
- data[nPerLane*0+i] += scanned.x;
- data[nPerLane*1+i] += scanned.y;
- data[nPerLane*2+i] += scanned.z;
- data[nPerLane*3+i] += scanned.w;
- }
-
- for(int i=0; i<nPerWI; i++)
- {
- int index = nPerWI*lIdx+i;
- if (index < NUM_BUCKET*nWGs)
- wHistogram1[nPerWI*lIdx+i] = data[i];
- }
-}
-
-// 4 scan, 4 exchange
-void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
-{
- for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)
- {
- u32 mask = (1<<bitIdx);
- uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );
- uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );
- u32 total;
- prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );
- {
- uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);
- uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );
- dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );
-
- GROUP_LDS_BARRIER;
-
- ldsSortData[dstAddr.x] = sortData[0];
- ldsSortData[dstAddr.y] = sortData[1];
- ldsSortData[dstAddr.z] = sortData[2];
- ldsSortData[dstAddr.w] = sortData[3];
-
- GROUP_LDS_BARRIER;
-
- sortData[0] = ldsSortData[localAddr.x];
- sortData[1] = ldsSortData[localAddr.y];
- sortData[2] = ldsSortData[localAddr.z];
- sortData[3] = ldsSortData[localAddr.w];
-
- GROUP_LDS_BARRIER;
- }
- }
-}
-
-// 2 scan, 2 exchange
-void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)
-{
- for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
- {
- uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3,
- (sortData[1]>>(startBit+ibit)) & 0x3,
- (sortData[2]>>(startBit+ibit)) & 0x3,
- (sortData[3]>>(startBit+ibit)) & 0x3);
-
- u32 key4;
- u32 sKeyPacked[4] = { 0, 0, 0, 0 };
- {
- sKeyPacked[0] |= 1<<(8*b.x);
- sKeyPacked[1] |= 1<<(8*b.y);
- sKeyPacked[2] |= 1<<(8*b.z);
- sKeyPacked[3] |= 1<<(8*b.w);
-
- key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
- }
-
- u32 rankPacked;
- u32 sumPacked;
- {
- rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
- }
-
- GROUP_LDS_BARRIER;
-
- u32 newOffset[4] = { 0,0,0,0 };
- {
- u32 sumScanned = bit8Scan( sumPacked );
-
- u32 scannedKeys[4];
- scannedKeys[0] = 1<<(8*b.x);
- scannedKeys[1] = 1<<(8*b.y);
- scannedKeys[2] = 1<<(8*b.z);
- scannedKeys[3] = 1<<(8*b.w);
- { // 4 scans at once
- u32 sum4 = 0;
- for(int ie=0; ie<4; ie++)
- {
- u32 tmp = scannedKeys[ie];
- scannedKeys[ie] = sum4;
- sum4 += tmp;
- }
- }
-
- {
- u32 sumPlusRank = sumScanned + rankPacked;
- { u32 ie = b.x;
- scannedKeys[0] += sumPlusRank;
- newOffset[0] = unpack4Key( scannedKeys[0], ie );
- }
- { u32 ie = b.y;
- scannedKeys[1] += sumPlusRank;
- newOffset[1] = unpack4Key( scannedKeys[1], ie );
- }
- { u32 ie = b.z;
- scannedKeys[2] += sumPlusRank;
- newOffset[2] = unpack4Key( scannedKeys[2], ie );
- }
- { u32 ie = b.w;
- scannedKeys[3] += sumPlusRank;
- newOffset[3] = unpack4Key( scannedKeys[3], ie );
- }
- }
- }
-
-
- GROUP_LDS_BARRIER;
-
- {
- ldsSortData[newOffset[0]] = sortData[0];
- ldsSortData[newOffset[1]] = sortData[1];
- ldsSortData[newOffset[2]] = sortData[2];
- ldsSortData[newOffset[3]] = sortData[3];
-
- GROUP_LDS_BARRIER;
-
- u32 dstAddr = 4*lIdx;
- sortData[0] = ldsSortData[dstAddr+0];
- sortData[1] = ldsSortData[dstAddr+1];
- sortData[2] = ldsSortData[dstAddr+2];
- sortData[3] = ldsSortData[dstAddr+3];
-
- GROUP_LDS_BARRIER;
- }
- }
-}
-
-#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )
-{
- __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
- __local u32 localHistogramToCarry[NUM_BUCKET];
- __local u32 localHistogram[NUM_BUCKET*2];
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 lIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
-
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int startBit = cb.m_startBit;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- if( lIdx < (NUM_BUCKET) )
- {
- localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
- }
-
- GROUP_LDS_BARRIER;
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
-
- int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
-
- int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
- {
- u32 myHistogram = 0;
-
- u32 sortData[ELEMENTS_PER_WORK_ITEM];
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
-#if defined(CHECK_BOUNDARY)
- sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;
-#else
- sortData[i] = gSrc[ addr+i ];
-#endif
-
- sort4Bits(sortData, startBit, lIdx, ldsSortData);
-
- u32 keys[ELEMENTS_PER_WORK_ITEM];
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
- keys[i] = (sortData[i]>>startBit) & 0xf;
-
- { // create histogram
- u32 setIdx = lIdx/16;
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[lIdx] = 0;
- }
- ldsSortData[lIdx] = 0;
- GROUP_LDS_BARRIER;
-
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
-#if defined(CHECK_BOUNDARY)
- if( addr+i < n )
-#endif
-
-#if defined(NV_GPU)
- SET_HISTOGRAM( setIdx, keys[i] )++;
-#else
- AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
-#endif
-
- GROUP_LDS_BARRIER;
-
- uint hIdx = NUM_BUCKET+lIdx;
- if( lIdx < NUM_BUCKET )
- {
- u32 sum = 0;
- for(int i=0; i<WG_SIZE/16; i++)
- {
- sum += SET_HISTOGRAM( i, lIdx );
- }
- myHistogram = sum;
- localHistogram[hIdx] = sum;
- }
- GROUP_LDS_BARRIER;
-
-#if defined(USE_2LEVEL_REDUCE)
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[hIdx] = localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
-
- u32 u0, u1, u2;
- u0 = localHistogram[hIdx-3];
- u1 = localHistogram[hIdx-2];
- u2 = localHistogram[hIdx-1];
- AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
- GROUP_MEM_FENCE;
- u0 = localHistogram[hIdx-12];
- u1 = localHistogram[hIdx-8];
- u2 = localHistogram[hIdx-4];
- AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
- GROUP_MEM_FENCE;
- }
-#else
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[hIdx] = localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-2];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-4];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-8];
- GROUP_MEM_FENCE;
- }
-#endif
- GROUP_LDS_BARRIER;
- }
-
- {
- for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
- {
- int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
- int binIdx = keys[ie];
- int groupOffset = localHistogramToCarry[binIdx];
- int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
-#if defined(CHECK_BOUNDARY)
- if( addr+ie < n )
-#endif
- gDst[ groupOffset + myIdx ] = sortData[ie];
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx < NUM_BUCKET )
- {
- localHistogramToCarry[lIdx] += myHistogram;
- }
- GROUP_LDS_BARRIER;
- }
-}
-
-// 2 scan, 2 exchange
-void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)
-{
- for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)
- {
- uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3,
- (sortData[1]>>(startBit+ibit)) & 0x3,
- (sortData[2]>>(startBit+ibit)) & 0x3,
- (sortData[3]>>(startBit+ibit)) & 0x3);
-
- u32 key4;
- u32 sKeyPacked[4] = { 0, 0, 0, 0 };
- {
- sKeyPacked[0] |= 1<<(8*b.x);
- sKeyPacked[1] |= 1<<(8*b.y);
- sKeyPacked[2] |= 1<<(8*b.z);
- sKeyPacked[3] |= 1<<(8*b.w);
-
- key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];
- }
-
- u32 rankPacked;
- u32 sumPacked;
- {
- rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );
- }
-
- GROUP_LDS_BARRIER;
-
- u32 newOffset[4] = { 0,0,0,0 };
- {
- u32 sumScanned = bit8Scan( sumPacked );
-
- u32 scannedKeys[4];
- scannedKeys[0] = 1<<(8*b.x);
- scannedKeys[1] = 1<<(8*b.y);
- scannedKeys[2] = 1<<(8*b.z);
- scannedKeys[3] = 1<<(8*b.w);
- { // 4 scans at once
- u32 sum4 = 0;
- for(int ie=0; ie<4; ie++)
- {
- u32 tmp = scannedKeys[ie];
- scannedKeys[ie] = sum4;
- sum4 += tmp;
- }
- }
-
- {
- u32 sumPlusRank = sumScanned + rankPacked;
- { u32 ie = b.x;
- scannedKeys[0] += sumPlusRank;
- newOffset[0] = unpack4Key( scannedKeys[0], ie );
- }
- { u32 ie = b.y;
- scannedKeys[1] += sumPlusRank;
- newOffset[1] = unpack4Key( scannedKeys[1], ie );
- }
- { u32 ie = b.z;
- scannedKeys[2] += sumPlusRank;
- newOffset[2] = unpack4Key( scannedKeys[2], ie );
- }
- { u32 ie = b.w;
- scannedKeys[3] += sumPlusRank;
- newOffset[3] = unpack4Key( scannedKeys[3], ie );
- }
- }
- }
-
-
- GROUP_LDS_BARRIER;
-
- {
- ldsSortData[newOffset[0]] = sortData[0];
- ldsSortData[newOffset[1]] = sortData[1];
- ldsSortData[newOffset[2]] = sortData[2];
- ldsSortData[newOffset[3]] = sortData[3];
-
- ldsSortVal[newOffset[0]] = sortVal[0];
- ldsSortVal[newOffset[1]] = sortVal[1];
- ldsSortVal[newOffset[2]] = sortVal[2];
- ldsSortVal[newOffset[3]] = sortVal[3];
-
- GROUP_LDS_BARRIER;
-
- u32 dstAddr = 4*lIdx;
- sortData[0] = ldsSortData[dstAddr+0];
- sortData[1] = ldsSortData[dstAddr+1];
- sortData[2] = ldsSortData[dstAddr+2];
- sortData[3] = ldsSortData[dstAddr+3];
-
- sortVal[0] = ldsSortVal[dstAddr+0];
- sortVal[1] = ldsSortVal[dstAddr+1];
- sortVal[2] = ldsSortVal[dstAddr+2];
- sortVal[3] = ldsSortVal[dstAddr+3];
-
- GROUP_LDS_BARRIER;
- }
- }
-}
-
-
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
-{
- __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
- __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];
- __local u32 localHistogramToCarry[NUM_BUCKET];
- __local u32 localHistogram[NUM_BUCKET*2];
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 lIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
-
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int startBit = cb.m_startBit;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- if( lIdx < (NUM_BUCKET) )
- {
- localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];
- }
-
- GROUP_LDS_BARRIER;
-
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
-
- int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;
-
- int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)
- {
-
- u32 myHistogram = 0;
-
- int sortData[ELEMENTS_PER_WORK_ITEM];
- int sortVal[ELEMENTS_PER_WORK_ITEM];
-
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
-#if defined(CHECK_BOUNDARY)
- {
- sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;
- sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;
- }
-#else
- {
- sortData[i] = gSrc[ addr+i ].m_key;
- sortVal[i] = gSrc[ addr+i ].m_value;
- }
-#endif
-
- sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);
-
- u32 keys[ELEMENTS_PER_WORK_ITEM];
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
- keys[i] = (sortData[i]>>startBit) & 0xf;
-
- { // create histogram
- u32 setIdx = lIdx/16;
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[lIdx] = 0;
- }
- ldsSortData[lIdx] = 0;
- GROUP_LDS_BARRIER;
-
- for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)
-#if defined(CHECK_BOUNDARY)
- if( addr+i < n )
-#endif
-
-#if defined(NV_GPU)
- SET_HISTOGRAM( setIdx, keys[i] )++;
-#else
- AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );
-#endif
-
- GROUP_LDS_BARRIER;
-
- uint hIdx = NUM_BUCKET+lIdx;
- if( lIdx < NUM_BUCKET )
- {
- u32 sum = 0;
- for(int i=0; i<WG_SIZE/16; i++)
- {
- sum += SET_HISTOGRAM( i, lIdx );
- }
- myHistogram = sum;
- localHistogram[hIdx] = sum;
- }
- GROUP_LDS_BARRIER;
-
-#if defined(USE_2LEVEL_REDUCE)
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[hIdx] = localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
-
- u32 u0, u1, u2;
- u0 = localHistogram[hIdx-3];
- u1 = localHistogram[hIdx-2];
- u2 = localHistogram[hIdx-1];
- AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
- GROUP_MEM_FENCE;
- u0 = localHistogram[hIdx-12];
- u1 = localHistogram[hIdx-8];
- u2 = localHistogram[hIdx-4];
- AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );
- GROUP_MEM_FENCE;
- }
-#else
- if( lIdx < NUM_BUCKET )
- {
- localHistogram[hIdx] = localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-1];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-2];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-4];
- GROUP_MEM_FENCE;
- localHistogram[hIdx] += localHistogram[hIdx-8];
- GROUP_MEM_FENCE;
- }
-#endif
- GROUP_LDS_BARRIER;
- }
-
- {
- for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)
- {
- int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;
- int binIdx = keys[ie];
- int groupOffset = localHistogramToCarry[binIdx];
- int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];
-#if defined(CHECK_BOUNDARY)
- if( addr+ie < n )
- {
- if ((groupOffset + myIdx)<n)
- {
- if (sortData[ie]==sortVal[ie])
- {
-
- SortDataCL tmp;
- tmp.m_key = sortData[ie];
- tmp.m_value = sortVal[ie];
- if (tmp.m_key == tmp.m_value)
- gDst[groupOffset + myIdx ] = tmp;
- }
-
- }
- }
-#else
- if ((groupOffset + myIdx)<n)
- {
- gDst[ groupOffset + myIdx ].m_key = sortData[ie];
- gDst[ groupOffset + myIdx ].m_value = sortVal[ie];
- }
-#endif
- }
- }
-
- GROUP_LDS_BARRIER;
-
- if( lIdx < NUM_BUCKET )
- {
- localHistogramToCarry[lIdx] += myHistogram;
- }
- GROUP_LDS_BARRIER;
- }
-}
-
-
-
-
-
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)
-{
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 realLocalIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
- const int startBit = cb.m_startBit;
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- int counter[NUM_BUCKET];
-
- if (realLocalIdx>0)
- return;
-
- for (int c=0;c<NUM_BUCKET;c++)
- counter[c]=0;
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
-
- int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
- {
- for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
- {
- int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
- {
- int i = addr2+j;
- if( i < n )
- {
- int tableIdx;
- tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1
- gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
- counter[tableIdx] ++;
- }
- }
- }
- }
-
-}
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )
-{
-
- u32 gIdx = GET_GLOBAL_IDX;
- u32 realLocalIdx = GET_LOCAL_IDX;
- u32 wgIdx = GET_GROUP_IDX;
- u32 wgSize = GET_GROUP_SIZE;
- const int startBit = cb.m_startBit;
- const int n = cb.m_n;
- const int nWGs = cb.m_nWGs;
- const int nBlocksPerWG = cb.m_nBlocksPerWG;
-
- int counter[NUM_BUCKET];
-
- if (realLocalIdx>0)
- return;
-
- for (int c=0;c<NUM_BUCKET;c++)
- counter[c]=0;
-
- const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;
-
- int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;
-
- for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)
- {
- for (int lIdx=0;lIdx<WG_SIZE;lIdx++)
- {
- int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;
-
- for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)
- {
- int i = addr2+j;
- if( i < n )
- {
- int tableIdx;
- tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1
- gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];
- counter[tableIdx] ++;
- }
- }
- }
- }
-
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h b/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
deleted file mode 100644
index fb4bdda303..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/ParallelPrimitives/kernels/RadixSort32KernelsCL.h
+++ /dev/null
@@ -1,909 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* radixSort32KernelsCL =
- "/*\n"
- "Bullet Continuous Collision Detection and Physics Library\n"
- "Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org\n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Author Takahiro Harada\n"
- "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "typedef unsigned int u32;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_uint4 (uint4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define WG_SIZE 64\n"
- "#define ELEMENTS_PER_WORK_ITEM (256/WG_SIZE)\n"
- "#define BITS_PER_PASS 4\n"
- "#define NUM_BUCKET (1<<BITS_PER_PASS)\n"
- "typedef uchar u8;\n"
- "// this isn't optimization for VLIW. But just reducing writes. \n"
- "#define USE_2LEVEL_REDUCE 1\n"
- "//#define CHECK_BOUNDARY 1\n"
- "//#define NV_GPU 1\n"
- "// Cypress\n"
- "#define nPerWI 16\n"
- "// Cayman\n"
- "//#define nPerWI 20\n"
- "#define m_n x\n"
- "#define m_nWGs y\n"
- "#define m_startBit z\n"
- "#define m_nBlocksPerWG w\n"
- "/*\n"
- "typedef struct\n"
- "{\n"
- " int m_n;\n"
- " int m_nWGs;\n"
- " int m_startBit;\n"
- " int m_nBlocksPerWG;\n"
- "} ConstBuffer;\n"
- "*/\n"
- "typedef struct\n"
- "{\n"
- " unsigned int m_key;\n"
- " unsigned int m_value;\n"
- "} SortDataCL;\n"
- "uint prefixScanVectorEx( uint4* data )\n"
- "{\n"
- " u32 sum = 0;\n"
- " u32 tmp = data[0].x;\n"
- " data[0].x = sum;\n"
- " sum += tmp;\n"
- " tmp = data[0].y;\n"
- " data[0].y = sum;\n"
- " sum += tmp;\n"
- " tmp = data[0].z;\n"
- " data[0].z = sum;\n"
- " sum += tmp;\n"
- " tmp = data[0].w;\n"
- " data[0].w = sum;\n"
- " sum += tmp;\n"
- " return sum;\n"
- "}\n"
- "u32 localPrefixSum( u32 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory, int wgSize /*64 or 128*/ )\n"
- "{\n"
- " { // Set data\n"
- " sorterSharedMemory[lIdx] = 0;\n"
- " sorterSharedMemory[lIdx+wgSize] = pData;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " { // Prefix sum\n"
- " int idx = 2*lIdx + (wgSize+1);\n"
- "#if defined(USE_2LEVEL_REDUCE)\n"
- " if( lIdx < 64 )\n"
- " {\n"
- " u32 u0, u1, u2;\n"
- " u0 = sorterSharedMemory[idx-3];\n"
- " u1 = sorterSharedMemory[idx-2];\n"
- " u2 = sorterSharedMemory[idx-1];\n"
- " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
- " GROUP_MEM_FENCE;\n"
- " u0 = sorterSharedMemory[idx-12];\n"
- " u1 = sorterSharedMemory[idx-8];\n"
- " u2 = sorterSharedMemory[idx-4];\n"
- " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
- " GROUP_MEM_FENCE;\n"
- " u0 = sorterSharedMemory[idx-48];\n"
- " u1 = sorterSharedMemory[idx-32];\n"
- " u2 = sorterSharedMemory[idx-16];\n"
- " AtomAdd( sorterSharedMemory[idx], u0+u1+u2 ); \n"
- " GROUP_MEM_FENCE;\n"
- " if( wgSize > 64 )\n"
- " {\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- " sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#else\n"
- " if( lIdx < 64 )\n"
- " {\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-2]; \n"
- " GROUP_MEM_FENCE;\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-4];\n"
- " GROUP_MEM_FENCE;\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-8];\n"
- " GROUP_MEM_FENCE;\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-16];\n"
- " GROUP_MEM_FENCE;\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-32];\n"
- " GROUP_MEM_FENCE;\n"
- " if( wgSize > 64 )\n"
- " {\n"
- " sorterSharedMemory[idx] += sorterSharedMemory[idx-64];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- " sorterSharedMemory[idx-1] += sorterSharedMemory[idx-2];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#endif\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " *totalSum = sorterSharedMemory[wgSize*2-1];\n"
- " u32 addValue = sorterSharedMemory[lIdx+wgSize-1];\n"
- " return addValue;\n"
- "}\n"
- "//__attribute__((reqd_work_group_size(128,1,1)))\n"
- "uint4 localPrefixSum128V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
- "{\n"
- " u32 s4 = prefixScanVectorEx( &pData );\n"
- " u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 128 );\n"
- " return pData + make_uint4( rank, rank, rank, rank );\n"
- "}\n"
- "//__attribute__((reqd_work_group_size(64,1,1)))\n"
- "uint4 localPrefixSum64V( uint4 pData, uint lIdx, uint* totalSum, __local u32* sorterSharedMemory )\n"
- "{\n"
- " u32 s4 = prefixScanVectorEx( &pData );\n"
- " u32 rank = localPrefixSum( s4, lIdx, totalSum, sorterSharedMemory, 64 );\n"
- " return pData + make_uint4( rank, rank, rank, rank );\n"
- "}\n"
- "u32 unpack4Key( u32 key, int keyIdx ){ return (key>>(keyIdx*8)) & 0xff;}\n"
- "u32 bit8Scan(u32 v)\n"
- "{\n"
- " return (v<<8) + (v<<16) + (v<<24);\n"
- "}\n"
- "//===\n"
- "#define MY_HISTOGRAM(idx) localHistogramMat[(idx)*WG_SIZE+lIdx]\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void StreamCountKernel( __global u32* gSrc, __global u32* histogramOut, int4 cb )\n"
- "{\n"
- " __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 lIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " for(int i=0; i<NUM_BUCKET; i++)\n"
- " {\n"
- " MY_HISTOGRAM(i) = 0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " u32 localKey;\n"
- " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
- " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
- " {\n"
- " // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
- " // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
- " // AMD: AtomInc performs better while NV prefers ++\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- " {\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+i < n )\n"
- "#endif\n"
- " {\n"
- " localKey = (gSrc[addr+i]>>startBit) & 0xf;\n"
- "#if defined(NV_GPU)\n"
- " MY_HISTOGRAM( localKey )++;\n"
- "#else\n"
- " AtomInc( MY_HISTOGRAM( localKey ) );\n"
- "#endif\n"
- " }\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<GET_GROUP_SIZE; i++)\n"
- " {\n"
- " sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
- " }\n"
- " histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void StreamCountSortDataKernel( __global SortDataCL* gSrc, __global u32* histogramOut, int4 cb )\n"
- "{\n"
- " __local u32 localHistogramMat[NUM_BUCKET*WG_SIZE];\n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 lIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " for(int i=0; i<NUM_BUCKET; i++)\n"
- " {\n"
- " MY_HISTOGRAM(i) = 0;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " u32 localKey;\n"
- " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
- " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
- " {\n"
- " // MY_HISTOGRAM( localKeys.x ) ++ is much expensive than atomic add as it requires read and write while atomics can just add on AMD\n"
- " // Using registers didn't perform well. It seems like use localKeys to address requires a lot of alu ops\n"
- " // AMD: AtomInc performs better while NV prefers ++\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- " {\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+i < n )\n"
- "#endif\n"
- " {\n"
- " localKey = (gSrc[addr+i].m_key>>startBit) & 0xf;\n"
- "#if defined(NV_GPU)\n"
- " MY_HISTOGRAM( localKey )++;\n"
- "#else\n"
- " AtomInc( MY_HISTOGRAM( localKey ) );\n"
- "#endif\n"
- " }\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<GET_GROUP_SIZE; i++)\n"
- " {\n"
- " sum += localHistogramMat[lIdx*WG_SIZE+(i+lIdx)%GET_GROUP_SIZE];\n"
- " }\n"
- " histogramOut[lIdx*nWGs+wgIdx] = sum;\n"
- " }\n"
- "}\n"
- "#define nPerLane (nPerWI/4)\n"
- "// NUM_BUCKET*nWGs < 128*nPerWI\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(128,1,1)))\n"
- "void PrefixScanKernel( __global u32* wHistogram1, int4 cb )\n"
- "{\n"
- " __local u32 ldsTopScanData[128*2];\n"
- " u32 lIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " u32 data[nPerWI];\n"
- " for(int i=0; i<nPerWI; i++)\n"
- " {\n"
- " data[i] = 0;\n"
- " if( (nPerWI*lIdx+i) < NUM_BUCKET*nWGs )\n"
- " data[i] = wHistogram1[nPerWI*lIdx+i];\n"
- " }\n"
- " uint4 myData = make_uint4(0,0,0,0);\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " myData.x += data[nPerLane*0+i];\n"
- " myData.y += data[nPerLane*1+i];\n"
- " myData.z += data[nPerLane*2+i];\n"
- " myData.w += data[nPerLane*3+i];\n"
- " }\n"
- " uint totalSum;\n"
- " uint4 scanned = localPrefixSum128V( myData, lIdx, &totalSum, ldsTopScanData );\n"
- "// for(int j=0; j<4; j++) // somehow it introduces a lot of branches\n"
- " { int j = 0;\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " u32 tmp = data[nPerLane*j+i];\n"
- " data[nPerLane*j+i] = sum;\n"
- " sum += tmp;\n"
- " }\n"
- " }\n"
- " { int j = 1;\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " u32 tmp = data[nPerLane*j+i];\n"
- " data[nPerLane*j+i] = sum;\n"
- " sum += tmp;\n"
- " }\n"
- " }\n"
- " { int j = 2;\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " u32 tmp = data[nPerLane*j+i];\n"
- " data[nPerLane*j+i] = sum;\n"
- " sum += tmp;\n"
- " }\n"
- " }\n"
- " { int j = 3;\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " u32 tmp = data[nPerLane*j+i];\n"
- " data[nPerLane*j+i] = sum;\n"
- " sum += tmp;\n"
- " }\n"
- " }\n"
- " for(int i=0; i<nPerLane; i++)\n"
- " {\n"
- " data[nPerLane*0+i] += scanned.x;\n"
- " data[nPerLane*1+i] += scanned.y;\n"
- " data[nPerLane*2+i] += scanned.z;\n"
- " data[nPerLane*3+i] += scanned.w;\n"
- " }\n"
- " for(int i=0; i<nPerWI; i++)\n"
- " {\n"
- " int index = nPerWI*lIdx+i;\n"
- " if (index < NUM_BUCKET*nWGs)\n"
- " wHistogram1[nPerWI*lIdx+i] = data[i];\n"
- " }\n"
- "}\n"
- "// 4 scan, 4 exchange\n"
- "void sort4Bits(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
- "{\n"
- " for(int bitIdx=0; bitIdx<BITS_PER_PASS; bitIdx++)\n"
- " {\n"
- " u32 mask = (1<<bitIdx);\n"
- " uint4 cmpResult = make_uint4( (sortData[0]>>startBit) & mask, (sortData[1]>>startBit) & mask, (sortData[2]>>startBit) & mask, (sortData[3]>>startBit) & mask );\n"
- " uint4 prefixSum = SELECT_UINT4( make_uint4(1,1,1,1), make_uint4(0,0,0,0), cmpResult != make_uint4(0,0,0,0) );\n"
- " u32 total;\n"
- " prefixSum = localPrefixSum64V( prefixSum, lIdx, &total, ldsSortData );\n"
- " {\n"
- " uint4 localAddr = make_uint4(lIdx*4+0,lIdx*4+1,lIdx*4+2,lIdx*4+3);\n"
- " uint4 dstAddr = localAddr - prefixSum + make_uint4( total, total, total, total );\n"
- " dstAddr = SELECT_UINT4( prefixSum, dstAddr, cmpResult != make_uint4(0, 0, 0, 0) );\n"
- " GROUP_LDS_BARRIER;\n"
- " ldsSortData[dstAddr.x] = sortData[0];\n"
- " ldsSortData[dstAddr.y] = sortData[1];\n"
- " ldsSortData[dstAddr.z] = sortData[2];\n"
- " ldsSortData[dstAddr.w] = sortData[3];\n"
- " GROUP_LDS_BARRIER;\n"
- " sortData[0] = ldsSortData[localAddr.x];\n"
- " sortData[1] = ldsSortData[localAddr.y];\n"
- " sortData[2] = ldsSortData[localAddr.z];\n"
- " sortData[3] = ldsSortData[localAddr.w];\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " }\n"
- "}\n"
- "// 2 scan, 2 exchange\n"
- "void sort4Bits1(u32 sortData[4], int startBit, int lIdx, __local u32* ldsSortData)\n"
- "{\n"
- " for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
- " {\n"
- " uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[1]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[2]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[3]>>(startBit+ibit)) & 0x3);\n"
- " u32 key4;\n"
- " u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
- " {\n"
- " sKeyPacked[0] |= 1<<(8*b.x);\n"
- " sKeyPacked[1] |= 1<<(8*b.y);\n"
- " sKeyPacked[2] |= 1<<(8*b.z);\n"
- " sKeyPacked[3] |= 1<<(8*b.w);\n"
- " key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
- " }\n"
- " u32 rankPacked;\n"
- " u32 sumPacked;\n"
- " {\n"
- " rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " u32 newOffset[4] = { 0,0,0,0 };\n"
- " {\n"
- " u32 sumScanned = bit8Scan( sumPacked );\n"
- " u32 scannedKeys[4];\n"
- " scannedKeys[0] = 1<<(8*b.x);\n"
- " scannedKeys[1] = 1<<(8*b.y);\n"
- " scannedKeys[2] = 1<<(8*b.z);\n"
- " scannedKeys[3] = 1<<(8*b.w);\n"
- " { // 4 scans at once\n"
- " u32 sum4 = 0;\n"
- " for(int ie=0; ie<4; ie++)\n"
- " {\n"
- " u32 tmp = scannedKeys[ie];\n"
- " scannedKeys[ie] = sum4;\n"
- " sum4 += tmp;\n"
- " }\n"
- " }\n"
- " {\n"
- " u32 sumPlusRank = sumScanned + rankPacked;\n"
- " { u32 ie = b.x;\n"
- " scannedKeys[0] += sumPlusRank;\n"
- " newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
- " }\n"
- " { u32 ie = b.y;\n"
- " scannedKeys[1] += sumPlusRank;\n"
- " newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
- " }\n"
- " { u32 ie = b.z;\n"
- " scannedKeys[2] += sumPlusRank;\n"
- " newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
- " }\n"
- " { u32 ie = b.w;\n"
- " scannedKeys[3] += sumPlusRank;\n"
- " newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
- " }\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " {\n"
- " ldsSortData[newOffset[0]] = sortData[0];\n"
- " ldsSortData[newOffset[1]] = sortData[1];\n"
- " ldsSortData[newOffset[2]] = sortData[2];\n"
- " ldsSortData[newOffset[3]] = sortData[3];\n"
- " GROUP_LDS_BARRIER;\n"
- " u32 dstAddr = 4*lIdx;\n"
- " sortData[0] = ldsSortData[dstAddr+0];\n"
- " sortData[1] = ldsSortData[dstAddr+1];\n"
- " sortData[2] = ldsSortData[dstAddr+2];\n"
- " sortData[3] = ldsSortData[dstAddr+3];\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " }\n"
- "}\n"
- "#define SET_HISTOGRAM(setIdx, key) ldsSortData[(setIdx)*NUM_BUCKET+key]\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SortAndScatterKernel( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
- "{\n"
- " __local u32 ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
- " __local u32 localHistogramToCarry[NUM_BUCKET];\n"
- " __local u32 localHistogram[NUM_BUCKET*2];\n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 lIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " if( lIdx < (NUM_BUCKET) )\n"
- " {\n"
- " localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
- " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
- " {\n"
- " u32 myHistogram = 0;\n"
- " u32 sortData[ELEMENTS_PER_WORK_ITEM];\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " sortData[i] = ( addr+i < n )? gSrc[ addr+i ] : 0xffffffff;\n"
- "#else\n"
- " sortData[i] = gSrc[ addr+i ];\n"
- "#endif\n"
- " sort4Bits(sortData, startBit, lIdx, ldsSortData);\n"
- " u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- " keys[i] = (sortData[i]>>startBit) & 0xf;\n"
- " { // create histogram\n"
- " u32 setIdx = lIdx/16;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[lIdx] = 0;\n"
- " }\n"
- " ldsSortData[lIdx] = 0;\n"
- " GROUP_LDS_BARRIER;\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+i < n )\n"
- "#endif\n"
- "#if defined(NV_GPU)\n"
- " SET_HISTOGRAM( setIdx, keys[i] )++;\n"
- "#else\n"
- " AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
- "#endif\n"
- " \n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " uint hIdx = NUM_BUCKET+lIdx;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<WG_SIZE/16; i++)\n"
- " {\n"
- " sum += SET_HISTOGRAM( i, lIdx );\n"
- " }\n"
- " myHistogram = sum;\n"
- " localHistogram[hIdx] = sum;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- "#if defined(USE_2LEVEL_REDUCE)\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " u32 u0, u1, u2;\n"
- " u0 = localHistogram[hIdx-3];\n"
- " u1 = localHistogram[hIdx-2];\n"
- " u2 = localHistogram[hIdx-1];\n"
- " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
- " GROUP_MEM_FENCE;\n"
- " u0 = localHistogram[hIdx-12];\n"
- " u1 = localHistogram[hIdx-8];\n"
- " u2 = localHistogram[hIdx-4];\n"
- " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#else\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-2];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-4];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-8];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#endif\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " {\n"
- " for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
- " {\n"
- " int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
- " int binIdx = keys[ie];\n"
- " int groupOffset = localHistogramToCarry[binIdx];\n"
- " int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+ie < n )\n"
- "#endif\n"
- " gDst[ groupOffset + myIdx ] = sortData[ie];\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogramToCarry[lIdx] += myHistogram;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- "}\n"
- "// 2 scan, 2 exchange\n"
- "void sort4Bits1KeyValue(u32 sortData[4], int sortVal[4], int startBit, int lIdx, __local u32* ldsSortData, __local int *ldsSortVal)\n"
- "{\n"
- " for(uint ibit=0; ibit<BITS_PER_PASS; ibit+=2)\n"
- " {\n"
- " uint4 b = make_uint4((sortData[0]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[1]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[2]>>(startBit+ibit)) & 0x3, \n"
- " (sortData[3]>>(startBit+ibit)) & 0x3);\n"
- " u32 key4;\n"
- " u32 sKeyPacked[4] = { 0, 0, 0, 0 };\n"
- " {\n"
- " sKeyPacked[0] |= 1<<(8*b.x);\n"
- " sKeyPacked[1] |= 1<<(8*b.y);\n"
- " sKeyPacked[2] |= 1<<(8*b.z);\n"
- " sKeyPacked[3] |= 1<<(8*b.w);\n"
- " key4 = sKeyPacked[0] + sKeyPacked[1] + sKeyPacked[2] + sKeyPacked[3];\n"
- " }\n"
- " u32 rankPacked;\n"
- " u32 sumPacked;\n"
- " {\n"
- " rankPacked = localPrefixSum( key4, lIdx, &sumPacked, ldsSortData, WG_SIZE );\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " u32 newOffset[4] = { 0,0,0,0 };\n"
- " {\n"
- " u32 sumScanned = bit8Scan( sumPacked );\n"
- " u32 scannedKeys[4];\n"
- " scannedKeys[0] = 1<<(8*b.x);\n"
- " scannedKeys[1] = 1<<(8*b.y);\n"
- " scannedKeys[2] = 1<<(8*b.z);\n"
- " scannedKeys[3] = 1<<(8*b.w);\n"
- " { // 4 scans at once\n"
- " u32 sum4 = 0;\n"
- " for(int ie=0; ie<4; ie++)\n"
- " {\n"
- " u32 tmp = scannedKeys[ie];\n"
- " scannedKeys[ie] = sum4;\n"
- " sum4 += tmp;\n"
- " }\n"
- " }\n"
- " {\n"
- " u32 sumPlusRank = sumScanned + rankPacked;\n"
- " { u32 ie = b.x;\n"
- " scannedKeys[0] += sumPlusRank;\n"
- " newOffset[0] = unpack4Key( scannedKeys[0], ie );\n"
- " }\n"
- " { u32 ie = b.y;\n"
- " scannedKeys[1] += sumPlusRank;\n"
- " newOffset[1] = unpack4Key( scannedKeys[1], ie );\n"
- " }\n"
- " { u32 ie = b.z;\n"
- " scannedKeys[2] += sumPlusRank;\n"
- " newOffset[2] = unpack4Key( scannedKeys[2], ie );\n"
- " }\n"
- " { u32 ie = b.w;\n"
- " scannedKeys[3] += sumPlusRank;\n"
- " newOffset[3] = unpack4Key( scannedKeys[3], ie );\n"
- " }\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " {\n"
- " ldsSortData[newOffset[0]] = sortData[0];\n"
- " ldsSortData[newOffset[1]] = sortData[1];\n"
- " ldsSortData[newOffset[2]] = sortData[2];\n"
- " ldsSortData[newOffset[3]] = sortData[3];\n"
- " ldsSortVal[newOffset[0]] = sortVal[0];\n"
- " ldsSortVal[newOffset[1]] = sortVal[1];\n"
- " ldsSortVal[newOffset[2]] = sortVal[2];\n"
- " ldsSortVal[newOffset[3]] = sortVal[3];\n"
- " GROUP_LDS_BARRIER;\n"
- " u32 dstAddr = 4*lIdx;\n"
- " sortData[0] = ldsSortData[dstAddr+0];\n"
- " sortData[1] = ldsSortData[dstAddr+1];\n"
- " sortData[2] = ldsSortData[dstAddr+2];\n"
- " sortData[3] = ldsSortData[dstAddr+3];\n"
- " sortVal[0] = ldsSortVal[dstAddr+0];\n"
- " sortVal[1] = ldsSortVal[dstAddr+1];\n"
- " sortVal[2] = ldsSortVal[dstAddr+2];\n"
- " sortVal[3] = ldsSortVal[dstAddr+3];\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SortAndScatterSortDataKernel( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
- "{\n"
- " __local int ldsSortData[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
- " __local int ldsSortVal[WG_SIZE*ELEMENTS_PER_WORK_ITEM+16];\n"
- " __local u32 localHistogramToCarry[NUM_BUCKET];\n"
- " __local u32 localHistogram[NUM_BUCKET*2];\n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 lIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " if( lIdx < (NUM_BUCKET) )\n"
- " {\n"
- " localHistogramToCarry[lIdx] = rHistogram[lIdx*nWGs + wgIdx];\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " int nBlocks = n/blockSize - nBlocksPerWG*wgIdx;\n"
- " int addr = blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++, addr+=blockSize)\n"
- " {\n"
- " u32 myHistogram = 0;\n"
- " int sortData[ELEMENTS_PER_WORK_ITEM];\n"
- " int sortVal[ELEMENTS_PER_WORK_ITEM];\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " {\n"
- " sortData[i] = ( addr+i < n )? gSrc[ addr+i ].m_key : 0xffffffff;\n"
- " sortVal[i] = ( addr+i < n )? gSrc[ addr+i ].m_value : 0xffffffff;\n"
- " }\n"
- "#else\n"
- " {\n"
- " sortData[i] = gSrc[ addr+i ].m_key;\n"
- " sortVal[i] = gSrc[ addr+i ].m_value;\n"
- " }\n"
- "#endif\n"
- " sort4Bits1KeyValue(sortData, sortVal, startBit, lIdx, ldsSortData, ldsSortVal);\n"
- " u32 keys[ELEMENTS_PER_WORK_ITEM];\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- " keys[i] = (sortData[i]>>startBit) & 0xf;\n"
- " { // create histogram\n"
- " u32 setIdx = lIdx/16;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[lIdx] = 0;\n"
- " }\n"
- " ldsSortData[lIdx] = 0;\n"
- " GROUP_LDS_BARRIER;\n"
- " for(int i=0; i<ELEMENTS_PER_WORK_ITEM; i++)\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+i < n )\n"
- "#endif\n"
- "#if defined(NV_GPU)\n"
- " SET_HISTOGRAM( setIdx, keys[i] )++;\n"
- "#else\n"
- " AtomInc( SET_HISTOGRAM( setIdx, keys[i] ) );\n"
- "#endif\n"
- " \n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " uint hIdx = NUM_BUCKET+lIdx;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " u32 sum = 0;\n"
- " for(int i=0; i<WG_SIZE/16; i++)\n"
- " {\n"
- " sum += SET_HISTOGRAM( i, lIdx );\n"
- " }\n"
- " myHistogram = sum;\n"
- " localHistogram[hIdx] = sum;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- "#if defined(USE_2LEVEL_REDUCE)\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " u32 u0, u1, u2;\n"
- " u0 = localHistogram[hIdx-3];\n"
- " u1 = localHistogram[hIdx-2];\n"
- " u2 = localHistogram[hIdx-1];\n"
- " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
- " GROUP_MEM_FENCE;\n"
- " u0 = localHistogram[hIdx-12];\n"
- " u1 = localHistogram[hIdx-8];\n"
- " u2 = localHistogram[hIdx-4];\n"
- " AtomAdd( localHistogram[hIdx], u0 + u1 + u2 );\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#else\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogram[hIdx] = localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-1];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-2];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-4];\n"
- " GROUP_MEM_FENCE;\n"
- " localHistogram[hIdx] += localHistogram[hIdx-8];\n"
- " GROUP_MEM_FENCE;\n"
- " }\n"
- "#endif\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " {\n"
- " for(int ie=0; ie<ELEMENTS_PER_WORK_ITEM; ie++)\n"
- " {\n"
- " int dataIdx = ELEMENTS_PER_WORK_ITEM*lIdx+ie;\n"
- " int binIdx = keys[ie];\n"
- " int groupOffset = localHistogramToCarry[binIdx];\n"
- " int myIdx = dataIdx - localHistogram[NUM_BUCKET+binIdx];\n"
- "#if defined(CHECK_BOUNDARY)\n"
- " if( addr+ie < n )\n"
- " {\n"
- " if ((groupOffset + myIdx)<n)\n"
- " {\n"
- " if (sortData[ie]==sortVal[ie])\n"
- " {\n"
- " \n"
- " SortDataCL tmp;\n"
- " tmp.m_key = sortData[ie];\n"
- " tmp.m_value = sortVal[ie];\n"
- " if (tmp.m_key == tmp.m_value)\n"
- " gDst[groupOffset + myIdx ] = tmp;\n"
- " }\n"
- " \n"
- " }\n"
- " }\n"
- "#else\n"
- " if ((groupOffset + myIdx)<n)\n"
- " {\n"
- " gDst[ groupOffset + myIdx ].m_key = sortData[ie];\n"
- " gDst[ groupOffset + myIdx ].m_value = sortVal[ie];\n"
- " }\n"
- "#endif\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx < NUM_BUCKET )\n"
- " {\n"
- " localHistogramToCarry[lIdx] += myHistogram;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SortAndScatterSortDataKernelSerial( __global const SortDataCL* restrict gSrc, __global const u32* rHistogram, __global SortDataCL* restrict gDst, int4 cb)\n"
- "{\n"
- " \n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 realLocalIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " int counter[NUM_BUCKET];\n"
- " \n"
- " if (realLocalIdx>0)\n"
- " return;\n"
- " \n"
- " for (int c=0;c<NUM_BUCKET;c++)\n"
- " counter[c]=0;\n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " \n"
- " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
- " {\n"
- " for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
- " {\n"
- " int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " \n"
- " for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
- " {\n"
- " int i = addr2+j;\n"
- " if( i < n )\n"
- " {\n"
- " int tableIdx;\n"
- " tableIdx = (gSrc[i].m_key>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
- " gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
- " counter[tableIdx] ++;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SortAndScatterKernelSerial( __global const u32* restrict gSrc, __global const u32* rHistogram, __global u32* restrict gDst, int4 cb )\n"
- "{\n"
- " \n"
- " u32 gIdx = GET_GLOBAL_IDX;\n"
- " u32 realLocalIdx = GET_LOCAL_IDX;\n"
- " u32 wgIdx = GET_GROUP_IDX;\n"
- " u32 wgSize = GET_GROUP_SIZE;\n"
- " const int startBit = cb.m_startBit;\n"
- " const int n = cb.m_n;\n"
- " const int nWGs = cb.m_nWGs;\n"
- " const int nBlocksPerWG = cb.m_nBlocksPerWG;\n"
- " int counter[NUM_BUCKET];\n"
- " \n"
- " if (realLocalIdx>0)\n"
- " return;\n"
- " \n"
- " for (int c=0;c<NUM_BUCKET;c++)\n"
- " counter[c]=0;\n"
- " const int blockSize = ELEMENTS_PER_WORK_ITEM*WG_SIZE;\n"
- " \n"
- " int nBlocks = (n)/blockSize - nBlocksPerWG*wgIdx;\n"
- " for(int iblock=0; iblock<min(nBlocksPerWG, nBlocks); iblock++)\n"
- " {\n"
- " for (int lIdx=0;lIdx<WG_SIZE;lIdx++)\n"
- " {\n"
- " int addr2 = iblock*blockSize + blockSize*nBlocksPerWG*wgIdx + ELEMENTS_PER_WORK_ITEM*lIdx;\n"
- " \n"
- " for(int j=0; j<ELEMENTS_PER_WORK_ITEM; j++)\n"
- " {\n"
- " int i = addr2+j;\n"
- " if( i < n )\n"
- " {\n"
- " int tableIdx;\n"
- " tableIdx = (gSrc[i]>>startBit) & 0xf;//0xf = NUM_TABLES-1\n"
- " gDst[rHistogram[tableIdx*nWGs+wgIdx] + counter[tableIdx]] = gSrc[i];\n"
- " counter[tableIdx] ++;\n"
- " }\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
deleted file mode 100644
index 6571f30548..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-
-#include "b3GpuRaycast.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3GpuParallelLinearBvh.h"
-
-#include "Bullet3OpenCL/Raycast/kernels/rayCastKernels.h"
-
-#define B3_RAYCAST_PATH "src/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl"
-
-struct b3GpuRaycastInternalData
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_q;
- cl_kernel m_raytraceKernel;
- cl_kernel m_raytracePairsKernel;
- cl_kernel m_findRayRigidPairIndexRanges;
-
- b3GpuParallelLinearBvh* m_plbvh;
- b3RadixSort32CL* m_radixSorter;
- b3FillCL* m_fill;
-
- //1 element per ray
- b3OpenCLArray<b3RayInfo>* m_gpuRays;
- b3OpenCLArray<b3RayHit>* m_gpuHitResults;
- b3OpenCLArray<int>* m_firstRayRigidPairIndexPerRay;
- b3OpenCLArray<int>* m_numRayRigidPairsPerRay;
-
- //1 element per (ray index, rigid index) pair, where the ray intersects with the rigid's AABB
- b3OpenCLArray<int>* m_gpuNumRayRigidPairs;
- b3OpenCLArray<b3Int2>* m_gpuRayRigidPairs; //x == ray index, y == rigid index
-
- int m_test;
-};
-
-b3GpuRaycast::b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q)
-{
- m_data = new b3GpuRaycastInternalData;
- m_data->m_context = ctx;
- m_data->m_device = device;
- m_data->m_q = q;
- m_data->m_raytraceKernel = 0;
- m_data->m_raytracePairsKernel = 0;
- m_data->m_findRayRigidPairIndexRanges = 0;
-
- m_data->m_plbvh = new b3GpuParallelLinearBvh(ctx, device, q);
- m_data->m_radixSorter = new b3RadixSort32CL(ctx, device, q);
- m_data->m_fill = new b3FillCL(ctx, device, q);
-
- m_data->m_gpuRays = new b3OpenCLArray<b3RayInfo>(ctx, q);
- m_data->m_gpuHitResults = new b3OpenCLArray<b3RayHit>(ctx, q);
- m_data->m_firstRayRigidPairIndexPerRay = new b3OpenCLArray<int>(ctx, q);
- m_data->m_numRayRigidPairsPerRay = new b3OpenCLArray<int>(ctx, q);
- m_data->m_gpuNumRayRigidPairs = new b3OpenCLArray<int>(ctx, q);
- m_data->m_gpuRayRigidPairs = new b3OpenCLArray<b3Int2>(ctx, q);
-
- {
- cl_int errNum = 0;
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, &errNum, "", B3_RAYCAST_PATH);
- b3Assert(errNum == CL_SUCCESS);
- m_data->m_raytraceKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_data->m_raytracePairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "rayCastPairsKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_data->m_findRayRigidPairIndexRanges = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, rayCastKernelCL, "findRayRigidPairIndexRanges", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- clReleaseProgram(prog);
- }
-}
-
-b3GpuRaycast::~b3GpuRaycast()
-{
- clReleaseKernel(m_data->m_raytraceKernel);
- clReleaseKernel(m_data->m_raytracePairsKernel);
- clReleaseKernel(m_data->m_findRayRigidPairIndexRanges);
-
- delete m_data->m_plbvh;
- delete m_data->m_radixSorter;
- delete m_data->m_fill;
-
- delete m_data->m_gpuRays;
- delete m_data->m_gpuHitResults;
- delete m_data->m_firstRayRigidPairIndexPerRay;
- delete m_data->m_numRayRigidPairsPerRay;
- delete m_data->m_gpuNumRayRigidPairs;
- delete m_data->m_gpuRayRigidPairs;
-
- delete m_data;
-}
-
-bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo, float& hitFraction)
-{
- b3Vector3 rs = rayFrom - spherePos;
- b3Vector3 rayDir = rayTo - rayFrom;
-
- float A = b3Dot(rayDir, rayDir);
- float B = b3Dot(rs, rayDir);
- float C = b3Dot(rs, rs) - (radius * radius);
-
- float D = B * B - A * C;
-
- if (D > 0.0)
- {
- float t = (-B - sqrt(D)) / A;
-
- if ((t >= 0.0f) && (t < hitFraction))
- {
- hitFraction = t;
- return true;
- }
- }
- return false;
-}
-
-bool rayConvex(const b3Vector3& rayFromLocal, const b3Vector3& rayToLocal, const b3ConvexPolyhedronData& poly,
- const b3AlignedObjectArray<b3GpuFace>& faces, float& hitFraction, b3Vector3& hitNormal)
-{
- float exitFraction = hitFraction;
- float enterFraction = -0.1f;
- b3Vector3 curHitNormal = b3MakeVector3(0, 0, 0);
- for (int i = 0; i < poly.m_numFaces; i++)
- {
- const b3GpuFace& face = faces[poly.m_faceOffset + i];
- float fromPlaneDist = b3Dot(rayFromLocal, face.m_plane) + face.m_plane.w;
- float toPlaneDist = b3Dot(rayToLocal, face.m_plane) + face.m_plane.w;
- if (fromPlaneDist < 0.f)
- {
- if (toPlaneDist >= 0.f)
- {
- float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
- if (exitFraction > fraction)
- {
- exitFraction = fraction;
- }
- }
- }
- else
- {
- if (toPlaneDist < 0.f)
- {
- float fraction = fromPlaneDist / (fromPlaneDist - toPlaneDist);
- if (enterFraction <= fraction)
- {
- enterFraction = fraction;
- curHitNormal = face.m_plane;
- curHitNormal.w = 0.f;
- }
- }
- else
- {
- return false;
- }
- }
- if (exitFraction <= enterFraction)
- return false;
- }
-
- if (enterFraction < 0.f)
- return false;
-
- hitFraction = enterFraction;
- hitNormal = curHitNormal;
- return true;
-}
-
-void b3GpuRaycast::castRaysHost(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables, const struct b3GpuNarrowPhaseInternalData* narrowphaseData)
-{
- // return castRays(rays,hitResults,numBodies,bodies,numCollidables,collidables);
-
- B3_PROFILE("castRaysHost");
- for (int r = 0; r < rays.size(); r++)
- {
- b3Vector3 rayFrom = rays[r].m_from;
- b3Vector3 rayTo = rays[r].m_to;
- float hitFraction = hitResults[r].m_hitFraction;
-
- int hitBodyIndex = -1;
- b3Vector3 hitNormal;
-
- for (int b = 0; b < numBodies; b++)
- {
- const b3Vector3& pos = bodies[b].m_pos;
- //const b3Quaternion& orn = bodies[b].m_quat;
-
- switch (collidables[bodies[b].m_collidableIdx].m_shapeType)
- {
- case SHAPE_SPHERE:
- {
- b3Scalar radius = collidables[bodies[b].m_collidableIdx].m_radius;
- if (sphere_intersect(pos, radius, rayFrom, rayTo, hitFraction))
- {
- hitBodyIndex = b;
- b3Vector3 hitPoint;
- hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
- hitNormal = (hitPoint - bodies[b].m_pos).normalize();
- }
- }
- case SHAPE_CONVEX_HULL:
- {
- b3Transform convexWorldTransform;
- convexWorldTransform.setIdentity();
- convexWorldTransform.setOrigin(bodies[b].m_pos);
- convexWorldTransform.setRotation(bodies[b].m_quat);
- b3Transform convexWorld2Local = convexWorldTransform.inverse();
-
- b3Vector3 rayFromLocal = convexWorld2Local(rayFrom);
- b3Vector3 rayToLocal = convexWorld2Local(rayTo);
-
- int shapeIndex = collidables[bodies[b].m_collidableIdx].m_shapeIndex;
- const b3ConvexPolyhedronData& poly = narrowphaseData->m_convexPolyhedra[shapeIndex];
- if (rayConvex(rayFromLocal, rayToLocal, poly, narrowphaseData->m_convexFaces, hitFraction, hitNormal))
- {
- hitBodyIndex = b;
- }
-
- break;
- }
- default:
- {
- static bool once = true;
- if (once)
- {
- once = false;
- b3Warning("Raytest: unsupported shape type\n");
- }
- }
- }
- }
- if (hitBodyIndex >= 0)
- {
- hitResults[r].m_hitFraction = hitFraction;
- hitResults[r].m_hitPoint.setInterpolate3(rays[r].m_from, rays[r].m_to, hitFraction);
- hitResults[r].m_hitNormal = hitNormal;
- hitResults[r].m_hitBody = hitBodyIndex;
- }
- }
-}
-///todo: add some acceleration structure (AABBs, tree etc)
-void b3GpuRaycast::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase)
-{
- //castRaysHost(rays,hitResults,numBodies,bodies,numCollidables,collidables,narrowphaseData);
-
- B3_PROFILE("castRaysGPU");
-
- {
- B3_PROFILE("raycast copyFromHost");
- m_data->m_gpuRays->copyFromHost(rays);
- m_data->m_gpuHitResults->copyFromHost(hitResults);
- }
-
- int numRays = hitResults.size();
- {
- m_data->m_firstRayRigidPairIndexPerRay->resize(numRays);
- m_data->m_numRayRigidPairsPerRay->resize(numRays);
-
- m_data->m_gpuNumRayRigidPairs->resize(1);
- m_data->m_gpuRayRigidPairs->resize(numRays * 16);
- }
-
- //run kernel
- const bool USE_BRUTE_FORCE_RAYCAST = false;
- if (USE_BRUTE_FORCE_RAYCAST)
- {
- B3_PROFILE("raycast launch1D");
-
- b3LauncherCL launcher(m_data->m_q, m_data->m_raytraceKernel, "m_raytraceKernel");
- int numRays = rays.size();
- launcher.setConst(numRays);
-
- launcher.setBuffer(m_data->m_gpuRays->getBufferCL());
- launcher.setBuffer(m_data->m_gpuHitResults->getBufferCL());
-
- launcher.setConst(numBodies);
- launcher.setBuffer(narrowphaseData->m_bodyBufferGPU->getBufferCL());
- launcher.setBuffer(narrowphaseData->m_collidablesGPU->getBufferCL());
- launcher.setBuffer(narrowphaseData->m_convexFacesGPU->getBufferCL());
- launcher.setBuffer(narrowphaseData->m_convexPolyhedraGPU->getBufferCL());
-
- launcher.launch1D(numRays);
- clFinish(m_data->m_q);
- }
- else
- {
- m_data->m_plbvh->build(broadphase->getAllAabbsGPU(), broadphase->getSmallAabbIndicesGPU(), broadphase->getLargeAabbIndicesGPU());
-
- m_data->m_plbvh->testRaysAgainstBvhAabbs(*m_data->m_gpuRays, *m_data->m_gpuNumRayRigidPairs, *m_data->m_gpuRayRigidPairs);
-
- int numRayRigidPairs = -1;
- m_data->m_gpuNumRayRigidPairs->copyToHostPointer(&numRayRigidPairs, 1);
- if (numRayRigidPairs > m_data->m_gpuRayRigidPairs->size())
- {
- numRayRigidPairs = m_data->m_gpuRayRigidPairs->size();
- m_data->m_gpuNumRayRigidPairs->copyFromHostPointer(&numRayRigidPairs, 1);
- }
-
- m_data->m_gpuRayRigidPairs->resize(numRayRigidPairs); //Radix sort needs b3OpenCLArray::size() to be correct
-
- //Sort ray-rigid pairs by ray index
- {
- B3_PROFILE("sort ray-rigid pairs");
- m_data->m_radixSorter->execute(*reinterpret_cast<b3OpenCLArray<b3SortData>*>(m_data->m_gpuRayRigidPairs));
- }
-
- //detect start,count of each ray pair
- {
- B3_PROFILE("detect ray-rigid pair index ranges");
-
- {
- B3_PROFILE("reset ray-rigid pair index ranges");
-
- m_data->m_fill->execute(*m_data->m_firstRayRigidPairIndexPerRay, numRayRigidPairs, numRays); //atomic_min used to find first index
- m_data->m_fill->execute(*m_data->m_numRayRigidPairsPerRay, 0, numRays);
- clFinish(m_data->m_q);
- }
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL()),
-
- b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
- b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL())};
-
- b3LauncherCL launcher(m_data->m_q, m_data->m_findRayRigidPairIndexRanges, "m_findRayRigidPairIndexRanges");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numRayRigidPairs);
-
- launcher.launch1D(numRayRigidPairs);
- clFinish(m_data->m_q);
- }
-
- {
- B3_PROFILE("ray-rigid intersection");
-
- b3BufferInfoCL bufferInfo[] =
- {
- b3BufferInfoCL(m_data->m_gpuRays->getBufferCL()),
- b3BufferInfoCL(m_data->m_gpuHitResults->getBufferCL()),
- b3BufferInfoCL(m_data->m_firstRayRigidPairIndexPerRay->getBufferCL()),
- b3BufferInfoCL(m_data->m_numRayRigidPairsPerRay->getBufferCL()),
-
- b3BufferInfoCL(narrowphaseData->m_bodyBufferGPU->getBufferCL()),
- b3BufferInfoCL(narrowphaseData->m_collidablesGPU->getBufferCL()),
- b3BufferInfoCL(narrowphaseData->m_convexFacesGPU->getBufferCL()),
- b3BufferInfoCL(narrowphaseData->m_convexPolyhedraGPU->getBufferCL()),
-
- b3BufferInfoCL(m_data->m_gpuRayRigidPairs->getBufferCL())};
-
- b3LauncherCL launcher(m_data->m_q, m_data->m_raytracePairsKernel, "m_raytracePairsKernel");
- launcher.setBuffers(bufferInfo, sizeof(bufferInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(numRays);
-
- launcher.launch1D(numRays);
- clFinish(m_data->m_q);
- }
- }
-
- //copy results
- {
- B3_PROFILE("raycast copyToHost");
- m_data->m_gpuHitResults->copyToHost(hitResults);
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h b/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h
deleted file mode 100644
index f1f6ffd402..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/b3GpuRaycast.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef B3_GPU_RAYCAST_H
-#define B3_GPU_RAYCAST_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
-
-class b3GpuRaycast
-{
-protected:
- struct b3GpuRaycastInternalData* m_data;
-
-public:
- b3GpuRaycast(cl_context ctx, cl_device_id device, cl_command_queue q);
- virtual ~b3GpuRaycast();
-
- void castRaysHost(const b3AlignedObjectArray<b3RayInfo>& raysIn, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData);
-
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults,
- int numBodies, const struct b3RigidBodyData* bodies, int numCollidables, const struct b3Collidable* collidables,
- const struct b3GpuNarrowPhaseInternalData* narrowphaseData, class b3GpuBroadphaseInterface* broadphase);
-};
-
-#endif //B3_GPU_RAYCAST_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl b/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl
deleted file mode 100644
index e72d96876b..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.cl
+++ /dev/null
@@ -1,439 +0,0 @@
-
-#define SHAPE_CONVEX_HULL 3
-#define SHAPE_PLANE 4
-#define SHAPE_CONCAVE_TRIMESH 5
-#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6
-#define SHAPE_SPHERE 7
-
-
-typedef struct
-{
- float4 m_from;
- float4 m_to;
-} b3RayInfo;
-
-typedef struct
-{
- float m_hitFraction;
- int m_hitResult0;
- int m_hitResult1;
- int m_hitResult2;
- float4 m_hitPoint;
- float4 m_hitNormal;
-} b3RayHit;
-
-typedef struct
-{
- float4 m_pos;
- float4 m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- unsigned int m_collidableIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} Body;
-
-typedef struct Collidable
-{
- union {
- int m_numChildShapes;
- int m_bvhIndex;
- };
- float m_radius;
- int m_shapeType;
- int m_shapeIndex;
-} Collidable;
-
-
-typedef struct
-{
- float4 m_localCenter;
- float4 m_extents;
- float4 mC;
- float4 mE;
-
- float m_radius;
- int m_faceOffset;
- int m_numFaces;
- int m_numVertices;
-
- int m_vertexOffset;
- int m_uniqueEdgesOffset;
- int m_numUniqueEdges;
- int m_unused;
-
-} ConvexPolyhedronCL;
-
-typedef struct
-{
- float4 m_plane;
- int m_indexOffset;
- int m_numIndices;
-} b3GpuFace;
-
-
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
- Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
- Quaternion qtNormalize(Quaternion in);
-
-
-__inline
- Quaternion qtInvert(Quaternion q);
-
-
-__inline
- float dot3F4(float4 a, float4 b)
-{
- float4 a1 = (float4)(a.xyz,0.f);
- float4 b1 = (float4)(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-
-__inline
- Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross( a, b );
- ans += a.w*b+b.w*a;
- // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
- Quaternion qtNormalize(Quaternion in)
-{
- return fast_normalize(in);
- // in /= length( in );
- // return in;
-}
-__inline
- float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(q,vcpy);
- out = qtMul(out,qInv);
- return out;
-}
-
-__inline
- Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
- float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-
-
-void trInverse(float4 translationIn, Quaternion orientationIn,
- float4* translationOut, Quaternion* orientationOut)
-{
- *orientationOut = qtInvert(orientationIn);
- *translationOut = qtRotate(*orientationOut, -translationIn);
-}
-
-
-
-
-
-bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,
- __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)
-{
- rayFromLocal.w = 0.f;
- rayToLocal.w = 0.f;
- bool result = true;
-
- float exitFraction = hitFraction[0];
- float enterFraction = -0.3f;
- float4 curHitNormal = (float4)(0,0,0,0);
- for (int i=0;i<numFaces && result;i++)
- {
- b3GpuFace face = faces[faceOffset+i];
- float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;
- float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;
- if (fromPlaneDist<0.f)
- {
- if (toPlaneDist >= 0.f)
- {
- float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
- if (exitFraction>fraction)
- {
- exitFraction = fraction;
- }
- }
- } else
- {
- if (toPlaneDist<0.f)
- {
- float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);
- if (enterFraction <= fraction)
- {
- enterFraction = fraction;
- curHitNormal = face.m_plane;
- curHitNormal.w = 0.f;
- }
- } else
- {
- result = false;
- }
- }
- if (exitFraction <= enterFraction)
- result = false;
- }
-
- if (enterFraction < 0.f)
- {
- result = false;
- }
-
- if (result)
- {
- hitFraction[0] = enterFraction;
- hitNormal[0] = curHitNormal;
- }
- return result;
-}
-
-
-
-
-
-
-bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)
-{
- float4 rs = rayFrom - spherePos;
- rs.w = 0.f;
- float4 rayDir = rayTo-rayFrom;
- rayDir.w = 0.f;
- float A = dot(rayDir,rayDir);
- float B = dot(rs, rayDir);
- float C = dot(rs, rs) - (radius * radius);
-
- float D = B * B - A*C;
-
- if (D > 0.0f)
- {
- float t = (-B - sqrt(D))/A;
-
- if ( (t >= 0.0f) && (t < (*hitFraction)) )
- {
- *hitFraction = t;
- return true;
- }
- }
- return false;
-}
-
-float4 setInterpolate3(float4 from, float4 to, float t)
-{
- float s = 1.0f - t;
- float4 result;
- result = s * from + t * to;
- result.w = 0.f;
- return result;
-}
-
-__kernel void rayCastKernel(
- int numRays,
- const __global b3RayInfo* rays,
- __global b3RayHit* hitResults,
- const int numBodies,
- __global Body* bodies,
- __global Collidable* collidables,
- __global const b3GpuFace* faces,
- __global const ConvexPolyhedronCL* convexShapes )
-{
-
- int i = get_global_id(0);
- if (i>=numRays)
- return;
-
- hitResults[i].m_hitFraction = 1.f;
-
- float4 rayFrom = rays[i].m_from;
- float4 rayTo = rays[i].m_to;
- float hitFraction = 1.f;
- float4 hitPoint;
- float4 hitNormal;
- int hitBodyIndex= -1;
-
- int cachedCollidableIndex = -1;
- Collidable cachedCollidable;
-
- for (int b=0;b<numBodies;b++)
- {
- if (hitResults[i].m_hitResult2==b)
- continue;
- Body body = bodies[b];
- float4 pos = body.m_pos;
- float4 orn = body.m_quat;
- if (cachedCollidableIndex != body.m_collidableIdx)
- {
- cachedCollidableIndex = body.m_collidableIdx;
- cachedCollidable = collidables[cachedCollidableIndex];
- }
- if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)
- {
-
- float4 invPos = (float4)(0,0,0,0);
- float4 invOrn = (float4)(0,0,0,0);
- float4 rayFromLocal = (float4)(0,0,0,0);
- float4 rayToLocal = (float4)(0,0,0,0);
- invOrn = qtInvert(orn);
- invPos = qtRotate(invOrn, -pos);
- rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
- rayToLocal = qtRotate( invOrn, rayTo) + invPos;
- rayFromLocal.w = 0.f;
- rayToLocal.w = 0.f;
- int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;
- int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;
- if (numFaces)
- {
- if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
- {
- hitBodyIndex = b;
-
- }
- }
- }
- if (cachedCollidable.m_shapeType == SHAPE_SPHERE)
- {
- float radius = cachedCollidable.m_radius;
-
- if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))
- {
- hitBodyIndex = b;
- hitNormal = (float4) (hitPoint-bodies[b].m_pos);
- }
- }
- }
-
- if (hitBodyIndex>=0)
- {
- hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);
- hitResults[i].m_hitFraction = hitFraction;
- hitResults[i].m_hitPoint = hitPoint;
- hitResults[i].m_hitNormal = normalize(hitNormal);
- hitResults[i].m_hitResult0 = hitBodyIndex;
- }
-
-}
-
-
-__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs,
- __global int* out_firstRayRigidPairIndexPerRay,
- __global int* out_numRayRigidPairsPerRay,
- int numRayRigidPairs)
-{
- int rayRigidPairIndex = get_global_id(0);
- if (rayRigidPairIndex >= numRayRigidPairs) return;
-
- int rayIndex = rayRigidPairs[rayRigidPairIndex].x;
-
- atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);
- atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);
-}
-
-__kernel void rayCastPairsKernel(const __global b3RayInfo* rays,
- __global b3RayHit* hitResults,
- __global int* firstRayRigidPairIndexPerRay,
- __global int* numRayRigidPairsPerRay,
-
- __global Body* bodies,
- __global Collidable* collidables,
- __global const b3GpuFace* faces,
- __global const ConvexPolyhedronCL* convexShapes,
-
- __global int2* rayRigidPairs,
- int numRays)
-{
- int i = get_global_id(0);
- if (i >= numRays) return;
-
- float4 rayFrom = rays[i].m_from;
- float4 rayTo = rays[i].m_to;
-
- hitResults[i].m_hitFraction = 1.f;
-
- float hitFraction = 1.f;
- float4 hitPoint;
- float4 hitNormal;
- int hitBodyIndex = -1;
-
- //
- for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)
- {
- int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];
- int b = rayRigidPairs[rayRigidPairIndex].y;
-
- if (hitResults[i].m_hitResult2 == b) continue;
-
- Body body = bodies[b];
- Collidable rigidCollidable = collidables[body.m_collidableIdx];
-
- float4 pos = body.m_pos;
- float4 orn = body.m_quat;
-
- if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)
- {
- float4 invPos = (float4)(0,0,0,0);
- float4 invOrn = (float4)(0,0,0,0);
- float4 rayFromLocal = (float4)(0,0,0,0);
- float4 rayToLocal = (float4)(0,0,0,0);
- invOrn = qtInvert(orn);
- invPos = qtRotate(invOrn, -pos);
- rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;
- rayToLocal = qtRotate( invOrn, rayTo) + invPos;
- rayFromLocal.w = 0.f;
- rayToLocal.w = 0.f;
- int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;
- int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;
-
- if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))
- {
- hitBodyIndex = b;
- hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
- }
- }
-
- if (rigidCollidable.m_shapeType == SHAPE_SPHERE)
- {
- float radius = rigidCollidable.m_radius;
-
- if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))
- {
- hitBodyIndex = b;
- hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);
- hitNormal = (float4) (hitPoint - bodies[b].m_pos);
- }
- }
- }
-
- if (hitBodyIndex >= 0)
- {
- hitResults[i].m_hitFraction = hitFraction;
- hitResults[i].m_hitPoint = hitPoint;
- hitResults[i].m_hitNormal = normalize(hitNormal);
- hitResults[i].m_hitResult0 = hitBodyIndex;
- }
-
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h b/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
deleted file mode 100644
index 94f6a8eb9f..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/Raycast/kernels/rayCastKernels.h
+++ /dev/null
@@ -1,380 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* rayCastKernelCL =
- "#define SHAPE_CONVEX_HULL 3\n"
- "#define SHAPE_PLANE 4\n"
- "#define SHAPE_CONCAVE_TRIMESH 5\n"
- "#define SHAPE_COMPOUND_OF_CONVEX_HULLS 6\n"
- "#define SHAPE_SPHERE 7\n"
- "typedef struct\n"
- "{\n"
- " float4 m_from;\n"
- " float4 m_to;\n"
- "} b3RayInfo;\n"
- "typedef struct\n"
- "{\n"
- " float m_hitFraction;\n"
- " int m_hitResult0;\n"
- " int m_hitResult1;\n"
- " int m_hitResult2;\n"
- " float4 m_hitPoint;\n"
- " float4 m_hitNormal;\n"
- "} b3RayHit;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " float4 m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " unsigned int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} Body;\n"
- "typedef struct Collidable\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " float m_radius;\n"
- " int m_shapeType;\n"
- " int m_shapeIndex;\n"
- "} Collidable;\n"
- "typedef struct \n"
- "{\n"
- " float4 m_localCenter;\n"
- " float4 m_extents;\n"
- " float4 mC;\n"
- " float4 mE;\n"
- " float m_radius;\n"
- " int m_faceOffset;\n"
- " int m_numFaces;\n"
- " int m_numVertices;\n"
- " int m_vertexOffset;\n"
- " int m_uniqueEdgesOffset;\n"
- " int m_numUniqueEdges;\n"
- " int m_unused;\n"
- "} ConvexPolyhedronCL;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_plane;\n"
- " int m_indexOffset;\n"
- " int m_numIndices;\n"
- "} b3GpuFace;\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- " Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- " Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- " Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- " float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = (float4)(a.xyz,0.f);\n"
- " float4 b1 = (float4)(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- " Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- " // ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- " Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fast_normalize(in);\n"
- " // in /= length( in );\n"
- " // return in;\n"
- "}\n"
- "__inline\n"
- " float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(q,vcpy);\n"
- " out = qtMul(out,qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- " Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- " float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "void trInverse(float4 translationIn, Quaternion orientationIn,\n"
- " float4* translationOut, Quaternion* orientationOut)\n"
- "{\n"
- " *orientationOut = qtInvert(orientationIn);\n"
- " *translationOut = qtRotate(*orientationOut, -translationIn);\n"
- "}\n"
- "bool rayConvex(float4 rayFromLocal, float4 rayToLocal, int numFaces, int faceOffset,\n"
- " __global const b3GpuFace* faces, float* hitFraction, float4* hitNormal)\n"
- "{\n"
- " rayFromLocal.w = 0.f;\n"
- " rayToLocal.w = 0.f;\n"
- " bool result = true;\n"
- " float exitFraction = hitFraction[0];\n"
- " float enterFraction = -0.3f;\n"
- " float4 curHitNormal = (float4)(0,0,0,0);\n"
- " for (int i=0;i<numFaces && result;i++)\n"
- " {\n"
- " b3GpuFace face = faces[faceOffset+i];\n"
- " float fromPlaneDist = dot(rayFromLocal,face.m_plane)+face.m_plane.w;\n"
- " float toPlaneDist = dot(rayToLocal,face.m_plane)+face.m_plane.w;\n"
- " if (fromPlaneDist<0.f)\n"
- " {\n"
- " if (toPlaneDist >= 0.f)\n"
- " {\n"
- " float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
- " if (exitFraction>fraction)\n"
- " {\n"
- " exitFraction = fraction;\n"
- " }\n"
- " } \n"
- " } else\n"
- " {\n"
- " if (toPlaneDist<0.f)\n"
- " {\n"
- " float fraction = fromPlaneDist / (fromPlaneDist-toPlaneDist);\n"
- " if (enterFraction <= fraction)\n"
- " {\n"
- " enterFraction = fraction;\n"
- " curHitNormal = face.m_plane;\n"
- " curHitNormal.w = 0.f;\n"
- " }\n"
- " } else\n"
- " {\n"
- " result = false;\n"
- " }\n"
- " }\n"
- " if (exitFraction <= enterFraction)\n"
- " result = false;\n"
- " }\n"
- " if (enterFraction < 0.f)\n"
- " {\n"
- " result = false;\n"
- " }\n"
- " if (result)\n"
- " { \n"
- " hitFraction[0] = enterFraction;\n"
- " hitNormal[0] = curHitNormal;\n"
- " }\n"
- " return result;\n"
- "}\n"
- "bool sphere_intersect(float4 spherePos, float radius, float4 rayFrom, float4 rayTo, float* hitFraction)\n"
- "{\n"
- " float4 rs = rayFrom - spherePos;\n"
- " rs.w = 0.f;\n"
- " float4 rayDir = rayTo-rayFrom;\n"
- " rayDir.w = 0.f;\n"
- " float A = dot(rayDir,rayDir);\n"
- " float B = dot(rs, rayDir);\n"
- " float C = dot(rs, rs) - (radius * radius);\n"
- " float D = B * B - A*C;\n"
- " if (D > 0.0f)\n"
- " {\n"
- " float t = (-B - sqrt(D))/A;\n"
- " if ( (t >= 0.0f) && (t < (*hitFraction)) )\n"
- " {\n"
- " *hitFraction = t;\n"
- " return true;\n"
- " }\n"
- " }\n"
- " return false;\n"
- "}\n"
- "float4 setInterpolate3(float4 from, float4 to, float t)\n"
- "{\n"
- " float s = 1.0f - t;\n"
- " float4 result;\n"
- " result = s * from + t * to;\n"
- " result.w = 0.f; \n"
- " return result; \n"
- "}\n"
- "__kernel void rayCastKernel( \n"
- " int numRays, \n"
- " const __global b3RayInfo* rays, \n"
- " __global b3RayHit* hitResults, \n"
- " const int numBodies, \n"
- " __global Body* bodies,\n"
- " __global Collidable* collidables,\n"
- " __global const b3GpuFace* faces,\n"
- " __global const ConvexPolyhedronCL* convexShapes )\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numRays)\n"
- " return;\n"
- " hitResults[i].m_hitFraction = 1.f;\n"
- " float4 rayFrom = rays[i].m_from;\n"
- " float4 rayTo = rays[i].m_to;\n"
- " float hitFraction = 1.f;\n"
- " float4 hitPoint;\n"
- " float4 hitNormal;\n"
- " int hitBodyIndex= -1;\n"
- " int cachedCollidableIndex = -1;\n"
- " Collidable cachedCollidable;\n"
- " for (int b=0;b<numBodies;b++)\n"
- " {\n"
- " if (hitResults[i].m_hitResult2==b)\n"
- " continue;\n"
- " Body body = bodies[b];\n"
- " float4 pos = body.m_pos;\n"
- " float4 orn = body.m_quat;\n"
- " if (cachedCollidableIndex != body.m_collidableIdx)\n"
- " {\n"
- " cachedCollidableIndex = body.m_collidableIdx;\n"
- " cachedCollidable = collidables[cachedCollidableIndex];\n"
- " }\n"
- " if (cachedCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
- " {\n"
- " float4 invPos = (float4)(0,0,0,0);\n"
- " float4 invOrn = (float4)(0,0,0,0);\n"
- " float4 rayFromLocal = (float4)(0,0,0,0);\n"
- " float4 rayToLocal = (float4)(0,0,0,0);\n"
- " invOrn = qtInvert(orn);\n"
- " invPos = qtRotate(invOrn, -pos);\n"
- " rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
- " rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
- " rayFromLocal.w = 0.f;\n"
- " rayToLocal.w = 0.f;\n"
- " int numFaces = convexShapes[cachedCollidable.m_shapeIndex].m_numFaces;\n"
- " int faceOffset = convexShapes[cachedCollidable.m_shapeIndex].m_faceOffset;\n"
- " if (numFaces)\n"
- " {\n"
- " if (rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
- " {\n"
- " hitBodyIndex = b;\n"
- " \n"
- " }\n"
- " }\n"
- " }\n"
- " if (cachedCollidable.m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " float radius = cachedCollidable.m_radius;\n"
- " \n"
- " if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
- " {\n"
- " hitBodyIndex = b;\n"
- " hitNormal = (float4) (hitPoint-bodies[b].m_pos);\n"
- " }\n"
- " }\n"
- " }\n"
- " if (hitBodyIndex>=0)\n"
- " {\n"
- " hitPoint = setInterpolate3(rayFrom, rayTo,hitFraction);\n"
- " hitResults[i].m_hitFraction = hitFraction;\n"
- " hitResults[i].m_hitPoint = hitPoint;\n"
- " hitResults[i].m_hitNormal = normalize(hitNormal);\n"
- " hitResults[i].m_hitResult0 = hitBodyIndex;\n"
- " }\n"
- "}\n"
- "__kernel void findRayRigidPairIndexRanges(__global int2* rayRigidPairs, \n"
- " __global int* out_firstRayRigidPairIndexPerRay,\n"
- " __global int* out_numRayRigidPairsPerRay,\n"
- " int numRayRigidPairs)\n"
- "{\n"
- " int rayRigidPairIndex = get_global_id(0);\n"
- " if (rayRigidPairIndex >= numRayRigidPairs) return;\n"
- " \n"
- " int rayIndex = rayRigidPairs[rayRigidPairIndex].x;\n"
- " \n"
- " atomic_min(&out_firstRayRigidPairIndexPerRay[rayIndex], rayRigidPairIndex);\n"
- " atomic_inc(&out_numRayRigidPairsPerRay[rayIndex]);\n"
- "}\n"
- "__kernel void rayCastPairsKernel(const __global b3RayInfo* rays, \n"
- " __global b3RayHit* hitResults, \n"
- " __global int* firstRayRigidPairIndexPerRay,\n"
- " __global int* numRayRigidPairsPerRay,\n"
- " \n"
- " __global Body* bodies,\n"
- " __global Collidable* collidables,\n"
- " __global const b3GpuFace* faces,\n"
- " __global const ConvexPolyhedronCL* convexShapes,\n"
- " \n"
- " __global int2* rayRigidPairs,\n"
- " int numRays)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i >= numRays) return;\n"
- " \n"
- " float4 rayFrom = rays[i].m_from;\n"
- " float4 rayTo = rays[i].m_to;\n"
- " \n"
- " hitResults[i].m_hitFraction = 1.f;\n"
- " \n"
- " float hitFraction = 1.f;\n"
- " float4 hitPoint;\n"
- " float4 hitNormal;\n"
- " int hitBodyIndex = -1;\n"
- " \n"
- " //\n"
- " for(int pair = 0; pair < numRayRigidPairsPerRay[i]; ++pair)\n"
- " {\n"
- " int rayRigidPairIndex = pair + firstRayRigidPairIndexPerRay[i];\n"
- " int b = rayRigidPairs[rayRigidPairIndex].y;\n"
- " \n"
- " if (hitResults[i].m_hitResult2 == b) continue;\n"
- " \n"
- " Body body = bodies[b];\n"
- " Collidable rigidCollidable = collidables[body.m_collidableIdx];\n"
- " \n"
- " float4 pos = body.m_pos;\n"
- " float4 orn = body.m_quat;\n"
- " \n"
- " if (rigidCollidable.m_shapeType == SHAPE_CONVEX_HULL)\n"
- " {\n"
- " float4 invPos = (float4)(0,0,0,0);\n"
- " float4 invOrn = (float4)(0,0,0,0);\n"
- " float4 rayFromLocal = (float4)(0,0,0,0);\n"
- " float4 rayToLocal = (float4)(0,0,0,0);\n"
- " invOrn = qtInvert(orn);\n"
- " invPos = qtRotate(invOrn, -pos);\n"
- " rayFromLocal = qtRotate( invOrn, rayFrom ) + invPos;\n"
- " rayToLocal = qtRotate( invOrn, rayTo) + invPos;\n"
- " rayFromLocal.w = 0.f;\n"
- " rayToLocal.w = 0.f;\n"
- " int numFaces = convexShapes[rigidCollidable.m_shapeIndex].m_numFaces;\n"
- " int faceOffset = convexShapes[rigidCollidable.m_shapeIndex].m_faceOffset;\n"
- " \n"
- " if (numFaces && rayConvex(rayFromLocal, rayToLocal, numFaces, faceOffset,faces, &hitFraction, &hitNormal))\n"
- " {\n"
- " hitBodyIndex = b;\n"
- " hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
- " }\n"
- " }\n"
- " \n"
- " if (rigidCollidable.m_shapeType == SHAPE_SPHERE)\n"
- " {\n"
- " float radius = rigidCollidable.m_radius;\n"
- " \n"
- " if (sphere_intersect(pos, radius, rayFrom, rayTo, &hitFraction))\n"
- " {\n"
- " hitBodyIndex = b;\n"
- " hitPoint = setInterpolate3(rayFrom, rayTo, hitFraction);\n"
- " hitNormal = (float4) (hitPoint - bodies[b].m_pos);\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " if (hitBodyIndex >= 0)\n"
- " {\n"
- " hitResults[i].m_hitFraction = hitFraction;\n"
- " hitResults[i].m_hitPoint = hitPoint;\n"
- " hitResults[i].m_hitNormal = normalize(hitNormal);\n"
- " hitResults[i].m_hitResult0 = hitBodyIndex;\n"
- " }\n"
- " \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
deleted file mode 100644
index 89c0142ab3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuConstraint4.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-#ifndef B3_CONSTRAINT4_h
-#define B3_CONSTRAINT4_h
-#include "Bullet3Common/b3Vector3.h"
-
-#include "Bullet3Dynamics/shared/b3ContactConstraint4.h"
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3GpuConstraint4 : public b3ContactConstraint4
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- inline void setFrictionCoeff(float value) { m_linear[3] = value; }
- inline float getFrictionCoeff() const { return m_linear[3]; }
-};
-
-#endif //B3_CONSTRAINT4_h
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
deleted file mode 100644
index a271090af4..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "b3GpuGenericConstraint.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include <new>
-#include "Bullet3Common/b3Transform.h"
-
-void b3GpuGenericConstraint::getInfo1(unsigned int* info, const b3RigidBodyData* bodies)
-{
- switch (m_constraintType)
- {
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
- {
- *info = 3;
- break;
- };
- default:
- {
- b3Assert(0);
- }
- };
-}
-
-void getInfo2Point2Point(b3GpuGenericConstraint* constraint, b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
-{
- b3Transform trA;
- trA.setIdentity();
- trA.setOrigin(bodies[constraint->m_rbA].m_pos);
- trA.setRotation(bodies[constraint->m_rbA].m_quat);
-
- b3Transform trB;
- trB.setIdentity();
- trB.setOrigin(bodies[constraint->m_rbB].m_pos);
- trB.setRotation(bodies[constraint->m_rbB].m_quat);
-
- // anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip + 1] = 1;
- info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
-
- b3Vector3 a1 = trA.getBasis() * constraint->getPivotInA();
- //b3Vector3 a1a = b3QuatRotate(trA.getRotation(),constraint->getPivotInA());
-
- {
- b3Vector3* angular0 = (b3Vector3*)(info->m_J1angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J1angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J1angularAxis + 2 * info->rowskip);
- b3Vector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- if (info->m_J2linearAxis)
- {
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip + 1] = -1;
- info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
- }
-
- b3Vector3 a2 = trB.getBasis() * constraint->getPivotInB();
-
- {
- // b3Vector3 a2n = -a2;
- b3Vector3* angular0 = (b3Vector3*)(info->m_J2angularAxis);
- b3Vector3* angular1 = (b3Vector3*)(info->m_J2angularAxis + info->rowskip);
- b3Vector3* angular2 = (b3Vector3*)(info->m_J2angularAxis + 2 * info->rowskip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- // set right hand side
- // b3Scalar currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
- b3Scalar currERP = info->erp;
-
- b3Scalar k = info->fps * currERP;
- int j;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[j * info->rowskip] = k * (a2[j] + trB.getOrigin()[j] - a1[j] - trA.getOrigin()[j]);
- //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
-#if 0
- if(m_flags & B3_P2P_FLAGS_CFM)
- {
- for (j=0; j<3; j++)
- {
- info->cfm[j*info->rowskip] = m_cfm;
- }
- }
-#endif
-
-#if 0
- b3Scalar impulseClamp = m_setting.m_impulseClamp;//
- for (j=0; j<3; j++)
- {
- if (m_setting.m_impulseClamp > 0)
- {
- info->m_lowerLimit[j*info->rowskip] = -impulseClamp;
- info->m_upperLimit[j*info->rowskip] = impulseClamp;
- }
- }
- info->m_damping = m_setting.m_damping;
-#endif
-}
-
-void b3GpuGenericConstraint::getInfo2(b3GpuConstraintInfo2* info, const b3RigidBodyData* bodies)
-{
- switch (m_constraintType)
- {
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
- {
- getInfo2Point2Point(this, info, bodies);
- break;
- };
- default:
- {
- b3Assert(0);
- }
- };
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
deleted file mode 100644
index 1f163ba7d5..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_GPU_GENERIC_CONSTRAINT_H
-#define B3_GPU_GENERIC_CONSTRAINT_H
-
-#include "Bullet3Common/b3Quaternion.h"
-struct b3RigidBodyData;
-enum B3_CONSTRAINT_FLAGS
-{
- B3_CONSTRAINT_FLAG_ENABLED = 1,
-};
-
-enum b3GpuGenericConstraintType
-{
- B3_GPU_POINT2POINT_CONSTRAINT_TYPE = 3,
- B3_GPU_FIXED_CONSTRAINT_TYPE = 4,
- // B3_HINGE_CONSTRAINT_TYPE,
- // B3_CONETWIST_CONSTRAINT_TYPE,
- // B3_D6_CONSTRAINT_TYPE,
- // B3_SLIDER_CONSTRAINT_TYPE,
- // B3_CONTACT_CONSTRAINT_TYPE,
- // B3_D6_SPRING_CONSTRAINT_TYPE,
- // B3_GEAR_CONSTRAINT_TYPE,
-
- B3_GPU_MAX_CONSTRAINT_TYPE
-};
-
-struct b3GpuConstraintInfo2
-{
- // integrator parameters: frames per second (1/stepsize), default error
- // reduction parameter (0..1).
- b3Scalar fps, erp;
-
- // for the first and second body, pointers to two (linear and angular)
- // n*3 jacobian sub matrices, stored by rows. these matrices will have
- // been initialized to 0 on entry. if the second body is zero then the
- // J2xx pointers may be 0.
- b3Scalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
-
- // elements to jump from one row to the next in J's
- int rowskip;
-
- // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
- // "constraint force mixing" vector. c is set to zero on entry, cfm is
- // set to a constant value (typically very small or zero) value on entry.
- b3Scalar *m_constraintError, *cfm;
-
- // lo and hi limits for variables (set to -/+ infinity on entry).
- b3Scalar *m_lowerLimit, *m_upperLimit;
-
- // findex vector for variables. see the LCP solver interface for a
- // description of what this does. this is set to -1 on entry.
- // note that the returned indexes are relative to the first index of
- // the constraint.
- int* findex;
- // number of solver iterations
- int m_numIterations;
-
- //damping of the velocity
- b3Scalar m_damping;
-};
-
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3GpuGenericConstraint
-{
- int m_constraintType;
- int m_rbA;
- int m_rbB;
- float m_breakingImpulseThreshold;
-
- b3Vector3 m_pivotInA;
- b3Vector3 m_pivotInB;
- b3Quaternion m_relTargetAB;
-
- int m_flags;
- int m_uid;
- int m_padding[2];
-
- int getRigidBodyA() const
- {
- return m_rbA;
- }
- int getRigidBodyB() const
- {
- return m_rbB;
- }
-
- const b3Vector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- const b3Vector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- int isEnabled() const
- {
- return m_flags & B3_CONSTRAINT_FLAG_ENABLED;
- }
-
- float getBreakingImpulseThreshold() const
- {
- return m_breakingImpulseThreshold;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- void getInfo1(unsigned int* info, const b3RigidBodyData* bodies);
-
- ///internal method used by the constraint solver, don't use them directly
- void getInfo2(b3GpuConstraintInfo2 * info, const b3RigidBodyData* bodies);
-};
-
-#endif //B3_GPU_GENERIC_CONSTRAINT_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
deleted file mode 100644
index 089fb1f6a6..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.cpp
+++ /dev/null
@@ -1,1305 +0,0 @@
-
-#include "b3GpuJacobiContactSolver.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3FillCL.h" //b3Int2
-class b3Vector3;
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3OpenCL/RigidBody/kernels/solverUtils.h"
-#include "Bullet3Common/b3Logging.h"
-#include "b3GpuConstraint4.h"
-#include "Bullet3Common/shared/b3Int2.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#define SOLVER_UTILS_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl"
-
-struct b3GpuJacobiSolverInternalData
-{
- //btRadixSort32CL* m_sort32;
- //btBoundSearchCL* m_search;
- b3PrefixScanCL* m_scan;
-
- b3OpenCLArray<unsigned int>* m_bodyCount;
- b3OpenCLArray<b3Int2>* m_contactConstraintOffsets;
- b3OpenCLArray<unsigned int>* m_offsetSplitBodies;
-
- b3OpenCLArray<b3Vector3>* m_deltaLinearVelocities;
- b3OpenCLArray<b3Vector3>* m_deltaAngularVelocities;
-
- b3AlignedObjectArray<b3Vector3> m_deltaLinearVelocitiesCPU;
- b3AlignedObjectArray<b3Vector3> m_deltaAngularVelocitiesCPU;
-
- b3OpenCLArray<b3GpuConstraint4>* m_contactConstraints;
-
- b3FillCL* m_filler;
-
- cl_kernel m_countBodiesKernel;
- cl_kernel m_contactToConstraintSplitKernel;
- cl_kernel m_clearVelocitiesKernel;
- cl_kernel m_averageVelocitiesKernel;
- cl_kernel m_updateBodyVelocitiesKernel;
- cl_kernel m_solveContactKernel;
- cl_kernel m_solveFrictionKernel;
-};
-
-b3GpuJacobiContactSolver::b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
- : m_context(ctx),
- m_device(device),
- m_queue(queue)
-{
- m_data = new b3GpuJacobiSolverInternalData;
- m_data->m_scan = new b3PrefixScanCL(m_context, m_device, m_queue);
- m_data->m_bodyCount = new b3OpenCLArray<unsigned int>(m_context, m_queue);
- m_data->m_filler = new b3FillCL(m_context, m_device, m_queue);
- m_data->m_contactConstraintOffsets = new b3OpenCLArray<b3Int2>(m_context, m_queue);
- m_data->m_offsetSplitBodies = new b3OpenCLArray<unsigned int>(m_context, m_queue);
- m_data->m_contactConstraints = new b3OpenCLArray<b3GpuConstraint4>(m_context, m_queue);
- m_data->m_deltaLinearVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
- m_data->m_deltaAngularVelocities = new b3OpenCLArray<b3Vector3>(m_context, m_queue);
-
- cl_int pErrNum;
- const char* additionalMacros = "";
- const char* solverUtilsSource = solverUtilsCL;
- {
- cl_program solverUtilsProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverUtilsSource, &pErrNum, additionalMacros, SOLVER_UTILS_KERNEL_PATH);
- b3Assert(solverUtilsProg);
- m_data->m_countBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "CountBodiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_countBodiesKernel);
-
- m_data->m_contactToConstraintSplitKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ContactToConstraintSplitKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_contactToConstraintSplitKernel);
- m_data->m_clearVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "ClearVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_clearVelocitiesKernel);
-
- m_data->m_averageVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "AverageVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_averageVelocitiesKernel);
-
- m_data->m_updateBodyVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "UpdateBodyVelocitiesKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_updateBodyVelocitiesKernel);
-
- m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveContactJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_solveContactKernel);
-
- m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverUtilsSource, "SolveFrictionJacobiKernel", &pErrNum, solverUtilsProg, additionalMacros);
- b3Assert(m_data->m_solveFrictionKernel);
- }
-}
-
-b3GpuJacobiContactSolver::~b3GpuJacobiContactSolver()
-{
- clReleaseKernel(m_data->m_solveContactKernel);
- clReleaseKernel(m_data->m_solveFrictionKernel);
- clReleaseKernel(m_data->m_countBodiesKernel);
- clReleaseKernel(m_data->m_contactToConstraintSplitKernel);
- clReleaseKernel(m_data->m_averageVelocitiesKernel);
- clReleaseKernel(m_data->m_updateBodyVelocitiesKernel);
- clReleaseKernel(m_data->m_clearVelocitiesKernel);
-
- delete m_data->m_deltaLinearVelocities;
- delete m_data->m_deltaAngularVelocities;
- delete m_data->m_contactConstraints;
- delete m_data->m_offsetSplitBodies;
- delete m_data->m_contactConstraintOffsets;
- delete m_data->m_bodyCount;
- delete m_data->m_filler;
- delete m_data->m_scan;
- delete m_data;
-}
-
-b3Vector3 make_float4(float v)
-{
- return b3MakeVector3(v, v, v);
-}
-
-b3Vector4 make_float4(float x, float y, float z, float w)
-{
- return b3MakeVector4(x, y, z, w);
-}
-
-static inline float calcRelVel(const b3Vector3& l0, const b3Vector3& l1, const b3Vector3& a0, const b3Vector3& a1,
- const b3Vector3& linVel0, const b3Vector3& angVel0, const b3Vector3& linVel1, const b3Vector3& angVel1)
-{
- return b3Dot(l0, linVel0) + b3Dot(a0, angVel0) + b3Dot(l1, linVel1) + b3Dot(a1, angVel1);
-}
-
-static inline void setLinearAndAngular(const b3Vector3& n, const b3Vector3& r0, const b3Vector3& r1,
- b3Vector3& linear, b3Vector3& angular0, b3Vector3& angular1)
-{
- linear = n;
- angular0 = b3Cross(r0, n);
- angular1 = -b3Cross(r1, n);
-}
-
-static __inline void solveContact(b3GpuConstraint4& cs,
- const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
-{
- for (int ic = 0; ic < 4; ic++)
- {
- // dont necessary because this makes change to 0
- if (cs.m_jacCoeffInv[ic] == 0.f) continue;
-
- {
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
- b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, linear, angular0, angular1);
-
- float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
- linVelARO + dLinVelA, angVelARO + dAngVelA, linVelBRO + dLinVelB, angVelBRO + dAngVelB) +
- cs.m_b[ic];
- rambdaDt *= cs.m_jacCoeffInv[ic];
-
- {
- float prevSum = cs.m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[ic]);
- updated = b3Min(updated, maxRambdaDt[ic]);
- rambdaDt = updated - prevSum;
- cs.m_appliedRambdaDt[ic] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
-
- if (invMassA)
- {
- dLinVelA += linImp0;
- dAngVelA += angImp0;
- }
- if (invMassB)
- {
- dLinVelB += linImp1;
- dAngVelB += angImp1;
- }
- }
- }
-}
-
-void solveContact3(b3GpuConstraint4* cs,
- b3Vector3* posAPtr, b3Vector3* linVelA, b3Vector3* angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- b3Vector3* posBPtr, b3Vector3* linVelB, b3Vector3* angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- b3Vector3* dLinVelA, b3Vector3* dAngVelA, b3Vector3* dLinVelB, b3Vector3* dAngVelB)
-{
- float minRambdaDt = 0;
- float maxRambdaDt = FLT_MAX;
-
- for (int ic = 0; ic < 4; ic++)
- {
- if (cs->m_jacCoeffInv[ic] == 0.f) continue;
-
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = cs->m_worldPos[ic] - *posAPtr;
- b3Vector3 r1 = cs->m_worldPos[ic] - *posBPtr;
- setLinearAndAngular(cs->m_linear, r0, r1, linear, angular0, angular1);
-
- float rambdaDt = calcRelVel(cs->m_linear, -cs->m_linear, angular0, angular1,
- *linVelA + *dLinVelA, *angVelA + *dAngVelA, *linVelB + *dLinVelB, *angVelB + *dAngVelB) +
- cs->m_b[ic];
- rambdaDt *= cs->m_jacCoeffInv[ic];
-
- {
- float prevSum = cs->m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt);
- updated = b3Min(updated, maxRambdaDt);
- rambdaDt = updated - prevSum;
- cs->m_appliedRambdaDt[ic] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-
- if (invMassA)
- {
- *dLinVelA += linImp0;
- *dAngVelA += angImp0;
- }
- if (invMassB)
- {
- *dLinVelB += linImp1;
- *dAngVelB += angImp1;
- }
- }
-}
-
-static inline void solveFriction(b3GpuConstraint4& cs,
- const b3Vector3& posA, const b3Vector3& linVelARO, const b3Vector3& angVelARO, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelBRO, const b3Vector3& angVelBRO, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4], b3Vector3& dLinVelA, b3Vector3& dAngVelA, b3Vector3& dLinVelB, b3Vector3& dAngVelB)
-{
- b3Vector3 linVelA = linVelARO + dLinVelA;
- b3Vector3 linVelB = linVelBRO + dLinVelB;
- b3Vector3 angVelA = angVelARO + dAngVelA;
- b3Vector3 angVelB = angVelBRO + dAngVelB;
-
- if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
- const b3Vector3& center = (const b3Vector3&)cs.m_center;
-
- b3Vector3 n = -(const b3Vector3&)cs.m_linear;
-
- b3Vector3 tangent[2];
-#if 1
- b3PlaneSpace1(n, tangent[0], tangent[1]);
-#else
- b3Vector3 r = cs.m_worldPos[0] - center;
- tangent[0] = cross3(n, r);
- tangent[1] = cross3(tangent[0], n);
- tangent[0] = normalize3(tangent[0]);
- tangent[1] = normalize3(tangent[1]);
-#endif
-
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = center - posA;
- b3Vector3 r1 = center - posB;
- for (int i = 0; i < 2; i++)
- {
- setLinearAndAngular(tangent[i], r0, r1, linear, angular0, angular1);
- float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
- rambdaDt *= cs.m_fJacCoeffInv[i];
-
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[i]);
- updated = b3Min(updated, maxRambdaDt[i]);
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
- if (invMassA)
- {
- dLinVelA += linImp0;
- dAngVelA += angImp0;
- }
- if (invMassB)
- {
- dLinVelB += linImp1;
- dAngVelB += angImp1;
- }
- }
-
- { // angular damping for point constraint
- b3Vector3 ab = (posB - posA).normalized();
- b3Vector3 ac = (center - posA).normalized();
- if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = b3Dot(n, angVelA);
- float angNB = b3Dot(n, angVelB);
-
- if (invMassA)
- dAngVelA -= (angNA * 0.1f) * n;
- if (invMassB)
- dAngVelB -= (angNB * 0.1f) * n;
- }
- }
-}
-
-float calcJacCoeff(const b3Vector3& linear0, const b3Vector3& linear1, const b3Vector3& angular0, const b3Vector3& angular1,
- float invMass0, const b3Matrix3x3* invInertia0, float invMass1, const b3Matrix3x3* invInertia1, float countA, float countB)
-{
- // linear0,1 are normlized
- float jmj0 = invMass0; //dot3F4(linear0, linear0)*invMass0;
-
- float jmj1 = b3Dot(mtMul3(angular0, *invInertia0), angular0);
- float jmj2 = invMass1; //dot3F4(linear1, linear1)*invMass1;
- float jmj3 = b3Dot(mtMul3(angular1, *invInertia1), angular1);
- return -1.f / ((jmj0 + jmj1) * countA + (jmj2 + jmj3) * countB);
- // return -1.f/((jmj0+jmj1)+(jmj2+jmj3));
-}
-
-void setConstraint4(const b3Vector3& posA, const b3Vector3& linVelA, const b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, const b3Vector3& linVelB, const b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- b3Contact4* src, float dt, float positionDrift, float positionConstraintCoeff, float countA, float countB,
- b3GpuConstraint4* dstC)
-{
- dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
- dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
-
- float dtInv = 1.f / dt;
- for (int ic = 0; ic < 4; ic++)
- {
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
-
- dstC->m_linear = src->m_worldNormalOnB;
- dstC->m_linear[3] = 0.7f; //src->getFrictionCoeff() );
- for (int ic = 0; ic < 4; ic++)
- {
- b3Vector3 r0 = src->m_worldPosB[ic] - posA;
- b3Vector3 r1 = src->m_worldPosB[ic] - posB;
-
- if (ic >= src->m_worldNormalOnB[3]) //npoints
- {
- dstC->m_jacCoeffInv[ic] = 0.f;
- continue;
- }
-
- float relVelN;
- {
- b3Vector3 linear, angular0, angular1;
- setLinearAndAngular(src->m_worldNormalOnB, r0, r1, linear, angular0, angular1);
-
- dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
-
- relVelN = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
-
- float e = 0.f; //src->getRestituitionCoeff();
- if (relVelN * relVelN < 0.004f)
- {
- e = 0.f;
- }
-
- dstC->m_b[ic] = e * relVelN;
- //float penetration = src->m_worldPos[ic].w;
- dstC->m_b[ic] += (src->m_worldPosB[ic][3] + positionDrift) * positionConstraintCoeff * dtInv;
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- }
-
- if (src->m_worldNormalOnB[3] > 0) //npoints
- { // prepare friction
- b3Vector3 center = make_float4(0.f);
- for (int i = 0; i < src->m_worldNormalOnB[3]; i++)
- center += src->m_worldPosB[i];
- center /= (float)src->m_worldNormalOnB[3];
-
- b3Vector3 tangent[2];
- b3PlaneSpace1(src->m_worldNormalOnB, tangent[0], tangent[1]);
-
- b3Vector3 r[2];
- r[0] = center - posA;
- r[1] = center - posB;
-
- for (int i = 0; i < 2; i++)
- {
- b3Vector3 linear, angular0, angular1;
- setLinearAndAngular(tangent[i], r[0], r[1], linear, angular0, angular1);
-
- dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB, countA, countB);
- dstC->m_fAppliedRambdaDt[i] = 0.f;
- }
- dstC->m_center = center;
- }
-
- for (int i = 0; i < 4; i++)
- {
- if (i < src->m_worldNormalOnB[3])
- {
- dstC->m_worldPos[i] = src->m_worldPosB[i];
- }
- else
- {
- dstC->m_worldPos[i] = make_float4(0.f);
- }
- }
-}
-
-void ContactToConstraintKernel(b3Contact4* gContact, b3RigidBodyData* gBodies, b3InertiaData* gShapes, b3GpuConstraint4* gConstraintOut, int nContacts,
- float dt,
- float positionDrift,
- float positionConstraintCoeff, int gIdx, b3AlignedObjectArray<unsigned int>& bodyCount)
-{
- //int gIdx = 0;//GET_GLOBAL_IDX;
-
- if (gIdx < nContacts)
- {
- int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
- int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
-
- b3Vector3 posA = gBodies[aIdx].m_pos;
- b3Vector3 linVelA = gBodies[aIdx].m_linVel;
- b3Vector3 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- b3Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertiaWorld; //.m_invInertia;
-
- b3Vector3 posB = gBodies[bIdx].m_pos;
- b3Vector3 linVelB = gBodies[bIdx].m_linVel;
- b3Vector3 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- b3Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertiaWorld; //m_invInertia;
-
- b3GpuConstraint4 cs;
- float countA = invMassA ? (float)(bodyCount[aIdx]) : 1;
- float countB = invMassB ? (float)(bodyCount[bIdx]) : 1;
- setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], dt, positionDrift, positionConstraintCoeff, countA, countB,
- &cs);
-
- cs.m_batchIdx = gContact[gIdx].m_batchIdx;
-
- gConstraintOut[gIdx] = cs;
- }
-}
-
-void b3GpuJacobiContactSolver::solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo)
-{
- B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
-
- b3AlignedObjectArray<unsigned int> bodyCount;
- bodyCount.resize(numBodies);
- for (int i = 0; i < numBodies; i++)
- bodyCount[i] = 0;
-
- b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
- contactConstraintOffsets.resize(numManifolds);
-
- for (int i = 0; i < numManifolds; i++)
- {
- int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
- int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
-
- bool isFixedA = (pa < 0) || (pa == solverInfo.m_fixedBodyIndex);
- bool isFixedB = (pb < 0) || (pb == solverInfo.m_fixedBodyIndex);
-
- int bodyIndexA = manifoldPtr[i].getBodyA();
- int bodyIndexB = manifoldPtr[i].getBodyB();
-
- if (!isFixedA)
- {
- contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
- bodyCount[bodyIndexA]++;
- }
- if (!isFixedB)
- {
- contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
- bodyCount[bodyIndexB]++;
- }
- }
-
- b3AlignedObjectArray<unsigned int> offsetSplitBodies;
- offsetSplitBodies.resize(numBodies);
- unsigned int totalNumSplitBodies;
- m_data->m_scan->executeHost(bodyCount, offsetSplitBodies, numBodies, &totalNumSplitBodies);
- int numlastBody = bodyCount[numBodies - 1];
- totalNumSplitBodies += numlastBody;
- printf("totalNumSplitBodies = %d\n", totalNumSplitBodies);
-
- b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
- contactConstraints.resize(numManifolds);
-
- for (int i = 0; i < numManifolds; i++)
- {
- ContactToConstraintKernel(&manifoldPtr[0], bodies, inertias, &contactConstraints[0], numManifolds,
- solverInfo.m_deltaTime,
- solverInfo.m_positionDrift,
- solverInfo.m_positionConstraintCoeff,
- i, bodyCount);
- }
- int maxIter = solverInfo.m_numIterations;
-
- b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
- b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
- deltaLinearVelocities.resize(totalNumSplitBodies);
- deltaAngularVelocities.resize(totalNumSplitBodies);
- for (unsigned int i = 0; i < totalNumSplitBodies; i++)
- {
- deltaLinearVelocities[i].setZero();
- deltaAngularVelocities[i].setZero();
- }
-
- for (int iter = 0; iter < maxIter; iter++)
- {
- int i = 0;
- for (i = 0; i < numManifolds; i++)
- {
- //float frictionCoeff = contactConstraints[i].getFrictionCoeff();
- int aIdx = (int)contactConstraints[i].m_bodyA;
- int bIdx = (int)contactConstraints[i].m_bodyB;
- b3RigidBodyData& bodyA = bodies[aIdx];
- b3RigidBodyData& bodyB = bodies[bIdx];
-
- b3Vector3 zero = b3MakeVector3(0, 0, 0);
-
- b3Vector3* dlvAPtr = &zero;
- b3Vector3* davAPtr = &zero;
- b3Vector3* dlvBPtr = &zero;
- b3Vector3* davBPtr = &zero;
-
- if (bodyA.m_invMass)
- {
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA + constraintOffsetA;
- dlvAPtr = &deltaLinearVelocities[splitIndexA];
- davAPtr = &deltaAngularVelocities[splitIndexA];
- }
-
- if (bodyB.m_invMass)
- {
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB = bodyOffsetB + constraintOffsetB;
- dlvBPtr = &deltaLinearVelocities[splitIndexB];
- davBPtr = &deltaAngularVelocities[splitIndexB];
- }
-
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
-
- solveContact(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
- }
- }
-
- //easy
- for (int i = 0; i < numBodies; i++)
- {
- if (bodies[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- float factor = 1.f / float(count);
- b3Vector3 averageLinVel;
- averageLinVel.setZero();
- b3Vector3 averageAngVel;
- averageAngVel.setZero();
- for (int j = 0; j < count; j++)
- {
- averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
- averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
- }
- for (int j = 0; j < count; j++)
- {
- deltaLinearVelocities[bodyOffset + j] = averageLinVel;
- deltaAngularVelocities[bodyOffset + j] = averageAngVel;
- }
- }
- }
- }
- for (int iter = 0; iter < maxIter; iter++)
- {
- //int i=0;
-
- //solve friction
-
- for (int i = 0; i < numManifolds; i++)
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
-
- float sum = 0;
- for (int j = 0; j < 4; j++)
- {
- sum += contactConstraints[i].m_appliedRambdaDt[j];
- }
- float frictionCoeff = contactConstraints[i].getFrictionCoeff();
- int aIdx = (int)contactConstraints[i].m_bodyA;
- int bIdx = (int)contactConstraints[i].m_bodyB;
- b3RigidBodyData& bodyA = bodies[aIdx];
- b3RigidBodyData& bodyB = bodies[bIdx];
-
- b3Vector3 zero = b3MakeVector3(0, 0, 0);
-
- b3Vector3* dlvAPtr = &zero;
- b3Vector3* davAPtr = &zero;
- b3Vector3* dlvBPtr = &zero;
- b3Vector3* davBPtr = &zero;
-
- if (bodyA.m_invMass)
- {
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA + constraintOffsetA;
- dlvAPtr = &deltaLinearVelocities[splitIndexA];
- davAPtr = &deltaAngularVelocities[splitIndexA];
- }
-
- if (bodyB.m_invMass)
- {
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB = bodyOffsetB + constraintOffsetB;
- dlvBPtr = &deltaLinearVelocities[splitIndexB];
- davBPtr = &deltaAngularVelocities[splitIndexB];
- }
-
- for (int j = 0; j < 4; j++)
- {
- maxRambdaDt[j] = frictionCoeff * sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
-
- solveFriction(contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertias[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertias[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt, *dlvAPtr, *davAPtr, *dlvBPtr, *davBPtr);
- }
-
- //easy
- for (int i = 0; i < numBodies; i++)
- {
- if (bodies[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- float factor = 1.f / float(count);
- b3Vector3 averageLinVel;
- averageLinVel.setZero();
- b3Vector3 averageAngVel;
- averageAngVel.setZero();
- for (int j = 0; j < count; j++)
- {
- averageLinVel += deltaLinearVelocities[bodyOffset + j] * factor;
- averageAngVel += deltaAngularVelocities[bodyOffset + j] * factor;
- }
- for (int j = 0; j < count; j++)
- {
- deltaLinearVelocities[bodyOffset + j] = averageLinVel;
- deltaAngularVelocities[bodyOffset + j] = averageAngVel;
- }
- }
- }
- }
-
- //easy
- for (int i = 0; i < numBodies; i++)
- {
- if (bodies[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- if (count)
- {
- bodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
- bodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
- }
- }
- }
-}
-
-void b3GpuJacobiContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index)
-//
-//
-//void b3GpuJacobiContactSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* bodies,b3OpenCLArray<b3InertiaData>* inertias,b3OpenCLArray<b3Contact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo)
-{
- b3JacobiSolverInfo solverInfo;
- solverInfo.m_fixedBodyIndex = static0Index;
-
- B3_PROFILE("b3GpuJacobiContactSolver::solveGroup");
-
- //int numBodies = bodies->size();
- int numManifolds = numContacts; //manifoldPtr->size();
-
- {
- B3_PROFILE("resize");
- m_data->m_bodyCount->resize(numBodies);
- }
-
- unsigned int val = 0;
- b3Int2 val2;
- val2.x = 0;
- val2.y = 0;
-
- {
- B3_PROFILE("m_filler");
- m_data->m_contactConstraintOffsets->resize(numManifolds);
- m_data->m_filler->execute(*m_data->m_bodyCount, val, numBodies);
-
- m_data->m_filler->execute(*m_data->m_contactConstraintOffsets, val2, numManifolds);
- }
-
- {
- B3_PROFILE("m_countBodiesKernel");
- b3LauncherCL launcher(this->m_queue, m_data->m_countBodiesKernel, "m_countBodiesKernel");
- launcher.setBuffer(contactBuf); //manifoldPtr->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setConst(numManifolds);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.launch1D(numManifolds);
- }
- unsigned int totalNumSplitBodies = 0;
- {
- B3_PROFILE("m_scan->execute");
-
- m_data->m_offsetSplitBodies->resize(numBodies);
- m_data->m_scan->execute(*m_data->m_bodyCount, *m_data->m_offsetSplitBodies, numBodies, &totalNumSplitBodies);
- totalNumSplitBodies += m_data->m_bodyCount->at(numBodies - 1);
- }
-
- {
- B3_PROFILE("m_data->m_contactConstraints->resize");
- //int numContacts = manifoldPtr->size();
- m_data->m_contactConstraints->resize(numContacts);
- }
-
- {
- B3_PROFILE("contactToConstraintSplitKernel");
- b3LauncherCL launcher(m_queue, m_data->m_contactToConstraintSplitKernel, "m_contactToConstraintSplitKernel");
- launcher.setBuffer(contactBuf);
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(inertiaBuf);
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setConst(numContacts);
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.launch1D(numContacts, 64);
- }
-
- {
- B3_PROFILE("m_data->m_deltaLinearVelocities->resize");
- m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
- m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
- }
-
- {
- B3_PROFILE("m_clearVelocitiesKernel");
- b3LauncherCL launch(m_queue, m_data->m_clearVelocitiesKernel, "m_clearVelocitiesKernel");
- launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launch.setConst(totalNumSplitBodies);
- launch.launch1D(totalNumSplitBodies);
- clFinish(m_queue);
- }
-
- int maxIter = solverInfo.m_numIterations;
-
- for (int iter = 0; iter < maxIter; iter++)
- {
- {
- B3_PROFILE("m_solveContactKernel");
- b3LauncherCL launcher(m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(inertiaBuf);
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.setConst(numManifolds);
-
- launcher.launch1D(numManifolds);
- clFinish(m_queue);
- }
-
- {
- B3_PROFILE("average velocities");
- b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-
- {
- B3_PROFILE("m_solveFrictionKernel");
- b3LauncherCL launcher(m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(inertiaBuf);
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.setConst(numManifolds);
-
- launcher.launch1D(numManifolds);
- clFinish(m_queue);
- }
-
- {
- B3_PROFILE("average velocities");
- b3LauncherCL launcher(m_queue, m_data->m_averageVelocitiesKernel, "m_averageVelocitiesKernel");
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
- }
-
- {
- B3_PROFILE("update body velocities");
- b3LauncherCL launcher(m_queue, m_data->m_updateBodyVelocitiesKernel, "m_updateBodyVelocitiesKernel");
- launcher.setBuffer(bodyBuf);
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-}
-
-#if 0
-
-void b3GpuJacobiContactSolver::solveGroupMixed(b3OpenCLArray<b3RigidBodyData>* bodiesGPU,b3OpenCLArray<b3InertiaData>* inertiasGPU,b3OpenCLArray<b3Contact4>* manifoldPtrGPU,const btJacobiSolverInfo& solverInfo)
-{
-
- b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
- bodiesGPU->copyToHost(bodiesCPU);
- b3AlignedObjectArray<b3InertiaData> inertiasCPU;
- inertiasGPU->copyToHost(inertiasCPU);
- b3AlignedObjectArray<b3Contact4> manifoldPtrCPU;
- manifoldPtrGPU->copyToHost(manifoldPtrCPU);
-
- int numBodiesCPU = bodiesGPU->size();
- int numManifoldsCPU = manifoldPtrGPU->size();
- B3_PROFILE("b3GpuJacobiContactSolver::solveGroupMixed");
-
- b3AlignedObjectArray<unsigned int> bodyCount;
- bodyCount.resize(numBodiesCPU);
- for (int i=0;i<numBodiesCPU;i++)
- bodyCount[i] = 0;
-
- b3AlignedObjectArray<b3Int2> contactConstraintOffsets;
- contactConstraintOffsets.resize(numManifoldsCPU);
-
-
- for (int i=0;i<numManifoldsCPU;i++)
- {
- int pa = manifoldPtrCPU[i].m_bodyAPtrAndSignBit;
- int pb = manifoldPtrCPU[i].m_bodyBPtrAndSignBit;
-
- bool isFixedA = (pa <0) || (pa == solverInfo.m_fixedBodyIndex);
- bool isFixedB = (pb <0) || (pb == solverInfo.m_fixedBodyIndex);
-
- int bodyIndexA = manifoldPtrCPU[i].getBodyA();
- int bodyIndexB = manifoldPtrCPU[i].getBodyB();
-
- if (!isFixedA)
- {
- contactConstraintOffsets[i].x = bodyCount[bodyIndexA];
- bodyCount[bodyIndexA]++;
- }
- if (!isFixedB)
- {
- contactConstraintOffsets[i].y = bodyCount[bodyIndexB];
- bodyCount[bodyIndexB]++;
- }
- }
-
- b3AlignedObjectArray<unsigned int> offsetSplitBodies;
- offsetSplitBodies.resize(numBodiesCPU);
- unsigned int totalNumSplitBodiesCPU;
- m_data->m_scan->executeHost(bodyCount,offsetSplitBodies,numBodiesCPU,&totalNumSplitBodiesCPU);
- int numlastBody = bodyCount[numBodiesCPU-1];
- totalNumSplitBodiesCPU += numlastBody;
-
- int numBodies = bodiesGPU->size();
- int numManifolds = manifoldPtrGPU->size();
-
- m_data->m_bodyCount->resize(numBodies);
-
- unsigned int val=0;
- b3Int2 val2;
- val2.x=0;
- val2.y=0;
-
- {
- B3_PROFILE("m_filler");
- m_data->m_contactConstraintOffsets->resize(numManifolds);
- m_data->m_filler->execute(*m_data->m_bodyCount,val,numBodies);
-
-
- m_data->m_filler->execute(*m_data->m_contactConstraintOffsets,val2,numManifolds);
- }
-
- {
- B3_PROFILE("m_countBodiesKernel");
- b3LauncherCL launcher(this->m_queue,m_data->m_countBodiesKernel);
- launcher.setBuffer(manifoldPtrGPU->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setConst(numManifolds);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.launch1D(numManifolds);
- }
-
- unsigned int totalNumSplitBodies=0;
- m_data->m_offsetSplitBodies->resize(numBodies);
- m_data->m_scan->execute(*m_data->m_bodyCount,*m_data->m_offsetSplitBodies,numBodies,&totalNumSplitBodies);
- totalNumSplitBodies+=m_data->m_bodyCount->at(numBodies-1);
-
- if (totalNumSplitBodies != totalNumSplitBodiesCPU)
- {
- printf("error in totalNumSplitBodies!\n");
- }
-
- int numContacts = manifoldPtrGPU->size();
- m_data->m_contactConstraints->resize(numContacts);
-
-
- {
- B3_PROFILE("contactToConstraintSplitKernel");
- b3LauncherCL launcher( m_queue, m_data->m_contactToConstraintSplitKernel);
- launcher.setBuffer(manifoldPtrGPU->getBufferCL());
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(inertiasGPU->getBufferCL());
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setConst(numContacts);
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.launch1D( numContacts, 64 );
- clFinish(m_queue);
- }
-
-
-
- b3AlignedObjectArray<b3GpuConstraint4> contactConstraints;
- contactConstraints.resize(numManifoldsCPU);
-
- for (int i=0;i<numManifoldsCPU;i++)
- {
- ContactToConstraintKernel(&manifoldPtrCPU[0],&bodiesCPU[0],&inertiasCPU[0],&contactConstraints[0],numManifoldsCPU,
- solverInfo.m_deltaTime,
- solverInfo.m_positionDrift,
- solverInfo.m_positionConstraintCoeff,
- i, bodyCount);
- }
- int maxIter = solverInfo.m_numIterations;
-
-
- b3AlignedObjectArray<b3Vector3> deltaLinearVelocities;
- b3AlignedObjectArray<b3Vector3> deltaAngularVelocities;
- deltaLinearVelocities.resize(totalNumSplitBodiesCPU);
- deltaAngularVelocities.resize(totalNumSplitBodiesCPU);
- for (int i=0;i<totalNumSplitBodiesCPU;i++)
- {
- deltaLinearVelocities[i].setZero();
- deltaAngularVelocities[i].setZero();
- }
-
- m_data->m_deltaLinearVelocities->resize(totalNumSplitBodies);
- m_data->m_deltaAngularVelocities->resize(totalNumSplitBodies);
-
-
-
- {
- B3_PROFILE("m_clearVelocitiesKernel");
- b3LauncherCL launch(m_queue,m_data->m_clearVelocitiesKernel);
- launch.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launch.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launch.setConst(totalNumSplitBodies);
- launch.launch1D(totalNumSplitBodies);
- }
-
-
- ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-
- m_data->m_contactConstraints->copyToHost(contactConstraints);
- m_data->m_offsetSplitBodies->copyToHost(offsetSplitBodies);
- m_data->m_contactConstraintOffsets->copyToHost(contactConstraintOffsets);
- m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
- m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
-
- for (int iter = 0;iter<maxIter;iter++)
- {
-
- {
- B3_PROFILE("m_solveContactKernel");
- b3LauncherCL launcher( m_queue, m_data->m_solveContactKernel );
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(inertiasGPU->getBufferCL());
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.setConst(numManifolds);
-
- launcher.launch1D(numManifolds);
- clFinish(m_queue);
- }
-
-
- int i=0;
- for( i=0; i<numManifoldsCPU; i++)
- {
-
- float frictionCoeff = contactConstraints[i].getFrictionCoeff();
- int aIdx = (int)contactConstraints[i].m_bodyA;
- int bIdx = (int)contactConstraints[i].m_bodyB;
- b3RigidBodyData& bodyA = bodiesCPU[aIdx];
- b3RigidBodyData& bodyB = bodiesCPU[bIdx];
-
- b3Vector3 zero(0,0,0);
-
- b3Vector3* dlvAPtr=&zero;
- b3Vector3* davAPtr=&zero;
- b3Vector3* dlvBPtr=&zero;
- b3Vector3* davBPtr=&zero;
-
- if (bodyA.m_invMass)
- {
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
- dlvAPtr = &deltaLinearVelocities[splitIndexA];
- davAPtr = &deltaAngularVelocities[splitIndexA];
- }
-
- if (bodyB.m_invMass)
- {
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
- dlvBPtr =&deltaLinearVelocities[splitIndexB];
- davBPtr = &deltaAngularVelocities[splitIndexB];
- }
-
-
-
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- solveContact( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, inertiasCPU[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr );
-
-
- }
- }
-
-
- {
- B3_PROFILE("average velocities");
- b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-
- //easy
- for (int i=0;i<numBodiesCPU;i++)
- {
- if (bodiesCPU[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- float factor = 1.f/float(count);
- b3Vector3 averageLinVel;
- averageLinVel.setZero();
- b3Vector3 averageAngVel;
- averageAngVel.setZero();
- for (int j=0;j<count;j++)
- {
- averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
- averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
- }
- for (int j=0;j<count;j++)
- {
- deltaLinearVelocities[bodyOffset+j] = averageLinVel;
- deltaAngularVelocities[bodyOffset+j] = averageAngVel;
- }
- }
- }
-// m_data->m_deltaAngularVelocities->copyFromHost(deltaAngularVelocities);
- //m_data->m_deltaLinearVelocities->copyFromHost(deltaLinearVelocities);
- m_data->m_deltaAngularVelocities->copyToHost(deltaAngularVelocities);
- m_data->m_deltaLinearVelocities->copyToHost(deltaLinearVelocities);
-
-#if 0
-
- {
- B3_PROFILE("m_solveFrictionKernel");
- b3LauncherCL launcher( m_queue, m_data->m_solveFrictionKernel);
- launcher.setBuffer(m_data->m_contactConstraints->getBufferCL());
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(inertiasGPU->getBufferCL());
- launcher.setBuffer(m_data->m_contactConstraintOffsets->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(solverInfo.m_deltaTime);
- launcher.setConst(solverInfo.m_positionDrift);
- launcher.setConst(solverInfo.m_positionConstraintCoeff);
- launcher.setConst(solverInfo.m_fixedBodyIndex);
- launcher.setConst(numManifolds);
-
- launcher.launch1D(numManifolds);
- clFinish(m_queue);
- }
-
- //solve friction
-
- for(int i=0; i<numManifoldsCPU; i++)
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- float sum = 0;
- for(int j=0; j<4; j++)
- {
- sum +=contactConstraints[i].m_appliedRambdaDt[j];
- }
- float frictionCoeff = contactConstraints[i].getFrictionCoeff();
- int aIdx = (int)contactConstraints[i].m_bodyA;
- int bIdx = (int)contactConstraints[i].m_bodyB;
- b3RigidBodyData& bodyA = bodiesCPU[aIdx];
- b3RigidBodyData& bodyB = bodiesCPU[bIdx];
-
- b3Vector3 zero(0,0,0);
-
- b3Vector3* dlvAPtr=&zero;
- b3Vector3* davAPtr=&zero;
- b3Vector3* dlvBPtr=&zero;
- b3Vector3* davBPtr=&zero;
-
- if (bodyA.m_invMass)
- {
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[i].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
- dlvAPtr = &deltaLinearVelocities[splitIndexA];
- davAPtr = &deltaAngularVelocities[splitIndexA];
- }
-
- if (bodyB.m_invMass)
- {
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[i].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
- dlvBPtr =&deltaLinearVelocities[splitIndexB];
- davBPtr = &deltaAngularVelocities[splitIndexB];
- }
-
- for(int j=0; j<4; j++)
- {
- maxRambdaDt[j] = frictionCoeff*sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
-
- solveFriction( contactConstraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,inertiasCPU[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, inertiasCPU[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt , *dlvAPtr,*davAPtr,*dlvBPtr,*davBPtr);
-
- }
-
- {
- B3_PROFILE("average velocities");
- b3LauncherCL launcher( m_queue, m_data->m_averageVelocitiesKernel);
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-
- //easy
- for (int i=0;i<numBodiesCPU;i++)
- {
- if (bodiesCPU[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- float factor = 1.f/float(count);
- b3Vector3 averageLinVel;
- averageLinVel.setZero();
- b3Vector3 averageAngVel;
- averageAngVel.setZero();
- for (int j=0;j<count;j++)
- {
- averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
- averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
- }
- for (int j=0;j<count;j++)
- {
- deltaLinearVelocities[bodyOffset+j] = averageLinVel;
- deltaAngularVelocities[bodyOffset+j] = averageAngVel;
- }
- }
- }
-
-#endif
-
- }
-
- {
- B3_PROFILE("update body velocities");
- b3LauncherCL launcher( m_queue, m_data->m_updateBodyVelocitiesKernel);
- launcher.setBuffer(bodiesGPU->getBufferCL());
- launcher.setBuffer(m_data->m_offsetSplitBodies->getBufferCL());
- launcher.setBuffer(m_data->m_bodyCount->getBufferCL());
- launcher.setBuffer(m_data->m_deltaLinearVelocities->getBufferCL());
- launcher.setBuffer(m_data->m_deltaAngularVelocities->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_queue);
- }
-
-
- //easy
- for (int i=0;i<numBodiesCPU;i++)
- {
- if (bodiesCPU[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- if (count)
- {
- bodiesCPU[i].m_linVel += deltaLinearVelocities[bodyOffset];
- bodiesCPU[i].m_angVel += deltaAngularVelocities[bodyOffset];
- }
- }
- }
-
-
-// bodiesGPU->copyFromHost(bodiesCPU);
-
-
-}
-#endif
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
deleted file mode 100644
index 8281aee05d..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuJacobiContactSolver.h
+++ /dev/null
@@ -1,56 +0,0 @@
-
-#ifndef B3_GPU_JACOBI_CONTACT_SOLVER_H
-#define B3_GPU_JACOBI_CONTACT_SOLVER_H
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-//#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-
-//struct b3InertiaData;
-//b3InertiaData
-
-class b3TypedConstraint;
-
-struct b3JacobiSolverInfo
-{
- int m_fixedBodyIndex;
-
- float m_deltaTime;
- float m_positionDrift;
- float m_positionConstraintCoeff;
- int m_numIterations;
-
- b3JacobiSolverInfo()
- : m_fixedBodyIndex(0),
- m_deltaTime(1. / 60.f),
- m_positionDrift(0.005f),
- m_positionConstraintCoeff(0.99f),
- m_numIterations(7)
- {
- }
-};
-class b3GpuJacobiContactSolver
-{
-protected:
- struct b3GpuJacobiSolverInternalData* m_data;
-
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
-public:
- b3GpuJacobiContactSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
- virtual ~b3GpuJacobiContactSolver();
-
- void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
- void solveGroupHost(b3RigidBodyData* bodies, b3InertiaData* inertias, int numBodies, struct b3Contact4* manifoldPtr, int numManifolds, const b3JacobiSolverInfo& solverInfo);
- //void solveGroupHost(btRigidBodyCL* bodies,b3InertiaData* inertias,int numBodies,btContact4* manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btJacobiSolverInfo& solverInfo);
-
- //b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies,b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies,b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints,int numConstraints,const b3ContactSolverInfo& infoGlobal);
-
- //void solveGroup(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
- //void solveGroupMixed(btOpenCLArray<btRigidBodyCL>* bodies,btOpenCLArray<btInertiaCL>* inertias,btOpenCLArray<btContact4>* manifoldPtr,const btJacobiSolverInfo& solverInfo);
-};
-#endif //B3_GPU_JACOBI_CONTACT_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
deleted file mode 100644
index 2e4f6c1572..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-#include "b3GpuNarrowPhase.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3ConvexHullContact.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
-#include <string.h>
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3OptimizedBvh.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3TriangleIndexVertexArray.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
-
-#include "b3GpuNarrowPhaseInternalData.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3ConvexUtility.h"
-
-b3GpuNarrowPhase::b3GpuNarrowPhase(cl_context ctx, cl_device_id device, cl_command_queue queue, const b3Config& config)
- : m_data(0), m_planeBodyIndex(-1), m_static0Index(-1), m_context(ctx), m_device(device), m_queue(queue)
-{
- m_data = new b3GpuNarrowPhaseInternalData();
- m_data->m_currentContactBuffer = 0;
-
- memset(m_data, 0, sizeof(b3GpuNarrowPhaseInternalData));
-
- m_data->m_config = config;
-
- m_data->m_gpuSatCollision = new GpuSatCollision(ctx, device, queue);
-
- m_data->m_triangleConvexPairs = new b3OpenCLArray<b3Int4>(m_context, m_queue, config.m_maxTriConvexPairCapacity);
-
- //m_data->m_convexPairsOutGPU = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
- //m_data->m_planePairs = new b3OpenCLArray<b3Int2>(ctx,queue,config.m_maxBroadphasePairs,false);
-
- m_data->m_pBufContactOutCPU = new b3AlignedObjectArray<b3Contact4>();
- m_data->m_pBufContactOutCPU->resize(config.m_maxBroadphasePairs);
- m_data->m_bodyBufferCPU = new b3AlignedObjectArray<b3RigidBodyData>();
- m_data->m_bodyBufferCPU->resize(config.m_maxConvexBodies);
-
- m_data->m_inertiaBufferCPU = new b3AlignedObjectArray<b3InertiaData>();
- m_data->m_inertiaBufferCPU->resize(config.m_maxConvexBodies);
-
- m_data->m_pBufContactBuffersGPU[0] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
- m_data->m_pBufContactBuffersGPU[1] = new b3OpenCLArray<b3Contact4>(ctx, queue, config.m_maxContactCapacity, true);
-
- m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, queue, config.m_maxConvexBodies, false);
- m_data->m_collidablesGPU = new b3OpenCLArray<b3Collidable>(ctx, queue, config.m_maxConvexShapes);
- m_data->m_collidablesCPU.reserve(config.m_maxConvexShapes);
-
- m_data->m_localShapeAABBCPU = new b3AlignedObjectArray<b3SapAabb>;
- m_data->m_localShapeAABBGPU = new b3OpenCLArray<b3SapAabb>(ctx, queue, config.m_maxConvexShapes);
-
- //m_data->m_solverDataGPU = adl::Solver<adl::TYPE_CL>::allocate(ctx,queue, config.m_maxBroadphasePairs,false);
- m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, queue, config.m_maxConvexBodies, false);
-
- m_data->m_convexFacesGPU = new b3OpenCLArray<b3GpuFace>(ctx, queue, config.m_maxConvexShapes * config.m_maxFacesPerShape, false);
- m_data->m_convexFaces.reserve(config.m_maxConvexShapes * config.m_maxFacesPerShape);
-
- m_data->m_gpuChildShapes = new b3OpenCLArray<b3GpuChildShape>(ctx, queue, config.m_maxCompoundChildShapes, false);
-
- m_data->m_convexPolyhedraGPU = new b3OpenCLArray<b3ConvexPolyhedronData>(ctx, queue, config.m_maxConvexShapes, false);
- m_data->m_convexPolyhedra.reserve(config.m_maxConvexShapes);
-
- m_data->m_uniqueEdgesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexUniqueEdges, true);
- m_data->m_uniqueEdges.reserve(config.m_maxConvexUniqueEdges);
-
- m_data->m_convexVerticesGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexVertices, true);
- m_data->m_convexVertices.reserve(config.m_maxConvexVertices);
-
- m_data->m_convexIndicesGPU = new b3OpenCLArray<int>(ctx, queue, config.m_maxConvexIndices, true);
- m_data->m_convexIndices.reserve(config.m_maxConvexIndices);
-
- m_data->m_worldVertsB1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
- m_data->m_clippingFacesOutGPU = new b3OpenCLArray<b3Int4>(ctx, queue, config.m_maxConvexBodies);
- m_data->m_worldNormalsAGPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies);
- m_data->m_worldVertsA1GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
- m_data->m_worldVertsB2GPU = new b3OpenCLArray<b3Vector3>(ctx, queue, config.m_maxConvexBodies * config.m_maxVerticesPerFace);
-
- m_data->m_convexData = new b3AlignedObjectArray<b3ConvexUtility*>();
-
- m_data->m_convexData->resize(config.m_maxConvexShapes);
- m_data->m_convexPolyhedra.resize(config.m_maxConvexShapes);
-
- m_data->m_numAcceleratedShapes = 0;
- m_data->m_numAcceleratedRigidBodies = 0;
-
- m_data->m_subTreesGPU = new b3OpenCLArray<b3BvhSubtreeInfo>(this->m_context, this->m_queue);
- m_data->m_treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context, this->m_queue);
- m_data->m_bvhInfoGPU = new b3OpenCLArray<b3BvhInfo>(this->m_context, this->m_queue);
-
- //m_data->m_contactCGPU = new b3OpenCLArray<Constraint4>(ctx,queue,config.m_maxBroadphasePairs,false);
- //m_data->m_frictionCGPU = new b3OpenCLArray<adl::Solver<adl::TYPE_CL>::allocateFrictionConstraint( m_data->m_deviceCL, config.m_maxBroadphasePairs);
-}
-
-b3GpuNarrowPhase::~b3GpuNarrowPhase()
-{
- delete m_data->m_gpuSatCollision;
-
- delete m_data->m_triangleConvexPairs;
- //delete m_data->m_convexPairsOutGPU;
- //delete m_data->m_planePairs;
- delete m_data->m_pBufContactOutCPU;
- delete m_data->m_bodyBufferCPU;
- delete m_data->m_inertiaBufferCPU;
- delete m_data->m_pBufContactBuffersGPU[0];
- delete m_data->m_pBufContactBuffersGPU[1];
-
- delete m_data->m_inertiaBufferGPU;
- delete m_data->m_collidablesGPU;
- delete m_data->m_localShapeAABBCPU;
- delete m_data->m_localShapeAABBGPU;
- delete m_data->m_bodyBufferGPU;
- delete m_data->m_convexFacesGPU;
- delete m_data->m_gpuChildShapes;
- delete m_data->m_convexPolyhedraGPU;
- delete m_data->m_uniqueEdgesGPU;
- delete m_data->m_convexVerticesGPU;
- delete m_data->m_convexIndicesGPU;
- delete m_data->m_worldVertsB1GPU;
- delete m_data->m_clippingFacesOutGPU;
- delete m_data->m_worldNormalsAGPU;
- delete m_data->m_worldVertsA1GPU;
- delete m_data->m_worldVertsB2GPU;
-
- delete m_data->m_bvhInfoGPU;
-
- for (int i = 0; i < m_data->m_bvhData.size(); i++)
- {
- delete m_data->m_bvhData[i];
- }
- for (int i = 0; i < m_data->m_meshInterfaces.size(); i++)
- {
- delete m_data->m_meshInterfaces[i];
- }
- m_data->m_meshInterfaces.clear();
- m_data->m_bvhData.clear();
- delete m_data->m_treeNodesGPU;
- delete m_data->m_subTreesGPU;
-
- delete m_data->m_convexData;
- delete m_data;
-}
-
-int b3GpuNarrowPhase::allocateCollidable()
-{
- int curSize = m_data->m_collidablesCPU.size();
- if (curSize < m_data->m_config.m_maxConvexShapes)
- {
- m_data->m_collidablesCPU.expand();
- return curSize;
- }
- else
- {
- b3Error("allocateCollidable out-of-range %d\n", m_data->m_config.m_maxConvexShapes);
- }
- return -1;
-}
-
-int b3GpuNarrowPhase::registerSphereShape(float radius)
-{
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = getCollidableCpu(collidableIndex);
- col.m_shapeType = SHAPE_SPHERE;
- col.m_shapeIndex = 0;
- col.m_radius = radius;
-
- if (col.m_shapeIndex >= 0)
- {
- b3SapAabb aabb;
- b3Vector3 myAabbMin = b3MakeVector3(-radius, -radius, -radius);
- b3Vector3 myAabbMax = b3MakeVector3(radius, radius, radius);
-
- aabb.m_min[0] = myAabbMin[0]; //s_convexHeightField->m_aabb.m_min.x;
- aabb.m_min[1] = myAabbMin[1]; //s_convexHeightField->m_aabb.m_min.y;
- aabb.m_min[2] = myAabbMin[2]; //s_convexHeightField->m_aabb.m_min.z;
- aabb.m_minIndices[3] = 0;
-
- aabb.m_max[0] = myAabbMax[0]; //s_convexHeightField->m_aabb.m_max.x;
- aabb.m_max[1] = myAabbMax[1]; //s_convexHeightField->m_aabb.m_max.y;
- aabb.m_max[2] = myAabbMax[2]; //s_convexHeightField->m_aabb.m_max.z;
- aabb.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabb);
- // m_data->m_localShapeAABBGPU->push_back(aabb);
- clFinish(m_queue);
- }
-
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerFace(const b3Vector3& faceNormal, float faceConstant)
-{
- int faceOffset = m_data->m_convexFaces.size();
- b3GpuFace& face = m_data->m_convexFaces.expand();
- face.m_plane = b3MakeVector3(faceNormal.x, faceNormal.y, faceNormal.z, faceConstant);
- return faceOffset;
-}
-
-int b3GpuNarrowPhase::registerPlaneShape(const b3Vector3& planeNormal, float planeConstant)
-{
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = getCollidableCpu(collidableIndex);
- col.m_shapeType = SHAPE_PLANE;
- col.m_shapeIndex = registerFace(planeNormal, planeConstant);
- col.m_radius = planeConstant;
-
- if (col.m_shapeIndex >= 0)
- {
- b3SapAabb aabb;
- aabb.m_min[0] = -1e30f;
- aabb.m_min[1] = -1e30f;
- aabb.m_min[2] = -1e30f;
- aabb.m_minIndices[3] = 0;
-
- aabb.m_max[0] = 1e30f;
- aabb.m_max[1] = 1e30f;
- aabb.m_max[2] = 1e30f;
- aabb.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabb);
- // m_data->m_localShapeAABBGPU->push_back(aabb);
- clFinish(m_queue);
- }
-
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerConvexHullShapeInternal(b3ConvexUtility* convexPtr, b3Collidable& col)
-{
- m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
- convex.mC = convexPtr->mC;
- convex.mE = convexPtr->mE;
- convex.m_extents = convexPtr->m_extents;
- convex.m_localCenter = convexPtr->m_localCenter;
- convex.m_radius = convexPtr->m_radius;
-
- convex.m_numUniqueEdges = convexPtr->m_uniqueEdges.size();
- int edgeOffset = m_data->m_uniqueEdges.size();
- convex.m_uniqueEdgesOffset = edgeOffset;
-
- m_data->m_uniqueEdges.resize(edgeOffset + convex.m_numUniqueEdges);
-
- //convex data here
- int i;
- for (i = 0; i < convexPtr->m_uniqueEdges.size(); i++)
- {
- m_data->m_uniqueEdges[edgeOffset + i] = convexPtr->m_uniqueEdges[i];
- }
-
- int faceOffset = m_data->m_convexFaces.size();
- convex.m_faceOffset = faceOffset;
- convex.m_numFaces = convexPtr->m_faces.size();
-
- m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
-
- for (i = 0; i < convexPtr->m_faces.size(); i++)
- {
- m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector3(convexPtr->m_faces[i].m_plane[0],
- convexPtr->m_faces[i].m_plane[1],
- convexPtr->m_faces[i].m_plane[2],
- convexPtr->m_faces[i].m_plane[3]);
-
- int indexOffset = m_data->m_convexIndices.size();
- int numIndices = convexPtr->m_faces[i].m_indices.size();
- m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset + numIndices);
- for (int p = 0; p < numIndices; p++)
- {
- m_data->m_convexIndices[indexOffset + p] = convexPtr->m_faces[i].m_indices[p];
- }
- }
-
- convex.m_numVertices = convexPtr->m_vertices.size();
- int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset = vertexOffset;
-
- m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
- for (int i = 0; i < convexPtr->m_vertices.size(); i++)
- {
- m_data->m_convexVertices[vertexOffset + i] = convexPtr->m_vertices[i];
- }
-
- (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = convexPtr;
-
- return m_data->m_numAcceleratedShapes++;
-}
-
-int b3GpuNarrowPhase::registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling)
-{
- b3AlignedObjectArray<b3Vector3> verts;
-
- unsigned char* vts = (unsigned char*)vertices;
- for (int i = 0; i < numVertices; i++)
- {
- float* vertex = (float*)&vts[i * strideInBytes];
- verts.push_back(b3MakeVector3(vertex[0] * scaling[0], vertex[1] * scaling[1], vertex[2] * scaling[2]));
- }
-
- b3ConvexUtility* utilPtr = new b3ConvexUtility();
- bool merge = true;
- if (numVertices)
- {
- utilPtr->initializePolyhedralFeatures(&verts[0], verts.size(), merge);
- }
-
- int collidableIndex = registerConvexHullShape(utilPtr);
- delete utilPtr;
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerConvexHullShape(b3ConvexUtility* utilPtr)
-{
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = getCollidableCpu(collidableIndex);
- col.m_shapeType = SHAPE_CONVEX_HULL;
- col.m_shapeIndex = -1;
-
- {
- b3Vector3 localCenter = b3MakeVector3(0, 0, 0);
- for (int i = 0; i < utilPtr->m_vertices.size(); i++)
- localCenter += utilPtr->m_vertices[i];
- localCenter *= (1.f / utilPtr->m_vertices.size());
- utilPtr->m_localCenter = localCenter;
-
- col.m_shapeIndex = registerConvexHullShapeInternal(utilPtr, col);
- }
-
- if (col.m_shapeIndex >= 0)
- {
- b3SapAabb aabb;
-
- b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
- b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
-
- for (int i = 0; i < utilPtr->m_vertices.size(); i++)
- {
- myAabbMin.setMin(utilPtr->m_vertices[i]);
- myAabbMax.setMax(utilPtr->m_vertices[i]);
- }
- aabb.m_min[0] = myAabbMin[0];
- aabb.m_min[1] = myAabbMin[1];
- aabb.m_min[2] = myAabbMin[2];
- aabb.m_minIndices[3] = 0;
-
- aabb.m_max[0] = myAabbMax[0];
- aabb.m_max[1] = myAabbMax[1];
- aabb.m_max[2] = myAabbMax[2];
- aabb.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabb);
- // m_data->m_localShapeAABBGPU->push_back(aabb);
- }
-
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes)
-{
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = getCollidableCpu(collidableIndex);
- col.m_shapeType = SHAPE_COMPOUND_OF_CONVEX_HULLS;
- col.m_shapeIndex = m_data->m_cpuChildShapes.size();
- col.m_compoundBvhIndex = m_data->m_bvhInfoCPU.size();
-
- {
- b3Assert(col.m_shapeIndex + childShapes->size() < m_data->m_config.m_maxCompoundChildShapes);
- for (int i = 0; i < childShapes->size(); i++)
- {
- m_data->m_cpuChildShapes.push_back(childShapes->at(i));
- }
- }
-
- col.m_numChildShapes = childShapes->size();
-
- b3SapAabb aabbLocalSpace;
- b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
- b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
-
- b3AlignedObjectArray<b3Aabb> childLocalAabbs;
- childLocalAabbs.resize(childShapes->size());
-
- //compute local AABB of the compound of all children
- for (int i = 0; i < childShapes->size(); i++)
- {
- int childColIndex = childShapes->at(i).m_shapeIndex;
- //b3Collidable& childCol = getCollidableCpu(childColIndex);
- b3SapAabb aabbLoc = m_data->m_localShapeAABBCPU->at(childColIndex);
-
- b3Vector3 childLocalAabbMin = b3MakeVector3(aabbLoc.m_min[0], aabbLoc.m_min[1], aabbLoc.m_min[2]);
- b3Vector3 childLocalAabbMax = b3MakeVector3(aabbLoc.m_max[0], aabbLoc.m_max[1], aabbLoc.m_max[2]);
- b3Vector3 aMin, aMax;
- b3Scalar margin(0.f);
- b3Transform childTr;
- childTr.setIdentity();
-
- childTr.setOrigin(childShapes->at(i).m_childPosition);
- childTr.setRotation(b3Quaternion(childShapes->at(i).m_childOrientation));
- b3TransformAabb(childLocalAabbMin, childLocalAabbMax, margin, childTr, aMin, aMax);
- myAabbMin.setMin(aMin);
- myAabbMax.setMax(aMax);
- childLocalAabbs[i].m_min[0] = aMin[0];
- childLocalAabbs[i].m_min[1] = aMin[1];
- childLocalAabbs[i].m_min[2] = aMin[2];
- childLocalAabbs[i].m_min[3] = 0;
- childLocalAabbs[i].m_max[0] = aMax[0];
- childLocalAabbs[i].m_max[1] = aMax[1];
- childLocalAabbs[i].m_max[2] = aMax[2];
- childLocalAabbs[i].m_max[3] = 0;
- }
-
- aabbLocalSpace.m_min[0] = myAabbMin[0]; //s_convexHeightField->m_aabb.m_min.x;
- aabbLocalSpace.m_min[1] = myAabbMin[1]; //s_convexHeightField->m_aabb.m_min.y;
- aabbLocalSpace.m_min[2] = myAabbMin[2]; //s_convexHeightField->m_aabb.m_min.z;
- aabbLocalSpace.m_minIndices[3] = 0;
-
- aabbLocalSpace.m_max[0] = myAabbMax[0]; //s_convexHeightField->m_aabb.m_max.x;
- aabbLocalSpace.m_max[1] = myAabbMax[1]; //s_convexHeightField->m_aabb.m_max.y;
- aabbLocalSpace.m_max[2] = myAabbMax[2]; //s_convexHeightField->m_aabb.m_max.z;
- aabbLocalSpace.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabbLocalSpace);
-
- b3QuantizedBvh* bvh = new b3QuantizedBvh;
- bvh->setQuantizationValues(myAabbMin, myAabbMax);
- QuantizedNodeArray& nodes = bvh->getLeafNodeArray();
- int numNodes = childShapes->size();
-
- for (int i = 0; i < numNodes; i++)
- {
- b3QuantizedBvhNode node;
- b3Vector3 aabbMin, aabbMax;
- aabbMin = (b3Vector3&)childLocalAabbs[i].m_min;
- aabbMax = (b3Vector3&)childLocalAabbs[i].m_max;
-
- bvh->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
- bvh->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
- int partId = 0;
- node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | i;
- nodes.push_back(node);
- }
- bvh->buildInternal();
-
- int numSubTrees = bvh->getSubtreeInfoArray().size();
-
- //void setQuantizationValues(const b3Vector3& bvhAabbMin,const b3Vector3& bvhAabbMax,b3Scalar quantizationMargin=b3Scalar(1.0));
- //QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
- ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
- //void buildInternal();
-
- b3BvhInfo bvhInfo;
-
- bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
- bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
- bvhInfo.m_quantization = bvh->m_bvhQuantization;
- bvhInfo.m_numNodes = numNodes;
- bvhInfo.m_numSubTrees = numSubTrees;
- bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
- bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
-
- int numNewNodes = bvh->getQuantizedNodeArray().size();
-
- for (int i = 0; i < numNewNodes - 1; i++)
- {
- if (bvh->getQuantizedNodeArray()[i].isLeafNode())
- {
- int orgIndex = bvh->getQuantizedNodeArray()[i].getTriangleIndex();
-
- b3Vector3 nodeMinVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMin);
- b3Vector3 nodeMaxVec = bvh->unQuantize(bvh->getQuantizedNodeArray()[i].m_quantizedAabbMax);
-
- for (int c = 0; c < 3; c++)
- {
- if (childLocalAabbs[orgIndex].m_min[c] < nodeMinVec[c])
- {
- printf("min org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_min[c], nodeMinVec[c], i, c);
- }
- if (childLocalAabbs[orgIndex].m_max[c] > nodeMaxVec[c])
- {
- printf("max org (%f) and new (%f) ? at i:%d,c:%d\n", childLocalAabbs[i].m_max[c], nodeMaxVec[c], i, c);
- }
- }
- }
- }
-
- m_data->m_bvhInfoCPU.push_back(bvhInfo);
-
- int numNewSubtrees = bvh->getSubtreeInfoArray().size();
- m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
- for (int i = 0; i < numNewSubtrees; i++)
- {
- m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
- }
- int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
-
- for (int i = 0; i < numNewTreeNodes; i++)
- {
- m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
- }
-
- // m_data->m_localShapeAABBGPU->push_back(aabbWS);
- clFinish(m_queue);
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling1)
-{
- b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
-
- int collidableIndex = allocateCollidable();
- if (collidableIndex < 0)
- return collidableIndex;
-
- b3Collidable& col = getCollidableCpu(collidableIndex);
-
- col.m_shapeType = SHAPE_CONCAVE_TRIMESH;
- col.m_shapeIndex = registerConcaveMeshShape(vertices, indices, col, scaling);
- col.m_bvhIndex = m_data->m_bvhInfoCPU.size();
-
- b3SapAabb aabb;
- b3Vector3 myAabbMin = b3MakeVector3(1e30f, 1e30f, 1e30f);
- b3Vector3 myAabbMax = b3MakeVector3(-1e30f, -1e30f, -1e30f);
-
- for (int i = 0; i < vertices->size(); i++)
- {
- b3Vector3 vtx(vertices->at(i) * scaling);
- myAabbMin.setMin(vtx);
- myAabbMax.setMax(vtx);
- }
- aabb.m_min[0] = myAabbMin[0];
- aabb.m_min[1] = myAabbMin[1];
- aabb.m_min[2] = myAabbMin[2];
- aabb.m_minIndices[3] = 0;
-
- aabb.m_max[0] = myAabbMax[0];
- aabb.m_max[1] = myAabbMax[1];
- aabb.m_max[2] = myAabbMax[2];
- aabb.m_signedMaxIndices[3] = 0;
-
- m_data->m_localShapeAABBCPU->push_back(aabb);
- // m_data->m_localShapeAABBGPU->push_back(aabb);
-
- b3OptimizedBvh* bvh = new b3OptimizedBvh();
- //void b3OptimizedBvh::build(b3StridingMeshInterface* triangles, bool useQuantizedAabbCompression, const b3Vector3& bvhAabbMin, const b3Vector3& bvhAabbMax)
-
- bool useQuantizedAabbCompression = true;
- b3TriangleIndexVertexArray* meshInterface = new b3TriangleIndexVertexArray();
- m_data->m_meshInterfaces.push_back(meshInterface);
- b3IndexedMesh mesh;
- mesh.m_numTriangles = indices->size() / 3;
- mesh.m_numVertices = vertices->size();
- mesh.m_vertexBase = (const unsigned char*)&vertices->at(0).x;
- mesh.m_vertexStride = sizeof(b3Vector3);
- mesh.m_triangleIndexStride = 3 * sizeof(int); // or sizeof(int)
- mesh.m_triangleIndexBase = (const unsigned char*)&indices->at(0);
-
- meshInterface->addIndexedMesh(mesh);
- bvh->build(meshInterface, useQuantizedAabbCompression, (b3Vector3&)aabb.m_min, (b3Vector3&)aabb.m_max);
- m_data->m_bvhData.push_back(bvh);
- int numNodes = bvh->getQuantizedNodeArray().size();
- //b3OpenCLArray<b3QuantizedBvhNode>* treeNodesGPU = new b3OpenCLArray<b3QuantizedBvhNode>(this->m_context,this->m_queue,numNodes);
- int numSubTrees = bvh->getSubtreeInfoArray().size();
-
- b3BvhInfo bvhInfo;
-
- bvhInfo.m_aabbMin = bvh->m_bvhAabbMin;
- bvhInfo.m_aabbMax = bvh->m_bvhAabbMax;
- bvhInfo.m_quantization = bvh->m_bvhQuantization;
- bvhInfo.m_numNodes = numNodes;
- bvhInfo.m_numSubTrees = numSubTrees;
- bvhInfo.m_nodeOffset = m_data->m_treeNodesCPU.size();
- bvhInfo.m_subTreeOffset = m_data->m_subTreesCPU.size();
-
- m_data->m_bvhInfoCPU.push_back(bvhInfo);
-
- int numNewSubtrees = bvh->getSubtreeInfoArray().size();
- m_data->m_subTreesCPU.reserve(m_data->m_subTreesCPU.size() + numNewSubtrees);
- for (int i = 0; i < numNewSubtrees; i++)
- {
- m_data->m_subTreesCPU.push_back(bvh->getSubtreeInfoArray()[i]);
- }
- int numNewTreeNodes = bvh->getQuantizedNodeArray().size();
-
- for (int i = 0; i < numNewTreeNodes; i++)
- {
- m_data->m_treeNodesCPU.push_back(bvh->getQuantizedNodeArray()[i]);
- }
-
- return collidableIndex;
-}
-
-int b3GpuNarrowPhase::registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling1)
-{
- b3Vector3 scaling = b3MakeVector3(scaling1[0], scaling1[1], scaling1[2]);
-
- m_data->m_convexData->resize(m_data->m_numAcceleratedShapes + 1);
- m_data->m_convexPolyhedra.resize(m_data->m_numAcceleratedShapes + 1);
-
- b3ConvexPolyhedronData& convex = m_data->m_convexPolyhedra.at(m_data->m_convexPolyhedra.size() - 1);
- convex.mC = b3MakeVector3(0, 0, 0);
- convex.mE = b3MakeVector3(0, 0, 0);
- convex.m_extents = b3MakeVector3(0, 0, 0);
- convex.m_localCenter = b3MakeVector3(0, 0, 0);
- convex.m_radius = 0.f;
-
- convex.m_numUniqueEdges = 0;
- int edgeOffset = m_data->m_uniqueEdges.size();
- convex.m_uniqueEdgesOffset = edgeOffset;
-
- int faceOffset = m_data->m_convexFaces.size();
- convex.m_faceOffset = faceOffset;
-
- convex.m_numFaces = indices->size() / 3;
- m_data->m_convexFaces.resize(faceOffset + convex.m_numFaces);
- m_data->m_convexIndices.reserve(convex.m_numFaces * 3);
- for (int i = 0; i < convex.m_numFaces; i++)
- {
- if (i % 256 == 0)
- {
- //printf("i=%d out of %d", i,convex.m_numFaces);
- }
- b3Vector3 vert0(vertices->at(indices->at(i * 3)) * scaling);
- b3Vector3 vert1(vertices->at(indices->at(i * 3 + 1)) * scaling);
- b3Vector3 vert2(vertices->at(indices->at(i * 3 + 2)) * scaling);
-
- b3Vector3 normal = ((vert1 - vert0).cross(vert2 - vert0)).normalize();
- b3Scalar c = -(normal.dot(vert0));
-
- m_data->m_convexFaces[convex.m_faceOffset + i].m_plane = b3MakeVector4(normal.x, normal.y, normal.z, c);
- int indexOffset = m_data->m_convexIndices.size();
- int numIndices = 3;
- m_data->m_convexFaces[convex.m_faceOffset + i].m_numIndices = numIndices;
- m_data->m_convexFaces[convex.m_faceOffset + i].m_indexOffset = indexOffset;
- m_data->m_convexIndices.resize(indexOffset + numIndices);
- for (int p = 0; p < numIndices; p++)
- {
- int vi = indices->at(i * 3 + p);
- m_data->m_convexIndices[indexOffset + p] = vi; //convexPtr->m_faces[i].m_indices[p];
- }
- }
-
- convex.m_numVertices = vertices->size();
- int vertexOffset = m_data->m_convexVertices.size();
- convex.m_vertexOffset = vertexOffset;
- m_data->m_convexVertices.resize(vertexOffset + convex.m_numVertices);
- for (int i = 0; i < vertices->size(); i++)
- {
- m_data->m_convexVertices[vertexOffset + i] = vertices->at(i) * scaling;
- }
-
- (*m_data->m_convexData)[m_data->m_numAcceleratedShapes] = 0;
-
- return m_data->m_numAcceleratedShapes++;
-}
-
-cl_mem b3GpuNarrowPhase::getBodiesGpu()
-{
- return (cl_mem)m_data->m_bodyBufferGPU->getBufferCL();
-}
-
-const struct b3RigidBodyData* b3GpuNarrowPhase::getBodiesCpu() const
-{
- return &m_data->m_bodyBufferCPU->at(0);
-};
-
-int b3GpuNarrowPhase::getNumBodiesGpu() const
-{
- return m_data->m_bodyBufferGPU->size();
-}
-
-cl_mem b3GpuNarrowPhase::getBodyInertiasGpu()
-{
- return (cl_mem)m_data->m_inertiaBufferGPU->getBufferCL();
-}
-
-int b3GpuNarrowPhase::getNumBodyInertiasGpu() const
-{
- return m_data->m_inertiaBufferGPU->size();
-}
-
-b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex)
-{
- return m_data->m_collidablesCPU[collidableIndex];
-}
-
-const b3Collidable& b3GpuNarrowPhase::getCollidableCpu(int collidableIndex) const
-{
- return m_data->m_collidablesCPU[collidableIndex];
-}
-
-cl_mem b3GpuNarrowPhase::getCollidablesGpu()
-{
- return m_data->m_collidablesGPU->getBufferCL();
-}
-
-const struct b3Collidable* b3GpuNarrowPhase::getCollidablesCpu() const
-{
- if (m_data->m_collidablesCPU.size())
- return &m_data->m_collidablesCPU[0];
- return 0;
-}
-
-const struct b3SapAabb* b3GpuNarrowPhase::getLocalSpaceAabbsCpu() const
-{
- if (m_data->m_localShapeAABBCPU->size())
- {
- return &m_data->m_localShapeAABBCPU->at(0);
- }
- return 0;
-}
-
-cl_mem b3GpuNarrowPhase::getAabbLocalSpaceBufferGpu()
-{
- return m_data->m_localShapeAABBGPU->getBufferCL();
-}
-int b3GpuNarrowPhase::getNumCollidablesGpu() const
-{
- return m_data->m_collidablesGPU->size();
-}
-
-int b3GpuNarrowPhase::getNumContactsGpu() const
-{
- return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
-}
-cl_mem b3GpuNarrowPhase::getContactsGpu()
-{
- return m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->getBufferCL();
-}
-
-const b3Contact4* b3GpuNarrowPhase::getContactsCPU() const
-{
- m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->copyToHost(*m_data->m_pBufContactOutCPU);
- return &m_data->m_pBufContactOutCPU->at(0);
-}
-
-void b3GpuNarrowPhase::computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects)
-{
- cl_mem aabbsLocalSpace = m_data->m_localShapeAABBGPU->getBufferCL();
-
- int nContactOut = 0;
-
- //swap buffer
- m_data->m_currentContactBuffer = 1 - m_data->m_currentContactBuffer;
-
- //int curSize = m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer]->size();
-
- int maxTriConvexPairCapacity = m_data->m_config.m_maxTriConvexPairCapacity;
- int numTriConvexPairsOut = 0;
-
- b3OpenCLArray<b3Int4> broadphasePairsGPU(m_context, m_queue);
- broadphasePairsGPU.setFromOpenCLBuffer(broadphasePairs, numBroadphasePairs);
-
- b3OpenCLArray<b3Aabb> clAabbArrayWorldSpace(this->m_context, this->m_queue);
- clAabbArrayWorldSpace.setFromOpenCLBuffer(aabbsWorldSpace, numObjects);
-
- b3OpenCLArray<b3Aabb> clAabbArrayLocalSpace(this->m_context, this->m_queue);
- clAabbArrayLocalSpace.setFromOpenCLBuffer(aabbsLocalSpace, numObjects);
-
- m_data->m_gpuSatCollision->computeConvexConvexContactsGPUSAT(
- &broadphasePairsGPU, numBroadphasePairs,
- m_data->m_bodyBufferGPU,
- m_data->m_pBufContactBuffersGPU[m_data->m_currentContactBuffer],
- nContactOut,
- m_data->m_pBufContactBuffersGPU[1 - m_data->m_currentContactBuffer],
- m_data->m_config.m_maxContactCapacity,
- m_data->m_config.m_compoundPairCapacity,
- *m_data->m_convexPolyhedraGPU,
- *m_data->m_convexVerticesGPU,
- *m_data->m_uniqueEdgesGPU,
- *m_data->m_convexFacesGPU,
- *m_data->m_convexIndicesGPU,
- *m_data->m_collidablesGPU,
- *m_data->m_gpuChildShapes,
- clAabbArrayWorldSpace,
- clAabbArrayLocalSpace,
- *m_data->m_worldVertsB1GPU,
- *m_data->m_clippingFacesOutGPU,
- *m_data->m_worldNormalsAGPU,
- *m_data->m_worldVertsA1GPU,
- *m_data->m_worldVertsB2GPU,
- m_data->m_bvhData,
- m_data->m_treeNodesGPU,
- m_data->m_subTreesGPU,
- m_data->m_bvhInfoGPU,
- numObjects,
- maxTriConvexPairCapacity,
- *m_data->m_triangleConvexPairs,
- numTriConvexPairsOut);
-
- /*b3AlignedObjectArray<b3Int4> broadphasePairsCPU;
- broadphasePairsGPU.copyToHost(broadphasePairsCPU);
- printf("checking pairs\n");
- */
-}
-
-const b3SapAabb& b3GpuNarrowPhase::getLocalSpaceAabb(int collidableIndex) const
-{
- return m_data->m_localShapeAABBCPU->at(collidableIndex);
-}
-
-int b3GpuNarrowPhase::registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMinPtr, const float* aabbMaxPtr, bool writeToGpu)
-{
- b3Vector3 aabbMin = b3MakeVector3(aabbMinPtr[0], aabbMinPtr[1], aabbMinPtr[2]);
- b3Vector3 aabbMax = b3MakeVector3(aabbMaxPtr[0], aabbMaxPtr[1], aabbMaxPtr[2]);
-
- if (m_data->m_numAcceleratedRigidBodies >= (m_data->m_config.m_maxConvexBodies))
- {
- b3Error("registerRigidBody: exceeding the number of rigid bodies, %d > %d \n", m_data->m_numAcceleratedRigidBodies, m_data->m_config.m_maxConvexBodies);
- return -1;
- }
-
- m_data->m_bodyBufferCPU->resize(m_data->m_numAcceleratedRigidBodies + 1);
-
- b3RigidBodyData& body = m_data->m_bodyBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
-
- float friction = 1.f;
- float restitution = 0.f;
-
- body.m_frictionCoeff = friction;
- body.m_restituitionCoeff = restitution;
- body.m_angVel = b3MakeVector3(0, 0, 0);
- body.m_linVel = b3MakeVector3(0, 0, 0); //.setZero();
- body.m_pos = b3MakeVector3(position[0], position[1], position[2]);
- body.m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
- body.m_collidableIdx = collidableIndex;
- if (collidableIndex >= 0)
- {
- // body.m_shapeType = m_data->m_collidablesCPU.at(collidableIndex).m_shapeType;
- }
- else
- {
- // body.m_shapeType = CollisionShape::SHAPE_PLANE;
- m_planeBodyIndex = m_data->m_numAcceleratedRigidBodies;
- }
- //body.m_shapeType = shapeType;
-
- body.m_invMass = mass ? 1.f / mass : 0.f;
-
- if (writeToGpu)
- {
- m_data->m_bodyBufferGPU->copyFromHostPointer(&body, 1, m_data->m_numAcceleratedRigidBodies);
- }
-
- b3InertiaData& shapeInfo = m_data->m_inertiaBufferCPU->at(m_data->m_numAcceleratedRigidBodies);
-
- if (mass == 0.f)
- {
- if (m_data->m_numAcceleratedRigidBodies == 0)
- m_static0Index = 0;
-
- shapeInfo.m_initInvInertia.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- shapeInfo.m_invInertiaWorld.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- }
- else
- {
- b3Assert(body.m_collidableIdx >= 0);
-
- //approximate using the aabb of the shape
-
- //Aabb aabb = (*m_data->m_shapePointers)[shapeIndex]->m_aabb;
- b3Vector3 halfExtents = (aabbMax - aabbMin); //*0.5f;//fake larger inertia makes demos more stable ;-)
-
- b3Vector3 localInertia;
-
- float lx = 2.f * halfExtents[0];
- float ly = 2.f * halfExtents[1];
- float lz = 2.f * halfExtents[2];
-
- localInertia.setValue((mass / 12.0f) * (ly * ly + lz * lz),
- (mass / 12.0f) * (lx * lx + lz * lz),
- (mass / 12.0f) * (lx * lx + ly * ly));
-
- b3Vector3 invLocalInertia;
- invLocalInertia[0] = 1.f / localInertia[0];
- invLocalInertia[1] = 1.f / localInertia[1];
- invLocalInertia[2] = 1.f / localInertia[2];
- invLocalInertia[3] = 0.f;
-
- shapeInfo.m_initInvInertia.setValue(
- invLocalInertia[0], 0, 0,
- 0, invLocalInertia[1], 0,
- 0, 0, invLocalInertia[2]);
-
- b3Matrix3x3 m(body.m_quat);
-
- shapeInfo.m_invInertiaWorld = m.scaled(invLocalInertia) * m.transpose();
- }
-
- if (writeToGpu)
- m_data->m_inertiaBufferGPU->copyFromHostPointer(&shapeInfo, 1, m_data->m_numAcceleratedRigidBodies);
-
- return m_data->m_numAcceleratedRigidBodies++;
-}
-
-int b3GpuNarrowPhase::getNumRigidBodies() const
-{
- return m_data->m_numAcceleratedRigidBodies;
-}
-
-void b3GpuNarrowPhase::writeAllBodiesToGpu()
-{
- if (m_data->m_localShapeAABBCPU->size())
- {
- m_data->m_localShapeAABBGPU->copyFromHost(*m_data->m_localShapeAABBCPU);
- }
-
- m_data->m_gpuChildShapes->copyFromHost(m_data->m_cpuChildShapes);
- m_data->m_convexFacesGPU->copyFromHost(m_data->m_convexFaces);
- m_data->m_convexPolyhedraGPU->copyFromHost(m_data->m_convexPolyhedra);
- m_data->m_uniqueEdgesGPU->copyFromHost(m_data->m_uniqueEdges);
- m_data->m_convexVerticesGPU->copyFromHost(m_data->m_convexVertices);
- m_data->m_convexIndicesGPU->copyFromHost(m_data->m_convexIndices);
- m_data->m_bvhInfoGPU->copyFromHost(m_data->m_bvhInfoCPU);
- m_data->m_treeNodesGPU->copyFromHost(m_data->m_treeNodesCPU);
- m_data->m_subTreesGPU->copyFromHost(m_data->m_subTreesCPU);
-
- m_data->m_bodyBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
- m_data->m_inertiaBufferGPU->resize(m_data->m_numAcceleratedRigidBodies);
-
- if (m_data->m_numAcceleratedRigidBodies)
- {
- m_data->m_bodyBufferGPU->copyFromHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
- m_data->m_inertiaBufferGPU->copyFromHostPointer(&m_data->m_inertiaBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
- }
- if (m_data->m_collidablesCPU.size())
- {
- m_data->m_collidablesGPU->copyFromHost(m_data->m_collidablesCPU);
- }
-}
-
-void b3GpuNarrowPhase::reset()
-{
- m_data->m_numAcceleratedShapes = 0;
- m_data->m_numAcceleratedRigidBodies = 0;
- this->m_static0Index = -1;
- m_data->m_uniqueEdges.resize(0);
- m_data->m_convexVertices.resize(0);
- m_data->m_convexPolyhedra.resize(0);
- m_data->m_convexIndices.resize(0);
- m_data->m_cpuChildShapes.resize(0);
- m_data->m_convexFaces.resize(0);
- m_data->m_collidablesCPU.resize(0);
- m_data->m_localShapeAABBCPU->resize(0);
- m_data->m_bvhData.resize(0);
- m_data->m_treeNodesCPU.resize(0);
- m_data->m_subTreesCPU.resize(0);
- m_data->m_bvhInfoCPU.resize(0);
-}
-
-void b3GpuNarrowPhase::readbackAllBodiesToCpu()
-{
- m_data->m_bodyBufferGPU->copyToHostPointer(&m_data->m_bodyBufferCPU->at(0), m_data->m_numAcceleratedRigidBodies);
-}
-
-void b3GpuNarrowPhase::setObjectTransformCpu(float* position, float* orientation, int bodyIndex)
-{
- if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
- {
- m_data->m_bodyBufferCPU->at(bodyIndex).m_pos = b3MakeVector3(position[0], position[1], position[2]);
- m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.setValue(orientation[0], orientation[1], orientation[2], orientation[3]);
- }
- else
- {
- b3Warning("setObjectVelocityCpu out of range.\n");
- }
-}
-void b3GpuNarrowPhase::setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex)
-{
- if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
- {
- m_data->m_bodyBufferCPU->at(bodyIndex).m_linVel = b3MakeVector3(linVel[0], linVel[1], linVel[2]);
- m_data->m_bodyBufferCPU->at(bodyIndex).m_angVel = b3MakeVector3(angVel[0], angVel[1], angVel[2]);
- }
- else
- {
- b3Warning("setObjectVelocityCpu out of range.\n");
- }
-}
-
-bool b3GpuNarrowPhase::getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const
-{
- if (bodyIndex >= 0 && bodyIndex < m_data->m_bodyBufferCPU->size())
- {
- position[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.x;
- position[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.y;
- position[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_pos.z;
- position[3] = 1.f; //or 1
-
- orientation[0] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.x;
- orientation[1] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.y;
- orientation[2] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.z;
- orientation[3] = m_data->m_bodyBufferCPU->at(bodyIndex).m_quat.w;
- return true;
- }
-
- b3Warning("getObjectTransformFromCpu out of range.\n");
- return false;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
deleted file mode 100644
index 21a68de343..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhase.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef B3_GPU_NARROWPHASE_H
-#define B3_GPU_NARROWPHASE_H
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Vector3.h"
-
-class b3GpuNarrowPhase
-{
-protected:
- struct b3GpuNarrowPhaseInternalData* m_data;
- int m_acceleratedCompanionShapeIndex;
- int m_planeBodyIndex;
- int m_static0Index;
-
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- int registerConvexHullShapeInternal(class b3ConvexUtility* convexPtr, b3Collidable& col);
- int registerConcaveMeshShape(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, b3Collidable& col, const float* scaling);
-
-public:
- b3GpuNarrowPhase(cl_context vtx, cl_device_id dev, cl_command_queue q, const struct b3Config& config);
-
- virtual ~b3GpuNarrowPhase(void);
-
- int registerSphereShape(float radius);
- int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
-
- int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
- int registerFace(const b3Vector3& faceNormal, float faceConstant);
-
- int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
-
- //do they need to be merged?
-
- int registerConvexHullShape(b3ConvexUtility* utilPtr);
- int registerConvexHullShape(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
-
- int registerRigidBody(int collidableIndex, float mass, const float* position, const float* orientation, const float* aabbMin, const float* aabbMax, bool writeToGpu);
- void setObjectTransform(const float* position, const float* orientation, int bodyIndex);
-
- void writeAllBodiesToGpu();
- void reset();
- void readbackAllBodiesToCpu();
- bool getObjectTransformFromCpu(float* position, float* orientation, int bodyIndex) const;
-
- void setObjectTransformCpu(float* position, float* orientation, int bodyIndex);
- void setObjectVelocityCpu(float* linVel, float* angVel, int bodyIndex);
-
- virtual void computeContacts(cl_mem broadphasePairs, int numBroadphasePairs, cl_mem aabbsWorldSpace, int numObjects);
-
- cl_mem getBodiesGpu();
- const struct b3RigidBodyData* getBodiesCpu() const;
- //struct b3RigidBodyData* getBodiesCpu();
-
- int getNumBodiesGpu() const;
-
- cl_mem getBodyInertiasGpu();
- int getNumBodyInertiasGpu() const;
-
- cl_mem getCollidablesGpu();
- const struct b3Collidable* getCollidablesCpu() const;
- int getNumCollidablesGpu() const;
-
- const struct b3SapAabb* getLocalSpaceAabbsCpu() const;
-
- const struct b3Contact4* getContactsCPU() const;
-
- cl_mem getContactsGpu();
- int getNumContactsGpu() const;
-
- cl_mem getAabbLocalSpaceBufferGpu();
-
- int getNumRigidBodies() const;
-
- int allocateCollidable();
-
- int getStatic0Index() const
- {
- return m_static0Index;
- }
- b3Collidable& getCollidableCpu(int collidableIndex);
- const b3Collidable& getCollidableCpu(int collidableIndex) const;
-
- const b3GpuNarrowPhaseInternalData* getInternalData() const
- {
- return m_data;
- }
-
- b3GpuNarrowPhaseInternalData* getInternalData()
- {
- return m_data;
- }
-
- const struct b3SapAabb& getLocalSpaceAabb(int collidableIndex) const;
-};
-
-#endif //B3_GPU_NARROWPHASE_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
deleted file mode 100644
index 716a5ea0fc..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h
+++ /dev/null
@@ -1,89 +0,0 @@
-
-#ifndef B3_GPU_NARROWPHASE_INTERNAL_DATA_H
-#define B3_GPU_NARROWPHASE_INTERNAL_DATA_H
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3ConvexPolyhedronData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3Vector3.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
-
-#include "Bullet3OpenCL/NarrowphaseCollision/b3QuantizedBvh.h"
-#include "Bullet3OpenCL/NarrowphaseCollision/b3BvhInfo.h"
-#include "Bullet3Common/shared/b3Int4.h"
-#include "Bullet3Common/shared/b3Int2.h"
-
-class b3ConvexUtility;
-
-struct b3GpuNarrowPhaseInternalData
-{
- b3AlignedObjectArray<b3ConvexUtility*>* m_convexData;
-
- b3AlignedObjectArray<b3ConvexPolyhedronData> m_convexPolyhedra;
- b3AlignedObjectArray<b3Vector3> m_uniqueEdges;
- b3AlignedObjectArray<b3Vector3> m_convexVertices;
- b3AlignedObjectArray<int> m_convexIndices;
-
- b3OpenCLArray<b3ConvexPolyhedronData>* m_convexPolyhedraGPU;
- b3OpenCLArray<b3Vector3>* m_uniqueEdgesGPU;
- b3OpenCLArray<b3Vector3>* m_convexVerticesGPU;
- b3OpenCLArray<int>* m_convexIndicesGPU;
-
- b3OpenCLArray<b3Vector3>* m_worldVertsB1GPU;
- b3OpenCLArray<b3Int4>* m_clippingFacesOutGPU;
- b3OpenCLArray<b3Vector3>* m_worldNormalsAGPU;
- b3OpenCLArray<b3Vector3>* m_worldVertsA1GPU;
- b3OpenCLArray<b3Vector3>* m_worldVertsB2GPU;
-
- b3AlignedObjectArray<b3GpuChildShape> m_cpuChildShapes;
- b3OpenCLArray<b3GpuChildShape>* m_gpuChildShapes;
-
- b3AlignedObjectArray<b3GpuFace> m_convexFaces;
- b3OpenCLArray<b3GpuFace>* m_convexFacesGPU;
-
- struct GpuSatCollision* m_gpuSatCollision;
-
- b3OpenCLArray<b3Int4>* m_triangleConvexPairs;
-
- b3OpenCLArray<b3Contact4>* m_pBufContactBuffersGPU[2];
- int m_currentContactBuffer;
- b3AlignedObjectArray<b3Contact4>* m_pBufContactOutCPU;
-
- b3AlignedObjectArray<b3RigidBodyData>* m_bodyBufferCPU;
- b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
-
- b3AlignedObjectArray<b3InertiaData>* m_inertiaBufferCPU;
- b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
-
- int m_numAcceleratedShapes;
- int m_numAcceleratedRigidBodies;
-
- b3AlignedObjectArray<b3Collidable> m_collidablesCPU;
- b3OpenCLArray<b3Collidable>* m_collidablesGPU;
-
- b3OpenCLArray<b3SapAabb>* m_localShapeAABBGPU;
- b3AlignedObjectArray<b3SapAabb>* m_localShapeAABBCPU;
-
- b3AlignedObjectArray<class b3OptimizedBvh*> m_bvhData;
- b3AlignedObjectArray<class b3TriangleIndexVertexArray*> m_meshInterfaces;
-
- b3AlignedObjectArray<b3QuantizedBvhNode> m_treeNodesCPU;
- b3AlignedObjectArray<b3BvhSubtreeInfo> m_subTreesCPU;
-
- b3AlignedObjectArray<b3BvhInfo> m_bvhInfoCPU;
- b3OpenCLArray<b3BvhInfo>* m_bvhInfoGPU;
-
- b3OpenCLArray<b3QuantizedBvhNode>* m_treeNodesGPU;
- b3OpenCLArray<b3BvhSubtreeInfo>* m_subTreesGPU;
-
- b3Config m_config;
-};
-
-#endif //B3_GPU_NARROWPHASE_INTERNAL_DATA_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
deleted file mode 100644
index bd9d6bb04b..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.cpp
+++ /dev/null
@@ -1,1068 +0,0 @@
-
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-bool useGpuInitSolverBodies = true;
-bool useGpuInfo1 = true;
-bool useGpuInfo2 = true;
-bool useGpuSolveJointConstraintRows = true;
-bool useGpuWriteBackVelocities = true;
-bool gpuBreakConstraints = true;
-
-#include "b3GpuPgsConstraintSolver.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
-#include <new>
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include <string.h> //for memset
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-
-#include "Bullet3OpenCL/RigidBody/kernels/jointSolver.h" //solveConstraintRowsCL
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-
-#define B3_JOINT_SOLVER_PATH "src/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl"
-
-struct b3GpuPgsJacobiSolverInternalData
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- b3PrefixScanCL* m_prefixScan;
-
- cl_kernel m_solveJointConstraintRowsKernels;
- cl_kernel m_initSolverBodiesKernel;
- cl_kernel m_getInfo1Kernel;
- cl_kernel m_initBatchConstraintsKernel;
- cl_kernel m_getInfo2Kernel;
- cl_kernel m_writeBackVelocitiesKernel;
- cl_kernel m_breakViolatedConstraintsKernel;
-
- b3OpenCLArray<unsigned int>* m_gpuConstraintRowOffsets;
-
- b3OpenCLArray<b3GpuSolverBody>* m_gpuSolverBodies;
- b3OpenCLArray<b3BatchConstraint>* m_gpuBatchConstraints;
- b3OpenCLArray<b3GpuSolverConstraint>* m_gpuConstraintRows;
- b3OpenCLArray<unsigned int>* m_gpuConstraintInfo1;
-
- // b3AlignedObjectArray<b3GpuSolverBody> m_cpuSolverBodies;
- b3AlignedObjectArray<b3BatchConstraint> m_cpuBatchConstraints;
- b3AlignedObjectArray<b3GpuSolverConstraint> m_cpuConstraintRows;
- b3AlignedObjectArray<unsigned int> m_cpuConstraintInfo1;
- b3AlignedObjectArray<unsigned int> m_cpuConstraintRowOffsets;
-
- b3AlignedObjectArray<b3RigidBodyData> m_cpuBodies;
- b3AlignedObjectArray<b3InertiaData> m_cpuInertias;
-
- b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
-
- b3AlignedObjectArray<int> m_batchSizes;
-};
-
-/*
-static b3Transform getWorldTransform(b3RigidBodyData* rb)
-{
- b3Transform newTrans;
- newTrans.setOrigin(rb->m_pos);
- newTrans.setRotation(rb->m_quat);
- return newTrans;
-}
-
-static const b3Matrix3x3& getInvInertiaTensorWorld(b3InertiaData* inertia)
-{
- return inertia->m_invInertiaWorld;
-}
-
-*/
-
-static const b3Vector3& getLinearVelocity(b3RigidBodyData* rb)
-{
- return rb->m_linVel;
-}
-
-static const b3Vector3& getAngularVelocity(b3RigidBodyData* rb)
-{
- return rb->m_angVel;
-}
-
-b3Vector3 getVelocityInLocalPoint(b3RigidBodyData* rb, const b3Vector3& rel_pos)
-{
- //we also calculate lin/ang velocity for kinematic objects
- return getLinearVelocity(rb) + getAngularVelocity(rb).cross(rel_pos);
-}
-
-b3GpuPgsConstraintSolver::b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs)
-{
- m_usePgs = usePgs;
- m_gpuData = new b3GpuPgsJacobiSolverInternalData();
- m_gpuData->m_context = ctx;
- m_gpuData->m_device = device;
- m_gpuData->m_queue = queue;
-
- m_gpuData->m_prefixScan = new b3PrefixScanCL(ctx, device, queue);
-
- m_gpuData->m_gpuConstraintRowOffsets = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
-
- m_gpuData->m_gpuSolverBodies = new b3OpenCLArray<b3GpuSolverBody>(m_gpuData->m_context, m_gpuData->m_queue);
- m_gpuData->m_gpuBatchConstraints = new b3OpenCLArray<b3BatchConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
- m_gpuData->m_gpuConstraintRows = new b3OpenCLArray<b3GpuSolverConstraint>(m_gpuData->m_context, m_gpuData->m_queue);
- m_gpuData->m_gpuConstraintInfo1 = new b3OpenCLArray<unsigned int>(m_gpuData->m_context, m_gpuData->m_queue);
- cl_int errNum = 0;
-
- {
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, &errNum, "", B3_JOINT_SOLVER_PATH);
- //cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_gpuData->m_context,m_gpuData->m_device,0,&errNum,"",B3_JOINT_SOLVER_PATH,true);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_solveJointConstraintRowsKernels = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "solveJointConstraintRows", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_initSolverBodiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initSolverBodies", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_getInfo1Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo1Kernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_initBatchConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "initBatchConstraintsKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_getInfo2Kernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "getInfo2Kernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_writeBackVelocitiesKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "writeBackVelocitiesKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- m_gpuData->m_breakViolatedConstraintsKernel = b3OpenCLUtils::compileCLKernelFromString(m_gpuData->m_context, m_gpuData->m_device, solveConstraintRowsCL, "breakViolatedConstraintsKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
-
- clReleaseProgram(prog);
- }
-}
-
-b3GpuPgsConstraintSolver::~b3GpuPgsConstraintSolver()
-{
- clReleaseKernel(m_gpuData->m_solveJointConstraintRowsKernels);
- clReleaseKernel(m_gpuData->m_initSolverBodiesKernel);
- clReleaseKernel(m_gpuData->m_getInfo1Kernel);
- clReleaseKernel(m_gpuData->m_initBatchConstraintsKernel);
- clReleaseKernel(m_gpuData->m_getInfo2Kernel);
- clReleaseKernel(m_gpuData->m_writeBackVelocitiesKernel);
- clReleaseKernel(m_gpuData->m_breakViolatedConstraintsKernel);
-
- delete m_gpuData->m_prefixScan;
- delete m_gpuData->m_gpuConstraintRowOffsets;
- delete m_gpuData->m_gpuSolverBodies;
- delete m_gpuData->m_gpuBatchConstraints;
- delete m_gpuData->m_gpuConstraintRows;
- delete m_gpuData->m_gpuConstraintInfo1;
-
- delete m_gpuData;
-}
-
-struct b3BatchConstraint
-{
- int m_bodyAPtrAndSignBit;
- int m_bodyBPtrAndSignBit;
- int m_originalConstraintIndex;
- int m_batchId;
-};
-
-static b3AlignedObjectArray<b3BatchConstraint> batchConstraints;
-
-void b3GpuPgsConstraintSolver::recomputeBatches()
-{
- m_gpuData->m_batchSizes.clear();
-}
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("GPU solveGroupCacheFriendlySetup");
- batchConstraints.resize(numConstraints);
- m_gpuData->m_gpuBatchConstraints->resize(numConstraints);
- m_staticIdx = -1;
- m_maxOverrideNumSolverIterations = 0;
-
- /* m_gpuData->m_gpuBodies->resize(numBodies);
- m_gpuData->m_gpuBodies->copyFromHostPointer(bodies,numBodies);
-
- b3OpenCLArray<b3InertiaData> gpuInertias(m_gpuData->m_context,m_gpuData->m_queue);
- gpuInertias.resize(numBodies);
- gpuInertias.copyFromHostPointer(inertias,numBodies);
- */
-
- m_gpuData->m_gpuSolverBodies->resize(numBodies);
-
- m_tmpSolverBodyPool.resize(numBodies);
- {
- if (useGpuInitSolverBodies)
- {
- B3_PROFILE("m_initSolverBodiesKernel");
-
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initSolverBodiesKernel, "m_initSolverBodiesKernel");
- launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
- launcher.setBuffer(gpuBodies->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_gpuData->m_queue);
-
- // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- }
- else
- {
- gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
- for (int i = 0; i < numBodies; i++)
- {
- b3RigidBodyData& body = m_gpuData->m_cpuBodies[i];
- b3GpuSolverBody& solverBody = m_tmpSolverBodyPool[i];
- initSolverBody(i, &solverBody, &body);
- solverBody.m_originalBodyIndex = i;
- }
- m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
- }
- }
-
- // int totalBodies = 0;
- int totalNumRows = 0;
- //b3RigidBody* rb0=0,*rb1=0;
- //if (1)
- {
- {
- // int i;
-
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
-
- // b3OpenCLArray<b3GpuGenericConstraint> gpuConstraints(m_gpuData->m_context,m_gpuData->m_queue);
-
- if (useGpuInfo1)
- {
- B3_PROFILE("info1 and init batchConstraint");
-
- m_gpuData->m_gpuConstraintInfo1->resize(numConstraints);
-
- if (1)
- {
- B3_PROFILE("getInfo1Kernel");
-
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo1Kernel, "m_getInfo1Kernel");
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(gpuConstraints->getBufferCL());
- launcher.setConst(numConstraints);
- launcher.launch1D(numConstraints);
- clFinish(m_gpuData->m_queue);
- }
-
- if (m_gpuData->m_batchSizes.size() == 0)
- {
- B3_PROFILE("initBatchConstraintsKernel");
-
- m_gpuData->m_gpuConstraintRowOffsets->resize(numConstraints);
- unsigned int total = 0;
- m_gpuData->m_prefixScan->execute(*m_gpuData->m_gpuConstraintInfo1, *m_gpuData->m_gpuConstraintRowOffsets, numConstraints, &total);
- unsigned int lastElem = m_gpuData->m_gpuConstraintInfo1->at(numConstraints - 1);
- totalNumRows = total + lastElem;
-
- {
- B3_PROFILE("init batch constraints");
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_initBatchConstraintsKernel, "m_initBatchConstraintsKernel");
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
- launcher.setBuffer(gpuConstraints->getBufferCL());
- launcher.setBuffer(gpuBodies->getBufferCL());
- launcher.setConst(numConstraints);
- launcher.launch1D(numConstraints);
- clFinish(m_gpuData->m_queue);
- }
- //assume the batching happens on CPU, so copy the data
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
- }
- }
- else
- {
- totalNumRows = 0;
- gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
- //calculate the total number of contraint rows
- for (int i = 0; i < numConstraints; i++)
- {
- unsigned int& info1 = m_tmpConstraintSizesPool[i];
- // unsigned int info1;
- if (m_gpuData->m_cpuConstraints[i].isEnabled())
- {
- m_gpuData->m_cpuConstraints[i].getInfo1(&info1, &m_gpuData->m_cpuBodies[0]);
- }
- else
- {
- info1 = 0;
- }
-
- totalNumRows += info1;
- }
-
- m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
- m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
- m_gpuData->m_gpuConstraintRows->resize(totalNumRows);
-
- // b3GpuConstraintArray verify;
-
- if (useGpuInfo2)
- {
- {
- B3_PROFILE("getInfo2Kernel");
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_getInfo2Kernel, "m_getInfo2Kernel");
- launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(gpuConstraints->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
- launcher.setBuffer(gpuBodies->getBufferCL());
- launcher.setBuffer(gpuInertias->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
- launcher.setConst(infoGlobal.m_timeStep);
- launcher.setConst(infoGlobal.m_erp);
- launcher.setConst(infoGlobal.m_globalCfm);
- launcher.setConst(infoGlobal.m_damping);
- launcher.setConst(infoGlobal.m_numIterations);
- launcher.setConst(numConstraints);
- launcher.launch1D(numConstraints);
- clFinish(m_gpuData->m_queue);
-
- if (m_gpuData->m_batchSizes.size() == 0)
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
- //m_gpuData->m_gpuConstraintRows->copyToHost(verify);
- //m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
- }
- }
- else
- {
- gpuInertias->copyToHost(m_gpuData->m_cpuInertias);
-
- ///setup the b3SolverConstraints
-
- for (int i = 0; i < numConstraints; i++)
- {
- const int& info1 = m_tmpConstraintSizesPool[i];
-
- if (info1)
- {
- int constraintIndex = batchConstraints[i].m_originalConstraintIndex;
- int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[constraintIndex];
-
- b3GpuSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[constraintRowOffset];
- b3GpuGenericConstraint& constraint = m_gpuData->m_cpuConstraints[i];
-
- b3RigidBodyData& rbA = m_gpuData->m_cpuBodies[constraint.getRigidBodyA()];
- //b3RigidBody& rbA = constraint.getRigidBodyA();
- // b3RigidBody& rbB = constraint.getRigidBodyB();
- b3RigidBodyData& rbB = m_gpuData->m_cpuBodies[constraint.getRigidBodyB()];
-
- int solverBodyIdA = constraint.getRigidBodyA(); //getOrInitSolverBody(constraint.getRigidBodyA(),bodies,inertias);
- int solverBodyIdB = constraint.getRigidBodyB(); //getOrInitSolverBody(constraint.getRigidBodyB(),bodies,inertias);
-
- b3GpuSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- b3GpuSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
-
- if (rbA.m_invMass)
- {
- batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
- }
- else
- {
- if (!solverBodyIdA)
- m_staticIdx = 0;
- batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
- }
-
- if (rbB.m_invMass)
- {
- batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
- }
- else
- {
- if (!solverBodyIdB)
- m_staticIdx = 0;
- batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
- }
-
- int overrideNumSolverIterations = 0; //constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
- m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
- int j;
- for (j = 0; j < info1; j++)
- {
- memset(&currentConstraintRow[j], 0, sizeof(b3GpuSolverConstraint));
- currentConstraintRow[j].m_angularComponentA.setValue(0, 0, 0);
- currentConstraintRow[j].m_angularComponentB.setValue(0, 0, 0);
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_cfm = 0.f;
- currentConstraintRow[j].m_contactNormal.setValue(0, 0, 0);
- currentConstraintRow[j].m_friction = 0.f;
- currentConstraintRow[j].m_frictionIndex = 0;
- currentConstraintRow[j].m_jacDiagABInv = 0.f;
- currentConstraintRow[j].m_lowerLimit = 0.f;
- currentConstraintRow[j].m_upperLimit = 0.f;
-
- currentConstraintRow[j].m_originalContactPoint = 0;
- currentConstraintRow[j].m_overrideNumSolverIterations = 0;
- currentConstraintRow[j].m_relpos1CrossNormal.setValue(0, 0, 0);
- currentConstraintRow[j].m_relpos2CrossNormal.setValue(0, 0, 0);
- currentConstraintRow[j].m_rhs = 0.f;
- currentConstraintRow[j].m_rhsPenetration = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = 0;
- currentConstraintRow[j].m_solverBodyIdB = 0;
-
- currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
- currentConstraintRow[j].m_upperLimit = B3_INFINITY;
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
- currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
- currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
- }
-
- bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- bodyAPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- bodyBPtr->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- b3GpuConstraintInfo2 info2;
- info2.fps = 1.f / infoGlobal.m_timeStep;
- info2.erp = infoGlobal.m_erp;
- info2.m_J1linearAxis = currentConstraintRow->m_contactNormal;
- info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxis = 0;
- info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(b3GpuSolverConstraint) / sizeof(b3Scalar); //check this
- ///the size of b3GpuSolverConstraint needs be a multiple of b3Scalar
- b3Assert(info2.rowskip * sizeof(b3Scalar) == sizeof(b3GpuSolverConstraint));
- info2.m_constraintError = &currentConstraintRow->m_rhs;
- currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
- info2.m_damping = infoGlobal.m_damping;
- info2.cfm = &currentConstraintRow->m_cfm;
- info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
- info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
- info2.m_numIterations = infoGlobal.m_numIterations;
- m_gpuData->m_cpuConstraints[i].getInfo2(&info2, &m_gpuData->m_cpuBodies[0]);
-
- ///finalize the constraint setup
- for (j = 0; j < info1; j++)
- {
- b3GpuSolverConstraint& solverConstraint = currentConstraintRow[j];
-
- if (solverConstraint.m_upperLimit >= m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
- {
- solverConstraint.m_upperLimit = m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
- }
-
- if (solverConstraint.m_lowerLimit <= -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold())
- {
- solverConstraint.m_lowerLimit = -m_gpuData->m_cpuConstraints[i].getBreakingImpulseThreshold();
- }
-
- // solverConstraint.m_originalContactPoint = constraint;
-
- b3Matrix3x3& invInertiaWorldA = m_gpuData->m_cpuInertias[constraint.getRigidBodyA()].m_invInertiaWorld;
- {
- //b3Vector3 angularFactorA(1,1,1);
- const b3Vector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = invInertiaWorldA * ftorqueAxis1; //*angularFactorA;
- }
-
- b3Matrix3x3& invInertiaWorldB = m_gpuData->m_cpuInertias[constraint.getRigidBodyB()].m_invInertiaWorld;
- {
- const b3Vector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = invInertiaWorldB * ftorqueAxis2; //*constraint.getRigidBodyB().getAngularFactor();
- }
-
- {
- //it is ok to use solverConstraint.m_contactNormal instead of -solverConstraint.m_contactNormal
- //because it gets multiplied iMJlB
- b3Vector3 iMJlA = solverConstraint.m_contactNormal * rbA.m_invMass;
- b3Vector3 iMJaA = invInertiaWorldA * solverConstraint.m_relpos1CrossNormal;
- b3Vector3 iMJlB = solverConstraint.m_contactNormal * rbB.m_invMass; //sign of normal?
- b3Vector3 iMJaB = invInertiaWorldB * solverConstraint.m_relpos2CrossNormal;
-
- b3Scalar sum = iMJlA.dot(solverConstraint.m_contactNormal);
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJlB.dot(solverConstraint.m_contactNormal);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- b3Scalar fsum = b3Fabs(sum);
- b3Assert(fsum > B3_EPSILON);
- solverConstraint.m_jacDiagABInv = fsum > B3_EPSILON ? b3Scalar(1.) / sum : 0.f;
- }
-
- ///fix rhs
- ///todo: add force/torque accelerators
- {
- b3Scalar rel_vel;
- b3Scalar vel1Dotn = solverConstraint.m_contactNormal.dot(rbA.m_linVel) + solverConstraint.m_relpos1CrossNormal.dot(rbA.m_angVel);
- b3Scalar vel2Dotn = -solverConstraint.m_contactNormal.dot(rbB.m_linVel) + solverConstraint.m_relpos2CrossNormal.dot(rbB.m_angVel);
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- b3Scalar restitution = 0.f;
- b3Scalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
- b3Scalar velocityError = restitution - rel_vel * info2.m_damping;
- b3Scalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- b3Scalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_appliedImpulse = 0.f;
- }
- }
- }
- }
-
- m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
- m_gpuData->m_gpuConstraintInfo1->copyFromHost(m_tmpConstraintSizesPool);
-
- if (m_gpuData->m_batchSizes.size() == 0)
- m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
- else
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
-
- m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
-
- } //end useGpuInfo2
- }
-
-#ifdef B3_SUPPORT_CONTACT_CONSTRAINTS
- {
- int i;
-
- for (i = 0; i < numManifolds; i++)
- {
- b3Contact4& manifold = manifoldPtr[i];
- convertContact(bodies, inertias, &manifold, infoGlobal);
- }
- }
-#endif //B3_SUPPORT_CONTACT_CONSTRAINTS
- }
-
- // b3ContactSolverInfo info = infoGlobal;
-
- // int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- // int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- // int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- return 0.f;
-}
-
-///a straight copy from GPU/OpenCL kernel, for debugging
-__inline void internalApplyImpulse(b3GpuSolverBody* body, const b3Vector3& linearComponent, const b3Vector3& angularComponent, float impulseMagnitude)
-{
- body->m_deltaLinearVelocity += linearComponent * impulseMagnitude * body->m_linearFactor;
- body->m_deltaAngularVelocity += angularComponent * (impulseMagnitude * body->m_angularFactor);
-}
-
-void resolveSingleConstraintRowGeneric2(b3GpuSolverBody* body1, b3GpuSolverBody* body2, b3GpuSolverConstraint* c)
-{
- float deltaImpulse = c->m_rhs - b3Scalar(c->m_appliedImpulse) * c->m_cfm;
- float deltaVel1Dotn = b3Dot(c->m_contactNormal, body1->m_deltaLinearVelocity) + b3Dot(c->m_relpos1CrossNormal, body1->m_deltaAngularVelocity);
- float deltaVel2Dotn = -b3Dot(c->m_contactNormal, body2->m_deltaLinearVelocity) + b3Dot(c->m_relpos2CrossNormal, body2->m_deltaAngularVelocity);
-
- deltaImpulse -= deltaVel1Dotn * c->m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c->m_jacDiagABInv;
-
- float sum = b3Scalar(c->m_appliedImpulse) + deltaImpulse;
- if (sum < c->m_lowerLimit)
- {
- deltaImpulse = c->m_lowerLimit - b3Scalar(c->m_appliedImpulse);
- c->m_appliedImpulse = c->m_lowerLimit;
- }
- else if (sum > c->m_upperLimit)
- {
- deltaImpulse = c->m_upperLimit - b3Scalar(c->m_appliedImpulse);
- c->m_appliedImpulse = c->m_upperLimit;
- }
- else
- {
- c->m_appliedImpulse = sum;
- }
-
- internalApplyImpulse(body1, c->m_contactNormal * body1->m_invMass, c->m_angularComponentA, deltaImpulse);
- internalApplyImpulse(body2, -c->m_contactNormal * body2->m_invMass, c->m_angularComponentB, deltaImpulse);
-}
-
-void b3GpuPgsConstraintSolver::initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb)
-{
- solverBody->m_deltaLinearVelocity.setValue(0.f, 0.f, 0.f);
- solverBody->m_deltaAngularVelocity.setValue(0.f, 0.f, 0.f);
- solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- b3Assert(rb);
- // solverBody->m_worldTransform = getWorldTransform(rb);
- solverBody->internalSetInvMass(b3MakeVector3(rb->m_invMass, rb->m_invMass, rb->m_invMass));
- solverBody->m_originalBodyIndex = bodyIndex;
- solverBody->m_angularFactor = b3MakeVector3(1, 1, 1);
- solverBody->m_linearFactor = b3MakeVector3(1, 1, 1);
- solverBody->m_linearVelocity = getLinearVelocity(rb);
- solverBody->m_angularVelocity = getAngularVelocity(rb);
-}
-
-void b3GpuPgsConstraintSolver::averageVelocities()
-{
-}
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- //only create the batches once.
- //@todo: incrementally update batches when constraints are added/activated and/or removed/deactivated
- B3_PROFILE("GpuSolveGroupCacheFriendlyIterations");
-
- bool createBatches = m_gpuData->m_batchSizes.size() == 0;
- {
- if (createBatches)
- {
- m_gpuData->m_batchSizes.resize(0);
-
- {
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
-
- B3_PROFILE("batch joints");
- b3Assert(batchConstraints.size() == numConstraints);
- int simdWidth = numConstraints + 1;
- int numBodies = m_tmpSolverBodyPool.size();
- sortConstraintByBatch3(&batchConstraints[0], numConstraints, simdWidth, m_staticIdx, numBodies);
-
- m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
- }
- }
- else
- {
- /*b3AlignedObjectArray<b3BatchConstraint> cpuCheckBatches;
- m_gpuData->m_gpuBatchConstraints->copyToHost(cpuCheckBatches);
- b3Assert(cpuCheckBatches.size()==batchConstraints.size());
- printf(".\n");
- */
- //>copyFromHost(batchConstraints);
- }
- int maxIterations = infoGlobal.m_numIterations;
-
- bool useBatching = true;
-
- if (useBatching)
- {
- if (!useGpuSolveJointConstraintRows)
- {
- B3_PROFILE("copy to host");
- m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- m_gpuData->m_gpuBatchConstraints->copyToHost(batchConstraints);
- m_gpuData->m_gpuConstraintRows->copyToHost(m_tmpSolverNonContactConstraintPool);
- m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
- m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
- gpuConstraints1->copyToHost(m_gpuData->m_cpuConstraints);
- }
-
- for (int iteration = 0; iteration < maxIterations; iteration++)
- {
- int batchOffset = 0;
- int constraintOffset = 0;
- int numBatches = m_gpuData->m_batchSizes.size();
- for (int bb = 0; bb < numBatches; bb++)
- {
- int numConstraintsInBatch = m_gpuData->m_batchSizes[bb];
-
- if (useGpuSolveJointConstraintRows)
- {
- B3_PROFILE("solveJointConstraintRowsKernels");
-
- /*
- __kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
- __global b3BatchConstraint* batchConstraints,
- __global b3SolverConstraint* rows,
- __global unsigned int* numConstraintRowsInfo1,
- __global unsigned int* rowOffsets,
- __global b3GpuGenericConstraint* constraints,
- int batchOffset,
- int numConstraintsInBatch*/
-
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_solveJointConstraintRowsKernels, "m_solveJointConstraintRowsKernels");
- launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuBatchConstraints->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(gpuConstraints1->getBufferCL()); //to detect disabled constraints
- launcher.setConst(batchOffset);
- launcher.setConst(numConstraintsInBatch);
-
- launcher.launch1D(numConstraintsInBatch);
- }
- else //useGpu
- {
- for (int b = 0; b < numConstraintsInBatch; b++)
- {
- const b3BatchConstraint& c = batchConstraints[batchOffset + b];
- /*printf("-----------\n");
- printf("bb=%d\n",bb);
- printf("c.batchId = %d\n", c.m_batchId);
- */
- b3Assert(c.m_batchId == bb);
- b3GpuGenericConstraint* constraint = &m_gpuData->m_cpuConstraints[c.m_originalConstraintIndex];
- if (constraint->m_flags & B3_CONSTRAINT_FLAG_ENABLED)
- {
- int numConstraintRows = m_gpuData->m_cpuConstraintInfo1[c.m_originalConstraintIndex];
- int constraintOffset = m_gpuData->m_cpuConstraintRowOffsets[c.m_originalConstraintIndex];
-
- for (int jj = 0; jj < numConstraintRows; jj++)
- {
- //
- b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[constraintOffset + jj];
- //resolveSingleConstraintRowGenericSIMD(m_tmpSolverBodyPool[constraint.m_solverBodyIdA],m_tmpSolverBodyPool[constraint.m_solverBodyIdB],constraint);
- resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
- }
- }
- }
- } //useGpu
- batchOffset += numConstraintsInBatch;
- constraintOffset += numConstraintsInBatch;
- }
- } //for (int iteration...
-
- if (!useGpuSolveJointConstraintRows)
- {
- {
- B3_PROFILE("copy from host");
- m_gpuData->m_gpuSolverBodies->copyFromHost(m_tmpSolverBodyPool);
- m_gpuData->m_gpuBatchConstraints->copyFromHost(batchConstraints);
- m_gpuData->m_gpuConstraintRows->copyFromHost(m_tmpSolverNonContactConstraintPool);
- }
-
- //B3_PROFILE("copy to host");
- //m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- }
- //int sz = sizeof(b3GpuSolverBody);
- //printf("cpu sizeof(b3GpuSolverBody)=%d\n",sz);
- }
- else
- {
- for (int iteration = 0; iteration < maxIterations; iteration++)
- {
- int numJoints = m_tmpSolverNonContactConstraintPool.size();
- for (int j = 0; j < numJoints; j++)
- {
- b3GpuSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[j];
- resolveSingleConstraintRowGeneric2(&m_tmpSolverBodyPool[constraint.m_solverBodyIdA], &m_tmpSolverBodyPool[constraint.m_solverBodyIdB], &constraint);
- }
-
- if (!m_usePgs)
- {
- averageVelocities();
- }
- }
- }
- }
- clFinish(m_gpuData->m_queue);
- return 0.f;
-}
-
-static b3AlignedObjectArray<int> bodyUsed;
-static b3AlignedObjectArray<int> curUsed;
-
-inline int b3GpuPgsConstraintSolver::sortConstraintByBatch3(b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
-{
- //int sz = sizeof(b3BatchConstraint);
-
- B3_PROFILE("sortConstraintByBatch3");
-
- static int maxSwaps = 0;
- int numSwaps = 0;
-
- curUsed.resize(2 * simdWidth);
-
- static int maxNumConstraints = 0;
- if (maxNumConstraints < numConstraints)
- {
- maxNumConstraints = numConstraints;
- //printf("maxNumConstraints = %d\n",maxNumConstraints );
- }
-
- int numUsedArray = numBodies / 32 + 1;
- bodyUsed.resize(numUsedArray);
-
- for (int q = 0; q < numUsedArray; q++)
- bodyUsed[q] = 0;
-
- int curBodyUsed = 0;
-
- int numIter = 0;
-
-#if defined(_DEBUG)
- for (int i = 0; i < numConstraints; i++)
- cs[i].m_batchId = -1;
-#endif
-
- int numValidConstraints = 0;
- // int unprocessedConstraintIndex = 0;
-
- int batchIdx = 0;
-
- {
- B3_PROFILE("cpu batch innerloop");
-
- while (numValidConstraints < numConstraints)
- {
- numIter++;
- int nCurrentBatch = 0;
- // clear flag
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed[curUsed[i] / 32] = 0;
-
- curBodyUsed = 0;
-
- for (int i = numValidConstraints; i < numConstraints; i++)
- {
- int idx = i;
- b3Assert(idx < numConstraints);
- // check if it can go
- int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
- int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
- int bodyA = abs(bodyAS);
- int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
- bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
- int aUnavailable = 0;
- int bUnavailable = 0;
- if (!aIsStatic)
- {
- aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
- }
- if (!aUnavailable)
- if (!bIsStatic)
- {
- bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
- }
-
- if (aUnavailable == 0 && bUnavailable == 0) // ok
- {
- if (!aIsStatic)
- {
- bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
- curUsed[curBodyUsed++] = bodyA;
- }
- if (!bIsStatic)
- {
- bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
- curUsed[curBodyUsed++] = bodyB;
- }
-
- cs[idx].m_batchId = batchIdx;
-
- if (i != numValidConstraints)
- {
- b3Swap(cs[i], cs[numValidConstraints]);
- numSwaps++;
- }
-
- numValidConstraints++;
- {
- nCurrentBatch++;
- if (nCurrentBatch == simdWidth)
- {
- nCurrentBatch = 0;
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed[curUsed[i] / 32] = 0;
- curBodyUsed = 0;
- }
- }
- }
- }
- m_gpuData->m_batchSizes.push_back(nCurrentBatch);
- batchIdx++;
- }
- }
-
-#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for (int i = 0; i < numConstraints; i++)
- {
- b3Assert(cs[i].m_batchId != -1);
- }
-#endif
-
- if (maxSwaps < numSwaps)
- {
- maxSwaps = numSwaps;
- //printf("maxSwaps = %d\n", maxSwaps);
- }
-
- return batchIdx;
-}
-
-/// b3PgsJacobiSolver Sequentially applies impulses
-b3Scalar b3GpuPgsConstraintSolver::solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveJoints");
- //you need to provide at least some bodies
-
- solveGroupCacheFriendlySetup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
-
- solveGroupCacheFriendlyIterations(gpuConstraints, numConstraints, infoGlobal);
-
- solveGroupCacheFriendlyFinish(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
-
- return 0.f;
-}
-
-void b3GpuPgsConstraintSolver::solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints)
-{
- b3ContactSolverInfo infoGlobal;
- infoGlobal.m_splitImpulse = false;
- infoGlobal.m_timeStep = 1.f / 60.f;
- infoGlobal.m_numIterations = 4; //4;
- // infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS|B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION;
- //infoGlobal.m_solverMode|=B3_SOLVER_USE_2_FRICTION_DIRECTIONS|B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS;
- infoGlobal.m_solverMode |= B3_SOLVER_USE_2_FRICTION_DIRECTIONS;
-
- //if (infoGlobal.m_solverMode & B3_SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- //if ((infoGlobal.m_solverMode & B3_SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & B3_SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
-
- solveGroup(gpuBodies, gpuInertias, numBodies, gpuConstraints, numConstraints, infoGlobal);
-}
-
-//b3AlignedObjectArray<b3RigidBodyData> testBodies;
-
-b3Scalar b3GpuPgsConstraintSolver::solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal)
-{
- B3_PROFILE("solveGroupCacheFriendlyFinish");
- // int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- // int i,j;
-
- {
- if (gpuBreakConstraints)
- {
- B3_PROFILE("breakViolatedConstraintsKernel");
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_breakViolatedConstraintsKernel, "m_breakViolatedConstraintsKernel");
- launcher.setBuffer(gpuConstraints->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintInfo1->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRowOffsets->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuConstraintRows->getBufferCL());
- launcher.setConst(numConstraints);
- launcher.launch1D(numConstraints);
- }
- else
- {
- gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
- m_gpuData->m_gpuBatchConstraints->copyToHost(m_gpuData->m_cpuBatchConstraints);
- m_gpuData->m_gpuConstraintRows->copyToHost(m_gpuData->m_cpuConstraintRows);
- gpuConstraints->copyToHost(m_gpuData->m_cpuConstraints);
- m_gpuData->m_gpuConstraintInfo1->copyToHost(m_gpuData->m_cpuConstraintInfo1);
- m_gpuData->m_gpuConstraintRowOffsets->copyToHost(m_gpuData->m_cpuConstraintRowOffsets);
-
- for (int cid = 0; cid < numConstraints; cid++)
- {
- int originalConstraintIndex = batchConstraints[cid].m_originalConstraintIndex;
- int constraintRowOffset = m_gpuData->m_cpuConstraintRowOffsets[originalConstraintIndex];
- int numRows = m_gpuData->m_cpuConstraintInfo1[originalConstraintIndex];
- if (numRows)
- {
- // printf("cid=%d, breakingThreshold =%f\n",cid,breakingThreshold);
- for (int i = 0; i < numRows; i++)
- {
- int rowIndex = constraintRowOffset + i;
- int orgConstraintIndex = m_gpuData->m_cpuConstraintRows[rowIndex].m_originalConstraintIndex;
- float breakingThreshold = m_gpuData->m_cpuConstraints[orgConstraintIndex].m_breakingImpulseThreshold;
- // printf("rows[%d].m_appliedImpulse=%f\n",rowIndex,rows[rowIndex].m_appliedImpulse);
- if (b3Fabs(m_gpuData->m_cpuConstraintRows[rowIndex].m_appliedImpulse) >= breakingThreshold)
- {
- m_gpuData->m_cpuConstraints[orgConstraintIndex].m_flags = 0; //&= ~B3_CONSTRAINT_FLAG_ENABLED;
- }
- }
- }
- }
-
- gpuConstraints->copyFromHost(m_gpuData->m_cpuConstraints);
- }
- }
-
- {
- if (useGpuWriteBackVelocities)
- {
- B3_PROFILE("GPU write back velocities and transforms");
-
- b3LauncherCL launcher(m_gpuData->m_queue, m_gpuData->m_writeBackVelocitiesKernel, "m_writeBackVelocitiesKernel");
- launcher.setBuffer(gpuBodies->getBufferCL());
- launcher.setBuffer(m_gpuData->m_gpuSolverBodies->getBufferCL());
- launcher.setConst(numBodies);
- launcher.launch1D(numBodies);
- clFinish(m_gpuData->m_queue);
- // m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- // m_gpuData->m_gpuBodies->copyToHostPointer(bodies,numBodies);
- //m_gpuData->m_gpuBodies->copyToHost(testBodies);
- }
- else
- {
- B3_PROFILE("CPU write back velocities and transforms");
-
- m_gpuData->m_gpuSolverBodies->copyToHost(m_tmpSolverBodyPool);
- gpuBodies->copyToHost(m_gpuData->m_cpuBodies);
- for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
- {
- int bodyIndex = m_tmpSolverBodyPool[i].m_originalBodyIndex;
- //printf("bodyIndex=%d\n",bodyIndex);
- b3Assert(i == bodyIndex);
-
- b3RigidBodyData* body = &m_gpuData->m_cpuBodies[bodyIndex];
- if (body->m_invMass)
- {
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
- else
- m_tmpSolverBodyPool[i].writebackVelocity();
-
- if (m_usePgs)
- {
- body->m_linVel = m_tmpSolverBodyPool[i].m_linearVelocity;
- body->m_angVel = m_tmpSolverBodyPool[i].m_angularVelocity;
- }
- else
- {
- b3Assert(0);
- }
- /*
- if (infoGlobal.m_splitImpulse)
- {
- body->m_pos = m_tmpSolverBodyPool[i].m_worldTransform.getOrigin();
- b3Quaternion orn;
- orn = m_tmpSolverBodyPool[i].m_worldTransform.getRotation();
- body->m_quat = orn;
- }
- */
- }
- } //for
-
- gpuBodies->copyFromHost(m_gpuData->m_cpuBodies);
- }
- }
-
- clFinish(m_gpuData->m_queue);
-
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
-
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
deleted file mode 100644
index 00bc544f02..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_GPU_PGS_CONSTRAINT_SOLVER_H
-#define B3_GPU_PGS_CONSTRAINT_SOLVER_H
-
-struct b3Contact4;
-struct b3ContactPoint;
-
-class b3Dispatcher;
-
-#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
-#include "Bullet3Dynamics/ConstraintSolver/b3ContactSolverInfo.h"
-#include "b3GpuSolverBody.h"
-#include "b3GpuSolverConstraint.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-struct b3RigidBodyData;
-struct b3InertiaData;
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "b3GpuGenericConstraint.h"
-
-class b3GpuPgsConstraintSolver
-{
-protected:
- int m_staticIdx;
- struct b3GpuPgsJacobiSolverInternalData* m_gpuData;
-
-protected:
- b3AlignedObjectArray<b3GpuSolverBody> m_tmpSolverBodyPool;
- b3GpuConstraintArray m_tmpSolverContactConstraintPool;
- b3GpuConstraintArray m_tmpSolverNonContactConstraintPool;
- b3GpuConstraintArray m_tmpSolverContactFrictionConstraintPool;
- b3GpuConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
-
- b3AlignedObjectArray<unsigned int> m_tmpConstraintSizesPool;
-
- bool m_usePgs;
- void averageVelocities();
-
- int m_maxOverrideNumSolverIterations;
-
- int m_numSplitImpulseRecoveries;
-
- // int getOrInitSolverBody(int bodyIndex, b3RigidBodyData* bodies,b3InertiaData* inertias);
- void initSolverBody(int bodyIndex, b3GpuSolverBody* solverBody, b3RigidBodyData* rb);
-
-public:
- b3GpuPgsConstraintSolver(cl_context ctx, cl_device_id device, cl_command_queue queue, bool usePgs);
- virtual ~b3GpuPgsConstraintSolver();
-
- virtual b3Scalar solveGroupCacheFriendlyIterations(b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints1, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- virtual b3Scalar solveGroupCacheFriendlySetup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- b3Scalar solveGroupCacheFriendlyFinish(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
-
- b3Scalar solveGroup(b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias, int numBodies, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints, int numConstraints, const b3ContactSolverInfo& infoGlobal);
- void solveJoints(int numBodies, b3OpenCLArray<b3RigidBodyData>* gpuBodies, b3OpenCLArray<b3InertiaData>* gpuInertias,
- int numConstraints, b3OpenCLArray<b3GpuGenericConstraint>* gpuConstraints);
-
- int sortConstraintByBatch3(struct b3BatchConstraint* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies);
- void recomputeBatches();
-};
-
-#endif //B3_GPU_PGS_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
deleted file mode 100644
index e3d235a4fd..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.cpp
+++ /dev/null
@@ -1,1529 +0,0 @@
-
-bool gUseLargeBatches = false;
-bool gCpuBatchContacts = false;
-bool gCpuSolveConstraint = false;
-bool gCpuRadixSort = false;
-bool gCpuSetSortData = false;
-bool gCpuSortContactsDeterminism = false;
-bool gUseCpuCopyConstraints = false;
-bool gUseScanHost = false;
-bool gReorderContactsOnCpu = false;
-
-bool optionalSortContactsDeterminism = true;
-
-#include "b3GpuPgsContactSolver.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-#include <string.h>
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-#include "b3Solver.h"
-
-#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
-#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
-#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
-#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
-#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
-#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
-
-#include "kernels/solverSetup.h"
-#include "kernels/solverSetup2.h"
-#include "kernels/solveContact.h"
-#include "kernels/solveFriction.h"
-#include "kernels/batchingKernels.h"
-#include "kernels/batchingKernelsNew.h"
-
-struct b3GpuBatchingPgsSolverInternalData
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
- int m_pairCapacity;
- int m_nIterations;
-
- b3OpenCLArray<b3GpuConstraint4>* m_contactCGPU;
- b3OpenCLArray<unsigned int>* m_numConstraints;
- b3OpenCLArray<unsigned int>* m_offsets;
-
- b3Solver* m_solverGPU;
-
- cl_kernel m_batchingKernel;
- cl_kernel m_batchingKernelNew;
- cl_kernel m_solveContactKernel;
- cl_kernel m_solveSingleContactKernel;
- cl_kernel m_solveSingleFrictionKernel;
- cl_kernel m_solveFrictionKernel;
- cl_kernel m_contactToConstraintKernel;
- cl_kernel m_setSortDataKernel;
- cl_kernel m_reorderContactKernel;
- cl_kernel m_copyConstraintKernel;
-
- cl_kernel m_setDeterminismSortDataBodyAKernel;
- cl_kernel m_setDeterminismSortDataBodyBKernel;
- cl_kernel m_setDeterminismSortDataChildShapeAKernel;
- cl_kernel m_setDeterminismSortDataChildShapeBKernel;
-
- class b3RadixSort32CL* m_sort32;
- class b3BoundSearchCL* m_search;
- class b3PrefixScanCL* m_scan;
-
- b3OpenCLArray<b3SortData>* m_sortDataBuffer;
- b3OpenCLArray<b3Contact4>* m_contactBuffer;
-
- b3OpenCLArray<b3RigidBodyData>* m_bodyBufferGPU;
- b3OpenCLArray<b3InertiaData>* m_inertiaBufferGPU;
- b3OpenCLArray<b3Contact4>* m_pBufContactOutGPU;
-
- b3OpenCLArray<b3Contact4>* m_pBufContactOutGPUCopy;
- b3OpenCLArray<b3SortData>* m_contactKeyValues;
-
- b3AlignedObjectArray<unsigned int> m_idxBuffer;
- b3AlignedObjectArray<b3SortData> m_sortData;
- b3AlignedObjectArray<b3Contact4> m_old;
-
- b3AlignedObjectArray<int> m_batchSizes;
- b3OpenCLArray<int>* m_batchSizesGpu;
-};
-
-b3GpuPgsContactSolver::b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity)
-{
- m_debugOutput = 0;
- m_data = new b3GpuBatchingPgsSolverInternalData;
- m_data->m_context = ctx;
- m_data->m_device = device;
- m_data->m_queue = q;
- m_data->m_pairCapacity = pairCapacity;
- m_data->m_nIterations = 4;
- m_data->m_batchSizesGpu = new b3OpenCLArray<int>(ctx, q);
- m_data->m_bodyBufferGPU = new b3OpenCLArray<b3RigidBodyData>(ctx, q);
- m_data->m_inertiaBufferGPU = new b3OpenCLArray<b3InertiaData>(ctx, q);
- m_data->m_pBufContactOutGPU = new b3OpenCLArray<b3Contact4>(ctx, q);
-
- m_data->m_pBufContactOutGPUCopy = new b3OpenCLArray<b3Contact4>(ctx, q);
- m_data->m_contactKeyValues = new b3OpenCLArray<b3SortData>(ctx, q);
-
- m_data->m_solverGPU = new b3Solver(ctx, device, q, 512 * 1024);
-
- m_data->m_sort32 = new b3RadixSort32CL(ctx, device, m_data->m_queue);
- m_data->m_scan = new b3PrefixScanCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
- m_data->m_search = new b3BoundSearchCL(ctx, device, m_data->m_queue, B3_SOLVER_N_CELLS);
-
- const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
-
- m_data->m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, m_data->m_queue, sortSize);
- m_data->m_contactBuffer = new b3OpenCLArray<b3Contact4>(ctx, m_data->m_queue);
-
- m_data->m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
- m_data->m_numConstraints->resize(B3_SOLVER_N_CELLS);
-
- m_data->m_contactCGPU = new b3OpenCLArray<b3GpuConstraint4>(ctx, q, pairCapacity);
-
- m_data->m_offsets = new b3OpenCLArray<unsigned int>(ctx, m_data->m_queue, B3_SOLVER_N_CELLS);
- m_data->m_offsets->resize(B3_SOLVER_N_CELLS);
- const char* additionalMacros = "";
- //const char* srcFileNameForCaching="";
-
- cl_int pErrNum;
- const char* batchKernelSource = batchingKernelsCL;
- const char* batchKernelNewSource = batchingKernelsNewCL;
- const char* solverSetupSource = solverSetupCL;
- const char* solverSetup2Source = solverSetup2CL;
- const char* solveContactSource = solveContactCL;
- const char* solveFrictionSource = solveFrictionCL;
-
- {
- cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
- b3Assert(solveContactProg);
-
- cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
- b3Assert(solveFrictionProg);
-
- cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
-
- b3Assert(solverSetup2Prog);
-
- cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
- b3Assert(solverSetupProg);
-
- m_data->m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
- b3Assert(m_data->m_solveFrictionKernel);
-
- m_data->m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
- b3Assert(m_data->m_solveContactKernel);
-
- m_data->m_solveSingleContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "solveSingleContactKernel", &pErrNum, solveContactProg, additionalMacros);
- b3Assert(m_data->m_solveSingleContactKernel);
-
- m_data->m_solveSingleFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "solveSingleFrictionKernel", &pErrNum, solveFrictionProg, additionalMacros);
- b3Assert(m_data->m_solveSingleFrictionKernel);
-
- m_data->m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
- b3Assert(m_data->m_contactToConstraintKernel);
-
- m_data->m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_setSortDataKernel);
-
- m_data->m_setDeterminismSortDataBodyAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyA", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_setDeterminismSortDataBodyAKernel);
-
- m_data->m_setDeterminismSortDataBodyBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataBodyB", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_setDeterminismSortDataBodyBKernel);
-
- m_data->m_setDeterminismSortDataChildShapeAKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeA", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_setDeterminismSortDataChildShapeAKernel);
-
- m_data->m_setDeterminismSortDataChildShapeBKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetDeterminismSortDataChildShapeB", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_setDeterminismSortDataChildShapeBKernel);
-
- m_data->m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_reorderContactKernel);
-
- m_data->m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_data->m_copyConstraintKernel);
- }
-
- {
- cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
- b3Assert(batchingProg);
-
- m_data->m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
- b3Assert(m_data->m_batchingKernel);
- }
-
- {
- cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
- b3Assert(batchingNewProg);
-
- m_data->m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
- b3Assert(m_data->m_batchingKernelNew);
- }
-}
-
-b3GpuPgsContactSolver::~b3GpuPgsContactSolver()
-{
- delete m_data->m_batchSizesGpu;
- delete m_data->m_bodyBufferGPU;
- delete m_data->m_inertiaBufferGPU;
- delete m_data->m_pBufContactOutGPU;
- delete m_data->m_pBufContactOutGPUCopy;
- delete m_data->m_contactKeyValues;
-
- delete m_data->m_contactCGPU;
- delete m_data->m_numConstraints;
- delete m_data->m_offsets;
- delete m_data->m_sortDataBuffer;
- delete m_data->m_contactBuffer;
-
- delete m_data->m_sort32;
- delete m_data->m_scan;
- delete m_data->m_search;
- delete m_data->m_solverGPU;
-
- clReleaseKernel(m_data->m_batchingKernel);
- clReleaseKernel(m_data->m_batchingKernelNew);
- clReleaseKernel(m_data->m_solveSingleContactKernel);
- clReleaseKernel(m_data->m_solveSingleFrictionKernel);
- clReleaseKernel(m_data->m_solveContactKernel);
- clReleaseKernel(m_data->m_solveFrictionKernel);
-
- clReleaseKernel(m_data->m_contactToConstraintKernel);
- clReleaseKernel(m_data->m_setSortDataKernel);
- clReleaseKernel(m_data->m_reorderContactKernel);
- clReleaseKernel(m_data->m_copyConstraintKernel);
-
- clReleaseKernel(m_data->m_setDeterminismSortDataBodyAKernel);
- clReleaseKernel(m_data->m_setDeterminismSortDataBodyBKernel);
- clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeAKernel);
- clReleaseKernel(m_data->m_setDeterminismSortDataChildShapeBKernel);
-
- delete m_data;
-}
-
-struct b3ConstraintCfg
-{
- b3ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(0) {}
-
- float m_positionDrift;
- float m_positionConstraintCoeff;
- float m_dt;
- bool m_enableParallelSolve;
- float m_batchCellSize;
- int m_staticIdx;
-};
-
-void b3GpuPgsContactSolver::solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes) //const b3OpenCLArray<int>* gpuBatchSizes)
-{
- B3_PROFILE("solveContactConstraintBatchSizes");
- int numBatches = batchSizes->size() / B3_MAX_NUM_BATCHES;
- for (int iter = 0; iter < numIterations; iter++)
- {
- for (int cellId = 0; cellId < numBatches; cellId++)
- {
- int offset = 0;
- for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
- {
- int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
- if (!numInBatch)
- break;
-
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleContactKernel, "m_solveSingleContactKernel");
- launcher.setBuffer(bodyBuf->getBufferCL());
- launcher.setBuffer(shapeBuf->getBufferCL());
- launcher.setBuffer(constraint->getBufferCL());
- launcher.setConst(cellId);
- launcher.setConst(offset);
- launcher.setConst(numInBatch);
- launcher.launch1D(numInBatch);
- offset += numInBatch;
- }
- }
- }
- }
-
- for (int iter = 0; iter < numIterations; iter++)
- {
- for (int cellId = 0; cellId < numBatches; cellId++)
- {
- int offset = 0;
- for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
- {
- int numInBatch = batchSizes->at(cellId * B3_MAX_NUM_BATCHES + ii);
- if (!numInBatch)
- break;
-
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solveSingleFrictionKernel, "m_solveSingleFrictionKernel");
- launcher.setBuffer(bodyBuf->getBufferCL());
- launcher.setBuffer(shapeBuf->getBufferCL());
- launcher.setBuffer(constraint->getBufferCL());
- launcher.setConst(cellId);
- launcher.setConst(offset);
- launcher.setConst(numInBatch);
- launcher.launch1D(numInBatch);
- offset += numInBatch;
- }
- }
- }
- }
-}
-
-void b3GpuPgsContactSolver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes) //,const b3OpenCLArray<int>* gpuBatchSizes)
-{
- //sort the contacts
-
- b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
- {
- const int nn = B3_SOLVER_N_CELLS;
-
- cdata.x = 0;
- cdata.y = maxNumBatches; //250;
-
- int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
-#ifdef DEBUG_ME
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
-#endif
-
- {
- B3_PROFILE("m_batchSolveKernel iterations");
- for (int iter = 0; iter < numIterations; iter++)
- {
- for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
- {
-#ifdef DEBUG_ME
- memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
- gpuDebugInfo.write(debugInfo, numWorkItems);
-#endif
-
- cdata.z = ib;
-
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solveContactKernel, "m_solveContactKernel");
-#if 1
-
- b3BufferInfoCL bInfo[] = {
-
- b3BufferInfoCL(bodyBuf->getBufferCL()),
- b3BufferInfoCL(shapeBuf->getBufferCL()),
- b3BufferInfoCL(constraint->getBufferCL()),
- b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
- b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
-#ifdef DEBUG_ME
- ,
- b3BufferInfoCL(&gpuDebugInfo)
-#endif
- };
-
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
- //launcher.setConst( cdata.x );
- launcher.setConst(cdata.y);
- launcher.setConst(cdata.z);
- b3Int4 nSplit;
- nSplit.x = B3_SOLVER_N_SPLIT_X;
- nSplit.y = B3_SOLVER_N_SPLIT_Y;
- nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- launcher.setConst(nSplit);
- launcher.launch1D(numWorkItems, 64);
-
-#else
- const char* fileName = "m_batchSolveKernel.bin";
- FILE* f = fopen(fileName, "rb");
- if (f)
- {
- int sizeInBytes = 0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
- fread(buf, sizeInBytes, 1, f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
- int num = *(int*)&buf[serializedBytes];
-
- launcher.launch1D(num);
-
- //this clFinish is for testing on errors
- clFinish(m_queue);
- }
-
-#endif
-
-#ifdef DEBUG_ME
- clFinish(m_queue);
- gpuDebugInfo.read(debugInfo, numWorkItems);
- clFinish(m_queue);
- for (int i = 0; i < numWorkItems; i++)
- {
- if (debugInfo[i].m_valInt2 > 0)
- {
- printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
- }
-
- if (debugInfo[i].m_valInt3 > 0)
- {
- printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
- }
- }
-#endif //DEBUG_ME
- }
- }
-
- clFinish(m_data->m_queue);
- }
-
- cdata.x = 1;
- bool applyFriction = true;
- if (applyFriction)
- {
- B3_PROFILE("m_batchSolveKernel iterations2");
- for (int iter = 0; iter < numIterations; iter++)
- {
- for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
- {
- cdata.z = ib;
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(bodyBuf->getBufferCL()),
- b3BufferInfoCL(shapeBuf->getBufferCL()),
- b3BufferInfoCL(constraint->getBufferCL()),
- b3BufferInfoCL(m_data->m_solverGPU->m_numConstraints->getBufferCL()),
- b3BufferInfoCL(m_data->m_solverGPU->m_offsets->getBufferCL())
-#ifdef DEBUG_ME
- ,
- b3BufferInfoCL(&gpuDebugInfo)
-#endif //DEBUG_ME
- };
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solveFrictionKernel, "m_solveFrictionKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setBuffer(m_data->m_solverGPU->m_batchSizes.getBufferCL());
- //launcher.setConst( cdata.x );
- launcher.setConst(cdata.y);
- launcher.setConst(cdata.z);
-
- b3Int4 nSplit;
- nSplit.x = B3_SOLVER_N_SPLIT_X;
- nSplit.y = B3_SOLVER_N_SPLIT_Y;
- nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- launcher.setConst(nSplit);
-
- launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
- }
- }
- clFinish(m_data->m_queue);
- }
-#ifdef DEBUG_ME
- delete[] debugInfo;
-#endif //DEBUG_ME
- }
-}
-
-static bool sortfnc(const b3SortData& a, const b3SortData& b)
-{
- return (a.m_key < b.m_key);
-}
-
-static bool b3ContactCmp(const b3Contact4& p, const b3Contact4& q)
-{
- return ((p.m_bodyAPtrAndSignBit < q.m_bodyAPtrAndSignBit) ||
- ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit < q.m_bodyBPtrAndSignBit)) ||
- ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
- ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA < q.m_childIndexA) ||
- ((p.m_bodyAPtrAndSignBit == q.m_bodyAPtrAndSignBit) && (p.m_bodyBPtrAndSignBit == q.m_bodyBPtrAndSignBit) && p.m_childIndexA == q.m_childIndexA && p.m_childIndexB < q.m_childIndexB));
-}
-
-#define USE_SPATIAL_BATCHING 1
-#define USE_4x4_GRID 1
-
-#ifndef USE_SPATIAL_BATCHING
-static const int gridTable4x4[] =
- {
- 0, 1, 17, 16,
- 1, 2, 18, 19,
- 17, 18, 32, 3,
- 16, 19, 3, 34};
-static const int gridTable8x8[] =
- {
- 0, 2, 3, 16, 17, 18, 19, 1,
- 66, 64, 80, 67, 82, 81, 65, 83,
- 131, 144, 128, 130, 147, 129, 145, 146,
- 208, 195, 194, 192, 193, 211, 210, 209,
- 21, 22, 23, 5, 4, 6, 7, 20,
- 86, 85, 69, 87, 70, 68, 84, 71,
- 151, 133, 149, 150, 135, 148, 132, 134,
- 197, 27, 214, 213, 212, 199, 198, 196
-
-};
-
-#endif
-
-void SetSortDataCPU(b3Contact4* gContact, b3RigidBodyData* gBodies, b3SortData* gSortDataOut, int nContacts, float scale, const b3Int4& nSplit, int staticIdx)
-{
- for (int gIdx = 0; gIdx < nContacts; gIdx++)
- {
- if (gIdx < nContacts)
- {
- int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
- int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
-
- int aIdx = abs(aPtrAndSignBit);
- int bIdx = abs(bPtrAndSignBit);
-
- bool aStatic = (aPtrAndSignBit < 0) || (aPtrAndSignBit == staticIdx);
-
-#if USE_SPATIAL_BATCHING
- int idx = (aStatic) ? bIdx : aIdx;
- b3Vector3 p = gBodies[idx].m_pos;
- int xIdx = (int)((p.x - ((p.x < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.x - 1);
- int yIdx = (int)((p.y - ((p.y < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.y - 1);
- int zIdx = (int)((p.z - ((p.z < 0.f) ? 1.f : 0.f)) * scale) & (nSplit.z - 1);
-
- int newIndex = (xIdx + yIdx * nSplit.x + zIdx * nSplit.x * nSplit.y);
-
-#else //USE_SPATIAL_BATCHING
- bool bStatic = (bPtrAndSignBit < 0) || (bPtrAndSignBit == staticIdx);
-
-#if USE_4x4_GRID
- int aa = aIdx & 3;
- int bb = bIdx & 3;
- if (aStatic)
- aa = bb;
- if (bStatic)
- bb = aa;
-
- int gridIndex = aa + bb * 4;
- int newIndex = gridTable4x4[gridIndex];
-#else //USE_4x4_GRID
- int aa = aIdx & 7;
- int bb = bIdx & 7;
- if (aStatic)
- aa = bb;
- if (bStatic)
- bb = aa;
-
- int gridIndex = aa + bb * 8;
- int newIndex = gridTable8x8[gridIndex];
-#endif //USE_4x4_GRID
-#endif //USE_SPATIAL_BATCHING
-
- gSortDataOut[gIdx].x = newIndex;
- gSortDataOut[gIdx].y = gIdx;
- }
- else
- {
- gSortDataOut[gIdx].x = 0xffffffff;
- }
- }
-}
-
-void b3GpuPgsContactSolver::solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const b3Config& config, int static0Index)
-{
- B3_PROFILE("solveContacts");
- m_data->m_bodyBufferGPU->setFromOpenCLBuffer(bodyBuf, numBodies);
- m_data->m_inertiaBufferGPU->setFromOpenCLBuffer(inertiaBuf, numBodies);
- m_data->m_pBufContactOutGPU->setFromOpenCLBuffer(contactBuf, numContacts);
-
- if (optionalSortContactsDeterminism)
- {
- if (!gCpuSortContactsDeterminism)
- {
- B3_PROFILE("GPU Sort contact constraints (determinism)");
-
- m_data->m_pBufContactOutGPUCopy->resize(numContacts);
- m_data->m_contactKeyValues->resize(numContacts);
-
- m_data->m_pBufContactOutGPU->copyToCL(m_data->m_pBufContactOutGPUCopy->getBufferCL(), numContacts, 0, 0);
-
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeBKernel, "m_setDeterminismSortDataChildShapeBKernel");
- launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
- launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst(numContacts);
- launcher.launch1D(numContacts, 64);
- }
- m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataChildShapeAKernel, "m_setDeterminismSortDataChildShapeAKernel");
- launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
- launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst(numContacts);
- launcher.launch1D(numContacts, 64);
- }
- m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyBKernel, "m_setDeterminismSortDataBodyBKernel");
- launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
- launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst(numContacts);
- launcher.launch1D(numContacts, 64);
- }
-
- m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
-
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_setDeterminismSortDataBodyAKernel, "m_setDeterminismSortDataBodyAKernel");
- launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
- launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst(numContacts);
- launcher.launch1D(numContacts, 64);
- }
-
- m_data->m_solverGPU->m_sort32->execute(*m_data->m_contactKeyValues);
-
- {
- B3_PROFILE("gpu reorderContactKernel (determinism)");
-
- b3Int4 cdata;
- cdata.x = numContacts;
-
- //b3BufferInfoCL bInfo[] = { b3BufferInfoCL( m_data->m_pBufContactOutGPU->getBufferCL() ), b3BufferInfoCL( m_data->m_solverGPU->m_contactBuffer2->getBufferCL())
- // , b3BufferInfoCL( m_data->m_solverGPU->m_sortDataBuffer->getBufferCL()) };
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
- launcher.setBuffer(m_data->m_pBufContactOutGPUCopy->getBufferCL());
- launcher.setBuffer(m_data->m_pBufContactOutGPU->getBufferCL());
- launcher.setBuffer(m_data->m_contactKeyValues->getBufferCL());
- launcher.setConst(cdata);
- launcher.launch1D(numContacts, 64);
- }
- }
- else
- {
- B3_PROFILE("CPU Sort contact constraints (determinism)");
- b3AlignedObjectArray<b3Contact4> cpuConstraints;
- m_data->m_pBufContactOutGPU->copyToHost(cpuConstraints);
- bool sort = true;
- if (sort)
- {
- cpuConstraints.quickSort(b3ContactCmp);
-
- for (int i = 0; i < cpuConstraints.size(); i++)
- {
- cpuConstraints[i].m_batchIdx = i;
- }
- }
- m_data->m_pBufContactOutGPU->copyFromHost(cpuConstraints);
- if (m_debugOutput == 100)
- {
- for (int i = 0; i < cpuConstraints.size(); i++)
- {
- printf("c[%d].m_bodyA = %d, m_bodyB = %d, batchId = %d\n", i, cpuConstraints[i].m_bodyAPtrAndSignBit, cpuConstraints[i].m_bodyBPtrAndSignBit, cpuConstraints[i].m_batchIdx);
- }
- }
-
- m_debugOutput++;
- }
- }
-
- int nContactOut = m_data->m_pBufContactOutGPU->size();
-
- bool useSolver = true;
-
- if (useSolver)
- {
- float dt = 1. / 60.;
- b3ConstraintCfg csCfg(dt);
- csCfg.m_enableParallelSolve = true;
- csCfg.m_batchCellSize = 6;
- csCfg.m_staticIdx = static0Index;
-
- b3OpenCLArray<b3RigidBodyData>* bodyBuf = m_data->m_bodyBufferGPU;
-
- void* additionalData = 0; //m_data->m_frictionCGPU;
- const b3OpenCLArray<b3InertiaData>* shapeBuf = m_data->m_inertiaBufferGPU;
- b3OpenCLArray<b3GpuConstraint4>* contactConstraintOut = m_data->m_contactCGPU;
- int nContacts = nContactOut;
-
- int maxNumBatches = 0;
-
- if (!gUseLargeBatches)
- {
- if (m_data->m_solverGPU->m_contactBuffer2)
- {
- m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
- }
-
- if (m_data->m_solverGPU->m_contactBuffer2 == 0)
- {
- m_data->m_solverGPU->m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(m_data->m_context, m_data->m_queue, nContacts);
- m_data->m_solverGPU->m_contactBuffer2->resize(nContacts);
- }
-
- //clFinish(m_data->m_queue);
-
- {
- B3_PROFILE("batching");
- //@todo: just reserve it, without copy of original contact (unless we use warmstarting)
-
- //const b3OpenCLArray<b3RigidBodyData>* bodyNative = bodyBuf;
-
- {
- //b3OpenCLArray<b3RigidBodyData>* bodyNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, bodyBuf );
- //b3OpenCLArray<b3Contact4>* contactNative = b3OpenCLArrayUtils::map<adl::TYPE_CL, true>( data->m_device, contactsIn );
-
- const int sortAlignment = 512; // todo. get this out of sort
- if (csCfg.m_enableParallelSolve)
- {
- int sortSize = B3NEXTMULTIPLEOF(nContacts, sortAlignment);
-
- b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
- b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
- if (!gCpuSetSortData)
- { // 2. set cell idx
- B3_PROFILE("GPU set cell idx");
- struct CB
- {
- int m_nContacts;
- int m_staticIdx;
- float m_scale;
- b3Int4 m_nSplit;
- };
-
- b3Assert(sortSize % 64 == 0);
- CB cdata;
- cdata.m_nContacts = nContacts;
- cdata.m_staticIdx = csCfg.m_staticIdx;
- cdata.m_scale = 1.f / csCfg.m_batchCellSize;
- cdata.m_nSplit.x = B3_SOLVER_N_SPLIT_X;
- cdata.m_nSplit.y = B3_SOLVER_N_SPLIT_Y;
- cdata.m_nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
-
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_setSortDataKernel, "m_setSortDataKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata.m_nContacts);
- launcher.setConst(cdata.m_scale);
- launcher.setConst(cdata.m_nSplit);
- launcher.setConst(cdata.m_staticIdx);
-
- launcher.launch1D(sortSize, 64);
- }
- else
- {
- m_data->m_solverGPU->m_sortDataBuffer->resize(nContacts);
- b3AlignedObjectArray<b3SortData> sortDataCPU;
- m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataCPU);
-
- b3AlignedObjectArray<b3Contact4> contactCPU;
- m_data->m_pBufContactOutGPU->copyToHost(contactCPU);
- b3AlignedObjectArray<b3RigidBodyData> bodiesCPU;
- bodyBuf->copyToHost(bodiesCPU);
- float scale = 1.f / csCfg.m_batchCellSize;
- b3Int4 nSplit;
- nSplit.x = B3_SOLVER_N_SPLIT_X;
- nSplit.y = B3_SOLVER_N_SPLIT_Y;
- nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- SetSortDataCPU(&contactCPU[0], &bodiesCPU[0], &sortDataCPU[0], nContacts, scale, nSplit, csCfg.m_staticIdx);
-
- m_data->m_solverGPU->m_sortDataBuffer->copyFromHost(sortDataCPU);
- }
-
- if (!gCpuRadixSort)
- { // 3. sort by cell idx
- B3_PROFILE("gpuRadixSort");
- //int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
- //int sortBit = 32;
- //if( n <= 0xffff ) sortBit = 16;
- //if( n <= 0xff ) sortBit = 8;
- //adl::RadixSort<adl::TYPE_CL>::execute( data->m_sort, *data->m_sortDataBuffer, sortSize );
- //adl::RadixSort32<adl::TYPE_CL>::execute( data->m_sort32, *data->m_sortDataBuffer, sortSize );
- b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
- this->m_data->m_solverGPU->m_sort32->execute(keyValuesInOut);
- }
- else
- {
- b3OpenCLArray<b3SortData>& keyValuesInOut = *(m_data->m_solverGPU->m_sortDataBuffer);
- b3AlignedObjectArray<b3SortData> hostValues;
- keyValuesInOut.copyToHost(hostValues);
- hostValues.quickSort(sortfnc);
- keyValuesInOut.copyFromHost(hostValues);
- }
-
- if (gUseScanHost)
- {
- // 4. find entries
- B3_PROFILE("cpuBoundSearch");
- b3AlignedObjectArray<unsigned int> countsHost;
- countsNative->copyToHost(countsHost);
-
- b3AlignedObjectArray<b3SortData> sortDataHost;
- m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
-
- //m_data->m_solverGPU->m_search->executeHost(*m_data->m_solverGPU->m_sortDataBuffer,nContacts,*countsNative,B3_SOLVER_N_CELLS,b3BoundSearchCL::COUNT);
- m_data->m_solverGPU->m_search->executeHost(sortDataHost, nContacts, countsHost, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
-
- countsNative->copyFromHost(countsHost);
-
- //adl::BoundSearch<adl::TYPE_CL>::execute( data->m_search, *data->m_sortDataBuffer, nContacts, *countsNative,
- // B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, adl::BoundSearchBase::COUNT );
-
- //unsigned int sum;
- //m_data->m_solverGPU->m_scan->execute(*countsNative,*offsetsNative, B3_SOLVER_N_CELLS);//,&sum );
- b3AlignedObjectArray<unsigned int> offsetsHost;
- offsetsHost.resize(offsetsNative->size());
-
- m_data->m_solverGPU->m_scan->executeHost(countsHost, offsetsHost, B3_SOLVER_N_CELLS); //,&sum );
- offsetsNative->copyFromHost(offsetsHost);
-
- //printf("sum = %d\n",sum);
- }
- else
- {
- // 4. find entries
- B3_PROFILE("gpuBoundSearch");
- m_data->m_solverGPU->m_search->execute(*m_data->m_solverGPU->m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_CELLS, b3BoundSearchCL::COUNT);
- m_data->m_solverGPU->m_scan->execute(*countsNative, *offsetsNative, B3_SOLVER_N_CELLS); //,&sum );
- }
-
- if (nContacts)
- { // 5. sort constraints by cellIdx
- if (gReorderContactsOnCpu)
- {
- B3_PROFILE("cpu m_reorderContactKernel");
- b3AlignedObjectArray<b3SortData> sortDataHost;
- m_data->m_solverGPU->m_sortDataBuffer->copyToHost(sortDataHost);
- b3AlignedObjectArray<b3Contact4> inContacts;
- b3AlignedObjectArray<b3Contact4> outContacts;
- m_data->m_pBufContactOutGPU->copyToHost(inContacts);
- outContacts.resize(inContacts.size());
- for (int i = 0; i < nContacts; i++)
- {
- int srcIdx = sortDataHost[i].y;
- outContacts[i] = inContacts[srcIdx];
- }
- m_data->m_solverGPU->m_contactBuffer2->copyFromHost(outContacts);
-
- /* "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
- "{\n"
- " int nContacts = cb.x;\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int srcIdx = sortData[gIdx].y;\n"
- " out[gIdx] = in[srcIdx];\n"
- " }\n"
- "}\n"
- */
- }
- else
- {
- B3_PROFILE("gpu m_reorderContactKernel");
-
- b3Int4 cdata;
- cdata.x = nContacts;
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL()),
- b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()), b3BufferInfoCL(m_data->m_solverGPU->m_sortDataBuffer->getBufferCL())};
-
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_reorderContactKernel, "m_reorderContactKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(nContacts, 64);
- }
- }
- }
- }
-
- //clFinish(m_data->m_queue);
-
- // {
- // b3AlignedObjectArray<unsigned int> histogram;
- // m_data->m_solverGPU->m_numConstraints->copyToHost(histogram);
- // printf(",,,\n");
- // }
-
- if (nContacts)
- {
- if (gUseCpuCopyConstraints)
- {
- for (int i = 0; i < nContacts; i++)
- {
- m_data->m_pBufContactOutGPU->copyFromOpenCLArray(*m_data->m_solverGPU->m_contactBuffer2);
- // m_data->m_solverGPU->m_contactBuffer2->getBufferCL();
- // m_data->m_pBufContactOutGPU->getBufferCL()
- }
- }
- else
- {
- B3_PROFILE("gpu m_copyConstraintKernel");
- b3Int4 cdata;
- cdata.x = nContacts;
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(m_data->m_solverGPU->m_contactBuffer2->getBufferCL()),
- b3BufferInfoCL(m_data->m_pBufContactOutGPU->getBufferCL())};
-
- b3LauncherCL launcher(m_data->m_queue, m_data->m_solverGPU->m_copyConstraintKernel, "m_copyConstraintKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- launcher.setConst(cdata);
- launcher.launch1D(nContacts, 64);
- //we use the clFinish for proper benchmark/profile
- clFinish(m_data->m_queue);
- }
- }
-
- // bool compareGPU = false;
- if (nContacts)
- {
- if (!gCpuBatchContacts)
- {
- B3_PROFILE("gpu batchContacts");
- maxNumBatches = 250; //250;
- m_data->m_solverGPU->batchContacts(m_data->m_pBufContactOutGPU, nContacts, m_data->m_solverGPU->m_numConstraints, m_data->m_solverGPU->m_offsets, csCfg.m_staticIdx);
- clFinish(m_data->m_queue);
- }
- else
- {
- B3_PROFILE("cpu batchContacts");
- static b3AlignedObjectArray<b3Contact4> cpuContacts;
- b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
- {
- B3_PROFILE("copyToHost");
- contactsIn->copyToHost(cpuContacts);
- }
- b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
- b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
- b3AlignedObjectArray<unsigned int> nNativeHost;
- b3AlignedObjectArray<unsigned int> offsetsNativeHost;
-
- {
- B3_PROFILE("countsNative/offsetsNative copyToHost");
- countsNative->copyToHost(nNativeHost);
- offsetsNative->copyToHost(offsetsNativeHost);
- }
-
- int numNonzeroGrid = 0;
-
- if (gUseLargeBatches)
- {
- m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
- int totalNumConstraints = cpuContacts.size();
- //int simdWidth =numBodies+1;//-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]); // on GPU
- maxNumBatches = b3Max(numBatches, maxNumBatches);
- static int globalMaxBatch = 0;
- if (maxNumBatches > globalMaxBatch)
- {
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n", maxNumBatches);
- }
- }
- else
- {
- m_data->m_batchSizes.resize(B3_SOLVER_N_CELLS * B3_MAX_NUM_BATCHES);
- B3_PROFILE("cpu batch grid");
- for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
- {
- int n = (nNativeHost)[i];
- int offset = (offsetsNativeHost)[i];
- if (n)
- {
- numNonzeroGrid++;
- int simdWidth = numBodies + 1; //-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3(&cpuContacts[0] + offset, n, simdWidth, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[i * B3_MAX_NUM_BATCHES]); // on GPU
- maxNumBatches = b3Max(numBatches, maxNumBatches);
- static int globalMaxBatch = 0;
- if (maxNumBatches > globalMaxBatch)
- {
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n", maxNumBatches);
- }
- //we use the clFinish for proper benchmark/profile
- }
- }
- //clFinish(m_data->m_queue);
- }
- {
- B3_PROFILE("m_contactBuffer->copyFromHost");
- m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
- }
- }
- }
- }
- }
-
- //printf("maxNumBatches = %d\n", maxNumBatches);
-
- if (gUseLargeBatches)
- {
- if (nContacts)
- {
- B3_PROFILE("cpu batchContacts");
- static b3AlignedObjectArray<b3Contact4> cpuContacts;
- // b3OpenCLArray<b3Contact4>* contactsIn = m_data->m_solverGPU->m_contactBuffer2;
- {
- B3_PROFILE("copyToHost");
- m_data->m_pBufContactOutGPU->copyToHost(cpuContacts);
- }
- // b3OpenCLArray<unsigned int>* countsNative = m_data->m_solverGPU->m_numConstraints;
- // b3OpenCLArray<unsigned int>* offsetsNative = m_data->m_solverGPU->m_offsets;
-
- // int numNonzeroGrid=0;
-
- {
- m_data->m_batchSizes.resize(B3_MAX_NUM_BATCHES);
- int totalNumConstraints = cpuContacts.size();
- // int simdWidth =numBodies+1;//-1;//64;//-1;//32;
- int numBatches = sortConstraintByBatch3(&cpuContacts[0], totalNumConstraints, totalNumConstraints + 1, csCfg.m_staticIdx, numBodies, &m_data->m_batchSizes[0]); // on GPU
- maxNumBatches = b3Max(numBatches, maxNumBatches);
- static int globalMaxBatch = 0;
- if (maxNumBatches > globalMaxBatch)
- {
- globalMaxBatch = maxNumBatches;
- b3Printf("maxNumBatches = %d\n", maxNumBatches);
- }
- }
- {
- B3_PROFILE("m_contactBuffer->copyFromHost");
- m_data->m_solverGPU->m_contactBuffer2->copyFromHost((b3AlignedObjectArray<b3Contact4>&)cpuContacts);
- }
- }
- }
-
- if (nContacts)
- {
- B3_PROFILE("gpu convertToConstraints");
- m_data->m_solverGPU->convertToConstraints(bodyBuf,
- shapeBuf, m_data->m_solverGPU->m_contactBuffer2,
- contactConstraintOut,
- additionalData, nContacts,
- (b3SolverBase::ConstraintCfg&)csCfg);
- clFinish(m_data->m_queue);
- }
-
- if (1)
- {
- int numIter = 4;
-
- m_data->m_solverGPU->m_nIterations = numIter; //10
- if (!gCpuSolveConstraint)
- {
- B3_PROFILE("GPU solveContactConstraint");
-
- /*m_data->m_solverGPU->solveContactConstraint(
- m_data->m_bodyBufferGPU,
- m_data->m_inertiaBufferGPU,
- m_data->m_contactCGPU,0,
- nContactOut ,
- maxNumBatches);
- */
-
- //m_data->m_batchSizesGpu->copyFromHost(m_data->m_batchSizes);
-
- if (gUseLargeBatches)
- {
- solveContactConstraintBatchSizes(m_data->m_bodyBufferGPU,
- m_data->m_inertiaBufferGPU,
- m_data->m_contactCGPU, 0,
- nContactOut,
- maxNumBatches, numIter, &m_data->m_batchSizes);
- }
- else
- {
- solveContactConstraint(
- m_data->m_bodyBufferGPU,
- m_data->m_inertiaBufferGPU,
- m_data->m_contactCGPU, 0,
- nContactOut,
- maxNumBatches, numIter, &m_data->m_batchSizes); //m_data->m_batchSizesGpu);
- }
- }
- else
- {
- B3_PROFILE("Host solveContactConstraint");
-
- m_data->m_solverGPU->solveContactConstraintHost(m_data->m_bodyBufferGPU, m_data->m_inertiaBufferGPU, m_data->m_contactCGPU, 0, nContactOut, maxNumBatches, &m_data->m_batchSizes);
- }
- }
-
-#if 0
- if (0)
- {
- B3_PROFILE("read body velocities back to CPU");
- //read body updated linear/angular velocities back to CPU
- m_data->m_bodyBufferGPU->read(
- m_data->m_bodyBufferCPU->m_ptr,numOfConvexRBodies);
- adl::DeviceUtils::waitForCompletion( m_data->m_deviceCL );
- }
-#endif
- }
-}
-
-void b3GpuPgsContactSolver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx)
-{
-}
-
-b3AlignedObjectArray<unsigned int> idxBuffer;
-b3AlignedObjectArray<b3SortData> sortData;
-b3AlignedObjectArray<b3Contact4> old;
-
-inline int b3GpuPgsContactSolver::sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies)
-{
- B3_PROFILE("sortConstraintByBatch");
- int numIter = 0;
-
- sortData.resize(n);
- idxBuffer.resize(n);
- old.resize(n);
-
- unsigned int* idxSrc = &idxBuffer[0];
- unsigned int* idxDst = &idxBuffer[0];
- int nIdxSrc, nIdxDst;
-
- const int N_FLG = 256;
- const int FLG_MASK = N_FLG - 1;
- unsigned int flg[N_FLG / 32];
-#if defined(_DEBUG)
- for (int i = 0; i < n; i++)
- cs[i].getBatchIdx() = -1;
-#endif
- for (int i = 0; i < n; i++)
- idxSrc[i] = i;
- nIdxSrc = n;
-
- int batchIdx = 0;
-
- {
- B3_PROFILE("cpu batch innerloop");
- while (nIdxSrc)
- {
- numIter++;
- nIdxDst = 0;
- int nCurrentBatch = 0;
-
- // clear flag
- for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
-
- for (int i = 0; i < nIdxSrc; i++)
- {
- int idx = idxSrc[i];
-
- b3Assert(idx < n);
- // check if it can go
- int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
- int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
-
- int bodyA = abs(bodyAS);
- int bodyB = abs(bodyBS);
-
- int aIdx = bodyA & FLG_MASK;
- int bIdx = bodyB & FLG_MASK;
-
- unsigned int aUnavailable = flg[aIdx / 32] & (1 << (aIdx & 31));
- unsigned int bUnavailable = flg[bIdx / 32] & (1 << (bIdx & 31));
-
- bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
- bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
-
- //use inv_mass!
- aUnavailable = !aIsStatic ? aUnavailable : 0; //
- bUnavailable = !bIsStatic ? bUnavailable : 0;
-
- if (aUnavailable == 0 && bUnavailable == 0) // ok
- {
- if (!aIsStatic)
- flg[aIdx / 32] |= (1 << (aIdx & 31));
- if (!bIsStatic)
- flg[bIdx / 32] |= (1 << (bIdx & 31));
-
- cs[idx].getBatchIdx() = batchIdx;
- sortData[idx].m_key = batchIdx;
- sortData[idx].m_value = idx;
-
- {
- nCurrentBatch++;
- if (nCurrentBatch == simdWidth)
- {
- nCurrentBatch = 0;
- for (int i = 0; i < N_FLG / 32; i++) flg[i] = 0;
- }
- }
- }
- else
- {
- idxDst[nIdxDst++] = idx;
- }
- }
- b3Swap(idxSrc, idxDst);
- b3Swap(nIdxSrc, nIdxDst);
- batchIdx++;
- }
- }
- {
- B3_PROFILE("quickSort");
- sortData.quickSort(sortfnc);
- }
-
- {
- B3_PROFILE("reorder");
- // reorder
-
- memcpy(&old[0], cs, sizeof(b3Contact4) * n);
- for (int i = 0; i < n; i++)
- {
- int idx = sortData[i].m_value;
- cs[i] = old[idx];
- }
- }
-
-#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for (int i = 0; i < n; i++)
- {
- b3Assert(cs[i].getBatchIdx() != -1);
- }
-#endif
- return batchIdx;
-}
-
-b3AlignedObjectArray<int> bodyUsed2;
-
-inline int b3GpuPgsContactSolver::sortConstraintByBatch2(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies)
-{
- B3_PROFILE("sortConstraintByBatch2");
-
- bodyUsed2.resize(2 * simdWidth);
-
- for (int q = 0; q < 2 * simdWidth; q++)
- bodyUsed2[q] = 0;
-
- int curBodyUsed = 0;
-
- int numIter = 0;
-
- m_data->m_sortData.resize(numConstraints);
- m_data->m_idxBuffer.resize(numConstraints);
- m_data->m_old.resize(numConstraints);
-
- unsigned int* idxSrc = &m_data->m_idxBuffer[0];
-
-#if defined(_DEBUG)
- for (int i = 0; i < numConstraints; i++)
- cs[i].getBatchIdx() = -1;
-#endif
- for (int i = 0; i < numConstraints; i++)
- idxSrc[i] = i;
-
- int numValidConstraints = 0;
- // int unprocessedConstraintIndex = 0;
-
- int batchIdx = 0;
-
- {
- B3_PROFILE("cpu batch innerloop");
-
- while (numValidConstraints < numConstraints)
- {
- numIter++;
- int nCurrentBatch = 0;
- // clear flag
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed2[i] = 0;
- curBodyUsed = 0;
-
- for (int i = numValidConstraints; i < numConstraints; i++)
- {
- int idx = idxSrc[i];
- b3Assert(idx < numConstraints);
- // check if it can go
- int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
- int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
- int bodyA = abs(bodyAS);
- int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
- bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
- int aUnavailable = 0;
- int bUnavailable = 0;
- if (!aIsStatic)
- {
- for (int j = 0; j < curBodyUsed; j++)
- {
- if (bodyA == bodyUsed2[j])
- {
- aUnavailable = 1;
- break;
- }
- }
- }
- if (!aUnavailable)
- if (!bIsStatic)
- {
- for (int j = 0; j < curBodyUsed; j++)
- {
- if (bodyB == bodyUsed2[j])
- {
- bUnavailable = 1;
- break;
- }
- }
- }
-
- if (aUnavailable == 0 && bUnavailable == 0) // ok
- {
- if (!aIsStatic)
- {
- bodyUsed2[curBodyUsed++] = bodyA;
- }
- if (!bIsStatic)
- {
- bodyUsed2[curBodyUsed++] = bodyB;
- }
-
- cs[idx].getBatchIdx() = batchIdx;
- m_data->m_sortData[idx].m_key = batchIdx;
- m_data->m_sortData[idx].m_value = idx;
-
- if (i != numValidConstraints)
- {
- b3Swap(idxSrc[i], idxSrc[numValidConstraints]);
- }
-
- numValidConstraints++;
- {
- nCurrentBatch++;
- if (nCurrentBatch == simdWidth)
- {
- nCurrentBatch = 0;
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed2[i] = 0;
-
- curBodyUsed = 0;
- }
- }
- }
- }
-
- batchIdx++;
- }
- }
- {
- B3_PROFILE("quickSort");
- //m_data->m_sortData.quickSort(sortfnc);
- }
-
- {
- B3_PROFILE("reorder");
- // reorder
-
- memcpy(&m_data->m_old[0], cs, sizeof(b3Contact4) * numConstraints);
-
- for (int i = 0; i < numConstraints; i++)
- {
- b3Assert(m_data->m_sortData[idxSrc[i]].m_value == idxSrc[i]);
- int idx = m_data->m_sortData[idxSrc[i]].m_value;
- cs[i] = m_data->m_old[idx];
- }
- }
-
-#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for (int i = 0; i < numConstraints; i++)
- {
- b3Assert(cs[i].getBatchIdx() != -1);
- }
-#endif
-
- return batchIdx;
-}
-
-b3AlignedObjectArray<int> bodyUsed;
-b3AlignedObjectArray<int> curUsed;
-
-inline int b3GpuPgsContactSolver::sortConstraintByBatch3(b3Contact4* cs, int numConstraints, int simdWidth, int staticIdx, int numBodies, int* batchSizes)
-{
- B3_PROFILE("sortConstraintByBatch3");
-
- static int maxSwaps = 0;
- int numSwaps = 0;
-
- curUsed.resize(2 * simdWidth);
-
- static int maxNumConstraints = 0;
- if (maxNumConstraints < numConstraints)
- {
- maxNumConstraints = numConstraints;
- //printf("maxNumConstraints = %d\n",maxNumConstraints );
- }
-
- int numUsedArray = numBodies / 32 + 1;
- bodyUsed.resize(numUsedArray);
-
- for (int q = 0; q < numUsedArray; q++)
- bodyUsed[q] = 0;
-
- int curBodyUsed = 0;
-
- int numIter = 0;
-
- m_data->m_sortData.resize(0);
- m_data->m_idxBuffer.resize(0);
- m_data->m_old.resize(0);
-
-#if defined(_DEBUG)
- for (int i = 0; i < numConstraints; i++)
- cs[i].getBatchIdx() = -1;
-#endif
-
- int numValidConstraints = 0;
- // int unprocessedConstraintIndex = 0;
-
- int batchIdx = 0;
-
- {
- B3_PROFILE("cpu batch innerloop");
-
- while (numValidConstraints < numConstraints)
- {
- numIter++;
- int nCurrentBatch = 0;
- batchSizes[batchIdx] = 0;
-
- // clear flag
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed[curUsed[i] / 32] = 0;
-
- curBodyUsed = 0;
-
- for (int i = numValidConstraints; i < numConstraints; i++)
- {
- int idx = i;
- b3Assert(idx < numConstraints);
- // check if it can go
- int bodyAS = cs[idx].m_bodyAPtrAndSignBit;
- int bodyBS = cs[idx].m_bodyBPtrAndSignBit;
- int bodyA = abs(bodyAS);
- int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS < 0) || bodyAS == staticIdx;
- bool bIsStatic = (bodyBS < 0) || bodyBS == staticIdx;
- int aUnavailable = 0;
- int bUnavailable = 0;
- if (!aIsStatic)
- {
- aUnavailable = bodyUsed[bodyA / 32] & (1 << (bodyA & 31));
- }
- if (!aUnavailable)
- if (!bIsStatic)
- {
- bUnavailable = bodyUsed[bodyB / 32] & (1 << (bodyB & 31));
- }
-
- if (aUnavailable == 0 && bUnavailable == 0) // ok
- {
- if (!aIsStatic)
- {
- bodyUsed[bodyA / 32] |= (1 << (bodyA & 31));
- curUsed[curBodyUsed++] = bodyA;
- }
- if (!bIsStatic)
- {
- bodyUsed[bodyB / 32] |= (1 << (bodyB & 31));
- curUsed[curBodyUsed++] = bodyB;
- }
-
- cs[idx].getBatchIdx() = batchIdx;
-
- if (i != numValidConstraints)
- {
- b3Swap(cs[i], cs[numValidConstraints]);
- numSwaps++;
- }
-
- numValidConstraints++;
- {
- nCurrentBatch++;
- if (nCurrentBatch == simdWidth)
- {
- batchSizes[batchIdx] += simdWidth;
- nCurrentBatch = 0;
- for (int i = 0; i < curBodyUsed; i++)
- bodyUsed[curUsed[i] / 32] = 0;
- curBodyUsed = 0;
- }
- }
- }
- }
-
- if (batchIdx >= B3_MAX_NUM_BATCHES)
- {
- b3Error("batchIdx>=B3_MAX_NUM_BATCHES");
- b3Assert(0);
- break;
- }
-
- batchSizes[batchIdx] += nCurrentBatch;
-
- batchIdx++;
- }
- }
-
-#if defined(_DEBUG)
- // debugPrintf( "nBatches: %d\n", batchIdx );
- for (int i = 0; i < numConstraints; i++)
- {
- b3Assert(cs[i].getBatchIdx() != -1);
- }
-#endif
-
- batchSizes[batchIdx] = 0;
-
- if (maxSwaps < numSwaps)
- {
- maxSwaps = numSwaps;
- //printf("maxSwaps = %d\n", maxSwaps);
- }
-
- return batchIdx;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
deleted file mode 100644
index 6ab7502af3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuPgsContactSolver.h
+++ /dev/null
@@ -1,37 +0,0 @@
-
-#ifndef B3_GPU_BATCHING_PGS_SOLVER_H
-#define B3_GPU_BATCHING_PGS_SOLVER_H
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "b3GpuConstraint4.h"
-
-class b3GpuPgsContactSolver
-{
-protected:
- int m_debugOutput;
-
- struct b3GpuBatchingPgsSolverInternalData* m_data;
-
- void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
-
- inline int sortConstraintByBatch(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
- inline int sortConstraintByBatch2(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies);
- inline int sortConstraintByBatch3(b3Contact4* cs, int n, int simdWidth, int staticIdx, int numBodies, int* batchSizes);
-
- void solveContactConstraintBatchSizes(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes); //const b3OpenCLArray<int>* gpuBatchSizes);
-
- void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, int numIterations, const b3AlignedObjectArray<int>* batchSizes); //const b3OpenCLArray<int>* gpuBatchSizes);
-
-public:
- b3GpuPgsContactSolver(cl_context ctx, cl_device_id device, cl_command_queue q, int pairCapacity);
- virtual ~b3GpuPgsContactSolver();
-
- void solveContacts(int numBodies, cl_mem bodyBuf, cl_mem inertiaBuf, int numContacts, cl_mem contactBuf, const struct b3Config& config, int static0Index);
-};
-
-#endif //B3_GPU_BATCHING_PGS_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
deleted file mode 100644
index fef33ad1cd..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.cpp
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "b3GpuRigidBodyPipeline.h"
-#include "b3GpuRigidBodyPipelineInternalData.h"
-#include "kernels/integrateKernel.h"
-#include "kernels/updateAabbsKernel.h"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-#include "b3GpuNarrowPhase.h"
-#include "Bullet3Geometry/b3AabbUtil.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
-#include "Bullet3OpenCL/BroadphaseCollision/b3GpuBroadphaseInterface.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3Dynamics/ConstraintSolver/b3PgsJacobiSolver.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
-#include "Bullet3Collision/BroadPhaseCollision/b3DynamicBvhBroadphase.h"
-
-//#define TEST_OTHER_GPU_SOLVER
-
-#define B3_RIGIDBODY_INTEGRATE_PATH "src/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl"
-#define B3_RIGIDBODY_UPDATEAABB_PATH "src/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl"
-
-bool useBullet2CpuSolver = true;
-
-//choice of contact solver
-bool gUseJacobi = false;
-bool gUseDbvt = false;
-bool gDumpContactStats = false;
-bool gCalcWorldSpaceAabbOnCpu = false;
-bool gUseCalculateOverlappingPairsHost = false;
-bool gIntegrateOnCpu = false;
-bool gClearPairsOnGpu = true;
-
-#define TEST_OTHER_GPU_SOLVER 1
-#ifdef TEST_OTHER_GPU_SOLVER
-#include "b3GpuJacobiContactSolver.h"
-#endif //TEST_OTHER_GPU_SOLVER
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-#include "Bullet3OpenCL/RigidBody/b3GpuPgsConstraintSolver.h"
-
-#include "b3GpuPgsContactSolver.h"
-#include "b3Solver.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-#include "Bullet3OpenCL/Raycast/b3GpuRaycast.h"
-
-#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
-#include "Bullet3OpenCL/RigidBody/b3GpuNarrowPhaseInternalData.h"
-
-b3GpuRigidBodyPipeline::b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config)
-{
- m_data = new b3GpuRigidBodyPipelineInternalData;
- m_data->m_constraintUid = 0;
- m_data->m_config = config;
- m_data->m_context = ctx;
- m_data->m_device = device;
- m_data->m_queue = q;
-
- m_data->m_solver = new b3PgsJacobiSolver(true); //new b3PgsJacobiSolver(true);
- m_data->m_gpuSolver = new b3GpuPgsConstraintSolver(ctx, device, q, true); //new b3PgsJacobiSolver(true);
-
- m_data->m_allAabbsGPU = new b3OpenCLArray<b3SapAabb>(ctx, q, config.m_maxConvexBodies);
- m_data->m_overlappingPairsGPU = new b3OpenCLArray<b3BroadphasePair>(ctx, q, config.m_maxBroadphasePairs);
-
- m_data->m_gpuConstraints = new b3OpenCLArray<b3GpuGenericConstraint>(ctx, q);
-#ifdef TEST_OTHER_GPU_SOLVER
- m_data->m_solver3 = new b3GpuJacobiContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
-#endif // TEST_OTHER_GPU_SOLVER
-
- m_data->m_solver2 = new b3GpuPgsContactSolver(ctx, device, q, config.m_maxBroadphasePairs);
-
- m_data->m_raycaster = new b3GpuRaycast(ctx, device, q);
-
- m_data->m_broadphaseDbvt = broadphaseDbvt;
- m_data->m_broadphaseSap = broadphaseSap;
- m_data->m_narrowphase = narrowphase;
- m_data->m_gravity.setValue(0.f, -9.8f, 0.f);
-
- cl_int errNum = 0;
-
- {
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, integrateKernelCL, &errNum, "", B3_RIGIDBODY_INTEGRATE_PATH);
- b3Assert(errNum == CL_SUCCESS);
- m_data->m_integrateTransformsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, integrateKernelCL, "integrateTransformsKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
- clReleaseProgram(prog);
- }
- {
- cl_program prog = b3OpenCLUtils::compileCLProgramFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, &errNum, "", B3_RIGIDBODY_UPDATEAABB_PATH);
- b3Assert(errNum == CL_SUCCESS);
- m_data->m_updateAabbsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "initializeGpuAabbsFull", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
-
- m_data->m_clearOverlappingPairsKernel = b3OpenCLUtils::compileCLKernelFromString(m_data->m_context, m_data->m_device, updateAabbsKernelCL, "clearOverlappingPairsKernel", &errNum, prog);
- b3Assert(errNum == CL_SUCCESS);
-
- clReleaseProgram(prog);
- }
-}
-
-b3GpuRigidBodyPipeline::~b3GpuRigidBodyPipeline()
-{
- if (m_data->m_integrateTransformsKernel)
- clReleaseKernel(m_data->m_integrateTransformsKernel);
-
- if (m_data->m_updateAabbsKernel)
- clReleaseKernel(m_data->m_updateAabbsKernel);
-
- if (m_data->m_clearOverlappingPairsKernel)
- clReleaseKernel(m_data->m_clearOverlappingPairsKernel);
- delete m_data->m_raycaster;
- delete m_data->m_solver;
- delete m_data->m_allAabbsGPU;
- delete m_data->m_gpuConstraints;
- delete m_data->m_overlappingPairsGPU;
-
-#ifdef TEST_OTHER_GPU_SOLVER
- delete m_data->m_solver3;
-#endif //TEST_OTHER_GPU_SOLVER
-
- delete m_data->m_solver2;
-
- delete m_data;
-}
-
-void b3GpuRigidBodyPipeline::reset()
-{
- m_data->m_gpuConstraints->resize(0);
- m_data->m_cpuConstraints.resize(0);
- m_data->m_allAabbsGPU->resize(0);
- m_data->m_allAabbsCPU.resize(0);
-}
-
-void b3GpuRigidBodyPipeline::addConstraint(b3TypedConstraint* constraint)
-{
- m_data->m_joints.push_back(constraint);
-}
-
-void b3GpuRigidBodyPipeline::removeConstraint(b3TypedConstraint* constraint)
-{
- m_data->m_joints.remove(constraint);
-}
-
-void b3GpuRigidBodyPipeline::removeConstraintByUid(int uid)
-{
- m_data->m_gpuSolver->recomputeBatches();
- //slow linear search
- m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
- //remove
- for (int i = 0; i < m_data->m_cpuConstraints.size(); i++)
- {
- if (m_data->m_cpuConstraints[i].m_uid == uid)
- {
- //m_data->m_cpuConstraints.remove(m_data->m_cpuConstraints[i]);
- m_data->m_cpuConstraints.swap(i, m_data->m_cpuConstraints.size() - 1);
- m_data->m_cpuConstraints.pop_back();
-
- break;
- }
- }
-
- if (m_data->m_cpuConstraints.size())
- {
- m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
- }
- else
- {
- m_data->m_gpuConstraints->resize(0);
- }
-}
-int b3GpuRigidBodyPipeline::createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold)
-{
- m_data->m_gpuSolver->recomputeBatches();
- b3GpuGenericConstraint c;
- c.m_uid = m_data->m_constraintUid;
- m_data->m_constraintUid++;
- c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
- c.m_rbA = bodyA;
- c.m_rbB = bodyB;
- c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
- c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
- c.m_breakingImpulseThreshold = breakingThreshold;
- c.m_constraintType = B3_GPU_POINT2POINT_CONSTRAINT_TYPE;
- m_data->m_cpuConstraints.push_back(c);
- return c.m_uid;
-}
-int b3GpuRigidBodyPipeline::createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold)
-{
- m_data->m_gpuSolver->recomputeBatches();
- b3GpuGenericConstraint c;
- c.m_uid = m_data->m_constraintUid;
- m_data->m_constraintUid++;
- c.m_flags = B3_CONSTRAINT_FLAG_ENABLED;
- c.m_rbA = bodyA;
- c.m_rbB = bodyB;
- c.m_pivotInA.setValue(pivotInA[0], pivotInA[1], pivotInA[2]);
- c.m_pivotInB.setValue(pivotInB[0], pivotInB[1], pivotInB[2]);
- c.m_relTargetAB.setValue(relTargetAB[0], relTargetAB[1], relTargetAB[2], relTargetAB[3]);
- c.m_breakingImpulseThreshold = breakingThreshold;
- c.m_constraintType = B3_GPU_FIXED_CONSTRAINT_TYPE;
-
- m_data->m_cpuConstraints.push_back(c);
- return c.m_uid;
-}
-
-void b3GpuRigidBodyPipeline::stepSimulation(float deltaTime)
-{
- //update worldspace AABBs from local AABB/worldtransform
- {
- B3_PROFILE("setupGpuAabbs");
- setupGpuAabbsFull();
- }
-
- int numPairs = 0;
-
- //compute overlapping pairs
- {
- if (gUseDbvt)
- {
- {
- B3_PROFILE("setAabb");
- m_data->m_allAabbsGPU->copyToHost(m_data->m_allAabbsCPU);
- for (int i = 0; i < m_data->m_allAabbsCPU.size(); i++)
- {
- b3Vector3 aabbMin = b3MakeVector3(m_data->m_allAabbsCPU[i].m_min[0], m_data->m_allAabbsCPU[i].m_min[1], m_data->m_allAabbsCPU[i].m_min[2]);
- b3Vector3 aabbMax = b3MakeVector3(m_data->m_allAabbsCPU[i].m_max[0], m_data->m_allAabbsCPU[i].m_max[1], m_data->m_allAabbsCPU[i].m_max[2]);
- m_data->m_broadphaseDbvt->setAabb(i, aabbMin, aabbMax, 0);
- }
- }
-
- {
- B3_PROFILE("calculateOverlappingPairs");
- m_data->m_broadphaseDbvt->calculateOverlappingPairs();
- }
- numPairs = m_data->m_broadphaseDbvt->getOverlappingPairCache()->getNumOverlappingPairs();
- }
- else
- {
- if (gUseCalculateOverlappingPairsHost)
- {
- m_data->m_broadphaseSap->calculateOverlappingPairsHost(m_data->m_config.m_maxBroadphasePairs);
- }
- else
- {
- m_data->m_broadphaseSap->calculateOverlappingPairs(m_data->m_config.m_maxBroadphasePairs);
- }
- numPairs = m_data->m_broadphaseSap->getNumOverlap();
- }
- }
-
- //compute contact points
- // printf("numPairs=%d\n",numPairs);
-
- int numContacts = 0;
-
- int numBodies = m_data->m_narrowphase->getNumRigidBodies();
-
- if (numPairs)
- {
- cl_mem pairs = 0;
- cl_mem aabbsWS = 0;
- if (gUseDbvt)
- {
- B3_PROFILE("m_overlappingPairsGPU->copyFromHost");
- m_data->m_overlappingPairsGPU->copyFromHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
- pairs = m_data->m_overlappingPairsGPU->getBufferCL();
- aabbsWS = m_data->m_allAabbsGPU->getBufferCL();
- }
- else
- {
- pairs = m_data->m_broadphaseSap->getOverlappingPairBuffer();
- aabbsWS = m_data->m_broadphaseSap->getAabbBufferWS();
- }
-
- m_data->m_overlappingPairsGPU->resize(numPairs);
-
- //mark the contacts for each pair as 'unused'
- if (numPairs)
- {
- b3OpenCLArray<b3BroadphasePair> gpuPairs(this->m_data->m_context, m_data->m_queue);
- gpuPairs.setFromOpenCLBuffer(pairs, numPairs);
-
- if (gClearPairsOnGpu)
- {
- //b3AlignedObjectArray<b3BroadphasePair> hostPairs;//just for debugging
- //gpuPairs.copyToHost(hostPairs);
-
- b3LauncherCL launcher(m_data->m_queue, m_data->m_clearOverlappingPairsKernel, "clearOverlappingPairsKernel");
- launcher.setBuffer(pairs);
- launcher.setConst(numPairs);
- launcher.launch1D(numPairs);
-
- //gpuPairs.copyToHost(hostPairs);
- }
- else
- {
- b3AlignedObjectArray<b3BroadphasePair> hostPairs;
- gpuPairs.copyToHost(hostPairs);
-
- for (int i = 0; i < hostPairs.size(); i++)
- {
- hostPairs[i].z = 0xffffffff;
- }
-
- gpuPairs.copyFromHost(hostPairs);
- }
- }
-
- m_data->m_narrowphase->computeContacts(pairs, numPairs, aabbsWS, numBodies);
- numContacts = m_data->m_narrowphase->getNumContactsGpu();
-
- if (gUseDbvt)
- {
- ///store the cached information (contact locations in the 'z' component)
- B3_PROFILE("m_overlappingPairsGPU->copyToHost");
- m_data->m_overlappingPairsGPU->copyToHost(m_data->m_broadphaseDbvt->getOverlappingPairCache()->getOverlappingPairArray());
- }
- if (gDumpContactStats && numContacts)
- {
- m_data->m_narrowphase->getContactsGpu();
-
- printf("numContacts = %d\n", numContacts);
-
- int totalPoints = 0;
- const b3Contact4* contacts = m_data->m_narrowphase->getContactsCPU();
-
- for (int i = 0; i < numContacts; i++)
- {
- totalPoints += contacts->getNPoints();
- }
- printf("totalPoints=%d\n", totalPoints);
- }
- }
-
- //convert contact points to contact constraints
-
- //solve constraints
-
- b3OpenCLArray<b3RigidBodyData> gpuBodies(m_data->m_context, m_data->m_queue, 0, true);
- gpuBodies.setFromOpenCLBuffer(m_data->m_narrowphase->getBodiesGpu(), m_data->m_narrowphase->getNumRigidBodies());
- b3OpenCLArray<b3InertiaData> gpuInertias(m_data->m_context, m_data->m_queue, 0, true);
- gpuInertias.setFromOpenCLBuffer(m_data->m_narrowphase->getBodyInertiasGpu(), m_data->m_narrowphase->getNumRigidBodies());
- b3OpenCLArray<b3Contact4> gpuContacts(m_data->m_context, m_data->m_queue, 0, true);
- gpuContacts.setFromOpenCLBuffer(m_data->m_narrowphase->getContactsGpu(), m_data->m_narrowphase->getNumContactsGpu());
-
- int numJoints = m_data->m_joints.size() ? m_data->m_joints.size() : m_data->m_cpuConstraints.size();
- if (useBullet2CpuSolver && numJoints)
- {
- // b3AlignedObjectArray<b3Contact4> hostContacts;
- //gpuContacts.copyToHost(hostContacts);
- {
- bool useGpu = m_data->m_joints.size() == 0;
-
- // b3Contact4* contacts = numContacts? &hostContacts[0]: 0;
- //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,contacts,numJoints, joints);
- if (useGpu)
- {
- m_data->m_gpuSolver->solveJoints(m_data->m_narrowphase->getNumRigidBodies(), &gpuBodies, &gpuInertias, numJoints, m_data->m_gpuConstraints);
- }
- else
- {
- b3AlignedObjectArray<b3RigidBodyData> hostBodies;
- gpuBodies.copyToHost(hostBodies);
- b3AlignedObjectArray<b3InertiaData> hostInertias;
- gpuInertias.copyToHost(hostInertias);
-
- b3TypedConstraint** joints = numJoints ? &m_data->m_joints[0] : 0;
- m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumRigidBodies(), &hostBodies[0], &hostInertias[0], 0, 0, numJoints, joints);
- gpuBodies.copyFromHost(hostBodies);
- }
- }
- }
-
- if (numContacts)
- {
-#ifdef TEST_OTHER_GPU_SOLVER
-
- if (gUseJacobi)
- {
- bool useGpu = true;
- if (useGpu)
- {
- bool forceHost = false;
- if (forceHost)
- {
- b3AlignedObjectArray<b3RigidBodyData> hostBodies;
- b3AlignedObjectArray<b3InertiaData> hostInertias;
- b3AlignedObjectArray<b3Contact4> hostContacts;
-
- {
- B3_PROFILE("copyToHost");
- gpuBodies.copyToHost(hostBodies);
- gpuInertias.copyToHost(hostInertias);
- gpuContacts.copyToHost(hostContacts);
- }
-
- {
- b3JacobiSolverInfo solverInfo;
- m_data->m_solver3->solveGroupHost(&hostBodies[0], &hostInertias[0], hostBodies.size(), &hostContacts[0], hostContacts.size(), solverInfo);
- }
- {
- B3_PROFILE("copyFromHost");
- gpuBodies.copyFromHost(hostBodies);
- }
- }
- else
-
- {
- int static0Index = m_data->m_narrowphase->getStatic0Index();
- b3JacobiSolverInfo solverInfo;
- //m_data->m_solver3->solveContacts( >solveGroup(&gpuBodies, &gpuInertias, &gpuContacts,solverInfo);
- //m_data->m_solver3->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
- m_data->m_solver3->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
- }
- }
- else
- {
- b3AlignedObjectArray<b3RigidBodyData> hostBodies;
- gpuBodies.copyToHost(hostBodies);
- b3AlignedObjectArray<b3InertiaData> hostInertias;
- gpuInertias.copyToHost(hostInertias);
- b3AlignedObjectArray<b3Contact4> hostContacts;
- gpuContacts.copyToHost(hostContacts);
- {
- //m_data->m_solver->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(),&hostBodies[0],&hostInertias[0],numContacts,&hostContacts[0]);
- }
- gpuBodies.copyFromHost(hostBodies);
- }
- }
- else
-#endif //TEST_OTHER_GPU_SOLVER
- {
- int static0Index = m_data->m_narrowphase->getStatic0Index();
- m_data->m_solver2->solveContacts(numBodies, gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL(), m_data->m_config, static0Index);
-
- //m_data->m_solver4->solveContacts(m_data->m_narrowphase->getNumBodiesGpu(), gpuBodies.getBufferCL(), gpuInertias.getBufferCL(), numContacts, gpuContacts.getBufferCL());
-
- /*m_data->m_solver3->solveContactConstraintHost(
- (b3OpenCLArray<RigidBodyBase::Body>*)&gpuBodies,
- (b3OpenCLArray<RigidBodyBase::Inertia>*)&gpuInertias,
- (b3OpenCLArray<Constraint4>*) &gpuContacts,
- 0,numContacts,256);
- */
- }
- }
-
- integrate(deltaTime);
-}
-
-void b3GpuRigidBodyPipeline::integrate(float timeStep)
-{
- //integrate
- int numBodies = m_data->m_narrowphase->getNumRigidBodies();
- float angularDamp = 0.99f;
-
- if (gIntegrateOnCpu)
- {
- if (numBodies)
- {
- b3GpuNarrowPhaseInternalData* npData = m_data->m_narrowphase->getInternalData();
- npData->m_bodyBufferGPU->copyToHost(*npData->m_bodyBufferCPU);
-
- b3RigidBodyData_t* bodies = &npData->m_bodyBufferCPU->at(0);
-
- for (int nodeID = 0; nodeID < numBodies; nodeID++)
- {
- integrateSingleTransform(bodies, nodeID, timeStep, angularDamp, m_data->m_gravity);
- }
- npData->m_bodyBufferGPU->copyFromHost(*npData->m_bodyBufferCPU);
- }
- }
- else
- {
- b3LauncherCL launcher(m_data->m_queue, m_data->m_integrateTransformsKernel, "m_integrateTransformsKernel");
- launcher.setBuffer(m_data->m_narrowphase->getBodiesGpu());
-
- launcher.setConst(numBodies);
- launcher.setConst(timeStep);
- launcher.setConst(angularDamp);
- launcher.setConst(m_data->m_gravity);
- launcher.launch1D(numBodies);
- }
-}
-
-void b3GpuRigidBodyPipeline::setupGpuAabbsFull()
-{
- cl_int ciErrNum = 0;
-
- int numBodies = m_data->m_narrowphase->getNumRigidBodies();
- if (!numBodies)
- return;
-
- if (gCalcWorldSpaceAabbOnCpu)
- {
- if (numBodies)
- {
- if (gUseDbvt)
- {
- m_data->m_allAabbsCPU.resize(numBodies);
- m_data->m_narrowphase->readbackAllBodiesToCpu();
- for (int i = 0; i < numBodies; i++)
- {
- b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_allAabbsCPU[0]);
- }
- m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
- }
- else
- {
- m_data->m_broadphaseSap->getAllAabbsCPU().resize(numBodies);
- m_data->m_narrowphase->readbackAllBodiesToCpu();
- for (int i = 0; i < numBodies; i++)
- {
- b3ComputeWorldAabb(i, m_data->m_narrowphase->getBodiesCpu(), m_data->m_narrowphase->getCollidablesCpu(), m_data->m_narrowphase->getLocalSpaceAabbsCpu(), &m_data->m_broadphaseSap->getAllAabbsCPU()[0]);
- }
- m_data->m_broadphaseSap->getAllAabbsGPU().copyFromHost(m_data->m_broadphaseSap->getAllAabbsCPU());
- //m_data->m_broadphaseSap->writeAabbsToGpu();
- }
- }
- }
- else
- {
- //__kernel void initializeGpuAabbsFull( const int numNodes, __global Body* gBodies,__global Collidable* collidables, __global b3AABBCL* plocalShapeAABB, __global b3AABBCL* pAABB)
- b3LauncherCL launcher(m_data->m_queue, m_data->m_updateAabbsKernel, "m_updateAabbsKernel");
- launcher.setConst(numBodies);
- cl_mem bodies = m_data->m_narrowphase->getBodiesGpu();
- launcher.setBuffer(bodies);
- cl_mem collidables = m_data->m_narrowphase->getCollidablesGpu();
- launcher.setBuffer(collidables);
- cl_mem localAabbs = m_data->m_narrowphase->getAabbLocalSpaceBufferGpu();
- launcher.setBuffer(localAabbs);
-
- cl_mem worldAabbs = 0;
- if (gUseDbvt)
- {
- worldAabbs = m_data->m_allAabbsGPU->getBufferCL();
- }
- else
- {
- worldAabbs = m_data->m_broadphaseSap->getAabbBufferWS();
- }
- launcher.setBuffer(worldAabbs);
- launcher.launch1D(numBodies);
-
- oclCHECKERROR(ciErrNum, CL_SUCCESS);
- }
-
- /*
- b3AlignedObjectArray<b3SapAabb> aabbs;
- m_data->m_broadphaseSap->m_allAabbsGPU.copyToHost(aabbs);
-
- printf("numAabbs = %d\n", aabbs.size());
-
- for (int i=0;i<aabbs.size();i++)
- {
- printf("aabb[%d].m_min=%f,%f,%f,%d\n",i,aabbs[i].m_minVec[0],aabbs[i].m_minVec[1],aabbs[i].m_minVec[2],aabbs[i].m_minIndices[3]);
- printf("aabb[%d].m_max=%f,%f,%f,%d\n",i,aabbs[i].m_maxVec[0],aabbs[i].m_maxVec[1],aabbs[i].m_maxVec[2],aabbs[i].m_signedMaxIndices[3]);
-
- };
- */
-}
-
-cl_mem b3GpuRigidBodyPipeline::getBodyBuffer()
-{
- return m_data->m_narrowphase->getBodiesGpu();
-}
-
-int b3GpuRigidBodyPipeline::getNumBodies() const
-{
- return m_data->m_narrowphase->getNumRigidBodies();
-}
-
-void b3GpuRigidBodyPipeline::setGravity(const float* grav)
-{
- m_data->m_gravity.setValue(grav[0], grav[1], grav[2]);
-}
-
-void b3GpuRigidBodyPipeline::copyConstraintsToHost()
-{
- m_data->m_gpuConstraints->copyToHost(m_data->m_cpuConstraints);
-}
-
-void b3GpuRigidBodyPipeline::writeAllInstancesToGpu()
-{
- m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
- m_data->m_gpuConstraints->copyFromHost(m_data->m_cpuConstraints);
-}
-
-int b3GpuRigidBodyPipeline::registerPhysicsInstance(float mass, const float* position, const float* orientation, int collidableIndex, int userIndex, bool writeInstanceToGpu)
-{
- b3Vector3 aabbMin = b3MakeVector3(0, 0, 0), aabbMax = b3MakeVector3(0, 0, 0);
-
- if (collidableIndex >= 0)
- {
- b3SapAabb localAabb = m_data->m_narrowphase->getLocalSpaceAabb(collidableIndex);
- b3Vector3 localAabbMin = b3MakeVector3(localAabb.m_min[0], localAabb.m_min[1], localAabb.m_min[2]);
- b3Vector3 localAabbMax = b3MakeVector3(localAabb.m_max[0], localAabb.m_max[1], localAabb.m_max[2]);
-
- b3Scalar margin = 0.01f;
- b3Transform t;
- t.setIdentity();
- t.setOrigin(b3MakeVector3(position[0], position[1], position[2]));
- t.setRotation(b3Quaternion(orientation[0], orientation[1], orientation[2], orientation[3]));
- b3TransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
- }
- else
- {
- b3Error("registerPhysicsInstance using invalid collidableIndex\n");
- return -1;
- }
-
- bool writeToGpu = false;
- int bodyIndex = m_data->m_narrowphase->getNumRigidBodies();
- bodyIndex = m_data->m_narrowphase->registerRigidBody(collidableIndex, mass, position, orientation, &aabbMin.getX(), &aabbMax.getX(), writeToGpu);
-
- if (bodyIndex >= 0)
- {
- if (gUseDbvt)
- {
- m_data->m_broadphaseDbvt->createProxy(aabbMin, aabbMax, bodyIndex, 0, 1, 1);
- b3SapAabb aabb;
- for (int i = 0; i < 3; i++)
- {
- aabb.m_min[i] = aabbMin[i];
- aabb.m_max[i] = aabbMax[i];
- aabb.m_minIndices[3] = bodyIndex;
- }
- m_data->m_allAabbsCPU.push_back(aabb);
- if (writeInstanceToGpu)
- {
- m_data->m_allAabbsGPU->copyFromHost(m_data->m_allAabbsCPU);
- }
- }
- else
- {
- if (mass)
- {
- m_data->m_broadphaseSap->createProxy(aabbMin, aabbMax, bodyIndex, 1, 1); //m_dispatcher);
- }
- else
- {
- m_data->m_broadphaseSap->createLargeProxy(aabbMin, aabbMax, bodyIndex, 1, 1); //m_dispatcher);
- }
- }
- }
-
- /*
- if (mass>0.f)
- m_numDynamicPhysicsInstances++;
-
- m_numPhysicsInstances++;
- */
-
- return bodyIndex;
-}
-
-void b3GpuRigidBodyPipeline::castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults)
-{
- this->m_data->m_raycaster->castRays(rays, hitResults,
- getNumBodies(), this->m_data->m_narrowphase->getBodiesCpu(),
- m_data->m_narrowphase->getNumCollidablesGpu(), m_data->m_narrowphase->getCollidablesCpu(),
- m_data->m_narrowphase->getInternalData(), m_data->m_broadphaseSap);
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
deleted file mode 100644
index 0e5c6fec12..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipeline.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_GPU_RIGIDBODY_PIPELINE_H
-#define B3_GPU_RIGIDBODY_PIPELINE_H
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3RaycastInfo.h"
-
-class b3GpuRigidBodyPipeline
-{
-protected:
- struct b3GpuRigidBodyPipelineInternalData* m_data;
-
- int allocateCollidable();
-
-public:
- b3GpuRigidBodyPipeline(cl_context ctx, cl_device_id device, cl_command_queue q, class b3GpuNarrowPhase* narrowphase, class b3GpuBroadphaseInterface* broadphaseSap, struct b3DynamicBvhBroadphase* broadphaseDbvt, const b3Config& config);
- virtual ~b3GpuRigidBodyPipeline();
-
- void stepSimulation(float deltaTime);
- void integrate(float timeStep);
- void setupGpuAabbsFull();
-
- int registerConvexPolyhedron(class b3ConvexUtility* convex);
-
- //int registerConvexPolyhedron(const float* vertices, int strideInBytes, int numVertices, const float* scaling);
- //int registerSphereShape(float radius);
- //int registerPlaneShape(const b3Vector3& planeNormal, float planeConstant);
-
- //int registerConcaveMesh(b3AlignedObjectArray<b3Vector3>* vertices, b3AlignedObjectArray<int>* indices, const float* scaling);
- //int registerCompoundShape(b3AlignedObjectArray<b3GpuChildShape>* childShapes);
-
- int registerPhysicsInstance(float mass, const float* position, const float* orientation, int collisionShapeIndex, int userData, bool writeInstanceToGpu);
- //if you passed "writeInstanceToGpu" false in the registerPhysicsInstance method (for performance) you need to call writeAllInstancesToGpu after all instances are registered
- void writeAllInstancesToGpu();
- void copyConstraintsToHost();
- void setGravity(const float* grav);
- void reset();
-
- int createPoint2PointConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, float breakingThreshold);
- int createFixedConstraint(int bodyA, int bodyB, const float* pivotInA, const float* pivotInB, const float* relTargetAB, float breakingThreshold);
- void removeConstraintByUid(int uid);
-
- void addConstraint(class b3TypedConstraint* constraint);
- void removeConstraint(b3TypedConstraint* constraint);
-
- void castRays(const b3AlignedObjectArray<b3RayInfo>& rays, b3AlignedObjectArray<b3RayHit>& hitResults);
-
- cl_mem getBodyBuffer();
-
- int getNumBodies() const;
-};
-
-#endif //B3_GPU_RIGIDBODY_PIPELINE_H \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
deleted file mode 100644
index e0a26fda17..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuRigidBodyPipelineInternalData.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
-#define B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLInclude.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Collidable.h"
-
-#include "Bullet3OpenCL/BroadphaseCollision/b3SapAabb.h"
-#include "Bullet3Dynamics/ConstraintSolver/b3TypedConstraint.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Config.h"
-
-#include "Bullet3Collision/BroadPhaseCollision/b3OverlappingPair.h"
-#include "Bullet3OpenCL/RigidBody/b3GpuGenericConstraint.h"
-
-struct b3GpuRigidBodyPipelineInternalData
-{
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- cl_kernel m_integrateTransformsKernel;
- cl_kernel m_updateAabbsKernel;
- cl_kernel m_clearOverlappingPairsKernel;
-
- class b3PgsJacobiSolver* m_solver;
-
- class b3GpuPgsConstraintSolver* m_gpuSolver;
-
- class b3GpuPgsContactSolver* m_solver2;
- class b3GpuJacobiContactSolver* m_solver3;
- class b3GpuRaycast* m_raycaster;
-
- class b3GpuBroadphaseInterface* m_broadphaseSap;
-
- struct b3DynamicBvhBroadphase* m_broadphaseDbvt;
- b3OpenCLArray<b3SapAabb>* m_allAabbsGPU;
- b3AlignedObjectArray<b3SapAabb> m_allAabbsCPU;
- b3OpenCLArray<b3BroadphasePair>* m_overlappingPairsGPU;
-
- b3OpenCLArray<b3GpuGenericConstraint>* m_gpuConstraints;
- b3AlignedObjectArray<b3GpuGenericConstraint> m_cpuConstraints;
-
- b3AlignedObjectArray<b3TypedConstraint*> m_joints;
- int m_constraintUid;
- class b3GpuNarrowPhase* m_narrowphase;
- b3Vector3 m_gravity;
-
- b3Config m_config;
-};
-
-#endif //B3_GPU_RIGIDBODY_PIPELINE_INTERNAL_DATA_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
deleted file mode 100644
index db815d9b31..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverBody.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#ifndef B3_GPU_SOLVER_BODY_H
-#define B3_GPU_SOLVER_BODY_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Matrix3x3.h"
-
-#include "Bullet3Common/b3AlignedAllocator.h"
-#include "Bullet3Common/b3TransformUtil.h"
-
-///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
-#ifdef B3_USE_SSE
-#define USE_SIMD 1
-#endif //
-
-///The b3SolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3GpuSolverBody
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
- // b3Transform m_worldTransformUnused;
- b3Vector3 m_deltaLinearVelocity;
- b3Vector3 m_deltaAngularVelocity;
- b3Vector3 m_angularFactor;
- b3Vector3 m_linearFactor;
- b3Vector3 m_invMass;
- b3Vector3 m_pushVelocity;
- b3Vector3 m_turnVelocity;
- b3Vector3 m_linearVelocity;
- b3Vector3 m_angularVelocity;
-
- union {
- void* m_originalBody;
- int m_originalBodyIndex;
- };
-
- int padding[3];
-
- /*
- void setWorldTransform(const b3Transform& worldTransform)
- {
- m_worldTransform = worldTransform;
- }
-
- const b3Transform& getWorldTransform() const
- {
- return m_worldTransform;
- }
- */
- B3_FORCE_INLINE void getVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
- {
- if (m_originalBody)
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- else
- velocity.setValue(0, 0, 0);
- }
-
- B3_FORCE_INLINE void getAngularVelocity(b3Vector3 & angVel) const
- {
- if (m_originalBody)
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- else
- angVel.setValue(0, 0, 0);
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void applyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- B3_FORCE_INLINE void internalApplyPushImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, b3Scalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- const b3Vector3& getDeltaLinearVelocity() const
- {
- return m_deltaLinearVelocity;
- }
-
- const b3Vector3& getDeltaAngularVelocity() const
- {
- return m_deltaAngularVelocity;
- }
-
- const b3Vector3& getPushVelocity() const
- {
- return m_pushVelocity;
- }
-
- const b3Vector3& getTurnVelocity() const
- {
- return m_turnVelocity;
- }
-
- ////////////////////////////////////////////////
- ///some internal methods, don't use them
-
- b3Vector3& internalGetDeltaLinearVelocity()
- {
- return m_deltaLinearVelocity;
- }
-
- b3Vector3& internalGetDeltaAngularVelocity()
- {
- return m_deltaAngularVelocity;
- }
-
- const b3Vector3& internalGetAngularFactor() const
- {
- return m_angularFactor;
- }
-
- const b3Vector3& internalGetInvMass() const
- {
- return m_invMass;
- }
-
- void internalSetInvMass(const b3Vector3& invMass)
- {
- m_invMass = invMass;
- }
-
- b3Vector3& internalGetPushVelocity()
- {
- return m_pushVelocity;
- }
-
- b3Vector3& internalGetTurnVelocity()
- {
- return m_turnVelocity;
- }
-
- B3_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const b3Vector3& rel_pos, b3Vector3& velocity) const
- {
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- }
-
- B3_FORCE_INLINE void internalGetAngularVelocity(b3Vector3 & angVel) const
- {
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- B3_FORCE_INLINE void internalApplyImpulse(const b3Vector3& linearComponent, const b3Vector3& angularComponent, const b3Scalar impulseMagnitude)
- {
- //if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- void writebackVelocity()
- {
- //if (m_originalBody>=0)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //m_originalBody->setCompanionId(-1);
- }
- }
-
- void writebackVelocityAndTransform(b3Scalar timeStep, b3Scalar splitImpulseTurnErp)
- {
- (void)timeStep;
- if (m_originalBody)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //correct the position/orientation based on push/turn recovery
- b3Transform newTransform;
- if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
- {
- // b3Quaternion orn = m_worldTransform.getRotation();
- // b3TransformUtil::integrateTransform(m_worldTransform,m_pushVelocity,m_turnVelocity*splitImpulseTurnErp,timeStep,newTransform);
- // m_worldTransform = newTransform;
- }
- //m_worldTransform.setRotation(orn);
- //m_originalBody->setCompanionId(-1);
- }
- }
-};
-
-#endif //B3_SOLVER_BODY_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
deleted file mode 100644
index 7d9eea243a..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3GpuSolverConstraint.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://github.com/erwincoumans/bullet3
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_GPU_SOLVER_CONSTRAINT_H
-#define B3_GPU_SOLVER_CONSTRAINT_H
-
-#include "Bullet3Common/b3Vector3.h"
-#include "Bullet3Common/b3Matrix3x3.h"
-//#include "b3JacobianEntry.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-
-//#define NO_FRICTION_TANGENTIALS 1
-
-///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-B3_ATTRIBUTE_ALIGNED16(struct)
-b3GpuSolverConstraint
-{
- B3_DECLARE_ALIGNED_ALLOCATOR();
-
- b3Vector3 m_relpos1CrossNormal;
- b3Vector3 m_contactNormal;
-
- b3Vector3 m_relpos2CrossNormal;
- //b3Vector3 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
-
- b3Vector3 m_angularComponentA;
- b3Vector3 m_angularComponentB;
-
- mutable b3Scalar m_appliedPushImpulse;
- mutable b3Scalar m_appliedImpulse;
- int m_padding1;
- int m_padding2;
- b3Scalar m_friction;
- b3Scalar m_jacDiagABInv;
- b3Scalar m_rhs;
- b3Scalar m_cfm;
-
- b3Scalar m_lowerLimit;
- b3Scalar m_upperLimit;
- b3Scalar m_rhsPenetration;
- union {
- void* m_originalContactPoint;
- int m_originalConstraintIndex;
- b3Scalar m_unusedPadding4;
- };
-
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
- int m_solverBodyIdA;
- int m_solverBodyIdB;
-
- enum b3SolverConstraintType
- {
- B3_SOLVER_CONTACT_1D = 0,
- B3_SOLVER_FRICTION_1D
- };
-};
-
-typedef b3AlignedObjectArray<b3GpuSolverConstraint> b3GpuConstraintArray;
-
-#endif //B3_GPU_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp
deleted file mode 100644
index ccf67da1a8..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.cpp
+++ /dev/null
@@ -1,1128 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#include "b3Solver.h"
-
-///useNewBatchingKernel is a rewritten kernel using just a single thread of the warp, for experiments
-bool useNewBatchingKernel = true;
-bool gConvertConstraintOnCpu = false;
-
-#define B3_SOLVER_SETUP_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl"
-#define B3_SOLVER_SETUP2_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl"
-#define B3_SOLVER_CONTACT_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveContact.cl"
-#define B3_SOLVER_FRICTION_KERNEL_PATH "src/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl"
-#define B3_BATCHING_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl"
-#define B3_BATCHING_NEW_PATH "src/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl"
-
-#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
-
-#include "kernels/solverSetup.h"
-#include "kernels/solverSetup2.h"
-
-#include "kernels/solveContact.h"
-#include "kernels/solveFriction.h"
-
-#include "kernels/batchingKernels.h"
-#include "kernels/batchingKernelsNew.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3LauncherCL.h"
-#include "Bullet3Common/b3Vector3.h"
-
-struct SolverDebugInfo
-{
- int m_valInt0;
- int m_valInt1;
- int m_valInt2;
- int m_valInt3;
-
- int m_valInt4;
- int m_valInt5;
- int m_valInt6;
- int m_valInt7;
-
- int m_valInt8;
- int m_valInt9;
- int m_valInt10;
- int m_valInt11;
-
- int m_valInt12;
- int m_valInt13;
- int m_valInt14;
- int m_valInt15;
-
- float m_val0;
- float m_val1;
- float m_val2;
- float m_val3;
-};
-
-class SolverDeviceInl
-{
-public:
- struct ParallelSolveData
- {
- b3OpenCLArray<unsigned int>* m_numConstraints;
- b3OpenCLArray<unsigned int>* m_offsets;
- };
-};
-
-b3Solver::b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity)
- : m_context(ctx),
- m_device(device),
- m_queue(queue),
- m_batchSizes(ctx, queue),
- m_nIterations(4)
-{
- m_sort32 = new b3RadixSort32CL(ctx, device, queue);
- m_scan = new b3PrefixScanCL(ctx, device, queue, B3_SOLVER_N_CELLS);
- m_search = new b3BoundSearchCL(ctx, device, queue, B3_SOLVER_N_CELLS);
-
- const int sortSize = B3NEXTMULTIPLEOF(pairCapacity, 512);
-
- m_sortDataBuffer = new b3OpenCLArray<b3SortData>(ctx, queue, sortSize);
- m_contactBuffer2 = new b3OpenCLArray<b3Contact4>(ctx, queue);
-
- m_numConstraints = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
- m_numConstraints->resize(B3_SOLVER_N_CELLS);
-
- m_offsets = new b3OpenCLArray<unsigned int>(ctx, queue, B3_SOLVER_N_CELLS);
- m_offsets->resize(B3_SOLVER_N_CELLS);
- const char* additionalMacros = "";
- // const char* srcFileNameForCaching="";
-
- cl_int pErrNum;
- const char* batchKernelSource = batchingKernelsCL;
- const char* batchKernelNewSource = batchingKernelsNewCL;
-
- const char* solverSetupSource = solverSetupCL;
- const char* solverSetup2Source = solverSetup2CL;
- const char* solveContactSource = solveContactCL;
- const char* solveFrictionSource = solveFrictionCL;
-
- {
- cl_program solveContactProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveContactSource, &pErrNum, additionalMacros, B3_SOLVER_CONTACT_KERNEL_PATH);
- b3Assert(solveContactProg);
-
- cl_program solveFrictionProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solveFrictionSource, &pErrNum, additionalMacros, B3_SOLVER_FRICTION_KERNEL_PATH);
- b3Assert(solveFrictionProg);
-
- cl_program solverSetup2Prog = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetup2Source, &pErrNum, additionalMacros, B3_SOLVER_SETUP2_KERNEL_PATH);
- b3Assert(solverSetup2Prog);
-
- cl_program solverSetupProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, solverSetupSource, &pErrNum, additionalMacros, B3_SOLVER_SETUP_KERNEL_PATH);
- b3Assert(solverSetupProg);
-
- m_solveFrictionKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveFrictionSource, "BatchSolveKernelFriction", &pErrNum, solveFrictionProg, additionalMacros);
- b3Assert(m_solveFrictionKernel);
-
- m_solveContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solveContactSource, "BatchSolveKernelContact", &pErrNum, solveContactProg, additionalMacros);
- b3Assert(m_solveContactKernel);
-
- m_contactToConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetupSource, "ContactToConstraintKernel", &pErrNum, solverSetupProg, additionalMacros);
- b3Assert(m_contactToConstraintKernel);
-
- m_setSortDataKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "SetSortDataKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_setSortDataKernel);
-
- m_reorderContactKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "ReorderContactKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_reorderContactKernel);
-
- m_copyConstraintKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, solverSetup2Source, "CopyConstraintKernel", &pErrNum, solverSetup2Prog, additionalMacros);
- b3Assert(m_copyConstraintKernel);
- }
-
- {
- cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelSource, &pErrNum, additionalMacros, B3_BATCHING_PATH);
- //cl_program batchingProg = b3OpenCLUtils::compileCLProgramFromString( ctx, device, 0, &pErrNum,additionalMacros, B3_BATCHING_PATH,true);
- b3Assert(batchingProg);
-
- m_batchingKernel = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelSource, "CreateBatches", &pErrNum, batchingProg, additionalMacros);
- b3Assert(m_batchingKernel);
- }
- {
- cl_program batchingNewProg = b3OpenCLUtils::compileCLProgramFromString(ctx, device, batchKernelNewSource, &pErrNum, additionalMacros, B3_BATCHING_NEW_PATH);
- b3Assert(batchingNewProg);
-
- m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString(ctx, device, batchKernelNewSource, "CreateBatchesNew", &pErrNum, batchingNewProg, additionalMacros);
- //m_batchingKernelNew = b3OpenCLUtils::compileCLKernelFromString( ctx, device, batchKernelNewSource, "CreateBatchesBruteForce", &pErrNum, batchingNewProg,additionalMacros );
- b3Assert(m_batchingKernelNew);
- }
-}
-
-b3Solver::~b3Solver()
-{
- delete m_offsets;
- delete m_numConstraints;
- delete m_sortDataBuffer;
- delete m_contactBuffer2;
-
- delete m_sort32;
- delete m_scan;
- delete m_search;
-
- clReleaseKernel(m_batchingKernel);
- clReleaseKernel(m_batchingKernelNew);
-
- clReleaseKernel(m_solveContactKernel);
- clReleaseKernel(m_solveFrictionKernel);
-
- clReleaseKernel(m_contactToConstraintKernel);
- clReleaseKernel(m_setSortDataKernel);
- clReleaseKernel(m_reorderContactKernel);
- clReleaseKernel(m_copyConstraintKernel);
-}
-
-template <bool JACOBI>
-static __inline void solveContact(b3GpuConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
-{
- b3Vector3 dLinVelA;
- dLinVelA.setZero();
- b3Vector3 dAngVelA;
- dAngVelA.setZero();
- b3Vector3 dLinVelB;
- dLinVelB.setZero();
- b3Vector3 dAngVelB;
- dAngVelB.setZero();
-
- for (int ic = 0; ic < 4; ic++)
- {
- // dont necessary because this makes change to 0
- if (cs.m_jacCoeffInv[ic] == 0.f) continue;
-
- {
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = cs.m_worldPos[ic] - (b3Vector3&)posA;
- b3Vector3 r1 = cs.m_worldPos[ic] - (b3Vector3&)posB;
- setLinearAndAngular((const b3Vector3&)cs.m_linear, (const b3Vector3&)r0, (const b3Vector3&)r1, &linear, &angular0, &angular1);
-
- float rambdaDt = calcRelVel((const b3Vector3&)cs.m_linear, (const b3Vector3&)-cs.m_linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB) +
- cs.m_b[ic];
- rambdaDt *= cs.m_jacCoeffInv[ic];
-
- {
- float prevSum = cs.m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[ic]);
- updated = b3Min(updated, maxRambdaDt[ic]);
- rambdaDt = updated - prevSum;
- cs.m_appliedRambdaDt[ic] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
- if (JACOBI)
- {
- dLinVelA += linImp0;
- dAngVelA += angImp0;
- dLinVelB += linImp1;
- dAngVelB += angImp1;
- }
- else
- {
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
- }
- }
-
- if (JACOBI)
- {
- linVelA += dLinVelA;
- angVelA += dAngVelA;
- linVelB += dLinVelB;
- angVelB += dAngVelB;
- }
-}
-
-static __inline void solveFriction(b3GpuConstraint4& cs,
- const b3Vector3& posA, b3Vector3& linVelA, b3Vector3& angVelA, float invMassA, const b3Matrix3x3& invInertiaA,
- const b3Vector3& posB, b3Vector3& linVelB, b3Vector3& angVelB, float invMassB, const b3Matrix3x3& invInertiaB,
- float maxRambdaDt[4], float minRambdaDt[4])
-{
- if (cs.m_fJacCoeffInv[0] == 0 && cs.m_fJacCoeffInv[0] == 0) return;
- const b3Vector3& center = (const b3Vector3&)cs.m_center;
-
- b3Vector3 n = -(const b3Vector3&)cs.m_linear;
-
- b3Vector3 tangent[2];
-#if 1
- b3PlaneSpace1(n, tangent[0], tangent[1]);
-#else
- b3Vector3 r = cs.m_worldPos[0] - center;
- tangent[0] = cross3(n, r);
- tangent[1] = cross3(tangent[0], n);
- tangent[0] = normalize3(tangent[0]);
- tangent[1] = normalize3(tangent[1]);
-#endif
-
- b3Vector3 angular0, angular1, linear;
- b3Vector3 r0 = center - posA;
- b3Vector3 r1 = center - posB;
- for (int i = 0; i < 2; i++)
- {
- setLinearAndAngular(tangent[i], r0, r1, &linear, &angular0, &angular1);
- float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
- rambdaDt *= cs.m_fJacCoeffInv[i];
-
- {
- float prevSum = cs.m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = b3Max(updated, minRambdaDt[i]);
- updated = b3Min(updated, maxRambdaDt[i]);
- rambdaDt = updated - prevSum;
- cs.m_fAppliedRambdaDt[i] = updated;
- }
-
- b3Vector3 linImp0 = invMassA * linear * rambdaDt;
- b3Vector3 linImp1 = invMassB * (-linear) * rambdaDt;
- b3Vector3 angImp0 = (invInertiaA * angular0) * rambdaDt;
- b3Vector3 angImp1 = (invInertiaB * angular1) * rambdaDt;
-#ifdef _WIN32
- b3Assert(_finite(linImp0.getX()));
- b3Assert(_finite(linImp1.getX()));
-#endif
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
-
- { // angular damping for point constraint
- b3Vector3 ab = (posB - posA).normalized();
- b3Vector3 ac = (center - posA).normalized();
- if (b3Dot(ab, ac) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = b3Dot(n, angVelA);
- float angNB = b3Dot(n, angVelB);
-
- angVelA -= (angNA * 0.1f) * n;
- angVelB -= (angNB * 0.1f) * n;
- }
- }
-}
-/*
- b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
- b3AlignedObjectArray<b3InertiaData>& m_shapes;
- b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
- b3AlignedObjectArray<int>* m_batchSizes;
- int m_cellIndex;
- int m_curWgidx;
- int m_start;
- int m_nConstraints;
- bool m_solveFriction;
- int m_maxNumBatches;
- */
-
-struct SolveTask // : public ThreadPool::Task
-{
- SolveTask(b3AlignedObjectArray<b3RigidBodyData>& bodies, b3AlignedObjectArray<b3InertiaData>& shapes, b3AlignedObjectArray<b3GpuConstraint4>& constraints,
- int start, int nConstraints, int maxNumBatches, b3AlignedObjectArray<int>* wgUsedBodies, int curWgidx, b3AlignedObjectArray<int>* batchSizes, int cellIndex)
- : m_bodies(bodies), m_shapes(shapes), m_constraints(constraints), m_batchSizes(batchSizes), m_cellIndex(cellIndex), m_curWgidx(curWgidx), m_start(start), m_nConstraints(nConstraints), m_solveFriction(true), m_maxNumBatches(maxNumBatches)
- {
- }
-
- unsigned short int getType() { return 0; }
-
- void run(int tIdx)
- {
- int offset = 0;
- for (int ii = 0; ii < B3_MAX_NUM_BATCHES; ii++)
- {
- int numInBatch = m_batchSizes->at(m_cellIndex * B3_MAX_NUM_BATCHES + ii);
- if (!numInBatch)
- break;
-
- for (int jj = 0; jj < numInBatch; jj++)
- {
- int i = m_start + offset + jj;
- int batchId = m_constraints[i].m_batchIdx;
- b3Assert(batchId == ii);
- float frictionCoeff = m_constraints[i].getFrictionCoeff();
- int aIdx = (int)m_constraints[i].m_bodyA;
- int bIdx = (int)m_constraints[i].m_bodyB;
- // int localBatch = m_constraints[i].m_batchIdx;
- b3RigidBodyData& bodyA = m_bodies[aIdx];
- b3RigidBodyData& bodyB = m_bodies[bIdx];
-
- if (!m_solveFriction)
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
-
- solveContact<false>(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt);
- }
- else
- {
- float maxRambdaDt[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX};
- float minRambdaDt[4] = {0.f, 0.f, 0.f, 0.f};
- float sum = 0;
- for (int j = 0; j < 4; j++)
- {
- sum += m_constraints[i].m_appliedRambdaDt[j];
- }
- frictionCoeff = 0.7f;
- for (int j = 0; j < 4; j++)
- {
- maxRambdaDt[j] = frictionCoeff * sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
- solveFriction(m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3&)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3&)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt);
- }
- }
- offset += numInBatch;
- }
- /* for (int bb=0;bb<m_maxNumBatches;bb++)
- {
- //for(int ic=m_nConstraints-1; ic>=0; ic--)
- for(int ic=0; ic<m_nConstraints; ic++)
- {
-
- int i = m_start + ic;
- if (m_constraints[i].m_batchIdx != bb)
- continue;
-
- float frictionCoeff = m_constraints[i].getFrictionCoeff();
- int aIdx = (int)m_constraints[i].m_bodyA;
- int bIdx = (int)m_constraints[i].m_bodyB;
- int localBatch = m_constraints[i].m_batchIdx;
- b3RigidBodyData& bodyA = m_bodies[aIdx];
- b3RigidBodyData& bodyB = m_bodies[bIdx];
-
- if( !m_solveFriction )
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- solveContact<false>( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass, (const b3Matrix3x3 &)m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass, (const b3Matrix3x3 &)m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
- }
- else
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
- float sum = 0;
- for(int j=0; j<4; j++)
- {
- sum +=m_constraints[i].m_appliedRambdaDt[j];
- }
- frictionCoeff = 0.7f;
- for(int j=0; j<4; j++)
- {
- maxRambdaDt[j] = frictionCoeff*sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
- solveFriction( m_constraints[i], (b3Vector3&)bodyA.m_pos, (b3Vector3&)bodyA.m_linVel, (b3Vector3&)bodyA.m_angVel, bodyA.m_invMass,(const b3Matrix3x3 &) m_shapes[aIdx].m_invInertiaWorld,
- (b3Vector3&)bodyB.m_pos, (b3Vector3&)bodyB.m_linVel, (b3Vector3&)bodyB.m_angVel, bodyB.m_invMass,(const b3Matrix3x3 &) m_shapes[bIdx].m_invInertiaWorld,
- maxRambdaDt, minRambdaDt );
-
- }
- }
- }
- */
- }
-
- b3AlignedObjectArray<b3RigidBodyData>& m_bodies;
- b3AlignedObjectArray<b3InertiaData>& m_shapes;
- b3AlignedObjectArray<b3GpuConstraint4>& m_constraints;
- b3AlignedObjectArray<int>* m_batchSizes;
- int m_cellIndex;
- int m_curWgidx;
- int m_start;
- int m_nConstraints;
- bool m_solveFriction;
- int m_maxNumBatches;
-};
-
-void b3Solver::solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes)
-{
-#if 0
- {
- int nSplitX = B3_SOLVER_N_SPLIT_X;
- int nSplitY = B3_SOLVER_N_SPLIT_Y;
- int numWorkgroups = B3_SOLVER_N_CELLS/B3_SOLVER_N_BATCHES;
- for (int z=0;z<4;z++)
- {
- for (int y=0;y<4;y++)
- {
- for (int x=0;x<4;x++)
- {
- int newIndex = (x+y*nSplitX+z*nSplitX*nSplitY);
- // printf("newIndex=%d\n",newIndex);
-
- int zIdx = newIndex/(nSplitX*nSplitY);
- int remain = newIndex%(nSplitX*nSplitY);
- int yIdx = remain/nSplitX;
- int xIdx = remain%nSplitX;
- // printf("newIndex=%d\n",newIndex);
- }
- }
- }
-
- //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
- for (int cellBatch=0;cellBatch<B3_SOLVER_N_BATCHES;cellBatch++)
- {
- for (int wgIdx=0;wgIdx<numWorkgroups;wgIdx++)
- {
- int zIdx = (wgIdx/((nSplitX*nSplitY)/4))*2+((cellBatch&4)>>2);
- int remain= (wgIdx%((nSplitX*nSplitY)/4));
- int yIdx = (remain/(nSplitX/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain%(nSplitX/2))*2 + (cellBatch&1);
-
- /*int zIdx = newIndex/(nSplitX*nSplitY);
- int remain = newIndex%(nSplitX*nSplitY);
- int yIdx = remain/nSplitX;
- int xIdx = remain%nSplitX;
- */
- int cellIdx = xIdx+yIdx*nSplitX+zIdx*(nSplitX*nSplitY);
- // printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
- }
- }
- }
-#endif
-
- b3AlignedObjectArray<b3RigidBodyData> bodyNative;
- bodyBuf->copyToHost(bodyNative);
- b3AlignedObjectArray<b3InertiaData> shapeNative;
- shapeBuf->copyToHost(shapeNative);
- b3AlignedObjectArray<b3GpuConstraint4> constraintNative;
- constraint->copyToHost(constraintNative);
-
- b3AlignedObjectArray<unsigned int> numConstraintsHost;
- m_numConstraints->copyToHost(numConstraintsHost);
-
- //printf("------------------------\n");
- b3AlignedObjectArray<unsigned int> offsetsHost;
- m_offsets->copyToHost(offsetsHost);
- static int frame = 0;
- bool useBatches = true;
- if (useBatches)
- {
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
- {
- int nSplitX = B3_SOLVER_N_SPLIT_X;
- int nSplitY = B3_SOLVER_N_SPLIT_Y;
- int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
- //printf("cell Batch %d\n",cellBatch);
- b3AlignedObjectArray<int> usedBodies[B3_SOLVER_N_CELLS];
- for (int i = 0; i < B3_SOLVER_N_CELLS; i++)
- {
- usedBodies[i].resize(0);
- }
-
- //for (int wgIdx=numWorkgroups-1;wgIdx>=0;wgIdx--)
- for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
- {
- int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
- int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
- int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
- int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
- int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
-
- if (numConstraintsHost[cellIdx] == 0)
- continue;
-
- //printf("wgIdx %d: xIdx=%d, yIdx=%d, zIdx=%d, cellIdx=%d, cell Batch %d\n",wgIdx,xIdx,yIdx,zIdx,cellIdx,cellBatch);
- //printf("cell %d has %d constraints\n", cellIdx,numConstraintsHost[cellIdx]);
- if (zIdx)
- {
- //printf("?\n");
- }
-
- if (iter == 0)
- {
- //printf("frame=%d, Cell xIdx=%x, yIdx=%d ",frame, xIdx,yIdx);
- //printf("cellBatch=%d, wgIdx=%d, #constraints in cell=%d\n",cellBatch,wgIdx,numConstraintsHost[cellIdx]);
- }
- const int start = offsetsHost[cellIdx];
- int numConstraintsInCell = numConstraintsHost[cellIdx];
- // const int end = start + numConstraintsInCell;
-
- SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, usedBodies, wgIdx, batchSizes, cellIdx);
- task.m_solveFriction = false;
- task.run(0);
- }
- }
- }
-
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- for (int cellBatch = 0; cellBatch < B3_SOLVER_N_BATCHES; cellBatch++)
- {
- int nSplitX = B3_SOLVER_N_SPLIT_X;
- int nSplitY = B3_SOLVER_N_SPLIT_Y;
-
- int numWorkgroups = B3_SOLVER_N_CELLS / B3_SOLVER_N_BATCHES;
-
- for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
- {
- int zIdx = (wgIdx / ((nSplitX * nSplitY) / 4)) * 2 + ((cellBatch & 4) >> 2);
- int remain = (wgIdx % ((nSplitX * nSplitY) / 4));
- int yIdx = (remain / (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
- int xIdx = (remain % (nSplitX / 2)) * 2 + (cellBatch & 1);
-
- int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
-
- if (numConstraintsHost[cellIdx] == 0)
- continue;
-
- //printf("yIdx=%d\n",yIdx);
-
- const int start = offsetsHost[cellIdx];
- int numConstraintsInCell = numConstraintsHost[cellIdx];
- // const int end = start + numConstraintsInCell;
-
- SolveTask task(bodyNative, shapeNative, constraintNative, start, numConstraintsInCell, maxNumBatches, 0, 0, batchSizes, cellIdx);
- task.m_solveFriction = true;
- task.run(0);
- }
- }
- }
- }
- else
- {
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
- task.m_solveFriction = false;
- task.run(0);
- }
-
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- SolveTask task(bodyNative, shapeNative, constraintNative, 0, n, maxNumBatches, 0, 0, 0, 0);
- task.m_solveFriction = true;
- task.run(0);
- }
- }
-
- bodyBuf->copyFromHost(bodyNative);
- shapeBuf->copyFromHost(shapeNative);
- constraint->copyFromHost(constraintNative);
- frame++;
-}
-
-void checkConstraintBatch(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint,
- b3OpenCLArray<unsigned int>* m_numConstraints,
- b3OpenCLArray<unsigned int>* m_offsets,
- int batchId)
-{
- // b3BufferInfoCL( m_numConstraints->getBufferCL() ),
- // b3BufferInfoCL( m_offsets->getBufferCL() )
-
- int cellBatch = batchId;
- const int nn = B3_SOLVER_N_CELLS;
- // int numWorkItems = 64*nn/B3_SOLVER_N_BATCHES;
-
- b3AlignedObjectArray<unsigned int> gN;
- m_numConstraints->copyToHost(gN);
- b3AlignedObjectArray<unsigned int> gOffsets;
- m_offsets->copyToHost(gOffsets);
- int nSplitX = B3_SOLVER_N_SPLIT_X;
- int nSplitY = B3_SOLVER_N_SPLIT_Y;
-
- // int bIdx = batchId;
-
- b3AlignedObjectArray<b3GpuConstraint4> cpuConstraints;
- constraint->copyToHost(cpuConstraints);
-
- printf("batch = %d\n", batchId);
-
- int numWorkgroups = nn / B3_SOLVER_N_BATCHES;
- b3AlignedObjectArray<int> usedBodies;
-
- for (int wgIdx = 0; wgIdx < numWorkgroups; wgIdx++)
- {
- printf("wgIdx = %d ", wgIdx);
-
- int zIdx = (wgIdx / ((nSplitX * nSplitY)) / 2) * 2 + ((cellBatch & 4) >> 2);
- int remain = wgIdx % ((nSplitX * nSplitY));
- int yIdx = (remain % (nSplitX / 2)) * 2 + ((cellBatch & 2) >> 1);
- int xIdx = (remain / (nSplitX / 2)) * 2 + (cellBatch & 1);
-
- int cellIdx = xIdx + yIdx * nSplitX + zIdx * (nSplitX * nSplitY);
- printf("cellIdx=%d\n", cellIdx);
- if (gN[cellIdx] == 0)
- continue;
-
- const int start = gOffsets[cellIdx];
- const int end = start + gN[cellIdx];
-
- for (int c = start; c < end; c++)
- {
- b3GpuConstraint4& constraint = cpuConstraints[c];
- //printf("constraint (%d,%d)\n", constraint.m_bodyA,constraint.m_bodyB);
- if (usedBodies.findLinearSearch(constraint.m_bodyA) < usedBodies.size())
- {
- printf("error?\n");
- }
- if (usedBodies.findLinearSearch(constraint.m_bodyB) < usedBodies.size())
- {
- printf("error?\n");
- }
- }
-
- for (int c = start; c < end; c++)
- {
- b3GpuConstraint4& constraint = cpuConstraints[c];
- usedBodies.push_back(constraint.m_bodyA);
- usedBodies.push_back(constraint.m_bodyB);
- }
- }
-}
-
-static bool verify = false;
-
-void b3Solver::solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches)
-{
- b3Int4 cdata = b3MakeInt4(n, 0, 0, 0);
- {
- const int nn = B3_SOLVER_N_CELLS;
-
- cdata.x = 0;
- cdata.y = maxNumBatches; //250;
-
- int numWorkItems = 64 * nn / B3_SOLVER_N_BATCHES;
-#ifdef DEBUG_ME
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
-#endif
-
- {
- B3_PROFILE("m_batchSolveKernel iterations");
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
- {
- if (verify)
- {
- checkConstraintBatch(bodyBuf, shapeBuf, constraint, m_numConstraints, m_offsets, ib);
- }
-
-#ifdef DEBUG_ME
- memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
- gpuDebugInfo.write(debugInfo, numWorkItems);
-#endif
-
- cdata.z = ib;
-
- b3LauncherCL launcher(m_queue, m_solveContactKernel, "m_solveContactKernel");
-#if 1
-
- b3BufferInfoCL bInfo[] = {
-
- b3BufferInfoCL(bodyBuf->getBufferCL()),
- b3BufferInfoCL(shapeBuf->getBufferCL()),
- b3BufferInfoCL(constraint->getBufferCL()),
- b3BufferInfoCL(m_numConstraints->getBufferCL()),
- b3BufferInfoCL(m_offsets->getBufferCL())
-#ifdef DEBUG_ME
- ,
- b3BufferInfoCL(&gpuDebugInfo)
-#endif
- };
-
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- //launcher.setConst( cdata.x );
- launcher.setConst(cdata.y);
- launcher.setConst(cdata.z);
- b3Int4 nSplit;
- nSplit.x = B3_SOLVER_N_SPLIT_X;
- nSplit.y = B3_SOLVER_N_SPLIT_Y;
- nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- launcher.setConst(nSplit);
- launcher.launch1D(numWorkItems, 64);
-
-#else
- const char* fileName = "m_batchSolveKernel.bin";
- FILE* f = fopen(fileName, "rb");
- if (f)
- {
- int sizeInBytes = 0;
- if (fseek(f, 0, SEEK_END) || (sizeInBytes = ftell(f)) == EOF || fseek(f, 0, SEEK_SET))
- {
- printf("error, cannot get file size\n");
- exit(0);
- }
-
- unsigned char* buf = (unsigned char*)malloc(sizeInBytes);
- fread(buf, sizeInBytes, 1, f);
- int serializedBytes = launcher.deserializeArgs(buf, sizeInBytes, m_context);
- int num = *(int*)&buf[serializedBytes];
-
- launcher.launch1D(num);
-
- //this clFinish is for testing on errors
- clFinish(m_queue);
- }
-
-#endif
-
-#ifdef DEBUG_ME
- clFinish(m_queue);
- gpuDebugInfo.read(debugInfo, numWorkItems);
- clFinish(m_queue);
- for (int i = 0; i < numWorkItems; i++)
- {
- if (debugInfo[i].m_valInt2 > 0)
- {
- printf("debugInfo[i].m_valInt2 = %d\n", i, debugInfo[i].m_valInt2);
- }
-
- if (debugInfo[i].m_valInt3 > 0)
- {
- printf("debugInfo[i].m_valInt3 = %d\n", i, debugInfo[i].m_valInt3);
- }
- }
-#endif //DEBUG_ME
- }
- }
-
- clFinish(m_queue);
- }
-
- cdata.x = 1;
- bool applyFriction = true;
- if (applyFriction)
- {
- B3_PROFILE("m_batchSolveKernel iterations2");
- for (int iter = 0; iter < m_nIterations; iter++)
- {
- for (int ib = 0; ib < B3_SOLVER_N_BATCHES; ib++)
- {
- cdata.z = ib;
-
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL(bodyBuf->getBufferCL()),
- b3BufferInfoCL(shapeBuf->getBufferCL()),
- b3BufferInfoCL(constraint->getBufferCL()),
- b3BufferInfoCL(m_numConstraints->getBufferCL()),
- b3BufferInfoCL(m_offsets->getBufferCL())
-#ifdef DEBUG_ME
- ,
- b3BufferInfoCL(&gpuDebugInfo)
-#endif //DEBUG_ME
- };
- b3LauncherCL launcher(m_queue, m_solveFrictionKernel, "m_solveFrictionKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- //launcher.setConst( cdata.x );
- launcher.setConst(cdata.y);
- launcher.setConst(cdata.z);
- b3Int4 nSplit;
- nSplit.x = B3_SOLVER_N_SPLIT_X;
- nSplit.y = B3_SOLVER_N_SPLIT_Y;
- nSplit.z = B3_SOLVER_N_SPLIT_Z;
-
- launcher.setConst(nSplit);
-
- launcher.launch1D(64 * nn / B3_SOLVER_N_BATCHES, 64);
- }
- }
- clFinish(m_queue);
- }
-#ifdef DEBUG_ME
- delete[] debugInfo;
-#endif //DEBUG_ME
- }
-}
-
-void b3Solver::convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
- int nContacts, const ConstraintCfg& cfg)
-{
- // b3OpenCLArray<b3GpuConstraint4>* constraintNative =0;
- contactCOut->resize(nContacts);
- struct CB
- {
- int m_nContacts;
- float m_dt;
- float m_positionDrift;
- float m_positionConstraintCoeff;
- };
-
- {
- CB cdata;
- cdata.m_nContacts = nContacts;
- cdata.m_dt = cfg.m_dt;
- cdata.m_positionDrift = cfg.m_positionDrift;
- cdata.m_positionConstraintCoeff = cfg.m_positionConstraintCoeff;
-
- if (gConvertConstraintOnCpu)
- {
- b3AlignedObjectArray<b3RigidBodyData> gBodies;
- bodyBuf->copyToHost(gBodies);
-
- b3AlignedObjectArray<b3Contact4> gContact;
- contactsIn->copyToHost(gContact);
-
- b3AlignedObjectArray<b3InertiaData> gShapes;
- shapeBuf->copyToHost(gShapes);
-
- b3AlignedObjectArray<b3GpuConstraint4> gConstraintOut;
- gConstraintOut.resize(nContacts);
-
- B3_PROFILE("cpu contactToConstraintKernel");
- for (int gIdx = 0; gIdx < nContacts; gIdx++)
- {
- int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
- int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
-
- b3Float4 posA = gBodies[aIdx].m_pos;
- b3Float4 linVelA = gBodies[aIdx].m_linVel;
- b3Float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
-
- b3Float4 posB = gBodies[bIdx].m_pos;
- b3Float4 linVelB = gBodies[bIdx].m_linVel;
- b3Float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
-
- b3ContactConstraint4_t cs;
-
- setConstraint4(posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], cdata.m_dt, cdata.m_positionDrift, cdata.m_positionConstraintCoeff,
- &cs);
-
- cs.m_batchIdx = gContact[gIdx].m_batchIdx;
-
- gConstraintOut[gIdx] = (b3GpuConstraint4&)cs;
- }
-
- contactCOut->copyFromHost(gConstraintOut);
- }
- else
- {
- B3_PROFILE("gpu m_contactToConstraintKernel");
-
- b3BufferInfoCL bInfo[] = {b3BufferInfoCL(contactsIn->getBufferCL()), b3BufferInfoCL(bodyBuf->getBufferCL()), b3BufferInfoCL(shapeBuf->getBufferCL()),
- b3BufferInfoCL(contactCOut->getBufferCL())};
- b3LauncherCL launcher(m_queue, m_contactToConstraintKernel, "m_contactToConstraintKernel");
- launcher.setBuffers(bInfo, sizeof(bInfo) / sizeof(b3BufferInfoCL));
- //launcher.setConst( cdata );
-
- launcher.setConst(cdata.m_nContacts);
- launcher.setConst(cdata.m_dt);
- launcher.setConst(cdata.m_positionDrift);
- launcher.setConst(cdata.m_positionConstraintCoeff);
-
- launcher.launch1D(nContacts, 64);
- clFinish(m_queue);
- }
- }
-}
-
-/*
-void b3Solver::sortContacts( const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- b3OpenCLArray<b3Contact4>* contactsIn, void* additionalData,
- int nContacts, const b3Solver::ConstraintCfg& cfg )
-{
-
-
-
- const int sortAlignment = 512; // todo. get this out of sort
- if( cfg.m_enableParallelSolve )
- {
-
-
- int sortSize = NEXTMULTIPLEOF( nContacts, sortAlignment );
-
- b3OpenCLArray<unsigned int>* countsNative = m_numConstraints;//BufferUtils::map<TYPE_CL, false>( data->m_device, &countsHost );
- b3OpenCLArray<unsigned int>* offsetsNative = m_offsets;//BufferUtils::map<TYPE_CL, false>( data->m_device, &offsetsHost );
-
- { // 2. set cell idx
- struct CB
- {
- int m_nContacts;
- int m_staticIdx;
- float m_scale;
- int m_nSplit;
- };
-
- b3Assert( sortSize%64 == 0 );
- CB cdata;
- cdata.m_nContacts = nContacts;
- cdata.m_staticIdx = cfg.m_staticIdx;
- cdata.m_scale = 1.f/(N_OBJ_PER_SPLIT*cfg.m_averageExtent);
- cdata.m_nSplit = B3_SOLVER_N_SPLIT;
-
-
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( bodyBuf->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
- b3LauncherCL launcher( m_queue, m_setSortDataKernel );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( sortSize, 64 );
- }
-
- { // 3. sort by cell idx
- int n = B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT;
- int sortBit = 32;
- //if( n <= 0xffff ) sortBit = 16;
- //if( n <= 0xff ) sortBit = 8;
- m_sort32->execute(*m_sortDataBuffer,sortSize);
- }
- { // 4. find entries
- m_search->execute( *m_sortDataBuffer, nContacts, *countsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT, b3BoundSearchCL::COUNT);
-
- m_scan->execute( *countsNative, *offsetsNative, B3_SOLVER_N_SPLIT*B3_SOLVER_N_SPLIT );
- }
-
- { // 5. sort constraints by cellIdx
- // todo. preallocate this
-// b3Assert( contactsIn->getType() == TYPE_HOST );
-// b3OpenCLArray<b3Contact4>* out = BufferUtils::map<TYPE_CL, false>( data->m_device, contactsIn ); // copying contacts to this buffer
-
- {
-
-
- b3Int4 cdata; cdata.x = nContacts;
- b3BufferInfoCL bInfo[] = { b3BufferInfoCL( contactsIn->getBufferCL() ), b3BufferInfoCL( m_contactBuffer->getBufferCL() ), b3BufferInfoCL( m_sortDataBuffer->getBufferCL() ) };
- b3LauncherCL launcher( m_queue, m_reorderContactKernel );
- launcher.setBuffers( bInfo, sizeof(bInfo)/sizeof(b3BufferInfoCL) );
- launcher.setConst( cdata );
- launcher.launch1D( nContacts, 64 );
- }
-// BufferUtils::unmap<true>( out, contactsIn, nContacts );
- }
- }
-
-
-}
-
-*/
-void b3Solver::batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* nNative, b3OpenCLArray<unsigned int>* offsetsNative, int staticIdx)
-{
- int numWorkItems = 64 * B3_SOLVER_N_CELLS;
- {
- B3_PROFILE("batch generation");
-
- b3Int4 cdata;
- cdata.x = nContacts;
- cdata.y = 0;
- cdata.z = staticIdx;
-
-#ifdef BATCH_DEBUG
- SolverDebugInfo* debugInfo = new SolverDebugInfo[numWorkItems];
- adl::b3OpenCLArray<SolverDebugInfo> gpuDebugInfo(data->m_device, numWorkItems);
- memset(debugInfo, 0, sizeof(SolverDebugInfo) * numWorkItems);
- gpuDebugInfo.write(debugInfo, numWorkItems);
-#endif
-
-#if 0
- b3BufferInfoCL bInfo[] = {
- b3BufferInfoCL( contacts->getBufferCL() ),
- b3BufferInfoCL( m_contactBuffer2->getBufferCL()),
- b3BufferInfoCL( nNative->getBufferCL() ),
- b3BufferInfoCL( offsetsNative->getBufferCL() ),
-#ifdef BATCH_DEBUG
- , b3BufferInfoCL(&gpuDebugInfo)
-#endif
- };
-#endif
-
- {
- m_batchSizes.resize(nNative->size());
- B3_PROFILE("batchingKernel");
- //b3LauncherCL launcher( m_queue, m_batchingKernel);
- cl_kernel k = useNewBatchingKernel ? m_batchingKernelNew : m_batchingKernel;
-
- b3LauncherCL launcher(m_queue, k, "*batchingKernel");
- if (!useNewBatchingKernel)
- {
- launcher.setBuffer(contacts->getBufferCL());
- }
- launcher.setBuffer(m_contactBuffer2->getBufferCL());
- launcher.setBuffer(nNative->getBufferCL());
- launcher.setBuffer(offsetsNative->getBufferCL());
-
- launcher.setBuffer(m_batchSizes.getBufferCL());
-
- //launcher.setConst( cdata );
- launcher.setConst(staticIdx);
-
- launcher.launch1D(numWorkItems, 64);
- //clFinish(m_queue);
- //b3AlignedObjectArray<int> batchSizesCPU;
- //m_batchSizes.copyToHost(batchSizesCPU);
- //printf(".\n");
- }
-
-#ifdef BATCH_DEBUG
- aaaa
- b3Contact4* hostContacts = new b3Contact4[nContacts];
- m_contactBuffer->read(hostContacts, nContacts);
- clFinish(m_queue);
-
- gpuDebugInfo.read(debugInfo, numWorkItems);
- clFinish(m_queue);
-
- for (int i = 0; i < numWorkItems; i++)
- {
- if (debugInfo[i].m_valInt1 > 0)
- {
- printf("catch\n");
- }
- if (debugInfo[i].m_valInt2 > 0)
- {
- printf("catch22\n");
- }
-
- if (debugInfo[i].m_valInt3 > 0)
- {
- printf("catch666\n");
- }
-
- if (debugInfo[i].m_valInt4 > 0)
- {
- printf("catch777\n");
- }
- }
- delete[] debugInfo;
-#endif //BATCH_DEBUG
- }
-
- // copy buffer to buffer
- //b3Assert(m_contactBuffer->size()==nContacts);
- //contacts->copyFromOpenCLArray( *m_contactBuffer);
- //clFinish(m_queue);//needed?
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h
deleted file mode 100644
index ee63531d78..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/b3Solver.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#ifndef __ADL_SOLVER_H
-#define __ADL_SOLVER_H
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3OpenCLArray.h"
-#include "b3GpuConstraint4.h"
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-#include "Bullet3Collision/NarrowPhaseCollision/b3Contact4.h"
-
-#include "Bullet3OpenCL/ParallelPrimitives/b3PrefixScanCL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3RadixSort32CL.h"
-#include "Bullet3OpenCL/ParallelPrimitives/b3BoundSearchCL.h"
-
-#include "Bullet3OpenCL/Initialize/b3OpenCLUtils.h"
-
-#define B3NEXTMULTIPLEOF(num, alignment) (((num) / (alignment) + (((num) % (alignment) == 0) ? 0 : 1)) * (alignment))
-
-enum
-{
- B3_SOLVER_N_SPLIT_X = 8, //16,//4,
- B3_SOLVER_N_SPLIT_Y = 4, //16,//4,
- B3_SOLVER_N_SPLIT_Z = 8, //,
- B3_SOLVER_N_CELLS = B3_SOLVER_N_SPLIT_X * B3_SOLVER_N_SPLIT_Y * B3_SOLVER_N_SPLIT_Z,
- B3_SOLVER_N_BATCHES = 8, //4,//8,//4,
- B3_MAX_NUM_BATCHES = 128,
-};
-
-class b3SolverBase
-{
-public:
- struct ConstraintCfg
- {
- ConstraintCfg(float dt = 0.f) : m_positionDrift(0.005f), m_positionConstraintCoeff(0.2f), m_dt(dt), m_staticIdx(-1) {}
-
- float m_positionDrift;
- float m_positionConstraintCoeff;
- float m_dt;
- bool m_enableParallelSolve;
- float m_batchCellSize;
- int m_staticIdx;
- };
-};
-
-class b3Solver : public b3SolverBase
-{
-public:
- cl_context m_context;
- cl_device_id m_device;
- cl_command_queue m_queue;
-
- b3OpenCLArray<unsigned int>* m_numConstraints;
- b3OpenCLArray<unsigned int>* m_offsets;
- b3OpenCLArray<int> m_batchSizes;
-
- int m_nIterations;
- cl_kernel m_batchingKernel;
- cl_kernel m_batchingKernelNew;
- cl_kernel m_solveContactKernel;
- cl_kernel m_solveFrictionKernel;
- cl_kernel m_contactToConstraintKernel;
- cl_kernel m_setSortDataKernel;
- cl_kernel m_reorderContactKernel;
- cl_kernel m_copyConstraintKernel;
-
- class b3RadixSort32CL* m_sort32;
- class b3BoundSearchCL* m_search;
- class b3PrefixScanCL* m_scan;
-
- b3OpenCLArray<b3SortData>* m_sortDataBuffer;
- b3OpenCLArray<b3Contact4>* m_contactBuffer2;
-
- enum
- {
- DYNAMIC_CONTACT_ALLOCATION_THRESHOLD = 2000000,
- };
-
- b3Solver(cl_context ctx, cl_device_id device, cl_command_queue queue, int pairCapacity);
-
- virtual ~b3Solver();
-
- void solveContactConstraint(const b3OpenCLArray<b3RigidBodyData>* bodyBuf, const b3OpenCLArray<b3InertiaData>* inertiaBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches);
-
- void solveContactConstraintHost(b3OpenCLArray<b3RigidBodyData>* bodyBuf, b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3GpuConstraint4>* constraint, void* additionalData, int n, int maxNumBatches, b3AlignedObjectArray<int>* batchSizes);
-
- void convertToConstraints(const b3OpenCLArray<b3RigidBodyData>* bodyBuf,
- const b3OpenCLArray<b3InertiaData>* shapeBuf,
- b3OpenCLArray<b3Contact4>* contactsIn, b3OpenCLArray<b3GpuConstraint4>* contactCOut, void* additionalData,
- int nContacts, const ConstraintCfg& cfg);
-
- void batchContacts(b3OpenCLArray<b3Contact4>* contacts, int nContacts, b3OpenCLArray<unsigned int>* n, b3OpenCLArray<unsigned int>* offsets, int staticIdx);
-};
-
-#endif //__ADL_SOLVER_H
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
deleted file mode 100644
index 3b891b863d..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.cl
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile __global int*
-#endif
-
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-#define WG_SIZE 64
-
-
-
-
-
-typedef struct
-{
- int m_n;
- int m_start;
- int m_staticIdx;
- int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_a;
- int m_b;
- u32 m_idx;
-}Elem;
-
-#define STACK_SIZE (WG_SIZE*10)
-//#define STACK_SIZE (WG_SIZE)
-#define RING_SIZE 1024
-#define RING_SIZE_MASK (RING_SIZE-1)
-#define CHECK_SIZE (WG_SIZE)
-
-
-#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)
-#define RING_END ldsTmp
-
-u32 readBuf(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
- return buff[bufIdx] & (1<<bitIdx);
-}
-
-void writeBuf(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
-// buff[bufIdx] |= (1<<bitIdx);
- atom_or( &buff[bufIdx], (1<<bitIdx) );
-}
-
-u32 tryWrite(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
- u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
- return ((ans >> bitIdx)&1) == 0;
-}
-
-// batching on the GPU
-__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,
- __global const u32* gN, __global const u32* gStart, __global int* batchSizes,
- int m_staticIdx )
-{
- __local u32 ldsStackIdx[STACK_SIZE];
- __local u32 ldsStackEnd;
- __local Elem ldsRingElem[RING_SIZE];
- __local u32 ldsRingEnd;
- __local u32 ldsTmp;
- __local u32 ldsCheckBuffer[CHECK_SIZE];
- __local u32 ldsFixedBuffer[CHECK_SIZE];
- __local u32 ldsGEnd;
- __local u32 ldsDstEnd;
-
- int wgIdx = GET_GROUP_IDX;
- int lIdx = GET_LOCAL_IDX;
-
- const int m_n = gN[wgIdx];
- const int m_start = gStart[wgIdx];
-
- if( lIdx == 0 )
- {
- ldsRingEnd = 0;
- ldsGEnd = 0;
- ldsStackEnd = 0;
- ldsDstEnd = m_start;
- }
-
-
-
-// while(1)
-//was 250
- int ie=0;
- int maxBatch = 0;
- for(ie=0; ie<50; ie++)
- {
- ldsFixedBuffer[lIdx] = 0;
-
- for(int giter=0; giter<4; giter++)
- {
- int ringCap = GET_RING_CAPACITY;
-
- // 1. fill ring
- if( ldsGEnd < m_n )
- {
- while( ringCap > WG_SIZE )
- {
- if( ldsGEnd >= m_n ) break;
- if( lIdx < ringCap - WG_SIZE )
- {
- int srcIdx;
- AtomInc1( ldsGEnd, srcIdx );
- if( srcIdx < m_n )
- {
- int dstIdx;
- AtomInc1( ldsRingEnd, dstIdx );
-
- int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;
- int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;
- ldsRingElem[dstIdx].m_a = (a>b)? b:a;
- ldsRingElem[dstIdx].m_b = (a>b)? a:b;
- ldsRingElem[dstIdx].m_idx = srcIdx;
- }
- }
- ringCap = GET_RING_CAPACITY;
- }
- }
-
- GROUP_LDS_BARRIER;
-
- // 2. fill stack
- __local Elem* dst = ldsRingElem;
- if( lIdx == 0 ) RING_END = 0;
-
- int srcIdx=lIdx;
- int end = ldsRingEnd;
-
- {
- for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)
- {
- Elem e;
- if(srcIdx<end) e = ldsRingElem[srcIdx];
- bool done = (srcIdx<end)?false:true;
-
- for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;
-
- if( !done )
- {
- int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));
- int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));
-
- if( aUsed==0 && bUsed==0 )
- {
- int aAvailable=1;
- int bAvailable=1;
- int ea = abs(e.m_a);
- int eb = abs(e.m_b);
-
- bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);
- bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);
-
- if (!aStatic)
- aAvailable = tryWrite( ldsCheckBuffer, ea );
- if (!bStatic)
- bAvailable = tryWrite( ldsCheckBuffer, eb );
-
- //aAvailable = aStatic? 1: aAvailable;
- //bAvailable = bStatic? 1: bAvailable;
-
- bool success = (aAvailable && bAvailable);
- if(success)
- {
-
- if (!aStatic)
- writeBuf( ldsFixedBuffer, ea );
- if (!bStatic)
- writeBuf( ldsFixedBuffer, eb );
- }
- done = success;
- }
- }
-
- // put it aside
- if(srcIdx<end)
- {
- if( done )
- {
- int dstIdx; AtomInc1( ldsStackEnd, dstIdx );
- if( dstIdx < STACK_SIZE )
- ldsStackIdx[dstIdx] = e.m_idx;
- else{
- done = false;
- AtomAdd( ldsStackEnd, -1 );
- }
- }
- if( !done )
- {
- int dstIdx; AtomInc1( RING_END, dstIdx );
- dst[dstIdx] = e;
- }
- }
-
- // if filled, flush
- if( ldsStackEnd == STACK_SIZE )
- {
- for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)
- {
- int idx = m_start + ldsStackIdx[i];
- int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
- gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
- gConstraintsOut[ dstIdx ].m_batchIdx = ie;
- }
- if( lIdx == 0 ) ldsStackEnd = 0;
-
- //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE)
- ldsFixedBuffer[lIdx] = 0;
- }
- }
- }
-
- if( lIdx == 0 ) ldsRingEnd = RING_END;
- }
-
- GROUP_LDS_BARRIER;
-
- for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)
- {
- int idx = m_start + ldsStackIdx[i];
- int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
- gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
- gConstraintsOut[ dstIdx ].m_batchIdx = ie;
- }
-
- // in case it couldn't consume any pair. Flush them
- // todo. Serial batch worth while?
- if( ldsStackEnd == 0 )
- {
- for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)
- {
- int idx = m_start + ldsRingElem[i].m_idx;
- int dstIdx; AtomInc1( ldsDstEnd, dstIdx );
- gConstraintsOut[ dstIdx ] = gConstraints[ idx ];
- int curBatch = 100+i;
- if (maxBatch < curBatch)
- maxBatch = curBatch;
-
- gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;
-
- }
- GROUP_LDS_BARRIER;
- if( lIdx == 0 ) ldsRingEnd = 0;
- }
-
- if( lIdx == 0 ) ldsStackEnd = 0;
-
- GROUP_LDS_BARRIER;
-
- // termination
- if( ldsGEnd == m_n && ldsRingEnd == 0 )
- break;
- }
-
- if( lIdx == 0 )
- {
- if (maxBatch < ie)
- maxBatch=ie;
- batchSizes[wgIdx]=maxBatch;
- }
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
deleted file mode 100644
index 7c73c96baa..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernels.h
+++ /dev/null
@@ -1,387 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* batchingKernelsCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile __global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "#define WG_SIZE 64\n"
- "typedef struct \n"
- "{\n"
- " int m_n;\n"
- " int m_start;\n"
- " int m_staticIdx;\n"
- " int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct \n"
- "{\n"
- " int m_a;\n"
- " int m_b;\n"
- " u32 m_idx;\n"
- "}Elem;\n"
- "#define STACK_SIZE (WG_SIZE*10)\n"
- "//#define STACK_SIZE (WG_SIZE)\n"
- "#define RING_SIZE 1024\n"
- "#define RING_SIZE_MASK (RING_SIZE-1)\n"
- "#define CHECK_SIZE (WG_SIZE)\n"
- "#define GET_RING_CAPACITY (RING_SIZE - ldsRingEnd)\n"
- "#define RING_END ldsTmp\n"
- "u32 readBuf(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- " return buff[bufIdx] & (1<<bitIdx);\n"
- "}\n"
- "void writeBuf(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- "// buff[bufIdx] |= (1<<bitIdx);\n"
- " atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
- "}\n"
- "u32 tryWrite(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- " u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
- " return ((ans >> bitIdx)&1) == 0;\n"
- "}\n"
- "// batching on the GPU\n"
- "__kernel void CreateBatches( __global const struct b3Contact4Data* gConstraints, __global struct b3Contact4Data* gConstraintsOut,\n"
- " __global const u32* gN, __global const u32* gStart, __global int* batchSizes, \n"
- " int m_staticIdx )\n"
- "{\n"
- " __local u32 ldsStackIdx[STACK_SIZE];\n"
- " __local u32 ldsStackEnd;\n"
- " __local Elem ldsRingElem[RING_SIZE];\n"
- " __local u32 ldsRingEnd;\n"
- " __local u32 ldsTmp;\n"
- " __local u32 ldsCheckBuffer[CHECK_SIZE];\n"
- " __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
- " __local u32 ldsGEnd;\n"
- " __local u32 ldsDstEnd;\n"
- " int wgIdx = GET_GROUP_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " \n"
- " const int m_n = gN[wgIdx];\n"
- " const int m_start = gStart[wgIdx];\n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " ldsRingEnd = 0;\n"
- " ldsGEnd = 0;\n"
- " ldsStackEnd = 0;\n"
- " ldsDstEnd = m_start;\n"
- " }\n"
- " \n"
- " \n"
- " \n"
- "// while(1)\n"
- "//was 250\n"
- " int ie=0;\n"
- " int maxBatch = 0;\n"
- " for(ie=0; ie<50; ie++)\n"
- " {\n"
- " ldsFixedBuffer[lIdx] = 0;\n"
- " for(int giter=0; giter<4; giter++)\n"
- " {\n"
- " int ringCap = GET_RING_CAPACITY;\n"
- " \n"
- " // 1. fill ring\n"
- " if( ldsGEnd < m_n )\n"
- " {\n"
- " while( ringCap > WG_SIZE )\n"
- " {\n"
- " if( ldsGEnd >= m_n ) break;\n"
- " if( lIdx < ringCap - WG_SIZE )\n"
- " {\n"
- " int srcIdx;\n"
- " AtomInc1( ldsGEnd, srcIdx );\n"
- " if( srcIdx < m_n )\n"
- " {\n"
- " int dstIdx;\n"
- " AtomInc1( ldsRingEnd, dstIdx );\n"
- " \n"
- " int a = gConstraints[m_start+srcIdx].m_bodyAPtrAndSignBit;\n"
- " int b = gConstraints[m_start+srcIdx].m_bodyBPtrAndSignBit;\n"
- " ldsRingElem[dstIdx].m_a = (a>b)? b:a;\n"
- " ldsRingElem[dstIdx].m_b = (a>b)? a:b;\n"
- " ldsRingElem[dstIdx].m_idx = srcIdx;\n"
- " }\n"
- " }\n"
- " ringCap = GET_RING_CAPACITY;\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " // 2. fill stack\n"
- " __local Elem* dst = ldsRingElem;\n"
- " if( lIdx == 0 ) RING_END = 0;\n"
- " int srcIdx=lIdx;\n"
- " int end = ldsRingEnd;\n"
- " {\n"
- " for(int ii=0; ii<end; ii+=WG_SIZE, srcIdx+=WG_SIZE)\n"
- " {\n"
- " Elem e;\n"
- " if(srcIdx<end) e = ldsRingElem[srcIdx];\n"
- " bool done = (srcIdx<end)?false:true;\n"
- " for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) ldsCheckBuffer[lIdx] = 0;\n"
- " \n"
- " if( !done )\n"
- " {\n"
- " int aUsed = readBuf( ldsFixedBuffer, abs(e.m_a));\n"
- " int bUsed = readBuf( ldsFixedBuffer, abs(e.m_b));\n"
- " if( aUsed==0 && bUsed==0 )\n"
- " {\n"
- " int aAvailable=1;\n"
- " int bAvailable=1;\n"
- " int ea = abs(e.m_a);\n"
- " int eb = abs(e.m_b);\n"
- " bool aStatic = (e.m_a<0) ||(ea==m_staticIdx);\n"
- " bool bStatic = (e.m_b<0) ||(eb==m_staticIdx);\n"
- " \n"
- " if (!aStatic)\n"
- " aAvailable = tryWrite( ldsCheckBuffer, ea );\n"
- " if (!bStatic)\n"
- " bAvailable = tryWrite( ldsCheckBuffer, eb );\n"
- " \n"
- " //aAvailable = aStatic? 1: aAvailable;\n"
- " //bAvailable = bStatic? 1: bAvailable;\n"
- " bool success = (aAvailable && bAvailable);\n"
- " if(success)\n"
- " {\n"
- " \n"
- " if (!aStatic)\n"
- " writeBuf( ldsFixedBuffer, ea );\n"
- " if (!bStatic)\n"
- " writeBuf( ldsFixedBuffer, eb );\n"
- " }\n"
- " done = success;\n"
- " }\n"
- " }\n"
- " // put it aside\n"
- " if(srcIdx<end)\n"
- " {\n"
- " if( done )\n"
- " {\n"
- " int dstIdx; AtomInc1( ldsStackEnd, dstIdx );\n"
- " if( dstIdx < STACK_SIZE )\n"
- " ldsStackIdx[dstIdx] = e.m_idx;\n"
- " else{\n"
- " done = false;\n"
- " AtomAdd( ldsStackEnd, -1 );\n"
- " }\n"
- " }\n"
- " if( !done )\n"
- " {\n"
- " int dstIdx; AtomInc1( RING_END, dstIdx );\n"
- " dst[dstIdx] = e;\n"
- " }\n"
- " }\n"
- " // if filled, flush\n"
- " if( ldsStackEnd == STACK_SIZE )\n"
- " {\n"
- " for(int i=lIdx; i<STACK_SIZE; i+=WG_SIZE)\n"
- " {\n"
- " int idx = m_start + ldsStackIdx[i];\n"
- " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
- " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
- " gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
- " }\n"
- " if( lIdx == 0 ) ldsStackEnd = 0;\n"
- " //for(int i=lIdx; i<CHECK_SIZE; i+=WG_SIZE) \n"
- " ldsFixedBuffer[lIdx] = 0;\n"
- " }\n"
- " }\n"
- " }\n"
- " if( lIdx == 0 ) ldsRingEnd = RING_END;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " for(int i=lIdx; i<ldsStackEnd; i+=WG_SIZE)\n"
- " {\n"
- " int idx = m_start + ldsStackIdx[i];\n"
- " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
- " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
- " gConstraintsOut[ dstIdx ].m_batchIdx = ie;\n"
- " }\n"
- " // in case it couldn't consume any pair. Flush them\n"
- " // todo. Serial batch worth while?\n"
- " if( ldsStackEnd == 0 )\n"
- " {\n"
- " for(int i=lIdx; i<ldsRingEnd; i+=WG_SIZE)\n"
- " {\n"
- " int idx = m_start + ldsRingElem[i].m_idx;\n"
- " int dstIdx; AtomInc1( ldsDstEnd, dstIdx );\n"
- " gConstraintsOut[ dstIdx ] = gConstraints[ idx ];\n"
- " int curBatch = 100+i;\n"
- " if (maxBatch < curBatch)\n"
- " maxBatch = curBatch;\n"
- " \n"
- " gConstraintsOut[ dstIdx ].m_batchIdx = curBatch;\n"
- " \n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx == 0 ) ldsRingEnd = 0;\n"
- " }\n"
- " if( lIdx == 0 ) ldsStackEnd = 0;\n"
- " GROUP_LDS_BARRIER;\n"
- " // termination\n"
- " if( ldsGEnd == m_n && ldsRingEnd == 0 )\n"
- " break;\n"
- " }\n"
- " if( lIdx == 0 )\n"
- " {\n"
- " if (maxBatch < ie)\n"
- " maxBatch=ie;\n"
- " batchSizes[wgIdx]=maxBatch;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
deleted file mode 100644
index ba1b66d2c3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.cl
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile __global int*
-#endif
-
-#define SIMD_WIDTH 64
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-#define WG_SIZE 64
-
-
-
-
-
-typedef struct
-{
- int m_n;
- int m_start;
- int m_staticIdx;
- int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_a;
- int m_b;
- u32 m_idx;
-}Elem;
-
-
-
-
-
-// batching on the GPU
-__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )
-{
- int wgIdx = GET_GROUP_IDX;
- int lIdx = GET_LOCAL_IDX;
-
- const int m_n = gN[wgIdx];
- const int m_start = gStart[wgIdx];
-
- if( lIdx == 0 )
- {
- for (int i=0;i<m_n;i++)
- {
- int srcIdx = i+m_start;
- int batchIndex = i;
- gConstraints[ srcIdx ].m_batchIdx = batchIndex;
- }
- }
-}
-
-
-#define CHECK_SIZE (WG_SIZE)
-
-
-
-
-u32 readBuf(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
- return buff[bufIdx] & (1<<bitIdx);
-}
-
-void writeBuf(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
- buff[bufIdx] |= (1<<bitIdx);
- //atom_or( &buff[bufIdx], (1<<bitIdx) );
-}
-
-u32 tryWrite(__local u32* buff, int idx)
-{
- idx = idx % (32*CHECK_SIZE);
- int bitIdx = idx%32;
- int bufIdx = idx/32;
- u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );
- return ((ans >> bitIdx)&1) == 0;
-}
-
-
-// batching on the GPU
-__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )
-{
- int wgIdx = GET_GROUP_IDX;
- int lIdx = GET_LOCAL_IDX;
- const int numConstraints = gN[wgIdx];
- const int m_start = gStart[wgIdx];
- b3Contact4Data_t tmp;
-
- __local u32 ldsFixedBuffer[CHECK_SIZE];
-
-
-
-
-
- if( lIdx == 0 )
- {
-
-
- __global struct b3Contact4Data* cs = &gConstraints[m_start];
-
-
- int numValidConstraints = 0;
- int batchIdx = 0;
-
- while( numValidConstraints < numConstraints)
- {
- int nCurrentBatch = 0;
- // clear flag
-
- for(int i=0; i<CHECK_SIZE; i++)
- ldsFixedBuffer[i] = 0;
-
- for(int i=numValidConstraints; i<numConstraints; i++)
- {
-
- int bodyAS = cs[i].m_bodyAPtrAndSignBit;
- int bodyBS = cs[i].m_bodyBPtrAndSignBit;
- int bodyA = abs(bodyAS);
- int bodyB = abs(bodyBS);
- bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;
- bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;
- int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);
- int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);
-
- if( aUnavailable==0 && bUnavailable==0 ) // ok
- {
- if (!aIsStatic)
- {
- writeBuf( ldsFixedBuffer, bodyA );
- }
- if (!bIsStatic)
- {
- writeBuf( ldsFixedBuffer, bodyB );
- }
-
- cs[i].m_batchIdx = batchIdx;
-
- if (i!=numValidConstraints)
- {
-
- tmp = cs[i];
- cs[i] = cs[numValidConstraints];
- cs[numValidConstraints] = tmp;
-
-
- }
-
- numValidConstraints++;
-
- nCurrentBatch++;
- if( nCurrentBatch == SIMD_WIDTH)
- {
- nCurrentBatch = 0;
- for(int i=0; i<CHECK_SIZE; i++)
- ldsFixedBuffer[i] = 0;
-
- }
- }
- }//for
- batchIdx ++;
- }//while
-
- batchSizes[wgIdx] = batchIdx;
-
- }//if( lIdx == 0 )
-
- //return batchIdx;
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
deleted file mode 100644
index 05800656cb..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/batchingKernelsNew.h
+++ /dev/null
@@ -1,290 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* batchingKernelsNewCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Erwin Coumans\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile __global int*\n"
- "#endif\n"
- "#define SIMD_WIDTH 64\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "#define WG_SIZE 64\n"
- "typedef struct \n"
- "{\n"
- " int m_n;\n"
- " int m_start;\n"
- " int m_staticIdx;\n"
- " int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct \n"
- "{\n"
- " int m_a;\n"
- " int m_b;\n"
- " u32 m_idx;\n"
- "}Elem;\n"
- "// batching on the GPU\n"
- "__kernel void CreateBatchesBruteForce( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, int m_staticIdx )\n"
- "{\n"
- " int wgIdx = GET_GROUP_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " \n"
- " const int m_n = gN[wgIdx];\n"
- " const int m_start = gStart[wgIdx];\n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " for (int i=0;i<m_n;i++)\n"
- " {\n"
- " int srcIdx = i+m_start;\n"
- " int batchIndex = i;\n"
- " gConstraints[ srcIdx ].m_batchIdx = batchIndex; \n"
- " }\n"
- " }\n"
- "}\n"
- "#define CHECK_SIZE (WG_SIZE)\n"
- "u32 readBuf(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- " return buff[bufIdx] & (1<<bitIdx);\n"
- "}\n"
- "void writeBuf(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- " buff[bufIdx] |= (1<<bitIdx);\n"
- " //atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
- "}\n"
- "u32 tryWrite(__local u32* buff, int idx)\n"
- "{\n"
- " idx = idx % (32*CHECK_SIZE);\n"
- " int bitIdx = idx%32;\n"
- " int bufIdx = idx/32;\n"
- " u32 ans = (u32)atom_or( &buff[bufIdx], (1<<bitIdx) );\n"
- " return ((ans >> bitIdx)&1) == 0;\n"
- "}\n"
- "// batching on the GPU\n"
- "__kernel void CreateBatchesNew( __global struct b3Contact4Data* gConstraints, __global const u32* gN, __global const u32* gStart, __global int* batchSizes, int staticIdx )\n"
- "{\n"
- " int wgIdx = GET_GROUP_IDX;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " const int numConstraints = gN[wgIdx];\n"
- " const int m_start = gStart[wgIdx];\n"
- " b3Contact4Data_t tmp;\n"
- " \n"
- " __local u32 ldsFixedBuffer[CHECK_SIZE];\n"
- " \n"
- " \n"
- " \n"
- " \n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " \n"
- " \n"
- " __global struct b3Contact4Data* cs = &gConstraints[m_start]; \n"
- " \n"
- " \n"
- " int numValidConstraints = 0;\n"
- " int batchIdx = 0;\n"
- " while( numValidConstraints < numConstraints)\n"
- " {\n"
- " int nCurrentBatch = 0;\n"
- " // clear flag\n"
- " \n"
- " for(int i=0; i<CHECK_SIZE; i++) \n"
- " ldsFixedBuffer[i] = 0; \n"
- " for(int i=numValidConstraints; i<numConstraints; i++)\n"
- " {\n"
- " int bodyAS = cs[i].m_bodyAPtrAndSignBit;\n"
- " int bodyBS = cs[i].m_bodyBPtrAndSignBit;\n"
- " int bodyA = abs(bodyAS);\n"
- " int bodyB = abs(bodyBS);\n"
- " bool aIsStatic = (bodyAS<0) || bodyAS==staticIdx;\n"
- " bool bIsStatic = (bodyBS<0) || bodyBS==staticIdx;\n"
- " int aUnavailable = aIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyA);\n"
- " int bUnavailable = bIsStatic ? 0 : readBuf( ldsFixedBuffer, bodyB);\n"
- " \n"
- " if( aUnavailable==0 && bUnavailable==0 ) // ok\n"
- " {\n"
- " if (!aIsStatic)\n"
- " {\n"
- " writeBuf( ldsFixedBuffer, bodyA );\n"
- " }\n"
- " if (!bIsStatic)\n"
- " {\n"
- " writeBuf( ldsFixedBuffer, bodyB );\n"
- " }\n"
- " cs[i].m_batchIdx = batchIdx;\n"
- " if (i!=numValidConstraints)\n"
- " {\n"
- " tmp = cs[i];\n"
- " cs[i] = cs[numValidConstraints];\n"
- " cs[numValidConstraints] = tmp;\n"
- " }\n"
- " numValidConstraints++;\n"
- " \n"
- " nCurrentBatch++;\n"
- " if( nCurrentBatch == SIMD_WIDTH)\n"
- " {\n"
- " nCurrentBatch = 0;\n"
- " for(int i=0; i<CHECK_SIZE; i++) \n"
- " ldsFixedBuffer[i] = 0;\n"
- " \n"
- " }\n"
- " }\n"
- " }//for\n"
- " batchIdx ++;\n"
- " }//while\n"
- " \n"
- " batchSizes[wgIdx] = batchIdx;\n"
- " }//if( lIdx == 0 )\n"
- " \n"
- " //return batchIdx;\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
deleted file mode 100644
index e22bc9bc33..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.cl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3RigidBodyData.h"
-
-#include "Bullet3Dynamics/shared/b3IntegrateTransforms.h"
-
-
-
-__kernel void
- integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)
-{
- int nodeID = get_global_id(0);
-
- if( nodeID < numNodes)
- {
- integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
deleted file mode 100644
index 6e9c53e161..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/integrateKernel.h
+++ /dev/null
@@ -1,432 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* integrateKernelCL =
- "/*\n"
- "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Erwin Coumans\n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#define B3_RIGIDBODY_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
- "struct b3RigidBodyData\n"
- "{\n"
- " b3Float4 m_pos;\n"
- " b3Quat m_quat;\n"
- " b3Float4 m_linVel;\n"
- " b3Float4 m_angVel;\n"
- " int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "};\n"
- "typedef struct b3InertiaData b3InertiaData_t;\n"
- "struct b3InertiaData\n"
- "{\n"
- " b3Mat3x3 m_invInertiaWorld;\n"
- " b3Mat3x3 m_initInvInertia;\n"
- "};\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "inline void integrateSingleTransform( __global b3RigidBodyData_t* bodies,int nodeID, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
- "{\n"
- " \n"
- " if (bodies[nodeID].m_invMass != 0.f)\n"
- " {\n"
- " float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
- " //angular velocity\n"
- " {\n"
- " b3Float4 axis;\n"
- " //add some hardcoded angular damping\n"
- " bodies[nodeID].m_angVel.x *= angularDamping;\n"
- " bodies[nodeID].m_angVel.y *= angularDamping;\n"
- " bodies[nodeID].m_angVel.z *= angularDamping;\n"
- " \n"
- " b3Float4 angvel = bodies[nodeID].m_angVel;\n"
- " float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
- " \n"
- " //limit the angular motion\n"
- " if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
- " {\n"
- " fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
- " }\n"
- " if(fAngle < 0.001f)\n"
- " {\n"
- " // use Taylor's expansions of sync function\n"
- " axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
- " }\n"
- " else\n"
- " {\n"
- " // sync(fAngle) = sin(c*fAngle)/t\n"
- " axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
- " }\n"
- " \n"
- " b3Quat dorn;\n"
- " dorn.x = axis.x;\n"
- " dorn.y = axis.y;\n"
- " dorn.z = axis.z;\n"
- " dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
- " b3Quat orn0 = bodies[nodeID].m_quat;\n"
- " b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
- " predictedOrn = b3QuatNormalized(predictedOrn);\n"
- " bodies[nodeID].m_quat=predictedOrn;\n"
- " }\n"
- " //linear velocity \n"
- " bodies[nodeID].m_pos += bodies[nodeID].m_linVel * timeStep;\n"
- " \n"
- " //apply gravity\n"
- " bodies[nodeID].m_linVel += gravityAcceleration * timeStep;\n"
- " \n"
- " }\n"
- " \n"
- "}\n"
- "inline void b3IntegrateTransform( __global b3RigidBodyData_t* body, float timeStep, float angularDamping, b3Float4ConstArg gravityAcceleration)\n"
- "{\n"
- " float BT_GPU_ANGULAR_MOTION_THRESHOLD = (0.25f * 3.14159254f);\n"
- " \n"
- " if( (body->m_invMass != 0.f))\n"
- " {\n"
- " //angular velocity\n"
- " {\n"
- " b3Float4 axis;\n"
- " //add some hardcoded angular damping\n"
- " body->m_angVel.x *= angularDamping;\n"
- " body->m_angVel.y *= angularDamping;\n"
- " body->m_angVel.z *= angularDamping;\n"
- " \n"
- " b3Float4 angvel = body->m_angVel;\n"
- " float fAngle = b3Sqrt(b3Dot3F4(angvel, angvel));\n"
- " //limit the angular motion\n"
- " if(fAngle*timeStep > BT_GPU_ANGULAR_MOTION_THRESHOLD)\n"
- " {\n"
- " fAngle = BT_GPU_ANGULAR_MOTION_THRESHOLD / timeStep;\n"
- " }\n"
- " if(fAngle < 0.001f)\n"
- " {\n"
- " // use Taylor's expansions of sync function\n"
- " axis = angvel * (0.5f*timeStep-(timeStep*timeStep*timeStep)*0.020833333333f * fAngle * fAngle);\n"
- " }\n"
- " else\n"
- " {\n"
- " // sync(fAngle) = sin(c*fAngle)/t\n"
- " axis = angvel * ( b3Sin(0.5f * fAngle * timeStep) / fAngle);\n"
- " }\n"
- " b3Quat dorn;\n"
- " dorn.x = axis.x;\n"
- " dorn.y = axis.y;\n"
- " dorn.z = axis.z;\n"
- " dorn.w = b3Cos(fAngle * timeStep * 0.5f);\n"
- " b3Quat orn0 = body->m_quat;\n"
- " b3Quat predictedOrn = b3QuatMul(dorn, orn0);\n"
- " predictedOrn = b3QuatNormalized(predictedOrn);\n"
- " body->m_quat=predictedOrn;\n"
- " }\n"
- " //apply gravity\n"
- " body->m_linVel += gravityAcceleration * timeStep;\n"
- " //linear velocity \n"
- " body->m_pos += body->m_linVel * timeStep;\n"
- " \n"
- " }\n"
- " \n"
- "}\n"
- "__kernel void \n"
- " integrateTransformsKernel( __global b3RigidBodyData_t* bodies,const int numNodes, float timeStep, float angularDamping, float4 gravityAcceleration)\n"
- "{\n"
- " int nodeID = get_global_id(0);\n"
- " \n"
- " if( nodeID < numNodes)\n"
- " {\n"
- " integrateSingleTransform(bodies,nodeID, timeStep, angularDamping,gravityAcceleration);\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl
deleted file mode 100644
index 7f5dabe274..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.cl
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#define B3_CONSTRAINT_FLAG_ENABLED 1
-
-#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3
-#define B3_GPU_FIXED_CONSTRAINT_TYPE 4
-
-#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails
-#define B3_INFINITY 1e30f
-
-#define mymake_float4 (float4)
-
-
-__inline float dot3F4(float4 a, float4 b)
-{
- float4 a1 = mymake_float4(a.xyz,0.f);
- float4 b1 = mymake_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-
-typedef float4 Quaternion;
-
-
-typedef struct
-{
- float4 m_row[3];
-}Matrix3x3;
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b);
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b);
-
-
-
-
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b)
-{
- float4 ans;
- ans.x = dot3F4( a.m_row[0], b );
- ans.y = dot3F4( a.m_row[1], b );
- ans.z = dot3F4( a.m_row[2], b );
- ans.w = 0.f;
- return ans;
-}
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b)
-{
- float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- float4 ans;
- ans.x = dot3F4( a, colx );
- ans.y = dot3F4( a, coly );
- ans.z = dot3F4( a, colz );
- return ans;
-}
-
-
-
-typedef struct
-{
- Matrix3x3 m_invInertiaWorld;
- Matrix3x3 m_initInvInertia;
-} BodyInertia;
-
-
-typedef struct
-{
- Matrix3x3 m_basis;//orientation
- float4 m_origin;//transform
-}b3Transform;
-
-typedef struct
-{
-// b3Transform m_worldTransformUnused;
- float4 m_deltaLinearVelocity;
- float4 m_deltaAngularVelocity;
- float4 m_angularFactor;
- float4 m_linearFactor;
- float4 m_invMass;
- float4 m_pushVelocity;
- float4 m_turnVelocity;
- float4 m_linearVelocity;
- float4 m_angularVelocity;
-
- union
- {
- void* m_originalBody;
- int m_originalBodyIndex;
- };
- int padding[3];
-
-} b3GpuSolverBody;
-
-typedef struct
-{
- float4 m_pos;
- Quaternion m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- unsigned int m_shapeIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} b3RigidBodyCL;
-
-typedef struct
-{
-
- float4 m_relpos1CrossNormal;
- float4 m_contactNormal;
-
- float4 m_relpos2CrossNormal;
- //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal
-
- float4 m_angularComponentA;
- float4 m_angularComponentB;
-
- float m_appliedPushImpulse;
- float m_appliedImpulse;
- int m_padding1;
- int m_padding2;
- float m_friction;
- float m_jacDiagABInv;
- float m_rhs;
- float m_cfm;
-
- float m_lowerLimit;
- float m_upperLimit;
- float m_rhsPenetration;
- int m_originalConstraint;
-
-
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
- int m_solverBodyIdA;
- int m_solverBodyIdB;
-
-} b3SolverConstraint;
-
-typedef struct
-{
- int m_bodyAPtrAndSignBit;
- int m_bodyBPtrAndSignBit;
- int m_originalConstraintIndex;
- int m_batchId;
-} b3BatchConstraint;
-
-
-
-
-
-
-typedef struct
-{
- int m_constraintType;
- int m_rbA;
- int m_rbB;
- float m_breakingImpulseThreshold;
-
- float4 m_pivotInA;
- float4 m_pivotInB;
- Quaternion m_relTargetAB;
-
- int m_flags;
- int m_padding[3];
-} b3GpuGenericConstraint;
-
-
-/*b3Transform getWorldTransform(b3RigidBodyCL* rb)
-{
- b3Transform newTrans;
- newTrans.setOrigin(rb->m_pos);
- newTrans.setRotation(rb->m_quat);
- return newTrans;
-}*/
-
-
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- v = mymake_float4(v.xyz,0.f);
- return fast_normalize(v);
-}
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-
-__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)
-{
- body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;
- body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);
-}
-
-
-void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)
-{
- float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;
- float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);
- float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);
-
- deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;
-
- float sum = c->m_appliedImpulse + deltaImpulse;
- if (sum < c->m_lowerLimit)
- {
- deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;
- c->m_appliedImpulse = c->m_lowerLimit;
- }
- else if (sum > c->m_upperLimit)
- {
- deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;
- c->m_appliedImpulse = c->m_upperLimit;
- }
- else
- {
- c->m_appliedImpulse = sum;
- }
-
- internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);
- internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);
-
-}
-
-__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,
- __global b3BatchConstraint* batchConstraints,
- __global b3SolverConstraint* rows,
- __global unsigned int* numConstraintRowsInfo1,
- __global unsigned int* rowOffsets,
- __global b3GpuGenericConstraint* constraints,
- int batchOffset,
- int numConstraintsInBatch
- )
-{
- int b = get_global_id(0);
- if (b>=numConstraintsInBatch)
- return;
-
- __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];
- int originalConstraintIndex = c->m_originalConstraintIndex;
- if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)
- {
- int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];
- int rowOffset = rowOffsets[originalConstraintIndex];
- for (int jj=0;jj<numConstraintRows;jj++)
- {
- __global b3SolverConstraint* constraint = &rows[rowOffset+jj];
- resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);
- }
- }
-};
-
-__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)
-{
- int i = get_global_id(0);
- if (i>=numBodies)
- return;
-
- __global b3GpuSolverBody* solverBody = &solverBodies[i];
- __global b3RigidBodyCL* bodyCL = &bodiesCL[i];
-
- solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);
- solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);
- solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
- solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);
- solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);
- solverBody->m_originalBodyIndex = i;
- solverBody->m_angularFactor = (float4)(1,1,1,0);
- solverBody->m_linearFactor = (float4) (1,1,1,0);
- solverBody->m_linearVelocity = bodyCL->m_linVel;
- solverBody->m_angularVelocity = bodyCL->m_angVel;
-}
-
-__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)
-{
- int cid = get_global_id(0);
- if (cid>=numConstraints)
- return;
- int numRows = numConstraintRows[cid];
- if (numRows)
- {
- for (int i=0;i<numRows;i++)
- {
- int rowIndex = rowOffsets[cid]+i;
- float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;
- if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)
- {
- constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;
- }
- }
- }
-}
-
-
-
-__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)
-{
- int i = get_global_id(0);
- if (i>=numConstraints)
- return;
-
- __global b3GpuGenericConstraint* constraint = &constraints[i];
-
- switch (constraint->m_constraintType)
- {
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
- {
- infos[i] = 3;
- break;
- }
- case B3_GPU_FIXED_CONSTRAINT_TYPE:
- {
- infos[i] = 6;
- break;
- }
- default:
- {
- }
- }
-}
-
-__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets,
- __global b3BatchConstraint* batchConstraints,
- __global b3GpuGenericConstraint* constraints,
- __global b3RigidBodyCL* bodies,
- int numConstraints)
-{
- int i = get_global_id(0);
- if (i>=numConstraints)
- return;
-
- int rbA = constraints[i].m_rbA;
- int rbB = constraints[i].m_rbB;
-
- batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;
- batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;
- batchConstraints[i].m_batchId = -1;
- batchConstraints[i].m_originalConstraintIndex = i;
-
-}
-
-
-
-
-typedef struct
-{
- // integrator parameters: frames per second (1/stepsize), default error
- // reduction parameter (0..1).
- float fps,erp;
-
- // for the first and second body, pointers to two (linear and angular)
- // n*3 jacobian sub matrices, stored by rows. these matrices will have
- // been initialized to 0 on entry. if the second body is zero then the
- // J2xx pointers may be 0.
- union
- {
- __global float4* m_J1linearAxisFloat4;
- __global float* m_J1linearAxis;
- };
- union
- {
- __global float4* m_J1angularAxisFloat4;
- __global float* m_J1angularAxis;
-
- };
- union
- {
- __global float4* m_J2linearAxisFloat4;
- __global float* m_J2linearAxis;
- };
- union
- {
- __global float4* m_J2angularAxisFloat4;
- __global float* m_J2angularAxis;
- };
- // elements to jump from one row to the next in J's
- int rowskip;
-
- // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
- // "constraint force mixing" vector. c is set to zero on entry, cfm is
- // set to a constant value (typically very small or zero) value on entry.
- __global float* m_constraintError;
- __global float* cfm;
-
- // lo and hi limits for variables (set to -/+ infinity on entry).
- __global float* m_lowerLimit;
- __global float* m_upperLimit;
-
- // findex vector for variables. see the LCP solver interface for a
- // description of what this does. this is set to -1 on entry.
- // note that the returned indexes are relative to the first index of
- // the constraint.
- __global int *findex;
- // number of solver iterations
- int m_numIterations;
-
- //damping of the velocity
- float m_damping;
-} b3GpuConstraintInfo2;
-
-
-void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)
-{
- *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);
- *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);
- *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);
-}
-
-
-void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)
-{
- float4 posA = bodies[constraint->m_rbA].m_pos;
- Quaternion rotA = bodies[constraint->m_rbA].m_quat;
-
- float4 posB = bodies[constraint->m_rbB].m_pos;
- Quaternion rotB = bodies[constraint->m_rbB].m_quat;
-
-
-
- // anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip+1] = 1;
- info->m_J1linearAxis[2*info->rowskip+2] = 1;
-
- float4 a1 = qtRotate(rotA,constraint->m_pivotInA);
-
- {
- __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);
- __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);
- __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);
- float4 a1neg = -a1;
- getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);
- }
- if (info->m_J2linearAxis)
- {
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip+1] = -1;
- info->m_J2linearAxis[2*info->rowskip+2] = -1;
- }
-
- float4 a2 = qtRotate(rotB,constraint->m_pivotInB);
-
- {
- // float4 a2n = -a2;
- __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);
- __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);
- __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);
- getSkewSymmetricMatrix(a2,angular0,angular1,angular2);
- }
-
- // set right hand side
-// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;
- float currERP = info->erp;
-
- float k = info->fps * currERP;
- int j;
- float4 result = a2 + posB - a1 - posA;
- float* resultPtr = &result;
-
- for (j=0; j<3; j++)
- {
- info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);
- }
-}
-
-Quaternion nearest( Quaternion first, Quaternion qd)
-{
- Quaternion diff,sum;
- diff = first- qd;
- sum = first + qd;
-
- if( dot(diff,diff) < dot(sum,sum) )
- return qd;
- return (-qd);
-}
-
-float b3Acos(float x)
-{
- if (x<-1)
- x=-1;
- if (x>1)
- x=1;
- return acos(x);
-}
-
-float getAngle(Quaternion orn)
-{
- if (orn.w>=1.f)
- orn.w=1.f;
- float s = 2.f * b3Acos(orn.w);
- return s;
-}
-
-void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)
-{
- Quaternion orn1 = nearest(orn0,orn1a);
-
- Quaternion dorn = qtMul(orn1,qtInvert(orn0));
- *angle = getAngle(dorn);
- *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);
-
- //check for axis length
- float len = dot3F4(*axis,*axis);
- if (len < FLT_EPSILON*FLT_EPSILON)
- *axis = (float4)(1,0,0,0);
- else
- *axis /= sqrt(len);
-}
-
-
-
-void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)
-{
- Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;
- Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;
-
- int s = info->rowskip;
- int start_index = start_row * s;
-
- // 3 rows to make body rotations equal
- info->m_J1angularAxis[start_index] = 1;
- info->m_J1angularAxis[start_index + s + 1] = 1;
- info->m_J1angularAxis[start_index + s*2+2] = 1;
- if ( info->m_J2angularAxis)
- {
- info->m_J2angularAxis[start_index] = -1;
- info->m_J2angularAxis[start_index + s+1] = -1;
- info->m_J2angularAxis[start_index + s*2+2] = -1;
- }
-
- float currERP = info->erp;
- float k = info->fps * currERP;
- float4 diff;
- float angle;
- float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));
-
- calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);
- diff*=-angle;
-
- float* resultPtr = &diff;
-
- for (int j=0; j<3; j++)
- {
- info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];
- }
-
-
-}
-
-
-__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)
-{
- int i = get_global_id(0);
- if (i>=numBodies)
- return;
-
- if (bodies[i].m_invMass)
- {
-// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)
- {
- bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;
- }
-// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)
- {
- bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;
- }
- }
-}
-
-
-__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows,
- __global unsigned int* infos,
- __global unsigned int* constraintRowOffsets,
- __global b3GpuGenericConstraint* constraints,
- __global b3BatchConstraint* batchConstraints,
- __global b3RigidBodyCL* bodies,
- __global BodyInertia* inertias,
- __global b3GpuSolverBody* solverBodies,
- float timeStep,
- float globalErp,
- float globalCfm,
- float globalDamping,
- int globalNumIterations,
- int numConstraints)
-{
-
- int i = get_global_id(0);
- if (i>=numConstraints)
- return;
-
- //for now, always initialize the batch info
- int info1 = infos[i];
-
- __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];
- __global b3GpuGenericConstraint* constraint = &constraints[i];
-
- __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];
- __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];
-
- int solverBodyIdA = constraint->m_rbA;
- int solverBodyIdB = constraint->m_rbB;
-
- __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];
- __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];
-
-
- if (rbA->m_invMass)
- {
- batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;
- } else
- {
-// if (!solverBodyIdA)
-// m_staticIdx = 0;
- batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;
- }
-
- if (rbB->m_invMass)
- {
- batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;
- } else
- {
-// if (!solverBodyIdB)
-// m_staticIdx = 0;
- batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;
- }
-
- if (info1)
- {
- int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
-// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)
- // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
-
- int j;
- for ( j=0;j<info1;j++)
- {
-// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));
- currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);
- currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_cfm = 0.f;
- currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);
- currentConstraintRow[j].m_friction = 0.f;
- currentConstraintRow[j].m_frictionIndex = 0;
- currentConstraintRow[j].m_jacDiagABInv = 0.f;
- currentConstraintRow[j].m_lowerLimit = 0.f;
- currentConstraintRow[j].m_upperLimit = 0.f;
-
- currentConstraintRow[j].m_originalConstraint = i;
- currentConstraintRow[j].m_overrideNumSolverIterations = 0;
- currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);
- currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);
- currentConstraintRow[j].m_rhs = 0.f;
- currentConstraintRow[j].m_rhsPenetration = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = 0;
- currentConstraintRow[j].m_solverBodyIdB = 0;
-
- currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;
- currentConstraintRow[j].m_upperLimit = B3_INFINITY;
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
- currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
- currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
- }
-
- bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
- bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
- bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);
- bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);
- bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);
- bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);
- bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);
- bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);
-
- int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
-
-
-
-
- b3GpuConstraintInfo2 info2;
- info2.fps = 1.f/timeStep;
- info2.erp = globalErp;
- info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;
- info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxisFloat4 = 0;
- info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this
-
- ///the size of b3SolverConstraint needs be a multiple of float
-// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));
- info2.m_constraintError = &currentConstraintRow->m_rhs;
- currentConstraintRow->m_cfm = globalCfm;
- info2.m_damping = globalDamping;
- info2.cfm = &currentConstraintRow->m_cfm;
- info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
- info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
- info2.m_numIterations = globalNumIterations;
-
- switch (constraint->m_constraintType)
- {
- case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:
- {
- getInfo2Point2Point(constraint,&info2,bodies);
- break;
- }
- case B3_GPU_FIXED_CONSTRAINT_TYPE:
- {
- getInfo2Point2Point(constraint,&info2,bodies);
-
- getInfo2FixedOrientation(constraint,&info2,bodies,3);
-
- break;
- }
-
- default:
- {
- }
- }
-
- ///finalize the constraint setup
- for ( j=0;j<info1;j++)
- {
- __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];
-
- if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)
- {
- solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;
- }
-
- if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)
- {
- solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;
- }
-
-// solverConstraint->m_originalContactPoint = constraint;
-
- Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;
- {
-
- //float4 angularFactorA(1,1,1);
- float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;
- solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;
- }
-
- Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;
- {
-
- float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;
- solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();
- }
-
- {
- //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal
- //because it gets multiplied iMJlB
- float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;
- float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);
- float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?
- float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);
-
- float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);
- sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);
- sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);
- sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);
- float fsum = fabs(sum);
- if (fsum>FLT_EPSILON)
- {
- solverConstraint->m_jacDiagABInv = 1.f/sum;
- } else
- {
- solverConstraint->m_jacDiagABInv = 0.f;
- }
- }
-
-
- ///fix rhs
- ///todo: add force/torque accelerators
- {
- float rel_vel;
- float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);
- float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);
-
- rel_vel = vel1Dotn+vel2Dotn;
-
- float restitution = 0.f;
- float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2
- float velocityError = restitution - rel_vel * info2.m_damping;
- float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;
- float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;
- solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;
- solverConstraint->m_appliedImpulse = 0.f;
-
- }
- }
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
deleted file mode 100644
index c94b55851e..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/jointSolver.h
+++ /dev/null
@@ -1,720 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveConstraintRowsCL =
- "/*\n"
- "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Erwin Coumans\n"
- "#define B3_CONSTRAINT_FLAG_ENABLED 1\n"
- "#define B3_GPU_POINT2POINT_CONSTRAINT_TYPE 3\n"
- "#define B3_GPU_FIXED_CONSTRAINT_TYPE 4\n"
- "#define MOTIONCLAMP 100000 //unused, for debugging/safety in case constraint solver fails\n"
- "#define B3_INFINITY 1e30f\n"
- "#define mymake_float4 (float4)\n"
- "__inline float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = mymake_float4(a.xyz,0.f);\n"
- " float4 b1 = mymake_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "typedef float4 Quaternion;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_row[3];\n"
- "}Matrix3x3;\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b);\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b);\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b)\n"
- "{\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a.m_row[0], b );\n"
- " ans.y = dot3F4( a.m_row[1], b );\n"
- " ans.z = dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b)\n"
- "{\n"
- " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a, colx );\n"
- " ans.y = dot3F4( a, coly );\n"
- " ans.z = dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_invInertiaWorld;\n"
- " Matrix3x3 m_initInvInertia;\n"
- "} BodyInertia;\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_basis;//orientation\n"
- " float4 m_origin;//transform\n"
- "}b3Transform;\n"
- "typedef struct\n"
- "{\n"
- "// b3Transform m_worldTransformUnused;\n"
- " float4 m_deltaLinearVelocity;\n"
- " float4 m_deltaAngularVelocity;\n"
- " float4 m_angularFactor;\n"
- " float4 m_linearFactor;\n"
- " float4 m_invMass;\n"
- " float4 m_pushVelocity;\n"
- " float4 m_turnVelocity;\n"
- " float4 m_linearVelocity;\n"
- " float4 m_angularVelocity;\n"
- " union \n"
- " {\n"
- " void* m_originalBody;\n"
- " int m_originalBodyIndex;\n"
- " };\n"
- " int padding[3];\n"
- "} b3GpuSolverBody;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " Quaternion m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " unsigned int m_shapeIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} b3RigidBodyCL;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_relpos1CrossNormal;\n"
- " float4 m_contactNormal;\n"
- " float4 m_relpos2CrossNormal;\n"
- " //float4 m_contactNormal2;//usually m_contactNormal2 == -m_contactNormal\n"
- " float4 m_angularComponentA;\n"
- " float4 m_angularComponentB;\n"
- " \n"
- " float m_appliedPushImpulse;\n"
- " float m_appliedImpulse;\n"
- " int m_padding1;\n"
- " int m_padding2;\n"
- " float m_friction;\n"
- " float m_jacDiagABInv;\n"
- " float m_rhs;\n"
- " float m_cfm;\n"
- " \n"
- " float m_lowerLimit;\n"
- " float m_upperLimit;\n"
- " float m_rhsPenetration;\n"
- " int m_originalConstraint;\n"
- " int m_overrideNumSolverIterations;\n"
- " int m_frictionIndex;\n"
- " int m_solverBodyIdA;\n"
- " int m_solverBodyIdB;\n"
- "} b3SolverConstraint;\n"
- "typedef struct \n"
- "{\n"
- " int m_bodyAPtrAndSignBit;\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_originalConstraintIndex;\n"
- " int m_batchId;\n"
- "} b3BatchConstraint;\n"
- "typedef struct \n"
- "{\n"
- " int m_constraintType;\n"
- " int m_rbA;\n"
- " int m_rbB;\n"
- " float m_breakingImpulseThreshold;\n"
- " float4 m_pivotInA;\n"
- " float4 m_pivotInB;\n"
- " Quaternion m_relTargetAB;\n"
- " int m_flags;\n"
- " int m_padding[3];\n"
- "} b3GpuGenericConstraint;\n"
- "/*b3Transform getWorldTransform(b3RigidBodyCL* rb)\n"
- "{\n"
- " b3Transform newTrans;\n"
- " newTrans.setOrigin(rb->m_pos);\n"
- " newTrans.setRotation(rb->m_quat);\n"
- " return newTrans;\n"
- "}*/\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " v = mymake_float4(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline void internalApplyImpulse(__global b3GpuSolverBody* body, float4 linearComponent, float4 angularComponent,float impulseMagnitude)\n"
- "{\n"
- " body->m_deltaLinearVelocity += linearComponent*impulseMagnitude*body->m_linearFactor;\n"
- " body->m_deltaAngularVelocity += angularComponent*(impulseMagnitude*body->m_angularFactor);\n"
- "}\n"
- "void resolveSingleConstraintRowGeneric(__global b3GpuSolverBody* body1, __global b3GpuSolverBody* body2, __global b3SolverConstraint* c)\n"
- "{\n"
- " float deltaImpulse = c->m_rhs-c->m_appliedImpulse*c->m_cfm;\n"
- " float deltaVel1Dotn = dot3F4(c->m_contactNormal,body1->m_deltaLinearVelocity) + dot3F4(c->m_relpos1CrossNormal,body1->m_deltaAngularVelocity);\n"
- " float deltaVel2Dotn = -dot3F4(c->m_contactNormal,body2->m_deltaLinearVelocity) + dot3F4(c->m_relpos2CrossNormal,body2->m_deltaAngularVelocity);\n"
- " deltaImpulse -= deltaVel1Dotn*c->m_jacDiagABInv;\n"
- " deltaImpulse -= deltaVel2Dotn*c->m_jacDiagABInv;\n"
- " float sum = c->m_appliedImpulse + deltaImpulse;\n"
- " if (sum < c->m_lowerLimit)\n"
- " {\n"
- " deltaImpulse = c->m_lowerLimit-c->m_appliedImpulse;\n"
- " c->m_appliedImpulse = c->m_lowerLimit;\n"
- " }\n"
- " else if (sum > c->m_upperLimit) \n"
- " {\n"
- " deltaImpulse = c->m_upperLimit-c->m_appliedImpulse;\n"
- " c->m_appliedImpulse = c->m_upperLimit;\n"
- " }\n"
- " else\n"
- " {\n"
- " c->m_appliedImpulse = sum;\n"
- " }\n"
- " internalApplyImpulse(body1,c->m_contactNormal*body1->m_invMass,c->m_angularComponentA,deltaImpulse);\n"
- " internalApplyImpulse(body2,-c->m_contactNormal*body2->m_invMass,c->m_angularComponentB,deltaImpulse);\n"
- "}\n"
- "__kernel void solveJointConstraintRows(__global b3GpuSolverBody* solverBodies,\n"
- " __global b3BatchConstraint* batchConstraints,\n"
- " __global b3SolverConstraint* rows,\n"
- " __global unsigned int* numConstraintRowsInfo1, \n"
- " __global unsigned int* rowOffsets,\n"
- " __global b3GpuGenericConstraint* constraints,\n"
- " int batchOffset,\n"
- " int numConstraintsInBatch\n"
- " )\n"
- "{\n"
- " int b = get_global_id(0);\n"
- " if (b>=numConstraintsInBatch)\n"
- " return;\n"
- " __global b3BatchConstraint* c = &batchConstraints[b+batchOffset];\n"
- " int originalConstraintIndex = c->m_originalConstraintIndex;\n"
- " if (constraints[originalConstraintIndex].m_flags&B3_CONSTRAINT_FLAG_ENABLED)\n"
- " {\n"
- " int numConstraintRows = numConstraintRowsInfo1[originalConstraintIndex];\n"
- " int rowOffset = rowOffsets[originalConstraintIndex];\n"
- " for (int jj=0;jj<numConstraintRows;jj++)\n"
- " {\n"
- " __global b3SolverConstraint* constraint = &rows[rowOffset+jj];\n"
- " resolveSingleConstraintRowGeneric(&solverBodies[constraint->m_solverBodyIdA],&solverBodies[constraint->m_solverBodyIdB],constraint);\n"
- " }\n"
- " }\n"
- "};\n"
- "__kernel void initSolverBodies(__global b3GpuSolverBody* solverBodies,__global b3RigidBodyCL* bodiesCL, int numBodies)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numBodies)\n"
- " return;\n"
- " __global b3GpuSolverBody* solverBody = &solverBodies[i];\n"
- " __global b3RigidBodyCL* bodyCL = &bodiesCL[i];\n"
- " solverBody->m_deltaLinearVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
- " solverBody->m_deltaAngularVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
- " solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
- " solverBody->m_pushVelocity = (float4)(0.f,0.f,0.f,0.f);\n"
- " solverBody->m_invMass = (float4)(bodyCL->m_invMass,bodyCL->m_invMass,bodyCL->m_invMass,0.f);\n"
- " solverBody->m_originalBodyIndex = i;\n"
- " solverBody->m_angularFactor = (float4)(1,1,1,0);\n"
- " solverBody->m_linearFactor = (float4) (1,1,1,0);\n"
- " solverBody->m_linearVelocity = bodyCL->m_linVel;\n"
- " solverBody->m_angularVelocity = bodyCL->m_angVel;\n"
- "}\n"
- "__kernel void breakViolatedConstraintsKernel(__global b3GpuGenericConstraint* constraints, __global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, __global b3SolverConstraint* rows, int numConstraints)\n"
- "{\n"
- " int cid = get_global_id(0);\n"
- " if (cid>=numConstraints)\n"
- " return;\n"
- " int numRows = numConstraintRows[cid];\n"
- " if (numRows)\n"
- " {\n"
- " for (int i=0;i<numRows;i++)\n"
- " {\n"
- " int rowIndex = rowOffsets[cid]+i;\n"
- " float breakingThreshold = constraints[cid].m_breakingImpulseThreshold;\n"
- " if (fabs(rows[rowIndex].m_appliedImpulse) >= breakingThreshold)\n"
- " {\n"
- " constraints[cid].m_flags =0;//&= ~B3_CONSTRAINT_FLAG_ENABLED;\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void getInfo1Kernel(__global unsigned int* infos, __global b3GpuGenericConstraint* constraints, int numConstraints)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numConstraints)\n"
- " return;\n"
- " __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
- " switch (constraint->m_constraintType)\n"
- " {\n"
- " case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
- " {\n"
- " infos[i] = 3;\n"
- " break;\n"
- " }\n"
- " case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
- " {\n"
- " infos[i] = 6;\n"
- " break;\n"
- " }\n"
- " default:\n"
- " {\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel void initBatchConstraintsKernel(__global unsigned int* numConstraintRows, __global unsigned int* rowOffsets, \n"
- " __global b3BatchConstraint* batchConstraints, \n"
- " __global b3GpuGenericConstraint* constraints,\n"
- " __global b3RigidBodyCL* bodies,\n"
- " int numConstraints)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numConstraints)\n"
- " return;\n"
- " int rbA = constraints[i].m_rbA;\n"
- " int rbB = constraints[i].m_rbB;\n"
- " batchConstraints[i].m_bodyAPtrAndSignBit = bodies[rbA].m_invMass != 0.f ? rbA : -rbA;\n"
- " batchConstraints[i].m_bodyBPtrAndSignBit = bodies[rbB].m_invMass != 0.f ? rbB : -rbB;\n"
- " batchConstraints[i].m_batchId = -1;\n"
- " batchConstraints[i].m_originalConstraintIndex = i;\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " // integrator parameters: frames per second (1/stepsize), default error\n"
- " // reduction parameter (0..1).\n"
- " float fps,erp;\n"
- " // for the first and second body, pointers to two (linear and angular)\n"
- " // n*3 jacobian sub matrices, stored by rows. these matrices will have\n"
- " // been initialized to 0 on entry. if the second body is zero then the\n"
- " // J2xx pointers may be 0.\n"
- " union \n"
- " {\n"
- " __global float4* m_J1linearAxisFloat4;\n"
- " __global float* m_J1linearAxis;\n"
- " };\n"
- " union\n"
- " {\n"
- " __global float4* m_J1angularAxisFloat4;\n"
- " __global float* m_J1angularAxis;\n"
- " };\n"
- " union\n"
- " {\n"
- " __global float4* m_J2linearAxisFloat4;\n"
- " __global float* m_J2linearAxis;\n"
- " };\n"
- " union\n"
- " {\n"
- " __global float4* m_J2angularAxisFloat4;\n"
- " __global float* m_J2angularAxis;\n"
- " };\n"
- " // elements to jump from one row to the next in J's\n"
- " int rowskip;\n"
- " // right hand sides of the equation J*v = c + cfm * lambda. cfm is the\n"
- " // \"constraint force mixing\" vector. c is set to zero on entry, cfm is\n"
- " // set to a constant value (typically very small or zero) value on entry.\n"
- " __global float* m_constraintError;\n"
- " __global float* cfm;\n"
- " // lo and hi limits for variables (set to -/+ infinity on entry).\n"
- " __global float* m_lowerLimit;\n"
- " __global float* m_upperLimit;\n"
- " // findex vector for variables. see the LCP solver interface for a\n"
- " // description of what this does. this is set to -1 on entry.\n"
- " // note that the returned indexes are relative to the first index of\n"
- " // the constraint.\n"
- " __global int *findex;\n"
- " // number of solver iterations\n"
- " int m_numIterations;\n"
- " //damping of the velocity\n"
- " float m_damping;\n"
- "} b3GpuConstraintInfo2;\n"
- "void getSkewSymmetricMatrix(float4 vecIn, __global float4* v0,__global float4* v1,__global float4* v2)\n"
- "{\n"
- " *v0 = (float4)(0. ,-vecIn.z ,vecIn.y,0.f);\n"
- " *v1 = (float4)(vecIn.z ,0. ,-vecIn.x,0.f);\n"
- " *v2 = (float4)(-vecIn.y ,vecIn.x ,0.f,0.f);\n"
- "}\n"
- "void getInfo2Point2Point(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies)\n"
- "{\n"
- " float4 posA = bodies[constraint->m_rbA].m_pos;\n"
- " Quaternion rotA = bodies[constraint->m_rbA].m_quat;\n"
- " float4 posB = bodies[constraint->m_rbB].m_pos;\n"
- " Quaternion rotB = bodies[constraint->m_rbB].m_quat;\n"
- " // anchor points in global coordinates with respect to body PORs.\n"
- " \n"
- " // set jacobian\n"
- " info->m_J1linearAxis[0] = 1;\n"
- " info->m_J1linearAxis[info->rowskip+1] = 1;\n"
- " info->m_J1linearAxis[2*info->rowskip+2] = 1;\n"
- " float4 a1 = qtRotate(rotA,constraint->m_pivotInA);\n"
- " {\n"
- " __global float4* angular0 = (__global float4*)(info->m_J1angularAxis);\n"
- " __global float4* angular1 = (__global float4*)(info->m_J1angularAxis+info->rowskip);\n"
- " __global float4* angular2 = (__global float4*)(info->m_J1angularAxis+2*info->rowskip);\n"
- " float4 a1neg = -a1;\n"
- " getSkewSymmetricMatrix(a1neg,angular0,angular1,angular2);\n"
- " }\n"
- " if (info->m_J2linearAxis)\n"
- " {\n"
- " info->m_J2linearAxis[0] = -1;\n"
- " info->m_J2linearAxis[info->rowskip+1] = -1;\n"
- " info->m_J2linearAxis[2*info->rowskip+2] = -1;\n"
- " }\n"
- " \n"
- " float4 a2 = qtRotate(rotB,constraint->m_pivotInB);\n"
- " \n"
- " {\n"
- " // float4 a2n = -a2;\n"
- " __global float4* angular0 = (__global float4*)(info->m_J2angularAxis);\n"
- " __global float4* angular1 = (__global float4*)(info->m_J2angularAxis+info->rowskip);\n"
- " __global float4* angular2 = (__global float4*)(info->m_J2angularAxis+2*info->rowskip);\n"
- " getSkewSymmetricMatrix(a2,angular0,angular1,angular2);\n"
- " }\n"
- " \n"
- " // set right hand side\n"
- "// float currERP = (m_flags & B3_P2P_FLAGS_ERP) ? m_erp : info->erp;\n"
- " float currERP = info->erp;\n"
- " float k = info->fps * currERP;\n"
- " int j;\n"
- " float4 result = a2 + posB - a1 - posA;\n"
- " float* resultPtr = &result;\n"
- " for (j=0; j<3; j++)\n"
- " {\n"
- " info->m_constraintError[j*info->rowskip] = k * (resultPtr[j]);\n"
- " }\n"
- "}\n"
- "Quaternion nearest( Quaternion first, Quaternion qd)\n"
- "{\n"
- " Quaternion diff,sum;\n"
- " diff = first- qd;\n"
- " sum = first + qd;\n"
- " \n"
- " if( dot(diff,diff) < dot(sum,sum) )\n"
- " return qd;\n"
- " return (-qd);\n"
- "}\n"
- "float b3Acos(float x) \n"
- "{ \n"
- " if (x<-1) \n"
- " x=-1; \n"
- " if (x>1) \n"
- " x=1;\n"
- " return acos(x); \n"
- "}\n"
- "float getAngle(Quaternion orn)\n"
- "{\n"
- " if (orn.w>=1.f)\n"
- " orn.w=1.f;\n"
- " float s = 2.f * b3Acos(orn.w);\n"
- " return s;\n"
- "}\n"
- "void calculateDiffAxisAngleQuaternion( Quaternion orn0,Quaternion orn1a,float4* axis,float* angle)\n"
- "{\n"
- " Quaternion orn1 = nearest(orn0,orn1a);\n"
- " \n"
- " Quaternion dorn = qtMul(orn1,qtInvert(orn0));\n"
- " *angle = getAngle(dorn);\n"
- " *axis = (float4)(dorn.x,dorn.y,dorn.z,0.f);\n"
- " \n"
- " //check for axis length\n"
- " float len = dot3F4(*axis,*axis);\n"
- " if (len < FLT_EPSILON*FLT_EPSILON)\n"
- " *axis = (float4)(1,0,0,0);\n"
- " else\n"
- " *axis /= sqrt(len);\n"
- "}\n"
- "void getInfo2FixedOrientation(__global b3GpuGenericConstraint* constraint,b3GpuConstraintInfo2* info,__global b3RigidBodyCL* bodies, int start_row)\n"
- "{\n"
- " Quaternion worldOrnA = bodies[constraint->m_rbA].m_quat;\n"
- " Quaternion worldOrnB = bodies[constraint->m_rbB].m_quat;\n"
- " int s = info->rowskip;\n"
- " int start_index = start_row * s;\n"
- " // 3 rows to make body rotations equal\n"
- " info->m_J1angularAxis[start_index] = 1;\n"
- " info->m_J1angularAxis[start_index + s + 1] = 1;\n"
- " info->m_J1angularAxis[start_index + s*2+2] = 1;\n"
- " if ( info->m_J2angularAxis)\n"
- " {\n"
- " info->m_J2angularAxis[start_index] = -1;\n"
- " info->m_J2angularAxis[start_index + s+1] = -1;\n"
- " info->m_J2angularAxis[start_index + s*2+2] = -1;\n"
- " }\n"
- " \n"
- " float currERP = info->erp;\n"
- " float k = info->fps * currERP;\n"
- " float4 diff;\n"
- " float angle;\n"
- " float4 qrelCur = qtMul(worldOrnA,qtInvert(worldOrnB));\n"
- " \n"
- " calculateDiffAxisAngleQuaternion(constraint->m_relTargetAB,qrelCur,&diff,&angle);\n"
- " diff*=-angle;\n"
- " \n"
- " float* resultPtr = &diff;\n"
- " \n"
- " for (int j=0; j<3; j++)\n"
- " {\n"
- " info->m_constraintError[(3+j)*info->rowskip] = k * resultPtr[j];\n"
- " }\n"
- " \n"
- "}\n"
- "__kernel void writeBackVelocitiesKernel(__global b3RigidBodyCL* bodies,__global b3GpuSolverBody* solverBodies,int numBodies)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numBodies)\n"
- " return;\n"
- " if (bodies[i].m_invMass)\n"
- " {\n"
- "// if (length(solverBodies[i].m_deltaLinearVelocity)<MOTIONCLAMP)\n"
- " {\n"
- " bodies[i].m_linVel += solverBodies[i].m_deltaLinearVelocity;\n"
- " }\n"
- "// if (length(solverBodies[i].m_deltaAngularVelocity)<MOTIONCLAMP)\n"
- " {\n"
- " bodies[i].m_angVel += solverBodies[i].m_deltaAngularVelocity;\n"
- " } \n"
- " }\n"
- "}\n"
- "__kernel void getInfo2Kernel(__global b3SolverConstraint* solverConstraintRows, \n"
- " __global unsigned int* infos, \n"
- " __global unsigned int* constraintRowOffsets, \n"
- " __global b3GpuGenericConstraint* constraints, \n"
- " __global b3BatchConstraint* batchConstraints, \n"
- " __global b3RigidBodyCL* bodies,\n"
- " __global BodyInertia* inertias,\n"
- " __global b3GpuSolverBody* solverBodies,\n"
- " float timeStep,\n"
- " float globalErp,\n"
- " float globalCfm,\n"
- " float globalDamping,\n"
- " int globalNumIterations,\n"
- " int numConstraints)\n"
- "{\n"
- " int i = get_global_id(0);\n"
- " if (i>=numConstraints)\n"
- " return;\n"
- " \n"
- " //for now, always initialize the batch info\n"
- " int info1 = infos[i];\n"
- " \n"
- " __global b3SolverConstraint* currentConstraintRow = &solverConstraintRows[constraintRowOffsets[i]];\n"
- " __global b3GpuGenericConstraint* constraint = &constraints[i];\n"
- " __global b3RigidBodyCL* rbA = &bodies[ constraint->m_rbA];\n"
- " __global b3RigidBodyCL* rbB = &bodies[ constraint->m_rbB];\n"
- " int solverBodyIdA = constraint->m_rbA;\n"
- " int solverBodyIdB = constraint->m_rbB;\n"
- " __global b3GpuSolverBody* bodyAPtr = &solverBodies[solverBodyIdA];\n"
- " __global b3GpuSolverBody* bodyBPtr = &solverBodies[solverBodyIdB];\n"
- " if (rbA->m_invMass)\n"
- " {\n"
- " batchConstraints[i].m_bodyAPtrAndSignBit = solverBodyIdA;\n"
- " } else\n"
- " {\n"
- "// if (!solverBodyIdA)\n"
- "// m_staticIdx = 0;\n"
- " batchConstraints[i].m_bodyAPtrAndSignBit = -solverBodyIdA;\n"
- " }\n"
- " if (rbB->m_invMass)\n"
- " {\n"
- " batchConstraints[i].m_bodyBPtrAndSignBit = solverBodyIdB;\n"
- " } else\n"
- " {\n"
- "// if (!solverBodyIdB)\n"
- "// m_staticIdx = 0;\n"
- " batchConstraints[i].m_bodyBPtrAndSignBit = -solverBodyIdB;\n"
- " }\n"
- " if (info1)\n"
- " {\n"
- " int overrideNumSolverIterations = 0;//constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;\n"
- "// if (overrideNumSolverIterations>m_maxOverrideNumSolverIterations)\n"
- " // m_maxOverrideNumSolverIterations = overrideNumSolverIterations;\n"
- " int j;\n"
- " for ( j=0;j<info1;j++)\n"
- " {\n"
- "// memset(&currentConstraintRow[j],0,sizeof(b3SolverConstraint));\n"
- " currentConstraintRow[j].m_angularComponentA = (float4)(0,0,0,0);\n"
- " currentConstraintRow[j].m_angularComponentB = (float4)(0,0,0,0);\n"
- " currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
- " currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
- " currentConstraintRow[j].m_cfm = 0.f;\n"
- " currentConstraintRow[j].m_contactNormal = (float4)(0,0,0,0);\n"
- " currentConstraintRow[j].m_friction = 0.f;\n"
- " currentConstraintRow[j].m_frictionIndex = 0;\n"
- " currentConstraintRow[j].m_jacDiagABInv = 0.f;\n"
- " currentConstraintRow[j].m_lowerLimit = 0.f;\n"
- " currentConstraintRow[j].m_upperLimit = 0.f;\n"
- " currentConstraintRow[j].m_originalConstraint = i;\n"
- " currentConstraintRow[j].m_overrideNumSolverIterations = 0;\n"
- " currentConstraintRow[j].m_relpos1CrossNormal = (float4)(0,0,0,0);\n"
- " currentConstraintRow[j].m_relpos2CrossNormal = (float4)(0,0,0,0);\n"
- " currentConstraintRow[j].m_rhs = 0.f;\n"
- " currentConstraintRow[j].m_rhsPenetration = 0.f;\n"
- " currentConstraintRow[j].m_solverBodyIdA = 0;\n"
- " currentConstraintRow[j].m_solverBodyIdB = 0;\n"
- " \n"
- " currentConstraintRow[j].m_lowerLimit = -B3_INFINITY;\n"
- " currentConstraintRow[j].m_upperLimit = B3_INFINITY;\n"
- " currentConstraintRow[j].m_appliedImpulse = 0.f;\n"
- " currentConstraintRow[j].m_appliedPushImpulse = 0.f;\n"
- " currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;\n"
- " currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;\n"
- " currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations; \n"
- " }\n"
- " bodyAPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
- " bodyAPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
- " bodyAPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
- " bodyAPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
- " bodyBPtr->m_deltaLinearVelocity = (float4)(0,0,0,0);\n"
- " bodyBPtr->m_deltaAngularVelocity = (float4)(0,0,0,0);\n"
- " bodyBPtr->m_pushVelocity = (float4)(0,0,0,0);\n"
- " bodyBPtr->m_turnVelocity = (float4)(0,0,0,0);\n"
- " int rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
- " \n"
- " b3GpuConstraintInfo2 info2;\n"
- " info2.fps = 1.f/timeStep;\n"
- " info2.erp = globalErp;\n"
- " info2.m_J1linearAxisFloat4 = &currentConstraintRow->m_contactNormal;\n"
- " info2.m_J1angularAxisFloat4 = &currentConstraintRow->m_relpos1CrossNormal;\n"
- " info2.m_J2linearAxisFloat4 = 0;\n"
- " info2.m_J2angularAxisFloat4 = &currentConstraintRow->m_relpos2CrossNormal;\n"
- " info2.rowskip = sizeof(b3SolverConstraint)/sizeof(float);//check this\n"
- " ///the size of b3SolverConstraint needs be a multiple of float\n"
- "// b3Assert(info2.rowskip*sizeof(float)== sizeof(b3SolverConstraint));\n"
- " info2.m_constraintError = &currentConstraintRow->m_rhs;\n"
- " currentConstraintRow->m_cfm = globalCfm;\n"
- " info2.m_damping = globalDamping;\n"
- " info2.cfm = &currentConstraintRow->m_cfm;\n"
- " info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;\n"
- " info2.m_upperLimit = &currentConstraintRow->m_upperLimit;\n"
- " info2.m_numIterations = globalNumIterations;\n"
- " switch (constraint->m_constraintType)\n"
- " {\n"
- " case B3_GPU_POINT2POINT_CONSTRAINT_TYPE:\n"
- " {\n"
- " getInfo2Point2Point(constraint,&info2,bodies);\n"
- " break;\n"
- " }\n"
- " case B3_GPU_FIXED_CONSTRAINT_TYPE:\n"
- " {\n"
- " getInfo2Point2Point(constraint,&info2,bodies);\n"
- " getInfo2FixedOrientation(constraint,&info2,bodies,3);\n"
- " break;\n"
- " }\n"
- " default:\n"
- " {\n"
- " }\n"
- " }\n"
- " ///finalize the constraint setup\n"
- " for ( j=0;j<info1;j++)\n"
- " {\n"
- " __global b3SolverConstraint* solverConstraint = &currentConstraintRow[j];\n"
- " if (solverConstraint->m_upperLimit>=constraint->m_breakingImpulseThreshold)\n"
- " {\n"
- " solverConstraint->m_upperLimit = constraint->m_breakingImpulseThreshold;\n"
- " }\n"
- " if (solverConstraint->m_lowerLimit<=-constraint->m_breakingImpulseThreshold)\n"
- " {\n"
- " solverConstraint->m_lowerLimit = -constraint->m_breakingImpulseThreshold;\n"
- " }\n"
- "// solverConstraint->m_originalContactPoint = constraint;\n"
- " \n"
- " Matrix3x3 invInertiaWorldA= inertias[constraint->m_rbA].m_invInertiaWorld;\n"
- " {\n"
- " //float4 angularFactorA(1,1,1);\n"
- " float4 ftorqueAxis1 = solverConstraint->m_relpos1CrossNormal;\n"
- " solverConstraint->m_angularComponentA = mtMul1(invInertiaWorldA,ftorqueAxis1);//*angularFactorA;\n"
- " }\n"
- " \n"
- " Matrix3x3 invInertiaWorldB= inertias[constraint->m_rbB].m_invInertiaWorld;\n"
- " {\n"
- " float4 ftorqueAxis2 = solverConstraint->m_relpos2CrossNormal;\n"
- " solverConstraint->m_angularComponentB = mtMul1(invInertiaWorldB,ftorqueAxis2);//*constraint->m_rbB.getAngularFactor();\n"
- " }\n"
- " {\n"
- " //it is ok to use solverConstraint->m_contactNormal instead of -solverConstraint->m_contactNormal\n"
- " //because it gets multiplied iMJlB\n"
- " float4 iMJlA = solverConstraint->m_contactNormal*rbA->m_invMass;\n"
- " float4 iMJaA = mtMul3(solverConstraint->m_relpos1CrossNormal,invInertiaWorldA);\n"
- " float4 iMJlB = solverConstraint->m_contactNormal*rbB->m_invMass;//sign of normal?\n"
- " float4 iMJaB = mtMul3(solverConstraint->m_relpos2CrossNormal,invInertiaWorldB);\n"
- " float sum = dot3F4(iMJlA,solverConstraint->m_contactNormal);\n"
- " sum += dot3F4(iMJaA,solverConstraint->m_relpos1CrossNormal);\n"
- " sum += dot3F4(iMJlB,solverConstraint->m_contactNormal);\n"
- " sum += dot3F4(iMJaB,solverConstraint->m_relpos2CrossNormal);\n"
- " float fsum = fabs(sum);\n"
- " if (fsum>FLT_EPSILON)\n"
- " {\n"
- " solverConstraint->m_jacDiagABInv = 1.f/sum;\n"
- " } else\n"
- " {\n"
- " solverConstraint->m_jacDiagABInv = 0.f;\n"
- " }\n"
- " }\n"
- " ///fix rhs\n"
- " ///todo: add force/torque accelerators\n"
- " {\n"
- " float rel_vel;\n"
- " float vel1Dotn = dot3F4(solverConstraint->m_contactNormal,rbA->m_linVel) + dot3F4(solverConstraint->m_relpos1CrossNormal,rbA->m_angVel);\n"
- " float vel2Dotn = -dot3F4(solverConstraint->m_contactNormal,rbB->m_linVel) + dot3F4(solverConstraint->m_relpos2CrossNormal,rbB->m_angVel);\n"
- " rel_vel = vel1Dotn+vel2Dotn;\n"
- " float restitution = 0.f;\n"
- " float positionalError = solverConstraint->m_rhs;//already filled in by getConstraintInfo2\n"
- " float velocityError = restitution - rel_vel * info2.m_damping;\n"
- " float penetrationImpulse = positionalError*solverConstraint->m_jacDiagABInv;\n"
- " float velocityImpulse = velocityError *solverConstraint->m_jacDiagABInv;\n"
- " solverConstraint->m_rhs = penetrationImpulse+velocityImpulse;\n"
- " solverConstraint->m_appliedImpulse = 0.f;\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
deleted file mode 100644
index 5c4d62e4ec..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.cl
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-//#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile global int*
-#endif
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define mymake_float4 (float4)
-//#define make_float2 (float2)
-//#define make_uint4 (uint4)
-//#define make_int4 (int4)
-//#define make_uint2 (uint2)
-//#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-///////////////////////////////////////
-// Vector
-///////////////////////////////////////
-
-
-
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = mymake_float4(a.xyz,0.f);
- float4 b1 = mymake_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-// float length = sqrtf(dot3F4(a, a));
-// return 1.f/length * a;
-}
-
-
-
-
-///////////////////////////////////////
-// Matrix3x3
-///////////////////////////////////////
-
-typedef struct
-{
- float4 m_row[3];
-}Matrix3x3;
-
-
-
-
-
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b);
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b);
-
-
-
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b)
-{
- float4 ans;
- ans.x = dot3F4( a.m_row[0], b );
- ans.y = dot3F4( a.m_row[1], b );
- ans.z = dot3F4( a.m_row[2], b );
- ans.w = 0.f;
- return ans;
-}
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b)
-{
- float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- float4 ans;
- ans.x = dot3F4( a, colx );
- ans.y = dot3F4( a, coly );
- ans.z = dot3F4( a, colz );
- return ans;
-}
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-
-
-
-
-
-
-#define WG_SIZE 64
-
-typedef struct
-{
- float4 m_pos;
- Quaternion m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_shapeIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} Body;
-
-typedef struct
-{
- Matrix3x3 m_invInertia;
- Matrix3x3 m_initInvInertia;
-} Shape;
-
-typedef struct
-{
- float4 m_linear;
- float4 m_worldPos[4];
- float4 m_center;
- float m_jacCoeffInv[4];
- float m_b[4];
- float m_appliedRambdaDt[4];
-
- float m_fJacCoeffInv[2];
- float m_fAppliedRambdaDt[2];
-
- u32 m_bodyA;
- u32 m_bodyB;
-
- int m_batchIdx;
- u32 m_paddings[1];
-} Constraint4;
-
-
-
-typedef struct
-{
- int m_nConstraints;
- int m_start;
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_solveFriction;
- int m_maxBatch; // long batch really kills the performance
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBufferBatchSolve;
-
-void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
-
-void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
-{
- *linear = mymake_float4(-n.xyz,0.f);
- *angular0 = -cross3(r0, n);
- *angular1 = cross3(r1, n);
-}
-
-float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
-
-float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
-{
- return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
-}
-
-
-float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
- float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
-
-float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
- float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
-{
- // linear0,1 are normlized
- float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
- float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
- float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
- float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
- return -1.f/(jmj0+jmj1+jmj2+jmj3);
-}
-
-
-void solveContact(__global Constraint4* cs,
- float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
- float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);
-
-void solveContact(__global Constraint4* cs,
- float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
- float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)
-{
- float minRambdaDt = 0;
- float maxRambdaDt = FLT_MAX;
-
- for(int ic=0; ic<4; ic++)
- {
- if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
-
- float4 angular0, angular1, linear;
- float4 r0 = cs->m_worldPos[ic] - posA;
- float4 r1 = cs->m_worldPos[ic] - posB;
- setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
-
- float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
- *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];
- rambdaDt *= cs->m_jacCoeffInv[ic];
-
- {
- float prevSum = cs->m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = max2( updated, minRambdaDt );
- updated = min2( updated, maxRambdaDt );
- rambdaDt = updated - prevSum;
- cs->m_appliedRambdaDt[ic] = updated;
- }
-
- float4 linImp0 = invMassA*linear*rambdaDt;
- float4 linImp1 = invMassB*(-linear)*rambdaDt;
- float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
- float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
-
- *linVelA += linImp0;
- *angVelA += angImp0;
- *linVelB += linImp1;
- *angVelB += angImp1;
- }
-}
-
-void btPlaneSpace1 (const float4* n, float4* p, float4* q);
- void btPlaneSpace1 (const float4* n, float4* p, float4* q)
-{
- if (fabs(n[0].z) > 0.70710678f) {
- // choose p in y-z plane
- float a = n[0].y*n[0].y + n[0].z*n[0].z;
- float k = 1.f/sqrt(a);
- p[0].x = 0;
- p[0].y = -n[0].z*k;
- p[0].z = n[0].y*k;
- // set q = n x p
- q[0].x = a*k;
- q[0].y = -n[0].x*p[0].z;
- q[0].z = n[0].x*p[0].y;
- }
- else {
- // choose p in x-y plane
- float a = n[0].x*n[0].x + n[0].y*n[0].y;
- float k = 1.f/sqrt(a);
- p[0].x = -n[0].y*k;
- p[0].y = n[0].x*k;
- p[0].z = 0;
- // set q = n x p
- q[0].x = -n[0].z*p[0].y;
- q[0].y = n[0].z*p[0].x;
- q[0].z = a*k;
- }
-}
-
-void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
-void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
-{
- //float frictionCoeff = ldsCs[0].m_linear.w;
- int aIdx = ldsCs[0].m_bodyA;
- int bIdx = ldsCs[0].m_bodyB;
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
-
- solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
- posB, &linVelB, &angVelB, invMassB, invInertiaB );
-
- if (gBodies[aIdx].m_invMass)
- {
- gBodies[aIdx].m_linVel = linVelA;
- gBodies[aIdx].m_angVel = angVelA;
- } else
- {
- gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
- gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
-
- }
- if (gBodies[bIdx].m_invMass)
- {
- gBodies[bIdx].m_linVel = linVelB;
- gBodies[bIdx].m_angVel = angVelB;
- } else
- {
- gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
- gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
-
- }
-
-}
-
-
-
-typedef struct
-{
- int m_valInt0;
- int m_valInt1;
- int m_valInt2;
- int m_valInt3;
-
- float m_val0;
- float m_val1;
- float m_val2;
- float m_val3;
-} SolverDebugInfo;
-
-
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void BatchSolveKernelContact(__global Body* gBodies,
- __global Shape* gShapes,
- __global Constraint4* gConstraints,
- __global int* gN,
- __global int* gOffsets,
- __global int* batchSizes,
- int maxBatch1,
- int cellBatch,
- int4 nSplit
- )
-{
- //__local int ldsBatchIdx[WG_SIZE+1];
- __local int ldsCurBatch;
- __local int ldsNextBatch;
- __local int ldsStart;
-
- int lIdx = GET_LOCAL_IDX;
- int wgIdx = GET_GROUP_IDX;
-
-// int gIdx = GET_GLOBAL_IDX;
-// debugInfo[gIdx].m_valInt0 = gIdx;
- //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
-
-
-
-
- int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
- int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
- int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
- int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
-
- //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);
- //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);
- //int cellIdx = xIdx+yIdx*nSplit;
-
- if( gN[cellIdx] == 0 )
- return;
-
- int maxBatch = batchSizes[cellIdx];
-
-
- const int start = gOffsets[cellIdx];
- const int end = start + gN[cellIdx];
-
-
-
-
- if( lIdx == 0 )
- {
- ldsCurBatch = 0;
- ldsNextBatch = 0;
- ldsStart = start;
- }
-
-
- GROUP_LDS_BARRIER;
-
- int idx=ldsStart+lIdx;
- while (ldsCurBatch < maxBatch)
- {
- for(; idx<end; )
- {
- if (gConstraints[idx].m_batchIdx == ldsCurBatch)
- {
- solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
-
- idx+=64;
- } else
- {
- break;
- }
- }
- GROUP_LDS_BARRIER;
-
- if( lIdx == 0 )
- {
- ldsCurBatch++;
- }
- GROUP_LDS_BARRIER;
- }
-
-
-}
-
-
-
-__kernel void solveSingleContactKernel(__global Body* gBodies,
- __global Shape* gShapes,
- __global Constraint4* gConstraints,
- int cellIdx,
- int batchOffset,
- int numConstraintsInBatch
- )
-{
-
- int index = get_global_id(0);
- if (index < numConstraintsInBatch)
- {
- int idx=batchOffset+index;
- solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );
- }
-}
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h
deleted file mode 100644
index 6e14ad51fc..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveContact.h
+++ /dev/null
@@ -1,392 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveContactCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define mymake_float4 (float4)\n"
- "//#define make_float2 (float2)\n"
- "//#define make_uint4 (uint4)\n"
- "//#define make_int4 (int4)\n"
- "//#define make_uint2 (uint2)\n"
- "//#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "///////////////////////////////////////\n"
- "// Vector\n"
- "///////////////////////////////////////\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = mymake_float4(a.xyz,0.f);\n"
- " float4 b1 = mymake_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "// float length = sqrtf(dot3F4(a, a));\n"
- "// return 1.f/length * a;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Matrix3x3\n"
- "///////////////////////////////////////\n"
- "typedef struct\n"
- "{\n"
- " float4 m_row[3];\n"
- "}Matrix3x3;\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b);\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b);\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b)\n"
- "{\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a.m_row[0], b );\n"
- " ans.y = dot3F4( a.m_row[1], b );\n"
- " ans.z = dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b)\n"
- "{\n"
- " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a, colx );\n"
- " ans.y = dot3F4( a, coly );\n"
- " ans.z = dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "#define WG_SIZE 64\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " Quaternion m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_shapeIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} Body;\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_invInertia;\n"
- " Matrix3x3 m_initInvInertia;\n"
- "} Shape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_linear;\n"
- " float4 m_worldPos[4];\n"
- " float4 m_center; \n"
- " float m_jacCoeffInv[4];\n"
- " float m_b[4];\n"
- " float m_appliedRambdaDt[4];\n"
- " float m_fJacCoeffInv[2]; \n"
- " float m_fAppliedRambdaDt[2]; \n"
- " u32 m_bodyA;\n"
- " u32 m_bodyB;\n"
- " int m_batchIdx;\n"
- " u32 m_paddings[1];\n"
- "} Constraint4;\n"
- "typedef struct\n"
- "{\n"
- " int m_nConstraints;\n"
- " int m_start;\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct\n"
- "{\n"
- " int m_solveFriction;\n"
- " int m_maxBatch; // long batch really kills the performance\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBufferBatchSolve;\n"
- "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
- "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
- "{\n"
- " *linear = mymake_float4(-n.xyz,0.f);\n"
- " *angular0 = -cross3(r0, n);\n"
- " *angular1 = cross3(r1, n);\n"
- "}\n"
- "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
- "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
- "{\n"
- " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
- "}\n"
- "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
- " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
- "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
- " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
- "{\n"
- " // linear0,1 are normlized\n"
- " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
- " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
- " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
- " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
- " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
- "}\n"
- "void solveContact(__global Constraint4* cs,\n"
- " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
- " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB);\n"
- "void solveContact(__global Constraint4* cs,\n"
- " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
- " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB)\n"
- "{\n"
- " float minRambdaDt = 0;\n"
- " float maxRambdaDt = FLT_MAX;\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
- " float4 angular0, angular1, linear;\n"
- " float4 r0 = cs->m_worldPos[ic] - posA;\n"
- " float4 r1 = cs->m_worldPos[ic] - posB;\n"
- " setLinearAndAngular( -cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
- " float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
- " *linVelA, *angVelA, *linVelB, *angVelB ) + cs->m_b[ic];\n"
- " rambdaDt *= cs->m_jacCoeffInv[ic];\n"
- " {\n"
- " float prevSum = cs->m_appliedRambdaDt[ic];\n"
- " float updated = prevSum;\n"
- " updated += rambdaDt;\n"
- " updated = max2( updated, minRambdaDt );\n"
- " updated = min2( updated, maxRambdaDt );\n"
- " rambdaDt = updated - prevSum;\n"
- " cs->m_appliedRambdaDt[ic] = updated;\n"
- " }\n"
- " float4 linImp0 = invMassA*linear*rambdaDt;\n"
- " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
- " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
- " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
- " *linVelA += linImp0;\n"
- " *angVelA += angImp0;\n"
- " *linVelB += linImp1;\n"
- " *angVelB += angImp1;\n"
- " }\n"
- "}\n"
- "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
- " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
- "{\n"
- " if (fabs(n[0].z) > 0.70710678f) {\n"
- " // choose p in y-z plane\n"
- " float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = 0;\n"
- " p[0].y = -n[0].z*k;\n"
- " p[0].z = n[0].y*k;\n"
- " // set q = n x p\n"
- " q[0].x = a*k;\n"
- " q[0].y = -n[0].x*p[0].z;\n"
- " q[0].z = n[0].x*p[0].y;\n"
- " }\n"
- " else {\n"
- " // choose p in x-y plane\n"
- " float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = -n[0].y*k;\n"
- " p[0].y = n[0].x*k;\n"
- " p[0].z = 0;\n"
- " // set q = n x p\n"
- " q[0].x = -n[0].z*p[0].y;\n"
- " q[0].y = n[0].z*p[0].x;\n"
- " q[0].z = a*k;\n"
- " }\n"
- "}\n"
- "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
- "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
- "{\n"
- " //float frictionCoeff = ldsCs[0].m_linear.w;\n"
- " int aIdx = ldsCs[0].m_bodyA;\n"
- " int bIdx = ldsCs[0].m_bodyB;\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
- " solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
- " posB, &linVelB, &angVelB, invMassB, invInertiaB );\n"
- " if (gBodies[aIdx].m_invMass)\n"
- " {\n"
- " gBodies[aIdx].m_linVel = linVelA;\n"
- " gBodies[aIdx].m_angVel = angVelA;\n"
- " } else\n"
- " {\n"
- " gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
- " gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
- " \n"
- " }\n"
- " if (gBodies[bIdx].m_invMass)\n"
- " {\n"
- " gBodies[bIdx].m_linVel = linVelB;\n"
- " gBodies[bIdx].m_angVel = angVelB;\n"
- " } else\n"
- " {\n"
- " gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
- " gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
- " \n"
- " }\n"
- "}\n"
- "typedef struct \n"
- "{\n"
- " int m_valInt0;\n"
- " int m_valInt1;\n"
- " int m_valInt2;\n"
- " int m_valInt3;\n"
- " float m_val0;\n"
- " float m_val1;\n"
- " float m_val2;\n"
- " float m_val3;\n"
- "} SolverDebugInfo;\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void BatchSolveKernelContact(__global Body* gBodies,\n"
- " __global Shape* gShapes,\n"
- " __global Constraint4* gConstraints,\n"
- " __global int* gN,\n"
- " __global int* gOffsets,\n"
- " __global int* batchSizes,\n"
- " int maxBatch1,\n"
- " int cellBatch,\n"
- " int4 nSplit\n"
- " )\n"
- "{\n"
- " //__local int ldsBatchIdx[WG_SIZE+1];\n"
- " __local int ldsCurBatch;\n"
- " __local int ldsNextBatch;\n"
- " __local int ldsStart;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " int wgIdx = GET_GROUP_IDX;\n"
- "// int gIdx = GET_GLOBAL_IDX;\n"
- "// debugInfo[gIdx].m_valInt0 = gIdx;\n"
- " //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
- " \n"
- " \n"
- " int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
- " int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
- " int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
- " int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
- " int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
- " //int xIdx = (wgIdx/(nSplit/2))*2 + (bIdx&1);\n"
- " //int yIdx = (wgIdx%(nSplit/2))*2 + (bIdx>>1);\n"
- " //int cellIdx = xIdx+yIdx*nSplit;\n"
- " \n"
- " if( gN[cellIdx] == 0 ) \n"
- " return;\n"
- " int maxBatch = batchSizes[cellIdx];\n"
- " \n"
- " \n"
- " const int start = gOffsets[cellIdx];\n"
- " const int end = start + gN[cellIdx];\n"
- " \n"
- " \n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " ldsCurBatch = 0;\n"
- " ldsNextBatch = 0;\n"
- " ldsStart = start;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " int idx=ldsStart+lIdx;\n"
- " while (ldsCurBatch < maxBatch)\n"
- " {\n"
- " for(; idx<end; )\n"
- " {\n"
- " if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
- " {\n"
- " solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
- " idx+=64;\n"
- " } else\n"
- " {\n"
- " break;\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " ldsCurBatch++;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " \n"
- " \n"
- "}\n"
- "__kernel void solveSingleContactKernel(__global Body* gBodies,\n"
- " __global Shape* gShapes,\n"
- " __global Constraint4* gConstraints,\n"
- " int cellIdx,\n"
- " int batchOffset,\n"
- " int numConstraintsInBatch\n"
- " )\n"
- "{\n"
- " int index = get_global_id(0);\n"
- " if (index < numConstraintsInBatch)\n"
- " {\n"
- " int idx=batchOffset+index;\n"
- " solveContactConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
- " } \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
deleted file mode 100644
index 1d70fbbae3..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.cl
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-//#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile global int*
-#endif
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define mymake_float4 (float4)
-//#define make_float2 (float2)
-//#define make_uint4 (uint4)
-//#define make_int4 (int4)
-//#define make_uint2 (uint2)
-//#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-///////////////////////////////////////
-// Vector
-///////////////////////////////////////
-
-
-
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = mymake_float4(a.xyz,0.f);
- float4 b1 = mymake_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-
-
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = mymake_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-// float length = sqrtf(dot3F4(a, a));
-// return 1.f/length * a;
-}
-
-
-
-
-///////////////////////////////////////
-// Matrix3x3
-///////////////////////////////////////
-
-typedef struct
-{
- float4 m_row[3];
-}Matrix3x3;
-
-
-
-
-
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b);
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b);
-
-
-
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b)
-{
- float4 ans;
- ans.x = dot3F4( a.m_row[0], b );
- ans.y = dot3F4( a.m_row[1], b );
- ans.z = dot3F4( a.m_row[2], b );
- ans.w = 0.f;
- return ans;
-}
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b)
-{
- float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- float4 ans;
- ans.x = dot3F4( a, colx );
- ans.y = dot3F4( a, coly );
- ans.z = dot3F4( a, colz );
- return ans;
-}
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-
-
-
-
-
-
-#define WG_SIZE 64
-
-typedef struct
-{
- float4 m_pos;
- Quaternion m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_shapeIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} Body;
-
-typedef struct
-{
- Matrix3x3 m_invInertia;
- Matrix3x3 m_initInvInertia;
-} Shape;
-
-typedef struct
-{
- float4 m_linear;
- float4 m_worldPos[4];
- float4 m_center;
- float m_jacCoeffInv[4];
- float m_b[4];
- float m_appliedRambdaDt[4];
-
- float m_fJacCoeffInv[2];
- float m_fAppliedRambdaDt[2];
-
- u32 m_bodyA;
- u32 m_bodyB;
-
- int m_batchIdx;
- u32 m_paddings[1];
-} Constraint4;
-
-
-
-typedef struct
-{
- int m_nConstraints;
- int m_start;
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_solveFriction;
- int m_maxBatch; // long batch really kills the performance
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBufferBatchSolve;
-
-void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);
-
-void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
-{
- *linear = mymake_float4(-n.xyz,0.f);
- *angular0 = -cross3(r0, n);
- *angular1 = cross3(r1, n);
-}
-
-float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );
-
-float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
-{
- return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
-}
-
-
-float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
- float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);
-
-float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
- float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)
-{
- // linear0,1 are normlized
- float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
- float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
- float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
- float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
- return -1.f/(jmj0+jmj1+jmj2+jmj3);
-}
-void btPlaneSpace1 (const float4* n, float4* p, float4* q);
- void btPlaneSpace1 (const float4* n, float4* p, float4* q)
-{
- if (fabs(n[0].z) > 0.70710678f) {
- // choose p in y-z plane
- float a = n[0].y*n[0].y + n[0].z*n[0].z;
- float k = 1.f/sqrt(a);
- p[0].x = 0;
- p[0].y = -n[0].z*k;
- p[0].z = n[0].y*k;
- // set q = n x p
- q[0].x = a*k;
- q[0].y = -n[0].x*p[0].z;
- q[0].z = n[0].x*p[0].y;
- }
- else {
- // choose p in x-y plane
- float a = n[0].x*n[0].x + n[0].y*n[0].y;
- float k = 1.f/sqrt(a);
- p[0].x = -n[0].y*k;
- p[0].y = n[0].x*k;
- p[0].z = 0;
- // set q = n x p
- q[0].x = -n[0].z*p[0].y;
- q[0].y = n[0].z*p[0].x;
- q[0].z = a*k;
- }
-}
-
-
-void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);
-void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)
-{
- float frictionCoeff = ldsCs[0].m_linear.w;
- int aIdx = ldsCs[0].m_bodyA;
- int bIdx = ldsCs[0].m_bodyB;
-
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
-
-
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- float sum = 0;
- for(int j=0; j<4; j++)
- {
- sum +=ldsCs[0].m_appliedRambdaDt[j];
- }
- frictionCoeff = 0.7f;
- for(int j=0; j<4; j++)
- {
- maxRambdaDt[j] = frictionCoeff*sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
-
-
-// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
-// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
-
-
- {
-
- __global Constraint4* cs = ldsCs;
-
- if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
- const float4 center = cs->m_center;
-
- float4 n = -cs->m_linear;
-
- float4 tangent[2];
- btPlaneSpace1(&n,&tangent[0],&tangent[1]);
- float4 angular0, angular1, linear;
- float4 r0 = center - posA;
- float4 r1 = center - posB;
- for(int i=0; i<2; i++)
- {
- setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
- float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB );
- rambdaDt *= cs->m_fJacCoeffInv[i];
-
- {
- float prevSum = cs->m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = max2( updated, minRambdaDt[i] );
- updated = min2( updated, maxRambdaDt[i] );
- rambdaDt = updated - prevSum;
- cs->m_fAppliedRambdaDt[i] = updated;
- }
-
- float4 linImp0 = invMassA*linear*rambdaDt;
- float4 linImp1 = invMassB*(-linear)*rambdaDt;
- float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
- float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
-
- linVelA += linImp0;
- angVelA += angImp0;
- linVelB += linImp1;
- angVelB += angImp1;
- }
- { // angular damping for point constraint
- float4 ab = normalize3( posB - posA );
- float4 ac = normalize3( center - posA );
- if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = dot3F4( n, angVelA );
- float angNB = dot3F4( n, angVelB );
-
- angVelA -= (angNA*0.1f)*n;
- angVelB -= (angNB*0.1f)*n;
- }
- }
- }
-
-
-
- }
-
- if (gBodies[aIdx].m_invMass)
- {
- gBodies[aIdx].m_linVel = linVelA;
- gBodies[aIdx].m_angVel = angVelA;
- } else
- {
- gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);
- gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);
- }
- if (gBodies[bIdx].m_invMass)
- {
- gBodies[bIdx].m_linVel = linVelB;
- gBodies[bIdx].m_angVel = angVelB;
- } else
- {
- gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);
- gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);
- }
-
-
-}
-
-typedef struct
-{
- int m_valInt0;
- int m_valInt1;
- int m_valInt2;
- int m_valInt3;
-
- float m_val0;
- float m_val1;
- float m_val2;
- float m_val3;
-} SolverDebugInfo;
-
-
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void BatchSolveKernelFriction(__global Body* gBodies,
- __global Shape* gShapes,
- __global Constraint4* gConstraints,
- __global int* gN,
- __global int* gOffsets,
- __global int* batchSizes,
- int maxBatch1,
- int cellBatch,
- int4 nSplit
- )
-{
- //__local int ldsBatchIdx[WG_SIZE+1];
- __local int ldsCurBatch;
- __local int ldsNextBatch;
- __local int ldsStart;
-
- int lIdx = GET_LOCAL_IDX;
- int wgIdx = GET_GROUP_IDX;
-
-// int gIdx = GET_GLOBAL_IDX;
-// debugInfo[gIdx].m_valInt0 = gIdx;
- //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;
-
-
- int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);
- int remain= (wgIdx%((nSplit.x*nSplit.y)/4));
- int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);
- int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);
- int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);
-
-
- if( gN[cellIdx] == 0 )
- return;
-
- int maxBatch = batchSizes[cellIdx];
-
- const int start = gOffsets[cellIdx];
- const int end = start + gN[cellIdx];
-
-
- if( lIdx == 0 )
- {
- ldsCurBatch = 0;
- ldsNextBatch = 0;
- ldsStart = start;
- }
-
-
- GROUP_LDS_BARRIER;
-
- int idx=ldsStart+lIdx;
- while (ldsCurBatch < maxBatch)
- {
- for(; idx<end; )
- {
- if (gConstraints[idx].m_batchIdx == ldsCurBatch)
- {
-
- solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
-
- idx+=64;
- } else
- {
- break;
- }
- }
- GROUP_LDS_BARRIER;
- if( lIdx == 0 )
- {
- ldsCurBatch++;
- }
- GROUP_LDS_BARRIER;
- }
-
-
-}
-
-
-
-
-
-
-__kernel void solveSingleFrictionKernel(__global Body* gBodies,
- __global Shape* gShapes,
- __global Constraint4* gConstraints,
- int cellIdx,
- int batchOffset,
- int numConstraintsInBatch
- )
-{
-
- int index = get_global_id(0);
- if (index < numConstraintsInBatch)
- {
-
- int idx=batchOffset+index;
-
- solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
deleted file mode 100644
index 9707cdb25d..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solveFriction.h
+++ /dev/null
@@ -1,420 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solveFrictionCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "//#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define mymake_float4 (float4)\n"
- "//#define make_float2 (float2)\n"
- "//#define make_uint4 (uint4)\n"
- "//#define make_int4 (int4)\n"
- "//#define make_uint2 (uint2)\n"
- "//#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "///////////////////////////////////////\n"
- "// Vector\n"
- "///////////////////////////////////////\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = mymake_float4(a.xyz,0.f);\n"
- " float4 b1 = mymake_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = mymake_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "// float length = sqrtf(dot3F4(a, a));\n"
- "// return 1.f/length * a;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Matrix3x3\n"
- "///////////////////////////////////////\n"
- "typedef struct\n"
- "{\n"
- " float4 m_row[3];\n"
- "}Matrix3x3;\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b);\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b);\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b)\n"
- "{\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a.m_row[0], b );\n"
- " ans.y = dot3F4( a.m_row[1], b );\n"
- " ans.z = dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b)\n"
- "{\n"
- " float4 colx = mymake_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " float4 coly = mymake_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " float4 colz = mymake_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a, colx );\n"
- " ans.y = dot3F4( a, coly );\n"
- " ans.z = dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "#define WG_SIZE 64\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " Quaternion m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_shapeIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} Body;\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_invInertia;\n"
- " Matrix3x3 m_initInvInertia;\n"
- "} Shape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_linear;\n"
- " float4 m_worldPos[4];\n"
- " float4 m_center; \n"
- " float m_jacCoeffInv[4];\n"
- " float m_b[4];\n"
- " float m_appliedRambdaDt[4];\n"
- " float m_fJacCoeffInv[2]; \n"
- " float m_fAppliedRambdaDt[2]; \n"
- " u32 m_bodyA;\n"
- " u32 m_bodyB;\n"
- " int m_batchIdx;\n"
- " u32 m_paddings[1];\n"
- "} Constraint4;\n"
- "typedef struct\n"
- "{\n"
- " int m_nConstraints;\n"
- " int m_start;\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct\n"
- "{\n"
- " int m_solveFriction;\n"
- " int m_maxBatch; // long batch really kills the performance\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBufferBatchSolve;\n"
- "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1);\n"
- "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
- "{\n"
- " *linear = mymake_float4(-n.xyz,0.f);\n"
- " *angular0 = -cross3(r0, n);\n"
- " *angular1 = cross3(r1, n);\n"
- "}\n"
- "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 );\n"
- "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
- "{\n"
- " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
- "}\n"
- "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
- " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1);\n"
- "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
- " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1)\n"
- "{\n"
- " // linear0,1 are normlized\n"
- " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
- " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
- " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
- " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
- " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
- "}\n"
- "void btPlaneSpace1 (const float4* n, float4* p, float4* q);\n"
- " void btPlaneSpace1 (const float4* n, float4* p, float4* q)\n"
- "{\n"
- " if (fabs(n[0].z) > 0.70710678f) {\n"
- " // choose p in y-z plane\n"
- " float a = n[0].y*n[0].y + n[0].z*n[0].z;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = 0;\n"
- " p[0].y = -n[0].z*k;\n"
- " p[0].z = n[0].y*k;\n"
- " // set q = n x p\n"
- " q[0].x = a*k;\n"
- " q[0].y = -n[0].x*p[0].z;\n"
- " q[0].z = n[0].x*p[0].y;\n"
- " }\n"
- " else {\n"
- " // choose p in x-y plane\n"
- " float a = n[0].x*n[0].x + n[0].y*n[0].y;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = -n[0].y*k;\n"
- " p[0].y = n[0].x*k;\n"
- " p[0].z = 0;\n"
- " // set q = n x p\n"
- " q[0].x = -n[0].z*p[0].y;\n"
- " q[0].y = n[0].z*p[0].x;\n"
- " q[0].z = a*k;\n"
- " }\n"
- "}\n"
- "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs);\n"
- "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs)\n"
- "{\n"
- " float frictionCoeff = ldsCs[0].m_linear.w;\n"
- " int aIdx = ldsCs[0].m_bodyA;\n"
- " int bIdx = ldsCs[0].m_bodyB;\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
- " \n"
- " {\n"
- " float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
- " float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
- " float sum = 0;\n"
- " for(int j=0; j<4; j++)\n"
- " {\n"
- " sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
- " }\n"
- " frictionCoeff = 0.7f;\n"
- " for(int j=0; j<4; j++)\n"
- " {\n"
- " maxRambdaDt[j] = frictionCoeff*sum;\n"
- " minRambdaDt[j] = -maxRambdaDt[j];\n"
- " }\n"
- " \n"
- "// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
- "// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
- " \n"
- " \n"
- " {\n"
- " \n"
- " __global Constraint4* cs = ldsCs;\n"
- " \n"
- " if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
- " const float4 center = cs->m_center;\n"
- " \n"
- " float4 n = -cs->m_linear;\n"
- " \n"
- " float4 tangent[2];\n"
- " btPlaneSpace1(&n,&tangent[0],&tangent[1]);\n"
- " float4 angular0, angular1, linear;\n"
- " float4 r0 = center - posA;\n"
- " float4 r1 = center - posB;\n"
- " for(int i=0; i<2; i++)\n"
- " {\n"
- " setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
- " float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
- " linVelA, angVelA, linVelB, angVelB );\n"
- " rambdaDt *= cs->m_fJacCoeffInv[i];\n"
- " \n"
- " {\n"
- " float prevSum = cs->m_fAppliedRambdaDt[i];\n"
- " float updated = prevSum;\n"
- " updated += rambdaDt;\n"
- " updated = max2( updated, minRambdaDt[i] );\n"
- " updated = min2( updated, maxRambdaDt[i] );\n"
- " rambdaDt = updated - prevSum;\n"
- " cs->m_fAppliedRambdaDt[i] = updated;\n"
- " }\n"
- " \n"
- " float4 linImp0 = invMassA*linear*rambdaDt;\n"
- " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
- " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
- " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
- " \n"
- " linVelA += linImp0;\n"
- " angVelA += angImp0;\n"
- " linVelB += linImp1;\n"
- " angVelB += angImp1;\n"
- " }\n"
- " { // angular damping for point constraint\n"
- " float4 ab = normalize3( posB - posA );\n"
- " float4 ac = normalize3( center - posA );\n"
- " if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
- " {\n"
- " float angNA = dot3F4( n, angVelA );\n"
- " float angNB = dot3F4( n, angVelB );\n"
- " \n"
- " angVelA -= (angNA*0.1f)*n;\n"
- " angVelB -= (angNB*0.1f)*n;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " \n"
- " }\n"
- " if (gBodies[aIdx].m_invMass)\n"
- " {\n"
- " gBodies[aIdx].m_linVel = linVelA;\n"
- " gBodies[aIdx].m_angVel = angVelA;\n"
- " } else\n"
- " {\n"
- " gBodies[aIdx].m_linVel = mymake_float4(0,0,0,0);\n"
- " gBodies[aIdx].m_angVel = mymake_float4(0,0,0,0);\n"
- " }\n"
- " if (gBodies[bIdx].m_invMass)\n"
- " {\n"
- " gBodies[bIdx].m_linVel = linVelB;\n"
- " gBodies[bIdx].m_angVel = angVelB;\n"
- " } else\n"
- " {\n"
- " gBodies[bIdx].m_linVel = mymake_float4(0,0,0,0);\n"
- " gBodies[bIdx].m_angVel = mymake_float4(0,0,0,0);\n"
- " }\n"
- " \n"
- "}\n"
- "typedef struct \n"
- "{\n"
- " int m_valInt0;\n"
- " int m_valInt1;\n"
- " int m_valInt2;\n"
- " int m_valInt3;\n"
- " float m_val0;\n"
- " float m_val1;\n"
- " float m_val2;\n"
- " float m_val3;\n"
- "} SolverDebugInfo;\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void BatchSolveKernelFriction(__global Body* gBodies,\n"
- " __global Shape* gShapes,\n"
- " __global Constraint4* gConstraints,\n"
- " __global int* gN,\n"
- " __global int* gOffsets,\n"
- " __global int* batchSizes,\n"
- " int maxBatch1,\n"
- " int cellBatch,\n"
- " int4 nSplit\n"
- " )\n"
- "{\n"
- " //__local int ldsBatchIdx[WG_SIZE+1];\n"
- " __local int ldsCurBatch;\n"
- " __local int ldsNextBatch;\n"
- " __local int ldsStart;\n"
- " int lIdx = GET_LOCAL_IDX;\n"
- " int wgIdx = GET_GROUP_IDX;\n"
- "// int gIdx = GET_GLOBAL_IDX;\n"
- "// debugInfo[gIdx].m_valInt0 = gIdx;\n"
- " //debugInfo[gIdx].m_valInt1 = GET_GROUP_SIZE;\n"
- " int zIdx = (wgIdx/((nSplit.x*nSplit.y)/4))*2+((cellBatch&4)>>2);\n"
- " int remain= (wgIdx%((nSplit.x*nSplit.y)/4));\n"
- " int yIdx = (remain/(nSplit.x/2))*2 + ((cellBatch&2)>>1);\n"
- " int xIdx = (remain%(nSplit.x/2))*2 + (cellBatch&1);\n"
- " int cellIdx = xIdx+yIdx*nSplit.x+zIdx*(nSplit.x*nSplit.y);\n"
- " \n"
- " if( gN[cellIdx] == 0 ) \n"
- " return;\n"
- " int maxBatch = batchSizes[cellIdx];\n"
- " const int start = gOffsets[cellIdx];\n"
- " const int end = start + gN[cellIdx];\n"
- " \n"
- " if( lIdx == 0 )\n"
- " {\n"
- " ldsCurBatch = 0;\n"
- " ldsNextBatch = 0;\n"
- " ldsStart = start;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " int idx=ldsStart+lIdx;\n"
- " while (ldsCurBatch < maxBatch)\n"
- " {\n"
- " for(; idx<end; )\n"
- " {\n"
- " if (gConstraints[idx].m_batchIdx == ldsCurBatch)\n"
- " {\n"
- " solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
- " idx+=64;\n"
- " } else\n"
- " {\n"
- " break;\n"
- " }\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " if( lIdx == 0 )\n"
- " {\n"
- " ldsCurBatch++;\n"
- " }\n"
- " GROUP_LDS_BARRIER;\n"
- " }\n"
- " \n"
- " \n"
- "}\n"
- "__kernel void solveSingleFrictionKernel(__global Body* gBodies,\n"
- " __global Shape* gShapes,\n"
- " __global Constraint4* gConstraints,\n"
- " int cellIdx,\n"
- " int batchOffset,\n"
- " int numConstraintsInBatch\n"
- " )\n"
- "{\n"
- " int index = get_global_id(0);\n"
- " if (index < numConstraintsInBatch)\n"
- " {\n"
- " \n"
- " int idx=batchOffset+index;\n"
- " \n"
- " solveFrictionConstraint( gBodies, gShapes, &gConstraints[idx] );\n"
- " } \n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
deleted file mode 100644
index 8e2de7b5a6..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.cl
+++ /dev/null
@@ -1,277 +0,0 @@
-
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-#include "Bullet3Dynamics/shared/b3ConvertConstraint4.h"
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile global int*
-#endif
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-///////////////////////////////////////
-// Vector
-///////////////////////////////////////
-__inline
-float fastDiv(float numerator, float denominator)
-{
- return native_divide(numerator, denominator);
-// return numerator/denominator;
-}
-
-__inline
-float4 fastDiv4(float4 numerator, float4 denominator)
-{
- return native_divide(numerator, denominator);
-}
-
-__inline
-float fastSqrtf(float f2)
-{
- return native_sqrt(f2);
-// return sqrt(f2);
-}
-
-__inline
-float fastRSqrt(float f2)
-{
- return native_rsqrt(f2);
-}
-
-__inline
-float fastLength4(float4 v)
-{
- return fast_length(v);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-__inline
-float sqrtf(float a)
-{
-// return sqrt(a);
- return native_sqrt(a);
-}
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float length3(const float4 a)
-{
- return sqrtf(dot3F4(a,a));
-}
-
-__inline
-float dot4(const float4 a, const float4 b)
-{
- return dot( a, b );
-}
-
-// for height
-__inline
-float dot3w1(const float4 point, const float4 eqn)
-{
- return dot3F4(point,eqn) + eqn.w;
-}
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-// float length = sqrtf(dot3F4(a, a));
-// return 1.f/length * a;
-}
-
-__inline
-float4 normalize4(const float4 a)
-{
- float length = sqrtf(dot4(a, a));
- return 1.f/length * a;
-}
-
-__inline
-float4 createEquation(const float4 a, const float4 b, const float4 c)
-{
- float4 eqn;
- float4 ab = b-a;
- float4 ac = c-a;
- eqn = normalize3( cross3(ab, ac) );
- eqn.w = -dot3F4(eqn,a);
- return eqn;
-}
-
-
-
-#define WG_SIZE 64
-
-
-
-
-
-
-
-typedef struct
-{
- int m_nConstraints;
- int m_start;
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_solveFriction;
- int m_maxBatch; // long batch really kills the performance
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBufferBatchSolve;
-
-
-
-
-
-
-
-typedef struct
-{
- int m_valInt0;
- int m_valInt1;
- int m_valInt2;
- int m_valInt3;
-
- float m_val0;
- float m_val1;
- float m_val2;
- float m_val3;
-} SolverDebugInfo;
-
-
-
-
-
-
-typedef struct
-{
- int m_nContacts;
- float m_dt;
- float m_positionDrift;
- float m_positionConstraintCoeff;
-} ConstBufferCTC;
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut,
-int nContacts,
-float dt,
-float positionDrift,
-float positionConstraintCoeff
-)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
- int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;
-
- b3ContactConstraint4_t cs;
-
- setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,
- &cs );
-
- cs.m_batchIdx = gContact[gIdx].m_batchIdx;
-
- gConstraintOut[gIdx] = cs;
- }
-}
-
-
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
deleted file mode 100644
index d53db03181..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup.h
+++ /dev/null
@@ -1,702 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverSetupCL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#ifndef B3_CONTACT_CONSTRAINT5_H\n"
- "#define B3_CONTACT_CONSTRAINT5_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3ContactConstraint4 b3ContactConstraint4_t;\n"
- "struct b3ContactConstraint4\n"
- "{\n"
- " b3Float4 m_linear;//normal?\n"
- " b3Float4 m_worldPos[4];\n"
- " b3Float4 m_center; // friction\n"
- " float m_jacCoeffInv[4];\n"
- " float m_b[4];\n"
- " float m_appliedRambdaDt[4];\n"
- " float m_fJacCoeffInv[2]; // friction\n"
- " float m_fAppliedRambdaDt[2]; // friction\n"
- " unsigned int m_bodyA;\n"
- " unsigned int m_bodyB;\n"
- " int m_batchIdx;\n"
- " unsigned int m_paddings;\n"
- "};\n"
- "//inline void setFrictionCoeff(float value) { m_linear[3] = value; }\n"
- "inline float b3GetFrictionCoeff(b3ContactConstraint4_t* constraint) \n"
- "{\n"
- " return constraint->m_linear.w; \n"
- "}\n"
- "#endif //B3_CONTACT_CONSTRAINT5_H\n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#define B3_RIGIDBODY_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
- "struct b3RigidBodyData\n"
- "{\n"
- " b3Float4 m_pos;\n"
- " b3Quat m_quat;\n"
- " b3Float4 m_linVel;\n"
- " b3Float4 m_angVel;\n"
- " int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "};\n"
- "typedef struct b3InertiaData b3InertiaData_t;\n"
- "struct b3InertiaData\n"
- "{\n"
- " b3Mat3x3 m_invInertiaWorld;\n"
- " b3Mat3x3 m_initInvInertia;\n"
- "};\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q);\n"
- " void b3PlaneSpace1 (b3Float4ConstArg n, b3Float4* p, b3Float4* q)\n"
- "{\n"
- " if (b3Fabs(n.z) > 0.70710678f) {\n"
- " // choose p in y-z plane\n"
- " float a = n.y*n.y + n.z*n.z;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = 0;\n"
- " p[0].y = -n.z*k;\n"
- " p[0].z = n.y*k;\n"
- " // set q = n x p\n"
- " q[0].x = a*k;\n"
- " q[0].y = -n.x*p[0].z;\n"
- " q[0].z = n.x*p[0].y;\n"
- " }\n"
- " else {\n"
- " // choose p in x-y plane\n"
- " float a = n.x*n.x + n.y*n.y;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = -n.y*k;\n"
- " p[0].y = n.x*k;\n"
- " p[0].z = 0;\n"
- " // set q = n x p\n"
- " q[0].x = -n.z*p[0].y;\n"
- " q[0].y = n.z*p[0].x;\n"
- " q[0].z = a*k;\n"
- " }\n"
- "}\n"
- " \n"
- "void setLinearAndAngular( b3Float4ConstArg n, b3Float4ConstArg r0, b3Float4ConstArg r1, b3Float4* linear, b3Float4* angular0, b3Float4* angular1)\n"
- "{\n"
- " *linear = b3MakeFloat4(n.x,n.y,n.z,0.f);\n"
- " *angular0 = b3Cross3(r0, n);\n"
- " *angular1 = -b3Cross3(r1, n);\n"
- "}\n"
- "float calcRelVel( b3Float4ConstArg l0, b3Float4ConstArg l1, b3Float4ConstArg a0, b3Float4ConstArg a1, b3Float4ConstArg linVel0,\n"
- " b3Float4ConstArg angVel0, b3Float4ConstArg linVel1, b3Float4ConstArg angVel1 )\n"
- "{\n"
- " return b3Dot3F4(l0, linVel0) + b3Dot3F4(a0, angVel0) + b3Dot3F4(l1, linVel1) + b3Dot3F4(a1, angVel1);\n"
- "}\n"
- "float calcJacCoeff(b3Float4ConstArg linear0, b3Float4ConstArg linear1, b3Float4ConstArg angular0, b3Float4ConstArg angular1,\n"
- " float invMass0, const b3Mat3x3* invInertia0, float invMass1, const b3Mat3x3* invInertia1)\n"
- "{\n"
- " // linear0,1 are normlized\n"
- " float jmj0 = invMass0;//b3Dot3F4(linear0, linear0)*invMass0;\n"
- " float jmj1 = b3Dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
- " float jmj2 = invMass1;//b3Dot3F4(linear1, linear1)*invMass1;\n"
- " float jmj3 = b3Dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
- " return -1.f/(jmj0+jmj1+jmj2+jmj3);\n"
- "}\n"
- "void setConstraint4( b3Float4ConstArg posA, b3Float4ConstArg linVelA, b3Float4ConstArg angVelA, float invMassA, b3Mat3x3ConstArg invInertiaA,\n"
- " b3Float4ConstArg posB, b3Float4ConstArg linVelB, b3Float4ConstArg angVelB, float invMassB, b3Mat3x3ConstArg invInertiaB, \n"
- " __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,\n"
- " b3ContactConstraint4_t* dstC )\n"
- "{\n"
- " dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
- " dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
- " float dtInv = 1.f/dt;\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
- " }\n"
- " dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
- " dstC->m_linear = src->m_worldNormalOnB;\n"
- " dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " b3Float4 r0 = src->m_worldPosB[ic] - posA;\n"
- " b3Float4 r1 = src->m_worldPosB[ic] - posB;\n"
- " if( ic >= src->m_worldNormalOnB.w )//npoints\n"
- " {\n"
- " dstC->m_jacCoeffInv[ic] = 0.f;\n"
- " continue;\n"
- " }\n"
- " float relVelN;\n"
- " {\n"
- " b3Float4 linear, angular0, angular1;\n"
- " setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
- " dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
- " invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
- " relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
- " linVelA, angVelA, linVelB, angVelB);\n"
- " float e = 0.f;//src->getRestituitionCoeff();\n"
- " if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
- " dstC->m_b[ic] = e*relVelN;\n"
- " //float penetration = src->m_worldPosB[ic].w;\n"
- " dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
- " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
- " }\n"
- " }\n"
- " if( src->m_worldNormalOnB.w > 0 )//npoints\n"
- " { // prepare friction\n"
- " b3Float4 center = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
- " for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
- " center += src->m_worldPosB[i];\n"
- " center /= (float)src->m_worldNormalOnB.w;\n"
- " b3Float4 tangent[2];\n"
- " b3PlaneSpace1(src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
- " \n"
- " b3Float4 r[2];\n"
- " r[0] = center - posA;\n"
- " r[1] = center - posB;\n"
- " for(int i=0; i<2; i++)\n"
- " {\n"
- " b3Float4 linear, angular0, angular1;\n"
- " setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
- " dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
- " invMassA, &invInertiaA, invMassB, &invInertiaB );\n"
- " dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
- " }\n"
- " dstC->m_center = center;\n"
- " }\n"
- " for(int i=0; i<4; i++)\n"
- " {\n"
- " if( i<src->m_worldNormalOnB.w )\n"
- " {\n"
- " dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
- " }\n"
- " else\n"
- " {\n"
- " dstC->m_worldPos[i] = b3MakeFloat4(0.f,0.f,0.f,0.f);\n"
- " }\n"
- " }\n"
- "}\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "///////////////////////////////////////\n"
- "// Vector\n"
- "///////////////////////////////////////\n"
- "__inline\n"
- "float fastDiv(float numerator, float denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "// return numerator/denominator; \n"
- "}\n"
- "__inline\n"
- "float4 fastDiv4(float4 numerator, float4 denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "}\n"
- "__inline\n"
- "float fastSqrtf(float f2)\n"
- "{\n"
- " return native_sqrt(f2);\n"
- "// return sqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastRSqrt(float f2)\n"
- "{\n"
- " return native_rsqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastLength4(float4 v)\n"
- "{\n"
- " return fast_length(v);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "float sqrtf(float a)\n"
- "{\n"
- "// return sqrt(a);\n"
- " return native_sqrt(a);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float length3(const float4 a)\n"
- "{\n"
- " return sqrtf(dot3F4(a,a));\n"
- "}\n"
- "__inline\n"
- "float dot4(const float4 a, const float4 b)\n"
- "{\n"
- " return dot( a, b );\n"
- "}\n"
- "// for height\n"
- "__inline\n"
- "float dot3w1(const float4 point, const float4 eqn)\n"
- "{\n"
- " return dot3F4(point,eqn) + eqn.w;\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "// float length = sqrtf(dot3F4(a, a));\n"
- "// return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 normalize4(const float4 a)\n"
- "{\n"
- " float length = sqrtf(dot4(a, a));\n"
- " return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
- "{\n"
- " float4 eqn;\n"
- " float4 ab = b-a;\n"
- " float4 ac = c-a;\n"
- " eqn = normalize3( cross3(ab, ac) );\n"
- " eqn.w = -dot3F4(eqn,a);\n"
- " return eqn;\n"
- "}\n"
- "#define WG_SIZE 64\n"
- "typedef struct\n"
- "{\n"
- " int m_nConstraints;\n"
- " int m_start;\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct\n"
- "{\n"
- " int m_solveFriction;\n"
- " int m_maxBatch; // long batch really kills the performance\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBufferBatchSolve;\n"
- " \n"
- "typedef struct \n"
- "{\n"
- " int m_valInt0;\n"
- " int m_valInt1;\n"
- " int m_valInt2;\n"
- " int m_valInt3;\n"
- " float m_val0;\n"
- " float m_val1;\n"
- " float m_val2;\n"
- " float m_val3;\n"
- "} SolverDebugInfo;\n"
- "typedef struct\n"
- "{\n"
- " int m_nContacts;\n"
- " float m_dt;\n"
- " float m_positionDrift;\n"
- " float m_positionConstraintCoeff;\n"
- "} ConstBufferCTC;\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void ContactToConstraintKernel(__global struct b3Contact4Data* gContact, __global b3RigidBodyData_t* gBodies, __global b3InertiaData_t* gShapes, __global b3ContactConstraint4_t* gConstraintOut, \n"
- "int nContacts,\n"
- "float dt,\n"
- "float positionDrift,\n"
- "float positionConstraintCoeff\n"
- ")\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " \n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
- " int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " b3Mat3x3 invInertiaA = gShapes[aIdx].m_initInvInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " b3Mat3x3 invInertiaB = gShapes[bIdx].m_initInvInertia;\n"
- " b3ContactConstraint4_t cs;\n"
- " setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
- " &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,\n"
- " &cs );\n"
- " \n"
- " cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
- " gConstraintOut[gIdx] = cs;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
deleted file mode 100644
index 3dc48d4350..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.cl
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
-Copyright (c) 2012 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Takahiro Harada
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile global int*
-#endif
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-///////////////////////////////////////
-// Vector
-///////////////////////////////////////
-__inline
-float fastDiv(float numerator, float denominator)
-{
- return native_divide(numerator, denominator);
-// return numerator/denominator;
-}
-
-__inline
-float4 fastDiv4(float4 numerator, float4 denominator)
-{
- return native_divide(numerator, denominator);
-}
-
-__inline
-float fastSqrtf(float f2)
-{
- return native_sqrt(f2);
-// return sqrt(f2);
-}
-
-__inline
-float fastRSqrt(float f2)
-{
- return native_rsqrt(f2);
-}
-
-__inline
-float fastLength4(float4 v)
-{
- return fast_length(v);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-__inline
-float sqrtf(float a)
-{
-// return sqrt(a);
- return native_sqrt(a);
-}
-
-__inline
-float4 cross3(float4 a, float4 b)
-{
- return cross(a,b);
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float length3(const float4 a)
-{
- return sqrtf(dot3F4(a,a));
-}
-
-__inline
-float dot4(const float4 a, const float4 b)
-{
- return dot( a, b );
-}
-
-// for height
-__inline
-float dot3w1(const float4 point, const float4 eqn)
-{
- return dot3F4(point,eqn) + eqn.w;
-}
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-// float length = sqrtf(dot3F4(a, a));
-// return 1.f/length * a;
-}
-
-__inline
-float4 normalize4(const float4 a)
-{
- float length = sqrtf(dot4(a, a));
- return 1.f/length * a;
-}
-
-__inline
-float4 createEquation(const float4 a, const float4 b, const float4 c)
-{
- float4 eqn;
- float4 ab = b-a;
- float4 ac = c-a;
- eqn = normalize3( cross3(ab, ac) );
- eqn.w = -dot3F4(eqn,a);
- return eqn;
-}
-
-///////////////////////////////////////
-// Matrix3x3
-///////////////////////////////////////
-
-typedef struct
-{
- float4 m_row[3];
-}Matrix3x3;
-
-__inline
-Matrix3x3 mtZero();
-
-__inline
-Matrix3x3 mtIdentity();
-
-__inline
-Matrix3x3 mtTranspose(Matrix3x3 m);
-
-__inline
-Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b);
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b);
-
-__inline
-Matrix3x3 mtZero()
-{
- Matrix3x3 m;
- m.m_row[0] = (float4)(0.f);
- m.m_row[1] = (float4)(0.f);
- m.m_row[2] = (float4)(0.f);
- return m;
-}
-
-__inline
-Matrix3x3 mtIdentity()
-{
- Matrix3x3 m;
- m.m_row[0] = (float4)(1,0,0,0);
- m.m_row[1] = (float4)(0,1,0,0);
- m.m_row[2] = (float4)(0,0,1,0);
- return m;
-}
-
-__inline
-Matrix3x3 mtTranspose(Matrix3x3 m)
-{
- Matrix3x3 out;
- out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
- out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
- out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
- return out;
-}
-
-__inline
-Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
-{
- Matrix3x3 transB;
- transB = mtTranspose( b );
- Matrix3x3 ans;
- // why this doesn't run when 0ing in the for{}
- a.m_row[0].w = 0.f;
- a.m_row[1].w = 0.f;
- a.m_row[2].w = 0.f;
- for(int i=0; i<3; i++)
- {
-// a.m_row[i].w = 0.f;
- ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
- ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
- ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
- ans.m_row[i].w = 0.f;
- }
- return ans;
-}
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b)
-{
- float4 ans;
- ans.x = dot3F4( a.m_row[0], b );
- ans.y = dot3F4( a.m_row[1], b );
- ans.z = dot3F4( a.m_row[2], b );
- ans.w = 0.f;
- return ans;
-}
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b)
-{
- float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- float4 ans;
- ans.x = dot3F4( a, colx );
- ans.y = dot3F4( a, coly );
- ans.z = dot3F4( a, colz );
- return ans;
-}
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-
-
-
-#define WG_SIZE 64
-
-typedef struct
-{
- float4 m_pos;
- Quaternion m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_shapeIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} Body;
-
-typedef struct
-{
- Matrix3x3 m_invInertia;
- Matrix3x3 m_initInvInertia;
-} Shape;
-
-typedef struct
-{
- float4 m_linear;
- float4 m_worldPos[4];
- float4 m_center;
- float m_jacCoeffInv[4];
- float m_b[4];
- float m_appliedRambdaDt[4];
-
- float m_fJacCoeffInv[2];
- float m_fAppliedRambdaDt[2];
-
- u32 m_bodyA;
- u32 m_bodyB;
-
- int m_batchIdx;
- u32 m_paddings[1];
-} Constraint4;
-
-
-
-typedef struct
-{
- int m_nConstraints;
- int m_start;
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBuffer;
-
-typedef struct
-{
- int m_solveFriction;
- int m_maxBatch; // long batch really kills the performance
- int m_batchIdx;
- int m_nSplit;
-// int m_paddings[1];
-} ConstBufferBatchSolve;
-
-
-
-
-
-typedef struct
-{
- int m_valInt0;
- int m_valInt1;
- int m_valInt2;
- int m_valInt3;
-
- float m_val0;
- float m_val1;
- float m_val2;
- float m_val3;
-} SolverDebugInfo;
-
-
-
-
-// others
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )
-{
- int nContacts = cb.x;
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int srcIdx = sortData[gIdx].y;
- out[gIdx] = in[srcIdx];
- }
-}
-
-__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int2 sd;
- sd.x = contactsIn[gIdx].m_childIndexB;
- sd.y = gIdx;
- sortDataOut[gIdx] = sd;
- }
-}
-
-__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int2 sdIn;
- sdIn = sortDataInOut[gIdx];
- int2 sdOut;
- sdOut.x = contactsIn[sdIn.y].m_childIndexA;
- sdOut.y = sdIn.y;
- sortDataInOut[gIdx] = sdOut;
- }
-}
-
-__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int2 sdIn;
- sdIn = sortDataInOut[gIdx];
- int2 sdOut;
- sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;
- sdOut.y = sdIn.y;
- sortDataInOut[gIdx] = sdOut;
- }
-}
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int2 sdIn;
- sdIn = sortDataInOut[gIdx];
- int2 sdOut;
- sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;
- sdOut.y = sdIn.y;
- sortDataInOut[gIdx] = sdOut;
- }
-}
-
-
-
-
-typedef struct
-{
- int m_nContacts;
- int m_staticIdx;
- float m_scale;
- int m_nSplit;
-} ConstBufferSSD;
-
-
-__constant const int gridTable4x4[] =
-{
- 0,1,17,16,
- 1,2,18,19,
- 17,18,32,3,
- 16,19,3,34
-};
-
-__constant const int gridTable8x8[] =
-{
- 0, 2, 3, 16, 17, 18, 19, 1,
- 66, 64, 80, 67, 82, 81, 65, 83,
- 131,144,128,130,147,129,145,146,
- 208,195,194,192,193,211,210,209,
- 21, 22, 23, 5, 4, 6, 7, 20,
- 86, 85, 69, 87, 70, 68, 84, 71,
- 151,133,149,150,135,148,132,134,
- 197,27,214,213,212,199,198,196
-
-};
-
-
-
-
-#define USE_SPATIAL_BATCHING 1
-#define USE_4x4_GRID 1
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut,
-int nContacts,float scale,int4 nSplit,int staticIdx)
-
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;
- int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;
-
- int aIdx = abs(aPtrAndSignBit );
- int bIdx = abs(bPtrAndSignBit);
-
- bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);
- bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);
-
-#if USE_SPATIAL_BATCHING
- int idx = (aStatic)? bIdx: aIdx;
- float4 p = gBodies[idx].m_pos;
- int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);
- int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);
- int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);
- int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);
-
-#else//USE_SPATIAL_BATCHING
- #if USE_4x4_GRID
- int aa = aIdx&3;
- int bb = bIdx&3;
- if (aStatic)
- aa = bb;
- if (bStatic)
- bb = aa;
-
- int gridIndex = aa + bb*4;
- int newIndex = gridTable4x4[gridIndex];
- #else//USE_4x4_GRID
- int aa = aIdx&7;
- int bb = bIdx&7;
- if (aStatic)
- aa = bb;
- if (bStatic)
- bb = aa;
-
- int gridIndex = aa + bb*8;
- int newIndex = gridTable8x8[gridIndex];
- #endif//USE_4x4_GRID
-#endif//USE_SPATIAL_BATCHING
-
-
- gSortDataOut[gIdx].x = newIndex;
- gSortDataOut[gIdx].y = gIdx;
- }
- else
- {
- gSortDataOut[gIdx].x = 0xffffffff;
- }
-}
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )
-{
- int gIdx = GET_GLOBAL_IDX;
- if( gIdx < cb.x )
- {
- gOut[gIdx] = gIn[gIdx];
- }
-}
-
-
-
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
deleted file mode 100644
index 1e6e3579b6..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverSetup2.h
+++ /dev/null
@@ -1,600 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverSetup2CL =
- "/*\n"
- "Copyright (c) 2012 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Takahiro Harada\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "///////////////////////////////////////\n"
- "// Vector\n"
- "///////////////////////////////////////\n"
- "__inline\n"
- "float fastDiv(float numerator, float denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "// return numerator/denominator; \n"
- "}\n"
- "__inline\n"
- "float4 fastDiv4(float4 numerator, float4 denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "}\n"
- "__inline\n"
- "float fastSqrtf(float f2)\n"
- "{\n"
- " return native_sqrt(f2);\n"
- "// return sqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastRSqrt(float f2)\n"
- "{\n"
- " return native_rsqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastLength4(float4 v)\n"
- "{\n"
- " return fast_length(v);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "float sqrtf(float a)\n"
- "{\n"
- "// return sqrt(a);\n"
- " return native_sqrt(a);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a, float4 b)\n"
- "{\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float length3(const float4 a)\n"
- "{\n"
- " return sqrtf(dot3F4(a,a));\n"
- "}\n"
- "__inline\n"
- "float dot4(const float4 a, const float4 b)\n"
- "{\n"
- " return dot( a, b );\n"
- "}\n"
- "// for height\n"
- "__inline\n"
- "float dot3w1(const float4 point, const float4 eqn)\n"
- "{\n"
- " return dot3F4(point,eqn) + eqn.w;\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "// float length = sqrtf(dot3F4(a, a));\n"
- "// return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 normalize4(const float4 a)\n"
- "{\n"
- " float length = sqrtf(dot4(a, a));\n"
- " return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
- "{\n"
- " float4 eqn;\n"
- " float4 ab = b-a;\n"
- " float4 ac = c-a;\n"
- " eqn = normalize3( cross3(ab, ac) );\n"
- " eqn.w = -dot3F4(eqn,a);\n"
- " return eqn;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Matrix3x3\n"
- "///////////////////////////////////////\n"
- "typedef struct\n"
- "{\n"
- " float4 m_row[3];\n"
- "}Matrix3x3;\n"
- "__inline\n"
- "Matrix3x3 mtZero();\n"
- "__inline\n"
- "Matrix3x3 mtIdentity();\n"
- "__inline\n"
- "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
- "__inline\n"
- "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b);\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b);\n"
- "__inline\n"
- "Matrix3x3 mtZero()\n"
- "{\n"
- " Matrix3x3 m;\n"
- " m.m_row[0] = (float4)(0.f);\n"
- " m.m_row[1] = (float4)(0.f);\n"
- " m.m_row[2] = (float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtIdentity()\n"
- "{\n"
- " Matrix3x3 m;\n"
- " m.m_row[0] = (float4)(1,0,0,0);\n"
- " m.m_row[1] = (float4)(0,1,0,0);\n"
- " m.m_row[2] = (float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
- "{\n"
- " Matrix3x3 out;\n"
- " out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
- "{\n"
- " Matrix3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " Matrix3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b)\n"
- "{\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a.m_row[0], b );\n"
- " ans.y = dot3F4( a.m_row[1], b );\n"
- " ans.z = dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b)\n"
- "{\n"
- " float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a, colx );\n"
- " ans.y = dot3F4( a, coly );\n"
- " ans.z = dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "#define WG_SIZE 64\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " Quaternion m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_shapeIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} Body;\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_invInertia;\n"
- " Matrix3x3 m_initInvInertia;\n"
- "} Shape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_linear;\n"
- " float4 m_worldPos[4];\n"
- " float4 m_center; \n"
- " float m_jacCoeffInv[4];\n"
- " float m_b[4];\n"
- " float m_appliedRambdaDt[4];\n"
- " float m_fJacCoeffInv[2]; \n"
- " float m_fAppliedRambdaDt[2]; \n"
- " u32 m_bodyA;\n"
- " u32 m_bodyB;\n"
- " int m_batchIdx;\n"
- " u32 m_paddings[1];\n"
- "} Constraint4;\n"
- "typedef struct\n"
- "{\n"
- " int m_nConstraints;\n"
- " int m_start;\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBuffer;\n"
- "typedef struct\n"
- "{\n"
- " int m_solveFriction;\n"
- " int m_maxBatch; // long batch really kills the performance\n"
- " int m_batchIdx;\n"
- " int m_nSplit;\n"
- "// int m_paddings[1];\n"
- "} ConstBufferBatchSolve;\n"
- " \n"
- "typedef struct \n"
- "{\n"
- " int m_valInt0;\n"
- " int m_valInt1;\n"
- " int m_valInt2;\n"
- " int m_valInt3;\n"
- " float m_val0;\n"
- " float m_val1;\n"
- " float m_val2;\n"
- " float m_val3;\n"
- "} SolverDebugInfo;\n"
- "// others\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void ReorderContactKernel(__global struct b3Contact4Data* in, __global struct b3Contact4Data* out, __global int2* sortData, int4 cb )\n"
- "{\n"
- " int nContacts = cb.x;\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int srcIdx = sortData[gIdx].y;\n"
- " out[gIdx] = in[srcIdx];\n"
- " }\n"
- "}\n"
- "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SetDeterminismSortDataChildShapeB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataOut, int nContacts)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int2 sd;\n"
- " sd.x = contactsIn[gIdx].m_childIndexB;\n"
- " sd.y = gIdx;\n"
- " sortDataOut[gIdx] = sd;\n"
- " }\n"
- "}\n"
- "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SetDeterminismSortDataChildShapeA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int2 sdIn;\n"
- " sdIn = sortDataInOut[gIdx];\n"
- " int2 sdOut;\n"
- " sdOut.x = contactsIn[sdIn.y].m_childIndexA;\n"
- " sdOut.y = sdIn.y;\n"
- " sortDataInOut[gIdx] = sdOut;\n"
- " }\n"
- "}\n"
- "__kernel __attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SetDeterminismSortDataBodyA(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int2 sdIn;\n"
- " sdIn = sortDataInOut[gIdx];\n"
- " int2 sdOut;\n"
- " sdOut.x = contactsIn[sdIn.y].m_bodyAPtrAndSignBit;\n"
- " sdOut.y = sdIn.y;\n"
- " sortDataInOut[gIdx] = sdOut;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SetDeterminismSortDataBodyB(__global struct b3Contact4Data* contactsIn, __global int2* sortDataInOut, int nContacts)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int2 sdIn;\n"
- " sdIn = sortDataInOut[gIdx];\n"
- " int2 sdOut;\n"
- " sdOut.x = contactsIn[sdIn.y].m_bodyBPtrAndSignBit;\n"
- " sdOut.y = sdIn.y;\n"
- " sortDataInOut[gIdx] = sdOut;\n"
- " }\n"
- "}\n"
- "typedef struct\n"
- "{\n"
- " int m_nContacts;\n"
- " int m_staticIdx;\n"
- " float m_scale;\n"
- " int m_nSplit;\n"
- "} ConstBufferSSD;\n"
- "__constant const int gridTable4x4[] = \n"
- "{\n"
- " 0,1,17,16,\n"
- " 1,2,18,19,\n"
- " 17,18,32,3,\n"
- " 16,19,3,34\n"
- "};\n"
- "__constant const int gridTable8x8[] = \n"
- "{\n"
- " 0, 2, 3, 16, 17, 18, 19, 1,\n"
- " 66, 64, 80, 67, 82, 81, 65, 83,\n"
- " 131,144,128,130,147,129,145,146,\n"
- " 208,195,194,192,193,211,210,209,\n"
- " 21, 22, 23, 5, 4, 6, 7, 20,\n"
- " 86, 85, 69, 87, 70, 68, 84, 71,\n"
- " 151,133,149,150,135,148,132,134,\n"
- " 197,27,214,213,212,199,198,196\n"
- " \n"
- "};\n"
- "#define USE_SPATIAL_BATCHING 1\n"
- "#define USE_4x4_GRID 1\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void SetSortDataKernel(__global struct b3Contact4Data* gContact, __global Body* gBodies, __global int2* gSortDataOut, \n"
- "int nContacts,float scale,int4 nSplit,int staticIdx)\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " \n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int aPtrAndSignBit = gContact[gIdx].m_bodyAPtrAndSignBit;\n"
- " int bPtrAndSignBit = gContact[gIdx].m_bodyBPtrAndSignBit;\n"
- " int aIdx = abs(aPtrAndSignBit );\n"
- " int bIdx = abs(bPtrAndSignBit);\n"
- " bool aStatic = (aPtrAndSignBit<0) ||(aPtrAndSignBit==staticIdx);\n"
- " bool bStatic = (bPtrAndSignBit<0) ||(bPtrAndSignBit==staticIdx);\n"
- "#if USE_SPATIAL_BATCHING \n"
- " int idx = (aStatic)? bIdx: aIdx;\n"
- " float4 p = gBodies[idx].m_pos;\n"
- " int xIdx = (int)((p.x-((p.x<0.f)?1.f:0.f))*scale) & (nSplit.x-1);\n"
- " int yIdx = (int)((p.y-((p.y<0.f)?1.f:0.f))*scale) & (nSplit.y-1);\n"
- " int zIdx = (int)((p.z-((p.z<0.f)?1.f:0.f))*scale) & (nSplit.z-1);\n"
- " int newIndex = (xIdx+yIdx*nSplit.x+zIdx*nSplit.x*nSplit.y);\n"
- " \n"
- "#else//USE_SPATIAL_BATCHING\n"
- " #if USE_4x4_GRID\n"
- " int aa = aIdx&3;\n"
- " int bb = bIdx&3;\n"
- " if (aStatic)\n"
- " aa = bb;\n"
- " if (bStatic)\n"
- " bb = aa;\n"
- " int gridIndex = aa + bb*4;\n"
- " int newIndex = gridTable4x4[gridIndex];\n"
- " #else//USE_4x4_GRID\n"
- " int aa = aIdx&7;\n"
- " int bb = bIdx&7;\n"
- " if (aStatic)\n"
- " aa = bb;\n"
- " if (bStatic)\n"
- " bb = aa;\n"
- " int gridIndex = aa + bb*8;\n"
- " int newIndex = gridTable8x8[gridIndex];\n"
- " #endif//USE_4x4_GRID\n"
- "#endif//USE_SPATIAL_BATCHING\n"
- " gSortDataOut[gIdx].x = newIndex;\n"
- " gSortDataOut[gIdx].y = gIdx;\n"
- " }\n"
- " else\n"
- " {\n"
- " gSortDataOut[gIdx].x = 0xffffffff;\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void CopyConstraintKernel(__global struct b3Contact4Data* gIn, __global struct b3Contact4Data* gOut, int4 cb )\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " if( gIdx < cb.x )\n"
- " {\n"
- " gOut[gIdx] = gIn[gIdx];\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
deleted file mode 100644
index a21a08c3b4..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.cl
+++ /dev/null
@@ -1,968 +0,0 @@
-/*
-Copyright (c) 2013 Advanced Micro Devices, Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-//Originally written by Erwin Coumans
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3Contact4Data.h"
-
-#pragma OPENCL EXTENSION cl_amd_printf : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable
-#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable
-
-
-#ifdef cl_ext_atomic_counters_32
-#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable
-#else
-#define counter32_t volatile global int*
-#endif
-
-typedef unsigned int u32;
-typedef unsigned short u16;
-typedef unsigned char u8;
-
-#define GET_GROUP_IDX get_group_id(0)
-#define GET_LOCAL_IDX get_local_id(0)
-#define GET_GLOBAL_IDX get_global_id(0)
-#define GET_GROUP_SIZE get_local_size(0)
-#define GET_NUM_GROUPS get_num_groups(0)
-#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)
-#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)
-#define AtomInc(x) atom_inc(&(x))
-#define AtomInc1(x, out) out = atom_inc(&(x))
-#define AppendInc(x, out) out = atomic_inc(x)
-#define AtomAdd(x, value) atom_add(&(x), value)
-#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )
-#define AtomXhg(x, value) atom_xchg ( &(x), value )
-
-
-#define SELECT_UINT4( b, a, condition ) select( b,a,condition )
-
-#define make_float4 (float4)
-#define make_float2 (float2)
-#define make_uint4 (uint4)
-#define make_int4 (int4)
-#define make_uint2 (uint2)
-#define make_int2 (int2)
-
-
-#define max2 max
-#define min2 min
-
-
-///////////////////////////////////////
-// Vector
-///////////////////////////////////////
-__inline
-float fastDiv(float numerator, float denominator)
-{
- return native_divide(numerator, denominator);
-// return numerator/denominator;
-}
-
-__inline
-float4 fastDiv4(float4 numerator, float4 denominator)
-{
- return native_divide(numerator, denominator);
-}
-
-__inline
-float fastSqrtf(float f2)
-{
- return native_sqrt(f2);
-// return sqrt(f2);
-}
-
-__inline
-float fastRSqrt(float f2)
-{
- return native_rsqrt(f2);
-}
-
-__inline
-float fastLength4(float4 v)
-{
- return fast_length(v);
-}
-
-__inline
-float4 fastNormalize4(float4 v)
-{
- return fast_normalize(v);
-}
-
-
-__inline
-float sqrtf(float a)
-{
-// return sqrt(a);
- return native_sqrt(a);
-}
-
-__inline
-float4 cross3(float4 a1, float4 b1)
-{
-
- float4 a=make_float4(a1.xyz,0.f);
- float4 b=make_float4(b1.xyz,0.f);
- //float4 a=a1;
- //float4 b=b1;
- return cross(a,b);
-}
-
-__inline
-float dot3F4(float4 a, float4 b)
-{
- float4 a1 = make_float4(a.xyz,0.f);
- float4 b1 = make_float4(b.xyz,0.f);
- return dot(a1, b1);
-}
-
-__inline
-float length3(const float4 a)
-{
- return sqrtf(dot3F4(a,a));
-}
-
-__inline
-float dot4(const float4 a, const float4 b)
-{
- return dot( a, b );
-}
-
-// for height
-__inline
-float dot3w1(const float4 point, const float4 eqn)
-{
- return dot3F4(point,eqn) + eqn.w;
-}
-
-__inline
-float4 normalize3(const float4 a)
-{
- float4 n = make_float4(a.x, a.y, a.z, 0.f);
- return fastNormalize4( n );
-// float length = sqrtf(dot3F4(a, a));
-// return 1.f/length * a;
-}
-
-__inline
-float4 normalize4(const float4 a)
-{
- float length = sqrtf(dot4(a, a));
- return 1.f/length * a;
-}
-
-__inline
-float4 createEquation(const float4 a, const float4 b, const float4 c)
-{
- float4 eqn;
- float4 ab = b-a;
- float4 ac = c-a;
- eqn = normalize3( cross3(ab, ac) );
- eqn.w = -dot3F4(eqn,a);
- return eqn;
-}
-
-///////////////////////////////////////
-// Matrix3x3
-///////////////////////////////////////
-
-typedef struct
-{
- float4 m_row[3];
-}Matrix3x3;
-
-__inline
-Matrix3x3 mtZero();
-
-__inline
-Matrix3x3 mtIdentity();
-
-__inline
-Matrix3x3 mtTranspose(Matrix3x3 m);
-
-__inline
-Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b);
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b);
-
-__inline
-Matrix3x3 mtZero()
-{
- Matrix3x3 m;
- m.m_row[0] = (float4)(0.f);
- m.m_row[1] = (float4)(0.f);
- m.m_row[2] = (float4)(0.f);
- return m;
-}
-
-__inline
-Matrix3x3 mtIdentity()
-{
- Matrix3x3 m;
- m.m_row[0] = (float4)(1,0,0,0);
- m.m_row[1] = (float4)(0,1,0,0);
- m.m_row[2] = (float4)(0,0,1,0);
- return m;
-}
-
-__inline
-Matrix3x3 mtTranspose(Matrix3x3 m)
-{
- Matrix3x3 out;
- out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);
- out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);
- out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);
- return out;
-}
-
-__inline
-Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)
-{
- Matrix3x3 transB;
- transB = mtTranspose( b );
- Matrix3x3 ans;
- // why this doesn't run when 0ing in the for{}
- a.m_row[0].w = 0.f;
- a.m_row[1].w = 0.f;
- a.m_row[2].w = 0.f;
- for(int i=0; i<3; i++)
- {
-// a.m_row[i].w = 0.f;
- ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);
- ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);
- ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);
- ans.m_row[i].w = 0.f;
- }
- return ans;
-}
-
-__inline
-float4 mtMul1(Matrix3x3 a, float4 b)
-{
- float4 ans;
- ans.x = dot3F4( a.m_row[0], b );
- ans.y = dot3F4( a.m_row[1], b );
- ans.z = dot3F4( a.m_row[2], b );
- ans.w = 0.f;
- return ans;
-}
-
-__inline
-float4 mtMul3(float4 a, Matrix3x3 b)
-{
- float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);
- float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);
- float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);
-
- float4 ans;
- ans.x = dot3F4( a, colx );
- ans.y = dot3F4( a, coly );
- ans.z = dot3F4( a, colz );
- return ans;
-}
-
-///////////////////////////////////////
-// Quaternion
-///////////////////////////////////////
-
-typedef float4 Quaternion;
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b);
-
-__inline
-Quaternion qtNormalize(Quaternion in);
-
-__inline
-float4 qtRotate(Quaternion q, float4 vec);
-
-__inline
-Quaternion qtInvert(Quaternion q);
-
-
-
-
-
-__inline
-Quaternion qtMul(Quaternion a, Quaternion b)
-{
- Quaternion ans;
- ans = cross3( a, b );
- ans += a.w*b+b.w*a;
-// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);
- ans.w = a.w*b.w - dot3F4(a, b);
- return ans;
-}
-
-__inline
-Quaternion qtNormalize(Quaternion in)
-{
- return fastNormalize4(in);
-// in /= length( in );
-// return in;
-}
-__inline
-float4 qtRotate(Quaternion q, float4 vec)
-{
- Quaternion qInv = qtInvert( q );
- float4 vcpy = vec;
- vcpy.w = 0.f;
- float4 out = qtMul(qtMul(q,vcpy),qInv);
- return out;
-}
-
-__inline
-Quaternion qtInvert(Quaternion q)
-{
- return (Quaternion)(-q.xyz, q.w);
-}
-
-__inline
-float4 qtInvRotate(const Quaternion q, float4 vec)
-{
- return qtRotate( qtInvert( q ), vec );
-}
-
-
-
-
-#define WG_SIZE 64
-
-typedef struct
-{
- float4 m_pos;
- Quaternion m_quat;
- float4 m_linVel;
- float4 m_angVel;
-
- u32 m_shapeIdx;
- float m_invMass;
- float m_restituitionCoeff;
- float m_frictionCoeff;
-} Body;
-
-
-
-typedef struct
-{
- Matrix3x3 m_invInertia;
- Matrix3x3 m_initInvInertia;
-} Shape;
-
-typedef struct
-{
- float4 m_linear;
- float4 m_worldPos[4];
- float4 m_center;
- float m_jacCoeffInv[4];
- float m_b[4];
- float m_appliedRambdaDt[4];
-
- float m_fJacCoeffInv[2];
- float m_fAppliedRambdaDt[2];
-
- u32 m_bodyA;
- u32 m_bodyB;
- int m_batchIdx;
- u32 m_paddings;
-} Constraint4;
-
-
-
-
-
-
-__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)
-{
- int i = GET_GLOBAL_IDX;
-
- if( i < numContactManifolds)
- {
- int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;
- bool isFixedA = (pa <0) || (pa == fixedBodyIndex);
- int bodyIndexA = abs(pa);
- if (!isFixedA)
- {
- AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);
- }
- barrier(CLK_GLOBAL_MEM_FENCE);
- int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;
- bool isFixedB = (pb <0) || (pb == fixedBodyIndex);
- int bodyIndexB = abs(pb);
- if (!isFixedB)
- {
- AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);
- }
- }
-}
-
-__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)
-{
- int i = GET_GLOBAL_IDX;
-
- if( i < numSplitBodies)
- {
- linearVelocities[i] = make_float4(0);
- angularVelocities[i] = make_float4(0);
- }
-}
-
-
-__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
-__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
-{
- int i = GET_GLOBAL_IDX;
- if (i<numBodies)
- {
- if (gBodies[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- float factor = 1.f/((float)count);
- float4 averageLinVel = make_float4(0.f);
- float4 averageAngVel = make_float4(0.f);
-
- for (int j=0;j<count;j++)
- {
- averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;
- averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;
- }
-
- for (int j=0;j<count;j++)
- {
- deltaLinearVelocities[bodyOffset+j] = averageLinVel;
- deltaAngularVelocities[bodyOffset+j] = averageAngVel;
- }
-
- }//bodies[i].m_invMass
- }//i<numBodies
-}
-
-
-
-void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)
-{
- *linear = make_float4(n.xyz,0.f);
- *angular0 = cross3(r0, n);
- *angular1 = -cross3(r1, n);
-}
-
-
-float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )
-{
- return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);
-}
-
-
-float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,
- float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)
-{
- // linear0,1 are normlized
- float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;
- float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);
- float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;
- float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);
- return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);
-}
-
-
-void btPlaneSpace1 (float4 n, float4* p, float4* q);
- void btPlaneSpace1 (float4 n, float4* p, float4* q)
-{
- if (fabs(n.z) > 0.70710678f) {
- // choose p in y-z plane
- float a = n.y*n.y + n.z*n.z;
- float k = 1.f/sqrt(a);
- p[0].x = 0;
- p[0].y = -n.z*k;
- p[0].z = n.y*k;
- // set q = n x p
- q[0].x = a*k;
- q[0].y = -n.x*p[0].z;
- q[0].z = n.x*p[0].y;
- }
- else {
- // choose p in x-y plane
- float a = n.x*n.x + n.y*n.y;
- float k = 1.f/sqrt(a);
- p[0].x = -n.y*k;
- p[0].y = n.x*k;
- p[0].z = 0;
- // set q = n x p
- q[0].x = -n.z*p[0].y;
- q[0].y = n.z*p[0].x;
- q[0].z = a*k;
- }
-}
-
-
-
-
-
-void solveContact(__global Constraint4* cs,
- float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,
- float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,
- float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)
-{
- float minRambdaDt = 0;
- float maxRambdaDt = FLT_MAX;
-
- for(int ic=0; ic<4; ic++)
- {
- if( cs->m_jacCoeffInv[ic] == 0.f ) continue;
-
- float4 angular0, angular1, linear;
- float4 r0 = cs->m_worldPos[ic] - posA;
- float4 r1 = cs->m_worldPos[ic] - posB;
- setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );
-
-
-
- float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1,
- *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];
- rambdaDt *= cs->m_jacCoeffInv[ic];
-
-
- {
- float prevSum = cs->m_appliedRambdaDt[ic];
- float updated = prevSum;
- updated += rambdaDt;
- updated = max2( updated, minRambdaDt );
- updated = min2( updated, maxRambdaDt );
- rambdaDt = updated - prevSum;
- cs->m_appliedRambdaDt[ic] = updated;
- }
-
-
- float4 linImp0 = invMassA*linear*rambdaDt;
- float4 linImp1 = invMassB*(-linear)*rambdaDt;
- float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
- float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
-
-
- if (invMassA)
- {
- *dLinVelA += linImp0;
- *dAngVelA += angImp0;
- }
- if (invMassB)
- {
- *dLinVelB += linImp1;
- *dAngVelB += angImp1;
- }
- }
-}
-
-
-// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
-
-
-void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
-__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
-__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
-{
-
- //float frictionCoeff = ldsCs[0].m_linear.w;
- int aIdx = ldsCs[0].m_bodyA;
- int bIdx = ldsCs[0].m_bodyB;
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
-
-
- float4 dLinVelA = make_float4(0,0,0,0);
- float4 dAngVelA = make_float4(0,0,0,0);
- float4 dLinVelB = make_float4(0,0,0,0);
- float4 dAngVelB = make_float4(0,0,0,0);
-
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[0].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
-
- if (invMassA)
- {
- dLinVelA = deltaLinearVelocities[splitIndexA];
- dAngVelA = deltaAngularVelocities[splitIndexA];
- }
-
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[0].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
-
- if (invMassB)
- {
- dLinVelB = deltaLinearVelocities[splitIndexB];
- dAngVelB = deltaAngularVelocities[splitIndexB];
- }
-
- solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
- posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);
-
- if (invMassA)
- {
- deltaLinearVelocities[splitIndexA] = dLinVelA;
- deltaAngularVelocities[splitIndexA] = dAngVelA;
- }
- if (invMassB)
- {
- deltaLinearVelocities[splitIndexB] = dLinVelB;
- deltaAngularVelocities[splitIndexB] = dAngVelB;
- }
-
-}
-
-
-__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
-__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
-float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
-)
-{
- int i = GET_GLOBAL_IDX;
- if (i<numManifolds)
- {
- solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
- }
-}
-
-
-
-
-void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,
- __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
- __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)
-{
- float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;
- int aIdx = ldsCs[0].m_bodyA;
- int bIdx = ldsCs[0].m_bodyB;
-
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
-
-
- float4 dLinVelA = make_float4(0,0,0,0);
- float4 dAngVelA = make_float4(0,0,0,0);
- float4 dLinVelB = make_float4(0,0,0,0);
- float4 dAngVelB = make_float4(0,0,0,0);
-
- int bodyOffsetA = offsetSplitBodies[aIdx];
- int constraintOffsetA = contactConstraintOffsets[0].x;
- int splitIndexA = bodyOffsetA+constraintOffsetA;
-
- if (invMassA)
- {
- dLinVelA = deltaLinearVelocities[splitIndexA];
- dAngVelA = deltaAngularVelocities[splitIndexA];
- }
-
- int bodyOffsetB = offsetSplitBodies[bIdx];
- int constraintOffsetB = contactConstraintOffsets[0].y;
- int splitIndexB= bodyOffsetB+constraintOffsetB;
-
- if (invMassB)
- {
- dLinVelB = deltaLinearVelocities[splitIndexB];
- dAngVelB = deltaAngularVelocities[splitIndexB];
- }
-
-
-
-
- {
- float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};
- float minRambdaDt[4] = {0.f,0.f,0.f,0.f};
-
- float sum = 0;
- for(int j=0; j<4; j++)
- {
- sum +=ldsCs[0].m_appliedRambdaDt[j];
- }
- frictionCoeff = 0.7f;
- for(int j=0; j<4; j++)
- {
- maxRambdaDt[j] = frictionCoeff*sum;
- minRambdaDt[j] = -maxRambdaDt[j];
- }
-
-
-// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,
-// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );
-
-
- {
-
- __global Constraint4* cs = ldsCs;
-
- if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;
- const float4 center = cs->m_center;
-
- float4 n = -cs->m_linear;
-
- float4 tangent[2];
- btPlaneSpace1(n,&tangent[0],&tangent[1]);
- float4 angular0, angular1, linear;
- float4 r0 = center - posA;
- float4 r1 = center - posB;
- for(int i=0; i<2; i++)
- {
- setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );
- float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,
- linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );
- rambdaDt *= cs->m_fJacCoeffInv[i];
-
- {
- float prevSum = cs->m_fAppliedRambdaDt[i];
- float updated = prevSum;
- updated += rambdaDt;
- updated = max2( updated, minRambdaDt[i] );
- updated = min2( updated, maxRambdaDt[i] );
- rambdaDt = updated - prevSum;
- cs->m_fAppliedRambdaDt[i] = updated;
- }
-
- float4 linImp0 = invMassA*linear*rambdaDt;
- float4 linImp1 = invMassB*(-linear)*rambdaDt;
- float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;
- float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;
-
- dLinVelA += linImp0;
- dAngVelA += angImp0;
- dLinVelB += linImp1;
- dAngVelB += angImp1;
- }
- { // angular damping for point constraint
- float4 ab = normalize3( posB - posA );
- float4 ac = normalize3( center - posA );
- if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))
- {
- float angNA = dot3F4( n, angVelA );
- float angNB = dot3F4( n, angVelB );
-
- dAngVelA -= (angNA*0.1f)*n;
- dAngVelB -= (angNB*0.1f)*n;
- }
- }
- }
-
-
-
- }
-
- if (invMassA)
- {
- deltaLinearVelocities[splitIndexA] = dLinVelA;
- deltaAngularVelocities[splitIndexA] = dAngVelA;
- }
- if (invMassB)
- {
- deltaLinearVelocities[splitIndexB] = dLinVelB;
- deltaAngularVelocities[splitIndexB] = dAngVelB;
- }
-
-
-}
-
-
-__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,
- __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,
- __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,
- float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds
-)
-{
- int i = GET_GLOBAL_IDX;
- if (i<numManifolds)
- {
- solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);
- }
-}
-
-
-__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,
- __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)
-{
- int i = GET_GLOBAL_IDX;
- if (i<numBodies)
- {
- if (gBodies[i].m_invMass)
- {
- int bodyOffset = offsetSplitBodies[i];
- int count = bodyCount[i];
- if (count)
- {
- gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];
- gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];
- }
- }
- }
-}
-
-
-
-void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,
- const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB,
- __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,
- Constraint4* dstC )
-{
- dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);
- dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);
-
- float dtInv = 1.f/dt;
- for(int ic=0; ic<4; ic++)
- {
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;
-
-
- dstC->m_linear = src->m_worldNormalOnB;
- dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );
- for(int ic=0; ic<4; ic++)
- {
- float4 r0 = src->m_worldPosB[ic] - posA;
- float4 r1 = src->m_worldPosB[ic] - posB;
-
- if( ic >= src->m_worldNormalOnB.w )//npoints
- {
- dstC->m_jacCoeffInv[ic] = 0.f;
- continue;
- }
-
- float relVelN;
- {
- float4 linear, angular0, angular1;
- setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);
-
- dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);
-
- relVelN = calcRelVel(linear, -linear, angular0, angular1,
- linVelA, angVelA, linVelB, angVelB);
-
- float e = 0.f;//src->getRestituitionCoeff();
- if( relVelN*relVelN < 0.004f ) e = 0.f;
-
- dstC->m_b[ic] = e*relVelN;
- //float penetration = src->m_worldPosB[ic].w;
- dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;
- dstC->m_appliedRambdaDt[ic] = 0.f;
- }
- }
-
- if( src->m_worldNormalOnB.w > 0 )//npoints
- { // prepare friction
- float4 center = make_float4(0.f);
- for(int i=0; i<src->m_worldNormalOnB.w; i++)
- center += src->m_worldPosB[i];
- center /= (float)src->m_worldNormalOnB.w;
-
- float4 tangent[2];
- btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);
-
- float4 r[2];
- r[0] = center - posA;
- r[1] = center - posB;
-
- for(int i=0; i<2; i++)
- {
- float4 linear, angular0, angular1;
- setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);
-
- dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,
- invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);
- dstC->m_fAppliedRambdaDt[i] = 0.f;
- }
- dstC->m_center = center;
- }
-
- for(int i=0; i<4; i++)
- {
- if( i<src->m_worldNormalOnB.w )
- {
- dstC->m_worldPos[i] = src->m_worldPosB[i];
- }
- else
- {
- dstC->m_worldPos[i] = make_float4(0.f);
- }
- }
-}
-
-
-__kernel
-__attribute__((reqd_work_group_size(WG_SIZE,1,1)))
-void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut,
-__global const unsigned int* bodyCount,
-int nContacts,
-float dt,
-float positionDrift,
-float positionConstraintCoeff
-)
-{
- int gIdx = GET_GLOBAL_IDX;
-
- if( gIdx < nContacts )
- {
- int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);
- int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);
-
- float4 posA = gBodies[aIdx].m_pos;
- float4 linVelA = gBodies[aIdx].m_linVel;
- float4 angVelA = gBodies[aIdx].m_angVel;
- float invMassA = gBodies[aIdx].m_invMass;
- Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;
-
- float4 posB = gBodies[bIdx].m_pos;
- float4 linVelB = gBodies[bIdx].m_linVel;
- float4 angVelB = gBodies[bIdx].m_angVel;
- float invMassB = gBodies[bIdx].m_invMass;
- Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;
-
- Constraint4 cs;
-
- float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;
- float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;
-
- setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,
- &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,
- &cs );
-
- cs.m_batchIdx = gContact[gIdx].m_batchIdx;
-
- gConstraintOut[gIdx] = cs;
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
deleted file mode 100644
index f4d98d9941..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/solverUtils.h
+++ /dev/null
@@ -1,908 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* solverUtilsCL =
- "/*\n"
- "Copyright (c) 2013 Advanced Micro Devices, Inc. \n"
- "This software is provided 'as-is', without any express or implied warranty.\n"
- "In no event will the authors be held liable for any damages arising from the use of this software.\n"
- "Permission is granted to anyone to use this software for any purpose, \n"
- "including commercial applications, and to alter it and redistribute it freely, \n"
- "subject to the following restrictions:\n"
- "1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\n"
- "2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\n"
- "3. This notice may not be removed or altered from any source distribution.\n"
- "*/\n"
- "//Originally written by Erwin Coumans\n"
- "#ifndef B3_CONTACT4DATA_H\n"
- "#define B3_CONTACT4DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "typedef struct b3Contact4Data b3Contact4Data_t;\n"
- "struct b3Contact4Data\n"
- "{\n"
- " b3Float4 m_worldPosB[4];\n"
- "// b3Float4 m_localPosA[4];\n"
- "// b3Float4 m_localPosB[4];\n"
- " b3Float4 m_worldNormalOnB; // w: m_nPoints\n"
- " unsigned short m_restituitionCoeffCmp;\n"
- " unsigned short m_frictionCoeffCmp;\n"
- " int m_batchIdx;\n"
- " int m_bodyAPtrAndSignBit;//x:m_bodyAPtr, y:m_bodyBPtr\n"
- " int m_bodyBPtrAndSignBit;\n"
- " int m_childIndexA;\n"
- " int m_childIndexB;\n"
- " int m_unused1;\n"
- " int m_unused2;\n"
- "};\n"
- "inline int b3Contact4Data_getNumPoints(const struct b3Contact4Data* contact)\n"
- "{\n"
- " return (int)contact->m_worldNormalOnB.w;\n"
- "};\n"
- "inline void b3Contact4Data_setNumPoints(struct b3Contact4Data* contact, int numPoints)\n"
- "{\n"
- " contact->m_worldNormalOnB.w = (float)numPoints;\n"
- "};\n"
- "#endif //B3_CONTACT4DATA_H\n"
- "#pragma OPENCL EXTENSION cl_amd_printf : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_base_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_local_int32_extended_atomics : enable\n"
- "#pragma OPENCL EXTENSION cl_khr_global_int32_extended_atomics : enable\n"
- "#ifdef cl_ext_atomic_counters_32\n"
- "#pragma OPENCL EXTENSION cl_ext_atomic_counters_32 : enable\n"
- "#else\n"
- "#define counter32_t volatile global int*\n"
- "#endif\n"
- "typedef unsigned int u32;\n"
- "typedef unsigned short u16;\n"
- "typedef unsigned char u8;\n"
- "#define GET_GROUP_IDX get_group_id(0)\n"
- "#define GET_LOCAL_IDX get_local_id(0)\n"
- "#define GET_GLOBAL_IDX get_global_id(0)\n"
- "#define GET_GROUP_SIZE get_local_size(0)\n"
- "#define GET_NUM_GROUPS get_num_groups(0)\n"
- "#define GROUP_LDS_BARRIER barrier(CLK_LOCAL_MEM_FENCE)\n"
- "#define GROUP_MEM_FENCE mem_fence(CLK_LOCAL_MEM_FENCE)\n"
- "#define AtomInc(x) atom_inc(&(x))\n"
- "#define AtomInc1(x, out) out = atom_inc(&(x))\n"
- "#define AppendInc(x, out) out = atomic_inc(x)\n"
- "#define AtomAdd(x, value) atom_add(&(x), value)\n"
- "#define AtomCmpxhg(x, cmp, value) atom_cmpxchg( &(x), cmp, value )\n"
- "#define AtomXhg(x, value) atom_xchg ( &(x), value )\n"
- "#define SELECT_UINT4( b, a, condition ) select( b,a,condition )\n"
- "#define make_float4 (float4)\n"
- "#define make_float2 (float2)\n"
- "#define make_uint4 (uint4)\n"
- "#define make_int4 (int4)\n"
- "#define make_uint2 (uint2)\n"
- "#define make_int2 (int2)\n"
- "#define max2 max\n"
- "#define min2 min\n"
- "///////////////////////////////////////\n"
- "// Vector\n"
- "///////////////////////////////////////\n"
- "__inline\n"
- "float fastDiv(float numerator, float denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "// return numerator/denominator; \n"
- "}\n"
- "__inline\n"
- "float4 fastDiv4(float4 numerator, float4 denominator)\n"
- "{\n"
- " return native_divide(numerator, denominator); \n"
- "}\n"
- "__inline\n"
- "float fastSqrtf(float f2)\n"
- "{\n"
- " return native_sqrt(f2);\n"
- "// return sqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastRSqrt(float f2)\n"
- "{\n"
- " return native_rsqrt(f2);\n"
- "}\n"
- "__inline\n"
- "float fastLength4(float4 v)\n"
- "{\n"
- " return fast_length(v);\n"
- "}\n"
- "__inline\n"
- "float4 fastNormalize4(float4 v)\n"
- "{\n"
- " return fast_normalize(v);\n"
- "}\n"
- "__inline\n"
- "float sqrtf(float a)\n"
- "{\n"
- "// return sqrt(a);\n"
- " return native_sqrt(a);\n"
- "}\n"
- "__inline\n"
- "float4 cross3(float4 a1, float4 b1)\n"
- "{\n"
- " float4 a=make_float4(a1.xyz,0.f);\n"
- " float4 b=make_float4(b1.xyz,0.f);\n"
- " //float4 a=a1;\n"
- " //float4 b=b1;\n"
- " return cross(a,b);\n"
- "}\n"
- "__inline\n"
- "float dot3F4(float4 a, float4 b)\n"
- "{\n"
- " float4 a1 = make_float4(a.xyz,0.f);\n"
- " float4 b1 = make_float4(b.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- "}\n"
- "__inline\n"
- "float length3(const float4 a)\n"
- "{\n"
- " return sqrtf(dot3F4(a,a));\n"
- "}\n"
- "__inline\n"
- "float dot4(const float4 a, const float4 b)\n"
- "{\n"
- " return dot( a, b );\n"
- "}\n"
- "// for height\n"
- "__inline\n"
- "float dot3w1(const float4 point, const float4 eqn)\n"
- "{\n"
- " return dot3F4(point,eqn) + eqn.w;\n"
- "}\n"
- "__inline\n"
- "float4 normalize3(const float4 a)\n"
- "{\n"
- " float4 n = make_float4(a.x, a.y, a.z, 0.f);\n"
- " return fastNormalize4( n );\n"
- "// float length = sqrtf(dot3F4(a, a));\n"
- "// return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 normalize4(const float4 a)\n"
- "{\n"
- " float length = sqrtf(dot4(a, a));\n"
- " return 1.f/length * a;\n"
- "}\n"
- "__inline\n"
- "float4 createEquation(const float4 a, const float4 b, const float4 c)\n"
- "{\n"
- " float4 eqn;\n"
- " float4 ab = b-a;\n"
- " float4 ac = c-a;\n"
- " eqn = normalize3( cross3(ab, ac) );\n"
- " eqn.w = -dot3F4(eqn,a);\n"
- " return eqn;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Matrix3x3\n"
- "///////////////////////////////////////\n"
- "typedef struct\n"
- "{\n"
- " float4 m_row[3];\n"
- "}Matrix3x3;\n"
- "__inline\n"
- "Matrix3x3 mtZero();\n"
- "__inline\n"
- "Matrix3x3 mtIdentity();\n"
- "__inline\n"
- "Matrix3x3 mtTranspose(Matrix3x3 m);\n"
- "__inline\n"
- "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b);\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b);\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b);\n"
- "__inline\n"
- "Matrix3x3 mtZero()\n"
- "{\n"
- " Matrix3x3 m;\n"
- " m.m_row[0] = (float4)(0.f);\n"
- " m.m_row[1] = (float4)(0.f);\n"
- " m.m_row[2] = (float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtIdentity()\n"
- "{\n"
- " Matrix3x3 m;\n"
- " m.m_row[0] = (float4)(1,0,0,0);\n"
- " m.m_row[1] = (float4)(0,1,0,0);\n"
- " m.m_row[2] = (float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtTranspose(Matrix3x3 m)\n"
- "{\n"
- " Matrix3x3 out;\n"
- " out.m_row[0] = (float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Matrix3x3 mtMul(Matrix3x3 a, Matrix3x3 b)\n"
- "{\n"
- " Matrix3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " Matrix3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul1(Matrix3x3 a, float4 b)\n"
- "{\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a.m_row[0], b );\n"
- " ans.y = dot3F4( a.m_row[1], b );\n"
- " ans.z = dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "float4 mtMul3(float4 a, Matrix3x3 b)\n"
- "{\n"
- " float4 colx = make_float4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " float4 coly = make_float4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " float4 colz = make_float4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " float4 ans;\n"
- " ans.x = dot3F4( a, colx );\n"
- " ans.y = dot3F4( a, coly );\n"
- " ans.z = dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "///////////////////////////////////////\n"
- "// Quaternion\n"
- "///////////////////////////////////////\n"
- "typedef float4 Quaternion;\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b);\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in);\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec);\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q);\n"
- "__inline\n"
- "Quaternion qtMul(Quaternion a, Quaternion b)\n"
- "{\n"
- " Quaternion ans;\n"
- " ans = cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtNormalize(Quaternion in)\n"
- "{\n"
- " return fastNormalize4(in);\n"
- "// in /= length( in );\n"
- "// return in;\n"
- "}\n"
- "__inline\n"
- "float4 qtRotate(Quaternion q, float4 vec)\n"
- "{\n"
- " Quaternion qInv = qtInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = qtMul(qtMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "Quaternion qtInvert(Quaternion q)\n"
- "{\n"
- " return (Quaternion)(-q.xyz, q.w);\n"
- "}\n"
- "__inline\n"
- "float4 qtInvRotate(const Quaternion q, float4 vec)\n"
- "{\n"
- " return qtRotate( qtInvert( q ), vec );\n"
- "}\n"
- "#define WG_SIZE 64\n"
- "typedef struct\n"
- "{\n"
- " float4 m_pos;\n"
- " Quaternion m_quat;\n"
- " float4 m_linVel;\n"
- " float4 m_angVel;\n"
- " u32 m_shapeIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "} Body;\n"
- "typedef struct\n"
- "{\n"
- " Matrix3x3 m_invInertia;\n"
- " Matrix3x3 m_initInvInertia;\n"
- "} Shape;\n"
- "typedef struct\n"
- "{\n"
- " float4 m_linear;\n"
- " float4 m_worldPos[4];\n"
- " float4 m_center; \n"
- " float m_jacCoeffInv[4];\n"
- " float m_b[4];\n"
- " float m_appliedRambdaDt[4];\n"
- " float m_fJacCoeffInv[2]; \n"
- " float m_fAppliedRambdaDt[2]; \n"
- " u32 m_bodyA;\n"
- " u32 m_bodyB;\n"
- " int m_batchIdx;\n"
- " u32 m_paddings;\n"
- "} Constraint4;\n"
- "__kernel void CountBodiesKernel(__global struct b3Contact4Data* manifoldPtr, __global unsigned int* bodyCount, __global int2* contactConstraintOffsets, int numContactManifolds, int fixedBodyIndex)\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " \n"
- " if( i < numContactManifolds)\n"
- " {\n"
- " int pa = manifoldPtr[i].m_bodyAPtrAndSignBit;\n"
- " bool isFixedA = (pa <0) || (pa == fixedBodyIndex);\n"
- " int bodyIndexA = abs(pa);\n"
- " if (!isFixedA)\n"
- " {\n"
- " AtomInc1(bodyCount[bodyIndexA],contactConstraintOffsets[i].x);\n"
- " }\n"
- " barrier(CLK_GLOBAL_MEM_FENCE);\n"
- " int pb = manifoldPtr[i].m_bodyBPtrAndSignBit;\n"
- " bool isFixedB = (pb <0) || (pb == fixedBodyIndex);\n"
- " int bodyIndexB = abs(pb);\n"
- " if (!isFixedB)\n"
- " {\n"
- " AtomInc1(bodyCount[bodyIndexB],contactConstraintOffsets[i].y);\n"
- " } \n"
- " }\n"
- "}\n"
- "__kernel void ClearVelocitiesKernel(__global float4* linearVelocities,__global float4* angularVelocities, int numSplitBodies)\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " \n"
- " if( i < numSplitBodies)\n"
- " {\n"
- " linearVelocities[i] = make_float4(0);\n"
- " angularVelocities[i] = make_float4(0);\n"
- " }\n"
- "}\n"
- "__kernel void AverageVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
- "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " if (i<numBodies)\n"
- " {\n"
- " if (gBodies[i].m_invMass)\n"
- " {\n"
- " int bodyOffset = offsetSplitBodies[i];\n"
- " int count = bodyCount[i];\n"
- " float factor = 1.f/((float)count);\n"
- " float4 averageLinVel = make_float4(0.f);\n"
- " float4 averageAngVel = make_float4(0.f);\n"
- " \n"
- " for (int j=0;j<count;j++)\n"
- " {\n"
- " averageLinVel += deltaLinearVelocities[bodyOffset+j]*factor;\n"
- " averageAngVel += deltaAngularVelocities[bodyOffset+j]*factor;\n"
- " }\n"
- " \n"
- " for (int j=0;j<count;j++)\n"
- " {\n"
- " deltaLinearVelocities[bodyOffset+j] = averageLinVel;\n"
- " deltaAngularVelocities[bodyOffset+j] = averageAngVel;\n"
- " }\n"
- " \n"
- " }//bodies[i].m_invMass\n"
- " }//i<numBodies\n"
- "}\n"
- "void setLinearAndAngular( float4 n, float4 r0, float4 r1, float4* linear, float4* angular0, float4* angular1)\n"
- "{\n"
- " *linear = make_float4(n.xyz,0.f);\n"
- " *angular0 = cross3(r0, n);\n"
- " *angular1 = -cross3(r1, n);\n"
- "}\n"
- "float calcRelVel( float4 l0, float4 l1, float4 a0, float4 a1, float4 linVel0, float4 angVel0, float4 linVel1, float4 angVel1 )\n"
- "{\n"
- " return dot3F4(l0, linVel0) + dot3F4(a0, angVel0) + dot3F4(l1, linVel1) + dot3F4(a1, angVel1);\n"
- "}\n"
- "float calcJacCoeff(const float4 linear0, const float4 linear1, const float4 angular0, const float4 angular1,\n"
- " float invMass0, const Matrix3x3* invInertia0, float invMass1, const Matrix3x3* invInertia1, float countA, float countB)\n"
- "{\n"
- " // linear0,1 are normlized\n"
- " float jmj0 = invMass0;//dot3F4(linear0, linear0)*invMass0;\n"
- " float jmj1 = dot3F4(mtMul3(angular0,*invInertia0), angular0);\n"
- " float jmj2 = invMass1;//dot3F4(linear1, linear1)*invMass1;\n"
- " float jmj3 = dot3F4(mtMul3(angular1,*invInertia1), angular1);\n"
- " return -1.f/((jmj0+jmj1)*countA+(jmj2+jmj3)*countB);\n"
- "}\n"
- "void btPlaneSpace1 (float4 n, float4* p, float4* q);\n"
- " void btPlaneSpace1 (float4 n, float4* p, float4* q)\n"
- "{\n"
- " if (fabs(n.z) > 0.70710678f) {\n"
- " // choose p in y-z plane\n"
- " float a = n.y*n.y + n.z*n.z;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = 0;\n"
- " p[0].y = -n.z*k;\n"
- " p[0].z = n.y*k;\n"
- " // set q = n x p\n"
- " q[0].x = a*k;\n"
- " q[0].y = -n.x*p[0].z;\n"
- " q[0].z = n.x*p[0].y;\n"
- " }\n"
- " else {\n"
- " // choose p in x-y plane\n"
- " float a = n.x*n.x + n.y*n.y;\n"
- " float k = 1.f/sqrt(a);\n"
- " p[0].x = -n.y*k;\n"
- " p[0].y = n.x*k;\n"
- " p[0].z = 0;\n"
- " // set q = n x p\n"
- " q[0].x = -n.z*p[0].y;\n"
- " q[0].y = n.z*p[0].x;\n"
- " q[0].z = a*k;\n"
- " }\n"
- "}\n"
- "void solveContact(__global Constraint4* cs,\n"
- " float4 posA, float4* linVelA, float4* angVelA, float invMassA, Matrix3x3 invInertiaA,\n"
- " float4 posB, float4* linVelB, float4* angVelB, float invMassB, Matrix3x3 invInertiaB,\n"
- " float4* dLinVelA, float4* dAngVelA, float4* dLinVelB, float4* dAngVelB)\n"
- "{\n"
- " float minRambdaDt = 0;\n"
- " float maxRambdaDt = FLT_MAX;\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " if( cs->m_jacCoeffInv[ic] == 0.f ) continue;\n"
- " float4 angular0, angular1, linear;\n"
- " float4 r0 = cs->m_worldPos[ic] - posA;\n"
- " float4 r1 = cs->m_worldPos[ic] - posB;\n"
- " setLinearAndAngular( cs->m_linear, r0, r1, &linear, &angular0, &angular1 );\n"
- " \n"
- " float rambdaDt = calcRelVel( cs->m_linear, -cs->m_linear, angular0, angular1, \n"
- " *linVelA+*dLinVelA, *angVelA+*dAngVelA, *linVelB+*dLinVelB, *angVelB+*dAngVelB ) + cs->m_b[ic];\n"
- " rambdaDt *= cs->m_jacCoeffInv[ic];\n"
- " \n"
- " {\n"
- " float prevSum = cs->m_appliedRambdaDt[ic];\n"
- " float updated = prevSum;\n"
- " updated += rambdaDt;\n"
- " updated = max2( updated, minRambdaDt );\n"
- " updated = min2( updated, maxRambdaDt );\n"
- " rambdaDt = updated - prevSum;\n"
- " cs->m_appliedRambdaDt[ic] = updated;\n"
- " }\n"
- " \n"
- " float4 linImp0 = invMassA*linear*rambdaDt;\n"
- " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
- " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
- " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
- " \n"
- " if (invMassA)\n"
- " {\n"
- " *dLinVelA += linImp0;\n"
- " *dAngVelA += angImp0;\n"
- " }\n"
- " if (invMassB)\n"
- " {\n"
- " *dLinVelB += linImp1;\n"
- " *dAngVelB += angImp1;\n"
- " }\n"
- " }\n"
- "}\n"
- "// solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,contactConstraintOffsets,offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
- "void solveContactConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs, \n"
- "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
- "__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
- "{\n"
- " //float frictionCoeff = ldsCs[0].m_linear.w;\n"
- " int aIdx = ldsCs[0].m_bodyA;\n"
- " int bIdx = ldsCs[0].m_bodyB;\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
- " \n"
- " float4 dLinVelA = make_float4(0,0,0,0);\n"
- " float4 dAngVelA = make_float4(0,0,0,0);\n"
- " float4 dLinVelB = make_float4(0,0,0,0);\n"
- " float4 dAngVelB = make_float4(0,0,0,0);\n"
- " \n"
- " int bodyOffsetA = offsetSplitBodies[aIdx];\n"
- " int constraintOffsetA = contactConstraintOffsets[0].x;\n"
- " int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
- " \n"
- " if (invMassA)\n"
- " {\n"
- " dLinVelA = deltaLinearVelocities[splitIndexA];\n"
- " dAngVelA = deltaAngularVelocities[splitIndexA];\n"
- " }\n"
- " int bodyOffsetB = offsetSplitBodies[bIdx];\n"
- " int constraintOffsetB = contactConstraintOffsets[0].y;\n"
- " int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
- " if (invMassB)\n"
- " {\n"
- " dLinVelB = deltaLinearVelocities[splitIndexB];\n"
- " dAngVelB = deltaAngularVelocities[splitIndexB];\n"
- " }\n"
- " solveContact( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
- " posB, &linVelB, &angVelB, invMassB, invInertiaB ,&dLinVelA, &dAngVelA, &dLinVelB, &dAngVelB);\n"
- " if (invMassA)\n"
- " {\n"
- " deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
- " deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
- " } \n"
- " if (invMassB)\n"
- " {\n"
- " deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
- " deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
- " }\n"
- "}\n"
- "__kernel void SolveContactJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
- "__global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,__global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
- "float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
- ")\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " if (i<numManifolds)\n"
- " {\n"
- " solveContactConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
- " }\n"
- "}\n"
- "void solveFrictionConstraint(__global Body* gBodies, __global Shape* gShapes, __global Constraint4* ldsCs,\n"
- " __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
- " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities)\n"
- "{\n"
- " float frictionCoeff = 0.7f;//ldsCs[0].m_linear.w;\n"
- " int aIdx = ldsCs[0].m_bodyA;\n"
- " int bIdx = ldsCs[0].m_bodyB;\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
- " \n"
- " float4 dLinVelA = make_float4(0,0,0,0);\n"
- " float4 dAngVelA = make_float4(0,0,0,0);\n"
- " float4 dLinVelB = make_float4(0,0,0,0);\n"
- " float4 dAngVelB = make_float4(0,0,0,0);\n"
- " \n"
- " int bodyOffsetA = offsetSplitBodies[aIdx];\n"
- " int constraintOffsetA = contactConstraintOffsets[0].x;\n"
- " int splitIndexA = bodyOffsetA+constraintOffsetA;\n"
- " \n"
- " if (invMassA)\n"
- " {\n"
- " dLinVelA = deltaLinearVelocities[splitIndexA];\n"
- " dAngVelA = deltaAngularVelocities[splitIndexA];\n"
- " }\n"
- " int bodyOffsetB = offsetSplitBodies[bIdx];\n"
- " int constraintOffsetB = contactConstraintOffsets[0].y;\n"
- " int splitIndexB= bodyOffsetB+constraintOffsetB;\n"
- " if (invMassB)\n"
- " {\n"
- " dLinVelB = deltaLinearVelocities[splitIndexB];\n"
- " dAngVelB = deltaAngularVelocities[splitIndexB];\n"
- " }\n"
- " {\n"
- " float maxRambdaDt[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX};\n"
- " float minRambdaDt[4] = {0.f,0.f,0.f,0.f};\n"
- " float sum = 0;\n"
- " for(int j=0; j<4; j++)\n"
- " {\n"
- " sum +=ldsCs[0].m_appliedRambdaDt[j];\n"
- " }\n"
- " frictionCoeff = 0.7f;\n"
- " for(int j=0; j<4; j++)\n"
- " {\n"
- " maxRambdaDt[j] = frictionCoeff*sum;\n"
- " minRambdaDt[j] = -maxRambdaDt[j];\n"
- " }\n"
- " \n"
- "// solveFriction( ldsCs, posA, &linVelA, &angVelA, invMassA, invInertiaA,\n"
- "// posB, &linVelB, &angVelB, invMassB, invInertiaB, maxRambdaDt, minRambdaDt );\n"
- " \n"
- " \n"
- " {\n"
- " \n"
- " __global Constraint4* cs = ldsCs;\n"
- " \n"
- " if( cs->m_fJacCoeffInv[0] == 0 && cs->m_fJacCoeffInv[0] == 0 ) return;\n"
- " const float4 center = cs->m_center;\n"
- " \n"
- " float4 n = -cs->m_linear;\n"
- " \n"
- " float4 tangent[2];\n"
- " btPlaneSpace1(n,&tangent[0],&tangent[1]);\n"
- " float4 angular0, angular1, linear;\n"
- " float4 r0 = center - posA;\n"
- " float4 r1 = center - posB;\n"
- " for(int i=0; i<2; i++)\n"
- " {\n"
- " setLinearAndAngular( tangent[i], r0, r1, &linear, &angular0, &angular1 );\n"
- " float rambdaDt = calcRelVel(linear, -linear, angular0, angular1,\n"
- " linVelA+dLinVelA, angVelA+dAngVelA, linVelB+dLinVelB, angVelB+dAngVelB );\n"
- " rambdaDt *= cs->m_fJacCoeffInv[i];\n"
- " \n"
- " {\n"
- " float prevSum = cs->m_fAppliedRambdaDt[i];\n"
- " float updated = prevSum;\n"
- " updated += rambdaDt;\n"
- " updated = max2( updated, minRambdaDt[i] );\n"
- " updated = min2( updated, maxRambdaDt[i] );\n"
- " rambdaDt = updated - prevSum;\n"
- " cs->m_fAppliedRambdaDt[i] = updated;\n"
- " }\n"
- " \n"
- " float4 linImp0 = invMassA*linear*rambdaDt;\n"
- " float4 linImp1 = invMassB*(-linear)*rambdaDt;\n"
- " float4 angImp0 = mtMul1(invInertiaA, angular0)*rambdaDt;\n"
- " float4 angImp1 = mtMul1(invInertiaB, angular1)*rambdaDt;\n"
- " \n"
- " dLinVelA += linImp0;\n"
- " dAngVelA += angImp0;\n"
- " dLinVelB += linImp1;\n"
- " dAngVelB += angImp1;\n"
- " }\n"
- " { // angular damping for point constraint\n"
- " float4 ab = normalize3( posB - posA );\n"
- " float4 ac = normalize3( center - posA );\n"
- " if( dot3F4( ab, ac ) > 0.95f || (invMassA == 0.f || invMassB == 0.f))\n"
- " {\n"
- " float angNA = dot3F4( n, angVelA );\n"
- " float angNB = dot3F4( n, angVelB );\n"
- " \n"
- " dAngVelA -= (angNA*0.1f)*n;\n"
- " dAngVelB -= (angNB*0.1f)*n;\n"
- " }\n"
- " }\n"
- " }\n"
- " \n"
- " \n"
- " }\n"
- " if (invMassA)\n"
- " {\n"
- " deltaLinearVelocities[splitIndexA] = dLinVelA;\n"
- " deltaAngularVelocities[splitIndexA] = dAngVelA;\n"
- " } \n"
- " if (invMassB)\n"
- " {\n"
- " deltaLinearVelocities[splitIndexB] = dLinVelB;\n"
- " deltaAngularVelocities[splitIndexB] = dAngVelB;\n"
- " }\n"
- " \n"
- "}\n"
- "__kernel void SolveFrictionJacobiKernel(__global Constraint4* gConstraints, __global Body* gBodies, __global Shape* gShapes ,\n"
- " __global int2* contactConstraintOffsets,__global unsigned int* offsetSplitBodies,\n"
- " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities,\n"
- " float deltaTime, float positionDrift, float positionConstraintCoeff, int fixedBodyIndex, int numManifolds\n"
- ")\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " if (i<numManifolds)\n"
- " {\n"
- " solveFrictionConstraint( gBodies, gShapes, &gConstraints[i] ,&contactConstraintOffsets[i],offsetSplitBodies, deltaLinearVelocities, deltaAngularVelocities);\n"
- " }\n"
- "}\n"
- "__kernel void UpdateBodyVelocitiesKernel(__global Body* gBodies,__global int* offsetSplitBodies,__global const unsigned int* bodyCount,\n"
- " __global float4* deltaLinearVelocities, __global float4* deltaAngularVelocities, int numBodies)\n"
- "{\n"
- " int i = GET_GLOBAL_IDX;\n"
- " if (i<numBodies)\n"
- " {\n"
- " if (gBodies[i].m_invMass)\n"
- " {\n"
- " int bodyOffset = offsetSplitBodies[i];\n"
- " int count = bodyCount[i];\n"
- " if (count)\n"
- " {\n"
- " gBodies[i].m_linVel += deltaLinearVelocities[bodyOffset];\n"
- " gBodies[i].m_angVel += deltaAngularVelocities[bodyOffset];\n"
- " }\n"
- " }\n"
- " }\n"
- "}\n"
- "void setConstraint4( const float4 posA, const float4 linVelA, const float4 angVelA, float invMassA, const Matrix3x3 invInertiaA,\n"
- " const float4 posB, const float4 linVelB, const float4 angVelB, float invMassB, const Matrix3x3 invInertiaB, \n"
- " __global struct b3Contact4Data* src, float dt, float positionDrift, float positionConstraintCoeff,float countA, float countB,\n"
- " Constraint4* dstC )\n"
- "{\n"
- " dstC->m_bodyA = abs(src->m_bodyAPtrAndSignBit);\n"
- " dstC->m_bodyB = abs(src->m_bodyBPtrAndSignBit);\n"
- " float dtInv = 1.f/dt;\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
- " }\n"
- " dstC->m_fJacCoeffInv[0] = dstC->m_fJacCoeffInv[1] = 0.f;\n"
- " dstC->m_linear = src->m_worldNormalOnB;\n"
- " dstC->m_linear.w = 0.7f ;//src->getFrictionCoeff() );\n"
- " for(int ic=0; ic<4; ic++)\n"
- " {\n"
- " float4 r0 = src->m_worldPosB[ic] - posA;\n"
- " float4 r1 = src->m_worldPosB[ic] - posB;\n"
- " if( ic >= src->m_worldNormalOnB.w )//npoints\n"
- " {\n"
- " dstC->m_jacCoeffInv[ic] = 0.f;\n"
- " continue;\n"
- " }\n"
- " float relVelN;\n"
- " {\n"
- " float4 linear, angular0, angular1;\n"
- " setLinearAndAngular(src->m_worldNormalOnB, r0, r1, &linear, &angular0, &angular1);\n"
- " dstC->m_jacCoeffInv[ic] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
- " invMassA, &invInertiaA, invMassB, &invInertiaB , countA, countB);\n"
- " relVelN = calcRelVel(linear, -linear, angular0, angular1,\n"
- " linVelA, angVelA, linVelB, angVelB);\n"
- " float e = 0.f;//src->getRestituitionCoeff();\n"
- " if( relVelN*relVelN < 0.004f ) e = 0.f;\n"
- " dstC->m_b[ic] = e*relVelN;\n"
- " //float penetration = src->m_worldPosB[ic].w;\n"
- " dstC->m_b[ic] += (src->m_worldPosB[ic].w + positionDrift)*positionConstraintCoeff*dtInv;\n"
- " dstC->m_appliedRambdaDt[ic] = 0.f;\n"
- " }\n"
- " }\n"
- " if( src->m_worldNormalOnB.w > 0 )//npoints\n"
- " { // prepare friction\n"
- " float4 center = make_float4(0.f);\n"
- " for(int i=0; i<src->m_worldNormalOnB.w; i++) \n"
- " center += src->m_worldPosB[i];\n"
- " center /= (float)src->m_worldNormalOnB.w;\n"
- " float4 tangent[2];\n"
- " btPlaneSpace1(-src->m_worldNormalOnB,&tangent[0],&tangent[1]);\n"
- " \n"
- " float4 r[2];\n"
- " r[0] = center - posA;\n"
- " r[1] = center - posB;\n"
- " for(int i=0; i<2; i++)\n"
- " {\n"
- " float4 linear, angular0, angular1;\n"
- " setLinearAndAngular(tangent[i], r[0], r[1], &linear, &angular0, &angular1);\n"
- " dstC->m_fJacCoeffInv[i] = calcJacCoeff(linear, -linear, angular0, angular1,\n"
- " invMassA, &invInertiaA, invMassB, &invInertiaB ,countA, countB);\n"
- " dstC->m_fAppliedRambdaDt[i] = 0.f;\n"
- " }\n"
- " dstC->m_center = center;\n"
- " }\n"
- " for(int i=0; i<4; i++)\n"
- " {\n"
- " if( i<src->m_worldNormalOnB.w )\n"
- " {\n"
- " dstC->m_worldPos[i] = src->m_worldPosB[i];\n"
- " }\n"
- " else\n"
- " {\n"
- " dstC->m_worldPos[i] = make_float4(0.f);\n"
- " }\n"
- " }\n"
- "}\n"
- "__kernel\n"
- "__attribute__((reqd_work_group_size(WG_SIZE,1,1)))\n"
- "void ContactToConstraintSplitKernel(__global const struct b3Contact4Data* gContact, __global const Body* gBodies, __global const Shape* gShapes, __global Constraint4* gConstraintOut, \n"
- "__global const unsigned int* bodyCount,\n"
- "int nContacts,\n"
- "float dt,\n"
- "float positionDrift,\n"
- "float positionConstraintCoeff\n"
- ")\n"
- "{\n"
- " int gIdx = GET_GLOBAL_IDX;\n"
- " \n"
- " if( gIdx < nContacts )\n"
- " {\n"
- " int aIdx = abs(gContact[gIdx].m_bodyAPtrAndSignBit);\n"
- " int bIdx = abs(gContact[gIdx].m_bodyBPtrAndSignBit);\n"
- " float4 posA = gBodies[aIdx].m_pos;\n"
- " float4 linVelA = gBodies[aIdx].m_linVel;\n"
- " float4 angVelA = gBodies[aIdx].m_angVel;\n"
- " float invMassA = gBodies[aIdx].m_invMass;\n"
- " Matrix3x3 invInertiaA = gShapes[aIdx].m_invInertia;\n"
- " float4 posB = gBodies[bIdx].m_pos;\n"
- " float4 linVelB = gBodies[bIdx].m_linVel;\n"
- " float4 angVelB = gBodies[bIdx].m_angVel;\n"
- " float invMassB = gBodies[bIdx].m_invMass;\n"
- " Matrix3x3 invInertiaB = gShapes[bIdx].m_invInertia;\n"
- " Constraint4 cs;\n"
- " float countA = invMassA != 0.f ? (float)bodyCount[aIdx] : 1;\n"
- " float countB = invMassB != 0.f ? (float)bodyCount[bIdx] : 1;\n"
- " setConstraint4( posA, linVelA, angVelA, invMassA, invInertiaA, posB, linVelB, angVelB, invMassB, invInertiaB,\n"
- " &gContact[gIdx], dt, positionDrift, positionConstraintCoeff,countA,countB,\n"
- " &cs );\n"
- " \n"
- " cs.m_batchIdx = gContact[gIdx].m_batchIdx;\n"
- " gConstraintOut[gIdx] = cs;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
deleted file mode 100644
index ba8ba735d0..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.cl
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-#include "Bullet3Collision/NarrowPhaseCollision/shared/b3UpdateAabbs.h"
-
-
-__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)
-{
- int nodeID = get_global_id(0);
- if( nodeID < numNodes )
- {
- b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);
- }
-}
-
-__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)
-{
- int pairId = get_global_id(0);
- if( pairId< numPairs )
- {
- pairs[pairId].z = 0xffffffff;
- }
-} \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h b/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
deleted file mode 100644
index bb949b2027..0000000000
--- a/thirdparty/bullet/Bullet3OpenCL/RigidBody/kernels/updateAabbsKernel.h
+++ /dev/null
@@ -1,482 +0,0 @@
-//this file is autogenerated using stringify.bat (premake --stringify) in the build folder of this project
-static const char* updateAabbsKernelCL =
- "#ifndef B3_UPDATE_AABBS_H\n"
- "#define B3_UPDATE_AABBS_H\n"
- "#ifndef B3_AABB_H\n"
- "#define B3_AABB_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#define B3_FLOAT4_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#define B3_PLATFORM_DEFINITIONS_H\n"
- "struct MyTest\n"
- "{\n"
- " int bla;\n"
- "};\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "//keep B3_LARGE_FLOAT*B3_LARGE_FLOAT < FLT_MAX\n"
- "#define B3_LARGE_FLOAT 1e18f\n"
- "#define B3_INFINITY 1e18f\n"
- "#define b3Assert(a)\n"
- "#define b3ConstArray(a) __global const a*\n"
- "#define b3AtomicInc atomic_inc\n"
- "#define b3AtomicAdd atomic_add\n"
- "#define b3Fabs fabs\n"
- "#define b3Sqrt native_sqrt\n"
- "#define b3Sin native_sin\n"
- "#define b3Cos native_cos\n"
- "#define B3_STATIC\n"
- "#endif\n"
- "#endif\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Float4;\n"
- " #define b3Float4ConstArg const b3Float4\n"
- " #define b3MakeFloat4 (float4)\n"
- " float b3Dot3F4(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return dot(a1, b1);\n"
- " }\n"
- " b3Float4 b3Cross3(b3Float4ConstArg v0,b3Float4ConstArg v1)\n"
- " {\n"
- " float4 a1 = b3MakeFloat4(v0.xyz,0.f);\n"
- " float4 b1 = b3MakeFloat4(v1.xyz,0.f);\n"
- " return cross(a1, b1);\n"
- " }\n"
- " #define b3MinFloat4 min\n"
- " #define b3MaxFloat4 max\n"
- " #define b3Normalized(a) normalize(a)\n"
- "#endif \n"
- " \n"
- "inline bool b3IsAlmostZero(b3Float4ConstArg v)\n"
- "{\n"
- " if(b3Fabs(v.x)>1e-6 || b3Fabs(v.y)>1e-6 || b3Fabs(v.z)>1e-6) \n"
- " return false;\n"
- " return true;\n"
- "}\n"
- "inline int b3MaxDot( b3Float4ConstArg vec, __global const b3Float4* vecArray, int vecLen, float* dotOut )\n"
- "{\n"
- " float maxDot = -B3_INFINITY;\n"
- " int i = 0;\n"
- " int ptIndex = -1;\n"
- " for( i = 0; i < vecLen; i++ )\n"
- " {\n"
- " float dot = b3Dot3F4(vecArray[i],vec);\n"
- " \n"
- " if( dot > maxDot )\n"
- " {\n"
- " maxDot = dot;\n"
- " ptIndex = i;\n"
- " }\n"
- " }\n"
- " b3Assert(ptIndex>=0);\n"
- " if (ptIndex<0)\n"
- " {\n"
- " ptIndex = 0;\n"
- " }\n"
- " *dotOut = maxDot;\n"
- " return ptIndex;\n"
- "}\n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#define B3_MAT3x3_H\n"
- "#ifndef B3_QUAT_H\n"
- "#define B3_QUAT_H\n"
- "#ifndef B3_PLATFORM_DEFINITIONS_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- " typedef float4 b3Quat;\n"
- " #define b3QuatConstArg const b3Quat\n"
- " \n"
- " \n"
- "inline float4 b3FastNormalize4(float4 v)\n"
- "{\n"
- " v = (float4)(v.xyz,0.f);\n"
- " return fast_normalize(v);\n"
- "}\n"
- " \n"
- "inline b3Quat b3QuatMul(b3Quat a, b3Quat b);\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in);\n"
- "inline b3Quat b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec);\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q);\n"
- "inline b3Quat b3QuatMul(b3QuatConstArg a, b3QuatConstArg b)\n"
- "{\n"
- " b3Quat ans;\n"
- " ans = b3Cross3( a, b );\n"
- " ans += a.w*b+b.w*a;\n"
- "// ans.w = a.w*b.w - (a.x*b.x+a.y*b.y+a.z*b.z);\n"
- " ans.w = a.w*b.w - b3Dot3F4(a, b);\n"
- " return ans;\n"
- "}\n"
- "inline b3Quat b3QuatNormalized(b3QuatConstArg in)\n"
- "{\n"
- " b3Quat q;\n"
- " q=in;\n"
- " //return b3FastNormalize4(in);\n"
- " float len = native_sqrt(dot(q, q));\n"
- " if(len > 0.f)\n"
- " {\n"
- " q *= 1.f / len;\n"
- " }\n"
- " else\n"
- " {\n"
- " q.x = q.y = q.z = 0.f;\n"
- " q.w = 1.f;\n"
- " }\n"
- " return q;\n"
- "}\n"
- "inline float4 b3QuatRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " b3Quat qInv = b3QuatInvert( q );\n"
- " float4 vcpy = vec;\n"
- " vcpy.w = 0.f;\n"
- " float4 out = b3QuatMul(b3QuatMul(q,vcpy),qInv);\n"
- " return out;\n"
- "}\n"
- "inline b3Quat b3QuatInverse(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline b3Quat b3QuatInvert(b3QuatConstArg q)\n"
- "{\n"
- " return (b3Quat)(-q.xyz, q.w);\n"
- "}\n"
- "inline float4 b3QuatInvRotate(b3QuatConstArg q, b3QuatConstArg vec)\n"
- "{\n"
- " return b3QuatRotate( b3QuatInvert( q ), vec );\n"
- "}\n"
- "inline b3Float4 b3TransformPoint(b3Float4ConstArg point, b3Float4ConstArg translation, b3QuatConstArg orientation)\n"
- "{\n"
- " return b3QuatRotate( orientation, point ) + (translation);\n"
- "}\n"
- " \n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "typedef struct\n"
- "{\n"
- " b3Float4 m_row[3];\n"
- "}b3Mat3x3;\n"
- "#define b3Mat3x3ConstArg const b3Mat3x3\n"
- "#define b3GetRow(m,row) (m.m_row[row])\n"
- "inline b3Mat3x3 b3QuatGetRotationMatrix(b3Quat quat)\n"
- "{\n"
- " b3Float4 quat2 = (b3Float4)(quat.x*quat.x, quat.y*quat.y, quat.z*quat.z, 0.f);\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0].x=1-2*quat2.y-2*quat2.z;\n"
- " out.m_row[0].y=2*quat.x*quat.y-2*quat.w*quat.z;\n"
- " out.m_row[0].z=2*quat.x*quat.z+2*quat.w*quat.y;\n"
- " out.m_row[0].w = 0.f;\n"
- " out.m_row[1].x=2*quat.x*quat.y+2*quat.w*quat.z;\n"
- " out.m_row[1].y=1-2*quat2.x-2*quat2.z;\n"
- " out.m_row[1].z=2*quat.y*quat.z-2*quat.w*quat.x;\n"
- " out.m_row[1].w = 0.f;\n"
- " out.m_row[2].x=2*quat.x*quat.z-2*quat.w*quat.y;\n"
- " out.m_row[2].y=2*quat.y*quat.z+2*quat.w*quat.x;\n"
- " out.m_row[2].z=1-2*quat2.x-2*quat2.y;\n"
- " out.m_row[2].w = 0.f;\n"
- " return out;\n"
- "}\n"
- "inline b3Mat3x3 b3AbsoluteMat3x3(b3Mat3x3ConstArg matIn)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = fabs(matIn.m_row[0]);\n"
- " out.m_row[1] = fabs(matIn.m_row[1]);\n"
- " out.m_row[2] = fabs(matIn.m_row[2]);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtZero();\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity();\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m);\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b);\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b);\n"
- "__inline\n"
- "b3Mat3x3 mtZero()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(0.f);\n"
- " m.m_row[1] = (b3Float4)(0.f);\n"
- " m.m_row[2] = (b3Float4)(0.f);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtIdentity()\n"
- "{\n"
- " b3Mat3x3 m;\n"
- " m.m_row[0] = (b3Float4)(1,0,0,0);\n"
- " m.m_row[1] = (b3Float4)(0,1,0,0);\n"
- " m.m_row[2] = (b3Float4)(0,0,1,0);\n"
- " return m;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtTranspose(b3Mat3x3 m)\n"
- "{\n"
- " b3Mat3x3 out;\n"
- " out.m_row[0] = (b3Float4)(m.m_row[0].x, m.m_row[1].x, m.m_row[2].x, 0.f);\n"
- " out.m_row[1] = (b3Float4)(m.m_row[0].y, m.m_row[1].y, m.m_row[2].y, 0.f);\n"
- " out.m_row[2] = (b3Float4)(m.m_row[0].z, m.m_row[1].z, m.m_row[2].z, 0.f);\n"
- " return out;\n"
- "}\n"
- "__inline\n"
- "b3Mat3x3 mtMul(b3Mat3x3 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Mat3x3 transB;\n"
- " transB = mtTranspose( b );\n"
- " b3Mat3x3 ans;\n"
- " // why this doesn't run when 0ing in the for{}\n"
- " a.m_row[0].w = 0.f;\n"
- " a.m_row[1].w = 0.f;\n"
- " a.m_row[2].w = 0.f;\n"
- " for(int i=0; i<3; i++)\n"
- " {\n"
- "// a.m_row[i].w = 0.f;\n"
- " ans.m_row[i].x = b3Dot3F4(a.m_row[i],transB.m_row[0]);\n"
- " ans.m_row[i].y = b3Dot3F4(a.m_row[i],transB.m_row[1]);\n"
- " ans.m_row[i].z = b3Dot3F4(a.m_row[i],transB.m_row[2]);\n"
- " ans.m_row[i].w = 0.f;\n"
- " }\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul1(b3Mat3x3 a, b3Float4 b)\n"
- "{\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a.m_row[0], b );\n"
- " ans.y = b3Dot3F4( a.m_row[1], b );\n"
- " ans.z = b3Dot3F4( a.m_row[2], b );\n"
- " ans.w = 0.f;\n"
- " return ans;\n"
- "}\n"
- "__inline\n"
- "b3Float4 mtMul3(b3Float4 a, b3Mat3x3 b)\n"
- "{\n"
- " b3Float4 colx = b3MakeFloat4(b.m_row[0].x, b.m_row[1].x, b.m_row[2].x, 0);\n"
- " b3Float4 coly = b3MakeFloat4(b.m_row[0].y, b.m_row[1].y, b.m_row[2].y, 0);\n"
- " b3Float4 colz = b3MakeFloat4(b.m_row[0].z, b.m_row[1].z, b.m_row[2].z, 0);\n"
- " b3Float4 ans;\n"
- " ans.x = b3Dot3F4( a, colx );\n"
- " ans.y = b3Dot3F4( a, coly );\n"
- " ans.z = b3Dot3F4( a, colz );\n"
- " return ans;\n"
- "}\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3Aabb b3Aabb_t;\n"
- "struct b3Aabb\n"
- "{\n"
- " union\n"
- " {\n"
- " float m_min[4];\n"
- " b3Float4 m_minVec;\n"
- " int m_minIndices[4];\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_max[4];\n"
- " b3Float4 m_maxVec;\n"
- " int m_signedMaxIndices[4];\n"
- " };\n"
- "};\n"
- "inline void b3TransformAabb2(b3Float4ConstArg localAabbMin,b3Float4ConstArg localAabbMax, float margin,\n"
- " b3Float4ConstArg pos,\n"
- " b3QuatConstArg orn,\n"
- " b3Float4* aabbMinOut,b3Float4* aabbMaxOut)\n"
- "{\n"
- " b3Float4 localHalfExtents = 0.5f*(localAabbMax-localAabbMin);\n"
- " localHalfExtents+=b3MakeFloat4(margin,margin,margin,0.f);\n"
- " b3Float4 localCenter = 0.5f*(localAabbMax+localAabbMin);\n"
- " b3Mat3x3 m;\n"
- " m = b3QuatGetRotationMatrix(orn);\n"
- " b3Mat3x3 abs_b = b3AbsoluteMat3x3(m);\n"
- " b3Float4 center = b3TransformPoint(localCenter,pos,orn);\n"
- " \n"
- " b3Float4 extent = b3MakeFloat4(b3Dot3F4(localHalfExtents,b3GetRow(abs_b,0)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,1)),\n"
- " b3Dot3F4(localHalfExtents,b3GetRow(abs_b,2)),\n"
- " 0.f);\n"
- " *aabbMinOut = center-extent;\n"
- " *aabbMaxOut = center+extent;\n"
- "}\n"
- "/// conservative test for overlap between two aabbs\n"
- "inline bool b3TestAabbAgainstAabb(b3Float4ConstArg aabbMin1,b3Float4ConstArg aabbMax1,\n"
- " b3Float4ConstArg aabbMin2, b3Float4ConstArg aabbMax2)\n"
- "{\n"
- " bool overlap = true;\n"
- " overlap = (aabbMin1.x > aabbMax2.x || aabbMax1.x < aabbMin2.x) ? false : overlap;\n"
- " overlap = (aabbMin1.z > aabbMax2.z || aabbMax1.z < aabbMin2.z) ? false : overlap;\n"
- " overlap = (aabbMin1.y > aabbMax2.y || aabbMax1.y < aabbMin2.y) ? false : overlap;\n"
- " return overlap;\n"
- "}\n"
- "#endif //B3_AABB_H\n"
- "#ifndef B3_COLLIDABLE_H\n"
- "#define B3_COLLIDABLE_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "enum b3ShapeTypes\n"
- "{\n"
- " SHAPE_HEIGHT_FIELD=1,\n"
- " SHAPE_CONVEX_HULL=3,\n"
- " SHAPE_PLANE=4,\n"
- " SHAPE_CONCAVE_TRIMESH=5,\n"
- " SHAPE_COMPOUND_OF_CONVEX_HULLS=6,\n"
- " SHAPE_SPHERE=7,\n"
- " MAX_NUM_SHAPE_TYPES,\n"
- "};\n"
- "typedef struct b3Collidable b3Collidable_t;\n"
- "struct b3Collidable\n"
- "{\n"
- " union {\n"
- " int m_numChildShapes;\n"
- " int m_bvhIndex;\n"
- " };\n"
- " union\n"
- " {\n"
- " float m_radius;\n"
- " int m_compoundBvhIndex;\n"
- " };\n"
- " int m_shapeType;\n"
- " union\n"
- " {\n"
- " int m_shapeIndex;\n"
- " float m_height;\n"
- " };\n"
- "};\n"
- "typedef struct b3GpuChildShape b3GpuChildShape_t;\n"
- "struct b3GpuChildShape\n"
- "{\n"
- " b3Float4 m_childPosition;\n"
- " b3Quat m_childOrientation;\n"
- " union\n"
- " {\n"
- " int m_shapeIndex;//used for SHAPE_COMPOUND_OF_CONVEX_HULLS\n"
- " int m_capsuleAxis;\n"
- " };\n"
- " union \n"
- " {\n"
- " float m_radius;//used for childshape of SHAPE_COMPOUND_OF_SPHERES or SHAPE_COMPOUND_OF_CAPSULES\n"
- " int m_numChildShapes;//used for compound shape\n"
- " };\n"
- " union \n"
- " {\n"
- " float m_height;//used for childshape of SHAPE_COMPOUND_OF_CAPSULES\n"
- " int m_collidableShapeIndex;\n"
- " };\n"
- " int m_shapeType;\n"
- "};\n"
- "struct b3CompoundOverlappingPair\n"
- "{\n"
- " int m_bodyIndexA;\n"
- " int m_bodyIndexB;\n"
- "// int m_pairType;\n"
- " int m_childShapeIndexA;\n"
- " int m_childShapeIndexB;\n"
- "};\n"
- "#endif //B3_COLLIDABLE_H\n"
- "#ifndef B3_RIGIDBODY_DATA_H\n"
- "#define B3_RIGIDBODY_DATA_H\n"
- "#ifndef B3_FLOAT4_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_FLOAT4_H\n"
- "#ifndef B3_QUAT_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif \n"
- "#endif //B3_QUAT_H\n"
- "#ifndef B3_MAT3x3_H\n"
- "#ifdef __cplusplus\n"
- "#else\n"
- "#endif\n"
- "#endif //B3_MAT3x3_H\n"
- "typedef struct b3RigidBodyData b3RigidBodyData_t;\n"
- "struct b3RigidBodyData\n"
- "{\n"
- " b3Float4 m_pos;\n"
- " b3Quat m_quat;\n"
- " b3Float4 m_linVel;\n"
- " b3Float4 m_angVel;\n"
- " int m_collidableIdx;\n"
- " float m_invMass;\n"
- " float m_restituitionCoeff;\n"
- " float m_frictionCoeff;\n"
- "};\n"
- "typedef struct b3InertiaData b3InertiaData_t;\n"
- "struct b3InertiaData\n"
- "{\n"
- " b3Mat3x3 m_invInertiaWorld;\n"
- " b3Mat3x3 m_initInvInertia;\n"
- "};\n"
- "#endif //B3_RIGIDBODY_DATA_H\n"
- " \n"
- "void b3ComputeWorldAabb( int bodyId, __global const b3RigidBodyData_t* bodies, __global const b3Collidable_t* collidables, __global const b3Aabb_t* localShapeAABB, __global b3Aabb_t* worldAabbs)\n"
- "{\n"
- " __global const b3RigidBodyData_t* body = &bodies[bodyId];\n"
- " b3Float4 position = body->m_pos;\n"
- " b3Quat orientation = body->m_quat;\n"
- " \n"
- " int collidableIndex = body->m_collidableIdx;\n"
- " int shapeIndex = collidables[collidableIndex].m_shapeIndex;\n"
- " \n"
- " if (shapeIndex>=0)\n"
- " {\n"
- " \n"
- " b3Aabb_t localAabb = localShapeAABB[collidableIndex];\n"
- " b3Aabb_t worldAabb;\n"
- " \n"
- " b3Float4 aabbAMinOut,aabbAMaxOut; \n"
- " float margin = 0.f;\n"
- " b3TransformAabb2(localAabb.m_minVec,localAabb.m_maxVec,margin,position,orientation,&aabbAMinOut,&aabbAMaxOut);\n"
- " \n"
- " worldAabb.m_minVec =aabbAMinOut;\n"
- " worldAabb.m_minIndices[3] = bodyId;\n"
- " worldAabb.m_maxVec = aabbAMaxOut;\n"
- " worldAabb.m_signedMaxIndices[3] = body[bodyId].m_invMass==0.f? 0 : 1;\n"
- " worldAabbs[bodyId] = worldAabb;\n"
- " }\n"
- "}\n"
- "#endif //B3_UPDATE_AABBS_H\n"
- "__kernel void initializeGpuAabbsFull( const int numNodes, __global b3RigidBodyData_t* gBodies,__global b3Collidable_t* collidables, __global b3Aabb_t* plocalShapeAABB, __global b3Aabb_t* pAABB)\n"
- "{\n"
- " int nodeID = get_global_id(0);\n"
- " if( nodeID < numNodes )\n"
- " {\n"
- " b3ComputeWorldAabb(nodeID, gBodies, collidables, plocalShapeAABB,pAABB);\n"
- " }\n"
- "}\n"
- "__kernel void clearOverlappingPairsKernel( __global int4* pairs, int numPairs)\n"
- "{\n"
- " int pairId = get_global_id(0);\n"
- " if( pairId< numPairs )\n"
- " {\n"
- " pairs[pairId].z = 0xffffffff;\n"
- " }\n"
- "}\n";
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
deleted file mode 100644
index eaa27dfe8f..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/autogenerated/bullet2.h
+++ /dev/null
@@ -1,987 +0,0 @@
-/* Copyright (C) 2011 Erwin Coumans & Charlie C
-*
-* This software is provided 'as-is', without any express or implied
-* warranty. In no event will the authors be held liable for any damages
-* arising from the use of this software.
-*
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-*
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would be
-* appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-* misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-*/
-// Auto generated from Bullet/Extras/HeaderGenerator/bulletGenerate.py
-#ifndef __BULLET2_H__
-#define __BULLET2_H__
-namespace Bullet3SerializeBullet2
-{
-// put an empty struct in the case
-typedef struct bInvalidHandle
-{
- int unused;
-} bInvalidHandle;
-
-class PointerArray;
-class b3PhysicsSystem;
-class ListBase;
-class b3Vector3FloatData;
-class b3Vector3DoubleData;
-class b3Matrix3x3FloatData;
-class b3Matrix3x3DoubleData;
-class b3TransformFloatData;
-class b3TransformDoubleData;
-class b3BvhSubtreeInfoData;
-class b3OptimizedBvhNodeFloatData;
-class b3OptimizedBvhNodeDoubleData;
-class b3QuantizedBvhNodeData;
-class b3QuantizedBvhFloatData;
-class b3QuantizedBvhDoubleData;
-class b3CollisionShapeData;
-class b3StaticPlaneShapeData;
-class b3ConvexInternalShapeData;
-class b3PositionAndRadius;
-class b3MultiSphereShapeData;
-class b3IntIndexData;
-class b3ShortIntIndexData;
-class b3ShortIntIndexTripletData;
-class b3CharIndexTripletData;
-class b3MeshPartData;
-class b3StridingMeshInterfaceData;
-class b3TriangleMeshShapeData;
-class b3ScaledTriangleMeshShapeData;
-class b3CompoundShapeChildData;
-class b3CompoundShapeData;
-class b3CylinderShapeData;
-class b3CapsuleShapeData;
-class b3TriangleInfoData;
-class b3TriangleInfoMapData;
-class b3GImpactMeshShapeData;
-class b3ConvexHullShapeData;
-class b3CollisionObjectDoubleData;
-class b3CollisionObjectFloatData;
-class b3DynamicsWorldDoubleData;
-class b3DynamicsWorldFloatData;
-class b3RigidBodyFloatData;
-class b3RigidBodyDoubleData;
-class b3ConstraintInfo1;
-class b3TypedConstraintData;
-class b3Point2PointConstraintFloatData;
-class b3Point2PointConstraintDoubleData;
-class b3HingeConstraintDoubleData;
-class b3HingeConstraintFloatData;
-class b3ConeTwistConstraintData;
-class b3Generic6DofConstraintData;
-class b3Generic6DofSpringConstraintData;
-class b3SliderConstraintData;
-class b3ContactSolverInfoDoubleData;
-class b3ContactSolverInfoFloatData;
-class SoftBodyMaterialData;
-class SoftBodyNodeData;
-class SoftBodyLinkData;
-class SoftBodyFaceData;
-class SoftBodyTetraData;
-class SoftRigidAnchorData;
-class SoftBodyConfigData;
-class SoftBodyPoseData;
-class SoftBodyClusterData;
-class b3SoftBodyJointData;
-class b3SoftBodyFloatData;
-// -------------------------------------------------- //
-class PointerArray
-{
-public:
- int m_size;
- int m_capacity;
- void *m_data;
-};
-
-// -------------------------------------------------- //
-class b3PhysicsSystem
-{
-public:
- PointerArray m_collisionShapes;
- PointerArray m_collisionObjects;
- PointerArray m_constraints;
-};
-
-// -------------------------------------------------- //
-class ListBase
-{
-public:
- void *first;
- void *last;
-};
-
-// -------------------------------------------------- //
-class b3Vector3FloatData
-{
-public:
- float m_floats[4];
-};
-
-// -------------------------------------------------- //
-class b3Vector3DoubleData
-{
-public:
- double m_floats[4];
-};
-
-// -------------------------------------------------- //
-class b3Matrix3x3FloatData
-{
-public:
- b3Vector3FloatData m_el[3];
-};
-
-// -------------------------------------------------- //
-class b3Matrix3x3DoubleData
-{
-public:
- b3Vector3DoubleData m_el[3];
-};
-
-// -------------------------------------------------- //
-class b3TransformFloatData
-{
-public:
- b3Matrix3x3FloatData m_basis;
- b3Vector3FloatData m_origin;
-};
-
-// -------------------------------------------------- //
-class b3TransformDoubleData
-{
-public:
- b3Matrix3x3DoubleData m_basis;
- b3Vector3DoubleData m_origin;
-};
-
-// -------------------------------------------------- //
-class b3BvhSubtreeInfoData
-{
-public:
- int m_rootNodeIndex;
- int m_subtreeSize;
- short m_quantizedAabbMin[3];
- short m_quantizedAabbMax[3];
-};
-
-// -------------------------------------------------- //
-class b3OptimizedBvhNodeFloatData
-{
-public:
- b3Vector3FloatData m_aabbMinOrg;
- b3Vector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-// -------------------------------------------------- //
-class b3OptimizedBvhNodeDoubleData
-{
-public:
- b3Vector3DoubleData m_aabbMinOrg;
- b3Vector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-// -------------------------------------------------- //
-class b3QuantizedBvhNodeData
-{
-public:
- short m_quantizedAabbMin[3];
- short m_quantizedAabbMax[3];
- int m_escapeIndexOrTriangleIndex;
-};
-
-// -------------------------------------------------- //
-class b3QuantizedBvhFloatData
-{
-public:
- b3Vector3FloatData m_bvhAabbMin;
- b3Vector3FloatData m_bvhAabbMax;
- b3Vector3FloatData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeFloatData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
-};
-
-// -------------------------------------------------- //
-class b3QuantizedBvhDoubleData
-{
-public:
- b3Vector3DoubleData m_bvhAabbMin;
- b3Vector3DoubleData m_bvhAabbMax;
- b3Vector3DoubleData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- b3OptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
- b3QuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
- b3BvhSubtreeInfoData *m_subTreeInfoPtr;
-};
-
-// -------------------------------------------------- //
-class b3CollisionShapeData
-{
-public:
- char *m_name;
- int m_shapeType;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3StaticPlaneShapeData
-{
-public:
- b3CollisionShapeData m_collisionShapeData;
- b3Vector3FloatData m_localScaling;
- b3Vector3FloatData m_planeNormal;
- float m_planeConstant;
- char m_pad[4];
-};
-
-// -------------------------------------------------- //
-class b3ConvexInternalShapeData
-{
-public:
- b3CollisionShapeData m_collisionShapeData;
- b3Vector3FloatData m_localScaling;
- b3Vector3FloatData m_implicitShapeDimensions;
- float m_collisionMargin;
- int m_padding;
-};
-
-// -------------------------------------------------- //
-class b3PositionAndRadius
-{
-public:
- b3Vector3FloatData m_pos;
- float m_radius;
-};
-
-// -------------------------------------------------- //
-class b3MultiSphereShapeData
-{
-public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- b3PositionAndRadius *m_localPositionArrayPtr;
- int m_localPositionArraySize;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3IntIndexData
-{
-public:
- int m_value;
-};
-
-// -------------------------------------------------- //
-class b3ShortIntIndexData
-{
-public:
- short m_value;
- char m_pad[2];
-};
-
-// -------------------------------------------------- //
-class b3ShortIntIndexTripletData
-{
-public:
- short m_values[3];
- char m_pad[2];
-};
-
-// -------------------------------------------------- //
-class b3CharIndexTripletData
-{
-public:
- char m_values[3];
- char m_pad;
-};
-
-// -------------------------------------------------- //
-class b3MeshPartData
-{
-public:
- b3Vector3FloatData *m_vertices3f;
- b3Vector3DoubleData *m_vertices3d;
- b3IntIndexData *m_indices32;
- b3ShortIntIndexTripletData *m_3indices16;
- b3CharIndexTripletData *m_3indices8;
- b3ShortIntIndexData *m_indices16;
- int m_numTriangles;
- int m_numVertices;
-};
-
-// -------------------------------------------------- //
-class b3StridingMeshInterfaceData
-{
-public:
- b3MeshPartData *m_meshPartsPtr;
- b3Vector3FloatData m_scaling;
- int m_numMeshParts;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3TriangleMeshShapeData
-{
-public:
- b3CollisionShapeData m_collisionShapeData;
- b3StridingMeshInterfaceData m_meshInterface;
- b3QuantizedBvhFloatData *m_quantizedFloatBvh;
- b3QuantizedBvhDoubleData *m_quantizedDoubleBvh;
- b3TriangleInfoMapData *m_triangleInfoMap;
- float m_collisionMargin;
- char m_pad3[4];
-};
-
-// -------------------------------------------------- //
-class b3ScaledTriangleMeshShapeData
-{
-public:
- b3TriangleMeshShapeData m_trimeshShapeData;
- b3Vector3FloatData m_localScaling;
-};
-
-// -------------------------------------------------- //
-class b3CompoundShapeChildData
-{
-public:
- b3TransformFloatData m_transform;
- b3CollisionShapeData *m_childShape;
- int m_childShapeType;
- float m_childMargin;
-};
-
-// -------------------------------------------------- //
-class b3CompoundShapeData
-{
-public:
- b3CollisionShapeData m_collisionShapeData;
- b3CompoundShapeChildData *m_childShapePtr;
- int m_numChildShapes;
- float m_collisionMargin;
-};
-
-// -------------------------------------------------- //
-class b3CylinderShapeData
-{
-public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3CapsuleShapeData
-{
-public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- int m_upAxis;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3TriangleInfoData
-{
-public:
- int m_flags;
- float m_edgeV0V1Angle;
- float m_edgeV1V2Angle;
- float m_edgeV2V0Angle;
-};
-
-// -------------------------------------------------- //
-class b3TriangleInfoMapData
-{
-public:
- int *m_hashTablePtr;
- int *m_nextPtr;
- b3TriangleInfoData *m_valueArrayPtr;
- int *m_keyArrayPtr;
- float m_convexEpsilon;
- float m_planarEpsilon;
- float m_equalVertexThreshold;
- float m_edgeDistanceThreshold;
- float m_zeroAreaThreshold;
- int m_nextSize;
- int m_hashTableSize;
- int m_numValues;
- int m_numKeys;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3GImpactMeshShapeData
-{
-public:
- b3CollisionShapeData m_collisionShapeData;
- b3StridingMeshInterfaceData m_meshInterface;
- b3Vector3FloatData m_localScaling;
- float m_collisionMargin;
- int m_gimpactSubType;
-};
-
-// -------------------------------------------------- //
-class b3ConvexHullShapeData
-{
-public:
- b3ConvexInternalShapeData m_convexInternalShapeData;
- b3Vector3FloatData *m_unscaledPointsFloatPtr;
- b3Vector3DoubleData *m_unscaledPointsDoublePtr;
- int m_numUnscaledPoints;
- char m_padding3[4];
-};
-
-// -------------------------------------------------- //
-class b3CollisionObjectDoubleData
-{
-public:
- void *m_broadphaseHandle;
- void *m_collisionShape;
- b3CollisionShapeData *m_rootCollisionShape;
- char *m_name;
- b3TransformDoubleData m_worldTransform;
- b3TransformDoubleData m_interpolationWorldTransform;
- b3Vector3DoubleData m_interpolationLinearVelocity;
- b3Vector3DoubleData m_interpolationAngularVelocity;
- b3Vector3DoubleData m_anisotropicFriction;
- double m_contactProcessingThreshold;
- double m_deactivationTime;
- double m_friction;
- double m_rollingFriction;
- double m_restitution;
- double m_hitFraction;
- double m_ccdSweptSphereRadius;
- double m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3CollisionObjectFloatData
-{
-public:
- void *m_broadphaseHandle;
- void *m_collisionShape;
- b3CollisionShapeData *m_rootCollisionShape;
- char *m_name;
- b3TransformFloatData m_worldTransform;
- b3TransformFloatData m_interpolationWorldTransform;
- b3Vector3FloatData m_interpolationLinearVelocity;
- b3Vector3FloatData m_interpolationAngularVelocity;
- b3Vector3FloatData m_anisotropicFriction;
- float m_contactProcessingThreshold;
- float m_deactivationTime;
- float m_friction;
- float m_rollingFriction;
- float m_restitution;
- float m_hitFraction;
- float m_ccdSweptSphereRadius;
- float m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3RigidBodyFloatData
-{
-public:
- b3CollisionObjectFloatData m_collisionObjectData;
- b3Matrix3x3FloatData m_invInertiaTensorWorld;
- b3Vector3FloatData m_linearVelocity;
- b3Vector3FloatData m_angularVelocity;
- b3Vector3FloatData m_angularFactor;
- b3Vector3FloatData m_linearFactor;
- b3Vector3FloatData m_gravity;
- b3Vector3FloatData m_gravity_acceleration;
- b3Vector3FloatData m_invInertiaLocal;
- b3Vector3FloatData m_totalForce;
- b3Vector3FloatData m_totalTorque;
- float m_inverseMass;
- float m_linearDamping;
- float m_angularDamping;
- float m_additionalDampingFactor;
- float m_additionalLinearDampingThresholdSqr;
- float m_additionalAngularDampingThresholdSqr;
- float m_additionalAngularDampingFactor;
- float m_linearSleepingThreshold;
- float m_angularSleepingThreshold;
- int m_additionalDamping;
-};
-
-// -------------------------------------------------- //
-class b3RigidBodyDoubleData
-{
-public:
- b3CollisionObjectDoubleData m_collisionObjectData;
- b3Matrix3x3DoubleData m_invInertiaTensorWorld;
- b3Vector3DoubleData m_linearVelocity;
- b3Vector3DoubleData m_angularVelocity;
- b3Vector3DoubleData m_angularFactor;
- b3Vector3DoubleData m_linearFactor;
- b3Vector3DoubleData m_gravity;
- b3Vector3DoubleData m_gravity_acceleration;
- b3Vector3DoubleData m_invInertiaLocal;
- b3Vector3DoubleData m_totalForce;
- b3Vector3DoubleData m_totalTorque;
- double m_inverseMass;
- double m_linearDamping;
- double m_angularDamping;
- double m_additionalDampingFactor;
- double m_additionalLinearDampingThresholdSqr;
- double m_additionalAngularDampingThresholdSqr;
- double m_additionalAngularDampingFactor;
- double m_linearSleepingThreshold;
- double m_angularSleepingThreshold;
- int m_additionalDamping;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3ConstraintInfo1
-{
-public:
- int m_numConstraintRows;
- int nub;
-};
-
-// -------------------------------------------------- //
-class b3TypedConstraintData
-{
-public:
- bInvalidHandle *m_rbA;
- bInvalidHandle *m_rbB;
- char *m_name;
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
- float m_appliedImpulse;
- float m_dbgDrawSize;
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
- float m_breakingImpulseThreshold;
- int m_isEnabled;
-};
-
-// -------------------------------------------------- //
-class b3Point2PointConstraintFloatData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3FloatData m_pivotInA;
- b3Vector3FloatData m_pivotInB;
-};
-
-// -------------------------------------------------- //
-class b3Point2PointConstraintDoubleData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3Vector3DoubleData m_pivotInA;
- b3Vector3DoubleData m_pivotInB;
-};
-
-// -------------------------------------------------- //
-class b3HingeConstraintDoubleData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformDoubleData m_rbAFrame;
- b3TransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-};
-
-// -------------------------------------------------- //
-class b3HingeConstraintFloatData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-};
-
-// -------------------------------------------------- //
-class b3ConeTwistConstraintData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- float m_swingSpan1;
- float m_swingSpan2;
- float m_twistSpan;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
- float m_damping;
- char m_pad[4];
-};
-
-// -------------------------------------------------- //
-class b3Generic6DofConstraintData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- b3Vector3FloatData m_linearUpperLimit;
- b3Vector3FloatData m_linearLowerLimit;
- b3Vector3FloatData m_angularUpperLimit;
- b3Vector3FloatData m_angularLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-// -------------------------------------------------- //
-class b3Generic6DofSpringConstraintData
-{
-public:
- b3Generic6DofConstraintData m_6dofData;
- int m_springEnabled[6];
- float m_equilibriumPoint[6];
- float m_springStiffness[6];
- float m_springDamping[6];
-};
-
-// -------------------------------------------------- //
-class b3SliderConstraintData
-{
-public:
- b3TypedConstraintData m_typeConstraintData;
- b3TransformFloatData m_rbAFrame;
- b3TransformFloatData m_rbBFrame;
- float m_linearUpperLimit;
- float m_linearLowerLimit;
- float m_angularUpperLimit;
- float m_angularLowerLimit;
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-// -------------------------------------------------- //
-class b3ContactSolverInfoDoubleData
-{
-public:
- double m_tau;
- double m_damping;
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp;
- double m_erp2;
- double m_globalCfm;
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_maxGyroscopicForce;
- double m_singleAxisRollingFrictionThreshold;
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3ContactSolverInfoFloatData
-{
-public:
- float m_tau;
- float m_damping;
- float m_friction;
- float m_timeStep;
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp;
- float m_erp2;
- float m_globalCfm;
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_maxGyroscopicForce;
- float m_singleAxisRollingFrictionThreshold;
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-};
-
-// -------------------------------------------------- //
-class b3DynamicsWorldDoubleData
-{
-public:
- b3ContactSolverInfoDoubleData m_solverInfo;
- b3Vector3DoubleData m_gravity;
-};
-
-// -------------------------------------------------- //
-class b3DynamicsWorldFloatData
-{
-public:
- b3ContactSolverInfoFloatData m_solverInfo;
- b3Vector3FloatData m_gravity;
-};
-
-// -------------------------------------------------- //
-class SoftBodyMaterialData
-{
-public:
- float m_linearStiffness;
- float m_angularStiffness;
- float m_volumeStiffness;
- int m_flags;
-};
-
-// -------------------------------------------------- //
-class SoftBodyNodeData
-{
-public:
- SoftBodyMaterialData *m_material;
- b3Vector3FloatData m_position;
- b3Vector3FloatData m_previousPosition;
- b3Vector3FloatData m_velocity;
- b3Vector3FloatData m_accumulatedForce;
- b3Vector3FloatData m_normal;
- float m_inverseMass;
- float m_area;
- int m_attach;
- int m_pad;
-};
-
-// -------------------------------------------------- //
-class SoftBodyLinkData
-{
-public:
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[2];
- float m_restLength;
- int m_bbending;
-};
-
-// -------------------------------------------------- //
-class SoftBodyFaceData
-{
-public:
- b3Vector3FloatData m_normal;
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[3];
- float m_restArea;
-};
-
-// -------------------------------------------------- //
-class SoftBodyTetraData
-{
-public:
- b3Vector3FloatData m_c0[4];
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[4];
- float m_restVolume;
- float m_c1;
- float m_c2;
- int m_pad;
-};
-
-// -------------------------------------------------- //
-class SoftRigidAnchorData
-{
-public:
- b3Matrix3x3FloatData m_c0;
- b3Vector3FloatData m_c1;
- b3Vector3FloatData m_localFrame;
- bInvalidHandle *m_rigidBody;
- int m_nodeIndex;
- float m_c2;
-};
-
-// -------------------------------------------------- //
-class SoftBodyConfigData
-{
-public:
- int m_aeroModel;
- float m_baumgarte;
- float m_damping;
- float m_drag;
- float m_lift;
- float m_pressure;
- float m_volume;
- float m_dynamicFriction;
- float m_poseMatch;
- float m_rigidContactHardness;
- float m_kineticContactHardness;
- float m_softContactHardness;
- float m_anchorHardness;
- float m_softRigidClusterHardness;
- float m_softKineticClusterHardness;
- float m_softSoftClusterHardness;
- float m_softRigidClusterImpulseSplit;
- float m_softKineticClusterImpulseSplit;
- float m_softSoftClusterImpulseSplit;
- float m_maxVolume;
- float m_timeScale;
- int m_velocityIterations;
- int m_positionIterations;
- int m_driftIterations;
- int m_clusterIterations;
- int m_collisionFlags;
-};
-
-// -------------------------------------------------- //
-class SoftBodyPoseData
-{
-public:
- b3Matrix3x3FloatData m_rot;
- b3Matrix3x3FloatData m_scale;
- b3Matrix3x3FloatData m_aqq;
- b3Vector3FloatData m_com;
- b3Vector3FloatData *m_positions;
- float *m_weights;
- int m_numPositions;
- int m_numWeigts;
- int m_bvolume;
- int m_bframe;
- float m_restVolume;
- int m_pad;
-};
-
-// -------------------------------------------------- //
-class SoftBodyClusterData
-{
-public:
- b3TransformFloatData m_framexform;
- b3Matrix3x3FloatData m_locii;
- b3Matrix3x3FloatData m_invwi;
- b3Vector3FloatData m_com;
- b3Vector3FloatData m_vimpulses[2];
- b3Vector3FloatData m_dimpulses[2];
- b3Vector3FloatData m_lv;
- b3Vector3FloatData m_av;
- b3Vector3FloatData *m_framerefs;
- int *m_nodeIndices;
- float *m_masses;
- int m_numFrameRefs;
- int m_numNodes;
- int m_numMasses;
- float m_idmass;
- float m_imass;
- int m_nvimpulses;
- int m_ndimpulses;
- float m_ndamping;
- float m_ldamping;
- float m_adamping;
- float m_matching;
- float m_maxSelfCollisionImpulse;
- float m_selfCollisionImpulseFactor;
- int m_containsAnchor;
- int m_collide;
- int m_clusterIndex;
-};
-
-// -------------------------------------------------- //
-class b3SoftBodyJointData
-{
-public:
- void *m_bodyA;
- void *m_bodyB;
- b3Vector3FloatData m_refs[2];
- float m_cfm;
- float m_erp;
- float m_split;
- int m_delete;
- b3Vector3FloatData m_relPosition[2];
- int m_bodyAtype;
- int m_bodyBtype;
- int m_jointType;
- int m_pad;
-};
-
-// -------------------------------------------------- //
-class b3SoftBodyFloatData
-{
-public:
- b3CollisionObjectFloatData m_collisionObjectData;
- SoftBodyPoseData *m_pose;
- SoftBodyMaterialData **m_materials;
- SoftBodyNodeData *m_nodes;
- SoftBodyLinkData *m_links;
- SoftBodyFaceData *m_faces;
- SoftBodyTetraData *m_tetrahedra;
- SoftRigidAnchorData *m_anchors;
- SoftBodyClusterData *m_clusters;
- b3SoftBodyJointData *m_joints;
- int m_numMaterials;
- int m_numNodes;
- int m_numLinks;
- int m_numFaces;
- int m_numTetrahedra;
- int m_numAnchors;
- int m_numClusters;
- int m_numJoints;
- SoftBodyConfigData m_config;
-};
-
-} // namespace Bullet3SerializeBullet2
-#endif //__BULLET2_H__ \ No newline at end of file
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
deleted file mode 100644
index d2a7163670..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.cpp
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2010 Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3BulletFile.h"
-#include "b3Defines.h"
-#include "b3DNA.h"
-
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-
-// 32 && 64 bit versions
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-#ifdef _WIN64
-extern char b3s_bulletDNAstr64[];
-extern int b3s_bulletDNAlen64;
-#else
-extern char b3s_bulletDNAstr[];
-extern int b3s_bulletDNAlen;
-#endif //_WIN64
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
-extern char b3s_bulletDNAstr64[];
-extern int b3s_bulletDNAlen64;
-extern char b3s_bulletDNAstr[];
-extern int b3s_bulletDNAlen;
-
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
-using namespace bParse;
-
-b3BulletFile::b3BulletFile()
- : bFile("", "BULLET ")
-{
- mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor,@todo not consistent with the rule 'who allocates it, has to deallocate it"
-
- m_DnaCopy = 0;
-
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-#ifdef _WIN64
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
- mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
-#else //_WIN64
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
- mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
-#endif //_WIN64
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
- mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen64);
- }
- else
- {
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
- mMemoryDNA->init(m_DnaCopy, b3s_bulletDNAlen);
- }
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-}
-
-b3BulletFile::b3BulletFile(const char* fileName)
- : bFile(fileName, "BULLET ")
-{
- m_DnaCopy = 0;
-}
-
-b3BulletFile::b3BulletFile(char* memoryBuffer, int len)
- : bFile(memoryBuffer, len, "BULLET ")
-{
- m_DnaCopy = 0;
-}
-
-b3BulletFile::~b3BulletFile()
-{
- if (m_DnaCopy)
- b3AlignedFree(m_DnaCopy);
-
- while (m_dataBlocks.size())
- {
- char* dataBlock = m_dataBlocks[m_dataBlocks.size() - 1];
- delete[] dataBlock;
- m_dataBlocks.pop_back();
- }
-}
-
-// ----------------------------------------------------- //
-void b3BulletFile::parseData()
-{
- // printf ("Building datablocks");
- // printf ("Chunk size = %d",CHUNK_HEADER_LEN);
- // printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
-
- const bool brokenDNA = (mFlags & FD_BROKEN_DNA) != 0;
-
- //const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
-
- mDataStart = 12;
-
- char* dataPtr = mFileBuffer + mDataStart;
-
- bChunkInd dataChunk;
- dataChunk.code = 0;
-
- //dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
- int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
-
- if (mFlags & FD_ENDIAN_SWAP)
- swapLen(dataPtr);
-
- //dataPtr += ChunkUtils::getOffset(mFlags);
- char* dataPtrHead = 0;
-
- while (dataChunk.code != B3_DNA1)
- {
- if (!brokenDNA || (dataChunk.code != B3_QUANTIZED_BVH_CODE))
- {
- // one behind
- if (dataChunk.code == B3_SDNA) break;
- //if (dataChunk.code == DNA1) break;
-
- // same as (BHEAD+DATA dependency)
- dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
- if (dataChunk.dna_nr >= 0)
- {
- char* id = readStruct(dataPtrHead, dataChunk);
-
- // lookup maps
- if (id)
- {
- m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
- mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
-
- m_chunks.push_back(dataChunk);
- // block it
- //bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
- //if (listID)
- // listID->push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_SOFTBODY_CODE)
- {
- m_softBodies.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_RIGIDBODY_CODE)
- {
- m_rigidBodies.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_DYNAMICSWORLD_CODE)
- {
- m_dynamicsWorldInfo.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_CONSTRAINT_CODE)
- {
- m_constraints.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_QUANTIZED_BVH_CODE)
- {
- m_bvhs.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_TRIANLGE_INFO_MAP)
- {
- m_triangleInfoMaps.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_COLLISIONOBJECT_CODE)
- {
- m_collisionObjects.push_back((bStructHandle*)id);
- }
-
- if (dataChunk.code == B3_SHAPE_CODE)
- {
- m_collisionShapes.push_back((bStructHandle*)id);
- }
-
- // if (dataChunk.code == GLOB)
- // {
- // m_glob = (bStructHandle*) id;
- // }
- }
- else
- {
- //printf("unknown chunk\n");
-
- mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
- }
- }
- else
- {
- printf("skipping B3_QUANTIZED_BVH_CODE due to broken DNA\n");
- }
-
- dataPtr += seek;
-
- seek = getNextBlock(&dataChunk, dataPtr, mFlags);
- if (mFlags & FD_ENDIAN_SWAP)
- swapLen(dataPtr);
-
- if (seek < 0)
- break;
- }
-}
-
-void b3BulletFile::addDataBlock(char* dataBlock)
-{
- m_dataBlocks.push_back(dataBlock);
-}
-
-void b3BulletFile::writeDNA(FILE* fp)
-{
- bChunkInd dataChunk;
- dataChunk.code = B3_DNA1;
- dataChunk.dna_nr = 0;
- dataChunk.nr = 1;
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
-#ifdef _WIN64
- dataChunk.len = b3s_bulletDNAlen64;
- dataChunk.oldPtr = b3s_bulletDNAstr64;
- fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
- fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
-#else
- b3Assert(0);
-#endif
- }
- else
- {
-#ifndef _WIN64
- dataChunk.len = b3s_bulletDNAlen;
- dataChunk.oldPtr = b3s_bulletDNAstr;
- fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
- fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
-#else //_WIN64
- b3Assert(0);
-#endif //_WIN64
- }
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- dataChunk.len = b3s_bulletDNAlen64;
- dataChunk.oldPtr = b3s_bulletDNAstr64;
- fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
- fwrite(b3s_bulletDNAstr64, b3s_bulletDNAlen64, 1, fp);
- }
- else
- {
- dataChunk.len = b3s_bulletDNAlen;
- dataChunk.oldPtr = b3s_bulletDNAstr;
- fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
- fwrite(b3s_bulletDNAstr, b3s_bulletDNAlen, 1, fp);
- }
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-}
-
-void b3BulletFile::parse(int verboseMode)
-{
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
-#ifdef _WIN64
-
- if (m_DnaCopy)
- delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
- parseInternal(verboseMode, (char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
-#else
- b3Assert(0);
-#endif
- }
- else
- {
-#ifndef _WIN64
-
- if (m_DnaCopy)
- delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
- parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
-#else
- b3Assert(0);
-#endif
- }
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- if (m_DnaCopy)
- delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen64, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr64, b3s_bulletDNAlen64);
- parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen64);
- }
- else
- {
- if (m_DnaCopy)
- delete m_DnaCopy;
- m_DnaCopy = (char*)b3AlignedAlloc(b3s_bulletDNAlen, 16);
- memcpy(m_DnaCopy, b3s_bulletDNAstr, b3s_bulletDNAlen);
- parseInternal(verboseMode, m_DnaCopy, b3s_bulletDNAlen);
- }
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
-
- //the parsing will convert to cpu endian
- mFlags &= ~FD_ENDIAN_SWAP;
-
- int littleEndian = 1;
- littleEndian = ((char*)&littleEndian)[0];
-
- mFileBuffer[8] = littleEndian ? 'v' : 'V';
-}
-
-// experimental
-int b3BulletFile::write(const char* fileName, bool fixupPointers)
-{
- FILE* fp = fopen(fileName, "wb");
- if (fp)
- {
- char header[B3_SIZEOFBLENDERHEADER];
- memcpy(header, m_headerString, 7);
- int endian = 1;
- endian = ((char*)&endian)[0];
-
- if (endian)
- {
- header[7] = '_';
- }
- else
- {
- header[7] = '-';
- }
- if (VOID_IS_8)
- {
- header[8] = 'V';
- }
- else
- {
- header[8] = 'v';
- }
-
- header[9] = '2';
- header[10] = '7';
- header[11] = '5';
-
- fwrite(header, B3_SIZEOFBLENDERHEADER, 1, fp);
-
- writeChunks(fp, fixupPointers);
-
- writeDNA(fp);
-
- fclose(fp);
- }
- else
- {
- printf("Error: cannot open file %s for writing\n", fileName);
- return 0;
- }
- return 1;
-}
-
-void b3BulletFile::addStruct(const char* structType, void* data, int len, void* oldPtr, int code)
-{
- bParse::bChunkInd dataChunk;
- dataChunk.code = code;
- dataChunk.nr = 1;
- dataChunk.len = len;
- dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
- dataChunk.oldPtr = oldPtr;
-
- ///Perform structure size validation
- short* structInfo = mMemoryDNA->getStruct(dataChunk.dna_nr);
- int elemBytes;
- elemBytes = mMemoryDNA->getLength(structInfo[0]);
- // int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
- assert(len == elemBytes);
-
- mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
- m_chunks.push_back(dataChunk);
-}
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
deleted file mode 100644
index ede1d378ae..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3BulletFile.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2010 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_BULLET_FILE_H
-#define B3_BULLET_FILE_H
-
-#include "b3File.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "b3Defines.h"
-
-#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
-
-namespace bParse
-{
-// ----------------------------------------------------- //
-class b3BulletFile : public bFile
-{
-protected:
- char* m_DnaCopy;
-
-public:
- b3AlignedObjectArray<bStructHandle*> m_softBodies;
-
- b3AlignedObjectArray<bStructHandle*> m_rigidBodies;
-
- b3AlignedObjectArray<bStructHandle*> m_collisionObjects;
-
- b3AlignedObjectArray<bStructHandle*> m_collisionShapes;
-
- b3AlignedObjectArray<bStructHandle*> m_constraints;
-
- b3AlignedObjectArray<bStructHandle*> m_bvhs;
-
- b3AlignedObjectArray<bStructHandle*> m_triangleInfoMaps;
-
- b3AlignedObjectArray<bStructHandle*> m_dynamicsWorldInfo;
-
- b3AlignedObjectArray<char*> m_dataBlocks;
- b3BulletFile();
-
- b3BulletFile(const char* fileName);
-
- b3BulletFile(char* memoryBuffer, int len);
-
- virtual ~b3BulletFile();
-
- virtual void addDataBlock(char* dataBlock);
-
- // experimental
- virtual int write(const char* fileName, bool fixupPointers = false);
-
- virtual void parse(int verboseMode);
-
- virtual void parseData();
-
- virtual void writeDNA(FILE* fp);
-
- void addStruct(const char* structType, void* data, int len, void* oldPtr, int code);
-};
-}; // namespace bParse
-
-#endif //B3_BULLET_FILE_H
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
deleted file mode 100644
index ff75ff8cc4..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "b3Chunk.h"
-#include "b3Defines.h"
-#include "b3File.h"
-
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-
-using namespace bParse;
-
-// ----------------------------------------------------- //
-short ChunkUtils::swapShort(short sht)
-{
- B3_SWITCH_SHORT(sht);
- return sht;
-}
-
-// ----------------------------------------------------- //
-int ChunkUtils::swapInt(int inte)
-{
- B3_SWITCH_INT(inte);
- return inte;
-}
-
-// ----------------------------------------------------- //
-b3Long64 ChunkUtils::swapLong64(b3Long64 lng)
-{
- B3_SWITCH_LONGINT(lng);
- return lng;
-}
-
-// ----------------------------------------------------- //
-int ChunkUtils::getOffset(int flags)
-{
- // if the file is saved in a
- // different format, get the
- // file's chunk size
- int res = CHUNK_HEADER_LEN;
-
- if (VOID_IS_8)
- {
- if (flags & FD_BITS_VARIES)
- res = sizeof(bChunkPtr4);
- }
- else
- {
- if (flags & FD_BITS_VARIES)
- res = sizeof(bChunkPtr8);
- }
- return res;
-}
-
-//eof
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
deleted file mode 100644
index c9d0f37d9e..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Chunk.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef __BCHUNK_H__
-#define __BCHUNK_H__
-
-#if defined(_WIN32) && !defined(__MINGW32__)
-#define b3Long64 __int64
-#elif defined(__MINGW32__)
-#include <stdint.h>
-#define b3Long64 int64_t
-#else
-#define b3Long64 long long
-#endif
-
-namespace bParse
-{
-// ----------------------------------------------------- //
-class bChunkPtr4
-{
-public:
- bChunkPtr4() {}
- int code;
- int len;
- union {
- int m_uniqueInt;
- };
- int dna_nr;
- int nr;
-};
-
-// ----------------------------------------------------- //
-class bChunkPtr8
-{
-public:
- bChunkPtr8() {}
- int code, len;
- union {
- b3Long64 oldPrev;
- int m_uniqueInts[2];
- };
- int dna_nr, nr;
-};
-
-// ----------------------------------------------------- //
-class bChunkInd
-{
-public:
- bChunkInd() {}
- int code, len;
- void *oldPtr;
- int dna_nr, nr;
-};
-
-// ----------------------------------------------------- //
-class ChunkUtils
-{
-public:
- // file chunk offset
- static int getOffset(int flags);
-
- // endian utils
- static short swapShort(short sht);
- static int swapInt(int inte);
- static b3Long64 swapLong64(b3Long64 lng);
-};
-
-const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
-const bool VOID_IS_8 = ((sizeof(void *) == 8));
-} // namespace bParse
-
-#endif //__BCHUNK_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h
deleted file mode 100644
index 5884fad4d6..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Common.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef __BCOMMON_H__
-#define __BCOMMON_H__
-
-#include <assert.h>
-//#include "bLog.h"
-#include "Bullet3Common/b3AlignedObjectArray.h"
-#include "Bullet3Common/b3HashMap.h"
-
-namespace bParse
-{
-class bMain;
-class bFileData;
-class bFile;
-class bDNA;
-
-// delete void* undefined
-typedef struct bStructHandle
-{
- int unused;
-} bStructHandle;
-typedef b3AlignedObjectArray<bStructHandle*> bListBasePtr;
-typedef b3HashMap<b3HashPtr, bStructHandle*> bPtrMap;
-} // namespace bParse
-
-#endif //__BCOMMON_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
deleted file mode 100644
index 09c8f23859..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.cpp
+++ /dev/null
@@ -1,616 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include <assert.h>
-
-#include "b3DNA.h"
-#include "b3Chunk.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-//this define will force traversal of structures, to check backward (and forward) compatibility
-//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
-
-using namespace bParse;
-
-// ----------------------------------------------------- //
-bDNA::bDNA()
- : mPtrLen(0)
-{
- // --
-}
-
-// ----------------------------------------------------- //
-bDNA::~bDNA()
-{
- // --
-}
-
-// ----------------------------------------------------- //
-bool bDNA::lessThan(bDNA *file)
-{
- return (m_Names.size() < file->m_Names.size());
-}
-
-// ----------------------------------------------------- //
-char *bDNA::getName(int ind)
-{
- assert(ind <= (int)m_Names.size());
- return m_Names[ind].m_name;
-}
-
-// ----------------------------------------------------- //
-char *bDNA::getType(int ind)
-{
- assert(ind <= (int)mTypes.size());
- return mTypes[ind];
-}
-
-// ----------------------------------------------------- //
-short *bDNA::getStruct(int ind)
-{
- assert(ind <= (int)mStructs.size());
- return mStructs[ind];
-}
-
-// ----------------------------------------------------- //
-short bDNA::getLength(int ind)
-{
- assert(ind <= (int)mTlens.size());
- return mTlens[ind];
-}
-
-// ----------------------------------------------------- //
-int bDNA::getReverseType(short type)
-{
- int *intPtr = mStructReverse.find(type);
- if (intPtr)
- return *intPtr;
-
- return -1;
-}
-
-// ----------------------------------------------------- //
-int bDNA::getReverseType(const char *type)
-{
- b3HashString key(type);
- int *valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
-
- return -1;
-}
-
-// ----------------------------------------------------- //
-int bDNA::getNumStructs()
-{
- return (int)mStructs.size();
-}
-
-// ----------------------------------------------------- //
-bool bDNA::flagNotEqual(int dna_nr)
-{
- assert(dna_nr <= (int)mCMPFlags.size());
- return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
-}
-
-// ----------------------------------------------------- //
-bool bDNA::flagEqual(int dna_nr)
-{
- assert(dna_nr <= (int)mCMPFlags.size());
- int flag = mCMPFlags[dna_nr];
- return flag == FDF_STRUCT_EQU;
-}
-
-// ----------------------------------------------------- //
-bool bDNA::flagNone(int dna_nr)
-{
- assert(dna_nr <= (int)mCMPFlags.size());
- return mCMPFlags[dna_nr] == FDF_NONE;
-}
-
-// ----------------------------------------------------- //
-int bDNA::getPointerSize()
-{
- return mPtrLen;
-}
-
-// ----------------------------------------------------- //
-void bDNA::initRecurseCmpFlags(int iter)
-{
- // iter is FDF_STRUCT_NEQU
-
- short *oldStrc = mStructs[iter];
- short type = oldStrc[0];
-
- for (int i = 0; i < (int)mStructs.size(); i++)
- {
- if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU)
- {
- short *curStruct = mStructs[i];
- int eleLen = curStruct[1];
- curStruct += 2;
-
- for (int j = 0; j < eleLen; j++, curStruct += 2)
- {
- if (curStruct[0] == type)
- {
- //char *name = m_Names[curStruct[1]].m_name;
- //if (name[0] != '*')
- if (m_Names[curStruct[1]].m_isPointer)
- {
- mCMPFlags[i] = FDF_STRUCT_NEQU;
- initRecurseCmpFlags(i);
- }
- }
- }
- }
- }
-}
-
-// ----------------------------------------------------- //
-void bDNA::initCmpFlags(bDNA *memDNA)
-{
- // compare the file to memory
- // this ptr should be the file data
-
- assert(!(m_Names.size() == 0)); // && "SDNA empty!");
- mCMPFlags.resize(mStructs.size(), FDF_NONE);
-
- int i;
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short *oldStruct = mStructs[i];
-
- int oldLookup = getReverseType(oldStruct[0]);
- if (oldLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
- //char* typeName = mTypes[oldStruct[0]];
-
-//#define SLOW_FORWARD_COMPATIBLE 1
-#ifdef SLOW_FORWARD_COMPATIBLE
- char *typeName = mTypes[oldLookup];
- int newLookup = memDNA->getReverseType(typeName);
- if (newLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
- short *curStruct = memDNA->mStructs[newLookup];
-#else
- // memory for file
-
- if (oldLookup < memDNA->mStructs.size())
- {
- short *curStruct = memDNA->mStructs[oldLookup];
-#endif
-
- // rebuild...
- mCMPFlags[i] = FDF_STRUCT_NEQU;
-
-#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
-
- if (curStruct[1] == oldStruct[1])
- {
- // type len same ...
- if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
- {
- bool isSame = true;
- int elementLength = oldStruct[1];
-
- curStruct += 2;
- oldStruct += 2;
-
- for (int j = 0; j < elementLength; j++, curStruct += 2, oldStruct += 2)
- {
- // type the same
- //const char* typeFileDNA = mTypes[oldStruct[0]];
- //const char* typeMemDNA = mTypes[curStruct[0]];
- if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]]) != 0)
- {
- isSame = false;
- break;
- }
-
- // name the same
- if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name) != 0)
- {
- isSame = false;
- break;
- }
- }
- // flag valid ==
- if (isSame)
- mCMPFlags[i] = FDF_STRUCT_EQU;
- }
- }
-#endif
- }
-}
-
-// recurse in
-for (i = 0; i < (int)mStructs.size(); i++)
-{
- if (mCMPFlags[i] == FDF_STRUCT_NEQU)
- initRecurseCmpFlags(i);
-}
-}
-
-static int name_is_array(char *name, int *dim1, int *dim2)
-{
- int len = strlen(name);
- /*fprintf(stderr,"[%s]",name);*/
- /*if (len >= 1) {
- if (name[len-1] != ']')
- return 1;
- }
- return 0;*/
- char *bp;
- int num;
- if (dim1)
- {
- *dim1 = 1;
- }
- if (dim2)
- {
- *dim2 = 1;
- }
- bp = strchr(name, '[');
- if (!bp)
- {
- return 0;
- }
- num = 0;
- while (++bp < name + len - 1)
- {
- const char c = *bp;
- if (c == ']')
- {
- break;
- }
- if (c <= '9' && c >= '0')
- {
- num *= 10;
- num += (c - '0');
- }
- else
- {
- printf("array parse error.\n");
- return 0;
- }
- }
- if (dim2)
- {
- *dim2 = num;
- }
-
- /* find second dim, if any. */
- bp = strchr(bp, '[');
- if (!bp)
- {
- return 1; /* at least we got the first dim. */
- }
- num = 0;
- while (++bp < name + len - 1)
- {
- const char c = *bp;
- if (c == ']')
- {
- break;
- }
- if (c <= '9' && c >= '0')
- {
- num *= 10;
- num += (c - '0');
- }
- else
- {
- printf("array2 parse error.\n");
- return 1;
- }
- }
- if (dim1)
- {
- if (dim2)
- {
- *dim1 = *dim2;
- *dim2 = num;
- }
- else
- {
- *dim1 = num;
- }
- }
-
- return 1;
-}
-
-// ----------------------------------------------------- //
-void bDNA::init(char *data, int len, bool swap)
-{
- int *intPtr = 0;
- short *shtPtr = 0;
- char *cp = 0;
- int dataLen = 0;
- //long nr=0;
- intPtr = (int *)data;
-
- /*
- SDNA (4 bytes) (magic number)
- NAME (4 bytes)
- <nr> (4 bytes) amount of names (int)
- <string>
- <string>
- */
-
- if (strncmp(data, "SDNA", 4) == 0)
- {
- // skip ++ NAME
- intPtr++;
- intPtr++;
- }
-
- // Parse names
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
-
- cp = (char *)intPtr;
- int i;
- for (i = 0; i < dataLen; i++)
- {
- bNameInfo info;
- info.m_name = cp;
- info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
- name_is_array(info.m_name, &info.m_dim0, &info.m_dim1);
- m_Names.push_back(info);
- while (*cp) cp++;
- cp++;
- }
-
- cp = b3AlignPointer(cp, 4);
-
- /*
- TYPE (4 bytes)
- <nr> amount of types (int)
- <string>
- <string>
- */
-
- intPtr = (int *)cp;
- assert(strncmp(cp, "TYPE", 4) == 0);
- intPtr++;
-
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
-
- cp = (char *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp) cp++;
- cp++;
- }
-
- cp = b3AlignPointer(cp, 4);
-
- /*
- TLEN (4 bytes)
- <len> (short) the lengths of types
- <len>
- */
-
- // Parse type lens
- intPtr = (int *)cp;
- assert(strncmp(cp, "TLEN", 4) == 0);
- intPtr++;
-
- dataLen = (int)mTypes.size();
-
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++, shtPtr++)
- {
- if (swap)
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
-
- if (dataLen & 1) shtPtr++;
-
- /*
- STRC (4 bytes)
- <nr> amount of structs (int)
- <typenr>
- <nr_of_elems>
- <typenr>
- <namenr>
- <typenr>
- <namenr>
- */
-
- intPtr = (int *)shtPtr;
- cp = (char *)intPtr;
- assert(strncmp(cp, "STRC", 4) == 0);
- intPtr++;
-
- if (swap)
- {
- *intPtr = ChunkUtils::swapInt(*intPtr);
- }
- dataLen = *intPtr;
- intPtr++;
-
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mStructs.push_back(shtPtr);
- if (swap)
- {
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
-
- int len = shtPtr[1];
- shtPtr += 2;
-
- for (int a = 0; a < len; a++, shtPtr += 2)
- {
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
- }
- }
- else
- shtPtr += (2 * shtPtr[1]) + 2;
- }
-
- // build reverse lookups
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short *strc = mStructs.at(i);
- if (!mPtrLen && strcmp(mTypes[strc[0]], "ListBase") == 0)
- {
- mPtrLen = mTlens[strc[0]] / 2;
- }
-
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
- }
-}
-
-// ----------------------------------------------------- //
-int bDNA::getArraySize(char *string)
-{
- int ret = 1;
- int len = strlen(string);
-
- char *next = 0;
- for (int i = 0; i < len; i++)
- {
- char c = string[i];
-
- if (c == '[')
- next = &string[i + 1];
- else if (c == ']')
- if (next)
- ret *= atoi(next);
- }
-
- // print (string << ' ' << ret);
- return ret;
-}
-
-void bDNA::dumpTypeDefinitions()
-{
- int i;
-
- int numTypes = mTypes.size();
-
- for (i = 0; i < numTypes; i++)
- {
- }
-
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- int totalBytes = 0;
- short *oldStruct = mStructs[i];
-
- int oldLookup = getReverseType(oldStruct[0]);
- if (oldLookup == -1)
- {
- mCMPFlags[i] = FDF_NONE;
- continue;
- }
-
- short *newStruct = mStructs[oldLookup];
- char *typeName = mTypes[newStruct[0]];
- printf("%3d: %s ", i, typeName);
-
- //char *name = mNames[oldStruct[1]];
- int len = oldStruct[1];
- printf(" (%d fields) ", len);
- oldStruct += 2;
-
- printf("{");
- int j;
- for (j = 0; j < len; ++j, oldStruct += 2)
- {
- const char *name = m_Names[oldStruct[1]].m_name;
- printf("%s %s", mTypes[oldStruct[0]], name);
- int elemNumBytes = 0;
- int arrayDimensions = getArraySizeNew(oldStruct[1]);
-
- if (m_Names[oldStruct[1]].m_isPointer)
- {
- elemNumBytes = VOID_IS_8 ? 8 : 4;
- }
- else
- {
- elemNumBytes = getLength(oldStruct[0]);
- }
- printf(" /* %d bytes */", elemNumBytes * arrayDimensions);
-
- if (j == len - 1)
- {
- printf(";}");
- }
- else
- {
- printf("; ");
- }
- totalBytes += elemNumBytes * arrayDimensions;
- }
- printf("\ntotalBytes=%d\n\n", totalBytes);
- }
-
-#if 0
- /* dump out display of types and their sizes */
- for (i=0; i<bf->types_count; ++i) {
- /* if (!bf->types[i].is_struct)*/
- {
- printf("%3d: sizeof(%s%s)=%d",
- i,
- bf->types[i].is_struct ? "struct " : "atomic ",
- bf->types[i].name, bf->types[i].size);
- if (bf->types[i].is_struct) {
- int j;
- printf(", %d fields: { ", bf->types[i].fieldtypes_count);
- for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
- printf("%s %s",
- bf->types[bf->types[i].fieldtypes[j]].name,
- bf->names[bf->types[i].fieldnames[j]]);
- if (j == bf->types[i].fieldtypes_count-1) {
- printf(";}");
- } else {
- printf("; ");
- }
- }
- }
- printf("\n\n");
-
- }
- }
-#endif
-}
-
-//eof
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
deleted file mode 100644
index ca6004d960..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3DNA.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef __BDNA_H__
-#define __BDNA_H__
-
-#include "b3Common.h"
-
-namespace bParse
-{
-struct bNameInfo
-{
- char *m_name;
- bool m_isPointer;
- int m_dim0;
- int m_dim1;
-};
-
-class bDNA
-{
-public:
- bDNA();
- ~bDNA();
-
- void init(char *data, int len, bool swap = false);
-
- int getArraySize(char *str);
- int getArraySizeNew(short name)
- {
- const bNameInfo &nameInfo = m_Names[name];
- return nameInfo.m_dim0 * nameInfo.m_dim1;
- }
- int getElementSize(short type, short name)
- {
- const bNameInfo &nameInfo = m_Names[name];
- int size = nameInfo.m_isPointer ? mPtrLen * nameInfo.m_dim0 * nameInfo.m_dim1 : mTlens[type] * nameInfo.m_dim0 * nameInfo.m_dim1;
- return size;
- }
-
- int getNumNames() const
- {
- return m_Names.size();
- }
-
- char *getName(int ind);
- char *getType(int ind);
- short *getStruct(int ind);
- short getLength(int ind);
- int getReverseType(short type);
- int getReverseType(const char *type);
-
- int getNumStructs();
-
- //
- bool lessThan(bDNA *other);
-
- void initCmpFlags(bDNA *memDNA);
- bool flagNotEqual(int dna_nr);
- bool flagEqual(int dna_nr);
- bool flagNone(int dna_nr);
-
- int getPointerSize();
-
- void dumpTypeDefinitions();
-
-private:
- enum FileDNAFlags
- {
- FDF_NONE = 0,
- FDF_STRUCT_NEQU,
- FDF_STRUCT_EQU
- };
-
- void initRecurseCmpFlags(int i);
-
- b3AlignedObjectArray<int> mCMPFlags;
-
- b3AlignedObjectArray<bNameInfo> m_Names;
- b3AlignedObjectArray<char *> mTypes;
- b3AlignedObjectArray<short *> mStructs;
- b3AlignedObjectArray<short> mTlens;
- b3HashMap<b3HashInt, int> mStructReverse;
- b3HashMap<b3HashString, int> mTypeLookup;
-
- int mPtrLen;
-};
-} // namespace bParse
-
-#endif //__BDNA_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
deleted file mode 100644
index 0524c94db1..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Defines.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-*
-* This software is provided 'as-is', without any express or implied
-* warranty. In no event will the authors be held liable for any damages
-* arising from the use of this software.
-*
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-*
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would be
-* appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-* misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-*/
-#ifndef __B_DEFINES_H__
-#define __B_DEFINES_H__
-
-// MISC defines, see BKE_global.h, BKE_utildefines.h
-#define B3_SIZEOFBLENDERHEADER 12
-
-// ------------------------------------------------------------
-#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
-#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
-#else
-#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
-#endif
-
-// ------------------------------------------------------------
-#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
-#define B3_MAKE_ID2(c, d) ((c) << 8 | (d))
-#else
-#define B3_MAKE_ID2(c, d) ((d) << 8 | (c))
-#endif
-
-// ------------------------------------------------------------
-#define B3_ID_SCE B3_MAKE_ID2('S', 'C')
-#define B3_ID_LI B3_MAKE_ID2('L', 'I')
-#define B3_ID_OB B3_MAKE_ID2('O', 'B')
-#define B3_ID_ME B3_MAKE_ID2('M', 'E')
-#define B3_ID_CU B3_MAKE_ID2('C', 'U')
-#define B3_ID_MB B3_MAKE_ID2('M', 'B')
-#define B3_ID_MA B3_MAKE_ID2('M', 'A')
-#define B3_ID_TE B3_MAKE_ID2('T', 'E')
-#define B3_ID_IM B3_MAKE_ID2('I', 'M')
-#define B3_ID_IK B3_MAKE_ID2('I', 'K')
-#define B3_ID_WV B3_MAKE_ID2('W', 'V')
-#define B3_ID_LT B3_MAKE_ID2('L', 'T')
-#define B3_ID_SE B3_MAKE_ID2('S', 'E')
-#define B3_ID_LF B3_MAKE_ID2('L', 'F')
-#define B3_ID_LA B3_MAKE_ID2('L', 'A')
-#define B3_ID_CA B3_MAKE_ID2('C', 'A')
-#define B3_ID_IP B3_MAKE_ID2('I', 'P')
-#define B3_ID_KE B3_MAKE_ID2('K', 'E')
-#define B3_ID_WO B3_MAKE_ID2('W', 'O')
-#define B3_ID_SCR B3_MAKE_ID2('S', 'R')
-#define B3_ID_VF B3_MAKE_ID2('V', 'F')
-#define B3_ID_TXT B3_MAKE_ID2('T', 'X')
-#define B3_ID_SO B3_MAKE_ID2('S', 'O')
-#define B3_ID_SAMPLE B3_MAKE_ID2('S', 'A')
-#define B3_ID_GR B3_MAKE_ID2('G', 'R')
-#define B3_ID_ID B3_MAKE_ID2('I', 'D')
-#define B3_ID_AR B3_MAKE_ID2('A', 'R')
-#define B3_ID_AC B3_MAKE_ID2('A', 'C')
-#define B3_ID_SCRIPT B3_MAKE_ID2('P', 'Y')
-#define B3_ID_FLUIDSIM B3_MAKE_ID2('F', 'S')
-#define B3_ID_NT B3_MAKE_ID2('N', 'T')
-#define B3_ID_BR B3_MAKE_ID2('B', 'R')
-
-#define B3_ID_SEQ B3_MAKE_ID2('S', 'Q')
-#define B3_ID_CO B3_MAKE_ID2('C', 'O')
-#define B3_ID_PO B3_MAKE_ID2('A', 'C')
-#define B3_ID_NLA B3_MAKE_ID2('N', 'L')
-
-#define B3_ID_VS B3_MAKE_ID2('V', 'S')
-#define B3_ID_VN B3_MAKE_ID2('V', 'N')
-
-// ------------------------------------------------------------
-#define B3_FORM B3_MAKE_ID('F', 'O', 'R', 'M')
-#define B3_DDG1 B3_MAKE_ID('3', 'D', 'G', '1')
-#define B3_DDG2 B3_MAKE_ID('3', 'D', 'G', '2')
-#define B3_DDG3 B3_MAKE_ID('3', 'D', 'G', '3')
-#define B3_DDG4 B3_MAKE_ID('3', 'D', 'G', '4')
-#define B3_GOUR B3_MAKE_ID('G', 'O', 'U', 'R')
-#define B3_BLEN B3_MAKE_ID('B', 'L', 'E', 'N')
-#define B3_DER_ B3_MAKE_ID('D', 'E', 'R', '_')
-#define B3_V100 B3_MAKE_ID('V', '1', '0', '0')
-#define B3_DATA B3_MAKE_ID('D', 'A', 'T', 'A')
-#define B3_GLOB B3_MAKE_ID('G', 'L', 'O', 'B')
-#define B3_IMAG B3_MAKE_ID('I', 'M', 'A', 'G')
-#define B3_TEST B3_MAKE_ID('T', 'E', 'S', 'T')
-#define B3_USER B3_MAKE_ID('U', 'S', 'E', 'R')
-
-// ------------------------------------------------------------
-#define B3_DNA1 B3_MAKE_ID('D', 'N', 'A', '1')
-#define B3_REND B3_MAKE_ID('R', 'E', 'N', 'D')
-#define B3_ENDB B3_MAKE_ID('E', 'N', 'D', 'B')
-#define B3_NAME B3_MAKE_ID('N', 'A', 'M', 'E')
-#define B3_SDNA B3_MAKE_ID('S', 'D', 'N', 'A')
-#define B3_TYPE B3_MAKE_ID('T', 'Y', 'P', 'E')
-#define B3_TLEN B3_MAKE_ID('T', 'L', 'E', 'N')
-#define B3_STRC B3_MAKE_ID('S', 'T', 'R', 'C')
-
-// ------------------------------------------------------------
-#define B3_SWITCH_INT(a) \
- { \
- char s_i, *p_i; \
- p_i = (char *)&(a); \
- s_i = p_i[0]; \
- p_i[0] = p_i[3]; \
- p_i[3] = s_i; \
- s_i = p_i[1]; \
- p_i[1] = p_i[2]; \
- p_i[2] = s_i; \
- }
-
-// ------------------------------------------------------------
-#define B3_SWITCH_SHORT(a) \
- { \
- char s_i, *p_i; \
- p_i = (char *)&(a); \
- s_i = p_i[0]; \
- p_i[0] = p_i[1]; \
- p_i[1] = s_i; \
- }
-
-// ------------------------------------------------------------
-#define B3_SWITCH_LONGINT(a) \
- { \
- char s_i, *p_i; \
- p_i = (char *)&(a); \
- s_i = p_i[0]; \
- p_i[0] = p_i[7]; \
- p_i[7] = s_i; \
- s_i = p_i[1]; \
- p_i[1] = p_i[6]; \
- p_i[6] = s_i; \
- s_i = p_i[2]; \
- p_i[2] = p_i[5]; \
- p_i[5] = s_i; \
- s_i = p_i[3]; \
- p_i[3] = p_i[4]; \
- p_i[4] = s_i; \
- }
-
-#endif //__B_DEFINES_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
deleted file mode 100644
index f6c779a919..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.cpp
+++ /dev/null
@@ -1,1653 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include "b3File.h"
-#include "b3Common.h"
-#include "b3Chunk.h"
-#include "b3DNA.h"
-#include <math.h>
-#include <string.h>
-#include <stdlib.h>
-#include "b3Defines.h"
-#include "Bullet3Serialize/Bullet2FileLoader/b3Serializer.h"
-#include "Bullet3Common/b3AlignedAllocator.h"
-#include "Bullet3Common/b3MinMax.h"
-
-#define B3_SIZEOFBLENDERHEADER 12
-#define MAX_ARRAY_LENGTH 512
-using namespace bParse;
-#define MAX_STRLEN 1024
-
-const char *getCleanName(const char *memName, char *buffer)
-{
- int slen = strlen(memName);
- assert(slen < MAX_STRLEN);
- slen = b3Min(slen, MAX_STRLEN);
- for (int i = 0; i < slen; i++)
- {
- if (memName[i] == ']' || memName[i] == '[')
- {
- buffer[i] = 0; //'_';
- }
- else
- {
- buffer[i] = memName[i];
- }
- }
- buffer[slen] = 0;
- return buffer;
-}
-
-// ----------------------------------------------------- //
-bFile::bFile(const char *filename, const char headerString[7])
- : mOwnsBuffer(true),
- mFileBuffer(0),
- mFileLen(0),
- mVersion(0),
- mDataStart(0),
- mFileDNA(0),
- mMemoryDNA(0),
- mFlags(FD_INVALID)
-{
- for (int i = 0; i < 7; i++)
- {
- m_headerString[i] = headerString[i];
- }
-
- FILE *fp = fopen(filename, "rb");
- if (fp)
- {
- fseek(fp, 0L, SEEK_END);
- mFileLen = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
-
- mFileBuffer = (char *)malloc(mFileLen + 1);
- int bytesRead;
- bytesRead = fread(mFileBuffer, mFileLen, 1, fp);
-
- fclose(fp);
-
- //
- parseHeader();
- }
-}
-
-// ----------------------------------------------------- //
-bFile::bFile(char *memoryBuffer, int len, const char headerString[7])
- : mOwnsBuffer(false),
- mFileBuffer(0),
- mFileLen(0),
- mVersion(0),
- mDataStart(0),
- mFileDNA(0),
- mMemoryDNA(0),
- mFlags(FD_INVALID)
-{
- for (int i = 0; i < 7; i++)
- {
- m_headerString[i] = headerString[i];
- }
- mFileBuffer = memoryBuffer;
- mFileLen = len;
-
- parseHeader();
-}
-
-// ----------------------------------------------------- //
-bFile::~bFile()
-{
- if (mOwnsBuffer && mFileBuffer)
- {
- free(mFileBuffer);
- mFileBuffer = 0;
- }
-
- delete mMemoryDNA;
- delete mFileDNA;
-}
-
-// ----------------------------------------------------- //
-void bFile::parseHeader()
-{
- if (!mFileLen || !mFileBuffer)
- return;
-
- char *blenderBuf = mFileBuffer;
- char header[B3_SIZEOFBLENDERHEADER + 1];
- memcpy(header, blenderBuf, B3_SIZEOFBLENDERHEADER);
- header[B3_SIZEOFBLENDERHEADER] = '\0';
-
- if (strncmp(header, m_headerString, 6) != 0)
- {
- memcpy(header, m_headerString, B3_SIZEOFBLENDERHEADER);
- return;
- }
-
- if (header[6] == 'd')
- {
- mFlags |= FD_DOUBLE_PRECISION;
- }
-
- char *ver = header + 9;
- mVersion = atoi(ver);
- if (mVersion <= 241)
- {
- //printf("Warning, %d not fully tested : <= 242\n", mVersion);
- }
-
- int littleEndian = 1;
- littleEndian = ((char *)&littleEndian)[0];
-
- // swap ptr sizes...
- if (header[7] == '-')
- {
- mFlags |= FD_FILE_64;
- if (!VOID_IS_8)
- mFlags |= FD_BITS_VARIES;
- }
- else if (VOID_IS_8)
- mFlags |= FD_BITS_VARIES;
-
- // swap endian...
- if (header[8] == 'V')
- {
- if (littleEndian == 1)
- mFlags |= FD_ENDIAN_SWAP;
- }
- else if (littleEndian == 0)
- mFlags |= FD_ENDIAN_SWAP;
-
- mFlags |= FD_OK;
-}
-
-// ----------------------------------------------------- //
-bool bFile::ok()
-{
- return (mFlags & FD_OK) != 0;
-}
-
-// ----------------------------------------------------- //
-void bFile::parseInternal(int verboseMode, char *memDna, int memDnaLength)
-{
- if ((mFlags & FD_OK) == 0)
- return;
-
- char *blenderData = mFileBuffer;
- bChunkInd dna;
- dna.oldPtr = 0;
-
- char *tempBuffer = blenderData;
- for (int i = 0; i < mFileLen; i++)
- {
- // looking for the data's starting position
- // and the start of SDNA decls
-
- if (!mDataStart && strncmp(tempBuffer, "REND", 4) == 0)
- mDataStart = i;
-
- if (strncmp(tempBuffer, "DNA1", 4) == 0)
- {
- // read the DNA1 block and extract SDNA
- if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
- {
- if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) == 0)
- dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
- else
- dna.oldPtr = 0;
- }
- else
- dna.oldPtr = 0;
- }
- // Some Bullet files are missing the DNA1 block
- // In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
- // In Bullet tests its SDNA + NAME
- else if (strncmp(tempBuffer, "SDNANAME", 8) == 0)
- {
- dna.oldPtr = blenderData + i;
- dna.len = mFileLen - i;
-
- // Also no REND block, so exit now.
- if (mVersion == 276) break;
- }
-
- if (mDataStart && dna.oldPtr) break;
- tempBuffer++;
- }
- if (!dna.oldPtr || !dna.len)
- {
- //printf("Failed to find DNA1+SDNA pair\n");
- mFlags &= ~FD_OK;
- return;
- }
-
- mFileDNA = new bDNA();
-
- ///mFileDNA->init will convert part of DNA file endianness to current CPU endianness if necessary
- mFileDNA->init((char *)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP) != 0);
-
- if (mVersion == 276)
- {
- int i;
- for (i = 0; i < mFileDNA->getNumNames(); i++)
- {
- if (strcmp(mFileDNA->getName(i), "int") == 0)
- {
- mFlags |= FD_BROKEN_DNA;
- }
- }
- if ((mFlags & FD_BROKEN_DNA) != 0)
- {
- //printf("warning: fixing some broken DNA version\n");
- }
- }
-
- if (verboseMode & FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS)
- mFileDNA->dumpTypeDefinitions();
-
- mMemoryDNA = new bDNA();
- int littleEndian = 1;
- littleEndian = ((char *)&littleEndian)[0];
-
- mMemoryDNA->init(memDna, memDnaLength, littleEndian == 0);
-
- ///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
- if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
- {
- mFlags |= FD_VERSION_VARIES;
- //printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
- }
-
- // as long as it kept up to date it will be ok!!
- if (mMemoryDNA->lessThan(mFileDNA))
- {
- //printf ("Warning, file DNA is newer than built in.");
- }
-
- mFileDNA->initCmpFlags(mMemoryDNA);
-
- parseData();
-
- resolvePointers(verboseMode);
-
- updateOldPointers();
-}
-
-// ----------------------------------------------------- //
-void bFile::swap(char *head, bChunkInd &dataChunk, bool ignoreEndianFlag)
-{
- char *data = head;
- short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
-
- const char s[] = "SoftBodyMaterialData";
- int szs = sizeof(s);
- if (strncmp((char *)&dataChunk.code, "ARAY", 4) == 0)
- {
- short *oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
- char *oldType = mFileDNA->getType(oldStruct[0]);
- if (strncmp(oldType, s, szs) == 0)
- {
- return;
- }
- }
-
- int len = mFileDNA->getLength(strc[0]);
-
- for (int i = 0; i < dataChunk.nr; i++)
- {
- swapStruct(dataChunk.dna_nr, data, ignoreEndianFlag);
- data += len;
- }
-}
-
-void bFile::swapLen(char *dataPtr)
-{
- const bool VOID_IS_8 = ((sizeof(void *) == 8));
- if (VOID_IS_8)
- {
- if (mFlags & FD_BITS_VARIES)
- {
- bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
- if ((c->code & 0xFFFF) == 0)
- c->code >>= 16;
- B3_SWITCH_INT(c->len);
- B3_SWITCH_INT(c->dna_nr);
- B3_SWITCH_INT(c->nr);
- }
- else
- {
- bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
- if ((c->code & 0xFFFF) == 0)
- c->code >>= 16;
- B3_SWITCH_INT(c->len);
- B3_SWITCH_INT(c->dna_nr);
- B3_SWITCH_INT(c->nr);
- }
- }
- else
- {
- if (mFlags & FD_BITS_VARIES)
- {
- bChunkPtr8 *c = (bChunkPtr8 *)dataPtr;
- if ((c->code & 0xFFFF) == 0)
- c->code >>= 16;
- B3_SWITCH_INT(c->len);
- B3_SWITCH_INT(c->dna_nr);
- B3_SWITCH_INT(c->nr);
- }
- else
- {
- bChunkPtr4 *c = (bChunkPtr4 *)dataPtr;
- if ((c->code & 0xFFFF) == 0)
- c->code >>= 16;
- B3_SWITCH_INT(c->len);
-
- B3_SWITCH_INT(c->dna_nr);
- B3_SWITCH_INT(c->nr);
- }
- }
-}
-
-void bFile::swapDNA(char *ptr)
-{
- bool swap = ((mFlags & FD_ENDIAN_SWAP) != 0);
-
- char *data = &ptr[20];
- // void bDNA::init(char *data, int len, bool swap)
- int *intPtr = 0;
- short *shtPtr = 0;
- char *cp = 0;
- int dataLen = 0;
- //long nr=0;
- intPtr = (int *)data;
-
- /*
- SDNA (4 bytes) (magic number)
- NAME (4 bytes)
- <nr> (4 bytes) amount of names (int)
- <string>
- <string>
- */
-
- if (strncmp(data, "SDNA", 4) == 0)
- {
- // skip ++ NAME
- intPtr++;
- intPtr++;
- }
-
- // Parse names
- if (swap)
- dataLen = ChunkUtils::swapInt(*intPtr);
- else
- dataLen = *intPtr;
-
- *intPtr = ChunkUtils::swapInt(*intPtr);
- intPtr++;
-
- cp = (char *)intPtr;
- int i;
- for (i = 0; i < dataLen; i++)
- {
- while (*cp) cp++;
- cp++;
- }
-
- cp = b3AlignPointer(cp, 4);
-
- /*
- TYPE (4 bytes)
- <nr> amount of types (int)
- <string>
- <string>
- */
-
- intPtr = (int *)cp;
- assert(strncmp(cp, "TYPE", 4) == 0);
- intPtr++;
-
- if (swap)
- dataLen = ChunkUtils::swapInt(*intPtr);
- else
- dataLen = *intPtr;
-
- *intPtr = ChunkUtils::swapInt(*intPtr);
-
- intPtr++;
-
- cp = (char *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- while (*cp) cp++;
- cp++;
- }
-
- cp = b3AlignPointer(cp, 4);
-
- /*
- TLEN (4 bytes)
- <len> (short) the lengths of types
- <len>
- */
-
- // Parse type lens
- intPtr = (int *)cp;
- assert(strncmp(cp, "TLEN", 4) == 0);
- intPtr++;
-
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++, shtPtr++)
- {
- //??????if (swap)
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- }
-
- if (dataLen & 1)
- shtPtr++;
-
- /*
- STRC (4 bytes)
- <nr> amount of structs (int)
- <typenr>
- <nr_of_elems>
- <typenr>
- <namenr>
- <typenr>
- <namenr>
- */
-
- intPtr = (int *)shtPtr;
- cp = (char *)intPtr;
- assert(strncmp(cp, "STRC", 4) == 0);
- intPtr++;
-
- if (swap)
- dataLen = ChunkUtils::swapInt(*intPtr);
- else
- dataLen = *intPtr;
-
- *intPtr = ChunkUtils::swapInt(*intPtr);
-
- intPtr++;
-
- shtPtr = (short *)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- //if (swap)
- {
- int len = shtPtr[1];
-
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
-
- shtPtr += 2;
-
- for (int a = 0; a < len; a++, shtPtr += 2)
- {
- shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
- shtPtr[1] = ChunkUtils::swapShort(shtPtr[1]);
- }
- }
- // else
- // shtPtr+= (2*shtPtr[1])+2;
- }
-}
-
-void bFile::writeFile(const char *fileName)
-{
- FILE *f = fopen(fileName, "wb");
- fwrite(mFileBuffer, 1, mFileLen, f);
- fclose(f);
-}
-
-void bFile::preSwap()
-{
- //const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
- //FD_ENDIAN_SWAP
- //byte 8 determines the endianness of the file, little (v) versus big (V)
- int littleEndian = 1;
- littleEndian = ((char *)&littleEndian)[0];
-
- if (mFileBuffer[8] == 'V')
- {
- mFileBuffer[8] = 'v';
- }
- else
- {
- mFileBuffer[8] = 'V';
- }
-
- mDataStart = 12;
-
- char *dataPtr = mFileBuffer + mDataStart;
-
- bChunkInd dataChunk;
- dataChunk.code = 0;
- bool ignoreEndianFlag = true;
-
- //we always want to swap here
-
- int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
- //dataPtr += ChunkUtils::getOffset(mFlags);
- char *dataPtrHead = 0;
-
- while (1)
- {
- // one behind
- if (dataChunk.code == B3_SDNA || dataChunk.code == B3_DNA1 || dataChunk.code == B3_TYPE || dataChunk.code == B3_TLEN || dataChunk.code == B3_STRC)
- {
- swapDNA(dataPtr);
- break;
- }
- else
- {
- //if (dataChunk.code == DNA1) break;
- dataPtrHead = dataPtr + ChunkUtils::getOffset(mFlags);
-
- swapLen(dataPtr);
- if (dataChunk.dna_nr >= 0)
- {
- swap(dataPtrHead, dataChunk, ignoreEndianFlag);
- }
- else
- {
- //printf("unknown chunk\n");
- }
- }
-
- // next please!
- dataPtr += seek;
-
- seek = getNextBlock(&dataChunk, dataPtr, mFlags);
- if (seek < 0)
- break;
- }
-
- if (mFlags & FD_ENDIAN_SWAP)
- {
- mFlags &= ~FD_ENDIAN_SWAP;
- }
- else
- {
- mFlags |= FD_ENDIAN_SWAP;
- }
-}
-
-// ----------------------------------------------------- //
-char *bFile::readStruct(char *head, bChunkInd &dataChunk)
-{
- bool ignoreEndianFlag = false;
-
- if (mFlags & FD_ENDIAN_SWAP)
- swap(head, dataChunk, ignoreEndianFlag);
-
- if (!mFileDNA->flagEqual(dataChunk.dna_nr))
- {
- // Ouch! need to rebuild the struct
- short *oldStruct, *curStruct;
- char *oldType, *newType;
- int oldLen, curLen, reverseOld;
-
- oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
- oldType = mFileDNA->getType(oldStruct[0]);
-
- oldLen = mFileDNA->getLength(oldStruct[0]);
-
- if ((mFlags & FD_BROKEN_DNA) != 0)
- {
- if ((strcmp(oldType, "b3QuantizedBvhNodeData") == 0) && oldLen == 20)
- {
- return 0;
- }
- if ((strcmp(oldType, "b3ShortIntIndexData") == 0))
- {
- int allocLen = 2;
- char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
- memset(dataAlloc, 0, (dataChunk.nr * allocLen) + 1);
- short *dest = (short *)dataAlloc;
- const short *src = (short *)head;
- for (int i = 0; i < dataChunk.nr; i++)
- {
- dest[i] = src[i];
- if (mFlags & FD_ENDIAN_SWAP)
- {
- B3_SWITCH_SHORT(dest[i]);
- }
- }
- addDataBlock(dataAlloc);
- return dataAlloc;
- }
- }
-
- ///don't try to convert Link block data, just memcpy it. Other data can be converted.
- if (strcmp("Link", oldType) != 0)
- {
- reverseOld = mMemoryDNA->getReverseType(oldType);
-
- if ((reverseOld != -1))
- {
- // make sure it's here
- //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
-
- //
- curStruct = mMemoryDNA->getStruct(reverseOld);
- newType = mMemoryDNA->getType(curStruct[0]);
- curLen = mMemoryDNA->getLength(curStruct[0]);
-
- // make sure it's the same
- assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
-
- // numBlocks * length
-
- int allocLen = (curLen);
- char *dataAlloc = new char[(dataChunk.nr * allocLen) + 1];
- memset(dataAlloc, 0, (dataChunk.nr * allocLen));
-
- // track allocated
- addDataBlock(dataAlloc);
-
- char *cur = dataAlloc;
- char *old = head;
- for (int block = 0; block < dataChunk.nr; block++)
- {
- bool fixupPointers = true;
- parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
- mLibPointers.insert(old, (bStructHandle *)cur);
-
- cur += curLen;
- old += oldLen;
- }
- return dataAlloc;
- }
- }
- else
- {
- //printf("Link found\n");
- }
- }
- else
- {
-//#define DEBUG_EQUAL_STRUCTS
-#ifdef DEBUG_EQUAL_STRUCTS
- short *oldStruct;
- char *oldType;
- oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
- oldType = mFileDNA->getType(oldStruct[0]);
- printf("%s equal structure, just memcpy\n", oldType);
-#endif //
- }
-
- char *dataAlloc = new char[(dataChunk.len) + 1];
- memset(dataAlloc, 0, dataChunk.len + 1);
-
- // track allocated
- addDataBlock(dataAlloc);
-
- memcpy(dataAlloc, head, dataChunk.len);
- return dataAlloc;
-}
-
-// ----------------------------------------------------- //
-void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
-{
- if (old_dna == -1) return;
- if (new_dna == -1) return;
-
- //disable this, because we need to fixup pointers/ListBase
- if (0) //mFileDNA->flagEqual(old_dna))
- {
- short *strc = mFileDNA->getStruct(old_dna);
- int len = mFileDNA->getLength(strc[0]);
-
- memcpy(strcPtr, dtPtr, len);
- return;
- }
-
- // Ok, now build the struct
- char *memType, *memName, *cpc, *cpo;
- short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
- int elementLength, size, revType, old_nr, new_nr, fpLen;
- short firstStructType;
-
- // File to memory lookup
- memoryStruct = mMemoryDNA->getStruct(new_dna);
- fileStruct = mFileDNA->getStruct(old_dna);
- firstStruct = fileStruct;
-
- filePtrOld = fileStruct;
- firstStructType = mMemoryDNA->getStruct(0)[0];
-
- // Get number of elements
- elementLength = memoryStruct[1];
- memoryStruct += 2;
-
- cpc = strcPtr;
- cpo = 0;
- for (int ele = 0; ele < elementLength; ele++, memoryStruct += 2)
- {
- memType = mMemoryDNA->getType(memoryStruct[0]);
- memName = mMemoryDNA->getName(memoryStruct[1]);
-
- size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
- revType = mMemoryDNA->getReverseType(memoryStruct[0]);
-
- if (revType != -1 && memoryStruct[0] >= firstStructType && memName[0] != '*')
- {
- cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
- if (cpo)
- {
- int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
- old_nr = mFileDNA->getReverseType(memType);
- new_nr = revType;
- fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
- if (arrayLen == 1)
- {
- parseStruct(cpc, cpo, old_nr, new_nr, fixupPointers);
- }
- else
- {
- char *tmpCpc = cpc;
- char *tmpCpo = cpo;
-
- for (int i = 0; i < arrayLen; i++)
- {
- parseStruct(tmpCpc, tmpCpo, old_nr, new_nr, fixupPointers);
- tmpCpc += size / arrayLen;
- tmpCpo += fpLen / arrayLen;
- }
- }
- cpc += size;
- cpo += fpLen;
- }
- else
- cpc += size;
- }
- else
- {
- getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr, fixupPointers);
- cpc += size;
- }
- }
-}
-
-// ----------------------------------------------------- //
-static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
-{
-#define b3GetEle(value, current, type, cast, size, ptr) \
- if (strcmp(current, type) == 0) \
- { \
- value = (*(cast *)ptr); \
- ptr += size; \
- }
-
-#define b3SetEle(value, current, type, cast, size, ptr) \
- if (strcmp(current, type) == 0) \
- { \
- (*(cast *)ptr) = (cast)value; \
- ptr += size; \
- }
- double value = 0.0;
-
- for (int i = 0; i < arrayLen; i++)
- {
- b3GetEle(value, old, "char", char, sizeof(char), oldPtr);
- b3SetEle(value, cur, "char", char, sizeof(char), curData);
- b3GetEle(value, old, "short", short, sizeof(short), oldPtr);
- b3SetEle(value, cur, "short", short, sizeof(short), curData);
- b3GetEle(value, old, "ushort", unsigned short, sizeof(unsigned short), oldPtr);
- b3SetEle(value, cur, "ushort", unsigned short, sizeof(unsigned short), curData);
- b3GetEle(value, old, "int", int, sizeof(int), oldPtr);
- b3SetEle(value, cur, "int", int, sizeof(int), curData);
- b3GetEle(value, old, "long", int, sizeof(int), oldPtr);
- b3SetEle(value, cur, "long", int, sizeof(int), curData);
- b3GetEle(value, old, "float", float, sizeof(float), oldPtr);
- b3SetEle(value, cur, "float", float, sizeof(float), curData);
- b3GetEle(value, old, "double", double, sizeof(double), oldPtr);
- b3SetEle(value, cur, "double", double, sizeof(double), curData);
- }
-}
-
-// ----------------------------------------------------- //
-void bFile::swapData(char *data, short type, int arraySize, bool ignoreEndianFlag)
-{
- if (ignoreEndianFlag || (mFlags & FD_ENDIAN_SWAP))
- {
- if (type == 2 || type == 3)
- {
- short *sp = (short *)data;
- for (int i = 0; i < arraySize; i++)
- {
- sp[0] = ChunkUtils::swapShort(sp[0]);
- sp++;
- }
- }
- if (type > 3 && type < 8)
- {
- char c;
- char *cp = data;
- for (int i = 0; i < arraySize; i++)
- {
- c = cp[0];
- cp[0] = cp[3];
- cp[3] = c;
- c = cp[1];
- cp[1] = cp[2];
- cp[2] = c;
- cp += 4;
- }
- }
- }
-}
-
-void bFile::safeSwapPtr(char *dst, const char *src)
-{
- if (!src || !dst)
- return;
-
- int ptrFile = mFileDNA->getPointerSize();
- int ptrMem = mMemoryDNA->getPointerSize();
-
- if (ptrFile == ptrMem)
- {
- memcpy(dst, src, ptrMem);
- }
- else if (ptrMem == 4 && ptrFile == 8)
- {
- b3PointerUid *oldPtr = (b3PointerUid *)src;
- b3PointerUid *newPtr = (b3PointerUid *)dst;
-
- if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
- {
- //Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
- //so it can be used to distinguish between .blend and .bullet
- newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
- }
- else
- {
- //deal with pointers the Blender .blend style way, see
- //readfile.c in the Blender source tree
- b3Long64 longValue = *((b3Long64 *)src);
- //endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
- if (mFlags & FD_ENDIAN_SWAP)
- B3_SWITCH_LONGINT(longValue);
- *((int *)dst) = (int)(longValue >> 3);
- }
- }
- else if (ptrMem == 8 && ptrFile == 4)
- {
- b3PointerUid *oldPtr = (b3PointerUid *)src;
- b3PointerUid *newPtr = (b3PointerUid *)dst;
- if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
- {
- newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
- newPtr->m_uniqueIds[1] = 0;
- }
- else
- {
- *((b3Long64 *)dst) = *((int *)src);
- }
- }
- else
- {
- printf("%d %d\n", ptrFile, ptrMem);
- assert(0 && "Invalid pointer len");
- }
-}
-
-// ----------------------------------------------------- //
-void bFile::getMatchingFileDNA(short *dna_addr, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers)
-{
- // find the matching memory dna data
- // to the file being loaded. Fill the
- // memory with the file data...
-
- int len = dna_addr[1];
- dna_addr += 2;
-
- for (int i = 0; i < len; i++, dna_addr += 2)
- {
- const char *type = mFileDNA->getType(dna_addr[0]);
- const char *name = mFileDNA->getName(dna_addr[1]);
-
- int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
-
- if ((mFlags & FD_BROKEN_DNA) != 0)
- {
- if ((strcmp(type, "short") == 0) && (strcmp(name, "int") == 0))
- {
- eleLen = 0;
- }
- }
-
- if (strcmp(lookupName, name) == 0)
- {
- //int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
- int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
- //assert(arrayLenold == arrayLen);
-
- if (name[0] == '*')
- {
- // cast pointers
- int ptrFile = mFileDNA->getPointerSize();
- int ptrMem = mMemoryDNA->getPointerSize();
- safeSwapPtr(strcData, data);
-
- if (fixupPointers)
- {
- if (arrayLen > 1)
- {
- //void **sarray = (void**)strcData;
- //void **darray = (void**)data;
-
- char *cpc, *cpo;
- cpc = (char *)strcData;
- cpo = (char *)data;
-
- for (int a = 0; a < arrayLen; a++)
- {
- safeSwapPtr(cpc, cpo);
- m_pointerFixupArray.push_back(cpc);
- cpc += ptrMem;
- cpo += ptrFile;
- }
- }
- else
- {
- if (name[1] == '*')
- m_pointerPtrFixupArray.push_back(strcData);
- else
- m_pointerFixupArray.push_back(strcData);
- }
- }
- else
- {
- // printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
- }
- }
-
- else if (strcmp(type, lookupType) == 0)
- memcpy(strcData, data, eleLen);
- else
- getElement(arrayLen, lookupType, type, data, strcData);
-
- // --
- return;
- }
- data += eleLen;
- }
-}
-
-// ----------------------------------------------------- //
-char *bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
-{
- short *old = firstStruct; //mFileDNA->getStruct(old_nr);
- int elementLength = old[1];
- old += 2;
-
- for (int i = 0; i < elementLength; i++, old += 2)
- {
- char *type = mFileDNA->getType(old[0]);
- char *name = mFileDNA->getName(old[1]);
- int len = mFileDNA->getElementSize(old[0], old[1]);
-
- if (strcmp(lookupName, name) == 0)
- {
- if (strcmp(type, lookupType) == 0)
- {
- if (foundPos)
- *foundPos = old;
- return data;
- }
- return 0;
- }
- data += len;
- }
- return 0;
-}
-
-// ----------------------------------------------------- //
-void bFile::swapStruct(int dna_nr, char *data, bool ignoreEndianFlag)
-{
- if (dna_nr == -1) return;
-
- short *strc = mFileDNA->getStruct(dna_nr);
- //short *firstStrc = strc;
-
- int elementLen = strc[1];
- strc += 2;
-
- short first = mFileDNA->getStruct(0)[0];
-
- char *buf = data;
- for (int i = 0; i < elementLen; i++, strc += 2)
- {
- char *type = mFileDNA->getType(strc[0]);
- char *name = mFileDNA->getName(strc[1]);
-
- int size = mFileDNA->getElementSize(strc[0], strc[1]);
- if (strc[0] >= first && name[0] != '*')
- {
- int old_nr = mFileDNA->getReverseType(type);
- int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
- if (arrayLen == 1)
- {
- swapStruct(old_nr, buf, ignoreEndianFlag);
- }
- else
- {
- char *tmpBuf = buf;
- for (int i = 0; i < arrayLen; i++)
- {
- swapStruct(old_nr, tmpBuf, ignoreEndianFlag);
- tmpBuf += size / arrayLen;
- }
- }
- }
- else
- {
- //int arrayLenOld = mFileDNA->getArraySize(name);
- int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
- //assert(arrayLenOld == arrayLen);
- swapData(buf, strc[0], arrayLen, ignoreEndianFlag);
- }
- buf += size;
- }
-}
-
-void bFile::resolvePointersMismatch()
-{
- // printf("resolvePointersStructMismatch\n");
-
- int i;
-
- for (i = 0; i < m_pointerFixupArray.size(); i++)
- {
- char *cur = m_pointerFixupArray.at(i);
- void **ptrptr = (void **)cur;
- void *ptr = *ptrptr;
- ptr = findLibPointer(ptr);
- if (ptr)
- {
- //printf("Fixup pointer!\n");
- *(ptrptr) = ptr;
- }
- else
- {
- // printf("pointer not found: %x\n",cur);
- }
- }
-
- for (i = 0; i < m_pointerPtrFixupArray.size(); i++)
- {
- char *cur = m_pointerPtrFixupArray.at(i);
- void **ptrptr = (void **)cur;
-
- bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
- if (block)
- {
- int ptrMem = mMemoryDNA->getPointerSize();
- int ptrFile = mFileDNA->getPointerSize();
-
- int blockLen = block->len / ptrFile;
-
- void *onptr = findLibPointer(*ptrptr);
- if (onptr)
- {
- char *newPtr = new char[blockLen * ptrMem];
- addDataBlock(newPtr);
- memset(newPtr, 0, blockLen * ptrMem);
-
- void **onarray = (void **)onptr;
- char *oldPtr = (char *)onarray;
-
- int p = 0;
- while (blockLen-- > 0)
- {
- b3PointerUid dp = {{0}};
- safeSwapPtr((char *)dp.m_uniqueIds, oldPtr);
-
- void **tptr = (void **)(newPtr + p * ptrMem);
- *tptr = findLibPointer(dp.m_ptr);
-
- oldPtr += ptrFile;
- ++p;
- }
-
- *ptrptr = newPtr;
- }
- }
- }
-}
-
-///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
-void bFile::resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode)
-{
- bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
-
- short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
- short oldLen = fileDna->getLength(oldStruct[0]);
- //char* structType = fileDna->getType(oldStruct[0]);
-
- char *cur = (char *)findLibPointer(dataChunk.oldPtr);
- for (int block = 0; block < dataChunk.nr; block++)
- {
- resolvePointersStructRecursive(cur, dataChunk.dna_nr, verboseMode, 1);
- cur += oldLen;
- }
-}
-
-int bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, int verboseMode, int recursion)
-{
- bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
-
- char *memType;
- char *memName;
- short firstStructType = fileDna->getStruct(0)[0];
-
- char *elemPtr = strcPtr;
-
- short int *oldStruct = fileDna->getStruct(dna_nr);
-
- int elementLength = oldStruct[1];
- oldStruct += 2;
-
- int totalSize = 0;
-
- for (int ele = 0; ele < elementLength; ele++, oldStruct += 2)
- {
- memType = fileDna->getType(oldStruct[0]);
- memName = fileDna->getName(oldStruct[1]);
-
- int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
- if (memName[0] == '*')
- {
- if (arrayLen > 1)
- {
- void **array = (void **)elemPtr;
- for (int a = 0; a < arrayLen; a++)
- {
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- for (int i = 0; i < recursion; i++)
- {
- printf(" ");
- }
- //skip the *
- printf("<%s type=\"pointer\"> ", &memName[1]);
- printf("%p ", array[a]);
- printf("</%s>\n", &memName[1]);
- }
-
- array[a] = findLibPointer(array[a]);
- }
- }
- else
- {
- void **ptrptr = (void **)elemPtr;
- void *ptr = *ptrptr;
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- for (int i = 0; i < recursion; i++)
- {
- printf(" ");
- }
- printf("<%s type=\"pointer\"> ", &memName[1]);
- printf("%p ", ptr);
- printf("</%s>\n", &memName[1]);
- }
- ptr = findLibPointer(ptr);
-
- if (ptr)
- {
- // printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
- *(ptrptr) = ptr;
- if (memName[1] == '*' && ptrptr && *ptrptr)
- {
- // This will only work if the given **array is continuous
- void **array = (void **)*(ptrptr);
- void *np = array[0];
- int n = 0;
- while (np)
- {
- np = findLibPointer(array[n]);
- if (np) array[n] = np;
- n++;
- }
- }
- }
- else
- {
- // printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
- }
- }
- }
- else
- {
- int revType = fileDna->getReverseType(oldStruct[0]);
- if (oldStruct[0] >= firstStructType) //revType != -1 &&
- {
- char cleanName[MAX_STRLEN];
- getCleanName(memName, cleanName);
-
- int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
- int byteOffset = 0;
-
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- for (int i = 0; i < recursion; i++)
- {
- printf(" ");
- }
-
- if (arrayLen > 1)
- {
- printf("<%s type=\"%s\" count=%d>\n", cleanName, memType, arrayLen);
- }
- else
- {
- printf("<%s type=\"%s\">\n", cleanName, memType);
- }
- }
-
- for (int i = 0; i < arrayLen; i++)
- {
- byteOffset += resolvePointersStructRecursive(elemPtr + byteOffset, revType, verboseMode, recursion + 1);
- }
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- for (int i = 0; i < recursion; i++)
- {
- printf(" ");
- }
- printf("</%s>\n", cleanName);
- }
- }
- else
- {
- //export a simple type
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- if (arrayLen > MAX_ARRAY_LENGTH)
- {
- printf("too long\n");
- }
- else
- {
- //printf("%s %s\n",memType,memName);
-
- bool isIntegerType = (strcmp(memType, "char") == 0) || (strcmp(memType, "int") == 0) || (strcmp(memType, "short") == 0);
-
- if (isIntegerType)
- {
- const char *newtype = "int";
- int dbarray[MAX_ARRAY_LENGTH];
- int *dbPtr = 0;
- char *tmp = elemPtr;
- dbPtr = &dbarray[0];
- if (dbPtr)
- {
- char cleanName[MAX_STRLEN];
- getCleanName(memName, cleanName);
-
- int i;
- getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
- for (i = 0; i < recursion; i++)
- printf(" ");
- if (arrayLen == 1)
- printf("<%s type=\"%s\">", cleanName, memType);
- else
- printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
- for (i = 0; i < arrayLen; i++)
- printf(" %d ", dbPtr[i]);
- printf("</%s>\n", cleanName);
- }
- }
- else
- {
- const char *newtype = "double";
- double dbarray[MAX_ARRAY_LENGTH];
- double *dbPtr = 0;
- char *tmp = elemPtr;
- dbPtr = &dbarray[0];
- if (dbPtr)
- {
- int i;
- getElement(arrayLen, newtype, memType, tmp, (char *)dbPtr);
- for (i = 0; i < recursion; i++)
- printf(" ");
- char cleanName[MAX_STRLEN];
- getCleanName(memName, cleanName);
-
- if (arrayLen == 1)
- {
- printf("<%s type=\"%s\">", memName, memType);
- }
- else
- {
- printf("<%s type=\"%s\" count=%d>", cleanName, memType, arrayLen);
- }
- for (i = 0; i < arrayLen; i++)
- printf(" %f ", dbPtr[i]);
- printf("</%s>\n", cleanName);
- }
- }
- }
- }
- }
- }
-
- int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
- totalSize += size;
- elemPtr += size;
- }
-
- return totalSize;
-}
-
-///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
-void bFile::resolvePointers(int verboseMode)
-{
- bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
-
- //char *dataPtr = mFileBuffer+mDataStart;
-
- if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
- {
- resolvePointersMismatch();
- }
-
- {
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
- int numitems = m_chunks.size();
- printf("<bullet_physics version=%d itemcount = %d>\n", b3GetVersion(), numitems);
- }
- for (int i = 0; i < m_chunks.size(); i++)
- {
- const bChunkInd &dataChunk = m_chunks.at(i);
-
- if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
- {
- //dataChunk.len
- short int *oldStruct = fileDna->getStruct(dataChunk.dna_nr);
- char *oldType = fileDna->getType(oldStruct[0]);
-
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- printf(" <%s pointer=%p>\n", oldType, dataChunk.oldPtr);
-
- resolvePointersChunk(dataChunk, verboseMode);
-
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- printf(" </%s>\n", oldType);
- }
- else
- {
- //printf("skipping mStruct\n");
- }
- }
- if (verboseMode & FD_VERBOSE_EXPORT_XML)
- {
- printf("</bullet_physics>\n");
- }
- }
-}
-
-// ----------------------------------------------------- //
-void *bFile::findLibPointer(void *ptr)
-{
- bStructHandle **ptrptr = getLibPointers().find(ptr);
- if (ptrptr)
- return *ptrptr;
- return 0;
-}
-
-void bFile::updateOldPointers()
-{
- int i;
-
- for (i = 0; i < m_chunks.size(); i++)
- {
- bChunkInd &dataChunk = m_chunks[i];
- dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
- }
-}
-void bFile::dumpChunks(bParse::bDNA *dna)
-{
- int i;
-
- for (i = 0; i < m_chunks.size(); i++)
- {
- bChunkInd &dataChunk = m_chunks[i];
- char *codeptr = (char *)&dataChunk.code;
- char codestr[5] = {codeptr[0], codeptr[1], codeptr[2], codeptr[3], 0};
-
- short *newStruct = dna->getStruct(dataChunk.dna_nr);
- char *typeName = dna->getType(newStruct[0]);
- printf("%3d: %s ", i, typeName);
-
- printf("code=%s ", codestr);
-
- printf("ptr=%p ", dataChunk.oldPtr);
- printf("len=%d ", dataChunk.len);
- printf("nr=%d ", dataChunk.nr);
- if (dataChunk.nr != 1)
- {
- printf("not 1\n");
- }
- printf("\n");
- }
-
-#if 0
- IDFinderData ifd;
- ifd.success = 0;
- ifd.IDname = NULL;
- ifd.just_print_it = 1;
- for (i=0; i<bf->m_blocks.size(); ++i)
- {
- BlendBlock* bb = bf->m_blocks[i];
- printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]", bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
- block_ID_finder(bb, bf, &ifd);
- printf("\n");
- }
-#endif
-}
-
-void bFile::writeChunks(FILE *fp, bool fixupPointers)
-{
- bParse::bDNA *fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
-
- for (int i = 0; i < m_chunks.size(); i++)
- {
- bChunkInd &dataChunk = m_chunks.at(i);
-
- // Ouch! need to rebuild the struct
- short *oldStruct, *curStruct;
- char *oldType, *newType;
- int oldLen, curLen, reverseOld;
-
- oldStruct = fileDna->getStruct(dataChunk.dna_nr);
- oldType = fileDna->getType(oldStruct[0]);
- oldLen = fileDna->getLength(oldStruct[0]);
- ///don't try to convert Link block data, just memcpy it. Other data can be converted.
- reverseOld = mMemoryDNA->getReverseType(oldType);
-
- if ((reverseOld != -1))
- {
- // make sure it's here
- //assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
- //
- curStruct = mMemoryDNA->getStruct(reverseOld);
- newType = mMemoryDNA->getType(curStruct[0]);
- // make sure it's the same
- assert((strcmp(oldType, newType) == 0) && "internal error, struct mismatch!");
-
- curLen = mMemoryDNA->getLength(curStruct[0]);
- dataChunk.dna_nr = reverseOld;
- if (strcmp("Link", oldType) != 0)
- {
- dataChunk.len = curLen * dataChunk.nr;
- }
- else
- {
- // printf("keep length of link = %d\n",dataChunk.len);
- }
-
- //write the structure header
- fwrite(&dataChunk, sizeof(bChunkInd), 1, fp);
-
- short int *curStruct1;
- curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
- assert(curStruct1 == curStruct);
-
- char *cur = fixupPointers ? (char *)findLibPointer(dataChunk.oldPtr) : (char *)dataChunk.oldPtr;
-
- //write the actual contents of the structure(s)
- fwrite(cur, dataChunk.len, 1, fp);
- }
- else
- {
- printf("serious error, struct mismatch: don't write\n");
- }
- }
-}
-
-// ----------------------------------------------------- //
-int bFile::getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags)
-{
- bool swap = false;
- bool varies = false;
-
- if (flags & FD_ENDIAN_SWAP)
- swap = true;
- if (flags & FD_BITS_VARIES)
- varies = true;
-
- if (VOID_IS_8)
- {
- if (varies)
- {
- bChunkPtr4 head;
- memcpy(&head, dataPtr, sizeof(bChunkPtr4));
-
- bChunkPtr8 chunk;
-
- chunk.code = head.code;
- chunk.len = head.len;
- chunk.m_uniqueInts[0] = head.m_uniqueInt;
- chunk.m_uniqueInts[1] = 0;
- chunk.dna_nr = head.dna_nr;
- chunk.nr = head.nr;
-
- if (swap)
- {
- if ((chunk.code & 0xFFFF) == 0)
- chunk.code >>= 16;
-
- B3_SWITCH_INT(chunk.len);
- B3_SWITCH_INT(chunk.dna_nr);
- B3_SWITCH_INT(chunk.nr);
- }
-
- memcpy(dataChunk, &chunk, sizeof(bChunkInd));
- }
- else
- {
- bChunkPtr8 c;
- memcpy(&c, dataPtr, sizeof(bChunkPtr8));
-
- if (swap)
- {
- if ((c.code & 0xFFFF) == 0)
- c.code >>= 16;
-
- B3_SWITCH_INT(c.len);
- B3_SWITCH_INT(c.dna_nr);
- B3_SWITCH_INT(c.nr);
- }
-
- memcpy(dataChunk, &c, sizeof(bChunkInd));
- }
- }
- else
- {
- if (varies)
- {
- bChunkPtr8 head;
- memcpy(&head, dataPtr, sizeof(bChunkPtr8));
-
- bChunkPtr4 chunk;
- chunk.code = head.code;
- chunk.len = head.len;
-
- if (head.m_uniqueInts[0] == head.m_uniqueInts[1])
- {
- chunk.m_uniqueInt = head.m_uniqueInts[0];
- }
- else
- {
- b3Long64 oldPtr = 0;
- memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
- if (swap)
- B3_SWITCH_LONGINT(oldPtr);
- chunk.m_uniqueInt = (int)(oldPtr >> 3);
- }
-
- chunk.dna_nr = head.dna_nr;
- chunk.nr = head.nr;
-
- if (swap)
- {
- if ((chunk.code & 0xFFFF) == 0)
- chunk.code >>= 16;
-
- B3_SWITCH_INT(chunk.len);
- B3_SWITCH_INT(chunk.dna_nr);
- B3_SWITCH_INT(chunk.nr);
- }
-
- memcpy(dataChunk, &chunk, sizeof(bChunkInd));
- }
- else
- {
- bChunkPtr4 c;
- memcpy(&c, dataPtr, sizeof(bChunkPtr4));
-
- if (swap)
- {
- if ((c.code & 0xFFFF) == 0)
- c.code >>= 16;
-
- B3_SWITCH_INT(c.len);
- B3_SWITCH_INT(c.dna_nr);
- B3_SWITCH_INT(c.nr);
- }
- memcpy(dataChunk, &c, sizeof(bChunkInd));
- }
- }
-
- if (dataChunk->len < 0)
- return -1;
-
-#if 0
- print ("----------");
- print (dataChunk->code);
- print (dataChunk->len);
- print (dataChunk->old);
- print (dataChunk->dna_nr);
- print (dataChunk->nr);
-#endif
- return (dataChunk->len + ChunkUtils::getOffset(flags));
-}
-
-//eof
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h
deleted file mode 100644
index bda229cfbd..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3File.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-bParse
-Copyright (c) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef __BFILE_H__
-#define __BFILE_H__
-
-#include "b3Common.h"
-#include "b3Chunk.h"
-#include <stdio.h>
-
-namespace bParse
-{
-// ----------------------------------------------------- //
-enum bFileFlags
-{
- FD_INVALID = 0,
- FD_OK = 1,
- FD_VOID_IS_8 = 2,
- FD_ENDIAN_SWAP = 4,
- FD_FILE_64 = 8,
- FD_BITS_VARIES = 16,
- FD_VERSION_VARIES = 32,
- FD_DOUBLE_PRECISION = 64,
- FD_BROKEN_DNA = 128
-};
-
-enum bFileVerboseMode
-{
- FD_VERBOSE_EXPORT_XML = 1,
- FD_VERBOSE_DUMP_DNA_TYPE_DEFINITIONS = 2,
- FD_VERBOSE_DUMP_CHUNKS = 4,
- FD_VERBOSE_DUMP_FILE_INFO = 8,
-};
-// ----------------------------------------------------- //
-class bFile
-{
-protected:
- char m_headerString[7];
-
- bool mOwnsBuffer;
- char *mFileBuffer;
- int mFileLen;
- int mVersion;
-
- bPtrMap mLibPointers;
-
- int mDataStart;
- bDNA *mFileDNA;
- bDNA *mMemoryDNA;
-
- b3AlignedObjectArray<char *> m_pointerFixupArray;
- b3AlignedObjectArray<char *> m_pointerPtrFixupArray;
-
- b3AlignedObjectArray<bChunkInd> m_chunks;
- b3HashMap<b3HashPtr, bChunkInd> m_chunkPtrPtrMap;
-
- //
-
- bPtrMap mDataPointers;
-
- int mFlags;
-
- // ////////////////////////////////////////////////////////////////////////////
-
- // buffer offset util
- int getNextBlock(bChunkInd *dataChunk, const char *dataPtr, const int flags);
- void safeSwapPtr(char *dst, const char *src);
-
- virtual void parseHeader();
-
- virtual void parseData() = 0;
-
- void resolvePointersMismatch();
- void resolvePointersChunk(const bChunkInd &dataChunk, int verboseMode);
-
- int resolvePointersStructRecursive(char *strcPtr, int old_dna, int verboseMode, int recursion);
- //void swapPtr(char *dst, char *src);
-
- void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
- void getMatchingFileDNA(short *old, const char *lookupName, const char *lookupType, char *strcData, char *data, bool fixupPointers);
- char *getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
-
- void swap(char *head, class bChunkInd &ch, bool ignoreEndianFlag);
- void swapData(char *data, short type, int arraySize, bool ignoreEndianFlag);
- void swapStruct(int dna_nr, char *data, bool ignoreEndianFlag);
- void swapLen(char *dataPtr);
- void swapDNA(char *ptr);
-
- char *readStruct(char *head, class bChunkInd &chunk);
- char *getAsString(int code);
-
- void parseInternal(int verboseMode, char *memDna, int memDnaLength);
-
-public:
- bFile(const char *filename, const char headerString[7]);
-
- //todo: make memoryBuffer const char
- //bFile( const char *memoryBuffer, int len);
- bFile(char *memoryBuffer, int len, const char headerString[7]);
- virtual ~bFile();
-
- bDNA *getFileDNA()
- {
- return mFileDNA;
- }
-
- virtual void addDataBlock(char *dataBlock) = 0;
-
- int getFlags() const
- {
- return mFlags;
- }
-
- bPtrMap &getLibPointers()
- {
- return mLibPointers;
- }
-
- void *findLibPointer(void *ptr);
-
- bool ok();
-
- virtual void parse(int verboseMode) = 0;
-
- virtual int write(const char *fileName, bool fixupPointers = false) = 0;
-
- virtual void writeChunks(FILE *fp, bool fixupPointers);
-
- virtual void writeDNA(FILE *fp) = 0;
-
- void updateOldPointers();
- void resolvePointers(int verboseMode);
-
- void dumpChunks(bDNA *dna);
-
- int getVersion() const
- {
- return mVersion;
- }
- //pre-swap the endianness, so that data loaded on a target with different endianness doesn't need to be swapped
- void preSwap();
- void writeFile(const char *fileName);
-};
-} // namespace bParse
-
-#endif //__BFILE_H__
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
deleted file mode 100644
index ea4a8e2007..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.cpp
+++ /dev/null
@@ -1,18062 +0,0 @@
-char b3s_bulletDNAstr[] = {
- char(83),
- char(68),
- char(78),
- char(65),
- char(78),
- char(65),
- char(77),
- char(69),
- char(63),
- char(1),
- char(0),
- char(0),
- char(109),
- char(95),
- char(115),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(97),
- char(112),
- char(97),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(42),
- char(109),
- char(95),
- char(100),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(42),
- char(102),
- char(105),
- char(114),
- char(115),
- char(116),
- char(0),
- char(42),
- char(108),
- char(97),
- char(115),
- char(116),
- char(0),
- char(109),
- char(95),
- char(102),
- char(108),
- char(111),
- char(97),
- char(116),
- char(115),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(108),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(98),
- char(97),
- char(115),
- char(105),
- char(115),
- char(0),
- char(109),
- char(95),
- char(111),
- char(114),
- char(105),
- char(103),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(111),
- char(116),
- char(78),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(97),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(79),
- char(114),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(79),
- char(114),
- char(103),
- char(0),
- char(109),
- char(95),
- char(101),
- char(115),
- char(99),
- char(97),
- char(112),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(80),
- char(97),
- char(114),
- char(116),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(115),
- char(99),
- char(97),
- char(112),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(79),
- char(114),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(117),
- char(114),
- char(78),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(76),
- char(101),
- char(97),
- char(102),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(84),
- char(114),
- char(101),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(97),
- char(118),
- char(101),
- char(114),
- char(115),
- char(97),
- char(108),
- char(77),
- char(111),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(83),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(72),
- char(101),
- char(97),
- char(100),
- char(101),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(104),
- char(97),
- char(112),
- char(101),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(83),
- char(99),
- char(97),
- char(108),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(101),
- char(78),
- char(111),
- char(114),
- char(109),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(97),
- char(110),
- char(116),
- char(0),
- char(109),
- char(95),
- char(105),
- char(109),
- char(112),
- char(108),
- char(105),
- char(99),
- char(105),
- char(116),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(105),
- char(109),
- char(101),
- char(110),
- char(115),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(77),
- char(97),
- char(114),
- char(103),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(0),
- char(109),
- char(95),
- char(114),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(42),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(115),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(102),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(100),
- char(0),
- char(42),
- char(109),
- char(95),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(50),
- char(0),
- char(42),
- char(109),
- char(95),
- char(51),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(49),
- char(54),
- char(0),
- char(42),
- char(109),
- char(95),
- char(51),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(56),
- char(0),
- char(42),
- char(109),
- char(95),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(49),
- char(54),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(86),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(115),
- char(99),
- char(97),
- char(108),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(109),
- char(101),
- char(115),
- char(104),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(102),
- char(97),
- char(99),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(66),
- char(118),
- char(104),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(66),
- char(118),
- char(104),
- char(0),
- char(42),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(77),
- char(97),
- char(112),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(51),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(109),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(77),
- char(97),
- char(114),
- char(103),
- char(105),
- char(110),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(117),
- char(112),
- char(65),
- char(120),
- char(105),
- char(115),
- char(0),
- char(109),
- char(95),
- char(102),
- char(108),
- char(97),
- char(103),
- char(115),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(48),
- char(86),
- char(49),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(49),
- char(86),
- char(50),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(50),
- char(86),
- char(48),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(104),
- char(84),
- char(97),
- char(98),
- char(108),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(101),
- char(120),
- char(116),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(107),
- char(101),
- char(121),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(69),
- char(112),
- char(115),
- char(105),
- char(108),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(97),
- char(114),
- char(69),
- char(112),
- char(115),
- char(105),
- char(108),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(101),
- char(113),
- char(117),
- char(97),
- char(108),
- char(86),
- char(101),
- char(114),
- char(116),
- char(101),
- char(120),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(68),
- char(105),
- char(115),
- char(116),
- char(97),
- char(110),
- char(99),
- char(101),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(122),
- char(101),
- char(114),
- char(111),
- char(65),
- char(114),
- char(101),
- char(97),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(101),
- char(120),
- char(116),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(104),
- char(84),
- char(97),
- char(98),
- char(108),
- char(101),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(86),
- char(97),
- char(108),
- char(117),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(75),
- char(101),
- char(121),
- char(115),
- char(0),
- char(109),
- char(95),
- char(103),
- char(105),
- char(109),
- char(112),
- char(97),
- char(99),
- char(116),
- char(83),
- char(117),
- char(98),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(117),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(117),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(85),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(51),
- char(91),
- char(52),
- char(93),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(114),
- char(111),
- char(97),
- char(100),
- char(112),
- char(104),
- char(97),
- char(115),
- char(101),
- char(72),
- char(97),
- char(110),
- char(100),
- char(108),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(111),
- char(111),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(119),
- char(111),
- char(114),
- char(108),
- char(100),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(105),
- char(115),
- char(111),
- char(116),
- char(114),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(80),
- char(114),
- char(111),
- char(99),
- char(101),
- char(115),
- char(115),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(100),
- char(101),
- char(97),
- char(99),
- char(116),
- char(105),
- char(118),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(105),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(102),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(108),
- char(108),
- char(105),
- char(110),
- char(103),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(105),
- char(116),
- char(117),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(104),
- char(105),
- char(116),
- char(70),
- char(114),
- char(97),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(99),
- char(100),
- char(83),
- char(119),
- char(101),
- char(112),
- char(116),
- char(83),
- char(112),
- char(104),
- char(101),
- char(114),
- char(101),
- char(82),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(99),
- char(100),
- char(77),
- char(111),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(65),
- char(110),
- char(105),
- char(115),
- char(111),
- char(116),
- char(114),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(70),
- char(108),
- char(97),
- char(103),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(115),
- char(108),
- char(97),
- char(110),
- char(100),
- char(84),
- char(97),
- char(103),
- char(49),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(109),
- char(112),
- char(97),
- char(110),
- char(105),
- char(111),
- char(110),
- char(73),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(99),
- char(116),
- char(105),
- char(118),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(83),
- char(116),
- char(97),
- char(116),
- char(101),
- char(49),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(101),
- char(99),
- char(107),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(100),
- char(101),
- char(87),
- char(105),
- char(116),
- char(104),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(0),
- char(109),
- char(95),
- char(103),
- char(114),
- char(97),
- char(118),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(73),
- char(110),
- char(101),
- char(114),
- char(116),
- char(105),
- char(97),
- char(84),
- char(101),
- char(110),
- char(115),
- char(111),
- char(114),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(103),
- char(114),
- char(97),
- char(118),
- char(105),
- char(116),
- char(121),
- char(95),
- char(97),
- char(99),
- char(99),
- char(101),
- char(108),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(73),
- char(110),
- char(101),
- char(114),
- char(116),
- char(105),
- char(97),
- char(76),
- char(111),
- char(99),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(116),
- char(111),
- char(116),
- char(97),
- char(108),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(116),
- char(111),
- char(116),
- char(97),
- char(108),
- char(84),
- char(111),
- char(114),
- char(113),
- char(117),
- char(101),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(101),
- char(114),
- char(115),
- char(101),
- char(77),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(83),
- char(113),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(83),
- char(113),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(108),
- char(101),
- char(101),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(83),
- char(108),
- char(101),
- char(101),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(82),
- char(111),
- char(119),
- char(115),
- char(0),
- char(110),
- char(117),
- char(98),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(98),
- char(65),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(98),
- char(66),
- char(0),
- char(109),
- char(95),
- char(111),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(73),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(101),
- char(101),
- char(100),
- char(115),
- char(70),
- char(101),
- char(101),
- char(100),
- char(98),
- char(97),
- char(99),
- char(107),
- char(0),
- char(109),
- char(95),
- char(97),
- char(112),
- char(112),
- char(108),
- char(105),
- char(101),
- char(100),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(98),
- char(103),
- char(68),
- char(114),
- char(97),
- char(119),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(105),
- char(115),
- char(97),
- char(98),
- char(108),
- char(101),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(115),
- char(66),
- char(101),
- char(116),
- char(119),
- char(101),
- char(101),
- char(110),
- char(76),
- char(105),
- char(110),
- char(107),
- char(101),
- char(100),
- char(66),
- char(111),
- char(100),
- char(105),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(111),
- char(118),
- char(101),
- char(114),
- char(114),
- char(105),
- char(100),
- char(101),
- char(78),
- char(117),
- char(109),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(114),
- char(101),
- char(97),
- char(107),
- char(105),
- char(110),
- char(103),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(105),
- char(115),
- char(69),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(100),
- char(0),
- char(109),
- char(95),
- char(116),
- char(121),
- char(112),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(112),
- char(105),
- char(118),
- char(111),
- char(116),
- char(73),
- char(110),
- char(65),
- char(0),
- char(109),
- char(95),
- char(112),
- char(105),
- char(118),
- char(111),
- char(116),
- char(73),
- char(110),
- char(66),
- char(0),
- char(109),
- char(95),
- char(114),
- char(98),
- char(65),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(98),
- char(66),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(82),
- char(101),
- char(102),
- char(101),
- char(114),
- char(101),
- char(110),
- char(99),
- char(101),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(65),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(79),
- char(110),
- char(108),
- char(121),
- char(0),
- char(109),
- char(95),
- char(101),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(77),
- char(111),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(109),
- char(111),
- char(116),
- char(111),
- char(114),
- char(84),
- char(97),
- char(114),
- char(103),
- char(101),
- char(116),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(77),
- char(111),
- char(116),
- char(111),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(117),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(109),
- char(105),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(105),
- char(97),
- char(115),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(108),
- char(97),
- char(120),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(115),
- char(119),
- char(105),
- char(110),
- char(103),
- char(83),
- char(112),
- char(97),
- char(110),
- char(49),
- char(0),
- char(109),
- char(95),
- char(115),
- char(119),
- char(105),
- char(110),
- char(103),
- char(83),
- char(112),
- char(97),
- char(110),
- char(50),
- char(0),
- char(109),
- char(95),
- char(116),
- char(119),
- char(105),
- char(115),
- char(116),
- char(83),
- char(112),
- char(97),
- char(110),
- char(0),
- char(109),
- char(95),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(85),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(76),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(85),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(76),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(82),
- char(101),
- char(102),
- char(101),
- char(114),
- char(101),
- char(110),
- char(99),
- char(101),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(65),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(79),
- char(102),
- char(102),
- char(115),
- char(101),
- char(116),
- char(70),
- char(111),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(54),
- char(100),
- char(111),
- char(102),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(69),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(100),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(113),
- char(117),
- char(105),
- char(108),
- char(105),
- char(98),
- char(114),
- char(105),
- char(117),
- char(109),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(116),
- char(97),
- char(117),
- char(0),
- char(109),
- char(95),
- char(116),
- char(105),
- char(109),
- char(101),
- char(83),
- char(116),
- char(101),
- char(112),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(69),
- char(114),
- char(114),
- char(111),
- char(114),
- char(82),
- char(101),
- char(100),
- char(117),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(101),
- char(114),
- char(112),
- char(0),
- char(109),
- char(95),
- char(101),
- char(114),
- char(112),
- char(50),
- char(0),
- char(109),
- char(95),
- char(103),
- char(108),
- char(111),
- char(98),
- char(97),
- char(108),
- char(67),
- char(102),
- char(109),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(80),
- char(101),
- char(110),
- char(101),
- char(116),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(84),
- char(117),
- char(114),
- char(110),
- char(69),
- char(114),
- char(112),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(108),
- char(111),
- char(112),
- char(0),
- char(109),
- char(95),
- char(119),
- char(97),
- char(114),
- char(109),
- char(115),
- char(116),
- char(97),
- char(114),
- char(116),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(71),
- char(121),
- char(114),
- char(111),
- char(115),
- char(99),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(105),
- char(110),
- char(103),
- char(108),
- char(101),
- char(65),
- char(120),
- char(105),
- char(115),
- char(82),
- char(111),
- char(108),
- char(108),
- char(105),
- char(110),
- char(103),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(77),
- char(111),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(105),
- char(110),
- char(103),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(82),
- char(101),
- char(115),
- char(116),
- char(105),
- char(116),
- char(117),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(109),
- char(105),
- char(110),
- char(105),
- char(109),
- char(117),
- char(109),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(66),
- char(97),
- char(116),
- char(99),
- char(104),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(114),
- char(101),
- char(118),
- char(105),
- char(111),
- char(117),
- char(115),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(118),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(99),
- char(99),
- char(117),
- char(109),
- char(117),
- char(108),
- char(97),
- char(116),
- char(101),
- char(100),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(114),
- char(109),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(97),
- char(114),
- char(101),
- char(97),
- char(0),
- char(109),
- char(95),
- char(97),
- char(116),
- char(116),
- char(97),
- char(99),
- char(104),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(76),
- char(101),
- char(110),
- char(103),
- char(116),
- char(104),
- char(0),
- char(109),
- char(95),
- char(98),
- char(98),
- char(101),
- char(110),
- char(100),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(65),
- char(114),
- char(101),
- char(97),
- char(0),
- char(109),
- char(95),
- char(99),
- char(48),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(86),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(49),
- char(0),
- char(109),
- char(95),
- char(99),
- char(50),
- char(0),
- char(109),
- char(95),
- char(99),
- char(48),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(97),
- char(101),
- char(114),
- char(111),
- char(77),
- char(111),
- char(100),
- char(101),
- char(108),
- char(0),
- char(109),
- char(95),
- char(98),
- char(97),
- char(117),
- char(109),
- char(103),
- char(97),
- char(114),
- char(116),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(114),
- char(97),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(102),
- char(116),
- char(0),
- char(109),
- char(95),
- char(112),
- char(114),
- char(101),
- char(115),
- char(115),
- char(117),
- char(114),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(101),
- char(77),
- char(97),
- char(116),
- char(99),
- char(104),
- char(0),
- char(109),
- char(95),
- char(114),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(107),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(75),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(75),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(86),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(116),
- char(105),
- char(109),
- char(101),
- char(83),
- char(99),
- char(97),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(100),
- char(114),
- char(105),
- char(102),
- char(116),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(97),
- char(113),
- char(113),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(109),
- char(0),
- char(42),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(119),
- char(101),
- char(105),
- char(103),
- char(104),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(87),
- char(101),
- char(105),
- char(103),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(98),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(120),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(105),
- char(105),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(119),
- char(105),
- char(0),
- char(109),
- char(95),
- char(118),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(100),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(108),
- char(118),
- char(0),
- char(109),
- char(95),
- char(97),
- char(118),
- char(0),
- char(42),
- char(109),
- char(95),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(114),
- char(101),
- char(102),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(115),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(82),
- char(101),
- char(102),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(97),
- char(115),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(100),
- char(109),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(109),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(118),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(100),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(99),
- char(104),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(83),
- char(101),
- char(108),
- char(102),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(101),
- char(108),
- char(102),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(97),
- char(105),
- char(110),
- char(115),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(65),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(66),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(102),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(99),
- char(102),
- char(109),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(100),
- char(101),
- char(108),
- char(101),
- char(116),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(65),
- char(116),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(66),
- char(116),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(106),
- char(111),
- char(105),
- char(110),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(101),
- char(0),
- char(42),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(107),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(102),
- char(97),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(116),
- char(101),
- char(116),
- char(114),
- char(97),
- char(104),
- char(101),
- char(100),
- char(114),
- char(97),
- char(0),
- char(42),
- char(109),
- char(95),
- char(97),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(106),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(76),
- char(105),
- char(110),
- char(107),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(70),
- char(97),
- char(99),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(84),
- char(101),
- char(116),
- char(114),
- char(97),
- char(104),
- char(101),
- char(100),
- char(114),
- char(97),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(74),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(102),
- char(105),
- char(103),
- char(0),
- char(84),
- char(89),
- char(80),
- char(69),
- char(76),
- char(0),
- char(0),
- char(0),
- char(99),
- char(104),
- char(97),
- char(114),
- char(0),
- char(117),
- char(99),
- char(104),
- char(97),
- char(114),
- char(0),
- char(115),
- char(104),
- char(111),
- char(114),
- char(116),
- char(0),
- char(117),
- char(115),
- char(104),
- char(111),
- char(114),
- char(116),
- char(0),
- char(105),
- char(110),
- char(116),
- char(0),
- char(108),
- char(111),
- char(110),
- char(103),
- char(0),
- char(117),
- char(108),
- char(111),
- char(110),
- char(103),
- char(0),
- char(102),
- char(108),
- char(111),
- char(97),
- char(116),
- char(0),
- char(100),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(0),
- char(118),
- char(111),
- char(105),
- char(100),
- char(0),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(0),
- char(98),
- char(116),
- char(80),
- char(104),
- char(121),
- char(115),
- char(105),
- char(99),
- char(115),
- char(83),
- char(121),
- char(115),
- char(116),
- char(101),
- char(109),
- char(0),
- char(76),
- char(105),
- char(115),
- char(116),
- char(66),
- char(97),
- char(115),
- char(101),
- char(0),
- char(98),
- char(116),
- char(86),
- char(101),
- char(99),
- char(116),
- char(111),
- char(114),
- char(51),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(86),
- char(101),
- char(99),
- char(116),
- char(111),
- char(114),
- char(51),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(97),
- char(116),
- char(114),
- char(105),
- char(120),
- char(51),
- char(120),
- char(51),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(97),
- char(116),
- char(114),
- char(105),
- char(120),
- char(51),
- char(120),
- char(51),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(66),
- char(118),
- char(104),
- char(83),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(79),
- char(112),
- char(116),
- char(105),
- char(109),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(79),
- char(112),
- char(116),
- char(105),
- char(109),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(116),
- char(97),
- char(116),
- char(105),
- char(99),
- char(80),
- char(108),
- char(97),
- char(110),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(110),
- char(100),
- char(82),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(98),
- char(116),
- char(77),
- char(117),
- char(108),
- char(116),
- char(105),
- char(83),
- char(112),
- char(104),
- char(101),
- char(114),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(104),
- char(111),
- char(114),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(104),
- char(111),
- char(114),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(84),
- char(114),
- char(105),
- char(112),
- char(108),
- char(101),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(104),
- char(97),
- char(114),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(84),
- char(114),
- char(105),
- char(112),
- char(108),
- char(101),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(116),
- char(114),
- char(105),
- char(100),
- char(105),
- char(110),
- char(103),
- char(77),
- char(101),
- char(115),
- char(104),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(102),
- char(97),
- char(99),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(77),
- char(97),
- char(112),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(109),
- char(112),
- char(111),
- char(117),
- char(110),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(67),
- char(104),
- char(105),
- char(108),
- char(100),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(109),
- char(112),
- char(111),
- char(117),
- char(110),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(121),
- char(108),
- char(105),
- char(110),
- char(100),
- char(101),
- char(114),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(97),
- char(112),
- char(115),
- char(117),
- char(108),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(73),
- char(109),
- char(112),
- char(97),
- char(99),
- char(116),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(72),
- char(117),
- char(108),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(68),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(115),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(68),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(115),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(73),
- char(110),
- char(102),
- char(111),
- char(49),
- char(0),
- char(98),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(50),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(50),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(72),
- char(105),
- char(110),
- char(103),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(72),
- char(105),
- char(110),
- char(103),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(101),
- char(84),
- char(119),
- char(105),
- char(115),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(101),
- char(110),
- char(101),
- char(114),
- char(105),
- char(99),
- char(54),
- char(68),
- char(111),
- char(102),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(101),
- char(110),
- char(101),
- char(114),
- char(105),
- char(99),
- char(54),
- char(68),
- char(111),
- char(102),
- char(83),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(108),
- char(105),
- char(100),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(77),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(76),
- char(105),
- char(110),
- char(107),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(97),
- char(99),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(84),
- char(101),
- char(116),
- char(114),
- char(97),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(67),
- char(111),
- char(110),
- char(102),
- char(105),
- char(103),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(80),
- char(111),
- char(115),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(74),
- char(111),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(0),
- char(0),
- char(84),
- char(76),
- char(69),
- char(78),
- char(1),
- char(0),
- char(1),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(8),
- char(0),
- char(0),
- char(0),
- char(12),
- char(0),
- char(36),
- char(0),
- char(8),
- char(0),
- char(16),
- char(0),
- char(32),
- char(0),
- char(48),
- char(0),
- char(96),
- char(0),
- char(64),
- char(0),
- char(-128),
- char(0),
- char(20),
- char(0),
- char(48),
- char(0),
- char(80),
- char(0),
- char(16),
- char(0),
- char(84),
- char(0),
- char(-124),
- char(0),
- char(12),
- char(0),
- char(52),
- char(0),
- char(52),
- char(0),
- char(20),
- char(0),
- char(64),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(8),
- char(0),
- char(4),
- char(0),
- char(32),
- char(0),
- char(28),
- char(0),
- char(60),
- char(0),
- char(56),
- char(0),
- char(76),
- char(0),
- char(76),
- char(0),
- char(24),
- char(0),
- char(60),
- char(0),
- char(60),
- char(0),
- char(16),
- char(0),
- char(64),
- char(0),
- char(68),
- char(0),
- char(-48),
- char(1),
- char(0),
- char(1),
- char(-72),
- char(0),
- char(-104),
- char(0),
- char(104),
- char(0),
- char(88),
- char(0),
- char(-24),
- char(1),
- char(-96),
- char(3),
- char(8),
- char(0),
- char(52),
- char(0),
- char(0),
- char(0),
- char(84),
- char(0),
- char(116),
- char(0),
- char(92),
- char(1),
- char(-36),
- char(0),
- char(-44),
- char(0),
- char(-4),
- char(0),
- char(92),
- char(1),
- char(-52),
- char(0),
- char(16),
- char(0),
- char(100),
- char(0),
- char(20),
- char(0),
- char(36),
- char(0),
- char(100),
- char(0),
- char(92),
- char(0),
- char(104),
- char(0),
- char(-64),
- char(0),
- char(92),
- char(1),
- char(104),
- char(0),
- char(-84),
- char(1),
- char(83),
- char(84),
- char(82),
- char(67),
- char(65),
- char(0),
- char(0),
- char(0),
- char(10),
- char(0),
- char(3),
- char(0),
- char(4),
- char(0),
- char(0),
- char(0),
- char(4),
- char(0),
- char(1),
- char(0),
- char(9),
- char(0),
- char(2),
- char(0),
- char(11),
- char(0),
- char(3),
- char(0),
- char(10),
- char(0),
- char(3),
- char(0),
- char(10),
- char(0),
- char(4),
- char(0),
- char(10),
- char(0),
- char(5),
- char(0),
- char(12),
- char(0),
- char(2),
- char(0),
- char(9),
- char(0),
- char(6),
- char(0),
- char(9),
- char(0),
- char(7),
- char(0),
- char(13),
- char(0),
- char(1),
- char(0),
- char(7),
- char(0),
- char(8),
- char(0),
- char(14),
- char(0),
- char(1),
- char(0),
- char(8),
- char(0),
- char(8),
- char(0),
- char(15),
- char(0),
- char(1),
- char(0),
- char(13),
- char(0),
- char(9),
- char(0),
- char(16),
- char(0),
- char(1),
- char(0),
- char(14),
- char(0),
- char(9),
- char(0),
- char(17),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(10),
- char(0),
- char(13),
- char(0),
- char(11),
- char(0),
- char(18),
- char(0),
- char(2),
- char(0),
- char(16),
- char(0),
- char(10),
- char(0),
- char(14),
- char(0),
- char(11),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(12),
- char(0),
- char(4),
- char(0),
- char(13),
- char(0),
- char(2),
- char(0),
- char(14),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(20),
- char(0),
- char(6),
- char(0),
- char(13),
- char(0),
- char(16),
- char(0),
- char(13),
- char(0),
- char(17),
- char(0),
- char(4),
- char(0),
- char(18),
- char(0),
- char(4),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(20),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(21),
- char(0),
- char(6),
- char(0),
- char(14),
- char(0),
- char(16),
- char(0),
- char(14),
- char(0),
- char(17),
- char(0),
- char(4),
- char(0),
- char(18),
- char(0),
- char(4),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(20),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(22),
- char(0),
- char(3),
- char(0),
- char(2),
- char(0),
- char(14),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(4),
- char(0),
- char(22),
- char(0),
- char(23),
- char(0),
- char(12),
- char(0),
- char(13),
- char(0),
- char(23),
- char(0),
- char(13),
- char(0),
- char(24),
- char(0),
- char(13),
- char(0),
- char(25),
- char(0),
- char(4),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(4),
- char(0),
- char(28),
- char(0),
- char(4),
- char(0),
- char(29),
- char(0),
- char(20),
- char(0),
- char(30),
- char(0),
- char(22),
- char(0),
- char(31),
- char(0),
- char(19),
- char(0),
- char(32),
- char(0),
- char(4),
- char(0),
- char(33),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(24),
- char(0),
- char(12),
- char(0),
- char(14),
- char(0),
- char(23),
- char(0),
- char(14),
- char(0),
- char(24),
- char(0),
- char(14),
- char(0),
- char(25),
- char(0),
- char(4),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(4),
- char(0),
- char(28),
- char(0),
- char(4),
- char(0),
- char(29),
- char(0),
- char(21),
- char(0),
- char(30),
- char(0),
- char(22),
- char(0),
- char(31),
- char(0),
- char(4),
- char(0),
- char(33),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(19),
- char(0),
- char(32),
- char(0),
- char(25),
- char(0),
- char(3),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(36),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(26),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(13),
- char(0),
- char(40),
- char(0),
- char(7),
- char(0),
- char(41),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(27),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(13),
- char(0),
- char(42),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(44),
- char(0),
- char(28),
- char(0),
- char(2),
- char(0),
- char(13),
- char(0),
- char(45),
- char(0),
- char(7),
- char(0),
- char(46),
- char(0),
- char(29),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(28),
- char(0),
- char(48),
- char(0),
- char(4),
- char(0),
- char(49),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(30),
- char(0),
- char(1),
- char(0),
- char(4),
- char(0),
- char(50),
- char(0),
- char(31),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(50),
- char(0),
- char(0),
- char(0),
- char(51),
- char(0),
- char(32),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(52),
- char(0),
- char(0),
- char(0),
- char(51),
- char(0),
- char(33),
- char(0),
- char(2),
- char(0),
- char(0),
- char(0),
- char(52),
- char(0),
- char(0),
- char(0),
- char(53),
- char(0),
- char(34),
- char(0),
- char(8),
- char(0),
- char(13),
- char(0),
- char(54),
- char(0),
- char(14),
- char(0),
- char(55),
- char(0),
- char(30),
- char(0),
- char(56),
- char(0),
- char(32),
- char(0),
- char(57),
- char(0),
- char(33),
- char(0),
- char(58),
- char(0),
- char(31),
- char(0),
- char(59),
- char(0),
- char(4),
- char(0),
- char(60),
- char(0),
- char(4),
- char(0),
- char(61),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(62),
- char(0),
- char(13),
- char(0),
- char(63),
- char(0),
- char(4),
- char(0),
- char(64),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(36),
- char(0),
- char(7),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(35),
- char(0),
- char(65),
- char(0),
- char(23),
- char(0),
- char(66),
- char(0),
- char(24),
- char(0),
- char(67),
- char(0),
- char(37),
- char(0),
- char(68),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(0),
- char(0),
- char(69),
- char(0),
- char(38),
- char(0),
- char(2),
- char(0),
- char(36),
- char(0),
- char(70),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(39),
- char(0),
- char(4),
- char(0),
- char(17),
- char(0),
- char(71),
- char(0),
- char(25),
- char(0),
- char(72),
- char(0),
- char(4),
- char(0),
- char(73),
- char(0),
- char(7),
- char(0),
- char(74),
- char(0),
- char(40),
- char(0),
- char(4),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(39),
- char(0),
- char(75),
- char(0),
- char(4),
- char(0),
- char(76),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(41),
- char(0),
- char(3),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(4),
- char(0),
- char(77),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(42),
- char(0),
- char(3),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(4),
- char(0),
- char(77),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(78),
- char(0),
- char(7),
- char(0),
- char(79),
- char(0),
- char(7),
- char(0),
- char(80),
- char(0),
- char(7),
- char(0),
- char(81),
- char(0),
- char(37),
- char(0),
- char(14),
- char(0),
- char(4),
- char(0),
- char(82),
- char(0),
- char(4),
- char(0),
- char(83),
- char(0),
- char(43),
- char(0),
- char(84),
- char(0),
- char(4),
- char(0),
- char(85),
- char(0),
- char(7),
- char(0),
- char(86),
- char(0),
- char(7),
- char(0),
- char(87),
- char(0),
- char(7),
- char(0),
- char(88),
- char(0),
- char(7),
- char(0),
- char(89),
- char(0),
- char(7),
- char(0),
- char(90),
- char(0),
- char(4),
- char(0),
- char(91),
- char(0),
- char(4),
- char(0),
- char(92),
- char(0),
- char(4),
- char(0),
- char(93),
- char(0),
- char(4),
- char(0),
- char(94),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(44),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(35),
- char(0),
- char(65),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(95),
- char(0),
- char(45),
- char(0),
- char(5),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(13),
- char(0),
- char(96),
- char(0),
- char(14),
- char(0),
- char(97),
- char(0),
- char(4),
- char(0),
- char(98),
- char(0),
- char(0),
- char(0),
- char(99),
- char(0),
- char(46),
- char(0),
- char(25),
- char(0),
- char(9),
- char(0),
- char(100),
- char(0),
- char(9),
- char(0),
- char(101),
- char(0),
- char(25),
- char(0),
- char(102),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(18),
- char(0),
- char(103),
- char(0),
- char(18),
- char(0),
- char(104),
- char(0),
- char(14),
- char(0),
- char(105),
- char(0),
- char(14),
- char(0),
- char(106),
- char(0),
- char(14),
- char(0),
- char(107),
- char(0),
- char(8),
- char(0),
- char(108),
- char(0),
- char(8),
- char(0),
- char(109),
- char(0),
- char(8),
- char(0),
- char(110),
- char(0),
- char(8),
- char(0),
- char(111),
- char(0),
- char(8),
- char(0),
- char(112),
- char(0),
- char(8),
- char(0),
- char(113),
- char(0),
- char(8),
- char(0),
- char(114),
- char(0),
- char(8),
- char(0),
- char(115),
- char(0),
- char(4),
- char(0),
- char(116),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(4),
- char(0),
- char(118),
- char(0),
- char(4),
- char(0),
- char(119),
- char(0),
- char(4),
- char(0),
- char(120),
- char(0),
- char(4),
- char(0),
- char(121),
- char(0),
- char(4),
- char(0),
- char(122),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(47),
- char(0),
- char(25),
- char(0),
- char(9),
- char(0),
- char(100),
- char(0),
- char(9),
- char(0),
- char(101),
- char(0),
- char(25),
- char(0),
- char(102),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(17),
- char(0),
- char(103),
- char(0),
- char(17),
- char(0),
- char(104),
- char(0),
- char(13),
- char(0),
- char(105),
- char(0),
- char(13),
- char(0),
- char(106),
- char(0),
- char(13),
- char(0),
- char(107),
- char(0),
- char(7),
- char(0),
- char(108),
- char(0),
- char(7),
- char(0),
- char(109),
- char(0),
- char(7),
- char(0),
- char(110),
- char(0),
- char(7),
- char(0),
- char(111),
- char(0),
- char(7),
- char(0),
- char(112),
- char(0),
- char(7),
- char(0),
- char(113),
- char(0),
- char(7),
- char(0),
- char(114),
- char(0),
- char(7),
- char(0),
- char(115),
- char(0),
- char(4),
- char(0),
- char(116),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(4),
- char(0),
- char(118),
- char(0),
- char(4),
- char(0),
- char(119),
- char(0),
- char(4),
- char(0),
- char(120),
- char(0),
- char(4),
- char(0),
- char(121),
- char(0),
- char(4),
- char(0),
- char(122),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(48),
- char(0),
- char(2),
- char(0),
- char(49),
- char(0),
- char(123),
- char(0),
- char(14),
- char(0),
- char(124),
- char(0),
- char(50),
- char(0),
- char(2),
- char(0),
- char(51),
- char(0),
- char(123),
- char(0),
- char(13),
- char(0),
- char(124),
- char(0),
- char(52),
- char(0),
- char(21),
- char(0),
- char(47),
- char(0),
- char(125),
- char(0),
- char(15),
- char(0),
- char(126),
- char(0),
- char(13),
- char(0),
- char(127),
- char(0),
- char(13),
- char(0),
- char(-128),
- char(0),
- char(13),
- char(0),
- char(-127),
- char(0),
- char(13),
- char(0),
- char(-126),
- char(0),
- char(13),
- char(0),
- char(124),
- char(0),
- char(13),
- char(0),
- char(-125),
- char(0),
- char(13),
- char(0),
- char(-124),
- char(0),
- char(13),
- char(0),
- char(-123),
- char(0),
- char(13),
- char(0),
- char(-122),
- char(0),
- char(7),
- char(0),
- char(-121),
- char(0),
- char(7),
- char(0),
- char(-120),
- char(0),
- char(7),
- char(0),
- char(-119),
- char(0),
- char(7),
- char(0),
- char(-118),
- char(0),
- char(7),
- char(0),
- char(-117),
- char(0),
- char(7),
- char(0),
- char(-116),
- char(0),
- char(7),
- char(0),
- char(-115),
- char(0),
- char(7),
- char(0),
- char(-114),
- char(0),
- char(7),
- char(0),
- char(-113),
- char(0),
- char(4),
- char(0),
- char(-112),
- char(0),
- char(53),
- char(0),
- char(22),
- char(0),
- char(46),
- char(0),
- char(125),
- char(0),
- char(16),
- char(0),
- char(126),
- char(0),
- char(14),
- char(0),
- char(127),
- char(0),
- char(14),
- char(0),
- char(-128),
- char(0),
- char(14),
- char(0),
- char(-127),
- char(0),
- char(14),
- char(0),
- char(-126),
- char(0),
- char(14),
- char(0),
- char(124),
- char(0),
- char(14),
- char(0),
- char(-125),
- char(0),
- char(14),
- char(0),
- char(-124),
- char(0),
- char(14),
- char(0),
- char(-123),
- char(0),
- char(14),
- char(0),
- char(-122),
- char(0),
- char(8),
- char(0),
- char(-121),
- char(0),
- char(8),
- char(0),
- char(-120),
- char(0),
- char(8),
- char(0),
- char(-119),
- char(0),
- char(8),
- char(0),
- char(-118),
- char(0),
- char(8),
- char(0),
- char(-117),
- char(0),
- char(8),
- char(0),
- char(-116),
- char(0),
- char(8),
- char(0),
- char(-115),
- char(0),
- char(8),
- char(0),
- char(-114),
- char(0),
- char(8),
- char(0),
- char(-113),
- char(0),
- char(4),
- char(0),
- char(-112),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(54),
- char(0),
- char(2),
- char(0),
- char(4),
- char(0),
- char(-111),
- char(0),
- char(4),
- char(0),
- char(-110),
- char(0),
- char(55),
- char(0),
- char(13),
- char(0),
- char(56),
- char(0),
- char(-109),
- char(0),
- char(56),
- char(0),
- char(-108),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(-107),
- char(0),
- char(4),
- char(0),
- char(-106),
- char(0),
- char(4),
- char(0),
- char(-105),
- char(0),
- char(4),
- char(0),
- char(-104),
- char(0),
- char(7),
- char(0),
- char(-103),
- char(0),
- char(7),
- char(0),
- char(-102),
- char(0),
- char(4),
- char(0),
- char(-101),
- char(0),
- char(4),
- char(0),
- char(-100),
- char(0),
- char(7),
- char(0),
- char(-99),
- char(0),
- char(4),
- char(0),
- char(-98),
- char(0),
- char(57),
- char(0),
- char(3),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(13),
- char(0),
- char(-96),
- char(0),
- char(13),
- char(0),
- char(-95),
- char(0),
- char(58),
- char(0),
- char(3),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(14),
- char(0),
- char(-96),
- char(0),
- char(14),
- char(0),
- char(-95),
- char(0),
- char(59),
- char(0),
- char(13),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(18),
- char(0),
- char(-94),
- char(0),
- char(18),
- char(0),
- char(-93),
- char(0),
- char(4),
- char(0),
- char(-92),
- char(0),
- char(4),
- char(0),
- char(-91),
- char(0),
- char(4),
- char(0),
- char(-90),
- char(0),
- char(7),
- char(0),
- char(-89),
- char(0),
- char(7),
- char(0),
- char(-88),
- char(0),
- char(7),
- char(0),
- char(-87),
- char(0),
- char(7),
- char(0),
- char(-86),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(60),
- char(0),
- char(13),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(4),
- char(0),
- char(-92),
- char(0),
- char(4),
- char(0),
- char(-91),
- char(0),
- char(4),
- char(0),
- char(-90),
- char(0),
- char(7),
- char(0),
- char(-89),
- char(0),
- char(7),
- char(0),
- char(-88),
- char(0),
- char(7),
- char(0),
- char(-87),
- char(0),
- char(7),
- char(0),
- char(-86),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(61),
- char(0),
- char(11),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(7),
- char(0),
- char(-82),
- char(0),
- char(7),
- char(0),
- char(-81),
- char(0),
- char(7),
- char(0),
- char(-80),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(62),
- char(0),
- char(9),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(13),
- char(0),
- char(-78),
- char(0),
- char(13),
- char(0),
- char(-77),
- char(0),
- char(13),
- char(0),
- char(-76),
- char(0),
- char(13),
- char(0),
- char(-75),
- char(0),
- char(4),
- char(0),
- char(-74),
- char(0),
- char(4),
- char(0),
- char(-73),
- char(0),
- char(63),
- char(0),
- char(5),
- char(0),
- char(62),
- char(0),
- char(-72),
- char(0),
- char(4),
- char(0),
- char(-71),
- char(0),
- char(7),
- char(0),
- char(-70),
- char(0),
- char(7),
- char(0),
- char(-69),
- char(0),
- char(7),
- char(0),
- char(-68),
- char(0),
- char(64),
- char(0),
- char(9),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(7),
- char(0),
- char(-78),
- char(0),
- char(7),
- char(0),
- char(-77),
- char(0),
- char(7),
- char(0),
- char(-76),
- char(0),
- char(7),
- char(0),
- char(-75),
- char(0),
- char(4),
- char(0),
- char(-74),
- char(0),
- char(4),
- char(0),
- char(-73),
- char(0),
- char(49),
- char(0),
- char(22),
- char(0),
- char(8),
- char(0),
- char(-67),
- char(0),
- char(8),
- char(0),
- char(-79),
- char(0),
- char(8),
- char(0),
- char(110),
- char(0),
- char(8),
- char(0),
- char(-66),
- char(0),
- char(8),
- char(0),
- char(112),
- char(0),
- char(8),
- char(0),
- char(-65),
- char(0),
- char(8),
- char(0),
- char(-64),
- char(0),
- char(8),
- char(0),
- char(-63),
- char(0),
- char(8),
- char(0),
- char(-62),
- char(0),
- char(8),
- char(0),
- char(-61),
- char(0),
- char(8),
- char(0),
- char(-60),
- char(0),
- char(8),
- char(0),
- char(-59),
- char(0),
- char(8),
- char(0),
- char(-58),
- char(0),
- char(8),
- char(0),
- char(-57),
- char(0),
- char(8),
- char(0),
- char(-56),
- char(0),
- char(8),
- char(0),
- char(-55),
- char(0),
- char(4),
- char(0),
- char(-54),
- char(0),
- char(4),
- char(0),
- char(-53),
- char(0),
- char(4),
- char(0),
- char(-52),
- char(0),
- char(4),
- char(0),
- char(-51),
- char(0),
- char(4),
- char(0),
- char(-50),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(51),
- char(0),
- char(22),
- char(0),
- char(7),
- char(0),
- char(-67),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(7),
- char(0),
- char(110),
- char(0),
- char(7),
- char(0),
- char(-66),
- char(0),
- char(7),
- char(0),
- char(112),
- char(0),
- char(7),
- char(0),
- char(-65),
- char(0),
- char(7),
- char(0),
- char(-64),
- char(0),
- char(7),
- char(0),
- char(-63),
- char(0),
- char(7),
- char(0),
- char(-62),
- char(0),
- char(7),
- char(0),
- char(-61),
- char(0),
- char(7),
- char(0),
- char(-60),
- char(0),
- char(7),
- char(0),
- char(-59),
- char(0),
- char(7),
- char(0),
- char(-58),
- char(0),
- char(7),
- char(0),
- char(-57),
- char(0),
- char(7),
- char(0),
- char(-56),
- char(0),
- char(7),
- char(0),
- char(-55),
- char(0),
- char(4),
- char(0),
- char(-54),
- char(0),
- char(4),
- char(0),
- char(-53),
- char(0),
- char(4),
- char(0),
- char(-52),
- char(0),
- char(4),
- char(0),
- char(-51),
- char(0),
- char(4),
- char(0),
- char(-50),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(65),
- char(0),
- char(4),
- char(0),
- char(7),
- char(0),
- char(-49),
- char(0),
- char(7),
- char(0),
- char(-48),
- char(0),
- char(7),
- char(0),
- char(-47),
- char(0),
- char(4),
- char(0),
- char(78),
- char(0),
- char(66),
- char(0),
- char(10),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(13),
- char(0),
- char(-45),
- char(0),
- char(13),
- char(0),
- char(-44),
- char(0),
- char(13),
- char(0),
- char(-43),
- char(0),
- char(13),
- char(0),
- char(-42),
- char(0),
- char(13),
- char(0),
- char(-41),
- char(0),
- char(7),
- char(0),
- char(-121),
- char(0),
- char(7),
- char(0),
- char(-40),
- char(0),
- char(4),
- char(0),
- char(-39),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(67),
- char(0),
- char(4),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-38),
- char(0),
- char(7),
- char(0),
- char(-37),
- char(0),
- char(4),
- char(0),
- char(-36),
- char(0),
- char(68),
- char(0),
- char(4),
- char(0),
- char(13),
- char(0),
- char(-41),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-35),
- char(0),
- char(7),
- char(0),
- char(-34),
- char(0),
- char(69),
- char(0),
- char(7),
- char(0),
- char(13),
- char(0),
- char(-33),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-32),
- char(0),
- char(7),
- char(0),
- char(-31),
- char(0),
- char(7),
- char(0),
- char(-30),
- char(0),
- char(7),
- char(0),
- char(-29),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(70),
- char(0),
- char(6),
- char(0),
- char(15),
- char(0),
- char(-28),
- char(0),
- char(13),
- char(0),
- char(-30),
- char(0),
- char(13),
- char(0),
- char(-27),
- char(0),
- char(56),
- char(0),
- char(-26),
- char(0),
- char(4),
- char(0),
- char(-25),
- char(0),
- char(7),
- char(0),
- char(-29),
- char(0),
- char(71),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(-24),
- char(0),
- char(7),
- char(0),
- char(-23),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(7),
- char(0),
- char(-22),
- char(0),
- char(7),
- char(0),
- char(-21),
- char(0),
- char(7),
- char(0),
- char(-20),
- char(0),
- char(7),
- char(0),
- char(-19),
- char(0),
- char(7),
- char(0),
- char(-18),
- char(0),
- char(7),
- char(0),
- char(-17),
- char(0),
- char(7),
- char(0),
- char(-16),
- char(0),
- char(7),
- char(0),
- char(-15),
- char(0),
- char(7),
- char(0),
- char(-14),
- char(0),
- char(7),
- char(0),
- char(-13),
- char(0),
- char(7),
- char(0),
- char(-12),
- char(0),
- char(7),
- char(0),
- char(-11),
- char(0),
- char(7),
- char(0),
- char(-10),
- char(0),
- char(7),
- char(0),
- char(-9),
- char(0),
- char(7),
- char(0),
- char(-8),
- char(0),
- char(7),
- char(0),
- char(-7),
- char(0),
- char(7),
- char(0),
- char(-6),
- char(0),
- char(7),
- char(0),
- char(-5),
- char(0),
- char(4),
- char(0),
- char(-4),
- char(0),
- char(4),
- char(0),
- char(-3),
- char(0),
- char(4),
- char(0),
- char(-2),
- char(0),
- char(4),
- char(0),
- char(-1),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(72),
- char(0),
- char(12),
- char(0),
- char(15),
- char(0),
- char(0),
- char(1),
- char(15),
- char(0),
- char(1),
- char(1),
- char(15),
- char(0),
- char(2),
- char(1),
- char(13),
- char(0),
- char(3),
- char(1),
- char(13),
- char(0),
- char(4),
- char(1),
- char(7),
- char(0),
- char(5),
- char(1),
- char(4),
- char(0),
- char(6),
- char(1),
- char(4),
- char(0),
- char(7),
- char(1),
- char(4),
- char(0),
- char(8),
- char(1),
- char(4),
- char(0),
- char(9),
- char(1),
- char(7),
- char(0),
- char(-31),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(73),
- char(0),
- char(27),
- char(0),
- char(17),
- char(0),
- char(10),
- char(1),
- char(15),
- char(0),
- char(11),
- char(1),
- char(15),
- char(0),
- char(12),
- char(1),
- char(13),
- char(0),
- char(3),
- char(1),
- char(13),
- char(0),
- char(13),
- char(1),
- char(13),
- char(0),
- char(14),
- char(1),
- char(13),
- char(0),
- char(15),
- char(1),
- char(13),
- char(0),
- char(16),
- char(1),
- char(13),
- char(0),
- char(17),
- char(1),
- char(4),
- char(0),
- char(18),
- char(1),
- char(7),
- char(0),
- char(19),
- char(1),
- char(4),
- char(0),
- char(20),
- char(1),
- char(4),
- char(0),
- char(21),
- char(1),
- char(4),
- char(0),
- char(22),
- char(1),
- char(7),
- char(0),
- char(23),
- char(1),
- char(7),
- char(0),
- char(24),
- char(1),
- char(4),
- char(0),
- char(25),
- char(1),
- char(4),
- char(0),
- char(26),
- char(1),
- char(7),
- char(0),
- char(27),
- char(1),
- char(7),
- char(0),
- char(28),
- char(1),
- char(7),
- char(0),
- char(29),
- char(1),
- char(7),
- char(0),
- char(30),
- char(1),
- char(7),
- char(0),
- char(31),
- char(1),
- char(7),
- char(0),
- char(32),
- char(1),
- char(4),
- char(0),
- char(33),
- char(1),
- char(4),
- char(0),
- char(34),
- char(1),
- char(4),
- char(0),
- char(35),
- char(1),
- char(74),
- char(0),
- char(12),
- char(0),
- char(9),
- char(0),
- char(36),
- char(1),
- char(9),
- char(0),
- char(37),
- char(1),
- char(13),
- char(0),
- char(38),
- char(1),
- char(7),
- char(0),
- char(39),
- char(1),
- char(7),
- char(0),
- char(-63),
- char(0),
- char(7),
- char(0),
- char(40),
- char(1),
- char(4),
- char(0),
- char(41),
- char(1),
- char(13),
- char(0),
- char(42),
- char(1),
- char(4),
- char(0),
- char(43),
- char(1),
- char(4),
- char(0),
- char(44),
- char(1),
- char(4),
- char(0),
- char(45),
- char(1),
- char(4),
- char(0),
- char(53),
- char(0),
- char(75),
- char(0),
- char(19),
- char(0),
- char(47),
- char(0),
- char(125),
- char(0),
- char(72),
- char(0),
- char(46),
- char(1),
- char(65),
- char(0),
- char(47),
- char(1),
- char(66),
- char(0),
- char(48),
- char(1),
- char(67),
- char(0),
- char(49),
- char(1),
- char(68),
- char(0),
- char(50),
- char(1),
- char(69),
- char(0),
- char(51),
- char(1),
- char(70),
- char(0),
- char(52),
- char(1),
- char(73),
- char(0),
- char(53),
- char(1),
- char(74),
- char(0),
- char(54),
- char(1),
- char(4),
- char(0),
- char(55),
- char(1),
- char(4),
- char(0),
- char(21),
- char(1),
- char(4),
- char(0),
- char(56),
- char(1),
- char(4),
- char(0),
- char(57),
- char(1),
- char(4),
- char(0),
- char(58),
- char(1),
- char(4),
- char(0),
- char(59),
- char(1),
- char(4),
- char(0),
- char(60),
- char(1),
- char(4),
- char(0),
- char(61),
- char(1),
- char(71),
- char(0),
- char(62),
- char(1),
-};
-int b3s_bulletDNAlen = sizeof(b3s_bulletDNAstr);
-char b3s_bulletDNAstr64[] = {
- char(83),
- char(68),
- char(78),
- char(65),
- char(78),
- char(65),
- char(77),
- char(69),
- char(63),
- char(1),
- char(0),
- char(0),
- char(109),
- char(95),
- char(115),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(97),
- char(112),
- char(97),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(42),
- char(109),
- char(95),
- char(100),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(42),
- char(102),
- char(105),
- char(114),
- char(115),
- char(116),
- char(0),
- char(42),
- char(108),
- char(97),
- char(115),
- char(116),
- char(0),
- char(109),
- char(95),
- char(102),
- char(108),
- char(111),
- char(97),
- char(116),
- char(115),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(108),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(98),
- char(97),
- char(115),
- char(105),
- char(115),
- char(0),
- char(109),
- char(95),
- char(111),
- char(114),
- char(105),
- char(103),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(111),
- char(116),
- char(78),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(97),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(79),
- char(114),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(79),
- char(114),
- char(103),
- char(0),
- char(109),
- char(95),
- char(101),
- char(115),
- char(99),
- char(97),
- char(112),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(80),
- char(97),
- char(114),
- char(116),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(115),
- char(99),
- char(97),
- char(112),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(79),
- char(114),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(65),
- char(97),
- char(98),
- char(98),
- char(77),
- char(97),
- char(120),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(104),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(117),
- char(114),
- char(78),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(76),
- char(101),
- char(97),
- char(102),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(105),
- char(103),
- char(117),
- char(111),
- char(117),
- char(115),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(115),
- char(117),
- char(98),
- char(84),
- char(114),
- char(101),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(97),
- char(118),
- char(101),
- char(114),
- char(115),
- char(97),
- char(108),
- char(77),
- char(111),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(83),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(72),
- char(101),
- char(97),
- char(100),
- char(101),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(104),
- char(97),
- char(112),
- char(101),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(83),
- char(99),
- char(97),
- char(108),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(101),
- char(78),
- char(111),
- char(114),
- char(109),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(97),
- char(110),
- char(116),
- char(0),
- char(109),
- char(95),
- char(105),
- char(109),
- char(112),
- char(108),
- char(105),
- char(99),
- char(105),
- char(116),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(105),
- char(109),
- char(101),
- char(110),
- char(115),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(77),
- char(97),
- char(114),
- char(103),
- char(105),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(0),
- char(109),
- char(95),
- char(114),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(42),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(115),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(102),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(100),
- char(0),
- char(42),
- char(109),
- char(95),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(51),
- char(50),
- char(0),
- char(42),
- char(109),
- char(95),
- char(51),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(49),
- char(54),
- char(0),
- char(42),
- char(109),
- char(95),
- char(51),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(56),
- char(0),
- char(42),
- char(109),
- char(95),
- char(105),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(49),
- char(54),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(86),
- char(101),
- char(114),
- char(116),
- char(105),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(115),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(115),
- char(99),
- char(97),
- char(108),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(109),
- char(101),
- char(115),
- char(104),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(102),
- char(97),
- char(99),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(66),
- char(118),
- char(104),
- char(0),
- char(42),
- char(109),
- char(95),
- char(113),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(66),
- char(118),
- char(104),
- char(0),
- char(42),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(77),
- char(97),
- char(112),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(51),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(105),
- char(109),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(116),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(77),
- char(97),
- char(114),
- char(103),
- char(105),
- char(110),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(104),
- char(105),
- char(108),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(117),
- char(112),
- char(65),
- char(120),
- char(105),
- char(115),
- char(0),
- char(109),
- char(95),
- char(102),
- char(108),
- char(97),
- char(103),
- char(115),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(48),
- char(86),
- char(49),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(49),
- char(86),
- char(50),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(86),
- char(50),
- char(86),
- char(48),
- char(65),
- char(110),
- char(103),
- char(108),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(104),
- char(84),
- char(97),
- char(98),
- char(108),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(101),
- char(120),
- char(116),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(118),
- char(97),
- char(108),
- char(117),
- char(101),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(107),
- char(101),
- char(121),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(69),
- char(112),
- char(115),
- char(105),
- char(108),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(108),
- char(97),
- char(110),
- char(97),
- char(114),
- char(69),
- char(112),
- char(115),
- char(105),
- char(108),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(101),
- char(113),
- char(117),
- char(97),
- char(108),
- char(86),
- char(101),
- char(114),
- char(116),
- char(101),
- char(120),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(101),
- char(100),
- char(103),
- char(101),
- char(68),
- char(105),
- char(115),
- char(116),
- char(97),
- char(110),
- char(99),
- char(101),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(122),
- char(101),
- char(114),
- char(111),
- char(65),
- char(114),
- char(101),
- char(97),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(101),
- char(120),
- char(116),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(104),
- char(84),
- char(97),
- char(98),
- char(108),
- char(101),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(86),
- char(97),
- char(108),
- char(117),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(75),
- char(101),
- char(121),
- char(115),
- char(0),
- char(109),
- char(95),
- char(103),
- char(105),
- char(109),
- char(112),
- char(97),
- char(99),
- char(116),
- char(83),
- char(117),
- char(98),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(117),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(80),
- char(116),
- char(114),
- char(0),
- char(42),
- char(109),
- char(95),
- char(117),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(80),
- char(116),
- char(114),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(85),
- char(110),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(112),
- char(97),
- char(100),
- char(100),
- char(105),
- char(110),
- char(103),
- char(51),
- char(91),
- char(52),
- char(93),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(114),
- char(111),
- char(97),
- char(100),
- char(112),
- char(104),
- char(97),
- char(115),
- char(101),
- char(72),
- char(97),
- char(110),
- char(100),
- char(108),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(111),
- char(111),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(119),
- char(111),
- char(114),
- char(108),
- char(100),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(112),
- char(111),
- char(108),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(105),
- char(115),
- char(111),
- char(116),
- char(114),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(80),
- char(114),
- char(111),
- char(99),
- char(101),
- char(115),
- char(115),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(100),
- char(101),
- char(97),
- char(99),
- char(116),
- char(105),
- char(118),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(105),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(102),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(108),
- char(108),
- char(105),
- char(110),
- char(103),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(105),
- char(116),
- char(117),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(104),
- char(105),
- char(116),
- char(70),
- char(114),
- char(97),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(99),
- char(100),
- char(83),
- char(119),
- char(101),
- char(112),
- char(116),
- char(83),
- char(112),
- char(104),
- char(101),
- char(114),
- char(101),
- char(82),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(99),
- char(100),
- char(77),
- char(111),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(104),
- char(97),
- char(115),
- char(65),
- char(110),
- char(105),
- char(115),
- char(111),
- char(116),
- char(114),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(70),
- char(108),
- char(97),
- char(103),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(115),
- char(108),
- char(97),
- char(110),
- char(100),
- char(84),
- char(97),
- char(103),
- char(49),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(109),
- char(112),
- char(97),
- char(110),
- char(105),
- char(111),
- char(110),
- char(73),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(99),
- char(116),
- char(105),
- char(118),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(83),
- char(116),
- char(97),
- char(116),
- char(101),
- char(49),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(104),
- char(101),
- char(99),
- char(107),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(100),
- char(101),
- char(87),
- char(105),
- char(116),
- char(104),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(0),
- char(109),
- char(95),
- char(103),
- char(114),
- char(97),
- char(118),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(73),
- char(110),
- char(101),
- char(114),
- char(116),
- char(105),
- char(97),
- char(84),
- char(101),
- char(110),
- char(115),
- char(111),
- char(114),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(103),
- char(114),
- char(97),
- char(118),
- char(105),
- char(116),
- char(121),
- char(95),
- char(97),
- char(99),
- char(99),
- char(101),
- char(108),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(73),
- char(110),
- char(101),
- char(114),
- char(116),
- char(105),
- char(97),
- char(76),
- char(111),
- char(99),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(116),
- char(111),
- char(116),
- char(97),
- char(108),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(116),
- char(111),
- char(116),
- char(97),
- char(108),
- char(84),
- char(111),
- char(114),
- char(113),
- char(117),
- char(101),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(101),
- char(114),
- char(115),
- char(101),
- char(77),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(83),
- char(113),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(83),
- char(113),
- char(114),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(108),
- char(101),
- char(101),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(83),
- char(108),
- char(101),
- char(101),
- char(112),
- char(105),
- char(110),
- char(103),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(100),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(97),
- char(108),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(82),
- char(111),
- char(119),
- char(115),
- char(0),
- char(110),
- char(117),
- char(98),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(98),
- char(65),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(98),
- char(66),
- char(0),
- char(109),
- char(95),
- char(111),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(73),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(101),
- char(101),
- char(100),
- char(115),
- char(70),
- char(101),
- char(101),
- char(100),
- char(98),
- char(97),
- char(99),
- char(107),
- char(0),
- char(109),
- char(95),
- char(97),
- char(112),
- char(112),
- char(108),
- char(105),
- char(101),
- char(100),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(98),
- char(103),
- char(68),
- char(114),
- char(97),
- char(119),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(105),
- char(115),
- char(97),
- char(98),
- char(108),
- char(101),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(115),
- char(66),
- char(101),
- char(116),
- char(119),
- char(101),
- char(101),
- char(110),
- char(76),
- char(105),
- char(110),
- char(107),
- char(101),
- char(100),
- char(66),
- char(111),
- char(100),
- char(105),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(111),
- char(118),
- char(101),
- char(114),
- char(114),
- char(105),
- char(100),
- char(101),
- char(78),
- char(117),
- char(109),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(114),
- char(101),
- char(97),
- char(107),
- char(105),
- char(110),
- char(103),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(105),
- char(115),
- char(69),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(100),
- char(0),
- char(109),
- char(95),
- char(116),
- char(121),
- char(112),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(112),
- char(105),
- char(118),
- char(111),
- char(116),
- char(73),
- char(110),
- char(65),
- char(0),
- char(109),
- char(95),
- char(112),
- char(105),
- char(118),
- char(111),
- char(116),
- char(73),
- char(110),
- char(66),
- char(0),
- char(109),
- char(95),
- char(114),
- char(98),
- char(65),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(98),
- char(66),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(82),
- char(101),
- char(102),
- char(101),
- char(114),
- char(101),
- char(110),
- char(99),
- char(101),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(65),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(79),
- char(110),
- char(108),
- char(121),
- char(0),
- char(109),
- char(95),
- char(101),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(65),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(77),
- char(111),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(109),
- char(111),
- char(116),
- char(111),
- char(114),
- char(84),
- char(97),
- char(114),
- char(103),
- char(101),
- char(116),
- char(86),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(77),
- char(111),
- char(116),
- char(111),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(117),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(109),
- char(105),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(105),
- char(97),
- char(115),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(108),
- char(97),
- char(120),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(115),
- char(119),
- char(105),
- char(110),
- char(103),
- char(83),
- char(112),
- char(97),
- char(110),
- char(49),
- char(0),
- char(109),
- char(95),
- char(115),
- char(119),
- char(105),
- char(110),
- char(103),
- char(83),
- char(112),
- char(97),
- char(110),
- char(50),
- char(0),
- char(109),
- char(95),
- char(116),
- char(119),
- char(105),
- char(115),
- char(116),
- char(83),
- char(112),
- char(97),
- char(110),
- char(0),
- char(109),
- char(95),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(85),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(76),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(85),
- char(112),
- char(112),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(76),
- char(111),
- char(119),
- char(101),
- char(114),
- char(76),
- char(105),
- char(109),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(76),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(82),
- char(101),
- char(102),
- char(101),
- char(114),
- char(101),
- char(110),
- char(99),
- char(101),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(65),
- char(0),
- char(109),
- char(95),
- char(117),
- char(115),
- char(101),
- char(79),
- char(102),
- char(102),
- char(115),
- char(101),
- char(116),
- char(70),
- char(111),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(54),
- char(100),
- char(111),
- char(102),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(69),
- char(110),
- char(97),
- char(98),
- char(108),
- char(101),
- char(100),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(101),
- char(113),
- char(117),
- char(105),
- char(108),
- char(105),
- char(98),
- char(114),
- char(105),
- char(117),
- char(109),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(68),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(91),
- char(54),
- char(93),
- char(0),
- char(109),
- char(95),
- char(116),
- char(97),
- char(117),
- char(0),
- char(109),
- char(95),
- char(116),
- char(105),
- char(109),
- char(101),
- char(83),
- char(116),
- char(101),
- char(112),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(69),
- char(114),
- char(114),
- char(111),
- char(114),
- char(82),
- char(101),
- char(100),
- char(117),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(101),
- char(114),
- char(112),
- char(0),
- char(109),
- char(95),
- char(101),
- char(114),
- char(112),
- char(50),
- char(0),
- char(109),
- char(95),
- char(103),
- char(108),
- char(111),
- char(98),
- char(97),
- char(108),
- char(67),
- char(102),
- char(109),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(80),
- char(101),
- char(110),
- char(101),
- char(116),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(84),
- char(117),
- char(114),
- char(110),
- char(69),
- char(114),
- char(112),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(108),
- char(111),
- char(112),
- char(0),
- char(109),
- char(95),
- char(119),
- char(97),
- char(114),
- char(109),
- char(115),
- char(116),
- char(97),
- char(114),
- char(116),
- char(105),
- char(110),
- char(103),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(71),
- char(121),
- char(114),
- char(111),
- char(115),
- char(99),
- char(111),
- char(112),
- char(105),
- char(99),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(105),
- char(110),
- char(103),
- char(108),
- char(101),
- char(65),
- char(120),
- char(105),
- char(115),
- char(82),
- char(111),
- char(108),
- char(108),
- char(105),
- char(110),
- char(103),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(77),
- char(111),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(105),
- char(110),
- char(103),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(82),
- char(101),
- char(115),
- char(116),
- char(105),
- char(116),
- char(117),
- char(116),
- char(105),
- char(111),
- char(110),
- char(84),
- char(104),
- char(114),
- char(101),
- char(115),
- char(104),
- char(111),
- char(108),
- char(100),
- char(0),
- char(109),
- char(95),
- char(109),
- char(105),
- char(110),
- char(105),
- char(109),
- char(117),
- char(109),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(66),
- char(97),
- char(116),
- char(99),
- char(104),
- char(83),
- char(105),
- char(122),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(101),
- char(97),
- char(114),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(103),
- char(117),
- char(108),
- char(97),
- char(114),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(83),
- char(116),
- char(105),
- char(102),
- char(102),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(114),
- char(101),
- char(118),
- char(105),
- char(111),
- char(117),
- char(115),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(118),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(0),
- char(109),
- char(95),
- char(97),
- char(99),
- char(99),
- char(117),
- char(109),
- char(117),
- char(108),
- char(97),
- char(116),
- char(101),
- char(100),
- char(70),
- char(111),
- char(114),
- char(99),
- char(101),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(114),
- char(109),
- char(97),
- char(108),
- char(0),
- char(109),
- char(95),
- char(97),
- char(114),
- char(101),
- char(97),
- char(0),
- char(109),
- char(95),
- char(97),
- char(116),
- char(116),
- char(97),
- char(99),
- char(104),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(76),
- char(101),
- char(110),
- char(103),
- char(116),
- char(104),
- char(0),
- char(109),
- char(95),
- char(98),
- char(98),
- char(101),
- char(110),
- char(100),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(51),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(65),
- char(114),
- char(101),
- char(97),
- char(0),
- char(109),
- char(95),
- char(99),
- char(48),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(91),
- char(52),
- char(93),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(115),
- char(116),
- char(86),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(49),
- char(0),
- char(109),
- char(95),
- char(99),
- char(50),
- char(0),
- char(109),
- char(95),
- char(99),
- char(48),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(97),
- char(108),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(114),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(0),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(109),
- char(95),
- char(97),
- char(101),
- char(114),
- char(111),
- char(77),
- char(111),
- char(100),
- char(101),
- char(108),
- char(0),
- char(109),
- char(95),
- char(98),
- char(97),
- char(117),
- char(109),
- char(103),
- char(97),
- char(114),
- char(116),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(114),
- char(97),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(105),
- char(102),
- char(116),
- char(0),
- char(109),
- char(95),
- char(112),
- char(114),
- char(101),
- char(115),
- char(115),
- char(117),
- char(114),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(100),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(70),
- char(114),
- char(105),
- char(99),
- char(116),
- char(105),
- char(111),
- char(110),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(101),
- char(77),
- char(97),
- char(116),
- char(99),
- char(104),
- char(0),
- char(109),
- char(95),
- char(114),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(107),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(97),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(75),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(72),
- char(97),
- char(114),
- char(100),
- char(110),
- char(101),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(75),
- char(105),
- char(110),
- char(101),
- char(116),
- char(105),
- char(99),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(111),
- char(102),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(83),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(86),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(116),
- char(105),
- char(109),
- char(101),
- char(83),
- char(99),
- char(97),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(118),
- char(101),
- char(108),
- char(111),
- char(99),
- char(105),
- char(116),
- char(121),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(100),
- char(114),
- char(105),
- char(102),
- char(116),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(116),
- char(101),
- char(114),
- char(97),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(114),
- char(111),
- char(116),
- char(0),
- char(109),
- char(95),
- char(115),
- char(99),
- char(97),
- char(108),
- char(101),
- char(0),
- char(109),
- char(95),
- char(97),
- char(113),
- char(113),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(109),
- char(0),
- char(42),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(119),
- char(101),
- char(105),
- char(103),
- char(104),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(87),
- char(101),
- char(105),
- char(103),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(98),
- char(118),
- char(111),
- char(108),
- char(117),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(98),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(0),
- char(109),
- char(95),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(120),
- char(102),
- char(111),
- char(114),
- char(109),
- char(0),
- char(109),
- char(95),
- char(108),
- char(111),
- char(99),
- char(105),
- char(105),
- char(0),
- char(109),
- char(95),
- char(105),
- char(110),
- char(118),
- char(119),
- char(105),
- char(0),
- char(109),
- char(95),
- char(118),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(100),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(108),
- char(118),
- char(0),
- char(109),
- char(95),
- char(97),
- char(118),
- char(0),
- char(42),
- char(109),
- char(95),
- char(102),
- char(114),
- char(97),
- char(109),
- char(101),
- char(114),
- char(101),
- char(102),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(73),
- char(110),
- char(100),
- char(105),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(115),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(70),
- char(114),
- char(97),
- char(109),
- char(101),
- char(82),
- char(101),
- char(102),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(78),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(97),
- char(115),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(100),
- char(109),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(105),
- char(109),
- char(97),
- char(115),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(118),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(100),
- char(105),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(108),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(97),
- char(100),
- char(97),
- char(109),
- char(112),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(99),
- char(104),
- char(105),
- char(110),
- char(103),
- char(0),
- char(109),
- char(95),
- char(109),
- char(97),
- char(120),
- char(83),
- char(101),
- char(108),
- char(102),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(0),
- char(109),
- char(95),
- char(115),
- char(101),
- char(108),
- char(102),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(73),
- char(109),
- char(112),
- char(117),
- char(108),
- char(115),
- char(101),
- char(70),
- char(97),
- char(99),
- char(116),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(116),
- char(97),
- char(105),
- char(110),
- char(115),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(108),
- char(108),
- char(105),
- char(100),
- char(101),
- char(0),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(65),
- char(0),
- char(42),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(66),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(102),
- char(115),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(99),
- char(102),
- char(109),
- char(0),
- char(109),
- char(95),
- char(115),
- char(112),
- char(108),
- char(105),
- char(116),
- char(0),
- char(109),
- char(95),
- char(100),
- char(101),
- char(108),
- char(101),
- char(116),
- char(101),
- char(0),
- char(109),
- char(95),
- char(114),
- char(101),
- char(108),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(91),
- char(50),
- char(93),
- char(0),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(65),
- char(116),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(98),
- char(111),
- char(100),
- char(121),
- char(66),
- char(116),
- char(121),
- char(112),
- char(101),
- char(0),
- char(109),
- char(95),
- char(106),
- char(111),
- char(105),
- char(110),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(0),
- char(42),
- char(109),
- char(95),
- char(112),
- char(111),
- char(115),
- char(101),
- char(0),
- char(42),
- char(42),
- char(109),
- char(95),
- char(109),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(110),
- char(111),
- char(100),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(108),
- char(105),
- char(110),
- char(107),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(102),
- char(97),
- char(99),
- char(101),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(116),
- char(101),
- char(116),
- char(114),
- char(97),
- char(104),
- char(101),
- char(100),
- char(114),
- char(97),
- char(0),
- char(42),
- char(109),
- char(95),
- char(97),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(99),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(115),
- char(0),
- char(42),
- char(109),
- char(95),
- char(106),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(77),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(76),
- char(105),
- char(110),
- char(107),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(70),
- char(97),
- char(99),
- char(101),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(84),
- char(101),
- char(116),
- char(114),
- char(97),
- char(104),
- char(101),
- char(100),
- char(114),
- char(97),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(115),
- char(0),
- char(109),
- char(95),
- char(110),
- char(117),
- char(109),
- char(74),
- char(111),
- char(105),
- char(110),
- char(116),
- char(115),
- char(0),
- char(109),
- char(95),
- char(99),
- char(111),
- char(110),
- char(102),
- char(105),
- char(103),
- char(0),
- char(84),
- char(89),
- char(80),
- char(69),
- char(76),
- char(0),
- char(0),
- char(0),
- char(99),
- char(104),
- char(97),
- char(114),
- char(0),
- char(117),
- char(99),
- char(104),
- char(97),
- char(114),
- char(0),
- char(115),
- char(104),
- char(111),
- char(114),
- char(116),
- char(0),
- char(117),
- char(115),
- char(104),
- char(111),
- char(114),
- char(116),
- char(0),
- char(105),
- char(110),
- char(116),
- char(0),
- char(108),
- char(111),
- char(110),
- char(103),
- char(0),
- char(117),
- char(108),
- char(111),
- char(110),
- char(103),
- char(0),
- char(102),
- char(108),
- char(111),
- char(97),
- char(116),
- char(0),
- char(100),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(0),
- char(118),
- char(111),
- char(105),
- char(100),
- char(0),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(101),
- char(114),
- char(65),
- char(114),
- char(114),
- char(97),
- char(121),
- char(0),
- char(98),
- char(116),
- char(80),
- char(104),
- char(121),
- char(115),
- char(105),
- char(99),
- char(115),
- char(83),
- char(121),
- char(115),
- char(116),
- char(101),
- char(109),
- char(0),
- char(76),
- char(105),
- char(115),
- char(116),
- char(66),
- char(97),
- char(115),
- char(101),
- char(0),
- char(98),
- char(116),
- char(86),
- char(101),
- char(99),
- char(116),
- char(111),
- char(114),
- char(51),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(86),
- char(101),
- char(99),
- char(116),
- char(111),
- char(114),
- char(51),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(97),
- char(116),
- char(114),
- char(105),
- char(120),
- char(51),
- char(120),
- char(51),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(97),
- char(116),
- char(114),
- char(105),
- char(120),
- char(51),
- char(120),
- char(51),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(97),
- char(110),
- char(115),
- char(102),
- char(111),
- char(114),
- char(109),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(66),
- char(118),
- char(104),
- char(83),
- char(117),
- char(98),
- char(116),
- char(114),
- char(101),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(79),
- char(112),
- char(116),
- char(105),
- char(109),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(79),
- char(112),
- char(116),
- char(105),
- char(109),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(81),
- char(117),
- char(97),
- char(110),
- char(116),
- char(105),
- char(122),
- char(101),
- char(100),
- char(66),
- char(118),
- char(104),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(116),
- char(97),
- char(116),
- char(105),
- char(99),
- char(80),
- char(108),
- char(97),
- char(110),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(110),
- char(97),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(115),
- char(105),
- char(116),
- char(105),
- char(111),
- char(110),
- char(65),
- char(110),
- char(100),
- char(82),
- char(97),
- char(100),
- char(105),
- char(117),
- char(115),
- char(0),
- char(98),
- char(116),
- char(77),
- char(117),
- char(108),
- char(116),
- char(105),
- char(83),
- char(112),
- char(104),
- char(101),
- char(114),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(104),
- char(111),
- char(114),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(104),
- char(111),
- char(114),
- char(116),
- char(73),
- char(110),
- char(116),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(84),
- char(114),
- char(105),
- char(112),
- char(108),
- char(101),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(104),
- char(97),
- char(114),
- char(73),
- char(110),
- char(100),
- char(101),
- char(120),
- char(84),
- char(114),
- char(105),
- char(112),
- char(108),
- char(101),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(77),
- char(101),
- char(115),
- char(104),
- char(80),
- char(97),
- char(114),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(116),
- char(114),
- char(105),
- char(100),
- char(105),
- char(110),
- char(103),
- char(77),
- char(101),
- char(115),
- char(104),
- char(73),
- char(110),
- char(116),
- char(101),
- char(114),
- char(102),
- char(97),
- char(99),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(77),
- char(97),
- char(112),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(99),
- char(97),
- char(108),
- char(101),
- char(100),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(109),
- char(112),
- char(111),
- char(117),
- char(110),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(67),
- char(104),
- char(105),
- char(108),
- char(100),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(109),
- char(112),
- char(111),
- char(117),
- char(110),
- char(100),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(121),
- char(108),
- char(105),
- char(110),
- char(100),
- char(101),
- char(114),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(97),
- char(112),
- char(115),
- char(117),
- char(108),
- char(101),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(84),
- char(114),
- char(105),
- char(97),
- char(110),
- char(103),
- char(108),
- char(101),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(73),
- char(109),
- char(112),
- char(97),
- char(99),
- char(116),
- char(77),
- char(101),
- char(115),
- char(104),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(118),
- char(101),
- char(120),
- char(72),
- char(117),
- char(108),
- char(108),
- char(83),
- char(104),
- char(97),
- char(112),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(108),
- char(108),
- char(105),
- char(115),
- char(105),
- char(111),
- char(110),
- char(79),
- char(98),
- char(106),
- char(101),
- char(99),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(68),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(115),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(68),
- char(121),
- char(110),
- char(97),
- char(109),
- char(105),
- char(99),
- char(115),
- char(87),
- char(111),
- char(114),
- char(108),
- char(100),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(116),
- char(97),
- char(99),
- char(116),
- char(83),
- char(111),
- char(108),
- char(118),
- char(101),
- char(114),
- char(73),
- char(110),
- char(102),
- char(111),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(73),
- char(110),
- char(102),
- char(111),
- char(49),
- char(0),
- char(98),
- char(116),
- char(84),
- char(121),
- char(112),
- char(101),
- char(100),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(66),
- char(111),
- char(100),
- char(121),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(50),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(50),
- char(80),
- char(111),
- char(105),
- char(110),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(72),
- char(105),
- char(110),
- char(103),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(111),
- char(117),
- char(98),
- char(108),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(72),
- char(105),
- char(110),
- char(103),
- char(101),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(67),
- char(111),
- char(110),
- char(101),
- char(84),
- char(119),
- char(105),
- char(115),
- char(116),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(101),
- char(110),
- char(101),
- char(114),
- char(105),
- char(99),
- char(54),
- char(68),
- char(111),
- char(102),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(71),
- char(101),
- char(110),
- char(101),
- char(114),
- char(105),
- char(99),
- char(54),
- char(68),
- char(111),
- char(102),
- char(83),
- char(112),
- char(114),
- char(105),
- char(110),
- char(103),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(108),
- char(105),
- char(100),
- char(101),
- char(114),
- char(67),
- char(111),
- char(110),
- char(115),
- char(116),
- char(114),
- char(97),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(77),
- char(97),
- char(116),
- char(101),
- char(114),
- char(105),
- char(97),
- char(108),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(78),
- char(111),
- char(100),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(76),
- char(105),
- char(110),
- char(107),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(97),
- char(99),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(84),
- char(101),
- char(116),
- char(114),
- char(97),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(82),
- char(105),
- char(103),
- char(105),
- char(100),
- char(65),
- char(110),
- char(99),
- char(104),
- char(111),
- char(114),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(67),
- char(111),
- char(110),
- char(102),
- char(105),
- char(103),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(80),
- char(111),
- char(115),
- char(101),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(67),
- char(108),
- char(117),
- char(115),
- char(116),
- char(101),
- char(114),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(74),
- char(111),
- char(105),
- char(110),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(98),
- char(116),
- char(83),
- char(111),
- char(102),
- char(116),
- char(66),
- char(111),
- char(100),
- char(121),
- char(70),
- char(108),
- char(111),
- char(97),
- char(116),
- char(68),
- char(97),
- char(116),
- char(97),
- char(0),
- char(0),
- char(0),
- char(84),
- char(76),
- char(69),
- char(78),
- char(1),
- char(0),
- char(1),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(8),
- char(0),
- char(0),
- char(0),
- char(16),
- char(0),
- char(48),
- char(0),
- char(16),
- char(0),
- char(16),
- char(0),
- char(32),
- char(0),
- char(48),
- char(0),
- char(96),
- char(0),
- char(64),
- char(0),
- char(-128),
- char(0),
- char(20),
- char(0),
- char(48),
- char(0),
- char(80),
- char(0),
- char(16),
- char(0),
- char(96),
- char(0),
- char(-112),
- char(0),
- char(16),
- char(0),
- char(56),
- char(0),
- char(56),
- char(0),
- char(20),
- char(0),
- char(72),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(8),
- char(0),
- char(4),
- char(0),
- char(56),
- char(0),
- char(32),
- char(0),
- char(80),
- char(0),
- char(72),
- char(0),
- char(96),
- char(0),
- char(80),
- char(0),
- char(32),
- char(0),
- char(64),
- char(0),
- char(64),
- char(0),
- char(16),
- char(0),
- char(72),
- char(0),
- char(80),
- char(0),
- char(-32),
- char(1),
- char(16),
- char(1),
- char(-72),
- char(0),
- char(-104),
- char(0),
- char(104),
- char(0),
- char(88),
- char(0),
- char(-8),
- char(1),
- char(-80),
- char(3),
- char(8),
- char(0),
- char(64),
- char(0),
- char(0),
- char(0),
- char(96),
- char(0),
- char(-128),
- char(0),
- char(104),
- char(1),
- char(-24),
- char(0),
- char(-32),
- char(0),
- char(8),
- char(1),
- char(104),
- char(1),
- char(-40),
- char(0),
- char(16),
- char(0),
- char(104),
- char(0),
- char(24),
- char(0),
- char(40),
- char(0),
- char(104),
- char(0),
- char(96),
- char(0),
- char(104),
- char(0),
- char(-56),
- char(0),
- char(104),
- char(1),
- char(112),
- char(0),
- char(-32),
- char(1),
- char(83),
- char(84),
- char(82),
- char(67),
- char(65),
- char(0),
- char(0),
- char(0),
- char(10),
- char(0),
- char(3),
- char(0),
- char(4),
- char(0),
- char(0),
- char(0),
- char(4),
- char(0),
- char(1),
- char(0),
- char(9),
- char(0),
- char(2),
- char(0),
- char(11),
- char(0),
- char(3),
- char(0),
- char(10),
- char(0),
- char(3),
- char(0),
- char(10),
- char(0),
- char(4),
- char(0),
- char(10),
- char(0),
- char(5),
- char(0),
- char(12),
- char(0),
- char(2),
- char(0),
- char(9),
- char(0),
- char(6),
- char(0),
- char(9),
- char(0),
- char(7),
- char(0),
- char(13),
- char(0),
- char(1),
- char(0),
- char(7),
- char(0),
- char(8),
- char(0),
- char(14),
- char(0),
- char(1),
- char(0),
- char(8),
- char(0),
- char(8),
- char(0),
- char(15),
- char(0),
- char(1),
- char(0),
- char(13),
- char(0),
- char(9),
- char(0),
- char(16),
- char(0),
- char(1),
- char(0),
- char(14),
- char(0),
- char(9),
- char(0),
- char(17),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(10),
- char(0),
- char(13),
- char(0),
- char(11),
- char(0),
- char(18),
- char(0),
- char(2),
- char(0),
- char(16),
- char(0),
- char(10),
- char(0),
- char(14),
- char(0),
- char(11),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(12),
- char(0),
- char(4),
- char(0),
- char(13),
- char(0),
- char(2),
- char(0),
- char(14),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(20),
- char(0),
- char(6),
- char(0),
- char(13),
- char(0),
- char(16),
- char(0),
- char(13),
- char(0),
- char(17),
- char(0),
- char(4),
- char(0),
- char(18),
- char(0),
- char(4),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(20),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(21),
- char(0),
- char(6),
- char(0),
- char(14),
- char(0),
- char(16),
- char(0),
- char(14),
- char(0),
- char(17),
- char(0),
- char(4),
- char(0),
- char(18),
- char(0),
- char(4),
- char(0),
- char(19),
- char(0),
- char(4),
- char(0),
- char(20),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(22),
- char(0),
- char(3),
- char(0),
- char(2),
- char(0),
- char(14),
- char(0),
- char(2),
- char(0),
- char(15),
- char(0),
- char(4),
- char(0),
- char(22),
- char(0),
- char(23),
- char(0),
- char(12),
- char(0),
- char(13),
- char(0),
- char(23),
- char(0),
- char(13),
- char(0),
- char(24),
- char(0),
- char(13),
- char(0),
- char(25),
- char(0),
- char(4),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(4),
- char(0),
- char(28),
- char(0),
- char(4),
- char(0),
- char(29),
- char(0),
- char(20),
- char(0),
- char(30),
- char(0),
- char(22),
- char(0),
- char(31),
- char(0),
- char(19),
- char(0),
- char(32),
- char(0),
- char(4),
- char(0),
- char(33),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(24),
- char(0),
- char(12),
- char(0),
- char(14),
- char(0),
- char(23),
- char(0),
- char(14),
- char(0),
- char(24),
- char(0),
- char(14),
- char(0),
- char(25),
- char(0),
- char(4),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(4),
- char(0),
- char(28),
- char(0),
- char(4),
- char(0),
- char(29),
- char(0),
- char(21),
- char(0),
- char(30),
- char(0),
- char(22),
- char(0),
- char(31),
- char(0),
- char(4),
- char(0),
- char(33),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(19),
- char(0),
- char(32),
- char(0),
- char(25),
- char(0),
- char(3),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(36),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(26),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(13),
- char(0),
- char(40),
- char(0),
- char(7),
- char(0),
- char(41),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(27),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(13),
- char(0),
- char(42),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(44),
- char(0),
- char(28),
- char(0),
- char(2),
- char(0),
- char(13),
- char(0),
- char(45),
- char(0),
- char(7),
- char(0),
- char(46),
- char(0),
- char(29),
- char(0),
- char(4),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(28),
- char(0),
- char(48),
- char(0),
- char(4),
- char(0),
- char(49),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(30),
- char(0),
- char(1),
- char(0),
- char(4),
- char(0),
- char(50),
- char(0),
- char(31),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(50),
- char(0),
- char(0),
- char(0),
- char(51),
- char(0),
- char(32),
- char(0),
- char(2),
- char(0),
- char(2),
- char(0),
- char(52),
- char(0),
- char(0),
- char(0),
- char(51),
- char(0),
- char(33),
- char(0),
- char(2),
- char(0),
- char(0),
- char(0),
- char(52),
- char(0),
- char(0),
- char(0),
- char(53),
- char(0),
- char(34),
- char(0),
- char(8),
- char(0),
- char(13),
- char(0),
- char(54),
- char(0),
- char(14),
- char(0),
- char(55),
- char(0),
- char(30),
- char(0),
- char(56),
- char(0),
- char(32),
- char(0),
- char(57),
- char(0),
- char(33),
- char(0),
- char(58),
- char(0),
- char(31),
- char(0),
- char(59),
- char(0),
- char(4),
- char(0),
- char(60),
- char(0),
- char(4),
- char(0),
- char(61),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(34),
- char(0),
- char(62),
- char(0),
- char(13),
- char(0),
- char(63),
- char(0),
- char(4),
- char(0),
- char(64),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(36),
- char(0),
- char(7),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(35),
- char(0),
- char(65),
- char(0),
- char(23),
- char(0),
- char(66),
- char(0),
- char(24),
- char(0),
- char(67),
- char(0),
- char(37),
- char(0),
- char(68),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(0),
- char(0),
- char(69),
- char(0),
- char(38),
- char(0),
- char(2),
- char(0),
- char(36),
- char(0),
- char(70),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(39),
- char(0),
- char(4),
- char(0),
- char(17),
- char(0),
- char(71),
- char(0),
- char(25),
- char(0),
- char(72),
- char(0),
- char(4),
- char(0),
- char(73),
- char(0),
- char(7),
- char(0),
- char(74),
- char(0),
- char(40),
- char(0),
- char(4),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(39),
- char(0),
- char(75),
- char(0),
- char(4),
- char(0),
- char(76),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(41),
- char(0),
- char(3),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(4),
- char(0),
- char(77),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(42),
- char(0),
- char(3),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(4),
- char(0),
- char(77),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(4),
- char(0),
- char(78),
- char(0),
- char(7),
- char(0),
- char(79),
- char(0),
- char(7),
- char(0),
- char(80),
- char(0),
- char(7),
- char(0),
- char(81),
- char(0),
- char(37),
- char(0),
- char(14),
- char(0),
- char(4),
- char(0),
- char(82),
- char(0),
- char(4),
- char(0),
- char(83),
- char(0),
- char(43),
- char(0),
- char(84),
- char(0),
- char(4),
- char(0),
- char(85),
- char(0),
- char(7),
- char(0),
- char(86),
- char(0),
- char(7),
- char(0),
- char(87),
- char(0),
- char(7),
- char(0),
- char(88),
- char(0),
- char(7),
- char(0),
- char(89),
- char(0),
- char(7),
- char(0),
- char(90),
- char(0),
- char(4),
- char(0),
- char(91),
- char(0),
- char(4),
- char(0),
- char(92),
- char(0),
- char(4),
- char(0),
- char(93),
- char(0),
- char(4),
- char(0),
- char(94),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(44),
- char(0),
- char(5),
- char(0),
- char(25),
- char(0),
- char(38),
- char(0),
- char(35),
- char(0),
- char(65),
- char(0),
- char(13),
- char(0),
- char(39),
- char(0),
- char(7),
- char(0),
- char(43),
- char(0),
- char(4),
- char(0),
- char(95),
- char(0),
- char(45),
- char(0),
- char(5),
- char(0),
- char(27),
- char(0),
- char(47),
- char(0),
- char(13),
- char(0),
- char(96),
- char(0),
- char(14),
- char(0),
- char(97),
- char(0),
- char(4),
- char(0),
- char(98),
- char(0),
- char(0),
- char(0),
- char(99),
- char(0),
- char(46),
- char(0),
- char(25),
- char(0),
- char(9),
- char(0),
- char(100),
- char(0),
- char(9),
- char(0),
- char(101),
- char(0),
- char(25),
- char(0),
- char(102),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(18),
- char(0),
- char(103),
- char(0),
- char(18),
- char(0),
- char(104),
- char(0),
- char(14),
- char(0),
- char(105),
- char(0),
- char(14),
- char(0),
- char(106),
- char(0),
- char(14),
- char(0),
- char(107),
- char(0),
- char(8),
- char(0),
- char(108),
- char(0),
- char(8),
- char(0),
- char(109),
- char(0),
- char(8),
- char(0),
- char(110),
- char(0),
- char(8),
- char(0),
- char(111),
- char(0),
- char(8),
- char(0),
- char(112),
- char(0),
- char(8),
- char(0),
- char(113),
- char(0),
- char(8),
- char(0),
- char(114),
- char(0),
- char(8),
- char(0),
- char(115),
- char(0),
- char(4),
- char(0),
- char(116),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(4),
- char(0),
- char(118),
- char(0),
- char(4),
- char(0),
- char(119),
- char(0),
- char(4),
- char(0),
- char(120),
- char(0),
- char(4),
- char(0),
- char(121),
- char(0),
- char(4),
- char(0),
- char(122),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(47),
- char(0),
- char(25),
- char(0),
- char(9),
- char(0),
- char(100),
- char(0),
- char(9),
- char(0),
- char(101),
- char(0),
- char(25),
- char(0),
- char(102),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(17),
- char(0),
- char(103),
- char(0),
- char(17),
- char(0),
- char(104),
- char(0),
- char(13),
- char(0),
- char(105),
- char(0),
- char(13),
- char(0),
- char(106),
- char(0),
- char(13),
- char(0),
- char(107),
- char(0),
- char(7),
- char(0),
- char(108),
- char(0),
- char(7),
- char(0),
- char(109),
- char(0),
- char(7),
- char(0),
- char(110),
- char(0),
- char(7),
- char(0),
- char(111),
- char(0),
- char(7),
- char(0),
- char(112),
- char(0),
- char(7),
- char(0),
- char(113),
- char(0),
- char(7),
- char(0),
- char(114),
- char(0),
- char(7),
- char(0),
- char(115),
- char(0),
- char(4),
- char(0),
- char(116),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(4),
- char(0),
- char(118),
- char(0),
- char(4),
- char(0),
- char(119),
- char(0),
- char(4),
- char(0),
- char(120),
- char(0),
- char(4),
- char(0),
- char(121),
- char(0),
- char(4),
- char(0),
- char(122),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(48),
- char(0),
- char(2),
- char(0),
- char(49),
- char(0),
- char(123),
- char(0),
- char(14),
- char(0),
- char(124),
- char(0),
- char(50),
- char(0),
- char(2),
- char(0),
- char(51),
- char(0),
- char(123),
- char(0),
- char(13),
- char(0),
- char(124),
- char(0),
- char(52),
- char(0),
- char(21),
- char(0),
- char(47),
- char(0),
- char(125),
- char(0),
- char(15),
- char(0),
- char(126),
- char(0),
- char(13),
- char(0),
- char(127),
- char(0),
- char(13),
- char(0),
- char(-128),
- char(0),
- char(13),
- char(0),
- char(-127),
- char(0),
- char(13),
- char(0),
- char(-126),
- char(0),
- char(13),
- char(0),
- char(124),
- char(0),
- char(13),
- char(0),
- char(-125),
- char(0),
- char(13),
- char(0),
- char(-124),
- char(0),
- char(13),
- char(0),
- char(-123),
- char(0),
- char(13),
- char(0),
- char(-122),
- char(0),
- char(7),
- char(0),
- char(-121),
- char(0),
- char(7),
- char(0),
- char(-120),
- char(0),
- char(7),
- char(0),
- char(-119),
- char(0),
- char(7),
- char(0),
- char(-118),
- char(0),
- char(7),
- char(0),
- char(-117),
- char(0),
- char(7),
- char(0),
- char(-116),
- char(0),
- char(7),
- char(0),
- char(-115),
- char(0),
- char(7),
- char(0),
- char(-114),
- char(0),
- char(7),
- char(0),
- char(-113),
- char(0),
- char(4),
- char(0),
- char(-112),
- char(0),
- char(53),
- char(0),
- char(22),
- char(0),
- char(46),
- char(0),
- char(125),
- char(0),
- char(16),
- char(0),
- char(126),
- char(0),
- char(14),
- char(0),
- char(127),
- char(0),
- char(14),
- char(0),
- char(-128),
- char(0),
- char(14),
- char(0),
- char(-127),
- char(0),
- char(14),
- char(0),
- char(-126),
- char(0),
- char(14),
- char(0),
- char(124),
- char(0),
- char(14),
- char(0),
- char(-125),
- char(0),
- char(14),
- char(0),
- char(-124),
- char(0),
- char(14),
- char(0),
- char(-123),
- char(0),
- char(14),
- char(0),
- char(-122),
- char(0),
- char(8),
- char(0),
- char(-121),
- char(0),
- char(8),
- char(0),
- char(-120),
- char(0),
- char(8),
- char(0),
- char(-119),
- char(0),
- char(8),
- char(0),
- char(-118),
- char(0),
- char(8),
- char(0),
- char(-117),
- char(0),
- char(8),
- char(0),
- char(-116),
- char(0),
- char(8),
- char(0),
- char(-115),
- char(0),
- char(8),
- char(0),
- char(-114),
- char(0),
- char(8),
- char(0),
- char(-113),
- char(0),
- char(4),
- char(0),
- char(-112),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(54),
- char(0),
- char(2),
- char(0),
- char(4),
- char(0),
- char(-111),
- char(0),
- char(4),
- char(0),
- char(-110),
- char(0),
- char(55),
- char(0),
- char(13),
- char(0),
- char(56),
- char(0),
- char(-109),
- char(0),
- char(56),
- char(0),
- char(-108),
- char(0),
- char(0),
- char(0),
- char(35),
- char(0),
- char(4),
- char(0),
- char(-107),
- char(0),
- char(4),
- char(0),
- char(-106),
- char(0),
- char(4),
- char(0),
- char(-105),
- char(0),
- char(4),
- char(0),
- char(-104),
- char(0),
- char(7),
- char(0),
- char(-103),
- char(0),
- char(7),
- char(0),
- char(-102),
- char(0),
- char(4),
- char(0),
- char(-101),
- char(0),
- char(4),
- char(0),
- char(-100),
- char(0),
- char(7),
- char(0),
- char(-99),
- char(0),
- char(4),
- char(0),
- char(-98),
- char(0),
- char(57),
- char(0),
- char(3),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(13),
- char(0),
- char(-96),
- char(0),
- char(13),
- char(0),
- char(-95),
- char(0),
- char(58),
- char(0),
- char(3),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(14),
- char(0),
- char(-96),
- char(0),
- char(14),
- char(0),
- char(-95),
- char(0),
- char(59),
- char(0),
- char(13),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(18),
- char(0),
- char(-94),
- char(0),
- char(18),
- char(0),
- char(-93),
- char(0),
- char(4),
- char(0),
- char(-92),
- char(0),
- char(4),
- char(0),
- char(-91),
- char(0),
- char(4),
- char(0),
- char(-90),
- char(0),
- char(7),
- char(0),
- char(-89),
- char(0),
- char(7),
- char(0),
- char(-88),
- char(0),
- char(7),
- char(0),
- char(-87),
- char(0),
- char(7),
- char(0),
- char(-86),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(60),
- char(0),
- char(13),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(4),
- char(0),
- char(-92),
- char(0),
- char(4),
- char(0),
- char(-91),
- char(0),
- char(4),
- char(0),
- char(-90),
- char(0),
- char(7),
- char(0),
- char(-89),
- char(0),
- char(7),
- char(0),
- char(-88),
- char(0),
- char(7),
- char(0),
- char(-87),
- char(0),
- char(7),
- char(0),
- char(-86),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(61),
- char(0),
- char(11),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(7),
- char(0),
- char(-82),
- char(0),
- char(7),
- char(0),
- char(-81),
- char(0),
- char(7),
- char(0),
- char(-80),
- char(0),
- char(7),
- char(0),
- char(-85),
- char(0),
- char(7),
- char(0),
- char(-84),
- char(0),
- char(7),
- char(0),
- char(-83),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(0),
- char(0),
- char(21),
- char(0),
- char(62),
- char(0),
- char(9),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(13),
- char(0),
- char(-78),
- char(0),
- char(13),
- char(0),
- char(-77),
- char(0),
- char(13),
- char(0),
- char(-76),
- char(0),
- char(13),
- char(0),
- char(-75),
- char(0),
- char(4),
- char(0),
- char(-74),
- char(0),
- char(4),
- char(0),
- char(-73),
- char(0),
- char(63),
- char(0),
- char(5),
- char(0),
- char(62),
- char(0),
- char(-72),
- char(0),
- char(4),
- char(0),
- char(-71),
- char(0),
- char(7),
- char(0),
- char(-70),
- char(0),
- char(7),
- char(0),
- char(-69),
- char(0),
- char(7),
- char(0),
- char(-68),
- char(0),
- char(64),
- char(0),
- char(9),
- char(0),
- char(55),
- char(0),
- char(-97),
- char(0),
- char(17),
- char(0),
- char(-94),
- char(0),
- char(17),
- char(0),
- char(-93),
- char(0),
- char(7),
- char(0),
- char(-78),
- char(0),
- char(7),
- char(0),
- char(-77),
- char(0),
- char(7),
- char(0),
- char(-76),
- char(0),
- char(7),
- char(0),
- char(-75),
- char(0),
- char(4),
- char(0),
- char(-74),
- char(0),
- char(4),
- char(0),
- char(-73),
- char(0),
- char(49),
- char(0),
- char(22),
- char(0),
- char(8),
- char(0),
- char(-67),
- char(0),
- char(8),
- char(0),
- char(-79),
- char(0),
- char(8),
- char(0),
- char(110),
- char(0),
- char(8),
- char(0),
- char(-66),
- char(0),
- char(8),
- char(0),
- char(112),
- char(0),
- char(8),
- char(0),
- char(-65),
- char(0),
- char(8),
- char(0),
- char(-64),
- char(0),
- char(8),
- char(0),
- char(-63),
- char(0),
- char(8),
- char(0),
- char(-62),
- char(0),
- char(8),
- char(0),
- char(-61),
- char(0),
- char(8),
- char(0),
- char(-60),
- char(0),
- char(8),
- char(0),
- char(-59),
- char(0),
- char(8),
- char(0),
- char(-58),
- char(0),
- char(8),
- char(0),
- char(-57),
- char(0),
- char(8),
- char(0),
- char(-56),
- char(0),
- char(8),
- char(0),
- char(-55),
- char(0),
- char(4),
- char(0),
- char(-54),
- char(0),
- char(4),
- char(0),
- char(-53),
- char(0),
- char(4),
- char(0),
- char(-52),
- char(0),
- char(4),
- char(0),
- char(-51),
- char(0),
- char(4),
- char(0),
- char(-50),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(51),
- char(0),
- char(22),
- char(0),
- char(7),
- char(0),
- char(-67),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(7),
- char(0),
- char(110),
- char(0),
- char(7),
- char(0),
- char(-66),
- char(0),
- char(7),
- char(0),
- char(112),
- char(0),
- char(7),
- char(0),
- char(-65),
- char(0),
- char(7),
- char(0),
- char(-64),
- char(0),
- char(7),
- char(0),
- char(-63),
- char(0),
- char(7),
- char(0),
- char(-62),
- char(0),
- char(7),
- char(0),
- char(-61),
- char(0),
- char(7),
- char(0),
- char(-60),
- char(0),
- char(7),
- char(0),
- char(-59),
- char(0),
- char(7),
- char(0),
- char(-58),
- char(0),
- char(7),
- char(0),
- char(-57),
- char(0),
- char(7),
- char(0),
- char(-56),
- char(0),
- char(7),
- char(0),
- char(-55),
- char(0),
- char(4),
- char(0),
- char(-54),
- char(0),
- char(4),
- char(0),
- char(-53),
- char(0),
- char(4),
- char(0),
- char(-52),
- char(0),
- char(4),
- char(0),
- char(-51),
- char(0),
- char(4),
- char(0),
- char(-50),
- char(0),
- char(0),
- char(0),
- char(37),
- char(0),
- char(65),
- char(0),
- char(4),
- char(0),
- char(7),
- char(0),
- char(-49),
- char(0),
- char(7),
- char(0),
- char(-48),
- char(0),
- char(7),
- char(0),
- char(-47),
- char(0),
- char(4),
- char(0),
- char(78),
- char(0),
- char(66),
- char(0),
- char(10),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(13),
- char(0),
- char(-45),
- char(0),
- char(13),
- char(0),
- char(-44),
- char(0),
- char(13),
- char(0),
- char(-43),
- char(0),
- char(13),
- char(0),
- char(-42),
- char(0),
- char(13),
- char(0),
- char(-41),
- char(0),
- char(7),
- char(0),
- char(-121),
- char(0),
- char(7),
- char(0),
- char(-40),
- char(0),
- char(4),
- char(0),
- char(-39),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(67),
- char(0),
- char(4),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-38),
- char(0),
- char(7),
- char(0),
- char(-37),
- char(0),
- char(4),
- char(0),
- char(-36),
- char(0),
- char(68),
- char(0),
- char(4),
- char(0),
- char(13),
- char(0),
- char(-41),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-35),
- char(0),
- char(7),
- char(0),
- char(-34),
- char(0),
- char(69),
- char(0),
- char(7),
- char(0),
- char(13),
- char(0),
- char(-33),
- char(0),
- char(65),
- char(0),
- char(-46),
- char(0),
- char(4),
- char(0),
- char(-32),
- char(0),
- char(7),
- char(0),
- char(-31),
- char(0),
- char(7),
- char(0),
- char(-30),
- char(0),
- char(7),
- char(0),
- char(-29),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(70),
- char(0),
- char(6),
- char(0),
- char(15),
- char(0),
- char(-28),
- char(0),
- char(13),
- char(0),
- char(-30),
- char(0),
- char(13),
- char(0),
- char(-27),
- char(0),
- char(56),
- char(0),
- char(-26),
- char(0),
- char(4),
- char(0),
- char(-25),
- char(0),
- char(7),
- char(0),
- char(-29),
- char(0),
- char(71),
- char(0),
- char(26),
- char(0),
- char(4),
- char(0),
- char(-24),
- char(0),
- char(7),
- char(0),
- char(-23),
- char(0),
- char(7),
- char(0),
- char(-79),
- char(0),
- char(7),
- char(0),
- char(-22),
- char(0),
- char(7),
- char(0),
- char(-21),
- char(0),
- char(7),
- char(0),
- char(-20),
- char(0),
- char(7),
- char(0),
- char(-19),
- char(0),
- char(7),
- char(0),
- char(-18),
- char(0),
- char(7),
- char(0),
- char(-17),
- char(0),
- char(7),
- char(0),
- char(-16),
- char(0),
- char(7),
- char(0),
- char(-15),
- char(0),
- char(7),
- char(0),
- char(-14),
- char(0),
- char(7),
- char(0),
- char(-13),
- char(0),
- char(7),
- char(0),
- char(-12),
- char(0),
- char(7),
- char(0),
- char(-11),
- char(0),
- char(7),
- char(0),
- char(-10),
- char(0),
- char(7),
- char(0),
- char(-9),
- char(0),
- char(7),
- char(0),
- char(-8),
- char(0),
- char(7),
- char(0),
- char(-7),
- char(0),
- char(7),
- char(0),
- char(-6),
- char(0),
- char(7),
- char(0),
- char(-5),
- char(0),
- char(4),
- char(0),
- char(-4),
- char(0),
- char(4),
- char(0),
- char(-3),
- char(0),
- char(4),
- char(0),
- char(-2),
- char(0),
- char(4),
- char(0),
- char(-1),
- char(0),
- char(4),
- char(0),
- char(117),
- char(0),
- char(72),
- char(0),
- char(12),
- char(0),
- char(15),
- char(0),
- char(0),
- char(1),
- char(15),
- char(0),
- char(1),
- char(1),
- char(15),
- char(0),
- char(2),
- char(1),
- char(13),
- char(0),
- char(3),
- char(1),
- char(13),
- char(0),
- char(4),
- char(1),
- char(7),
- char(0),
- char(5),
- char(1),
- char(4),
- char(0),
- char(6),
- char(1),
- char(4),
- char(0),
- char(7),
- char(1),
- char(4),
- char(0),
- char(8),
- char(1),
- char(4),
- char(0),
- char(9),
- char(1),
- char(7),
- char(0),
- char(-31),
- char(0),
- char(4),
- char(0),
- char(53),
- char(0),
- char(73),
- char(0),
- char(27),
- char(0),
- char(17),
- char(0),
- char(10),
- char(1),
- char(15),
- char(0),
- char(11),
- char(1),
- char(15),
- char(0),
- char(12),
- char(1),
- char(13),
- char(0),
- char(3),
- char(1),
- char(13),
- char(0),
- char(13),
- char(1),
- char(13),
- char(0),
- char(14),
- char(1),
- char(13),
- char(0),
- char(15),
- char(1),
- char(13),
- char(0),
- char(16),
- char(1),
- char(13),
- char(0),
- char(17),
- char(1),
- char(4),
- char(0),
- char(18),
- char(1),
- char(7),
- char(0),
- char(19),
- char(1),
- char(4),
- char(0),
- char(20),
- char(1),
- char(4),
- char(0),
- char(21),
- char(1),
- char(4),
- char(0),
- char(22),
- char(1),
- char(7),
- char(0),
- char(23),
- char(1),
- char(7),
- char(0),
- char(24),
- char(1),
- char(4),
- char(0),
- char(25),
- char(1),
- char(4),
- char(0),
- char(26),
- char(1),
- char(7),
- char(0),
- char(27),
- char(1),
- char(7),
- char(0),
- char(28),
- char(1),
- char(7),
- char(0),
- char(29),
- char(1),
- char(7),
- char(0),
- char(30),
- char(1),
- char(7),
- char(0),
- char(31),
- char(1),
- char(7),
- char(0),
- char(32),
- char(1),
- char(4),
- char(0),
- char(33),
- char(1),
- char(4),
- char(0),
- char(34),
- char(1),
- char(4),
- char(0),
- char(35),
- char(1),
- char(74),
- char(0),
- char(12),
- char(0),
- char(9),
- char(0),
- char(36),
- char(1),
- char(9),
- char(0),
- char(37),
- char(1),
- char(13),
- char(0),
- char(38),
- char(1),
- char(7),
- char(0),
- char(39),
- char(1),
- char(7),
- char(0),
- char(-63),
- char(0),
- char(7),
- char(0),
- char(40),
- char(1),
- char(4),
- char(0),
- char(41),
- char(1),
- char(13),
- char(0),
- char(42),
- char(1),
- char(4),
- char(0),
- char(43),
- char(1),
- char(4),
- char(0),
- char(44),
- char(1),
- char(4),
- char(0),
- char(45),
- char(1),
- char(4),
- char(0),
- char(53),
- char(0),
- char(75),
- char(0),
- char(19),
- char(0),
- char(47),
- char(0),
- char(125),
- char(0),
- char(72),
- char(0),
- char(46),
- char(1),
- char(65),
- char(0),
- char(47),
- char(1),
- char(66),
- char(0),
- char(48),
- char(1),
- char(67),
- char(0),
- char(49),
- char(1),
- char(68),
- char(0),
- char(50),
- char(1),
- char(69),
- char(0),
- char(51),
- char(1),
- char(70),
- char(0),
- char(52),
- char(1),
- char(73),
- char(0),
- char(53),
- char(1),
- char(74),
- char(0),
- char(54),
- char(1),
- char(4),
- char(0),
- char(55),
- char(1),
- char(4),
- char(0),
- char(21),
- char(1),
- char(4),
- char(0),
- char(56),
- char(1),
- char(4),
- char(0),
- char(57),
- char(1),
- char(4),
- char(0),
- char(58),
- char(1),
- char(4),
- char(0),
- char(59),
- char(1),
- char(4),
- char(0),
- char(60),
- char(1),
- char(4),
- char(0),
- char(61),
- char(1),
- char(71),
- char(0),
- char(62),
- char(1),
-};
-int b3s_bulletDNAlen64 = sizeof(b3s_bulletDNAstr64);
diff --git a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h b/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
deleted file mode 100644
index d9e153e238..0000000000
--- a/thirdparty/bullet/Bullet3Serialize/Bullet2FileLoader/b3Serializer.h
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef B3_SERIALIZER_H
-#define B3_SERIALIZER_H
-
-#include "Bullet3Common/b3Scalar.h" // has definitions like B3_FORCE_INLINE
-#include "Bullet3Common/b3StackAlloc.h"
-#include "Bullet3Common/b3HashMap.h"
-
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-
-extern char b3s_bulletDNAstr[];
-extern int b3s_bulletDNAlen;
-extern char b3s_bulletDNAstr64[];
-extern int b3s_bulletDNAlen64;
-
-B3_FORCE_INLINE int b3StrLen(const char* str)
-{
- if (!str)
- return (0);
- int len = 0;
-
- while (*str != 0)
- {
- str++;
- len++;
- }
-
- return len;
-}
-
-class b3Chunk
-{
-public:
- int m_chunkCode;
- int m_length;
- void* m_oldPtr;
- int m_dna_nr;
- int m_number;
-};
-
-enum b3SerializationFlags
-{
- B3_SERIALIZE_NO_BVH = 1,
- B3_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
- B3_SERIALIZE_NO_DUPLICATE_ASSERT = 4
-};
-
-class b3Serializer
-{
-public:
- virtual ~b3Serializer() {}
-
- virtual const unsigned char* getBufferPointer() const = 0;
-
- virtual int getCurrentBufferSize() const = 0;
-
- virtual b3Chunk* allocate(size_t size, int numElements) = 0;
-
- virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
-
- virtual void* findPointer(void* oldPtr) = 0;
-
- virtual void* getUniquePointer(void* oldPtr) = 0;
-
- virtual void startSerialization() = 0;
-
- virtual void finishSerialization() = 0;
-
- virtual const char* findNameForPointer(const void* ptr) const = 0;
-
- virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
-
- virtual void serializeName(const char* ptr) = 0;
-
- virtual int getSerializationFlags() const = 0;
-
- virtual void setSerializationFlags(int flags) = 0;
-};
-
-#define B3_HEADER_LENGTH 12
-#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
-#define B3_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
-#else
-#define B3_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
-#endif
-
-#define B3_SOFTBODY_CODE B3_MAKE_ID('S', 'B', 'D', 'Y')
-#define B3_COLLISIONOBJECT_CODE B3_MAKE_ID('C', 'O', 'B', 'J')
-#define B3_RIGIDBODY_CODE B3_MAKE_ID('R', 'B', 'D', 'Y')
-#define B3_CONSTRAINT_CODE B3_MAKE_ID('C', 'O', 'N', 'S')
-#define B3_BOXSHAPE_CODE B3_MAKE_ID('B', 'O', 'X', 'S')
-#define B3_QUANTIZED_BVH_CODE B3_MAKE_ID('Q', 'B', 'V', 'H')
-#define B3_TRIANLGE_INFO_MAP B3_MAKE_ID('T', 'M', 'A', 'P')
-#define B3_SHAPE_CODE B3_MAKE_ID('S', 'H', 'A', 'P')
-#define B3_ARRAY_CODE B3_MAKE_ID('A', 'R', 'A', 'Y')
-#define B3_SBMATERIAL_CODE B3_MAKE_ID('S', 'B', 'M', 'T')
-#define B3_SBNODE_CODE B3_MAKE_ID('S', 'B', 'N', 'D')
-#define B3_DYNAMICSWORLD_CODE B3_MAKE_ID('D', 'W', 'L', 'D')
-#define B3_DNA_CODE B3_MAKE_ID('D', 'N', 'A', '1')
-
-struct b3PointerUid
-{
- union {
- void* m_ptr;
- int m_uniqueIds[2];
- };
-};
-
-///The b3DefaultSerializer is the main Bullet serialization class.
-///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
-class b3DefaultSerializer : public b3Serializer
-{
- b3AlignedObjectArray<char*> mTypes;
- b3AlignedObjectArray<short*> mStructs;
- b3AlignedObjectArray<short> mTlens;
- b3HashMap<b3HashInt, int> mStructReverse;
- b3HashMap<b3HashString, int> mTypeLookup;
-
- b3HashMap<b3HashPtr, void*> m_chunkP;
-
- b3HashMap<b3HashPtr, const char*> m_nameMap;
-
- b3HashMap<b3HashPtr, b3PointerUid> m_uniquePointers;
- int m_uniqueIdGenerator;
-
- int m_totalSize;
- unsigned char* m_buffer;
- int m_currentSize;
- void* m_dna;
- int m_dnaLength;
-
- int m_serializationFlags;
-
- b3AlignedObjectArray<b3Chunk*> m_chunkPtrs;
-
-protected:
- virtual void* findPointer(void* oldPtr)
- {
- void** ptr = m_chunkP.find(oldPtr);
- if (ptr && *ptr)
- return *ptr;
- return 0;
- }
-
- void writeDNA()
- {
- b3Chunk* dnaChunk = allocate(m_dnaLength, 1);
- memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
- finalizeChunk(dnaChunk, "DNA1", B3_DNA_CODE, m_dna);
- }
-
- int getReverseType(const char* type) const
- {
- b3HashString key(type);
- const int* valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
-
- return -1;
- }
-
- void initDNA(const char* bdnaOrg, int dnalen)
- {
- ///was already initialized
- if (m_dna)
- return;
-
- int littleEndian = 1;
- littleEndian = ((char*)&littleEndian)[0];
-
- m_dna = b3AlignedAlloc(dnalen, 16);
- memcpy(m_dna, bdnaOrg, dnalen);
- m_dnaLength = dnalen;
-
- int* intPtr = 0;
- short* shtPtr = 0;
- char* cp = 0;
- int dataLen = 0;
- intPtr = (int*)m_dna;
-
- /*
- SDNA (4 bytes) (magic number)
- NAME (4 bytes)
- <nr> (4 bytes) amount of names (int)
- <string>
- <string>
- */
-
- if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
- {
- // skip ++ NAME
- intPtr++;
- intPtr++;
- }
-
- // Parse names
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
-
- dataLen = *intPtr;
-
- intPtr++;
-
- cp = (char*)intPtr;
- int i;
- for (i = 0; i < dataLen; i++)
- {
- while (*cp) cp++;
- cp++;
- }
- cp = b3AlignPointer(cp, 4);
-
- /*
- TYPE (4 bytes)
- <nr> amount of types (int)
- <string>
- <string>
- */
-
- intPtr = (int*)cp;
- b3Assert(strncmp(cp, "TYPE", 4) == 0);
- intPtr++;
-
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
-
- dataLen = *intPtr;
- intPtr++;
-
- cp = (char*)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp) cp++;
- cp++;
- }
-
- cp = b3AlignPointer(cp, 4);
-
- /*
- TLEN (4 bytes)
- <len> (short) the lengths of types
- <len>
- */
-
- // Parse type lens
- intPtr = (int*)cp;
- b3Assert(strncmp(cp, "TLEN", 4) == 0);
- intPtr++;
-
- dataLen = (int)mTypes.size();
-
- shtPtr = (short*)intPtr;
- for (i = 0; i < dataLen; i++, shtPtr++)
- {
- if (!littleEndian)
- shtPtr[0] = b3SwapEndian(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
-
- if (dataLen & 1) shtPtr++;
-
- /*
- STRC (4 bytes)
- <nr> amount of structs (int)
- <typenr>
- <nr_of_elems>
- <typenr>
- <namenr>
- <typenr>
- <namenr>
- */
-
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- b3Assert(strncmp(cp, "STRC", 4) == 0);
- intPtr++;
-
- if (!littleEndian)
- *intPtr = b3SwapEndian(*intPtr);
- dataLen = *intPtr;
- intPtr++;
-
- shtPtr = (short*)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mStructs.push_back(shtPtr);
-
- if (!littleEndian)
- {
- shtPtr[0] = b3SwapEndian(shtPtr[0]);
- shtPtr[1] = b3SwapEndian(shtPtr[1]);
-
- int len = shtPtr[1];
- shtPtr += 2;
-
- for (int a = 0; a < len; a++, shtPtr += 2)
- {
- shtPtr[0] = b3SwapEndian(shtPtr[0]);
- shtPtr[1] = b3SwapEndian(shtPtr[1]);
- }
- }
- else
- {
- shtPtr += (2 * shtPtr[1]) + 2;
- }
- }
-
- // build reverse lookups
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short* strc = mStructs.at(i);
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(b3HashString(mTypes[strc[0]]), i);
- }
- }
-
-public:
- b3DefaultSerializer(int totalSize = 0)
- : m_totalSize(totalSize),
- m_currentSize(0),
- m_dna(0),
- m_dnaLength(0),
- m_serializationFlags(0)
- {
- m_buffer = m_totalSize ? (unsigned char*)b3AlignedAlloc(totalSize, 16) : 0;
-
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
-#ifdef B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
-#if _WIN64
- initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
-#else
- b3Assert(0);
-#endif
- }
- else
- {
-#ifndef _WIN64
- initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
-#else
- b3Assert(0);
-#endif
- }
-
-#else //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- initDNA((const char*)b3s_bulletDNAstr64, b3s_bulletDNAlen64);
- }
- else
- {
- initDNA((const char*)b3s_bulletDNAstr, b3s_bulletDNAlen);
- }
-#endif //B3_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- }
-
- virtual ~b3DefaultSerializer()
- {
- if (m_buffer)
- b3AlignedFree(m_buffer);
- if (m_dna)
- b3AlignedFree(m_dna);
- }
-
- void writeHeader(unsigned char* buffer) const
- {
-#ifdef B3_USE_DOUBLE_PRECISION
- memcpy(buffer, "BULLETd", 7);
-#else
- memcpy(buffer, "BULLETf", 7);
-#endif //B3_USE_DOUBLE_PRECISION
-
- int littleEndian = 1;
- littleEndian = ((char*)&littleEndian)[0];
-
- if (sizeof(void*) == 8)
- {
- buffer[7] = '-';
- }
- else
- {
- buffer[7] = '_';
- }
-
- if (littleEndian)
- {
- buffer[8] = 'v';
- }
- else
- {
- buffer[8] = 'V';
- }
-
- buffer[9] = '2';
- buffer[10] = '8';
- buffer[11] = '1';
- }
-
- virtual void startSerialization()
- {
- m_uniqueIdGenerator = 1;
- if (m_totalSize)
- {
- unsigned char* buffer = internalAlloc(B3_HEADER_LENGTH);
- writeHeader(buffer);
- }
- }
-
- virtual void finishSerialization()
- {
- writeDNA();
-
- //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
- int mysize = 0;
- if (!m_totalSize)
- {
- if (m_buffer)
- b3AlignedFree(m_buffer);
-
- m_currentSize += B3_HEADER_LENGTH;
- m_buffer = (unsigned char*)b3AlignedAlloc(m_currentSize, 16);
-
- unsigned char* currentPtr = m_buffer;
- writeHeader(m_buffer);
- currentPtr += B3_HEADER_LENGTH;
- mysize += B3_HEADER_LENGTH;
- for (int i = 0; i < m_chunkPtrs.size(); i++)
- {
- int curLength = sizeof(b3Chunk) + m_chunkPtrs[i]->m_length;
- memcpy(currentPtr, m_chunkPtrs[i], curLength);
- b3AlignedFree(m_chunkPtrs[i]);
- currentPtr += curLength;
- mysize += curLength;
- }
- }
-
- mTypes.clear();
- mStructs.clear();
- mTlens.clear();
- mStructReverse.clear();
- mTypeLookup.clear();
- m_chunkP.clear();
- m_nameMap.clear();
- m_uniquePointers.clear();
- m_chunkPtrs.clear();
- }
-
- virtual void* getUniquePointer(void* oldPtr)
- {
- if (!oldPtr)
- return 0;
-
- b3PointerUid* uptr = (b3PointerUid*)m_uniquePointers.find(oldPtr);
- if (uptr)
- {
- return uptr->m_ptr;
- }
- m_uniqueIdGenerator++;
-
- b3PointerUid uid;
- uid.m_uniqueIds[0] = m_uniqueIdGenerator;
- uid.m_uniqueIds[1] = m_uniqueIdGenerator;
- m_uniquePointers.insert(oldPtr, uid);
- return uid.m_ptr;
- }
-
- virtual const unsigned char* getBufferPointer() const
- {
- return m_buffer;
- }
-
- virtual int getCurrentBufferSize() const
- {
- return m_currentSize;
- }
-
- virtual void finalizeChunk(b3Chunk* chunk, const char* structType, int chunkCode, void* oldPtr)
- {
- if (!(m_serializationFlags & B3_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- b3Assert(!findPointer(oldPtr));
- }
-
- chunk->m_dna_nr = getReverseType(structType);
-
- chunk->m_chunkCode = chunkCode;
-
- void* uniquePtr = getUniquePointer(oldPtr);
-
- m_chunkP.insert(oldPtr, uniquePtr); //chunk->m_oldPtr);
- chunk->m_oldPtr = uniquePtr; //oldPtr;
- }
-
- virtual unsigned char* internalAlloc(size_t size)
- {
- unsigned char* ptr = 0;
-
- if (m_totalSize)
- {
- ptr = m_buffer + m_currentSize;
- m_currentSize += int(size);
- b3Assert(m_currentSize < m_totalSize);
- }
- else
- {
- ptr = (unsigned char*)b3AlignedAlloc(size, 16);
- m_currentSize += int(size);
- }
- return ptr;
- }
-
- virtual b3Chunk* allocate(size_t size, int numElements)
- {
- unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(b3Chunk));
-
- unsigned char* data = ptr + sizeof(b3Chunk);
-
- b3Chunk* chunk = (b3Chunk*)ptr;
- chunk->m_chunkCode = 0;
- chunk->m_oldPtr = data;
- chunk->m_length = int(size) * numElements;
- chunk->m_number = numElements;
-
- m_chunkPtrs.push_back(chunk);
-
- return chunk;
- }
-
- virtual const char* findNameForPointer(const void* ptr) const
- {
- const char* const* namePtr = m_nameMap.find(ptr);
- if (namePtr && *namePtr)
- return *namePtr;
- return 0;
- }
-
- virtual void registerNameForPointer(const void* ptr, const char* name)
- {
- m_nameMap.insert(ptr, name);
- }
-
- virtual void serializeName(const char* name)
- {
- if (name)
- {
- //don't serialize name twice
- if (findPointer((void*)name))
- return;
-
- int len = b3StrLen(name);
- if (len)
- {
- int newLen = len + 1;
- int padding = ((newLen + 3) & ~3) - newLen;
- newLen += padding;
-
- //serialize name string now
- b3Chunk* chunk = allocate(sizeof(char), newLen);
- char* destinationName = (char*)chunk->m_oldPtr;
- for (int i = 0; i < len; i++)
- {
- destinationName[i] = name[i];
- }
- destinationName[len] = 0;
- finalizeChunk(chunk, "char", B3_ARRAY_CODE, (void*)name);
- }
- }
- }
-
- virtual int getSerializationFlags() const
- {
- return m_serializationFlags;
- }
-
- virtual void setSerializationFlags(int flags)
- {
- m_serializationFlags = flags;
- }
-};
-
-#endif //B3_SERIALIZER_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
deleted file mode 100644
index ec6fe9f4d8..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-
-//Bullet Continuous Collision Detection and Physics Library
-//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-//
-// btAxisSweep3
-//
-// Copyright (c) 2006 Simon Hobbs
-//
-// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-#include "btAxisSweep3.h"
-
-btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
- : btAxisSweep3Internal<unsigned short int>(worldAabbMin, worldAabbMax, 0xfffe, 0xffff, maxHandles, pairCache, disableRaycastAccelerator)
-{
- // 1 handle is reserved as sentinel
- btAssert(maxHandles > 1 && maxHandles < 32767);
-}
-
-bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
- : btAxisSweep3Internal<unsigned int>(worldAabbMin, worldAabbMax, 0xfffffffe, 0x7fffffff, maxHandles, pairCache, disableRaycastAccelerator)
-{
- // 1 handle is reserved as sentinel
- btAssert(maxHandles > 1 && maxHandles < 2147483647);
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
deleted file mode 100644
index 1e42f25f3b..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//Bullet Continuous Collision Detection and Physics Library
-//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-//
-// btAxisSweep3.h
-//
-// Copyright (c) 2006 Simon Hobbs
-//
-// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-
-#ifndef BT_AXIS_SWEEP_3_H
-#define BT_AXIS_SWEEP_3_H
-
-#include "LinearMath/btVector3.h"
-#include "btOverlappingPairCache.h"
-#include "btBroadphaseInterface.h"
-#include "btBroadphaseProxy.h"
-#include "btOverlappingPairCallback.h"
-#include "btDbvtBroadphase.h"
-#include "btAxisSweep3Internal.h"
-
-/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
-/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
-/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
-class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
-{
-public:
- btAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
-};
-
-/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
-/// This comes at the cost of more memory per handle, and a bit slower performance.
-/// It uses arrays rather then lists for storage of the 3 axis.
-class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
-{
-public:
- bt32BitAxisSweep3(const btVector3& worldAabbMin, const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
-};
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
deleted file mode 100644
index 2ee35528fd..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3Internal.h
+++ /dev/null
@@ -1,954 +0,0 @@
-//Bullet Continuous Collision Detection and Physics Library
-//Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-//
-// btAxisSweep3.h
-//
-// Copyright (c) 2006 Simon Hobbs
-//
-// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
-//
-// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
-//
-// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-//
-// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-//
-// 3. This notice may not be removed or altered from any source distribution.
-
-#ifndef BT_AXIS_SWEEP_3_INTERNAL_H
-#define BT_AXIS_SWEEP_3_INTERNAL_H
-
-#include "LinearMath/btVector3.h"
-#include "btOverlappingPairCache.h"
-#include "btBroadphaseInterface.h"
-#include "btBroadphaseProxy.h"
-#include "btOverlappingPairCallback.h"
-#include "btDbvtBroadphase.h"
-
-//#define DEBUG_BROADPHASE 1
-#define USE_OVERLAP_TEST_ON_REMOVES 1
-
-/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
-/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
-/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
-template <typename BP_FP_INT_TYPE>
-class btAxisSweep3Internal : public btBroadphaseInterface
-{
-protected:
- BP_FP_INT_TYPE m_bpHandleMask;
- BP_FP_INT_TYPE m_handleSentinel;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- class Edge
- {
- public:
- BP_FP_INT_TYPE m_pos; // low bit is min/max
- BP_FP_INT_TYPE m_handle;
-
- BP_FP_INT_TYPE IsMax() const { return static_cast<BP_FP_INT_TYPE>(m_pos & 1); }
- };
-
-public:
- class Handle : public btBroadphaseProxy
- {
- public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- // indexes into the edge arrays
- BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3]; // 6 * 2 = 12
- // BP_FP_INT_TYPE m_uniqueId;
- btBroadphaseProxy* m_dbvtProxy; //for faster raycast
- //void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
-
- SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) { m_minEdges[0] = next; }
- SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const { return m_minEdges[0]; }
- }; // 24 bytes + 24 for Edge structures = 44 bytes total per entry
-
-protected:
- btVector3 m_worldAabbMin; // overall system bounds
- btVector3 m_worldAabbMax; // overall system bounds
-
- btVector3 m_quantize; // scaling factor for quantization
-
- BP_FP_INT_TYPE m_numHandles; // number of active handles
- BP_FP_INT_TYPE m_maxHandles; // max number of handles
- Handle* m_pHandles; // handles pool
-
- BP_FP_INT_TYPE m_firstFreeHandle; // free handles list
-
- Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
- void* m_pEdgesRawPtr[3];
-
- btOverlappingPairCache* m_pairCache;
-
- ///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
- btOverlappingPairCallback* m_userPairCallback;
-
- bool m_ownsPairCache;
-
- int m_invalidPair;
-
- ///additional dynamic aabb structure, used to accelerate ray cast queries.
- ///can be disabled using a optional argument in the constructor
- btDbvtBroadphase* m_raycastAccelerator;
- btOverlappingPairCache* m_nullPairCache;
-
- // allocation/deallocation
- BP_FP_INT_TYPE allocHandle();
- void freeHandle(BP_FP_INT_TYPE handle);
-
- bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1);
-
-#ifdef DEBUG_BROADPHASE
- void debugPrintAxis(int axis, bool checkCardinality = true);
-#endif //DEBUG_BROADPHASE
-
- //Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
- //void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
-
- void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
- void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps);
-
-public:
- btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
-
- virtual ~btAxisSweep3Internal();
-
- BP_FP_INT_TYPE getNumHandles() const
- {
- return m_numHandles;
- }
-
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
-
- BP_FP_INT_TYPE addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- void removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher);
- void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const { return m_pHandles + index; }
-
- virtual void resetPool(btDispatcher* dispatcher);
-
- void processAllOverlappingPairs(btOverlapCallback* callback);
-
- //Broadphase Interface
- virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
- void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
- ///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
- void unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
-
- bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
-
- btOverlappingPairCache* getOverlappingPairCache()
- {
- return m_pairCache;
- }
- const btOverlappingPairCache* getOverlappingPairCache() const
- {
- return m_pairCache;
- }
-
- void setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
- {
- m_userPairCallback = pairCallback;
- }
- const btOverlappingPairCallback* getOverlappingPairUserCallback() const
- {
- return m_userPairCallback;
- }
-
- ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
- ///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- aabbMin = m_worldAabbMin;
- aabbMax = m_worldAabbMax;
- }
-
- virtual void printStats()
- {
- /* printf("btAxisSweep3.h\n");
- printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
- printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
- m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
- */
- }
-};
-
-////////////////////////////////////////////////////////////////////
-
-#ifdef DEBUG_BROADPHASE
-#include <stdio.h>
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
-{
- int numEdges = m_pHandles[0].m_maxEdges[axis];
- printf("SAP Axis %d, numEdges=%d\n", axis, numEdges);
-
- int i;
- for (i = 0; i < numEdges + 1; i++)
- {
- Edge* pEdge = m_pEdges[axis] + i;
- Handle* pHandlePrev = getHandle(pEdge->m_handle);
- int handleIndex = pEdge->IsMax() ? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
- char beginOrEnd;
- beginOrEnd = pEdge->IsMax() ? 'E' : 'B';
- printf(" [%c,h=%d,p=%x,i=%d]\n", beginOrEnd, pEdge->m_handle, pEdge->m_pos, handleIndex);
- }
-
- if (checkCardinality)
- btAssert(numEdges == m_numHandles * 2 + 1);
-}
-#endif //DEBUG_BROADPHASE
-
-template <typename BP_FP_INT_TYPE>
-btBroadphaseProxy* btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
-{
- (void)shapeType;
- BP_FP_INT_TYPE handleId = addHandle(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
-
- Handle* handle = getHandle(handleId);
-
- if (m_raycastAccelerator)
- {
- btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask, dispatcher);
- handle->m_dbvtProxy = rayProxy;
- }
- return handle;
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
-{
- Handle* handle = static_cast<Handle*>(proxy);
- if (m_raycastAccelerator)
- m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy, dispatcher);
- removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
-{
- Handle* handle = static_cast<Handle*>(proxy);
- handle->m_aabbMin = aabbMin;
- handle->m_aabbMax = aabbMax;
- updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax, dispatcher);
- if (m_raycastAccelerator)
- m_raycastAccelerator->setAabb(handle->m_dbvtProxy, aabbMin, aabbMax, dispatcher);
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- if (m_raycastAccelerator)
- {
- m_raycastAccelerator->rayTest(rayFrom, rayTo, rayCallback, aabbMin, aabbMax);
- }
- else
- {
- //choose axis?
- BP_FP_INT_TYPE axis = 0;
- //for each proxy
- for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
- {
- if (m_pEdges[axis][i].IsMax())
- {
- rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
- }
- }
- }
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
-{
- if (m_raycastAccelerator)
- {
- m_raycastAccelerator->aabbTest(aabbMin, aabbMax, callback);
- }
- else
- {
- //choose axis?
- BP_FP_INT_TYPE axis = 0;
- //for each proxy
- for (BP_FP_INT_TYPE i = 1; i < m_numHandles * 2 + 1; i++)
- {
- if (m_pEdges[axis][i].IsMax())
- {
- Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
- if (TestAabbAgainstAabb2(aabbMin, aabbMax, handle->m_aabbMin, handle->m_aabbMax))
- {
- callback.process(handle);
- }
- }
- }
- }
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
-{
- Handle* pHandle = static_cast<Handle*>(proxy);
- aabbMin = pHandle->m_aabbMin;
- aabbMax = pHandle->m_aabbMax;
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
-{
- Handle* pHandle = static_cast<Handle*>(proxy);
-
- unsigned short vecInMin[3];
- unsigned short vecInMax[3];
-
- vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos;
- vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos + 1;
- vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos;
- vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos + 1;
- vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos;
- vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos + 1;
-
- aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()), (btScalar)(vecInMin[1]) / (m_quantize.getY()), (btScalar)(vecInMin[2]) / (m_quantize.getZ()));
- aabbMin += m_worldAabbMin;
-
- aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()), (btScalar)(vecInMax[1]) / (m_quantize.getY()), (btScalar)(vecInMax[2]) / (m_quantize.getZ()));
- aabbMax += m_worldAabbMin;
-}
-
-template <typename BP_FP_INT_TYPE>
-btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin, const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
- : m_bpHandleMask(handleMask),
- m_handleSentinel(handleSentinel),
- m_pairCache(pairCache),
- m_userPairCallback(0),
- m_ownsPairCache(false),
- m_invalidPair(0),
- m_raycastAccelerator(0)
-{
- BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles + 1); //need to add one sentinel handle
-
- if (!m_pairCache)
- {
- void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
- m_pairCache = new (ptr) btHashedOverlappingPairCache();
- m_ownsPairCache = true;
- }
-
- if (!disableRaycastAccelerator)
- {
- m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache), 16)) btNullPairCache();
- m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase), 16)) btDbvtBroadphase(m_nullPairCache); //m_pairCache);
- m_raycastAccelerator->m_deferedcollide = true; //don't add/remove pairs
- }
-
- //btAssert(bounds.HasVolume());
-
- // init bounds
- m_worldAabbMin = worldAabbMin;
- m_worldAabbMax = worldAabbMax;
-
- btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
-
- BP_FP_INT_TYPE maxInt = m_handleSentinel;
-
- m_quantize = btVector3(btScalar(maxInt), btScalar(maxInt), btScalar(maxInt)) / aabbSize;
-
- // allocate handles buffer, using btAlignedAlloc, and put all handles on free list
- m_pHandles = new Handle[maxHandles];
-
- m_maxHandles = maxHandles;
- m_numHandles = 0;
-
- // handle 0 is reserved as the null index, and is also used as the sentinel
- m_firstFreeHandle = 1;
- {
- for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
- m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
- m_pHandles[maxHandles - 1].SetNextFree(0);
- }
-
- {
- // allocate edge buffers
- for (int i = 0; i < 3; i++)
- {
- m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge) * maxHandles * 2, 16);
- m_pEdges[i] = new (m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
- }
- }
- //removed overlap management
-
- // make boundary sentinels
-
- m_pHandles[0].m_clientObject = 0;
-
- for (int axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_minEdges[axis] = 0;
- m_pHandles[0].m_maxEdges[axis] = 1;
-
- m_pEdges[axis][0].m_pos = 0;
- m_pEdges[axis][0].m_handle = 0;
- m_pEdges[axis][1].m_pos = m_handleSentinel;
- m_pEdges[axis][1].m_handle = 0;
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
- }
-}
-
-template <typename BP_FP_INT_TYPE>
-btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
-{
- if (m_raycastAccelerator)
- {
- m_nullPairCache->~btOverlappingPairCache();
- btAlignedFree(m_nullPairCache);
- m_raycastAccelerator->~btDbvtBroadphase();
- btAlignedFree(m_raycastAccelerator);
- }
-
- for (int i = 2; i >= 0; i--)
- {
- btAlignedFree(m_pEdgesRawPtr[i]);
- }
- delete[] m_pHandles;
-
- if (m_ownsPairCache)
- {
- m_pairCache->~btOverlappingPairCache();
- btAlignedFree(m_pairCache);
- }
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
-{
-#ifdef OLD_CLAMPING_METHOD
- ///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
- ///see http://code.google.com/p/bullet/issues/detail?id=87
- btVector3 clampedPoint(point);
- clampedPoint.setMax(m_worldAabbMin);
- clampedPoint.setMin(m_worldAabbMax);
- btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
- out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
- out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
- out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
-#else
- btVector3 v = (point - m_worldAabbMin) * m_quantize;
- out[0] = (v[0] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[0] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0] & m_bpHandleMask) | isMax);
- out[1] = (v[1] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[1] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1] & m_bpHandleMask) | isMax);
- out[2] = (v[2] <= 0) ? (BP_FP_INT_TYPE)isMax : (v[2] >= m_handleSentinel) ? (BP_FP_INT_TYPE)((m_handleSentinel & m_bpHandleMask) | isMax) : (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2] & m_bpHandleMask) | isMax);
-#endif //OLD_CLAMPING_METHOD
-}
-
-template <typename BP_FP_INT_TYPE>
-BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
-{
- btAssert(m_firstFreeHandle);
-
- BP_FP_INT_TYPE handle = m_firstFreeHandle;
- m_firstFreeHandle = getHandle(handle)->GetNextFree();
- m_numHandles++;
-
- return handle;
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
-{
- btAssert(handle > 0 && handle < m_maxHandles);
-
- getHandle(handle)->SetNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
-
- m_numHandles--;
-}
-
-template <typename BP_FP_INT_TYPE>
-BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin, const btVector3& aabbMax, void* pOwner, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher)
-{
- // quantize the bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
-
- // allocate a handle
- BP_FP_INT_TYPE handle = allocHandle();
-
- Handle* pHandle = getHandle(handle);
-
- pHandle->m_uniqueId = static_cast<int>(handle);
- //pHandle->m_pOverlaps = 0;
- pHandle->m_clientObject = pOwner;
- pHandle->m_collisionFilterGroup = collisionFilterGroup;
- pHandle->m_collisionFilterMask = collisionFilterMask;
-
- // compute current limit of edge arrays
- BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
-
- // insert new edges just inside the max boundary edge
- for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_maxEdges[axis] += 2;
-
- m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
-
- m_pEdges[axis][limit - 1].m_pos = min[axis];
- m_pEdges[axis][limit - 1].m_handle = handle;
-
- m_pEdges[axis][limit].m_pos = max[axis];
- m_pEdges[axis][limit].m_handle = handle;
-
- pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
- pHandle->m_maxEdges[axis] = limit;
- }
-
- // now sort the new edges to their correct position
- sortMinDown(0, pHandle->m_minEdges[0], dispatcher, false);
- sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher, false);
- sortMinDown(1, pHandle->m_minEdges[1], dispatcher, false);
- sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher, false);
- sortMinDown(2, pHandle->m_minEdges[2], dispatcher, true);
- sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher, true);
-
- return handle;
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle, btDispatcher* dispatcher)
-{
- Handle* pHandle = getHandle(handle);
-
- //explicitly remove the pairs containing the proxy
- //we could do it also in the sortMinUp (passing true)
- ///@todo: compare performance
- if (!m_pairCache->hasDeferredRemoval())
- {
- m_pairCache->removeOverlappingPairsContainingProxy(pHandle, dispatcher);
- }
-
- // compute current limit of edge arrays
- int limit = static_cast<int>(m_numHandles * 2);
-
- int axis;
-
- for (axis = 0; axis < 3; axis++)
- {
- m_pHandles[0].m_maxEdges[axis] -= 2;
- }
-
- // remove the edges by sorting them up to the end of the list
- for (axis = 0; axis < 3; axis++)
- {
- Edge* pEdges = m_pEdges[axis];
- BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
- pEdges[max].m_pos = m_handleSentinel;
-
- sortMaxUp(axis, max, dispatcher, false);
-
- BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
- pEdges[i].m_pos = m_handleSentinel;
-
- sortMinUp(axis, i, dispatcher, false);
-
- pEdges[limit - 1].m_handle = 0;
- pEdges[limit - 1].m_pos = m_handleSentinel;
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis, false);
-#endif //DEBUG_BROADPHASE
- }
-
- // free the handle
- freeHandle(handle);
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* /*dispatcher*/)
-{
- if (m_numHandles == 0)
- {
- m_firstFreeHandle = 1;
- {
- for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
- m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
- m_pHandles[m_maxHandles - 1].SetNextFree(0);
- }
- }
-}
-
-//#include <stdio.h>
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
-{
- if (m_pairCache->hasDeferredRemoval())
- {
- btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
-
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-
- int i;
-
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
-
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- btBroadphasePair& pair = overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- ///important to use an AABB test that is consistent with the broadphase
- bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
-
- if (hasOverlap)
- {
- needsRemoval = false; //callback->processOverlap(pair);
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
-
- if (needsRemoval)
- {
- m_pairCache->cleanOverlappingPair(pair, dispatcher);
-
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- m_invalidPair++;
- }
- }
-
-///if you don't like to skip the invalid pairs in the array, execute following code:
-#define CLEAN_INVALID_PAIRS 1
-#ifdef CLEAN_INVALID_PAIRS
-
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
-
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-#endif //CLEAN_INVALID_PAIRS
-
- //printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
- }
-}
-
-template <typename BP_FP_INT_TYPE>
-bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- const Handle* pHandleA = static_cast<Handle*>(proxy0);
- const Handle* pHandleB = static_cast<Handle*>(proxy1);
-
- //optimization 1: check the array index (memory address), instead of the m_pos
-
- for (int axis = 0; axis < 3; axis++)
- {
- if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] ||
- pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis])
- {
- return false;
- }
- }
- return true;
-}
-
-template <typename BP_FP_INT_TYPE>
-bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB, int axis0, int axis1)
-{
- //optimization 1: check the array index (memory address), instead of the m_pos
-
- if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] ||
- pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
- pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
- pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1])
- {
- return false;
- }
- return true;
-}
-
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher)
-{
- // btAssert(bounds.IsFinite());
- //btAssert(bounds.HasVolume());
-
- Handle* pHandle = getHandle(handle);
-
- // quantize the new bounds
- BP_FP_INT_TYPE min[3], max[3];
- quantize(min, aabbMin, 0);
- quantize(max, aabbMax, 1);
-
- // update changed edges
- for (int axis = 0; axis < 3; axis++)
- {
- BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
- BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
-
- int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
- int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
-
- m_pEdges[axis][emin].m_pos = min[axis];
- m_pEdges[axis][emax].m_pos = max[axis];
-
- // expand (only adds overlaps)
- if (dmin < 0)
- sortMinDown(axis, emin, dispatcher, true);
-
- if (dmax > 0)
- sortMaxUp(axis, emax, dispatcher, true);
-
- // shrink (only removes overlaps)
- if (dmin > 0)
- sortMinUp(axis, emin, dispatcher, true);
-
- if (dmax < 0)
- sortMaxDown(axis, emax, dispatcher, true);
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
- }
-}
-
-// sorting a min edge downwards can only ever *add* overlaps
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
-
- if (pPrev->IsMax())
- {
- // if previous edge is a maximum check the bounds and add an overlap if necessary
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev, axis1, axis2))
- {
- m_pairCache->addOverlappingPair(pHandleEdge, pHandlePrev);
- if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(pHandleEdge, pHandlePrev);
-
- //AddOverlap(pEdge->m_handle, pPrev->m_handle);
- }
-
- // update edge reference in other handle
- pHandlePrev->m_maxEdges[axis]++;
- }
- else
- pHandlePrev->m_minEdges[axis]++;
-
- pHandleEdge->m_minEdges[axis]--;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
-
- // decrement
- pEdge--;
- pPrev--;
- }
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-}
-
-// sorting a min edge upwards can only ever *remove* overlaps
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
-
- if (pNext->IsMax())
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
-
- // if next edge is maximum remove any overlap between the two handles
- if (updateOverlaps
-#ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0, handle1, axis1, axis2)
-#endif //USE_OVERLAP_TEST_ON_REMOVES
- )
- {
- m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
- if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
- }
-
- // update edge reference in other handle
- pHandleNext->m_maxEdges[axis]--;
- }
- else
- pHandleNext->m_minEdges[axis]--;
-
- pHandleEdge->m_minEdges[axis]++;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
-
- // increment
- pEdge++;
- pNext++;
- }
-}
-
-// sorting a max edge downwards can only ever *remove* overlaps
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pPrev = pEdge - 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pEdge->m_pos < pPrev->m_pos)
- {
- Handle* pHandlePrev = getHandle(pPrev->m_handle);
-
- if (!pPrev->IsMax())
- {
- // if previous edge was a minimum remove any overlap between the two handles
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pPrev->m_handle);
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
-
- if (updateOverlaps
-#ifdef USE_OVERLAP_TEST_ON_REMOVES
- && testOverlap2D(handle0, handle1, axis1, axis2)
-#endif //USE_OVERLAP_TEST_ON_REMOVES
- )
- {
- //this is done during the overlappingpairarray iteration/narrowphase collision
-
- m_pairCache->removeOverlappingPair(handle0, handle1, dispatcher);
- if (m_userPairCallback)
- m_userPairCallback->removeOverlappingPair(handle0, handle1, dispatcher);
- }
-
- // update edge reference in other handle
- pHandlePrev->m_minEdges[axis]++;
- ;
- }
- else
- pHandlePrev->m_maxEdges[axis]++;
-
- pHandleEdge->m_maxEdges[axis]--;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pPrev;
- *pPrev = swap;
-
- // decrement
- pEdge--;
- pPrev--;
- }
-
-#ifdef DEBUG_BROADPHASE
- debugPrintAxis(axis);
-#endif //DEBUG_BROADPHASE
-}
-
-// sorting a max edge upwards can only ever *add* overlaps
-template <typename BP_FP_INT_TYPE>
-void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
-{
- Edge* pEdge = m_pEdges[axis] + edge;
- Edge* pNext = pEdge + 1;
- Handle* pHandleEdge = getHandle(pEdge->m_handle);
-
- while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
- {
- Handle* pHandleNext = getHandle(pNext->m_handle);
-
- const int axis1 = (1 << axis) & 3;
- const int axis2 = (1 << axis1) & 3;
-
- if (!pNext->IsMax())
- {
- // if next edge is a minimum check the bounds and add an overlap if necessary
- if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext, axis1, axis2))
- {
- Handle* handle0 = getHandle(pEdge->m_handle);
- Handle* handle1 = getHandle(pNext->m_handle);
- m_pairCache->addOverlappingPair(handle0, handle1);
- if (m_userPairCallback)
- m_userPairCallback->addOverlappingPair(handle0, handle1);
- }
-
- // update edge reference in other handle
- pHandleNext->m_minEdges[axis]--;
- }
- else
- pHandleNext->m_maxEdges[axis]--;
-
- pHandleEdge->m_maxEdges[axis]++;
-
- // swap the edges
- Edge swap = *pEdge;
- *pEdge = *pNext;
- *pNext = swap;
-
- // increment
- pEdge++;
- pNext++;
- }
-}
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
deleted file mode 100644
index b097eca5f5..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BROADPHASE_INTERFACE_H
-#define BT_BROADPHASE_INTERFACE_H
-
-struct btDispatcherInfo;
-class btDispatcher;
-#include "btBroadphaseProxy.h"
-
-class btOverlappingPairCache;
-
-struct btBroadphaseAabbCallback
-{
- virtual ~btBroadphaseAabbCallback() {}
- virtual bool process(const btBroadphaseProxy* proxy) = 0;
-};
-
-struct btBroadphaseRayCallback : public btBroadphaseAabbCallback
-{
- ///added some cached data to accelerate ray-AABB tests
- btVector3 m_rayDirectionInverse;
- unsigned int m_signs[3];
- btScalar m_lambda_max;
-
- virtual ~btBroadphaseRayCallback() {}
-
-protected:
- btBroadphaseRayCallback() {}
-};
-
-#include "LinearMath/btVector3.h"
-
-///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
-///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
-///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
-class btBroadphaseInterface
-{
-public:
- virtual ~btBroadphaseInterface() {}
-
- virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher) = 0;
- virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
- virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher) = 0;
- virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const = 0;
-
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0)) = 0;
-
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
-
- ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher) = 0;
-
- virtual btOverlappingPairCache* getOverlappingPairCache() = 0;
- virtual const btOverlappingPairCache* getOverlappingPairCache() const = 0;
-
- ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
- ///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const = 0;
-
- ///reset broadphase internal structures, to ensure determinism/reproducability
- virtual void resetPool(btDispatcher* dispatcher) { (void)dispatcher; };
-
- virtual void printStats() = 0;
-};
-
-#endif //BT_BROADPHASE_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
deleted file mode 100644
index 7ee065aac3..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btBroadphaseProxy.h"
-
-BT_NOT_EMPTY_FILE // fix warning LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
deleted file mode 100644
index bc0742ad62..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BROADPHASE_PROXY_H
-#define BT_BROADPHASE_PROXY_H
-
-#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAlignedAllocator.h"
-
-/// btDispatcher uses these types
-/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
-/// to facilitate type checking
-/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
-enum BroadphaseNativeTypes
-{
- // polyhedral convex shapes
- BOX_SHAPE_PROXYTYPE,
- TRIANGLE_SHAPE_PROXYTYPE,
- TETRAHEDRAL_SHAPE_PROXYTYPE,
- CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
- CONVEX_HULL_SHAPE_PROXYTYPE,
- CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
- CUSTOM_POLYHEDRAL_SHAPE_TYPE,
- //implicit convex shapes
- IMPLICIT_CONVEX_SHAPES_START_HERE,
- SPHERE_SHAPE_PROXYTYPE,
- MULTI_SPHERE_SHAPE_PROXYTYPE,
- CAPSULE_SHAPE_PROXYTYPE,
- CONE_SHAPE_PROXYTYPE,
- CONVEX_SHAPE_PROXYTYPE,
- CYLINDER_SHAPE_PROXYTYPE,
- UNIFORM_SCALING_SHAPE_PROXYTYPE,
- MINKOWSKI_SUM_SHAPE_PROXYTYPE,
- MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
- BOX_2D_SHAPE_PROXYTYPE,
- CONVEX_2D_SHAPE_PROXYTYPE,
- CUSTOM_CONVEX_SHAPE_TYPE,
- //concave shapes
- CONCAVE_SHAPES_START_HERE,
- //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
- TRIANGLE_MESH_SHAPE_PROXYTYPE,
- SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
- ///used for demo integration FAST/Swift collision library and Bullet
- FAST_CONCAVE_MESH_PROXYTYPE,
- //terrain
- TERRAIN_SHAPE_PROXYTYPE,
- ///Used for GIMPACT Trimesh integration
- GIMPACT_SHAPE_PROXYTYPE,
- ///Multimaterial mesh
- MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
-
- EMPTY_SHAPE_PROXYTYPE,
- STATIC_PLANE_PROXYTYPE,
- CUSTOM_CONCAVE_SHAPE_TYPE,
- SDF_SHAPE_PROXYTYPE = CUSTOM_CONCAVE_SHAPE_TYPE,
- CONCAVE_SHAPES_END_HERE,
-
- COMPOUND_SHAPE_PROXYTYPE,
-
- SOFTBODY_SHAPE_PROXYTYPE,
- HFFLUID_SHAPE_PROXYTYPE,
- HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
- INVALID_SHAPE_PROXYTYPE,
-
- MAX_BROADPHASE_COLLISION_TYPES
-
-};
-
-///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases.
-///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
-ATTRIBUTE_ALIGNED16(struct)
-btBroadphaseProxy
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///optional filtering to cull potential collisions
- enum CollisionFilterGroups
- {
- DefaultFilter = 1,
- StaticFilter = 2,
- KinematicFilter = 4,
- DebrisFilter = 8,
- SensorTrigger = 16,
- CharacterFilter = 32,
- AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
- };
-
- //Usually the client btCollisionObject or Rigidbody class
- void* m_clientObject;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
-
- int m_uniqueId; //m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
-
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
-
- SIMD_FORCE_INLINE int getUid() const
- {
- return m_uniqueId;
- }
-
- //used for memory pools
- btBroadphaseProxy() : m_clientObject(0)
- {
- }
-
- btBroadphaseProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- : m_clientObject(userPtr),
- m_collisionFilterGroup(collisionFilterGroup),
- m_collisionFilterMask(collisionFilterMask),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
- {
- }
-
- static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
- {
- return (proxyType < IMPLICIT_CONVEX_SHAPES_START_HERE);
- }
-
- static SIMD_FORCE_INLINE bool isConvex(int proxyType)
- {
- return (proxyType < CONCAVE_SHAPES_START_HERE);
- }
-
- static SIMD_FORCE_INLINE bool isNonMoving(int proxyType)
- {
- return (isConcave(proxyType) && !(proxyType == GIMPACT_SHAPE_PROXYTYPE));
- }
-
- static SIMD_FORCE_INLINE bool isConcave(int proxyType)
- {
- return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
- (proxyType < CONCAVE_SHAPES_END_HERE));
- }
- static SIMD_FORCE_INLINE bool isCompound(int proxyType)
- {
- return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
- }
-
- static SIMD_FORCE_INLINE bool isSoftBody(int proxyType)
- {
- return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
- }
-
- static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
- {
- return (proxyType == STATIC_PLANE_PROXYTYPE);
- }
-
- static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
- {
- return (proxyType == BOX_2D_SHAPE_PROXYTYPE) || (proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
- }
-};
-
-class btCollisionAlgorithm;
-
-struct btBroadphaseProxy;
-
-///The btBroadphasePair class contains a pair of aabb-overlapping objects.
-///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
-ATTRIBUTE_ALIGNED16(struct)
-btBroadphasePair
-{
- btBroadphasePair()
- : m_pProxy0(0),
- m_pProxy1(0),
- m_algorithm(0),
- m_internalInfo1(0)
- {
- }
-
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btBroadphasePair(btBroadphaseProxy & proxy0, btBroadphaseProxy & proxy1)
- {
- //keep them sorted, so the std::set operations work
- if (proxy0.m_uniqueId < proxy1.m_uniqueId)
- {
- m_pProxy0 = &proxy0;
- m_pProxy1 = &proxy1;
- }
- else
- {
- m_pProxy0 = &proxy1;
- m_pProxy1 = &proxy0;
- }
-
- m_algorithm = 0;
- m_internalInfo1 = 0;
- }
-
- btBroadphaseProxy* m_pProxy0;
- btBroadphaseProxy* m_pProxy1;
-
- mutable btCollisionAlgorithm* m_algorithm;
- union {
- void* m_internalInfo1;
- int m_internalTmpValue;
- }; //don't use this data, it will be removed in future version.
-};
-
-/*
-//comparison for set operation, see Solid DT_Encounter
-SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b)
-{
- return a.m_pProxy0 < b.m_pProxy0 ||
- (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1);
-}
-*/
-
-class btBroadphasePairSortPredicate
-{
-public:
- bool operator()(const btBroadphasePair& a, const btBroadphasePair& b) const
- {
- const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
- const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
- const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
- const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
-
- return uidA0 > uidB0 ||
- (a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
- (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm);
- }
-};
-
-SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b)
-{
- return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
-}
-
-#endif //BT_BROADPHASE_PROXY_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
deleted file mode 100644
index 6e36d3bd73..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionAlgorithm.h"
-#include "btDispatcher.h"
-
-btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
-{
- m_dispatcher = ci.m_dispatcher1;
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
deleted file mode 100644
index b00c0b1b4b..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_ALGORITHM_H
-#define BT_COLLISION_ALGORITHM_H
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-struct btBroadphaseProxy;
-class btDispatcher;
-class btManifoldResult;
-class btCollisionObject;
-struct btCollisionObjectWrapper;
-struct btDispatcherInfo;
-class btPersistentManifold;
-
-typedef btAlignedObjectArray<btPersistentManifold*> btManifoldArray;
-
-struct btCollisionAlgorithmConstructionInfo
-{
- btCollisionAlgorithmConstructionInfo()
- : m_dispatcher1(0),
- m_manifold(0)
- {
- }
- btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher, int temp)
- : m_dispatcher1(dispatcher)
- {
- (void)temp;
- }
-
- btDispatcher* m_dispatcher1;
- btPersistentManifold* m_manifold;
-
- // int getDispatcherId();
-};
-
-///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
-///It is persistent over frames
-class btCollisionAlgorithm
-{
-protected:
- btDispatcher* m_dispatcher;
-
-protected:
- // int getDispatcherId();
-
-public:
- btCollisionAlgorithm(){};
-
- btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
-
- virtual ~btCollisionAlgorithm(){};
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut) = 0;
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray) = 0;
-};
-
-#endif //BT_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
deleted file mode 100644
index 166cb04c0b..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
+++ /dev/null
@@ -1,1357 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btDbvt implementation by Nathanael Presson
-
-#include "btDbvt.h"
-
-//
-typedef btAlignedObjectArray<btDbvtNode*> tNodeArray;
-typedef btAlignedObjectArray<const btDbvtNode*> tConstNodeArray;
-
-//
-struct btDbvtNodeEnumerator : btDbvt::ICollide
-{
- tConstNodeArray nodes;
- void Process(const btDbvtNode* n) { nodes.push_back(n); }
-};
-
-//
-static DBVT_INLINE int indexof(const btDbvtNode* node)
-{
- return (node->parent->childs[1] == node);
-}
-
-//
-static DBVT_INLINE btDbvtVolume merge(const btDbvtVolume& a,
- const btDbvtVolume& b)
-{
-#ifdef BT_USE_SSE
- ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
- btDbvtVolume* ptr = (btDbvtVolume*)locals;
- btDbvtVolume& res = *ptr;
-#else
- btDbvtVolume res;
-#endif
- Merge(a, b, res);
- return (res);
-}
-
-// volume+edge lengths
-static DBVT_INLINE btScalar size(const btDbvtVolume& a)
-{
- const btVector3 edges = a.Lengths();
- return (edges.x() * edges.y() * edges.z() +
- edges.x() + edges.y() + edges.z());
-}
-
-//
-static void getmaxdepth(const btDbvtNode* node, int depth, int& maxdepth)
-{
- if (node->isinternal())
- {
- getmaxdepth(node->childs[0], depth + 1, maxdepth);
- getmaxdepth(node->childs[1], depth + 1, maxdepth);
- }
- else
- maxdepth = btMax(maxdepth, depth);
-}
-
-//
-static DBVT_INLINE void deletenode(btDbvt* pdbvt,
- btDbvtNode* node)
-{
- btAlignedFree(pdbvt->m_free);
- pdbvt->m_free = node;
-}
-
-//
-static void recursedeletenode(btDbvt* pdbvt,
- btDbvtNode* node)
-{
- if (node == 0) return;
- if (!node->isleaf())
- {
- recursedeletenode(pdbvt, node->childs[0]);
- recursedeletenode(pdbvt, node->childs[1]);
- }
- if (node == pdbvt->m_root) pdbvt->m_root = 0;
- deletenode(pdbvt, node);
-}
-
-//
-static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
- btDbvtNode* parent,
- void* data)
-{
- btDbvtNode* node;
- if (pdbvt->m_free)
- {
- node = pdbvt->m_free;
- pdbvt->m_free = 0;
- }
- else
- {
- node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
- }
- node->parent = parent;
- node->data = data;
- node->childs[1] = 0;
- return (node);
-}
-
-//
-static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
- btDbvtNode* parent,
- const btDbvtVolume& volume,
- void* data)
-{
- btDbvtNode* node = createnode(pdbvt, parent, data);
- node->volume = volume;
- return (node);
-}
-
-//
-static DBVT_INLINE btDbvtNode* createnode(btDbvt* pdbvt,
- btDbvtNode* parent,
- const btDbvtVolume& volume0,
- const btDbvtVolume& volume1,
- void* data)
-{
- btDbvtNode* node = createnode(pdbvt, parent, data);
- Merge(volume0, volume1, node->volume);
- return (node);
-}
-
-//
-static void insertleaf(btDbvt* pdbvt,
- btDbvtNode* root,
- btDbvtNode* leaf)
-{
- if (!pdbvt->m_root)
- {
- pdbvt->m_root = leaf;
- leaf->parent = 0;
- }
- else
- {
- if (!root->isleaf())
- {
- do
- {
- root = root->childs[Select(leaf->volume,
- root->childs[0]->volume,
- root->childs[1]->volume)];
- } while (!root->isleaf());
- }
- btDbvtNode* prev = root->parent;
- btDbvtNode* node = createnode(pdbvt, prev, leaf->volume, root->volume, 0);
- if (prev)
- {
- prev->childs[indexof(root)] = node;
- node->childs[0] = root;
- root->parent = node;
- node->childs[1] = leaf;
- leaf->parent = node;
- do
- {
- if (!prev->volume.Contain(node->volume))
- Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
- else
- break;
- node = prev;
- } while (0 != (prev = node->parent));
- }
- else
- {
- node->childs[0] = root;
- root->parent = node;
- node->childs[1] = leaf;
- leaf->parent = node;
- pdbvt->m_root = node;
- }
- }
-}
-
-//
-static btDbvtNode* removeleaf(btDbvt* pdbvt,
- btDbvtNode* leaf)
-{
- if (leaf == pdbvt->m_root)
- {
- pdbvt->m_root = 0;
- return (0);
- }
- else
- {
- btDbvtNode* parent = leaf->parent;
- btDbvtNode* prev = parent->parent;
- btDbvtNode* sibling = parent->childs[1 - indexof(leaf)];
- if (prev)
- {
- prev->childs[indexof(parent)] = sibling;
- sibling->parent = prev;
- deletenode(pdbvt, parent);
- while (prev)
- {
- const btDbvtVolume pb = prev->volume;
- Merge(prev->childs[0]->volume, prev->childs[1]->volume, prev->volume);
- if (NotEqual(pb, prev->volume))
- {
- prev = prev->parent;
- }
- else
- break;
- }
- return (prev ? prev : pdbvt->m_root);
- }
- else
- {
- pdbvt->m_root = sibling;
- sibling->parent = 0;
- deletenode(pdbvt, parent);
- return (pdbvt->m_root);
- }
- }
-}
-
-//
-static void fetchleaves(btDbvt* pdbvt,
- btDbvtNode* root,
- tNodeArray& leaves,
- int depth = -1)
-{
- if (root->isinternal() && depth)
- {
- fetchleaves(pdbvt, root->childs[0], leaves, depth - 1);
- fetchleaves(pdbvt, root->childs[1], leaves, depth - 1);
- deletenode(pdbvt, root);
- }
- else
- {
- leaves.push_back(root);
- }
-}
-
-//
-static bool leftOfAxis(const btDbvtNode* node,
- const btVector3& org,
- const btVector3& axis)
-{
- return btDot(axis, node->volume.Center() - org) <= 0;
-}
-
-// Partitions leaves such that leaves[0, n) are on the
-// left of axis, and leaves[n, count) are on the right
-// of axis. returns N.
-static int split(btDbvtNode** leaves,
- int count,
- const btVector3& org,
- const btVector3& axis)
-{
- int begin = 0;
- int end = count;
- for (;;)
- {
- while (begin != end && leftOfAxis(leaves[begin], org, axis))
- {
- ++begin;
- }
-
- if (begin == end)
- {
- break;
- }
-
- while (begin != end && !leftOfAxis(leaves[end - 1], org, axis))
- {
- --end;
- }
-
- if (begin == end)
- {
- break;
- }
-
- // swap out of place nodes
- --end;
- btDbvtNode* temp = leaves[begin];
- leaves[begin] = leaves[end];
- leaves[end] = temp;
- ++begin;
- }
-
- return begin;
-}
-
-//
-static btDbvtVolume bounds(btDbvtNode** leaves,
- int count)
-{
-#ifdef BT_USE_SSE
- ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtVolume)]);
- btDbvtVolume* ptr = (btDbvtVolume*)locals;
- btDbvtVolume& volume = *ptr;
- volume = leaves[0]->volume;
-#else
- btDbvtVolume volume = leaves[0]->volume;
-#endif
- for (int i = 1, ni = count; i < ni; ++i)
- {
- Merge(volume, leaves[i]->volume, volume);
- }
- return (volume);
-}
-
-//
-static void bottomup(btDbvt* pdbvt,
- btDbvtNode** leaves,
- int count)
-{
- while (count > 1)
- {
- btScalar minsize = SIMD_INFINITY;
- int minidx[2] = {-1, -1};
- for (int i = 0; i < count; ++i)
- {
- for (int j = i + 1; j < count; ++j)
- {
- const btScalar sz = size(merge(leaves[i]->volume, leaves[j]->volume));
- if (sz < minsize)
- {
- minsize = sz;
- minidx[0] = i;
- minidx[1] = j;
- }
- }
- }
- btDbvtNode* n[] = {leaves[minidx[0]], leaves[minidx[1]]};
- btDbvtNode* p = createnode(pdbvt, 0, n[0]->volume, n[1]->volume, 0);
- p->childs[0] = n[0];
- p->childs[1] = n[1];
- n[0]->parent = p;
- n[1]->parent = p;
- leaves[minidx[0]] = p;
- leaves[minidx[1]] = leaves[count - 1];
- --count;
- }
-}
-
-//
-static btDbvtNode* topdown(btDbvt* pdbvt,
- btDbvtNode** leaves,
- int count,
- int bu_treshold)
-{
- static const btVector3 axis[] = {btVector3(1, 0, 0),
- btVector3(0, 1, 0),
- btVector3(0, 0, 1)};
- btAssert(bu_treshold > 2);
- if (count > 1)
- {
- if (count > bu_treshold)
- {
- const btDbvtVolume vol = bounds(leaves, count);
- const btVector3 org = vol.Center();
- int partition;
- int bestaxis = -1;
- int bestmidp = count;
- int splitcount[3][2] = {{0, 0}, {0, 0}, {0, 0}};
- int i;
- for (i = 0; i < count; ++i)
- {
- const btVector3 x = leaves[i]->volume.Center() - org;
- for (int j = 0; j < 3; ++j)
- {
- ++splitcount[j][btDot(x, axis[j]) > 0 ? 1 : 0];
- }
- }
- for (i = 0; i < 3; ++i)
- {
- if ((splitcount[i][0] > 0) && (splitcount[i][1] > 0))
- {
- const int midp = (int)btFabs(btScalar(splitcount[i][0] - splitcount[i][1]));
- if (midp < bestmidp)
- {
- bestaxis = i;
- bestmidp = midp;
- }
- }
- }
- if (bestaxis >= 0)
- {
- partition = split(leaves, count, org, axis[bestaxis]);
- btAssert(partition != 0 && partition != count);
- }
- else
- {
- partition = count / 2 + 1;
- }
- btDbvtNode* node = createnode(pdbvt, 0, vol, 0);
- node->childs[0] = topdown(pdbvt, &leaves[0], partition, bu_treshold);
- node->childs[1] = topdown(pdbvt, &leaves[partition], count - partition, bu_treshold);
- node->childs[0]->parent = node;
- node->childs[1]->parent = node;
- return (node);
- }
- else
- {
- bottomup(pdbvt, leaves, count);
- return (leaves[0]);
- }
- }
- return (leaves[0]);
-}
-
-//
-static DBVT_INLINE btDbvtNode* sort(btDbvtNode* n, btDbvtNode*& r)
-{
- btDbvtNode* p = n->parent;
- btAssert(n->isinternal());
- if (p > n)
- {
- const int i = indexof(n);
- const int j = 1 - i;
- btDbvtNode* s = p->childs[j];
- btDbvtNode* q = p->parent;
- btAssert(n == p->childs[i]);
- if (q)
- q->childs[indexof(p)] = n;
- else
- r = n;
- s->parent = n;
- p->parent = n;
- n->parent = q;
- p->childs[0] = n->childs[0];
- p->childs[1] = n->childs[1];
- n->childs[0]->parent = p;
- n->childs[1]->parent = p;
- n->childs[i] = p;
- n->childs[j] = s;
- btSwap(p->volume, n->volume);
- return (p);
- }
- return (n);
-}
-
-#if 0
-static DBVT_INLINE btDbvtNode* walkup(btDbvtNode* n,int count)
-{
- while(n&&(count--)) n=n->parent;
- return(n);
-}
-#endif
-
-//
-// Api
-//
-
-//
-btDbvt::btDbvt()
-{
- m_root = 0;
- m_free = 0;
- m_lkhd = -1;
- m_leaves = 0;
- m_opath = 0;
-}
-
-//
-btDbvt::~btDbvt()
-{
- clear();
-}
-
-//
-void btDbvt::clear()
-{
- if (m_root)
- recursedeletenode(this, m_root);
- btAlignedFree(m_free);
- m_free = 0;
- m_lkhd = -1;
- m_stkStack.clear();
- m_opath = 0;
-}
-
-//
-void btDbvt::optimizeBottomUp()
-{
- if (m_root)
- {
- tNodeArray leaves;
- leaves.reserve(m_leaves);
- fetchleaves(this, m_root, leaves);
- bottomup(this, &leaves[0], leaves.size());
- m_root = leaves[0];
- }
-}
-
-//
-void btDbvt::optimizeTopDown(int bu_treshold)
-{
- if (m_root)
- {
- tNodeArray leaves;
- leaves.reserve(m_leaves);
- fetchleaves(this, m_root, leaves);
- m_root = topdown(this, &leaves[0], leaves.size(), bu_treshold);
- }
-}
-
-//
-void btDbvt::optimizeIncremental(int passes)
-{
- if (passes < 0) passes = m_leaves;
- if (m_root && (passes > 0))
- {
- do
- {
- btDbvtNode* node = m_root;
- unsigned bit = 0;
- while (node->isinternal())
- {
- node = sort(node, m_root)->childs[(m_opath >> bit) & 1];
- bit = (bit + 1) & (sizeof(unsigned) * 8 - 1);
- }
- update(node);
- ++m_opath;
- } while (--passes);
- }
-}
-
-//
-btDbvtNode* btDbvt::insert(const btDbvtVolume& volume, void* data)
-{
- btDbvtNode* leaf = createnode(this, 0, volume, data);
- insertleaf(this, m_root, leaf);
- ++m_leaves;
- return (leaf);
-}
-
-//
-void btDbvt::update(btDbvtNode* leaf, int lookahead)
-{
- btDbvtNode* root = removeleaf(this, leaf);
- if (root)
- {
- if (lookahead >= 0)
- {
- for (int i = 0; (i < lookahead) && root->parent; ++i)
- {
- root = root->parent;
- }
- }
- else
- root = m_root;
- }
- insertleaf(this, root, leaf);
-}
-
-//
-void btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume)
-{
- btDbvtNode* root = removeleaf(this, leaf);
- if (root)
- {
- if (m_lkhd >= 0)
- {
- for (int i = 0; (i < m_lkhd) && root->parent; ++i)
- {
- root = root->parent;
- }
- }
- else
- root = m_root;
- }
- leaf->volume = volume;
- insertleaf(this, root, leaf);
-}
-
-//
-bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.Expand(btVector3(margin, margin, margin));
- volume.SignedExpand(velocity);
- update(leaf, volume);
- return (true);
-}
-
-//
-bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.SignedExpand(velocity);
- update(leaf, volume);
- return (true);
-}
-
-//
-bool btDbvt::update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin)
-{
- if (leaf->volume.Contain(volume)) return (false);
- volume.Expand(btVector3(margin, margin, margin));
- update(leaf, volume);
- return (true);
-}
-
-//
-void btDbvt::remove(btDbvtNode* leaf)
-{
- removeleaf(this, leaf);
- deletenode(this, leaf);
- --m_leaves;
-}
-
-//
-void btDbvt::write(IWriter* iwriter) const
-{
- btDbvtNodeEnumerator nodes;
- nodes.nodes.reserve(m_leaves * 2);
- enumNodes(m_root, nodes);
- iwriter->Prepare(m_root, nodes.nodes.size());
- for (int i = 0; i < nodes.nodes.size(); ++i)
- {
- const btDbvtNode* n = nodes.nodes[i];
- int p = -1;
- if (n->parent) p = nodes.nodes.findLinearSearch(n->parent);
- if (n->isinternal())
- {
- const int c0 = nodes.nodes.findLinearSearch(n->childs[0]);
- const int c1 = nodes.nodes.findLinearSearch(n->childs[1]);
- iwriter->WriteNode(n, i, p, c0, c1);
- }
- else
- {
- iwriter->WriteLeaf(n, i, p);
- }
- }
-}
-
-//
-void btDbvt::clone(btDbvt& dest, IClone* iclone) const
-{
- dest.clear();
- if (m_root != 0)
- {
- btAlignedObjectArray<sStkCLN> stack;
- stack.reserve(m_leaves);
- stack.push_back(sStkCLN(m_root, 0));
- do
- {
- const int i = stack.size() - 1;
- const sStkCLN e = stack[i];
- btDbvtNode* n = createnode(&dest, e.parent, e.node->volume, e.node->data);
- stack.pop_back();
- if (e.parent != 0)
- e.parent->childs[i & 1] = n;
- else
- dest.m_root = n;
- if (e.node->isinternal())
- {
- stack.push_back(sStkCLN(e.node->childs[0], n));
- stack.push_back(sStkCLN(e.node->childs[1], n));
- }
- else
- {
- iclone->CloneLeaf(n);
- }
- } while (stack.size() > 0);
- }
-}
-
-//
-int btDbvt::maxdepth(const btDbvtNode* node)
-{
- int depth = 0;
- if (node) getmaxdepth(node, 1, depth);
- return (depth);
-}
-
-//
-int btDbvt::countLeaves(const btDbvtNode* node)
-{
- if (node->isinternal())
- return (countLeaves(node->childs[0]) + countLeaves(node->childs[1]));
- else
- return (1);
-}
-
-//
-void btDbvt::extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves)
-{
- if (node->isinternal())
- {
- extractLeaves(node->childs[0], leaves);
- extractLeaves(node->childs[1], leaves);
- }
- else
- {
- leaves.push_back(node);
- }
-}
-
-//
-#if DBVT_ENABLE_BENCHMARK
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "LinearMath/btQuickProf.h"
-
-/*
-q6600,2.4ghz
-
-/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
-/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
-/Fo"..\..\out\release8\build\libbulletcollision\\"
-/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
-/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
-
-Benchmarking dbvt...
-World scale: 100.000000
-Extents base: 1.000000
-Extents range: 4.000000
-Leaves: 8192
-sizeof(btDbvtVolume): 32 bytes
-sizeof(btDbvtNode): 44 bytes
-[1] btDbvtVolume intersections: 3499 ms (-1%)
-[2] btDbvtVolume merges: 1934 ms (0%)
-[3] btDbvt::collideTT: 5485 ms (-21%)
-[4] btDbvt::collideTT self: 2814 ms (-20%)
-[5] btDbvt::collideTT xform: 7379 ms (-1%)
-[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
-[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
-[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
-[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
-[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
-[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
-[12] btDbvtVolume notequal: 3659 ms (0%)
-[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
-[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
-[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
-[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
-[17] btDbvtVolume select: 3419 ms (0%)
-*/
-
-struct btDbvtBenchmark
-{
- struct NilPolicy : btDbvt::ICollide
- {
- NilPolicy() : m_pcount(0), m_depth(-SIMD_INFINITY), m_checksort(true) {}
- void Process(const btDbvtNode*, const btDbvtNode*) { ++m_pcount; }
- void Process(const btDbvtNode*) { ++m_pcount; }
- void Process(const btDbvtNode*, btScalar depth)
- {
- ++m_pcount;
- if (m_checksort)
- {
- if (depth >= m_depth)
- m_depth = depth;
- else
- printf("wrong depth: %f (should be >= %f)\r\n", depth, m_depth);
- }
- }
- int m_pcount;
- btScalar m_depth;
- bool m_checksort;
- };
- struct P14 : btDbvt::ICollide
- {
- struct Node
- {
- const btDbvtNode* leaf;
- btScalar depth;
- };
- void Process(const btDbvtNode* leaf, btScalar depth)
- {
- Node n;
- n.leaf = leaf;
- n.depth = depth;
- }
- static int sortfnc(const Node& a, const Node& b)
- {
- if (a.depth < b.depth) return (+1);
- if (a.depth > b.depth) return (-1);
- return (0);
- }
- btAlignedObjectArray<Node> m_nodes;
- };
- struct P15 : btDbvt::ICollide
- {
- struct Node
- {
- const btDbvtNode* leaf;
- btScalar depth;
- };
- void Process(const btDbvtNode* leaf)
- {
- Node n;
- n.leaf = leaf;
- n.depth = dot(leaf->volume.Center(), m_axis);
- }
- static int sortfnc(const Node& a, const Node& b)
- {
- if (a.depth < b.depth) return (+1);
- if (a.depth > b.depth) return (-1);
- return (0);
- }
- btAlignedObjectArray<Node> m_nodes;
- btVector3 m_axis;
- };
- static btScalar RandUnit()
- {
- return (rand() / (btScalar)RAND_MAX);
- }
- static btVector3 RandVector3()
- {
- return (btVector3(RandUnit(), RandUnit(), RandUnit()));
- }
- static btVector3 RandVector3(btScalar cs)
- {
- return (RandVector3() * cs - btVector3(cs, cs, cs) / 2);
- }
- static btDbvtVolume RandVolume(btScalar cs, btScalar eb, btScalar es)
- {
- return (btDbvtVolume::FromCE(RandVector3(cs), btVector3(eb, eb, eb) + RandVector3() * es));
- }
- static btTransform RandTransform(btScalar cs)
- {
- btTransform t;
- t.setOrigin(RandVector3(cs));
- t.setRotation(btQuaternion(RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2, RandUnit() * SIMD_PI * 2).normalized());
- return (t);
- }
- static void RandTree(btScalar cs, btScalar eb, btScalar es, int leaves, btDbvt& dbvt)
- {
- dbvt.clear();
- for (int i = 0; i < leaves; ++i)
- {
- dbvt.insert(RandVolume(cs, eb, es), 0);
- }
- }
-};
-
-void btDbvt::benchmark()
-{
- static const btScalar cfgVolumeCenterScale = 100;
- static const btScalar cfgVolumeExentsBase = 1;
- static const btScalar cfgVolumeExentsScale = 4;
- static const int cfgLeaves = 8192;
- static const bool cfgEnable = true;
-
- //[1] btDbvtVolume intersections
- bool cfgBenchmark1_Enable = cfgEnable;
- static const int cfgBenchmark1_Iterations = 8;
- static const int cfgBenchmark1_Reference = 3499;
- //[2] btDbvtVolume merges
- bool cfgBenchmark2_Enable = cfgEnable;
- static const int cfgBenchmark2_Iterations = 4;
- static const int cfgBenchmark2_Reference = 1945;
- //[3] btDbvt::collideTT
- bool cfgBenchmark3_Enable = cfgEnable;
- static const int cfgBenchmark3_Iterations = 512;
- static const int cfgBenchmark3_Reference = 5485;
- //[4] btDbvt::collideTT self
- bool cfgBenchmark4_Enable = cfgEnable;
- static const int cfgBenchmark4_Iterations = 512;
- static const int cfgBenchmark4_Reference = 2814;
- //[5] btDbvt::collideTT xform
- bool cfgBenchmark5_Enable = cfgEnable;
- static const int cfgBenchmark5_Iterations = 512;
- static const btScalar cfgBenchmark5_OffsetScale = 2;
- static const int cfgBenchmark5_Reference = 7379;
- //[6] btDbvt::collideTT xform,self
- bool cfgBenchmark6_Enable = cfgEnable;
- static const int cfgBenchmark6_Iterations = 512;
- static const btScalar cfgBenchmark6_OffsetScale = 2;
- static const int cfgBenchmark6_Reference = 7270;
- //[7] btDbvt::rayTest
- bool cfgBenchmark7_Enable = cfgEnable;
- static const int cfgBenchmark7_Passes = 32;
- static const int cfgBenchmark7_Iterations = 65536;
- static const int cfgBenchmark7_Reference = 6307;
- //[8] insert/remove
- bool cfgBenchmark8_Enable = cfgEnable;
- static const int cfgBenchmark8_Passes = 32;
- static const int cfgBenchmark8_Iterations = 65536;
- static const int cfgBenchmark8_Reference = 2105;
- //[9] updates (teleport)
- bool cfgBenchmark9_Enable = cfgEnable;
- static const int cfgBenchmark9_Passes = 32;
- static const int cfgBenchmark9_Iterations = 65536;
- static const int cfgBenchmark9_Reference = 1879;
- //[10] updates (jitter)
- bool cfgBenchmark10_Enable = cfgEnable;
- static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale / 10000;
- static const int cfgBenchmark10_Passes = 32;
- static const int cfgBenchmark10_Iterations = 65536;
- static const int cfgBenchmark10_Reference = 1244;
- //[11] optimize (incremental)
- bool cfgBenchmark11_Enable = cfgEnable;
- static const int cfgBenchmark11_Passes = 64;
- static const int cfgBenchmark11_Iterations = 65536;
- static const int cfgBenchmark11_Reference = 2510;
- //[12] btDbvtVolume notequal
- bool cfgBenchmark12_Enable = cfgEnable;
- static const int cfgBenchmark12_Iterations = 32;
- static const int cfgBenchmark12_Reference = 3677;
- //[13] culling(OCL+fullsort)
- bool cfgBenchmark13_Enable = cfgEnable;
- static const int cfgBenchmark13_Iterations = 1024;
- static const int cfgBenchmark13_Reference = 2231;
- //[14] culling(OCL+qsort)
- bool cfgBenchmark14_Enable = cfgEnable;
- static const int cfgBenchmark14_Iterations = 8192;
- static const int cfgBenchmark14_Reference = 3500;
- //[15] culling(KDOP+qsort)
- bool cfgBenchmark15_Enable = cfgEnable;
- static const int cfgBenchmark15_Iterations = 8192;
- static const int cfgBenchmark15_Reference = 1151;
- //[16] insert/remove batch
- bool cfgBenchmark16_Enable = cfgEnable;
- static const int cfgBenchmark16_BatchCount = 256;
- static const int cfgBenchmark16_Passes = 16384;
- static const int cfgBenchmark16_Reference = 5138;
- //[17] select
- bool cfgBenchmark17_Enable = cfgEnable;
- static const int cfgBenchmark17_Iterations = 4;
- static const int cfgBenchmark17_Reference = 3390;
-
- btClock wallclock;
- printf("Benchmarking dbvt...\r\n");
- printf("\tWorld scale: %f\r\n", cfgVolumeCenterScale);
- printf("\tExtents base: %f\r\n", cfgVolumeExentsBase);
- printf("\tExtents range: %f\r\n", cfgVolumeExentsScale);
- printf("\tLeaves: %u\r\n", cfgLeaves);
- printf("\tsizeof(btDbvtVolume): %u bytes\r\n", sizeof(btDbvtVolume));
- printf("\tsizeof(btDbvtNode): %u bytes\r\n", sizeof(btDbvtNode));
- if (cfgBenchmark1_Enable)
- { // Benchmark 1
- srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<bool> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[1] btDbvtVolume intersections: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark1_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- results[k] = Intersect(volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark1_Reference) * 100 / time);
- }
- if (cfgBenchmark2_Enable)
- { // Benchmark 2
- srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<btDbvtVolume> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[2] btDbvtVolume merges: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark2_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- Merge(volumes[j], volumes[k], results[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark2_Reference) * 100 / time);
- }
- if (cfgBenchmark3_Enable)
- { // Benchmark 3
- srand(380843);
- btDbvt dbvt[2];
- btDbvtBenchmark::NilPolicy policy;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
- dbvt[0].optimizeTopDown();
- dbvt[1].optimizeTopDown();
- printf("[3] btDbvt::collideTT: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark3_Iterations; ++i)
- {
- btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark3_Reference) * 100 / time);
- }
- if (cfgBenchmark4_Enable)
- { // Benchmark 4
- srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::NilPolicy policy;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[4] btDbvt::collideTT self: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark4_Iterations; ++i)
- {
- btDbvt::collideTT(dbvt.m_root, dbvt.m_root, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark4_Reference) * 100 / time);
- }
- if (cfgBenchmark5_Enable)
- { // Benchmark 5
- srand(380843);
- btDbvt dbvt[2];
- btAlignedObjectArray<btTransform> transforms;
- btDbvtBenchmark::NilPolicy policy;
- transforms.resize(cfgBenchmark5_Iterations);
- for (int i = 0; i < transforms.size(); ++i)
- {
- transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark5_OffsetScale);
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[0]);
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt[1]);
- dbvt[0].optimizeTopDown();
- dbvt[1].optimizeTopDown();
- printf("[5] btDbvt::collideTT xform: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark5_Iterations; ++i)
- {
- btDbvt::collideTT(dbvt[0].m_root, dbvt[1].m_root, transforms[i], policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark5_Reference) * 100 / time);
- }
- if (cfgBenchmark6_Enable)
- { // Benchmark 6
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btTransform> transforms;
- btDbvtBenchmark::NilPolicy policy;
- transforms.resize(cfgBenchmark6_Iterations);
- for (int i = 0; i < transforms.size(); ++i)
- {
- transforms[i] = btDbvtBenchmark::RandTransform(cfgVolumeCenterScale * cfgBenchmark6_OffsetScale);
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[6] btDbvt::collideTT xform,self: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark6_Iterations; ++i)
- {
- btDbvt::collideTT(dbvt.m_root, dbvt.m_root, transforms[i], policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark6_Reference) * 100 / time);
- }
- if (cfgBenchmark7_Enable)
- { // Benchmark 7
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> rayorg;
- btAlignedObjectArray<btVector3> raydir;
- btDbvtBenchmark::NilPolicy policy;
- rayorg.resize(cfgBenchmark7_Iterations);
- raydir.resize(cfgBenchmark7_Iterations);
- for (int i = 0; i < rayorg.size(); ++i)
- {
- rayorg[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
- raydir[i] = btDbvtBenchmark::RandVector3(cfgVolumeCenterScale * 2);
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[7] btDbvt::rayTest: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark7_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark7_Iterations; ++j)
- {
- btDbvt::rayTest(dbvt.m_root, rayorg[j], rayorg[j] + raydir[j], policy);
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- unsigned rays = cfgBenchmark7_Passes * cfgBenchmark7_Iterations;
- printf("%u ms (%i%%),(%u r/s)\r\n", time, (time - cfgBenchmark7_Reference) * 100 / time, (rays * 1000) / time);
- }
- if (cfgBenchmark8_Enable)
- { // Benchmark 8
- srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[8] insert/remove: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark8_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark8_Iterations; ++j)
- {
- dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int ir = cfgBenchmark8_Passes * cfgBenchmark8_Iterations;
- printf("%u ms (%i%%),(%u ir/s)\r\n", time, (time - cfgBenchmark8_Reference) * 100 / time, ir * 1000 / time);
- }
- if (cfgBenchmark9_Enable)
- { // Benchmark 9
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<const btDbvtNode*> leaves;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root, leaves);
- printf("[9] updates (teleport): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark9_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark9_Iterations; ++j)
- {
- dbvt.update(const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]),
- btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale));
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int up = cfgBenchmark9_Passes * cfgBenchmark9_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark9_Reference) * 100 / time, up * 1000 / time);
- }
- if (cfgBenchmark10_Enable)
- { // Benchmark 10
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<const btDbvtNode*> leaves;
- btAlignedObjectArray<btVector3> vectors;
- vectors.resize(cfgBenchmark10_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)) * cfgBenchmark10_Scale;
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- dbvt.extractLeaves(dbvt.m_root, leaves);
- printf("[10] updates (jitter): ");
- wallclock.reset();
-
- for (int i = 0; i < cfgBenchmark10_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark10_Iterations; ++j)
- {
- const btVector3& d = vectors[j];
- btDbvtNode* l = const_cast<btDbvtNode*>(leaves[rand() % cfgLeaves]);
- btDbvtVolume v = btDbvtVolume::FromMM(l->volume.Mins() + d, l->volume.Maxs() + d);
- dbvt.update(l, v);
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int up = cfgBenchmark10_Passes * cfgBenchmark10_Iterations;
- printf("%u ms (%i%%),(%u u/s)\r\n", time, (time - cfgBenchmark10_Reference) * 100 / time, up * 1000 / time);
- }
- if (cfgBenchmark11_Enable)
- { // Benchmark 11
- srand(380843);
- btDbvt dbvt;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[11] optimize (incremental): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark11_Passes; ++i)
- {
- dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int op = cfgBenchmark11_Passes * cfgBenchmark11_Iterations;
- printf("%u ms (%i%%),(%u o/s)\r\n", time, (time - cfgBenchmark11_Reference) * 100 / time, op / time * 1000);
- }
- if (cfgBenchmark12_Enable)
- { // Benchmark 12
- srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<bool> results;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- printf("[12] btDbvtVolume notequal: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark12_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- results[k] = NotEqual(volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark12_Reference) * 100 / time);
- }
- if (cfgBenchmark13_Enable)
- { // Benchmark 13
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::NilPolicy policy;
- vectors.resize(cfgBenchmark13_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- printf("[13] culling(OCL+fullsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark13_Iterations; ++i)
- {
- static const btScalar offset = 0;
- policy.m_depth = -SIMD_INFINITY;
- dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark13_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark13_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark14_Enable)
- { // Benchmark 14
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::P14 policy;
- vectors.resize(cfgBenchmark14_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- policy.m_nodes.reserve(cfgLeaves);
- printf("[14] culling(OCL+qsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark14_Iterations; ++i)
- {
- static const btScalar offset = 0;
- policy.m_nodes.resize(0);
- dbvt.collideOCL(dbvt.m_root, &vectors[i], &offset, vectors[i], 1, policy, false);
- policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark14_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark14_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark15_Enable)
- { // Benchmark 15
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btVector3> vectors;
- btDbvtBenchmark::P15 policy;
- vectors.resize(cfgBenchmark15_Iterations);
- for (int i = 0; i < vectors.size(); ++i)
- {
- vectors[i] = (btDbvtBenchmark::RandVector3() * 2 - btVector3(1, 1, 1)).normalized();
- }
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- policy.m_nodes.reserve(cfgLeaves);
- printf("[15] culling(KDOP+qsort): ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark15_Iterations; ++i)
- {
- static const btScalar offset = 0;
- policy.m_nodes.resize(0);
- policy.m_axis = vectors[i];
- dbvt.collideKDOP(dbvt.m_root, &vectors[i], &offset, 1, policy);
- policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int t = cfgBenchmark15_Iterations;
- printf("%u ms (%i%%),(%u t/s)\r\n", time, (time - cfgBenchmark15_Reference) * 100 / time, (t * 1000) / time);
- }
- if (cfgBenchmark16_Enable)
- { // Benchmark 16
- srand(380843);
- btDbvt dbvt;
- btAlignedObjectArray<btDbvtNode*> batch;
- btDbvtBenchmark::RandTree(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale, cfgLeaves, dbvt);
- dbvt.optimizeTopDown();
- batch.reserve(cfgBenchmark16_BatchCount);
- printf("[16] insert/remove batch(%u): ", cfgBenchmark16_BatchCount);
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark16_Passes; ++i)
- {
- for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
- {
- batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale), 0));
- }
- for (int j = 0; j < cfgBenchmark16_BatchCount; ++j)
- {
- dbvt.remove(batch[j]);
- }
- batch.resize(0);
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- const int ir = cfgBenchmark16_Passes * cfgBenchmark16_BatchCount;
- printf("%u ms (%i%%),(%u bir/s)\r\n", time, (time - cfgBenchmark16_Reference) * 100 / time, int(ir * 1000.0 / time));
- }
- if (cfgBenchmark17_Enable)
- { // Benchmark 17
- srand(380843);
- btAlignedObjectArray<btDbvtVolume> volumes;
- btAlignedObjectArray<int> results;
- btAlignedObjectArray<int> indices;
- volumes.resize(cfgLeaves);
- results.resize(cfgLeaves);
- indices.resize(cfgLeaves);
- for (int i = 0; i < cfgLeaves; ++i)
- {
- indices[i] = i;
- volumes[i] = btDbvtBenchmark::RandVolume(cfgVolumeCenterScale, cfgVolumeExentsBase, cfgVolumeExentsScale);
- }
- for (int i = 0; i < cfgLeaves; ++i)
- {
- btSwap(indices[i], indices[rand() % cfgLeaves]);
- }
- printf("[17] btDbvtVolume select: ");
- wallclock.reset();
- for (int i = 0; i < cfgBenchmark17_Iterations; ++i)
- {
- for (int j = 0; j < cfgLeaves; ++j)
- {
- for (int k = 0; k < cfgLeaves; ++k)
- {
- const int idx = indices[k];
- results[idx] = Select(volumes[idx], volumes[j], volumes[k]);
- }
- }
- }
- const int time = (int)wallclock.getTimeMilliseconds();
- printf("%u ms (%i%%)\r\n", time, (time - cfgBenchmark17_Reference) * 100 / time);
- }
- printf("\r\n\r\n");
-}
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
deleted file mode 100644
index 55daa7fb57..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
+++ /dev/null
@@ -1,1578 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btDbvt implementation by Nathanael Presson
-
-#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
-#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btAabbUtil2.h"
-//
-// Compile time configuration
-//
-
-// Implementation profiles
-#define DBVT_IMPL_GENERIC 0 // Generic implementation
-#define DBVT_IMPL_SSE 1 // SSE
-
-// Template implementation of ICollide
-#ifdef _WIN32
-#if (defined(_MSC_VER) && _MSC_VER >= 1400)
-#define DBVT_USE_TEMPLATE 1
-#else
-#define DBVT_USE_TEMPLATE 0
-#endif
-#else
-#define DBVT_USE_TEMPLATE 0
-#endif
-
-// Use only intrinsics instead of inline asm
-#define DBVT_USE_INTRINSIC_SSE 1
-
-// Using memmov for collideOCL
-#define DBVT_USE_MEMMOVE 1
-
-// Enable benchmarking code
-#define DBVT_ENABLE_BENCHMARK 0
-
-// Inlining
-#define DBVT_INLINE SIMD_FORCE_INLINE
-
-// Specific methods implementation
-
-//SSE gives errors on a MSVC 7.1
-#if defined(BT_USE_SSE) //&& defined (_WIN32)
-#define DBVT_SELECT_IMPL DBVT_IMPL_SSE
-#define DBVT_MERGE_IMPL DBVT_IMPL_SSE
-#define DBVT_INT0_IMPL DBVT_IMPL_SSE
-#else
-#define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC
-#define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC
-#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC
-#endif
-
-#if (DBVT_SELECT_IMPL == DBVT_IMPL_SSE) || \
- (DBVT_MERGE_IMPL == DBVT_IMPL_SSE) || \
- (DBVT_INT0_IMPL == DBVT_IMPL_SSE)
-#include <emmintrin.h>
-#endif
-
-//
-// Auto config and checks
-//
-
-#if DBVT_USE_TEMPLATE
-#define DBVT_VIRTUAL
-#define DBVT_VIRTUAL_DTOR(a)
-#define DBVT_PREFIX template <typename T>
-#define DBVT_IPOLICY T& policy
-#define DBVT_CHECKTYPE \
- static const ICollide& typechecker = *(T*)1; \
- (void)typechecker;
-#else
-#define DBVT_VIRTUAL_DTOR(a) \
- virtual ~a() {}
-#define DBVT_VIRTUAL virtual
-#define DBVT_PREFIX
-#define DBVT_IPOLICY ICollide& policy
-#define DBVT_CHECKTYPE
-#endif
-
-#if DBVT_USE_MEMMOVE
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-#endif
-
-#ifndef DBVT_USE_TEMPLATE
-#error "DBVT_USE_TEMPLATE undefined"
-#endif
-
-#ifndef DBVT_USE_MEMMOVE
-#error "DBVT_USE_MEMMOVE undefined"
-#endif
-
-#ifndef DBVT_ENABLE_BENCHMARK
-#error "DBVT_ENABLE_BENCHMARK undefined"
-#endif
-
-#ifndef DBVT_SELECT_IMPL
-#error "DBVT_SELECT_IMPL undefined"
-#endif
-
-#ifndef DBVT_MERGE_IMPL
-#error "DBVT_MERGE_IMPL undefined"
-#endif
-
-#ifndef DBVT_INT0_IMPL
-#error "DBVT_INT0_IMPL undefined"
-#endif
-
-//
-// Defaults volumes
-//
-
-/* btDbvtAabbMm */
-struct btDbvtAabbMm
-{
- DBVT_INLINE btDbvtAabbMm(){}
- DBVT_INLINE btVector3 Center() const { return ((mi + mx) / 2); }
- DBVT_INLINE btVector3 Lengths() const { return (mx - mi); }
- DBVT_INLINE btVector3 Extents() const { return ((mx - mi) / 2); }
- DBVT_INLINE const btVector3& Mins() const { return (mi); }
- DBVT_INLINE const btVector3& Maxs() const { return (mx); }
- static inline btDbvtAabbMm FromCE(const btVector3& c, const btVector3& e);
- static inline btDbvtAabbMm FromCR(const btVector3& c, btScalar r);
- static inline btDbvtAabbMm FromMM(const btVector3& mi, const btVector3& mx);
- static inline btDbvtAabbMm FromPoints(const btVector3* pts, int n);
- static inline btDbvtAabbMm FromPoints(const btVector3** ppts, int n);
- DBVT_INLINE void Expand(const btVector3& e);
- DBVT_INLINE void SignedExpand(const btVector3& e);
- DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const;
- DBVT_INLINE int Classify(const btVector3& n, btScalar o, int s) const;
- DBVT_INLINE btScalar ProjectMinimum(const btVector3& v, unsigned signs) const;
- DBVT_INLINE friend bool Intersect(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
-
- DBVT_INLINE friend bool Intersect(const btDbvtAabbMm& a,
- const btVector3& b);
-
- DBVT_INLINE friend btScalar Proximity(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
- DBVT_INLINE friend int Select(const btDbvtAabbMm& o,
- const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
- DBVT_INLINE friend void Merge(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b,
- btDbvtAabbMm& r);
- DBVT_INLINE friend bool NotEqual(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b);
-
- DBVT_INLINE btVector3& tMins() { return (mi); }
- DBVT_INLINE btVector3& tMaxs() { return (mx); }
-
-private:
- DBVT_INLINE void AddSpan(const btVector3& d, btScalar& smi, btScalar& smx) const;
-
-private:
- btVector3 mi, mx;
-};
-
-// Types
-typedef btDbvtAabbMm btDbvtVolume;
-
-/* btDbvtNode */
-struct btDbvtNode
-{
- btDbvtVolume volume;
- btDbvtNode* parent;
- DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
- DBVT_INLINE bool isinternal() const { return (!isleaf()); }
- union {
- btDbvtNode* childs[2];
- void* data;
- int dataAsInt;
- };
-};
-
-/* btDbv(normal)tNode */
-struct btDbvntNode
-{
- btDbvtVolume volume;
- btVector3 normal;
- btScalar angle;
- DBVT_INLINE bool isleaf() const { return (childs[1] == 0); }
- DBVT_INLINE bool isinternal() const { return (!isleaf()); }
- btDbvntNode* childs[2];
- void* data;
-
- btDbvntNode(const btDbvtNode* n)
- : volume(n->volume)
- , normal(0,0,0)
- , angle(0)
- , data(n->data)
- {
- childs[0] = 0;
- childs[1] = 0;
- }
-
- ~btDbvntNode()
- {
- if (childs[0])
- delete childs[0];
- if (childs[1])
- delete childs[1];
- }
-};
-
-typedef btAlignedObjectArray<const btDbvtNode*> btNodeStack;
-
-///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
-///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
-///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
-struct btDbvt
-{
- /* Stack element */
- struct sStkNN
- {
- const btDbvtNode* a;
- const btDbvtNode* b;
- sStkNN() {}
- sStkNN(const btDbvtNode* na, const btDbvtNode* nb) : a(na), b(nb) {}
- };
- struct sStkNP
- {
- const btDbvtNode* node;
- int mask;
- sStkNP(const btDbvtNode* n, unsigned m) : node(n), mask(m) {}
- };
- struct sStkNPS
- {
- const btDbvtNode* node;
- int mask;
- btScalar value;
- sStkNPS() {}
- sStkNPS(const btDbvtNode* n, unsigned m, btScalar v) : node(n), mask(m), value(v) {}
- };
- struct sStkCLN
- {
- const btDbvtNode* node;
- btDbvtNode* parent;
- sStkCLN(const btDbvtNode* n, btDbvtNode* p) : node(n), parent(p) {}
- };
-
- struct sStknNN
- {
- const btDbvntNode* a;
- const btDbvntNode* b;
- sStknNN() {}
- sStknNN(const btDbvntNode* na, const btDbvntNode* nb) : a(na), b(nb) {}
- };
- // Policies/Interfaces
-
- /* ICollide */
- struct ICollide
- {
- DBVT_VIRTUAL_DTOR(ICollide)
- DBVT_VIRTUAL void Process(const btDbvtNode*, const btDbvtNode*) {}
- DBVT_VIRTUAL void Process(const btDbvtNode*) {}
- DBVT_VIRTUAL void Process(const btDbvtNode* n, btScalar) { Process(n); }
- DBVT_VIRTUAL void Process(const btDbvntNode*, const btDbvntNode*) {}
- DBVT_VIRTUAL bool Descent(const btDbvtNode*) { return (true); }
- DBVT_VIRTUAL bool AllLeaves(const btDbvtNode*) { return (true); }
- };
- /* IWriter */
- struct IWriter
- {
- virtual ~IWriter() {}
- virtual void Prepare(const btDbvtNode* root, int numnodes) = 0;
- virtual void WriteNode(const btDbvtNode*, int index, int parent, int child0, int child1) = 0;
- virtual void WriteLeaf(const btDbvtNode*, int index, int parent) = 0;
- };
- /* IClone */
- struct IClone
- {
- virtual ~IClone() {}
- virtual void CloneLeaf(btDbvtNode*) {}
- };
-
- // Constants
- enum
- {
- SIMPLE_STACKSIZE = 64,
- DOUBLE_STACKSIZE = SIMPLE_STACKSIZE * 2
- };
-
- // Fields
- btDbvtNode* m_root;
- btDbvtNode* m_free;
- int m_lkhd;
- int m_leaves;
- unsigned m_opath;
-
- btAlignedObjectArray<sStkNN> m_stkStack;
-
- // Methods
- btDbvt();
- ~btDbvt();
- void clear();
- bool empty() const { return (0 == m_root); }
- void optimizeBottomUp();
- void optimizeTopDown(int bu_treshold = 128);
- void optimizeIncremental(int passes);
- btDbvtNode* insert(const btDbvtVolume& box, void* data);
- void update(btDbvtNode* leaf, int lookahead = -1);
- void update(btDbvtNode* leaf, btDbvtVolume& volume);
- bool update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity, btScalar margin);
- bool update(btDbvtNode* leaf, btDbvtVolume& volume, const btVector3& velocity);
- bool update(btDbvtNode* leaf, btDbvtVolume& volume, btScalar margin);
- void remove(btDbvtNode* leaf);
- void write(IWriter* iwriter) const;
- void clone(btDbvt& dest, IClone* iclone = 0) const;
- static int maxdepth(const btDbvtNode* node);
- static int countLeaves(const btDbvtNode* node);
- static void extractLeaves(const btDbvtNode* node, btAlignedObjectArray<const btDbvtNode*>& leaves);
-#if DBVT_ENABLE_BENCHMARK
- static void benchmark();
-#else
- static void benchmark()
- {
- }
-#endif
- // DBVT_IPOLICY must support ICollide policy/interface
- DBVT_PREFIX
- static void enumNodes(const btDbvtNode* root,
- DBVT_IPOLICY);
- DBVT_PREFIX
- static void enumLeaves(const btDbvtNode* root,
- DBVT_IPOLICY);
- DBVT_PREFIX
- void collideTT(const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY);
- DBVT_PREFIX
- void selfCollideT(const btDbvntNode* root,
- DBVT_IPOLICY);
- DBVT_PREFIX
- void selfCollideTT(const btDbvtNode* root,
- DBVT_IPOLICY);
-
- DBVT_PREFIX
- void collideTTpersistentStack(const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY);
-#if 0
- DBVT_PREFIX
- void collideTT( const btDbvtNode* root0,
- const btDbvtNode* root1,
- const btTransform& xform,
- DBVT_IPOLICY);
- DBVT_PREFIX
- void collideTT( const btDbvtNode* root0,
- const btTransform& xform0,
- const btDbvtNode* root1,
- const btTransform& xform1,
- DBVT_IPOLICY);
-#endif
-
- DBVT_PREFIX
- void collideTV(const btDbvtNode* root,
- const btDbvtVolume& volume,
- DBVT_IPOLICY) const;
-
- DBVT_PREFIX
- void collideTVNoStackAlloc(const btDbvtNode* root,
- const btDbvtVolume& volume,
- btNodeStack& stack,
- DBVT_IPOLICY) const;
-
- ///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
- ///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
- DBVT_PREFIX
- static void rayTest(const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- DBVT_IPOLICY);
- ///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
- ///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
- DBVT_PREFIX
- void rayTestInternal(const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayDirectionInverse,
- unsigned int signs[3],
- btScalar lambda_max,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btAlignedObjectArray<const btDbvtNode*>& stack,
- DBVT_IPOLICY) const;
-
- DBVT_PREFIX
- static void collideKDOP(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- int count,
- DBVT_IPOLICY);
- DBVT_PREFIX
- static void collideOCL(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- const btVector3& sortaxis,
- int count,
- DBVT_IPOLICY,
- bool fullsort = true);
- DBVT_PREFIX
- static void collideTU(const btDbvtNode* root,
- DBVT_IPOLICY);
- // Helpers
- static DBVT_INLINE int nearest(const int* i, const btDbvt::sStkNPS* a, btScalar v, int l, int h)
- {
- int m = 0;
- while (l < h)
- {
- m = (l + h) >> 1;
- if (a[i[m]].value >= v)
- l = m + 1;
- else
- h = m;
- }
- return (h);
- }
- static DBVT_INLINE int allocate(btAlignedObjectArray<int>& ifree,
- btAlignedObjectArray<sStkNPS>& stock,
- const sStkNPS& value)
- {
- int i;
- if (ifree.size() > 0)
- {
- i = ifree[ifree.size() - 1];
- ifree.pop_back();
- stock[i] = value;
- }
- else
- {
- i = stock.size();
- stock.push_back(value);
- }
- return (i);
- }
- //
-private:
- btDbvt(const btDbvt&) {}
-};
-
-//
-// Inline's
-//
-
-//
-inline btDbvtAabbMm btDbvtAabbMm::FromCE(const btVector3& c, const btVector3& e)
-{
- btDbvtAabbMm box;
- box.mi = c - e;
- box.mx = c + e;
- return (box);
-}
-
-//
-inline btDbvtAabbMm btDbvtAabbMm::FromCR(const btVector3& c, btScalar r)
-{
- return (FromCE(c, btVector3(r, r, r)));
-}
-
-//
-inline btDbvtAabbMm btDbvtAabbMm::FromMM(const btVector3& mi, const btVector3& mx)
-{
- btDbvtAabbMm box;
- box.mi = mi;
- box.mx = mx;
- return (box);
-}
-
-//
-inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3* pts, int n)
-{
- btDbvtAabbMm box;
- box.mi = box.mx = pts[0];
- for (int i = 1; i < n; ++i)
- {
- box.mi.setMin(pts[i]);
- box.mx.setMax(pts[i]);
- }
- return (box);
-}
-
-//
-inline btDbvtAabbMm btDbvtAabbMm::FromPoints(const btVector3** ppts, int n)
-{
- btDbvtAabbMm box;
- box.mi = box.mx = *ppts[0];
- for (int i = 1; i < n; ++i)
- {
- box.mi.setMin(*ppts[i]);
- box.mx.setMax(*ppts[i]);
- }
- return (box);
-}
-
-//
-DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e)
-{
- mi -= e;
- mx += e;
-}
-
-//
-DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e)
-{
- if (e.x() > 0)
- mx.setX(mx.x() + e[0]);
- else
- mi.setX(mi.x() + e[0]);
- if (e.y() > 0)
- mx.setY(mx.y() + e[1]);
- else
- mi.setY(mi.y() + e[1]);
- if (e.z() > 0)
- mx.setZ(mx.z() + e[2]);
- else
- mi.setZ(mi.z() + e[2]);
-}
-
-//
-DBVT_INLINE bool btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
-{
- return ((mi.x() <= a.mi.x()) &&
- (mi.y() <= a.mi.y()) &&
- (mi.z() <= a.mi.z()) &&
- (mx.x() >= a.mx.x()) &&
- (mx.y() >= a.mx.y()) &&
- (mx.z() >= a.mx.z()));
-}
-
-//
-DBVT_INLINE int btDbvtAabbMm::Classify(const btVector3& n, btScalar o, int s) const
-{
- btVector3 pi, px;
- switch (s)
- {
- case (0 + 0 + 0):
- px = btVector3(mi.x(), mi.y(), mi.z());
- pi = btVector3(mx.x(), mx.y(), mx.z());
- break;
- case (1 + 0 + 0):
- px = btVector3(mx.x(), mi.y(), mi.z());
- pi = btVector3(mi.x(), mx.y(), mx.z());
- break;
- case (0 + 2 + 0):
- px = btVector3(mi.x(), mx.y(), mi.z());
- pi = btVector3(mx.x(), mi.y(), mx.z());
- break;
- case (1 + 2 + 0):
- px = btVector3(mx.x(), mx.y(), mi.z());
- pi = btVector3(mi.x(), mi.y(), mx.z());
- break;
- case (0 + 0 + 4):
- px = btVector3(mi.x(), mi.y(), mx.z());
- pi = btVector3(mx.x(), mx.y(), mi.z());
- break;
- case (1 + 0 + 4):
- px = btVector3(mx.x(), mi.y(), mx.z());
- pi = btVector3(mi.x(), mx.y(), mi.z());
- break;
- case (0 + 2 + 4):
- px = btVector3(mi.x(), mx.y(), mx.z());
- pi = btVector3(mx.x(), mi.y(), mi.z());
- break;
- case (1 + 2 + 4):
- px = btVector3(mx.x(), mx.y(), mx.z());
- pi = btVector3(mi.x(), mi.y(), mi.z());
- break;
- }
- if ((btDot(n, px) + o) < 0) return (-1);
- if ((btDot(n, pi) + o) >= 0) return (+1);
- return (0);
-}
-
-//
-DBVT_INLINE btScalar btDbvtAabbMm::ProjectMinimum(const btVector3& v, unsigned signs) const
-{
- const btVector3* b[] = {&mx, &mi};
- const btVector3 p(b[(signs >> 0) & 1]->x(),
- b[(signs >> 1) & 1]->y(),
- b[(signs >> 2) & 1]->z());
- return (btDot(p, v));
-}
-
-//
-DBVT_INLINE void btDbvtAabbMm::AddSpan(const btVector3& d, btScalar& smi, btScalar& smx) const
-{
- for (int i = 0; i < 3; ++i)
- {
- if (d[i] < 0)
- {
- smi += mx[i] * d[i];
- smx += mi[i] * d[i];
- }
- else
- {
- smi += mi[i] * d[i];
- smx += mx[i] * d[i];
- }
- }
-}
-
-//
-DBVT_INLINE bool Intersect(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
-{
-#if DBVT_INT0_IMPL == DBVT_IMPL_SSE
- const __m128 rt(_mm_or_ps(_mm_cmplt_ps(_mm_load_ps(b.mx), _mm_load_ps(a.mi)),
- _mm_cmplt_ps(_mm_load_ps(a.mx), _mm_load_ps(b.mi))));
-#if defined(_WIN32)
- const __int32* pu((const __int32*)&rt);
-#else
- const int* pu((const int*)&rt);
-#endif
- return ((pu[0] | pu[1] | pu[2]) == 0);
-#else
- return ((a.mi.x() <= b.mx.x()) &&
- (a.mx.x() >= b.mi.x()) &&
- (a.mi.y() <= b.mx.y()) &&
- (a.mx.y() >= b.mi.y()) &&
- (a.mi.z() <= b.mx.z()) &&
- (a.mx.z() >= b.mi.z()));
-#endif
-}
-
-//
-DBVT_INLINE bool Intersect(const btDbvtAabbMm& a,
- const btVector3& b)
-{
- return ((b.x() >= a.mi.x()) &&
- (b.y() >= a.mi.y()) &&
- (b.z() >= a.mi.z()) &&
- (b.x() <= a.mx.x()) &&
- (b.y() <= a.mx.y()) &&
- (b.z() <= a.mx.z()));
-}
-
-//////////////////////////////////////
-
-//
-DBVT_INLINE btScalar Proximity(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
-{
- const btVector3 d = (a.mi + a.mx) - (b.mi + b.mx);
- return (btFabs(d.x()) + btFabs(d.y()) + btFabs(d.z()));
-}
-
-//
-DBVT_INLINE int Select(const btDbvtAabbMm& o,
- const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
-{
-#if DBVT_SELECT_IMPL == DBVT_IMPL_SSE
-
-#if defined(_WIN32)
- static ATTRIBUTE_ALIGNED16(const unsigned __int32) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff};
-#else
- static ATTRIBUTE_ALIGNED16(const unsigned int) mask[] = {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x00000000 /*0x7fffffff*/};
-#endif
- ///@todo: the intrinsic version is 11% slower
-#if DBVT_USE_INTRINSIC_SSE
-
- union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
- {
- __m128 ssereg;
- float floats[4];
- int ints[4];
- };
-
- __m128 omi(_mm_load_ps(o.mi));
- omi = _mm_add_ps(omi, _mm_load_ps(o.mx));
- __m128 ami(_mm_load_ps(a.mi));
- ami = _mm_add_ps(ami, _mm_load_ps(a.mx));
- ami = _mm_sub_ps(ami, omi);
- ami = _mm_and_ps(ami, _mm_load_ps((const float*)mask));
- __m128 bmi(_mm_load_ps(b.mi));
- bmi = _mm_add_ps(bmi, _mm_load_ps(b.mx));
- bmi = _mm_sub_ps(bmi, omi);
- bmi = _mm_and_ps(bmi, _mm_load_ps((const float*)mask));
- __m128 t0(_mm_movehl_ps(ami, ami));
- ami = _mm_add_ps(ami, t0);
- ami = _mm_add_ss(ami, _mm_shuffle_ps(ami, ami, 1));
- __m128 t1(_mm_movehl_ps(bmi, bmi));
- bmi = _mm_add_ps(bmi, t1);
- bmi = _mm_add_ss(bmi, _mm_shuffle_ps(bmi, bmi, 1));
-
- btSSEUnion tmp;
- tmp.ssereg = _mm_cmple_ss(bmi, ami);
- return tmp.ints[0] & 1;
-
-#else
- ATTRIBUTE_ALIGNED16(__int32 r[1]);
- __asm
- {
- mov eax,o
- mov ecx,a
- mov edx,b
- movaps xmm0,[eax]
- movaps xmm5,mask
- addps xmm0,[eax+16]
- movaps xmm1,[ecx]
- movaps xmm2,[edx]
- addps xmm1,[ecx+16]
- addps xmm2,[edx+16]
- subps xmm1,xmm0
- subps xmm2,xmm0
- andps xmm1,xmm5
- andps xmm2,xmm5
- movhlps xmm3,xmm1
- movhlps xmm4,xmm2
- addps xmm1,xmm3
- addps xmm2,xmm4
- pshufd xmm3,xmm1,1
- pshufd xmm4,xmm2,1
- addss xmm1,xmm3
- addss xmm2,xmm4
- cmpless xmm2,xmm1
- movss r,xmm2
- }
- return (r[0] & 1);
-#endif
-#else
- return (Proximity(o, a) < Proximity(o, b) ? 0 : 1);
-#endif
-}
-
-//
-DBVT_INLINE void Merge(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b,
- btDbvtAabbMm& r)
-{
-#if DBVT_MERGE_IMPL == DBVT_IMPL_SSE
- __m128 ami(_mm_load_ps(a.mi));
- __m128 amx(_mm_load_ps(a.mx));
- __m128 bmi(_mm_load_ps(b.mi));
- __m128 bmx(_mm_load_ps(b.mx));
- ami = _mm_min_ps(ami, bmi);
- amx = _mm_max_ps(amx, bmx);
- _mm_store_ps(r.mi, ami);
- _mm_store_ps(r.mx, amx);
-#else
- for (int i = 0; i < 3; ++i)
- {
- if (a.mi[i] < b.mi[i])
- r.mi[i] = a.mi[i];
- else
- r.mi[i] = b.mi[i];
- if (a.mx[i] > b.mx[i])
- r.mx[i] = a.mx[i];
- else
- r.mx[i] = b.mx[i];
- }
-#endif
-}
-
-//
-DBVT_INLINE bool NotEqual(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b)
-{
- return ((a.mi.x() != b.mi.x()) ||
- (a.mi.y() != b.mi.y()) ||
- (a.mi.z() != b.mi.z()) ||
- (a.mx.x() != b.mx.x()) ||
- (a.mx.y() != b.mx.y()) ||
- (a.mx.z() != b.mx.z()));
-}
-
-//
-// Inline's
-//
-
-//
-DBVT_PREFIX
-inline void btDbvt::enumNodes(const btDbvtNode* root,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- policy.Process(root);
- if (root->isinternal())
- {
- enumNodes(root->childs[0], policy);
- enumNodes(root->childs[1], policy);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::enumLeaves(const btDbvtNode* root,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root->isinternal())
- {
- enumLeaves(root->childs[0], policy);
- enumLeaves(root->childs[1], policy);
- }
- else
- {
- policy.Process(root);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::collideTT(const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root0 && root1)
- {
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 4;
- btAlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(DOUBLE_STACKSIZE);
- stkStack[0] = sStkNN(root0, root1);
- do
- {
- sStkNN p = stkStack[--depth];
- if (depth > treshold)
- {
- stkStack.resize(stkStack.size() * 2);
- treshold = stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::selfCollideT(const btDbvntNode* root,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 4;
- btAlignedObjectArray<sStknNN> stkStack;
- stkStack.resize(DOUBLE_STACKSIZE);
- stkStack[0] = sStknNN(root, root);
- do
- {
- sStknNN p = stkStack[--depth];
- if (depth > treshold)
- {
- stkStack.resize(stkStack.size() * 2);
- treshold = stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal() && p.a->angle > SIMD_PI)
- {
- stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[0]);
- stkStack[depth++] = sStknNN(p.a->childs[1], p.a->childs[1]);
- stkStack[depth++] = sStknNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[0]);
- stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[0]);
- stkStack[depth++] = sStknNN(p.a->childs[0], p.b->childs[1]);
- stkStack[depth++] = sStknNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- stkStack[depth++] = sStknNN(p.a->childs[0], p.b);
- stkStack[depth++] = sStknNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStknNN(p.a, p.b->childs[0]);
- stkStack[depth++] = sStknNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::selfCollideTT(const btDbvtNode* root,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 4;
- btAlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(DOUBLE_STACKSIZE);
- stkStack[0] = sStkNN(root, root);
- do
- {
- sStkNN p = stkStack[--depth];
- if (depth > treshold)
- {
- stkStack.resize(stkStack.size() * 2);
- treshold = stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
- stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
- stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-
-DBVT_PREFIX
-inline void btDbvt::collideTTpersistentStack(const btDbvtNode* root0,
- const btDbvtNode* root1,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root0 && root1)
- {
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 4;
-
- m_stkStack.resize(DOUBLE_STACKSIZE);
- m_stkStack[0] = sStkNN(root0, root1);
- do
- {
- sStkNN p = m_stkStack[--depth];
- if (depth > treshold)
- {
- m_stkStack.resize(m_stkStack.size() * 2);
- treshold = m_stkStack.size() - 4;
- }
- if (p.a == p.b)
- {
- if (p.a->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.a->childs[1]);
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.a->childs[1]);
- }
- }
- else if (Intersect(p.a->volume, p.b->volume))
- {
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b->childs[1]);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- m_stkStack[depth++] = sStkNN(p.a->childs[0], p.b);
- m_stkStack[depth++] = sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- m_stkStack[depth++] = sStkNN(p.a, p.b->childs[0]);
- m_stkStack[depth++] = sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-#if 0
-//
-DBVT_PREFIX
-inline void btDbvt::collideTT( const btDbvtNode* root0,
- const btDbvtNode* root1,
- const btTransform& xform,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if(root0&&root1)
- {
- int depth=1;
- int treshold=DOUBLE_STACKSIZE-4;
- btAlignedObjectArray<sStkNN> stkStack;
- stkStack.resize(DOUBLE_STACKSIZE);
- stkStack[0]=sStkNN(root0,root1);
- do {
- sStkNN p=stkStack[--depth];
- if(Intersect(p.a->volume,p.b->volume,xform))
- {
- if(depth>treshold)
- {
- stkStack.resize(stkStack.size()*2);
- treshold=stkStack.size()-4;
- }
- if(p.a->isinternal())
- {
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
- }
- else
- {
- stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
- stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
- }
- }
- else
- {
- if(p.b->isinternal())
- {
- stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
- stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
- }
- else
- {
- policy.Process(p.a,p.b);
- }
- }
- }
- } while(depth);
- }
-}
-//
-DBVT_PREFIX
-inline void btDbvt::collideTT( const btDbvtNode* root0,
- const btTransform& xform0,
- const btDbvtNode* root1,
- const btTransform& xform1,
- DBVT_IPOLICY)
-{
- const btTransform xform=xform0.inverse()*xform1;
- collideTT(root0,root1,xform,policy);
-}
-#endif
-
-DBVT_PREFIX
-inline void btDbvt::collideTV(const btDbvtNode* root,
- const btDbvtVolume& vol,
- DBVT_IPOLICY) const
-{
- DBVT_CHECKTYPE
- if (root)
- {
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- volume(vol);
- btAlignedObjectArray<const btDbvtNode*> stack;
- stack.resize(0);
-#ifndef BT_DISABLE_STACK_TEMP_MEMORY
- char tempmemory[SIMPLE_STACKSIZE * sizeof(const btDbvtNode*)];
- stack.initializeFromBuffer(tempmemory, 0, SIMPLE_STACKSIZE);
-#else
- stack.reserve(SIMPLE_STACKSIZE);
-#endif //BT_DISABLE_STACK_TEMP_MEMORY
-
- stack.push_back(root);
- do
- {
- const btDbvtNode* n = stack[stack.size() - 1];
- stack.pop_back();
- if (Intersect(n->volume, volume))
- {
- if (n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
- }
- } while (stack.size() > 0);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::collideTVNoStackAlloc(const btDbvtNode* root,
- const btDbvtVolume& vol,
- btNodeStack& stack,
- DBVT_IPOLICY) const
-{
- DBVT_CHECKTYPE
- if (root)
- {
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- volume(vol);
- stack.resize(0);
- stack.reserve(SIMPLE_STACKSIZE);
- stack.push_back(root);
- do
- {
- const btDbvtNode* n = stack[stack.size() - 1];
- stack.pop_back();
- if (Intersect(n->volume, volume))
- {
- if (n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
- }
- } while (stack.size() > 0);
- }
-}
-
-DBVT_PREFIX
-inline void btDbvt::rayTestInternal(const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayDirectionInverse,
- unsigned int signs[3],
- btScalar lambda_max,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btAlignedObjectArray<const btDbvtNode*>& stack,
- DBVT_IPOLICY) const
-{
- (void)rayTo;
- DBVT_CHECKTYPE
- if (root)
- {
- btVector3 resultNormal;
-
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 2;
- stack.resize(DOUBLE_STACKSIZE);
- stack[0] = root;
- btVector3 bounds[2];
- do
- {
- const btDbvtNode* node = stack[--depth];
- bounds[0] = node->volume.Mins() - aabbMax;
- bounds[1] = node->volume.Maxs() - aabbMin;
- btScalar tmin = 1.f, lambda_min = 0.f;
- unsigned int result1 = false;
- result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
- if (result1)
- {
- if (node->isinternal())
- {
- if (depth > treshold)
- {
- stack.resize(stack.size() * 2);
- treshold = stack.size() - 2;
- }
- stack[depth++] = node->childs[0];
- stack[depth++] = node->childs[1];
- }
- else
- {
- policy.Process(node);
- }
- }
- } while (depth);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::rayTest(const btDbvtNode* root,
- const btVector3& rayFrom,
- const btVector3& rayTo,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- btVector3 rayDir = (rayTo - rayFrom);
- rayDir.normalize();
-
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- btVector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- unsigned int signs[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
-
- btScalar lambda_max = rayDir.dot(rayTo - rayFrom);
-
- btVector3 resultNormal;
-
- btAlignedObjectArray<const btDbvtNode*> stack;
-
- int depth = 1;
- int treshold = DOUBLE_STACKSIZE - 2;
-
- char tempmemory[DOUBLE_STACKSIZE * sizeof(const btDbvtNode*)];
-#ifndef BT_DISABLE_STACK_TEMP_MEMORY
- stack.initializeFromBuffer(tempmemory, DOUBLE_STACKSIZE, DOUBLE_STACKSIZE);
-#else //BT_DISABLE_STACK_TEMP_MEMORY
- stack.resize(DOUBLE_STACKSIZE);
-#endif //BT_DISABLE_STACK_TEMP_MEMORY
- stack[0] = root;
- btVector3 bounds[2];
- do
- {
- const btDbvtNode* node = stack[--depth];
-
- bounds[0] = node->volume.Mins();
- bounds[1] = node->volume.Maxs();
-
- btScalar tmin = 1.f, lambda_min = 0.f;
- unsigned int result1 = btRayAabb2(rayFrom, rayDirectionInverse, signs, bounds, tmin, lambda_min, lambda_max);
-
-#ifdef COMPARE_BTRAY_AABB2
- btScalar param = 1.f;
- bool result2 = btRayAabb(rayFrom, rayTo, node->volume.Mins(), node->volume.Maxs(), param, resultNormal);
- btAssert(result1 == result2);
-#endif //TEST_BTRAY_AABB2
-
- if (result1)
- {
- if (node->isinternal())
- {
- if (depth > treshold)
- {
- stack.resize(stack.size() * 2);
- treshold = stack.size() - 2;
- }
- stack[depth++] = node->childs[0];
- stack[depth++] = node->childs[1];
- }
- else
- {
- policy.Process(node);
- }
- }
- } while (depth);
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::collideKDOP(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- int count,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- const int inside = (1 << count) - 1;
- btAlignedObjectArray<sStkNP> stack;
- int signs[sizeof(unsigned) * 8];
- btAssert(count < int(sizeof(signs) / sizeof(signs[0])));
- for (int i = 0; i < count; ++i)
- {
- signs[i] = ((normals[i].x() >= 0) ? 1 : 0) +
- ((normals[i].y() >= 0) ? 2 : 0) +
- ((normals[i].z() >= 0) ? 4 : 0);
- }
- stack.reserve(SIMPLE_STACKSIZE);
- stack.push_back(sStkNP(root, 0));
- do
- {
- sStkNP se = stack[stack.size() - 1];
- bool out = false;
- stack.pop_back();
- for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
- {
- if (0 == (se.mask & j))
- {
- const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
- switch (side)
- {
- case -1:
- out = true;
- break;
- case +1:
- se.mask |= j;
- break;
- }
- }
- }
- if (!out)
- {
- if ((se.mask != inside) && (se.node->isinternal()))
- {
- stack.push_back(sStkNP(se.node->childs[0], se.mask));
- stack.push_back(sStkNP(se.node->childs[1], se.mask));
- }
- else
- {
- if (policy.AllLeaves(se.node)) enumLeaves(se.node, policy);
- }
- }
- } while (stack.size());
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::collideOCL(const btDbvtNode* root,
- const btVector3* normals,
- const btScalar* offsets,
- const btVector3& sortaxis,
- int count,
- DBVT_IPOLICY,
- bool fsort)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- const unsigned srtsgns = (sortaxis[0] >= 0 ? 1 : 0) +
- (sortaxis[1] >= 0 ? 2 : 0) +
- (sortaxis[2] >= 0 ? 4 : 0);
- const int inside = (1 << count) - 1;
- btAlignedObjectArray<sStkNPS> stock;
- btAlignedObjectArray<int> ifree;
- btAlignedObjectArray<int> stack;
- int signs[sizeof(unsigned) * 8];
- btAssert(count < int(sizeof(signs) / sizeof(signs[0])));
- for (int i = 0; i < count; ++i)
- {
- signs[i] = ((normals[i].x() >= 0) ? 1 : 0) +
- ((normals[i].y() >= 0) ? 2 : 0) +
- ((normals[i].z() >= 0) ? 4 : 0);
- }
- stock.reserve(SIMPLE_STACKSIZE);
- stack.reserve(SIMPLE_STACKSIZE);
- ifree.reserve(SIMPLE_STACKSIZE);
- stack.push_back(allocate(ifree, stock, sStkNPS(root, 0, root->volume.ProjectMinimum(sortaxis, srtsgns))));
- do
- {
- const int id = stack[stack.size() - 1];
- sStkNPS se = stock[id];
- stack.pop_back();
- ifree.push_back(id);
- if (se.mask != inside)
- {
- bool out = false;
- for (int i = 0, j = 1; (!out) && (i < count); ++i, j <<= 1)
- {
- if (0 == (se.mask & j))
- {
- const int side = se.node->volume.Classify(normals[i], offsets[i], signs[i]);
- switch (side)
- {
- case -1:
- out = true;
- break;
- case +1:
- se.mask |= j;
- break;
- }
- }
- }
- if (out) continue;
- }
- if (policy.Descent(se.node))
- {
- if (se.node->isinternal())
- {
- const btDbvtNode* pns[] = {se.node->childs[0], se.node->childs[1]};
- sStkNPS nes[] = {sStkNPS(pns[0], se.mask, pns[0]->volume.ProjectMinimum(sortaxis, srtsgns)),
- sStkNPS(pns[1], se.mask, pns[1]->volume.ProjectMinimum(sortaxis, srtsgns))};
- const int q = nes[0].value < nes[1].value ? 1 : 0;
- int j = stack.size();
- if (fsort && (j > 0))
- {
- /* Insert 0 */
- j = nearest(&stack[0], &stock[0], nes[q].value, 0, stack.size());
- stack.push_back(0);
-
- //void * memmove ( void * destination, const void * source, size_t num );
-
-#if DBVT_USE_MEMMOVE
- {
- int num_items_to_move = stack.size() - 1 - j;
- if (num_items_to_move > 0)
- memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
- }
-#else
- for (int k = stack.size() - 1; k > j; --k)
- {
- stack[k] = stack[k - 1];
- }
-#endif
- stack[j] = allocate(ifree, stock, nes[q]);
- /* Insert 1 */
- j = nearest(&stack[0], &stock[0], nes[1 - q].value, j, stack.size());
- stack.push_back(0);
-#if DBVT_USE_MEMMOVE
- {
- int num_items_to_move = stack.size() - 1 - j;
- if (num_items_to_move > 0)
- memmove(&stack[j + 1], &stack[j], sizeof(int) * num_items_to_move);
- }
-#else
- for (int k = stack.size() - 1; k > j; --k)
- {
- stack[k] = stack[k - 1];
- }
-#endif
- stack[j] = allocate(ifree, stock, nes[1 - q]);
- }
- else
- {
- stack.push_back(allocate(ifree, stock, nes[q]));
- stack.push_back(allocate(ifree, stock, nes[1 - q]));
- }
- }
- else
- {
- policy.Process(se.node, se.value);
- }
- }
- } while (stack.size());
- }
-}
-
-//
-DBVT_PREFIX
-inline void btDbvt::collideTU(const btDbvtNode* root,
- DBVT_IPOLICY)
-{
- DBVT_CHECKTYPE
- if (root)
- {
- btAlignedObjectArray<const btDbvtNode*> stack;
- stack.reserve(SIMPLE_STACKSIZE);
- stack.push_back(root);
- do
- {
- const btDbvtNode* n = stack[stack.size() - 1];
- stack.pop_back();
- if (policy.Descent(n))
- {
- if (n->isinternal())
- {
- stack.push_back(n->childs[0]);
- stack.push_back(n->childs[1]);
- }
- else
- {
- policy.Process(n);
- }
- }
- } while (stack.size() > 0);
- }
-}
-
-//
-// PP Cleanup
-//
-
-#undef DBVT_USE_MEMMOVE
-#undef DBVT_USE_TEMPLATE
-#undef DBVT_VIRTUAL_DTOR
-#undef DBVT_VIRTUAL
-#undef DBVT_PREFIX
-#undef DBVT_IPOLICY
-#undef DBVT_CHECKTYPE
-#undef DBVT_IMPL_GENERIC
-#undef DBVT_IMPL_SSE
-#undef DBVT_USE_INTRINSIC_SSE
-#undef DBVT_SELECT_IMPL
-#undef DBVT_MERGE_IMPL
-#undef DBVT_INT0_IMPL
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
deleted file mode 100644
index 7b39dbdc0f..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///btDbvtBroadphase implementation by Nathanael Presson
-
-#include "btDbvtBroadphase.h"
-#include "LinearMath/btThreads.h"
-btScalar gDbvtMargin = btScalar(0.05);
-//
-// Profiling
-//
-
-#if DBVT_BP_PROFILE || DBVT_BP_ENABLE_BENCHMARK
-#include <stdio.h>
-#endif
-
-#if DBVT_BP_PROFILE
-struct ProfileScope
-{
- __forceinline ProfileScope(btClock& clock, unsigned long& value) : m_clock(&clock), m_value(&value), m_base(clock.getTimeMicroseconds())
- {
- }
- __forceinline ~ProfileScope()
- {
- (*m_value) += m_clock->getTimeMicroseconds() - m_base;
- }
- btClock* m_clock;
- unsigned long* m_value;
- unsigned long m_base;
-};
-#define SPC(_value_) ProfileScope spc_scope(m_clock, _value_)
-#else
-#define SPC(_value_)
-#endif
-
-//
-// Helpers
-//
-
-//
-template <typename T>
-static inline void listappend(T* item, T*& list)
-{
- item->links[0] = 0;
- item->links[1] = list;
- if (list) list->links[0] = item;
- list = item;
-}
-
-//
-template <typename T>
-static inline void listremove(T* item, T*& list)
-{
- if (item->links[0])
- item->links[0]->links[1] = item->links[1];
- else
- list = item->links[1];
- if (item->links[1]) item->links[1]->links[0] = item->links[0];
-}
-
-//
-template <typename T>
-static inline int listcount(T* root)
-{
- int n = 0;
- while (root)
- {
- ++n;
- root = root->links[1];
- }
- return (n);
-}
-
-//
-template <typename T>
-static inline void clear(T& value)
-{
- static const struct ZeroDummy : T
- {
- } zerodummy;
- value = zerodummy;
-}
-
-//
-// Colliders
-//
-
-/* Tree collider */
-struct btDbvtTreeCollider : btDbvt::ICollide
-{
- btDbvtBroadphase* pbp;
- btDbvtProxy* proxy;
- btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
- void Process(const btDbvtNode* na, const btDbvtNode* nb)
- {
- if (na != nb)
- {
- btDbvtProxy* pa = (btDbvtProxy*)na->data;
- btDbvtProxy* pb = (btDbvtProxy*)nb->data;
-#if DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- btSwap(pa, pb);
-#endif
- pbp->m_paircache->addOverlappingPair(pa, pb);
- ++pbp->m_newpairs;
- }
- }
- void Process(const btDbvtNode* n)
- {
- Process(n, proxy->leaf);
- }
-};
-
-//
-// btDbvtBroadphase
-//
-
-//
-btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
-{
- m_deferedcollide = false;
- m_needcleanup = true;
- m_releasepaircache = (paircache != 0) ? false : true;
- m_prediction = 0;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
- m_paircache = paircache ? paircache : new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
-#if BT_THREADSAFE
- m_rayTestStacks.resize(BT_MAX_THREAD_COUNT);
-#else
- m_rayTestStacks.resize(1);
-#endif
-#if DBVT_BP_PROFILE
- clear(m_profiling);
-#endif
-}
-
-//
-btDbvtBroadphase::~btDbvtBroadphase()
-{
- if (m_releasepaircache)
- {
- m_paircache->~btOverlappingPairCache();
- btAlignedFree(m_paircache);
- }
-}
-
-//
-btBroadphaseProxy* btDbvtBroadphase::createProxy(const btVector3& aabbMin,
- const btVector3& aabbMax,
- int /*shapeType*/,
- void* userPtr,
- int collisionFilterGroup,
- int collisionFilterMask,
- btDispatcher* /*dispatcher*/)
-{
- btDbvtProxy* proxy = new (btAlignedAlloc(sizeof(btDbvtProxy), 16)) btDbvtProxy(aabbMin, aabbMax, userPtr,
- collisionFilterGroup,
- collisionFilterMask);
-
- btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
-
- //bproxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
- proxy->stage = m_stageCurrent;
- proxy->m_uniqueId = ++m_gid;
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- collider.proxy = proxy;
- m_sets[0].collideTV(m_sets[0].m_root, aabb, collider);
- m_sets[1].collideTV(m_sets[1].m_root, aabb, collider);
- }
- return (proxy);
-}
-
-//
-void btDbvtBroadphase::destroyProxy(btBroadphaseProxy* absproxy,
- btDispatcher* dispatcher)
-{
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- if (proxy->stage == STAGECOUNT)
- m_sets[1].remove(proxy->leaf);
- else
- m_sets[0].remove(proxy->leaf);
- listremove(proxy, m_stageRoots[proxy->stage]);
- m_paircache->removeOverlappingPairsContainingProxy(proxy, dispatcher);
- btAlignedFree(proxy);
- m_needcleanup = true;
-}
-
-void btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- aabbMin = proxy->m_aabbMin;
- aabbMax = proxy->m_aabbMax;
-}
-
-struct BroadphaseRayTester : btDbvt::ICollide
-{
- btBroadphaseRayCallback& m_rayCallback;
- BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
- : m_rayCallback(orgCallback)
- {
- }
- void Process(const btDbvtNode* leaf)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
- m_rayCallback.process(proxy);
- }
-};
-
-void btDbvtBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- BroadphaseRayTester callback(rayCallback);
- btAlignedObjectArray<const btDbvtNode*>* stack = &m_rayTestStacks[0];
-#if BT_THREADSAFE
- // for this function to be threadsafe, each thread must have a separate copy
- // of this stack. This could be thread-local static to avoid dynamic allocations,
- // instead of just a local.
- int threadIndex = btGetCurrentThreadIndex();
- btAlignedObjectArray<const btDbvtNode*> localStack;
- //todo(erwincoumans, "why do we get tsan issue here?")
- if (0)//threadIndex < m_rayTestStacks.size())
- //if (threadIndex < m_rayTestStacks.size())
- {
- // use per-thread preallocated stack if possible to avoid dynamic allocations
- stack = &m_rayTestStacks[threadIndex];
- }
- else
- {
- stack = &localStack;
- }
-#endif
-
- m_sets[0].rayTestInternal(m_sets[0].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
-
- m_sets[1].rayTestInternal(m_sets[1].m_root,
- rayFrom,
- rayTo,
- rayCallback.m_rayDirectionInverse,
- rayCallback.m_signs,
- rayCallback.m_lambda_max,
- aabbMin,
- aabbMax,
- *stack,
- callback);
-}
-
-struct BroadphaseAabbTester : btDbvt::ICollide
-{
- btBroadphaseAabbCallback& m_aabbCallback;
- BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
- : m_aabbCallback(orgCallback)
- {
- }
- void Process(const btDbvtNode* leaf)
- {
- btDbvtProxy* proxy = (btDbvtProxy*)leaf->data;
- m_aabbCallback.process(proxy);
- }
-};
-
-void btDbvtBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& aabbCallback)
-{
- BroadphaseAabbTester callback(aabbCallback);
-
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(aabbMin, aabbMax);
- //process all children, that overlap with the given AABB bounds
- m_sets[0].collideTV(m_sets[0].m_root, bounds, callback);
- m_sets[1].collideTV(m_sets[1].m_root, bounds, callback);
-}
-
-//
-void btDbvtBroadphase::setAabb(btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
-{
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
-#if DBVT_BP_PREVENTFALSEUPDATE
- if (NotEqual(aabb, proxy->leaf->volume))
-#endif
- {
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- if (Intersect(proxy->leaf->volume, aabb))
- { /* Moving */
-
- const btVector3 delta = aabbMin - proxy->m_aabbMin;
- btVector3 velocity(((proxy->m_aabbMax - proxy->m_aabbMin) / 2) * m_prediction);
- if (delta[0] < 0) velocity[0] = -velocity[0];
- if (delta[1] < 0) velocity[1] = -velocity[1];
- if (delta[2] < 0) velocity[2] = -velocity[2];
- if (
- m_sets[0].update(proxy->leaf, aabb, velocity, gDbvtMargin)
-
- )
- {
- ++m_updates_done;
- docollide = true;
- }
- }
- else
- { /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- }
- listremove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
- }
-}
-
-//
-void btDbvtBroadphase::setAabbForceUpdate(btBroadphaseProxy* absproxy,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btDispatcher* /*dispatcher*/)
-{
- btDbvtProxy* proxy = (btDbvtProxy*)absproxy;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- aabb = btDbvtVolume::FromMM(aabbMin, aabbMax);
- bool docollide = false;
- if (proxy->stage == STAGECOUNT)
- { /* fixed -> dynamic set */
- m_sets[1].remove(proxy->leaf);
- proxy->leaf = m_sets[0].insert(aabb, proxy);
- docollide = true;
- }
- else
- { /* dynamic set */
- ++m_updates_call;
- /* Teleporting */
- m_sets[0].update(proxy->leaf, aabb);
- ++m_updates_done;
- docollide = true;
- }
- listremove(proxy, m_stageRoots[proxy->stage]);
- proxy->m_aabbMin = aabbMin;
- proxy->m_aabbMax = aabbMax;
- proxy->stage = m_stageCurrent;
- listappend(proxy, m_stageRoots[m_stageCurrent]);
- if (docollide)
- {
- m_needcleanup = true;
- if (!m_deferedcollide)
- {
- btDbvtTreeCollider collider(this);
- m_sets[1].collideTTpersistentStack(m_sets[1].m_root, proxy->leaf, collider);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, proxy->leaf, collider);
- }
- }
-}
-
-//
-void btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
-{
- collide(dispatcher);
-#if DBVT_BP_PROFILE
- if (0 == (m_pid % DBVT_BP_PROFILING_RATE))
- {
- printf("fixed(%u) dynamics(%u) pairs(%u)\r\n", m_sets[1].m_leaves, m_sets[0].m_leaves, m_paircache->getNumOverlappingPairs());
- unsigned int total = m_profiling.m_total;
- if (total <= 0) total = 1;
- printf("ddcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_ddcollide * 100) / total, m_profiling.m_ddcollide / DBVT_BP_PROFILING_RATE);
- printf("fdcollide: %u%% (%uus)\r\n", (50 + m_profiling.m_fdcollide * 100) / total, m_profiling.m_fdcollide / DBVT_BP_PROFILING_RATE);
- printf("cleanup: %u%% (%uus)\r\n", (50 + m_profiling.m_cleanup * 100) / total, m_profiling.m_cleanup / DBVT_BP_PROFILING_RATE);
- printf("total: %uus\r\n", total / DBVT_BP_PROFILING_RATE);
- const unsigned long sum = m_profiling.m_ddcollide +
- m_profiling.m_fdcollide +
- m_profiling.m_cleanup;
- printf("leaked: %u%% (%uus)\r\n", 100 - ((50 + sum * 100) / total), (total - sum) / DBVT_BP_PROFILING_RATE);
- printf("job counts: %u%%\r\n", (m_profiling.m_jobcount * 100) / ((m_sets[0].m_leaves + m_sets[1].m_leaves) * DBVT_BP_PROFILING_RATE));
- clear(m_profiling);
- m_clock.reset();
- }
-#endif
-
- performDeferredRemoval(dispatcher);
-}
-
-void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
-{
- if (m_paircache->hasDeferredRemoval())
- {
- btBroadphasePairArray& overlappingPairArray = m_paircache->getOverlappingPairArray();
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
-
- int invalidPair = 0;
-
- int i;
-
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
-
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- btBroadphasePair& pair = overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- //important to perform AABB check that is consistent with the broadphase
- btDbvtProxy* pa = (btDbvtProxy*)pair.m_pProxy0;
- btDbvtProxy* pb = (btDbvtProxy*)pair.m_pProxy1;
- bool hasOverlap = Intersect(pa->leaf->volume, pb->leaf->volume);
-
- if (hasOverlap)
- {
- needsRemoval = false;
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
-
- if (needsRemoval)
- {
- m_paircache->cleanOverlappingPair(pair, dispatcher);
-
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- invalidPair++;
- }
- }
-
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
- overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
- }
-}
-
-//
-void btDbvtBroadphase::collide(btDispatcher* dispatcher)
-{
- /*printf("---------------------------------------------------------\n");
- printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
- printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
- printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
- {
- int i;
- for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
- {
- printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
- getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
- }
- printf("\n");
- }
-*/
-
- SPC(m_profiling.m_total);
- /* optimize */
- m_sets[0].optimizeIncremental(1 + (m_sets[0].m_leaves * m_dupdates) / 100);
- if (m_fixedleft)
- {
- const int count = 1 + (m_sets[1].m_leaves * m_fupdates) / 100;
- m_sets[1].optimizeIncremental(1 + (m_sets[1].m_leaves * m_fupdates) / 100);
- m_fixedleft = btMax<int>(0, m_fixedleft - count);
- }
- /* dynamic -> fixed set */
- m_stageCurrent = (m_stageCurrent + 1) % STAGECOUNT;
- btDbvtProxy* current = m_stageRoots[m_stageCurrent];
- if (current)
- {
-#if DBVT_BP_ACCURATESLEEPING
- btDbvtTreeCollider collider(this);
-#endif
- do
- {
- btDbvtProxy* next = current->links[1];
- listremove(current, m_stageRoots[current->stage]);
- listappend(current, m_stageRoots[STAGECOUNT]);
-#if DBVT_BP_ACCURATESLEEPING
- m_paircache->removeOverlappingPairsContainingProxy(current, dispatcher);
- collider.proxy = current;
- btDbvt::collideTV(m_sets[0].m_root, current->aabb, collider);
- btDbvt::collideTV(m_sets[1].m_root, current->aabb, collider);
-#endif
- m_sets[0].remove(current->leaf);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- curAabb = btDbvtVolume::FromMM(current->m_aabbMin, current->m_aabbMax);
- current->leaf = m_sets[1].insert(curAabb, current);
- current->stage = STAGECOUNT;
- current = next;
- } while (current);
- m_fixedleft = m_sets[1].m_leaves;
- m_needcleanup = true;
- }
- /* collide dynamics */
- {
- btDbvtTreeCollider collider(this);
- if (m_deferedcollide)
- {
- SPC(m_profiling.m_fdcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[1].m_root, collider);
- }
- if (m_deferedcollide)
- {
- SPC(m_profiling.m_ddcollide);
- m_sets[0].collideTTpersistentStack(m_sets[0].m_root, m_sets[0].m_root, collider);
- }
- }
- /* clean up */
- if (m_needcleanup)
- {
- SPC(m_profiling.m_cleanup);
- btBroadphasePairArray& pairs = m_paircache->getOverlappingPairArray();
- if (pairs.size() > 0)
- {
- int ni = btMin(pairs.size(), btMax<int>(m_newpairs, (pairs.size() * m_cupdates) / 100));
- for (int i = 0; i < ni; ++i)
- {
- btBroadphasePair& p = pairs[(m_cid + i) % pairs.size()];
- btDbvtProxy* pa = (btDbvtProxy*)p.m_pProxy0;
- btDbvtProxy* pb = (btDbvtProxy*)p.m_pProxy1;
- if (!Intersect(pa->leaf->volume, pb->leaf->volume))
- {
-#if DBVT_BP_SORTPAIRS
- if (pa->m_uniqueId > pb->m_uniqueId)
- btSwap(pa, pb);
-#endif
- m_paircache->removeOverlappingPair(pa, pb, dispatcher);
- --ni;
- --i;
- }
- }
- if (pairs.size() > 0)
- m_cid = (m_cid + ni) % pairs.size();
- else
- m_cid = 0;
- }
- }
- ++m_pid;
- m_newpairs = 1;
- m_needcleanup = false;
- if (m_updates_call > 0)
- {
- m_updates_ratio = m_updates_done / (btScalar)m_updates_call;
- }
- else
- {
- m_updates_ratio = 0;
- }
- m_updates_done /= 2;
- m_updates_call /= 2;
-}
-
-//
-void btDbvtBroadphase::optimize()
-{
- m_sets[0].optimizeTopDown();
- m_sets[1].optimizeTopDown();
-}
-
-//
-btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache()
-{
- return (m_paircache);
-}
-
-//
-const btOverlappingPairCache* btDbvtBroadphase::getOverlappingPairCache() const
-{
- return (m_paircache);
-}
-
-//
-void btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
-{
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- bounds;
-
- if (!m_sets[0].empty())
- if (!m_sets[1].empty())
- Merge(m_sets[0].m_root->volume,
- m_sets[1].m_root->volume, bounds);
- else
- bounds = m_sets[0].m_root->volume;
- else if (!m_sets[1].empty())
- bounds = m_sets[1].m_root->volume;
- else
- bounds = btDbvtVolume::FromCR(btVector3(0, 0, 0), 0);
- aabbMin = bounds.Mins();
- aabbMax = bounds.Maxs();
-}
-
-void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
-{
- int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
- if (!totalObjects)
- {
- //reset internal dynamic tree data structures
- m_sets[0].clear();
- m_sets[1].clear();
-
- m_deferedcollide = false;
- m_needcleanup = true;
- m_stageCurrent = 0;
- m_fixedleft = 0;
- m_fupdates = 1;
- m_dupdates = 0;
- m_cupdates = 10;
- m_newpairs = 1;
- m_updates_call = 0;
- m_updates_done = 0;
- m_updates_ratio = 0;
-
- m_gid = 0;
- m_pid = 0;
- m_cid = 0;
- for (int i = 0; i <= STAGECOUNT; ++i)
- {
- m_stageRoots[i] = 0;
- }
- }
-}
-
-//
-void btDbvtBroadphase::printStats()
-{
-}
-
-//
-#if DBVT_BP_ENABLE_BENCHMARK
-
-struct btBroadphaseBenchmark
-{
- struct Experiment
- {
- const char* name;
- int object_count;
- int update_count;
- int spawn_count;
- int iterations;
- btScalar speed;
- btScalar amplitude;
- };
- struct Object
- {
- btVector3 center;
- btVector3 extents;
- btBroadphaseProxy* proxy;
- btScalar time;
- void update(btScalar speed, btScalar amplitude, btBroadphaseInterface* pbi)
- {
- time += speed;
- center[0] = btCos(time * (btScalar)2.17) * amplitude +
- btSin(time) * amplitude / 2;
- center[1] = btCos(time * (btScalar)1.38) * amplitude +
- btSin(time) * amplitude;
- center[2] = btSin(time * (btScalar)0.777) * amplitude;
- pbi->setAabb(proxy, center - extents, center + extents, 0);
- }
- };
- static int UnsignedRand(int range = RAND_MAX - 1) { return (rand() % (range + 1)); }
- static btScalar UnitRand() { return (UnsignedRand(16384) / (btScalar)16384); }
- static void OutputTime(const char* name, btClock& c, unsigned count = 0)
- {
- const unsigned long us = c.getTimeMicroseconds();
- const unsigned long ms = (us + 500) / 1000;
- const btScalar sec = us / (btScalar)(1000 * 1000);
- if (count > 0)
- printf("%s : %u us (%u ms), %.2f/s\r\n", name, us, ms, count / sec);
- else
- printf("%s : %u us (%u ms)\r\n", name, us, ms);
- }
-};
-
-void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
-{
- static const btBroadphaseBenchmark::Experiment experiments[] =
- {
- {"1024o.10%", 1024, 10, 0, 8192, (btScalar)0.005, (btScalar)100},
- /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
- {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
- };
- static const int nexperiments = sizeof(experiments) / sizeof(experiments[0]);
- btAlignedObjectArray<btBroadphaseBenchmark::Object*> objects;
- btClock wallclock;
- /* Begin */
- for (int iexp = 0; iexp < nexperiments; ++iexp)
- {
- const btBroadphaseBenchmark::Experiment& experiment = experiments[iexp];
- const int object_count = experiment.object_count;
- const int update_count = (object_count * experiment.update_count) / 100;
- const int spawn_count = (object_count * experiment.spawn_count) / 100;
- const btScalar speed = experiment.speed;
- const btScalar amplitude = experiment.amplitude;
- printf("Experiment #%u '%s':\r\n", iexp, experiment.name);
- printf("\tObjects: %u\r\n", object_count);
- printf("\tUpdate: %u\r\n", update_count);
- printf("\tSpawn: %u\r\n", spawn_count);
- printf("\tSpeed: %f\r\n", speed);
- printf("\tAmplitude: %f\r\n", amplitude);
- srand(180673);
- /* Create objects */
- wallclock.reset();
- objects.reserve(object_count);
- for (int i = 0; i < object_count; ++i)
- {
- btBroadphaseBenchmark::Object* po = new btBroadphaseBenchmark::Object();
- po->center[0] = btBroadphaseBenchmark::UnitRand() * 50;
- po->center[1] = btBroadphaseBenchmark::UnitRand() * 50;
- po->center[2] = btBroadphaseBenchmark::UnitRand() * 50;
- po->extents[0] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[1] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->extents[2] = btBroadphaseBenchmark::UnitRand() * 2 + 2;
- po->time = btBroadphaseBenchmark::UnitRand() * 2000;
- po->proxy = pbi->createProxy(po->center - po->extents, po->center + po->extents, 0, po, 1, 1, 0, 0);
- objects.push_back(po);
- }
- btBroadphaseBenchmark::OutputTime("\tInitialization", wallclock);
- /* First update */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- objects[i]->update(speed, amplitude, pbi);
- }
- btBroadphaseBenchmark::OutputTime("\tFirst update", wallclock);
- /* Updates */
- wallclock.reset();
- for (int i = 0; i < experiment.iterations; ++i)
- {
- for (int j = 0; j < update_count; ++j)
- {
- objects[j]->update(speed, amplitude, pbi);
- }
- pbi->calculateOverlappingPairs(0);
- }
- btBroadphaseBenchmark::OutputTime("\tUpdate", wallclock, experiment.iterations);
- /* Clean up */
- wallclock.reset();
- for (int i = 0; i < objects.size(); ++i)
- {
- pbi->destroyProxy(objects[i]->proxy, 0);
- delete objects[i];
- }
- objects.resize(0);
- btBroadphaseBenchmark::OutputTime("\tRelease", wallclock);
- }
-}
-#else
-void btDbvtBroadphase::benchmark(btBroadphaseInterface*)
-{
-}
-#endif
-
-#if DBVT_BP_PROFILE
-#undef SPC
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
deleted file mode 100644
index a71feef53b..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///btDbvtBroadphase implementation by Nathanael Presson
-#ifndef BT_DBVT_BROADPHASE_H
-#define BT_DBVT_BROADPHASE_H
-
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-
-//
-// Compile time config
-//
-
-#define DBVT_BP_PROFILE 0
-//#define DBVT_BP_SORTPAIRS 1
-#define DBVT_BP_PREVENTFALSEUPDATE 0
-#define DBVT_BP_ACCURATESLEEPING 0
-#define DBVT_BP_ENABLE_BENCHMARK 0
-//#define DBVT_BP_MARGIN (btScalar)0.05
-extern btScalar gDbvtMargin;
-
-#if DBVT_BP_PROFILE
-#define DBVT_BP_PROFILING_RATE 256
-#include "LinearMath/btQuickprof.h"
-#endif
-
-//
-// btDbvtProxy
-//
-struct btDbvtProxy : btBroadphaseProxy
-{
- /* Fields */
- //btDbvtAabbMm aabb;
- btDbvtNode* leaf;
- btDbvtProxy* links[2];
- int stage;
- /* ctor */
- btDbvtProxy(const btVector3& aabbMin, const btVector3& aabbMax, void* userPtr, int collisionFilterGroup, int collisionFilterMask) : btBroadphaseProxy(aabbMin, aabbMax, userPtr, collisionFilterGroup, collisionFilterMask)
- {
- links[0] = links[1] = 0;
- }
-};
-
-typedef btAlignedObjectArray<btDbvtProxy*> btDbvtProxyArray;
-
-///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
-///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
-///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
-struct btDbvtBroadphase : btBroadphaseInterface
-{
- /* Config */
- enum
- {
- DYNAMIC_SET = 0, /* Dynamic set index */
- FIXED_SET = 1, /* Fixed set index */
- STAGECOUNT = 2 /* Number of stages */
- };
- /* Fields */
- btDbvt m_sets[2]; // Dbvt sets
- btDbvtProxy* m_stageRoots[STAGECOUNT + 1]; // Stages list
- btOverlappingPairCache* m_paircache; // Pair cache
- btScalar m_prediction; // Velocity prediction
- int m_stageCurrent; // Current stage
- int m_fupdates; // % of fixed updates per frame
- int m_dupdates; // % of dynamic updates per frame
- int m_cupdates; // % of cleanup updates per frame
- int m_newpairs; // Number of pairs created
- int m_fixedleft; // Fixed optimization left
- unsigned m_updates_call; // Number of updates call
- unsigned m_updates_done; // Number of updates done
- btScalar m_updates_ratio; // m_updates_done/m_updates_call
- int m_pid; // Parse id
- int m_cid; // Cleanup index
- int m_gid; // Gen id
- bool m_releasepaircache; // Release pair cache on delete
- bool m_deferedcollide; // Defere dynamic/static collision to collide call
- bool m_needcleanup; // Need to run cleanup?
- btAlignedObjectArray<btAlignedObjectArray<const btDbvtNode*> > m_rayTestStacks;
-#if DBVT_BP_PROFILE
- btClock m_clock;
- struct
- {
- unsigned long m_total;
- unsigned long m_ddcollide;
- unsigned long m_fdcollide;
- unsigned long m_cleanup;
- unsigned long m_jobcount;
- } m_profiling;
-#endif
- /* Methods */
- btDbvtBroadphase(btOverlappingPairCache* paircache = 0);
- ~btDbvtBroadphase();
- void collide(btDispatcher* dispatcher);
- void optimize();
-
- /* btBroadphaseInterface Implementation */
- btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
- virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
- virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
- virtual btOverlappingPairCache* getOverlappingPairCache();
- virtual const btOverlappingPairCache* getOverlappingPairCache() const;
- virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void printStats();
-
- ///reset broadphase internal structures, to ensure determinism/reproducability
- virtual void resetPool(btDispatcher* dispatcher);
-
- void performDeferredRemoval(btDispatcher* dispatcher);
-
- void setVelocityPrediction(btScalar prediction)
- {
- m_prediction = prediction;
- }
- btScalar getVelocityPrediction() const
- {
- return m_prediction;
- }
-
- ///this setAabbForceUpdate is similar to setAabb but always forces the aabb update.
- ///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
- ///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
- ///http://code.google.com/p/bullet/issues/detail?id=223
- void setAabbForceUpdate(btBroadphaseProxy* absproxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/);
-
- static void benchmark(btBroadphaseInterface*);
-};
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
deleted file mode 100644
index d76d408aa6..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btDispatcher.h"
-
-btDispatcher::~btDispatcher()
-{
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
deleted file mode 100644
index b09b7d4d42..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DISPATCHER_H
-#define BT_DISPATCHER_H
-#include "LinearMath/btScalar.h"
-
-class btCollisionAlgorithm;
-struct btBroadphaseProxy;
-class btRigidBody;
-class btCollisionObject;
-class btOverlappingPairCache;
-struct btCollisionObjectWrapper;
-
-class btPersistentManifold;
-class btPoolAllocator;
-
-struct btDispatcherInfo
-{
- enum DispatchFunc
- {
- DISPATCH_DISCRETE = 1,
- DISPATCH_CONTINUOUS
- };
- btDispatcherInfo()
- : m_timeStep(btScalar(0.)),
- m_stepCount(0),
- m_dispatchFunc(DISPATCH_DISCRETE),
- m_timeOfImpact(btScalar(1.)),
- m_useContinuous(true),
- m_debugDraw(0),
- m_enableSatConvex(false),
- m_enableSPU(true),
- m_useEpa(true),
- m_allowedCcdPenetration(btScalar(0.04)),
- m_useConvexConservativeDistanceUtil(false),
- m_convexConservativeDistanceThreshold(0.0f),
- m_deterministicOverlappingPairs(false)
- {
- }
- btScalar m_timeStep;
- int m_stepCount;
- int m_dispatchFunc;
- mutable btScalar m_timeOfImpact;
- bool m_useContinuous;
- class btIDebugDraw* m_debugDraw;
- bool m_enableSatConvex;
- bool m_enableSPU;
- bool m_useEpa;
- btScalar m_allowedCcdPenetration;
- bool m_useConvexConservativeDistanceUtil;
- btScalar m_convexConservativeDistanceThreshold;
- bool m_deterministicOverlappingPairs;
-};
-
-enum ebtDispatcherQueryType
-{
- BT_CONTACT_POINT_ALGORITHMS = 1,
- BT_CLOSEST_POINT_ALGORITHMS = 2
-};
-
-///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
-///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
-class btDispatcher
-{
-public:
- virtual ~btDispatcher();
-
- virtual btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType) = 0;
-
- virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1) = 0;
-
- virtual void releaseManifold(btPersistentManifold* manifold) = 0;
-
- virtual void clearManifold(btPersistentManifold* manifold) = 0;
-
- virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
-
- virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1) = 0;
-
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher) = 0;
-
- virtual int getNumManifolds() const = 0;
-
- virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
-
- virtual btPersistentManifold** getInternalManifoldPointer() = 0;
-
- virtual btPoolAllocator* getInternalManifoldPool() = 0;
-
- virtual const btPoolAllocator* getInternalManifoldPool() const = 0;
-
- virtual void* allocateCollisionAlgorithm(int size) = 0;
-
- virtual void freeCollisionAlgorithm(void* ptr) = 0;
-};
-
-#endif //BT_DISPATCHER_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
deleted file mode 100644
index 8ce1087c9f..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btOverlappingPairCache.h"
-
-#include "btDispatcher.h"
-#include "btCollisionAlgorithm.h"
-#include "LinearMath/btAabbUtil2.h"
-
-#include <stdio.h>
-
-btHashedOverlappingPairCache::btHashedOverlappingPairCache() : m_overlapFilterCallback(0),
- m_ghostPairCallback(0)
-{
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
- growTables();
-}
-
-btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
-{
-}
-
-void btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
-{
- if (pair.m_algorithm && dispatcher)
- {
- {
- pair.m_algorithm->~btCollisionAlgorithm();
- dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm = 0;
- }
- }
-}
-
-void btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
-{
- class CleanPairCallback : public btOverlapCallback
- {
- btBroadphaseProxy* m_cleanProxy;
- btOverlappingPairCache* m_pairCache;
- btDispatcher* m_dispatcher;
-
- public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
- : m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- if ((pair.m_pProxy0 == m_cleanProxy) ||
- (pair.m_pProxy1 == m_cleanProxy))
- {
- m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
- }
- return false;
- }
- };
-
- CleanPairCallback cleanPairs(proxy, this, dispatcher);
-
- processAllOverlappingPairs(&cleanPairs, dispatcher);
-}
-
-void btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
-{
- class RemovePairCallback : public btOverlapCallback
- {
- btBroadphaseProxy* m_obsoleteProxy;
-
- public:
- RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
- : m_obsoleteProxy(obsoleteProxy)
- {
- }
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- return ((pair.m_pProxy0 == m_obsoleteProxy) ||
- (pair.m_pProxy1 == m_obsoleteProxy));
- }
- };
-
- RemovePairCallback removeCallback(proxy);
-
- processAllOverlappingPairs(&removeCallback, dispatcher);
-}
-
-btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- if (proxy0->m_uniqueId > proxy1->m_uniqueId)
- btSwap(proxy0, proxy1);
- int proxyId1 = proxy0->getUid();
- int proxyId2 = proxy1->getUid();
-
- /*if (proxyId1 > proxyId2)
- btSwap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
-
- if (hash >= m_hashTable.size())
- {
- return NULL;
- }
-
- int index = m_hashTable[hash];
- while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
- {
- index = m_next[index];
- }
-
- if (index == BT_NULL_PAIR)
- {
- return NULL;
- }
-
- btAssert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
-}
-
-//#include <stdio.h>
-
-void btHashedOverlappingPairCache::growTables()
-{
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
-
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
-
- int i;
-
- for (i = 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = BT_NULL_PAIR;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = BT_NULL_PAIR;
- }
-
- for (i = 0; i < curHashtableSize; i++)
- {
- const btBroadphasePair& pair = m_overlappingPairArray[i];
- int proxyId1 = pair.m_pProxy0->getUid();
- int proxyId2 = pair.m_pProxy1->getUid();
- /*if (proxyId1 > proxyId2)
- btSwap(proxyId1, proxyId2);*/
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
-}
-
-btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- if (proxy0->m_uniqueId > proxy1->m_uniqueId)
- btSwap(proxy0, proxy1);
- int proxyId1 = proxy0->getUid();
- int proxyId2 = proxy1->getUid();
-
- /*if (proxyId1 > proxyId2)
- btSwap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
-
- btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
- if (pair != NULL)
- {
- return pair;
- }
- /*for(int i=0;i<m_overlappingPairArray.size();++i)
- {
- if( (m_overlappingPairArray[i].m_pProxy0==proxy0)&&
- (m_overlappingPairArray[i].m_pProxy1==proxy1))
- {
- printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
- internalFindPair(proxy0, proxy1, hash);
- }
- }*/
- int count = m_overlappingPairArray.size();
- int oldCapacity = m_overlappingPairArray.capacity();
- void* mem = &m_overlappingPairArray.expandNonInitializing();
-
- //this is where we add an actual pair, so also call the 'ghost'
- if (m_ghostPairCallback)
- m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
-
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (oldCapacity < newCapacity)
- {
- growTables();
- //hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
- }
-
- pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
- // pair->m_pProxy0 = proxy0;
- // pair->m_pProxy1 = proxy1;
- pair->m_algorithm = 0;
- pair->m_internalTmpValue = 0;
-
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
-
- return pair;
-}
-
-void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
-{
- if (proxy0->m_uniqueId > proxy1->m_uniqueId)
- btSwap(proxy0, proxy1);
- int proxyId1 = proxy0->getUid();
- int proxyId2 = proxy1->getUid();
-
- /*if (proxyId1 > proxyId2)
- btSwap(proxyId1, proxyId2);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity() - 1));
-
- btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
- if (pair == NULL)
- {
- return 0;
- }
-
- cleanOverlappingPair(*pair, dispatcher);
-
- void* userData = pair->m_internalInfo1;
-
- btAssert(pair->m_pProxy0->getUid() == proxyId1);
- btAssert(pair->m_pProxy1->getUid() == proxyId2);
-
- int pairIndex = int(pair - &m_overlappingPairArray[0]);
- btAssert(pairIndex < m_overlappingPairArray.size());
-
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- btAssert(index != BT_NULL_PAIR);
-
- int previous = BT_NULL_PAIR;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_NULL_PAIR)
- {
- btAssert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
-
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
-
- int lastPairIndex = m_overlappingPairArray.size() - 1;
-
- if (m_ghostPairCallback)
- m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
-
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_overlappingPairArray.pop_back();
- return userData;
- }
-
- // Remove the last pair from the hash table.
- const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity() - 1));
-
- index = m_hashTable[lastHash];
- btAssert(index != BT_NULL_PAIR);
-
- previous = BT_NULL_PAIR;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_NULL_PAIR)
- {
- btAssert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
-
- // Copy the last pair into the remove pair's spot.
- m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
-
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
-
- m_overlappingPairArray.pop_back();
-
- return userData;
-}
-//#include <stdio.h>
-#include "LinearMath/btQuickprof.h"
-void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
-{
- BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
- int i;
-
- // printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
- for (i = 0; i < m_overlappingPairArray.size();)
- {
- btBroadphasePair* pair = &m_overlappingPairArray[i];
- if (callback->processOverlap(*pair))
- {
- removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
- }
- else
- {
- i++;
- }
- }
-}
-
-struct MyPairIndex
-{
- int m_orgIndex;
- int m_uidA0;
- int m_uidA1;
-};
-
-class MyPairIndeSortPredicate
-{
-public:
- bool operator()(const MyPairIndex& a, const MyPairIndex& b) const
- {
- const int uidA0 = a.m_uidA0;
- const int uidB0 = b.m_uidA0;
- const int uidA1 = a.m_uidA1;
- const int uidB1 = b.m_uidA1;
- return uidA0 > uidB0 || (uidA0 == uidB0 && uidA1 > uidB1);
- }
-};
-
-void btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& dispatchInfo)
-{
- if (dispatchInfo.m_deterministicOverlappingPairs)
- {
- btBroadphasePairArray& pa = getOverlappingPairArray();
- btAlignedObjectArray<MyPairIndex> indices;
- {
- BT_PROFILE("sortOverlappingPairs");
- indices.resize(pa.size());
- for (int i = 0; i < indices.size(); i++)
- {
- const btBroadphasePair& p = pa[i];
- const int uidA0 = p.m_pProxy0 ? p.m_pProxy0->m_uniqueId : -1;
- const int uidA1 = p.m_pProxy1 ? p.m_pProxy1->m_uniqueId : -1;
-
- indices[i].m_uidA0 = uidA0;
- indices[i].m_uidA1 = uidA1;
- indices[i].m_orgIndex = i;
- }
- indices.quickSort(MyPairIndeSortPredicate());
- }
- {
- BT_PROFILE("btHashedOverlappingPairCache::processAllOverlappingPairs");
- int i;
- for (i = 0; i < indices.size();)
- {
- btBroadphasePair* pair = &pa[indices[i].m_orgIndex];
- if (callback->processOverlap(*pair))
- {
- removeOverlappingPair(pair->m_pProxy0, pair->m_pProxy1, dispatcher);
- }
- else
- {
- i++;
- }
- }
- }
- }
- else
- {
- processAllOverlappingPairs(callback, dispatcher);
- }
-}
-
-void btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
-{
- ///need to keep hashmap in sync with pair address, so rebuild all
- btBroadphasePairArray tmpPairs;
- int i;
- for (i = 0; i < m_overlappingPairArray.size(); i++)
- {
- tmpPairs.push_back(m_overlappingPairArray[i]);
- }
-
- for (i = 0; i < tmpPairs.size(); i++)
- {
- removeOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1, dispatcher);
- }
-
- for (i = 0; i < m_next.size(); i++)
- {
- m_next[i] = BT_NULL_PAIR;
- }
-
- tmpPairs.quickSort(btBroadphasePairSortPredicate());
-
- for (i = 0; i < tmpPairs.size(); i++)
- {
- addOverlappingPair(tmpPairs[i].m_pProxy0, tmpPairs[i].m_pProxy1);
- }
-}
-
-void* btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
-{
- if (!hasDeferredRemoval())
- {
- btBroadphasePair findPair(*proxy0, *proxy1);
-
- int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
- if (findIndex < m_overlappingPairArray.size())
- {
- btBroadphasePair& pair = m_overlappingPairArray[findIndex];
- void* userData = pair.m_internalInfo1;
- cleanOverlappingPair(pair, dispatcher);
- if (m_ghostPairCallback)
- m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1, dispatcher);
-
- m_overlappingPairArray.swap(findIndex, m_overlappingPairArray.capacity() - 1);
- m_overlappingPairArray.pop_back();
- return userData;
- }
- }
-
- return 0;
-}
-
-btBroadphasePair* btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- //don't add overlap with own
- btAssert(proxy0 != proxy1);
-
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- void* mem = &m_overlappingPairArray.expandNonInitializing();
- btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0, *proxy1);
-
- if (m_ghostPairCallback)
- m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
- return pair;
-}
-
-///this findPair becomes really slow. Either sort the list to speedup the query, or
-///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
-///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
-///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
-btBroadphasePair* btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- btBroadphasePair tmpPair(*proxy0, *proxy1);
- int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
-
- if (findIndex < m_overlappingPairArray.size())
- {
- //btAssert(it != m_overlappingPairSet.end());
- btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
- return pair;
- }
- return 0;
-}
-
-//#include <stdio.h>
-
-void btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher)
-{
- int i;
-
- for (i = 0; i < m_overlappingPairArray.size();)
- {
- btBroadphasePair* pair = &m_overlappingPairArray[i];
- if (callback->processOverlap(*pair))
- {
- cleanOverlappingPair(*pair, dispatcher);
- pair->m_pProxy0 = 0;
- pair->m_pProxy1 = 0;
- m_overlappingPairArray.swap(i, m_overlappingPairArray.size() - 1);
- m_overlappingPairArray.pop_back();
- }
- else
- {
- i++;
- }
- }
-}
-
-btSortedOverlappingPairCache::btSortedOverlappingPairCache() : m_blockedForChanges(false),
- m_hasDeferredRemoval(true),
- m_overlapFilterCallback(0),
- m_ghostPairCallback(0)
-{
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
-}
-
-btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
-{
-}
-
-void btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher)
-{
- if (pair.m_algorithm)
- {
- {
- pair.m_algorithm->~btCollisionAlgorithm();
- dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
- pair.m_algorithm = 0;
- }
- }
-}
-
-void btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
-{
- class CleanPairCallback : public btOverlapCallback
- {
- btBroadphaseProxy* m_cleanProxy;
- btOverlappingPairCache* m_pairCache;
- btDispatcher* m_dispatcher;
-
- public:
- CleanPairCallback(btBroadphaseProxy* cleanProxy, btOverlappingPairCache* pairCache, btDispatcher* dispatcher)
- : m_cleanProxy(cleanProxy),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- if ((pair.m_pProxy0 == m_cleanProxy) ||
- (pair.m_pProxy1 == m_cleanProxy))
- {
- m_pairCache->cleanOverlappingPair(pair, m_dispatcher);
- }
- return false;
- }
- };
-
- CleanPairCallback cleanPairs(proxy, this, dispatcher);
-
- processAllOverlappingPairs(&cleanPairs, dispatcher);
-}
-
-void btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher)
-{
- class RemovePairCallback : public btOverlapCallback
- {
- btBroadphaseProxy* m_obsoleteProxy;
-
- public:
- RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
- : m_obsoleteProxy(obsoleteProxy)
- {
- }
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- return ((pair.m_pProxy0 == m_obsoleteProxy) ||
- (pair.m_pProxy1 == m_obsoleteProxy));
- }
- };
-
- RemovePairCallback removeCallback(proxy);
-
- processAllOverlappingPairs(&removeCallback, dispatcher);
-}
-
-void btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
-{
- //should already be sorted
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
deleted file mode 100644
index 56011899cb..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_OVERLAPPING_PAIR_CACHE_H
-#define BT_OVERLAPPING_PAIR_CACHE_H
-
-#include "btBroadphaseInterface.h"
-#include "btBroadphaseProxy.h"
-#include "btOverlappingPairCallback.h"
-
-#include "LinearMath/btAlignedObjectArray.h"
-class btDispatcher;
-
-typedef btAlignedObjectArray<btBroadphasePair> btBroadphasePairArray;
-
-struct btOverlapCallback
-{
- virtual ~btOverlapCallback()
- {
- }
- //return true for deletion of the pair
- virtual bool processOverlap(btBroadphasePair& pair) = 0;
-};
-
-struct btOverlapFilterCallback
-{
- virtual ~btOverlapFilterCallback()
- {
- }
- // return true when pairs need collision
- virtual bool needBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const = 0;
-};
-
-const int BT_NULL_PAIR = 0xffffffff;
-
-///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
-///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
-class btOverlappingPairCache : public btOverlappingPairCallback
-{
-public:
- virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
-
- virtual btBroadphasePair* getOverlappingPairArrayPtr() = 0;
-
- virtual const btBroadphasePair* getOverlappingPairArrayPtr() const = 0;
-
- virtual btBroadphasePairArray& getOverlappingPairArray() = 0;
-
- virtual void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher) = 0;
-
- virtual int getNumOverlappingPairs() const = 0;
- virtual bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const = 0;
- virtual btOverlapFilterCallback* getOverlapFilterCallback() = 0;
- virtual void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher) = 0;
-
- virtual void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
-
- virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher) = 0;
-
- virtual void processAllOverlappingPairs(btOverlapCallback* callback, btDispatcher* dispatcher, const struct btDispatcherInfo& /*dispatchInfo*/)
- {
- processAllOverlappingPairs(callback, dispatcher);
- }
- virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
-
- virtual bool hasDeferredRemoval() = 0;
-
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback) = 0;
-
- virtual void sortOverlappingPairs(btDispatcher* dispatcher) = 0;
-};
-
-/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
-
-ATTRIBUTE_ALIGNED16(class)
-btHashedOverlappingPairCache : public btOverlappingPairCache
-{
- btBroadphasePairArray m_overlappingPairArray;
- btOverlapFilterCallback* m_overlapFilterCallback;
-
-protected:
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
- btOverlappingPairCallback* m_ghostPairCallback;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btHashedOverlappingPairCache();
- virtual ~btHashedOverlappingPairCache();
-
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
-
- virtual void* removeOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, btDispatcher * dispatcher);
-
- SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
- bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- // Add a pair and return the new pair. If the pair already exists,
- // no new pair is created and the old one is returned.
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1)
- {
- if (!needsBroadphaseCollision(proxy0, proxy1))
- return 0;
-
- return internalAddPair(proxy0, proxy1);
- }
-
- void cleanProxyFromPairs(btBroadphaseProxy * proxy, btDispatcher * dispatcher);
-
- virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher * dispatcher);
-
- virtual void processAllOverlappingPairs(btOverlapCallback * callback, btDispatcher * dispatcher, const struct btDispatcherInfo& dispatchInfo);
-
- virtual btBroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
-
- const btBroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
-
- btBroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- const btBroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
-
- void cleanOverlappingPair(btBroadphasePair & pair, btDispatcher * dispatcher);
-
- btBroadphasePair* findPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
-
- int GetCount() const { return m_overlappingPairArray.size(); }
- // btBroadphasePair* GetPairs() { return m_pairs; }
-
- btOverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
-
- void setOverlapFilterCallback(btOverlapFilterCallback * callback)
- {
- m_overlapFilterCallback = callback;
- }
-
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
-private:
- btBroadphasePair* internalAddPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1);
-
- void growTables();
-
- SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
- {
- return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
- }
-
- /*
- // Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
- // This assumes proxyId1 and proxyId2 are 16-bit.
- SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
- {
- int key = (proxyId2 << 16) | proxyId1;
- key = ~key + (key << 15);
- key = key ^ (key >> 12);
- key = key + (key << 2);
- key = key ^ (key >> 4);
- key = key * 2057;
- key = key ^ (key >> 16);
- return key;
- }
- */
-
- SIMD_FORCE_INLINE unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
- {
- unsigned int key = proxyId1 | (proxyId2 << 16);
- // Thomas Wang's hash
-
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-
- SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy * proxy0, btBroadphaseProxy * proxy1, int hash)
- {
- int proxyId1 = proxy0->getUid();
- int proxyId2 = proxy1->getUid();
-#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
- if (proxyId1 > proxyId2)
- btSwap(proxyId1, proxyId2);
-#endif
-
- int index = m_hashTable[hash];
-
- while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
- {
- index = m_next[index];
- }
-
- if (index == BT_NULL_PAIR)
- {
- return NULL;
- }
-
- btAssert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
- }
-
- virtual bool hasDeferredRemoval()
- {
- return false;
- }
-
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback * ghostPairCallback)
- {
- m_ghostPairCallback = ghostPairCallback;
- }
-
- virtual void sortOverlappingPairs(btDispatcher * dispatcher);
-};
-
-///btSortedOverlappingPairCache maintains the objects with overlapping AABB
-///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
-class btSortedOverlappingPairCache : public btOverlappingPairCache
-{
-protected:
- //avoid brute-force finding all the time
- btBroadphasePairArray m_overlappingPairArray;
-
- //during the dispatch, check that user doesn't destroy/create proxy
- bool m_blockedForChanges;
-
- ///by default, do the removal during the pair traversal
- bool m_hasDeferredRemoval;
-
- //if set, use the callback instead of the built in filter in needBroadphaseCollision
- btOverlapFilterCallback* m_overlapFilterCallback;
-
- btOverlappingPairCallback* m_ghostPairCallback;
-
-public:
- btSortedOverlappingPairCache();
- virtual ~btSortedOverlappingPairCache();
-
- virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* dispatcher);
-
- void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher);
-
- void cleanOverlappingPair(btBroadphasePair& pair, btDispatcher* dispatcher);
-
- btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
-
- btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
-
- void cleanProxyFromPairs(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
-
- void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
-
- inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) const
- {
- if (m_overlapFilterCallback)
- return m_overlapFilterCallback->needBroadphaseCollision(proxy0, proxy1);
-
- bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
- collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
-
- return collides;
- }
-
- btBroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- const btBroadphasePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
-
- btBroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
-
- const btBroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
-
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
- btOverlapFilterCallback* getOverlapFilterCallback()
- {
- return m_overlapFilterCallback;
- }
-
- void setOverlapFilterCallback(btOverlapFilterCallback* callback)
- {
- m_overlapFilterCallback = callback;
- }
-
- virtual bool hasDeferredRemoval()
- {
- return m_hasDeferredRemoval;
- }
-
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
- {
- m_ghostPairCallback = ghostPairCallback;
- }
-
- virtual void sortOverlappingPairs(btDispatcher* dispatcher);
-};
-
-///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
-class btNullPairCache : public btOverlappingPairCache
-{
- btBroadphasePairArray m_overlappingPairArray;
-
-public:
- virtual btBroadphasePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
- const btBroadphasePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
- btBroadphasePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- virtual void cleanOverlappingPair(btBroadphasePair& /*pair*/, btDispatcher* /*dispatcher*/)
- {
- }
-
- virtual int getNumOverlappingPairs() const
- {
- return 0;
- }
-
- virtual void cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/, btDispatcher* /*dispatcher*/)
- {
- }
-
- bool needsBroadphaseCollision(btBroadphaseProxy*, btBroadphaseProxy*) const
- {
- return true;
- }
- btOverlapFilterCallback* getOverlapFilterCallback()
- {
- return 0;
- }
- virtual void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
- {
- }
-
- virtual void processAllOverlappingPairs(btOverlapCallback*, btDispatcher* /*dispatcher*/)
- {
- }
-
- virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
- {
- return 0;
- }
-
- virtual bool hasDeferredRemoval()
- {
- return true;
- }
-
- virtual void setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
- {
- }
-
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
- {
- return 0;
- }
-
- virtual void* removeOverlappingPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/, btDispatcher* /*dispatcher*/)
- {
- return 0;
- }
-
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
- {
- }
-
- virtual void sortOverlappingPairs(btDispatcher* dispatcher)
- {
- (void)dispatcher;
- }
-};
-
-#endif //BT_OVERLAPPING_PAIR_CACHE_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
deleted file mode 100644
index d16c72542f..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
+++ /dev/null
@@ -1,41 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef OVERLAPPING_PAIR_CALLBACK_H
-#define OVERLAPPING_PAIR_CALLBACK_H
-
-class btDispatcher;
-struct btBroadphasePair;
-
-///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
-class btOverlappingPairCallback
-{
-protected:
- btOverlappingPairCallback() {}
-
-public:
- virtual ~btOverlappingPairCallback()
- {
- }
-
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
-
- virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher) = 0;
-
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0, btDispatcher* dispatcher) = 0;
-};
-
-#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
deleted file mode 100644
index 19f1737b73..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btQuantizedBvh.h"
-
-#include "LinearMath/btAabbUtil2.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btSerializer.h"
-
-#define RAYAABB2
-
-btQuantizedBvh::btQuantizedBvh() : m_bulletVersion(BT_BULLET_VERSION),
- m_useQuantization(false),
- //m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
- m_traversalMode(TRAVERSAL_STACKLESS)
- //m_traversalMode(TRAVERSAL_RECURSIVE)
- ,
- m_subtreeHeaderCount(0) //PCK: add this line
-{
- m_bvhAabbMin.setValue(-SIMD_INFINITY, -SIMD_INFINITY, -SIMD_INFINITY);
- m_bvhAabbMax.setValue(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
-}
-
-void btQuantizedBvh::buildInternal()
-{
- ///assumes that caller filled in the m_quantizedLeafNodes
- m_useQuantization = true;
- int numLeafNodes = 0;
-
- if (m_useQuantization)
- {
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2 * numLeafNodes);
- }
-
- m_curNodeIndex = 0;
-
- buildTree(0, numLeafNodes);
-
- ///if the entire tree is small then subtree size, we need to create a header info for the tree
- if (m_useQuantization && !m_SubtreeHeaders.size())
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
- subtree.m_rootNodeIndex = 0;
- subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
- m_quantizedLeafNodes.clear();
- m_leafNodes.clear();
-}
-
-///just for debugging, to visualize the individual patches/subtrees
-#ifdef DEBUG_PATCH_COLORS
-btVector3 color[4] =
- {
- btVector3(1, 0, 0),
- btVector3(0, 1, 0),
- btVector3(0, 0, 1),
- btVector3(0, 1, 1)};
-#endif //DEBUG_PATCH_COLORS
-
-void btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin)
-{
- //enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
- m_bvhAabbMin = bvhAabbMin - clampValue;
- m_bvhAabbMax = bvhAabbMax + clampValue;
- btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
-
- m_useQuantization = true;
-
- {
- unsigned short vecIn[3];
- btVector3 v;
- {
- quantize(vecIn, m_bvhAabbMin, false);
- v = unQuantize(vecIn);
- m_bvhAabbMin.setMin(v - clampValue);
- }
- aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
- {
- quantize(vecIn, m_bvhAabbMax, true);
- v = unQuantize(vecIn);
- m_bvhAabbMax.setMax(v + clampValue);
- }
- aabbSize = m_bvhAabbMax - m_bvhAabbMin;
- m_bvhQuantization = btVector3(btScalar(65533.0), btScalar(65533.0), btScalar(65533.0)) / aabbSize;
- }
-}
-
-btQuantizedBvh::~btQuantizedBvh()
-{
-}
-
-#ifdef DEBUG_TREE_BUILDING
-int gStackDepth = 0;
-int gMaxStackDepth = 0;
-#endif //DEBUG_TREE_BUILDING
-
-void btQuantizedBvh::buildTree(int startIndex, int endIndex)
-{
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth++;
- if (gStackDepth > gMaxStackDepth)
- gMaxStackDepth = gStackDepth;
-#endif //DEBUG_TREE_BUILDING
-
- int splitAxis, splitIndex, i;
- int numIndices = endIndex - startIndex;
- int curIndex = m_curNodeIndex;
-
- btAssert(numIndices > 0);
-
- if (numIndices == 1)
- {
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- assignInternalNodeFromLeafNode(m_curNodeIndex, startIndex);
-
- m_curNodeIndex++;
- return;
- }
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- splitAxis = calcSplittingAxis(startIndex, endIndex);
-
- splitIndex = sortAndCalcSplittingIndex(startIndex, endIndex, splitAxis);
-
- int internalNodeIndex = m_curNodeIndex;
-
- //set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
- //the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
- setInternalNodeAabbMin(m_curNodeIndex, m_bvhAabbMax); //can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
- setInternalNodeAabbMax(m_curNodeIndex, m_bvhAabbMin); //can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
-
- for (i = startIndex; i < endIndex; i++)
- {
- mergeInternalNodeAabb(m_curNodeIndex, getAabbMin(i), getAabbMax(i));
- }
-
- m_curNodeIndex++;
-
- //internalNode->m_escapeIndex;
-
- int leftChildNodexIndex = m_curNodeIndex;
-
- //build left child tree
- buildTree(startIndex, splitIndex);
-
- int rightChildNodexIndex = m_curNodeIndex;
- //build right child tree
- buildTree(splitIndex, endIndex);
-
-#ifdef DEBUG_TREE_BUILDING
- gStackDepth--;
-#endif //DEBUG_TREE_BUILDING
-
- int escapeIndex = m_curNodeIndex - curIndex;
-
- if (m_useQuantization)
- {
- //escapeIndex is the number of nodes of this subtree
- const int sizeQuantizedNode = sizeof(btQuantizedBvhNode);
- const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
- if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
- {
- updateSubtreeHeaders(leftChildNodexIndex, rightChildNodexIndex);
- }
- }
- else
- {
- }
-
- setInternalNodeEscapeIndex(internalNodeIndex, escapeIndex);
-}
-
-void btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex)
-{
- btAssert(m_useQuantization);
-
- btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
- int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
- int leftSubTreeSizeInBytes = leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
-
- btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
- int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
- int rightSubTreeSizeInBytes = rightSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
-
- if (leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(leftChildNode);
- subtree.m_rootNodeIndex = leftChildNodexIndex;
- subtree.m_subtreeSize = leftSubTreeSize;
- }
-
- if (rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(rightChildNode);
- subtree.m_rootNodeIndex = rightChildNodexIndex;
- subtree.m_subtreeSize = rightSubTreeSize;
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-}
-
-int btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis)
-{
- int i;
- int splitIndex = startIndex;
- int numIndices = endIndex - startIndex;
- btScalar splitValue;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- splitValue = means[splitAxis];
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- if (center[splitAxis] > splitValue)
- {
- //swap
- swapLeafNodes(i, splitIndex);
- splitIndex++;
- }
- }
-
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
-
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
-
- //this should be safe too:
- int rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
-
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
-
- bool unbal = (splitIndex == startIndex) || (splitIndex == (endIndex));
- (void)unbal;
- btAssert(!unbal);
-
- return splitIndex;
-}
-
-int btQuantizedBvh::calcSplittingAxis(int startIndex, int endIndex)
-{
- int i;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
- int numIndices = endIndex - startIndex;
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (getAabbMax(i) + getAabbMin(i));
- btVector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
-
- return variance.maxAxis();
-}
-
-void btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- //either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
-
- if (m_useQuantization)
- {
- ///quantize query AABB
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, aabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, aabbMax, 1);
-
- switch (m_traversalMode)
- {
- case TRAVERSAL_STACKLESS:
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax, 0, m_curNodeIndex);
- break;
- case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
- walkStacklessQuantizedTreeCacheFriendly(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- break;
- case TRAVERSAL_RECURSIVE:
- {
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
- walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- break;
- default:
- //unsupported
- btAssert(0);
- }
- }
- else
- {
- walkStacklessTree(nodeCallback, aabbMin, aabbMax);
- }
-}
-
-void btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- btAssert(!m_useQuantization);
-
- const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- while (curIndex < m_curNodeIndex)
- {
- //catch bugs in tree data
- btAssert(walkIterations < m_curNodeIndex);
-
- walkIterations++;
- aabbOverlap = TestAabbAgainstAabb2(aabbMin, aabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- isLeafNode = rootNode->m_escapeIndex == -1;
-
- //PCK: unsigned instead of bool
- if (isLeafNode && (aabbOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
-
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
-}
-
-/*
-///this was the original recursive traversal, before we optimized towards stackless traversal
-void btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
-{
- bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
- if (aabbOverlap)
- {
- isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
- if (isLeafNode)
- {
- nodeCallback->processNode(rootNode);
- } else
- {
- walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
- walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
- }
- }
-
-}
-*/
-
-void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
-{
- btAssert(m_useQuantization);
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- //PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, currentNode->m_quantizedAabbMin, currentNode->m_quantizedAabbMax);
- isLeafNode = currentNode->isLeafNode();
-
- //PCK: unsigned instead of bool
- if (aabbOverlap != 0)
- {
- if (isLeafNode)
- {
- nodeCallback->processNode(currentNode->getPartId(), currentNode->getTriangleIndex());
- }
- else
- {
- //process left and right children
- const btQuantizedBvhNode* leftChildNode = currentNode + 1;
- walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
-
- const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode + 1 : leftChildNode + leftChildNode->getEscapeIndex();
- walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode, nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax);
- }
- }
-}
-
-void btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
-{
- btAssert(!m_useQuantization);
-
- const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
- int escapeIndex, curIndex = 0;
- int walkIterations = 0;
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap = 0;
- unsigned rayBoxOverlap = 0;
- btScalar lambda_max = 1.0;
-
- /* Quick pruning by quantized box */
- btVector3 rayAabbMin = raySource;
- btVector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
-
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
-
-#ifdef RAYAABB2
- btVector3 rayDir = (rayTarget - raySource);
- rayDir.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
- lambda_max = rayDir.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- btVector3 rayDirectionInverse;
- rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- unsigned int sign[3] = {rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
-#endif
-
- btVector3 bounds[2];
-
- while (curIndex < m_curNodeIndex)
- {
- btScalar param = 1.0;
- //catch bugs in tree data
- btAssert(walkIterations < m_curNodeIndex);
-
- walkIterations++;
-
- bounds[0] = rootNode->m_aabbMinOrg;
- bounds[1] = rootNode->m_aabbMaxOrg;
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
-
- aabbOverlap = TestAabbAgainstAabb2(rayAabbMin, rayAabbMax, rootNode->m_aabbMinOrg, rootNode->m_aabbMaxOrg);
- //perhaps profile if it is worth doing the aabbOverlap test first
-
-#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
- rayBoxOverlap = aabbOverlap ? btRayAabb2(raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
-
-#else
- btVector3 normal;
- rayBoxOverlap = btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
-#endif
-
- isLeafNode = rootNode->m_escapeIndex == -1;
-
- //PCK: unsigned instead of bool
- if (isLeafNode && (rayBoxOverlap != 0))
- {
- nodeCallback->processNode(rootNode->m_subPart, rootNode->m_triangleIndex);
- }
-
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->m_escapeIndex;
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
-}
-
-void btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const
-{
- btAssert(m_useQuantization);
-
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
-
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned boxBoxOverlap = 0;
- unsigned rayBoxOverlap = 0;
-
- btScalar lambda_max = 1.0;
-
-#ifdef RAYAABB2
- btVector3 rayDirection = (rayTarget - raySource);
- rayDirection.safeNormalize();// stephengold changed normalize to safeNormalize 2020-02-17
- lambda_max = rayDirection.dot(rayTarget - raySource);
- ///what about division by zero? --> just set rayDirection[i] to 1.0
- rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
- rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
- rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
- unsigned int sign[3] = {rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
-#endif
-
- /* Quick pruning by quantized box */
- btVector3 rayAabbMin = raySource;
- btVector3 rayAabbMax = raySource;
- rayAabbMin.setMin(rayTarget);
- rayAabbMax.setMax(rayTarget);
-
- /* Add box cast extents to bounding box */
- rayAabbMin += aabbMin;
- rayAabbMax += aabbMax;
-
- unsigned short int quantizedQueryAabbMin[3];
- unsigned short int quantizedQueryAabbMax[3];
- quantizeWithClamp(quantizedQueryAabbMin, rayAabbMin, 0);
- quantizeWithClamp(quantizedQueryAabbMax, rayAabbMax, 1);
-
- while (curIndex < endNodeIndex)
- {
-//#define VISUALLY_ANALYZE_BVH 1
-#ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern btIDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- btVector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
-#endif //VISUALLY_ANALYZE_BVH
-
- //catch bugs in tree data
- btAssert(walkIterations < subTreeSize);
-
- walkIterations++;
- //PCK: unsigned instead of bool
- // only interested if this is closer than any previous hit
- btScalar param = 1.0;
- rayBoxOverlap = 0;
- boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
- if (boxBoxOverlap)
- {
- btVector3 bounds[2];
- bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
- bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
- /* Add box cast extents */
- bounds[0] -= aabbMax;
- bounds[1] -= aabbMin;
- btVector3 normal;
-#if 0
- bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
- bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
- if (ra2 != ra)
- {
- printf("functions don't match\n");
- }
-#endif
-#ifdef RAYAABB2
- ///careful with this check: need to check division by zero (above) and fix the unQuantize method
- ///thanks Joerg/hiker for the reproduction case!
- ///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
-
- //BT_PROFILE("btRayAabb2");
- rayBoxOverlap = btRayAabb2(raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
-
-#else
- rayBoxOverlap = true; //btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
-#endif
- }
-
- if (isLeafNode && rayBoxOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
-
- //PCK: unsigned instead of bool
- if ((rayBoxOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
-}
-
-void btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const
-{
- btAssert(m_useQuantization);
-
- int curIndex = startNodeIndex;
- int walkIterations = 0;
- int subTreeSize = endNodeIndex - startNodeIndex;
- (void)subTreeSize;
-
- const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
- int escapeIndex;
-
- bool isLeafNode;
- //PCK: unsigned instead of bool
- unsigned aabbOverlap;
-
- while (curIndex < endNodeIndex)
- {
-//#define VISUALLY_ANALYZE_BVH 1
-#ifdef VISUALLY_ANALYZE_BVH
- //some code snippet to debugDraw aabb, to visually analyze bvh structure
- static int drawPatch = 0;
- //need some global access to a debugDrawer
- extern btIDebugDraw* debugDrawerPtr;
- if (curIndex == drawPatch)
- {
- btVector3 aabbMin, aabbMax;
- aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
- aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
- btVector3 color(1, 0, 0);
- debugDrawerPtr->drawAabb(aabbMin, aabbMax, color);
- }
-#endif //VISUALLY_ANALYZE_BVH
-
- //catch bugs in tree data
- btAssert(walkIterations < subTreeSize);
-
- walkIterations++;
- //PCK: unsigned instead of bool
- aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, rootNode->m_quantizedAabbMin, rootNode->m_quantizedAabbMax);
- isLeafNode = rootNode->isLeafNode();
-
- if (isLeafNode && aabbOverlap)
- {
- nodeCallback->processNode(rootNode->getPartId(), rootNode->getTriangleIndex());
- }
-
- //PCK: unsigned instead of bool
- if ((aabbOverlap != 0) || isLeafNode)
- {
- rootNode++;
- curIndex++;
- }
- else
- {
- escapeIndex = rootNode->getEscapeIndex();
- rootNode += escapeIndex;
- curIndex += escapeIndex;
- }
- }
-}
-
-//This traversal can be called from Playstation 3 SPU
-void btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const
-{
- btAssert(m_useQuantization);
-
- int i;
-
- for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
- {
- const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
-
- //PCK: unsigned instead of bool
- unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- walkStacklessQuantizedTree(nodeCallback, quantizedQueryAabbMin, quantizedQueryAabbMax,
- subtree.m_rootNodeIndex,
- subtree.m_rootNodeIndex + subtree.m_subtreeSize);
- }
- }
-}
-
-void btQuantizedBvh::reportRayOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
-{
- reportBoxCastOverlappingNodex(nodeCallback, raySource, rayTarget, btVector3(0, 0, 0), btVector3(0, 0, 0));
-}
-
-void btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- //always use stackless
-
- if (m_useQuantization)
- {
- walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- else
- {
- walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
- }
- /*
- {
- //recursive traversal
- btVector3 qaabbMin = raySource;
- btVector3 qaabbMax = raySource;
- qaabbMin.setMin(rayTarget);
- qaabbMax.setMax(rayTarget);
- qaabbMin += aabbMin;
- qaabbMax += aabbMax;
- reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
- }
- */
-}
-
-void btQuantizedBvh::swapLeafNodes(int i, int splitIndex)
-{
- if (m_useQuantization)
- {
- btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
- m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
- m_quantizedLeafNodes[splitIndex] = tmp;
- }
- else
- {
- btOptimizedBvhNode tmp = m_leafNodes[i];
- m_leafNodes[i] = m_leafNodes[splitIndex];
- m_leafNodes[splitIndex] = tmp;
- }
-}
-
-void btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex)
-{
- if (m_useQuantization)
- {
- m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
- }
- else
- {
- m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
- }
-}
-
-//PCK: include
-#include <new>
-
-#if 0
-//PCK: consts
-static const unsigned BVH_ALIGNMENT = 16;
-static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
-
-static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
-#endif
-
-unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
-{
- // I changed this to 0 since the extra padding is not needed or used.
- return 0; //BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
-}
-
-unsigned btQuantizedBvh::calculateSerializeBufferSize() const
-{
- unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
- baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
- if (m_useQuantization)
- {
- return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
- }
- return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
-}
-
-bool btQuantizedBvh::serialize(void* o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
-{
- btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- /* if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- ///check alignedment for buffer?
- btAssert(0);
- return false;
- }
-*/
-
- btQuantizedBvh* targetBvh = (btQuantizedBvh*)o_alignedDataBuffer;
-
- // construct the class so the virtual function table, etc will be set up
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (targetBvh) btQuantizedBvh;
-
- if (i_swapEndian)
- {
- targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
-
- btSwapVector3Endian(m_bvhAabbMin, targetBvh->m_bvhAabbMin);
- btSwapVector3Endian(m_bvhAabbMax, targetBvh->m_bvhAabbMax);
- btSwapVector3Endian(m_bvhQuantization, targetBvh->m_bvhQuantization);
-
- targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
- targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
- }
- else
- {
- targetBvh->m_curNodeIndex = m_curNodeIndex;
- targetBvh->m_bvhAabbMin = m_bvhAabbMin;
- targetBvh->m_bvhAabbMax = m_bvhAabbMax;
- targetBvh->m_bvhQuantization = m_bvhQuantization;
- targetBvh->m_traversalMode = m_traversalMode;
- targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
- }
-
- targetBvh->m_useQuantization = m_useQuantization;
-
- unsigned char* nodeData = (unsigned char*)targetBvh;
- nodeData += sizeof(btQuantizedBvh);
-
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- int nodeCount = m_curNodeIndex;
-
- if (m_useQuantization)
- {
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
-
- targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
- }
- }
- nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
- else
- {
- targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- else
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
- targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
-
- targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
- targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
- targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
- }
- }
- nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
- }
-
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- // Now serialize the subtree headers
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
- else
- {
- for (int i = 0; i < m_subtreeHeaderCount; i++)
- {
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
- targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
-
- // need to clear padding in destination buffer
- targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
- targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
- }
- }
- nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
-
- // this clears the pointer in the member variable it doesn't really do anything to the data
- // it does call the destructor on the contained objects, but they are all classes with no destructor defined
- // so the memory (which is not freed) is left alone
- targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
-
- // this wipes the virtual function table pointer at the start of the buffer for the class
- *((void**)o_alignedDataBuffer) = NULL;
-
- return true;
-}
-
-btQuantizedBvh* btQuantizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
-{
- if (i_alignedDataBuffer == NULL) // || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
- {
- return NULL;
- }
- btQuantizedBvh* bvh = (btQuantizedBvh*)i_alignedDataBuffer;
-
- if (i_swapEndian)
- {
- bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
-
- btUnSwapVector3Endian(bvh->m_bvhAabbMin);
- btUnSwapVector3Endian(bvh->m_bvhAabbMax);
- btUnSwapVector3Endian(bvh->m_bvhQuantization);
-
- bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
- bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
- }
-
- unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
- btAssert(calculatedBufSize <= i_dataBufferSize);
-
- if (calculatedBufSize > i_dataBufferSize)
- {
- return NULL;
- }
-
- unsigned char* nodeData = (unsigned char*)bvh;
- nodeData += sizeof(btQuantizedBvh);
-
- unsigned sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- int nodeCount = bvh->m_curNodeIndex;
-
- // Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
- // Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
- new (bvh) btQuantizedBvh(*bvh, false);
-
- if (bvh->m_useQuantization)
- {
- bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
-
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
- bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
-
- bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
- }
- }
- nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
- }
- else
- {
- bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
-
- if (i_swapEndian)
- {
- for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
- {
- btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
- btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
-
- bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
- bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
- bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
- }
- }
- nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
- }
-
- sizeToAdd = 0; //(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
- nodeData += sizeToAdd;
-
- // Now serialize the subtree headers
- bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
- if (i_swapEndian)
- {
- for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
- {
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
-
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
- bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
-
- bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
- bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
- }
- }
-
- return bvh;
-}
-
-// Constructor that prevents btVector3's default constructor from being called
-btQuantizedBvh::btQuantizedBvh(btQuantizedBvh& self, bool /* ownsMemory */) : m_bvhAabbMin(self.m_bvhAabbMin),
- m_bvhAabbMax(self.m_bvhAabbMax),
- m_bvhQuantization(self.m_bvhQuantization),
- m_bulletVersion(BT_BULLET_VERSION)
-{
-}
-
-void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
-{
- m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
-
- m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
- m_useQuantization = quantizedBvhFloatData.m_useQuantization != 0;
-
- {
- int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
-
- if (numElem)
- {
- btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
-
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
-
- {
- int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
-
- if (numElem)
- {
- btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
-
- m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
-
- {
- int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
-}
-
-void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
-{
- m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
- m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
- m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
-
- m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
- m_useQuantization = quantizedBvhDoubleData.m_useQuantization != 0;
-
- {
- int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
- m_contiguousNodes.resize(numElem);
-
- if (numElem)
- {
- btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
-
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
- m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
- m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
- m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
- }
- }
- }
-
- {
- int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
- m_quantizedContiguousNodes.resize(numElem);
-
- if (numElem)
- {
- btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- }
- }
- }
-
- m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
-
- {
- int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
- m_SubtreeHeaders.resize(numElem);
- if (numElem)
- {
- btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
- m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
- m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
- m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
- m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
- m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
- m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
- m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
- }
- }
- }
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
-
- m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
- m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
- m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
-
- quantizedData->m_curNodeIndex = m_curNodeIndex;
- quantizedData->m_useQuantization = m_useQuantization;
-
- quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
- quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*)(m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
- if (quantizedData->m_contiguousNodesPtr)
- {
- int sz = sizeof(btOptimizedBvhNodeData);
- int numElem = m_contiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
- m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
- memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
- memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
- memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
- // Fill padding with zeros to appease msan.
- memset(memPtr->m_pad, 0, sizeof(memPtr->m_pad));
- }
- serializer->finalizeChunk(chunk, "btOptimizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_contiguousNodes[0]);
- }
-
- quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
- // printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
- quantizedData->m_quantizedContiguousNodesPtr = (btQuantizedBvhNodeData*)(m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
- if (quantizedData->m_quantizedContiguousNodesPtr)
- {
- int sz = sizeof(btQuantizedBvhNodeData);
- int numElem = m_quantizedContiguousNodes.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
- memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
- memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
- memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
- memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
- memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
- memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
- }
- serializer->finalizeChunk(chunk, "btQuantizedBvhNodeData", BT_ARRAY_CODE, (void*)&m_quantizedContiguousNodes[0]);
- }
-
- quantizedData->m_traversalMode = int(m_traversalMode);
- quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
-
- quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*)(m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
- if (quantizedData->m_subTreeInfoPtr)
- {
- int sz = sizeof(btBvhSubtreeInfoData);
- int numElem = m_SubtreeHeaders.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
- memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
- memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
- memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
- memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
- memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
-
- memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
- memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
- }
- serializer->finalizeChunk(chunk, "btBvhSubtreeInfoData", BT_ARRAY_CODE, (void*)&m_SubtreeHeaders[0]);
- }
- return btQuantizedBvhDataName;
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
deleted file mode 100644
index 1c47b9ccf2..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_QUANTIZED_BVH_H
-#define BT_QUANTIZED_BVH_H
-
-class btSerializer;
-
-//#define DEBUG_CHECK_DEQUANTIZATION 1
-#ifdef DEBUG_CHECK_DEQUANTIZATION
-#ifdef __SPU__
-#define printf spu_printf
-#endif //__SPU__
-
-#include <stdio.h>
-#include <stdlib.h>
-#endif //DEBUG_CHECK_DEQUANTIZATION
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAlignedAllocator.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btQuantizedBvhData btQuantizedBvhDoubleData
-#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
-#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
-#else
-#define btQuantizedBvhData btQuantizedBvhFloatData
-#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
-#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
-#endif
-
-//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
-
-//Note: currently we have 16 bytes per quantized node
-#define MAX_SUBTREE_SIZE_IN_BYTES 2048
-
-// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
-// actually) triangles each (since the sign bit is reserved
-#define MAX_NUM_PARTS_IN_BITS 10
-
-///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-ATTRIBUTE_ALIGNED16(struct)
-btQuantizedBvhNode
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrTriangleIndex;
-
- bool isLeafNode() const
- {
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrTriangleIndex >= 0);
- }
- int getEscapeIndex() const
- {
- btAssert(!isLeafNode());
- return -m_escapeIndexOrTriangleIndex;
- }
- int getTriangleIndex() const
- {
- btAssert(isLeafNode());
- unsigned int x = 0;
- unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
- // Get only the lower bits where the triangle index is stored
- return (m_escapeIndexOrTriangleIndex & ~(y));
- }
- int getPartId() const
- {
- btAssert(isLeafNode());
- // Get only the highest bits where the part index is stored
- return (m_escapeIndexOrTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
- }
-};
-
-/// btOptimizedBvhNode contains both internal and leaf node information.
-/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
-ATTRIBUTE_ALIGNED16(struct)
-btOptimizedBvhNode
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- //32 bytes
- btVector3 m_aabbMinOrg;
- btVector3 m_aabbMaxOrg;
-
- //4
- int m_escapeIndex;
-
- //8
- //for child nodes
- int m_subPart;
- int m_triangleIndex;
-
- //pad the size to 64 bytes
- char m_padding[20];
-};
-
-///btBvhSubtreeInfo provides info to gather a subtree of limited size
-ATTRIBUTE_ALIGNED16(class)
-btBvhSubtreeInfo
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes, points to the root of the subtree
- int m_rootNodeIndex;
- //4 bytes
- int m_subtreeSize;
- int m_padding[3];
-
- btBvhSubtreeInfo()
- {
- //memset(&m_padding[0], 0, sizeof(m_padding));
- }
-
- void setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
- {
- m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
- m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
- m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
- m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
- m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
- m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
- }
-};
-
-class btNodeOverlapCallback
-{
-public:
- virtual ~btNodeOverlapCallback(){};
-
- virtual void processNode(int subPart, int triangleIndex) = 0;
-};
-
-#include "LinearMath/btAlignedAllocator.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-///for code readability:
-typedef btAlignedObjectArray<btOptimizedBvhNode> NodeArray;
-typedef btAlignedObjectArray<btQuantizedBvhNode> QuantizedNodeArray;
-typedef btAlignedObjectArray<btBvhSubtreeInfo> BvhSubtreeInfoArray;
-
-///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
-///It is used by the btBvhTriangleMeshShape as midphase.
-///It is recommended to use quantization for better performance and lower memory requirements.
-ATTRIBUTE_ALIGNED16(class)
-btQuantizedBvh
-{
-public:
- enum btTraversalMode
- {
- TRAVERSAL_STACKLESS = 0,
- TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
- TRAVERSAL_RECURSIVE
- };
-
-protected:
- btVector3 m_bvhAabbMin;
- btVector3 m_bvhAabbMax;
- btVector3 m_bvhQuantization;
-
- int m_bulletVersion; //for serialization versioning. It could also be used to detect endianess.
-
- int m_curNodeIndex;
- //quantization data
- bool m_useQuantization;
-
- NodeArray m_leafNodes;
- NodeArray m_contiguousNodes;
- QuantizedNodeArray m_quantizedLeafNodes;
- QuantizedNodeArray m_quantizedContiguousNodes;
-
- btTraversalMode m_traversalMode;
- BvhSubtreeInfoArray m_SubtreeHeaders;
-
- //This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
- mutable int m_subtreeHeaderCount;
-
- ///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
- ///this might be refactored into a virtual, it is usually not calculated at run-time
- void setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
- {
- if (m_useQuantization)
- {
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0], aabbMin, 0);
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
- }
- }
- void setInternalNodeAabbMax(int nodeIndex, const btVector3& aabbMax)
- {
- if (m_useQuantization)
- {
- quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0], aabbMax, 1);
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
- }
- }
-
- btVector3 getAabbMin(int nodeIndex) const
- {
- if (m_useQuantization)
- {
- return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
- }
- //non-quantized
- return m_leafNodes[nodeIndex].m_aabbMinOrg;
- }
- btVector3 getAabbMax(int nodeIndex) const
- {
- if (m_useQuantization)
- {
- return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
- }
- //non-quantized
- return m_leafNodes[nodeIndex].m_aabbMaxOrg;
- }
-
- void setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
- {
- if (m_useQuantization)
- {
- m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
- }
- else
- {
- m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
- }
- }
-
- void mergeInternalNodeAabb(int nodeIndex, const btVector3& newAabbMin, const btVector3& newAabbMax)
- {
- if (m_useQuantization)
- {
- unsigned short int quantizedAabbMin[3];
- unsigned short int quantizedAabbMax[3];
- quantize(quantizedAabbMin, newAabbMin, 0);
- quantize(quantizedAabbMax, newAabbMax, 1);
- for (int i = 0; i < 3; i++)
- {
- if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
- m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
-
- if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
- m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
- }
- }
- else
- {
- //non-quantized
- m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
- m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);
- }
- }
-
- void swapLeafNodes(int firstIndex, int secondIndex);
-
- void assignInternalNodeFromLeafNode(int internalNode, int leafNodeIndex);
-
-protected:
- void buildTree(int startIndex, int endIndex);
-
- int calcSplittingAxis(int startIndex, int endIndex);
-
- int sortAndCalcSplittingIndex(int startIndex, int endIndex, int splitAxis);
-
- void walkStacklessTree(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- void walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
- void walkStacklessQuantizedTree(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax, int startNodeIndex, int endNodeIndex) const;
- void walkStacklessTreeAgainstRay(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex, int endNodeIndex) const;
-
- ///tree traversal designed for small-memory processors like PS3 SPU
- void walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback * nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
-
- ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode, btNodeOverlapCallback* nodeCallback, unsigned short int* quantizedQueryAabbMin, unsigned short int* quantizedQueryAabbMax) const;
-
- ///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
- void walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA, const btQuantizedBvhNode* treeNodeB, btNodeOverlapCallback* nodeCallback) const;
-
- void updateSubtreeHeaders(int leftChildNodexIndex, int rightChildNodexIndex);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btQuantizedBvh();
-
- virtual ~btQuantizedBvh();
-
- ///***************************************** expert/internal use only *************************
- void setQuantizationValues(const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, btScalar quantizationMargin = btScalar(1.0));
- QuantizedNodeArray& getLeafNodeArray() { return m_quantizedLeafNodes; }
- ///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
- void buildInternal();
- ///***************************************** expert/internal use only *************************
-
- void reportAabbOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- void reportRayOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
- void reportBoxCastOverlappingNodex(btNodeOverlapCallback * nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point, int isMax) const
- {
- btAssert(m_useQuantization);
-
- btAssert(point.getX() <= m_bvhAabbMax.getX());
- btAssert(point.getY() <= m_bvhAabbMax.getY());
- btAssert(point.getZ() <= m_bvhAabbMax.getZ());
-
- btAssert(point.getX() >= m_bvhAabbMin.getX());
- btAssert(point.getY() >= m_bvhAabbMin.getY());
- btAssert(point.getZ() >= m_bvhAabbMin.getZ());
-
- btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
- ///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
- ///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
- ///@todo: double-check this
- if (isMax)
- {
- out[0] = (unsigned short)(((unsigned short)(v.getX() + btScalar(1.)) | 1));
- out[1] = (unsigned short)(((unsigned short)(v.getY() + btScalar(1.)) | 1));
- out[2] = (unsigned short)(((unsigned short)(v.getZ() + btScalar(1.)) | 1));
- }
- else
- {
- out[0] = (unsigned short)(((unsigned short)(v.getX()) & 0xfffe));
- out[1] = (unsigned short)(((unsigned short)(v.getY()) & 0xfffe));
- out[2] = (unsigned short)(((unsigned short)(v.getZ()) & 0xfffe));
- }
-
-#ifdef DEBUG_CHECK_DEQUANTIZATION
- btVector3 newPoint = unQuantize(out);
- if (isMax)
- {
- if (newPoint.getX() < point.getX())
- {
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
- }
- if (newPoint.getY() < point.getY())
- {
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
- }
- if (newPoint.getZ() < point.getZ())
- {
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
- }
- }
- else
- {
- if (newPoint.getX() > point.getX())
- {
- printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n", newPoint.getX() - point.getX(), newPoint.getX(), point.getX());
- }
- if (newPoint.getY() > point.getY())
- {
- printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n", newPoint.getY() - point.getY(), newPoint.getY(), point.getY());
- }
- if (newPoint.getZ() > point.getZ())
- {
- printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n", newPoint.getZ() - point.getZ(), newPoint.getZ(), point.getZ());
- }
- }
-#endif //DEBUG_CHECK_DEQUANTIZATION
- }
-
- SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2, int isMax) const
- {
- btAssert(m_useQuantization);
-
- btVector3 clampedPoint(point2);
- clampedPoint.setMax(m_bvhAabbMin);
- clampedPoint.setMin(m_bvhAabbMax);
-
- quantize(out, clampedPoint, isMax);
- }
-
- SIMD_FORCE_INLINE btVector3 unQuantize(const unsigned short* vecIn) const
- {
- btVector3 vecOut;
- vecOut.setValue(
- (btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
- (btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
- (btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
- vecOut += m_bvhAabbMin;
- return vecOut;
- }
-
- ///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
- void setTraversalMode(btTraversalMode traversalMode)
- {
- m_traversalMode = traversalMode;
- }
-
- SIMD_FORCE_INLINE QuantizedNodeArray& getQuantizedNodeArray()
- {
- return m_quantizedContiguousNodes;
- }
-
- SIMD_FORCE_INLINE BvhSubtreeInfoArray& getSubtreeInfoArray()
- {
- return m_SubtreeHeaders;
- }
-
- ////////////////////////////////////////////////////////////////////
-
- /////Calculate space needed to store BVH for serialization
- unsigned calculateSerializeBufferSize() const;
-
- /// Data buffer MUST be 16 byte aligned
- virtual bool serialize(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
-
- ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static btQuantizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-
- static unsigned int getAlignmentSerializationPadding();
- //////////////////////////////////////////////////////////////////////
-
- virtual int calculateSerializeBufferSizeNew() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void deSerializeFloat(struct btQuantizedBvhFloatData & quantizedBvhFloatData);
-
- virtual void deSerializeDouble(struct btQuantizedBvhDoubleData & quantizedBvhDoubleData);
-
- ////////////////////////////////////////////////////////////////////
-
- SIMD_FORCE_INLINE bool isQuantized()
- {
- return m_useQuantization;
- }
-
-private:
- // Special "copy" constructor that allows for in-place deserialization
- // Prevents btVector3's default constructor from being called, but doesn't inialize much else
- // ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
- btQuantizedBvh(btQuantizedBvh & other, bool ownsMemory);
-};
-
-// clang-format off
-// parser needs * with the name
-struct btBvhSubtreeInfoData
-{
- int m_rootNodeIndex;
- int m_subtreeSize;
- unsigned short m_quantizedAabbMin[3];
- unsigned short m_quantizedAabbMax[3];
-};
-
-struct btOptimizedBvhNodeFloatData
-{
- btVector3FloatData m_aabbMinOrg;
- btVector3FloatData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-struct btOptimizedBvhNodeDoubleData
-{
- btVector3DoubleData m_aabbMinOrg;
- btVector3DoubleData m_aabbMaxOrg;
- int m_escapeIndex;
- int m_subPart;
- int m_triangleIndex;
- char m_pad[4];
-};
-
-
-struct btQuantizedBvhNodeData
-{
- unsigned short m_quantizedAabbMin[3];
- unsigned short m_quantizedAabbMax[3];
- int m_escapeIndexOrTriangleIndex;
-};
-
-struct btQuantizedBvhFloatData
-{
- btVector3FloatData m_bvhAabbMin;
- btVector3FloatData m_bvhAabbMax;
- btVector3FloatData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- btOptimizedBvhNodeFloatData *m_contiguousNodesPtr;
- btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
- btBvhSubtreeInfoData *m_subTreeInfoPtr;
- int m_traversalMode;
- int m_numSubtreeHeaders;
-
-};
-
-struct btQuantizedBvhDoubleData
-{
- btVector3DoubleData m_bvhAabbMin;
- btVector3DoubleData m_bvhAabbMax;
- btVector3DoubleData m_bvhQuantization;
- int m_curNodeIndex;
- int m_useQuantization;
- int m_numContiguousLeafNodes;
- int m_numQuantizedContiguousNodes;
- btOptimizedBvhNodeDoubleData *m_contiguousNodesPtr;
- btQuantizedBvhNodeData *m_quantizedContiguousNodesPtr;
-
- int m_traversalMode;
- int m_numSubtreeHeaders;
- btBvhSubtreeInfoData *m_subTreeInfoPtr;
-};
-// clang-format on
-
-SIMD_FORCE_INLINE int btQuantizedBvh::calculateSerializeBufferSizeNew() const
-{
- return sizeof(btQuantizedBvhData);
-}
-
-#endif //BT_QUANTIZED_BVH_H
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
deleted file mode 100644
index b7fe0a1f34..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSimpleBroadphase.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "LinearMath/btAabbUtil2.h"
-
-#include <new>
-
-void btSimpleBroadphase::validate()
-{
- for (int i = 0; i < m_numHandles; i++)
- {
- for (int j = i + 1; j < m_numHandles; j++)
- {
- btAssert(&m_pHandles[i] != &m_pHandles[j]);
- }
- }
-}
-
-btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
- : m_pairCache(overlappingPairCache),
- m_ownsPairCache(false),
- m_invalidPair(0)
-{
- if (!overlappingPairCache)
- {
- void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16);
- m_pairCache = new (mem) btHashedOverlappingPairCache();
- m_ownsPairCache = true;
- }
-
- // allocate handles buffer and put all handles on free list
- m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy) * maxProxies, 16);
- m_pHandles = new (m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
- m_maxHandles = maxProxies;
- m_numHandles = 0;
- m_firstFreeHandle = 0;
- m_LastHandleIndex = -1;
-
- {
- for (int i = m_firstFreeHandle; i < maxProxies; i++)
- {
- m_pHandles[i].SetNextFree(i + 1);
- m_pHandles[i].m_uniqueId = i + 2; //any UID will do, we just avoid too trivial values (0,1) for debugging purposes
- }
- m_pHandles[maxProxies - 1].SetNextFree(0);
- }
-}
-
-btSimpleBroadphase::~btSimpleBroadphase()
-{
- btAlignedFree(m_pHandlesRawPtr);
-
- if (m_ownsPairCache)
- {
- m_pairCache->~btOverlappingPairCache();
- btAlignedFree(m_pairCache);
- }
-}
-
-btBroadphaseProxy* btSimpleBroadphase::createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* /*dispatcher*/)
-{
- if (m_numHandles >= m_maxHandles)
- {
- btAssert(0);
- return 0; //should never happen, but don't let the game crash ;-)
- }
- btAssert(aabbMin[0] <= aabbMax[0] && aabbMin[1] <= aabbMax[1] && aabbMin[2] <= aabbMax[2]);
-
- int newHandleIndex = allocHandle();
- btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex]) btSimpleBroadphaseProxy(aabbMin, aabbMax, shapeType, userPtr, collisionFilterGroup, collisionFilterMask);
-
- return proxy;
-}
-
-class RemovingOverlapCallback : public btOverlapCallback
-{
-protected:
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- (void)pair;
- btAssert(0);
- return false;
- }
-};
-
-class RemovePairContainingProxy
-{
- btBroadphaseProxy* m_targetProxy;
-
-public:
- virtual ~RemovePairContainingProxy()
- {
- }
-
-protected:
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
- btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
-
- return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
- };
-};
-
-void btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg, btDispatcher* dispatcher)
-{
- m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg, dispatcher);
-
- btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
- freeHandle(proxy0);
-
- //validate();
-}
-
-void btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const
-{
- const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
- aabbMin = sbp->m_aabbMin;
- aabbMax = sbp->m_aabbMax;
-}
-
-void btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
-{
- btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
- sbp->m_aabbMin = aabbMin;
- sbp->m_aabbMax = aabbMax;
-}
-
-void btSimpleBroadphase::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- for (int i = 0; i <= m_LastHandleIndex; i++)
- {
- btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
- if (!proxy->m_clientObject)
- {
- continue;
- }
- rayCallback.process(proxy);
- }
-}
-
-void btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
-{
- for (int i = 0; i <= m_LastHandleIndex; i++)
- {
- btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
- if (!proxy->m_clientObject)
- {
- continue;
- }
- if (TestAabbAgainstAabb2(aabbMin, aabbMax, proxy->m_aabbMin, proxy->m_aabbMax))
- {
- callback.process(proxy);
- }
- }
-}
-
-bool btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1)
-{
- return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] &&
- proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
- proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
-}
-
-//then remove non-overlapping ones
-class CheckOverlapCallback : public btOverlapCallback
-{
-public:
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0), static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
- }
-};
-
-void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
-{
- //first check for new overlapping pairs
- int i, j;
- if (m_numHandles >= 0)
- {
- int new_largest_index = -1;
- for (i = 0; i <= m_LastHandleIndex; i++)
- {
- btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
- if (!proxy0->m_clientObject)
- {
- continue;
- }
- new_largest_index = i;
- for (j = i + 1; j <= m_LastHandleIndex; j++)
- {
- btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
- btAssert(proxy0 != proxy1);
- if (!proxy1->m_clientObject)
- {
- continue;
- }
-
- btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
- btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
-
- if (aabbOverlap(p0, p1))
- {
- if (!m_pairCache->findPair(proxy0, proxy1))
- {
- m_pairCache->addOverlappingPair(proxy0, proxy1);
- }
- }
- else
- {
- if (!m_pairCache->hasDeferredRemoval())
- {
- if (m_pairCache->findPair(proxy0, proxy1))
- {
- m_pairCache->removeOverlappingPair(proxy0, proxy1, dispatcher);
- }
- }
- }
- }
- }
-
- m_LastHandleIndex = new_largest_index;
-
- if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
- {
- btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray();
-
- //perform a sort, to find duplicates and to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
-
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-
- btBroadphasePair previousPair;
- previousPair.m_pProxy0 = 0;
- previousPair.m_pProxy1 = 0;
- previousPair.m_algorithm = 0;
-
- for (i = 0; i < overlappingPairArray.size(); i++)
- {
- btBroadphasePair& pair = overlappingPairArray[i];
-
- bool isDuplicate = (pair == previousPair);
-
- previousPair = pair;
-
- bool needsRemoval = false;
-
- if (!isDuplicate)
- {
- bool hasOverlap = testAabbOverlap(pair.m_pProxy0, pair.m_pProxy1);
-
- if (hasOverlap)
- {
- needsRemoval = false; //callback->processOverlap(pair);
- }
- else
- {
- needsRemoval = true;
- }
- }
- else
- {
- //remove duplicate
- needsRemoval = true;
- //should have no algorithm
- btAssert(!pair.m_algorithm);
- }
-
- if (needsRemoval)
- {
- m_pairCache->cleanOverlappingPair(pair, dispatcher);
-
- // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
- // m_overlappingPairArray.pop_back();
- pair.m_pProxy0 = 0;
- pair.m_pProxy1 = 0;
- m_invalidPair++;
- }
- }
-
- ///if you don't like to skip the invalid pairs in the array, execute following code:
-#define CLEAN_INVALID_PAIRS 1
-#ifdef CLEAN_INVALID_PAIRS
-
- //perform a sort, to sort 'invalid' pairs to the end
- overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
-
- overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
- m_invalidPair = 0;
-#endif //CLEAN_INVALID_PAIRS
- }
- }
-}
-
-bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
-{
- btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
- btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
- return aabbOverlap(p0, p1);
-}
-
-void btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
-{
- //not yet
-}
diff --git a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
deleted file mode 100644
index 3e02fdc003..0000000000
--- a/thirdparty/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMPLE_BROADPHASE_H
-#define BT_SIMPLE_BROADPHASE_H
-
-#include "btOverlappingPairCache.h"
-
-struct btSimpleBroadphaseProxy : public btBroadphaseProxy
-{
- int m_nextFree;
-
- // int m_handleId;
-
- btSimpleBroadphaseProxy(){};
-
- btSimpleBroadphaseProxy(const btVector3& minpt, const btVector3& maxpt, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask)
- : btBroadphaseProxy(minpt, maxpt, userPtr, collisionFilterGroup, collisionFilterMask)
- {
- (void)shapeType;
- }
-
- SIMD_FORCE_INLINE void SetNextFree(int next) { m_nextFree = next; }
- SIMD_FORCE_INLINE int GetNextFree() const { return m_nextFree; }
-};
-
-///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
-///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
-class btSimpleBroadphase : public btBroadphaseInterface
-{
-protected:
- int m_numHandles; // number of active handles
- int m_maxHandles; // max number of handles
- int m_LastHandleIndex;
-
- btSimpleBroadphaseProxy* m_pHandles; // handles pool
-
- void* m_pHandlesRawPtr;
- int m_firstFreeHandle; // free handles list
-
- int allocHandle()
- {
- btAssert(m_numHandles < m_maxHandles);
- int freeHandle = m_firstFreeHandle;
- m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
- m_numHandles++;
- if (freeHandle > m_LastHandleIndex)
- {
- m_LastHandleIndex = freeHandle;
- }
- return freeHandle;
- }
-
- void freeHandle(btSimpleBroadphaseProxy* proxy)
- {
- int handle = int(proxy - m_pHandles);
- btAssert(handle >= 0 && handle < m_maxHandles);
- if (handle == m_LastHandleIndex)
- {
- m_LastHandleIndex--;
- }
- proxy->SetNextFree(m_firstFreeHandle);
- m_firstFreeHandle = handle;
-
- proxy->m_clientObject = 0;
-
- m_numHandles--;
- }
-
- btOverlappingPairCache* m_pairCache;
- bool m_ownsPairCache;
-
- int m_invalidPair;
-
- inline btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
- {
- btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
- return proxy0;
- }
-
- inline const btSimpleBroadphaseProxy* getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
- {
- const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
- return proxy0;
- }
-
- ///reset broadphase internal structures, to ensure determinism/reproducability
- virtual void resetPool(btDispatcher* dispatcher);
-
- void validate();
-
-protected:
-public:
- btSimpleBroadphase(int maxProxies = 16384, btOverlappingPairCache* overlappingPairCache = 0);
- virtual ~btSimpleBroadphase();
-
- static bool aabbOverlap(btSimpleBroadphaseProxy* proxy0, btSimpleBroadphaseProxy* proxy1);
-
- virtual btBroadphaseProxy* createProxy(const btVector3& aabbMin, const btVector3& aabbMax, int shapeType, void* userPtr, int collisionFilterGroup, int collisionFilterMask, btDispatcher* dispatcher);
-
- virtual void calculateOverlappingPairs(btDispatcher* dispatcher);
-
- virtual void destroyProxy(btBroadphaseProxy* proxy, btDispatcher* dispatcher);
- virtual void setAabb(btBroadphaseProxy* proxy, const btVector3& aabbMin, const btVector3& aabbMax, btDispatcher* dispatcher);
- virtual void getAabb(btBroadphaseProxy* proxy, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin = btVector3(0, 0, 0), const btVector3& aabbMax = btVector3(0, 0, 0));
- virtual void aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
-
- btOverlappingPairCache* getOverlappingPairCache()
- {
- return m_pairCache;
- }
- const btOverlappingPairCache* getOverlappingPairCache() const
- {
- return m_pairCache;
- }
-
- bool testAabbOverlap(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
-
- ///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
- ///will add some transform later
- virtual void getBroadphaseAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- aabbMin.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
- aabbMax.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- }
-
- virtual void printStats()
- {
- // printf("btSimpleBroadphase.h\n");
- // printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
- }
-};
-
-#endif //BT_SIMPLE_BROADPHASE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
deleted file mode 100644
index 7647f67360..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btScalar.h"
-#include "SphereTriangleDetector.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold)
- : m_sphere(sphere),
- m_triangle(triangle),
- m_contactBreakingThreshold(contactBreakingThreshold)
-{
-}
-
-void SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults)
-{
- (void)debugDraw;
- const btTransform& transformA = input.m_transformA;
- const btTransform& transformB = input.m_transformB;
-
- btVector3 point, normal;
- btScalar timeOfImpact = btScalar(1.);
- btScalar depth = btScalar(0.);
- // output.m_distance = btScalar(BT_LARGE_FLOAT);
- //move sphere into triangle space
- btTransform sphereInTr = transformB.inverseTimes(transformA);
-
- if (collide(sphereInTr.getOrigin(), point, normal, depth, timeOfImpact, m_contactBreakingThreshold))
- {
- if (swapResults)
- {
- btVector3 normalOnB = transformB.getBasis() * normal;
- btVector3 normalOnA = -normalOnB;
- btVector3 pointOnA = transformB * point + normalOnB * depth;
- output.addContactPoint(normalOnA, pointOnA, depth);
- }
- else
- {
- output.addContactPoint(transformB.getBasis() * normal, transformB * point, depth);
- }
- }
-}
-
-// See also geometrictools.com
-// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
-btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest);
-
-btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to, const btVector3& p, btVector3& nearest)
-{
- btVector3 diff = p - from;
- btVector3 v = to - from;
- btScalar t = v.dot(diff);
-
- if (t > 0)
- {
- btScalar dotVV = v.dot(v);
- if (t < dotVV)
- {
- t /= dotVV;
- diff -= t * v;
- }
- else
- {
- t = 1;
- diff -= v;
- }
- }
- else
- t = 0;
-
- nearest = from + t * v;
- return diff.dot(diff);
-}
-
-bool SphereTriangleDetector::facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal)
-{
- btVector3 lp(p);
- btVector3 lnormal(normal);
-
- return pointInTriangle(vertices, lnormal, &lp);
-}
-
-bool SphereTriangleDetector::collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold)
-{
- const btVector3* vertices = &m_triangle->getVertexPtr(0);
-
- btScalar radius = m_sphere->getRadius();
- btScalar radiusWithThreshold = radius + contactBreakingThreshold;
-
- btVector3 normal = (vertices[1] - vertices[0]).cross(vertices[2] - vertices[0]);
-
- btScalar l2 = normal.length2();
- bool hasContact = false;
- btVector3 contactPoint;
-
- if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
- {
- normal /= btSqrt(l2);
-
- btVector3 p1ToCentre = sphereCenter - vertices[0];
- btScalar distanceFromPlane = p1ToCentre.dot(normal);
-
- if (distanceFromPlane < btScalar(0.))
- {
- //triangle facing the other way
- distanceFromPlane *= btScalar(-1.);
- normal *= btScalar(-1.);
- }
-
- bool isInsideContactPlane = distanceFromPlane < radiusWithThreshold;
-
- // Check for contact / intersection
-
- if (isInsideContactPlane)
- {
- if (facecontains(sphereCenter, vertices, normal))
- {
- // Inside the contact wedge - touches a point on the shell plane
- hasContact = true;
- contactPoint = sphereCenter - normal * distanceFromPlane;
- }
- else
- {
- // Could be inside one of the contact capsules
- btScalar contactCapsuleRadiusSqr = radiusWithThreshold * radiusWithThreshold;
- btScalar minDistSqr = contactCapsuleRadiusSqr;
- btVector3 nearestOnEdge;
- for (int i = 0; i < m_triangle->getNumEdges(); i++)
- {
- btVector3 pa;
- btVector3 pb;
-
- m_triangle->getEdge(i, pa, pb);
-
- btScalar distanceSqr = SegmentSqrDistance(pa, pb, sphereCenter, nearestOnEdge);
- if (distanceSqr < minDistSqr)
- {
- // Yep, we're inside a capsule, and record the capsule with smallest distance
- minDistSqr = distanceSqr;
- hasContact = true;
- contactPoint = nearestOnEdge;
- }
- }
- }
- }
- }
-
- if (hasContact)
- {
- btVector3 contactToCentre = sphereCenter - contactPoint;
- btScalar distanceSqr = contactToCentre.length2();
-
- if (distanceSqr < radiusWithThreshold * radiusWithThreshold)
- {
- if (distanceSqr > SIMD_EPSILON)
- {
- btScalar distance = btSqrt(distanceSqr);
- resultNormal = contactToCentre;
- resultNormal.normalize();
- point = contactPoint;
- depth = -(radius - distance);
- }
- else
- {
- resultNormal = normal;
- point = contactPoint;
- depth = -radius;
- }
- return true;
- }
- }
-
- return false;
-}
-
-bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p)
-{
- const btVector3* p1 = &vertices[0];
- const btVector3* p2 = &vertices[1];
- const btVector3* p3 = &vertices[2];
-
- btVector3 edge1(*p2 - *p1);
- btVector3 edge2(*p3 - *p2);
- btVector3 edge3(*p1 - *p3);
-
- btVector3 p1_to_p(*p - *p1);
- btVector3 p2_to_p(*p - *p2);
- btVector3 p3_to_p(*p - *p3);
-
- btVector3 edge1_normal(edge1.cross(normal));
- btVector3 edge2_normal(edge2.cross(normal));
- btVector3 edge3_normal(edge3.cross(normal));
-
- btScalar r1, r2, r3;
- r1 = edge1_normal.dot(p1_to_p);
- r2 = edge2_normal.dot(p2_to_p);
- r3 = edge3_normal.dot(p3_to_p);
- if ((r1 > 0 && r2 > 0 && r3 > 0) ||
- (r1 <= 0 && r2 <= 0 && r3 <= 0))
- return true;
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
deleted file mode 100644
index d47e47530d..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SPHERE_TRIANGLE_DETECTOR_H
-#define BT_SPHERE_TRIANGLE_DETECTOR_H
-
-#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-
-class btSphereShape;
-class btTriangleShape;
-
-/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
-struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
-{
- virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
-
- SphereTriangleDetector(btSphereShape* sphere, btTriangleShape* triangle, btScalar contactBreakingThreshold);
-
- virtual ~SphereTriangleDetector(){};
-
- bool collide(const btVector3& sphereCenter, btVector3& point, btVector3& resultNormal, btScalar& depth, btScalar& timeOfImpact, btScalar contactBreakingThreshold);
-
-private:
- bool pointInTriangle(const btVector3 vertices[], const btVector3& normal, btVector3* p);
- bool facecontains(const btVector3& p, const btVector3* vertices, btVector3& normal);
-
- btSphereShape* m_sphere;
- btTriangleShape* m_triangle;
- btScalar m_contactBreakingThreshold;
-};
-#endif //BT_SPHERE_TRIANGLE_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
deleted file mode 100644
index ac5de45d27..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "btCollisionDispatcher.h"
-#include "btCollisionObject.h"
-
-btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btCollisionAlgorithm(ci)
-//,
-//m_colObj0(0),
-//m_colObj1(0)
-{
-}
-btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*)
- : btCollisionAlgorithm(ci)
-//,
-//m_colObj0(0),
-//m_colObj1(0)
-{
- // if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
- // {
- // m_colObj0 = colObj0;
- // m_colObj1 = colObj1;
- //
- // m_colObj0->activate();
- // m_colObj1->activate();
- // }
-}
-
-btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
-{
- // m_colObj0->activate();
- // m_colObj1->activate();
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
deleted file mode 100644
index 862060571b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H
-#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
-///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
-class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
-{
- // btCollisionObject* m_colObj0;
- // btCollisionObject* m_colObj1;
-
-protected:
- btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
-
- btActivatingCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
-public:
- virtual ~btActivatingCollisionAlgorithm();
-};
-#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
deleted file mode 100644
index 6873a95d90..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library.
-///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross
-
-#include "btBox2dBox2dCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
-#include "BulletCollision/CollisionShapes/btBox2dShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-#define USE_PERSISTENT_CONTACTS 1
-
-btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap)
- : btActivatingCollisionAlgorithm(ci, obj0Wrap, obj1Wrap),
- m_ownManifold(false),
- m_manifoldPtr(mf)
-{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject()))
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(obj0Wrap->getCollisionObject(), obj1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void b2CollidePolygons(btManifoldResult* manifold, const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
-
-//#include <stdio.h>
-void btBox2dBox2dCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- if (!m_manifoldPtr)
- return;
-
- const btBox2dShape* box0 = (const btBox2dShape*)body0Wrap->getCollisionShape();
- const btBox2dShape* box1 = (const btBox2dShape*)body1Wrap->getCollisionShape();
-
- resultOut->setPersistentManifold(m_manifoldPtr);
-
- b2CollidePolygons(resultOut, box0, body0Wrap->getWorldTransform(), box1, body1Wrap->getWorldTransform());
-
- // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
-}
-
-btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
-{
- //not yet
- return 1.f;
-}
-
-struct ClipVertex
-{
- btVector3 v;
- int id;
- //b2ContactID id;
- //b2ContactID id;
-};
-
-#define b2Dot(a, b) (a).dot(b)
-#define b2Mul(a, b) (a) * (b)
-#define b2MulT(a, b) (a).transpose() * (b)
-#define b2Cross(a, b) (a).cross(b)
-#define btCrossS(a, s) btVector3(s* a.getY(), -s* a.getX(), 0.f)
-
-int b2_maxManifoldPoints = 2;
-
-static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
- const btVector3& normal, btScalar offset)
-{
- // Start with no output points
- int numOut = 0;
-
- // Calculate the distance of end points to the line
- btScalar distance0 = b2Dot(normal, vIn[0].v) - offset;
- btScalar distance1 = b2Dot(normal, vIn[1].v) - offset;
-
- // If the points are behind the plane
- if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
- if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
-
- // If the points are on different sides of the plane
- if (distance0 * distance1 < 0.0f)
- {
- // Find intersection point of edge and plane
- btScalar interp = distance0 / (distance0 - distance1);
- vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
- if (distance0 > 0.0f)
- {
- vOut[numOut].id = vIn[0].id;
- }
- else
- {
- vOut[numOut].id = vIn[1].id;
- }
- ++numOut;
- }
-
- return numOut;
-}
-
-// Find the separation between poly1 and poly2 for a give edge normal on poly1.
-static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
- const btBox2dShape* poly2, const btTransform& xf2)
-{
- const btVector3* vertices1 = poly1->getVertices();
- const btVector3* normals1 = poly1->getNormals();
-
- int count2 = poly2->getVertexCount();
- const btVector3* vertices2 = poly2->getVertices();
-
- btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
-
- // Convert normal from poly1's frame into poly2's frame.
- btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]);
- btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World);
-
- // Find support vertex on poly2 for -normal.
- int index = 0;
- btScalar minDot = BT_LARGE_FLOAT;
-
- if (count2 > 0)
- index = (int)normal1.minDot(vertices2, count2, minDot);
-
- btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
- btVector3 v2 = b2Mul(xf2, vertices2[index]);
- btScalar separation = b2Dot(v2 - v1, normal1World);
- return separation;
-}
-
-// Find the max separation between poly1 and poly2 using edge normals from poly1.
-static btScalar FindMaxSeparation(int* edgeIndex,
- const btBox2dShape* poly1, const btTransform& xf1,
- const btBox2dShape* poly2, const btTransform& xf2)
-{
- int count1 = poly1->getVertexCount();
- const btVector3* normals1 = poly1->getNormals();
-
- // Vector pointing from the centroid of poly1 to the centroid of poly2.
- btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid());
- btVector3 dLocal1 = b2MulT(xf1.getBasis(), d);
-
- // Find edge normal on poly1 that has the largest projection onto d.
- int edge = 0;
- btScalar maxDot;
- if (count1 > 0)
- edge = (int)dLocal1.maxDot(normals1, count1, maxDot);
-
- // Get the separation for the edge normal.
- btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
- if (s > 0.0f)
- {
- return s;
- }
-
- // Check the separation for the previous edge normal.
- int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
- btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
- if (sPrev > 0.0f)
- {
- return sPrev;
- }
-
- // Check the separation for the next edge normal.
- int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
- btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
- if (sNext > 0.0f)
- {
- return sNext;
- }
-
- // Find the best edge and the search direction.
- int bestEdge;
- btScalar bestSeparation;
- int increment;
- if (sPrev > s && sPrev > sNext)
- {
- increment = -1;
- bestEdge = prevEdge;
- bestSeparation = sPrev;
- }
- else if (sNext > s)
- {
- increment = 1;
- bestEdge = nextEdge;
- bestSeparation = sNext;
- }
- else
- {
- *edgeIndex = edge;
- return s;
- }
-
- // Perform a local search for the best edge normal.
- for (;;)
- {
- if (increment == -1)
- edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
- else
- edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
-
- s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
- if (s > 0.0f)
- {
- return s;
- }
-
- if (s > bestSeparation)
- {
- bestEdge = edge;
- bestSeparation = s;
- }
- else
- {
- break;
- }
- }
-
- *edgeIndex = bestEdge;
- return bestSeparation;
-}
-
-static void FindIncidentEdge(ClipVertex c[2],
- const btBox2dShape* poly1, const btTransform& xf1, int edge1,
- const btBox2dShape* poly2, const btTransform& xf2)
-{
- const btVector3* normals1 = poly1->getNormals();
-
- int count2 = poly2->getVertexCount();
- const btVector3* vertices2 = poly2->getVertices();
- const btVector3* normals2 = poly2->getNormals();
-
- btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
-
- // Get the normal of the reference edge in poly2's frame.
- btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1]));
-
- // Find the incident edge on poly2.
- int index = 0;
- btScalar minDot = BT_LARGE_FLOAT;
- for (int i = 0; i < count2; ++i)
- {
- btScalar dot = b2Dot(normal1, normals2[i]);
- if (dot < minDot)
- {
- minDot = dot;
- index = i;
- }
- }
-
- // Build the clip vertices for the incident edge.
- int i1 = index;
- int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
-
- c[0].v = b2Mul(xf2, vertices2[i1]);
- // c[0].id.features.referenceEdge = (unsigned char)edge1;
- // c[0].id.features.incidentEdge = (unsigned char)i1;
- // c[0].id.features.incidentVertex = 0;
-
- c[1].v = b2Mul(xf2, vertices2[i2]);
- // c[1].id.features.referenceEdge = (unsigned char)edge1;
- // c[1].id.features.incidentEdge = (unsigned char)i2;
- // c[1].id.features.incidentVertex = 1;
-}
-
-// Find edge normal of max separation on A - return if separating axis is found
-// Find edge normal of max separation on B - return if separation axis is found
-// Choose reference edge as min(minA, minB)
-// Find incident edge
-// Clip
-
-// The normal points from 1 to 2
-void b2CollidePolygons(btManifoldResult* manifold,
- const btBox2dShape* polyA, const btTransform& xfA,
- const btBox2dShape* polyB, const btTransform& xfB)
-{
- int edgeA = 0;
- btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
- if (separationA > 0.0f)
- return;
-
- int edgeB = 0;
- btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
- if (separationB > 0.0f)
- return;
-
- const btBox2dShape* poly1; // reference poly
- const btBox2dShape* poly2; // incident poly
- btTransform xf1, xf2;
- int edge1; // reference edge
- unsigned char flip;
- const btScalar k_relativeTol = 0.98f;
- const btScalar k_absoluteTol = 0.001f;
-
- // TODO_ERIN use "radius" of poly for absolute tolerance.
- if (separationB > k_relativeTol * separationA + k_absoluteTol)
- {
- poly1 = polyB;
- poly2 = polyA;
- xf1 = xfB;
- xf2 = xfA;
- edge1 = edgeB;
- flip = 1;
- }
- else
- {
- poly1 = polyA;
- poly2 = polyB;
- xf1 = xfA;
- xf2 = xfB;
- edge1 = edgeA;
- flip = 0;
- }
-
- ClipVertex incidentEdge[2];
- FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
-
- int count1 = poly1->getVertexCount();
- const btVector3* vertices1 = poly1->getVertices();
-
- btVector3 v11 = vertices1[edge1];
- btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1 + 1] : vertices1[0];
-
- //btVector3 dv = v12 - v11;
- btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
- sideNormal.normalize();
- btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
-
- v11 = b2Mul(xf1, v11);
- v12 = b2Mul(xf1, v12);
-
- btScalar frontOffset = b2Dot(frontNormal, v11);
- btScalar sideOffset1 = -b2Dot(sideNormal, v11);
- btScalar sideOffset2 = b2Dot(sideNormal, v12);
-
- // Clip incident edge against extruded edge1 side edges.
- ClipVertex clipPoints1[2];
- clipPoints1[0].v.setValue(0, 0, 0);
- clipPoints1[1].v.setValue(0, 0, 0);
-
- ClipVertex clipPoints2[2];
- clipPoints2[0].v.setValue(0, 0, 0);
- clipPoints2[1].v.setValue(0, 0, 0);
-
- int np;
-
- // Clip to box side 1
- np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
-
- if (np < 2)
- return;
-
- // Clip to negative box side 1
- np = ClipSegmentToLine(clipPoints2, clipPoints1, sideNormal, sideOffset2);
-
- if (np < 2)
- {
- return;
- }
-
- // Now clipPoints2 contains the clipped points.
- btVector3 manifoldNormal = flip ? -frontNormal : frontNormal;
-
- int pointCount = 0;
- for (int i = 0; i < b2_maxManifoldPoints; ++i)
- {
- btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
-
- if (separation <= 0.0f)
- {
- //b2ManifoldPoint* cp = manifold->points + pointCount;
- //btScalar separation = separation;
- //cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
- //cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
-
- manifold->addContactPoint(-manifoldNormal, clipPoints2[i].v, separation);
-
- // cp->id = clipPoints2[i].id;
- // cp->id.features.flip = flip;
- ++pointCount;
- }
- }
-
- // manifold->pointCount = pointCount;}
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
deleted file mode 100644
index 3b66d1fd0b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
-#define BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
-
-#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-
-class btPersistentManifold;
-
-///box-box collision detection
-class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
-public:
- btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btActivatingCollisionAlgorithm(ci) {}
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
- virtual ~btBox2dBox2dCollisionAlgorithm();
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
- void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new (ptr) btBox2dBox2dCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
- }
- };
-};
-
-#endif //BT_BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
deleted file mode 100644
index 7a391e059a..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btBoxBoxCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "btBoxBoxDetector.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-#define USE_PERSISTENT_CONTACTS 1
-
-btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_ownManifold(false),
- m_manifoldPtr(mf)
-{
- if (!m_manifoldPtr && m_dispatcher->needsCollision(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject()))
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btBoxBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- if (!m_manifoldPtr)
- return;
-
- const btBoxShape* box0 = (btBoxShape*)body0Wrap->getCollisionShape();
- const btBoxShape* box1 = (btBoxShape*)body1Wrap->getCollisionShape();
-
- /// report a contact. internally this will be kept persistent, and contact reduction is done
- resultOut->setPersistentManifold(m_manifoldPtr);
-#ifndef USE_PERSISTENT_CONTACTS
- m_manifoldPtr->clearManifold();
-#endif //USE_PERSISTENT_CONTACTS
-
- btDiscreteCollisionDetectorInterface::ClosestPointInput input;
- input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB = body1Wrap->getWorldTransform();
-
- btBoxBoxDetector detector(box0, box1);
- detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
-
-#ifdef USE_PERSISTENT_CONTACTS
- // refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
-#endif //USE_PERSISTENT_CONTACTS
-}
-
-btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
-{
- //not yet
- return 1.f;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
deleted file mode 100644
index eb21065765..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BOX_BOX__COLLISION_ALGORITHM_H
-#define BT_BOX_BOX__COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-
-class btPersistentManifold;
-
-///box-box collision detection
-class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
-public:
- btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btActivatingCollisionAlgorithm(ci) {}
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btBoxBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
- virtual ~btBoxBoxCollisionAlgorithm();
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
- void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new (ptr) btBoxBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
- }
- };
-};
-
-#endif //BT_BOX_BOX__COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
deleted file mode 100644
index 202039956e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
- * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
- * All rights reserved. Email: russ@q12.org Web: www.q12.org
- Bullet Continuous Collision Detection and Physics Library
- Bullet is Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///ODE box-box collision detection is adapted to work with Bullet
-
-#include "btBoxBoxDetector.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-
-#include <float.h>
-#include <string.h>
-
-btBoxBoxDetector::btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2)
- : m_box1(box1),
- m_box2(box2)
-{
-}
-
-// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
-// generate contact points. this returns 0 if there is no contact otherwise
-// it returns the number of contacts generated.
-// `normal' returns the contact normal.
-// `depth' returns the maximum penetration depth along that normal.
-// `return_code' returns a number indicating the type of contact that was
-// detected:
-// 1,2,3 = box 2 intersects with a face of box 1
-// 4,5,6 = box 1 intersects with a face of box 2
-// 7..15 = edge-edge contact
-// `maxc' is the maximum number of contacts allowed to be generated, i.e.
-// the size of the `contact' array.
-// `contact' and `skip' are the contact array information provided to the
-// collision functions. this function only fills in the position and depth
-// fields.
-struct dContactGeom;
-#define dDOTpq(a, b, p, q) ((a)[0] * (b)[0] + (a)[p] * (b)[q] + (a)[2 * (p)] * (b)[2 * (q)])
-#define dInfinity FLT_MAX
-
-/*PURE_INLINE btScalar dDOT (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
-PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
-PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
-PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
-*/
-static btScalar dDOT(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 1, 1); }
-static btScalar dDOT44(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 4, 4); }
-static btScalar dDOT41(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 4, 1); }
-static btScalar dDOT14(const btScalar* a, const btScalar* b) { return dDOTpq(a, b, 1, 4); }
-#define dMULTIPLYOP1_331(A, op, B, C) \
- { \
- (A)[0] op dDOT41((B), (C)); \
- (A)[1] op dDOT41((B + 1), (C)); \
- (A)[2] op dDOT41((B + 2), (C)); \
- }
-
-#define dMULTIPLYOP0_331(A, op, B, C) \
- { \
- (A)[0] op dDOT((B), (C)); \
- (A)[1] op dDOT((B + 4), (C)); \
- (A)[2] op dDOT((B + 8), (C)); \
- }
-
-#define dMULTIPLY1_331(A, B, C) dMULTIPLYOP1_331(A, =, B, C)
-#define dMULTIPLY0_331(A, B, C) dMULTIPLYOP0_331(A, =, B, C)
-
-typedef btScalar dMatrix3[4 * 3];
-
-void dLineClosestApproach(const btVector3& pa, const btVector3& ua,
- const btVector3& pb, const btVector3& ub,
- btScalar* alpha, btScalar* beta);
-void dLineClosestApproach(const btVector3& pa, const btVector3& ua,
- const btVector3& pb, const btVector3& ub,
- btScalar* alpha, btScalar* beta)
-{
- btVector3 p;
- p[0] = pb[0] - pa[0];
- p[1] = pb[1] - pa[1];
- p[2] = pb[2] - pa[2];
- btScalar uaub = dDOT(ua, ub);
- btScalar q1 = dDOT(ua, p);
- btScalar q2 = -dDOT(ub, p);
- btScalar d = 1 - uaub * uaub;
- if (d <= btScalar(0.0001f))
- {
- // @@@ this needs to be made more robust
- *alpha = 0;
- *beta = 0;
- }
- else
- {
- d = 1.f / d;
- *alpha = (q1 + uaub * q2) * d;
- *beta = (uaub * q1 + q2) * d;
- }
-}
-
-// find all the intersection points between the 2D rectangle with vertices
-// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
-// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
-//
-// the intersection points are returned as x,y pairs in the 'ret' array.
-// the number of intersection points is returned by the function (this will
-// be in the range 0 to 8).
-
-static int intersectRectQuad2(btScalar h[2], btScalar p[8], btScalar ret[16])
-{
- // q (and r) contain nq (and nr) coordinate points for the current (and
- // chopped) polygons
- int nq = 4, nr = 0;
- btScalar buffer[16];
- btScalar* q = p;
- btScalar* r = ret;
- for (int dir = 0; dir <= 1; dir++)
- {
- // direction notation: xy[0] = x axis, xy[1] = y axis
- for (int sign = -1; sign <= 1; sign += 2)
- {
- // chop q along the line xy[dir] = sign*h[dir]
- btScalar* pq = q;
- btScalar* pr = r;
- nr = 0;
- for (int i = nq; i > 0; i--)
- {
- // go through all points in q and all lines between adjacent points
- if (sign * pq[dir] < h[dir])
- {
- // this point is inside the chopping line
- pr[0] = pq[0];
- pr[1] = pq[1];
- pr += 2;
- nr++;
- if (nr & 8)
- {
- q = r;
- goto done;
- }
- }
- btScalar* nextq = (i > 1) ? pq + 2 : q;
- if ((sign * pq[dir] < h[dir]) ^ (sign * nextq[dir] < h[dir]))
- {
- // this line crosses the chopping line
- pr[1 - dir] = pq[1 - dir] + (nextq[1 - dir] - pq[1 - dir]) /
- (nextq[dir] - pq[dir]) * (sign * h[dir] - pq[dir]);
- pr[dir] = sign * h[dir];
- pr += 2;
- nr++;
- if (nr & 8)
- {
- q = r;
- goto done;
- }
- }
- pq += 2;
- }
- q = r;
- r = (q == ret) ? buffer : ret;
- nq = nr;
- }
- }
-done:
- if (q != ret) memcpy(ret, q, nr * 2 * sizeof(btScalar));
- return nr;
-}
-
-#define M__PI 3.14159265f
-
-// given n points in the plane (array p, of size 2*n), generate m points that
-// best represent the whole set. the definition of 'best' here is not
-// predetermined - the idea is to select points that give good box-box
-// collision detection behavior. the chosen point indexes are returned in the
-// array iret (of size m). 'i0' is always the first entry in the array.
-// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
-// in the range [0..n-1].
-
-void cullPoints2(int n, btScalar p[], int m, int i0, int iret[]);
-void cullPoints2(int n, btScalar p[], int m, int i0, int iret[])
-{
- // compute the centroid of the polygon in cx,cy
- int i, j;
- btScalar a, cx, cy, q;
- if (n == 1)
- {
- cx = p[0];
- cy = p[1];
- }
- else if (n == 2)
- {
- cx = btScalar(0.5) * (p[0] + p[2]);
- cy = btScalar(0.5) * (p[1] + p[3]);
- }
- else
- {
- a = 0;
- cx = 0;
- cy = 0;
- for (i = 0; i < (n - 1); i++)
- {
- q = p[i * 2] * p[i * 2 + 3] - p[i * 2 + 2] * p[i * 2 + 1];
- a += q;
- cx += q * (p[i * 2] + p[i * 2 + 2]);
- cy += q * (p[i * 2 + 1] + p[i * 2 + 3]);
- }
- q = p[n * 2 - 2] * p[1] - p[0] * p[n * 2 - 1];
- if (btFabs(a + q) > SIMD_EPSILON)
- {
- a = 1.f / (btScalar(3.0) * (a + q));
- }
- else
- {
- a = BT_LARGE_FLOAT;
- }
- cx = a * (cx + q * (p[n * 2 - 2] + p[0]));
- cy = a * (cy + q * (p[n * 2 - 1] + p[1]));
- }
-
- // compute the angle of each point w.r.t. the centroid
- btScalar A[8];
- for (i = 0; i < n; i++) A[i] = btAtan2(p[i * 2 + 1] - cy, p[i * 2] - cx);
-
- // search for points that have angles closest to A[i0] + i*(2*pi/m).
- int avail[8];
- for (i = 0; i < n; i++) avail[i] = 1;
- avail[i0] = 0;
- iret[0] = i0;
- iret++;
- for (j = 1; j < m; j++)
- {
- a = btScalar(j) * (2 * M__PI / m) + A[i0];
- if (a > M__PI) a -= 2 * M__PI;
- btScalar maxdiff = 1e9, diff;
-
- *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
-
- for (i = 0; i < n; i++)
- {
- if (avail[i])
- {
- diff = btFabs(A[i] - a);
- if (diff > M__PI) diff = 2 * M__PI - diff;
- if (diff < maxdiff)
- {
- maxdiff = diff;
- *iret = i;
- }
- }
- }
-#if defined(DEBUG) || defined(_DEBUG)
- btAssert(*iret != i0); // ensure iret got set
-#endif
- avail[*iret] = 0;
- iret++;
- }
-}
-
-int dBoxBox2(const btVector3& p1, const dMatrix3 R1,
- const btVector3& side1, const btVector3& p2,
- const dMatrix3 R2, const btVector3& side2,
- btVector3& normal, btScalar* depth, int* return_code,
- int maxc, dContactGeom* /*contact*/, int /*skip*/, btDiscreteCollisionDetectorInterface::Result& output);
-int dBoxBox2(const btVector3& p1, const dMatrix3 R1,
- const btVector3& side1, const btVector3& p2,
- const dMatrix3 R2, const btVector3& side2,
- btVector3& normal, btScalar* depth, int* return_code,
- int maxc, dContactGeom* /*contact*/, int /*skip*/, btDiscreteCollisionDetectorInterface::Result& output)
-{
- const btScalar fudge_factor = btScalar(1.05);
- btVector3 p, pp, normalC(0.f, 0.f, 0.f);
- const btScalar* normalR = 0;
- btScalar A[3], B[3], R11, R12, R13, R21, R22, R23, R31, R32, R33,
- Q11, Q12, Q13, Q21, Q22, Q23, Q31, Q32, Q33, s, s2, l;
- int i, j, invert_normal, code;
-
- // get vector from centers of box 1 to box 2, relative to box 1
- p = p2 - p1;
- dMULTIPLY1_331(pp, R1, p); // get pp = p relative to body 1
-
- // get side lengths / 2
- A[0] = side1[0] * btScalar(0.5);
- A[1] = side1[1] * btScalar(0.5);
- A[2] = side1[2] * btScalar(0.5);
- B[0] = side2[0] * btScalar(0.5);
- B[1] = side2[1] * btScalar(0.5);
- B[2] = side2[2] * btScalar(0.5);
-
- // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
- R11 = dDOT44(R1 + 0, R2 + 0);
- R12 = dDOT44(R1 + 0, R2 + 1);
- R13 = dDOT44(R1 + 0, R2 + 2);
- R21 = dDOT44(R1 + 1, R2 + 0);
- R22 = dDOT44(R1 + 1, R2 + 1);
- R23 = dDOT44(R1 + 1, R2 + 2);
- R31 = dDOT44(R1 + 2, R2 + 0);
- R32 = dDOT44(R1 + 2, R2 + 1);
- R33 = dDOT44(R1 + 2, R2 + 2);
-
- Q11 = btFabs(R11);
- Q12 = btFabs(R12);
- Q13 = btFabs(R13);
- Q21 = btFabs(R21);
- Q22 = btFabs(R22);
- Q23 = btFabs(R23);
- Q31 = btFabs(R31);
- Q32 = btFabs(R32);
- Q33 = btFabs(R33);
-
- // for all 15 possible separating axes:
- // * see if the axis separates the boxes. if so, return 0.
- // * find the depth of the penetration along the separating axis (s2)
- // * if this is the largest depth so far, record it.
- // the normal vector will be set to the separating axis with the smallest
- // depth. note: normalR is set to point to a column of R1 or R2 if that is
- // the smallest depth normal so far. otherwise normalR is 0 and normalC is
- // set to a vector relative to body 1. invert_normal is 1 if the sign of
- // the normal should be flipped.
-
-#define TST(expr1, expr2, norm, cc) \
- s2 = btFabs(expr1) - (expr2); \
- if (s2 > 0) return 0; \
- if (s2 > s) \
- { \
- s = s2; \
- normalR = norm; \
- invert_normal = ((expr1) < 0); \
- code = (cc); \
- }
-
- s = -dInfinity;
- invert_normal = 0;
- code = 0;
-
- // separating axis = u1,u2,u3
- TST(pp[0], (A[0] + B[0] * Q11 + B[1] * Q12 + B[2] * Q13), R1 + 0, 1);
- TST(pp[1], (A[1] + B[0] * Q21 + B[1] * Q22 + B[2] * Q23), R1 + 1, 2);
- TST(pp[2], (A[2] + B[0] * Q31 + B[1] * Q32 + B[2] * Q33), R1 + 2, 3);
-
- // separating axis = v1,v2,v3
- TST(dDOT41(R2 + 0, p), (A[0] * Q11 + A[1] * Q21 + A[2] * Q31 + B[0]), R2 + 0, 4);
- TST(dDOT41(R2 + 1, p), (A[0] * Q12 + A[1] * Q22 + A[2] * Q32 + B[1]), R2 + 1, 5);
- TST(dDOT41(R2 + 2, p), (A[0] * Q13 + A[1] * Q23 + A[2] * Q33 + B[2]), R2 + 2, 6);
-
- // note: cross product axes need to be scaled when s is computed.
- // normal (n1,n2,n3) is relative to box 1.
-#undef TST
-#define TST(expr1, expr2, n1, n2, n3, cc) \
- s2 = btFabs(expr1) - (expr2); \
- if (s2 > SIMD_EPSILON) return 0; \
- l = btSqrt((n1) * (n1) + (n2) * (n2) + (n3) * (n3)); \
- if (l > SIMD_EPSILON) \
- { \
- s2 /= l; \
- if (s2 * fudge_factor > s) \
- { \
- s = s2; \
- normalR = 0; \
- normalC[0] = (n1) / l; \
- normalC[1] = (n2) / l; \
- normalC[2] = (n3) / l; \
- invert_normal = ((expr1) < 0); \
- code = (cc); \
- } \
- }
-
- btScalar fudge2(1.0e-5f);
-
- Q11 += fudge2;
- Q12 += fudge2;
- Q13 += fudge2;
-
- Q21 += fudge2;
- Q22 += fudge2;
- Q23 += fudge2;
-
- Q31 += fudge2;
- Q32 += fudge2;
- Q33 += fudge2;
-
- // separating axis = u1 x (v1,v2,v3)
- TST(pp[2] * R21 - pp[1] * R31, (A[1] * Q31 + A[2] * Q21 + B[1] * Q13 + B[2] * Q12), 0, -R31, R21, 7);
- TST(pp[2] * R22 - pp[1] * R32, (A[1] * Q32 + A[2] * Q22 + B[0] * Q13 + B[2] * Q11), 0, -R32, R22, 8);
- TST(pp[2] * R23 - pp[1] * R33, (A[1] * Q33 + A[2] * Q23 + B[0] * Q12 + B[1] * Q11), 0, -R33, R23, 9);
-
- // separating axis = u2 x (v1,v2,v3)
- TST(pp[0] * R31 - pp[2] * R11, (A[0] * Q31 + A[2] * Q11 + B[1] * Q23 + B[2] * Q22), R31, 0, -R11, 10);
- TST(pp[0] * R32 - pp[2] * R12, (A[0] * Q32 + A[2] * Q12 + B[0] * Q23 + B[2] * Q21), R32, 0, -R12, 11);
- TST(pp[0] * R33 - pp[2] * R13, (A[0] * Q33 + A[2] * Q13 + B[0] * Q22 + B[1] * Q21), R33, 0, -R13, 12);
-
- // separating axis = u3 x (v1,v2,v3)
- TST(pp[1] * R11 - pp[0] * R21, (A[0] * Q21 + A[1] * Q11 + B[1] * Q33 + B[2] * Q32), -R21, R11, 0, 13);
- TST(pp[1] * R12 - pp[0] * R22, (A[0] * Q22 + A[1] * Q12 + B[0] * Q33 + B[2] * Q31), -R22, R12, 0, 14);
- TST(pp[1] * R13 - pp[0] * R23, (A[0] * Q23 + A[1] * Q13 + B[0] * Q32 + B[1] * Q31), -R23, R13, 0, 15);
-
-#undef TST
-
- if (!code) return 0;
-
- // if we get to this point, the boxes interpenetrate. compute the normal
- // in global coordinates.
- if (normalR)
- {
- normal[0] = normalR[0];
- normal[1] = normalR[4];
- normal[2] = normalR[8];
- }
- else
- {
- dMULTIPLY0_331(normal, R1, normalC);
- }
- if (invert_normal)
- {
- normal[0] = -normal[0];
- normal[1] = -normal[1];
- normal[2] = -normal[2];
- }
- *depth = -s;
-
- // compute contact point(s)
-
- if (code > 6)
- {
- // an edge from box 1 touches an edge from box 2.
- // find a point pa on the intersecting edge of box 1
- btVector3 pa;
- btScalar sign;
- for (i = 0; i < 3; i++) pa[i] = p1[i];
- for (j = 0; j < 3; j++)
- {
- sign = (dDOT14(normal, R1 + j) > 0) ? btScalar(1.0) : btScalar(-1.0);
- for (i = 0; i < 3; i++) pa[i] += sign * A[j] * R1[i * 4 + j];
- }
-
- // find a point pb on the intersecting edge of box 2
- btVector3 pb;
- for (i = 0; i < 3; i++) pb[i] = p2[i];
- for (j = 0; j < 3; j++)
- {
- sign = (dDOT14(normal, R2 + j) > 0) ? btScalar(-1.0) : btScalar(1.0);
- for (i = 0; i < 3; i++) pb[i] += sign * B[j] * R2[i * 4 + j];
- }
-
- btScalar alpha, beta;
- btVector3 ua, ub;
- for (i = 0; i < 3; i++) ua[i] = R1[((code)-7) / 3 + i * 4];
- for (i = 0; i < 3; i++) ub[i] = R2[((code)-7) % 3 + i * 4];
-
- dLineClosestApproach(pa, ua, pb, ub, &alpha, &beta);
- for (i = 0; i < 3; i++) pa[i] += ua[i] * alpha;
- for (i = 0; i < 3; i++) pb[i] += ub[i] * beta;
-
- {
- //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
- //contact[0].depth = *depth;
- btVector3 pointInWorld;
-
-#ifdef USE_CENTER_POINT
- for (i = 0; i < 3; i++)
- pointInWorld[i] = (pa[i] + pb[i]) * btScalar(0.5);
- output.addContactPoint(-normal, pointInWorld, -*depth);
-#else
- output.addContactPoint(-normal, pb, -*depth);
-
-#endif //
- *return_code = code;
- }
- return 1;
- }
-
- // okay, we have a face-something intersection (because the separating
- // axis is perpendicular to a face). define face 'a' to be the reference
- // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
- // the incident face (the closest face of the other box).
-
- const btScalar *Ra, *Rb, *pa, *pb, *Sa, *Sb;
- if (code <= 3)
- {
- Ra = R1;
- Rb = R2;
- pa = p1;
- pb = p2;
- Sa = A;
- Sb = B;
- }
- else
- {
- Ra = R2;
- Rb = R1;
- pa = p2;
- pb = p1;
- Sa = B;
- Sb = A;
- }
-
- // nr = normal vector of reference face dotted with axes of incident box.
- // anr = absolute values of nr.
- btVector3 normal2, nr, anr;
- if (code <= 3)
- {
- normal2[0] = normal[0];
- normal2[1] = normal[1];
- normal2[2] = normal[2];
- }
- else
- {
- normal2[0] = -normal[0];
- normal2[1] = -normal[1];
- normal2[2] = -normal[2];
- }
- dMULTIPLY1_331(nr, Rb, normal2);
- anr[0] = btFabs(nr[0]);
- anr[1] = btFabs(nr[1]);
- anr[2] = btFabs(nr[2]);
-
- // find the largest compontent of anr: this corresponds to the normal
- // for the indident face. the other axis numbers of the indicent face
- // are stored in a1,a2.
- int lanr, a1, a2;
- if (anr[1] > anr[0])
- {
- if (anr[1] > anr[2])
- {
- a1 = 0;
- lanr = 1;
- a2 = 2;
- }
- else
- {
- a1 = 0;
- a2 = 1;
- lanr = 2;
- }
- }
- else
- {
- if (anr[0] > anr[2])
- {
- lanr = 0;
- a1 = 1;
- a2 = 2;
- }
- else
- {
- a1 = 0;
- a2 = 1;
- lanr = 2;
- }
- }
-
- // compute center point of incident face, in reference-face coordinates
- btVector3 center;
- if (nr[lanr] < 0)
- {
- for (i = 0; i < 3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i * 4 + lanr];
- }
- else
- {
- for (i = 0; i < 3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i * 4 + lanr];
- }
-
- // find the normal and non-normal axis numbers of the reference box
- int codeN, code1, code2;
- if (code <= 3)
- codeN = code - 1;
- else
- codeN = code - 4;
- if (codeN == 0)
- {
- code1 = 1;
- code2 = 2;
- }
- else if (codeN == 1)
- {
- code1 = 0;
- code2 = 2;
- }
- else
- {
- code1 = 0;
- code2 = 1;
- }
-
- // find the four corners of the incident face, in reference-face coordinates
- btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
- btScalar c1, c2, m11, m12, m21, m22;
- c1 = dDOT14(center, Ra + code1);
- c2 = dDOT14(center, Ra + code2);
- // optimize this? - we have already computed this data above, but it is not
- // stored in an easy-to-index format. for now it's quicker just to recompute
- // the four dot products.
- m11 = dDOT44(Ra + code1, Rb + a1);
- m12 = dDOT44(Ra + code1, Rb + a2);
- m21 = dDOT44(Ra + code2, Rb + a1);
- m22 = dDOT44(Ra + code2, Rb + a2);
- {
- btScalar k1 = m11 * Sb[a1];
- btScalar k2 = m21 * Sb[a1];
- btScalar k3 = m12 * Sb[a2];
- btScalar k4 = m22 * Sb[a2];
- quad[0] = c1 - k1 - k3;
- quad[1] = c2 - k2 - k4;
- quad[2] = c1 - k1 + k3;
- quad[3] = c2 - k2 + k4;
- quad[4] = c1 + k1 + k3;
- quad[5] = c2 + k2 + k4;
- quad[6] = c1 + k1 - k3;
- quad[7] = c2 + k2 - k4;
- }
-
- // find the size of the reference face
- btScalar rect[2];
- rect[0] = Sa[code1];
- rect[1] = Sa[code2];
-
- // intersect the incident and reference faces
- btScalar ret[16];
- int n = intersectRectQuad2(rect, quad, ret);
- if (n < 1) return 0; // this should never happen
-
- // convert the intersection points into reference-face coordinates,
- // and compute the contact position and depth for each point. only keep
- // those points that have a positive (penetrating) depth. delete points in
- // the 'ret' array as necessary so that 'point' and 'ret' correspond.
- btScalar point[3 * 8]; // penetrating contact points
- btScalar dep[8]; // depths for those points
- btScalar det1 = 1.f / (m11 * m22 - m12 * m21);
- m11 *= det1;
- m12 *= det1;
- m21 *= det1;
- m22 *= det1;
- int cnum = 0; // number of penetrating contact points found
- for (j = 0; j < n; j++)
- {
- btScalar k1 = m22 * (ret[j * 2] - c1) - m12 * (ret[j * 2 + 1] - c2);
- btScalar k2 = -m21 * (ret[j * 2] - c1) + m11 * (ret[j * 2 + 1] - c2);
- for (i = 0; i < 3; i++) point[cnum * 3 + i] =
- center[i] + k1 * Rb[i * 4 + a1] + k2 * Rb[i * 4 + a2];
- dep[cnum] = Sa[codeN] - dDOT(normal2, point + cnum * 3);
- if (dep[cnum] >= 0)
- {
- ret[cnum * 2] = ret[j * 2];
- ret[cnum * 2 + 1] = ret[j * 2 + 1];
- cnum++;
- }
- }
- if (cnum < 1) return 0; // this should never happen
-
- // we can't generate more contacts than we actually have
- if (maxc > cnum) maxc = cnum;
- if (maxc < 1) maxc = 1;
-
- if (cnum <= maxc)
- {
- if (code < 4)
- {
- // we have less contacts than we need, so we use them all
- for (j = 0; j < cnum; j++)
- {
- btVector3 pointInWorld;
- for (i = 0; i < 3; i++)
- pointInWorld[i] = point[j * 3 + i] + pa[i];
- output.addContactPoint(-normal, pointInWorld, -dep[j]);
- }
- }
- else
- {
- // we have less contacts than we need, so we use them all
- for (j = 0; j < cnum; j++)
- {
- btVector3 pointInWorld;
- for (i = 0; i < 3; i++)
- pointInWorld[i] = point[j * 3 + i] + pa[i] - normal[i] * dep[j];
- //pointInWorld[i] = point[j*3+i] + pa[i];
- output.addContactPoint(-normal, pointInWorld, -dep[j]);
- }
- }
- }
- else
- {
- // we have more contacts than are wanted, some of them must be culled.
- // find the deepest point, it is always the first contact.
- int i1 = 0;
- btScalar maxdepth = dep[0];
- for (i = 1; i < cnum; i++)
- {
- if (dep[i] > maxdepth)
- {
- maxdepth = dep[i];
- i1 = i;
- }
- }
-
- int iret[8];
- cullPoints2(cnum, ret, maxc, i1, iret);
-
- for (j = 0; j < maxc; j++)
- {
- // dContactGeom *con = CONTACT(contact,skip*j);
- // for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
- // con->depth = dep[iret[j]];
-
- btVector3 posInWorld;
- for (i = 0; i < 3; i++)
- posInWorld[i] = point[iret[j] * 3 + i] + pa[i];
- if (code < 4)
- {
- output.addContactPoint(-normal, posInWorld, -dep[iret[j]]);
- }
- else
- {
- output.addContactPoint(-normal, posInWorld - normal * dep[iret[j]], -dep[iret[j]]);
- }
- }
- cnum = maxc;
- }
-
- *return_code = code;
- return cnum;
-}
-
-void btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* /*debugDraw*/, bool /*swapResults*/)
-{
- const btTransform& transformA = input.m_transformA;
- const btTransform& transformB = input.m_transformB;
-
- int skip = 0;
- dContactGeom* contact = 0;
-
- dMatrix3 R1;
- dMatrix3 R2;
-
- for (int j = 0; j < 3; j++)
- {
- R1[0 + 4 * j] = transformA.getBasis()[j].x();
- R2[0 + 4 * j] = transformB.getBasis()[j].x();
-
- R1[1 + 4 * j] = transformA.getBasis()[j].y();
- R2[1 + 4 * j] = transformB.getBasis()[j].y();
-
- R1[2 + 4 * j] = transformA.getBasis()[j].z();
- R2[2 + 4 * j] = transformB.getBasis()[j].z();
- }
-
- btVector3 normal;
- btScalar depth;
- int return_code;
- int maxc = 4;
-
- dBoxBox2(transformA.getOrigin(),
- R1,
- 2.f * m_box1->getHalfExtentsWithMargin(),
- transformB.getOrigin(),
- R2,
- 2.f * m_box2->getHalfExtentsWithMargin(),
- normal, &depth, &return_code,
- maxc, contact, skip,
- output);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
deleted file mode 100644
index 9f7d988fc1..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
- * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
- * All rights reserved. Email: russ@q12.org Web: www.q12.org
-
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#ifndef BT_BOX_BOX_DETECTOR_H
-#define BT_BOX_BOX_DETECTOR_H
-
-class btBoxShape;
-#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-
-/// btBoxBoxDetector wraps the ODE box-box collision detector
-/// re-distributed under the Zlib license with permission from Russell L. Smith
-struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
-{
- const btBoxShape* m_box1;
- const btBoxShape* m_box2;
-
-public:
- btBoxBoxDetector(const btBoxShape* box1, const btBoxShape* box2);
-
- virtual ~btBoxBoxDetector(){};
-
- virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
-};
-
-#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
deleted file mode 100644
index d6e15f555b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_CONFIGURATION
-#define BT_COLLISION_CONFIGURATION
-
-struct btCollisionAlgorithmCreateFunc;
-
-class btPoolAllocator;
-
-///btCollisionConfiguration allows to configure Bullet collision detection
-///stack allocator size, default collision algorithms and persistent manifold pool size
-///@todo: describe the meaning
-class btCollisionConfiguration
-{
-public:
- virtual ~btCollisionConfiguration()
- {
- }
-
- ///memory pools
- virtual btPoolAllocator* getPersistentManifoldPool() = 0;
-
- virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
-
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
-
- virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1) = 0;
-};
-
-#endif //BT_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
deleted file mode 100644
index bd81284939..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_CREATE_FUNC
-#define BT_COLLISION_CREATE_FUNC
-
-#include "LinearMath/btAlignedObjectArray.h"
-class btCollisionAlgorithm;
-class btCollisionObject;
-struct btCollisionObjectWrapper;
-struct btCollisionAlgorithmConstructionInfo;
-
-///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
-struct btCollisionAlgorithmCreateFunc
-{
- bool m_swapped;
-
- btCollisionAlgorithmCreateFunc()
- : m_swapped(false)
- {
- }
- virtual ~btCollisionAlgorithmCreateFunc(){};
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo&, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- (void)body0Wrap;
- (void)body1Wrap;
- return 0;
- }
-};
-#endif //BT_COLLISION_CREATE_FUNC
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
deleted file mode 100644
index 25b2b1ea46..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionDispatcher.h"
-#include "LinearMath/btQuickprof.h"
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-#include "LinearMath/btPoolAllocator.h"
-#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-#ifdef BT_DEBUG
-#include <stdio.h>
-#endif
-
-btCollisionDispatcher::btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration) : m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
- m_collisionConfiguration(collisionConfiguration)
-{
- int i;
-
- setNearCallback(defaultNearCallback);
-
- m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
-
- m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
-
- for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
- {
- for (int j = 0; j < MAX_BROADPHASE_COLLISION_TYPES; j++)
- {
- m_doubleDispatchContactPoints[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i, j);
- btAssert(m_doubleDispatchContactPoints[i][j]);
- m_doubleDispatchClosestPoints[i][j] = m_collisionConfiguration->getClosestPointsAlgorithmCreateFunc(i, j);
- }
- }
-}
-
-void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
-{
- m_doubleDispatchContactPoints[proxyType0][proxyType1] = createFunc;
-}
-
-void btCollisionDispatcher::registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc)
-{
- m_doubleDispatchClosestPoints[proxyType0][proxyType1] = createFunc;
-}
-
-btCollisionDispatcher::~btCollisionDispatcher()
-{
-}
-
-btPersistentManifold* btCollisionDispatcher::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- //btAssert(gNumManifold < 65535);
-
- //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
-
- btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
- : gContactBreakingThreshold;
-
- btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
-
- void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
- if (NULL == mem)
- {
- //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
- if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
- {
- mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
- }
- else
- {
- btAssert(0);
- //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
- return 0;
- }
- }
- btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
- manifold->m_index1a = m_manifoldsPtr.size();
- m_manifoldsPtr.push_back(manifold);
-
- return manifold;
-}
-
-void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
-{
- manifold->clearManifold();
-}
-
-void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
-{
- //printf("releaseManifold: gNumManifold %d\n",gNumManifold);
- clearManifold(manifold);
-
- int findIndex = manifold->m_index1a;
- btAssert(findIndex < m_manifoldsPtr.size());
- m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
- m_manifoldsPtr[findIndex]->m_index1a = findIndex;
- m_manifoldsPtr.pop_back();
-
- manifold->~btPersistentManifold();
- if (m_persistentManifoldPoolAllocator->validPtr(manifold))
- {
- m_persistentManifoldPoolAllocator->freeMemory(manifold);
- }
- else
- {
- btAlignedFree(manifold);
- }
-}
-
-btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType algoType)
-{
- btCollisionAlgorithmConstructionInfo ci;
-
- ci.m_dispatcher1 = this;
- ci.m_manifold = sharedManifold;
- btCollisionAlgorithm* algo = 0;
- if (algoType == BT_CONTACT_POINT_ALGORITHMS)
- {
- algo = m_doubleDispatchContactPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
- }
- else
- {
- algo = m_doubleDispatchClosestPoints[body0Wrap->getCollisionShape()->getShapeType()][body1Wrap->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci, body0Wrap, body1Wrap);
- }
-
- return algo;
-}
-
-bool btCollisionDispatcher::needsResponse(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- //here you can do filtering
- bool hasResponse =
- (body0->hasContactResponse() && body1->hasContactResponse());
- //no response between two static/kinematic bodies:
- hasResponse = hasResponse &&
- ((!body0->isStaticOrKinematicObject()) || (!body1->isStaticOrKinematicObject()));
- return hasResponse;
-}
-
-bool btCollisionDispatcher::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- btAssert(body0);
- btAssert(body1);
-
- bool needsCollision = true;
-
-#ifdef BT_DEBUG
- if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
- {
- //broadphase filtering already deals with this
- if (body0->isStaticOrKinematicObject() && body1->isStaticOrKinematicObject())
- {
- m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
- printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
- }
- }
-#endif //BT_DEBUG
-
- if ((!body0->isActive()) && (!body1->isActive()))
- needsCollision = false;
- else if ((!body0->checkCollideWith(body1)) || (!body1->checkCollideWith(body0)))
- needsCollision = false;
-
- return needsCollision;
-}
-
-///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
-///this is useful for the collision dispatcher.
-class btCollisionPairCallback : public btOverlapCallback
-{
- const btDispatcherInfo& m_dispatchInfo;
- btCollisionDispatcher* m_dispatcher;
-
-public:
- btCollisionPairCallback(const btDispatcherInfo& dispatchInfo, btCollisionDispatcher* dispatcher)
- : m_dispatchInfo(dispatchInfo),
- m_dispatcher(dispatcher)
- {
- }
-
- /*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
- {
- m_dispatchInfo = other.m_dispatchInfo;
- m_dispatcher = other.m_dispatcher;
- return *this;
- }
- */
-
- virtual ~btCollisionPairCallback() {}
-
- virtual bool processOverlap(btBroadphasePair& pair)
- {
- (*m_dispatcher->getNearCallback())(pair, *m_dispatcher, m_dispatchInfo);
- return false;
- }
-};
-
-void btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher)
-{
- //m_blockedForChanges = true;
-
- btCollisionPairCallback collisionCallback(dispatchInfo, this);
-
- {
- BT_PROFILE("processAllOverlappingPairs");
- pairCache->processAllOverlappingPairs(&collisionCallback, dispatcher, dispatchInfo);
- }
-
- //m_blockedForChanges = false;
-}
-
-//by default, Bullet will use this near callback
-void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
-{
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
-
- if (dispatcher.needsCollision(colObj0, colObj1))
- {
- btCollisionObjectWrapper obj0Wrap(0, colObj0->getCollisionShape(), colObj0, colObj0->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper obj1Wrap(0, colObj1->getCollisionShape(), colObj1, colObj1->getWorldTransform(), -1, -1);
-
- //dispatcher will keep algorithms persistent in the collision pair
- if (!collisionPair.m_algorithm)
- {
- collisionPair.m_algorithm = dispatcher.findAlgorithm(&obj0Wrap, &obj1Wrap, 0, BT_CONTACT_POINT_ALGORITHMS);
- }
-
- if (collisionPair.m_algorithm)
- {
- btManifoldResult contactPointResult(&obj0Wrap, &obj1Wrap);
-
- if (dispatchInfo.m_dispatchFunc == btDispatcherInfo::DISPATCH_DISCRETE)
- {
- //discrete collision detection query
-
- collisionPair.m_algorithm->processCollision(&obj0Wrap, &obj1Wrap, dispatchInfo, &contactPointResult);
- }
- else
- {
- //continuous collision detection query, time of impact (toi)
- btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0, colObj1, dispatchInfo, &contactPointResult);
- if (dispatchInfo.m_timeOfImpact > toi)
- dispatchInfo.m_timeOfImpact = toi;
- }
- }
- }
-}
-
-void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
-{
- void* mem = m_collisionAlgorithmPoolAllocator->allocate(size);
- if (NULL == mem)
- {
- //warn user for overflow?
- return btAlignedAlloc(static_cast<size_t>(size), 16);
- }
- return mem;
-}
-
-void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
-{
- if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
- {
- m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
- }
- else
- {
- btAlignedFree(ptr);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
deleted file mode 100644
index 04309670cf..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION__DISPATCHER_H
-#define BT_COLLISION__DISPATCHER_H
-
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-class btIDebugDraw;
-class btOverlappingPairCache;
-class btPoolAllocator;
-class btCollisionConfiguration;
-
-#include "btCollisionCreateFunc.h"
-
-#define USE_DISPATCH_REGISTRY_ARRAY 1
-
-class btCollisionDispatcher;
-///user can override this nearcallback for collision filtering and more finegrained control over collision detection
-typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
-
-///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
-///Time of Impact, Closest Points and Penetration Depth.
-class btCollisionDispatcher : public btDispatcher
-{
-protected:
- int m_dispatcherFlags;
-
- btAlignedObjectArray<btPersistentManifold*> m_manifoldsPtr;
-
- btNearCallback m_nearCallback;
-
- btPoolAllocator* m_collisionAlgorithmPoolAllocator;
-
- btPoolAllocator* m_persistentManifoldPoolAllocator;
-
- btCollisionAlgorithmCreateFunc* m_doubleDispatchContactPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
-
- btCollisionAlgorithmCreateFunc* m_doubleDispatchClosestPoints[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
-
- btCollisionConfiguration* m_collisionConfiguration;
-
-public:
- enum DispatcherFlags
- {
- CD_STATIC_STATIC_REPORTED = 1,
- CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2,
- CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION = 4
- };
-
- int getDispatcherFlags() const
- {
- return m_dispatcherFlags;
- }
-
- void setDispatcherFlags(int flags)
- {
- m_dispatcherFlags = flags;
- }
-
- ///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
- void registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
-
- void registerClosestPointsCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
-
- int getNumManifolds() const
- {
- return int(m_manifoldsPtr.size());
- }
-
- btPersistentManifold** getInternalManifoldPointer()
- {
- return m_manifoldsPtr.size() ? &m_manifoldsPtr[0] : 0;
- }
-
- btPersistentManifold* getManifoldByIndexInternal(int index)
- {
- btAssert(index>=0);
- btAssert(index<m_manifoldsPtr.size());
- return m_manifoldsPtr[index];
- }
-
- const btPersistentManifold* getManifoldByIndexInternal(int index) const
- {
- btAssert(index>=0);
- btAssert(index<m_manifoldsPtr.size());
- return m_manifoldsPtr[index];
- }
-
- btCollisionDispatcher(btCollisionConfiguration* collisionConfiguration);
-
- virtual ~btCollisionDispatcher();
-
- virtual btPersistentManifold* getNewManifold(const btCollisionObject* b0, const btCollisionObject* b1);
-
- virtual void releaseManifold(btPersistentManifold* manifold);
-
- virtual void clearManifold(btPersistentManifold* manifold);
-
- btCollisionAlgorithm* findAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btPersistentManifold* sharedManifold, ebtDispatcherQueryType queryType);
-
- virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
-
- virtual bool needsResponse(const btCollisionObject* body0, const btCollisionObject* body1);
-
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& dispatchInfo, btDispatcher* dispatcher);
-
- void setNearCallback(btNearCallback nearCallback)
- {
- m_nearCallback = nearCallback;
- }
-
- btNearCallback getNearCallback() const
- {
- return m_nearCallback;
- }
-
- //by default, Bullet will use this near callback
- static void defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
-
- virtual void* allocateCollisionAlgorithm(int size);
-
- virtual void freeCollisionAlgorithm(void* ptr);
-
- btCollisionConfiguration* getCollisionConfiguration()
- {
- return m_collisionConfiguration;
- }
-
- const btCollisionConfiguration* getCollisionConfiguration() const
- {
- return m_collisionConfiguration;
- }
-
- void setCollisionConfiguration(btCollisionConfiguration* config)
- {
- m_collisionConfiguration = config;
- }
-
- virtual btPoolAllocator* getInternalManifoldPool()
- {
- return m_persistentManifoldPoolAllocator;
- }
-
- virtual const btPoolAllocator* getInternalManifoldPool() const
- {
- return m_persistentManifoldPoolAllocator;
- }
-};
-
-#endif //BT_COLLISION__DISPATCHER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
deleted file mode 100644
index 89bc8d920e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionDispatcherMt.h"
-#include "LinearMath/btQuickprof.h"
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-#include "LinearMath/btPoolAllocator.h"
-#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btCollisionDispatcherMt::btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize)
- : btCollisionDispatcher(config)
-{
- m_batchManifoldsPtr.resize(btGetTaskScheduler()->getNumThreads());
- m_batchUpdating = false;
- m_grainSize = grainSize; // iterations per task
-}
-
-btPersistentManifold* btCollisionDispatcherMt::getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- //optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
-
- btScalar contactBreakingThreshold = (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold), body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
- : gContactBreakingThreshold;
-
- btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(), body1->getContactProcessingThreshold());
-
- void* mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
- if (NULL == mem)
- {
- //we got a pool memory overflow, by default we fallback to dynamically allocate memory. If we require a contiguous contact pool then assert.
- if ((m_dispatcherFlags & CD_DISABLE_CONTACTPOOL_DYNAMIC_ALLOCATION) == 0)
- {
- mem = btAlignedAlloc(sizeof(btPersistentManifold), 16);
- }
- else
- {
- btAssert(0);
- //make sure to increase the m_defaultMaxPersistentManifoldPoolSize in the btDefaultCollisionConstructionInfo/btDefaultCollisionConfiguration
- return 0;
- }
- }
- btPersistentManifold* manifold = new (mem) btPersistentManifold(body0, body1, 0, contactBreakingThreshold, contactProcessingThreshold);
- if (!m_batchUpdating)
- {
- // batch updater will update manifold pointers array after finishing, so
- // only need to update array when not batch-updating
- //btAssert( !btThreadsAreRunning() );
- manifold->m_index1a = m_manifoldsPtr.size();
- m_manifoldsPtr.push_back(manifold);
- }
- else
- {
- m_batchManifoldsPtr[btGetCurrentThreadIndex()].push_back(manifold);
- }
-
- return manifold;
-}
-
-void btCollisionDispatcherMt::releaseManifold(btPersistentManifold* manifold)
-{
- clearManifold(manifold);
- //btAssert( !btThreadsAreRunning() );
- if (!m_batchUpdating)
- {
- // batch updater will update manifold pointers array after finishing, so
- // only need to update array when not batch-updating
- int findIndex = manifold->m_index1a;
- btAssert(findIndex < m_manifoldsPtr.size());
- m_manifoldsPtr.swap(findIndex, m_manifoldsPtr.size() - 1);
- m_manifoldsPtr[findIndex]->m_index1a = findIndex;
- m_manifoldsPtr.pop_back();
- }
-
- manifold->~btPersistentManifold();
- if (m_persistentManifoldPoolAllocator->validPtr(manifold))
- {
- m_persistentManifoldPoolAllocator->freeMemory(manifold);
- }
- else
- {
- btAlignedFree(manifold);
- }
-}
-
-struct CollisionDispatcherUpdater : public btIParallelForBody
-{
- btBroadphasePair* mPairArray;
- btNearCallback mCallback;
- btCollisionDispatcher* mDispatcher;
- const btDispatcherInfo* mInfo;
-
- CollisionDispatcherUpdater()
- {
- mPairArray = NULL;
- mCallback = NULL;
- mDispatcher = NULL;
- mInfo = NULL;
- }
- void forLoop(int iBegin, int iEnd) const
- {
- for (int i = iBegin; i < iEnd; ++i)
- {
- btBroadphasePair* pair = &mPairArray[i];
- mCallback(*pair, *mDispatcher, *mInfo);
- }
- }
-};
-
-void btCollisionDispatcherMt::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher)
-{
- const int pairCount = pairCache->getNumOverlappingPairs();
- if (pairCount == 0)
- {
- return;
- }
- CollisionDispatcherUpdater updater;
- updater.mCallback = getNearCallback();
- updater.mPairArray = pairCache->getOverlappingPairArrayPtr();
- updater.mDispatcher = this;
- updater.mInfo = &info;
-
- m_batchUpdating = true;
- btParallelFor(0, pairCount, m_grainSize, updater);
- m_batchUpdating = false;
-
- // merge new manifolds, if any
- for (int i = 0; i < m_batchManifoldsPtr.size(); ++i)
- {
- btAlignedObjectArray<btPersistentManifold*>& batchManifoldsPtr = m_batchManifoldsPtr[i];
-
- for (int j = 0; j < batchManifoldsPtr.size(); ++j)
- {
- m_manifoldsPtr.push_back(batchManifoldsPtr[j]);
- }
-
- batchManifoldsPtr.resizeNoInitialize(0);
- }
-
- // update the indices (used when releasing manifolds)
- for (int i = 0; i < m_manifoldsPtr.size(); ++i)
- {
- m_manifoldsPtr[i]->m_index1a = i;
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
deleted file mode 100644
index 1155de2cfe..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcherMt.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_DISPATCHER_MT_H
-#define BT_COLLISION_DISPATCHER_MT_H
-
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "LinearMath/btThreads.h"
-
-class btCollisionDispatcherMt : public btCollisionDispatcher
-{
-public:
- btCollisionDispatcherMt(btCollisionConfiguration* config, int grainSize = 40);
-
- virtual btPersistentManifold* getNewManifold(const btCollisionObject* body0, const btCollisionObject* body1) BT_OVERRIDE;
- virtual void releaseManifold(btPersistentManifold* manifold) BT_OVERRIDE;
-
- virtual void dispatchAllCollisionPairs(btOverlappingPairCache* pairCache, const btDispatcherInfo& info, btDispatcher* dispatcher) BT_OVERRIDE;
-
-protected:
- btAlignedObjectArray<btAlignedObjectArray<btPersistentManifold*> > m_batchManifoldsPtr;
- bool m_batchUpdating;
- int m_grainSize;
-};
-
-#endif //BT_COLLISION_DISPATCHER_MT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
deleted file mode 100644
index b48d9301d7..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionObject.h"
-#include "LinearMath/btSerializer.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-
-btCollisionObject::btCollisionObject()
- : m_interpolationLinearVelocity(0.f, 0.f, 0.f),
- m_interpolationAngularVelocity(0.f, 0.f, 0.f),
- m_anisotropicFriction(1.f, 1.f, 1.f),
- m_hasAnisotropicFriction(false),
- m_contactProcessingThreshold(BT_LARGE_FLOAT),
- m_broadphaseHandle(0),
- m_collisionShape(0),
- m_extensionPointer(0),
- m_rootCollisionShape(0),
- m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
- m_islandTag1(-1),
- m_companionId(-1),
- m_worldArrayIndex(-1),
- m_activationState1(1),
- m_deactivationTime(btScalar(0.)),
- m_friction(btScalar(0.5)),
- m_restitution(btScalar(0.)),
- m_rollingFriction(0.0f),
- m_spinningFriction(0.f),
- m_contactDamping(.1),
- m_contactStiffness(BT_LARGE_FLOAT),
- m_internalType(CO_COLLISION_OBJECT),
- m_userObjectPointer(0),
- m_userIndex2(-1),
- m_userIndex(-1),
- m_userIndex3(-1),
- m_hitFraction(btScalar(1.)),
- m_ccdSweptSphereRadius(btScalar(0.)),
- m_ccdMotionThreshold(btScalar(0.)),
- m_checkCollideWith(false),
- m_updateRevision(0)
-{
- m_worldTransform.setIdentity();
- m_interpolationWorldTransform.setIdentity();
-}
-
-btCollisionObject::~btCollisionObject()
-{
-}
-
-void btCollisionObject::setActivationState(int newState) const
-{
- if ((m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
- m_activationState1 = newState;
-}
-
-void btCollisionObject::forceActivationState(int newState) const
-{
- m_activationState1 = newState;
-}
-
-void btCollisionObject::activate(bool forceActivation) const
-{
- if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT)))
- {
- setActivationState(ACTIVE_TAG);
- m_deactivationTime = btScalar(0.);
- }
-}
-
-const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
-
- m_worldTransform.serialize(dataOut->m_worldTransform);
- m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform);
- m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity);
- m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity);
- m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction);
- dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction;
- dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
- dataOut->m_broadphaseHandle = 0;
- dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
- dataOut->m_rootCollisionShape = 0; //@todo
- dataOut->m_collisionFlags = m_collisionFlags;
- dataOut->m_islandTag1 = m_islandTag1;
- dataOut->m_companionId = m_companionId;
- dataOut->m_activationState1 = m_activationState1;
- dataOut->m_deactivationTime = m_deactivationTime;
- dataOut->m_friction = m_friction;
- dataOut->m_rollingFriction = m_rollingFriction;
- dataOut->m_contactDamping = m_contactDamping;
- dataOut->m_contactStiffness = m_contactStiffness;
- dataOut->m_restitution = m_restitution;
- dataOut->m_internalType = m_internalType;
-
- char* name = (char*)serializer->findNameForPointer(this);
- dataOut->m_name = (char*)serializer->getUniquePointer(name);
- if (dataOut->m_name)
- {
- serializer->serializeName(name);
- }
- dataOut->m_hitFraction = m_hitFraction;
- dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
- dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
- dataOut->m_checkCollideWith = m_checkCollideWith;
- if (m_broadphaseHandle)
- {
- dataOut->m_collisionFilterGroup = m_broadphaseHandle->m_collisionFilterGroup;
- dataOut->m_collisionFilterMask = m_broadphaseHandle->m_collisionFilterMask;
- dataOut->m_uniqueId = m_broadphaseHandle->m_uniqueId;
- }
- else
- {
- dataOut->m_collisionFilterGroup = 0;
- dataOut->m_collisionFilterMask = 0;
- dataOut->m_uniqueId = -1;
- }
- return btCollisionObjectDataName;
-}
-
-void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
-{
- int len = calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_COLLISIONOBJECT_CODE, (void*)this);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
deleted file mode 100644
index dbe82fd61f..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_OBJECT_H
-#define BT_COLLISION_OBJECT_H
-
-#include "LinearMath/btTransform.h"
-
-//island management, m_activationState1
-#define ACTIVE_TAG 1
-#define ISLAND_SLEEPING 2
-#define WANTS_DEACTIVATION 3
-#define DISABLE_DEACTIVATION 4
-#define DISABLE_SIMULATION 5
-#define FIXED_BASE_MULTI_BODY 6
-
-struct btBroadphaseProxy;
-class btCollisionShape;
-struct btCollisionShapeData;
-#include "LinearMath/btMotionState.h"
-#include "LinearMath/btAlignedAllocator.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btCollisionObjectData btCollisionObjectDoubleData
-#define btCollisionObjectDataName "btCollisionObjectDoubleData"
-#else
-#define btCollisionObjectData btCollisionObjectFloatData
-#define btCollisionObjectDataName "btCollisionObjectFloatData"
-#endif
-
-/// btCollisionObject can be used to manage collision detection objects.
-/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
-/// They can be added to the btCollisionWorld.
-ATTRIBUTE_ALIGNED16(class)
-btCollisionObject
-{
-protected:
- btTransform m_worldTransform;
-
- ///m_interpolationWorldTransform is used for CCD and interpolation
- ///it can be either previous or future (predicted) transform
- btTransform m_interpolationWorldTransform;
- //those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities)
- //without destroying the continuous interpolated motion (which uses this interpolation velocities)
- btVector3 m_interpolationLinearVelocity;
- btVector3 m_interpolationAngularVelocity;
-
- btVector3 m_anisotropicFriction;
- int m_hasAnisotropicFriction;
- btScalar m_contactProcessingThreshold;
-
- btBroadphaseProxy* m_broadphaseHandle;
- btCollisionShape* m_collisionShape;
- ///m_extensionPointer is used by some internal low-level Bullet extensions.
- void* m_extensionPointer;
-
- ///m_rootCollisionShape is temporarily used to store the original collision shape
- ///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
- ///If it is NULL, the m_collisionShape is not temporarily replaced.
- btCollisionShape* m_rootCollisionShape;
-
- int m_collisionFlags;
-
- int m_islandTag1;
- int m_companionId;
- int m_worldArrayIndex; // index of object in world's collisionObjects array
-
- mutable int m_activationState1;
- mutable btScalar m_deactivationTime;
-
- btScalar m_friction;
- btScalar m_restitution;
- btScalar m_rollingFriction; //torsional friction orthogonal to contact normal (useful to stop spheres rolling forever)
- btScalar m_spinningFriction; // torsional friction around the contact normal (useful for grasping)
- btScalar m_contactDamping;
- btScalar m_contactStiffness;
-
- ///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
- ///do not assign your own m_internalType unless you write a new dynamics object class.
- int m_internalType;
-
- ///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
-
- void* m_userObjectPointer;
-
- int m_userIndex2;
-
- int m_userIndex;
-
- int m_userIndex3;
-
- ///time of impact calculation
- btScalar m_hitFraction;
-
- ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- btScalar m_ccdSweptSphereRadius;
-
- /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
- btScalar m_ccdMotionThreshold;
-
- /// If some object should have elaborate collision filtering by sub-classes
- int m_checkCollideWith;
-
- btAlignedObjectArray<const btCollisionObject*> m_objectsWithoutCollisionCheck;
-
- ///internal update revision number. It will be increased when the object changes. This allows some subsystems to perform lazy evaluation.
- int m_updateRevision;
-
- btVector3 m_customDebugColorRGB;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- enum CollisionFlags
- {
- CF_DYNAMIC_OBJECT = 0,
- CF_STATIC_OBJECT = 1,
- CF_KINEMATIC_OBJECT = 2,
- CF_NO_CONTACT_RESPONSE = 4,
- CF_CUSTOM_MATERIAL_CALLBACK = 8, //this allows per-triangle material (friction/restitution)
- CF_CHARACTER_OBJECT = 16,
- CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
- CF_DISABLE_SPU_COLLISION_PROCESSING = 64, //disable parallel/SPU processing
- CF_HAS_CONTACT_STIFFNESS_DAMPING = 128,
- CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR = 256,
- CF_HAS_FRICTION_ANCHOR = 512,
- CF_HAS_COLLISION_SOUND_TRIGGER = 1024
- };
-
- enum CollisionObjectTypes
- {
- CO_COLLISION_OBJECT = 1,
- CO_RIGID_BODY = 2,
- ///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
- ///It is useful for collision sensors, explosion objects, character controller etc.
- CO_GHOST_OBJECT = 4,
- CO_SOFT_BODY = 8,
- CO_HF_FLUID = 16,
- CO_USER_TYPE = 32,
- CO_FEATHERSTONE_LINK = 64
- };
-
- enum AnisotropicFrictionFlags
- {
- CF_ANISOTROPIC_FRICTION_DISABLED = 0,
- CF_ANISOTROPIC_FRICTION = 1,
- CF_ANISOTROPIC_ROLLING_FRICTION = 2
- };
-
- SIMD_FORCE_INLINE bool mergesSimulationIslands() const
- {
- ///static objects, kinematic and object without contact response don't merge islands
- return ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE)) == 0);
- }
-
- const btVector3& getAnisotropicFriction() const
- {
- return m_anisotropicFriction;
- }
- void setAnisotropicFriction(const btVector3& anisotropicFriction, int frictionMode = CF_ANISOTROPIC_FRICTION)
- {
- m_anisotropicFriction = anisotropicFriction;
- bool isUnity = (anisotropicFriction[0] != 1.f) || (anisotropicFriction[1] != 1.f) || (anisotropicFriction[2] != 1.f);
- m_hasAnisotropicFriction = isUnity ? frictionMode : 0;
- }
- bool hasAnisotropicFriction(int frictionMode = CF_ANISOTROPIC_FRICTION) const
- {
- return (m_hasAnisotropicFriction & frictionMode) != 0;
- }
-
- ///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
- ///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
- void setContactProcessingThreshold(btScalar contactProcessingThreshold)
- {
- m_contactProcessingThreshold = contactProcessingThreshold;
- }
- btScalar getContactProcessingThreshold() const
- {
- return m_contactProcessingThreshold;
- }
-
- SIMD_FORCE_INLINE bool isStaticObject() const
- {
- return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
- }
-
- SIMD_FORCE_INLINE bool isKinematicObject() const
- {
- return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
- }
-
- SIMD_FORCE_INLINE bool isStaticOrKinematicObject() const
- {
- return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0;
- }
-
- SIMD_FORCE_INLINE bool hasContactResponse() const
- {
- return (m_collisionFlags & CF_NO_CONTACT_RESPONSE) == 0;
- }
-
- btCollisionObject();
-
- virtual ~btCollisionObject();
-
- virtual void setCollisionShape(btCollisionShape * collisionShape)
- {
- m_updateRevision++;
- m_collisionShape = collisionShape;
- m_rootCollisionShape = collisionShape;
- }
-
- SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
- {
- return m_collisionShape;
- }
-
- SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
- {
- return m_collisionShape;
- }
-
- void setIgnoreCollisionCheck(const btCollisionObject* co, bool ignoreCollisionCheck)
- {
- if (ignoreCollisionCheck)
- {
- //We don't check for duplicates. Is it ok to leave that up to the user of this API?
- //int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
- //if (index == m_objectsWithoutCollisionCheck.size())
- //{
- m_objectsWithoutCollisionCheck.push_back(co);
- //}
- }
- else
- {
- m_objectsWithoutCollisionCheck.remove(co);
- }
- m_checkCollideWith = m_objectsWithoutCollisionCheck.size() > 0;
- }
-
- int getNumObjectsWithoutCollision() const
- {
- return m_objectsWithoutCollisionCheck.size();
- }
-
- const btCollisionObject* getObjectWithoutCollision(int index)
- {
- return m_objectsWithoutCollisionCheck[index];
- }
-
- virtual bool checkCollideWithOverride(const btCollisionObject* co) const
- {
- int index = m_objectsWithoutCollisionCheck.findLinearSearch(co);
- if (index < m_objectsWithoutCollisionCheck.size())
- {
- return false;
- }
- return true;
- }
-
- ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions.
- ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
- void* internalGetExtensionPointer() const
- {
- return m_extensionPointer;
- }
- ///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
- ///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
- void internalSetExtensionPointer(void* pointer)
- {
- m_extensionPointer = pointer;
- }
-
- SIMD_FORCE_INLINE int getActivationState() const { return m_activationState1; }
-
- void setActivationState(int newState) const;
-
- void setDeactivationTime(btScalar time)
- {
- m_deactivationTime = time;
- }
- btScalar getDeactivationTime() const
- {
- return m_deactivationTime;
- }
-
- void forceActivationState(int newState) const;
-
- void activate(bool forceActivation = false) const;
-
- SIMD_FORCE_INLINE bool isActive() const
- {
- return ((getActivationState() != FIXED_BASE_MULTI_BODY) && (getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
- }
-
- void setRestitution(btScalar rest)
- {
- m_updateRevision++;
- m_restitution = rest;
- }
- btScalar getRestitution() const
- {
- return m_restitution;
- }
- void setFriction(btScalar frict)
- {
- m_updateRevision++;
- m_friction = frict;
- }
- btScalar getFriction() const
- {
- return m_friction;
- }
-
- void setRollingFriction(btScalar frict)
- {
- m_updateRevision++;
- m_rollingFriction = frict;
- }
- btScalar getRollingFriction() const
- {
- return m_rollingFriction;
- }
- void setSpinningFriction(btScalar frict)
- {
- m_updateRevision++;
- m_spinningFriction = frict;
- }
- btScalar getSpinningFriction() const
- {
- return m_spinningFriction;
- }
- void setContactStiffnessAndDamping(btScalar stiffness, btScalar damping)
- {
- m_updateRevision++;
- m_contactStiffness = stiffness;
- m_contactDamping = damping;
-
- m_collisionFlags |= CF_HAS_CONTACT_STIFFNESS_DAMPING;
-
- //avoid divisions by zero...
- if (m_contactStiffness < SIMD_EPSILON)
- {
- m_contactStiffness = SIMD_EPSILON;
- }
- }
-
- btScalar getContactStiffness() const
- {
- return m_contactStiffness;
- }
-
- btScalar getContactDamping() const
- {
- return m_contactDamping;
- }
-
- ///reserved for Bullet internal usage
- int getInternalType() const
- {
- return m_internalType;
- }
-
- btTransform& getWorldTransform()
- {
- return m_worldTransform;
- }
-
- const btTransform& getWorldTransform() const
- {
- return m_worldTransform;
- }
-
- void setWorldTransform(const btTransform& worldTrans)
- {
- m_updateRevision++;
- m_worldTransform = worldTrans;
- }
-
- SIMD_FORCE_INLINE btBroadphaseProxy* getBroadphaseHandle()
- {
- return m_broadphaseHandle;
- }
-
- SIMD_FORCE_INLINE const btBroadphaseProxy* getBroadphaseHandle() const
- {
- return m_broadphaseHandle;
- }
-
- void setBroadphaseHandle(btBroadphaseProxy * handle)
- {
- m_broadphaseHandle = handle;
- }
-
- const btTransform& getInterpolationWorldTransform() const
- {
- return m_interpolationWorldTransform;
- }
-
- btTransform& getInterpolationWorldTransform()
- {
- return m_interpolationWorldTransform;
- }
-
- void setInterpolationWorldTransform(const btTransform& trans)
- {
- m_updateRevision++;
- m_interpolationWorldTransform = trans;
- }
-
- void setInterpolationLinearVelocity(const btVector3& linvel)
- {
- m_updateRevision++;
- m_interpolationLinearVelocity = linvel;
- }
-
- void setInterpolationAngularVelocity(const btVector3& angvel)
- {
- m_updateRevision++;
- m_interpolationAngularVelocity = angvel;
- }
-
- const btVector3& getInterpolationLinearVelocity() const
- {
- return m_interpolationLinearVelocity;
- }
-
- const btVector3& getInterpolationAngularVelocity() const
- {
- return m_interpolationAngularVelocity;
- }
-
- SIMD_FORCE_INLINE int getIslandTag() const
- {
- return m_islandTag1;
- }
-
- void setIslandTag(int tag)
- {
- m_islandTag1 = tag;
- }
-
- SIMD_FORCE_INLINE int getCompanionId() const
- {
- return m_companionId;
- }
-
- void setCompanionId(int id)
- {
- m_companionId = id;
- }
-
- SIMD_FORCE_INLINE int getWorldArrayIndex() const
- {
- return m_worldArrayIndex;
- }
-
- // only should be called by CollisionWorld
- void setWorldArrayIndex(int ix)
- {
- m_worldArrayIndex = ix;
- }
-
- SIMD_FORCE_INLINE btScalar getHitFraction() const
- {
- return m_hitFraction;
- }
-
- void setHitFraction(btScalar hitFraction)
- {
- m_hitFraction = hitFraction;
- }
-
- SIMD_FORCE_INLINE int getCollisionFlags() const
- {
- return m_collisionFlags;
- }
-
- void setCollisionFlags(int flags)
- {
- m_collisionFlags = flags;
- }
-
- ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- btScalar getCcdSweptSphereRadius() const
- {
- return m_ccdSweptSphereRadius;
- }
-
- ///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
- void setCcdSweptSphereRadius(btScalar radius)
- {
- m_ccdSweptSphereRadius = radius;
- }
-
- btScalar getCcdMotionThreshold() const
- {
- return m_ccdMotionThreshold;
- }
-
- btScalar getCcdSquareMotionThreshold() const
- {
- return m_ccdMotionThreshold * m_ccdMotionThreshold;
- }
-
- /// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
- void setCcdMotionThreshold(btScalar ccdMotionThreshold)
- {
- m_ccdMotionThreshold = ccdMotionThreshold;
- }
-
- ///users can point to their objects, userPointer is not used by Bullet
- void* getUserPointer() const
- {
- return m_userObjectPointer;
- }
-
- int getUserIndex() const
- {
- return m_userIndex;
- }
-
- int getUserIndex2() const
- {
- return m_userIndex2;
- }
-
- int getUserIndex3() const
- {
- return m_userIndex3;
- }
-
- ///users can point to their objects, userPointer is not used by Bullet
- void setUserPointer(void* userPointer)
- {
- m_userObjectPointer = userPointer;
- }
-
- ///users can point to their objects, userPointer is not used by Bullet
- void setUserIndex(int index)
- {
- m_userIndex = index;
- }
-
- void setUserIndex2(int index)
- {
- m_userIndex2 = index;
- }
-
- void setUserIndex3(int index)
- {
- m_userIndex3 = index;
- }
-
- int getUpdateRevisionInternal() const
- {
- return m_updateRevision;
- }
-
- void setCustomDebugColor(const btVector3& colorRGB)
- {
- m_customDebugColorRGB = colorRGB;
- m_collisionFlags |= CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
- }
-
- void removeCustomDebugColor()
- {
- m_collisionFlags &= ~CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR;
- }
-
- bool getCustomDebugColor(btVector3 & colorRGB) const
- {
- bool hasCustomColor = (0 != (m_collisionFlags & CF_HAS_CUSTOM_DEBUG_RENDERING_COLOR));
- if (hasCustomColor)
- {
- colorRGB = m_customDebugColorRGB;
- }
- return hasCustomColor;
- }
-
- inline bool checkCollideWith(const btCollisionObject* co) const
- {
- if (m_checkCollideWith)
- return checkCollideWithOverride(co);
-
- return true;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
- virtual void serializeSingleObject(class btSerializer * serializer) const;
-};
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCollisionObjectDoubleData
-{
- void *m_broadphaseHandle;
- void *m_collisionShape;
- btCollisionShapeData *m_rootCollisionShape;
- char *m_name;
-
- btTransformDoubleData m_worldTransform;
- btTransformDoubleData m_interpolationWorldTransform;
- btVector3DoubleData m_interpolationLinearVelocity;
- btVector3DoubleData m_interpolationAngularVelocity;
- btVector3DoubleData m_anisotropicFriction;
- double m_contactProcessingThreshold;
- double m_deactivationTime;
- double m_friction;
- double m_rollingFriction;
- double m_contactDamping;
- double m_contactStiffness;
- double m_restitution;
- double m_hitFraction;
- double m_ccdSweptSphereRadius;
- double m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- int m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCollisionObjectFloatData
-{
- void *m_broadphaseHandle;
- void *m_collisionShape;
- btCollisionShapeData *m_rootCollisionShape;
- char *m_name;
-
- btTransformFloatData m_worldTransform;
- btTransformFloatData m_interpolationWorldTransform;
- btVector3FloatData m_interpolationLinearVelocity;
- btVector3FloatData m_interpolationAngularVelocity;
- btVector3FloatData m_anisotropicFriction;
- float m_contactProcessingThreshold;
- float m_deactivationTime;
- float m_friction;
- float m_rollingFriction;
- float m_contactDamping;
- float m_contactStiffness;
- float m_restitution;
- float m_hitFraction;
- float m_ccdSweptSphereRadius;
- float m_ccdMotionThreshold;
- int m_hasAnisotropicFriction;
- int m_collisionFlags;
- int m_islandTag1;
- int m_companionId;
- int m_activationState1;
- int m_internalType;
- int m_checkCollideWith;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- int m_uniqueId;
-};
-// clang-format on
-
-SIMD_FORCE_INLINE int btCollisionObject::calculateSerializeBufferSize() const
-{
- return sizeof(btCollisionObjectData);
-}
-
-#endif //BT_COLLISION_OBJECT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
deleted file mode 100644
index 56341b7d29..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef BT_COLLISION_OBJECT_WRAPPER_H
-#define BT_COLLISION_OBJECT_WRAPPER_H
-
-///btCollisionObjectWrapperis an internal data structure.
-///Most users can ignore this and use btCollisionObject and btCollisionShape instead
-class btCollisionShape;
-class btCollisionObject;
-class btTransform;
-#include "LinearMath/btScalar.h" // for SIMD_FORCE_INLINE definition
-
-#define BT_DECLARE_STACK_ONLY_OBJECT \
-private: \
- void* operator new(size_t size); \
- void operator delete(void*);
-
-struct btCollisionObjectWrapper;
-struct btCollisionObjectWrapper
-{
- BT_DECLARE_STACK_ONLY_OBJECT
-
-private:
- btCollisionObjectWrapper(const btCollisionObjectWrapper&); // not implemented. Not allowed.
- btCollisionObjectWrapper* operator=(const btCollisionObjectWrapper&);
-
-public:
- const btCollisionObjectWrapper* m_parent;
- const btCollisionShape* m_shape;
- const btCollisionObject* m_collisionObject;
- const btTransform& m_worldTransform;
- const btTransform* m_preTransform;
- int m_partId;
- int m_index;
-
- btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, int partId, int index)
- : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(NULL), m_partId(partId), m_index(index)
- {
- }
-
- btCollisionObjectWrapper(const btCollisionObjectWrapper* parent, const btCollisionShape* shape, const btCollisionObject* collisionObject, const btTransform& worldTransform, const btTransform& preTransform, int partId, int index)
- : m_parent(parent), m_shape(shape), m_collisionObject(collisionObject), m_worldTransform(worldTransform), m_preTransform(&preTransform), m_partId(partId), m_index(index)
- {
- }
-
- SIMD_FORCE_INLINE const btTransform& getWorldTransform() const { return m_worldTransform; }
- SIMD_FORCE_INLINE const btCollisionObject* getCollisionObject() const { return m_collisionObject; }
- SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const { return m_shape; }
-};
-
-#endif //BT_COLLISION_OBJECT_WRAPPER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
deleted file mode 100644
index f74dcabc54..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
+++ /dev/null
@@ -1,1625 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionWorld.h"
-#include "btCollisionDispatcher.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
-#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" //for raycasting
-#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h" //for raycasting
-#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btSerializer.h"
-#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//#define DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
-
-//#define USE_BRUTEFORCE_RAYBROADPHASE 1
-//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation' or 'updateAabbs' before using a rayTest
-//#define RECALCULATE_AABB_RAYCAST 1
-
-//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
-#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
-
-///for debug drawing
-
-//for debug rendering
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/CollisionShapes/btConeShape.h"
-#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btCylinderShape.h"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
-#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
-#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-
-btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
- : m_dispatcher1(dispatcher),
- m_broadphasePairCache(pairCache),
- m_debugDrawer(0),
- m_forceUpdateAllAabbs(true)
-{
-}
-
-btCollisionWorld::~btCollisionWorld()
-{
- //clean up remaining objects
- int i;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_collisionObjects[i];
-
- btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
- if (bp)
- {
- //
- // only clear the cached algorithms
- //
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
- getBroadphase()->destroyProxy(bp, m_dispatcher1);
- collisionObject->setBroadphaseHandle(0);
- }
- }
-}
-
-void btCollisionWorld::refreshBroadphaseProxy(btCollisionObject* collisionObject)
-{
- if (collisionObject->getBroadphaseHandle())
- {
- int collisionFilterGroup = collisionObject->getBroadphaseHandle()->m_collisionFilterGroup;
- int collisionFilterMask = collisionObject->getBroadphaseHandle()->m_collisionFilterMask;
-
- getBroadphase()->destroyProxy(collisionObject->getBroadphaseHandle(), getDispatcher());
-
- //calculate new AABB
- btTransform trans = collisionObject->getWorldTransform();
-
- btVector3 minAabb;
- btVector3 maxAabb;
- collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
-
- int type = collisionObject->getCollisionShape()->getShapeType();
- collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
- minAabb,
- maxAabb,
- type,
- collisionObject,
- collisionFilterGroup,
- collisionFilterMask,
- m_dispatcher1));
- }
-}
-
-void btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
-{
- btAssert(collisionObject);
-
- //check that the object isn't already added
- btAssert(m_collisionObjects.findLinearSearch(collisionObject) == m_collisionObjects.size());
- btAssert(collisionObject->getWorldArrayIndex() == -1); // do not add the same object to more than one collision world
-
- collisionObject->setWorldArrayIndex(m_collisionObjects.size());
- m_collisionObjects.push_back(collisionObject);
-
- //calculate new AABB
- btTransform trans = collisionObject->getWorldTransform();
-
- btVector3 minAabb;
- btVector3 maxAabb;
- collisionObject->getCollisionShape()->getAabb(trans, minAabb, maxAabb);
-
- int type = collisionObject->getCollisionShape()->getShapeType();
- collisionObject->setBroadphaseHandle(getBroadphase()->createProxy(
- minAabb,
- maxAabb,
- type,
- collisionObject,
- collisionFilterGroup,
- collisionFilterMask,
- m_dispatcher1));
-}
-
-void btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
-{
- btVector3 minAabb, maxAabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
- //need to increase the aabb for contact thresholds
- btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
- minAabb -= contactThreshold;
- maxAabb += contactThreshold;
-
- if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
- {
- btVector3 minAabb2, maxAabb2;
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
- minAabb2 -= contactThreshold;
- maxAabb2 += contactThreshold;
- minAabb.setMin(minAabb2);
- maxAabb.setMax(maxAabb2);
- }
-
- btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
-
- //moving objects should be moderately sized, probably something wrong if not
- if (colObj->isStaticObject() || ((maxAabb - minAabb).length2() < btScalar(1e12)))
- {
- bp->setAabb(colObj->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
- }
- else
- {
- //something went wrong, investigate
- //this assert is unwanted in 3D modelers (danger of loosing work)
- colObj->setActivationState(DISABLE_SIMULATION);
-
- static bool reportMe = true;
- if (reportMe && m_debugDrawer)
- {
- reportMe = false;
- m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
- m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs@continuousphysics.com\n");
- m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
- m_debugDrawer->reportErrorWarning("Thanks.\n");
- }
- }
-}
-
-void btCollisionWorld::updateAabbs()
-{
- BT_PROFILE("updateAabbs");
-
- btTransform predictedTrans;
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btAssert(colObj->getWorldArrayIndex() == i);
-
- //only update aabb of active objects
- if (m_forceUpdateAllAabbs || colObj->isActive())
- {
- updateSingleAabb(colObj);
- }
- }
-}
-
-void btCollisionWorld::computeOverlappingPairs()
-{
- BT_PROFILE("calculateOverlappingPairs");
- m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
-}
-
-void btCollisionWorld::performDiscreteCollisionDetection()
-{
- BT_PROFILE("performDiscreteCollisionDetection");
-
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
-
- updateAabbs();
-
- computeOverlappingPairs();
-
- btDispatcher* dispatcher = getDispatcher();
- {
- BT_PROFILE("dispatchAllCollisionPairs");
- if (dispatcher)
- dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(), dispatchInfo, m_dispatcher1);
- }
-}
-
-void btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- //bool removeFromBroadphase = false;
-
- {
- btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
- if (bp)
- {
- //
- // only clear the cached algorithms
- //
- getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp, m_dispatcher1);
- getBroadphase()->destroyProxy(bp, m_dispatcher1);
- collisionObject->setBroadphaseHandle(0);
- }
- }
-
- int iObj = collisionObject->getWorldArrayIndex();
- // btAssert(iObj >= 0 && iObj < m_collisionObjects.size()); // trying to remove an object that was never added or already removed previously?
- if (iObj >= 0 && iObj < m_collisionObjects.size())
- {
- btAssert(collisionObject == m_collisionObjects[iObj]);
- m_collisionObjects.swap(iObj, m_collisionObjects.size() - 1);
- m_collisionObjects.pop_back();
- if (iObj < m_collisionObjects.size())
- {
- m_collisionObjects[iObj]->setWorldArrayIndex(iObj);
- }
- }
- else
- {
- // slow linear search
- //swapremove
- m_collisionObjects.remove(collisionObject);
- }
- collisionObject->setWorldArrayIndex(-1);
-}
-
-void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
-{
- btCollisionObjectWrapper colObWrap(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
- btCollisionWorld::rayTestSingleInternal(rayFromTrans, rayToTrans, &colObWrap, resultCallback);
-}
-
-void btCollisionWorld::rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- const btCollisionObjectWrapper* collisionObjectWrap,
- RayResultCallback& resultCallback)
-{
- btSphereShape pointShape(btScalar(0.0));
- pointShape.setMargin(0.f);
- const btConvexShape* castShape = &pointShape;
- const btCollisionShape* collisionShape = collisionObjectWrap->getCollisionShape();
- const btTransform& colObjWorldTransform = collisionObjectWrap->getWorldTransform();
-
- if (collisionShape->isConvex())
- {
- // BT_PROFILE("rayTestConvex");
- btConvexCast::CastResult castResult;
- castResult.m_fraction = resultCallback.m_closestHitFraction;
-
- btConvexShape* convexShape = (btConvexShape*)collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast subSimplexConvexCaster(castShape, convexShape, &simplexSolver);
-
- btGjkConvexCast gjkConvexCaster(castShape, convexShape, &simplexSolver);
-
- //btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
-
- btConvexCast* convexCasterPtr = 0;
- //use kF_UseSubSimplexConvexCastRaytest by default
- if (resultCallback.m_flags & btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest)
- convexCasterPtr = &gjkConvexCaster;
- else
- convexCasterPtr = &subSimplexConvexCaster;
-
- btConvexCast& convexCaster = *convexCasterPtr;
-
- if (convexCaster.calcTimeOfImpact(rayFromTrans, rayToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- //todo: figure out what this is about. When is rayFromTest.getBasis() not identity?
-#ifdef USE_SUBSIMPLEX_CONVEX_CAST
- //rotate normal into worldspace
- castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
-#endif //USE_SUBSIMPLEX_CONVEX_CAST
-
- castResult.m_normal.normalize();
- btCollisionWorld::LocalRayResult localRayResult(
- collisionObjectWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_fraction);
-
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- if (collisionShape->isConcave())
- {
- //ConvexCast::CastResult
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
- {
- btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- const btConcaveShape* m_triangleMesh;
-
- btTransform m_colObjWorldTransform;
-
- BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, const btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
- btTriangleRaycastCallback(from, to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
- {
- }
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
-
- btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
-
- btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
-
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
- }
- };
-
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
-
- // BT_PROFILE("rayTestConcave");
- if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- ///optimized version for btBvhTriangleMeshShape
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- triangleMesh->performRaycast(&rcb, rayFromLocal, rayToLocal);
- }
- else if (collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- ///optimized version for btScaledBvhTriangleMeshShape
- btScaledBvhTriangleMeshShape* scaledTriangleMesh = (btScaledBvhTriangleMeshShape*)collisionShape;
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)scaledTriangleMesh->getChildShape();
-
- //scale the ray positions
- btVector3 scale = scaledTriangleMesh->getLocalScaling();
- btVector3 rayFromLocalScaled = rayFromLocal / scale;
- btVector3 rayToLocalScaled = rayToLocal / scale;
-
- //perform raycast in the underlying btBvhTriangleMeshShape
- BridgeTriangleRaycastCallback rcb(rayFromLocalScaled, rayToLocalScaled, &resultCallback, collisionObjectWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- triangleMesh->performRaycast(&rcb, rayFromLocalScaled, rayToLocalScaled);
- }
- else if (((resultCallback.m_flags&btTriangleRaycastCallback::kF_DisableHeightfieldAccelerator)==0)
- && collisionShape->getShapeType() == TERRAIN_SHAPE_PROXYTYPE
- )
- {
- ///optimized version for btHeightfieldTerrainShape
- btHeightfieldTerrainShape* heightField = (btHeightfieldTerrainShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), heightField, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
- heightField->performRaycast(&rcb, rayFromLocal, rayToLocal);
- }
- else
- {
- //generic (slower) case
- btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
-
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
-
- btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
- btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
-
- //ConvexCast::CastResult
-
- struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
- {
- btCollisionWorld::RayResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
-
- btTransform m_colObjWorldTransform;
-
- BridgeTriangleRaycastCallback(const btVector3& from, const btVector3& to,
- btCollisionWorld::RayResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& colObjWorldTransform) : //@BP Mod
- btTriangleRaycastCallback(from, to, resultCallback->m_flags),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh),
- m_colObjWorldTransform(colObjWorldTransform)
- {
- }
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
-
- btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
-
- btCollisionWorld::LocalRayResult rayResult(m_collisionObject,
- &shapeInfo,
- hitNormalWorld,
- hitFraction);
-
- bool normalInWorldSpace = true;
- return m_resultCallback->addSingleResult(rayResult, normalInWorldSpace);
- }
- };
-
- BridgeTriangleRaycastCallback rcb(rayFromLocal, rayToLocal, &resultCallback, collisionObjectWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
- rcb.m_hitFraction = resultCallback.m_closestHitFraction;
-
- btVector3 rayAabbMinLocal = rayFromLocal;
- rayAabbMinLocal.setMin(rayToLocal);
- btVector3 rayAabbMaxLocal = rayFromLocal;
- rayAabbMaxLocal.setMax(rayToLocal);
-
- concaveShape->processAllTriangles(&rcb, rayAabbMinLocal, rayAabbMaxLocal);
- }
- }
- else
- {
- // BT_PROFILE("rayTestCompound");
- if (collisionShape->isCompound())
- {
- struct LocalInfoAdder2 : public RayResultCallback
- {
- RayResultCallback* m_userCallback;
- int m_i;
-
- LocalInfoAdder2(int i, RayResultCallback* user)
- : m_userCallback(user), m_i(i)
- {
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- m_flags = m_userCallback->m_flags;
- }
- virtual bool needsCollision(btBroadphaseProxy* p) const
- {
- return m_userCallback->needsCollision(p);
- }
-
- virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& r, bool b)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = -1;
- shapeInfo.m_triangleIndex = m_i;
- if (r.m_localShapeInfo == NULL)
- r.m_localShapeInfo = &shapeInfo;
-
- const btScalar result = m_userCallback->addSingleResult(r, b);
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- return result;
- }
- };
-
- struct RayTester : btDbvt::ICollide
- {
- const btCollisionObject* m_collisionObject;
- const btCompoundShape* m_compoundShape;
- const btTransform& m_colObjWorldTransform;
- const btTransform& m_rayFromTrans;
- const btTransform& m_rayToTrans;
- RayResultCallback& m_resultCallback;
-
- RayTester(const btCollisionObject* collisionObject,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- const btTransform& rayFromTrans,
- const btTransform& rayToTrans,
- RayResultCallback& resultCallback) : m_collisionObject(collisionObject),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_rayFromTrans(rayFromTrans),
- m_rayToTrans(rayToTrans),
- m_resultCallback(resultCallback)
- {
- }
-
- void ProcessLeaf(int i)
- {
- const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(i);
- const btTransform& childTrans = m_compoundShape->getChildTransform(i);
- btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
-
- btCollisionObjectWrapper tmpOb(0, childCollisionShape, m_collisionObject, childWorldTrans, -1, i);
- // replace collision shape so that callback can determine the triangle
-
- LocalInfoAdder2 my_cb(i, &m_resultCallback);
-
- rayTestSingleInternal(
- m_rayFromTrans,
- m_rayToTrans,
- &tmpOb,
- my_cb);
- }
-
- void Process(const btDbvtNode* leaf)
- {
- ProcessLeaf(leaf->dataAsInt);
- }
- };
-
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
- const btDbvt* dbvt = compoundShape->getDynamicAabbTree();
-
- RayTester rayCB(
- collisionObjectWrap->getCollisionObject(),
- compoundShape,
- colObjWorldTransform,
- rayFromTrans,
- rayToTrans,
- resultCallback);
-#ifndef DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
- if (dbvt)
- {
- btVector3 localRayFrom = colObjWorldTransform.inverseTimes(rayFromTrans).getOrigin();
- btVector3 localRayTo = colObjWorldTransform.inverseTimes(rayToTrans).getOrigin();
- btDbvt::rayTest(dbvt->m_root, localRayFrom, localRayTo, rayCB);
- }
- else
-#endif //DISABLE_DBVT_COMPOUNDSHAPE_RAYCAST_ACCELERATION
- {
- for (int i = 0, n = compoundShape->getNumChildShapes(); i < n; ++i)
- {
- rayCB.ProcessLeaf(i);
- }
- }
- }
- }
- }
-}
-
-void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
-{
- btCollisionObjectWrapper tmpOb(0, collisionShape, collisionObject, colObjWorldTransform, -1, -1);
- btCollisionWorld::objectQuerySingleInternal(castShape, convexFromTrans, convexToTrans, &tmpOb, resultCallback, allowedPenetration);
-}
-
-void btCollisionWorld::objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
- const btCollisionObjectWrapper* colObjWrap,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration)
-{
- const btCollisionShape* collisionShape = colObjWrap->getCollisionShape();
- const btTransform& colObjWorldTransform = colObjWrap->getWorldTransform();
-
- if (collisionShape->isConvex())
- {
- //BT_PROFILE("convexSweepConvex");
- btConvexCast::CastResult castResult;
- castResult.m_allowedPenetration = allowedPenetration;
- castResult.m_fraction = resultCallback.m_closestHitFraction; //btScalar(1.);//??
-
- btConvexShape* convexShape = (btConvexShape*)collisionShape;
- btVoronoiSimplexSolver simplexSolver;
- btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
-
- btContinuousConvexCollision convexCaster1(castShape, convexShape, &simplexSolver, &gjkEpaPenetrationSolver);
- //btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
- //btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
-
- btConvexCast* castPtr = &convexCaster1;
-
- if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult(
- colObjWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction);
-
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- if (collisionShape->isConcave())
- {
- if (collisionShape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- //BT_PROFILE("convexSweepbtBvhTriangleMesh");
- btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
- btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
- // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
- btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
-
- //ConvexCast::CastResult
- struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
- {
- btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btTriangleMeshShape* m_triangleMesh;
-
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btTriangleMeshShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
- {
- }
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- if (hitFraction <= m_resultCallback->m_closestHitFraction)
- {
- btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
-
- bool normalInWorldSpace = true;
-
- return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
- }
- return hitFraction;
- }
- };
-
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), triangleMesh, colObjWorldTransform);
- tccb.m_hitFraction = resultCallback.m_closestHitFraction;
- tccb.m_allowedPenetration = allowedPenetration;
- btVector3 boxMinLocal, boxMaxLocal;
- castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
- triangleMesh->performConvexcast(&tccb, convexFromLocal, convexToLocal, boxMinLocal, boxMaxLocal);
- }
- else
- {
- if (collisionShape->getShapeType() == STATIC_PLANE_PROXYTYPE)
- {
- btConvexCast::CastResult castResult;
- castResult.m_allowedPenetration = allowedPenetration;
- castResult.m_fraction = resultCallback.m_closestHitFraction;
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*)collisionShape;
- btContinuousConvexCollision convexCaster1(castShape, planeShape);
- btConvexCast* castPtr = &convexCaster1;
-
- if (castPtr->calcTimeOfImpact(convexFromTrans, convexToTrans, colObjWorldTransform, colObjWorldTransform, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < resultCallback.m_closestHitFraction)
- {
- castResult.m_normal.normalize();
- btCollisionWorld::LocalConvexResult localConvexResult(
- colObjWrap->getCollisionObject(),
- 0,
- castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction);
-
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- //BT_PROFILE("convexSweepConcave");
- btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
- btTransform worldTocollisionObject = colObjWorldTransform.inverse();
- btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
- btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
- // rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
- btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
-
- //ConvexCast::CastResult
- struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
- {
- btCollisionWorld::ConvexResultCallback* m_resultCallback;
- const btCollisionObject* m_collisionObject;
- btConcaveShape* m_triangleMesh;
-
- BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from, const btTransform& to,
- btCollisionWorld::ConvexResultCallback* resultCallback, const btCollisionObject* collisionObject, btConcaveShape* triangleMesh, const btTransform& triangleToWorld) : btTriangleConvexcastCallback(castShape, from, to, triangleToWorld, triangleMesh->getMargin()),
- m_resultCallback(resultCallback),
- m_collisionObject(collisionObject),
- m_triangleMesh(triangleMesh)
- {
- }
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = partId;
- shapeInfo.m_triangleIndex = triangleIndex;
- if (hitFraction <= m_resultCallback->m_closestHitFraction)
- {
- btCollisionWorld::LocalConvexResult convexResult(m_collisionObject,
- &shapeInfo,
- hitNormalLocal,
- hitPointLocal,
- hitFraction);
-
- bool normalInWorldSpace = true;
-
- return m_resultCallback->addSingleResult(convexResult, normalInWorldSpace);
- }
- return hitFraction;
- }
- };
-
- BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans, convexToTrans, &resultCallback, colObjWrap->getCollisionObject(), concaveShape, colObjWorldTransform);
- tccb.m_hitFraction = resultCallback.m_closestHitFraction;
- tccb.m_allowedPenetration = allowedPenetration;
- btVector3 boxMinLocal, boxMaxLocal;
- castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
-
- btVector3 rayAabbMinLocal = convexFromLocal;
- rayAabbMinLocal.setMin(convexToLocal);
- btVector3 rayAabbMaxLocal = convexFromLocal;
- rayAabbMaxLocal.setMax(convexToLocal);
- rayAabbMinLocal += boxMinLocal;
- rayAabbMaxLocal += boxMaxLocal;
- concaveShape->processAllTriangles(&tccb, rayAabbMinLocal, rayAabbMaxLocal);
- }
- }
- }
- else
- {
- if (collisionShape->isCompound())
- {
- struct btCompoundLeafCallback : btDbvt::ICollide
- {
- btCompoundLeafCallback(
- const btCollisionObjectWrapper* colObjWrap,
- const btConvexShape* castShape,
- const btTransform& convexFromTrans,
- const btTransform& convexToTrans,
- btScalar allowedPenetration,
- const btCompoundShape* compoundShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback)
- : m_colObjWrap(colObjWrap),
- m_castShape(castShape),
- m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_allowedPenetration(allowedPenetration),
- m_compoundShape(compoundShape),
- m_colObjWorldTransform(colObjWorldTransform),
- m_resultCallback(resultCallback)
- {
- }
-
- const btCollisionObjectWrapper* m_colObjWrap;
- const btConvexShape* m_castShape;
- const btTransform& m_convexFromTrans;
- const btTransform& m_convexToTrans;
- btScalar m_allowedPenetration;
- const btCompoundShape* m_compoundShape;
- const btTransform& m_colObjWorldTransform;
- ConvexResultCallback& m_resultCallback;
-
- public:
- void ProcessChild(int index, const btTransform& childTrans, const btCollisionShape* childCollisionShape)
- {
- btTransform childWorldTrans = m_colObjWorldTransform * childTrans;
-
- struct LocalInfoAdder : public ConvexResultCallback
- {
- ConvexResultCallback* m_userCallback;
- int m_i;
-
- LocalInfoAdder(int i, ConvexResultCallback* user)
- : m_userCallback(user), m_i(i)
- {
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- }
- virtual bool needsCollision(btBroadphaseProxy* p) const
- {
- return m_userCallback->needsCollision(p);
- }
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& r, bool b)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = -1;
- shapeInfo.m_triangleIndex = m_i;
- if (r.m_localShapeInfo == NULL)
- r.m_localShapeInfo = &shapeInfo;
- const btScalar result = m_userCallback->addSingleResult(r, b);
- m_closestHitFraction = m_userCallback->m_closestHitFraction;
- return result;
- }
- };
-
- LocalInfoAdder my_cb(index, &m_resultCallback);
-
- btCollisionObjectWrapper tmpObj(m_colObjWrap, childCollisionShape, m_colObjWrap->getCollisionObject(), childWorldTrans, -1, index);
-
- objectQuerySingleInternal(m_castShape, m_convexFromTrans, m_convexToTrans, &tmpObj, my_cb, m_allowedPenetration);
- }
-
- void Process(const btDbvtNode* leaf)
- {
- // Processing leaf node
- int index = leaf->dataAsInt;
-
- btTransform childTrans = m_compoundShape->getChildTransform(index);
- const btCollisionShape* childCollisionShape = m_compoundShape->getChildShape(index);
-
- ProcessChild(index, childTrans, childCollisionShape);
- }
- };
-
- BT_PROFILE("convexSweepCompound");
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
-
- btVector3 fromLocalAabbMin, fromLocalAabbMax;
- btVector3 toLocalAabbMin, toLocalAabbMax;
-
- castShape->getAabb(colObjWorldTransform.inverse() * convexFromTrans, fromLocalAabbMin, fromLocalAabbMax);
- castShape->getAabb(colObjWorldTransform.inverse() * convexToTrans, toLocalAabbMin, toLocalAabbMax);
-
- fromLocalAabbMin.setMin(toLocalAabbMin);
- fromLocalAabbMax.setMax(toLocalAabbMax);
-
- btCompoundLeafCallback callback(colObjWrap, castShape, convexFromTrans, convexToTrans,
- allowedPenetration, compoundShape, colObjWorldTransform, resultCallback);
-
- const btDbvt* tree = compoundShape->getDynamicAabbTree();
- if (tree)
- {
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(fromLocalAabbMin, fromLocalAabbMax);
- tree->collideTV(tree->m_root, bounds, callback);
- }
- else
- {
- int i;
- for (i = 0; i < compoundShape->getNumChildShapes(); i++)
- {
- const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
- btTransform childTrans = compoundShape->getChildTransform(i);
- callback.ProcessChild(i, childTrans, childCollisionShape);
- }
- }
- }
- }
- }
-}
-
-struct btSingleRayCallback : public btBroadphaseRayCallback
-{
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btCollisionWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btCollisionWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- m_rayFromTrans.setIdentity();
- m_rayFromTrans.setOrigin(m_rayFromWorld);
- m_rayToTrans.setIdentity();
- m_rayToTrans.setOrigin(m_rayToWorld);
-
- btVector3 rayDir = (rayToWorld - rayFromWorld);
-
- rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
-
- m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further ray tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
-
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
-#if 0
-#ifdef RECALCULATE_AABB
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
-#else
- //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
- const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
- const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
-#endif
-#endif
- //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
- //culling already done by broadphase
- //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
- {
- m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
- }
- }
- return true;
- }
-};
-
-void btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
-{
- //BT_PROFILE("rayTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- btSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
-
-#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
-#else
- for (int i = 0; i < this->getNumCollisionObjects(); i++)
- {
- rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-}
-
-struct btSingleSweepCallback : public btBroadphaseRayCallback
-{
- btTransform m_convexFromTrans;
- btTransform m_convexToTrans;
- btVector3 m_hitNormal;
- const btCollisionWorld* m_world;
- btCollisionWorld::ConvexResultCallback& m_resultCallback;
- btScalar m_allowedCcdPenetration;
- const btConvexShape* m_castShape;
-
- btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans, const btCollisionWorld* world, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedPenetration)
- : m_convexFromTrans(convexFromTrans),
- m_convexToTrans(convexToTrans),
- m_world(world),
- m_resultCallback(resultCallback),
- m_allowedCcdPenetration(allowedPenetration),
- m_castShape(castShape)
- {
- btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin() - m_convexFromTrans.getOrigin());
- btVector3 rayDir = unnormalizedRayDir.fuzzyZero() ? btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0)) : unnormalizedRayDir.normalized();
- ///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
-
- m_lambda_max = rayDir.dot(unnormalizedRayDir);
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further convex sweep tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
-
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- m_world->objectQuerySingle(m_castShape, m_convexFromTrans, m_convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback,
- m_allowedCcdPenetration);
- }
-
- return true;
- }
-};
-
-void btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
-{
- BT_PROFILE("convexSweepTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- /// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
-
- btTransform convexFromTrans, convexToTrans;
- convexFromTrans = convexFromWorld;
- convexToTrans = convexToWorld;
- btVector3 castShapeAabbMin, castShapeAabbMax;
- /* Compute AABB that encompasses angular movement */
- {
- btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0f, linVel, angVel);
- btVector3 zeroLinVel;
- zeroLinVel.setValue(0, 0, 0);
- btTransform R;
- R.setIdentity();
- R.setRotation(convexFromTrans.getRotation());
- castShape->calculateTemporalAabb(R, zeroLinVel, angVel, 1.0f, castShapeAabbMin, castShapeAabbMax);
- }
-
-#ifndef USE_BRUTEFORCE_RAYBROADPHASE
-
- btSingleSweepCallback convexCB(castShape, convexFromWorld, convexToWorld, this, resultCallback, allowedCcdPenetration);
-
- m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(), convexToTrans.getOrigin(), convexCB, castShapeAabbMin, castShapeAabbMax);
-
-#else
- /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
- // do a ray-shape query using convexCaster (CCD)
- int i;
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_collisionObjects[i];
- //only perform raycast if filterMask matches
- if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
- AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
- btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
- btVector3 hitNormal;
- if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
- {
- objectQuerySingle(castShape, convexFromTrans, convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- allowedCcdPenetration);
- }
- }
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-}
-
-struct btBridgedManifoldResult : public btManifoldResult
-{
- btCollisionWorld::ContactResultCallback& m_resultCallback;
-
- btBridgedManifoldResult(const btCollisionObjectWrapper* obj0Wrap, const btCollisionObjectWrapper* obj1Wrap, btCollisionWorld::ContactResultCallback& resultCallback)
- : btManifoldResult(obj0Wrap, obj1Wrap),
- m_resultCallback(resultCallback)
- {
- }
-
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
- btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
- btVector3 localA;
- btVector3 localB;
- if (isSwapped)
- {
- localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
- else
- {
- localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
-
- btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
- newPt.m_positionWorldOnA = pointA;
- newPt.m_positionWorldOnB = pointInWorld;
-
- //BP mod, store contact triangles.
- if (isSwapped)
- {
- newPt.m_partId0 = m_partId1;
- newPt.m_partId1 = m_partId0;
- newPt.m_index0 = m_index1;
- newPt.m_index1 = m_index0;
- }
- else
- {
- newPt.m_partId0 = m_partId0;
- newPt.m_partId1 = m_partId1;
- newPt.m_index0 = m_index0;
- newPt.m_index1 = m_index1;
- }
-
- //experimental feature info, for per-triangle material etc.
- const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
- const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
- m_resultCallback.addSingleResult(newPt, obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
- }
-};
-
-struct btSingleContactCallback : public btBroadphaseAabbCallback
-{
- btCollisionObject* m_collisionObject;
- btCollisionWorld* m_world;
- btCollisionWorld::ContactResultCallback& m_resultCallback;
-
- btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world, btCollisionWorld::ContactResultCallback& resultCallback)
- : m_collisionObject(collisionObject),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
- if (collisionObject == m_collisionObject)
- return true;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- btCollisionObjectWrapper ob0(0, m_collisionObject->getCollisionShape(), m_collisionObject, m_collisionObject->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper ob1(0, collisionObject->getCollisionShape(), collisionObject, collisionObject->getWorldTransform(), -1, -1);
-
- btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(&ob0, &ob1, 0, BT_CLOSEST_POINT_ALGORITHMS);
- if (algorithm)
- {
- btBridgedManifoldResult contactPointResult(&ob0, &ob1, m_resultCallback);
- //discrete collision detection query
-
- algorithm->processCollision(&ob0, &ob1, m_world->getDispatchInfo(), &contactPointResult);
-
- algorithm->~btCollisionAlgorithm();
- m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
- }
- }
- return true;
- }
-};
-
-///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
-///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
-void btCollisionWorld::contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback)
-{
- btVector3 aabbMin, aabbMax;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), aabbMin, aabbMax);
- btSingleContactCallback contactCB(colObj, this, resultCallback);
-
- m_broadphasePairCache->aabbTest(aabbMin, aabbMax, contactCB);
-}
-
-///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
-///it reports one or more contact points (including the one with deepest penetration)
-void btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
-{
- btCollisionObjectWrapper obA(0, colObjA->getCollisionShape(), colObjA, colObjA->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper obB(0, colObjB->getCollisionShape(), colObjB, colObjB->getWorldTransform(), -1, -1);
-
- btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(&obA, &obB, 0, BT_CLOSEST_POINT_ALGORITHMS);
- if (algorithm)
- {
- btBridgedManifoldResult contactPointResult(&obA, &obB, resultCallback);
- contactPointResult.m_closestPointDistanceThreshold = resultCallback.m_closestDistanceThreshold;
- //discrete collision detection query
- algorithm->processCollision(&obA, &obB, getDispatchInfo(), &contactPointResult);
-
- algorithm->~btCollisionAlgorithm();
- getDispatcher()->freeCollisionAlgorithm(algorithm);
- }
-}
-
-class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
-{
- btIDebugDraw* m_debugDrawer;
- btVector3 m_color;
- btTransform m_worldTrans;
-
-public:
- DebugDrawcallback(btIDebugDraw* debugDrawer, const btTransform& worldTrans, const btVector3& color) : m_debugDrawer(debugDrawer),
- m_color(color),
- m_worldTrans(worldTrans)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- processTriangle(triangle, partId, triangleIndex);
- }
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
-
- btVector3 wv0, wv1, wv2;
- wv0 = m_worldTrans * triangle[0];
- wv1 = m_worldTrans * triangle[1];
- wv2 = m_worldTrans * triangle[2];
- btVector3 center = (wv0 + wv1 + wv2) * btScalar(1. / 3.);
-
- if (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
- {
- btVector3 normal = (wv1 - wv0).cross(wv2 - wv0);
- normal.normalize();
- btVector3 normalColor(1, 1, 0);
- m_debugDrawer->drawLine(center, center + normal, normalColor);
- }
- m_debugDrawer->drawTriangle(wv0, wv1, wv2, m_color, 1.0);
- }
-};
-
-void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
-{
- // Draw a small simplex at the center of the object
- if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawFrames)
- {
- getDebugDrawer()->drawTransform(worldTransform, .1);
- }
-
- if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
- {
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
- for (int i = compoundShape->getNumChildShapes() - 1; i >= 0; i--)
- {
- btTransform childTrans = compoundShape->getChildTransform(i);
- const btCollisionShape* colShape = compoundShape->getChildShape(i);
- debugDrawObject(worldTransform * childTrans, colShape, color);
- }
- }
- else
- {
- switch (shape->getShapeType())
- {
- case BOX_SHAPE_PROXYTYPE:
- {
- const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
- btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
- getDebugDrawer()->drawBox(-halfExtents, halfExtents, worldTransform, color);
- break;
- }
-
- case SPHERE_SHAPE_PROXYTYPE:
- {
- const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
- btScalar radius = sphereShape->getMargin(); //radius doesn't include the margin, so draw with margin
-
- getDebugDrawer()->drawSphere(radius, worldTransform, color);
- break;
- }
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- {
- const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
-
- btTransform childTransform;
- childTransform.setIdentity();
-
- for (int i = multiSphereShape->getSphereCount() - 1; i >= 0; i--)
- {
- childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
- getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform * childTransform, color);
- }
-
- break;
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
-
- btScalar radius = capsuleShape->getRadius();
- btScalar halfHeight = capsuleShape->getHalfHeight();
-
- int upAxis = capsuleShape->getUpAxis();
- getDebugDrawer()->drawCapsule(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
- btScalar radius = coneShape->getRadius(); //+coneShape->getMargin();
- btScalar height = coneShape->getHeight(); //+coneShape->getMargin();
-
- int upAxis = coneShape->getConeUpIndex();
- getDebugDrawer()->drawCone(radius, height, upAxis, worldTransform, color);
- break;
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
- int upAxis = cylinder->getUpAxis();
- btScalar radius = cylinder->getRadius();
- btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
- getDebugDrawer()->drawCylinder(radius, halfHeight, upAxis, worldTransform, color);
- break;
- }
-
- case STATIC_PLANE_PROXYTYPE:
- {
- const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
- btScalar planeConst = staticPlaneShape->getPlaneConstant();
- const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
- getDebugDrawer()->drawPlane(planeNormal, planeConst, worldTransform, color);
- break;
- }
- default:
- {
- /// for polyhedral shapes
- if (shape->isPolyhedral())
- {
- btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*)shape;
-
- int i;
- if (polyshape->getConvexPolyhedron())
- {
- const btConvexPolyhedron* poly = polyshape->getConvexPolyhedron();
- for (i = 0; i < poly->m_faces.size(); i++)
- {
- btVector3 centroid(0, 0, 0);
- int numVerts = poly->m_faces[i].m_indices.size();
- if (numVerts)
- {
- int lastV = poly->m_faces[i].m_indices[numVerts - 1];
- for (int v = 0; v < poly->m_faces[i].m_indices.size(); v++)
- {
- int curVert = poly->m_faces[i].m_indices[v];
- centroid += poly->m_vertices[curVert];
- getDebugDrawer()->drawLine(worldTransform * poly->m_vertices[lastV], worldTransform * poly->m_vertices[curVert], color);
- lastV = curVert;
- }
- }
- centroid *= btScalar(1.f) / btScalar(numVerts);
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawNormals)
- {
- btVector3 normalColor(1, 1, 0);
- btVector3 faceNormal(poly->m_faces[i].m_plane[0], poly->m_faces[i].m_plane[1], poly->m_faces[i].m_plane[2]);
- getDebugDrawer()->drawLine(worldTransform * centroid, worldTransform * (centroid + faceNormal), normalColor);
- }
- }
- }
- else
- {
- for (i = 0; i < polyshape->getNumEdges(); i++)
- {
- btVector3 a, b;
- polyshape->getEdge(i, a, b);
- btVector3 wa = worldTransform * a;
- btVector3 wb = worldTransform * b;
- getDebugDrawer()->drawLine(wa, wb, color);
- }
- }
- }
-
- if (shape->isConcave())
- {
- btConcaveShape* concaveMesh = (btConcaveShape*)shape;
-
- ///@todo pass camera, for some culling? no -> we are not a graphics lib
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
-
- DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
- concaveMesh->processAllTriangles(&drawCallback, aabbMin, aabbMax);
- }
-
- if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
- {
- btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*)shape;
- //todo: pass camera for some culling
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- //DebugDrawcallback drawCallback;
- DebugDrawcallback drawCallback(getDebugDrawer(), worldTransform, color);
- convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback, aabbMin, aabbMax);
- }
- }
- }
- }
-}
-
-void btCollisionWorld::debugDrawWorld()
-{
- if (getDebugDrawer())
- {
- getDebugDrawer()->clearLines();
-
- btIDebugDraw::DefaultColors defaultColors = getDebugDrawer()->getDefaultColors();
-
- if (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
- {
- if (getDispatcher())
- {
- int numManifolds = getDispatcher()->getNumManifolds();
-
- for (int i = 0; i < numManifolds; i++)
- {
- btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
- //btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
- //btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
-
- int numContacts = contactManifold->getNumContacts();
- for (int j = 0; j < numContacts; j++)
- {
- btManifoldPoint& cp = contactManifold->getContactPoint(j);
- getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB, cp.m_normalWorldOnB, cp.getDistance(), cp.getLifeTime(), defaultColors.m_contactPoint);
- }
- }
- }
- }
-
- if ((getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb)))
- {
- int i;
-
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT) == 0)
- {
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
- {
- btVector3 color(btScalar(0.4), btScalar(0.4), btScalar(0.4));
-
- switch (colObj->getActivationState())
- {
- case ACTIVE_TAG:
- color = defaultColors.m_activeObject;
- break;
- case ISLAND_SLEEPING:
- color = defaultColors.m_deactivatedObject;
- break;
- case WANTS_DEACTIVATION:
- color = defaultColors.m_wantsDeactivationObject;
- break;
- case DISABLE_DEACTIVATION:
- color = defaultColors.m_disabledDeactivationObject;
- break;
- case DISABLE_SIMULATION:
- color = defaultColors.m_disabledSimulationObject;
- break;
- default:
- {
- color = btVector3(btScalar(.3), btScalar(0.3), btScalar(0.3));
- }
- };
-
- colObj->getCustomDebugColor(color);
-
- debugDrawObject(colObj->getWorldTransform(), colObj->getCollisionShape(), color);
- }
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- btVector3 minAabb, maxAabb;
- btVector3 colorvec = defaultColors.m_aabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
- btVector3 contactThreshold(gContactBreakingThreshold, gContactBreakingThreshold, gContactBreakingThreshold);
- minAabb -= contactThreshold;
- maxAabb += contactThreshold;
-
- btVector3 minAabb2, maxAabb2;
-
- if (getDispatchInfo().m_useContinuous && colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY && !colObj->isStaticOrKinematicObject())
- {
- colObj->getCollisionShape()->getAabb(colObj->getInterpolationWorldTransform(), minAabb2, maxAabb2);
- minAabb2 -= contactThreshold;
- maxAabb2 += contactThreshold;
- minAabb.setMin(minAabb2);
- maxAabb.setMax(maxAabb2);
- }
-
- m_debugDrawer->drawAabb(minAabb, maxAabb, colorvec);
- }
- }
- }
- }
- }
-}
-
-void btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
-{
- int i;
-
- ///keep track of shapes already serialized
- btHashMap<btHashPtr, btCollisionShape*> serializedShapes;
-
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btCollisionShape* shape = colObj->getCollisionShape();
-
- if (!serializedShapes.find(shape))
- {
- serializedShapes.insert(shape, shape);
- shape->serializeSingleShape(serializer);
- }
- }
-
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
- {
- colObj->serializeSingleObject(serializer);
- }
- }
-}
-
-void btCollisionWorld::serializeContactManifolds(btSerializer* serializer)
-{
- if (serializer->getSerializationFlags() & BT_SERIALIZE_CONTACT_MANIFOLDS)
- {
- int numManifolds = getDispatcher()->getNumManifolds();
- for (int i = 0; i < numManifolds; i++)
- {
- const btPersistentManifold* manifold = getDispatcher()->getInternalManifoldPointer()[i];
- //don't serialize empty manifolds, they just take space
- //(may have to do it anyway if it destroys determinism)
- if (manifold->getNumContacts() == 0)
- continue;
-
- btChunk* chunk = serializer->allocate(manifold->calculateSerializeBufferSize(), 1);
- const char* structType = manifold->serialize(manifold, chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_CONTACTMANIFOLD_CODE, (void*)manifold);
- }
- }
-}
-
-void btCollisionWorld::serialize(btSerializer* serializer)
-{
- serializer->startSerialization();
-
- serializeCollisionObjects(serializer);
-
- serializeContactManifolds(serializer);
-
- serializer->finishSerialization();
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
deleted file mode 100644
index fd0e5b9bbd..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/**
- * @mainpage Bullet Documentation
- *
- * @section intro_sec Introduction
- * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
- *
- * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution.
- * There is the Physics Forum for feedback and general Collision Detection and Physics discussions.
- * Please visit http://www.bulletphysics.org
- *
- * @section install_sec Installation
- *
- * @subsection step1 Step 1: Download
- * You can download the Bullet Physics Library from the github repository: https://github.com/bulletphysics/bullet3/releases
- *
- * @subsection step2 Step 2: Building
- * Bullet has multiple build systems, including premake, cmake and autotools. Premake and cmake support all platforms.
- * Premake is included in the Bullet/build folder for Windows, Mac OSX and Linux.
- * Under Windows you can click on Bullet/build/vs2010.bat to create Microsoft Visual Studio projects.
- * On Mac OSX and Linux you can open a terminal and generate Makefile, codeblocks or Xcode4 projects:
- * cd Bullet/build
- * ./premake4_osx gmake or ./premake4_linux gmake or ./premake4_linux64 gmake or (for Mac) ./premake4_osx xcode4
- * cd Bullet/build/gmake
- * make
- *
- * An alternative to premake is cmake. You can download cmake from http://www.cmake.org
- * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles.
- * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles.
- * You can also use cmake in the command-line. Here are some examples for various platforms:
- * cmake . -G "Visual Studio 9 2008"
- * cmake . -G Xcode
- * cmake . -G "Unix Makefiles"
- * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make.
- *
- * @subsection step3 Step 3: Testing demos
- * Try to run and experiment with BasicDemo executable as a starting point.
- * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
- * The Dependencies can be seen in this documentation under Directories
- *
- * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation
- * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
- * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld.
- * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
- * Bullet Collision Detection can also be used without the Dynamics/Extras.
- * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo.
- * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
- * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
- *
- * @section copyright Copyright
- * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
- *
- */
-
-#ifndef BT_COLLISION_WORLD_H
-#define BT_COLLISION_WORLD_H
-
-class btCollisionShape;
-class btConvexShape;
-class btBroadphaseInterface;
-class btSerializer;
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "btCollisionObject.h"
-#include "btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-///CollisionWorld is interface and container for the collision detection
-class btCollisionWorld
-{
-protected:
- btAlignedObjectArray<btCollisionObject*> m_collisionObjects;
-
- btDispatcher* m_dispatcher1;
-
- btDispatcherInfo m_dispatchInfo;
-
- btBroadphaseInterface* m_broadphasePairCache;
-
- btIDebugDraw* m_debugDrawer;
-
- ///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
- ///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
- bool m_forceUpdateAllAabbs;
-
- void serializeCollisionObjects(btSerializer* serializer);
-
- void serializeContactManifolds(btSerializer* serializer);
-
-public:
- //this constructor doesn't own the dispatcher and paircache/broadphase
- btCollisionWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
-
- virtual ~btCollisionWorld();
-
- void setBroadphase(btBroadphaseInterface* pairCache)
- {
- m_broadphasePairCache = pairCache;
- }
-
- const btBroadphaseInterface* getBroadphase() const
- {
- return m_broadphasePairCache;
- }
-
- btBroadphaseInterface* getBroadphase()
- {
- return m_broadphasePairCache;
- }
-
- btOverlappingPairCache* getPairCache()
- {
- return m_broadphasePairCache->getOverlappingPairCache();
- }
-
- btDispatcher* getDispatcher()
- {
- return m_dispatcher1;
- }
-
- const btDispatcher* getDispatcher() const
- {
- return m_dispatcher1;
- }
-
- void updateSingleAabb(btCollisionObject* colObj);
-
- virtual void updateAabbs();
-
- ///the computeOverlappingPairs is usually already called by performDiscreteCollisionDetection (or stepSimulation)
- ///it can be useful to use if you perform ray tests without collision detection/simulation
- virtual void computeOverlappingPairs();
-
- virtual void setDebugDrawer(btIDebugDraw* debugDrawer)
- {
- m_debugDrawer = debugDrawer;
- }
-
- virtual btIDebugDraw* getDebugDrawer()
- {
- return m_debugDrawer;
- }
-
- virtual void debugDrawWorld();
-
- virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
-
- ///LocalShapeInfo gives extra information for complex shapes
- ///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
- struct LocalShapeInfo
- {
- int m_shapePart;
- int m_triangleIndex;
-
- //const btCollisionShape* m_shapeTemp;
- //const btTransform* m_shapeLocalTransform;
- };
-
- struct LocalRayResult
- {
- LocalRayResult(const btCollisionObject* collisionObject,
- LocalShapeInfo* localShapeInfo,
- const btVector3& hitNormalLocal,
- btScalar hitFraction)
- : m_collisionObject(collisionObject),
- m_localShapeInfo(localShapeInfo),
- m_hitNormalLocal(hitNormalLocal),
- m_hitFraction(hitFraction)
- {
- }
-
- const btCollisionObject* m_collisionObject;
- LocalShapeInfo* m_localShapeInfo;
- btVector3 m_hitNormalLocal;
- btScalar m_hitFraction;
- };
-
- ///RayResultCallback is used to report new raycast results
- struct RayResultCallback
- {
- btScalar m_closestHitFraction;
- const btCollisionObject* m_collisionObject;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback.h. Apply any of the EFlags defined there on m_flags here to invoke.
- unsigned int m_flags;
-
- virtual ~RayResultCallback()
- {
- }
- bool hasHit() const
- {
- return (m_collisionObject != 0);
- }
-
- RayResultCallback()
- : m_closestHitFraction(btScalar(1.)),
- m_collisionObject(0),
- m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter),
- //@BP Mod
- m_flags(0)
- {
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
- collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
- return collides;
- }
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace) = 0;
- };
-
- struct ClosestRayResultCallback : public RayResultCallback
- {
- ClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld)
- {
- }
-
- btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
- btVector3 m_rayToWorld;
-
- btVector3 m_hitNormalWorld;
- btVector3 m_hitPointWorld;
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
- {
- //caller already does the filter on the m_closestHitFraction
- btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
-
- m_closestHitFraction = rayResult.m_hitFraction;
- m_collisionObject = rayResult.m_collisionObject;
- if (normalInWorldSpace)
- {
- m_hitNormalWorld = rayResult.m_hitNormalLocal;
- }
- else
- {
- ///need to transform normal into worldspace
- m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
- }
- m_hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
- return rayResult.m_hitFraction;
- }
- };
-
- struct AllHitsRayResultCallback : public RayResultCallback
- {
- AllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld)
- {
- }
-
- btAlignedObjectArray<const btCollisionObject*> m_collisionObjects;
-
- btVector3 m_rayFromWorld; //used to calculate hitPointWorld from hitFraction
- btVector3 m_rayToWorld;
-
- btAlignedObjectArray<btVector3> m_hitNormalWorld;
- btAlignedObjectArray<btVector3> m_hitPointWorld;
- btAlignedObjectArray<btScalar> m_hitFractions;
-
- virtual btScalar addSingleResult(LocalRayResult& rayResult, bool normalInWorldSpace)
- {
- m_collisionObject = rayResult.m_collisionObject;
- m_collisionObjects.push_back(rayResult.m_collisionObject);
- btVector3 hitNormalWorld;
- if (normalInWorldSpace)
- {
- hitNormalWorld = rayResult.m_hitNormalLocal;
- }
- else
- {
- ///need to transform normal into worldspace
- hitNormalWorld = m_collisionObject->getWorldTransform().getBasis() * rayResult.m_hitNormalLocal;
- }
- m_hitNormalWorld.push_back(hitNormalWorld);
- btVector3 hitPointWorld;
- hitPointWorld.setInterpolate3(m_rayFromWorld, m_rayToWorld, rayResult.m_hitFraction);
- m_hitPointWorld.push_back(hitPointWorld);
- m_hitFractions.push_back(rayResult.m_hitFraction);
- return m_closestHitFraction;
- }
- };
-
- struct LocalConvexResult
- {
- LocalConvexResult(const btCollisionObject* hitCollisionObject,
- LocalShapeInfo* localShapeInfo,
- const btVector3& hitNormalLocal,
- const btVector3& hitPointLocal,
- btScalar hitFraction)
- : m_hitCollisionObject(hitCollisionObject),
- m_localShapeInfo(localShapeInfo),
- m_hitNormalLocal(hitNormalLocal),
- m_hitPointLocal(hitPointLocal),
- m_hitFraction(hitFraction)
- {
- }
-
- const btCollisionObject* m_hitCollisionObject;
- LocalShapeInfo* m_localShapeInfo;
- btVector3 m_hitNormalLocal;
- btVector3 m_hitPointLocal;
- btScalar m_hitFraction;
- };
-
- ///RayResultCallback is used to report new raycast results
- struct ConvexResultCallback
- {
- btScalar m_closestHitFraction;
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
-
- ConvexResultCallback()
- : m_closestHitFraction(btScalar(1.)),
- m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter)
- {
- }
-
- virtual ~ConvexResultCallback()
- {
- }
-
- bool hasHit() const
- {
- return (m_closestHitFraction < btScalar(1.));
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
- collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
- return collides;
- }
-
- virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace) = 0;
- };
-
- struct ClosestConvexResultCallback : public ConvexResultCallback
- {
- ClosestConvexResultCallback(const btVector3& convexFromWorld, const btVector3& convexToWorld)
- : m_convexFromWorld(convexFromWorld),
- m_convexToWorld(convexToWorld),
- m_hitCollisionObject(0)
- {
- }
-
- btVector3 m_convexFromWorld; //used to calculate hitPointWorld from hitFraction
- btVector3 m_convexToWorld;
-
- btVector3 m_hitNormalWorld;
- btVector3 m_hitPointWorld;
- const btCollisionObject* m_hitCollisionObject;
-
- virtual btScalar addSingleResult(LocalConvexResult& convexResult, bool normalInWorldSpace)
- {
- //caller already does the filter on the m_closestHitFraction
- btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
-
- m_closestHitFraction = convexResult.m_hitFraction;
- m_hitCollisionObject = convexResult.m_hitCollisionObject;
- if (normalInWorldSpace)
- {
- m_hitNormalWorld = convexResult.m_hitNormalLocal;
- }
- else
- {
- ///need to transform normal into worldspace
- m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
- }
- m_hitPointWorld = convexResult.m_hitPointLocal;
- return convexResult.m_hitFraction;
- }
- };
-
- ///ContactResultCallback is used to report contact points
- struct ContactResultCallback
- {
- int m_collisionFilterGroup;
- int m_collisionFilterMask;
- btScalar m_closestDistanceThreshold;
-
- ContactResultCallback()
- : m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
- m_collisionFilterMask(btBroadphaseProxy::AllFilter),
- m_closestDistanceThreshold(0)
- {
- }
-
- virtual ~ContactResultCallback()
- {
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
- collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
- return collides;
- }
-
- virtual btScalar addSingleResult(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1) = 0;
- };
-
- int getNumCollisionObjects() const
- {
- return int(m_collisionObjects.size());
- }
-
- /// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
- /// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
-
- /// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
- /// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
- void convexSweepTest(const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = btScalar(0.)) const;
-
- ///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
- ///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
- void contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
-
- ///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
- ///it reports one or more contact points (including the one with deepest penetration)
- void contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
-
- /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
- /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
- /// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
-
- static void rayTestSingleInternal(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- const btCollisionObjectWrapper* collisionObjectWrap,
- RayResultCallback& resultCallback);
-
- /// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
- static void objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration);
-
- static void objectQuerySingleInternal(const btConvexShape* castShape, const btTransform& convexFromTrans, const btTransform& convexToTrans,
- const btCollisionObjectWrapper* colObjWrap,
- ConvexResultCallback& resultCallback, btScalar allowedPenetration);
-
- virtual void addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
-
- virtual void refreshBroadphaseProxy(btCollisionObject* collisionObject);
-
- btCollisionObjectArray& getCollisionObjectArray()
- {
- return m_collisionObjects;
- }
-
- const btCollisionObjectArray& getCollisionObjectArray() const
- {
- return m_collisionObjects;
- }
-
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- virtual void performDiscreteCollisionDetection();
-
- btDispatcherInfo& getDispatchInfo()
- {
- return m_dispatchInfo;
- }
-
- const btDispatcherInfo& getDispatchInfo() const
- {
- return m_dispatchInfo;
- }
-
- bool getForceUpdateAllAabbs() const
- {
- return m_forceUpdateAllAabbs;
- }
- void setForceUpdateAllAabbs(bool forceUpdateAllAabbs)
- {
- m_forceUpdateAllAabbs = forceUpdateAllAabbs;
- }
-
- ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
- virtual void serialize(btSerializer* serializer);
-};
-
-#endif //BT_COLLISION_WORLD_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
deleted file mode 100644
index e56e73dcf5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp
+++ /dev/null
@@ -1,1087 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCollisionWorldImporter.h"
-#include "btBulletCollisionCommon.h"
-#include "LinearMath/btSerializer.h" //for btBulletSerializedArrays definition
-
-#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
-#include "BulletCollision/Gimpact/btGImpactShape.h"
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
-
-btCollisionWorldImporter::btCollisionWorldImporter(btCollisionWorld* world)
- : m_collisionWorld(world),
- m_verboseMode(0)
-{
-}
-
-btCollisionWorldImporter::~btCollisionWorldImporter()
-{
-}
-
-bool btCollisionWorldImporter::convertAllObjects(btBulletSerializedArrays* arrays)
-{
- m_shapeMap.clear();
- m_bodyMap.clear();
-
- int i;
-
- for (i = 0; i < arrays->m_bvhsDouble.size(); i++)
- {
- btOptimizedBvh* bvh = createOptimizedBvh();
- btQuantizedBvhDoubleData* bvhData = arrays->m_bvhsDouble[i];
- bvh->deSerializeDouble(*bvhData);
- m_bvhMap.insert(arrays->m_bvhsDouble[i], bvh);
- }
- for (i = 0; i < arrays->m_bvhsFloat.size(); i++)
- {
- btOptimizedBvh* bvh = createOptimizedBvh();
- btQuantizedBvhFloatData* bvhData = arrays->m_bvhsFloat[i];
- bvh->deSerializeFloat(*bvhData);
- m_bvhMap.insert(arrays->m_bvhsFloat[i], bvh);
- }
-
- for (i = 0; i < arrays->m_colShapeData.size(); i++)
- {
- btCollisionShapeData* shapeData = arrays->m_colShapeData[i];
- btCollisionShape* shape = convertCollisionShape(shapeData);
- if (shape)
- {
- // printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
- m_shapeMap.insert(shapeData, shape);
- }
-
- if (shape && shapeData->m_name)
- {
- char* newname = duplicateName(shapeData->m_name);
- m_objectNameMap.insert(shape, newname);
- m_nameShapeMap.insert(newname, shape);
- }
- }
-
- for (i = 0; i < arrays->m_collisionObjectDataDouble.size(); i++)
- {
- btCollisionObjectDoubleData* colObjData = arrays->m_collisionObjectDataDouble[i];
- btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
- if (shapePtr && *shapePtr)
- {
- btTransform startTransform;
- colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
- startTransform.deSerializeDouble(colObjData->m_worldTransform);
-
- btCollisionShape* shape = (btCollisionShape*)*shapePtr;
- btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
- body->setFriction(btScalar(colObjData->m_friction));
- body->setRestitution(btScalar(colObjData->m_restitution));
-
-#ifdef USE_INTERNAL_EDGE_UTILITY
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
- if (trimesh->getTriangleInfoMap())
- {
- body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
- }
- }
-#endif //USE_INTERNAL_EDGE_UTILITY
- m_bodyMap.insert(colObjData, body);
- }
- else
- {
- printf("error: no shape found\n");
- }
- }
- for (i = 0; i < arrays->m_collisionObjectDataFloat.size(); i++)
- {
- btCollisionObjectFloatData* colObjData = arrays->m_collisionObjectDataFloat[i];
- btCollisionShape** shapePtr = m_shapeMap.find(colObjData->m_collisionShape);
- if (shapePtr && *shapePtr)
- {
- btTransform startTransform;
- colObjData->m_worldTransform.m_origin.m_floats[3] = 0.f;
- startTransform.deSerializeFloat(colObjData->m_worldTransform);
-
- btCollisionShape* shape = (btCollisionShape*)*shapePtr;
- btCollisionObject* body = createCollisionObject(startTransform, shape, colObjData->m_name);
-
-#ifdef USE_INTERNAL_EDGE_UTILITY
- if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
- if (trimesh->getTriangleInfoMap())
- {
- body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
- }
- }
-#endif //USE_INTERNAL_EDGE_UTILITY
- m_bodyMap.insert(colObjData, body);
- }
- else
- {
- printf("error: no shape found\n");
- }
- }
-
- return true;
-}
-
-void btCollisionWorldImporter::deleteAllData()
-{
- int i;
-
- for (i = 0; i < m_allocatedCollisionObjects.size(); i++)
- {
- if (m_collisionWorld)
- m_collisionWorld->removeCollisionObject(m_allocatedCollisionObjects[i]);
- delete m_allocatedCollisionObjects[i];
- }
-
- m_allocatedCollisionObjects.clear();
-
- for (i = 0; i < m_allocatedCollisionShapes.size(); i++)
- {
- delete m_allocatedCollisionShapes[i];
- }
- m_allocatedCollisionShapes.clear();
-
- for (i = 0; i < m_allocatedBvhs.size(); i++)
- {
- delete m_allocatedBvhs[i];
- }
- m_allocatedBvhs.clear();
-
- for (i = 0; i < m_allocatedTriangleInfoMaps.size(); i++)
- {
- delete m_allocatedTriangleInfoMaps[i];
- }
- m_allocatedTriangleInfoMaps.clear();
- for (i = 0; i < m_allocatedTriangleIndexArrays.size(); i++)
- {
- delete m_allocatedTriangleIndexArrays[i];
- }
- m_allocatedTriangleIndexArrays.clear();
- for (i = 0; i < m_allocatedNames.size(); i++)
- {
- delete[] m_allocatedNames[i];
- }
- m_allocatedNames.clear();
-
- for (i = 0; i < m_allocatedbtStridingMeshInterfaceDatas.size(); i++)
- {
- btStridingMeshInterfaceData* curData = m_allocatedbtStridingMeshInterfaceDatas[i];
-
- for (int a = 0; a < curData->m_numMeshParts; a++)
- {
- btMeshPartData* curPart = &curData->m_meshPartsPtr[a];
- if (curPart->m_vertices3f)
- delete[] curPart->m_vertices3f;
-
- if (curPart->m_vertices3d)
- delete[] curPart->m_vertices3d;
-
- if (curPart->m_indices32)
- delete[] curPart->m_indices32;
-
- if (curPart->m_3indices16)
- delete[] curPart->m_3indices16;
-
- if (curPart->m_indices16)
- delete[] curPart->m_indices16;
-
- if (curPart->m_3indices8)
- delete[] curPart->m_3indices8;
- }
- delete[] curData->m_meshPartsPtr;
- delete curData;
- }
- m_allocatedbtStridingMeshInterfaceDatas.clear();
-
- for (i = 0; i < m_indexArrays.size(); i++)
- {
- btAlignedFree(m_indexArrays[i]);
- }
- m_indexArrays.clear();
-
- for (i = 0; i < m_shortIndexArrays.size(); i++)
- {
- btAlignedFree(m_shortIndexArrays[i]);
- }
- m_shortIndexArrays.clear();
-
- for (i = 0; i < m_charIndexArrays.size(); i++)
- {
- btAlignedFree(m_charIndexArrays[i]);
- }
- m_charIndexArrays.clear();
-
- for (i = 0; i < m_floatVertexArrays.size(); i++)
- {
- btAlignedFree(m_floatVertexArrays[i]);
- }
- m_floatVertexArrays.clear();
-
- for (i = 0; i < m_doubleVertexArrays.size(); i++)
- {
- btAlignedFree(m_doubleVertexArrays[i]);
- }
- m_doubleVertexArrays.clear();
-}
-
-btCollisionShape* btCollisionWorldImporter::convertCollisionShape(btCollisionShapeData* shapeData)
-{
- btCollisionShape* shape = 0;
-
- switch (shapeData->m_shapeType)
- {
- case STATIC_PLANE_PROXYTYPE:
- {
- btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
- btVector3 planeNormal, localScaling;
- planeNormal.deSerializeFloat(planeData->m_planeNormal);
- localScaling.deSerializeFloat(planeData->m_localScaling);
- shape = createPlaneShape(planeNormal, planeData->m_planeConstant);
- shape->setLocalScaling(localScaling);
-
- break;
- }
- case SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE:
- {
- btScaledTriangleMeshShapeData* scaledMesh = (btScaledTriangleMeshShapeData*)shapeData;
- btCollisionShapeData* colShapeData = (btCollisionShapeData*)&scaledMesh->m_trimeshShapeData;
- colShapeData->m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- btCollisionShape* childShape = convertCollisionShape(colShapeData);
- btBvhTriangleMeshShape* meshShape = (btBvhTriangleMeshShape*)childShape;
- btVector3 localScaling;
- localScaling.deSerializeFloat(scaledMesh->m_localScaling);
-
- shape = createScaledTrangleMeshShape(meshShape, localScaling);
- break;
- }
-#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
- case GIMPACT_SHAPE_PROXYTYPE:
- {
- btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*)shapeData;
- if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
- {
- btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&gimpactData->m_meshInterface);
- btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
-
- btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
- btVector3 localScaling;
- localScaling.deSerializeFloat(gimpactData->m_localScaling);
- gimpactShape->setLocalScaling(localScaling);
- gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
- gimpactShape->updateBound();
- shape = gimpactShape;
- }
- else
- {
- printf("unsupported gimpact sub type\n");
- }
- break;
- }
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
- //The btCapsuleShape* API has issue passing the margin/scaling/halfextents unmodified through the API
- //so deal with this
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
-
- switch (capData->m_upAxis)
- {
- case 0:
- {
- shape = createCapsuleShapeX(1, 1);
- break;
- }
- case 1:
- {
- shape = createCapsuleShapeY(1, 1);
- break;
- }
- case 2:
- {
- shape = createCapsuleShapeZ(1, 1);
- break;
- }
- default:
- {
- printf("error: wrong up axis for btCapsuleShape\n");
- }
- };
- if (shape)
- {
- btCapsuleShape* cap = (btCapsuleShape*)shape;
- cap->deSerializeFloat(capData);
- }
- break;
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- case CONE_SHAPE_PROXYTYPE:
- case BOX_SHAPE_PROXYTYPE:
- case SPHERE_SHAPE_PROXYTYPE:
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
- btVector3 implicitShapeDimensions;
- implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
- btVector3 localScaling;
- localScaling.deSerializeFloat(bsd->m_localScaling);
- btVector3 margin(bsd->m_collisionMargin, bsd->m_collisionMargin, bsd->m_collisionMargin);
- switch (shapeData->m_shapeType)
- {
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* box = (btBoxShape*)createBoxShape(implicitShapeDimensions / localScaling + margin);
- //box->initializePolyhedralFeatures();
- shape = box;
-
- break;
- }
- case SPHERE_SHAPE_PROXYTYPE:
- {
- shape = createSphereShape(implicitShapeDimensions.getX());
- break;
- }
-
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShapeData* cylData = (btCylinderShapeData*)shapeData;
- btVector3 halfExtents = implicitShapeDimensions + margin;
- switch (cylData->m_upAxis)
- {
- case 0:
- {
- shape = createCylinderShapeX(halfExtents.getY(), halfExtents.getX());
- break;
- }
- case 1:
- {
- shape = createCylinderShapeY(halfExtents.getX(), halfExtents.getY());
- break;
- }
- case 2:
- {
- shape = createCylinderShapeZ(halfExtents.getX(), halfExtents.getZ());
- break;
- }
- default:
- {
- printf("unknown Cylinder up axis\n");
- }
- };
-
- break;
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- btConeShapeData* conData = (btConeShapeData*)shapeData;
- btVector3 halfExtents = implicitShapeDimensions; //+margin;
- switch (conData->m_upIndex)
- {
- case 0:
- {
- shape = createConeShapeX(halfExtents.getY(), halfExtents.getX());
- break;
- }
- case 1:
- {
- shape = createConeShapeY(halfExtents.getX(), halfExtents.getY());
- break;
- }
- case 2:
- {
- shape = createConeShapeZ(halfExtents.getX(), halfExtents.getZ());
- break;
- }
- default:
- {
- printf("unknown Cone up axis\n");
- }
- };
-
- break;
- }
- case MULTI_SPHERE_SHAPE_PROXYTYPE:
- {
- btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
- int numSpheres = mss->m_localPositionArraySize;
-
- btAlignedObjectArray<btVector3> tmpPos;
- btAlignedObjectArray<btScalar> radii;
- radii.resize(numSpheres);
- tmpPos.resize(numSpheres);
- int i;
- for (i = 0; i < numSpheres; i++)
- {
- tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
- radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
- }
- shape = createMultiSphereShape(&tmpPos[0], &radii[0], numSpheres);
- break;
- }
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- // int sz = sizeof(btConvexHullShapeData);
- // int sz2 = sizeof(btConvexInternalShapeData);
- // int sz3 = sizeof(btCollisionShapeData);
- btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
- int numPoints = convexData->m_numUnscaledPoints;
-
- btAlignedObjectArray<btVector3> tmpPoints;
- tmpPoints.resize(numPoints);
- int i;
- for (i = 0; i < numPoints; i++)
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- if (convexData->m_unscaledPointsDoublePtr)
- tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
- if (convexData->m_unscaledPointsFloatPtr)
- tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
-#else
- if (convexData->m_unscaledPointsFloatPtr)
- tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
- if (convexData->m_unscaledPointsDoublePtr)
- tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
-#endif //BT_USE_DOUBLE_PRECISION
- }
- btConvexHullShape* hullShape = createConvexHullShape();
- for (i = 0; i < numPoints; i++)
- {
- hullShape->addPoint(tmpPoints[i]);
- }
- hullShape->setMargin(bsd->m_collisionMargin);
- //hullShape->initializePolyhedralFeatures();
- shape = hullShape;
- break;
- }
- default:
- {
- printf("error: cannot create shape type (%d)\n", shapeData->m_shapeType);
- }
- }
-
- if (shape)
- {
- shape->setMargin(bsd->m_collisionMargin);
-
- btVector3 localScaling;
- localScaling.deSerializeFloat(bsd->m_localScaling);
- shape->setLocalScaling(localScaling);
- }
- break;
- }
- case TRIANGLE_MESH_SHAPE_PROXYTYPE:
- {
- btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
- btStridingMeshInterfaceData* interfaceData = createStridingMeshInterfaceData(&trimesh->m_meshInterface);
- btTriangleIndexVertexArray* meshInterface = createMeshInterface(*interfaceData);
- if (!meshInterface->getNumSubParts())
- {
- return 0;
- }
-
- btVector3 scaling;
- scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
- meshInterface->setScaling(scaling);
-
- btOptimizedBvh* bvh = 0;
-#if 1
- if (trimesh->m_quantizedFloatBvh)
- {
- btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh);
- if (bvhPtr && *bvhPtr)
- {
- bvh = *bvhPtr;
- }
- else
- {
- bvh = createOptimizedBvh();
- bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh);
- }
- }
- if (trimesh->m_quantizedDoubleBvh)
- {
- btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh);
- if (bvhPtr && *bvhPtr)
- {
- bvh = *bvhPtr;
- }
- else
- {
- bvh = createOptimizedBvh();
- bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh);
- }
- }
-#endif
-
- btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface, bvh);
- trimeshShape->setMargin(trimesh->m_collisionMargin);
- shape = trimeshShape;
-
- if (trimesh->m_triangleInfoMap)
- {
- btTriangleInfoMap* map = createTriangleInfoMap();
- map->deSerialize(*trimesh->m_triangleInfoMap);
- trimeshShape->setTriangleInfoMap(map);
-
-#ifdef USE_INTERNAL_EDGE_UTILITY
- gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
-#endif //USE_INTERNAL_EDGE_UTILITY
- }
-
- //printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
- break;
- }
- case COMPOUND_SHAPE_PROXYTYPE:
- {
- btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
- btCompoundShape* compoundShape = createCompoundShape();
-
- //btCompoundShapeChildData* childShapeDataArray = &compoundData->m_childShapePtr[0];
-
- btAlignedObjectArray<btCollisionShape*> childShapes;
- for (int i = 0; i < compoundData->m_numChildShapes; i++)
- {
- //btCompoundShapeChildData* ptr = &compoundData->m_childShapePtr[i];
-
- btCollisionShapeData* cd = compoundData->m_childShapePtr[i].m_childShape;
-
- btCollisionShape* childShape = convertCollisionShape(cd);
- if (childShape)
- {
- btTransform localTransform;
- localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
- compoundShape->addChildShape(localTransform, childShape);
- }
- else
- {
-#ifdef _DEBUG
- printf("error: couldn't create childShape for compoundShape\n");
-#endif
- }
- }
- shape = compoundShape;
-
- break;
- }
- case SOFTBODY_SHAPE_PROXYTYPE:
- {
- return 0;
- }
- default:
- {
-#ifdef _DEBUG
- printf("unsupported shape type (%d)\n", shapeData->m_shapeType);
-#endif
- }
- }
-
- return shape;
-}
-
-char* btCollisionWorldImporter::duplicateName(const char* name)
-{
- if (name)
- {
- int l = (int)strlen(name);
- char* newName = new char[l + 1];
- memcpy(newName, name, l);
- newName[l] = 0;
- m_allocatedNames.push_back(newName);
- return newName;
- }
- return 0;
-}
-
-btTriangleIndexVertexArray* btCollisionWorldImporter::createMeshInterface(btStridingMeshInterfaceData& meshData)
-{
- btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();
-
- for (int i = 0; i < meshData.m_numMeshParts; i++)
- {
- btIndexedMesh meshPart;
- meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
- meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
-
- if (meshData.m_meshPartsPtr[i].m_indices32)
- {
- meshPart.m_indexType = PHY_INTEGER;
- meshPart.m_triangleIndexStride = 3 * sizeof(int);
- int* indexArray = (int*)btAlignedAlloc(sizeof(int) * 3 * meshPart.m_numTriangles, 16);
- m_indexArrays.push_back(indexArray);
- for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
- {
- indexArray[j] = meshData.m_meshPartsPtr[i].m_indices32[j].m_value;
- }
- meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
- }
- else
- {
- if (meshData.m_meshPartsPtr[i].m_3indices16)
- {
- meshPart.m_indexType = PHY_SHORT;
- meshPart.m_triangleIndexStride = sizeof(short int) * 3; //sizeof(btShortIntIndexTripletData);
-
- short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
- m_shortIndexArrays.push_back(indexArray);
-
- for (int j = 0; j < meshPart.m_numTriangles; j++)
- {
- indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[0];
- indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[1];
- indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices16[j].m_values[2];
- }
-
- meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
- }
- if (meshData.m_meshPartsPtr[i].m_indices16)
- {
- meshPart.m_indexType = PHY_SHORT;
- meshPart.m_triangleIndexStride = 3 * sizeof(short int);
- short int* indexArray = (short int*)btAlignedAlloc(sizeof(short int) * 3 * meshPart.m_numTriangles, 16);
- m_shortIndexArrays.push_back(indexArray);
- for (int j = 0; j < 3 * meshPart.m_numTriangles; j++)
- {
- indexArray[j] = meshData.m_meshPartsPtr[i].m_indices16[j].m_value;
- }
-
- meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
- }
-
- if (meshData.m_meshPartsPtr[i].m_3indices8)
- {
- meshPart.m_indexType = PHY_UCHAR;
- meshPart.m_triangleIndexStride = sizeof(unsigned char) * 3;
-
- unsigned char* indexArray = (unsigned char*)btAlignedAlloc(sizeof(unsigned char) * 3 * meshPart.m_numTriangles, 16);
- m_charIndexArrays.push_back(indexArray);
-
- for (int j = 0; j < meshPart.m_numTriangles; j++)
- {
- indexArray[3 * j] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[0];
- indexArray[3 * j + 1] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[1];
- indexArray[3 * j + 2] = meshData.m_meshPartsPtr[i].m_3indices8[j].m_values[2];
- }
-
- meshPart.m_triangleIndexBase = (const unsigned char*)indexArray;
- }
- }
-
- if (meshData.m_meshPartsPtr[i].m_vertices3f)
- {
- meshPart.m_vertexType = PHY_FLOAT;
- meshPart.m_vertexStride = sizeof(btVector3FloatData);
- btVector3FloatData* vertices = (btVector3FloatData*)btAlignedAlloc(sizeof(btVector3FloatData) * meshPart.m_numVertices, 16);
- m_floatVertexArrays.push_back(vertices);
-
- for (int j = 0; j < meshPart.m_numVertices; j++)
- {
- vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[0];
- vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[1];
- vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[2];
- vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3f[j].m_floats[3];
- }
- meshPart.m_vertexBase = (const unsigned char*)vertices;
- }
- else
- {
- meshPart.m_vertexType = PHY_DOUBLE;
- meshPart.m_vertexStride = sizeof(btVector3DoubleData);
-
- btVector3DoubleData* vertices = (btVector3DoubleData*)btAlignedAlloc(sizeof(btVector3DoubleData) * meshPart.m_numVertices, 16);
- m_doubleVertexArrays.push_back(vertices);
-
- for (int j = 0; j < meshPart.m_numVertices; j++)
- {
- vertices[j].m_floats[0] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[0];
- vertices[j].m_floats[1] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[1];
- vertices[j].m_floats[2] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[2];
- vertices[j].m_floats[3] = meshData.m_meshPartsPtr[i].m_vertices3d[j].m_floats[3];
- }
- meshPart.m_vertexBase = (const unsigned char*)vertices;
- }
-
- if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
- {
- meshInterface->addIndexedMesh(meshPart, meshPart.m_indexType);
- }
- }
-
- return meshInterface;
-}
-
-btStridingMeshInterfaceData* btCollisionWorldImporter::createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData)
-{
- //create a new btStridingMeshInterfaceData that is an exact copy of shapedata and store it in the WorldImporter
- btStridingMeshInterfaceData* newData = new btStridingMeshInterfaceData;
-
- newData->m_scaling = interfaceData->m_scaling;
- newData->m_numMeshParts = interfaceData->m_numMeshParts;
- newData->m_meshPartsPtr = new btMeshPartData[newData->m_numMeshParts];
-
- for (int i = 0; i < newData->m_numMeshParts; i++)
- {
- btMeshPartData* curPart = &interfaceData->m_meshPartsPtr[i];
- btMeshPartData* curNewPart = &newData->m_meshPartsPtr[i];
-
- curNewPart->m_numTriangles = curPart->m_numTriangles;
- curNewPart->m_numVertices = curPart->m_numVertices;
-
- if (curPart->m_vertices3f)
- {
- curNewPart->m_vertices3f = new btVector3FloatData[curNewPart->m_numVertices];
- memcpy(curNewPart->m_vertices3f, curPart->m_vertices3f, sizeof(btVector3FloatData) * curNewPart->m_numVertices);
- }
- else
- curNewPart->m_vertices3f = NULL;
-
- if (curPart->m_vertices3d)
- {
- curNewPart->m_vertices3d = new btVector3DoubleData[curNewPart->m_numVertices];
- memcpy(curNewPart->m_vertices3d, curPart->m_vertices3d, sizeof(btVector3DoubleData) * curNewPart->m_numVertices);
- }
- else
- curNewPart->m_vertices3d = NULL;
-
- int numIndices = curNewPart->m_numTriangles * 3;
- ///the m_3indices8 was not initialized in some Bullet versions, this can cause crashes at loading time
- ///we catch it by only dealing with m_3indices8 if none of the other indices are initialized
- bool uninitialized3indices8Workaround = false;
-
- if (curPart->m_indices32)
- {
- uninitialized3indices8Workaround = true;
- curNewPart->m_indices32 = new btIntIndexData[numIndices];
- memcpy(curNewPart->m_indices32, curPart->m_indices32, sizeof(btIntIndexData) * numIndices);
- }
- else
- curNewPart->m_indices32 = NULL;
-
- if (curPart->m_3indices16)
- {
- uninitialized3indices8Workaround = true;
- curNewPart->m_3indices16 = new btShortIntIndexTripletData[curNewPart->m_numTriangles];
- memcpy(curNewPart->m_3indices16, curPart->m_3indices16, sizeof(btShortIntIndexTripletData) * curNewPart->m_numTriangles);
- }
- else
- curNewPart->m_3indices16 = NULL;
-
- if (curPart->m_indices16)
- {
- uninitialized3indices8Workaround = true;
- curNewPart->m_indices16 = new btShortIntIndexData[numIndices];
- memcpy(curNewPart->m_indices16, curPart->m_indices16, sizeof(btShortIntIndexData) * numIndices);
- }
- else
- curNewPart->m_indices16 = NULL;
-
- if (!uninitialized3indices8Workaround && curPart->m_3indices8)
- {
- curNewPart->m_3indices8 = new btCharIndexTripletData[curNewPart->m_numTriangles];
- memcpy(curNewPart->m_3indices8, curPart->m_3indices8, sizeof(btCharIndexTripletData) * curNewPart->m_numTriangles);
- }
- else
- curNewPart->m_3indices8 = NULL;
- }
-
- m_allocatedbtStridingMeshInterfaceDatas.push_back(newData);
-
- return (newData);
-}
-
-#ifdef USE_INTERNAL_EDGE_UTILITY
-extern ContactAddedCallback gContactAddedCallback;
-
-static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp, const btCollisionObject* colObj0, int partId0, int index0, const btCollisionObject* colObj1, int partId1, int index1)
-{
- btAdjustInternalEdgeContacts(cp, colObj1, colObj0, partId1, index1);
- //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
- //btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
- return true;
-}
-#endif //USE_INTERNAL_EDGE_UTILITY
-
-/*
-btRigidBody* btWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName)
-{
- btVector3 localInertia;
- localInertia.setZero();
-
- if (mass)
- shape->calculateLocalInertia(mass,localInertia);
-
- btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);
- body->setWorldTransform(startTransform);
-
- if (m_dynamicsWorld)
- m_dynamicsWorld->addRigidBody(body);
-
- if (bodyName)
- {
- char* newname = duplicateName(bodyName);
- m_objectNameMap.insert(body,newname);
- m_nameBodyMap.insert(newname,body);
- }
- m_allocatedRigidBodies.push_back(body);
- return body;
-
-}
-*/
-
-btCollisionObject* btCollisionWorldImporter::getCollisionObjectByName(const char* name)
-{
- btCollisionObject** bodyPtr = m_nameColObjMap.find(name);
- if (bodyPtr && *bodyPtr)
- {
- return *bodyPtr;
- }
- return 0;
-}
-
-btCollisionObject* btCollisionWorldImporter::createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName)
-{
- btCollisionObject* colObj = new btCollisionObject();
- colObj->setWorldTransform(startTransform);
- colObj->setCollisionShape(shape);
- m_collisionWorld->addCollisionObject(colObj); //todo: flags etc
-
- if (bodyName)
- {
- char* newname = duplicateName(bodyName);
- m_objectNameMap.insert(colObj, newname);
- m_nameColObjMap.insert(newname, colObj);
- }
- m_allocatedCollisionObjects.push_back(colObj);
-
- return colObj;
-}
-
-btCollisionShape* btCollisionWorldImporter::createPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
-{
- btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal, planeConstant);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-btCollisionShape* btCollisionWorldImporter::createBoxShape(const btVector3& halfExtents)
-{
- btBoxShape* shape = new btBoxShape(halfExtents);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-btCollisionShape* btCollisionWorldImporter::createSphereShape(btScalar radius)
-{
- btSphereShape* shape = new btSphereShape(radius);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height)
-{
- btCapsuleShapeX* shape = new btCapsuleShapeX(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height)
-{
- btCapsuleShape* shape = new btCapsuleShape(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height)
-{
- btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeX(btScalar radius, btScalar height)
-{
- btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height, radius, radius));
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeY(btScalar radius, btScalar height)
-{
- btCylinderShape* shape = new btCylinderShape(btVector3(radius, height, radius));
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createCylinderShapeZ(btScalar radius, btScalar height)
-{
- btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius, radius, height));
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createConeShapeX(btScalar radius, btScalar height)
-{
- btConeShapeX* shape = new btConeShapeX(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createConeShapeY(btScalar radius, btScalar height)
-{
- btConeShape* shape = new btConeShape(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCollisionShape* btCollisionWorldImporter::createConeShapeZ(btScalar radius, btScalar height)
-{
- btConeShapeZ* shape = new btConeShapeZ(radius, height);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btTriangleIndexVertexArray* btCollisionWorldImporter::createTriangleMeshContainer()
-{
- btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray();
- m_allocatedTriangleIndexArrays.push_back(in);
- return in;
-}
-
-btOptimizedBvh* btCollisionWorldImporter::createOptimizedBvh()
-{
- btOptimizedBvh* bvh = new btOptimizedBvh();
- m_allocatedBvhs.push_back(bvh);
- return bvh;
-}
-
-btTriangleInfoMap* btCollisionWorldImporter::createTriangleInfoMap()
-{
- btTriangleInfoMap* tim = new btTriangleInfoMap();
- m_allocatedTriangleInfoMaps.push_back(tim);
- return tim;
-}
-
-btBvhTriangleMeshShape* btCollisionWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh)
-{
- if (bvh)
- {
- btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh, bvh->isQuantized(), false);
- bvhTriMesh->setOptimizedBvh(bvh);
- m_allocatedCollisionShapes.push_back(bvhTriMesh);
- return bvhTriMesh;
- }
-
- btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh, true);
- m_allocatedCollisionShapes.push_back(ts);
- return ts;
-}
-btCollisionShape* btCollisionWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh)
-{
- return 0;
-}
-#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
-btGImpactMeshShape* btCollisionWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh)
-{
- btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
-
-btConvexHullShape* btCollisionWorldImporter::createConvexHullShape()
-{
- btConvexHullShape* shape = new btConvexHullShape();
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btCompoundShape* btCollisionWorldImporter::createCompoundShape()
-{
- btCompoundShape* shape = new btCompoundShape();
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btScaledBvhTriangleMeshShape* btCollisionWorldImporter::createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScaling)
-{
- btScaledBvhTriangleMeshShape* shape = new btScaledBvhTriangleMeshShape(meshShape, localScaling);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-btMultiSphereShape* btCollisionWorldImporter::createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
-{
- btMultiSphereShape* shape = new btMultiSphereShape(positions, radi, numSpheres);
- m_allocatedCollisionShapes.push_back(shape);
- return shape;
-}
-
-// query for data
-int btCollisionWorldImporter::getNumCollisionShapes() const
-{
- return m_allocatedCollisionShapes.size();
-}
-
-btCollisionShape* btCollisionWorldImporter::getCollisionShapeByIndex(int index)
-{
- return m_allocatedCollisionShapes[index];
-}
-
-btCollisionShape* btCollisionWorldImporter::getCollisionShapeByName(const char* name)
-{
- btCollisionShape** shapePtr = m_nameShapeMap.find(name);
- if (shapePtr && *shapePtr)
- {
- return *shapePtr;
- }
- return 0;
-}
-
-const char* btCollisionWorldImporter::getNameForPointer(const void* ptr) const
-{
- const char* const* namePtr = m_objectNameMap.find(ptr);
- if (namePtr && *namePtr)
- return *namePtr;
- return 0;
-}
-
-int btCollisionWorldImporter::getNumRigidBodies() const
-{
- return m_allocatedRigidBodies.size();
-}
-
-btCollisionObject* btCollisionWorldImporter::getRigidBodyByIndex(int index) const
-{
- return m_allocatedRigidBodies[index];
-}
-
-int btCollisionWorldImporter::getNumBvhs() const
-{
- return m_allocatedBvhs.size();
-}
-btOptimizedBvh* btCollisionWorldImporter::getBvhByIndex(int index) const
-{
- return m_allocatedBvhs[index];
-}
-
-int btCollisionWorldImporter::getNumTriangleInfoMaps() const
-{
- return m_allocatedTriangleInfoMaps.size();
-}
-
-btTriangleInfoMap* btCollisionWorldImporter::getTriangleInfoMapByIndex(int index) const
-{
- return m_allocatedTriangleInfoMaps[index];
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
deleted file mode 100644
index 5e8bc95341..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCollisionWorldImporter.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_WORLD_IMPORTER_H
-#define BT_COLLISION_WORLD_IMPORTER_H
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btHashMap.h"
-
-class btCollisionShape;
-class btCollisionObject;
-struct btBulletSerializedArrays;
-
-struct ConstraintInput;
-class btCollisionWorld;
-struct btCollisionShapeData;
-class btTriangleIndexVertexArray;
-class btStridingMeshInterface;
-struct btStridingMeshInterfaceData;
-class btGImpactMeshShape;
-class btOptimizedBvh;
-struct btTriangleInfoMap;
-class btBvhTriangleMeshShape;
-class btPoint2PointConstraint;
-class btHingeConstraint;
-class btConeTwistConstraint;
-class btGeneric6DofConstraint;
-class btGeneric6DofSpringConstraint;
-class btSliderConstraint;
-class btGearConstraint;
-struct btContactSolverInfo;
-
-class btCollisionWorldImporter
-{
-protected:
- btCollisionWorld* m_collisionWorld;
-
- int m_verboseMode;
-
- btAlignedObjectArray<btCollisionShape*> m_allocatedCollisionShapes;
- btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
-
- btAlignedObjectArray<btOptimizedBvh*> m_allocatedBvhs;
- btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
- btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
- btAlignedObjectArray<btStridingMeshInterfaceData*> m_allocatedbtStridingMeshInterfaceDatas;
- btAlignedObjectArray<btCollisionObject*> m_allocatedCollisionObjects;
-
- btAlignedObjectArray<char*> m_allocatedNames;
-
- btAlignedObjectArray<int*> m_indexArrays;
- btAlignedObjectArray<short int*> m_shortIndexArrays;
- btAlignedObjectArray<unsigned char*> m_charIndexArrays;
-
- btAlignedObjectArray<btVector3FloatData*> m_floatVertexArrays;
- btAlignedObjectArray<btVector3DoubleData*> m_doubleVertexArrays;
-
- btHashMap<btHashPtr, btOptimizedBvh*> m_bvhMap;
- btHashMap<btHashPtr, btTriangleInfoMap*> m_timMap;
-
- btHashMap<btHashString, btCollisionShape*> m_nameShapeMap;
- btHashMap<btHashString, btCollisionObject*> m_nameColObjMap;
-
- btHashMap<btHashPtr, const char*> m_objectNameMap;
-
- btHashMap<btHashPtr, btCollisionShape*> m_shapeMap;
- btHashMap<btHashPtr, btCollisionObject*> m_bodyMap;
-
- //methods
-
- char* duplicateName(const char* name);
-
- btCollisionShape* convertCollisionShape(btCollisionShapeData* shapeData);
-
-public:
- btCollisionWorldImporter(btCollisionWorld* world);
-
- virtual ~btCollisionWorldImporter();
-
- bool convertAllObjects(btBulletSerializedArrays* arrays);
-
- ///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
- ///make sure you don't use the dynamics world containing objects after you call this method
- virtual void deleteAllData();
-
- void setVerboseMode(int verboseMode)
- {
- m_verboseMode = verboseMode;
- }
-
- int getVerboseMode() const
- {
- return m_verboseMode;
- }
-
- // query for data
- int getNumCollisionShapes() const;
- btCollisionShape* getCollisionShapeByIndex(int index);
- int getNumRigidBodies() const;
- btCollisionObject* getRigidBodyByIndex(int index) const;
-
- int getNumBvhs() const;
- btOptimizedBvh* getBvhByIndex(int index) const;
- int getNumTriangleInfoMaps() const;
- btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
-
- // queris involving named objects
- btCollisionShape* getCollisionShapeByName(const char* name);
- btCollisionObject* getCollisionObjectByName(const char* name);
-
- const char* getNameForPointer(const void* ptr) const;
-
- ///those virtuals are called by load and can be overridden by the user
-
- //bodies
-
- virtual btCollisionObject* createCollisionObject(const btTransform& startTransform, btCollisionShape* shape, const char* bodyName);
-
- ///shapes
-
- virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
- virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
- virtual btCollisionShape* createSphereShape(btScalar radius);
- virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
- virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
- virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
-
- virtual btCollisionShape* createCylinderShapeX(btScalar radius, btScalar height);
- virtual btCollisionShape* createCylinderShapeY(btScalar radius, btScalar height);
- virtual btCollisionShape* createCylinderShapeZ(btScalar radius, btScalar height);
- virtual btCollisionShape* createConeShapeX(btScalar radius, btScalar height);
- virtual btCollisionShape* createConeShapeY(btScalar radius, btScalar height);
- virtual btCollisionShape* createConeShapeZ(btScalar radius, btScalar height);
- virtual class btTriangleIndexVertexArray* createTriangleMeshContainer();
- virtual btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
- virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
-#ifdef SUPPORT_GIMPACT_SHAPE_IMPORT
- virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh);
-#endif //SUPPORT_GIMPACT_SHAPE_IMPORT
- virtual btStridingMeshInterfaceData* createStridingMeshInterfaceData(btStridingMeshInterfaceData* interfaceData);
-
- virtual class btConvexHullShape* createConvexHullShape();
- virtual class btCompoundShape* createCompoundShape();
- virtual class btScaledBvhTriangleMeshShape* createScaledTrangleMeshShape(btBvhTriangleMeshShape* meshShape, const btVector3& localScalingbtBvhTriangleMeshShape);
-
- virtual class btMultiSphereShape* createMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
-
- virtual btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
-
- ///acceleration and connectivity structures
- virtual btOptimizedBvh* createOptimizedBvh();
- virtual btTriangleInfoMap* createTriangleInfoMap();
-};
-
-#endif //BT_WORLD_IMPORTER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
deleted file mode 100644
index b5f4a3c869..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-*/
-
-#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "btManifoldResult.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btShapePairCallback gCompoundChildShapePairCallback = 0;
-
-btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_isSwapped(isSwapped),
- m_sharedManifold(ci.m_manifold)
-{
- m_ownsManifold = false;
-
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- btAssert(colObjWrap->getCollisionShape()->isCompound());
-
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
- m_compoundShapeRevision = compoundShape->getUpdateRevision();
-
- preallocateChildAlgorithms(body0Wrap, body1Wrap);
-}
-
-void btCompoundCollisionAlgorithm::preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
-{
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
- btAssert(colObjWrap->getCollisionShape()->isCompound());
-
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
-
- int numChildren = compoundShape->getNumChildShapes();
- int i;
-
- m_childCollisionAlgorithms.resize(numChildren);
- for (i = 0; i < numChildren; i++)
- {
- if (compoundShape->getDynamicAabbTree())
- {
- m_childCollisionAlgorithms[i] = 0;
- }
- else
- {
- const btCollisionShape* childShape = compoundShape->getChildShape(i);
-
- btCollisionObjectWrapper childWrap(colObjWrap, childShape, colObjWrap->getCollisionObject(), colObjWrap->getWorldTransform(), -1, i); //wrong child trans, but unused (hopefully)
- m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(&childWrap, otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
-
- btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsContact;
- btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithmsClosestPoints;
- }
- }
-}
-
-void btCompoundCollisionAlgorithm::removeChildAlgorithms()
-{
- int numChildren = m_childCollisionAlgorithms.size();
- int i;
- for (i = 0; i < numChildren; i++)
- {
- if (m_childCollisionAlgorithms[i])
- {
- m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
- }
- }
-}
-
-btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
-{
- removeChildAlgorithms();
-}
-
-struct btCompoundLeafCallback : btDbvt::ICollide
-{
-public:
- const btCollisionObjectWrapper* m_compoundColObjWrap;
- const btCollisionObjectWrapper* m_otherObjWrap;
- btDispatcher* m_dispatcher;
- const btDispatcherInfo& m_dispatchInfo;
- btManifoldResult* m_resultOut;
- btCollisionAlgorithm** m_childCollisionAlgorithms;
- btPersistentManifold* m_sharedManifold;
-
- btCompoundLeafCallback(const btCollisionObjectWrapper* compoundObjWrap, const btCollisionObjectWrapper* otherObjWrap, btDispatcher* dispatcher, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut, btCollisionAlgorithm** childCollisionAlgorithms, btPersistentManifold* sharedManifold)
- : m_compoundColObjWrap(compoundObjWrap), m_otherObjWrap(otherObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithms(childCollisionAlgorithms), m_sharedManifold(sharedManifold)
- {
- }
-
- void ProcessChildShape(const btCollisionShape* childShape, int index)
- {
- btAssert(index >= 0);
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
- btAssert(index < compoundShape->getNumChildShapes());
-
- if (gCompoundChildShapePairCallback)
- {
- if (!gCompoundChildShapePairCallback(m_otherObjWrap->getCollisionShape(), childShape))
- return;
- }
-
- //backup
- btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
-
- const btTransform& childTrans = compoundShape->getChildTransform(index);
- btTransform newChildWorldTrans = orgTrans * childTrans;
-
- //perform an AABB check first
- btVector3 aabbMin0, aabbMax0;
- childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
-
- btVector3 extendAabb(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
- aabbMin0 -= extendAabb;
- aabbMax0 += extendAabb;
-
- btVector3 aabbMin1, aabbMax1;
- m_otherObjWrap->getCollisionShape()->getAabb(m_otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
-
-
- if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
- {
- btTransform preTransform = childTrans;
- if (this->m_compoundColObjWrap->m_preTransform)
- {
- preTransform = preTransform *(*(this->m_compoundColObjWrap->m_preTransform));
- }
- btCollisionObjectWrapper compoundWrap(this->m_compoundColObjWrap, childShape, m_compoundColObjWrap->getCollisionObject(), newChildWorldTrans, preTransform, -1, index);
-
- btCollisionAlgorithm* algo = 0;
- bool allocatedAlgorithm = false;
-
- if (m_resultOut->m_closestPointDistanceThreshold > 0)
- {
- algo = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
- allocatedAlgorithm = true;
- }
- else
- {
- //the contactpoint is still projected back using the original inverted worldtrans
- if (!m_childCollisionAlgorithms[index])
- {
- m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(&compoundWrap, m_otherObjWrap, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
- }
- algo = m_childCollisionAlgorithms[index];
- }
-
- const btCollisionObjectWrapper* tmpWrap = 0;
-
- ///detect swapping case
- if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
- {
- tmpWrap = m_resultOut->getBody0Wrap();
- m_resultOut->setBody0Wrap(&compoundWrap);
- m_resultOut->setShapeIdentifiersA(-1, index);
- }
- else
- {
- tmpWrap = m_resultOut->getBody1Wrap();
- m_resultOut->setBody1Wrap(&compoundWrap);
- m_resultOut->setShapeIdentifiersB(-1, index);
- }
-
- algo->processCollision(&compoundWrap, m_otherObjWrap, m_dispatchInfo, m_resultOut);
-
-#if 0
- if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- btVector3 worldAabbMin,worldAabbMax;
- m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
- m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
- }
-#endif
-
- if (m_resultOut->getBody0Internal() == m_compoundColObjWrap->getCollisionObject())
- {
- m_resultOut->setBody0Wrap(tmpWrap);
- }
- else
- {
- m_resultOut->setBody1Wrap(tmpWrap);
- }
- if (allocatedAlgorithm)
- {
- algo->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(algo);
- }
- }
- }
- void Process(const btDbvtNode* leaf)
- {
- int index = leaf->dataAsInt;
-
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(m_compoundColObjWrap->getCollisionShape());
- const btCollisionShape* childShape = compoundShape->getChildShape(index);
-
-#if 0
- if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- btVector3 worldAabbMin,worldAabbMax;
- btTransform orgTrans = m_compoundColObjWrap->getWorldTransform();
- btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
- m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
- }
-#endif
-
- ProcessChildShape(childShape, index);
- }
-};
-
-void btCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- const btCollisionObjectWrapper* colObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* otherObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- btAssert(colObjWrap->getCollisionShape()->isCompound());
- const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(colObjWrap->getCollisionShape());
-
- ///btCompoundShape might have changed:
- ////make sure the internal child collision algorithm caches are still valid
- if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
- {
- ///clear and update all
- removeChildAlgorithms();
-
- preallocateChildAlgorithms(body0Wrap, body1Wrap);
- m_compoundShapeRevision = compoundShape->getUpdateRevision();
- }
-
- if (m_childCollisionAlgorithms.size() == 0)
- return;
-
- const btDbvt* tree = compoundShape->getDynamicAabbTree();
- //use a dynamic aabb tree to cull potential child-overlaps
- btCompoundLeafCallback callback(colObjWrap, otherObjWrap, m_dispatcher, dispatchInfo, resultOut, &m_childCollisionAlgorithms[0], m_sharedManifold);
-
- ///we need to refresh all contact manifolds
- ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
- ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
- {
- int i;
- manifoldArray.resize(0);
- for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
- {
- if (m_childCollisionAlgorithms[i])
- {
- m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
- for (int m = 0; m < manifoldArray.size(); m++)
- {
- if (manifoldArray[m]->getNumContacts())
- {
- resultOut->setPersistentManifold(manifoldArray[m]);
- resultOut->refreshContactPoints();
- resultOut->setPersistentManifold(0); //??necessary?
- }
- }
- manifoldArray.resize(0);
- }
- }
- }
-
- if (tree)
- {
- btVector3 localAabbMin, localAabbMax;
- btTransform otherInCompoundSpace;
- otherInCompoundSpace = colObjWrap->getWorldTransform().inverse() * otherObjWrap->getWorldTransform();
- otherObjWrap->getCollisionShape()->getAabb(otherInCompoundSpace, localAabbMin, localAabbMax);
- btVector3 extraExtends(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
- localAabbMin -= extraExtends;
- localAabbMax += extraExtends;
-
- const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
- //process all children, that overlap with the given AABB bounds
- tree->collideTVNoStackAlloc(tree->m_root, bounds, stack2, callback);
- }
- else
- {
- //iterate over all children, perform an AABB check inside ProcessChildShape
- int numChildren = m_childCollisionAlgorithms.size();
- int i;
- for (i = 0; i < numChildren; i++)
- {
- callback.ProcessChildShape(compoundShape->getChildShape(i), i);
- }
- }
-
- {
- //iterate over all children, perform an AABB check inside ProcessChildShape
- int numChildren = m_childCollisionAlgorithms.size();
- int i;
- manifoldArray.resize(0);
- const btCollisionShape* childShape = 0;
- btTransform orgTrans;
-
- btTransform newChildWorldTrans;
- btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
-
- for (i = 0; i < numChildren; i++)
- {
- if (m_childCollisionAlgorithms[i])
- {
- childShape = compoundShape->getChildShape(i);
- //if not longer overlapping, remove the algorithm
- orgTrans = colObjWrap->getWorldTransform();
-
- const btTransform& childTrans = compoundShape->getChildTransform(i);
- newChildWorldTrans = orgTrans * childTrans;
-
- //perform an AABB check first
- childShape->getAabb(newChildWorldTrans, aabbMin0, aabbMax0);
- otherObjWrap->getCollisionShape()->getAabb(otherObjWrap->getWorldTransform(), aabbMin1, aabbMax1);
-
- if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
- {
- m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
- m_childCollisionAlgorithms[i] = 0;
- }
- }
- }
- }
-}
-
-btScalar btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- btAssert(0);
- //needs to be fixed, using btCollisionObjectWrapper and NOT modifying internal data structures
- btCollisionObject* colObj = m_isSwapped ? body1 : body0;
- btCollisionObject* otherObj = m_isSwapped ? body0 : body1;
-
- btAssert(colObj->getCollisionShape()->isCompound());
-
- btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
-
- //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
- //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
- //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
- //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
- //then use each overlapping node AABB against Tree0
- //and vise versa.
-
- btScalar hitFraction = btScalar(1.);
-
- int numChildren = m_childCollisionAlgorithms.size();
- int i;
- btTransform orgTrans;
- btScalar frac;
- for (i = 0; i < numChildren; i++)
- {
- //btCollisionShape* childShape = compoundShape->getChildShape(i);
-
- //backup
- orgTrans = colObj->getWorldTransform();
-
- const btTransform& childTrans = compoundShape->getChildTransform(i);
- //btTransform newChildWorldTrans = orgTrans*childTrans ;
- colObj->setWorldTransform(orgTrans * childTrans);
-
- //btCollisionShape* tmpShape = colObj->getCollisionShape();
- //colObj->internalSetTemporaryCollisionShape( childShape );
- frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj, otherObj, dispatchInfo, resultOut);
- if (frac < hitFraction)
- {
- hitFraction = frac;
- }
- //revert back
- //colObj->internalSetTemporaryCollisionShape( tmpShape);
- colObj->setWorldTransform(orgTrans);
- }
- return hitFraction;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
deleted file mode 100644
index 4ea5e77185..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-*/
-
-#ifndef BT_COMPOUND_COLLISION_ALGORITHM_H
-#define BT_COMPOUND_COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btDispatcher;
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "btCollisionCreateFunc.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-class btDispatcher;
-class btCollisionObject;
-
-class btCollisionShape;
-typedef bool (*btShapePairCallback)(const btCollisionShape* pShape0, const btCollisionShape* pShape1);
-extern btShapePairCallback gCompoundChildShapePairCallback;
-
-/// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes
-class btCompoundCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- btNodeStack stack2;
- btManifoldArray manifoldArray;
-
-protected:
- btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
- bool m_isSwapped;
-
- class btPersistentManifold* m_sharedManifold;
- bool m_ownsManifold;
-
- int m_compoundShapeRevision; //to keep track of changes, so that childAlgorithm array can be updated
-
- void removeChildAlgorithms();
-
- void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
-public:
- btCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- virtual ~btCompoundCollisionAlgorithm();
-
- btCollisionAlgorithm* getChildAlgorithm(int n) const
- {
- return m_childCollisionAlgorithms[n];
- }
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- int i;
- for (i = 0; i < m_childCollisionAlgorithms.size(); i++)
- {
- if (m_childCollisionAlgorithms[i])
- m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
- }
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
- }
- };
-
- struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
- return new (mem) btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
- }
- };
-};
-
-#endif //BT_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
deleted file mode 100644
index 044b60dbb1..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-*/
-
-#include "btCompoundCompoundCollisionAlgorithm.h"
-#include "LinearMath/btQuickprof.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//USE_LOCAL_STACK will avoid most (often all) dynamic memory allocations due to resizing in processCollision and MycollideTT
-#define USE_LOCAL_STACK 1
-
-btShapePairCallback gCompoundCompoundChildShapePairCallback = 0;
-
-btCompoundCompoundCollisionAlgorithm::btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
- : btCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, isSwapped)
-{
- void* ptr = btAlignedAlloc(sizeof(btHashedSimplePairCache), 16);
- m_childCollisionAlgorithmCache = new (ptr) btHashedSimplePairCache();
-
- const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
- btAssert(col0ObjWrap->getCollisionShape()->isCompound());
-
- const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
- btAssert(col1ObjWrap->getCollisionShape()->isCompound());
-
- const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
- m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
-
- const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
- m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
-}
-
-btCompoundCompoundCollisionAlgorithm::~btCompoundCompoundCollisionAlgorithm()
-{
- removeChildAlgorithms();
- m_childCollisionAlgorithmCache->~btHashedSimplePairCache();
- btAlignedFree(m_childCollisionAlgorithmCache);
-}
-
-void btCompoundCompoundCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
-{
- int i;
- btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
- for (i = 0; i < pairs.size(); i++)
- {
- if (pairs[i].m_userPointer)
- {
- ((btCollisionAlgorithm*)pairs[i].m_userPointer)->getAllContactManifolds(manifoldArray);
- }
- }
-}
-
-void btCompoundCompoundCollisionAlgorithm::removeChildAlgorithms()
-{
- btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
-
- int numChildren = pairs.size();
- int i;
- for (i = 0; i < numChildren; i++)
- {
- if (pairs[i].m_userPointer)
- {
- btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
- algo->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(algo);
- }
- }
- m_childCollisionAlgorithmCache->removeAllPairs();
-}
-
-struct btCompoundCompoundLeafCallback : btDbvt::ICollide
-{
- int m_numOverlapPairs;
-
- const btCollisionObjectWrapper* m_compound0ColObjWrap;
- const btCollisionObjectWrapper* m_compound1ColObjWrap;
- btDispatcher* m_dispatcher;
- const btDispatcherInfo& m_dispatchInfo;
- btManifoldResult* m_resultOut;
-
- class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
-
- btPersistentManifold* m_sharedManifold;
-
- btCompoundCompoundLeafCallback(const btCollisionObjectWrapper* compound1ObjWrap,
- const btCollisionObjectWrapper* compound0ObjWrap,
- btDispatcher* dispatcher,
- const btDispatcherInfo& dispatchInfo,
- btManifoldResult* resultOut,
- btHashedSimplePairCache* childAlgorithmsCache,
- btPersistentManifold* sharedManifold)
- : m_numOverlapPairs(0), m_compound0ColObjWrap(compound1ObjWrap), m_compound1ColObjWrap(compound0ObjWrap), m_dispatcher(dispatcher), m_dispatchInfo(dispatchInfo), m_resultOut(resultOut), m_childCollisionAlgorithmCache(childAlgorithmsCache), m_sharedManifold(sharedManifold)
- {
- }
-
- void Process(const btDbvtNode* leaf0, const btDbvtNode* leaf1)
- {
- BT_PROFILE("btCompoundCompoundLeafCallback::Process");
- m_numOverlapPairs++;
-
- int childIndex0 = leaf0->dataAsInt;
- int childIndex1 = leaf1->dataAsInt;
-
- btAssert(childIndex0 >= 0);
- btAssert(childIndex1 >= 0);
-
- const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(m_compound0ColObjWrap->getCollisionShape());
- btAssert(childIndex0 < compoundShape0->getNumChildShapes());
-
- const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(m_compound1ColObjWrap->getCollisionShape());
- btAssert(childIndex1 < compoundShape1->getNumChildShapes());
-
- const btCollisionShape* childShape0 = compoundShape0->getChildShape(childIndex0);
- const btCollisionShape* childShape1 = compoundShape1->getChildShape(childIndex1);
-
- //backup
- btTransform orgTrans0 = m_compound0ColObjWrap->getWorldTransform();
- const btTransform& childTrans0 = compoundShape0->getChildTransform(childIndex0);
- btTransform newChildWorldTrans0 = orgTrans0 * childTrans0;
-
- btTransform orgTrans1 = m_compound1ColObjWrap->getWorldTransform();
- const btTransform& childTrans1 = compoundShape1->getChildTransform(childIndex1);
- btTransform newChildWorldTrans1 = orgTrans1 * childTrans1;
-
- //perform an AABB check first
- btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
- childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
- childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
-
- btVector3 thresholdVec(m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold, m_resultOut->m_closestPointDistanceThreshold);
-
- aabbMin0 -= thresholdVec;
- aabbMax0 += thresholdVec;
-
- if (gCompoundCompoundChildShapePairCallback)
- {
- if (!gCompoundCompoundChildShapePairCallback(childShape0, childShape1))
- return;
- }
-
- if (TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
- {
- btCollisionObjectWrapper compoundWrap0(this->m_compound0ColObjWrap, childShape0, m_compound0ColObjWrap->getCollisionObject(), newChildWorldTrans0, -1, childIndex0);
- btCollisionObjectWrapper compoundWrap1(this->m_compound1ColObjWrap, childShape1, m_compound1ColObjWrap->getCollisionObject(), newChildWorldTrans1, -1, childIndex1);
-
- btSimplePair* pair = m_childCollisionAlgorithmCache->findPair(childIndex0, childIndex1);
- bool removePair = false;
- btCollisionAlgorithm* colAlgo = 0;
- if (m_resultOut->m_closestPointDistanceThreshold > 0)
- {
- colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, 0, BT_CLOSEST_POINT_ALGORITHMS);
- removePair = true;
- }
- else
- {
- if (pair)
- {
- colAlgo = (btCollisionAlgorithm*)pair->m_userPointer;
- }
- else
- {
- colAlgo = m_dispatcher->findAlgorithm(&compoundWrap0, &compoundWrap1, m_sharedManifold, BT_CONTACT_POINT_ALGORITHMS);
- pair = m_childCollisionAlgorithmCache->addOverlappingPair(childIndex0, childIndex1);
- btAssert(pair);
- pair->m_userPointer = colAlgo;
- }
- }
-
- btAssert(colAlgo);
-
- const btCollisionObjectWrapper* tmpWrap0 = 0;
- const btCollisionObjectWrapper* tmpWrap1 = 0;
-
- tmpWrap0 = m_resultOut->getBody0Wrap();
- tmpWrap1 = m_resultOut->getBody1Wrap();
-
- m_resultOut->setBody0Wrap(&compoundWrap0);
- m_resultOut->setBody1Wrap(&compoundWrap1);
-
- m_resultOut->setShapeIdentifiersA(-1, childIndex0);
- m_resultOut->setShapeIdentifiersB(-1, childIndex1);
-
- colAlgo->processCollision(&compoundWrap0, &compoundWrap1, m_dispatchInfo, m_resultOut);
-
- m_resultOut->setBody0Wrap(tmpWrap0);
- m_resultOut->setBody1Wrap(tmpWrap1);
-
- if (removePair)
- {
- colAlgo->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(colAlgo);
- }
- }
- }
-};
-
-static DBVT_INLINE bool MyIntersect(const btDbvtAabbMm& a,
- const btDbvtAabbMm& b, const btTransform& xform, btScalar distanceThreshold)
-{
- btVector3 newmin, newmax;
- btTransformAabb(b.Mins(), b.Maxs(), 0.f, xform, newmin, newmax);
- newmin -= btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
- newmax += btVector3(distanceThreshold, distanceThreshold, distanceThreshold);
- btDbvtAabbMm newb = btDbvtAabbMm::FromMM(newmin, newmax);
- return Intersect(a, newb);
-}
-
-static inline void MycollideTT(const btDbvtNode* root0,
- const btDbvtNode* root1,
- const btTransform& xform,
- btCompoundCompoundLeafCallback* callback, btScalar distanceThreshold)
-{
- if (root0 && root1)
- {
- int depth = 1;
- int treshold = btDbvt::DOUBLE_STACKSIZE - 4;
- btAlignedObjectArray<btDbvt::sStkNN> stkStack;
-#ifdef USE_LOCAL_STACK
- ATTRIBUTE_ALIGNED16(btDbvt::sStkNN localStack[btDbvt::DOUBLE_STACKSIZE]);
- stkStack.initializeFromBuffer(&localStack, btDbvt::DOUBLE_STACKSIZE, btDbvt::DOUBLE_STACKSIZE);
-#else
- stkStack.resize(btDbvt::DOUBLE_STACKSIZE);
-#endif
- stkStack[0] = btDbvt::sStkNN(root0, root1);
- do
- {
- btDbvt::sStkNN p = stkStack[--depth];
- if (MyIntersect(p.a->volume, p.b->volume, xform, distanceThreshold))
- {
- if (depth > treshold)
- {
- stkStack.resize(stkStack.size() * 2);
- treshold = stkStack.size() - 4;
- }
- if (p.a->isinternal())
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[0]);
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[0]);
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b->childs[1]);
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b->childs[1]);
- }
- else
- {
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[0], p.b);
- stkStack[depth++] = btDbvt::sStkNN(p.a->childs[1], p.b);
- }
- }
- else
- {
- if (p.b->isinternal())
- {
- stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[0]);
- stkStack[depth++] = btDbvt::sStkNN(p.a, p.b->childs[1]);
- }
- else
- {
- callback->Process(p.a, p.b);
- }
- }
- }
- } while (depth);
- }
-}
-
-void btCompoundCompoundCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- const btCollisionObjectWrapper* col0ObjWrap = body0Wrap;
- const btCollisionObjectWrapper* col1ObjWrap = body1Wrap;
-
- btAssert(col0ObjWrap->getCollisionShape()->isCompound());
- btAssert(col1ObjWrap->getCollisionShape()->isCompound());
- const btCompoundShape* compoundShape0 = static_cast<const btCompoundShape*>(col0ObjWrap->getCollisionShape());
- const btCompoundShape* compoundShape1 = static_cast<const btCompoundShape*>(col1ObjWrap->getCollisionShape());
-
- const btDbvt* tree0 = compoundShape0->getDynamicAabbTree();
- const btDbvt* tree1 = compoundShape1->getDynamicAabbTree();
- if (!tree0 || !tree1)
- {
- return btCompoundCollisionAlgorithm::processCollision(body0Wrap, body1Wrap, dispatchInfo, resultOut);
- }
- ///btCompoundShape might have changed:
- ////make sure the internal child collision algorithm caches are still valid
- if ((compoundShape0->getUpdateRevision() != m_compoundShapeRevision0) || (compoundShape1->getUpdateRevision() != m_compoundShapeRevision1))
- {
- ///clear all
- removeChildAlgorithms();
- m_compoundShapeRevision0 = compoundShape0->getUpdateRevision();
- m_compoundShapeRevision1 = compoundShape1->getUpdateRevision();
- }
-
- ///we need to refresh all contact manifolds
- ///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
- ///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
- {
- int i;
- btManifoldArray manifoldArray;
-#ifdef USE_LOCAL_STACK
- btPersistentManifold localManifolds[4];
- manifoldArray.initializeFromBuffer(&localManifolds, 0, 4);
-#endif
- btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
- for (i = 0; i < pairs.size(); i++)
- {
- if (pairs[i].m_userPointer)
- {
- btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
- algo->getAllContactManifolds(manifoldArray);
- for (int m = 0; m < manifoldArray.size(); m++)
- {
- if (manifoldArray[m]->getNumContacts())
- {
- resultOut->setPersistentManifold(manifoldArray[m]);
- resultOut->refreshContactPoints();
- resultOut->setPersistentManifold(0);
- }
- }
- manifoldArray.resize(0);
- }
- }
- }
-
- btCompoundCompoundLeafCallback callback(col0ObjWrap, col1ObjWrap, this->m_dispatcher, dispatchInfo, resultOut, this->m_childCollisionAlgorithmCache, m_sharedManifold);
-
- const btTransform xform = col0ObjWrap->getWorldTransform().inverse() * col1ObjWrap->getWorldTransform();
- MycollideTT(tree0->m_root, tree1->m_root, xform, &callback, resultOut->m_closestPointDistanceThreshold);
-
- //printf("#compound-compound child/leaf overlap =%d \r",callback.m_numOverlapPairs);
-
- //remove non-overlapping child pairs
-
- {
- btAssert(m_removePairs.size() == 0);
-
- //iterate over all children, perform an AABB check inside ProcessChildShape
- btSimplePairArray& pairs = m_childCollisionAlgorithmCache->getOverlappingPairArray();
-
- int i;
- btManifoldArray manifoldArray;
-
- btVector3 aabbMin0, aabbMax0, aabbMin1, aabbMax1;
-
- for (i = 0; i < pairs.size(); i++)
- {
- if (pairs[i].m_userPointer)
- {
- btCollisionAlgorithm* algo = (btCollisionAlgorithm*)pairs[i].m_userPointer;
-
- {
- const btCollisionShape* childShape0 = 0;
-
- btTransform newChildWorldTrans0;
- childShape0 = compoundShape0->getChildShape(pairs[i].m_indexA);
- const btTransform& childTrans0 = compoundShape0->getChildTransform(pairs[i].m_indexA);
- newChildWorldTrans0 = col0ObjWrap->getWorldTransform() * childTrans0;
- childShape0->getAabb(newChildWorldTrans0, aabbMin0, aabbMax0);
- }
- btVector3 thresholdVec(resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold, resultOut->m_closestPointDistanceThreshold);
- aabbMin0 -= thresholdVec;
- aabbMax0 += thresholdVec;
- {
- const btCollisionShape* childShape1 = 0;
- btTransform newChildWorldTrans1;
-
- childShape1 = compoundShape1->getChildShape(pairs[i].m_indexB);
- const btTransform& childTrans1 = compoundShape1->getChildTransform(pairs[i].m_indexB);
- newChildWorldTrans1 = col1ObjWrap->getWorldTransform() * childTrans1;
- childShape1->getAabb(newChildWorldTrans1, aabbMin1, aabbMax1);
- }
-
- aabbMin1 -= thresholdVec;
- aabbMax1 += thresholdVec;
-
- if (!TestAabbAgainstAabb2(aabbMin0, aabbMax0, aabbMin1, aabbMax1))
- {
- algo->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(algo);
- m_removePairs.push_back(btSimplePair(pairs[i].m_indexA, pairs[i].m_indexB));
- }
- }
- }
- for (int i = 0; i < m_removePairs.size(); i++)
- {
- m_childCollisionAlgorithmCache->removeOverlappingPair(m_removePairs[i].m_indexA, m_removePairs[i].m_indexB);
- }
- m_removePairs.clear();
- }
-}
-
-btScalar btCompoundCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- btAssert(0);
- return 0.f;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
deleted file mode 100644
index a940d840e0..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-*/
-
-#ifndef BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
-#define BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
-
-#include "btCompoundCollisionAlgorithm.h"
-
-#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btDispatcher;
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.h"
-class btDispatcher;
-class btCollisionObject;
-
-class btCollisionShape;
-
-extern btShapePairCallback gCompoundCompoundChildShapePairCallback;
-
-/// btCompoundCompoundCollisionAlgorithm supports collision between two btCompoundCollisionShape shapes
-class btCompoundCompoundCollisionAlgorithm : public btCompoundCollisionAlgorithm
-{
- class btHashedSimplePairCache* m_childCollisionAlgorithmCache;
- btSimplePairArray m_removePairs;
-
- int m_compoundShapeRevision0; //to keep track of changes, so that childAlgorithm array can be updated
- int m_compoundShapeRevision1;
-
- void removeChildAlgorithms();
-
- // void preallocateChildAlgorithms(const btCollisionObjectWrapper* body0Wrap,const btCollisionObjectWrapper* body1Wrap);
-
-public:
- btCompoundCompoundCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- virtual ~btCompoundCompoundCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray);
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
- return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
- }
- };
-
- struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCompoundCollisionAlgorithm));
- return new (mem) btCompoundCompoundCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
- }
- };
-};
-
-#endif //BT_COMPOUND_COMPOUND_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
deleted file mode 100644
index 9087f84398..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvex2dConvex2dAlgorithm.h"
-
-//#include <stdio.h>
-#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
-{
- m_simplexSolver = simplexSolver;
- m_pdSolver = pdSolver;
-}
-
-btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc()
-{
-}
-
-btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int /* numPerturbationIterations */, int /* minimumPointsPerturbationThreshold */)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_simplexSolver(simplexSolver),
- m_pdSolver(pdSolver),
- m_ownManifold(false),
- m_manifoldPtr(mf),
- m_lowLevelOfDetail(false)
-{
- (void)body0Wrap;
- (void)body1Wrap;
-}
-
-btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
-{
- m_lowLevelOfDetail = useLowLevel;
-}
-
-extern btScalar gContactBreakingThreshold;
-
-//
-// Convex-Convex collision algorithm
-//
-void btConvex2dConvex2dAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- if (!m_manifoldPtr)
- {
- //swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
- resultOut->setPersistentManifold(m_manifoldPtr);
-
- //comment-out next line to test multi-contact generation
- //resultOut->getPersistentManifold()->clearManifold();
-
- const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
- const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
-
- btVector3 normalOnB;
- btVector3 pointOnBWorld;
-
- {
- btGjkPairDetector::ClosestPointInput input;
-
- btGjkPairDetector gjkPairDetector(min0, min1, m_simplexSolver, m_pdSolver);
- //TODO: if (dispatchInfo.m_useContinuous)
- gjkPairDetector.setMinkowskiA(min0);
- gjkPairDetector.setMinkowskiB(min1);
-
- {
- input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
- input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
- }
-
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB = body1Wrap->getWorldTransform();
-
- gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
-
- btVector3 v0, v1;
- btVector3 sepNormalWorldSpace;
- }
-
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
-}
-
-btScalar btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
-
- ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
- ///col0->m_worldTransform,
- btScalar resultFraction = btScalar(1.);
-
- btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
- btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
-
- if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
- squareMot1 < col1->getCcdSquareMotionThreshold())
- return resultFraction;
-
- //An adhoc way of testing the Continuous Collision Detection algorithms
- //One object is approximated as a sphere, to simplify things
- //Starting in penetration should report no time of impact
- //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
- //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
-
- /// Convex0 against sphere for Convex1
- {
- btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
-
- btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
- btConvexCast::CastResult result;
- btVoronoiSimplexSolver voronoiSimplex;
- //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
- ///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
- //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
- {
- //store result.m_fraction in both bodies
-
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction(result.m_fraction);
-
- if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction(result.m_fraction);
-
- if (resultFraction > result.m_fraction)
- resultFraction = result.m_fraction;
- }
- }
-
- /// Sphere (for convex0) against Convex1
- {
- btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
-
- btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
- btConvexCast::CastResult result;
- btVoronoiSimplexSolver voronoiSimplex;
- //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
- ///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
- //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
- {
- //store result.m_fraction in both bodies
-
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction(result.m_fraction);
-
- if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction(result.m_fraction);
-
- if (resultFraction > result.m_fraction)
- resultFraction = result.m_fraction;
- }
- }
-
- return resultFraction;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
deleted file mode 100644
index 9fca463fbe..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
-#define BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
-
-#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
-
-class btConvexPenetrationDepthSolver;
-
-///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
-///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
-class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
-{
- btSimplexSolverInterface* m_simplexSolver;
- btConvexPenetrationDepthSolver* m_pdSolver;
-
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_lowLevelOfDetail;
-
-public:
- btConvex2dConvex2dAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
-
- virtual ~btConvex2dConvex2dAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- ///should we use m_ownManifold to avoid adding duplicates?
- if (m_manifoldPtr && m_ownManifold)
- manifoldArray.push_back(m_manifoldPtr);
- }
-
- void setLowLevelOfDetail(bool useLowLevel);
-
- const btPersistentManifold* getManifold()
- {
- return m_manifoldPtr;
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- btConvexPenetrationDepthSolver* m_pdSolver;
- btSimplexSolverInterface* m_simplexSolver;
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
-
- CreateFunc(btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
-
- virtual ~CreateFunc();
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
- return new (mem) btConvex2dConvex2dAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_simplexSolver, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
- }
- };
-};
-
-#endif //BT_CONVEX_2D_CONVEX_2D_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
deleted file mode 100644
index e50f85e2bb..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexConcaveCollisionAlgorithm.h"
-#include "LinearMath/btQuickprof.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionShapes/btConcaveShape.h"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-#include "BulletCollision/CollisionShapes/btSdfCollisionShape.h"
-
-btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_btConvexTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped),
- m_isSwapped(isSwapped)
-{
-}
-
-btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
-{
-}
-
-void btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray& manifoldArray)
-{
- if (m_btConvexTriangleCallback.m_manifoldPtr)
- {
- manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
- }
-}
-
-btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
- m_dispatchInfoPtr(0)
-{
- m_convexBodyWrap = isSwapped ? body1Wrap : body0Wrap;
- m_triBodyWrap = isSwapped ? body0Wrap : body1Wrap;
-
- //
- // create the manifold from the dispatcher 'manifold pool'
- //
- m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBodyWrap->getCollisionObject(), m_triBodyWrap->getCollisionObject());
-
- clearCache();
-}
-
-btConvexTriangleCallback::~btConvexTriangleCallback()
-{
- clearCache();
- m_dispatcher->releaseManifold(m_manifoldPtr);
-}
-
-void btConvexTriangleCallback::clearCache()
-{
- m_dispatcher->clearManifold(m_manifoldPtr);
-}
-
-void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
-{
- BT_PROFILE("btConvexTriangleCallback::processTriangle");
-
- if (!TestTriangleAgainstAabb2(triangle, m_aabbMin, m_aabbMax))
- {
- return;
- }
-
- //just for debugging purposes
- //printf("triangle %d",m_triangleCount++);
-
- btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher1 = m_dispatcher;
-
-#if 0
-
- ///debug drawing of the overlapping triangles
- if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
- {
- const btCollisionObject* ob = const_cast<btCollisionObject*>(m_triBodyWrap->getCollisionObject());
- btVector3 color(1,1,0);
- btTransform& tr = ob->getWorldTransform();
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
- }
-#endif
-
- if (m_convexBodyWrap->getCollisionShape()->isConvex())
- {
- btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
- tm.setMargin(m_collisionMarginTriangle);
-
- btCollisionObjectWrapper triObWrap(m_triBodyWrap, &tm, m_triBodyWrap->getCollisionObject(), m_triBodyWrap->getWorldTransform(), partId, triangleIndex); //correct transform?
- btCollisionAlgorithm* colAlgo = 0;
-
- if (m_resultOut->m_closestPointDistanceThreshold > 0)
- {
- colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, 0, BT_CLOSEST_POINT_ALGORITHMS);
- }
- else
- {
- colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBodyWrap, &triObWrap, m_manifoldPtr, BT_CONTACT_POINT_ALGORITHMS);
- }
- const btCollisionObjectWrapper* tmpWrap = 0;
-
- if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
- {
- tmpWrap = m_resultOut->getBody0Wrap();
- m_resultOut->setBody0Wrap(&triObWrap);
- m_resultOut->setShapeIdentifiersA(partId, triangleIndex);
- }
- else
- {
- tmpWrap = m_resultOut->getBody1Wrap();
- m_resultOut->setBody1Wrap(&triObWrap);
- m_resultOut->setShapeIdentifiersB(partId, triangleIndex);
- }
-
- colAlgo->processCollision(m_convexBodyWrap, &triObWrap, *m_dispatchInfoPtr, m_resultOut);
-
- if (m_resultOut->getBody0Internal() == m_triBodyWrap->getCollisionObject())
- {
- m_resultOut->setBody0Wrap(tmpWrap);
- }
- else
- {
- m_resultOut->setBody1Wrap(tmpWrap);
- }
-
- colAlgo->~btCollisionAlgorithm();
- ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
- }
-}
-
-void btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut)
-{
- m_convexBodyWrap = convexBodyWrap;
- m_triBodyWrap = triBodyWrap;
-
- m_dispatchInfoPtr = &dispatchInfo;
- m_collisionMarginTriangle = collisionMarginTriangle;
- m_resultOut = resultOut;
-
- //recalc aabbs
- btTransform convexInTriangleSpace;
- convexInTriangleSpace = m_triBodyWrap->getWorldTransform().inverse() * m_convexBodyWrap->getWorldTransform();
- const btCollisionShape* convexShape = static_cast<const btCollisionShape*>(m_convexBodyWrap->getCollisionShape());
- //CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
- convexShape->getAabb(convexInTriangleSpace, m_aabbMin, m_aabbMax);
- btScalar extraMargin = collisionMarginTriangle + resultOut->m_closestPointDistanceThreshold;
-
- btVector3 extra(extraMargin, extraMargin, extraMargin);
-
- m_aabbMax += extra;
- m_aabbMin -= extra;
-}
-
-void btConvexConcaveCollisionAlgorithm::clearCache()
-{
- m_btConvexTriangleCallback.clearCache();
-}
-
-void btConvexConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- BT_PROFILE("btConvexConcaveCollisionAlgorithm::processCollision");
-
- const btCollisionObjectWrapper* convexBodyWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* triBodyWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- if (triBodyWrap->getCollisionShape()->isConcave())
- {
- if (triBodyWrap->getCollisionShape()->getShapeType() == SDF_SHAPE_PROXYTYPE)
- {
- btSdfCollisionShape* sdfShape = (btSdfCollisionShape*)triBodyWrap->getCollisionShape();
- if (convexBodyWrap->getCollisionShape()->isConvex())
- {
- btConvexShape* convex = (btConvexShape*)convexBodyWrap->getCollisionShape();
- btAlignedObjectArray<btVector3> queryVertices;
-
- if (convex->isPolyhedral())
- {
- btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
- for (int v = 0; v < poly->getNumVertices(); v++)
- {
- btVector3 vtx;
- poly->getVertex(v, vtx);
- queryVertices.push_back(vtx);
- }
- }
- btScalar maxDist = SIMD_EPSILON;
-
- if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
- {
- queryVertices.push_back(btVector3(0, 0, 0));
- btSphereShape* sphere = (btSphereShape*)convex;
- maxDist = sphere->getRadius() + SIMD_EPSILON;
- }
- if (queryVertices.size())
- {
- resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
- //m_btConvexTriangleCallback.m_manifoldPtr->clearManifold();
-
- btPolyhedralConvexShape* poly = (btPolyhedralConvexShape*)convex;
- for (int v = 0; v < queryVertices.size(); v++)
- {
- const btVector3& vtx = queryVertices[v];
- btVector3 vtxWorldSpace = convexBodyWrap->getWorldTransform() * vtx;
- btVector3 vtxInSdf = triBodyWrap->getWorldTransform().invXform(vtxWorldSpace);
-
- btVector3 normalLocal;
- btScalar dist;
- if (sdfShape->queryPoint(vtxInSdf, dist, normalLocal))
- {
- if (dist <= maxDist)
- {
- normalLocal.safeNormalize();
- btVector3 normal = triBodyWrap->getWorldTransform().getBasis() * normalLocal;
-
- if (convex->getShapeType() == SPHERE_SHAPE_PROXYTYPE)
- {
- btSphereShape* sphere = (btSphereShape*)convex;
- dist -= sphere->getRadius();
- vtxWorldSpace -= sphere->getRadius() * normal;
- }
- resultOut->addContactPoint(normal, vtxWorldSpace - normal * dist, dist);
- }
- }
- }
- resultOut->refreshContactPoints();
- }
- }
- }
- else
- {
- const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triBodyWrap->getCollisionShape());
-
- if (convexBodyWrap->getCollisionShape()->isConvex())
- {
- btScalar collisionMarginTriangle = concaveShape->getMargin();
-
- resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
- m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, dispatchInfo, convexBodyWrap, triBodyWrap, resultOut);
-
- m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBodyWrap->getCollisionObject(), triBodyWrap->getCollisionObject());
-
- concaveShape->processAllTriangles(&m_btConvexTriangleCallback, m_btConvexTriangleCallback.getAabbMin(), m_btConvexTriangleCallback.getAabbMax());
-
- resultOut->refreshContactPoints();
-
- m_btConvexTriangleCallback.clearWrapperData();
- }
- }
- }
-}
-
-btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
- btCollisionObject* triBody = m_isSwapped ? body0 : body1;
-
- //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
-
- //only perform CCD above a certain threshold, this prevents blocking on the long run
- //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
- btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
- if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
- {
- return btScalar(1.);
- }
-
- //const btVector3& from = convexbody->m_worldTransform.getOrigin();
- //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
- //todo: only do if the motion exceeds the 'radius'
-
- btTransform triInv = triBody->getWorldTransform().inverse();
- btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
- btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
-
- struct LocalTriangleSphereCastCallback : public btTriangleCallback
- {
- btTransform m_ccdSphereFromTrans;
- btTransform m_ccdSphereToTrans;
- btTransform m_meshTransform;
-
- btScalar m_ccdSphereRadius;
- btScalar m_hitFraction;
-
- LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
- : m_ccdSphereFromTrans(from),
- m_ccdSphereToTrans(to),
- m_ccdSphereRadius(ccdSphereRadius),
- m_hitFraction(hitFraction)
- {
- }
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- BT_PROFILE("processTriangle");
- (void)partId;
- (void)triangleIndex;
- //do a swept sphere for now
- btTransform ident;
- ident.setIdentity();
- btConvexCast::CastResult castResult;
- castResult.m_fraction = m_hitFraction;
- btSphereShape pointShape(m_ccdSphereRadius);
- btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
- //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
- //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
- //local space?
-
- if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
- ident, ident, castResult))
- {
- if (m_hitFraction > castResult.m_fraction)
- m_hitFraction = castResult.m_fraction;
- }
- }
- };
-
- if (triBody->getCollisionShape()->isConcave())
- {
- btVector3 rayAabbMin = convexFromLocal.getOrigin();
- rayAabbMin.setMin(convexToLocal.getOrigin());
- btVector3 rayAabbMax = convexFromLocal.getOrigin();
- rayAabbMax.setMax(convexToLocal.getOrigin());
- btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
- rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
- rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
-
- btScalar curHitFraction = btScalar(1.); //is this available?
- LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
- convexbody->getCcdSweptSphereRadius(), curHitFraction);
-
- raycastCallback.m_hitFraction = convexbody->getHitFraction();
-
- btCollisionObject* concavebody = triBody;
-
- btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
-
- if (triangleMesh)
- {
- triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
- }
-
- if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
- {
- convexbody->setHitFraction(raycastCallback.m_hitFraction);
- return raycastCallback.m_hitFraction;
- }
- }
-
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
deleted file mode 100644
index b72e402981..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
-#define BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btDispatcher;
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "btCollisionCreateFunc.h"
-
-///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
-ATTRIBUTE_ALIGNED16(class)
-btConvexTriangleCallback : public btTriangleCallback
-{
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
-
- const btCollisionObjectWrapper* m_convexBodyWrap;
- const btCollisionObjectWrapper* m_triBodyWrap;
-
- btManifoldResult* m_resultOut;
- btDispatcher* m_dispatcher;
- const btDispatcherInfo* m_dispatchInfoPtr;
- btScalar m_collisionMarginTriangle;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_triangleCount;
-
- btPersistentManifold* m_manifoldPtr;
-
- btConvexTriangleCallback(btDispatcher * dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btDispatcherInfo& dispatchInfo, const btCollisionObjectWrapper* convexBodyWrap, const btCollisionObjectWrapper* triBodyWrap, btManifoldResult* resultOut);
-
- void clearWrapperData()
- {
- m_convexBodyWrap = 0;
- m_triBodyWrap = 0;
- }
- virtual ~btConvexTriangleCallback();
-
- virtual void processTriangle(btVector3 * triangle, int partId, int triangleIndex);
-
- void clearCache();
-
- SIMD_FORCE_INLINE const btVector3& getAabbMin() const
- {
- return m_aabbMin;
- }
- SIMD_FORCE_INLINE const btVector3& getAabbMax() const
- {
- return m_aabbMax;
- }
-};
-
-/// btConvexConcaveCollisionAlgorithm supports collision between convex shapes and (concave) trianges meshes.
-ATTRIBUTE_ALIGNED16(class)
-btConvexConcaveCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- btConvexTriangleCallback m_btConvexTriangleCallback;
-
- bool m_isSwapped;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- virtual ~btConvexConcaveCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btScalar calculateTimeOfImpact(btCollisionObject * body0, btCollisionObject * body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray & manifoldArray);
-
- void clearCache();
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
- }
- };
-
- struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
- return new (mem) btConvexConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
- }
- };
-};
-
-#endif //BT_CONVEX_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
deleted file mode 100644
index b48d97f2b2..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
-///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
-///with reproduction case
-//#define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
-//#define ZERO_MARGIN
-
-#include "btConvexConvexAlgorithm.h"
-
-//#include <stdio.h>
-#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-///////////
-
-static SIMD_FORCE_INLINE void segmentsClosestPoints(
- btVector3& ptsVector,
- btVector3& offsetA,
- btVector3& offsetB,
- btScalar& tA, btScalar& tB,
- const btVector3& translation,
- const btVector3& dirA, btScalar hlenA,
- const btVector3& dirB, btScalar hlenB)
-{
- // compute the parameters of the closest points on each line segment
-
- btScalar dirA_dot_dirB = btDot(dirA, dirB);
- btScalar dirA_dot_trans = btDot(dirA, translation);
- btScalar dirB_dot_trans = btDot(dirB, translation);
-
- btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
-
- if (denom == 0.0f)
- {
- tA = 0.0f;
- }
- else
- {
- tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
-
- tB = tA * dirA_dot_dirB - dirB_dot_trans;
-
- if (tB < -hlenB)
- {
- tB = -hlenB;
- tA = tB * dirA_dot_dirB + dirA_dot_trans;
-
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
- else if (tB > hlenB)
- {
- tB = hlenB;
- tA = tB * dirA_dot_dirB + dirA_dot_trans;
-
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
-
- // compute the closest points relative to segment centers.
-
- offsetA = dirA * tA;
- offsetB = dirB * tB;
-
- ptsVector = translation - offsetA + offsetB;
-}
-
-static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
- btVector3& normalOnB,
- btVector3& pointOnB,
- btScalar capsuleLengthA,
- btScalar capsuleRadiusA,
- btScalar capsuleLengthB,
- btScalar capsuleRadiusB,
- int capsuleAxisA,
- int capsuleAxisB,
- const btTransform& transformA,
- const btTransform& transformB,
- btScalar distanceThreshold)
-{
- btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
- btVector3 translationA = transformA.getOrigin();
- btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
- btVector3 translationB = transformB.getOrigin();
-
- // translation between centers
-
- btVector3 translation = translationB - translationA;
-
- // compute the closest points of the capsule line segments
-
- btVector3 ptsVector; // the vector between the closest points
-
- btVector3 offsetA, offsetB; // offsets from segment centers to their closest points
- btScalar tA, tB; // parameters on line segment
-
- segmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB, translation,
- directionA, capsuleLengthA, directionB, capsuleLengthB);
-
- btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
-
- if (distance > distanceThreshold)
- return distance;
-
- btScalar lenSqr = ptsVector.length2();
- if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
- {
- //degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
- btVector3 q;
- btPlaneSpace1(directionA, normalOnB, q);
- }
- else
- {
- // compute the contact normal
- normalOnB = ptsVector * -btRecipSqrt(lenSqr);
- }
- pointOnB = transformB.getOrigin() + offsetB + normalOnB * capsuleRadiusB;
-
- return distance;
-}
-
-//////////
-
-btConvexConvexAlgorithm::CreateFunc::CreateFunc(btConvexPenetrationDepthSolver* pdSolver)
-{
- m_numPerturbationIterations = 0;
- m_minimumPointsPerturbationThreshold = 3;
- m_pdSolver = pdSolver;
-}
-
-btConvexConvexAlgorithm::CreateFunc::~CreateFunc()
-{
-}
-
-btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_pdSolver(pdSolver),
- m_ownManifold(false),
- m_manifoldPtr(mf),
- m_lowLevelOfDetail(false),
-#ifdef USE_SEPDISTANCE_UTIL2
- m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
- (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
-#endif
- m_numPerturbationIterations(numPerturbationIterations),
- m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
-{
- (void)body0Wrap;
- (void)body1Wrap;
-}
-
-btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
-{
- m_lowLevelOfDetail = useLowLevel;
-}
-
-struct btPerturbedContactResult : public btManifoldResult
-{
- btManifoldResult* m_originalManifoldResult;
- btTransform m_transformA;
- btTransform m_transformB;
- btTransform m_unPerturbedTransform;
- bool m_perturbA;
- btIDebugDraw* m_debugDrawer;
-
- btPerturbedContactResult(btManifoldResult* originalResult, const btTransform& transformA, const btTransform& transformB, const btTransform& unPerturbedTransform, bool perturbA, btIDebugDraw* debugDrawer)
- : m_originalManifoldResult(originalResult),
- m_transformA(transformA),
- m_transformB(transformB),
- m_unPerturbedTransform(unPerturbedTransform),
- m_perturbA(perturbA),
- m_debugDrawer(debugDrawer)
- {
- }
- virtual ~btPerturbedContactResult()
- {
- }
-
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar orgDepth)
- {
- btVector3 endPt, startPt;
- btScalar newDepth;
- btVector3 newNormal;
-
- if (m_perturbA)
- {
- btVector3 endPtOrg = pointInWorld + normalOnBInWorld * orgDepth;
- endPt = (m_unPerturbedTransform * m_transformA.inverse())(endPtOrg);
- newDepth = (endPt - pointInWorld).dot(normalOnBInWorld);
- startPt = endPt - normalOnBInWorld * newDepth;
- }
- else
- {
- endPt = pointInWorld + normalOnBInWorld * orgDepth;
- startPt = (m_unPerturbedTransform * m_transformB.inverse())(pointInWorld);
- newDepth = (endPt - startPt).dot(normalOnBInWorld);
- }
-
-//#define DEBUG_CONTACTS 1
-#ifdef DEBUG_CONTACTS
- m_debugDrawer->drawLine(startPt, endPt, btVector3(1, 0, 0));
- m_debugDrawer->drawSphere(startPt, 0.05, btVector3(0, 1, 0));
- m_debugDrawer->drawSphere(endPt, 0.05, btVector3(0, 0, 1));
-#endif //DEBUG_CONTACTS
-
- m_originalManifoldResult->addContactPoint(normalOnBInWorld, startPt, newDepth);
- }
-};
-
-extern btScalar gContactBreakingThreshold;
-
-//
-// Convex-Convex collision algorithm
-//
-void btConvexConvexAlgorithm ::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- if (!m_manifoldPtr)
- {
- //swapped?
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
- resultOut->setPersistentManifold(m_manifoldPtr);
-
- //comment-out next line to test multi-contact generation
- //resultOut->getPersistentManifold()->clearManifold();
-
- const btConvexShape* min0 = static_cast<const btConvexShape*>(body0Wrap->getCollisionShape());
- const btConvexShape* min1 = static_cast<const btConvexShape*>(body1Wrap->getCollisionShape());
-
- btVector3 normalOnB;
- btVector3 pointOnBWorld;
-#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
- if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
- {
- //m_manifoldPtr->clearManifold();
-
- btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
- btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
-
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
- capsuleB->getHalfHeight(), capsuleB->getRadius(), capsuleA->getUpAxis(), capsuleB->getUpAxis(),
- body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
-
- if (dist < threshold)
- {
- btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
- }
- resultOut->refreshContactPoints();
- return;
- }
-
- if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == SPHERE_SHAPE_PROXYTYPE))
- {
- //m_manifoldPtr->clearManifold();
-
- btCapsuleShape* capsuleA = (btCapsuleShape*)min0;
- btSphereShape* capsuleB = (btSphereShape*)min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
-
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, capsuleA->getHalfHeight(), capsuleA->getRadius(),
- 0., capsuleB->getRadius(), capsuleA->getUpAxis(), 1,
- body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
-
- if (dist < threshold)
- {
- btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
- }
- resultOut->refreshContactPoints();
- return;
- }
-
- if ((min0->getShapeType() == SPHERE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
- {
- //m_manifoldPtr->clearManifold();
-
- btSphereShape* capsuleA = (btSphereShape*)min0;
- btCapsuleShape* capsuleB = (btCapsuleShape*)min1;
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
-
- btScalar dist = capsuleCapsuleDistance(normalOnB, pointOnBWorld, 0., capsuleA->getRadius(),
- capsuleB->getHalfHeight(), capsuleB->getRadius(), 1, capsuleB->getUpAxis(),
- body0Wrap->getWorldTransform(), body1Wrap->getWorldTransform(), threshold);
-
- if (dist < threshold)
- {
- btAssert(normalOnB.length2() >= (SIMD_EPSILON * SIMD_EPSILON));
- resultOut->addContactPoint(normalOnB, pointOnBWorld, dist);
- }
- resultOut->refreshContactPoints();
- return;
- }
-#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
-
-#ifdef USE_SEPDISTANCE_UTIL2
- if (dispatchInfo.m_useConvexConservativeDistanceUtil)
- {
- m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(), body1->getWorldTransform());
- }
-
- if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance() <= 0.f)
-#endif //USE_SEPDISTANCE_UTIL2
-
- {
- btGjkPairDetector::ClosestPointInput input;
- btVoronoiSimplexSolver simplexSolver;
- btGjkPairDetector gjkPairDetector(min0, min1, &simplexSolver, m_pdSolver);
- //TODO: if (dispatchInfo.m_useContinuous)
- gjkPairDetector.setMinkowskiA(min0);
- gjkPairDetector.setMinkowskiB(min1);
-
-#ifdef USE_SEPDISTANCE_UTIL2
- if (dispatchInfo.m_useConvexConservativeDistanceUtil)
- {
- input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
- }
- else
-#endif //USE_SEPDISTANCE_UTIL2
- {
- //if (dispatchInfo.m_convexMaxDistanceUseCPT)
- //{
- // input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
- //} else
- //{
- input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold;
- // }
-
- input.m_maximumDistanceSquared *= input.m_maximumDistanceSquared;
- }
-
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB = body1Wrap->getWorldTransform();
-
-#ifdef USE_SEPDISTANCE_UTIL2
- btScalar sepDist = 0.f;
- if (dispatchInfo.m_useConvexConservativeDistanceUtil)
- {
- sepDist = gjkPairDetector.getCachedSeparatingDistance();
- if (sepDist > SIMD_EPSILON)
- {
- sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
- //now perturbe directions to get multiple contact points
- }
- }
-#endif //USE_SEPDISTANCE_UTIL2
-
- if (min0->isPolyhedral() && min1->isPolyhedral())
- {
- struct btDummyResult : public btDiscreteCollisionDetectorInterface::Result
- {
- btVector3 m_normalOnBInWorld;
- btVector3 m_pointInWorld;
- btScalar m_depth;
- bool m_hasContact;
-
- btDummyResult()
- : m_hasContact(false)
- {
- }
-
- virtual void setShapeIdentifiersA(int partId0, int index0) {}
- virtual void setShapeIdentifiersB(int partId1, int index1) {}
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- m_hasContact = true;
- m_normalOnBInWorld = normalOnBInWorld;
- m_pointInWorld = pointInWorld;
- m_depth = depth;
- }
- };
-
- struct btWithoutMarginResult : public btDiscreteCollisionDetectorInterface::Result
- {
- btDiscreteCollisionDetectorInterface::Result* m_originalResult;
- btVector3 m_reportedNormalOnWorld;
- btScalar m_marginOnA;
- btScalar m_marginOnB;
- btScalar m_reportedDistance;
-
- bool m_foundResult;
- btWithoutMarginResult(btDiscreteCollisionDetectorInterface::Result* result, btScalar marginOnA, btScalar marginOnB)
- : m_originalResult(result),
- m_marginOnA(marginOnA),
- m_marginOnB(marginOnB),
- m_foundResult(false)
- {
- }
-
- virtual void setShapeIdentifiersA(int partId0, int index0) {}
- virtual void setShapeIdentifiersB(int partId1, int index1) {}
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorldOrg, btScalar depthOrg)
- {
- m_reportedDistance = depthOrg;
- m_reportedNormalOnWorld = normalOnBInWorld;
-
- btVector3 adjustedPointB = pointInWorldOrg - normalOnBInWorld * m_marginOnB;
- m_reportedDistance = depthOrg + (m_marginOnA + m_marginOnB);
- if (m_reportedDistance < 0.f)
- {
- m_foundResult = true;
- }
- m_originalResult->addContactPoint(normalOnBInWorld, adjustedPointB, m_reportedDistance);
- }
- };
-
- btDummyResult dummy;
-
- ///btBoxShape is an exception: its vertices are created WITH margin so don't subtract it
-
- btScalar min0Margin = min0->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min0->getMargin();
- btScalar min1Margin = min1->getShapeType() == BOX_SHAPE_PROXYTYPE ? 0.f : min1->getMargin();
-
- btWithoutMarginResult withoutMargin(resultOut, min0Margin, min1Margin);
-
- btPolyhedralConvexShape* polyhedronA = (btPolyhedralConvexShape*)min0;
- btPolyhedralConvexShape* polyhedronB = (btPolyhedralConvexShape*)min1;
- if (polyhedronA->getConvexPolyhedron() && polyhedronB->getConvexPolyhedron())
- {
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
-
- btScalar minDist = -1e30f;
- btVector3 sepNormalWorldSpace;
- bool foundSepAxis = true;
-
- if (dispatchInfo.m_enableSatConvex)
- {
- foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
- *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(),
- sepNormalWorldSpace, *resultOut);
- }
- else
- {
-#ifdef ZERO_MARGIN
- gjkPairDetector.setIgnoreMargin(true);
- gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
-#else
-
- gjkPairDetector.getClosestPoints(input, withoutMargin, dispatchInfo.m_debugDraw);
- //gjkPairDetector.getClosestPoints(input,dummy,dispatchInfo.m_debugDraw);
-#endif //ZERO_MARGIN
- //btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
- //if (l2>SIMD_EPSILON)
- {
- sepNormalWorldSpace = withoutMargin.m_reportedNormalOnWorld; //gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
- //minDist = -1e30f;//gjkPairDetector.getCachedSeparatingDistance();
- minDist = withoutMargin.m_reportedDistance; //gjkPairDetector.getCachedSeparatingDistance()+min0->getMargin()+min1->getMargin();
-
-#ifdef ZERO_MARGIN
- foundSepAxis = true; //gjkPairDetector.getCachedSeparatingDistance()<0.f;
-#else
- foundSepAxis = withoutMargin.m_foundResult && minDist < 0; //-(min0->getMargin()+min1->getMargin());
-#endif
- }
- }
- if (foundSepAxis)
- {
- // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
-
- worldVertsB1.resize(0);
- btPolyhedralContactClipping::clipHullAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(), minDist - threshold, threshold, worldVertsB1, worldVertsB2,
- *resultOut);
- }
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
- return;
- }
- else
- {
- //we can also deal with convex versus triangle (without connectivity data)
- if (dispatchInfo.m_enableSatConvex && polyhedronA->getConvexPolyhedron() && polyhedronB->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE)
- {
- btVertexArray worldSpaceVertices;
- btTriangleShape* tri = (btTriangleShape*)polyhedronB;
- worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[0]);
- worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[1]);
- worldSpaceVertices.push_back(body1Wrap->getWorldTransform() * tri->m_vertices1[2]);
-
- //tri->initializePolyhedralFeatures();
-
- btScalar threshold = m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
-
- btVector3 sepNormalWorldSpace;
- btScalar minDist = -1e30f;
- btScalar maxDist = threshold;
-
- bool foundSepAxis = false;
- bool useSatSepNormal = true;
-
- if (useSatSepNormal)
- {
-#if 0
- if (0)
- {
- //initializePolyhedralFeatures performs a convex hull computation, not needed for a single triangle
- polyhedronB->initializePolyhedralFeatures();
- } else
-#endif
- {
- btVector3 uniqueEdges[3] = {tri->m_vertices1[1] - tri->m_vertices1[0],
- tri->m_vertices1[2] - tri->m_vertices1[1],
- tri->m_vertices1[0] - tri->m_vertices1[2]};
-
- uniqueEdges[0].normalize();
- uniqueEdges[1].normalize();
- uniqueEdges[2].normalize();
-
- btConvexPolyhedron polyhedron;
- polyhedron.m_vertices.push_back(tri->m_vertices1[2]);
- polyhedron.m_vertices.push_back(tri->m_vertices1[0]);
- polyhedron.m_vertices.push_back(tri->m_vertices1[1]);
-
- {
- btFace combinedFaceA;
- combinedFaceA.m_indices.push_back(0);
- combinedFaceA.m_indices.push_back(1);
- combinedFaceA.m_indices.push_back(2);
- btVector3 faceNormal = uniqueEdges[0].cross(uniqueEdges[1]);
- faceNormal.normalize();
- btScalar planeEq = 1e30f;
- for (int v = 0; v < combinedFaceA.m_indices.size(); v++)
- {
- btScalar eq = tri->m_vertices1[combinedFaceA.m_indices[v]].dot(faceNormal);
- if (planeEq > eq)
- {
- planeEq = eq;
- }
- }
- combinedFaceA.m_plane[0] = faceNormal[0];
- combinedFaceA.m_plane[1] = faceNormal[1];
- combinedFaceA.m_plane[2] = faceNormal[2];
- combinedFaceA.m_plane[3] = -planeEq;
- polyhedron.m_faces.push_back(combinedFaceA);
- }
- {
- btFace combinedFaceB;
- combinedFaceB.m_indices.push_back(0);
- combinedFaceB.m_indices.push_back(2);
- combinedFaceB.m_indices.push_back(1);
- btVector3 faceNormal = -uniqueEdges[0].cross(uniqueEdges[1]);
- faceNormal.normalize();
- btScalar planeEq = 1e30f;
- for (int v = 0; v < combinedFaceB.m_indices.size(); v++)
- {
- btScalar eq = tri->m_vertices1[combinedFaceB.m_indices[v]].dot(faceNormal);
- if (planeEq > eq)
- {
- planeEq = eq;
- }
- }
-
- combinedFaceB.m_plane[0] = faceNormal[0];
- combinedFaceB.m_plane[1] = faceNormal[1];
- combinedFaceB.m_plane[2] = faceNormal[2];
- combinedFaceB.m_plane[3] = -planeEq;
- polyhedron.m_faces.push_back(combinedFaceB);
- }
-
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[0]);
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[1]);
- polyhedron.m_uniqueEdges.push_back(uniqueEdges[2]);
- polyhedron.initialize2();
-
- polyhedronB->setPolyhedralFeatures(polyhedron);
- }
-
- foundSepAxis = btPolyhedralContactClipping::findSeparatingAxis(
- *polyhedronA->getConvexPolyhedron(), *polyhedronB->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(),
- body1Wrap->getWorldTransform(),
- sepNormalWorldSpace, *resultOut);
- // printf("sepNormalWorldSpace=%f,%f,%f\n",sepNormalWorldSpace.getX(),sepNormalWorldSpace.getY(),sepNormalWorldSpace.getZ());
- }
- else
- {
-#ifdef ZERO_MARGIN
- gjkPairDetector.setIgnoreMargin(true);
- gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
-#else
- gjkPairDetector.getClosestPoints(input, dummy, dispatchInfo.m_debugDraw);
-#endif //ZERO_MARGIN
-
- if (dummy.m_hasContact && dummy.m_depth < 0)
- {
- if (foundSepAxis)
- {
- if (dummy.m_normalOnBInWorld.dot(sepNormalWorldSpace) < 0.99)
- {
- printf("?\n");
- }
- }
- else
- {
- printf("!\n");
- }
- sepNormalWorldSpace.setValue(0, 0, 1); // = dummy.m_normalOnBInWorld;
- //minDist = dummy.m_depth;
- foundSepAxis = true;
- }
-#if 0
- btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
- if (l2>SIMD_EPSILON)
- {
- sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis()*(1.f/l2);
- //minDist = gjkPairDetector.getCachedSeparatingDistance();
- //maxDist = threshold;
- minDist = gjkPairDetector.getCachedSeparatingDistance()-min0->getMargin()-min1->getMargin();
- foundSepAxis = true;
- }
-#endif
- }
-
- if (foundSepAxis)
- {
- worldVertsB2.resize(0);
- btPolyhedralContactClipping::clipFaceAgainstHull(sepNormalWorldSpace, *polyhedronA->getConvexPolyhedron(),
- body0Wrap->getWorldTransform(), worldSpaceVertices, worldVertsB2, minDist - threshold, maxDist, *resultOut);
- }
-
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
-
- return;
- }
- }
- }
-
- gjkPairDetector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw);
-
- //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
-
- //perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
- if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
- {
- int i;
- btVector3 v0, v1;
- btVector3 sepNormalWorldSpace;
- btScalar l2 = gjkPairDetector.getCachedSeparatingAxis().length2();
-
- if (l2 > SIMD_EPSILON)
- {
- sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis() * (1.f / l2);
-
- btPlaneSpace1(sepNormalWorldSpace, v0, v1);
-
- bool perturbeA = true;
- const btScalar angleLimit = 0.125f * SIMD_PI;
- btScalar perturbeAngle;
- btScalar radiusA = min0->getAngularMotionDisc();
- btScalar radiusB = min1->getAngularMotionDisc();
- if (radiusA < radiusB)
- {
- perturbeAngle = gContactBreakingThreshold / radiusA;
- perturbeA = true;
- }
- else
- {
- perturbeAngle = gContactBreakingThreshold / radiusB;
- perturbeA = false;
- }
- if (perturbeAngle > angleLimit)
- perturbeAngle = angleLimit;
-
- btTransform unPerturbedTransform;
- if (perturbeA)
- {
- unPerturbedTransform = input.m_transformA;
- }
- else
- {
- unPerturbedTransform = input.m_transformB;
- }
-
- for (i = 0; i < m_numPerturbationIterations; i++)
- {
- if (v0.length2() > SIMD_EPSILON)
- {
- btQuaternion perturbeRot(v0, perturbeAngle);
- btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
- btQuaternion rotq(sepNormalWorldSpace, iterationAngle);
-
- if (perturbeA)
- {
- input.m_transformA.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body0Wrap->getWorldTransform().getBasis());
- input.m_transformB = body1Wrap->getWorldTransform();
-#ifdef DEBUG_CONTACTS
- dispatchInfo.m_debugDraw->drawTransform(input.m_transformA, 10.0);
-#endif //DEBUG_CONTACTS
- }
- else
- {
- input.m_transformA = body0Wrap->getWorldTransform();
- input.m_transformB.setBasis(btMatrix3x3(rotq.inverse() * perturbeRot * rotq) * body1Wrap->getWorldTransform().getBasis());
-#ifdef DEBUG_CONTACTS
- dispatchInfo.m_debugDraw->drawTransform(input.m_transformB, 10.0);
-#endif
- }
-
- btPerturbedContactResult perturbedResultOut(resultOut, input.m_transformA, input.m_transformB, unPerturbedTransform, perturbeA, dispatchInfo.m_debugDraw);
- gjkPairDetector.getClosestPoints(input, perturbedResultOut, dispatchInfo.m_debugDraw);
- }
- }
- }
- }
-
-#ifdef USE_SEPDISTANCE_UTIL2
- if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist > SIMD_EPSILON))
- {
- m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(), sepDist, body0->getWorldTransform(), body1->getWorldTransform());
- }
-#endif //USE_SEPDISTANCE_UTIL2
- }
-
- if (m_ownManifold)
- {
- resultOut->refreshContactPoints();
- }
-}
-
-bool disableCcd = false;
-btScalar btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- ///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
-
- ///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
- ///col0->m_worldTransform,
- btScalar resultFraction = btScalar(1.);
-
- btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
- btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
-
- if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
- squareMot1 < col1->getCcdSquareMotionThreshold())
- return resultFraction;
-
- if (disableCcd)
- return btScalar(1.);
-
- //An adhoc way of testing the Continuous Collision Detection algorithms
- //One object is approximated as a sphere, to simplify things
- //Starting in penetration should report no time of impact
- //For proper CCD, better accuracy and handling of 'allowed' penetration should be added
- //also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
-
- /// Convex0 against sphere for Convex1
- {
- btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
-
- btSphereShape sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
- btConvexCast::CastResult result;
- btVoronoiSimplexSolver voronoiSimplex;
- //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
- ///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(convex0, &sphere1, &voronoiSimplex);
- //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
- {
- //store result.m_fraction in both bodies
-
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction(result.m_fraction);
-
- if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction(result.m_fraction);
-
- if (resultFraction > result.m_fraction)
- resultFraction = result.m_fraction;
- }
- }
-
- /// Sphere (for convex0) against Convex1
- {
- btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
-
- btSphereShape sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
- btConvexCast::CastResult result;
- btVoronoiSimplexSolver voronoiSimplex;
- //SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
- ///Simplification, one object is simplified as a sphere
- btGjkConvexCast ccd1(&sphere0, convex1, &voronoiSimplex);
- //ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
- if (ccd1.calcTimeOfImpact(col0->getWorldTransform(), col0->getInterpolationWorldTransform(),
- col1->getWorldTransform(), col1->getInterpolationWorldTransform(), result))
- {
- //store result.m_fraction in both bodies
-
- if (col0->getHitFraction() > result.m_fraction)
- col0->setHitFraction(result.m_fraction);
-
- if (col1->getHitFraction() > result.m_fraction)
- col1->setHitFraction(result.m_fraction);
-
- if (resultFraction > result.m_fraction)
- resultFraction = result.m_fraction;
- }
- }
-
- return resultFraction;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
deleted file mode 100644
index eac5b4d824..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_CONVEX_ALGORITHM_H
-#define BT_CONVEX_CONVEX_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-#include "btCollisionCreateFunc.h"
-#include "btCollisionDispatcher.h"
-#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
-#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h"
-
-class btConvexPenetrationDepthSolver;
-
-///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise
-///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions.
-///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util
-///for certain pairs that have a small size ratio
-
-//#define USE_SEPDISTANCE_UTIL2 1
-
-///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects.
-///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal.
-///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888
-class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
-{
-#ifdef USE_SEPDISTANCE_UTIL2
- btConvexSeparatingDistanceUtil m_sepDistance;
-#endif
- btConvexPenetrationDepthSolver* m_pdSolver;
-
- btVertexArray worldVertsB1;
- btVertexArray worldVertsB2;
-
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_lowLevelOfDetail;
-
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
-
- ///cache separating vector to speedup collision detection
-
-public:
- btConvexConvexAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
-
- virtual ~btConvexConvexAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- ///should we use m_ownManifold to avoid adding duplicates?
- if (m_manifoldPtr && m_ownManifold)
- manifoldArray.push_back(m_manifoldPtr);
- }
-
- void setLowLevelOfDetail(bool useLowLevel);
-
- const btPersistentManifold* getManifold()
- {
- return m_manifoldPtr;
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- btConvexPenetrationDepthSolver* m_pdSolver;
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
-
- CreateFunc(btConvexPenetrationDepthSolver* pdSolver);
-
- virtual ~CreateFunc();
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
- return new (mem) btConvexConvexAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_pdSolver, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
- }
- };
-};
-
-#endif //BT_CONVEX_CONVEX_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
deleted file mode 100644
index ba1bc06b69..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexPlaneCollisionAlgorithm.h"
-
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//#include <stdio.h>
-
-btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold)
- : btCollisionAlgorithm(ci),
- m_ownManifold(false),
- m_manifoldPtr(mf),
- m_isSwapped(isSwapped),
- m_numPerturbationIterations(numPerturbationIterations),
- m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
-{
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
-
- if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject()))
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(convexObjWrap->getCollisionObject(), planeObjWrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btConvexPlaneCollisionAlgorithm::collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
-
- bool hasCollision = false;
- const btVector3& planeNormal = planeShape->getPlaneNormal();
- const btScalar& planeConstant = planeShape->getPlaneConstant();
-
- btTransform convexWorldTransform = convexObjWrap->getWorldTransform();
- btTransform convexInPlaneTrans;
- convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexWorldTransform;
- //now perturbe the convex-world transform
- convexWorldTransform.getBasis() *= btMatrix3x3(perturbeRot);
- btTransform planeInConvex;
- planeInConvex = convexWorldTransform.inverse() * planeObjWrap->getWorldTransform();
-
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
-
- btVector3 vtxInPlane = convexInPlaneTrans(vtx);
- btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
-
- btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
- btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
-
- hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
- resultOut->setPersistentManifold(m_manifoldPtr);
- if (hasCollision)
- {
- /// report a contact. internally this will be kept persistent, and contact reduction is done
- btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
- btVector3 pOnB = vtxInPlaneWorld;
- resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
- }
-}
-
-void btConvexPlaneCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)dispatchInfo;
- if (!m_manifoldPtr)
- return;
-
- const btCollisionObjectWrapper* convexObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* planeObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- btConvexShape* convexShape = (btConvexShape*)convexObjWrap->getCollisionShape();
- btStaticPlaneShape* planeShape = (btStaticPlaneShape*)planeObjWrap->getCollisionShape();
-
- bool hasCollision = false;
- const btVector3& planeNormal = planeShape->getPlaneNormal();
- const btScalar& planeConstant = planeShape->getPlaneConstant();
- btTransform planeInConvex;
- planeInConvex = convexObjWrap->getWorldTransform().inverse() * planeObjWrap->getWorldTransform();
- btTransform convexInPlaneTrans;
- convexInPlaneTrans = planeObjWrap->getWorldTransform().inverse() * convexObjWrap->getWorldTransform();
-
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
- btVector3 vtxInPlane = convexInPlaneTrans(vtx);
- btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
-
- btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
- btVector3 vtxInPlaneWorld = planeObjWrap->getWorldTransform() * vtxInPlaneProjected;
-
- hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold()+ resultOut->m_closestPointDistanceThreshold;
- resultOut->setPersistentManifold(m_manifoldPtr);
- if (hasCollision)
- {
- /// report a contact. internally this will be kept persistent, and contact reduction is done
- btVector3 normalOnSurfaceB = planeObjWrap->getWorldTransform().getBasis() * planeNormal;
- btVector3 pOnB = vtxInPlaneWorld;
- resultOut->addContactPoint(normalOnSurfaceB, pOnB, distance);
- }
-
- //the perturbation algorithm doesn't work well with implicit surfaces such as spheres, cylinder and cones:
- //they keep on rolling forever because of the additional off-center contact points
- //so only enable the feature for polyhedral shapes (btBoxShape, btConvexHullShape etc)
- if (convexShape->isPolyhedral() && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
- {
- btVector3 v0, v1;
- btPlaneSpace1(planeNormal, v0, v1);
- //now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
-
- const btScalar angleLimit = 0.125f * SIMD_PI;
- btScalar perturbeAngle;
- btScalar radius = convexShape->getAngularMotionDisc();
- perturbeAngle = gContactBreakingThreshold / radius;
- if (perturbeAngle > angleLimit)
- perturbeAngle = angleLimit;
-
- btQuaternion perturbeRot(v0, perturbeAngle);
- for (int i = 0; i < m_numPerturbationIterations; i++)
- {
- btScalar iterationAngle = i * (SIMD_2_PI / btScalar(m_numPerturbationIterations));
- btQuaternion rotq(planeNormal, iterationAngle);
- collideSingleContact(rotq.inverse() * perturbeRot * rotq, body0Wrap, body1Wrap, dispatchInfo, resultOut);
- }
- }
-
- if (m_ownManifold)
- {
- if (m_manifoldPtr->getNumContacts())
- {
- resultOut->refreshContactPoints();
- }
- }
-}
-
-btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- (void)col0;
- (void)col1;
-
- //not yet
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
deleted file mode 100644
index b693da118f..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
-#define BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-class btPersistentManifold;
-#include "btCollisionDispatcher.h"
-
-#include "LinearMath/btVector3.h"
-
-/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
-/// Other features are frame-coherency (persistent data) and collision response.
-class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_isSwapped;
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
-
-public:
- btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
-
- virtual ~btConvexPlaneCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- void collideSingleContact(const btQuaternion& perturbeRot, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- int m_numPerturbationIterations;
- int m_minimumPointsPerturbationThreshold;
-
- CreateFunc()
- : m_numPerturbationIterations(1),
- m_minimumPointsPerturbationThreshold(0)
- {
- }
-
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
- if (!m_swapped)
- {
- return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
- }
- else
- {
- return new (mem) btConvexPlaneCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true, m_numPerturbationIterations, m_minimumPointsPerturbationThreshold);
- }
- }
- };
-};
-
-#endif //BT_CONVEX_PLANE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
deleted file mode 100644
index ef3ea9e394..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btDefaultCollisionConfiguration.h"
-
-#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.h"
-
-#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
-#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-
-#include "LinearMath/btPoolAllocator.h"
-
-btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
-//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc* stackAlloc,btPoolAllocator* persistentManifoldPool,btPoolAllocator* collisionAlgorithmPool)
-{
- void* mem = NULL;
- if (constructionInfo.m_useEpaPenetrationAlgorithm)
- {
- mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver), 16);
- m_pdSolver = new (mem) btGjkEpaPenetrationDepthSolver;
- }
- else
- {
- mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver), 16);
- m_pdSolver = new (mem) btMinkowskiPenetrationDepthSolver;
- }
-
- //default CreationFunctions, filling the m_doubleDispatch table
- mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc), 16);
- m_convexConvexCreateFunc = new (mem) btConvexConvexAlgorithm::CreateFunc(m_pdSolver);
- mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
- m_convexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc), 16);
- m_swappedConvexConcaveCreateFunc = new (mem) btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
- mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc), 16);
- m_compoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btCompoundCompoundCollisionAlgorithm::CreateFunc), 16);
- m_compoundCompoundCreateFunc = new (mem) btCompoundCompoundCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc), 16);
- m_swappedCompoundCreateFunc = new (mem) btCompoundCollisionAlgorithm::SwappedCreateFunc;
- mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc), 16);
- m_emptyCreateFunc = new (mem) btEmptyAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc), 16);
- m_sphereSphereCF = new (mem) btSphereSphereCollisionAlgorithm::CreateFunc;
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
- m_sphereBoxCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc), 16);
- m_boxSphereCF = new (mem) btSphereBoxCollisionAlgorithm::CreateFunc;
- m_boxSphereCF->m_swapped = true;
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
- mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
- m_sphereTriangleCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc), 16);
- m_triangleSphereCF = new (mem) btSphereTriangleCollisionAlgorithm::CreateFunc;
- m_triangleSphereCF->m_swapped = true;
-
- mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc), 16);
- m_boxBoxCF = new (mem) btBoxBoxCollisionAlgorithm::CreateFunc;
-
- //convex versus plane
- mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
- m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
- mem = btAlignedAlloc(sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc), 16);
- m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
- m_planeConvexCF->m_swapped = true;
-
- ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
- int maxSize = sizeof(btConvexConvexAlgorithm);
- int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
- int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
- int maxSize4 = sizeof(btCompoundCompoundCollisionAlgorithm);
-
- int collisionAlgorithmMaxElementSize = btMax(maxSize, constructionInfo.m_customCollisionAlgorithmMaxElementSize);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize3);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize4);
-
- if (constructionInfo.m_persistentManifoldPool)
- {
- m_ownsPersistentManifoldPool = false;
- m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
- }
- else
- {
- m_ownsPersistentManifoldPool = true;
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
- m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold), constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
- }
-
- collisionAlgorithmMaxElementSize = (collisionAlgorithmMaxElementSize + 16) & 0xffffffffffff0;
- if (constructionInfo.m_collisionAlgorithmPool)
- {
- m_ownsCollisionAlgorithmPool = false;
- m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
- }
- else
- {
- m_ownsCollisionAlgorithmPool = true;
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
- m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
- }
-}
-
-btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
-{
- if (m_ownsCollisionAlgorithmPool)
- {
- m_collisionAlgorithmPool->~btPoolAllocator();
- btAlignedFree(m_collisionAlgorithmPool);
- }
- if (m_ownsPersistentManifoldPool)
- {
- m_persistentManifoldPool->~btPoolAllocator();
- btAlignedFree(m_persistentManifoldPool);
- }
-
- m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_convexConvexCreateFunc);
-
- m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_convexConcaveCreateFunc);
- m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_swappedConvexConcaveCreateFunc);
-
- m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_compoundCreateFunc);
-
- m_compoundCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_compoundCompoundCreateFunc);
-
- m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_swappedCompoundCreateFunc);
-
- m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_emptyCreateFunc);
-
- m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_sphereSphereCF);
-
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_sphereBoxCF);
- m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_boxSphereCF);
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
- m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_sphereTriangleCF);
- m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_triangleSphereCF);
- m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_boxBoxCF);
-
- m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_convexPlaneCF);
- m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_planeConvexCF);
-
- m_pdSolver->~btConvexPenetrationDepthSolver();
-
- btAlignedFree(m_pdSolver);
-}
-
-btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1)
-{
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_sphereSphereCF;
- }
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
- {
- return m_sphereBoxCF;
- }
-
- if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_boxSphereCF;
- }
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
- {
- return m_sphereTriangleCF;
- }
-
- if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_triangleSphereCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
- {
- return m_convexPlaneCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
- {
- return m_planeConvexCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
- {
- return m_convexConvexCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
- {
- return m_convexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
- {
- return m_swappedConvexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_compoundCompoundCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0))
- {
- return m_compoundCreateFunc;
- }
- else
- {
- if (btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_swappedCompoundCreateFunc;
- }
- }
-
- //failed to find an algorithm
- return m_emptyCreateFunc;
-}
-
-btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
-{
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_sphereSphereCF;
- }
-#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
- {
- return m_sphereBoxCF;
- }
-
- if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_boxSphereCF;
- }
-#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
-
- if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1 == TRIANGLE_SHAPE_PROXYTYPE))
- {
- return m_sphereTriangleCF;
- }
-
- if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE) && (proxyType1 == SPHERE_SHAPE_PROXYTYPE))
- {
- return m_triangleSphereCF;
- }
-
- if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
- {
- return m_boxBoxCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
- {
- return m_convexPlaneCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
- {
- return m_planeConvexCF;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
- {
- return m_convexConvexCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
- {
- return m_convexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
- {
- return m_swappedConvexConcaveCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0) && btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_compoundCompoundCreateFunc;
- }
-
- if (btBroadphaseProxy::isCompound(proxyType0))
- {
- return m_compoundCreateFunc;
- }
- else
- {
- if (btBroadphaseProxy::isCompound(proxyType1))
- {
- return m_swappedCompoundCreateFunc;
- }
- }
-
- //failed to find an algorithm
- return m_emptyCreateFunc;
-}
-
-void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
-{
- btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*)m_convexConvexCreateFunc;
- convexConvex->m_numPerturbationIterations = numPerturbationIterations;
- convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
-}
-
-void btDefaultCollisionConfiguration::setPlaneConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
-{
- btConvexPlaneCollisionAlgorithm::CreateFunc* cpCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_convexPlaneCF;
- cpCF->m_numPerturbationIterations = numPerturbationIterations;
- cpCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
-
- btConvexPlaneCollisionAlgorithm::CreateFunc* pcCF = (btConvexPlaneCollisionAlgorithm::CreateFunc*)m_planeConvexCF;
- pcCF->m_numPerturbationIterations = numPerturbationIterations;
- pcCF->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
deleted file mode 100644
index b39a3f41de..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
-#define BT_DEFAULT_COLLISION_CONFIGURATION
-
-#include "btCollisionConfiguration.h"
-class btVoronoiSimplexSolver;
-class btConvexPenetrationDepthSolver;
-
-struct btDefaultCollisionConstructionInfo
-{
- btPoolAllocator* m_persistentManifoldPool;
- btPoolAllocator* m_collisionAlgorithmPool;
- int m_defaultMaxPersistentManifoldPoolSize;
- int m_defaultMaxCollisionAlgorithmPoolSize;
- int m_customCollisionAlgorithmMaxElementSize;
- int m_useEpaPenetrationAlgorithm;
-
- btDefaultCollisionConstructionInfo()
- : m_persistentManifoldPool(0),
- m_collisionAlgorithmPool(0),
- m_defaultMaxPersistentManifoldPoolSize(4096),
- m_defaultMaxCollisionAlgorithmPoolSize(4096),
- m_customCollisionAlgorithmMaxElementSize(0),
- m_useEpaPenetrationAlgorithm(true)
- {
- }
-};
-
-///btCollisionConfiguration allows to configure Bullet collision detection
-///stack allocator, pool memory allocators
-///@todo: describe the meaning
-class btDefaultCollisionConfiguration : public btCollisionConfiguration
-{
-protected:
- int m_persistentManifoldPoolSize;
-
- btPoolAllocator* m_persistentManifoldPool;
- bool m_ownsPersistentManifoldPool;
-
- btPoolAllocator* m_collisionAlgorithmPool;
- bool m_ownsCollisionAlgorithmPool;
-
- //default penetration depth solver
- btConvexPenetrationDepthSolver* m_pdSolver;
-
- //default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_convexConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_convexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedConvexConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_compoundCompoundCreateFunc;
-
- btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc;
- btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
- btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
- btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
- btCollisionAlgorithmCreateFunc* m_boxSphereCF;
-
- btCollisionAlgorithmCreateFunc* m_boxBoxCF;
- btCollisionAlgorithmCreateFunc* m_sphereTriangleCF;
- btCollisionAlgorithmCreateFunc* m_triangleSphereCF;
- btCollisionAlgorithmCreateFunc* m_planeConvexCF;
- btCollisionAlgorithmCreateFunc* m_convexPlaneCF;
-
-public:
- btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
-
- virtual ~btDefaultCollisionConfiguration();
-
- ///memory pools
- virtual btPoolAllocator* getPersistentManifoldPool()
- {
- return m_persistentManifoldPool;
- }
-
- virtual btPoolAllocator* getCollisionAlgorithmPool()
- {
- return m_collisionAlgorithmPool;
- }
-
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
-
- virtual btCollisionAlgorithmCreateFunc* getClosestPointsAlgorithmCreateFunc(int proxyType0, int proxyType1);
-
- ///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
- ///By default, this feature is disabled for best performance.
- ///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature.
- ///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled
- ///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
- ///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
- ///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
- void setConvexConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
-
- void setPlaneConvexMultipointIterations(int numPerturbationIterations = 3, int minimumPointsPerturbationThreshold = 3);
-};
-
-#endif //BT_DEFAULT_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
deleted file mode 100644
index 7cd41bdb33..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btEmptyCollisionAlgorithm.h"
-
-btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btCollisionAlgorithm(ci)
-{
-}
-
-void btEmptyAlgorithm::processCollision(const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, const btDispatcherInfo&, btManifoldResult*)
-{
-}
-
-btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject*, btCollisionObject*, const btDispatcherInfo&, btManifoldResult*)
-{
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
deleted file mode 100644
index 65ef83e094..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_EMPTY_ALGORITH
-#define BT_EMPTY_ALGORITH
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "btCollisionCreateFunc.h"
-#include "btCollisionDispatcher.h"
-
-#define ATTRIBUTE_ALIGNED(a)
-
-///EmptyAlgorithm is a stub for unsupported collision pairs.
-///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
-class btEmptyAlgorithm : public btCollisionAlgorithm
-{
-public:
- btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- (void)body0Wrap;
- (void)body1Wrap;
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
- return new (mem) btEmptyAlgorithm(ci);
- }
- };
-
-} ATTRIBUTE_ALIGNED(16);
-
-#endif //BT_EMPTY_ALGORITH
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
deleted file mode 100644
index 00f16fd0a8..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGhostObject.h"
-#include "btCollisionWorld.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "LinearMath/btAabbUtil2.h"
-
-btGhostObject::btGhostObject()
-{
- m_internalType = CO_GHOST_OBJECT;
-}
-
-btGhostObject::~btGhostObject()
-{
- ///btGhostObject should have been removed from the world, so no overlapping objects
- btAssert(!m_overlappingObjects.size());
-}
-
-void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
-{
- btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
- btAssert(otherObject);
- ///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
- int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index == m_overlappingObjects.size())
- {
- //not found
- m_overlappingObjects.push_back(otherObject);
- }
-}
-
-void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy)
-{
- btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
- btAssert(otherObject);
- int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index < m_overlappingObjects.size())
- {
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
- m_overlappingObjects.pop_back();
- }
-}
-
-btPairCachingGhostObject::btPairCachingGhostObject()
-{
- m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache), 16)) btHashedOverlappingPairCache();
-}
-
-btPairCachingGhostObject::~btPairCachingGhostObject()
-{
- m_hashPairCache->~btHashedOverlappingPairCache();
- btAlignedFree(m_hashPairCache);
-}
-
-void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy)
-{
- btBroadphaseProxy* actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
- btAssert(actualThisProxy);
-
- btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
- btAssert(otherObject);
- int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index == m_overlappingObjects.size())
- {
- m_overlappingObjects.push_back(otherObject);
- m_hashPairCache->addOverlappingPair(actualThisProxy, otherProxy);
- }
-}
-
-void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy1)
-{
- btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
- btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
- btAssert(actualThisProxy);
-
- btAssert(otherObject);
- int index = m_overlappingObjects.findLinearSearch(otherObject);
- if (index < m_overlappingObjects.size())
- {
- m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size() - 1];
- m_overlappingObjects.pop_back();
- m_hashPairCache->removeOverlappingPair(actualThisProxy, otherProxy, dispatcher);
- }
-}
-
-void btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
-{
- btTransform convexFromTrans, convexToTrans;
- convexFromTrans = convexFromWorld;
- convexToTrans = convexToWorld;
- btVector3 castShapeAabbMin, castShapeAabbMax;
- /* Compute AABB that encompasses angular movement */
- {
- btVector3 linVel, angVel;
- btTransformUtil::calculateVelocity(convexFromTrans, convexToTrans, 1.0, linVel, angVel);
- btTransform R;
- R.setIdentity();
- R.setRotation(convexFromTrans.getRotation());
- castShape->calculateTemporalAabb(R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
- }
-
- /// go over all objects, and if the ray intersects their aabb + cast shape aabb,
- // do a ray-shape query using convexCaster (CCD)
- int i;
- for (i = 0; i < m_overlappingObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_overlappingObjects[i];
- //only perform raycast if filterMask matches
- if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- btVector3 collisionObjectAabbMin, collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(), collisionObjectAabbMin, collisionObjectAabbMax);
- AabbExpand(collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
- btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
- btVector3 hitNormal;
- if (btRayAabb(convexFromWorld.getOrigin(), convexToWorld.getOrigin(), collisionObjectAabbMin, collisionObjectAabbMax, hitLambda, hitNormal))
- {
- btCollisionWorld::objectQuerySingle(castShape, convexFromTrans, convexToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback,
- allowedCcdPenetration);
- }
- }
- }
-}
-
-void btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
-{
- btTransform rayFromTrans;
- rayFromTrans.setIdentity();
- rayFromTrans.setOrigin(rayFromWorld);
- btTransform rayToTrans;
- rayToTrans.setIdentity();
- rayToTrans.setOrigin(rayToWorld);
-
- int i;
- for (i = 0; i < m_overlappingObjects.size(); i++)
- {
- btCollisionObject* collisionObject = m_overlappingObjects[i];
- //only perform raycast if filterMask matches
- if (resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- resultCallback);
- }
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
deleted file mode 100644
index aa7f48d5cb..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GHOST_OBJECT_H
-#define BT_GHOST_OBJECT_H
-
-#include "btCollisionObject.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
-#include "LinearMath/btAlignedAllocator.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-#include "btCollisionWorld.h"
-
-class btConvexShape;
-
-class btDispatcher;
-
-///The btGhostObject can keep track of all objects that are overlapping
-///By default, this overlap is based on the AABB
-///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
-///We plan on adding rayTest and other queries for the btGhostObject
-ATTRIBUTE_ALIGNED16(class)
-btGhostObject : public btCollisionObject
-{
-protected:
- btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
-
-public:
- btGhostObject();
-
- virtual ~btGhostObject();
-
- void convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
-
- void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const;
-
- ///this method is mainly for expert/internal use only.
- virtual void addOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btBroadphaseProxy* thisProxy = 0);
- ///this method is mainly for expert/internal use only.
- virtual void removeOverlappingObjectInternal(btBroadphaseProxy * otherProxy, btDispatcher * dispatcher, btBroadphaseProxy* thisProxy = 0);
-
- int getNumOverlappingObjects() const
- {
- return m_overlappingObjects.size();
- }
-
- btCollisionObject* getOverlappingObject(int index)
- {
- return m_overlappingObjects[index];
- }
-
- const btCollisionObject* getOverlappingObject(int index) const
- {
- return m_overlappingObjects[index];
- }
-
- btAlignedObjectArray<btCollisionObject*>& getOverlappingPairs()
- {
- return m_overlappingObjects;
- }
-
- const btAlignedObjectArray<btCollisionObject*> getOverlappingPairs() const
- {
- return m_overlappingObjects;
- }
-
- //
- // internal cast
- //
-
- static const btGhostObject* upcast(const btCollisionObject* colObj)
- {
- if (colObj->getInternalType() == CO_GHOST_OBJECT)
- return (const btGhostObject*)colObj;
- return 0;
- }
- static btGhostObject* upcast(btCollisionObject * colObj)
- {
- if (colObj->getInternalType() == CO_GHOST_OBJECT)
- return (btGhostObject*)colObj;
- return 0;
- }
-};
-
-class btPairCachingGhostObject : public btGhostObject
-{
- btHashedOverlappingPairCache* m_hashPairCache;
-
-public:
- btPairCachingGhostObject();
-
- virtual ~btPairCachingGhostObject();
-
- ///this method is mainly for expert/internal use only.
- virtual void addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy = 0);
-
- virtual void removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btDispatcher* dispatcher, btBroadphaseProxy* thisProxy = 0);
-
- btHashedOverlappingPairCache* getOverlappingPairCache()
- {
- return m_hashPairCache;
- }
-};
-
-///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
-class btGhostPairCallback : public btOverlappingPairCallback
-{
-public:
- btGhostPairCallback()
- {
- }
-
- virtual ~btGhostPairCallback()
- {
- }
-
- virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
- {
- btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
- btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
- btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
- if (ghost0)
- ghost0->addOverlappingObjectInternal(proxy1, proxy0);
- if (ghost1)
- ghost1->addOverlappingObjectInternal(proxy0, proxy1);
- return 0;
- }
-
- virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, btDispatcher* dispatcher)
- {
- btCollisionObject* colObj0 = (btCollisionObject*)proxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)proxy1->m_clientObject;
- btGhostObject* ghost0 = btGhostObject::upcast(colObj0);
- btGhostObject* ghost1 = btGhostObject::upcast(colObj1);
- if (ghost0)
- ghost0->removeOverlappingObjectInternal(proxy1, dispatcher, proxy0);
- if (ghost1)
- ghost1->removeOverlappingObjectInternal(proxy0, dispatcher, proxy1);
- return 0;
- }
-
- virtual void removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/, btDispatcher* /*dispatcher*/)
- {
- btAssert(0);
- //need to keep track of all ghost objects and call them here
- //m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
- }
-};
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
deleted file mode 100644
index b686d98d1e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btHashedSimplePairCache.h"
-
-#include <stdio.h>
-
-#ifdef BT_DEBUG_COLLISION_PAIRS
-int gOverlappingSimplePairs = 0;
-int gRemoveSimplePairs = 0;
-int gAddedSimplePairs = 0;
-int gFindSimplePairs = 0;
-#endif //BT_DEBUG_COLLISION_PAIRS
-
-btHashedSimplePairCache::btHashedSimplePairCache()
-{
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
- growTables();
-}
-
-btHashedSimplePairCache::~btHashedSimplePairCache()
-{
-}
-
-void btHashedSimplePairCache::removeAllPairs()
-{
- m_overlappingPairArray.clear();
- m_hashTable.clear();
- m_next.clear();
-
- int initialAllocatedSize = 2;
- m_overlappingPairArray.reserve(initialAllocatedSize);
- growTables();
-}
-
-btSimplePair* btHashedSimplePairCache::findPair(int indexA, int indexB)
-{
-#ifdef BT_DEBUG_COLLISION_PAIRS
- gFindSimplePairs++;
-#endif
-
- /*if (indexA > indexB)
- btSwap(indexA, indexB);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
-
- if (hash >= m_hashTable.size())
- {
- return NULL;
- }
-
- int index = m_hashTable[hash];
- while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], indexA, indexB) == false)
- {
- index = m_next[index];
- }
-
- if (index == BT_SIMPLE_NULL_PAIR)
- {
- return NULL;
- }
-
- btAssert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
-}
-
-//#include <stdio.h>
-
-void btHashedSimplePairCache::growTables()
-{
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
-
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
-
- int i;
-
- for (i = 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = BT_SIMPLE_NULL_PAIR;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = BT_SIMPLE_NULL_PAIR;
- }
-
- for (i = 0; i < curHashtableSize; i++)
- {
- const btSimplePair& pair = m_overlappingPairArray[i];
- int indexA = pair.m_indexA;
- int indexB = pair.m_indexB;
-
- int hashValue = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
-}
-
-btSimplePair* btHashedSimplePairCache::internalAddPair(int indexA, int indexB)
-{
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1)); // New hash value with new mask
-
- btSimplePair* pair = internalFindPair(indexA, indexB, hash);
- if (pair != NULL)
- {
- return pair;
- }
-
- int count = m_overlappingPairArray.size();
- int oldCapacity = m_overlappingPairArray.capacity();
- void* mem = &m_overlappingPairArray.expandNonInitializing();
-
- int newCapacity = m_overlappingPairArray.capacity();
-
- if (oldCapacity < newCapacity)
- {
- growTables();
- //hash with new capacity
- hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
- }
-
- pair = new (mem) btSimplePair(indexA, indexB);
-
- pair->m_userPointer = 0;
-
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
-
- return pair;
-}
-
-void* btHashedSimplePairCache::removeOverlappingPair(int indexA, int indexB)
-{
-#ifdef BT_DEBUG_COLLISION_PAIRS
- gRemoveSimplePairs++;
-#endif
-
- /*if (indexA > indexB)
- btSwap(indexA, indexB);*/
-
- int hash = static_cast<int>(getHash(static_cast<unsigned int>(indexA), static_cast<unsigned int>(indexB)) & (m_overlappingPairArray.capacity() - 1));
-
- btSimplePair* pair = internalFindPair(indexA, indexB, hash);
- if (pair == NULL)
- {
- return 0;
- }
-
- void* userData = pair->m_userPointer;
-
- int pairIndex = int(pair - &m_overlappingPairArray[0]);
- btAssert(pairIndex < m_overlappingPairArray.size());
-
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- btAssert(index != BT_SIMPLE_NULL_PAIR);
-
- int previous = BT_SIMPLE_NULL_PAIR;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_SIMPLE_NULL_PAIR)
- {
- btAssert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
-
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
-
- int lastPairIndex = m_overlappingPairArray.size() - 1;
-
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_overlappingPairArray.pop_back();
- return userData;
- }
-
- // Remove the last pair from the hash table.
- const btSimplePair* last = &m_overlappingPairArray[lastPairIndex];
- /* missing swap here too, Nat. */
- int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_indexA), static_cast<unsigned int>(last->m_indexB)) & (m_overlappingPairArray.capacity() - 1));
-
- index = m_hashTable[lastHash];
- btAssert(index != BT_SIMPLE_NULL_PAIR);
-
- previous = BT_SIMPLE_NULL_PAIR;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_SIMPLE_NULL_PAIR)
- {
- btAssert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
-
- // Copy the last pair into the remove pair's spot.
- m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
-
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
-
- m_overlappingPairArray.pop_back();
-
- return userData;
-}
-//#include <stdio.h>
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
deleted file mode 100644
index fd38a4f0e1..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btHashedSimplePairCache.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_HASHED_SIMPLE_PAIR_CACHE_H
-#define BT_HASHED_SIMPLE_PAIR_CACHE_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-
-const int BT_SIMPLE_NULL_PAIR = 0xffffffff;
-
-struct btSimplePair
-{
- btSimplePair(int indexA, int indexB)
- : m_indexA(indexA),
- m_indexB(indexB),
- m_userPointer(0)
- {
- }
-
- int m_indexA;
- int m_indexB;
- union {
- void* m_userPointer;
- int m_userValue;
- };
-};
-
-typedef btAlignedObjectArray<btSimplePair> btSimplePairArray;
-
-#ifdef BT_DEBUG_COLLISION_PAIRS
-extern int gOverlappingSimplePairs;
-extern int gRemoveSimplePairs;
-extern int gAddedSimplePairs;
-extern int gFindSimplePairs;
-#endif //BT_DEBUG_COLLISION_PAIRS
-
-class btHashedSimplePairCache
-{
- btSimplePairArray m_overlappingPairArray;
-
-protected:
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
-
-public:
- btHashedSimplePairCache();
- virtual ~btHashedSimplePairCache();
-
- void removeAllPairs();
-
- virtual void* removeOverlappingPair(int indexA, int indexB);
-
- // Add a pair and return the new pair. If the pair already exists,
- // no new pair is created and the old one is returned.
- virtual btSimplePair* addOverlappingPair(int indexA, int indexB)
- {
-#ifdef BT_DEBUG_COLLISION_PAIRS
- gAddedSimplePairs++;
-#endif
-
- return internalAddPair(indexA, indexB);
- }
-
- virtual btSimplePair* getOverlappingPairArrayPtr()
- {
- return &m_overlappingPairArray[0];
- }
-
- const btSimplePair* getOverlappingPairArrayPtr() const
- {
- return &m_overlappingPairArray[0];
- }
-
- btSimplePairArray& getOverlappingPairArray()
- {
- return m_overlappingPairArray;
- }
-
- const btSimplePairArray& getOverlappingPairArray() const
- {
- return m_overlappingPairArray;
- }
-
- btSimplePair* findPair(int indexA, int indexB);
-
- int GetCount() const { return m_overlappingPairArray.size(); }
-
- int getNumOverlappingPairs() const
- {
- return m_overlappingPairArray.size();
- }
-
-private:
- btSimplePair* internalAddPair(int indexA, int indexB);
-
- void growTables();
-
- SIMD_FORCE_INLINE bool equalsPair(const btSimplePair& pair, int indexA, int indexB)
- {
- return pair.m_indexA == indexA && pair.m_indexB == indexB;
- }
-
- SIMD_FORCE_INLINE unsigned int getHash(unsigned int indexA, unsigned int indexB)
- {
- unsigned int key = indexA | (indexB << 16);
- // Thomas Wang's hash
-
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-
- SIMD_FORCE_INLINE btSimplePair* internalFindPair(int proxyIdA, int proxyIdB, int hash)
- {
- int index = m_hashTable[hash];
-
- while (index != BT_SIMPLE_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyIdA, proxyIdB) == false)
- {
- index = m_next[index];
- }
-
- if (index == BT_SIMPLE_NULL_PAIR)
- {
- return NULL;
- }
-
- btAssert(index < m_overlappingPairArray.size());
-
- return &m_overlappingPairArray[index];
- }
-};
-
-#endif //BT_HASHED_SIMPLE_PAIR_CACHE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
deleted file mode 100644
index a71700f58a..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
+++ /dev/null
@@ -1,900 +0,0 @@
-#include "btInternalEdgeUtility.h"
-
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h"
-
-#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//#define DEBUG_INTERNAL_EDGE
-
-#ifdef DEBUG_INTERNAL_EDGE
-#include <stdio.h>
-#endif //DEBUG_INTERNAL_EDGE
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
-static btIDebugDraw* gDebugDrawer = 0;
-
-void btSetDebugDrawer(btIDebugDraw* debugDrawer)
-{
- gDebugDrawer = debugDrawer;
-}
-
-static void btDebugDrawLine(const btVector3& from, const btVector3& to, const btVector3& color)
-{
- if (gDebugDrawer)
- gDebugDrawer->drawLine(from, to, color);
-}
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-static int btGetHash(int partId, int triangleIndex)
-{
- int hash = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
- return hash;
-}
-
-static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA, const btVector3& normalB)
-{
- const btVector3 refAxis0 = edgeA;
- const btVector3 refAxis1 = normalA;
- const btVector3 swingAxis = normalB;
- btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
- return angle;
-}
-
-struct btConnectivityProcessor : public btTriangleCallback
-{
- int m_partIdA;
- int m_triangleIndexA;
- btVector3* m_triangleVerticesA;
- btTriangleInfoMap* m_triangleInfoMap;
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- //skip self-collisions
- if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
- return;
-
- //skip duplicates (disabled for now)
- //if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
- // return;
-
- //search for shared vertices and edges
- int numshared = 0;
- int sharedVertsA[3] = {-1, -1, -1};
- int sharedVertsB[3] = {-1, -1, -1};
-
- ///skip degenerate triangles
- btScalar crossBSqr = ((triangle[1] - triangle[0]).cross(triangle[2] - triangle[0])).length2();
- if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
- return;
-
- btScalar crossASqr = ((m_triangleVerticesA[1] - m_triangleVerticesA[0]).cross(m_triangleVerticesA[2] - m_triangleVerticesA[0])).length2();
- ///skip degenerate triangles
- if (crossASqr < m_triangleInfoMap->m_equalVertexThreshold)
- return;
-
-#if 0
- printf("triangle A[0] = (%f,%f,%f)\ntriangle A[1] = (%f,%f,%f)\ntriangle A[2] = (%f,%f,%f)\n",
- m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
- m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
- m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
-
- printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
- printf("triangle B[0] = (%f,%f,%f)\ntriangle B[1] = (%f,%f,%f)\ntriangle B[2] = (%f,%f,%f)\n",
- triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
- triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
- triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
-#endif
-
- for (int i = 0; i < 3; i++)
- {
- for (int j = 0; j < 3; j++)
- {
- if ((m_triangleVerticesA[i] - triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
- {
- sharedVertsA[numshared] = i;
- sharedVertsB[numshared] = j;
- numshared++;
- ///degenerate case
- if (numshared >= 3)
- return;
- }
- }
- ///degenerate case
- if (numshared >= 3)
- return;
- }
- switch (numshared)
- {
- case 0:
- {
- break;
- }
- case 1:
- {
- //shared vertex
- break;
- }
- case 2:
- {
- //shared edge
- //we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
- if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
- {
- sharedVertsA[0] = 2;
- sharedVertsA[1] = 0;
- int tmp = sharedVertsB[1];
- sharedVertsB[1] = sharedVertsB[0];
- sharedVertsB[0] = tmp;
- }
-
- int hash = btGetHash(m_partIdA, m_triangleIndexA);
-
- btTriangleInfo* info = m_triangleInfoMap->find(hash);
- if (!info)
- {
- btTriangleInfo tmp;
- m_triangleInfoMap->insert(hash, tmp);
- info = m_triangleInfoMap->find(hash);
- }
-
- int sumvertsA = sharedVertsA[0] + sharedVertsA[1];
- int otherIndexA = 3 - sumvertsA;
-
- btVector3 edge(m_triangleVerticesA[sharedVertsA[1]] - m_triangleVerticesA[sharedVertsA[0]]);
-
- btTriangleShape tA(m_triangleVerticesA[0], m_triangleVerticesA[1], m_triangleVerticesA[2]);
- int otherIndexB = 3 - (sharedVertsB[0] + sharedVertsB[1]);
-
- btTriangleShape tB(triangle[sharedVertsB[1]], triangle[sharedVertsB[0]], triangle[otherIndexB]);
- //btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
-
- btVector3 normalA;
- btVector3 normalB;
- tA.calcNormal(normalA);
- tB.calcNormal(normalB);
- edge.normalize();
- btVector3 edgeCrossA = edge.cross(normalA).normalize();
-
- {
- btVector3 tmp = m_triangleVerticesA[otherIndexA] - m_triangleVerticesA[sharedVertsA[0]];
- if (edgeCrossA.dot(tmp) < 0)
- {
- edgeCrossA *= -1;
- }
- }
-
- btVector3 edgeCrossB = edge.cross(normalB).normalize();
-
- {
- btVector3 tmp = triangle[otherIndexB] - triangle[sharedVertsB[0]];
- if (edgeCrossB.dot(tmp) < 0)
- {
- edgeCrossB *= -1;
- }
- }
-
- btScalar angle2 = 0;
- btScalar ang4 = 0.f;
-
- btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
- btScalar len2 = calculatedEdge.length2();
-
- btScalar correctedAngle(0);
- //btVector3 calculatedNormalB = normalA;
- bool isConvex = false;
-
- if (len2 < m_triangleInfoMap->m_planarEpsilon)
- {
- angle2 = 0.f;
- ang4 = 0.f;
- }
- else
- {
- calculatedEdge.normalize();
- btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
- calculatedNormalA.normalize();
- angle2 = btGetAngle(calculatedNormalA, edgeCrossA, edgeCrossB);
- ang4 = SIMD_PI - angle2;
- btScalar dotA = normalA.dot(edgeCrossB);
- ///@todo: check if we need some epsilon, due to floating point imprecision
- isConvex = (dotA < 0.);
-
- correctedAngle = isConvex ? ang4 : -ang4;
- }
-
- //alternatively use
- //btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
-
- switch (sumvertsA)
- {
- case 1:
- {
- btVector3 edge = m_triangleVerticesA[0] - m_triangleVerticesA[1];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- btScalar bla = computedNormalB.dot(normalB);
- if (bla < 0)
- {
- computedNormalB *= -1;
- info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
- }
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- info->m_edgeV0V1Angle = -correctedAngle;
-
- if (isConvex)
- info->m_flags |= TRI_INFO_V0V1_CONVEX;
- break;
- }
- case 2:
- {
- btVector3 edge = m_triangleVerticesA[2] - m_triangleVerticesA[0];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- if (computedNormalB.dot(normalB) < 0)
- {
- computedNormalB *= -1;
- info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
- }
-
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
- info->m_edgeV2V0Angle = -correctedAngle;
- if (isConvex)
- info->m_flags |= TRI_INFO_V2V0_CONVEX;
- break;
- }
- case 3:
- {
- btVector3 edge = m_triangleVerticesA[1] - m_triangleVerticesA[2];
- btQuaternion orn(edge, -correctedAngle);
- btVector3 computedNormalB = quatRotate(orn, normalA);
- if (computedNormalB.dot(normalB) < 0)
- {
- info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
- computedNormalB *= -1;
- }
-#ifdef DEBUG_INTERNAL_EDGE
- if ((computedNormalB - normalB).length() > 0.0001)
- {
- printf("warning: normals not identical\n");
- }
-#endif //DEBUG_INTERNAL_EDGE
- info->m_edgeV1V2Angle = -correctedAngle;
-
- if (isConvex)
- info->m_flags |= TRI_INFO_V1V2_CONVEX;
- break;
- }
- }
-
- break;
- }
- default:
- {
- // printf("warning: duplicate triangle\n");
- }
- }
- }
-};
-
-
-struct b3ProcessAllTrianglesHeightfield: public btTriangleCallback
-{
- btHeightfieldTerrainShape* m_heightfieldShape;
- btTriangleInfoMap* m_triangleInfoMap;
-
-
- b3ProcessAllTrianglesHeightfield(btHeightfieldTerrainShape* heightFieldShape, btTriangleInfoMap* triangleInfoMap)
- :m_heightfieldShape(heightFieldShape),
- m_triangleInfoMap(triangleInfoMap)
- {
- }
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- btConnectivityProcessor connectivityProcessor;
- connectivityProcessor.m_partIdA = partId;
- connectivityProcessor.m_triangleIndexA = triangleIndex;
- connectivityProcessor.m_triangleVerticesA = triangle;
- connectivityProcessor.m_triangleInfoMap = m_triangleInfoMap;
- btVector3 aabbMin, aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- m_heightfieldShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
- }
-};
-/////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////
-
-void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap)
-{
- //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
- if (trimeshShape->getTriangleInfoMap())
- return;
-
- trimeshShape->setTriangleInfoMap(triangleInfoMap);
-
- btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
- const btVector3& meshScaling = meshInterface->getScaling();
-
- for (int partId = 0; partId < meshInterface->getNumSubParts(); partId++)
- {
- const unsigned char* vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char* indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
- //PHY_ScalarType indexType=0;
-
- btVector3 triangleVerts[3];
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, partId);
- btVector3 aabbMin, aabbMax;
-
- for (int triangleIndex = 0; triangleIndex < numfaces; triangleIndex++)
- {
- unsigned int* gfxbase = (unsigned int*)(indexbase + triangleIndex * indexstride);
-
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: btAssert(0);
- }
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(
- graphicsbase[0] * meshScaling.getX(),
- graphicsbase[1] * meshScaling.getY(),
- graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
- }
- }
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- btConnectivityProcessor connectivityProcessor;
- connectivityProcessor.m_partIdA = partId;
- connectivityProcessor.m_triangleIndexA = triangleIndex;
- connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
- connectivityProcessor.m_triangleInfoMap = triangleInfoMap;
-
- trimeshShape->processAllTriangles(&connectivityProcessor, aabbMin, aabbMax);
- }
- }
-}
-
-
-void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* heightfieldShape, btTriangleInfoMap* triangleInfoMap)
-{
-
- //the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
- if (heightfieldShape->getTriangleInfoMap())
- return;
-
- heightfieldShape->setTriangleInfoMap(triangleInfoMap);
-
- //get all the triangles of the heightfield
-
- btVector3 aabbMin, aabbMax;
-
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
-
- b3ProcessAllTrianglesHeightfield processHeightfield(heightfieldShape, triangleInfoMap);
- heightfieldShape->processAllTriangles(&processHeightfield, aabbMin, aabbMax);
-
-}
-
-// Given a point and a line segment (defined by two points), compute the closest point
-// in the line. Cap the point at the endpoints of the line segment.
-void btNearestPointInLineSegment(const btVector3& point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
-{
- btVector3 lineDelta = line1 - line0;
-
- // Handle degenerate lines
- if (lineDelta.fuzzyZero())
- {
- nearestPoint = line0;
- }
- else
- {
- btScalar delta = (point - line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
-
- // Clamp the point to conform to the segment's endpoints
- if (delta < 0)
- delta = 0;
- else if (delta > 1)
- delta = 1;
-
- nearestPoint = line0 + lineDelta * delta;
- }
-}
-
-bool btClampNormal(const btVector3& edge, const btVector3& tri_normal_org, const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3& clampedLocalNormal)
-{
- btVector3 tri_normal = tri_normal_org;
- //we only have a local triangle normal, not a local contact normal -> only normal in world space...
- //either compute the current angle all in local space, or all in world space
-
- btVector3 edgeCross = edge.cross(tri_normal).normalize();
- btScalar curAngle = btGetAngle(edgeCross, tri_normal, localContactNormalOnB);
-
- if (correctedEdgeAngle < 0)
- {
- if (curAngle < correctedEdgeAngle)
- {
- btScalar diffAngle = correctedEdgeAngle - curAngle;
- btQuaternion rotation(edge, diffAngle);
- clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
- return true;
- }
- }
-
- if (correctedEdgeAngle >= 0)
- {
- if (curAngle > correctedEdgeAngle)
- {
- btScalar diffAngle = correctedEdgeAngle - curAngle;
- btQuaternion rotation(edge, diffAngle);
- clampedLocalNormal = btMatrix3x3(rotation) * localContactNormalOnB;
- return true;
- }
- }
- return false;
-}
-
-/// Changes a btManifoldPoint collision normal to the normal from the mesh.
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, const btCollisionObjectWrapper* colObj1Wrap, int partId0, int index0, int normalAdjustFlags)
-{
- //btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
- if (colObj0Wrap->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
- return;
-
-
- btTriangleInfoMap* triangleInfoMapPtr = 0;
-
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
- {
- btHeightfieldTerrainShape* heightfield = (btHeightfieldTerrainShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
- triangleInfoMapPtr = heightfield->getTriangleInfoMap();
-
-//#define USE_HEIGHTFIELD_TRIANGLES
-#ifdef USE_HEIGHTFIELD_TRIANGLES
- btVector3 newNormal = btVector3(0, 0, 1);
-
- const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
- btVector3 tri_normal;
- tri_shape->calcNormal(tri_normal);
- newNormal = tri_normal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal. (what about cp.m_distance1?)
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- return;
-#endif
- }
-
-
- btBvhTriangleMeshShape* trimesh = 0;
-
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- trimesh = ((btScaledBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape())->getChildShape();
- }
- else
- {
- if (colObj0Wrap->getCollisionObject()->getCollisionShape()->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
- {
- trimesh = (btBvhTriangleMeshShape*)colObj0Wrap->getCollisionObject()->getCollisionShape();
- }
- }
- if (trimesh)
- {
- triangleInfoMapPtr = (btTriangleInfoMap*)trimesh->getTriangleInfoMap();
- }
-
-
- if (!triangleInfoMapPtr)
- return;
-
- int hash = btGetHash(partId0, index0);
-
- btTriangleInfo* info = triangleInfoMapPtr->find(hash);
- if (!info)
- return;
-
- btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE) == 0 ? 1.f : -1.f;
-
- const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0Wrap->getCollisionShape());
- btVector3 v0, v1, v2;
- tri_shape->getVertex(0, v0);
- tri_shape->getVertex(1, v1);
- tri_shape->getVertex(2, v2);
-
- //btVector3 center = (v0+v1+v2)*btScalar(1./3.);
-
- btVector3 red(1, 0, 0), green(0, 1, 0), blue(0, 0, 1), white(1, 1, 1), black(0, 0, 0);
- btVector3 tri_normal;
- tri_shape->calcNormal(tri_normal);
-
- //btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
-
- btVector3 contact = cp.m_localPointB;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- const btTransform& tr = colObj0->getWorldTransform();
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, red);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- bool isNearEdge = false;
-
- int numConcaveEdgeHits = 0;
- int numConvexEdgeHits = 0;
-
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- localContactNormalOnB.normalize(); //is this necessary?
-
- // Get closest edge
- int bestedge = -1;
- btScalar disttobestedge = BT_LARGE_FLOAT;
- //
- // Edge 0 -> 1
- if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v0, v1, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 0;
- disttobestedge = len;
- }
- }
- // Edge 1 -> 2
- if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v1, v2, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 1;
- disttobestedge = len;
- }
- }
- // Edge 2 -> 0
- if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
- btVector3 nearest;
- btNearestPointInLineSegment(cp.m_localPointB, v2, v0, nearest);
- btScalar len = (contact - nearest).length();
- //
- if (len < disttobestedge)
- {
- bestedge = 2;
- disttobestedge = len;
- }
- }
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btVector3 upfix = tri_normal * btVector3(0.1f, 0.1f, 0.1f);
- btDebugDrawLine(tr * v0 + upfix, tr * v1 + upfix, red);
-#endif
- if (btFabs(info->m_edgeV0V1Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 0)
- {
- btVector3 edge(v0 - v1);
- isNearEdge = true;
-
- if (info->m_edgeV0V1Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
-
- btQuaternion orn(edge, info->m_edgeV0V1Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV0V1Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal. (what about cp.m_distance1?)
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
- btNearestPointInLineSegment(contact, v1, v2, nearest);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, green);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v1 + upfix, tr * v2 + upfix, green);
-#endif
-
- if (btFabs(info->m_edgeV1V2Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 1)
- {
- isNearEdge = true;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 edge(v1 - v2);
-
- isNearEdge = true;
-
- if (info->m_edgeV1V2Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX) != 0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
-
- btQuaternion orn(edge, info->m_edgeV1V2Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV1V2Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
- btNearestPointInLineSegment(contact, v2, v0, nearest);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * cp.m_localPointB, blue);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * v2 + upfix, tr * v0 + upfix, blue);
-#endif
-
- if (btFabs(info->m_edgeV2V0Angle) < triangleInfoMapPtr->m_maxEdgeAngleThreshold)
- {
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * contact, tr * (contact + cp.m_normalWorldOnB * 10), black);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btScalar len = (contact - nearest).length();
- if (len < triangleInfoMapPtr->m_edgeDistanceThreshold)
- if (bestedge == 2)
- {
- isNearEdge = true;
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 edge(v2 - v0);
-
- if (info->m_edgeV2V0Angle == btScalar(0))
- {
- numConcaveEdgeHits++;
- }
- else
- {
- bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX) != 0;
- btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
- btDebugDrawLine(tr * nearest, tr * (nearest + swapFactor * tri_normal * 10), white);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
- btVector3 nA = swapFactor * tri_normal;
- btQuaternion orn(edge, info->m_edgeV2V0Angle);
- btVector3 computedNormalB = quatRotate(orn, tri_normal);
- if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
- computedNormalB *= -1;
- btVector3 nB = swapFactor * computedNormalB;
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + tr.getBasis() * (nB * 20), red);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- btScalar NdotA = localContactNormalOnB.dot(nA);
- btScalar NdotB = localContactNormalOnB.dot(nB);
- bool backFacingNormal = (NdotA < triangleInfoMapPtr->m_convexEpsilon) && (NdotB < triangleInfoMapPtr->m_convexEpsilon);
-
- if (backFacingNormal)
- {
- numConcaveEdgeHits++;
- }
- else
- {
- numConvexEdgeHits++;
- // printf("hitting convex edge\n");
-
- btVector3 localContactNormalOnB = colObj0Wrap->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
- btVector3 clampedLocalNormal;
- bool isClamped = btClampNormal(edge, swapFactor * tri_normal, localContactNormalOnB, info->m_edgeV2V0Angle, clampedLocalNormal);
- if (isClamped)
- {
- if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED) != 0) || (clampedLocalNormal.dot(frontFacing * tri_normal) > 0))
- {
- btVector3 newNormal = colObj0Wrap->getWorldTransform().getBasis() * clampedLocalNormal;
- // cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
- cp.m_normalWorldOnB = newNormal;
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
- }
- }
- }
- }
-
-#ifdef DEBUG_INTERNAL_EDGE
- {
- btVector3 color(0, 1, 1);
- btDebugDrawLine(cp.getPositionWorldOnB(), cp.getPositionWorldOnB() + cp.m_normalWorldOnB * 10, color);
- }
-#endif //DEBUG_INTERNAL_EDGE
-
- if (isNearEdge)
- {
- if (numConcaveEdgeHits > 0)
- {
- if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED) != 0)
- {
- //fix tri_normal so it pointing the same direction as the current local contact normal
- if (tri_normal.dot(localContactNormalOnB) < 0)
- {
- tri_normal *= -1;
- }
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * tri_normal;
- }
- else
- {
- btVector3 newNormal = tri_normal * frontFacing;
- //if the tri_normal is pointing opposite direction as the current local contact normal, skip it
- btScalar d = newNormal.dot(localContactNormalOnB);
- if (d < 0)
- {
- return;
- }
- //modify the normal to be the triangle normal (or backfacing normal)
- cp.m_normalWorldOnB = colObj0Wrap->getWorldTransform().getBasis() * newNormal;
- }
-
- // Reproject collision point along normal.
- cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
- cp.m_localPointB = colObj0Wrap->getWorldTransform().invXform(cp.m_positionWorldOnB);
- }
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
deleted file mode 100644
index cc6d11c241..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
+++ /dev/null
@@ -1,44 +0,0 @@
-
-#ifndef BT_INTERNAL_EDGE_UTILITY_H
-#define BT_INTERNAL_EDGE_UTILITY_H
-
-#include "LinearMath/btHashMap.h"
-#include "LinearMath/btVector3.h"
-
-#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h"
-
-///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges.
-///See also http://code.google.com/p/bullet/issues/detail?id=27
-
-class btBvhTriangleMeshShape;
-class btCollisionObject;
-struct btCollisionObjectWrapper;
-class btManifoldPoint;
-class btIDebugDraw;
-class btHeightfieldTerrainShape;
-
-enum btInternalEdgeAdjustFlags
-{
- BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
- BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
- BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
-};
-
-///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
-void btGenerateInternalEdgeInfo(btBvhTriangleMeshShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
-
-void btGenerateInternalEdgeInfo(btHeightfieldTerrainShape* trimeshShape, btTriangleInfoMap* triangleInfoMap);
-
-///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
-///If this info map is missing, or the triangle is not store in this map, nothing will be done
-void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObjectWrapper* trimeshColObj0Wrap, const btCollisionObjectWrapper* otherColObj1Wrap, int partId0, int index0, int normalAdjustFlags = 0);
-
-///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
-///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
-//#define BT_INTERNAL_EDGE_DEBUG_DRAW
-
-#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
-void btSetDebugDrawer(btIDebugDraw* debugDrawer);
-#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
-
-#endif //BT_INTERNAL_EDGE_UTILITY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
deleted file mode 100644
index 770eb24369..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btManifoldResult.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-///This is to allow MaterialCombiner/Custom Friction/Restitution values
-ContactAddedCallback gContactAddedCallback = 0;
-
-CalculateCombinedCallback gCalculateCombinedRestitutionCallback = &btManifoldResult::calculateCombinedRestitution;
-CalculateCombinedCallback gCalculateCombinedFrictionCallback = &btManifoldResult::calculateCombinedFriction;
-CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback = &btManifoldResult::calculateCombinedRollingFriction;
-CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback = &btManifoldResult::calculateCombinedSpinningFriction;
-CalculateCombinedCallback gCalculateCombinedContactDampingCallback = &btManifoldResult::calculateCombinedContactDamping;
-CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback = &btManifoldResult::calculateCombinedContactStiffness;
-
-btScalar btManifoldResult::calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- btScalar friction = body0->getRollingFriction() * body1->getFriction() + body1->getRollingFriction() * body0->getFriction();
-
- const btScalar MAX_FRICTION = btScalar(10.);
- if (friction < -MAX_FRICTION)
- friction = -MAX_FRICTION;
- if (friction > MAX_FRICTION)
- friction = MAX_FRICTION;
- return friction;
-}
-
-btScalar btManifoldResult::calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- btScalar friction = body0->getSpinningFriction() * body1->getFriction() + body1->getSpinningFriction() * body0->getFriction();
-
- const btScalar MAX_FRICTION = btScalar(10.);
- if (friction < -MAX_FRICTION)
- friction = -MAX_FRICTION;
- if (friction > MAX_FRICTION)
- friction = MAX_FRICTION;
- return friction;
-}
-
-///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
-btScalar btManifoldResult::calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- btScalar friction = body0->getFriction() * body1->getFriction();
-
- const btScalar MAX_FRICTION = btScalar(10.);
- if (friction < -MAX_FRICTION)
- friction = -MAX_FRICTION;
- if (friction > MAX_FRICTION)
- friction = MAX_FRICTION;
- return friction;
-}
-
-btScalar btManifoldResult::calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- return body0->getRestitution() * body1->getRestitution();
-}
-
-btScalar btManifoldResult::calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- return body0->getContactDamping() + body1->getContactDamping();
-}
-
-btScalar btManifoldResult::calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- btScalar s0 = body0->getContactStiffness();
- btScalar s1 = body1->getContactStiffness();
-
- btScalar tmp0 = btScalar(1) / s0;
- btScalar tmp1 = btScalar(1) / s1;
- btScalar combinedStiffness = btScalar(1) / (tmp0 + tmp1);
- return combinedStiffness;
-}
-
-btManifoldResult::btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- : m_manifoldPtr(0),
- m_body0Wrap(body0Wrap),
- m_body1Wrap(body1Wrap)
-#ifdef DEBUG_PART_INDEX
- ,
- m_partId0(-1),
- m_partId1(-1),
- m_index0(-1),
- m_index1(-1)
-#endif //DEBUG_PART_INDEX
- ,
- m_closestPointDistanceThreshold(0)
-{
-}
-
-void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
-{
- btAssert(m_manifoldPtr);
- //order in manifold needs to match
-
- if (depth > m_manifoldPtr->getContactBreakingThreshold())
- // if (depth > m_manifoldPtr->getContactProcessingThreshold())
- return;
-
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
- bool isNewCollision = m_manifoldPtr->getNumContacts() == 0;
-
- btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
-
- btVector3 localA;
- btVector3 localB;
-
- if (isSwapped)
- {
- localA = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
- else
- {
- localA = m_body0Wrap->getCollisionObject()->getWorldTransform().invXform(pointA);
- localB = m_body1Wrap->getCollisionObject()->getWorldTransform().invXform(pointInWorld);
- }
-
- btManifoldPoint newPt(localA, localB, normalOnBInWorld, depth);
- newPt.m_positionWorldOnA = pointA;
- newPt.m_positionWorldOnB = pointInWorld;
-
- int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
-
- newPt.m_combinedFriction = gCalculateCombinedFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
- newPt.m_combinedRestitution = gCalculateCombinedRestitutionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
- newPt.m_combinedRollingFriction = gCalculateCombinedRollingFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
- newPt.m_combinedSpinningFriction = gCalculateCombinedSpinningFrictionCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
-
- if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_CONTACT_STIFFNESS_DAMPING))
- {
- newPt.m_combinedContactDamping1 = gCalculateCombinedContactDampingCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
- newPt.m_combinedContactStiffness1 = gCalculateCombinedContactStiffnessCallback(m_body0Wrap->getCollisionObject(), m_body1Wrap->getCollisionObject());
- newPt.m_contactPointFlags |= BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING;
- }
-
- if ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_HAS_FRICTION_ANCHOR))
- {
- newPt.m_contactPointFlags |= BT_CONTACT_FLAG_FRICTION_ANCHOR;
- }
-
- btPlaneSpace1(newPt.m_normalWorldOnB, newPt.m_lateralFrictionDir1, newPt.m_lateralFrictionDir2);
-
- //BP mod, store contact triangles.
- if (isSwapped)
- {
- newPt.m_partId0 = m_partId1;
- newPt.m_partId1 = m_partId0;
- newPt.m_index0 = m_index1;
- newPt.m_index1 = m_index0;
- }
- else
- {
- newPt.m_partId0 = m_partId0;
- newPt.m_partId1 = m_partId1;
- newPt.m_index0 = m_index0;
- newPt.m_index1 = m_index1;
- }
- //printf("depth=%f\n",depth);
- ///@todo, check this for any side effects
- if (insertIndex >= 0)
- {
- //const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
- m_manifoldPtr->replaceContactPoint(newPt, insertIndex);
- }
- else
- {
- insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
- }
-
- //User can override friction and/or restitution
- if (gContactAddedCallback &&
- //and if either of the two bodies requires custom material
- ((m_body0Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
- (m_body1Wrap->getCollisionObject()->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
- {
- //experimental feature info, for per-triangle material etc.
- const btCollisionObjectWrapper* obj0Wrap = isSwapped ? m_body1Wrap : m_body0Wrap;
- const btCollisionObjectWrapper* obj1Wrap = isSwapped ? m_body0Wrap : m_body1Wrap;
- (*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex), obj0Wrap, newPt.m_partId0, newPt.m_index0, obj1Wrap, newPt.m_partId1, newPt.m_index1);
- }
-
- if (gContactStartedCallback && isNewCollision)
- {
- gContactStartedCallback(m_manifoldPtr);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
deleted file mode 100644
index 6c0a2d9a43..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MANIFOLD_RESULT_H
-#define BT_MANIFOLD_RESULT_H
-
-class btCollisionObject;
-struct btCollisionObjectWrapper;
-
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btManifoldPoint;
-
-#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
-
-#include "LinearMath/btTransform.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-typedef bool (*ContactAddedCallback)(btManifoldPoint& cp, const btCollisionObjectWrapper* colObj0Wrap, int partId0, int index0, const btCollisionObjectWrapper* colObj1Wrap, int partId1, int index1);
-extern ContactAddedCallback gContactAddedCallback;
-
-//#define DEBUG_PART_INDEX 1
-
-/// These callbacks are used to customize the algorith that combine restitution, friction, damping, Stiffness
-typedef btScalar (*CalculateCombinedCallback)(const btCollisionObject* body0, const btCollisionObject* body1);
-
-extern CalculateCombinedCallback gCalculateCombinedRestitutionCallback;
-extern CalculateCombinedCallback gCalculateCombinedFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedRollingFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedSpinningFrictionCallback;
-extern CalculateCombinedCallback gCalculateCombinedContactDampingCallback;
-extern CalculateCombinedCallback gCalculateCombinedContactStiffnessCallback;
-
-///btManifoldResult is a helper class to manage contact results.
-class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
-{
-protected:
- btPersistentManifold* m_manifoldPtr;
-
- const btCollisionObjectWrapper* m_body0Wrap;
- const btCollisionObjectWrapper* m_body1Wrap;
- int m_partId0;
- int m_partId1;
- int m_index0;
- int m_index1;
-
-public:
- btManifoldResult()
- :
-#ifdef DEBUG_PART_INDEX
-
- m_partId0(-1),
- m_partId1(-1),
- m_index0(-1),
- m_index1(-1)
-#endif //DEBUG_PART_INDEX
- m_closestPointDistanceThreshold(0)
- {
- }
-
- btManifoldResult(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
- virtual ~btManifoldResult(){};
-
- void setPersistentManifold(btPersistentManifold* manifoldPtr)
- {
- m_manifoldPtr = manifoldPtr;
- }
-
- const btPersistentManifold* getPersistentManifold() const
- {
- return m_manifoldPtr;
- }
- btPersistentManifold* getPersistentManifold()
- {
- return m_manifoldPtr;
- }
-
- virtual void setShapeIdentifiersA(int partId0, int index0)
- {
- m_partId0 = partId0;
- m_index0 = index0;
- }
-
- virtual void setShapeIdentifiersB(int partId1, int index1)
- {
- m_partId1 = partId1;
- m_index1 = index1;
- }
-
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth);
-
- SIMD_FORCE_INLINE void refreshContactPoints()
- {
- btAssert(m_manifoldPtr);
- if (!m_manifoldPtr->getNumContacts())
- return;
-
- bool isSwapped = m_manifoldPtr->getBody0() != m_body0Wrap->getCollisionObject();
-
- if (isSwapped)
- {
- m_manifoldPtr->refreshContactPoints(m_body1Wrap->getCollisionObject()->getWorldTransform(), m_body0Wrap->getCollisionObject()->getWorldTransform());
- }
- else
- {
- m_manifoldPtr->refreshContactPoints(m_body0Wrap->getCollisionObject()->getWorldTransform(), m_body1Wrap->getCollisionObject()->getWorldTransform());
- }
- }
-
- const btCollisionObjectWrapper* getBody0Wrap() const
- {
- return m_body0Wrap;
- }
- const btCollisionObjectWrapper* getBody1Wrap() const
- {
- return m_body1Wrap;
- }
-
- void setBody0Wrap(const btCollisionObjectWrapper* obj0Wrap)
- {
- m_body0Wrap = obj0Wrap;
- }
-
- void setBody1Wrap(const btCollisionObjectWrapper* obj1Wrap)
- {
- m_body1Wrap = obj1Wrap;
- }
-
- const btCollisionObject* getBody0Internal() const
- {
- return m_body0Wrap->getCollisionObject();
- }
-
- const btCollisionObject* getBody1Internal() const
- {
- return m_body1Wrap->getCollisionObject();
- }
-
- btScalar m_closestPointDistanceThreshold;
-
- /// in the future we can let the user override the methods to combine restitution and friction
- static btScalar calculateCombinedRestitution(const btCollisionObject* body0, const btCollisionObject* body1);
- static btScalar calculateCombinedFriction(const btCollisionObject* body0, const btCollisionObject* body1);
- static btScalar calculateCombinedRollingFriction(const btCollisionObject* body0, const btCollisionObject* body1);
- static btScalar calculateCombinedSpinningFriction(const btCollisionObject* body0, const btCollisionObject* body1);
- static btScalar calculateCombinedContactDamping(const btCollisionObject* body0, const btCollisionObject* body1);
- static btScalar calculateCombinedContactStiffness(const btCollisionObject* body0, const btCollisionObject* body1);
-};
-
-#endif //BT_MANIFOLD_RESULT_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
deleted file mode 100644
index 327b3f076a..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btScalar.h"
-#include "btSimulationIslandManager.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-
-//#include <stdio.h>
-#include "LinearMath/btQuickprof.h"
-
-btSimulationIslandManager::btSimulationIslandManager() : m_splitIslands(true)
-{
-}
-
-btSimulationIslandManager::~btSimulationIslandManager()
-{
-}
-
-void btSimulationIslandManager::initUnionFind(int n)
-{
- m_unionFind.reset(n);
-}
-
-void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */, btCollisionWorld* colWorld)
-{
- {
- btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
- const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
- if (numOverlappingPairs)
- {
- btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
-
- for (int i = 0; i < numOverlappingPairs; i++)
- {
- const btBroadphasePair& collisionPair = pairPtr[i];
- btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
- btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
-
- if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
- ((colObj1) && ((colObj1)->mergesSimulationIslands())))
- {
- m_unionFind.unite((colObj0)->getIslandTag(),
- (colObj1)->getIslandTag());
- }
- }
- }
- }
-}
-
-#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
-void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
-{
- // put the index into m_controllers into m_tag
- int index = 0;
- {
- int i;
- for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
- {
- btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
- //Adding filtering here
- if (!collisionObject->isStaticOrKinematicObject())
- {
- collisionObject->setIslandTag(index++);
- }
- collisionObject->setCompanionId(-1);
- collisionObject->setHitFraction(btScalar(1.));
- }
- }
- // do the union find
-
- initUnionFind(index);
-
- findUnions(dispatcher, colWorld);
-}
-
-void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
-{
- // put the islandId ('find' value) into m_tag
- {
- int index = 0;
- int i;
- for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
- {
- btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
- if (!collisionObject->isStaticOrKinematicObject())
- {
- collisionObject->setIslandTag(m_unionFind.find(index));
- //Set the correct object offset in Collision Object Array
- m_unionFind.getElement(index).m_sz = i;
- collisionObject->setCompanionId(-1);
- index++;
- }
- else
- {
- collisionObject->setIslandTag(-1);
- collisionObject->setCompanionId(-2);
- }
- }
- }
-}
-
-#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
-void btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher)
-{
- initUnionFind(int(colWorld->getCollisionObjectArray().size()));
-
- // put the index into m_controllers into m_tag
- {
- int index = 0;
- int i;
- for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
- {
- btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
- collisionObject->setIslandTag(index);
- collisionObject->setCompanionId(-1);
- collisionObject->setHitFraction(btScalar(1.));
- index++;
- }
- }
- // do the union find
-
- findUnions(dispatcher, colWorld);
-}
-
-void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
-{
- // put the islandId ('find' value) into m_tag
- {
- int index = 0;
- int i;
- for (i = 0; i < colWorld->getCollisionObjectArray().size(); i++)
- {
- btCollisionObject* collisionObject = colWorld->getCollisionObjectArray()[i];
- if (!collisionObject->isStaticOrKinematicObject())
- {
- collisionObject->setIslandTag(m_unionFind.find(index));
- collisionObject->setCompanionId(-1);
- }
- else
- {
- collisionObject->setIslandTag(-1);
- collisionObject->setCompanionId(-2);
- }
- index++;
- }
- }
-}
-
-#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
-
-inline int getIslandId(const btPersistentManifold* lhs)
-{
- int islandId;
- const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
- const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
- islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
- return islandId;
-}
-
-/// function object that routes calls to operator<
-class btPersistentManifoldSortPredicate
-{
-public:
- SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
- {
- return getIslandId(lhs) < getIslandId(rhs);
- }
-};
-
-class btPersistentManifoldSortPredicateDeterministic
-{
-public:
- SIMD_FORCE_INLINE bool operator()(const btPersistentManifold* lhs, const btPersistentManifold* rhs) const
- {
- return (
- (getIslandId(lhs) < getIslandId(rhs)) || ((getIslandId(lhs) == getIslandId(rhs)) && lhs->getBody0()->getBroadphaseHandle()->m_uniqueId < rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) || ((getIslandId(lhs) == getIslandId(rhs)) && (lhs->getBody0()->getBroadphaseHandle()->m_uniqueId == rhs->getBody0()->getBroadphaseHandle()->m_uniqueId) && (lhs->getBody1()->getBroadphaseHandle()->m_uniqueId < rhs->getBody1()->getBroadphaseHandle()->m_uniqueId)));
- }
-};
-
-void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
-{
- BT_PROFILE("islandUnionFindAndQuickSort");
-
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
-
- m_islandmanifold.resize(0);
-
- //we are going to sort the unionfind array, and store the element id in the size
- //afterwards, we clean unionfind, to make sure no-one uses it anymore
-
- getUnionFind().sortIslands();
- int numElem = getUnionFind().getNumElements();
-
- int endIslandIndex = 1;
- int startIslandIndex;
-
- //update the sleeping state for bodies, if all are sleeping
- for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
- {
- int islandId = getUnionFind().getElement(startIslandIndex).m_id;
- for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
- {
- }
-
- //int numSleeping = 0;
-
- bool allSleeping = true;
-
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
-
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
- if (colObj0->getIslandTag() == islandId)
- {
- if (colObj0->getActivationState() == ACTIVE_TAG ||
- colObj0->getActivationState() == DISABLE_DEACTIVATION)
- {
- allSleeping = false;
- break;
- }
- }
- }
-
- if (allSleeping)
- {
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
-
- if (colObj0->getIslandTag() == islandId)
- {
- colObj0->setActivationState(ISLAND_SLEEPING);
- }
- }
- }
- else
- {
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
-
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
-
-
- if (colObj0->getIslandTag() == islandId)
- {
- if (colObj0->getActivationState() == ISLAND_SLEEPING)
- {
- colObj0->setActivationState(WANTS_DEACTIVATION);
- colObj0->setDeactivationTime(0.f);
- }
- }
- }
- }
- }
-
- int i;
- int maxNumManifolds = dispatcher->getNumManifolds();
-
- //#define SPLIT_ISLANDS 1
- //#ifdef SPLIT_ISLANDS
-
- //#endif //SPLIT_ISLANDS
-
- for (i = 0; i < maxNumManifolds; i++)
- {
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
- if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
- {
- if (manifold->getNumContacts() == 0)
- continue;
- }
-
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
-
- ///@todo: check sleeping conditions!
- if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
- ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
- {
- //kinematic objects don't merge islands, but wake up all connected objects
- if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj0->hasContactResponse())
- colObj1->activate();
- }
- if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj1->hasContactResponse())
- colObj0->activate();
- }
- if (m_splitIslands)
- {
- //filtering for response
- if (dispatcher->needsResponse(colObj0, colObj1))
- m_islandmanifold.push_back(manifold);
- }
- }
- }
-}
-
-
-///@todo: this is random access, it can be walked 'cache friendly'!
-void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
-{
- buildIslands(dispatcher, collisionWorld);
- processIslands(dispatcher, collisionWorld, callback);
-}
-
-void btSimulationIslandManager::processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback)
-{
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
- int endIslandIndex = 1;
- int startIslandIndex;
- int numElem = getUnionFind().getNumElements();
-
- BT_PROFILE("processIslands");
-
- if (!m_splitIslands)
- {
- btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
- int maxNumManifolds = dispatcher->getNumManifolds();
- callback->processIsland(&collisionObjects[0], collisionObjects.size(), manifold, maxNumManifolds, -1);
- }
- else
- {
- // Sort manifolds, based on islands
- // Sort the vector using predicate and std::sort
- //std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
-
- int numManifolds = int(m_islandmanifold.size());
-
- //tried a radix sort, but quicksort/heapsort seems still faster
- //@todo rewrite island management
- //btPersistentManifoldSortPredicateDeterministic sorts contact manifolds based on islandid,
- //but also based on object0 unique id and object1 unique id
- if (collisionWorld->getDispatchInfo().m_deterministicOverlappingPairs)
- {
- m_islandmanifold.quickSort(btPersistentManifoldSortPredicateDeterministic());
- }
- else
- {
- m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
- }
-
- //m_islandmanifold.heapSort(btPersistentManifoldSortPredicate());
-
- //now process all active islands (sets of manifolds for now)
-
- int startManifoldIndex = 0;
- int endManifoldIndex = 1;
-
- //int islandId;
-
- // printf("Start Islands\n");
-
- //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
- for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
- {
- int islandId = getUnionFind().getElement(startIslandIndex).m_id;
-
- bool islandSleeping = true;
-
- for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
- {
- int i = getUnionFind().getElement(endIslandIndex).m_sz;
- btCollisionObject* colObj0 = collisionObjects[i];
- m_islandBodies.push_back(colObj0);
- if (colObj0->isActive())
- islandSleeping = false;
- }
-
- //find the accompanying contact manifold for this islandId
- int numIslandManifolds = 0;
- btPersistentManifold** startManifold = 0;
-
- if (startManifoldIndex < numManifolds)
- {
- int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
- if (curIslandId == islandId)
- {
- startManifold = &m_islandmanifold[startManifoldIndex];
-
- for (endManifoldIndex = startManifoldIndex + 1; (endManifoldIndex < numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex])); endManifoldIndex++)
- {
- }
- /// Process the actual simulation, only if not sleeping/deactivated
- numIslandManifolds = endManifoldIndex - startManifoldIndex;
- }
- }
-
- if (!islandSleeping)
- {
- callback->processIsland(&m_islandBodies[0], m_islandBodies.size(), startManifold, numIslandManifolds, islandId);
- // printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
- }
-
- if (numIslandManifolds)
- {
- startManifoldIndex = endManifoldIndex;
- }
-
- m_islandBodies.resize(0);
- }
- } // else if(!splitIslands)
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
deleted file mode 100644
index 197bb457cf..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMULATION_ISLAND_MANAGER_H
-#define BT_SIMULATION_ISLAND_MANAGER_H
-
-#include "BulletCollision/CollisionDispatch/btUnionFind.h"
-#include "btCollisionCreateFunc.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "btCollisionObject.h"
-
-class btCollisionObject;
-class btCollisionWorld;
-class btDispatcher;
-class btPersistentManifold;
-
-///SimulationIslandManager creates and handles simulation islands, using btUnionFind
-class btSimulationIslandManager
-{
- btUnionFind m_unionFind;
-
- btAlignedObjectArray<btPersistentManifold*> m_islandmanifold;
- btAlignedObjectArray<btCollisionObject*> m_islandBodies;
-
- bool m_splitIslands;
-
-public:
- btSimulationIslandManager();
- virtual ~btSimulationIslandManager();
-
- void initUnionFind(int n);
-
- btUnionFind& getUnionFind() { return m_unionFind; }
-
- virtual void updateActivationState(btCollisionWorld* colWorld, btDispatcher* dispatcher);
- virtual void storeIslandActivationState(btCollisionWorld* world);
-
- void findUnions(btDispatcher* dispatcher, btCollisionWorld* colWorld);
-
- struct IslandCallback
- {
- virtual ~IslandCallback(){};
-
- virtual void processIsland(btCollisionObject** bodies, int numBodies, class btPersistentManifold** manifolds, int numManifolds, int islandId) = 0;
- };
-
- void buildAndProcessIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
-
- void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
-
- void processIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld, IslandCallback* callback);
-
- bool getSplitIslands()
- {
- return m_splitIslands;
- }
- void setSplitIslands(bool doSplitIslands)
- {
- m_splitIslands = doSplitIslands;
- }
-};
-
-#endif //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
deleted file mode 100644
index bc68b285b8..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSphereBoxCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-//#include <stdio.h>
-
-btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, bool isSwapped)
- : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
- m_ownManifold(false),
- m_manifoldPtr(mf),
- m_isSwapped(isSwapped)
-{
- const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? col0Wrap : col1Wrap;
-
- if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject()))
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(sphereObjWrap->getCollisionObject(), boxObjWrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btSphereBoxCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)dispatchInfo;
- (void)resultOut;
- if (!m_manifoldPtr)
- return;
-
- const btCollisionObjectWrapper* sphereObjWrap = m_isSwapped ? body1Wrap : body0Wrap;
- const btCollisionObjectWrapper* boxObjWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- btVector3 pOnBox;
-
- btVector3 normalOnSurfaceB;
- btScalar penetrationDepth;
- btVector3 sphereCenter = sphereObjWrap->getWorldTransform().getOrigin();
- const btSphereShape* sphere0 = (const btSphereShape*)sphereObjWrap->getCollisionShape();
- btScalar radius = sphere0->getRadius();
- btScalar maxContactDistance = m_manifoldPtr->getContactBreakingThreshold();
-
- resultOut->setPersistentManifold(m_manifoldPtr);
-
- if (getSphereDistance(boxObjWrap, pOnBox, normalOnSurfaceB, penetrationDepth, sphereCenter, radius, maxContactDistance))
- {
- /// report a contact. internally this will be kept persistent, and contact reduction is done
- resultOut->addContactPoint(normalOnSurfaceB, pOnBox, penetrationDepth);
- }
-
- if (m_ownManifold)
- {
- if (m_manifoldPtr->getNumContacts())
- {
- resultOut->refreshContactPoints();
- }
- }
-}
-
-btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- (void)col0;
- (void)col1;
-
- //not yet
- return btScalar(1.);
-}
-
-bool btSphereBoxCollisionAlgorithm::getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& pointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& sphereCenter, btScalar fRadius, btScalar maxContactDistance)
-{
- const btBoxShape* boxShape = (const btBoxShape*)boxObjWrap->getCollisionShape();
- btVector3 const& boxHalfExtent = boxShape->getHalfExtentsWithoutMargin();
- btScalar boxMargin = boxShape->getMargin();
- penetrationDepth = 1.0f;
-
- // convert the sphere position to the box's local space
- btTransform const& m44T = boxObjWrap->getWorldTransform();
- btVector3 sphereRelPos = m44T.invXform(sphereCenter);
-
- // Determine the closest point to the sphere center in the box
- btVector3 closestPoint = sphereRelPos;
- closestPoint.setX(btMin(boxHalfExtent.getX(), closestPoint.getX()));
- closestPoint.setX(btMax(-boxHalfExtent.getX(), closestPoint.getX()));
- closestPoint.setY(btMin(boxHalfExtent.getY(), closestPoint.getY()));
- closestPoint.setY(btMax(-boxHalfExtent.getY(), closestPoint.getY()));
- closestPoint.setZ(btMin(boxHalfExtent.getZ(), closestPoint.getZ()));
- closestPoint.setZ(btMax(-boxHalfExtent.getZ(), closestPoint.getZ()));
-
- btScalar intersectionDist = fRadius + boxMargin;
- btScalar contactDist = intersectionDist + maxContactDistance;
- normal = sphereRelPos - closestPoint;
-
- //if there is no penetration, we are done
- btScalar dist2 = normal.length2();
- if (dist2 > contactDist * contactDist)
- {
- return false;
- }
-
- btScalar distance;
-
- //special case if the sphere center is inside the box
- if (dist2 <= SIMD_EPSILON)
- {
- distance = -getSpherePenetration(boxHalfExtent, sphereRelPos, closestPoint, normal);
- }
- else //compute the penetration details
- {
- distance = normal.length();
- normal /= distance;
- }
-
- pointOnBox = closestPoint + normal * boxMargin;
- // v3PointOnSphere = sphereRelPos - (normal * fRadius);
- penetrationDepth = distance - intersectionDist;
-
- // transform back in world space
- btVector3 tmp = m44T(pointOnBox);
- pointOnBox = tmp;
- // tmp = m44T(v3PointOnSphere);
- // v3PointOnSphere = tmp;
- tmp = m44T.getBasis() * normal;
- normal = tmp;
-
- return true;
-}
-
-btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal)
-{
- //project the center of the sphere on the closest face of the box
- btScalar faceDist = boxHalfExtent.getX() - sphereRelPos.getX();
- btScalar minDist = faceDist;
- closestPoint.setX(boxHalfExtent.getX());
- normal.setValue(btScalar(1.0f), btScalar(0.0f), btScalar(0.0f));
-
- faceDist = boxHalfExtent.getX() + sphereRelPos.getX();
- if (faceDist < minDist)
- {
- minDist = faceDist;
- closestPoint = sphereRelPos;
- closestPoint.setX(-boxHalfExtent.getX());
- normal.setValue(btScalar(-1.0f), btScalar(0.0f), btScalar(0.0f));
- }
-
- faceDist = boxHalfExtent.getY() - sphereRelPos.getY();
- if (faceDist < minDist)
- {
- minDist = faceDist;
- closestPoint = sphereRelPos;
- closestPoint.setY(boxHalfExtent.getY());
- normal.setValue(btScalar(0.0f), btScalar(1.0f), btScalar(0.0f));
- }
-
- faceDist = boxHalfExtent.getY() + sphereRelPos.getY();
- if (faceDist < minDist)
- {
- minDist = faceDist;
- closestPoint = sphereRelPos;
- closestPoint.setY(-boxHalfExtent.getY());
- normal.setValue(btScalar(0.0f), btScalar(-1.0f), btScalar(0.0f));
- }
-
- faceDist = boxHalfExtent.getZ() - sphereRelPos.getZ();
- if (faceDist < minDist)
- {
- minDist = faceDist;
- closestPoint = sphereRelPos;
- closestPoint.setZ(boxHalfExtent.getZ());
- normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f));
- }
-
- faceDist = boxHalfExtent.getZ() + sphereRelPos.getZ();
- if (faceDist < minDist)
- {
- minDist = faceDist;
- closestPoint = sphereRelPos;
- closestPoint.setZ(-boxHalfExtent.getZ());
- normal.setValue(btScalar(0.0f), btScalar(0.0f), btScalar(-1.0f));
- }
-
- return minDist;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
deleted file mode 100644
index 3348bc89af..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SPHERE_BOX_COLLISION_ALGORITHM_H
-#define BT_SPHERE_BOX_COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-class btPersistentManifold;
-#include "btCollisionDispatcher.h"
-
-#include "LinearMath/btVector3.h"
-
-/// btSphereBoxCollisionAlgorithm provides sphere-box collision detection.
-/// Other features are frame-coherency (persistent data) and collision response.
-class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_isSwapped;
-
-public:
- btSphereBoxCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- virtual ~btSphereBoxCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- bool getSphereDistance(const btCollisionObjectWrapper* boxObjWrap, btVector3& v3PointOnBox, btVector3& normal, btScalar& penetrationDepth, const btVector3& v3SphereCenter, btScalar fRadius, btScalar maxContactDistance);
-
- btScalar getSpherePenetration(btVector3 const& boxHalfExtent, btVector3 const& sphereRelPos, btVector3& closestPoint, btVector3& normal);
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
- if (!m_swapped)
- {
- return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
- }
- else
- {
- return new (mem) btSphereBoxCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
- }
- }
- };
-};
-
-#endif //BT_SPHERE_BOX_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
deleted file mode 100644
index 7fa0559f97..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#define CLEAR_MANIFOLD 1
-
-#include "btSphereSphereCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
- : btActivatingCollisionAlgorithm(ci, col0Wrap, col1Wrap),
- m_ownManifold(false),
- m_manifoldPtr(mf)
-{
- if (!m_manifoldPtr)
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(col0Wrap->getCollisionObject(), col1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btSphereSphereCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)dispatchInfo;
-
- if (!m_manifoldPtr)
- return;
-
- resultOut->setPersistentManifold(m_manifoldPtr);
-
- btSphereShape* sphere0 = (btSphereShape*)col0Wrap->getCollisionShape();
- btSphereShape* sphere1 = (btSphereShape*)col1Wrap->getCollisionShape();
-
- btVector3 diff = col0Wrap->getWorldTransform().getOrigin() - col1Wrap->getWorldTransform().getOrigin();
- btScalar len = diff.length();
- btScalar radius0 = sphere0->getRadius();
- btScalar radius1 = sphere1->getRadius();
-
-#ifdef CLEAR_MANIFOLD
- m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
-#endif
-
- ///iff distance positive, don't generate a new contact
- if (len > (radius0 + radius1 + resultOut->m_closestPointDistanceThreshold))
- {
-#ifndef CLEAR_MANIFOLD
- resultOut->refreshContactPoints();
-#endif //CLEAR_MANIFOLD
- return;
- }
- ///distance (negative means penetration)
- btScalar dist = len - (radius0 + radius1);
-
- btVector3 normalOnSurfaceB(1, 0, 0);
- if (len > SIMD_EPSILON)
- {
- normalOnSurfaceB = diff / len;
- }
-
- ///point on A (worldspace)
- ///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
- ///point on B (worldspace)
- btVector3 pos1 = col1Wrap->getWorldTransform().getOrigin() + radius1 * normalOnSurfaceB;
-
- /// report a contact. internally this will be kept persistent, and contact reduction is done
-
- resultOut->addContactPoint(normalOnSurfaceB, pos1, dist);
-
-#ifndef CLEAR_MANIFOLD
- resultOut->refreshContactPoints();
-#endif //CLEAR_MANIFOLD
-}
-
-btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)col0;
- (void)col1;
- (void)dispatchInfo;
- (void)resultOut;
-
- //not yet
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
deleted file mode 100644
index b08d0df76d..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
-#define BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-#include "btCollisionDispatcher.h"
-
-class btPersistentManifold;
-
-/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
-/// Other features are frame-coherency (persistent data) and collision response.
-/// Also provides the most basic sample for custom/user btCollisionAlgorithm
-class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
-public:
- btSphereSphereCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap);
-
- btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btActivatingCollisionAlgorithm(ci) {}
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- virtual ~btSphereSphereCollisionAlgorithm();
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
- return new (mem) btSphereSphereCollisionAlgorithm(0, ci, col0Wrap, col1Wrap);
- }
- };
-};
-
-#endif //BT_SPHERE_SPHERE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
deleted file mode 100644
index 1bc3056c01..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSphereTriangleCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "SphereTriangleDetector.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap),
- m_ownManifold(false),
- m_manifoldPtr(mf),
- m_swapped(swapped)
-{
- if (!m_manifoldPtr)
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
- m_ownManifold = true;
- }
-}
-
-btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
-{
- if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
-}
-
-void btSphereTriangleCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* col0Wrap, const btCollisionObjectWrapper* col1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- if (!m_manifoldPtr)
- return;
-
- const btCollisionObjectWrapper* sphereObjWrap = m_swapped ? col1Wrap : col0Wrap;
- const btCollisionObjectWrapper* triObjWrap = m_swapped ? col0Wrap : col1Wrap;
-
- btSphereShape* sphere = (btSphereShape*)sphereObjWrap->getCollisionShape();
- btTriangleShape* triangle = (btTriangleShape*)triObjWrap->getCollisionShape();
-
- /// report a contact. internally this will be kept persistent, and contact reduction is done
- resultOut->setPersistentManifold(m_manifoldPtr);
- SphereTriangleDetector detector(sphere, triangle, m_manifoldPtr->getContactBreakingThreshold() + resultOut->m_closestPointDistanceThreshold);
-
- btDiscreteCollisionDetectorInterface::ClosestPointInput input;
- input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); ///@todo: tighter bounds
- input.m_transformA = sphereObjWrap->getWorldTransform();
- input.m_transformB = triObjWrap->getWorldTransform();
-
- bool swapResults = m_swapped;
-
- detector.getClosestPoints(input, *resultOut, dispatchInfo.m_debugDraw, swapResults);
-
- if (m_ownManifold)
- resultOut->refreshContactPoints();
-}
-
-btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- (void)col0;
- (void)col1;
-
- //not yet
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
deleted file mode 100644
index d660222f16..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
-#define BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
-
-#include "btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-class btPersistentManifold;
-#include "btCollisionDispatcher.h"
-
-/// btSphereSphereCollisionAlgorithm provides sphere-sphere collision detection.
-/// Other features are frame-coherency (persistent data) and collision response.
-/// Also provides the most basic sample for custom/user btCollisionAlgorithm
-class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
- bool m_swapped;
-
-public:
- btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool swapped);
-
- btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btActivatingCollisionAlgorithm(ci) {}
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- {
- manifoldArray.push_back(m_manifoldPtr);
- }
- }
-
- virtual ~btSphereTriangleCollisionAlgorithm();
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
-
- return new (mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold, ci, body0Wrap, body1Wrap, m_swapped);
- }
- };
-};
-
-#endif //BT_SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
deleted file mode 100644
index 816bf1e6ad..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btUnionFind.h"
-
-btUnionFind::~btUnionFind()
-{
- Free();
-}
-
-btUnionFind::btUnionFind()
-{
-}
-
-void btUnionFind::allocate(int N)
-{
- m_elements.resize(N);
-}
-void btUnionFind::Free()
-{
- m_elements.clear();
-}
-
-void btUnionFind::reset(int N)
-{
- allocate(N);
-
- for (int i = 0; i < N; i++)
- {
- m_elements[i].m_id = i;
- m_elements[i].m_sz = 1;
- }
-}
-
-class btUnionFindElementSortPredicate
-{
-public:
- bool operator()(const btElement& lhs, const btElement& rhs) const
- {
- return lhs.m_id < rhs.m_id;
- }
-};
-
-///this is a special operation, destroying the content of btUnionFind.
-///it sorts the elements, based on island id, in order to make it easy to iterate over islands
-void btUnionFind::sortIslands()
-{
- //first store the original body index, and islandId
- int numElements = m_elements.size();
-
- for (int i = 0; i < numElements; i++)
- {
- m_elements[i].m_id = find(i);
-#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
- m_elements[i].m_sz = i;
-#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
- }
-
- // Sort the vector using predicate and std::sort
- //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
- m_elements.quickSort(btUnionFindElementSortPredicate());
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h b/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
deleted file mode 100644
index d422ef55eb..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_UNION_FIND_H
-#define BT_UNION_FIND_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-
-#define USE_PATH_COMPRESSION 1
-
-///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
-#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
-
-struct btElement
-{
- int m_id;
- int m_sz;
-};
-
-///UnionFind calculates connected subsets
-// Implements weighted Quick Union with path compression
-// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
-class btUnionFind
-{
-private:
- btAlignedObjectArray<btElement> m_elements;
-
-public:
- btUnionFind();
- ~btUnionFind();
-
- //this is a special operation, destroying the content of btUnionFind.
- //it sorts the elements, based on island id, in order to make it easy to iterate over islands
- void sortIslands();
-
- void reset(int N);
-
- SIMD_FORCE_INLINE int getNumElements() const
- {
- return int(m_elements.size());
- }
- SIMD_FORCE_INLINE bool isRoot(int x) const
- {
- return (x == m_elements[x].m_id);
- }
-
- btElement& getElement(int index)
- {
- return m_elements[index];
- }
- const btElement& getElement(int index) const
- {
- return m_elements[index];
- }
-
- void allocate(int N);
- void Free();
-
- int find(int p, int q)
- {
- return (find(p) == find(q));
- }
-
- void unite(int p, int q)
- {
- int i = find(p), j = find(q);
- if (i == j)
- return;
-
-#ifndef USE_PATH_COMPRESSION
- //weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
- if (m_elements[i].m_sz < m_elements[j].m_sz)
- {
- m_elements[i].m_id = j;
- m_elements[j].m_sz += m_elements[i].m_sz;
- }
- else
- {
- m_elements[j].m_id = i;
- m_elements[i].m_sz += m_elements[j].m_sz;
- }
-#else
- m_elements[i].m_id = j;
- m_elements[j].m_sz += m_elements[i].m_sz;
-#endif //USE_PATH_COMPRESSION
- }
-
- int find(int x)
- {
- //btAssert(x < m_N);
- //btAssert(x >= 0);
-
- while (x != m_elements[x].m_id)
- {
- //not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
-
-#ifdef USE_PATH_COMPRESSION
- const btElement* elementPtr = &m_elements[m_elements[x].m_id];
- m_elements[x].m_id = elementPtr->m_id;
- x = elementPtr->m_id;
-#else //
- x = m_elements[x].m_id;
-#endif
- //btAssert(x < m_N);
- //btAssert(x >= 0);
- }
- return x;
- }
-};
-
-#endif //BT_UNION_FIND_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
deleted file mode 100644
index a3d8075daf..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btBox2dShape.h"
-
-//{
-
-void btBox2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
-}
-
-void btBox2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- //btScalar margin = btScalar(0.);
- btVector3 halfExtents = getHalfExtentsWithMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x());
- btScalar ly = btScalar(2.) * (halfExtents.y());
- btScalar lz = btScalar(2.) * (halfExtents.z());
-
- inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + ly * ly));
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
deleted file mode 100644
index 7e085f9e2e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_OBB_BOX_2D_SHAPE_H
-#define BT_OBB_BOX_2D_SHAPE_H
-
-#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btMinMax.h"
-
-///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-ATTRIBUTE_ALIGNED16(class)
-btBox2dShape : public btPolyhedralConvexShape
-{
- //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
-
- btVector3 m_centroid;
- btVector3 m_vertices[4];
- btVector3 m_normals[4];
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 getHalfExtentsWithMargin() const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(), getMargin(), getMargin());
- halfExtents += margin;
- return halfExtents;
- }
-
- const btVector3& getHalfExtentsWithoutMargin() const
- {
- return m_implicitShapeDimensions; //changed in Bullet 2.63: assume the scaling and margin are included
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(), getMargin(), getMargin());
- halfExtents += margin;
-
- return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
-
- SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
- {
- const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
- {
- const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- for (int i = 0; i < numVectors; i++)
- {
- const btVector3& vec = vectors[i];
- supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
- }
-
- ///a btBox2dShape is a flat 2D box in the X-Y plane (Z extents are zero)
- btBox2dShape(const btVector3& boxHalfExtents)
- : btPolyhedralConvexShape(),
- m_centroid(0, 0, 0)
- {
- m_vertices[0].setValue(-boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
- m_vertices[1].setValue(boxHalfExtents.getX(), -boxHalfExtents.getY(), 0);
- m_vertices[2].setValue(boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
- m_vertices[3].setValue(-boxHalfExtents.getX(), boxHalfExtents.getY(), 0);
-
- m_normals[0].setValue(0, -1, 0);
- m_normals[1].setValue(1, 0, 0);
- m_normals[2].setValue(0, 1, 0);
- m_normals[3].setValue(-1, 0, 0);
-
- btScalar minDimension = boxHalfExtents.getX();
- if (minDimension > boxHalfExtents.getY())
- minDimension = boxHalfExtents.getY();
-
- m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
- btVector3 margin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
-
- setSafeMargin(minDimension);
- };
-
- virtual void setMargin(btScalar collisionMargin)
- {
- //correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
-
- btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
- }
- virtual void setLocalScaling(const btVector3& scaling)
- {
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
- btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
-
- btConvexInternalShape::setLocalScaling(scaling);
-
- m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- int getVertexCount() const
- {
- return 4;
- }
-
- virtual int getNumVertices() const
- {
- return 4;
- }
-
- const btVector3* getVertices() const
- {
- return &m_vertices[0];
- }
-
- const btVector3* getNormals() const
- {
- return &m_normals[0];
- }
-
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
- {
- //this plane might not be aligned...
- btVector4 plane;
- getPlaneEquation(plane, i);
- planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
- planeSupport = localGetSupportingVertex(-planeNormal);
- }
-
- const btVector3& getCentroid() const
- {
- return m_centroid;
- }
-
- virtual int getNumPlanes() const
- {
- return 6;
- }
-
- virtual int getNumEdges() const
- {
- return 12;
- }
-
- virtual void getVertex(int i, btVector3& vtx) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
-
- vtx = btVector3(
- halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
- halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
- halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
- }
-
- virtual void getPlaneEquation(btVector4 & plane, int i) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
-
- switch (i)
- {
- case 0:
- plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
- break;
- case 1:
- plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
- break;
- case 2:
- plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
- break;
- case 3:
- plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
- break;
- case 4:
- plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
- break;
- case 5:
- plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
- break;
- default:
- btAssert(0);
- }
- }
-
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
- //virtual void getEdge(int i,Edge& edge) const
- {
- int edgeVert0 = 0;
- int edgeVert1 = 0;
-
- switch (i)
- {
- case 0:
- edgeVert0 = 0;
- edgeVert1 = 1;
- break;
- case 1:
- edgeVert0 = 0;
- edgeVert1 = 2;
- break;
- case 2:
- edgeVert0 = 1;
- edgeVert1 = 3;
-
- break;
- case 3:
- edgeVert0 = 2;
- edgeVert1 = 3;
- break;
- case 4:
- edgeVert0 = 0;
- edgeVert1 = 4;
- break;
- case 5:
- edgeVert0 = 1;
- edgeVert1 = 5;
-
- break;
- case 6:
- edgeVert0 = 2;
- edgeVert1 = 6;
- break;
- case 7:
- edgeVert0 = 3;
- edgeVert1 = 7;
- break;
- case 8:
- edgeVert0 = 4;
- edgeVert1 = 5;
- break;
- case 9:
- edgeVert0 = 4;
- edgeVert1 = 6;
- break;
- case 10:
- edgeVert0 = 5;
- edgeVert1 = 7;
- break;
- case 11:
- edgeVert0 = 6;
- edgeVert1 = 7;
- break;
- default:
- btAssert(0);
- }
-
- getVertex(edgeVert0, pa);
- getVertex(edgeVert1, pb);
- }
-
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
-
- //btScalar minDist = 2*tolerance;
-
- bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
- (pt.x() >= (-halfExtents.x() - tolerance)) &&
- (pt.y() <= (halfExtents.y() + tolerance)) &&
- (pt.y() >= (-halfExtents.y() - tolerance)) &&
- (pt.z() <= (halfExtents.z() + tolerance)) &&
- (pt.z() >= (-halfExtents.z() - tolerance));
-
- return result;
- }
-
- //debugging
- virtual const char* getName() const
- {
- return "Box2d";
- }
-
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 6;
- }
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- switch (index)
- {
- case 0:
- penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
- break;
- case 1:
- penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
- break;
- case 2:
- penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
- break;
- case 3:
- penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
- break;
- case 4:
- penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
- break;
- case 5:
- penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
- break;
- default:
- btAssert(0);
- }
- }
-};
-
-#endif //BT_OBB_BOX_2D_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
deleted file mode 100644
index cb91d023e4..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include "btBoxShape.h"
-
-btBoxShape::btBoxShape(const btVector3& boxHalfExtents)
- : btPolyhedralConvexShape()
-{
- m_shapeType = BOX_SHAPE_PROXYTYPE;
-
- btVector3 margin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
-
- setSafeMargin(boxHalfExtents);
-};
-
-void btBoxShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
-}
-
-void btBoxShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- //btScalar margin = btScalar(0.);
- btVector3 halfExtents = getHalfExtentsWithMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x());
- btScalar ly = btScalar(2.) * (halfExtents.y());
- btScalar lz = btScalar(2.) * (halfExtents.z());
-
- inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + ly * ly));
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h
deleted file mode 100644
index 3c65505d5b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBoxShape.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_OBB_BOX_MINKOWSKI_H
-#define BT_OBB_BOX_MINKOWSKI_H
-
-#include "btPolyhedralConvexShape.h"
-#include "btCollisionMargin.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btMinMax.h"
-
-///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
-ATTRIBUTE_ALIGNED16(class)
-btBoxShape : public btPolyhedralConvexShape
-{
- //btVector3 m_boxHalfExtents1; //use m_implicitShapeDimensions instead
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 getHalfExtentsWithMargin() const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(), getMargin(), getMargin());
- halfExtents += margin;
- return halfExtents;
- }
-
- const btVector3& getHalfExtentsWithoutMargin() const
- {
- return m_implicitShapeDimensions; //scaling is included, margin is not
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(), getMargin(), getMargin());
- halfExtents += margin;
-
- return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
-
- SIMD_FORCE_INLINE btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
- {
- const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
- {
- const btVector3& halfExtents = getHalfExtentsWithoutMargin();
-
- for (int i = 0; i < numVectors; i++)
- {
- const btVector3& vec = vectors[i];
- supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
- }
- }
-
- btBoxShape(const btVector3& boxHalfExtents);
-
- virtual void setMargin(btScalar collisionMargin)
- {
- //correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
-
- btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
- }
- virtual void setLocalScaling(const btVector3& scaling)
- {
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
- btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
-
- btConvexInternalShape::setLocalScaling(scaling);
-
- m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
- {
- //this plane might not be aligned...
- btVector4 plane;
- getPlaneEquation(plane, i);
- planeNormal = btVector3(plane.getX(), plane.getY(), plane.getZ());
- planeSupport = localGetSupportingVertex(-planeNormal);
- }
-
- virtual int getNumPlanes() const
- {
- return 6;
- }
-
- virtual int getNumVertices() const
- {
- return 8;
- }
-
- virtual int getNumEdges() const
- {
- return 12;
- }
-
- virtual void getVertex(int i, btVector3& vtx) const
- {
- btVector3 halfExtents = getHalfExtentsWithMargin();
-
- vtx = btVector3(
- halfExtents.x() * (1 - (i & 1)) - halfExtents.x() * (i & 1),
- halfExtents.y() * (1 - ((i & 2) >> 1)) - halfExtents.y() * ((i & 2) >> 1),
- halfExtents.z() * (1 - ((i & 4) >> 2)) - halfExtents.z() * ((i & 4) >> 2));
- }
-
- virtual void getPlaneEquation(btVector4 & plane, int i) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
-
- switch (i)
- {
- case 0:
- plane.setValue(btScalar(1.), btScalar(0.), btScalar(0.), -halfExtents.x());
- break;
- case 1:
- plane.setValue(btScalar(-1.), btScalar(0.), btScalar(0.), -halfExtents.x());
- break;
- case 2:
- plane.setValue(btScalar(0.), btScalar(1.), btScalar(0.), -halfExtents.y());
- break;
- case 3:
- plane.setValue(btScalar(0.), btScalar(-1.), btScalar(0.), -halfExtents.y());
- break;
- case 4:
- plane.setValue(btScalar(0.), btScalar(0.), btScalar(1.), -halfExtents.z());
- break;
- case 5:
- plane.setValue(btScalar(0.), btScalar(0.), btScalar(-1.), -halfExtents.z());
- break;
- default:
- btAssert(0);
- }
- }
-
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
- //virtual void getEdge(int i,Edge& edge) const
- {
- int edgeVert0 = 0;
- int edgeVert1 = 0;
-
- switch (i)
- {
- case 0:
- edgeVert0 = 0;
- edgeVert1 = 1;
- break;
- case 1:
- edgeVert0 = 0;
- edgeVert1 = 2;
- break;
- case 2:
- edgeVert0 = 1;
- edgeVert1 = 3;
-
- break;
- case 3:
- edgeVert0 = 2;
- edgeVert1 = 3;
- break;
- case 4:
- edgeVert0 = 0;
- edgeVert1 = 4;
- break;
- case 5:
- edgeVert0 = 1;
- edgeVert1 = 5;
-
- break;
- case 6:
- edgeVert0 = 2;
- edgeVert1 = 6;
- break;
- case 7:
- edgeVert0 = 3;
- edgeVert1 = 7;
- break;
- case 8:
- edgeVert0 = 4;
- edgeVert1 = 5;
- break;
- case 9:
- edgeVert0 = 4;
- edgeVert1 = 6;
- break;
- case 10:
- edgeVert0 = 5;
- edgeVert1 = 7;
- break;
- case 11:
- edgeVert0 = 6;
- edgeVert1 = 7;
- break;
- default:
- btAssert(0);
- }
-
- getVertex(edgeVert0, pa);
- getVertex(edgeVert1, pb);
- }
-
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
-
- //btScalar minDist = 2*tolerance;
-
- bool result = (pt.x() <= (halfExtents.x() + tolerance)) &&
- (pt.x() >= (-halfExtents.x() - tolerance)) &&
- (pt.y() <= (halfExtents.y() + tolerance)) &&
- (pt.y() >= (-halfExtents.y() - tolerance)) &&
- (pt.z() <= (halfExtents.z() + tolerance)) &&
- (pt.z() >= (-halfExtents.z() - tolerance));
-
- return result;
- }
-
- //debugging
- virtual const char* getName() const
- {
- return "Box";
- }
-
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 6;
- }
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- switch (index)
- {
- case 0:
- penetrationVector.setValue(btScalar(1.), btScalar(0.), btScalar(0.));
- break;
- case 1:
- penetrationVector.setValue(btScalar(-1.), btScalar(0.), btScalar(0.));
- break;
- case 2:
- penetrationVector.setValue(btScalar(0.), btScalar(1.), btScalar(0.));
- break;
- case 3:
- penetrationVector.setValue(btScalar(0.), btScalar(-1.), btScalar(0.));
- break;
- case 4:
- penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(1.));
- break;
- case 5:
- penetrationVector.setValue(btScalar(0.), btScalar(0.), btScalar(-1.));
- break;
- default:
- btAssert(0);
- }
- }
-};
-
-#endif //BT_OBB_BOX_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
deleted file mode 100644
index c66ce58e3e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//#define DISABLE_BVH
-
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
-#include "LinearMath/btSerializer.h"
-
-///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
-///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
-btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
- : btTriangleMeshShape(meshInterface),
- m_bvh(0),
- m_triangleInfoMap(0),
- m_useQuantizedAabbCompression(useQuantizedAabbCompression),
- m_ownsBvh(false)
-{
- m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- //construct bvh from meshInterface
-#ifndef DISABLE_BVH
-
- if (buildBvh)
- {
- buildOptimizedBvh();
- }
-
-#endif //DISABLE_BVH
-}
-
-btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh)
- : btTriangleMeshShape(meshInterface),
- m_bvh(0),
- m_triangleInfoMap(0),
- m_useQuantizedAabbCompression(useQuantizedAabbCompression),
- m_ownsBvh(false)
-{
- m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- //construct bvh from meshInterface
-#ifndef DISABLE_BVH
-
- if (buildBvh)
- {
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
- m_bvh = new (mem) btOptimizedBvh();
-
- m_bvh->build(meshInterface, m_useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax);
- m_ownsBvh = true;
- }
-
-#endif //DISABLE_BVH
-}
-
-void btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax)
-{
- m_bvh->refitPartial(m_meshInterface, aabbMin, aabbMax);
-
- m_localAabbMin.setMin(aabbMin);
- m_localAabbMax.setMax(aabbMax);
-}
-
-void btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin, const btVector3& aabbMax)
-{
- m_bvh->refit(m_meshInterface, aabbMin, aabbMax);
-
- recalcLocalAabb();
-}
-
-btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
-{
- if (m_ownsBvh)
- {
- m_bvh->~btOptimizedBvh();
- btAlignedFree(m_bvh);
- }
-}
-
-void btBvhTriangleMeshShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
-{
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
-
- MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
- : m_meshInterface(meshInterface),
- m_callback(callback)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- btVector3 m_triangle[3];
- const unsigned char* vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char* indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
-
- unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: btAssert(0);
- }
-
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
- }
- }
-
- /* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
-
- MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
-
- m_bvh->reportRayOverlappingNodex(&myNodeCallback, raySource, rayTarget);
-}
-
-void btBvhTriangleMeshShape::performConvexcast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
-
- MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
- : m_meshInterface(meshInterface),
- m_callback(callback)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- btVector3 m_triangle[3];
- const unsigned char* vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char* indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
-
- unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: btAssert(0);
- }
-
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(btScalar(graphicsbase[0]) * meshScaling.getX(), btScalar(graphicsbase[1]) * meshScaling.getY(), btScalar(graphicsbase[2]) * meshScaling.getZ());
- }
- }
-
- /* Perform ray vs. triangle collision here */
- m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
-
- MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
-
- m_bvh->reportBoxCastOverlappingNodex(&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
-}
-
-//perform bvh tree traversal and report overlapping triangles to 'callback'
-void btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
-#ifdef DISABLE_BVH
- //brute force traverse all triangles
- btTriangleMeshShape::processAllTriangles(callback, aabbMin, aabbMax);
-#else
-
- //first get all the nodes
-
- struct MyNodeOverlapCallback : public btNodeOverlapCallback
- {
- btStridingMeshInterface* m_meshInterface;
- btTriangleCallback* m_callback;
- btVector3 m_triangle[3];
- int m_numOverlap;
-
- MyNodeOverlapCallback(btTriangleCallback* callback, btStridingMeshInterface* meshInterface)
- : m_meshInterface(meshInterface),
- m_callback(callback),
- m_numOverlap(0)
- {
- }
-
- virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
- {
- m_numOverlap++;
- const unsigned char* vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char* indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- nodeSubPart);
-
- unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
- btAssert(indicestype == PHY_INTEGER || indicestype == PHY_SHORT || indicestype == PHY_UCHAR);
-
- const btVector3& meshScaling = m_meshInterface->getScaling();
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex = indicestype == PHY_SHORT ? ((unsigned short*)gfxbase)[j] : indicestype == PHY_INTEGER ? gfxbase[j] : ((unsigned char*)gfxbase)[j];
-
-#ifdef DEBUG_TRIANGLE_MESH
- printf("%d ,", graphicsindex);
-#endif //DEBUG_TRIANGLE_MESH
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(
- graphicsbase[0] * meshScaling.getX(),
- graphicsbase[1] * meshScaling.getY(),
- graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
-
- m_triangle[j] = btVector3(
- btScalar(graphicsbase[0]) * meshScaling.getX(),
- btScalar(graphicsbase[1]) * meshScaling.getY(),
- btScalar(graphicsbase[2]) * meshScaling.getZ());
- }
-#ifdef DEBUG_TRIANGLE_MESH
- printf("triangle vertices:%f,%f,%f\n", triangle[j].x(), triangle[j].y(), triangle[j].z());
-#endif //DEBUG_TRIANGLE_MESH
- }
-
- m_callback->processTriangle(m_triangle, nodeSubPart, nodeTriangleIndex);
- m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
- }
- };
-
- MyNodeOverlapCallback myNodeCallback(callback, m_meshInterface);
-
- m_bvh->reportAabbOverlappingNodex(&myNodeCallback, aabbMin, aabbMax);
-
-#endif //DISABLE_BVH
-}
-
-void btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
-{
- if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- buildOptimizedBvh();
- }
-}
-
-void btBvhTriangleMeshShape::buildOptimizedBvh()
-{
- if (m_ownsBvh)
- {
- m_bvh->~btOptimizedBvh();
- btAlignedFree(m_bvh);
- }
- ///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
- void* mem = btAlignedAlloc(sizeof(btOptimizedBvh), 16);
- m_bvh = new (mem) btOptimizedBvh();
- //rebuild the bvh...
- m_bvh->build(m_meshInterface, m_useQuantizedAabbCompression, m_localAabbMin, m_localAabbMax);
- m_ownsBvh = true;
-}
-
-void btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
-{
- btAssert(!m_bvh);
- btAssert(!m_ownsBvh);
-
- m_bvh = bvh;
- m_ownsBvh = false;
- // update the scaling without rebuilding the bvh
- if ((getLocalScaling() - scaling).length2() > SIMD_EPSILON)
- {
- btTriangleMeshShape::setLocalScaling(scaling);
- }
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*)dataBuffer;
-
- btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
-
- m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
-
- trimeshData->m_collisionMargin = float(m_collisionMargin);
-
- if (m_bvh && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_BVH))
- {
- void* chunk = serializer->findPointer(m_bvh);
- if (chunk)
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
- trimeshData->m_quantizedFloatBvh = 0;
-#else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)chunk;
- trimeshData->m_quantizedDoubleBvh = 0;
-#endif //BT_USE_DOUBLE_PRECISION
- }
- else
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
- trimeshData->m_quantizedFloatBvh = 0;
-#else
- trimeshData->m_quantizedFloatBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
- trimeshData->m_quantizedDoubleBvh = 0;
-#endif //BT_USE_DOUBLE_PRECISION
-
- int sz = m_bvh->calculateSerializeBufferSizeNew();
- btChunk* chunk = serializer->allocate(sz, 1);
- const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, m_bvh);
- }
- }
- else
- {
- trimeshData->m_quantizedFloatBvh = 0;
- trimeshData->m_quantizedDoubleBvh = 0;
- }
-
- if (m_triangleInfoMap && !(serializer->getSerializationFlags() & BT_SERIALIZE_NO_TRIANGLEINFOMAP))
- {
- void* chunk = serializer->findPointer(m_triangleInfoMap);
- if (chunk)
- {
- trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
- }
- else
- {
- trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
- int sz = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(sz, 1);
- const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, m_triangleInfoMap);
- }
- }
- else
- {
- trimeshData->m_triangleInfoMap = 0;
- }
-
- // Fill padding with zeros to appease msan.
- memset(trimeshData->m_pad3, 0, sizeof(trimeshData->m_pad3));
-
- return "btTriangleMeshShapeData";
-}
-
-void btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
-{
- if (m_bvh)
- {
- int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_QUANTIZED_BVH_CODE, (void*)m_bvh);
- }
-}
-
-void btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
-{
- if (m_triangleInfoMap)
- {
- int len = m_triangleInfoMap->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_TRIANLGE_INFO_MAP, (void*)m_triangleInfoMap);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
deleted file mode 100644
index 8b2f2ee85e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BVH_TRIANGLE_MESH_SHAPE_H
-#define BT_BVH_TRIANGLE_MESH_SHAPE_H
-
-#include "btTriangleMeshShape.h"
-#include "btOptimizedBvh.h"
-#include "LinearMath/btAlignedAllocator.h"
-#include "btTriangleInfoMap.h"
-
-///The btBvhTriangleMeshShape is a static-triangle mesh shape, it can only be used for fixed/non-moving objects.
-///If you required moving concave triangle meshes, it is recommended to perform convex decomposition
-///using HACD, see Bullet/Demos/ConvexDecompositionDemo.
-///Alternatively, you can use btGimpactMeshShape for moving concave triangle meshes.
-///btBvhTriangleMeshShape has several optimizations, such as bounding volume hierarchy and
-///cache friendly traversal for PlayStation 3 Cell SPU.
-///It is recommended to enable useQuantizedAabbCompression for better memory usage.
-///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
-///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
-///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
-ATTRIBUTE_ALIGNED16(class)
-btBvhTriangleMeshShape : public btTriangleMeshShape
-{
- btOptimizedBvh* m_bvh;
- btTriangleInfoMap* m_triangleInfoMap;
-
- bool m_useQuantizedAabbCompression;
- bool m_ownsBvh;
-#ifdef __clang__
- bool m_pad[11] __attribute__((unused)); ////need padding due to alignment
-#else
- bool m_pad[11]; ////need padding due to alignment
-#endif
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
-
- ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
- btBvhTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax, bool buildBvh = true);
-
- virtual ~btBvhTriangleMeshShape();
-
- bool getOwnsBvh() const
- {
- return m_ownsBvh;
- }
-
- void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget);
- void performConvexcast(btTriangleCallback * callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- void refitTree(const btVector3& aabbMin, const btVector3& aabbMax);
-
- ///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
- void partialRefitTree(const btVector3& aabbMin, const btVector3& aabbMax);
-
- //debugging
- virtual const char* getName() const { return "BVHTRIANGLEMESH"; }
-
- virtual void setLocalScaling(const btVector3& scaling);
-
- btOptimizedBvh* getOptimizedBvh()
- {
- return m_bvh;
- }
-
- void setOptimizedBvh(btOptimizedBvh * bvh, const btVector3& localScaling = btVector3(1, 1, 1));
-
- void buildOptimizedBvh();
-
- bool usesQuantizedAabbCompression() const
- {
- return m_useQuantizedAabbCompression;
- }
-
- void setTriangleInfoMap(btTriangleInfoMap * triangleInfoMap)
- {
- m_triangleInfoMap = triangleInfoMap;
- }
-
- const btTriangleInfoMap* getTriangleInfoMap() const
- {
- return m_triangleInfoMap;
- }
-
- btTriangleInfoMap* getTriangleInfoMap()
- {
- return m_triangleInfoMap;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void serializeSingleBvh(btSerializer * serializer) const;
-
- virtual void serializeSingleTriangleInfoMap(btSerializer * serializer) const;
-};
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btTriangleMeshShapeData
-{
- btCollisionShapeData m_collisionShapeData;
-
- btStridingMeshInterfaceData m_meshInterface;
-
- btQuantizedBvhFloatData *m_quantizedFloatBvh;
- btQuantizedBvhDoubleData *m_quantizedDoubleBvh;
-
- btTriangleInfoMapData *m_triangleInfoMap;
-
- float m_collisionMargin;
-
- char m_pad3[4];
-
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btBvhTriangleMeshShape::calculateSerializeBufferSize() const
-{
- return sizeof(btTriangleMeshShapeData);
-}
-
-#endif //BT_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
deleted file mode 100644
index 7c33774284..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCapsuleShape.h"
-
-#include "LinearMath/btQuaternion.h"
-
-btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape()
-{
- m_collisionMargin = radius;
- m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
- m_upAxis = 1;
- m_implicitShapeDimensions.setValue(radius, 0.5f * height, radius);
-}
-
-btVector3 btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
-{
- btVector3 supVec(0, 0, 0);
-
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < btScalar(0.0001))
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
-
- btVector3 vtx;
- btScalar newDot;
-
- {
- btVector3 pos(0, 0, 0);
- pos[getUpAxis()] = getHalfHeight();
-
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- {
- btVector3 pos(0, 0, 0);
- pos[getUpAxis()] = -getHalfHeight();
-
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
-
- return supVec;
-}
-
-void btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int j = 0; j < numVectors; j++)
- {
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
- const btVector3& vec = vectors[j];
-
- btVector3 vtx;
- btScalar newDot;
- {
- btVector3 pos(0, 0, 0);
- pos[getUpAxis()] = getHalfHeight();
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supportVerticesOut[j] = vtx;
- }
- }
- {
- btVector3 pos(0, 0, 0);
- pos[getUpAxis()] = -getHalfHeight();
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supportVerticesOut[j] = vtx;
- }
- }
- }
-}
-
-void btCapsuleShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- //as an approximation, take the inertia of the box that bounds the spheres
-
- btTransform ident;
- ident.setIdentity();
-
- btScalar radius = getRadius();
-
- btVector3 halfExtents(radius, radius, radius);
- halfExtents[getUpAxis()] += getHalfHeight();
-
- btScalar lx = btScalar(2.) * (halfExtents[0]);
- btScalar ly = btScalar(2.) * (halfExtents[1]);
- btScalar lz = btScalar(2.) * (halfExtents[2]);
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(.08333333);
-
- inertia[0] = scaledmass * (y2 + z2);
- inertia[1] = scaledmass * (x2 + z2);
- inertia[2] = scaledmass * (x2 + y2);
-}
-
-btCapsuleShapeX::btCapsuleShapeX(btScalar radius, btScalar height)
-{
- m_collisionMargin = radius;
- m_upAxis = 0;
- m_implicitShapeDimensions.setValue(0.5f * height, radius, radius);
-}
-
-btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius, btScalar height)
-{
- m_collisionMargin = radius;
- m_upAxis = 2;
- m_implicitShapeDimensions.setValue(radius, radius, 0.5f * height);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
deleted file mode 100644
index 138d0c0f7c..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CAPSULE_SHAPE_H
-#define BT_CAPSULE_SHAPE_H
-
-#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
-///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
-///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
-ATTRIBUTE_ALIGNED16(class)
-btCapsuleShape : public btConvexInternalShape
-{
-protected:
- int m_upAxis;
-
-protected:
- ///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
- btCapsuleShape() : btConvexInternalShape() { m_shapeType = CAPSULE_SHAPE_PROXYTYPE; };
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCapsuleShape(btScalar radius, btScalar height);
-
- ///CollisionShape Interface
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- /// btConvexShape Interface
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void setMargin(btScalar collisionMargin)
- {
- //don't override the margin for capsules, their entire radius == margin
- (void)collisionMargin;
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- btVector3 halfExtents(getRadius(), getRadius(), getRadius());
- halfExtents[m_upAxis] = getRadius() + getHalfHeight();
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
-
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
-
- virtual const char* getName() const
- {
- return "CapsuleShape";
- }
-
- int getUpAxis() const
- {
- return m_upAxis;
- }
-
- btScalar getRadius() const
- {
- int radiusAxis = (m_upAxis + 2) % 3;
- return m_implicitShapeDimensions[radiusAxis];
- }
-
- btScalar getHalfHeight() const
- {
- return m_implicitShapeDimensions[m_upAxis];
- }
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- btVector3 unScaledImplicitShapeDimensions = m_implicitShapeDimensions / m_localScaling;
- btConvexInternalShape::setLocalScaling(scaling);
- m_implicitShapeDimensions = (unScaledImplicitShapeDimensions * scaling);
- //update m_collisionMargin, since entire radius==margin
- int radiusAxis = (m_upAxis + 2) % 3;
- m_collisionMargin = m_implicitShapeDimensions[radiusAxis];
- }
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- btVector3 aniDir(0, 0, 0);
- aniDir[getUpAxis()] = 1;
- return aniDir;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- SIMD_FORCE_INLINE void deSerializeFloat(struct btCapsuleShapeData * dataBuffer);
-};
-
-///btCapsuleShapeX represents a capsule around the Z axis
-///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
-class btCapsuleShapeX : public btCapsuleShape
-{
-public:
- btCapsuleShapeX(btScalar radius, btScalar height);
-
- //debugging
- virtual const char* getName() const
- {
- return "CapsuleX";
- }
-};
-
-///btCapsuleShapeZ represents a capsule around the Z axis
-///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
-class btCapsuleShapeZ : public btCapsuleShape
-{
-public:
- btCapsuleShapeZ(btScalar radius, btScalar height);
-
- //debugging
- virtual const char* getName() const
- {
- return "CapsuleZ";
- }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCapsuleShapeData
-{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- int m_upAxis;
-
- char m_padding[4];
-};
-
-SIMD_FORCE_INLINE int btCapsuleShape::calculateSerializeBufferSize() const
-{
- return sizeof(btCapsuleShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btCapsuleShapeData* shapeData = (btCapsuleShapeData*)dataBuffer;
-
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
-
- shapeData->m_upAxis = m_upAxis;
-
- // Fill padding with zeros to appease msan.
- shapeData->m_padding[0] = 0;
- shapeData->m_padding[1] = 0;
- shapeData->m_padding[2] = 0;
- shapeData->m_padding[3] = 0;
-
- return "btCapsuleShapeData";
-}
-
-SIMD_FORCE_INLINE void btCapsuleShape::deSerializeFloat(btCapsuleShapeData* dataBuffer)
-{
- m_implicitShapeDimensions.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_implicitShapeDimensions);
- m_collisionMargin = dataBuffer->m_convexInternalShapeData.m_collisionMargin;
- m_localScaling.deSerializeFloat(dataBuffer->m_convexInternalShapeData.m_localScaling);
- //it is best to already pre-allocate the matching btCapsuleShape*(X/Z) version to match m_upAxis
- m_upAxis = dataBuffer->m_upAxis;
-}
-
-#endif //BT_CAPSULE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
deleted file mode 100644
index abd8ab3eb5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_MARGIN_H
-#define BT_COLLISION_MARGIN_H
-
-///The CONVEX_DISTANCE_MARGIN is a default collision margin for convex collision shapes derived from btConvexInternalShape.
-///This collision margin is used by Gjk and some other algorithms
-///Note that when creating small objects, you need to make sure to set a smaller collision margin, using the 'setMargin' API
-#define CONVEX_DISTANCE_MARGIN btScalar(0.04) // btScalar(0.1)//;//btScalar(0.01)
-
-#endif //BT_COLLISION_MARGIN_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
deleted file mode 100644
index 0b3640a65b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "LinearMath/btSerializer.h"
-
-/*
- Make sure this dummy function never changes so that it
- can be used by probes that are checking whether the
- library is actually installed.
-*/
-extern "C"
-{
- void btBulletCollisionProbe();
-
- void btBulletCollisionProbe() {}
-}
-
-void btCollisionShape::getBoundingSphere(btVector3& center, btScalar& radius) const
-{
- btTransform tr;
- tr.setIdentity();
- btVector3 aabbMin, aabbMax;
-
- getAabb(tr, aabbMin, aabbMax);
-
- radius = (aabbMax - aabbMin).length() * btScalar(0.5);
- center = (aabbMin + aabbMax) * btScalar(0.5);
-}
-
-btScalar btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
-{
- return getAngularMotionDisc() * defaultContactThreshold;
-}
-
-btScalar btCollisionShape::getAngularMotionDisc() const
-{
- ///@todo cache this value, to improve performance
- btVector3 center;
- btScalar disc;
- getBoundingSphere(center, disc);
- disc += (center).length();
- return disc;
-}
-
-void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const
-{
- //start with static aabb
- getAabb(curTrans, temporalAabbMin, temporalAabbMax);
-
- btScalar temporalAabbMaxx = temporalAabbMax.getX();
- btScalar temporalAabbMaxy = temporalAabbMax.getY();
- btScalar temporalAabbMaxz = temporalAabbMax.getZ();
- btScalar temporalAabbMinx = temporalAabbMin.getX();
- btScalar temporalAabbMiny = temporalAabbMin.getY();
- btScalar temporalAabbMinz = temporalAabbMin.getZ();
-
- // add linear motion
- btVector3 linMotion = linvel * timeStep;
- ///@todo: simd would have a vector max/min operation, instead of per-element access
- if (linMotion.x() > btScalar(0.))
- temporalAabbMaxx += linMotion.x();
- else
- temporalAabbMinx += linMotion.x();
- if (linMotion.y() > btScalar(0.))
- temporalAabbMaxy += linMotion.y();
- else
- temporalAabbMiny += linMotion.y();
- if (linMotion.z() > btScalar(0.))
- temporalAabbMaxz += linMotion.z();
- else
- temporalAabbMinz += linMotion.z();
-
- //add conservative angular motion
- btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
- btVector3 angularMotion3d(angularMotion, angularMotion, angularMotion);
- temporalAabbMin = btVector3(temporalAabbMinx, temporalAabbMiny, temporalAabbMinz);
- temporalAabbMax = btVector3(temporalAabbMaxx, temporalAabbMaxy, temporalAabbMaxz);
-
- temporalAabbMin -= angularMotion3d;
- temporalAabbMax += angularMotion3d;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btCollisionShapeData* shapeData = (btCollisionShapeData*)dataBuffer;
- char* name = (char*)serializer->findNameForPointer(this);
- shapeData->m_name = (char*)serializer->getUniquePointer(name);
- if (shapeData->m_name)
- {
- serializer->serializeName(name);
- }
- shapeData->m_shapeType = m_shapeType;
-
- // Fill padding with zeros to appease msan.
- memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
-
- return "btCollisionShapeData";
-}
-
-void btCollisionShape::serializeSingleShape(btSerializer* serializer) const
-{
- int len = calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, (void*)this);
-} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
deleted file mode 100644
index 16f9e0c77a..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COLLISION_SHAPE_H
-#define BT_COLLISION_SHAPE_H
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
-class btSerializer;
-
-///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
-ATTRIBUTE_ALIGNED16(class)
-btCollisionShape
-{
-protected:
- int m_shapeType;
- void* m_userPointer;
- int m_userIndex;
- int m_userIndex2;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCollisionShape() : m_shapeType(INVALID_SHAPE_PROXYTYPE), m_userPointer(0), m_userIndex(-1), m_userIndex2(-1)
- {
- }
-
- virtual ~btCollisionShape()
- {
- }
-
- ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
-
- virtual void getBoundingSphere(btVector3 & center, btScalar & radius) const;
-
- ///getAngularMotionDisc returns the maximum radius needed for Conservative Advancement to handle time-of-impact with rotations.
- virtual btScalar getAngularMotionDisc() const;
-
- virtual btScalar getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
-
- ///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
- ///result is conservative
- void calculateTemporalAabb(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btVector3& temporalAabbMin, btVector3& temporalAabbMax) const;
-
- SIMD_FORCE_INLINE bool isPolyhedral() const
- {
- return btBroadphaseProxy::isPolyhedral(getShapeType());
- }
-
- SIMD_FORCE_INLINE bool isConvex2d() const
- {
- return btBroadphaseProxy::isConvex2d(getShapeType());
- }
-
- SIMD_FORCE_INLINE bool isConvex() const
- {
- return btBroadphaseProxy::isConvex(getShapeType());
- }
- SIMD_FORCE_INLINE bool isNonMoving() const
- {
- return btBroadphaseProxy::isNonMoving(getShapeType());
- }
- SIMD_FORCE_INLINE bool isConcave() const
- {
- return btBroadphaseProxy::isConcave(getShapeType());
- }
- SIMD_FORCE_INLINE bool isCompound() const
- {
- return btBroadphaseProxy::isCompound(getShapeType());
- }
-
- SIMD_FORCE_INLINE bool isSoftBody() const
- {
- return btBroadphaseProxy::isSoftBody(getShapeType());
- }
-
- ///isInfinite is used to catch simulation error (aabb check)
- SIMD_FORCE_INLINE bool isInfinite() const
- {
- return btBroadphaseProxy::isInfinite(getShapeType());
- }
-
-#ifndef __SPU__
- virtual void setLocalScaling(const btVector3& scaling) = 0;
- virtual const btVector3& getLocalScaling() const = 0;
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const = 0;
-
- //debugging support
- virtual const char* getName() const = 0;
-#endif //__SPU__
-
- int getShapeType() const
- {
- return m_shapeType;
- }
-
- ///the getAnisotropicRollingFrictionDirection can be used in combination with setAnisotropicFriction
- ///See Bullet/Demos/RollingFrictionDemo for an example
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- return btVector3(1, 1, 1);
- }
- virtual void setMargin(btScalar margin) = 0;
- virtual btScalar getMargin() const = 0;
-
- ///optional user data pointer
- void setUserPointer(void* userPtr)
- {
- m_userPointer = userPtr;
- }
-
- void* getUserPointer() const
- {
- return m_userPointer;
- }
- void setUserIndex(int index)
- {
- m_userIndex = index;
- }
-
- int getUserIndex() const
- {
- return m_userIndex;
- }
-
- void setUserIndex2(int index)
- {
- m_userIndex2 = index;
- }
-
- int getUserIndex2() const
- {
- return m_userIndex2;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- virtual void serializeSingleShape(btSerializer * serializer) const;
-};
-
-// clang-format off
-// parser needs * with the name
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCollisionShapeData
-{
- char *m_name;
- int m_shapeType;
- char m_padding[4];
-};
-// clang-format on
-SIMD_FORCE_INLINE int btCollisionShape::calculateSerializeBufferSize() const
-{
- return sizeof(btCollisionShapeData);
-}
-
-#endif //BT_COLLISION_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
deleted file mode 100644
index fd7828b104..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCompoundShape.h"
-#include "btCollisionShape.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "LinearMath/btSerializer.h"
-
-btCompoundShape::btCompoundShape(bool enableDynamicAabbTree, const int initialChildCapacity)
- : m_localAabbMin(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT)),
- m_localAabbMax(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT)),
- m_dynamicAabbTree(0),
- m_updateRevision(1),
- m_collisionMargin(btScalar(0.)),
- m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
-{
- m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
-
- if (enableDynamicAabbTree)
- {
- void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
- m_dynamicAabbTree = new (mem) btDbvt();
- btAssert(mem == m_dynamicAabbTree);
- }
-
- m_children.reserve(initialChildCapacity);
-}
-
-btCompoundShape::~btCompoundShape()
-{
- if (m_dynamicAabbTree)
- {
- m_dynamicAabbTree->~btDbvt();
- btAlignedFree(m_dynamicAabbTree);
- }
-}
-
-void btCompoundShape::addChildShape(const btTransform& localTransform, btCollisionShape* shape)
-{
- m_updateRevision++;
- //m_childTransforms.push_back(localTransform);
- //m_childShapes.push_back(shape);
- btCompoundShapeChild child;
- child.m_node = 0;
- child.m_transform = localTransform;
- child.m_childShape = shape;
- child.m_childShapeType = shape->getShapeType();
- child.m_childMargin = shape->getMargin();
-
- //extend the local aabbMin/aabbMax
- btVector3 localAabbMin, localAabbMax;
- shape->getAabb(localTransform, localAabbMin, localAabbMax);
- for (int i = 0; i < 3; i++)
- {
- if (m_localAabbMin[i] > localAabbMin[i])
- {
- m_localAabbMin[i] = localAabbMin[i];
- }
- if (m_localAabbMax[i] < localAabbMax[i])
- {
- m_localAabbMax[i] = localAabbMax[i];
- }
- }
- if (m_dynamicAabbTree)
- {
- const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
- size_t index = m_children.size();
- child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index));
- }
-
- m_children.push_back(child);
-}
-
-void btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb)
-{
- m_children[childIndex].m_transform = newChildTransform;
-
- if (m_dynamicAabbTree)
- {
- ///update the dynamic aabb tree
- btVector3 localAabbMin, localAabbMax;
- m_children[childIndex].m_childShape->getAabb(newChildTransform, localAabbMin, localAabbMax);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
- //int index = m_children.size()-1;
- m_dynamicAabbTree->update(m_children[childIndex].m_node, bounds);
- }
-
- if (shouldRecalculateLocalAabb)
- {
- recalculateLocalAabb();
- }
-}
-
-void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
-{
- m_updateRevision++;
- btAssert(childShapeIndex >= 0 && childShapeIndex < m_children.size());
- if (m_dynamicAabbTree)
- {
- m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
- }
- m_children.swap(childShapeIndex, m_children.size() - 1);
- if (m_dynamicAabbTree)
- m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
- m_children.pop_back();
-}
-
-void btCompoundShape::removeChildShape(btCollisionShape* shape)
-{
- m_updateRevision++;
- // Find the children containing the shape specified, and remove those children.
- //note: there might be multiple children using the same shape!
- for (int i = m_children.size() - 1; i >= 0; i--)
- {
- if (m_children[i].m_childShape == shape)
- {
- removeChildShapeByIndex(i);
- }
- }
-
- recalculateLocalAabb();
-}
-
-void btCompoundShape::recalculateLocalAabb()
-{
- // Recalculate the local aabb
- // Brute force, it iterates over all the shapes left.
-
- m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
-
- //extend the local aabbMin/aabbMax
- for (int j = 0; j < m_children.size(); j++)
- {
- btVector3 localAabbMin, localAabbMax;
- m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
- for (int i = 0; i < 3; i++)
- {
- if (m_localAabbMin[i] > localAabbMin[i])
- m_localAabbMin[i] = localAabbMin[i];
- if (m_localAabbMax[i] < localAabbMax[i])
- m_localAabbMax[i] = localAabbMax[i];
- }
- }
-}
-
-///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btCompoundShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btVector3 localHalfExtents = btScalar(0.5) * (m_localAabbMax - m_localAabbMin);
- btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
-
- //avoid an illegal AABB when there are no children
- if (!m_children.size())
- {
- localHalfExtents.setValue(0, 0, 0);
- localCenter.setValue(0, 0, 0);
- }
- localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
-
- btMatrix3x3 abs_b = trans.getBasis().absolute();
-
- btVector3 center = trans(localCenter);
-
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
-}
-
-void btCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- //approximation: take the inertia from the aabb for now
- btTransform ident;
- ident.setIdentity();
- btVector3 aabbMin, aabbMax;
- getAabb(ident, aabbMin, aabbMax);
-
- btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
-
- btScalar lx = btScalar(2.) * (halfExtents.x());
- btScalar ly = btScalar(2.) * (halfExtents.y());
- btScalar lz = btScalar(2.) * (halfExtents.z());
-
- inertia[0] = mass / (btScalar(12.0)) * (ly * ly + lz * lz);
- inertia[1] = mass / (btScalar(12.0)) * (lx * lx + lz * lz);
- inertia[2] = mass / (btScalar(12.0)) * (lx * lx + ly * ly);
-}
-
-void btCompoundShape::calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const
-{
- int n = m_children.size();
-
- btScalar totalMass = 0;
- btVector3 center(0, 0, 0);
- int k;
-
- for (k = 0; k < n; k++)
- {
- btAssert(masses[k] > 0);
- center += m_children[k].m_transform.getOrigin() * masses[k];
- totalMass += masses[k];
- }
-
- btAssert(totalMass > 0);
-
- center /= totalMass;
- principal.setOrigin(center);
-
- btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
- for (k = 0; k < n; k++)
- {
- btVector3 i;
- m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
-
- const btTransform& t = m_children[k].m_transform;
- btVector3 o = t.getOrigin() - center;
-
- //compute inertia tensor in coordinate system of compound shape
- btMatrix3x3 j = t.getBasis().transpose();
- j[0] *= i[0];
- j[1] *= i[1];
- j[2] *= i[2];
- j = t.getBasis() * j;
-
- //add inertia tensor
- tensor[0] += j[0];
- tensor[1] += j[1];
- tensor[2] += j[2];
-
- //compute inertia tensor of pointmass at o
- btScalar o2 = o.length2();
- j[0].setValue(o2, 0, 0);
- j[1].setValue(0, o2, 0);
- j[2].setValue(0, 0, o2);
- j[0] += o * -o.x();
- j[1] += o * -o.y();
- j[2] += o * -o.z();
-
- //add inertia tensor of pointmass
- tensor[0] += masses[k] * j[0];
- tensor[1] += masses[k] * j[1];
- tensor[2] += masses[k] * j[2];
- }
-
- tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
- inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
-}
-
-void btCompoundShape::setLocalScaling(const btVector3& scaling)
-{
- for (int i = 0; i < m_children.size(); i++)
- {
- btTransform childTrans = getChildTransform(i);
- btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
- // childScale = childScale * (childTrans.getBasis() * scaling);
- childScale = childScale * scaling / m_localScaling;
- m_children[i].m_childShape->setLocalScaling(childScale);
- childTrans.setOrigin((childTrans.getOrigin()) * scaling / m_localScaling);
- updateChildTransform(i, childTrans, false);
- }
-
- m_localScaling = scaling;
- recalculateLocalAabb();
-}
-
-void btCompoundShape::createAabbTreeFromChildren()
-{
- if (!m_dynamicAabbTree)
- {
- void* mem = btAlignedAlloc(sizeof(btDbvt), 16);
- m_dynamicAabbTree = new (mem) btDbvt();
- btAssert(mem == m_dynamicAabbTree);
-
- for (int index = 0; index < m_children.size(); index++)
- {
- btCompoundShapeChild& child = m_children[index];
-
- //extend the local aabbMin/aabbMax
- btVector3 localAabbMin, localAabbMax;
- child.m_childShape->getAabb(child.m_transform, localAabbMin, localAabbMax);
-
- const btDbvtVolume bounds = btDbvtVolume::FromMM(localAabbMin, localAabbMax);
- size_t index2 = index;
- child.m_node = m_dynamicAabbTree->insert(bounds, reinterpret_cast<void*>(index2));
- }
- }
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btCompoundShapeData* shapeData = (btCompoundShapeData*)dataBuffer;
- btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
-
- shapeData->m_collisionMargin = float(m_collisionMargin);
- shapeData->m_numChildShapes = m_children.size();
- shapeData->m_childShapePtr = 0;
- if (shapeData->m_numChildShapes)
- {
- btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData), shapeData->m_numChildShapes);
- btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
- shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
-
- for (int i = 0; i < shapeData->m_numChildShapes; i++, memPtr++)
- {
- memPtr->m_childMargin = float(m_children[i].m_childMargin);
- memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
- //don't serialize shapes that already have been serialized
- if (!serializer->findPointer(m_children[i].m_childShape))
- {
- btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(), 1);
- const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_SHAPE_CODE, m_children[i].m_childShape);
- }
-
- memPtr->m_childShapeType = m_children[i].m_childShapeType;
- m_children[i].m_transform.serializeFloat(memPtr->m_transform);
- }
- serializer->finalizeChunk(chunk, "btCompoundShapeChildData", BT_ARRAY_CODE, chunk->m_oldPtr);
- }
- return "btCompoundShapeData";
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
deleted file mode 100644
index 7e2d0eb817..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_COMPOUND_SHAPE_H
-#define BT_COMPOUND_SHAPE_H
-
-#include "btCollisionShape.h"
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "btCollisionMargin.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-//class btOptimizedBvh;
-struct btDbvt;
-
-ATTRIBUTE_ALIGNED16(struct)
-btCompoundShapeChild
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btTransform m_transform;
- btCollisionShape* m_childShape;
- int m_childShapeType;
- btScalar m_childMargin;
- struct btDbvtNode* m_node;
-};
-
-SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
-{
- return (c1.m_transform == c2.m_transform &&
- c1.m_childShape == c2.m_childShape &&
- c1.m_childShapeType == c2.m_childShapeType &&
- c1.m_childMargin == c2.m_childMargin);
-}
-
-/// The btCompoundShape allows to store multiple other btCollisionShapes
-/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
-/// It has an (optional) dynamic aabb tree to accelerate early rejection tests.
-/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
-/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
-ATTRIBUTE_ALIGNED16(class)
-btCompoundShape : public btCollisionShape
-{
-protected:
- btAlignedObjectArray<btCompoundShapeChild> m_children;
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
-
- btDbvt* m_dynamicAabbTree;
-
- ///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
- int m_updateRevision;
-
- btScalar m_collisionMargin;
-
- btVector3 m_localScaling;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- explicit btCompoundShape(bool enableDynamicAabbTree = true, const int initialChildCapacity = 0);
-
- virtual ~btCompoundShape();
-
- void addChildShape(const btTransform& localTransform, btCollisionShape* shape);
-
- /// Remove all children shapes that contain the specified shape
- virtual void removeChildShape(btCollisionShape * shape);
-
- void removeChildShapeByIndex(int childShapeindex);
-
- int getNumChildShapes() const
- {
- return int(m_children.size());
- }
-
- btCollisionShape* getChildShape(int index)
- {
- return m_children[index].m_childShape;
- }
- const btCollisionShape* getChildShape(int index) const
- {
- return m_children[index].m_childShape;
- }
-
- btTransform& getChildTransform(int index)
- {
- return m_children[index].m_transform;
- }
- const btTransform& getChildTransform(int index) const
- {
- return m_children[index].m_transform;
- }
-
- ///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
- void updateChildTransform(int childIndex, const btTransform& newChildTransform, bool shouldRecalculateLocalAabb = true);
-
- btCompoundShapeChild* getChildList()
- {
- return &m_children[0];
- }
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- /** Re-calculate the local Aabb. Is called at the end of removeChildShapes.
- Use this yourself if you modify the children or their transforms. */
- virtual void recalculateLocalAabb();
-
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual const btVector3& getLocalScaling() const
- {
- return m_localScaling;
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
- }
- virtual btScalar getMargin() const
- {
- return m_collisionMargin;
- }
- virtual const char* getName() const
- {
- return "Compound";
- }
-
- const btDbvt* getDynamicAabbTree() const
- {
- return m_dynamicAabbTree;
- }
-
- btDbvt* getDynamicAabbTree()
- {
- return m_dynamicAabbTree;
- }
-
- void createAabbTreeFromChildren();
-
- ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
- ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
- ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
- ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
- ///of the collision object by the principal transform.
- void calculatePrincipalAxisTransform(const btScalar* masses, btTransform& principal, btVector3& inertia) const;
-
- int getUpdateRevision() const
- {
- return m_updateRevision;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCompoundShapeChildData
-{
- btTransformFloatData m_transform;
- btCollisionShapeData *m_childShape;
- int m_childShapeType;
- float m_childMargin;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCompoundShapeData
-{
- btCollisionShapeData m_collisionShapeData;
-
- btCompoundShapeChildData *m_childShapePtr;
-
- int m_numChildShapes;
-
- float m_collisionMargin;
-
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btCompoundShape::calculateSerializeBufferSize() const
-{
- return sizeof(btCompoundShapeData);
-}
-
-#endif //BT_COMPOUND_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
deleted file mode 100644
index 5d396844dd..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConcaveShape.h"
-
-btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
-{
-}
-
-btConcaveShape::~btConcaveShape()
-{
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
deleted file mode 100644
index 716624e182..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONCAVE_SHAPE_H
-#define BT_CONCAVE_SHAPE_H
-
-#include "btCollisionShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "btTriangleCallback.h"
-
-/// PHY_ScalarType enumerates possible scalar types.
-/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
-typedef enum PHY_ScalarType
-{
- PHY_FLOAT,
- PHY_DOUBLE,
- PHY_INTEGER,
- PHY_SHORT,
- PHY_FIXEDPOINT88,
- PHY_UCHAR
-} PHY_ScalarType;
-
-///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
-///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
-ATTRIBUTE_ALIGNED16(class)
-btConcaveShape : public btCollisionShape
-{
-protected:
- btScalar m_collisionMargin;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConcaveShape();
-
- virtual ~btConcaveShape();
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const = 0;
-
- virtual btScalar getMargin() const
- {
- return m_collisionMargin;
- }
- virtual void setMargin(btScalar collisionMargin)
- {
- m_collisionMargin = collisionMargin;
- }
-};
-
-#endif //BT_CONCAVE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
deleted file mode 100644
index 64a6f272ca..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConeShape.h"
-
-btConeShape::btConeShape(btScalar radius, btScalar height) : btConvexInternalShape(),
- m_radius(radius),
- m_height(height)
-{
- m_shapeType = CONE_SHAPE_PROXYTYPE;
- setConeUpIndex(1);
- btVector3 halfExtents;
- m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
-}
-
-btConeShapeZ::btConeShapeZ(btScalar radius, btScalar height) : btConeShape(radius, height)
-{
- setConeUpIndex(2);
-}
-
-btConeShapeX::btConeShapeX(btScalar radius, btScalar height) : btConeShape(radius, height)
-{
- setConeUpIndex(0);
-}
-
-///choose upAxis index
-void btConeShape::setConeUpIndex(int upIndex)
-{
- switch (upIndex)
- {
- case 0:
- m_coneIndices[0] = 1;
- m_coneIndices[1] = 0;
- m_coneIndices[2] = 2;
- break;
- case 1:
- m_coneIndices[0] = 0;
- m_coneIndices[1] = 1;
- m_coneIndices[2] = 2;
- break;
- case 2:
- m_coneIndices[0] = 0;
- m_coneIndices[1] = 2;
- m_coneIndices[2] = 1;
- break;
- default:
- btAssert(0);
- };
-
- m_implicitShapeDimensions[m_coneIndices[0]] = m_radius;
- m_implicitShapeDimensions[m_coneIndices[1]] = m_height;
- m_implicitShapeDimensions[m_coneIndices[2]] = m_radius;
-}
-
-btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
-{
- btScalar halfHeight = m_height * btScalar(0.5);
-
- if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
- {
- btVector3 tmp;
-
- tmp[m_coneIndices[0]] = btScalar(0.);
- tmp[m_coneIndices[1]] = halfHeight;
- tmp[m_coneIndices[2]] = btScalar(0.);
- return tmp;
- }
- else
- {
- btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
- if (s > SIMD_EPSILON)
- {
- btScalar d = m_radius / s;
- btVector3 tmp;
- tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
- tmp[m_coneIndices[1]] = -halfHeight;
- tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
- return tmp;
- }
- else
- {
- btVector3 tmp;
- tmp[m_coneIndices[0]] = btScalar(0.);
- tmp[m_coneIndices[1]] = -halfHeight;
- tmp[m_coneIndices[2]] = btScalar(0.);
- return tmp;
- }
- }
-}
-
-btVector3 btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- return coneLocalSupport(vec);
-}
-
-void btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int i = 0; i < numVectors; i++)
- {
- const btVector3& vec = vectors[i];
- supportVerticesOut[i] = coneLocalSupport(vec);
- }
-}
-
-btVector3 btConeShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supVertex = coneLocalSupport(vec);
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
-}
-
-void btConeShape::setLocalScaling(const btVector3& scaling)
-{
- int axis = m_coneIndices[1];
- int r1 = m_coneIndices[0];
- int r2 = m_coneIndices[2];
- m_height *= scaling[axis] / m_localScaling[axis];
- m_radius *= (scaling[r1] / m_localScaling[r1] + scaling[r2] / m_localScaling[r2]) / 2;
- m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
- btConvexInternalShape::setLocalScaling(scaling);
-} \ No newline at end of file
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h
deleted file mode 100644
index 49f26bc4e5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConeShape.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONE_MINKOWSKI_H
-#define BT_CONE_MINKOWSKI_H
-
-#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
-ATTRIBUTE_ALIGNED16(class)
-btConeShape : public btConvexInternalShape
-
-{
- btScalar m_sinAngle;
- btScalar m_radius;
- btScalar m_height;
- int m_coneIndices[3];
- btVector3 coneLocalSupport(const btVector3& v) const;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConeShape(btScalar radius, btScalar height);
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- btScalar getRadius() const { return m_radius; }
- btScalar getHeight() const { return m_height; }
-
- void setRadius(const btScalar radius)
- {
- m_radius = radius;
- }
- void setHeight(const btScalar height)
- {
- m_height = height;
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
- {
- btTransform identity;
- identity.setIdentity();
- btVector3 aabbMin, aabbMax;
- getAabb(identity, aabbMin, aabbMax);
-
- btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
-
- btScalar margin = getMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-
- // inertia.x() = scaledmass * (y2+z2);
- // inertia.y() = scaledmass * (x2+z2);
- // inertia.z() = scaledmass * (x2+y2);
- }
-
- virtual const char* getName() const
- {
- return "Cone";
- }
-
- ///choose upAxis index
- void setConeUpIndex(int upIndex);
-
- int getConeUpIndex() const
- {
- return m_coneIndices[1];
- }
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- return btVector3(0, 1, 0);
- }
-
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///btConeShape implements a Cone shape, around the X axis
-class btConeShapeX : public btConeShape
-{
-public:
- btConeShapeX(btScalar radius, btScalar height);
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- return btVector3(1, 0, 0);
- }
-
- //debugging
- virtual const char* getName() const
- {
- return "ConeX";
- }
-};
-
-///btConeShapeZ implements a Cone shape, around the Z axis
-class btConeShapeZ : public btConeShape
-{
-public:
- btConeShapeZ(btScalar radius, btScalar height);
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- return btVector3(0, 0, 1);
- }
-
- //debugging
- virtual const char* getName() const
- {
- return "ConeZ";
- }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btConeShapeData
-{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- int m_upIndex;
-
- char m_padding[4];
-};
-
-SIMD_FORCE_INLINE int btConeShape::calculateSerializeBufferSize() const
-{
- return sizeof(btConeShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConeShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btConeShapeData* shapeData = (btConeShapeData*)dataBuffer;
-
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
-
- shapeData->m_upIndex = m_coneIndices[1];
-
- // Fill padding with zeros to appease msan.
- shapeData->m_padding[0] = 0;
- shapeData->m_padding[1] = 0;
- shapeData->m_padding[2] = 0;
- shapeData->m_padding[3] = 0;
-
- return "btConeShapeData";
-}
-
-#endif //BT_CONE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
deleted file mode 100644
index 7d3d1d362f..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvex2dShape.h"
-
-btConvex2dShape::btConvex2dShape(btConvexShape* convexChildShape) : btConvexShape(), m_childConvexShape(convexChildShape)
-{
- m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
-}
-
-btConvex2dShape::~btConvex2dShape()
-{
-}
-
-btVector3 btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
-}
-
-void btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors, supportVerticesOut, numVectors);
-}
-
-btVector3 btConvex2dShape::localGetSupportingVertex(const btVector3& vec) const
-{
- return m_childConvexShape->localGetSupportingVertex(vec);
-}
-
-void btConvex2dShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- ///this linear upscaling is not realistic, but we don't deal with large mass ratios...
- m_childConvexShape->calculateLocalInertia(mass, inertia);
-}
-
-///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btConvex2dShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- m_childConvexShape->getAabb(t, aabbMin, aabbMax);
-}
-
-void btConvex2dShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- m_childConvexShape->getAabbSlow(t, aabbMin, aabbMax);
-}
-
-void btConvex2dShape::setLocalScaling(const btVector3& scaling)
-{
- m_childConvexShape->setLocalScaling(scaling);
-}
-
-const btVector3& btConvex2dShape::getLocalScaling() const
-{
- return m_childConvexShape->getLocalScaling();
-}
-
-void btConvex2dShape::setMargin(btScalar margin)
-{
- m_childConvexShape->setMargin(margin);
-}
-btScalar btConvex2dShape::getMargin() const
-{
- return m_childConvexShape->getMargin();
-}
-
-int btConvex2dShape::getNumPreferredPenetrationDirections() const
-{
- return m_childConvexShape->getNumPreferredPenetrationDirections();
-}
-
-void btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
-{
- m_childConvexShape->getPreferredPenetrationDirection(index, penetrationVector);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
deleted file mode 100644
index cd4f1ef7b8..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_2D_SHAPE_H
-#define BT_CONVEX_2D_SHAPE_H
-
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-///The btConvex2dShape allows to use arbitrary convex shapes as 2d convex shapes, with the Z component assumed to be 0.
-///For 2d boxes, the btBox2dShape is recommended.
-ATTRIBUTE_ALIGNED16(class)
-btConvex2dShape : public btConvexShape
-{
- btConvexShape* m_childConvexShape;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvex2dShape(btConvexShape * convexChildShape);
-
- virtual ~btConvex2dShape();
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- btConvexShape* getChildShape()
- {
- return m_childConvexShape;
- }
-
- const btConvexShape* getChildShape() const
- {
- return m_childConvexShape;
- }
-
- virtual const char* getName() const
- {
- return "Convex2dShape";
- }
-
- ///////////////////////////
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
-
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
-
- virtual int getNumPreferredPenetrationDirections() const;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
-};
-
-#endif //BT_CONVEX_2D_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
deleted file mode 100644
index 703de45922..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#if defined(_WIN32) || defined(__i386__)
-#define BT_USE_SSE_IN_API
-#endif
-
-#include "btConvexHullShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-#include "LinearMath/btQuaternion.h"
-#include "LinearMath/btSerializer.h"
-#include "btConvexPolyhedron.h"
-#include "LinearMath/btConvexHullComputer.h"
-
-btConvexHullShape ::btConvexHullShape(const btScalar* points, int numPoints, int stride) : btPolyhedralConvexAabbCachingShape()
-{
- m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
- m_unscaledPoints.resize(numPoints);
-
- unsigned char* pointsAddress = (unsigned char*)points;
-
- for (int i = 0; i < numPoints; i++)
- {
- btScalar* point = (btScalar*)pointsAddress;
- m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
- pointsAddress += stride;
- }
-
- recalcLocalAabb();
-}
-
-void btConvexHullShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling;
- recalcLocalAabb();
-}
-
-void btConvexHullShape::addPoint(const btVector3& point, bool recalculateLocalAabb)
-{
- m_unscaledPoints.push_back(point);
- if (recalculateLocalAabb)
- recalcLocalAabb();
-}
-
-btVector3 btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
- btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
-
- // Here we take advantage of dot(a, b*c) = dot(a*b, c). Note: This is true mathematically, but not numerically.
- if (0 < m_unscaledPoints.size())
- {
- btVector3 scaled = vec * m_localScaling;
- int index = (int)scaled.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), maxDot); // FIXME: may violate encapsulation of m_unscaledPoints
- return m_unscaledPoints[index] * m_localScaling;
- }
-
- return supVec;
-}
-
-void btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- btScalar newDot;
- //use 'w' component of supportVerticesOut?
- {
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
- }
- }
-
- for (int j = 0; j < numVectors; j++)
- {
- btVector3 vec = vectors[j] * m_localScaling; // dot(a*b,c) = dot(a,b*c)
- if (0 < m_unscaledPoints.size())
- {
- int i = (int)vec.maxDot(&m_unscaledPoints[0], m_unscaledPoints.size(), newDot);
- supportVerticesOut[j] = getScaledPoint(i);
- supportVerticesOut[j][3] = newDot;
- }
- else
- supportVerticesOut[j][3] = -BT_LARGE_FLOAT;
- }
-}
-
-btVector3 btConvexHullShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
-}
-
-void btConvexHullShape::optimizeConvexHull()
-{
- btConvexHullComputer conv;
- conv.compute(&m_unscaledPoints[0].getX(), sizeof(btVector3), m_unscaledPoints.size(), 0.f, 0.f);
- int numVerts = conv.vertices.size();
- m_unscaledPoints.resize(0);
- for (int i = 0; i < numVerts; i++)
- {
- m_unscaledPoints.push_back(conv.vertices[i]);
- }
-}
-
-//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
-//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
-int btConvexHullShape::getNumVertices() const
-{
- return m_unscaledPoints.size();
-}
-
-int btConvexHullShape::getNumEdges() const
-{
- return m_unscaledPoints.size();
-}
-
-void btConvexHullShape::getEdge(int i, btVector3& pa, btVector3& pb) const
-{
- int index0 = i % m_unscaledPoints.size();
- int index1 = (i + 1) % m_unscaledPoints.size();
- pa = getScaledPoint(index0);
- pb = getScaledPoint(index1);
-}
-
-void btConvexHullShape::getVertex(int i, btVector3& vtx) const
-{
- vtx = getScaledPoint(i);
-}
-
-int btConvexHullShape::getNumPlanes() const
-{
- return 0;
-}
-
-void btConvexHullShape::getPlane(btVector3&, btVector3&, int) const
-{
- btAssert(0);
-}
-
-//not yet
-bool btConvexHullShape::isInside(const btVector3&, btScalar) const
-{
- btAssert(0);
- return false;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- //int szc = sizeof(btConvexHullShapeData);
- btConvexHullShapeData* shapeData = (btConvexHullShapeData*)dataBuffer;
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
-
- int numElem = m_unscaledPoints.size();
- shapeData->m_numUnscaledPoints = numElem;
-#ifdef BT_USE_DOUBLE_PRECISION
- shapeData->m_unscaledPointsFloatPtr = 0;
- shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
-#else
- shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]) : 0;
- shapeData->m_unscaledPointsDoublePtr = 0;
-#endif
-
- if (numElem)
- {
- int sz = sizeof(btVector3Data);
- // int sz2 = sizeof(btVector3DoubleData);
- // int sz3 = sizeof(btVector3FloatData);
- btChunk* chunk = serializer->allocate(sz, numElem);
- btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_unscaledPoints[i].serialize(*memPtr);
- }
- serializer->finalizeChunk(chunk, btVector3DataName, BT_ARRAY_CODE, (void*)&m_unscaledPoints[0]);
- }
-
- // Fill padding with zeros to appease msan.
- memset(shapeData->m_padding3, 0, sizeof(shapeData->m_padding3));
-
- return "btConvexHullShapeData";
-}
-
-void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
-{
-#if 1
- minProj = FLT_MAX;
- maxProj = -FLT_MAX;
-
- int numVerts = m_unscaledPoints.size();
- for (int i = 0; i < numVerts; i++)
- {
- btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
- btVector3 pt = trans * vtx;
- btScalar dp = pt.dot(dir);
- if (dp < minProj)
- {
- minProj = dp;
- witnesPtMin = pt;
- }
- if (dp > maxProj)
- {
- maxProj = dp;
- witnesPtMax = pt;
- }
- }
-#else
- btVector3 localAxis = dir * trans.getBasis();
- witnesPtMin = trans(localGetSupportingVertex(localAxis));
- witnesPtMax = trans(localGetSupportingVertex(-localAxis));
-
- minProj = witnesPtMin.dot(dir);
- maxProj = witnesPtMax.dot(dir);
-#endif
-
- if (minProj > maxProj)
- {
- btSwap(minProj, maxProj);
- btSwap(witnesPtMin, witnesPtMax);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
deleted file mode 100644
index 96136d7dd7..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_HULL_SHAPE_H
-#define BT_CONVEX_HULL_SHAPE_H
-
-#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "LinearMath/btAlignedObjectArray.h"
-
-///The btConvexHullShape implements an implicit convex hull of an array of vertices.
-///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
-ATTRIBUTE_ALIGNED16(class)
-btConvexHullShape : public btPolyhedralConvexAabbCachingShape
-{
- btAlignedObjectArray<btVector3> m_unscaledPoints;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
- ///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
- ///btConvexHullShape make an internal copy of the points.
- btConvexHullShape(const btScalar* points = 0, int numPoints = 0, int stride = sizeof(btVector3));
-
- void addPoint(const btVector3& point, bool recalculateLocalAabb = true);
-
- btVector3* getUnscaledPoints()
- {
- return &m_unscaledPoints[0];
- }
-
- const btVector3* getUnscaledPoints() const
- {
- return &m_unscaledPoints[0];
- }
-
- ///getPoints is obsolete, please use getUnscaledPoints
- const btVector3* getPoints() const
- {
- return getUnscaledPoints();
- }
-
- void optimizeConvexHull();
-
- SIMD_FORCE_INLINE btVector3 getScaledPoint(int i) const
- {
- return m_unscaledPoints[i] * m_localScaling;
- }
-
- SIMD_FORCE_INLINE int getNumPoints() const
- {
- return m_unscaledPoints.size();
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
-
- //debugging
- virtual const char* getName() const { return "Convex"; }
-
- virtual int getNumVertices() const;
- virtual int getNumEdges() const;
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
- virtual void getVertex(int i, btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
-
- ///in case we receive negative scaling
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btConvexHullShapeData
-{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- btVector3FloatData *m_unscaledPointsFloatPtr;
- btVector3DoubleData *m_unscaledPointsDoublePtr;
-
- int m_numUnscaledPoints;
- char m_padding3[4];
-
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btConvexHullShape::calculateSerializeBufferSize() const
-{
- return sizeof(btConvexHullShapeData);
-}
-
-#endif //BT_CONVEX_HULL_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
deleted file mode 100644
index 4d598b1aa2..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexInternalShape.h"
-
-btConvexInternalShape::btConvexInternalShape()
- : m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.)),
- m_collisionMargin(CONVEX_DISTANCE_MARGIN)
-{
-}
-
-void btConvexInternalShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling.absolute();
-}
-
-void btConvexInternalShape::getAabbSlow(const btTransform& trans, btVector3& minAabb, btVector3& maxAabb) const
-{
-#ifndef __SPU__
- //use localGetSupportingVertexWithoutMargin?
- btScalar margin = getMargin();
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
-
- btVector3 sv = localGetSupportingVertex(vec * trans.getBasis());
-
- btVector3 tmp = trans(sv);
- maxAabb[i] = tmp[i] + margin;
- vec[i] = btScalar(-1.);
- tmp = trans(localGetSupportingVertex(vec * trans.getBasis()));
- minAabb[i] = tmp[i] - margin;
- }
-#endif
-}
-
-btVector3 btConvexInternalShape::localGetSupportingVertex(const btVector3& vec) const
-{
-#ifndef __SPU__
-
- btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
-
-#else
- btAssert(0);
- return btVector3(0, 0, 0);
-#endif //__SPU__
-}
-
-btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
- : btConvexInternalShape(),
- m_localAabbMin(1, 1, 1),
- m_localAabbMax(-1, -1, -1),
- m_isLocalAabbValid(false)
-{
-}
-
-void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
-}
-
-void btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
-{
- btConvexInternalShape::setLocalScaling(scaling);
- recalcLocalAabb();
-}
-
-void btConvexInternalAabbCachingShape::recalcLocalAabb()
-{
- m_isLocalAabbValid = true;
-
-#if 1
- static const btVector3 _directions[] =
- {
- btVector3(1., 0., 0.),
- btVector3(0., 1., 0.),
- btVector3(0., 0., 1.),
- btVector3(-1., 0., 0.),
- btVector3(0., -1., 0.),
- btVector3(0., 0., -1.)};
-
- btVector3 _supporting[] =
- {
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.)};
-
- batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- for (int i = 0; i < 3; ++i)
- {
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
- }
-
-#else
-
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
- btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i] + m_collisionMargin;
- vec[i] = btScalar(-1.);
- tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i] - m_collisionMargin;
- }
-#endif
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
deleted file mode 100644
index a28c57de4b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_INTERNAL_SHAPE_H
-#define BT_CONVEX_INTERNAL_SHAPE_H
-
-#include "btConvexShape.h"
-#include "LinearMath/btAabbUtil2.h"
-
-///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
-///The btConvexInternalShape uses a default collision margin set to CONVEX_DISTANCE_MARGIN.
-///This collision margin used by Gjk and some other algorithms, see also btCollisionMargin.h
-///Note that when creating small shapes (derived from btConvexInternalShape),
-///you need to make sure to set a smaller collision margin, using the 'setMargin' API
-///There is a automatic mechanism 'setSafeMargin' used by btBoxShape and btCylinderShape
-ATTRIBUTE_ALIGNED16(class)
-btConvexInternalShape : public btConvexShape
-{
-protected:
- //local scaling. collisionMargin is not scaled !
- btVector3 m_localScaling;
-
- btVector3 m_implicitShapeDimensions;
-
- btScalar m_collisionMargin;
-
- btScalar m_padding;
-
- btConvexInternalShape();
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- virtual ~btConvexInternalShape()
- {
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
-
- const btVector3& getImplicitShapeDimensions() const
- {
- return m_implicitShapeDimensions;
- }
-
- ///warning: use setImplicitShapeDimensions with care
- ///changing a collision shape while the body is in the world is not recommended,
- ///it is best to remove the body from the world, then make the change, and re-add it
- ///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
- void setImplicitShapeDimensions(const btVector3& dimensions)
- {
- m_implicitShapeDimensions = dimensions;
- }
-
- void setSafeMargin(btScalar minDimension, btScalar defaultMarginMultiplier = 0.1f)
- {
- btScalar safeMargin = defaultMarginMultiplier * minDimension;
- if (safeMargin < getMargin())
- {
- setMargin(safeMargin);
- }
- }
- void setSafeMargin(const btVector3& halfExtents, btScalar defaultMarginMultiplier = 0.1f)
- {
- //see http://code.google.com/p/bullet/issues/detail?id=349
- //this margin check could could be added to other collision shapes too,
- //or add some assert/warning somewhere
- btScalar minDimension = halfExtents[halfExtents.minAxis()];
- setSafeMargin(minDimension, defaultMarginMultiplier);
- }
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- getAabbSlow(t, aabbMin, aabbMax);
- }
-
- virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const
- {
- return m_localScaling;
- }
-
- const btVector3& getLocalScalingNV() const
- {
- return m_localScaling;
- }
-
- virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
- }
- virtual btScalar getMargin() const
- {
- return m_collisionMargin;
- }
-
- btScalar getMarginNV() const
- {
- return m_collisionMargin;
- }
-
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 0;
- }
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- (void)penetrationVector;
- (void)index;
- btAssert(0);
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btConvexInternalShapeData
-{
- btCollisionShapeData m_collisionShapeData;
-
- btVector3FloatData m_localScaling;
-
- btVector3FloatData m_implicitShapeDimensions;
-
- float m_collisionMargin;
-
- int m_padding;
-};
-
-SIMD_FORCE_INLINE int btConvexInternalShape::calculateSerializeBufferSize() const
-{
- return sizeof(btConvexInternalShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*)dataBuffer;
- btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
-
- m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
- m_localScaling.serializeFloat(shapeData->m_localScaling);
- shapeData->m_collisionMargin = float(m_collisionMargin);
-
- // Fill padding with zeros to appease msan.
- shapeData->m_padding = 0;
-
- return "btConvexInternalShapeData";
-}
-
-///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
-class btConvexInternalAabbCachingShape : public btConvexInternalShape
-{
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- bool m_isLocalAabbValid;
-
-protected:
- btConvexInternalAabbCachingShape();
-
- void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
- {
- m_isLocalAabbValid = true;
- m_localAabbMin = aabbMin;
- m_localAabbMax = aabbMax;
- }
-
- inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- btAssert(m_isLocalAabbValid);
- aabbMin = m_localAabbMin;
- aabbMax = m_localAabbMax;
- }
-
- inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
- {
- //lazy evaluation of local aabb
- btAssert(m_isLocalAabbValid);
- btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
- }
-
-public:
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- void recalcLocalAabb();
-};
-
-#endif //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
deleted file mode 100644
index f00a440fa3..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexPointCloudShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-#include "LinearMath/btQuaternion.h"
-
-void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling;
- recalcLocalAabb();
-}
-
-#ifndef __SPU__
-btVector3 btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
-{
- btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
- btScalar maxDot = btScalar(-BT_LARGE_FLOAT);
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < btScalar(0.0001))
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
-
- if (m_numPoints > 0)
- {
- // Here we take advantage of dot(a*b, c) = dot( a, b*c) to do less work. Note this transformation is true mathematically, not numerically.
- // btVector3 scaled = vec * m_localScaling;
- int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot); //FIXME: may violate encapsulation of m_unscaledPoints
- return getScaledPoint(index);
- }
-
- return supVec;
-}
-
-void btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int j = 0; j < numVectors; j++)
- {
- const btVector3& vec = vectors[j] * m_localScaling; // dot( a*c, b) = dot(a, b*c)
- btScalar maxDot;
- int index = (int)vec.maxDot(&m_unscaledPoints[0], m_numPoints, maxDot);
- supportVerticesOut[j][3] = btScalar(-BT_LARGE_FLOAT);
- if (0 <= index)
- {
- //WARNING: don't swap next lines, the w component would get overwritten!
- supportVerticesOut[j] = getScaledPoint(index);
- supportVerticesOut[j][3] = maxDot;
- }
- }
-}
-
-btVector3 btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
-}
-
-#endif
-
-//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
-//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
-int btConvexPointCloudShape::getNumVertices() const
-{
- return m_numPoints;
-}
-
-int btConvexPointCloudShape::getNumEdges() const
-{
- return 0;
-}
-
-void btConvexPointCloudShape::getEdge(int i, btVector3& pa, btVector3& pb) const
-{
- btAssert(0);
-}
-
-void btConvexPointCloudShape::getVertex(int i, btVector3& vtx) const
-{
- vtx = m_unscaledPoints[i] * m_localScaling;
-}
-
-int btConvexPointCloudShape::getNumPlanes() const
-{
- return 0;
-}
-
-void btConvexPointCloudShape::getPlane(btVector3&, btVector3&, int) const
-{
- btAssert(0);
-}
-
-//not yet
-bool btConvexPointCloudShape::isInside(const btVector3&, btScalar) const
-{
- btAssert(0);
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
deleted file mode 100644
index c7d554a4d3..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H
-#define BT_CONVEX_POINT_CLOUD_SHAPE_H
-
-#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "LinearMath/btAlignedObjectArray.h"
-
-///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
-ATTRIBUTE_ALIGNED16(class)
-btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
-{
- btVector3* m_unscaledPoints;
- int m_numPoints;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexPointCloudShape()
- {
- m_localScaling.setValue(1.f, 1.f, 1.f);
- m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
- m_unscaledPoints = 0;
- m_numPoints = 0;
- }
-
- btConvexPointCloudShape(btVector3 * points, int numPoints, const btVector3& localScaling, bool computeAabb = true)
- {
- m_localScaling = localScaling;
- m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
- m_unscaledPoints = points;
- m_numPoints = numPoints;
-
- if (computeAabb)
- recalcLocalAabb();
- }
-
- void setPoints(btVector3 * points, int numPoints, bool computeAabb = true, const btVector3& localScaling = btVector3(1.f, 1.f, 1.f))
- {
- m_unscaledPoints = points;
- m_numPoints = numPoints;
- m_localScaling = localScaling;
-
- if (computeAabb)
- recalcLocalAabb();
- }
-
- SIMD_FORCE_INLINE btVector3* getUnscaledPoints()
- {
- return m_unscaledPoints;
- }
-
- SIMD_FORCE_INLINE const btVector3* getUnscaledPoints() const
- {
- return m_unscaledPoints;
- }
-
- SIMD_FORCE_INLINE int getNumPoints() const
- {
- return m_numPoints;
- }
-
- SIMD_FORCE_INLINE btVector3 getScaledPoint(int index) const
- {
- return m_unscaledPoints[index] * m_localScaling;
- }
-
-#ifndef __SPU__
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-#endif
-
- //debugging
- virtual const char* getName() const { return "ConvexPointCloud"; }
-
- virtual int getNumVertices() const;
- virtual int getNumEdges() const;
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
- virtual void getVertex(int i, btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
-
- ///in case we receive negative scaling
- virtual void setLocalScaling(const btVector3& scaling);
-};
-
-#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
deleted file mode 100644
index 9694f4ddb3..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-///Separating axis rest based on work from Pierre Terdiman, see
-///And contact clipping based on work from Simon Hobbs
-
-#include "btConvexPolyhedron.h"
-#include "LinearMath/btHashMap.h"
-
-btConvexPolyhedron::btConvexPolyhedron()
-{
-}
-btConvexPolyhedron::~btConvexPolyhedron()
-{
-}
-
-inline bool IsAlmostZero1(const btVector3& v)
-{
- if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
- return true;
-}
-
-struct btInternalVertexPair
-{
- btInternalVertexPair(short int v0, short int v1)
- : m_v0(v0),
- m_v1(v1)
- {
- if (m_v1 > m_v0)
- btSwap(m_v0, m_v1);
- }
- short int m_v0;
- short int m_v1;
- int getHash() const
- {
- return m_v0 + (m_v1 << 16);
- }
- bool equals(const btInternalVertexPair& other) const
- {
- return m_v0 == other.m_v0 && m_v1 == other.m_v1;
- }
-};
-
-struct btInternalEdge
-{
- btInternalEdge()
- : m_face0(-1),
- m_face1(-1)
- {
- }
- short int m_face0;
- short int m_face1;
-};
-
-//
-
-#ifdef TEST_INTERNAL_OBJECTS
-bool btConvexPolyhedron::testContainment() const
-{
- for (int p = 0; p < 8; p++)
- {
- btVector3 LocalPt;
- if (p == 0)
- LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
- else if (p == 1)
- LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
- else if (p == 2)
- LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
- else if (p == 3)
- LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
- else if (p == 4)
- LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
- else if (p == 5)
- LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
- else if (p == 6)
- LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
- else if (p == 7)
- LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
-
- for (int i = 0; i < m_faces.size(); i++)
- {
- const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
- const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
- if (d > 0.0f)
- return false;
- }
- }
- return true;
-}
-#endif
-
-void btConvexPolyhedron::initialize()
-{
- btHashMap<btInternalVertexPair, btInternalEdge> edges;
-
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices;
- for (int j = 0; j < NbTris; j++)
- {
- int k = (j + 1) % numVertices;
- btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
- btInternalEdge* edptr = edges.find(vp);
- btVector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
- edge.normalize();
-
- bool found = false;
-
- for (int p = 0; p < m_uniqueEdges.size(); p++)
- {
- if (IsAlmostZero1(m_uniqueEdges[p] - edge) ||
- IsAlmostZero1(m_uniqueEdges[p] + edge))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- m_uniqueEdges.push_back(edge);
- }
-
- if (edptr)
- {
- btAssert(edptr->m_face0 >= 0);
- btAssert(edptr->m_face1 < 0);
- edptr->m_face1 = i;
- }
- else
- {
- btInternalEdge ed;
- ed.m_face0 = i;
- edges.insert(vp, ed);
- }
- }
- }
-
-#ifdef USE_CONNECTED_FACES
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- m_faces[i].m_connectedFaces.resize(numVertices);
-
- for (int j = 0; j < numVertices; j++)
- {
- int k = (j + 1) % numVertices;
- btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
- btInternalEdge* edptr = edges.find(vp);
- btAssert(edptr);
- btAssert(edptr->m_face0 >= 0);
- btAssert(edptr->m_face1 >= 0);
-
- int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
- m_faces[i].m_connectedFaces[j] = connectedFace;
- }
- }
-#endif //USE_CONNECTED_FACES
-
- initialize2();
-}
-
-void btConvexPolyhedron::initialize2()
-{
- m_localCenter.setValue(0, 0, 0);
- btScalar TotalArea = 0.0f;
- for (int i = 0; i < m_faces.size(); i++)
- {
- int numVertices = m_faces[i].m_indices.size();
- int NbTris = numVertices - 2;
-
- const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
- for (int j = 1; j <= NbTris; j++)
- {
- int k = (j + 1) % numVertices;
- const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
- const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
- btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
- btVector3 Center = (p0 + p1 + p2) / 3.0f;
- m_localCenter += Area * Center;
- TotalArea += Area;
- }
- }
- m_localCenter /= TotalArea;
-
-#ifdef TEST_INTERNAL_OBJECTS
- if (1)
- {
- m_radius = FLT_MAX;
- for (int i = 0; i < m_faces.size(); i++)
- {
- const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
- const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
- if (dist < m_radius)
- m_radius = dist;
- }
-
- btScalar MinX = FLT_MAX;
- btScalar MinY = FLT_MAX;
- btScalar MinZ = FLT_MAX;
- btScalar MaxX = -FLT_MAX;
- btScalar MaxY = -FLT_MAX;
- btScalar MaxZ = -FLT_MAX;
- for (int i = 0; i < m_vertices.size(); i++)
- {
- const btVector3& pt = m_vertices[i];
- if (pt.x() < MinX) MinX = pt.x();
- if (pt.x() > MaxX) MaxX = pt.x();
- if (pt.y() < MinY) MinY = pt.y();
- if (pt.y() > MaxY) MaxY = pt.y();
- if (pt.z() < MinZ) MinZ = pt.z();
- if (pt.z() > MaxZ) MaxZ = pt.z();
- }
- mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
- mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
-
- // const btScalar r = m_radius / sqrtf(2.0f);
- const btScalar r = m_radius / sqrtf(3.0f);
- const int LargestExtent = mE.maxAxis();
- const btScalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
- m_extents[0] = m_extents[1] = m_extents[2] = r;
- m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
- bool FoundBox = false;
- for (int j = 0; j < 1024; j++)
- {
- if (testContainment())
- {
- FoundBox = true;
- break;
- }
-
- m_extents[LargestExtent] -= Step;
- }
- if (!FoundBox)
- {
- m_extents[0] = m_extents[1] = m_extents[2] = r;
- }
- else
- {
- // Refine the box
- const btScalar Step = (m_radius - r) / 1024.0f;
- const int e0 = (1 << LargestExtent) & 3;
- const int e1 = (1 << e0) & 3;
-
- for (int j = 0; j < 1024; j++)
- {
- const btScalar Saved0 = m_extents[e0];
- const btScalar Saved1 = m_extents[e1];
- m_extents[e0] += Step;
- m_extents[e1] += Step;
-
- if (!testContainment())
- {
- m_extents[e0] = Saved0;
- m_extents[e1] = Saved1;
- break;
- }
- }
- }
- }
-#endif
-}
-void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
-{
- minProj = FLT_MAX;
- maxProj = -FLT_MAX;
- int numVerts = m_vertices.size();
- for (int i = 0; i < numVerts; i++)
- {
- btVector3 pt = trans * m_vertices[i];
- btScalar dp = pt.dot(dir);
- if (dp < minProj)
- {
- minProj = dp;
- witnesPtMin = pt;
- }
- if (dp > maxProj)
- {
- maxProj = dp;
- witnesPtMax = pt;
- }
- }
- if (minProj > maxProj)
- {
- btSwap(minProj, maxProj);
- btSwap(witnesPtMin, witnesPtMax);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
deleted file mode 100644
index 638aa9b3df..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef _BT_POLYHEDRAL_FEATURES_H
-#define _BT_POLYHEDRAL_FEATURES_H
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-#define TEST_INTERNAL_OBJECTS 1
-
-struct btFace
-{
- btAlignedObjectArray<int> m_indices;
- // btAlignedObjectArray<int> m_connectedFaces;
- btScalar m_plane[4];
-};
-
-ATTRIBUTE_ALIGNED16(class)
-btConvexPolyhedron
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexPolyhedron();
- virtual ~btConvexPolyhedron();
-
- btAlignedObjectArray<btVector3> m_vertices;
- btAlignedObjectArray<btFace> m_faces;
- btAlignedObjectArray<btVector3> m_uniqueEdges;
-
- btVector3 m_localCenter;
- btVector3 m_extents;
- btScalar m_radius;
- btVector3 mC;
- btVector3 mE;
-
- void initialize();
- void initialize2();
- bool testContainment() const;
-
- void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
-};
-
-#endif //_BT_POLYHEDRAL_FEATURES_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
deleted file mode 100644
index f8fb0aa9fd..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#if defined(_WIN32) || defined(__i386__)
-#define BT_USE_SSE_IN_API
-#endif
-
-#include "btConvexShape.h"
-#include "btTriangleShape.h"
-#include "btSphereShape.h"
-#include "btCylinderShape.h"
-#include "btConeShape.h"
-#include "btCapsuleShape.h"
-#include "btConvexHullShape.h"
-#include "btConvexPointCloudShape.h"
-
-///not supported on IBM SDK, until we fix the alignment of btVector3
-#if defined(__CELLOS_LV2__) && defined(__SPU__)
-#include <spu_intrinsics.h>
-static inline vec_float4 vec_dot3(vec_float4 vec0, vec_float4 vec1)
-{
- vec_float4 result;
- result = spu_mul(vec0, vec1);
- result = spu_madd(spu_rlqwbyte(vec0, 4), spu_rlqwbyte(vec1, 4), result);
- return spu_madd(spu_rlqwbyte(vec0, 8), spu_rlqwbyte(vec1, 8), result);
-}
-#endif //__SPU__
-
-btConvexShape::btConvexShape()
-{
-}
-
-btConvexShape::~btConvexShape()
-{
-}
-
-void btConvexShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max, btVector3& witnesPtMin, btVector3& witnesPtMax) const
-{
- btVector3 localAxis = dir * trans.getBasis();
- btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
- btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
-
- min = vtx1.dot(dir);
- max = vtx2.dot(dir);
- witnesPtMax = vtx2;
- witnesPtMin = vtx1;
-
- if (min > max)
- {
- btScalar tmp = min;
- min = max;
- max = tmp;
- witnesPtMax = vtx1;
- witnesPtMin = vtx2;
- }
-}
-
-static btVector3 convexHullSupport(const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
-{
- btVector3 vec = localDirOrg * localScaling;
-
-#if defined(__CELLOS_LV2__) && defined(__SPU__)
-
- btVector3 localDir = vec;
-
- vec_float4 v_distMax = {-FLT_MAX, 0, 0, 0};
- vec_int4 v_idxMax = {-999, 0, 0, 0};
- int v = 0;
- int numverts = numPoints;
-
- for (; v < (int)numverts - 4; v += 4)
- {
- vec_float4 p0 = vec_dot3(points[v].get128(), localDir.get128());
- vec_float4 p1 = vec_dot3(points[v + 1].get128(), localDir.get128());
- vec_float4 p2 = vec_dot3(points[v + 2].get128(), localDir.get128());
- vec_float4 p3 = vec_dot3(points[v + 3].get128(), localDir.get128());
- const vec_int4 i0 = {v, 0, 0, 0};
- const vec_int4 i1 = {v + 1, 0, 0, 0};
- const vec_int4 i2 = {v + 2, 0, 0, 0};
- const vec_int4 i3 = {v + 3, 0, 0, 0};
- vec_uint4 retGt01 = spu_cmpgt(p0, p1);
- vec_float4 pmax01 = spu_sel(p1, p0, retGt01);
- vec_int4 imax01 = spu_sel(i1, i0, retGt01);
- vec_uint4 retGt23 = spu_cmpgt(p2, p3);
- vec_float4 pmax23 = spu_sel(p3, p2, retGt23);
- vec_int4 imax23 = spu_sel(i3, i2, retGt23);
- vec_uint4 retGt0123 = spu_cmpgt(pmax01, pmax23);
- vec_float4 pmax0123 = spu_sel(pmax23, pmax01, retGt0123);
- vec_int4 imax0123 = spu_sel(imax23, imax01, retGt0123);
- vec_uint4 retGtMax = spu_cmpgt(v_distMax, pmax0123);
- v_distMax = spu_sel(pmax0123, v_distMax, retGtMax);
- v_idxMax = spu_sel(imax0123, v_idxMax, retGtMax);
- }
- for (; v < (int)numverts; v++)
- {
- vec_float4 p = vec_dot3(points[v].get128(), localDir.get128());
- const vec_int4 i = {v, 0, 0, 0};
- vec_uint4 retGtMax = spu_cmpgt(v_distMax, p);
- v_distMax = spu_sel(p, v_distMax, retGtMax);
- v_idxMax = spu_sel(i, v_idxMax, retGtMax);
- }
- int ptIndex = spu_extract(v_idxMax, 0);
- const btVector3& supVec = points[ptIndex] * localScaling;
- return supVec;
-#else
-
- btScalar maxDot;
- long ptIndex = vec.maxDot(points, numPoints, maxDot);
- btAssert(ptIndex >= 0);
- if (ptIndex < 0)
- {
- ptIndex = 0;
- }
- btVector3 supVec = points[ptIndex] * localScaling;
- return supVec;
-#endif //__SPU__
-}
-
-btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual(const btVector3& localDir) const
-{
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- return btVector3(0, 0, 0);
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
-
-#if defined(__APPLE__) && (defined(BT_USE_SSE) || defined(BT_USE_NEON))
-#if defined(BT_USE_SSE)
- return btVector3(_mm_xor_ps(_mm_and_ps(localDir.mVec128, (__m128){-0.0f, -0.0f, -0.0f, -0.0f}), halfExtents.mVec128));
-#elif defined(BT_USE_NEON)
- return btVector3((float32x4_t)(((uint32x4_t)localDir.mVec128 & (uint32x4_t){0x80000000, 0x80000000, 0x80000000, 0x80000000}) ^ (uint32x4_t)halfExtents.mVec128));
-#else
-#error unknown vector arch
-#endif
-#else
- return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
- btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
- btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
-#endif
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btVector3 dir(localDir.getX(), localDir.getY(), localDir.getZ());
- btVector3* vertices = &triangleShape->m_vertices1[0];
- btVector3 dots = dir.dot3(vertices[0], vertices[1], vertices[2]);
- btVector3 sup = vertices[dots.maxAxis()];
- return btVector3(sup.getX(), sup.getY(), sup.getZ());
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- //mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
-
- btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
- btVector3 v(localDir.getX(), localDir.getY(), localDir.getZ());
- int cylinderUpAxis = cylShape->getUpAxis();
- int XX(1), YY(0), ZZ(2);
-
- switch (cylinderUpAxis)
- {
- case 0:
- {
- XX = 1;
- YY = 0;
- ZZ = 2;
- }
- break;
- case 1:
- {
- XX = 0;
- YY = 1;
- ZZ = 2;
- }
- break;
- case 2:
- {
- XX = 0;
- YY = 2;
- ZZ = 1;
- }
- break;
- default:
- btAssert(0);
- break;
- };
-
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
-
- btVector3 tmp;
- btScalar d;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
- }
- else
- {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return btVector3(tmp.getX(), tmp.getY(), tmp.getZ());
- }
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btVector3 vec0(localDir.getX(), localDir.getY(), localDir.getZ());
-
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btScalar halfHeight = capsuleShape->getHalfHeight();
- int capsuleUpAxis = capsuleShape->getUpAxis();
-
- btVector3 supVec(0, 0, 0);
-
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < SIMD_EPSILON * SIMD_EPSILON)
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
- btVector3 vtx;
- btScalar newDot;
- {
- btVector3 pos(0, 0, 0);
- pos[capsuleUpAxis] = halfHeight;
-
- vtx = pos;
- newDot = vec.dot(vtx);
-
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- {
- btVector3 pos(0, 0, 0);
- pos[capsuleUpAxis] = -halfHeight;
-
- vtx = pos;
- newDot = vec.dot(vtx);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = vtx;
- }
- }
- return btVector3(supVec.getX(), supVec.getY(), supVec.getZ());
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- {
- btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
- btVector3* points = convexPointCloudShape->getUnscaledPoints();
- int numPoints = convexPointCloudShape->getNumPoints();
- return convexHullSupport(localDir, points, numPoints, convexPointCloudShape->getLocalScalingNV());
- }
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
- btVector3* points = convexHullShape->getUnscaledPoints();
- int numPoints = convexHullShape->getNumPoints();
- return convexHullSupport(localDir, points, numPoints, convexHullShape->getLocalScalingNV());
- }
- default:
-#ifndef __SPU__
- return this->localGetSupportingVertexWithoutMargin(localDir);
-#else
- btAssert(0);
-#endif
- }
-
- // should never reach here
- btAssert(0);
- return btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
-}
-
-btVector3 btConvexShape::localGetSupportVertexNonVirtual(const btVector3& localDir) const
-{
- btVector3 localDirNorm = localDir;
- if (localDirNorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- localDirNorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- localDirNorm.normalize();
-
- return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm) + getMarginNonVirtual() * localDirNorm;
-}
-
-/* TODO: This should be bumped up to btCollisionShape () */
-btScalar btConvexShape::getMarginNonVirtual() const
-{
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- return sphereShape->getRadius();
- }
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- return convexShape->getMarginNV();
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- return triangleShape->getMarginNV();
- }
- case CYLINDER_SHAPE_PROXYTYPE:
- {
- btCylinderShape* cylShape = (btCylinderShape*)this;
- return cylShape->getMarginNV();
- }
- case CONE_SHAPE_PROXYTYPE:
- {
- btConeShape* conShape = (btConeShape*)this;
- return conShape->getMarginNV();
- }
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- return capsuleShape->getMarginNV();
- }
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- /* fall through */
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
- return convexHullShape->getMarginNV();
- }
- default:
-#ifndef __SPU__
- return this->getMargin();
-#else
- btAssert(0);
-#endif
- }
-
- // should never reach here
- btAssert(0);
- return btScalar(0.0f);
-}
-#ifndef __SPU__
-void btConvexShape::getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- switch (m_shapeType)
- {
- case SPHERE_SHAPE_PROXYTYPE:
- {
- btSphereShape* sphereShape = (btSphereShape*)this;
- btScalar radius = sphereShape->getImplicitShapeDimensions().getX(); // * convexShape->getLocalScaling().getX();
- btScalar margin = radius + sphereShape->getMarginNonVirtual();
- const btVector3& center = t.getOrigin();
- btVector3 extent(margin, margin, margin);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CYLINDER_SHAPE_PROXYTYPE:
- /* fall through */
- case BOX_SHAPE_PROXYTYPE:
- {
- btBoxShape* convexShape = (btBoxShape*)this;
- btScalar margin = convexShape->getMarginNonVirtual();
- btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
- halfExtents += btVector3(margin, margin, margin);
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
-
- aabbMin = center - extent;
- aabbMax = center + extent;
- break;
- }
- case TRIANGLE_SHAPE_PROXYTYPE:
- {
- btTriangleShape* triangleShape = (btTriangleShape*)this;
- btScalar margin = triangleShape->getMarginNonVirtual();
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
-
- btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis());
-
- btVector3 tmp = t(sv);
- aabbMax[i] = tmp[i] + margin;
- vec[i] = btScalar(-1.);
- tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec * t.getBasis()));
- aabbMin[i] = tmp[i] - margin;
- }
- }
- break;
- case CAPSULE_SHAPE_PROXYTYPE:
- {
- btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
- btVector3 halfExtents(capsuleShape->getRadius(), capsuleShape->getRadius(), capsuleShape->getRadius());
- int m_upAxis = capsuleShape->getUpAxis();
- halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
- }
- break;
- case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
- case CONVEX_HULL_SHAPE_PROXYTYPE:
- {
- btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
- btScalar margin = convexHullShape->getMarginNonVirtual();
- convexHullShape->getNonvirtualAabb(t, aabbMin, aabbMax, margin);
- }
- break;
- default:
-#ifndef __SPU__
- this->getAabb(t, aabbMin, aabbMax);
-#else
- btAssert(0);
-#endif
- break;
- }
-
- // should never reach here
- btAssert(0);
-}
-
-#endif //__SPU__
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h
deleted file mode 100644
index d3b3ed816e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexShape.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_SHAPE_INTERFACE1
-#define BT_CONVEX_SHAPE_INTERFACE1
-
-#include "btCollisionShape.h"
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "btCollisionMargin.h"
-#include "LinearMath/btAlignedAllocator.h"
-
-#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
-
-/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
-/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
-ATTRIBUTE_ALIGNED16(class)
-btConvexShape : public btCollisionShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexShape();
-
- virtual ~btConvexShape();
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const = 0;
-
-////////
-#ifndef __SPU__
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const = 0;
-#endif //#ifndef __SPU__
-
- btVector3 localGetSupportVertexWithoutMarginNonVirtual(const btVector3& vec) const;
- btVector3 localGetSupportVertexNonVirtual(const btVector3& vec) const;
- btScalar getMarginNonVirtual() const;
- void getAabbNonVirtual(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const;
-
- //notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const = 0;
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
-
- virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const = 0;
-
- virtual void setLocalScaling(const btVector3& scaling) = 0;
- virtual const btVector3& getLocalScaling() const = 0;
-
- virtual void setMargin(btScalar margin) = 0;
-
- virtual btScalar getMargin() const = 0;
-
- virtual int getNumPreferredPenetrationDirections() const = 0;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const = 0;
-};
-
-#endif //BT_CONVEX_SHAPE_INTERFACE1
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
deleted file mode 100644
index f6987cc760..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-#include "LinearMath/btQuaternion.h"
-#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
-
-btConvexTriangleMeshShape ::btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb)
- : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
-{
- m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
- if (calcAabb)
- recalcLocalAabb();
-}
-
-///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
-///but then we are duplicating
-class LocalSupportVertexCallback : public btInternalTriangleIndexCallback
-{
- btVector3 m_supportVertexLocal;
-
-public:
- btScalar m_maxDot;
- btVector3 m_supportVecLocal;
-
- LocalSupportVertexCallback(const btVector3& supportVecLocal)
- : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)),
- m_maxDot(btScalar(-BT_LARGE_FLOAT)),
- m_supportVecLocal(supportVecLocal)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)triangleIndex;
- (void)partId;
-
- for (int i = 0; i < 3; i++)
- {
- btScalar dot = m_supportVecLocal.dot(triangle[i]);
- if (dot > m_maxDot)
- {
- m_maxDot = dot;
- m_supportVertexLocal = triangle[i];
- }
- }
- }
-
- btVector3 GetSupportVertexLocal()
- {
- return m_supportVertexLocal;
- }
-};
-
-btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
-{
- btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < btScalar(0.0001))
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
-
- LocalSupportVertexCallback supportCallback(vec);
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
- supVec = supportCallback.GetSupportVertexLocal();
-
- return supVec;
-}
-
-void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- //use 'w' component of supportVerticesOut?
- {
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
- }
- }
-
- ///@todo: could do the batch inside the callback!
-
- for (int j = 0; j < numVectors; j++)
- {
- const btVector3& vec = vectors[j];
- LocalSupportVertexCallback supportCallback(vec);
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
- supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
- }
-}
-
-btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
-}
-
-//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
-//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
-int btConvexTriangleMeshShape::getNumVertices() const
-{
- //cache this?
- return 0;
-}
-
-int btConvexTriangleMeshShape::getNumEdges() const
-{
- return 0;
-}
-
-void btConvexTriangleMeshShape::getEdge(int, btVector3&, btVector3&) const
-{
- btAssert(0);
-}
-
-void btConvexTriangleMeshShape::getVertex(int, btVector3&) const
-{
- btAssert(0);
-}
-
-int btConvexTriangleMeshShape::getNumPlanes() const
-{
- return 0;
-}
-
-void btConvexTriangleMeshShape::getPlane(btVector3&, btVector3&, int) const
-{
- btAssert(0);
-}
-
-//not yet
-bool btConvexTriangleMeshShape::isInside(const btVector3&, btScalar) const
-{
- btAssert(0);
- return false;
-}
-
-void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
-{
- m_stridingMesh->setScaling(scaling);
-
- recalcLocalAabb();
-}
-
-const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
-{
- return m_stridingMesh->getScaling();
-}
-
-void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
-{
- class CenterCallback : public btInternalTriangleIndexCallback
- {
- bool first;
- btVector3 ref;
- btVector3 sum;
- btScalar volume;
-
- public:
- CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)triangleIndex;
- (void)partId;
- if (first)
- {
- ref = triangle[0];
- first = false;
- }
- else
- {
- btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
- sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
- volume += vol;
- }
- }
-
- btVector3 getCenter()
- {
- return (volume > 0) ? sum / volume : ref;
- }
-
- btScalar getVolume()
- {
- return volume * btScalar(1. / 6);
- }
- };
-
- class InertiaCallback : public btInternalTriangleIndexCallback
- {
- btMatrix3x3 sum;
- btVector3 center;
-
- public:
- InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)triangleIndex;
- (void)partId;
- btMatrix3x3 i;
- btVector3 a = triangle[0] - center;
- btVector3 b = triangle[1] - center;
- btVector3 c = triangle[2] - center;
- btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
- for (int j = 0; j < 3; j++)
- {
- for (int k = 0; k <= j; k++)
- {
- i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
- }
- }
- btScalar i00 = -i[0][0];
- btScalar i11 = -i[1][1];
- btScalar i22 = -i[2][2];
- i[0][0] = i11 + i22;
- i[1][1] = i22 + i00;
- i[2][2] = i00 + i11;
- sum[0] += i[0];
- sum[1] += i[1];
- sum[2] += i[2];
- }
-
- btMatrix3x3& getInertia()
- {
- return sum;
- }
- };
-
- CenterCallback centerCallback;
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
- btVector3 center = centerCallback.getCenter();
- principal.setOrigin(center);
- volume = centerCallback.getVolume();
-
- InertiaCallback inertiaCallback(center);
- m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
-
- btMatrix3x3& i = inertiaCallback.getInertia();
- i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
- inertia.setValue(i[0][0], i[1][1], i[2][2]);
- inertia /= volume;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
deleted file mode 100644
index 6dac9fff04..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#ifndef BT_CONVEX_TRIANGLEMESH_SHAPE_H
-#define BT_CONVEX_TRIANGLEMESH_SHAPE_H
-
-#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
-/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
-ATTRIBUTE_ALIGNED16(class)
-btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
-{
- class btStridingMeshInterface* m_stridingMesh;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConvexTriangleMeshShape(btStridingMeshInterface * meshInterface, bool calcAabb = true);
-
- class btStridingMeshInterface* getMeshInterface()
- {
- return m_stridingMesh;
- }
- const class btStridingMeshInterface* getMeshInterface() const
- {
- return m_stridingMesh;
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- //debugging
- virtual const char* getName() const { return "ConvexTrimesh"; }
-
- virtual int getNumVertices() const;
- virtual int getNumEdges() const;
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
- virtual void getVertex(int i, btVector3& vtx) const;
- virtual int getNumPlanes() const;
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
-
- ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
- ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
- ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
- ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
- ///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
- void calculatePrincipalAxisTransform(btTransform & principal, btVector3 & inertia, btScalar & volume) const;
-};
-
-#endif //BT_CONVEX_TRIANGLEMESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
deleted file mode 100644
index 66dbb8e53d..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btCylinderShape.h"
-
-btCylinderShape::btCylinderShape(const btVector3& halfExtents)
- : btConvexInternalShape(),
- m_upAxis(1)
-{
- btVector3 margin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
-
- setSafeMargin(halfExtents);
-
- m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
-}
-
-btCylinderShapeX::btCylinderShapeX(const btVector3& halfExtents)
- : btCylinderShape(halfExtents)
-{
- m_upAxis = 0;
-}
-
-btCylinderShapeZ::btCylinderShapeZ(const btVector3& halfExtents)
- : btCylinderShape(halfExtents)
-{
- m_upAxis = 2;
-}
-
-void btCylinderShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btTransformAabb(getHalfExtentsWithoutMargin(), getMargin(), t, aabbMin, aabbMax);
-}
-
-void btCylinderShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
-//Until Bullet 2.77 a box approximation was used, so uncomment this if you need backwards compatibility
-//#define USE_BOX_INERTIA_APPROXIMATION 1
-#ifndef USE_BOX_INERTIA_APPROXIMATION
-
- /*
- cylinder is defined as following:
- *
- * - principle axis aligned along y by default, radius in x, z-value not used
- * - for btCylinderShapeX: principle axis aligned along x, radius in y direction, z-value not used
- * - for btCylinderShapeZ: principle axis aligned along z, radius in x direction, y-value not used
- *
- */
-
- btScalar radius2; // square of cylinder radius
- btScalar height2; // square of cylinder height
- btVector3 halfExtents = getHalfExtentsWithMargin(); // get cylinder dimension
- btScalar div12 = mass / 12.f;
- btScalar div4 = mass / 4.f;
- btScalar div2 = mass / 2.f;
- int idxRadius, idxHeight;
-
- switch (m_upAxis) // get indices of radius and height of cylinder
- {
- case 0: // cylinder is aligned along x
- idxRadius = 1;
- idxHeight = 0;
- break;
- case 2: // cylinder is aligned along z
- idxRadius = 0;
- idxHeight = 2;
- break;
- default: // cylinder is aligned along y
- idxRadius = 0;
- idxHeight = 1;
- }
-
- // calculate squares
- radius2 = halfExtents[idxRadius] * halfExtents[idxRadius];
- height2 = btScalar(4.) * halfExtents[idxHeight] * halfExtents[idxHeight];
-
- // calculate tensor terms
- btScalar t1 = div12 * height2 + div4 * radius2;
- btScalar t2 = div2 * radius2;
-
- switch (m_upAxis) // set diagonal elements of inertia tensor
- {
- case 0: // cylinder is aligned along x
- inertia.setValue(t2, t1, t1);
- break;
- case 2: // cylinder is aligned along z
- inertia.setValue(t1, t1, t2);
- break;
- default: // cylinder is aligned along y
- inertia.setValue(t1, t2, t1);
- }
-#else //USE_BOX_INERTIA_APPROXIMATION
- //approximation of box shape
- btVector3 halfExtents = getHalfExtentsWithMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x());
- btScalar ly = btScalar(2.) * (halfExtents.y());
- btScalar lz = btScalar(2.) * (halfExtents.z());
-
- inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + ly * ly));
-#endif //USE_BOX_INERTIA_APPROXIMATION
-}
-
-SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents, const btVector3& v)
-{
- const int cylinderUpAxis = 0;
- const int XX = 1;
- const int YY = 0;
- const int ZZ = 2;
-
- //mapping depends on how cylinder local orientation is
- // extents of the cylinder is: X,Y is for radius, and Z for height
-
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
-
- btVector3 tmp;
- btScalar d;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return tmp;
- }
- else
- {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return tmp;
- }
-}
-
-inline btVector3 CylinderLocalSupportY(const btVector3& halfExtents, const btVector3& v)
-{
- const int cylinderUpAxis = 1;
- const int XX = 0;
- const int YY = 1;
- const int ZZ = 2;
-
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
-
- btVector3 tmp;
- btScalar d;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return tmp;
- }
- else
- {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return tmp;
- }
-}
-
-inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents, const btVector3& v)
-{
- const int cylinderUpAxis = 2;
- const int XX = 0;
- const int YY = 2;
- const int ZZ = 1;
-
- //mapping depends on how cylinder local orientation is
- // extents of the cylinder is: X,Y is for radius, and Z for height
-
- btScalar radius = halfExtents[XX];
- btScalar halfHeight = halfExtents[cylinderUpAxis];
-
- btVector3 tmp;
- btScalar d;
-
- btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
- if (s != btScalar(0.0))
- {
- d = radius / s;
- tmp[XX] = v[XX] * d;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = v[ZZ] * d;
- return tmp;
- }
- else
- {
- tmp[XX] = radius;
- tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
- tmp[ZZ] = btScalar(0.0);
- return tmp;
- }
-}
-
-btVector3 btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- return CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vec);
-}
-
-btVector3 btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vec);
-}
-btVector3 btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- return CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vec);
-}
-
-void btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(), vectors[i]);
- }
-}
-
-void btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(), vectors[i]);
- }
-}
-
-void btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(), vectors[i]);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
deleted file mode 100644
index d3f64508ba..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CYLINDER_MINKOWSKI_H
-#define BT_CYLINDER_MINKOWSKI_H
-
-#include "btBoxShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "LinearMath/btVector3.h"
-
-/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
-ATTRIBUTE_ALIGNED16(class)
-btCylinderShape : public btConvexInternalShape
-
-{
-protected:
- int m_upAxis;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 getHalfExtentsWithMargin() const
- {
- btVector3 halfExtents = getHalfExtentsWithoutMargin();
- btVector3 margin(getMargin(), getMargin(), getMargin());
- halfExtents += margin;
- return halfExtents;
- }
-
- const btVector3& getHalfExtentsWithoutMargin() const
- {
- return m_implicitShapeDimensions; //changed in Bullet 2.63: assume the scaling and margin are included
- }
-
- btCylinderShape(const btVector3& halfExtents);
-
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void setMargin(btScalar collisionMargin)
- {
- //correct the m_implicitShapeDimensions for the margin
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
-
- btConvexInternalShape::setMargin(collisionMargin);
- btVector3 newMargin(getMargin(), getMargin(), getMargin());
- m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
- {
- btVector3 supVertex;
- supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- if (getMargin() != btScalar(0.))
- {
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- }
- return supVertex;
- }
-
- //use box inertia
- // virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const;
-
- int getUpAxis() const
- {
- return m_upAxis;
- }
-
- virtual btVector3 getAnisotropicRollingFrictionDirection() const
- {
- btVector3 aniDir(0, 0, 0);
- aniDir[getUpAxis()] = 1;
- return aniDir;
- }
-
- virtual btScalar getRadius() const
- {
- return getHalfExtentsWithMargin().getX();
- }
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- btVector3 oldMargin(getMargin(), getMargin(), getMargin());
- btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions + oldMargin;
- btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
-
- btConvexInternalShape::setLocalScaling(scaling);
-
- m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
- }
-
- //debugging
- virtual const char* getName() const
- {
- return "CylinderY";
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-class btCylinderShapeX : public btCylinderShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCylinderShapeX(const btVector3& halfExtents);
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- //debugging
- virtual const char* getName() const
- {
- return "CylinderX";
- }
-
- virtual btScalar getRadius() const
- {
- return getHalfExtentsWithMargin().getY();
- }
-};
-
-class btCylinderShapeZ : public btCylinderShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btCylinderShapeZ(const btVector3& halfExtents);
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- //debugging
- virtual const char* getName() const
- {
- return "CylinderZ";
- }
-
- virtual btScalar getRadius() const
- {
- return getHalfExtentsWithMargin().getX();
- }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btCylinderShapeData
-{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- int m_upAxis;
-
- char m_padding[4];
-};
-
-SIMD_FORCE_INLINE int btCylinderShape::calculateSerializeBufferSize() const
-{
- return sizeof(btCylinderShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btCylinderShapeData* shapeData = (btCylinderShapeData*)dataBuffer;
-
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
-
- shapeData->m_upAxis = m_upAxis;
-
- // Fill padding with zeros to appease msan.
- shapeData->m_padding[0] = 0;
- shapeData->m_padding[1] = 0;
- shapeData->m_padding[2] = 0;
- shapeData->m_padding[3] = 0;
-
- return "btCylinderShapeData";
-}
-
-#endif //BT_CYLINDER_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
deleted file mode 100644
index 4699555bd8..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btEmptyShape.h"
-
-#include "btCollisionShape.h"
-
-btEmptyShape::btEmptyShape() : btConcaveShape()
-{
- m_shapeType = EMPTY_SHAPE_PROXYTYPE;
-}
-
-btEmptyShape::~btEmptyShape()
-{
-}
-
-///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btEmptyShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btVector3 margin(getMargin(), getMargin(), getMargin());
-
- aabbMin = t.getOrigin() - margin;
-
- aabbMax = t.getOrigin() + margin;
-}
-
-void btEmptyShape::calculateLocalInertia(btScalar, btVector3&) const
-{
- btAssert(0);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
deleted file mode 100644
index d2e21173b2..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_EMPTY_SHAPE_H
-#define BT_EMPTY_SHAPE_H
-
-#include "btConcaveShape.h"
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "btCollisionMargin.h"
-
-/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
-/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
-ATTRIBUTE_ALIGNED16(class)
-btEmptyShape : public btConcaveShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btEmptyShape();
-
- virtual ~btEmptyShape();
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- m_localScaling = scaling;
- }
- virtual const btVector3& getLocalScaling() const
- {
- return m_localScaling;
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual const char* getName() const
- {
- return "Empty";
- }
-
- virtual void processAllTriangles(btTriangleCallback*, const btVector3&, const btVector3&) const
- {
- }
-
-protected:
- btVector3 m_localScaling;
-};
-
-#endif //BT_EMPTY_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
deleted file mode 100644
index 01bf7f67f5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btHeightfieldTerrainShape.h"
-
-#include "LinearMath/btTransformUtil.h"
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength,
- const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
- int upAxis, bool flipQuadEdges)
- : m_userValue3(0), m_triangleInfoMap(0)
-{
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_FLOAT,
- flipQuadEdges);
-}
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength, const double* heightfieldData,
- btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
- : m_userValue3(0), m_triangleInfoMap(0)
-{
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- /*heightScale=*/1, minHeight, maxHeight, upAxis, PHY_DOUBLE,
- flipQuadEdges);
-}
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength, const short* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
- : m_userValue3(0), m_triangleInfoMap(0)
-{
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, PHY_SHORT,
- flipQuadEdges);
-}
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength, const unsigned char* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight, int upAxis, bool flipQuadEdges)
- : m_userValue3(0), m_triangleInfoMap(0)
-{
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, PHY_UCHAR,
- flipQuadEdges);
-}
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength, const void* heightfieldData,
- btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
- PHY_ScalarType hdt, bool flipQuadEdges)
- :m_userValue3(0),
- m_triangleInfoMap(0)
-{
- // legacy constructor: Assumes PHY_FLOAT means btScalar.
-#ifdef BT_USE_DOUBLE_PRECISION
- if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
-#endif
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, hdt,
- flipQuadEdges);
-}
-
-btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges)
- : m_userValue3(0),
- m_triangleInfoMap(0)
-{
- // legacy constructor: support only btScalar or unsigned char data,
- // and min height is zero.
- PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
-#ifdef BT_USE_DOUBLE_PRECISION
- if (hdt == PHY_FLOAT) hdt = PHY_DOUBLE;
-#endif
- btScalar minHeight = 0.0f;
-
- // previously, height = uchar * maxHeight / 65535.
- // So to preserve legacy behavior, heightScale = maxHeight / 65535
- btScalar heightScale = maxHeight / 65535;
-
- initialize(heightStickWidth, heightStickLength, heightfieldData,
- heightScale, minHeight, maxHeight, upAxis, hdt,
- flipQuadEdges);
-}
-
-void btHeightfieldTerrainShape::initialize(
- int heightStickWidth, int heightStickLength, const void* heightfieldData,
- btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
- PHY_ScalarType hdt, bool flipQuadEdges)
-{
- // validation
- btAssert(heightStickWidth > 1); // && "bad width");
- btAssert(heightStickLength > 1); // && "bad length");
- btAssert(heightfieldData); // && "null heightfield data");
- // btAssert(heightScale) -- do we care? Trust caller here
- btAssert(minHeight <= maxHeight); // && "bad min/max height");
- btAssert(upAxis >= 0 && upAxis < 3); // && "bad upAxis--should be in range [0,2]");
- btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_DOUBLE || hdt != PHY_SHORT); // && "Bad height data type enum");
-
- // initialize member variables
- m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
- m_heightStickWidth = heightStickWidth;
- m_heightStickLength = heightStickLength;
- m_minHeight = minHeight;
- m_maxHeight = maxHeight;
- m_width = (btScalar)(heightStickWidth - 1);
- m_length = (btScalar)(heightStickLength - 1);
- m_heightScale = heightScale;
- m_heightfieldDataUnknown = heightfieldData;
- m_heightDataType = hdt;
- m_flipQuadEdges = flipQuadEdges;
- m_useDiamondSubdivision = false;
- m_useZigzagSubdivision = false;
- m_flipTriangleWinding = false;
- m_upAxis = upAxis;
- m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
-
- m_vboundsChunkSize = 0;
- m_vboundsGridWidth = 0;
- m_vboundsGridLength = 0;
-
- // determine min/max axis-aligned bounding box (aabb) values
- switch (m_upAxis)
- {
- case 0:
- {
- m_localAabbMin.setValue(m_minHeight, 0, 0);
- m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
- break;
- }
- case 1:
- {
- m_localAabbMin.setValue(0, m_minHeight, 0);
- m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
- break;
- };
- case 2:
- {
- m_localAabbMin.setValue(0, 0, m_minHeight);
- m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
- break;
- }
- default:
- {
- //need to get valid m_upAxis
- btAssert(0); // && "Bad m_upAxis");
- }
- }
-
- // remember origin (defined as exact middle of aabb)
- m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
-}
-
-btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
-{
- clearAccelerator();
-}
-
-void btHeightfieldTerrainShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btVector3 halfExtents = (m_localAabbMax - m_localAabbMin) * m_localScaling * btScalar(0.5);
-
- btVector3 localOrigin(0, 0, 0);
- localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
- localOrigin *= m_localScaling;
-
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- extent += btVector3(getMargin(), getMargin(), getMargin());
-
- aabbMin = center - extent;
- aabbMax = center + extent;
-}
-
-/// This returns the "raw" (user's initial) height, not the actual height.
-/// The actual height needs to be adjusted to be relative to the center
-/// of the heightfield's AABB.
-btScalar
-btHeightfieldTerrainShape::getRawHeightFieldValue(int x, int y) const
-{
- btScalar val = 0.f;
- switch (m_heightDataType)
- {
- case PHY_FLOAT:
- {
- val = m_heightfieldDataFloat[(y * m_heightStickWidth) + x];
- break;
- }
-
- case PHY_DOUBLE:
- {
- val = m_heightfieldDataDouble[(y * m_heightStickWidth) + x];
- break;
- }
-
- case PHY_UCHAR:
- {
- unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y * m_heightStickWidth) + x];
- val = heightFieldValue * m_heightScale;
- break;
- }
-
- case PHY_SHORT:
- {
- short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
- val = hfValue * m_heightScale;
- break;
- }
-
- default:
- {
- btAssert(!"Bad m_heightDataType");
- }
- }
-
- return val;
-}
-
-/// this returns the vertex in bullet-local coordinates
-void btHeightfieldTerrainShape::getVertex(int x, int y, btVector3& vertex) const
-{
- btAssert(x >= 0);
- btAssert(y >= 0);
- btAssert(x < m_heightStickWidth);
- btAssert(y < m_heightStickLength);
-
- btScalar height = getRawHeightFieldValue(x, y);
-
- switch (m_upAxis)
- {
- case 0:
- {
- vertex.setValue(
- height - m_localOrigin.getX(),
- (-m_width / btScalar(2.0)) + x,
- (-m_length / btScalar(2.0)) + y);
- break;
- }
- case 1:
- {
- vertex.setValue(
- (-m_width / btScalar(2.0)) + x,
- height - m_localOrigin.getY(),
- (-m_length / btScalar(2.0)) + y);
- break;
- };
- case 2:
- {
- vertex.setValue(
- (-m_width / btScalar(2.0)) + x,
- (-m_length / btScalar(2.0)) + y,
- height - m_localOrigin.getZ());
- break;
- }
- default:
- {
- //need to get valid m_upAxis
- btAssert(0);
- }
- }
-
- vertex *= m_localScaling;
-}
-
-static inline int
-getQuantized(
- btScalar x)
-{
- if (x < 0.0)
- {
- return (int)(x - 0.5);
- }
- return (int)(x + 0.5);
-}
-
-// Equivalent to std::minmax({a, b, c}).
-// Performs at most 3 comparisons.
-static btHeightfieldTerrainShape::Range minmaxRange(btScalar a, btScalar b, btScalar c)
-{
- if (a > b)
- {
- if (b > c)
- return btHeightfieldTerrainShape::Range(c, a);
- else if (a > c)
- return btHeightfieldTerrainShape::Range(b, a);
- else
- return btHeightfieldTerrainShape::Range(b, c);
- }
- else
- {
- if (a > c)
- return btHeightfieldTerrainShape::Range(c, b);
- else if (b > c)
- return btHeightfieldTerrainShape::Range(a, b);
- else
- return btHeightfieldTerrainShape::Range(a, c);
- }
-}
-
-/// given input vector, return quantized version
-/**
- This routine is basically determining the gridpoint indices for a given
- input vector, answering the question: "which gridpoint is closest to the
- provided point?".
-
- "with clamp" means that we restrict the point to be in the heightfield's
- axis-aligned bounding box.
- */
-void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point, int /*isMax*/) const
-{
- btVector3 clampedPoint(point);
- clampedPoint.setMax(m_localAabbMin);
- clampedPoint.setMin(m_localAabbMax);
-
- out[0] = getQuantized(clampedPoint.getX());
- out[1] = getQuantized(clampedPoint.getY());
- out[2] = getQuantized(clampedPoint.getZ());
-}
-
-/// process all triangles within the provided axis-aligned bounding box
-/**
- basic algorithm:
- - convert input aabb to local coordinates (scale down and shift for local origin)
- - convert input aabb to a range of heightfield grid points (quantize)
- - iterate over all triangles in that subset of the grid
- */
-void btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- // scale down the input aabb's so they are in local (non-scaled) coordinates
- btVector3 localAabbMin = aabbMin * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
- btVector3 localAabbMax = aabbMax * btVector3(1.f / m_localScaling[0], 1.f / m_localScaling[1], 1.f / m_localScaling[2]);
-
- // account for local origin
- localAabbMin += m_localOrigin;
- localAabbMax += m_localOrigin;
-
- //quantize the aabbMin and aabbMax, and adjust the start/end ranges
- int quantizedAabbMin[3];
- int quantizedAabbMax[3];
- quantizeWithClamp(quantizedAabbMin, localAabbMin, 0);
- quantizeWithClamp(quantizedAabbMax, localAabbMax, 1);
-
- // expand the min/max quantized values
- // this is to catch the case where the input aabb falls between grid points!
- for (int i = 0; i < 3; ++i)
- {
- quantizedAabbMin[i]--;
- quantizedAabbMax[i]++;
- }
-
- int startX = 0;
- int endX = m_heightStickWidth - 1;
- int startJ = 0;
- int endJ = m_heightStickLength - 1;
-
- switch (m_upAxis)
- {
- case 0:
- {
- if (quantizedAabbMin[1] > startX)
- startX = quantizedAabbMin[1];
- if (quantizedAabbMax[1] < endX)
- endX = quantizedAabbMax[1];
- if (quantizedAabbMin[2] > startJ)
- startJ = quantizedAabbMin[2];
- if (quantizedAabbMax[2] < endJ)
- endJ = quantizedAabbMax[2];
- break;
- }
- case 1:
- {
- if (quantizedAabbMin[0] > startX)
- startX = quantizedAabbMin[0];
- if (quantizedAabbMax[0] < endX)
- endX = quantizedAabbMax[0];
- if (quantizedAabbMin[2] > startJ)
- startJ = quantizedAabbMin[2];
- if (quantizedAabbMax[2] < endJ)
- endJ = quantizedAabbMax[2];
- break;
- };
- case 2:
- {
- if (quantizedAabbMin[0] > startX)
- startX = quantizedAabbMin[0];
- if (quantizedAabbMax[0] < endX)
- endX = quantizedAabbMax[0];
- if (quantizedAabbMin[1] > startJ)
- startJ = quantizedAabbMin[1];
- if (quantizedAabbMax[1] < endJ)
- endJ = quantizedAabbMax[1];
- break;
- }
- default:
- {
- //need to get valid m_upAxis
- btAssert(0);
- }
- }
-
- // TODO If m_vboundsGrid is available, use it to determine if we really need to process this area
-
- const Range aabbUpRange(aabbMin[m_upAxis], aabbMax[m_upAxis]);
- for (int j = startJ; j < endJ; j++)
- {
- for (int x = startX; x < endX; x++)
- {
- btVector3 vertices[3];
- int indices[3] = { 0, 1, 2 };
- if (m_flipTriangleWinding)
- {
- indices[0] = 2;
- indices[2] = 0;
- }
-
- if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j + x) & 1)) || (m_useZigzagSubdivision && !(j & 1)))
- {
- getVertex(x, j, vertices[indices[0]]);
- getVertex(x, j + 1, vertices[indices[1]]);
- getVertex(x + 1, j + 1, vertices[indices[2]]);
-
- // Skip triangle processing if the triangle is out-of-AABB.
- Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
-
- if (upRange.overlaps(aabbUpRange))
- callback->processTriangle(vertices, 2 * x, j);
-
- // already set: getVertex(x, j, vertices[indices[0]])
-
- // equivalent to: getVertex(x + 1, j + 1, vertices[indices[1]]);
- vertices[indices[1]] = vertices[indices[2]];
-
- getVertex(x + 1, j, vertices[indices[2]]);
- upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
- upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
-
- if (upRange.overlaps(aabbUpRange))
- callback->processTriangle(vertices, 2 * x + 1, j);
- }
- else
- {
- getVertex(x, j, vertices[indices[0]]);
- getVertex(x, j + 1, vertices[indices[1]]);
- getVertex(x + 1, j, vertices[indices[2]]);
-
- // Skip triangle processing if the triangle is out-of-AABB.
- Range upRange = minmaxRange(vertices[0][m_upAxis], vertices[1][m_upAxis], vertices[2][m_upAxis]);
-
- if (upRange.overlaps(aabbUpRange))
- callback->processTriangle(vertices, 2 * x, j);
-
- // already set: getVertex(x, j + 1, vertices[indices[1]]);
-
- // equivalent to: getVertex(x + 1, j, vertices[indices[0]]);
- vertices[indices[0]] = vertices[indices[2]];
-
- getVertex(x + 1, j + 1, vertices[indices[2]]);
- upRange.min = btMin(upRange.min, vertices[indices[2]][m_upAxis]);
- upRange.max = btMax(upRange.max, vertices[indices[2]][m_upAxis]);
-
- if (upRange.overlaps(aabbUpRange))
- callback->processTriangle(vertices, 2 * x + 1, j);
- }
- }
- }
-}
-
-void btHeightfieldTerrainShape::calculateLocalInertia(btScalar, btVector3& inertia) const
-{
- //moving concave objects not supported
-
- inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-}
-
-void btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling;
-}
-const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
-{
- return m_localScaling;
-}
-
-namespace
-{
- struct GridRaycastState
- {
- int x; // Next quad coords
- int z;
- int prev_x; // Previous quad coords
- int prev_z;
- btScalar param; // Exit param for previous quad
- btScalar prevParam; // Enter param for previous quad
- btScalar maxDistanceFlat;
- btScalar maxDistance3d;
- };
-}
-
-// TODO Does it really need to take 3D vectors?
-/// Iterates through a virtual 2D grid of unit-sized square cells,
-/// and executes an action on each cell intersecting the given segment, ordered from begin to end.
-/// Initially inspired by http://www.cse.yorku.ca/~amana/research/grid.pdf
-template <typename Action_T>
-void gridRaycast(Action_T& quadAction, const btVector3& beginPos, const btVector3& endPos, int indices[3])
-{
- GridRaycastState rs;
- rs.maxDistance3d = beginPos.distance(endPos);
- if (rs.maxDistance3d < 0.0001)
- {
- // Consider the ray is too small to hit anything
- return;
- }
-
-
- btScalar rayDirectionFlatX = endPos[indices[0]] - beginPos[indices[0]];
- btScalar rayDirectionFlatZ = endPos[indices[2]] - beginPos[indices[2]];
- rs.maxDistanceFlat = btSqrt(rayDirectionFlatX * rayDirectionFlatX + rayDirectionFlatZ * rayDirectionFlatZ);
-
- if (rs.maxDistanceFlat < 0.0001)
- {
- // Consider the ray vertical
- rayDirectionFlatX = 0;
- rayDirectionFlatZ = 0;
- }
- else
- {
- rayDirectionFlatX /= rs.maxDistanceFlat;
- rayDirectionFlatZ /= rs.maxDistanceFlat;
- }
-
- const int xiStep = rayDirectionFlatX > 0 ? 1 : rayDirectionFlatX < 0 ? -1 : 0;
- const int ziStep = rayDirectionFlatZ > 0 ? 1 : rayDirectionFlatZ < 0 ? -1 : 0;
-
- const float infinite = 9999999;
- const btScalar paramDeltaX = xiStep != 0 ? 1.f / btFabs(rayDirectionFlatX) : infinite;
- const btScalar paramDeltaZ = ziStep != 0 ? 1.f / btFabs(rayDirectionFlatZ) : infinite;
-
- // pos = param * dir
- btScalar paramCrossX; // At which value of `param` we will cross a x-axis lane?
- btScalar paramCrossZ; // At which value of `param` we will cross a z-axis lane?
-
- // paramCrossX and paramCrossZ are initialized as being the first cross
- // X initialization
- if (xiStep != 0)
- {
- if (xiStep == 1)
- {
- paramCrossX = (ceil(beginPos[indices[0]]) - beginPos[indices[0]]) * paramDeltaX;
- }
- else
- {
- paramCrossX = (beginPos[indices[0]] - floor(beginPos[indices[0]])) * paramDeltaX;
- }
- }
- else
- {
- paramCrossX = infinite; // Will never cross on X
- }
-
- // Z initialization
- if (ziStep != 0)
- {
- if (ziStep == 1)
- {
- paramCrossZ = (ceil(beginPos[indices[2]]) - beginPos[indices[2]]) * paramDeltaZ;
- }
- else
- {
- paramCrossZ = (beginPos[indices[2]] - floor(beginPos[indices[2]])) * paramDeltaZ;
- }
- }
- else
- {
- paramCrossZ = infinite; // Will never cross on Z
- }
-
- rs.x = static_cast<int>(floor(beginPos[indices[0]]));
- rs.z = static_cast<int>(floor(beginPos[indices[2]]));
-
- // Workaround cases where the ray starts at an integer position
- if (paramCrossX == 0.0)
- {
- paramCrossX += paramDeltaX;
- // If going backwards, we should ignore the position we would get by the above flooring,
- // because the ray is not heading in that direction
- if (xiStep == -1)
- {
- rs.x -= 1;
- }
- }
-
- if (paramCrossZ == 0.0)
- {
- paramCrossZ += paramDeltaZ;
- if (ziStep == -1)
- rs.z -= 1;
- }
-
- rs.prev_x = rs.x;
- rs.prev_z = rs.z;
- rs.param = 0;
-
- while (true)
- {
- rs.prev_x = rs.x;
- rs.prev_z = rs.z;
- rs.prevParam = rs.param;
-
- if (paramCrossX < paramCrossZ)
- {
- // X lane
- rs.x += xiStep;
- // Assign before advancing the param,
- // to be in sync with the initialization step
- rs.param = paramCrossX;
- paramCrossX += paramDeltaX;
- }
- else
- {
- // Z lane
- rs.z += ziStep;
- rs.param = paramCrossZ;
- paramCrossZ += paramDeltaZ;
- }
-
- if (rs.param > rs.maxDistanceFlat)
- {
- rs.param = rs.maxDistanceFlat;
- quadAction(rs);
- break;
- }
- else
- {
- quadAction(rs);
- }
- }
-}
-
-struct ProcessTrianglesAction
-{
- const btHeightfieldTerrainShape* shape;
- bool flipQuadEdges;
- bool useDiamondSubdivision;
- int width;
- int length;
- btTriangleCallback* callback;
-
- void exec(int x, int z) const
- {
- if (x < 0 || z < 0 || x >= width || z >= length)
- {
- return;
- }
-
- btVector3 vertices[3];
-
- // TODO Since this is for raycasts, we could greatly benefit from an early exit on the first hit
-
- // Check quad
- if (flipQuadEdges || (useDiamondSubdivision && (((z + x) & 1) > 0)))
- {
- // First triangle
- shape->getVertex(x, z, vertices[0]);
- shape->getVertex(x + 1, z, vertices[1]);
- shape->getVertex(x + 1, z + 1, vertices[2]);
- callback->processTriangle(vertices, x, z);
-
- // Second triangle
- shape->getVertex(x, z, vertices[0]);
- shape->getVertex(x + 1, z + 1, vertices[1]);
- shape->getVertex(x, z + 1, vertices[2]);
- callback->processTriangle(vertices, x, z);
- }
- else
- {
- // First triangle
- shape->getVertex(x, z, vertices[0]);
- shape->getVertex(x, z + 1, vertices[1]);
- shape->getVertex(x + 1, z, vertices[2]);
- callback->processTriangle(vertices, x, z);
-
- // Second triangle
- shape->getVertex(x + 1, z, vertices[0]);
- shape->getVertex(x, z + 1, vertices[1]);
- shape->getVertex(x + 1, z + 1, vertices[2]);
- callback->processTriangle(vertices, x, z);
- }
- }
-
- void operator()(const GridRaycastState& bs) const
- {
- exec(bs.prev_x, bs.prev_z);
- }
-};
-
-struct ProcessVBoundsAction
-{
- const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& vbounds;
- int width;
- int length;
- int chunkSize;
-
- btVector3 rayBegin;
- btVector3 rayEnd;
- btVector3 rayDir;
-
- int* m_indices;
- ProcessTrianglesAction processTriangles;
-
- ProcessVBoundsAction(const btAlignedObjectArray<btHeightfieldTerrainShape::Range>& bnd, int* indices)
- : vbounds(bnd),
- m_indices(indices)
- {
- }
- void operator()(const GridRaycastState& rs) const
- {
- int x = rs.prev_x;
- int z = rs.prev_z;
-
- if (x < 0 || z < 0 || x >= width || z >= length)
- {
- return;
- }
-
- const btHeightfieldTerrainShape::Range chunk = vbounds[x + z * width];
-
- btVector3 enterPos;
- btVector3 exitPos;
-
- if (rs.maxDistanceFlat > 0.0001)
- {
- btScalar flatTo3d = chunkSize * rs.maxDistance3d / rs.maxDistanceFlat;
- btScalar enterParam3d = rs.prevParam * flatTo3d;
- btScalar exitParam3d = rs.param * flatTo3d;
- enterPos = rayBegin + rayDir * enterParam3d;
- exitPos = rayBegin + rayDir * exitParam3d;
-
- // We did enter the flat projection of the AABB,
- // but we have to check if we intersect it on the vertical axis
- if (enterPos[1] > chunk.max && exitPos[m_indices[1]] > chunk.max)
- {
- return;
- }
- if (enterPos[1] < chunk.min && exitPos[m_indices[1]] < chunk.min)
- {
- return;
- }
- }
- else
- {
- // Consider the ray vertical
- // (though we shouldn't reach this often because there is an early check up-front)
- enterPos = rayBegin;
- exitPos = rayEnd;
- }
-
- gridRaycast(processTriangles, enterPos, exitPos, m_indices);
- // Note: it could be possible to have more than one grid at different levels,
- // to do this there would be a branch using a pointer to another ProcessVBoundsAction
- }
-};
-
-// TODO How do I interrupt the ray when there is a hit? `callback` does not return any result
-/// Performs a raycast using a hierarchical Bresenham algorithm.
-/// Does not allocate any memory by itself.
-void btHeightfieldTerrainShape::performRaycast(btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget) const
-{
- // Transform to cell-local
- btVector3 beginPos = raySource / m_localScaling;
- btVector3 endPos = rayTarget / m_localScaling;
- beginPos += m_localOrigin;
- endPos += m_localOrigin;
-
- ProcessTrianglesAction processTriangles;
- processTriangles.shape = this;
- processTriangles.flipQuadEdges = m_flipQuadEdges;
- processTriangles.useDiamondSubdivision = m_useDiamondSubdivision;
- processTriangles.callback = callback;
- processTriangles.width = m_heightStickWidth - 1;
- processTriangles.length = m_heightStickLength - 1;
-
- // TODO Transform vectors to account for m_upAxis
- int indices[3] = { 0, 1, 2 };
- if (m_upAxis == 2)
- {
- indices[1] = 2;
- indices[2] = 1;
- }
- int iBeginX = static_cast<int>(floor(beginPos[indices[0]]));
- int iBeginZ = static_cast<int>(floor(beginPos[indices[2]]));
- int iEndX = static_cast<int>(floor(endPos[indices[0]]));
- int iEndZ = static_cast<int>(floor(endPos[indices[2]]));
-
- if (iBeginX == iEndX && iBeginZ == iEndZ)
- {
- // The ray will never cross quads within the plane,
- // so directly process triangles within one quad
- // (typically, vertical rays should end up here)
- processTriangles.exec(iBeginX, iEndZ);
- return;
- }
-
-
-
- if (m_vboundsGrid.size()==0)
- {
- // Process all quads intersecting the flat projection of the ray
- gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
- }
- else
- {
- btVector3 rayDiff = endPos - beginPos;
- btScalar flatDistance2 = rayDiff[indices[0]] * rayDiff[indices[0]] + rayDiff[indices[2]] * rayDiff[indices[2]];
- if (flatDistance2 < m_vboundsChunkSize * m_vboundsChunkSize)
- {
- // Don't use chunks, the ray is too short in the plane
- gridRaycast(processTriangles, beginPos, endPos, &indices[0]);
- }
-
- ProcessVBoundsAction processVBounds(m_vboundsGrid, &indices[0]);
- processVBounds.width = m_vboundsGridWidth;
- processVBounds.length = m_vboundsGridLength;
- processVBounds.rayBegin = beginPos;
- processVBounds.rayEnd = endPos;
- processVBounds.rayDir = rayDiff.normalized();
- processVBounds.processTriangles = processTriangles;
- processVBounds.chunkSize = m_vboundsChunkSize;
- // The ray is long, run raycast on a higher-level grid
- gridRaycast(processVBounds, beginPos / m_vboundsChunkSize, endPos / m_vboundsChunkSize, indices);
- }
-}
-
-/// Builds a grid data structure storing the min and max heights of the terrain in chunks.
-/// if chunkSize is zero, that accelerator is removed.
-/// If you modify the heights, you need to rebuild this accelerator.
-void btHeightfieldTerrainShape::buildAccelerator(int chunkSize)
-{
- if (chunkSize <= 0)
- {
- clearAccelerator();
- return;
- }
-
- m_vboundsChunkSize = chunkSize;
- int nChunksX = m_heightStickWidth / chunkSize;
- int nChunksZ = m_heightStickLength / chunkSize;
-
- if (m_heightStickWidth % chunkSize > 0)
- {
- ++nChunksX; // In case terrain size isn't dividable by chunk size
- }
- if (m_heightStickLength % chunkSize > 0)
- {
- ++nChunksZ;
- }
-
- if (m_vboundsGridWidth != nChunksX || m_vboundsGridLength != nChunksZ)
- {
- clearAccelerator();
- m_vboundsGridWidth = nChunksX;
- m_vboundsGridLength = nChunksZ;
- }
-
- if (nChunksX == 0 || nChunksZ == 0)
- {
- return;
- }
-
- // This data structure is only reallocated if the required size changed
- m_vboundsGrid.resize(nChunksX * nChunksZ);
-
- // Compute min and max height for all chunks
- for (int cz = 0; cz < nChunksZ; ++cz)
- {
- int z0 = cz * chunkSize;
-
- for (int cx = 0; cx < nChunksX; ++cx)
- {
- int x0 = cx * chunkSize;
-
- Range r;
-
- r.min = getRawHeightFieldValue(x0, z0);
- r.max = r.min;
-
- // Compute min and max height for this chunk.
- // We have to include one extra cell to account for neighbors.
- // Here is why:
- // Say we have a flat terrain, and a plateau that fits a chunk perfectly.
- //
- // Left Right
- // 0---0---0---1---1---1
- // | | | | | |
- // 0---0---0---1---1---1
- // | | | | | |
- // 0---0---0---1---1---1
- // x
- //
- // If the AABB for the Left chunk did not share vertices with the Right,
- // then we would fail collision tests at x due to a gap.
- //
- for (int z = z0; z < z0 + chunkSize + 1; ++z)
- {
- if (z >= m_heightStickLength)
- {
- continue;
- }
-
- for (int x = x0; x < x0 + chunkSize + 1; ++x)
- {
- if (x >= m_heightStickWidth)
- {
- continue;
- }
-
- btScalar height = getRawHeightFieldValue(x, z);
-
- if (height < r.min)
- {
- r.min = height;
- }
- else if (height > r.max)
- {
- r.max = height;
- }
- }
- }
-
- m_vboundsGrid[cx + cz * nChunksX] = r;
- }
- }
-}
-
-void btHeightfieldTerrainShape::clearAccelerator()
-{
- m_vboundsGrid.clear();
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
deleted file mode 100644
index 7e251fa71e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_HEIGHTFIELD_TERRAIN_SHAPE_H
-#define BT_HEIGHTFIELD_TERRAIN_SHAPE_H
-
-#include "btConcaveShape.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-///btHeightfieldTerrainShape simulates a 2D heightfield terrain
-/**
- The caller is responsible for maintaining the heightfield array; this
- class does not make a copy.
-
- The heightfield can be dynamic so long as the min/max height values
- capture the extremes (heights must always be in that range).
-
- The local origin of the heightfield is assumed to be the exact
- center (as determined by width and length and height, with each
- axis multiplied by the localScaling).
-
- \b NOTE: be careful with coordinates. If you have a heightfield with a local
- min height of -100m, and a max height of +500m, you may be tempted to place it
- at the origin (0,0) and expect the heights in world coordinates to be
- -100 to +500 meters.
- Actually, the heights will be -300 to +300m, because bullet will re-center
- the heightfield based on its AABB (which is determined by the min/max
- heights). So keep in mind that once you create a btHeightfieldTerrainShape
- object, the heights will be adjusted relative to the center of the AABB. This
- is different to the behavior of many rendering engines, but is useful for
- physics engines.
-
- Most (but not all) rendering and heightfield libraries assume upAxis = 1
- (that is, the y-axis is "up"). This class allows any of the 3 coordinates
- to be "up". Make sure your choice of axis is consistent with your rendering
- system.
-
- The heightfield heights are determined from the data type used for the
- heightfieldData array.
-
- - unsigned char: height at a point is the uchar value at the
- grid point, multipled by heightScale. uchar isn't recommended
- because of its inability to deal with negative values, and
- low resolution (8-bit).
-
- - short: height at a point is the short int value at that grid
- point, multipled by heightScale.
-
- - float or dobule: height at a point is the value at that grid point.
-
- Whatever the caller specifies as minHeight and maxHeight will be honored.
- The class will not inspect the heightfield to discover the actual minimum
- or maximum heights. These values are used to determine the heightfield's
- axis-aligned bounding box, multiplied by localScaling.
-
- For usage and testing see the TerrainDemo.
- */
-ATTRIBUTE_ALIGNED16(class)
-btHeightfieldTerrainShape : public btConcaveShape
-{
-public:
- struct Range
- {
- Range() {}
- Range(btScalar min, btScalar max) : min(min), max(max) {}
-
- bool overlaps(const Range& other) const
- {
- return !(min > other.max || max < other.min);
- }
-
- btScalar min;
- btScalar max;
- };
-
-protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- btVector3 m_localOrigin;
-
- ///terrain data
- int m_heightStickWidth;
- int m_heightStickLength;
- btScalar m_minHeight;
- btScalar m_maxHeight;
- btScalar m_width;
- btScalar m_length;
- btScalar m_heightScale;
- union {
- const unsigned char* m_heightfieldDataUnsignedChar;
- const short* m_heightfieldDataShort;
- const float* m_heightfieldDataFloat;
- const double* m_heightfieldDataDouble;
- const void* m_heightfieldDataUnknown;
- };
-
- PHY_ScalarType m_heightDataType;
- bool m_flipQuadEdges;
- bool m_useDiamondSubdivision;
- bool m_useZigzagSubdivision;
- bool m_flipTriangleWinding;
- int m_upAxis;
-
- btVector3 m_localScaling;
-
- // Accelerator
- btAlignedObjectArray<Range> m_vboundsGrid;
- int m_vboundsGridWidth;
- int m_vboundsGridLength;
- int m_vboundsChunkSize;
-
-
- btScalar m_userValue3;
-
- struct btTriangleInfoMap* m_triangleInfoMap;
-
- virtual btScalar getRawHeightFieldValue(int x, int y) const;
- void quantizeWithClamp(int* out, const btVector3& point, int isMax) const;
-
- /// protected initialization
- /**
- Handles the work of constructors so that public constructors can be
- backwards-compatible without a lot of copy/paste.
- */
- void initialize(int heightStickWidth, int heightStickLength,
- const void* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight, int upAxis,
- PHY_ScalarType heightDataType, bool flipQuadEdges);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- /// preferred constructors
- btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength,
- const float* heightfieldData, btScalar minHeight, btScalar maxHeight,
- int upAxis, bool flipQuadEdges);
- btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength,
- const double* heightfieldData, btScalar minHeight, btScalar maxHeight,
- int upAxis, bool flipQuadEdges);
- btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength,
- const short* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
- int upAxis, bool flipQuadEdges);
- btHeightfieldTerrainShape(
- int heightStickWidth, int heightStickLength,
- const unsigned char* heightfieldData, btScalar heightScale, btScalar minHeight, btScalar maxHeight,
- int upAxis, bool flipQuadEdges);
-
- /// legacy constructor
- /**
- This constructor supports a range of heightfield
- data types, and allows for a non-zero minimum height value.
- heightScale is needed for any integer-based heightfield data types.
-
- This legacy constructor considers `PHY_FLOAT` to mean `btScalar`.
- With `BT_USE_DOUBLE_PRECISION`, it will expect `heightfieldData`
- to be double-precision.
- */
- btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,
- const void* heightfieldData, btScalar heightScale,
- btScalar minHeight, btScalar maxHeight,
- int upAxis, PHY_ScalarType heightDataType,
- bool flipQuadEdges);
-
- /// legacy constructor
- /**
- The legacy constructor assumes the heightfield has a minimum height
- of zero. Only unsigned char or btScalar data are supported. For legacy
- compatibility reasons, heightScale is calculated as maxHeight / 65535
- (and is only used when useFloatData = false).
- */
- btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength, const void* heightfieldData, btScalar maxHeight, int upAxis, bool useFloatData, bool flipQuadEdges);
-
- virtual ~btHeightfieldTerrainShape();
-
- void setUseDiamondSubdivision(bool useDiamondSubdivision = true) { m_useDiamondSubdivision = useDiamondSubdivision; }
-
- ///could help compatibility with Ogre heightfields. See https://code.google.com/p/bullet/issues/detail?id=625
- void setUseZigzagSubdivision(bool useZigzagSubdivision = true) { m_useZigzagSubdivision = useZigzagSubdivision; }
-
- void setFlipTriangleWinding(bool flipTriangleWinding)
- {
- m_flipTriangleWinding = flipTriangleWinding;
- }
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual const btVector3& getLocalScaling() const;
-
- void getVertex(int x, int y, btVector3& vertex) const;
-
- void performRaycast(btTriangleCallback * callback, const btVector3& raySource, const btVector3& rayTarget) const;
-
- void buildAccelerator(int chunkSize = 16);
- void clearAccelerator();
-
- int getUpAxis() const
- {
- return m_upAxis;
- }
- //debugging
- virtual const char* getName() const { return "HEIGHTFIELD"; }
-
-
- void setUserValue3(btScalar value)
- {
- m_userValue3 = value;
- }
- btScalar getUserValue3() const
- {
- return m_userValue3;
- }
- const struct btTriangleInfoMap* getTriangleInfoMap() const
- {
- return m_triangleInfoMap;
- }
- struct btTriangleInfoMap* getTriangleInfoMap()
- {
- return m_triangleInfoMap;
- }
- void setTriangleInfoMap(btTriangleInfoMap* map)
- {
- m_triangleInfoMap = map;
- }
- const unsigned char* getHeightfieldRawData() const
- {
- return m_heightfieldDataUnsignedChar;
- }
-};
-
-#endif //BT_HEIGHTFIELD_TERRAIN_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h
deleted file mode 100644
index c9a436bf26..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMaterial.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// This file was created by Alex Silverman
-
-#ifndef BT_MATERIAL_H
-#define BT_MATERIAL_H
-
-// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
-class btMaterial
-{
- // public members so that materials can change due to world events
-public:
- btScalar m_friction;
- btScalar m_restitution;
- int pad[2];
-
- btMaterial() {}
- btMaterial(btScalar fric, btScalar rest)
- {
- m_friction = fric;
- m_restitution = rest;
- }
-};
-
-#endif // BT_MATERIAL_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp
deleted file mode 100644
index 13c0a343f1..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-#include "btMiniSDF.h"
-
-//
-//Based on code from DiscreGrid, https://github.com/InteractiveComputerGraphics/Discregrid
-//example:
-//GenerateSDF.exe -r "32 32 32" -d "-1.6 -1.6 -.6 1.6 1.6 .6" concave_box.obj
-//The MIT License (MIT)
-//
-//Copyright (c) 2017 Dan Koschier
-//
-
-#include <limits.h>
-#include <string.h> //memcpy
-
-struct btSdfDataStream
-{
- const char* m_data;
- int m_size;
-
- int m_currentOffset;
-
- btSdfDataStream(const char* data, int size)
- : m_data(data),
- m_size(size),
- m_currentOffset(0)
- {
- }
-
- template <class T>
- bool read(T& val)
- {
- int bytes = sizeof(T);
- if (m_currentOffset + bytes <= m_size)
- {
- char* dest = (char*)&val;
- memcpy(dest, &m_data[m_currentOffset], bytes);
- m_currentOffset += bytes;
- return true;
- }
- btAssert(0);
- return false;
- }
-};
-
-bool btMiniSDF::load(const char* data, int size)
-{
- int fileSize = -1;
-
- btSdfDataStream ds(data, size);
- {
- double buf[6];
- ds.read(buf);
- m_domain.m_min[0] = buf[0];
- m_domain.m_min[1] = buf[1];
- m_domain.m_min[2] = buf[2];
- m_domain.m_min[3] = 0;
- m_domain.m_max[0] = buf[3];
- m_domain.m_max[1] = buf[4];
- m_domain.m_max[2] = buf[5];
- m_domain.m_max[3] = 0;
- }
- {
- unsigned int buf2[3];
- ds.read(buf2);
- m_resolution[0] = buf2[0];
- m_resolution[1] = buf2[1];
- m_resolution[2] = buf2[2];
- }
- {
- double buf[3];
- ds.read(buf);
- m_cell_size[0] = buf[0];
- m_cell_size[1] = buf[1];
- m_cell_size[2] = buf[2];
- }
- {
- double buf[3];
- ds.read(buf);
- m_inv_cell_size[0] = buf[0];
- m_inv_cell_size[1] = buf[1];
- m_inv_cell_size[2] = buf[2];
- }
- {
- unsigned long long int cells;
- ds.read(cells);
- m_n_cells = cells;
- }
- {
- unsigned long long int fields;
- ds.read(fields);
- m_n_fields = fields;
- }
-
- unsigned long long int nodes0;
- std::size_t n_nodes0;
- ds.read(nodes0);
- n_nodes0 = nodes0;
- if (n_nodes0 > 1024 * 1024 * 1024)
- {
- return m_isValid;
- }
- m_nodes.resize(n_nodes0);
- for (unsigned int i = 0; i < n_nodes0; i++)
- {
- unsigned long long int n_nodes1;
- ds.read(n_nodes1);
- btAlignedObjectArray<double>& nodes = m_nodes[i];
- nodes.resize(n_nodes1);
- for (int j = 0; j < nodes.size(); j++)
- {
- double& node = nodes[j];
- ds.read(node);
- }
- }
-
- unsigned long long int n_cells0;
- ds.read(n_cells0);
- m_cells.resize(n_cells0);
- for (int i = 0; i < n_cells0; i++)
- {
- unsigned long long int n_cells1;
- btAlignedObjectArray<btCell32>& cells = m_cells[i];
- ds.read(n_cells1);
- cells.resize(n_cells1);
- for (int j = 0; j < n_cells1; j++)
- {
- btCell32& cell = cells[j];
- ds.read(cell);
- }
- }
-
- {
- unsigned long long int n_cell_maps0;
- ds.read(n_cell_maps0);
-
- m_cell_map.resize(n_cell_maps0);
- for (int i = 0; i < n_cell_maps0; i++)
- {
- unsigned long long int n_cell_maps1;
- btAlignedObjectArray<unsigned int>& cell_maps = m_cell_map[i];
- ds.read(n_cell_maps1);
- cell_maps.resize(n_cell_maps1);
- for (int j = 0; j < n_cell_maps1; j++)
- {
- unsigned int& cell_map = cell_maps[j];
- ds.read(cell_map);
- }
- }
- }
-
- m_isValid = (ds.m_currentOffset == ds.m_size);
- return m_isValid;
-}
-
-unsigned int btMiniSDF::multiToSingleIndex(btMultiIndex const& ijk) const
-{
- return m_resolution[1] * m_resolution[0] * ijk.ijk[2] + m_resolution[0] * ijk.ijk[1] + ijk.ijk[0];
-}
-
-btAlignedBox3d
-btMiniSDF::subdomain(btMultiIndex const& ijk) const
-{
- btAssert(m_isValid);
- btVector3 tmp;
- tmp.m_floats[0] = m_cell_size[0] * (double)ijk.ijk[0];
- tmp.m_floats[1] = m_cell_size[1] * (double)ijk.ijk[1];
- tmp.m_floats[2] = m_cell_size[2] * (double)ijk.ijk[2];
-
- btVector3 origin = m_domain.min() + tmp;
-
- btAlignedBox3d box = btAlignedBox3d(origin, origin + m_cell_size);
- return box;
-}
-
-btMultiIndex
-btMiniSDF::singleToMultiIndex(unsigned int l) const
-{
- btAssert(m_isValid);
- unsigned int n01 = m_resolution[0] * m_resolution[1];
- unsigned int k = l / n01;
- unsigned int temp = l % n01;
- unsigned int j = temp / m_resolution[0];
- unsigned int i = temp % m_resolution[0];
- btMultiIndex mi;
- mi.ijk[0] = i;
- mi.ijk[1] = j;
- mi.ijk[2] = k;
- return mi;
-}
-
-btAlignedBox3d
-btMiniSDF::subdomain(unsigned int l) const
-{
- btAssert(m_isValid);
- return subdomain(singleToMultiIndex(l));
-}
-
-btShapeMatrix
-btMiniSDF::shape_function_(btVector3 const& xi, btShapeGradients* gradient) const
-{
- btAssert(m_isValid);
- btShapeMatrix res;
-
- btScalar x = xi[0];
- btScalar y = xi[1];
- btScalar z = xi[2];
-
- btScalar x2 = x * x;
- btScalar y2 = y * y;
- btScalar z2 = z * z;
-
- btScalar _1mx = 1.0 - x;
- btScalar _1my = 1.0 - y;
- btScalar _1mz = 1.0 - z;
-
- btScalar _1px = 1.0 + x;
- btScalar _1py = 1.0 + y;
- btScalar _1pz = 1.0 + z;
-
- btScalar _1m3x = 1.0 - 3.0 * x;
- btScalar _1m3y = 1.0 - 3.0 * y;
- btScalar _1m3z = 1.0 - 3.0 * z;
-
- btScalar _1p3x = 1.0 + 3.0 * x;
- btScalar _1p3y = 1.0 + 3.0 * y;
- btScalar _1p3z = 1.0 + 3.0 * z;
-
- btScalar _1mxt1my = _1mx * _1my;
- btScalar _1mxt1py = _1mx * _1py;
- btScalar _1pxt1my = _1px * _1my;
- btScalar _1pxt1py = _1px * _1py;
-
- btScalar _1mxt1mz = _1mx * _1mz;
- btScalar _1mxt1pz = _1mx * _1pz;
- btScalar _1pxt1mz = _1px * _1mz;
- btScalar _1pxt1pz = _1px * _1pz;
-
- btScalar _1myt1mz = _1my * _1mz;
- btScalar _1myt1pz = _1my * _1pz;
- btScalar _1pyt1mz = _1py * _1mz;
- btScalar _1pyt1pz = _1py * _1pz;
-
- btScalar _1mx2 = 1.0 - x2;
- btScalar _1my2 = 1.0 - y2;
- btScalar _1mz2 = 1.0 - z2;
-
- // Corner nodes.
- btScalar fac = 1.0 / 64.0 * (9.0 * (x2 + y2 + z2) - 19.0);
- res[0] = fac * _1mxt1my * _1mz;
- res[1] = fac * _1pxt1my * _1mz;
- res[2] = fac * _1mxt1py * _1mz;
- res[3] = fac * _1pxt1py * _1mz;
- res[4] = fac * _1mxt1my * _1pz;
- res[5] = fac * _1pxt1my * _1pz;
- res[6] = fac * _1mxt1py * _1pz;
- res[7] = fac * _1pxt1py * _1pz;
-
- // Edge nodes.
-
- fac = 9.0 / 64.0 * _1mx2;
- btScalar fact1m3x = fac * _1m3x;
- btScalar fact1p3x = fac * _1p3x;
- res[8] = fact1m3x * _1myt1mz;
- res[9] = fact1p3x * _1myt1mz;
- res[10] = fact1m3x * _1myt1pz;
- res[11] = fact1p3x * _1myt1pz;
- res[12] = fact1m3x * _1pyt1mz;
- res[13] = fact1p3x * _1pyt1mz;
- res[14] = fact1m3x * _1pyt1pz;
- res[15] = fact1p3x * _1pyt1pz;
-
- fac = 9.0 / 64.0 * _1my2;
- btScalar fact1m3y = fac * _1m3y;
- btScalar fact1p3y = fac * _1p3y;
- res[16] = fact1m3y * _1mxt1mz;
- res[17] = fact1p3y * _1mxt1mz;
- res[18] = fact1m3y * _1pxt1mz;
- res[19] = fact1p3y * _1pxt1mz;
- res[20] = fact1m3y * _1mxt1pz;
- res[21] = fact1p3y * _1mxt1pz;
- res[22] = fact1m3y * _1pxt1pz;
- res[23] = fact1p3y * _1pxt1pz;
-
- fac = 9.0 / 64.0 * _1mz2;
- btScalar fact1m3z = fac * _1m3z;
- btScalar fact1p3z = fac * _1p3z;
- res[24] = fact1m3z * _1mxt1my;
- res[25] = fact1p3z * _1mxt1my;
- res[26] = fact1m3z * _1mxt1py;
- res[27] = fact1p3z * _1mxt1py;
- res[28] = fact1m3z * _1pxt1my;
- res[29] = fact1p3z * _1pxt1my;
- res[30] = fact1m3z * _1pxt1py;
- res[31] = fact1p3z * _1pxt1py;
-
- if (gradient)
- {
- btShapeGradients& dN = *gradient;
-
- btScalar _9t3x2py2pz2m19 = 9.0 * (3.0 * x2 + y2 + z2) - 19.0;
- btScalar _9tx2p3y2pz2m19 = 9.0 * (x2 + 3.0 * y2 + z2) - 19.0;
- btScalar _9tx2py2p3z2m19 = 9.0 * (x2 + y2 + 3.0 * z2) - 19.0;
- btScalar _18x = 18.0 * x;
- btScalar _18y = 18.0 * y;
- btScalar _18z = 18.0 * z;
-
- btScalar _3m9x2 = 3.0 - 9.0 * x2;
- btScalar _3m9y2 = 3.0 - 9.0 * y2;
- btScalar _3m9z2 = 3.0 - 9.0 * z2;
-
- btScalar _2x = 2.0 * x;
- btScalar _2y = 2.0 * y;
- btScalar _2z = 2.0 * z;
-
- btScalar _18xm9t3x2py2pz2m19 = _18x - _9t3x2py2pz2m19;
- btScalar _18xp9t3x2py2pz2m19 = _18x + _9t3x2py2pz2m19;
- btScalar _18ym9tx2p3y2pz2m19 = _18y - _9tx2p3y2pz2m19;
- btScalar _18yp9tx2p3y2pz2m19 = _18y + _9tx2p3y2pz2m19;
- btScalar _18zm9tx2py2p3z2m19 = _18z - _9tx2py2p3z2m19;
- btScalar _18zp9tx2py2p3z2m19 = _18z + _9tx2py2p3z2m19;
-
- dN(0, 0) = _18xm9t3x2py2pz2m19 * _1myt1mz;
- dN(0, 1) = _1mxt1mz * _18ym9tx2p3y2pz2m19;
- dN(0, 2) = _1mxt1my * _18zm9tx2py2p3z2m19;
- dN(1, 0) = _18xp9t3x2py2pz2m19 * _1myt1mz;
- dN(1, 1) = _1pxt1mz * _18ym9tx2p3y2pz2m19;
- dN(1, 2) = _1pxt1my * _18zm9tx2py2p3z2m19;
- dN(2, 0) = _18xm9t3x2py2pz2m19 * _1pyt1mz;
- dN(2, 1) = _1mxt1mz * _18yp9tx2p3y2pz2m19;
- dN(2, 2) = _1mxt1py * _18zm9tx2py2p3z2m19;
- dN(3, 0) = _18xp9t3x2py2pz2m19 * _1pyt1mz;
- dN(3, 1) = _1pxt1mz * _18yp9tx2p3y2pz2m19;
- dN(3, 2) = _1pxt1py * _18zm9tx2py2p3z2m19;
- dN(4, 0) = _18xm9t3x2py2pz2m19 * _1myt1pz;
- dN(4, 1) = _1mxt1pz * _18ym9tx2p3y2pz2m19;
- dN(4, 2) = _1mxt1my * _18zp9tx2py2p3z2m19;
- dN(5, 0) = _18xp9t3x2py2pz2m19 * _1myt1pz;
- dN(5, 1) = _1pxt1pz * _18ym9tx2p3y2pz2m19;
- dN(5, 2) = _1pxt1my * _18zp9tx2py2p3z2m19;
- dN(6, 0) = _18xm9t3x2py2pz2m19 * _1pyt1pz;
- dN(6, 1) = _1mxt1pz * _18yp9tx2p3y2pz2m19;
- dN(6, 2) = _1mxt1py * _18zp9tx2py2p3z2m19;
- dN(7, 0) = _18xp9t3x2py2pz2m19 * _1pyt1pz;
- dN(7, 1) = _1pxt1pz * _18yp9tx2p3y2pz2m19;
- dN(7, 2) = _1pxt1py * _18zp9tx2py2p3z2m19;
-
- dN.topRowsDivide(8, 64.0);
-
- btScalar _m3m9x2m2x = -_3m9x2 - _2x;
- btScalar _p3m9x2m2x = _3m9x2 - _2x;
- btScalar _1mx2t1m3x = _1mx2 * _1m3x;
- btScalar _1mx2t1p3x = _1mx2 * _1p3x;
- dN(8, 0) = _m3m9x2m2x * _1myt1mz,
- dN(8, 1) = -_1mx2t1m3x * _1mz,
- dN(8, 2) = -_1mx2t1m3x * _1my;
- dN(9, 0) = _p3m9x2m2x * _1myt1mz,
- dN(9, 1) = -_1mx2t1p3x * _1mz,
- dN(9, 2) = -_1mx2t1p3x * _1my;
- dN(10, 0) = _m3m9x2m2x * _1myt1pz,
- dN(10, 1) = -_1mx2t1m3x * _1pz,
- dN(10, 2) = _1mx2t1m3x * _1my;
- dN(11, 0) = _p3m9x2m2x * _1myt1pz,
- dN(11, 1) = -_1mx2t1p3x * _1pz,
- dN(11, 2) = _1mx2t1p3x * _1my;
- dN(12, 0) = _m3m9x2m2x * _1pyt1mz,
- dN(12, 1) = _1mx2t1m3x * _1mz,
- dN(12, 2) = -_1mx2t1m3x * _1py;
- dN(13, 0) = _p3m9x2m2x * _1pyt1mz,
- dN(13, 1) = _1mx2t1p3x * _1mz,
- dN(13, 2) = -_1mx2t1p3x * _1py;
- dN(14, 0) = _m3m9x2m2x * _1pyt1pz,
- dN(14, 1) = _1mx2t1m3x * _1pz,
- dN(14, 2) = _1mx2t1m3x * _1py;
- dN(15, 0) = _p3m9x2m2x * _1pyt1pz,
- dN(15, 1) = _1mx2t1p3x * _1pz,
- dN(15, 2) = _1mx2t1p3x * _1py;
-
- btScalar _m3m9y2m2y = -_3m9y2 - _2y;
- btScalar _p3m9y2m2y = _3m9y2 - _2y;
- btScalar _1my2t1m3y = _1my2 * _1m3y;
- btScalar _1my2t1p3y = _1my2 * _1p3y;
- dN(16, 0) = -_1my2t1m3y * _1mz,
- dN(16, 1) = _m3m9y2m2y * _1mxt1mz,
- dN(16, 2) = -_1my2t1m3y * _1mx;
- dN(17, 0) = -_1my2t1p3y * _1mz,
- dN(17, 1) = _p3m9y2m2y * _1mxt1mz,
- dN(17, 2) = -_1my2t1p3y * _1mx;
- dN(18, 0) = _1my2t1m3y * _1mz,
- dN(18, 1) = _m3m9y2m2y * _1pxt1mz,
- dN(18, 2) = -_1my2t1m3y * _1px;
- dN(19, 0) = _1my2t1p3y * _1mz,
- dN(19, 1) = _p3m9y2m2y * _1pxt1mz,
- dN(19, 2) = -_1my2t1p3y * _1px;
- dN(20, 0) = -_1my2t1m3y * _1pz,
- dN(20, 1) = _m3m9y2m2y * _1mxt1pz,
- dN(20, 2) = _1my2t1m3y * _1mx;
- dN(21, 0) = -_1my2t1p3y * _1pz,
- dN(21, 1) = _p3m9y2m2y * _1mxt1pz,
- dN(21, 2) = _1my2t1p3y * _1mx;
- dN(22, 0) = _1my2t1m3y * _1pz,
- dN(22, 1) = _m3m9y2m2y * _1pxt1pz,
- dN(22, 2) = _1my2t1m3y * _1px;
- dN(23, 0) = _1my2t1p3y * _1pz,
- dN(23, 1) = _p3m9y2m2y * _1pxt1pz,
- dN(23, 2) = _1my2t1p3y * _1px;
-
- btScalar _m3m9z2m2z = -_3m9z2 - _2z;
- btScalar _p3m9z2m2z = _3m9z2 - _2z;
- btScalar _1mz2t1m3z = _1mz2 * _1m3z;
- btScalar _1mz2t1p3z = _1mz2 * _1p3z;
- dN(24, 0) = -_1mz2t1m3z * _1my,
- dN(24, 1) = -_1mz2t1m3z * _1mx,
- dN(24, 2) = _m3m9z2m2z * _1mxt1my;
- dN(25, 0) = -_1mz2t1p3z * _1my,
- dN(25, 1) = -_1mz2t1p3z * _1mx,
- dN(25, 2) = _p3m9z2m2z * _1mxt1my;
- dN(26, 0) = -_1mz2t1m3z * _1py,
- dN(26, 1) = _1mz2t1m3z * _1mx,
- dN(26, 2) = _m3m9z2m2z * _1mxt1py;
- dN(27, 0) = -_1mz2t1p3z * _1py,
- dN(27, 1) = _1mz2t1p3z * _1mx,
- dN(27, 2) = _p3m9z2m2z * _1mxt1py;
- dN(28, 0) = _1mz2t1m3z * _1my,
- dN(28, 1) = -_1mz2t1m3z * _1px,
- dN(28, 2) = _m3m9z2m2z * _1pxt1my;
- dN(29, 0) = _1mz2t1p3z * _1my,
- dN(29, 1) = -_1mz2t1p3z * _1px,
- dN(29, 2) = _p3m9z2m2z * _1pxt1my;
- dN(30, 0) = _1mz2t1m3z * _1py,
- dN(30, 1) = _1mz2t1m3z * _1px,
- dN(30, 2) = _m3m9z2m2z * _1pxt1py;
- dN(31, 0) = _1mz2t1p3z * _1py,
- dN(31, 1) = _1mz2t1p3z * _1px,
- dN(31, 2) = _p3m9z2m2z * _1pxt1py;
-
- dN.bottomRowsMul(32u - 8u, 9.0 / 64.0);
- }
-
- return res;
-}
-
-bool btMiniSDF::interpolate(unsigned int field_id, double& dist, btVector3 const& x,
- btVector3* gradient) const
-{
- btAssert(m_isValid);
- if (!m_isValid)
- return false;
-
- if (!m_domain.contains(x))
- return false;
-
- btVector3 tmpmi = ((x - m_domain.min()) * (m_inv_cell_size)); //.cast<unsigned int>().eval();
- unsigned int mi[3] = {(unsigned int)tmpmi[0], (unsigned int)tmpmi[1], (unsigned int)tmpmi[2]};
- if (mi[0] >= m_resolution[0])
- mi[0] = m_resolution[0] - 1;
- if (mi[1] >= m_resolution[1])
- mi[1] = m_resolution[1] - 1;
- if (mi[2] >= m_resolution[2])
- mi[2] = m_resolution[2] - 1;
- btMultiIndex mui;
- mui.ijk[0] = mi[0];
- mui.ijk[1] = mi[1];
- mui.ijk[2] = mi[2];
- int i = multiToSingleIndex(mui);
- unsigned int i_ = m_cell_map[field_id][i];
- if (i_ == UINT_MAX)
- return false;
-
- btAlignedBox3d sd = subdomain(i);
- i = i_;
- btVector3 d = sd.m_max - sd.m_min; //.diagonal().eval();
-
- btVector3 denom = (sd.max() - sd.min());
- btVector3 c0 = btVector3(2.0, 2.0, 2.0) / denom;
- btVector3 c1 = (sd.max() + sd.min()) / denom;
- btVector3 xi = (c0 * x - c1);
-
- btCell32 const& cell = m_cells[field_id][i];
- if (!gradient)
- {
- //auto phi = m_coefficients[field_id][i].dot(shape_function_(xi, 0));
- double phi = 0.0;
- btShapeMatrix N = shape_function_(xi, 0);
- for (unsigned int j = 0u; j < 32u; ++j)
- {
- unsigned int v = cell.m_cells[j];
- double c = m_nodes[field_id][v];
- if (c == DBL_MAX)
- {
- return false;
- ;
- }
- phi += c * N[j];
- }
-
- dist = phi;
- return true;
- }
-
- btShapeGradients dN;
- btShapeMatrix N = shape_function_(xi, &dN);
-
- double phi = 0.0;
- gradient->setZero();
- for (unsigned int j = 0u; j < 32u; ++j)
- {
- unsigned int v = cell.m_cells[j];
- double c = m_nodes[field_id][v];
- if (c == DBL_MAX)
- {
- gradient->setZero();
- return false;
- }
- phi += c * N[j];
- (*gradient)[0] += c * dN(j, 0);
- (*gradient)[1] += c * dN(j, 1);
- (*gradient)[2] += c * dN(j, 2);
- }
- (*gradient) *= c0;
- dist = phi;
- return true;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h
deleted file mode 100644
index b60fd102fd..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMiniSDF.h
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef MINISDF_H
-#define MINISDF_H
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-struct btMultiIndex
-{
- unsigned int ijk[3];
-};
-
-struct btAlignedBox3d
-{
- btVector3 m_min;
- btVector3 m_max;
-
- const btVector3& min() const
- {
- return m_min;
- }
-
- const btVector3& max() const
- {
- return m_max;
- }
-
- bool contains(const btVector3& x) const
- {
- return TestPointAgainstAabb2(m_min, m_max, x);
- }
-
- btAlignedBox3d(const btVector3& mn, const btVector3& mx)
- : m_min(mn),
- m_max(mx)
- {
- }
-
- btAlignedBox3d()
- {
- }
-};
-
-struct btShapeMatrix
-{
- double m_vec[32];
-
- inline double& operator[](int i)
- {
- return m_vec[i];
- }
-
- inline const double& operator[](int i) const
- {
- return m_vec[i];
- }
-};
-
-struct btShapeGradients
-{
- btVector3 m_vec[32];
-
- void topRowsDivide(int row, double denom)
- {
- for (int i = 0; i < row; i++)
- {
- m_vec[i] /= denom;
- }
- }
-
- void bottomRowsMul(int row, double val)
- {
- for (int i = 32 - row; i < 32; i++)
- {
- m_vec[i] *= val;
- }
- }
-
- inline btScalar& operator()(int i, int j)
- {
- return m_vec[i][j];
- }
-};
-
-struct btCell32
-{
- unsigned int m_cells[32];
-};
-
-struct btMiniSDF
-{
- btAlignedBox3d m_domain;
- unsigned int m_resolution[3];
- btVector3 m_cell_size;
- btVector3 m_inv_cell_size;
- std::size_t m_n_cells;
- std::size_t m_n_fields;
- bool m_isValid;
-
- btAlignedObjectArray<btAlignedObjectArray<double> > m_nodes;
- btAlignedObjectArray<btAlignedObjectArray<btCell32> > m_cells;
- btAlignedObjectArray<btAlignedObjectArray<unsigned int> > m_cell_map;
-
- btMiniSDF()
- : m_isValid(false)
- {
- }
- bool load(const char* data, int size);
- bool isValid() const
- {
- return m_isValid;
- }
- unsigned int multiToSingleIndex(btMultiIndex const& ijk) const;
-
- btAlignedBox3d subdomain(btMultiIndex const& ijk) const;
-
- btMultiIndex singleToMultiIndex(unsigned int l) const;
-
- btAlignedBox3d subdomain(unsigned int l) const;
-
- btShapeMatrix
- shape_function_(btVector3 const& xi, btShapeGradients* gradient = 0) const;
-
- bool interpolate(unsigned int field_id, double& dist, btVector3 const& x, btVector3* gradient) const;
-};
-
-#endif //MINISDF_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
deleted file mode 100644
index d4b6a651de..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btMinkowskiSumShape.h"
-
-btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB)
- : btConvexInternalShape(),
- m_shapeA(shapeA),
- m_shapeB(shapeB)
-{
- m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
- m_transA.setIdentity();
- m_transB.setIdentity();
-}
-
-btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec * m_transA.getBasis()));
- btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec * m_transB.getBasis()));
- return supVertexA - supVertexB;
-}
-
-void btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- ///@todo: could make recursive use of batching. probably this shape is not used frequently.
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
- }
-}
-
-btScalar btMinkowskiSumShape::getMargin() const
-{
- return m_shapeA->getMargin() + m_shapeB->getMargin();
-}
-
-void btMinkowskiSumShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- (void)mass;
- //inertia of the AABB of the Minkowski sum
- btTransform identity;
- identity.setIdentity();
- btVector3 aabbMin, aabbMax;
- getAabb(identity, aabbMin, aabbMax);
-
- btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
-
- btScalar margin = getMargin();
-
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
deleted file mode 100644
index 3b5150f6d5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MINKOWSKI_SUM_SHAPE_H
-#define BT_MINKOWSKI_SUM_SHAPE_H
-
-#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
-ATTRIBUTE_ALIGNED16(class)
-btMinkowskiSumShape : public btConvexInternalShape
-{
- btTransform m_transA;
- btTransform m_transB;
- const btConvexShape* m_shapeA;
- const btConvexShape* m_shapeB;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMinkowskiSumShape(const btConvexShape* shapeA, const btConvexShape* shapeB);
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- void setTransformA(const btTransform& transA) { m_transA = transA; }
- void setTransformB(const btTransform& transB) { m_transB = transB; }
-
- const btTransform& getTransformA() const { return m_transA; }
- const btTransform& GetTransformB() const { return m_transB; }
-
- virtual btScalar getMargin() const;
-
- const btConvexShape* getShapeA() const { return m_shapeA; }
- const btConvexShape* getShapeB() const { return m_shapeB; }
-
- virtual const char* getName() const
- {
- return "MinkowskiSum";
- }
-};
-
-#endif //BT_MINKOWSKI_SUM_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
deleted file mode 100644
index c0cc55dfb0..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#if defined(_WIN32) || defined(__i386__)
-#define BT_USE_SSE_IN_API
-#endif
-
-#include "btMultiSphereShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-#include "LinearMath/btQuaternion.h"
-#include "LinearMath/btSerializer.h"
-
-btMultiSphereShape::btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres)
- : btConvexInternalAabbCachingShape()
-{
- m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
- //btScalar startMargin = btScalar(BT_LARGE_FLOAT);
-
- m_localPositionArray.resize(numSpheres);
- m_radiArray.resize(numSpheres);
- for (int i = 0; i < numSpheres; i++)
- {
- m_localPositionArray[i] = positions[i];
- m_radiArray[i] = radi[i];
- }
-
- recalcLocalAabb();
-}
-
-#ifndef MIN
-#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
-#endif
-btVector3 btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
-{
- btVector3 supVec(0, 0, 0);
-
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
-
- btVector3 vtx;
- btScalar newDot;
-
- const btVector3* pos = &m_localPositionArray[0];
- const btScalar* rad = &m_radiArray[0];
- int numSpheres = m_localPositionArray.size();
-
- for (int k = 0; k < numSpheres; k += 128)
- {
- btVector3 temp[128];
- int inner_count = MIN(numSpheres - k, 128);
- for (long i = 0; i < inner_count; i++)
- {
- temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
- pos++;
- rad++;
- }
- long i = vec.maxDot(temp, inner_count, newDot);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = temp[i];
- }
- }
-
- return supVec;
-}
-
-void btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- for (int j = 0; j < numVectors; j++)
- {
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
- const btVector3& vec = vectors[j];
-
- btVector3 vtx;
- btScalar newDot;
-
- const btVector3* pos = &m_localPositionArray[0];
- const btScalar* rad = &m_radiArray[0];
- int numSpheres = m_localPositionArray.size();
-
- for (int k = 0; k < numSpheres; k += 128)
- {
- btVector3 temp[128];
- int inner_count = MIN(numSpheres - k, 128);
- for (long i = 0; i < inner_count; i++)
- {
- temp[i] = (*pos) * m_localScaling + vec * m_localScaling * (*rad) - vec * getMargin();
- pos++;
- rad++;
- }
- long i = vec.maxDot(temp, inner_count, newDot);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supportVerticesOut[j] = temp[i];
- }
- }
- }
-}
-
-void btMultiSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- //as an approximation, take the inertia of the box that bounds the spheres
-
- btVector3 localAabbMin, localAabbMax;
- getCachedLocalAabb(localAabbMin, localAabbMax);
- btVector3 halfExtents = (localAabbMax - localAabbMin) * btScalar(0.5);
-
- btScalar lx = btScalar(2.) * (halfExtents.x());
- btScalar ly = btScalar(2.) * (halfExtents.y());
- btScalar lz = btScalar(2.) * (halfExtents.z());
-
- inertia.setValue(mass / (btScalar(12.0)) * (ly * ly + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + lz * lz),
- mass / (btScalar(12.0)) * (lx * lx + ly * ly));
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*)dataBuffer;
- btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
-
- int numElem = m_localPositionArray.size();
- shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]) : 0;
-
- shapeData->m_localPositionArraySize = numElem;
- if (numElem)
- {
- btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius), numElem);
- btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_localPositionArray[i].serializeFloat(memPtr->m_pos);
- memPtr->m_radius = float(m_radiArray[i]);
- }
- serializer->finalizeChunk(chunk, "btPositionAndRadius", BT_ARRAY_CODE, (void*)&m_localPositionArray[0]);
- }
-
- // Fill padding with zeros to appease msan.
- memset(shapeData->m_padding, 0, sizeof(shapeData->m_padding));
-
- return "btMultiSphereShapeData";
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
deleted file mode 100644
index 2d79c07ca4..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTI_SPHERE_MINKOWSKI_H
-#define BT_MULTI_SPHERE_MINKOWSKI_H
-
-#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btAabbUtil2.h"
-
-///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
-///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
-ATTRIBUTE_ALIGNED16(class)
-btMultiSphereShape : public btConvexInternalAabbCachingShape
-{
- btAlignedObjectArray<btVector3> m_localPositionArray;
- btAlignedObjectArray<btScalar> m_radiArray;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultiSphereShape(const btVector3* positions, const btScalar* radi, int numSpheres);
-
- ///CollisionShape Interface
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- /// btConvexShape Interface
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- int getSphereCount() const
- {
- return m_localPositionArray.size();
- }
-
- const btVector3& getSpherePosition(int index) const
- {
- return m_localPositionArray[index];
- }
-
- btScalar getSphereRadius(int index) const
- {
- return m_radiArray[index];
- }
-
- virtual const char* getName() const
- {
- return "MultiSphere";
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-struct btPositionAndRadius
-{
- btVector3FloatData m_pos;
- float m_radius;
-};
-
-// clang-format off
-
-struct btMultiSphereShapeData
-{
- btConvexInternalShapeData m_convexInternalShapeData;
-
- btPositionAndRadius *m_localPositionArrayPtr;
- int m_localPositionArraySize;
- char m_padding[4];
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btMultiSphereShape::calculateSerializeBufferSize() const
-{
- return sizeof(btMultiSphereShapeData);
-}
-
-#endif //BT_MULTI_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
deleted file mode 100644
index 30108c9e7b..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// This file was created by Alex Silverman
-
-#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
-//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
-
-///Obtains the material for a specific triangle
-const btMaterial *btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
-{
- const unsigned char *materialBase = 0;
- int numMaterials;
- PHY_ScalarType materialType;
- int materialStride;
- const unsigned char *triangleMaterialBase = 0;
- int numTriangles;
- int triangleMaterialStride;
- PHY_ScalarType triangleType;
-
- ((btTriangleIndexVertexMaterialArray *)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride, &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
-
- // return the pointer to the place with the friction for the triangle
- // TODO: This depends on whether it's a moving mesh or not
- // BUG IN GIMPACT
- //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
- int *matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
- btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
- return (matVal);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
deleted file mode 100644
index d1d42f8e04..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// This file was created by Alex Silverman
-
-#ifndef BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
-#define BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
-
-#include "btBvhTriangleMeshShape.h"
-#include "btMaterial.h"
-
-///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
-ATTRIBUTE_ALIGNED16(class)
-btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
-{
- btAlignedObjectArray<btMaterial *> m_materialList;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultimaterialTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true) : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
- {
- m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
-
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
-
- for (int i = 0; i < meshInterface->getNumSubParts(); i++)
- {
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- i);
- //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
- }
- }
-
- ///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
- btMultimaterialTriangleMeshShape(btStridingMeshInterface * meshInterface, bool useQuantizedAabbCompression, const btVector3 &bvhAabbMin, const btVector3 &bvhAabbMax, bool buildBvh = true) : btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
- {
- m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
-
- const unsigned char *vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char *indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
-
- for (int i = 0; i < meshInterface->getNumSubParts(); i++)
- {
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase,
- numverts,
- type,
- stride,
- &indexbase,
- indexstride,
- numfaces,
- indicestype,
- i);
- //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
- }
- }
-
- virtual ~btMultimaterialTriangleMeshShape()
- {
- /*
- for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
- {
- btAlignedFree(m_materialValues[i]);
- m_materialLookup[i] = NULL;
- }
- btAlignedFree(m_materialValues);
- m_materialLookup = NULL;
-*/
- }
- //debugging
- virtual const char *getName() const { return "MULTIMATERIALTRIANGLEMESH"; }
-
- ///Obtains the material for a specific triangle
- const btMaterial *getMaterialProperties(int partID, int triIndex);
-};
-
-#endif //BT_BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
deleted file mode 100644
index 863ea6d6ac..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btOptimizedBvh.h"
-#include "btStridingMeshInterface.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "LinearMath/btIDebugDraw.h"
-
-btOptimizedBvh::btOptimizedBvh()
-{
-}
-
-btOptimizedBvh::~btOptimizedBvh()
-{
-}
-
-void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
-{
- m_useQuantization = useQuantizedAabbCompression;
-
- // NodeArray triangleNodes;
-
- struct NodeTriangleCallback : public btInternalTriangleIndexCallback
- {
- NodeArray& m_triangleNodes;
-
- NodeTriangleCallback& operator=(NodeTriangleCallback& other)
- {
- m_triangleNodes.copyFromArray(other.m_triangleNodes);
- return *this;
- }
-
- NodeTriangleCallback(NodeArray& triangleNodes)
- : m_triangleNodes(triangleNodes)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- btOptimizedBvhNode node;
- btVector3 aabbMin, aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- //with quantization?
- node.m_aabbMinOrg = aabbMin;
- node.m_aabbMaxOrg = aabbMax;
-
- node.m_escapeIndex = -1;
-
- //for child nodes
- node.m_subPart = partId;
- node.m_triangleIndex = triangleIndex;
- m_triangleNodes.push_back(node);
- }
- };
- struct QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
- {
- QuantizedNodeArray& m_triangleNodes;
- const btQuantizedBvh* m_optimizedTree; // for quantization
-
- QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
- {
- m_triangleNodes.copyFromArray(other.m_triangleNodes);
- m_optimizedTree = other.m_optimizedTree;
- return *this;
- }
-
- QuantizedNodeTriangleCallback(QuantizedNodeArray& triangleNodes, const btQuantizedBvh* tree)
- : m_triangleNodes(triangleNodes), m_optimizedTree(tree)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- // The partId and triangle index must fit in the same (positive) integer
- btAssert(partId < (1 << MAX_NUM_PARTS_IN_BITS));
- btAssert(triangleIndex < (1 << (31 - MAX_NUM_PARTS_IN_BITS)));
- //negative indices are reserved for escapeIndex
- btAssert(triangleIndex >= 0);
-
- btQuantizedBvhNode node;
- btVector3 aabbMin, aabbMax;
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangle[0]);
- aabbMax.setMax(triangle[0]);
- aabbMin.setMin(triangle[1]);
- aabbMax.setMax(triangle[1]);
- aabbMin.setMin(triangle[2]);
- aabbMax.setMax(triangle[2]);
-
- //PCK: add these checks for zero dimensions of aabb
- const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
- const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
- if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
- {
- aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
- }
- if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
- {
- aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
- }
- if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
- {
- aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
- aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
- }
-
- m_optimizedTree->quantize(&node.m_quantizedAabbMin[0], aabbMin, 0);
- m_optimizedTree->quantize(&node.m_quantizedAabbMax[0], aabbMax, 1);
-
- node.m_escapeIndexOrTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
-
- m_triangleNodes.push_back(node);
- }
- };
-
- int numLeafNodes = 0;
-
- if (m_useQuantization)
- {
- //initialize quantization values
- setQuantizationValues(bvhAabbMin, bvhAabbMax);
-
- QuantizedNodeTriangleCallback callback(m_quantizedLeafNodes, this);
-
- triangles->InternalProcessAllTriangles(&callback, m_bvhAabbMin, m_bvhAabbMax);
-
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_quantizedLeafNodes.size();
-
- m_quantizedContiguousNodes.resize(2 * numLeafNodes);
- }
- else
- {
- NodeTriangleCallback callback(m_leafNodes);
-
- btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
-
- triangles->InternalProcessAllTriangles(&callback, aabbMin, aabbMax);
-
- //now we have an array of leafnodes in m_leafNodes
- numLeafNodes = m_leafNodes.size();
-
- m_contiguousNodes.resize(2 * numLeafNodes);
- }
-
- m_curNodeIndex = 0;
-
- buildTree(0, numLeafNodes);
-
- ///if the entire tree is small then subtree size, we need to create a header info for the tree
- if (m_useQuantization && !m_SubtreeHeaders.size())
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
- subtree.m_rootNodeIndex = 0;
- subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
- }
-
- //PCK: update the copy of the size
- m_subtreeHeaderCount = m_SubtreeHeaders.size();
-
- //PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
- m_quantizedLeafNodes.clear();
- m_leafNodes.clear();
-}
-
-void btOptimizedBvh::refit(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- if (m_useQuantization)
- {
- setQuantizationValues(aabbMin, aabbMax);
-
- updateBvhNodes(meshInterface, 0, m_curNodeIndex, 0);
-
- ///now update all subtree headers
-
- int i;
- for (i = 0; i < m_SubtreeHeaders.size(); i++)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
- }
- }
- else
- {
- }
-}
-
-void btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface, const btVector3& aabbMin, const btVector3& aabbMax)
-{
- //incrementally initialize quantization values
- btAssert(m_useQuantization);
-
- btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
- btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
- btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
-
- btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
- btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
- btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
-
- ///we should update all quantization values, using updateBvhNodes(meshInterface);
- ///but we only update chunks that overlap the given aabb
-
- unsigned short quantizedQueryAabbMin[3];
- unsigned short quantizedQueryAabbMax[3];
-
- quantize(&quantizedQueryAabbMin[0], aabbMin, 0);
- quantize(&quantizedQueryAabbMax[0], aabbMax, 1);
-
- int i;
- for (i = 0; i < this->m_SubtreeHeaders.size(); i++)
- {
- btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
-
- //PCK: unsigned instead of bool
- unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin, quantizedQueryAabbMax, subtree.m_quantizedAabbMin, subtree.m_quantizedAabbMax);
- if (overlap != 0)
- {
- updateBvhNodes(meshInterface, subtree.m_rootNodeIndex, subtree.m_rootNodeIndex + subtree.m_subtreeSize, i);
-
- subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
- }
- }
-}
-
-void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface, int firstNode, int endNode, int index)
-{
- (void)index;
-
- btAssert(m_useQuantization);
-
- int curNodeSubPart = -1;
-
- //get access info to trianglemesh data
- const unsigned char* vertexbase = 0;
- int numverts = 0;
- PHY_ScalarType type = PHY_INTEGER;
- int stride = 0;
- const unsigned char* indexbase = 0;
- int indexstride = 0;
- int numfaces = 0;
- PHY_ScalarType indicestype = PHY_INTEGER;
-
- btVector3 triangleVerts[3];
- btVector3 aabbMin, aabbMax;
- const btVector3& meshScaling = meshInterface->getScaling();
-
- int i;
- for (i = endNode - 1; i >= firstNode; i--)
- {
- btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
- if (curNode.isLeafNode())
- {
- //recalc aabb from triangle data
- int nodeSubPart = curNode.getPartId();
- int nodeTriangleIndex = curNode.getTriangleIndex();
- if (nodeSubPart != curNodeSubPart)
- {
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
- meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numfaces, indicestype, nodeSubPart);
-
- curNodeSubPart = nodeSubPart;
- }
- //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
-
- unsigned int* gfxbase = (unsigned int*)(indexbase + nodeTriangleIndex * indexstride);
-
- for (int j = 2; j >= 0; j--)
- {
- int graphicsindex;
- switch (indicestype) {
- case PHY_INTEGER: graphicsindex = gfxbase[j]; break;
- case PHY_SHORT: graphicsindex = ((unsigned short*)gfxbase)[j]; break;
- case PHY_UCHAR: graphicsindex = ((unsigned char*)gfxbase)[j]; break;
- default: btAssert(0);
- }
- if (type == PHY_FLOAT)
- {
- float* graphicsbase = (float*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(
- graphicsbase[0] * meshScaling.getX(),
- graphicsbase[1] * meshScaling.getY(),
- graphicsbase[2] * meshScaling.getZ());
- }
- else
- {
- double* graphicsbase = (double*)(vertexbase + graphicsindex * stride);
- triangleVerts[j] = btVector3(btScalar(graphicsbase[0] * meshScaling.getX()), btScalar(graphicsbase[1] * meshScaling.getY()), btScalar(graphicsbase[2] * meshScaling.getZ()));
- }
- }
-
- aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMin.setMin(triangleVerts[0]);
- aabbMax.setMax(triangleVerts[0]);
- aabbMin.setMin(triangleVerts[1]);
- aabbMax.setMax(triangleVerts[1]);
- aabbMin.setMin(triangleVerts[2]);
- aabbMax.setMax(triangleVerts[2]);
-
- quantize(&curNode.m_quantizedAabbMin[0], aabbMin, 0);
- quantize(&curNode.m_quantizedAabbMax[0], aabbMax, 1);
- }
- else
- {
- //combine aabb from both children
-
- btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i + 1];
-
- btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i + 2] : &m_quantizedContiguousNodes[i + 1 + leftChildNode->getEscapeIndex()];
-
- {
- for (int i = 0; i < 3; i++)
- {
- curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
- if (curNode.m_quantizedAabbMin[i] > rightChildNode->m_quantizedAabbMin[i])
- curNode.m_quantizedAabbMin[i] = rightChildNode->m_quantizedAabbMin[i];
-
- curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
- if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
- curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
- }
- }
- }
- }
-
- if (curNodeSubPart >= 0)
- meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
-}
-
-///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
-btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
-{
- btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
-
- //we don't add additional data so just do a static upcast
- return static_cast<btOptimizedBvh*>(bvh);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
deleted file mode 100644
index 22f131c8b2..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///Contains contributions from Disney Studio's
-
-#ifndef BT_OPTIMIZED_BVH_H
-#define BT_OPTIMIZED_BVH_H
-
-#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
-
-class btStridingMeshInterface;
-
-///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
-ATTRIBUTE_ALIGNED16(class)
-btOptimizedBvh : public btQuantizedBvh
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
-protected:
-public:
- btOptimizedBvh();
-
- virtual ~btOptimizedBvh();
-
- void build(btStridingMeshInterface * triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
-
- void refit(btStridingMeshInterface * triangles, const btVector3& aabbMin, const btVector3& aabbMax);
-
- void refitPartial(btStridingMeshInterface * triangles, const btVector3& aabbMin, const btVector3& aabbMax);
-
- void updateBvhNodes(btStridingMeshInterface * meshInterface, int firstNode, int endNode, int index);
-
- /// Data buffer MUST be 16 byte aligned
- virtual bool serializeInPlace(void* o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
- {
- return btQuantizedBvh::serialize(o_alignedDataBuffer, i_dataBufferSize, i_swapEndian);
- }
-
- ///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
- static btOptimizedBvh* deSerializeInPlace(void* i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
-};
-
-#endif //BT_OPTIMIZED_BVH_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
deleted file mode 100644
index 521ecfc760..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#if defined(_WIN32) || defined(__i386__)
-#define BT_USE_SSE_IN_API
-#endif
-
-#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
-#include "btConvexPolyhedron.h"
-#include "LinearMath/btConvexHullComputer.h"
-#include <new>
-#include "LinearMath/btGeometryUtil.h"
-#include "LinearMath/btGrahamScan2dConvexHull.h"
-
-btPolyhedralConvexShape::btPolyhedralConvexShape() : btConvexInternalShape(),
- m_polyhedron(0)
-{
-}
-
-btPolyhedralConvexShape::~btPolyhedralConvexShape()
-{
- if (m_polyhedron)
- {
- m_polyhedron->~btConvexPolyhedron();
- btAlignedFree(m_polyhedron);
- }
-}
-
-void btPolyhedralConvexShape::setPolyhedralFeatures(btConvexPolyhedron& polyhedron)
-{
- if (m_polyhedron)
- {
- *m_polyhedron = polyhedron;
- }
- else
- {
- void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
- m_polyhedron = new (mem) btConvexPolyhedron(polyhedron);
- }
-}
-
-bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
-{
- if (m_polyhedron)
- {
- m_polyhedron->~btConvexPolyhedron();
- btAlignedFree(m_polyhedron);
- }
-
- void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron), 16);
- m_polyhedron = new (mem) btConvexPolyhedron;
-
- btAlignedObjectArray<btVector3> orgVertices;
-
- for (int i = 0; i < getNumVertices(); i++)
- {
- btVector3& newVertex = orgVertices.expand();
- getVertex(i, newVertex);
- }
-
- btConvexHullComputer conv;
-
- if (shiftVerticesByMargin)
- {
- btAlignedObjectArray<btVector3> planeEquations;
- btGeometryUtil::getPlaneEquationsFromVertices(orgVertices, planeEquations);
-
- btAlignedObjectArray<btVector3> shiftedPlaneEquations;
- for (int p = 0; p < planeEquations.size(); p++)
- {
- btVector3 plane = planeEquations[p];
- // btScalar margin = getMargin();
- plane[3] -= getMargin();
- shiftedPlaneEquations.push_back(plane);
- }
-
- btAlignedObjectArray<btVector3> tmpVertices;
-
- btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations, tmpVertices);
-
- conv.compute(&tmpVertices[0].getX(), sizeof(btVector3), tmpVertices.size(), 0.f, 0.f);
- }
- else
- {
- conv.compute(&orgVertices[0].getX(), sizeof(btVector3), orgVertices.size(), 0.f, 0.f);
- }
-
-#ifndef BT_RECONSTRUCT_FACES
-
- int numVertices = conv.vertices.size();
- m_polyhedron->m_vertices.resize(numVertices);
- for (int p = 0; p < numVertices; p++)
- {
- m_polyhedron->m_vertices[p] = conv.vertices[p];
- }
-
- int v0, v1;
- for (int j = 0; j < conv.faces.size(); j++)
- {
- btVector3 edges[3];
- int numEdges = 0;
- btFace combinedFace;
- const btConvexHullComputer::Edge* edge = &conv.edges[conv.faces[j]];
- v0 = edge->getSourceVertex();
- int prevVertex = v0;
- combinedFace.m_indices.push_back(v0);
- v1 = edge->getTargetVertex();
- while (v1 != v0)
- {
- btVector3 wa = conv.vertices[prevVertex];
- btVector3 wb = conv.vertices[v1];
- btVector3 newEdge = wb - wa;
- newEdge.normalize();
- if (numEdges < 2)
- edges[numEdges++] = newEdge;
-
- //face->addIndex(v1);
- combinedFace.m_indices.push_back(v1);
- edge = edge->getNextEdgeOfFace();
- prevVertex = v1;
- int v01 = edge->getSourceVertex();
- v1 = edge->getTargetVertex();
- }
-
- btAssert(combinedFace.m_indices.size() > 2);
-
- btVector3 faceNormal = edges[0].cross(edges[1]);
- faceNormal.normalize();
-
- btScalar planeEq = 1e30f;
-
- for (int v = 0; v < combinedFace.m_indices.size(); v++)
- {
- btScalar eq = m_polyhedron->m_vertices[combinedFace.m_indices[v]].dot(faceNormal);
- if (planeEq > eq)
- {
- planeEq = eq;
- }
- }
- combinedFace.m_plane[0] = faceNormal.getX();
- combinedFace.m_plane[1] = faceNormal.getY();
- combinedFace.m_plane[2] = faceNormal.getZ();
- combinedFace.m_plane[3] = -planeEq;
-
- m_polyhedron->m_faces.push_back(combinedFace);
- }
-
-#else //BT_RECONSTRUCT_FACES
-
- btAlignedObjectArray<btVector3> faceNormals;
- int numFaces = conv.faces.size();
- faceNormals.resize(numFaces);
- btConvexHullComputer* convexUtil = &conv;
-
- btAlignedObjectArray<btFace> tmpFaces;
- tmpFaces.resize(numFaces);
-
- int numVertices = convexUtil->vertices.size();
- m_polyhedron->m_vertices.resize(numVertices);
- for (int p = 0; p < numVertices; p++)
- {
- m_polyhedron->m_vertices[p] = convexUtil->vertices[p];
- }
-
- for (int i = 0; i < numFaces; i++)
- {
- int face = convexUtil->faces[i];
- //printf("face=%d\n",face);
- const btConvexHullComputer::Edge* firstEdge = &convexUtil->edges[face];
- const btConvexHullComputer::Edge* edge = firstEdge;
-
- btVector3 edges[3];
- int numEdges = 0;
- //compute face normals
-
- do
- {
- int src = edge->getSourceVertex();
- tmpFaces[i].m_indices.push_back(src);
- int targ = edge->getTargetVertex();
- btVector3 wa = convexUtil->vertices[src];
-
- btVector3 wb = convexUtil->vertices[targ];
- btVector3 newEdge = wb - wa;
- newEdge.normalize();
- if (numEdges < 2)
- edges[numEdges++] = newEdge;
-
- edge = edge->getNextEdgeOfFace();
- } while (edge != firstEdge);
-
- btScalar planeEq = 1e30f;
-
- if (numEdges == 2)
- {
- faceNormals[i] = edges[0].cross(edges[1]);
- faceNormals[i].normalize();
- tmpFaces[i].m_plane[0] = faceNormals[i].getX();
- tmpFaces[i].m_plane[1] = faceNormals[i].getY();
- tmpFaces[i].m_plane[2] = faceNormals[i].getZ();
- tmpFaces[i].m_plane[3] = planeEq;
- }
- else
- {
- btAssert(0); //degenerate?
- faceNormals[i].setZero();
- }
-
- for (int v = 0; v < tmpFaces[i].m_indices.size(); v++)
- {
- btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]);
- if (planeEq > eq)
- {
- planeEq = eq;
- }
- }
- tmpFaces[i].m_plane[3] = -planeEq;
- }
-
- //merge coplanar faces and copy them to m_polyhedron
-
- btScalar faceWeldThreshold = 0.999f;
- btAlignedObjectArray<int> todoFaces;
- for (int i = 0; i < tmpFaces.size(); i++)
- todoFaces.push_back(i);
-
- while (todoFaces.size())
- {
- btAlignedObjectArray<int> coplanarFaceGroup;
- int refFace = todoFaces[todoFaces.size() - 1];
-
- coplanarFaceGroup.push_back(refFace);
- btFace& faceA = tmpFaces[refFace];
- todoFaces.pop_back();
-
- btVector3 faceNormalA(faceA.m_plane[0], faceA.m_plane[1], faceA.m_plane[2]);
- for (int j = todoFaces.size() - 1; j >= 0; j--)
- {
- int i = todoFaces[j];
- btFace& faceB = tmpFaces[i];
- btVector3 faceNormalB(faceB.m_plane[0], faceB.m_plane[1], faceB.m_plane[2]);
- if (faceNormalA.dot(faceNormalB) > faceWeldThreshold)
- {
- coplanarFaceGroup.push_back(i);
- todoFaces.remove(i);
- }
- }
-
- bool did_merge = false;
- if (coplanarFaceGroup.size() > 1)
- {
- //do the merge: use Graham Scan 2d convex hull
-
- btAlignedObjectArray<GrahamVector3> orgpoints;
- btVector3 averageFaceNormal(0, 0, 0);
-
- for (int i = 0; i < coplanarFaceGroup.size(); i++)
- {
- // m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
-
- btFace& face = tmpFaces[coplanarFaceGroup[i]];
- btVector3 faceNormal(face.m_plane[0], face.m_plane[1], face.m_plane[2]);
- averageFaceNormal += faceNormal;
- for (int f = 0; f < face.m_indices.size(); f++)
- {
- int orgIndex = face.m_indices[f];
- btVector3 pt = m_polyhedron->m_vertices[orgIndex];
-
- bool found = false;
-
- for (int i = 0; i < orgpoints.size(); i++)
- {
- //if ((orgpoints[i].m_orgIndex == orgIndex) || ((rotatedPt-orgpoints[i]).length2()<0.0001))
- if (orgpoints[i].m_orgIndex == orgIndex)
- {
- found = true;
- break;
- }
- }
- if (!found)
- orgpoints.push_back(GrahamVector3(pt, orgIndex));
- }
- }
-
- btFace combinedFace;
- for (int i = 0; i < 4; i++)
- combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
-
- btAlignedObjectArray<GrahamVector3> hull;
-
- averageFaceNormal.normalize();
- GrahamScanConvexHull2D(orgpoints, hull, averageFaceNormal);
-
- for (int i = 0; i < hull.size(); i++)
- {
- combinedFace.m_indices.push_back(hull[i].m_orgIndex);
- for (int k = 0; k < orgpoints.size(); k++)
- {
- if (orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
- {
- orgpoints[k].m_orgIndex = -1; // invalidate...
- break;
- }
- }
- }
-
- // are there rejected vertices?
- bool reject_merge = false;
-
- for (int i = 0; i < orgpoints.size(); i++)
- {
- if (orgpoints[i].m_orgIndex == -1)
- continue; // this is in the hull...
- // this vertex is rejected -- is anybody else using this vertex?
- for (int j = 0; j < tmpFaces.size(); j++)
- {
- btFace& face = tmpFaces[j];
- // is this a face of the current coplanar group?
- bool is_in_current_group = false;
- for (int k = 0; k < coplanarFaceGroup.size(); k++)
- {
- if (coplanarFaceGroup[k] == j)
- {
- is_in_current_group = true;
- break;
- }
- }
- if (is_in_current_group) // ignore this face...
- continue;
- // does this face use this rejected vertex?
- for (int v = 0; v < face.m_indices.size(); v++)
- {
- if (face.m_indices[v] == orgpoints[i].m_orgIndex)
- {
- // this rejected vertex is used in another face -- reject merge
- reject_merge = true;
- break;
- }
- }
- if (reject_merge)
- break;
- }
- if (reject_merge)
- break;
- }
-
- if (!reject_merge)
- {
- // do this merge!
- did_merge = true;
- m_polyhedron->m_faces.push_back(combinedFace);
- }
- }
- if (!did_merge)
- {
- for (int i = 0; i < coplanarFaceGroup.size(); i++)
- {
- btFace face = tmpFaces[coplanarFaceGroup[i]];
- m_polyhedron->m_faces.push_back(face);
- }
- }
- }
-
-#endif //BT_RECONSTRUCT_FACES
-
- m_polyhedron->initialize();
-
- return true;
-}
-
-#ifndef MIN
-#define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b))
-#endif
-
-btVector3 btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
-{
- btVector3 supVec(0, 0, 0);
-#ifndef __SPU__
- int i;
- btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
-
- btVector3 vec = vec0;
- btScalar lenSqr = vec.length2();
- if (lenSqr < btScalar(0.0001))
- {
- vec.setValue(1, 0, 0);
- }
- else
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- vec *= rlen;
- }
-
- btVector3 vtx;
- btScalar newDot;
-
- for (int k = 0; k < getNumVertices(); k += 128)
- {
- btVector3 temp[128];
- int inner_count = MIN(getNumVertices() - k, 128);
- for (i = 0; i < inner_count; i++)
- getVertex(i, temp[i]);
- i = (int)vec.maxDot(temp, inner_count, newDot);
- if (newDot > maxDot)
- {
- maxDot = newDot;
- supVec = temp[i];
- }
- }
-
-#endif //__SPU__
- return supVec;
-}
-
-void btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
-#ifndef __SPU__
- int i;
-
- btVector3 vtx;
- btScalar newDot;
-
- for (i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
- }
-
- for (int j = 0; j < numVectors; j++)
- {
- const btVector3& vec = vectors[j];
-
- for (int k = 0; k < getNumVertices(); k += 128)
- {
- btVector3 temp[128];
- int inner_count = MIN(getNumVertices() - k, 128);
- for (i = 0; i < inner_count; i++)
- getVertex(i, temp[i]);
- i = (int)vec.maxDot(temp, inner_count, newDot);
- if (newDot > supportVerticesOut[j][3])
- {
- supportVerticesOut[j] = temp[i];
- supportVerticesOut[j][3] = newDot;
- }
- }
- }
-
-#endif //__SPU__
-}
-
-void btPolyhedralConvexShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
-#ifndef __SPU__
- //not yet, return box inertia
-
- btScalar margin = getMargin();
-
- btTransform ident;
- ident.setIdentity();
- btVector3 aabbMin, aabbMax;
- getAabb(ident, aabbMin, aabbMax);
- btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
-
- btScalar lx = btScalar(2.) * (halfExtents.x() + margin);
- btScalar ly = btScalar(2.) * (halfExtents.y() + margin);
- btScalar lz = btScalar(2.) * (halfExtents.z() + margin);
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-#endif //__SPU__
-}
-
-void btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
-{
- btConvexInternalShape::setLocalScaling(scaling);
- recalcLocalAabb();
-}
-
-btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
- : btPolyhedralConvexShape(),
- m_localAabbMin(1, 1, 1),
- m_localAabbMax(-1, -1, -1),
- m_isLocalAabbValid(false)
-{
-}
-
-void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- getNonvirtualAabb(trans, aabbMin, aabbMax, getMargin());
-}
-
-void btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
-{
- m_isLocalAabbValid = true;
-
-#if 1
- static const btVector3 _directions[] =
- {
- btVector3(1., 0., 0.),
- btVector3(0., 1., 0.),
- btVector3(0., 0., 1.),
- btVector3(-1., 0., 0.),
- btVector3(0., -1., 0.),
- btVector3(0., 0., -1.)};
-
- btVector3 _supporting[] =
- {
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.)};
-
- batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- for (int i = 0; i < 3; ++i)
- {
- m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
- m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
- }
-
-#else
-
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
- btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i];
- vec[i] = btScalar(-1.);
- tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i];
- }
-#endif
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
deleted file mode 100644
index b3ffab7a23..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_POLYHEDRAL_CONVEX_SHAPE_H
-#define BT_POLYHEDRAL_CONVEX_SHAPE_H
-
-#include "LinearMath/btMatrix3x3.h"
-#include "btConvexInternalShape.h"
-class btConvexPolyhedron;
-
-///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
-ATTRIBUTE_ALIGNED16(class)
-btPolyhedralConvexShape : public btConvexInternalShape
-{
-protected:
- btConvexPolyhedron* m_polyhedron;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btPolyhedralConvexShape();
-
- virtual ~btPolyhedralConvexShape();
-
- ///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
- ///experimental/work-in-progress
- virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin = 0);
-
- virtual void setPolyhedralFeatures(btConvexPolyhedron & polyhedron);
-
- const btConvexPolyhedron* getConvexPolyhedron() const
- {
- return m_polyhedron;
- }
-
- //brute force implementations
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual int getNumVertices() const = 0;
- virtual int getNumEdges() const = 0;
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const = 0;
- virtual void getVertex(int i, btVector3& vtx) const = 0;
- virtual int getNumPlanes() const = 0;
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const = 0;
- // virtual int getIndex(int i) const = 0 ;
-
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const = 0;
-};
-
-///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
-class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
-{
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- bool m_isLocalAabbValid;
-
-protected:
- void setCachedLocalAabb(const btVector3& aabbMin, const btVector3& aabbMax)
- {
- m_isLocalAabbValid = true;
- m_localAabbMin = aabbMin;
- m_localAabbMax = aabbMax;
- }
-
- inline void getCachedLocalAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- btAssert(m_isLocalAabbValid);
- aabbMin = m_localAabbMin;
- aabbMax = m_localAabbMax;
- }
-
-protected:
- btPolyhedralConvexAabbCachingShape();
-
-public:
- inline void getNonvirtualAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax, btScalar margin) const
- {
- //lazy evaluation of local aabb
- btAssert(m_isLocalAabbValid);
- btTransformAabb(m_localAabbMin, m_localAabbMax, margin, trans, aabbMin, aabbMax);
- }
-
- virtual void setLocalScaling(const btVector3& scaling);
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- void recalcLocalAabb();
-};
-
-#endif //BT_POLYHEDRAL_CONVEX_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
deleted file mode 100644
index f427319974..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btScaledBvhTriangleMeshShape.h"
-
-btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape, const btVector3& localScaling)
- : m_localScaling(localScaling), m_bvhTriMeshShape(childShape)
-{
- m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
-}
-
-btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
-{
-}
-
-class btScaledTriangleCallback : public btTriangleCallback
-{
- btTriangleCallback* m_originalCallback;
-
- btVector3 m_localScaling;
-
-public:
- btScaledTriangleCallback(btTriangleCallback* originalCallback, const btVector3& localScaling)
- : m_originalCallback(originalCallback),
- m_localScaling(localScaling)
- {
- }
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- btVector3 newTriangle[3];
- newTriangle[0] = triangle[0] * m_localScaling;
- newTriangle[1] = triangle[1] * m_localScaling;
- newTriangle[2] = triangle[2] * m_localScaling;
- m_originalCallback->processTriangle(&newTriangle[0], partId, triangleIndex);
- }
-};
-
-void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- btScaledTriangleCallback scaledCallback(callback, m_localScaling);
-
- btVector3 invLocalScaling(1.f / m_localScaling.getX(), 1.f / m_localScaling.getY(), 1.f / m_localScaling.getZ());
- btVector3 scaledAabbMin, scaledAabbMax;
-
- ///support negative scaling
- scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
- scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
- scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
- scaledAabbMin[3] = 0.f;
-
- scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
- scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
- scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
- scaledAabbMax[3] = 0.f;
-
- m_bvhTriMeshShape->processAllTriangles(&scaledCallback, scaledAabbMin, scaledAabbMax);
-}
-
-void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
- btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
-
- btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
- btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
-
- localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
- localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
- localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
- localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
- localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
- localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
-
- btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
- btScalar margin = m_bvhTriMeshShape->getMargin();
- localHalfExtents += btVector3(margin, margin, margin);
- btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
-
- btMatrix3x3 abs_b = trans.getBasis().absolute();
-
- btVector3 center = trans(localCenter);
-
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
-}
-
-void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling;
-}
-
-const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
-{
- return m_localScaling;
-}
-
-void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- ///don't make this a movable object!
- // btAssert(0);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
deleted file mode 100644
index 4d6feb61af..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
-#define BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
-
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-
-///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
-///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
-ATTRIBUTE_ALIGNED16(class)
-btScaledBvhTriangleMeshShape : public btConcaveShape
-{
- btVector3 m_localScaling;
-
- btBvhTriangleMeshShape* m_bvhTriMeshShape;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape * childShape, const btVector3& localScaling);
-
- virtual ~btScaledBvhTriangleMeshShape();
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- btBvhTriangleMeshShape* getChildShape()
- {
- return m_bvhTriMeshShape;
- }
-
- const btBvhTriangleMeshShape* getChildShape() const
- {
- return m_bvhTriMeshShape;
- }
-
- //debugging
- virtual const char* getName() const { return "SCALEDBVHTRIANGLEMESH"; }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btScaledTriangleMeshShapeData
-{
- btTriangleMeshShapeData m_trimeshShapeData;
-
- btVector3FloatData m_localScaling;
-};
-
-SIMD_FORCE_INLINE int btScaledBvhTriangleMeshShape::calculateSerializeBufferSize() const
-{
- return sizeof(btScaledTriangleMeshShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btScaledBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btScaledTriangleMeshShapeData* scaledMeshData = (btScaledTriangleMeshShapeData*)dataBuffer;
- m_bvhTriMeshShape->serialize(&scaledMeshData->m_trimeshShapeData, serializer);
- scaledMeshData->m_trimeshShapeData.m_collisionShapeData.m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
- m_localScaling.serializeFloat(scaledMeshData->m_localScaling);
- return "btScaledTriangleMeshShapeData";
-}
-
-#endif //BT_SCALED_BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
deleted file mode 100644
index 23c95ad3ff..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#include "btSdfCollisionShape.h"
-#include "btMiniSDF.h"
-#include "LinearMath/btAabbUtil2.h"
-
-ATTRIBUTE_ALIGNED16(struct)
-btSdfCollisionShapeInternalData
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 m_localScaling;
- btScalar m_margin;
- btMiniSDF m_sdf;
-
- btSdfCollisionShapeInternalData()
- : m_localScaling(1, 1, 1),
- m_margin(0)
- {
- }
-};
-
-bool btSdfCollisionShape::initializeSDF(const char* sdfData, int sizeInBytes)
-{
- bool valid = m_data->m_sdf.load(sdfData, sizeInBytes);
- return valid;
-}
-btSdfCollisionShape::btSdfCollisionShape()
-{
- m_shapeType = SDF_SHAPE_PROXYTYPE;
- m_data = new btSdfCollisionShapeInternalData();
-
- //"E:/develop/bullet3/data/toys/ground_hole64_64_8.cdf");//ground_cube.cdf");
- /*unsigned int field_id=0;
- Eigen::Vector3d x (1,10,1);
- Eigen::Vector3d gradient;
- double dist = m_data->m_sdf.interpolate(field_id, x, &gradient);
- printf("dist=%g\n", dist);
- */
-}
-btSdfCollisionShape::~btSdfCollisionShape()
-{
- delete m_data;
-}
-
-void btSdfCollisionShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btAssert(m_data->m_sdf.isValid());
- btVector3 localAabbMin = m_data->m_sdf.m_domain.m_min;
- btVector3 localAabbMax = m_data->m_sdf.m_domain.m_max;
- btScalar margin(0);
- btTransformAabb(localAabbMin, localAabbMax, margin, t, aabbMin, aabbMax);
-}
-
-void btSdfCollisionShape::setLocalScaling(const btVector3& scaling)
-{
- m_data->m_localScaling = scaling;
-}
-const btVector3& btSdfCollisionShape::getLocalScaling() const
-{
- return m_data->m_localScaling;
-}
-void btSdfCollisionShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- inertia.setValue(0, 0, 0);
-}
-const char* btSdfCollisionShape::getName() const
-{
- return "btSdfCollisionShape";
-}
-void btSdfCollisionShape::setMargin(btScalar margin)
-{
- m_data->m_margin = margin;
-}
-btScalar btSdfCollisionShape::getMargin() const
-{
- return m_data->m_margin;
-}
-
-void btSdfCollisionShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- //not yet
-}
-
-bool btSdfCollisionShape::queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal)
-{
- int field = 0;
- btVector3 grad;
- double dist;
- bool hasResult = m_data->m_sdf.interpolate(field, dist, ptInSDF, &grad);
- if (hasResult)
- {
- normal.setValue(grad[0], grad[1], grad[2]);
- distOut = dist;
- }
- return hasResult;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h
deleted file mode 100644
index 3989d6245e..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSdfCollisionShape.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef BT_SDF_COLLISION_SHAPE_H
-#define BT_SDF_COLLISION_SHAPE_H
-
-#include "btConcaveShape.h"
-
-class btSdfCollisionShape : public btConcaveShape
-{
- struct btSdfCollisionShapeInternalData* m_data;
-
-public:
- btSdfCollisionShape();
- virtual ~btSdfCollisionShape();
-
- bool initializeSDF(const char* sdfData, int sizeInBytes);
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
- virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
- virtual const char* getName() const;
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
-
- virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- bool queryPoint(const btVector3& ptInSDF, btScalar& distOut, btVector3& normal);
-};
-
-#endif //BT_SDF_COLLISION_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
deleted file mode 100644
index a2c490faf9..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//btShapeHull was implemented by John McCutchan.
-
-#include "btShapeHull.h"
-#include "LinearMath/btConvexHull.h"
-
-#define NUM_UNITSPHERE_POINTS 42
-#define NUM_UNITSPHERE_POINTS_HIGHRES 256
-
-btShapeHull::btShapeHull(const btConvexShape* shape)
-{
- m_shape = shape;
- m_vertices.clear();
- m_indices.clear();
- m_numIndices = 0;
-}
-
-btShapeHull::~btShapeHull()
-{
- m_indices.clear();
- m_vertices.clear();
-}
-
-bool btShapeHull::buildHull(btScalar /*margin*/, int highres)
-{
-
- int numSampleDirections = highres ? NUM_UNITSPHERE_POINTS_HIGHRES : NUM_UNITSPHERE_POINTS;
- btVector3 supportPoints[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- int i;
- for (i = 0; i < numSampleDirections; i++)
- {
- supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints(highres)[i]);
- }
-
- int numPDA = m_shape->getNumPreferredPenetrationDirections();
- if (numPDA)
- {
- for (int s = 0; s < numPDA; s++)
- {
- btVector3 norm;
- m_shape->getPreferredPenetrationDirection(s, norm);
- supportPoints[i++] = m_shape->localGetSupportingVertex(norm);
- numSampleDirections++;
- }
- }
- HullDesc hd;
- hd.mFlags = QF_TRIANGLES;
- hd.mVcount = static_cast<unsigned int>(numSampleDirections);
-
-#ifdef BT_USE_DOUBLE_PRECISION
- hd.mVertices = &supportPoints[0];
- hd.mVertexStride = sizeof(btVector3);
-#else
- hd.mVertices = &supportPoints[0];
- hd.mVertexStride = sizeof(btVector3);
-#endif
-
- HullLibrary hl;
- HullResult hr;
- if (hl.CreateConvexHull(hd, hr) == QE_FAIL)
- {
- return false;
- }
-
- m_vertices.resize(static_cast<int>(hr.mNumOutputVertices));
-
- for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
- {
- m_vertices[i] = hr.m_OutputVertices[i];
- }
- m_numIndices = hr.mNumIndices;
- m_indices.resize(static_cast<int>(m_numIndices));
- for (i = 0; i < static_cast<int>(m_numIndices); i++)
- {
- m_indices[i] = hr.m_Indices[i];
- }
-
- // free temporary hull result that we just copied
- hl.ReleaseResult(hr);
-
- return true;
-}
-
-int btShapeHull::numTriangles() const
-{
- return static_cast<int>(m_numIndices / 3);
-}
-
-int btShapeHull::numVertices() const
-{
- return m_vertices.size();
-}
-
-int btShapeHull::numIndices() const
-{
- return static_cast<int>(m_numIndices);
-}
-
-btVector3* btShapeHull::getUnitSpherePoints(int highres)
-{
- static btVector3 sUnitSpherePointsHighres[NUM_UNITSPHERE_POINTS_HIGHRES + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
- {
- btVector3(btScalar(0.997604), btScalar(0.067004), btScalar(0.017144)),
- btVector3(btScalar(0.984139), btScalar(-0.086784), btScalar(-0.154427)),
- btVector3(btScalar(0.971065), btScalar(0.124164), btScalar(-0.203224)),
- btVector3(btScalar(0.955844), btScalar(0.291173), btScalar(-0.037704)),
- btVector3(btScalar(0.957405), btScalar(0.212238), btScalar(0.195157)),
- btVector3(btScalar(0.971650), btScalar(-0.012709), btScalar(0.235561)),
- btVector3(btScalar(0.984920), btScalar(-0.161831), btScalar(0.059695)),
- btVector3(btScalar(0.946673), btScalar(-0.299288), btScalar(-0.117536)),
- btVector3(btScalar(0.922670), btScalar(-0.219186), btScalar(-0.317019)),
- btVector3(btScalar(0.928134), btScalar(-0.007265), btScalar(-0.371867)),
- btVector3(btScalar(0.875642), btScalar(0.198434), btScalar(-0.439988)),
- btVector3(btScalar(0.908035), btScalar(0.325975), btScalar(-0.262562)),
- btVector3(btScalar(0.864519), btScalar(0.488706), btScalar(-0.116755)),
- btVector3(btScalar(0.893009), btScalar(0.428046), btScalar(0.137185)),
- btVector3(btScalar(0.857494), btScalar(0.362137), btScalar(0.364776)),
- btVector3(btScalar(0.900815), btScalar(0.132524), btScalar(0.412987)),
- btVector3(btScalar(0.934964), btScalar(-0.241739), btScalar(0.259179)),
- btVector3(btScalar(0.894570), btScalar(-0.103504), btScalar(0.434263)),
- btVector3(btScalar(0.922085), btScalar(-0.376668), btScalar(0.086241)),
- btVector3(btScalar(0.862177), btScalar(-0.499154), btScalar(-0.085330)),
- btVector3(btScalar(0.861982), btScalar(-0.420218), btScalar(-0.282861)),
- btVector3(btScalar(0.818076), btScalar(-0.328256), btScalar(-0.471804)),
- btVector3(btScalar(0.762657), btScalar(-0.179329), btScalar(-0.621124)),
- btVector3(btScalar(0.826857), btScalar(0.019760), btScalar(-0.561786)),
- btVector3(btScalar(0.731434), btScalar(0.206599), btScalar(-0.649817)),
- btVector3(btScalar(0.769486), btScalar(0.379052), btScalar(-0.513770)),
- btVector3(btScalar(0.796806), btScalar(0.507176), btScalar(-0.328145)),
- btVector3(btScalar(0.679722), btScalar(0.684101), btScalar(-0.264123)),
- btVector3(btScalar(0.786854), btScalar(0.614886), btScalar(0.050912)),
- btVector3(btScalar(0.769486), btScalar(0.571141), btScalar(0.285139)),
- btVector3(btScalar(0.707432), btScalar(0.492789), btScalar(0.506288)),
- btVector3(btScalar(0.774560), btScalar(0.268037), btScalar(0.572652)),
- btVector3(btScalar(0.796220), btScalar(0.031230), btScalar(0.604077)),
- btVector3(btScalar(0.837395), btScalar(-0.320285), btScalar(0.442461)),
- btVector3(btScalar(0.848127), btScalar(-0.450548), btScalar(0.278307)),
- btVector3(btScalar(0.775536), btScalar(-0.206354), btScalar(0.596465)),
- btVector3(btScalar(0.816320), btScalar(-0.567007), btScalar(0.109469)),
- btVector3(btScalar(0.741191), btScalar(-0.668690), btScalar(-0.056832)),
- btVector3(btScalar(0.755632), btScalar(-0.602975), btScalar(-0.254949)),
- btVector3(btScalar(0.720311), btScalar(-0.521318), btScalar(-0.457165)),
- btVector3(btScalar(0.670746), btScalar(-0.386583), btScalar(-0.632835)),
- btVector3(btScalar(0.587031), btScalar(-0.219769), btScalar(-0.778836)),
- btVector3(btScalar(0.676015), btScalar(-0.003182), btScalar(-0.736676)),
- btVector3(btScalar(0.566932), btScalar(0.186963), btScalar(-0.802064)),
- btVector3(btScalar(0.618254), btScalar(0.398105), btScalar(-0.677533)),
- btVector3(btScalar(0.653964), btScalar(0.575224), btScalar(-0.490933)),
- btVector3(btScalar(0.525367), btScalar(0.743205), btScalar(-0.414028)),
- btVector3(btScalar(0.506439), btScalar(0.836528), btScalar(-0.208885)),
- btVector3(btScalar(0.651427), btScalar(0.756426), btScalar(-0.056247)),
- btVector3(btScalar(0.641670), btScalar(0.745149), btScalar(0.180908)),
- btVector3(btScalar(0.602643), btScalar(0.687211), btScalar(0.405180)),
- btVector3(btScalar(0.516586), btScalar(0.596999), btScalar(0.613447)),
- btVector3(btScalar(0.602252), btScalar(0.387801), btScalar(0.697573)),
- btVector3(btScalar(0.646549), btScalar(0.153911), btScalar(0.746956)),
- btVector3(btScalar(0.650842), btScalar(-0.087756), btScalar(0.753983)),
- btVector3(btScalar(0.740411), btScalar(-0.497404), btScalar(0.451830)),
- btVector3(btScalar(0.726946), btScalar(-0.619890), btScalar(0.295093)),
- btVector3(btScalar(0.637768), btScalar(-0.313092), btScalar(0.703624)),
- btVector3(btScalar(0.678942), btScalar(-0.722934), btScalar(0.126645)),
- btVector3(btScalar(0.489072), btScalar(-0.867195), btScalar(-0.092942)),
- btVector3(btScalar(0.622742), btScalar(-0.757541), btScalar(-0.194636)),
- btVector3(btScalar(0.596788), btScalar(-0.693576), btScalar(-0.403098)),
- btVector3(btScalar(0.550150), btScalar(-0.582172), btScalar(-0.598287)),
- btVector3(btScalar(0.474436), btScalar(-0.429745), btScalar(-0.768101)),
- btVector3(btScalar(0.372574), btScalar(-0.246016), btScalar(-0.894583)),
- btVector3(btScalar(0.480095), btScalar(-0.026513), btScalar(-0.876626)),
- btVector3(btScalar(0.352474), btScalar(0.177242), btScalar(-0.918787)),
- btVector3(btScalar(0.441848), btScalar(0.374386), btScalar(-0.814946)),
- btVector3(btScalar(0.492389), btScalar(0.582223), btScalar(-0.646693)),
- btVector3(btScalar(0.343498), btScalar(0.866080), btScalar(-0.362693)),
- btVector3(btScalar(0.362036), btScalar(0.745149), btScalar(-0.559639)),
- btVector3(btScalar(0.334131), btScalar(0.937044), btScalar(-0.099774)),
- btVector3(btScalar(0.486925), btScalar(0.871718), btScalar(0.052473)),
- btVector3(btScalar(0.452776), btScalar(0.845665), btScalar(0.281820)),
- btVector3(btScalar(0.399503), btScalar(0.771785), btScalar(0.494576)),
- btVector3(btScalar(0.296469), btScalar(0.673018), btScalar(0.677469)),
- btVector3(btScalar(0.392088), btScalar(0.479179), btScalar(0.785213)),
- btVector3(btScalar(0.452190), btScalar(0.252094), btScalar(0.855286)),
- btVector3(btScalar(0.478339), btScalar(0.013149), btScalar(0.877928)),
- btVector3(btScalar(0.481656), btScalar(-0.219380), btScalar(0.848259)),
- btVector3(btScalar(0.615327), btScalar(-0.494293), btScalar(0.613837)),
- btVector3(btScalar(0.594642), btScalar(-0.650414), btScalar(0.472325)),
- btVector3(btScalar(0.562249), btScalar(-0.771345), btScalar(0.297631)),
- btVector3(btScalar(0.467411), btScalar(-0.437133), btScalar(0.768231)),
- btVector3(btScalar(0.519513), btScalar(-0.847947), btScalar(0.103808)),
- btVector3(btScalar(0.297640), btScalar(-0.938159), btScalar(-0.176288)),
- btVector3(btScalar(0.446727), btScalar(-0.838615), btScalar(-0.311359)),
- btVector3(btScalar(0.331790), btScalar(-0.942437), btScalar(0.040762)),
- btVector3(btScalar(0.413358), btScalar(-0.748403), btScalar(-0.518259)),
- btVector3(btScalar(0.347596), btScalar(-0.621640), btScalar(-0.701737)),
- btVector3(btScalar(0.249831), btScalar(-0.456186), btScalar(-0.853984)),
- btVector3(btScalar(0.131772), btScalar(-0.262931), btScalar(-0.955678)),
- btVector3(btScalar(0.247099), btScalar(-0.042261), btScalar(-0.967975)),
- btVector3(btScalar(0.113624), btScalar(0.165965), btScalar(-0.979491)),
- btVector3(btScalar(0.217438), btScalar(0.374580), btScalar(-0.901220)),
- btVector3(btScalar(0.307983), btScalar(0.554615), btScalar(-0.772786)),
- btVector3(btScalar(0.166702), btScalar(0.953181), btScalar(-0.252021)),
- btVector3(btScalar(0.172751), btScalar(0.844499), btScalar(-0.506743)),
- btVector3(btScalar(0.177630), btScalar(0.711125), btScalar(-0.679876)),
- btVector3(btScalar(0.120064), btScalar(0.992260), btScalar(-0.030482)),
- btVector3(btScalar(0.289640), btScalar(0.949098), btScalar(0.122546)),
- btVector3(btScalar(0.239879), btScalar(0.909047), btScalar(0.340377)),
- btVector3(btScalar(0.181142), btScalar(0.821363), btScalar(0.540641)),
- btVector3(btScalar(0.066986), btScalar(0.719097), btScalar(0.691327)),
- btVector3(btScalar(0.156750), btScalar(0.545478), btScalar(0.823079)),
- btVector3(btScalar(0.236172), btScalar(0.342306), btScalar(0.909353)),
- btVector3(btScalar(0.277541), btScalar(0.112693), btScalar(0.953856)),
- btVector3(btScalar(0.295299), btScalar(-0.121974), btScalar(0.947415)),
- btVector3(btScalar(0.287883), btScalar(-0.349254), btScalar(0.891591)),
- btVector3(btScalar(0.437165), btScalar(-0.634666), btScalar(0.636869)),
- btVector3(btScalar(0.407113), btScalar(-0.784954), btScalar(0.466664)),
- btVector3(btScalar(0.375111), btScalar(-0.888193), btScalar(0.264839)),
- btVector3(btScalar(0.275394), btScalar(-0.560591), btScalar(0.780723)),
- btVector3(btScalar(0.122015), btScalar(-0.992209), btScalar(-0.024821)),
- btVector3(btScalar(0.087866), btScalar(-0.966156), btScalar(-0.241676)),
- btVector3(btScalar(0.239489), btScalar(-0.885665), btScalar(-0.397437)),
- btVector3(btScalar(0.167287), btScalar(-0.965184), btScalar(0.200817)),
- btVector3(btScalar(0.201632), btScalar(-0.776789), btScalar(-0.596335)),
- btVector3(btScalar(0.122015), btScalar(-0.637971), btScalar(-0.760098)),
- btVector3(btScalar(0.008054), btScalar(-0.464741), btScalar(-0.885214)),
- btVector3(btScalar(-0.116054), btScalar(-0.271096), btScalar(-0.955482)),
- btVector3(btScalar(-0.000727), btScalar(-0.056065), btScalar(-0.998424)),
- btVector3(btScalar(-0.134007), btScalar(0.152939), btScalar(-0.978905)),
- btVector3(btScalar(-0.025900), btScalar(0.366026), btScalar(-0.930108)),
- btVector3(btScalar(0.081231), btScalar(0.557337), btScalar(-0.826072)),
- btVector3(btScalar(-0.002874), btScalar(0.917213), btScalar(-0.398023)),
- btVector3(btScalar(-0.050683), btScalar(0.981761), btScalar(-0.182534)),
- btVector3(btScalar(-0.040536), btScalar(0.710153), btScalar(-0.702713)),
- btVector3(btScalar(-0.139081), btScalar(0.827973), btScalar(-0.543048)),
- btVector3(btScalar(-0.101029), btScalar(0.994010), btScalar(0.041152)),
- btVector3(btScalar(0.069328), btScalar(0.978067), btScalar(0.196133)),
- btVector3(btScalar(0.023860), btScalar(0.911380), btScalar(0.410645)),
- btVector3(btScalar(-0.153521), btScalar(0.736789), btScalar(0.658145)),
- btVector3(btScalar(-0.070002), btScalar(0.591750), btScalar(0.802780)),
- btVector3(btScalar(0.002590), btScalar(0.312948), btScalar(0.949562)),
- btVector3(btScalar(0.090988), btScalar(-0.020680), btScalar(0.995627)),
- btVector3(btScalar(0.088842), btScalar(-0.250099), btScalar(0.964006)),
- btVector3(btScalar(0.083378), btScalar(-0.470185), btScalar(0.878318)),
- btVector3(btScalar(0.240074), btScalar(-0.749764), btScalar(0.616374)),
- btVector3(btScalar(0.210803), btScalar(-0.885860), btScalar(0.412987)),
- btVector3(btScalar(0.077524), btScalar(-0.660524), btScalar(0.746565)),
- btVector3(btScalar(-0.096736), btScalar(-0.990070), btScalar(-0.100945)),
- btVector3(btScalar(-0.052634), btScalar(-0.990264), btScalar(0.127426)),
- btVector3(btScalar(-0.106102), btScalar(-0.938354), btScalar(-0.328340)),
- btVector3(btScalar(0.013323), btScalar(-0.863112), btScalar(-0.504596)),
- btVector3(btScalar(-0.002093), btScalar(-0.936993), btScalar(0.349161)),
- btVector3(btScalar(-0.106297), btScalar(-0.636610), btScalar(-0.763612)),
- btVector3(btScalar(-0.229430), btScalar(-0.463769), btScalar(-0.855546)),
- btVector3(btScalar(-0.245236), btScalar(-0.066175), btScalar(-0.966999)),
- btVector3(btScalar(-0.351587), btScalar(-0.270513), btScalar(-0.896145)),
- btVector3(btScalar(-0.370906), btScalar(0.133108), btScalar(-0.918982)),
- btVector3(btScalar(-0.264360), btScalar(0.346000), btScalar(-0.900049)),
- btVector3(btScalar(-0.151375), btScalar(0.543728), btScalar(-0.825291)),
- btVector3(btScalar(-0.218697), btScalar(0.912741), btScalar(-0.344346)),
- btVector3(btScalar(-0.274507), btScalar(0.953764), btScalar(-0.121635)),
- btVector3(btScalar(-0.259677), btScalar(0.692266), btScalar(-0.673044)),
- btVector3(btScalar(-0.350416), btScalar(0.798810), btScalar(-0.488786)),
- btVector3(btScalar(-0.320170), btScalar(0.941127), btScalar(0.108297)),
- btVector3(btScalar(-0.147667), btScalar(0.952792), btScalar(0.265034)),
- btVector3(btScalar(-0.188061), btScalar(0.860636), btScalar(0.472910)),
- btVector3(btScalar(-0.370906), btScalar(0.739900), btScalar(0.560941)),
- btVector3(btScalar(-0.297143), btScalar(0.585334), btScalar(0.754178)),
- btVector3(btScalar(-0.189622), btScalar(0.428241), btScalar(0.883393)),
- btVector3(btScalar(-0.091272), btScalar(0.098695), btScalar(0.990747)),
- btVector3(btScalar(-0.256945), btScalar(0.228375), btScalar(0.938827)),
- btVector3(btScalar(-0.111761), btScalar(-0.133251), btScalar(0.984696)),
- btVector3(btScalar(-0.118006), btScalar(-0.356253), btScalar(0.926725)),
- btVector3(btScalar(-0.119372), btScalar(-0.563896), btScalar(0.817029)),
- btVector3(btScalar(0.041228), btScalar(-0.833949), btScalar(0.550010)),
- btVector3(btScalar(-0.121909), btScalar(-0.736543), btScalar(0.665172)),
- btVector3(btScalar(-0.307681), btScalar(-0.931160), btScalar(-0.195026)),
- btVector3(btScalar(-0.283679), btScalar(-0.957990), btScalar(0.041348)),
- btVector3(btScalar(-0.227284), btScalar(-0.935243), btScalar(0.270890)),
- btVector3(btScalar(-0.293436), btScalar(-0.858252), btScalar(-0.420860)),
- btVector3(btScalar(-0.175767), btScalar(-0.780677), btScalar(-0.599262)),
- btVector3(btScalar(-0.170108), btScalar(-0.858835), btScalar(0.482865)),
- btVector3(btScalar(-0.332854), btScalar(-0.635055), btScalar(-0.696857)),
- btVector3(btScalar(-0.447791), btScalar(-0.445299), btScalar(-0.775128)),
- btVector3(btScalar(-0.470622), btScalar(-0.074146), btScalar(-0.879164)),
- btVector3(btScalar(-0.639417), btScalar(-0.340505), btScalar(-0.689049)),
- btVector3(btScalar(-0.598438), btScalar(0.104722), btScalar(-0.794256)),
- btVector3(btScalar(-0.488575), btScalar(0.307699), btScalar(-0.816313)),
- btVector3(btScalar(-0.379882), btScalar(0.513592), btScalar(-0.769077)),
- btVector3(btScalar(-0.425740), btScalar(0.862775), btScalar(-0.272516)),
- btVector3(btScalar(-0.480769), btScalar(0.875412), btScalar(-0.048439)),
- btVector3(btScalar(-0.467890), btScalar(0.648716), btScalar(-0.600043)),
- btVector3(btScalar(-0.543799), btScalar(0.730956), btScalar(-0.411881)),
- btVector3(btScalar(-0.516284), btScalar(0.838277), btScalar(0.174076)),
- btVector3(btScalar(-0.353343), btScalar(0.876384), btScalar(0.326519)),
- btVector3(btScalar(-0.572875), btScalar(0.614497), btScalar(0.542007)),
- btVector3(btScalar(-0.503600), btScalar(0.497261), btScalar(0.706161)),
- btVector3(btScalar(-0.530920), btScalar(0.754870), btScalar(0.384685)),
- btVector3(btScalar(-0.395884), btScalar(0.366414), btScalar(0.841818)),
- btVector3(btScalar(-0.300656), btScalar(0.001678), btScalar(0.953661)),
- btVector3(btScalar(-0.461060), btScalar(0.146912), btScalar(0.875000)),
- btVector3(btScalar(-0.315486), btScalar(-0.232212), btScalar(0.919893)),
- btVector3(btScalar(-0.323682), btScalar(-0.449187), btScalar(0.832644)),
- btVector3(btScalar(-0.318999), btScalar(-0.639527), btScalar(0.699134)),
- btVector3(btScalar(-0.496771), btScalar(-0.866029), btScalar(-0.055271)),
- btVector3(btScalar(-0.496771), btScalar(-0.816257), btScalar(-0.294377)),
- btVector3(btScalar(-0.456377), btScalar(-0.869528), btScalar(0.188130)),
- btVector3(btScalar(-0.380858), btScalar(-0.827144), btScalar(0.412792)),
- btVector3(btScalar(-0.449352), btScalar(-0.727405), btScalar(-0.518259)),
- btVector3(btScalar(-0.570533), btScalar(-0.551064), btScalar(-0.608632)),
- btVector3(btScalar(-0.656394), btScalar(-0.118280), btScalar(-0.744874)),
- btVector3(btScalar(-0.756696), btScalar(-0.438105), btScalar(-0.484882)),
- btVector3(btScalar(-0.801773), btScalar(-0.204798), btScalar(-0.561005)),
- btVector3(btScalar(-0.785186), btScalar(0.038618), btScalar(-0.617805)),
- btVector3(btScalar(-0.709082), btScalar(0.262399), btScalar(-0.654306)),
- btVector3(btScalar(-0.583412), btScalar(0.462265), btScalar(-0.667383)),
- btVector3(btScalar(-0.616001), btScalar(0.761286), btScalar(-0.201272)),
- btVector3(btScalar(-0.660687), btScalar(0.750204), btScalar(0.020072)),
- btVector3(btScalar(-0.744987), btScalar(0.435823), btScalar(-0.504791)),
- btVector3(btScalar(-0.713765), btScalar(0.605554), btScalar(-0.351373)),
- btVector3(btScalar(-0.686251), btScalar(0.687600), btScalar(0.236927)),
- btVector3(btScalar(-0.680201), btScalar(0.429407), btScalar(0.593732)),
- btVector3(btScalar(-0.733474), btScalar(0.546450), btScalar(0.403814)),
- btVector3(btScalar(-0.591023), btScalar(0.292923), btScalar(0.751445)),
- btVector3(btScalar(-0.500283), btScalar(-0.080757), btScalar(0.861922)),
- btVector3(btScalar(-0.643710), btScalar(0.070115), btScalar(0.761985)),
- btVector3(btScalar(-0.506332), btScalar(-0.308425), btScalar(0.805122)),
- btVector3(btScalar(-0.503015), btScalar(-0.509847), btScalar(0.697573)),
- btVector3(btScalar(-0.482525), btScalar(-0.682105), btScalar(0.549229)),
- btVector3(btScalar(-0.680396), btScalar(-0.716323), btScalar(-0.153451)),
- btVector3(btScalar(-0.658346), btScalar(-0.746264), btScalar(0.097562)),
- btVector3(btScalar(-0.653272), btScalar(-0.646915), btScalar(-0.392948)),
- btVector3(btScalar(-0.590828), btScalar(-0.732655), btScalar(0.337645)),
- btVector3(btScalar(-0.819140), btScalar(-0.518013), btScalar(-0.246166)),
- btVector3(btScalar(-0.900513), btScalar(-0.282178), btScalar(-0.330487)),
- btVector3(btScalar(-0.914953), btScalar(-0.028652), btScalar(-0.402122)),
- btVector3(btScalar(-0.859924), btScalar(0.220209), btScalar(-0.459898)),
- btVector3(btScalar(-0.777185), btScalar(0.613720), btScalar(-0.137836)),
- btVector3(btScalar(-0.805285), btScalar(0.586889), btScalar(0.082728)),
- btVector3(btScalar(-0.872413), btScalar(0.406077), btScalar(-0.271735)),
- btVector3(btScalar(-0.859339), btScalar(0.448072), btScalar(0.246101)),
- btVector3(btScalar(-0.757671), btScalar(0.216320), btScalar(0.615594)),
- btVector3(btScalar(-0.826165), btScalar(0.348139), btScalar(0.442851)),
- btVector3(btScalar(-0.671810), btScalar(-0.162803), btScalar(0.722557)),
- btVector3(btScalar(-0.796504), btScalar(-0.004543), btScalar(0.604468)),
- btVector3(btScalar(-0.676298), btScalar(-0.378223), btScalar(0.631794)),
- btVector3(btScalar(-0.668883), btScalar(-0.558258), btScalar(0.490673)),
- btVector3(btScalar(-0.821287), btScalar(-0.570118), btScalar(0.006994)),
- btVector3(btScalar(-0.767428), btScalar(-0.587810), btScalar(0.255470)),
- btVector3(btScalar(-0.933296), btScalar(-0.349837), btScalar(-0.079865)),
- btVector3(btScalar(-0.982667), btScalar(-0.100393), btScalar(-0.155208)),
- btVector3(btScalar(-0.961396), btScalar(0.160910), btScalar(-0.222938)),
- btVector3(btScalar(-0.934858), btScalar(0.354555), btScalar(-0.006864)),
- btVector3(btScalar(-0.941687), btScalar(0.229736), btScalar(0.245711)),
- btVector3(btScalar(-0.884317), btScalar(0.131552), btScalar(0.447536)),
- btVector3(btScalar(-0.810359), btScalar(-0.219769), btScalar(0.542788)),
- btVector3(btScalar(-0.915929), btScalar(-0.210048), btScalar(0.341743)),
- btVector3(btScalar(-0.816799), btScalar(-0.407192), btScalar(0.408303)),
- btVector3(btScalar(-0.903050), btScalar(-0.392416), btScalar(0.174076)),
- btVector3(btScalar(-0.980325), btScalar(-0.170969), btScalar(0.096586)),
- btVector3(btScalar(-0.995936), btScalar(0.084891), btScalar(0.029441)),
- btVector3(btScalar(-0.960031), btScalar(0.002650), btScalar(0.279283)),
- };
- static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
- {
- btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
- btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
- btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
- btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
- btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
- btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
- btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
- btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
- btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
- btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
- btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
- btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
- btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
- btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
- btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
- btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
- btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
- btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
- btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
- btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
- btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
- btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
- btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
- btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
- btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
- btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
- btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
- btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
- btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
- btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
- btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
- btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
- btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
- btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
- btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
- btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
- btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
- btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
- btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
- btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
- btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
- btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
- if (highres)
- return sUnitSpherePointsHighres;
- return sUnitSpherePoints;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h
deleted file mode 100644
index 54439f9ca2..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btShapeHull.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///btShapeHull implemented by John McCutchan.
-
-#ifndef BT_SHAPE_HULL_H
-#define BT_SHAPE_HULL_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
-///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
-///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
-///It approximates the convex hull using the supporting vertex of 42 directions.
-ATTRIBUTE_ALIGNED16(class)
-btShapeHull
-{
-protected:
- btAlignedObjectArray<btVector3> m_vertices;
- btAlignedObjectArray<unsigned int> m_indices;
- unsigned int m_numIndices;
- const btConvexShape* m_shape;
-
- static btVector3* getUnitSpherePoints(int highres = 0);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btShapeHull(const btConvexShape* shape);
- ~btShapeHull();
-
- bool buildHull(btScalar margin, int highres = 0);
-
- int numTriangles() const;
- int numVertices() const;
- int numIndices() const;
-
- const btVector3* getVertexPointer() const
- {
- return &m_vertices[0];
- }
- const unsigned int* getIndexPointer() const
- {
- return &m_indices[0];
- }
-};
-
-#endif //BT_SHAPE_HULL_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
deleted file mode 100644
index 027db2e104..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-#include "LinearMath/btQuaternion.h"
-
-btVector3 btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- (void)vec;
- return btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
-}
-
-void btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- (void)vectors;
-
- for (int i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i].setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- }
-}
-
-btVector3 btSphereShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supVertex;
- supVertex = localGetSupportingVertexWithoutMargin(vec);
-
- btVector3 vecnorm = vec;
- if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
- {
- vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
- }
- vecnorm.normalize();
- supVertex += getMargin() * vecnorm;
- return supVertex;
-}
-
-//broken due to scaling
-void btSphereShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- const btVector3& center = t.getOrigin();
- btVector3 extent(getMargin(), getMargin(), getMargin());
- aabbMin = center - extent;
- aabbMax = center + extent;
-}
-
-void btSphereShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- btScalar elem = btScalar(0.4) * mass * getMargin() * getMargin();
- inertia.setValue(elem, elem, elem);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h
deleted file mode 100644
index 75e4fd8e18..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btSphereShape.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#ifndef BT_SPHERE_MINKOWSKI_H
-#define BT_SPHERE_MINKOWSKI_H
-
-#include "btConvexInternalShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
-ATTRIBUTE_ALIGNED16(class)
-btSphereShape : public btConvexInternalShape
-
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btSphereShape(btScalar radius) : btConvexInternalShape()
- {
- m_shapeType = SPHERE_SHAPE_PROXYTYPE;
- m_localScaling.setValue(1.0, 1.0, 1.0);
- m_implicitShapeDimensions.setZero();
- m_implicitShapeDimensions.setX(radius);
- m_collisionMargin = radius;
- m_padding = 0;
- }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
- //notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- btScalar getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX(); }
-
- void setUnscaledRadius(btScalar radius)
- {
- m_implicitShapeDimensions.setX(radius);
- btConvexInternalShape::setMargin(radius);
- }
-
- //debugging
- virtual const char* getName() const { return "SPHERE"; }
-
- virtual void setMargin(btScalar margin)
- {
- btConvexInternalShape::setMargin(margin);
- }
- virtual btScalar getMargin() const
- {
- //to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
- //this means, non-uniform scaling is not supported anymore
- return getRadius();
- }
-};
-
-#endif //BT_SPHERE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
deleted file mode 100644
index 9238c919d5..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btStaticPlaneShape.h"
-
-#include "LinearMath/btTransformUtil.h"
-
-btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant)
- : btConcaveShape(), m_planeNormal(planeNormal.normalized()), m_planeConstant(planeConstant), m_localScaling(btScalar(1.), btScalar(1.), btScalar(1.))
-{
- m_shapeType = STATIC_PLANE_PROXYTYPE;
- // btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
-}
-
-btStaticPlaneShape::~btStaticPlaneShape()
-{
-}
-
-void btStaticPlaneShape::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
- (void)t;
- /*
- btVector3 infvec (btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
-
- btVector3 center = m_planeNormal*m_planeConstant;
- aabbMin = center + infvec*m_planeNormal;
- aabbMax = aabbMin;
- aabbMin.setMin(center - infvec*m_planeNormal);
- aabbMax.setMax(center - infvec*m_planeNormal);
- */
-
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
-}
-
-void btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
- btScalar radius = halfExtents.length();
- btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
-
- //this is where the triangles are generated, given AABB and plane equation (normal/constant)
-
- btVector3 tangentDir0, tangentDir1;
-
- //tangentDir0/tangentDir1 can be precalculated
- btPlaneSpace1(m_planeNormal, tangentDir0, tangentDir1);
-
- btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant) * m_planeNormal;
-
- btVector3 triangle[3];
- triangle[0] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
- triangle[1] = projectedCenter + tangentDir0 * radius - tangentDir1 * radius;
- triangle[2] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
-
- callback->processTriangle(triangle, 0, 0);
-
- triangle[0] = projectedCenter - tangentDir0 * radius - tangentDir1 * radius;
- triangle[1] = projectedCenter - tangentDir0 * radius + tangentDir1 * radius;
- triangle[2] = projectedCenter + tangentDir0 * radius + tangentDir1 * radius;
-
- callback->processTriangle(triangle, 0, 1);
-}
-
-void btStaticPlaneShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- (void)mass;
-
- //moving concave objects not supported
-
- inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-}
-
-void btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
-{
- m_localScaling = scaling;
-}
-const btVector3& btStaticPlaneShape::getLocalScaling() const
-{
- return m_localScaling;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
deleted file mode 100644
index 1cda8bbc75..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_STATIC_PLANE_SHAPE_H
-#define BT_STATIC_PLANE_SHAPE_H
-
-#include "btConcaveShape.h"
-
-///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
-ATTRIBUTE_ALIGNED16(class)
-btStaticPlaneShape : public btConcaveShape
-{
-protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
-
- btVector3 m_planeNormal;
- btScalar m_planeConstant;
- btVector3 m_localScaling;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btStaticPlaneShape(const btVector3& planeNormal, btScalar planeConstant);
-
- virtual ~btStaticPlaneShape();
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
-
- const btVector3& getPlaneNormal() const
- {
- return m_planeNormal;
- }
-
- const btScalar& getPlaneConstant() const
- {
- return m_planeConstant;
- }
-
- //debugging
- virtual const char* getName() const { return "STATICPLANE"; }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btStaticPlaneShapeData
-{
- btCollisionShapeData m_collisionShapeData;
-
- btVector3FloatData m_localScaling;
- btVector3FloatData m_planeNormal;
- float m_planeConstant;
- char m_pad[4];
-};
-
-SIMD_FORCE_INLINE int btStaticPlaneShape::calculateSerializeBufferSize() const
-{
- return sizeof(btStaticPlaneShapeData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)dataBuffer;
- btCollisionShape::serialize(&planeData->m_collisionShapeData, serializer);
-
- m_localScaling.serializeFloat(planeData->m_localScaling);
- m_planeNormal.serializeFloat(planeData->m_planeNormal);
- planeData->m_planeConstant = float(m_planeConstant);
-
- // Fill padding with zeros to appease msan.
- planeData->m_pad[0] = 0;
- planeData->m_pad[1] = 0;
- planeData->m_pad[2] = 0;
- planeData->m_pad[3] = 0;
-
- return "btStaticPlaneShapeData";
-}
-
-#endif //BT_STATIC_PLANE_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
deleted file mode 100644
index eb288e99c9..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btStridingMeshInterface.h"
-#include "LinearMath/btSerializer.h"
-
-btStridingMeshInterface::~btStridingMeshInterface()
-{
-}
-
-void btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- (void)aabbMin;
- (void)aabbMax;
- int numtotalphysicsverts = 0;
- int part, graphicssubparts = getNumSubParts();
- const unsigned char* vertexbase;
- const unsigned char* indexbase;
- int indexstride;
- PHY_ScalarType type;
- PHY_ScalarType gfxindextype;
- int stride, numverts, numtriangles;
- int gfxindex;
- btVector3 triangle[3];
-
- btVector3 meshScaling = getScaling();
-
- ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part = 0; part < graphicssubparts; part++)
- {
- getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
- numtotalphysicsverts += numtriangles * 3; //upper bound
-
- ///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
- ///so disable this feature by default
- ///see patch http://code.google.com/p/bullet/issues/detail?id=213
-
- switch (type)
- {
- case PHY_FLOAT:
- {
- float* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
- graphicsbase = (float*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (float*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue(graphicsbase[0] * meshScaling.getX(), graphicsbase[1] * meshScaling.getY(), graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- default:
- btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
-
- case PHY_DOUBLE:
- {
- double* graphicsbase;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_SHORT:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- case PHY_UCHAR:
- {
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
- graphicsbase = (double*)(vertexbase + tri_indices[0] * stride);
- triangle[0].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[1] * stride);
- triangle[1].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- graphicsbase = (double*)(vertexbase + tri_indices[2] * stride);
- triangle[2].setValue((btScalar)graphicsbase[0] * meshScaling.getX(), (btScalar)graphicsbase[1] * meshScaling.getY(), (btScalar)graphicsbase[2] * meshScaling.getZ());
- callback->internalProcessTriangleIndex(triangle, part, gfxindex);
- }
- break;
- }
- default:
- btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
- }
- break;
- }
- default:
- btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
- }
-
- unLockReadOnlyVertexBase(part);
- }
-}
-
-void btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin, btVector3& aabbMax)
-{
- struct AabbCalculationCallback : public btInternalTriangleIndexCallback
- {
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
-
- AabbCalculationCallback()
- {
- m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
-
- m_aabbMin.setMin(triangle[0]);
- m_aabbMax.setMax(triangle[0]);
- m_aabbMin.setMin(triangle[1]);
- m_aabbMax.setMax(triangle[1]);
- m_aabbMin.setMin(triangle[2]);
- m_aabbMax.setMax(triangle[2]);
- }
- };
-
- //first calculate the total aabb for all triangles
- AabbCalculationCallback aabbCallback;
- aabbMin.setValue(btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT), btScalar(-BT_LARGE_FLOAT));
- aabbMax.setValue(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- InternalProcessAllTriangles(&aabbCallback, aabbMin, aabbMax);
-
- aabbMin = aabbCallback.m_aabbMin;
- aabbMax = aabbCallback.m_aabbMax;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*)dataBuffer;
-
- trimeshData->m_numMeshParts = getNumSubParts();
-
- //void* uniquePtr = 0;
-
- trimeshData->m_meshPartsPtr = 0;
-
- if (trimeshData->m_numMeshParts)
- {
- btChunk* chunk = serializer->allocate(sizeof(btMeshPartData), trimeshData->m_numMeshParts);
- btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
- trimeshData->m_meshPartsPtr = (btMeshPartData*)serializer->getUniquePointer(memPtr);
-
- // int numtotalphysicsverts = 0;
- int part, graphicssubparts = getNumSubParts();
- const unsigned char* vertexbase;
- const unsigned char* indexbase;
- int indexstride;
- PHY_ScalarType type;
- PHY_ScalarType gfxindextype;
- int stride, numverts, numtriangles;
- int gfxindex;
- // btVector3 triangle[3];
-
- // btVector3 meshScaling = getScaling();
-
- ///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
- for (part = 0; part < graphicssubparts; part++, memPtr++)
- {
- getLockedReadOnlyVertexIndexBase(&vertexbase, numverts, type, stride, &indexbase, indexstride, numtriangles, gfxindextype, part);
- memPtr->m_numTriangles = numtriangles; //indices = 3*numtriangles
- memPtr->m_numVertices = numverts;
- memPtr->m_indices16 = 0;
- memPtr->m_indices32 = 0;
- memPtr->m_3indices16 = 0;
- memPtr->m_3indices8 = 0;
- memPtr->m_vertices3f = 0;
- memPtr->m_vertices3d = 0;
-
- switch (gfxindextype)
- {
- case PHY_INTEGER:
- {
- int numindices = numtriangles * 3;
-
- if (numindices)
- {
- btChunk* chunk = serializer->allocate(sizeof(btIntIndexData), numindices);
- btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
- memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned int* tri_indices = (unsigned int*)(indexbase + gfxindex * indexstride);
- tmpIndices[gfxindex * 3].m_value = tri_indices[0];
- tmpIndices[gfxindex * 3 + 1].m_value = tri_indices[1];
- tmpIndices[gfxindex * 3 + 2].m_value = tri_indices[2];
- }
- serializer->finalizeChunk(chunk, "btIntIndexData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
- }
- break;
- }
- case PHY_SHORT:
- {
- if (numtriangles)
- {
- btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData), numtriangles);
- btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
- memPtr->m_3indices16 = (btShortIntIndexTripletData*)serializer->getUniquePointer(tmpIndices);
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned short int* tri_indices = (unsigned short int*)(indexbase + gfxindex * indexstride);
- tmpIndices[gfxindex].m_values[0] = tri_indices[0];
- tmpIndices[gfxindex].m_values[1] = tri_indices[1];
- tmpIndices[gfxindex].m_values[2] = tri_indices[2];
- // Fill padding with zeros to appease msan.
- tmpIndices[gfxindex].m_pad[0] = 0;
- tmpIndices[gfxindex].m_pad[1] = 0;
- }
- serializer->finalizeChunk(chunk, "btShortIntIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
- }
- break;
- }
- case PHY_UCHAR:
- {
- if (numtriangles)
- {
- btChunk* chunk = serializer->allocate(sizeof(btCharIndexTripletData), numtriangles);
- btCharIndexTripletData* tmpIndices = (btCharIndexTripletData*)chunk->m_oldPtr;
- memPtr->m_3indices8 = (btCharIndexTripletData*)serializer->getUniquePointer(tmpIndices);
- for (gfxindex = 0; gfxindex < numtriangles; gfxindex++)
- {
- unsigned char* tri_indices = (unsigned char*)(indexbase + gfxindex * indexstride);
- tmpIndices[gfxindex].m_values[0] = tri_indices[0];
- tmpIndices[gfxindex].m_values[1] = tri_indices[1];
- tmpIndices[gfxindex].m_values[2] = tri_indices[2];
- // Fill padding with zeros to appease msan.
- tmpIndices[gfxindex].m_pad = 0;
- }
- serializer->finalizeChunk(chunk, "btCharIndexTripletData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
- }
- break;
- }
- default:
- {
- btAssert(0);
- //unknown index type
- }
- }
-
- switch (type)
- {
- case PHY_FLOAT:
- {
- float* graphicsbase;
-
- if (numverts)
- {
- btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData), numverts);
- btVector3FloatData* tmpVertices = (btVector3FloatData*)chunk->m_oldPtr;
- memPtr->m_vertices3f = (btVector3FloatData*)serializer->getUniquePointer(tmpVertices);
- for (int i = 0; i < numverts; i++)
- {
- graphicsbase = (float*)(vertexbase + i * stride);
- tmpVertices[i].m_floats[0] = graphicsbase[0];
- tmpVertices[i].m_floats[1] = graphicsbase[1];
- tmpVertices[i].m_floats[2] = graphicsbase[2];
- }
- serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
- }
- break;
- }
-
- case PHY_DOUBLE:
- {
- if (numverts)
- {
- btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData), numverts);
- btVector3DoubleData* tmpVertices = (btVector3DoubleData*)chunk->m_oldPtr;
- memPtr->m_vertices3d = (btVector3DoubleData*)serializer->getUniquePointer(tmpVertices);
- for (int i = 0; i < numverts; i++)
- {
- double* graphicsbase = (double*)(vertexbase + i * stride); //for now convert to float, might leave it at double
- tmpVertices[i].m_floats[0] = graphicsbase[0];
- tmpVertices[i].m_floats[1] = graphicsbase[1];
- tmpVertices[i].m_floats[2] = graphicsbase[2];
- }
- serializer->finalizeChunk(chunk, "btVector3DoubleData", BT_ARRAY_CODE, (void*)chunk->m_oldPtr);
- }
- break;
- }
-
- default:
- btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
- }
-
- unLockReadOnlyVertexBase(part);
- }
-
- serializer->finalizeChunk(chunk, "btMeshPartData", BT_ARRAY_CODE, chunk->m_oldPtr);
- }
-
- // Fill padding with zeros to appease msan.
- memset(trimeshData->m_padding, 0, sizeof(trimeshData->m_padding));
-
- m_scaling.serializeFloat(trimeshData->m_scaling);
- return "btStridingMeshInterfaceData";
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
deleted file mode 100644
index 68a41dfb45..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_STRIDING_MESHINTERFACE_H
-#define BT_STRIDING_MESHINTERFACE_H
-
-#include "LinearMath/btVector3.h"
-#include "btTriangleCallback.h"
-#include "btConcaveShape.h"
-
-/// The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
-/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
-/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
-ATTRIBUTE_ALIGNED16(class)
-btStridingMeshInterface
-{
-protected:
- btVector3 m_scaling;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btStridingMeshInterface() : m_scaling(btScalar(1.), btScalar(1.), btScalar(1.))
- {
- }
-
- virtual ~btStridingMeshInterface();
-
- virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- ///brute force method to calculate aabb
- void calculateAabbBruteForce(btVector3 & aabbMin, btVector3 & aabbMax);
-
- /// get read and write access to a subpart of a triangle mesh
- /// this subpart has a continuous array of vertices and indices
- /// in this way the mesh can be handled as chunks of memory with striding
- /// very similar to OpenGL vertexarray support
- /// make a call to unLockVertexBase when the read and write access is finished
- virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) = 0;
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& stride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const = 0;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) = 0;
-
- virtual void unLockReadOnlyVertexBase(int subpart) const = 0;
-
- /// getNumSubParts returns the number of separate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const = 0;
-
- virtual void preallocateVertices(int numverts) = 0;
- virtual void preallocateIndices(int numindices) = 0;
-
- virtual bool hasPremadeAabb() const { return false; }
- virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
- {
- (void)aabbMin;
- (void)aabbMax;
- }
- virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const
- {
- (void)aabbMin;
- (void)aabbMax;
- }
-
- const btVector3& getScaling() const
- {
- return m_scaling;
- }
- void setScaling(const btVector3& scaling)
- {
- m_scaling = scaling;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-struct btIntIndexData
-{
- int m_value;
-};
-
-struct btShortIntIndexData
-{
- short m_value;
- char m_pad[2];
-};
-
-struct btShortIntIndexTripletData
-{
- short m_values[3];
- char m_pad[2];
-};
-
-struct btCharIndexTripletData
-{
- unsigned char m_values[3];
- char m_pad;
-};
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btMeshPartData
-{
- btVector3FloatData *m_vertices3f;
- btVector3DoubleData *m_vertices3d;
-
- btIntIndexData *m_indices32;
- btShortIntIndexTripletData *m_3indices16;
- btCharIndexTripletData *m_3indices8;
-
- btShortIntIndexData *m_indices16;//backwards compatibility
-
- int m_numTriangles;//length of m_indices = m_numTriangles
- int m_numVertices;
-};
-
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btStridingMeshInterfaceData
-{
- btMeshPartData *m_meshPartsPtr;
- btVector3FloatData m_scaling;
- int m_numMeshParts;
- char m_padding[4];
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btStridingMeshInterface::calculateSerializeBufferSize() const
-{
- return sizeof(btStridingMeshInterfaceData);
-}
-
-#endif //BT_STRIDING_MESHINTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
deleted file mode 100644
index c4d33c429f..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTetrahedronShape.h"
-#include "LinearMath/btMatrix3x3.h"
-
-btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape(),
- m_numVertices(0)
-{
- m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
-}
-
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape(),
- m_numVertices(0)
-{
- m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
- addVertex(pt0);
-}
-
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1) : btPolyhedralConvexAabbCachingShape(),
- m_numVertices(0)
-{
- m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
- addVertex(pt0);
- addVertex(pt1);
-}
-
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2) : btPolyhedralConvexAabbCachingShape(),
- m_numVertices(0)
-{
- m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
- addVertex(pt0);
- addVertex(pt1);
- addVertex(pt2);
-}
-
-btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3) : btPolyhedralConvexAabbCachingShape(),
- m_numVertices(0)
-{
- m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
- addVertex(pt0);
- addVertex(pt1);
- addVertex(pt2);
- addVertex(pt3);
-}
-
-void btBU_Simplex1to4::getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
-#if 1
- btPolyhedralConvexAabbCachingShape::getAabb(t, aabbMin, aabbMax);
-#else
- aabbMin.setValue(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- aabbMax.setValue(-BT_LARGE_FLOAT, -BT_LARGE_FLOAT, -BT_LARGE_FLOAT);
-
- //just transform the vertices in worldspace, and take their AABB
- for (int i = 0; i < m_numVertices; i++)
- {
- btVector3 worldVertex = t(m_vertices[i]);
- aabbMin.setMin(worldVertex);
- aabbMax.setMax(worldVertex);
- }
-#endif
-}
-
-void btBU_Simplex1to4::addVertex(const btVector3& pt)
-{
- m_vertices[m_numVertices++] = pt;
- recalcLocalAabb();
-}
-
-int btBU_Simplex1to4::getNumVertices() const
-{
- return m_numVertices;
-}
-
-int btBU_Simplex1to4::getNumEdges() const
-{
- //euler formula, F-E+V = 2, so E = F+V-2
-
- switch (m_numVertices)
- {
- case 0:
- return 0;
- case 1:
- return 0;
- case 2:
- return 1;
- case 3:
- return 3;
- case 4:
- return 6;
- }
-
- return 0;
-}
-
-void btBU_Simplex1to4::getEdge(int i, btVector3& pa, btVector3& pb) const
-{
- switch (m_numVertices)
- {
- case 2:
- pa = m_vertices[0];
- pb = m_vertices[1];
- break;
- case 3:
- switch (i)
- {
- case 0:
- pa = m_vertices[0];
- pb = m_vertices[1];
- break;
- case 1:
- pa = m_vertices[1];
- pb = m_vertices[2];
- break;
- case 2:
- pa = m_vertices[2];
- pb = m_vertices[0];
- break;
- }
- break;
- case 4:
- switch (i)
- {
- case 0:
- pa = m_vertices[0];
- pb = m_vertices[1];
- break;
- case 1:
- pa = m_vertices[1];
- pb = m_vertices[2];
- break;
- case 2:
- pa = m_vertices[2];
- pb = m_vertices[0];
- break;
- case 3:
- pa = m_vertices[0];
- pb = m_vertices[3];
- break;
- case 4:
- pa = m_vertices[1];
- pb = m_vertices[3];
- break;
- case 5:
- pa = m_vertices[2];
- pb = m_vertices[3];
- break;
- }
- }
-}
-
-void btBU_Simplex1to4::getVertex(int i, btVector3& vtx) const
-{
- vtx = m_vertices[i];
-}
-
-int btBU_Simplex1to4::getNumPlanes() const
-{
- switch (m_numVertices)
- {
- case 0:
- return 0;
- case 1:
- return 0;
- case 2:
- return 0;
- case 3:
- return 2;
- case 4:
- return 4;
- default:
- {
- }
- }
- return 0;
-}
-
-void btBU_Simplex1to4::getPlane(btVector3&, btVector3&, int) const
-{
-}
-
-int btBU_Simplex1to4::getIndex(int) const
-{
- return 0;
-}
-
-bool btBU_Simplex1to4::isInside(const btVector3&, btScalar) const
-{
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
deleted file mode 100644
index f5e2209ed0..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMPLEX_1TO4_SHAPE
-#define BT_SIMPLEX_1TO4_SHAPE
-
-#include "btPolyhedralConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-
-///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
-ATTRIBUTE_ALIGNED16(class)
-btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
-{
-protected:
- int m_numVertices;
- btVector3 m_vertices[4];
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btBU_Simplex1to4();
-
- btBU_Simplex1to4(const btVector3& pt0);
- btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1);
- btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2);
- btBU_Simplex1to4(const btVector3& pt0, const btVector3& pt1, const btVector3& pt2, const btVector3& pt3);
-
- void reset()
- {
- m_numVertices = 0;
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- void addVertex(const btVector3& pt);
-
- //PolyhedralConvexShape interface
-
- virtual int getNumVertices() const;
-
- virtual int getNumEdges() const;
-
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const;
-
- virtual void getVertex(int i, btVector3& vtx) const;
-
- virtual int getNumPlanes() const;
-
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const;
-
- virtual int getIndex(int i) const;
-
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const;
-
- ///getName is for debugging
- virtual const char* getName() const { return "btBU_Simplex1to4"; }
-};
-
-#endif //BT_SIMPLEX_1TO4_SHAPE
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
deleted file mode 100644
index 3b6db2b39f..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleBuffer.h"
-
-void btTriangleBuffer::processTriangle(btVector3* triangle, int partId, int triangleIndex)
-{
- btTriangle tri;
- tri.m_vertex0 = triangle[0];
- tri.m_vertex1 = triangle[1];
- tri.m_vertex2 = triangle[2];
- tri.m_partId = partId;
- tri.m_triangleIndex = triangleIndex;
-
- m_triangleBuffer.push_back(tri);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
deleted file mode 100644
index a89b9cd8a4..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRIANGLE_BUFFER_H
-#define BT_TRIANGLE_BUFFER_H
-
-#include "btTriangleCallback.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-struct btTriangle
-{
- btVector3 m_vertex0;
- btVector3 m_vertex1;
- btVector3 m_vertex2;
- int m_partId;
- int m_triangleIndex;
-};
-
-///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
-///Example usage of this class:
-/// btTriangleBuffer triBuf;
-/// concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
-/// for (int i=0;i<triBuf.getNumTriangles();i++)
-/// {
-/// const btTriangle& tri = triBuf.getTriangle(i);
-/// //do something useful here with the triangle
-/// }
-class btTriangleBuffer : public btTriangleCallback
-{
- btAlignedObjectArray<btTriangle> m_triangleBuffer;
-
-public:
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
- int getNumTriangles() const
- {
- return int(m_triangleBuffer.size());
- }
-
- const btTriangle& getTriangle(int index) const
- {
- return m_triangleBuffer[index];
- }
-
- void clearBuffer()
- {
- m_triangleBuffer.clear();
- }
-};
-
-#endif //BT_TRIANGLE_BUFFER_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
deleted file mode 100644
index 5bd2c595fe..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleCallback.h"
-
-btTriangleCallback::~btTriangleCallback()
-{
-}
-
-btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
-{
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
deleted file mode 100644
index d3644891ee..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRIANGLE_CALLBACK_H
-#define BT_TRIANGLE_CALLBACK_H
-
-#include "LinearMath/btVector3.h"
-
-///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
-///This callback is called by processAllTriangles for all btConcaveShape derived class, such as btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
-class btTriangleCallback
-{
-public:
- virtual ~btTriangleCallback();
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
-};
-
-class btInternalTriangleIndexCallback
-{
-public:
- virtual ~btInternalTriangleIndexCallback();
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) = 0;
-};
-
-#endif //BT_TRIANGLE_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
deleted file mode 100644
index dae4255194..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleIndexVertexArray.h"
-
-btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride)
- : m_hasAabb(0)
-{
- btIndexedMesh mesh;
-
- mesh.m_numTriangles = numTriangles;
- mesh.m_triangleIndexBase = (const unsigned char*)triangleIndexBase;
- mesh.m_triangleIndexStride = triangleIndexStride;
- mesh.m_numVertices = numVertices;
- mesh.m_vertexBase = (const unsigned char*)vertexBase;
- mesh.m_vertexStride = vertexStride;
-
- addIndexedMesh(mesh);
-}
-
-btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
-{
-}
-
-void btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart)
-{
- btAssert(subpart < getNumSubParts());
-
- btIndexedMesh& mesh = m_indexedMeshes[subpart];
-
- numverts = mesh.m_numVertices;
- (*vertexbase) = (unsigned char*)mesh.m_vertexBase;
-
- type = mesh.m_vertexType;
-
- vertexStride = mesh.m_vertexStride;
-
- numfaces = mesh.m_numTriangles;
-
- (*indexbase) = (unsigned char*)mesh.m_triangleIndexBase;
- indexstride = mesh.m_triangleIndexStride;
- indicestype = mesh.m_indexType;
-}
-
-void btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart) const
-{
- const btIndexedMesh& mesh = m_indexedMeshes[subpart];
-
- numverts = mesh.m_numVertices;
- (*vertexbase) = (const unsigned char*)mesh.m_vertexBase;
-
- type = mesh.m_vertexType;
-
- vertexStride = mesh.m_vertexStride;
-
- numfaces = mesh.m_numTriangles;
- (*indexbase) = (const unsigned char*)mesh.m_triangleIndexBase;
- indexstride = mesh.m_triangleIndexStride;
- indicestype = mesh.m_indexType;
-}
-
-bool btTriangleIndexVertexArray::hasPremadeAabb() const
-{
- return (m_hasAabb == 1);
-}
-
-void btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- m_aabbMin = aabbMin;
- m_aabbMax = aabbMax;
- m_hasAabb = 1; // this is intentionally an int see notes in header
-}
-
-void btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax) const
-{
- *aabbMin = m_aabbMin;
- *aabbMax = m_aabbMax;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
deleted file mode 100644
index 556aa3fef4..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
-#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
-
-#include "btStridingMeshInterface.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btScalar.h"
-
-///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
-///Instead of the number of indices, we pass the number of triangles.
-ATTRIBUTE_ALIGNED16(struct)
-btIndexedMesh
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_numTriangles;
- const unsigned char* m_triangleIndexBase;
- // Size in byte of the indices for one triangle (3*sizeof(index_type) if the indices are tightly packed)
- int m_triangleIndexStride;
- int m_numVertices;
- const unsigned char* m_vertexBase;
- // Size of a vertex, in bytes
- int m_vertexStride;
-
- // The index type is set when adding an indexed mesh to the
- // btTriangleIndexVertexArray, do not set it manually
- PHY_ScalarType m_indexType;
-
- // The vertex type has a default type similar to Bullet's precision mode (float or double)
- // but can be set manually if you for example run Bullet with double precision but have
- // mesh data in single precision..
- PHY_ScalarType m_vertexType;
-
- btIndexedMesh()
- : m_indexType(PHY_INTEGER),
-#ifdef BT_USE_DOUBLE_PRECISION
- m_vertexType(PHY_DOUBLE)
-#else // BT_USE_DOUBLE_PRECISION
- m_vertexType(PHY_FLOAT)
-#endif // BT_USE_DOUBLE_PRECISION
- {
- }
-};
-
-typedef btAlignedObjectArray<btIndexedMesh> IndexedMeshArray;
-
-///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
-///Additional meshes can be added using addIndexedMesh
-///No duplicate is made of the vertex/index data, it only indexes into external vertex/index arrays.
-///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
-ATTRIBUTE_ALIGNED16(class)
-btTriangleIndexVertexArray : public btStridingMeshInterface
-{
-protected:
- IndexedMeshArray m_indexedMeshes;
- int m_pad[2];
- mutable int m_hasAabb; // using int instead of bool to maintain alignment
- mutable btVector3 m_aabbMin;
- mutable btVector3 m_aabbMax;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btTriangleIndexVertexArray() : m_hasAabb(0)
- {
- }
-
- virtual ~btTriangleIndexVertexArray();
-
- //just to be backwards compatible
- btTriangleIndexVertexArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride, int numVertices, btScalar* vertexBase, int vertexStride);
-
- void addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
- {
- m_indexedMeshes.push_back(mesh);
- m_indexedMeshes[m_indexedMeshes.size() - 1].m_indexType = indexType;
- }
-
- virtual void getLockedVertexIndexBase(unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0);
-
- virtual void getLockedReadOnlyVertexIndexBase(const unsigned char** vertexbase, int& numverts, PHY_ScalarType& type, int& vertexStride, const unsigned char** indexbase, int& indexstride, int& numfaces, PHY_ScalarType& indicestype, int subpart = 0) const;
-
- /// unLockVertexBase finishes the access to a subpart of the triangle mesh
- /// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
- virtual void unLockVertexBase(int subpart) { (void)subpart; }
-
- virtual void unLockReadOnlyVertexBase(int subpart) const { (void)subpart; }
-
- /// getNumSubParts returns the number of separate subparts
- /// each subpart has a continuous array of vertices and indices
- virtual int getNumSubParts() const
- {
- return (int)m_indexedMeshes.size();
- }
-
- IndexedMeshArray& getIndexedMeshArray()
- {
- return m_indexedMeshes;
- }
-
- const IndexedMeshArray& getIndexedMeshArray() const
- {
- return m_indexedMeshes;
- }
-
- virtual void preallocateVertices(int numverts) { (void)numverts; }
- virtual void preallocateIndices(int numindices) { (void)numindices; }
-
- virtual bool hasPremadeAabb() const;
- virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void getPremadeAabb(btVector3 * aabbMin, btVector3 * aabbMax) const;
-};
-
-#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
deleted file mode 100644
index 4bf133d7ac..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was created by Alex Silverman
-
-#include "btTriangleIndexVertexMaterialArray.h"
-
-btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride,
- int numVertices, btScalar* vertexBase, int vertexStride,
- int numMaterials, unsigned char* materialBase, int materialStride,
- int* triangleMaterialsBase, int materialIndexStride) : btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
-{
- btMaterialProperties mat;
-
- mat.m_numMaterials = numMaterials;
- mat.m_materialBase = materialBase;
- mat.m_materialStride = materialStride;
-#ifdef BT_USE_DOUBLE_PRECISION
- mat.m_materialType = PHY_DOUBLE;
-#else
- mat.m_materialType = PHY_FLOAT;
-#endif
-
- mat.m_numTriangles = numTriangles;
- mat.m_triangleMaterialsBase = (unsigned char*)triangleMaterialsBase;
- mat.m_triangleMaterialStride = materialIndexStride;
- mat.m_triangleType = PHY_INTEGER;
-
- addMaterialProperties(mat);
-}
-
-void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
-{
- btAssert(subpart < getNumSubParts());
-
- btMaterialProperties& mats = m_materials[subpart];
-
- numMaterials = mats.m_numMaterials;
- (*materialBase) = (unsigned char*)mats.m_materialBase;
-#ifdef BT_USE_DOUBLE_PRECISION
- materialType = PHY_DOUBLE;
-#else
- materialType = PHY_FLOAT;
-#endif
- materialStride = mats.m_materialStride;
-
- numTriangles = mats.m_numTriangles;
- (*triangleMaterialBase) = (unsigned char*)mats.m_triangleMaterialsBase;
- triangleMaterialStride = mats.m_triangleMaterialStride;
- triangleType = mats.m_triangleType;
-}
-
-void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- const unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
-{
- btMaterialProperties& mats = m_materials[subpart];
-
- numMaterials = mats.m_numMaterials;
- (*materialBase) = (const unsigned char*)mats.m_materialBase;
-#ifdef BT_USE_DOUBLE_PRECISION
- materialType = PHY_DOUBLE;
-#else
- materialType = PHY_FLOAT;
-#endif
- materialStride = mats.m_materialStride;
-
- numTriangles = mats.m_numTriangles;
- (*triangleMaterialBase) = (const unsigned char*)mats.m_triangleMaterialsBase;
- triangleMaterialStride = mats.m_triangleMaterialStride;
- triangleType = mats.m_triangleType;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
deleted file mode 100644
index 315b1e21f3..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was created by Alex Silverman
-
-#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
-#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
-
-#include "btTriangleIndexVertexArray.h"
-
-ATTRIBUTE_ALIGNED16(struct)
-btMaterialProperties
-{
- ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
- int m_numMaterials;
- const unsigned char* m_materialBase;
- int m_materialStride;
- PHY_ScalarType m_materialType;
- ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
- /// padding the structure, it can be reproduced at no real cost
- ///m_triangleMaterials =====> 1 integer value makes up one entry
- /// eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
- int m_numTriangles;
- const unsigned char* m_triangleMaterialsBase;
- int m_triangleMaterialStride;
- ///m_triangleType <========== Automatically set in addMaterialProperties
- PHY_ScalarType m_triangleType;
-};
-
-typedef btAlignedObjectArray<btMaterialProperties> MaterialArray;
-
-///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
-///The addition of a material array allows for the utilization of the partID and
-///triangleIndex that are returned in the ContactAddedCallback. As with
-///TriangleIndexVertexArray, no duplicate is made of the material data, so it
-///is the users responsibility to maintain the array during the lifetime of the
-///TriangleIndexVertexMaterialArray.
-ATTRIBUTE_ALIGNED16(class)
-btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
-{
-protected:
- MaterialArray m_materials;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btTriangleIndexVertexMaterialArray()
- {
- }
-
- btTriangleIndexVertexMaterialArray(int numTriangles, int* triangleIndexBase, int triangleIndexStride,
- int numVertices, btScalar* vertexBase, int vertexStride,
- int numMaterials, unsigned char* materialBase, int materialStride,
- int* triangleMaterialsBase, int materialIndexStride);
-
- virtual ~btTriangleIndexVertexMaterialArray() {}
-
- void addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
- {
- m_materials.push_back(mat);
- m_materials[m_materials.size() - 1].m_triangleType = triangleType;
- }
-
- virtual void getLockedMaterialBase(unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
-
- virtual void getLockedReadOnlyMaterialBase(const unsigned char** materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
- const unsigned char** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
-};
-
-#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
deleted file mode 100644
index 8ee35ef5fa..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2010 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef _BT_TRIANGLE_INFO_MAP_H
-#define _BT_TRIANGLE_INFO_MAP_H
-
-#include "LinearMath/btHashMap.h"
-#include "LinearMath/btSerializer.h"
-
-///for btTriangleInfo m_flags
-#define TRI_INFO_V0V1_CONVEX 1
-#define TRI_INFO_V1V2_CONVEX 2
-#define TRI_INFO_V2V0_CONVEX 4
-
-#define TRI_INFO_V0V1_SWAP_NORMALB 8
-#define TRI_INFO_V1V2_SWAP_NORMALB 16
-#define TRI_INFO_V2V0_SWAP_NORMALB 32
-
-///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
-///it can be generated using
-struct btTriangleInfo
-{
- btTriangleInfo()
- {
- m_edgeV0V1Angle = SIMD_2_PI;
- m_edgeV1V2Angle = SIMD_2_PI;
- m_edgeV2V0Angle = SIMD_2_PI;
- m_flags = 0;
- }
-
- int m_flags;
-
- btScalar m_edgeV0V1Angle;
- btScalar m_edgeV1V2Angle;
- btScalar m_edgeV2V0Angle;
-};
-
-typedef btHashMap<btHashInt, btTriangleInfo> btInternalTriangleInfoMap;
-
-///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
-struct btTriangleInfoMap : public btInternalTriangleInfoMap
-{
- btScalar m_convexEpsilon; ///used to determine if an edge or contact normal is convex, using the dot product
- btScalar m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
- btScalar m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
- btScalar m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
- btScalar m_maxEdgeAngleThreshold; //ignore edges that connect triangles at an angle larger than this m_maxEdgeAngleThreshold
- btScalar m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
-
- btTriangleInfoMap()
- {
- m_convexEpsilon = 0.00f;
- m_planarEpsilon = 0.0001f;
- m_equalVertexThreshold = btScalar(0.0001) * btScalar(0.0001);
- m_edgeDistanceThreshold = btScalar(0.1);
- m_zeroAreaThreshold = btScalar(0.0001) * btScalar(0.0001);
- m_maxEdgeAngleThreshold = SIMD_2_PI;
- }
- virtual ~btTriangleInfoMap() {}
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- void deSerialize(struct btTriangleInfoMapData& data);
-};
-
-// clang-format off
-
-///those fields have to be float and not btScalar for the serialization to work properly
-struct btTriangleInfoData
-{
- int m_flags;
- float m_edgeV0V1Angle;
- float m_edgeV1V2Angle;
- float m_edgeV2V0Angle;
-};
-
-struct btTriangleInfoMapData
-{
- int *m_hashTablePtr;
- int *m_nextPtr;
- btTriangleInfoData *m_valueArrayPtr;
- int *m_keyArrayPtr;
-
- float m_convexEpsilon;
- float m_planarEpsilon;
- float m_equalVertexThreshold;
- float m_edgeDistanceThreshold;
- float m_zeroAreaThreshold;
-
- int m_nextSize;
- int m_hashTableSize;
- int m_numValues;
- int m_numKeys;
- char m_padding[4];
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btTriangleInfoMap::calculateSerializeBufferSize() const
-{
- return sizeof(btTriangleInfoMapData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*)dataBuffer;
- tmapData->m_convexEpsilon = (float)m_convexEpsilon;
- tmapData->m_planarEpsilon = (float)m_planarEpsilon;
- tmapData->m_equalVertexThreshold = (float)m_equalVertexThreshold;
- tmapData->m_edgeDistanceThreshold = (float)m_edgeDistanceThreshold;
- tmapData->m_zeroAreaThreshold = (float)m_zeroAreaThreshold;
-
- tmapData->m_hashTableSize = m_hashTable.size();
-
- tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
- if (tmapData->m_hashTablePtr)
- {
- //serialize an int buffer
- int sz = sizeof(int);
- int numElem = tmapData->m_hashTableSize;
- btChunk* chunk = serializer->allocate(sz, numElem);
- int* memPtr = (int*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- *memPtr = m_hashTable[i];
- }
- serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_hashTable[0]);
- }
-
- tmapData->m_nextSize = m_next.size();
- tmapData->m_nextPtr = tmapData->m_nextSize ? (int*)serializer->getUniquePointer((void*)&m_next[0]) : 0;
- if (tmapData->m_nextPtr)
- {
- int sz = sizeof(int);
- int numElem = tmapData->m_nextSize;
- btChunk* chunk = serializer->allocate(sz, numElem);
- int* memPtr = (int*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- *memPtr = m_next[i];
- }
- serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_next[0]);
- }
-
- tmapData->m_numValues = m_valueArray.size();
- tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]) : 0;
- if (tmapData->m_valueArrayPtr)
- {
- int sz = sizeof(btTriangleInfoData);
- int numElem = tmapData->m_numValues;
- btChunk* chunk = serializer->allocate(sz, numElem);
- btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_edgeV0V1Angle = (float)m_valueArray[i].m_edgeV0V1Angle;
- memPtr->m_edgeV1V2Angle = (float)m_valueArray[i].m_edgeV1V2Angle;
- memPtr->m_edgeV2V0Angle = (float)m_valueArray[i].m_edgeV2V0Angle;
- memPtr->m_flags = m_valueArray[i].m_flags;
- }
- serializer->finalizeChunk(chunk, "btTriangleInfoData", BT_ARRAY_CODE, (void*)&m_valueArray[0]);
- }
-
- tmapData->m_numKeys = m_keyArray.size();
- tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
- if (tmapData->m_keyArrayPtr)
- {
- int sz = sizeof(int);
- int numElem = tmapData->m_numValues;
- btChunk* chunk = serializer->allocate(sz, numElem);
- int* memPtr = (int*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- *memPtr = m_keyArray[i].getUid1();
- }
- serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_keyArray[0]);
- }
-
- // Fill padding with zeros to appease msan.
- tmapData->m_padding[0] = 0;
- tmapData->m_padding[1] = 0;
- tmapData->m_padding[2] = 0;
- tmapData->m_padding[3] = 0;
-
- return "btTriangleInfoMapData";
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE void btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData)
-{
- m_convexEpsilon = tmapData.m_convexEpsilon;
- m_planarEpsilon = tmapData.m_planarEpsilon;
- m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
- m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
- m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
- m_hashTable.resize(tmapData.m_hashTableSize);
- int i = 0;
- for (i = 0; i < tmapData.m_hashTableSize; i++)
- {
- m_hashTable[i] = tmapData.m_hashTablePtr[i];
- }
- m_next.resize(tmapData.m_nextSize);
- for (i = 0; i < tmapData.m_nextSize; i++)
- {
- m_next[i] = tmapData.m_nextPtr[i];
- }
- m_valueArray.resize(tmapData.m_numValues);
- for (i = 0; i < tmapData.m_numValues; i++)
- {
- m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
- m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
- m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
- m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
- }
-
- m_keyArray.resize(tmapData.m_numKeys, btHashInt(0));
- for (i = 0; i < tmapData.m_numKeys; i++)
- {
- m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
- }
-}
-
-#endif //_BT_TRIANGLE_INFO_MAP_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
deleted file mode 100644
index abd8c22786..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleMesh.h"
-
-btTriangleMesh::btTriangleMesh(bool use32bitIndices, bool use4componentVertices)
- : m_use32bitIndices(use32bitIndices),
- m_use4componentVertices(use4componentVertices),
- m_weldingThreshold(0.0)
-{
- btIndexedMesh meshIndex;
- meshIndex.m_numTriangles = 0;
- meshIndex.m_numVertices = 0;
- meshIndex.m_indexType = PHY_INTEGER;
- meshIndex.m_triangleIndexBase = 0;
- meshIndex.m_triangleIndexStride = 3 * sizeof(int);
- meshIndex.m_vertexBase = 0;
- meshIndex.m_vertexStride = sizeof(btVector3);
- m_indexedMeshes.push_back(meshIndex);
-
- if (m_use32bitIndices)
- {
- m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size() / 3;
- m_indexedMeshes[0].m_triangleIndexBase = 0;
- m_indexedMeshes[0].m_indexType = PHY_INTEGER;
- m_indexedMeshes[0].m_triangleIndexStride = 3 * sizeof(int);
- }
- else
- {
- m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size() / 3;
- m_indexedMeshes[0].m_triangleIndexBase = 0;
- m_indexedMeshes[0].m_indexType = PHY_SHORT;
- m_indexedMeshes[0].m_triangleIndexStride = 3 * sizeof(short int);
- }
-
- if (m_use4componentVertices)
- {
- m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
- m_indexedMeshes[0].m_vertexBase = 0;
- m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
- }
- else
- {
- m_indexedMeshes[0].m_numVertices = m_3componentVertices.size() / 3;
- m_indexedMeshes[0].m_vertexBase = 0;
- m_indexedMeshes[0].m_vertexStride = 3 * sizeof(btScalar);
- }
-}
-
-void btTriangleMesh::addIndex(int index)
-{
- if (m_use32bitIndices)
- {
- m_32bitIndices.push_back(index);
- m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_32bitIndices[0];
- }
- else
- {
- m_16bitIndices.push_back(index);
- m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*)&m_16bitIndices[0];
- }
-}
-
-void btTriangleMesh::addTriangleIndices(int index1, int index2, int index3)
-{
- m_indexedMeshes[0].m_numTriangles++;
- addIndex(index1);
- addIndex(index2);
- addIndex(index3);
-}
-
-int btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
-{
- //return index of new/existing vertex
- ///@todo: could use acceleration structure for this
- if (m_use4componentVertices)
- {
- if (removeDuplicateVertices)
- {
- for (int i = 0; i < m_4componentVertices.size(); i++)
- {
- if ((m_4componentVertices[i] - vertex).length2() <= m_weldingThreshold)
- {
- return i;
- }
- }
- }
- m_indexedMeshes[0].m_numVertices++;
- m_4componentVertices.push_back(vertex);
- m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
-
- return m_4componentVertices.size() - 1;
- }
- else
- {
- if (removeDuplicateVertices)
- {
- for (int i = 0; i < m_3componentVertices.size(); i += 3)
- {
- btVector3 vtx(m_3componentVertices[i], m_3componentVertices[i + 1], m_3componentVertices[i + 2]);
- if ((vtx - vertex).length2() <= m_weldingThreshold)
- {
- return i / 3;
- }
- }
- }
- m_3componentVertices.push_back(vertex.getX());
- m_3componentVertices.push_back(vertex.getY());
- m_3componentVertices.push_back(vertex.getZ());
- m_indexedMeshes[0].m_numVertices++;
- m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
- return (m_3componentVertices.size() / 3) - 1;
- }
-}
-
-void btTriangleMesh::addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices)
-{
- m_indexedMeshes[0].m_numTriangles++;
- addIndex(findOrAddVertex(vertex0, removeDuplicateVertices));
- addIndex(findOrAddVertex(vertex1, removeDuplicateVertices));
- addIndex(findOrAddVertex(vertex2, removeDuplicateVertices));
-}
-
-int btTriangleMesh::getNumTriangles() const
-{
- if (m_use32bitIndices)
- {
- return m_32bitIndices.size() / 3;
- }
- return m_16bitIndices.size() / 3;
-}
-
-void btTriangleMesh::preallocateVertices(int numverts)
-{
- if (m_use4componentVertices)
- {
- m_4componentVertices.reserve(numverts);
- }
- else
- {
- m_3componentVertices.reserve(numverts);
- }
-}
-
-void btTriangleMesh::preallocateIndices(int numindices)
-{
- if (m_use32bitIndices)
- {
- m_32bitIndices.reserve(numindices);
- }
- else
- {
- m_16bitIndices.reserve(numindices);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
deleted file mode 100644
index a8a362355c..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRIANGLE_MESH_H
-#define BT_TRIANGLE_MESH_H
-
-#include "btTriangleIndexVertexArray.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape.
-///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
-///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
-///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
-class btTriangleMesh : public btTriangleIndexVertexArray
-{
- btAlignedObjectArray<btVector3> m_4componentVertices;
- btAlignedObjectArray<btScalar> m_3componentVertices;
-
- btAlignedObjectArray<unsigned int> m_32bitIndices;
- btAlignedObjectArray<unsigned short int> m_16bitIndices;
- bool m_use32bitIndices;
- bool m_use4componentVertices;
-
-public:
- btScalar m_weldingThreshold;
-
- btTriangleMesh(bool use32bitIndices = true, bool use4componentVertices = true);
-
- bool getUse32bitIndices() const
- {
- return m_use32bitIndices;
- }
-
- bool getUse4componentVertices() const
- {
- return m_use4componentVertices;
- }
- ///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
- ///In general it is better to directly use btTriangleIndexVertexArray instead.
- void addTriangle(const btVector3& vertex0, const btVector3& vertex1, const btVector3& vertex2, bool removeDuplicateVertices = false);
-
- ///Add a triangle using its indices. Make sure the indices are pointing within the vertices array, so add the vertices first (and to be sure, avoid removal of duplicate vertices)
- void addTriangleIndices(int index1, int index2, int index3);
-
- int getNumTriangles() const;
-
- virtual void preallocateVertices(int numverts);
- virtual void preallocateIndices(int numindices);
-
- ///findOrAddVertex is an internal method, use addTriangle instead
- int findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
- ///addIndex is an internal method, use addTriangle instead
- void addIndex(int index);
-};
-
-#endif //BT_TRIANGLE_MESH_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
deleted file mode 100644
index aec239063c..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleMeshShape.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btQuaternion.h"
-#include "btStridingMeshInterface.h"
-#include "LinearMath/btAabbUtil2.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
- : btConcaveShape(), m_meshInterface(meshInterface)
-{
- m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
- if (meshInterface->hasPremadeAabb())
- {
- meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
- }
- else
- {
- recalcLocalAabb();
- }
-}
-
-btTriangleMeshShape::~btTriangleMeshShape()
-{
-}
-
-void btTriangleMeshShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- btVector3 localHalfExtents = btScalar(0.5) * (m_localAabbMax - m_localAabbMin);
- localHalfExtents += btVector3(getMargin(), getMargin(), getMargin());
- btVector3 localCenter = btScalar(0.5) * (m_localAabbMax + m_localAabbMin);
-
- btMatrix3x3 abs_b = trans.getBasis().absolute();
-
- btVector3 center = trans(localCenter);
-
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMin = center - extent;
- aabbMax = center + extent;
-}
-
-void btTriangleMeshShape::recalcLocalAabb()
-{
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
- btVector3 tmp = localGetSupportingVertex(vec);
- m_localAabbMax[i] = tmp[i] + m_collisionMargin;
- vec[i] = btScalar(-1.);
- tmp = localGetSupportingVertex(vec);
- m_localAabbMin[i] = tmp[i] - m_collisionMargin;
- }
-}
-
-class SupportVertexCallback : public btTriangleCallback
-{
- btVector3 m_supportVertexLocal;
-
-public:
- btTransform m_worldTrans;
- btScalar m_maxDot;
- btVector3 m_supportVecLocal;
-
- SupportVertexCallback(const btVector3& supportVecWorld, const btTransform& trans)
- : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)), m_worldTrans(trans), m_maxDot(btScalar(-BT_LARGE_FLOAT))
-
- {
- m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
- }
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
- for (int i = 0; i < 3; i++)
- {
- btScalar dot = m_supportVecLocal.dot(triangle[i]);
- if (dot > m_maxDot)
- {
- m_maxDot = dot;
- m_supportVertexLocal = triangle[i];
- }
- }
- }
-
- btVector3 GetSupportVertexWorldSpace()
- {
- return m_worldTrans(m_supportVertexLocal);
- }
-
- btVector3 GetSupportVertexLocal()
- {
- return m_supportVertexLocal;
- }
-};
-
-void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
-{
- m_meshInterface->setScaling(scaling);
- recalcLocalAabb();
-}
-
-const btVector3& btTriangleMeshShape::getLocalScaling() const
-{
- return m_meshInterface->getScaling();
-}
-
-//#define DEBUG_TRIANGLE_MESH
-
-void btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- struct FilteredCallback : public btInternalTriangleIndexCallback
- {
- btTriangleCallback* m_callback;
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
-
- FilteredCallback(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax)
- : m_callback(callback),
- m_aabbMin(aabbMin),
- m_aabbMax(aabbMax)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- if (TestTriangleAgainstAabb2(&triangle[0], m_aabbMin, m_aabbMax))
- {
- //check aabb in triangle-space, before doing this
- m_callback->processTriangle(triangle, partId, triangleIndex);
- }
- }
- };
-
- FilteredCallback filterCallback(callback, aabbMin, aabbMax);
-
- m_meshInterface->InternalProcessAllTriangles(&filterCallback, aabbMin, aabbMax);
-}
-
-void btTriangleMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- (void)mass;
- //moving concave objects not supported
- btAssert(0);
- inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-}
-
-btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 supportVertex;
-
- btTransform ident;
- ident.setIdentity();
-
- SupportVertexCallback supportCallback(vec, ident);
-
- btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
-
- processAllTriangles(&supportCallback, -aabbMax, aabbMax);
-
- supportVertex = supportCallback.GetSupportVertexLocal();
-
- return supportVertex;
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
deleted file mode 100644
index 4a70e283fa..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRIANGLE_MESH_SHAPE_H
-#define BT_TRIANGLE_MESH_SHAPE_H
-
-#include "btConcaveShape.h"
-#include "btStridingMeshInterface.h"
-
-///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
-ATTRIBUTE_ALIGNED16(class)
-btTriangleMeshShape : public btConcaveShape
-{
-protected:
- btVector3 m_localAabbMin;
- btVector3 m_localAabbMax;
- btStridingMeshInterface* m_meshInterface;
-
- ///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
- ///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
- btTriangleMeshShape(btStridingMeshInterface * meshInterface);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- virtual ~btTriangleMeshShape();
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
- {
- btAssert(0);
- return localGetSupportingVertex(vec);
- }
-
- void recalcLocalAabb();
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void processAllTriangles(btTriangleCallback * callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
-
- btStridingMeshInterface* getMeshInterface()
- {
- return m_meshInterface;
- }
-
- const btStridingMeshInterface* getMeshInterface() const
- {
- return m_meshInterface;
- }
-
- const btVector3& getLocalAabbMin() const
- {
- return m_localAabbMin;
- }
- const btVector3& getLocalAabbMax() const
- {
- return m_localAabbMax;
- }
-
- //debugging
- virtual const char* getName() const { return "TRIANGLEMESH"; }
-};
-
-#endif //BT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
deleted file mode 100644
index 190cbdae69..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_OBB_TRIANGLE_MINKOWSKI_H
-#define BT_OBB_TRIANGLE_MINKOWSKI_H
-
-#include "btConvexShape.h"
-#include "btBoxShape.h"
-
-ATTRIBUTE_ALIGNED16(class)
-btTriangleShape : public btPolyhedralConvexShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 m_vertices1[3];
-
- virtual int getNumVertices() const
- {
- return 3;
- }
-
- btVector3& getVertexPtr(int index)
- {
- return m_vertices1[index];
- }
-
- const btVector3& getVertexPtr(int index) const
- {
- return m_vertices1[index];
- }
- virtual void getVertex(int index, btVector3& vert) const
- {
- vert = m_vertices1[index];
- }
-
- virtual int getNumEdges() const
- {
- return 3;
- }
-
- virtual void getEdge(int i, btVector3& pa, btVector3& pb) const
- {
- getVertex(i, pa);
- getVertex((i + 1) % 3, pb);
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- // btAssert(0);
- getAabbSlow(t, aabbMin, aabbMax);
- }
-
- btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir) const
- {
- btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
- return m_vertices1[dots.maxAxis()];
- }
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
- {
- for (int i = 0; i < numVectors; i++)
- {
- const btVector3& dir = vectors[i];
- btVector3 dots = dir.dot3(m_vertices1[0], m_vertices1[1], m_vertices1[2]);
- supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
- }
- }
-
- btTriangleShape() : btPolyhedralConvexShape()
- {
- m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
- }
-
- btTriangleShape(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btPolyhedralConvexShape()
- {
- m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
- m_vertices1[0] = p0;
- m_vertices1[1] = p1;
- m_vertices1[2] = p2;
- }
-
- virtual void getPlane(btVector3 & planeNormal, btVector3 & planeSupport, int i) const
- {
- getPlaneEquation(i, planeNormal, planeSupport);
- }
-
- virtual int getNumPlanes() const
- {
- return 1;
- }
-
- void calcNormal(btVector3 & normal) const
- {
- normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
- normal.normalize();
- }
-
- virtual void getPlaneEquation(int i, btVector3& planeNormal, btVector3& planeSupport) const
- {
- (void)i;
- calcNormal(planeNormal);
- planeSupport = m_vertices1[0];
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const
- {
- (void)mass;
- btAssert(0);
- inertia.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- }
-
- virtual bool isInside(const btVector3& pt, btScalar tolerance) const
- {
- btVector3 normal;
- calcNormal(normal);
- //distance to plane
- btScalar dist = pt.dot(normal);
- btScalar planeconst = m_vertices1[0].dot(normal);
- dist -= planeconst;
- if (dist >= -tolerance && dist <= tolerance)
- {
- //inside check on edge-planes
- int i;
- for (i = 0; i < 3; i++)
- {
- btVector3 pa, pb;
- getEdge(i, pa, pb);
- btVector3 edge = pb - pa;
- btVector3 edgeNormal = edge.cross(normal);
- edgeNormal.normalize();
- btScalar dist = pt.dot(edgeNormal);
- btScalar edgeConst = pa.dot(edgeNormal);
- dist -= edgeConst;
- if (dist < -tolerance)
- return false;
- }
-
- return true;
- }
-
- return false;
- }
- //debugging
- virtual const char* getName() const
- {
- return "Triangle";
- }
-
- virtual int getNumPreferredPenetrationDirections() const
- {
- return 2;
- }
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
- {
- calcNormal(penetrationVector);
- if (index)
- penetrationVector *= btScalar(-1.);
- }
-};
-
-#endif //BT_OBB_TRIANGLE_MINKOWSKI_H
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
deleted file mode 100644
index ed3cd2d259..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btUniformScalingShape.h"
-
-btUniformScalingShape::btUniformScalingShape(btConvexShape* convexChildShape, btScalar uniformScalingFactor) : btConvexShape(), m_childConvexShape(convexChildShape), m_uniformScalingFactor(uniformScalingFactor)
-{
- m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
-}
-
-btUniformScalingShape::~btUniformScalingShape()
-{
-}
-
-btVector3 btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
-{
- btVector3 tmpVertex;
- tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
- return tmpVertex * m_uniformScalingFactor;
-}
-
-void btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
-{
- m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors, supportVerticesOut, numVectors);
- int i;
- for (i = 0; i < numVectors; i++)
- {
- supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
- }
-}
-
-btVector3 btUniformScalingShape::localGetSupportingVertex(const btVector3& vec) const
-{
- btVector3 tmpVertex;
- tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
- return tmpVertex * m_uniformScalingFactor;
-}
-
-void btUniformScalingShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- ///this linear upscaling is not realistic, but we don't deal with large mass ratios...
- btVector3 tmpInertia;
- m_childConvexShape->calculateLocalInertia(mass, tmpInertia);
- inertia = tmpInertia * m_uniformScalingFactor;
-}
-
-///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
-void btUniformScalingShape::getAabb(const btTransform& trans, btVector3& aabbMin, btVector3& aabbMax) const
-{
- getAabbSlow(trans, aabbMin, aabbMax);
-}
-
-void btUniformScalingShape::getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
-{
-#if 1
- btVector3 _directions[] =
- {
- btVector3(1., 0., 0.),
- btVector3(0., 1., 0.),
- btVector3(0., 0., 1.),
- btVector3(-1., 0., 0.),
- btVector3(0., -1., 0.),
- btVector3(0., 0., -1.)};
-
- btVector3 _supporting[] =
- {
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.),
- btVector3(0., 0., 0.)};
-
- for (int i = 0; i < 6; i++)
- {
- _directions[i] = _directions[i] * t.getBasis();
- }
-
- batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
-
- btVector3 aabbMin1(0, 0, 0), aabbMax1(0, 0, 0);
-
- for (int i = 0; i < 3; ++i)
- {
- aabbMax1[i] = t(_supporting[i])[i];
- aabbMin1[i] = t(_supporting[i + 3])[i];
- }
- btVector3 marginVec(getMargin(), getMargin(), getMargin());
- aabbMin = aabbMin1 - marginVec;
- aabbMax = aabbMax1 + marginVec;
-
-#else
-
- btScalar margin = getMargin();
- for (int i = 0; i < 3; i++)
- {
- btVector3 vec(btScalar(0.), btScalar(0.), btScalar(0.));
- vec[i] = btScalar(1.);
- btVector3 sv = localGetSupportingVertex(vec * t.getBasis());
- btVector3 tmp = t(sv);
- aabbMax[i] = tmp[i] + margin;
- vec[i] = btScalar(-1.);
- sv = localGetSupportingVertex(vec * t.getBasis());
- tmp = t(sv);
- aabbMin[i] = tmp[i] - margin;
- }
-
-#endif
-}
-
-void btUniformScalingShape::setLocalScaling(const btVector3& scaling)
-{
- m_childConvexShape->setLocalScaling(scaling);
-}
-
-const btVector3& btUniformScalingShape::getLocalScaling() const
-{
- return m_childConvexShape->getLocalScaling();
-}
-
-void btUniformScalingShape::setMargin(btScalar margin)
-{
- m_childConvexShape->setMargin(margin);
-}
-btScalar btUniformScalingShape::getMargin() const
-{
- return m_childConvexShape->getMargin() * m_uniformScalingFactor;
-}
-
-int btUniformScalingShape::getNumPreferredPenetrationDirections() const
-{
- return m_childConvexShape->getNumPreferredPenetrationDirections();
-}
-
-void btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
-{
- m_childConvexShape->getPreferredPenetrationDirection(index, penetrationVector);
-}
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h b/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
deleted file mode 100644
index 4dfe34efbd..0000000000
--- a/thirdparty/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_UNIFORM_SCALING_SHAPE_H
-#define BT_UNIFORM_SCALING_SHAPE_H
-
-#include "btConvexShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
-
-///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
-///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
-ATTRIBUTE_ALIGNED16(class)
-btUniformScalingShape : public btConvexShape
-{
- btConvexShape* m_childConvexShape;
-
- btScalar m_uniformScalingFactor;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btUniformScalingShape(btConvexShape * convexChildShape, btScalar uniformScalingFactor);
-
- virtual ~btUniformScalingShape();
-
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
-
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const;
-
- virtual void calculateLocalInertia(btScalar mass, btVector3 & inertia) const;
-
- btScalar getUniformScalingFactor() const
- {
- return m_uniformScalingFactor;
- }
-
- btConvexShape* getChildShape()
- {
- return m_childConvexShape;
- }
-
- const btConvexShape* getChildShape() const
- {
- return m_childConvexShape;
- }
-
- virtual const char* getName() const
- {
- return "UniformScalingShape";
- }
-
- ///////////////////////////
-
- ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void getAabbSlow(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
-
- virtual void setLocalScaling(const btVector3& scaling);
- virtual const btVector3& getLocalScaling() const;
-
- virtual void setMargin(btScalar margin);
- virtual btScalar getMargin() const;
-
- virtual int getNumPreferredPenetrationDirections() const;
-
- virtual void getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
-};
-
-#endif //BT_UNIFORM_SCALING_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h b/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h
deleted file mode 100644
index 182835c3b4..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btBoxCollision.h
+++ /dev/null
@@ -1,620 +0,0 @@
-#ifndef BT_BOX_COLLISION_H_INCLUDED
-#define BT_BOX_COLLISION_H_INCLUDED
-
-/*! \file gim_box_collision.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btTransform.h"
-
-///Swap numbers
-#define BT_SWAP_NUMBERS(a, b) \
- { \
- a = a + b; \
- b = a - b; \
- a = a - b; \
- }
-
-#define BT_MAX(a, b) (a < b ? b : a)
-#define BT_MIN(a, b) (a > b ? b : a)
-
-#define BT_GREATER(x, y) btFabs(x) > (y)
-
-#define BT_MAX3(a, b, c) BT_MAX(a, BT_MAX(b, c))
-#define BT_MIN3(a, b, c) BT_MIN(a, BT_MIN(b, c))
-
-enum eBT_PLANE_INTERSECTION_TYPE
-{
- BT_CONST_BACK_PLANE = 0,
- BT_CONST_COLLIDE_PLANE,
- BT_CONST_FRONT_PLANE
-};
-
-//SIMD_FORCE_INLINE bool test_cross_edge_box(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, const btVector3 & extend,
-// int dir_index0,
-// int dir_index1
-// int component_index0,
-// int component_index1)
-//{
-// // dir coords are -z and y
-//
-// const btScalar dir0 = -edge[dir_index0];
-// const btScalar dir1 = edge[dir_index1];
-// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
-// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
-// //find minmax
-// if(pmin>pmax)
-// {
-// BT_SWAP_NUMBERS(pmin,pmax);
-// }
-// //find extends
-// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
-// extend[component_index1] * absolute_edge[dir_index1];
-//
-// if(pmin>rad || -rad>pmax) return false;
-// return true;
-//}
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
-//}
-//
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
-//}
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
-//}
-
-#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
- { \
- const btScalar dir0 = -edge[i_dir_0]; \
- const btScalar dir1 = edge[i_dir_1]; \
- btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1; \
- btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1; \
- if (pmin > pmax) \
- { \
- BT_SWAP_NUMBERS(pmin, pmax); \
- } \
- const btScalar abs_dir0 = absolute_edge[i_dir_0]; \
- const btScalar abs_dir1 = absolute_edge[i_dir_1]; \
- const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1; \
- if (pmin > rad || -rad > pmax) return false; \
- }
-
-#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
- }
-
-#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
- }
-
-#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
- }
-
-//! Returns the dot product between a vec3f and the col of a matrix
-SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
- const btMatrix3x3 &mat, const btVector3 &vec3, int colindex)
-{
- return vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex];
-}
-
-//! Class for transforming a model1 to the space of model0
-ATTRIBUTE_ALIGNED16(class)
-BT_BOX_BOX_TRANSFORM_CACHE
-{
-public:
- btVector3 m_T1to0; //!< Transforms translation of model1 to model 0
- btMatrix3x3 m_R1to0; //!< Transforms Rotation of model1 to model 0, equal to R0' * R1
- btMatrix3x3 m_AR; //!< Absolute value of m_R1to0
-
- SIMD_FORCE_INLINE void calc_absolute_matrix()
- {
- // static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
- // m_AR[0] = vepsi + m_R1to0[0].absolute();
- // m_AR[1] = vepsi + m_R1to0[1].absolute();
- // m_AR[2] = vepsi + m_R1to0[2].absolute();
-
- int i, j;
-
- for (i = 0; i < 3; i++)
- {
- for (j = 0; j < 3; j++)
- {
- m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
- }
- }
- }
-
- BT_BOX_BOX_TRANSFORM_CACHE()
- {
- }
-
- //! Calc the transformation relative 1 to 0. Inverts matrics by transposing
- SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
- {
- btTransform temp_trans = trans0.inverse();
- temp_trans = temp_trans * trans1;
-
- m_T1to0 = temp_trans.getOrigin();
- m_R1to0 = temp_trans.getBasis();
-
- calc_absolute_matrix();
- }
-
- //! Calcs the full invertion of the matrices. Useful for scaling matrices
- SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
- {
- m_R1to0 = trans0.getBasis().inverse();
- m_T1to0 = m_R1to0 * (-trans0.getOrigin());
-
- m_T1to0 += m_R1to0 * trans1.getOrigin();
- m_R1to0 *= trans1.getBasis();
-
- calc_absolute_matrix();
- }
-
- SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
- {
- return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
- }
-};
-
-#define BOX_PLANE_EPSILON 0.000001f
-
-//! Axis aligned box
-ATTRIBUTE_ALIGNED16(class)
-btAABB
-{
-public:
- btVector3 m_min;
- btVector3 m_max;
-
- btAABB()
- {
- }
-
- btAABB(const btVector3 &V1,
- const btVector3 &V2,
- const btVector3 &V3)
- {
- m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
- }
-
- btAABB(const btVector3 &V1,
- const btVector3 &V2,
- const btVector3 &V3,
- btScalar margin)
- {
- m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
-
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- btAABB(const btAABB &other) : m_min(other.m_min), m_max(other.m_max)
- {
- }
-
- btAABB(const btAABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
- {
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- SIMD_FORCE_INLINE void invalidate()
- {
- m_min[0] = SIMD_INFINITY;
- m_min[1] = SIMD_INFINITY;
- m_min[2] = SIMD_INFINITY;
- m_max[0] = -SIMD_INFINITY;
- m_max[1] = -SIMD_INFINITY;
- m_max[2] = -SIMD_INFINITY;
- }
-
- SIMD_FORCE_INLINE void increment_margin(btScalar margin)
- {
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
- {
- m_min[0] = other.m_min[0] - margin;
- m_min[1] = other.m_min[1] - margin;
- m_min[2] = other.m_min[2] - margin;
-
- m_max[0] = other.m_max[0] + margin;
- m_max[1] = other.m_max[1] + margin;
- m_max[2] = other.m_max[2] + margin;
- }
-
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void calc_from_triangle(
- const CLASS_POINT &V1,
- const CLASS_POINT &V2,
- const CLASS_POINT &V3)
- {
- m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
- }
-
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void calc_from_triangle_margin(
- const CLASS_POINT &V1,
- const CLASS_POINT &V2,
- const CLASS_POINT &V3, btScalar margin)
- {
- m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
-
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- //! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
- {
- btVector3 center = (m_max + m_min) * 0.5f;
- btVector3 extends = m_max - center;
- // Compute new center
- center = trans(center);
-
- btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
- trans.getBasis().getRow(1).absolute(),
- trans.getBasis().getRow(2).absolute());
-
- m_min = center - textends;
- m_max = center + textends;
- }
-
- //! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE &trans)
- {
- btVector3 center = (m_max + m_min) * 0.5f;
- btVector3 extends = m_max - center;
- // Compute new center
- center = trans.transform(center);
-
- btVector3 textends = extends.dot3(trans.m_R1to0.getRow(0).absolute(),
- trans.m_R1to0.getRow(1).absolute(),
- trans.m_R1to0.getRow(2).absolute());
-
- m_min = center - textends;
- m_max = center + textends;
- }
-
- //! Merges a Box
- SIMD_FORCE_INLINE void merge(const btAABB &box)
- {
- m_min[0] = BT_MIN(m_min[0], box.m_min[0]);
- m_min[1] = BT_MIN(m_min[1], box.m_min[1]);
- m_min[2] = BT_MIN(m_min[2], box.m_min[2]);
-
- m_max[0] = BT_MAX(m_max[0], box.m_max[0]);
- m_max[1] = BT_MAX(m_max[1], box.m_max[1]);
- m_max[2] = BT_MAX(m_max[2], box.m_max[2]);
- }
-
- //! Merges a point
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
- {
- m_min[0] = BT_MIN(m_min[0], point[0]);
- m_min[1] = BT_MIN(m_min[1], point[1]);
- m_min[2] = BT_MIN(m_min[2], point[2]);
-
- m_max[0] = BT_MAX(m_max[0], point[0]);
- m_max[1] = BT_MAX(m_max[1], point[1]);
- m_max[2] = BT_MAX(m_max[2], point[2]);
- }
-
- //! Gets the extend and center
- SIMD_FORCE_INLINE void get_center_extend(btVector3 & center, btVector3 & extend) const
- {
- center = (m_max + m_min) * 0.5f;
- extend = m_max - center;
- }
-
- //! Finds the intersecting box between this box and the other.
- SIMD_FORCE_INLINE void find_intersection(const btAABB &other, btAABB &intersection) const
- {
- intersection.m_min[0] = BT_MAX(other.m_min[0], m_min[0]);
- intersection.m_min[1] = BT_MAX(other.m_min[1], m_min[1]);
- intersection.m_min[2] = BT_MAX(other.m_min[2], m_min[2]);
-
- intersection.m_max[0] = BT_MIN(other.m_max[0], m_max[0]);
- intersection.m_max[1] = BT_MIN(other.m_max[1], m_max[1]);
- intersection.m_max[2] = BT_MIN(other.m_max[2], m_max[2]);
- }
-
- SIMD_FORCE_INLINE bool has_collision(const btAABB &other) const
- {
- if (m_min[0] > other.m_max[0] ||
- m_max[0] < other.m_min[0] ||
- m_min[1] > other.m_max[1] ||
- m_max[1] < other.m_min[1] ||
- m_min[2] > other.m_max[2] ||
- m_max[2] < other.m_min[2])
- {
- return false;
- }
- return true;
- }
-
- /*! \brief Finds the Ray intersection parameter.
- \param aabb Aligned box
- \param vorigin A vec3f with the origin of the ray
- \param vdir A vec3f with the direction of the ray
- */
- SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir) const
- {
- btVector3 extents, center;
- this->get_center_extend(center, extents);
- ;
-
- btScalar Dx = vorigin[0] - center[0];
- if (BT_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
- btScalar Dy = vorigin[1] - center[1];
- if (BT_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
- btScalar Dz = vorigin[2] - center[2];
- if (BT_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
-
- btScalar f = vdir[1] * Dz - vdir[2] * Dy;
- if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
- f = vdir[2] * Dx - vdir[0] * Dz;
- if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
- f = vdir[0] * Dy - vdir[1] * Dx;
- if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
- return true;
- }
-
- SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
- {
- btVector3 center = (m_max + m_min) * 0.5f;
- btVector3 extend = m_max - center;
-
- btScalar _fOrigin = direction.dot(center);
- btScalar _fMaximumExtent = extend.dot(direction.absolute());
- vmin = _fOrigin - _fMaximumExtent;
- vmax = _fOrigin + _fMaximumExtent;
- }
-
- SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
- {
- btScalar _fmin, _fmax;
- this->projection_interval(plane, _fmin, _fmax);
-
- if (plane[3] > _fmax + BOX_PLANE_EPSILON)
- {
- return BT_CONST_BACK_PLANE; // 0
- }
-
- if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
- {
- return BT_CONST_COLLIDE_PLANE; //1
- }
- return BT_CONST_FRONT_PLANE; //2
- }
-
- SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB &box, btTransform &trans1_to_0) const
- {
- btAABB tbox = box;
- tbox.appy_transform(trans1_to_0);
- return has_collision(tbox);
- }
-
- SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB &box,
- const BT_BOX_BOX_TRANSFORM_CACHE &trans1_to_0) const
- {
- btAABB tbox = box;
- tbox.appy_transform_trans_cache(trans1_to_0);
- return has_collision(tbox);
- }
-
- //! transcache is the transformation cache from box to this AABB
- SIMD_FORCE_INLINE bool overlapping_trans_cache(
- const btAABB &box, const BT_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest) const
- {
- //Taken from OPCODE
- btVector3 ea, eb; //extends
- btVector3 ca, cb; //extends
- get_center_extend(ca, ea);
- box.get_center_extend(cb, eb);
-
- btVector3 T;
- btScalar t, t2;
- int i;
-
- // Class I : A's basis vectors
- for (i = 0; i < 3; i++)
- {
- T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
- t = transcache.m_AR[i].dot(eb) + ea[i];
- if (BT_GREATER(T[i], t)) return false;
- }
- // Class II : B's basis vectors
- for (i = 0; i < 3; i++)
- {
- t = bt_mat3_dot_col(transcache.m_R1to0, T, i);
- t2 = bt_mat3_dot_col(transcache.m_AR, ea, i) + eb[i];
- if (BT_GREATER(t, t2)) return false;
- }
- // Class III : 9 cross products
- if (fulltest)
- {
- int j, m, n, o, p, q, r;
- for (i = 0; i < 3; i++)
- {
- m = (i + 1) % 3;
- n = (i + 2) % 3;
- o = i == 0 ? 1 : 0;
- p = i == 2 ? 1 : 2;
- for (j = 0; j < 3; j++)
- {
- q = j == 2 ? 1 : 2;
- r = j == 0 ? 1 : 0;
- t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
- t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
- eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
- if (BT_GREATER(t, t2)) return false;
- }
- }
- }
- return true;
- }
-
- //! Simple test for planes.
- SIMD_FORCE_INLINE bool collide_plane(
- const btVector4 &plane) const
- {
- eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
- return (classify == BT_CONST_COLLIDE_PLANE);
- }
-
- //! test for a triangle, with edges
- SIMD_FORCE_INLINE bool collide_triangle_exact(
- const btVector3 &p1,
- const btVector3 &p2,
- const btVector3 &p3,
- const btVector4 &triangle_plane) const
- {
- if (!collide_plane(triangle_plane)) return false;
-
- btVector3 center, extends;
- this->get_center_extend(center, extends);
-
- const btVector3 v1(p1 - center);
- const btVector3 v2(p2 - center);
- const btVector3 v3(p3 - center);
-
- //First axis
- btVector3 diff(v2 - v1);
- btVector3 abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
-
- diff = v3 - v2;
- abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
-
- diff = v1 - v3;
- abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
-
- return true;
- }
-};
-
-//! Compairison of transformation objects
-SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
-{
- if (!(t1.getOrigin() == t2.getOrigin())) return false;
-
- if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
- if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
- if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
- return true;
-}
-
-#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h b/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h
deleted file mode 100644
index 38c23e222d..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btClipPolygon.h
+++ /dev/null
@@ -1,173 +0,0 @@
-#ifndef BT_CLIP_POLYGON_H_INCLUDED
-#define BT_CLIP_POLYGON_H_INCLUDED
-
-/*! \file btClipPolygon.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btGeometryUtil.h"
-
-SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 &plane, const btVector3 &point)
-{
- return point.dot(plane) - plane[3];
-}
-
-/*! Vector blending
-Takes two vectors a, b, blends them together*/
-SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va, const btVector3 &vb, btScalar blend_factor)
-{
- vr = (1 - blend_factor) * va + blend_factor * vb;
-}
-
-//! This function calcs the distance from a 3D plane
-SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
- const btVector3 &point0,
- const btVector3 &point1,
- btScalar dist0,
- btScalar dist1,
- btVector3 *clipped,
- int &clipped_count)
-{
- bool _prevclassif = (dist0 > SIMD_EPSILON);
- bool _classif = (dist1 > SIMD_EPSILON);
- if (_classif != _prevclassif)
- {
- btScalar blendfactor = -dist0 / (dist1 - dist0);
- bt_vec_blend(clipped[clipped_count], point0, point1, blendfactor);
- clipped_count++;
- }
- if (!_classif)
- {
- clipped[clipped_count] = point1;
- clipped_count++;
- }
-}
-
-//! Clips a polygon by a plane
-/*!
-*\return The count of the clipped counts
-*/
-SIMD_FORCE_INLINE int bt_plane_clip_polygon(
- const btVector4 &plane,
- const btVector3 *polygon_points,
- int polygon_point_count,
- btVector3 *clipped)
-{
- int clipped_count = 0;
-
- //clip first point
- btScalar firstdist = bt_distance_point_plane(plane, polygon_points[0]);
- ;
- if (!(firstdist > SIMD_EPSILON))
- {
- clipped[clipped_count] = polygon_points[0];
- clipped_count++;
- }
-
- btScalar olddist = firstdist;
- for (int i = 1; i < polygon_point_count; i++)
- {
- btScalar dist = bt_distance_point_plane(plane, polygon_points[i]);
-
- bt_plane_clip_polygon_collect(
- polygon_points[i - 1], polygon_points[i],
- olddist,
- dist,
- clipped,
- clipped_count);
-
- olddist = dist;
- }
-
- //RETURN TO FIRST point
-
- bt_plane_clip_polygon_collect(
- polygon_points[polygon_point_count - 1], polygon_points[0],
- olddist,
- firstdist,
- clipped,
- clipped_count);
-
- return clipped_count;
-}
-
-//! Clips a polygon by a plane
-/*!
-*\param clipped must be an array of 16 points.
-*\return The count of the clipped counts
-*/
-SIMD_FORCE_INLINE int bt_plane_clip_triangle(
- const btVector4 &plane,
- const btVector3 &point0,
- const btVector3 &point1,
- const btVector3 &point2,
- btVector3 *clipped // an allocated array of 16 points at least
-)
-{
- int clipped_count = 0;
-
- //clip first point0
- btScalar firstdist = bt_distance_point_plane(plane, point0);
- ;
- if (!(firstdist > SIMD_EPSILON))
- {
- clipped[clipped_count] = point0;
- clipped_count++;
- }
-
- // point 1
- btScalar olddist = firstdist;
- btScalar dist = bt_distance_point_plane(plane, point1);
-
- bt_plane_clip_polygon_collect(
- point0, point1,
- olddist,
- dist,
- clipped,
- clipped_count);
-
- olddist = dist;
-
- // point 2
- dist = bt_distance_point_plane(plane, point2);
-
- bt_plane_clip_polygon_collect(
- point1, point2,
- olddist,
- dist,
- clipped,
- clipped_count);
- olddist = dist;
-
- //RETURN TO FIRST point0
- bt_plane_clip_polygon_collect(
- point2, point0,
- olddist,
- firstdist,
- clipped,
- clipped_count);
-
- return clipped_count;
-}
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h b/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
deleted file mode 100644
index ede59e8a57..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef BT_COMPOUND_FROM_GIMPACT
-#define BT_COMPOUND_FROM_GIMPACT
-
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "btGImpactShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-
-ATTRIBUTE_ALIGNED16(class)
-btCompoundFromGimpactShape : public btCompoundShape
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- virtual ~btCompoundFromGimpactShape()
- {
- /*delete all the btBU_Simplex1to4 ChildShapes*/
- for (int i = 0; i < m_children.size(); i++)
- {
- delete m_children[i].m_childShape;
- }
- }
-};
-
-struct MyCallback : public btTriangleRaycastCallback
-{
- int m_ignorePart;
- int m_ignoreTriangleIndex;
-
- MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex)
- : btTriangleRaycastCallback(from, to),
- m_ignorePart(ignorePart),
- m_ignoreTriangleIndex(ignoreTriangleIndex)
- {
- }
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex)
- {
- if (partId != m_ignorePart || triangleIndex != m_ignoreTriangleIndex)
- {
- if (hitFraction < m_hitFraction)
- return hitFraction;
- }
-
- return m_hitFraction;
- }
-};
-struct MyInternalTriangleIndexCallback : public btInternalTriangleIndexCallback
-{
- const btGImpactMeshShape* m_gimpactShape;
- btCompoundShape* m_colShape;
- btScalar m_depth;
-
- MyInternalTriangleIndexCallback(btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth)
- : m_colShape(colShape),
- m_gimpactShape(meshShape),
- m_depth(depth)
- {
- }
-
- virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
- {
- btVector3 scale = m_gimpactShape->getLocalScaling();
- btVector3 v0 = triangle[0] * scale;
- btVector3 v1 = triangle[1] * scale;
- btVector3 v2 = triangle[2] * scale;
-
- btVector3 centroid = (v0 + v1 + v2) / 3;
- btVector3 normal = (v1 - v0).cross(v2 - v0);
- normal.normalize();
- btVector3 rayFrom = centroid;
- btVector3 rayTo = centroid - normal * m_depth;
-
- MyCallback cb(rayFrom, rayTo, partId, triangleIndex);
-
- m_gimpactShape->processAllTrianglesRay(&cb, rayFrom, rayTo);
- if (cb.m_hitFraction < 1)
- {
- rayTo.setInterpolate3(cb.m_from, cb.m_to, cb.m_hitFraction);
- //rayTo = cb.m_from;
- //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction);
- //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0));
- }
-
- btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0, v1, v2, rayTo);
- btTransform ident;
- ident.setIdentity();
- m_colShape->addChildShape(ident, tet);
- }
-};
-
-btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth)
-{
- btCompoundShape* colShape = new btCompoundFromGimpactShape();
-
- btTransform tr;
- tr.setIdentity();
-
- MyInternalTriangleIndexCallback cb(colShape, gimpactMesh, depth);
- btVector3 aabbMin, aabbMax;
- gimpactMesh->getAabb(tr, aabbMin, aabbMax);
- gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb, aabbMin, aabbMax);
-
- return colShape;
-}
-
-#endif //BT_COMPOUND_FROM_GIMPACT
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp
deleted file mode 100644
index f2e3e18d61..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include "btContactProcessing.h"
-
-#define MAX_COINCIDENT 8
-
-struct CONTACT_KEY_TOKEN
-{
- unsigned int m_key;
- int m_value;
- CONTACT_KEY_TOKEN()
- {
- }
-
- CONTACT_KEY_TOKEN(unsigned int key, int token)
- {
- m_key = key;
- m_value = token;
- }
-
- CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
- {
- m_key = rtoken.m_key;
- m_value = rtoken.m_value;
- }
-
- inline bool operator<(const CONTACT_KEY_TOKEN& other) const
- {
- return (m_key < other.m_key);
- }
-
- inline bool operator>(const CONTACT_KEY_TOKEN& other) const
- {
- return (m_key > other.m_key);
- }
-};
-
-class CONTACT_KEY_TOKEN_COMP
-{
-public:
- bool operator()(const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b) const
- {
- return (a < b);
- }
-};
-
-void btContactArray::merge_contacts(
- const btContactArray& contacts, bool normal_contact_average)
-{
- clear();
-
- int i;
- if (contacts.size() == 0) return;
-
- if (contacts.size() == 1)
- {
- push_back(contacts[0]);
- return;
- }
-
- btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
-
- keycontacts.reserve(contacts.size());
-
- //fill key contacts
-
- for (i = 0; i < contacts.size(); i++)
- {
- keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(), i));
- }
-
- //sort keys
- keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
-
- // Merge contacts
- int coincident_count = 0;
- btVector3 coincident_normals[MAX_COINCIDENT];
-
- unsigned int last_key = keycontacts[0].m_key;
- unsigned int key = 0;
-
- push_back(contacts[keycontacts[0].m_value]);
-
- GIM_CONTACT* pcontact = &(*this)[0];
-
- for (i = 1; i < keycontacts.size(); i++)
- {
- key = keycontacts[i].m_key;
- const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
-
- if (last_key == key) //same points
- {
- //merge contact
- if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth) //)
- {
- *pcontact = *scontact;
- coincident_count = 0;
- }
- else if (normal_contact_average)
- {
- if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
- {
- if (coincident_count < MAX_COINCIDENT)
- {
- coincident_normals[coincident_count] = scontact->m_normal;
- coincident_count++;
- }
- }
- }
- }
- else
- { //add new contact
-
- if (normal_contact_average && coincident_count > 0)
- {
- pcontact->interpolate_normals(coincident_normals, coincident_count);
- coincident_count = 0;
- }
-
- push_back(*scontact);
- pcontact = &(*this)[this->size() - 1];
- }
- last_key = key;
- }
-}
-
-void btContactArray::merge_contacts_unique(const btContactArray& contacts)
-{
- clear();
-
- if (contacts.size() == 0) return;
-
- if (contacts.size() == 1)
- {
- push_back(contacts[0]);
- return;
- }
-
- GIM_CONTACT average_contact = contacts[0];
-
- for (int i = 1; i < contacts.size(); i++)
- {
- average_contact.m_point += contacts[i].m_point;
- average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
- }
-
- //divide
- btScalar divide_average = 1.0f / ((btScalar)contacts.size());
-
- average_contact.m_point *= divide_average;
-
- average_contact.m_normal *= divide_average;
-
- average_contact.m_depth = average_contact.m_normal.length();
-
- average_contact.m_normal /= average_contact.m_depth;
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h
deleted file mode 100644
index 4ff09d7cdd..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessing.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef BT_CONTACT_H_INCLUDED
-#define BT_CONTACT_H_INCLUDED
-
-/*! \file gim_contact.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "btTriangleShapeEx.h"
-#include "btContactProcessingStructs.h"
-
-class btContactArray : public btAlignedObjectArray<GIM_CONTACT>
-{
-public:
- btContactArray()
- {
- reserve(64);
- }
-
- SIMD_FORCE_INLINE void push_contact(
- const btVector3 &point, const btVector3 &normal,
- btScalar depth, int feature1, int feature2)
- {
- push_back(GIM_CONTACT(point, normal, depth, feature1, feature2));
- }
-
- SIMD_FORCE_INLINE void push_triangle_contacts(
- const GIM_TRIANGLE_CONTACT &tricontact,
- int feature1, int feature2)
- {
- for (int i = 0; i < tricontact.m_point_count; i++)
- {
- push_contact(
- tricontact.m_points[i],
- tricontact.m_separating_normal,
- tricontact.m_penetration_depth, feature1, feature2);
- }
- }
-
- void merge_contacts(const btContactArray &contacts, bool normal_contact_average = true);
-
- void merge_contacts_unique(const btContactArray &contacts);
-};
-
-#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h
deleted file mode 100644
index bc8a709246..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btContactProcessingStructs.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
-#define BT_CONTACT_H_STRUCTS_INCLUDED
-
-/*! \file gim_contact.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "btTriangleShapeEx.h"
-
-/**
-Configuration var for applying interpolation of contact normals
-*/
-#define NORMAL_CONTACT_AVERAGE 1
-
-#define CONTACT_DIFF_EPSILON 0.00001f
-
-///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
-///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
-class GIM_CONTACT
-{
-public:
- btVector3 m_point;
- btVector3 m_normal;
- btScalar m_depth; //Positive value indicates interpenetration
- btScalar m_distance; //Padding not for use
- int m_feature1; //Face number
- int m_feature2; //Face number
-public:
- GIM_CONTACT()
- {
- }
-
- GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
- m_normal(contact.m_normal),
- m_depth(contact.m_depth),
- m_feature1(contact.m_feature1),
- m_feature2(contact.m_feature2)
- {
- }
-
- GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
- btScalar depth, int feature1, int feature2) : m_point(point),
- m_normal(normal),
- m_depth(depth),
- m_feature1(feature1),
- m_feature2(feature2)
- {
- }
-
- //! Calcs key for coord classification
- SIMD_FORCE_INLINE unsigned int calc_key_contact() const
- {
- int _coords[] = {
- (int)(m_point[0] * 1000.0f + 1.0f),
- (int)(m_point[1] * 1333.0f),
- (int)(m_point[2] * 2133.0f + 3.0f)};
- unsigned int _hash = 0;
- unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
- _hash = *_uitmp;
- _uitmp++;
- _hash += (*_uitmp) << 4;
- _uitmp++;
- _hash += (*_uitmp) << 8;
- return _hash;
- }
-
- SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, int normal_count)
- {
- btVector3 vec_sum(m_normal);
- for (int i = 0; i < normal_count; i++)
- {
- vec_sum += normals[i];
- }
-
- btScalar vec_sum_len = vec_sum.length2();
- if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
-
- //GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
-
- m_normal = vec_sum / btSqrt(vec_sum_len);
- }
-};
-
-#endif // BT_CONTACT_H_STRUCTS_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
deleted file mode 100644
index bb520e061d..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.cpp
+++ /dev/null
@@ -1,464 +0,0 @@
-/*! \file gim_box_set.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#include "btGImpactBvh.h"
-#include "LinearMath/btQuickprof.h"
-
-#ifdef TRI_COLLISION_PROFILING
-
-btClock g_tree_clock;
-
-float g_accum_tree_collision_time = 0;
-int g_count_traversing = 0;
-
-void bt_begin_gim02_tree_time()
-{
- g_tree_clock.reset();
-}
-
-void bt_end_gim02_tree_time()
-{
- g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
- g_count_traversing++;
-}
-
-//! Gets the average time in miliseconds of tree collisions
-float btGImpactBvh::getAverageTreeCollisionTime()
-{
- if (g_count_traversing == 0) return 0;
-
- float avgtime = g_accum_tree_collision_time;
- avgtime /= (float)g_count_traversing;
-
- g_accum_tree_collision_time = 0;
- g_count_traversing = 0;
- return avgtime;
-
- // float avgtime = g_count_traversing;
- // g_count_traversing = 0;
- // return avgtime;
-}
-
-#endif //TRI_COLLISION_PROFILING
-
-/////////////////////// btBvhTree /////////////////////////////////
-
-int btBvhTree::_calc_splitting_axis(
- GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
-{
- int i;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
- int numIndices = endIndex - startIndex;
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
-
- return variance.maxAxis();
-}
-
-int btBvhTree::_sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
- int endIndex, int splitAxis)
-{
- int i;
- int splitIndex = startIndex;
- int numIndices = endIndex - startIndex;
-
- // average of centers
- btScalar splitValue = 0.0f;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- splitValue = means[splitAxis];
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- if (center[splitAxis] > splitValue)
- {
- //swap
- primitive_boxes.swap(i, splitIndex);
- //swapLeafNodes(i,splitIndex);
- splitIndex++;
- }
- }
-
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
-
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
-
- //this should be safe too:
- int rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
-
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
-
- btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
-
- return splitIndex;
-}
-
-void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
-{
- int curIndex = m_num_nodes;
- m_num_nodes++;
-
- btAssert((endIndex - startIndex) > 0);
-
- if ((endIndex - startIndex) == 1)
- {
- //We have a leaf node
- setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
- m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
-
- return;
- }
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- //split axis
- int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
-
- splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes, startIndex, endIndex,
- splitIndex //split axis
- );
-
- //calc this node bounding box
-
- btAABB node_bound;
- node_bound.invalidate();
-
- for (int i = startIndex; i < endIndex; i++)
- {
- node_bound.merge(primitive_boxes[i].m_bound);
- }
-
- setNodeBound(curIndex, node_bound);
-
- //build left branch
- _build_sub_tree(primitive_boxes, startIndex, splitIndex);
-
- //build right branch
- _build_sub_tree(primitive_boxes, splitIndex, endIndex);
-
- m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
-}
-
-//! stackless build tree
-void btBvhTree::build_tree(
- GIM_BVH_DATA_ARRAY& primitive_boxes)
-{
- // initialize node count to 0
- m_num_nodes = 0;
- // allocate nodes
- m_node_array.resize(primitive_boxes.size() * 2);
-
- _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
-}
-
-////////////////////////////////////class btGImpactBvh
-
-void btGImpactBvh::refit()
-{
- int nodecount = getNodeCount();
- while (nodecount--)
- {
- if (isLeafNode(nodecount))
- {
- btAABB leafbox;
- m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
- setNodeBound(nodecount, leafbox);
- }
- else
- {
- //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
- //get left bound
- btAABB bound;
- bound.invalidate();
-
- btAABB temp_box;
-
- int child_node = getLeftNode(nodecount);
- if (child_node)
- {
- getNodeBound(child_node, temp_box);
- bound.merge(temp_box);
- }
-
- child_node = getRightNode(nodecount);
- if (child_node)
- {
- getNodeBound(child_node, temp_box);
- bound.merge(temp_box);
- }
-
- setNodeBound(nodecount, bound);
- }
- }
-}
-
-//! this rebuild the entire set
-void btGImpactBvh::buildSet()
-{
- //obtain primitive boxes
- GIM_BVH_DATA_ARRAY primitive_boxes;
- primitive_boxes.resize(m_primitive_manager->get_primitive_count());
-
- for (int i = 0; i < primitive_boxes.size(); i++)
- {
- m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
- }
-
- m_box_tree.build_tree(primitive_boxes);
-}
-
-//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
-{
- int curIndex = 0;
- int numNodes = getNodeCount();
-
- while (curIndex < numNodes)
- {
- btAABB bound;
- getNodeBound(curIndex, bound);
-
- //catch bugs in tree data
-
- bool aabbOverlap = bound.has_collision(box);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getEscapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
-}
-
-//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactBvh::rayQuery(
- const btVector3& ray_dir, const btVector3& ray_origin,
- btAlignedObjectArray<int>& collided_results) const
-{
- int curIndex = 0;
- int numNodes = getNodeCount();
-
- while (curIndex < numNodes)
- {
- btAABB bound;
- getNodeBound(curIndex, bound);
-
- //catch bugs in tree data
-
- bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getEscapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
-}
-
-SIMD_FORCE_INLINE bool _node_collision(
- btGImpactBvh* boxset0, btGImpactBvh* boxset1,
- const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
- int node0, int node1, bool complete_primitive_tests)
-{
- btAABB box0;
- boxset0->getNodeBound(node0, box0);
- btAABB box1;
- boxset1->getNodeBound(node1, box1);
-
- return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
- // box1.appy_transform_trans_cache(trans_cache_1to0);
- // return box0.has_collision(box1);
-}
-
-//stackless recursive collision routine
-static void _find_collision_pairs_recursive(
- btGImpactBvh* boxset0, btGImpactBvh* boxset1,
- btPairSet* collision_pairs,
- const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
- int node0, int node1, bool complete_primitive_tests)
-{
- if (_node_collision(
- boxset0, boxset1, trans_cache_1to0,
- node0, node1, complete_primitive_tests) == false) return; //avoid colliding internal nodes
-
- if (boxset0->isLeafNode(node0))
- {
- if (boxset1->isLeafNode(node1))
- {
- // collision result
- collision_pairs->push_pair(
- boxset0->getNodeData(node0), boxset1->getNodeData(node1));
- return;
- }
- else
- {
- //collide left recursive
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- node0, boxset1->getLeftNode(node1), false);
-
- //collide right recursive
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- node0, boxset1->getRightNode(node1), false);
- }
- }
- else
- {
- if (boxset1->isLeafNode(node1))
- {
- //collide left recursive
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), node1, false);
-
- //collide right recursive
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), node1, false);
- }
- else
- {
- //collide left0 left1
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
-
- //collide left0 right1
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
-
- //collide right0 left1
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
-
- //collide right0 right1
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
-
- } // else if node1 is not a leaf
- } // else if node0 is not a leaf
-}
-
-void btGImpactBvh::find_collision(btGImpactBvh* boxset0, const btTransform& trans0,
- btGImpactBvh* boxset1, const btTransform& trans1,
- btPairSet& collision_pairs)
-{
- if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
-
- BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
-
- trans_cache_1to0.calc_from_homogenic(trans0, trans1);
-
-#ifdef TRI_COLLISION_PROFILING
- bt_begin_gim02_tree_time();
-#endif //TRI_COLLISION_PROFILING
-
- _find_collision_pairs_recursive(
- boxset0, boxset1,
- &collision_pairs, trans_cache_1to0, 0, 0, true);
-#ifdef TRI_COLLISION_PROFILING
- bt_end_gim02_tree_time();
-#endif //TRI_COLLISION_PROFILING
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h
deleted file mode 100644
index 3cd8fa24e7..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvh.h
+++ /dev/null
@@ -1,309 +0,0 @@
-#ifndef BT_GIMPACT_BVH_H_INCLUDED
-#define BT_GIMPACT_BVH_H_INCLUDED
-
-/*! \file gim_box_set.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btAlignedObjectArray.h"
-
-#include "btBoxCollision.h"
-#include "btTriangleShapeEx.h"
-#include "btGImpactBvhStructs.h"
-
-//! A pairset array
-class btPairSet : public btAlignedObjectArray<GIM_PAIR>
-{
-public:
- btPairSet()
- {
- reserve(32);
- }
- inline void push_pair(int index1, int index2)
- {
- push_back(GIM_PAIR(index1, index2));
- }
-
- inline void push_pair_inv(int index1, int index2)
- {
- push_back(GIM_PAIR(index2, index1));
- }
-};
-
-class GIM_BVH_DATA_ARRAY : public btAlignedObjectArray<GIM_BVH_DATA>
-{
-};
-
-class GIM_BVH_TREE_NODE_ARRAY : public btAlignedObjectArray<GIM_BVH_TREE_NODE>
-{
-};
-
-//! Basic Box tree structure
-class btBvhTree
-{
-protected:
- int m_num_nodes;
- GIM_BVH_TREE_NODE_ARRAY m_node_array;
-
-protected:
- int _sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY& primitive_boxes,
- int startIndex, int endIndex, int splitAxis);
-
- int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
-
- void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
-
-public:
- btBvhTree()
- {
- m_num_nodes = 0;
- }
-
- //! prototype functions for box tree management
- //!@{
- void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
-
- SIMD_FORCE_INLINE void clearNodes()
- {
- m_node_array.clear();
- m_num_nodes = 0;
- }
-
- //! node count
- SIMD_FORCE_INLINE int getNodeCount() const
- {
- return m_num_nodes;
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
- {
- return m_node_array[nodeindex].isLeafNode();
- }
-
- SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
- {
- return m_node_array[nodeindex].getDataIndex();
- }
-
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
- {
- bound = m_node_array[nodeindex].m_bound;
- }
-
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
- {
- m_node_array[nodeindex].m_bound = bound;
- }
-
- SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
- {
- return nodeindex + 1;
- }
-
- SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
- {
- if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
- return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
- }
-
- SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
- {
- return m_node_array[nodeindex].getEscapeIndex();
- }
-
- SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
- {
- return &m_node_array[index];
- }
-
- //!@}
-};
-
-//! Prototype Base class for primitive classification
-/*!
-This class is a wrapper for primitive collections.
-This tells relevant info for the Bounding Box set classes, which take care of space classification.
-This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
-*/
-class btPrimitiveManagerBase
-{
-public:
- virtual ~btPrimitiveManagerBase() {}
-
- //! determines if this manager consist on only triangles, which special case will be optimized
- virtual bool is_trimesh() const = 0;
- virtual int get_primitive_count() const = 0;
- virtual void get_primitive_box(int prim_index, btAABB& primbox) const = 0;
- //! retrieves only the points of the triangle, and the collision margin
- virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const = 0;
-};
-
-//! Structure for containing Boxes
-/*!
-This class offers an structure for managing a box tree of primitives.
-Requires a Primitive prototype (like btPrimitiveManagerBase )
-*/
-class btGImpactBvh
-{
-protected:
- btBvhTree m_box_tree;
- btPrimitiveManagerBase* m_primitive_manager;
-
-protected:
- //stackless refit
- void refit();
-
-public:
- //! this constructor doesn't build the tree. you must call buildSet
- btGImpactBvh()
- {
- m_primitive_manager = NULL;
- }
-
- //! this constructor doesn't build the tree. you must call buildSet
- btGImpactBvh(btPrimitiveManagerBase* primitive_manager)
- {
- m_primitive_manager = primitive_manager;
- }
-
- SIMD_FORCE_INLINE btAABB getGlobalBox() const
- {
- btAABB totalbox;
- getNodeBound(0, totalbox);
- return totalbox;
- }
-
- SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
- {
- m_primitive_manager = primitive_manager;
- }
-
- SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
- {
- return m_primitive_manager;
- }
-
- //! node manager prototype functions
- ///@{
-
- //! this attemps to refit the box set.
- SIMD_FORCE_INLINE void update()
- {
- refit();
- }
-
- //! this rebuild the entire set
- void buildSet();
-
- //! returns the indices of the primitives in the m_primitive_manager
- bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
-
- //! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
- const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
- {
- btAABB transbox = box;
- transbox.appy_transform(transform);
- return boxQuery(transbox, collided_results);
- }
-
- //! returns the indices of the primitives in the m_primitive_manager
- bool rayQuery(
- const btVector3& ray_dir, const btVector3& ray_origin,
- btAlignedObjectArray<int>& collided_results) const;
-
- //! tells if this set has hierarcht
- SIMD_FORCE_INLINE bool hasHierarchy() const
- {
- return true;
- }
-
- //! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
- {
- return m_primitive_manager->is_trimesh();
- }
-
- //! node count
- SIMD_FORCE_INLINE int getNodeCount() const
- {
- return m_box_tree.getNodeCount();
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
- {
- return m_box_tree.isLeafNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
- {
- return m_box_tree.getNodeData(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
- {
- m_box_tree.getNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
- {
- m_box_tree.setNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
- {
- return m_box_tree.getLeftNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
- {
- return m_box_tree.getRightNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
- {
- return m_box_tree.getEscapeNodeIndex(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
- {
- m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
- }
-
- SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE* get_node_pointer(int index = 0) const
- {
- return m_box_tree.get_node_pointer(index);
- }
-
-#ifdef TRI_COLLISION_PROFILING
- static float getAverageTreeCollisionTime();
-#endif //TRI_COLLISION_PROFILING
-
- static void find_collision(btGImpactBvh* boxset1, const btTransform& trans1,
- btGImpactBvh* boxset2, const btTransform& trans2,
- btPairSet& collision_pairs);
-};
-
-#endif // BT_GIMPACT_BVH_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
deleted file mode 100644
index 8f78c234b4..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactBvhStructs.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#ifndef GIM_BOX_SET_STRUCT_H_INCLUDED
-#define GIM_BOX_SET_STRUCT_H_INCLUDED
-
-/*! \file gim_box_set.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btAlignedObjectArray.h"
-
-#include "btBoxCollision.h"
-#include "btTriangleShapeEx.h"
-#include "gim_pair.h" //for GIM_PAIR
-
-///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
-struct GIM_BVH_DATA
-{
- btAABB m_bound;
- int m_data;
-};
-
-//! Node Structure for trees
-class GIM_BVH_TREE_NODE
-{
-public:
- btAABB m_bound;
-
-protected:
- int m_escapeIndexOrDataIndex;
-
-public:
- GIM_BVH_TREE_NODE()
- {
- m_escapeIndexOrDataIndex = 0;
- }
-
- SIMD_FORCE_INLINE bool isLeafNode() const
- {
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrDataIndex >= 0);
- }
-
- SIMD_FORCE_INLINE int getEscapeIndex() const
- {
- //btAssert(m_escapeIndexOrDataIndex < 0);
- return -m_escapeIndexOrDataIndex;
- }
-
- SIMD_FORCE_INLINE void setEscapeIndex(int index)
- {
- m_escapeIndexOrDataIndex = -index;
- }
-
- SIMD_FORCE_INLINE int getDataIndex() const
- {
- //btAssert(m_escapeIndexOrDataIndex >= 0);
-
- return m_escapeIndexOrDataIndex;
- }
-
- SIMD_FORCE_INLINE void setDataIndex(int index)
- {
- m_escapeIndexOrDataIndex = index;
- }
-};
-
-#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
deleted file mode 100644
index 73e3db1010..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-/*
-Author: Francisco Leon Najera
-Concave-Concave Collision
-
-*/
-
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "btGImpactCollisionAlgorithm.h"
-#include "btContactProcessing.h"
-#include "LinearMath/btQuickprof.h"
-
-//! Class for accessing the plane equation
-class btPlaneShape : public btStaticPlaneShape
-{
-public:
- btPlaneShape(const btVector3& v, float f)
- : btStaticPlaneShape(v, f)
- {
- }
-
- void get_plane_equation(btVector4& equation)
- {
- equation[0] = m_planeNormal[0];
- equation[1] = m_planeNormal[1];
- equation[2] = m_planeNormal[2];
- equation[3] = m_planeConstant;
- }
-
- void get_plane_equation_transformed(const btTransform& trans, btVector4& equation) const
- {
- const btVector3 normal = trans.getBasis() * m_planeNormal;
- equation[0] = normal[0];
- equation[1] = normal[1];
- equation[2] = normal[2];
- equation[3] = normal.dot(trans * (m_planeConstant * m_planeNormal));
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-#ifdef TRI_COLLISION_PROFILING
-
-btClock g_triangle_clock;
-
-float g_accum_triangle_collision_time = 0;
-int g_count_triangle_collision = 0;
-
-void bt_begin_gim02_tri_time()
-{
- g_triangle_clock.reset();
-}
-
-void bt_end_gim02_tri_time()
-{
- g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
- g_count_triangle_collision++;
-}
-#endif //TRI_COLLISION_PROFILING
-//! Retrieving shapes shapes
-/*!
-Declared here due of insuficent space on Pool allocators
-*/
-//!@{
-class GIM_ShapeRetriever
-{
-public:
- const btGImpactShapeInterface* m_gim_shape;
- btTriangleShapeEx m_trishape;
- btTetrahedronShapeEx m_tetrashape;
-
-public:
- class ChildShapeRetriever
- {
- public:
- GIM_ShapeRetriever* m_parent;
- virtual const btCollisionShape* getChildShape(int index)
- {
- return m_parent->m_gim_shape->getChildShape(index);
- }
- virtual ~ChildShapeRetriever() {}
- };
-
- class TriangleShapeRetriever : public ChildShapeRetriever
- {
- public:
- virtual btCollisionShape* getChildShape(int index)
- {
- m_parent->m_gim_shape->getBulletTriangle(index, m_parent->m_trishape);
- return &m_parent->m_trishape;
- }
- virtual ~TriangleShapeRetriever() {}
- };
-
- class TetraShapeRetriever : public ChildShapeRetriever
- {
- public:
- virtual btCollisionShape* getChildShape(int index)
- {
- m_parent->m_gim_shape->getBulletTetrahedron(index, m_parent->m_tetrashape);
- return &m_parent->m_tetrashape;
- }
- };
-
-public:
- ChildShapeRetriever m_child_retriever;
- TriangleShapeRetriever m_tri_retriever;
- TetraShapeRetriever m_tetra_retriever;
- ChildShapeRetriever* m_current_retriever;
-
- GIM_ShapeRetriever(const btGImpactShapeInterface* gim_shape)
- {
- m_gim_shape = gim_shape;
- //select retriever
- if (m_gim_shape->needsRetrieveTriangles())
- {
- m_current_retriever = &m_tri_retriever;
- }
- else if (m_gim_shape->needsRetrieveTetrahedrons())
- {
- m_current_retriever = &m_tetra_retriever;
- }
- else
- {
- m_current_retriever = &m_child_retriever;
- }
-
- m_current_retriever->m_parent = this;
- }
-
- const btCollisionShape* getChildShape(int index)
- {
- return m_current_retriever->getChildShape(index);
- }
-};
-
-//!@}
-
-#ifdef TRI_COLLISION_PROFILING
-
-//! Gets the average time in miliseconds of tree collisions
-float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
-{
- return btGImpactBoxSet::getAverageTreeCollisionTime();
-}
-
-//! Gets the average time in miliseconds of triangle collisions
-float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
-{
- if (g_count_triangle_collision == 0) return 0;
-
- float avgtime = g_accum_triangle_collision_time;
- avgtime /= (float)g_count_triangle_collision;
-
- g_accum_triangle_collision_time = 0;
- g_count_triangle_collision = 0;
-
- return avgtime;
-}
-
-#endif //TRI_COLLISION_PROFILING
-
-btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- : btActivatingCollisionAlgorithm(ci, body0Wrap, body1Wrap)
-{
- m_manifoldPtr = NULL;
- m_convex_algorithm = NULL;
-}
-
-btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
-{
- clearCache();
-}
-
-void btGImpactCollisionAlgorithm::addContactPoint(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btVector3& point,
- const btVector3& normal,
- btScalar distance)
-{
- m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
- checkManifold(body0Wrap, body1Wrap);
- m_resultOut->addContactPoint(normal, point, distance);
-}
-
-void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1)
-{
- {
- btCollisionAlgorithm* algor = newAlgorithm(body0Wrap, body1Wrap);
- // post : checkManifold is called
-
- m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
-
- algor->processCollision(body0Wrap, body1Wrap, *m_dispatchInfo, m_resultOut);
-
- algor->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(algor);
- }
-}
-
-void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1)
-{
- m_resultOut->setShapeIdentifiersA(m_part0, m_triface0);
- m_resultOut->setShapeIdentifiersB(m_part1, m_triface1);
-
- btCollisionObjectWrapper ob0(body0Wrap, shape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
- btCollisionObjectWrapper ob1(body1Wrap, shape1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), m_part1, m_triface1);
- checkConvexAlgorithm(&ob0, &ob1);
- m_convex_algorithm->processCollision(&ob0, &ob1, *m_dispatchInfo, m_resultOut);
-}
-
-void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
- const btTransform& trans0,
- const btTransform& trans1,
- const btGImpactShapeInterface* shape0,
- const btGImpactShapeInterface* shape1, btPairSet& pairset)
-{
- if (shape0->hasBoxSet() && shape1->hasBoxSet())
- {
- btGImpactBoxSet::find_collision(shape0->getBoxSet(), trans0, shape1->getBoxSet(), trans1, pairset);
- }
- else
- {
- btAABB boxshape0;
- btAABB boxshape1;
- int i = shape0->getNumChildShapes();
-
- while (i--)
- {
- shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
-
- int j = shape1->getNumChildShapes();
- while (j--)
- {
- shape1->getChildAabb(i, trans1, boxshape1.m_min, boxshape1.m_max);
-
- if (boxshape1.has_collision(boxshape0))
- {
- pairset.push_pair(i, j);
- }
- }
- }
- }
-}
-
-void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
- const btTransform& trans0,
- const btTransform& trans1,
- const btGImpactShapeInterface* shape0,
- const btCollisionShape* shape1,
- btAlignedObjectArray<int>& collided_primitives)
-{
- btAABB boxshape;
-
- if (shape0->hasBoxSet())
- {
- btTransform trans1to0 = trans0.inverse();
- trans1to0 *= trans1;
-
- shape1->getAabb(trans1to0, boxshape.m_min, boxshape.m_max);
-
- shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
- }
- else
- {
- shape1->getAabb(trans1, boxshape.m_min, boxshape.m_max);
-
- btAABB boxshape0;
- int i = shape0->getNumChildShapes();
-
- while (i--)
- {
- shape0->getChildAabb(i, trans0, boxshape0.m_min, boxshape0.m_max);
-
- if (boxshape.has_collision(boxshape0))
- {
- collided_primitives.push_back(i);
- }
- }
- }
-}
-
-void btGImpactCollisionAlgorithm::collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btGImpactMeshShapePart* shape1,
- const int* pairs, int pair_count)
-{
- btTriangleShapeEx tri0;
- btTriangleShapeEx tri1;
-
- shape0->lockChildShapes();
- shape1->lockChildShapes();
-
- const int* pair_pointer = pairs;
-
- while (pair_count--)
- {
- m_triface0 = *(pair_pointer);
- m_triface1 = *(pair_pointer + 1);
- pair_pointer += 2;
-
- shape0->getBulletTriangle(m_triface0, tri0);
- shape1->getBulletTriangle(m_triface1, tri1);
-
- //collide two convex shapes
- if (tri0.overlap_test_conservative(tri1))
- {
- convex_vs_convex_collision(body0Wrap, body1Wrap, &tri0, &tri1);
- }
- }
-
- shape0->unlockChildShapes();
- shape1->unlockChildShapes();
-}
-
-void btGImpactCollisionAlgorithm::collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btGImpactMeshShapePart* shape1,
- const int* pairs, int pair_count)
-{
- btTransform orgtrans0 = body0Wrap->getWorldTransform();
- btTransform orgtrans1 = body1Wrap->getWorldTransform();
-
- btPrimitiveTriangle ptri0;
- btPrimitiveTriangle ptri1;
- GIM_TRIANGLE_CONTACT contact_data;
-
- shape0->lockChildShapes();
- shape1->lockChildShapes();
-
- const int* pair_pointer = pairs;
-
- while (pair_count--)
- {
- m_triface0 = *(pair_pointer);
- m_triface1 = *(pair_pointer + 1);
- pair_pointer += 2;
-
- shape0->getPrimitiveTriangle(m_triface0, ptri0);
- shape1->getPrimitiveTriangle(m_triface1, ptri1);
-
-#ifdef TRI_COLLISION_PROFILING
- bt_begin_gim02_tri_time();
-#endif
-
- ptri0.applyTransform(orgtrans0);
- ptri1.applyTransform(orgtrans1);
-
- //build planes
- ptri0.buildTriPlane();
- ptri1.buildTriPlane();
- // test conservative
-
- if (ptri0.overlap_test_conservative(ptri1))
- {
- if (ptri0.find_triangle_collision_clip_method(ptri1, contact_data))
- {
- int j = contact_data.m_point_count;
- while (j--)
- {
- addContactPoint(body0Wrap, body1Wrap,
- contact_data.m_points[j],
- contact_data.m_separating_normal,
- -contact_data.m_penetration_depth);
- }
- }
- }
-
-#ifdef TRI_COLLISION_PROFILING
- bt_end_gim02_tri_time();
-#endif
- }
-
- shape0->unlockChildShapes();
- shape1->unlockChildShapes();
-}
-
-void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btGImpactShapeInterface* shape1)
-{
- if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
- {
- const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
- m_part0 = meshshape0->getMeshPartCount();
-
- while (m_part0--)
- {
- gimpact_vs_gimpact(body0Wrap, body1Wrap, meshshape0->getMeshPart(m_part0), shape1);
- }
-
- return;
- }
-
- if (shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
- {
- const btGImpactMeshShape* meshshape1 = static_cast<const btGImpactMeshShape*>(shape1);
- m_part1 = meshshape1->getMeshPartCount();
-
- while (m_part1--)
- {
- gimpact_vs_gimpact(body0Wrap, body1Wrap, shape0, meshshape1->getMeshPart(m_part1));
- }
-
- return;
- }
-
- btTransform orgtrans0 = body0Wrap->getWorldTransform();
- btTransform orgtrans1 = body1Wrap->getWorldTransform();
-
- btPairSet pairset;
-
- gimpact_vs_gimpact_find_pairs(orgtrans0, orgtrans1, shape0, shape1, pairset);
-
- if (pairset.size() == 0) return;
-
- if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
- shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
- {
- const btGImpactMeshShapePart* shapepart0 = static_cast<const btGImpactMeshShapePart*>(shape0);
- const btGImpactMeshShapePart* shapepart1 = static_cast<const btGImpactMeshShapePart*>(shape1);
-//specialized function
-#ifdef BULLET_TRIANGLE_COLLISION
- collide_gjk_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
-#else
- collide_sat_triangles(body0Wrap, body1Wrap, shapepart0, shapepart1, &pairset[0].m_index1, pairset.size());
-#endif
-
- return;
- }
-
- //general function
-
- shape0->lockChildShapes();
- shape1->lockChildShapes();
-
- GIM_ShapeRetriever retriever0(shape0);
- GIM_ShapeRetriever retriever1(shape1);
-
- bool child_has_transform0 = shape0->childrenHasTransform();
- bool child_has_transform1 = shape1->childrenHasTransform();
-
- int i = pairset.size();
- while (i--)
- {
- GIM_PAIR* pair = &pairset[i];
- m_triface0 = pair->m_index1;
- m_triface1 = pair->m_index2;
- const btCollisionShape* colshape0 = retriever0.getChildShape(m_triface0);
- const btCollisionShape* colshape1 = retriever1.getChildShape(m_triface1);
-
- btTransform tr0 = body0Wrap->getWorldTransform();
- btTransform tr1 = body1Wrap->getWorldTransform();
-
- if (child_has_transform0)
- {
- tr0 = orgtrans0 * shape0->getChildTransform(m_triface0);
- }
-
- if (child_has_transform1)
- {
- tr1 = orgtrans1 * shape1->getChildTransform(m_triface1);
- }
-
- btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), tr0, m_part0, m_triface0);
- btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), tr1, m_part1, m_triface1);
-
- //collide two convex shapes
- convex_vs_convex_collision(&ob0, &ob1, colshape0, colshape1);
- }
-
- shape0->unlockChildShapes();
- shape1->unlockChildShapes();
-}
-
-void btGImpactCollisionAlgorithm::gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btCollisionShape* shape1, bool swapped)
-{
- if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE)
- {
- const btGImpactMeshShape* meshshape0 = static_cast<const btGImpactMeshShape*>(shape0);
- int& part = swapped ? m_part1 : m_part0;
- part = meshshape0->getMeshPartCount();
-
- while (part--)
- {
- gimpact_vs_shape(body0Wrap,
- body1Wrap,
- meshshape0->getMeshPart(part),
- shape1, swapped);
- }
-
- return;
- }
-
-#ifdef GIMPACT_VS_PLANE_COLLISION
- if (shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
- shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
- {
- const btGImpactMeshShapePart* shapepart = static_cast<const btGImpactMeshShapePart*>(shape0);
- const btStaticPlaneShape* planeshape = static_cast<const btStaticPlaneShape*>(shape1);
- gimpacttrimeshpart_vs_plane_collision(body0Wrap, body1Wrap, shapepart, planeshape, swapped);
- return;
- }
-
-#endif
-
- if (shape1->isCompound())
- {
- const btCompoundShape* compoundshape = static_cast<const btCompoundShape*>(shape1);
- gimpact_vs_compoundshape(body0Wrap, body1Wrap, shape0, compoundshape, swapped);
- return;
- }
- else if (shape1->isConcave())
- {
- const btConcaveShape* concaveshape = static_cast<const btConcaveShape*>(shape1);
- gimpact_vs_concave(body0Wrap, body1Wrap, shape0, concaveshape, swapped);
- return;
- }
-
- btTransform orgtrans0 = body0Wrap->getWorldTransform();
-
- btTransform orgtrans1 = body1Wrap->getWorldTransform();
-
- btAlignedObjectArray<int> collided_results;
-
- gimpact_vs_shape_find_pairs(orgtrans0, orgtrans1, shape0, shape1, collided_results);
-
- if (collided_results.size() == 0) return;
-
- shape0->lockChildShapes();
-
- GIM_ShapeRetriever retriever0(shape0);
-
- bool child_has_transform0 = shape0->childrenHasTransform();
-
- int i = collided_results.size();
-
- while (i--)
- {
- int child_index = collided_results[i];
- if (swapped)
- m_triface1 = child_index;
- else
- m_triface0 = child_index;
-
- const btCollisionShape* colshape0 = retriever0.getChildShape(child_index);
-
- btTransform tr0 = body0Wrap->getWorldTransform();
-
- if (child_has_transform0)
- {
- tr0 = orgtrans0 * shape0->getChildTransform(child_index);
- }
-
- btCollisionObjectWrapper ob0(body0Wrap, colshape0, body0Wrap->getCollisionObject(), body0Wrap->getWorldTransform(), m_part0, m_triface0);
- const btCollisionObjectWrapper* prevObj;
-
- if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
- {
- prevObj = m_resultOut->getBody0Wrap();
- m_resultOut->setBody0Wrap(&ob0);
- }
- else
- {
- prevObj = m_resultOut->getBody1Wrap();
- m_resultOut->setBody1Wrap(&ob0);
- }
-
- //collide two shapes
- if (swapped)
- {
- shape_vs_shape_collision(body1Wrap, &ob0, shape1, colshape0);
- }
- else
- {
- shape_vs_shape_collision(&ob0, body1Wrap, colshape0, shape1);
- }
-
- if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob0.getCollisionObject())
- {
- m_resultOut->setBody0Wrap(prevObj);
- }
- else
- {
- m_resultOut->setBody1Wrap(prevObj);
- }
- }
-
- shape0->unlockChildShapes();
-}
-
-void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btCompoundShape* shape1, bool swapped)
-{
- btTransform orgtrans1 = body1Wrap->getWorldTransform();
-
- int i = shape1->getNumChildShapes();
- while (i--)
- {
- const btCollisionShape* colshape1 = shape1->getChildShape(i);
- btTransform childtrans1 = orgtrans1 * shape1->getChildTransform(i);
-
- btCollisionObjectWrapper ob1(body1Wrap, colshape1, body1Wrap->getCollisionObject(), childtrans1, -1, i);
-
- const btCollisionObjectWrapper* tmp = 0;
- if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
- {
- tmp = m_resultOut->getBody0Wrap();
- m_resultOut->setBody0Wrap(&ob1);
- }
- else
- {
- tmp = m_resultOut->getBody1Wrap();
- m_resultOut->setBody1Wrap(&ob1);
- }
- //collide child shape
- gimpact_vs_shape(body0Wrap, &ob1,
- shape0, colshape1, swapped);
-
- if (m_resultOut->getBody0Wrap()->getCollisionObject() == ob1.getCollisionObject())
- {
- m_resultOut->setBody0Wrap(tmp);
- }
- else
- {
- m_resultOut->setBody1Wrap(tmp);
- }
- }
-}
-
-void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btStaticPlaneShape* shape1, bool swapped)
-{
- btTransform orgtrans0 = body0Wrap->getWorldTransform();
- btTransform orgtrans1 = body1Wrap->getWorldTransform();
-
- const btPlaneShape* planeshape = static_cast<const btPlaneShape*>(shape1);
- btVector4 plane;
- planeshape->get_plane_equation_transformed(orgtrans1, plane);
-
- //test box against plane
-
- btAABB tribox;
- shape0->getAabb(orgtrans0, tribox.m_min, tribox.m_max);
- tribox.increment_margin(planeshape->getMargin());
-
- if (tribox.plane_classify(plane) != BT_CONST_COLLIDE_PLANE) return;
-
- shape0->lockChildShapes();
-
- btScalar margin = shape0->getMargin() + planeshape->getMargin();
-
- btVector3 vertex;
- int vi = shape0->getVertexCount();
- while (vi--)
- {
- shape0->getVertex(vi, vertex);
- vertex = orgtrans0(vertex);
-
- btScalar distance = vertex.dot(plane) - plane[3] - margin;
-
- if (distance < 0.0) //add contact
- {
- if (swapped)
- {
- addContactPoint(body1Wrap, body0Wrap,
- vertex,
- -plane,
- distance);
- }
- else
- {
- addContactPoint(body0Wrap, body1Wrap,
- vertex,
- plane,
- distance);
- }
- }
- }
-
- shape0->unlockChildShapes();
-}
-
-class btGImpactTriangleCallback : public btTriangleCallback
-{
-public:
- btGImpactCollisionAlgorithm* algorithm;
- const btCollisionObjectWrapper* body0Wrap;
- const btCollisionObjectWrapper* body1Wrap;
- const btGImpactShapeInterface* gimpactshape0;
- bool swapped;
- btScalar margin;
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- btTriangleShapeEx tri1(triangle[0], triangle[1], triangle[2]);
- tri1.setMargin(margin);
- if (swapped)
- {
- algorithm->setPart0(partId);
- algorithm->setFace0(triangleIndex);
- }
- else
- {
- algorithm->setPart1(partId);
- algorithm->setFace1(triangleIndex);
- }
-
- btCollisionObjectWrapper ob1Wrap(body1Wrap, &tri1, body1Wrap->getCollisionObject(), body1Wrap->getWorldTransform(), partId, triangleIndex);
- const btCollisionObjectWrapper* tmp = 0;
-
- if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
- {
- tmp = algorithm->internalGetResultOut()->getBody0Wrap();
- algorithm->internalGetResultOut()->setBody0Wrap(&ob1Wrap);
- }
- else
- {
- tmp = algorithm->internalGetResultOut()->getBody1Wrap();
- algorithm->internalGetResultOut()->setBody1Wrap(&ob1Wrap);
- }
-
- algorithm->gimpact_vs_shape(
- body0Wrap, &ob1Wrap, gimpactshape0, &tri1, swapped);
-
- if (algorithm->internalGetResultOut()->getBody0Wrap()->getCollisionObject() == ob1Wrap.getCollisionObject())
- {
- algorithm->internalGetResultOut()->setBody0Wrap(tmp);
- }
- else
- {
- algorithm->internalGetResultOut()->setBody1Wrap(tmp);
- }
- }
-};
-
-void btGImpactCollisionAlgorithm::gimpact_vs_concave(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btConcaveShape* shape1, bool swapped)
-{
- //create the callback
- btGImpactTriangleCallback tricallback;
- tricallback.algorithm = this;
- tricallback.body0Wrap = body0Wrap;
- tricallback.body1Wrap = body1Wrap;
- tricallback.gimpactshape0 = shape0;
- tricallback.swapped = swapped;
- tricallback.margin = shape1->getMargin();
-
- //getting the trimesh AABB
- btTransform gimpactInConcaveSpace;
-
- gimpactInConcaveSpace = body1Wrap->getWorldTransform().inverse() * body0Wrap->getWorldTransform();
-
- btVector3 minAABB, maxAABB;
- shape0->getAabb(gimpactInConcaveSpace, minAABB, maxAABB);
-
- shape1->processAllTriangles(&tricallback, minAABB, maxAABB);
-}
-
-void btGImpactCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- clearCache();
-
- m_resultOut = resultOut;
- m_dispatchInfo = &dispatchInfo;
- const btGImpactShapeInterface* gimpactshape0;
- const btGImpactShapeInterface* gimpactshape1;
-
- if (body0Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- {
- gimpactshape0 = static_cast<const btGImpactShapeInterface*>(body0Wrap->getCollisionShape());
-
- if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- {
- gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
-
- gimpact_vs_gimpact(body0Wrap, body1Wrap, gimpactshape0, gimpactshape1);
- }
- else
- {
- gimpact_vs_shape(body0Wrap, body1Wrap, gimpactshape0, body1Wrap->getCollisionShape(), false);
- }
- }
- else if (body1Wrap->getCollisionShape()->getShapeType() == GIMPACT_SHAPE_PROXYTYPE)
- {
- gimpactshape1 = static_cast<const btGImpactShapeInterface*>(body1Wrap->getCollisionShape());
-
- gimpact_vs_shape(body1Wrap, body0Wrap, gimpactshape1, body0Wrap->getCollisionShape(), true);
- }
-
- // Ensure that gContactProcessedCallback is called for concave shapes.
- if (getLastManifold())
- {
- m_resultOut->refreshContactPoints();
- }
-}
-
-btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- return 1.f;
-}
-
-///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
-
-//! Use this function for register the algorithm externally
-void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher* dispatcher)
-{
- static btGImpactCollisionAlgorithm::CreateFunc s_gimpact_cf;
-
- int i;
-
- for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
- {
- dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE, i, &s_gimpact_cf);
- }
-
- for (i = 0; i < MAX_BROADPHASE_COLLISION_TYPES; i++)
- {
- dispatcher->registerCollisionCreateFunc(i, GIMPACT_SHAPE_PROXYTYPE, &s_gimpact_cf);
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
deleted file mode 100644
index a368c8a0c0..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h
+++ /dev/null
@@ -1,288 +0,0 @@
-/*! \file btGImpactShape.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
-#define BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btDispatcher;
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-
-#include "LinearMath/btAlignedObjectArray.h"
-
-#include "btGImpactShape.h"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-//! Collision Algorithm for GImpact Shapes
-/*!
-For register this algorithm in Bullet, proceed as following:
- \code
-btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
-btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
- \endcode
-*/
-class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
-{
-protected:
- btCollisionAlgorithm* m_convex_algorithm;
- btPersistentManifold* m_manifoldPtr;
- btManifoldResult* m_resultOut;
- const btDispatcherInfo* m_dispatchInfo;
- int m_triface0;
- int m_part0;
- int m_triface1;
- int m_part1;
-
- //! Creates a new contact point
- SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(const btCollisionObject* body0, const btCollisionObject* body1)
- {
- m_manifoldPtr = m_dispatcher->getNewManifold(body0, body1);
- return m_manifoldPtr;
- }
-
- SIMD_FORCE_INLINE void destroyConvexAlgorithm()
- {
- if (m_convex_algorithm)
- {
- m_convex_algorithm->~btCollisionAlgorithm();
- m_dispatcher->freeCollisionAlgorithm(m_convex_algorithm);
- m_convex_algorithm = NULL;
- }
- }
-
- SIMD_FORCE_INLINE void destroyContactManifolds()
- {
- if (m_manifoldPtr == NULL) return;
- m_dispatcher->releaseManifold(m_manifoldPtr);
- m_manifoldPtr = NULL;
- }
-
- SIMD_FORCE_INLINE void clearCache()
- {
- destroyContactManifolds();
- destroyConvexAlgorithm();
-
- m_triface0 = -1;
- m_part0 = -1;
- m_triface1 = -1;
- m_part1 = -1;
- }
-
- SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
- {
- return m_manifoldPtr;
- }
-
- // Call before process collision
- SIMD_FORCE_INLINE void checkManifold(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- if (getLastManifold() == 0)
- {
- newContactManifold(body0Wrap->getCollisionObject(), body1Wrap->getCollisionObject());
- }
-
- m_resultOut->setPersistentManifold(getLastManifold());
- }
-
- // Call before process collision
- SIMD_FORCE_INLINE btCollisionAlgorithm* newAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- checkManifold(body0Wrap, body1Wrap);
-
- btCollisionAlgorithm* convex_algorithm = m_dispatcher->findAlgorithm(
- body0Wrap, body1Wrap, getLastManifold(), BT_CONTACT_POINT_ALGORITHMS);
- return convex_algorithm;
- }
-
- // Call before process collision
- SIMD_FORCE_INLINE void checkConvexAlgorithm(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- if (m_convex_algorithm) return;
- m_convex_algorithm = newAlgorithm(body0Wrap, body1Wrap);
- }
-
- void addContactPoint(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btVector3& point,
- const btVector3& normal,
- btScalar distance);
-
- //! Collision routines
- //!@{
-
- void collide_gjk_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btGImpactMeshShapePart* shape1,
- const int* pairs, int pair_count);
-
- void collide_sat_triangles(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btGImpactMeshShapePart* shape1,
- const int* pairs, int pair_count);
-
- void shape_vs_shape_collision(
- const btCollisionObjectWrapper* body0,
- const btCollisionObjectWrapper* body1,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1);
-
- void convex_vs_convex_collision(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btCollisionShape* shape0,
- const btCollisionShape* shape1);
-
- void gimpact_vs_gimpact_find_pairs(
- const btTransform& trans0,
- const btTransform& trans1,
- const btGImpactShapeInterface* shape0,
- const btGImpactShapeInterface* shape1, btPairSet& pairset);
-
- void gimpact_vs_shape_find_pairs(
- const btTransform& trans0,
- const btTransform& trans1,
- const btGImpactShapeInterface* shape0,
- const btCollisionShape* shape1,
- btAlignedObjectArray<int>& collided_primitives);
-
- void gimpacttrimeshpart_vs_plane_collision(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactMeshShapePart* shape0,
- const btStaticPlaneShape* shape1, bool swapped);
-
-public:
- btGImpactCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
- virtual ~btGImpactCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr)
- manifoldArray.push_back(m_manifoldPtr);
- }
-
- btManifoldResult* internalGetResultOut()
- {
- return m_resultOut;
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
- return new (mem) btGImpactCollisionAlgorithm(ci, body0Wrap, body1Wrap);
- }
- };
-
- //! Use this function for register the algorithm externally
- static void registerAlgorithm(btCollisionDispatcher* dispatcher);
-#ifdef TRI_COLLISION_PROFILING
- //! Gets the average time in miliseconds of tree collisions
- static float getAverageTreeCollisionTime();
-
- //! Gets the average time in miliseconds of triangle collisions
- static float getAverageTriangleCollisionTime();
-#endif //TRI_COLLISION_PROFILING
-
- //! Collides two gimpact shapes
- /*!
- \pre shape0 and shape1 couldn't be btGImpactMeshShape objects
- */
-
- void gimpact_vs_gimpact(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btGImpactShapeInterface* shape1);
-
- void gimpact_vs_shape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btCollisionShape* shape1, bool swapped);
-
- void gimpact_vs_compoundshape(const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btCompoundShape* shape1, bool swapped);
-
- void gimpact_vs_concave(
- const btCollisionObjectWrapper* body0Wrap,
- const btCollisionObjectWrapper* body1Wrap,
- const btGImpactShapeInterface* shape0,
- const btConcaveShape* shape1, bool swapped);
-
- /// Accessor/Mutator pairs for Part and triangleID
- void setFace0(int value)
- {
- m_triface0 = value;
- }
- int getFace0()
- {
- return m_triface0;
- }
- void setFace1(int value)
- {
- m_triface1 = value;
- }
- int getFace1()
- {
- return m_triface1;
- }
- void setPart0(int value)
- {
- m_part0 = value;
- }
- int getPart0()
- {
- return m_part0;
- }
- void setPart1(int value)
- {
- m_part1 = value;
- }
- int getPart1()
- {
- return m_part1;
- }
-};
-
-//algorithm details
-//#define BULLET_TRIANGLE_COLLISION 1
-#define GIMPACT_VS_PLANE_COLLISION 1
-
-#endif //BT_GIMPACT_BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h
deleted file mode 100644
index 1cde46ed8b..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactMassUtil.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*! \file btGImpactMassUtil.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef GIMPACT_MASS_UTIL_H
-#define GIMPACT_MASS_UTIL_H
-
-#include "LinearMath/btTransform.h"
-
-SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
- const btVector3& source_inertia, const btVector3& added_inertia, const btTransform& transform)
-{
- btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
-
- btScalar x2 = transform.getOrigin()[0];
- x2 *= x2;
- btScalar y2 = transform.getOrigin()[1];
- y2 *= y2;
- btScalar z2 = transform.getOrigin()[2];
- z2 *= z2;
-
- btScalar ix = rotatedTensor[0][0] * (y2 + z2);
- btScalar iy = rotatedTensor[1][1] * (x2 + z2);
- btScalar iz = rotatedTensor[2][2] * (x2 + y2);
-
- return btVector3(source_inertia[0] + ix, source_inertia[1] + iy, source_inertia[2] + iz);
-}
-
-SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3& point, btScalar mass)
-{
- btScalar x2 = point[0] * point[0];
- btScalar y2 = point[1] * point[1];
- btScalar z2 = point[2] * point[2];
- return btVector3(mass * (y2 + z2), mass * (x2 + z2), mass * (x2 + y2));
-}
-
-#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
deleted file mode 100644
index b81fc97044..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-/*! \file gim_box_set.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGImpactQuantizedBvh.h"
-#include "LinearMath/btQuickprof.h"
-
-#ifdef TRI_COLLISION_PROFILING
-btClock g_q_tree_clock;
-
-float g_q_accum_tree_collision_time = 0;
-int g_q_count_traversing = 0;
-
-void bt_begin_gim02_q_tree_time()
-{
- g_q_tree_clock.reset();
-}
-
-void bt_end_gim02_q_tree_time()
-{
- g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
- g_q_count_traversing++;
-}
-
-//! Gets the average time in miliseconds of tree collisions
-float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
-{
- if (g_q_count_traversing == 0) return 0;
-
- float avgtime = g_q_accum_tree_collision_time;
- avgtime /= (float)g_q_count_traversing;
-
- g_q_accum_tree_collision_time = 0;
- g_q_count_traversing = 0;
- return avgtime;
-
- // float avgtime = g_q_count_traversing;
- // g_q_count_traversing = 0;
- // return avgtime;
-}
-
-#endif //TRI_COLLISION_PROFILING
-
-/////////////////////// btQuantizedBvhTree /////////////////////////////////
-
-void btQuantizedBvhTree::calc_quantization(
- GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin)
-{
- //calc globa box
- btAABB global_bound;
- global_bound.invalidate();
-
- for (int i = 0; i < primitive_boxes.size(); i++)
- {
- global_bound.merge(primitive_boxes[i].m_bound);
- }
-
- bt_calc_quantization_parameters(
- m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization, global_bound.m_min, global_bound.m_max, boundMargin);
-}
-
-int btQuantizedBvhTree::_calc_splitting_axis(
- GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
-{
- int i;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
- int numIndices = endIndex - startIndex;
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
-
- return variance.maxAxis();
-}
-
-int btQuantizedBvhTree::_sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex,
- int endIndex, int splitAxis)
-{
- int i;
- int splitIndex = startIndex;
- int numIndices = endIndex - startIndex;
-
- // average of centers
- btScalar splitValue = 0.0f;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- splitValue = means[splitAxis];
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- if (center[splitAxis] > splitValue)
- {
- //swap
- primitive_boxes.swap(i, splitIndex);
- //swapLeafNodes(i,splitIndex);
- splitIndex++;
- }
- }
-
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
-
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
-
- //this should be safe too:
- int rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
-
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
-
- btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
-
- return splitIndex;
-}
-
-void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex)
-{
- int curIndex = m_num_nodes;
- m_num_nodes++;
-
- btAssert((endIndex - startIndex) > 0);
-
- if ((endIndex - startIndex) == 1)
- {
- //We have a leaf node
- setNodeBound(curIndex, primitive_boxes[startIndex].m_bound);
- m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
-
- return;
- }
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- //split axis
- int splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
-
- splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes, startIndex, endIndex,
- splitIndex //split axis
- );
-
- //calc this node bounding box
-
- btAABB node_bound;
- node_bound.invalidate();
-
- for (int i = startIndex; i < endIndex; i++)
- {
- node_bound.merge(primitive_boxes[i].m_bound);
- }
-
- setNodeBound(curIndex, node_bound);
-
- //build left branch
- _build_sub_tree(primitive_boxes, startIndex, splitIndex);
-
- //build right branch
- _build_sub_tree(primitive_boxes, splitIndex, endIndex);
-
- m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
-}
-
-//! stackless build tree
-void btQuantizedBvhTree::build_tree(
- GIM_BVH_DATA_ARRAY& primitive_boxes)
-{
- calc_quantization(primitive_boxes);
- // initialize node count to 0
- m_num_nodes = 0;
- // allocate nodes
- m_node_array.resize(primitive_boxes.size() * 2);
-
- _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
-}
-
-////////////////////////////////////class btGImpactQuantizedBvh
-
-void btGImpactQuantizedBvh::refit()
-{
- int nodecount = getNodeCount();
- while (nodecount--)
- {
- if (isLeafNode(nodecount))
- {
- btAABB leafbox;
- m_primitive_manager->get_primitive_box(getNodeData(nodecount), leafbox);
- setNodeBound(nodecount, leafbox);
- }
- else
- {
- //const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
- //get left bound
- btAABB bound;
- bound.invalidate();
-
- btAABB temp_box;
-
- int child_node = getLeftNode(nodecount);
- if (child_node)
- {
- getNodeBound(child_node, temp_box);
- bound.merge(temp_box);
- }
-
- child_node = getRightNode(nodecount);
- if (child_node)
- {
- getNodeBound(child_node, temp_box);
- bound.merge(temp_box);
- }
-
- setNodeBound(nodecount, bound);
- }
- }
-}
-
-//! this rebuild the entire set
-void btGImpactQuantizedBvh::buildSet()
-{
- //obtain primitive boxes
- GIM_BVH_DATA_ARRAY primitive_boxes;
- primitive_boxes.resize(m_primitive_manager->get_primitive_count());
-
- for (int i = 0; i < primitive_boxes.size(); i++)
- {
- m_primitive_manager->get_primitive_box(i, primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
- }
-
- m_box_tree.build_tree(primitive_boxes);
-}
-
-//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactQuantizedBvh::boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const
-{
- int curIndex = 0;
- int numNodes = getNodeCount();
-
- //quantize box
-
- unsigned short quantizedMin[3];
- unsigned short quantizedMax[3];
-
- m_box_tree.quantizePoint(quantizedMin, box.m_min);
- m_box_tree.quantizePoint(quantizedMax, box.m_max);
-
- while (curIndex < numNodes)
- {
- //catch bugs in tree data
-
- bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin, quantizedMax);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getEscapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
-}
-
-//! returns the indices of the primitives in the m_primitive_manager
-bool btGImpactQuantizedBvh::rayQuery(
- const btVector3& ray_dir, const btVector3& ray_origin,
- btAlignedObjectArray<int>& collided_results) const
-{
- int curIndex = 0;
- int numNodes = getNodeCount();
-
- while (curIndex < numNodes)
- {
- btAABB bound;
- getNodeBound(curIndex, bound);
-
- //catch bugs in tree data
-
- bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getEscapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
-}
-
-SIMD_FORCE_INLINE bool _quantized_node_collision(
- const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
- const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
- int node0, int node1, bool complete_primitive_tests)
-{
- btAABB box0;
- boxset0->getNodeBound(node0, box0);
- btAABB box1;
- boxset1->getNodeBound(node1, box1);
-
- return box0.overlapping_trans_cache(box1, trans_cache_1to0, complete_primitive_tests);
- // box1.appy_transform_trans_cache(trans_cache_1to0);
- // return box0.has_collision(box1);
-}
-
-//stackless recursive collision routine
-static void _find_quantized_collision_pairs_recursive(
- const btGImpactQuantizedBvh* boxset0, const btGImpactQuantizedBvh* boxset1,
- btPairSet* collision_pairs,
- const BT_BOX_BOX_TRANSFORM_CACHE& trans_cache_1to0,
- int node0, int node1, bool complete_primitive_tests)
-{
- if (_quantized_node_collision(
- boxset0, boxset1, trans_cache_1to0,
- node0, node1, complete_primitive_tests) == false) return; //avoid colliding internal nodes
-
- if (boxset0->isLeafNode(node0))
- {
- if (boxset1->isLeafNode(node1))
- {
- // collision result
- collision_pairs->push_pair(
- boxset0->getNodeData(node0), boxset1->getNodeData(node1));
- return;
- }
- else
- {
- //collide left recursive
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- node0, boxset1->getLeftNode(node1), false);
-
- //collide right recursive
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- node0, boxset1->getRightNode(node1), false);
- }
- }
- else
- {
- if (boxset1->isLeafNode(node1))
- {
- //collide left recursive
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), node1, false);
-
- //collide right recursive
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), node1, false);
- }
- else
- {
- //collide left0 left1
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), boxset1->getLeftNode(node1), false);
-
- //collide left0 right1
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getLeftNode(node0), boxset1->getRightNode(node1), false);
-
- //collide right0 left1
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), boxset1->getLeftNode(node1), false);
-
- //collide right0 right1
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- collision_pairs, trans_cache_1to0,
- boxset0->getRightNode(node0), boxset1->getRightNode(node1), false);
-
- } // else if node1 is not a leaf
- } // else if node0 is not a leaf
-}
-
-void btGImpactQuantizedBvh::find_collision(const btGImpactQuantizedBvh* boxset0, const btTransform& trans0,
- const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
- btPairSet& collision_pairs)
-{
- if (boxset0->getNodeCount() == 0 || boxset1->getNodeCount() == 0) return;
-
- BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
-
- trans_cache_1to0.calc_from_homogenic(trans0, trans1);
-
-#ifdef TRI_COLLISION_PROFILING
- bt_begin_gim02_q_tree_time();
-#endif //TRI_COLLISION_PROFILING
-
- _find_quantized_collision_pairs_recursive(
- boxset0, boxset1,
- &collision_pairs, trans_cache_1to0, 0, 0, true);
-#ifdef TRI_COLLISION_PROFILING
- bt_end_gim02_q_tree_time();
-#endif //TRI_COLLISION_PROFILING
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
deleted file mode 100644
index b231c1e832..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvh.h
+++ /dev/null
@@ -1,298 +0,0 @@
-#ifndef GIM_QUANTIZED_SET_H_INCLUDED
-#define GIM_QUANTIZED_SET_H_INCLUDED
-
-/*! \file btGImpactQuantizedBvh.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGImpactBvh.h"
-#include "btQuantization.h"
-#include "btGImpactQuantizedBvhStructs.h"
-
-class GIM_QUANTIZED_BVH_NODE_ARRAY : public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
-{
-};
-
-//! Basic Box tree structure
-class btQuantizedBvhTree
-{
-protected:
- int m_num_nodes;
- GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
- btAABB m_global_bound;
- btVector3 m_bvhQuantization;
-
-protected:
- void calc_quantization(GIM_BVH_DATA_ARRAY& primitive_boxes, btScalar boundMargin = btScalar(1.0));
-
- int _sort_and_calc_splitting_index(
- GIM_BVH_DATA_ARRAY& primitive_boxes,
- int startIndex, int endIndex, int splitAxis);
-
- int _calc_splitting_axis(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
-
- void _build_sub_tree(GIM_BVH_DATA_ARRAY& primitive_boxes, int startIndex, int endIndex);
-
-public:
- btQuantizedBvhTree()
- {
- m_num_nodes = 0;
- }
-
- //! prototype functions for box tree management
- //!@{
- void build_tree(GIM_BVH_DATA_ARRAY& primitive_boxes);
-
- SIMD_FORCE_INLINE void quantizePoint(
- unsigned short* quantizedpoint, const btVector3& point) const
- {
- bt_quantize_clamp(quantizedpoint, point, m_global_bound.m_min, m_global_bound.m_max, m_bvhQuantization);
- }
-
- SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
- int node_index,
- unsigned short* quantizedMin, unsigned short* quantizedMax) const
- {
- return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin, quantizedMax);
- }
-
- SIMD_FORCE_INLINE void clearNodes()
- {
- m_node_array.clear();
- m_num_nodes = 0;
- }
-
- //! node count
- SIMD_FORCE_INLINE int getNodeCount() const
- {
- return m_num_nodes;
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
- {
- return m_node_array[nodeindex].isLeafNode();
- }
-
- SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
- {
- return m_node_array[nodeindex].getDataIndex();
- }
-
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
- {
- bound.m_min = bt_unquantize(
- m_node_array[nodeindex].m_quantizedAabbMin,
- m_global_bound.m_min, m_bvhQuantization);
-
- bound.m_max = bt_unquantize(
- m_node_array[nodeindex].m_quantizedAabbMax,
- m_global_bound.m_min, m_bvhQuantization);
- }
-
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
- {
- bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMin,
- bound.m_min,
- m_global_bound.m_min,
- m_global_bound.m_max,
- m_bvhQuantization);
-
- bt_quantize_clamp(m_node_array[nodeindex].m_quantizedAabbMax,
- bound.m_max,
- m_global_bound.m_min,
- m_global_bound.m_max,
- m_bvhQuantization);
- }
-
- SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
- {
- return nodeindex + 1;
- }
-
- SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
- {
- if (m_node_array[nodeindex + 1].isLeafNode()) return nodeindex + 2;
- return nodeindex + 1 + m_node_array[nodeindex + 1].getEscapeIndex();
- }
-
- SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
- {
- return m_node_array[nodeindex].getEscapeIndex();
- }
-
- SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
- {
- return &m_node_array[index];
- }
-
- //!@}
-};
-
-//! Structure for containing Boxes
-/*!
-This class offers an structure for managing a box tree of primitives.
-Requires a Primitive prototype (like btPrimitiveManagerBase )
-*/
-class btGImpactQuantizedBvh
-{
-protected:
- btQuantizedBvhTree m_box_tree;
- btPrimitiveManagerBase* m_primitive_manager;
-
-protected:
- //stackless refit
- void refit();
-
-public:
- //! this constructor doesn't build the tree. you must call buildSet
- btGImpactQuantizedBvh()
- {
- m_primitive_manager = NULL;
- }
-
- //! this constructor doesn't build the tree. you must call buildSet
- btGImpactQuantizedBvh(btPrimitiveManagerBase* primitive_manager)
- {
- m_primitive_manager = primitive_manager;
- }
-
- SIMD_FORCE_INLINE btAABB getGlobalBox() const
- {
- btAABB totalbox;
- getNodeBound(0, totalbox);
- return totalbox;
- }
-
- SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase* primitive_manager)
- {
- m_primitive_manager = primitive_manager;
- }
-
- SIMD_FORCE_INLINE btPrimitiveManagerBase* getPrimitiveManager() const
- {
- return m_primitive_manager;
- }
-
- //! node manager prototype functions
- ///@{
-
- //! this attemps to refit the box set.
- SIMD_FORCE_INLINE void update()
- {
- refit();
- }
-
- //! this rebuild the entire set
- void buildSet();
-
- //! returns the indices of the primitives in the m_primitive_manager
- bool boxQuery(const btAABB& box, btAlignedObjectArray<int>& collided_results) const;
-
- //! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB& box,
- const btTransform& transform, btAlignedObjectArray<int>& collided_results) const
- {
- btAABB transbox = box;
- transbox.appy_transform(transform);
- return boxQuery(transbox, collided_results);
- }
-
- //! returns the indices of the primitives in the m_primitive_manager
- bool rayQuery(
- const btVector3& ray_dir, const btVector3& ray_origin,
- btAlignedObjectArray<int>& collided_results) const;
-
- //! tells if this set has hierarcht
- SIMD_FORCE_INLINE bool hasHierarchy() const
- {
- return true;
- }
-
- //! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
- {
- return m_primitive_manager->is_trimesh();
- }
-
- //! node count
- SIMD_FORCE_INLINE int getNodeCount() const
- {
- return m_box_tree.getNodeCount();
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
- {
- return m_box_tree.isLeafNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
- {
- return m_box_tree.getNodeData(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB& bound) const
- {
- m_box_tree.getNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB& bound)
- {
- m_box_tree.setNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
- {
- return m_box_tree.getLeftNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
- {
- return m_box_tree.getRightNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
- {
- return m_box_tree.getEscapeNodeIndex(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex, btPrimitiveTriangle& triangle) const
- {
- m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex), triangle);
- }
-
- SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE* get_node_pointer(int index = 0) const
- {
- return m_box_tree.get_node_pointer(index);
- }
-
-#ifdef TRI_COLLISION_PROFILING
- static float getAverageTreeCollisionTime();
-#endif //TRI_COLLISION_PROFILING
-
- static void find_collision(const btGImpactQuantizedBvh* boxset1, const btTransform& trans1,
- const btGImpactQuantizedBvh* boxset2, const btTransform& trans2,
- btPairSet& collision_pairs);
-};
-
-#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
deleted file mode 100644
index bd50cb5b87..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactQuantizedBvhStructs.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
-#define GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
-
-/*! \file btGImpactQuantizedBvh.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGImpactBvh.h"
-#include "btQuantization.h"
-
-///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
-///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
-ATTRIBUTE_ALIGNED16(struct)
-BT_QUANTIZED_BVH_NODE
-{
- //12 bytes
- unsigned short int m_quantizedAabbMin[3];
- unsigned short int m_quantizedAabbMax[3];
- //4 bytes
- int m_escapeIndexOrDataIndex;
-
- BT_QUANTIZED_BVH_NODE()
- {
- m_escapeIndexOrDataIndex = 0;
- }
-
- SIMD_FORCE_INLINE bool isLeafNode() const
- {
- //skipindex is negative (internal node), triangleindex >=0 (leafnode)
- return (m_escapeIndexOrDataIndex >= 0);
- }
-
- SIMD_FORCE_INLINE int getEscapeIndex() const
- {
- //btAssert(m_escapeIndexOrDataIndex < 0);
- return -m_escapeIndexOrDataIndex;
- }
-
- SIMD_FORCE_INLINE void setEscapeIndex(int index)
- {
- m_escapeIndexOrDataIndex = -index;
- }
-
- SIMD_FORCE_INLINE int getDataIndex() const
- {
- //btAssert(m_escapeIndexOrDataIndex >= 0);
-
- return m_escapeIndexOrDataIndex;
- }
-
- SIMD_FORCE_INLINE void setDataIndex(int index)
- {
- m_escapeIndexOrDataIndex = index;
- }
-
- SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
- unsigned short* quantizedMin, unsigned short* quantizedMax) const
- {
- if (m_quantizedAabbMin[0] > quantizedMax[0] ||
- m_quantizedAabbMax[0] < quantizedMin[0] ||
- m_quantizedAabbMin[1] > quantizedMax[1] ||
- m_quantizedAabbMax[1] < quantizedMin[1] ||
- m_quantizedAabbMin[2] > quantizedMax[2] ||
- m_quantizedAabbMax[2] < quantizedMin[2])
- {
- return false;
- }
- return true;
- }
-};
-
-#endif // GIM_QUANTIZED_SET_STRUCTS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp
deleted file mode 100644
index 34c229a3ab..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGImpactShape.h"
-#include "btGImpactMassUtil.h"
-
-btGImpactMeshShapePart::btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part)
-{
- // moved from .h to .cpp because of conditional compilation
- // (The setting of BT_THREADSAFE may differ between various cpp files, so it is best to
- // avoid using it in h files)
- m_primitive_manager.m_meshInterface = meshInterface;
- m_primitive_manager.m_part = part;
- m_box_set.setPrimitiveManager(&m_primitive_manager);
-#if BT_THREADSAFE
- // If threadsafe is requested, this object uses a different lock/unlock
- // model with the btStridingMeshInterface -- lock once when the object is constructed
- // and unlock once in the destructor.
- // The other way of locking and unlocking for each collision check in the narrowphase
- // is not threadsafe. Note these are not thread-locks, they are calls to the meshInterface's
- // getLockedReadOnlyVertexIndexBase virtual function, which by default just returns a couple of
- // pointers. In theory a client could override the lock function to do all sorts of
- // things like reading data from GPU memory, or decompressing data on the fly, but such things
- // do not seem all that likely or useful, given the performance cost.
- m_primitive_manager.lock();
-#endif
-}
-
-btGImpactMeshShapePart::~btGImpactMeshShapePart()
-{
- // moved from .h to .cpp because of conditional compilation
-#if BT_THREADSAFE
- m_primitive_manager.unlock();
-#endif
-}
-
-void btGImpactMeshShapePart::lockChildShapes() const
-{
- // moved from .h to .cpp because of conditional compilation
-#if !BT_THREADSAFE
- // called in the narrowphase -- not threadsafe!
- void* dummy = (void*)(m_box_set.getPrimitiveManager());
- TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
- dummymanager->lock();
-#endif
-}
-
-void btGImpactMeshShapePart::unlockChildShapes() const
-{
- // moved from .h to .cpp because of conditional compilation
-#if !BT_THREADSAFE
- // called in the narrowphase -- not threadsafe!
- void* dummy = (void*)(m_box_set.getPrimitiveManager());
- TrimeshPrimitiveManager* dummymanager = static_cast<TrimeshPrimitiveManager*>(dummy);
- dummymanager->unlock();
-#endif
-}
-
-#define CALC_EXACT_INERTIA 1
-
-void btGImpactCompoundShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- lockChildShapes();
-#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f, 0.f, 0.f);
-
- int i = this->getNumChildShapes();
- btScalar shapemass = mass / btScalar(i);
-
- while (i--)
- {
- btVector3 temp_inertia;
- m_childShapes[i]->calculateLocalInertia(shapemass, temp_inertia);
- if (childrenHasTransform())
- {
- inertia = gim_inertia_add_transformed(inertia, temp_inertia, m_childTransforms[i]);
- }
- else
- {
- inertia = gim_inertia_add_transformed(inertia, temp_inertia, btTransform::getIdentity());
- }
- }
-
-#else
-
- // Calc box inertia
-
- btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-
-#endif
- unlockChildShapes();
-}
-
-void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
- lockChildShapes();
-
-#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f, 0.f, 0.f);
-
- int i = this->getVertexCount();
- btScalar pointmass = mass / btScalar(i);
-
- while (i--)
- {
- btVector3 pointintertia;
- this->getVertex(i, pointintertia);
- pointintertia = gim_get_point_inertia(pointintertia, pointmass);
- inertia += pointintertia;
- }
-
-#else
-
- // Calc box inertia
-
- btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-
-#endif
-
- unlockChildShapes();
-}
-
-void btGImpactMeshShape::calculateLocalInertia(btScalar mass, btVector3& inertia) const
-{
-#ifdef CALC_EXACT_INERTIA
- inertia.setValue(0.f, 0.f, 0.f);
-
- int i = this->getMeshPartCount();
- btScalar partmass = mass / btScalar(i);
-
- while (i--)
- {
- btVector3 partinertia;
- getMeshPart(i)->calculateLocalInertia(partmass, partinertia);
- inertia += partinertia;
- }
-
-#else
-
- // Calc box inertia
-
- btScalar lx = m_localAABB.m_max[0] - m_localAABB.m_min[0];
- btScalar ly = m_localAABB.m_max[1] - m_localAABB.m_min[1];
- btScalar lz = m_localAABB.m_max[2] - m_localAABB.m_min[2];
- const btScalar x2 = lx * lx;
- const btScalar y2 = ly * ly;
- const btScalar z2 = lz * lz;
- const btScalar scaledmass = mass * btScalar(0.08333333);
-
- inertia = scaledmass * (btVector3(y2 + z2, x2 + z2, x2 + y2));
-
-#endif
-}
-
-void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
-{
-}
-
-void btGImpactMeshShapePart::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
-{
- lockChildShapes();
-
- btAlignedObjectArray<int> collided;
- btVector3 rayDir(rayTo - rayFrom);
- rayDir.normalize();
- m_box_set.rayQuery(rayDir, rayFrom, collided);
-
- if (collided.size() == 0)
- {
- unlockChildShapes();
- return;
- }
-
- int part = (int)getPart();
- btPrimitiveTriangle triangle;
- int i = collided.size();
- while (i--)
- {
- getPrimitiveTriangle(collided[i], triangle);
- callback->processTriangle(triangle.m_vertices, part, collided[i]);
- }
- unlockChildShapes();
-}
-
-void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- lockChildShapes();
- btAABB box;
- box.m_min = aabbMin;
- box.m_max = aabbMax;
-
- btAlignedObjectArray<int> collided;
- m_box_set.boxQuery(box, collided);
-
- if (collided.size() == 0)
- {
- unlockChildShapes();
- return;
- }
-
- int part = (int)getPart();
- btPrimitiveTriangle triangle;
- int i = collided.size();
- while (i--)
- {
- this->getPrimitiveTriangle(collided[i], triangle);
- callback->processTriangle(triangle.m_vertices, part, collided[i]);
- }
- unlockChildShapes();
-}
-
-void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
-{
- int i = m_mesh_parts.size();
- while (i--)
- {
- m_mesh_parts[i]->processAllTriangles(callback, aabbMin, aabbMax);
- }
-}
-
-void btGImpactMeshShape::processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const
-{
- int i = m_mesh_parts.size();
- while (i--)
- {
- m_mesh_parts[i]->processAllTrianglesRay(callback, rayFrom, rayTo);
- }
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btGImpactMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btGImpactMeshShapeData* trimeshData = (btGImpactMeshShapeData*)dataBuffer;
-
- btCollisionShape::serialize(&trimeshData->m_collisionShapeData, serializer);
-
- m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
-
- trimeshData->m_collisionMargin = float(m_collisionMargin);
-
- localScaling.serializeFloat(trimeshData->m_localScaling);
-
- trimeshData->m_gimpactSubType = int(getGImpactShapeType());
-
- return "btGImpactMeshShapeData";
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h b/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
deleted file mode 100644
index cc91079579..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGImpactShape.h
+++ /dev/null
@@ -1,1115 +0,0 @@
-/*! \file btGImpactShape.h
-\author Francisco Len Nßjera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef GIMPACT_SHAPE_H
-#define GIMPACT_SHAPE_H
-
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include "BulletCollision/CollisionShapes/btConcaveShape.h"
-#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-#include "btGImpactQuantizedBvh.h" // box tree class
-
-//! declare Quantized trees, (you can change to float based trees)
-typedef btGImpactQuantizedBvh btGImpactBoxSet;
-
-enum eGIMPACT_SHAPE_TYPE
-{
- CONST_GIMPACT_COMPOUND_SHAPE = 0,
- CONST_GIMPACT_TRIMESH_SHAPE_PART,
- CONST_GIMPACT_TRIMESH_SHAPE
-};
-
-//! Helper class for tetrahedrons
-class btTetrahedronShapeEx : public btBU_Simplex1to4
-{
-public:
- btTetrahedronShapeEx()
- {
- m_numVertices = 4;
- }
-
- SIMD_FORCE_INLINE void setVertices(
- const btVector3& v0, const btVector3& v1,
- const btVector3& v2, const btVector3& v3)
- {
- m_vertices[0] = v0;
- m_vertices[1] = v1;
- m_vertices[2] = v2;
- m_vertices[3] = v3;
- recalcLocalAabb();
- }
-};
-
-//! Base class for gimpact shapes
-class btGImpactShapeInterface : public btConcaveShape
-{
-protected:
- btAABB m_localAABB;
- bool m_needs_update;
- btVector3 localScaling;
- btGImpactBoxSet m_box_set; // optionally boxset
-
- //! use this function for perfofm refit in bounding boxes
- //! use this function for perfofm refit in bounding boxes
- virtual void calcLocalAABB()
- {
- lockChildShapes();
- if (m_box_set.getNodeCount() == 0)
- {
- m_box_set.buildSet();
- }
- else
- {
- m_box_set.update();
- }
- unlockChildShapes();
-
- m_localAABB = m_box_set.getGlobalBox();
- }
-
-public:
- btGImpactShapeInterface()
- {
- m_shapeType = GIMPACT_SHAPE_PROXYTYPE;
- m_localAABB.invalidate();
- m_needs_update = true;
- localScaling.setValue(1.f, 1.f, 1.f);
- }
-
- //! performs refit operation
- /*!
- Updates the entire Box set of this shape.
- \pre postUpdate() must be called for attemps to calculating the box set, else this function
- will does nothing.
- \post if m_needs_update == true, then it calls calcLocalAABB();
- */
- SIMD_FORCE_INLINE void updateBound()
- {
- if (!m_needs_update) return;
- calcLocalAABB();
- m_needs_update = false;
- }
-
- //! If the Bounding box is not updated, then this class attemps to calculate it.
- /*!
- \post Calls updateBound() for update the box set.
- */
- void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- btAABB transformedbox = m_localAABB;
- transformedbox.appy_transform(t);
- aabbMin = transformedbox.m_min;
- aabbMax = transformedbox.m_max;
- }
-
- //! Tells to this object that is needed to refit the box set
- virtual void postUpdate()
- {
- m_needs_update = true;
- }
-
- //! Obtains the local box, which is the global calculated box of the total of subshapes
- SIMD_FORCE_INLINE const btAABB& getLocalBox()
- {
- return m_localAABB;
- }
-
- virtual int getShapeType() const
- {
- return GIMPACT_SHAPE_PROXYTYPE;
- }
-
- /*!
- \post You must call updateBound() for update the box set.
- */
- virtual void setLocalScaling(const btVector3& scaling)
- {
- localScaling = scaling;
- postUpdate();
- }
-
- virtual const btVector3& getLocalScaling() const
- {
- return localScaling;
- }
-
- virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
- int i = getNumChildShapes();
- while (i--)
- {
- btCollisionShape* child = getChildShape(i);
- child->setMargin(margin);
- }
-
- m_needs_update = true;
- }
-
- //! Subshape member functions
- //!@{
-
- //! Base method for determinig which kind of GIMPACT shape we get
- virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0;
-
- //! gets boxset
- SIMD_FORCE_INLINE const btGImpactBoxSet* getBoxSet() const
- {
- return &m_box_set;
- }
-
- //! Determines if this class has a hierarchy structure for sorting its primitives
- SIMD_FORCE_INLINE bool hasBoxSet() const
- {
- if (m_box_set.getNodeCount() == 0) return false;
- return true;
- }
-
- //! Obtains the primitive manager
- virtual const btPrimitiveManagerBase* getPrimitiveManager() const = 0;
-
- //! Gets the number of children
- virtual int getNumChildShapes() const = 0;
-
- //! if true, then its children must get transforms.
- virtual bool childrenHasTransform() const = 0;
-
- //! Determines if this shape has triangles
- virtual bool needsRetrieveTriangles() const = 0;
-
- //! Determines if this shape has tetrahedrons
- virtual bool needsRetrieveTetrahedrons() const = 0;
-
- virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const = 0;
-
- virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const = 0;
-
- //! call when reading child shapes
- virtual void lockChildShapes() const
- {
- }
-
- virtual void unlockChildShapes() const
- {
- }
-
- //! if this trimesh
- SIMD_FORCE_INLINE void getPrimitiveTriangle(int index, btPrimitiveTriangle& triangle) const
- {
- getPrimitiveManager()->get_primitive_triangle(index, triangle);
- }
-
- //! Retrieves the bound from a child
- /*!
- */
- virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- btAABB child_aabb;
- getPrimitiveManager()->get_primitive_box(child_index, child_aabb);
- child_aabb.appy_transform(t);
- aabbMin = child_aabb.m_min;
- aabbMax = child_aabb.m_max;
- }
-
- //! Gets the children
- virtual btCollisionShape* getChildShape(int index) = 0;
-
- //! Gets the child
- virtual const btCollisionShape* getChildShape(int index) const = 0;
-
- //! Gets the children transform
- virtual btTransform getChildTransform(int index) const = 0;
-
- //! Sets the children transform
- /*!
- \post You must call updateBound() for update the box set.
- */
- virtual void setChildTransform(int index, const btTransform& transform) = 0;
-
- //!@}
-
- //! virtual method for ray collision
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
- {
- (void)rayFrom;
- (void)rayTo;
- (void)resultCallback;
- }
-
- //! Function for retrieve triangles.
- /*!
- It gives the triangles in local space
- */
- virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
- {
- (void)callback;
- (void)aabbMin;
- (void)aabbMax;
- }
-
- //! Function for retrieve triangles.
- /*!
- It gives the triangles in local space
- */
- virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/, const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
- {
- }
-
- //!@}
-};
-
-//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
-/*!
-This class only can manage Convex subshapes
-*/
-class btGImpactCompoundShape : public btGImpactShapeInterface
-{
-public:
- //! compound primitive manager
- class CompoundPrimitiveManager : public btPrimitiveManagerBase
- {
- public:
- virtual ~CompoundPrimitiveManager() {}
- btGImpactCompoundShape* m_compoundShape;
-
- CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
- : btPrimitiveManagerBase()
- {
- m_compoundShape = compound.m_compoundShape;
- }
-
- CompoundPrimitiveManager(btGImpactCompoundShape* compoundShape)
- {
- m_compoundShape = compoundShape;
- }
-
- CompoundPrimitiveManager()
- {
- m_compoundShape = NULL;
- }
-
- virtual bool is_trimesh() const
- {
- return false;
- }
-
- virtual int get_primitive_count() const
- {
- return (int)m_compoundShape->getNumChildShapes();
- }
-
- virtual void get_primitive_box(int prim_index, btAABB& primbox) const
- {
- btTransform prim_trans;
- if (m_compoundShape->childrenHasTransform())
- {
- prim_trans = m_compoundShape->getChildTransform(prim_index);
- }
- else
- {
- prim_trans.setIdentity();
- }
- const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
- shape->getAabb(prim_trans, primbox.m_min, primbox.m_max);
- }
-
- virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
- {
- btAssert(0);
- (void)prim_index;
- (void)triangle;
- }
- };
-
-protected:
- CompoundPrimitiveManager m_primitive_manager;
- btAlignedObjectArray<btTransform> m_childTransforms;
- btAlignedObjectArray<btCollisionShape*> m_childShapes;
-
-public:
- btGImpactCompoundShape(bool children_has_transform = true)
- {
- (void)children_has_transform;
- m_primitive_manager.m_compoundShape = this;
- m_box_set.setPrimitiveManager(&m_primitive_manager);
- }
-
- virtual ~btGImpactCompoundShape()
- {
- }
-
- //! if true, then its children must get transforms.
- virtual bool childrenHasTransform() const
- {
- if (m_childTransforms.size() == 0) return false;
- return true;
- }
-
- //! Obtains the primitive manager
- virtual const btPrimitiveManagerBase* getPrimitiveManager() const
- {
- return &m_primitive_manager;
- }
-
- //! Obtains the compopund primitive manager
- SIMD_FORCE_INLINE CompoundPrimitiveManager* getCompoundPrimitiveManager()
- {
- return &m_primitive_manager;
- }
-
- //! Gets the number of children
- virtual int getNumChildShapes() const
- {
- return m_childShapes.size();
- }
-
- //! Use this method for adding children. Only Convex shapes are allowed.
- void addChildShape(const btTransform& localTransform, btCollisionShape* shape)
- {
- btAssert(shape->isConvex());
- m_childTransforms.push_back(localTransform);
- m_childShapes.push_back(shape);
- }
-
- //! Use this method for adding children. Only Convex shapes are allowed.
- void addChildShape(btCollisionShape* shape)
- {
- btAssert(shape->isConvex());
- m_childShapes.push_back(shape);
- }
-
- //! Gets the children
- virtual btCollisionShape* getChildShape(int index)
- {
- return m_childShapes[index];
- }
-
- //! Gets the children
- virtual const btCollisionShape* getChildShape(int index) const
- {
- return m_childShapes[index];
- }
-
- //! Retrieves the bound from a child
- /*!
- */
- virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- if (childrenHasTransform())
- {
- m_childShapes[child_index]->getAabb(t * m_childTransforms[child_index], aabbMin, aabbMax);
- }
- else
- {
- m_childShapes[child_index]->getAabb(t, aabbMin, aabbMax);
- }
- }
-
- //! Gets the children transform
- virtual btTransform getChildTransform(int index) const
- {
- btAssert(m_childTransforms.size() == m_childShapes.size());
- return m_childTransforms[index];
- }
-
- //! Sets the children transform
- /*!
- \post You must call updateBound() for update the box set.
- */
- virtual void setChildTransform(int index, const btTransform& transform)
- {
- btAssert(m_childTransforms.size() == m_childShapes.size());
- m_childTransforms[index] = transform;
- postUpdate();
- }
-
- //! Determines if this shape has triangles
- virtual bool needsRetrieveTriangles() const
- {
- return false;
- }
-
- //! Determines if this shape has tetrahedrons
- virtual bool needsRetrieveTetrahedrons() const
- {
- return false;
- }
-
- virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
- {
- (void)prim_index;
- (void)triangle;
- btAssert(0);
- }
-
- virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
- {
- (void)prim_index;
- (void)tetrahedron;
- btAssert(0);
- }
-
- //! Calculates the exact inertia tensor for this shape
- virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
-
- virtual const char* getName() const
- {
- return "GImpactCompound";
- }
-
- virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
- {
- return CONST_GIMPACT_COMPOUND_SHAPE;
- }
-};
-
-//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
-/*!
-- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
-- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
-- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
-
-*/
-class btGImpactMeshShapePart : public btGImpactShapeInterface
-{
-public:
- //! Trimesh primitive manager
- /*!
- Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
- */
- class TrimeshPrimitiveManager : public btPrimitiveManagerBase
- {
- public:
- btScalar m_margin;
- btStridingMeshInterface* m_meshInterface;
- btVector3 m_scale;
- int m_part;
- int m_lock_count;
- const unsigned char* vertexbase;
- int numverts;
- PHY_ScalarType type;
- int stride;
- const unsigned char* indexbase;
- int indexstride;
- int numfaces;
- PHY_ScalarType indicestype;
-
- TrimeshPrimitiveManager()
- {
- m_meshInterface = NULL;
- m_part = 0;
- m_margin = 0.01f;
- m_scale = btVector3(1.f, 1.f, 1.f);
- m_lock_count = 0;
- vertexbase = 0;
- numverts = 0;
- stride = 0;
- indexbase = 0;
- indexstride = 0;
- numfaces = 0;
- }
-
- TrimeshPrimitiveManager(const TrimeshPrimitiveManager& manager)
- : btPrimitiveManagerBase()
- {
- m_meshInterface = manager.m_meshInterface;
- m_part = manager.m_part;
- m_margin = manager.m_margin;
- m_scale = manager.m_scale;
- m_lock_count = 0;
- vertexbase = 0;
- numverts = 0;
- stride = 0;
- indexbase = 0;
- indexstride = 0;
- numfaces = 0;
- }
-
- TrimeshPrimitiveManager(
- btStridingMeshInterface* meshInterface, int part)
- {
- m_meshInterface = meshInterface;
- m_part = part;
- m_scale = m_meshInterface->getScaling();
- m_margin = 0.1f;
- m_lock_count = 0;
- vertexbase = 0;
- numverts = 0;
- stride = 0;
- indexbase = 0;
- indexstride = 0;
- numfaces = 0;
- }
-
- virtual ~TrimeshPrimitiveManager() {}
-
- void lock()
- {
- if (m_lock_count > 0)
- {
- m_lock_count++;
- return;
- }
- m_meshInterface->getLockedReadOnlyVertexIndexBase(
- &vertexbase, numverts,
- type, stride, &indexbase, indexstride, numfaces, indicestype, m_part);
-
- m_lock_count = 1;
- }
-
- void unlock()
- {
- if (m_lock_count == 0) return;
- if (m_lock_count > 1)
- {
- --m_lock_count;
- return;
- }
- m_meshInterface->unLockReadOnlyVertexBase(m_part);
- vertexbase = NULL;
- m_lock_count = 0;
- }
-
- virtual bool is_trimesh() const
- {
- return true;
- }
-
- virtual int get_primitive_count() const
- {
- return (int)numfaces;
- }
-
- SIMD_FORCE_INLINE int get_vertex_count() const
- {
- return (int)numverts;
- }
-
- SIMD_FORCE_INLINE void get_indices(int face_index, unsigned int& i0, unsigned int& i1, unsigned int& i2) const
- {
- if (indicestype == PHY_SHORT)
- {
- unsigned short* s_indices = (unsigned short*)(indexbase + face_index * indexstride);
- i0 = s_indices[0];
- i1 = s_indices[1];
- i2 = s_indices[2];
- }
- else if (indicestype == PHY_INTEGER)
- {
- unsigned int* i_indices = (unsigned int*)(indexbase + face_index * indexstride);
- i0 = i_indices[0];
- i1 = i_indices[1];
- i2 = i_indices[2];
- }
- else
- {
- btAssert(indicestype == PHY_UCHAR);
- unsigned char* i_indices = (unsigned char*)(indexbase + face_index * indexstride);
- i0 = i_indices[0];
- i1 = i_indices[1];
- i2 = i_indices[2];
- }
- }
-
- SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3& vertex) const
- {
- if (type == PHY_DOUBLE)
- {
- double* dvertices = (double*)(vertexbase + vertex_index * stride);
- vertex[0] = btScalar(dvertices[0] * m_scale[0]);
- vertex[1] = btScalar(dvertices[1] * m_scale[1]);
- vertex[2] = btScalar(dvertices[2] * m_scale[2]);
- }
- else
- {
- float* svertices = (float*)(vertexbase + vertex_index * stride);
- vertex[0] = svertices[0] * m_scale[0];
- vertex[1] = svertices[1] * m_scale[1];
- vertex[2] = svertices[2] * m_scale[2];
- }
- }
-
- virtual void get_primitive_box(int prim_index, btAABB& primbox) const
- {
- btPrimitiveTriangle triangle;
- get_primitive_triangle(prim_index, triangle);
- primbox.calc_from_triangle_margin(
- triangle.m_vertices[0],
- triangle.m_vertices[1], triangle.m_vertices[2], triangle.m_margin);
- }
-
- virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
- {
- unsigned int indices[3];
- get_indices(prim_index, indices[0], indices[1], indices[2]);
- get_vertex(indices[0], triangle.m_vertices[0]);
- get_vertex(indices[1], triangle.m_vertices[1]);
- get_vertex(indices[2], triangle.m_vertices[2]);
- triangle.m_margin = m_margin;
- }
-
- SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index, btTriangleShapeEx& triangle) const
- {
- unsigned int indices[3];
- get_indices(prim_index, indices[0], indices[1], indices[2]);
- get_vertex(indices[0], triangle.m_vertices1[0]);
- get_vertex(indices[1], triangle.m_vertices1[1]);
- get_vertex(indices[2], triangle.m_vertices1[2]);
- triangle.setMargin(m_margin);
- }
- };
-
-protected:
- TrimeshPrimitiveManager m_primitive_manager;
-
-public:
- btGImpactMeshShapePart()
- {
- m_box_set.setPrimitiveManager(&m_primitive_manager);
- }
-
- btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part);
- virtual ~btGImpactMeshShapePart();
-
- //! if true, then its children must get transforms.
- virtual bool childrenHasTransform() const
- {
- return false;
- }
-
- //! call when reading child shapes
- virtual void lockChildShapes() const;
- virtual void unlockChildShapes() const;
-
- //! Gets the number of children
- virtual int getNumChildShapes() const
- {
- return m_primitive_manager.get_primitive_count();
- }
-
- //! Gets the children
- virtual btCollisionShape* getChildShape(int index)
- {
- (void)index;
- btAssert(0);
- return NULL;
- }
-
- //! Gets the child
- virtual const btCollisionShape* getChildShape(int index) const
- {
- (void)index;
- btAssert(0);
- return NULL;
- }
-
- //! Gets the children transform
- virtual btTransform getChildTransform(int index) const
- {
- (void)index;
- btAssert(0);
- return btTransform();
- }
-
- //! Sets the children transform
- /*!
- \post You must call updateBound() for update the box set.
- */
- virtual void setChildTransform(int index, const btTransform& transform)
- {
- (void)index;
- (void)transform;
- btAssert(0);
- }
-
- //! Obtains the primitive manager
- virtual const btPrimitiveManagerBase* getPrimitiveManager() const
- {
- return &m_primitive_manager;
- }
-
- SIMD_FORCE_INLINE TrimeshPrimitiveManager* getTrimeshPrimitiveManager()
- {
- return &m_primitive_manager;
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
-
- virtual const char* getName() const
- {
- return "GImpactMeshShapePart";
- }
-
- virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
- {
- return CONST_GIMPACT_TRIMESH_SHAPE_PART;
- }
-
- //! Determines if this shape has triangles
- virtual bool needsRetrieveTriangles() const
- {
- return true;
- }
-
- //! Determines if this shape has tetrahedrons
- virtual bool needsRetrieveTetrahedrons() const
- {
- return false;
- }
-
- virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
- {
- m_primitive_manager.get_bullet_triangle(prim_index, triangle);
- }
-
- virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
- {
- (void)prim_index;
- (void)tetrahedron;
- btAssert(0);
- }
-
- SIMD_FORCE_INLINE int getVertexCount() const
- {
- return m_primitive_manager.get_vertex_count();
- }
-
- SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3& vertex) const
- {
- m_primitive_manager.get_vertex(vertex_index, vertex);
- }
-
- SIMD_FORCE_INLINE void setMargin(btScalar margin)
- {
- m_primitive_manager.m_margin = margin;
- postUpdate();
- }
-
- SIMD_FORCE_INLINE btScalar getMargin() const
- {
- return m_primitive_manager.m_margin;
- }
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- m_primitive_manager.m_scale = scaling;
- postUpdate();
- }
-
- virtual const btVector3& getLocalScaling() const
- {
- return m_primitive_manager.m_scale;
- }
-
- SIMD_FORCE_INLINE int getPart() const
- {
- return (int)m_primitive_manager.m_part;
- }
-
- virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
- virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
-};
-
-//! This class manages a mesh supplied by the btStridingMeshInterface interface.
-/*!
-Set of btGImpactMeshShapePart parts
-- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
-
-- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
-
-*/
-class btGImpactMeshShape : public btGImpactShapeInterface
-{
- btStridingMeshInterface* m_meshInterface;
-
-protected:
- btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
- void buildMeshParts(btStridingMeshInterface* meshInterface)
- {
- for (int i = 0; i < meshInterface->getNumSubParts(); ++i)
- {
- btGImpactMeshShapePart* newpart = new btGImpactMeshShapePart(meshInterface, i);
- m_mesh_parts.push_back(newpart);
- }
- }
-
- //! use this function for perfofm refit in bounding boxes
- virtual void calcLocalAABB()
- {
- m_localAABB.invalidate();
- int i = m_mesh_parts.size();
- while (i--)
- {
- m_mesh_parts[i]->updateBound();
- m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
- }
- }
-
-public:
- btGImpactMeshShape(btStridingMeshInterface* meshInterface)
- {
- m_meshInterface = meshInterface;
- buildMeshParts(meshInterface);
- }
-
- virtual ~btGImpactMeshShape()
- {
- int i = m_mesh_parts.size();
- while (i--)
- {
- btGImpactMeshShapePart* part = m_mesh_parts[i];
- delete part;
- }
- m_mesh_parts.clear();
- }
-
- btStridingMeshInterface* getMeshInterface()
- {
- return m_meshInterface;
- }
-
- const btStridingMeshInterface* getMeshInterface() const
- {
- return m_meshInterface;
- }
-
- int getMeshPartCount() const
- {
- return m_mesh_parts.size();
- }
-
- btGImpactMeshShapePart* getMeshPart(int index)
- {
- return m_mesh_parts[index];
- }
-
- const btGImpactMeshShapePart* getMeshPart(int index) const
- {
- return m_mesh_parts[index];
- }
-
- virtual void setLocalScaling(const btVector3& scaling)
- {
- localScaling = scaling;
-
- int i = m_mesh_parts.size();
- while (i--)
- {
- btGImpactMeshShapePart* part = m_mesh_parts[i];
- part->setLocalScaling(scaling);
- }
-
- m_needs_update = true;
- }
-
- virtual void setMargin(btScalar margin)
- {
- m_collisionMargin = margin;
-
- int i = m_mesh_parts.size();
- while (i--)
- {
- btGImpactMeshShapePart* part = m_mesh_parts[i];
- part->setMargin(margin);
- }
-
- m_needs_update = true;
- }
-
- //! Tells to this object that is needed to refit all the meshes
- virtual void postUpdate()
- {
- int i = m_mesh_parts.size();
- while (i--)
- {
- btGImpactMeshShapePart* part = m_mesh_parts[i];
- part->postUpdate();
- }
-
- m_needs_update = true;
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
-
- //! Obtains the primitive manager
- virtual const btPrimitiveManagerBase* getPrimitiveManager() const
- {
- btAssert(0);
- return NULL;
- }
-
- //! Gets the number of children
- virtual int getNumChildShapes() const
- {
- btAssert(0);
- return 0;
- }
-
- //! if true, then its children must get transforms.
- virtual bool childrenHasTransform() const
- {
- btAssert(0);
- return false;
- }
-
- //! Determines if this shape has triangles
- virtual bool needsRetrieveTriangles() const
- {
- btAssert(0);
- return false;
- }
-
- //! Determines if this shape has tetrahedrons
- virtual bool needsRetrieveTetrahedrons() const
- {
- btAssert(0);
- return false;
- }
-
- virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
- {
- (void)prim_index;
- (void)triangle;
- btAssert(0);
- }
-
- virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
- {
- (void)prim_index;
- (void)tetrahedron;
- btAssert(0);
- }
-
- //! call when reading child shapes
- virtual void lockChildShapes() const
- {
- btAssert(0);
- }
-
- virtual void unlockChildShapes() const
- {
- btAssert(0);
- }
-
- //! Retrieves the bound from a child
- /*!
- */
- virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- (void)child_index;
- (void)t;
- (void)aabbMin;
- (void)aabbMax;
- btAssert(0);
- }
-
- //! Gets the children
- virtual btCollisionShape* getChildShape(int index)
- {
- (void)index;
- btAssert(0);
- return NULL;
- }
-
- //! Gets the child
- virtual const btCollisionShape* getChildShape(int index) const
- {
- (void)index;
- btAssert(0);
- return NULL;
- }
-
- //! Gets the children transform
- virtual btTransform getChildTransform(int index) const
- {
- (void)index;
- btAssert(0);
- return btTransform();
- }
-
- //! Sets the children transform
- /*!
- \post You must call updateBound() for update the box set.
- */
- virtual void setChildTransform(int index, const btTransform& transform)
- {
- (void)index;
- (void)transform;
- btAssert(0);
- }
-
- virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
- {
- return CONST_GIMPACT_TRIMESH_SHAPE;
- }
-
- virtual const char* getName() const
- {
- return "GImpactMesh";
- }
-
- virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
-
- //! Function for retrieve triangles.
- /*!
- It gives the triangles in local space
- */
- virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
-
- virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btGImpactMeshShapeData
-{
- btCollisionShapeData m_collisionShapeData;
-
- btStridingMeshInterfaceData m_meshInterface;
-
- btVector3FloatData m_localScaling;
-
- float m_collisionMargin;
-
- int m_gimpactSubType;
-};
-
-SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
-{
- return sizeof(btGImpactMeshShapeData);
-}
-
-#endif //GIMPACT_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
deleted file mode 100644
index bfdb3db5d0..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/*! \file btGenericPoolAllocator.cpp
-\author Francisco Leon Najera. email projectileman@yahoo.com
-
-General purpose allocator class
-*/
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGenericPoolAllocator.h"
-
-/// *************** btGenericMemoryPool ******************///////////
-
-size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
-{
- size_t ptr = BT_UINT_MAX;
-
- if (m_free_nodes_count == 0) return BT_UINT_MAX;
- // find an avaliable free node with the correct size
- size_t revindex = m_free_nodes_count;
-
- while (revindex-- && ptr == BT_UINT_MAX)
- {
- if (m_allocated_sizes[m_free_nodes[revindex]] >= num_elements)
- {
- ptr = revindex;
- }
- }
- if (ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
-
- revindex = ptr;
- ptr = m_free_nodes[revindex];
- // post: ptr contains the node index, and revindex the index in m_free_nodes
-
- size_t finalsize = m_allocated_sizes[ptr];
- finalsize -= num_elements;
-
- m_allocated_sizes[ptr] = num_elements;
-
- // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
-
- if (finalsize > 0) // preserve free node, there are some free memory
- {
- m_free_nodes[revindex] = ptr + num_elements;
- m_allocated_sizes[ptr + num_elements] = finalsize;
- }
- else // delete free node
- {
- // swap with end
- m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count - 1];
- m_free_nodes_count--;
- }
-
- return ptr;
-}
-
-size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
-{
- if (m_allocated_count + num_elements > m_max_element_count) return BT_UINT_MAX;
-
- size_t ptr = m_allocated_count;
-
- m_allocated_sizes[m_allocated_count] = num_elements;
- m_allocated_count += num_elements;
-
- return ptr;
-}
-
-void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
-{
- m_allocated_count = 0;
- m_free_nodes_count = 0;
-
- m_element_size = element_size;
- m_max_element_count = element_count;
-
- m_pool = (unsigned char *)btAlignedAlloc(m_element_size * m_max_element_count, 16);
- m_free_nodes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
- m_allocated_sizes = (size_t *)btAlignedAlloc(sizeof(size_t) * m_max_element_count, 16);
-
- for (size_t i = 0; i < m_max_element_count; i++)
- {
- m_allocated_sizes[i] = 0;
- }
-}
-
-void btGenericMemoryPool::end_pool()
-{
- btAlignedFree(m_pool);
- btAlignedFree(m_free_nodes);
- btAlignedFree(m_allocated_sizes);
- m_allocated_count = 0;
- m_free_nodes_count = 0;
-}
-
-//! Allocates memory in pool
-/*!
-\param size_bytes size in bytes of the buffer
-*/
-void *btGenericMemoryPool::allocate(size_t size_bytes)
-{
- size_t module = size_bytes % m_element_size;
- size_t element_count = size_bytes / m_element_size;
- if (module > 0) element_count++;
-
- size_t alloc_pos = allocate_from_free_nodes(element_count);
- // a free node is found
- if (alloc_pos != BT_UINT_MAX)
- {
- return get_element_data(alloc_pos);
- }
- // allocate directly on pool
- alloc_pos = allocate_from_pool(element_count);
-
- if (alloc_pos == BT_UINT_MAX) return NULL; // not space
- return get_element_data(alloc_pos);
-}
-
-bool btGenericMemoryPool::freeMemory(void *pointer)
-{
- unsigned char *pointer_pos = (unsigned char *)pointer;
- unsigned char *pool_pos = (unsigned char *)m_pool;
- // calc offset
- if (pointer_pos < pool_pos) return false; //other pool
- size_t offset = size_t(pointer_pos - pool_pos);
- if (offset >= get_pool_capacity()) return false; // far away
-
- // find free position
- m_free_nodes[m_free_nodes_count] = offset / m_element_size;
- m_free_nodes_count++;
- return true;
-}
-
-/// *******************! btGenericPoolAllocator *******************!///
-
-btGenericPoolAllocator::~btGenericPoolAllocator()
-{
- // destroy pools
- size_t i;
- for (i = 0; i < m_pool_count; i++)
- {
- m_pools[i]->end_pool();
- btAlignedFree(m_pools[i]);
- }
-}
-
-// creates a pool
-btGenericMemoryPool *btGenericPoolAllocator::push_new_pool()
-{
- if (m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
-
- btGenericMemoryPool *newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool), 16);
-
- m_pools[m_pool_count] = newptr;
-
- m_pools[m_pool_count]->init_pool(m_pool_element_size, m_pool_element_count);
-
- m_pool_count++;
- return newptr;
-}
-
-void *btGenericPoolAllocator::failback_alloc(size_t size_bytes)
-{
- btGenericMemoryPool *pool = NULL;
-
- if (size_bytes <= get_pool_capacity())
- {
- pool = push_new_pool();
- }
-
- if (pool == NULL) // failback
- {
- return btAlignedAlloc(size_bytes, 16);
- }
-
- return pool->allocate(size_bytes);
-}
-
-bool btGenericPoolAllocator::failback_free(void *pointer)
-{
- btAlignedFree(pointer);
- return true;
-}
-
-//! Allocates memory in pool
-/*!
-\param size_bytes size in bytes of the buffer
-*/
-void *btGenericPoolAllocator::allocate(size_t size_bytes)
-{
- void *ptr = NULL;
-
- size_t i = 0;
- while (i < m_pool_count && ptr == NULL)
- {
- ptr = m_pools[i]->allocate(size_bytes);
- ++i;
- }
-
- if (ptr) return ptr;
-
- return failback_alloc(size_bytes);
-}
-
-bool btGenericPoolAllocator::freeMemory(void *pointer)
-{
- bool result = false;
-
- size_t i = 0;
- while (i < m_pool_count && result == false)
- {
- result = m_pools[i]->freeMemory(pointer);
- ++i;
- }
-
- if (result) return true;
-
- return failback_free(pointer);
-}
-
-/// ************** STANDARD ALLOCATOR ***************************///
-
-#define BT_DEFAULT_POOL_SIZE 32768
-#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
-
-// main allocator
-class GIM_STANDARD_ALLOCATOR : public btGenericPoolAllocator
-{
-public:
- GIM_STANDARD_ALLOCATOR() : btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE, BT_DEFAULT_POOL_SIZE)
- {
- }
-};
-
-// global allocator
-GIM_STANDARD_ALLOCATOR g_main_allocator;
-
-void *btPoolAlloc(size_t size)
-{
- return g_main_allocator.allocate(size);
-}
-
-void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
-{
- void *newptr = btPoolAlloc(newsize);
- size_t copysize = oldsize < newsize ? oldsize : newsize;
- memcpy(newptr, ptr, copysize);
- btPoolFree(ptr);
- return newptr;
-}
-
-void btPoolFree(void *ptr)
-{
- g_main_allocator.freeMemory(ptr);
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h b/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h
deleted file mode 100644
index a535088e48..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGenericPoolAllocator.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*! \file btGenericPoolAllocator.h
-\author Francisco Leon Najera. email projectileman@yahoo.com
-
-General purpose allocator class
-*/
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GENERIC_POOL_ALLOCATOR_H
-#define BT_GENERIC_POOL_ALLOCATOR_H
-
-#include <limits.h>
-#include <stdio.h>
-#include <string.h>
-#include "LinearMath/btAlignedAllocator.h"
-
-#define BT_UINT_MAX UINT_MAX
-#define BT_DEFAULT_MAX_POOLS 16
-
-//! Generic Pool class
-class btGenericMemoryPool
-{
-public:
- unsigned char *m_pool; //[m_element_size*m_max_element_count];
- size_t *m_free_nodes; //[m_max_element_count];//! free nodes
- size_t *m_allocated_sizes; //[m_max_element_count];//! Number of elements allocated per node
- size_t m_allocated_count;
- size_t m_free_nodes_count;
-
-protected:
- size_t m_element_size;
- size_t m_max_element_count;
-
- size_t allocate_from_free_nodes(size_t num_elements);
- size_t allocate_from_pool(size_t num_elements);
-
-public:
- void init_pool(size_t element_size, size_t element_count);
-
- void end_pool();
-
- btGenericMemoryPool(size_t element_size, size_t element_count)
- {
- init_pool(element_size, element_count);
- }
-
- ~btGenericMemoryPool()
- {
- end_pool();
- }
-
- inline size_t get_pool_capacity()
- {
- return m_element_size * m_max_element_count;
- }
-
- inline size_t gem_element_size()
- {
- return m_element_size;
- }
-
- inline size_t get_max_element_count()
- {
- return m_max_element_count;
- }
-
- inline size_t get_allocated_count()
- {
- return m_allocated_count;
- }
-
- inline size_t get_free_positions_count()
- {
- return m_free_nodes_count;
- }
-
- inline void *get_element_data(size_t element_index)
- {
- return &m_pool[element_index * m_element_size];
- }
-
- //! Allocates memory in pool
- /*!
- \param size_bytes size in bytes of the buffer
- */
- void *allocate(size_t size_bytes);
-
- bool freeMemory(void *pointer);
-};
-
-//! Generic Allocator with pools
-/*!
-General purpose Allocator which can create Memory Pools dynamiacally as needed.
-*/
-class btGenericPoolAllocator
-{
-protected:
- size_t m_pool_element_size;
- size_t m_pool_element_count;
-
-public:
- btGenericMemoryPool *m_pools[BT_DEFAULT_MAX_POOLS];
- size_t m_pool_count;
-
- inline size_t get_pool_capacity()
- {
- return m_pool_element_size * m_pool_element_count;
- }
-
-protected:
- // creates a pool
- btGenericMemoryPool *push_new_pool();
-
- void *failback_alloc(size_t size_bytes);
-
- bool failback_free(void *pointer);
-
-public:
- btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
- {
- m_pool_count = 0;
- m_pool_element_size = pool_element_size;
- m_pool_element_count = pool_element_count;
- }
-
- virtual ~btGenericPoolAllocator();
-
- //! Allocates memory in pool
- /*!
- \param size_bytes size in bytes of the buffer
- */
- void *allocate(size_t size_bytes);
-
- bool freeMemory(void *pointer);
-};
-
-void *btPoolAlloc(size_t size);
-void *btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
-void btPoolFree(void *ptr);
-
-#endif
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h b/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h
deleted file mode 100644
index 6a1ee6dcf9..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btGeometryOperations.h
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
-#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
-
-/*! \file btGeometryOperations.h
-*\author Francisco Leon Najera
-
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btBoxCollision.h"
-
-#define PLANEDIREPSILON 0.0000001f
-#define PARALELENORMALS 0.000001f
-
-#define BT_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
-
-/// Calc a plane from a triangle edge an a normal. plane is a vec4f
-SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 &e1, const btVector3 &e2, const btVector3 &normal, btVector4 &plane)
-{
- btVector3 planenormal = (e2 - e1).cross(normal);
- planenormal.normalize();
- plane.setValue(planenormal[0], planenormal[1], planenormal[2], e2.dot(planenormal));
-}
-
-//***************** SEGMENT and LINE FUNCTIONS **********************************///
-
-/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
- */
-SIMD_FORCE_INLINE void bt_closest_point_on_segment(
- btVector3 &cp, const btVector3 &v,
- const btVector3 &e1, const btVector3 &e2)
-{
- btVector3 n = e2 - e1;
- cp = v - e1;
- btScalar _scalar = cp.dot(n) / n.dot(n);
- if (_scalar < 0.0f)
- {
- cp = e1;
- }
- else if (_scalar > 1.0f)
- {
- cp = e2;
- }
- else
- {
- cp = _scalar * n + e1;
- }
-}
-
-//! line plane collision
-/*!
-*\return
- -0 if the ray never intersects
- -1 if the ray collides in front
- -2 if the ray collides in back
-*/
-
-SIMD_FORCE_INLINE int bt_line_plane_collision(
- const btVector4 &plane,
- const btVector3 &vDir,
- const btVector3 &vPoint,
- btVector3 &pout,
- btScalar &tparam,
- btScalar tmin, btScalar tmax)
-{
- btScalar _dotdir = vDir.dot(plane);
-
- if (btFabs(_dotdir) < PLANEDIREPSILON)
- {
- tparam = tmax;
- return 0;
- }
-
- btScalar _dis = bt_distance_point_plane(plane, vPoint);
- char returnvalue = _dis < 0.0f ? 2 : 1;
- tparam = -_dis / _dotdir;
-
- if (tparam < tmin)
- {
- returnvalue = 0;
- tparam = tmin;
- }
- else if (tparam > tmax)
- {
- returnvalue = 0;
- tparam = tmax;
- }
- pout = tparam * vDir + vPoint;
- return returnvalue;
-}
-
-//! Find closest points on segments
-SIMD_FORCE_INLINE void bt_segment_collision(
- const btVector3 &vA1,
- const btVector3 &vA2,
- const btVector3 &vB1,
- const btVector3 &vB2,
- btVector3 &vPointA,
- btVector3 &vPointB)
-{
- btVector3 AD = vA2 - vA1;
- btVector3 BD = vB2 - vB1;
- btVector3 N = AD.cross(BD);
- btScalar tp = N.length2();
-
- btVector4 _M; //plane
-
- if (tp < SIMD_EPSILON) //ARE PARALELE
- {
- //project B over A
- bool invert_b_order = false;
- _M[0] = vB1.dot(AD);
- _M[1] = vB2.dot(AD);
-
- if (_M[0] > _M[1])
- {
- invert_b_order = true;
- BT_SWAP_NUMBERS(_M[0], _M[1]);
- }
- _M[2] = vA1.dot(AD);
- _M[3] = vA2.dot(AD);
- //mid points
- N[0] = (_M[0] + _M[1]) * 0.5f;
- N[1] = (_M[2] + _M[3]) * 0.5f;
-
- if (N[0] < N[1])
- {
- if (_M[1] < _M[2])
- {
- vPointB = invert_b_order ? vB1 : vB2;
- vPointA = vA1;
- }
- else if (_M[1] < _M[3])
- {
- vPointB = invert_b_order ? vB1 : vB2;
- bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
- }
- else
- {
- vPointA = vA2;
- bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
- }
- }
- else
- {
- if (_M[3] < _M[0])
- {
- vPointB = invert_b_order ? vB2 : vB1;
- vPointA = vA2;
- }
- else if (_M[3] < _M[1])
- {
- vPointA = vA2;
- bt_closest_point_on_segment(vPointB, vPointA, vB1, vB2);
- }
- else
- {
- vPointB = invert_b_order ? vB1 : vB2;
- bt_closest_point_on_segment(vPointA, vPointB, vA1, vA2);
- }
- }
- return;
- }
-
- N = N.cross(BD);
- _M.setValue(N[0], N[1], N[2], vB1.dot(N));
-
- // get point A as the plane collision point
- bt_line_plane_collision(_M, AD, vA1, vPointA, tp, btScalar(0), btScalar(1));
-
- /*Closest point on segment*/
- vPointB = vPointA - vB1;
- tp = vPointB.dot(BD);
- tp /= BD.dot(BD);
- tp = BT_CLAMP(tp, 0.0f, 1.0f);
-
- vPointB = tp * BD + vB1;
-}
-
-#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h b/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h
deleted file mode 100644
index 19a02a2177..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btQuantization.h
+++ /dev/null
@@ -1,79 +0,0 @@
-#ifndef BT_GIMPACT_QUANTIZATION_H_INCLUDED
-#define BT_GIMPACT_QUANTIZATION_H_INCLUDED
-
-/*! \file btQuantization.h
-*\author Francisco Leon Najera
-
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btTransform.h"
-
-SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
- btVector3& outMinBound,
- btVector3& outMaxBound,
- btVector3& bvhQuantization,
- const btVector3& srcMinBound, const btVector3& srcMaxBound,
- btScalar quantizationMargin)
-{
- //enlarge the AABB to avoid division by zero when initializing the quantization values
- btVector3 clampValue(quantizationMargin, quantizationMargin, quantizationMargin);
- outMinBound = srcMinBound - clampValue;
- outMaxBound = srcMaxBound + clampValue;
- btVector3 aabbSize = outMaxBound - outMinBound;
- bvhQuantization = btVector3(btScalar(65535.0),
- btScalar(65535.0),
- btScalar(65535.0)) /
- aabbSize;
-}
-
-SIMD_FORCE_INLINE void bt_quantize_clamp(
- unsigned short* out,
- const btVector3& point,
- const btVector3& min_bound,
- const btVector3& max_bound,
- const btVector3& bvhQuantization)
-{
- btVector3 clampedPoint(point);
- clampedPoint.setMax(min_bound);
- clampedPoint.setMin(max_bound);
-
- btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
- out[0] = (unsigned short)(v.getX() + 0.5f);
- out[1] = (unsigned short)(v.getY() + 0.5f);
- out[2] = (unsigned short)(v.getZ() + 0.5f);
-}
-
-SIMD_FORCE_INLINE btVector3 bt_unquantize(
- const unsigned short* vecIn,
- const btVector3& offset,
- const btVector3& bvhQuantization)
-{
- btVector3 vecOut;
- vecOut.setValue(
- (btScalar)(vecIn[0]) / (bvhQuantization.getX()),
- (btScalar)(vecIn[1]) / (bvhQuantization.getY()),
- (btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
- vecOut += offset;
- return vecOut;
-}
-
-#endif // BT_GIMPACT_QUANTIZATION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp
deleted file mode 100644
index 292ef8c1ff..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*! \file btGImpactTriangleShape.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTriangleShapeEx.h"
-
-void GIM_TRIANGLE_CONTACT::merge_points(const btVector4& plane,
- btScalar margin, const btVector3* points, int point_count)
-{
- m_point_count = 0;
- m_penetration_depth = -1000.0f;
-
- int point_indices[MAX_TRI_CLIPPING];
-
- int _k;
-
- for (_k = 0; _k < point_count; _k++)
- {
- btScalar _dist = -bt_distance_point_plane(plane, points[_k]) + margin;
-
- if (_dist >= 0.0f)
- {
- if (_dist > m_penetration_depth)
- {
- m_penetration_depth = _dist;
- point_indices[0] = _k;
- m_point_count = 1;
- }
- else if ((_dist + SIMD_EPSILON) >= m_penetration_depth)
- {
- point_indices[m_point_count] = _k;
- m_point_count++;
- }
- }
- }
-
- for (_k = 0; _k < m_point_count; _k++)
- {
- m_points[_k] = points[point_indices[_k]];
- }
-}
-
-///class btPrimitiveTriangle
-bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
-{
- btScalar total_margin = m_margin + other.m_margin;
- // classify points on other triangle
- btScalar dis0 = bt_distance_point_plane(m_plane, other.m_vertices[0]) - total_margin;
-
- btScalar dis1 = bt_distance_point_plane(m_plane, other.m_vertices[1]) - total_margin;
-
- btScalar dis2 = bt_distance_point_plane(m_plane, other.m_vertices[2]) - total_margin;
-
- if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
-
- // classify points on this triangle
- dis0 = bt_distance_point_plane(other.m_plane, m_vertices[0]) - total_margin;
-
- dis1 = bt_distance_point_plane(other.m_plane, m_vertices[1]) - total_margin;
-
- dis2 = bt_distance_point_plane(other.m_plane, m_vertices[2]) - total_margin;
-
- if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
-
- return true;
-}
-
-int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points)
-{
- // edge 0
-
- btVector3 temp_points[MAX_TRI_CLIPPING];
-
- btVector4 edgeplane;
-
- get_edge_plane(0, edgeplane);
-
- int clipped_count = bt_plane_clip_triangle(
- edgeplane, other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], temp_points);
-
- if (clipped_count == 0) return 0;
-
- btVector3 temp_points1[MAX_TRI_CLIPPING];
-
- // edge 1
- get_edge_plane(1, edgeplane);
-
- clipped_count = bt_plane_clip_polygon(edgeplane, temp_points, clipped_count, temp_points1);
-
- if (clipped_count == 0) return 0;
-
- // edge 2
- get_edge_plane(2, edgeplane);
-
- clipped_count = bt_plane_clip_polygon(
- edgeplane, temp_points1, clipped_count, clipped_points);
-
- return clipped_count;
-}
-
-bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts)
-{
- btScalar margin = m_margin + other.m_margin;
-
- btVector3 clipped_points[MAX_TRI_CLIPPING];
- int clipped_count;
- //create planes
- // plane v vs U points
-
- GIM_TRIANGLE_CONTACT contacts1;
-
- contacts1.m_separating_normal = m_plane;
-
- clipped_count = clip_triangle(other, clipped_points);
-
- if (clipped_count == 0)
- {
- return false; //Reject
- }
-
- //find most deep interval face1
- contacts1.merge_points(contacts1.m_separating_normal, margin, clipped_points, clipped_count);
- if (contacts1.m_point_count == 0) return false; // too far
- //Normal pointing to this triangle
- contacts1.m_separating_normal *= -1.f;
-
- //Clip tri1 by tri2 edges
- GIM_TRIANGLE_CONTACT contacts2;
- contacts2.m_separating_normal = other.m_plane;
-
- clipped_count = other.clip_triangle(*this, clipped_points);
-
- if (clipped_count == 0)
- {
- return false; //Reject
- }
-
- //find most deep interval face1
- contacts2.merge_points(contacts2.m_separating_normal, margin, clipped_points, clipped_count);
- if (contacts2.m_point_count == 0) return false; // too far
-
- ////check most dir for contacts
- if (contacts2.m_penetration_depth < contacts1.m_penetration_depth)
- {
- contacts.copy_from(contacts2);
- }
- else
- {
- contacts.copy_from(contacts1);
- }
- return true;
-}
-
-///class btTriangleShapeEx: public btTriangleShape
-
-bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
-{
- btScalar total_margin = getMargin() + other.getMargin();
-
- btVector4 plane0;
- buildTriPlane(plane0);
- btVector4 plane1;
- other.buildTriPlane(plane1);
-
- // classify points on other triangle
- btScalar dis0 = bt_distance_point_plane(plane0, other.m_vertices1[0]) - total_margin;
-
- btScalar dis1 = bt_distance_point_plane(plane0, other.m_vertices1[1]) - total_margin;
-
- btScalar dis2 = bt_distance_point_plane(plane0, other.m_vertices1[2]) - total_margin;
-
- if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
-
- // classify points on this triangle
- dis0 = bt_distance_point_plane(plane1, m_vertices1[0]) - total_margin;
-
- dis1 = bt_distance_point_plane(plane1, m_vertices1[1]) - total_margin;
-
- dis2 = bt_distance_point_plane(plane1, m_vertices1[2]) - total_margin;
-
- if (dis0 > 0.0f && dis1 > 0.0f && dis2 > 0.0f) return false;
-
- return true;
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h b/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h
deleted file mode 100644
index 568a1ce811..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/btTriangleShapeEx.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*! \file btGImpactShape.h
-\author Francisco Leon Najera
-*/
-/*
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef GIMPACT_TRIANGLE_SHAPE_EX_H
-#define GIMPACT_TRIANGLE_SHAPE_EX_H
-
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "btBoxCollision.h"
-#include "btClipPolygon.h"
-#include "btGeometryOperations.h"
-
-#define MAX_TRI_CLIPPING 16
-
-//! Structure for collision
-struct GIM_TRIANGLE_CONTACT
-{
- btScalar m_penetration_depth;
- int m_point_count;
- btVector4 m_separating_normal;
- btVector3 m_points[MAX_TRI_CLIPPING];
-
- SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
- {
- m_penetration_depth = other.m_penetration_depth;
- m_separating_normal = other.m_separating_normal;
- m_point_count = other.m_point_count;
- int i = m_point_count;
- while (i--)
- {
- m_points[i] = other.m_points[i];
- }
- }
-
- GIM_TRIANGLE_CONTACT()
- {
- }
-
- GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other)
- {
- copy_from(other);
- }
-
- //! classify points that are closer
- void merge_points(const btVector4& plane,
- btScalar margin, const btVector3* points, int point_count);
-};
-
-class btPrimitiveTriangle
-{
-public:
- btVector3 m_vertices[3];
- btVector4 m_plane;
- btScalar m_margin;
- btScalar m_dummy;
- btPrimitiveTriangle() : m_margin(0.01f)
- {
- }
-
- SIMD_FORCE_INLINE void buildTriPlane()
- {
- btVector3 normal = (m_vertices[1] - m_vertices[0]).cross(m_vertices[2] - m_vertices[0]);
- normal.normalize();
- m_plane.setValue(normal[0], normal[1], normal[2], m_vertices[0].dot(normal));
- }
-
- //! Test if triangles could collide
- bool overlap_test_conservative(const btPrimitiveTriangle& other);
-
- //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
- /*!
- \pre this triangle must have its plane calculated.
- */
- SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4& plane) const
- {
- const btVector3& e0 = m_vertices[edge_index];
- const btVector3& e1 = m_vertices[(edge_index + 1) % 3];
- bt_edge_plane(e0, e1, m_plane, plane);
- }
-
- void applyTransform(const btTransform& t)
- {
- m_vertices[0] = t(m_vertices[0]);
- m_vertices[1] = t(m_vertices[1]);
- m_vertices[2] = t(m_vertices[2]);
- }
-
- //! Clips the triangle against this
- /*!
- \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
- \return the number of clipped points
- */
- int clip_triangle(btPrimitiveTriangle& other, btVector3* clipped_points);
-
- //! Find collision using the clipping method
- /*!
- \pre this triangle and other must have their triangles calculated
- */
- bool find_triangle_collision_clip_method(btPrimitiveTriangle& other, GIM_TRIANGLE_CONTACT& contacts);
-};
-
-//! Helper class for colliding Bullet Triangle Shapes
-/*!
-This class implements a better getAabb method than the previous btTriangleShape class
-*/
-class btTriangleShapeEx : public btTriangleShape
-{
-public:
- btTriangleShapeEx() : btTriangleShape(btVector3(0, 0, 0), btVector3(0, 0, 0), btVector3(0, 0, 0))
- {
- }
-
- btTriangleShapeEx(const btVector3& p0, const btVector3& p1, const btVector3& p2) : btTriangleShape(p0, p1, p2)
- {
- }
-
- btTriangleShapeEx(const btTriangleShapeEx& other) : btTriangleShape(other.m_vertices1[0], other.m_vertices1[1], other.m_vertices1[2])
- {
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- btVector3 tv0 = t(m_vertices1[0]);
- btVector3 tv1 = t(m_vertices1[1]);
- btVector3 tv2 = t(m_vertices1[2]);
-
- btAABB trianglebox(tv0, tv1, tv2, m_collisionMargin);
- aabbMin = trianglebox.m_min;
- aabbMax = trianglebox.m_max;
- }
-
- void applyTransform(const btTransform& t)
- {
- m_vertices1[0] = t(m_vertices1[0]);
- m_vertices1[1] = t(m_vertices1[1]);
- m_vertices1[2] = t(m_vertices1[2]);
- }
-
- SIMD_FORCE_INLINE void buildTriPlane(btVector4& plane) const
- {
- btVector3 normal = (m_vertices1[1] - m_vertices1[0]).cross(m_vertices1[2] - m_vertices1[0]);
- normal.normalize();
- plane.setValue(normal[0], normal[1], normal[2], m_vertices1[0].dot(normal));
- }
-
- bool overlap_test_conservative(const btTriangleShapeEx& other);
-};
-
-#endif //GIMPACT_TRIANGLE_MESH_SHAPE_H
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h
deleted file mode 100644
index fc2dc38a33..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_array.h
+++ /dev/null
@@ -1,318 +0,0 @@
-#ifndef GIM_ARRAY_H_INCLUDED
-#define GIM_ARRAY_H_INCLUDED
-/*! \file gim_array.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_memory.h"
-
-#define GIM_ARRAY_GROW_INCREMENT 2
-#define GIM_ARRAY_GROW_FACTOR 2
-
-//! Very simple array container with fast access and simd memory
-template <typename T>
-class gim_array
-{
-public:
- //! properties
- //!@{
- T* m_data;
- GUINT m_size;
- GUINT m_allocated_size;
- //!@}
- //! protected operations
- //!@{
-
- inline void destroyData()
- {
- m_allocated_size = 0;
- if (m_data == NULL) return;
- gim_free(m_data);
- m_data = NULL;
- }
-
- inline bool resizeData(GUINT newsize)
- {
- if (newsize == 0)
- {
- destroyData();
- return true;
- }
-
- if (m_size > 0)
- {
- m_data = (T*)gim_realloc(m_data, m_size * sizeof(T), newsize * sizeof(T));
- }
- else
- {
- m_data = (T*)gim_alloc(newsize * sizeof(T));
- }
- m_allocated_size = newsize;
- return true;
- }
-
- inline bool growingCheck()
- {
- if (m_allocated_size <= m_size)
- {
- GUINT requestsize = m_size;
- m_size = m_allocated_size;
- if (resizeData((requestsize + GIM_ARRAY_GROW_INCREMENT) * GIM_ARRAY_GROW_FACTOR) == false) return false;
- }
- return true;
- }
-
- //!@}
- //! public operations
- //!@{
- inline bool reserve(GUINT size)
- {
- if (m_allocated_size >= size) return false;
- return resizeData(size);
- }
-
- inline void clear_range(GUINT start_range)
- {
- while (m_size > start_range)
- {
- m_data[--m_size].~T();
- }
- }
-
- inline void clear()
- {
- if (m_size == 0) return;
- clear_range(0);
- }
-
- inline void clear_memory()
- {
- clear();
- destroyData();
- }
-
- gim_array()
- {
- m_data = 0;
- m_size = 0;
- m_allocated_size = 0;
- }
-
- gim_array(GUINT reservesize)
- {
- m_data = 0;
- m_size = 0;
-
- m_allocated_size = 0;
- reserve(reservesize);
- }
-
- ~gim_array()
- {
- clear_memory();
- }
-
- inline GUINT size() const
- {
- return m_size;
- }
-
- inline GUINT max_size() const
- {
- return m_allocated_size;
- }
-
- inline T& operator[](size_t i)
- {
- return m_data[i];
- }
- inline const T& operator[](size_t i) const
- {
- return m_data[i];
- }
-
- inline T* pointer() { return m_data; }
- inline const T* pointer() const
- {
- return m_data;
- }
-
- inline T* get_pointer_at(GUINT i)
- {
- return m_data + i;
- }
-
- inline const T* get_pointer_at(GUINT i) const
- {
- return m_data + i;
- }
-
- inline T& at(GUINT i)
- {
- return m_data[i];
- }
-
- inline const T& at(GUINT i) const
- {
- return m_data[i];
- }
-
- inline T& front()
- {
- return *m_data;
- }
-
- inline const T& front() const
- {
- return *m_data;
- }
-
- inline T& back()
- {
- return m_data[m_size - 1];
- }
-
- inline const T& back() const
- {
- return m_data[m_size - 1];
- }
-
- inline void swap(GUINT i, GUINT j)
- {
- gim_swap_elements(m_data, i, j);
- }
-
- inline void push_back(const T& obj)
- {
- this->growingCheck();
- m_data[m_size] = obj;
- m_size++;
- }
-
- //!Simply increase the m_size, doesn't call the new element constructor
- inline void push_back_mem()
- {
- this->growingCheck();
- m_size++;
- }
-
- inline void push_back_memcpy(const T& obj)
- {
- this->growingCheck();
- gim_simd_memcpy(&m_data[m_size], &obj, sizeof(T));
- m_size++;
- }
-
- inline void pop_back()
- {
- m_size--;
- m_data[m_size].~T();
- }
-
- //!Simply decrease the m_size, doesn't call the deleted element destructor
- inline void pop_back_mem()
- {
- m_size--;
- }
-
- //! fast erase
- inline void erase(GUINT index)
- {
- if (index < m_size - 1)
- {
- swap(index, m_size - 1);
- }
- pop_back();
- }
-
- inline void erase_sorted_mem(GUINT index)
- {
- m_size--;
- for (GUINT i = index; i < m_size; i++)
- {
- gim_simd_memcpy(m_data + i, m_data + i + 1, sizeof(T));
- }
- }
-
- inline void erase_sorted(GUINT index)
- {
- m_data[index].~T();
- erase_sorted_mem(index);
- }
-
- inline void insert_mem(GUINT index)
- {
- this->growingCheck();
- for (GUINT i = m_size; i > index; i--)
- {
- gim_simd_memcpy(m_data + i, m_data + i - 1, sizeof(T));
- }
- m_size++;
- }
-
- inline void insert(const T& obj, GUINT index)
- {
- insert_mem(index);
- m_data[index] = obj;
- }
-
- inline void resize(GUINT size, bool call_constructor = true, const T& fillData = T())
- {
- if (size > m_size)
- {
- reserve(size);
- if (call_constructor)
- {
- while (m_size < size)
- {
- m_data[m_size] = fillData;
- m_size++;
- }
- }
- else
- {
- m_size = size;
- }
- }
- else if (size < m_size)
- {
- if (call_constructor) clear_range(size);
- m_size = size;
- }
- }
-
- inline void refit()
- {
- resizeData(m_size);
- }
-};
-
-#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h
deleted file mode 100644
index 7ab783672d..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_basic_geometry_operations.h
+++ /dev/null
@@ -1,536 +0,0 @@
-#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
-#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
-
-/*! \file gim_basic_geometry_operations.h
-*\author Francisco Leon Najera
-type independant geometry routines
-
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_linear_math.h"
-
-#ifndef PLANEDIREPSILON
-#define PLANEDIREPSILON 0.0000001f
-#endif
-
-#ifndef PARALELENORMALS
-#define PARALELENORMALS 0.000001f
-#endif
-
-#define TRIANGLE_NORMAL(v1, v2, v3, n) \
- { \
- vec3f _dif1, _dif2; \
- VEC_DIFF(_dif1, v2, v1); \
- VEC_DIFF(_dif2, v3, v1); \
- VEC_CROSS(n, _dif1, _dif2); \
- VEC_NORMALIZE(n); \
- }
-
-#define TRIANGLE_NORMAL_FAST(v1, v2, v3, n) \
- { \
- vec3f _dif1, _dif2; \
- VEC_DIFF(_dif1, v2, v1); \
- VEC_DIFF(_dif2, v3, v1); \
- VEC_CROSS(n, _dif1, _dif2); \
- }
-
-/// plane is a vec4f
-#define TRIANGLE_PLANE(v1, v2, v3, plane) \
- { \
- TRIANGLE_NORMAL(v1, v2, v3, plane); \
- plane[3] = VEC_DOT(v1, plane); \
- }
-
-/// plane is a vec4f
-#define TRIANGLE_PLANE_FAST(v1, v2, v3, plane) \
- { \
- TRIANGLE_NORMAL_FAST(v1, v2, v3, plane); \
- plane[3] = VEC_DOT(v1, plane); \
- }
-
-/// Calc a plane from an edge an a normal. plane is a vec4f
-#define EDGE_PLANE(e1, e2, n, plane) \
- { \
- vec3f _dif; \
- VEC_DIFF(_dif, e2, e1); \
- VEC_CROSS(plane, _dif, n); \
- VEC_NORMALIZE(plane); \
- plane[3] = VEC_DOT(e1, plane); \
- }
-
-#define DISTANCE_PLANE_POINT(plane, point) (VEC_DOT(plane, point) - plane[3])
-
-#define PROJECT_POINT_PLANE(point, plane, projected) \
- { \
- GREAL _dis; \
- _dis = DISTANCE_PLANE_POINT(plane, point); \
- VEC_SCALE(projected, -_dis, plane); \
- VEC_SUM(projected, projected, point); \
- }
-
-//! Verifies if a point is in the plane hull
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE bool POINT_IN_HULL(
- const CLASS_POINT &point, const CLASS_PLANE *planes, GUINT plane_count)
-{
- GREAL _dis;
- for (GUINT _i = 0; _i < plane_count; ++_i)
- {
- _dis = DISTANCE_PLANE_POINT(planes[_i], point);
- if (_dis > 0.0f) return false;
- }
- return true;
-}
-
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
- const CLASS_POINT &s1,
- const CLASS_POINT &s2, const CLASS_PLANE &plane, CLASS_POINT &clipped)
-{
- GREAL _dis1, _dis2;
- _dis1 = DISTANCE_PLANE_POINT(plane, s1);
- VEC_DIFF(clipped, s2, s1);
- _dis2 = VEC_DOT(clipped, plane);
- VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
- VEC_SUM(clipped, clipped, s1);
-}
-
-enum ePLANE_INTERSECTION_TYPE
-{
- G_BACK_PLANE = 0,
- G_COLLIDE_PLANE,
- G_FRONT_PLANE
-};
-
-enum eLINE_PLANE_INTERSECTION_TYPE
-{
- G_FRONT_PLANE_S1 = 0,
- G_FRONT_PLANE_S2,
- G_BACK_PLANE_S1,
- G_BACK_PLANE_S2,
- G_COLLIDE_PLANE_S1,
- G_COLLIDE_PLANE_S2
-};
-
-//! Confirms if the plane intersect the edge or nor
-/*!
-intersection type must have the following values
-<ul>
-<li> 0 : Segment in front of plane, s1 closest
-<li> 1 : Segment in front of plane, s2 closest
-<li> 2 : Segment in back of plane, s1 closest
-<li> 3 : Segment in back of plane, s2 closest
-<li> 4 : Segment collides plane, s1 in back
-<li> 5 : Segment collides plane, s2 in back
-</ul>
-*/
-
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
- const CLASS_POINT &s1,
- const CLASS_POINT &s2,
- const CLASS_PLANE &plane, CLASS_POINT &clipped)
-{
- GREAL _dis1 = DISTANCE_PLANE_POINT(plane, s1);
- GREAL _dis2 = DISTANCE_PLANE_POINT(plane, s2);
- if (_dis1 > -G_EPSILON && _dis2 > -G_EPSILON)
- {
- if (_dis1 < _dis2) return G_FRONT_PLANE_S1;
- return G_FRONT_PLANE_S2;
- }
- else if (_dis1 < G_EPSILON && _dis2 < G_EPSILON)
- {
- if (_dis1 > _dis2) return G_BACK_PLANE_S1;
- return G_BACK_PLANE_S2;
- }
-
- VEC_DIFF(clipped, s2, s1);
- _dis2 = VEC_DOT(clipped, plane);
- VEC_SCALE(clipped, -_dis1 / _dis2, clipped);
- VEC_SUM(clipped, clipped, s1);
- if (_dis1 < _dis2) return G_COLLIDE_PLANE_S1;
- return G_COLLIDE_PLANE_S2;
-}
-
-//! Confirms if the plane intersect the edge or not
-/*!
-clipped1 and clipped2 are the vertices behind the plane.
-clipped1 is the closest
-
-intersection_type must have the following values
-<ul>
-<li> 0 : Segment in front of plane, s1 closest
-<li> 1 : Segment in front of plane, s2 closest
-<li> 2 : Segment in back of plane, s1 closest
-<li> 3 : Segment in back of plane, s2 closest
-<li> 4 : Segment collides plane, s1 in back
-<li> 5 : Segment collides plane, s2 in back
-</ul>
-*/
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
- const CLASS_POINT &s1,
- const CLASS_POINT &s2,
- const CLASS_PLANE &plane,
- CLASS_POINT &clipped1, CLASS_POINT &clipped2)
-{
- eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1, s2, plane, clipped1);
- switch (intersection_type)
- {
- case G_FRONT_PLANE_S1:
- VEC_COPY(clipped1, s1);
- VEC_COPY(clipped2, s2);
- break;
- case G_FRONT_PLANE_S2:
- VEC_COPY(clipped1, s2);
- VEC_COPY(clipped2, s1);
- break;
- case G_BACK_PLANE_S1:
- VEC_COPY(clipped1, s1);
- VEC_COPY(clipped2, s2);
- break;
- case G_BACK_PLANE_S2:
- VEC_COPY(clipped1, s2);
- VEC_COPY(clipped2, s1);
- break;
- case G_COLLIDE_PLANE_S1:
- VEC_COPY(clipped2, s1);
- break;
- case G_COLLIDE_PLANE_S2:
- VEC_COPY(clipped2, s2);
- break;
- }
- return intersection_type;
-}
-
-//! Finds the 2 smallest cartesian coordinates of a plane normal
-#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
-
-//! Ray plane collision in one way
-/*!
-Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
-It uses the PLANEDIREPSILON constant.
-*/
-template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
- const CLASS_PLANE &plane,
- const CLASS_POINT &vDir,
- const CLASS_POINT &vPoint,
- CLASS_POINT &pout, T &tparam)
-{
- GREAL _dis, _dotdir;
- _dotdir = VEC_DOT(plane, vDir);
- if (_dotdir < PLANEDIREPSILON)
- {
- return false;
- }
- _dis = DISTANCE_PLANE_POINT(plane, vPoint);
- tparam = -_dis / _dotdir;
- VEC_SCALE(pout, tparam, vDir);
- VEC_SUM(pout, vPoint, pout);
- return true;
-}
-
-//! line collision
-/*!
-*\return
- -0 if the ray never intersects
- -1 if the ray collides in front
- -2 if the ray collides in back
-*/
-template <typename T, typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
- const CLASS_PLANE &plane,
- const CLASS_POINT &vDir,
- const CLASS_POINT &vPoint,
- CLASS_POINT &pout,
- T &tparam,
- T tmin, T tmax)
-{
- GREAL _dis, _dotdir;
- _dotdir = VEC_DOT(plane, vDir);
- if (btFabs(_dotdir) < PLANEDIREPSILON)
- {
- tparam = tmax;
- return 0;
- }
- _dis = DISTANCE_PLANE_POINT(plane, vPoint);
- char returnvalue = _dis < 0.0f ? 2 : 1;
- tparam = -_dis / _dotdir;
-
- if (tparam < tmin)
- {
- returnvalue = 0;
- tparam = tmin;
- }
- else if (tparam > tmax)
- {
- returnvalue = 0;
- tparam = tmax;
- }
-
- VEC_SCALE(pout, tparam, vDir);
- VEC_SUM(pout, vPoint, pout);
- return returnvalue;
-}
-
-/*! \brief Returns the Ray on which 2 planes intersect if they do.
- Written by Rodrigo Hernandez on ODE convex collision
-
- \param p1 Plane 1
- \param p2 Plane 2
- \param p Contains the origin of the ray upon returning if planes intersect
- \param d Contains the direction of the ray upon returning if planes intersect
- \return true if the planes intersect, 0 if paralell.
-
-*/
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE bool INTERSECT_PLANES(
- const CLASS_PLANE &p1,
- const CLASS_PLANE &p2,
- CLASS_POINT &p,
- CLASS_POINT &d)
-{
- VEC_CROSS(d, p1, p2);
- GREAL denom = VEC_DOT(d, d);
- if (GIM_IS_ZERO(denom)) return false;
- vec3f _n;
- _n[0] = p1[3] * p2[0] - p2[3] * p1[0];
- _n[1] = p1[3] * p2[1] - p2[3] * p1[1];
- _n[2] = p1[3] * p2[2] - p2[3] * p1[2];
- VEC_CROSS(p, _n, d);
- p[0] /= denom;
- p[1] /= denom;
- p[2] /= denom;
- return true;
-}
-
-//***************** SEGMENT and LINE FUNCTIONS **********************************///
-
-/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
- */
-template <typename CLASS_POINT>
-SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
- CLASS_POINT &cp, const CLASS_POINT &v,
- const CLASS_POINT &e1, const CLASS_POINT &e2)
-{
- vec3f _n;
- VEC_DIFF(_n, e2, e1);
- VEC_DIFF(cp, v, e1);
- GREAL _scalar = VEC_DOT(cp, _n);
- _scalar /= VEC_DOT(_n, _n);
- if (_scalar < 0.0f)
- {
- VEC_COPY(cp, e1);
- }
- else if (_scalar > 1.0f)
- {
- VEC_COPY(cp, e2);
- }
- else
- {
- VEC_SCALE(cp, _scalar, _n);
- VEC_SUM(cp, cp, e1);
- }
-}
-
-/*! \brief Finds the line params where these lines intersect.
-
-\param dir1 Direction of line 1
-\param point1 Point of line 1
-\param dir2 Direction of line 2
-\param point2 Point of line 2
-\param t1 Result Parameter for line 1
-\param t2 Result Parameter for line 2
-\param dointersect 0 if the lines won't intersect, else 1
-
-*/
-template <typename T, typename CLASS_POINT>
-SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
- const CLASS_POINT &dir1,
- CLASS_POINT &point1,
- const CLASS_POINT &dir2,
- CLASS_POINT &point2,
- T &t1, T &t2)
-{
- GREAL det;
- GREAL e1e1 = VEC_DOT(dir1, dir1);
- GREAL e1e2 = VEC_DOT(dir1, dir2);
- GREAL e2e2 = VEC_DOT(dir2, dir2);
- vec3f p1p2;
- VEC_DIFF(p1p2, point1, point2);
- GREAL p1p2e1 = VEC_DOT(p1p2, dir1);
- GREAL p1p2e2 = VEC_DOT(p1p2, dir2);
- det = e1e2 * e1e2 - e1e1 * e2e2;
- if (GIM_IS_ZERO(det)) return false;
- t1 = (e1e2 * p1p2e2 - e2e2 * p1p2e1) / det;
- t2 = (e1e1 * p1p2e2 - e1e2 * p1p2e1) / det;
- return true;
-}
-
-//! Find closest points on segments
-template <typename CLASS_POINT>
-SIMD_FORCE_INLINE void SEGMENT_COLLISION(
- const CLASS_POINT &vA1,
- const CLASS_POINT &vA2,
- const CLASS_POINT &vB1,
- const CLASS_POINT &vB2,
- CLASS_POINT &vPointA,
- CLASS_POINT &vPointB)
-{
- CLASS_POINT _AD, _BD, n;
- vec4f _M; //plane
- VEC_DIFF(_AD, vA2, vA1);
- VEC_DIFF(_BD, vB2, vB1);
- VEC_CROSS(n, _AD, _BD);
- GREAL _tp = VEC_DOT(n, n);
- if (_tp < G_EPSILON) //ARE PARALELE
- {
- //project B over A
- bool invert_b_order = false;
- _M[0] = VEC_DOT(vB1, _AD);
- _M[1] = VEC_DOT(vB2, _AD);
- if (_M[0] > _M[1])
- {
- invert_b_order = true;
- GIM_SWAP_NUMBERS(_M[0], _M[1]);
- }
- _M[2] = VEC_DOT(vA1, _AD);
- _M[3] = VEC_DOT(vA2, _AD);
- //mid points
- n[0] = (_M[0] + _M[1]) * 0.5f;
- n[1] = (_M[2] + _M[3]) * 0.5f;
-
- if (n[0] < n[1])
- {
- if (_M[1] < _M[2])
- {
- vPointB = invert_b_order ? vB1 : vB2;
- vPointA = vA1;
- }
- else if (_M[1] < _M[3])
- {
- vPointB = invert_b_order ? vB1 : vB2;
- CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
- }
- else
- {
- vPointA = vA2;
- CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
- }
- }
- else
- {
- if (_M[3] < _M[0])
- {
- vPointB = invert_b_order ? vB2 : vB1;
- vPointA = vA2;
- }
- else if (_M[3] < _M[1])
- {
- vPointA = vA2;
- CLOSEST_POINT_ON_SEGMENT(vPointB, vPointA, vB1, vB2);
- }
- else
- {
- vPointB = invert_b_order ? vB1 : vB2;
- CLOSEST_POINT_ON_SEGMENT(vPointA, vPointB, vA1, vA2);
- }
- }
- return;
- }
-
- VEC_CROSS(_M, n, _BD);
- _M[3] = VEC_DOT(_M, vB1);
-
- LINE_PLANE_COLLISION(_M, _AD, vA1, vPointA, _tp, btScalar(0), btScalar(1));
- /*Closest point on segment*/
- VEC_DIFF(vPointB, vPointA, vB1);
- _tp = VEC_DOT(vPointB, _BD);
- _tp /= VEC_DOT(_BD, _BD);
- _tp = GIM_CLAMP(_tp, 0.0f, 1.0f);
- VEC_SCALE(vPointB, _tp, _BD);
- VEC_SUM(vPointB, vPointB, vB1);
-}
-
-//! Line box intersection in one dimension
-/*!
-
-*\param pos Position of the ray
-*\param dir Projection of the Direction of the ray
-*\param bmin Minimum bound of the box
-*\param bmax Maximum bound of the box
-*\param tfirst the minimum projection. Assign to 0 at first.
-*\param tlast the maximum projection. Assign to INFINITY at first.
-*\return true if there is an intersection.
-*/
-template <typename T>
-SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir, T bmin, T bmax, T &tfirst, T &tlast)
-{
- if (GIM_IS_ZERO(dir))
- {
- return !(pos < bmin || pos > bmax);
- }
- GREAL a0 = (bmin - pos) / dir;
- GREAL a1 = (bmax - pos) / dir;
- if (a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
- tfirst = GIM_MAX(a0, tfirst);
- tlast = GIM_MIN(a1, tlast);
- if (tlast < tfirst) return false;
- return true;
-}
-
-//! Sorts 3 componets
-template <typename T>
-SIMD_FORCE_INLINE void SORT_3_INDICES(
- const T *values,
- GUINT *order_indices)
-{
- //get minimum
- order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
-
- //get second and third
- GUINT i0 = (order_indices[0] + 1) % 3;
- GUINT i1 = (i0 + 1) % 3;
-
- if (values[i0] < values[i1])
- {
- order_indices[1] = i0;
- order_indices[2] = i1;
- }
- else
- {
- order_indices[1] = i1;
- order_indices[2] = i0;
- }
-}
-
-#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h
deleted file mode 100644
index c1fb41a5c0..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_bitset.h
+++ /dev/null
@@ -1,117 +0,0 @@
-#ifndef GIM_BITSET_H_INCLUDED
-#define GIM_BITSET_H_INCLUDED
-/*! \file gim_bitset.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_array.h"
-
-#define GUINT_BIT_COUNT 32
-#define GUINT_EXPONENT 5
-
-class gim_bitset
-{
-public:
- gim_array<GUINT> m_container;
-
- gim_bitset()
- {
- }
-
- gim_bitset(GUINT bits_count)
- {
- resize(bits_count);
- }
-
- ~gim_bitset()
- {
- }
-
- inline bool resize(GUINT newsize)
- {
- GUINT oldsize = m_container.size();
- m_container.resize(newsize / GUINT_BIT_COUNT + 1, false);
- while (oldsize < m_container.size())
- {
- m_container[oldsize] = 0;
- }
- return true;
- }
-
- inline GUINT size()
- {
- return m_container.size() * GUINT_BIT_COUNT;
- }
-
- inline void set_all()
- {
- for (GUINT i = 0; i < m_container.size(); ++i)
- {
- m_container[i] = 0xffffffff;
- }
- }
-
- inline void clear_all()
- {
- for (GUINT i = 0; i < m_container.size(); ++i)
- {
- m_container[i] = 0;
- }
- }
-
- inline void set(GUINT bit_index)
- {
- if (bit_index >= size())
- {
- resize(bit_index);
- }
- m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
- }
-
- ///Return 0 or 1
- inline char get(GUINT bit_index)
- {
- if (bit_index >= size())
- {
- return 0;
- }
- char value = m_container[bit_index >> GUINT_EXPONENT] &
- (1 << (bit_index & (GUINT_BIT_COUNT - 1)));
- return value;
- }
-
- inline void clear(GUINT bit_index)
- {
- m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT - 1)));
- }
-};
-
-#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h
deleted file mode 100644
index 9f7cbe732f..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_collision.h
+++ /dev/null
@@ -1,578 +0,0 @@
-#ifndef GIM_BOX_COLLISION_H_INCLUDED
-#define GIM_BOX_COLLISION_H_INCLUDED
-
-/*! \file gim_box_collision.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-#include "gim_basic_geometry_operations.h"
-#include "LinearMath/btTransform.h"
-
-//SIMD_FORCE_INLINE bool test_cross_edge_box(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, const btVector3 & extend,
-// int dir_index0,
-// int dir_index1
-// int component_index0,
-// int component_index1)
-//{
-// // dir coords are -z and y
-//
-// const btScalar dir0 = -edge[dir_index0];
-// const btScalar dir1 = edge[dir_index1];
-// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
-// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
-// //find minmax
-// if(pmin>pmax)
-// {
-// GIM_SWAP_NUMBERS(pmin,pmax);
-// }
-// //find extends
-// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
-// extend[component_index1] * absolute_edge[dir_index1];
-//
-// if(pmin>rad || -rad>pmax) return false;
-// return true;
-//}
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
-//}
-//
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
-//}
-//
-//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
-// const btVector3 & edge,
-// const btVector3 & absolute_edge,
-// const btVector3 & pointa,
-// const btVector3 & pointb, btVector3 & extend)
-//{
-//
-// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
-//}
-
-#ifndef TEST_CROSS_EDGE_BOX_MCR
-
-#define TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, i_dir_0, i_dir_1, i_comp_0, i_comp_1) \
- { \
- const btScalar dir0 = -edge[i_dir_0]; \
- const btScalar dir1 = edge[i_dir_1]; \
- btScalar pmin = pointa[i_comp_0] * dir0 + pointa[i_comp_1] * dir1; \
- btScalar pmax = pointb[i_comp_0] * dir0 + pointb[i_comp_1] * dir1; \
- if (pmin > pmax) \
- { \
- GIM_SWAP_NUMBERS(pmin, pmax); \
- } \
- const btScalar abs_dir0 = absolute_edge[i_dir_0]; \
- const btScalar abs_dir1 = absolute_edge[i_dir_1]; \
- const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1; \
- if (pmin > rad || -rad > pmax) return false; \
- }
-
-#endif
-
-#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 2, 1, 1, 2); \
- }
-
-#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 0, 2, 2, 0); \
- }
-
-#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge, absolute_edge, pointa, pointb, _extend) \
- { \
- TEST_CROSS_EDGE_BOX_MCR(edge, absolute_edge, pointa, pointb, _extend, 1, 0, 0, 1); \
- }
-
-//! Class for transforming a model1 to the space of model0
-class GIM_BOX_BOX_TRANSFORM_CACHE
-{
-public:
- btVector3 m_T1to0; //!< Transforms translation of model1 to model 0
- btMatrix3x3 m_R1to0; //!< Transforms Rotation of model1 to model 0, equal to R0' * R1
- btMatrix3x3 m_AR; //!< Absolute value of m_R1to0
-
- SIMD_FORCE_INLINE void calc_absolute_matrix()
- {
- static const btVector3 vepsi(1e-6f, 1e-6f, 1e-6f);
- m_AR[0] = vepsi + m_R1to0[0].absolute();
- m_AR[1] = vepsi + m_R1to0[1].absolute();
- m_AR[2] = vepsi + m_R1to0[2].absolute();
- }
-
- GIM_BOX_BOX_TRANSFORM_CACHE()
- {
- }
-
- GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
- {
- COPY_MATRIX_3X3(m_R1to0, trans1_to_0)
- MAT_GET_TRANSLATION(trans1_to_0, m_T1to0)
- calc_absolute_matrix();
- }
-
- //! Calc the transformation relative 1 to 0. Inverts matrics by transposing
- SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform &trans0, const btTransform &trans1)
- {
- m_R1to0 = trans0.getBasis().transpose();
- m_T1to0 = m_R1to0 * (-trans0.getOrigin());
-
- m_T1to0 += m_R1to0 * trans1.getOrigin();
- m_R1to0 *= trans1.getBasis();
-
- calc_absolute_matrix();
- }
-
- //! Calcs the full invertion of the matrices. Useful for scaling matrices
- SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform &trans0, const btTransform &trans1)
- {
- m_R1to0 = trans0.getBasis().inverse();
- m_T1to0 = m_R1to0 * (-trans0.getOrigin());
-
- m_T1to0 += m_R1to0 * trans1.getOrigin();
- m_R1to0 *= trans1.getBasis();
-
- calc_absolute_matrix();
- }
-
- SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point)
- {
- return point.dot3(m_R1to0[0], m_R1to0[1], m_R1to0[2]) + m_T1to0;
- }
-};
-
-#ifndef BOX_PLANE_EPSILON
-#define BOX_PLANE_EPSILON 0.000001f
-#endif
-
-//! Axis aligned box
-class GIM_AABB
-{
-public:
- btVector3 m_min;
- btVector3 m_max;
-
- GIM_AABB()
- {
- }
-
- GIM_AABB(const btVector3 &V1,
- const btVector3 &V2,
- const btVector3 &V3)
- {
- m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
- }
-
- GIM_AABB(const btVector3 &V1,
- const btVector3 &V2,
- const btVector3 &V3,
- GREAL margin)
- {
- m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
-
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- GIM_AABB(const GIM_AABB &other) : m_min(other.m_min), m_max(other.m_max)
- {
- }
-
- GIM_AABB(const GIM_AABB &other, btScalar margin) : m_min(other.m_min), m_max(other.m_max)
- {
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- SIMD_FORCE_INLINE void invalidate()
- {
- m_min[0] = G_REAL_INFINITY;
- m_min[1] = G_REAL_INFINITY;
- m_min[2] = G_REAL_INFINITY;
- m_max[0] = -G_REAL_INFINITY;
- m_max[1] = -G_REAL_INFINITY;
- m_max[2] = -G_REAL_INFINITY;
- }
-
- SIMD_FORCE_INLINE void increment_margin(btScalar margin)
- {
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
- {
- m_min[0] = other.m_min[0] - margin;
- m_min[1] = other.m_min[1] - margin;
- m_min[2] = other.m_min[2] - margin;
-
- m_max[0] = other.m_max[0] + margin;
- m_max[1] = other.m_max[1] + margin;
- m_max[2] = other.m_max[2] + margin;
- }
-
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void calc_from_triangle(
- const CLASS_POINT &V1,
- const CLASS_POINT &V2,
- const CLASS_POINT &V3)
- {
- m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
- }
-
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void calc_from_triangle_margin(
- const CLASS_POINT &V1,
- const CLASS_POINT &V2,
- const CLASS_POINT &V3, btScalar margin)
- {
- m_min[0] = GIM_MIN3(V1[0], V2[0], V3[0]);
- m_min[1] = GIM_MIN3(V1[1], V2[1], V3[1]);
- m_min[2] = GIM_MIN3(V1[2], V2[2], V3[2]);
-
- m_max[0] = GIM_MAX3(V1[0], V2[0], V3[0]);
- m_max[1] = GIM_MAX3(V1[1], V2[1], V3[1]);
- m_max[2] = GIM_MAX3(V1[2], V2[2], V3[2]);
-
- m_min[0] -= margin;
- m_min[1] -= margin;
- m_min[2] -= margin;
- m_max[0] += margin;
- m_max[1] += margin;
- m_max[2] += margin;
- }
-
- //! Apply a transform to an AABB
- SIMD_FORCE_INLINE void appy_transform(const btTransform &trans)
- {
- btVector3 center = (m_max + m_min) * 0.5f;
- btVector3 extends = m_max - center;
- // Compute new center
- center = trans(center);
-
- btVector3 textends = extends.dot3(trans.getBasis().getRow(0).absolute(),
- trans.getBasis().getRow(1).absolute(),
- trans.getBasis().getRow(2).absolute());
-
- m_min = center - textends;
- m_max = center + textends;
- }
-
- //! Merges a Box
- SIMD_FORCE_INLINE void merge(const GIM_AABB &box)
- {
- m_min[0] = GIM_MIN(m_min[0], box.m_min[0]);
- m_min[1] = GIM_MIN(m_min[1], box.m_min[1]);
- m_min[2] = GIM_MIN(m_min[2], box.m_min[2]);
-
- m_max[0] = GIM_MAX(m_max[0], box.m_max[0]);
- m_max[1] = GIM_MAX(m_max[1], box.m_max[1]);
- m_max[2] = GIM_MAX(m_max[2], box.m_max[2]);
- }
-
- //! Merges a point
- template <typename CLASS_POINT>
- SIMD_FORCE_INLINE void merge_point(const CLASS_POINT &point)
- {
- m_min[0] = GIM_MIN(m_min[0], point[0]);
- m_min[1] = GIM_MIN(m_min[1], point[1]);
- m_min[2] = GIM_MIN(m_min[2], point[2]);
-
- m_max[0] = GIM_MAX(m_max[0], point[0]);
- m_max[1] = GIM_MAX(m_max[1], point[1]);
- m_max[2] = GIM_MAX(m_max[2], point[2]);
- }
-
- //! Gets the extend and center
- SIMD_FORCE_INLINE void get_center_extend(btVector3 &center, btVector3 &extend) const
- {
- center = (m_max + m_min) * 0.5f;
- extend = m_max - center;
- }
-
- //! Finds the intersecting box between this box and the other.
- SIMD_FORCE_INLINE void find_intersection(const GIM_AABB &other, GIM_AABB &intersection) const
- {
- intersection.m_min[0] = GIM_MAX(other.m_min[0], m_min[0]);
- intersection.m_min[1] = GIM_MAX(other.m_min[1], m_min[1]);
- intersection.m_min[2] = GIM_MAX(other.m_min[2], m_min[2]);
-
- intersection.m_max[0] = GIM_MIN(other.m_max[0], m_max[0]);
- intersection.m_max[1] = GIM_MIN(other.m_max[1], m_max[1]);
- intersection.m_max[2] = GIM_MIN(other.m_max[2], m_max[2]);
- }
-
- SIMD_FORCE_INLINE bool has_collision(const GIM_AABB &other) const
- {
- if (m_min[0] > other.m_max[0] ||
- m_max[0] < other.m_min[0] ||
- m_min[1] > other.m_max[1] ||
- m_max[1] < other.m_min[1] ||
- m_min[2] > other.m_max[2] ||
- m_max[2] < other.m_min[2])
- {
- return false;
- }
- return true;
- }
-
- /*! \brief Finds the Ray intersection parameter.
- \param aabb Aligned box
- \param vorigin A vec3f with the origin of the ray
- \param vdir A vec3f with the direction of the ray
- */
- SIMD_FORCE_INLINE bool collide_ray(const btVector3 &vorigin, const btVector3 &vdir)
- {
- btVector3 extents, center;
- this->get_center_extend(center, extents);
- ;
-
- btScalar Dx = vorigin[0] - center[0];
- if (GIM_GREATER(Dx, extents[0]) && Dx * vdir[0] >= 0.0f) return false;
- btScalar Dy = vorigin[1] - center[1];
- if (GIM_GREATER(Dy, extents[1]) && Dy * vdir[1] >= 0.0f) return false;
- btScalar Dz = vorigin[2] - center[2];
- if (GIM_GREATER(Dz, extents[2]) && Dz * vdir[2] >= 0.0f) return false;
-
- btScalar f = vdir[1] * Dz - vdir[2] * Dy;
- if (btFabs(f) > extents[1] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[1])) return false;
- f = vdir[2] * Dx - vdir[0] * Dz;
- if (btFabs(f) > extents[0] * btFabs(vdir[2]) + extents[2] * btFabs(vdir[0])) return false;
- f = vdir[0] * Dy - vdir[1] * Dx;
- if (btFabs(f) > extents[0] * btFabs(vdir[1]) + extents[1] * btFabs(vdir[0])) return false;
- return true;
- }
-
- SIMD_FORCE_INLINE void projection_interval(const btVector3 &direction, btScalar &vmin, btScalar &vmax) const
- {
- btVector3 center = (m_max + m_min) * 0.5f;
- btVector3 extend = m_max - center;
-
- btScalar _fOrigin = direction.dot(center);
- btScalar _fMaximumExtent = extend.dot(direction.absolute());
- vmin = _fOrigin - _fMaximumExtent;
- vmax = _fOrigin + _fMaximumExtent;
- }
-
- SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
- {
- btScalar _fmin, _fmax;
- this->projection_interval(plane, _fmin, _fmax);
-
- if (plane[3] > _fmax + BOX_PLANE_EPSILON)
- {
- return G_BACK_PLANE; // 0
- }
-
- if (plane[3] + BOX_PLANE_EPSILON >= _fmin)
- {
- return G_COLLIDE_PLANE; //1
- }
- return G_FRONT_PLANE; //2
- }
-
- SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB &box, btTransform &trans1_to_0)
- {
- GIM_AABB tbox = box;
- tbox.appy_transform(trans1_to_0);
- return has_collision(tbox);
- }
-
- //! transcache is the transformation cache from box to this AABB
- SIMD_FORCE_INLINE bool overlapping_trans_cache(
- const GIM_AABB &box, const GIM_BOX_BOX_TRANSFORM_CACHE &transcache, bool fulltest)
- {
- //Taken from OPCODE
- btVector3 ea, eb; //extends
- btVector3 ca, cb; //extends
- get_center_extend(ca, ea);
- box.get_center_extend(cb, eb);
-
- btVector3 T;
- btScalar t, t2;
- int i;
-
- // Class I : A's basis vectors
- for (i = 0; i < 3; i++)
- {
- T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
- t = transcache.m_AR[i].dot(eb) + ea[i];
- if (GIM_GREATER(T[i], t)) return false;
- }
- // Class II : B's basis vectors
- for (i = 0; i < 3; i++)
- {
- t = MAT_DOT_COL(transcache.m_R1to0, T, i);
- t2 = MAT_DOT_COL(transcache.m_AR, ea, i) + eb[i];
- if (GIM_GREATER(t, t2)) return false;
- }
- // Class III : 9 cross products
- if (fulltest)
- {
- int j, m, n, o, p, q, r;
- for (i = 0; i < 3; i++)
- {
- m = (i + 1) % 3;
- n = (i + 2) % 3;
- o = i == 0 ? 1 : 0;
- p = i == 2 ? 1 : 2;
- for (j = 0; j < 3; j++)
- {
- q = j == 2 ? 1 : 2;
- r = j == 0 ? 1 : 0;
- t = T[n] * transcache.m_R1to0[m][j] - T[m] * transcache.m_R1to0[n][j];
- t2 = ea[o] * transcache.m_AR[p][j] + ea[p] * transcache.m_AR[o][j] +
- eb[r] * transcache.m_AR[i][q] + eb[q] * transcache.m_AR[i][r];
- if (GIM_GREATER(t, t2)) return false;
- }
- }
- }
- return true;
- }
-
- //! Simple test for planes.
- SIMD_FORCE_INLINE bool collide_plane(
- const btVector4 &plane)
- {
- ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
- return (classify == G_COLLIDE_PLANE);
- }
-
- //! test for a triangle, with edges
- SIMD_FORCE_INLINE bool collide_triangle_exact(
- const btVector3 &p1,
- const btVector3 &p2,
- const btVector3 &p3,
- const btVector4 &triangle_plane)
- {
- if (!collide_plane(triangle_plane)) return false;
-
- btVector3 center, extends;
- this->get_center_extend(center, extends);
-
- const btVector3 v1(p1 - center);
- const btVector3 v2(p2 - center);
- const btVector3 v3(p3 - center);
-
- //First axis
- btVector3 diff(v2 - v1);
- btVector3 abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v1, v3, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v1, v3, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v1, v3, extends);
-
- diff = v3 - v2;
- abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v2, v1, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v2, v1, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v2, v1, extends);
-
- diff = v1 - v3;
- abs_diff = diff.absolute();
- //Test With X axis
- TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff, abs_diff, v3, v2, extends);
- //Test With Y axis
- TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff, abs_diff, v3, v2, extends);
- //Test With Z axis
- TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff, abs_diff, v3, v2, extends);
-
- return true;
- }
-};
-
-#ifndef BT_BOX_COLLISION_H_INCLUDED
-//! Compairison of transformation objects
-SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform &t1, const btTransform &t2)
-{
- if (!(t1.getOrigin() == t2.getOrigin())) return false;
-
- if (!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0))) return false;
- if (!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1))) return false;
- if (!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2))) return false;
- return true;
-}
-#endif
-
-#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp
deleted file mode 100644
index 0c7a6b7fc1..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_box_set.h"
-
-GUINT GIM_BOX_TREE::_calc_splitting_axis(
- gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
-{
- GUINT i;
-
- btVector3 means(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 variance(btScalar(0.), btScalar(0.), btScalar(0.));
- GUINT numIndices = endIndex - startIndex;
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- means += center;
- }
- means *= (btScalar(1.) / (btScalar)numIndices);
-
- for (i = startIndex; i < endIndex; i++)
- {
- btVector3 center = btScalar(0.5) * (primitive_boxes[i].m_bound.m_max +
- primitive_boxes[i].m_bound.m_min);
- btVector3 diff2 = center - means;
- diff2 = diff2 * diff2;
- variance += diff2;
- }
- variance *= (btScalar(1.) / ((btScalar)numIndices - 1));
-
- return variance.maxAxis();
-}
-
-GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
- gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex,
- GUINT endIndex, GUINT splitAxis)
-{
- GUINT i;
- GUINT splitIndex = startIndex;
- GUINT numIndices = endIndex - startIndex;
-
- // average of centers
- btScalar splitValue = 0.0f;
- for (i = startIndex; i < endIndex; i++)
- {
- splitValue += 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
- primitive_boxes[i].m_bound.m_min[splitAxis]);
- }
- splitValue /= (btScalar)numIndices;
-
- //sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
- for (i = startIndex; i < endIndex; i++)
- {
- btScalar center = 0.5f * (primitive_boxes[i].m_bound.m_max[splitAxis] +
- primitive_boxes[i].m_bound.m_min[splitAxis]);
- if (center > splitValue)
- {
- //swap
- primitive_boxes.swap(i, splitIndex);
- splitIndex++;
- }
- }
-
- //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
- //otherwise the tree-building might fail due to stack-overflows in certain cases.
- //unbalanced1 is unsafe: it can cause stack overflows
- //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
-
- //unbalanced2 should work too: always use center (perfect balanced trees)
- //bool unbalanced2 = true;
-
- //this should be safe too:
- GUINT rangeBalancedIndices = numIndices / 3;
- bool unbalanced = ((splitIndex <= (startIndex + rangeBalancedIndices)) || (splitIndex >= (endIndex - 1 - rangeBalancedIndices)));
-
- if (unbalanced)
- {
- splitIndex = startIndex + (numIndices >> 1);
- }
-
- btAssert(!((splitIndex == startIndex) || (splitIndex == (endIndex))));
-
- return splitIndex;
-}
-
-void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex)
-{
- GUINT current_index = m_num_nodes++;
-
- btAssert((endIndex - startIndex) > 0);
-
- if ((endIndex - startIndex) == 1) //we got a leaf
- {
- m_node_array[current_index].m_left = 0;
- m_node_array[current_index].m_right = 0;
- m_node_array[current_index].m_escapeIndex = 0;
-
- m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
- m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
- return;
- }
-
- //configure inner node
-
- GUINT splitIndex;
-
- //calc this node bounding box
- m_node_array[current_index].m_bound.invalidate();
- for (splitIndex = startIndex; splitIndex < endIndex; splitIndex++)
- {
- m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
- }
-
- //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
-
- //split axis
- splitIndex = _calc_splitting_axis(primitive_boxes, startIndex, endIndex);
-
- splitIndex = _sort_and_calc_splitting_index(
- primitive_boxes, startIndex, endIndex, splitIndex);
-
- //configure this inner node : the left node index
- m_node_array[current_index].m_left = m_num_nodes;
- //build left child tree
- _build_sub_tree(primitive_boxes, startIndex, splitIndex);
-
- //configure this inner node : the right node index
- m_node_array[current_index].m_right = m_num_nodes;
-
- //build right child tree
- _build_sub_tree(primitive_boxes, splitIndex, endIndex);
-
- //configure this inner node : the escape index
- m_node_array[current_index].m_escapeIndex = m_num_nodes - current_index;
-}
-
-//! stackless build tree
-void GIM_BOX_TREE::build_tree(
- gim_array<GIM_AABB_DATA>& primitive_boxes)
-{
- // initialize node count to 0
- m_num_nodes = 0;
- // allocate nodes
- m_node_array.resize(primitive_boxes.size() * 2);
-
- _build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
deleted file mode 100644
index afc591dac0..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_box_set.h
+++ /dev/null
@@ -1,640 +0,0 @@
-#ifndef GIM_BOX_SET_H_INCLUDED
-#define GIM_BOX_SET_H_INCLUDED
-
-/*! \file gim_box_set.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_array.h"
-#include "gim_radixsort.h"
-#include "gim_box_collision.h"
-#include "gim_tri_collision.h"
-#include "gim_pair.h"
-
-//! A pairset array
-class gim_pair_set : public gim_array<GIM_PAIR>
-{
-public:
- gim_pair_set() : gim_array<GIM_PAIR>(32)
- {
- }
- inline void push_pair(GUINT index1, GUINT index2)
- {
- push_back(GIM_PAIR(index1, index2));
- }
-
- inline void push_pair_inv(GUINT index1, GUINT index2)
- {
- push_back(GIM_PAIR(index2, index1));
- }
-};
-
-//! Prototype Base class for primitive classification
-/*!
-This class is a wrapper for primitive collections.
-This tells relevant info for the Bounding Box set classes, which take care of space classification.
-This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
-*/
-class GIM_PRIMITIVE_MANAGER_PROTOTYPE
-{
-public:
- virtual ~GIM_PRIMITIVE_MANAGER_PROTOTYPE() {}
- //! determines if this manager consist on only triangles, which special case will be optimized
- virtual bool is_trimesh() = 0;
- virtual GUINT get_primitive_count() = 0;
- virtual void get_primitive_box(GUINT prim_index, GIM_AABB& primbox) = 0;
- virtual void get_primitive_triangle(GUINT prim_index, GIM_TRIANGLE& triangle) = 0;
-};
-
-struct GIM_AABB_DATA
-{
- GIM_AABB m_bound;
- GUINT m_data;
-};
-
-//! Node Structure for trees
-struct GIM_BOX_TREE_NODE
-{
- GIM_AABB m_bound;
- GUINT m_left; //!< Left subtree
- GUINT m_right; //!< Right subtree
- GUINT m_escapeIndex; //!< Scape index for traversing
- GUINT m_data; //!< primitive index if apply
-
- GIM_BOX_TREE_NODE()
- {
- m_left = 0;
- m_right = 0;
- m_escapeIndex = 0;
- m_data = 0;
- }
-
- SIMD_FORCE_INLINE bool is_leaf_node() const
- {
- return (!m_left && !m_right);
- }
-};
-
-//! Basic Box tree structure
-class GIM_BOX_TREE
-{
-protected:
- GUINT m_num_nodes;
- gim_array<GIM_BOX_TREE_NODE> m_node_array;
-
-protected:
- GUINT _sort_and_calc_splitting_index(
- gim_array<GIM_AABB_DATA>& primitive_boxes,
- GUINT startIndex, GUINT endIndex, GUINT splitAxis);
-
- GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
-
- void _build_sub_tree(gim_array<GIM_AABB_DATA>& primitive_boxes, GUINT startIndex, GUINT endIndex);
-
-public:
- GIM_BOX_TREE()
- {
- m_num_nodes = 0;
- }
-
- //! prototype functions for box tree management
- //!@{
- void build_tree(gim_array<GIM_AABB_DATA>& primitive_boxes);
-
- SIMD_FORCE_INLINE void clearNodes()
- {
- m_node_array.clear();
- m_num_nodes = 0;
- }
-
- //! node count
- SIMD_FORCE_INLINE GUINT getNodeCount() const
- {
- return m_num_nodes;
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
- {
- return m_node_array[nodeindex].is_leaf_node();
- }
-
- SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
- {
- return m_node_array[nodeindex].m_data;
- }
-
- SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
- {
- bound = m_node_array[nodeindex].m_bound;
- }
-
- SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
- {
- m_node_array[nodeindex].m_bound = bound;
- }
-
- SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
- {
- return m_node_array[nodeindex].m_left;
- }
-
- SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
- {
- return m_node_array[nodeindex].m_right;
- }
-
- SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
- {
- return m_node_array[nodeindex].m_escapeIndex;
- }
-
- //!@}
-};
-
-//! Generic Box Tree Template
-/*!
-This class offers an structure for managing a box tree of primitives.
-Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
-a Box tree structure ( like GIM_BOX_TREE).
-*/
-template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
-class GIM_BOX_TREE_TEMPLATE_SET
-{
-protected:
- _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
- _GIM_BOX_TREE_PROTOTYPE m_box_tree;
-
-protected:
- //stackless refit
- SIMD_FORCE_INLINE void refit()
- {
- GUINT nodecount = getNodeCount();
- while (nodecount--)
- {
- if (isLeafNode(nodecount))
- {
- GIM_AABB leafbox;
- m_primitive_manager.get_primitive_box(getNodeData(nodecount), leafbox);
- setNodeBound(nodecount, leafbox);
- }
- else
- {
- //get left bound
- GUINT childindex = getLeftNodeIndex(nodecount);
- GIM_AABB bound;
- getNodeBound(childindex, bound);
- //get right bound
- childindex = getRightNodeIndex(nodecount);
- GIM_AABB bound2;
- getNodeBound(childindex, bound2);
- bound.merge(bound2);
-
- setNodeBound(nodecount, bound);
- }
- }
- }
-
-public:
- GIM_BOX_TREE_TEMPLATE_SET()
- {
- }
-
- SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const
- {
- GIM_AABB totalbox;
- getNodeBound(0, totalbox);
- return totalbox;
- }
-
- SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& primitive_manager)
- {
- m_primitive_manager = primitive_manager;
- }
-
- const _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager() const
- {
- return m_primitive_manager;
- }
-
- _GIM_PRIMITIVE_MANAGER_PROTOTYPE& getPrimitiveManager()
- {
- return m_primitive_manager;
- }
-
- //! node manager prototype functions
- ///@{
-
- //! this attemps to refit the box set.
- SIMD_FORCE_INLINE void update()
- {
- refit();
- }
-
- //! this rebuild the entire set
- SIMD_FORCE_INLINE void buildSet()
- {
- //obtain primitive boxes
- gim_array<GIM_AABB_DATA> primitive_boxes;
- primitive_boxes.resize(m_primitive_manager.get_primitive_count(), false);
-
- for (GUINT i = 0; i < primitive_boxes.size(); i++)
- {
- m_primitive_manager.get_primitive_box(i, primitive_boxes[i].m_bound);
- primitive_boxes[i].m_data = i;
- }
-
- m_box_tree.build_tree(primitive_boxes);
- }
-
- //! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB& box, gim_array<GUINT>& collided_results) const
- {
- GUINT curIndex = 0;
- GUINT numNodes = getNodeCount();
-
- while (curIndex < numNodes)
- {
- GIM_AABB bound;
- getNodeBound(curIndex, bound);
-
- //catch bugs in tree data
-
- bool aabbOverlap = bound.has_collision(box);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getScapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
- }
-
- //! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB& box,
- const btTransform& transform, gim_array<GUINT>& collided_results) const
- {
- GIM_AABB transbox = box;
- transbox.appy_transform(transform);
- return boxQuery(transbox, collided_results);
- }
-
- //! returns the indices of the primitives in the m_primitive_manager
- SIMD_FORCE_INLINE bool rayQuery(
- const btVector3& ray_dir, const btVector3& ray_origin,
- gim_array<GUINT>& collided_results) const
- {
- GUINT curIndex = 0;
- GUINT numNodes = getNodeCount();
-
- while (curIndex < numNodes)
- {
- GIM_AABB bound;
- getNodeBound(curIndex, bound);
-
- //catch bugs in tree data
-
- bool aabbOverlap = bound.collide_ray(ray_origin, ray_dir);
- bool isleafnode = isLeafNode(curIndex);
-
- if (isleafnode && aabbOverlap)
- {
- collided_results.push_back(getNodeData(curIndex));
- }
-
- if (aabbOverlap || isleafnode)
- {
- //next subnode
- curIndex++;
- }
- else
- {
- //skip node
- curIndex += getScapeNodeIndex(curIndex);
- }
- }
- if (collided_results.size() > 0) return true;
- return false;
- }
-
- //! tells if this set has hierarcht
- SIMD_FORCE_INLINE bool hasHierarchy() const
- {
- return true;
- }
-
- //! tells if this set is a trimesh
- SIMD_FORCE_INLINE bool isTrimesh() const
- {
- return m_primitive_manager.is_trimesh();
- }
-
- //! node count
- SIMD_FORCE_INLINE GUINT getNodeCount() const
- {
- return m_box_tree.getNodeCount();
- }
-
- //! tells if the node is a leaf
- SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
- {
- return m_box_tree.isLeafNode(nodeindex);
- }
-
- SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
- {
- return m_box_tree.getNodeData(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB& bound) const
- {
- m_box_tree.getNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB& bound)
- {
- m_box_tree.setNodeBound(nodeindex, bound);
- }
-
- SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
- {
- return m_box_tree.getLeftNodeIndex(nodeindex);
- }
-
- SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
- {
- return m_box_tree.getRightNodeIndex(nodeindex);
- }
-
- SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
- {
- return m_box_tree.getScapeNodeIndex(nodeindex);
- }
-
- SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex, GIM_TRIANGLE& triangle) const
- {
- m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex), triangle);
- }
-};
-
-//! Class for Box Tree Sets
-/*!
-this has the GIM_BOX_TREE implementation for bounding boxes.
-*/
-template <typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
-class GIM_BOX_TREE_SET : public GIM_BOX_TREE_TEMPLATE_SET<_GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
-{
-public:
-};
-
-/// GIM_BOX_SET collision methods
-template <typename BOX_SET_CLASS0, typename BOX_SET_CLASS1>
-class GIM_TREE_TREE_COLLIDER
-{
-public:
- gim_pair_set* m_collision_pairs;
- BOX_SET_CLASS0* m_boxset0;
- BOX_SET_CLASS1* m_boxset1;
- GUINT current_node0;
- GUINT current_node1;
- bool node0_is_leaf;
- bool node1_is_leaf;
- bool t0_is_trimesh;
- bool t1_is_trimesh;
- bool node0_has_triangle;
- bool node1_has_triangle;
- GIM_AABB m_box0;
- GIM_AABB m_box1;
- GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
- btTransform trans_cache_0to1;
- GIM_TRIANGLE m_tri0;
- btVector4 m_tri0_plane;
- GIM_TRIANGLE m_tri1;
- btVector4 m_tri1_plane;
-
-public:
- GIM_TREE_TREE_COLLIDER()
- {
- current_node0 = G_UINT_INFINITY;
- current_node1 = G_UINT_INFINITY;
- }
-
-protected:
- SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
- {
- if (node0_has_triangle) return;
- m_boxset0->getNodeTriangle(node0, m_tri0);
- //transform triangle
- m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
- m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
- m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
- m_tri0.get_plane(m_tri0_plane);
-
- node0_has_triangle = true;
- }
-
- SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
- {
- if (node1_has_triangle) return;
- m_boxset1->getNodeTriangle(node1, m_tri1);
- //transform triangle
- m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
- m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
- m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
- m_tri1.get_plane(m_tri1_plane);
-
- node1_has_triangle = true;
- }
-
- SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
- {
- if (node0 == current_node0) return;
- m_boxset0->getNodeBound(node0, m_box0);
- node0_is_leaf = m_boxset0->isLeafNode(node0);
- node0_has_triangle = false;
- current_node0 = node0;
- }
-
- SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
- {
- if (node1 == current_node1) return;
- m_boxset1->getNodeBound(node1, m_box1);
- node1_is_leaf = m_boxset1->isLeafNode(node1);
- node1_has_triangle = false;
- current_node1 = node1;
- }
-
- SIMD_FORCE_INLINE bool node_collision(GUINT node0, GUINT node1)
- {
- retrieve_node0_info(node0);
- retrieve_node1_info(node1);
- bool result = m_box0.overlapping_trans_cache(m_box1, trans_cache_1to0, true);
- if (!result) return false;
-
- if (t0_is_trimesh && node0_is_leaf)
- {
- //perform primitive vs box collision
- retrieve_node0_triangle(node0);
- //do triangle vs box collision
- m_box1.increment_margin(m_tri0.m_margin);
-
- result = m_box1.collide_triangle_exact(
- m_tri0.m_vertices[0], m_tri0.m_vertices[1], m_tri0.m_vertices[2], m_tri0_plane);
-
- m_box1.increment_margin(-m_tri0.m_margin);
-
- if (!result) return false;
- return true;
- }
- else if (t1_is_trimesh && node1_is_leaf)
- {
- //perform primitive vs box collision
- retrieve_node1_triangle(node1);
- //do triangle vs box collision
- m_box0.increment_margin(m_tri1.m_margin);
-
- result = m_box0.collide_triangle_exact(
- m_tri1.m_vertices[0], m_tri1.m_vertices[1], m_tri1.m_vertices[2], m_tri1_plane);
-
- m_box0.increment_margin(-m_tri1.m_margin);
-
- if (!result) return false;
- return true;
- }
- return true;
- }
-
- //stackless collision routine
- void find_collision_pairs()
- {
- gim_pair_set stack_collisions;
- stack_collisions.reserve(32);
-
- //add the first pair
- stack_collisions.push_pair(0, 0);
-
- while (stack_collisions.size())
- {
- //retrieve the last pair and pop
- GUINT node0 = stack_collisions.back().m_index1;
- GUINT node1 = stack_collisions.back().m_index2;
- stack_collisions.pop_back();
- if (node_collision(node0, node1)) // a collision is found
- {
- if (node0_is_leaf)
- {
- if (node1_is_leaf)
- {
- m_collision_pairs->push_pair(m_boxset0->getNodeData(node0), m_boxset1->getNodeData(node1));
- }
- else
- {
- //collide left
- stack_collisions.push_pair(node0, m_boxset1->getLeftNodeIndex(node1));
-
- //collide right
- stack_collisions.push_pair(node0, m_boxset1->getRightNodeIndex(node1));
- }
- }
- else
- {
- if (node1_is_leaf)
- {
- //collide left
- stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0), node1);
- //collide right
- stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0), node1);
- }
- else
- {
- GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
- GUINT right0 = m_boxset0->getRightNodeIndex(node0);
- GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
- GUINT right1 = m_boxset1->getRightNodeIndex(node1);
- //collide left
- stack_collisions.push_pair(left0, left1);
- //collide right
- stack_collisions.push_pair(left0, right1);
- //collide left
- stack_collisions.push_pair(right0, left1);
- //collide right
- stack_collisions.push_pair(right0, right1);
-
- } // else if node1 is not a leaf
- } // else if node0 is not a leaf
-
- } // if(node_collision(node0,node1))
- } //while(stack_collisions.size())
- }
-
-public:
- void find_collision(BOX_SET_CLASS0* boxset1, const btTransform& trans1,
- BOX_SET_CLASS1* boxset2, const btTransform& trans2,
- gim_pair_set& collision_pairs, bool complete_primitive_tests = true)
- {
- m_collision_pairs = &collision_pairs;
- m_boxset0 = boxset1;
- m_boxset1 = boxset2;
-
- trans_cache_1to0.calc_from_homogenic(trans1, trans2);
-
- trans_cache_0to1 = trans2.inverse();
- trans_cache_0to1 *= trans1;
-
- if (complete_primitive_tests)
- {
- t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
- t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
- }
- else
- {
- t0_is_trimesh = false;
- t1_is_trimesh = false;
- }
-
- find_collision_pairs();
- }
-};
-
-#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h
deleted file mode 100644
index 57b9c5c91a..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_clip_polygon.h
+++ /dev/null
@@ -1,199 +0,0 @@
-#ifndef GIM_CLIP_POLYGON_H_INCLUDED
-#define GIM_CLIP_POLYGON_H_INCLUDED
-
-/*! \file gim_tri_collision.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-//! This function calcs the distance from a 3D plane
-class DISTANCE_PLANE_3D_FUNC
-{
-public:
- template <typename CLASS_POINT, typename CLASS_PLANE>
- inline GREAL operator()(const CLASS_PLANE& plane, const CLASS_POINT& point)
- {
- return DISTANCE_PLANE_POINT(plane, point);
- }
-};
-
-template <typename CLASS_POINT>
-SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
- const CLASS_POINT& point0,
- const CLASS_POINT& point1,
- GREAL dist0,
- GREAL dist1,
- CLASS_POINT* clipped,
- GUINT& clipped_count)
-{
- GUINT _prevclassif = (dist0 > G_EPSILON);
- GUINT _classif = (dist1 > G_EPSILON);
- if (_classif != _prevclassif)
- {
- GREAL blendfactor = -dist0 / (dist1 - dist0);
- VEC_BLEND(clipped[clipped_count], point0, point1, blendfactor);
- clipped_count++;
- }
- if (!_classif)
- {
- VEC_COPY(clipped[clipped_count], point1);
- clipped_count++;
- }
-}
-
-//! Clips a polygon by a plane
-/*!
-*\return The count of the clipped counts
-*/
-template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
-SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
- const CLASS_PLANE& plane,
- const CLASS_POINT* polygon_points,
- GUINT polygon_point_count,
- CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
-{
- GUINT clipped_count = 0;
-
- //clip first point
- GREAL firstdist = distance_func(plane, polygon_points[0]);
- ;
- if (!(firstdist > G_EPSILON))
- {
- VEC_COPY(clipped[clipped_count], polygon_points[0]);
- clipped_count++;
- }
-
- GREAL olddist = firstdist;
- for (GUINT _i = 1; _i < polygon_point_count; _i++)
- {
- GREAL dist = distance_func(plane, polygon_points[_i]);
-
- PLANE_CLIP_POLYGON_COLLECT(
- polygon_points[_i - 1], polygon_points[_i],
- olddist,
- dist,
- clipped,
- clipped_count);
-
- olddist = dist;
- }
-
- //RETURN TO FIRST point
-
- PLANE_CLIP_POLYGON_COLLECT(
- polygon_points[polygon_point_count - 1], polygon_points[0],
- olddist,
- firstdist,
- clipped,
- clipped_count);
-
- return clipped_count;
-}
-
-//! Clips a polygon by a plane
-/*!
-*\return The count of the clipped counts
-*/
-template <typename CLASS_POINT, typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
-SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
- const CLASS_PLANE& plane,
- const CLASS_POINT& point0,
- const CLASS_POINT& point1,
- const CLASS_POINT& point2,
- CLASS_POINT* clipped, DISTANCE_PLANE_FUNC distance_func)
-{
- GUINT clipped_count = 0;
-
- //clip first point
- GREAL firstdist = distance_func(plane, point0);
- ;
- if (!(firstdist > G_EPSILON))
- {
- VEC_COPY(clipped[clipped_count], point0);
- clipped_count++;
- }
-
- // point 1
- GREAL olddist = firstdist;
- GREAL dist = distance_func(plane, point1);
-
- PLANE_CLIP_POLYGON_COLLECT(
- point0, point1,
- olddist,
- dist,
- clipped,
- clipped_count);
-
- olddist = dist;
-
- // point 2
- dist = distance_func(plane, point2);
-
- PLANE_CLIP_POLYGON_COLLECT(
- point1, point2,
- olddist,
- dist,
- clipped,
- clipped_count);
- olddist = dist;
-
- //RETURN TO FIRST point
- PLANE_CLIP_POLYGON_COLLECT(
- point2, point0,
- olddist,
- firstdist,
- clipped,
- clipped_count);
-
- return clipped_count;
-}
-
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
- const CLASS_PLANE& plane,
- const CLASS_POINT* polygon_points,
- GUINT polygon_point_count,
- CLASS_POINT* clipped)
-{
- return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, polygon_points, polygon_point_count, clipped, DISTANCE_PLANE_3D_FUNC());
-}
-
-template <typename CLASS_POINT, typename CLASS_PLANE>
-SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
- const CLASS_PLANE& plane,
- const CLASS_POINT& point0,
- const CLASS_POINT& point1,
- const CLASS_POINT& point2,
- CLASS_POINT* clipped)
-{
- return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT, CLASS_PLANE>(plane, point0, point1, point2, clipped, DISTANCE_PLANE_3D_FUNC());
-}
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp
deleted file mode 100644
index 390225709e..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_contact.h"
-
-#define MAX_COINCIDENT 8
-
-void gim_contact_array::merge_contacts(
- const gim_contact_array& contacts, bool normal_contact_average)
-{
- clear();
-
- if (contacts.size() == 1)
- {
- push_back(contacts.back());
- return;
- }
-
- gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
- keycontacts.resize(contacts.size(), false);
-
- //fill key contacts
-
- GUINT i;
-
- for (i = 0; i < contacts.size(); i++)
- {
- keycontacts[i].m_key = contacts[i].calc_key_contact();
- keycontacts[i].m_value = i;
- }
-
- //sort keys
- gim_heap_sort(keycontacts.pointer(), keycontacts.size(), GIM_RSORT_TOKEN_COMPARATOR());
-
- // Merge contacts
-
- GUINT coincident_count = 0;
- btVector3 coincident_normals[MAX_COINCIDENT];
-
- GUINT last_key = keycontacts[0].m_key;
- GUINT key = 0;
-
- push_back(contacts[keycontacts[0].m_value]);
- GIM_CONTACT* pcontact = &back();
-
- for (i = 1; i < keycontacts.size(); i++)
- {
- key = keycontacts[i].m_key;
- const GIM_CONTACT* scontact = &contacts[keycontacts[i].m_value];
-
- if (last_key == key) //same points
- {
- //merge contact
- if (pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth) //)
- {
- *pcontact = *scontact;
- coincident_count = 0;
- }
- else if (normal_contact_average)
- {
- if (btFabs(pcontact->m_depth - scontact->m_depth) < CONTACT_DIFF_EPSILON)
- {
- if (coincident_count < MAX_COINCIDENT)
- {
- coincident_normals[coincident_count] = scontact->m_normal;
- coincident_count++;
- }
- }
- }
- }
- else
- { //add new contact
-
- if (normal_contact_average && coincident_count > 0)
- {
- pcontact->interpolate_normals(coincident_normals, coincident_count);
- coincident_count = 0;
- }
-
- push_back(*scontact);
- pcontact = &back();
- }
- last_key = key;
- }
-}
-
-void gim_contact_array::merge_contacts_unique(const gim_contact_array& contacts)
-{
- clear();
-
- if (contacts.size() == 1)
- {
- push_back(contacts.back());
- return;
- }
-
- GIM_CONTACT average_contact = contacts.back();
-
- for (GUINT i = 1; i < contacts.size(); i++)
- {
- average_contact.m_point += contacts[i].m_point;
- average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
- }
-
- //divide
- GREAL divide_average = 1.0f / ((GREAL)contacts.size());
-
- average_contact.m_point *= divide_average;
-
- average_contact.m_normal *= divide_average;
-
- average_contact.m_depth = average_contact.m_normal.length();
-
- average_contact.m_normal /= average_contact.m_depth;
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h
deleted file mode 100644
index 9deb28a26e..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_contact.h
+++ /dev/null
@@ -1,168 +0,0 @@
-#ifndef GIM_CONTACT_H_INCLUDED
-#define GIM_CONTACT_H_INCLUDED
-
-/*! \file gim_contact.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-#include "gim_geometry.h"
-#include "gim_radixsort.h"
-#include "gim_array.h"
-
-/**
-Configuration var for applying interpolation of contact normals
-*/
-#ifndef NORMAL_CONTACT_AVERAGE
-#define NORMAL_CONTACT_AVERAGE 1
-#endif
-
-#ifndef CONTACT_DIFF_EPSILON
-#define CONTACT_DIFF_EPSILON 0.00001f
-#endif
-
-#ifndef BT_CONTACT_H_STRUCTS_INCLUDED
-
-/// Structure for collision results
-///Functions for managing and sorting contacts resulting from a collision query.
-///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
-///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
-///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
-class GIM_CONTACT
-{
-public:
- btVector3 m_point;
- btVector3 m_normal;
- GREAL m_depth; //Positive value indicates interpenetration
- GREAL m_distance; //Padding not for use
- GUINT m_feature1; //Face number
- GUINT m_feature2; //Face number
-public:
- GIM_CONTACT()
- {
- }
-
- GIM_CONTACT(const GIM_CONTACT &contact) : m_point(contact.m_point),
- m_normal(contact.m_normal),
- m_depth(contact.m_depth),
- m_feature1(contact.m_feature1),
- m_feature2(contact.m_feature2)
- {
- m_point = contact.m_point;
- m_normal = contact.m_normal;
- m_depth = contact.m_depth;
- m_feature1 = contact.m_feature1;
- m_feature2 = contact.m_feature2;
- }
-
- GIM_CONTACT(const btVector3 &point, const btVector3 &normal,
- GREAL depth, GUINT feature1, GUINT feature2) : m_point(point),
- m_normal(normal),
- m_depth(depth),
- m_feature1(feature1),
- m_feature2(feature2)
- {
- }
-
- //! Calcs key for coord classification
- SIMD_FORCE_INLINE GUINT calc_key_contact() const
- {
- GINT _coords[] = {
- (GINT)(m_point[0] * 1000.0f + 1.0f),
- (GINT)(m_point[1] * 1333.0f),
- (GINT)(m_point[2] * 2133.0f + 3.0f)};
- GUINT _hash = 0;
- GUINT *_uitmp = (GUINT *)(&_coords[0]);
- _hash = *_uitmp;
- _uitmp++;
- _hash += (*_uitmp) << 4;
- _uitmp++;
- _hash += (*_uitmp) << 8;
- return _hash;
- }
-
- SIMD_FORCE_INLINE void interpolate_normals(btVector3 *normals, GUINT normal_count)
- {
- btVector3 vec_sum(m_normal);
- for (GUINT i = 0; i < normal_count; i++)
- {
- vec_sum += normals[i];
- }
-
- GREAL vec_sum_len = vec_sum.length2();
- if (vec_sum_len < CONTACT_DIFF_EPSILON) return;
-
- GIM_INV_SQRT(vec_sum_len, vec_sum_len); // 1/sqrt(vec_sum_len)
-
- m_normal = vec_sum * vec_sum_len;
- }
-};
-
-#endif
-
-class gim_contact_array : public gim_array<GIM_CONTACT>
-{
-public:
- gim_contact_array() : gim_array<GIM_CONTACT>(64)
- {
- }
-
- SIMD_FORCE_INLINE void push_contact(const btVector3 &point, const btVector3 &normal,
- GREAL depth, GUINT feature1, GUINT feature2)
- {
- push_back_mem();
- GIM_CONTACT &newele = back();
- newele.m_point = point;
- newele.m_normal = normal;
- newele.m_depth = depth;
- newele.m_feature1 = feature1;
- newele.m_feature2 = feature2;
- }
-
- SIMD_FORCE_INLINE void push_triangle_contacts(
- const GIM_TRIANGLE_CONTACT_DATA &tricontact,
- GUINT feature1, GUINT feature2)
- {
- for (GUINT i = 0; i < tricontact.m_point_count; i++)
- {
- push_back_mem();
- GIM_CONTACT &newele = back();
- newele.m_point = tricontact.m_points[i];
- newele.m_normal = tricontact.m_separating_normal;
- newele.m_depth = tricontact.m_penetration_depth;
- newele.m_feature1 = feature1;
- newele.m_feature2 = feature2;
- }
- }
-
- void merge_contacts(const gim_contact_array &contacts, bool normal_contact_average = true);
- void merge_contacts_unique(const gim_contact_array &contacts);
-};
-
-#endif // GIM_CONTACT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h
deleted file mode 100644
index 9dc48f354b..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_geom_types.h
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef GIM_GEOM_TYPES_H_INCLUDED
-#define GIM_GEOM_TYPES_H_INCLUDED
-
-/*! \file gim_geom_types.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_math.h"
-
-//! Short Integer vector 2D
-typedef GSHORT vec2s[2];
-//! Integer vector 3D
-typedef GSHORT vec3s[3];
-//! Integer vector 4D
-typedef GSHORT vec4s[4];
-
-//! Short Integer vector 2D
-typedef GUSHORT vec2us[2];
-//! Integer vector 3D
-typedef GUSHORT vec3us[3];
-//! Integer vector 4D
-typedef GUSHORT vec4us[4];
-
-//! Integer vector 2D
-typedef GINT vec2i[2];
-//! Integer vector 3D
-typedef GINT vec3i[3];
-//! Integer vector 4D
-typedef GINT vec4i[4];
-
-//! Unsigned Integer vector 2D
-typedef GUINT vec2ui[2];
-//! Unsigned Integer vector 3D
-typedef GUINT vec3ui[3];
-//! Unsigned Integer vector 4D
-typedef GUINT vec4ui[4];
-
-//! Float vector 2D
-typedef GREAL vec2f[2];
-//! Float vector 3D
-typedef GREAL vec3f[3];
-//! Float vector 4D
-typedef GREAL vec4f[4];
-
-//! Double vector 2D
-typedef GREAL2 vec2d[2];
-//! Float vector 3D
-typedef GREAL2 vec3d[3];
-//! Float vector 4D
-typedef GREAL2 vec4d[4];
-
-//! Matrix 2D, row ordered
-typedef GREAL mat2f[2][2];
-//! Matrix 3D, row ordered
-typedef GREAL mat3f[3][3];
-//! Matrix 4D, row ordered
-typedef GREAL mat4f[4][4];
-
-//! Quaternion
-typedef GREAL quatf[4];
-
-//typedef struct _aabb3f aabb3f;
-
-#endif // GIM_GEOM_TYPES_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h
deleted file mode 100644
index 4a7ac3c4d8..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_geometry.h
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef GIM_GEOMETRY_H_INCLUDED
-#define GIM_GEOMETRY_H_INCLUDED
-
-/*! \file gim_geometry.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-///Additional Headers for Collision
-#include "gim_basic_geometry_operations.h"
-#include "gim_clip_polygon.h"
-#include "gim_box_collision.h"
-#include "gim_tri_collision.h"
-
-#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h
deleted file mode 100644
index abf88d3108..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_hash_table.h
+++ /dev/null
@@ -1,857 +0,0 @@
-#ifndef GIM_HASH_TABLE_H_INCLUDED
-#define GIM_HASH_TABLE_H_INCLUDED
-/*! \file gim_trimesh_data.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_radixsort.h"
-
-#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
-#define GIM_DEFAULT_HASH_TABLE_SIZE 380
-#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
-#define GIM_HASH_TABLE_GROW_FACTOR 2
-
-#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
-
-template <typename T>
-struct GIM_HASH_TABLE_NODE
-{
- GUINT m_key;
- T m_data;
- GIM_HASH_TABLE_NODE()
- {
- }
-
- GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE& value)
- {
- m_key = value.m_key;
- m_data = value.m_data;
- }
-
- GIM_HASH_TABLE_NODE(GUINT key, const T& data)
- {
- m_key = key;
- m_data = data;
- }
-
- bool operator<(const GIM_HASH_TABLE_NODE<T>& other) const
- {
- ///inverse order, further objects are first
- if (m_key < other.m_key) return true;
- return false;
- }
-
- bool operator>(const GIM_HASH_TABLE_NODE<T>& other) const
- {
- ///inverse order, further objects are first
- if (m_key > other.m_key) return true;
- return false;
- }
-
- bool operator==(const GIM_HASH_TABLE_NODE<T>& other) const
- {
- ///inverse order, further objects are first
- if (m_key == other.m_key) return true;
- return false;
- }
-};
-
-///Macro for getting the key
-class GIM_HASH_NODE_GET_KEY
-{
-public:
- template <class T>
- inline GUINT operator()(const T& a)
- {
- return a.m_key;
- }
-};
-
-///Macro for comparing the key and the element
-class GIM_HASH_NODE_CMP_KEY_MACRO
-{
-public:
- template <class T>
- inline int operator()(const T& a, GUINT key)
- {
- return ((int)(a.m_key - key));
- }
-};
-
-///Macro for comparing Hash nodes
-class GIM_HASH_NODE_CMP_MACRO
-{
-public:
- template <class T>
- inline int operator()(const T& a, const T& b)
- {
- return ((int)(a.m_key - b.m_key));
- }
-};
-
-//! Sorting for hash table
-/*!
-switch automatically between quicksort and radixsort
-*/
-template <typename T>
-void gim_sort_hash_node_array(T* array, GUINT array_count)
-{
- if (array_count < GIM_MIN_RADIX_SORT_SIZE)
- {
- gim_heap_sort(array, array_count, GIM_HASH_NODE_CMP_MACRO());
- }
- else
- {
- memcopy_elements_func cmpfunc;
- gim_radix_sort(array, array_count, GIM_HASH_NODE_GET_KEY(), cmpfunc);
- }
-}
-
-// Note: assumes long is at least 32 bits.
-#define GIM_NUM_PRIME 28
-
-static const GUINT gim_prime_list[GIM_NUM_PRIME] =
- {
- 53ul, 97ul, 193ul, 389ul, 769ul,
- 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
- 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
- 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
- 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
- 1610612741ul, 3221225473ul, 4294967291ul};
-
-inline GUINT gim_next_prime(GUINT number)
-{
- //Find nearest upper prime
- GUINT result_ind = 0;
- gim_binary_search(gim_prime_list, 0, (GIM_NUM_PRIME - 2), number, result_ind);
-
- // inv: result_ind < 28
- return gim_prime_list[result_ind];
-}
-
-//! A compact hash table implementation
-/*!
-A memory aligned compact hash table that coud be treated as an array.
-It could be a simple sorted array without the overhead of the hash key bucked, or could
-be a formely hash table with an array of keys.
-You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
-</br>
-
-<ul>
-<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
-When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
-<li> If node_size != 0, then this container becomes a hash table for ever
-</ul>
-
-*/
-template <class T>
-class gim_hash_table
-{
-protected:
- typedef GIM_HASH_TABLE_NODE<T> _node_type;
-
- //!The nodes
- //array< _node_type, SuperAllocator<_node_type> > m_nodes;
- gim_array<_node_type> m_nodes;
- //SuperBufferedArray< _node_type > m_nodes;
- bool m_sorted;
-
- ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
- GUINT* m_hash_table; //!<
- GUINT m_table_size; //!<
- GUINT m_node_size; //!<
- GUINT m_min_hash_table_size;
-
- //! Returns the cell index
- inline GUINT _find_cell(GUINT hashkey)
- {
- _node_type* nodesptr = m_nodes.pointer();
- GUINT start_index = (hashkey % m_table_size) * m_node_size;
- GUINT end_index = start_index + m_node_size;
-
- while (start_index < end_index)
- {
- GUINT value = m_hash_table[start_index];
- if (value != GIM_INVALID_HASH)
- {
- if (nodesptr[value].m_key == hashkey) return start_index;
- }
- start_index++;
- }
- return GIM_INVALID_HASH;
- }
-
- //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
- inline GUINT _find_avaliable_cell(GUINT hashkey)
- {
- _node_type* nodesptr = m_nodes.pointer();
- GUINT avaliable_index = GIM_INVALID_HASH;
- GUINT start_index = (hashkey % m_table_size) * m_node_size;
- GUINT end_index = start_index + m_node_size;
-
- while (start_index < end_index)
- {
- GUINT value = m_hash_table[start_index];
- if (value == GIM_INVALID_HASH)
- {
- if (avaliable_index == GIM_INVALID_HASH)
- {
- avaliable_index = start_index;
- }
- }
- else if (nodesptr[value].m_key == hashkey)
- {
- return start_index;
- }
- start_index++;
- }
- return avaliable_index;
- }
-
- //! reserves the memory for the hash table.
- /*!
- \pre hash table must be empty
- \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
- */
- inline void _reserve_table_memory(GUINT newtablesize)
- {
- if (newtablesize == 0) return;
- if (m_node_size == 0) return;
-
- //Get a Prime size
-
- m_table_size = gim_next_prime(newtablesize);
-
- GUINT datasize = m_table_size * m_node_size;
- //Alloc the data buffer
- m_hash_table = (GUINT*)gim_alloc(datasize * sizeof(GUINT));
- }
-
- inline void _invalidate_keys()
- {
- GUINT datasize = m_table_size * m_node_size;
- for (GUINT i = 0; i < datasize; i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH; // invalidate keys
- }
- }
-
- //! Clear all memory for the hash table
- inline void _clear_table_memory()
- {
- if (m_hash_table == NULL) return;
- gim_free(m_hash_table);
- m_hash_table = NULL;
- m_table_size = 0;
- }
-
- //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
- inline void _rehash()
- {
- _invalidate_keys();
-
- _node_type* nodesptr = m_nodes.pointer();
- for (GUINT i = 0; i < (GUINT)m_nodes.size(); i++)
- {
- GUINT nodekey = nodesptr[i].m_key;
- if (nodekey != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT index = _find_avaliable_cell(nodekey);
-
- if (m_hash_table[index] != GIM_INVALID_HASH)
- { //The new index is alreade used... discard this new incomming object, repeated key
- btAssert(m_hash_table[index] == nodekey);
- nodesptr[i].m_key = GIM_INVALID_HASH;
- }
- else
- {
- //;
- //Assign the value for alloc
- m_hash_table[index] = i;
- }
- }
- }
- }
-
- //! Resize hash table indices
- inline void _resize_table(GUINT newsize)
- {
- //Clear memory
- _clear_table_memory();
- //Alloc the data
- _reserve_table_memory(newsize);
- //Invalidate keys and rehash
- _rehash();
- }
-
- //! Destroy hash table memory
- inline void _destroy()
- {
- if (m_hash_table == NULL) return;
- _clear_table_memory();
- }
-
- //! Finds an avaliable hash table cell, and resizes the table if there isn't space
- inline GUINT _assign_hash_table_cell(GUINT hashkey)
- {
- GUINT cell_index = _find_avaliable_cell(hashkey);
-
- if (cell_index == GIM_INVALID_HASH)
- {
- //rehashing
- _resize_table(m_table_size + 1);
- GUINT cell_index = _find_avaliable_cell(hashkey);
- btAssert(cell_index != GIM_INVALID_HASH);
- }
- return cell_index;
- }
-
- //! erase by index in hash table
- inline bool _erase_by_index_hash_table(GUINT index)
- {
- if (index >= m_nodes.size()) return false;
- if (m_nodes[index].m_key != GIM_INVALID_HASH)
- {
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(m_nodes[index].m_key);
-
- btAssert(cell_index != GIM_INVALID_HASH);
- btAssert(m_hash_table[cell_index] == index);
-
- m_hash_table[cell_index] = GIM_INVALID_HASH;
- }
-
- return this->_erase_unsorted(index);
- }
-
- //! erase by key in hash table
- inline bool _erase_hash_table(GUINT hashkey)
- {
- if (hashkey == GIM_INVALID_HASH) return false;
-
- //Search for the avaliable cell in buffer
- GUINT cell_index = _find_cell(hashkey);
- if (cell_index == GIM_INVALID_HASH) return false;
-
- GUINT index = m_hash_table[cell_index];
- m_hash_table[cell_index] = GIM_INVALID_HASH;
-
- return this->_erase_unsorted(index);
- }
-
- //! insert an element in hash table
- /*!
- If the element exists, this won't insert the element
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT _insert_hash_table(GUINT hashkey, const T& value)
- {
- if (hashkey == GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey, value);
- return GIM_INVALID_HASH;
- }
-
- GUINT cell_index = _assign_hash_table_cell(hashkey);
-
- GUINT value_key = m_hash_table[cell_index];
-
- if (value_key != GIM_INVALID_HASH) return value_key; // Not overrited
-
- m_hash_table[cell_index] = m_nodes.size();
-
- _insert_unsorted(hashkey, value);
- return GIM_INVALID_HASH;
- }
-
- //! insert an element in hash table.
- /*!
- If the element exists, this replaces the element.
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT _insert_hash_table_replace(GUINT hashkey, const T& value)
- {
- if (hashkey == GIM_INVALID_HASH)
- {
- //Insert anyway
- _insert_unsorted(hashkey, value);
- return GIM_INVALID_HASH;
- }
-
- GUINT cell_index = _assign_hash_table_cell(hashkey);
-
- GUINT value_key = m_hash_table[cell_index];
-
- if (value_key != GIM_INVALID_HASH)
- { //replaces the existing
- m_nodes[value_key] = _node_type(hashkey, value);
- return value_key; // index of the replaced element
- }
-
- m_hash_table[cell_index] = m_nodes.size();
-
- _insert_unsorted(hashkey, value);
- return GIM_INVALID_HASH;
- }
-
- ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
- inline bool _erase_sorted(GUINT index)
- {
- if (index >= (GUINT)m_nodes.size()) return false;
- m_nodes.erase_sorted(index);
- if (m_nodes.size() < 2) m_sorted = false;
- return true;
- }
-
- //! faster, but unsorted
- inline bool _erase_unsorted(GUINT index)
- {
- if (index >= m_nodes.size()) return false;
-
- GUINT lastindex = m_nodes.size() - 1;
- if (index < lastindex && m_hash_table != 0)
- {
- GUINT hashkey = m_nodes[lastindex].m_key;
- if (hashkey != GIM_INVALID_HASH)
- {
- //update the new position of the last element
- GUINT cell_index = _find_cell(hashkey);
- btAssert(cell_index != GIM_INVALID_HASH);
- //new position of the last element which will be swaped
- m_hash_table[cell_index] = index;
- }
- }
- m_nodes.erase(index);
- m_sorted = false;
- return true;
- }
-
- //! Insert in position ordered
- /*!
- Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
- */
- inline void _insert_in_pos(GUINT hashkey, const T& value, GUINT pos)
- {
- m_nodes.insert(_node_type(hashkey, value), pos);
- this->check_for_switching_to_hashtable();
- }
-
- //! Insert an element in an ordered array
- inline GUINT _insert_sorted(GUINT hashkey, const T& value)
- {
- if (hashkey == GIM_INVALID_HASH || size() == 0)
- {
- m_nodes.push_back(_node_type(hashkey, value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
-
- GUINT result_ind = 0;
- GUINT last_index = m_nodes.size() - 1;
- _node_type* ptr = m_nodes.pointer();
-
- bool found = gim_binary_search_ex(
- ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
-
- //Insert before found index
- if (found)
- {
- return result_ind;
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return GIM_INVALID_HASH;
- }
-
- inline GUINT _insert_sorted_replace(GUINT hashkey, const T& value)
- {
- if (hashkey == GIM_INVALID_HASH || size() == 0)
- {
- m_nodes.push_back(_node_type(hashkey, value));
- return GIM_INVALID_HASH;
- }
- //Insert at last position
- //Sort element
- GUINT result_ind;
- GUINT last_index = m_nodes.size() - 1;
- _node_type* ptr = m_nodes.pointer();
-
- bool found = gim_binary_search_ex(
- ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
-
- //Insert before found index
- if (found)
- {
- m_nodes[result_ind] = _node_type(hashkey, value);
- }
- else
- {
- _insert_in_pos(hashkey, value, result_ind);
- }
- return result_ind;
- }
-
- //! Fast insertion in m_nodes array
- inline GUINT _insert_unsorted(GUINT hashkey, const T& value)
- {
- m_nodes.push_back(_node_type(hashkey, value));
- m_sorted = false;
- return GIM_INVALID_HASH;
- }
-
-public:
- /*!
- <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
- When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
- <li> If node_size != 0, then this container becomes a hash table for ever
- </ul>
- */
- gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
- GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
- GUINT min_hash_table_size = GIM_INVALID_HASH)
- {
- m_hash_table = NULL;
- m_table_size = 0;
- m_sorted = false;
- m_node_size = node_size;
- m_min_hash_table_size = min_hash_table_size;
-
- if (m_node_size != 0)
- {
- if (reserve_size != 0)
- {
- m_nodes.reserve(reserve_size);
- _reserve_table_memory(reserve_size);
- _invalidate_keys();
- }
- else
- {
- m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
- _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
- _invalidate_keys();
- }
- }
- else if (reserve_size != 0)
- {
- m_nodes.reserve(reserve_size);
- }
- }
-
- ~gim_hash_table()
- {
- _destroy();
- }
-
- inline bool is_hash_table()
- {
- if (m_hash_table) return true;
- return false;
- }
-
- inline bool is_sorted()
- {
- if (size() < 2) return true;
- return m_sorted;
- }
-
- bool sort()
- {
- if (is_sorted()) return true;
- if (m_nodes.size() < 2) return false;
-
- _node_type* ptr = m_nodes.pointer();
- GUINT siz = m_nodes.size();
- gim_sort_hash_node_array(ptr, siz);
- m_sorted = true;
-
- if (m_hash_table)
- {
- _rehash();
- }
- return true;
- }
-
- bool switch_to_hashtable()
- {
- if (m_hash_table) return false;
- if (m_node_size == 0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- if (m_nodes.size() < GIM_DEFAULT_HASH_TABLE_SIZE)
- {
- _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
- }
- else
- {
- _resize_table(m_nodes.size() + 1);
- }
-
- return true;
- }
-
- bool switch_to_sorted_array()
- {
- if (m_hash_table == NULL) return true;
- _clear_table_memory();
- return sort();
- }
-
- //!If the container reaches the
- bool check_for_switching_to_hashtable()
- {
- if (this->m_hash_table) return true;
-
- if (!(m_nodes.size() < m_min_hash_table_size))
- {
- if (m_node_size == 0)
- {
- m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
- }
-
- _resize_table(m_nodes.size() + 1);
- return true;
- }
- return false;
- }
-
- inline void set_sorted(bool value)
- {
- m_sorted = value;
- }
-
- //! Retrieves the amount of keys.
- inline GUINT size() const
- {
- return m_nodes.size();
- }
-
- //! Retrieves the hash key.
- inline GUINT get_key(GUINT index) const
- {
- return m_nodes[index].m_key;
- }
-
- //! Retrieves the value by index
- /*!
- */
- inline T* get_value_by_index(GUINT index)
- {
- return &m_nodes[index].m_data;
- }
-
- inline const T& operator[](GUINT index) const
- {
- return m_nodes[index].m_data;
- }
-
- inline T& operator[](GUINT index)
- {
- return m_nodes[index].m_data;
- }
-
- //! Finds the index of the element with the key
- /*!
- \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
- If so, the element has been inserted at the last position of the array.
- */
- inline GUINT find(GUINT hashkey)
- {
- if (m_hash_table)
- {
- GUINT cell_index = _find_cell(hashkey);
- if (cell_index == GIM_INVALID_HASH) return GIM_INVALID_HASH;
- return m_hash_table[cell_index];
- }
- GUINT last_index = m_nodes.size();
- if (last_index < 2)
- {
- if (last_index == 0) return GIM_INVALID_HASH;
- if (m_nodes[0].m_key == hashkey) return 0;
- return GIM_INVALID_HASH;
- }
- else if (m_sorted)
- {
- //Binary search
- GUINT result_ind = 0;
- last_index--;
- _node_type* ptr = m_nodes.pointer();
-
- bool found = gim_binary_search_ex(ptr, 0, last_index, result_ind, hashkey, GIM_HASH_NODE_CMP_KEY_MACRO());
-
- if (found) return result_ind;
- }
- return GIM_INVALID_HASH;
- }
-
- //! Retrieves the value associated with the index
- /*!
- \return the found element, or null
- */
- inline T* get_value(GUINT hashkey)
- {
- GUINT index = find(hashkey);
- if (index == GIM_INVALID_HASH) return NULL;
- return &m_nodes[index].m_data;
- }
-
- /*!
- */
- inline bool erase_by_index(GUINT index)
- {
- if (index > m_nodes.size()) return false;
-
- if (m_hash_table == NULL)
- {
- if (is_sorted())
- {
- return this->_erase_sorted(index);
- }
- else
- {
- return this->_erase_unsorted(index);
- }
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
-
- inline bool erase_by_index_unsorted(GUINT index)
- {
- if (index > m_nodes.size()) return false;
-
- if (m_hash_table == NULL)
- {
- return this->_erase_unsorted(index);
- }
- else
- {
- return this->_erase_by_index_hash_table(index);
- }
- return false;
- }
-
- /*!
-
- */
- inline bool erase_by_key(GUINT hashkey)
- {
- if (size() == 0) return false;
-
- if (m_hash_table)
- {
- return this->_erase_hash_table(hashkey);
- }
- //Binary search
-
- if (is_sorted() == false) return false;
-
- GUINT result_ind = find(hashkey);
- if (result_ind != GIM_INVALID_HASH)
- {
- return this->_erase_sorted(result_ind);
- }
- return false;
- }
-
- void clear()
- {
- m_nodes.clear();
-
- if (m_hash_table == NULL) return;
- GUINT datasize = m_table_size * m_node_size;
- //Initialize the hashkeys.
- GUINT i;
- for (i = 0; i < datasize; i++)
- {
- m_hash_table[i] = GIM_INVALID_HASH; // invalidate keys
- }
- m_sorted = false;
- }
-
- //! Insert an element into the hash
- /*!
- \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
- of the existing element.
- */
- inline GUINT insert(GUINT hashkey, const T& element)
- {
- if (m_hash_table)
- {
- return this->_insert_hash_table(hashkey, element);
- }
- if (this->is_sorted())
- {
- return this->_insert_sorted(hashkey, element);
- }
- return this->_insert_unsorted(hashkey, element);
- }
-
- //! Insert an element into the hash, and could overrite an existing object with the same hash.
- /*!
- \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
- of the replaced element.
- */
- inline GUINT insert_override(GUINT hashkey, const T& element)
- {
- if (m_hash_table)
- {
- return this->_insert_hash_table_replace(hashkey, element);
- }
- if (this->is_sorted())
- {
- return this->_insert_sorted_replace(hashkey, element);
- }
- this->_insert_unsorted(hashkey, element);
- return m_nodes.size();
- }
-
- //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
- /*!
- */
- inline GUINT insert_unsorted(GUINT hashkey, const T& element)
- {
- if (m_hash_table)
- {
- return this->_insert_hash_table(hashkey, element);
- }
- return this->_insert_unsorted(hashkey, element);
- }
-};
-
-#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h
deleted file mode 100644
index 98401a404a..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_linear_math.h
+++ /dev/null
@@ -1,1488 +0,0 @@
-#ifndef GIM_LINEAR_H_INCLUDED
-#define GIM_LINEAR_H_INCLUDED
-
-/*! \file gim_linear_math.h
-*\author Francisco Leon Najera
-Type Independant Vector and matrix operations.
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_math.h"
-#include "gim_geom_types.h"
-
-//! Zero out a 2D vector
-#define VEC_ZERO_2(a) \
- { \
- (a)[0] = (a)[1] = 0.0f; \
- }
-
-//! Zero out a 3D vector
-#define VEC_ZERO(a) \
- { \
- (a)[0] = (a)[1] = (a)[2] = 0.0f; \
- }
-
-/// Zero out a 4D vector
-#define VEC_ZERO_4(a) \
- { \
- (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \
- }
-
-/// Vector copy
-#define VEC_COPY_2(b, a) \
- { \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
- }
-
-/// Copy 3D vector
-#define VEC_COPY(b, a) \
- { \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
- (b)[2] = (a)[2]; \
- }
-
-/// Copy 4D vector
-#define VEC_COPY_4(b, a) \
- { \
- (b)[0] = (a)[0]; \
- (b)[1] = (a)[1]; \
- (b)[2] = (a)[2]; \
- (b)[3] = (a)[3]; \
- }
-
-/// VECTOR SWAP
-#define VEC_SWAP(b, a) \
- { \
- GIM_SWAP_NUMBERS((b)[0], (a)[0]); \
- GIM_SWAP_NUMBERS((b)[1], (a)[1]); \
- GIM_SWAP_NUMBERS((b)[2], (a)[2]); \
- }
-
-/// Vector difference
-#define VEC_DIFF_2(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
- }
-
-/// Vector difference
-#define VEC_DIFF(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
- (v21)[2] = (v2)[2] - (v1)[2]; \
- }
-
-/// Vector difference
-#define VEC_DIFF_4(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] - (v1)[0]; \
- (v21)[1] = (v2)[1] - (v1)[1]; \
- (v21)[2] = (v2)[2] - (v1)[2]; \
- (v21)[3] = (v2)[3] - (v1)[3]; \
- }
-
-/// Vector sum
-#define VEC_SUM_2(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
- }
-
-/// Vector sum
-#define VEC_SUM(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
- (v21)[2] = (v2)[2] + (v1)[2]; \
- }
-
-/// Vector sum
-#define VEC_SUM_4(v21, v2, v1) \
- { \
- (v21)[0] = (v2)[0] + (v1)[0]; \
- (v21)[1] = (v2)[1] + (v1)[1]; \
- (v21)[2] = (v2)[2] + (v1)[2]; \
- (v21)[3] = (v2)[3] + (v1)[3]; \
- }
-
-/// scalar times vector
-#define VEC_SCALE_2(c, a, b) \
- { \
- (c)[0] = (a) * (b)[0]; \
- (c)[1] = (a) * (b)[1]; \
- }
-
-/// scalar times vector
-#define VEC_SCALE(c, a, b) \
- { \
- (c)[0] = (a) * (b)[0]; \
- (c)[1] = (a) * (b)[1]; \
- (c)[2] = (a) * (b)[2]; \
- }
-
-/// scalar times vector
-#define VEC_SCALE_4(c, a, b) \
- { \
- (c)[0] = (a) * (b)[0]; \
- (c)[1] = (a) * (b)[1]; \
- (c)[2] = (a) * (b)[2]; \
- (c)[3] = (a) * (b)[3]; \
- }
-
-/// accumulate scaled vector
-#define VEC_ACCUM_2(c, a, b) \
- { \
- (c)[0] += (a) * (b)[0]; \
- (c)[1] += (a) * (b)[1]; \
- }
-
-/// accumulate scaled vector
-#define VEC_ACCUM(c, a, b) \
- { \
- (c)[0] += (a) * (b)[0]; \
- (c)[1] += (a) * (b)[1]; \
- (c)[2] += (a) * (b)[2]; \
- }
-
-/// accumulate scaled vector
-#define VEC_ACCUM_4(c, a, b) \
- { \
- (c)[0] += (a) * (b)[0]; \
- (c)[1] += (a) * (b)[1]; \
- (c)[2] += (a) * (b)[2]; \
- (c)[3] += (a) * (b)[3]; \
- }
-
-/// Vector dot product
-#define VEC_DOT_2(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1])
-
-/// Vector dot product
-#define VEC_DOT(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2])
-
-/// Vector dot product
-#define VEC_DOT_4(a, b) ((a)[0] * (b)[0] + (a)[1] * (b)[1] + (a)[2] * (b)[2] + (a)[3] * (b)[3])
-
-/// vector impact parameter (squared)
-#define VEC_IMPACT_SQ(bsq, direction, position) \
- { \
- GREAL _llel_ = VEC_DOT(direction, position); \
- bsq = VEC_DOT(position, position) - _llel_ * _llel_; \
- }
-
-/// vector impact parameter
-#define VEC_IMPACT(bsq, direction, position) \
- { \
- VEC_IMPACT_SQ(bsq, direction, position); \
- GIM_SQRT(bsq, bsq); \
- }
-
-/// Vector length
-#define VEC_LENGTH_2(a, l) \
- { \
- GREAL _pp = VEC_DOT_2(a, a); \
- GIM_SQRT(_pp, l); \
- }
-
-/// Vector length
-#define VEC_LENGTH(a, l) \
- { \
- GREAL _pp = VEC_DOT(a, a); \
- GIM_SQRT(_pp, l); \
- }
-
-/// Vector length
-#define VEC_LENGTH_4(a, l) \
- { \
- GREAL _pp = VEC_DOT_4(a, a); \
- GIM_SQRT(_pp, l); \
- }
-
-/// Vector inv length
-#define VEC_INV_LENGTH_2(a, l) \
- { \
- GREAL _pp = VEC_DOT_2(a, a); \
- GIM_INV_SQRT(_pp, l); \
- }
-
-/// Vector inv length
-#define VEC_INV_LENGTH(a, l) \
- { \
- GREAL _pp = VEC_DOT(a, a); \
- GIM_INV_SQRT(_pp, l); \
- }
-
-/// Vector inv length
-#define VEC_INV_LENGTH_4(a, l) \
- { \
- GREAL _pp = VEC_DOT_4(a, a); \
- GIM_INV_SQRT(_pp, l); \
- }
-
-/// distance between two points
-#define VEC_DISTANCE(_len, _va, _vb) \
- { \
- vec3f _tmp_; \
- VEC_DIFF(_tmp_, _vb, _va); \
- VEC_LENGTH(_tmp_, _len); \
- }
-
-/// Vector length
-#define VEC_CONJUGATE_LENGTH(a, l) \
- { \
- GREAL _pp = 1.0 - a[0] * a[0] - a[1] * a[1] - a[2] * a[2]; \
- GIM_SQRT(_pp, l); \
- }
-
-/// Vector length
-#define VEC_NORMALIZE(a) \
- { \
- GREAL len; \
- VEC_INV_LENGTH(a, len); \
- if (len < G_REAL_INFINITY) \
- { \
- a[0] *= len; \
- a[1] *= len; \
- a[2] *= len; \
- } \
- }
-
-/// Set Vector size
-#define VEC_RENORMALIZE(a, newlen) \
- { \
- GREAL len; \
- VEC_INV_LENGTH(a, len); \
- if (len < G_REAL_INFINITY) \
- { \
- len *= newlen; \
- a[0] *= len; \
- a[1] *= len; \
- a[2] *= len; \
- } \
- }
-
-/// Vector cross
-#define VEC_CROSS(c, a, b) \
- { \
- c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
- c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
- c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
- }
-
-/*! Vector perp -- assumes that n is of unit length
- * accepts vector v, subtracts out any component parallel to n */
-#define VEC_PERPENDICULAR(vp, v, n) \
- { \
- GREAL dot = VEC_DOT(v, n); \
- vp[0] = (v)[0] - dot * (n)[0]; \
- vp[1] = (v)[1] - dot * (n)[1]; \
- vp[2] = (v)[2] - dot * (n)[2]; \
- }
-
-/*! Vector parallel -- assumes that n is of unit length */
-#define VEC_PARALLEL(vp, v, n) \
- { \
- GREAL dot = VEC_DOT(v, n); \
- vp[0] = (dot) * (n)[0]; \
- vp[1] = (dot) * (n)[1]; \
- vp[2] = (dot) * (n)[2]; \
- }
-
-/*! Same as Vector parallel -- n can have any length
- * accepts vector v, subtracts out any component perpendicular to n */
-#define VEC_PROJECT(vp, v, n) \
- { \
- GREAL scalar = VEC_DOT(v, n); \
- scalar /= VEC_DOT(n, n); \
- vp[0] = (scalar) * (n)[0]; \
- vp[1] = (scalar) * (n)[1]; \
- vp[2] = (scalar) * (n)[2]; \
- }
-
-/*! accepts vector v*/
-#define VEC_UNPROJECT(vp, v, n) \
- { \
- GREAL scalar = VEC_DOT(v, n); \
- scalar = VEC_DOT(n, n) / scalar; \
- vp[0] = (scalar) * (n)[0]; \
- vp[1] = (scalar) * (n)[1]; \
- vp[2] = (scalar) * (n)[2]; \
- }
-
-/*! Vector reflection -- assumes n is of unit length
- Takes vector v, reflects it against reflector n, and returns vr */
-#define VEC_REFLECT(vr, v, n) \
- { \
- GREAL dot = VEC_DOT(v, n); \
- vr[0] = (v)[0] - 2.0 * (dot) * (n)[0]; \
- vr[1] = (v)[1] - 2.0 * (dot) * (n)[1]; \
- vr[2] = (v)[2] - 2.0 * (dot) * (n)[2]; \
- }
-
-/*! Vector blending
-Takes two vectors a, b, blends them together with two scalars */
-#define VEC_BLEND_AB(vr, sa, a, sb, b) \
- { \
- vr[0] = (sa) * (a)[0] + (sb) * (b)[0]; \
- vr[1] = (sa) * (a)[1] + (sb) * (b)[1]; \
- vr[2] = (sa) * (a)[2] + (sb) * (b)[2]; \
- }
-
-/*! Vector blending
-Takes two vectors a, b, blends them together with s <=1 */
-#define VEC_BLEND(vr, a, b, s) VEC_BLEND_AB(vr, (1 - s), a, s, b)
-
-#define VEC_SET3(a, b, op, c) \
- a[0] = b[0] op c[0]; \
- a[1] = b[1] op c[1]; \
- a[2] = b[2] op c[2];
-
-//! Finds the bigger cartesian coordinate from a vector
-#define VEC_MAYOR_COORD(vec, maxc) \
- { \
- GREAL A[] = {fabs(vec[0]), fabs(vec[1]), fabs(vec[2])}; \
- maxc = A[0] > A[1] ? (A[0] > A[2] ? 0 : 2) : (A[1] > A[2] ? 1 : 2); \
- }
-
-//! Finds the 2 smallest cartesian coordinates from a vector
-#define VEC_MINOR_AXES(vec, i0, i1) \
- { \
- VEC_MAYOR_COORD(vec, i0); \
- i0 = (i0 + 1) % 3; \
- i1 = (i0 + 1) % 3; \
- }
-
-#define VEC_EQUAL(v1, v2) (v1[0] == v2[0] && v1[1] == v2[1] && v1[2] == v2[2])
-
-#define VEC_NEAR_EQUAL(v1, v2) (GIM_NEAR_EQUAL(v1[0], v2[0]) && GIM_NEAR_EQUAL(v1[1], v2[1]) && GIM_NEAR_EQUAL(v1[2], v2[2]))
-
-/// Vector cross
-#define X_AXIS_CROSS_VEC(dst, src) \
- { \
- dst[0] = 0.0f; \
- dst[1] = -src[2]; \
- dst[2] = src[1]; \
- }
-
-#define Y_AXIS_CROSS_VEC(dst, src) \
- { \
- dst[0] = src[2]; \
- dst[1] = 0.0f; \
- dst[2] = -src[0]; \
- }
-
-#define Z_AXIS_CROSS_VEC(dst, src) \
- { \
- dst[0] = -src[1]; \
- dst[1] = src[0]; \
- dst[2] = 0.0f; \
- }
-
-/// initialize matrix
-#define IDENTIFY_MATRIX_3X3(m) \
- { \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
- }
-
-/*! initialize matrix */
-#define IDENTIFY_MATRIX_4X4(m) \
- { \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
- }
-
-/*! initialize matrix */
-#define ZERO_MATRIX_4X4(m) \
- { \
- m[0][0] = 0.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 0.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 0.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 0.0; \
- }
-
-/*! matrix rotation X */
-#define ROTX_CS(m, cosine, sine) \
- { \
- /* rotation about the x-axis */ \
- \
- m[0][0] = 1.0; \
- m[0][1] = 0.0; \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = (cosine); \
- m[1][2] = (sine); \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = -(sine); \
- m[2][2] = (cosine); \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
- }
-
-/*! matrix rotation Y */
-#define ROTY_CS(m, cosine, sine) \
- { \
- /* rotation about the y-axis */ \
- \
- m[0][0] = (cosine); \
- m[0][1] = 0.0; \
- m[0][2] = -(sine); \
- m[0][3] = 0.0; \
- \
- m[1][0] = 0.0; \
- m[1][1] = 1.0; \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = (sine); \
- m[2][1] = 0.0; \
- m[2][2] = (cosine); \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
- }
-
-/*! matrix rotation Z */
-#define ROTZ_CS(m, cosine, sine) \
- { \
- /* rotation about the z-axis */ \
- \
- m[0][0] = (cosine); \
- m[0][1] = (sine); \
- m[0][2] = 0.0; \
- m[0][3] = 0.0; \
- \
- m[1][0] = -(sine); \
- m[1][1] = (cosine); \
- m[1][2] = 0.0; \
- m[1][3] = 0.0; \
- \
- m[2][0] = 0.0; \
- m[2][1] = 0.0; \
- m[2][2] = 1.0; \
- m[2][3] = 0.0; \
- \
- m[3][0] = 0.0; \
- m[3][1] = 0.0; \
- m[3][2] = 0.0; \
- m[3][3] = 1.0; \
- }
-
-/*! matrix copy */
-#define COPY_MATRIX_2X2(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- }
-
-/*! matrix copy */
-#define COPY_MATRIX_2X3(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
- }
-
-/*! matrix copy */
-#define COPY_MATRIX_3X3(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
- \
- b[2][0] = a[2][0]; \
- b[2][1] = a[2][1]; \
- b[2][2] = a[2][2]; \
- }
-
-/*! matrix copy */
-#define COPY_MATRIX_4X4(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[0][1]; \
- b[0][2] = a[0][2]; \
- b[0][3] = a[0][3]; \
- \
- b[1][0] = a[1][0]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[1][2]; \
- b[1][3] = a[1][3]; \
- \
- b[2][0] = a[2][0]; \
- b[2][1] = a[2][1]; \
- b[2][2] = a[2][2]; \
- b[2][3] = a[2][3]; \
- \
- b[3][0] = a[3][0]; \
- b[3][1] = a[3][1]; \
- b[3][2] = a[3][2]; \
- b[3][3] = a[3][3]; \
- }
-
-/*! matrix transpose */
-#define TRANSPOSE_MATRIX_2X2(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
- }
-
-/*! matrix transpose */
-#define TRANSPOSE_MATRIX_3X3(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- b[0][2] = a[2][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[2][1]; \
- \
- b[2][0] = a[0][2]; \
- b[2][1] = a[1][2]; \
- b[2][2] = a[2][2]; \
- }
-
-/*! matrix transpose */
-#define TRANSPOSE_MATRIX_4X4(b, a) \
- { \
- b[0][0] = a[0][0]; \
- b[0][1] = a[1][0]; \
- b[0][2] = a[2][0]; \
- b[0][3] = a[3][0]; \
- \
- b[1][0] = a[0][1]; \
- b[1][1] = a[1][1]; \
- b[1][2] = a[2][1]; \
- b[1][3] = a[3][1]; \
- \
- b[2][0] = a[0][2]; \
- b[2][1] = a[1][2]; \
- b[2][2] = a[2][2]; \
- b[2][3] = a[3][2]; \
- \
- b[3][0] = a[0][3]; \
- b[3][1] = a[1][3]; \
- b[3][2] = a[2][3]; \
- b[3][3] = a[3][3]; \
- }
-
-/*! multiply matrix by scalar */
-#define SCALE_MATRIX_2X2(b, s, a) \
- { \
- b[0][0] = (s)*a[0][0]; \
- b[0][1] = (s)*a[0][1]; \
- \
- b[1][0] = (s)*a[1][0]; \
- b[1][1] = (s)*a[1][1]; \
- }
-
-/*! multiply matrix by scalar */
-#define SCALE_MATRIX_3X3(b, s, a) \
- { \
- b[0][0] = (s)*a[0][0]; \
- b[0][1] = (s)*a[0][1]; \
- b[0][2] = (s)*a[0][2]; \
- \
- b[1][0] = (s)*a[1][0]; \
- b[1][1] = (s)*a[1][1]; \
- b[1][2] = (s)*a[1][2]; \
- \
- b[2][0] = (s)*a[2][0]; \
- b[2][1] = (s)*a[2][1]; \
- b[2][2] = (s)*a[2][2]; \
- }
-
-/*! multiply matrix by scalar */
-#define SCALE_MATRIX_4X4(b, s, a) \
- { \
- b[0][0] = (s)*a[0][0]; \
- b[0][1] = (s)*a[0][1]; \
- b[0][2] = (s)*a[0][2]; \
- b[0][3] = (s)*a[0][3]; \
- \
- b[1][0] = (s)*a[1][0]; \
- b[1][1] = (s)*a[1][1]; \
- b[1][2] = (s)*a[1][2]; \
- b[1][3] = (s)*a[1][3]; \
- \
- b[2][0] = (s)*a[2][0]; \
- b[2][1] = (s)*a[2][1]; \
- b[2][2] = (s)*a[2][2]; \
- b[2][3] = (s)*a[2][3]; \
- \
- b[3][0] = s * a[3][0]; \
- b[3][1] = s * a[3][1]; \
- b[3][2] = s * a[3][2]; \
- b[3][3] = s * a[3][3]; \
- }
-
-/*! multiply matrix by scalar */
-#define SCALE_VEC_MATRIX_2X2(b, svec, a) \
- { \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
- }
-
-/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */
-#define SCALE_VEC_MATRIX_3X3(b, svec, a) \
- { \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- b[2][0] = svec[0] * a[2][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
- b[2][1] = svec[1] * a[2][1]; \
- \
- b[0][2] = svec[2] * a[0][2]; \
- b[1][2] = svec[2] * a[1][2]; \
- b[2][2] = svec[2] * a[2][2]; \
- }
-
-/*! multiply matrix by scalar */
-#define SCALE_VEC_MATRIX_4X4(b, svec, a) \
- { \
- b[0][0] = svec[0] * a[0][0]; \
- b[1][0] = svec[0] * a[1][0]; \
- b[2][0] = svec[0] * a[2][0]; \
- b[3][0] = svec[0] * a[3][0]; \
- \
- b[0][1] = svec[1] * a[0][1]; \
- b[1][1] = svec[1] * a[1][1]; \
- b[2][1] = svec[1] * a[2][1]; \
- b[3][1] = svec[1] * a[3][1]; \
- \
- b[0][2] = svec[2] * a[0][2]; \
- b[1][2] = svec[2] * a[1][2]; \
- b[2][2] = svec[2] * a[2][2]; \
- b[3][2] = svec[2] * a[3][2]; \
- \
- b[0][3] = svec[3] * a[0][3]; \
- b[1][3] = svec[3] * a[1][3]; \
- b[2][3] = svec[3] * a[2][3]; \
- b[3][3] = svec[3] * a[3][3]; \
- }
-
-/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_2X2(b, s, a) \
- { \
- b[0][0] += (s)*a[0][0]; \
- b[0][1] += (s)*a[0][1]; \
- \
- b[1][0] += (s)*a[1][0]; \
- b[1][1] += (s)*a[1][1]; \
- }
-
-/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_3X3(b, s, a) \
- { \
- b[0][0] += (s)*a[0][0]; \
- b[0][1] += (s)*a[0][1]; \
- b[0][2] += (s)*a[0][2]; \
- \
- b[1][0] += (s)*a[1][0]; \
- b[1][1] += (s)*a[1][1]; \
- b[1][2] += (s)*a[1][2]; \
- \
- b[2][0] += (s)*a[2][0]; \
- b[2][1] += (s)*a[2][1]; \
- b[2][2] += (s)*a[2][2]; \
- }
-
-/*! multiply matrix by scalar */
-#define ACCUM_SCALE_MATRIX_4X4(b, s, a) \
- { \
- b[0][0] += (s)*a[0][0]; \
- b[0][1] += (s)*a[0][1]; \
- b[0][2] += (s)*a[0][2]; \
- b[0][3] += (s)*a[0][3]; \
- \
- b[1][0] += (s)*a[1][0]; \
- b[1][1] += (s)*a[1][1]; \
- b[1][2] += (s)*a[1][2]; \
- b[1][3] += (s)*a[1][3]; \
- \
- b[2][0] += (s)*a[2][0]; \
- b[2][1] += (s)*a[2][1]; \
- b[2][2] += (s)*a[2][2]; \
- b[2][3] += (s)*a[2][3]; \
- \
- b[3][0] += (s)*a[3][0]; \
- b[3][1] += (s)*a[3][1]; \
- b[3][2] += (s)*a[3][2]; \
- b[3][3] += (s)*a[3][3]; \
- }
-
-/*! matrix product */
-/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_2X2(c, a, b) \
- { \
- c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0]; \
- c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1]; \
- \
- c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0]; \
- c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1]; \
- }
-
-/*! matrix product */
-/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_3X3(c, a, b) \
- { \
- c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0]; \
- c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1]; \
- c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2]; \
- \
- c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0]; \
- c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1]; \
- c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2]; \
- \
- c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0]; \
- c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1]; \
- c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2]; \
- }
-
-/*! matrix product */
-/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
-#define MATRIX_PRODUCT_4X4(c, a, b) \
- { \
- c[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0] + a[0][2] * b[2][0] + a[0][3] * b[3][0]; \
- c[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1] + a[0][2] * b[2][1] + a[0][3] * b[3][1]; \
- c[0][2] = a[0][0] * b[0][2] + a[0][1] * b[1][2] + a[0][2] * b[2][2] + a[0][3] * b[3][2]; \
- c[0][3] = a[0][0] * b[0][3] + a[0][1] * b[1][3] + a[0][2] * b[2][3] + a[0][3] * b[3][3]; \
- \
- c[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0] + a[1][2] * b[2][0] + a[1][3] * b[3][0]; \
- c[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1] + a[1][2] * b[2][1] + a[1][3] * b[3][1]; \
- c[1][2] = a[1][0] * b[0][2] + a[1][1] * b[1][2] + a[1][2] * b[2][2] + a[1][3] * b[3][2]; \
- c[1][3] = a[1][0] * b[0][3] + a[1][1] * b[1][3] + a[1][2] * b[2][3] + a[1][3] * b[3][3]; \
- \
- c[2][0] = a[2][0] * b[0][0] + a[2][1] * b[1][0] + a[2][2] * b[2][0] + a[2][3] * b[3][0]; \
- c[2][1] = a[2][0] * b[0][1] + a[2][1] * b[1][1] + a[2][2] * b[2][1] + a[2][3] * b[3][1]; \
- c[2][2] = a[2][0] * b[0][2] + a[2][1] * b[1][2] + a[2][2] * b[2][2] + a[2][3] * b[3][2]; \
- c[2][3] = a[2][0] * b[0][3] + a[2][1] * b[1][3] + a[2][2] * b[2][3] + a[2][3] * b[3][3]; \
- \
- c[3][0] = a[3][0] * b[0][0] + a[3][1] * b[1][0] + a[3][2] * b[2][0] + a[3][3] * b[3][0]; \
- c[3][1] = a[3][0] * b[0][1] + a[3][1] * b[1][1] + a[3][2] * b[2][1] + a[3][3] * b[3][1]; \
- c[3][2] = a[3][0] * b[0][2] + a[3][1] * b[1][2] + a[3][2] * b[2][2] + a[3][3] * b[3][2]; \
- c[3][3] = a[3][0] * b[0][3] + a[3][1] * b[1][3] + a[3][2] * b[2][3] + a[3][3] * b[3][3]; \
- }
-
-/*! matrix times vector */
-#define MAT_DOT_VEC_2X2(p, m, v) \
- { \
- p[0] = m[0][0] * v[0] + m[0][1] * v[1]; \
- p[1] = m[1][0] * v[0] + m[1][1] * v[1]; \
- }
-
-/*! matrix times vector */
-#define MAT_DOT_VEC_3X3(p, m, v) \
- { \
- p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2]; \
- p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2]; \
- p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2]; \
- }
-
-/*! matrix times vector
-v is a vec4f
-*/
-#define MAT_DOT_VEC_4X4(p, m, v) \
- { \
- p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3]; \
- p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3]; \
- p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3]; \
- p[3] = m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]; \
- }
-
-/*! matrix times vector
-v is a vec3f
-and m is a mat4f<br>
-Last column is added as the position
-*/
-#define MAT_DOT_VEC_3X4(p, m, v) \
- { \
- p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3]; \
- p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3]; \
- p[2] = m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3]; \
- }
-
-/*! vector transpose times matrix */
-/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
-#define VEC_DOT_MAT_3X3(p, v, m) \
- { \
- p[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0]; \
- p[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1]; \
- p[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2]; \
- }
-
-/*! affine matrix times vector */
-/** The matrix is assumed to be an affine matrix, with last two
- * entries representing a translation */
-#define MAT_DOT_VEC_2X3(p, m, v) \
- { \
- p[0] = m[0][0] * v[0] + m[0][1] * v[1] + m[0][2]; \
- p[1] = m[1][0] * v[0] + m[1][1] * v[1] + m[1][2]; \
- }
-
-//! Transform a plane
-#define MAT_TRANSFORM_PLANE_4X4(pout, m, plane) \
- { \
- pout[0] = m[0][0] * plane[0] + m[0][1] * plane[1] + m[0][2] * plane[2]; \
- pout[1] = m[1][0] * plane[0] + m[1][1] * plane[1] + m[1][2] * plane[2]; \
- pout[2] = m[2][0] * plane[0] + m[2][1] * plane[1] + m[2][2] * plane[2]; \
- pout[3] = m[0][3] * pout[0] + m[1][3] * pout[1] + m[2][3] * pout[2] + plane[3]; \
- }
-
-/** inverse transpose of matrix times vector
- *
- * This macro computes inverse transpose of matrix m,
- * and multiplies vector v into it, to yeild vector p
- *
- * DANGER !!! Do Not use this on normal vectors!!!
- * It will leave normals the wrong length !!!
- * See macro below for use on normals.
- */
-#define INV_TRANSP_MAT_DOT_VEC_2X2(p, m, v) \
- { \
- GREAL det; \
- \
- det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
- p[0] = m[1][1] * v[0] - m[1][0] * v[1]; \
- p[1] = -m[0][1] * v[0] + m[0][0] * v[1]; \
- \
- /* if matrix not singular, and not orthonormal, then renormalize */ \
- if ((det != 1.0f) && (det != 0.0f)) \
- { \
- det = 1.0f / det; \
- p[0] *= det; \
- p[1] *= det; \
- } \
- }
-
-/** transform normal vector by inverse transpose of matrix
- * and then renormalize the vector
- *
- * This macro computes inverse transpose of matrix m,
- * and multiplies vector v into it, to yeild vector p
- * Vector p is then normalized.
- */
-#define NORM_XFORM_2X2(p, m, v) \
- { \
- GREAL len; \
- \
- /* do nothing if off-diagonals are zero and diagonals are \
- * equal */ \
- if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) \
- { \
- p[0] = m[1][1] * v[0] - m[1][0] * v[1]; \
- p[1] = -m[0][1] * v[0] + m[0][0] * v[1]; \
- \
- len = p[0] * p[0] + p[1] * p[1]; \
- GIM_INV_SQRT(len, len); \
- p[0] *= len; \
- p[1] *= len; \
- } \
- else \
- { \
- VEC_COPY_2(p, v); \
- } \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define OUTER_PRODUCT_2X2(m, v, t) \
- { \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define OUTER_PRODUCT_3X3(m, v, t) \
- { \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- m[0][2] = v[0] * t[2]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
- m[1][2] = v[1] * t[2]; \
- \
- m[2][0] = v[2] * t[0]; \
- m[2][1] = v[2] * t[1]; \
- m[2][2] = v[2] * t[2]; \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define OUTER_PRODUCT_4X4(m, v, t) \
- { \
- m[0][0] = v[0] * t[0]; \
- m[0][1] = v[0] * t[1]; \
- m[0][2] = v[0] * t[2]; \
- m[0][3] = v[0] * t[3]; \
- \
- m[1][0] = v[1] * t[0]; \
- m[1][1] = v[1] * t[1]; \
- m[1][2] = v[1] * t[2]; \
- m[1][3] = v[1] * t[3]; \
- \
- m[2][0] = v[2] * t[0]; \
- m[2][1] = v[2] * t[1]; \
- m[2][2] = v[2] * t[2]; \
- m[2][3] = v[2] * t[3]; \
- \
- m[3][0] = v[3] * t[0]; \
- m[3][1] = v[3] * t[1]; \
- m[3][2] = v[3] * t[2]; \
- m[3][3] = v[3] * t[3]; \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define ACCUM_OUTER_PRODUCT_2X2(m, v, t) \
- { \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define ACCUM_OUTER_PRODUCT_3X3(m, v, t) \
- { \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- m[0][2] += v[0] * t[2]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
- m[1][2] += v[1] * t[2]; \
- \
- m[2][0] += v[2] * t[0]; \
- m[2][1] += v[2] * t[1]; \
- m[2][2] += v[2] * t[2]; \
- }
-
-/** outer product of vector times vector transpose
- *
- * The outer product of vector v and vector transpose t yeilds
- * dyadic matrix m.
- */
-#define ACCUM_OUTER_PRODUCT_4X4(m, v, t) \
- { \
- m[0][0] += v[0] * t[0]; \
- m[0][1] += v[0] * t[1]; \
- m[0][2] += v[0] * t[2]; \
- m[0][3] += v[0] * t[3]; \
- \
- m[1][0] += v[1] * t[0]; \
- m[1][1] += v[1] * t[1]; \
- m[1][2] += v[1] * t[2]; \
- m[1][3] += v[1] * t[3]; \
- \
- m[2][0] += v[2] * t[0]; \
- m[2][1] += v[2] * t[1]; \
- m[2][2] += v[2] * t[2]; \
- m[2][3] += v[2] * t[3]; \
- \
- m[3][0] += v[3] * t[0]; \
- m[3][1] += v[3] * t[1]; \
- m[3][2] += v[3] * t[2]; \
- m[3][3] += v[3] * t[3]; \
- }
-
-/** determinant of matrix
- *
- * Computes determinant of matrix m, returning d
- */
-#define DETERMINANT_2X2(d, m) \
- { \
- d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \
- }
-
-/** determinant of matrix
- *
- * Computes determinant of matrix m, returning d
- */
-#define DETERMINANT_3X3(d, m) \
- { \
- d = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
- d -= m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]); \
- d += m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
- }
-
-/** i,j,th cofactor of a 4x4 matrix
- *
- */
-#define COFACTOR_4X4_IJ(fac, m, i, j) \
- { \
- GUINT __ii[4], __jj[4], __k; \
- \
- for (__k = 0; __k < i; __k++) __ii[__k] = __k; \
- for (__k = i; __k < 3; __k++) __ii[__k] = __k + 1; \
- for (__k = 0; __k < j; __k++) __jj[__k] = __k; \
- for (__k = j; __k < 3; __k++) __jj[__k] = __k + 1; \
- \
- (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[1]]); \
- (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[2]] - m[__ii[1]][__jj[2]] * m[__ii[2]][__jj[0]]); \
- (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]] * m[__ii[2]][__jj[1]] - m[__ii[1]][__jj[1]] * m[__ii[2]][__jj[0]]); \
- \
- __k = i + j; \
- if (__k != (__k / 2) * 2) \
- { \
- (fac) = -(fac); \
- } \
- }
-
-/** determinant of matrix
- *
- * Computes determinant of matrix m, returning d
- */
-#define DETERMINANT_4X4(d, m) \
- { \
- GREAL cofac; \
- COFACTOR_4X4_IJ(cofac, m, 0, 0); \
- d = m[0][0] * cofac; \
- COFACTOR_4X4_IJ(cofac, m, 0, 1); \
- d += m[0][1] * cofac; \
- COFACTOR_4X4_IJ(cofac, m, 0, 2); \
- d += m[0][2] * cofac; \
- COFACTOR_4X4_IJ(cofac, m, 0, 3); \
- d += m[0][3] * cofac; \
- }
-
-/** cofactor of matrix
- *
- * Computes cofactor of matrix m, returning a
- */
-#define COFACTOR_2X2(a, m) \
- { \
- a[0][0] = (m)[1][1]; \
- a[0][1] = -(m)[1][0]; \
- a[1][0] = -(m)[0][1]; \
- a[1][1] = (m)[0][0]; \
- }
-
-/** cofactor of matrix
- *
- * Computes cofactor of matrix m, returning a
- */
-#define COFACTOR_3X3(a, m) \
- { \
- a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; \
- a[0][1] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
- a[0][2] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; \
- a[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
- a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; \
- a[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
- a[2][0] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; \
- a[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
- a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
- }
-
-/** cofactor of matrix
- *
- * Computes cofactor of matrix m, returning a
- */
-#define COFACTOR_4X4(a, m) \
- { \
- int i, j; \
- \
- for (i = 0; i < 4; i++) \
- { \
- for (j = 0; j < 4; j++) \
- { \
- COFACTOR_4X4_IJ(a[i][j], m, i, j); \
- } \
- } \
- }
-
-/** adjoint of matrix
- *
- * Computes adjoint of matrix m, returning a
- * (Note that adjoint is just the transpose of the cofactor matrix)
- */
-#define ADJOINT_2X2(a, m) \
- { \
- a[0][0] = (m)[1][1]; \
- a[1][0] = -(m)[1][0]; \
- a[0][1] = -(m)[0][1]; \
- a[1][1] = (m)[0][0]; \
- }
-
-/** adjoint of matrix
- *
- * Computes adjoint of matrix m, returning a
- * (Note that adjoint is just the transpose of the cofactor matrix)
- */
-#define ADJOINT_3X3(a, m) \
- { \
- a[0][0] = m[1][1] * m[2][2] - m[1][2] * m[2][1]; \
- a[1][0] = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]); \
- a[2][0] = m[1][0] * m[2][1] - m[1][1] * m[2][0]; \
- a[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); \
- a[1][1] = m[0][0] * m[2][2] - m[0][2] * m[2][0]; \
- a[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); \
- a[0][2] = m[0][1] * m[1][2] - m[0][2] * m[1][1]; \
- a[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); \
- a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]); \
- }
-
-/** adjoint of matrix
- *
- * Computes adjoint of matrix m, returning a
- * (Note that adjoint is just the transpose of the cofactor matrix)
- */
-#define ADJOINT_4X4(a, m) \
- { \
- char _i_, _j_; \
- \
- for (_i_ = 0; _i_ < 4; _i_++) \
- { \
- for (_j_ = 0; _j_ < 4; _j_++) \
- { \
- COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
- } \
- } \
- }
-
-/** compute adjoint of matrix and scale
- *
- * Computes adjoint of matrix m, scales it by s, returning a
- */
-#define SCALE_ADJOINT_2X2(a, s, m) \
- { \
- a[0][0] = (s)*m[1][1]; \
- a[1][0] = -(s)*m[1][0]; \
- a[0][1] = -(s)*m[0][1]; \
- a[1][1] = (s)*m[0][0]; \
- }
-
-/** compute adjoint of matrix and scale
- *
- * Computes adjoint of matrix m, scales it by s, returning a
- */
-#define SCALE_ADJOINT_3X3(a, s, m) \
- { \
- a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]); \
- a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]); \
- a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); \
- \
- a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]); \
- a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]); \
- a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]); \
- \
- a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]); \
- a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]); \
- a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]); \
- }
-
-/** compute adjoint of matrix and scale
- *
- * Computes adjoint of matrix m, scales it by s, returning a
- */
-#define SCALE_ADJOINT_4X4(a, s, m) \
- { \
- char _i_, _j_; \
- for (_i_ = 0; _i_ < 4; _i_++) \
- { \
- for (_j_ = 0; _j_ < 4; _j_++) \
- { \
- COFACTOR_4X4_IJ(a[_j_][_i_], m, _i_, _j_); \
- a[_j_][_i_] *= s; \
- } \
- } \
- }
-
-/** inverse of matrix
- *
- * Compute inverse of matrix a, returning determinant m and
- * inverse b
- */
-#define INVERT_2X2(b, det, a) \
- { \
- GREAL _tmp_; \
- DETERMINANT_2X2(det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_2X2(b, _tmp_, a); \
- }
-
-/** inverse of matrix
- *
- * Compute inverse of matrix a, returning determinant m and
- * inverse b
- */
-#define INVERT_3X3(b, det, a) \
- { \
- GREAL _tmp_; \
- DETERMINANT_3X3(det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_3X3(b, _tmp_, a); \
- }
-
-/** inverse of matrix
- *
- * Compute inverse of matrix a, returning determinant m and
- * inverse b
- */
-#define INVERT_4X4(b, det, a) \
- { \
- GREAL _tmp_; \
- DETERMINANT_4X4(det, a); \
- _tmp_ = 1.0 / (det); \
- SCALE_ADJOINT_4X4(b, _tmp_, a); \
- }
-
-//! Get the triple(3) row of a transform matrix
-#define MAT_GET_ROW(mat, vec3, rowindex) \
- { \
- vec3[0] = mat[rowindex][0]; \
- vec3[1] = mat[rowindex][1]; \
- vec3[2] = mat[rowindex][2]; \
- }
-
-//! Get the tuple(2) row of a transform matrix
-#define MAT_GET_ROW2(mat, vec2, rowindex) \
- { \
- vec2[0] = mat[rowindex][0]; \
- vec2[1] = mat[rowindex][1]; \
- }
-
-//! Get the quad (4) row of a transform matrix
-#define MAT_GET_ROW4(mat, vec4, rowindex) \
- { \
- vec4[0] = mat[rowindex][0]; \
- vec4[1] = mat[rowindex][1]; \
- vec4[2] = mat[rowindex][2]; \
- vec4[3] = mat[rowindex][3]; \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_GET_COL(mat, vec3, colindex) \
- { \
- vec3[0] = mat[0][colindex]; \
- vec3[1] = mat[1][colindex]; \
- vec3[2] = mat[2][colindex]; \
- }
-
-//! Get the tuple(2) col of a transform matrix
-#define MAT_GET_COL2(mat, vec2, colindex) \
- { \
- vec2[0] = mat[0][colindex]; \
- vec2[1] = mat[1][colindex]; \
- }
-
-//! Get the quad (4) col of a transform matrix
-#define MAT_GET_COL4(mat, vec4, colindex) \
- { \
- vec4[0] = mat[0][colindex]; \
- vec4[1] = mat[1][colindex]; \
- vec4[2] = mat[2][colindex]; \
- vec4[3] = mat[3][colindex]; \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_GET_X(mat, vec3) \
- { \
- MAT_GET_COL(mat, vec3, 0); \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_GET_Y(mat, vec3) \
- { \
- MAT_GET_COL(mat, vec3, 1); \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_GET_Z(mat, vec3) \
- { \
- MAT_GET_COL(mat, vec3, 2); \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_SET_X(mat, vec3) \
- { \
- mat[0][0] = vec3[0]; \
- mat[1][0] = vec3[1]; \
- mat[2][0] = vec3[2]; \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_SET_Y(mat, vec3) \
- { \
- mat[0][1] = vec3[0]; \
- mat[1][1] = vec3[1]; \
- mat[2][1] = vec3[2]; \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_SET_Z(mat, vec3) \
- { \
- mat[0][2] = vec3[0]; \
- mat[1][2] = vec3[1]; \
- mat[2][2] = vec3[2]; \
- }
-
-//! Get the triple(3) col of a transform matrix
-#define MAT_GET_TRANSLATION(mat, vec3) \
- { \
- vec3[0] = mat[0][3]; \
- vec3[1] = mat[1][3]; \
- vec3[2] = mat[2][3]; \
- }
-
-//! Set the triple(3) col of a transform matrix
-#define MAT_SET_TRANSLATION(mat, vec3) \
- { \
- mat[0][3] = vec3[0]; \
- mat[1][3] = vec3[1]; \
- mat[2][3] = vec3[2]; \
- }
-
-//! Returns the dot product between a vec3f and the row of a matrix
-#define MAT_DOT_ROW(mat, vec3, rowindex) (vec3[0] * mat[rowindex][0] + vec3[1] * mat[rowindex][1] + vec3[2] * mat[rowindex][2])
-
-//! Returns the dot product between a vec2f and the row of a matrix
-#define MAT_DOT_ROW2(mat, vec2, rowindex) (vec2[0] * mat[rowindex][0] + vec2[1] * mat[rowindex][1])
-
-//! Returns the dot product between a vec4f and the row of a matrix
-#define MAT_DOT_ROW4(mat, vec4, rowindex) (vec4[0] * mat[rowindex][0] + vec4[1] * mat[rowindex][1] + vec4[2] * mat[rowindex][2] + vec4[3] * mat[rowindex][3])
-
-//! Returns the dot product between a vec3f and the col of a matrix
-#define MAT_DOT_COL(mat, vec3, colindex) (vec3[0] * mat[0][colindex] + vec3[1] * mat[1][colindex] + vec3[2] * mat[2][colindex])
-
-//! Returns the dot product between a vec2f and the col of a matrix
-#define MAT_DOT_COL2(mat, vec2, colindex) (vec2[0] * mat[0][colindex] + vec2[1] * mat[1][colindex])
-
-//! Returns the dot product between a vec4f and the col of a matrix
-#define MAT_DOT_COL4(mat, vec4, colindex) (vec4[0] * mat[0][colindex] + vec4[1] * mat[1][colindex] + vec4[2] * mat[2][colindex] + vec4[3] * mat[3][colindex])
-
-/*!Transpose matrix times vector
-v is a vec3f
-and m is a mat4f<br>
-*/
-#define INV_MAT_DOT_VEC_3X3(p, m, v) \
- { \
- p[0] = MAT_DOT_COL(m, v, 0); \
- p[1] = MAT_DOT_COL(m, v, 1); \
- p[2] = MAT_DOT_COL(m, v, 2); \
- }
-
-#endif // GIM_VECTOR_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h
deleted file mode 100644
index 3c4f821a72..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_math.h
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef GIM_MATH_H_INCLUDED
-#define GIM_MATH_H_INCLUDED
-/*! \file gim_math.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "LinearMath/btScalar.h"
-
-#define GREAL btScalar
-#define GREAL2 double
-#define GINT int
-#define GUINT unsigned int
-#define GSHORT short
-#define GUSHORT unsigned short
-#define GINT64 long long
-#define GUINT64 unsigned long long
-
-#define G_PI 3.14159265358979f
-#define G_HALF_PI 1.5707963f
-//267948966
-#define G_TWO_PI 6.28318530f
-//71795864
-#define G_ROOT3 1.73205f
-#define G_ROOT2 1.41421f
-#define G_UINT_INFINITY 0xffffffff //!< A very very high value
-#define G_REAL_INFINITY FLT_MAX
-#define G_SIGN_BITMASK 0x80000000
-#define G_EPSILON SIMD_EPSILON
-
-enum GIM_SCALAR_TYPES
-{
- G_STYPE_REAL = 0,
- G_STYPE_REAL2,
- G_STYPE_SHORT,
- G_STYPE_USHORT,
- G_STYPE_INT,
- G_STYPE_UINT,
- G_STYPE_INT64,
- G_STYPE_UINT64
-};
-
-#define G_DEGTORAD(X) ((X)*3.1415926f / 180.0f)
-#define G_RADTODEG(X) ((X)*180.0f / 3.1415926f)
-
-//! Integer representation of a floating-point value.
-#define GIM_IR(x) ((GUINT&)(x))
-
-//! Signed integer representation of a floating-point value.
-#define GIM_SIR(x) ((GINT&)(x))
-
-//! Absolute integer representation of a floating-point value
-#define GIM_AIR(x) (GIM_IR(x) & 0x7fffffff)
-
-//! Floating-point representation of an integer value.
-#define GIM_FR(x) ((GREAL&)(x))
-
-#define GIM_MAX(a, b) (a < b ? b : a)
-#define GIM_MIN(a, b) (a > b ? b : a)
-
-#define GIM_MAX3(a, b, c) GIM_MAX(a, GIM_MAX(b, c))
-#define GIM_MIN3(a, b, c) GIM_MIN(a, GIM_MIN(b, c))
-
-#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON)
-
-#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
-
-#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
-
-#define GIM_NEAR_EQUAL(v1, v2) GIM_IS_ZERO((v1 - v2))
-
-///returns a clamped number
-#define GIM_CLAMP(number, minval, maxval) (number < minval ? minval : (number > maxval ? maxval : number))
-
-#define GIM_GREATER(x, y) btFabs(x) > (y)
-
-///Swap numbers
-#define GIM_SWAP_NUMBERS(a, b) \
- { \
- a = a + b; \
- b = a - b; \
- a = a - b; \
- }
-
-#define GIM_INV_SQRT(va, isva) \
- { \
- if (va <= 0.0000001f) \
- { \
- isva = G_REAL_INFINITY; \
- } \
- else \
- { \
- GREAL _x = va * 0.5f; \
- GUINT _y = 0x5f3759df - (GIM_IR(va) >> 1); \
- isva = GIM_FR(_y); \
- isva = isva * (1.5f - (_x * isva * isva)); \
- } \
- }
-
-#define GIM_SQRT(va, sva) \
- { \
- GIM_INV_SQRT(va, sva); \
- sva = 1.0f / sva; \
- }
-
-//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
-inline GREAL gim_inv_sqrt(GREAL f)
-{
- GREAL r;
- GIM_INV_SQRT(f, r);
- return r;
-}
-
-inline GREAL gim_sqrt(GREAL f)
-{
- GREAL r;
- GIM_SQRT(f, r);
- return r;
-}
-
-#endif // GIM_MATH_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp
deleted file mode 100644
index 9e29ab91d6..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_memory.h"
-#include "stdlib.h"
-
-#ifdef GIM_SIMD_MEMORY
-#include "LinearMath/btAlignedAllocator.h"
-#endif
-
-static gim_alloc_function *g_allocfn = 0;
-static gim_alloca_function *g_allocafn = 0;
-static gim_realloc_function *g_reallocfn = 0;
-static gim_free_function *g_freefn = 0;
-
-void gim_set_alloc_handler(gim_alloc_function *fn)
-{
- g_allocfn = fn;
-}
-
-void gim_set_alloca_handler(gim_alloca_function *fn)
-{
- g_allocafn = fn;
-}
-
-void gim_set_realloc_handler(gim_realloc_function *fn)
-{
- g_reallocfn = fn;
-}
-
-void gim_set_free_handler(gim_free_function *fn)
-{
- g_freefn = fn;
-}
-
-gim_alloc_function *gim_get_alloc_handler()
-{
- return g_allocfn;
-}
-
-gim_alloca_function *gim_get_alloca_handler()
-{
- return g_allocafn;
-}
-
-gim_realloc_function *gim_get_realloc_handler()
-{
- return g_reallocfn;
-}
-
-gim_free_function *gim_get_free_handler()
-{
- return g_freefn;
-}
-
-void *gim_alloc(size_t size)
-{
- void *ptr;
- if (g_allocfn)
- {
- ptr = g_allocfn(size);
- }
- else
- {
-#ifdef GIM_SIMD_MEMORY
- ptr = btAlignedAlloc(size, 16);
-#else
- ptr = malloc(size);
-#endif
- }
- return ptr;
-}
-
-void *gim_alloca(size_t size)
-{
- if (g_allocafn)
- return g_allocafn(size);
- else
- return gim_alloc(size);
-}
-
-void *gim_realloc(void *ptr, size_t oldsize, size_t newsize)
-{
- void *newptr = gim_alloc(newsize);
- size_t copysize = oldsize < newsize ? oldsize : newsize;
- gim_simd_memcpy(newptr, ptr, copysize);
- gim_free(ptr);
- return newptr;
-}
-
-void gim_free(void *ptr)
-{
- if (!ptr) return;
- if (g_freefn)
- {
- g_freefn(ptr);
- }
- else
- {
-#ifdef GIM_SIMD_MEMORY
- btAlignedFree(ptr);
-#else
- free(ptr);
-#endif
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h
deleted file mode 100644
index fffbfa23d8..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_memory.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef GIM_MEMORY_H_INCLUDED
-#define GIM_MEMORY_H_INCLUDED
-/*! \file gim_memory.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_math.h"
-#include <string.h>
-
-#ifdef PREFETCH
-#include <xmmintrin.h> // for prefetch
-#define pfval 64
-#define pfval2 128
-//! Prefetch 64
-#define pf(_x, _i) _mm_prefetch((void *)(_x + _i + pfval), 0)
-//! Prefetch 128
-#define pf2(_x, _i) _mm_prefetch((void *)(_x + _i + pfval2), 0)
-#else
-//! Prefetch 64
-#define pf(_x, _i)
-//! Prefetch 128
-#define pf2(_x, _i)
-#endif
-
-///Functions for manip packed arrays of numbers
-#define GIM_COPY_ARRAYS(dest_array, source_array, element_count) \
- { \
- for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
- { \
- dest_array[_i_] = source_array[_i_]; \
- } \
- }
-
-#define GIM_COPY_ARRAYS_1(dest_array, source_array, element_count, copy_macro) \
- { \
- for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
- { \
- copy_macro(dest_array[_i_], source_array[_i_]); \
- } \
- }
-
-#define GIM_ZERO_ARRAY(array, element_count) \
- { \
- for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
- { \
- array[_i_] = 0; \
- } \
- }
-
-#define GIM_CONSTANT_ARRAY(array, element_count, constant) \
- { \
- for (GUINT _i_ = 0; _i_ < element_count; ++_i_) \
- { \
- array[_i_] = constant; \
- } \
- }
-
-///Function prototypes to allocate and free memory.
-typedef void *gim_alloc_function(size_t size);
-typedef void *gim_alloca_function(size_t size); //Allocs on the heap
-typedef void *gim_realloc_function(void *ptr, size_t oldsize, size_t newsize);
-typedef void gim_free_function(void *ptr);
-
-///Memory Function Handlers
-///set new memory management functions. if fn is 0, the default handlers are used.
-void gim_set_alloc_handler(gim_alloc_function *fn);
-void gim_set_alloca_handler(gim_alloca_function *fn);
-void gim_set_realloc_handler(gim_realloc_function *fn);
-void gim_set_free_handler(gim_free_function *fn);
-
-///get current memory management functions.
-gim_alloc_function *gim_get_alloc_handler(void);
-gim_alloca_function *gim_get_alloca_handler(void);
-gim_realloc_function *gim_get_realloc_handler(void);
-gim_free_function *gim_get_free_handler(void);
-
-///Standar Memory functions
-void *gim_alloc(size_t size);
-void *gim_alloca(size_t size);
-void *gim_realloc(void *ptr, size_t oldsize, size_t newsize);
-void gim_free(void *ptr);
-
-#if defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define GIM_SIMD_MEMORY 1
-#endif
-
-//! SIMD POINTER INTEGER
-#define SIMD_T GUINT64
-//! SIMD INTEGER SIZE
-#define SIMD_T_SIZE sizeof(SIMD_T)
-
-inline void gim_simd_memcpy(void *dst, const void *src, size_t copysize)
-{
-#ifdef GIM_SIMD_MEMORY
- /*
-//'long long int' is incompatible with visual studio 6...
- //copy words
- SIMD_T * ui_src_ptr = (SIMD_T *)src;
- SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
- while(copysize>=SIMD_T_SIZE)
- {
- *(ui_dst_ptr++) = *(ui_src_ptr++);
- copysize-=SIMD_T_SIZE;
- }
- if(copysize==0) return;
-*/
-
- char *c_src_ptr = (char *)src;
- char *c_dst_ptr = (char *)dst;
- while (copysize > 0)
- {
- *(c_dst_ptr++) = *(c_src_ptr++);
- copysize--;
- }
- return;
-#else
- memcpy(dst, src, copysize);
-#endif
-}
-
-template <class T>
-inline void gim_swap_elements(T *_array, size_t _i, size_t _j)
-{
- T _e_tmp_ = _array[_i];
- _array[_i] = _array[_j];
- _array[_j] = _e_tmp_;
-}
-
-template <class T>
-inline void gim_swap_elements_memcpy(T *_array, size_t _i, size_t _j)
-{
- char _e_tmp_[sizeof(T)];
- gim_simd_memcpy(_e_tmp_, &_array[_i], sizeof(T));
- gim_simd_memcpy(&_array[_i], &_array[_j], sizeof(T));
- gim_simd_memcpy(&_array[_j], _e_tmp_, sizeof(T));
-}
-
-template <int SIZE>
-inline void gim_swap_elements_ptr(char *_array, size_t _i, size_t _j)
-{
- char _e_tmp_[SIZE];
- _i *= SIZE;
- _j *= SIZE;
- gim_simd_memcpy(_e_tmp_, _array + _i, SIZE);
- gim_simd_memcpy(_array + _i, _array + _j, SIZE);
- gim_simd_memcpy(_array + _j, _e_tmp_, SIZE);
-}
-
-#endif // GIM_MEMORY_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h
deleted file mode 100644
index 56c185a5dc..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_pair.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef GIM_PAIR_H
-#define GIM_PAIR_H
-
-
-//! Overlapping pair
-struct GIM_PAIR
-{
- int m_index1;
- int m_index2;
- GIM_PAIR()
- {
- }
-
- GIM_PAIR(const GIM_PAIR& p)
- {
- m_index1 = p.m_index1;
- m_index2 = p.m_index2;
- }
-
- GIM_PAIR(int index1, int index2)
- {
- m_index1 = index1;
- m_index2 = index2;
- }
-};
-
-#endif //GIM_PAIR_H
-
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h
deleted file mode 100644
index ff7907adca..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_radixsort.h
+++ /dev/null
@@ -1,386 +0,0 @@
-#ifndef GIM_RADIXSORT_H_INCLUDED
-#define GIM_RADIXSORT_H_INCLUDED
-/*! \file gim_radixsort.h
-\author Francisco Leon Najera.
-Based on the work of Michael Herf : "fast floating-point radix sort"
-Avaliable on http://www.stereopsis.com/radix.html
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_memory.h"
-
-///Macros for sorting.
-//! Prototype for comparators
-class less_comparator
-{
-public:
- template <class T, class Z>
- inline int operator()(const T& a, const Z& b)
- {
- return (a < b ? -1 : (a > b ? 1 : 0));
- }
-};
-
-//! Prototype for comparators
-class integer_comparator
-{
-public:
- template <class T>
- inline int operator()(const T& a, const T& b)
- {
- return (int)(a - b);
- }
-};
-
-//!Prototype for getting the integer representation of an object
-class uint_key_func
-{
-public:
- template <class T>
- inline GUINT operator()(const T& a)
- {
- return (GUINT)a;
- }
-};
-
-//!Prototype for copying elements
-class copy_elements_func
-{
-public:
- template <class T>
- inline void operator()(T& a, T& b)
- {
- a = b;
- }
-};
-
-//!Prototype for copying elements
-class memcopy_elements_func
-{
-public:
- template <class T>
- inline void operator()(T& a, T& b)
- {
- gim_simd_memcpy(&a, &b, sizeof(T));
- }
-};
-
-//! @{
-struct GIM_RSORT_TOKEN
-{
- GUINT m_key;
- GUINT m_value;
- GIM_RSORT_TOKEN()
- {
- }
- GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
- {
- m_key = rtoken.m_key;
- m_value = rtoken.m_value;
- }
-
- inline bool operator<(const GIM_RSORT_TOKEN& other) const
- {
- return (m_key < other.m_key);
- }
-
- inline bool operator>(const GIM_RSORT_TOKEN& other) const
- {
- return (m_key > other.m_key);
- }
-};
-
-//! Prototype for comparators
-class GIM_RSORT_TOKEN_COMPARATOR
-{
-public:
- inline int operator()(const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b)
- {
- return (int)((a.m_key) - (b.m_key));
- }
-};
-
-#define kHist 2048
-// ---- utils for accessing 11-bit quantities
-#define D11_0(x) (x & 0x7FF)
-#define D11_1(x) (x >> 11 & 0x7FF)
-#define D11_2(x) (x >> 22)
-
-///Radix sort for unsigned integer keys
-inline void gim_radix_sort_rtokens(
- GIM_RSORT_TOKEN* array,
- GIM_RSORT_TOKEN* sorted, GUINT element_count)
-{
- GUINT i;
- GUINT b0[kHist * 3];
- GUINT* b1 = b0 + kHist;
- GUINT* b2 = b1 + kHist;
- for (i = 0; i < kHist * 3; ++i)
- {
- b0[i] = 0;
- }
- GUINT fi;
- GUINT pos;
- for (i = 0; i < element_count; ++i)
- {
- fi = array[i].m_key;
- b0[D11_0(fi)]++;
- b1[D11_1(fi)]++;
- b2[D11_2(fi)]++;
- }
- {
- GUINT sum0 = 0, sum1 = 0, sum2 = 0;
- GUINT tsum;
- for (i = 0; i < kHist; ++i)
- {
- tsum = b0[i] + sum0;
- b0[i] = sum0 - 1;
- sum0 = tsum;
- tsum = b1[i] + sum1;
- b1[i] = sum1 - 1;
- sum1 = tsum;
- tsum = b2[i] + sum2;
- b2[i] = sum2 - 1;
- sum2 = tsum;
- }
- }
- for (i = 0; i < element_count; ++i)
- {
- fi = array[i].m_key;
- pos = D11_0(fi);
- pos = ++b0[pos];
- sorted[pos].m_key = array[i].m_key;
- sorted[pos].m_value = array[i].m_value;
- }
- for (i = 0; i < element_count; ++i)
- {
- fi = sorted[i].m_key;
- pos = D11_1(fi);
- pos = ++b1[pos];
- array[pos].m_key = sorted[i].m_key;
- array[pos].m_value = sorted[i].m_value;
- }
- for (i = 0; i < element_count; ++i)
- {
- fi = array[i].m_key;
- pos = D11_2(fi);
- pos = ++b2[pos];
- sorted[pos].m_key = array[i].m_key;
- sorted[pos].m_value = array[i].m_value;
- }
-}
-
-/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
-/*!
-*\param array Array of elements to sort
-*\param sorted_tokens Tokens of sorted elements
-*\param element_count element count
-*\param uintkey_macro Functor which retrieves the integer representation of an array element
-*/
-template <typename T, class GETKEY_CLASS>
-void gim_radix_sort_array_tokens(
- T* array,
- GIM_RSORT_TOKEN* sorted_tokens,
- GUINT element_count, GETKEY_CLASS uintkey_macro)
-{
- GIM_RSORT_TOKEN* _unsorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
- for (GUINT _i = 0; _i < element_count; ++_i)
- {
- _unsorted[_i].m_key = uintkey_macro(array[_i]);
- _unsorted[_i].m_value = _i;
- }
- gim_radix_sort_rtokens(_unsorted, sorted_tokens, element_count);
- gim_free(_unsorted);
- gim_free(_unsorted);
-}
-
-/// Sorts array in place. For generic use
-/*!
-\param type Type of the array
-\param array
-\param element_count
-\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
-\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
-*/
-template <typename T, class GETKEY_CLASS, class COPY_CLASS>
-void gim_radix_sort(
- T* array, GUINT element_count,
- GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
-{
- GIM_RSORT_TOKEN* _sorted = (GIM_RSORT_TOKEN*)gim_alloc(sizeof(GIM_RSORT_TOKEN) * element_count);
- gim_radix_sort_array_tokens(array, _sorted, element_count, get_uintkey_macro);
- T* _original_array = (T*)gim_alloc(sizeof(T) * element_count);
- gim_simd_memcpy(_original_array, array, sizeof(T) * element_count);
- for (GUINT _i = 0; _i < element_count; ++_i)
- {
- copy_elements_macro(array[_i], _original_array[_sorted[_i].m_value]);
- }
- gim_free(_original_array);
- gim_free(_sorted);
-}
-
-//! Failsafe Iterative binary search,
-/*!
-If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
-\param _array
-\param _start_i the beginning of the array
-\param _end_i the ending index of the array
-\param _search_key Value to find
-\param _comp_macro macro for comparing elements
-\param _found If true the value has found. Boolean
-\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
-*/
-template <class T, typename KEYCLASS, typename COMP_CLASS>
-bool gim_binary_search_ex(
- const T* _array, GUINT _start_i,
- GUINT _end_i, GUINT& _result_index,
- const KEYCLASS& _search_key,
- COMP_CLASS _comp_macro)
-{
- GUINT _k;
- int _comp_result;
- GUINT _i = _start_i;
- GUINT _j = _end_i + 1;
- while (_i < _j)
- {
- _k = (_j + _i - 1) / 2;
- _comp_result = _comp_macro(_array[_k], _search_key);
- if (_comp_result == 0)
- {
- _result_index = _k;
- return true;
- }
- else if (_comp_result < 0)
- {
- _i = _k + 1;
- }
- else
- {
- _j = _k;
- }
- }
- _result_index = _i;
- return false;
-}
-
-//! Failsafe Iterative binary search,Template version
-/*!
-If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
-\param _array
-\param _start_i the beginning of the array
-\param _end_i the ending index of the array
-\param _search_key Value to find
-\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value
-\return true if found, else false
-*/
-template <class T>
-bool gim_binary_search(
- const T* _array, GUINT _start_i,
- GUINT _end_i, const T& _search_key,
- GUINT& _result_index)
-{
- GUINT _i = _start_i;
- GUINT _j = _end_i + 1;
- GUINT _k;
- while (_i < _j)
- {
- _k = (_j + _i - 1) / 2;
- if (_array[_k] == _search_key)
- {
- _result_index = _k;
- return true;
- }
- else if (_array[_k] < _search_key)
- {
- _i = _k + 1;
- }
- else
- {
- _j = _k;
- }
- }
- _result_index = _i;
- return false;
-}
-
-///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
-template <typename T, typename COMP_CLASS>
-void gim_down_heap(T* pArr, GUINT k, GUINT n, COMP_CLASS CompareFunc)
-{
- /* PRE: a[k+1..N] is a heap */
- /* POST: a[k..N] is a heap */
-
- T temp = pArr[k - 1];
- /* k has child(s) */
- while (k <= n / 2)
- {
- int child = 2 * k;
-
- if ((child < (int)n) && CompareFunc(pArr[child - 1], pArr[child]) < 0)
- {
- child++;
- }
- /* pick larger child */
- if (CompareFunc(temp, pArr[child - 1]) < 0)
- {
- /* move child up */
- pArr[k - 1] = pArr[child - 1];
- k = child;
- }
- else
- {
- break;
- }
- }
- pArr[k - 1] = temp;
-} /*downHeap*/
-
-template <typename T, typename COMP_CLASS>
-void gim_heap_sort(T* pArr, GUINT element_count, COMP_CLASS CompareFunc)
-{
- /* sort a[0..N-1], N.B. 0 to N-1 */
- GUINT k;
- GUINT n = element_count;
- for (k = n / 2; k > 0; k--)
- {
- gim_down_heap(pArr, k, n, CompareFunc);
- }
-
- /* a[1..N] is now a heap */
- while (n >= 2)
- {
- gim_swap_elements(pArr, 0, n - 1); /* largest of a[0..n-1] */
- --n;
- /* restore a[1..i-1] heap */
- gim_down_heap(pArr, 1, n, CompareFunc);
- }
-}
-
-#endif // GIM_RADIXSORT_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp
deleted file mode 100644
index 8d83e95da4..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.cpp
+++ /dev/null
@@ -1,619 +0,0 @@
-
-/*! \file gim_tri_collision.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_tri_collision.h"
-
-#define TRI_LOCAL_EPSILON 0.000001f
-#define MIN_EDGE_EDGE_DIS 0.00001f
-
-class GIM_TRIANGLE_CALCULATION_CACHE
-{
-public:
- GREAL margin;
- btVector3 tu_vertices[3];
- btVector3 tv_vertices[3];
- btVector4 tu_plane;
- btVector4 tv_plane;
- btVector3 closest_point_u;
- btVector3 closest_point_v;
- btVector3 edge_edge_dir;
- btVector3 distances;
- GREAL du[4];
- GREAL du0du1;
- GREAL du0du2;
- GREAL dv[4];
- GREAL dv0dv1;
- GREAL dv0dv2;
- btVector3 temp_points[MAX_TRI_CLIPPING];
- btVector3 temp_points1[MAX_TRI_CLIPPING];
- btVector3 contact_points[MAX_TRI_CLIPPING];
-
- //! if returns false, the faces are paralele
- SIMD_FORCE_INLINE bool compute_intervals(
- const GREAL &D0,
- const GREAL &D1,
- const GREAL &D2,
- const GREAL &D0D1,
- const GREAL &D0D2,
- GREAL &scale_edge0,
- GREAL &scale_edge1,
- GUINT &edge_index0,
- GUINT &edge_index1)
- {
- if (D0D1 > 0.0f)
- {
- /* here we know that D0D2<=0.0 */
- /* that is D0, D1 are on the same side, D2 on the other or on the plane */
- scale_edge0 = -D2 / (D0 - D2);
- scale_edge1 = -D1 / (D2 - D1);
- edge_index0 = 2;
- edge_index1 = 1;
- }
- else if (D0D2 > 0.0f)
- {
- /* here we know that d0d1<=0.0 */
- scale_edge0 = -D0 / (D1 - D0);
- scale_edge1 = -D1 / (D2 - D1);
- edge_index0 = 0;
- edge_index1 = 1;
- }
- else if (D1 * D2 > 0.0f || D0 != 0.0f)
- {
- /* here we know that d0d1<=0.0 or that D0!=0.0 */
- scale_edge0 = -D0 / (D1 - D0);
- scale_edge1 = -D2 / (D0 - D2);
- edge_index0 = 0;
- edge_index1 = 2;
- }
- else
- {
- return false;
- }
- return true;
- }
-
- //! clip triangle
- /*!
- */
- SIMD_FORCE_INLINE GUINT clip_triangle(
- const btVector4 &tri_plane,
- const btVector3 *tripoints,
- const btVector3 *srcpoints,
- btVector3 *clip_points)
- {
- // edge 0
-
- btVector4 edgeplane;
-
- EDGE_PLANE(tripoints[0], tripoints[1], tri_plane, edgeplane);
-
- GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
- edgeplane, srcpoints[0], srcpoints[1], srcpoints[2], temp_points);
-
- if (clipped_count == 0) return 0;
-
- // edge 1
-
- EDGE_PLANE(tripoints[1], tripoints[2], tri_plane, edgeplane);
-
- clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane, temp_points, clipped_count, temp_points1);
-
- if (clipped_count == 0) return 0;
-
- // edge 2
-
- EDGE_PLANE(tripoints[2], tripoints[0], tri_plane, edgeplane);
-
- clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane, temp_points1, clipped_count, clip_points);
-
- return clipped_count;
-
- /*GUINT i0 = (tri_plane.closestAxis()+1)%3;
- GUINT i1 = (i0+1)%3;
- // edge 0
- btVector3 temp_points[MAX_TRI_CLIPPING];
- btVector3 temp_points1[MAX_TRI_CLIPPING];
-
- GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
- 0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
- DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
-
-
- if(clipped_count == 0) return 0;
-
- // edge 1
- clipped_count = PLANE_CLIP_POLYGON_GENERIC(
- 0,temp_points,clipped_count,temp_points1,
- DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
-
- if(clipped_count == 0) return 0;
-
- // edge 2
- clipped_count = PLANE_CLIP_POLYGON_GENERIC(
- 0,temp_points1,clipped_count,clipped_points,
- DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
-
- return clipped_count;*/
- }
-
- SIMD_FORCE_INLINE void sort_isect(
- GREAL &isect0, GREAL &isect1, GUINT &e0, GUINT &e1, btVector3 &vec0, btVector3 &vec1)
- {
- if (isect1 < isect0)
- {
- //swap
- GIM_SWAP_NUMBERS(isect0, isect1);
- GIM_SWAP_NUMBERS(e0, e1);
- btVector3 tmp = vec0;
- vec0 = vec1;
- vec1 = tmp;
- }
- }
-
- //! Test verifying interval intersection with the direction between planes
- /*!
- \pre tv_plane and tu_plane must be set
- \post
- distances[2] is set with the distance
- closest_point_u, closest_point_v, edge_edge_dir are set too
- \return
- - 0: faces are paralele
- - 1: face U casts face V
- - 2: face V casts face U
- - 3: nearest edges
- */
- SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
- {
- // Compute direction of intersection line
- edge_edge_dir = tu_plane.cross(tv_plane);
- GREAL Dlen;
- VEC_LENGTH(edge_edge_dir, Dlen);
-
- if (Dlen < 0.0001)
- {
- return 0; //faces near paralele
- }
-
- edge_edge_dir *= 1 / Dlen; //normalize
-
- // Compute interval for triangle 1
- GUINT tu_e0, tu_e1; //edge indices
- GREAL tu_scale_e0, tu_scale_e1; //edge scale
- if (!compute_intervals(du[0], du[1], du[2],
- du0du1, du0du2, tu_scale_e0, tu_scale_e1, tu_e0, tu_e1)) return 0;
-
- // Compute interval for triangle 2
- GUINT tv_e0, tv_e1; //edge indices
- GREAL tv_scale_e0, tv_scale_e1; //edge scale
-
- if (!compute_intervals(dv[0], dv[1], dv[2],
- dv0dv1, dv0dv2, tv_scale_e0, tv_scale_e1, tv_e0, tv_e1)) return 0;
-
- //proyected vertices
- btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0 + 1) % 3], tu_scale_e0);
- btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1 + 1) % 3], tu_scale_e1);
-
- btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0 + 1) % 3], tv_scale_e0);
- btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1 + 1) % 3], tv_scale_e1);
-
- //proyected intervals
- GREAL isect_u[] = {up_e0.dot(edge_edge_dir), up_e1.dot(edge_edge_dir)};
- GREAL isect_v[] = {vp_e0.dot(edge_edge_dir), vp_e1.dot(edge_edge_dir)};
-
- sort_isect(isect_u[0], isect_u[1], tu_e0, tu_e1, up_e0, up_e1);
- sort_isect(isect_v[0], isect_v[1], tv_e0, tv_e1, vp_e0, vp_e1);
-
- const GREAL midpoint_u = 0.5f * (isect_u[0] + isect_u[1]); // midpoint
- const GREAL midpoint_v = 0.5f * (isect_v[0] + isect_v[1]); // midpoint
-
- if (midpoint_u < midpoint_v)
- {
- if (isect_u[1] >= isect_v[1]) // face U casts face V
- {
- return 1;
- }
- else if (isect_v[0] <= isect_u[0]) // face V casts face U
- {
- return 2;
- }
- // closest points
- closest_point_u = up_e1;
- closest_point_v = vp_e0;
- // calc edges and separation
-
- if (isect_u[1] + MIN_EDGE_EDGE_DIS < isect_v[0]) //calc distance between two lines instead
- {
- SEGMENT_COLLISION(
- tu_vertices[tu_e1], tu_vertices[(tu_e1 + 1) % 3],
- tv_vertices[tv_e0], tv_vertices[(tv_e0 + 1) % 3],
- closest_point_u,
- closest_point_v);
-
- edge_edge_dir = closest_point_u - closest_point_v;
- VEC_LENGTH(edge_edge_dir, distances[2]);
- edge_edge_dir *= 1.0f / distances[2]; // normalize
- }
- else
- {
- distances[2] = isect_v[0] - isect_u[1]; //distance negative
- //edge_edge_dir *= -1.0f; //normal pointing from V to U
- }
- }
- else
- {
- if (isect_v[1] >= isect_u[1]) // face V casts face U
- {
- return 2;
- }
- else if (isect_u[0] <= isect_v[0]) // face U casts face V
- {
- return 1;
- }
- // closest points
- closest_point_u = up_e0;
- closest_point_v = vp_e1;
- // calc edges and separation
-
- if (isect_v[1] + MIN_EDGE_EDGE_DIS < isect_u[0]) //calc distance between two lines instead
- {
- SEGMENT_COLLISION(
- tu_vertices[tu_e0], tu_vertices[(tu_e0 + 1) % 3],
- tv_vertices[tv_e1], tv_vertices[(tv_e1 + 1) % 3],
- closest_point_u,
- closest_point_v);
-
- edge_edge_dir = closest_point_u - closest_point_v;
- VEC_LENGTH(edge_edge_dir, distances[2]);
- edge_edge_dir *= 1.0f / distances[2]; // normalize
- }
- else
- {
- distances[2] = isect_u[0] - isect_v[1]; //distance negative
- //edge_edge_dir *= -1.0f; //normal pointing from V to U
- }
- }
- return 3;
- }
-
- //! collides by two sides
- SIMD_FORCE_INLINE bool triangle_collision(
- const btVector3 &u0,
- const btVector3 &u1,
- const btVector3 &u2,
- GREAL margin_u,
- const btVector3 &v0,
- const btVector3 &v1,
- const btVector3 &v2,
- GREAL margin_v,
- GIM_TRIANGLE_CONTACT_DATA &contacts)
- {
- margin = margin_u + margin_v;
-
- tu_vertices[0] = u0;
- tu_vertices[1] = u1;
- tu_vertices[2] = u2;
-
- tv_vertices[0] = v0;
- tv_vertices[1] = v1;
- tv_vertices[2] = v2;
-
- //create planes
- // plane v vs U points
-
- TRIANGLE_PLANE(tv_vertices[0], tv_vertices[1], tv_vertices[2], tv_plane);
-
- du[0] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[0]);
- du[1] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[1]);
- du[2] = DISTANCE_PLANE_POINT(tv_plane, tu_vertices[2]);
-
- du0du1 = du[0] * du[1];
- du0du2 = du[0] * du[2];
-
- if (du0du1 > 0.0f && du0du2 > 0.0f) // same sign on all of them + not equal 0 ?
- {
- if (du[0] < 0) //we need test behind the triangle plane
- {
- distances[0] = GIM_MAX3(du[0], du[1], du[2]);
- distances[0] = -distances[0];
- if (distances[0] > margin) return false; //never intersect
-
- //reorder triangle v
- VEC_SWAP(tv_vertices[0], tv_vertices[1]);
- VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
- }
- else
- {
- distances[0] = GIM_MIN3(du[0], du[1], du[2]);
- if (distances[0] > margin) return false; //never intersect
- }
- }
- else
- {
- //Look if we need to invert the triangle
- distances[0] = (du[0] + du[1] + du[2]) / 3.0f; //centroid
-
- if (distances[0] < 0.0f)
- {
- //reorder triangle v
- VEC_SWAP(tv_vertices[0], tv_vertices[1]);
- VEC_SCALE_4(tv_plane, -1.0f, tv_plane);
-
- distances[0] = GIM_MAX3(du[0], du[1], du[2]);
- distances[0] = -distances[0];
- }
- else
- {
- distances[0] = GIM_MIN3(du[0], du[1], du[2]);
- }
- }
-
- // plane U vs V points
-
- TRIANGLE_PLANE(tu_vertices[0], tu_vertices[1], tu_vertices[2], tu_plane);
-
- dv[0] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[0]);
- dv[1] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[1]);
- dv[2] = DISTANCE_PLANE_POINT(tu_plane, tv_vertices[2]);
-
- dv0dv1 = dv[0] * dv[1];
- dv0dv2 = dv[0] * dv[2];
-
- if (dv0dv1 > 0.0f && dv0dv2 > 0.0f) // same sign on all of them + not equal 0 ?
- {
- if (dv[0] < 0) //we need test behind the triangle plane
- {
- distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
- distances[1] = -distances[1];
- if (distances[1] > margin) return false; //never intersect
-
- //reorder triangle u
- VEC_SWAP(tu_vertices[0], tu_vertices[1]);
- VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
- }
- else
- {
- distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
- if (distances[1] > margin) return false; //never intersect
- }
- }
- else
- {
- //Look if we need to invert the triangle
- distances[1] = (dv[0] + dv[1] + dv[2]) / 3.0f; //centroid
-
- if (distances[1] < 0.0f)
- {
- //reorder triangle v
- VEC_SWAP(tu_vertices[0], tu_vertices[1]);
- VEC_SCALE_4(tu_plane, -1.0f, tu_plane);
-
- distances[1] = GIM_MAX3(dv[0], dv[1], dv[2]);
- distances[1] = -distances[1];
- }
- else
- {
- distances[1] = GIM_MIN3(dv[0], dv[1], dv[2]);
- }
- }
-
- GUINT bl;
- /* bl = cross_line_intersection_test();
- if(bl==3)
- {
- //take edge direction too
- bl = distances.maxAxis();
- }
- else
- {*/
- bl = 0;
- if (distances[0] < distances[1]) bl = 1;
- //}
-
- if (bl == 2) //edge edge separation
- {
- if (distances[2] > margin) return false;
-
- contacts.m_penetration_depth = -distances[2] + margin;
- contacts.m_points[0] = closest_point_v;
- contacts.m_point_count = 1;
- VEC_COPY(contacts.m_separating_normal, edge_edge_dir);
-
- return true;
- }
-
- //clip face against other
-
- GUINT point_count;
- //TODO
- if (bl == 0) //clip U points against V
- {
- point_count = clip_triangle(tv_plane, tv_vertices, tu_vertices, contact_points);
- if (point_count == 0) return false;
- contacts.merge_points(tv_plane, margin, contact_points, point_count);
- }
- else //clip V points against U
- {
- point_count = clip_triangle(tu_plane, tu_vertices, tv_vertices, contact_points);
- if (point_count == 0) return false;
- contacts.merge_points(tu_plane, margin, contact_points, point_count);
- contacts.m_separating_normal *= -1.f;
- }
- if (contacts.m_point_count == 0) return false;
- return true;
- }
-};
-
-/*class GIM_TRIANGLE_CALCULATION_CACHE
-{
-public:
- GREAL margin;
- GUINT clipped_count;
- btVector3 tu_vertices[3];
- btVector3 tv_vertices[3];
- btVector3 temp_points[MAX_TRI_CLIPPING];
- btVector3 temp_points1[MAX_TRI_CLIPPING];
- btVector3 clipped_points[MAX_TRI_CLIPPING];
- GIM_TRIANGLE_CONTACT_DATA contacts1;
- GIM_TRIANGLE_CONTACT_DATA contacts2;
-
-
- //! clip triangle
- GUINT clip_triangle(
- const btVector4 & tri_plane,
- const btVector3 * tripoints,
- const btVector3 * srcpoints,
- btVector3 * clipped_points)
- {
- // edge 0
-
- btVector4 edgeplane;
-
- EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
-
- GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
- edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
-
- if(clipped_count == 0) return 0;
-
- // edge 1
-
- EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
-
- clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane,temp_points,clipped_count,temp_points1);
-
- if(clipped_count == 0) return 0;
-
- // edge 2
-
- EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
-
- clipped_count = PLANE_CLIP_POLYGON3D(
- edgeplane,temp_points1,clipped_count,clipped_points);
-
- return clipped_count;
- }
-
-
-
-
- //! collides only on one side
- bool triangle_collision(
- const btVector3 & u0,
- const btVector3 & u1,
- const btVector3 & u2,
- GREAL margin_u,
- const btVector3 & v0,
- const btVector3 & v1,
- const btVector3 & v2,
- GREAL margin_v,
- GIM_TRIANGLE_CONTACT_DATA & contacts)
- {
-
- margin = margin_u + margin_v;
-
-
- tu_vertices[0] = u0;
- tu_vertices[1] = u1;
- tu_vertices[2] = u2;
-
- tv_vertices[0] = v0;
- tv_vertices[1] = v1;
- tv_vertices[2] = v2;
-
- //create planes
- // plane v vs U points
-
-
- TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
-
- clipped_count = clip_triangle(
- contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
-
- if(clipped_count == 0 )
- {
- return false;//Reject
- }
-
- //find most deep interval face1
- contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
- if(contacts1.m_point_count == 0) return false; // too far
-
- //Normal pointing to triangle1
- //contacts1.m_separating_normal *= -1.f;
-
- //Clip tri1 by tri2 edges
-
- TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
-
- clipped_count = clip_triangle(
- contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
-
- if(clipped_count == 0 )
- {
- return false;//Reject
- }
-
- //find most deep interval face1
- contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
- if(contacts2.m_point_count == 0) return false; // too far
-
- contacts2.m_separating_normal *= -1.f;
-
- ////check most dir for contacts
- if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
- {
- contacts.copy_from(contacts2);
- }
- else
- {
- contacts.copy_from(contacts1);
- }
- return true;
- }
-
-
-};*/
-
-bool GIM_TRIANGLE::collide_triangle_hard_test(
- const GIM_TRIANGLE &other,
- GIM_TRIANGLE_CONTACT_DATA &contact_data) const
-{
- GIM_TRIANGLE_CALCULATION_CACHE calc_cache;
- return calc_cache.triangle_collision(
- m_vertices[0], m_vertices[1], m_vertices[2], m_margin,
- other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin,
- contact_data);
-}
diff --git a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h b/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h
deleted file mode 100644
index e6d4bf5470..0000000000
--- a/thirdparty/bullet/BulletCollision/Gimpact/gim_tri_collision.h
+++ /dev/null
@@ -1,368 +0,0 @@
-#ifndef GIM_TRI_COLLISION_H_INCLUDED
-#define GIM_TRI_COLLISION_H_INCLUDED
-
-/*! \file gim_tri_collision.h
-\author Francisco Leon Najera
-*/
-/*
------------------------------------------------------------------------------
-This source file is part of GIMPACT Library.
-
-For the latest info, see http://gimpact.sourceforge.net/
-
-Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
-email: projectileman@yahoo.com
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of EITHER:
- (1) The GNU Lesser General Public License as published by the Free
- Software Foundation; either version 2.1 of the License, or (at
- your option) any later version. The text of the GNU Lesser
- General Public License is included with this library in the
- file GIMPACT-LICENSE-LGPL.TXT.
- (2) The BSD-style license that is included with this library in
- the file GIMPACT-LICENSE-BSD.TXT.
- (3) The zlib/libpng license that is included with this library in
- the file GIMPACT-LICENSE-ZLIB.TXT.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
- GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
-
------------------------------------------------------------------------------
-*/
-
-#include "gim_box_collision.h"
-#include "gim_clip_polygon.h"
-
-#ifndef MAX_TRI_CLIPPING
-#define MAX_TRI_CLIPPING 16
-#endif
-
-//! Structure for collision
-struct GIM_TRIANGLE_CONTACT_DATA
-{
- GREAL m_penetration_depth;
- GUINT m_point_count;
- btVector4 m_separating_normal;
- btVector3 m_points[MAX_TRI_CLIPPING];
-
- SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
- {
- m_penetration_depth = other.m_penetration_depth;
- m_separating_normal = other.m_separating_normal;
- m_point_count = other.m_point_count;
- GUINT i = m_point_count;
- while (i--)
- {
- m_points[i] = other.m_points[i];
- }
- }
-
- GIM_TRIANGLE_CONTACT_DATA()
- {
- }
-
- GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
- {
- copy_from(other);
- }
-
- //! classify points that are closer
- template <typename DISTANCE_FUNC, typename CLASS_PLANE>
- SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE &plane,
- GREAL margin, const btVector3 *points, GUINT point_count, DISTANCE_FUNC distance_func)
- {
- m_point_count = 0;
- m_penetration_depth = -1000.0f;
-
- GUINT point_indices[MAX_TRI_CLIPPING];
-
- GUINT _k;
-
- for (_k = 0; _k < point_count; _k++)
- {
- GREAL _dist = -distance_func(plane, points[_k]) + margin;
-
- if (_dist >= 0.0f)
- {
- if (_dist > m_penetration_depth)
- {
- m_penetration_depth = _dist;
- point_indices[0] = _k;
- m_point_count = 1;
- }
- else if ((_dist + G_EPSILON) >= m_penetration_depth)
- {
- point_indices[m_point_count] = _k;
- m_point_count++;
- }
- }
- }
-
- for (_k = 0; _k < m_point_count; _k++)
- {
- m_points[_k] = points[point_indices[_k]];
- }
- }
-
- //! classify points that are closer
- SIMD_FORCE_INLINE void merge_points(const btVector4 &plane, GREAL margin,
- const btVector3 *points, GUINT point_count)
- {
- m_separating_normal = plane;
- mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
- }
-};
-
-//! Class for colliding triangles
-class GIM_TRIANGLE
-{
-public:
- btScalar m_margin;
- btVector3 m_vertices[3];
-
- GIM_TRIANGLE() : m_margin(0.1f)
- {
- }
-
- SIMD_FORCE_INLINE GIM_AABB get_box() const
- {
- return GIM_AABB(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
- }
-
- SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
- {
- TRIANGLE_NORMAL(m_vertices[0], m_vertices[1], m_vertices[2], normal);
- }
-
- SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
- {
- TRIANGLE_PLANE(m_vertices[0], m_vertices[1], m_vertices[2], plane);
- ;
- }
-
- SIMD_FORCE_INLINE void apply_transform(const btTransform &trans)
- {
- m_vertices[0] = trans(m_vertices[0]);
- m_vertices[1] = trans(m_vertices[1]);
- m_vertices[2] = trans(m_vertices[2]);
- }
-
- SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index, const btVector3 &triangle_normal, btVector4 &plane) const
- {
- const btVector3 &e0 = m_vertices[edge_index];
- const btVector3 &e1 = m_vertices[(edge_index + 1) % 3];
- EDGE_PLANE(e0, e1, triangle_normal, plane);
- }
-
- //! Gets the relative transformation of this triangle
- /*!
- The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
- - triangle normal corresponds to Z axis.
- - 1st normalized edge corresponds to X axis,
-
- */
- SIMD_FORCE_INLINE void get_triangle_transform(btTransform &triangle_transform) const
- {
- btMatrix3x3 &matrix = triangle_transform.getBasis();
-
- btVector3 zaxis;
- get_normal(zaxis);
- MAT_SET_Z(matrix, zaxis);
-
- btVector3 xaxis = m_vertices[1] - m_vertices[0];
- VEC_NORMALIZE(xaxis);
- MAT_SET_X(matrix, xaxis);
-
- //y axis
- xaxis = zaxis.cross(xaxis);
- MAT_SET_Y(matrix, xaxis);
-
- triangle_transform.setOrigin(m_vertices[0]);
- }
-
- //! Test triangles by finding separating axis
- /*!
- \param other Triangle for collide
- \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
- */
- bool collide_triangle_hard_test(
- const GIM_TRIANGLE &other,
- GIM_TRIANGLE_CONTACT_DATA &contact_data) const;
-
- //! Test boxes before doing hard test
- /*!
- \param other Triangle for collide
- \param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
- \
- */
- SIMD_FORCE_INLINE bool collide_triangle(
- const GIM_TRIANGLE &other,
- GIM_TRIANGLE_CONTACT_DATA &contact_data) const
- {
- //test box collisioin
- GIM_AABB boxu(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
- GIM_AABB boxv(other.m_vertices[0], other.m_vertices[1], other.m_vertices[2], other.m_margin);
- if (!boxu.has_collision(boxv)) return false;
-
- //do hard test
- return collide_triangle_hard_test(other, contact_data);
- }
-
- /*!
-
- Solve the System for u,v parameters:
-
- u*axe1[i1] + v*axe2[i1] = vecproj[i1]
- u*axe1[i2] + v*axe2[i2] = vecproj[i2]
-
- sustitute:
- v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
-
- then the first equation in terms of 'u':
-
- --> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
-
- --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
-
- --> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
-
- --> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
-
- --> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
-
- --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])
-
-if 0.0<= u+v <=1.0 then they are inside of triangle
-
- \return false if the point is outside of triangle.This function doesn't take the margin
- */
- SIMD_FORCE_INLINE bool get_uv_parameters(
- const btVector3 &point,
- const btVector3 &tri_plane,
- GREAL &u, GREAL &v) const
- {
- btVector3 _axe1 = m_vertices[1] - m_vertices[0];
- btVector3 _axe2 = m_vertices[2] - m_vertices[0];
- btVector3 _vecproj = point - m_vertices[0];
- GUINT _i1 = (tri_plane.closestAxis() + 1) % 3;
- GUINT _i2 = (_i1 + 1) % 3;
- if (btFabs(_axe2[_i2]) < G_EPSILON)
- {
- u = (_vecproj[_i2] * _axe2[_i1] - _vecproj[_i1] * _axe2[_i2]) / (_axe1[_i2] * _axe2[_i1] - _axe1[_i1] * _axe2[_i2]);
- v = (_vecproj[_i1] - u * _axe1[_i1]) / _axe2[_i1];
- }
- else
- {
- u = (_vecproj[_i1] * _axe2[_i2] - _vecproj[_i2] * _axe2[_i1]) / (_axe1[_i1] * _axe2[_i2] - _axe1[_i2] * _axe2[_i1]);
- v = (_vecproj[_i2] - u * _axe1[_i2]) / _axe2[_i2];
- }
-
- if (u < -G_EPSILON)
- {
- return false;
- }
- else if (v < -G_EPSILON)
- {
- return false;
- }
- else
- {
- btScalar sumuv;
- sumuv = u + v;
- if (sumuv < -G_EPSILON)
- {
- return false;
- }
- else if (sumuv - 1.0f > G_EPSILON)
- {
- return false;
- }
- }
- return true;
- }
-
- //! is point in triangle beam?
- /*!
- Test if point is in triangle, with m_margin tolerance
- */
- SIMD_FORCE_INLINE bool is_point_inside(const btVector3 &point, const btVector3 &tri_normal) const
- {
- //Test with edge 0
- btVector4 edge_plane;
- this->get_edge_plane(0, tri_normal, edge_plane);
- GREAL dist = DISTANCE_PLANE_POINT(edge_plane, point);
- if (dist - m_margin > 0.0f) return false; // outside plane
-
- this->get_edge_plane(1, tri_normal, edge_plane);
- dist = DISTANCE_PLANE_POINT(edge_plane, point);
- if (dist - m_margin > 0.0f) return false; // outside plane
-
- this->get_edge_plane(2, tri_normal, edge_plane);
- dist = DISTANCE_PLANE_POINT(edge_plane, point);
- if (dist - m_margin > 0.0f) return false; // outside plane
- return true;
- }
-
- //! Bidireccional ray collision
- SIMD_FORCE_INLINE bool ray_collision(
- const btVector3 &vPoint,
- const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
- GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
- {
- btVector4 faceplane;
- {
- btVector3 dif1 = m_vertices[1] - m_vertices[0];
- btVector3 dif2 = m_vertices[2] - m_vertices[0];
- VEC_CROSS(faceplane, dif1, dif2);
- faceplane[3] = m_vertices[0].dot(faceplane);
- }
-
- GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
- if (res == 0) return false;
- if (!is_point_inside(pout, faceplane)) return false;
-
- if (res == 2) //invert normal
- {
- triangle_normal.setValue(-faceplane[0], -faceplane[1], -faceplane[2]);
- }
- else
- {
- triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
- }
-
- VEC_NORMALIZE(triangle_normal);
-
- return true;
- }
-
- //! one direccion ray collision
- SIMD_FORCE_INLINE bool ray_collision_front_side(
- const btVector3 &vPoint,
- const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal,
- GREAL &tparam, GREAL tmax = G_REAL_INFINITY)
- {
- btVector4 faceplane;
- {
- btVector3 dif1 = m_vertices[1] - m_vertices[0];
- btVector3 dif2 = m_vertices[2] - m_vertices[0];
- VEC_CROSS(faceplane, dif1, dif2);
- faceplane[3] = m_vertices[0].dot(faceplane);
- }
-
- GUINT res = LINE_PLANE_COLLISION(faceplane, vDir, vPoint, pout, tparam, btScalar(0), tmax);
- if (res != 1) return false;
-
- if (!is_point_inside(pout, faceplane)) return false;
-
- triangle_normal.setValue(faceplane[0], faceplane[1], faceplane[2]);
-
- VEC_NORMALIZE(triangle_normal);
-
- return true;
- }
-};
-
-#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
deleted file mode 100644
index 3c82133037..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btComputeGjkEpaPenetration.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
-#define BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
-
-#include "LinearMath/btTransform.h" // Note that btVector3 might be double precision...
-#include "btGjkEpa3.h"
-#include "btGjkCollisionDescription.h"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-
-template <typename btConvexTemplate>
-bool btGjkEpaCalcPenDepth(const btConvexTemplate& a, const btConvexTemplate& b,
- const btGjkCollisionDescription& colDesc,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB)
-{
- (void)v;
-
- // const btScalar radialmargin(btScalar(0.));
-
- btVector3 guessVector(b.getWorldTransform().getOrigin() - a.getWorldTransform().getOrigin()); //?? why not use the GJK input?
-
- btGjkEpaSolver3::sResults results;
-
- if (btGjkEpaSolver3_Penetration(a, b, guessVector, results))
-
- {
- // debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
- //resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return true;
- }
- else
- {
- if (btGjkEpaSolver3_Distance(a, b, guessVector, results))
- {
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return false;
- }
- }
- return false;
-}
-
-template <typename btConvexTemplate, typename btGjkDistanceTemplate>
-int btComputeGjkEpaPenetration(const btConvexTemplate& a, const btConvexTemplate& b, const btGjkCollisionDescription& colDesc, btVoronoiSimplexSolver& simplexSolver, btGjkDistanceTemplate* distInfo)
-{
- bool m_catchDegeneracies = true;
- btScalar m_cachedSeparatingDistance = 0.f;
-
- btScalar distance = btScalar(0.);
- btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
-
- btVector3 pointOnA, pointOnB;
- btTransform localTransA = a.getWorldTransform();
- btTransform localTransB = b.getWorldTransform();
-
- btScalar marginA = a.getMargin();
- btScalar marginB = b.getMargin();
-
- int m_curIter = 0;
- int gGjkMaxIter = colDesc.m_maxGjkIterations; //this is to catch invalid input, perhaps check for #NaN?
- btVector3 m_cachedSeparatingAxis = colDesc.m_firstDir;
-
- bool isValid = false;
- bool checkSimplex = false;
- bool checkPenetration = true;
- int m_degenerateSimplex = 0;
-
- int m_lastUsedMethod = -1;
-
- {
- btScalar squaredDistance = BT_LARGE_FLOAT;
- btScalar delta = btScalar(0.);
-
- btScalar margin = marginA + marginB;
-
- simplexSolver.reset();
-
- for (;;)
- //while (true)
- {
- btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
-
- btVector3 pInA = a.getLocalSupportWithoutMargin(separatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithoutMargin(separatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
-
- btVector3 w = pWorld - qWorld;
- delta = m_cachedSeparatingAxis.dot(w);
-
- // potential exit, they don't overlap
- if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * colDesc.m_maximumDistanceSquared))
- {
- m_degenerateSimplex = 10;
- checkSimplex = true;
- //checkPenetration = false;
- break;
- }
-
- //exit 0: the new point is already in the simplex, or we didn't come any closer
- if (simplexSolver.inSimplex(w))
- {
- m_degenerateSimplex = 1;
- checkSimplex = true;
- break;
- }
- // are we getting any closer ?
- btScalar f0 = squaredDistance - delta;
- btScalar f1 = squaredDistance * colDesc.m_gjkRelError2;
-
- if (f0 <= f1)
- {
- if (f0 <= btScalar(0.))
- {
- m_degenerateSimplex = 2;
- }
- else
- {
- m_degenerateSimplex = 11;
- }
- checkSimplex = true;
- break;
- }
-
- //add current vertex to simplex
- simplexSolver.addVertex(w, pWorld, qWorld);
- btVector3 newCachedSeparatingAxis;
-
- //calculate the closest point to the origin (update vector v)
- if (!simplexSolver.closest(newCachedSeparatingAxis))
- {
- m_degenerateSimplex = 3;
- checkSimplex = true;
- break;
- }
-
- if (newCachedSeparatingAxis.length2() < colDesc.m_gjkRelError2)
- {
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
- m_degenerateSimplex = 6;
- checkSimplex = true;
- break;
- }
-
- btScalar previousSquaredDistance = squaredDistance;
- squaredDistance = newCachedSeparatingAxis.length2();
-#if 0
- ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
- if (squaredDistance>previousSquaredDistance)
- {
- m_degenerateSimplex = 7;
- squaredDistance = previousSquaredDistance;
- checkSimplex = false;
- break;
- }
-#endif //
-
- //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
-
- //are we getting any closer ?
- if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
- {
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- checkSimplex = true;
- m_degenerateSimplex = 12;
-
- break;
- }
-
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
-
- //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
- if (m_curIter++ > gGjkMaxIter)
- {
-#if defined(DEBUG) || defined(_DEBUG)
-
- printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
- printf("sepAxis=(%f,%f,%f), squaredDistance = %f\n",
- m_cachedSeparatingAxis.getX(),
- m_cachedSeparatingAxis.getY(),
- m_cachedSeparatingAxis.getZ(),
- squaredDistance);
-#endif
-
- break;
- }
-
- bool check = (!simplexSolver.fullSimplex());
- //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
-
- if (!check)
- {
- //do we need this backup_closest here ?
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- m_degenerateSimplex = 13;
- break;
- }
- }
-
- if (checkSimplex)
- {
- simplexSolver.compute_points(pointOnA, pointOnB);
- normalInB = m_cachedSeparatingAxis;
-
- btScalar lenSqr = m_cachedSeparatingAxis.length2();
-
- //valid normal
- if (lenSqr < 0.0001)
- {
- m_degenerateSimplex = 5;
- }
- if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- normalInB *= rlen; //normalize
-
- btScalar s = btSqrt(squaredDistance);
-
- btAssert(s > btScalar(0.0));
- pointOnA -= m_cachedSeparatingAxis * (marginA / s);
- pointOnB += m_cachedSeparatingAxis * (marginB / s);
- distance = ((btScalar(1.) / rlen) - margin);
- isValid = true;
-
- m_lastUsedMethod = 1;
- }
- else
- {
- m_lastUsedMethod = 2;
- }
- }
-
- bool catchDegeneratePenetrationCase =
- (m_catchDegeneracies && m_degenerateSimplex && ((distance + margin) < 0.01));
-
- //if (checkPenetration && !isValid)
- if (checkPenetration && (!isValid || catchDegeneratePenetrationCase))
- {
- //penetration case
-
- //if there is no way to handle penetrations, bail out
-
- // Penetration depth case.
- btVector3 tmpPointOnA, tmpPointOnB;
-
- m_cachedSeparatingAxis.setZero();
-
- bool isValid2 = btGjkEpaCalcPenDepth(a, b,
- colDesc,
- m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB);
-
- if (isValid2)
- {
- btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
- btScalar lenSqr = tmpNormalInB.length2();
- if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
- {
- tmpNormalInB = m_cachedSeparatingAxis;
- lenSqr = m_cachedSeparatingAxis.length2();
- }
-
- if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
- {
- tmpNormalInB /= btSqrt(lenSqr);
- btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
- //only replace valid penetrations when the result is deeper (check)
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- normalInB = tmpNormalInB;
-
- isValid = true;
- m_lastUsedMethod = 3;
- }
- else
- {
- m_lastUsedMethod = 8;
- }
- }
- else
- {
- m_lastUsedMethod = 9;
- }
- }
- else
-
- {
- ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
- ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
- ///reports a valid positive distance. Use the results of the second GJK instead of failing.
- ///thanks to Jacob.Langford for the reproduction case
- ///http://code.google.com/p/bullet/issues/detail?id=250
-
- if (m_cachedSeparatingAxis.length2() > btScalar(0.))
- {
- btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
- //only replace valid distances when the distance is less
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- pointOnA -= m_cachedSeparatingAxis * marginA;
- pointOnB += m_cachedSeparatingAxis * marginB;
- normalInB = m_cachedSeparatingAxis;
- normalInB.normalize();
-
- isValid = true;
- m_lastUsedMethod = 6;
- }
- else
- {
- m_lastUsedMethod = 5;
- }
- }
- }
- }
- }
-
- if (isValid && ((distance < 0) || (distance * distance < colDesc.m_maximumDistanceSquared)))
- {
- m_cachedSeparatingAxis = normalInB;
- m_cachedSeparatingDistance = distance;
- distInfo->m_distance = distance;
- distInfo->m_normalBtoA = normalInB;
- distInfo->m_pointOnB = pointOnB;
- distInfo->m_pointOnA = pointOnB + normalInB * distance;
- return 0;
- }
- return -m_lastUsedMethod;
-}
-
-#endif //BT_GJK_EPA_PENETATION_CONVEX_COLLISION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
deleted file mode 100644
index 38df8d4808..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btContinuousConvexCollision.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
-#include "LinearMath/btTransformUtil.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-#include "btGjkPairDetector.h"
-#include "btPointCollector.h"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-
-btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
- : m_simplexSolver(simplexSolver),
- m_penetrationDepthSolver(penetrationDepthSolver),
- m_convexA(convexA),
- m_convexB1(convexB),
- m_planeShape(0)
-{
-}
-
-btContinuousConvexCollision::btContinuousConvexCollision(const btConvexShape* convexA, const btStaticPlaneShape* plane)
- : m_simplexSolver(0),
- m_penetrationDepthSolver(0),
- m_convexA(convexA),
- m_convexB1(0),
- m_planeShape(plane)
-{
-}
-
-/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
-/// You don't want your game ever to lock-up.
-#define MAX_ITERATIONS 64
-
-void btContinuousConvexCollision::computeClosestPoints(const btTransform& transA, const btTransform& transB, btPointCollector& pointCollector)
-{
- if (m_convexB1)
- {
- m_simplexSolver->reset();
- btGjkPairDetector gjk(m_convexA, m_convexB1, m_convexA->getShapeType(), m_convexB1->getShapeType(), m_convexA->getMargin(), m_convexB1->getMargin(), m_simplexSolver, m_penetrationDepthSolver);
- btGjkPairDetector::ClosestPointInput input;
- input.m_transformA = transA;
- input.m_transformB = transB;
- gjk.getClosestPoints(input, pointCollector, 0);
- }
- else
- {
- //convex versus plane
- const btConvexShape* convexShape = m_convexA;
- const btStaticPlaneShape* planeShape = m_planeShape;
-
- const btVector3& planeNormal = planeShape->getPlaneNormal();
- const btScalar& planeConstant = planeShape->getPlaneConstant();
-
- btTransform convexWorldTransform = transA;
- btTransform convexInPlaneTrans;
- convexInPlaneTrans = transB.inverse() * convexWorldTransform;
- btTransform planeInConvex;
- planeInConvex = convexWorldTransform.inverse() * transB;
-
- btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis() * -planeNormal);
-
- btVector3 vtxInPlane = convexInPlaneTrans(vtx);
- btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
-
- btVector3 vtxInPlaneProjected = vtxInPlane - distance * planeNormal;
- btVector3 vtxInPlaneWorld = transB * vtxInPlaneProjected;
- btVector3 normalOnSurfaceB = transB.getBasis() * planeNormal;
-
- pointCollector.addContactPoint(
- normalOnSurfaceB,
- vtxInPlaneWorld,
- distance);
- }
-}
-
-bool btContinuousConvexCollision::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
-{
- /// compute linear and angular velocity for this interval, to interpolate
- btVector3 linVelA, angVelA, linVelB, angVelB;
- btTransformUtil::calculateVelocity(fromA, toA, btScalar(1.), linVelA, angVelA);
- btTransformUtil::calculateVelocity(fromB, toB, btScalar(1.), linVelB, angVelB);
-
- btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
- btScalar boundingRadiusB = m_convexB1 ? m_convexB1->getAngularMotionDisc() : 0.f;
-
- btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
- btVector3 relLinVel = (linVelB - linVelA);
-
- btScalar relLinVelocLength = (linVelB - linVelA).length();
-
- if ((relLinVelocLength + maxAngularProjectedVelocity) == 0.f)
- return false;
-
- btScalar lambda = btScalar(0.);
-
- btVector3 n;
- n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- bool hasResult = false;
- btVector3 c;
-
- btScalar lastLambda = lambda;
- //btScalar epsilon = btScalar(0.001);
-
- int numIter = 0;
- //first solution, using GJK
-
- btScalar radius = 0.001f;
- // result.drawCoordSystem(sphereTr);
-
- btPointCollector pointCollector1;
-
- {
- computeClosestPoints(fromA, fromB, pointCollector1);
-
- hasResult = pointCollector1.m_hasResult;
- c = pointCollector1.m_pointInWorld;
- }
-
- if (hasResult)
- {
- btScalar dist;
- dist = pointCollector1.m_distance + result.m_allowedPenetration;
- n = pointCollector1.m_normalOnBInWorld;
- btScalar projectedLinearVelocity = relLinVel.dot(n);
- if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
- return false;
-
- //not close enough
- while (dist > radius)
- {
- if (result.m_debugDrawer)
- {
- result.m_debugDrawer->drawSphere(c, 0.2f, btVector3(1, 1, 1));
- }
- btScalar dLambda = btScalar(0.);
-
- projectedLinearVelocity = relLinVel.dot(n);
-
- //don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if ((projectedLinearVelocity + maxAngularProjectedVelocity) <= SIMD_EPSILON)
- return false;
-
- dLambda = dist / (projectedLinearVelocity + maxAngularProjectedVelocity);
-
- lambda += dLambda;
-
- if (lambda > btScalar(1.) || lambda < btScalar(0.))
- return false;
-
- //todo: next check with relative epsilon
- if (lambda <= lastLambda)
- {
- return false;
- //n.setValue(0,0,0);
- //break;
- }
- lastLambda = lambda;
-
- //interpolate to next lambda
- btTransform interpolatedTransA, interpolatedTransB, relativeTrans;
-
- btTransformUtil::integrateTransform(fromA, linVelA, angVelA, lambda, interpolatedTransA);
- btTransformUtil::integrateTransform(fromB, linVelB, angVelB, lambda, interpolatedTransB);
- relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
-
- if (result.m_debugDrawer)
- {
- result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(), 0.2f, btVector3(1, 0, 0));
- }
-
- result.DebugDraw(lambda);
-
- btPointCollector pointCollector;
- computeClosestPoints(interpolatedTransA, interpolatedTransB, pointCollector);
-
- if (pointCollector.m_hasResult)
- {
- dist = pointCollector.m_distance + result.m_allowedPenetration;
- c = pointCollector.m_pointInWorld;
- n = pointCollector.m_normalOnBInWorld;
- }
- else
- {
- result.reportFailure(-1, numIter);
- return false;
- }
-
- numIter++;
- if (numIter > MAX_ITERATIONS)
- {
- result.reportFailure(-2, numIter);
- return false;
- }
- }
-
- result.m_fraction = lambda;
- result.m_normal = n;
- result.m_hitPoint = c;
- return true;
- }
-
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
deleted file mode 100644
index 67b2205c36..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
-#define BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
-
-#include "btConvexCast.h"
-#include "btSimplexSolverInterface.h"
-class btConvexPenetrationDepthSolver;
-class btConvexShape;
-class btStaticPlaneShape;
-
-/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
-/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
-/// Algorithm operates in worldspace, in order to keep in between motion globally consistent.
-/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
-class btContinuousConvexCollision : public btConvexCast
-{
- btSimplexSolverInterface* m_simplexSolver;
- btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
- const btConvexShape* m_convexA;
- //second object is either a convex or a plane (code sharing)
- const btConvexShape* m_convexB1;
- const btStaticPlaneShape* m_planeShape;
-
- void computeClosestPoints(const btTransform& transA, const btTransform& transB, struct btPointCollector& pointCollector);
-
-public:
- btContinuousConvexCollision(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
-
- btContinuousConvexCollision(const btConvexShape* shapeA, const btStaticPlaneShape* plane);
-
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-};
-
-#endif //BT_CONTINUOUS_COLLISION_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
deleted file mode 100644
index d2a1310b23..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btConvexCast.h"
-
-btConvexCast::~btConvexCast()
-{
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
deleted file mode 100644
index 77b19be599..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_CAST_H
-#define BT_CONVEX_CAST_H
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btScalar.h"
-class btMinkowskiSumShape;
-#include "LinearMath/btIDebugDraw.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define MAX_CONVEX_CAST_ITERATIONS 64
-#define MAX_CONVEX_CAST_EPSILON (SIMD_EPSILON * 10)
-#else
-#define MAX_CONVEX_CAST_ITERATIONS 32
-#define MAX_CONVEX_CAST_EPSILON btScalar(0.0001)
-#endif
-///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
-///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
-//will need to digg deeper to make the algorithm more robust
-//since, a large epsilon can cause an early termination with false
-//positive results (ray intersections that shouldn't be there)
-
-/// btConvexCast is an interface for Casting
-class btConvexCast
-{
-public:
- virtual ~btConvexCast();
-
- ///RayResult stores the closest result
- /// alternatively, add a callback method to decide about closest/all results
- struct CastResult
- {
- //virtual bool addRayResult(const btVector3& normal,btScalar fraction) = 0;
-
- virtual void DebugDraw(btScalar fraction) { (void)fraction; }
- virtual void drawCoordSystem(const btTransform& trans) { (void)trans; }
- virtual void reportFailure(int errNo, int numIterations)
- {
- (void)errNo;
- (void)numIterations;
- }
- CastResult()
- : m_fraction(btScalar(BT_LARGE_FLOAT)),
- m_debugDrawer(0),
- m_allowedPenetration(btScalar(0)),
- m_subSimplexCastMaxIterations(MAX_CONVEX_CAST_ITERATIONS),
- m_subSimplexCastEpsilon(MAX_CONVEX_CAST_EPSILON)
- {
- }
-
- virtual ~CastResult(){};
-
- btTransform m_hitTransformA;
- btTransform m_hitTransformB;
- btVector3 m_normal;
- btVector3 m_hitPoint;
- btScalar m_fraction; //input and output
- btIDebugDraw* m_debugDrawer;
- btScalar m_allowedPenetration;
-
- int m_subSimplexCastMaxIterations;
- btScalar m_subSimplexCastEpsilon;
-
- };
-
- /// cast a convex against another convex object
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result) = 0;
-};
-
-#endif //BT_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
deleted file mode 100644
index 65c9df9340..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_PENETRATION_DEPTH_H
-#define BT_CONVEX_PENETRATION_DEPTH_H
-
-class btVector3;
-#include "btSimplexSolverInterface.h"
-class btConvexShape;
-class btTransform;
-
-///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
-class btConvexPenetrationDepthSolver
-{
-public:
- virtual ~btConvexPenetrationDepthSolver(){};
- virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA, const btConvexShape* convexB,
- const btTransform& transA, const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw) = 0;
-};
-#endif //BT_CONVEX_PENETRATION_DEPTH_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
deleted file mode 100644
index d1bbb1a46e..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
-#define BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btVector3.h"
-
-/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
-/// This interface allows to query for closest points and penetration depth between two (convex) objects
-/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
-/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
-/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
-struct btDiscreteCollisionDetectorInterface
-{
- struct Result
- {
- virtual ~Result() {}
-
- ///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
- virtual void setShapeIdentifiersA(int partId0, int index0) = 0;
- virtual void setShapeIdentifiersB(int partId1, int index1) = 0;
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth) = 0;
- };
-
- struct ClosestPointInput
- {
- ClosestPointInput()
- : m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT))
- {
- }
-
- btTransform m_transformA;
- btTransform m_transformB;
- btScalar m_maximumDistanceSquared;
- };
-
- virtual ~btDiscreteCollisionDetectorInterface(){};
-
- //
- // give either closest points (distance > 0) or penetration (distance)
- // the normal always points from B towards A
- //
- virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false) = 0;
-};
-
-struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
-{
- btVector3 m_normalOnSurfaceB;
- btVector3 m_closestPointInB;
- btScalar m_distance; //negative means penetration !
-
-protected:
- btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
- {
- }
-
-public:
- virtual ~btStorageResult(){};
-
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- if (depth < m_distance)
- {
- m_normalOnSurfaceB = normalOnBInWorld;
- m_closestPointInB = pointInWorld;
- m_distance = depth;
- }
- }
-};
-
-#endif //BT_DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
deleted file mode 100644
index c9fd84bebf..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkCollisionDescription.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2014 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef GJK_COLLISION_DESCRIPTION_H
-#define GJK_COLLISION_DESCRIPTION_H
-
-#include "LinearMath/btVector3.h"
-
-struct btGjkCollisionDescription
-{
- btVector3 m_firstDir;
- int m_maxGjkIterations;
- btScalar m_maximumDistanceSquared;
- btScalar m_gjkRelError2;
- btGjkCollisionDescription()
- : m_firstDir(0, 1, 0),
- m_maxGjkIterations(1000),
- m_maximumDistanceSquared(1e30f),
- m_gjkRelError2(1.0e-6)
- {
- }
- virtual ~btGjkCollisionDescription()
- {
- }
-};
-
-#endif //GJK_COLLISION_DESCRIPTION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
deleted file mode 100644
index 9d61e75dac..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGjkConvexCast.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "btGjkPairDetector.h"
-#include "btPointCollector.h"
-#include "LinearMath/btTransformUtil.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define MAX_ITERATIONS 64
-#else
-#define MAX_ITERATIONS 32
-#endif
-
-btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
- : m_simplexSolver(simplexSolver),
- m_convexA(convexA),
- m_convexB(convexB)
-{
-}
-
-bool btGjkConvexCast::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
-{
- m_simplexSolver->reset();
-
- /// compute linear velocity for this interval, to interpolate
- //assume no rotation/angular velocity, assert here?
- btVector3 linVelA, linVelB;
- linVelA = toA.getOrigin() - fromA.getOrigin();
- linVelB = toB.getOrigin() - fromB.getOrigin();
-
- btScalar radius = btScalar(0.001);
- btScalar lambda = btScalar(0.);
- btVector3 v(1, 0, 0);
-
- int maxIter = MAX_ITERATIONS;
-
- btVector3 n;
- n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- bool hasResult = false;
- btVector3 c;
- btVector3 r = (linVelA - linVelB);
-
- btScalar lastLambda = lambda;
- //btScalar epsilon = btScalar(0.001);
-
- int numIter = 0;
- //first solution, using GJK
-
- btTransform identityTrans;
- identityTrans.setIdentity();
-
- // result.drawCoordSystem(sphereTr);
-
- btPointCollector pointCollector;
-
- btGjkPairDetector gjk(m_convexA, m_convexB, m_simplexSolver, 0); //m_penetrationDepthSolver);
- btGjkPairDetector::ClosestPointInput input;
-
- //we don't use margins during CCD
- // gjk.setIgnoreMargin(true);
-
- input.m_transformA = fromA;
- input.m_transformB = fromB;
- gjk.getClosestPoints(input, pointCollector, 0);
-
- hasResult = pointCollector.m_hasResult;
- c = pointCollector.m_pointInWorld;
-
- if (hasResult)
- {
- btScalar dist;
- dist = pointCollector.m_distance;
- n = pointCollector.m_normalOnBInWorld;
-
- //not close enough
- while (dist > radius)
- {
- numIter++;
- if (numIter > maxIter)
- {
- return false; //todo: report a failure
- }
- btScalar dLambda = btScalar(0.);
-
- btScalar projectedLinearVelocity = r.dot(n);
-
- dLambda = dist / (projectedLinearVelocity);
-
- lambda = lambda - dLambda;
-
- if (lambda > btScalar(1.))
- return false;
-
- if (lambda < btScalar(0.))
- return false;
-
- //todo: next check with relative epsilon
- if (lambda <= lastLambda)
- {
- return false;
- //n.setValue(0,0,0);
- break;
- }
- lastLambda = lambda;
-
- //interpolate to next lambda
- result.DebugDraw(lambda);
- input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
- input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
-
- gjk.getClosestPoints(input, pointCollector, 0);
- if (pointCollector.m_hasResult)
- {
- if (pointCollector.m_distance < btScalar(0.))
- {
- result.m_fraction = lastLambda;
- n = pointCollector.m_normalOnBInWorld;
- result.m_normal = n;
- result.m_hitPoint = pointCollector.m_pointInWorld;
- return true;
- }
- c = pointCollector.m_pointInWorld;
- n = pointCollector.m_normalOnBInWorld;
- dist = pointCollector.m_distance;
- }
- else
- {
- //??
- return false;
- }
- }
-
- //is n normalized?
- //don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (n.dot(r) >= -result.m_allowedPenetration)
- return false;
-
- result.m_fraction = lambda;
- result.m_normal = n;
- result.m_hitPoint = c;
- return true;
- }
-
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
deleted file mode 100644
index ef5979173e..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GJK_CONVEX_CAST_H
-#define BT_GJK_CONVEX_CAST_H
-
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-#include "LinearMath/btVector3.h"
-#include "btConvexCast.h"
-class btConvexShape;
-class btMinkowskiSumShape;
-#include "btSimplexSolverInterface.h"
-
-///GjkConvexCast performs a raycast on a convex object using support mapping.
-class btGjkConvexCast : public btConvexCast
-{
- btSimplexSolverInterface* m_simplexSolver;
- const btConvexShape* m_convexA;
- const btConvexShape* m_convexB;
-
-public:
- btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver);
-
- /// cast a convex against another convex object
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-};
-
-#endif //BT_GJK_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
deleted file mode 100644
index 7d53f8624a..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
+++ /dev/null
@@ -1,1104 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the
-use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software in a
-product, an acknowledgment in the product documentation would be appreciated
-but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-GJK-EPA collision solver by Nathanael Presson, 2008
-*/
-#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "btGjkEpa2.h"
-
-#if defined(DEBUG) || defined(_DEBUG)
-#include <stdio.h> //for debug printf
-#ifdef __SPU__
-#include <spu_printf.h>
-#define printf spu_printf
-#endif //__SPU__
-#endif
-
-namespace gjkepa2_impl
-{
-// Config
-
-/* GJK */
-#define GJK_MAX_ITERATIONS 128
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define GJK_ACCURACY ((btScalar)1e-12)
-#define GJK_MIN_DISTANCE ((btScalar)1e-12)
-#define GJK_DUPLICATED_EPS ((btScalar)1e-12)
-#else
-#define GJK_ACCURACY ((btScalar)0.0001)
-#define GJK_MIN_DISTANCE ((btScalar)0.0001)
-#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
-#endif //BT_USE_DOUBLE_PRECISION
-
-#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
-
-/* EPA */
-#define EPA_MAX_VERTICES 128
-#define EPA_MAX_ITERATIONS 255
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define EPA_ACCURACY ((btScalar)1e-12)
-#define EPA_PLANE_EPS ((btScalar)1e-14)
-#define EPA_INSIDE_EPS ((btScalar)1e-9)
-#else
-#define EPA_ACCURACY ((btScalar)0.0001)
-#define EPA_PLANE_EPS ((btScalar)0.00001)
-#define EPA_INSIDE_EPS ((btScalar)0.01)
-#endif
-
-#define EPA_FALLBACK (10 * EPA_ACCURACY)
-#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
-
-// Shorthands
-typedef unsigned int U;
-typedef unsigned char U1;
-
-// MinkowskiDiff
-struct MinkowskiDiff
-{
- const btConvexShape* m_shapes[2];
- btMatrix3x3 m_toshape1;
- btTransform m_toshape0;
-#ifdef __SPU__
- bool m_enableMargin;
-#else
- btVector3 (btConvexShape::*Ls)(const btVector3&) const;
-#endif //__SPU__
-
- MinkowskiDiff()
- {
- }
-#ifdef __SPU__
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline btVector3 Support0(const btVector3& d) const
- {
- if (m_enableMargin)
- {
- return m_shapes[0]->localGetSupportVertexNonVirtual(d);
- }
- else
- {
- return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
- }
- }
- inline btVector3 Support1(const btVector3& d) const
- {
- if (m_enableMargin)
- {
- return m_toshape0 * (m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1 * d));
- }
- else
- {
- return m_toshape0 * (m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1 * d));
- }
- }
-#else
- void EnableMargin(bool enable)
- {
- if (enable)
- Ls = &btConvexShape::localGetSupportVertexNonVirtual;
- else
- Ls = &btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
- }
- inline btVector3 Support0(const btVector3& d) const
- {
- return (((m_shapes[0])->*(Ls))(d));
- }
- inline btVector3 Support1(const btVector3& d) const
- {
- return (m_toshape0 * ((m_shapes[1])->*(Ls))(m_toshape1 * d));
- }
-#endif //__SPU__
-
- inline btVector3 Support(const btVector3& d) const
- {
- return (Support0(d) - Support1(-d));
- }
- btVector3 Support(const btVector3& d, U index) const
- {
- if (index)
- return (Support1(d));
- else
- return (Support0(d));
- }
-};
-
-typedef MinkowskiDiff tShape;
-
-// GJK
-struct GJK
-{
- /* Types */
- struct sSV
- {
- btVector3 d, w;
- };
- struct sSimplex
- {
- sSV* c[4];
- btScalar p[4];
- U rank;
- };
- struct eStatus
- {
- enum _
- {
- Valid,
- Inside,
- Failed
- };
- };
- /* Fields */
- tShape m_shape;
- btVector3 m_ray;
- btScalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- U m_nfree;
- U m_current;
- sSimplex* m_simplex;
- eStatus::_ m_status;
- /* Methods */
- GJK()
- {
- Initialize();
- }
- void Initialize()
- {
- m_ray = btVector3(0, 0, 0);
- m_nfree = 0;
- m_status = eStatus::Failed;
- m_current = 0;
- m_distance = 0;
- }
- eStatus::_ Evaluate(const tShape& shapearg, const btVector3& guess)
- {
- U iterations = 0;
- btScalar sqdist = 0;
- btScalar alpha = 0;
- btVector3 lastw[4];
- U clastw = 0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eStatus::Valid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const btScalar sqrl = m_ray.length2();
- appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : btVector3(1, 0, 0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do
- {
- const U next = 1 - m_current;
- sSimplex& cs = m_simplices[m_current];
- sSimplex& ns = m_simplices[next];
- /* Check zero */
- const btScalar rl = m_ray.length();
- if (rl < GJK_MIN_DISTANCE)
- { /* Touching or inside */
- m_status = eStatus::Inside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs, -m_ray);
- const btVector3& w = cs.c[cs.rank - 1]->w;
- bool found = false;
- for (U i = 0; i < 4; ++i)
- {
- if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
- {
- found = true;
- break;
- }
- }
- if (found)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- else
- { /* Update lastw */
- lastw[clastw = (clastw + 1) & 3] = w;
- }
- /* Check for termination */
- const btScalar omega = btDot(m_ray, w) / rl;
- alpha = btMax(omega, alpha);
- if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- btScalar weights[4];
- U mask = 0;
- switch (cs.rank)
- {
- case 2:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- weights, mask);
- break;
- case 3:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights, mask);
- break;
- case 4:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights, mask);
- break;
- }
- if (sqdist >= 0)
- { /* Valid */
- ns.rank = 0;
- m_ray = btVector3(0, 0, 0);
- m_current = next;
- for (U i = 0, ni = cs.rank; i < ni; ++i)
- {
- if (mask & (1 << i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w * weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if (mask == 15) m_status = eStatus::Inside;
- }
- else
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
- } while (m_status == eStatus::Valid);
- m_simplex = &m_simplices[m_current];
- switch (m_status)
- {
- case eStatus::Valid:
- m_distance = m_ray.length();
- break;
- case eStatus::Inside:
- m_distance = 0;
- break;
- default:
- {
- }
- }
- return (m_status);
- }
- bool EncloseOrigin()
- {
- switch (m_simplex->rank)
- {
- case 1:
- {
- for (U i = 0; i < 3; ++i)
- {
- btVector3 axis = btVector3(0, 0, 0);
- axis[i] = 1;
- appendvertice(*m_simplex, axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 2:
- {
- const btVector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
- for (U i = 0; i < 3; ++i)
- {
- btVector3 axis = btVector3(0, 0, 0);
- axis[i] = 1;
- const btVector3 p = btCross(d, axis);
- if (p.length2() > 0)
- {
- appendvertice(*m_simplex, p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const btVector3 n = btCross(m_simplex->c[1]->w - m_simplex->c[0]->w,
- m_simplex->c[2]->w - m_simplex->c[0]->w);
- if (n.length2() > 0)
- {
- appendvertice(*m_simplex, n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
- {
- if (btFabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
- m_simplex->c[1]->w - m_simplex->c[3]->w,
- m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
- return (true);
- }
- break;
- }
- return (false);
- }
- /* Internals */
- void getsupport(const btVector3& d, sSV& sv) const
- {
- sv.d = d / d.length();
- sv.w = m_shape.Support(sv.d);
- }
- void removevertice(sSimplex& simplex)
- {
- m_free[m_nfree++] = simplex.c[--simplex.rank];
- }
- void appendvertice(sSimplex& simplex, const btVector3& v)
- {
- simplex.p[simplex.rank] = 0;
- simplex.c[simplex.rank] = m_free[--m_nfree];
- getsupport(v, *simplex.c[simplex.rank++]);
- }
- static btScalar det(const btVector3& a, const btVector3& b, const btVector3& c)
- {
- return (a.y() * b.z() * c.x() + a.z() * b.x() * c.y() -
- a.x() * b.z() * c.y() - a.y() * b.x() * c.z() +
- a.x() * b.y() * c.z() - a.z() * b.y() * c.x());
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- btScalar* w, U& m)
- {
- const btVector3 d = b - a;
- const btScalar l = d.length2();
- if (l > GJK_SIMPLEX2_EPS)
- {
- const btScalar t(l > 0 ? -btDot(a, d) / l : 0);
- if (t >= 1)
- {
- w[0] = 0;
- w[1] = 1;
- m = 2;
- return (b.length2());
- }
- else if (t <= 0)
- {
- w[0] = 1;
- w[1] = 0;
- m = 1;
- return (a.length2());
- }
- else
- {
- w[0] = 1 - (w[1] = t);
- m = 3;
- return ((a + d * t).length2());
- }
- }
- return (-1);
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar* w, U& m)
- {
- static const U imd3[] = {1, 2, 0};
- const btVector3* vt[] = {&a, &b, &c};
- const btVector3 dl[] = {a - b, b - c, c - a};
- const btVector3 n = btCross(dl[0], dl[1]);
- const btScalar l = n.length2();
- if (l > GJK_SIMPLEX3_EPS)
- {
- btScalar mindist = -1;
- btScalar subw[2] = {0.f, 0.f};
- U subm(0);
- for (U i = 0; i < 3; ++i)
- {
- if (btDot(*vt[i], btCross(dl[i], n)) > 0)
- {
- const U j = imd3[i];
- const btScalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<U>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
- }
- if (mindist < 0)
- {
- const btScalar d = btDot(a, n);
- const btScalar s = btSqrt(l);
- const btVector3 p = n * (d / l);
- mindist = p.length2();
- m = 7;
- w[0] = (btCross(dl[1], b - p)).length() / s;
- w[1] = (btCross(dl[2], c - p)).length() / s;
- w[2] = 1 - (w[0] + w[1]);
- }
- return (mindist);
- }
- return (-1);
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& d,
- btScalar* w, U& m)
- {
- static const U imd3[] = {1, 2, 0};
- const btVector3* vt[] = {&a, &b, &c, &d};
- const btVector3 dl[] = {a - d, b - d, c - d};
- const btScalar vl = det(dl[0], dl[1], dl[2]);
- const bool ng = (vl * btDot(a, btCross(b - c, a - b))) <= 0;
- if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
- {
- btScalar mindist = -1;
- btScalar subw[3] = {0.f, 0.f, 0.f};
- U subm(0);
- for (U i = 0; i < 3; ++i)
- {
- const U j = imd3[i];
- const btScalar s = vl * btDot(d, btCross(dl[i], dl[j]));
- if (s > 0)
- {
- const btScalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<U>((subm & 1 ? 1 << i : 0) +
- (subm & 2 ? 1 << j : 0) +
- (subm & 4 ? 8 : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
- }
- if (mindist < 0)
- {
- mindist = 0;
- m = 15;
- w[0] = det(c, b, d) / vl;
- w[1] = det(a, c, d) / vl;
- w[2] = det(b, a, d) / vl;
- w[3] = 1 - (w[0] + w[1] + w[2]);
- }
- return (mindist);
- }
- return (-1);
- }
-};
-
-// EPA
-struct EPA
-{
- /* Types */
- typedef GJK::sSV sSV;
- struct sFace
- {
- btVector3 n;
- btScalar d;
- sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- U1 e[3];
- U1 pass;
- };
- struct sList
- {
- sFace* root;
- U count;
- sList() : root(0), count(0) {}
- };
- struct sHorizon
- {
- sFace* cf;
- sFace* ff;
- U nf;
- sHorizon() : cf(0), ff(0), nf(0) {}
- };
- struct eStatus
- {
- enum _
- {
- Valid,
- Touching,
- Degenerated,
- NonConvex,
- InvalidHull,
- OutOfFaces,
- OutOfVertices,
- AccuraryReached,
- FallBack,
- Failed
- };
- };
- /* Fields */
- eStatus::_ m_status;
- GJK::sSimplex m_result;
- btVector3 m_normal;
- btScalar m_depth;
- sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- U m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- EPA()
- {
- Initialize();
- }
-
- static inline void bind(sFace* fa, U ea, sFace* fb, U eb)
- {
- fa->e[ea] = (U1)eb;
- fa->f[ea] = fb;
- fb->e[eb] = (U1)ea;
- fb->f[eb] = fa;
- }
- static inline void append(sList& list, sFace* face)
- {
- face->l[0] = 0;
- face->l[1] = list.root;
- if (list.root) list.root->l[0] = face;
- list.root = face;
- ++list.count;
- }
- static inline void remove(sList& list, sFace* face)
- {
- if (face->l[1]) face->l[1]->l[0] = face->l[0];
- if (face->l[0]) face->l[0]->l[1] = face->l[1];
- if (face == list.root) list.root = face->l[1];
- --list.count;
- }
-
- void Initialize()
- {
- m_status = eStatus::Failed;
- m_normal = btVector3(0, 0, 0);
- m_depth = 0;
- m_nextsv = 0;
- for (U i = 0; i < EPA_MAX_FACES; ++i)
- {
- append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
- }
- }
- eStatus::_ Evaluate(GJK& gjk, const btVector3& guess)
- {
- GJK::sSimplex& simplex = *gjk.m_simplex;
- if ((simplex.rank > 1) && gjk.EncloseOrigin())
- {
- /* Clean up */
- while (m_hull.root)
- {
- sFace* f = m_hull.root;
- remove(m_hull, f);
- append(m_stock, f);
- }
- m_status = eStatus::Valid;
- m_nextsv = 0;
- /* Orient simplex */
- if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
- simplex.c[1]->w - simplex.c[3]->w,
- simplex.c[2]->w - simplex.c[3]->w) < 0)
- {
- btSwap(simplex.c[0], simplex.c[1]);
- btSwap(simplex.p[0], simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
- newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
- newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
- newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
- if (m_hull.count == 4)
- {
- sFace* best = findbest();
- sFace outer = *best;
- U pass = 0;
- U iterations = 0;
- bind(tetra[0], 0, tetra[1], 0);
- bind(tetra[0], 1, tetra[2], 0);
- bind(tetra[0], 2, tetra[3], 0);
- bind(tetra[1], 1, tetra[3], 2);
- bind(tetra[1], 2, tetra[2], 1);
- bind(tetra[2], 2, tetra[3], 1);
- m_status = eStatus::Valid;
- for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
- {
- if (m_nextsv < EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- sSV* w = &m_sv_store[m_nextsv++];
- bool valid = true;
- best->pass = (U1)(++pass);
- gjk.getsupport(best->n, *w);
- const btScalar wdist = btDot(best->n, w->w) - best->d;
- if (wdist > EPA_ACCURACY)
- {
- for (U j = 0; (j < 3) && valid; ++j)
- {
- valid &= expand(pass, w,
- best->f[j], best->e[j],
- horizon);
- }
- if (valid && (horizon.nf >= 3))
- {
- bind(horizon.cf, 1, horizon.ff, 2);
- remove(m_hull, best);
- append(m_stock, best);
- best = findbest();
- outer = *best;
- }
- else
- {
- m_status = eStatus::InvalidHull;
- break;
- }
- }
- else
- {
- m_status = eStatus::AccuraryReached;
- break;
- }
- }
- else
- {
- m_status = eStatus::OutOfVertices;
- break;
- }
- }
- const btVector3 projection = outer.n * outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = btCross(outer.c[1]->w - projection,
- outer.c[2]->w - projection)
- .length();
- m_result.p[1] = btCross(outer.c[2]->w - projection,
- outer.c[0]->w - projection)
- .length();
- m_result.p[2] = btCross(outer.c[0]->w - projection,
- outer.c[1]->w - projection)
- .length();
- const btScalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return (m_status);
- }
- }
- /* Fallback */
- m_status = eStatus::FallBack;
- m_normal = -guess;
- const btScalar nl = m_normal.length();
- if (nl > 0)
- m_normal = m_normal / nl;
- else
- m_normal = btVector3(1, 0, 0);
- m_depth = 0;
- m_result.rank = 1;
- m_result.c[0] = simplex.c[0];
- m_result.p[0] = 1;
- return (m_status);
- }
- bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
- {
- const btVector3 ba = b->w - a->w;
- const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if (a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const btScalar ba_l2 = ba.length2();
- const btScalar a_dot_ba = btDot(a->w, ba);
- const btScalar b_dot_ba = btDot(b->w, ba);
-
- if (a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if (b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
- }
- else
- {
- // Pick distance to edge a->b
- const btScalar a_dot_b = btDot(a->w, b->w);
- dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
- }
-
- return true;
- }
-
- return false;
- }
- sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
- {
- if (m_stock.root)
- {
- sFace* face = m_stock.root;
- remove(m_stock, face);
- append(m_hull, face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = btCross(b->w - a->w, c->w - a->w);
- const btScalar l = face->n.length();
- const bool v = l > EPA_ACCURACY;
-
- if (v)
- {
- if (!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = btDot(a->w, face->n) / l;
- }
-
- face->n /= l;
- if (forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status = eStatus::NonConvex;
- }
- else
- m_status = eStatus::Degenerated;
-
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
- }
- m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
- return 0;
- }
- sFace* findbest()
- {
- sFace* minf = m_hull.root;
- btScalar mind = minf->d * minf->d;
- for (sFace* f = minf->l[1]; f; f = f->l[1])
- {
- const btScalar sqd = f->d * f->d;
- if (sqd < mind)
- {
- minf = f;
- mind = sqd;
- }
- }
- return (minf);
- }
- bool expand(U pass, sSV* w, sFace* f, U e, sHorizon& horizon)
- {
- static const U i1m3[] = {1, 2, 0};
- static const U i2m3[] = {2, 0, 1};
- if (f->pass != pass)
- {
- const U e1 = i1m3[e];
- if ((btDot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
- {
- sFace* nf = newface(f->c[e1], f->c[e], w, false);
- if (nf)
- {
- bind(nf, 0, f, e);
- if (horizon.cf)
- bind(horizon.cf, 1, nf, 2);
- else
- horizon.ff = nf;
- horizon.cf = nf;
- ++horizon.nf;
- return (true);
- }
- }
- else
- {
- const U e2 = i2m3[e];
- f->pass = (U1)pass;
- if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
- expand(pass, w, f->f[e2], f->e[e2], horizon))
- {
- remove(m_hull, f);
- append(m_stock, f);
- return (true);
- }
- }
- }
- return (false);
- }
-};
-
-//
-static void Initialize(const btConvexShape* shape0, const btTransform& wtrs0,
- const btConvexShape* shape1, const btTransform& wtrs1,
- btGjkEpaSolver2::sResults& results,
- tShape& shape,
- bool withmargins)
-{
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = btVector3(0, 0, 0);
- results.status = btGjkEpaSolver2::sResults::Separated;
- /* Shape */
- shape.m_shapes[0] = shape0;
- shape.m_shapes[1] = shape1;
- shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
- shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
- shape.EnableMargin(withmargins);
-}
-
-} // namespace gjkepa2_impl
-
-//
-// Api
-//
-
-using namespace gjkepa2_impl;
-
-//
-int btGjkEpaSolver2::StackSizeRequirement()
-{
- return (sizeof(GJK) + sizeof(EPA));
-}
-
-//
-bool btGjkEpaSolver2::Distance(const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results)
-{
- tShape shape;
- Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, false);
- GJK gjk;
- GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
- if (gjk_status == GJK::eStatus::Valid)
- {
- btVector3 w0 = btVector3(0, 0, 0);
- btVector3 w1 = btVector3(0, 0, 0);
- for (U i = 0; i < gjk.m_simplex->rank; ++i)
- {
- const btScalar p = gjk.m_simplex->p[i];
- w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
- w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
- }
- results.witnesses[0] = wtrs0 * w0;
- results.witnesses[1] = wtrs0 * w1;
- results.normal = w0 - w1;
- results.distance = results.normal.length();
- results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
- return (true);
- }
- else
- {
- results.status = gjk_status == GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
- return (false);
- }
-}
-
-//
-bool btGjkEpaSolver2::Penetration(const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results,
- bool usemargins)
-{
- tShape shape;
- Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, usemargins);
- GJK gjk;
- GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, -guess);
- switch (gjk_status)
- {
- case GJK::eStatus::Inside:
- {
- EPA epa;
- EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
- if (epa_status != EPA::eStatus::Failed)
- {
- btVector3 w0 = btVector3(0, 0, 0);
- for (U i = 0; i < epa.m_result.rank; ++i)
- {
- w0 += shape.Support(epa.m_result.c[i]->d, 0) * epa.m_result.p[i];
- }
- results.status = sResults::Penetrating;
- results.witnesses[0] = wtrs0 * w0;
- results.witnesses[1] = wtrs0 * (w0 - epa.m_normal * epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return (true);
- }
- else
- results.status = sResults::EPA_Failed;
- }
- break;
- case GJK::eStatus::Failed:
- results.status = sResults::GJK_Failed;
- break;
- default:
- {
- }
- }
- return (false);
-}
-
-#ifndef __SPU__
-//
-btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
- btScalar margin,
- const btConvexShape* shape0,
- const btTransform& wtrs0,
- sResults& results)
-{
- tShape shape;
- btSphereShape shape1(margin);
- btTransform wtrs1(btQuaternion(0, 0, 0, 1), position);
- Initialize(shape0, wtrs0, &shape1, wtrs1, results, shape, false);
- GJK gjk;
- GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, btVector3(1, 1, 1));
- if (gjk_status == GJK::eStatus::Valid)
- {
- btVector3 w0 = btVector3(0, 0, 0);
- btVector3 w1 = btVector3(0, 0, 0);
- for (U i = 0; i < gjk.m_simplex->rank; ++i)
- {
- const btScalar p = gjk.m_simplex->p[i];
- w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
- w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
- }
- results.witnesses[0] = wtrs0 * w0;
- results.witnesses[1] = wtrs0 * w1;
- const btVector3 delta = results.witnesses[1] -
- results.witnesses[0];
- const btScalar margin = shape0->getMarginNonVirtual() +
- shape1.getMarginNonVirtual();
- const btScalar length = delta.length();
- results.normal = delta / length;
- results.witnesses[0] += results.normal * margin;
- results.distance = length - margin;
- return results.distance;
- }
- else
- {
- if (gjk_status == GJK::eStatus::Inside)
- {
- if (Penetration(shape0, wtrs0, &shape1, wtrs1, gjk.m_ray, results))
- {
- const btVector3 delta = results.witnesses[0] -
- results.witnesses[1];
- const btScalar length = delta.length();
- if (length >= SIMD_EPSILON)
- results.normal = delta / length;
- return (-length);
- }
- }
- }
- return (SIMD_INFINITY);
-}
-
-//
-bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
- const btTransform& wtrs0,
- const btConvexShape* shape1,
- const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results)
-{
- if (!Distance(shape0, wtrs0, shape1, wtrs1, guess, results))
- return (Penetration(shape0, wtrs0, shape1, wtrs1, guess, results, false));
- else
- return (true);
-}
-#endif //__SPU__
-
-/* Symbols cleanup */
-
-#undef GJK_MAX_ITERATIONS
-#undef GJK_ACCURACY
-#undef GJK_MIN_DISTANCE
-#undef GJK_DUPLICATED_EPS
-#undef GJK_SIMPLEX2_EPS
-#undef GJK_SIMPLEX3_EPS
-#undef GJK_SIMPLEX4_EPS
-
-#undef EPA_MAX_VERTICES
-#undef EPA_MAX_FACES
-#undef EPA_MAX_ITERATIONS
-#undef EPA_ACCURACY
-#undef EPA_FALLBACK
-#undef EPA_PLANE_EPS
-#undef EPA_INSIDE_EPS
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
deleted file mode 100644
index 893daea3f5..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the
-use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software in a
-product, an acknowledgment in the product documentation would be appreciated
-but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-GJK-EPA collision solver by Nathanael Presson, 2008
-*/
-#ifndef BT_GJK_EPA2_H
-#define BT_GJK_EPA2_H
-
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
-///btGjkEpaSolver contributed under zlib by Nathanael Presson
-struct btGjkEpaSolver2
-{
- struct sResults
- {
- enum eStatus
- {
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- btVector3 witnesses[2];
- btVector3 normal;
- btScalar distance;
- };
-
- static int StackSizeRequirement();
-
- static bool Distance(const btConvexShape* shape0, const btTransform& wtrs0,
- const btConvexShape* shape1, const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results);
-
- static bool Penetration(const btConvexShape* shape0, const btTransform& wtrs0,
- const btConvexShape* shape1, const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results,
- bool usemargins = true);
-#ifndef __SPU__
- static btScalar SignedDistance(const btVector3& position,
- btScalar margin,
- const btConvexShape* shape,
- const btTransform& wtrs,
- sResults& results);
-
- static bool SignedDistance(const btConvexShape* shape0, const btTransform& wtrs0,
- const btConvexShape* shape1, const btTransform& wtrs1,
- const btVector3& guess,
- sResults& results);
-#endif //__SPU__
-};
-
-#endif //BT_GJK_EPA2_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
deleted file mode 100644
index 6fedbbb3e5..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa3.h
+++ /dev/null
@@ -1,1063 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2014 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the
-use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-claim that you wrote the original software. If you use this software in a
-product, an acknowledgment in the product documentation would be appreciated
-but is not required.
-2. Altered source versions must be plainly marked as such, and must not be
-misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-Initial GJK-EPA collision solver by Nathanael Presson, 2008
-Improvements and refactoring by Erwin Coumans, 2008-2014
-*/
-#ifndef BT_GJK_EPA3_H
-#define BT_GJK_EPA3_H
-
-#include "LinearMath/btTransform.h"
-#include "btGjkCollisionDescription.h"
-
-struct btGjkEpaSolver3
-{
- struct sResults
- {
- enum eStatus
- {
- Separated, /* Shapes doesnt penetrate */
- Penetrating, /* Shapes are penetrating */
- GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */
- EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */
- } status;
- btVector3 witnesses[2];
- btVector3 normal;
- btScalar distance;
- };
-};
-
-#if defined(DEBUG) || defined(_DEBUG)
-#include <stdio.h> //for debug printf
-#ifdef __SPU__
-#include <spu_printf.h>
-#define printf spu_printf
-#endif //__SPU__
-#endif
-
-// Config
-
-/* GJK */
-#define GJK_MAX_ITERATIONS 128
-#define GJK_ACCURARY ((btScalar)0.0001)
-#define GJK_MIN_DISTANCE ((btScalar)0.0001)
-#define GJK_DUPLICATED_EPS ((btScalar)0.0001)
-#define GJK_SIMPLEX2_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX3_EPS ((btScalar)0.0)
-#define GJK_SIMPLEX4_EPS ((btScalar)0.0)
-
-/* EPA */
-#define EPA_MAX_VERTICES 64
-#define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
-#define EPA_MAX_ITERATIONS 255
-#define EPA_ACCURACY ((btScalar)0.0001)
-#define EPA_FALLBACK (10 * EPA_ACCURACY)
-#define EPA_PLANE_EPS ((btScalar)0.00001)
-#define EPA_INSIDE_EPS ((btScalar)0.01)
-
-// Shorthands
-typedef unsigned int U;
-typedef unsigned char U1;
-
-// MinkowskiDiff
-template <typename btConvexTemplate>
-struct MinkowskiDiff
-{
- const btConvexTemplate* m_convexAPtr;
- const btConvexTemplate* m_convexBPtr;
-
- btMatrix3x3 m_toshape1;
- btTransform m_toshape0;
-
- bool m_enableMargin;
-
- MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
- : m_convexAPtr(&a),
- m_convexBPtr(&b)
- {
- }
-
- void EnableMargin(bool enable)
- {
- m_enableMargin = enable;
- }
- inline btVector3 Support0(const btVector3& d) const
- {
- return m_convexAPtr->getLocalSupportWithMargin(d);
- }
- inline btVector3 Support1(const btVector3& d) const
- {
- return m_toshape0 * m_convexBPtr->getLocalSupportWithMargin(m_toshape1 * d);
- }
-
- inline btVector3 Support(const btVector3& d) const
- {
- return (Support0(d) - Support1(-d));
- }
- btVector3 Support(const btVector3& d, U index) const
- {
- if (index)
- return (Support1(d));
- else
- return (Support0(d));
- }
-};
-
-enum eGjkStatus
-{
- eGjkValid,
- eGjkInside,
- eGjkFailed
-};
-
-// GJK
-template <typename btConvexTemplate>
-struct GJK
-{
- /* Types */
- struct sSV
- {
- btVector3 d, w;
- };
- struct sSimplex
- {
- sSV* c[4];
- btScalar p[4];
- U rank;
- };
-
- /* Fields */
-
- MinkowskiDiff<btConvexTemplate> m_shape;
- btVector3 m_ray;
- btScalar m_distance;
- sSimplex m_simplices[2];
- sSV m_store[4];
- sSV* m_free[4];
- U m_nfree;
- U m_current;
- sSimplex* m_simplex;
- eGjkStatus m_status;
- /* Methods */
-
- GJK(const btConvexTemplate& a, const btConvexTemplate& b)
- : m_shape(a, b)
- {
- Initialize();
- }
- void Initialize()
- {
- m_ray = btVector3(0, 0, 0);
- m_nfree = 0;
- m_status = eGjkFailed;
- m_current = 0;
- m_distance = 0;
- }
- eGjkStatus Evaluate(const MinkowskiDiff<btConvexTemplate>& shapearg, const btVector3& guess)
- {
- U iterations = 0;
- btScalar sqdist = 0;
- btScalar alpha = 0;
- btVector3 lastw[4];
- U clastw = 0;
- /* Initialize solver */
- m_free[0] = &m_store[0];
- m_free[1] = &m_store[1];
- m_free[2] = &m_store[2];
- m_free[3] = &m_store[3];
- m_nfree = 4;
- m_current = 0;
- m_status = eGjkValid;
- m_shape = shapearg;
- m_distance = 0;
- /* Initialize simplex */
- m_simplices[0].rank = 0;
- m_ray = guess;
- const btScalar sqrl = m_ray.length2();
- appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : btVector3(1, 0, 0));
- m_simplices[0].p[0] = 1;
- m_ray = m_simplices[0].c[0]->w;
- sqdist = sqrl;
- lastw[0] =
- lastw[1] =
- lastw[2] =
- lastw[3] = m_ray;
- /* Loop */
- do
- {
- const U next = 1 - m_current;
- sSimplex& cs = m_simplices[m_current];
- sSimplex& ns = m_simplices[next];
- /* Check zero */
- const btScalar rl = m_ray.length();
- if (rl < GJK_MIN_DISTANCE)
- { /* Touching or inside */
- m_status = eGjkInside;
- break;
- }
- /* Append new vertice in -'v' direction */
- appendvertice(cs, -m_ray);
- const btVector3& w = cs.c[cs.rank - 1]->w;
- bool found = false;
- for (U i = 0; i < 4; ++i)
- {
- if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
- {
- found = true;
- break;
- }
- }
- if (found)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- else
- { /* Update lastw */
- lastw[clastw = (clastw + 1) & 3] = w;
- }
- /* Check for termination */
- const btScalar omega = btDot(m_ray, w) / rl;
- alpha = btMax(omega, alpha);
- if (((rl - alpha) - (GJK_ACCURARY * rl)) <= 0)
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- /* Reduce simplex */
- btScalar weights[4];
- U mask = 0;
- switch (cs.rank)
- {
- case 2:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- weights, mask);
- break;
- case 3:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- weights, mask);
- break;
- case 4:
- sqdist = projectorigin(cs.c[0]->w,
- cs.c[1]->w,
- cs.c[2]->w,
- cs.c[3]->w,
- weights, mask);
- break;
- }
- if (sqdist >= 0)
- { /* Valid */
- ns.rank = 0;
- m_ray = btVector3(0, 0, 0);
- m_current = next;
- for (U i = 0, ni = cs.rank; i < ni; ++i)
- {
- if (mask & (1 << i))
- {
- ns.c[ns.rank] = cs.c[i];
- ns.p[ns.rank++] = weights[i];
- m_ray += cs.c[i]->w * weights[i];
- }
- else
- {
- m_free[m_nfree++] = cs.c[i];
- }
- }
- if (mask == 15) m_status = eGjkInside;
- }
- else
- { /* Return old simplex */
- removevertice(m_simplices[m_current]);
- break;
- }
- m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eGjkFailed;
- } while (m_status == eGjkValid);
- m_simplex = &m_simplices[m_current];
- switch (m_status)
- {
- case eGjkValid:
- m_distance = m_ray.length();
- break;
- case eGjkInside:
- m_distance = 0;
- break;
- default:
- {
- }
- }
- return (m_status);
- }
- bool EncloseOrigin()
- {
- switch (m_simplex->rank)
- {
- case 1:
- {
- for (U i = 0; i < 3; ++i)
- {
- btVector3 axis = btVector3(0, 0, 0);
- axis[i] = 1;
- appendvertice(*m_simplex, axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -axis);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 2:
- {
- const btVector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
- for (U i = 0; i < 3; ++i)
- {
- btVector3 axis = btVector3(0, 0, 0);
- axis[i] = 1;
- const btVector3 p = btCross(d, axis);
- if (p.length2() > 0)
- {
- appendvertice(*m_simplex, p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -p);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- }
- break;
- case 3:
- {
- const btVector3 n = btCross(m_simplex->c[1]->w - m_simplex->c[0]->w,
- m_simplex->c[2]->w - m_simplex->c[0]->w);
- if (n.length2() > 0)
- {
- appendvertice(*m_simplex, n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- appendvertice(*m_simplex, -n);
- if (EncloseOrigin()) return (true);
- removevertice(*m_simplex);
- }
- }
- break;
- case 4:
- {
- if (btFabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
- m_simplex->c[1]->w - m_simplex->c[3]->w,
- m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
- return (true);
- }
- break;
- }
- return (false);
- }
- /* Internals */
- void getsupport(const btVector3& d, sSV& sv) const
- {
- sv.d = d / d.length();
- sv.w = m_shape.Support(sv.d);
- }
- void removevertice(sSimplex& simplex)
- {
- m_free[m_nfree++] = simplex.c[--simplex.rank];
- }
- void appendvertice(sSimplex& simplex, const btVector3& v)
- {
- simplex.p[simplex.rank] = 0;
- simplex.c[simplex.rank] = m_free[--m_nfree];
- getsupport(v, *simplex.c[simplex.rank++]);
- }
- static btScalar det(const btVector3& a, const btVector3& b, const btVector3& c)
- {
- return (a.y() * b.z() * c.x() + a.z() * b.x() * c.y() -
- a.x() * b.z() * c.y() - a.y() * b.x() * c.z() +
- a.x() * b.y() * c.z() - a.z() * b.y() * c.x());
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- btScalar* w, U& m)
- {
- const btVector3 d = b - a;
- const btScalar l = d.length2();
- if (l > GJK_SIMPLEX2_EPS)
- {
- const btScalar t(l > 0 ? -btDot(a, d) / l : 0);
- if (t >= 1)
- {
- w[0] = 0;
- w[1] = 1;
- m = 2;
- return (b.length2());
- }
- else if (t <= 0)
- {
- w[0] = 1;
- w[1] = 0;
- m = 1;
- return (a.length2());
- }
- else
- {
- w[0] = 1 - (w[1] = t);
- m = 3;
- return ((a + d * t).length2());
- }
- }
- return (-1);
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar* w, U& m)
- {
- static const U imd3[] = {1, 2, 0};
- const btVector3* vt[] = {&a, &b, &c};
- const btVector3 dl[] = {a - b, b - c, c - a};
- const btVector3 n = btCross(dl[0], dl[1]);
- const btScalar l = n.length2();
- if (l > GJK_SIMPLEX3_EPS)
- {
- btScalar mindist = -1;
- btScalar subw[2] = {0.f, 0.f};
- U subm(0);
- for (U i = 0; i < 3; ++i)
- {
- if (btDot(*vt[i], btCross(dl[i], n)) > 0)
- {
- const U j = imd3[i];
- const btScalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<U>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- }
- }
- }
- if (mindist < 0)
- {
- const btScalar d = btDot(a, n);
- const btScalar s = btSqrt(l);
- const btVector3 p = n * (d / l);
- mindist = p.length2();
- m = 7;
- w[0] = (btCross(dl[1], b - p)).length() / s;
- w[1] = (btCross(dl[2], c - p)).length() / s;
- w[2] = 1 - (w[0] + w[1]);
- }
- return (mindist);
- }
- return (-1);
- }
- static btScalar projectorigin(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& d,
- btScalar* w, U& m)
- {
- static const U imd3[] = {1, 2, 0};
- const btVector3* vt[] = {&a, &b, &c, &d};
- const btVector3 dl[] = {a - d, b - d, c - d};
- const btScalar vl = det(dl[0], dl[1], dl[2]);
- const bool ng = (vl * btDot(a, btCross(b - c, a - b))) <= 0;
- if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
- {
- btScalar mindist = -1;
- btScalar subw[3] = {0.f, 0.f, 0.f};
- U subm(0);
- for (U i = 0; i < 3; ++i)
- {
- const U j = imd3[i];
- const btScalar s = vl * btDot(d, btCross(dl[i], dl[j]));
- if (s > 0)
- {
- const btScalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
- if ((mindist < 0) || (subd < mindist))
- {
- mindist = subd;
- m = static_cast<U>((subm & 1 ? 1 << i : 0) +
- (subm & 2 ? 1 << j : 0) +
- (subm & 4 ? 8 : 0));
- w[i] = subw[0];
- w[j] = subw[1];
- w[imd3[j]] = 0;
- w[3] = subw[2];
- }
- }
- }
- if (mindist < 0)
- {
- mindist = 0;
- m = 15;
- w[0] = det(c, b, d) / vl;
- w[1] = det(a, c, d) / vl;
- w[2] = det(b, a, d) / vl;
- w[3] = 1 - (w[0] + w[1] + w[2]);
- }
- return (mindist);
- }
- return (-1);
- }
-};
-
-enum eEpaStatus
-{
- eEpaValid,
- eEpaTouching,
- eEpaDegenerated,
- eEpaNonConvex,
- eEpaInvalidHull,
- eEpaOutOfFaces,
- eEpaOutOfVertices,
- eEpaAccuraryReached,
- eEpaFallBack,
- eEpaFailed
-};
-
-// EPA
-template <typename btConvexTemplate>
-struct EPA
-{
- /* Types */
-
- struct sFace
- {
- btVector3 n;
- btScalar d;
- typename GJK<btConvexTemplate>::sSV* c[3];
- sFace* f[3];
- sFace* l[2];
- U1 e[3];
- U1 pass;
- };
- struct sList
- {
- sFace* root;
- U count;
- sList() : root(0), count(0) {}
- };
- struct sHorizon
- {
- sFace* cf;
- sFace* ff;
- U nf;
- sHorizon() : cf(0), ff(0), nf(0) {}
- };
-
- /* Fields */
- eEpaStatus m_status;
- typename GJK<btConvexTemplate>::sSimplex m_result;
- btVector3 m_normal;
- btScalar m_depth;
- typename GJK<btConvexTemplate>::sSV m_sv_store[EPA_MAX_VERTICES];
- sFace m_fc_store[EPA_MAX_FACES];
- U m_nextsv;
- sList m_hull;
- sList m_stock;
- /* Methods */
- EPA()
- {
- Initialize();
- }
-
- static inline void bind(sFace* fa, U ea, sFace* fb, U eb)
- {
- fa->e[ea] = (U1)eb;
- fa->f[ea] = fb;
- fb->e[eb] = (U1)ea;
- fb->f[eb] = fa;
- }
- static inline void append(sList& list, sFace* face)
- {
- face->l[0] = 0;
- face->l[1] = list.root;
- if (list.root) list.root->l[0] = face;
- list.root = face;
- ++list.count;
- }
- static inline void remove(sList& list, sFace* face)
- {
- if (face->l[1]) face->l[1]->l[0] = face->l[0];
- if (face->l[0]) face->l[0]->l[1] = face->l[1];
- if (face == list.root) list.root = face->l[1];
- --list.count;
- }
-
- void Initialize()
- {
- m_status = eEpaFailed;
- m_normal = btVector3(0, 0, 0);
- m_depth = 0;
- m_nextsv = 0;
- for (U i = 0; i < EPA_MAX_FACES; ++i)
- {
- append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
- }
- }
- eEpaStatus Evaluate(GJK<btConvexTemplate>& gjk, const btVector3& guess)
- {
- typename GJK<btConvexTemplate>::sSimplex& simplex = *gjk.m_simplex;
- if ((simplex.rank > 1) && gjk.EncloseOrigin())
- {
- /* Clean up */
- while (m_hull.root)
- {
- sFace* f = m_hull.root;
- remove(m_hull, f);
- append(m_stock, f);
- }
- m_status = eEpaValid;
- m_nextsv = 0;
- /* Orient simplex */
- if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
- simplex.c[1]->w - simplex.c[3]->w,
- simplex.c[2]->w - simplex.c[3]->w) < 0)
- {
- btSwap(simplex.c[0], simplex.c[1]);
- btSwap(simplex.p[0], simplex.p[1]);
- }
- /* Build initial hull */
- sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
- newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
- newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
- newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
- if (m_hull.count == 4)
- {
- sFace* best = findbest();
- sFace outer = *best;
- U pass = 0;
- U iterations = 0;
- bind(tetra[0], 0, tetra[1], 0);
- bind(tetra[0], 1, tetra[2], 0);
- bind(tetra[0], 2, tetra[3], 0);
- bind(tetra[1], 1, tetra[3], 2);
- bind(tetra[1], 2, tetra[2], 1);
- bind(tetra[2], 2, tetra[3], 1);
- m_status = eEpaValid;
- for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
- {
- if (m_nextsv < EPA_MAX_VERTICES)
- {
- sHorizon horizon;
- typename GJK<btConvexTemplate>::sSV* w = &m_sv_store[m_nextsv++];
- bool valid = true;
- best->pass = (U1)(++pass);
- gjk.getsupport(best->n, *w);
- const btScalar wdist = btDot(best->n, w->w) - best->d;
- if (wdist > EPA_ACCURACY)
- {
- for (U j = 0; (j < 3) && valid; ++j)
- {
- valid &= expand(pass, w,
- best->f[j], best->e[j],
- horizon);
- }
- if (valid && (horizon.nf >= 3))
- {
- bind(horizon.cf, 1, horizon.ff, 2);
- remove(m_hull, best);
- append(m_stock, best);
- best = findbest();
- outer = *best;
- }
- else
- {
- m_status = eEpaInvalidHull;
- break;
- }
- }
- else
- {
- m_status = eEpaAccuraryReached;
- break;
- }
- }
- else
- {
- m_status = eEpaOutOfVertices;
- break;
- }
- }
- const btVector3 projection = outer.n * outer.d;
- m_normal = outer.n;
- m_depth = outer.d;
- m_result.rank = 3;
- m_result.c[0] = outer.c[0];
- m_result.c[1] = outer.c[1];
- m_result.c[2] = outer.c[2];
- m_result.p[0] = btCross(outer.c[1]->w - projection,
- outer.c[2]->w - projection)
- .length();
- m_result.p[1] = btCross(outer.c[2]->w - projection,
- outer.c[0]->w - projection)
- .length();
- m_result.p[2] = btCross(outer.c[0]->w - projection,
- outer.c[1]->w - projection)
- .length();
- const btScalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
- m_result.p[0] /= sum;
- m_result.p[1] /= sum;
- m_result.p[2] /= sum;
- return (m_status);
- }
- }
- /* Fallback */
- m_status = eEpaFallBack;
- m_normal = -guess;
- const btScalar nl = m_normal.length();
- if (nl > 0)
- m_normal = m_normal / nl;
- else
- m_normal = btVector3(1, 0, 0);
- m_depth = 0;
- m_result.rank = 1;
- m_result.c[0] = simplex.c[0];
- m_result.p[0] = 1;
- return (m_status);
- }
- bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
- {
- const btVector3 ba = b->w - a->w;
- const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
- const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
-
- if (a_dot_nab < 0)
- {
- // Outside of edge a->b
-
- const btScalar ba_l2 = ba.length2();
- const btScalar a_dot_ba = btDot(a->w, ba);
- const btScalar b_dot_ba = btDot(b->w, ba);
-
- if (a_dot_ba > 0)
- {
- // Pick distance vertex a
- dist = a->w.length();
- }
- else if (b_dot_ba < 0)
- {
- // Pick distance vertex b
- dist = b->w.length();
- }
- else
- {
- // Pick distance to edge a->b
- const btScalar a_dot_b = btDot(a->w, b->w);
- dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
- }
-
- return true;
- }
-
- return false;
- }
- sFace* newface(typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, typename GJK<btConvexTemplate>::sSV* c, bool forced)
- {
- if (m_stock.root)
- {
- sFace* face = m_stock.root;
- remove(m_stock, face);
- append(m_hull, face);
- face->pass = 0;
- face->c[0] = a;
- face->c[1] = b;
- face->c[2] = c;
- face->n = btCross(b->w - a->w, c->w - a->w);
- const btScalar l = face->n.length();
- const bool v = l > EPA_ACCURACY;
-
- if (v)
- {
- if (!(getedgedist(face, a, b, face->d) ||
- getedgedist(face, b, c, face->d) ||
- getedgedist(face, c, a, face->d)))
- {
- // Origin projects to the interior of the triangle
- // Use distance to triangle plane
- face->d = btDot(a->w, face->n) / l;
- }
-
- face->n /= l;
- if (forced || (face->d >= -EPA_PLANE_EPS))
- {
- return face;
- }
- else
- m_status = eEpaNonConvex;
- }
- else
- m_status = eEpaDegenerated;
-
- remove(m_hull, face);
- append(m_stock, face);
- return 0;
- }
- m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
- return 0;
- }
- sFace* findbest()
- {
- sFace* minf = m_hull.root;
- btScalar mind = minf->d * minf->d;
- for (sFace* f = minf->l[1]; f; f = f->l[1])
- {
- const btScalar sqd = f->d * f->d;
- if (sqd < mind)
- {
- minf = f;
- mind = sqd;
- }
- }
- return (minf);
- }
- bool expand(U pass, typename GJK<btConvexTemplate>::sSV* w, sFace* f, U e, sHorizon& horizon)
- {
- static const U i1m3[] = {1, 2, 0};
- static const U i2m3[] = {2, 0, 1};
- if (f->pass != pass)
- {
- const U e1 = i1m3[e];
- if ((btDot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
- {
- sFace* nf = newface(f->c[e1], f->c[e], w, false);
- if (nf)
- {
- bind(nf, 0, f, e);
- if (horizon.cf)
- bind(horizon.cf, 1, nf, 2);
- else
- horizon.ff = nf;
- horizon.cf = nf;
- ++horizon.nf;
- return (true);
- }
- }
- else
- {
- const U e2 = i2m3[e];
- f->pass = (U1)pass;
- if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
- expand(pass, w, f->f[e2], f->e[e2], horizon))
- {
- remove(m_hull, f);
- append(m_stock, f);
- return (true);
- }
- }
- }
- return (false);
- }
-};
-
-template <typename btConvexTemplate>
-static void Initialize(const btConvexTemplate& a, const btConvexTemplate& b,
- btGjkEpaSolver3::sResults& results,
- MinkowskiDiff<btConvexTemplate>& shape)
-{
- /* Results */
- results.witnesses[0] =
- results.witnesses[1] = btVector3(0, 0, 0);
- results.status = btGjkEpaSolver3::sResults::Separated;
- /* Shape */
-
- shape.m_toshape1 = b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
- shape.m_toshape0 = a.getWorldTransform().inverseTimes(b.getWorldTransform());
-}
-
-//
-// Api
-//
-
-//
-template <typename btConvexTemplate>
-bool btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
- const btVector3& guess,
- btGjkEpaSolver3::sResults& results)
-{
- MinkowskiDiff<btConvexTemplate> shape(a, b);
- Initialize(a, b, results, shape);
- GJK<btConvexTemplate> gjk(a, b);
- eGjkStatus gjk_status = gjk.Evaluate(shape, guess);
- if (gjk_status == eGjkValid)
- {
- btVector3 w0 = btVector3(0, 0, 0);
- btVector3 w1 = btVector3(0, 0, 0);
- for (U i = 0; i < gjk.m_simplex->rank; ++i)
- {
- const btScalar p = gjk.m_simplex->p[i];
- w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
- w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
- }
- results.witnesses[0] = a.getWorldTransform() * w0;
- results.witnesses[1] = a.getWorldTransform() * w1;
- results.normal = w0 - w1;
- results.distance = results.normal.length();
- results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
- return (true);
- }
- else
- {
- results.status = gjk_status == eGjkInside ? btGjkEpaSolver3::sResults::Penetrating : btGjkEpaSolver3::sResults::GJK_Failed;
- return (false);
- }
-}
-
-template <typename btConvexTemplate>
-bool btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
- const btConvexTemplate& b,
- const btVector3& guess,
- btGjkEpaSolver3::sResults& results)
-{
- MinkowskiDiff<btConvexTemplate> shape(a, b);
- Initialize(a, b, results, shape);
- GJK<btConvexTemplate> gjk(a, b);
- eGjkStatus gjk_status = gjk.Evaluate(shape, -guess);
- switch (gjk_status)
- {
- case eGjkInside:
- {
- EPA<btConvexTemplate> epa;
- eEpaStatus epa_status = epa.Evaluate(gjk, -guess);
- if (epa_status != eEpaFailed)
- {
- btVector3 w0 = btVector3(0, 0, 0);
- for (U i = 0; i < epa.m_result.rank; ++i)
- {
- w0 += shape.Support(epa.m_result.c[i]->d, 0) * epa.m_result.p[i];
- }
- results.status = btGjkEpaSolver3::sResults::Penetrating;
- results.witnesses[0] = a.getWorldTransform() * w0;
- results.witnesses[1] = a.getWorldTransform() * (w0 - epa.m_normal * epa.m_depth);
- results.normal = -epa.m_normal;
- results.distance = -epa.m_depth;
- return (true);
- }
- else
- results.status = btGjkEpaSolver3::sResults::EPA_Failed;
- }
- break;
- case eGjkFailed:
- results.status = btGjkEpaSolver3::sResults::GJK_Failed;
- break;
- default:
- {
- }
- }
- return (false);
-}
-
-#if 0
-int btComputeGjkEpaPenetration2(const btCollisionDescription& colDesc, btDistanceInfo* distInfo)
-{
- btGjkEpaSolver3::sResults results;
- btVector3 guess = colDesc.m_firstDir;
-
- bool res = btGjkEpaSolver3::Penetration(colDesc.m_objA,colDesc.m_objB,
- colDesc.m_transformA,colDesc.m_transformB,
- colDesc.m_localSupportFuncA,colDesc.m_localSupportFuncB,
- guess,
- results);
- if (res)
- {
- if ((results.status==btGjkEpaSolver3::sResults::Penetrating) || results.status==GJK::eStatus::Inside)
- {
- //normal could be 'swapped'
-
- distInfo->m_distance = results.distance;
- distInfo->m_normalBtoA = results.normal;
- btVector3 tmpNormalInB = results.witnesses[1]-results.witnesses[0];
- btScalar lenSqr = tmpNormalInB.length2();
- if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
- {
- tmpNormalInB = results.normal;
- lenSqr = results.normal.length2();
- }
-
- if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
- {
- tmpNormalInB /= btSqrt(lenSqr);
- btScalar distance2 = -(results.witnesses[0]-results.witnesses[1]).length();
- //only replace valid penetrations when the result is deeper (check)
- //if ((distance2 < results.distance))
- {
- distInfo->m_distance = distance2;
- distInfo->m_pointOnA= results.witnesses[0];
- distInfo->m_pointOnB= results.witnesses[1];
- distInfo->m_normalBtoA= tmpNormalInB;
- return 0;
- }
- }
- }
-
- }
-
- return -1;
-}
-#endif
-
-template <typename btConvexTemplate, typename btDistanceInfoTemplate>
-int btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
- const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
-{
- btGjkEpaSolver3::sResults results;
- btVector3 guess = colDesc.m_firstDir;
-
- bool isSeparated = btGjkEpaSolver3_Distance(a, b,
- guess,
- results);
- if (isSeparated)
- {
- distInfo->m_distance = results.distance;
- distInfo->m_pointOnA = results.witnesses[0];
- distInfo->m_pointOnB = results.witnesses[1];
- distInfo->m_normalBtoA = results.normal;
- return 0;
- }
-
- return -1;
-}
-
-/* Symbols cleanup */
-
-#undef GJK_MAX_ITERATIONS
-#undef GJK_ACCURARY
-#undef GJK_MIN_DISTANCE
-#undef GJK_DUPLICATED_EPS
-#undef GJK_SIMPLEX2_EPS
-#undef GJK_SIMPLEX3_EPS
-#undef GJK_SIMPLEX4_EPS
-
-#undef EPA_MAX_VERTICES
-#undef EPA_MAX_FACES
-#undef EPA_MAX_ITERATIONS
-#undef EPA_ACCURACY
-#undef EPA_FALLBACK
-#undef EPA_PLANE_EPS
-#undef EPA_INSIDE_EPS
-
-#endif //BT_GJK_EPA3_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
deleted file mode 100644
index 07629229ab..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-EPA Copyright (c) Ricardo Padrela 2006
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "btGjkEpaPenetrationDepthSolver.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-
-bool btGjkEpaPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* pConvexA, const btConvexShape* pConvexB,
- const btTransform& transformA, const btTransform& transformB,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
- class btIDebugDraw* debugDraw)
-{
- (void)debugDraw;
- (void)v;
- (void)simplexSolver;
-
- btVector3 guessVectors[] = {
- btVector3(transformB.getOrigin() - transformA.getOrigin()).safeNormalize(),
- btVector3(transformA.getOrigin() - transformB.getOrigin()).safeNormalize(),
- btVector3(0, 0, 1),
- btVector3(0, 1, 0),
- btVector3(1, 0, 0),
- btVector3(1, 1, 0),
- btVector3(1, 1, 1),
- btVector3(0, 1, 1),
- btVector3(1, 0, 1),
- };
-
- int numVectors = sizeof(guessVectors) / sizeof(btVector3);
-
- for (int i = 0; i < numVectors; i++)
- {
- simplexSolver.reset();
- btVector3 guessVector = guessVectors[i];
-
- btGjkEpaSolver2::sResults results;
-
- if (btGjkEpaSolver2::Penetration(pConvexA, transformA,
- pConvexB, transformB,
- guessVector, results))
-
- {
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return true;
- }
- else
- {
- if (btGjkEpaSolver2::Distance(pConvexA, transformA, pConvexB, transformB, guessVector, results))
- {
- wWitnessOnA = results.witnesses[0];
- wWitnessOnB = results.witnesses[1];
- v = results.normal;
- return false;
- }
- }
- }
-
- //failed to find a distance/penetration
- wWitnessOnA.setValue(0, 0, 0);
- wWitnessOnB.setValue(0, 0, 0);
- v.setValue(0, 0, 0);
- return false;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
deleted file mode 100644
index 92d6df1729..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-EPA Copyright (c) Ricardo Padrela 2006
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H
-#define BT_GJP_EPA_PENETRATION_DEPTH_H
-
-#include "btConvexPenetrationDepthSolver.h"
-
-///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to
-///calculate the penetration depth between two convex shapes.
-class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
-{
-public:
- btGjkEpaPenetrationDepthSolver()
- {
- }
-
- bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* pConvexA, const btConvexShape* pConvexB,
- const btTransform& transformA, const btTransform& transformB,
- btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
- class btIDebugDraw* debugDraw);
-
-private:
-};
-
-#endif // BT_GJP_EPA_PENETRATION_DEPTH_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
deleted file mode 100644
index 5af93cb2fb..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
+++ /dev/null
@@ -1,1183 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGjkPairDetector.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
-#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
-
-#if defined(DEBUG) || defined(_DEBUG)
-//#define TEST_NON_VIRTUAL 1
-#include <stdio.h> //for debug printf
-#ifdef __SPU__
-#include <spu_printf.h>
-#define printf spu_printf
-#endif //__SPU__
-#endif
-
-//must be above the machine epsilon
-#ifdef BT_USE_DOUBLE_PRECISION
-#define REL_ERROR2 btScalar(1.0e-12)
-btScalar gGjkEpaPenetrationTolerance = 1.0e-12;
-#else
-#define REL_ERROR2 btScalar(1.0e-6)
-btScalar gGjkEpaPenetrationTolerance = 0.001;
-#endif
-
-
-btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
- : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
- m_penetrationDepthSolver(penetrationDepthSolver),
- m_simplexSolver(simplexSolver),
- m_minkowskiA(objectA),
- m_minkowskiB(objectB),
- m_shapeTypeA(objectA->getShapeType()),
- m_shapeTypeB(objectB->getShapeType()),
- m_marginA(objectA->getMargin()),
- m_marginB(objectB->getMargin()),
- m_ignoreMargin(false),
- m_lastUsedMethod(-1),
- m_catchDegeneracies(1),
- m_fixContactNormalDirection(1)
-{
-}
-btGjkPairDetector::btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
- : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.)),
- m_penetrationDepthSolver(penetrationDepthSolver),
- m_simplexSolver(simplexSolver),
- m_minkowskiA(objectA),
- m_minkowskiB(objectB),
- m_shapeTypeA(shapeTypeA),
- m_shapeTypeB(shapeTypeB),
- m_marginA(marginA),
- m_marginB(marginB),
- m_ignoreMargin(false),
- m_lastUsedMethod(-1),
- m_catchDegeneracies(1),
- m_fixContactNormalDirection(1)
-{
-}
-
-void btGjkPairDetector::getClosestPoints(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw, bool swapResults)
-{
- (void)swapResults;
-
- getClosestPointsNonVirtual(input, output, debugDraw);
-}
-
-static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
-{
- btVector3 separatingAxisInA = (dir)*localTransA.getBasis();
- btVector3 separatingAxisInB = (-dir) * localTransB.getBasis();
-
- btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
-
- btVector3 pInA = pInANoMargin;
- btVector3 qInB = qInBNoMargin;
-
- supAworld = localTransA(pInA);
- supBworld = localTransB(qInB);
-
- if (check2d)
- {
- supAworld[2] = 0.f;
- supBworld[2] = 0.f;
- }
-
- aMinb = supAworld - supBworld;
-}
-
-struct btSupportVector
-{
- btVector3 v; //!< Support point in minkowski sum
- btVector3 v1; //!< Support point in obj1
- btVector3 v2; //!< Support point in obj2
-};
-
-struct btSimplex
-{
- btSupportVector ps[4];
- int last; //!< index of last added point
-};
-
-static btVector3 ccd_vec3_origin(0, 0, 0);
-
-inline void btSimplexInit(btSimplex *s)
-{
- s->last = -1;
-}
-
-inline int btSimplexSize(const btSimplex *s)
-{
- return s->last + 1;
-}
-
-inline const btSupportVector *btSimplexPoint(const btSimplex *s, int idx)
-{
- // here is no check on boundaries
- return &s->ps[idx];
-}
-inline void btSupportCopy(btSupportVector *d, const btSupportVector *s)
-{
- *d = *s;
-}
-
-inline void btVec3Copy(btVector3 *v, const btVector3 *w)
-{
- *v = *w;
-}
-
-inline void ccdVec3Add(btVector3 *v, const btVector3 *w)
-{
- v->m_floats[0] += w->m_floats[0];
- v->m_floats[1] += w->m_floats[1];
- v->m_floats[2] += w->m_floats[2];
-}
-
-inline void ccdVec3Sub(btVector3 *v, const btVector3 *w)
-{
- *v -= *w;
-}
-inline void btVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
-{
- *d = (*v) - (*w);
-}
-inline btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
-{
- btScalar dot;
- dot = a->dot(*b);
-
- return dot;
-}
-
-inline btScalar ccdVec3Dist2(const btVector3 *a, const btVector3 *b)
-{
- btVector3 ab;
- btVec3Sub2(&ab, a, b);
- return btVec3Dot(&ab, &ab);
-}
-
-inline void btVec3Scale(btVector3 *d, btScalar k)
-{
- d->m_floats[0] *= k;
- d->m_floats[1] *= k;
- d->m_floats[2] *= k;
-}
-
-inline void btVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
-{
- d->m_floats[0] = (a->m_floats[1] * b->m_floats[2]) - (a->m_floats[2] * b->m_floats[1]);
- d->m_floats[1] = (a->m_floats[2] * b->m_floats[0]) - (a->m_floats[0] * b->m_floats[2]);
- d->m_floats[2] = (a->m_floats[0] * b->m_floats[1]) - (a->m_floats[1] * b->m_floats[0]);
-}
-
-inline void btTripleCross(const btVector3 *a, const btVector3 *b,
- const btVector3 *c, btVector3 *d)
-{
- btVector3 e;
- btVec3Cross(&e, a, b);
- btVec3Cross(d, &e, c);
-}
-
-inline int ccdEq(btScalar _a, btScalar _b)
-{
- btScalar ab;
- btScalar a, b;
-
- ab = btFabs(_a - _b);
- if (btFabs(ab) < SIMD_EPSILON)
- return 1;
-
- a = btFabs(_a);
- b = btFabs(_b);
- if (b > a)
- {
- return ab < SIMD_EPSILON * b;
- }
- else
- {
- return ab < SIMD_EPSILON * a;
- }
-}
-
-btScalar ccdVec3X(const btVector3 *v)
-{
- return v->x();
-}
-
-btScalar ccdVec3Y(const btVector3 *v)
-{
- return v->y();
-}
-
-btScalar ccdVec3Z(const btVector3 *v)
-{
- return v->z();
-}
-inline int btVec3Eq(const btVector3 *a, const btVector3 *b)
-{
- return ccdEq(ccdVec3X(a), ccdVec3X(b)) && ccdEq(ccdVec3Y(a), ccdVec3Y(b)) && ccdEq(ccdVec3Z(a), ccdVec3Z(b));
-}
-
-inline void btSimplexAdd(btSimplex *s, const btSupportVector *v)
-{
- // here is no check on boundaries in sake of speed
- ++s->last;
- btSupportCopy(s->ps + s->last, v);
-}
-
-inline void btSimplexSet(btSimplex *s, size_t pos, const btSupportVector *a)
-{
- btSupportCopy(s->ps + pos, a);
-}
-
-inline void btSimplexSetSize(btSimplex *s, int size)
-{
- s->last = size - 1;
-}
-
-inline const btSupportVector *ccdSimplexLast(const btSimplex *s)
-{
- return btSimplexPoint(s, s->last);
-}
-
-inline int ccdSign(btScalar val)
-{
- if (btFuzzyZero(val))
- {
- return 0;
- }
- else if (val < btScalar(0))
- {
- return -1;
- }
- return 1;
-}
-
-inline btScalar btVec3PointSegmentDist2(const btVector3 *P,
- const btVector3 *x0,
- const btVector3 *b,
- btVector3 *witness)
-{
- // The computation comes from solving equation of segment:
- // S(t) = x0 + t.d
- // where - x0 is initial point of segment
- // - d is direction of segment from x0 (|d| > 0)
- // - t belongs to <0, 1> interval
- //
- // Than, distance from a segment to some point P can be expressed:
- // D(t) = |x0 + t.d - P|^2
- // which is distance from any point on segment. Minimization
- // of this function brings distance from P to segment.
- // Minimization of D(t) leads to simple quadratic equation that's
- // solving is straightforward.
- //
- // Bonus of this method is witness point for free.
-
- btScalar dist, t;
- btVector3 d, a;
-
- // direction of segment
- btVec3Sub2(&d, b, x0);
-
- // precompute vector from P to x0
- btVec3Sub2(&a, x0, P);
-
- t = -btScalar(1.) * btVec3Dot(&a, &d);
- t /= btVec3Dot(&d, &d);
-
- if (t < btScalar(0) || btFuzzyZero(t))
- {
- dist = ccdVec3Dist2(x0, P);
- if (witness)
- btVec3Copy(witness, x0);
- }
- else if (t > btScalar(1) || ccdEq(t, btScalar(1)))
- {
- dist = ccdVec3Dist2(b, P);
- if (witness)
- btVec3Copy(witness, b);
- }
- else
- {
- if (witness)
- {
- btVec3Copy(witness, &d);
- btVec3Scale(witness, t);
- ccdVec3Add(witness, x0);
- dist = ccdVec3Dist2(witness, P);
- }
- else
- {
- // recycling variables
- btVec3Scale(&d, t);
- ccdVec3Add(&d, &a);
- dist = btVec3Dot(&d, &d);
- }
- }
-
- return dist;
-}
-
-btScalar btVec3PointTriDist2(const btVector3 *P,
- const btVector3 *x0, const btVector3 *B,
- const btVector3 *C,
- btVector3 *witness)
-{
- // Computation comes from analytic expression for triangle (x0, B, C)
- // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
- // Then equation for distance is:
- // D(s, t) = | T(s, t) - P |^2
- // This leads to minimization of quadratic function of two variables.
- // The solution from is taken only if s is between 0 and 1, t is
- // between 0 and 1 and t + s < 1, otherwise distance from segment is
- // computed.
-
- btVector3 d1, d2, a;
- double u, v, w, p, q, r;
- double s, t, dist, dist2;
- btVector3 witness2;
-
- btVec3Sub2(&d1, B, x0);
- btVec3Sub2(&d2, C, x0);
- btVec3Sub2(&a, x0, P);
-
- u = btVec3Dot(&a, &a);
- v = btVec3Dot(&d1, &d1);
- w = btVec3Dot(&d2, &d2);
- p = btVec3Dot(&a, &d1);
- q = btVec3Dot(&a, &d2);
- r = btVec3Dot(&d1, &d2);
-
- s = (q * r - w * p) / (w * v - r * r);
- t = (-s * r - q) / w;
-
- if ((btFuzzyZero(s) || s > btScalar(0)) && (ccdEq(s, btScalar(1)) || s < btScalar(1)) && (btFuzzyZero(t) || t > btScalar(0)) && (ccdEq(t, btScalar(1)) || t < btScalar(1)) && (ccdEq(t + s, btScalar(1)) || t + s < btScalar(1)))
- {
- if (witness)
- {
- btVec3Scale(&d1, s);
- btVec3Scale(&d2, t);
- btVec3Copy(witness, x0);
- ccdVec3Add(witness, &d1);
- ccdVec3Add(witness, &d2);
-
- dist = ccdVec3Dist2(witness, P);
- }
- else
- {
- dist = s * s * v;
- dist += t * t * w;
- dist += btScalar(2.) * s * t * r;
- dist += btScalar(2.) * s * p;
- dist += btScalar(2.) * t * q;
- dist += u;
- }
- }
- else
- {
- dist = btVec3PointSegmentDist2(P, x0, B, witness);
-
- dist2 = btVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- btVec3Copy(witness, &witness2);
- }
-
- dist2 = btVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- btVec3Copy(witness, &witness2);
- }
- }
-
- return dist;
-}
-
-static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
-{
- const btSupportVector *A, *B;
- btVector3 AB, AO, tmp;
- btScalar dot;
-
- // get last added as A
- A = ccdSimplexLast(simplex);
- // get the other point
- B = btSimplexPoint(simplex, 0);
- // compute AB oriented segment
- btVec3Sub2(&AB, &B->v, &A->v);
- // compute AO vector
- btVec3Copy(&AO, &A->v);
- btVec3Scale(&AO, -btScalar(1));
-
- // dot product AB . AO
- dot = btVec3Dot(&AB, &AO);
-
- // check if origin doesn't lie on AB segment
- btVec3Cross(&tmp, &AB, &AO);
- if (btFuzzyZero(btVec3Dot(&tmp, &tmp)) && dot > btScalar(0))
- {
- return 1;
- }
-
- // check if origin is in area where AB segment is
- if (btFuzzyZero(dot) || dot < btScalar(0))
- {
- // origin is in outside are of A
- btSimplexSet(simplex, 0, A);
- btSimplexSetSize(simplex, 1);
- btVec3Copy(dir, &AO);
- }
- else
- {
- // origin is in area where AB segment is
-
- // keep simplex untouched and set direction to
- // AB x AO x AB
- btTripleCross(&AB, &AO, &AB, dir);
- }
-
- return 0;
-}
-
-static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
-{
- const btSupportVector *A, *B, *C;
- btVector3 AO, AB, AC, ABC, tmp;
- btScalar dot, dist;
-
- // get last added as A
- A = ccdSimplexLast(simplex);
- // get the other points
- B = btSimplexPoint(simplex, 1);
- C = btSimplexPoint(simplex, 0);
-
- // check touching contact
- dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
- if (btFuzzyZero(dist))
- {
- return 1;
- }
-
- // check if triangle is really triangle (has area > 0)
- // if not simplex can't be expanded and thus no itersection is found
- if (btVec3Eq(&A->v, &B->v) || btVec3Eq(&A->v, &C->v))
- {
- return -1;
- }
-
- // compute AO vector
- btVec3Copy(&AO, &A->v);
- btVec3Scale(&AO, -btScalar(1));
-
- // compute AB and AC segments and ABC vector (perpendircular to triangle)
- btVec3Sub2(&AB, &B->v, &A->v);
- btVec3Sub2(&AC, &C->v, &A->v);
- btVec3Cross(&ABC, &AB, &AC);
-
- btVec3Cross(&tmp, &ABC, &AC);
- dot = btVec3Dot(&tmp, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- dot = btVec3Dot(&AC, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- // C is already in place
- btSimplexSet(simplex, 1, A);
- btSimplexSetSize(simplex, 2);
- btTripleCross(&AC, &AO, &AC, dir);
- }
- else
- {
- dot = btVec3Dot(&AB, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- btSimplexSet(simplex, 0, B);
- btSimplexSet(simplex, 1, A);
- btSimplexSetSize(simplex, 2);
- btTripleCross(&AB, &AO, &AB, dir);
- }
- else
- {
- btSimplexSet(simplex, 0, A);
- btSimplexSetSize(simplex, 1);
- btVec3Copy(dir, &AO);
- }
- }
- }
- else
- {
- btVec3Cross(&tmp, &AB, &ABC);
- dot = btVec3Dot(&tmp, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- dot = btVec3Dot(&AB, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- btSimplexSet(simplex, 0, B);
- btSimplexSet(simplex, 1, A);
- btSimplexSetSize(simplex, 2);
- btTripleCross(&AB, &AO, &AB, dir);
- }
- else
- {
- btSimplexSet(simplex, 0, A);
- btSimplexSetSize(simplex, 1);
- btVec3Copy(dir, &AO);
- }
- }
- else
- {
- dot = btVec3Dot(&ABC, &AO);
- if (btFuzzyZero(dot) || dot > btScalar(0))
- {
- btVec3Copy(dir, &ABC);
- }
- else
- {
- btSupportVector tmp;
- btSupportCopy(&tmp, C);
- btSimplexSet(simplex, 0, B);
- btSimplexSet(simplex, 1, &tmp);
-
- btVec3Copy(dir, &ABC);
- btVec3Scale(dir, -btScalar(1));
- }
- }
- }
-
- return 0;
-}
-
-static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
-{
- const btSupportVector *A, *B, *C, *D;
- btVector3 AO, AB, AC, AD, ABC, ACD, ADB;
- int B_on_ACD, C_on_ADB, D_on_ABC;
- int AB_O, AC_O, AD_O;
- btScalar dist;
-
- // get last added as A
- A = ccdSimplexLast(simplex);
- // get the other points
- B = btSimplexPoint(simplex, 2);
- C = btSimplexPoint(simplex, 1);
- D = btSimplexPoint(simplex, 0);
-
- // check if tetrahedron is really tetrahedron (has volume > 0)
- // if it is not simplex can't be expanded and thus no intersection is
- // found
- dist = btVec3PointTriDist2(&A->v, &B->v, &C->v, &D->v, 0);
- if (btFuzzyZero(dist))
- {
- return -1;
- }
-
- // check if origin lies on some of tetrahedron's face - if so objects
- // intersect
- dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
- if (btFuzzyZero(dist))
- return 1;
- dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &C->v, &D->v, 0);
- if (btFuzzyZero(dist))
- return 1;
- dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &D->v, 0);
- if (btFuzzyZero(dist))
- return 1;
- dist = btVec3PointTriDist2(&ccd_vec3_origin, &B->v, &C->v, &D->v, 0);
- if (btFuzzyZero(dist))
- return 1;
-
- // compute AO, AB, AC, AD segments and ABC, ACD, ADB normal vectors
- btVec3Copy(&AO, &A->v);
- btVec3Scale(&AO, -btScalar(1));
- btVec3Sub2(&AB, &B->v, &A->v);
- btVec3Sub2(&AC, &C->v, &A->v);
- btVec3Sub2(&AD, &D->v, &A->v);
- btVec3Cross(&ABC, &AB, &AC);
- btVec3Cross(&ACD, &AC, &AD);
- btVec3Cross(&ADB, &AD, &AB);
-
- // side (positive or negative) of B, C, D relative to planes ACD, ADB
- // and ABC respectively
- B_on_ACD = ccdSign(btVec3Dot(&ACD, &AB));
- C_on_ADB = ccdSign(btVec3Dot(&ADB, &AC));
- D_on_ABC = ccdSign(btVec3Dot(&ABC, &AD));
-
- // whether origin is on same side of ACD, ADB, ABC as B, C, D
- // respectively
- AB_O = ccdSign(btVec3Dot(&ACD, &AO)) == B_on_ACD;
- AC_O = ccdSign(btVec3Dot(&ADB, &AO)) == C_on_ADB;
- AD_O = ccdSign(btVec3Dot(&ABC, &AO)) == D_on_ABC;
-
- if (AB_O && AC_O && AD_O)
- {
- // origin is in tetrahedron
- return 1;
- // rearrange simplex to triangle and call btDoSimplex3()
- }
- else if (!AB_O)
- {
- // B is farthest from the origin among all of the tetrahedron's
- // points, so remove it from the list and go on with the triangle
- // case
-
- // D and C are in place
- btSimplexSet(simplex, 2, A);
- btSimplexSetSize(simplex, 3);
- }
- else if (!AC_O)
- {
- // C is farthest
- btSimplexSet(simplex, 1, D);
- btSimplexSet(simplex, 0, B);
- btSimplexSet(simplex, 2, A);
- btSimplexSetSize(simplex, 3);
- }
- else
- { // (!AD_O)
- btSimplexSet(simplex, 0, C);
- btSimplexSet(simplex, 1, B);
- btSimplexSet(simplex, 2, A);
- btSimplexSetSize(simplex, 3);
- }
-
- return btDoSimplex3(simplex, dir);
-}
-
-static int btDoSimplex(btSimplex *simplex, btVector3 *dir)
-{
- if (btSimplexSize(simplex) == 2)
- {
- // simplex contains segment only one segment
- return btDoSimplex2(simplex, dir);
- }
- else if (btSimplexSize(simplex) == 3)
- {
- // simplex contains triangle
- return btDoSimplex3(simplex, dir);
- }
- else
- { // btSimplexSize(simplex) == 4
- // tetrahedron - this is the only shape which can encapsule origin
- // so btDoSimplex4() also contains test on it
- return btDoSimplex4(simplex, dir);
- }
-}
-
-#ifdef __SPU__
-void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
-#else
-void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
-#endif
-{
- m_cachedSeparatingDistance = 0.f;
-
- btScalar distance = btScalar(0.);
- btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
-
- btVector3 pointOnA, pointOnB;
- btTransform localTransA = input.m_transformA;
- btTransform localTransB = input.m_transformB;
- btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
- localTransA.getOrigin() -= positionOffset;
- localTransB.getOrigin() -= positionOffset;
-
- bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
-
- btScalar marginA = m_marginA;
- btScalar marginB = m_marginB;
-
-
- //for CCD we don't use margins
- if (m_ignoreMargin)
- {
- marginA = btScalar(0.);
- marginB = btScalar(0.);
- }
-
- m_curIter = 0;
- int gGjkMaxIter = 1000; //this is to catch invalid input, perhaps check for #NaN?
- m_cachedSeparatingAxis.setValue(0, 1, 0);
-
- bool isValid = false;
- bool checkSimplex = false;
- bool checkPenetration = true;
- m_degenerateSimplex = 0;
-
- m_lastUsedMethod = -1;
- int status = -2;
- btVector3 orgNormalInB(0, 0, 0);
- btScalar margin = marginA + marginB;
-
- //we add a separate implementation to check if the convex shapes intersect
- //See also "Real-time Collision Detection with Implicit Objects" by Leif Olvang
- //Todo: integrate the simplex penetration check directly inside the Bullet btVoronoiSimplexSolver
- //and remove this temporary code from libCCD
- //this fixes issue https://github.com/bulletphysics/bullet3/issues/1703
- //note, for large differences in shapes, use double precision build!
- {
- btScalar squaredDistance = BT_LARGE_FLOAT;
- btScalar delta = btScalar(0.);
-
- btSimplex simplex1;
- btSimplex *simplex = &simplex1;
- btSimplexInit(simplex);
-
- btVector3 dir(1, 0, 0);
-
- {
- btVector3 lastSupV;
- btVector3 supAworld;
- btVector3 supBworld;
- btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
-
- btSupportVector last;
- last.v = lastSupV;
- last.v1 = supAworld;
- last.v2 = supBworld;
-
- btSimplexAdd(simplex, &last);
-
- dir = -lastSupV;
-
- // start iterations
- for (int iterations = 0; iterations < gGjkMaxIter; iterations++)
- {
- // obtain support point
- btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
-
- // check if farthest point in Minkowski difference in direction dir
- // isn't somewhere before origin (the test on negative dot product)
- // - because if it is, objects are not intersecting at all.
- btScalar delta = lastSupV.dot(dir);
- if (delta < 0)
- {
- //no intersection, besides margin
- status = -1;
- break;
- }
-
- // add last support vector to simplex
- last.v = lastSupV;
- last.v1 = supAworld;
- last.v2 = supBworld;
-
- btSimplexAdd(simplex, &last);
-
- // if btDoSimplex returns 1 if objects intersect, -1 if objects don't
- // intersect and 0 if algorithm should continue
-
- btVector3 newDir;
- int do_simplex_res = btDoSimplex(simplex, &dir);
-
- if (do_simplex_res == 1)
- {
- status = 0; // intersection found
- break;
- }
- else if (do_simplex_res == -1)
- {
- // intersection not found
- status = -1;
- break;
- }
-
- if (btFuzzyZero(btVec3Dot(&dir, &dir)))
- {
- // intersection not found
- status = -1;
- }
-
- if (dir.length2() < SIMD_EPSILON)
- {
- //no intersection, besides margin
- status = -1;
- break;
- }
-
- if (dir.fuzzyZero())
- {
- // intersection not found
- status = -1;
- break;
- }
- }
- }
-
- m_simplexSolver->reset();
- if (status == 0)
- {
- //status = 0;
- //printf("Intersect!\n");
- }
-
- if (status == -1)
- {
- //printf("not intersect\n");
- }
- //printf("dir=%f,%f,%f\n",dir[0],dir[1],dir[2]);
- if (1)
- {
- for (;;)
- //while (true)
- {
- btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
- btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
-
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
-
- if (check2d)
- {
- pWorld[2] = 0.f;
- qWorld[2] = 0.f;
- }
-
- btVector3 w = pWorld - qWorld;
- delta = m_cachedSeparatingAxis.dot(w);
-
- // potential exit, they don't overlap
- if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
- {
- m_degenerateSimplex = 10;
- checkSimplex = true;
- //checkPenetration = false;
- break;
- }
-
- //exit 0: the new point is already in the simplex, or we didn't come any closer
- if (m_simplexSolver->inSimplex(w))
- {
- m_degenerateSimplex = 1;
- checkSimplex = true;
- break;
- }
- // are we getting any closer ?
- btScalar f0 = squaredDistance - delta;
- btScalar f1 = squaredDistance * REL_ERROR2;
-
- if (f0 <= f1)
- {
- if (f0 <= btScalar(0.))
- {
- m_degenerateSimplex = 2;
- }
- else
- {
- m_degenerateSimplex = 11;
- }
- checkSimplex = true;
- break;
- }
-
- //add current vertex to simplex
- m_simplexSolver->addVertex(w, pWorld, qWorld);
- btVector3 newCachedSeparatingAxis;
-
- //calculate the closest point to the origin (update vector v)
- if (!m_simplexSolver->closest(newCachedSeparatingAxis))
- {
- m_degenerateSimplex = 3;
- checkSimplex = true;
- break;
- }
-
- if (newCachedSeparatingAxis.length2() < REL_ERROR2)
- {
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
- m_degenerateSimplex = 6;
- checkSimplex = true;
- break;
- }
-
- btScalar previousSquaredDistance = squaredDistance;
- squaredDistance = newCachedSeparatingAxis.length2();
-#if 0
- ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
- if (squaredDistance > previousSquaredDistance)
- {
- m_degenerateSimplex = 7;
- squaredDistance = previousSquaredDistance;
- checkSimplex = false;
- break;
- }
-#endif //
-
- //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
-
- //are we getting any closer ?
- if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
- {
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- checkSimplex = true;
- m_degenerateSimplex = 12;
-
- break;
- }
-
- m_cachedSeparatingAxis = newCachedSeparatingAxis;
-
- //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
- if (m_curIter++ > gGjkMaxIter)
- {
-#if defined(DEBUG) || defined(_DEBUG)
-
- printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
- printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
- m_cachedSeparatingAxis.getX(),
- m_cachedSeparatingAxis.getY(),
- m_cachedSeparatingAxis.getZ(),
- squaredDistance,
- m_minkowskiA->getShapeType(),
- m_minkowskiB->getShapeType());
-
-#endif
- break;
- }
-
- bool check = (!m_simplexSolver->fullSimplex());
- //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
-
- if (!check)
- {
- //do we need this backup_closest here ?
- // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
- m_degenerateSimplex = 13;
- break;
- }
- }
-
- if (checkSimplex)
- {
- m_simplexSolver->compute_points(pointOnA, pointOnB);
- normalInB = m_cachedSeparatingAxis;
-
- btScalar lenSqr = m_cachedSeparatingAxis.length2();
-
- //valid normal
- if (lenSqr < REL_ERROR2)
- {
- m_degenerateSimplex = 5;
- }
- if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
- {
- btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
- normalInB *= rlen; //normalize
-
- btScalar s = btSqrt(squaredDistance);
-
- btAssert(s > btScalar(0.0));
- pointOnA -= m_cachedSeparatingAxis * (marginA / s);
- pointOnB += m_cachedSeparatingAxis * (marginB / s);
- distance = ((btScalar(1.) / rlen) - margin);
- isValid = true;
- orgNormalInB = normalInB;
-
- m_lastUsedMethod = 1;
- }
- else
- {
- m_lastUsedMethod = 2;
- }
- }
- }
-
- bool catchDegeneratePenetrationCase =
- (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance + margin) < gGjkEpaPenetrationTolerance));
-
- //if (checkPenetration && !isValid)
- if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase)) || (status == 0))
- {
- //penetration case
-
- //if there is no way to handle penetrations, bail out
- if (m_penetrationDepthSolver)
- {
- // Penetration depth case.
- btVector3 tmpPointOnA, tmpPointOnB;
-
- m_cachedSeparatingAxis.setZero();
-
- bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
- *m_simplexSolver,
- m_minkowskiA, m_minkowskiB,
- localTransA, localTransB,
- m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
- debugDraw);
-
- if (m_cachedSeparatingAxis.length2())
- {
- if (isValid2)
- {
- btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
- btScalar lenSqr = tmpNormalInB.length2();
- if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
- {
- tmpNormalInB = m_cachedSeparatingAxis;
- lenSqr = m_cachedSeparatingAxis.length2();
- }
-
- if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
- {
- tmpNormalInB /= btSqrt(lenSqr);
- btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
- m_lastUsedMethod = 3;
- //only replace valid penetrations when the result is deeper (check)
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- normalInB = tmpNormalInB;
- isValid = true;
- }
- else
- {
- m_lastUsedMethod = 8;
- }
- }
- else
- {
- m_lastUsedMethod = 9;
- }
- }
- else
-
- {
- ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
- ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
- ///reports a valid positive distance. Use the results of the second GJK instead of failing.
- ///thanks to Jacob.Langford for the reproduction case
- ///http://code.google.com/p/bullet/issues/detail?id=250
-
- if (m_cachedSeparatingAxis.length2() > btScalar(0.))
- {
- btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
- //only replace valid distances when the distance is less
- if (!isValid || (distance2 < distance))
- {
- distance = distance2;
- pointOnA = tmpPointOnA;
- pointOnB = tmpPointOnB;
- pointOnA -= m_cachedSeparatingAxis * marginA;
- pointOnB += m_cachedSeparatingAxis * marginB;
- normalInB = m_cachedSeparatingAxis;
- normalInB.normalize();
-
- isValid = true;
- m_lastUsedMethod = 6;
- }
- else
- {
- m_lastUsedMethod = 5;
- }
- }
- }
- }
- else
- {
- //printf("EPA didn't return a valid value\n");
- }
- }
- }
- }
-
- if (isValid && ((distance < 0) || (distance * distance < input.m_maximumDistanceSquared)))
- {
- m_cachedSeparatingAxis = normalInB;
- m_cachedSeparatingDistance = distance;
- if (1)
- {
- ///todo: need to track down this EPA penetration solver degeneracy
- ///the penetration solver reports penetration but the contact normal
- ///connecting the contact points is pointing in the opposite direction
- ///until then, detect the issue and revert the normal
-
- btScalar d2 = 0.f;
- {
- btVector3 separatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
- btVector3 separatingAxisInB = orgNormalInB * localTransB.getBasis();
-
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
- btVector3 w = pWorld - qWorld;
- d2 = orgNormalInB.dot(w) - margin;
- }
-
- btScalar d1 = 0;
- {
- btVector3 separatingAxisInA = (normalInB)*localTransA.getBasis();
- btVector3 separatingAxisInB = -normalInB * localTransB.getBasis();
-
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
- btVector3 w = pWorld - qWorld;
- d1 = (-normalInB).dot(w) - margin;
- }
- btScalar d0 = 0.f;
- {
- btVector3 separatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
- btVector3 separatingAxisInB = normalInB * input.m_transformB.getBasis();
-
- btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
-
- btVector3 pWorld = localTransA(pInA);
- btVector3 qWorld = localTransB(qInB);
- btVector3 w = pWorld - qWorld;
- d0 = normalInB.dot(w) - margin;
- }
-
- if (d1 > d0)
- {
- m_lastUsedMethod = 10;
- normalInB *= -1;
- }
-
- if (orgNormalInB.length2())
- {
- if (d2 > d0 && d2 > d1 && d2 > distance)
- {
- normalInB = orgNormalInB;
- distance = d2;
- }
- }
- }
-
- output.addContactPoint(
- normalInB,
- pointOnB + positionOffset,
- distance);
- }
- else
- {
- //printf("invalid gjk query\n");
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
deleted file mode 100644
index faa02287ca..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GJK_PAIR_DETECTOR_H
-#define BT_GJK_PAIR_DETECTOR_H
-
-#include "btDiscreteCollisionDetectorInterface.h"
-#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
-
-class btConvexShape;
-#include "btSimplexSolverInterface.h"
-class btConvexPenetrationDepthSolver;
-
-/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
-class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
-{
- btVector3 m_cachedSeparatingAxis;
- btConvexPenetrationDepthSolver* m_penetrationDepthSolver;
- btSimplexSolverInterface* m_simplexSolver;
- const btConvexShape* m_minkowskiA;
- const btConvexShape* m_minkowskiB;
- int m_shapeTypeA;
- int m_shapeTypeB;
- btScalar m_marginA;
- btScalar m_marginB;
-
- bool m_ignoreMargin;
- btScalar m_cachedSeparatingDistance;
-
-public:
- //some debugging to fix degeneracy problems
- int m_lastUsedMethod;
- int m_curIter;
- int m_degenerateSimplex;
- int m_catchDegeneracies;
- int m_fixContactNormalDirection;
-
- btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
- btGjkPairDetector(const btConvexShape* objectA, const btConvexShape* objectB, int shapeTypeA, int shapeTypeB, btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver);
- virtual ~btGjkPairDetector(){};
-
- virtual void getClosestPoints(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw, bool swapResults = false);
-
- void getClosestPointsNonVirtual(const ClosestPointInput& input, Result& output, class btIDebugDraw* debugDraw);
-
- void setMinkowskiA(const btConvexShape* minkA)
- {
- m_minkowskiA = minkA;
- }
-
- void setMinkowskiB(const btConvexShape* minkB)
- {
- m_minkowskiB = minkB;
- }
- void setCachedSeparatingAxis(const btVector3& separatingAxis)
- {
- m_cachedSeparatingAxis = separatingAxis;
- }
-
- const btVector3& getCachedSeparatingAxis() const
- {
- return m_cachedSeparatingAxis;
- }
- btScalar getCachedSeparatingDistance() const
- {
- return m_cachedSeparatingDistance;
- }
-
- void setPenetrationDepthSolver(btConvexPenetrationDepthSolver* penetrationDepthSolver)
- {
- m_penetrationDepthSolver = penetrationDepthSolver;
- }
-
- ///don't use setIgnoreMargin, it's for Bullet's internal use
- void setIgnoreMargin(bool ignoreMargin)
- {
- m_ignoreMargin = ignoreMargin;
- }
-};
-
-#endif //BT_GJK_PAIR_DETECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
deleted file mode 100644
index 573fc86bf9..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MANIFOLD_CONTACT_POINT_H
-#define BT_MANIFOLD_CONTACT_POINT_H
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransformUtil.h"
-
-#ifdef PFX_USE_FREE_VECTORMATH
-#include "physics_effects/base_level/solver/pfx_constraint_row.h"
-typedef sce::PhysicsEffects::PfxConstraintRow btConstraintRow;
-#else
-// Don't change following order of parameters
-ATTRIBUTE_ALIGNED16(struct)
-btConstraintRow
-{
- btScalar m_normal[3];
- btScalar m_rhs;
- btScalar m_jacDiagInv;
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_accumImpulse;
-};
-typedef btConstraintRow PfxConstraintRow;
-#endif //PFX_USE_FREE_VECTORMATH
-
-enum btContactPointFlags
-{
- BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED = 1,
- BT_CONTACT_FLAG_HAS_CONTACT_CFM = 2,
- BT_CONTACT_FLAG_HAS_CONTACT_ERP = 4,
- BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING = 8,
- BT_CONTACT_FLAG_FRICTION_ANCHOR = 16,
-};
-
-/// ManifoldContactPoint collects and maintains persistent contactpoints.
-/// used to improve stability and performance of rigidbody dynamics response.
-class btManifoldPoint
-{
-public:
- btManifoldPoint()
- : m_userPersistentData(0),
- m_contactPointFlags(0),
- m_appliedImpulse(0.f),
- m_prevRHS(0.f),
- m_appliedImpulseLateral1(0.f),
- m_appliedImpulseLateral2(0.f),
- m_contactMotion1(0.f),
- m_contactMotion2(0.f),
- m_contactCFM(0.f),
- m_contactERP(0.f),
- m_frictionCFM(0.f),
- m_lifeTime(0)
- {
- }
-
- btManifoldPoint(const btVector3& pointA, const btVector3& pointB,
- const btVector3& normal,
- btScalar distance) : m_localPointA(pointA),
- m_localPointB(pointB),
- m_normalWorldOnB(normal),
- m_distance1(distance),
- m_combinedFriction(btScalar(0.)),
- m_combinedRollingFriction(btScalar(0.)),
- m_combinedSpinningFriction(btScalar(0.)),
- m_combinedRestitution(btScalar(0.)),
- m_userPersistentData(0),
- m_contactPointFlags(0),
- m_appliedImpulse(0.f),
- m_prevRHS(0.f),
- m_appliedImpulseLateral1(0.f),
- m_appliedImpulseLateral2(0.f),
- m_contactMotion1(0.f),
- m_contactMotion2(0.f),
- m_contactCFM(0.f),
- m_contactERP(0.f),
- m_frictionCFM(0.f),
- m_lifeTime(0)
- {
- }
-
- btVector3 m_localPointA;
- btVector3 m_localPointB;
- btVector3 m_positionWorldOnB;
- ///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
- btVector3 m_positionWorldOnA;
- btVector3 m_normalWorldOnB;
-
- btScalar m_distance1;
- btScalar m_combinedFriction;
- btScalar m_combinedRollingFriction; //torsional friction orthogonal to contact normal, useful to make spheres stop rolling forever
- btScalar m_combinedSpinningFriction; //torsional friction around contact normal, useful for grasping objects
- btScalar m_combinedRestitution;
-
- //BP mod, store contact triangles.
- int m_partId0;
- int m_partId1;
- int m_index0;
- int m_index1;
-
- mutable void* m_userPersistentData;
- //bool m_lateralFrictionInitialized;
- int m_contactPointFlags;
-
- btScalar m_appliedImpulse;
- btScalar m_prevRHS;
- btScalar m_appliedImpulseLateral1;
- btScalar m_appliedImpulseLateral2;
- btScalar m_contactMotion1;
- btScalar m_contactMotion2;
-
- union {
- btScalar m_contactCFM;
- btScalar m_combinedContactStiffness1;
- };
-
- union {
- btScalar m_contactERP;
- btScalar m_combinedContactDamping1;
- };
-
- btScalar m_frictionCFM;
-
- int m_lifeTime; //lifetime of the contactpoint in frames
-
- btVector3 m_lateralFrictionDir1;
- btVector3 m_lateralFrictionDir2;
-
- btScalar getDistance() const
- {
- return m_distance1;
- }
- int getLifeTime() const
- {
- return m_lifeTime;
- }
-
- const btVector3& getPositionWorldOnA() const
- {
- return m_positionWorldOnA;
- // return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
- }
-
- const btVector3& getPositionWorldOnB() const
- {
- return m_positionWorldOnB;
- }
-
- void setDistance(btScalar dist)
- {
- m_distance1 = dist;
- }
-
- ///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
- btScalar getAppliedImpulse() const
- {
- return m_appliedImpulse;
- }
-};
-
-#endif //BT_MANIFOLD_CONTACT_POINT_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
deleted file mode 100644
index c042c24208..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btMinkowskiPenetrationDepthSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
-#define NUM_UNITSPHERE_POINTS 42
-
-bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA, const btConvexShape* convexB,
- const btTransform& transA, const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw)
-{
- (void)v;
-
- bool check2d = convexA->isConvex2d() && convexB->isConvex2d();
-
- struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
- {
- btIntermediateResult() : m_hasResult(false)
- {
- }
-
- btVector3 m_normalOnBInWorld;
- btVector3 m_pointInWorld;
- btScalar m_depth;
- bool m_hasResult;
-
- virtual void setShapeIdentifiersA(int partId0, int index0)
- {
- (void)partId0;
- (void)index0;
- }
- virtual void setShapeIdentifiersB(int partId1, int index1)
- {
- (void)partId1;
- (void)index1;
- }
- void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- m_normalOnBInWorld = normalOnBInWorld;
- m_pointInWorld = pointInWorld;
- m_depth = depth;
- m_hasResult = true;
- }
- };
-
- //just take fixed number of orientation, and sample the penetration depth in that direction
- btScalar minProj = btScalar(BT_LARGE_FLOAT);
- btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 minA, minB;
- btVector3 separatingAxisInA, separatingAxisInB;
- btVector3 pInA, qInB, pWorld, qWorld, w;
-
-#ifndef __SPU__
-#define USE_BATCHED_SUPPORT 1
-#endif
-#ifdef USE_BATCHED_SUPPORT
-
- btVector3 supportVerticesABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 supportVerticesBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 separatingAxisInABatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- btVector3 separatingAxisInBBatch[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2];
- int i;
-
- int numSampleDirections = NUM_UNITSPHERE_POINTS;
-
- for (i = 0; i < numSampleDirections; i++)
- {
- btVector3 norm = getPenetrationDirections()[i];
- separatingAxisInABatch[i] = (-norm) * transA.getBasis();
- separatingAxisInBBatch[i] = norm * transB.getBasis();
- }
-
- {
- int numPDA = convexA->getNumPreferredPenetrationDirections();
- if (numPDA)
- {
- for (int i = 0; i < numPDA; i++)
- {
- btVector3 norm;
- convexA->getPreferredPenetrationDirection(i, norm);
- norm = transA.getBasis() * norm;
- getPenetrationDirections()[numSampleDirections] = norm;
- separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
- numSampleDirections++;
- }
- }
- }
-
- {
- int numPDB = convexB->getNumPreferredPenetrationDirections();
- if (numPDB)
- {
- for (int i = 0; i < numPDB; i++)
- {
- btVector3 norm;
- convexB->getPreferredPenetrationDirection(i, norm);
- norm = transB.getBasis() * norm;
- getPenetrationDirections()[numSampleDirections] = norm;
- separatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
- separatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
- numSampleDirections++;
- }
- }
- }
-
- convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInABatch, supportVerticesABatch, numSampleDirections);
- convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(separatingAxisInBBatch, supportVerticesBBatch, numSampleDirections);
-
- for (i = 0; i < numSampleDirections; i++)
- {
- btVector3 norm = getPenetrationDirections()[i];
- if (check2d)
- {
- norm[2] = 0.f;
- }
- if (norm.length2() > 0.01)
- {
- separatingAxisInA = separatingAxisInABatch[i];
- separatingAxisInB = separatingAxisInBBatch[i];
-
- pInA = supportVerticesABatch[i];
- qInB = supportVerticesBBatch[i];
-
- pWorld = transA(pInA);
- qWorld = transB(qInB);
- if (check2d)
- {
- pWorld[2] = 0.f;
- qWorld[2] = 0.f;
- }
-
- w = qWorld - pWorld;
- btScalar delta = norm.dot(w);
- //find smallest delta
- if (delta < minProj)
- {
- minProj = delta;
- minNorm = norm;
- minA = pWorld;
- minB = qWorld;
- }
- }
- }
-#else
-
- int numSampleDirections = NUM_UNITSPHERE_POINTS;
-
-#ifndef __SPU__
- {
- int numPDA = convexA->getNumPreferredPenetrationDirections();
- if (numPDA)
- {
- for (int i = 0; i < numPDA; i++)
- {
- btVector3 norm;
- convexA->getPreferredPenetrationDirection(i, norm);
- norm = transA.getBasis() * norm;
- getPenetrationDirections()[numSampleDirections] = norm;
- numSampleDirections++;
- }
- }
- }
-
- {
- int numPDB = convexB->getNumPreferredPenetrationDirections();
- if (numPDB)
- {
- for (int i = 0; i < numPDB; i++)
- {
- btVector3 norm;
- convexB->getPreferredPenetrationDirection(i, norm);
- norm = transB.getBasis() * norm;
- getPenetrationDirections()[numSampleDirections] = norm;
- numSampleDirections++;
- }
- }
- }
-#endif // __SPU__
-
- for (int i = 0; i < numSampleDirections; i++)
- {
- const btVector3& norm = getPenetrationDirections()[i];
- separatingAxisInA = (-norm) * transA.getBasis();
- separatingAxisInB = norm * transB.getBasis();
- pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
- qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
- pWorld = transA(pInA);
- qWorld = transB(qInB);
- w = qWorld - pWorld;
- btScalar delta = norm.dot(w);
- //find smallest delta
- if (delta < minProj)
- {
- minProj = delta;
- minNorm = norm;
- minA = pWorld;
- minB = qWorld;
- }
- }
-#endif //USE_BATCHED_SUPPORT
-
- //add the margins
-
- minA += minNorm * convexA->getMarginNonVirtual();
- minB -= minNorm * convexB->getMarginNonVirtual();
- //no penetration
- if (minProj < btScalar(0.))
- return false;
-
- btScalar extraSeparation = 0.5f; ///scale dependent
- minProj += extraSeparation + (convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
-
-//#define DEBUG_DRAW 1
-#ifdef DEBUG_DRAW
- if (debugDraw)
- {
- btVector3 color(0, 1, 0);
- debugDraw->drawLine(minA, minB, color);
- color = btVector3(1, 1, 1);
- btVector3 vec = minB - minA;
- btScalar prj2 = minNorm.dot(vec);
- debugDraw->drawLine(minA, minA + (minNorm * minProj), color);
- }
-#endif //DEBUG_DRAW
-
- btGjkPairDetector gjkdet(convexA, convexB, &simplexSolver, 0);
-
- btScalar offsetDist = minProj;
- btVector3 offset = minNorm * offsetDist;
-
- btGjkPairDetector::ClosestPointInput input;
-
- btVector3 newOrg = transA.getOrigin() + offset;
-
- btTransform displacedTrans = transA;
- displacedTrans.setOrigin(newOrg);
-
- input.m_transformA = displacedTrans;
- input.m_transformB = transB;
- input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT); //minProj;
-
- btIntermediateResult res;
- gjkdet.setCachedSeparatingAxis(-minNorm);
- gjkdet.getClosestPoints(input, res, debugDraw);
-
- btScalar correctedMinNorm = minProj - res.m_depth;
-
- //the penetration depth is over-estimated, relax it
- btScalar penetration_relaxation = btScalar(1.);
- minNorm *= penetration_relaxation;
-
- if (res.m_hasResult)
- {
- pa = res.m_pointInWorld - minNorm * correctedMinNorm;
- pb = res.m_pointInWorld;
- v = minNorm;
-
-#ifdef DEBUG_DRAW
- if (debugDraw)
- {
- btVector3 color(1, 0, 0);
- debugDraw->drawLine(pa, pb, color);
- }
-#endif //DEBUG_DRAW
- }
- return res.m_hasResult;
-}
-
-btVector3* btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
-{
- static btVector3 sPenetrationDirections[NUM_UNITSPHERE_POINTS + MAX_PREFERRED_PENETRATION_DIRECTIONS * 2] =
- {
- btVector3(btScalar(0.000000), btScalar(-0.000000), btScalar(-1.000000)),
- btVector3(btScalar(0.723608), btScalar(-0.525725), btScalar(-0.447219)),
- btVector3(btScalar(-0.276388), btScalar(-0.850649), btScalar(-0.447219)),
- btVector3(btScalar(-0.894426), btScalar(-0.000000), btScalar(-0.447216)),
- btVector3(btScalar(-0.276388), btScalar(0.850649), btScalar(-0.447220)),
- btVector3(btScalar(0.723608), btScalar(0.525725), btScalar(-0.447219)),
- btVector3(btScalar(0.276388), btScalar(-0.850649), btScalar(0.447220)),
- btVector3(btScalar(-0.723608), btScalar(-0.525725), btScalar(0.447219)),
- btVector3(btScalar(-0.723608), btScalar(0.525725), btScalar(0.447219)),
- btVector3(btScalar(0.276388), btScalar(0.850649), btScalar(0.447219)),
- btVector3(btScalar(0.894426), btScalar(0.000000), btScalar(0.447216)),
- btVector3(btScalar(-0.000000), btScalar(0.000000), btScalar(1.000000)),
- btVector3(btScalar(0.425323), btScalar(-0.309011), btScalar(-0.850654)),
- btVector3(btScalar(-0.162456), btScalar(-0.499995), btScalar(-0.850654)),
- btVector3(btScalar(0.262869), btScalar(-0.809012), btScalar(-0.525738)),
- btVector3(btScalar(0.425323), btScalar(0.309011), btScalar(-0.850654)),
- btVector3(btScalar(0.850648), btScalar(-0.000000), btScalar(-0.525736)),
- btVector3(btScalar(-0.525730), btScalar(-0.000000), btScalar(-0.850652)),
- btVector3(btScalar(-0.688190), btScalar(-0.499997), btScalar(-0.525736)),
- btVector3(btScalar(-0.162456), btScalar(0.499995), btScalar(-0.850654)),
- btVector3(btScalar(-0.688190), btScalar(0.499997), btScalar(-0.525736)),
- btVector3(btScalar(0.262869), btScalar(0.809012), btScalar(-0.525738)),
- btVector3(btScalar(0.951058), btScalar(0.309013), btScalar(0.000000)),
- btVector3(btScalar(0.951058), btScalar(-0.309013), btScalar(0.000000)),
- btVector3(btScalar(0.587786), btScalar(-0.809017), btScalar(0.000000)),
- btVector3(btScalar(0.000000), btScalar(-1.000000), btScalar(0.000000)),
- btVector3(btScalar(-0.587786), btScalar(-0.809017), btScalar(0.000000)),
- btVector3(btScalar(-0.951058), btScalar(-0.309013), btScalar(-0.000000)),
- btVector3(btScalar(-0.951058), btScalar(0.309013), btScalar(-0.000000)),
- btVector3(btScalar(-0.587786), btScalar(0.809017), btScalar(-0.000000)),
- btVector3(btScalar(-0.000000), btScalar(1.000000), btScalar(-0.000000)),
- btVector3(btScalar(0.587786), btScalar(0.809017), btScalar(-0.000000)),
- btVector3(btScalar(0.688190), btScalar(-0.499997), btScalar(0.525736)),
- btVector3(btScalar(-0.262869), btScalar(-0.809012), btScalar(0.525738)),
- btVector3(btScalar(-0.850648), btScalar(0.000000), btScalar(0.525736)),
- btVector3(btScalar(-0.262869), btScalar(0.809012), btScalar(0.525738)),
- btVector3(btScalar(0.688190), btScalar(0.499997), btScalar(0.525736)),
- btVector3(btScalar(0.525730), btScalar(0.000000), btScalar(0.850652)),
- btVector3(btScalar(0.162456), btScalar(-0.499995), btScalar(0.850654)),
- btVector3(btScalar(-0.425323), btScalar(-0.309011), btScalar(0.850654)),
- btVector3(btScalar(-0.425323), btScalar(0.309011), btScalar(0.850654)),
- btVector3(btScalar(0.162456), btScalar(0.499995), btScalar(0.850654))};
-
- return sPenetrationDirections;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
deleted file mode 100644
index 8e3e393259..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
-#define BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
-
-#include "btConvexPenetrationDepthSolver.h"
-
-///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
-///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
-class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
-{
-protected:
- static btVector3* getPenetrationDirections();
-
-public:
- virtual bool calcPenDepth(btSimplexSolverInterface& simplexSolver,
- const btConvexShape* convexA, const btConvexShape* convexB,
- const btTransform& transA, const btTransform& transB,
- btVector3& v, btVector3& pa, btVector3& pb,
- class btIDebugDraw* debugDraw);
-};
-
-#endif //BT_MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
deleted file mode 100644
index 534a66d3fa..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btMprPenetration.h
+++ /dev/null
@@ -1,884 +0,0 @@
-
-/***
- * ---------------------------------
- * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
- *
- * This file was ported from mpr.c file, part of libccd.
- * The Minkoski Portal Refinement implementation was ported
- * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
- * The original MPR idea and implementation is by Gary Snethen
- * in XenoCollide, see http://github.com/erwincoumans/xenocollide
- *
- * Distributed under the OSI-approved BSD License (the "License");
- * see <http://www.opensource.org/licenses/bsd-license.php>.
- * This software is distributed WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the License for more information.
- */
-
-///2014 Oct, Erwin Coumans, Use templates to avoid void* casts
-
-#ifndef BT_MPR_PENETRATION_H
-#define BT_MPR_PENETRATION_H
-
-#define BT_DEBUG_MPR1
-
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-//#define MPR_AVERAGE_CONTACT_POSITIONS
-
-struct btMprCollisionDescription
-{
- btVector3 m_firstDir;
- int m_maxGjkIterations;
- btScalar m_maximumDistanceSquared;
- btScalar m_gjkRelError2;
-
- btMprCollisionDescription()
- : m_firstDir(0, 1, 0),
- m_maxGjkIterations(1000),
- m_maximumDistanceSquared(1e30f),
- m_gjkRelError2(1.0e-6)
- {
- }
- virtual ~btMprCollisionDescription()
- {
- }
-};
-
-struct btMprDistanceInfo
-{
- btVector3 m_pointOnA;
- btVector3 m_pointOnB;
- btVector3 m_normalBtoA;
- btScalar m_distance;
-};
-
-#ifdef __cplusplus
-#define BT_MPR_SQRT sqrtf
-#else
-#define BT_MPR_SQRT sqrt
-#endif
-#define BT_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
-#define BT_MPR_FABS fabs
-
-#define BT_MPR_TOLERANCE 1E-6f
-#define BT_MPR_MAX_ITERATIONS 1000
-
-struct _btMprSupport_t
-{
- btVector3 v; //!< Support point in minkowski sum
- btVector3 v1; //!< Support point in obj1
- btVector3 v2; //!< Support point in obj2
-};
-typedef struct _btMprSupport_t btMprSupport_t;
-
-struct _btMprSimplex_t
-{
- btMprSupport_t ps[4];
- int last; //!< index of last added point
-};
-typedef struct _btMprSimplex_t btMprSimplex_t;
-
-inline btMprSupport_t *btMprSimplexPointW(btMprSimplex_t *s, int idx)
-{
- return &s->ps[idx];
-}
-
-inline void btMprSimplexSetSize(btMprSimplex_t *s, int size)
-{
- s->last = size - 1;
-}
-
-#ifdef DEBUG_MPR
-inline void btPrintPortalVertex(_btMprSimplex_t *portal, int index)
-{
- printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(), portal->ps[index].v.y(), portal->ps[index].v.z(),
- portal->ps[index].v1.x(), portal->ps[index].v1.y(), portal->ps[index].v1.z(),
- portal->ps[index].v2.x(), portal->ps[index].v2.y(), portal->ps[index].v2.z());
-}
-#endif //DEBUG_MPR
-
-inline int btMprSimplexSize(const btMprSimplex_t *s)
-{
- return s->last + 1;
-}
-
-inline const btMprSupport_t *btMprSimplexPoint(const btMprSimplex_t *s, int idx)
-{
- // here is no check on boundaries
- return &s->ps[idx];
-}
-
-inline void btMprSupportCopy(btMprSupport_t *d, const btMprSupport_t *s)
-{
- *d = *s;
-}
-
-inline void btMprSimplexSet(btMprSimplex_t *s, size_t pos, const btMprSupport_t *a)
-{
- btMprSupportCopy(s->ps + pos, a);
-}
-
-inline void btMprSimplexSwap(btMprSimplex_t *s, size_t pos1, size_t pos2)
-{
- btMprSupport_t supp;
-
- btMprSupportCopy(&supp, &s->ps[pos1]);
- btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
- btMprSupportCopy(&s->ps[pos2], &supp);
-}
-
-inline int btMprIsZero(float val)
-{
- return BT_MPR_FABS(val) < FLT_EPSILON;
-}
-
-inline int btMprEq(float _a, float _b)
-{
- float ab;
- float a, b;
-
- ab = BT_MPR_FABS(_a - _b);
- if (BT_MPR_FABS(ab) < FLT_EPSILON)
- return 1;
-
- a = BT_MPR_FABS(_a);
- b = BT_MPR_FABS(_b);
- if (b > a)
- {
- return ab < FLT_EPSILON * b;
- }
- else
- {
- return ab < FLT_EPSILON * a;
- }
-}
-
-inline int btMprVec3Eq(const btVector3 *a, const btVector3 *b)
-{
- return btMprEq((*a).x(), (*b).x()) && btMprEq((*a).y(), (*b).y()) && btMprEq((*a).z(), (*b).z());
-}
-
-template <typename btConvexTemplate>
-inline void btFindOrigin(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprSupport_t *center)
-{
- center->v1 = a.getObjectCenterInWorld();
- center->v2 = b.getObjectCenterInWorld();
- center->v = center->v1 - center->v2;
-}
-
-inline void btMprVec3Set(btVector3 *v, float x, float y, float z)
-{
- v->setValue(x, y, z);
-}
-
-inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
-{
- *v += *w;
-}
-
-inline void btMprVec3Copy(btVector3 *v, const btVector3 *w)
-{
- *v = *w;
-}
-
-inline void btMprVec3Scale(btVector3 *d, float k)
-{
- *d *= k;
-}
-
-inline float btMprVec3Dot(const btVector3 *a, const btVector3 *b)
-{
- float dot;
-
- dot = btDot(*a, *b);
- return dot;
-}
-
-inline float btMprVec3Len2(const btVector3 *v)
-{
- return btMprVec3Dot(v, v);
-}
-
-inline void btMprVec3Normalize(btVector3 *d)
-{
- float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
- btMprVec3Scale(d, k);
-}
-
-inline void btMprVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
-{
- *d = btCross(*a, *b);
-}
-
-inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
-{
- *d = *v - *w;
-}
-
-inline void btPortalDir(const btMprSimplex_t *portal, btVector3 *dir)
-{
- btVector3 v2v1, v3v1;
-
- btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 1)->v);
- btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 1)->v);
- btMprVec3Cross(dir, &v2v1, &v3v1);
- btMprVec3Normalize(dir);
-}
-
-inline int portalEncapsulesOrigin(const btMprSimplex_t *portal,
- const btVector3 *dir)
-{
- float dot;
- dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
- return btMprIsZero(dot) || dot > 0.f;
-}
-
-inline int portalReachTolerance(const btMprSimplex_t *portal,
- const btMprSupport_t *v4,
- const btVector3 *dir)
-{
- float dv1, dv2, dv3, dv4;
- float dot1, dot2, dot3;
-
- // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
-
- dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
- dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
- dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
- dv4 = btMprVec3Dot(&v4->v, dir);
-
- dot1 = dv4 - dv1;
- dot2 = dv4 - dv2;
- dot3 = dv4 - dv3;
-
- dot1 = BT_MPR_FMIN(dot1, dot2);
- dot1 = BT_MPR_FMIN(dot1, dot3);
-
- return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
-}
-
-inline int portalCanEncapsuleOrigin(const btMprSimplex_t *portal,
- const btMprSupport_t *v4,
- const btVector3 *dir)
-{
- float dot;
- dot = btMprVec3Dot(&v4->v, dir);
- return btMprIsZero(dot) || dot > 0.f;
-}
-
-inline void btExpandPortal(btMprSimplex_t *portal,
- const btMprSupport_t *v4)
-{
- float dot;
- btVector3 v4v0;
-
- btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
- if (dot > 0.f)
- {
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
- if (dot > 0.f)
- {
- btMprSimplexSet(portal, 1, v4);
- }
- else
- {
- btMprSimplexSet(portal, 3, v4);
- }
- }
- else
- {
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
- if (dot > 0.f)
- {
- btMprSimplexSet(portal, 2, v4);
- }
- else
- {
- btMprSimplexSet(portal, 1, v4);
- }
- }
-}
-template <typename btConvexTemplate>
-inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
- const btMprCollisionDescription &colDesc,
- const btVector3 &dir, btMprSupport_t *supp)
-{
- btVector3 separatingAxisInA = dir * a.getWorldTransform().getBasis();
- btVector3 separatingAxisInB = -dir * b.getWorldTransform().getBasis();
-
- btVector3 pInA = a.getLocalSupportWithMargin(separatingAxisInA);
- btVector3 qInB = b.getLocalSupportWithMargin(separatingAxisInB);
-
- supp->v1 = a.getWorldTransform()(pInA);
- supp->v2 = b.getWorldTransform()(qInB);
- supp->v = supp->v1 - supp->v2;
-}
-
-template <typename btConvexTemplate>
-static int btDiscoverPortal(const btConvexTemplate &a, const btConvexTemplate &b,
- const btMprCollisionDescription &colDesc,
- btMprSimplex_t *portal)
-{
- btVector3 dir, va, vb;
- float dot;
- int cont;
-
- // vertex 0 is center of portal
- btFindOrigin(a, b, colDesc, btMprSimplexPointW(portal, 0));
-
- // vertex 0 is center of portal
- btMprSimplexSetSize(portal, 1);
-
- btVector3 zero = btVector3(0, 0, 0);
- btVector3 *org = &zero;
-
- if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org))
- {
- // Portal's center lies on origin (0,0,0) => we know that objects
- // intersect but we would need to know penetration info.
- // So move center little bit...
- btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
- btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
- }
-
- // vertex 1 = support in direction of origin
- btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Scale(&dir, -1.f);
- btMprVec3Normalize(&dir);
-
- btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 1));
-
- btMprSimplexSetSize(portal, 2);
-
- // test if origin isn't outside of v1
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
-
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
- // vertex 2
- btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
- &btMprSimplexPoint(portal, 1)->v);
- if (btMprIsZero(btMprVec3Len2(&dir)))
- {
- if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org))
- {
- // origin lies on v1
- return 1;
- }
- else
- {
- // origin lies on v0-v1 segment
- return 2;
- }
- }
-
- btMprVec3Normalize(&dir);
- btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 2));
-
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
- btMprSimplexSetSize(portal, 3);
-
- // vertex 3 direction
- btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Cross(&dir, &va, &vb);
- btMprVec3Normalize(&dir);
-
- // it is better to form portal faces to be oriented "outside" origin
- dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
- if (dot > 0.f)
- {
- btMprSimplexSwap(portal, 1, 2);
- btMprVec3Scale(&dir, -1.f);
- }
-
- while (btMprSimplexSize(portal) < 4)
- {
- btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 3));
-
- dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
- if (btMprIsZero(dot) || dot < 0.f)
- return -1;
-
- cont = 0;
-
- // test if origin is outside (v1, v0, v3) - set v2 as v3 and
- // continue
- btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 3)->v);
- dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !btMprIsZero(dot))
- {
- btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
- cont = 1;
- }
-
- if (!cont)
- {
- // test if origin is outside (v3, v0, v2) - set v1 as v3 and
- // continue
- btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 2)->v);
- dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
- if (dot < 0.f && !btMprIsZero(dot))
- {
- btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
- cont = 1;
- }
- }
-
- if (cont)
- {
- btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 0)->v);
- btMprVec3Cross(&dir, &va, &vb);
- btMprVec3Normalize(&dir);
- }
- else
- {
- btMprSimplexSetSize(portal, 4);
- }
- }
-
- return 0;
-}
-
-template <typename btConvexTemplate>
-static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc,
- btMprSimplex_t *portal)
-{
- btVector3 dir;
- btMprSupport_t v4;
-
- for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
- //while (1)
- {
- // compute direction outside the portal (from v0 through v1,v2,v3
- // face)
- btPortalDir(portal, &dir);
-
- // test if origin is inside the portal
- if (portalEncapsulesOrigin(portal, &dir))
- return 0;
-
- // get next support point
-
- btMprSupport(a, b, colDesc, dir, &v4);
-
- // test if v4 can expand portal to contain origin and if portal
- // expanding doesn't reach given tolerance
- if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir))
- {
- return -1;
- }
-
- // v1-v2-v3 triangle must be rearranged to face outside Minkowski
- // difference (direction from v0).
- btExpandPortal(portal, &v4);
- }
-
- return -1;
-}
-
-static void btFindPos(const btMprSimplex_t *portal, btVector3 *pos)
-{
- btVector3 zero = btVector3(0, 0, 0);
- btVector3 *origin = &zero;
-
- btVector3 dir;
- size_t i;
- float b[4], sum, inv;
- btVector3 vec, p1, p2;
-
- btPortalDir(portal, &dir);
-
- // use barycentric coordinates of tetrahedron to find origin
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
-
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
-
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
-
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
-
- sum = b[0] + b[1] + b[2] + b[3];
-
- if (btMprIsZero(sum) || sum < 0.f)
- {
- b[0] = 0.f;
-
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
- &btMprSimplexPoint(portal, 3)->v);
- b[1] = btMprVec3Dot(&vec, &dir);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
- &btMprSimplexPoint(portal, 1)->v);
- b[2] = btMprVec3Dot(&vec, &dir);
- btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
- &btMprSimplexPoint(portal, 2)->v);
- b[3] = btMprVec3Dot(&vec, &dir);
-
- sum = b[1] + b[2] + b[3];
- }
-
- inv = 1.f / sum;
-
- btMprVec3Copy(&p1, origin);
- btMprVec3Copy(&p2, origin);
- for (i = 0; i < 4; i++)
- {
- btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
- btMprVec3Scale(&vec, b[i]);
- btMprVec3Add(&p1, &vec);
-
- btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
- btMprVec3Scale(&vec, b[i]);
- btMprVec3Add(&p2, &vec);
- }
- btMprVec3Scale(&p1, inv);
- btMprVec3Scale(&p2, inv);
-#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &p1);
- btMprVec3Add(pos, &p2);
- btMprVec3Scale(pos, 0.5);
-#else
- btMprVec3Copy(pos, &p2);
-#endif //MPR_AVERAGE_CONTACT_POSITIONS
-}
-
-inline float btMprVec3Dist2(const btVector3 *a, const btVector3 *b)
-{
- btVector3 ab;
- btMprVec3Sub2(&ab, a, b);
- return btMprVec3Len2(&ab);
-}
-
-inline float _btMprVec3PointSegmentDist2(const btVector3 *P,
- const btVector3 *x0,
- const btVector3 *b,
- btVector3 *witness)
-{
- // The computation comes from solving equation of segment:
- // S(t) = x0 + t.d
- // where - x0 is initial point of segment
- // - d is direction of segment from x0 (|d| > 0)
- // - t belongs to <0, 1> interval
- //
- // Than, distance from a segment to some point P can be expressed:
- // D(t) = |x0 + t.d - P|^2
- // which is distance from any point on segment. Minimization
- // of this function brings distance from P to segment.
- // Minimization of D(t) leads to simple quadratic equation that's
- // solving is straightforward.
- //
- // Bonus of this method is witness point for free.
-
- float dist, t;
- btVector3 d, a;
-
- // direction of segment
- btMprVec3Sub2(&d, b, x0);
-
- // precompute vector from P to x0
- btMprVec3Sub2(&a, x0, P);
-
- t = -1.f * btMprVec3Dot(&a, &d);
- t /= btMprVec3Len2(&d);
-
- if (t < 0.f || btMprIsZero(t))
- {
- dist = btMprVec3Dist2(x0, P);
- if (witness)
- btMprVec3Copy(witness, x0);
- }
- else if (t > 1.f || btMprEq(t, 1.f))
- {
- dist = btMprVec3Dist2(b, P);
- if (witness)
- btMprVec3Copy(witness, b);
- }
- else
- {
- if (witness)
- {
- btMprVec3Copy(witness, &d);
- btMprVec3Scale(witness, t);
- btMprVec3Add(witness, x0);
- dist = btMprVec3Dist2(witness, P);
- }
- else
- {
- // recycling variables
- btMprVec3Scale(&d, t);
- btMprVec3Add(&d, &a);
- dist = btMprVec3Len2(&d);
- }
- }
-
- return dist;
-}
-
-inline float btMprVec3PointTriDist2(const btVector3 *P,
- const btVector3 *x0, const btVector3 *B,
- const btVector3 *C,
- btVector3 *witness)
-{
- // Computation comes from analytic expression for triangle (x0, B, C)
- // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
- // Then equation for distance is:
- // D(s, t) = | T(s, t) - P |^2
- // This leads to minimization of quadratic function of two variables.
- // The solution from is taken only if s is between 0 and 1, t is
- // between 0 and 1 and t + s < 1, otherwise distance from segment is
- // computed.
-
- btVector3 d1, d2, a;
- float u, v, w, p, q, r;
- float s, t, dist, dist2;
- btVector3 witness2;
-
- btMprVec3Sub2(&d1, B, x0);
- btMprVec3Sub2(&d2, C, x0);
- btMprVec3Sub2(&a, x0, P);
-
- u = btMprVec3Dot(&a, &a);
- v = btMprVec3Dot(&d1, &d1);
- w = btMprVec3Dot(&d2, &d2);
- p = btMprVec3Dot(&a, &d1);
- q = btMprVec3Dot(&a, &d2);
- r = btMprVec3Dot(&d1, &d2);
-
- btScalar div = (w * v - r * r);
- if (btMprIsZero(div))
- {
- s = -1;
- }
- else
- {
- s = (q * r - w * p) / div;
- t = (-s * r - q) / w;
- }
-
- if ((btMprIsZero(s) || s > 0.f) && (btMprEq(s, 1.f) || s < 1.f) && (btMprIsZero(t) || t > 0.f) && (btMprEq(t, 1.f) || t < 1.f) && (btMprEq(t + s, 1.f) || t + s < 1.f))
- {
- if (witness)
- {
- btMprVec3Scale(&d1, s);
- btMprVec3Scale(&d2, t);
- btMprVec3Copy(witness, x0);
- btMprVec3Add(witness, &d1);
- btMprVec3Add(witness, &d2);
-
- dist = btMprVec3Dist2(witness, P);
- }
- else
- {
- dist = s * s * v;
- dist += t * t * w;
- dist += 2.f * s * t * r;
- dist += 2.f * s * p;
- dist += 2.f * t * q;
- dist += u;
- }
- }
- else
- {
- dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
-
- dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- btMprVec3Copy(witness, &witness2);
- }
-
- dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
- if (dist2 < dist)
- {
- dist = dist2;
- if (witness)
- btMprVec3Copy(witness, &witness2);
- }
- }
-
- return dist;
-}
-
-template <typename btConvexTemplate>
-static void btFindPenetr(const btConvexTemplate &a, const btConvexTemplate &b,
- const btMprCollisionDescription &colDesc,
- btMprSimplex_t *portal,
- float *depth, btVector3 *pdir, btVector3 *pos)
-{
- btVector3 dir;
- btMprSupport_t v4;
- unsigned long iterations;
-
- btVector3 zero = btVector3(0, 0, 0);
- btVector3 *origin = &zero;
-
- iterations = 1UL;
- for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
- //while (1)
- {
- // compute portal direction and obtain next support point
- btPortalDir(portal, &dir);
-
- btMprSupport(a, b, colDesc, dir, &v4);
-
- // reached tolerance -> find penetration info
- if (portalReachTolerance(portal, &v4, &dir) || iterations == BT_MPR_MAX_ITERATIONS)
- {
- *depth = btMprVec3PointTriDist2(origin, &btMprSimplexPoint(portal, 1)->v, &btMprSimplexPoint(portal, 2)->v, &btMprSimplexPoint(portal, 3)->v, pdir);
- *depth = BT_MPR_SQRT(*depth);
-
- if (btMprIsZero((*pdir).x()) && btMprIsZero((*pdir).y()) && btMprIsZero((*pdir).z()))
- {
- *pdir = dir;
- }
- btMprVec3Normalize(pdir);
-
- // barycentric coordinates:
- btFindPos(portal, pos);
-
- return;
- }
-
- btExpandPortal(portal, &v4);
-
- iterations++;
- }
-}
-
-static void btFindPenetrTouch(btMprSimplex_t *portal, float *depth, btVector3 *dir, btVector3 *pos)
-{
- // Touching contact on portal's v1 - so depth is zero and direction
- // is unimportant and pos can be guessed
- *depth = 0.f;
- btVector3 zero = btVector3(0, 0, 0);
- btVector3 *origin = &zero;
-
- btMprVec3Copy(dir, origin);
-#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
- btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
- btMprVec3Scale(pos, 0.5);
-#else
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
-#endif
-}
-
-static void btFindPenetrSegment(btMprSimplex_t *portal,
- float *depth, btVector3 *dir, btVector3 *pos)
-{
- // Origin lies on v0-v1 segment.
- // Depth is distance to v1, direction also and position must be
- // computed
-#ifdef MPR_AVERAGE_CONTACT_POSITIONS
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
- btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
- btMprVec3Scale(pos, 0.5f);
-#else
- btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
-#endif //MPR_AVERAGE_CONTACT_POSITIONS
-
- btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
- *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
- btMprVec3Normalize(dir);
-}
-
-template <typename btConvexTemplate>
-inline int btMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b,
- const btMprCollisionDescription &colDesc,
- float *depthOut, btVector3 *dirOut, btVector3 *posOut)
-{
- btMprSimplex_t portal;
-
- // Phase 1: Portal discovery
- int result = btDiscoverPortal(a, b, colDesc, &portal);
-
- //sepAxis[pairIndex] = *pdir;//or -dir?
-
- switch (result)
- {
- case 0:
- {
- // Phase 2: Portal refinement
-
- result = btRefinePortal(a, b, colDesc, &portal);
- if (result < 0)
- return -1;
-
- // Phase 3. Penetration info
- btFindPenetr(a, b, colDesc, &portal, depthOut, dirOut, posOut);
-
- break;
- }
- case 1:
- {
- // Touching contact on portal's v1.
- btFindPenetrTouch(&portal, depthOut, dirOut, posOut);
- result = 0;
- break;
- }
- case 2:
- {
- btFindPenetrSegment(&portal, depthOut, dirOut, posOut);
- result = 0;
- break;
- }
- default:
- {
- //if (res < 0)
- //{
- // Origin isn't inside portal - no collision.
- result = -1;
- //}
- }
- };
-
- return result;
-};
-
-template <typename btConvexTemplate, typename btMprDistanceTemplate>
-inline int btComputeMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprDistanceTemplate *distInfo)
-{
- btVector3 dir, pos;
- float depth;
-
- int res = btMprPenetration(a, b, colDesc, &depth, &dir, &pos);
- if (res == 0)
- {
- distInfo->m_distance = -depth;
- distInfo->m_pointOnB = pos;
- distInfo->m_normalBtoA = -dir;
- distInfo->m_pointOnA = pos - distInfo->m_distance * dir;
- return 0;
- }
-
- return -1;
-}
-
-#endif //BT_MPR_PENETRATION_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
deleted file mode 100644
index dca3e09267..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btPersistentManifold.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btSerializer.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btCollisionObjectData btCollisionObjectDoubleData
-#else
-#define btCollisionObjectData btCollisionObjectFloatData
-#endif
-
-btScalar gContactBreakingThreshold = btScalar(0.02);
-ContactDestroyedCallback gContactDestroyedCallback = 0;
-ContactProcessedCallback gContactProcessedCallback = 0;
-ContactStartedCallback gContactStartedCallback = 0;
-ContactEndedCallback gContactEndedCallback = 0;
-///gContactCalcArea3Points will approximate the convex hull area using 3 points
-///when setting it to false, it will use 4 points to compute the area: it is more accurate but slower
-bool gContactCalcArea3Points = true;
-
-btPersistentManifold::btPersistentManifold()
- : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
- m_body0(0),
- m_body1(0),
- m_cachedPoints(0),
- m_companionIdA(0),
- m_companionIdB(0),
- m_index1a(0)
-{
-}
-
-#ifdef DEBUG_PERSISTENCY
-#include <stdio.h>
-void btPersistentManifold::DebugPersistency()
-{
- int i;
- printf("DebugPersistency : numPoints %d\n", m_cachedPoints);
- for (i = 0; i < m_cachedPoints; i++)
- {
- printf("m_pointCache[%d].m_userPersistentData = %x\n", i, m_pointCache[i].m_userPersistentData);
- }
-}
-#endif //DEBUG_PERSISTENCY
-
-void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
-{
- void* oldPtr = pt.m_userPersistentData;
- if (oldPtr)
- {
-#ifdef DEBUG_PERSISTENCY
- int i;
- int occurance = 0;
- for (i = 0; i < m_cachedPoints; i++)
- {
- if (m_pointCache[i].m_userPersistentData == oldPtr)
- {
- occurance++;
- if (occurance > 1)
- printf("error in clearUserCache\n");
- }
- }
- btAssert(occurance <= 0);
-#endif //DEBUG_PERSISTENCY
-
- if (pt.m_userPersistentData && gContactDestroyedCallback)
- {
- (*gContactDestroyedCallback)(pt.m_userPersistentData);
- pt.m_userPersistentData = 0;
- }
-
-#ifdef DEBUG_PERSISTENCY
- DebugPersistency();
-#endif
- }
-}
-
-static inline btScalar calcArea4Points(const btVector3& p0, const btVector3& p1, const btVector3& p2, const btVector3& p3)
-{
- // It calculates possible 3 area constructed from random 4 points and returns the biggest one.
-
- btVector3 a[3], b[3];
- a[0] = p0 - p1;
- a[1] = p0 - p2;
- a[2] = p0 - p3;
- b[0] = p2 - p3;
- b[1] = p1 - p3;
- b[2] = p1 - p2;
-
- //todo: Following 3 cross production can be easily optimized by SIMD.
- btVector3 tmp0 = a[0].cross(b[0]);
- btVector3 tmp1 = a[1].cross(b[1]);
- btVector3 tmp2 = a[2].cross(b[2]);
-
- return btMax(btMax(tmp0.length2(), tmp1.length2()), tmp2.length2());
-}
-
-int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt)
-{
- //calculate 4 possible cases areas, and take biggest area
- //also need to keep 'deepest'
-
- int maxPenetrationIndex = -1;
-#define KEEP_DEEPEST_POINT 1
-#ifdef KEEP_DEEPEST_POINT
- btScalar maxPenetration = pt.getDistance();
- for (int i = 0; i < 4; i++)
- {
- if (m_pointCache[i].getDistance() < maxPenetration)
- {
- maxPenetrationIndex = i;
- maxPenetration = m_pointCache[i].getDistance();
- }
- }
-#endif //KEEP_DEEPEST_POINT
-
- btScalar res0(btScalar(0.)), res1(btScalar(0.)), res2(btScalar(0.)), res3(btScalar(0.));
-
- if (gContactCalcArea3Points)
- {
- if (maxPenetrationIndex != 0)
- {
- btVector3 a0 = pt.m_localPointA - m_pointCache[1].m_localPointA;
- btVector3 b0 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
- btVector3 cross = a0.cross(b0);
- res0 = cross.length2();
- }
- if (maxPenetrationIndex != 1)
- {
- btVector3 a1 = pt.m_localPointA - m_pointCache[0].m_localPointA;
- btVector3 b1 = m_pointCache[3].m_localPointA - m_pointCache[2].m_localPointA;
- btVector3 cross = a1.cross(b1);
- res1 = cross.length2();
- }
-
- if (maxPenetrationIndex != 2)
- {
- btVector3 a2 = pt.m_localPointA - m_pointCache[0].m_localPointA;
- btVector3 b2 = m_pointCache[3].m_localPointA - m_pointCache[1].m_localPointA;
- btVector3 cross = a2.cross(b2);
- res2 = cross.length2();
- }
-
- if (maxPenetrationIndex != 3)
- {
- btVector3 a3 = pt.m_localPointA - m_pointCache[0].m_localPointA;
- btVector3 b3 = m_pointCache[2].m_localPointA - m_pointCache[1].m_localPointA;
- btVector3 cross = a3.cross(b3);
- res3 = cross.length2();
- }
- }
- else
- {
- if (maxPenetrationIndex != 0)
- {
- res0 = calcArea4Points(pt.m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
- }
-
- if (maxPenetrationIndex != 1)
- {
- res1 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[2].m_localPointA, m_pointCache[3].m_localPointA);
- }
-
- if (maxPenetrationIndex != 2)
- {
- res2 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[3].m_localPointA);
- }
-
- if (maxPenetrationIndex != 3)
- {
- res3 = calcArea4Points(pt.m_localPointA, m_pointCache[0].m_localPointA, m_pointCache[1].m_localPointA, m_pointCache[2].m_localPointA);
- }
- }
- btVector4 maxvec(res0, res1, res2, res3);
- int biggestarea = maxvec.closestAxis4();
- return biggestarea;
-}
-
-int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
-{
- btScalar shortestDist = getContactBreakingThreshold() * getContactBreakingThreshold();
- int size = getNumContacts();
- int nearestPoint = -1;
- for (int i = 0; i < size; i++)
- {
- const btManifoldPoint& mp = m_pointCache[i];
-
- btVector3 diffA = mp.m_localPointA - newPoint.m_localPointA;
- const btScalar distToManiPoint = diffA.dot(diffA);
- if (distToManiPoint < shortestDist)
- {
- shortestDist = distToManiPoint;
- nearestPoint = i;
- }
- }
- return nearestPoint;
-}
-
-int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive)
-{
- if (!isPredictive)
- {
- btAssert(validContactDistance(newPoint));
- }
-
- int insertIndex = getNumContacts();
- if (insertIndex == MANIFOLD_CACHE_SIZE)
- {
-#if MANIFOLD_CACHE_SIZE >= 4
- //sort cache so best points come first, based on area
- insertIndex = sortCachedPoints(newPoint);
-#else
- insertIndex = 0;
-#endif
- clearUserCache(m_pointCache[insertIndex]);
- }
- else
- {
- m_cachedPoints++;
- }
- if (insertIndex < 0)
- insertIndex = 0;
-
- btAssert(m_pointCache[insertIndex].m_userPersistentData == 0);
- m_pointCache[insertIndex] = newPoint;
- return insertIndex;
-}
-
-btScalar btPersistentManifold::getContactBreakingThreshold() const
-{
- return m_contactBreakingThreshold;
-}
-
-void btPersistentManifold::refreshContactPoints(const btTransform& trA, const btTransform& trB)
-{
- int i;
-#ifdef DEBUG_PERSISTENCY
- printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
- trA.getOrigin().getX(),
- trA.getOrigin().getY(),
- trA.getOrigin().getZ(),
- trB.getOrigin().getX(),
- trB.getOrigin().getY(),
- trB.getOrigin().getZ());
-#endif //DEBUG_PERSISTENCY
- /// first refresh worldspace positions and distance
- for (i = getNumContacts() - 1; i >= 0; i--)
- {
- btManifoldPoint& manifoldPoint = m_pointCache[i];
- manifoldPoint.m_positionWorldOnA = trA(manifoldPoint.m_localPointA);
- manifoldPoint.m_positionWorldOnB = trB(manifoldPoint.m_localPointB);
- manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA - manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
- manifoldPoint.m_lifeTime++;
- }
-
- /// then
- btScalar distance2d;
- btVector3 projectedDifference, projectedPoint;
- for (i = getNumContacts() - 1; i >= 0; i--)
- {
- btManifoldPoint& manifoldPoint = m_pointCache[i];
- //contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
- if (!validContactDistance(manifoldPoint))
- {
- removeContactPoint(i);
- }
- else
- {
- //todo: friction anchor may require the contact to be around a bit longer
- //contact also becomes invalid when relative movement orthogonal to normal exceeds margin
- projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
- projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
- distance2d = projectedDifference.dot(projectedDifference);
- if (distance2d > getContactBreakingThreshold() * getContactBreakingThreshold())
- {
- removeContactPoint(i);
- }
- else
- {
- //contact point processed callback
- if (gContactProcessedCallback)
- (*gContactProcessedCallback)(manifoldPoint, (void*)m_body0, (void*)m_body1);
- }
- }
- }
-#ifdef DEBUG_PERSISTENCY
- DebugPersistency();
-#endif //
-}
-
-int btPersistentManifold::calculateSerializeBufferSize() const
-{
- return sizeof(btPersistentManifoldData);
-}
-
-const char* btPersistentManifold::serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const
-{
- btPersistentManifoldData* dataOut = (btPersistentManifoldData*)dataBuffer;
- memset(dataOut, 0, sizeof(btPersistentManifoldData));
-
- dataOut->m_body0 = (btCollisionObjectData*)serializer->getUniquePointer((void*)manifold->getBody0());
- dataOut->m_body1 = (btCollisionObjectData*)serializer->getUniquePointer((void*)manifold->getBody1());
- dataOut->m_contactBreakingThreshold = manifold->getContactBreakingThreshold();
- dataOut->m_contactProcessingThreshold = manifold->getContactProcessingThreshold();
- dataOut->m_numCachedPoints = manifold->getNumContacts();
- dataOut->m_companionIdA = manifold->m_companionIdA;
- dataOut->m_companionIdB = manifold->m_companionIdB;
- dataOut->m_index1a = manifold->m_index1a;
- dataOut->m_objectType = manifold->m_objectType;
-
- for (int i = 0; i < this->getNumContacts(); i++)
- {
- const btManifoldPoint& pt = manifold->getContactPoint(i);
- dataOut->m_pointCacheAppliedImpulse[i] = pt.m_appliedImpulse;
- dataOut->m_pointCachePrevRHS[i] = pt.m_prevRHS;
- dataOut->m_pointCacheAppliedImpulseLateral1[i] = pt.m_appliedImpulseLateral1;
- dataOut->m_pointCacheAppliedImpulseLateral2[i] = pt.m_appliedImpulseLateral2;
- pt.m_localPointA.serialize(dataOut->m_pointCacheLocalPointA[i]);
- pt.m_localPointB.serialize(dataOut->m_pointCacheLocalPointB[i]);
- pt.m_normalWorldOnB.serialize(dataOut->m_pointCacheNormalWorldOnB[i]);
- dataOut->m_pointCacheDistance[i] = pt.m_distance1;
- dataOut->m_pointCacheCombinedContactDamping1[i] = pt.m_combinedContactDamping1;
- dataOut->m_pointCacheCombinedContactStiffness1[i] = pt.m_combinedContactStiffness1;
- dataOut->m_pointCacheLifeTime[i] = pt.m_lifeTime;
- dataOut->m_pointCacheFrictionCFM[i] = pt.m_frictionCFM;
- dataOut->m_pointCacheContactERP[i] = pt.m_contactERP;
- dataOut->m_pointCacheContactCFM[i] = pt.m_contactCFM;
- dataOut->m_pointCacheContactPointFlags[i] = pt.m_contactPointFlags;
- dataOut->m_pointCacheIndex0[i] = pt.m_index0;
- dataOut->m_pointCacheIndex1[i] = pt.m_index1;
- dataOut->m_pointCachePartId0[i] = pt.m_partId0;
- dataOut->m_pointCachePartId1[i] = pt.m_partId1;
- pt.m_positionWorldOnA.serialize(dataOut->m_pointCachePositionWorldOnA[i]);
- pt.m_positionWorldOnB.serialize(dataOut->m_pointCachePositionWorldOnB[i]);
- dataOut->m_pointCacheCombinedFriction[i] = pt.m_combinedFriction;
- pt.m_lateralFrictionDir1.serialize(dataOut->m_pointCacheLateralFrictionDir1[i]);
- pt.m_lateralFrictionDir2.serialize(dataOut->m_pointCacheLateralFrictionDir2[i]);
- dataOut->m_pointCacheCombinedRollingFriction[i] = pt.m_combinedRollingFriction;
- dataOut->m_pointCacheCombinedSpinningFriction[i] = pt.m_combinedSpinningFriction;
- dataOut->m_pointCacheCombinedRestitution[i] = pt.m_combinedRestitution;
- dataOut->m_pointCacheContactMotion1[i] = pt.m_contactMotion1;
- dataOut->m_pointCacheContactMotion2[i] = pt.m_contactMotion2;
- }
- return btPersistentManifoldDataName;
-}
-
-void btPersistentManifold::deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr)
-{
- m_contactBreakingThreshold = manifoldDataPtr->m_contactBreakingThreshold;
- m_contactProcessingThreshold = manifoldDataPtr->m_contactProcessingThreshold;
- m_cachedPoints = manifoldDataPtr->m_numCachedPoints;
- m_companionIdA = manifoldDataPtr->m_companionIdA;
- m_companionIdB = manifoldDataPtr->m_companionIdB;
- //m_index1a = manifoldDataPtr->m_index1a;
- m_objectType = manifoldDataPtr->m_objectType;
-
- for (int i = 0; i < this->getNumContacts(); i++)
- {
- btManifoldPoint& pt = m_pointCache[i];
-
- pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
- pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
- pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
- pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
- pt.m_localPointA.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointA[i]);
- pt.m_localPointB.deSerializeDouble(manifoldDataPtr->m_pointCacheLocalPointB[i]);
- pt.m_normalWorldOnB.deSerializeDouble(manifoldDataPtr->m_pointCacheNormalWorldOnB[i]);
- pt.m_distance1 = manifoldDataPtr->m_pointCacheDistance[i];
- pt.m_combinedContactDamping1 = manifoldDataPtr->m_pointCacheCombinedContactDamping1[i];
- pt.m_combinedContactStiffness1 = manifoldDataPtr->m_pointCacheCombinedContactStiffness1[i];
- pt.m_lifeTime = manifoldDataPtr->m_pointCacheLifeTime[i];
- pt.m_frictionCFM = manifoldDataPtr->m_pointCacheFrictionCFM[i];
- pt.m_contactERP = manifoldDataPtr->m_pointCacheContactERP[i];
- pt.m_contactCFM = manifoldDataPtr->m_pointCacheContactCFM[i];
- pt.m_contactPointFlags = manifoldDataPtr->m_pointCacheContactPointFlags[i];
- pt.m_index0 = manifoldDataPtr->m_pointCacheIndex0[i];
- pt.m_index1 = manifoldDataPtr->m_pointCacheIndex1[i];
- pt.m_partId0 = manifoldDataPtr->m_pointCachePartId0[i];
- pt.m_partId1 = manifoldDataPtr->m_pointCachePartId1[i];
- pt.m_positionWorldOnA.deSerializeDouble(manifoldDataPtr->m_pointCachePositionWorldOnA[i]);
- pt.m_positionWorldOnB.deSerializeDouble(manifoldDataPtr->m_pointCachePositionWorldOnB[i]);
- pt.m_combinedFriction = manifoldDataPtr->m_pointCacheCombinedFriction[i];
- pt.m_lateralFrictionDir1.deSerializeDouble(manifoldDataPtr->m_pointCacheLateralFrictionDir1[i]);
- pt.m_lateralFrictionDir2.deSerializeDouble(manifoldDataPtr->m_pointCacheLateralFrictionDir2[i]);
- pt.m_combinedRollingFriction = manifoldDataPtr->m_pointCacheCombinedRollingFriction[i];
- pt.m_combinedSpinningFriction = manifoldDataPtr->m_pointCacheCombinedSpinningFriction[i];
- pt.m_combinedRestitution = manifoldDataPtr->m_pointCacheCombinedRestitution[i];
- pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
- pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
- }
-}
-
-void btPersistentManifold::deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr)
-{
- m_contactBreakingThreshold = manifoldDataPtr->m_contactBreakingThreshold;
- m_contactProcessingThreshold = manifoldDataPtr->m_contactProcessingThreshold;
- m_cachedPoints = manifoldDataPtr->m_numCachedPoints;
- m_companionIdA = manifoldDataPtr->m_companionIdA;
- m_companionIdB = manifoldDataPtr->m_companionIdB;
- //m_index1a = manifoldDataPtr->m_index1a;
- m_objectType = manifoldDataPtr->m_objectType;
-
- for (int i = 0; i < this->getNumContacts(); i++)
- {
- btManifoldPoint& pt = m_pointCache[i];
-
- pt.m_appliedImpulse = manifoldDataPtr->m_pointCacheAppliedImpulse[i];
- pt.m_prevRHS = manifoldDataPtr->m_pointCachePrevRHS[i];
- pt.m_appliedImpulseLateral1 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral1[i];
- pt.m_appliedImpulseLateral2 = manifoldDataPtr->m_pointCacheAppliedImpulseLateral2[i];
- pt.m_localPointA.deSerialize(manifoldDataPtr->m_pointCacheLocalPointA[i]);
- pt.m_localPointB.deSerialize(manifoldDataPtr->m_pointCacheLocalPointB[i]);
- pt.m_normalWorldOnB.deSerialize(manifoldDataPtr->m_pointCacheNormalWorldOnB[i]);
- pt.m_distance1 = manifoldDataPtr->m_pointCacheDistance[i];
- pt.m_combinedContactDamping1 = manifoldDataPtr->m_pointCacheCombinedContactDamping1[i];
- pt.m_combinedContactStiffness1 = manifoldDataPtr->m_pointCacheCombinedContactStiffness1[i];
- pt.m_lifeTime = manifoldDataPtr->m_pointCacheLifeTime[i];
- pt.m_frictionCFM = manifoldDataPtr->m_pointCacheFrictionCFM[i];
- pt.m_contactERP = manifoldDataPtr->m_pointCacheContactERP[i];
- pt.m_contactCFM = manifoldDataPtr->m_pointCacheContactCFM[i];
- pt.m_contactPointFlags = manifoldDataPtr->m_pointCacheContactPointFlags[i];
- pt.m_index0 = manifoldDataPtr->m_pointCacheIndex0[i];
- pt.m_index1 = manifoldDataPtr->m_pointCacheIndex1[i];
- pt.m_partId0 = manifoldDataPtr->m_pointCachePartId0[i];
- pt.m_partId1 = manifoldDataPtr->m_pointCachePartId1[i];
- pt.m_positionWorldOnA.deSerialize(manifoldDataPtr->m_pointCachePositionWorldOnA[i]);
- pt.m_positionWorldOnB.deSerialize(manifoldDataPtr->m_pointCachePositionWorldOnB[i]);
- pt.m_combinedFriction = manifoldDataPtr->m_pointCacheCombinedFriction[i];
- pt.m_lateralFrictionDir1.deSerialize(manifoldDataPtr->m_pointCacheLateralFrictionDir1[i]);
- pt.m_lateralFrictionDir2.deSerialize(manifoldDataPtr->m_pointCacheLateralFrictionDir2[i]);
- pt.m_combinedRollingFriction = manifoldDataPtr->m_pointCacheCombinedRollingFriction[i];
- pt.m_combinedSpinningFriction = manifoldDataPtr->m_pointCacheCombinedSpinningFriction[i];
- pt.m_combinedRestitution = manifoldDataPtr->m_pointCacheCombinedRestitution[i];
- pt.m_contactMotion1 = manifoldDataPtr->m_pointCacheContactMotion1[i];
- pt.m_contactMotion2 = manifoldDataPtr->m_pointCacheContactMotion2[i];
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
deleted file mode 100644
index 0e26da0ebe..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_PERSISTENT_MANIFOLD_H
-#define BT_PERSISTENT_MANIFOLD_H
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-#include "btManifoldPoint.h"
-class btCollisionObject;
-#include "LinearMath/btAlignedAllocator.h"
-
-struct btCollisionResult;
-struct btCollisionObjectDoubleData;
-struct btCollisionObjectFloatData;
-
-///maximum contact breaking and merging threshold
-extern btScalar gContactBreakingThreshold;
-
-#ifndef SWIG
-class btPersistentManifold;
-
-typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
-typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp, void* body0, void* body1);
-typedef void (*ContactStartedCallback)(btPersistentManifold* const& manifold);
-typedef void (*ContactEndedCallback)(btPersistentManifold* const& manifold);
-extern ContactDestroyedCallback gContactDestroyedCallback;
-extern ContactProcessedCallback gContactProcessedCallback;
-extern ContactStartedCallback gContactStartedCallback;
-extern ContactEndedCallback gContactEndedCallback;
-#endif //SWIG
-
-//the enum starts at 1024 to avoid type conflicts with btTypedConstraint
-enum btContactManifoldTypes
-{
- MIN_CONTACT_MANIFOLD_TYPE = 1024,
- BT_PERSISTENT_MANIFOLD_TYPE
-};
-
-#define MANIFOLD_CACHE_SIZE 4
-
-///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
-///Those contact points are created by the collision narrow phase.
-///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
-///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
-///reduces the cache to 4 points, when more then 4 points are added, using following rules:
-///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
-///note that some pairs of objects might have more then one contact manifold.
-
-//ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
-ATTRIBUTE_ALIGNED16(class)
-btPersistentManifold : public btTypedObject
-{
- btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
-
- /// this two body pointers can point to the physics rigidbody class.
- const btCollisionObject* m_body0;
- const btCollisionObject* m_body1;
-
- int m_cachedPoints;
-
- btScalar m_contactBreakingThreshold;
- btScalar m_contactProcessingThreshold;
-
- /// sort cached points so most isolated points come first
- int sortCachedPoints(const btManifoldPoint& pt);
-
- int findContactPoint(const btManifoldPoint* unUsed, int numUnused, const btManifoldPoint& pt);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_companionIdA;
- int m_companionIdB;
-
- int m_index1a;
-
- btPersistentManifold();
-
- btPersistentManifold(const btCollisionObject* body0, const btCollisionObject* body1, int, btScalar contactBreakingThreshold, btScalar contactProcessingThreshold)
- : btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
- m_body0(body0),
- m_body1(body1),
- m_cachedPoints(0),
- m_contactBreakingThreshold(contactBreakingThreshold),
- m_contactProcessingThreshold(contactProcessingThreshold),
- m_companionIdA(0),
- m_companionIdB(0),
- m_index1a(0)
- {
- }
-
- SIMD_FORCE_INLINE const btCollisionObject* getBody0() const { return m_body0; }
- SIMD_FORCE_INLINE const btCollisionObject* getBody1() const { return m_body1; }
-
- void setBodies(const btCollisionObject* body0, const btCollisionObject* body1)
- {
- m_body0 = body0;
- m_body1 = body1;
- }
-
- void clearUserCache(btManifoldPoint & pt);
-
-#ifdef DEBUG_PERSISTENCY
- void DebugPersistency();
-#endif //
-
- SIMD_FORCE_INLINE int getNumContacts() const
- {
- return m_cachedPoints;
- }
- /// the setNumContacts API is usually not used, except when you gather/fill all contacts manually
- void setNumContacts(int cachedPoints)
- {
- m_cachedPoints = cachedPoints;
- }
-
- SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
- {
- btAssert(index < m_cachedPoints);
- return m_pointCache[index];
- }
-
- SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
- {
- btAssert(index < m_cachedPoints);
- return m_pointCache[index];
- }
-
- ///@todo: get this margin from the current physics / collision environment
- btScalar getContactBreakingThreshold() const;
-
- btScalar getContactProcessingThreshold() const
- {
- return m_contactProcessingThreshold;
- }
-
- void setContactBreakingThreshold(btScalar contactBreakingThreshold)
- {
- m_contactBreakingThreshold = contactBreakingThreshold;
- }
-
- void setContactProcessingThreshold(btScalar contactProcessingThreshold)
- {
- m_contactProcessingThreshold = contactProcessingThreshold;
- }
-
- int getCacheEntry(const btManifoldPoint& newPoint) const;
-
- int addManifoldPoint(const btManifoldPoint& newPoint, bool isPredictive = false);
-
- void removeContactPoint(int index)
- {
- clearUserCache(m_pointCache[index]);
-
- int lastUsedIndex = getNumContacts() - 1;
- // m_pointCache[index] = m_pointCache[lastUsedIndex];
- if (index != lastUsedIndex)
- {
- m_pointCache[index] = m_pointCache[lastUsedIndex];
- //get rid of duplicated userPersistentData pointer
- m_pointCache[lastUsedIndex].m_userPersistentData = 0;
- m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
- m_pointCache[lastUsedIndex].m_prevRHS = 0.f;
- m_pointCache[lastUsedIndex].m_contactPointFlags = 0;
- m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
- m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
- m_pointCache[lastUsedIndex].m_lifeTime = 0;
- }
-
- btAssert(m_pointCache[lastUsedIndex].m_userPersistentData == 0);
- m_cachedPoints--;
-
- if (gContactEndedCallback && m_cachedPoints == 0)
- {
- gContactEndedCallback(this);
- }
- }
- void replaceContactPoint(const btManifoldPoint& newPoint, int insertIndex)
- {
- btAssert(validContactDistance(newPoint));
-
-#define MAINTAIN_PERSISTENCY 1
-#ifdef MAINTAIN_PERSISTENCY
- int lifeTime = m_pointCache[insertIndex].getLifeTime();
- btScalar appliedImpulse = m_pointCache[insertIndex].m_appliedImpulse;
- btScalar prevRHS = m_pointCache[insertIndex].m_prevRHS;
- btScalar appliedLateralImpulse1 = m_pointCache[insertIndex].m_appliedImpulseLateral1;
- btScalar appliedLateralImpulse2 = m_pointCache[insertIndex].m_appliedImpulseLateral2;
-
- bool replacePoint = true;
- ///we keep existing contact points for friction anchors
- ///if the friction force is within the Coulomb friction cone
- if (newPoint.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
- {
- // printf("appliedImpulse=%f\n", appliedImpulse);
- // printf("appliedLateralImpulse1=%f\n", appliedLateralImpulse1);
- // printf("appliedLateralImpulse2=%f\n", appliedLateralImpulse2);
- // printf("mu = %f\n", m_pointCache[insertIndex].m_combinedFriction);
- btScalar mu = m_pointCache[insertIndex].m_combinedFriction;
- btScalar eps = 0; //we could allow to enlarge or shrink the tolerance to check against the friction cone a bit, say 1e-7
- btScalar a = appliedLateralImpulse1 * appliedLateralImpulse1 + appliedLateralImpulse2 * appliedLateralImpulse2;
- btScalar b = eps + mu * appliedImpulse;
- b = b * b;
- replacePoint = (a) > (b);
- }
-
- if (replacePoint)
- {
- btAssert(lifeTime >= 0);
- void* cache = m_pointCache[insertIndex].m_userPersistentData;
-
- m_pointCache[insertIndex] = newPoint;
- m_pointCache[insertIndex].m_userPersistentData = cache;
- m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
- m_pointCache[insertIndex].m_prevRHS = prevRHS;
- m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
- m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
- }
-
- m_pointCache[insertIndex].m_lifeTime = lifeTime;
-#else
- clearUserCache(m_pointCache[insertIndex]);
- m_pointCache[insertIndex] = newPoint;
-
-#endif
- }
-
- bool validContactDistance(const btManifoldPoint& pt) const
- {
- return pt.m_distance1 <= getContactBreakingThreshold();
- }
- /// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
- void refreshContactPoints(const btTransform& trA, const btTransform& trB);
-
- SIMD_FORCE_INLINE void clearManifold()
- {
- int i;
- for (i = 0; i < m_cachedPoints; i++)
- {
- clearUserCache(m_pointCache[i]);
- }
-
- if (gContactEndedCallback && m_cachedPoints)
- {
- gContactEndedCallback(this);
- }
- m_cachedPoints = 0;
- }
-
- int calculateSerializeBufferSize() const;
- const char* serialize(const class btPersistentManifold* manifold, void* dataBuffer, class btSerializer* serializer) const;
- void deSerialize(const struct btPersistentManifoldDoubleData* manifoldDataPtr);
- void deSerialize(const struct btPersistentManifoldFloatData* manifoldDataPtr);
-};
-
-// clang-format off
-
-struct btPersistentManifoldDoubleData
-{
- btVector3DoubleData m_pointCacheLocalPointA[4];
- btVector3DoubleData m_pointCacheLocalPointB[4];
- btVector3DoubleData m_pointCachePositionWorldOnA[4];
- btVector3DoubleData m_pointCachePositionWorldOnB[4];
- btVector3DoubleData m_pointCacheNormalWorldOnB[4];
- btVector3DoubleData m_pointCacheLateralFrictionDir1[4];
- btVector3DoubleData m_pointCacheLateralFrictionDir2[4];
- double m_pointCacheDistance[4];
- double m_pointCacheAppliedImpulse[4];
- double m_pointCachePrevRHS[4];
- double m_pointCacheCombinedFriction[4];
- double m_pointCacheCombinedRollingFriction[4];
- double m_pointCacheCombinedSpinningFriction[4];
- double m_pointCacheCombinedRestitution[4];
- int m_pointCachePartId0[4];
- int m_pointCachePartId1[4];
- int m_pointCacheIndex0[4];
- int m_pointCacheIndex1[4];
- int m_pointCacheContactPointFlags[4];
- double m_pointCacheAppliedImpulseLateral1[4];
- double m_pointCacheAppliedImpulseLateral2[4];
- double m_pointCacheContactMotion1[4];
- double m_pointCacheContactMotion2[4];
- double m_pointCacheContactCFM[4];
- double m_pointCacheCombinedContactStiffness1[4];
- double m_pointCacheContactERP[4];
- double m_pointCacheCombinedContactDamping1[4];
- double m_pointCacheFrictionCFM[4];
- int m_pointCacheLifeTime[4];
-
- int m_numCachedPoints;
- int m_companionIdA;
- int m_companionIdB;
- int m_index1a;
-
- int m_objectType;
- double m_contactBreakingThreshold;
- double m_contactProcessingThreshold;
- int m_padding;
-
- btCollisionObjectDoubleData *m_body0;
- btCollisionObjectDoubleData *m_body1;
-};
-
-
-struct btPersistentManifoldFloatData
-{
- btVector3FloatData m_pointCacheLocalPointA[4];
- btVector3FloatData m_pointCacheLocalPointB[4];
- btVector3FloatData m_pointCachePositionWorldOnA[4];
- btVector3FloatData m_pointCachePositionWorldOnB[4];
- btVector3FloatData m_pointCacheNormalWorldOnB[4];
- btVector3FloatData m_pointCacheLateralFrictionDir1[4];
- btVector3FloatData m_pointCacheLateralFrictionDir2[4];
- float m_pointCacheDistance[4];
- float m_pointCacheAppliedImpulse[4];
- float m_pointCachePrevRHS[4];
- float m_pointCacheCombinedFriction[4];
- float m_pointCacheCombinedRollingFriction[4];
- float m_pointCacheCombinedSpinningFriction[4];
- float m_pointCacheCombinedRestitution[4];
- int m_pointCachePartId0[4];
- int m_pointCachePartId1[4];
- int m_pointCacheIndex0[4];
- int m_pointCacheIndex1[4];
- int m_pointCacheContactPointFlags[4];
- float m_pointCacheAppliedImpulseLateral1[4];
- float m_pointCacheAppliedImpulseLateral2[4];
- float m_pointCacheContactMotion1[4];
- float m_pointCacheContactMotion2[4];
- float m_pointCacheContactCFM[4];
- float m_pointCacheCombinedContactStiffness1[4];
- float m_pointCacheContactERP[4];
- float m_pointCacheCombinedContactDamping1[4];
- float m_pointCacheFrictionCFM[4];
- int m_pointCacheLifeTime[4];
-
- int m_numCachedPoints;
- int m_companionIdA;
- int m_companionIdB;
- int m_index1a;
-
- int m_objectType;
- float m_contactBreakingThreshold;
- float m_contactProcessingThreshold;
- int m_padding;
-
- btCollisionObjectFloatData *m_body0;
- btCollisionObjectFloatData *m_body1;
-};
-
-// clang-format on
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btPersistentManifoldData btPersistentManifoldDoubleData
-#define btPersistentManifoldDataName "btPersistentManifoldDoubleData"
-#else
-#define btPersistentManifoldData btPersistentManifoldFloatData
-#define btPersistentManifoldDataName "btPersistentManifoldFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-#endif //BT_PERSISTENT_MANIFOLD_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
deleted file mode 100644
index 0900eb6e85..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_POINT_COLLECTOR_H
-#define BT_POINT_COLLECTOR_H
-
-#include "btDiscreteCollisionDetectorInterface.h"
-
-struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
-{
- btVector3 m_normalOnBInWorld;
- btVector3 m_pointInWorld;
- btScalar m_distance; //negative means penetration
-
- bool m_hasResult;
-
- btPointCollector()
- : m_distance(btScalar(BT_LARGE_FLOAT)), m_hasResult(false)
- {
- }
-
- virtual void setShapeIdentifiersA(int partId0, int index0)
- {
- (void)partId0;
- (void)index0;
- }
- virtual void setShapeIdentifiersB(int partId1, int index1)
- {
- (void)partId1;
- (void)index1;
- }
-
- virtual void addContactPoint(const btVector3& normalOnBInWorld, const btVector3& pointInWorld, btScalar depth)
- {
- if (depth < m_distance)
- {
- m_hasResult = true;
- m_normalOnBInWorld = normalOnBInWorld;
- m_pointInWorld = pointInWorld;
- //negative means penetration
- m_distance = depth;
- }
- }
-};
-
-#endif //BT_POINT_COLLECTOR_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
deleted file mode 100644
index 9d1836037d..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-///Separating axis rest based on work from Pierre Terdiman, see
-///And contact clipping based on work from Simon Hobbs
-
-#include "btPolyhedralContactClipping.h"
-#include "BulletCollision/CollisionShapes/btConvexPolyhedron.h"
-
-#include <float.h> //for FLT_MAX
-
-int gExpectedNbTests = 0;
-int gActualNbTests = 0;
-bool gUseInternalObject = true;
-
-// Clips a face to the back of a plane
-void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS)
-{
- int ve;
- btScalar ds, de;
- int numVerts = pVtxIn.size();
- if (numVerts < 2)
- return;
-
- btVector3 firstVertex = pVtxIn[pVtxIn.size() - 1];
- btVector3 endVertex = pVtxIn[0];
-
- ds = planeNormalWS.dot(firstVertex) + planeEqWS;
-
- for (ve = 0; ve < numVerts; ve++)
- {
- endVertex = pVtxIn[ve];
-
- de = planeNormalWS.dot(endVertex) + planeEqWS;
-
- if (ds < 0)
- {
- if (de < 0)
- {
- // Start < 0, end < 0, so output endVertex
- ppVtxOut.push_back(endVertex);
- }
- else
- {
- // Start < 0, end >= 0, so output intersection
- ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
- }
- }
- else
- {
- if (de < 0)
- {
- // Start >= 0, end < 0 so output intersection and end
- ppVtxOut.push_back(firstVertex.lerp(endVertex, btScalar(ds * 1.f / (ds - de))));
- ppVtxOut.push_back(endVertex);
- }
- }
- firstVertex = endVertex;
- ds = de;
- }
-}
-
-static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btVector3& sep_axis, btScalar& depth, btVector3& witnessPointA, btVector3& witnessPointB)
-{
- btScalar Min0, Max0;
- btScalar Min1, Max1;
- btVector3 witnesPtMinA, witnesPtMaxA;
- btVector3 witnesPtMinB, witnesPtMaxB;
-
- hullA.project(transA, sep_axis, Min0, Max0, witnesPtMinA, witnesPtMaxA);
- hullB.project(transB, sep_axis, Min1, Max1, witnesPtMinB, witnesPtMaxB);
-
- if (Max0 < Min1 || Max1 < Min0)
- return false;
-
- btScalar d0 = Max0 - Min1;
- btAssert(d0 >= 0.0f);
- btScalar d1 = Max1 - Min0;
- btAssert(d1 >= 0.0f);
- if (d0 < d1)
- {
- depth = d0;
- witnessPointA = witnesPtMaxA;
- witnessPointB = witnesPtMinB;
- }
- else
- {
- depth = d1;
- witnessPointA = witnesPtMinA;
- witnessPointB = witnesPtMaxB;
- }
-
- return true;
-}
-
-static int gActualSATPairTests = 0;
-
-inline bool IsAlmostZero(const btVector3& v)
-{
- if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
- return true;
-}
-
-#ifdef TEST_INTERNAL_OBJECTS
-
-inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3])
-{
- // This version is ~11.000 cycles (4%) faster overall in one of the tests.
- // IR(p[0]) = IR(extents[0])|(IR(sv[0])&SIGN_BITMASK);
- // IR(p[1]) = IR(extents[1])|(IR(sv[1])&SIGN_BITMASK);
- // IR(p[2]) = IR(extents[2])|(IR(sv[2])&SIGN_BITMASK);
- p[0] = sv[0] < 0.0f ? -extents[0] : extents[0];
- p[1] = sv[1] < 0.0f ? -extents[1] : extents[1];
- p[2] = sv[2] < 0.0f ? -extents[2] : extents[2];
-}
-
-void InverseTransformPoint3x3(btVector3& out, const btVector3& in, const btTransform& tr)
-{
- const btMatrix3x3& rot = tr.getBasis();
- const btVector3& r0 = rot[0];
- const btVector3& r1 = rot[1];
- const btVector3& r2 = rot[2];
-
- const btScalar x = r0.x() * in.x() + r1.x() * in.y() + r2.x() * in.z();
- const btScalar y = r0.y() * in.x() + r1.y() * in.y() + r2.y() * in.z();
- const btScalar z = r0.z() * in.x() + r1.z() * in.y() + r2.z() * in.z();
-
- out.setValue(x, y, z);
-}
-
-bool TestInternalObjects(const btTransform& trans0, const btTransform& trans1, const btVector3& delta_c, const btVector3& axis, const btConvexPolyhedron& convex0, const btConvexPolyhedron& convex1, btScalar dmin)
-{
- const btScalar dp = delta_c.dot(axis);
-
- btVector3 localAxis0;
- InverseTransformPoint3x3(localAxis0, axis, trans0);
- btVector3 localAxis1;
- InverseTransformPoint3x3(localAxis1, axis, trans1);
-
- btScalar p0[3];
- BoxSupport(convex0.m_extents, localAxis0, p0);
- btScalar p1[3];
- BoxSupport(convex1.m_extents, localAxis1, p1);
-
- const btScalar Radius0 = p0[0] * localAxis0.x() + p0[1] * localAxis0.y() + p0[2] * localAxis0.z();
- const btScalar Radius1 = p1[0] * localAxis1.x() + p1[1] * localAxis1.y() + p1[2] * localAxis1.z();
-
- const btScalar MinRadius = Radius0 > convex0.m_radius ? Radius0 : convex0.m_radius;
- const btScalar MaxRadius = Radius1 > convex1.m_radius ? Radius1 : convex1.m_radius;
-
- const btScalar MinMaxRadius = MaxRadius + MinRadius;
- const btScalar d0 = MinMaxRadius + dp;
- const btScalar d1 = MinMaxRadius - dp;
-
- const btScalar depth = d0 < d1 ? d0 : d1;
- if (depth > dmin)
- return false;
- return true;
-}
-#endif //TEST_INTERNAL_OBJECTS
-
-SIMD_FORCE_INLINE void btSegmentsClosestPoints(
- btVector3& ptsVector,
- btVector3& offsetA,
- btVector3& offsetB,
- btScalar& tA, btScalar& tB,
- const btVector3& translation,
- const btVector3& dirA, btScalar hlenA,
- const btVector3& dirB, btScalar hlenB)
-{
- // compute the parameters of the closest points on each line segment
-
- btScalar dirA_dot_dirB = btDot(dirA, dirB);
- btScalar dirA_dot_trans = btDot(dirA, translation);
- btScalar dirB_dot_trans = btDot(dirB, translation);
-
- btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
-
- if (denom == 0.0f)
- {
- tA = 0.0f;
- }
- else
- {
- tA = (dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB) / denom;
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
-
- tB = tA * dirA_dot_dirB - dirB_dot_trans;
-
- if (tB < -hlenB)
- {
- tB = -hlenB;
- tA = tB * dirA_dot_dirB + dirA_dot_trans;
-
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
- else if (tB > hlenB)
- {
- tB = hlenB;
- tA = tB * dirA_dot_dirB + dirA_dot_trans;
-
- if (tA < -hlenA)
- tA = -hlenA;
- else if (tA > hlenA)
- tA = hlenA;
- }
-
- // compute the closest points relative to segment centers.
-
- offsetA = dirA * tA;
- offsetB = dirB * tB;
-
- ptsVector = translation - offsetA + offsetB;
-}
-
-bool btPolyhedralContactClipping::findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut)
-{
- gActualSATPairTests++;
-
- //#ifdef TEST_INTERNAL_OBJECTS
- const btVector3 c0 = transA * hullA.m_localCenter;
- const btVector3 c1 = transB * hullB.m_localCenter;
- const btVector3 DeltaC2 = c0 - c1;
- //#endif
-
- btScalar dmin = FLT_MAX;
- int curPlaneTests = 0;
-
- int numFacesA = hullA.m_faces.size();
- // Test normals from hullA
- for (int i = 0; i < numFacesA; i++)
- {
- const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]);
- btVector3 faceANormalWS = transA.getBasis() * Normal;
- if (DeltaC2.dot(faceANormalWS) < 0)
- faceANormalWS *= -1.f;
-
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, faceANormalWS, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- btScalar d;
- btVector3 wA, wB;
- if (!TestSepAxis(hullA, hullB, transA, transB, faceANormalWS, d, wA, wB))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = faceANormalWS;
- }
- }
-
- int numFacesB = hullB.m_faces.size();
- // Test normals from hullB
- for (int i = 0; i < numFacesB; i++)
- {
- const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]);
- btVector3 WorldNormal = transB.getBasis() * Normal;
- if (DeltaC2.dot(WorldNormal) < 0)
- WorldNormal *= -1.f;
-
- curPlaneTests++;
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, WorldNormal, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- btScalar d;
- btVector3 wA, wB;
- if (!TestSepAxis(hullA, hullB, transA, transB, WorldNormal, d, wA, wB))
- return false;
-
- if (d < dmin)
- {
- dmin = d;
- sep = WorldNormal;
- }
- }
-
- btVector3 edgeAstart, edgeAend, edgeBstart, edgeBend;
- int edgeA = -1;
- int edgeB = -1;
- btVector3 worldEdgeA;
- btVector3 worldEdgeB;
- btVector3 witnessPointA(0, 0, 0), witnessPointB(0, 0, 0);
-
- int curEdgeEdge = 0;
- // Test edges
- for (int e0 = 0; e0 < hullA.m_uniqueEdges.size(); e0++)
- {
- const btVector3 edge0 = hullA.m_uniqueEdges[e0];
- const btVector3 WorldEdge0 = transA.getBasis() * edge0;
- for (int e1 = 0; e1 < hullB.m_uniqueEdges.size(); e1++)
- {
- const btVector3 edge1 = hullB.m_uniqueEdges[e1];
- const btVector3 WorldEdge1 = transB.getBasis() * edge1;
-
- btVector3 Cross = WorldEdge0.cross(WorldEdge1);
- curEdgeEdge++;
- if (!IsAlmostZero(Cross))
- {
- Cross = Cross.normalize();
- if (DeltaC2.dot(Cross) < 0)
- Cross *= -1.f;
-
-#ifdef TEST_INTERNAL_OBJECTS
- gExpectedNbTests++;
- if (gUseInternalObject && !TestInternalObjects(transA, transB, DeltaC2, Cross, hullA, hullB, dmin))
- continue;
- gActualNbTests++;
-#endif
-
- btScalar dist;
- btVector3 wA, wB;
- if (!TestSepAxis(hullA, hullB, transA, transB, Cross, dist, wA, wB))
- return false;
-
- if (dist < dmin)
- {
- dmin = dist;
- sep = Cross;
- edgeA = e0;
- edgeB = e1;
- worldEdgeA = WorldEdge0;
- worldEdgeB = WorldEdge1;
- witnessPointA = wA;
- witnessPointB = wB;
- }
- }
- }
- }
-
- if (edgeA >= 0 && edgeB >= 0)
- {
- // printf("edge-edge\n");
- //add an edge-edge contact
-
- btVector3 ptsVector;
- btVector3 offsetA;
- btVector3 offsetB;
- btScalar tA;
- btScalar tB;
-
- btVector3 translation = witnessPointB - witnessPointA;
-
- btVector3 dirA = worldEdgeA;
- btVector3 dirB = worldEdgeB;
-
- btScalar hlenB = 1e30f;
- btScalar hlenA = 1e30f;
-
- btSegmentsClosestPoints(ptsVector, offsetA, offsetB, tA, tB,
- translation,
- dirA, hlenA,
- dirB, hlenB);
-
- btScalar nlSqrt = ptsVector.length2();
- if (nlSqrt > SIMD_EPSILON)
- {
- btScalar nl = btSqrt(nlSqrt);
- ptsVector *= 1.f / nl;
- if (ptsVector.dot(DeltaC2) < 0.f)
- {
- ptsVector *= -1.f;
- }
- btVector3 ptOnB = witnessPointB + offsetB;
- btScalar distance = nl;
- resultOut.addContactPoint(ptsVector, ptOnB, -distance);
- }
- }
-
- if ((DeltaC2.dot(sep)) < 0.0f)
- sep = -sep;
-
- return true;
-}
-
-void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut)
-{
- worldVertsB2.resize(0);
- btVertexArray* pVtxIn = &worldVertsB1;
- btVertexArray* pVtxOut = &worldVertsB2;
- pVtxOut->reserve(pVtxIn->size());
-
- int closestFaceA = -1;
- {
- btScalar dmin = FLT_MAX;
- for (int face = 0; face < hullA.m_faces.size(); face++)
- {
- const btVector3 Normal(hullA.m_faces[face].m_plane[0], hullA.m_faces[face].m_plane[1], hullA.m_faces[face].m_plane[2]);
- const btVector3 faceANormalWS = transA.getBasis() * Normal;
-
- btScalar d = faceANormalWS.dot(separatingNormal);
- if (d < dmin)
- {
- dmin = d;
- closestFaceA = face;
- }
- }
- }
- if (closestFaceA < 0)
- return;
-
- const btFace& polyA = hullA.m_faces[closestFaceA];
-
- // clip polygon to back of planes of all faces of hull A that are adjacent to witness face
- int numVerticesA = polyA.m_indices.size();
- for (int e0 = 0; e0 < numVerticesA; e0++)
- {
- const btVector3& a = hullA.m_vertices[polyA.m_indices[e0]];
- const btVector3& b = hullA.m_vertices[polyA.m_indices[(e0 + 1) % numVerticesA]];
- const btVector3 edge0 = a - b;
- const btVector3 WorldEdge0 = transA.getBasis() * edge0;
- btVector3 worldPlaneAnormal1 = transA.getBasis() * btVector3(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
-
- btVector3 planeNormalWS1 = -WorldEdge0.cross(worldPlaneAnormal1); //.cross(WorldEdge0);
- btVector3 worldA1 = transA * a;
- btScalar planeEqWS1 = -worldA1.dot(planeNormalWS1);
-
-//int otherFace=0;
-#ifdef BLA1
- int otherFace = polyA.m_connectedFaces[e0];
- btVector3 localPlaneNormal(hullA.m_faces[otherFace].m_plane[0], hullA.m_faces[otherFace].m_plane[1], hullA.m_faces[otherFace].m_plane[2]);
- btScalar localPlaneEq = hullA.m_faces[otherFace].m_plane[3];
-
- btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
- btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
-#else
- btVector3 planeNormalWS = planeNormalWS1;
- btScalar planeEqWS = planeEqWS1;
-
-#endif
- //clip face
-
- clipFace(*pVtxIn, *pVtxOut, planeNormalWS, planeEqWS);
- btSwap(pVtxIn, pVtxOut);
- pVtxOut->resize(0);
- }
-
- //#define ONLY_REPORT_DEEPEST_POINT
-
- btVector3 point;
-
- // only keep points that are behind the witness face
- {
- btVector3 localPlaneNormal(polyA.m_plane[0], polyA.m_plane[1], polyA.m_plane[2]);
- btScalar localPlaneEq = polyA.m_plane[3];
- btVector3 planeNormalWS = transA.getBasis() * localPlaneNormal;
- btScalar planeEqWS = localPlaneEq - planeNormalWS.dot(transA.getOrigin());
- for (int i = 0; i < pVtxIn->size(); i++)
- {
- btVector3 vtx = pVtxIn->at(i);
- btScalar depth = planeNormalWS.dot(vtx) + planeEqWS;
- if (depth <= minDist)
- {
- // printf("clamped: depth=%f to minDist=%f\n",depth,minDist);
- depth = minDist;
- }
-
- if (depth <= maxDist)
- {
- btVector3 point = pVtxIn->at(i);
-#ifdef ONLY_REPORT_DEEPEST_POINT
- curMaxDist = depth;
-#else
-#if 0
- if (depth<-3)
- {
- printf("error in btPolyhedralContactClipping depth = %f\n", depth);
- printf("likely wrong separatingNormal passed in\n");
- }
-#endif
- resultOut.addContactPoint(separatingNormal, point, depth);
-#endif
- }
- }
- }
-#ifdef ONLY_REPORT_DEEPEST_POINT
- if (curMaxDist < maxDist)
- {
- resultOut.addContactPoint(separatingNormal, point, curMaxDist);
- }
-#endif //ONLY_REPORT_DEEPEST_POINT
-}
-
-void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut)
-{
- btVector3 separatingNormal = separatingNormal1.normalized();
- // const btVector3 c0 = transA * hullA.m_localCenter;
- // const btVector3 c1 = transB * hullB.m_localCenter;
- //const btVector3 DeltaC2 = c0 - c1;
-
- int closestFaceB = -1;
- btScalar dmax = -FLT_MAX;
- {
- for (int face = 0; face < hullB.m_faces.size(); face++)
- {
- const btVector3 Normal(hullB.m_faces[face].m_plane[0], hullB.m_faces[face].m_plane[1], hullB.m_faces[face].m_plane[2]);
- const btVector3 WorldNormal = transB.getBasis() * Normal;
- btScalar d = WorldNormal.dot(separatingNormal);
- if (d > dmax)
- {
- dmax = d;
- closestFaceB = face;
- }
- }
- }
- worldVertsB1.resize(0);
- {
- const btFace& polyB = hullB.m_faces[closestFaceB];
- const int numVertices = polyB.m_indices.size();
- for (int e0 = 0; e0 < numVertices; e0++)
- {
- const btVector3& b = hullB.m_vertices[polyB.m_indices[e0]];
- worldVertsB1.push_back(transB * b);
- }
- }
-
- if (closestFaceB >= 0)
- clipFaceAgainstHull(separatingNormal, hullA, transA, worldVertsB1, worldVertsB2, minDist, maxDist, resultOut);
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
deleted file mode 100644
index 328f6424bc..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_POLYHEDRAL_CONTACT_CLIPPING_H
-#define BT_POLYHEDRAL_CONTACT_CLIPPING_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btTransform.h"
-#include "btDiscreteCollisionDetectorInterface.h"
-
-class btConvexPolyhedron;
-
-typedef btAlignedObjectArray<btVector3> btVertexArray;
-
-// Clips a face to the back of a plane
-struct btPolyhedralContactClipping
-{
- static void clipHullAgainstHull(const btVector3& separatingNormal1, const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, const btScalar minDist, btScalar maxDist, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, btDiscreteCollisionDetectorInterface::Result& resultOut);
-
- static void clipFaceAgainstHull(const btVector3& separatingNormal, const btConvexPolyhedron& hullA, const btTransform& transA, btVertexArray& worldVertsB1, btVertexArray& worldVertsB2, const btScalar minDist, btScalar maxDist, btDiscreteCollisionDetectorInterface::Result& resultOut);
-
- static bool findSeparatingAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA, const btTransform& transB, btVector3& sep, btDiscreteCollisionDetectorInterface::Result& resultOut);
-
- ///the clipFace method is used internally
- static void clipFace(const btVertexArray& pVtxIn, btVertexArray& ppVtxOut, const btVector3& planeNormalWS, btScalar planeEqWS);
-};
-
-#endif // BT_POLYHEDRAL_CONTACT_CLIPPING_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
deleted file mode 100644
index 3d11e5bce5..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//#include <stdio.h>
-
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
-#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
-#include "btRaycastCallback.h"
-
-btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags)
- : m_from(from),
- m_to(to),
- //@BP Mod
- m_flags(flags),
- m_hitFraction(btScalar(1.))
-{
-}
-
-void btTriangleRaycastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
-{
- const btVector3& vert0 = triangle[0];
- const btVector3& vert1 = triangle[1];
- const btVector3& vert2 = triangle[2];
-
- btVector3 v10;
- v10 = vert1 - vert0;
- btVector3 v20;
- v20 = vert2 - vert0;
-
- btVector3 triangleNormal;
- triangleNormal = v10.cross(v20);
-
- const btScalar dist = vert0.dot(triangleNormal);
- btScalar dist_a = triangleNormal.dot(m_from);
- dist_a -= dist;
- btScalar dist_b = triangleNormal.dot(m_to);
- dist_b -= dist;
-
- if (dist_a * dist_b >= btScalar(0.0))
- {
- return; // same sign
- }
-
- if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a <= btScalar(0.0)))
- {
- // Backface, skip check
- return;
- }
-
- const btScalar proj_length = dist_a - dist_b;
- const btScalar distance = (dist_a) / (proj_length);
- // Now we have the intersection point on the plane, we'll see if it's inside the triangle
- // Add an epsilon as a tolerance for the raycast,
- // in case the ray hits exacly on the edge of the triangle.
- // It must be scaled for the triangle size.
-
- if (distance < m_hitFraction)
- {
- btScalar edge_tolerance = triangleNormal.length2();
- edge_tolerance *= btScalar(-0.0001);
- btVector3 point;
- point.setInterpolate3(m_from, m_to, distance);
- {
- btVector3 v0p;
- v0p = vert0 - point;
- btVector3 v1p;
- v1p = vert1 - point;
- btVector3 cp0;
- cp0 = v0p.cross(v1p);
-
- if ((btScalar)(cp0.dot(triangleNormal)) >= edge_tolerance)
- {
- btVector3 v2p;
- v2p = vert2 - point;
- btVector3 cp1;
- cp1 = v1p.cross(v2p);
- if ((btScalar)(cp1.dot(triangleNormal)) >= edge_tolerance)
- {
- btVector3 cp2;
- cp2 = v2p.cross(v0p);
-
- if ((btScalar)(cp2.dot(triangleNormal)) >= edge_tolerance)
- {
- //@BP Mod
- // Triangle normal isn't normalized
- triangleNormal.normalize();
-
- //@BP Mod - Allow for unflipped normal when raycasting against backfaces
- if (((m_flags & kF_KeepUnflippedNormal) == 0) && (dist_a <= btScalar(0.0)))
- {
- m_hitFraction = reportHit(-triangleNormal, distance, partId, triangleIndex);
- }
- else
- {
- m_hitFraction = reportHit(triangleNormal, distance, partId, triangleIndex);
- }
- }
- }
- }
- }
- }
-}
-
-btTriangleConvexcastCallback::btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
-{
- m_convexShape = convexShape;
- m_convexShapeFrom = convexShapeFrom;
- m_convexShapeTo = convexShapeTo;
- m_triangleToWorld = triangleToWorld;
- m_hitFraction = 1.0f;
- m_triangleCollisionMargin = triangleCollisionMargin;
- m_allowedPenetration = 0.f;
-}
-
-void btTriangleConvexcastCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
-{
- btTriangleShape triangleShape(triangle[0], triangle[1], triangle[2]);
- triangleShape.setMargin(m_triangleCollisionMargin);
-
- btVoronoiSimplexSolver simplexSolver;
- btGjkEpaPenetrationDepthSolver gjkEpaPenetrationSolver;
-
-//#define USE_SUBSIMPLEX_CONVEX_CAST 1
-//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
-#ifdef USE_SUBSIMPLEX_CONVEX_CAST
- btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
-#else
- //btGjkConvexCast convexCaster(m_convexShape,&triangleShape,&simplexSolver);
- btContinuousConvexCollision convexCaster(m_convexShape, &triangleShape, &simplexSolver, &gjkEpaPenetrationSolver);
-#endif //#USE_SUBSIMPLEX_CONVEX_CAST
-
- btConvexCast::CastResult castResult;
- castResult.m_fraction = btScalar(1.);
- castResult.m_allowedPenetration = m_allowedPenetration;
- if (convexCaster.calcTimeOfImpact(m_convexShapeFrom, m_convexShapeTo, m_triangleToWorld, m_triangleToWorld, castResult))
- {
- //add hit
- if (castResult.m_normal.length2() > btScalar(0.0001))
- {
- if (castResult.m_fraction < m_hitFraction)
- {
- /* btContinuousConvexCast's normal is already in world space */
- /*
-#ifdef USE_SUBSIMPLEX_CONVEX_CAST
- //rotate normal into worldspace
- castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
-#endif //USE_SUBSIMPLEX_CONVEX_CAST
-*/
- castResult.m_normal.normalize();
-
- reportHit(castResult.m_normal,
- castResult.m_hitPoint,
- castResult.m_fraction,
- partId,
- triangleIndex);
- }
- }
- }
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
deleted file mode 100644
index 2d0df718a2..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_RAYCAST_TRI_CALLBACK_H
-#define BT_RAYCAST_TRI_CALLBACK_H
-
-#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
-#include "LinearMath/btTransform.h"
-struct btBroadphaseProxy;
-class btConvexShape;
-
-class btTriangleRaycastCallback : public btTriangleCallback
-{
-public:
- //input
- btVector3 m_from;
- btVector3 m_to;
-
- //@BP Mod - allow backface filtering and unflipped normals
- enum EFlags
- {
- kF_None = 0,
- kF_FilterBackfaces = 1 << 0,
- kF_KeepUnflippedNormal = 1 << 1, // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
- ///SubSimplexConvexCastRaytest is the default, even if kF_None is set.
- kF_UseSubSimplexConvexCastRaytest = 1 << 2, // Uses an approximate but faster ray versus convex intersection algorithm
- kF_UseGjkConvexCastRaytest = 1 << 3,
- kF_DisableHeightfieldAccelerator = 1 << 4, //don't use the heightfield raycast accelerator. See https://github.com/bulletphysics/bullet3/pull/2062
- kF_Terminator = 0xFFFFFFFF
- };
- unsigned int m_flags;
-
- btScalar m_hitFraction;
-
- btTriangleRaycastCallback(const btVector3& from, const btVector3& to, unsigned int flags = 0);
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
-};
-
-class btTriangleConvexcastCallback : public btTriangleCallback
-{
-public:
- const btConvexShape* m_convexShape;
- btTransform m_convexShapeFrom;
- btTransform m_convexShapeTo;
- btTransform m_triangleToWorld;
- btScalar m_hitFraction;
- btScalar m_triangleCollisionMargin;
- btScalar m_allowedPenetration;
-
- btTriangleConvexcastCallback(const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
- virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
-};
-
-#endif //BT_RAYCAST_TRI_CALLBACK_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
deleted file mode 100644
index ccd227109d..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMPLEX_SOLVER_INTERFACE_H
-#define BT_SIMPLEX_SOLVER_INTERFACE_H
-
-#include "LinearMath/btVector3.h"
-
-#define NO_VIRTUAL_INTERFACE 1
-#ifdef NO_VIRTUAL_INTERFACE
-#include "btVoronoiSimplexSolver.h"
-#define btSimplexSolverInterface btVoronoiSimplexSolver
-#else
-
-/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices
-/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on
-/// voronoi regions or barycentric coordinates
-class btSimplexSolverInterface
-{
-public:
- virtual ~btSimplexSolverInterface(){};
-
- virtual void reset() = 0;
-
- virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
-
- virtual bool closest(btVector3& v) = 0;
-
- virtual btScalar maxVertex() = 0;
-
- virtual bool fullSimplex() const = 0;
-
- virtual int getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const = 0;
-
- virtual bool inSimplex(const btVector3& w) = 0;
-
- virtual void backup_closest(btVector3& v) = 0;
-
- virtual bool emptySimplex() const = 0;
-
- virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
-
- virtual int numVertices() const = 0;
-};
-#endif
-#endif //BT_SIMPLEX_SOLVER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
deleted file mode 100644
index 37458339e7..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSubSimplexConvexCast.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-
-#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
-#include "btPointCollector.h"
-#include "LinearMath/btTransformUtil.h"
-
-btSubsimplexConvexCast::btSubsimplexConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)
- : m_simplexSolver(simplexSolver),
- m_convexA(convexA),
- m_convexB(convexB)
-{
-}
-
-
-bool btSubsimplexConvexCast::calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result)
-{
- m_simplexSolver->reset();
-
- btVector3 linVelA, linVelB;
- linVelA = toA.getOrigin() - fromA.getOrigin();
- linVelB = toB.getOrigin() - fromB.getOrigin();
-
- btScalar lambda = btScalar(0.);
-
- btTransform interpolatedTransA = fromA;
- btTransform interpolatedTransB = fromB;
-
- ///take relative motion
- btVector3 r = (linVelA - linVelB);
- btVector3 v;
-
- btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r * fromA.getBasis()));
- btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r * fromB.getBasis()));
- v = supVertexA - supVertexB;
- int maxIter = result.m_subSimplexCastMaxIterations;
-
- btVector3 n;
- n.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-
- btVector3 c;
-
- btScalar dist2 = v.length2();
-
-
-
- btVector3 w, p;
- btScalar VdotR;
-
- while ((dist2 > result.m_subSimplexCastEpsilon) && maxIter--)
- {
- supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v * interpolatedTransA.getBasis()));
- supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v * interpolatedTransB.getBasis()));
- w = supVertexA - supVertexB;
-
- btScalar VdotW = v.dot(w);
-
- if (lambda > btScalar(1.0))
- {
- return false;
- }
-
- if (VdotW > btScalar(0.))
- {
- VdotR = v.dot(r);
-
- if (VdotR >= -(SIMD_EPSILON * SIMD_EPSILON))
- return false;
- else
- {
- lambda = lambda - VdotW / VdotR;
- //interpolate to next lambda
- // x = s + lambda * r;
- interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(), toA.getOrigin(), lambda);
- interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(), toB.getOrigin(), lambda);
- //m_simplexSolver->reset();
- //check next line
- w = supVertexA - supVertexB;
-
- n = v;
- }
- }
- ///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
- if (!m_simplexSolver->inSimplex(w))
- m_simplexSolver->addVertex(w, supVertexA, supVertexB);
-
- if (m_simplexSolver->closest(v))
- {
- dist2 = v.length2();
-
- //todo: check this normal for validity
- //n=v;
- //printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
- //printf("DIST2=%f\n",dist2);
- //printf("numverts = %i\n",m_simplexSolver->numVertices());
- }
- else
- {
- dist2 = btScalar(0.);
- }
- }
-
- //int numiter = MAX_ITERATIONS - maxIter;
- // printf("number of iterations: %d", numiter);
-
- //don't report a time of impact when moving 'away' from the hitnormal
-
- result.m_fraction = lambda;
- if (n.length2() >= (SIMD_EPSILON * SIMD_EPSILON))
- result.m_normal = n.normalized();
- else
- result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
-
- //don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (result.m_normal.dot(r) >= -result.m_allowedPenetration)
- return false;
-
- btVector3 hitA, hitB;
- m_simplexSolver->compute_points(hitA, hitB);
- result.m_hitPoint = hitB;
- return true;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
deleted file mode 100644
index 0638a30eb1..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SUBSIMPLEX_CONVEX_CAST_H
-#define BT_SUBSIMPLEX_CONVEX_CAST_H
-
-#include "btConvexCast.h"
-#include "btSimplexSolverInterface.h"
-class btConvexShape;
-
-/// btSubsimplexConvexCast implements Gino van den Bergens' paper
-///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
-/// GJK based Ray Cast, optimized version
-/// Objects should not start in overlap, otherwise results are not defined.
-class btSubsimplexConvexCast : public btConvexCast
-{
- btSimplexSolverInterface* m_simplexSolver;
- const btConvexShape* m_convexA;
- const btConvexShape* m_convexB;
-
-public:
- btSubsimplexConvexCast(const btConvexShape* shapeA, const btConvexShape* shapeB, btSimplexSolverInterface* simplexSolver);
-
- //virtual ~btSubsimplexConvexCast();
- ///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
- ///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
- virtual bool calcTimeOfImpact(
- const btTransform& fromA,
- const btTransform& toA,
- const btTransform& fromB,
- const btTransform& toB,
- CastResult& result);
-};
-
-#endif //BT_SUBSIMPLEX_CONVEX_CAST_H
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
deleted file mode 100644
index 8fda94d2ad..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
- Elsevier CDROM license agreements grants nonexclusive license to use the software
- for any purpose, commercial or non-commercial as long as the following credit is included
- identifying the original source of the software:
-
- Parts of the source are "from the book Real-Time Collision Detection by
- Christer Ericson, published by Morgan Kaufmann Publishers,
- (c) 2005 Elsevier Inc."
-
-*/
-
-#include "btVoronoiSimplexSolver.h"
-
-#define VERTA 0
-#define VERTB 1
-#define VERTC 2
-#define VERTD 3
-
-#define CATCH_DEGENERATE_TETRAHEDRON 1
-void btVoronoiSimplexSolver::removeVertex(int index)
-{
- btAssert(m_numVertices > 0);
- m_numVertices--;
- m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
- m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
- m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
-}
-
-void btVoronoiSimplexSolver::reduceVertices(const btUsageBitfield& usedVerts)
-{
- if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
- removeVertex(3);
-
- if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
- removeVertex(2);
-
- if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
- removeVertex(1);
-
- if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
- removeVertex(0);
-}
-
-//clear the simplex, remove all the vertices
-void btVoronoiSimplexSolver::reset()
-{
- m_cachedValidClosest = false;
- m_numVertices = 0;
- m_needsUpdate = true;
- m_lastW = btVector3(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_cachedBC.reset();
-}
-
-//add a vertex
-void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
-{
- m_lastW = w;
- m_needsUpdate = true;
-
- m_simplexVectorW[m_numVertices] = w;
- m_simplexPointsP[m_numVertices] = p;
- m_simplexPointsQ[m_numVertices] = q;
-
- m_numVertices++;
-}
-
-bool btVoronoiSimplexSolver::updateClosestVectorAndPoints()
-{
- if (m_needsUpdate)
- {
- m_cachedBC.reset();
-
- m_needsUpdate = false;
-
- switch (numVertices())
- {
- case 0:
- m_cachedValidClosest = false;
- break;
- case 1:
- {
- m_cachedP1 = m_simplexPointsP[0];
- m_cachedP2 = m_simplexPointsQ[0];
- m_cachedV = m_cachedP1 - m_cachedP2; //== m_simplexVectorW[0]
- m_cachedBC.reset();
- m_cachedBC.setBarycentricCoordinates(btScalar(1.), btScalar(0.), btScalar(0.), btScalar(0.));
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
- };
- case 2:
- {
- //closest point origin from line segment
- const btVector3& from = m_simplexVectorW[0];
- const btVector3& to = m_simplexVectorW[1];
- btVector3 nearest;
-
- btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
- btVector3 diff = p - from;
- btVector3 v = to - from;
- btScalar t = v.dot(diff);
-
- if (t > 0)
- {
- btScalar dotVV = v.dot(v);
- if (t < dotVV)
- {
- t /= dotVV;
- diff -= t * v;
- m_cachedBC.m_usedVertices.usedVertexA = true;
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- else
- {
- t = 1;
- diff -= v;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexB = true;
- }
- }
- else
- {
- t = 0;
- //reduce to 1 point
- m_cachedBC.m_usedVertices.usedVertexA = true;
- }
- m_cachedBC.setBarycentricCoordinates(1 - t, t);
- nearest = from + t * v;
-
- m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
- m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
-
- m_cachedValidClosest = m_cachedBC.isValid();
- break;
- }
- case 3:
- {
- //closest point origin from triangle
- btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
-
- const btVector3& a = m_simplexVectorW[0];
- const btVector3& b = m_simplexVectorW[1];
- const btVector3& c = m_simplexVectorW[2];
-
- closestPtPointTriangle(p, a, b, c, m_cachedBC);
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2];
-
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2];
-
- m_cachedV = m_cachedP1 - m_cachedP2;
-
- reduceVertices(m_cachedBC.m_usedVertices);
- m_cachedValidClosest = m_cachedBC.isValid();
-
- break;
- }
- case 4:
- {
- btVector3 p(btScalar(0.), btScalar(0.), btScalar(0.));
-
- const btVector3& a = m_simplexVectorW[0];
- const btVector3& b = m_simplexVectorW[1];
- const btVector3& c = m_simplexVectorW[2];
- const btVector3& d = m_simplexVectorW[3];
-
- bool hasSeparation = closestPtPointTetrahedron(p, a, b, c, d, m_cachedBC);
-
- if (hasSeparation)
- {
- m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
-
- m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
- m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
- m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
- m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
-
- m_cachedV = m_cachedP1 - m_cachedP2;
- reduceVertices(m_cachedBC.m_usedVertices);
- }
- else
- {
- // printf("sub distance got penetration\n");
-
- if (m_cachedBC.m_degenerate)
- {
- m_cachedValidClosest = false;
- }
- else
- {
- m_cachedValidClosest = true;
- //degenerate case == false, penetration = true + zero
- m_cachedV.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- }
- break;
- }
-
- m_cachedValidClosest = m_cachedBC.isValid();
-
- //closest point origin from tetrahedron
- break;
- }
- default:
- {
- m_cachedValidClosest = false;
- }
- };
- }
-
- return m_cachedValidClosest;
-}
-
-//return/calculate the closest vertex
-bool btVoronoiSimplexSolver::closest(btVector3& v)
-{
- bool succes = updateClosestVectorAndPoints();
- v = m_cachedV;
- return succes;
-}
-
-btScalar btVoronoiSimplexSolver::maxVertex()
-{
- int i, numverts = numVertices();
- btScalar maxV = btScalar(0.);
- for (i = 0; i < numverts; i++)
- {
- btScalar curLen2 = m_simplexVectorW[i].length2();
- if (maxV < curLen2)
- maxV = curLen2;
- }
- return maxV;
-}
-
-//return the current simplex
-int btVoronoiSimplexSolver::getSimplex(btVector3* pBuf, btVector3* qBuf, btVector3* yBuf) const
-{
- int i;
- for (i = 0; i < numVertices(); i++)
- {
- yBuf[i] = m_simplexVectorW[i];
- pBuf[i] = m_simplexPointsP[i];
- qBuf[i] = m_simplexPointsQ[i];
- }
- return numVertices();
-}
-
-bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
-{
- bool found = false;
- int i, numverts = numVertices();
- //btScalar maxV = btScalar(0.);
-
- //w is in the current (reduced) simplex
- for (i = 0; i < numverts; i++)
- {
-#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
- if (m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
-#else
- if (m_simplexVectorW[i] == w)
-#endif
- {
- found = true;
- break;
- }
- }
-
- //check in case lastW is already removed
- if (w == m_lastW)
- return true;
-
- return found;
-}
-
-void btVoronoiSimplexSolver::backup_closest(btVector3& v)
-{
- v = m_cachedV;
-}
-
-bool btVoronoiSimplexSolver::emptySimplex() const
-{
- return (numVertices() == 0);
-}
-
-void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2)
-{
- updateClosestVectorAndPoints();
- p1 = m_cachedP1;
- p2 = m_cachedP2;
-}
-
-bool btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result)
-{
- result.m_usedVertices.reset();
-
- // Check if P in vertex region outside A
- btVector3 ab = b - a;
- btVector3 ac = c - a;
- btVector3 ap = p - a;
- btScalar d1 = ab.dot(ap);
- btScalar d2 = ac.dot(ap);
- if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0))
- {
- result.m_closestPointOnSimplex = a;
- result.m_usedVertices.usedVertexA = true;
- result.setBarycentricCoordinates(1, 0, 0);
- return true; // a; // barycentric coordinates (1,0,0)
- }
-
- // Check if P in vertex region outside B
- btVector3 bp = p - b;
- btScalar d3 = ab.dot(bp);
- btScalar d4 = ac.dot(bp);
- if (d3 >= btScalar(0.0) && d4 <= d3)
- {
- result.m_closestPointOnSimplex = b;
- result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(0, 1, 0);
-
- return true; // b; // barycentric coordinates (0,1,0)
- }
- // Check if P in edge region of AB, if so return projection of P onto AB
- btScalar vc = d1 * d4 - d3 * d2;
- if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0))
- {
- btScalar v = d1 / (d1 - d3);
- result.m_closestPointOnSimplex = a + v * ab;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexB = true;
- result.setBarycentricCoordinates(1 - v, v, 0);
- return true;
- //return a + v * ab; // barycentric coordinates (1-v,v,0)
- }
-
- // Check if P in vertex region outside C
- btVector3 cp = p - c;
- btScalar d5 = ab.dot(cp);
- btScalar d6 = ac.dot(cp);
- if (d6 >= btScalar(0.0) && d5 <= d6)
- {
- result.m_closestPointOnSimplex = c;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0, 0, 1);
- return true; //c; // barycentric coordinates (0,0,1)
- }
-
- // Check if P in edge region of AC, if so return projection of P onto AC
- btScalar vb = d5 * d2 - d1 * d6;
- if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0))
- {
- btScalar w = d2 / (d2 - d6);
- result.m_closestPointOnSimplex = a + w * ac;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1 - w, 0, w);
- return true;
- //return a + w * ac; // barycentric coordinates (1-w,0,w)
- }
-
- // Check if P in edge region of BC, if so return projection of P onto BC
- btScalar va = d3 * d6 - d5 * d4;
- if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0))
- {
- btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
-
- result.m_closestPointOnSimplex = b + w * (c - b);
- result.m_usedVertices.usedVertexB = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(0, 1 - w, w);
- return true;
- // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
- }
-
- // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
- btScalar denom = btScalar(1.0) / (va + vb + vc);
- btScalar v = vb * denom;
- btScalar w = vc * denom;
-
- result.m_closestPointOnSimplex = a + ab * v + ac * w;
- result.m_usedVertices.usedVertexA = true;
- result.m_usedVertices.usedVertexB = true;
- result.m_usedVertices.usedVertexC = true;
- result.setBarycentricCoordinates(1 - v - w, v, w);
-
- return true;
- // return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
-}
-
-/// Test if point p and d lie on opposite sides of plane through abc
-int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
-{
- btVector3 normal = (b - a).cross(c - a);
-
- btScalar signp = (p - a).dot(normal); // [AP AB AC]
- btScalar signd = (d - a).dot(normal); // [AD AB AC]
-
-#ifdef CATCH_DEGENERATE_TETRAHEDRON
-#ifdef BT_USE_DOUBLE_PRECISION
- if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
- {
- return -1;
- }
-#else
- if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
- {
- // printf("affine dependent/degenerate\n");//
- return -1;
- }
-#endif
-
-#endif
- // Points on opposite sides if expression signs are opposite
- return signp * signd < btScalar(0.);
-}
-
-bool btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
-{
- btSubSimplexClosestResult tempResult;
-
- // Start out assuming point inside all halfspaces, so closest to itself
- finalResult.m_closestPointOnSimplex = p;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = true;
- finalResult.m_usedVertices.usedVertexB = true;
- finalResult.m_usedVertices.usedVertexC = true;
- finalResult.m_usedVertices.usedVertexD = true;
-
- int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
- int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
- int pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
- int pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
-
- if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
- {
- finalResult.m_degenerate = true;
- return false;
- }
-
- if (!pointOutsideABC && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
- {
- return false;
- }
-
- btScalar bestSqDist = FLT_MAX;
- // If point outside face abc then compute closest point on abc
- if (pointOutsideABC)
- {
- closestPtPointTriangle(p, a, b, c, tempResult);
- btVector3 q = tempResult.m_closestPointOnSimplex;
-
- btScalar sqDist = (q - p).dot(q - p);
- // Update best closest point if (squared) distance is less than current best
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- //convert result bitmask!
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC],
- 0);
- }
- }
-
- // Repeat test for face acd
- if (pointOutsideACD)
- {
- closestPtPointTriangle(p, a, c, d, tempResult);
- btVector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
-
- btScalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
-
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- 0,
- tempResult.m_barycentricCoords[VERTB],
- tempResult.m_barycentricCoords[VERTC]);
- }
- }
- // Repeat test for face adb
-
- if (pointOutsideADB)
- {
- closestPtPointTriangle(p, a, d, b, tempResult);
- btVector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
-
- btScalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
-
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
- finalResult.setBarycentricCoordinates(
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- 0,
- tempResult.m_barycentricCoords[VERTB]);
- }
- }
- // Repeat test for face bdc
-
- if (pointOutsideBDC)
- {
- closestPtPointTriangle(p, b, d, c, tempResult);
- btVector3 q = tempResult.m_closestPointOnSimplex;
- //convert result bitmask!
- btScalar sqDist = (q - p).dot(q - p);
- if (sqDist < bestSqDist)
- {
- bestSqDist = sqDist;
- finalResult.m_closestPointOnSimplex = q;
- finalResult.m_usedVertices.reset();
- //
- finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
- finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
- finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
-
- finalResult.setBarycentricCoordinates(
- 0,
- tempResult.m_barycentricCoords[VERTA],
- tempResult.m_barycentricCoords[VERTC],
- tempResult.m_barycentricCoords[VERTB]);
- }
- }
-
- //help! we ended up full !
-
- if (finalResult.m_usedVertices.usedVertexA &&
- finalResult.m_usedVertices.usedVertexB &&
- finalResult.m_usedVertices.usedVertexC &&
- finalResult.m_usedVertices.usedVertexD)
- {
- return true;
- }
-
- return true;
-}
diff --git a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
deleted file mode 100644
index 24a0a8f2df..0000000000
--- a/thirdparty/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_VORONOI_SIMPLEX_SOLVER_H
-#define BT_VORONOI_SIMPLEX_SOLVER_H
-
-#include "btSimplexSolverInterface.h"
-
-#define VORONOI_SIMPLEX_MAX_VERTS 5
-
-///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
-#define BT_USE_EQUAL_VERTEX_THRESHOLD
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 1e-12f
-#else
-#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
-#endif //BT_USE_DOUBLE_PRECISION
-
-struct btUsageBitfield
-{
- btUsageBitfield()
- {
- reset();
- }
-
- void reset()
- {
- usedVertexA = false;
- usedVertexB = false;
- usedVertexC = false;
- usedVertexD = false;
- }
- unsigned short usedVertexA : 1;
- unsigned short usedVertexB : 1;
- unsigned short usedVertexC : 1;
- unsigned short usedVertexD : 1;
- unsigned short unused1 : 1;
- unsigned short unused2 : 1;
- unsigned short unused3 : 1;
- unsigned short unused4 : 1;
-};
-
-struct btSubSimplexClosestResult
-{
- btVector3 m_closestPointOnSimplex;
- //MASK for m_usedVertices
- //stores the simplex vertex-usage, using the MASK,
- // if m_usedVertices & MASK then the related vertex is used
- btUsageBitfield m_usedVertices;
- btScalar m_barycentricCoords[4];
- bool m_degenerate;
-
- void reset()
- {
- m_degenerate = false;
- setBarycentricCoordinates();
- m_usedVertices.reset();
- }
- bool isValid()
- {
- bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
- (m_barycentricCoords[1] >= btScalar(0.)) &&
- (m_barycentricCoords[2] >= btScalar(0.)) &&
- (m_barycentricCoords[3] >= btScalar(0.));
-
- return valid;
- }
- void setBarycentricCoordinates(btScalar a = btScalar(0.), btScalar b = btScalar(0.), btScalar c = btScalar(0.), btScalar d = btScalar(0.))
- {
- m_barycentricCoords[0] = a;
- m_barycentricCoords[1] = b;
- m_barycentricCoords[2] = c;
- m_barycentricCoords[3] = d;
- }
-};
-
-/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
-/// Can be used with GJK, as an alternative to Johnson distance algorithm.
-#ifdef NO_VIRTUAL_INTERFACE
-ATTRIBUTE_ALIGNED16(class)
-btVoronoiSimplexSolver
-#else
-ATTRIBUTE_ALIGNED16(class)
-btVoronoiSimplexSolver : public btSimplexSolverInterface
-#endif
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- int m_numVertices;
-
- btVector3 m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
- btVector3 m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
- btVector3 m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
-
- btVector3 m_cachedP1;
- btVector3 m_cachedP2;
- btVector3 m_cachedV;
- btVector3 m_lastW;
-
- btScalar m_equalVertexThreshold;
- bool m_cachedValidClosest;
-
- btSubSimplexClosestResult m_cachedBC;
-
- bool m_needsUpdate;
-
- void removeVertex(int index);
- void reduceVertices(const btUsageBitfield& usedVerts);
- bool updateClosestVectorAndPoints();
-
- bool closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
- int pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
- bool closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, btSubSimplexClosestResult& result);
-
-public:
- btVoronoiSimplexSolver()
- : m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
- {
- }
- void reset();
-
- void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
-
- void setEqualVertexThreshold(btScalar threshold)
- {
- m_equalVertexThreshold = threshold;
- }
-
- btScalar getEqualVertexThreshold() const
- {
- return m_equalVertexThreshold;
- }
-
- bool closest(btVector3 & v);
-
- btScalar maxVertex();
-
- bool fullSimplex() const
- {
- return (m_numVertices == 4);
- }
-
- int getSimplex(btVector3 * pBuf, btVector3 * qBuf, btVector3 * yBuf) const;
-
- bool inSimplex(const btVector3& w);
-
- void backup_closest(btVector3 & v);
-
- bool emptySimplex() const;
-
- void compute_points(btVector3 & p1, btVector3 & p2);
-
- int numVertices() const
- {
- return m_numVertices;
- }
-};
-
-#endif //BT_VORONOI_SIMPLEX_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h b/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
deleted file mode 100644
index 2ccf317b92..0000000000
--- a/thirdparty/bullet/BulletDynamics/Character/btCharacterControllerInterface.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CHARACTER_CONTROLLER_INTERFACE_H
-#define BT_CHARACTER_CONTROLLER_INTERFACE_H
-
-#include "LinearMath/btVector3.h"
-#include "BulletDynamics/Dynamics/btActionInterface.h"
-
-class btCollisionShape;
-class btRigidBody;
-class btCollisionWorld;
-
-class btCharacterControllerInterface : public btActionInterface
-{
-public:
- btCharacterControllerInterface(){};
- virtual ~btCharacterControllerInterface(){};
-
- virtual void setWalkDirection(const btVector3& walkDirection) = 0;
- virtual void setVelocityForTimeInterval(const btVector3& velocity, btScalar timeInterval) = 0;
- virtual void reset(btCollisionWorld* collisionWorld) = 0;
- virtual void warp(const btVector3& origin) = 0;
-
- virtual void preStep(btCollisionWorld* collisionWorld) = 0;
- virtual void playerStep(btCollisionWorld* collisionWorld, btScalar dt) = 0;
- virtual bool canJump() const = 0;
- virtual void jump(const btVector3& dir = btVector3(0, 0, 0)) = 0;
-
- virtual bool onGround() const = 0;
- virtual void setUpInterpolate(bool value) = 0;
-};
-
-#endif //BT_CHARACTER_CONTROLLER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
deleted file mode 100644
index 2bbccb291c..0000000000
--- a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.cpp
+++ /dev/null
@@ -1,996 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include <stdio.h>
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionDispatch/btGhostObject.h"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include "LinearMath/btDefaultMotionState.h"
-#include "btKinematicCharacterController.h"
-
-// static helper method
-static btVector3
-getNormalizedVector(const btVector3& v)
-{
- btVector3 n(0, 0, 0);
-
- if (v.length() > SIMD_EPSILON)
- {
- n = v.normalized();
- }
- return n;
-}
-
-///@todo Interact with dynamic objects,
-///Ride kinematicly animated platforms properly
-///More realistic (or maybe just a config option) falling
-/// -> Should integrate falling velocity manually and use that in stepDown()
-///Support jumping
-///Support ducking
-class btKinematicClosestNotMeRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
-{
-public:
- btKinematicClosestNotMeRayResultCallback(btCollisionObject* me) : btCollisionWorld::ClosestRayResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0))
- {
- m_me = me;
- }
-
- virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
- {
- if (rayResult.m_collisionObject == m_me)
- return 1.0;
-
- return ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
- }
-
-protected:
- btCollisionObject* m_me;
-};
-
-class btKinematicClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
-{
-public:
- btKinematicClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& up, btScalar minSlopeDot)
- : btCollisionWorld::ClosestConvexResultCallback(btVector3(0.0, 0.0, 0.0), btVector3(0.0, 0.0, 0.0)), m_me(me), m_up(up), m_minSlopeDot(minSlopeDot)
- {
- }
-
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
- {
- if (convexResult.m_hitCollisionObject == m_me)
- return btScalar(1.0);
-
- if (!convexResult.m_hitCollisionObject->hasContactResponse())
- return btScalar(1.0);
-
- btVector3 hitNormalWorld;
- if (normalInWorldSpace)
- {
- hitNormalWorld = convexResult.m_hitNormalLocal;
- }
- else
- {
- ///need to transform normal into worldspace
- hitNormalWorld = convexResult.m_hitCollisionObject->getWorldTransform().getBasis() * convexResult.m_hitNormalLocal;
- }
-
- btScalar dotUp = m_up.dot(hitNormalWorld);
- if (dotUp < m_minSlopeDot)
- {
- return btScalar(1.0);
- }
-
- return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
- }
-
-protected:
- btCollisionObject* m_me;
- const btVector3 m_up;
- btScalar m_minSlopeDot;
-};
-
-/*
- * Returns the reflection direction of a ray going 'direction' hitting a surface with normal 'normal'
- *
- * from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html
- */
-btVector3 btKinematicCharacterController::computeReflectionDirection(const btVector3& direction, const btVector3& normal)
-{
- return direction - (btScalar(2.0) * direction.dot(normal)) * normal;
-}
-
-/*
- * Returns the portion of 'direction' that is parallel to 'normal'
- */
-btVector3 btKinematicCharacterController::parallelComponent(const btVector3& direction, const btVector3& normal)
-{
- btScalar magnitude = direction.dot(normal);
- return normal * magnitude;
-}
-
-/*
- * Returns the portion of 'direction' that is perpindicular to 'normal'
- */
-btVector3 btKinematicCharacterController::perpindicularComponent(const btVector3& direction, const btVector3& normal)
-{
- return direction - parallelComponent(direction, normal);
-}
-
-btKinematicCharacterController::btKinematicCharacterController(btPairCachingGhostObject* ghostObject, btConvexShape* convexShape, btScalar stepHeight, const btVector3& up)
-{
- m_ghostObject = ghostObject;
- m_up.setValue(0.0f, 0.0f, 1.0f);
- m_jumpAxis.setValue(0.0f, 0.0f, 1.0f);
- m_addedMargin = 0.02;
- m_walkDirection.setValue(0.0, 0.0, 0.0);
- m_AngVel.setValue(0.0, 0.0, 0.0);
- m_useGhostObjectSweepTest = true;
- m_turnAngle = btScalar(0.0);
- m_convexShape = convexShape;
- m_useWalkDirection = true; // use walk direction by default, legacy behavior
- m_velocityTimeInterval = 0.0;
- m_verticalVelocity = 0.0;
- m_verticalOffset = 0.0;
- m_gravity = 9.8 * 3.0; // 3G acceleration.
- m_fallSpeed = 55.0; // Terminal velocity of a sky diver in m/s.
- m_jumpSpeed = 10.0; // ?
- m_SetjumpSpeed = m_jumpSpeed;
- m_wasOnGround = false;
- m_wasJumping = false;
- m_interpolateUp = true;
- m_currentStepOffset = 0.0;
- m_maxPenetrationDepth = 0.2;
- full_drop = false;
- bounce_fix = false;
- m_linearDamping = btScalar(0.0);
- m_angularDamping = btScalar(0.0);
-
- setUp(up);
- setStepHeight(stepHeight);
- setMaxSlope(btRadians(45.0));
-}
-
-btKinematicCharacterController::~btKinematicCharacterController()
-{
-}
-
-btPairCachingGhostObject* btKinematicCharacterController::getGhostObject()
-{
- return m_ghostObject;
-}
-
-bool btKinematicCharacterController::recoverFromPenetration(btCollisionWorld* collisionWorld)
-{
- // Here we must refresh the overlapping paircache as the penetrating movement itself or the
- // previous recovery iteration might have used setWorldTransform and pushed us into an object
- // that is not in the previous cache contents from the last timestep, as will happen if we
- // are pushed into a new AABB overlap. Unhandled this means the next convex sweep gets stuck.
- //
- // Do this by calling the broadphase's setAabb with the moved AABB, this will update the broadphase
- // paircache and the ghostobject's internal paircache at the same time. /BW
-
- btVector3 minAabb, maxAabb;
- m_convexShape->getAabb(m_ghostObject->getWorldTransform(), minAabb, maxAabb);
- collisionWorld->getBroadphase()->setAabb(m_ghostObject->getBroadphaseHandle(),
- minAabb,
- maxAabb,
- collisionWorld->getDispatcher());
-
- bool penetration = false;
-
- collisionWorld->getDispatcher()->dispatchAllCollisionPairs(m_ghostObject->getOverlappingPairCache(), collisionWorld->getDispatchInfo(), collisionWorld->getDispatcher());
-
- m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
-
- // btScalar maxPen = btScalar(0.0);
- for (int i = 0; i < m_ghostObject->getOverlappingPairCache()->getNumOverlappingPairs(); i++)
- {
- m_manifoldArray.resize(0);
-
- btBroadphasePair* collisionPair = &m_ghostObject->getOverlappingPairCache()->getOverlappingPairArray()[i];
-
- btCollisionObject* obj0 = static_cast<btCollisionObject*>(collisionPair->m_pProxy0->m_clientObject);
- btCollisionObject* obj1 = static_cast<btCollisionObject*>(collisionPair->m_pProxy1->m_clientObject);
-
- if ((obj0 && !obj0->hasContactResponse()) || (obj1 && !obj1->hasContactResponse()))
- continue;
-
- if (!needsCollision(obj0, obj1))
- continue;
-
- if (collisionPair->m_algorithm)
- collisionPair->m_algorithm->getAllContactManifolds(m_manifoldArray);
-
- for (int j = 0; j < m_manifoldArray.size(); j++)
- {
- btPersistentManifold* manifold = m_manifoldArray[j];
- btScalar directionSign = manifold->getBody0() == m_ghostObject ? btScalar(-1.0) : btScalar(1.0);
- for (int p = 0; p < manifold->getNumContacts(); p++)
- {
- const btManifoldPoint& pt = manifold->getContactPoint(p);
-
- btScalar dist = pt.getDistance();
-
- if (dist < -m_maxPenetrationDepth)
- {
- // TODO: cause problems on slopes, not sure if it is needed
- //if (dist < maxPen)
- //{
- // maxPen = dist;
- // m_touchingNormal = pt.m_normalWorldOnB * directionSign;//??
-
- //}
- m_currentPosition += pt.m_normalWorldOnB * directionSign * dist * btScalar(0.2);
- penetration = true;
- }
- else
- {
- //printf("touching %f\n", dist);
- }
- }
-
- //manifold->clearManifold();
- }
- }
- btTransform newTrans = m_ghostObject->getWorldTransform();
- newTrans.setOrigin(m_currentPosition);
- m_ghostObject->setWorldTransform(newTrans);
- // printf("m_touchingNormal = %f,%f,%f\n",m_touchingNormal[0],m_touchingNormal[1],m_touchingNormal[2]);
- return penetration;
-}
-
-void btKinematicCharacterController::stepUp(btCollisionWorld* world)
-{
- btScalar stepHeight = 0.0f;
- if (m_verticalVelocity < 0.0)
- stepHeight = m_stepHeight;
-
- // phase 1: up
- btTransform start, end;
-
- start.setIdentity();
- end.setIdentity();
-
- /* FIXME: Handle penetration properly */
- start.setOrigin(m_currentPosition);
-
- m_targetPosition = m_currentPosition + m_up * (stepHeight) + m_jumpAxis * ((m_verticalOffset > 0.f ? m_verticalOffset : 0.f));
- m_currentPosition = m_targetPosition;
-
- end.setOrigin(m_targetPosition);
-
- start.setRotation(m_currentOrientation);
- end.setRotation(m_targetOrientation);
-
- btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, -m_up, m_maxSlopeCosine);
- callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
- if (m_useGhostObjectSweepTest)
- {
- m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
- }
- else
- {
- world->convexSweepTest(m_convexShape, start, end, callback, world->getDispatchInfo().m_allowedCcdPenetration);
- }
-
- if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
- {
- // Only modify the position if the hit was a slope and not a wall or ceiling.
- if (callback.m_hitNormalWorld.dot(m_up) > 0.0)
- {
- // we moved up only a fraction of the step height
- m_currentStepOffset = stepHeight * callback.m_closestHitFraction;
- if (m_interpolateUp == true)
- m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
- else
- m_currentPosition = m_targetPosition;
- }
-
- btTransform& xform = m_ghostObject->getWorldTransform();
- xform.setOrigin(m_currentPosition);
- m_ghostObject->setWorldTransform(xform);
-
- // fix penetration if we hit a ceiling for example
- int numPenetrationLoops = 0;
- m_touchingContact = false;
- while (recoverFromPenetration(world))
- {
- numPenetrationLoops++;
- m_touchingContact = true;
- if (numPenetrationLoops > 4)
- {
- //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
- break;
- }
- }
- m_targetPosition = m_ghostObject->getWorldTransform().getOrigin();
- m_currentPosition = m_targetPosition;
-
- if (m_verticalOffset > 0)
- {
- m_verticalOffset = 0.0;
- m_verticalVelocity = 0.0;
- m_currentStepOffset = m_stepHeight;
- }
- }
- else
- {
- m_currentStepOffset = stepHeight;
- m_currentPosition = m_targetPosition;
- }
-}
-
-bool btKinematicCharacterController::needsCollision(const btCollisionObject* body0, const btCollisionObject* body1)
-{
- bool collides = (body0->getBroadphaseHandle()->m_collisionFilterGroup & body1->getBroadphaseHandle()->m_collisionFilterMask) != 0;
- collides = collides && (body1->getBroadphaseHandle()->m_collisionFilterGroup & body0->getBroadphaseHandle()->m_collisionFilterMask);
- return collides;
-}
-
-void btKinematicCharacterController::updateTargetPositionBasedOnCollision(const btVector3& hitNormal, btScalar tangentMag, btScalar normalMag)
-{
- btVector3 movementDirection = m_targetPosition - m_currentPosition;
- btScalar movementLength = movementDirection.length();
- if (movementLength > SIMD_EPSILON)
- {
- movementDirection.normalize();
-
- btVector3 reflectDir = computeReflectionDirection(movementDirection, hitNormal);
- reflectDir.normalize();
-
- btVector3 parallelDir, perpindicularDir;
-
- parallelDir = parallelComponent(reflectDir, hitNormal);
- perpindicularDir = perpindicularComponent(reflectDir, hitNormal);
-
- m_targetPosition = m_currentPosition;
- if (0) //tangentMag != 0.0)
- {
- btVector3 parComponent = parallelDir * btScalar(tangentMag * movementLength);
- // printf("parComponent=%f,%f,%f\n",parComponent[0],parComponent[1],parComponent[2]);
- m_targetPosition += parComponent;
- }
-
- if (normalMag != 0.0)
- {
- btVector3 perpComponent = perpindicularDir * btScalar(normalMag * movementLength);
- // printf("perpComponent=%f,%f,%f\n",perpComponent[0],perpComponent[1],perpComponent[2]);
- m_targetPosition += perpComponent;
- }
- }
- else
- {
- // printf("movementLength don't normalize a zero vector\n");
- }
-}
-
-void btKinematicCharacterController::stepForwardAndStrafe(btCollisionWorld* collisionWorld, const btVector3& walkMove)
-{
- // printf("m_normalizedDirection=%f,%f,%f\n",
- // m_normalizedDirection[0],m_normalizedDirection[1],m_normalizedDirection[2]);
- // phase 2: forward and strafe
- btTransform start, end;
-
- m_targetPosition = m_currentPosition + walkMove;
-
- start.setIdentity();
- end.setIdentity();
-
- btScalar fraction = 1.0;
- btScalar distance2 = (m_currentPosition - m_targetPosition).length2();
- // printf("distance2=%f\n",distance2);
-
- int maxIter = 10;
-
- while (fraction > btScalar(0.01) && maxIter-- > 0)
- {
- start.setOrigin(m_currentPosition);
- end.setOrigin(m_targetPosition);
- btVector3 sweepDirNegative(m_currentPosition - m_targetPosition);
-
- start.setRotation(m_currentOrientation);
- end.setRotation(m_targetOrientation);
-
- btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, sweepDirNegative, btScalar(0.0));
- callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
- btScalar margin = m_convexShape->getMargin();
- m_convexShape->setMargin(margin + m_addedMargin);
-
- if (!(start == end))
- {
- if (m_useGhostObjectSweepTest)
- {
- m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
- }
- else
- {
- collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
- }
- }
- m_convexShape->setMargin(margin);
-
- fraction -= callback.m_closestHitFraction;
-
- if (callback.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))
- {
- // we moved only a fraction
- //btScalar hitDistance;
- //hitDistance = (callback.m_hitPointWorld - m_currentPosition).length();
-
- // m_currentPosition.setInterpolate3 (m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
-
- updateTargetPositionBasedOnCollision(callback.m_hitNormalWorld);
- btVector3 currentDir = m_targetPosition - m_currentPosition;
- distance2 = currentDir.length2();
- if (distance2 > SIMD_EPSILON)
- {
- currentDir.normalize();
- /* See Quake2: "If velocity is against original velocity, stop ead to avoid tiny oscilations in sloping corners." */
- if (currentDir.dot(m_normalizedDirection) <= btScalar(0.0))
- {
- break;
- }
- }
- else
- {
- // printf("currentDir: don't normalize a zero vector\n");
- break;
- }
- }
- else
- {
- m_currentPosition = m_targetPosition;
- }
- }
-}
-
-void btKinematicCharacterController::stepDown(btCollisionWorld* collisionWorld, btScalar dt)
-{
- btTransform start, end, end_double;
- bool runonce = false;
-
- // phase 3: down
- /*btScalar additionalDownStep = (m_wasOnGround && !onGround()) ? m_stepHeight : 0.0;
- btVector3 step_drop = m_up * (m_currentStepOffset + additionalDownStep);
- btScalar downVelocity = (additionalDownStep == 0.0 && m_verticalVelocity<0.0?-m_verticalVelocity:0.0) * dt;
- btVector3 gravity_drop = m_up * downVelocity;
- m_targetPosition -= (step_drop + gravity_drop);*/
-
- btVector3 orig_position = m_targetPosition;
-
- btScalar downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
-
- if (m_verticalVelocity > 0.0)
- return;
-
- if (downVelocity > 0.0 && downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
- downVelocity = m_fallSpeed;
-
- btVector3 step_drop = m_up * (m_currentStepOffset + downVelocity);
- m_targetPosition -= step_drop;
-
- btKinematicClosestNotMeConvexResultCallback callback(m_ghostObject, m_up, m_maxSlopeCosine);
- callback.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
- btKinematicClosestNotMeConvexResultCallback callback2(m_ghostObject, m_up, m_maxSlopeCosine);
- callback2.m_collisionFilterGroup = getGhostObject()->getBroadphaseHandle()->m_collisionFilterGroup;
- callback2.m_collisionFilterMask = getGhostObject()->getBroadphaseHandle()->m_collisionFilterMask;
-
- while (1)
- {
- start.setIdentity();
- end.setIdentity();
-
- end_double.setIdentity();
-
- start.setOrigin(m_currentPosition);
- end.setOrigin(m_targetPosition);
-
- start.setRotation(m_currentOrientation);
- end.setRotation(m_targetOrientation);
-
- //set double test for 2x the step drop, to check for a large drop vs small drop
- end_double.setOrigin(m_targetPosition - step_drop);
-
- if (m_useGhostObjectSweepTest)
- {
- m_ghostObject->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
-
- if (!callback.hasHit() && m_ghostObject->hasContactResponse())
- {
- //test a double fall height, to see if the character should interpolate it's fall (full) or not (partial)
- m_ghostObject->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
- }
- }
- else
- {
- collisionWorld->convexSweepTest(m_convexShape, start, end, callback, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
-
- if (!callback.hasHit() && m_ghostObject->hasContactResponse())
- {
- //test a double fall height, to see if the character should interpolate it's fall (large) or not (small)
- collisionWorld->convexSweepTest(m_convexShape, start, end_double, callback2, collisionWorld->getDispatchInfo().m_allowedCcdPenetration);
- }
- }
-
- btScalar downVelocity2 = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
- bool has_hit;
- if (bounce_fix == true)
- has_hit = (callback.hasHit() || callback2.hasHit()) && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback.m_hitCollisionObject);
- else
- has_hit = callback2.hasHit() && m_ghostObject->hasContactResponse() && needsCollision(m_ghostObject, callback2.m_hitCollisionObject);
-
- btScalar stepHeight = 0.0f;
- if (m_verticalVelocity < 0.0)
- stepHeight = m_stepHeight;
-
- if (downVelocity2 > 0.0 && downVelocity2 < stepHeight && has_hit == true && runonce == false && (m_wasOnGround || !m_wasJumping))
- {
- //redo the velocity calculation when falling a small amount, for fast stairs motion
- //for larger falls, use the smoother/slower interpolated movement by not touching the target position
-
- m_targetPosition = orig_position;
- downVelocity = stepHeight;
-
- step_drop = m_up * (m_currentStepOffset + downVelocity);
- m_targetPosition -= step_drop;
- runonce = true;
- continue; //re-run previous tests
- }
- break;
- }
-
- if ((m_ghostObject->hasContactResponse() && (callback.hasHit() && needsCollision(m_ghostObject, callback.m_hitCollisionObject))) || runonce == true)
- {
- // we dropped a fraction of the height -> hit floor
- btScalar fraction = (m_currentPosition.getY() - callback.m_hitPointWorld.getY()) / 2;
-
- //printf("hitpoint: %g - pos %g\n", callback.m_hitPointWorld.getY(), m_currentPosition.getY());
-
- if (bounce_fix == true)
- {
- if (full_drop == true)
- m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
- else
- //due to errors in the closestHitFraction variable when used with large polygons, calculate the hit fraction manually
- m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, fraction);
- }
- else
- m_currentPosition.setInterpolate3(m_currentPosition, m_targetPosition, callback.m_closestHitFraction);
-
- full_drop = false;
-
- m_verticalVelocity = 0.0;
- m_verticalOffset = 0.0;
- m_wasJumping = false;
- }
- else
- {
- // we dropped the full height
-
- full_drop = true;
-
- if (bounce_fix == true)
- {
- downVelocity = (m_verticalVelocity < 0.f ? -m_verticalVelocity : 0.f) * dt;
- if (downVelocity > m_fallSpeed && (m_wasOnGround || !m_wasJumping))
- {
- m_targetPosition += step_drop; //undo previous target change
- downVelocity = m_fallSpeed;
- step_drop = m_up * (m_currentStepOffset + downVelocity);
- m_targetPosition -= step_drop;
- }
- }
- //printf("full drop - %g, %g\n", m_currentPosition.getY(), m_targetPosition.getY());
-
- m_currentPosition = m_targetPosition;
- }
-}
-
-void btKinematicCharacterController::setWalkDirection(
- const btVector3& walkDirection)
-{
- m_useWalkDirection = true;
- m_walkDirection = walkDirection;
- m_normalizedDirection = getNormalizedVector(m_walkDirection);
-}
-
-void btKinematicCharacterController::setVelocityForTimeInterval(
- const btVector3& velocity,
- btScalar timeInterval)
-{
- // printf("setVelocity!\n");
- // printf(" interval: %f\n", timeInterval);
- // printf(" velocity: (%f, %f, %f)\n",
- // velocity.x(), velocity.y(), velocity.z());
-
- m_useWalkDirection = false;
- m_walkDirection = velocity;
- m_normalizedDirection = getNormalizedVector(m_walkDirection);
- m_velocityTimeInterval += timeInterval;
-}
-
-void btKinematicCharacterController::setAngularVelocity(const btVector3& velocity)
-{
- m_AngVel = velocity;
-}
-
-const btVector3& btKinematicCharacterController::getAngularVelocity() const
-{
- return m_AngVel;
-}
-
-void btKinematicCharacterController::setLinearVelocity(const btVector3& velocity)
-{
- m_walkDirection = velocity;
-
- // HACK: if we are moving in the direction of the up, treat it as a jump :(
- if (m_walkDirection.length2() > 0)
- {
- btVector3 w = velocity.normalized();
- btScalar c = w.dot(m_up);
- if (c != 0)
- {
- //there is a component in walkdirection for vertical velocity
- btVector3 upComponent = m_up * (btSin(SIMD_HALF_PI - btAcos(c)) * m_walkDirection.length());
- m_walkDirection -= upComponent;
- m_verticalVelocity = (c < 0.0f ? -1 : 1) * upComponent.length();
-
- if (c > 0.0f)
- {
- m_wasJumping = true;
- m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
- }
- }
- }
- else
- m_verticalVelocity = 0.0f;
-}
-
-btVector3 btKinematicCharacterController::getLinearVelocity() const
-{
- return m_walkDirection + (m_verticalVelocity * m_up);
-}
-
-void btKinematicCharacterController::reset(btCollisionWorld* collisionWorld)
-{
- m_verticalVelocity = 0.0;
- m_verticalOffset = 0.0;
- m_wasOnGround = false;
- m_wasJumping = false;
- m_walkDirection.setValue(0, 0, 0);
- m_velocityTimeInterval = 0.0;
-
- //clear pair cache
- btHashedOverlappingPairCache* cache = m_ghostObject->getOverlappingPairCache();
- while (cache->getOverlappingPairArray().size() > 0)
- {
- cache->removeOverlappingPair(cache->getOverlappingPairArray()[0].m_pProxy0, cache->getOverlappingPairArray()[0].m_pProxy1, collisionWorld->getDispatcher());
- }
-}
-
-void btKinematicCharacterController::warp(const btVector3& origin)
-{
- btTransform xform;
- xform.setIdentity();
- xform.setOrigin(origin);
- m_ghostObject->setWorldTransform(xform);
-}
-
-void btKinematicCharacterController::preStep(btCollisionWorld* collisionWorld)
-{
- m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
- m_targetPosition = m_currentPosition;
-
- m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
- m_targetOrientation = m_currentOrientation;
- // printf("m_targetPosition=%f,%f,%f\n",m_targetPosition[0],m_targetPosition[1],m_targetPosition[2]);
-}
-
-void btKinematicCharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar dt)
-{
- // printf("playerStep(): ");
- // printf(" dt = %f", dt);
-
- if (m_AngVel.length2() > 0.0f)
- {
- m_AngVel *= btPow(btScalar(1) - m_angularDamping, dt);
- }
-
- // integrate for angular velocity
- if (m_AngVel.length2() > 0.0f)
- {
- btTransform xform;
- xform = m_ghostObject->getWorldTransform();
-
- btQuaternion rot(m_AngVel.normalized(), m_AngVel.length() * dt);
-
- btQuaternion orn = rot * xform.getRotation();
-
- xform.setRotation(orn);
- m_ghostObject->setWorldTransform(xform);
-
- m_currentPosition = m_ghostObject->getWorldTransform().getOrigin();
- m_targetPosition = m_currentPosition;
- m_currentOrientation = m_ghostObject->getWorldTransform().getRotation();
- m_targetOrientation = m_currentOrientation;
- }
-
- // quick check...
- if (!m_useWalkDirection && (m_velocityTimeInterval <= 0.0 || m_walkDirection.fuzzyZero()))
- {
- // printf("\n");
- return; // no motion
- }
-
- m_wasOnGround = onGround();
-
- //btVector3 lvel = m_walkDirection;
- //btScalar c = 0.0f;
-
- if (m_walkDirection.length2() > 0)
- {
- // apply damping
- m_walkDirection *= btPow(btScalar(1) - m_linearDamping, dt);
- }
-
- m_verticalVelocity *= btPow(btScalar(1) - m_linearDamping, dt);
-
- // Update fall velocity.
- m_verticalVelocity -= m_gravity * dt;
- if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
- {
- m_verticalVelocity = m_jumpSpeed;
- }
- if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
- {
- m_verticalVelocity = -btFabs(m_fallSpeed);
- }
- m_verticalOffset = m_verticalVelocity * dt;
-
- btTransform xform;
- xform = m_ghostObject->getWorldTransform();
-
- // printf("walkDirection(%f,%f,%f)\n",walkDirection[0],walkDirection[1],walkDirection[2]);
- // printf("walkSpeed=%f\n",walkSpeed);
-
- stepUp(collisionWorld);
- //todo: Experimenting with behavior of controller when it hits a ceiling..
- //bool hitUp = stepUp (collisionWorld);
- //if (hitUp)
- //{
- // m_verticalVelocity -= m_gravity * dt;
- // if (m_verticalVelocity > 0.0 && m_verticalVelocity > m_jumpSpeed)
- // {
- // m_verticalVelocity = m_jumpSpeed;
- // }
- // if (m_verticalVelocity < 0.0 && btFabs(m_verticalVelocity) > btFabs(m_fallSpeed))
- // {
- // m_verticalVelocity = -btFabs(m_fallSpeed);
- // }
- // m_verticalOffset = m_verticalVelocity * dt;
-
- // xform = m_ghostObject->getWorldTransform();
- //}
-
- if (m_useWalkDirection)
- {
- stepForwardAndStrafe(collisionWorld, m_walkDirection);
- }
- else
- {
- //printf(" time: %f", m_velocityTimeInterval);
- // still have some time left for moving!
- btScalar dtMoving =
- (dt < m_velocityTimeInterval) ? dt : m_velocityTimeInterval;
- m_velocityTimeInterval -= dt;
-
- // how far will we move while we are moving?
- btVector3 move = m_walkDirection * dtMoving;
-
- //printf(" dtMoving: %f", dtMoving);
-
- // okay, step
- stepForwardAndStrafe(collisionWorld, move);
- }
- stepDown(collisionWorld, dt);
-
- //todo: Experimenting with max jump height
- //if (m_wasJumping)
- //{
- // btScalar ds = m_currentPosition[m_upAxis] - m_jumpPosition[m_upAxis];
- // if (ds > m_maxJumpHeight)
- // {
- // // substract the overshoot
- // m_currentPosition[m_upAxis] -= ds - m_maxJumpHeight;
-
- // // max height was reached, so potential energy is at max
- // // and kinematic energy is 0, thus velocity is 0.
- // if (m_verticalVelocity > 0.0)
- // m_verticalVelocity = 0.0;
- // }
- //}
- // printf("\n");
-
- xform.setOrigin(m_currentPosition);
- m_ghostObject->setWorldTransform(xform);
-
- int numPenetrationLoops = 0;
- m_touchingContact = false;
- while (recoverFromPenetration(collisionWorld))
- {
- numPenetrationLoops++;
- m_touchingContact = true;
- if (numPenetrationLoops > 4)
- {
- //printf("character could not recover from penetration = %d\n", numPenetrationLoops);
- break;
- }
- }
-}
-
-void btKinematicCharacterController::setFallSpeed(btScalar fallSpeed)
-{
- m_fallSpeed = fallSpeed;
-}
-
-void btKinematicCharacterController::setJumpSpeed(btScalar jumpSpeed)
-{
- m_jumpSpeed = jumpSpeed;
- m_SetjumpSpeed = m_jumpSpeed;
-}
-
-void btKinematicCharacterController::setMaxJumpHeight(btScalar maxJumpHeight)
-{
- m_maxJumpHeight = maxJumpHeight;
-}
-
-bool btKinematicCharacterController::canJump() const
-{
- return onGround();
-}
-
-void btKinematicCharacterController::jump(const btVector3& v)
-{
- m_jumpSpeed = v.length2() == 0 ? m_SetjumpSpeed : v.length();
- m_verticalVelocity = m_jumpSpeed;
- m_wasJumping = true;
-
- m_jumpAxis = v.length2() == 0 ? m_up : v.normalized();
-
- m_jumpPosition = m_ghostObject->getWorldTransform().getOrigin();
-
-#if 0
- currently no jumping.
- btTransform xform;
- m_rigidBody->getMotionState()->getWorldTransform (xform);
- btVector3 up = xform.getBasis()[1];
- up.normalize ();
- btScalar magnitude = (btScalar(1.0)/m_rigidBody->getInvMass()) * btScalar(8.0);
- m_rigidBody->applyCentralImpulse (up * magnitude);
-#endif
-}
-
-void btKinematicCharacterController::setGravity(const btVector3& gravity)
-{
- if (gravity.length2() > 0) setUpVector(-gravity);
-
- m_gravity = gravity.length();
-}
-
-btVector3 btKinematicCharacterController::getGravity() const
-{
- return -m_gravity * m_up;
-}
-
-void btKinematicCharacterController::setMaxSlope(btScalar slopeRadians)
-{
- m_maxSlopeRadians = slopeRadians;
- m_maxSlopeCosine = btCos(slopeRadians);
-}
-
-btScalar btKinematicCharacterController::getMaxSlope() const
-{
- return m_maxSlopeRadians;
-}
-
-void btKinematicCharacterController::setMaxPenetrationDepth(btScalar d)
-{
- m_maxPenetrationDepth = d;
-}
-
-btScalar btKinematicCharacterController::getMaxPenetrationDepth() const
-{
- return m_maxPenetrationDepth;
-}
-
-bool btKinematicCharacterController::onGround() const
-{
- return (fabs(m_verticalVelocity) < SIMD_EPSILON) && (fabs(m_verticalOffset) < SIMD_EPSILON);
-}
-
-void btKinematicCharacterController::setStepHeight(btScalar h)
-{
- m_stepHeight = h;
-}
-
-btVector3* btKinematicCharacterController::getUpAxisDirections()
-{
- static btVector3 sUpAxisDirection[3] = {btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f)};
-
- return sUpAxisDirection;
-}
-
-void btKinematicCharacterController::debugDraw(btIDebugDraw* debugDrawer)
-{
-}
-
-void btKinematicCharacterController::setUpInterpolate(bool value)
-{
- m_interpolateUp = value;
-}
-
-void btKinematicCharacterController::setUp(const btVector3& up)
-{
- if (up.length2() > 0 && m_gravity > 0.0f)
- {
- setGravity(-m_gravity * up.normalized());
- return;
- }
-
- setUpVector(up);
-}
-
-void btKinematicCharacterController::setUpVector(const btVector3& up)
-{
- if (m_up == up)
- return;
-
- btVector3 u = m_up;
-
- if (up.length2() > 0)
- m_up = up.normalized();
- else
- m_up = btVector3(0.0, 0.0, 0.0);
-
- if (!m_ghostObject) return;
- btQuaternion rot = getRotation(m_up, u);
-
- //set orientation with new up
- btTransform xform;
- xform = m_ghostObject->getWorldTransform();
- btQuaternion orn = rot.inverse() * xform.getRotation();
- xform.setRotation(orn);
- m_ghostObject->setWorldTransform(xform);
-}
-
-btQuaternion btKinematicCharacterController::getRotation(btVector3& v0, btVector3& v1) const
-{
- if (v0.length2() == 0.0f || v1.length2() == 0.0f)
- {
- btQuaternion q;
- return q;
- }
-
- return shortestArcQuatNormalize2(v0, v1);
-}
diff --git a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h b/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h
deleted file mode 100644
index ff34fc871a..0000000000
--- a/thirdparty/bullet/BulletDynamics/Character/btKinematicCharacterController.h
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_KINEMATIC_CHARACTER_CONTROLLER_H
-#define BT_KINEMATIC_CHARACTER_CONTROLLER_H
-
-#include "LinearMath/btVector3.h"
-
-#include "btCharacterControllerInterface.h"
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-
-class btCollisionShape;
-class btConvexShape;
-class btRigidBody;
-class btCollisionWorld;
-class btCollisionDispatcher;
-class btPairCachingGhostObject;
-
-///btKinematicCharacterController is an object that supports a sliding motion in a world.
-///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations.
-///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user.
-ATTRIBUTE_ALIGNED16(class)
-btKinematicCharacterController : public btCharacterControllerInterface
-{
-protected:
- btScalar m_halfHeight;
-
- btPairCachingGhostObject* m_ghostObject;
- btConvexShape* m_convexShape; //is also in m_ghostObject, but it needs to be convex, so we store it here to avoid upcast
-
- btScalar m_maxPenetrationDepth;
- btScalar m_verticalVelocity;
- btScalar m_verticalOffset;
- btScalar m_fallSpeed;
- btScalar m_jumpSpeed;
- btScalar m_SetjumpSpeed;
- btScalar m_maxJumpHeight;
- btScalar m_maxSlopeRadians; // Slope angle that is set (used for returning the exact value)
- btScalar m_maxSlopeCosine; // Cosine equivalent of m_maxSlopeRadians (calculated once when set, for optimization)
- btScalar m_gravity;
-
- btScalar m_turnAngle;
-
- btScalar m_stepHeight;
-
- btScalar m_addedMargin; //@todo: remove this and fix the code
-
- ///this is the desired walk direction, set by the user
- btVector3 m_walkDirection;
- btVector3 m_normalizedDirection;
- btVector3 m_AngVel;
-
- btVector3 m_jumpPosition;
-
- //some internal variables
- btVector3 m_currentPosition;
- btScalar m_currentStepOffset;
- btVector3 m_targetPosition;
-
- btQuaternion m_currentOrientation;
- btQuaternion m_targetOrientation;
-
- ///keep track of the contact manifolds
- btManifoldArray m_manifoldArray;
-
- bool m_touchingContact;
- btVector3 m_touchingNormal;
-
- btScalar m_linearDamping;
- btScalar m_angularDamping;
-
- bool m_wasOnGround;
- bool m_wasJumping;
- bool m_useGhostObjectSweepTest;
- bool m_useWalkDirection;
- btScalar m_velocityTimeInterval;
- btVector3 m_up;
- btVector3 m_jumpAxis;
-
- static btVector3* getUpAxisDirections();
- bool m_interpolateUp;
- bool full_drop;
- bool bounce_fix;
-
- btVector3 computeReflectionDirection(const btVector3& direction, const btVector3& normal);
- btVector3 parallelComponent(const btVector3& direction, const btVector3& normal);
- btVector3 perpindicularComponent(const btVector3& direction, const btVector3& normal);
-
- bool recoverFromPenetration(btCollisionWorld * collisionWorld);
- void stepUp(btCollisionWorld * collisionWorld);
- void updateTargetPositionBasedOnCollision(const btVector3& hit_normal, btScalar tangentMag = btScalar(0.0), btScalar normalMag = btScalar(1.0));
- void stepForwardAndStrafe(btCollisionWorld * collisionWorld, const btVector3& walkMove);
- void stepDown(btCollisionWorld * collisionWorld, btScalar dt);
-
- virtual bool needsCollision(const btCollisionObject* body0, const btCollisionObject* body1);
-
- void setUpVector(const btVector3& up);
-
- btQuaternion getRotation(btVector3 & v0, btVector3 & v1) const;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btKinematicCharacterController(btPairCachingGhostObject * ghostObject, btConvexShape * convexShape, btScalar stepHeight, const btVector3& up = btVector3(1.0, 0.0, 0.0));
- ~btKinematicCharacterController();
-
- ///btActionInterface interface
- virtual void updateAction(btCollisionWorld * collisionWorld, btScalar deltaTime)
- {
- preStep(collisionWorld);
- playerStep(collisionWorld, deltaTime);
- }
-
- ///btActionInterface interface
- void debugDraw(btIDebugDraw * debugDrawer);
-
- void setUp(const btVector3& up);
-
- const btVector3& getUp() { return m_up; }
-
- /// This should probably be called setPositionIncrementPerSimulatorStep.
- /// This is neither a direction nor a velocity, but the amount to
- /// increment the position each simulation iteration, regardless
- /// of dt.
- /// This call will reset any velocity set by setVelocityForTimeInterval().
- virtual void setWalkDirection(const btVector3& walkDirection);
-
- /// Caller provides a velocity with which the character should move for
- /// the given time period. After the time period, velocity is reset
- /// to zero.
- /// This call will reset any walk direction set by setWalkDirection().
- /// Negative time intervals will result in no motion.
- virtual void setVelocityForTimeInterval(const btVector3& velocity,
- btScalar timeInterval);
-
- virtual void setAngularVelocity(const btVector3& velocity);
- virtual const btVector3& getAngularVelocity() const;
-
- virtual void setLinearVelocity(const btVector3& velocity);
- virtual btVector3 getLinearVelocity() const;
-
- void setLinearDamping(btScalar d) { m_linearDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
- btScalar getLinearDamping() const { return m_linearDamping; }
- void setAngularDamping(btScalar d) { m_angularDamping = btClamped(d, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0)); }
- btScalar getAngularDamping() const { return m_angularDamping; }
-
- void reset(btCollisionWorld * collisionWorld);
- void warp(const btVector3& origin);
-
- void preStep(btCollisionWorld * collisionWorld);
- void playerStep(btCollisionWorld * collisionWorld, btScalar dt);
-
- void setStepHeight(btScalar h);
- btScalar getStepHeight() const { return m_stepHeight; }
- void setFallSpeed(btScalar fallSpeed);
- btScalar getFallSpeed() const { return m_fallSpeed; }
- void setJumpSpeed(btScalar jumpSpeed);
- btScalar getJumpSpeed() const { return m_jumpSpeed; }
- void setMaxJumpHeight(btScalar maxJumpHeight);
- bool canJump() const;
-
- void jump(const btVector3& v = btVector3(0, 0, 0));
-
- void applyImpulse(const btVector3& v) { jump(v); }
-
- void setGravity(const btVector3& gravity);
- btVector3 getGravity() const;
-
- /// The max slope determines the maximum angle that the controller can walk up.
- /// The slope angle is measured in radians.
- void setMaxSlope(btScalar slopeRadians);
- btScalar getMaxSlope() const;
-
- void setMaxPenetrationDepth(btScalar d);
- btScalar getMaxPenetrationDepth() const;
-
- btPairCachingGhostObject* getGhostObject();
- void setUseGhostSweepTest(bool useGhostObjectSweepTest)
- {
- m_useGhostObjectSweepTest = useGhostObjectSweepTest;
- }
-
- bool onGround() const;
- void setUpInterpolate(bool value);
-};
-
-#endif // BT_KINEMATIC_CHARACTER_CONTROLLER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
deleted file mode 100644
index 0f5ed1c2ce..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btBatchedConstraints.h"
-
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btMinMax.h"
-#include "LinearMath/btStackAlloc.h"
-#include "LinearMath/btQuickprof.h"
-
-#include <string.h> //for memset
-
-#include <cmath>
-
-const int kNoMerge = -1;
-
-bool btBatchedConstraints::s_debugDrawBatches = false;
-
-struct btBatchedConstraintInfo
-{
- int constraintIndex;
- int numConstraintRows;
- int bodyIds[2];
-};
-
-struct btBatchInfo
-{
- int numConstraints;
- int mergeIndex;
-
- btBatchInfo() : numConstraints(0), mergeIndex(kNoMerge) {}
-};
-
-bool btBatchedConstraints::validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const
-{
- //
- // validate: for debugging only. Verify coloring of bodies, that no body is touched by more than one batch in any given phase
- //
- int errors = 0;
- const int kUnassignedBatch = -1;
-
- btAlignedObjectArray<int> bodyBatchId;
- for (int iPhase = 0; iPhase < m_phases.size(); ++iPhase)
- {
- bodyBatchId.resizeNoInitialize(0);
- bodyBatchId.resize(bodies.size(), kUnassignedBatch);
- const Range& phase = m_phases[iPhase];
- for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
- {
- const Range& batch = m_batches[iBatch];
- for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
- {
- int iCons = m_constraintIndices[iiCons];
- const btSolverConstraint& cons = constraints->at(iCons);
- const btSolverBody& bodyA = bodies[cons.m_solverBodyIdA];
- const btSolverBody& bodyB = bodies[cons.m_solverBodyIdB];
- if (!bodyA.internalGetInvMass().isZero())
- {
- int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdA];
- if (thisBodyBatchId == kUnassignedBatch)
- {
- bodyBatchId[cons.m_solverBodyIdA] = iBatch;
- }
- else if (thisBodyBatchId != iBatch)
- {
- btAssert(!"dynamic body is used in 2 different batches in the same phase");
- errors++;
- }
- }
- if (!bodyB.internalGetInvMass().isZero())
- {
- int thisBodyBatchId = bodyBatchId[cons.m_solverBodyIdB];
- if (thisBodyBatchId == kUnassignedBatch)
- {
- bodyBatchId[cons.m_solverBodyIdB] = iBatch;
- }
- else if (thisBodyBatchId != iBatch)
- {
- btAssert(!"dynamic body is used in 2 different batches in the same phase");
- errors++;
- }
- }
- }
- }
- }
- return errors == 0;
-}
-
-static void debugDrawSingleBatch(const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int iBatch,
- const btVector3& color,
- const btVector3& offset)
-{
- if (bc && bc->m_debugDrawer && iBatch < bc->m_batches.size())
- {
- const btBatchedConstraints::Range& b = bc->m_batches[iBatch];
- for (int iiCon = b.begin; iiCon < b.end; ++iiCon)
- {
- int iCon = bc->m_constraintIndices[iiCon];
- const btSolverConstraint& con = constraints->at(iCon);
- int iBody0 = con.m_solverBodyIdA;
- int iBody1 = con.m_solverBodyIdB;
- btVector3 pos0 = bodies[iBody0].getWorldTransform().getOrigin() + offset;
- btVector3 pos1 = bodies[iBody1].getWorldTransform().getOrigin() + offset;
- bc->m_debugDrawer->drawLine(pos0, pos1, color);
- }
- }
-}
-
-static void debugDrawPhase(const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int iPhase,
- const btVector3& color0,
- const btVector3& color1,
- const btVector3& offset)
-{
- BT_PROFILE("debugDrawPhase");
- if (bc && bc->m_debugDrawer && iPhase < bc->m_phases.size())
- {
- const btBatchedConstraints::Range& phase = bc->m_phases[iPhase];
- for (int iBatch = phase.begin; iBatch < phase.end; ++iBatch)
- {
- float tt = float(iBatch - phase.begin) / float(btMax(1, phase.end - phase.begin - 1));
- btVector3 col = lerp(color0, color1, tt);
- debugDrawSingleBatch(bc, constraints, bodies, iBatch, col, offset);
- }
- }
-}
-
-static void debugDrawAllBatches(const btBatchedConstraints* bc,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies)
-{
- BT_PROFILE("debugDrawAllBatches");
- if (bc && bc->m_debugDrawer && bc->m_phases.size() > 0)
- {
- btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- btVector3 bboxMax = -bboxMin;
- for (int iBody = 0; iBody < bodies.size(); ++iBody)
- {
- const btVector3& pos = bodies[iBody].getWorldTransform().getOrigin();
- bboxMin.setMin(pos);
- bboxMax.setMax(pos);
- }
- btVector3 bboxExtent = bboxMax - bboxMin;
- btVector3 offsetBase = btVector3(0, bboxExtent.y() * 1.1f, 0);
- btVector3 offsetStep = btVector3(0, 0, bboxExtent.z() * 1.1f);
- int numPhases = bc->m_phases.size();
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- float b = float(iPhase) / float(numPhases - 1);
- btVector3 color0 = btVector3(1, 0, b);
- btVector3 color1 = btVector3(0, 1, b);
- btVector3 offset = offsetBase + offsetStep * (float(iPhase) - float(numPhases - 1) * 0.5);
- debugDrawPhase(bc, constraints, bodies, iPhase, color0, color1, offset);
- }
- }
-}
-
-static void initBatchedBodyDynamicFlags(btAlignedObjectArray<bool>* outBodyDynamicFlags, const btAlignedObjectArray<btSolverBody>& bodies)
-{
- BT_PROFILE("initBatchedBodyDynamicFlags");
- btAlignedObjectArray<bool>& bodyDynamicFlags = *outBodyDynamicFlags;
- bodyDynamicFlags.resizeNoInitialize(bodies.size());
- for (int i = 0; i < bodies.size(); ++i)
- {
- const btSolverBody& body = bodies[i];
- bodyDynamicFlags[i] = (body.internalGetInvMass().x() > btScalar(0));
- }
-}
-
-static int runLengthEncodeConstraintInfo(btBatchedConstraintInfo* outConInfos, int numConstraints)
-{
- BT_PROFILE("runLengthEncodeConstraintInfo");
- // detect and run-length encode constraint rows that repeat the same bodies
- int iDest = 0;
- int iSrc = 0;
- while (iSrc < numConstraints)
- {
- const btBatchedConstraintInfo& srcConInfo = outConInfos[iSrc];
- btBatchedConstraintInfo& conInfo = outConInfos[iDest];
- conInfo.constraintIndex = iSrc;
- conInfo.bodyIds[0] = srcConInfo.bodyIds[0];
- conInfo.bodyIds[1] = srcConInfo.bodyIds[1];
- while (iSrc < numConstraints && outConInfos[iSrc].bodyIds[0] == srcConInfo.bodyIds[0] && outConInfos[iSrc].bodyIds[1] == srcConInfo.bodyIds[1])
- {
- ++iSrc;
- }
- conInfo.numConstraintRows = iSrc - conInfo.constraintIndex;
- ++iDest;
- }
- return iDest;
-}
-
-struct ReadSolverConstraintsLoop : public btIParallelForBody
-{
- btBatchedConstraintInfo* m_outConInfos;
- btConstraintArray* m_constraints;
-
- ReadSolverConstraintsLoop(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
- {
- m_outConInfos = outConInfos;
- m_constraints = constraints;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- for (int i = iBegin; i < iEnd; ++i)
- {
- btBatchedConstraintInfo& conInfo = m_outConInfos[i];
- const btSolverConstraint& con = m_constraints->at(i);
- conInfo.bodyIds[0] = con.m_solverBodyIdA;
- conInfo.bodyIds[1] = con.m_solverBodyIdB;
- conInfo.constraintIndex = i;
- conInfo.numConstraintRows = 1;
- }
- }
-};
-
-static int initBatchedConstraintInfo(btBatchedConstraintInfo* outConInfos, btConstraintArray* constraints)
-{
- BT_PROFILE("initBatchedConstraintInfo");
- int numConstraints = constraints->size();
- bool inParallel = true;
- if (inParallel)
- {
- ReadSolverConstraintsLoop loop(outConInfos, constraints);
- int grainSize = 1200;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- for (int i = 0; i < numConstraints; ++i)
- {
- btBatchedConstraintInfo& conInfo = outConInfos[i];
- const btSolverConstraint& con = constraints->at(i);
- conInfo.bodyIds[0] = con.m_solverBodyIdA;
- conInfo.bodyIds[1] = con.m_solverBodyIdB;
- conInfo.constraintIndex = i;
- conInfo.numConstraintRows = 1;
- }
- }
- bool useRunLengthEncoding = true;
- if (useRunLengthEncoding)
- {
- numConstraints = runLengthEncodeConstraintInfo(outConInfos, numConstraints);
- }
- return numConstraints;
-}
-
-static void expandConstraintRowsInPlace(int* constraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
-{
- BT_PROFILE("expandConstraintRowsInPlace");
- if (numConstraintRows > numConstraints)
- {
- // we walk the array in reverse to avoid overwriteing
- for (int iCon = numConstraints - 1; iCon >= 0; --iCon)
- {
- const btBatchedConstraintInfo& conInfo = conInfos[iCon];
- int iBatch = constraintBatchIds[iCon];
- for (int i = conInfo.numConstraintRows - 1; i >= 0; --i)
- {
- int iDest = conInfo.constraintIndex + i;
- btAssert(iDest >= iCon);
- btAssert(iDest >= 0 && iDest < numConstraintRows);
- constraintBatchIds[iDest] = iBatch;
- }
- }
- }
-}
-
-static void expandConstraintRows(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
-{
- BT_PROFILE("expandConstraintRows");
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- const btBatchedConstraintInfo& conInfo = conInfos[iCon];
- int iBatch = srcConstraintBatchIds[iCon];
- for (int i = 0; i < conInfo.numConstraintRows; ++i)
- {
- int iDest = conInfo.constraintIndex + i;
- btAssert(iDest >= iCon);
- btAssert(iDest >= 0 && iDest < numConstraintRows);
- destConstraintBatchIds[iDest] = iBatch;
- }
- }
-}
-
-struct ExpandConstraintRowsLoop : public btIParallelForBody
-{
- int* m_destConstraintBatchIds;
- const int* m_srcConstraintBatchIds;
- const btBatchedConstraintInfo* m_conInfos;
- int m_numConstraintRows;
-
- ExpandConstraintRowsLoop(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraintRows)
- {
- m_destConstraintBatchIds = destConstraintBatchIds;
- m_srcConstraintBatchIds = srcConstraintBatchIds;
- m_conInfos = conInfos;
- m_numConstraintRows = numConstraintRows;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- expandConstraintRows(m_destConstraintBatchIds, m_srcConstraintBatchIds + iBegin, m_conInfos + iBegin, iEnd - iBegin, m_numConstraintRows);
- }
-};
-
-static void expandConstraintRowsMt(int* destConstraintBatchIds, const int* srcConstraintBatchIds, const btBatchedConstraintInfo* conInfos, int numConstraints, int numConstraintRows)
-{
- BT_PROFILE("expandConstraintRowsMt");
- ExpandConstraintRowsLoop loop(destConstraintBatchIds, srcConstraintBatchIds, conInfos, numConstraintRows);
- int grainSize = 600;
- btParallelFor(0, numConstraints, grainSize, loop);
-}
-
-static void initBatchedConstraintInfoArray(btAlignedObjectArray<btBatchedConstraintInfo>* outConInfos, btConstraintArray* constraints)
-{
- BT_PROFILE("initBatchedConstraintInfoArray");
- btAlignedObjectArray<btBatchedConstraintInfo>& conInfos = *outConInfos;
- int numConstraints = constraints->size();
- conInfos.resizeNoInitialize(numConstraints);
-
- int newSize = initBatchedConstraintInfo(&outConInfos->at(0), constraints);
- conInfos.resizeNoInitialize(newSize);
-}
-
-static void mergeSmallBatches(btBatchInfo* batches, int iBeginBatch, int iEndBatch, int minBatchSize, int maxBatchSize)
-{
- BT_PROFILE("mergeSmallBatches");
- for (int iBatch = iEndBatch - 1; iBatch >= iBeginBatch; --iBatch)
- {
- btBatchInfo& batch = batches[iBatch];
- if (batch.mergeIndex == kNoMerge && batch.numConstraints > 0 && batch.numConstraints < minBatchSize)
- {
- for (int iDestBatch = iBatch - 1; iDestBatch >= iBeginBatch; --iDestBatch)
- {
- btBatchInfo& destBatch = batches[iDestBatch];
- if (destBatch.mergeIndex == kNoMerge && (destBatch.numConstraints + batch.numConstraints) < maxBatchSize)
- {
- destBatch.numConstraints += batch.numConstraints;
- batch.numConstraints = 0;
- batch.mergeIndex = iDestBatch;
- break;
- }
- }
- }
- }
- // flatten mergeIndexes
- // e.g. in case where A was merged into B and then B was merged into C, we need A to point to C instead of B
- // Note: loop goes forward through batches because batches always merge from higher indexes to lower,
- // so by going from low to high it reduces the amount of trail-following
- for (int iBatch = iBeginBatch; iBatch < iEndBatch; ++iBatch)
- {
- btBatchInfo& batch = batches[iBatch];
- if (batch.mergeIndex != kNoMerge)
- {
- int iMergeDest = batches[batch.mergeIndex].mergeIndex;
- // follow trail of merges to the end
- while (iMergeDest != kNoMerge)
- {
- int iNext = batches[iMergeDest].mergeIndex;
- if (iNext == kNoMerge)
- {
- batch.mergeIndex = iMergeDest;
- break;
- }
- iMergeDest = iNext;
- }
- }
- }
-}
-
-static void updateConstraintBatchIdsForMerges(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
-{
- BT_PROFILE("updateConstraintBatchIdsForMerges");
- // update batchIds to account for merges
- for (int i = 0; i < numConstraints; ++i)
- {
- int iBatch = constraintBatchIds[i];
- btAssert(iBatch < numBatches);
- // if this constraint references a batch that was merged into another batch
- if (batches[iBatch].mergeIndex != kNoMerge)
- {
- // update batchId
- constraintBatchIds[i] = batches[iBatch].mergeIndex;
- }
- }
-}
-
-struct UpdateConstraintBatchIdsForMergesLoop : public btIParallelForBody
-{
- int* m_constraintBatchIds;
- const btBatchInfo* m_batches;
- int m_numBatches;
-
- UpdateConstraintBatchIdsForMergesLoop(int* constraintBatchIds, const btBatchInfo* batches, int numBatches)
- {
- m_constraintBatchIds = constraintBatchIds;
- m_batches = batches;
- m_numBatches = numBatches;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("UpdateConstraintBatchIdsForMergesLoop");
- updateConstraintBatchIdsForMerges(m_constraintBatchIds + iBegin, iEnd - iBegin, m_batches, m_numBatches);
- }
-};
-
-static void updateConstraintBatchIdsForMergesMt(int* constraintBatchIds, int numConstraints, const btBatchInfo* batches, int numBatches)
-{
- BT_PROFILE("updateConstraintBatchIdsForMergesMt");
- UpdateConstraintBatchIdsForMergesLoop loop(constraintBatchIds, batches, numBatches);
- int grainSize = 800;
- btParallelFor(0, numConstraints, grainSize, loop);
-}
-
-inline bool BatchCompare(const btBatchedConstraints::Range& a, const btBatchedConstraints::Range& b)
-{
- int lenA = a.end - a.begin;
- int lenB = b.end - b.begin;
- return lenA > lenB;
-}
-
-static void writeOutConstraintIndicesForRangeOfBatches(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- int* constraintIdPerBatch,
- int batchBegin,
- int batchEnd)
-{
- BT_PROFILE("writeOutConstraintIndicesForRangeOfBatches");
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- int iBatch = constraintBatchIds[iCon];
- if (iBatch >= batchBegin && iBatch < batchEnd)
- {
- int iDestCon = constraintIdPerBatch[iBatch];
- constraintIdPerBatch[iBatch] = iDestCon + 1;
- bc->m_constraintIndices[iDestCon] = iCon;
- }
- }
-}
-
-struct WriteOutConstraintIndicesLoop : public btIParallelForBody
-{
- btBatchedConstraints* m_batchedConstraints;
- const int* m_constraintBatchIds;
- int m_numConstraints;
- int* m_constraintIdPerBatch;
- int m_maxNumBatchesPerPhase;
-
- WriteOutConstraintIndicesLoop(btBatchedConstraints* bc, const int* constraintBatchIds, int numConstraints, int* constraintIdPerBatch, int maxNumBatchesPerPhase)
- {
- m_batchedConstraints = bc;
- m_constraintBatchIds = constraintBatchIds;
- m_numConstraints = numConstraints;
- m_constraintIdPerBatch = constraintIdPerBatch;
- m_maxNumBatchesPerPhase = maxNumBatchesPerPhase;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("WriteOutConstraintIndicesLoop");
- int batchBegin = iBegin * m_maxNumBatchesPerPhase;
- int batchEnd = iEnd * m_maxNumBatchesPerPhase;
- writeOutConstraintIndicesForRangeOfBatches(m_batchedConstraints,
- m_constraintBatchIds,
- m_numConstraints,
- m_constraintIdPerBatch,
- batchBegin,
- batchEnd);
- }
-};
-
-static void writeOutConstraintIndicesMt(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- int* constraintIdPerBatch,
- int maxNumBatchesPerPhase,
- int numPhases)
-{
- BT_PROFILE("writeOutConstraintIndicesMt");
- bool inParallel = true;
- if (inParallel)
- {
- WriteOutConstraintIndicesLoop loop(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase);
- btParallelFor(0, numPhases, 1, loop);
- }
- else
- {
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- int iBatch = constraintBatchIds[iCon];
- int iDestCon = constraintIdPerBatch[iBatch];
- constraintIdPerBatch[iBatch] = iDestCon + 1;
- bc->m_constraintIndices[iDestCon] = iCon;
- }
- }
-}
-
-static void writeGrainSizes(btBatchedConstraints* bc)
-{
- typedef btBatchedConstraints::Range Range;
- int numPhases = bc->m_phases.size();
- bc->m_phaseGrainSize.resizeNoInitialize(numPhases);
- int numThreads = btGetTaskScheduler()->getNumThreads();
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- const Range& phase = bc->m_phases[iPhase];
- int numBatches = phase.end - phase.begin;
- float grainSize = std::floor((0.25f * numBatches / float(numThreads)) + 0.0f);
- bc->m_phaseGrainSize[iPhase] = btMax(1, int(grainSize));
- }
-}
-
-static void writeOutBatches(btBatchedConstraints* bc,
- const int* constraintBatchIds,
- int numConstraints,
- const btBatchInfo* batches,
- int* batchWork,
- int maxNumBatchesPerPhase,
- int numPhases)
-{
- BT_PROFILE("writeOutBatches");
- typedef btBatchedConstraints::Range Range;
- bc->m_constraintIndices.reserve(numConstraints);
- bc->m_batches.resizeNoInitialize(0);
- bc->m_phases.resizeNoInitialize(0);
-
- //int maxNumBatches = numPhases * maxNumBatchesPerPhase;
- {
- int* constraintIdPerBatch = batchWork; // for each batch, keep an index into the next available slot in the m_constraintIndices array
- int iConstraint = 0;
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- int curPhaseBegin = bc->m_batches.size();
- int iBegin = iPhase * maxNumBatchesPerPhase;
- int iEnd = iBegin + maxNumBatchesPerPhase;
- for (int i = iBegin; i < iEnd; ++i)
- {
- const btBatchInfo& batch = batches[i];
- int curBatchBegin = iConstraint;
- constraintIdPerBatch[i] = curBatchBegin; // record the start of each batch in m_constraintIndices array
- int numConstraints = batch.numConstraints;
- iConstraint += numConstraints;
- if (numConstraints > 0)
- {
- bc->m_batches.push_back(Range(curBatchBegin, iConstraint));
- }
- }
- // if any batches were emitted this phase,
- if (bc->m_batches.size() > curPhaseBegin)
- {
- // output phase
- bc->m_phases.push_back(Range(curPhaseBegin, bc->m_batches.size()));
- }
- }
-
- btAssert(iConstraint == numConstraints);
- bc->m_constraintIndices.resizeNoInitialize(numConstraints);
- writeOutConstraintIndicesMt(bc, constraintBatchIds, numConstraints, constraintIdPerBatch, maxNumBatchesPerPhase, numPhases);
- }
- // for each phase
- for (int iPhase = 0; iPhase < bc->m_phases.size(); ++iPhase)
- {
- // sort the batches from largest to smallest (can be helpful to some task schedulers)
- const Range& curBatches = bc->m_phases[iPhase];
- bc->m_batches.quickSortInternal(BatchCompare, curBatches.begin, curBatches.end - 1);
- }
- bc->m_phaseOrder.resize(bc->m_phases.size());
- for (int i = 0; i < bc->m_phases.size(); ++i)
- {
- bc->m_phaseOrder[i] = i;
- }
- writeGrainSizes(bc);
-}
-
-//
-// PreallocatedMemoryHelper -- helper object for allocating a number of chunks of memory in a single contiguous block.
-// It is generally more efficient to do a single larger allocation than many smaller allocations.
-//
-// Example Usage:
-//
-// btVector3* bodyPositions = NULL;
-// btBatchedConstraintInfo* conInfos = NULL;
-// {
-// PreallocatedMemoryHelper<8> memHelper;
-// memHelper.addChunk( (void**) &bodyPositions, sizeof( btVector3 ) * bodies.size() );
-// memHelper.addChunk( (void**) &conInfos, sizeof( btBatchedConstraintInfo ) * numConstraints );
-// void* memPtr = malloc( memHelper.getSizeToAllocate() ); // allocate the memory
-// memHelper.setChunkPointers( memPtr ); // update pointers to chunks
-// }
-template <int N>
-class PreallocatedMemoryHelper
-{
- struct Chunk
- {
- void** ptr;
- size_t size;
- };
- Chunk m_chunks[N];
- int m_numChunks;
-
-public:
- PreallocatedMemoryHelper() { m_numChunks = 0; }
- void addChunk(void** ptr, size_t sz)
- {
- btAssert(m_numChunks < N);
- if (m_numChunks < N)
- {
- Chunk& chunk = m_chunks[m_numChunks];
- chunk.ptr = ptr;
- chunk.size = sz;
- m_numChunks++;
- }
- }
- size_t getSizeToAllocate() const
- {
- size_t totalSize = 0;
- for (int i = 0; i < m_numChunks; ++i)
- {
- totalSize += m_chunks[i].size;
- }
- return totalSize;
- }
- void setChunkPointers(void* mem) const
- {
- size_t totalSize = 0;
- for (int i = 0; i < m_numChunks; ++i)
- {
- const Chunk& chunk = m_chunks[i];
- char* chunkPtr = static_cast<char*>(mem) + totalSize;
- *chunk.ptr = chunkPtr;
- totalSize += chunk.size;
- }
- }
-};
-
-static btVector3 findMaxDynamicConstraintExtent(
- btVector3* bodyPositions,
- bool* bodyDynamicFlags,
- btBatchedConstraintInfo* conInfos,
- int numConstraints,
- int numBodies)
-{
- BT_PROFILE("findMaxDynamicConstraintExtent");
- btVector3 consExtent = btVector3(1, 1, 1) * 0.001;
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- const btBatchedConstraintInfo& con = conInfos[iCon];
- int iBody0 = con.bodyIds[0];
- int iBody1 = con.bodyIds[1];
- btAssert(iBody0 >= 0 && iBody0 < numBodies);
- btAssert(iBody1 >= 0 && iBody1 < numBodies);
- // is it a dynamic constraint?
- if (bodyDynamicFlags[iBody0] && bodyDynamicFlags[iBody1])
- {
- btVector3 delta = bodyPositions[iBody1] - bodyPositions[iBody0];
- consExtent.setMax(delta.absolute());
- }
- }
- return consExtent;
-}
-
-struct btIntVec3
-{
- int m_ints[3];
-
- SIMD_FORCE_INLINE const int& operator[](int i) const { return m_ints[i]; }
- SIMD_FORCE_INLINE int& operator[](int i) { return m_ints[i]; }
-};
-
-struct AssignConstraintsToGridBatchesParams
-{
- bool* bodyDynamicFlags;
- btIntVec3* bodyGridCoords;
- int numBodies;
- btBatchedConstraintInfo* conInfos;
- int* constraintBatchIds;
- btIntVec3 gridChunkDim;
- int maxNumBatchesPerPhase;
- int numPhases;
- int phaseMask;
-
- AssignConstraintsToGridBatchesParams()
- {
- memset(this, 0, sizeof(*this));
- }
-};
-
-static void assignConstraintsToGridBatches(const AssignConstraintsToGridBatchesParams& params, int iConBegin, int iConEnd)
-{
- BT_PROFILE("assignConstraintsToGridBatches");
- // (can be done in parallel)
- for (int iCon = iConBegin; iCon < iConEnd; ++iCon)
- {
- const btBatchedConstraintInfo& con = params.conInfos[iCon];
- int iBody0 = con.bodyIds[0];
- int iBody1 = con.bodyIds[1];
- int iPhase = iCon; //iBody0; // pseudorandom choice to distribute evenly amongst phases
- iPhase &= params.phaseMask;
- int gridCoord[3];
- // is it a dynamic constraint?
- if (params.bodyDynamicFlags[iBody0] && params.bodyDynamicFlags[iBody1])
- {
- const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
- const btIntVec3& body1Coords = params.bodyGridCoords[iBody1];
- // for each dimension x,y,z,
- for (int i = 0; i < 3; ++i)
- {
- int coordMin = btMin(body0Coords.m_ints[i], body1Coords.m_ints[i]);
- int coordMax = btMax(body0Coords.m_ints[i], body1Coords.m_ints[i]);
- if (coordMin != coordMax)
- {
- btAssert(coordMax == coordMin + 1);
- if ((coordMin & 1) == 0)
- {
- iPhase &= ~(1 << i); // force bit off
- }
- else
- {
- iPhase |= (1 << i); // force bit on
- iPhase &= params.phaseMask;
- }
- }
- gridCoord[i] = coordMin;
- }
- }
- else
- {
- if (!params.bodyDynamicFlags[iBody0])
- {
- iBody0 = con.bodyIds[1];
- }
- btAssert(params.bodyDynamicFlags[iBody0]);
- const btIntVec3& body0Coords = params.bodyGridCoords[iBody0];
- // for each dimension x,y,z,
- for (int i = 0; i < 3; ++i)
- {
- gridCoord[i] = body0Coords.m_ints[i];
- }
- }
- // calculate chunk coordinates
- int chunkCoord[3];
- btIntVec3 gridChunkDim = params.gridChunkDim;
- // for each dimension x,y,z,
- for (int i = 0; i < 3; ++i)
- {
- int coordOffset = (iPhase >> i) & 1;
- chunkCoord[i] = (gridCoord[i] - coordOffset) / 2;
- btClamp(chunkCoord[i], 0, gridChunkDim[i] - 1);
- btAssert(chunkCoord[i] < gridChunkDim[i]);
- }
- int iBatch = iPhase * params.maxNumBatchesPerPhase + chunkCoord[0] + chunkCoord[1] * gridChunkDim[0] + chunkCoord[2] * gridChunkDim[0] * gridChunkDim[1];
- btAssert(iBatch >= 0 && iBatch < params.maxNumBatchesPerPhase * params.numPhases);
- params.constraintBatchIds[iCon] = iBatch;
- }
-}
-
-struct AssignConstraintsToGridBatchesLoop : public btIParallelForBody
-{
- const AssignConstraintsToGridBatchesParams* m_params;
-
- AssignConstraintsToGridBatchesLoop(const AssignConstraintsToGridBatchesParams& params)
- {
- m_params = &params;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- assignConstraintsToGridBatches(*m_params, iBegin, iEnd);
- }
-};
-
-//
-// setupSpatialGridBatchesMt -- generate batches using a uniform 3D grid
-//
-/*
-
-Bodies are treated as 3D points at their center of mass. We only consider dynamic bodies at this stage,
-because only dynamic bodies are mutated when a constraint is solved, thus subject to race conditions.
-
-1. Compute a bounding box around all dynamic bodies
-2. Compute the maximum extent of all dynamic constraints. Each dynamic constraint is treated as a line segment, and we need the size of
- box that will fully enclose any single dynamic constraint
-
-3. Establish the cell size of our grid, the cell size in each dimension must be at least as large as the dynamic constraints max-extent,
- so that no dynamic constraint can span more than 2 cells of our grid on any axis of the grid. The cell size should be adjusted
- larger in order to keep the total number of cells from being excessively high
-
-Key idea: Given that each constraint spans 1 or 2 grid cells in each dimension, we can handle all constraints by processing
- in chunks of 2x2x2 cells with 8 different 1-cell offsets ((0,0,0),(0,0,1),(0,1,0),(0,1,1),(1,0,0)...).
- For each of the 8 offsets, we create a phase, and for each 2x2x2 chunk with dynamic constraints becomes a batch in that phase.
-
-4. Once the grid is established, we can calculate for each constraint which phase and batch it belongs in.
-
-5. Do a merge small batches on the batches of each phase separately, to try to even out the sizes of batches
-
-Optionally, we can "collapse" one dimension of our 3D grid to turn it into a 2D grid, which reduces the number of phases
-to 4. With fewer phases, there are more constraints per phase and this makes it easier to create batches of a useful size.
-*/
-//
-static void setupSpatialGridBatchesMt(
- btBatchedConstraints* batchedConstraints,
- btAlignedObjectArray<char>* scratchMemory,
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- int minBatchSize,
- int maxBatchSize,
- bool use2DGrid)
-{
- BT_PROFILE("setupSpatialGridBatchesMt");
- const int numPhases = 8;
- int numConstraints = constraints->size();
- int numConstraintRows = constraints->size();
-
- const int maxGridChunkCount = 128;
- int allocNumBatchesPerPhase = maxGridChunkCount;
- int minNumBatchesPerPhase = 16;
- int allocNumBatches = allocNumBatchesPerPhase * numPhases;
-
- btVector3* bodyPositions = NULL;
- bool* bodyDynamicFlags = NULL;
- btIntVec3* bodyGridCoords = NULL;
- btBatchInfo* batches = NULL;
- int* batchWork = NULL;
- btBatchedConstraintInfo* conInfos = NULL;
- int* constraintBatchIds = NULL;
- int* constraintRowBatchIds = NULL;
- {
- PreallocatedMemoryHelper<10> memHelper;
- memHelper.addChunk((void**)&bodyPositions, sizeof(btVector3) * bodies.size());
- memHelper.addChunk((void**)&bodyDynamicFlags, sizeof(bool) * bodies.size());
- memHelper.addChunk((void**)&bodyGridCoords, sizeof(btIntVec3) * bodies.size());
- memHelper.addChunk((void**)&batches, sizeof(btBatchInfo) * allocNumBatches);
- memHelper.addChunk((void**)&batchWork, sizeof(int) * allocNumBatches);
- memHelper.addChunk((void**)&conInfos, sizeof(btBatchedConstraintInfo) * numConstraints);
- memHelper.addChunk((void**)&constraintBatchIds, sizeof(int) * numConstraints);
- memHelper.addChunk((void**)&constraintRowBatchIds, sizeof(int) * numConstraintRows);
- size_t scratchSize = memHelper.getSizeToAllocate();
- // if we need to reallocate
- if (static_cast<size_t>(scratchMemory->capacity()) < scratchSize)
- {
- // allocate 6.25% extra to avoid repeated reallocs
- scratchMemory->reserve(scratchSize + scratchSize / 16);
- }
- scratchMemory->resizeNoInitialize(scratchSize);
- char* memPtr = &scratchMemory->at(0);
- memHelper.setChunkPointers(memPtr);
- }
-
- numConstraints = initBatchedConstraintInfo(conInfos, constraints);
-
- // compute bounding box around all dynamic bodies
- // (could be done in parallel)
- btVector3 bboxMin(BT_LARGE_FLOAT, BT_LARGE_FLOAT, BT_LARGE_FLOAT);
- btVector3 bboxMax = -bboxMin;
- //int dynamicBodyCount = 0;
- for (int i = 0; i < bodies.size(); ++i)
- {
- const btSolverBody& body = bodies[i];
- btVector3 bodyPos = body.getWorldTransform().getOrigin();
- bool isDynamic = (body.internalGetInvMass().x() > btScalar(0));
- bodyPositions[i] = bodyPos;
- bodyDynamicFlags[i] = isDynamic;
- if (isDynamic)
- {
- //dynamicBodyCount++;
- bboxMin.setMin(bodyPos);
- bboxMax.setMax(bodyPos);
- }
- }
-
- // find max extent of all dynamic constraints
- // (could be done in parallel)
- btVector3 consExtent = findMaxDynamicConstraintExtent(bodyPositions, bodyDynamicFlags, conInfos, numConstraints, bodies.size());
-
- btVector3 gridExtent = bboxMax - bboxMin;
-
- gridExtent.setMax(btVector3(btScalar(1), btScalar(1), btScalar(1)));
-
- btVector3 gridCellSize = consExtent;
- int gridDim[3];
- gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
- gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
- gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
-
- // if we can collapse an axis, it will cut our number of phases in half which could be more efficient
- int phaseMask = 7;
- bool collapseAxis = use2DGrid;
- if (collapseAxis)
- {
- // pick the smallest axis to collapse, leaving us with the greatest number of cells in our grid
- int iAxisToCollapse = 0;
- int axisDim = gridDim[iAxisToCollapse];
- //for each dimension
- for (int i = 0; i < 3; ++i)
- {
- if (gridDim[i] < axisDim)
- {
- iAxisToCollapse = i;
- axisDim = gridDim[i];
- }
- }
- // collapse it
- gridCellSize[iAxisToCollapse] = gridExtent[iAxisToCollapse] * 2.0f;
- phaseMask &= ~(1 << iAxisToCollapse);
- }
-
- int numGridChunks = 0;
- btIntVec3 gridChunkDim; // each chunk is 2x2x2 group of cells
- while (true)
- {
- gridDim[0] = int(1.0 + gridExtent.x() / gridCellSize.x());
- gridDim[1] = int(1.0 + gridExtent.y() / gridCellSize.y());
- gridDim[2] = int(1.0 + gridExtent.z() / gridCellSize.z());
- gridChunkDim[0] = btMax(1, (gridDim[0] + 0) / 2);
- gridChunkDim[1] = btMax(1, (gridDim[1] + 0) / 2);
- gridChunkDim[2] = btMax(1, (gridDim[2] + 0) / 2);
- numGridChunks = gridChunkDim[0] * gridChunkDim[1] * gridChunkDim[2];
- float nChunks = float(gridChunkDim[0]) * float(gridChunkDim[1]) * float(gridChunkDim[2]); // suceptible to integer overflow
- if (numGridChunks <= maxGridChunkCount && nChunks <= maxGridChunkCount)
- {
- break;
- }
- gridCellSize *= 1.25; // should roughly cut numCells in half
- }
- btAssert(numGridChunks <= maxGridChunkCount);
- int maxNumBatchesPerPhase = numGridChunks;
-
- // for each dynamic body, compute grid coords
- btVector3 invGridCellSize = btVector3(1, 1, 1) / gridCellSize;
- // (can be done in parallel)
- for (int iBody = 0; iBody < bodies.size(); ++iBody)
- {
- btIntVec3& coords = bodyGridCoords[iBody];
- if (bodyDynamicFlags[iBody])
- {
- btVector3 v = (bodyPositions[iBody] - bboxMin) * invGridCellSize;
- coords.m_ints[0] = int(v.x());
- coords.m_ints[1] = int(v.y());
- coords.m_ints[2] = int(v.z());
- btAssert(coords.m_ints[0] >= 0 && coords.m_ints[0] < gridDim[0]);
- btAssert(coords.m_ints[1] >= 0 && coords.m_ints[1] < gridDim[1]);
- btAssert(coords.m_ints[2] >= 0 && coords.m_ints[2] < gridDim[2]);
- }
- else
- {
- coords.m_ints[0] = -1;
- coords.m_ints[1] = -1;
- coords.m_ints[2] = -1;
- }
- }
-
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- int batchBegin = iPhase * maxNumBatchesPerPhase;
- int batchEnd = batchBegin + maxNumBatchesPerPhase;
- for (int iBatch = batchBegin; iBatch < batchEnd; ++iBatch)
- {
- btBatchInfo& batch = batches[iBatch];
- batch = btBatchInfo();
- }
- }
-
- {
- AssignConstraintsToGridBatchesParams params;
- params.bodyDynamicFlags = bodyDynamicFlags;
- params.bodyGridCoords = bodyGridCoords;
- params.numBodies = bodies.size();
- params.conInfos = conInfos;
- params.constraintBatchIds = constraintBatchIds;
- params.gridChunkDim = gridChunkDim;
- params.maxNumBatchesPerPhase = maxNumBatchesPerPhase;
- params.numPhases = numPhases;
- params.phaseMask = phaseMask;
- bool inParallel = true;
- if (inParallel)
- {
- AssignConstraintsToGridBatchesLoop loop(params);
- int grainSize = 250;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- assignConstraintsToGridBatches(params, 0, numConstraints);
- }
- }
- for (int iCon = 0; iCon < numConstraints; ++iCon)
- {
- const btBatchedConstraintInfo& con = conInfos[iCon];
- int iBatch = constraintBatchIds[iCon];
- btBatchInfo& batch = batches[iBatch];
- batch.numConstraints += con.numConstraintRows;
- }
-
- for (int iPhase = 0; iPhase < numPhases; ++iPhase)
- {
- // if phase is legit,
- if (iPhase == (iPhase & phaseMask))
- {
- int iBeginBatch = iPhase * maxNumBatchesPerPhase;
- int iEndBatch = iBeginBatch + maxNumBatchesPerPhase;
- mergeSmallBatches(batches, iBeginBatch, iEndBatch, minBatchSize, maxBatchSize);
- }
- }
- // all constraints have been assigned a batchId
- updateConstraintBatchIdsForMergesMt(constraintBatchIds, numConstraints, batches, maxNumBatchesPerPhase * numPhases);
-
- if (numConstraintRows > numConstraints)
- {
- expandConstraintRowsMt(&constraintRowBatchIds[0], &constraintBatchIds[0], &conInfos[0], numConstraints, numConstraintRows);
- }
- else
- {
- constraintRowBatchIds = constraintBatchIds;
- }
-
- writeOutBatches(batchedConstraints, constraintRowBatchIds, numConstraintRows, batches, batchWork, maxNumBatchesPerPhase, numPhases);
- btAssert(batchedConstraints->validate(constraints, bodies));
-}
-
-static void setupSingleBatch(
- btBatchedConstraints* bc,
- int numConstraints)
-{
- BT_PROFILE("setupSingleBatch");
- typedef btBatchedConstraints::Range Range;
-
- bc->m_constraintIndices.resize(numConstraints);
- for (int i = 0; i < numConstraints; ++i)
- {
- bc->m_constraintIndices[i] = i;
- }
-
- bc->m_batches.resizeNoInitialize(0);
- bc->m_phases.resizeNoInitialize(0);
- bc->m_phaseOrder.resizeNoInitialize(0);
- bc->m_phaseGrainSize.resizeNoInitialize(0);
-
- if (numConstraints > 0)
- {
- bc->m_batches.push_back(Range(0, numConstraints));
- bc->m_phases.push_back(Range(0, 1));
- bc->m_phaseOrder.push_back(0);
- bc->m_phaseGrainSize.push_back(1);
- }
-}
-
-void btBatchedConstraints::setup(
- btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- BatchingMethod batchingMethod,
- int minBatchSize,
- int maxBatchSize,
- btAlignedObjectArray<char>* scratchMemory)
-{
- if (constraints->size() >= minBatchSize * 4)
- {
- bool use2DGrid = batchingMethod == BATCHING_METHOD_SPATIAL_GRID_2D;
- setupSpatialGridBatchesMt(this, scratchMemory, constraints, bodies, minBatchSize, maxBatchSize, use2DGrid);
- if (s_debugDrawBatches)
- {
- debugDrawAllBatches(this, constraints, bodies);
- }
- }
- else
- {
- setupSingleBatch(this, constraints->size());
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
deleted file mode 100644
index 5d982ca370..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btBatchedConstraints.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_BATCHED_CONSTRAINTS_H
-#define BT_BATCHED_CONSTRAINTS_H
-
-#include "LinearMath/btThreads.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
-#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
-
-class btIDebugDraw;
-
-struct btBatchedConstraints
-{
- enum BatchingMethod
- {
- BATCHING_METHOD_SPATIAL_GRID_2D,
- BATCHING_METHOD_SPATIAL_GRID_3D,
- BATCHING_METHOD_COUNT
- };
- struct Range
- {
- int begin;
- int end;
-
- Range() : begin(0), end(0) {}
- Range(int _beg, int _end) : begin(_beg), end(_end) {}
- };
-
- btAlignedObjectArray<int> m_constraintIndices;
- btAlignedObjectArray<Range> m_batches; // each batch is a range of indices in the m_constraintIndices array
- btAlignedObjectArray<Range> m_phases; // each phase is range of indices in the m_batches array
- btAlignedObjectArray<char> m_phaseGrainSize; // max grain size for each phase
- btAlignedObjectArray<int> m_phaseOrder; // phases can be done in any order, so we can randomize the order here
- btIDebugDraw* m_debugDrawer;
-
- static bool s_debugDrawBatches;
-
- btBatchedConstraints() { m_debugDrawer = NULL; }
- void setup(btConstraintArray* constraints,
- const btAlignedObjectArray<btSolverBody>& bodies,
- BatchingMethod batchingMethod,
- int minBatchSize,
- int maxBatchSize,
- btAlignedObjectArray<char>* scratchMemory);
- bool validate(btConstraintArray* constraints, const btAlignedObjectArray<btSolverBody>& bodies) const;
-};
-
-#endif // BT_BATCHED_CONSTRAINTS_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
deleted file mode 100644
index ac046aa6ea..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp
+++ /dev/null
@@ -1,1116 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-Written by: Marcus Hennix
-*/
-
-#include "btConeTwistConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btMinMax.h"
-#include <cmath>
-#include <new>
-
-//#define CONETWIST_USE_OBSOLETE_SOLVER true
-#define CONETWIST_USE_OBSOLETE_SOLVER false
-#define CONETWIST_DEF_FIX_THRESH btScalar(.05f)
-
-SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis, const btMatrix3x3& invInertiaWorld)
-{
- btVector3 vec = axis * invInertiaWorld;
- return axis.dot(vec);
-}
-
-btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, btRigidBody& rbB,
- const btTransform& rbAFrame, const btTransform& rbBFrame)
- : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
-{
- init();
-}
-
-btConeTwistConstraint::btConeTwistConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
- : btTypedConstraint(CONETWIST_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_angularOnly(false), m_useSolveConstraintObsolete(CONETWIST_USE_OBSOLETE_SOLVER)
-{
- m_rbBFrame = m_rbAFrame;
- m_rbBFrame.setOrigin(btVector3(0., 0., 0.));
- init();
-}
-
-void btConeTwistConstraint::init()
-{
- m_angularOnly = false;
- m_solveTwistLimit = false;
- m_solveSwingLimit = false;
- m_bMotorEnabled = false;
- m_maxMotorImpulse = btScalar(-1);
-
- setLimit(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
- m_damping = btScalar(0.01);
- m_fixThresh = CONETWIST_DEF_FIX_THRESH;
- m_flags = 0;
- m_linCFM = btScalar(0.f);
- m_linERP = btScalar(0.7f);
- m_angCFM = btScalar(0.f);
-}
-
-void btConeTwistConstraint::getInfo1(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- info->m_numConstraintRows = 3;
- info->nub = 3;
- calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
- if (m_solveSwingLimit)
- {
- info->m_numConstraintRows++;
- info->nub--;
- if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
- if (m_solveTwistLimit)
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
-}
-
-void btConeTwistConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
-{
- //always reserve 6 rows: object transform is not available on SPU
- info->m_numConstraintRows = 6;
- info->nub = 0;
-}
-
-void btConeTwistConstraint::getInfo2(btConstraintInfo2* info)
-{
- getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
-}
-
-void btConeTwistConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
-{
- calcAngleInfo2(transA, transB, invInertiaWorldA, invInertiaWorldB);
-
- btAssert(!m_useSolveConstraintObsolete);
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip + 1] = 1;
- info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
- btVector3 a1 = transA.getBasis() * m_rbAFrame.getOrigin();
- {
- btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
- btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip + 1] = -1;
- info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
- btVector3 a2 = transB.getBasis() * m_rbBFrame.getOrigin();
- {
- btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
- // set right hand side
- btScalar linERP = (m_flags & BT_CONETWIST_FLAGS_LIN_ERP) ? m_linERP : info->erp;
- btScalar k = info->fps * linERP;
- int j;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[j * info->rowskip] = k * (a2[j] + transB.getOrigin()[j] - a1[j] - transA.getOrigin()[j]);
- info->m_lowerLimit[j * info->rowskip] = -SIMD_INFINITY;
- info->m_upperLimit[j * info->rowskip] = SIMD_INFINITY;
- if (m_flags & BT_CONETWIST_FLAGS_LIN_CFM)
- {
- info->cfm[j * info->rowskip] = m_linCFM;
- }
- }
- int row = 3;
- int srow = row * info->rowskip;
- btVector3 ax1;
- // angular limits
- if (m_solveSwingLimit)
- {
- btScalar* J1 = info->m_J1angularAxis;
- btScalar* J2 = info->m_J2angularAxis;
- if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
- {
- btTransform trA = transA * m_rbAFrame;
- btVector3 p = trA.getBasis().getColumn(1);
- btVector3 q = trA.getBasis().getColumn(2);
- int srow1 = srow + info->rowskip;
- J1[srow + 0] = p[0];
- J1[srow + 1] = p[1];
- J1[srow + 2] = p[2];
- J1[srow1 + 0] = q[0];
- J1[srow1 + 1] = q[1];
- J1[srow1 + 2] = q[2];
- J2[srow + 0] = -p[0];
- J2[srow + 1] = -p[1];
- J2[srow + 2] = -p[2];
- J2[srow1 + 0] = -q[0];
- J2[srow1 + 1] = -q[1];
- J2[srow1 + 2] = -q[2];
- btScalar fact = info->fps * m_relaxationFactor;
- info->m_constraintError[srow] = fact * m_swingAxis.dot(p);
- info->m_constraintError[srow1] = fact * m_swingAxis.dot(q);
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- info->m_lowerLimit[srow1] = -SIMD_INFINITY;
- info->m_upperLimit[srow1] = SIMD_INFINITY;
- srow = srow1 + info->rowskip;
- }
- else
- {
- ax1 = m_swingAxis * m_relaxationFactor * m_relaxationFactor;
- J1[srow + 0] = ax1[0];
- J1[srow + 1] = ax1[1];
- J1[srow + 2] = ax1[2];
- J2[srow + 0] = -ax1[0];
- J2[srow + 1] = -ax1[1];
- J2[srow + 2] = -ax1[2];
- btScalar k = info->fps * m_biasFactor;
-
- info->m_constraintError[srow] = k * m_swingCorrection;
- if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
- {
- info->cfm[srow] = m_angCFM;
- }
- // m_swingCorrection is always positive or 0
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = (m_bMotorEnabled && m_maxMotorImpulse >= 0.0f) ? m_maxMotorImpulse : SIMD_INFINITY;
- srow += info->rowskip;
- }
- }
- if (m_solveTwistLimit)
- {
- ax1 = m_twistAxis * m_relaxationFactor * m_relaxationFactor;
- btScalar* J1 = info->m_J1angularAxis;
- btScalar* J2 = info->m_J2angularAxis;
- J1[srow + 0] = ax1[0];
- J1[srow + 1] = ax1[1];
- J1[srow + 2] = ax1[2];
- J2[srow + 0] = -ax1[0];
- J2[srow + 1] = -ax1[1];
- J2[srow + 2] = -ax1[2];
- btScalar k = info->fps * m_biasFactor;
- info->m_constraintError[srow] = k * m_twistCorrection;
- if (m_flags & BT_CONETWIST_FLAGS_ANG_CFM)
- {
- info->cfm[srow] = m_angCFM;
- }
- if (m_twistSpan > 0.0f)
- {
- if (m_twistCorrection > 0.0f)
- {
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- {
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- }
- else
- {
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- srow += info->rowskip;
- }
-}
-
-void btConeTwistConstraint::buildJacobian()
-{
- if (m_useSolveConstraintObsolete)
- {
- m_appliedImpulse = btScalar(0.);
- m_accTwistLimitImpulse = btScalar(0.);
- m_accSwingLimitImpulse = btScalar(0.);
- m_accMotorImpulse = btVector3(0., 0., 0.);
-
- if (!m_angularOnly)
- {
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
- btVector3 relPos = pivotBInW - pivotAInW;
-
- btVector3 normal[3];
- if (relPos.length2() > SIMD_EPSILON)
- {
- normal[0] = relPos.normalized();
- }
- else
- {
- normal[0].setValue(btScalar(1.0), 0, 0);
- }
-
- btPlaneSpace1(normal[0], normal[1], normal[2]);
-
- for (int i = 0; i < 3; i++)
- {
- new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normal[i],
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
- }
- }
-
- calcAngleInfo2(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getInvInertiaTensorWorld(), m_rbB.getInvInertiaTensorWorld());
- }
-}
-
-void btConeTwistConstraint::solveConstraintObsolete(btSolverBody& bodyA, btSolverBody& bodyB, btScalar timeStep)
-{
-#ifndef __SPU__
- if (m_useSolveConstraintObsolete)
- {
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
-
- btScalar tau = btScalar(0.3);
-
- //linear part
- if (!m_angularOnly)
- {
- btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
- btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
-
- btVector3 vel1;
- bodyA.internalGetVelocityInLocalPointObsolete(rel_pos1, vel1);
- btVector3 vel2;
- bodyB.internalGetVelocityInLocalPointObsolete(rel_pos2, vel2);
- btVector3 vel = vel1 - vel2;
-
- for (int i = 0; i < 3; i++)
- {
- const btVector3& normal = m_jac[i].m_linearJointAxis;
- btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
-
- btScalar rel_vel;
- rel_vel = normal.dot(vel);
- //positional error (zeroth order error)
- btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
- btScalar impulse = depth * tau / timeStep * jacDiagABInv - rel_vel * jacDiagABInv;
- m_appliedImpulse += impulse;
-
- btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
- btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
- bodyA.internalApplyImpulse(normal * m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld() * ftorqueAxis1, impulse);
- bodyB.internalApplyImpulse(normal * m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld() * ftorqueAxis2, -impulse);
- }
- }
-
- // apply motor
- if (m_bMotorEnabled)
- {
- // compute current and predicted transforms
- btTransform trACur = m_rbA.getCenterOfMassTransform();
- btTransform trBCur = m_rbB.getCenterOfMassTransform();
- btVector3 omegaA;
- bodyA.internalGetAngularVelocity(omegaA);
- btVector3 omegaB;
- bodyB.internalGetAngularVelocity(omegaB);
- btTransform trAPred;
- trAPred.setIdentity();
- btVector3 zerovec(0, 0, 0);
- btTransformUtil::integrateTransform(
- trACur, zerovec, omegaA, timeStep, trAPred);
- btTransform trBPred;
- trBPred.setIdentity();
- btTransformUtil::integrateTransform(
- trBCur, zerovec, omegaB, timeStep, trBPred);
-
- // compute desired transforms in world
- btTransform trPose(m_qTarget);
- btTransform trABDes = m_rbBFrame * trPose * m_rbAFrame.inverse();
- btTransform trADes = trBPred * trABDes;
- btTransform trBDes = trAPred * trABDes.inverse();
-
- // compute desired omegas in world
- btVector3 omegaADes, omegaBDes;
-
- btTransformUtil::calculateVelocity(trACur, trADes, timeStep, zerovec, omegaADes);
- btTransformUtil::calculateVelocity(trBCur, trBDes, timeStep, zerovec, omegaBDes);
-
- // compute delta omegas
- btVector3 dOmegaA = omegaADes - omegaA;
- btVector3 dOmegaB = omegaBDes - omegaB;
-
- // compute weighted avg axis of dOmega (weighting based on inertias)
- btVector3 axisA, axisB;
- btScalar kAxisAInv = 0, kAxisBInv = 0;
-
- if (dOmegaA.length2() > SIMD_EPSILON)
- {
- axisA = dOmegaA.normalized();
- kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(axisA);
- }
-
- if (dOmegaB.length2() > SIMD_EPSILON)
- {
- axisB = dOmegaB.normalized();
- kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(axisB);
- }
-
- btVector3 avgAxis = kAxisAInv * axisA + kAxisBInv * axisB;
-
- static bool bDoTorque = true;
- if (bDoTorque && avgAxis.length2() > SIMD_EPSILON)
- {
- avgAxis.normalize();
- kAxisAInv = getRigidBodyA().computeAngularImpulseDenominator(avgAxis);
- kAxisBInv = getRigidBodyB().computeAngularImpulseDenominator(avgAxis);
- btScalar kInvCombined = kAxisAInv + kAxisBInv;
-
- btVector3 impulse = (kAxisAInv * dOmegaA - kAxisBInv * dOmegaB) /
- (kInvCombined * kInvCombined);
-
- if (m_maxMotorImpulse >= 0)
- {
- btScalar fMaxImpulse = m_maxMotorImpulse;
- if (m_bNormalizedMotorStrength)
- fMaxImpulse = fMaxImpulse / kAxisAInv;
-
- btVector3 newUnclampedAccImpulse = m_accMotorImpulse + impulse;
- btScalar newUnclampedMag = newUnclampedAccImpulse.length();
- if (newUnclampedMag > fMaxImpulse)
- {
- newUnclampedAccImpulse.normalize();
- newUnclampedAccImpulse *= fMaxImpulse;
- impulse = newUnclampedAccImpulse - m_accMotorImpulse;
- }
- m_accMotorImpulse += impulse;
- }
-
- btScalar impulseMag = impulse.length();
- btVector3 impulseAxis = impulse / impulseMag;
-
- bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
- }
- }
- else if (m_damping > SIMD_EPSILON) // no motor: do a little damping
- {
- btVector3 angVelA;
- bodyA.internalGetAngularVelocity(angVelA);
- btVector3 angVelB;
- bodyB.internalGetAngularVelocity(angVelB);
- btVector3 relVel = angVelB - angVelA;
- if (relVel.length2() > SIMD_EPSILON)
- {
- btVector3 relVelAxis = relVel.normalized();
- btScalar m_kDamping = btScalar(1.) /
- (getRigidBodyA().computeAngularImpulseDenominator(relVelAxis) +
- getRigidBodyB().computeAngularImpulseDenominator(relVelAxis));
- btVector3 impulse = m_damping * m_kDamping * relVel;
-
- btScalar impulseMag = impulse.length();
- btVector3 impulseAxis = impulse / impulseMag;
- bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * impulseAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * impulseAxis, -impulseMag);
- }
- }
-
- // joint limits
- {
- ///solve angular part
- btVector3 angVelA;
- bodyA.internalGetAngularVelocity(angVelA);
- btVector3 angVelB;
- bodyB.internalGetAngularVelocity(angVelB);
-
- // solve swing limit
- if (m_solveSwingLimit)
- {
- btScalar amplitude = m_swingLimitRatio * m_swingCorrection * m_biasFactor / timeStep;
- btScalar relSwingVel = (angVelB - angVelA).dot(m_swingAxis);
- if (relSwingVel > 0)
- amplitude += m_swingLimitRatio * relSwingVel * m_relaxationFactor;
- btScalar impulseMag = amplitude * m_kSwing;
-
- // Clamp the accumulated impulse
- btScalar temp = m_accSwingLimitImpulse;
- m_accSwingLimitImpulse = btMax(m_accSwingLimitImpulse + impulseMag, btScalar(0.0));
- impulseMag = m_accSwingLimitImpulse - temp;
-
- btVector3 impulse = m_swingAxis * impulseMag;
-
- // don't let cone response affect twist
- // (this can happen since body A's twist doesn't match body B's AND we use an elliptical cone limit)
- {
- btVector3 impulseTwistCouple = impulse.dot(m_twistAxisA) * m_twistAxisA;
- btVector3 impulseNoTwistCouple = impulse - impulseTwistCouple;
- impulse = impulseNoTwistCouple;
- }
-
- impulseMag = impulse.length();
- btVector3 noTwistSwingAxis = impulse / impulseMag;
-
- bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * noTwistSwingAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * noTwistSwingAxis, -impulseMag);
- }
-
- // solve twist limit
- if (m_solveTwistLimit)
- {
- btScalar amplitude = m_twistLimitRatio * m_twistCorrection * m_biasFactor / timeStep;
- btScalar relTwistVel = (angVelB - angVelA).dot(m_twistAxis);
- if (relTwistVel > 0) // only damp when moving towards limit (m_twistAxis flipping is important)
- amplitude += m_twistLimitRatio * relTwistVel * m_relaxationFactor;
- btScalar impulseMag = amplitude * m_kTwist;
-
- // Clamp the accumulated impulse
- btScalar temp = m_accTwistLimitImpulse;
- m_accTwistLimitImpulse = btMax(m_accTwistLimitImpulse + impulseMag, btScalar(0.0));
- impulseMag = m_accTwistLimitImpulse - temp;
-
- // btVector3 impulse = m_twistAxis * impulseMag;
-
- bodyA.internalApplyImpulse(btVector3(0, 0, 0), m_rbA.getInvInertiaTensorWorld() * m_twistAxis, impulseMag);
- bodyB.internalApplyImpulse(btVector3(0, 0, 0), m_rbB.getInvInertiaTensorWorld() * m_twistAxis, -impulseMag);
- }
- }
- }
-#else
- btAssert(0);
-#endif //__SPU__
-}
-
-void btConeTwistConstraint::updateRHS(btScalar timeStep)
-{
- (void)timeStep;
-}
-
-#ifndef __SPU__
-void btConeTwistConstraint::calcAngleInfo()
-{
- m_swingCorrection = btScalar(0.);
- m_twistLimitSign = btScalar(0.);
- m_solveTwistLimit = false;
- m_solveSwingLimit = false;
-
- btVector3 b1Axis1(0, 0, 0), b1Axis2(0, 0, 0), b1Axis3(0, 0, 0);
- btVector3 b2Axis1(0, 0, 0), b2Axis2(0, 0, 0);
-
- b1Axis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(0);
- b2Axis1 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(0);
-
- btScalar swing1 = btScalar(0.), swing2 = btScalar(0.);
-
- btScalar swx = btScalar(0.), swy = btScalar(0.);
- btScalar thresh = btScalar(10.);
- btScalar fact;
-
- // Get Frame into world space
- if (m_swingSpan1 >= btScalar(0.05f))
- {
- b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1);
- swx = b2Axis1.dot(b1Axis1);
- swy = b2Axis1.dot(b1Axis2);
- swing1 = btAtan2Fast(swy, swx);
- fact = (swy * swy + swx * swx) * thresh * thresh;
- fact = fact / (fact + btScalar(1.0));
- swing1 *= fact;
- }
-
- if (m_swingSpan2 >= btScalar(0.05f))
- {
- b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2);
- swx = b2Axis1.dot(b1Axis1);
- swy = b2Axis1.dot(b1Axis3);
- swing2 = btAtan2Fast(swy, swx);
- fact = (swy * swy + swx * swx) * thresh * thresh;
- fact = fact / (fact + btScalar(1.0));
- swing2 *= fact;
- }
-
- btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1);
- btScalar RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2);
- btScalar EllipseAngle = btFabs(swing1 * swing1) * RMaxAngle1Sq + btFabs(swing2 * swing2) * RMaxAngle2Sq;
-
- if (EllipseAngle > 1.0f)
- {
- m_swingCorrection = EllipseAngle - 1.0f;
- m_solveSwingLimit = true;
- // Calculate necessary axis & factors
- m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3));
- m_swingAxis.normalize();
- btScalar swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f;
- m_swingAxis *= swingAxisSign;
- }
-
- // Twist limits
- if (m_twistSpan >= btScalar(0.))
- {
- btVector3 b2Axis2 = getRigidBodyB().getCenterOfMassTransform().getBasis() * this->m_rbBFrame.getBasis().getColumn(1);
- btQuaternion rotationArc = shortestArcQuat(b2Axis1, b1Axis1);
- btVector3 TwistRef = quatRotate(rotationArc, b2Axis2);
- btScalar twist = btAtan2Fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2));
- m_twistAngle = twist;
-
- // btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? m_limitSoftness : btScalar(0.);
- btScalar lockedFreeFactor = (m_twistSpan > btScalar(0.05f)) ? btScalar(1.0f) : btScalar(0.);
- if (twist <= -m_twistSpan * lockedFreeFactor)
- {
- m_twistCorrection = -(twist + m_twistSpan);
- m_solveTwistLimit = true;
- m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
- m_twistAxis.normalize();
- m_twistAxis *= -1.0f;
- }
- else if (twist > m_twistSpan * lockedFreeFactor)
- {
- m_twistCorrection = (twist - m_twistSpan);
- m_solveTwistLimit = true;
- m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f;
- m_twistAxis.normalize();
- }
- }
-}
-#endif //__SPU__
-
-static btVector3 vTwist(1, 0, 0); // twist axis in constraint's space
-
-void btConeTwistConstraint::calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB)
-{
- m_swingCorrection = btScalar(0.);
- m_twistLimitSign = btScalar(0.);
- m_solveTwistLimit = false;
- m_solveSwingLimit = false;
- // compute rotation of A wrt B (in constraint space)
- if (m_bMotorEnabled && (!m_useSolveConstraintObsolete))
- { // it is assumed that setMotorTarget() was alredy called
- // and motor target m_qTarget is within constraint limits
- // TODO : split rotation to pure swing and pure twist
- // compute desired transforms in world
- btTransform trPose(m_qTarget);
- btTransform trA = transA * m_rbAFrame;
- btTransform trB = transB * m_rbBFrame;
- btTransform trDeltaAB = trB * trPose * trA.inverse();
- btQuaternion qDeltaAB = trDeltaAB.getRotation();
- btVector3 swingAxis = btVector3(qDeltaAB.x(), qDeltaAB.y(), qDeltaAB.z());
- btScalar swingAxisLen2 = swingAxis.length2();
- if (btFuzzyZero(swingAxisLen2))
- {
- return;
- }
- m_swingAxis = swingAxis;
- m_swingAxis.normalize();
- m_swingCorrection = qDeltaAB.getAngle();
- if (!btFuzzyZero(m_swingCorrection))
- {
- m_solveSwingLimit = true;
- }
- return;
- }
-
- {
- // compute rotation of A wrt B (in constraint space)
- btQuaternion qA = transA.getRotation() * m_rbAFrame.getRotation();
- btQuaternion qB = transB.getRotation() * m_rbBFrame.getRotation();
- btQuaternion qAB = qB.inverse() * qA;
- // split rotation into cone and twist
- // (all this is done from B's perspective. Maybe I should be averaging axes...)
- btVector3 vConeNoTwist = quatRotate(qAB, vTwist);
- vConeNoTwist.normalize();
- btQuaternion qABCone = shortestArcQuat(vTwist, vConeNoTwist);
- qABCone.normalize();
- btQuaternion qABTwist = qABCone.inverse() * qAB;
- qABTwist.normalize();
-
- if (m_swingSpan1 >= m_fixThresh && m_swingSpan2 >= m_fixThresh)
- {
- btScalar swingAngle, swingLimit = 0;
- btVector3 swingAxis;
- computeConeLimitInfo(qABCone, swingAngle, swingAxis, swingLimit);
-
- if (swingAngle > swingLimit * m_limitSoftness)
- {
- m_solveSwingLimit = true;
-
- // compute limit ratio: 0->1, where
- // 0 == beginning of soft limit
- // 1 == hard/real limit
- m_swingLimitRatio = 1.f;
- if (swingAngle < swingLimit && m_limitSoftness < 1.f - SIMD_EPSILON)
- {
- m_swingLimitRatio = (swingAngle - swingLimit * m_limitSoftness) /
- (swingLimit - swingLimit * m_limitSoftness);
- }
-
- // swing correction tries to get back to soft limit
- m_swingCorrection = swingAngle - (swingLimit * m_limitSoftness);
-
- // adjustment of swing axis (based on ellipse normal)
- adjustSwingAxisToUseEllipseNormal(swingAxis);
-
- // Calculate necessary axis & factors
- m_swingAxis = quatRotate(qB, -swingAxis);
-
- m_twistAxisA.setValue(0, 0, 0);
-
- m_kSwing = btScalar(1.) /
- (computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldA) +
- computeAngularImpulseDenominator(m_swingAxis, invInertiaWorldB));
- }
- }
- else
- {
- // you haven't set any limits;
- // or you're trying to set at least one of the swing limits too small. (if so, do you really want a conetwist constraint?)
- // anyway, we have either hinge or fixed joint
- btVector3 ivA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
- btVector3 jvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
- btVector3 kvA = transA.getBasis() * m_rbAFrame.getBasis().getColumn(2);
- btVector3 ivB = transB.getBasis() * m_rbBFrame.getBasis().getColumn(0);
- btVector3 target;
- btScalar x = ivB.dot(ivA);
- btScalar y = ivB.dot(jvA);
- btScalar z = ivB.dot(kvA);
- if ((m_swingSpan1 < m_fixThresh) && (m_swingSpan2 < m_fixThresh))
- { // fixed. We'll need to add one more row to constraint
- if ((!btFuzzyZero(y)) || (!(btFuzzyZero(z))))
- {
- m_solveSwingLimit = true;
- m_swingAxis = -ivB.cross(ivA);
- }
- }
- else
- {
- if (m_swingSpan1 < m_fixThresh)
- { // hinge around Y axis
- // if(!(btFuzzyZero(y)))
- if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(z))))
- {
- m_solveSwingLimit = true;
- if (m_swingSpan2 >= m_fixThresh)
- {
- y = btScalar(0.f);
- btScalar span2 = btAtan2(z, x);
- if (span2 > m_swingSpan2)
- {
- x = btCos(m_swingSpan2);
- z = btSin(m_swingSpan2);
- }
- else if (span2 < -m_swingSpan2)
- {
- x = btCos(m_swingSpan2);
- z = -btSin(m_swingSpan2);
- }
- }
- }
- }
- else
- { // hinge around Z axis
- // if(!btFuzzyZero(z))
- if ((!(btFuzzyZero(x))) || (!(btFuzzyZero(y))))
- {
- m_solveSwingLimit = true;
- if (m_swingSpan1 >= m_fixThresh)
- {
- z = btScalar(0.f);
- btScalar span1 = btAtan2(y, x);
- if (span1 > m_swingSpan1)
- {
- x = btCos(m_swingSpan1);
- y = btSin(m_swingSpan1);
- }
- else if (span1 < -m_swingSpan1)
- {
- x = btCos(m_swingSpan1);
- y = -btSin(m_swingSpan1);
- }
- }
- }
- }
- target[0] = x * ivA[0] + y * jvA[0] + z * kvA[0];
- target[1] = x * ivA[1] + y * jvA[1] + z * kvA[1];
- target[2] = x * ivA[2] + y * jvA[2] + z * kvA[2];
- target.normalize();
- m_swingAxis = -ivB.cross(target);
- m_swingCorrection = m_swingAxis.length();
-
- if (!btFuzzyZero(m_swingCorrection))
- m_swingAxis.normalize();
- }
- }
-
- if (m_twistSpan >= btScalar(0.f))
- {
- btVector3 twistAxis;
- computeTwistLimitInfo(qABTwist, m_twistAngle, twistAxis);
-
- if (m_twistAngle > m_twistSpan * m_limitSoftness)
- {
- m_solveTwistLimit = true;
-
- m_twistLimitRatio = 1.f;
- if (m_twistAngle < m_twistSpan && m_limitSoftness < 1.f - SIMD_EPSILON)
- {
- m_twistLimitRatio = (m_twistAngle - m_twistSpan * m_limitSoftness) /
- (m_twistSpan - m_twistSpan * m_limitSoftness);
- }
-
- // twist correction tries to get back to soft limit
- m_twistCorrection = m_twistAngle - (m_twistSpan * m_limitSoftness);
-
- m_twistAxis = quatRotate(qB, -twistAxis);
-
- m_kTwist = btScalar(1.) /
- (computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldA) +
- computeAngularImpulseDenominator(m_twistAxis, invInertiaWorldB));
- }
-
- if (m_solveSwingLimit)
- m_twistAxisA = quatRotate(qA, -twistAxis);
- }
- else
- {
- m_twistAngle = btScalar(0.f);
- }
- }
-}
-
-// given a cone rotation in constraint space, (pre: twist must already be removed)
-// this method computes its corresponding swing angle and axis.
-// more interestingly, it computes the cone/swing limit (angle) for this cone "pose".
-void btConeTwistConstraint::computeConeLimitInfo(const btQuaternion& qCone,
- btScalar& swingAngle, // out
- btVector3& vSwingAxis, // out
- btScalar& swingLimit) // out
-{
- swingAngle = qCone.getAngle();
- if (swingAngle > SIMD_EPSILON)
- {
- vSwingAxis = btVector3(qCone.x(), qCone.y(), qCone.z());
- vSwingAxis.normalize();
-#if 0
- // non-zero twist?! this should never happen.
- btAssert(fabs(vSwingAxis.x()) <= SIMD_EPSILON));
-#endif
-
- // Compute limit for given swing. tricky:
- // Given a swing axis, we're looking for the intersection with the bounding cone ellipse.
- // (Since we're dealing with angles, this ellipse is embedded on the surface of a sphere.)
-
- // For starters, compute the direction from center to surface of ellipse.
- // This is just the perpendicular (ie. rotate 2D vector by PI/2) of the swing axis.
- // (vSwingAxis is the cone rotation (in z,y); change vars and rotate to (x,y) coords.)
- btScalar xEllipse = vSwingAxis.y();
- btScalar yEllipse = -vSwingAxis.z();
-
- // Now, we use the slope of the vector (using x/yEllipse) and find the length
- // of the line that intersects the ellipse:
- // x^2 y^2
- // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
- // a^2 b^2
- // Do the math and it should be clear.
-
- swingLimit = m_swingSpan1; // if xEllipse == 0, we have a pure vSwingAxis.z rotation: just use swingspan1
- if (fabs(xEllipse) > SIMD_EPSILON)
- {
- btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
- btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
- norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
- btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
- swingLimit = std::sqrt(swingLimit2);
- }
-
- // test!
- /*swingLimit = m_swingSpan2;
- if (fabs(vSwingAxis.z()) > SIMD_EPSILON)
- {
- btScalar mag_2 = m_swingSpan1*m_swingSpan1 + m_swingSpan2*m_swingSpan2;
- btScalar sinphi = m_swingSpan2 / sqrt(mag_2);
- btScalar phi = asin(sinphi);
- btScalar theta = atan2(fabs(vSwingAxis.y()),fabs(vSwingAxis.z()));
- btScalar alpha = 3.14159f - theta - phi;
- btScalar sinalpha = sin(alpha);
- swingLimit = m_swingSpan1 * sinphi/sinalpha;
- }*/
- }
- else if (swingAngle < 0)
- {
- // this should never happen!
-#if 0
- btAssert(0);
-#endif
- }
-}
-
-btVector3 btConeTwistConstraint::GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const
-{
- // compute x/y in ellipse using cone angle (0 -> 2*PI along surface of cone)
- btScalar xEllipse = btCos(fAngleInRadians);
- btScalar yEllipse = btSin(fAngleInRadians);
-
- // Use the slope of the vector (using x/yEllipse) and find the length
- // of the line that intersects the ellipse:
- // x^2 y^2
- // --- + --- = 1, where a and b are semi-major axes 2 and 1 respectively (ie. the limits)
- // a^2 b^2
- // Do the math and it should be clear.
-
- btScalar swingLimit = m_swingSpan1; // if xEllipse == 0, just use axis b (1)
- if (fabs(xEllipse) > SIMD_EPSILON)
- {
- btScalar surfaceSlope2 = (yEllipse * yEllipse) / (xEllipse * xEllipse);
- btScalar norm = 1 / (m_swingSpan2 * m_swingSpan2);
- norm += surfaceSlope2 / (m_swingSpan1 * m_swingSpan1);
- btScalar swingLimit2 = (1 + surfaceSlope2) / norm;
- swingLimit = std::sqrt(swingLimit2);
- }
-
- // convert into point in constraint space:
- // note: twist is x-axis, swing 1 and 2 are along the z and y axes respectively
- btVector3 vSwingAxis(0, xEllipse, -yEllipse);
- btQuaternion qSwing(vSwingAxis, swingLimit);
- btVector3 vPointInConstraintSpace(fLength, 0, 0);
- return quatRotate(qSwing, vPointInConstraintSpace);
-}
-
-// given a twist rotation in constraint space, (pre: cone must already be removed)
-// this method computes its corresponding angle and axis.
-void btConeTwistConstraint::computeTwistLimitInfo(const btQuaternion& qTwist,
- btScalar& twistAngle, // out
- btVector3& vTwistAxis) // out
-{
- btQuaternion qMinTwist = qTwist;
- twistAngle = qTwist.getAngle();
-
- if (twistAngle > SIMD_PI) // long way around. flip quat and recalculate.
- {
- qMinTwist = -(qTwist);
- twistAngle = qMinTwist.getAngle();
- }
- if (twistAngle < 0)
- {
- // this should never happen
-#if 0
- btAssert(0);
-#endif
- }
-
- vTwistAxis = btVector3(qMinTwist.x(), qMinTwist.y(), qMinTwist.z());
- if (twistAngle > SIMD_EPSILON)
- vTwistAxis.normalize();
-}
-
-void btConeTwistConstraint::adjustSwingAxisToUseEllipseNormal(btVector3& vSwingAxis) const
-{
- // the swing axis is computed as the "twist-free" cone rotation,
- // but the cone limit is not circular, but elliptical (if swingspan1 != swingspan2).
- // so, if we're outside the limits, the closest way back inside the cone isn't
- // along the vector back to the center. better (and more stable) to use the ellipse normal.
-
- // convert swing axis to direction from center to surface of ellipse
- // (ie. rotate 2D vector by PI/2)
- btScalar y = -vSwingAxis.z();
- btScalar z = vSwingAxis.y();
-
- // do the math...
- if (fabs(z) > SIMD_EPSILON) // avoid division by 0. and we don't need an update if z == 0.
- {
- // compute gradient/normal of ellipse surface at current "point"
- btScalar grad = y / z;
- grad *= m_swingSpan2 / m_swingSpan1;
-
- // adjust y/z to represent normal at point (instead of vector to point)
- if (y > 0)
- y = fabs(grad * z);
- else
- y = -fabs(grad * z);
-
- // convert ellipse direction back to swing axis
- vSwingAxis.setZ(-y);
- vSwingAxis.setY(z);
- vSwingAxis.normalize();
- }
-}
-
-void btConeTwistConstraint::setMotorTarget(const btQuaternion& q)
-{
- //btTransform trACur = m_rbA.getCenterOfMassTransform();
- //btTransform trBCur = m_rbB.getCenterOfMassTransform();
- // btTransform trABCur = trBCur.inverse() * trACur;
- // btQuaternion qABCur = trABCur.getRotation();
- // btTransform trConstraintCur = (trBCur * m_rbBFrame).inverse() * (trACur * m_rbAFrame);
- //btQuaternion qConstraintCur = trConstraintCur.getRotation();
-
- btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * q * m_rbAFrame.getRotation();
- setMotorTargetInConstraintSpace(qConstraint);
-}
-
-void btConeTwistConstraint::setMotorTargetInConstraintSpace(const btQuaternion& q)
-{
- m_qTarget = q;
-
- // clamp motor target to within limits
- {
- btScalar softness = 1.f; //m_limitSoftness;
-
- // split into twist and cone
- btVector3 vTwisted = quatRotate(m_qTarget, vTwist);
- btQuaternion qTargetCone = shortestArcQuat(vTwist, vTwisted);
- qTargetCone.normalize();
- btQuaternion qTargetTwist = qTargetCone.inverse() * m_qTarget;
- qTargetTwist.normalize();
-
- // clamp cone
- if (m_swingSpan1 >= btScalar(0.05f) && m_swingSpan2 >= btScalar(0.05f))
- {
- btScalar swingAngle, swingLimit;
- btVector3 swingAxis;
- computeConeLimitInfo(qTargetCone, swingAngle, swingAxis, swingLimit);
-
- if (fabs(swingAngle) > SIMD_EPSILON)
- {
- if (swingAngle > swingLimit * softness)
- swingAngle = swingLimit * softness;
- else if (swingAngle < -swingLimit * softness)
- swingAngle = -swingLimit * softness;
- qTargetCone = btQuaternion(swingAxis, swingAngle);
- }
- }
-
- // clamp twist
- if (m_twistSpan >= btScalar(0.05f))
- {
- btScalar twistAngle;
- btVector3 twistAxis;
- computeTwistLimitInfo(qTargetTwist, twistAngle, twistAxis);
-
- if (fabs(twistAngle) > SIMD_EPSILON)
- {
- // eddy todo: limitSoftness used here???
- if (twistAngle > m_twistSpan * softness)
- twistAngle = m_twistSpan * softness;
- else if (twistAngle < -m_twistSpan * softness)
- twistAngle = -m_twistSpan * softness;
- qTargetTwist = btQuaternion(twistAxis, twistAngle);
- }
- }
-
- m_qTarget = qTargetCone * qTargetTwist;
- }
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void btConeTwistConstraint::setParam(int num, btScalar value, int axis)
-{
- switch (num)
- {
- case BT_CONSTRAINT_ERP:
- case BT_CONSTRAINT_STOP_ERP:
- if ((axis >= 0) && (axis < 3))
- {
- m_linERP = value;
- m_flags |= BT_CONETWIST_FLAGS_LIN_ERP;
- }
- else
- {
- m_biasFactor = value;
- }
- break;
- case BT_CONSTRAINT_CFM:
- case BT_CONSTRAINT_STOP_CFM:
- if ((axis >= 0) && (axis < 3))
- {
- m_linCFM = value;
- m_flags |= BT_CONETWIST_FLAGS_LIN_CFM;
- }
- else
- {
- m_angCFM = value;
- m_flags |= BT_CONETWIST_FLAGS_ANG_CFM;
- }
- break;
- default:
- btAssertConstrParams(0);
- break;
- }
-}
-
-///return the local value of parameter
-btScalar btConeTwistConstraint::getParam(int num, int axis) const
-{
- btScalar retVal = 0;
- switch (num)
- {
- case BT_CONSTRAINT_ERP:
- case BT_CONSTRAINT_STOP_ERP:
- if ((axis >= 0) && (axis < 3))
- {
- btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_ERP);
- retVal = m_linERP;
- }
- else if ((axis >= 3) && (axis < 6))
- {
- retVal = m_biasFactor;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_CFM:
- case BT_CONSTRAINT_STOP_CFM:
- if ((axis >= 0) && (axis < 3))
- {
- btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_LIN_CFM);
- retVal = m_linCFM;
- }
- else if ((axis >= 3) && (axis < 6))
- {
- btAssertConstrParams(m_flags & BT_CONETWIST_FLAGS_ANG_CFM);
- retVal = m_angCFM;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- default:
- btAssertConstrParams(0);
- }
- return retVal;
-}
-
-void btConeTwistConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
-{
- m_rbAFrame = frameA;
- m_rbBFrame = frameB;
- buildJacobian();
- //calculateTransforms();
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
deleted file mode 100644
index 64f44df1cb..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConeTwistConstraint.h
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-btConeTwistConstraint is Copyright (c) 2007 Starbreeze Studios
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-
-Written by: Marcus Hennix
-*/
-
-/*
-Overview:
-
-btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc).
-It is a fixed translation, 3 degree-of-freedom (DOF) rotational "joint".
-It divides the 3 rotational DOFs into swing (movement within a cone) and twist.
-Swing is divided into swing1 and swing2 which can have different limits, giving an elliptical shape.
-(Note: the cone's base isn't flat, so this ellipse is "embedded" on the surface of a sphere.)
-
-In the contraint's frame of reference:
-twist is along the x-axis,
-and swing 1 and 2 are along the z and y axes respectively.
-*/
-
-#ifndef BT_CONETWISTCONSTRAINT_H
-#define BT_CONETWISTCONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btConeTwistConstraintData2 btConeTwistConstraintDoubleData
-#define btConeTwistConstraintDataName "btConeTwistConstraintDoubleData"
-#else
-#define btConeTwistConstraintData2 btConeTwistConstraintData
-#define btConeTwistConstraintDataName "btConeTwistConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-class btRigidBody;
-
-enum btConeTwistFlags
-{
- BT_CONETWIST_FLAGS_LIN_CFM = 1,
- BT_CONETWIST_FLAGS_LIN_ERP = 2,
- BT_CONETWIST_FLAGS_ANG_CFM = 4
-};
-
-///btConeTwistConstraint can be used to simulate ragdoll joints (upper arm, leg etc)
-ATTRIBUTE_ALIGNED16(class)
-btConeTwistConstraint : public btTypedConstraint
-{
-#ifdef IN_PARALLELL_SOLVER
-public:
-#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
-
- btTransform m_rbAFrame;
- btTransform m_rbBFrame;
-
- btScalar m_limitSoftness;
- btScalar m_biasFactor;
- btScalar m_relaxationFactor;
-
- btScalar m_damping;
-
- btScalar m_swingSpan1;
- btScalar m_swingSpan2;
- btScalar m_twistSpan;
-
- btScalar m_fixThresh;
-
- btVector3 m_swingAxis;
- btVector3 m_twistAxis;
-
- btScalar m_kSwing;
- btScalar m_kTwist;
-
- btScalar m_twistLimitSign;
- btScalar m_swingCorrection;
- btScalar m_twistCorrection;
-
- btScalar m_twistAngle;
-
- btScalar m_accSwingLimitImpulse;
- btScalar m_accTwistLimitImpulse;
-
- bool m_angularOnly;
- bool m_solveTwistLimit;
- bool m_solveSwingLimit;
-
- bool m_useSolveConstraintObsolete;
-
- // not yet used...
- btScalar m_swingLimitRatio;
- btScalar m_twistLimitRatio;
- btVector3 m_twistAxisA;
-
- // motor
- bool m_bMotorEnabled;
- bool m_bNormalizedMotorStrength;
- btQuaternion m_qTarget;
- btScalar m_maxMotorImpulse;
- btVector3 m_accMotorImpulse;
-
- // parameters
- int m_flags;
- btScalar m_linCFM;
- btScalar m_linERP;
- btScalar m_angCFM;
-
-protected:
- void init();
-
- void computeConeLimitInfo(const btQuaternion& qCone, // in
- btScalar& swingAngle, btVector3& vSwingAxis, btScalar& swingLimit); // all outs
-
- void computeTwistLimitInfo(const btQuaternion& qTwist, // in
- btScalar& twistAngle, btVector3& vTwistAxis); // all outs
-
- void adjustSwingAxisToUseEllipseNormal(btVector3 & vSwingAxis) const;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btConeTwistConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame);
-
- btConeTwistConstraint(btRigidBody & rbA, const btTransform& rbAFrame);
-
- virtual void buildJacobian();
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- void getInfo1NonVirtual(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
-
- virtual void solveConstraintObsolete(btSolverBody & bodyA, btSolverBody & bodyB, btScalar timeStep);
-
- void updateRHS(btScalar timeStep);
-
- const btRigidBody& getRigidBodyA() const
- {
- return m_rbA;
- }
- const btRigidBody& getRigidBodyB() const
- {
- return m_rbB;
- }
-
- void setAngularOnly(bool angularOnly)
- {
- m_angularOnly = angularOnly;
- }
-
- bool getAngularOnly() const
- {
- return m_angularOnly;
- }
-
- void setLimit(int limitIndex, btScalar limitValue)
- {
- switch (limitIndex)
- {
- case 3:
- {
- m_twistSpan = limitValue;
- break;
- }
- case 4:
- {
- m_swingSpan2 = limitValue;
- break;
- }
- case 5:
- {
- m_swingSpan1 = limitValue;
- break;
- }
- default:
- {
- }
- };
- }
-
- btScalar getLimit(int limitIndex) const
- {
- switch (limitIndex)
- {
- case 3:
- {
- return m_twistSpan;
- break;
- }
- case 4:
- {
- return m_swingSpan2;
- break;
- }
- case 5:
- {
- return m_swingSpan1;
- break;
- }
- default:
- {
- btAssert(0 && "Invalid limitIndex specified for btConeTwistConstraint");
- return 0.0;
- }
- };
- }
-
- // setLimit(), a few notes:
- // _softness:
- // 0->1, recommend ~0.8->1.
- // describes % of limits where movement is free.
- // beyond this softness %, the limit is gradually enforced until the "hard" (1.0) limit is reached.
- // _biasFactor:
- // 0->1?, recommend 0.3 +/-0.3 or so.
- // strength with which constraint resists zeroth order (angular, not angular velocity) limit violation.
- // __relaxationFactor:
- // 0->1, recommend to stay near 1.
- // the lower the value, the less the constraint will fight velocities which violate the angular limits.
- void setLimit(btScalar _swingSpan1, btScalar _swingSpan2, btScalar _twistSpan, btScalar _softness = 1.f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
- {
- m_swingSpan1 = _swingSpan1;
- m_swingSpan2 = _swingSpan2;
- m_twistSpan = _twistSpan;
-
- m_limitSoftness = _softness;
- m_biasFactor = _biasFactor;
- m_relaxationFactor = _relaxationFactor;
- }
-
- const btTransform& getAFrame() const { return m_rbAFrame; };
- const btTransform& getBFrame() const { return m_rbBFrame; };
-
- inline int getSolveTwistLimit()
- {
- return m_solveTwistLimit;
- }
-
- inline int getSolveSwingLimit()
- {
- return m_solveSwingLimit;
- }
-
- inline btScalar getTwistLimitSign()
- {
- return m_twistLimitSign;
- }
-
- void calcAngleInfo();
- void calcAngleInfo2(const btTransform& transA, const btTransform& transB, const btMatrix3x3& invInertiaWorldA, const btMatrix3x3& invInertiaWorldB);
-
- inline btScalar getSwingSpan1() const
- {
- return m_swingSpan1;
- }
- inline btScalar getSwingSpan2() const
- {
- return m_swingSpan2;
- }
- inline btScalar getTwistSpan() const
- {
- return m_twistSpan;
- }
- inline btScalar getLimitSoftness() const
- {
- return m_limitSoftness;
- }
- inline btScalar getBiasFactor() const
- {
- return m_biasFactor;
- }
- inline btScalar getRelaxationFactor() const
- {
- return m_relaxationFactor;
- }
- inline btScalar getTwistAngle() const
- {
- return m_twistAngle;
- }
- bool isPastSwingLimit() { return m_solveSwingLimit; }
-
- btScalar getDamping() const { return m_damping; }
- void setDamping(btScalar damping) { m_damping = damping; }
-
- void enableMotor(bool b) { m_bMotorEnabled = b; }
- bool isMotorEnabled() const { return m_bMotorEnabled; }
- btScalar getMaxMotorImpulse() const { return m_maxMotorImpulse; }
- bool isMaxMotorImpulseNormalized() const { return m_bNormalizedMotorStrength; }
- void setMaxMotorImpulse(btScalar maxMotorImpulse)
- {
- m_maxMotorImpulse = maxMotorImpulse;
- m_bNormalizedMotorStrength = false;
- }
- void setMaxMotorImpulseNormalized(btScalar maxMotorImpulse)
- {
- m_maxMotorImpulse = maxMotorImpulse;
- m_bNormalizedMotorStrength = true;
- }
-
- btScalar getFixThresh() { return m_fixThresh; }
- void setFixThresh(btScalar fixThresh) { m_fixThresh = fixThresh; }
-
- // setMotorTarget:
- // q: the desired rotation of bodyA wrt bodyB.
- // note: if q violates the joint limits, the internal target is clamped to avoid conflicting impulses (very bad for stability)
- // note: don't forget to enableMotor()
- void setMotorTarget(const btQuaternion& q);
- const btQuaternion& getMotorTarget() const { return m_qTarget; }
-
- // same as above, but q is the desired rotation of frameA wrt frameB in constraint space
- void setMotorTargetInConstraintSpace(const btQuaternion& q);
-
- btVector3 GetPointForAngle(btScalar fAngleInRadians, btScalar fLength) const;
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
-
- virtual void setFrames(const btTransform& frameA, const btTransform& frameB);
-
- const btTransform& getFrameOffsetA() const
- {
- return m_rbAFrame;
- }
-
- const btTransform& getFrameOffsetB() const
- {
- return m_rbBFrame;
- }
-
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- int getFlags() const
- {
- return m_flags;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-struct btConeTwistConstraintDoubleData
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame;
- btTransformDoubleData m_rbBFrame;
-
- //limits
- double m_swingSpan1;
- double m_swingSpan2;
- double m_twistSpan;
- double m_limitSoftness;
- double m_biasFactor;
- double m_relaxationFactor;
-
- double m_damping;
-};
-
-#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-///this structure is not used, except for loading pre-2.82 .bullet files
-struct btConeTwistConstraintData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame;
- btTransformFloatData m_rbBFrame;
-
- //limits
- float m_swingSpan1;
- float m_swingSpan2;
- float m_twistSpan;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-
- float m_damping;
-
- char m_pad[4];
-};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-//
-
-SIMD_FORCE_INLINE int btConeTwistConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btConeTwistConstraintData2);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btConeTwistConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btConeTwistConstraintData2* cone = (btConeTwistConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&cone->m_typeConstraintData, serializer);
-
- m_rbAFrame.serialize(cone->m_rbAFrame);
- m_rbBFrame.serialize(cone->m_rbBFrame);
-
- cone->m_swingSpan1 = m_swingSpan1;
- cone->m_swingSpan2 = m_swingSpan2;
- cone->m_twistSpan = m_twistSpan;
- cone->m_limitSoftness = m_limitSoftness;
- cone->m_biasFactor = m_biasFactor;
- cone->m_relaxationFactor = m_relaxationFactor;
- cone->m_damping = m_damping;
-
- return btConeTwistConstraintDataName;
-}
-
-#endif //BT_CONETWISTCONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
deleted file mode 100644
index 68a4a07a1d..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btConstraintSolver.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONSTRAINT_SOLVER_H
-#define BT_CONSTRAINT_SOLVER_H
-
-#include "LinearMath/btScalar.h"
-
-class btPersistentManifold;
-class btRigidBody;
-class btCollisionObject;
-class btTypedConstraint;
-struct btContactSolverInfo;
-struct btBroadphaseProxy;
-class btIDebugDraw;
-class btStackAlloc;
-class btDispatcher;
-/// btConstraintSolver provides solver interface
-
-enum btConstraintSolverType
-{
- BT_SEQUENTIAL_IMPULSE_SOLVER = 1,
- BT_MLCP_SOLVER = 2,
- BT_NNCG_SOLVER = 4,
- BT_MULTIBODY_SOLVER = 8,
- BT_BLOCK_SOLVER = 16,
-};
-
-class btConstraintSolver
-{
-public:
- virtual ~btConstraintSolver() {}
-
- virtual void prepareSolve(int /* numBodies */, int /* numManifolds */) { ; }
-
- ///solve a group of constraints
- virtual btScalar solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, class btIDebugDraw* debugDrawer, btDispatcher* dispatcher) = 0;
-
- virtual void allSolved(const btContactSolverInfo& /* info */, class btIDebugDraw* /* debugDrawer */) { ; }
-
- ///clear internal cached data and reset random seed
- virtual void reset() = 0;
-
- virtual btConstraintSolverType getSolverType() const = 0;
-};
-
-#endif //BT_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
deleted file mode 100644
index 4b22b2fff5..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btContactConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btContactSolverInfo.h"
-#include "LinearMath/btMinMax.h"
-#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-
-btContactConstraint::btContactConstraint(btPersistentManifold* contactManifold, btRigidBody& rbA, btRigidBody& rbB)
- : btTypedConstraint(CONTACT_CONSTRAINT_TYPE, rbA, rbB),
- m_contactManifold(*contactManifold)
-{
-}
-
-btContactConstraint::~btContactConstraint()
-{
-}
-
-void btContactConstraint::setContactManifold(btPersistentManifold* contactManifold)
-{
- m_contactManifold = *contactManifold;
-}
-
-void btContactConstraint::getInfo1(btConstraintInfo1* info)
-{
-}
-
-void btContactConstraint::getInfo2(btConstraintInfo2* info)
-{
-}
-
-void btContactConstraint::buildJacobian()
-{
-}
-
-#include "btContactConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btContactSolverInfo.h"
-#include "LinearMath/btMinMax.h"
-#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-
-//response between two dynamic objects without friction and no restitution, assuming 0 penetration depth
-btScalar resolveSingleCollision(
- btRigidBody* body1,
- btCollisionObject* colObj2,
- const btVector3& contactPositionWorld,
- const btVector3& contactNormalOnB,
- const btContactSolverInfo& solverInfo,
- btScalar distance)
-{
- btRigidBody* body2 = btRigidBody::upcast(colObj2);
-
- const btVector3& normal = contactNormalOnB;
-
- btVector3 rel_pos1 = contactPositionWorld - body1->getWorldTransform().getOrigin();
- btVector3 rel_pos2 = contactPositionWorld - colObj2->getWorldTransform().getOrigin();
-
- btVector3 vel1 = body1->getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = body2 ? body2->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel;
- rel_vel = normal.dot(vel);
-
- btScalar combinedRestitution = 0.f;
- btScalar restitution = combinedRestitution * -rel_vel;
-
- btScalar positionalError = solverInfo.m_erp * -distance / solverInfo.m_timeStep;
- btScalar velocityError = -(1.0f + restitution) * rel_vel; // * damping;
- btScalar denom0 = body1->computeImpulseDenominator(contactPositionWorld, normal);
- btScalar denom1 = body2 ? body2->computeImpulseDenominator(contactPositionWorld, normal) : 0.f;
- btScalar relaxation = 1.f;
- btScalar jacDiagABInv = relaxation / (denom0 + denom1);
-
- btScalar penetrationImpulse = positionalError * jacDiagABInv;
- btScalar velocityImpulse = velocityError * jacDiagABInv;
-
- btScalar normalImpulse = penetrationImpulse + velocityImpulse;
- normalImpulse = 0.f > normalImpulse ? 0.f : normalImpulse;
-
- body1->applyImpulse(normal * (normalImpulse), rel_pos1);
- if (body2)
- body2->applyImpulse(-normal * (normalImpulse), rel_pos2);
-
- return normalImpulse;
-}
-
-//bilateral constraint between two dynamic objects
-void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
- btRigidBody& body2, const btVector3& pos2,
- btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep)
-{
- (void)timeStep;
- (void)distance;
-
- btScalar normalLenSqr = normal.length2();
- btAssert(btFabs(normalLenSqr) < btScalar(1.1));
- if (normalLenSqr > btScalar(1.1))
- {
- impulse = btScalar(0.);
- return;
- }
- btVector3 rel_pos1 = pos1 - body1.getCenterOfMassPosition();
- btVector3 rel_pos2 = pos2 - body2.getCenterOfMassPosition();
- //this jacobian entry could be re-used for all iterations
-
- btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
- btVector3 vel = vel1 - vel2;
-
- btJacobianEntry jac(body1.getCenterOfMassTransform().getBasis().transpose(),
- body2.getCenterOfMassTransform().getBasis().transpose(),
- rel_pos1, rel_pos2, normal, body1.getInvInertiaDiagLocal(), body1.getInvMass(),
- body2.getInvInertiaDiagLocal(), body2.getInvMass());
-
- btScalar jacDiagAB = jac.getDiagonal();
- btScalar jacDiagABInv = btScalar(1.) / jacDiagAB;
-
- btScalar rel_vel = jac.getRelativeVelocity(
- body1.getLinearVelocity(),
- body1.getCenterOfMassTransform().getBasis().transpose() * body1.getAngularVelocity(),
- body2.getLinearVelocity(),
- body2.getCenterOfMassTransform().getBasis().transpose() * body2.getAngularVelocity());
-
- rel_vel = normal.dot(vel);
-
- //todo: move this into proper structure
- btScalar contactDamping = btScalar(0.2);
-
-#ifdef ONLY_USE_LINEAR_MASS
- btScalar massTerm = btScalar(1.) / (body1.getInvMass() + body2.getInvMass());
- impulse = -contactDamping * rel_vel * massTerm;
-#else
- btScalar velocityImpulse = -contactDamping * rel_vel * jacDiagABInv;
- impulse = velocityImpulse;
-#endif
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
deleted file mode 100644
index 255489be99..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactConstraint.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONTACT_CONSTRAINT_H
-#define BT_CONTACT_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-
-///btContactConstraint can be automatically created to solve contact constraints using the unified btTypedConstraint interface
-ATTRIBUTE_ALIGNED16(class)
-btContactConstraint : public btTypedConstraint
-{
-protected:
- btPersistentManifold m_contactManifold;
-
-protected:
- btContactConstraint(btPersistentManifold * contactManifold, btRigidBody & rbA, btRigidBody & rbB);
-
-public:
- void setContactManifold(btPersistentManifold * contactManifold);
-
- btPersistentManifold* getContactManifold()
- {
- return &m_contactManifold;
- }
-
- const btPersistentManifold* getContactManifold() const
- {
- return &m_contactManifold;
- }
-
- virtual ~btContactConstraint();
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- ///obsolete methods
- virtual void buildJacobian();
-};
-
-///very basic collision resolution without friction
-btScalar resolveSingleCollision(btRigidBody* body1, class btCollisionObject* colObj2, const btVector3& contactPositionWorld, const btVector3& contactNormalOnB, const struct btContactSolverInfo& solverInfo, btScalar distance);
-
-///resolveSingleBilateral is an obsolete methods used for vehicle friction between two dynamic objects
-void resolveSingleBilateral(btRigidBody& body1, const btVector3& pos1,
- btRigidBody& body2, const btVector3& pos2,
- btScalar distance, const btVector3& normal, btScalar& impulse, btScalar timeStep);
-
-#endif //BT_CONTACT_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
deleted file mode 100644
index 3316403a87..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btContactSolverInfo.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONTACT_SOLVER_INFO
-#define BT_CONTACT_SOLVER_INFO
-
-#include "LinearMath/btScalar.h"
-
-enum btSolverMode
-{
- SOLVER_RANDMIZE_ORDER = 1,
- SOLVER_FRICTION_SEPARATE = 2,
- SOLVER_USE_WARMSTARTING = 4,
- SOLVER_USE_2_FRICTION_DIRECTIONS = 16,
- SOLVER_ENABLE_FRICTION_DIRECTION_CACHING = 32,
- SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION = 64,
- SOLVER_CACHE_FRIENDLY = 128,
- SOLVER_SIMD = 256,
- SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS = 512,
- SOLVER_ALLOW_ZERO_LENGTH_FRICTION_DIRECTIONS = 1024,
- SOLVER_DISABLE_IMPLICIT_CONE_FRICTION = 2048,
- SOLVER_USE_ARTICULATED_WARMSTARTING = 4096,
-};
-
-struct btContactSolverInfoData
-{
- btScalar m_tau;
- btScalar m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- btScalar m_friction;
- btScalar m_timeStep;
- btScalar m_restitution;
- int m_numIterations;
- btScalar m_maxErrorReduction;
- btScalar m_sor; //successive over-relaxation term
- btScalar m_erp; //error reduction for non-contact constraints
- btScalar m_erp2; //error reduction for contact constraints
- btScalar m_deformable_erp; //error reduction for deformable constraints
- btScalar m_deformable_cfm; //constraint force mixing for deformable constraints
- btScalar m_deformable_maxErrorReduction; // maxErrorReduction for deformable contact
- btScalar m_globalCfm; //constraint force mixing for contacts and non-contacts
- btScalar m_frictionERP; //error reduction for friction constraints
- btScalar m_frictionCFM; //constraint force mixing for friction constraints
-
- int m_splitImpulse;
- btScalar m_splitImpulsePenetrationThreshold;
- btScalar m_splitImpulseTurnErp;
- btScalar m_linearSlop;
- btScalar m_warmstartingFactor;
- btScalar m_articulatedWarmstartingFactor;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- btScalar m_maxGyroscopicForce;
- btScalar m_singleAxisRollingFrictionThreshold;
- btScalar m_leastSquaresResidualThreshold;
- btScalar m_restitutionVelocityThreshold;
- bool m_jointFeedbackInWorldSpace;
- bool m_jointFeedbackInJointFrame;
- int m_reportSolverAnalytics;
- int m_numNonContactInnerIterations;
-};
-
-struct btContactSolverInfo : public btContactSolverInfoData
-{
- inline btContactSolverInfo()
- {
- m_tau = btScalar(0.6);
- m_damping = btScalar(1.0);
- m_friction = btScalar(0.3);
- m_timeStep = btScalar(1.f / 60.f);
- m_restitution = btScalar(0.);
- m_maxErrorReduction = btScalar(20.);
- m_numIterations = 10;
- m_erp = btScalar(0.2);
- m_erp2 = btScalar(0.2);
- m_deformable_erp = btScalar(0.06);
- m_deformable_cfm = btScalar(0.01);
- m_deformable_maxErrorReduction = btScalar(0.1);
- m_globalCfm = btScalar(0.);
- m_frictionERP = btScalar(0.2); //positional friction 'anchors' are disabled by default
- m_frictionCFM = btScalar(0.);
- m_sor = btScalar(1.);
- m_splitImpulse = true;
- m_splitImpulsePenetrationThreshold = -.04f;
- m_splitImpulseTurnErp = 0.1f;
- m_linearSlop = btScalar(0.0);
- m_warmstartingFactor = btScalar(0.85);
- m_articulatedWarmstartingFactor = btScalar(0.85);
- //m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD | SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION|SOLVER_USE_2_FRICTION_DIRECTIONS|SOLVER_ENABLE_FRICTION_DIRECTION_CACHING;// | SOLVER_RANDMIZE_ORDER;
- m_solverMode = SOLVER_USE_WARMSTARTING | SOLVER_SIMD; // | SOLVER_RANDMIZE_ORDER;
- m_restingContactRestitutionThreshold = 2; //unused as of 2.81
- m_minimumSolverBatchSize = 128; //try to combine islands until the amount of constraints reaches this limit
- m_maxGyroscopicForce = 100.f; ///it is only used for 'explicit' version of gyroscopic force
- m_singleAxisRollingFrictionThreshold = 1e30f; ///if the velocity is above this threshold, it will use a single constraint row (axis), otherwise 3 rows.
- m_leastSquaresResidualThreshold = 0.f;
- m_restitutionVelocityThreshold = 0.2f; //if the relative velocity is below this threshold, there is zero restitution
- m_jointFeedbackInWorldSpace = false;
- m_jointFeedbackInJointFrame = false;
- m_reportSolverAnalytics = 0;
- m_numNonContactInnerIterations = 1; // the number of inner iterations for solving motor constraint in a single iteration of the constraint solve
- }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btContactSolverInfoDoubleData
-{
- double m_tau;
- double m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- double m_friction;
- double m_timeStep;
- double m_restitution;
- double m_maxErrorReduction;
- double m_sor;
- double m_erp; //used as Baumgarte factor
- double m_erp2; //used in Split Impulse
- double m_globalCfm; //constraint force mixing
- double m_splitImpulsePenetrationThreshold;
- double m_splitImpulseTurnErp;
- double m_linearSlop;
- double m_warmstartingFactor;
- double m_articulatedWarmstartingFactor;
- double m_maxGyroscopicForce; ///it is only used for 'explicit' version of gyroscopic force
- double m_singleAxisRollingFrictionThreshold;
-
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
- char m_padding[4];
-};
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btContactSolverInfoFloatData
-{
- float m_tau;
- float m_damping; //global non-contact constraint damping, can be locally overridden by constraints during 'getInfo2'.
- float m_friction;
- float m_timeStep;
-
- float m_restitution;
- float m_maxErrorReduction;
- float m_sor;
- float m_erp; //used as Baumgarte factor
-
- float m_erp2; //used in Split Impulse
- float m_globalCfm; //constraint force mixing
- float m_splitImpulsePenetrationThreshold;
- float m_splitImpulseTurnErp;
-
- float m_linearSlop;
- float m_warmstartingFactor;
- float m_articulatedWarmstartingFactor;
- float m_maxGyroscopicForce;
-
- float m_singleAxisRollingFrictionThreshold;
- int m_numIterations;
- int m_solverMode;
- int m_restingContactRestitutionThreshold;
-
- int m_minimumSolverBatchSize;
- int m_splitImpulse;
-
-};
-
-#endif //BT_CONTACT_SOLVER_INFO
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
deleted file mode 100644
index bba102d905..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btFixedConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include <new>
-
-btFixedConstraint::btFixedConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB)
- : btGeneric6DofSpring2Constraint(rbA, rbB, frameInA, frameInB)
-{
- setAngularLowerLimit(btVector3(0, 0, 0));
- setAngularUpperLimit(btVector3(0, 0, 0));
- setLinearLowerLimit(btVector3(0, 0, 0));
- setLinearUpperLimit(btVector3(0, 0, 0));
-}
-
-btFixedConstraint::~btFixedConstraint()
-{
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h
deleted file mode 100644
index 6d474ea81d..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btFixedConstraint.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_FIXED_CONSTRAINT_H
-#define BT_FIXED_CONSTRAINT_H
-
-#include "btGeneric6DofSpring2Constraint.h"
-
-ATTRIBUTE_ALIGNED16(class)
-btFixedConstraint : public btGeneric6DofSpring2Constraint
-{
-public:
- btFixedConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB);
-
- virtual ~btFixedConstraint();
-};
-
-#endif //BT_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
deleted file mode 100644
index 7535c52c05..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// Implemented by Erwin Coumans. The idea for the constraint comes from Dimitris Papavasiliou.
-
-#include "btGearConstraint.h"
-
-btGearConstraint::btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio)
- : btTypedConstraint(GEAR_CONSTRAINT_TYPE, rbA, rbB),
- m_axisInA(axisInA),
- m_axisInB(axisInB),
- m_ratio(ratio)
-{
-}
-
-btGearConstraint::~btGearConstraint()
-{
-}
-
-void btGearConstraint::getInfo1(btConstraintInfo1* info)
-{
- info->m_numConstraintRows = 1;
- info->nub = 1;
-}
-
-void btGearConstraint::getInfo2(btConstraintInfo2* info)
-{
- btVector3 globalAxisA, globalAxisB;
-
- globalAxisA = m_rbA.getWorldTransform().getBasis() * this->m_axisInA;
- globalAxisB = m_rbB.getWorldTransform().getBasis() * this->m_axisInB;
-
- info->m_J1angularAxis[0] = globalAxisA[0];
- info->m_J1angularAxis[1] = globalAxisA[1];
- info->m_J1angularAxis[2] = globalAxisA[2];
-
- info->m_J2angularAxis[0] = m_ratio * globalAxisB[0];
- info->m_J2angularAxis[1] = m_ratio * globalAxisB[1];
- info->m_J2angularAxis[2] = m_ratio * globalAxisB[2];
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h
deleted file mode 100644
index 64b15dfbce..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGearConstraint.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2012 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GEAR_CONSTRAINT_H
-#define BT_GEAR_CONSTRAINT_H
-
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btGearConstraintData btGearConstraintDoubleData
-#define btGearConstraintDataName "btGearConstraintDoubleData"
-#else
-#define btGearConstraintData btGearConstraintFloatData
-#define btGearConstraintDataName "btGearConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-///The btGeatConstraint will couple the angular velocity for two bodies around given local axis and ratio.
-///See Bullet/Demos/ConstraintDemo for an example use.
-class btGearConstraint : public btTypedConstraint
-{
-protected:
- btVector3 m_axisInA;
- btVector3 m_axisInB;
- bool m_useFrameA;
- btScalar m_ratio;
-
-public:
- btGearConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& axisInA, const btVector3& axisInB, btScalar ratio = 1.f);
- virtual ~btGearConstraint();
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1(btConstraintInfo1* info);
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2(btConstraintInfo2* info);
-
- void setAxisA(btVector3& axisA)
- {
- m_axisInA = axisA;
- }
- void setAxisB(btVector3& axisB)
- {
- m_axisInB = axisB;
- }
- void setRatio(btScalar ratio)
- {
- m_ratio = ratio;
- }
- const btVector3& getAxisA() const
- {
- return m_axisInA;
- }
- const btVector3& getAxisB() const
- {
- return m_axisInB;
- }
- btScalar getRatio() const
- {
- return m_ratio;
- }
-
- virtual void setParam(int num, btScalar value, int axis = -1)
- {
- (void)num;
- (void)value;
- (void)axis;
- btAssert(0);
- }
-
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const
- {
- (void)num;
- (void)axis;
- btAssert(0);
- return 0.f;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btGearConstraintFloatData
-{
- btTypedConstraintFloatData m_typeConstraintData;
-
- btVector3FloatData m_axisInA;
- btVector3FloatData m_axisInB;
-
- float m_ratio;
- char m_padding[4];
-};
-
-struct btGearConstraintDoubleData
-{
- btTypedConstraintDoubleData m_typeConstraintData;
-
- btVector3DoubleData m_axisInA;
- btVector3DoubleData m_axisInB;
-
- double m_ratio;
-};
-
-SIMD_FORCE_INLINE int btGearConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btGearConstraintData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGearConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btGearConstraintData* gear = (btGearConstraintData*)dataBuffer;
- btTypedConstraint::serialize(&gear->m_typeConstraintData, serializer);
-
- m_axisInA.serialize(gear->m_axisInA);
- m_axisInB.serialize(gear->m_axisInB);
-
- gear->m_ratio = m_ratio;
-
- // Fill padding with zeros to appease msan.
-#ifndef BT_USE_DOUBLE_PRECISION
- gear->m_padding[0] = 0;
- gear->m_padding[1] = 0;
- gear->m_padding[2] = 0;
- gear->m_padding[3] = 0;
-#endif
-
- return btGearConstraintDataName;
-}
-
-#endif //BT_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
deleted file mode 100644
index 1f54203532..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp
+++ /dev/null
@@ -1,975 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-/*
-2007-09-09
-Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#include "btGeneric6DofConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btTransformUtil.h"
-#include <new>
-
-#define D6_USE_OBSOLETE_METHOD false
-#define D6_USE_FRAME_OFFSET true
-
-btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btTypedConstraint(D6_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_useLinearReferenceFrameA(useLinearReferenceFrameA), m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET), m_flags(0), m_useSolveConstraintObsolete(D6_USE_OBSOLETE_METHOD)
-{
- calculateTransforms();
-}
-
-btGeneric6DofConstraint::btGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
- : btTypedConstraint(D6_CONSTRAINT_TYPE, getFixedBody(), rbB),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameB),
- m_useOffsetForConstraintFrame(D6_USE_FRAME_OFFSET),
- m_flags(0),
- m_useSolveConstraintObsolete(false)
-{
- ///not providing rigidbody A means implicitly using worldspace for body A
- m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
- calculateTransforms();
-}
-
-#define GENERIC_D6_DISABLE_WARMSTARTING 1
-
-btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
-btScalar btGetMatrixElem(const btMatrix3x3& mat, int index)
-{
- int i = index % 3;
- int j = index / 3;
- return mat[i][j];
-}
-
-///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
-bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
-{
- // // rot = cy*cz -cy*sz sy
- // // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
- //
-
- btScalar fi = btGetMatrixElem(mat, 2);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
- xyz[1] = btAsin(btGetMatrixElem(mat, 2));
- xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
- return true;
- }
- else
- {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = -SIMD_HALF_PI;
- xyz[2] = btScalar(0.0);
- return false;
- }
- }
- else
- {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = SIMD_HALF_PI;
- xyz[2] = 0.0;
- }
- return false;
-}
-
-//////////////////////////// btRotationalLimitMotor ////////////////////////////////////
-
-int btRotationalLimitMotor::testLimitValue(btScalar test_value)
-{
- if (m_loLimit > m_hiLimit)
- {
- m_currentLimit = 0; //Free from violation
- return 0;
- }
- if (test_value < m_loLimit)
- {
- m_currentLimit = 1; //low limit violation
- m_currentLimitError = test_value - m_loLimit;
- if (m_currentLimitError > SIMD_PI)
- m_currentLimitError -= SIMD_2_PI;
- else if (m_currentLimitError < -SIMD_PI)
- m_currentLimitError += SIMD_2_PI;
- return 1;
- }
- else if (test_value > m_hiLimit)
- {
- m_currentLimit = 2; //High limit violation
- m_currentLimitError = test_value - m_hiLimit;
- if (m_currentLimitError > SIMD_PI)
- m_currentLimitError -= SIMD_2_PI;
- else if (m_currentLimitError < -SIMD_PI)
- m_currentLimitError += SIMD_2_PI;
- return 2;
- };
-
- m_currentLimit = 0; //Free from violation
- return 0;
-}
-
-btScalar btRotationalLimitMotor::solveAngularLimits(
- btScalar timeStep, btVector3& axis, btScalar jacDiagABInv,
- btRigidBody* body0, btRigidBody* body1)
-{
- if (needApplyTorques() == false) return 0.0f;
-
- btScalar target_velocity = m_targetVelocity;
- btScalar maxMotorForce = m_maxMotorForce;
-
- //current error correction
- if (m_currentLimit != 0)
- {
- target_velocity = -m_stopERP * m_currentLimitError / (timeStep);
- maxMotorForce = m_maxLimitForce;
- }
-
- maxMotorForce *= timeStep;
-
- // current velocity difference
-
- btVector3 angVelA = body0->getAngularVelocity();
- btVector3 angVelB = body1->getAngularVelocity();
-
- btVector3 vel_diff;
- vel_diff = angVelA - angVelB;
-
- btScalar rel_vel = axis.dot(vel_diff);
-
- // correction velocity
- btScalar motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel);
-
- if (motor_relvel < SIMD_EPSILON && motor_relvel > -SIMD_EPSILON)
- {
- return 0.0f; //no need for applying force
- }
-
- // correction impulse
- btScalar unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv;
-
- // clip correction impulse
- btScalar clippedMotorImpulse;
-
- ///@todo: should clip against accumulated impulse
- if (unclippedMotorImpulse > 0.0f)
- {
- clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse;
- }
- else
- {
- clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse;
- }
-
- // sort with accumulated impulses
- btScalar lo = btScalar(-BT_LARGE_FLOAT);
- btScalar hi = btScalar(BT_LARGE_FLOAT);
-
- btScalar oldaccumImpulse = m_accumulatedImpulse;
- btScalar sum = oldaccumImpulse + clippedMotorImpulse;
- m_accumulatedImpulse = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
-
- clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse;
-
- btVector3 motorImp = clippedMotorImpulse * axis;
-
- body0->applyTorqueImpulse(motorImp);
- body1->applyTorqueImpulse(-motorImp);
-
- return clippedMotorImpulse;
-}
-
-//////////////////////////// End btRotationalLimitMotor ////////////////////////////////////
-
-//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
-
-int btTranslationalLimitMotor::testLimitValue(int limitIndex, btScalar test_value)
-{
- btScalar loLimit = m_lowerLimit[limitIndex];
- btScalar hiLimit = m_upperLimit[limitIndex];
- if (loLimit > hiLimit)
- {
- m_currentLimit[limitIndex] = 0; //Free from violation
- m_currentLimitError[limitIndex] = btScalar(0.f);
- return 0;
- }
-
- if (test_value < loLimit)
- {
- m_currentLimit[limitIndex] = 2; //low limit violation
- m_currentLimitError[limitIndex] = test_value - loLimit;
- return 2;
- }
- else if (test_value > hiLimit)
- {
- m_currentLimit[limitIndex] = 1; //High limit violation
- m_currentLimitError[limitIndex] = test_value - hiLimit;
- return 1;
- };
-
- m_currentLimit[limitIndex] = 0; //Free from violation
- m_currentLimitError[limitIndex] = btScalar(0.f);
- return 0;
-}
-
-btScalar btTranslationalLimitMotor::solveLinearAxis(
- btScalar timeStep,
- btScalar jacDiagABInv,
- btRigidBody& body1, const btVector3& pointInA,
- btRigidBody& body2, const btVector3& pointInB,
- int limit_index,
- const btVector3& axis_normal_on_a,
- const btVector3& anchorPos)
-{
- ///find relative velocity
- // btVector3 rel_pos1 = pointInA - body1.getCenterOfMassPosition();
- // btVector3 rel_pos2 = pointInB - body2.getCenterOfMassPosition();
- btVector3 rel_pos1 = anchorPos - body1.getCenterOfMassPosition();
- btVector3 rel_pos2 = anchorPos - body2.getCenterOfMassPosition();
-
- btVector3 vel1 = body1.getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = body2.getVelocityInLocalPoint(rel_pos2);
- btVector3 vel = vel1 - vel2;
-
- btScalar rel_vel = axis_normal_on_a.dot(vel);
-
- /// apply displacement correction
-
- //positional error (zeroth order error)
- btScalar depth = -(pointInA - pointInB).dot(axis_normal_on_a);
- btScalar lo = btScalar(-BT_LARGE_FLOAT);
- btScalar hi = btScalar(BT_LARGE_FLOAT);
-
- btScalar minLimit = m_lowerLimit[limit_index];
- btScalar maxLimit = m_upperLimit[limit_index];
-
- //handle the limits
- if (minLimit < maxLimit)
- {
- {
- if (depth > maxLimit)
- {
- depth -= maxLimit;
- lo = btScalar(0.);
- }
- else
- {
- if (depth < minLimit)
- {
- depth -= minLimit;
- hi = btScalar(0.);
- }
- else
- {
- return 0.0f;
- }
- }
- }
- }
-
- btScalar normalImpulse = m_limitSoftness * (m_restitution * depth / timeStep - m_damping * rel_vel) * jacDiagABInv;
-
- btScalar oldNormalImpulse = m_accumulatedImpulse[limit_index];
- btScalar sum = oldNormalImpulse + normalImpulse;
- m_accumulatedImpulse[limit_index] = sum > hi ? btScalar(0.) : sum < lo ? btScalar(0.) : sum;
- normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse;
-
- btVector3 impulse_vector = axis_normal_on_a * normalImpulse;
- body1.applyImpulse(impulse_vector, rel_pos1);
- body2.applyImpulse(-impulse_vector, rel_pos2);
-
- return normalImpulse;
-}
-
-//////////////////////////// btTranslationalLimitMotor ////////////////////////////////////
-
-void btGeneric6DofConstraint::calculateAngleInfo()
-{
- btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
- matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
- // in euler angle mode we do not actually constrain the angular velocity
- // along the axes axis[0] and axis[2] (although we do use axis[1]) :
- //
- // to get constrain w2-w1 along ...not
- // ------ --------------------- ------
- // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
- // d(angle[1])/dt = 0 ax[1]
- // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
- //
- // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
- // to prove the result for angle[0], write the expression for angle[0] from
- // GetInfo1 then take the derivative. to prove this for angle[2] it is
- // easier to take the euler rate expression for d(angle[2])/dt with respect
- // to the components of w and set that to 0.
- btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
- btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
-
- m_calculatedAxis[1] = axis2.cross(axis0);
- m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
- m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
-
- m_calculatedAxis[0].normalize();
- m_calculatedAxis[1].normalize();
- m_calculatedAxis[2].normalize();
-}
-
-void btGeneric6DofConstraint::calculateTransforms()
-{
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-}
-
-void btGeneric6DofConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
-{
- m_calculatedTransformA = transA * m_frameInA;
- m_calculatedTransformB = transB * m_frameInB;
- calculateLinearInfo();
- calculateAngleInfo();
- if (m_useOffsetForConstraintFrame)
- { // get weight factors depending on masses
- btScalar miA = getRigidBodyA().getInvMass();
- btScalar miB = getRigidBodyB().getInvMass();
- m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
- btScalar miS = miA + miB;
- if (miS > btScalar(0.f))
- {
- m_factA = miB / miS;
- }
- else
- {
- m_factA = btScalar(0.5f);
- }
- m_factB = btScalar(1.0f) - m_factA;
- }
-}
-
-void btGeneric6DofConstraint::buildLinearJacobian(
- btJacobianEntry& jacLinear, const btVector3& normalWorld,
- const btVector3& pivotAInW, const btVector3& pivotBInW)
-{
- new (&jacLinear) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normalWorld,
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
-}
-
-void btGeneric6DofConstraint::buildAngularJacobian(
- btJacobianEntry& jacAngular, const btVector3& jointAxisW)
-{
- new (&jacAngular) btJacobianEntry(jointAxisW,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-}
-
-bool btGeneric6DofConstraint::testAngularLimitMotor(int axis_index)
-{
- btScalar angle = m_calculatedAxisAngleDiff[axis_index];
- angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
- m_angularLimits[axis_index].m_currentPosition = angle;
- //test limits
- m_angularLimits[axis_index].testLimitValue(angle);
- return m_angularLimits[axis_index].needApplyTorques();
-}
-
-void btGeneric6DofConstraint::buildJacobian()
-{
-#ifndef __SPU__
- if (m_useSolveConstraintObsolete)
- {
- // Clear accumulated impulses for the next simulation step
- m_linearLimits.m_accumulatedImpulse.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- int i;
- for (i = 0; i < 3; i++)
- {
- m_angularLimits[i].m_accumulatedImpulse = btScalar(0.);
- }
- //calculates transform
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-
- // const btVector3& pivotAInW = m_calculatedTransformA.getOrigin();
- // const btVector3& pivotBInW = m_calculatedTransformB.getOrigin();
- calcAnchorPos();
- btVector3 pivotAInW = m_AnchorPos;
- btVector3 pivotBInW = m_AnchorPos;
-
- // not used here
- // btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
- // btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
-
- btVector3 normalWorld;
- //linear part
- for (i = 0; i < 3; i++)
- {
- if (m_linearLimits.isLimited(i))
- {
- if (m_useLinearReferenceFrameA)
- normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
- else
- normalWorld = m_calculatedTransformB.getBasis().getColumn(i);
-
- buildLinearJacobian(
- m_jacLinear[i], normalWorld,
- pivotAInW, pivotBInW);
- }
- }
-
- // angular part
- for (i = 0; i < 3; i++)
- {
- //calculates error angle
- if (testAngularLimitMotor(i))
- {
- normalWorld = this->getAxis(i);
- // Create angular atom
- buildAngularJacobian(m_jacAng[i], normalWorld);
- }
- }
- }
-#endif //__SPU__
-}
-
-void btGeneric6DofConstraint::getInfo1(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- //prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- info->m_numConstraintRows = 0;
- info->nub = 6;
- int i;
- //test linear limits
- for (i = 0; i < 3; i++)
- {
- if (m_linearLimits.needApplyForce(i))
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
- //test angular limits
- for (i = 0; i < 3; i++)
- {
- if (testAngularLimitMotor(i))
- {
- info->m_numConstraintRows++;
- info->nub--;
- }
- }
- }
-}
-
-void btGeneric6DofConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- //pre-allocate all 6
- info->m_numConstraintRows = 6;
- info->nub = 0;
- }
-}
-
-void btGeneric6DofConstraint::getInfo2(btConstraintInfo2* info)
-{
- btAssert(!m_useSolveConstraintObsolete);
-
- const btTransform& transA = m_rbA.getCenterOfMassTransform();
- const btTransform& transB = m_rbB.getCenterOfMassTransform();
- const btVector3& linVelA = m_rbA.getLinearVelocity();
- const btVector3& linVelB = m_rbB.getLinearVelocity();
- const btVector3& angVelA = m_rbA.getAngularVelocity();
- const btVector3& angVelB = m_rbB.getAngularVelocity();
-
- if (m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
- else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
-}
-
-void btGeneric6DofConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
-{
- btAssert(!m_useSolveConstraintObsolete);
- //prepare constraint
- calculateTransforms(transA, transB);
-
- int i;
- for (i = 0; i < 3; i++)
- {
- testAngularLimitMotor(i);
- }
-
- if (m_useOffsetForConstraintFrame)
- { // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
- else
- { // leave old version for compatibility
- int row = setLinearLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setAngularLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
- }
-}
-
-int btGeneric6DofConstraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
-{
- // int row = 0;
- //solve linear limits
- btRotationalLimitMotor limot;
- for (int i = 0; i < 3; i++)
- {
- if (m_linearLimits.needApplyForce(i))
- { // re-use rotational motor code
- limot.m_bounce = btScalar(0.f);
- limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
- limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_damping = m_linearLimits.m_damping;
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_limitSoftness = m_linearLimits.m_limitSoftness;
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxLimitForce = btScalar(0.f);
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
- btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
- int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT);
- limot.m_normalCFM = (flags & BT_6DOF_FLAGS_CFM_NORM) ? m_linearLimits.m_normalCFM[i] : info->cfm[0];
- limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP) ? m_linearLimits.m_stopERP[i] : info->erp;
- if (m_useOffsetForConstraintFrame)
- {
- int indx1 = (i + 1) % 3;
- int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis
- if (m_angularLimits[indx1].m_currentLimit && m_angularLimits[indx2].m_currentLimit)
- {
- rotAllowed = 0;
- }
- row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
- }
- else
- {
- row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0);
- }
- }
- }
- return row;
-}
-
-int btGeneric6DofConstraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
-{
- btGeneric6DofConstraint* d6constraint = this;
- int row = row_offset;
- //solve angular limits
- for (int i = 0; i < 3; i++)
- {
- if (d6constraint->getRotationalLimitMotor(i)->needApplyTorques())
- {
- btVector3 axis = d6constraint->getAxis(i);
- int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT);
- if (!(flags & BT_6DOF_FLAGS_CFM_NORM))
- {
- m_angularLimits[i].m_normalCFM = info->cfm[0];
- }
- if (!(flags & BT_6DOF_FLAGS_CFM_STOP))
- {
- m_angularLimits[i].m_stopCFM = info->cfm[0];
- }
- if (!(flags & BT_6DOF_FLAGS_ERP_STOP))
- {
- m_angularLimits[i].m_stopERP = info->erp;
- }
- row += get_limit_motor_info2(d6constraint->getRotationalLimitMotor(i),
- transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
- }
- }
-
- return row;
-}
-
-void btGeneric6DofConstraint::updateRHS(btScalar timeStep)
-{
- (void)timeStep;
-}
-
-void btGeneric6DofConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
-{
- m_frameInA = frameA;
- m_frameInB = frameB;
- buildJacobian();
- calculateTransforms();
-}
-
-btVector3 btGeneric6DofConstraint::getAxis(int axis_index) const
-{
- return m_calculatedAxis[axis_index];
-}
-
-btScalar btGeneric6DofConstraint::getRelativePivotPosition(int axisIndex) const
-{
- return m_calculatedLinearDiff[axisIndex];
-}
-
-btScalar btGeneric6DofConstraint::getAngle(int axisIndex) const
-{
- return m_calculatedAxisAngleDiff[axisIndex];
-}
-
-void btGeneric6DofConstraint::calcAnchorPos(void)
-{
- btScalar imA = m_rbA.getInvMass();
- btScalar imB = m_rbB.getInvMass();
- btScalar weight;
- if (imB == btScalar(0.0))
- {
- weight = btScalar(1.0);
- }
- else
- {
- weight = imA / (imA + imB);
- }
- const btVector3& pA = m_calculatedTransformA.getOrigin();
- const btVector3& pB = m_calculatedTransformB.getOrigin();
- m_AnchorPos = pA * weight + pB * (btScalar(1.0) - weight);
- return;
-}
-
-void btGeneric6DofConstraint::calculateLinearInfo()
-{
- m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
- m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for (int i = 0; i < 3; i++)
- {
- m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
- m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
- }
-}
-
-int btGeneric6DofConstraint::get_limit_motor_info2(
- btRotationalLimitMotor* limot,
- const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
- btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
-{
- int srow = row * info->rowskip;
- bool powered = limot->m_enableMotor;
- int limit = limot->m_currentLimit;
- if (powered || limit)
- { // if the joint is powered, or has joint limits, add in the extra row
- btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
- J1[srow + 0] = ax1[0];
- J1[srow + 1] = ax1[1];
- J1[srow + 2] = ax1[2];
-
- J2[srow + 0] = -ax1[0];
- J2[srow + 1] = -ax1[1];
- J2[srow + 2] = -ax1[2];
-
- if ((!rotational))
- {
- if (m_useOffsetForConstraintFrame)
- {
- btVector3 tmpA, tmpB, relA, relB;
- // get vector from bodyB to frameB in WCS
- relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
- // get its projection to constraint axis
- btVector3 projB = ax1 * relB.dot(ax1);
- // get vector directed from bodyB to constraint axis (and orthogonal to it)
- btVector3 orthoB = relB - projB;
- // same for bodyA
- relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
- btVector3 projA = ax1 * relA.dot(ax1);
- btVector3 orthoA = relA - projA;
- // get desired offset between frames A and B along constraint axis
- btScalar desiredOffs = limot->m_currentPosition - limot->m_currentLimitError;
- // desired vector from projection of center of bodyA to projection of center of bodyB to constraint axis
- btVector3 totalDist = projA + ax1 * desiredOffs - projB;
- // get offset vectors relA and relB
- relA = orthoA + totalDist * m_factA;
- relB = orthoB - totalDist * m_factB;
- tmpA = relA.cross(ax1);
- tmpB = relB.cross(ax1);
- if (m_hasStaticBody && (!rotAllowed))
- {
- tmpA *= m_factA;
- tmpB *= m_factB;
- }
- int i;
- for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
- }
- else
- {
- btVector3 ltd; // Linear Torque Decoupling vector
- btVector3 c = m_calculatedTransformB.getOrigin() - transA.getOrigin();
- ltd = c.cross(ax1);
- info->m_J1angularAxis[srow + 0] = ltd[0];
- info->m_J1angularAxis[srow + 1] = ltd[1];
- info->m_J1angularAxis[srow + 2] = ltd[2];
-
- c = m_calculatedTransformB.getOrigin() - transB.getOrigin();
- ltd = -c.cross(ax1);
- info->m_J2angularAxis[srow + 0] = ltd[0];
- info->m_J2angularAxis[srow + 1] = ltd[1];
- info->m_J2angularAxis[srow + 2] = ltd[2];
- }
- }
- // if we're limited low and high simultaneously, the joint motor is
- // ineffective
- if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = false;
- info->m_constraintError[srow] = btScalar(0.f);
- if (powered)
- {
- info->cfm[srow] = limot->m_normalCFM;
- if (!limit)
- {
- btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
-
- btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_stopERP);
- info->m_constraintError[srow] += mot_fact * limot->m_targetVelocity;
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- }
- }
- if (limit)
- {
- btScalar k = info->fps * limot->m_stopERP;
- if (!rotational)
- {
- info->m_constraintError[srow] += k * limot->m_currentLimitError;
- }
- else
- {
- info->m_constraintError[srow] += -k * limot->m_currentLimitError;
- }
- info->cfm[srow] = limot->m_stopCFM;
- if (limot->m_loLimit == limot->m_hiLimit)
- { // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- {
- if (limit == 1)
- {
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- {
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // deal with bounce
- if (limot->m_bounce > 0)
- {
- // calculate joint velocity
- btScalar vel;
- if (rotational)
- {
- vel = angVelA.dot(ax1);
- //make sure that if no body -> angVelB == zero vec
- // if (body1)
- vel -= angVelB.dot(ax1);
- }
- else
- {
- vel = linVelA.dot(ax1);
- //make sure that if no body -> angVelB == zero vec
- // if (body1)
- vel -= linVelB.dot(ax1);
- }
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- {
- if (vel < 0)
- {
- btScalar newc = -limot->m_bounce * vel;
- if (newc > info->m_constraintError[srow])
- info->m_constraintError[srow] = newc;
- }
- }
- else
- {
- if (vel > 0)
- {
- btScalar newc = -limot->m_bounce * vel;
- if (newc < info->m_constraintError[srow])
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- }
- return 1;
- }
- else
- return 0;
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void btGeneric6DofConstraint::setParam(int num, btScalar value, int axis)
-{
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- m_linearLimits.m_stopERP[axis] = value;
- m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case BT_CONSTRAINT_STOP_CFM:
- m_linearLimits.m_stopCFM[axis] = value;
- m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case BT_CONSTRAINT_CFM:
- m_linearLimits.m_normalCFM[axis] = value;
- m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- m_angularLimits[axis - 3].m_stopERP = value;
- m_flags |= BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case BT_CONSTRAINT_STOP_CFM:
- m_angularLimits[axis - 3].m_stopCFM = value;
- m_flags |= BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- case BT_CONSTRAINT_CFM:
- m_angularLimits[axis - 3].m_normalCFM = value;
- m_flags |= BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT);
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
-}
-
-///return the local value of parameter
-btScalar btGeneric6DofConstraint::getParam(int num, int axis) const
-{
- btScalar retVal = 0;
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_stopERP[axis];
- break;
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_stopCFM[axis];
- break;
- case BT_CONSTRAINT_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_linearLimits.m_normalCFM[axis];
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_stopERP;
- break;
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_stopCFM;
- break;
- case BT_CONSTRAINT_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_NORM << (axis * BT_6DOF_FLAGS_AXIS_SHIFT)));
- retVal = m_angularLimits[axis - 3].m_normalCFM;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
- return retVal;
-}
-
-void btGeneric6DofConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
-{
- btVector3 zAxis = axis1.normalized();
- btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
- // now get constraint frame in local coordinate systems
- m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
- calculateTransforms();
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
deleted file mode 100644
index b9e762e175..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
-/// Added support for generic constraint solver through getInfo1/getInfo2 methods
-
-/*
-2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#ifndef BT_GENERIC_6DOF_CONSTRAINT_H
-#define BT_GENERIC_6DOF_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-class btRigidBody;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofConstraintData2 btGeneric6DofConstraintDoubleData2
-#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintDoubleData2"
-#else
-#define btGeneric6DofConstraintData2 btGeneric6DofConstraintData
-#define btGeneric6DofConstraintDataName "btGeneric6DofConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-//! Rotation Limit structure for generic joints
-class btRotationalLimitMotor
-{
-public:
- //! limit_parameters
- //!@{
- btScalar m_loLimit; //!< joint limit
- btScalar m_hiLimit; //!< joint limit
- btScalar m_targetVelocity; //!< target motor velocity
- btScalar m_maxMotorForce; //!< max force on motor
- btScalar m_maxLimitForce; //!< max force on limit
- btScalar m_damping; //!< Damping.
- btScalar m_limitSoftness; //! Relaxation factor
- btScalar m_normalCFM; //!< Constraint force mixing factor
- btScalar m_stopERP; //!< Error tolerance factor when joint is at limit
- btScalar m_stopCFM; //!< Constraint force mixing factor when joint is at limit
- btScalar m_bounce; //!< restitution factor
- bool m_enableMotor;
-
- //!@}
-
- //! temp_variables
- //!@{
- btScalar m_currentLimitError; //! How much is violated this limit
- btScalar m_currentPosition; //! current value of angle
- int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit
- btScalar m_accumulatedImpulse;
- //!@}
-
- btRotationalLimitMotor()
- {
- m_accumulatedImpulse = 0.f;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_maxLimitForce = 300.0f;
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
- m_normalCFM = 0.f;
- m_stopERP = 0.2f;
- m_stopCFM = 0.f;
- m_bounce = 0.0f;
- m_damping = 1.0f;
- m_limitSoftness = 0.5f;
- m_currentLimit = 0;
- m_currentLimitError = 0;
- m_enableMotor = false;
- }
-
- btRotationalLimitMotor(const btRotationalLimitMotor& limot)
- {
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_limitSoftness = limot.m_limitSoftness;
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
- m_normalCFM = limot.m_normalCFM;
- m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_bounce = limot.m_bounce;
- m_currentLimit = limot.m_currentLimit;
- m_currentLimitError = limot.m_currentLimitError;
- m_enableMotor = limot.m_enableMotor;
- }
-
- //! Is limited
- bool isLimited() const
- {
- if (m_loLimit > m_hiLimit) return false;
- return true;
- }
-
- //! Need apply correction
- bool needApplyTorques() const
- {
- if (m_currentLimit == 0 && m_enableMotor == false) return false;
- return true;
- }
-
- //! calculates error
- /*!
- calculates m_currentLimit and m_currentLimitError.
- */
- int testLimitValue(btScalar test_value);
-
- //! apply the correction impulses for two bodies
- btScalar solveAngularLimits(btScalar timeStep, btVector3& axis, btScalar jacDiagABInv, btRigidBody* body0, btRigidBody* body1);
-};
-
-class btTranslationalLimitMotor
-{
-public:
- btVector3 m_lowerLimit; //!< the constraint lower limits
- btVector3 m_upperLimit; //!< the constraint upper limits
- btVector3 m_accumulatedImpulse;
- //! Linear_Limit_parameters
- //!@{
- btScalar m_limitSoftness; //!< Softness for linear limit
- btScalar m_damping; //!< Damping for linear limit
- btScalar m_restitution; //! Bounce parameter for linear limit
- btVector3 m_normalCFM; //!< Constraint force mixing factor
- btVector3 m_stopERP; //!< Error tolerance factor when joint is at limit
- btVector3 m_stopCFM; //!< Constraint force mixing factor when joint is at limit
- //!@}
- bool m_enableMotor[3];
- btVector3 m_targetVelocity; //!< target motor velocity
- btVector3 m_maxMotorForce; //!< max force on motor
- btVector3 m_currentLimitError; //! How much is violated this limit
- btVector3 m_currentLinearDiff; //! Current relative offset of constraint frames
- int m_currentLimit[3]; //!< 0=free, 1=at lower limit, 2=at upper limit
-
- btTranslationalLimitMotor()
- {
- m_lowerLimit.setValue(0.f, 0.f, 0.f);
- m_upperLimit.setValue(0.f, 0.f, 0.f);
- m_accumulatedImpulse.setValue(0.f, 0.f, 0.f);
- m_normalCFM.setValue(0.f, 0.f, 0.f);
- m_stopERP.setValue(0.2f, 0.2f, 0.2f);
- m_stopCFM.setValue(0.f, 0.f, 0.f);
-
- m_limitSoftness = 0.7f;
- m_damping = btScalar(1.0f);
- m_restitution = btScalar(0.5f);
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = false;
- m_targetVelocity[i] = btScalar(0.f);
- m_maxMotorForce[i] = btScalar(0.f);
- }
- }
-
- btTranslationalLimitMotor(const btTranslationalLimitMotor& other)
- {
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_accumulatedImpulse = other.m_accumulatedImpulse;
-
- m_limitSoftness = other.m_limitSoftness;
- m_damping = other.m_damping;
- m_restitution = other.m_restitution;
- m_normalCFM = other.m_normalCFM;
- m_stopERP = other.m_stopERP;
- m_stopCFM = other.m_stopCFM;
-
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = other.m_enableMotor[i];
- m_targetVelocity[i] = other.m_targetVelocity[i];
- m_maxMotorForce[i] = other.m_maxMotorForce[i];
- }
- }
-
- //! Test limit
- /*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
- inline bool isLimited(int limitIndex) const
- {
- return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
- }
- inline bool needApplyForce(int limitIndex) const
- {
- if (m_currentLimit[limitIndex] == 0 && m_enableMotor[limitIndex] == false) return false;
- return true;
- }
- int testLimitValue(int limitIndex, btScalar test_value);
-
- btScalar solveLinearAxis(
- btScalar timeStep,
- btScalar jacDiagABInv,
- btRigidBody& body1, const btVector3& pointInA,
- btRigidBody& body2, const btVector3& pointInB,
- int limit_index,
- const btVector3& axis_normal_on_a,
- const btVector3& anchorPos);
-};
-
-enum bt6DofFlags
-{
- BT_6DOF_FLAGS_CFM_NORM = 1,
- BT_6DOF_FLAGS_CFM_STOP = 2,
- BT_6DOF_FLAGS_ERP_STOP = 4
-};
-#define BT_6DOF_FLAGS_AXIS_SHIFT 3 // bits per axis
-
-/// btGeneric6DofConstraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
-/*!
-btGeneric6DofConstraint can leave any of the 6 degree of freedom 'free' or 'locked'.
-currently this limit supports rotational motors<br>
-<ul>
-<li> For Linear limits, use btGeneric6DofConstraint.setLinearUpperLimit, btGeneric6DofConstraint.setLinearLowerLimit. You can set the parameters with the btTranslationalLimitMotor structure accsesible through the btGeneric6DofConstraint.getTranslationalLimitMotor method.
-At this moment translational motors are not supported. May be in the future. </li>
-
-<li> For Angular limits, use the btRotationalLimitMotor structure for configuring the limit.
-This is accessible through btGeneric6DofConstraint.getLimitMotor method,
-This brings support for limit parameters and motors. </li>
-
-<li> Angulars limits have these possible ranges:
-<table border=1 >
-<tr>
- <td><b>AXIS</b></td>
- <td><b>MIN ANGLE</b></td>
- <td><b>MAX ANGLE</b></td>
-</tr><tr>
- <td>X</td>
- <td>-PI</td>
- <td>PI</td>
-</tr><tr>
- <td>Y</td>
- <td>-PI/2</td>
- <td>PI/2</td>
-</tr><tr>
- <td>Z</td>
- <td>-PI</td>
- <td>PI</td>
-</tr>
-</table>
-</li>
-</ul>
-
-*/
-ATTRIBUTE_ALIGNED16(class)
-btGeneric6DofConstraint : public btTypedConstraint
-{
-protected:
- //! relative_frames
- //!@{
- btTransform m_frameInA; //!< the constraint space w.r.t body A
- btTransform m_frameInB; //!< the constraint space w.r.t body B
- //!@}
-
- //! Jacobians
- //!@{
- btJacobianEntry m_jacLinear[3]; //!< 3 orthogonal linear constraints
- btJacobianEntry m_jacAng[3]; //!< 3 orthogonal angular constraints
- //!@}
-
- //! Linear_Limit_parameters
- //!@{
- btTranslationalLimitMotor m_linearLimits;
- //!@}
-
- //! hinge_parameters
- //!@{
- btRotationalLimitMotor m_angularLimits[3];
- //!@}
-
-protected:
- //! temporal variables
- //!@{
- btScalar m_timeStep;
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
- btVector3 m_calculatedAxisAngleDiff;
- btVector3 m_calculatedAxis[3];
- btVector3 m_calculatedLinearDiff;
- btScalar m_factA;
- btScalar m_factB;
- bool m_hasStaticBody;
-
- btVector3 m_AnchorPos; // point betwen pivots of bodies A and B to solve linear axes
-
- bool m_useLinearReferenceFrameA;
- bool m_useOffsetForConstraintFrame;
-
- int m_flags;
-
- //!@}
-
- btGeneric6DofConstraint& operator=(btGeneric6DofConstraint& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
- int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
-
- int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
-
- void buildLinearJacobian(
- btJacobianEntry & jacLinear, const btVector3& normalWorld,
- const btVector3& pivotAInW, const btVector3& pivotBInW);
-
- void buildAngularJacobian(btJacobianEntry & jacAngular, const btVector3& jointAxisW);
-
- // tests linear limits
- void calculateLinearInfo();
-
- //! calcs the euler angles between the two bodies.
- void calculateAngleInfo();
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
-
- btGeneric6DofConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
- btGeneric6DofConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
-
- //! Calcs global transform of the offsets
- /*!
- Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies.
- \sa btGeneric6DofConstraint.getCalculatedTransformA , btGeneric6DofConstraint.getCalculatedTransformB, btGeneric6DofConstraint.calculateAngleInfo
- */
- void calculateTransforms(const btTransform& transA, const btTransform& transB);
-
- void calculateTransforms();
-
- //! Gets the global transform of the offset for body A
- /*!
- \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
- */
- const btTransform& getCalculatedTransformA() const
- {
- return m_calculatedTransformA;
- }
-
- //! Gets the global transform of the offset for body B
- /*!
- \sa btGeneric6DofConstraint.getFrameOffsetA, btGeneric6DofConstraint.getFrameOffsetB, btGeneric6DofConstraint.calculateAngleInfo.
- */
- const btTransform& getCalculatedTransformB() const
- {
- return m_calculatedTransformB;
- }
-
- const btTransform& getFrameOffsetA() const
- {
- return m_frameInA;
- }
-
- const btTransform& getFrameOffsetB() const
- {
- return m_frameInB;
- }
-
- btTransform& getFrameOffsetA()
- {
- return m_frameInA;
- }
-
- btTransform& getFrameOffsetB()
- {
- return m_frameInB;
- }
-
- //! performs Jacobian calculation, and also calculates angle differences and axis
- virtual void buildJacobian();
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- void getInfo1NonVirtual(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
-
- void updateRHS(btScalar timeStep);
-
- //! Get the rotation axis in global coordinates
- /*!
- \pre btGeneric6DofConstraint.buildJacobian must be called previously.
- */
- btVector3 getAxis(int axis_index) const;
-
- //! Get the relative Euler angle
- /*!
- \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
- */
- btScalar getAngle(int axis_index) const;
-
- //! Get the relative position of the constraint pivot
- /*!
- \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
- */
- btScalar getRelativePivotPosition(int axis_index) const;
-
- void setFrames(const btTransform& frameA, const btTransform& frameB);
-
- //! Test angular limit.
- /*!
- Calculates angular correction and returns true if limit needs to be corrected.
- \pre btGeneric6DofConstraint::calculateTransforms() must be called previously.
- */
- bool testAngularLimitMotor(int axis_index);
-
- void setLinearLowerLimit(const btVector3& linearLower)
- {
- m_linearLimits.m_lowerLimit = linearLower;
- }
-
- void getLinearLowerLimit(btVector3 & linearLower) const
- {
- linearLower = m_linearLimits.m_lowerLimit;
- }
-
- void setLinearUpperLimit(const btVector3& linearUpper)
- {
- m_linearLimits.m_upperLimit = linearUpper;
- }
-
- void getLinearUpperLimit(btVector3 & linearUpper) const
- {
- linearUpper = m_linearLimits.m_upperLimit;
- }
-
- void setAngularLowerLimit(const btVector3& angularLower)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
- }
-
- void getAngularLowerLimit(btVector3 & angularLower) const
- {
- for (int i = 0; i < 3; i++)
- angularLower[i] = m_angularLimits[i].m_loLimit;
- }
-
- void setAngularUpperLimit(const btVector3& angularUpper)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
- }
-
- void getAngularUpperLimit(btVector3 & angularUpper) const
- {
- for (int i = 0; i < 3; i++)
- angularUpper[i] = m_angularLimits[i].m_hiLimit;
- }
-
- //! Retrieves the angular limit informacion
- btRotationalLimitMotor* getRotationalLimitMotor(int index)
- {
- return &m_angularLimits[index];
- }
-
- //! Retrieves the limit informacion
- btTranslationalLimitMotor* getTranslationalLimitMotor()
- {
- return &m_linearLimits;
- }
-
- //first 3 are linear, next 3 are angular
- void setLimit(int axis, btScalar lo, btScalar hi)
- {
- if (axis < 3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
- lo = btNormalizeAngle(lo);
- hi = btNormalizeAngle(hi);
- m_angularLimits[axis - 3].m_loLimit = lo;
- m_angularLimits[axis - 3].m_hiLimit = hi;
- }
- }
-
- //! Test limit
- /*!
- - free means upper < lower,
- - locked means upper == lower
- - limited means upper > lower
- - limitIndex: first 3 are linear, next 3 are angular
- */
- bool isLimited(int limitIndex) const
- {
- if (limitIndex < 3)
- {
- return m_linearLimits.isLimited(limitIndex);
- }
- return m_angularLimits[limitIndex - 3].isLimited();
- }
-
- virtual void calcAnchorPos(void); // overridable
-
- int get_limit_motor_info2(btRotationalLimitMotor * limot,
- const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
- btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
-
- // access for UseFrameOffset
- bool getUseFrameOffset() const { return m_useOffsetForConstraintFrame; }
- void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
-
- bool getUseLinearReferenceFrameA() const { return m_useLinearReferenceFrameA; }
- void setUseLinearReferenceFrameA(bool linearReferenceFrameA) { m_useLinearReferenceFrameA = linearReferenceFrameA; }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- void setAxis(const btVector3& axis1, const btVector3& axis2);
-
- virtual int getFlags() const
- {
- return m_flags;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-struct btGeneric6DofConstraintData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformFloatData m_rbBFrame;
-
- btVector3FloatData m_linearUpperLimit;
- btVector3FloatData m_linearLowerLimit;
-
- btVector3FloatData m_angularUpperLimit;
- btVector3FloatData m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-struct btGeneric6DofConstraintDoubleData2
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformDoubleData m_rbBFrame;
-
- btVector3DoubleData m_linearUpperLimit;
- btVector3DoubleData m_linearLowerLimit;
-
- btVector3DoubleData m_angularUpperLimit;
- btVector3DoubleData m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-SIMD_FORCE_INLINE int btGeneric6DofConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btGeneric6DofConstraintData2);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGeneric6DofConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btGeneric6DofConstraintData2* dof = (btGeneric6DofConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
-
- m_frameInA.serialize(dof->m_rbAFrame);
- m_frameInB.serialize(dof->m_rbBFrame);
-
- int i;
- for (i = 0; i < 3; i++)
- {
- dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
- dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
- dof->m_linearLowerLimit.m_floats[i] = m_linearLimits.m_lowerLimit[i];
- dof->m_linearUpperLimit.m_floats[i] = m_linearLimits.m_upperLimit[i];
- }
-
- dof->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA ? 1 : 0;
- dof->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame ? 1 : 0;
-
- return btGeneric6DofConstraintDataName;
-}
-
-#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
deleted file mode 100644
index 74a13c6249..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp
+++ /dev/null
@@ -1,1243 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
-Pros:
-- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
-- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
-- Servo motor functionality
-- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
-- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
-
-Cons:
-- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation. (with PGS)
-- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
-*/
-
-/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
-/// Added support for generic constraint solver through getInfo1/getInfo2 methods
-
-/*
-2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#include "btGeneric6DofSpring2Constraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include <cmath>
-#include <new>
-
-btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder)
- : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, rbA, rbB), m_frameInA(frameInA), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
-{
- calculateTransforms();
-}
-
-btGeneric6DofSpring2Constraint::btGeneric6DofSpring2Constraint(btRigidBody& rbB, const btTransform& frameInB, RotateOrder rotOrder)
- : btTypedConstraint(D6_SPRING_2_CONSTRAINT_TYPE, getFixedBody(), rbB), m_frameInB(frameInB), m_rotateOrder(rotOrder), m_flags(0)
-{
- ///not providing rigidbody A means implicitly using worldspace for body A
- m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
- calculateTransforms();
-}
-
-btScalar btGeneric6DofSpring2Constraint::btGetMatrixElem(const btMatrix3x3& mat, int index)
-{
- int i = index % 3;
- int j = index / 3;
- return mat[i][j];
-}
-
-// MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cy*cz -cy*sz sy
- // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-
- btScalar fi = btGetMatrixElem(mat, 2);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 8));
- xyz[1] = btAsin(btGetMatrixElem(mat, 2));
- xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
- return true;
- }
- else
- {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = -SIMD_HALF_PI;
- xyz[2] = btScalar(0.0);
- return false;
- }
- }
- else
- {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- xyz[1] = SIMD_HALF_PI;
- xyz[2] = 0.0;
- }
- return false;
-}
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cy*cz -sz sy*cz
- // cy*cx*sz+sx*sy cx*cz sy*cx*sz-cy*sx
- // cy*sx*sz-cx*sy sx*cz sy*sx*sz+cx*cy
-
- btScalar fi = btGetMatrixElem(mat, 1);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 4));
- xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
- xyz[2] = btAsin(-btGetMatrixElem(mat, 1));
- return true;
- }
- else
- {
- xyz[0] = -btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
- xyz[1] = btScalar(0.0);
- xyz[2] = SIMD_HALF_PI;
- return false;
- }
- }
- else
- {
- xyz[0] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
- xyz[1] = 0.0;
- xyz[2] = -SIMD_HALF_PI;
- }
- return false;
-}
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cy*cz+sy*sx*sz cz*sy*sx-cy*sz cx*sy
- // cx*sz cx*cz -sx
- // cy*sx*sz-cz*sy sy*sz+cy*cz*sx cy*cx
-
- btScalar fi = btGetMatrixElem(mat, 5);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAsin(-btGetMatrixElem(mat, 5));
- xyz[1] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 8));
- xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 4));
- return true;
- }
- else
- {
- xyz[0] = SIMD_HALF_PI;
- xyz[1] = -btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
- xyz[2] = btScalar(0.0);
- return false;
- }
- }
- else
- {
- xyz[0] = -SIMD_HALF_PI;
- xyz[1] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 0));
- xyz[2] = 0.0;
- }
- return false;
-}
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cy*cz sy*sx-cy*cx*sz cx*sy+cy*sz*sx
- // sz cz*cx -cz*sx
- // -cz*sy cy*sx+cx*sy*sz cy*cx-sy*sz*sx
-
- btScalar fi = btGetMatrixElem(mat, 3);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAtan2(-btGetMatrixElem(mat, 5), btGetMatrixElem(mat, 4));
- xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 0));
- xyz[2] = btAsin(btGetMatrixElem(mat, 3));
- return true;
- }
- else
- {
- xyz[0] = btScalar(0.0);
- xyz[1] = -btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
- xyz[2] = -SIMD_HALF_PI;
- return false;
- }
- }
- else
- {
- xyz[0] = btScalar(0.0);
- xyz[1] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
- xyz[2] = SIMD_HALF_PI;
- }
- return false;
-}
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cz*cy-sz*sx*sy -cx*sz cz*sy+cy*sz*sx
- // cy*sz+cz*sx*sy cz*cx sz*sy-cz*xy*sx
- // -cx*sy sx cx*cy
-
- btScalar fi = btGetMatrixElem(mat, 7);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAsin(btGetMatrixElem(mat, 7));
- xyz[1] = btAtan2(-btGetMatrixElem(mat, 6), btGetMatrixElem(mat, 8));
- xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 4));
- return true;
- }
- else
- {
- xyz[0] = -SIMD_HALF_PI;
- xyz[1] = btScalar(0.0);
- xyz[2] = -btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
- return false;
- }
- }
- else
- {
- xyz[0] = SIMD_HALF_PI;
- xyz[1] = btScalar(0.0);
- xyz[2] = btAtan2(btGetMatrixElem(mat, 2), btGetMatrixElem(mat, 0));
- }
- return false;
-}
-
-bool btGeneric6DofSpring2Constraint::matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz)
-{
- // rot = cz*cy cz*sy*sx-cx*sz sz*sx+cz*cx*sy
- // cy*sz cz*cx+sz*sy*sx cx*sz*sy-cz*sx
- // -sy cy*sx cy*cx
-
- btScalar fi = btGetMatrixElem(mat, 6);
- if (fi < btScalar(1.0f))
- {
- if (fi > btScalar(-1.0f))
- {
- xyz[0] = btAtan2(btGetMatrixElem(mat, 7), btGetMatrixElem(mat, 8));
- xyz[1] = btAsin(-btGetMatrixElem(mat, 6));
- xyz[2] = btAtan2(btGetMatrixElem(mat, 3), btGetMatrixElem(mat, 0));
- return true;
- }
- else
- {
- xyz[0] = btScalar(0.0);
- xyz[1] = SIMD_HALF_PI;
- xyz[2] = -btAtan2(btGetMatrixElem(mat, 1), btGetMatrixElem(mat, 2));
- return false;
- }
- }
- else
- {
- xyz[0] = btScalar(0.0);
- xyz[1] = -SIMD_HALF_PI;
- xyz[2] = btAtan2(-btGetMatrixElem(mat, 1), -btGetMatrixElem(mat, 2));
- }
- return false;
-}
-
-void btGeneric6DofSpring2Constraint::calculateAngleInfo()
-{
- btMatrix3x3 relative_frame = m_calculatedTransformA.getBasis().inverse() * m_calculatedTransformB.getBasis();
- switch (m_rotateOrder)
- {
- case RO_XYZ:
- matrixToEulerXYZ(relative_frame, m_calculatedAxisAngleDiff);
- break;
- case RO_XZY:
- matrixToEulerXZY(relative_frame, m_calculatedAxisAngleDiff);
- break;
- case RO_YXZ:
- matrixToEulerYXZ(relative_frame, m_calculatedAxisAngleDiff);
- break;
- case RO_YZX:
- matrixToEulerYZX(relative_frame, m_calculatedAxisAngleDiff);
- break;
- case RO_ZXY:
- matrixToEulerZXY(relative_frame, m_calculatedAxisAngleDiff);
- break;
- case RO_ZYX:
- matrixToEulerZYX(relative_frame, m_calculatedAxisAngleDiff);
- break;
- default:
- btAssert(false);
- }
- // in euler angle mode we do not actually constrain the angular velocity
- // along the axes axis[0] and axis[2] (although we do use axis[1]) :
- //
- // to get constrain w2-w1 along ...not
- // ------ --------------------- ------
- // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0]
- // d(angle[1])/dt = 0 ax[1]
- // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2]
- //
- // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0.
- // to prove the result for angle[0], write the expression for angle[0] from
- // GetInfo1 then take the derivative. to prove this for angle[2] it is
- // easier to take the euler rate expression for d(angle[2])/dt with respect
- // to the components of w and set that to 0.
- switch (m_rotateOrder)
- {
- case RO_XYZ:
- {
- //Is this the "line of nodes" calculation choosing planes YZ (B coordinate system) and xy (A coordinate system)? (http://en.wikipedia.org/wiki/Euler_angles)
- //The two planes are non-homologous, so this is a Tait Bryan angle formalism and not a proper Euler
- //Extrinsic rotations are equal to the reversed order intrinsic rotations so the above xyz extrinsic rotations (axes are fixed) are the same as the zy'x" intrinsic rotations (axes are refreshed after each rotation)
- //that is why xy and YZ planes are chosen (this will describe a zy'x" intrinsic rotation) (see the figure on the left at http://en.wikipedia.org/wiki/Euler_angles under Tait Bryan angles)
- // x' = Nperp = N.cross(axis2)
- // y' = N = axis2.cross(axis0)
- // z' = z
- //
- // x" = X
- // y" = y'
- // z" = ??
- //in other words:
- //first rotate around z
- //second rotate around y'= z.cross(X)
- //third rotate around x" = X
- //Original XYZ extrinsic rotation order.
- //Planes: xy and YZ normals: z, X. Plane intersection (N) is z.cross(X)
- btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
- btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
- m_calculatedAxis[1] = axis2.cross(axis0);
- m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
- m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
- break;
- }
- case RO_XZY:
- {
- //planes: xz,ZY normals: y, X
- //first rotate around y
- //second rotate around z'= y.cross(X)
- //third rotate around x" = X
- btVector3 axis0 = m_calculatedTransformB.getBasis().getColumn(0);
- btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
- m_calculatedAxis[2] = axis0.cross(axis1);
- m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
- m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
- break;
- }
- case RO_YXZ:
- {
- //planes: yx,XZ normals: z, Y
- //first rotate around z
- //second rotate around x'= z.cross(Y)
- //third rotate around y" = Y
- btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
- btVector3 axis2 = m_calculatedTransformA.getBasis().getColumn(2);
- m_calculatedAxis[0] = axis1.cross(axis2);
- m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
- m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
- break;
- }
- case RO_YZX:
- {
- //planes: yz,ZX normals: x, Y
- //first rotate around x
- //second rotate around z'= x.cross(Y)
- //third rotate around y" = Y
- btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
- btVector3 axis1 = m_calculatedTransformB.getBasis().getColumn(1);
- m_calculatedAxis[2] = axis0.cross(axis1);
- m_calculatedAxis[0] = axis1.cross(m_calculatedAxis[2]);
- m_calculatedAxis[1] = m_calculatedAxis[2].cross(axis0);
- break;
- }
- case RO_ZXY:
- {
- //planes: zx,XY normals: y, Z
- //first rotate around y
- //second rotate around x'= y.cross(Z)
- //third rotate around z" = Z
- btVector3 axis1 = m_calculatedTransformA.getBasis().getColumn(1);
- btVector3 axis2 = m_calculatedTransformB.getBasis().getColumn(2);
- m_calculatedAxis[0] = axis1.cross(axis2);
- m_calculatedAxis[1] = axis2.cross(m_calculatedAxis[0]);
- m_calculatedAxis[2] = m_calculatedAxis[0].cross(axis1);
- break;
- }
- case RO_ZYX:
- {
- //planes: zy,YX normals: x, Z
- //first rotate around x
- //second rotate around y' = x.cross(Z)
- //third rotate around z" = Z
- btVector3 axis0 = m_calculatedTransformA.getBasis().getColumn(0);
- btVector3 axis2 = m_calculatedTransformB.getBasis().getColumn(2);
- m_calculatedAxis[1] = axis2.cross(axis0);
- m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2);
- m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
- break;
- }
- default:
- btAssert(false);
- }
-
- m_calculatedAxis[0].normalize();
- m_calculatedAxis[1].normalize();
- m_calculatedAxis[2].normalize();
-}
-
-void btGeneric6DofSpring2Constraint::calculateTransforms()
-{
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-}
-
-void btGeneric6DofSpring2Constraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
-{
- m_calculatedTransformA = transA * m_frameInA;
- m_calculatedTransformB = transB * m_frameInB;
- calculateLinearInfo();
- calculateAngleInfo();
-
- btScalar miA = getRigidBodyA().getInvMass();
- btScalar miB = getRigidBodyB().getInvMass();
- m_hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
- btScalar miS = miA + miB;
- if (miS > btScalar(0.f))
- {
- m_factA = miB / miS;
- }
- else
- {
- m_factA = btScalar(0.5f);
- }
- m_factB = btScalar(1.0f) - m_factA;
-}
-
-void btGeneric6DofSpring2Constraint::testAngularLimitMotor(int axis_index)
-{
- btScalar angle = m_calculatedAxisAngleDiff[axis_index];
- angle = btAdjustAngleToLimits(angle, m_angularLimits[axis_index].m_loLimit, m_angularLimits[axis_index].m_hiLimit);
- m_angularLimits[axis_index].m_currentPosition = angle;
- m_angularLimits[axis_index].testLimitValue(angle);
-}
-
-void btGeneric6DofSpring2Constraint::getInfo1(btConstraintInfo1* info)
-{
- //prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- info->m_numConstraintRows = 0;
- info->nub = 0;
- int i;
- //test linear limits
- for (i = 0; i < 3; i++)
- {
- if (m_linearLimits.m_currentLimit[i] == 4)
- info->m_numConstraintRows += 2;
- else if (m_linearLimits.m_currentLimit[i] != 0)
- info->m_numConstraintRows += 1;
- if (m_linearLimits.m_enableMotor[i]) info->m_numConstraintRows += 1;
- if (m_linearLimits.m_enableSpring[i]) info->m_numConstraintRows += 1;
- }
- //test angular limits
- for (i = 0; i < 3; i++)
- {
- testAngularLimitMotor(i);
- if (m_angularLimits[i].m_currentLimit == 4)
- info->m_numConstraintRows += 2;
- else if (m_angularLimits[i].m_currentLimit != 0)
- info->m_numConstraintRows += 1;
- if (m_angularLimits[i].m_enableMotor) info->m_numConstraintRows += 1;
- if (m_angularLimits[i].m_enableSpring) info->m_numConstraintRows += 1;
- }
-}
-
-void btGeneric6DofSpring2Constraint::getInfo2(btConstraintInfo2* info)
-{
- const btTransform& transA = m_rbA.getCenterOfMassTransform();
- const btTransform& transB = m_rbB.getCenterOfMassTransform();
- const btVector3& linVelA = m_rbA.getLinearVelocity();
- const btVector3& linVelB = m_rbB.getLinearVelocity();
- const btVector3& angVelA = m_rbA.getAngularVelocity();
- const btVector3& angVelB = m_rbB.getAngularVelocity();
-
- // for stability better to solve angular limits first
- int row = setAngularLimits(info, 0, transA, transB, linVelA, linVelB, angVelA, angVelB);
- setLinearLimits(info, row, transA, transB, linVelA, linVelB, angVelA, angVelB);
-}
-
-int btGeneric6DofSpring2Constraint::setLinearLimits(btConstraintInfo2* info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
-{
- //solve linear limits
- btRotationalLimitMotor2 limot;
- for (int i = 0; i < 3; i++)
- {
- if (m_linearLimits.m_currentLimit[i] || m_linearLimits.m_enableMotor[i] || m_linearLimits.m_enableSpring[i])
- { // re-use rotational motor code
- limot.m_bounce = m_linearLimits.m_bounce[i];
- limot.m_currentLimit = m_linearLimits.m_currentLimit[i];
- limot.m_currentPosition = m_linearLimits.m_currentLinearDiff[i];
- limot.m_currentLimitError = m_linearLimits.m_currentLimitError[i];
- limot.m_currentLimitErrorHi = m_linearLimits.m_currentLimitErrorHi[i];
- limot.m_enableMotor = m_linearLimits.m_enableMotor[i];
- limot.m_servoMotor = m_linearLimits.m_servoMotor[i];
- limot.m_servoTarget = m_linearLimits.m_servoTarget[i];
- limot.m_enableSpring = m_linearLimits.m_enableSpring[i];
- limot.m_springStiffness = m_linearLimits.m_springStiffness[i];
- limot.m_springStiffnessLimited = m_linearLimits.m_springStiffnessLimited[i];
- limot.m_springDamping = m_linearLimits.m_springDamping[i];
- limot.m_springDampingLimited = m_linearLimits.m_springDampingLimited[i];
- limot.m_equilibriumPoint = m_linearLimits.m_equilibriumPoint[i];
- limot.m_hiLimit = m_linearLimits.m_upperLimit[i];
- limot.m_loLimit = m_linearLimits.m_lowerLimit[i];
- limot.m_maxMotorForce = m_linearLimits.m_maxMotorForce[i];
- limot.m_targetVelocity = m_linearLimits.m_targetVelocity[i];
- btVector3 axis = m_calculatedTransformA.getBasis().getColumn(i);
- int flags = m_flags >> (i * BT_6DOF_FLAGS_AXIS_SHIFT2);
- limot.m_stopCFM = (flags & BT_6DOF_FLAGS_CFM_STOP2) ? m_linearLimits.m_stopCFM[i] : info->cfm[0];
- limot.m_stopERP = (flags & BT_6DOF_FLAGS_ERP_STOP2) ? m_linearLimits.m_stopERP[i] : info->erp;
- limot.m_motorCFM = (flags & BT_6DOF_FLAGS_CFM_MOTO2) ? m_linearLimits.m_motorCFM[i] : info->cfm[0];
- limot.m_motorERP = (flags & BT_6DOF_FLAGS_ERP_MOTO2) ? m_linearLimits.m_motorERP[i] : info->erp;
-
- //rotAllowed is a bit of a magic from the original 6dof. The calculation of it here is something that imitates the original behavior as much as possible.
- int indx1 = (i + 1) % 3;
- int indx2 = (i + 2) % 3;
- int rotAllowed = 1; // rotations around orthos to current axis (it is used only when one of the body is static)
-#define D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION 1.0e-3
- bool indx1Violated = m_angularLimits[indx1].m_currentLimit == 1 ||
- m_angularLimits[indx1].m_currentLimit == 2 ||
- (m_angularLimits[indx1].m_currentLimit == 3 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
- (m_angularLimits[indx1].m_currentLimit == 4 && (m_angularLimits[indx1].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx1].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
- bool indx2Violated = m_angularLimits[indx2].m_currentLimit == 1 ||
- m_angularLimits[indx2].m_currentLimit == 2 ||
- (m_angularLimits[indx2].m_currentLimit == 3 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitError > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION)) ||
- (m_angularLimits[indx2].m_currentLimit == 4 && (m_angularLimits[indx2].m_currentLimitError < -D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION || m_angularLimits[indx2].m_currentLimitErrorHi > D6_LIMIT_ERROR_THRESHOLD_FOR_ROTATION));
- if (indx1Violated && indx2Violated)
- {
- rotAllowed = 0;
- }
- row += get_limit_motor_info2(&limot, transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 0, rotAllowed);
- }
- }
- return row;
-}
-
-int btGeneric6DofSpring2Constraint::setAngularLimits(btConstraintInfo2* info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB)
-{
- int row = row_offset;
-
- //order of rotational constraint rows
- int cIdx[] = {0, 1, 2};
- switch (m_rotateOrder)
- {
- case RO_XYZ:
- cIdx[0] = 0;
- cIdx[1] = 1;
- cIdx[2] = 2;
- break;
- case RO_XZY:
- cIdx[0] = 0;
- cIdx[1] = 2;
- cIdx[2] = 1;
- break;
- case RO_YXZ:
- cIdx[0] = 1;
- cIdx[1] = 0;
- cIdx[2] = 2;
- break;
- case RO_YZX:
- cIdx[0] = 1;
- cIdx[1] = 2;
- cIdx[2] = 0;
- break;
- case RO_ZXY:
- cIdx[0] = 2;
- cIdx[1] = 0;
- cIdx[2] = 1;
- break;
- case RO_ZYX:
- cIdx[0] = 2;
- cIdx[1] = 1;
- cIdx[2] = 0;
- break;
- default:
- btAssert(false);
- }
-
- for (int ii = 0; ii < 3; ii++)
- {
- int i = cIdx[ii];
- if (m_angularLimits[i].m_currentLimit || m_angularLimits[i].m_enableMotor || m_angularLimits[i].m_enableSpring)
- {
- btVector3 axis = getAxis(i);
- int flags = m_flags >> ((i + 3) * BT_6DOF_FLAGS_AXIS_SHIFT2);
- if (!(flags & BT_6DOF_FLAGS_CFM_STOP2))
- {
- m_angularLimits[i].m_stopCFM = info->cfm[0];
- }
- if (!(flags & BT_6DOF_FLAGS_ERP_STOP2))
- {
- m_angularLimits[i].m_stopERP = info->erp;
- }
- if (!(flags & BT_6DOF_FLAGS_CFM_MOTO2))
- {
- m_angularLimits[i].m_motorCFM = info->cfm[0];
- }
- if (!(flags & BT_6DOF_FLAGS_ERP_MOTO2))
- {
- m_angularLimits[i].m_motorERP = info->erp;
- }
- row += get_limit_motor_info2(&m_angularLimits[i], transA, transB, linVelA, linVelB, angVelA, angVelB, info, row, axis, 1);
- }
- }
-
- return row;
-}
-
-void btGeneric6DofSpring2Constraint::setFrames(const btTransform& frameA, const btTransform& frameB)
-{
- m_frameInA = frameA;
- m_frameInB = frameB;
- buildJacobian();
- calculateTransforms();
-}
-
-void btGeneric6DofSpring2Constraint::calculateLinearInfo()
-{
- m_calculatedLinearDiff = m_calculatedTransformB.getOrigin() - m_calculatedTransformA.getOrigin();
- m_calculatedLinearDiff = m_calculatedTransformA.getBasis().inverse() * m_calculatedLinearDiff;
- for (int i = 0; i < 3; i++)
- {
- m_linearLimits.m_currentLinearDiff[i] = m_calculatedLinearDiff[i];
- m_linearLimits.testLimitValue(i, m_calculatedLinearDiff[i]);
- }
-}
-
-void btGeneric6DofSpring2Constraint::calculateJacobi(btRotationalLimitMotor2* limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed)
-{
- btScalar* J1 = rotational ? info->m_J1angularAxis : info->m_J1linearAxis;
- btScalar* J2 = rotational ? info->m_J2angularAxis : info->m_J2linearAxis;
-
- J1[srow + 0] = ax1[0];
- J1[srow + 1] = ax1[1];
- J1[srow + 2] = ax1[2];
-
- J2[srow + 0] = -ax1[0];
- J2[srow + 1] = -ax1[1];
- J2[srow + 2] = -ax1[2];
-
- if (!rotational)
- {
- btVector3 tmpA, tmpB, relA, relB;
- // get vector from bodyB to frameB in WCS
- relB = m_calculatedTransformB.getOrigin() - transB.getOrigin();
- // same for bodyA
- relA = m_calculatedTransformA.getOrigin() - transA.getOrigin();
- tmpA = relA.cross(ax1);
- tmpB = relB.cross(ax1);
- if (m_hasStaticBody && (!rotAllowed))
- {
- tmpA *= m_factA;
- tmpB *= m_factB;
- }
- int i;
- for (i = 0; i < 3; i++) info->m_J1angularAxis[srow + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[srow + i] = -tmpB[i];
- }
-}
-
-int btGeneric6DofSpring2Constraint::get_limit_motor_info2(
- btRotationalLimitMotor2* limot,
- const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
- btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed)
-{
- int count = 0;
- int srow = row * info->rowskip;
-
- if (limot->m_currentLimit == 4)
- {
- btScalar vel = rotational ? angVelA.dot(ax1) - angVelB.dot(ax1) : linVelA.dot(ax1) - linVelB.dot(ax1);
-
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
- info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
- if (rotational)
- {
- if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
- {
- btScalar bounceerror = -limot->m_bounce * vel;
- if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
- }
- }
- else
- {
- if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
- {
- btScalar bounceerror = -limot->m_bounce * vel;
- if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
- }
- }
- info->m_lowerLimit[srow] = rotational ? 0 : -SIMD_INFINITY;
- info->m_upperLimit[srow] = rotational ? SIMD_INFINITY : 0;
- info->cfm[srow] = limot->m_stopCFM;
- srow += info->rowskip;
- ++count;
-
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
- info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitErrorHi * (rotational ? -1 : 1);
- if (rotational)
- {
- if (info->m_constraintError[srow] - vel * limot->m_stopERP < 0)
- {
- btScalar bounceerror = -limot->m_bounce * vel;
- if (bounceerror < info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
- }
- }
- else
- {
- if (info->m_constraintError[srow] - vel * limot->m_stopERP > 0)
- {
- btScalar bounceerror = -limot->m_bounce * vel;
- if (bounceerror > info->m_constraintError[srow]) info->m_constraintError[srow] = bounceerror;
- }
- }
- info->m_lowerLimit[srow] = rotational ? -SIMD_INFINITY : 0;
- info->m_upperLimit[srow] = rotational ? 0 : SIMD_INFINITY;
- info->cfm[srow] = limot->m_stopCFM;
- srow += info->rowskip;
- ++count;
- }
- else if (limot->m_currentLimit == 3)
- {
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
- info->m_constraintError[srow] = info->fps * limot->m_stopERP * limot->m_currentLimitError * (rotational ? -1 : 1);
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- info->cfm[srow] = limot->m_stopCFM;
- srow += info->rowskip;
- ++count;
- }
-
- if (limot->m_enableMotor && !limot->m_servoMotor)
- {
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
- btScalar tag_vel = rotational ? limot->m_targetVelocity : -limot->m_targetVelocity;
- btScalar mot_fact = getMotorFactor(limot->m_currentPosition,
- limot->m_loLimit,
- limot->m_hiLimit,
- tag_vel,
- info->fps * limot->m_motorERP);
- info->m_constraintError[srow] = mot_fact * limot->m_targetVelocity;
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- info->cfm[srow] = limot->m_motorCFM;
- srow += info->rowskip;
- ++count;
- }
-
- if (limot->m_enableMotor && limot->m_servoMotor)
- {
- btScalar error = limot->m_currentPosition - limot->m_servoTarget;
- btScalar curServoTarget = limot->m_servoTarget;
- if (rotational)
- {
- if (error > SIMD_PI)
- {
- error -= SIMD_2_PI;
- curServoTarget += SIMD_2_PI;
- }
- if (error < -SIMD_PI)
- {
- error += SIMD_2_PI;
- curServoTarget -= SIMD_2_PI;
- }
- }
-
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
- btScalar targetvelocity = error < 0 ? -limot->m_targetVelocity : limot->m_targetVelocity;
- btScalar tag_vel = -targetvelocity;
- btScalar mot_fact;
- if (error != 0)
- {
- btScalar lowLimit;
- btScalar hiLimit;
- if (limot->m_loLimit > limot->m_hiLimit)
- {
- lowLimit = error > 0 ? curServoTarget : -SIMD_INFINITY;
- hiLimit = error < 0 ? curServoTarget : SIMD_INFINITY;
- }
- else
- {
- lowLimit = error > 0 && curServoTarget > limot->m_loLimit ? curServoTarget : limot->m_loLimit;
- hiLimit = error < 0 && curServoTarget < limot->m_hiLimit ? curServoTarget : limot->m_hiLimit;
- }
- mot_fact = getMotorFactor(limot->m_currentPosition, lowLimit, hiLimit, tag_vel, info->fps * limot->m_motorERP);
- }
- else
- {
- mot_fact = 0;
- }
- info->m_constraintError[srow] = mot_fact * targetvelocity * (rotational ? -1 : 1);
- info->m_lowerLimit[srow] = -limot->m_maxMotorForce / info->fps;
- info->m_upperLimit[srow] = limot->m_maxMotorForce / info->fps;
- info->cfm[srow] = limot->m_motorCFM;
- srow += info->rowskip;
- ++count;
- }
-
- if (limot->m_enableSpring)
- {
- btScalar error = limot->m_currentPosition - limot->m_equilibriumPoint;
- calculateJacobi(limot, transA, transB, info, srow, ax1, rotational, rotAllowed);
-
- //btScalar cfm = 1.0 / ((1.0/info->fps)*limot->m_springStiffness+ limot->m_springDamping);
- //if(cfm > 0.99999)
- // cfm = 0.99999;
- //btScalar erp = (1.0/info->fps)*limot->m_springStiffness / ((1.0/info->fps)*limot->m_springStiffness + limot->m_springDamping);
- //info->m_constraintError[srow] = info->fps * erp * error * (rotational ? -1.0 : 1.0);
- //info->m_lowerLimit[srow] = -SIMD_INFINITY;
- //info->m_upperLimit[srow] = SIMD_INFINITY;
-
- btScalar dt = BT_ONE / info->fps;
- btScalar kd = limot->m_springDamping;
- btScalar ks = limot->m_springStiffness;
- btScalar vel;
- if (rotational)
- {
- vel = angVelA.dot(ax1) - angVelB.dot(ax1);
- }
- else
- {
- btVector3 tanVelA = angVelA.cross(m_calculatedTransformA.getOrigin() - transA.getOrigin());
- btVector3 tanVelB = angVelB.cross(m_calculatedTransformB.getOrigin() - transB.getOrigin());
- vel = (linVelA + tanVelA).dot(ax1) - (linVelB + tanVelB).dot(ax1);
- }
- btScalar cfm = BT_ZERO;
- btScalar mA = BT_ONE / m_rbA.getInvMass();
- btScalar mB = BT_ONE / m_rbB.getInvMass();
- if (rotational)
- {
- btScalar rrA = (m_calculatedTransformA.getOrigin() - transA.getOrigin()).length2();
- btScalar rrB = (m_calculatedTransformB.getOrigin() - transB.getOrigin()).length2();
- if (m_rbA.getInvMass()) mA = mA * rrA + 1 / (m_rbA.getInvInertiaTensorWorld() * ax1).length();
- if (m_rbB.getInvMass()) mB = mB * rrB + 1 / (m_rbB.getInvInertiaTensorWorld() * ax1).length();
- }
- btScalar m;
- if (m_rbA.getInvMass() == 0) m = mB; else
- if (m_rbB.getInvMass() == 0) m = mA; else
- m = mA*mB / (mA + mB);
- btScalar angularfreq = btSqrt(ks / m);
-
- //limit stiffness (the spring should not be sampled faster that the quarter of its angular frequency)
- if (limot->m_springStiffnessLimited && 0.25 < angularfreq * dt)
- {
- ks = BT_ONE / dt / dt / btScalar(16.0) * m;
- }
- //avoid damping that would blow up the spring
- if (limot->m_springDampingLimited && kd * dt > m)
- {
- kd = m / dt;
- }
- btScalar fs = ks * error * dt;
- btScalar fd = -kd * (vel) * (rotational ? -1 : 1) * dt;
- btScalar f = (fs + fd);
-
- // after the spring force affecting the body(es) the new velocity will be
- // vel + f / m * (rotational ? -1 : 1)
- // so in theory this should be set here for m_constraintError
- // (with m_constraintError we set a desired velocity for the affected body(es))
- // however in practice any value is fine as long as it is greater than the "proper" velocity,
- // because the m_lowerLimit and the m_upperLimit will determinate the strength of the final pulling force
- // so it is much simpler (and more robust) just to simply use inf (with the proper sign)
- // (Even with our best intent the "new" velocity is only an estimation. If we underestimate
- // the "proper" velocity that will weaken the spring, however if we overestimate it, it doesn't
- // matter, because the solver will limit it according the force limit)
- // you may also wonder what if the current velocity (vel) so high that the pulling force will not change its direction (in this iteration)
- // will we not request a velocity with the wrong direction ?
- // and the answer is not, because in practice during the solving the current velocity is subtracted from the m_constraintError
- // so the sign of the force that is really matters
- if (m_flags & BT_6DOF_FLAGS_USE_INFINITE_ERROR)
- info->m_constraintError[srow] = (rotational ? -1 : 1) * (f < 0 ? -SIMD_INFINITY : SIMD_INFINITY);
- else
- info->m_constraintError[srow] = vel + f / m * (rotational ? -1 : 1);
-
- btScalar minf = f < fd ? f : fd;
- btScalar maxf = f < fd ? fd : f;
- if (!rotational)
- {
- info->m_lowerLimit[srow] = minf > 0 ? 0 : minf;
- info->m_upperLimit[srow] = maxf < 0 ? 0 : maxf;
- }
- else
- {
- info->m_lowerLimit[srow] = -maxf > 0 ? 0 : -maxf;
- info->m_upperLimit[srow] = -minf < 0 ? 0 : -minf;
- }
-
- info->cfm[srow] = cfm;
- srow += info->rowskip;
- ++count;
- }
-
- return count;
-}
-
-//override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-//If no axis is provided, it uses the default axis for this constraint.
-void btGeneric6DofSpring2Constraint::setParam(int num, btScalar value, int axis)
-{
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- m_linearLimits.m_stopERP[axis] = value;
- m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_STOP_CFM:
- m_linearLimits.m_stopCFM[axis] = value;
- m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_ERP:
- m_linearLimits.m_motorERP[axis] = value;
- m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_CFM:
- m_linearLimits.m_motorCFM[axis] = value;
- m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- m_angularLimits[axis - 3].m_stopERP = value;
- m_flags |= BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_STOP_CFM:
- m_angularLimits[axis - 3].m_stopCFM = value;
- m_flags |= BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_ERP:
- m_angularLimits[axis - 3].m_motorERP = value;
- m_flags |= BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- case BT_CONSTRAINT_CFM:
- m_angularLimits[axis - 3].m_motorCFM = value;
- m_flags |= BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2);
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
-}
-
-//return the local value of parameter
-btScalar btGeneric6DofSpring2Constraint::getParam(int num, int axis) const
-{
- btScalar retVal = 0;
- if ((axis >= 0) && (axis < 3))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_linearLimits.m_stopERP[axis];
- break;
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_linearLimits.m_stopCFM[axis];
- break;
- case BT_CONSTRAINT_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_linearLimits.m_motorERP[axis];
- break;
- case BT_CONSTRAINT_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_linearLimits.m_motorCFM[axis];
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else if ((axis >= 3) && (axis < 6))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_angularLimits[axis - 3].m_stopERP;
- break;
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_STOP2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_angularLimits[axis - 3].m_stopCFM;
- break;
- case BT_CONSTRAINT_ERP:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_ERP_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_angularLimits[axis - 3].m_motorERP;
- break;
- case BT_CONSTRAINT_CFM:
- btAssertConstrParams(m_flags & (BT_6DOF_FLAGS_CFM_MOTO2 << (axis * BT_6DOF_FLAGS_AXIS_SHIFT2)));
- retVal = m_angularLimits[axis - 3].m_motorCFM;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
- return retVal;
-}
-
-void btGeneric6DofSpring2Constraint::setAxis(const btVector3& axis1, const btVector3& axis2)
-{
- btVector3 zAxis = axis1.normalized();
- btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
- // now get constraint frame in local coordinate systems
- m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
- calculateTransforms();
-}
-
-void btGeneric6DofSpring2Constraint::setBounce(int index, btScalar bounce)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_bounce[index] = bounce;
- else
- m_angularLimits[index - 3].m_bounce = bounce;
-}
-
-void btGeneric6DofSpring2Constraint::enableMotor(int index, bool onOff)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_enableMotor[index] = onOff;
- else
- m_angularLimits[index - 3].m_enableMotor = onOff;
-}
-
-void btGeneric6DofSpring2Constraint::setServo(int index, bool onOff)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_servoMotor[index] = onOff;
- else
- m_angularLimits[index - 3].m_servoMotor = onOff;
-}
-
-void btGeneric6DofSpring2Constraint::setTargetVelocity(int index, btScalar velocity)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_targetVelocity[index] = velocity;
- else
- m_angularLimits[index - 3].m_targetVelocity = velocity;
-}
-
-void btGeneric6DofSpring2Constraint::setServoTarget(int index, btScalar targetOrg)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- {
- m_linearLimits.m_servoTarget[index] = targetOrg;
- }
- else
- {
- //wrap between -PI and PI, see also
- //https://stackoverflow.com/questions/4633177/c-how-to-wrap-a-float-to-the-interval-pi-pi
-
- btScalar target = targetOrg + SIMD_PI;
- if (1)
- {
- btScalar m = target - SIMD_2_PI * std::floor(target / SIMD_2_PI);
- // handle boundary cases resulted from floating-point cut off:
- {
- if (m >= SIMD_2_PI)
- {
- target = 0;
- }
- else
- {
- if (m < 0)
- {
- if (SIMD_2_PI + m == SIMD_2_PI)
- target = 0;
- else
- target = SIMD_2_PI + m;
- }
- else
- {
- target = m;
- }
- }
- }
- target -= SIMD_PI;
- }
-
- m_angularLimits[index - 3].m_servoTarget = target;
- }
-}
-
-void btGeneric6DofSpring2Constraint::setMaxMotorForce(int index, btScalar force)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_maxMotorForce[index] = force;
- else
- m_angularLimits[index - 3].m_maxMotorForce = force;
-}
-
-void btGeneric6DofSpring2Constraint::enableSpring(int index, bool onOff)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_enableSpring[index] = onOff;
- else
- m_angularLimits[index - 3].m_enableSpring = onOff;
-}
-
-void btGeneric6DofSpring2Constraint::setStiffness(int index, btScalar stiffness, bool limitIfNeeded)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- {
- m_linearLimits.m_springStiffness[index] = stiffness;
- m_linearLimits.m_springStiffnessLimited[index] = limitIfNeeded;
- }
- else
- {
- m_angularLimits[index - 3].m_springStiffness = stiffness;
- m_angularLimits[index - 3].m_springStiffnessLimited = limitIfNeeded;
- }
-}
-
-void btGeneric6DofSpring2Constraint::setDamping(int index, btScalar damping, bool limitIfNeeded)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- {
- m_linearLimits.m_springDamping[index] = damping;
- m_linearLimits.m_springDampingLimited[index] = limitIfNeeded;
- }
- else
- {
- m_angularLimits[index - 3].m_springDamping = damping;
- m_angularLimits[index - 3].m_springDampingLimited = limitIfNeeded;
- }
-}
-
-void btGeneric6DofSpring2Constraint::setEquilibriumPoint()
-{
- calculateTransforms();
- int i;
- for (i = 0; i < 3; i++)
- m_linearLimits.m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
- for (i = 0; i < 3; i++)
- m_angularLimits[i].m_equilibriumPoint = m_calculatedAxisAngleDiff[i];
-}
-
-void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index)
-{
- btAssert((index >= 0) && (index < 6));
- calculateTransforms();
- if (index < 3)
- m_linearLimits.m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
- else
- m_angularLimits[index - 3].m_equilibriumPoint = m_calculatedAxisAngleDiff[index - 3];
-}
-
-void btGeneric6DofSpring2Constraint::setEquilibriumPoint(int index, btScalar val)
-{
- btAssert((index >= 0) && (index < 6));
- if (index < 3)
- m_linearLimits.m_equilibriumPoint[index] = val;
- else
- m_angularLimits[index - 3].m_equilibriumPoint = val;
-}
-
-//////////////////////////// btRotationalLimitMotor2 ////////////////////////////////////
-
-void btRotationalLimitMotor2::testLimitValue(btScalar test_value)
-{
- //we can't normalize the angles here because we would lost the sign that we use later, but it doesn't seem to be a problem
- if (m_loLimit > m_hiLimit)
- {
- m_currentLimit = 0;
- m_currentLimitError = btScalar(0.f);
- }
- else if (m_loLimit == m_hiLimit)
- {
- m_currentLimitError = test_value - m_loLimit;
- m_currentLimit = 3;
- }
- else
- {
- m_currentLimitError = test_value - m_loLimit;
- m_currentLimitErrorHi = test_value - m_hiLimit;
- m_currentLimit = 4;
- }
-}
-
-//////////////////////////// btTranslationalLimitMotor2 ////////////////////////////////////
-
-void btTranslationalLimitMotor2::testLimitValue(int limitIndex, btScalar test_value)
-{
- btScalar loLimit = m_lowerLimit[limitIndex];
- btScalar hiLimit = m_upperLimit[limitIndex];
- if (loLimit > hiLimit)
- {
- m_currentLimitError[limitIndex] = 0;
- m_currentLimit[limitIndex] = 0;
- }
- else if (loLimit == hiLimit)
- {
- m_currentLimitError[limitIndex] = test_value - loLimit;
- m_currentLimit[limitIndex] = 3;
- }
- else
- {
- m_currentLimitError[limitIndex] = test_value - loLimit;
- m_currentLimitErrorHi[limitIndex] = test_value - hiLimit;
- m_currentLimit[limitIndex] = 4;
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
deleted file mode 100644
index c86dc373da..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-2014 May: btGeneric6DofSpring2Constraint is created from the original (2.82.2712) btGeneric6DofConstraint by Gabor Puhr and Tamas Umenhoffer
-Pros:
-- Much more accurate and stable in a lot of situation. (Especially when a sleeping chain of RBs connected with 6dof2 is pulled)
-- Stable and accurate spring with minimal energy loss that works with all of the solvers. (latter is not true for the original 6dof spring)
-- Servo motor functionality
-- Much more accurate bouncing. 0 really means zero bouncing (not true for the original 6odf) and there is only a minimal energy loss when the value is 1 (because of the solvers' precision)
-- Rotation order for the Euler system can be set. (One axis' freedom is still limited to pi/2)
-
-Cons:
-- It is slower than the original 6dof. There is no exact ratio, but half speed is a good estimation.
-- At bouncing the correct velocity is calculated, but not the correct position. (it is because of the solver can correct position or velocity, but not both.)
-*/
-
-/// 2009 March: btGeneric6DofConstraint refactored by Roman Ponomarev
-/// Added support for generic constraint solver through getInfo1/getInfo2 methods
-
-/*
-2007-09-09
-btGeneric6DofConstraint Refactored by Francisco Le?n
-email: projectileman@yahoo.com
-http://gimpact.sf.net
-*/
-
-#ifndef BT_GENERIC_6DOF_CONSTRAINT2_H
-#define BT_GENERIC_6DOF_CONSTRAINT2_H
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-class btRigidBody;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintDoubleData2
-#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintDoubleData2"
-#else
-#define btGeneric6DofSpring2ConstraintData2 btGeneric6DofSpring2ConstraintData
-#define btGeneric6DofSpring2ConstraintDataName "btGeneric6DofSpring2ConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-enum RotateOrder
-{
- RO_XYZ = 0,
- RO_XZY,
- RO_YXZ,
- RO_YZX,
- RO_ZXY,
- RO_ZYX
-};
-
-class btRotationalLimitMotor2
-{
-public:
- // upper < lower means free
- // upper == lower means locked
- // upper > lower means limited
- btScalar m_loLimit;
- btScalar m_hiLimit;
- btScalar m_bounce;
- btScalar m_stopERP;
- btScalar m_stopCFM;
- btScalar m_motorERP;
- btScalar m_motorCFM;
- bool m_enableMotor;
- btScalar m_targetVelocity;
- btScalar m_maxMotorForce;
- bool m_servoMotor;
- btScalar m_servoTarget;
- bool m_enableSpring;
- btScalar m_springStiffness;
- bool m_springStiffnessLimited;
- btScalar m_springDamping;
- bool m_springDampingLimited;
- btScalar m_equilibriumPoint;
-
- btScalar m_currentLimitError;
- btScalar m_currentLimitErrorHi;
- btScalar m_currentPosition;
- int m_currentLimit;
-
- btRotationalLimitMotor2()
- {
- m_loLimit = 1.0f;
- m_hiLimit = -1.0f;
- m_bounce = 0.0f;
- m_stopERP = 0.2f;
- m_stopCFM = 0.f;
- m_motorERP = 0.9f;
- m_motorCFM = 0.f;
- m_enableMotor = false;
- m_targetVelocity = 0;
- m_maxMotorForce = 6.0f;
- m_servoMotor = false;
- m_servoTarget = 0;
- m_enableSpring = false;
- m_springStiffness = 0;
- m_springStiffnessLimited = false;
- m_springDamping = 0;
- m_springDampingLimited = false;
- m_equilibriumPoint = 0;
-
- m_currentLimitError = 0;
- m_currentLimitErrorHi = 0;
- m_currentPosition = 0;
- m_currentLimit = 0;
- }
-
- btRotationalLimitMotor2(const btRotationalLimitMotor2& limot)
- {
- m_loLimit = limot.m_loLimit;
- m_hiLimit = limot.m_hiLimit;
- m_bounce = limot.m_bounce;
- m_stopERP = limot.m_stopERP;
- m_stopCFM = limot.m_stopCFM;
- m_motorERP = limot.m_motorERP;
- m_motorCFM = limot.m_motorCFM;
- m_enableMotor = limot.m_enableMotor;
- m_targetVelocity = limot.m_targetVelocity;
- m_maxMotorForce = limot.m_maxMotorForce;
- m_servoMotor = limot.m_servoMotor;
- m_servoTarget = limot.m_servoTarget;
- m_enableSpring = limot.m_enableSpring;
- m_springStiffness = limot.m_springStiffness;
- m_springStiffnessLimited = limot.m_springStiffnessLimited;
- m_springDamping = limot.m_springDamping;
- m_springDampingLimited = limot.m_springDampingLimited;
- m_equilibriumPoint = limot.m_equilibriumPoint;
-
- m_currentLimitError = limot.m_currentLimitError;
- m_currentLimitErrorHi = limot.m_currentLimitErrorHi;
- m_currentPosition = limot.m_currentPosition;
- m_currentLimit = limot.m_currentLimit;
- }
-
- bool isLimited()
- {
- if (m_loLimit > m_hiLimit) return false;
- return true;
- }
-
- void testLimitValue(btScalar test_value);
-};
-
-class btTranslationalLimitMotor2
-{
-public:
- // upper < lower means free
- // upper == lower means locked
- // upper > lower means limited
- btVector3 m_lowerLimit;
- btVector3 m_upperLimit;
- btVector3 m_bounce;
- btVector3 m_stopERP;
- btVector3 m_stopCFM;
- btVector3 m_motorERP;
- btVector3 m_motorCFM;
- bool m_enableMotor[3];
- bool m_servoMotor[3];
- bool m_enableSpring[3];
- btVector3 m_servoTarget;
- btVector3 m_springStiffness;
- bool m_springStiffnessLimited[3];
- btVector3 m_springDamping;
- bool m_springDampingLimited[3];
- btVector3 m_equilibriumPoint;
- btVector3 m_targetVelocity;
- btVector3 m_maxMotorForce;
-
- btVector3 m_currentLimitError;
- btVector3 m_currentLimitErrorHi;
- btVector3 m_currentLinearDiff;
- int m_currentLimit[3];
-
- btTranslationalLimitMotor2()
- {
- m_lowerLimit.setValue(0.f, 0.f, 0.f);
- m_upperLimit.setValue(0.f, 0.f, 0.f);
- m_bounce.setValue(0.f, 0.f, 0.f);
- m_stopERP.setValue(0.2f, 0.2f, 0.2f);
- m_stopCFM.setValue(0.f, 0.f, 0.f);
- m_motorERP.setValue(0.9f, 0.9f, 0.9f);
- m_motorCFM.setValue(0.f, 0.f, 0.f);
-
- m_currentLimitError.setValue(0.f, 0.f, 0.f);
- m_currentLimitErrorHi.setValue(0.f, 0.f, 0.f);
- m_currentLinearDiff.setValue(0.f, 0.f, 0.f);
-
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = false;
- m_servoMotor[i] = false;
- m_enableSpring[i] = false;
- m_servoTarget[i] = btScalar(0.f);
- m_springStiffness[i] = btScalar(0.f);
- m_springStiffnessLimited[i] = false;
- m_springDamping[i] = btScalar(0.f);
- m_springDampingLimited[i] = false;
- m_equilibriumPoint[i] = btScalar(0.f);
- m_targetVelocity[i] = btScalar(0.f);
- m_maxMotorForce[i] = btScalar(0.f);
-
- m_currentLimit[i] = 0;
- }
- }
-
- btTranslationalLimitMotor2(const btTranslationalLimitMotor2& other)
- {
- m_lowerLimit = other.m_lowerLimit;
- m_upperLimit = other.m_upperLimit;
- m_bounce = other.m_bounce;
- m_stopERP = other.m_stopERP;
- m_stopCFM = other.m_stopCFM;
- m_motorERP = other.m_motorERP;
- m_motorCFM = other.m_motorCFM;
-
- m_currentLimitError = other.m_currentLimitError;
- m_currentLimitErrorHi = other.m_currentLimitErrorHi;
- m_currentLinearDiff = other.m_currentLinearDiff;
-
- for (int i = 0; i < 3; i++)
- {
- m_enableMotor[i] = other.m_enableMotor[i];
- m_servoMotor[i] = other.m_servoMotor[i];
- m_enableSpring[i] = other.m_enableSpring[i];
- m_servoTarget[i] = other.m_servoTarget[i];
- m_springStiffness[i] = other.m_springStiffness[i];
- m_springStiffnessLimited[i] = other.m_springStiffnessLimited[i];
- m_springDamping[i] = other.m_springDamping[i];
- m_springDampingLimited[i] = other.m_springDampingLimited[i];
- m_equilibriumPoint[i] = other.m_equilibriumPoint[i];
- m_targetVelocity[i] = other.m_targetVelocity[i];
- m_maxMotorForce[i] = other.m_maxMotorForce[i];
-
- m_currentLimit[i] = other.m_currentLimit[i];
- }
- }
-
- inline bool isLimited(int limitIndex)
- {
- return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]);
- }
-
- void testLimitValue(int limitIndex, btScalar test_value);
-};
-
-enum bt6DofFlags2
-{
- BT_6DOF_FLAGS_CFM_STOP2 = 1,
- BT_6DOF_FLAGS_ERP_STOP2 = 2,
- BT_6DOF_FLAGS_CFM_MOTO2 = 4,
- BT_6DOF_FLAGS_ERP_MOTO2 = 8,
- BT_6DOF_FLAGS_USE_INFINITE_ERROR = (1<<16)
-};
-#define BT_6DOF_FLAGS_AXIS_SHIFT2 4 // bits per axis
-
-ATTRIBUTE_ALIGNED16(class)
-btGeneric6DofSpring2Constraint : public btTypedConstraint
-{
-protected:
- btTransform m_frameInA;
- btTransform m_frameInB;
-
- btJacobianEntry m_jacLinear[3];
- btJacobianEntry m_jacAng[3];
-
- btTranslationalLimitMotor2 m_linearLimits;
- btRotationalLimitMotor2 m_angularLimits[3];
-
- RotateOrder m_rotateOrder;
-
-protected:
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
- btVector3 m_calculatedAxisAngleDiff;
- btVector3 m_calculatedAxis[3];
- btVector3 m_calculatedLinearDiff;
- btScalar m_factA;
- btScalar m_factB;
- bool m_hasStaticBody;
- int m_flags;
-
- btGeneric6DofSpring2Constraint& operator=(const btGeneric6DofSpring2Constraint&)
- {
- btAssert(0);
- return *this;
- }
-
- int setAngularLimits(btConstraintInfo2 * info, int row_offset, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
- int setLinearLimits(btConstraintInfo2 * info, int row, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB);
-
- void calculateLinearInfo();
- void calculateAngleInfo();
- void testAngularLimitMotor(int axis_index);
-
- void calculateJacobi(btRotationalLimitMotor2 * limot, const btTransform& transA, const btTransform& transB, btConstraintInfo2* info, int srow, btVector3& ax1, int rotational, int rotAllowed);
- int get_limit_motor_info2(btRotationalLimitMotor2 * limot,
- const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, const btVector3& angVelA, const btVector3& angVelB,
- btConstraintInfo2* info, int row, btVector3& ax1, int rotational, int rotAllowed = false);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btGeneric6DofSpring2Constraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
- btGeneric6DofSpring2Constraint(btRigidBody & rbB, const btTransform& frameInB, RotateOrder rotOrder = RO_XYZ);
-
- virtual void buildJacobian() {}
- virtual void getInfo1(btConstraintInfo1 * info);
- virtual void getInfo2(btConstraintInfo2 * info);
- virtual int calculateSerializeBufferSize() const;
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-
- btRotationalLimitMotor2* getRotationalLimitMotor(int index) { return &m_angularLimits[index]; }
- btTranslationalLimitMotor2* getTranslationalLimitMotor() { return &m_linearLimits; }
-
- // Calculates the global transform for the joint offset for body A an B, and also calculates the angle differences between the bodies.
- void calculateTransforms(const btTransform& transA, const btTransform& transB);
- void calculateTransforms();
-
- // Gets the global transform of the offset for body A
- const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; }
- // Gets the global transform of the offset for body B
- const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; }
-
- const btTransform& getFrameOffsetA() const { return m_frameInA; }
- const btTransform& getFrameOffsetB() const { return m_frameInB; }
-
- btTransform& getFrameOffsetA() { return m_frameInA; }
- btTransform& getFrameOffsetB() { return m_frameInB; }
-
- // Get the rotation axis in global coordinates ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
- btVector3 getAxis(int axis_index) const { return m_calculatedAxis[axis_index]; }
-
- // Get the relative Euler angle ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
- btScalar getAngle(int axis_index) const { return m_calculatedAxisAngleDiff[axis_index]; }
-
- // Get the relative position of the constraint pivot ( btGeneric6DofSpring2Constraint::calculateTransforms() must be called previously )
- btScalar getRelativePivotPosition(int axis_index) const { return m_calculatedLinearDiff[axis_index]; }
-
- void setFrames(const btTransform& frameA, const btTransform& frameB);
-
- void setLinearLowerLimit(const btVector3& linearLower) { m_linearLimits.m_lowerLimit = linearLower; }
- void getLinearLowerLimit(btVector3 & linearLower) { linearLower = m_linearLimits.m_lowerLimit; }
- void setLinearUpperLimit(const btVector3& linearUpper) { m_linearLimits.m_upperLimit = linearUpper; }
- void getLinearUpperLimit(btVector3 & linearUpper) { linearUpper = m_linearLimits.m_upperLimit; }
-
- void setAngularLowerLimit(const btVector3& angularLower)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_loLimit = btNormalizeAngle(angularLower[i]);
- }
-
- void setAngularLowerLimitReversed(const btVector3& angularLower)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_hiLimit = btNormalizeAngle(-angularLower[i]);
- }
-
- void getAngularLowerLimit(btVector3 & angularLower)
- {
- for (int i = 0; i < 3; i++)
- angularLower[i] = m_angularLimits[i].m_loLimit;
- }
-
- void getAngularLowerLimitReversed(btVector3 & angularLower)
- {
- for (int i = 0; i < 3; i++)
- angularLower[i] = -m_angularLimits[i].m_hiLimit;
- }
-
- void setAngularUpperLimit(const btVector3& angularUpper)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_hiLimit = btNormalizeAngle(angularUpper[i]);
- }
-
- void setAngularUpperLimitReversed(const btVector3& angularUpper)
- {
- for (int i = 0; i < 3; i++)
- m_angularLimits[i].m_loLimit = btNormalizeAngle(-angularUpper[i]);
- }
-
- void getAngularUpperLimit(btVector3 & angularUpper)
- {
- for (int i = 0; i < 3; i++)
- angularUpper[i] = m_angularLimits[i].m_hiLimit;
- }
-
- void getAngularUpperLimitReversed(btVector3 & angularUpper)
- {
- for (int i = 0; i < 3; i++)
- angularUpper[i] = -m_angularLimits[i].m_loLimit;
- }
-
- //first 3 are linear, next 3 are angular
-
- void setLimit(int axis, btScalar lo, btScalar hi)
- {
- if (axis < 3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
- lo = btNormalizeAngle(lo);
- hi = btNormalizeAngle(hi);
- m_angularLimits[axis - 3].m_loLimit = lo;
- m_angularLimits[axis - 3].m_hiLimit = hi;
- }
- }
-
- void setLimitReversed(int axis, btScalar lo, btScalar hi)
- {
- if (axis < 3)
- {
- m_linearLimits.m_lowerLimit[axis] = lo;
- m_linearLimits.m_upperLimit[axis] = hi;
- }
- else
- {
- lo = btNormalizeAngle(lo);
- hi = btNormalizeAngle(hi);
- m_angularLimits[axis - 3].m_hiLimit = -lo;
- m_angularLimits[axis - 3].m_loLimit = -hi;
- }
- }
-
- bool isLimited(int limitIndex)
- {
- if (limitIndex < 3)
- {
- return m_linearLimits.isLimited(limitIndex);
- }
- return m_angularLimits[limitIndex - 3].isLimited();
- }
-
- void setRotationOrder(RotateOrder order) { m_rotateOrder = order; }
- RotateOrder getRotationOrder() { return m_rotateOrder; }
-
- void setAxis(const btVector3& axis1, const btVector3& axis2);
-
- void setBounce(int index, btScalar bounce);
-
- void enableMotor(int index, bool onOff);
- void setServo(int index, bool onOff); // set the type of the motor (servo or not) (the motor has to be turned on for servo also)
- void setTargetVelocity(int index, btScalar velocity);
- void setServoTarget(int index, btScalar target);
- void setMaxMotorForce(int index, btScalar force);
-
- void enableSpring(int index, bool onOff);
- void setStiffness(int index, btScalar stiffness, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the stiffness in necessary situations where otherwise the spring would move unrealistically too widely
- void setDamping(int index, btScalar damping, bool limitIfNeeded = true); // if limitIfNeeded is true the system will automatically limit the damping in necessary situations where otherwise the spring would blow up
- void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
- void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
- void setEquilibriumPoint(int index, btScalar val);
-
- //override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- //If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
- virtual btScalar getParam(int num, int axis = -1) const;
-
- static btScalar btGetMatrixElem(const btMatrix3x3& mat, int index);
- static bool matrixToEulerXYZ(const btMatrix3x3& mat, btVector3& xyz);
- static bool matrixToEulerXZY(const btMatrix3x3& mat, btVector3& xyz);
- static bool matrixToEulerYXZ(const btMatrix3x3& mat, btVector3& xyz);
- static bool matrixToEulerYZX(const btMatrix3x3& mat, btVector3& xyz);
- static bool matrixToEulerZXY(const btMatrix3x3& mat, btVector3& xyz);
- static bool matrixToEulerZYX(const btMatrix3x3& mat, btVector3& xyz);
-};
-
-struct btGeneric6DofSpring2ConstraintData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame;
- btTransformFloatData m_rbBFrame;
-
- btVector3FloatData m_linearUpperLimit;
- btVector3FloatData m_linearLowerLimit;
- btVector3FloatData m_linearBounce;
- btVector3FloatData m_linearStopERP;
- btVector3FloatData m_linearStopCFM;
- btVector3FloatData m_linearMotorERP;
- btVector3FloatData m_linearMotorCFM;
- btVector3FloatData m_linearTargetVelocity;
- btVector3FloatData m_linearMaxMotorForce;
- btVector3FloatData m_linearServoTarget;
- btVector3FloatData m_linearSpringStiffness;
- btVector3FloatData m_linearSpringDamping;
- btVector3FloatData m_linearEquilibriumPoint;
- char m_linearEnableMotor[4];
- char m_linearServoMotor[4];
- char m_linearEnableSpring[4];
- char m_linearSpringStiffnessLimited[4];
- char m_linearSpringDampingLimited[4];
- char m_padding1[4];
-
- btVector3FloatData m_angularUpperLimit;
- btVector3FloatData m_angularLowerLimit;
- btVector3FloatData m_angularBounce;
- btVector3FloatData m_angularStopERP;
- btVector3FloatData m_angularStopCFM;
- btVector3FloatData m_angularMotorERP;
- btVector3FloatData m_angularMotorCFM;
- btVector3FloatData m_angularTargetVelocity;
- btVector3FloatData m_angularMaxMotorForce;
- btVector3FloatData m_angularServoTarget;
- btVector3FloatData m_angularSpringStiffness;
- btVector3FloatData m_angularSpringDamping;
- btVector3FloatData m_angularEquilibriumPoint;
- char m_angularEnableMotor[4];
- char m_angularServoMotor[4];
- char m_angularEnableSpring[4];
- char m_angularSpringStiffnessLimited[4];
- char m_angularSpringDampingLimited[4];
-
- int m_rotateOrder;
-};
-
-struct btGeneric6DofSpring2ConstraintDoubleData2
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame;
- btTransformDoubleData m_rbBFrame;
-
- btVector3DoubleData m_linearUpperLimit;
- btVector3DoubleData m_linearLowerLimit;
- btVector3DoubleData m_linearBounce;
- btVector3DoubleData m_linearStopERP;
- btVector3DoubleData m_linearStopCFM;
- btVector3DoubleData m_linearMotorERP;
- btVector3DoubleData m_linearMotorCFM;
- btVector3DoubleData m_linearTargetVelocity;
- btVector3DoubleData m_linearMaxMotorForce;
- btVector3DoubleData m_linearServoTarget;
- btVector3DoubleData m_linearSpringStiffness;
- btVector3DoubleData m_linearSpringDamping;
- btVector3DoubleData m_linearEquilibriumPoint;
- char m_linearEnableMotor[4];
- char m_linearServoMotor[4];
- char m_linearEnableSpring[4];
- char m_linearSpringStiffnessLimited[4];
- char m_linearSpringDampingLimited[4];
- char m_padding1[4];
-
- btVector3DoubleData m_angularUpperLimit;
- btVector3DoubleData m_angularLowerLimit;
- btVector3DoubleData m_angularBounce;
- btVector3DoubleData m_angularStopERP;
- btVector3DoubleData m_angularStopCFM;
- btVector3DoubleData m_angularMotorERP;
- btVector3DoubleData m_angularMotorCFM;
- btVector3DoubleData m_angularTargetVelocity;
- btVector3DoubleData m_angularMaxMotorForce;
- btVector3DoubleData m_angularServoTarget;
- btVector3DoubleData m_angularSpringStiffness;
- btVector3DoubleData m_angularSpringDamping;
- btVector3DoubleData m_angularEquilibriumPoint;
- char m_angularEnableMotor[4];
- char m_angularServoMotor[4];
- char m_angularEnableSpring[4];
- char m_angularSpringStiffnessLimited[4];
- char m_angularSpringDampingLimited[4];
-
- int m_rotateOrder;
-};
-
-SIMD_FORCE_INLINE int btGeneric6DofSpring2Constraint::calculateSerializeBufferSize() const
-{
- return sizeof(btGeneric6DofSpring2ConstraintData2);
-}
-
-SIMD_FORCE_INLINE const char* btGeneric6DofSpring2Constraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btGeneric6DofSpring2ConstraintData2* dof = (btGeneric6DofSpring2ConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&dof->m_typeConstraintData, serializer);
-
- m_frameInA.serialize(dof->m_rbAFrame);
- m_frameInB.serialize(dof->m_rbBFrame);
-
- int i;
- for (i = 0; i < 3; i++)
- {
- dof->m_angularLowerLimit.m_floats[i] = m_angularLimits[i].m_loLimit;
- dof->m_angularUpperLimit.m_floats[i] = m_angularLimits[i].m_hiLimit;
- dof->m_angularBounce.m_floats[i] = m_angularLimits[i].m_bounce;
- dof->m_angularStopERP.m_floats[i] = m_angularLimits[i].m_stopERP;
- dof->m_angularStopCFM.m_floats[i] = m_angularLimits[i].m_stopCFM;
- dof->m_angularMotorERP.m_floats[i] = m_angularLimits[i].m_motorERP;
- dof->m_angularMotorCFM.m_floats[i] = m_angularLimits[i].m_motorCFM;
- dof->m_angularTargetVelocity.m_floats[i] = m_angularLimits[i].m_targetVelocity;
- dof->m_angularMaxMotorForce.m_floats[i] = m_angularLimits[i].m_maxMotorForce;
- dof->m_angularServoTarget.m_floats[i] = m_angularLimits[i].m_servoTarget;
- dof->m_angularSpringStiffness.m_floats[i] = m_angularLimits[i].m_springStiffness;
- dof->m_angularSpringDamping.m_floats[i] = m_angularLimits[i].m_springDamping;
- dof->m_angularEquilibriumPoint.m_floats[i] = m_angularLimits[i].m_equilibriumPoint;
- }
- dof->m_angularLowerLimit.m_floats[3] = 0;
- dof->m_angularUpperLimit.m_floats[3] = 0;
- dof->m_angularBounce.m_floats[3] = 0;
- dof->m_angularStopERP.m_floats[3] = 0;
- dof->m_angularStopCFM.m_floats[3] = 0;
- dof->m_angularMotorERP.m_floats[3] = 0;
- dof->m_angularMotorCFM.m_floats[3] = 0;
- dof->m_angularTargetVelocity.m_floats[3] = 0;
- dof->m_angularMaxMotorForce.m_floats[3] = 0;
- dof->m_angularServoTarget.m_floats[3] = 0;
- dof->m_angularSpringStiffness.m_floats[3] = 0;
- dof->m_angularSpringDamping.m_floats[3] = 0;
- dof->m_angularEquilibriumPoint.m_floats[3] = 0;
- for (i = 0; i < 4; i++)
- {
- dof->m_angularEnableMotor[i] = i < 3 ? (m_angularLimits[i].m_enableMotor ? 1 : 0) : 0;
- dof->m_angularServoMotor[i] = i < 3 ? (m_angularLimits[i].m_servoMotor ? 1 : 0) : 0;
- dof->m_angularEnableSpring[i] = i < 3 ? (m_angularLimits[i].m_enableSpring ? 1 : 0) : 0;
- dof->m_angularSpringStiffnessLimited[i] = i < 3 ? (m_angularLimits[i].m_springStiffnessLimited ? 1 : 0) : 0;
- dof->m_angularSpringDampingLimited[i] = i < 3 ? (m_angularLimits[i].m_springDampingLimited ? 1 : 0) : 0;
- }
-
- m_linearLimits.m_lowerLimit.serialize(dof->m_linearLowerLimit);
- m_linearLimits.m_upperLimit.serialize(dof->m_linearUpperLimit);
- m_linearLimits.m_bounce.serialize(dof->m_linearBounce);
- m_linearLimits.m_stopERP.serialize(dof->m_linearStopERP);
- m_linearLimits.m_stopCFM.serialize(dof->m_linearStopCFM);
- m_linearLimits.m_motorERP.serialize(dof->m_linearMotorERP);
- m_linearLimits.m_motorCFM.serialize(dof->m_linearMotorCFM);
- m_linearLimits.m_targetVelocity.serialize(dof->m_linearTargetVelocity);
- m_linearLimits.m_maxMotorForce.serialize(dof->m_linearMaxMotorForce);
- m_linearLimits.m_servoTarget.serialize(dof->m_linearServoTarget);
- m_linearLimits.m_springStiffness.serialize(dof->m_linearSpringStiffness);
- m_linearLimits.m_springDamping.serialize(dof->m_linearSpringDamping);
- m_linearLimits.m_equilibriumPoint.serialize(dof->m_linearEquilibriumPoint);
- for (i = 0; i < 4; i++)
- {
- dof->m_linearEnableMotor[i] = i < 3 ? (m_linearLimits.m_enableMotor[i] ? 1 : 0) : 0;
- dof->m_linearServoMotor[i] = i < 3 ? (m_linearLimits.m_servoMotor[i] ? 1 : 0) : 0;
- dof->m_linearEnableSpring[i] = i < 3 ? (m_linearLimits.m_enableSpring[i] ? 1 : 0) : 0;
- dof->m_linearSpringStiffnessLimited[i] = i < 3 ? (m_linearLimits.m_springStiffnessLimited[i] ? 1 : 0) : 0;
- dof->m_linearSpringDampingLimited[i] = i < 3 ? (m_linearLimits.m_springDampingLimited[i] ? 1 : 0) : 0;
- }
-
- dof->m_rotateOrder = m_rotateOrder;
-
- dof->m_padding1[0] = 0;
- dof->m_padding1[1] = 0;
- dof->m_padding1[2] = 0;
- dof->m_padding1[3] = 0;
-
- return btGeneric6DofSpring2ConstraintDataName;
-}
-
-#endif //BT_GENERIC_6DOF_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
deleted file mode 100644
index 8baf52bcd1..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGeneric6DofSpringConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-
-btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btGeneric6DofConstraint(rbA, rbB, frameInA, frameInB, useLinearReferenceFrameA)
-{
- init();
-}
-
-btGeneric6DofSpringConstraint::btGeneric6DofSpringConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
- : btGeneric6DofConstraint(rbB, frameInB, useLinearReferenceFrameB)
-{
- init();
-}
-
-void btGeneric6DofSpringConstraint::init()
-{
- m_objectType = D6_SPRING_CONSTRAINT_TYPE;
-
- for (int i = 0; i < 6; i++)
- {
- m_springEnabled[i] = false;
- m_equilibriumPoint[i] = btScalar(0.f);
- m_springStiffness[i] = btScalar(0.f);
- m_springDamping[i] = btScalar(1.f);
- }
-}
-
-void btGeneric6DofSpringConstraint::enableSpring(int index, bool onOff)
-{
- btAssert((index >= 0) && (index < 6));
- m_springEnabled[index] = onOff;
- if (index < 3)
- {
- m_linearLimits.m_enableMotor[index] = onOff;
- }
- else
- {
- m_angularLimits[index - 3].m_enableMotor = onOff;
- }
-}
-
-void btGeneric6DofSpringConstraint::setStiffness(int index, btScalar stiffness)
-{
- btAssert((index >= 0) && (index < 6));
- m_springStiffness[index] = stiffness;
-}
-
-void btGeneric6DofSpringConstraint::setDamping(int index, btScalar damping)
-{
- btAssert((index >= 0) && (index < 6));
- m_springDamping[index] = damping;
-}
-
-void btGeneric6DofSpringConstraint::setEquilibriumPoint()
-{
- calculateTransforms();
- int i;
-
- for (i = 0; i < 3; i++)
- {
- m_equilibriumPoint[i] = m_calculatedLinearDiff[i];
- }
- for (i = 0; i < 3; i++)
- {
- m_equilibriumPoint[i + 3] = m_calculatedAxisAngleDiff[i];
- }
-}
-
-void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index)
-{
- btAssert((index >= 0) && (index < 6));
- calculateTransforms();
- if (index < 3)
- {
- m_equilibriumPoint[index] = m_calculatedLinearDiff[index];
- }
- else
- {
- m_equilibriumPoint[index] = m_calculatedAxisAngleDiff[index - 3];
- }
-}
-
-void btGeneric6DofSpringConstraint::setEquilibriumPoint(int index, btScalar val)
-{
- btAssert((index >= 0) && (index < 6));
- m_equilibriumPoint[index] = val;
-}
-
-void btGeneric6DofSpringConstraint::internalUpdateSprings(btConstraintInfo2* info)
-{
- // it is assumed that calculateTransforms() have been called before this call
- int i;
- //btVector3 relVel = m_rbB.getLinearVelocity() - m_rbA.getLinearVelocity();
- for (i = 0; i < 3; i++)
- {
- if (m_springEnabled[i])
- {
- // get current position of constraint
- btScalar currPos = m_calculatedLinearDiff[i];
- // calculate difference
- btScalar delta = currPos - m_equilibriumPoint[i];
- // spring force is (delta * m_stiffness) according to Hooke's Law
- btScalar force = delta * m_springStiffness[i];
- btScalar velFactor = info->fps * m_springDamping[i] / btScalar(info->m_numIterations);
- m_linearLimits.m_targetVelocity[i] = velFactor * force;
- m_linearLimits.m_maxMotorForce[i] = btFabs(force);
- }
- }
- for (i = 0; i < 3; i++)
- {
- if (m_springEnabled[i + 3])
- {
- // get current position of constraint
- btScalar currPos = m_calculatedAxisAngleDiff[i];
- // calculate difference
- btScalar delta = currPos - m_equilibriumPoint[i + 3];
- // spring force is (-delta * m_stiffness) according to Hooke's Law
- btScalar force = -delta * m_springStiffness[i + 3];
- btScalar velFactor = info->fps * m_springDamping[i + 3] / btScalar(info->m_numIterations);
- m_angularLimits[i].m_targetVelocity = velFactor * force;
- m_angularLimits[i].m_maxMotorForce = btFabs(force);
- }
- }
-}
-
-void btGeneric6DofSpringConstraint::getInfo2(btConstraintInfo2* info)
-{
- // this will be called by constraint solver at the constraint setup stage
- // set current motor parameters
- internalUpdateSprings(info);
- // do the rest of job for constraint setup
- btGeneric6DofConstraint::getInfo2(info);
-}
-
-void btGeneric6DofSpringConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
-{
- btVector3 zAxis = axis1.normalized();
- btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
-
- // now get constraint frame in local coordinate systems
- m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
- calculateTransforms();
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
deleted file mode 100644
index 02b9d4d05d..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
-#define BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btTypedConstraint.h"
-#include "btGeneric6DofConstraint.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintDoubleData2
-#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintDoubleData2"
-#else
-#define btGeneric6DofSpringConstraintData2 btGeneric6DofSpringConstraintData
-#define btGeneric6DofSpringConstraintDataName "btGeneric6DofSpringConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-/// Generic 6 DOF constraint that allows to set spring motors to any translational and rotational DOF
-
-/// DOF index used in enableSpring() and setStiffness() means:
-/// 0 : translation X
-/// 1 : translation Y
-/// 2 : translation Z
-/// 3 : rotation X (3rd Euler rotational around new position of X axis, range [-PI+epsilon, PI-epsilon] )
-/// 4 : rotation Y (2nd Euler rotational around new position of Y axis, range [-PI/2+epsilon, PI/2-epsilon] )
-/// 5 : rotation Z (1st Euler rotational around Z axis, range [-PI+epsilon, PI-epsilon] )
-
-ATTRIBUTE_ALIGNED16(class)
-btGeneric6DofSpringConstraint : public btGeneric6DofConstraint
-{
-protected:
- bool m_springEnabled[6];
- btScalar m_equilibriumPoint[6];
- btScalar m_springStiffness[6];
- btScalar m_springDamping[6]; // between 0 and 1 (1 == no damping)
- void init();
- void internalUpdateSprings(btConstraintInfo2 * info);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btGeneric6DofSpringConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
- btGeneric6DofSpringConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
- void enableSpring(int index, bool onOff);
- void setStiffness(int index, btScalar stiffness);
- void setDamping(int index, btScalar damping);
- void setEquilibriumPoint(); // set the current constraint position/orientation as an equilibrium point for all DOF
- void setEquilibriumPoint(int index); // set the current constraint position/orientation as an equilibrium point for given DOF
- void setEquilibriumPoint(int index, btScalar val);
-
- bool isSpringEnabled(int index) const
- {
- return m_springEnabled[index];
- }
-
- btScalar getStiffness(int index) const
- {
- return m_springStiffness[index];
- }
-
- btScalar getDamping(int index) const
- {
- return m_springDamping[index];
- }
-
- btScalar getEquilibriumPoint(int index) const
- {
- return m_equilibriumPoint[index];
- }
-
- virtual void setAxis(const btVector3& axis1, const btVector3& axis2);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- virtual int calculateSerializeBufferSize() const;
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-struct btGeneric6DofSpringConstraintData
-{
- btGeneric6DofConstraintData m_6dofData;
-
- int m_springEnabled[6];
- float m_equilibriumPoint[6];
- float m_springStiffness[6];
- float m_springDamping[6];
-};
-
-struct btGeneric6DofSpringConstraintDoubleData2
-{
- btGeneric6DofConstraintDoubleData2 m_6dofData;
-
- int m_springEnabled[6];
- double m_equilibriumPoint[6];
- double m_springStiffness[6];
- double m_springDamping[6];
-};
-
-SIMD_FORCE_INLINE int btGeneric6DofSpringConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btGeneric6DofSpringConstraintData2);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btGeneric6DofSpringConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btGeneric6DofSpringConstraintData2* dof = (btGeneric6DofSpringConstraintData2*)dataBuffer;
- btGeneric6DofConstraint::serialize(&dof->m_6dofData, serializer);
-
- int i;
- for (i = 0; i < 6; i++)
- {
- dof->m_equilibriumPoint[i] = m_equilibriumPoint[i];
- dof->m_springDamping[i] = m_springDamping[i];
- dof->m_springEnabled[i] = m_springEnabled[i] ? 1 : 0;
- dof->m_springStiffness[i] = m_springStiffness[i];
- }
- return btGeneric6DofSpringConstraintDataName;
-}
-
-#endif // BT_GENERIC_6DOF_SPRING_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
deleted file mode 100644
index 6507e1a0a7..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btHinge2Constraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-
-// constructor
-// anchor, axis1 and axis2 are in world coordinate system
-// axis1 must be orthogonal to axis2
-btHinge2Constraint::btHinge2Constraint(btRigidBody& rbA, btRigidBody& rbB, btVector3& anchor, btVector3& axis1, btVector3& axis2)
- : btGeneric6DofSpring2Constraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), RO_XYZ),
- m_anchor(anchor),
- m_axis1(axis1),
- m_axis2(axis2)
-{
- // build frame basis
- // 6DOF constraint uses Euler angles and to define limits
- // it is assumed that rotational order is :
- // Z - first, allowed limits are (-PI,PI);
- // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
- // used to prevent constraint from instability on poles;
- // new position of X, allowed limits are (-PI,PI);
- // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
- // Build the frame in world coordinate system first
- btVector3 zAxis = axis1.normalize();
- btVector3 xAxis = axis2.normalize();
- btVector3 yAxis = zAxis.cross(xAxis); // we want right coordinate system
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
- frameInW.setOrigin(anchor);
- // now get constraint frame in local coordinate systems
- m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
- // sei limits
- setLinearLowerLimit(btVector3(0.f, 0.f, -1.f));
- setLinearUpperLimit(btVector3(0.f, 0.f, 1.f));
- // like front wheels of a car
- setAngularLowerLimit(btVector3(1.f, 0.f, -SIMD_HALF_PI * 0.5f));
- setAngularUpperLimit(btVector3(-1.f, 0.f, SIMD_HALF_PI * 0.5f));
- // enable suspension
- enableSpring(2, true);
- setStiffness(2, SIMD_PI * SIMD_PI * 4.f);
- setDamping(2, 0.01f);
- setEquilibriumPoint();
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
deleted file mode 100644
index 95f604a890..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHinge2Constraint.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_HINGE2_CONSTRAINT_H
-#define BT_HINGE2_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btTypedConstraint.h"
-#include "btGeneric6DofSpring2Constraint.h"
-
-// Constraint similar to ODE Hinge2 Joint
-// has 3 degrees of frredom:
-// 2 rotational degrees of freedom, similar to Euler rotations around Z (axis 1) and X (axis 2)
-// 1 translational (along axis Z) with suspension spring
-
-ATTRIBUTE_ALIGNED16(class)
-btHinge2Constraint : public btGeneric6DofSpring2Constraint
-{
-protected:
- btVector3 m_anchor;
- btVector3 m_axis1;
- btVector3 m_axis2;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- // constructor
- // anchor, axis1 and axis2 are in world coordinate system
- // axis1 must be orthogonal to axis2
- btHinge2Constraint(btRigidBody & rbA, btRigidBody & rbB, btVector3 & anchor, btVector3 & axis1, btVector3 & axis2);
- // access
- const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
- const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
- const btVector3& getAxis1() { return m_axis1; }
- const btVector3& getAxis2() { return m_axis2; }
- btScalar getAngle1() { return getAngle(2); }
- btScalar getAngle2() { return getAngle(0); }
- // limits
- void setUpperLimit(btScalar ang1max) { setAngularUpperLimit(btVector3(-1.f, 0.f, ang1max)); }
- void setLowerLimit(btScalar ang1min) { setAngularLowerLimit(btVector3(1.f, 0.f, ang1min)); }
-};
-
-#endif // BT_HINGE2_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
deleted file mode 100644
index aa6f69000d..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp
+++ /dev/null
@@ -1,1083 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btHingeConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btMinMax.h"
-#include <new>
-#include "btSolverBody.h"
-
-//#define HINGE_USE_OBSOLETE_SOLVER false
-#define HINGE_USE_OBSOLETE_SOLVER false
-
-#define HINGE_USE_FRAME_OFFSET true
-
-#ifndef __SPU__
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB,
- const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA)
- : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB),
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit(),
-#endif
- m_angularOnly(false),
- m_enableAngularMotor(false),
- m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
- m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
- m_useReferenceFrameA(useReferenceFrameA),
- m_flags(0),
- m_normalCFM(0),
- m_normalERP(0),
- m_stopCFM(0),
- m_stopERP(0)
-{
- m_rbAFrame.getOrigin() = pivotInA;
-
- // since no frame is given, assume this to be zero angle and just pick rb transform axis
- btVector3 rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(0);
-
- btVector3 rbAxisA2;
- btScalar projection = axisInA.dot(rbAxisA1);
- if (projection >= 1.0f - SIMD_EPSILON)
- {
- rbAxisA1 = -rbA.getCenterOfMassTransform().getBasis().getColumn(2);
- rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
- }
- else if (projection <= -1.0f + SIMD_EPSILON)
- {
- rbAxisA1 = rbA.getCenterOfMassTransform().getBasis().getColumn(2);
- rbAxisA2 = rbA.getCenterOfMassTransform().getBasis().getColumn(1);
- }
- else
- {
- rbAxisA2 = axisInA.cross(rbAxisA1);
- rbAxisA1 = rbAxisA2.cross(axisInA);
- }
-
- m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
- rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
- rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
-
- btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
- btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
-
- m_rbBFrame.getOrigin() = pivotInB;
- m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
- rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
- rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
-
-#ifndef _BT_USE_CENTER_LIMIT_
- //start with free
- m_lowerLimit = btScalar(1.0f);
- m_upperLimit = btScalar(-1.0f);
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-#endif
- m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
-}
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA)
- : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit(),
-#endif
- m_angularOnly(false),
- m_enableAngularMotor(false),
- m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
- m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
- m_useReferenceFrameA(useReferenceFrameA),
- m_flags(0),
- m_normalCFM(0),
- m_normalERP(0),
- m_stopCFM(0),
- m_stopERP(0)
-{
- // since no frame is given, assume this to be zero angle and just pick rb transform axis
- // fixed axis in worldspace
- btVector3 rbAxisA1, rbAxisA2;
- btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
-
- m_rbAFrame.getOrigin() = pivotInA;
- m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
- rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
- rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
-
- btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
-
- btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
- btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
-
- m_rbBFrame.getOrigin() = rbA.getCenterOfMassTransform()(pivotInA);
- m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
- rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
- rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
-
-#ifndef _BT_USE_CENTER_LIMIT_
- //start with free
- m_lowerLimit = btScalar(1.0f);
- m_upperLimit = btScalar(-1.0f);
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-#endif
- m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
-}
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA, btRigidBody& rbB,
- const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
- : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA, rbB), m_rbAFrame(rbAFrame), m_rbBFrame(rbBFrame),
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit(),
-#endif
- m_angularOnly(false),
- m_enableAngularMotor(false),
- m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
- m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
- m_useReferenceFrameA(useReferenceFrameA),
- m_flags(0),
- m_normalCFM(0),
- m_normalERP(0),
- m_stopCFM(0),
- m_stopERP(0)
-{
-#ifndef _BT_USE_CENTER_LIMIT_
- //start with free
- m_lowerLimit = btScalar(1.0f);
- m_upperLimit = btScalar(-1.0f);
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-#endif
- m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
-}
-
-btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
- : btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_rbAFrame(rbAFrame), m_rbBFrame(rbAFrame),
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit(),
-#endif
- m_angularOnly(false),
- m_enableAngularMotor(false),
- m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
- m_useOffsetForConstraintFrame(HINGE_USE_FRAME_OFFSET),
- m_useReferenceFrameA(useReferenceFrameA),
- m_flags(0),
- m_normalCFM(0),
- m_normalERP(0),
- m_stopCFM(0),
- m_stopERP(0)
-{
- ///not providing rigidbody B means implicitly using worldspace for body B
-
- m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
-#ifndef _BT_USE_CENTER_LIMIT_
- //start with free
- m_lowerLimit = btScalar(1.0f);
- m_upperLimit = btScalar(-1.0f);
- m_biasFactor = 0.3f;
- m_relaxationFactor = 1.0f;
- m_limitSoftness = 0.9f;
- m_solveLimit = false;
-#endif
- m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
-}
-
-void btHingeConstraint::buildJacobian()
-{
- if (m_useSolveConstraintObsolete)
- {
- m_appliedImpulse = btScalar(0.);
- m_accMotorImpulse = btScalar(0.);
-
- if (!m_angularOnly)
- {
- btVector3 pivotAInW = m_rbA.getCenterOfMassTransform() * m_rbAFrame.getOrigin();
- btVector3 pivotBInW = m_rbB.getCenterOfMassTransform() * m_rbBFrame.getOrigin();
- btVector3 relPos = pivotBInW - pivotAInW;
-
- btVector3 normal[3];
- if (relPos.length2() > SIMD_EPSILON)
- {
- normal[0] = relPos.normalized();
- }
- else
- {
- normal[0].setValue(btScalar(1.0), 0, 0);
- }
-
- btPlaneSpace1(normal[0], normal[1], normal[2]);
-
- for (int i = 0; i < 3; i++)
- {
- new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- pivotAInW - m_rbA.getCenterOfMassPosition(),
- pivotBInW - m_rbB.getCenterOfMassPosition(),
- normal[i],
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
- }
- }
-
- //calculate two perpendicular jointAxis, orthogonal to hingeAxis
- //these two jointAxis require equal angular velocities for both bodies
-
- //this is unused for now, it's a todo
- btVector3 jointAxis0local;
- btVector3 jointAxis1local;
-
- btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2), jointAxis0local, jointAxis1local);
-
- btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
- btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
- btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
-
- new (&m_jacAng[0]) btJacobianEntry(jointAxis0,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- new (&m_jacAng[1]) btJacobianEntry(jointAxis1,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- new (&m_jacAng[2]) btJacobianEntry(hingeAxisWorld,
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getInvInertiaDiagLocal(),
- m_rbB.getInvInertiaDiagLocal());
-
- // clear accumulator
- m_accLimitImpulse = btScalar(0.);
-
- // test angular limit
- testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-
- //Compute K = J*W*J' for hinge axis
- btVector3 axisA = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
- m_kHinge = 1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
- getRigidBodyB().computeAngularImpulseDenominator(axisA));
- }
-}
-
-#endif //__SPU__
-
-static inline btScalar btNormalizeAnglePositive(btScalar angle)
-{
- return btFmod(btFmod(angle, btScalar(2.0 * SIMD_PI)) + btScalar(2.0 * SIMD_PI), btScalar(2.0 * SIMD_PI));
-}
-
-static btScalar btShortestAngularDistance(btScalar accAngle, btScalar curAngle)
-{
- btScalar result = btNormalizeAngle(btNormalizeAnglePositive(btNormalizeAnglePositive(curAngle) -
- btNormalizeAnglePositive(accAngle)));
- return result;
-}
-
-static btScalar btShortestAngleUpdate(btScalar accAngle, btScalar curAngle)
-{
- btScalar tol(0.3);
- btScalar result = btShortestAngularDistance(accAngle, curAngle);
-
- if (btFabs(result) > tol)
- return curAngle;
- else
- return accAngle + result;
-
- return curAngle;
-}
-
-btScalar btHingeAccumulatedAngleConstraint::getAccumulatedHingeAngle()
-{
- btScalar hingeAngle = getHingeAngle();
- m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, hingeAngle);
- return m_accumulatedAngle;
-}
-void btHingeAccumulatedAngleConstraint::setAccumulatedHingeAngle(btScalar accAngle)
-{
- m_accumulatedAngle = accAngle;
-}
-
-void btHingeAccumulatedAngleConstraint::getInfo1(btConstraintInfo1* info)
-{
- //update m_accumulatedAngle
- btScalar curHingeAngle = getHingeAngle();
- m_accumulatedAngle = btShortestAngleUpdate(m_accumulatedAngle, curHingeAngle);
-
- btHingeConstraint::getInfo1(info);
-}
-
-void btHingeConstraint::getInfo1(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
- info->nub = 1;
- //always add the row, to avoid computation (data is not available yet)
- //prepare constraint
- testLimit(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- if (getSolveLimit() || getEnableAngularMotor())
- {
- info->m_numConstraintRows++; // limit 3rd anguar as well
- info->nub--;
- }
- }
-}
-
-void btHingeConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- //always add the 'limit' row, to avoid computation (data is not available yet)
- info->m_numConstraintRows = 6; // Fixed 3 linear + 2 angular
- info->nub = 0;
- }
-}
-
-void btHingeConstraint::getInfo2(btConstraintInfo2* info)
-{
- if (m_useOffsetForConstraintFrame)
- {
- getInfo2InternalUsingFrameOffset(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
- }
- else
- {
- getInfo2Internal(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getAngularVelocity(), m_rbB.getAngularVelocity());
- }
-}
-
-void btHingeConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
-{
- ///the regular (virtual) implementation getInfo2 already performs 'testLimit' during getInfo1, so we need to do it now
- testLimit(transA, transB);
-
- getInfo2Internal(info, transA, transB, angVelA, angVelB);
-}
-
-void btHingeConstraint::getInfo2Internal(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
-{
- btAssert(!m_useSolveConstraintObsolete);
- int i, skip = info->rowskip;
- // transforms in world space
- btTransform trA = transA * m_rbAFrame;
- btTransform trB = transB * m_rbBFrame;
- // pivot point
- btVector3 pivotAInW = trA.getOrigin();
- btVector3 pivotBInW = trB.getOrigin();
-#if 0
- if (0)
- {
- for (i=0;i<6;i++)
- {
- info->m_J1linearAxis[i*skip]=0;
- info->m_J1linearAxis[i*skip+1]=0;
- info->m_J1linearAxis[i*skip+2]=0;
-
- info->m_J1angularAxis[i*skip]=0;
- info->m_J1angularAxis[i*skip+1]=0;
- info->m_J1angularAxis[i*skip+2]=0;
-
- info->m_J2linearAxis[i*skip]=0;
- info->m_J2linearAxis[i*skip+1]=0;
- info->m_J2linearAxis[i*skip+2]=0;
-
- info->m_J2angularAxis[i*skip]=0;
- info->m_J2angularAxis[i*skip+1]=0;
- info->m_J2angularAxis[i*skip+2]=0;
-
- info->m_constraintError[i*skip]=0.f;
- }
- }
-#endif //#if 0
- // linear (all fixed)
-
- if (!m_angularOnly)
- {
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[skip + 1] = 1;
- info->m_J1linearAxis[2 * skip + 2] = 1;
-
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[skip + 1] = -1;
- info->m_J2linearAxis[2 * skip + 2] = -1;
- }
-
- btVector3 a1 = pivotAInW - transA.getOrigin();
- {
- btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + skip);
- btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * skip);
- btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
- btVector3 a2 = pivotBInW - transB.getOrigin();
- {
- btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + skip);
- btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * skip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
- // linear RHS
- btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
-
- btScalar k = info->fps * normalErp;
- if (!m_angularOnly)
- {
- for (i = 0; i < 3; i++)
- {
- info->m_constraintError[i * skip] = k * (pivotBInW[i] - pivotAInW[i]);
- }
- }
- // make rotations around X and Y equal
- // the hinge axis should be the only unconstrained
- // rotational axis, the angular velocity of the two bodies perpendicular to
- // the hinge axis should be equal. thus the constraint equations are
- // p*w1 - p*w2 = 0
- // q*w1 - q*w2 = 0
- // where p and q are unit vectors normal to the hinge axis, and w1 and w2
- // are the angular velocity vectors of the two bodies.
- // get hinge axis (Z)
- btVector3 ax1 = trA.getBasis().getColumn(2);
- // get 2 orthos to hinge axis (X, Y)
- btVector3 p = trA.getBasis().getColumn(0);
- btVector3 q = trA.getBasis().getColumn(1);
- // set the two hinge angular rows
- int s3 = 3 * info->rowskip;
- int s4 = 4 * info->rowskip;
-
- info->m_J1angularAxis[s3 + 0] = p[0];
- info->m_J1angularAxis[s3 + 1] = p[1];
- info->m_J1angularAxis[s3 + 2] = p[2];
- info->m_J1angularAxis[s4 + 0] = q[0];
- info->m_J1angularAxis[s4 + 1] = q[1];
- info->m_J1angularAxis[s4 + 2] = q[2];
-
- info->m_J2angularAxis[s3 + 0] = -p[0];
- info->m_J2angularAxis[s3 + 1] = -p[1];
- info->m_J2angularAxis[s3 + 2] = -p[2];
- info->m_J2angularAxis[s4 + 0] = -q[0];
- info->m_J2angularAxis[s4 + 1] = -q[1];
- info->m_J2angularAxis[s4 + 2] = -q[2];
- // compute the right hand side of the constraint equation. set relative
- // body velocities along p and q to bring the hinge back into alignment.
- // if ax1,ax2 are the unit length hinge axes as computed from body1 and
- // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
- // if `theta' is the angle between ax1 and ax2, we need an angular velocity
- // along u to cover angle erp*theta in one step :
- // |angular_velocity| = angle/time = erp*theta / stepsize
- // = (erp*fps) * theta
- // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
- // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
- // ...as ax1 and ax2 are unit length. if theta is smallish,
- // theta ~= sin(theta), so
- // angular_velocity = (erp*fps) * (ax1 x ax2)
- // ax1 x ax2 is in the plane space of ax1, so we project the angular
- // velocity to p and q to find the right hand side.
- btVector3 ax2 = trB.getBasis().getColumn(2);
- btVector3 u = ax1.cross(ax2);
- info->m_constraintError[s3] = k * u.dot(p);
- info->m_constraintError[s4] = k * u.dot(q);
- // check angular limits
- int nrow = 4; // last filled row
- int srow;
- btScalar limit_err = btScalar(0.0);
- int limit = 0;
- if (getSolveLimit())
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- limit_err = m_limit.getCorrection() * m_referenceSign;
-#else
- limit_err = m_correction * m_referenceSign;
-#endif
- limit = (limit_err > btScalar(0.0)) ? 1 : 2;
- }
- // if the hinge has joint limits or motor, add in the extra row
- bool powered = getEnableAngularMotor();
- if (limit || powered)
- {
- nrow++;
- srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow + 0] = ax1[0];
- info->m_J1angularAxis[srow + 1] = ax1[1];
- info->m_J1angularAxis[srow + 2] = ax1[2];
-
- info->m_J2angularAxis[srow + 0] = -ax1[0];
- info->m_J2angularAxis[srow + 1] = -ax1[1];
- info->m_J2angularAxis[srow + 2] = -ax1[2];
-
- btScalar lostop = getLowerLimit();
- btScalar histop = getUpperLimit();
- if (limit && (lostop == histop))
- { // the joint motor is ineffective
- powered = false;
- }
- info->m_constraintError[srow] = btScalar(0.0f);
- btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
- if (powered)
- {
- if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
- {
- info->cfm[srow] = m_normalCFM;
- }
- btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
- info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
- info->m_lowerLimit[srow] = -m_maxMotorImpulse;
- info->m_upperLimit[srow] = m_maxMotorImpulse;
- }
- if (limit)
- {
- k = info->fps * currERP;
- info->m_constraintError[srow] += k * limit_err;
- if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
- {
- info->cfm[srow] = m_stopCFM;
- }
- if (lostop == histop)
- {
- // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else if (limit == 1)
- { // low limit
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- { // high limit
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
-#ifdef _BT_USE_CENTER_LIMIT_
- btScalar bounce = m_limit.getRelaxationFactor();
-#else
- btScalar bounce = m_relaxationFactor;
-#endif
- if (bounce > btScalar(0.0))
- {
- btScalar vel = angVelA.dot(ax1);
- vel -= angVelB.dot(ax1);
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- { // low limit
- if (vel < 0)
- {
- btScalar newc = -bounce * vel;
- if (newc > info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- else
- { // high limit - all those computations are reversed
- if (vel > 0)
- {
- btScalar newc = -bounce * vel;
- if (newc < info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
-#ifdef _BT_USE_CENTER_LIMIT_
- info->m_constraintError[srow] *= m_limit.getBiasFactor();
-#else
- info->m_constraintError[srow] *= m_biasFactor;
-#endif
- } // if(limit)
- } // if angular limit or powered
-}
-
-void btHingeConstraint::setFrames(const btTransform& frameA, const btTransform& frameB)
-{
- m_rbAFrame = frameA;
- m_rbBFrame = frameB;
- buildJacobian();
-}
-
-void btHingeConstraint::updateRHS(btScalar timeStep)
-{
- (void)timeStep;
-}
-
-btScalar btHingeConstraint::getHingeAngle()
-{
- return getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-}
-
-btScalar btHingeConstraint::getHingeAngle(const btTransform& transA, const btTransform& transB)
-{
- const btVector3 refAxis0 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(0);
- const btVector3 refAxis1 = transA.getBasis() * m_rbAFrame.getBasis().getColumn(1);
- const btVector3 swingAxis = transB.getBasis() * m_rbBFrame.getBasis().getColumn(1);
- // btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
- btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
- return m_referenceSign * angle;
-}
-
-void btHingeConstraint::testLimit(const btTransform& transA, const btTransform& transB)
-{
- // Compute limit information
- m_hingeAngle = getHingeAngle(transA, transB);
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit.test(m_hingeAngle);
-#else
- m_correction = btScalar(0.);
- m_limitSign = btScalar(0.);
- m_solveLimit = false;
- if (m_lowerLimit <= m_upperLimit)
- {
- m_hingeAngle = btAdjustAngleToLimits(m_hingeAngle, m_lowerLimit, m_upperLimit);
- if (m_hingeAngle <= m_lowerLimit)
- {
- m_correction = (m_lowerLimit - m_hingeAngle);
- m_limitSign = 1.0f;
- m_solveLimit = true;
- }
- else if (m_hingeAngle >= m_upperLimit)
- {
- m_correction = m_upperLimit - m_hingeAngle;
- m_limitSign = -1.0f;
- m_solveLimit = true;
- }
- }
-#endif
- return;
-}
-
-static btVector3 vHinge(0, 0, btScalar(1));
-
-void btHingeConstraint::setMotorTarget(const btQuaternion& qAinB, btScalar dt)
-{
- // convert target from body to constraint space
- btQuaternion qConstraint = m_rbBFrame.getRotation().inverse() * qAinB * m_rbAFrame.getRotation();
- qConstraint.normalize();
-
- // extract "pure" hinge component
- btVector3 vNoHinge = quatRotate(qConstraint, vHinge);
- vNoHinge.normalize();
- btQuaternion qNoHinge = shortestArcQuat(vHinge, vNoHinge);
- btQuaternion qHinge = qNoHinge.inverse() * qConstraint;
- qHinge.normalize();
-
- // compute angular target, clamped to limits
- btScalar targetAngle = qHinge.getAngle();
- if (targetAngle > SIMD_PI) // long way around. flip quat and recalculate.
- {
- qHinge = -(qHinge);
- targetAngle = qHinge.getAngle();
- }
- if (qHinge.getZ() < 0)
- targetAngle = -targetAngle;
-
- setMotorTarget(targetAngle, dt);
-}
-
-void btHingeConstraint::setMotorTarget(btScalar targetAngle, btScalar dt)
-{
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit.fit(targetAngle);
-#else
- if (m_lowerLimit < m_upperLimit)
- {
- if (targetAngle < m_lowerLimit)
- targetAngle = m_lowerLimit;
- else if (targetAngle > m_upperLimit)
- targetAngle = m_upperLimit;
- }
-#endif
- // compute angular velocity
- btScalar curAngle = getHingeAngle(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- btScalar dAngle = targetAngle - curAngle;
- m_motorTargetVelocity = dAngle / dt;
-}
-
-void btHingeConstraint::getInfo2InternalUsingFrameOffset(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB)
-{
- btAssert(!m_useSolveConstraintObsolete);
- int i, s = info->rowskip;
- // transforms in world space
- btTransform trA = transA * m_rbAFrame;
- btTransform trB = transB * m_rbBFrame;
- // pivot point
-// btVector3 pivotAInW = trA.getOrigin();
-// btVector3 pivotBInW = trB.getOrigin();
-#if 1
- // difference between frames in WCS
- btVector3 ofs = trB.getOrigin() - trA.getOrigin();
- // now get weight factors depending on masses
- btScalar miA = getRigidBodyA().getInvMass();
- btScalar miB = getRigidBodyB().getInvMass();
- bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
- btScalar miS = miA + miB;
- btScalar factA, factB;
- if (miS > btScalar(0.f))
- {
- factA = miB / miS;
- }
- else
- {
- factA = btScalar(0.5f);
- }
- factB = btScalar(1.0f) - factA;
- // get the desired direction of hinge axis
- // as weighted sum of Z-orthos of frameA and frameB in WCS
- btVector3 ax1A = trA.getBasis().getColumn(2);
- btVector3 ax1B = trB.getBasis().getColumn(2);
- btVector3 ax1 = ax1A * factA + ax1B * factB;
- if (ax1.length2()<SIMD_EPSILON)
- {
- factA=0.f;
- factB=1.f;
- ax1 = ax1A * factA + ax1B * factB;
- }
- ax1.normalize();
- // fill first 3 rows
- // we want: velA + wA x relA == velB + wB x relB
- btTransform bodyA_trans = transA;
- btTransform bodyB_trans = transB;
- int s0 = 0;
- int s1 = s;
- int s2 = s * 2;
- int nrow = 2; // last filled row
- btVector3 tmpA, tmpB, relA, relB, p, q;
- // get vector from bodyB to frameB in WCS
- relB = trB.getOrigin() - bodyB_trans.getOrigin();
- // get its projection to hinge axis
- btVector3 projB = ax1 * relB.dot(ax1);
- // get vector directed from bodyB to hinge axis (and orthogonal to it)
- btVector3 orthoB = relB - projB;
- // same for bodyA
- relA = trA.getOrigin() - bodyA_trans.getOrigin();
- btVector3 projA = ax1 * relA.dot(ax1);
- btVector3 orthoA = relA - projA;
- btVector3 totalDist = projA - projB;
- // get offset vectors relA and relB
- relA = orthoA + totalDist * factA;
- relB = orthoB - totalDist * factB;
- // now choose average ortho to hinge axis
- p = orthoB * factA + orthoA * factB;
- btScalar len2 = p.length2();
- if (len2 > SIMD_EPSILON)
- {
- p /= btSqrt(len2);
- }
- else
- {
- p = trA.getBasis().getColumn(1);
- }
- // make one more ortho
- q = ax1.cross(p);
- // fill three rows
- tmpA = relA.cross(p);
- tmpB = relB.cross(p);
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s0 + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s0 + i] = -tmpB[i];
- tmpA = relA.cross(q);
- tmpB = relB.cross(q);
- if (hasStaticBody && getSolveLimit())
- { // to make constraint between static and dynamic objects more rigid
- // remove wA (or wB) from equation if angular limit is hit
- tmpB *= factB;
- tmpA *= factA;
- }
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s1 + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s1 + i] = -tmpB[i];
- tmpA = relA.cross(ax1);
- tmpB = relB.cross(ax1);
- if (hasStaticBody)
- { // to make constraint between static and dynamic objects more rigid
- // remove wA (or wB) from equation
- tmpB *= factB;
- tmpA *= factA;
- }
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
-
- btScalar normalErp = (m_flags & BT_HINGE_FLAGS_ERP_NORM) ? m_normalERP : info->erp;
- btScalar k = info->fps * normalErp;
-
- if (!m_angularOnly)
- {
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s0 + i] = p[i];
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s1 + i] = q[i];
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = ax1[i];
-
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s0 + i] = -p[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s1 + i] = -q[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -ax1[i];
-
- // compute three elements of right hand side
-
- btScalar rhs = k * p.dot(ofs);
- info->m_constraintError[s0] = rhs;
- rhs = k * q.dot(ofs);
- info->m_constraintError[s1] = rhs;
- rhs = k * ax1.dot(ofs);
- info->m_constraintError[s2] = rhs;
- }
- // the hinge axis should be the only unconstrained
- // rotational axis, the angular velocity of the two bodies perpendicular to
- // the hinge axis should be equal. thus the constraint equations are
- // p*w1 - p*w2 = 0
- // q*w1 - q*w2 = 0
- // where p and q are unit vectors normal to the hinge axis, and w1 and w2
- // are the angular velocity vectors of the two bodies.
- int s3 = 3 * s;
- int s4 = 4 * s;
- info->m_J1angularAxis[s3 + 0] = p[0];
- info->m_J1angularAxis[s3 + 1] = p[1];
- info->m_J1angularAxis[s3 + 2] = p[2];
- info->m_J1angularAxis[s4 + 0] = q[0];
- info->m_J1angularAxis[s4 + 1] = q[1];
- info->m_J1angularAxis[s4 + 2] = q[2];
-
- info->m_J2angularAxis[s3 + 0] = -p[0];
- info->m_J2angularAxis[s3 + 1] = -p[1];
- info->m_J2angularAxis[s3 + 2] = -p[2];
- info->m_J2angularAxis[s4 + 0] = -q[0];
- info->m_J2angularAxis[s4 + 1] = -q[1];
- info->m_J2angularAxis[s4 + 2] = -q[2];
- // compute the right hand side of the constraint equation. set relative
- // body velocities along p and q to bring the hinge back into alignment.
- // if ax1A,ax1B are the unit length hinge axes as computed from bodyA and
- // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
- // if "theta" is the angle between ax1 and ax2, we need an angular velocity
- // along u to cover angle erp*theta in one step :
- // |angular_velocity| = angle/time = erp*theta / stepsize
- // = (erp*fps) * theta
- // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
- // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
- // ...as ax1 and ax2 are unit length. if theta is smallish,
- // theta ~= sin(theta), so
- // angular_velocity = (erp*fps) * (ax1 x ax2)
- // ax1 x ax2 is in the plane space of ax1, so we project the angular
- // velocity to p and q to find the right hand side.
- k = info->fps * normalErp; //??
-
- btVector3 u = ax1A.cross(ax1B);
- info->m_constraintError[s3] = k * u.dot(p);
- info->m_constraintError[s4] = k * u.dot(q);
-#endif
- // check angular limits
- nrow = 4; // last filled row
- int srow;
- btScalar limit_err = btScalar(0.0);
- int limit = 0;
- if (getSolveLimit())
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- limit_err = m_limit.getCorrection() * m_referenceSign;
-#else
- limit_err = m_correction * m_referenceSign;
-#endif
- limit = (limit_err > btScalar(0.0)) ? 1 : 2;
- }
- // if the hinge has joint limits or motor, add in the extra row
- bool powered = getEnableAngularMotor();
- if (limit || powered)
- {
- nrow++;
- srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow + 0] = ax1[0];
- info->m_J1angularAxis[srow + 1] = ax1[1];
- info->m_J1angularAxis[srow + 2] = ax1[2];
-
- info->m_J2angularAxis[srow + 0] = -ax1[0];
- info->m_J2angularAxis[srow + 1] = -ax1[1];
- info->m_J2angularAxis[srow + 2] = -ax1[2];
-
- btScalar lostop = getLowerLimit();
- btScalar histop = getUpperLimit();
- if (limit && (lostop == histop))
- { // the joint motor is ineffective
- powered = false;
- }
- info->m_constraintError[srow] = btScalar(0.0f);
- btScalar currERP = (m_flags & BT_HINGE_FLAGS_ERP_STOP) ? m_stopERP : normalErp;
- if (powered)
- {
- if (m_flags & BT_HINGE_FLAGS_CFM_NORM)
- {
- info->cfm[srow] = m_normalCFM;
- }
- btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * currERP);
- info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
- info->m_lowerLimit[srow] = -m_maxMotorImpulse;
- info->m_upperLimit[srow] = m_maxMotorImpulse;
- }
- if (limit)
- {
- k = info->fps * currERP;
- info->m_constraintError[srow] += k * limit_err;
- if (m_flags & BT_HINGE_FLAGS_CFM_STOP)
- {
- info->cfm[srow] = m_stopCFM;
- }
- if (lostop == histop)
- {
- // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else if (limit == 1)
- { // low limit
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- { // high limit
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
-#ifdef _BT_USE_CENTER_LIMIT_
- btScalar bounce = m_limit.getRelaxationFactor();
-#else
- btScalar bounce = m_relaxationFactor;
-#endif
- if (bounce > btScalar(0.0))
- {
- btScalar vel = angVelA.dot(ax1);
- vel -= angVelB.dot(ax1);
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- { // low limit
- if (vel < 0)
- {
- btScalar newc = -bounce * vel;
- if (newc > info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- else
- { // high limit - all those computations are reversed
- if (vel > 0)
- {
- btScalar newc = -bounce * vel;
- if (newc < info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
-#ifdef _BT_USE_CENTER_LIMIT_
- info->m_constraintError[srow] *= m_limit.getBiasFactor();
-#else
- info->m_constraintError[srow] *= m_biasFactor;
-#endif
- } // if(limit)
- } // if angular limit or powered
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void btHingeConstraint::setParam(int num, btScalar value, int axis)
-{
- if ((axis == -1) || (axis == 5))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- m_stopERP = value;
- m_flags |= BT_HINGE_FLAGS_ERP_STOP;
- break;
- case BT_CONSTRAINT_STOP_CFM:
- m_stopCFM = value;
- m_flags |= BT_HINGE_FLAGS_CFM_STOP;
- break;
- case BT_CONSTRAINT_CFM:
- m_normalCFM = value;
- m_flags |= BT_HINGE_FLAGS_CFM_NORM;
- break;
- case BT_CONSTRAINT_ERP:
- m_normalERP = value;
- m_flags |= BT_HINGE_FLAGS_ERP_NORM;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
-}
-
-///return the local value of parameter
-btScalar btHingeConstraint::getParam(int num, int axis) const
-{
- btScalar retVal = 0;
- if ((axis == -1) || (axis == 5))
- {
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_STOP);
- retVal = m_stopERP;
- break;
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_STOP);
- retVal = m_stopCFM;
- break;
- case BT_CONSTRAINT_CFM:
- btAssertConstrParams(m_flags & BT_HINGE_FLAGS_CFM_NORM);
- retVal = m_normalCFM;
- break;
- case BT_CONSTRAINT_ERP:
- btAssertConstrParams(m_flags & BT_HINGE_FLAGS_ERP_NORM);
- retVal = m_normalERP;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- else
- {
- btAssertConstrParams(0);
- }
- return retVal;
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
deleted file mode 100644
index c7509e30af..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.h
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/* Hinge Constraint by Dirk Gregorius. Limits added by Marcus Hennix at Starbreeze Studios */
-
-#ifndef BT_HINGECONSTRAINT_H
-#define BT_HINGECONSTRAINT_H
-
-#define _BT_USE_CENTER_LIMIT_ 1
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-class btRigidBody;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btHingeConstraintData btHingeConstraintDoubleData2 //rename to 2 for backwards compatibility, so we can still load the 'btHingeConstraintDoubleData' version
-#define btHingeConstraintDataName "btHingeConstraintDoubleData2"
-#else
-#define btHingeConstraintData btHingeConstraintFloatData
-#define btHingeConstraintDataName "btHingeConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-enum btHingeFlags
-{
- BT_HINGE_FLAGS_CFM_STOP = 1,
- BT_HINGE_FLAGS_ERP_STOP = 2,
- BT_HINGE_FLAGS_CFM_NORM = 4,
- BT_HINGE_FLAGS_ERP_NORM = 8
-};
-
-/// hinge constraint between two rigidbodies each with a pivotpoint that descibes the axis location in local space
-/// axis defines the orientation of the hinge axis
-ATTRIBUTE_ALIGNED16(class)
-btHingeConstraint : public btTypedConstraint
-{
-#ifdef IN_PARALLELL_SOLVER
-public:
-#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
- btJacobianEntry m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor
-
- btTransform m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransform m_rbBFrame;
-
- btScalar m_motorTargetVelocity;
- btScalar m_maxMotorImpulse;
-
-#ifdef _BT_USE_CENTER_LIMIT_
- btAngularLimit m_limit;
-#else
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_limitSign;
- btScalar m_correction;
-
- btScalar m_limitSoftness;
- btScalar m_biasFactor;
- btScalar m_relaxationFactor;
-
- bool m_solveLimit;
-#endif
-
- btScalar m_kHinge;
-
- btScalar m_accLimitImpulse;
- btScalar m_hingeAngle;
- btScalar m_referenceSign;
-
- bool m_angularOnly;
- bool m_enableAngularMotor;
- bool m_useSolveConstraintObsolete;
- bool m_useOffsetForConstraintFrame;
- bool m_useReferenceFrameA;
-
- btScalar m_accMotorImpulse;
-
- int m_flags;
- btScalar m_normalCFM;
- btScalar m_normalERP;
- btScalar m_stopCFM;
- btScalar m_stopERP;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false);
-
- btHingeConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false);
-
- btHingeConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false);
-
- btHingeConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false);
-
- virtual void buildJacobian();
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- void getInfo1NonVirtual(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
-
- void getInfo2Internal(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
- void getInfo2InternalUsingFrameOffset(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& angVelA, const btVector3& angVelB);
-
- void updateRHS(btScalar timeStep);
-
- const btRigidBody& getRigidBodyA() const
- {
- return m_rbA;
- }
- const btRigidBody& getRigidBodyB() const
- {
- return m_rbB;
- }
-
- btRigidBody& getRigidBodyA()
- {
- return m_rbA;
- }
-
- btRigidBody& getRigidBodyB()
- {
- return m_rbB;
- }
-
- btTransform& getFrameOffsetA()
- {
- return m_rbAFrame;
- }
-
- btTransform& getFrameOffsetB()
- {
- return m_rbBFrame;
- }
-
- void setFrames(const btTransform& frameA, const btTransform& frameB);
-
- void setAngularOnly(bool angularOnly)
- {
- m_angularOnly = angularOnly;
- }
-
- void enableAngularMotor(bool enableMotor, btScalar targetVelocity, btScalar maxMotorImpulse)
- {
- m_enableAngularMotor = enableMotor;
- m_motorTargetVelocity = targetVelocity;
- m_maxMotorImpulse = maxMotorImpulse;
- }
-
- // extra motor API, including ability to set a target rotation (as opposed to angular velocity)
- // note: setMotorTarget sets angular velocity under the hood, so you must call it every tick to
- // maintain a given angular target.
- void enableMotor(bool enableMotor) { m_enableAngularMotor = enableMotor; }
- void setMaxMotorImpulse(btScalar maxMotorImpulse) { m_maxMotorImpulse = maxMotorImpulse; }
- void setMotorTargetVelocity(btScalar motorTargetVelocity) { m_motorTargetVelocity = motorTargetVelocity; }
- void setMotorTarget(const btQuaternion& qAinB, btScalar dt); // qAinB is rotation of body A wrt body B.
- void setMotorTarget(btScalar targetAngle, btScalar dt);
-
- void setLimit(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f)
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- m_limit.set(low, high, _softness, _biasFactor, _relaxationFactor);
-#else
- m_lowerLimit = btNormalizeAngle(low);
- m_upperLimit = btNormalizeAngle(high);
- m_limitSoftness = _softness;
- m_biasFactor = _biasFactor;
- m_relaxationFactor = _relaxationFactor;
-#endif
- }
-
- btScalar getLimitSoftness() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getSoftness();
-#else
- return m_limitSoftness;
-#endif
- }
-
- btScalar getLimitBiasFactor() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getBiasFactor();
-#else
- return m_biasFactor;
-#endif
- }
-
- btScalar getLimitRelaxationFactor() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getRelaxationFactor();
-#else
- return m_relaxationFactor;
-#endif
- }
-
- void setAxis(btVector3 & axisInA)
- {
- btVector3 rbAxisA1, rbAxisA2;
- btPlaneSpace1(axisInA, rbAxisA1, rbAxisA2);
- btVector3 pivotInA = m_rbAFrame.getOrigin();
- // m_rbAFrame.getOrigin() = pivotInA;
- m_rbAFrame.getBasis().setValue(rbAxisA1.getX(), rbAxisA2.getX(), axisInA.getX(),
- rbAxisA1.getY(), rbAxisA2.getY(), axisInA.getY(),
- rbAxisA1.getZ(), rbAxisA2.getZ(), axisInA.getZ());
-
- btVector3 axisInB = m_rbA.getCenterOfMassTransform().getBasis() * axisInA;
-
- btQuaternion rotationArc = shortestArcQuat(axisInA, axisInB);
- btVector3 rbAxisB1 = quatRotate(rotationArc, rbAxisA1);
- btVector3 rbAxisB2 = axisInB.cross(rbAxisB1);
-
- m_rbBFrame.getOrigin() = m_rbB.getCenterOfMassTransform().inverse()(m_rbA.getCenterOfMassTransform()(pivotInA));
-
- m_rbBFrame.getBasis().setValue(rbAxisB1.getX(), rbAxisB2.getX(), axisInB.getX(),
- rbAxisB1.getY(), rbAxisB2.getY(), axisInB.getY(),
- rbAxisB1.getZ(), rbAxisB2.getZ(), axisInB.getZ());
- m_rbBFrame.getBasis() = m_rbB.getCenterOfMassTransform().getBasis().inverse() * m_rbBFrame.getBasis();
- }
-
- bool hasLimit() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getHalfRange() > 0;
-#else
- return m_lowerLimit <= m_upperLimit;
-#endif
- }
-
- btScalar getLowerLimit() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getLow();
-#else
- return m_lowerLimit;
-#endif
- }
-
- btScalar getUpperLimit() const
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getHigh();
-#else
- return m_upperLimit;
-#endif
- }
-
- ///The getHingeAngle gives the hinge angle in range [-PI,PI]
- btScalar getHingeAngle();
-
- btScalar getHingeAngle(const btTransform& transA, const btTransform& transB);
-
- void testLimit(const btTransform& transA, const btTransform& transB);
-
- const btTransform& getAFrame() const { return m_rbAFrame; };
- const btTransform& getBFrame() const { return m_rbBFrame; };
-
- btTransform& getAFrame() { return m_rbAFrame; };
- btTransform& getBFrame() { return m_rbBFrame; };
-
- inline int getSolveLimit()
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.isLimit();
-#else
- return m_solveLimit;
-#endif
- }
-
- inline btScalar getLimitSign()
- {
-#ifdef _BT_USE_CENTER_LIMIT_
- return m_limit.getSign();
-#else
- return m_limitSign;
-#endif
- }
-
- inline bool getAngularOnly()
- {
- return m_angularOnly;
- }
- inline bool getEnableAngularMotor()
- {
- return m_enableAngularMotor;
- }
- inline btScalar getMotorTargetVelocity()
- {
- return m_motorTargetVelocity;
- }
- inline btScalar getMaxMotorImpulse()
- {
- return m_maxMotorImpulse;
- }
- // access for UseFrameOffset
- bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
- void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
- // access for UseReferenceFrameA
- bool getUseReferenceFrameA() const { return m_useReferenceFrameA; }
- void setUseReferenceFrameA(bool useReferenceFrameA) { m_useReferenceFrameA = useReferenceFrameA; }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
- {
- return m_flags;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-//only for backward compatibility
-#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-///this structure is not used, except for loading pre-2.82 .bullet files
-struct btHingeConstraintDoubleData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
-
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-
-///The getAccumulatedHingeAngle returns the accumulated hinge angle, taking rotation across the -PI/PI boundary into account
-ATTRIBUTE_ALIGNED16(class)
-btHingeAccumulatedAngleConstraint : public btHingeConstraint
-{
-protected:
- btScalar m_accumulatedAngle;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB, const btVector3& axisInA, const btVector3& axisInB, bool useReferenceFrameA = false)
- : btHingeConstraint(rbA, rbB, pivotInA, pivotInB, axisInA, axisInB, useReferenceFrameA)
- {
- m_accumulatedAngle = getHingeAngle();
- }
-
- btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btVector3& pivotInA, const btVector3& axisInA, bool useReferenceFrameA = false)
- : btHingeConstraint(rbA, pivotInA, axisInA, useReferenceFrameA)
- {
- m_accumulatedAngle = getHingeAngle();
- }
-
- btHingeAccumulatedAngleConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA = false)
- : btHingeConstraint(rbA, rbB, rbAFrame, rbBFrame, useReferenceFrameA)
- {
- m_accumulatedAngle = getHingeAngle();
- }
-
- btHingeAccumulatedAngleConstraint(btRigidBody & rbA, const btTransform& rbAFrame, bool useReferenceFrameA = false)
- : btHingeConstraint(rbA, rbAFrame, useReferenceFrameA)
- {
- m_accumulatedAngle = getHingeAngle();
- }
- btScalar getAccumulatedHingeAngle();
- void setAccumulatedHingeAngle(btScalar accAngle);
- virtual void getInfo1(btConstraintInfo1 * info);
-};
-
-struct btHingeConstraintFloatData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformFloatData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
-
- int m_enableAngularMotor;
- float m_motorTargetVelocity;
- float m_maxMotorImpulse;
-
- float m_lowerLimit;
- float m_upperLimit;
- float m_limitSoftness;
- float m_biasFactor;
- float m_relaxationFactor;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btHingeConstraintDoubleData2
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformDoubleData m_rbBFrame;
- int m_useReferenceFrameA;
- int m_angularOnly;
- int m_enableAngularMotor;
- double m_motorTargetVelocity;
- double m_maxMotorImpulse;
-
- double m_lowerLimit;
- double m_upperLimit;
- double m_limitSoftness;
- double m_biasFactor;
- double m_relaxationFactor;
- char m_padding1[4];
-};
-
-SIMD_FORCE_INLINE int btHingeConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btHingeConstraintData);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btHingeConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btHingeConstraintData* hingeData = (btHingeConstraintData*)dataBuffer;
- btTypedConstraint::serialize(&hingeData->m_typeConstraintData, serializer);
-
- m_rbAFrame.serialize(hingeData->m_rbAFrame);
- m_rbBFrame.serialize(hingeData->m_rbBFrame);
-
- hingeData->m_angularOnly = m_angularOnly;
- hingeData->m_enableAngularMotor = m_enableAngularMotor;
- hingeData->m_maxMotorImpulse = float(m_maxMotorImpulse);
- hingeData->m_motorTargetVelocity = float(m_motorTargetVelocity);
- hingeData->m_useReferenceFrameA = m_useReferenceFrameA;
-#ifdef _BT_USE_CENTER_LIMIT_
- hingeData->m_lowerLimit = float(m_limit.getLow());
- hingeData->m_upperLimit = float(m_limit.getHigh());
- hingeData->m_limitSoftness = float(m_limit.getSoftness());
- hingeData->m_biasFactor = float(m_limit.getBiasFactor());
- hingeData->m_relaxationFactor = float(m_limit.getRelaxationFactor());
-#else
- hingeData->m_lowerLimit = float(m_lowerLimit);
- hingeData->m_upperLimit = float(m_upperLimit);
- hingeData->m_limitSoftness = float(m_limitSoftness);
- hingeData->m_biasFactor = float(m_biasFactor);
- hingeData->m_relaxationFactor = float(m_relaxationFactor);
-#endif
-
- // Fill padding with zeros to appease msan.
-#ifdef BT_USE_DOUBLE_PRECISION
- hingeData->m_padding1[0] = 0;
- hingeData->m_padding1[1] = 0;
- hingeData->m_padding1[2] = 0;
- hingeData->m_padding1[3] = 0;
-#endif
-
- return btHingeConstraintDataName;
-}
-
-#endif //BT_HINGECONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
deleted file mode 100644
index 438456fe51..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btJacobianEntry.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_JACOBIAN_ENTRY_H
-#define BT_JACOBIAN_ENTRY_H
-
-#include "LinearMath/btMatrix3x3.h"
-
-//notes:
-// Another memory optimization would be to store m_1MinvJt in the remaining 3 w components
-// which makes the btJacobianEntry memory layout 16 bytes
-// if you only are interested in angular part, just feed massInvA and massInvB zero
-
-/// Jacobian entry is an abstraction that allows to describe constraints
-/// it can be used in combination with a constraint solver
-/// Can be used to relate the effect of an impulse to the constraint error
-ATTRIBUTE_ALIGNED16(class)
-btJacobianEntry
-{
-public:
- btJacobianEntry(){};
- //constraint between two different rigidbodies
- btJacobianEntry(
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
- const btVector3& rel_pos1, const btVector3& rel_pos2,
- const btVector3& jointAxis,
- const btVector3& inertiaInvA,
- const btScalar massInvA,
- const btVector3& inertiaInvB,
- const btScalar massInvB)
- : m_linearJointAxis(jointAxis)
- {
- m_aJ = world2A * (rel_pos1.cross(m_linearJointAxis));
- m_bJ = world2B * (rel_pos2.cross(-m_linearJointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ);
-
- btAssert(m_Adiag > btScalar(0.0));
- }
-
- //angular constraint between two different rigidbodies
- btJacobianEntry(const btVector3& jointAxis,
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
- const btVector3& inertiaInvA,
- const btVector3& inertiaInvB)
- : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)))
- {
- m_aJ = world2A * jointAxis;
- m_bJ = world2B * -jointAxis;
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
-
- btAssert(m_Adiag > btScalar(0.0));
- }
-
- //angular constraint between two different rigidbodies
- btJacobianEntry(const btVector3& axisInA,
- const btVector3& axisInB,
- const btVector3& inertiaInvA,
- const btVector3& inertiaInvB)
- : m_linearJointAxis(btVector3(btScalar(0.), btScalar(0.), btScalar(0.))), m_aJ(axisInA), m_bJ(-axisInB)
- {
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = inertiaInvB * m_bJ;
- m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ);
-
- btAssert(m_Adiag > btScalar(0.0));
- }
-
- //constraint on one rigidbody
- btJacobianEntry(
- const btMatrix3x3& world2A,
- const btVector3& rel_pos1, const btVector3& rel_pos2,
- const btVector3& jointAxis,
- const btVector3& inertiaInvA,
- const btScalar massInvA)
- : m_linearJointAxis(jointAxis)
- {
- m_aJ = world2A * (rel_pos1.cross(jointAxis));
- m_bJ = world2A * (rel_pos2.cross(-jointAxis));
- m_0MinvJt = inertiaInvA * m_aJ;
- m_1MinvJt = btVector3(btScalar(0.), btScalar(0.), btScalar(0.));
- m_Adiag = massInvA + m_0MinvJt.dot(m_aJ);
-
- btAssert(m_Adiag > btScalar(0.0));
- }
-
- btScalar getDiagonal() const { return m_Adiag; }
-
- // for two constraints on the same rigidbody (for example vehicle friction)
- btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA) const
- {
- const btJacobianEntry& jacA = *this;
- btScalar lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis);
- btScalar ang = jacA.m_0MinvJt.dot(jacB.m_aJ);
- return lin + ang;
- }
-
- // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies)
- btScalar getNonDiagonal(const btJacobianEntry& jacB, const btScalar massInvA, const btScalar massInvB) const
- {
- const btJacobianEntry& jacA = *this;
- btVector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis;
- btVector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ;
- btVector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ;
- btVector3 lin0 = massInvA * lin;
- btVector3 lin1 = massInvB * lin;
- btVector3 sum = ang0 + ang1 + lin0 + lin1;
- return sum[0] + sum[1] + sum[2];
- }
-
- btScalar getRelativeVelocity(const btVector3& linvelA, const btVector3& angvelA, const btVector3& linvelB, const btVector3& angvelB)
- {
- btVector3 linrel = linvelA - linvelB;
- btVector3 angvela = angvelA * m_aJ;
- btVector3 angvelb = angvelB * m_bJ;
- linrel *= m_linearJointAxis;
- angvela += angvelb;
- angvela += linrel;
- btScalar rel_vel2 = angvela[0] + angvela[1] + angvela[2];
- return rel_vel2 + SIMD_EPSILON;
- }
- //private:
-
- btVector3 m_linearJointAxis;
- btVector3 m_aJ;
- btVector3 m_bJ;
- btVector3 m_0MinvJt;
- btVector3 m_1MinvJt;
- //Optimization: can be stored in the w/last component of one of the vectors
- btScalar m_Adiag;
-};
-
-#endif //BT_JACOBIAN_ENTRY_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
deleted file mode 100644
index ccf8916049..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btNNCGConstraintSolver.h"
-
-btScalar btNNCGConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- m_pNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
- m_pC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
- m_pCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
- m_pCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
-
- m_deltafNC.resizeNoInitialize(m_tmpSolverNonContactConstraintPool.size());
- m_deltafC.resizeNoInitialize(m_tmpSolverContactConstraintPool.size());
- m_deltafCF.resizeNoInitialize(m_tmpSolverContactFrictionConstraintPool.size());
- m_deltafCRF.resizeNoInitialize(m_tmpSolverContactRollingFrictionConstraintPool.size());
-
- return val;
-}
-
-btScalar btNNCGConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
-{
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- for (int j = 0; j < numNonContactPool; ++j)
- {
- int tmp = m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
- m_orderNonContactConstraintPool[swapi] = tmp;
- }
-
- //contact/friction constraints are not solved more than
- if (iteration < infoGlobal.m_numIterations)
- {
- for (int j = 0; j < numConstraintPool; ++j)
- {
- int tmp = m_orderTmpConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
- m_orderTmpConstraintPool[swapi] = tmp;
- }
-
- for (int j = 0; j < numFrictionPool; ++j)
- {
- int tmp = m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
- m_orderFrictionConstraintPool[swapi] = tmp;
- }
- }
- }
- }
-
- btScalar deltaflengthsqr = 0;
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
- m_deltafNC[j] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
- }
- }
-
- if (m_onlyForNoneContact)
- {
- if (iteration == 0)
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
- }
- else
- {
- // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
- btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
- if (beta > 1)
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
- }
- else
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar additionaldeltaimpulse = beta * m_pNC[j];
- constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
- m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
- btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
- }
- }
- }
- }
- m_deltafLengthSqrPrev = deltaflengthsqr;
- }
-
- {
- if (iteration < infoGlobal.m_numIterations)
- {
- for (int j = 0; j < numConstraints; j++)
- {
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
- }
- }
-
- ///solve all contact constraints
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
-
- for (int c = 0; c < numPoolConstraints; c++)
- {
- btScalar totalImpulse = 0;
-
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- m_deltafC[c] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- bool applyFriction = true;
- if (applyFriction)
- {
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- m_deltafCF[c * multiplier] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
- else
- {
- m_deltafCF[c * multiplier] = 0;
- }
- }
-
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- m_deltafCF[c * multiplier + 1] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
- else
- {
- m_deltafCF[c * multiplier + 1] = 0;
- }
- }
- }
- }
- }
- else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- //solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
-
- for (j = 0; j < numPoolConstraints; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar deltaf = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- m_deltafC[j] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
-
- ///solve all friction constraints
-
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j = 0; j < numFrictionPoolConstraints; j++)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- m_deltafCF[j] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
- else
- {
- m_deltafCF[j] = 0;
- }
- }
- }
-
- {
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > btScalar(0))
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar deltaf = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- m_deltafCRF[j] = deltaf;
- deltaflengthsqr += deltaf * deltaf;
- }
- else
- {
- m_deltafCRF[j] = 0;
- }
- }
- }
- }
- }
-
- if (!m_onlyForNoneContact)
- {
- if (iteration == 0)
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = m_deltafNC[j];
- for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = m_deltafC[j];
- for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = m_deltafCF[j];
- for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = m_deltafCRF[j];
- }
- else
- {
- // deltaflengthsqrprev can be 0 only if the solver solved the problem exactly in the previous iteration. In this case we should have quit, but mainly for debug reason with this 'hack' it is now allowed to continue the calculation
- btScalar beta = m_deltafLengthSqrPrev > 0 ? deltaflengthsqr / m_deltafLengthSqrPrev : 2;
- if (beta > 1)
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++) m_pNC[j] = 0;
- for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++) m_pC[j] = 0;
- for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++) m_pCF[j] = 0;
- for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++) m_pCRF[j] = 0;
- }
- else
- {
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar additionaldeltaimpulse = beta * m_pNC[j];
- constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
- m_pNC[j] = beta * m_pNC[j] + m_deltafNC[j];
- btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
- }
- }
- for (int j = 0; j < m_tmpSolverContactConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- if (iteration < infoGlobal.m_numIterations)
- {
- btScalar additionaldeltaimpulse = beta * m_pC[j];
- constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
- m_pC[j] = beta * m_pC[j] + m_deltafC[j];
- btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
- }
- }
- for (int j = 0; j < m_tmpSolverContactFrictionConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- if (iteration < infoGlobal.m_numIterations)
- {
- btScalar additionaldeltaimpulse = beta * m_pCF[j];
- constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
- m_pCF[j] = beta * m_pCF[j] + m_deltafCF[j];
- btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
- }
- }
- {
- for (int j = 0; j < m_tmpSolverContactRollingFrictionConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- if (iteration < infoGlobal.m_numIterations)
- {
- btScalar additionaldeltaimpulse = beta * m_pCRF[j];
- constraint.m_appliedImpulse = btScalar(constraint.m_appliedImpulse) + additionaldeltaimpulse;
- m_pCRF[j] = beta * m_pCRF[j] + m_deltafCRF[j];
- btSolverBody& body1 = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& body2 = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- const btSolverConstraint& c = constraint;
- body1.internalApplyImpulse(c.m_contactNormal1 * body1.internalGetInvMass(), c.m_angularComponentA, additionaldeltaimpulse);
- body2.internalApplyImpulse(c.m_contactNormal2 * body2.internalGetInvMass(), c.m_angularComponentB, additionaldeltaimpulse);
- }
- }
- }
- }
- }
- m_deltafLengthSqrPrev = deltaflengthsqr;
- }
-
- return deltaflengthsqr;
-}
-
-btScalar btNNCGConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- m_pNC.resizeNoInitialize(0);
- m_pC.resizeNoInitialize(0);
- m_pCF.resizeNoInitialize(0);
- m_pCRF.resizeNoInitialize(0);
-
- m_deltafNC.resizeNoInitialize(0);
- m_deltafC.resizeNoInitialize(0);
- m_deltafCF.resizeNoInitialize(0);
- m_deltafCRF.resizeNoInitialize(0);
-
- return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
deleted file mode 100644
index c84f274a99..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_NNCG_CONSTRAINT_SOLVER_H
-#define BT_NNCG_CONSTRAINT_SOLVER_H
-
-#include "btSequentialImpulseConstraintSolver.h"
-
-ATTRIBUTE_ALIGNED16(class)
-btNNCGConstraintSolver : public btSequentialImpulseConstraintSolver
-{
-protected:
- btScalar m_deltafLengthSqrPrev;
-
- btAlignedObjectArray<btScalar> m_pNC; // p for None Contact constraints
- btAlignedObjectArray<btScalar> m_pC; // p for Contact constraints
- btAlignedObjectArray<btScalar> m_pCF; // p for ContactFriction constraints
- btAlignedObjectArray<btScalar> m_pCRF; // p for ContactRollingFriction constraints
-
- //These are recalculated in every iterations. We just keep these to prevent reallocation in each iteration.
- btAlignedObjectArray<btScalar> m_deltafNC; // deltaf for NoneContact constraints
- btAlignedObjectArray<btScalar> m_deltafC; // deltaf for Contact constraints
- btAlignedObjectArray<btScalar> m_deltafCF; // deltaf for ContactFriction constraints
- btAlignedObjectArray<btScalar> m_deltafCRF; // deltaf for ContactRollingFriction constraints
-
-protected:
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btNNCGConstraintSolver() : btSequentialImpulseConstraintSolver(), m_onlyForNoneContact(false) {}
-
- virtual btConstraintSolverType getSolverType() const
- {
- return BT_NNCG_SOLVER;
- }
-
- bool m_onlyForNoneContact;
-};
-
-#endif //BT_NNCG_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
deleted file mode 100644
index ad399dc57f..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btPoint2PointConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include <new>
-
-btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB)
- : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA, rbB), m_pivotInA(pivotInA), m_pivotInB(pivotInB), m_flags(0), m_useSolveConstraintObsolete(false)
-{
-}
-
-btPoint2PointConstraint::btPoint2PointConstraint(btRigidBody& rbA, const btVector3& pivotInA)
- : btTypedConstraint(POINT2POINT_CONSTRAINT_TYPE, rbA), m_pivotInA(pivotInA), m_pivotInB(rbA.getCenterOfMassTransform()(pivotInA)), m_flags(0), m_useSolveConstraintObsolete(false)
-{
-}
-
-void btPoint2PointConstraint::buildJacobian()
-{
- ///we need it for both methods
- {
- m_appliedImpulse = btScalar(0.);
-
- btVector3 normal(0, 0, 0);
-
- for (int i = 0; i < 3; i++)
- {
- normal[i] = 1;
- new (&m_jac[i]) btJacobianEntry(
- m_rbA.getCenterOfMassTransform().getBasis().transpose(),
- m_rbB.getCenterOfMassTransform().getBasis().transpose(),
- m_rbA.getCenterOfMassTransform() * m_pivotInA - m_rbA.getCenterOfMassPosition(),
- m_rbB.getCenterOfMassTransform() * m_pivotInB - m_rbB.getCenterOfMassPosition(),
- normal,
- m_rbA.getInvInertiaDiagLocal(),
- m_rbA.getInvMass(),
- m_rbB.getInvInertiaDiagLocal(),
- m_rbB.getInvMass());
- normal[i] = 0;
- }
- }
-}
-
-void btPoint2PointConstraint::getInfo1(btConstraintInfo1* info)
-{
- getInfo1NonVirtual(info);
-}
-
-void btPoint2PointConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- info->m_numConstraintRows = 3;
- info->nub = 3;
- }
-}
-
-void btPoint2PointConstraint::getInfo2(btConstraintInfo2* info)
-{
- getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-}
-
-void btPoint2PointConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& body0_trans, const btTransform& body1_trans)
-{
- btAssert(!m_useSolveConstraintObsolete);
-
- //retrieve matrices
-
- // anchor points in global coordinates with respect to body PORs.
-
- // set jacobian
- info->m_J1linearAxis[0] = 1;
- info->m_J1linearAxis[info->rowskip + 1] = 1;
- info->m_J1linearAxis[2 * info->rowskip + 2] = 1;
-
- btVector3 a1 = body0_trans.getBasis() * getPivotInA();
- {
- btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * info->rowskip);
- btVector3 a1neg = -a1;
- a1neg.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- info->m_J2linearAxis[0] = -1;
- info->m_J2linearAxis[info->rowskip + 1] = -1;
- info->m_J2linearAxis[2 * info->rowskip + 2] = -1;
-
- btVector3 a2 = body1_trans.getBasis() * getPivotInB();
-
- {
- // btVector3 a2n = -a2;
- btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
- btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + info->rowskip);
- btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * info->rowskip);
- a2.getSkewSymmetricMatrix(angular0, angular1, angular2);
- }
-
- // set right hand side
- btScalar currERP = (m_flags & BT_P2P_FLAGS_ERP) ? m_erp : info->erp;
- btScalar k = info->fps * currERP;
- int j;
- for (j = 0; j < 3; j++)
- {
- info->m_constraintError[j * info->rowskip] = k * (a2[j] + body1_trans.getOrigin()[j] - a1[j] - body0_trans.getOrigin()[j]);
- //printf("info->m_constraintError[%d]=%f\n",j,info->m_constraintError[j]);
- }
- if (m_flags & BT_P2P_FLAGS_CFM)
- {
- for (j = 0; j < 3; j++)
- {
- info->cfm[j * info->rowskip] = m_cfm;
- }
- }
-
- btScalar impulseClamp = m_setting.m_impulseClamp; //
- for (j = 0; j < 3; j++)
- {
- if (m_setting.m_impulseClamp > 0)
- {
- info->m_lowerLimit[j * info->rowskip] = -impulseClamp;
- info->m_upperLimit[j * info->rowskip] = impulseClamp;
- }
- }
- info->m_damping = m_setting.m_damping;
-}
-
-void btPoint2PointConstraint::updateRHS(btScalar timeStep)
-{
- (void)timeStep;
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void btPoint2PointConstraint::setParam(int num, btScalar value, int axis)
-{
- if (axis != -1)
- {
- btAssertConstrParams(0);
- }
- else
- {
- switch (num)
- {
- case BT_CONSTRAINT_ERP:
- case BT_CONSTRAINT_STOP_ERP:
- m_erp = value;
- m_flags |= BT_P2P_FLAGS_ERP;
- break;
- case BT_CONSTRAINT_CFM:
- case BT_CONSTRAINT_STOP_CFM:
- m_cfm = value;
- m_flags |= BT_P2P_FLAGS_CFM;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
-}
-
-///return the local value of parameter
-btScalar btPoint2PointConstraint::getParam(int num, int axis) const
-{
- btScalar retVal(SIMD_INFINITY);
- if (axis != -1)
- {
- btAssertConstrParams(0);
- }
- else
- {
- switch (num)
- {
- case BT_CONSTRAINT_ERP:
- case BT_CONSTRAINT_STOP_ERP:
- btAssertConstrParams(m_flags & BT_P2P_FLAGS_ERP);
- retVal = m_erp;
- break;
- case BT_CONSTRAINT_CFM:
- case BT_CONSTRAINT_STOP_CFM:
- btAssertConstrParams(m_flags & BT_P2P_FLAGS_CFM);
- retVal = m_cfm;
- break;
- default:
- btAssertConstrParams(0);
- }
- }
- return retVal;
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
deleted file mode 100644
index 4717e19800..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_POINT2POINTCONSTRAINT_H
-#define BT_POINT2POINTCONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-class btRigidBody;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btPoint2PointConstraintData2 btPoint2PointConstraintDoubleData2
-#define btPoint2PointConstraintDataName "btPoint2PointConstraintDoubleData2"
-#else
-#define btPoint2PointConstraintData2 btPoint2PointConstraintFloatData
-#define btPoint2PointConstraintDataName "btPoint2PointConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-struct btConstraintSetting
-{
- btConstraintSetting() : m_tau(btScalar(0.3)),
- m_damping(btScalar(1.)),
- m_impulseClamp(btScalar(0.))
- {
- }
- btScalar m_tau;
- btScalar m_damping;
- btScalar m_impulseClamp;
-};
-
-enum btPoint2PointFlags
-{
- BT_P2P_FLAGS_ERP = 1,
- BT_P2P_FLAGS_CFM = 2
-};
-
-/// point to point constraint between two rigidbodies each with a pivotpoint that descibes the 'ballsocket' location in local space
-ATTRIBUTE_ALIGNED16(class)
-btPoint2PointConstraint : public btTypedConstraint
-{
-#ifdef IN_PARALLELL_SOLVER
-public:
-#endif
- btJacobianEntry m_jac[3]; //3 orthogonal linear constraints
-
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
-
- int m_flags;
- btScalar m_erp;
- btScalar m_cfm;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
-
- btConstraintSetting m_setting;
-
- btPoint2PointConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& pivotInA, const btVector3& pivotInB);
-
- btPoint2PointConstraint(btRigidBody & rbA, const btVector3& pivotInA);
-
- virtual void buildJacobian();
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- void getInfo1NonVirtual(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& body0_trans, const btTransform& body1_trans);
-
- void updateRHS(btScalar timeStep);
-
- void setPivotA(const btVector3& pivotA)
- {
- m_pivotInA = pivotA;
- }
-
- void setPivotB(const btVector3& pivotB)
- {
- m_pivotInB = pivotB;
- }
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- const btVector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
- {
- return m_flags;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintFloatData
-{
- btTypedConstraintData m_typeConstraintData;
- btVector3FloatData m_pivotInA;
- btVector3FloatData m_pivotInB;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintDoubleData2
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btVector3DoubleData m_pivotInA;
- btVector3DoubleData m_pivotInB;
-};
-
-#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-///this structure is not used, except for loading pre-2.82 .bullet files
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btPoint2PointConstraintDoubleData
-{
- btTypedConstraintData m_typeConstraintData;
- btVector3DoubleData m_pivotInA;
- btVector3DoubleData m_pivotInB;
-};
-#endif //BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-
-SIMD_FORCE_INLINE int btPoint2PointConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btPoint2PointConstraintData2);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btPoint2PointConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btPoint2PointConstraintData2* p2pData = (btPoint2PointConstraintData2*)dataBuffer;
-
- btTypedConstraint::serialize(&p2pData->m_typeConstraintData, serializer);
- m_pivotInA.serialize(p2pData->m_pivotInA);
- m_pivotInB.serialize(p2pData->m_pivotInB);
-
- return btPoint2PointConstraintDataName;
-}
-
-#endif //BT_POINT2POINTCONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
deleted file mode 100644
index d2641c582f..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp
+++ /dev/null
@@ -1,1875 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//#define COMPUTE_IMPULSE_DENOM 1
-#ifdef BT_DEBUG
-# define BT_ADDITIONAL_DEBUG
-#endif
-
-//It is not necessary (redundant) to refresh contact manifolds, this refresh has been moved to the collision algorithms.
-
-#include "btSequentialImpulseConstraintSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btCpuFeatureUtility.h"
-
-//#include "btJacobianEntry.h"
-#include "LinearMath/btMinMax.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include <new>
-#include "LinearMath/btStackAlloc.h"
-#include "LinearMath/btQuickprof.h"
-//#include "btSolverBody.h"
-//#include "btSolverConstraint.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include <string.h> //for memset
-
-int gNumSplitImpulseRecoveries = 0;
-
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-//#define VERBOSE_RESIDUAL_PRINTF 1
-///This is the scalar reference implementation of solving a single constraint row, the innerloop of the Projected Gauss Seidel/Sequential Impulse constraint solver
-///Below are optional SSE2 and SSE4/FMA3 versions. We assume most hardware has SSE2. For SSE4/FMA3 we perform a CPU feature check.
-static btScalar gResolveSingleConstraintRowGeneric_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
-
- // const btScalar delta_rel_vel = deltaVel1Dotn-deltaVel2Dotn;
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
-
- const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else if (sum > c.m_upperLimit)
- {
- deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_upperLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
-
- bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
-
- return deltaImpulse * (1. / c.m_jacDiagABInv);
-}
-
-static btScalar gResolveSingleConstraintRowLowerLimit_scalar_reference(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetDeltaAngularVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetDeltaAngularVelocity());
-
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
- bodyA.internalApplyImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- bodyB.internalApplyImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
-
- return deltaImpulse * (1. / c.m_jacDiagABInv);
-}
-
-#ifdef USE_SIMD
-#include <emmintrin.h>
-
-#define btVecSplat(x, e) _mm_shuffle_ps(x, x, _MM_SHUFFLE(e, e, e, e))
-static inline __m128 btSimdDot3(__m128 vec0, __m128 vec1)
-{
- __m128 result = _mm_mul_ps(vec0, vec1);
- return _mm_add_ps(btVecSplat(result, 0), _mm_add_ps(btVecSplat(result, 1), btVecSplat(result, 2)));
-}
-
-#if defined(BT_ALLOW_SSE4)
-#include <intrin.h>
-
-#define USE_FMA 1
-#define USE_FMA3_INSTEAD_FMA4 1
-#define USE_SSE4_DOT 1
-
-#define SSE4_DP(a, b) _mm_dp_ps(a, b, 0x7f)
-#define SSE4_DP_FP(a, b) _mm_cvtss_f32(_mm_dp_ps(a, b, 0x7f))
-
-#if USE_SSE4_DOT
-#define DOT_PRODUCT(a, b) SSE4_DP(a, b)
-#else
-#define DOT_PRODUCT(a, b) btSimdDot3(a, b)
-#endif
-
-#if USE_FMA
-#if USE_FMA3_INSTEAD_FMA4
-// a*b + c
-#define FMADD(a, b, c) _mm_fmadd_ps(a, b, c)
-// -(a*b) + c
-#define FMNADD(a, b, c) _mm_fnmadd_ps(a, b, c)
-#else // USE_FMA3
-// a*b + c
-#define FMADD(a, b, c) _mm_macc_ps(a, b, c)
-// -(a*b) + c
-#define FMNADD(a, b, c) _mm_nmacc_ps(a, b, c)
-#endif
-#else // USE_FMA
-// c + a*b
-#define FMADD(a, b, c) _mm_add_ps(c, _mm_mul_ps(a, b))
-// c - a*b
-#define FMNADD(a, b, c) _mm_sub_ps(c, _mm_mul_ps(a, b))
-#endif
-#endif
-
-// Project Gauss Seidel or the equivalent Sequential Impulse
-static btScalar gResolveSingleConstraintRowGeneric_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- btSimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 upperMinApplied = _mm_sub_ps(upperLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, deltaImpulse), _mm_andnot_ps(resultUpperLess, upperMinApplied));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultUpperLess, c.m_appliedImpulse), _mm_andnot_ps(resultUpperLess, upperLimit1));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps((c.m_contactNormal2).mVec128, bodyB.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
-}
-
-// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
-static btScalar gResolveSingleConstraintRowGeneric_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
-#if defined(BT_ALLOW_SSE4)
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 upperLimit = _mm_set_ps1(c.m_upperLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse); // sum
- const __m128 maskLower = _mm_cmpgt_ps(tmp, lowerLimit);
- const __m128 maskUpper = _mm_cmpgt_ps(upperLimit, tmp);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), _mm_blendv_ps(_mm_sub_ps(upperLimit, c.m_appliedImpulse), deltaImpulse, maskUpper), maskLower);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, _mm_blendv_ps(upperLimit, tmp, maskUpper), maskLower);
- bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
- bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
- bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
- bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
- btSimdScalar deltaImp = deltaImpulse;
- return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
-#else
- return gResolveSingleConstraintRowGeneric_sse2(bodyA, bodyB, c);
-#endif
-}
-
-static btScalar gResolveSingleConstraintRowLowerLimit_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- btSimdScalar deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhs), _mm_mul_ps(_mm_set1_ps(c.m_appliedImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- btSimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- bodyA.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- bodyA.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyA.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- bodyB.internalGetDeltaLinearVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaLinearVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- bodyB.internalGetDeltaAngularVelocity().mVec128 = _mm_add_ps(bodyB.internalGetDeltaAngularVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- return deltaImpulse.m_floats[0] / c.m_jacDiagABInv;
-}
-
-// Enhanced version of gResolveSingleConstraintRowGeneric_sse2 with SSE4.1 and FMA3
-static btScalar gResolveSingleConstraintRowLowerLimit_sse4_1_fma3(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
-#ifdef BT_ALLOW_SSE4
- __m128 tmp = _mm_set_ps1(c.m_jacDiagABInv);
- __m128 deltaImpulse = _mm_set_ps1(c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm);
- const __m128 lowerLimit = _mm_set_ps1(c.m_lowerLimit);
- const __m128 deltaVel1Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal1.mVec128, bodyA.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetDeltaAngularVelocity().mVec128));
- const __m128 deltaVel2Dotn = _mm_add_ps(DOT_PRODUCT(c.m_contactNormal2.mVec128, bodyB.internalGetDeltaLinearVelocity().mVec128), DOT_PRODUCT(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetDeltaAngularVelocity().mVec128));
- deltaImpulse = FMNADD(deltaVel1Dotn, tmp, deltaImpulse);
- deltaImpulse = FMNADD(deltaVel2Dotn, tmp, deltaImpulse);
- tmp = _mm_add_ps(c.m_appliedImpulse, deltaImpulse);
- const __m128 mask = _mm_cmpgt_ps(tmp, lowerLimit);
- deltaImpulse = _mm_blendv_ps(_mm_sub_ps(lowerLimit, c.m_appliedImpulse), deltaImpulse, mask);
- c.m_appliedImpulse = _mm_blendv_ps(lowerLimit, tmp, mask);
- bodyA.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128), deltaImpulse, bodyA.internalGetDeltaLinearVelocity().mVec128);
- bodyA.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentA.mVec128, deltaImpulse, bodyA.internalGetDeltaAngularVelocity().mVec128);
- bodyB.internalGetDeltaLinearVelocity().mVec128 = FMADD(_mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128), deltaImpulse, bodyB.internalGetDeltaLinearVelocity().mVec128);
- bodyB.internalGetDeltaAngularVelocity().mVec128 = FMADD(c.m_angularComponentB.mVec128, deltaImpulse, bodyB.internalGetDeltaAngularVelocity().mVec128);
- btSimdScalar deltaImp = deltaImpulse;
- return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
-#else
- return gResolveSingleConstraintRowLowerLimit_sse2(bodyA, bodyB, c);
-#endif //BT_ALLOW_SSE4
-}
-
-#endif //USE_SIMD
-
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGenericSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
-}
-
-// Project Gauss Seidel or the equivalent Sequential Impulse
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowGeneric(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- return m_resolveSingleConstraintRowGeneric(bodyA, bodyB, c);
-}
-
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimitSIMD(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
-}
-
-btScalar btSequentialImpulseConstraintSolver::resolveSingleConstraintRowLowerLimit(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
- return m_resolveSingleConstraintRowLowerLimit(bodyA, bodyB, c);
-}
-
-static btScalar gResolveSplitPenetrationImpulse_scalar_reference(
- btSolverBody& bodyA,
- btSolverBody& bodyB,
- const btSolverConstraint& c)
-{
- btScalar deltaImpulse = 0.f;
-
- if (c.m_rhsPenetration)
- {
- gNumSplitImpulseRecoveries++;
- deltaImpulse = c.m_rhsPenetration - btScalar(c.m_appliedPushImpulse) * c.m_cfm;
- const btScalar deltaVel1Dotn = c.m_contactNormal1.dot(bodyA.internalGetPushVelocity()) + c.m_relpos1CrossNormal.dot(bodyA.internalGetTurnVelocity());
- const btScalar deltaVel2Dotn = c.m_contactNormal2.dot(bodyB.internalGetPushVelocity()) + c.m_relpos2CrossNormal.dot(bodyB.internalGetTurnVelocity());
-
- deltaImpulse -= deltaVel1Dotn * c.m_jacDiagABInv;
- deltaImpulse -= deltaVel2Dotn * c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedPushImpulse) + deltaImpulse;
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedPushImpulse;
- c.m_appliedPushImpulse = c.m_lowerLimit;
- }
- else
- {
- c.m_appliedPushImpulse = sum;
- }
- bodyA.internalApplyPushImpulse(c.m_contactNormal1 * bodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- bodyB.internalApplyPushImpulse(c.m_contactNormal2 * bodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- }
- return deltaImpulse * (1. / c.m_jacDiagABInv);
-}
-
-static btScalar gResolveSplitPenetrationImpulse_sse2(btSolverBody& bodyA, btSolverBody& bodyB, const btSolverConstraint& c)
-{
-#ifdef USE_SIMD
- if (!c.m_rhsPenetration)
- return 0.f;
-
- gNumSplitImpulseRecoveries++;
-
- __m128 cpAppliedImp = _mm_set1_ps(c.m_appliedPushImpulse);
- __m128 lowerLimit1 = _mm_set1_ps(c.m_lowerLimit);
- __m128 upperLimit1 = _mm_set1_ps(c.m_upperLimit);
- __m128 deltaImpulse = _mm_sub_ps(_mm_set1_ps(c.m_rhsPenetration), _mm_mul_ps(_mm_set1_ps(c.m_appliedPushImpulse), _mm_set1_ps(c.m_cfm)));
- __m128 deltaVel1Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal1.mVec128, bodyA.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos1CrossNormal.mVec128, bodyA.internalGetTurnVelocity().mVec128));
- __m128 deltaVel2Dotn = _mm_add_ps(btSimdDot3(c.m_contactNormal2.mVec128, bodyB.internalGetPushVelocity().mVec128), btSimdDot3(c.m_relpos2CrossNormal.mVec128, bodyB.internalGetTurnVelocity().mVec128));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel1Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- deltaImpulse = _mm_sub_ps(deltaImpulse, _mm_mul_ps(deltaVel2Dotn, _mm_set1_ps(c.m_jacDiagABInv)));
- btSimdScalar sum = _mm_add_ps(cpAppliedImp, deltaImpulse);
- btSimdScalar resultLowerLess, resultUpperLess;
- resultLowerLess = _mm_cmplt_ps(sum, lowerLimit1);
- resultUpperLess = _mm_cmplt_ps(sum, upperLimit1);
- __m128 lowMinApplied = _mm_sub_ps(lowerLimit1, cpAppliedImp);
- deltaImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowMinApplied), _mm_andnot_ps(resultLowerLess, deltaImpulse));
- c.m_appliedPushImpulse = _mm_or_ps(_mm_and_ps(resultLowerLess, lowerLimit1), _mm_andnot_ps(resultLowerLess, sum));
- __m128 linearComponentA = _mm_mul_ps(c.m_contactNormal1.mVec128, bodyA.internalGetInvMass().mVec128);
- __m128 linearComponentB = _mm_mul_ps(c.m_contactNormal2.mVec128, bodyB.internalGetInvMass().mVec128);
- __m128 impulseMagnitude = deltaImpulse;
- bodyA.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyA.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentA, impulseMagnitude));
- bodyA.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyA.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentA.mVec128, impulseMagnitude));
- bodyB.internalGetPushVelocity().mVec128 = _mm_add_ps(bodyB.internalGetPushVelocity().mVec128, _mm_mul_ps(linearComponentB, impulseMagnitude));
- bodyB.internalGetTurnVelocity().mVec128 = _mm_add_ps(bodyB.internalGetTurnVelocity().mVec128, _mm_mul_ps(c.m_angularComponentB.mVec128, impulseMagnitude));
- btSimdScalar deltaImp = deltaImpulse;
- return deltaImp.m_floats[0] * (1. / c.m_jacDiagABInv);
-#else
- return gResolveSplitPenetrationImpulse_scalar_reference(bodyA, bodyB, c);
-#endif
-}
-
-btSequentialImpulseConstraintSolver::btSequentialImpulseConstraintSolver()
-{
- m_btSeed2 = 0;
- m_cachedSolverMode = 0;
- setupSolverFunctions(false);
-}
-
-void btSequentialImpulseConstraintSolver::setupSolverFunctions(bool useSimd)
-{
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_scalar_reference;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_scalar_reference;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_scalar_reference;
-
- if (useSimd)
- {
-#ifdef USE_SIMD
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse2;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse2;
- m_resolveSplitPenetrationImpulse = gResolveSplitPenetrationImpulse_sse2;
-
-#ifdef BT_ALLOW_SSE4
- int cpuFeatures = btCpuFeatureUtility::getCpuFeatures();
- if ((cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_FMA3) && (cpuFeatures & btCpuFeatureUtility::CPU_FEATURE_SSE4_1))
- {
- m_resolveSingleConstraintRowGeneric = gResolveSingleConstraintRowGeneric_sse4_1_fma3;
- m_resolveSingleConstraintRowLowerLimit = gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
- }
-#endif //BT_ALLOW_SSE4
-#endif //USE_SIMD
- }
-}
-
-btSequentialImpulseConstraintSolver::~btSequentialImpulseConstraintSolver()
-{
-}
-
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverGeneric()
-{
- return gResolveSingleConstraintRowGeneric_scalar_reference;
-}
-
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getScalarConstraintRowSolverLowerLimit()
-{
- return gResolveSingleConstraintRowLowerLimit_scalar_reference;
-}
-
-#ifdef USE_SIMD
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverGeneric()
-{
- return gResolveSingleConstraintRowGeneric_sse2;
-}
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE2ConstraintRowSolverLowerLimit()
-{
- return gResolveSingleConstraintRowLowerLimit_sse2;
-}
-#ifdef BT_ALLOW_SSE4
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverGeneric()
-{
- return gResolveSingleConstraintRowGeneric_sse4_1_fma3;
-}
-btSingleConstraintRowSolver btSequentialImpulseConstraintSolver::getSSE4_1ConstraintRowSolverLowerLimit()
-{
- return gResolveSingleConstraintRowLowerLimit_sse4_1_fma3;
-}
-#endif //BT_ALLOW_SSE4
-#endif //USE_SIMD
-
-unsigned long btSequentialImpulseConstraintSolver::btRand2()
-{
- m_btSeed2 = (1664525L * m_btSeed2 + 1013904223L) & 0xffffffff;
- return m_btSeed2;
-}
-
-//See ODE: adam's all-int straightforward(?) dRandInt (0..n-1)
-int btSequentialImpulseConstraintSolver::btRandInt2(int n)
-{
- // seems good; xor-fold and modulus
- const unsigned long un = static_cast<unsigned long>(n);
- unsigned long r = btRand2();
-
- // note: probably more aggressive than it needs to be -- might be
- // able to get away without one or two of the innermost branches.
- if (un <= 0x00010000UL)
- {
- r ^= (r >> 16);
- if (un <= 0x00000100UL)
- {
- r ^= (r >> 8);
- if (un <= 0x00000010UL)
- {
- r ^= (r >> 4);
- if (un <= 0x00000004UL)
- {
- r ^= (r >> 2);
- if (un <= 0x00000002UL)
- {
- r ^= (r >> 1);
- }
- }
- }
- }
- }
-
- return (int)(r % un);
-}
-
-void btSequentialImpulseConstraintSolver::initSolverBody(btSolverBody* solverBody, btCollisionObject* collisionObject, btScalar timeStep)
-{
- btRigidBody* rb = collisionObject ? btRigidBody::upcast(collisionObject) : 0;
-
- solverBody->internalGetDeltaLinearVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetDeltaAngularVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetPushVelocity().setValue(0.f, 0.f, 0.f);
- solverBody->internalGetTurnVelocity().setValue(0.f, 0.f, 0.f);
-
- if (rb)
- {
- solverBody->m_worldTransform = rb->getWorldTransform();
- solverBody->internalSetInvMass(btVector3(rb->getInvMass(), rb->getInvMass(), rb->getInvMass()) * rb->getLinearFactor());
- solverBody->m_originalBody = rb;
- solverBody->m_angularFactor = rb->getAngularFactor();
- solverBody->m_linearFactor = rb->getLinearFactor();
- solverBody->m_linearVelocity = rb->getLinearVelocity();
- solverBody->m_angularVelocity = rb->getAngularVelocity();
- solverBody->m_externalForceImpulse = rb->getTotalForce() * rb->getInvMass() * timeStep;
- solverBody->m_externalTorqueImpulse = rb->getTotalTorque() * rb->getInvInertiaTensorWorld() * timeStep;
- }
- else
- {
- solverBody->m_worldTransform.setIdentity();
- solverBody->internalSetInvMass(btVector3(0, 0, 0));
- solverBody->m_originalBody = 0;
- solverBody->m_angularFactor.setValue(1, 1, 1);
- solverBody->m_linearFactor.setValue(1, 1, 1);
- solverBody->m_linearVelocity.setValue(0, 0, 0);
- solverBody->m_angularVelocity.setValue(0, 0, 0);
- solverBody->m_externalForceImpulse.setValue(0, 0, 0);
- solverBody->m_externalTorqueImpulse.setValue(0, 0, 0);
- }
- }
-
-btScalar btSequentialImpulseConstraintSolver::restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold)
-{
- //printf("rel_vel =%f\n", rel_vel);
- if (btFabs(rel_vel) < velocityThreshold)
- return 0.;
-
- btScalar rest = restitution * -rel_vel;
- return rest;
-}
-
-void btSequentialImpulseConstraintSolver::applyAnisotropicFriction(btCollisionObject* colObj, btVector3& frictionDirection, int frictionMode)
-{
- if (colObj && colObj->hasAnisotropicFriction(frictionMode))
- {
- // transform to local coordinates
- btVector3 loc_lateral = frictionDirection * colObj->getWorldTransform().getBasis();
- const btVector3& friction_scaling = colObj->getAnisotropicFriction();
- //apply anisotropic friction
- loc_lateral *= friction_scaling;
- // ... and transform it back to global coordinates
- frictionDirection = colObj->getWorldTransform().getBasis() * loc_lateral;
- }
-}
-
-void btSequentialImpulseConstraintSolver::setupFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_friction = cp.m_combinedFriction;
- solverConstraint.m_originalContactPoint = 0;
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- if (body0)
- {
- solverConstraint.m_contactNormal1 = normalAxis;
- btVector3 ftorqueAxis1 = rel_pos1.cross(solverConstraint.m_contactNormal1);
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor();
- }
- else
- {
- solverConstraint.m_contactNormal1.setZero();
- solverConstraint.m_relpos1CrossNormal.setZero();
- solverConstraint.m_angularComponentA.setZero();
- }
-
- if (bodyA)
- {
- solverConstraint.m_contactNormal2 = -normalAxis;
- btVector3 ftorqueAxis1 = rel_pos2.cross(solverConstraint.m_contactNormal2);
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor();
- }
- else
- {
- solverConstraint.m_contactNormal2.setZero();
- solverConstraint.m_relpos2CrossNormal.setZero();
- solverConstraint.m_angularComponentB.setZero();
- }
-
- {
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (body0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = body0->getInvMass() + normalAxis.dot(vec);
- }
- if (bodyA)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = bodyA->getInvMass() + normalAxis.dot(vec);
- }
- btScalar denom = relaxation / (denom0 + denom1);
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- {
- btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- // btScalar positionalError = 0.f;
-
- btScalar velocityError = desiredVelocity - rel_vel;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
-
- btScalar penetrationImpulse = btScalar(0);
-
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
- {
- btScalar distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(normalAxis);
- btScalar positionalError = -distance * infoGlobal.m_frictionERP / infoGlobal.m_timeStep;
- penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- }
-
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
- }
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = m_tmpSolverContactFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-void btSequentialImpulseConstraintSolver::setupTorsionalFrictionConstraint(btSolverConstraint& solverConstraint, const btVector3& normalAxis1, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity, btScalar cfmSlip)
-
-{
- btVector3 normalAxis(0, 0, 0);
-
- solverConstraint.m_contactNormal1 = normalAxis;
- solverConstraint.m_contactNormal2 = -normalAxis;
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* body0 = m_tmpSolverBodyPool[solverBodyIdA].m_originalBody;
- btRigidBody* bodyA = m_tmpSolverBodyPool[solverBodyIdB].m_originalBody;
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_friction = combinedTorsionalFriction;
- solverConstraint.m_originalContactPoint = 0;
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- btVector3 ftorqueAxis1 = -normalAxis1;
- solverConstraint.m_relpos1CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentA = body0 ? body0->getInvInertiaTensorWorld() * ftorqueAxis1 * body0->getAngularFactor() : btVector3(0, 0, 0);
- }
- {
- btVector3 ftorqueAxis1 = normalAxis1;
- solverConstraint.m_relpos2CrossNormal = ftorqueAxis1;
- solverConstraint.m_angularComponentB = bodyA ? bodyA->getInvInertiaTensorWorld() * ftorqueAxis1 * bodyA->getAngularFactor() : btVector3(0, 0, 0);
- }
-
- {
- btVector3 iMJaA = body0 ? body0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
- btVector3 iMJaB = bodyA ? bodyA->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
- btScalar sum = 0;
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- solverConstraint.m_jacDiagABInv = btScalar(1.) / sum;
- }
-
- {
- btScalar rel_vel;
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(body0 ? solverBodyA.m_linearVelocity + solverBodyA.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(body0 ? solverBodyA.m_angularVelocity : btVector3(0, 0, 0));
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyA ? solverBodyB.m_linearVelocity + solverBodyB.m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(bodyA ? solverBodyB.m_angularVelocity : btVector3(0, 0, 0));
-
- rel_vel = vel1Dotn + vel2Dotn;
-
- // btScalar positionalError = 0.f;
-
- btSimdScalar velocityError = desiredVelocity - rel_vel;
- btSimdScalar velocityImpulse = velocityError * btSimdScalar(solverConstraint.m_jacDiagABInv);
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_cfm = cfmSlip;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
- }
-}
-
-btSolverConstraint& btSequentialImpulseConstraintSolver::addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity, btScalar cfmSlip)
-{
- btSolverConstraint& solverConstraint = m_tmpSolverContactRollingFrictionConstraintPool.expandNonInitializing();
- solverConstraint.m_frictionIndex = frictionIndex;
- setupTorsionalFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, combinedTorsionalFriction, rel_pos1, rel_pos2,
- colObj0, colObj1, relaxation, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-int btSequentialImpulseConstraintSolver::getOrInitSolverBody(btCollisionObject& body, btScalar timeStep)
-{
-#if BT_THREADSAFE
- int solverBodyId = -1;
- const bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- const bool isStaticOrKinematic = body.isStaticOrKinematicObject();
- const bool isKinematic = body.isKinematicObject();
- if (isRigidBodyType && !isStaticOrKinematic)
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyId);
- }
- }
- else if (isRigidBodyType && isKinematic)
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (uniqueId >= m_kinematicBodyUniqueIdToSolverBodyTable.size())
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- // if no table entry yet,
- if (solverBodyId == INVALID_SOLVER_BODY_ID)
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
- }
- }
- else
- {
- bool isMultiBodyType = (body.getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK);
- // Incorrectly set collision object flags can degrade performance in various ways.
- if (!isMultiBodyType)
- {
- btAssert(body.isStaticOrKinematicObject());
- }
- //it could be a multibody link collider
- // all fixed bodies (inf mass) get mapped to a single solver id
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-#else // BT_THREADSAFE
-
- int solverBodyIdA = -1;
-
- if (body.getCompanionId() >= 0)
- {
- //body has already been converted
- solverBodyIdA = body.getCompanionId();
- btAssert(solverBodyIdA < m_tmpSolverBodyPool.size());
- }
- else
- {
- btRigidBody* rb = btRigidBody::upcast(&body);
- //convert both active and kinematic objects (for their velocity)
- if (rb && (rb->getInvMass() || rb->isKinematicObject()))
- {
- solverBodyIdA = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyIdA);
- }
- else
- {
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- return m_fixedBodyId;
- // return 0;//assume first one is a fixed solver body
- }
- }
-
- return solverBodyIdA;
-#endif // BT_THREADSAFE
-}
-#include <stdio.h>
-
-void btSequentialImpulseConstraintSolver::setupContactConstraint(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- const btVector3& rel_pos1, const btVector3& rel_pos2)
-{
- // const btVector3& pos1 = cp.getPositionWorldOnA();
- // const btVector3& pos2 = cp.getPositionWorldOnB();
-
- btSolverBody* bodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* bodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* rb0 = bodyA->m_originalBody;
- btRigidBody* rb1 = bodyB->m_originalBody;
-
- // btVector3 rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- // btVector3 rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
- //rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- //rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = infoGlobal.m_sor;
- btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
-
- //cfm = 1 / ( dt * kp + kd )
- //erp = dt * kp / ( dt * kp + kd )
-
- btScalar cfm = infoGlobal.m_globalCfm;
- btScalar erp = infoGlobal.m_erp2;
-
- if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
- cfm = cp.m_contactCFM;
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
- erp = cp.m_contactERP;
- }
- else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
- {
- btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
- if (denom < SIMD_EPSILON)
- {
- denom = SIMD_EPSILON;
- }
- cfm = btScalar(1) / denom;
- erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
- }
- }
-
- cfm *= invTimeStep;
-
- btVector3 torqueAxis0 = rel_pos1.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
- btVector3 torqueAxis1 = rel_pos2.cross(cp.m_normalWorldOnB);
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
-
- {
-#ifdef COMPUTE_IMPULSE_DENOM
- btScalar denom0 = rb0->computeImpulseDenominator(pos1, cp.m_normalWorldOnB);
- btScalar denom1 = rb1->computeImpulseDenominator(pos2, cp.m_normalWorldOnB);
-#else
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- if (rb0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
- if (rb1)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->getInvMass() + cp.m_normalWorldOnB.dot(vec);
- }
-#endif //COMPUTE_IMPULSE_DENOM
-
- btScalar denom = relaxation / (denom0 + denom1 + cfm);
- solverConstraint.m_jacDiagABInv = denom;
- }
-
- if (rb0)
- {
- solverConstraint.m_contactNormal1 = cp.m_normalWorldOnB;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- }
- else
- {
- solverConstraint.m_contactNormal1.setZero();
- solverConstraint.m_relpos1CrossNormal.setZero();
- }
- if (rb1)
- {
- solverConstraint.m_contactNormal2 = -cp.m_normalWorldOnB;
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- }
- else
- {
- solverConstraint.m_contactNormal2.setZero();
- solverConstraint.m_relpos2CrossNormal.setZero();
- }
-
- btScalar restitution = 0.f;
- btScalar penetration = cp.getDistance() + infoGlobal.m_linearSlop;
-
- {
- btVector3 vel1, vel2;
-
- vel1 = rb0 ? rb0->getVelocityInLocalPoint(rel_pos1) : btVector3(0, 0, 0);
- vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0, 0, 0);
-
- // btVector3 vel2 = rb1 ? rb1->getVelocityInLocalPoint(rel_pos2) : btVector3(0,0,0);
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
-
- solverConstraint.m_friction = cp.m_combinedFriction;
-
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- };
- }
-
- ///warm starting (or zero if disabled)
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- solverConstraint.m_appliedImpulse = cp.m_appliedImpulse * infoGlobal.m_warmstartingFactor;
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
-
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- btVector3 externalForceImpulseA = bodyA->m_originalBody ? bodyA->m_externalForceImpulse : btVector3(0, 0, 0);
- btVector3 externalTorqueImpulseA = bodyA->m_originalBody ? bodyA->m_externalTorqueImpulse : btVector3(0, 0, 0);
- btVector3 externalForceImpulseB = bodyB->m_originalBody ? bodyB->m_externalForceImpulse : btVector3(0, 0, 0);
- btVector3 externalTorqueImpulseB = bodyB->m_originalBody ? bodyB->m_externalTorqueImpulse : btVector3(0, 0, 0);
-
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(bodyA->m_linearVelocity + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(bodyA->m_angularVelocity + externalTorqueImpulseA);
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(bodyB->m_linearVelocity + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(bodyB->m_angularVelocity + externalTorqueImpulseB);
- btScalar rel_vel = vel1Dotn + vel2Dotn;
-
- btScalar positionalError = 0.f;
- btScalar velocityError = restitution - rel_vel; // * damping;
-
- if (penetration > 0)
- {
- positionalError = 0;
-
- velocityError -= penetration * invTimeStep;
- }
- else
- {
- positionalError = -penetration * erp * invTimeStep;
- }
-
- btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
-
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse; //-solverConstraint.m_contactNormal1.dot(bodyA->m_externalForce*bodyA->m_invMass-bodyB->m_externalForce/bodyB->m_invMass)*solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhsPenetration = 0.f;
- }
- else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
-}
-
-void btSequentialImpulseConstraintSolver::setFrictionConstraintImpulse(btSolverConstraint& solverConstraint,
- int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal)
-{
- {
- btSolverConstraint& frictionConstraint1 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex];
-
- frictionConstraint1.m_appliedImpulse = 0.f;
- }
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- btSolverConstraint& frictionConstraint2 = m_tmpSolverContactFrictionConstraintPool[solverConstraint.m_frictionIndex + 1];
-
- frictionConstraint2.m_appliedImpulse = 0.f;
- }
-}
-
-void btSequentialImpulseConstraintSolver::convertContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
-{
- btCollisionObject *colObj0 = 0, *colObj1 = 0;
-
- colObj0 = (btCollisionObject*)manifold->getBody0();
- colObj1 = (btCollisionObject*)manifold->getBody1();
-
- int solverBodyIdA = getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-
- // btRigidBody* bodyA = btRigidBody::upcast(colObj0);
- // btRigidBody* bodyB = btRigidBody::upcast(colObj1);
-
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- ///avoid collision response between two static objects
- if (!solverBodyA || (solverBodyA->m_invMass.fuzzyZero() && (!solverBodyB || solverBodyB->m_invMass.fuzzyZero())))
- return;
-
- int rollingFriction = 1;
- for (int j = 0; j < manifold->getNumContacts(); j++)
- {
- btManifoldPoint& cp = manifold->getContactPoint(j);
-
- if (cp.getDistance() <= manifold->getContactProcessingThreshold())
- {
- btVector3 rel_pos1;
- btVector3 rel_pos2;
- btScalar relaxation;
-
- int frictionIndex = m_tmpSolverContactConstraintPool.size();
- btSolverConstraint& solverConstraint = m_tmpSolverContactConstraintPool.expandNonInitializing();
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- rel_pos1 = pos1 - colObj0->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - colObj1->getWorldTransform().getOrigin();
-
- btVector3 vel1;
- btVector3 vel2;
-
- solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
- solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
-
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
-
- setupContactConstraint(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
-
- /////setup the friction constraints
-
- solverConstraint.m_frictionIndex = m_tmpSolverContactFrictionConstraintPool.size();
-
- if ((cp.m_combinedRollingFriction > 0.f) && (rollingFriction > 0))
- {
- {
- addTorsionalFrictionConstraint(cp.m_normalWorldOnB, solverBodyIdA, solverBodyIdB, frictionIndex, cp, cp.m_combinedSpinningFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- btVector3 axis0, axis1;
- btPlaneSpace1(cp.m_normalWorldOnB, axis0, axis1);
- axis0.normalize();
- axis1.normalize();
-
- applyAnisotropicFriction(colObj0, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis0, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- if (axis0.length() > 0.001)
- addTorsionalFrictionConstraint(axis0, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
- cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- if (axis1.length() > 0.001)
- addTorsionalFrictionConstraint(axis1, solverBodyIdA, solverBodyIdB, frictionIndex, cp,
- cp.m_combinedRollingFriction, rel_pos1, rel_pos2, colObj0, colObj1, relaxation);
- }
- }
-
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
-
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and use contactPoint.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
-
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize(); //??
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
- }
- else
- {
- btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
-
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- }
- else
- {
- addFrictionConstraint(cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addFrictionConstraint(cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, frictionIndex, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
- }
- setFrictionConstraintImpulse(solverConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
- }
- }
- }
-
-void btSequentialImpulseConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
-{
- int i;
- btPersistentManifold* manifold = 0;
- // btCollisionObject* colObj0=0,*colObj1=0;
-
- for (i = 0; i < numManifolds; i++)
- {
- manifold = manifoldPtr[i];
- convertContact(manifold, infoGlobal);
- }
-}
-
-void btSequentialImpulseConstraintSolver::convertJoint(btSolverConstraint* currentConstraintRow,
- btTypedConstraint* constraint,
- const btTypedConstraint::btConstraintInfo1& info1,
- int solverBodyIdA,
- int solverBodyIdB,
- const btContactSolverInfo& infoGlobal)
-{
- const btRigidBody& rbA = constraint->getRigidBodyA();
- const btRigidBody& rbB = constraint->getRigidBodyB();
-
- const btSolverBody* bodyAPtr = &m_tmpSolverBodyPool[solverBodyIdA];
- const btSolverBody* bodyBPtr = &m_tmpSolverBodyPool[solverBodyIdB];
-
- int overrideNumSolverIterations = constraint->getOverrideNumSolverIterations() > 0 ? constraint->getOverrideNumSolverIterations() : infoGlobal.m_numIterations;
- if (overrideNumSolverIterations > m_maxOverrideNumSolverIterations)
- m_maxOverrideNumSolverIterations = overrideNumSolverIterations;
-
- for (int j = 0; j < info1.m_numConstraintRows; j++)
- {
- memset(&currentConstraintRow[j], 0, sizeof(btSolverConstraint));
- currentConstraintRow[j].m_lowerLimit = -SIMD_INFINITY;
- currentConstraintRow[j].m_upperLimit = SIMD_INFINITY;
- currentConstraintRow[j].m_appliedImpulse = 0.f;
- currentConstraintRow[j].m_appliedPushImpulse = 0.f;
- currentConstraintRow[j].m_solverBodyIdA = solverBodyIdA;
- currentConstraintRow[j].m_solverBodyIdB = solverBodyIdB;
- currentConstraintRow[j].m_overrideNumSolverIterations = overrideNumSolverIterations;
- }
-
- // these vectors are already cleared in initSolverBody, no need to redundantly clear again
- btAssert(bodyAPtr->getDeltaLinearVelocity().isZero());
- btAssert(bodyAPtr->getDeltaAngularVelocity().isZero());
- btAssert(bodyAPtr->getPushVelocity().isZero());
- btAssert(bodyAPtr->getTurnVelocity().isZero());
- btAssert(bodyBPtr->getDeltaLinearVelocity().isZero());
- btAssert(bodyBPtr->getDeltaAngularVelocity().isZero());
- btAssert(bodyBPtr->getPushVelocity().isZero());
- btAssert(bodyBPtr->getTurnVelocity().isZero());
- //bodyAPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- //bodyAPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- //bodyAPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- //bodyAPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
- //bodyBPtr->internalGetDeltaLinearVelocity().setValue(0.f,0.f,0.f);
- //bodyBPtr->internalGetDeltaAngularVelocity().setValue(0.f,0.f,0.f);
- //bodyBPtr->internalGetPushVelocity().setValue(0.f,0.f,0.f);
- //bodyBPtr->internalGetTurnVelocity().setValue(0.f,0.f,0.f);
-
- btTypedConstraint::btConstraintInfo2 info2;
- info2.fps = 1.f / infoGlobal.m_timeStep;
- info2.erp = infoGlobal.m_erp;
- info2.m_J1linearAxis = currentConstraintRow->m_contactNormal1;
- info2.m_J1angularAxis = currentConstraintRow->m_relpos1CrossNormal;
- info2.m_J2linearAxis = currentConstraintRow->m_contactNormal2;
- info2.m_J2angularAxis = currentConstraintRow->m_relpos2CrossNormal;
- info2.rowskip = sizeof(btSolverConstraint) / sizeof(btScalar); //check this
- ///the size of btSolverConstraint needs be a multiple of btScalar
- btAssert(info2.rowskip * sizeof(btScalar) == sizeof(btSolverConstraint));
- info2.m_constraintError = &currentConstraintRow->m_rhs;
- currentConstraintRow->m_cfm = infoGlobal.m_globalCfm;
- info2.m_damping = infoGlobal.m_damping;
- info2.cfm = &currentConstraintRow->m_cfm;
- info2.m_lowerLimit = &currentConstraintRow->m_lowerLimit;
- info2.m_upperLimit = &currentConstraintRow->m_upperLimit;
- info2.m_numIterations = infoGlobal.m_numIterations;
- constraint->getInfo2(&info2);
-
- ///finalize the constraint setup
- for (int j = 0; j < info1.m_numConstraintRows; j++)
- {
- btSolverConstraint& solverConstraint = currentConstraintRow[j];
-
- if (solverConstraint.m_upperLimit >= constraint->getBreakingImpulseThreshold())
- {
- solverConstraint.m_upperLimit = constraint->getBreakingImpulseThreshold();
- }
-
- if (solverConstraint.m_lowerLimit <= -constraint->getBreakingImpulseThreshold())
- {
- solverConstraint.m_lowerLimit = -constraint->getBreakingImpulseThreshold();
- }
-
- solverConstraint.m_originalContactPoint = constraint;
-
- {
- const btVector3& ftorqueAxis1 = solverConstraint.m_relpos1CrossNormal;
- solverConstraint.m_angularComponentA = constraint->getRigidBodyA().getInvInertiaTensorWorld() * ftorqueAxis1 * constraint->getRigidBodyA().getAngularFactor();
- }
- {
- const btVector3& ftorqueAxis2 = solverConstraint.m_relpos2CrossNormal;
- solverConstraint.m_angularComponentB = constraint->getRigidBodyB().getInvInertiaTensorWorld() * ftorqueAxis2 * constraint->getRigidBodyB().getAngularFactor();
- }
-
- {
- btVector3 iMJlA = solverConstraint.m_contactNormal1 * rbA.getInvMass();
- btVector3 iMJaA = rbA.getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal;
- btVector3 iMJlB = solverConstraint.m_contactNormal2 * rbB.getInvMass(); //sign of normal?
- btVector3 iMJaB = rbB.getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal;
-
- btScalar sum = iMJlA.dot(solverConstraint.m_contactNormal1);
- sum += iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- sum += iMJlB.dot(solverConstraint.m_contactNormal2);
- sum += iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- btScalar fsum = btFabs(sum);
- btAssert(fsum > SIMD_EPSILON);
- btScalar sorRelaxation = 1.f; //todo: get from globalInfo?
- solverConstraint.m_jacDiagABInv = fsum > SIMD_EPSILON ? sorRelaxation / sum : 0.f;
- }
-
- {
- btScalar rel_vel;
- btVector3 externalForceImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalForceImpulse : btVector3(0, 0, 0);
- btVector3 externalTorqueImpulseA = bodyAPtr->m_originalBody ? bodyAPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
-
- btVector3 externalForceImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalForceImpulse : btVector3(0, 0, 0);
- btVector3 externalTorqueImpulseB = bodyBPtr->m_originalBody ? bodyBPtr->m_externalTorqueImpulse : btVector3(0, 0, 0);
-
- btScalar vel1Dotn = solverConstraint.m_contactNormal1.dot(rbA.getLinearVelocity() + externalForceImpulseA) + solverConstraint.m_relpos1CrossNormal.dot(rbA.getAngularVelocity() + externalTorqueImpulseA);
-
- btScalar vel2Dotn = solverConstraint.m_contactNormal2.dot(rbB.getLinearVelocity() + externalForceImpulseB) + solverConstraint.m_relpos2CrossNormal.dot(rbB.getAngularVelocity() + externalTorqueImpulseB);
-
- rel_vel = vel1Dotn + vel2Dotn;
- btScalar restitution = 0.f;
- btScalar positionalError = solverConstraint.m_rhs; //already filled in by getConstraintInfo2
- btScalar velocityError = restitution - rel_vel * info2.m_damping;
- btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_appliedImpulse = 0.f;
- }
- }
-}
-
-void btSequentialImpulseConstraintSolver::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("convertJoints");
- for (int j = 0; j < numConstraints; j++)
- {
- btTypedConstraint* constraint = constraints[j];
- constraint->buildJacobian();
- constraint->internalSetAppliedImpulse(0.0f);
- }
-
- int totalNumRows = 0;
-
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- //calculate the total number of contraint rows
- for (int i = 0; i < numConstraints; i++)
- {
- btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- btJointFeedback* fb = constraints[i]->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
-
- if (constraints[i]->isEnabled())
- {
- constraints[i]->getInfo1(&info1);
- }
- else
- {
- info1.m_numConstraintRows = 0;
- info1.nub = 0;
- }
- totalNumRows += info1.m_numConstraintRows;
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
-
- ///setup the btSolverConstraints
- int currentRow = 0;
-
- for (int i = 0; i < numConstraints; i++)
- {
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
-
- if (info1.m_numConstraintRows)
- {
- btAssert(currentRow < totalNumRows);
-
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
- btTypedConstraint* constraint = constraints[i];
- btRigidBody& rbA = constraint->getRigidBodyA();
- btRigidBody& rbB = constraint->getRigidBodyB();
-
- int solverBodyIdA = getOrInitSolverBody(rbA, infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBody(rbB, infoGlobal.m_timeStep);
-
- convertJoint(currentConstraintRow, constraint, info1, solverBodyIdA, solverBodyIdB, infoGlobal);
- }
- currentRow += info1.m_numConstraintRows;
- }
-}
-
-void btSequentialImpulseConstraintSolver::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("convertBodies");
- for (int i = 0; i < numBodies; i++)
- {
- bodies[i]->setCompanionId(-1);
- }
-#if BT_THREADSAFE
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
-#endif // BT_THREADSAFE
-
- m_tmpSolverBodyPool.reserve(numBodies + 1);
- m_tmpSolverBodyPool.resize(0);
-
- //btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- //initSolverBody(&fixedBody,0);
-
- for (int i = 0; i < numBodies; i++)
- {
- int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
-
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body && body->getInvMass())
- {
- btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
- btVector3 gyroForce(0, 0, 0);
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
- {
- gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- }
- }
-}
-
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- m_fixedBodyId = -1;
- BT_PROFILE("solveGroupCacheFriendlySetup");
- (void)debugDrawer;
-
- // if solver mode has changed,
- if (infoGlobal.m_solverMode != m_cachedSolverMode)
- {
- // update solver functions to use SIMD or non-SIMD
- bool useSimd = !!(infoGlobal.m_solverMode & SOLVER_SIMD);
- setupSolverFunctions(useSimd);
- m_cachedSolverMode = infoGlobal.m_solverMode;
- }
- m_maxOverrideNumSolverIterations = 0;
-
-#ifdef BT_ADDITIONAL_DEBUG
- //make sure that dynamic bodies exist for all (enabled) constraints
- for (int i = 0; i < numConstraints; i++)
- {
- btTypedConstraint* constraint = constraints[i];
- if (constraint->isEnabled())
- {
- if (!constraint->getRigidBodyA().isStaticOrKinematicObject())
- {
- bool found = false;
- for (int b = 0; b < numBodies; b++)
- {
- if (&constraint->getRigidBodyA() == bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- if (!constraint->getRigidBodyB().isStaticOrKinematicObject())
- {
- bool found = false;
- for (int b = 0; b < numBodies; b++)
- {
- if (&constraint->getRigidBodyB() == bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- }
- }
- //make sure that dynamic bodies exist for all contact manifolds
- for (int i = 0; i < numManifolds; i++)
- {
- if (!manifoldPtr[i]->getBody0()->isStaticOrKinematicObject())
- {
- bool found = false;
- for (int b = 0; b < numBodies; b++)
- {
- if (manifoldPtr[i]->getBody0() == bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- if (!manifoldPtr[i]->getBody1()->isStaticOrKinematicObject())
- {
- bool found = false;
- for (int b = 0; b < numBodies; b++)
- {
- if (manifoldPtr[i]->getBody1() == bodies[b])
- {
- found = true;
- break;
- }
- }
- btAssert(found);
- }
- }
-#endif //BT_ADDITIONAL_DEBUG
-
- //convert all bodies
- convertBodies(bodies, numBodies, infoGlobal);
-
- convertJoints(constraints, numConstraints, infoGlobal);
-
- convertContacts(manifoldPtr, numManifolds, infoGlobal);
-
- // btContactSolverInfo info = infoGlobal;
-
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- ///@todo: use stack allocator for such temporarily memory, same for solver bodies/constraints
- m_orderNonContactConstraintPool.resizeNoInitialize(numNonContactPool);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool * 2);
- else
- m_orderTmpConstraintPool.resizeNoInitialize(numConstraintPool);
-
- m_orderFrictionConstraintPool.resizeNoInitialize(numFrictionPool);
- {
- int i;
- for (i = 0; i < numNonContactPool; i++)
- {
- m_orderNonContactConstraintPool[i] = i;
- }
- for (i = 0; i < numConstraintPool; i++)
- {
- m_orderTmpConstraintPool[i] = i;
- }
- for (i = 0; i < numFrictionPool; i++)
- {
- m_orderFrictionConstraintPool[i] = i;
- }
- }
-
- return 0.f;
-}
-
-btScalar btSequentialImpulseConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** /*bodies */, int /*numBodies*/, btPersistentManifold** /*manifoldPtr*/, int /*numManifolds*/, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* /*debugDrawer*/)
-{
- BT_PROFILE("solveSingleIteration");
- btScalar leastSquaresResidual = 0.f;
-
- int numNonContactPool = m_tmpSolverNonContactConstraintPool.size();
- int numConstraintPool = m_tmpSolverContactConstraintPool.size();
- int numFrictionPool = m_tmpSolverContactFrictionConstraintPool.size();
-
- if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- for (int j = 0; j < numNonContactPool; ++j)
- {
- int tmp = m_orderNonContactConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderNonContactConstraintPool[j] = m_orderNonContactConstraintPool[swapi];
- m_orderNonContactConstraintPool[swapi] = tmp;
- }
-
- //contact/friction constraints are not solved more than
- if (iteration < infoGlobal.m_numIterations)
- {
- for (int j = 0; j < numConstraintPool; ++j)
- {
- int tmp = m_orderTmpConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderTmpConstraintPool[j] = m_orderTmpConstraintPool[swapi];
- m_orderTmpConstraintPool[swapi] = tmp;
- }
-
- for (int j = 0; j < numFrictionPool; ++j)
- {
- int tmp = m_orderFrictionConstraintPool[j];
- int swapi = btRandInt2(j + 1);
- m_orderFrictionConstraintPool[j] = m_orderFrictionConstraintPool[swapi];
- m_orderFrictionConstraintPool[swapi] = tmp;
- }
- }
- }
- }
-
- ///solve all joint constraints
- for (int j = 0; j < m_tmpSolverNonContactConstraintPool.size(); j++)
- {
- btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[m_orderNonContactConstraintPool[j]];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[constraint.m_solverBodyIdA], m_tmpSolverBodyPool[constraint.m_solverBodyIdB], constraint);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
-
- if (iteration < infoGlobal.m_numIterations)
- {
- for (int j = 0; j < numConstraints; j++)
- {
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
- }
- }
-
- ///solve all contact constraints
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int multiplier = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
-
- for (int c = 0; c < numPoolConstraints; c++)
- {
- btScalar totalImpulse = 0;
-
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[c]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
-
- totalImpulse = solveManifold.m_appliedImpulse;
- }
- bool applyFriction = true;
- if (applyFriction)
- {
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier]];
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
-
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[c * multiplier + 1]];
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
- }
- }
- }
- else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- //solve the friction constraints after all contact constraints, don't interleave them
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
-
- for (j = 0; j < numPoolConstraints; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
-
- ///solve all friction constraints
-
- int numFrictionPoolConstraints = m_tmpSolverContactFrictionConstraintPool.size();
- for (j = 0; j < numFrictionPoolConstraints; j++)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[m_orderFrictionConstraintPool[j]];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
-
- if (totalImpulse > btScalar(0))
- {
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
- }
-
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > btScalar(0))
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
- }
- return leastSquaresResidual;
-}
-
-void btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
- int iteration;
- if (infoGlobal.m_splitImpulse)
- {
- {
- for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- btScalar leastSquaresResidual = 0.f;
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j = 0; j < numPoolConstraints; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
-
- btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- }
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
- {
-#ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
-#endif
- break;
- }
- }
- }
- }
-}
-
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- BT_PROFILE("solveGroupCacheFriendlyIterations");
-
- {
- ///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
-
- for (int iteration = 0; iteration < maxIterations; iteration++)
- //for ( int iteration = maxIterations-1 ; iteration >= 0;iteration--)
- {
- m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
- {
-#ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
-#endif
- m_analyticsData.m_numSolverCalls++;
- m_analyticsData.m_numIterationsUsed = iteration+1;
- m_analyticsData.m_islandId = -2;
- if (numBodies>0)
- m_analyticsData.m_islandId = bodies[0]->getCompanionId();
- m_analyticsData.m_numBodies = numBodies;
- m_analyticsData.m_numContactManifolds = numManifolds;
- m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
- break;
- }
- }
- }
- return 0.f;
-}
-
-void btSequentialImpulseConstraintSolver::writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- for (int j = iBegin; j < iEnd; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[j];
- btManifoldPoint* pt = (btManifoldPoint*)solveManifold.m_originalContactPoint;
- btAssert(pt);
- pt->m_appliedImpulse = solveManifold.m_appliedImpulse;
- // float f = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- // printf("pt->m_appliedImpulseLateral1 = %f\n", f);
- pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex].m_appliedImpulse;
- //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[solveManifold.m_frictionIndex + 1].m_appliedImpulse;
- }
- //do a callback here?
- }
-}
-
-void btSequentialImpulseConstraintSolver::writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- for (int j = iBegin; j < iEnd; j++)
- {
- const btSolverConstraint& solverConstr = m_tmpSolverNonContactConstraintPool[j];
- btTypedConstraint* constr = (btTypedConstraint*)solverConstr.m_originalContactPoint;
- btJointFeedback* fb = constr->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA += solverConstr.m_contactNormal1 * solverConstr.m_appliedImpulse * constr->getRigidBodyA().getLinearFactor() / infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += solverConstr.m_contactNormal2 * solverConstr.m_appliedImpulse * constr->getRigidBodyB().getLinearFactor() / infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += solverConstr.m_relpos1CrossNormal * constr->getRigidBodyA().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += solverConstr.m_relpos2CrossNormal * constr->getRigidBodyB().getAngularFactor() * solverConstr.m_appliedImpulse / infoGlobal.m_timeStep; /*RGM ???? */
- }
-
- constr->internalSetAppliedImpulse(solverConstr.m_appliedImpulse);
- if (btFabs(solverConstr.m_appliedImpulse) >= constr->getBreakingImpulseThreshold())
- {
- constr->setEnabled(false);
- }
- }
-}
-
-void btSequentialImpulseConstraintSolver::writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- for (int i = iBegin; i < iEnd; i++)
- {
- btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
- if (body)
- {
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].writebackVelocityAndTransform(infoGlobal.m_timeStep, infoGlobal.m_splitImpulseTurnErp);
- else
- m_tmpSolverBodyPool[i].writebackVelocity();
-
- m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(
- m_tmpSolverBodyPool[i].m_linearVelocity +
- m_tmpSolverBodyPool[i].m_externalForceImpulse);
-
- m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(
- m_tmpSolverBodyPool[i].m_angularVelocity +
- m_tmpSolverBodyPool[i].m_externalTorqueImpulse);
-
- if (infoGlobal.m_splitImpulse)
- m_tmpSolverBodyPool[i].m_originalBody->setWorldTransform(m_tmpSolverBodyPool[i].m_worldTransform);
-
- m_tmpSolverBodyPool[i].m_originalBody->setCompanionId(-1);
- }
- }
-}
-
-btScalar btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("solveGroupCacheFriendlyFinish");
-
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- writeBackContacts(0, m_tmpSolverContactConstraintPool.size(), infoGlobal);
- }
-
- writeBackJoints(0, m_tmpSolverNonContactConstraintPool.size(), infoGlobal);
- writeBackBodies(0, m_tmpSolverBodyPool.size(), infoGlobal);
-
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
-
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
-}
-
-/// btSequentialImpulseConstraintSolver Sequentially applies impulses
-btScalar btSequentialImpulseConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer, btDispatcher* /*dispatcher*/)
-{
- BT_PROFILE("solveGroup");
- //you need to provide at least some bodies
-
- solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
-
- return 0.f;
-}
-
-void btSequentialImpulseConstraintSolver::reset()
-{
- m_btSeed2 = 0;
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
deleted file mode 100644
index f3ef02fccc..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
-#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
-
-class btIDebugDraw;
-class btPersistentManifold;
-class btDispatcher;
-class btCollisionObject;
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
-#include "BulletDynamics/ConstraintSolver/btSolverConstraint.h"
-#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
-#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
-
-typedef btScalar (*btSingleConstraintRowSolver)(btSolverBody&, btSolverBody&, const btSolverConstraint&);
-
-struct btSolverAnalyticsData
-{
- btSolverAnalyticsData()
- {
- m_numSolverCalls = 0;
- m_numIterationsUsed = -1;
- m_remainingLeastSquaresResidual = -1;
- m_islandId = -2;
- }
- int m_islandId;
- int m_numBodies;
- int m_numContactManifolds;
- int m_numSolverCalls;
- int m_numIterationsUsed;
- double m_remainingLeastSquaresResidual;
-};
-
-///The btSequentialImpulseConstraintSolver is a fast SIMD implementation of the Projected Gauss Seidel (iterative LCP) method.
-ATTRIBUTE_ALIGNED16(class)
-btSequentialImpulseConstraintSolver : public btConstraintSolver
-{
-
-
-protected:
- btAlignedObjectArray<btSolverBody> m_tmpSolverBodyPool;
- btConstraintArray m_tmpSolverContactConstraintPool;
- btConstraintArray m_tmpSolverNonContactConstraintPool;
- btConstraintArray m_tmpSolverContactFrictionConstraintPool;
- btConstraintArray m_tmpSolverContactRollingFrictionConstraintPool;
-
- btAlignedObjectArray<int> m_orderTmpConstraintPool;
- btAlignedObjectArray<int> m_orderNonContactConstraintPool;
- btAlignedObjectArray<int> m_orderFrictionConstraintPool;
- btAlignedObjectArray<btTypedConstraint::btConstraintInfo1> m_tmpConstraintSizesPool;
- int m_maxOverrideNumSolverIterations;
- int m_fixedBodyId;
- // When running solvers on multiple threads, a race condition exists for Kinematic objects that
- // participate in more than one solver.
- // The getOrInitSolverBody() function writes the companionId of each body (storing the index of the solver body
- // for the current solver). For normal dynamic bodies it isn't an issue because they can only be in one island
- // (and therefore one thread) at a time. But kinematic bodies can be in multiple islands at once.
- // To avoid this race condition, this solver does not write the companionId, instead it stores the solver body
- // index in this solver-local table, indexed by the uniqueId of the body.
- btAlignedObjectArray<int> m_kinematicBodyUniqueIdToSolverBodyTable; // only used for multithreading
-
- btSingleConstraintRowSolver m_resolveSingleConstraintRowGeneric;
- btSingleConstraintRowSolver m_resolveSingleConstraintRowLowerLimit;
- btSingleConstraintRowSolver m_resolveSplitPenetrationImpulse;
- int m_cachedSolverMode; // used to check if SOLVER_SIMD flag has been changed
- void setupSolverFunctions(bool useSimd);
-
- btScalar m_leastSquaresResidual;
-
- void setupFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- const btContactSolverInfo& infoGlobal,
- btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
-
- void setupTorsionalFrictionConstraint(btSolverConstraint & solverConstraint, const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, btScalar combinedTorsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation,
- btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
-
- btSolverConstraint& addFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0., btScalar cfmSlip = 0.);
- btSolverConstraint& addTorsionalFrictionConstraint(const btVector3& normalAxis, int solverBodyIdA, int solverBodyIdB, int frictionIndex, btManifoldPoint& cp, btScalar torsionalFriction, const btVector3& rel_pos1, const btVector3& rel_pos2, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, btScalar desiredVelocity = 0, btScalar cfmSlip = 0.f);
-
- void setupContactConstraint(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB, btManifoldPoint& cp,
- const btContactSolverInfo& infoGlobal, btScalar& relaxation, const btVector3& rel_pos1, const btVector3& rel_pos2);
-
- static void applyAnisotropicFriction(btCollisionObject * colObj, btVector3 & frictionDirection, int frictionMode);
-
- void setFrictionConstraintImpulse(btSolverConstraint & solverConstraint, int solverBodyIdA, int solverBodyIdB,
- btManifoldPoint& cp, const btContactSolverInfo& infoGlobal);
-
- ///m_btSeed2 is used for re-arranging the constraint rows. improves convergence/quality of friction
- unsigned long m_btSeed2;
-
- btScalar restitutionCurve(btScalar rel_vel, btScalar restitution, btScalar velocityThreshold);
-
- virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
-
- void convertContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
-
- virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal);
- void convertJoint(btSolverConstraint * currentConstraintRow, btTypedConstraint * constraint, const btTypedConstraint::btConstraintInfo1& info1, int solverBodyIdA, int solverBodyIdB, const btContactSolverInfo& infoGlobal);
-
- virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
-
- btScalar resolveSplitPenetrationSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
- }
-
- btScalar resolveSplitPenetrationImpulseCacheFriendly(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
- }
-
- //internal method
- int getOrInitSolverBody(btCollisionObject & body, btScalar timeStep);
- void initSolverBody(btSolverBody * solverBody, btCollisionObject * collisionObject, btScalar timeStep);
-
- btScalar resolveSingleConstraintRowGeneric(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowGenericSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowLowerLimit(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
- btScalar resolveSingleConstraintRowLowerLimitSIMD(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint);
- btScalar resolveSplitPenetrationImpulse(btSolverBody & bodyA, btSolverBody & bodyB, const btSolverConstraint& contactConstraint)
- {
- return m_resolveSplitPenetrationImpulse(bodyA, bodyB, contactConstraint);
- }
-
-protected:
- void writeBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void writeBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void writeBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btSequentialImpulseConstraintSolver();
- virtual ~btSequentialImpulseConstraintSolver();
-
- virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
-
- ///clear internal cached data and reset random seed
- virtual void reset();
-
- unsigned long btRand2();
-
- int btRandInt2(int n);
-
- void setRandSeed(unsigned long seed)
- {
- m_btSeed2 = seed;
- }
- unsigned long getRandSeed() const
- {
- return m_btSeed2;
- }
-
- virtual btConstraintSolverType getSolverType() const
- {
- return BT_SEQUENTIAL_IMPULSE_SOLVER;
- }
-
- btSingleConstraintRowSolver getActiveConstraintRowSolverGeneric()
- {
- return m_resolveSingleConstraintRowGeneric;
- }
- void setConstraintRowSolverGeneric(btSingleConstraintRowSolver rowSolver)
- {
- m_resolveSingleConstraintRowGeneric = rowSolver;
- }
- btSingleConstraintRowSolver getActiveConstraintRowSolverLowerLimit()
- {
- return m_resolveSingleConstraintRowLowerLimit;
- }
- void setConstraintRowSolverLowerLimit(btSingleConstraintRowSolver rowSolver)
- {
- m_resolveSingleConstraintRowLowerLimit = rowSolver;
- }
-
-
-
- ///Various implementations of solving a single constraint row using a generic equality constraint, using scalar reference, SSE2 or SSE4
- btSingleConstraintRowSolver getScalarConstraintRowSolverGeneric();
- btSingleConstraintRowSolver getSSE2ConstraintRowSolverGeneric();
- btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverGeneric();
-
- ///Various implementations of solving a single constraint row using an inequality (lower limit) constraint, using scalar reference, SSE2 or SSE4
- btSingleConstraintRowSolver getScalarConstraintRowSolverLowerLimit();
- btSingleConstraintRowSolver getSSE2ConstraintRowSolverLowerLimit();
- btSingleConstraintRowSolver getSSE4_1ConstraintRowSolverLowerLimit();
- btSolverAnalyticsData m_analyticsData;
-};
-
-#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
deleted file mode 100644
index 2718da4a50..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp
+++ /dev/null
@@ -1,1554 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSequentialImpulseConstraintSolverMt.h"
-
-#include "LinearMath/btQuickprof.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-bool btSequentialImpulseConstraintSolverMt::s_allowNestedParallelForLoops = false; // some task schedulers don't like nested loops
-int btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching = 250;
-int btSequentialImpulseConstraintSolverMt::s_minBatchSize = 50;
-int btSequentialImpulseConstraintSolverMt::s_maxBatchSize = 100;
-btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_contactBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
-btBatchedConstraints::BatchingMethod btSequentialImpulseConstraintSolverMt::s_jointBatchingMethod = btBatchedConstraints::BATCHING_METHOD_SPATIAL_GRID_2D;
-
-btSequentialImpulseConstraintSolverMt::btSequentialImpulseConstraintSolverMt()
-{
- m_numFrictionDirections = 1;
- m_useBatching = false;
- m_useObsoleteJointConstraints = false;
-}
-
-btSequentialImpulseConstraintSolverMt::~btSequentialImpulseConstraintSolverMt()
-{
-}
-
-void btSequentialImpulseConstraintSolverMt::setupBatchedContactConstraints()
-{
- BT_PROFILE("setupBatchedContactConstraints");
- m_batchedContactConstraints.setup(&m_tmpSolverContactConstraintPool,
- m_tmpSolverBodyPool,
- s_contactBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory);
-}
-
-void btSequentialImpulseConstraintSolverMt::setupBatchedJointConstraints()
-{
- BT_PROFILE("setupBatchedJointConstraints");
- m_batchedJointConstraints.setup(&m_tmpSolverNonContactConstraintPool,
- m_tmpSolverBodyPool,
- s_jointBatchingMethod,
- s_minBatchSize,
- s_maxBatchSize,
- &m_scratchMemory);
-}
-
-void btSequentialImpulseConstraintSolverMt::internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal)
-{
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[iContactConstraint];
-
- btVector3 rel_pos1;
- btVector3 rel_pos2;
- btScalar relaxation;
-
- int solverBodyIdA = contactConstraint.m_solverBodyIdA;
- int solverBodyIdB = contactConstraint.m_solverBodyIdB;
-
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- btRigidBody* colObj0 = solverBodyA->m_originalBody;
- btRigidBody* colObj1 = solverBodyB->m_originalBody;
-
- btManifoldPoint& cp = *static_cast<btManifoldPoint*>(contactConstraint.m_originalContactPoint);
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- rel_pos1 = pos1 - solverBodyA->getWorldTransform().getOrigin();
- rel_pos2 = pos2 - solverBodyB->getWorldTransform().getOrigin();
-
- btVector3 vel1;
- btVector3 vel2;
-
- solverBodyA->getVelocityInLocalPointNoDelta(rel_pos1, vel1);
- solverBodyB->getVelocityInLocalPointNoDelta(rel_pos2, vel2);
-
- btVector3 vel = vel1 - vel2;
- btScalar rel_vel = cp.m_normalWorldOnB.dot(vel);
-
- setupContactConstraint(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal, relaxation, rel_pos1, rel_pos2);
-
- // setup rolling friction constraints
- int rollingFrictionIndex = m_rollingFrictionIndexTable[iContactConstraint];
- if (rollingFrictionIndex >= 0)
- {
- btSolverConstraint& spinningFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex];
- btAssert(spinningFrictionConstraint.m_frictionIndex == iContactConstraint);
- setupTorsionalFrictionConstraint(spinningFrictionConstraint,
- cp.m_normalWorldOnB,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedSpinningFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f);
- btVector3 axis[2];
- btPlaneSpace1(cp.m_normalWorldOnB, axis[0], axis[1]);
- axis[0].normalize();
- axis[1].normalize();
-
- applyAnisotropicFriction(colObj0, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis[0], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, axis[1], btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- // put the largest axis first
- if (axis[1].length2() > axis[0].length2())
- {
- btSwap(axis[0], axis[1]);
- }
- const btScalar kRollingFrictionThreshold = 0.001f;
- for (int i = 0; i < 2; ++i)
- {
- int iRollingFric = rollingFrictionIndex + 1 + i;
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- btAssert(rollingFrictionConstraint.m_frictionIndex == iContactConstraint);
- btVector3 dir = axis[i];
- if (dir.length() > kRollingFrictionThreshold)
- {
- setupTorsionalFrictionConstraint(rollingFrictionConstraint,
- dir,
- solverBodyIdA,
- solverBodyIdB,
- cp,
- cp.m_combinedRollingFriction,
- rel_pos1,
- rel_pos2,
- colObj0,
- colObj1,
- relaxation,
- 0.0f,
- 0.0f);
- }
- else
- {
- rollingFrictionConstraint.m_frictionIndex = -1; // disable constraint
- }
- }
- }
-
- // setup friction constraints
- // setupFrictionConstraint(solverConstraint, normalAxis, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, desiredVelocity, cfmSlip);
- {
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically very frame
- ///based on the relative linear velocity.
- ///If the relative velocity it zero, it will automatically compute a friction direction.
-
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
- btSolverConstraint* frictionConstraint1 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex];
- btAssert(frictionConstraint1->m_frictionIndex == iContactConstraint);
-
- btSolverConstraint* frictionConstraint2 = NULL;
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS)
- {
- frictionConstraint2 = &m_tmpSolverContactFrictionConstraintPool[contactConstraint.m_frictionIndex + 1];
- btAssert(frictionConstraint2->m_frictionIndex == iContactConstraint);
- }
-
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- {
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f / btSqrt(lat_rel_vel);
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
-
- if (frictionConstraint2)
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize(); //??
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
- }
- else
- {
- btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
-
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
-
- if (frictionConstraint2)
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal);
- }
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- }
- else
- {
- setupFrictionConstraint(*frictionConstraint1, cp.m_lateralFrictionDir1, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
- if (frictionConstraint2)
- {
- setupFrictionConstraint(*frictionConstraint2, cp.m_lateralFrictionDir2, solverBodyIdA, solverBodyIdB, cp, rel_pos1, rel_pos2, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
- }
- }
- }
-
- setFrictionConstraintImpulse(contactConstraint, solverBodyIdA, solverBodyIdB, cp, infoGlobal);
-}
-
-struct SetupContactConstraintsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- const btContactSolverInfo* m_infoGlobal;
-
- SetupContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_bc = bc;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("SetupContactConstraintsLoop");
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- for (int i = batch.begin; i < batch.end; ++i)
- {
- int iContact = m_bc->m_constraintIndices[i];
- m_solver->internalSetupContactConstraints(iContact, *m_infoGlobal);
- }
- }
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::setupAllContactConstraints(const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("setupAllContactConstraints");
- if (m_useBatching)
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- SetupContactConstraintsLoop loop(this, &batchedCons, infoGlobal);
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- btParallelFor(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); ++i)
- {
- internalSetupContactConstraints(i, infoGlobal);
- }
- }
-}
-
-int btSequentialImpulseConstraintSolverMt::getOrInitSolverBodyThreadsafe(btCollisionObject& body, btScalar timeStep)
-{
- //
- // getOrInitSolverBody is threadsafe only for a single thread per solver (with potentially multiple solvers)
- //
- // getOrInitSolverBodyThreadsafe -- attempts to be fully threadsafe (however may affect determinism)
- //
- int solverBodyId = -1;
- bool isRigidBodyType = btRigidBody::upcast(&body) != NULL;
- if (isRigidBodyType && !body.isStaticOrKinematicObject())
- {
- // dynamic body
- // Dynamic bodies can only be in one island, so it's safe to write to the companionId
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = body.getCompanionId();
- if (solverBodyId < 0)
- {
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- body.setCompanionId(solverBodyId);
- }
- m_bodySolverArrayMutex.unlock();
- }
- }
- else if (isRigidBodyType && body.isKinematicObject())
- {
- //
- // NOTE: must test for kinematic before static because some kinematic objects also
- // identify as "static"
- //
- // Kinematic bodies can be in multiple islands at once, so it is a
- // race condition to write to them, so we use an alternate method
- // to record the solverBodyId
- int uniqueId = body.getWorldArrayIndex();
- const int INVALID_SOLVER_BODY_ID = -1;
- if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
- {
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- // now that we have the lock, check again
- if (m_kinematicBodyUniqueIdToSolverBodyTable.size() <= uniqueId)
- {
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(uniqueId + 1, INVALID_SOLVER_BODY_ID);
- }
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- // if no table entry yet,
- if (INVALID_SOLVER_BODY_ID == solverBodyId)
- {
- // need to acquire both locks
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.lock();
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- solverBodyId = m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId];
- if (INVALID_SOLVER_BODY_ID == solverBodyId)
- {
- // create a table entry for this body
- solverBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& solverBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&solverBody, &body, timeStep);
- m_kinematicBodyUniqueIdToSolverBodyTable[uniqueId] = solverBodyId;
- }
- m_bodySolverArrayMutex.unlock();
- m_kinematicBodyUniqueIdToSolverBodyTableMutex.unlock();
- }
- }
- else
- {
- // all fixed bodies (inf mass) get mapped to a single solver id
- if (m_fixedBodyId < 0)
- {
- m_bodySolverArrayMutex.lock();
- // now that we have the lock, check again
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, timeStep);
- }
- m_bodySolverArrayMutex.unlock();
- }
- solverBodyId = m_fixedBodyId;
- }
- btAssert(solverBodyId >= 0 && solverBodyId < m_tmpSolverBodyPool.size());
- return solverBodyId;
-}
-
-void btSequentialImpulseConstraintSolverMt::internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalCollectContactManifoldCachedInfo");
- for (int i = 0; i < numManifolds; ++i)
- {
- btContactManifoldCachedInfo* cachedInfo = &cachedInfoArray[i];
- btPersistentManifold* manifold = manifoldPtr[i];
- btCollisionObject* colObj0 = (btCollisionObject*)manifold->getBody0();
- btCollisionObject* colObj1 = (btCollisionObject*)manifold->getBody1();
-
- int solverBodyIdA = getOrInitSolverBodyThreadsafe(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = getOrInitSolverBodyThreadsafe(*colObj1, infoGlobal.m_timeStep);
-
- cachedInfo->solverBodyIds[0] = solverBodyIdA;
- cachedInfo->solverBodyIds[1] = solverBodyIdB;
- cachedInfo->numTouchingContacts = 0;
-
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverBodyIdA];
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverBodyIdB];
-
- // A contact manifold between 2 static object should not exist!
- // check the collision flags of your objects if this assert fires.
- // Incorrectly set collision object flags can degrade performance in various ways.
- btAssert(!m_tmpSolverBodyPool[solverBodyIdA].m_invMass.isZero() || !m_tmpSolverBodyPool[solverBodyIdB].m_invMass.isZero());
-
- int iContact = 0;
- for (int j = 0; j < manifold->getNumContacts(); j++)
- {
- btManifoldPoint& cp = manifold->getContactPoint(j);
-
- if (cp.getDistance() <= manifold->getContactProcessingThreshold())
- {
- cachedInfo->contactPoints[iContact] = &cp;
- cachedInfo->contactHasRollingFriction[iContact] = (cp.m_combinedRollingFriction > 0.f);
- iContact++;
- }
- }
- cachedInfo->numTouchingContacts = iContact;
- }
-}
-
-struct CollectContactManifoldCachedInfoLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
- btPersistentManifold** m_manifoldPtr;
- const btContactSolverInfo* m_infoGlobal;
-
- CollectContactManifoldCachedInfoLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray, btPersistentManifold** manifoldPtr, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- m_manifoldPtr = manifoldPtr;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalCollectContactManifoldCachedInfo(m_cachedInfoArray + iBegin, m_manifoldPtr + iBegin, iEnd - iBegin, *m_infoGlobal);
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds)
-{
- BT_PROFILE("internalAllocContactConstraints");
- // possibly parallel part
- for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
- {
- const btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
- int contactIndex = cachedInfo.contactIndex;
- int frictionIndex = contactIndex * m_numFrictionDirections;
- int rollingFrictionIndex = cachedInfo.rollingFrictionIndex;
- for (int i = 0; i < cachedInfo.numTouchingContacts; i++)
- {
- btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[contactIndex];
- contactConstraint.m_solverBodyIdA = cachedInfo.solverBodyIds[0];
- contactConstraint.m_solverBodyIdB = cachedInfo.solverBodyIds[1];
- contactConstraint.m_originalContactPoint = cachedInfo.contactPoints[i];
-
- // allocate the friction constraints
- contactConstraint.m_frictionIndex = frictionIndex;
- for (int iDir = 0; iDir < m_numFrictionDirections; ++iDir)
- {
- btSolverConstraint& frictionConstraint = m_tmpSolverContactFrictionConstraintPool[frictionIndex];
- frictionConstraint.m_frictionIndex = contactIndex;
- frictionIndex++;
- }
-
- // allocate rolling friction constraints
- if (cachedInfo.contactHasRollingFriction[i])
- {
- m_rollingFrictionIndexTable[contactIndex] = rollingFrictionIndex;
- // allocate 3 (although we may use only 2 sometimes)
- for (int i = 0; i < 3; i++)
- {
- m_tmpSolverContactRollingFrictionConstraintPool[rollingFrictionIndex].m_frictionIndex = contactIndex;
- rollingFrictionIndex++;
- }
- }
- else
- {
- // indicate there is no rolling friction for this contact point
- m_rollingFrictionIndexTable[contactIndex] = -1;
- }
- contactIndex++;
- }
- }
-}
-
-struct AllocContactConstraintsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* m_cachedInfoArray;
-
- AllocContactConstraintsLoop(btSequentialImpulseConstraintSolverMt* solver, btSequentialImpulseConstraintSolverMt::btContactManifoldCachedInfo* cachedInfoArray)
- {
- m_solver = solver;
- m_cachedInfoArray = cachedInfoArray;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalAllocContactConstraints(m_cachedInfoArray + iBegin, iEnd - iBegin);
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::allocAllContactConstraints(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("allocAllContactConstraints");
- btAlignedObjectArray<btContactManifoldCachedInfo> cachedInfoArray; // = m_manifoldCachedInfoArray;
- cachedInfoArray.resizeNoInitialize(numManifolds);
- if (/* DISABLES CODE */ (false))
- {
- // sequential
- internalCollectContactManifoldCachedInfo(&cachedInfoArray[0], manifoldPtr, numManifolds, infoGlobal);
- }
- else
- {
- // may alter ordering of bodies which affects determinism
- CollectContactManifoldCachedInfoLoop loop(this, &cachedInfoArray[0], manifoldPtr, infoGlobal);
- int grainSize = 200;
- btParallelFor(0, numManifolds, grainSize, loop);
- }
-
- {
- // serial part
- int numContacts = 0;
- int numRollingFrictionConstraints = 0;
- for (int iManifold = 0; iManifold < numManifolds; ++iManifold)
- {
- btContactManifoldCachedInfo& cachedInfo = cachedInfoArray[iManifold];
- cachedInfo.contactIndex = numContacts;
- cachedInfo.rollingFrictionIndex = numRollingFrictionConstraints;
- numContacts += cachedInfo.numTouchingContacts;
- for (int i = 0; i < cachedInfo.numTouchingContacts; ++i)
- {
- if (cachedInfo.contactHasRollingFriction[i])
- {
- numRollingFrictionConstraints += 3;
- }
- }
- }
- {
- BT_PROFILE("allocPools");
- if (m_tmpSolverContactConstraintPool.capacity() < numContacts)
- {
- // if we need to reallocate, reserve some extra so we don't have to reallocate again next frame
- int extraReserve = numContacts / 16;
- m_tmpSolverContactConstraintPool.reserve(numContacts + extraReserve);
- m_rollingFrictionIndexTable.reserve(numContacts + extraReserve);
- m_tmpSolverContactFrictionConstraintPool.reserve((numContacts + extraReserve) * m_numFrictionDirections);
- m_tmpSolverContactRollingFrictionConstraintPool.reserve(numRollingFrictionConstraints + extraReserve);
- }
- m_tmpSolverContactConstraintPool.resizeNoInitialize(numContacts);
- m_rollingFrictionIndexTable.resizeNoInitialize(numContacts);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(numContacts * m_numFrictionDirections);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(numRollingFrictionConstraints);
- }
- }
- {
- AllocContactConstraintsLoop loop(this, &cachedInfoArray[0]);
- int grainSize = 200;
- btParallelFor(0, numManifolds, grainSize, loop);
- }
-}
-
-void btSequentialImpulseConstraintSolverMt::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
-{
- if (!m_useBatching)
- {
- btSequentialImpulseConstraintSolver::convertContacts(manifoldPtr, numManifolds, infoGlobal);
- return;
- }
- BT_PROFILE("convertContacts");
- if (numManifolds > 0)
- {
- if (m_fixedBodyId < 0)
- {
- m_fixedBodyId = m_tmpSolverBodyPool.size();
- btSolverBody& fixedBody = m_tmpSolverBodyPool.expand();
- initSolverBody(&fixedBody, 0, infoGlobal.m_timeStep);
- }
- allocAllContactConstraints(manifoldPtr, numManifolds, infoGlobal);
- if (m_useBatching)
- {
- setupBatchedContactConstraints();
- }
- setupAllContactConstraints(infoGlobal);
- }
-}
-
-void btSequentialImpulseConstraintSolverMt::internalInitMultipleJoints(btTypedConstraint** constraints, int iBegin, int iEnd)
-{
- BT_PROFILE("internalInitMultipleJoints");
- for (int i = iBegin; i < iEnd; i++)
- {
- btTypedConstraint* constraint = constraints[i];
- btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- if (constraint->isEnabled())
- {
- constraint->buildJacobian();
- constraint->internalSetAppliedImpulse(0.0f);
- btJointFeedback* fb = constraint->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA.setZero();
- fb->m_appliedTorqueBodyA.setZero();
- fb->m_appliedForceBodyB.setZero();
- fb->m_appliedTorqueBodyB.setZero();
- }
- constraint->getInfo1(&info1);
- }
- else
- {
- info1.m_numConstraintRows = 0;
- info1.nub = 0;
- }
- }
-}
-
-struct InitJointsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btTypedConstraint** m_constraints;
-
- InitJointsLoop(btSequentialImpulseConstraintSolverMt* solver, btTypedConstraint** constraints)
- {
- m_solver = solver;
- m_constraints = constraints;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalInitMultipleJoints(m_constraints, iBegin, iEnd);
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalConvertMultipleJoints");
- for (int i = iBegin; i < iEnd; ++i)
- {
- const JointParams& jointParams = jointParamsArray[i];
- int currentRow = jointParams.m_solverConstraint;
- if (currentRow != -1)
- {
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
- btAssert(currentRow < m_tmpSolverNonContactConstraintPool.size());
- btAssert(info1.m_numConstraintRows > 0);
-
- btSolverConstraint* currentConstraintRow = &m_tmpSolverNonContactConstraintPool[currentRow];
- btTypedConstraint* constraint = constraints[i];
-
- convertJoint(currentConstraintRow, constraint, info1, jointParams.m_solverBodyA, jointParams.m_solverBodyB, infoGlobal);
- }
- }
-}
-
-struct ConvertJointsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& m_jointParamsArray;
- btTypedConstraint** m_srcConstraints;
- const btContactSolverInfo& m_infoGlobal;
-
- ConvertJointsLoop(btSequentialImpulseConstraintSolverMt* solver,
- const btAlignedObjectArray<btSequentialImpulseConstraintSolverMt::JointParams>& jointParamsArray,
- btTypedConstraint** srcConstraints,
- const btContactSolverInfo& infoGlobal) : m_jointParamsArray(jointParamsArray),
- m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_srcConstraints = srcConstraints;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalConvertMultipleJoints(m_jointParamsArray, m_srcConstraints, iBegin, iEnd, m_infoGlobal);
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::convertJoints(btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal)
-{
- if (!m_useBatching)
- {
- btSequentialImpulseConstraintSolver::convertJoints(constraints, numConstraints, infoGlobal);
- return;
- }
- BT_PROFILE("convertJoints");
- bool parallelJointSetup = true;
- m_tmpConstraintSizesPool.resizeNoInitialize(numConstraints);
- if (parallelJointSetup)
- {
- InitJointsLoop loop(this, constraints);
- int grainSize = 40;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalInitMultipleJoints(constraints, 0, numConstraints);
- }
-
- int totalNumRows = 0;
- btAlignedObjectArray<JointParams> jointParamsArray;
- jointParamsArray.resizeNoInitialize(numConstraints);
-
- //calculate the total number of contraint rows
- for (int i = 0; i < numConstraints; i++)
- {
- btTypedConstraint* constraint = constraints[i];
-
- JointParams& params = jointParamsArray[i];
- const btTypedConstraint::btConstraintInfo1& info1 = m_tmpConstraintSizesPool[i];
-
- if (info1.m_numConstraintRows)
- {
- params.m_solverConstraint = totalNumRows;
- params.m_solverBodyA = getOrInitSolverBody(constraint->getRigidBodyA(), infoGlobal.m_timeStep);
- params.m_solverBodyB = getOrInitSolverBody(constraint->getRigidBodyB(), infoGlobal.m_timeStep);
- }
- else
- {
- params.m_solverConstraint = -1;
- }
- totalNumRows += info1.m_numConstraintRows;
- }
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(totalNumRows);
-
- ///setup the btSolverConstraints
- if (parallelJointSetup)
- {
- ConvertJointsLoop loop(this, jointParamsArray, constraints, infoGlobal);
- int grainSize = 20;
- btParallelFor(0, numConstraints, grainSize, loop);
- }
- else
- {
- internalConvertMultipleJoints(jointParamsArray, constraints, 0, numConstraints, infoGlobal);
- }
- setupBatchedJointConstraints();
-}
-
-void btSequentialImpulseConstraintSolverMt::internalConvertBodies(btCollisionObject** bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalConvertBodies");
- for (int i = iBegin; i < iEnd; i++)
- {
- btCollisionObject* obj = bodies[i];
- obj->setCompanionId(i);
- btSolverBody& solverBody = m_tmpSolverBodyPool[i];
- initSolverBody(&solverBody, obj, infoGlobal.m_timeStep);
-
- btRigidBody* body = btRigidBody::upcast(obj);
- if (body && body->getInvMass())
- {
- btVector3 gyroForce(0, 0, 0);
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT)
- {
- gyroForce = body->computeGyroscopicForceExplicit(infoGlobal.m_maxGyroscopicForce);
- solverBody.m_externalTorqueImpulse -= gyroForce * body->getInvInertiaTensorWorld() * infoGlobal.m_timeStep;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_World(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- if (body->getFlags() & BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY)
- {
- gyroForce = body->computeGyroscopicImpulseImplicit_Body(infoGlobal.m_timeStep);
- solverBody.m_externalTorqueImpulse += gyroForce;
- }
- }
- }
-}
-
-struct ConvertBodiesLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- btCollisionObject** m_bodies;
- int m_numBodies;
- const btContactSolverInfo& m_infoGlobal;
-
- ConvertBodiesLoop(btSequentialImpulseConstraintSolverMt* solver,
- btCollisionObject** bodies,
- int numBodies,
- const btContactSolverInfo& infoGlobal) : m_infoGlobal(infoGlobal)
- {
- m_solver = solver;
- m_bodies = bodies;
- m_numBodies = numBodies;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalConvertBodies(m_bodies, iBegin, iEnd, m_infoGlobal);
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::convertBodies(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("convertBodies");
- m_kinematicBodyUniqueIdToSolverBodyTable.resize(0);
-
- m_tmpSolverBodyPool.resizeNoInitialize(numBodies + 1);
-
- m_fixedBodyId = numBodies;
- {
- btSolverBody& fixedBody = m_tmpSolverBodyPool[m_fixedBodyId];
- initSolverBody(&fixedBody, NULL, infoGlobal.m_timeStep);
- }
-
- bool parallelBodySetup = true;
- if (parallelBodySetup)
- {
- ConvertBodiesLoop loop(this, bodies, numBodies, infoGlobal);
- int grainSize = 40;
- btParallelFor(0, numBodies, grainSize, loop);
- }
- else
- {
- internalConvertBodies(bodies, 0, numBodies, infoGlobal);
- }
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySetup(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer)
-{
- m_numFrictionDirections = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) ? 2 : 1;
- m_useBatching = false;
- if (numManifolds >= s_minimumContactManifoldsForBatching &&
- (s_allowNestedParallelForLoops || !btThreadsAreRunning()))
- {
- m_useBatching = true;
- m_batchedContactConstraints.m_debugDrawer = debugDrawer;
- m_batchedJointConstraints.m_debugDrawer = debugDrawer;
- }
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies,
- numBodies,
- manifoldPtr,
- numManifolds,
- constraints,
- numConstraints,
- infoGlobal,
- debugDrawer);
- return 0.0f;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
-{
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSplitPenetrationImpulse(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- return leastSquaresResidual;
-}
-
-struct ContactSplitPenetrationImpulseSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactSplitPenetrationImpulseSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactSplitPenetrationImpulseSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactSplitPenetrationImpulseConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
-};
-
-void btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
- if (infoGlobal.m_splitImpulse)
- {
- for (int iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- btScalar leastSquaresResidual = 0.f;
- if (m_useBatching)
- {
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSplitPenetrationImpulseSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- // non-batched
- leastSquaresResidual = resolveMultipleContactSplitPenetrationImpulseConstraints(m_orderTmpConstraintPool, 0, m_tmpSolverContactConstraintPool.size());
- }
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
- {
-#ifdef VERBOSE_RESIDUAL_PRINTF
- printf("residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
-#endif
- break;
- }
- }
- }
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- if (!m_useBatching)
- {
- return btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- }
- BT_PROFILE("solveSingleIterationMt");
- btScalar leastSquaresResidual = 0.f;
-
- if (infoGlobal.m_solverMode & SOLVER_RANDMIZE_ORDER)
- {
- if (1) // uncomment this for a bit less random ((iteration & 7) == 0)
- {
- randomizeConstraintOrdering(iteration, infoGlobal.m_numIterations);
- }
- }
-
- {
- ///solve all joint constraints
- leastSquaresResidual += resolveAllJointConstraints(iteration);
-
- if (iteration < infoGlobal.m_numIterations)
- {
- // this loop is only used for cone-twist constraints,
- // it would be nice to skip this loop if none of the constraints need it
- if (m_useObsoleteJointConstraints)
- {
- for (int j = 0; j < numConstraints; j++)
- {
- if (constraints[j]->isEnabled())
- {
- int bodyAid = getOrInitSolverBody(constraints[j]->getRigidBodyA(), infoGlobal.m_timeStep);
- int bodyBid = getOrInitSolverBody(constraints[j]->getRigidBodyB(), infoGlobal.m_timeStep);
- btSolverBody& bodyA = m_tmpSolverBodyPool[bodyAid];
- btSolverBody& bodyB = m_tmpSolverBodyPool[bodyBid];
- constraints[j]->solveConstraintObsolete(bodyA, bodyB, infoGlobal.m_timeStep);
- }
- }
- }
-
- if (infoGlobal.m_solverMode & SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS)
- {
- // solve all contact, contact-friction, and rolling friction constraints interleaved
- leastSquaresResidual += resolveAllContactConstraintsInterleaved();
- }
- else //SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS
- {
- // don't interleave them
- // solve all contact constraints
- leastSquaresResidual += resolveAllContactConstraints();
-
- // solve all contact friction constraints
- leastSquaresResidual += resolveAllContactFrictionConstraints();
-
- // solve all rolling friction constraints
- leastSquaresResidual += resolveAllRollingFrictionConstraints();
- }
- }
- }
- return leastSquaresResidual;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration)
-{
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& constraint = m_tmpSolverNonContactConstraintPool[iCons];
- if (iteration < constraint.m_overrideNumSolverIterations)
- {
- btSolverBody& bodyA = m_tmpSolverBodyPool[constraint.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[constraint.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, constraint);
- leastSquaresResidual += residual * residual;
- }
- }
- return leastSquaresResidual;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
-{
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iCons = consIndices[iiCons];
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iCons];
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowLowerLimit(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- return leastSquaresResidual;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
-{
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iContact = consIndices[iiCons];
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
-
- // apply sliding friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction++];
- btAssert(solveManifold.m_frictionIndex == iContact);
-
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- return leastSquaresResidual;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd)
-{
- btScalar leastSquaresResidual = 0.f;
- for (int iiCons = batchBegin; iiCons < batchEnd; ++iiCons)
- {
- int iContact = consIndices[iiCons];
- int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
- if (iFirstRollingFriction >= 0)
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[iContact].m_appliedImpulse;
- // apply rolling friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- if (rollingFrictionConstraint.m_frictionIndex != iContact)
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- }
- return leastSquaresResidual;
-}
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices,
- int batchBegin,
- int batchEnd)
-{
- btScalar leastSquaresResidual = 0.f;
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
-
- for (int iiCons = batchBegin; iiCons < batchEnd; iiCons++)
- {
- btScalar totalImpulse = 0;
- int iContact = contactIndices[iiCons];
- // apply penetration constraint
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[iContact];
- btScalar residual = resolveSingleConstraintRowLowerLimit(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual += residual * residual;
- totalImpulse = solveManifold.m_appliedImpulse;
- }
-
- // apply sliding friction
- if (totalImpulse > 0.0f)
- {
- int iBegin = iContact * m_numFrictionDirections;
- int iEnd = iBegin + m_numFrictionDirections;
- for (int iFriction = iBegin; iFriction < iEnd; ++iFriction)
- {
- btSolverConstraint& solveManifold = m_tmpSolverContactFrictionConstraintPool[iFriction];
- btAssert(solveManifold.m_frictionIndex == iContact);
-
- solveManifold.m_lowerLimit = -(solveManifold.m_friction * totalImpulse);
- solveManifold.m_upperLimit = solveManifold.m_friction * totalImpulse;
-
- btSolverBody& bodyA = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA];
- btSolverBody& bodyB = m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB];
- btScalar residual = resolveSingleConstraintRowGeneric(bodyA, bodyB, solveManifold);
- leastSquaresResidual += residual * residual;
- }
- }
-
- // apply rolling friction
- int iFirstRollingFriction = m_rollingFrictionIndexTable[iContact];
- if (totalImpulse > 0.0f && iFirstRollingFriction >= 0)
- {
- int iBegin = iFirstRollingFriction;
- int iEnd = iBegin + 3;
- for (int iRollingFric = iBegin; iRollingFric < iEnd; ++iRollingFric)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[iRollingFric];
- if (rollingFrictionConstraint.m_frictionIndex != iContact)
- {
- break;
- }
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- {
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
- }
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- return leastSquaresResidual;
-}
-
-void btSequentialImpulseConstraintSolverMt::randomizeBatchedConstraintOrdering(btBatchedConstraints* batchedConstraints)
-{
- btBatchedConstraints& bc = *batchedConstraints;
- // randomize ordering of phases
- for (int ii = 1; ii < bc.m_phaseOrder.size(); ++ii)
- {
- int iSwap = btRandInt2(ii + 1);
- bc.m_phaseOrder.swap(ii, iSwap);
- }
-
- // for each batch,
- for (int iBatch = 0; iBatch < bc.m_batches.size(); ++iBatch)
- {
- // randomize ordering of constraints within the batch
- const btBatchedConstraints::Range& batch = bc.m_batches[iBatch];
- for (int iiCons = batch.begin; iiCons < batch.end; ++iiCons)
- {
- int iSwap = batch.begin + btRandInt2(iiCons - batch.begin + 1);
- btAssert(iSwap >= batch.begin && iSwap < batch.end);
- bc.m_constraintIndices.swap(iiCons, iSwap);
- }
- }
-}
-
-void btSequentialImpulseConstraintSolverMt::randomizeConstraintOrdering(int iteration, int numIterations)
-{
- // randomize ordering of joint constraints
- randomizeBatchedConstraintOrdering(&m_batchedJointConstraints);
-
- //contact/friction constraints are not solved more than numIterations
- if (iteration < numIterations)
- {
- randomizeBatchedConstraintOrdering(&m_batchedContactConstraints);
- }
-}
-
-struct JointSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
- int m_iteration;
-
- JointSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc, int iteration)
- {
- m_solver = solver;
- m_bc = bc;
- m_iteration = iteration;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("JointSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleJointConstraints(m_bc->m_constraintIndices, batch.begin, batch.end, m_iteration);
- }
- return sum;
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveAllJointConstraints(int iteration)
-{
- BT_PROFILE("resolveAllJointConstraints");
- const btBatchedConstraints& batchedCons = m_batchedJointConstraints;
- JointSolverLoop loop(this, &batchedCons, iteration);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
-}
-
-struct ContactSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraints()
-{
- BT_PROFILE("resolveAllContactConstraints");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
-}
-
-struct ContactFrictionSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactFrictionSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactFrictionConstraints()
-{
- BT_PROFILE("resolveAllContactFrictionConstraints");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactFrictionSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = batchedCons.m_phaseGrainSize[iPhase];
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
-}
-
-struct InterleavedContactSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- InterleavedContactSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("InterleavedContactSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactConstraintsInterleaved(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveAllContactConstraintsInterleaved()
-{
- BT_PROFILE("resolveAllContactConstraintsInterleaved");
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- InterleavedContactSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- return leastSquaresResidual;
-}
-
-struct ContactRollingFrictionSolverLoop : public btIParallelSumBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btBatchedConstraints* m_bc;
-
- ContactRollingFrictionSolverLoop(btSequentialImpulseConstraintSolverMt* solver, const btBatchedConstraints* bc)
- {
- m_solver = solver;
- m_bc = bc;
- }
- btScalar sumLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- BT_PROFILE("ContactFrictionSolverLoop");
- btScalar sum = 0;
- for (int iBatch = iBegin; iBatch < iEnd; ++iBatch)
- {
- const btBatchedConstraints::Range& batch = m_bc->m_batches[iBatch];
- sum += m_solver->resolveMultipleContactRollingFrictionConstraints(m_bc->m_constraintIndices, batch.begin, batch.end);
- }
- return sum;
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::resolveAllRollingFrictionConstraints()
-{
- BT_PROFILE("resolveAllRollingFrictionConstraints");
- btScalar leastSquaresResidual = 0.f;
- //
- // We do not generate batches for rolling friction constraints. We assume that
- // one of two cases is true:
- //
- // 1. either most bodies in the simulation have rolling friction, in which case we can use the
- // batches for contacts and use a lookup table to translate contact indices to rolling friction
- // (ignoring any contact indices that don't map to a rolling friction constraint). As long as
- // most contacts have a corresponding rolling friction constraint, this should parallelize well.
- //
- // -OR-
- //
- // 2. few bodies in the simulation have rolling friction, so it is not worth trying to use the
- // batches from contacts as most of the contacts won't have corresponding rolling friction
- // constraints and most threads would end up doing very little work. Most of the time would
- // go to threading overhead, so we don't bother with threading.
- //
- int numRollingFrictionPoolConstraints = m_tmpSolverContactRollingFrictionConstraintPool.size();
- if (numRollingFrictionPoolConstraints >= m_tmpSolverContactConstraintPool.size())
- {
- // use batching if there are many rolling friction constraints
- const btBatchedConstraints& batchedCons = m_batchedContactConstraints;
- ContactRollingFrictionSolverLoop loop(this, &batchedCons);
- btScalar leastSquaresResidual = 0.f;
- for (int iiPhase = 0; iiPhase < batchedCons.m_phases.size(); ++iiPhase)
- {
- int iPhase = batchedCons.m_phaseOrder[iiPhase];
- const btBatchedConstraints::Range& phase = batchedCons.m_phases[iPhase];
- int grainSize = 1;
- leastSquaresResidual += btParallelSum(phase.begin, phase.end, grainSize, loop);
- }
- }
- else
- {
- // no batching, also ignores SOLVER_RANDMIZE_ORDER
- for (int j = 0; j < numRollingFrictionPoolConstraints; j++)
- {
- btSolverConstraint& rollingFrictionConstraint = m_tmpSolverContactRollingFrictionConstraintPool[j];
- if (rollingFrictionConstraint.m_frictionIndex >= 0)
- {
- btScalar totalImpulse = m_tmpSolverContactConstraintPool[rollingFrictionConstraint.m_frictionIndex].m_appliedImpulse;
- if (totalImpulse > 0.0f)
- {
- btScalar rollingFrictionMagnitude = rollingFrictionConstraint.m_friction * totalImpulse;
- if (rollingFrictionMagnitude > rollingFrictionConstraint.m_friction)
- rollingFrictionMagnitude = rollingFrictionConstraint.m_friction;
-
- rollingFrictionConstraint.m_lowerLimit = -rollingFrictionMagnitude;
- rollingFrictionConstraint.m_upperLimit = rollingFrictionMagnitude;
-
- btScalar residual = resolveSingleConstraintRowGeneric(m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdA], m_tmpSolverBodyPool[rollingFrictionConstraint.m_solverBodyIdB], rollingFrictionConstraint);
- leastSquaresResidual += residual * residual;
- }
- }
- }
- }
- return leastSquaresResidual;
-}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalWriteBackContacts");
- writeBackContacts(iBegin, iEnd, infoGlobal);
- //for ( int iContact = iBegin; iContact < iEnd; ++iContact)
- //{
- // const btSolverConstraint& contactConstraint = m_tmpSolverContactConstraintPool[ iContact ];
- // btManifoldPoint* pt = (btManifoldPoint*) contactConstraint.m_originalContactPoint;
- // btAssert( pt );
- // pt->m_appliedImpulse = contactConstraint.m_appliedImpulse;
- // pt->m_appliedImpulseLateral1 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex ].m_appliedImpulse;
- // if ( m_numFrictionDirections == 2 )
- // {
- // pt->m_appliedImpulseLateral2 = m_tmpSolverContactFrictionConstraintPool[ contactConstraint.m_frictionIndex + 1 ].m_appliedImpulse;
- // }
- //}
-}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalWriteBackJoints");
- writeBackJoints(iBegin, iEnd, infoGlobal);
-}
-
-void btSequentialImpulseConstraintSolverMt::internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("internalWriteBackBodies");
- writeBackBodies(iBegin, iEnd, infoGlobal);
-}
-
-struct WriteContactPointsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteContactPointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackContacts(iBegin, iEnd, *m_infoGlobal);
- }
-};
-
-struct WriteJointsLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteJointsLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackJoints(iBegin, iEnd, *m_infoGlobal);
- }
-};
-
-struct WriteBodiesLoop : public btIParallelForBody
-{
- btSequentialImpulseConstraintSolverMt* m_solver;
- const btContactSolverInfo* m_infoGlobal;
-
- WriteBodiesLoop(btSequentialImpulseConstraintSolverMt* solver, const btContactSolverInfo& infoGlobal)
- {
- m_solver = solver;
- m_infoGlobal = &infoGlobal;
- }
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- m_solver->internalWriteBackBodies(iBegin, iEnd, *m_infoGlobal);
- }
-};
-
-btScalar btSequentialImpulseConstraintSolverMt::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("solveGroupCacheFriendlyFinish");
-
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- WriteContactPointsLoop loop(this, infoGlobal);
- int grainSize = 500;
- btParallelFor(0, m_tmpSolverContactConstraintPool.size(), grainSize, loop);
- }
-
- {
- WriteJointsLoop loop(this, infoGlobal);
- int grainSize = 400;
- btParallelFor(0, m_tmpSolverNonContactConstraintPool.size(), grainSize, loop);
- }
- {
- WriteBodiesLoop loop(this, infoGlobal);
- int grainSize = 100;
- btParallelFor(0, m_tmpSolverBodyPool.size(), grainSize, loop);
- }
-
- m_tmpSolverContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverNonContactConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactFrictionConstraintPool.resizeNoInitialize(0);
- m_tmpSolverContactRollingFrictionConstraintPool.resizeNoInitialize(0);
-
- m_tmpSolverBodyPool.resizeNoInitialize(0);
- return 0.f;
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
deleted file mode 100644
index 1861ddd7d7..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
-#define BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
-
-#include "btSequentialImpulseConstraintSolver.h"
-#include "btBatchedConstraints.h"
-#include "LinearMath/btThreads.h"
-
-///
-/// btSequentialImpulseConstraintSolverMt
-///
-/// A multithreaded variant of the sequential impulse constraint solver. The constraints to be solved are grouped into
-/// batches and phases where each batch of constraints within a given phase can be solved in parallel with the rest.
-/// Ideally we want as few phases as possible, and each phase should have many batches, and all of the batches should
-/// have about the same number of constraints.
-/// This method works best on a large island of many constraints.
-///
-/// Supports all of the features of the normal sequential impulse solver such as:
-/// - split penetration impulse
-/// - rolling friction
-/// - interleaving constraints
-/// - warmstarting
-/// - 2 friction directions
-/// - randomized constraint ordering
-/// - early termination when leastSquaresResidualThreshold is satisfied
-///
-/// When the SOLVER_INTERLEAVE_CONTACT_AND_FRICTION_CONSTRAINTS flag is enabled, unlike the normal SequentialImpulse solver,
-/// the rolling friction is interleaved as well.
-/// Interleaving the contact penetration constraints with friction reduces the number of parallel loops that need to be done,
-/// which reduces threading overhead so it can be a performance win, however, it does seem to produce a less stable simulation,
-/// at least on stacks of blocks.
-///
-/// When the SOLVER_RANDMIZE_ORDER flag is enabled, the ordering of phases, and the ordering of constraints within each batch
-/// is randomized, however it does not swap constraints between batches.
-/// This is to avoid regenerating the batches for each solver iteration which would be quite costly in performance.
-///
-/// Note that a non-zero leastSquaresResidualThreshold could possibly affect the determinism of the simulation
-/// if the task scheduler's parallelSum operation is non-deterministic. The parallelSum operation can be non-deterministic
-/// because floating point addition is not associative due to rounding errors.
-/// The task scheduler can and should ensure that the result of any parallelSum operation is deterministic.
-///
-ATTRIBUTE_ALIGNED16(class)
-btSequentialImpulseConstraintSolverMt : public btSequentialImpulseConstraintSolver
-{
-public:
- virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer) BT_OVERRIDE;
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
-
- // temp struct used to collect info from persistent manifolds into a cache-friendly struct using multiple threads
- struct btContactManifoldCachedInfo
- {
- static const int MAX_NUM_CONTACT_POINTS = 4;
-
- int numTouchingContacts;
- int solverBodyIds[2];
- int contactIndex;
- int rollingFrictionIndex;
- bool contactHasRollingFriction[MAX_NUM_CONTACT_POINTS];
- btManifoldPoint* contactPoints[MAX_NUM_CONTACT_POINTS];
- };
- // temp struct used for setting up joint constraints in parallel
- struct JointParams
- {
- int m_solverConstraint;
- int m_solverBodyA;
- int m_solverBodyB;
- };
- void internalInitMultipleJoints(btTypedConstraint * *constraints, int iBegin, int iEnd);
- void internalConvertMultipleJoints(const btAlignedObjectArray<JointParams>& jointParamsArray, btTypedConstraint** constraints, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
-
- // parameters to control batching
- static bool s_allowNestedParallelForLoops; // whether to allow nested parallel operations
- static int s_minimumContactManifoldsForBatching; // don't even try to batch if fewer manifolds than this
- static btBatchedConstraints::BatchingMethod s_contactBatchingMethod;
- static btBatchedConstraints::BatchingMethod s_jointBatchingMethod;
- static int s_minBatchSize; // desired number of constraints per batch
- static int s_maxBatchSize;
-
-protected:
- static const int CACHE_LINE_SIZE = 64;
-
- btBatchedConstraints m_batchedContactConstraints;
- btBatchedConstraints m_batchedJointConstraints;
- int m_numFrictionDirections;
- bool m_useBatching;
- bool m_useObsoleteJointConstraints;
- btAlignedObjectArray<btContactManifoldCachedInfo> m_manifoldCachedInfoArray;
- btAlignedObjectArray<int> m_rollingFrictionIndexTable; // lookup table mapping contact index to rolling friction index
- btSpinMutex m_bodySolverArrayMutex;
- char m_antiFalseSharingPadding[CACHE_LINE_SIZE]; // padding to keep mutexes in separate cachelines
- btSpinMutex m_kinematicBodyUniqueIdToSolverBodyTableMutex;
- btAlignedObjectArray<char> m_scratchMemory;
-
- virtual void randomizeConstraintOrdering(int iteration, int numIterations);
- virtual btScalar resolveAllJointConstraints(int iteration);
- virtual btScalar resolveAllContactConstraints();
- virtual btScalar resolveAllContactFrictionConstraints();
- virtual btScalar resolveAllContactConstraintsInterleaved();
- virtual btScalar resolveAllRollingFrictionConstraints();
-
- virtual void setupBatchedContactConstraints();
- virtual void setupBatchedJointConstraints();
- virtual void convertJoints(btTypedConstraint * *constraints, int numConstraints, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
- virtual void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
- virtual void convertBodies(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal) BT_OVERRIDE;
-
- int getOrInitSolverBodyThreadsafe(btCollisionObject & body, btScalar timeStep);
- void allocAllContactConstraints(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- void setupAllContactConstraints(const btContactSolverInfo& infoGlobal);
- void randomizeBatchedConstraintOrdering(btBatchedConstraints * batchedConstraints);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btSequentialImpulseConstraintSolverMt();
- virtual ~btSequentialImpulseConstraintSolverMt();
-
- btScalar resolveMultipleJointConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd, int iteration);
- btScalar resolveMultipleContactConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
- btScalar resolveMultipleContactSplitPenetrationImpulseConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
- btScalar resolveMultipleContactFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
- btScalar resolveMultipleContactRollingFrictionConstraints(const btAlignedObjectArray<int>& consIndices, int batchBegin, int batchEnd);
- btScalar resolveMultipleContactConstraintsInterleaved(const btAlignedObjectArray<int>& contactIndices, int batchBegin, int batchEnd);
-
- void internalCollectContactManifoldCachedInfo(btContactManifoldCachedInfo * cachedInfoArray, btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
- void internalAllocContactConstraints(const btContactManifoldCachedInfo* cachedInfoArray, int numManifolds);
- void internalSetupContactConstraints(int iContactConstraint, const btContactSolverInfo& infoGlobal);
- void internalConvertBodies(btCollisionObject * *bodies, int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackContacts(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackJoints(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
- void internalWriteBackBodies(int iBegin, int iEnd, const btContactSolverInfo& infoGlobal);
-};
-
-#endif //BT_SEQUENTIAL_IMPULSE_CONSTRAINT_SOLVER_MT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
deleted file mode 100644
index cac5302a73..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp
+++ /dev/null
@@ -1,823 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-Added by Roman Ponomarev (rponom@gmail.com)
-April 04, 2008
-*/
-
-#include "btSliderConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-#include <new>
-
-#define USE_OFFSET_FOR_CONSTANT_FRAME true
-
-void btSliderConstraint::initParams()
-{
- m_lowerLinLimit = btScalar(1.0);
- m_upperLinLimit = btScalar(-1.0);
- m_lowerAngLimit = btScalar(0.);
- m_upperAngLimit = btScalar(0.);
- m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingDirLin = btScalar(0.);
- m_cfmDirLin = SLIDER_CONSTRAINT_DEF_CFM;
- m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingDirAng = btScalar(0.);
- m_cfmDirAng = SLIDER_CONSTRAINT_DEF_CFM;
- m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_cfmOrthoLin = SLIDER_CONSTRAINT_DEF_CFM;
- m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_cfmOrthoAng = SLIDER_CONSTRAINT_DEF_CFM;
- m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_cfmLimLin = SLIDER_CONSTRAINT_DEF_CFM;
- m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS;
- m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION;
- m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING;
- m_cfmLimAng = SLIDER_CONSTRAINT_DEF_CFM;
-
- m_poweredLinMotor = false;
- m_targetLinMotorVelocity = btScalar(0.);
- m_maxLinMotorForce = btScalar(0.);
- m_accumulatedLinMotorImpulse = btScalar(0.0);
-
- m_poweredAngMotor = false;
- m_targetAngMotorVelocity = btScalar(0.);
- m_maxAngMotorForce = btScalar(0.);
- m_accumulatedAngMotorImpulse = btScalar(0.0);
-
- m_flags = 0;
- m_flags = 0;
-
- m_useOffsetForConstraintFrame = USE_OFFSET_FOR_CONSTANT_FRAME;
-
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
-}
-
-btSliderConstraint::btSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, rbA, rbB),
- m_useSolveConstraintObsolete(false),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameA)
-{
- initParams();
-}
-
-btSliderConstraint::btSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
- : btTypedConstraint(SLIDER_CONSTRAINT_TYPE, getFixedBody(), rbB),
- m_useSolveConstraintObsolete(false),
- m_frameInB(frameInB),
- m_useLinearReferenceFrameA(useLinearReferenceFrameA)
-{
- ///not providing rigidbody A means implicitly using worldspace for body A
- m_frameInA = rbB.getCenterOfMassTransform() * m_frameInB;
- // m_frameInA.getOrigin() = m_rbA.getCenterOfMassTransform()(m_frameInA.getOrigin());
-
- initParams();
-}
-
-void btSliderConstraint::getInfo1(btConstraintInfo1* info)
-{
- if (m_useSolveConstraintObsolete)
- {
- info->m_numConstraintRows = 0;
- info->nub = 0;
- }
- else
- {
- info->m_numConstraintRows = 4; // Fixed 2 linear + 2 angular
- info->nub = 2;
- //prepare constraint
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- testAngLimits();
- testLinLimits();
- if (getSolveLinLimit() || getPoweredLinMotor())
- {
- info->m_numConstraintRows++; // limit 3rd linear as well
- info->nub--;
- }
- if (getSolveAngLimit() || getPoweredAngMotor())
- {
- info->m_numConstraintRows++; // limit 3rd angular as well
- info->nub--;
- }
- }
-}
-
-void btSliderConstraint::getInfo1NonVirtual(btConstraintInfo1* info)
-{
- info->m_numConstraintRows = 6; // Fixed 2 linear + 2 angular + 1 limit (even if not used)
- info->nub = 0;
-}
-
-void btSliderConstraint::getInfo2(btConstraintInfo2* info)
-{
- getInfo2NonVirtual(info, m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform(), m_rbA.getLinearVelocity(), m_rbB.getLinearVelocity(), m_rbA.getInvMass(), m_rbB.getInvMass());
-}
-
-void btSliderConstraint::calculateTransforms(const btTransform& transA, const btTransform& transB)
-{
- if (m_useLinearReferenceFrameA || (!m_useSolveConstraintObsolete))
- {
- m_calculatedTransformA = transA * m_frameInA;
- m_calculatedTransformB = transB * m_frameInB;
- }
- else
- {
- m_calculatedTransformA = transB * m_frameInB;
- m_calculatedTransformB = transA * m_frameInA;
- }
- m_realPivotAInW = m_calculatedTransformA.getOrigin();
- m_realPivotBInW = m_calculatedTransformB.getOrigin();
- m_sliderAxis = m_calculatedTransformA.getBasis().getColumn(0); // along X
- if (m_useLinearReferenceFrameA || m_useSolveConstraintObsolete)
- {
- m_delta = m_realPivotBInW - m_realPivotAInW;
- }
- else
- {
- m_delta = m_realPivotAInW - m_realPivotBInW;
- }
- m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis;
- btVector3 normalWorld;
- int i;
- //linear part
- for (i = 0; i < 3; i++)
- {
- normalWorld = m_calculatedTransformA.getBasis().getColumn(i);
- m_depth[i] = m_delta.dot(normalWorld);
- }
-}
-
-void btSliderConstraint::testLinLimits(void)
-{
- m_solveLinLim = false;
- m_linPos = m_depth[0];
- if (m_lowerLinLimit <= m_upperLinLimit)
- {
- if (m_depth[0] > m_upperLinLimit)
- {
- m_depth[0] -= m_upperLinLimit;
- m_solveLinLim = true;
- }
- else if (m_depth[0] < m_lowerLinLimit)
- {
- m_depth[0] -= m_lowerLinLimit;
- m_solveLinLim = true;
- }
- else
- {
- m_depth[0] = btScalar(0.);
- }
- }
- else
- {
- m_depth[0] = btScalar(0.);
- }
-}
-
-void btSliderConstraint::testAngLimits(void)
-{
- m_angDepth = btScalar(0.);
- m_solveAngLim = false;
- if (m_lowerAngLimit <= m_upperAngLimit)
- {
- const btVector3 axisA0 = m_calculatedTransformA.getBasis().getColumn(1);
- const btVector3 axisA1 = m_calculatedTransformA.getBasis().getColumn(2);
- const btVector3 axisB0 = m_calculatedTransformB.getBasis().getColumn(1);
- // btScalar rot = btAtan2Fast(axisB0.dot(axisA1), axisB0.dot(axisA0));
- btScalar rot = btAtan2(axisB0.dot(axisA1), axisB0.dot(axisA0));
- rot = btAdjustAngleToLimits(rot, m_lowerAngLimit, m_upperAngLimit);
- m_angPos = rot;
- if (rot < m_lowerAngLimit)
- {
- m_angDepth = rot - m_lowerAngLimit;
- m_solveAngLim = true;
- }
- else if (rot > m_upperAngLimit)
- {
- m_angDepth = rot - m_upperAngLimit;
- m_solveAngLim = true;
- }
- }
-}
-
-btVector3 btSliderConstraint::getAncorInA(void)
-{
- btVector3 ancorInA;
- ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * btScalar(0.5) * m_sliderAxis;
- ancorInA = m_rbA.getCenterOfMassTransform().inverse() * ancorInA;
- return ancorInA;
-}
-
-btVector3 btSliderConstraint::getAncorInB(void)
-{
- btVector3 ancorInB;
- ancorInB = m_frameInB.getOrigin();
- return ancorInB;
-}
-
-void btSliderConstraint::getInfo2NonVirtual(btConstraintInfo2* info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass)
-{
- const btTransform& trA = getCalculatedTransformA();
- const btTransform& trB = getCalculatedTransformB();
-
- btAssert(!m_useSolveConstraintObsolete);
- int i, s = info->rowskip;
-
- btScalar signFact = m_useLinearReferenceFrameA ? btScalar(1.0f) : btScalar(-1.0f);
-
- // difference between frames in WCS
- btVector3 ofs = trB.getOrigin() - trA.getOrigin();
- // now get weight factors depending on masses
- btScalar miA = rbAinvMass;
- btScalar miB = rbBinvMass;
- bool hasStaticBody = (miA < SIMD_EPSILON) || (miB < SIMD_EPSILON);
- btScalar miS = miA + miB;
- btScalar factA, factB;
- if (miS > btScalar(0.f))
- {
- factA = miB / miS;
- }
- else
- {
- factA = btScalar(0.5f);
- }
- factB = btScalar(1.0f) - factA;
- btVector3 ax1, p, q;
- btVector3 ax1A = trA.getBasis().getColumn(0);
- btVector3 ax1B = trB.getBasis().getColumn(0);
- if (m_useOffsetForConstraintFrame)
- {
- // get the desired direction of slider axis
- // as weighted sum of X-orthos of frameA and frameB in WCS
- ax1 = ax1A * factA + ax1B * factB;
- ax1.normalize();
- // construct two orthos to slider axis
- btPlaneSpace1(ax1, p, q);
- }
- else
- { // old way - use frameA
- ax1 = trA.getBasis().getColumn(0);
- // get 2 orthos to slider axis (Y, Z)
- p = trA.getBasis().getColumn(1);
- q = trA.getBasis().getColumn(2);
- }
- // make rotations around these orthos equal
- // the slider axis should be the only unconstrained
- // rotational axis, the angular velocity of the two bodies perpendicular to
- // the slider axis should be equal. thus the constraint equations are
- // p*w1 - p*w2 = 0
- // q*w1 - q*w2 = 0
- // where p and q are unit vectors normal to the slider axis, and w1 and w2
- // are the angular velocity vectors of the two bodies.
- info->m_J1angularAxis[0] = p[0];
- info->m_J1angularAxis[1] = p[1];
- info->m_J1angularAxis[2] = p[2];
- info->m_J1angularAxis[s + 0] = q[0];
- info->m_J1angularAxis[s + 1] = q[1];
- info->m_J1angularAxis[s + 2] = q[2];
-
- info->m_J2angularAxis[0] = -p[0];
- info->m_J2angularAxis[1] = -p[1];
- info->m_J2angularAxis[2] = -p[2];
- info->m_J2angularAxis[s + 0] = -q[0];
- info->m_J2angularAxis[s + 1] = -q[1];
- info->m_J2angularAxis[s + 2] = -q[2];
- // compute the right hand side of the constraint equation. set relative
- // body velocities along p and q to bring the slider back into alignment.
- // if ax1A,ax1B are the unit length slider axes as computed from bodyA and
- // bodyB, we need to rotate both bodies along the axis u = (ax1 x ax2).
- // if "theta" is the angle between ax1 and ax2, we need an angular velocity
- // along u to cover angle erp*theta in one step :
- // |angular_velocity| = angle/time = erp*theta / stepsize
- // = (erp*fps) * theta
- // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
- // = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
- // ...as ax1 and ax2 are unit length. if theta is smallish,
- // theta ~= sin(theta), so
- // angular_velocity = (erp*fps) * (ax1 x ax2)
- // ax1 x ax2 is in the plane space of ax1, so we project the angular
- // velocity to p and q to find the right hand side.
- // btScalar k = info->fps * info->erp * getSoftnessOrthoAng();
- btScalar currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTANG) ? m_softnessOrthoAng : m_softnessOrthoAng * info->erp;
- btScalar k = info->fps * currERP;
-
- btVector3 u = ax1A.cross(ax1B);
- info->m_constraintError[0] = k * u.dot(p);
- info->m_constraintError[s] = k * u.dot(q);
- if (m_flags & BT_SLIDER_FLAGS_CFM_ORTANG)
- {
- info->cfm[0] = m_cfmOrthoAng;
- info->cfm[s] = m_cfmOrthoAng;
- }
-
- int nrow = 1; // last filled row
- int srow;
- btScalar limit_err;
- int limit;
-
- // next two rows.
- // we want: velA + wA x relA == velB + wB x relB ... but this would
- // result in three equations, so we project along two orthos to the slider axis
-
- btTransform bodyA_trans = transA;
- btTransform bodyB_trans = transB;
- nrow++;
- int s2 = nrow * s;
- nrow++;
- int s3 = nrow * s;
- btVector3 tmpA(0, 0, 0), tmpB(0, 0, 0), relA(0, 0, 0), relB(0, 0, 0), c(0, 0, 0);
- if (m_useOffsetForConstraintFrame)
- {
- // get vector from bodyB to frameB in WCS
- relB = trB.getOrigin() - bodyB_trans.getOrigin();
- // get its projection to slider axis
- btVector3 projB = ax1 * relB.dot(ax1);
- // get vector directed from bodyB to slider axis (and orthogonal to it)
- btVector3 orthoB = relB - projB;
- // same for bodyA
- relA = trA.getOrigin() - bodyA_trans.getOrigin();
- btVector3 projA = ax1 * relA.dot(ax1);
- btVector3 orthoA = relA - projA;
- // get desired offset between frames A and B along slider axis
- btScalar sliderOffs = m_linPos - m_depth[0];
- // desired vector from projection of center of bodyA to projection of center of bodyB to slider axis
- btVector3 totalDist = projA + ax1 * sliderOffs - projB;
- // get offset vectors relA and relB
- relA = orthoA + totalDist * factA;
- relB = orthoB - totalDist * factB;
- // now choose average ortho to slider axis
- p = orthoB * factA + orthoA * factB;
- btScalar len2 = p.length2();
- if (len2 > SIMD_EPSILON)
- {
- p /= btSqrt(len2);
- }
- else
- {
- p = trA.getBasis().getColumn(1);
- }
- // make one more ortho
- q = ax1.cross(p);
- // fill two rows
- tmpA = relA.cross(p);
- tmpB = relB.cross(p);
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = -tmpB[i];
- tmpA = relA.cross(q);
- tmpB = relB.cross(q);
- if (hasStaticBody && getSolveAngLimit())
- { // to make constraint between static and dynamic objects more rigid
- // remove wA (or wB) from equation if angular limit is hit
- tmpB *= factB;
- tmpA *= factA;
- }
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = tmpA[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = -tmpB[i];
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
- }
- else
- { // old way - maybe incorrect if bodies are not on the slider axis
- // see discussion "Bug in slider constraint" http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=4024&start=0
- c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin();
- btVector3 tmp = c.cross(p);
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s2 + i] = factA * tmp[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s2 + i] = factB * tmp[i];
- tmp = c.cross(q);
- for (i = 0; i < 3; i++) info->m_J1angularAxis[s3 + i] = factA * tmp[i];
- for (i = 0; i < 3; i++) info->m_J2angularAxis[s3 + i] = factB * tmp[i];
-
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s2 + i] = p[i];
- for (i = 0; i < 3; i++) info->m_J1linearAxis[s3 + i] = q[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s2 + i] = -p[i];
- for (i = 0; i < 3; i++) info->m_J2linearAxis[s3 + i] = -q[i];
- }
- // compute two elements of right hand side
-
- // k = info->fps * info->erp * getSoftnessOrthoLin();
- currERP = (m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN) ? m_softnessOrthoLin : m_softnessOrthoLin * info->erp;
- k = info->fps * currERP;
-
- btScalar rhs = k * p.dot(ofs);
- info->m_constraintError[s2] = rhs;
- rhs = k * q.dot(ofs);
- info->m_constraintError[s3] = rhs;
- if (m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN)
- {
- info->cfm[s2] = m_cfmOrthoLin;
- info->cfm[s3] = m_cfmOrthoLin;
- }
-
- // check linear limits
- limit_err = btScalar(0.0);
- limit = 0;
- if (getSolveLinLimit())
- {
- limit_err = getLinDepth() * signFact;
- limit = (limit_err > btScalar(0.0)) ? 2 : 1;
- }
- bool powered = getPoweredLinMotor();
- // if the slider has joint limits or motor, add in the extra row
- if (limit || powered)
- {
- nrow++;
- srow = nrow * info->rowskip;
- info->m_J1linearAxis[srow + 0] = ax1[0];
- info->m_J1linearAxis[srow + 1] = ax1[1];
- info->m_J1linearAxis[srow + 2] = ax1[2];
- info->m_J2linearAxis[srow + 0] = -ax1[0];
- info->m_J2linearAxis[srow + 1] = -ax1[1];
- info->m_J2linearAxis[srow + 2] = -ax1[2];
- // linear torque decoupling step:
- //
- // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies
- // do not create a torque couple. in other words, the points that the
- // constraint force is applied at must lie along the same ax1 axis.
- // a torque couple will result in limited slider-jointed free
- // bodies from gaining angular momentum.
- if (m_useOffsetForConstraintFrame)
- {
- // this is needed only when bodyA and bodyB are both dynamic.
- if (!hasStaticBody)
- {
- tmpA = relA.cross(ax1);
- tmpB = relB.cross(ax1);
- info->m_J1angularAxis[srow + 0] = tmpA[0];
- info->m_J1angularAxis[srow + 1] = tmpA[1];
- info->m_J1angularAxis[srow + 2] = tmpA[2];
- info->m_J2angularAxis[srow + 0] = -tmpB[0];
- info->m_J2angularAxis[srow + 1] = -tmpB[1];
- info->m_J2angularAxis[srow + 2] = -tmpB[2];
- }
- }
- else
- { // The old way. May be incorrect if bodies are not on the slider axis
- btVector3 ltd; // Linear Torque Decoupling vector (a torque)
- ltd = c.cross(ax1);
- info->m_J1angularAxis[srow + 0] = factA * ltd[0];
- info->m_J1angularAxis[srow + 1] = factA * ltd[1];
- info->m_J1angularAxis[srow + 2] = factA * ltd[2];
- info->m_J2angularAxis[srow + 0] = factB * ltd[0];
- info->m_J2angularAxis[srow + 1] = factB * ltd[1];
- info->m_J2angularAxis[srow + 2] = factB * ltd[2];
- }
- // right-hand part
- btScalar lostop = getLowerLinLimit();
- btScalar histop = getUpperLinLimit();
- if (limit && (lostop == histop))
- { // the joint motor is ineffective
- powered = false;
- }
- info->m_constraintError[srow] = 0.;
- info->m_lowerLimit[srow] = 0.;
- info->m_upperLimit[srow] = 0.;
- currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN) ? m_softnessLimLin : info->erp;
- if (powered)
- {
- if (m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN)
- {
- info->cfm[srow] = m_cfmDirLin;
- }
- btScalar tag_vel = getTargetLinMotorVelocity();
- btScalar mot_fact = getMotorFactor(m_linPos, m_lowerLinLimit, m_upperLinLimit, tag_vel, info->fps * currERP);
- info->m_constraintError[srow] -= signFact * mot_fact * getTargetLinMotorVelocity();
- info->m_lowerLimit[srow] += -getMaxLinMotorForce() / info->fps;
- info->m_upperLimit[srow] += getMaxLinMotorForce() / info->fps;
- }
- if (limit)
- {
- k = info->fps * currERP;
- info->m_constraintError[srow] += k * limit_err;
- if (m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN)
- {
- info->cfm[srow] = m_cfmLimLin;
- }
- if (lostop == histop)
- { // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else if (limit == 1)
- { // low limit
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- else
- { // high limit
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that)
- btScalar bounce = btFabs(btScalar(1.0) - getDampingLimLin());
- if (bounce > btScalar(0.0))
- {
- btScalar vel = linVelA.dot(ax1);
- vel -= linVelB.dot(ax1);
- vel *= signFact;
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- { // low limit
- if (vel < 0)
- {
- btScalar newc = -bounce * vel;
- if (newc > info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- else
- { // high limit - all those computations are reversed
- if (vel > 0)
- {
- btScalar newc = -bounce * vel;
- if (newc < info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- info->m_constraintError[srow] *= getSoftnessLimLin();
- } // if(limit)
- } // if linear limit
- // check angular limits
- limit_err = btScalar(0.0);
- limit = 0;
- if (getSolveAngLimit())
- {
- limit_err = getAngDepth();
- limit = (limit_err > btScalar(0.0)) ? 1 : 2;
- }
- // if the slider has joint limits, add in the extra row
- powered = getPoweredAngMotor();
- if (limit || powered)
- {
- nrow++;
- srow = nrow * info->rowskip;
- info->m_J1angularAxis[srow + 0] = ax1[0];
- info->m_J1angularAxis[srow + 1] = ax1[1];
- info->m_J1angularAxis[srow + 2] = ax1[2];
-
- info->m_J2angularAxis[srow + 0] = -ax1[0];
- info->m_J2angularAxis[srow + 1] = -ax1[1];
- info->m_J2angularAxis[srow + 2] = -ax1[2];
-
- btScalar lostop = getLowerAngLimit();
- btScalar histop = getUpperAngLimit();
- if (limit && (lostop == histop))
- { // the joint motor is ineffective
- powered = false;
- }
- currERP = (m_flags & BT_SLIDER_FLAGS_ERP_LIMANG) ? m_softnessLimAng : info->erp;
- if (powered)
- {
- if (m_flags & BT_SLIDER_FLAGS_CFM_DIRANG)
- {
- info->cfm[srow] = m_cfmDirAng;
- }
- btScalar mot_fact = getMotorFactor(m_angPos, m_lowerAngLimit, m_upperAngLimit, getTargetAngMotorVelocity(), info->fps * currERP);
- info->m_constraintError[srow] = mot_fact * getTargetAngMotorVelocity();
- info->m_lowerLimit[srow] = -getMaxAngMotorForce() / info->fps;
- info->m_upperLimit[srow] = getMaxAngMotorForce() / info->fps;
- }
- if (limit)
- {
- k = info->fps * currERP;
- info->m_constraintError[srow] += k * limit_err;
- if (m_flags & BT_SLIDER_FLAGS_CFM_LIMANG)
- {
- info->cfm[srow] = m_cfmLimAng;
- }
- if (lostop == histop)
- {
- // limited low and high simultaneously
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else if (limit == 1)
- { // low limit
- info->m_lowerLimit[srow] = 0;
- info->m_upperLimit[srow] = SIMD_INFINITY;
- }
- else
- { // high limit
- info->m_lowerLimit[srow] = -SIMD_INFINITY;
- info->m_upperLimit[srow] = 0;
- }
- // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
- btScalar bounce = btFabs(btScalar(1.0) - getDampingLimAng());
- if (bounce > btScalar(0.0))
- {
- btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
- vel -= m_rbB.getAngularVelocity().dot(ax1);
- // only apply bounce if the velocity is incoming, and if the
- // resulting c[] exceeds what we already have.
- if (limit == 1)
- { // low limit
- if (vel < 0)
- {
- btScalar newc = -bounce * vel;
- if (newc > info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- else
- { // high limit - all those computations are reversed
- if (vel > 0)
- {
- btScalar newc = -bounce * vel;
- if (newc < info->m_constraintError[srow])
- {
- info->m_constraintError[srow] = newc;
- }
- }
- }
- }
- info->m_constraintError[srow] *= getSoftnessLimAng();
- } // if(limit)
- } // if angular limit or powered
-}
-
-///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
-///If no axis is provided, it uses the default axis for this constraint.
-void btSliderConstraint::setParam(int num, btScalar value, int axis)
-{
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- if (axis < 1)
- {
- m_softnessLimLin = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_LIMLIN;
- }
- else if (axis < 3)
- {
- m_softnessOrthoLin = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_ORTLIN;
- }
- else if (axis == 3)
- {
- m_softnessLimAng = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_LIMANG;
- }
- else if (axis < 6)
- {
- m_softnessOrthoAng = value;
- m_flags |= BT_SLIDER_FLAGS_ERP_ORTANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_CFM:
- if (axis < 1)
- {
- m_cfmDirLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_DIRLIN;
- }
- else if (axis == 3)
- {
- m_cfmDirAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_DIRANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_STOP_CFM:
- if (axis < 1)
- {
- m_cfmLimLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_LIMLIN;
- }
- else if (axis < 3)
- {
- m_cfmOrthoLin = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_ORTLIN;
- }
- else if (axis == 3)
- {
- m_cfmLimAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_LIMANG;
- }
- else if (axis < 6)
- {
- m_cfmOrthoAng = value;
- m_flags |= BT_SLIDER_FLAGS_CFM_ORTANG;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- }
-}
-
-///return the local value of parameter
-btScalar btSliderConstraint::getParam(int num, int axis) const
-{
- btScalar retVal(SIMD_INFINITY);
- switch (num)
- {
- case BT_CONSTRAINT_STOP_ERP:
- if (axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMLIN);
- retVal = m_softnessLimLin;
- }
- else if (axis < 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTLIN);
- retVal = m_softnessOrthoLin;
- }
- else if (axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_LIMANG);
- retVal = m_softnessLimAng;
- }
- else if (axis < 6)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_ERP_ORTANG);
- retVal = m_softnessOrthoAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_CFM:
- if (axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRLIN);
- retVal = m_cfmDirLin;
- }
- else if (axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_DIRANG);
- retVal = m_cfmDirAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- case BT_CONSTRAINT_STOP_CFM:
- if (axis < 1)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMLIN);
- retVal = m_cfmLimLin;
- }
- else if (axis < 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTLIN);
- retVal = m_cfmOrthoLin;
- }
- else if (axis == 3)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_LIMANG);
- retVal = m_cfmLimAng;
- }
- else if (axis < 6)
- {
- btAssertConstrParams(m_flags & BT_SLIDER_FLAGS_CFM_ORTANG);
- retVal = m_cfmOrthoAng;
- }
- else
- {
- btAssertConstrParams(0);
- }
- break;
- }
- return retVal;
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
deleted file mode 100644
index 75ca34e978..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSliderConstraint.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-Added by Roman Ponomarev (rponom@gmail.com)
-April 04, 2008
-
-TODO:
- - add clamping od accumulated impulse to improve stability
- - add conversion for ODE constraint solver
-*/
-
-#ifndef BT_SLIDER_CONSTRAINT_H
-#define BT_SLIDER_CONSTRAINT_H
-
-#include "LinearMath/btScalar.h" //for BT_USE_DOUBLE_PRECISION
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btSliderConstraintData2 btSliderConstraintDoubleData
-#define btSliderConstraintDataName "btSliderConstraintDoubleData"
-#else
-#define btSliderConstraintData2 btSliderConstraintData
-#define btSliderConstraintDataName "btSliderConstraintData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-#include "btTypedConstraint.h"
-
-class btRigidBody;
-
-#define SLIDER_CONSTRAINT_DEF_SOFTNESS (btScalar(1.0))
-#define SLIDER_CONSTRAINT_DEF_DAMPING (btScalar(1.0))
-#define SLIDER_CONSTRAINT_DEF_RESTITUTION (btScalar(0.7))
-#define SLIDER_CONSTRAINT_DEF_CFM (btScalar(0.f))
-
-enum btSliderFlags
-{
- BT_SLIDER_FLAGS_CFM_DIRLIN = (1 << 0),
- BT_SLIDER_FLAGS_ERP_DIRLIN = (1 << 1),
- BT_SLIDER_FLAGS_CFM_DIRANG = (1 << 2),
- BT_SLIDER_FLAGS_ERP_DIRANG = (1 << 3),
- BT_SLIDER_FLAGS_CFM_ORTLIN = (1 << 4),
- BT_SLIDER_FLAGS_ERP_ORTLIN = (1 << 5),
- BT_SLIDER_FLAGS_CFM_ORTANG = (1 << 6),
- BT_SLIDER_FLAGS_ERP_ORTANG = (1 << 7),
- BT_SLIDER_FLAGS_CFM_LIMLIN = (1 << 8),
- BT_SLIDER_FLAGS_ERP_LIMLIN = (1 << 9),
- BT_SLIDER_FLAGS_CFM_LIMANG = (1 << 10),
- BT_SLIDER_FLAGS_ERP_LIMANG = (1 << 11)
-};
-
-ATTRIBUTE_ALIGNED16(class)
-btSliderConstraint : public btTypedConstraint
-{
-protected:
- ///for backwards compatibility during the transition to 'getInfo/getInfo2'
- bool m_useSolveConstraintObsolete;
- bool m_useOffsetForConstraintFrame;
- btTransform m_frameInA;
- btTransform m_frameInB;
- // use frameA fo define limits, if true
- bool m_useLinearReferenceFrameA;
- // linear limits
- btScalar m_lowerLinLimit;
- btScalar m_upperLinLimit;
- // angular limits
- btScalar m_lowerAngLimit;
- btScalar m_upperAngLimit;
- // softness, restitution and damping for different cases
- // DirLin - moving inside linear limits
- // LimLin - hitting linear limit
- // DirAng - moving inside angular limits
- // LimAng - hitting angular limit
- // OrthoLin, OrthoAng - against constraint axis
- btScalar m_softnessDirLin;
- btScalar m_restitutionDirLin;
- btScalar m_dampingDirLin;
- btScalar m_cfmDirLin;
-
- btScalar m_softnessDirAng;
- btScalar m_restitutionDirAng;
- btScalar m_dampingDirAng;
- btScalar m_cfmDirAng;
-
- btScalar m_softnessLimLin;
- btScalar m_restitutionLimLin;
- btScalar m_dampingLimLin;
- btScalar m_cfmLimLin;
-
- btScalar m_softnessLimAng;
- btScalar m_restitutionLimAng;
- btScalar m_dampingLimAng;
- btScalar m_cfmLimAng;
-
- btScalar m_softnessOrthoLin;
- btScalar m_restitutionOrthoLin;
- btScalar m_dampingOrthoLin;
- btScalar m_cfmOrthoLin;
-
- btScalar m_softnessOrthoAng;
- btScalar m_restitutionOrthoAng;
- btScalar m_dampingOrthoAng;
- btScalar m_cfmOrthoAng;
-
- // for interlal use
- bool m_solveLinLim;
- bool m_solveAngLim;
-
- int m_flags;
-
- btJacobianEntry m_jacLin[3];
- btScalar m_jacLinDiagABInv[3];
-
- btJacobianEntry m_jacAng[3];
-
- btScalar m_timeStep;
- btTransform m_calculatedTransformA;
- btTransform m_calculatedTransformB;
-
- btVector3 m_sliderAxis;
- btVector3 m_realPivotAInW;
- btVector3 m_realPivotBInW;
- btVector3 m_projPivotInW;
- btVector3 m_delta;
- btVector3 m_depth;
- btVector3 m_relPosA;
- btVector3 m_relPosB;
-
- btScalar m_linPos;
- btScalar m_angPos;
-
- btScalar m_angDepth;
- btScalar m_kAngle;
-
- bool m_poweredLinMotor;
- btScalar m_targetLinMotorVelocity;
- btScalar m_maxLinMotorForce;
- btScalar m_accumulatedLinMotorImpulse;
-
- bool m_poweredAngMotor;
- btScalar m_targetAngMotorVelocity;
- btScalar m_maxAngMotorForce;
- btScalar m_accumulatedAngMotorImpulse;
-
- //------------------------
- void initParams();
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- // constructors
- btSliderConstraint(btRigidBody & rbA, btRigidBody & rbB, const btTransform& frameInA, const btTransform& frameInB, bool useLinearReferenceFrameA);
- btSliderConstraint(btRigidBody & rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
-
- // overrides
-
- virtual void getInfo1(btConstraintInfo1 * info);
-
- void getInfo1NonVirtual(btConstraintInfo1 * info);
-
- virtual void getInfo2(btConstraintInfo2 * info);
-
- void getInfo2NonVirtual(btConstraintInfo2 * info, const btTransform& transA, const btTransform& transB, const btVector3& linVelA, const btVector3& linVelB, btScalar rbAinvMass, btScalar rbBinvMass);
-
- // access
- const btRigidBody& getRigidBodyA() const { return m_rbA; }
- const btRigidBody& getRigidBodyB() const { return m_rbB; }
- const btTransform& getCalculatedTransformA() const { return m_calculatedTransformA; }
- const btTransform& getCalculatedTransformB() const { return m_calculatedTransformB; }
- const btTransform& getFrameOffsetA() const { return m_frameInA; }
- const btTransform& getFrameOffsetB() const { return m_frameInB; }
- btTransform& getFrameOffsetA() { return m_frameInA; }
- btTransform& getFrameOffsetB() { return m_frameInB; }
- btScalar getLowerLinLimit() { return m_lowerLinLimit; }
- void setLowerLinLimit(btScalar lowerLimit) { m_lowerLinLimit = lowerLimit; }
- btScalar getUpperLinLimit() { return m_upperLinLimit; }
- void setUpperLinLimit(btScalar upperLimit) { m_upperLinLimit = upperLimit; }
- btScalar getLowerAngLimit() { return m_lowerAngLimit; }
- void setLowerAngLimit(btScalar lowerLimit) { m_lowerAngLimit = btNormalizeAngle(lowerLimit); }
- btScalar getUpperAngLimit() { return m_upperAngLimit; }
- void setUpperAngLimit(btScalar upperLimit) { m_upperAngLimit = btNormalizeAngle(upperLimit); }
- bool getUseLinearReferenceFrameA() { return m_useLinearReferenceFrameA; }
- btScalar getSoftnessDirLin() { return m_softnessDirLin; }
- btScalar getRestitutionDirLin() { return m_restitutionDirLin; }
- btScalar getDampingDirLin() { return m_dampingDirLin; }
- btScalar getSoftnessDirAng() { return m_softnessDirAng; }
- btScalar getRestitutionDirAng() { return m_restitutionDirAng; }
- btScalar getDampingDirAng() { return m_dampingDirAng; }
- btScalar getSoftnessLimLin() { return m_softnessLimLin; }
- btScalar getRestitutionLimLin() { return m_restitutionLimLin; }
- btScalar getDampingLimLin() { return m_dampingLimLin; }
- btScalar getSoftnessLimAng() { return m_softnessLimAng; }
- btScalar getRestitutionLimAng() { return m_restitutionLimAng; }
- btScalar getDampingLimAng() { return m_dampingLimAng; }
- btScalar getSoftnessOrthoLin() { return m_softnessOrthoLin; }
- btScalar getRestitutionOrthoLin() { return m_restitutionOrthoLin; }
- btScalar getDampingOrthoLin() { return m_dampingOrthoLin; }
- btScalar getSoftnessOrthoAng() { return m_softnessOrthoAng; }
- btScalar getRestitutionOrthoAng() { return m_restitutionOrthoAng; }
- btScalar getDampingOrthoAng() { return m_dampingOrthoAng; }
- void setSoftnessDirLin(btScalar softnessDirLin) { m_softnessDirLin = softnessDirLin; }
- void setRestitutionDirLin(btScalar restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; }
- void setDampingDirLin(btScalar dampingDirLin) { m_dampingDirLin = dampingDirLin; }
- void setSoftnessDirAng(btScalar softnessDirAng) { m_softnessDirAng = softnessDirAng; }
- void setRestitutionDirAng(btScalar restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; }
- void setDampingDirAng(btScalar dampingDirAng) { m_dampingDirAng = dampingDirAng; }
- void setSoftnessLimLin(btScalar softnessLimLin) { m_softnessLimLin = softnessLimLin; }
- void setRestitutionLimLin(btScalar restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; }
- void setDampingLimLin(btScalar dampingLimLin) { m_dampingLimLin = dampingLimLin; }
- void setSoftnessLimAng(btScalar softnessLimAng) { m_softnessLimAng = softnessLimAng; }
- void setRestitutionLimAng(btScalar restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; }
- void setDampingLimAng(btScalar dampingLimAng) { m_dampingLimAng = dampingLimAng; }
- void setSoftnessOrthoLin(btScalar softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; }
- void setRestitutionOrthoLin(btScalar restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; }
- void setDampingOrthoLin(btScalar dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; }
- void setSoftnessOrthoAng(btScalar softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; }
- void setRestitutionOrthoAng(btScalar restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; }
- void setDampingOrthoAng(btScalar dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; }
- void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; }
- bool getPoweredLinMotor() { return m_poweredLinMotor; }
- void setTargetLinMotorVelocity(btScalar targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; }
- btScalar getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; }
- void setMaxLinMotorForce(btScalar maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; }
- btScalar getMaxLinMotorForce() { return m_maxLinMotorForce; }
- void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; }
- bool getPoweredAngMotor() { return m_poweredAngMotor; }
- void setTargetAngMotorVelocity(btScalar targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; }
- btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; }
- void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; }
- btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; }
-
- btScalar getLinearPos() const { return m_linPos; }
- btScalar getAngularPos() const { return m_angPos; }
-
- // access for ODE solver
- bool getSolveLinLimit() { return m_solveLinLim; }
- btScalar getLinDepth() { return m_depth[0]; }
- bool getSolveAngLimit() { return m_solveAngLim; }
- btScalar getAngDepth() { return m_angDepth; }
- // shared code used by ODE solver
- void calculateTransforms(const btTransform& transA, const btTransform& transB);
- void testLinLimits();
- void testAngLimits();
- // access for PE Solver
- btVector3 getAncorInA();
- btVector3 getAncorInB();
- // access for UseFrameOffset
- bool getUseFrameOffset() { return m_useOffsetForConstraintFrame; }
- void setUseFrameOffset(bool frameOffsetOnOff) { m_useOffsetForConstraintFrame = frameOffsetOnOff; }
-
- void setFrames(const btTransform& frameA, const btTransform& frameB)
- {
- m_frameInA = frameA;
- m_frameInB = frameB;
- calculateTransforms(m_rbA.getCenterOfMassTransform(), m_rbB.getCenterOfMassTransform());
- buildJacobian();
- }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1);
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const;
-
- virtual int getFlags() const
- {
- return m_flags;
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-
-struct btSliderConstraintData
-{
- btTypedConstraintData m_typeConstraintData;
- btTransformFloatData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformFloatData m_rbBFrame;
-
- float m_linearUpperLimit;
- float m_linearLowerLimit;
-
- float m_angularUpperLimit;
- float m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-struct btSliderConstraintDoubleData
-{
- btTypedConstraintDoubleData m_typeConstraintData;
- btTransformDoubleData m_rbAFrame; // constraint axii. Assumes z is hinge axis.
- btTransformDoubleData m_rbBFrame;
-
- double m_linearUpperLimit;
- double m_linearLowerLimit;
-
- double m_angularUpperLimit;
- double m_angularLowerLimit;
-
- int m_useLinearReferenceFrameA;
- int m_useOffsetForConstraintFrame;
-};
-
-SIMD_FORCE_INLINE int btSliderConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btSliderConstraintData2);
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-SIMD_FORCE_INLINE const char* btSliderConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btSliderConstraintData2* sliderData = (btSliderConstraintData2*)dataBuffer;
- btTypedConstraint::serialize(&sliderData->m_typeConstraintData, serializer);
-
- m_frameInA.serialize(sliderData->m_rbAFrame);
- m_frameInB.serialize(sliderData->m_rbBFrame);
-
- sliderData->m_linearUpperLimit = m_upperLinLimit;
- sliderData->m_linearLowerLimit = m_lowerLinLimit;
-
- sliderData->m_angularUpperLimit = m_upperAngLimit;
- sliderData->m_angularLowerLimit = m_lowerAngLimit;
-
- sliderData->m_useLinearReferenceFrameA = m_useLinearReferenceFrameA;
- sliderData->m_useOffsetForConstraintFrame = m_useOffsetForConstraintFrame;
-
- return btSliderConstraintDataName;
-}
-
-#endif //BT_SLIDER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
deleted file mode 100644
index 1ea20edcb2..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSolve2LinearConstraint.h"
-
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btVector3.h"
-#include "btJacobianEntry.h"
-
-void btSolve2LinearConstraint::resolveUnilateralPairConstraint(
- btRigidBody* body1,
- btRigidBody* body2,
-
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA, const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB, const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1, const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0, btScalar& imp1)
-{
- (void)linvelA;
- (void)linvelB;
- (void)angvelB;
- (void)angvelA;
-
- imp0 = btScalar(0.);
- imp1 = btScalar(0.);
-
- btScalar len = btFabs(normalA.length()) - btScalar(1.);
- if (btFabs(len) >= SIMD_EPSILON)
- return;
-
- btAssert(len < SIMD_EPSILON);
-
- //this jacobian entry could be re-used for all iterations
- btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
- invInertiaBDiag, invMassB);
- btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
- invInertiaBDiag, invMassB);
-
- //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
- //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
-
- const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
- const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
-
- // btScalar penetrationImpulse = (depth*contactTau*timeCorrection) * massTerm;//jacDiagABInv
- btScalar massTerm = btScalar(1.) / (invMassA + invMassB);
-
- // calculate rhs (or error) terms
- const btScalar dv0 = depthA * m_tau * massTerm - vel0 * m_damping;
- const btScalar dv1 = depthB * m_tau * massTerm - vel1 * m_damping;
-
- // dC/dv * dv = -C
-
- // jacobian * impulse = -error
- //
-
- //impulse = jacobianInverse * -error
-
- // inverting 2x2 symmetric system (offdiagonal are equal!)
- //
-
- btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
- btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
-
- //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
-
- imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
-
- //[a b] [d -c]
- //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
-
- //[jA nD] * [imp0] = [dv0]
- //[nD jB] [imp1] [dv1]
-}
-
-void btSolve2LinearConstraint::resolveBilateralPairConstraint(
- btRigidBody* body1,
- btRigidBody* body2,
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA, const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB, const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1, const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0, btScalar& imp1)
-{
- (void)linvelA;
- (void)linvelB;
- (void)angvelA;
- (void)angvelB;
-
- imp0 = btScalar(0.);
- imp1 = btScalar(0.);
-
- btScalar len = btFabs(normalA.length()) - btScalar(1.);
- if (btFabs(len) >= SIMD_EPSILON)
- return;
-
- btAssert(len < SIMD_EPSILON);
-
- //this jacobian entry could be re-used for all iterations
- btJacobianEntry jacA(world2A, world2B, rel_posA1, rel_posA2, normalA, invInertiaADiag, invMassA,
- invInertiaBDiag, invMassB);
- btJacobianEntry jacB(world2A, world2B, rel_posB1, rel_posB2, normalB, invInertiaADiag, invMassA,
- invInertiaBDiag, invMassB);
-
- //const btScalar vel0 = jacA.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
- //const btScalar vel1 = jacB.getRelativeVelocity(linvelA,angvelA,linvelB,angvelB);
-
- const btScalar vel0 = normalA.dot(body1->getVelocityInLocalPoint(rel_posA1) - body2->getVelocityInLocalPoint(rel_posA1));
- const btScalar vel1 = normalB.dot(body1->getVelocityInLocalPoint(rel_posB1) - body2->getVelocityInLocalPoint(rel_posB1));
-
- // calculate rhs (or error) terms
- const btScalar dv0 = depthA * m_tau - vel0 * m_damping;
- const btScalar dv1 = depthB * m_tau - vel1 * m_damping;
-
- // dC/dv * dv = -C
-
- // jacobian * impulse = -error
- //
-
- //impulse = jacobianInverse * -error
-
- // inverting 2x2 symmetric system (offdiagonal are equal!)
- //
-
- btScalar nonDiag = jacA.getNonDiagonal(jacB, invMassA, invMassB);
- btScalar invDet = btScalar(1.0) / (jacA.getDiagonal() * jacB.getDiagonal() - nonDiag * nonDiag);
-
- //imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- //imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * - nonDiag * invDet;
-
- imp0 = dv0 * jacA.getDiagonal() * invDet + dv1 * -nonDiag * invDet;
- imp1 = dv1 * jacB.getDiagonal() * invDet + dv0 * -nonDiag * invDet;
-
- //[a b] [d -c]
- //[c d] inverse = (1 / determinant) * [-b a] where determinant is (ad - bc)
-
- //[jA nD] * [imp0] = [dv0]
- //[nD jB] [imp1] [dv1]
-
- if (imp0 > btScalar(0.0))
- {
- if (imp1 > btScalar(0.0))
- {
- //both positive
- }
- else
- {
- imp1 = btScalar(0.);
-
- // now imp0>0 imp1<0
- imp0 = dv0 / jacA.getDiagonal();
- if (imp0 > btScalar(0.0))
- {
- }
- else
- {
- imp0 = btScalar(0.);
- }
- }
- }
- else
- {
- imp0 = btScalar(0.);
-
- imp1 = dv1 / jacB.getDiagonal();
- if (imp1 <= btScalar(0.0))
- {
- imp1 = btScalar(0.);
- // now imp0>0 imp1<0
- imp0 = dv0 / jacA.getDiagonal();
- if (imp0 > btScalar(0.0))
- {
- }
- else
- {
- imp0 = btScalar(0.);
- }
- }
- else
- {
- }
- }
-}
-
-/*
-void btSolve2LinearConstraint::resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btMatrix3x3& invInertiaBWS,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1)
-{
-
-}
-*/
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
deleted file mode 100644
index fca8ecec81..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOLVE_2LINEAR_CONSTRAINT_H
-#define BT_SOLVE_2LINEAR_CONSTRAINT_H
-
-#include "LinearMath/btMatrix3x3.h"
-#include "LinearMath/btVector3.h"
-
-class btRigidBody;
-
-/// constraint class used for lateral tyre friction.
-class btSolve2LinearConstraint
-{
- btScalar m_tau;
- btScalar m_damping;
-
-public:
- btSolve2LinearConstraint(btScalar tau, btScalar damping)
- {
- m_tau = tau;
- m_damping = damping;
- }
- //
- // solve unilateral constraint (equality, direct method)
- //
- void resolveUnilateralPairConstraint(
- btRigidBody* body0,
- btRigidBody* body1,
-
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA, const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB, const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1, const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0, btScalar& imp1);
-
- //
- // solving 2x2 lcp problem (inequality, direct solution )
- //
- void resolveBilateralPairConstraint(
- btRigidBody* body0,
- btRigidBody* body1,
- const btMatrix3x3& world2A,
- const btMatrix3x3& world2B,
-
- const btVector3& invInertiaADiag,
- const btScalar invMassA,
- const btVector3& linvelA, const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btVector3& invInertiaBDiag,
- const btScalar invMassB,
- const btVector3& linvelB, const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1, const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0, btScalar& imp1);
-
- /*
- void resolveAngularConstraint( const btMatrix3x3& invInertiaAWS,
- const btScalar invMassA,
- const btVector3& linvelA,const btVector3& angvelA,
- const btVector3& rel_posA1,
- const btMatrix3x3& invInertiaBWS,
- const btScalar invMassB,
- const btVector3& linvelB,const btVector3& angvelB,
- const btVector3& rel_posA2,
-
- btScalar depthA, const btVector3& normalA,
- const btVector3& rel_posB1,const btVector3& rel_posB2,
- btScalar depthB, const btVector3& normalB,
- btScalar& imp0,btScalar& imp1);
-
-*/
-};
-
-#endif //BT_SOLVE_2LINEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
deleted file mode 100644
index 409aa8a08c..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverBody.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOLVER_BODY_H
-#define BT_SOLVER_BODY_H
-
-class btRigidBody;
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btMatrix3x3.h"
-
-#include "LinearMath/btAlignedAllocator.h"
-#include "LinearMath/btTransformUtil.h"
-
-///Until we get other contributions, only use SIMD on Windows, when using Visual Studio 2008 or later, and not double precision
-#ifdef BT_USE_SSE
-#define USE_SIMD 1
-#endif //
-
-#ifdef USE_SIMD
-
-struct btSimdScalar
-{
- SIMD_FORCE_INLINE btSimdScalar()
- {
- }
-
- SIMD_FORCE_INLINE btSimdScalar(float fl)
- : m_vec128(_mm_set1_ps(fl))
- {
- }
-
- SIMD_FORCE_INLINE btSimdScalar(__m128 v128)
- : m_vec128(v128)
- {
- }
- union {
- __m128 m_vec128;
- float m_floats[4];
- int m_ints[4];
- btScalar m_unusedPadding;
- };
- SIMD_FORCE_INLINE __m128 get128()
- {
- return m_vec128;
- }
-
- SIMD_FORCE_INLINE const __m128 get128() const
- {
- return m_vec128;
- }
-
- SIMD_FORCE_INLINE void set128(__m128 v128)
- {
- m_vec128 = v128;
- }
-
- SIMD_FORCE_INLINE operator __m128()
- {
- return m_vec128;
- }
- SIMD_FORCE_INLINE operator const __m128() const
- {
- return m_vec128;
- }
-
- SIMD_FORCE_INLINE operator float() const
- {
- return m_floats[0];
- }
-};
-
-///@brief Return the elementwise product of two btSimdScalar
-SIMD_FORCE_INLINE btSimdScalar
-operator*(const btSimdScalar& v1, const btSimdScalar& v2)
-{
- return btSimdScalar(_mm_mul_ps(v1.get128(), v2.get128()));
-}
-
-///@brief Return the elementwise product of two btSimdScalar
-SIMD_FORCE_INLINE btSimdScalar
-operator+(const btSimdScalar& v1, const btSimdScalar& v2)
-{
- return btSimdScalar(_mm_add_ps(v1.get128(), v2.get128()));
-}
-
-#else
-#define btSimdScalar btScalar
-#endif
-
-///The btSolverBody is an internal datastructure for the constraint solver. Only necessary data is packed to increase cache coherence/performance.
-ATTRIBUTE_ALIGNED16(struct)
-btSolverBody
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
- btTransform m_worldTransform;
- btVector3 m_deltaLinearVelocity;
- btVector3 m_deltaAngularVelocity;
- btVector3 m_angularFactor;
- btVector3 m_linearFactor;
- btVector3 m_invMass;
- btVector3 m_pushVelocity;
- btVector3 m_turnVelocity;
- btVector3 m_linearVelocity;
- btVector3 m_angularVelocity;
- btVector3 m_externalForceImpulse;
- btVector3 m_externalTorqueImpulse;
-
- btRigidBody* m_originalBody;
- void setWorldTransform(const btTransform& worldTransform)
- {
- m_worldTransform = worldTransform;
- }
-
- const btTransform& getWorldTransform() const
- {
- return m_worldTransform;
- }
-
- SIMD_FORCE_INLINE void getVelocityInLocalPointNoDelta(const btVector3& rel_pos, btVector3& velocity) const
- {
- if (m_originalBody)
- velocity = m_linearVelocity + m_externalForceImpulse + (m_angularVelocity + m_externalTorqueImpulse).cross(rel_pos);
- else
- velocity.setValue(0, 0, 0);
- }
-
- SIMD_FORCE_INLINE void getVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
- {
- if (m_originalBody)
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- else
- velocity.setValue(0, 0, 0);
- }
-
- SIMD_FORCE_INLINE void getAngularVelocity(btVector3 & angVel) const
- {
- if (m_originalBody)
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- else
- angVel.setValue(0, 0, 0);
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- SIMD_FORCE_INLINE void applyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent, btScalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_pushVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_turnVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- const btVector3& getDeltaLinearVelocity() const
- {
- return m_deltaLinearVelocity;
- }
-
- const btVector3& getDeltaAngularVelocity() const
- {
- return m_deltaAngularVelocity;
- }
-
- const btVector3& getPushVelocity() const
- {
- return m_pushVelocity;
- }
-
- const btVector3& getTurnVelocity() const
- {
- return m_turnVelocity;
- }
-
- ////////////////////////////////////////////////
- ///some internal methods, don't use them
-
- btVector3& internalGetDeltaLinearVelocity()
- {
- return m_deltaLinearVelocity;
- }
-
- btVector3& internalGetDeltaAngularVelocity()
- {
- return m_deltaAngularVelocity;
- }
-
- const btVector3& internalGetAngularFactor() const
- {
- return m_angularFactor;
- }
-
- const btVector3& internalGetInvMass() const
- {
- return m_invMass;
- }
-
- void internalSetInvMass(const btVector3& invMass)
- {
- m_invMass = invMass;
- }
-
- btVector3& internalGetPushVelocity()
- {
- return m_pushVelocity;
- }
-
- btVector3& internalGetTurnVelocity()
- {
- return m_turnVelocity;
- }
-
- SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity) const
- {
- velocity = m_linearVelocity + m_deltaLinearVelocity + (m_angularVelocity + m_deltaAngularVelocity).cross(rel_pos);
- }
-
- SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3 & angVel) const
- {
- angVel = m_angularVelocity + m_deltaAngularVelocity;
- }
-
- //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
- SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent, const btScalar impulseMagnitude)
- {
- if (m_originalBody)
- {
- m_deltaLinearVelocity += linearComponent * impulseMagnitude * m_linearFactor;
- m_deltaAngularVelocity += angularComponent * (impulseMagnitude * m_angularFactor);
- }
- }
-
- void writebackVelocity()
- {
- if (m_originalBody)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //m_originalBody->setCompanionId(-1);
- }
- }
-
- void writebackVelocityAndTransform(btScalar timeStep, btScalar splitImpulseTurnErp)
- {
- (void)timeStep;
- if (m_originalBody)
- {
- m_linearVelocity += m_deltaLinearVelocity;
- m_angularVelocity += m_deltaAngularVelocity;
-
- //correct the position/orientation based on push/turn recovery
- btTransform newTransform;
- if (m_pushVelocity[0] != 0.f || m_pushVelocity[1] != 0 || m_pushVelocity[2] != 0 || m_turnVelocity[0] != 0.f || m_turnVelocity[1] != 0 || m_turnVelocity[2] != 0)
- {
- // btQuaternion orn = m_worldTransform.getRotation();
- btTransformUtil::integrateTransform(m_worldTransform, m_pushVelocity, m_turnVelocity * splitImpulseTurnErp, timeStep, newTransform);
- m_worldTransform = newTransform;
- }
- //m_worldTransform.setRotation(orn);
- //m_originalBody->setCompanionId(-1);
- }
- }
-};
-
-#endif //BT_SOLVER_BODY_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
deleted file mode 100644
index c7938df867..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btSolverConstraint.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOLVER_CONSTRAINT_H
-#define BT_SOLVER_CONSTRAINT_H
-
-class btRigidBody;
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "btJacobianEntry.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-//#define NO_FRICTION_TANGENTIALS 1
-#include "btSolverBody.h"
-
-///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-ATTRIBUTE_ALIGNED16(struct)
-btSolverConstraint
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btVector3 m_relpos1CrossNormal;
- btVector3 m_contactNormal1;
-
- btVector3 m_relpos2CrossNormal;
- btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
-
- btVector3 m_angularComponentA;
- btVector3 m_angularComponentB;
-
- mutable btSimdScalar m_appliedPushImpulse;
- mutable btSimdScalar m_appliedImpulse;
-
- btScalar m_friction;
- btScalar m_jacDiagABInv;
- btScalar m_rhs;
- btScalar m_cfm;
-
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_rhsPenetration;
- union {
- void* m_originalContactPoint;
- btScalar m_unusedPadding4;
- int m_numRowsForNonContactConstraint;
- };
-
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
- int m_solverBodyIdA;
- int m_solverBodyIdB;
-
- enum btSolverConstraintType
- {
- BT_SOLVER_CONTACT_1D = 0,
- BT_SOLVER_FRICTION_1D
- };
-};
-
-typedef btAlignedObjectArray<btSolverConstraint> btConstraintArray;
-
-#endif //BT_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
deleted file mode 100644
index ebe679c449..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.cpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btTypedConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btSerializer.h"
-
-#define DEFAULT_DEBUGDRAW_SIZE btScalar(0.05f)
-
-btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA)
- : btTypedObject(type),
- m_userConstraintType(-1),
- m_userConstraintPtr((void*)-1),
- m_breakingImpulseThreshold(SIMD_INFINITY),
- m_isEnabled(true),
- m_needsFeedback(false),
- m_overrideNumSolverIterations(-1),
- m_rbA(rbA),
- m_rbB(getFixedBody()),
- m_appliedImpulse(btScalar(0.)),
- m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
- m_jointFeedback(0)
-{
-}
-
-btTypedConstraint::btTypedConstraint(btTypedConstraintType type, btRigidBody& rbA, btRigidBody& rbB)
- : btTypedObject(type),
- m_userConstraintType(-1),
- m_userConstraintPtr((void*)-1),
- m_breakingImpulseThreshold(SIMD_INFINITY),
- m_isEnabled(true),
- m_needsFeedback(false),
- m_overrideNumSolverIterations(-1),
- m_rbA(rbA),
- m_rbB(rbB),
- m_appliedImpulse(btScalar(0.)),
- m_dbgDrawSize(DEFAULT_DEBUGDRAW_SIZE),
- m_jointFeedback(0)
-{
-}
-
-btScalar btTypedConstraint::getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact)
-{
- if (lowLim > uppLim)
- {
- return btScalar(1.0f);
- }
- else if (lowLim == uppLim)
- {
- return btScalar(0.0f);
- }
- btScalar lim_fact = btScalar(1.0f);
- btScalar delta_max = vel / timeFact;
- if (delta_max < btScalar(0.0f))
- {
- if ((pos >= lowLim) && (pos < (lowLim - delta_max)))
- {
- lim_fact = (lowLim - pos) / delta_max;
- }
- else if (pos < lowLim)
- {
- lim_fact = btScalar(0.0f);
- }
- else
- {
- lim_fact = btScalar(1.0f);
- }
- }
- else if (delta_max > btScalar(0.0f))
- {
- if ((pos <= uppLim) && (pos > (uppLim - delta_max)))
- {
- lim_fact = (uppLim - pos) / delta_max;
- }
- else if (pos > uppLim)
- {
- lim_fact = btScalar(0.0f);
- }
- else
- {
- lim_fact = btScalar(1.0f);
- }
- }
- else
- {
- lim_fact = btScalar(0.0f);
- }
- return lim_fact;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btTypedConstraint::serialize(void* dataBuffer, btSerializer* serializer) const
-{
- btTypedConstraintData2* tcd = (btTypedConstraintData2*)dataBuffer;
-
- tcd->m_rbA = (btRigidBodyData*)serializer->getUniquePointer(&m_rbA);
- tcd->m_rbB = (btRigidBodyData*)serializer->getUniquePointer(&m_rbB);
- char* name = (char*)serializer->findNameForPointer(this);
- tcd->m_name = (char*)serializer->getUniquePointer(name);
- if (tcd->m_name)
- {
- serializer->serializeName(name);
- }
-
- tcd->m_objectType = m_objectType;
- tcd->m_needsFeedback = m_needsFeedback;
- tcd->m_overrideNumSolverIterations = m_overrideNumSolverIterations;
- tcd->m_breakingImpulseThreshold = m_breakingImpulseThreshold;
- tcd->m_isEnabled = m_isEnabled ? 1 : 0;
-
- tcd->m_userConstraintId = m_userConstraintId;
- tcd->m_userConstraintType = m_userConstraintType;
-
- tcd->m_appliedImpulse = m_appliedImpulse;
- tcd->m_dbgDrawSize = m_dbgDrawSize;
-
- tcd->m_disableCollisionsBetweenLinkedBodies = false;
-
- int i;
- for (i = 0; i < m_rbA.getNumConstraintRefs(); i++)
- if (m_rbA.getConstraintRef(i) == this)
- tcd->m_disableCollisionsBetweenLinkedBodies = true;
- for (i = 0; i < m_rbB.getNumConstraintRefs(); i++)
- if (m_rbB.getConstraintRef(i) == this)
- tcd->m_disableCollisionsBetweenLinkedBodies = true;
-
- return btTypedConstraintDataName;
-}
-
-btRigidBody& btTypedConstraint::getFixedBody()
-{
- static btRigidBody s_fixed(0, 0, 0);
- s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
- return s_fixed;
-}
-
-void btAngularLimit::set(btScalar low, btScalar high, btScalar _softness, btScalar _biasFactor, btScalar _relaxationFactor)
-{
- m_halfRange = (high - low) / 2.0f;
- m_center = btNormalizeAngle(low + m_halfRange);
- m_softness = _softness;
- m_biasFactor = _biasFactor;
- m_relaxationFactor = _relaxationFactor;
-}
-
-void btAngularLimit::test(const btScalar angle)
-{
- m_correction = 0.0f;
- m_sign = 0.0f;
- m_solveLimit = false;
-
- if (m_halfRange >= 0.0f)
- {
- btScalar deviation = btNormalizeAngle(angle - m_center);
- if (deviation < -m_halfRange)
- {
- m_solveLimit = true;
- m_correction = -(deviation + m_halfRange);
- m_sign = +1.0f;
- }
- else if (deviation > m_halfRange)
- {
- m_solveLimit = true;
- m_correction = m_halfRange - deviation;
- m_sign = -1.0f;
- }
- }
-}
-
-btScalar btAngularLimit::getError() const
-{
- return m_correction * m_sign;
-}
-
-void btAngularLimit::fit(btScalar& angle) const
-{
- if (m_halfRange > 0.0f)
- {
- btScalar relativeAngle = btNormalizeAngle(angle - m_center);
- if (!btEqual(relativeAngle, m_halfRange))
- {
- if (relativeAngle > 0.0f)
- {
- angle = getHigh();
- }
- else
- {
- angle = getLow();
- }
- }
- }
-}
-
-btScalar btAngularLimit::getLow() const
-{
- return btNormalizeAngle(m_center - m_halfRange);
-}
-
-btScalar btAngularLimit::getHigh() const
-{
- return btNormalizeAngle(m_center + m_halfRange);
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
deleted file mode 100644
index d30f3dee5c..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btTypedConstraint.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2010 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TYPED_CONSTRAINT_H
-#define BT_TYPED_CONSTRAINT_H
-
-#include "LinearMath/btScalar.h"
-#include "btSolverConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btTypedConstraintData2 btTypedConstraintDoubleData
-#define btTypedConstraintDataName "btTypedConstraintDoubleData"
-#else
-#define btTypedConstraintData2 btTypedConstraintFloatData
-#define btTypedConstraintDataName "btTypedConstraintFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-class btSerializer;
-
-//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
-enum btTypedConstraintType
-{
- POINT2POINT_CONSTRAINT_TYPE = 3,
- HINGE_CONSTRAINT_TYPE,
- CONETWIST_CONSTRAINT_TYPE,
- D6_CONSTRAINT_TYPE,
- SLIDER_CONSTRAINT_TYPE,
- CONTACT_CONSTRAINT_TYPE,
- D6_SPRING_CONSTRAINT_TYPE,
- GEAR_CONSTRAINT_TYPE,
- FIXED_CONSTRAINT_TYPE,
- D6_SPRING_2_CONSTRAINT_TYPE,
- MAX_CONSTRAINT_TYPE
-};
-
-enum btConstraintParams
-{
- BT_CONSTRAINT_ERP = 1,
- BT_CONSTRAINT_STOP_ERP,
- BT_CONSTRAINT_CFM,
- BT_CONSTRAINT_STOP_CFM
-};
-
-#if 1
-#define btAssertConstrParams(_par) btAssert(_par)
-#else
-#define btAssertConstrParams(_par)
-#endif
-
-ATTRIBUTE_ALIGNED16(struct)
-btJointFeedback
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
- btVector3 m_appliedForceBodyA;
- btVector3 m_appliedTorqueBodyA;
- btVector3 m_appliedForceBodyB;
- btVector3 m_appliedTorqueBodyB;
-};
-
-///TypedConstraint is the baseclass for Bullet constraints and vehicles
-ATTRIBUTE_ALIGNED16(class)
-btTypedConstraint : public btTypedObject
-{
- int m_userConstraintType;
-
- union {
- int m_userConstraintId;
- void* m_userConstraintPtr;
- };
-
- btScalar m_breakingImpulseThreshold;
- bool m_isEnabled;
- bool m_needsFeedback;
- int m_overrideNumSolverIterations;
-
- btTypedConstraint& operator=(btTypedConstraint& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
-protected:
- btRigidBody& m_rbA;
- btRigidBody& m_rbB;
- btScalar m_appliedImpulse;
- btScalar m_dbgDrawSize;
- btJointFeedback* m_jointFeedback;
-
- ///internal method used by the constraint solver, don't use them directly
- btScalar getMotorFactor(btScalar pos, btScalar lowLim, btScalar uppLim, btScalar vel, btScalar timeFact);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- virtual ~btTypedConstraint(){};
- btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA);
- btTypedConstraint(btTypedConstraintType type, btRigidBody & rbA, btRigidBody & rbB);
-
- struct btConstraintInfo1
- {
- int m_numConstraintRows, nub;
- };
-
- static btRigidBody& getFixedBody();
-
- struct btConstraintInfo2
- {
- // integrator parameters: frames per second (1/stepsize), default error
- // reduction parameter (0..1).
- btScalar fps, erp;
-
- // for the first and second body, pointers to two (linear and angular)
- // n*3 jacobian sub matrices, stored by rows. these matrices will have
- // been initialized to 0 on entry. if the second body is zero then the
- // J2xx pointers may be 0.
- btScalar *m_J1linearAxis, *m_J1angularAxis, *m_J2linearAxis, *m_J2angularAxis;
-
- // elements to jump from one row to the next in J's
- int rowskip;
-
- // right hand sides of the equation J*v = c + cfm * lambda. cfm is the
- // "constraint force mixing" vector. c is set to zero on entry, cfm is
- // set to a constant value (typically very small or zero) value on entry.
- btScalar *m_constraintError, *cfm;
-
- // lo and hi limits for variables (set to -/+ infinity on entry).
- btScalar *m_lowerLimit, *m_upperLimit;
-
- // number of solver iterations
- int m_numIterations;
-
- //damping of the velocity
- btScalar m_damping;
- };
-
- int getOverrideNumSolverIterations() const
- {
- return m_overrideNumSolverIterations;
- }
-
- ///override the number of constraint solver iterations used to solve this constraint
- ///-1 will use the default number of iterations, as specified in SolverInfo.m_numIterations
- void setOverrideNumSolverIterations(int overideNumIterations)
- {
- m_overrideNumSolverIterations = overideNumIterations;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void buildJacobian(){};
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void setupSolverConstraint(btConstraintArray & ca, int solverBodyA, int solverBodyB, btScalar timeStep)
- {
- (void)ca;
- (void)solverBodyA;
- (void)solverBodyB;
- (void)timeStep;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo1(btConstraintInfo1 * info) = 0;
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void getInfo2(btConstraintInfo2 * info) = 0;
-
- ///internal method used by the constraint solver, don't use them directly
- void internalSetAppliedImpulse(btScalar appliedImpulse)
- {
- m_appliedImpulse = appliedImpulse;
- }
- ///internal method used by the constraint solver, don't use them directly
- btScalar internalGetAppliedImpulse()
- {
- return m_appliedImpulse;
- }
-
- btScalar getBreakingImpulseThreshold() const
- {
- return m_breakingImpulseThreshold;
- }
-
- void setBreakingImpulseThreshold(btScalar threshold)
- {
- m_breakingImpulseThreshold = threshold;
- }
-
- bool isEnabled() const
- {
- return m_isEnabled;
- }
-
- void setEnabled(bool enabled)
- {
- m_isEnabled = enabled;
- }
-
- ///internal method used by the constraint solver, don't use them directly
- virtual void solveConstraintObsolete(btSolverBody& /*bodyA*/, btSolverBody& /*bodyB*/, btScalar /*timeStep*/){};
-
- const btRigidBody& getRigidBodyA() const
- {
- return m_rbA;
- }
- const btRigidBody& getRigidBodyB() const
- {
- return m_rbB;
- }
-
- btRigidBody& getRigidBodyA()
- {
- return m_rbA;
- }
- btRigidBody& getRigidBodyB()
- {
- return m_rbB;
- }
-
- int getUserConstraintType() const
- {
- return m_userConstraintType;
- }
-
- void setUserConstraintType(int userConstraintType)
- {
- m_userConstraintType = userConstraintType;
- };
-
- void setUserConstraintId(int uid)
- {
- m_userConstraintId = uid;
- }
-
- int getUserConstraintId() const
- {
- return m_userConstraintId;
- }
-
- void setUserConstraintPtr(void* ptr)
- {
- m_userConstraintPtr = ptr;
- }
-
- void* getUserConstraintPtr()
- {
- return m_userConstraintPtr;
- }
-
- void setJointFeedback(btJointFeedback * jointFeedback)
- {
- m_jointFeedback = jointFeedback;
- }
-
- const btJointFeedback* getJointFeedback() const
- {
- return m_jointFeedback;
- }
-
- btJointFeedback* getJointFeedback()
- {
- return m_jointFeedback;
- }
-
- int getUid() const
- {
- return m_userConstraintId;
- }
-
- bool needsFeedback() const
- {
- return m_needsFeedback;
- }
-
- ///enableFeedback will allow to read the applied linear and angular impulse
- ///use getAppliedImpulse, getAppliedLinearImpulse and getAppliedAngularImpulse to read feedback information
- void enableFeedback(bool needsFeedback)
- {
- m_needsFeedback = needsFeedback;
- }
-
- ///getAppliedImpulse is an estimated total applied impulse.
- ///This feedback could be used to determine breaking constraints or playing sounds.
- btScalar getAppliedImpulse() const
- {
- btAssert(m_needsFeedback);
- return m_appliedImpulse;
- }
-
- btTypedConstraintType getConstraintType() const
- {
- return btTypedConstraintType(m_objectType);
- }
-
- void setDbgDrawSize(btScalar dbgDrawSize)
- {
- m_dbgDrawSize = dbgDrawSize;
- }
- btScalar getDbgDrawSize()
- {
- return m_dbgDrawSize;
- }
-
- ///override the default global value of a parameter (such as ERP or CFM), optionally provide the axis (0..5).
- ///If no axis is provided, it uses the default axis for this constraint.
- virtual void setParam(int num, btScalar value, int axis = -1) = 0;
-
- ///return the local value of parameter
- virtual btScalar getParam(int num, int axis = -1) const = 0;
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
-};
-
-// returns angle in range [-SIMD_2_PI, SIMD_2_PI], closest to one of the limits
-// all arguments should be normalized angles (i.e. in range [-SIMD_PI, SIMD_PI])
-SIMD_FORCE_INLINE btScalar btAdjustAngleToLimits(btScalar angleInRadians, btScalar angleLowerLimitInRadians, btScalar angleUpperLimitInRadians)
-{
- if (angleLowerLimitInRadians >= angleUpperLimitInRadians)
- {
- return angleInRadians;
- }
- else if (angleInRadians < angleLowerLimitInRadians)
- {
- btScalar diffLo = btFabs(btNormalizeAngle(angleLowerLimitInRadians - angleInRadians));
- btScalar diffHi = btFabs(btNormalizeAngle(angleUpperLimitInRadians - angleInRadians));
- return (diffLo < diffHi) ? angleInRadians : (angleInRadians + SIMD_2_PI);
- }
- else if (angleInRadians > angleUpperLimitInRadians)
- {
- btScalar diffHi = btFabs(btNormalizeAngle(angleInRadians - angleUpperLimitInRadians));
- btScalar diffLo = btFabs(btNormalizeAngle(angleInRadians - angleLowerLimitInRadians));
- return (diffLo < diffHi) ? (angleInRadians - SIMD_2_PI) : angleInRadians;
- }
- else
- {
- return angleInRadians;
- }
-}
-
-// clang-format off
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btTypedConstraintFloatData
-{
- btRigidBodyFloatData *m_rbA;
- btRigidBodyFloatData *m_rbB;
- char *m_name;
-
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
-
- float m_appliedImpulse;
- float m_dbgDrawSize;
-
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
-
- float m_breakingImpulseThreshold;
- int m_isEnabled;
-
-};
-
-
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-
-#define BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-#ifdef BT_BACKWARDS_COMPATIBLE_SERIALIZATION
-///this structure is not used, except for loading pre-2.82 .bullet files
-struct btTypedConstraintData
-{
- btRigidBodyData *m_rbA;
- btRigidBodyData *m_rbB;
- char *m_name;
-
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
-
- float m_appliedImpulse;
- float m_dbgDrawSize;
-
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
-
- float m_breakingImpulseThreshold;
- int m_isEnabled;
-
-};
-#endif //BACKWARDS_COMPATIBLE
-
-struct btTypedConstraintDoubleData
-{
- btRigidBodyDoubleData *m_rbA;
- btRigidBodyDoubleData *m_rbB;
- char *m_name;
-
- int m_objectType;
- int m_userConstraintType;
- int m_userConstraintId;
- int m_needsFeedback;
-
- double m_appliedImpulse;
- double m_dbgDrawSize;
-
- int m_disableCollisionsBetweenLinkedBodies;
- int m_overrideNumSolverIterations;
-
- double m_breakingImpulseThreshold;
- int m_isEnabled;
- char padding[4];
-
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btTypedConstraint::calculateSerializeBufferSize() const
-{
- return sizeof(btTypedConstraintData2);
-}
-
-class btAngularLimit
-{
-private:
- btScalar
- m_center,
- m_halfRange,
- m_softness,
- m_biasFactor,
- m_relaxationFactor,
- m_correction,
- m_sign;
-
- bool
- m_solveLimit;
-
-public:
- /// Default constructor initializes limit as inactive, allowing free constraint movement
- btAngularLimit()
- : m_center(0.0f),
- m_halfRange(-1.0f),
- m_softness(0.9f),
- m_biasFactor(0.3f),
- m_relaxationFactor(1.0f),
- m_correction(0.0f),
- m_sign(0.0f),
- m_solveLimit(false)
- {
- }
-
- /// Sets all limit's parameters.
- /// When low > high limit becomes inactive.
- /// When high - low > 2PI limit is ineffective too becouse no angle can exceed the limit
- void set(btScalar low, btScalar high, btScalar _softness = 0.9f, btScalar _biasFactor = 0.3f, btScalar _relaxationFactor = 1.0f);
-
- /// Checks conastaint angle against limit. If limit is active and the angle violates the limit
- /// correction is calculated.
- void test(const btScalar angle);
-
- /// Returns limit's softness
- inline btScalar getSoftness() const
- {
- return m_softness;
- }
-
- /// Returns limit's bias factor
- inline btScalar getBiasFactor() const
- {
- return m_biasFactor;
- }
-
- /// Returns limit's relaxation factor
- inline btScalar getRelaxationFactor() const
- {
- return m_relaxationFactor;
- }
-
- /// Returns correction value evaluated when test() was invoked
- inline btScalar getCorrection() const
- {
- return m_correction;
- }
-
- /// Returns sign value evaluated when test() was invoked
- inline btScalar getSign() const
- {
- return m_sign;
- }
-
- /// Gives half of the distance between min and max limit angle
- inline btScalar getHalfRange() const
- {
- return m_halfRange;
- }
-
- /// Returns true when the last test() invocation recognized limit violation
- inline bool isLimit() const
- {
- return m_solveLimit;
- }
-
- /// Checks given angle against limit. If limit is active and angle doesn't fit it, the angle
- /// returned is modified so it equals to the limit closest to given angle.
- void fit(btScalar& angle) const;
-
- /// Returns correction value multiplied by sign value
- btScalar getError() const;
-
- btScalar getLow() const;
-
- btScalar getHigh() const;
-};
-
-#endif //BT_TYPED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
deleted file mode 100644
index 42ed1fbb87..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btUniversalConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btTransformUtil.h"
-
-#define UNIV_EPS btScalar(0.01f)
-
-// constructor
-// anchor, axis1 and axis2 are in world coordinate system
-// axis1 must be orthogonal to axis2
-btUniversalConstraint::btUniversalConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2)
- : btGeneric6DofConstraint(rbA, rbB, btTransform::getIdentity(), btTransform::getIdentity(), true),
- m_anchor(anchor),
- m_axis1(axis1),
- m_axis2(axis2)
-{
- // build frame basis
- // 6DOF constraint uses Euler angles and to define limits
- // it is assumed that rotational order is :
- // Z - first, allowed limits are (-PI,PI);
- // new position of Y - second (allowed limits are (-PI/2 + epsilon, PI/2 - epsilon), where epsilon is a small positive number
- // used to prevent constraint from instability on poles;
- // new position of X, allowed limits are (-PI,PI);
- // So to simulate ODE Universal joint we should use parent axis as Z, child axis as Y and limit all other DOFs
- // Build the frame in world coordinate system first
- btVector3 zAxis = m_axis1.normalize();
- btVector3 yAxis = m_axis2.normalize();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
- frameInW.setOrigin(anchor);
- // now get constraint frame in local coordinate systems
- m_frameInA = rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = rbB.getCenterOfMassTransform().inverse() * frameInW;
- // sei limits
- setLinearLowerLimit(btVector3(0., 0., 0.));
- setLinearUpperLimit(btVector3(0., 0., 0.));
- setAngularLowerLimit(btVector3(0.f, -SIMD_HALF_PI + UNIV_EPS, -SIMD_PI + UNIV_EPS));
- setAngularUpperLimit(btVector3(0.f, SIMD_HALF_PI - UNIV_EPS, SIMD_PI - UNIV_EPS));
-}
-
-void btUniversalConstraint::setAxis(const btVector3& axis1, const btVector3& axis2)
-{
- m_axis1 = axis1;
- m_axis2 = axis2;
-
- btVector3 zAxis = axis1.normalized();
- btVector3 yAxis = axis2.normalized();
- btVector3 xAxis = yAxis.cross(zAxis); // we want right coordinate system
-
- btTransform frameInW;
- frameInW.setIdentity();
- frameInW.getBasis().setValue(xAxis[0], yAxis[0], zAxis[0],
- xAxis[1], yAxis[1], zAxis[1],
- xAxis[2], yAxis[2], zAxis[2]);
- frameInW.setOrigin(m_anchor);
-
- // now get constraint frame in local coordinate systems
- m_frameInA = m_rbA.getCenterOfMassTransform().inverse() * frameInW;
- m_frameInB = m_rbB.getCenterOfMassTransform().inverse() * frameInW;
-
- calculateTransforms();
-}
diff --git a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h b/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
deleted file mode 100644
index 8c24d93a64..0000000000
--- a/thirdparty/bullet/BulletDynamics/ConstraintSolver/btUniversalConstraint.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org
-Copyright (C) 2006, 2007 Sony Computer Entertainment Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_UNIVERSAL_CONSTRAINT_H
-#define BT_UNIVERSAL_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "btTypedConstraint.h"
-#include "btGeneric6DofConstraint.h"
-
-/// Constraint similar to ODE Universal Joint
-/// has 2 rotatioonal degrees of freedom, similar to Euler rotations around Z (axis 1)
-/// and Y (axis 2)
-/// Description from ODE manual :
-/// "Given axis 1 on body 1, and axis 2 on body 2 that is perpendicular to axis 1, it keeps them perpendicular.
-/// In other words, rotation of the two bodies about the direction perpendicular to the two axes will be equal."
-
-ATTRIBUTE_ALIGNED16(class)
-btUniversalConstraint : public btGeneric6DofConstraint
-{
-protected:
- btVector3 m_anchor;
- btVector3 m_axis1;
- btVector3 m_axis2;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- // constructor
- // anchor, axis1 and axis2 are in world coordinate system
- // axis1 must be orthogonal to axis2
- btUniversalConstraint(btRigidBody & rbA, btRigidBody & rbB, const btVector3& anchor, const btVector3& axis1, const btVector3& axis2);
- // access
- const btVector3& getAnchor() { return m_calculatedTransformA.getOrigin(); }
- const btVector3& getAnchor2() { return m_calculatedTransformB.getOrigin(); }
- const btVector3& getAxis1() { return m_axis1; }
- const btVector3& getAxis2() { return m_axis2; }
- btScalar getAngle1() { return getAngle(2); }
- btScalar getAngle2() { return getAngle(1); }
- // limits
- void setUpperLimit(btScalar ang1max, btScalar ang2max) { setAngularUpperLimit(btVector3(0.f, ang1max, ang2max)); }
- void setLowerLimit(btScalar ang1min, btScalar ang2min) { setAngularLowerLimit(btVector3(0.f, ang1min, ang2min)); }
-
- void setAxis(const btVector3& axis1, const btVector3& axis2);
-};
-
-#endif // BT_UNIVERSAL_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h b/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h
deleted file mode 100644
index b5cac56cdc..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btActionInterface.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef _BT_ACTION_INTERFACE_H
-#define _BT_ACTION_INTERFACE_H
-
-class btIDebugDraw;
-class btCollisionWorld;
-
-#include "LinearMath/btScalar.h"
-#include "btRigidBody.h"
-
-///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld
-class btActionInterface
-{
-protected:
- static btRigidBody& getFixedBody();
-
-public:
- virtual ~btActionInterface()
- {
- }
-
- virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) = 0;
-
- virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
-};
-
-#endif //_BT_ACTION_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
deleted file mode 100644
index fb15ae31eb..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
+++ /dev/null
@@ -1,1469 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btDiscreteDynamicsWorld.h"
-
-//collision detection
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btQuickprof.h"
-
-//rigidbody & constraints
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
-#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-#include "BulletDynamics/Dynamics/btActionInterface.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btMotionState.h"
-
-#include "LinearMath/btSerializer.h"
-
-#if 0
-btAlignedObjectArray<btVector3> debugContacts;
-btAlignedObjectArray<btVector3> debugNormals;
-int startHit=2;
-int firstHit=startHit;
-#endif
-
-SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
-{
- int islandId;
-
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
-}
-
-class btSortConstraintOnIslandPredicate
-{
-public:
- bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetConstraintIslandId(rhs);
- lIslandId0 = btGetConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
-{
- btContactSolverInfo* m_solverInfo;
- btConstraintSolver* m_solver;
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
-
- btAlignedObjectArray<btCollisionObject*> m_bodies;
- btAlignedObjectArray<btPersistentManifold*> m_manifolds;
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
-
- InplaceSolverIslandCallback(
- btConstraintSolver* solver,
- btStackAlloc* stackAlloc,
- btDispatcher* dispatcher)
- : m_solverInfo(NULL),
- m_solver(solver),
- m_sortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
- {
- }
-
- InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
- SIMD_FORCE_INLINE void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btIDebugDraw* debugDrawer)
- {
- btAssert(solverInfo);
- m_solverInfo = solverInfo;
- m_sortedConstraints = sortedConstraints;
- m_numConstraints = numConstraints;
- m_debugDrawer = debugDrawer;
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- }
-
- virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
- {
- if (islandId < 0)
- {
- ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, &m_sortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- }
- else
- {
- //also add all non-contact constraints/joints for this island
- btTypedConstraint** startConstraint = 0;
- int numCurConstraints = 0;
- int i;
-
- //find the first constraint for this island
- for (i = 0; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
- {
- startConstraint = &m_sortedConstraints[i];
- break;
- }
- }
- //count the number of constraints in this island
- for (; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
- {
- numCurConstraints++;
- }
- }
-
- if (m_solverInfo->m_minimumSolverBatchSize <= 1)
- {
- m_solver->solveGroup(bodies, numBodies, manifolds, numManifolds, startConstraint, numCurConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- }
- else
- {
- for (i = 0; i < numBodies; i++)
- m_bodies.push_back(bodies[i]);
- for (i = 0; i < numManifolds; i++)
- m_manifolds.push_back(manifolds[i]);
- for (i = 0; i < numCurConstraints; i++)
- m_constraints.push_back(startConstraint[i]);
- if ((m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
- {
- processConstraints();
- }
- else
- {
- //printf("deferred\n");
- }
- }
- }
- }
- void processConstraints()
- {
- btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
- btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
- btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
-
- m_solver->solveGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- }
-};
-
-btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
- : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
- m_sortedConstraints(),
- m_solverIslandCallback(NULL),
- m_constraintSolver(constraintSolver),
- m_gravity(0, -10, 0),
- m_localTime(0),
- m_fixedTimeStep(0),
- m_synchronizeAllMotionStates(false),
- m_applySpeculativeContactRestitution(false),
- m_profileTimings(0),
- m_latencyMotionStateInterpolation(true)
-
-{
- if (!m_constraintSolver)
- {
- void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver), 16);
- m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
- m_ownsConstraintSolver = true;
- }
- else
- {
- m_ownsConstraintSolver = false;
- }
-
- {
- void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager), 16);
- m_islandManager = new (mem) btSimulationIslandManager();
- }
-
- m_ownsIslandManager = true;
-
- {
- void* mem = btAlignedAlloc(sizeof(InplaceSolverIslandCallback), 16);
- m_solverIslandCallback = new (mem) InplaceSolverIslandCallback(m_constraintSolver, 0, dispatcher);
- }
-}
-
-btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
-{
- //only delete it when we created it
- if (m_ownsIslandManager)
- {
- m_islandManager->~btSimulationIslandManager();
- btAlignedFree(m_islandManager);
- }
- if (m_solverIslandCallback)
- {
- m_solverIslandCallback->~InplaceSolverIslandCallback();
- btAlignedFree(m_solverIslandCallback);
- }
- if (m_ownsConstraintSolver)
- {
- m_constraintSolver->~btConstraintSolver();
- btAlignedFree(m_constraintSolver);
- }
-}
-
-void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
-{
- ///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
- ///to switch status _after_ adding kinematic objects to the world
- ///fix it for Bullet 3.x release
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body && body->getActivationState() != ISLAND_SLEEPING)
- {
- if (body->isKinematicObject())
- {
- //to calculate velocities next frame
- body->saveKinematicState(timeStep);
- }
- }
- }
-}
-
-void btDiscreteDynamicsWorld::debugDrawWorld()
-{
- BT_PROFILE("debugDrawWorld");
-
- btCollisionWorld::debugDrawWorld();
-
- bool drawConstraints = false;
- if (getDebugDrawer())
- {
- int mode = getDebugDrawer()->getDebugMode();
- if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
- {
- drawConstraints = true;
- }
- }
- if (drawConstraints)
- {
- for (int i = getNumConstraints() - 1; i >= 0; i--)
- {
- btTypedConstraint* constraint = getConstraint(i);
- debugDrawConstraint(constraint);
- }
- }
-
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb | btIDebugDraw::DBG_DrawNormals)))
- {
- int i;
-
- if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
- {
- for (i = 0; i < m_actions.size(); i++)
- {
- m_actions[i]->debugDraw(m_debugDrawer);
- }
- }
- }
- if (getDebugDrawer())
- getDebugDrawer()->flushLines();
-}
-
-void btDiscreteDynamicsWorld::clearForces()
-{
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- //need to check if next line is ok
- //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
- body->clearForces();
- }
-}
-
-///apply gravity, call this once per timestep
-void btDiscreteDynamicsWorld::applyGravity()
-{
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive())
- {
- body->applyGravity();
- }
- }
-}
-
-void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
-{
- btAssert(body);
-
- if (body->getMotionState() && !body->isStaticOrKinematicObject())
- {
- //we need to call the update at least once, even for sleeping objects
- //otherwise the 'graphics' transform never updates properly
- ///@todo: add 'dirty' flag
- //if (body->getActivationState() != ISLAND_SLEEPING)
- {
- btTransform interpolatedTransform;
- btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
- body->getInterpolationLinearVelocity(), body->getInterpolationAngularVelocity(),
- (m_latencyMotionStateInterpolation && m_fixedTimeStep) ? m_localTime - m_fixedTimeStep : m_localTime * body->getHitFraction(),
- interpolatedTransform);
- body->getMotionState()->setWorldTransform(interpolatedTransform);
- }
- }
-}
-
-void btDiscreteDynamicsWorld::synchronizeMotionStates()
-{
- // BT_PROFILE("synchronizeMotionStates");
- if (m_synchronizeAllMotionStates)
- {
- //iterate over all collision objects
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- synchronizeSingleMotionState(body);
- }
- }
- else
- {
- //iterate over all active rigid bodies
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive())
- synchronizeSingleMotionState(body);
- }
- }
-}
-
-int btDiscreteDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
-{
- startProfiling(timeStep);
-
- int numSimulationSubSteps = 0;
-
- if (maxSubSteps)
- {
- //fixed timestep with interpolation
- m_fixedTimeStep = fixedTimeStep;
- m_localTime += timeStep;
- if (m_localTime >= fixedTimeStep)
- {
- numSimulationSubSteps = int(m_localTime / fixedTimeStep);
- m_localTime -= numSimulationSubSteps * fixedTimeStep;
- }
- }
- else
- {
- //variable timestep
- fixedTimeStep = timeStep;
- m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
- m_fixedTimeStep = 0;
- if (btFuzzyZero(timeStep))
- {
- numSimulationSubSteps = 0;
- maxSubSteps = 0;
- }
- else
- {
- numSimulationSubSteps = 1;
- maxSubSteps = 1;
- }
- }
-
- //process some debugging flags
- if (getDebugDrawer())
- {
- btIDebugDraw* debugDrawer = getDebugDrawer();
- gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
- }
- if (numSimulationSubSteps)
- {
- //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
- int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
-
- saveKinematicState(fixedTimeStep * clampedSimulationSteps);
-
- applyGravity();
-
- for (int i = 0; i < clampedSimulationSteps; i++)
- {
- internalSingleStepSimulation(fixedTimeStep);
- synchronizeMotionStates();
- }
- }
- else
- {
- synchronizeMotionStates();
- }
-
- clearForces();
-
-#ifndef BT_NO_PROFILE
- CProfileManager::Increment_Frame_Counter();
-#endif //BT_NO_PROFILE
-
- return numSimulationSubSteps;
-}
-
-void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
-{
- BT_PROFILE("internalSingleStepSimulation");
-
- if (0 != m_internalPreTickCallback)
- {
- (*m_internalPreTickCallback)(this, timeStep);
- }
-
- ///apply gravity, predict motion
- predictUnconstraintMotion(timeStep);
-
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
-
- dispatchInfo.m_timeStep = timeStep;
- dispatchInfo.m_stepCount = 0;
- dispatchInfo.m_debugDraw = getDebugDrawer();
-
- createPredictiveContacts(timeStep);
-
- ///perform collision detection
- performDiscreteCollisionDetection();
-
- calculateSimulationIslands();
-
- getSolverInfo().m_timeStep = timeStep;
-
- ///solve contact and other joint constraints
- solveConstraints(getSolverInfo());
-
- ///CallbackTriggers();
-
- ///integrate transforms
-
- integrateTransforms(timeStep);
-
- ///update vehicle simulation
- updateActions(timeStep);
-
- updateActivationState(timeStep);
-
- if (0 != m_internalTickCallback)
- {
- (*m_internalTickCallback)(this, timeStep);
- }
-}
-
-void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
-{
- m_gravity = gravity;
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(gravity);
- }
- }
-}
-
-btVector3 btDiscreteDynamicsWorld::getGravity() const
-{
- return m_gravity;
-}
-
-void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject, int collisionFilterGroup, int collisionFilterMask)
-{
- btCollisionWorld::addCollisionObject(collisionObject, collisionFilterGroup, collisionFilterMask);
-}
-
-void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- btRigidBody* body = btRigidBody::upcast(collisionObject);
- if (body)
- removeRigidBody(body);
- else
- btCollisionWorld::removeCollisionObject(collisionObject);
-}
-
-void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
-{
- m_nonStaticRigidBodies.remove(body);
- btCollisionWorld::removeCollisionObject(body);
-}
-
-void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
-{
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(m_gravity);
- }
-
- if (body->getCollisionShape())
- {
- if (!body->isStaticObject())
- {
- m_nonStaticRigidBodies.push_back(body);
- }
- else
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
-
- bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
- int collisionFilterGroup = isDynamic ? int(btBroadphaseProxy::DefaultFilter) : int(btBroadphaseProxy::StaticFilter);
- int collisionFilterMask = isDynamic ? int(btBroadphaseProxy::AllFilter) : int(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
-
- addCollisionObject(body, collisionFilterGroup, collisionFilterMask);
- }
-}
-
-void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
-{
- if (!body->isStaticOrKinematicObject() && !(body->getFlags() & BT_DISABLE_WORLD_GRAVITY))
- {
- body->setGravity(m_gravity);
- }
-
- if (body->getCollisionShape())
- {
- if (!body->isStaticObject())
- {
- m_nonStaticRigidBodies.push_back(body);
- }
- else
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
- addCollisionObject(body, group, mask);
- }
-}
-
-void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
-{
- BT_PROFILE("updateActions");
-
- for (int i = 0; i < m_actions.size(); i++)
- {
- m_actions[i]->updateAction(this, timeStep);
- }
-}
-
-void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
-{
- BT_PROFILE("updateActivationState");
-
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body)
- {
- body->updateDeactivation(timeStep);
-
- if (body->wantsSleeping())
- {
- if (body->isStaticOrKinematicObject())
- {
- body->setActivationState(ISLAND_SLEEPING);
- }
- else
- {
- if (body->getActivationState() == ACTIVE_TAG)
- body->setActivationState(WANTS_DEACTIVATION);
- if (body->getActivationState() == ISLAND_SLEEPING)
- {
- body->setAngularVelocity(btVector3(0, 0, 0));
- body->setLinearVelocity(btVector3(0, 0, 0));
- }
- }
- }
- else
- {
- if (body->getActivationState() != DISABLE_DEACTIVATION)
- body->setActivationState(ACTIVE_TAG);
- }
- }
- }
-}
-
-void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies)
-{
- m_constraints.push_back(constraint);
- //Make sure the two bodies of a type constraint are different (possibly add this to the btTypedConstraint constructor?)
- btAssert(&constraint->getRigidBodyA() != &constraint->getRigidBodyB());
-
- if (disableCollisionsBetweenLinkedBodies)
- {
- constraint->getRigidBodyA().addConstraintRef(constraint);
- constraint->getRigidBodyB().addConstraintRef(constraint);
- }
-}
-
-void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
-{
- m_constraints.remove(constraint);
- constraint->getRigidBodyA().removeConstraintRef(constraint);
- constraint->getRigidBodyB().removeConstraintRef(constraint);
-}
-
-void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
-{
- m_actions.push_back(action);
-}
-
-void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
-{
- m_actions.remove(action);
-}
-
-void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
-{
- addAction(vehicle);
-}
-
-void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
-{
- removeAction(vehicle);
-}
-
-void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
-{
- addAction(character);
-}
-
-void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
-{
- removeAction(character);
-}
-
-void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
-{
- BT_PROFILE("solveConstraints");
-
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
-
- // btAssert(0);
-
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
-
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
-
- m_solverIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), getDebugDrawer());
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
-
- /// solve all the constraints for this island
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverIslandCallback);
-
- m_solverIslandCallback->processConstraints();
-
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
-}
-
-void btDiscreteDynamicsWorld::calculateSimulationIslands()
-{
- BT_PROFILE("calculateSimulationIslands");
-
- getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
-
- {
- //merge islands based on speculative contact manifolds too
- for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
-
- const btCollisionObject* colObj0 = manifold->getBody0();
- const btCollisionObject* colObj1 = manifold->getBody1();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
- }
- }
- }
-
- {
- int i;
- int numConstraints = int(m_constraints.size());
- for (i = 0; i < numConstraints; i++)
- {
- btTypedConstraint* constraint = m_constraints[i];
- if (constraint->isEnabled())
- {
- const btRigidBody* colObj0 = &constraint->getRigidBodyA();
- const btRigidBody* colObj1 = &constraint->getRigidBodyB();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
- }
- }
- }
- }
-
- //Store the island id in each body
- getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
-}
-
-class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
-{
-public:
- btCollisionObject* m_me;
- btScalar m_allowedPenetration;
- btOverlappingPairCache* m_pairCache;
- btDispatcher* m_dispatcher;
-
-public:
- btClosestNotMeConvexResultCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btCollisionWorld::ClosestConvexResultCallback(fromA, toA),
- m_me(me),
- m_allowedPenetration(0.0f),
- m_pairCache(pairCache),
- m_dispatcher(dispatcher)
- {
- }
-
- virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult, bool normalInWorldSpace)
- {
- if (convexResult.m_hitCollisionObject == m_me)
- return 1.0f;
-
- //ignore result if there is no contact response
- if (!convexResult.m_hitCollisionObject->hasContactResponse())
- return 1.0f;
-
- btVector3 linVelA, linVelB;
- linVelA = m_convexToWorld - m_convexFromWorld;
- linVelB = btVector3(0, 0, 0); //toB.getOrigin()-fromB.getOrigin();
-
- btVector3 relativeVelocity = (linVelA - linVelB);
- //don't report time of impact for motion away from the contact normal (or causes minor penetration)
- if (convexResult.m_hitNormalLocal.dot(relativeVelocity) >= -m_allowedPenetration)
- return 1.f;
-
- return ClosestConvexResultCallback::addSingleResult(convexResult, normalInWorldSpace);
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- //don't collide with itself
- if (proxy0->m_clientObject == m_me)
- return false;
-
- ///don't do CCD when the collision filters are not matching
- if (!ClosestConvexResultCallback::needsCollision(proxy0))
- return false;
- if (m_pairCache->getOverlapFilterCallback()) {
- btBroadphaseProxy* proxy1 = m_me->getBroadphaseHandle();
- bool collides = m_pairCache->needsBroadphaseCollision(proxy0, proxy1);
- if (!collides)
- {
- return false;
- }
- }
-
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
-
- if (!m_dispatcher->needsCollision(m_me, otherObj))
- return false;
-
- //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
- if (m_dispatcher->needsResponse(m_me, otherObj))
- {
-#if 0
- ///don't do CCD when there are already contact points (touching contact/penetration)
- btAlignedObjectArray<btPersistentManifold*> manifoldArray;
- btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
- if (collisionPair)
- {
- if (collisionPair->m_algorithm)
- {
- manifoldArray.resize(0);
- collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
- for (int j=0;j<manifoldArray.size();j++)
- {
- btPersistentManifold* manifold = manifoldArray[j];
- if (manifold->getNumContacts()>0)
- return false;
- }
- }
- }
-#endif
- return true;
- }
-
- return false;
- }
-};
-
-///internal debugging variable. this value shouldn't be too high
-int gNumClampedCcdMotions = 0;
-
-void btDiscreteDynamicsWorld::createPredictiveContactsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
-{
- btTransform predictedTrans;
- for (int i = 0; i < numBodies; i++)
- {
- btRigidBody* body = bodies[i];
- body->setHitFraction(1.f);
-
- if (body->isActive() && (!body->isStaticOrKinematicObject()))
- {
- body->predictIntegratedTransform(timeStep, predictedTrans);
-
- btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
-
- if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
- {
- BT_PROFILE("predictive convexSweepTest");
- if (body->getCollisionShape()->isConvex())
- {
- gNumClampedCcdMotions++;
-#ifdef PREDICTIVE_CONTACT_USE_STATIC_ONLY
- class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
- {
- public:
- StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
- {
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if (!otherObj->isStaticOrKinematicObject())
- return false;
- return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
- }
- };
-
- StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
-#else
- btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
-#endif
- //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
-
- sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
- btTransform modifiedPredictedTrans = predictedTrans;
- modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
-
- convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
- if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
- {
- btVector3 distVec = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()) * sweepResults.m_closestHitFraction;
- btScalar distance = distVec.dot(-sweepResults.m_hitNormalWorld);
-
- btPersistentManifold* manifold = m_dispatcher1->getNewManifold(body, sweepResults.m_hitCollisionObject);
- btMutexLock(&m_predictiveManifoldsMutex);
- m_predictiveManifolds.push_back(manifold);
- btMutexUnlock(&m_predictiveManifoldsMutex);
-
- btVector3 worldPointB = body->getWorldTransform().getOrigin() + distVec;
- btVector3 localPointB = sweepResults.m_hitCollisionObject->getWorldTransform().inverse() * worldPointB;
-
- btManifoldPoint newPoint(btVector3(0, 0, 0), localPointB, sweepResults.m_hitNormalWorld, distance);
-
- bool isPredictive = true;
- int index = manifold->addManifoldPoint(newPoint, isPredictive);
- btManifoldPoint& pt = manifold->getContactPoint(index);
- pt.m_combinedRestitution = 0;
- pt.m_combinedFriction = gCalculateCombinedFrictionCallback(body, sweepResults.m_hitCollisionObject);
- pt.m_positionWorldOnA = body->getWorldTransform().getOrigin();
- pt.m_positionWorldOnB = worldPointB;
- }
- }
- }
- }
- }
-}
-
-void btDiscreteDynamicsWorld::releasePredictiveContacts()
-{
- BT_PROFILE("release predictive contact manifolds");
-
- for (int i = 0; i < m_predictiveManifolds.size(); i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
- this->m_dispatcher1->releaseManifold(manifold);
- }
- m_predictiveManifolds.clear();
-}
-
-void btDiscreteDynamicsWorld::createPredictiveContacts(btScalar timeStep)
-{
- BT_PROFILE("createPredictiveContacts");
- releasePredictiveContacts();
- if (m_nonStaticRigidBodies.size() > 0)
- {
- createPredictiveContactsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
- }
-}
-
-void btDiscreteDynamicsWorld::integrateTransformsInternal(btRigidBody** bodies, int numBodies, btScalar timeStep)
-{
- btTransform predictedTrans;
- for (int i = 0; i < numBodies; i++)
- {
- btRigidBody* body = bodies[i];
- body->setHitFraction(1.f);
-
- if (body->isActive() && (!body->isStaticOrKinematicObject()))
- {
- body->predictIntegratedTransform(timeStep, predictedTrans);
-
- btScalar squareMotion = (predictedTrans.getOrigin() - body->getWorldTransform().getOrigin()).length2();
-
- if (getDispatchInfo().m_useContinuous && body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
- {
- BT_PROFILE("CCD motion clamping");
- if (body->getCollisionShape()->isConvex())
- {
- gNumClampedCcdMotions++;
-#ifdef USE_STATIC_ONLY
- class StaticOnlyCallback : public btClosestNotMeConvexResultCallback
- {
- public:
- StaticOnlyCallback(btCollisionObject* me, const btVector3& fromA, const btVector3& toA, btOverlappingPairCache* pairCache, btDispatcher* dispatcher) : btClosestNotMeConvexResultCallback(me, fromA, toA, pairCache, dispatcher)
- {
- }
-
- virtual bool needsCollision(btBroadphaseProxy* proxy0) const
- {
- btCollisionObject* otherObj = (btCollisionObject*)proxy0->m_clientObject;
- if (!otherObj->isStaticOrKinematicObject())
- return false;
- return btClosestNotMeConvexResultCallback::needsCollision(proxy0);
- }
- };
-
- StaticOnlyCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
-#else
- btClosestNotMeConvexResultCallback sweepResults(body, body->getWorldTransform().getOrigin(), predictedTrans.getOrigin(), getBroadphase()->getOverlappingPairCache(), getDispatcher());
-#endif
- //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- btSphereShape tmpSphere(body->getCcdSweptSphereRadius()); //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
- sweepResults.m_allowedPenetration = getDispatchInfo().m_allowedCcdPenetration;
-
- sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
- sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
- btTransform modifiedPredictedTrans = predictedTrans;
- modifiedPredictedTrans.setBasis(body->getWorldTransform().getBasis());
-
- convexSweepTest(&tmpSphere, body->getWorldTransform(), modifiedPredictedTrans, sweepResults);
- if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
- {
- //printf("clamped integration to hit fraction = %f\n",fraction);
- body->setHitFraction(sweepResults.m_closestHitFraction);
- body->predictIntegratedTransform(timeStep * body->getHitFraction(), predictedTrans);
- body->setHitFraction(0.f);
- body->proceedToTransform(predictedTrans);
-
-#if 0
- btVector3 linVel = body->getLinearVelocity();
-
- btScalar maxSpeed = body->getCcdMotionThreshold()/getSolverInfo().m_timeStep;
- btScalar maxSpeedSqr = maxSpeed*maxSpeed;
- if (linVel.length2()>maxSpeedSqr)
- {
- linVel.normalize();
- linVel*= maxSpeed;
- body->setLinearVelocity(linVel);
- btScalar ms2 = body->getLinearVelocity().length2();
- body->predictIntegratedTransform(timeStep, predictedTrans);
-
- btScalar sm2 = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
- btScalar smt = body->getCcdSquareMotionThreshold();
- printf("sm2=%f\n",sm2);
- }
-#else
-
- //don't apply the collision response right now, it will happen next frame
- //if you really need to, you can uncomment next 3 lines. Note that is uses zero restitution.
- //btScalar appliedImpulse = 0.f;
- //btScalar depth = 0.f;
- //appliedImpulse = resolveSingleCollision(body,(btCollisionObject*)sweepResults.m_hitCollisionObject,sweepResults.m_hitPointWorld,sweepResults.m_hitNormalWorld,getSolverInfo(), depth);
-
-#endif
-
- continue;
- }
- }
- }
-
- body->proceedToTransform(predictedTrans);
- }
- }
-}
-
-void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
-{
- BT_PROFILE("integrateTransforms");
- if (m_nonStaticRigidBodies.size() > 0)
- {
- integrateTransformsInternal(&m_nonStaticRigidBodies[0], m_nonStaticRigidBodies.size(), timeStep);
- }
-
- ///this should probably be switched on by default, but it is not well tested yet
- if (m_applySpeculativeContactRestitution)
- {
- BT_PROFILE("apply speculative contact restitution");
- for (int i = 0; i < m_predictiveManifolds.size(); i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
- btRigidBody* body0 = btRigidBody::upcast((btCollisionObject*)manifold->getBody0());
- btRigidBody* body1 = btRigidBody::upcast((btCollisionObject*)manifold->getBody1());
-
- for (int p = 0; p < manifold->getNumContacts(); p++)
- {
- const btManifoldPoint& pt = manifold->getContactPoint(p);
- btScalar combinedRestitution = gCalculateCombinedRestitutionCallback(body0, body1);
-
- if (combinedRestitution > 0 && pt.m_appliedImpulse != 0.f)
- //if (pt.getDistance()>0 && combinedRestitution>0 && pt.m_appliedImpulse != 0.f)
- {
- btVector3 imp = -pt.m_normalWorldOnB * pt.m_appliedImpulse * combinedRestitution;
-
- const btVector3& pos1 = pt.getPositionWorldOnA();
- const btVector3& pos2 = pt.getPositionWorldOnB();
-
- btVector3 rel_pos0 = pos1 - body0->getWorldTransform().getOrigin();
- btVector3 rel_pos1 = pos2 - body1->getWorldTransform().getOrigin();
-
- if (body0)
- body0->applyImpulse(imp, rel_pos0);
- if (body1)
- body1->applyImpulse(-imp, rel_pos1);
- }
- }
- }
- }
-}
-
-void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- BT_PROFILE("predictUnconstraintMotion");
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (!body->isStaticOrKinematicObject())
- {
- //don't integrate/update velocities here, it happens in the constraint solver
-
- body->applyDamping(timeStep);
-
- body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
- }
- }
-}
-
-void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
-{
- (void)timeStep;
-
-#ifndef BT_NO_PROFILE
- CProfileManager::Reset();
-#endif //BT_NO_PROFILE
-}
-
-void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
-{
- bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
- bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
- btScalar dbgDrawSize = constraint->getDbgDrawSize();
- if (dbgDrawSize <= btScalar(0.f))
- {
- return;
- }
-
- switch (constraint->getConstraintType())
- {
- case POINT2POINT_CONSTRAINT_TYPE:
- {
- btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
- btTransform tr;
- tr.setIdentity();
- btVector3 pivot = p2pC->getPivotInA();
- pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- // that ideally should draw the same frame
- pivot = p2pC->getPivotInB();
- pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
- tr.setOrigin(pivot);
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- }
- break;
- case HINGE_CONSTRAINT_TYPE:
- {
- btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
- btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- btScalar minAng = pHinge->getLowerLimit();
- btScalar maxAng = pHinge->getUpperLimit();
- if (minAng == maxAng)
- {
- break;
- }
- bool drawSect = true;
- if (!pHinge->hasLimit())
- {
- minAng = btScalar(0.f);
- maxAng = SIMD_2_PI;
- drawSect = false;
- }
- if (drawLimits)
- {
- btVector3& center = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0, 0, 0), drawSect);
- }
- }
- break;
- case CONETWIST_CONSTRAINT_TYPE:
- {
- btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
- btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- //const btScalar length = btScalar(5);
- const btScalar length = dbgDrawSize;
- static int nSegments = 8 * 4;
- btScalar fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)(nSegments - 1) / btScalar(nSegments);
- btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
- pPrev = tr * pPrev;
- for (int i = 0; i < nSegments; i++)
- {
- fAngleInRadians = btScalar(2. * 3.1415926) * (btScalar)i / btScalar(nSegments);
- btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
- pCur = tr * pCur;
- getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0, 0, 0));
-
- if (i % (nSegments / 8) == 0)
- getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0, 0, 0));
-
- pPrev = pCur;
- }
- btScalar tws = pCT->getTwistSpan();
- btScalar twa = pCT->getTwistAngle();
- bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
- if (useFrameB)
- {
- tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
- }
- else
- {
- tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
- }
- btVector3 pivot = tr.getOrigin();
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis1 = tr.getBasis().getColumn(1);
- getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa - tws, -twa + tws, btVector3(0, 0, 0), true);
- }
- }
- break;
- case D6_SPRING_CONSTRAINT_TYPE:
- case D6_CONSTRAINT_TYPE:
- {
- btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
- btTransform tr = p6DOF->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = p6DOF->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- tr = p6DOF->getCalculatedTransformA();
- const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
- btVector3 up = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
- btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
- btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
- btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
- getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
- axis = tr.getBasis().getColumn(1);
- btScalar ay = p6DOF->getAngle(1);
- btScalar az = p6DOF->getAngle(2);
- btScalar cy = btCos(ay);
- btScalar sy = btSin(ay);
- btScalar cz = btCos(az);
- btScalar sz = btSin(az);
- btVector3 ref;
- ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
- ref[1] = -sz * axis[0] + cz * axis[1];
- ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
- tr = p6DOF->getCalculatedTransformB();
- btVector3 normal = -tr.getBasis().getColumn(0);
- btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
- btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
- if (minFi > maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
- }
- else if (minFi < maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
- }
- tr = p6DOF->getCalculatedTransformA();
- btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
- btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
- getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
- }
- }
- break;
- ///note: the code for D6_SPRING_2_CONSTRAINT_TYPE is identical to D6_CONSTRAINT_TYPE, the D6_CONSTRAINT_TYPE+D6_SPRING_CONSTRAINT_TYPE will likely become obsolete/deprecated at some stage
- case D6_SPRING_2_CONSTRAINT_TYPE:
- {
- {
- btGeneric6DofSpring2Constraint* p6DOF = (btGeneric6DofSpring2Constraint*)constraint;
- btTransform tr = p6DOF->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = p6DOF->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- tr = p6DOF->getCalculatedTransformA();
- const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
- btVector3 up = tr.getBasis().getColumn(2);
- btVector3 axis = tr.getBasis().getColumn(0);
- btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
- btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
- if (minTh <= maxTh)
- {
- btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
- btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
- getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0, 0, 0));
- }
- axis = tr.getBasis().getColumn(1);
- btScalar ay = p6DOF->getAngle(1);
- btScalar az = p6DOF->getAngle(2);
- btScalar cy = btCos(ay);
- btScalar sy = btSin(ay);
- btScalar cz = btCos(az);
- btScalar sz = btSin(az);
- btVector3 ref;
- ref[0] = cy * cz * axis[0] + cy * sz * axis[1] - sy * axis[2];
- ref[1] = -sz * axis[0] + cz * axis[1];
- ref[2] = cz * sy * axis[0] + sz * sy * axis[1] + cy * axis[2];
- tr = p6DOF->getCalculatedTransformB();
- btVector3 normal = -tr.getBasis().getColumn(0);
- btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
- btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
- if (minFi > maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0, 0, 0), false);
- }
- else if (minFi < maxFi)
- {
- getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0, 0, 0), true);
- }
- tr = p6DOF->getCalculatedTransformA();
- btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
- btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
- getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0, 0, 0));
- }
- }
- break;
- }
- case SLIDER_CONSTRAINT_TYPE:
- {
- btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
- btTransform tr = pSlider->getCalculatedTransformA();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- tr = pSlider->getCalculatedTransformB();
- if (drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
- if (drawLimits)
- {
- btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
- btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
- btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
- getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
- btVector3 normal = tr.getBasis().getColumn(0);
- btVector3 axis = tr.getBasis().getColumn(1);
- btScalar a_min = pSlider->getLowerAngLimit();
- btScalar a_max = pSlider->getUpperAngLimit();
- const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
- getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0, 0, 0), true);
- }
- }
- break;
- default:
- break;
- }
- return;
-}
-
-void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
-{
- if (m_ownsConstraintSolver)
- {
- btAlignedFree(m_constraintSolver);
- }
- m_ownsConstraintSolver = false;
- m_constraintSolver = solver;
- m_solverIslandCallback->m_solver = solver;
-}
-
-btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
-{
- return m_constraintSolver;
-}
-
-int btDiscreteDynamicsWorld::getNumConstraints() const
-{
- return int(m_constraints.size());
-}
-btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
-{
- return m_constraints[index];
-}
-const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
-{
- return m_constraints[index];
-}
-
-void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
-{
- int i;
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
- {
- int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, colObj);
- }
- }
-
- for (i = 0; i < m_constraints.size(); i++)
- {
- btTypedConstraint* constraint = m_constraints[i];
- int size = constraint->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(size, 1);
- const char* structType = constraint->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_CONSTRAINT_CODE, constraint);
- }
-}
-
-void btDiscreteDynamicsWorld::serializeDynamicsWorldInfo(btSerializer* serializer)
-{
-#ifdef BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldDoubleData);
- btChunk* chunk = serializer->allocate(len, 1);
- btDynamicsWorldDoubleData* worldInfo = (btDynamicsWorldDoubleData*)chunk->m_oldPtr;
-#else //BT_USE_DOUBLE_PRECISION
- int len = sizeof(btDynamicsWorldFloatData);
- btChunk* chunk = serializer->allocate(len, 1);
- btDynamicsWorldFloatData* worldInfo = (btDynamicsWorldFloatData*)chunk->m_oldPtr;
-#endif //BT_USE_DOUBLE_PRECISION
-
- memset(worldInfo, 0x00, len);
-
- m_gravity.serialize(worldInfo->m_gravity);
- worldInfo->m_solverInfo.m_tau = getSolverInfo().m_tau;
- worldInfo->m_solverInfo.m_damping = getSolverInfo().m_damping;
- worldInfo->m_solverInfo.m_friction = getSolverInfo().m_friction;
- worldInfo->m_solverInfo.m_timeStep = getSolverInfo().m_timeStep;
-
- worldInfo->m_solverInfo.m_restitution = getSolverInfo().m_restitution;
- worldInfo->m_solverInfo.m_maxErrorReduction = getSolverInfo().m_maxErrorReduction;
- worldInfo->m_solverInfo.m_sor = getSolverInfo().m_sor;
- worldInfo->m_solverInfo.m_erp = getSolverInfo().m_erp;
-
- worldInfo->m_solverInfo.m_erp2 = getSolverInfo().m_erp2;
- worldInfo->m_solverInfo.m_globalCfm = getSolverInfo().m_globalCfm;
- worldInfo->m_solverInfo.m_splitImpulsePenetrationThreshold = getSolverInfo().m_splitImpulsePenetrationThreshold;
- worldInfo->m_solverInfo.m_splitImpulseTurnErp = getSolverInfo().m_splitImpulseTurnErp;
-
- worldInfo->m_solverInfo.m_linearSlop = getSolverInfo().m_linearSlop;
- worldInfo->m_solverInfo.m_warmstartingFactor = getSolverInfo().m_warmstartingFactor;
- worldInfo->m_solverInfo.m_maxGyroscopicForce = getSolverInfo().m_maxGyroscopicForce;
- worldInfo->m_solverInfo.m_singleAxisRollingFrictionThreshold = getSolverInfo().m_singleAxisRollingFrictionThreshold;
-
- worldInfo->m_solverInfo.m_numIterations = getSolverInfo().m_numIterations;
- worldInfo->m_solverInfo.m_solverMode = getSolverInfo().m_solverMode;
- worldInfo->m_solverInfo.m_restingContactRestitutionThreshold = getSolverInfo().m_restingContactRestitutionThreshold;
- worldInfo->m_solverInfo.m_minimumSolverBatchSize = getSolverInfo().m_minimumSolverBatchSize;
-
- worldInfo->m_solverInfo.m_splitImpulse = getSolverInfo().m_splitImpulse;
-
-
-#ifdef BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldDoubleData";
-#else //BT_USE_DOUBLE_PRECISION
- const char* structType = "btDynamicsWorldFloatData";
-#endif //BT_USE_DOUBLE_PRECISION
- serializer->finalizeChunk(chunk, structType, BT_DYNAMICSWORLD_CODE, worldInfo);
-}
-
-void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
-{
- serializer->startSerialization();
-
- serializeDynamicsWorldInfo(serializer);
-
- serializeCollisionObjects(serializer);
-
- serializeRigidBodies(serializer);
-
- serializeContactManifolds(serializer);
-
- serializer->finishSerialization();
-}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
deleted file mode 100644
index 73607c61fd..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
-#define BT_DISCRETE_DYNAMICS_WORLD_H
-
-#include "btDynamicsWorld.h"
-class btDispatcher;
-class btOverlappingPairCache;
-class btConstraintSolver;
-class btSimulationIslandManager;
-class btTypedConstraint;
-class btActionInterface;
-class btPersistentManifold;
-class btIDebugDraw;
-
-struct InplaceSolverIslandCallback;
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btThreads.h"
-
-///btDiscreteDynamicsWorld provides discrete rigid body simulation
-///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
-ATTRIBUTE_ALIGNED16(class)
-btDiscreteDynamicsWorld : public btDynamicsWorld
-{
-protected:
- btAlignedObjectArray<btTypedConstraint*> m_sortedConstraints;
- InplaceSolverIslandCallback* m_solverIslandCallback;
-
- btConstraintSolver* m_constraintSolver;
-
- btSimulationIslandManager* m_islandManager;
-
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
-
- btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
-
- btVector3 m_gravity;
-
- //for variable timesteps
- btScalar m_localTime;
- btScalar m_fixedTimeStep;
- //for variable timesteps
-
- bool m_ownsIslandManager;
- bool m_ownsConstraintSolver;
- bool m_synchronizeAllMotionStates;
- bool m_applySpeculativeContactRestitution;
-
- btAlignedObjectArray<btActionInterface*> m_actions;
-
- int m_profileTimings;
-
- bool m_latencyMotionStateInterpolation;
-
- btAlignedObjectArray<btPersistentManifold*> m_predictiveManifolds;
- btSpinMutex m_predictiveManifoldsMutex; // used to synchronize threads creating predictive contacts
-
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- void integrateTransformsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep); // can be called in parallel
- virtual void integrateTransforms(btScalar timeStep);
-
- virtual void calculateSimulationIslands();
-
-
-
- virtual void updateActivationState(btScalar timeStep);
-
- void updateActions(btScalar timeStep);
-
- void startProfiling(btScalar timeStep);
-
- virtual void internalSingleStepSimulation(btScalar timeStep);
-
- void releasePredictiveContacts();
- void createPredictiveContactsInternal(btRigidBody * *bodies, int numBodies, btScalar timeStep); // can be called in parallel
- virtual void createPredictiveContacts(btScalar timeStep);
-
- virtual void saveKinematicState(btScalar timeStep);
-
- void serializeRigidBodies(btSerializer * serializer);
-
- void serializeDynamicsWorldInfo(btSerializer * serializer);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
- btDiscreteDynamicsWorld(btDispatcher * dispatcher, btBroadphaseInterface * pairCache, btConstraintSolver * constraintSolver, btCollisionConfiguration * collisionConfiguration);
-
- virtual ~btDiscreteDynamicsWorld();
-
- ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
- virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
-
- virtual void solveConstraints(btContactSolverInfo & solverInfo);
-
- virtual void synchronizeMotionStates();
-
- ///this can be useful to synchronize a single rigid body -> graphics object
- void synchronizeSingleMotionState(btRigidBody * body);
-
- virtual void addConstraint(btTypedConstraint * constraint, bool disableCollisionsBetweenLinkedBodies = false);
-
- virtual void removeConstraint(btTypedConstraint * constraint);
-
- virtual void addAction(btActionInterface*);
-
- virtual void removeAction(btActionInterface*);
-
- btSimulationIslandManager* getSimulationIslandManager()
- {
- return m_islandManager;
- }
-
- const btSimulationIslandManager* getSimulationIslandManager() const
- {
- return m_islandManager;
- }
-
- btCollisionWorld* getCollisionWorld()
- {
- return this;
- }
-
- virtual void setGravity(const btVector3& gravity);
-
- virtual btVector3 getGravity() const;
-
- virtual void addCollisionObject(btCollisionObject * collisionObject, int collisionFilterGroup = btBroadphaseProxy::StaticFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
-
- virtual void addRigidBody(btRigidBody * body);
-
- virtual void addRigidBody(btRigidBody * body, int group, int mask);
-
- virtual void removeRigidBody(btRigidBody * body);
-
- ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject * collisionObject);
-
- virtual void debugDrawConstraint(btTypedConstraint * constraint);
-
- virtual void debugDrawWorld();
-
- virtual void setConstraintSolver(btConstraintSolver * solver);
-
- virtual btConstraintSolver* getConstraintSolver();
-
- virtual int getNumConstraints() const;
-
- virtual btTypedConstraint* getConstraint(int index);
-
- virtual const btTypedConstraint* getConstraint(int index) const;
-
- virtual btDynamicsWorldType getWorldType() const
- {
- return BT_DISCRETE_DYNAMICS_WORLD;
- }
-
- ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
- virtual void clearForces();
-
- ///apply gravity, call this once per timestep
- virtual void applyGravity();
-
- virtual void setNumTasks(int numTasks)
- {
- (void)numTasks;
- }
-
- ///obsolete, use updateActions instead
- virtual void updateVehicles(btScalar timeStep)
- {
- updateActions(timeStep);
- }
-
- ///obsolete, use addAction instead
- virtual void addVehicle(btActionInterface * vehicle);
- ///obsolete, use removeAction instead
- virtual void removeVehicle(btActionInterface * vehicle);
- ///obsolete, use addAction instead
- virtual void addCharacter(btActionInterface * character);
- ///obsolete, use removeAction instead
- virtual void removeCharacter(btActionInterface * character);
-
- void setSynchronizeAllMotionStates(bool synchronizeAll)
- {
- m_synchronizeAllMotionStates = synchronizeAll;
- }
- bool getSynchronizeAllMotionStates() const
- {
- return m_synchronizeAllMotionStates;
- }
-
- void setApplySpeculativeContactRestitution(bool enable)
- {
- m_applySpeculativeContactRestitution = enable;
- }
-
- bool getApplySpeculativeContactRestitution() const
- {
- return m_applySpeculativeContactRestitution;
- }
-
- ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
- virtual void serialize(btSerializer * serializer);
-
- ///Interpolate motion state between previous and current transform, instead of current and next transform.
- ///This can relieve discontinuities in the rendering, due to penetrations
- void setLatencyMotionStateInterpolation(bool latencyInterpolation)
- {
- m_latencyMotionStateInterpolation = latencyInterpolation;
- }
- bool getLatencyMotionStateInterpolation() const
- {
- return m_latencyMotionStateInterpolation;
- }
-
- btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies()
- {
- return m_nonStaticRigidBodies;
- }
-
- const btAlignedObjectArray<btRigidBody*>& getNonStaticRigidBodies() const
- {
- return m_nonStaticRigidBodies;
- }
-};
-
-#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
deleted file mode 100644
index 8207b47135..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btDiscreteDynamicsWorldMt.h"
-
-//collision detection
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "btSimulationIslandManagerMt.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btQuickprof.h"
-
-//rigidbody & constraints
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
-#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-
-#include "BulletDynamics/Dynamics/btActionInterface.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btMotionState.h"
-
-#include "LinearMath/btSerializer.h"
-
-///
-/// btConstraintSolverPoolMt
-///
-
-btConstraintSolverPoolMt::ThreadSolver* btConstraintSolverPoolMt::getAndLockThreadSolver()
-{
- int i = 0;
-#if BT_THREADSAFE
- i = btGetCurrentThreadIndex() % m_solvers.size();
-#endif // #if BT_THREADSAFE
- while (true)
- {
- ThreadSolver& solver = m_solvers[i];
- if (solver.mutex.tryLock())
- {
- return &solver;
- }
- // failed, try the next one
- i = (i + 1) % m_solvers.size();
- }
- return NULL;
-}
-
-void btConstraintSolverPoolMt::init(btConstraintSolver** solvers, int numSolvers)
-{
- m_solverType = BT_SEQUENTIAL_IMPULSE_SOLVER;
- m_solvers.resize(numSolvers);
- for (int i = 0; i < numSolvers; ++i)
- {
- m_solvers[i].solver = solvers[i];
- }
- if (numSolvers > 0)
- {
- m_solverType = solvers[0]->getSolverType();
- }
-}
-
-// create the solvers for me
-btConstraintSolverPoolMt::btConstraintSolverPoolMt(int numSolvers)
-{
- btAlignedObjectArray<btConstraintSolver*> solvers;
- solvers.reserve(numSolvers);
- for (int i = 0; i < numSolvers; ++i)
- {
- btConstraintSolver* solver = new btSequentialImpulseConstraintSolver();
- solvers.push_back(solver);
- }
- init(&solvers[0], numSolvers);
-}
-
-// pass in fully constructed solvers (destructor will delete them)
-btConstraintSolverPoolMt::btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers)
-{
- init(solvers, numSolvers);
-}
-
-btConstraintSolverPoolMt::~btConstraintSolverPoolMt()
-{
- // delete all solvers
- for (int i = 0; i < m_solvers.size(); ++i)
- {
- ThreadSolver& solver = m_solvers[i];
- delete solver.solver;
- solver.solver = NULL;
- }
-}
-
-///solve a group of constraints
-btScalar btConstraintSolverPoolMt::solveGroup(btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifolds,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& info,
- btIDebugDraw* debugDrawer,
- btDispatcher* dispatcher)
-{
- ThreadSolver* ts = getAndLockThreadSolver();
- ts->solver->solveGroup(bodies, numBodies, manifolds, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
- ts->mutex.unlock();
- return 0.0f;
-}
-
-void btConstraintSolverPoolMt::reset()
-{
- for (int i = 0; i < m_solvers.size(); ++i)
- {
- ThreadSolver& solver = m_solvers[i];
- solver.mutex.lock();
- solver.solver->reset();
- solver.mutex.unlock();
- }
-}
-
-///
-/// btDiscreteDynamicsWorldMt
-///
-
-btDiscreteDynamicsWorldMt::btDiscreteDynamicsWorldMt(btDispatcher* dispatcher,
- btBroadphaseInterface* pairCache,
- btConstraintSolverPoolMt* solverPool,
- btConstraintSolver* constraintSolverMt,
- btCollisionConfiguration* collisionConfiguration)
- : btDiscreteDynamicsWorld(dispatcher, pairCache, solverPool, collisionConfiguration)
-{
- if (m_ownsIslandManager)
- {
- m_islandManager->~btSimulationIslandManager();
- btAlignedFree(m_islandManager);
- }
- {
- void* mem = btAlignedAlloc(sizeof(btSimulationIslandManagerMt), 16);
- btSimulationIslandManagerMt* im = new (mem) btSimulationIslandManagerMt();
- im->setMinimumSolverBatchSize(m_solverInfo.m_minimumSolverBatchSize);
- m_islandManager = im;
- }
- m_constraintSolverMt = constraintSolverMt;
-}
-
-btDiscreteDynamicsWorldMt::~btDiscreteDynamicsWorldMt()
-{
-}
-
-void btDiscreteDynamicsWorldMt::solveConstraints(btContactSolverInfo& solverInfo)
-{
- BT_PROFILE("solveConstraints");
-
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
-
- /// solve all the constraints for this island
- btSimulationIslandManagerMt* im = static_cast<btSimulationIslandManagerMt*>(m_islandManager);
- btSimulationIslandManagerMt::SolverParams solverParams;
- solverParams.m_solverPool = m_constraintSolver;
- solverParams.m_solverMt = m_constraintSolverMt;
- solverParams.m_solverInfo = &solverInfo;
- solverParams.m_debugDrawer = m_debugDrawer;
- solverParams.m_dispatcher = getCollisionWorld()->getDispatcher();
- im->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_constraints, solverParams);
-
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
-}
-
-struct UpdaterUnconstrainedMotion : public btIParallelForBody
-{
- btScalar timeStep;
- btRigidBody** rigidBodies;
-
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- for (int i = iBegin; i < iEnd; ++i)
- {
- btRigidBody* body = rigidBodies[i];
- if (!body->isStaticOrKinematicObject())
- {
- //don't integrate/update velocities here, it happens in the constraint solver
- body->applyDamping(timeStep);
- body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
- }
- }
- }
-};
-
-void btDiscreteDynamicsWorldMt::predictUnconstraintMotion(btScalar timeStep)
-{
- BT_PROFILE("predictUnconstraintMotion");
- if (m_nonStaticRigidBodies.size() > 0)
- {
- UpdaterUnconstrainedMotion update;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[0];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
- }
-}
-
-void btDiscreteDynamicsWorldMt::createPredictiveContacts(btScalar timeStep)
-{
- BT_PROFILE("createPredictiveContacts");
- releasePredictiveContacts();
- if (m_nonStaticRigidBodies.size() > 0)
- {
- UpdaterCreatePredictiveContacts update;
- update.world = this;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[0];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
- }
-}
-
-void btDiscreteDynamicsWorldMt::integrateTransforms(btScalar timeStep)
-{
- BT_PROFILE("integrateTransforms");
- if (m_nonStaticRigidBodies.size() > 0)
- {
- UpdaterIntegrateTransforms update;
- update.world = this;
- update.timeStep = timeStep;
- update.rigidBodies = &m_nonStaticRigidBodies[0];
- int grainSize = 50; // num of iterations per task for task scheduler
- btParallelFor(0, m_nonStaticRigidBodies.size(), grainSize, update);
- }
-}
-
-int btDiscreteDynamicsWorldMt::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
-{
- int numSubSteps = btDiscreteDynamicsWorld::stepSimulation(timeStep, maxSubSteps, fixedTimeStep);
- if (btITaskScheduler* scheduler = btGetTaskScheduler())
- {
- // tell Bullet's threads to sleep, so other threads can run
- scheduler->sleepWorkerThreadsHint();
- }
- return numSubSteps;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
deleted file mode 100644
index dccf35d7a7..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DISCRETE_DYNAMICS_WORLD_MT_H
-#define BT_DISCRETE_DYNAMICS_WORLD_MT_H
-
-#include "btDiscreteDynamicsWorld.h"
-#include "btSimulationIslandManagerMt.h"
-#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h"
-
-///
-/// btConstraintSolverPoolMt - masquerades as a constraint solver, but really it is a threadsafe pool of them.
-///
-/// Each solver in the pool is protected by a mutex. When solveGroup is called from a thread,
-/// the pool looks for a solver that isn't being used by another thread, locks it, and dispatches the
-/// call to the solver.
-/// So long as there are at least as many solvers as there are hardware threads, it should never need to
-/// spin wait.
-///
-class btConstraintSolverPoolMt : public btConstraintSolver
-{
-public:
- // create the solvers for me
- explicit btConstraintSolverPoolMt(int numSolvers);
-
- // pass in fully constructed solvers (destructor will delete them)
- btConstraintSolverPoolMt(btConstraintSolver** solvers, int numSolvers);
-
- virtual ~btConstraintSolverPoolMt();
-
- ///solve a group of constraints
- virtual btScalar solveGroup(btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifolds,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& info,
- btIDebugDraw* debugDrawer,
- btDispatcher* dispatcher) BT_OVERRIDE;
-
- virtual void reset() BT_OVERRIDE;
- virtual btConstraintSolverType getSolverType() const BT_OVERRIDE { return m_solverType; }
-
-private:
- const static size_t kCacheLineSize = 128;
- struct ThreadSolver
- {
- btConstraintSolver* solver;
- btSpinMutex mutex;
- char _cachelinePadding[kCacheLineSize - sizeof(btSpinMutex) - sizeof(void*)]; // keep mutexes from sharing a cache line
- };
- btAlignedObjectArray<ThreadSolver> m_solvers;
- btConstraintSolverType m_solverType;
-
- ThreadSolver* getAndLockThreadSolver();
- void init(btConstraintSolver** solvers, int numSolvers);
-};
-
-///
-/// btDiscreteDynamicsWorldMt -- a version of DiscreteDynamicsWorld with some minor changes to support
-/// solving simulation islands on multiple threads.
-///
-/// Should function exactly like btDiscreteDynamicsWorld.
-/// Also 3 methods that iterate over all of the rigidbodies can run in parallel:
-/// - predictUnconstraintMotion
-/// - integrateTransforms
-/// - createPredictiveContacts
-///
-ATTRIBUTE_ALIGNED16(class)
-btDiscreteDynamicsWorldMt : public btDiscreteDynamicsWorld
-{
-protected:
- btConstraintSolver* m_constraintSolverMt;
-
- virtual void solveConstraints(btContactSolverInfo & solverInfo) BT_OVERRIDE;
-
- virtual void predictUnconstraintMotion(btScalar timeStep) BT_OVERRIDE;
-
- struct UpdaterCreatePredictiveContacts : public btIParallelForBody
- {
- btScalar timeStep;
- btRigidBody** rigidBodies;
- btDiscreteDynamicsWorldMt* world;
-
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- world->createPredictiveContactsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
- }
- };
- virtual void createPredictiveContacts(btScalar timeStep) BT_OVERRIDE;
-
- struct UpdaterIntegrateTransforms : public btIParallelForBody
- {
- btScalar timeStep;
- btRigidBody** rigidBodies;
- btDiscreteDynamicsWorldMt* world;
-
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- world->integrateTransformsInternal(&rigidBodies[iBegin], iEnd - iBegin, timeStep);
- }
- };
- virtual void integrateTransforms(btScalar timeStep) BT_OVERRIDE;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btDiscreteDynamicsWorldMt(btDispatcher * dispatcher,
- btBroadphaseInterface * pairCache,
- btConstraintSolverPoolMt * solverPool, // Note this should be a solver-pool for multi-threading
- btConstraintSolver * constraintSolverMt, // single multi-threaded solver for large islands (or NULL)
- btCollisionConfiguration * collisionConfiguration);
- virtual ~btDiscreteDynamicsWorldMt();
-
- virtual int stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep) BT_OVERRIDE;
-};
-
-#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
deleted file mode 100644
index 3c55234a8a..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btDynamicsWorld.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_DYNAMICS_WORLD_H
-#define BT_DYNAMICS_WORLD_H
-
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-
-class btTypedConstraint;
-class btActionInterface;
-class btConstraintSolver;
-class btDynamicsWorld;
-
-/// Type for the callback for each tick
-typedef void (*btInternalTickCallback)(btDynamicsWorld* world, btScalar timeStep);
-
-enum btDynamicsWorldType
-{
- BT_SIMPLE_DYNAMICS_WORLD = 1,
- BT_DISCRETE_DYNAMICS_WORLD = 2,
- BT_CONTINUOUS_DYNAMICS_WORLD = 3,
- BT_SOFT_RIGID_DYNAMICS_WORLD = 4,
- BT_GPU_DYNAMICS_WORLD = 5,
- BT_SOFT_MULTIBODY_DYNAMICS_WORLD = 6,
- BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD = 7
-};
-
-///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
-class btDynamicsWorld : public btCollisionWorld
-{
-protected:
- btInternalTickCallback m_internalTickCallback;
- btInternalTickCallback m_internalPreTickCallback;
- void* m_worldUserInfo;
-
- btContactSolverInfo m_solverInfo;
-
-public:
- btDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* broadphase, btCollisionConfiguration* collisionConfiguration)
- : btCollisionWorld(dispatcher, broadphase, collisionConfiguration), m_internalTickCallback(0), m_internalPreTickCallback(0), m_worldUserInfo(0)
- {
- }
-
- virtual ~btDynamicsWorld()
- {
- }
-
- ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
- ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
- ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
- ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
- virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.)) = 0;
-
- virtual void debugDrawWorld() = 0;
-
- virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies = false)
- {
- (void)constraint;
- (void)disableCollisionsBetweenLinkedBodies;
- }
-
- virtual void removeConstraint(btTypedConstraint* constraint) { (void)constraint; }
-
- virtual void addAction(btActionInterface* action) = 0;
-
- virtual void removeAction(btActionInterface* action) = 0;
-
- //once a rigidbody is added to the dynamics world, it will get this gravity assigned
- //existing rigidbodies in the world get gravity assigned too, during this method
- virtual void setGravity(const btVector3& gravity) = 0;
- virtual btVector3 getGravity() const = 0;
-
- virtual void synchronizeMotionStates() = 0;
-
- virtual void addRigidBody(btRigidBody* body) = 0;
-
- virtual void addRigidBody(btRigidBody* body, int group, int mask) = 0;
-
- virtual void removeRigidBody(btRigidBody* body) = 0;
-
- virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
-
- virtual btConstraintSolver* getConstraintSolver() = 0;
-
- virtual int getNumConstraints() const { return 0; }
-
- virtual btTypedConstraint* getConstraint(int index)
- {
- (void)index;
- return 0;
- }
-
- virtual const btTypedConstraint* getConstraint(int index) const
- {
- (void)index;
- return 0;
- }
-
- virtual btDynamicsWorldType getWorldType() const = 0;
-
- virtual void clearForces() = 0;
-
- /// Set the callback for when an internal tick (simulation substep) happens, optional user info
- void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo = 0, bool isPreTick = false)
- {
- if (isPreTick)
- {
- m_internalPreTickCallback = cb;
- }
- else
- {
- m_internalTickCallback = cb;
- }
- m_worldUserInfo = worldUserInfo;
- }
-
- void setWorldUserInfo(void* worldUserInfo)
- {
- m_worldUserInfo = worldUserInfo;
- }
-
- void* getWorldUserInfo() const
- {
- return m_worldUserInfo;
- }
-
- btContactSolverInfo& getSolverInfo()
- {
- return m_solverInfo;
- }
-
- const btContactSolverInfo& getSolverInfo() const
- {
- return m_solverInfo;
- }
-
- ///obsolete, use addAction instead.
- virtual void addVehicle(btActionInterface* vehicle) { (void)vehicle; }
- ///obsolete, use removeAction instead
- virtual void removeVehicle(btActionInterface* vehicle) { (void)vehicle; }
- ///obsolete, use addAction instead.
- virtual void addCharacter(btActionInterface* character) { (void)character; }
- ///obsolete, use removeAction instead
- virtual void removeCharacter(btActionInterface* character) { (void)character; }
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btDynamicsWorldDoubleData
-{
- btContactSolverInfoDoubleData m_solverInfo;
- btVector3DoubleData m_gravity;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btDynamicsWorldFloatData
-{
- btContactSolverInfoFloatData m_solverInfo;
- btVector3FloatData m_gravity;
-};
-
-#endif //BT_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
deleted file mode 100644
index 27fdead761..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btRigidBody.h"
-#include "BulletCollision/CollisionShapes/btConvexShape.h"
-#include "LinearMath/btMinMax.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btMotionState.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "LinearMath/btSerializer.h"
-
-//'temporarily' global variables
-btScalar gDeactivationTime = btScalar(2.);
-bool gDisableDeactivation = false;
-static int uniqueId = 0;
-
-btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
-{
- setupRigidBody(constructionInfo);
-}
-
-btRigidBody::btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia)
-{
- btRigidBodyConstructionInfo cinfo(mass, motionState, collisionShape, localInertia);
- setupRigidBody(cinfo);
-}
-
-void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
-{
- m_internalType = CO_RIGID_BODY;
-
- m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- m_angularFactor.setValue(1, 1, 1);
- m_linearFactor.setValue(1, 1, 1);
- m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
- setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
-
- m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
- m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
- m_optionalMotionState = constructionInfo.m_motionState;
- m_contactSolverType = 0;
- m_frictionSolverType = 0;
- m_additionalDamping = constructionInfo.m_additionalDamping;
- m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
- m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
- m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
- m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
-
- if (m_optionalMotionState)
- {
- m_optionalMotionState->getWorldTransform(m_worldTransform);
- }
- else
- {
- m_worldTransform = constructionInfo.m_startWorldTransform;
- }
-
- m_interpolationWorldTransform = m_worldTransform;
- m_interpolationLinearVelocity.setValue(0, 0, 0);
- m_interpolationAngularVelocity.setValue(0, 0, 0);
-
- //moved to btCollisionObject
- m_friction = constructionInfo.m_friction;
- m_rollingFriction = constructionInfo.m_rollingFriction;
- m_spinningFriction = constructionInfo.m_spinningFriction;
-
- m_restitution = constructionInfo.m_restitution;
-
- setCollisionShape(constructionInfo.m_collisionShape);
- m_debugBodyId = uniqueId++;
-
- setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
- updateInertiaTensor();
-
- m_rigidbodyFlags = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY;
-
- m_deltaLinearVelocity.setZero();
- m_deltaAngularVelocity.setZero();
- m_invMass = m_inverseMass * m_linearFactor;
- m_pushVelocity.setZero();
- m_turnVelocity.setZero();
-}
-
-void btRigidBody::predictIntegratedTransform(btScalar timeStep, btTransform& predictedTransform)
-{
- btTransformUtil::integrateTransform(m_worldTransform, m_linearVelocity, m_angularVelocity, timeStep, predictedTransform);
-}
-
-void btRigidBody::saveKinematicState(btScalar timeStep)
-{
- //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
- if (timeStep != btScalar(0.))
- {
- //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
- if (getMotionState())
- getMotionState()->getWorldTransform(m_worldTransform);
- btVector3 linVel, angVel;
-
- btTransformUtil::calculateVelocity(m_interpolationWorldTransform, m_worldTransform, timeStep, m_linearVelocity, m_angularVelocity);
- m_interpolationLinearVelocity = m_linearVelocity;
- m_interpolationAngularVelocity = m_angularVelocity;
- m_interpolationWorldTransform = m_worldTransform;
- //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
- }
-}
-
-void btRigidBody::getAabb(btVector3& aabbMin, btVector3& aabbMax) const
-{
- getCollisionShape()->getAabb(m_worldTransform, aabbMin, aabbMax);
-}
-
-void btRigidBody::setGravity(const btVector3& acceleration)
-{
- if (m_inverseMass != btScalar(0.0))
- {
- m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
- }
- m_gravity_acceleration = acceleration;
-}
-
-void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
-{
-#ifdef BT_USE_OLD_DAMPING_METHOD
- m_linearDamping = btMax(lin_damping, btScalar(0.0));
- m_angularDamping = btMax(ang_damping, btScalar(0.0));
-#else
- m_linearDamping = btClamped(lin_damping, btScalar(0.0), btScalar(1.0));
- m_angularDamping = btClamped(ang_damping, btScalar(0.0), btScalar(1.0));
-#endif
-}
-
-///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
-void btRigidBody::applyDamping(btScalar timeStep)
-{
- //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
- //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
-
-#ifdef BT_USE_OLD_DAMPING_METHOD
- m_linearVelocity *= btMax((btScalar(1.0) - timeStep * m_linearDamping), btScalar(0.0));
- m_angularVelocity *= btMax((btScalar(1.0) - timeStep * m_angularDamping), btScalar(0.0));
-#else
- m_linearVelocity *= btPow(btScalar(1) - m_linearDamping, timeStep);
- m_angularVelocity *= btPow(btScalar(1) - m_angularDamping, timeStep);
-#endif
-
- if (m_additionalDamping)
- {
- //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
- //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
- if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
- (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
- {
- m_angularVelocity *= m_additionalDampingFactor;
- m_linearVelocity *= m_additionalDampingFactor;
- }
-
- btScalar speed = m_linearVelocity.length();
- if (speed < m_linearDamping)
- {
- btScalar dampVel = btScalar(0.005);
- if (speed > dampVel)
- {
- btVector3 dir = m_linearVelocity.normalized();
- m_linearVelocity -= dir * dampVel;
- }
- else
- {
- m_linearVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- }
- }
-
- btScalar angSpeed = m_angularVelocity.length();
- if (angSpeed < m_angularDamping)
- {
- btScalar angDampVel = btScalar(0.005);
- if (angSpeed > angDampVel)
- {
- btVector3 dir = m_angularVelocity.normalized();
- m_angularVelocity -= dir * angDampVel;
- }
- else
- {
- m_angularVelocity.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- }
- }
- }
-}
-
-void btRigidBody::applyGravity()
-{
- if (isStaticOrKinematicObject())
- return;
-
- applyCentralForce(m_gravity);
-}
-
-void btRigidBody::clearGravity()
-{
- if (isStaticOrKinematicObject())
- return;
-
- applyCentralForce(-m_gravity);
-}
-
-void btRigidBody::proceedToTransform(const btTransform& newTrans)
-{
- setCenterOfMassTransform(newTrans);
-}
-
-void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
-{
- if (mass == btScalar(0.))
- {
- m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
- m_inverseMass = btScalar(0.);
- }
- else
- {
- m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
- m_inverseMass = btScalar(1.0) / mass;
- }
-
- //Fg = m * a
- m_gravity = mass * m_gravity_acceleration;
-
- m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
- inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
- inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
-
- m_invMass = m_linearFactor * m_inverseMass;
-}
-
-void btRigidBody::updateInertiaTensor()
-{
- m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
-}
-
-btVector3 btRigidBody::getLocalInertia() const
-{
- btVector3 inertiaLocal;
- const btVector3 inertia = m_invInertiaLocal;
- inertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x() : btScalar(0.0),
- inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y() : btScalar(0.0),
- inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z() : btScalar(0.0));
- return inertiaLocal;
-}
-
-inline btVector3 evalEulerEqn(const btVector3& w1, const btVector3& w0, const btVector3& T, const btScalar dt,
- const btMatrix3x3& I)
-{
- const btVector3 w2 = I * w1 + w1.cross(I * w1) * dt - (T * dt + I * w0);
- return w2;
-}
-
-inline btMatrix3x3 evalEulerEqnDeriv(const btVector3& w1, const btVector3& w0, const btScalar dt,
- const btMatrix3x3& I)
-{
- btMatrix3x3 w1x, Iw1x;
- const btVector3 Iwi = (I * w1);
- w1.getSkewSymmetricMatrix(&w1x[0], &w1x[1], &w1x[2]);
- Iwi.getSkewSymmetricMatrix(&Iw1x[0], &Iw1x[1], &Iw1x[2]);
-
- const btMatrix3x3 dfw1 = I + (w1x * I - Iw1x) * dt;
- return dfw1;
-}
-
-btVector3 btRigidBody::computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const
-{
- btVector3 inertiaLocal = getLocalInertia();
- btMatrix3x3 inertiaTensorWorld = getWorldTransform().getBasis().scaled(inertiaLocal) * getWorldTransform().getBasis().transpose();
- btVector3 tmp = inertiaTensorWorld * getAngularVelocity();
- btVector3 gf = getAngularVelocity().cross(tmp);
- btScalar l2 = gf.length2();
- if (l2 > maxGyroscopicForce * maxGyroscopicForce)
- {
- gf *= btScalar(1.) / btSqrt(l2) * maxGyroscopicForce;
- }
- return gf;
-}
-
-btVector3 btRigidBody::computeGyroscopicImpulseImplicit_Body(btScalar step) const
-{
- btVector3 idl = getLocalInertia();
- btVector3 omega1 = getAngularVelocity();
- btQuaternion q = getWorldTransform().getRotation();
-
- // Convert to body coordinates
- btVector3 omegab = quatRotate(q.inverse(), omega1);
- btMatrix3x3 Ib;
- Ib.setValue(idl.x(), 0, 0,
- 0, idl.y(), 0,
- 0, 0, idl.z());
-
- btVector3 ibo = Ib * omegab;
-
- // Residual vector
- btVector3 f = step * omegab.cross(ibo);
-
- btMatrix3x3 skew0;
- omegab.getSkewSymmetricMatrix(&skew0[0], &skew0[1], &skew0[2]);
- btVector3 om = Ib * omegab;
- btMatrix3x3 skew1;
- om.getSkewSymmetricMatrix(&skew1[0], &skew1[1], &skew1[2]);
-
- // Jacobian
- btMatrix3x3 J = Ib + (skew0 * Ib - skew1) * step;
-
- // btMatrix3x3 Jinv = J.inverse();
- // btVector3 omega_div = Jinv*f;
- btVector3 omega_div = J.solve33(f);
-
- // Single Newton-Raphson update
- omegab = omegab - omega_div; //Solve33(J, f);
- // Back to world coordinates
- btVector3 omega2 = quatRotate(q, omegab);
- btVector3 gf = omega2 - omega1;
- return gf;
-}
-
-btVector3 btRigidBody::computeGyroscopicImpulseImplicit_World(btScalar step) const
-{
- // use full newton-euler equations. common practice to drop the wxIw term. want it for better tumbling behavior.
- // calculate using implicit euler step so it's stable.
-
- const btVector3 inertiaLocal = getLocalInertia();
- const btVector3 w0 = getAngularVelocity();
-
- btMatrix3x3 I;
-
- I = m_worldTransform.getBasis().scaled(inertiaLocal) *
- m_worldTransform.getBasis().transpose();
-
- // use newtons method to find implicit solution for new angular velocity (w')
- // f(w') = -(T*step + Iw) + Iw' + w' + w'xIw'*step = 0
- // df/dw' = I + 1xIw'*step + w'xI*step
-
- btVector3 w1 = w0;
-
- // one step of newton's method
- {
- const btVector3 fw = evalEulerEqn(w1, w0, btVector3(0, 0, 0), step, I);
- const btMatrix3x3 dfw = evalEulerEqnDeriv(w1, w0, step, I);
-
- btVector3 dw;
- dw = dfw.solve33(fw);
- //const btMatrix3x3 dfw_inv = dfw.inverse();
- //dw = dfw_inv*fw;
-
- w1 -= dw;
- }
-
- btVector3 gf = (w1 - w0);
- return gf;
-}
-
-void btRigidBody::integrateVelocities(btScalar step)
-{
- if (isStaticOrKinematicObject())
- return;
-
- m_linearVelocity += m_totalForce * (m_inverseMass * step);
- m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
-
-#define MAX_ANGVEL SIMD_HALF_PI
- /// clamp angular velocity. collision calculations will fail on higher angular velocities
- btScalar angvel = m_angularVelocity.length();
- if (angvel * step > MAX_ANGVEL)
- {
- m_angularVelocity *= (MAX_ANGVEL / step) / angvel;
- }
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_angularVelocity);
- #endif
-}
-
-btQuaternion btRigidBody::getOrientation() const
-{
- btQuaternion orn;
- m_worldTransform.getBasis().getRotation(orn);
- return orn;
-}
-
-void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
-{
- if (isKinematicObject())
- {
- m_interpolationWorldTransform = m_worldTransform;
- }
- else
- {
- m_interpolationWorldTransform = xform;
- }
- m_interpolationLinearVelocity = getLinearVelocity();
- m_interpolationAngularVelocity = getAngularVelocity();
- m_worldTransform = xform;
- updateInertiaTensor();
-}
-
-void btRigidBody::addConstraintRef(btTypedConstraint* c)
-{
- ///disable collision with the 'other' body
-
- int index = m_constraintRefs.findLinearSearch(c);
- //don't add constraints that are already referenced
- //btAssert(index == m_constraintRefs.size());
- if (index == m_constraintRefs.size())
- {
- m_constraintRefs.push_back(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, true);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, true);
- }
- }
-}
-
-void btRigidBody::removeConstraintRef(btTypedConstraint* c)
-{
- int index = m_constraintRefs.findLinearSearch(c);
- //don't remove constraints that are not referenced
- if (index < m_constraintRefs.size())
- {
- m_constraintRefs.remove(c);
- btCollisionObject* colObjA = &c->getRigidBodyA();
- btCollisionObject* colObjB = &c->getRigidBodyB();
- if (colObjA == this)
- {
- colObjA->setIgnoreCollisionCheck(colObjB, false);
- }
- else
- {
- colObjB->setIgnoreCollisionCheck(colObjA, false);
- }
- }
-}
-
-int btRigidBody::calculateSerializeBufferSize() const
-{
- int sz = sizeof(btRigidBodyData);
- return sz;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
-{
- btRigidBodyData* rbd = (btRigidBodyData*)dataBuffer;
-
- btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
-
- m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
- m_linearVelocity.serialize(rbd->m_linearVelocity);
- m_angularVelocity.serialize(rbd->m_angularVelocity);
- rbd->m_inverseMass = m_inverseMass;
- m_angularFactor.serialize(rbd->m_angularFactor);
- m_linearFactor.serialize(rbd->m_linearFactor);
- m_gravity.serialize(rbd->m_gravity);
- m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
- m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
- m_totalForce.serialize(rbd->m_totalForce);
- m_totalTorque.serialize(rbd->m_totalTorque);
- rbd->m_linearDamping = m_linearDamping;
- rbd->m_angularDamping = m_angularDamping;
- rbd->m_additionalDamping = m_additionalDamping;
- rbd->m_additionalDampingFactor = m_additionalDampingFactor;
- rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
- rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
- rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
- rbd->m_linearSleepingThreshold = m_linearSleepingThreshold;
- rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
-
- // Fill padding with zeros to appease msan.
-#ifdef BT_USE_DOUBLE_PRECISION
- memset(rbd->m_padding, 0, sizeof(rbd->m_padding));
-#endif
-
- return btRigidBodyDataName;
-}
-
-void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
-{
- btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(), 1);
- const char* structType = serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_RIGIDBODY_CODE, (void*)this);
-}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h b/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
deleted file mode 100644
index 7442dd1e6a..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btRigidBody.h
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_RIGIDBODY_H
-#define BT_RIGIDBODY_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btTransform.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-class btCollisionShape;
-class btMotionState;
-class btTypedConstraint;
-
-extern btScalar gDeactivationTime;
-extern bool gDisableDeactivation;
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btRigidBodyData btRigidBodyDoubleData
-#define btRigidBodyDataName "btRigidBodyDoubleData"
-#else
-#define btRigidBodyData btRigidBodyFloatData
-#define btRigidBodyDataName "btRigidBodyFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-enum btRigidBodyFlags
-{
- BT_DISABLE_WORLD_GRAVITY = 1,
- ///BT_ENABLE_GYROPSCOPIC_FORCE flags is enabled by default in Bullet 2.83 and onwards.
- ///and it BT_ENABLE_GYROPSCOPIC_FORCE becomes equivalent to BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY
- ///See Demos/GyroscopicDemo and computeGyroscopicImpulseImplicit
- BT_ENABLE_GYROSCOPIC_FORCE_EXPLICIT = 2,
- BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_WORLD = 4,
- BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY = 8,
- BT_ENABLE_GYROPSCOPIC_FORCE = BT_ENABLE_GYROSCOPIC_FORCE_IMPLICIT_BODY,
-};
-
-///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
-///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
-///There are 3 types of rigid bodies:
-///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
-///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
-///- C) Kinematic objects, which are objects without mass, but the user can move them. There is one-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
-///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
-///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
-class btRigidBody : public btCollisionObject
-{
- btMatrix3x3 m_invInertiaTensorWorld;
- btVector3 m_linearVelocity;
- btVector3 m_angularVelocity;
- btScalar m_inverseMass;
- btVector3 m_linearFactor;
-
- btVector3 m_gravity;
- btVector3 m_gravity_acceleration;
- btVector3 m_invInertiaLocal;
- btVector3 m_totalForce;
- btVector3 m_totalTorque;
-
- btScalar m_linearDamping;
- btScalar m_angularDamping;
-
- bool m_additionalDamping;
- btScalar m_additionalDampingFactor;
- btScalar m_additionalLinearDampingThresholdSqr;
- btScalar m_additionalAngularDampingThresholdSqr;
- btScalar m_additionalAngularDampingFactor;
-
- btScalar m_linearSleepingThreshold;
- btScalar m_angularSleepingThreshold;
-
- //m_optionalMotionState allows to automatic synchronize the world transform for active objects
- btMotionState* m_optionalMotionState;
-
- //keep track of typed constraints referencing this rigid body, to disable collision between linked bodies
- btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
-
- int m_rigidbodyFlags;
-
- int m_debugBodyId;
-
-protected:
- ATTRIBUTE_ALIGNED16(btVector3 m_deltaLinearVelocity);
- btVector3 m_deltaAngularVelocity;
- btVector3 m_angularFactor;
- btVector3 m_invMass;
- btVector3 m_pushVelocity;
- btVector3 m_turnVelocity;
-
-public:
- ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
- ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
- ///You can use the motion state to synchronize the world transform between physics and graphics objects.
- ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
- ///m_startWorldTransform is only used when you don't provide a motion state.
- struct btRigidBodyConstructionInfo
- {
- btScalar m_mass;
-
- ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
- ///In this case, m_startWorldTransform is ignored.
- btMotionState* m_motionState;
- btTransform m_startWorldTransform;
-
- btCollisionShape* m_collisionShape;
- btVector3 m_localInertia;
- btScalar m_linearDamping;
- btScalar m_angularDamping;
-
- ///best simulation results when friction is non-zero
- btScalar m_friction;
- ///the m_rollingFriction prevents rounded shapes, such as spheres, cylinders and capsules from rolling forever.
- ///See Bullet/Demos/RollingFrictionDemo for usage
- btScalar m_rollingFriction;
- btScalar m_spinningFriction; //torsional friction around contact normal
-
- ///best simulation results using zero restitution.
- btScalar m_restitution;
-
- btScalar m_linearSleepingThreshold;
- btScalar m_angularSleepingThreshold;
-
- //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
- //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
- bool m_additionalDamping;
- btScalar m_additionalDampingFactor;
- btScalar m_additionalLinearDampingThresholdSqr;
- btScalar m_additionalAngularDampingThresholdSqr;
- btScalar m_additionalAngularDampingFactor;
-
- btRigidBodyConstructionInfo(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0)) : m_mass(mass),
- m_motionState(motionState),
- m_collisionShape(collisionShape),
- m_localInertia(localInertia),
- m_linearDamping(btScalar(0.)),
- m_angularDamping(btScalar(0.)),
- m_friction(btScalar(0.5)),
- m_rollingFriction(btScalar(0)),
- m_spinningFriction(btScalar(0)),
- m_restitution(btScalar(0.)),
- m_linearSleepingThreshold(btScalar(0.8)),
- m_angularSleepingThreshold(btScalar(1.f)),
- m_additionalDamping(false),
- m_additionalDampingFactor(btScalar(0.005)),
- m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
- m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
- m_additionalAngularDampingFactor(btScalar(0.01))
- {
- m_startWorldTransform.setIdentity();
- }
- };
-
- ///btRigidBody constructor using construction info
- btRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
-
- ///btRigidBody constructor for backwards compatibility.
- ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
- btRigidBody(btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia = btVector3(0, 0, 0));
-
- virtual ~btRigidBody()
- {
- //No constraints should point to this rigidbody
- //Remove constraints from the dynamics world before you delete the related rigidbodies.
- btAssert(m_constraintRefs.size() == 0);
- }
-
-protected:
- ///setupRigidBody is only used internally by the constructor
- void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
-
-public:
- void proceedToTransform(const btTransform& newTrans);
-
- ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
- ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
- static const btRigidBody* upcast(const btCollisionObject* colObj)
- {
- if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
- return (const btRigidBody*)colObj;
- return 0;
- }
- static btRigidBody* upcast(btCollisionObject* colObj)
- {
- if (colObj->getInternalType() & btCollisionObject::CO_RIGID_BODY)
- return (btRigidBody*)colObj;
- return 0;
- }
-
- /// continuous collision detection needs prediction
- void predictIntegratedTransform(btScalar step, btTransform& predictedTransform);
-
- void saveKinematicState(btScalar step);
-
- void applyGravity();
-
- void clearGravity();
-
- void setGravity(const btVector3& acceleration);
-
- const btVector3& getGravity() const
- {
- return m_gravity_acceleration;
- }
-
- void setDamping(btScalar lin_damping, btScalar ang_damping);
-
- btScalar getLinearDamping() const
- {
- return m_linearDamping;
- }
-
- btScalar getAngularDamping() const
- {
- return m_angularDamping;
- }
-
- btScalar getLinearSleepingThreshold() const
- {
- return m_linearSleepingThreshold;
- }
-
- btScalar getAngularSleepingThreshold() const
- {
- return m_angularSleepingThreshold;
- }
-
- void applyDamping(btScalar timeStep);
-
- SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const
- {
- return m_collisionShape;
- }
-
- SIMD_FORCE_INLINE btCollisionShape* getCollisionShape()
- {
- return m_collisionShape;
- }
-
- void setMassProps(btScalar mass, const btVector3& inertia);
-
- const btVector3& getLinearFactor() const
- {
- return m_linearFactor;
- }
- void setLinearFactor(const btVector3& linearFactor)
- {
- m_linearFactor = linearFactor;
- m_invMass = m_linearFactor * m_inverseMass;
- }
- btScalar getInvMass() const { return m_inverseMass; }
- btScalar getMass() const { return m_inverseMass == btScalar(0.) ? btScalar(0.) : btScalar(1.0) / m_inverseMass; }
- const btMatrix3x3& getInvInertiaTensorWorld() const
- {
- return m_invInertiaTensorWorld;
- }
-
- void integrateVelocities(btScalar step);
-
- void setCenterOfMassTransform(const btTransform& xform);
-
- void applyCentralForce(const btVector3& force)
- {
- m_totalForce += force * m_linearFactor;
- }
-
- const btVector3& getTotalForce() const
- {
- return m_totalForce;
- };
-
- const btVector3& getTotalTorque() const
- {
- return m_totalTorque;
- };
-
- const btVector3& getInvInertiaDiagLocal() const
- {
- return m_invInertiaLocal;
- };
-
- void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
- {
- m_invInertiaLocal = diagInvInertia;
- }
-
- void setSleepingThresholds(btScalar linear, btScalar angular)
- {
- m_linearSleepingThreshold = linear;
- m_angularSleepingThreshold = angular;
- }
-
- void applyTorque(const btVector3& torque)
- {
- m_totalTorque += torque * m_angularFactor;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_totalTorque);
- #endif
- }
-
- void applyForce(const btVector3& force, const btVector3& rel_pos)
- {
- applyCentralForce(force);
- applyTorque(rel_pos.cross(force * m_linearFactor));
- }
-
- void applyCentralImpulse(const btVector3& impulse)
- {
- m_linearVelocity += impulse * m_linearFactor * m_inverseMass;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_linearVelocity);
- #endif
- }
-
- void applyTorqueImpulse(const btVector3& torque)
- {
- m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_angularVelocity);
- #endif
- }
-
- void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
- {
- if (m_inverseMass != btScalar(0.))
- {
- applyCentralImpulse(impulse);
- if (m_angularFactor)
- {
- applyTorqueImpulse(rel_pos.cross(impulse * m_linearFactor));
- }
- }
- }
-
- void applyPushImpulse(const btVector3& impulse, const btVector3& rel_pos)
- {
- if (m_inverseMass != btScalar(0.))
- {
- applyCentralPushImpulse(impulse);
- if (m_angularFactor)
- {
- applyTorqueTurnImpulse(rel_pos.cross(impulse * m_linearFactor));
- }
- }
- }
-
- btVector3 getPushVelocity() const
- {
- return m_pushVelocity;
- }
-
- btVector3 getTurnVelocity() const
- {
- return m_turnVelocity;
- }
-
- void setPushVelocity(const btVector3& v)
- {
- m_pushVelocity = v;
- }
-
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- void clampVelocity(btVector3& v) const {
- v.setX(
- fmax(-BT_CLAMP_VELOCITY_TO,
- fmin(BT_CLAMP_VELOCITY_TO, v.getX()))
- );
- v.setY(
- fmax(-BT_CLAMP_VELOCITY_TO,
- fmin(BT_CLAMP_VELOCITY_TO, v.getY()))
- );
- v.setZ(
- fmax(-BT_CLAMP_VELOCITY_TO,
- fmin(BT_CLAMP_VELOCITY_TO, v.getZ()))
- );
- }
- #endif
-
- void setTurnVelocity(const btVector3& v)
- {
- m_turnVelocity = v;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_turnVelocity);
- #endif
- }
-
- void applyCentralPushImpulse(const btVector3& impulse)
- {
- m_pushVelocity += impulse * m_linearFactor * m_inverseMass;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_pushVelocity);
- #endif
- }
-
- void applyTorqueTurnImpulse(const btVector3& torque)
- {
- m_turnVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_turnVelocity);
- #endif
- }
-
- void clearForces()
- {
- m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- }
-
- void updateInertiaTensor();
-
- const btVector3& getCenterOfMassPosition() const
- {
- return m_worldTransform.getOrigin();
- }
- btQuaternion getOrientation() const;
-
- const btTransform& getCenterOfMassTransform() const
- {
- return m_worldTransform;
- }
- const btVector3& getLinearVelocity() const
- {
- return m_linearVelocity;
- }
- const btVector3& getAngularVelocity() const
- {
- return m_angularVelocity;
- }
-
- inline void setLinearVelocity(const btVector3& lin_vel)
- {
- m_updateRevision++;
- m_linearVelocity = lin_vel;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_linearVelocity);
- #endif
- }
-
- inline void setAngularVelocity(const btVector3& ang_vel)
- {
- m_updateRevision++;
- m_angularVelocity = ang_vel;
- #if defined(BT_CLAMP_VELOCITY_TO) && BT_CLAMP_VELOCITY_TO > 0
- clampVelocity(m_angularVelocity);
- #endif
- }
-
- btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
- {
- //we also calculate lin/ang velocity for kinematic objects
- return m_linearVelocity + m_angularVelocity.cross(rel_pos);
-
- //for kinematic objects, we could also use use:
- // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
- }
-
- btVector3 getPushVelocityInLocalPoint(const btVector3& rel_pos) const
- {
- //we also calculate lin/ang velocity for kinematic objects
- return m_pushVelocity + m_turnVelocity.cross(rel_pos);
- }
-
- void translate(const btVector3& v)
- {
- m_worldTransform.getOrigin() += v;
- }
-
- void getAabb(btVector3& aabbMin, btVector3& aabbMax) const;
-
- SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
- {
- btVector3 r0 = pos - getCenterOfMassPosition();
-
- btVector3 c0 = (r0).cross(normal);
-
- btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
-
- return m_inverseMass + normal.dot(vec);
- }
-
- SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
- {
- btVector3 vec = axis * getInvInertiaTensorWorld();
- return axis.dot(vec);
- }
-
- SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
- {
- if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
- return;
-
- if ((getLinearVelocity().length2() < m_linearSleepingThreshold * m_linearSleepingThreshold) &&
- (getAngularVelocity().length2() < m_angularSleepingThreshold * m_angularSleepingThreshold))
- {
- m_deactivationTime += timeStep;
- }
- else
- {
- m_deactivationTime = btScalar(0.);
- setActivationState(0);
- }
- }
-
- SIMD_FORCE_INLINE bool wantsSleeping()
- {
- if (getActivationState() == DISABLE_DEACTIVATION)
- return false;
-
- //disable deactivation
- if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
- return false;
-
- if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
- return true;
-
- if (m_deactivationTime > gDeactivationTime)
- {
- return true;
- }
- return false;
- }
-
- const btBroadphaseProxy* getBroadphaseProxy() const
- {
- return m_broadphaseHandle;
- }
- btBroadphaseProxy* getBroadphaseProxy()
- {
- return m_broadphaseHandle;
- }
- void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
- {
- m_broadphaseHandle = broadphaseProxy;
- }
-
- //btMotionState allows to automatic synchronize the world transform for active objects
- btMotionState* getMotionState()
- {
- return m_optionalMotionState;
- }
- const btMotionState* getMotionState() const
- {
- return m_optionalMotionState;
- }
- void setMotionState(btMotionState* motionState)
- {
- m_optionalMotionState = motionState;
- if (m_optionalMotionState)
- motionState->getWorldTransform(m_worldTransform);
- }
-
- //for experimental overriding of friction/contact solver func
- int m_contactSolverType;
- int m_frictionSolverType;
-
- void setAngularFactor(const btVector3& angFac)
- {
- m_updateRevision++;
- m_angularFactor = angFac;
- }
-
- void setAngularFactor(btScalar angFac)
- {
- m_updateRevision++;
- m_angularFactor.setValue(angFac, angFac, angFac);
- }
- const btVector3& getAngularFactor() const
- {
- return m_angularFactor;
- }
-
- //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
- bool isInWorld() const
- {
- return (getBroadphaseProxy() != 0);
- }
-
- void addConstraintRef(btTypedConstraint* c);
- void removeConstraintRef(btTypedConstraint* c);
-
- btTypedConstraint* getConstraintRef(int index)
- {
- return m_constraintRefs[index];
- }
-
- int getNumConstraintRefs() const
- {
- return m_constraintRefs.size();
- }
-
- void setFlags(int flags)
- {
- m_rigidbodyFlags = flags;
- }
-
- int getFlags() const
- {
- return m_rigidbodyFlags;
- }
-
- ///perform implicit force computation in world space
- btVector3 computeGyroscopicImpulseImplicit_World(btScalar dt) const;
-
- ///perform implicit force computation in body space (inertial frame)
- btVector3 computeGyroscopicImpulseImplicit_Body(btScalar step) const;
-
- ///explicit version is best avoided, it gains energy
- btVector3 computeGyroscopicForceExplicit(btScalar maxGyroscopicForce) const;
- btVector3 getLocalInertia() const;
-
- ///////////////////////////////////////////////
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-
- virtual void serializeSingleObject(class btSerializer* serializer) const;
-};
-
-//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btRigidBodyFloatData
-{
- btCollisionObjectFloatData m_collisionObjectData;
- btMatrix3x3FloatData m_invInertiaTensorWorld;
- btVector3FloatData m_linearVelocity;
- btVector3FloatData m_angularVelocity;
- btVector3FloatData m_angularFactor;
- btVector3FloatData m_linearFactor;
- btVector3FloatData m_gravity;
- btVector3FloatData m_gravity_acceleration;
- btVector3FloatData m_invInertiaLocal;
- btVector3FloatData m_totalForce;
- btVector3FloatData m_totalTorque;
- float m_inverseMass;
- float m_linearDamping;
- float m_angularDamping;
- float m_additionalDampingFactor;
- float m_additionalLinearDampingThresholdSqr;
- float m_additionalAngularDampingThresholdSqr;
- float m_additionalAngularDampingFactor;
- float m_linearSleepingThreshold;
- float m_angularSleepingThreshold;
- int m_additionalDamping;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btRigidBodyDoubleData
-{
- btCollisionObjectDoubleData m_collisionObjectData;
- btMatrix3x3DoubleData m_invInertiaTensorWorld;
- btVector3DoubleData m_linearVelocity;
- btVector3DoubleData m_angularVelocity;
- btVector3DoubleData m_angularFactor;
- btVector3DoubleData m_linearFactor;
- btVector3DoubleData m_gravity;
- btVector3DoubleData m_gravity_acceleration;
- btVector3DoubleData m_invInertiaLocal;
- btVector3DoubleData m_totalForce;
- btVector3DoubleData m_totalTorque;
- double m_inverseMass;
- double m_linearDamping;
- double m_angularDamping;
- double m_additionalDampingFactor;
- double m_additionalLinearDampingThresholdSqr;
- double m_additionalAngularDampingThresholdSqr;
- double m_additionalAngularDampingFactor;
- double m_linearSleepingThreshold;
- double m_angularSleepingThreshold;
- int m_additionalDamping;
- char m_padding[4];
-};
-
-#endif //BT_RIGIDBODY_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
deleted file mode 100644
index 8103390fb1..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSimpleDynamicsWorld.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-
-/*
- Make sure this dummy function never changes so that it
- can be used by probes that are checking whether the
- library is actually installed.
-*/
-extern "C"
-{
- void btBulletDynamicsProbe();
- void btBulletDynamicsProbe() {}
-}
-
-btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
- : btDynamicsWorld(dispatcher, pairCache, collisionConfiguration),
- m_constraintSolver(constraintSolver),
- m_ownsConstraintSolver(false),
- m_gravity(0, 0, -10)
-{
-}
-
-btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
-{
- if (m_ownsConstraintSolver)
- btAlignedFree(m_constraintSolver);
-}
-
-int btSimpleDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
-{
- (void)fixedTimeStep;
- (void)maxSubSteps;
-
- ///apply gravity, predict motion
- predictUnconstraintMotion(timeStep);
-
- btDispatcherInfo& dispatchInfo = getDispatchInfo();
- dispatchInfo.m_timeStep = timeStep;
- dispatchInfo.m_stepCount = 0;
- dispatchInfo.m_debugDraw = getDebugDrawer();
-
- ///perform collision detection
- performDiscreteCollisionDetection();
-
- ///solve contact constraints
- int numManifolds = m_dispatcher1->getNumManifolds();
- if (numManifolds)
- {
- btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
-
- btContactSolverInfo infoGlobal;
- infoGlobal.m_timeStep = timeStep;
- m_constraintSolver->prepareSolve(0, numManifolds);
- m_constraintSolver->solveGroup(&getCollisionObjectArray()[0], getNumCollisionObjects(), manifoldPtr, numManifolds, 0, 0, infoGlobal, m_debugDrawer, m_dispatcher1);
- m_constraintSolver->allSolved(infoGlobal, m_debugDrawer);
- }
-
- ///integrate transforms
- integrateTransforms(timeStep);
-
- updateAabbs();
-
- synchronizeMotionStates();
-
- clearForces();
-
- return 1;
-}
-
-void btSimpleDynamicsWorld::clearForces()
-{
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
-
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- body->clearForces();
- }
- }
-}
-
-void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
-{
- m_gravity = gravity;
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- body->setGravity(gravity);
- }
- }
-}
-
-btVector3 btSimpleDynamicsWorld::getGravity() const
-{
- return m_gravity;
-}
-
-void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
-{
- btCollisionWorld::removeCollisionObject(body);
-}
-
-void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- btRigidBody* body = btRigidBody::upcast(collisionObject);
- if (body)
- removeRigidBody(body);
- else
- btCollisionWorld::removeCollisionObject(collisionObject);
-}
-
-void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
-{
- body->setGravity(m_gravity);
-
- if (body->getCollisionShape())
- {
- addCollisionObject(body);
- }
-}
-
-void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body, int group, int mask)
-{
- body->setGravity(m_gravity);
-
- if (body->getCollisionShape())
- {
- addCollisionObject(body, group, mask);
- }
-}
-
-void btSimpleDynamicsWorld::debugDrawWorld()
-{
-}
-
-void btSimpleDynamicsWorld::addAction(btActionInterface* action)
-{
-}
-
-void btSimpleDynamicsWorld::removeAction(btActionInterface* action)
-{
-}
-
-void btSimpleDynamicsWorld::updateAabbs()
-{
- btTransform predictedTrans;
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- if (body->isActive() && (!body->isStaticObject()))
- {
- btVector3 minAabb, maxAabb;
- colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb, maxAabb);
- btBroadphaseInterface* bp = getBroadphase();
- bp->setAabb(body->getBroadphaseHandle(), minAabb, maxAabb, m_dispatcher1);
- }
- }
- }
-}
-
-void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
-{
- btTransform predictedTrans;
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- if (body->isActive() && (!body->isStaticObject()))
- {
- body->predictIntegratedTransform(timeStep, predictedTrans);
- body->proceedToTransform(predictedTrans);
- }
- }
- }
-}
-
-void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body)
- {
- if (!body->isStaticObject())
- {
- if (body->isActive())
- {
- body->applyGravity();
- body->integrateVelocities(timeStep);
- body->applyDamping(timeStep);
- body->predictIntegratedTransform(timeStep, body->getInterpolationWorldTransform());
- }
- }
- }
- }
-}
-
-void btSimpleDynamicsWorld::synchronizeMotionStates()
-{
- ///@todo: iterate over awake simulation islands!
- for (int i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- btRigidBody* body = btRigidBody::upcast(colObj);
- if (body && body->getMotionState())
- {
- if (body->getActivationState() != ISLAND_SLEEPING)
- {
- body->getMotionState()->setWorldTransform(body->getWorldTransform());
- }
- }
- }
-}
-
-void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
-{
- if (m_ownsConstraintSolver)
- {
- btAlignedFree(m_constraintSolver);
- }
- m_ownsConstraintSolver = false;
- m_constraintSolver = solver;
-}
-
-btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
-{
- return m_constraintSolver;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
deleted file mode 100644
index 12be231c7f..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMPLE_DYNAMICS_WORLD_H
-#define BT_SIMPLE_DYNAMICS_WORLD_H
-
-#include "btDynamicsWorld.h"
-
-class btDispatcher;
-class btOverlappingPairCache;
-class btConstraintSolver;
-
-///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds.
-///Please use btDiscreteDynamicsWorld instead
-class btSimpleDynamicsWorld : public btDynamicsWorld
-{
-protected:
- btConstraintSolver* m_constraintSolver;
-
- bool m_ownsConstraintSolver;
-
- void predictUnconstraintMotion(btScalar timeStep);
-
- void integrateTransforms(btScalar timeStep);
-
- btVector3 m_gravity;
-
-public:
- ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
- btSimpleDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
-
- virtual ~btSimpleDynamicsWorld();
-
- ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
- virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
-
- virtual void setGravity(const btVector3& gravity);
-
- virtual btVector3 getGravity() const;
-
- virtual void addRigidBody(btRigidBody* body);
-
- virtual void addRigidBody(btRigidBody* body, int group, int mask);
-
- virtual void removeRigidBody(btRigidBody* body);
-
- virtual void debugDrawWorld();
-
- virtual void addAction(btActionInterface* action);
-
- virtual void removeAction(btActionInterface* action);
-
- ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- virtual void updateAabbs();
-
- virtual void synchronizeMotionStates();
-
- virtual void setConstraintSolver(btConstraintSolver* solver);
-
- virtual btConstraintSolver* getConstraintSolver();
-
- virtual btDynamicsWorldType getWorldType() const
- {
- return BT_SIMPLE_DYNAMICS_WORLD;
- }
-
- virtual void clearForces();
-};
-
-#endif //BT_SIMPLE_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
deleted file mode 100644
index 772b774202..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btThreads.h"
-#include "btSimulationIslandManagerMt.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.h" // for s_minimumContactManifoldsForBatching
-
-//#include <stdio.h>
-#include "LinearMath/btQuickprof.h"
-
-SIMD_FORCE_INLINE int calcBatchCost(int bodies, int manifolds, int constraints)
-{
- // rough estimate of the cost of a batch, used for merging
- int batchCost = bodies + 8 * manifolds + 4 * constraints;
- return batchCost;
-}
-
-SIMD_FORCE_INLINE int calcBatchCost(const btSimulationIslandManagerMt::Island* island)
-{
- return calcBatchCost(island->bodyArray.size(), island->manifoldArray.size(), island->constraintArray.size());
-}
-
-btSimulationIslandManagerMt::btSimulationIslandManagerMt()
-{
- m_minimumSolverBatchSize = calcBatchCost(0, 128, 0);
- m_batchIslandMinBodyCount = 32;
- m_islandDispatch = parallelIslandDispatch;
- m_batchIsland = NULL;
-}
-
-btSimulationIslandManagerMt::~btSimulationIslandManagerMt()
-{
- for (int i = 0; i < m_allocatedIslands.size(); ++i)
- {
- delete m_allocatedIslands[i];
- }
- m_allocatedIslands.resize(0);
- m_activeIslands.resize(0);
- m_freeIslands.resize(0);
-}
-
-inline int getIslandId(const btPersistentManifold* lhs)
-{
- const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
- const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
- int islandId = rcolObj0->getIslandTag() >= 0 ? rcolObj0->getIslandTag() : rcolObj1->getIslandTag();
- return islandId;
-}
-
-SIMD_FORCE_INLINE int btGetConstraintIslandId1(const btTypedConstraint* lhs)
-{
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- int islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
-}
-
-/// function object that routes calls to operator<
-class IslandBatchSizeSortPredicate
-{
-public:
- bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
- {
- int lCost = calcBatchCost(lhs);
- int rCost = calcBatchCost(rhs);
- return lCost > rCost;
- }
-};
-
-class IslandBodyCapacitySortPredicate
-{
-public:
- bool operator()(const btSimulationIslandManagerMt::Island* lhs, const btSimulationIslandManagerMt::Island* rhs) const
- {
- return lhs->bodyArray.capacity() > rhs->bodyArray.capacity();
- }
-};
-
-void btSimulationIslandManagerMt::Island::append(const Island& other)
-{
- // append bodies
- for (int i = 0; i < other.bodyArray.size(); ++i)
- {
- bodyArray.push_back(other.bodyArray[i]);
- }
- // append manifolds
- for (int i = 0; i < other.manifoldArray.size(); ++i)
- {
- manifoldArray.push_back(other.manifoldArray[i]);
- }
- // append constraints
- for (int i = 0; i < other.constraintArray.size(); ++i)
- {
- constraintArray.push_back(other.constraintArray[i]);
- }
-}
-
-bool btIsBodyInIsland(const btSimulationIslandManagerMt::Island& island, const btCollisionObject* obj)
-{
- for (int i = 0; i < island.bodyArray.size(); ++i)
- {
- if (island.bodyArray[i] == obj)
- {
- return true;
- }
- }
- return false;
-}
-
-void btSimulationIslandManagerMt::initIslandPools()
-{
- // reset island pools
- int numElem = getUnionFind().getNumElements();
- m_lookupIslandFromId.resize(numElem);
- for (int i = 0; i < m_lookupIslandFromId.size(); ++i)
- {
- m_lookupIslandFromId[i] = NULL;
- }
- m_activeIslands.resize(0);
- m_freeIslands.resize(0);
- // check whether allocated islands are sorted by body capacity (largest to smallest)
- int lastCapacity = 0;
- bool isSorted = true;
- for (int i = 0; i < m_allocatedIslands.size(); ++i)
- {
- Island* island = m_allocatedIslands[i];
- int cap = island->bodyArray.capacity();
- if (cap > lastCapacity)
- {
- isSorted = false;
- break;
- }
- lastCapacity = cap;
- }
- if (!isSorted)
- {
- m_allocatedIslands.quickSort(IslandBodyCapacitySortPredicate());
- }
-
- m_batchIsland = NULL;
- // mark all islands free (but avoid deallocation)
- for (int i = 0; i < m_allocatedIslands.size(); ++i)
- {
- Island* island = m_allocatedIslands[i];
- island->bodyArray.resize(0);
- island->manifoldArray.resize(0);
- island->constraintArray.resize(0);
- island->id = -1;
- island->isSleeping = true;
- m_freeIslands.push_back(island);
- }
-}
-
-btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::getIsland(int id)
-{
- btAssert(id >= 0);
- btAssert(id < m_lookupIslandFromId.size());
- Island* island = m_lookupIslandFromId[id];
- if (island == NULL)
- {
- // search for existing island
- for (int i = 0; i < m_activeIslands.size(); ++i)
- {
- if (m_activeIslands[i]->id == id)
- {
- island = m_activeIslands[i];
- break;
- }
- }
- m_lookupIslandFromId[id] = island;
- }
- return island;
-}
-
-btSimulationIslandManagerMt::Island* btSimulationIslandManagerMt::allocateIsland(int id, int numBodies)
-{
- Island* island = NULL;
- int allocSize = numBodies;
- if (numBodies < m_batchIslandMinBodyCount)
- {
- if (m_batchIsland)
- {
- island = m_batchIsland;
- m_lookupIslandFromId[id] = island;
- // if we've made a large enough batch,
- if (island->bodyArray.size() + numBodies >= m_batchIslandMinBodyCount)
- {
- // next time start a new batch
- m_batchIsland = NULL;
- }
- return island;
- }
- else
- {
- // need to allocate a batch island
- allocSize = m_batchIslandMinBodyCount * 2;
- }
- }
- btAlignedObjectArray<Island*>& freeIslands = m_freeIslands;
-
- // search for free island
- if (freeIslands.size() > 0)
- {
- // try to reuse a previously allocated island
- int iFound = freeIslands.size();
- // linear search for smallest island that can hold our bodies
- for (int i = freeIslands.size() - 1; i >= 0; --i)
- {
- if (freeIslands[i]->bodyArray.capacity() >= allocSize)
- {
- iFound = i;
- island = freeIslands[i];
- island->id = id;
- break;
- }
- }
- // if found, shrink array while maintaining ordering
- if (island)
- {
- int iDest = iFound;
- int iSrc = iDest + 1;
- while (iSrc < freeIslands.size())
- {
- freeIslands[iDest++] = freeIslands[iSrc++];
- }
- freeIslands.pop_back();
- }
- }
- if (island == NULL)
- {
- // no free island found, allocate
- island = new Island(); // TODO: change this to use the pool allocator
- island->id = id;
- island->bodyArray.reserve(allocSize);
- m_allocatedIslands.push_back(island);
- }
- m_lookupIslandFromId[id] = island;
- if (numBodies < m_batchIslandMinBodyCount)
- {
- m_batchIsland = island;
- }
- m_activeIslands.push_back(island);
- return island;
-}
-
-void btSimulationIslandManagerMt::buildIslands(btDispatcher* dispatcher, btCollisionWorld* collisionWorld)
-{
- BT_PROFILE("buildIslands");
-
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
-
- //we are going to sort the unionfind array, and store the element id in the size
- //afterwards, we clean unionfind, to make sure no-one uses it anymore
-
- getUnionFind().sortIslands();
- int numElem = getUnionFind().getNumElements();
-
- int endIslandIndex = 1;
- int startIslandIndex;
-
- //update the sleeping state for bodies, if all are sleeping
- for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
- {
- int islandId = getUnionFind().getElement(startIslandIndex).m_id;
- for (endIslandIndex = startIslandIndex + 1; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
- {
- }
-
- //int numSleeping = 0;
-
- bool allSleeping = true;
-
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
-
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
- if (colObj0->getIslandTag() == islandId)
- {
- if (colObj0->getActivationState() == ACTIVE_TAG ||
- colObj0->getActivationState() == DISABLE_DEACTIVATION)
- {
- allSleeping = false;
- break;
- }
- }
- }
-
- if (allSleeping)
- {
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
-
- if (colObj0->getIslandTag() == islandId)
- {
- colObj0->setActivationState(ISLAND_SLEEPING);
- }
- }
- }
- else
- {
- int idx;
- for (idx = startIslandIndex; idx < endIslandIndex; idx++)
- {
- int i = getUnionFind().getElement(idx).m_sz;
-
- btCollisionObject* colObj0 = collisionObjects[i];
- if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
- {
- // printf("error in island management\n");
- }
-
- btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
-
- if (colObj0->getIslandTag() == islandId)
- {
- if (colObj0->getActivationState() == ISLAND_SLEEPING)
- {
- colObj0->setActivationState(WANTS_DEACTIVATION);
- colObj0->setDeactivationTime(0.f);
- }
- }
- }
- }
- }
-}
-
-void btSimulationIslandManagerMt::addBodiesToIslands(btCollisionWorld* collisionWorld)
-{
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
- int endIslandIndex = 1;
- int startIslandIndex;
- int numElem = getUnionFind().getNumElements();
-
- // create explicit islands and add bodies to each
- for (startIslandIndex = 0; startIslandIndex < numElem; startIslandIndex = endIslandIndex)
- {
- int islandId = getUnionFind().getElement(startIslandIndex).m_id;
-
- // find end index
- for (endIslandIndex = startIslandIndex; (endIslandIndex < numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId); endIslandIndex++)
- {
- }
- // check if island is sleeping
- bool islandSleeping = true;
- for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
- {
- int i = getUnionFind().getElement(iElem).m_sz;
- btCollisionObject* colObj = collisionObjects[i];
- if (colObj->isActive())
- {
- islandSleeping = false;
- }
- }
- if (!islandSleeping)
- {
- // want to count the number of bodies before allocating the island to optimize memory usage of the Island structures
- int numBodies = endIslandIndex - startIslandIndex;
- Island* island = allocateIsland(islandId, numBodies);
- island->isSleeping = false;
-
- // add bodies to island
- for (int iElem = startIslandIndex; iElem < endIslandIndex; iElem++)
- {
- int i = getUnionFind().getElement(iElem).m_sz;
- btCollisionObject* colObj = collisionObjects[i];
- island->bodyArray.push_back(colObj);
- }
- }
- }
-}
-
-void btSimulationIslandManagerMt::addManifoldsToIslands(btDispatcher* dispatcher)
-{
- // walk all the manifolds, activating bodies touched by kinematic objects, and add each manifold to its Island
- int maxNumManifolds = dispatcher->getNumManifolds();
- for (int i = 0; i < maxNumManifolds; i++)
- {
- btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
-
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
-
- ///@todo: check sleeping conditions!
- if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
- ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
- {
- //kinematic objects don't merge islands, but wake up all connected objects
- if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj0->hasContactResponse())
- colObj1->activate();
- }
- if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj1->hasContactResponse())
- colObj0->activate();
- }
- //filtering for response
- if (dispatcher->needsResponse(colObj0, colObj1))
- {
- // scatter manifolds into various islands
- int islandId = getIslandId(manifold);
- // if island not sleeping,
- if (Island* island = getIsland(islandId))
- {
- island->manifoldArray.push_back(manifold);
- }
- }
- }
- }
-}
-
-void btSimulationIslandManagerMt::addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints)
-{
- // walk constraints
- for (int i = 0; i < constraints.size(); i++)
- {
- // scatter constraints into various islands
- btTypedConstraint* constraint = constraints[i];
- if (constraint->isEnabled())
- {
- int islandId = btGetConstraintIslandId1(constraint);
- // if island is not sleeping,
- if (Island* island = getIsland(islandId))
- {
- island->constraintArray.push_back(constraint);
- }
- }
- }
-}
-
-void btSimulationIslandManagerMt::mergeIslands()
-{
- // sort islands in order of decreasing batch size
- m_activeIslands.quickSort(IslandBatchSizeSortPredicate());
-
- // merge small islands to satisfy minimum batch size
- // find first small batch island
- int destIslandIndex = m_activeIslands.size();
- for (int i = 0; i < m_activeIslands.size(); ++i)
- {
- Island* island = m_activeIslands[i];
- int batchSize = calcBatchCost(island);
- if (batchSize < m_minimumSolverBatchSize)
- {
- destIslandIndex = i;
- break;
- }
- }
- int lastIndex = m_activeIslands.size() - 1;
- while (destIslandIndex < lastIndex)
- {
- // merge islands from the back of the list
- Island* island = m_activeIslands[destIslandIndex];
- int numBodies = island->bodyArray.size();
- int numManifolds = island->manifoldArray.size();
- int numConstraints = island->constraintArray.size();
- int firstIndex = lastIndex;
- // figure out how many islands we want to merge and find out how many bodies, manifolds and constraints we will have
- while (true)
- {
- Island* src = m_activeIslands[firstIndex];
- numBodies += src->bodyArray.size();
- numManifolds += src->manifoldArray.size();
- numConstraints += src->constraintArray.size();
- int batchCost = calcBatchCost(numBodies, numManifolds, numConstraints);
- if (batchCost >= m_minimumSolverBatchSize)
- {
- break;
- }
- if (firstIndex - 1 == destIslandIndex)
- {
- break;
- }
- firstIndex--;
- }
- // reserve space for these pointers to minimize reallocation
- island->bodyArray.reserve(numBodies);
- island->manifoldArray.reserve(numManifolds);
- island->constraintArray.reserve(numConstraints);
- // merge islands
- for (int i = firstIndex; i <= lastIndex; ++i)
- {
- island->append(*m_activeIslands[i]);
- }
- // shrink array to exclude the islands that were merged from
- m_activeIslands.resize(firstIndex);
- lastIndex = firstIndex - 1;
- destIslandIndex++;
- }
-}
-
-void btSimulationIslandManagerMt::solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams)
-{
- btPersistentManifold** manifolds = island.manifoldArray.size() ? &island.manifoldArray[0] : NULL;
- btTypedConstraint** constraintsPtr = island.constraintArray.size() ? &island.constraintArray[0] : NULL;
- solver->solveGroup(&island.bodyArray[0],
- island.bodyArray.size(),
- manifolds,
- island.manifoldArray.size(),
- constraintsPtr,
- island.constraintArray.size(),
- *solverParams.m_solverInfo,
- solverParams.m_debugDrawer,
- solverParams.m_dispatcher);
-}
-
-void btSimulationIslandManagerMt::serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
-{
- BT_PROFILE("serialIslandDispatch");
- // serial dispatch
- btAlignedObjectArray<Island*>& islands = *islandsPtr;
- btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
- for (int i = 0; i < islands.size(); ++i)
- {
- solveIsland(solver, *islands[i], solverParams);
- }
-}
-
-struct UpdateIslandDispatcher : public btIParallelForBody
-{
- btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& m_islandsPtr;
- const btSimulationIslandManagerMt::SolverParams& m_solverParams;
-
- UpdateIslandDispatcher(btAlignedObjectArray<btSimulationIslandManagerMt::Island*>& islandsPtr, const btSimulationIslandManagerMt::SolverParams& solverParams)
- : m_islandsPtr(islandsPtr), m_solverParams(solverParams)
- {
- }
-
- void forLoop(int iBegin, int iEnd) const BT_OVERRIDE
- {
- btConstraintSolver* solver = m_solverParams.m_solverPool;
- for (int i = iBegin; i < iEnd; ++i)
- {
- btSimulationIslandManagerMt::Island* island = m_islandsPtr[i];
- btSimulationIslandManagerMt::solveIsland(solver, *island, m_solverParams);
- }
- }
-};
-
-void btSimulationIslandManagerMt::parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams)
-{
- BT_PROFILE("parallelIslandDispatch");
- //
- // if there are islands with many contacts, it may be faster to submit these
- // large islands *serially* to a single parallel constraint solver, and then later
- // submit the remaining smaller islands in parallel to multiple sequential solvers.
- //
- // Some task schedulers do not deal well with nested parallelFor loops. One implementation
- // of OpenMP was actually slower than doing everything single-threaded. Intel TBB
- // on the other hand, seems to do a pretty respectable job with it.
- //
- // When solving islands in parallel, the worst case performance happens when there
- // is one very large island and then perhaps a smattering of very small
- // islands -- one worker thread takes the large island and the remaining workers
- // tear through the smaller islands and then sit idle waiting for the first worker
- // to finish. Solving islands in parallel works best when there are numerous small
- // islands, roughly equal in size.
- //
- // By contrast, the other approach -- the parallel constraint solver -- is only
- // able to deliver a worthwhile speedup when the island is large. For smaller islands,
- // it is difficult to extract a useful amount of parallelism -- the overhead of grouping
- // the constraints into batches and sending the batches to worker threads can nullify
- // any gains from parallelism.
- //
-
- UpdateIslandDispatcher dispatcher(*islandsPtr, solverParams);
- // We take advantage of the fact the islands are sorted in order of decreasing size
- int iBegin = 0;
- if (solverParams.m_solverMt)
- {
- while (iBegin < islandsPtr->size())
- {
- btSimulationIslandManagerMt::Island* island = (*islandsPtr)[iBegin];
- if (island->manifoldArray.size() < btSequentialImpulseConstraintSolverMt::s_minimumContactManifoldsForBatching)
- {
- // OK to submit the rest of the array in parallel
- break;
- }
- // serial dispatch to parallel solver for large islands (if any)
- solveIsland(solverParams.m_solverMt, *island, solverParams);
- ++iBegin;
- }
- }
- // parallel dispatch to sequential solvers for rest
- btParallelFor(iBegin, islandsPtr->size(), 1, dispatcher);
-}
-
-///@todo: this is random access, it can be walked 'cache friendly'!
-void btSimulationIslandManagerMt::buildAndProcessIslands(btDispatcher* dispatcher,
- btCollisionWorld* collisionWorld,
- btAlignedObjectArray<btTypedConstraint*>& constraints,
- const SolverParams& solverParams)
-{
- BT_PROFILE("buildAndProcessIslands");
- btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
-
- buildIslands(dispatcher, collisionWorld);
-
- if (!getSplitIslands())
- {
- btPersistentManifold** manifolds = dispatcher->getInternalManifoldPointer();
- int maxNumManifolds = dispatcher->getNumManifolds();
-
- for (int i = 0; i < maxNumManifolds; i++)
- {
- btPersistentManifold* manifold = manifolds[i];
-
- const btCollisionObject* colObj0 = static_cast<const btCollisionObject*>(manifold->getBody0());
- const btCollisionObject* colObj1 = static_cast<const btCollisionObject*>(manifold->getBody1());
-
- ///@todo: check sleeping conditions!
- if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
- ((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
- {
- //kinematic objects don't merge islands, but wake up all connected objects
- if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj0->hasContactResponse())
- colObj1->activate();
- }
- if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
- {
- if (colObj1->hasContactResponse())
- colObj0->activate();
- }
- }
- }
- btTypedConstraint** constraintsPtr = constraints.size() ? &constraints[0] : NULL;
- btConstraintSolver* solver = solverParams.m_solverMt ? solverParams.m_solverMt : solverParams.m_solverPool;
- solver->solveGroup(&collisionObjects[0],
- collisionObjects.size(),
- manifolds,
- maxNumManifolds,
- constraintsPtr,
- constraints.size(),
- *solverParams.m_solverInfo,
- solverParams.m_debugDrawer,
- solverParams.m_dispatcher);
- }
- else
- {
- initIslandPools();
-
- //traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
- addBodiesToIslands(collisionWorld);
- addManifoldsToIslands(dispatcher);
- addConstraintsToIslands(constraints);
-
- // m_activeIslands array should now contain all non-sleeping Islands, and each Island should
- // have all the necessary bodies, manifolds and constraints.
-
- // if we want to merge islands with small batch counts,
- if (m_minimumSolverBatchSize > 1)
- {
- mergeIslands();
- }
- // dispatch islands to solver
- m_islandDispatch(&m_activeIslands, solverParams);
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h b/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
deleted file mode 100644
index ab73a899f1..0000000000
--- a/thirdparty/bullet/BulletDynamics/Dynamics/btSimulationIslandManagerMt.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMULATION_ISLAND_MANAGER_MT_H
-#define BT_SIMULATION_ISLAND_MANAGER_MT_H
-
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-
-class btTypedConstraint;
-class btConstraintSolver;
-struct btContactSolverInfo;
-class btIDebugDraw;
-
-///
-/// SimulationIslandManagerMt -- Multithread capable version of SimulationIslandManager
-/// Splits the world up into islands which can be solved in parallel.
-/// In order to solve islands in parallel, an IslandDispatch function
-/// must be provided which will dispatch calls to multiple threads.
-/// The amount of parallelism that can be achieved depends on the number
-/// of islands. If only a single island exists, then no parallelism is
-/// possible.
-///
-class btSimulationIslandManagerMt : public btSimulationIslandManager
-{
-public:
- struct Island
- {
- // a simulation island consisting of bodies, manifolds and constraints,
- // to be passed into a constraint solver.
- btAlignedObjectArray<btCollisionObject*> bodyArray;
- btAlignedObjectArray<btPersistentManifold*> manifoldArray;
- btAlignedObjectArray<btTypedConstraint*> constraintArray;
- int id; // island id
- bool isSleeping;
-
- void append(const Island& other); // add bodies, manifolds, constraints to my own
- };
- struct SolverParams
- {
- btConstraintSolver* m_solverPool;
- btConstraintSolver* m_solverMt;
- btContactSolverInfo* m_solverInfo;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
- };
- static void solveIsland(btConstraintSolver* solver, Island& island, const SolverParams& solverParams);
-
- typedef void (*IslandDispatchFunc)(btAlignedObjectArray<Island*>* islands, const SolverParams& solverParams);
- static void serialIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
- static void parallelIslandDispatch(btAlignedObjectArray<Island*>* islandsPtr, const SolverParams& solverParams);
-
-protected:
- btAlignedObjectArray<Island*> m_allocatedIslands; // owner of all Islands
- btAlignedObjectArray<Island*> m_activeIslands; // islands actively in use
- btAlignedObjectArray<Island*> m_freeIslands; // islands ready to be reused
- btAlignedObjectArray<Island*> m_lookupIslandFromId; // big lookup table to map islandId to Island pointer
- Island* m_batchIsland;
- int m_minimumSolverBatchSize;
- int m_batchIslandMinBodyCount;
- IslandDispatchFunc m_islandDispatch;
-
- Island* getIsland(int id);
- virtual Island* allocateIsland(int id, int numBodies);
- virtual void initIslandPools();
- virtual void addBodiesToIslands(btCollisionWorld* collisionWorld);
- virtual void addManifoldsToIslands(btDispatcher* dispatcher);
- virtual void addConstraintsToIslands(btAlignedObjectArray<btTypedConstraint*>& constraints);
- virtual void mergeIslands();
-
-public:
- btSimulationIslandManagerMt();
- virtual ~btSimulationIslandManagerMt();
-
- virtual void buildAndProcessIslands(btDispatcher* dispatcher,
- btCollisionWorld* collisionWorld,
- btAlignedObjectArray<btTypedConstraint*>& constraints,
- const SolverParams& solverParams);
-
- virtual void buildIslands(btDispatcher* dispatcher, btCollisionWorld* colWorld);
-
- int getMinimumSolverBatchSize() const
- {
- return m_minimumSolverBatchSize;
- }
- void setMinimumSolverBatchSize(int sz)
- {
- m_minimumSolverBatchSize = sz;
- }
- IslandDispatchFunc getIslandDispatchFunction() const
- {
- return m_islandDispatch;
- }
- // allow users to set their own dispatch function for multithreaded dispatch
- void setIslandDispatchFunction(IslandDispatchFunc func)
- {
- m_islandDispatch = func;
- }
-};
-
-#endif //BT_SIMULATION_ISLAND_MANAGER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
deleted file mode 100644
index d7588aedc8..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.cpp
+++ /dev/null
@@ -1,2461 +0,0 @@
-/*
- * PURPOSE:
- * Class representing an articulated rigid body. Stores the body's
- * current state, allows forces and torques to be set, handles
- * timestepping and implements Featherstone's algorithm.
- *
- * COPYRIGHT:
- * Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
- * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
- * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
-
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- */
-
-#include "btMultiBody.h"
-#include "btMultiBodyLink.h"
-#include "btMultiBodyLinkCollider.h"
-#include "btMultiBodyJointFeedback.h"
-#include "LinearMath/btTransformUtil.h"
-#include "LinearMath/btSerializer.h"
-//#include "Bullet3Common/b3Logging.h"
-// #define INCLUDE_GYRO_TERM
-
-
-namespace
-{
-const btScalar INITIAL_SLEEP_EPSILON = btScalar(0.05); // this is a squared velocity (m^2 s^-2)
-const btScalar INITIAL_SLEEP_TIMEOUT = btScalar(2); // in seconds
-} // namespace
-
-void btMultiBody::spatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
- const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
- const btVector3 &top_in, // top part of input vector
- const btVector3 &bottom_in, // bottom part of input vector
- btVector3 &top_out, // top part of output vector
- btVector3 &bottom_out) // bottom part of output vector
-{
- top_out = rotation_matrix * top_in;
- bottom_out = -displacement.cross(top_out) + rotation_matrix * bottom_in;
-}
-
-namespace
-{
-
-
-#if 0
- void InverseSpatialTransform(const btMatrix3x3 &rotation_matrix,
- const btVector3 &displacement,
- const btVector3 &top_in,
- const btVector3 &bottom_in,
- btVector3 &top_out,
- btVector3 &bottom_out)
- {
- top_out = rotation_matrix.transpose() * top_in;
- bottom_out = rotation_matrix.transpose() * (bottom_in + displacement.cross(top_in));
- }
-
- btScalar SpatialDotProduct(const btVector3 &a_top,
- const btVector3 &a_bottom,
- const btVector3 &b_top,
- const btVector3 &b_bottom)
- {
- return a_bottom.dot(b_top) + a_top.dot(b_bottom);
- }
-
- void SpatialCrossProduct(const btVector3 &a_top,
- const btVector3 &a_bottom,
- const btVector3 &b_top,
- const btVector3 &b_bottom,
- btVector3 &top_out,
- btVector3 &bottom_out)
- {
- top_out = a_top.cross(b_top);
- bottom_out = a_bottom.cross(b_top) + a_top.cross(b_bottom);
- }
-#endif
-
-} // namespace
-
-//
-// Implementation of class btMultiBody
-//
-
-btMultiBody::btMultiBody(int n_links,
- btScalar mass,
- const btVector3 &inertia,
- bool fixedBase,
- bool canSleep,
- bool /*deprecatedUseMultiDof*/)
- : m_baseCollider(0),
- m_baseName(0),
- m_basePos(0, 0, 0),
- m_baseQuat(0, 0, 0, 1),
- m_basePos_interpolate(0, 0, 0),
- m_baseQuat_interpolate(0, 0, 0, 1),
- m_baseMass(mass),
- m_baseInertia(inertia),
-
- m_fixedBase(fixedBase),
- m_awake(true),
- m_canSleep(canSleep),
- m_canWakeup(true),
- m_sleepTimer(0),
- m_sleepEpsilon(INITIAL_SLEEP_EPSILON),
- m_sleepTimeout(INITIAL_SLEEP_TIMEOUT),
-
- m_userObjectPointer(0),
- m_userIndex2(-1),
- m_userIndex(-1),
- m_companionId(-1),
- m_linearDamping(0.04f),
- m_angularDamping(0.04f),
- m_useGyroTerm(true),
- m_maxAppliedImpulse(1000.f),
- m_maxCoordinateVelocity(100.f),
- m_hasSelfCollision(true),
- __posUpdated(false),
- m_dofCount(0),
- m_posVarCnt(0),
- m_useRK4(false),
- m_useGlobalVelocities(false),
- m_internalNeedsJointFeedback(false),
- m_kinematic_calculate_velocity(false)
-{
- m_cachedInertiaTopLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- m_cachedInertiaTopRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- m_cachedInertiaLowerLeft.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- m_cachedInertiaLowerRight.setValue(0, 0, 0, 0, 0, 0, 0, 0, 0);
- m_cachedInertiaValid = false;
-
- m_links.resize(n_links);
- m_matrixBuf.resize(n_links + 1);
-
- m_baseForce.setValue(0, 0, 0);
- m_baseTorque.setValue(0, 0, 0);
-
- clearConstraintForces();
- clearForcesAndTorques();
-}
-
-btMultiBody::~btMultiBody()
-{
-}
-
-void btMultiBody::setupFixed(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset, bool /*deprecatedDisableParentCollision*/)
-{
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].setAxisTop(0, 0., 0., 0.);
- m_links[i].setAxisBottom(0, btVector3(0, 0, 0));
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
-
- m_links[i].m_jointType = btMultibodyLink::eFixed;
- m_links[i].m_dofCount = 0;
- m_links[i].m_posVarCount = 0;
-
- m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
-
- m_links[i].updateCacheMultiDof();
-
- updateLinksDofOffsets();
-}
-
-void btMultiBody::setupPrismatic(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
-{
- m_dofCount += 1;
- m_posVarCnt += 1;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].setAxisTop(0, 0., 0., 0.);
- m_links[i].setAxisBottom(0, jointAxis);
- m_links[i].m_eVector = parentComToThisPivotOffset;
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_cachedRotParentToThis = rotParentToThis;
-
- m_links[i].m_jointType = btMultibodyLink::ePrismatic;
- m_links[i].m_dofCount = 1;
- m_links[i].m_posVarCount = 1;
- m_links[i].m_jointPos[0] = 0.f;
- m_links[i].m_jointTorque[0] = 0.f;
-
- if (disableParentCollision)
- m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
-
- m_links[i].updateCacheMultiDof();
-
- updateLinksDofOffsets();
-}
-
-void btMultiBody::setupRevolute(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
-{
- m_dofCount += 1;
- m_posVarCnt += 1;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].setAxisTop(0, jointAxis);
- m_links[i].setAxisBottom(0, jointAxis.cross(thisPivotToThisComOffset));
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
-
- m_links[i].m_jointType = btMultibodyLink::eRevolute;
- m_links[i].m_dofCount = 1;
- m_links[i].m_posVarCount = 1;
- m_links[i].m_jointPos[0] = 0.f;
- m_links[i].m_jointTorque[0] = 0.f;
-
- if (disableParentCollision)
- m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
- m_links[i].updateCacheMultiDof();
- //
- updateLinksDofOffsets();
-}
-
-void btMultiBody::setupSpherical(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision)
-{
- m_dofCount += 3;
- m_posVarCnt += 4;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].m_dVector = thisPivotToThisComOffset;
- m_links[i].m_eVector = parentComToThisPivotOffset;
-
- m_links[i].m_jointType = btMultibodyLink::eSpherical;
- m_links[i].m_dofCount = 3;
- m_links[i].m_posVarCount = 4;
- m_links[i].setAxisTop(0, 1.f, 0.f, 0.f);
- m_links[i].setAxisTop(1, 0.f, 1.f, 0.f);
- m_links[i].setAxisTop(2, 0.f, 0.f, 1.f);
- m_links[i].setAxisBottom(0, m_links[i].getAxisTop(0).cross(thisPivotToThisComOffset));
- m_links[i].setAxisBottom(1, m_links[i].getAxisTop(1).cross(thisPivotToThisComOffset));
- m_links[i].setAxisBottom(2, m_links[i].getAxisTop(2).cross(thisPivotToThisComOffset));
- m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
- m_links[i].m_jointPos[3] = 1.f;
- m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
-
- if (disableParentCollision)
- m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
- m_links[i].updateCacheMultiDof();
- //
- updateLinksDofOffsets();
-}
-
-void btMultiBody::setupPlanar(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &rotationAxis,
- const btVector3 &parentComToThisComOffset,
- bool disableParentCollision)
-{
- m_dofCount += 3;
- m_posVarCnt += 3;
-
- m_links[i].m_mass = mass;
- m_links[i].m_inertiaLocal = inertia;
- m_links[i].m_parent = parent;
- m_links[i].m_zeroRotParentToThis = rotParentToThis;
- m_links[i].m_dVector.setZero();
- m_links[i].m_eVector = parentComToThisComOffset;
-
- //
- btVector3 vecNonParallelToRotAxis(1, 0, 0);
- if (rotationAxis.normalized().dot(vecNonParallelToRotAxis) > 0.999)
- vecNonParallelToRotAxis.setValue(0, 1, 0);
- //
-
- m_links[i].m_jointType = btMultibodyLink::ePlanar;
- m_links[i].m_dofCount = 3;
- m_links[i].m_posVarCount = 3;
- btVector3 n = rotationAxis.normalized();
- m_links[i].setAxisTop(0, n[0], n[1], n[2]);
- m_links[i].setAxisTop(1, 0, 0, 0);
- m_links[i].setAxisTop(2, 0, 0, 0);
- m_links[i].setAxisBottom(0, 0, 0, 0);
- btVector3 cr = m_links[i].getAxisTop(0).cross(vecNonParallelToRotAxis);
- m_links[i].setAxisBottom(1, cr[0], cr[1], cr[2]);
- cr = m_links[i].getAxisBottom(1).cross(m_links[i].getAxisTop(0));
- m_links[i].setAxisBottom(2, cr[0], cr[1], cr[2]);
- m_links[i].m_jointPos[0] = m_links[i].m_jointPos[1] = m_links[i].m_jointPos[2] = 0.f;
- m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = 0.f;
-
- if (disableParentCollision)
- m_links[i].m_flags |= BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION;
- //
- m_links[i].updateCacheMultiDof();
- //
- updateLinksDofOffsets();
-
- m_links[i].setAxisBottom(1, m_links[i].getAxisBottom(1).normalized());
- m_links[i].setAxisBottom(2, m_links[i].getAxisBottom(2).normalized());
-}
-
-void btMultiBody::finalizeMultiDof()
-{
- m_deltaV.resize(0);
- m_deltaV.resize(6 + m_dofCount);
- m_splitV.resize(0);
- m_splitV.resize(6 + m_dofCount);
- m_realBuf.resize(6 + m_dofCount + m_dofCount * m_dofCount + 6 + m_dofCount); //m_dofCount for joint-space vels + m_dofCount^2 for "D" matrices + delta-pos vector (6 base "vels" + joint "vels")
- m_vectorBuf.resize(2 * m_dofCount); //two 3-vectors (i.e. one six-vector) for each system dof ("h" matrices)
- m_matrixBuf.resize(m_links.size() + 1);
- for (int i = 0; i < m_vectorBuf.size(); i++)
- {
- m_vectorBuf[i].setValue(0, 0, 0);
- }
- updateLinksDofOffsets();
-}
-
-int btMultiBody::getParent(int link_num) const
-{
- return m_links[link_num].m_parent;
-}
-
-btScalar btMultiBody::getLinkMass(int i) const
-{
- return m_links[i].m_mass;
-}
-
-const btVector3 &btMultiBody::getLinkInertia(int i) const
-{
- return m_links[i].m_inertiaLocal;
-}
-
-btScalar btMultiBody::getJointPos(int i) const
-{
- return m_links[i].m_jointPos[0];
-}
-
-btScalar btMultiBody::getJointVel(int i) const
-{
- return m_realBuf[6 + m_links[i].m_dofOffset];
-}
-
-btScalar *btMultiBody::getJointPosMultiDof(int i)
-{
- return &m_links[i].m_jointPos[0];
-}
-
-btScalar *btMultiBody::getJointVelMultiDof(int i)
-{
- return &m_realBuf[6 + m_links[i].m_dofOffset];
-}
-
-const btScalar *btMultiBody::getJointPosMultiDof(int i) const
-{
- return &m_links[i].m_jointPos[0];
-}
-
-const btScalar *btMultiBody::getJointVelMultiDof(int i) const
-{
- return &m_realBuf[6 + m_links[i].m_dofOffset];
-}
-
-void btMultiBody::setJointPos(int i, btScalar q)
-{
- m_links[i].m_jointPos[0] = q;
- m_links[i].updateCacheMultiDof();
-}
-
-
-void btMultiBody::setJointPosMultiDof(int i, const double *q)
-{
- for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
- m_links[i].m_jointPos[pos] = (btScalar)q[pos];
-
- m_links[i].updateCacheMultiDof();
-}
-
-void btMultiBody::setJointPosMultiDof(int i, const float *q)
-{
- for (int pos = 0; pos < m_links[i].m_posVarCount; ++pos)
- m_links[i].m_jointPos[pos] = (btScalar)q[pos];
-
- m_links[i].updateCacheMultiDof();
-}
-
-
-
-void btMultiBody::setJointVel(int i, btScalar qdot)
-{
- m_realBuf[6 + m_links[i].m_dofOffset] = qdot;
-}
-
-void btMultiBody::setJointVelMultiDof(int i, const double *qdot)
-{
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
-}
-
-void btMultiBody::setJointVelMultiDof(int i, const float* qdot)
-{
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- m_realBuf[6 + m_links[i].m_dofOffset + dof] = (btScalar)qdot[dof];
-}
-
-const btVector3 &btMultiBody::getRVector(int i) const
-{
- return m_links[i].m_cachedRVector;
-}
-
-const btQuaternion &btMultiBody::getParentToLocalRot(int i) const
-{
- return m_links[i].m_cachedRotParentToThis;
-}
-
-const btVector3 &btMultiBody::getInterpolateRVector(int i) const
-{
- return m_links[i].m_cachedRVector_interpolate;
-}
-
-const btQuaternion &btMultiBody::getInterpolateParentToLocalRot(int i) const
-{
- return m_links[i].m_cachedRotParentToThis_interpolate;
-}
-
-btVector3 btMultiBody::localPosToWorld(int i, const btVector3 &local_pos) const
-{
- btAssert(i >= -1);
- btAssert(i < m_links.size());
- if ((i < -1) || (i >= m_links.size()))
- {
- return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
- }
-
- btVector3 result = local_pos;
- while (i != -1)
- {
- // 'result' is in frame i. transform it to frame parent(i)
- result += getRVector(i);
- result = quatRotate(getParentToLocalRot(i).inverse(), result);
- i = getParent(i);
- }
-
- // 'result' is now in the base frame. transform it to world frame
- result = quatRotate(getWorldToBaseRot().inverse(), result);
- result += getBasePos();
-
- return result;
-}
-
-btVector3 btMultiBody::worldPosToLocal(int i, const btVector3 &world_pos) const
-{
- btAssert(i >= -1);
- btAssert(i < m_links.size());
- if ((i < -1) || (i >= m_links.size()))
- {
- return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
- }
-
- if (i == -1)
- {
- // world to base
- return quatRotate(getWorldToBaseRot(), (world_pos - getBasePos()));
- }
- else
- {
- // find position in parent frame, then transform to current frame
- return quatRotate(getParentToLocalRot(i), worldPosToLocal(getParent(i), world_pos)) - getRVector(i);
- }
-}
-
-btVector3 btMultiBody::localDirToWorld(int i, const btVector3 &local_dir) const
-{
- btAssert(i >= -1);
- btAssert(i < m_links.size());
- if ((i < -1) || (i >= m_links.size()))
- {
- return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
- }
-
- btVector3 result = local_dir;
- while (i != -1)
- {
- result = quatRotate(getParentToLocalRot(i).inverse(), result);
- i = getParent(i);
- }
- result = quatRotate(getWorldToBaseRot().inverse(), result);
- return result;
-}
-
-btVector3 btMultiBody::worldDirToLocal(int i, const btVector3 &world_dir) const
-{
- btAssert(i >= -1);
- btAssert(i < m_links.size());
- if ((i < -1) || (i >= m_links.size()))
- {
- return btVector3(SIMD_INFINITY, SIMD_INFINITY, SIMD_INFINITY);
- }
-
- if (i == -1)
- {
- return quatRotate(getWorldToBaseRot(), world_dir);
- }
- else
- {
- return quatRotate(getParentToLocalRot(i), worldDirToLocal(getParent(i), world_dir));
- }
-}
-
-btMatrix3x3 btMultiBody::localFrameToWorld(int i, const btMatrix3x3 &local_frame) const
-{
- btMatrix3x3 result = local_frame;
- btVector3 frameInWorld0 = localDirToWorld(i, local_frame.getColumn(0));
- btVector3 frameInWorld1 = localDirToWorld(i, local_frame.getColumn(1));
- btVector3 frameInWorld2 = localDirToWorld(i, local_frame.getColumn(2));
- result.setValue(frameInWorld0[0], frameInWorld1[0], frameInWorld2[0], frameInWorld0[1], frameInWorld1[1], frameInWorld2[1], frameInWorld0[2], frameInWorld1[2], frameInWorld2[2]);
- return result;
-}
-
-void btMultiBody::compTreeLinkVelocities(btVector3 *omega, btVector3 *vel) const
-{
- int num_links = getNumLinks();
- // Calculates the velocities of each link (and the base) in its local frame
- const btQuaternion& base_rot = getWorldToBaseRot();
- omega[0] = quatRotate(base_rot, getBaseOmega());
- vel[0] = quatRotate(base_rot, getBaseVel());
-
- for (int i = 0; i < num_links; ++i)
- {
- const btMultibodyLink& link = getLink(i);
- const int parent = link.m_parent;
-
- // transform parent vel into this frame, store in omega[i+1], vel[i+1]
- spatialTransform(btMatrix3x3(link.m_cachedRotParentToThis), link.m_cachedRVector,
- omega[parent + 1], vel[parent + 1],
- omega[i + 1], vel[i + 1]);
-
- // now add qidot * shat_i
- const btScalar* jointVel = getJointVelMultiDof(i);
- for (int dof = 0; dof < link.m_dofCount; ++dof)
- {
- omega[i + 1] += jointVel[dof] * link.getAxisTop(dof);
- vel[i + 1] += jointVel[dof] * link.getAxisBottom(dof);
- }
- }
-}
-
-
-void btMultiBody::clearConstraintForces()
-{
- m_baseConstraintForce.setValue(0, 0, 0);
- m_baseConstraintTorque.setValue(0, 0, 0);
-
- for (int i = 0; i < getNumLinks(); ++i)
- {
- m_links[i].m_appliedConstraintForce.setValue(0, 0, 0);
- m_links[i].m_appliedConstraintTorque.setValue(0, 0, 0);
- }
-}
-void btMultiBody::clearForcesAndTorques()
-{
- m_baseForce.setValue(0, 0, 0);
- m_baseTorque.setValue(0, 0, 0);
-
- for (int i = 0; i < getNumLinks(); ++i)
- {
- m_links[i].m_appliedForce.setValue(0, 0, 0);
- m_links[i].m_appliedTorque.setValue(0, 0, 0);
- m_links[i].m_jointTorque[0] = m_links[i].m_jointTorque[1] = m_links[i].m_jointTorque[2] = m_links[i].m_jointTorque[3] = m_links[i].m_jointTorque[4] = m_links[i].m_jointTorque[5] = 0.f;
- }
-}
-
-void btMultiBody::clearVelocities()
-{
- for (int i = 0; i < 6 + getNumDofs(); ++i)
- {
- m_realBuf[i] = 0.f;
- }
-}
-void btMultiBody::addLinkForce(int i, const btVector3 &f)
-{
- m_links[i].m_appliedForce += f;
-}
-
-void btMultiBody::addLinkTorque(int i, const btVector3 &t)
-{
- m_links[i].m_appliedTorque += t;
-}
-
-void btMultiBody::addLinkConstraintForce(int i, const btVector3 &f)
-{
- m_links[i].m_appliedConstraintForce += f;
-}
-
-void btMultiBody::addLinkConstraintTorque(int i, const btVector3 &t)
-{
- m_links[i].m_appliedConstraintTorque += t;
-}
-
-void btMultiBody::addJointTorque(int i, btScalar Q)
-{
- m_links[i].m_jointTorque[0] += Q;
-}
-
-void btMultiBody::addJointTorqueMultiDof(int i, int dof, btScalar Q)
-{
- m_links[i].m_jointTorque[dof] += Q;
-}
-
-void btMultiBody::addJointTorqueMultiDof(int i, const btScalar *Q)
-{
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- m_links[i].m_jointTorque[dof] = Q[dof];
-}
-
-const btVector3 &btMultiBody::getLinkForce(int i) const
-{
- return m_links[i].m_appliedForce;
-}
-
-const btVector3 &btMultiBody::getLinkTorque(int i) const
-{
- return m_links[i].m_appliedTorque;
-}
-
-btScalar btMultiBody::getJointTorque(int i) const
-{
- return m_links[i].m_jointTorque[0];
-}
-
-btScalar *btMultiBody::getJointTorqueMultiDof(int i)
-{
- return &m_links[i].m_jointTorque[0];
-}
-
-bool btMultiBody::hasFixedBase() const
-{
- return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticObject());
-}
-
-bool btMultiBody::isBaseStaticOrKinematic() const
-{
- return m_fixedBase || (getBaseCollider() && getBaseCollider()->isStaticOrKinematicObject());
-}
-
-bool btMultiBody::isBaseKinematic() const
-{
- return getBaseCollider() && getBaseCollider()->isKinematicObject();
-}
-
-void btMultiBody::setBaseDynamicType(int dynamicType)
-{
- if(getBaseCollider()) {
- int oldFlags = getBaseCollider()->getCollisionFlags();
- oldFlags &= ~(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
- getBaseCollider()->setCollisionFlags(oldFlags | dynamicType);
- }
-}
-
-inline btMatrix3x3 outerProduct(const btVector3 &v0, const btVector3 &v1) //renamed it from vecMulVecTranspose (http://en.wikipedia.org/wiki/Outer_product); maybe it should be moved to btVector3 like dot and cross?
-{
- btVector3 row0 = btVector3(
- v0.x() * v1.x(),
- v0.x() * v1.y(),
- v0.x() * v1.z());
- btVector3 row1 = btVector3(
- v0.y() * v1.x(),
- v0.y() * v1.y(),
- v0.y() * v1.z());
- btVector3 row2 = btVector3(
- v0.z() * v1.x(),
- v0.z() * v1.y(),
- v0.z() * v1.z());
-
- btMatrix3x3 m(row0[0], row0[1], row0[2],
- row1[0], row1[1], row1[2],
- row2[0], row2[1], row2[2]);
- return m;
-}
-
-#define vecMulVecTranspose(v0, v1Transposed) outerProduct(v0, v1Transposed)
-//
-
-void btMultiBody::computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m,
- bool isConstraintPass,
- bool jointFeedbackInWorldSpace,
- bool jointFeedbackInJointFrame)
-{
- // Implement Featherstone's algorithm to calculate joint accelerations (q_double_dot)
- // and the base linear & angular accelerations.
-
- // We apply damping forces in this routine as well as any external forces specified by the
- // caller (via addBaseForce etc).
-
- // output should point to an array of 6 + num_links reals.
- // Format is: 3 angular accelerations (in world frame), 3 linear accelerations (in world frame),
- // num_links joint acceleration values.
-
- // We added support for multi degree of freedom (multi dof) joints.
- // In addition we also can compute the joint reaction forces. This is performed in a second pass,
- // so that we can include the effect of the constraint solver forces (computed in the PGS LCP solver)
-
- m_internalNeedsJointFeedback = false;
-
- int num_links = getNumLinks();
-
- const btScalar DAMPING_K1_LINEAR = m_linearDamping;
- const btScalar DAMPING_K2_LINEAR = m_linearDamping;
-
- const btScalar DAMPING_K1_ANGULAR = m_angularDamping;
- const btScalar DAMPING_K2_ANGULAR = m_angularDamping;
-
- const btVector3 base_vel = getBaseVel();
- const btVector3 base_omega = getBaseOmega();
-
- // Temporary matrices/vectors -- use scratch space from caller
- // so that we don't have to keep reallocating every frame
-
- scratch_r.resize(2 * m_dofCount + 7); //multidof? ("Y"s use it and it is used to store qdd) => 2 x m_dofCount
- scratch_v.resize(8 * num_links + 6);
- scratch_m.resize(4 * num_links + 4);
-
- //btScalar * r_ptr = &scratch_r[0];
- btScalar *output = &scratch_r[m_dofCount]; // "output" holds the q_double_dot results
- btVector3 *v_ptr = &scratch_v[0];
-
- // vhat_i (top = angular, bottom = linear part)
- btSpatialMotionVector *spatVel = (btSpatialMotionVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
- //
- // zhat_i^A
- btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
- //
- // chat_i (note NOT defined for the base)
- btSpatialMotionVector *spatCoriolisAcc = (btSpatialMotionVector *)v_ptr;
- v_ptr += num_links * 2;
- //
- // Ihat_i^A.
- btSymmetricSpatialDyad *spatInertia = (btSymmetricSpatialDyad *)&scratch_m[num_links + 1];
-
- // Cached 3x3 rotation matrices from parent frame to this frame.
- btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
- btMatrix3x3 *rot_from_world = &scratch_m[0];
-
- // hhat_i, ahat_i
- // hhat is NOT stored for the base (but ahat is)
- btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
- btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
- //
- // Y_i, invD_i
- btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
- btScalar *Y = &scratch_r[0];
- //
- //aux variables
- btSpatialMotionVector spatJointVel; //spatial velocity due to the joint motion (i.e. without predecessors' influence)
- btScalar D[36]; //"D" matrix; it's dofxdof for each body so asingle 6x6 D matrix will do
- btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
- btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
- btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
- btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
- btSpatialTransformationMatrix fromParent; //spatial transform from parent to child
- btSymmetricSpatialDyad dyadTemp; //inertia matrix temp
- btSpatialTransformationMatrix fromWorld;
- fromWorld.m_trnVec.setZero();
- /////////////////
-
- // ptr to the joint accel part of the output
- btScalar *joint_accel = output + 6;
-
- // Start of the algorithm proper.
-
- // First 'upward' loop.
- // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
-
- rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
-
- //create the vector of spatial velocity of the base by transforming global-coor linear and angular velocities into base-local coordinates
- spatVel[0].setVector(rot_from_parent[0] * base_omega, rot_from_parent[0] * base_vel);
-
- if (isBaseStaticOrKinematic())
- {
- zeroAccSpatFrc[0].setZero();
- }
- else
- {
- const btVector3 &baseForce = isConstraintPass ? m_baseConstraintForce : m_baseForce;
- const btVector3 &baseTorque = isConstraintPass ? m_baseConstraintTorque : m_baseTorque;
- //external forces
- zeroAccSpatFrc[0].setVector(-(rot_from_parent[0] * baseTorque), -(rot_from_parent[0] * baseForce));
-
- //adding damping terms (only)
- const btScalar linDampMult = 1., angDampMult = 1.;
- zeroAccSpatFrc[0].addVector(angDampMult * m_baseInertia * spatVel[0].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[0].getAngular().safeNorm()),
- linDampMult * m_baseMass * spatVel[0].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[0].getLinear().safeNorm()));
-
- //
- //p += vhat x Ihat vhat - done in a simpler way
- if (m_useGyroTerm)
- zeroAccSpatFrc[0].addAngular(spatVel[0].getAngular().cross(m_baseInertia * spatVel[0].getAngular()));
- //
- zeroAccSpatFrc[0].addLinear(m_baseMass * spatVel[0].getAngular().cross(spatVel[0].getLinear()));
- }
-
- //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
- spatInertia[0].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
- //
- btMatrix3x3(m_baseMass, 0, 0,
- 0, m_baseMass, 0,
- 0, 0, m_baseMass),
- //
- btMatrix3x3(m_baseInertia[0], 0, 0,
- 0, m_baseInertia[1], 0,
- 0, 0, m_baseInertia[2]));
-
- rot_from_world[0] = rot_from_parent[0];
-
- //
- for (int i = 0; i < num_links; ++i)
- {
- const int parent = m_links[i].m_parent;
- rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
- rot_from_world[i + 1] = rot_from_parent[i + 1] * rot_from_world[parent + 1];
-
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
- fromWorld.m_rotMat = rot_from_world[i + 1];
- fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
-
- // now set vhat_i to its true value by doing
- // vhat_i += qidot * shat_i
- if (!m_useGlobalVelocities)
- {
- spatJointVel.setZero();
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
-
- // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
- spatVel[i + 1] += spatJointVel;
-
- //
- // vhat_i is vhat_p(i) transformed to local coors + the velocity across the i-th inboard joint
- //spatVel[i+1] = fromParent * spatVel[parent+1] + spatJointVel;
- }
- else
- {
- fromWorld.transformRotationOnly(m_links[i].m_absFrameTotVelocity, spatVel[i + 1]);
- fromWorld.transformRotationOnly(m_links[i].m_absFrameLocVelocity, spatJointVel);
- }
-
- // we can now calculate chat_i
- spatVel[i + 1].cross(spatJointVel, spatCoriolisAcc[i]);
-
- // calculate zhat_i^A
- //
- if (isLinkAndAllAncestorsKinematic(i))
- {
- zeroAccSpatFrc[i].setZero();
- }
- else{
- //external forces
- btVector3 linkAppliedForce = isConstraintPass ? m_links[i].m_appliedConstraintForce : m_links[i].m_appliedForce;
- btVector3 linkAppliedTorque = isConstraintPass ? m_links[i].m_appliedConstraintTorque : m_links[i].m_appliedTorque;
-
- zeroAccSpatFrc[i + 1].setVector(-(rot_from_world[i + 1] * linkAppliedTorque), -(rot_from_world[i + 1] * linkAppliedForce));
-
-#if 0
- {
-
- b3Printf("stepVelocitiesMultiDof zeroAccSpatFrc[%d] linear:%f,%f,%f, angular:%f,%f,%f",
- i+1,
- zeroAccSpatFrc[i+1].m_topVec[0],
- zeroAccSpatFrc[i+1].m_topVec[1],
- zeroAccSpatFrc[i+1].m_topVec[2],
-
- zeroAccSpatFrc[i+1].m_bottomVec[0],
- zeroAccSpatFrc[i+1].m_bottomVec[1],
- zeroAccSpatFrc[i+1].m_bottomVec[2]);
- }
-#endif
- //
- //adding damping terms (only)
- btScalar linDampMult = 1., angDampMult = 1.;
- zeroAccSpatFrc[i + 1].addVector(angDampMult * m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular() * (DAMPING_K1_ANGULAR + DAMPING_K2_ANGULAR * spatVel[i + 1].getAngular().safeNorm()),
- linDampMult * m_links[i].m_mass * spatVel[i + 1].getLinear() * (DAMPING_K1_LINEAR + DAMPING_K2_LINEAR * spatVel[i + 1].getLinear().safeNorm()));
- //p += vhat x Ihat vhat - done in a simpler way
- if (m_useGyroTerm)
- zeroAccSpatFrc[i + 1].addAngular(spatVel[i + 1].getAngular().cross(m_links[i].m_inertiaLocal * spatVel[i + 1].getAngular()));
- //
- zeroAccSpatFrc[i + 1].addLinear(m_links[i].m_mass * spatVel[i + 1].getAngular().cross(spatVel[i + 1].getLinear()));
- //
- //btVector3 temp = m_links[i].m_mass * spatVel[i+1].getAngular().cross(spatVel[i+1].getLinear());
- ////clamp parent's omega
- //btScalar parOmegaMod = temp.length();
- //btScalar parOmegaModMax = 1000;
- //if(parOmegaMod > parOmegaModMax)
- // temp *= parOmegaModMax / parOmegaMod;
- //zeroAccSpatFrc[i+1].addLinear(temp);
- //printf("|zeroAccSpatFrc[%d]| = %.4f\n", i+1, temp.length());
- //temp = spatCoriolisAcc[i].getLinear();
- //printf("|spatCoriolisAcc[%d]| = %.4f\n", i+1, temp.length());
- }
-
- // calculate Ihat_i^A
- //init the spatial AB inertia (it has the simple form thanks to choosing local body frames origins at their COMs)
- spatInertia[i + 1].setMatrix(btMatrix3x3(0, 0, 0, 0, 0, 0, 0, 0, 0),
- //
- btMatrix3x3(m_links[i].m_mass, 0, 0,
- 0, m_links[i].m_mass, 0,
- 0, 0, m_links[i].m_mass),
- //
- btMatrix3x3(m_links[i].m_inertiaLocal[0], 0, 0,
- 0, m_links[i].m_inertiaLocal[1], 0,
- 0, 0, m_links[i].m_inertiaLocal[2]));
-
- //printf("w[%d] = [%.4f %.4f %.4f]\n", i, vel_top_angular[i+1].x(), vel_top_angular[i+1].y(), vel_top_angular[i+1].z());
- //printf("v[%d] = [%.4f %.4f %.4f]\n", i, vel_bottom_linear[i+1].x(), vel_bottom_linear[i+1].y(), vel_bottom_linear[i+1].z());
- //printf("c[%d] = [%.4f %.4f %.4f]\n", i, coriolis_bottom_linear[i].x(), coriolis_bottom_linear[i].y(), coriolis_bottom_linear[i].z());
- }
-
- // 'Downward' loop.
- // (part of TreeForwardDynamics in Mirtich.)
- for (int i = num_links - 1; i >= 0; --i)
- {
- if(isLinkAndAllAncestorsKinematic(i))
- continue;
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- hDof = spatInertia[i + 1] * m_links[i].m_axes[dof];
- //
- Y[m_links[i].m_dofOffset + dof] = m_links[i].m_jointTorque[dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]) - spatCoriolisAcc[i].dot(hDof);
- }
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- btScalar *D_row = &D[dof * m_links[i].m_dofCount];
- for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
- {
- const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
- D_row[dof2] = m_links[i].m_axes[dof].dot(hDof2);
- }
- }
-
- btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
- switch (m_links[i].m_jointType)
- {
- case btMultibodyLink::ePrismatic:
- case btMultibodyLink::eRevolute:
- {
- if (D[0] >= SIMD_EPSILON)
- {
- invDi[0] = 1.0f / D[0];
- }
- else
- {
- invDi[0] = 0;
- }
- break;
- }
- case btMultibodyLink::eSpherical:
- case btMultibodyLink::ePlanar:
- {
- const btMatrix3x3 D3x3(D[0], D[1], D[2], D[3], D[4], D[5], D[6], D[7], D[8]);
- const btMatrix3x3 invD3x3(D3x3.inverse());
-
- //unroll the loop?
- for (int row = 0; row < 3; ++row)
- {
- for (int col = 0; col < 3; ++col)
- {
- invDi[row * 3 + col] = invD3x3[row][col];
- }
- }
-
- break;
- }
- default:
- {
- }
- }
-
- //determine h*D^{-1}
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- spatForceVecTemps[dof].setZero();
-
- for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
- {
- const btSpatialForceVector &hDof2 = h[m_links[i].m_dofOffset + dof2];
- //
- spatForceVecTemps[dof] += hDof2 * invDi[dof2 * m_links[i].m_dofCount + dof];
- }
- }
-
- dyadTemp = spatInertia[i + 1];
-
- //determine (h*D^{-1}) * h^{T}
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- dyadTemp -= symmetricSpatialOuterProduct(hDof, spatForceVecTemps[dof]);
- }
-
- fromParent.transformInverse(dyadTemp, spatInertia[parent + 1], btSpatialTransformationMatrix::Add);
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- invD_times_Y[dof] = 0.f;
-
- for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
- {
- invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
- }
- }
-
- spatForceVecTemps[0] = zeroAccSpatFrc[i + 1] + spatInertia[i + 1] * spatCoriolisAcc[i];
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- spatForceVecTemps[0] += hDof * invD_times_Y[dof];
- }
-
- fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
-
- zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
- }
-
- // Second 'upward' loop
- // (part of TreeForwardDynamics in Mirtich)
-
- if (isBaseStaticOrKinematic())
- {
- spatAcc[0].setZero();
- }
- else
- {
- if (num_links > 0)
- {
- m_cachedInertiaValid = true;
- m_cachedInertiaTopLeft = spatInertia[0].m_topLeftMat;
- m_cachedInertiaTopRight = spatInertia[0].m_topRightMat;
- m_cachedInertiaLowerLeft = spatInertia[0].m_bottomLeftMat;
- m_cachedInertiaLowerRight = spatInertia[0].m_topLeftMat.transpose();
- }
-
- solveImatrix(zeroAccSpatFrc[0], result);
- spatAcc[0] = -result;
- }
-
- // now do the loop over the m_links
- for (int i = 0; i < num_links; ++i)
- {
- // qdd = D^{-1} * (Y - h^{T}*apar) = (S^{T}*I*S)^{-1} * (tau - S^{T}*I*cor - S^{T}*zeroAccFrc - S^{T}*I*apar)
- // a = apar + cor + Sqdd
- //or
- // qdd = D^{-1} * (Y - h^{T}*(apar+cor))
- // a = apar + Sqdd
-
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
-
- fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
-
- if(!isLinkAndAllAncestorsKinematic(i))
- {
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
- }
- btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
- //D^{-1} * (Y - h^{T}*apar)
- mulMatrix(invDi, Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
-
- spatAcc[i + 1] += spatCoriolisAcc[i];
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
- }
-
- if (m_links[i].m_jointFeedback)
- {
- m_internalNeedsJointFeedback = true;
-
- btVector3 angularBotVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_bottomVec;
- btVector3 linearTopVec = (spatInertia[i + 1] * spatAcc[i + 1] + zeroAccSpatFrc[i + 1]).m_topVec;
-
- if (jointFeedbackInJointFrame)
- {
- //shift the reaction forces to the joint frame
- //linear (force) component is the same
- //shift the angular (torque, moment) component using the relative position, m_links[i].m_dVector
- angularBotVec = angularBotVec - linearTopVec.cross(m_links[i].m_dVector);
- }
-
- if (jointFeedbackInWorldSpace)
- {
- if (isConstraintPass)
- {
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec += m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
- }
- else
- {
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = m_links[i].m_cachedWorldTransform.getBasis() * angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec = m_links[i].m_cachedWorldTransform.getBasis() * linearTopVec;
- }
- }
- else
- {
- if (isConstraintPass)
- {
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec += angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec += linearTopVec;
- }
- else
- {
- m_links[i].m_jointFeedback->m_reactionForces.m_bottomVec = angularBotVec;
- m_links[i].m_jointFeedback->m_reactionForces.m_topVec = linearTopVec;
- }
- }
- }
- }
-
- // transform base accelerations back to the world frame.
- const btVector3 omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
- output[0] = omegadot_out[0];
- output[1] = omegadot_out[1];
- output[2] = omegadot_out[2];
-
- const btVector3 vdot_out = rot_from_parent[0].transpose() * (spatAcc[0].getLinear() + spatVel[0].getAngular().cross(spatVel[0].getLinear()));
- output[3] = vdot_out[0];
- output[4] = vdot_out[1];
- output[5] = vdot_out[2];
-
- /////////////////
- //printf("q = [");
- //printf("%.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f ", m_baseQuat.x(), m_baseQuat.y(), m_baseQuat.z(), m_baseQuat.w(), m_basePos.x(), m_basePos.y(), m_basePos.z());
- //for(int link = 0; link < getNumLinks(); ++link)
- // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
- // printf("%.6f ", m_links[link].m_jointPos[dof]);
- //printf("]\n");
- ////
- //printf("qd = [");
- //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
- // printf("%.6f ", m_realBuf[dof]);
- //printf("]\n");
- //printf("qdd = [");
- //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
- // printf("%.6f ", output[dof]);
- //printf("]\n");
- /////////////////
-
- // Final step: add the accelerations (times dt) to the velocities.
-
- if (!isConstraintPass)
- {
- if (dt > 0.)
- applyDeltaVeeMultiDof(output, dt);
- }
- /////
- //btScalar angularThres = 1;
- //btScalar maxAngVel = 0.;
- //bool scaleDown = 1.;
- //for(int link = 0; link < m_links.size(); ++link)
- //{
- // if(spatVel[link+1].getAngular().length() > maxAngVel)
- // {
- // maxAngVel = spatVel[link+1].getAngular().length();
- // scaleDown = angularThres / spatVel[link+1].getAngular().length();
- // break;
- // }
- //}
-
- //if(scaleDown != 1.)
- //{
- // for(int link = 0; link < m_links.size(); ++link)
- // {
- // if(m_links[link].m_jointType == btMultibodyLink::eRevolute || m_links[link].m_jointType == btMultibodyLink::eSpherical)
- // {
- // for(int dof = 0; dof < m_links[link].m_dofCount; ++dof)
- // getJointVelMultiDof(link)[dof] *= scaleDown;
- // }
- // }
- //}
- /////
-
- /////////////////////
- if (m_useGlobalVelocities)
- {
- for (int i = 0; i < num_links; ++i)
- {
- const int parent = m_links[i].m_parent;
- //rot_from_parent[i+1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis); /// <- done
- //rot_from_world[i+1] = rot_from_parent[i+1] * rot_from_world[parent+1]; /// <- done
-
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
- fromWorld.m_rotMat = rot_from_world[i + 1];
-
- // vhat_i = i_xhat_p(i) * vhat_p(i)
- fromParent.transform(spatVel[parent + 1], spatVel[i + 1]);
- //nice alternative below (using operator *) but it generates temps
- /////////////////////////////////////////////////////////////
-
- // now set vhat_i to its true value by doing
- // vhat_i += qidot * shat_i
- spatJointVel.setZero();
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatJointVel += m_links[i].m_axes[dof] * getJointVelMultiDof(i)[dof];
-
- // remember vhat_i is really vhat_p(i) (but in current frame) at this point => we need to add velocity across the inboard joint
- spatVel[i + 1] += spatJointVel;
-
- fromWorld.transformInverseRotationOnly(spatVel[i + 1], m_links[i].m_absFrameTotVelocity);
- fromWorld.transformInverseRotationOnly(spatJointVel, m_links[i].m_absFrameLocVelocity);
- }
- }
-}
-
-void btMultiBody::solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const
-{
- int num_links = getNumLinks();
- ///solve I * x = rhs, so the result = invI * rhs
- if (num_links == 0)
- {
- // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
-
- if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
- {
- result[0] = rhs_bot[0] / m_baseInertia[0];
- result[1] = rhs_bot[1] / m_baseInertia[1];
- result[2] = rhs_bot[2] / m_baseInertia[2];
- }
- else
- {
- result[0] = 0;
- result[1] = 0;
- result[2] = 0;
- }
- if (m_baseMass >= SIMD_EPSILON)
- {
- result[3] = rhs_top[0] / m_baseMass;
- result[4] = rhs_top[1] / m_baseMass;
- result[5] = rhs_top[2] / m_baseMass;
- }
- else
- {
- result[3] = 0;
- result[4] = 0;
- result[5] = 0;
- }
- }
- else
- {
- if (!m_cachedInertiaValid)
- {
- for (int i = 0; i < 6; i++)
- {
- result[i] = 0.f;
- }
- return;
- }
- /// Special routine for calculating the inverse of a spatial inertia matrix
- ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
- btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
- btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
- btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
- tmp = invIupper_right * m_cachedInertiaLowerRight;
- btMatrix3x3 invI_upper_left = (tmp * Binv);
- btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
- tmp = m_cachedInertiaTopLeft * invI_upper_left;
- tmp[0][0] -= 1.0;
- tmp[1][1] -= 1.0;
- tmp[2][2] -= 1.0;
- btMatrix3x3 invI_lower_left = (Binv * tmp);
-
- //multiply result = invI * rhs
- {
- btVector3 vtop = invI_upper_left * rhs_top;
- btVector3 tmp;
- tmp = invIupper_right * rhs_bot;
- vtop += tmp;
- btVector3 vbot = invI_lower_left * rhs_top;
- tmp = invI_lower_right * rhs_bot;
- vbot += tmp;
- result[0] = vtop[0];
- result[1] = vtop[1];
- result[2] = vtop[2];
- result[3] = vbot[0];
- result[4] = vbot[1];
- result[5] = vbot[2];
- }
- }
-}
-void btMultiBody::solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const
-{
- int num_links = getNumLinks();
- ///solve I * x = rhs, so the result = invI * rhs
- if (num_links == 0)
- {
- // in the case of 0 m_links (i.e. a plain rigid body, not a multibody) rhs * invI is easier
- if ((m_baseInertia[0] >= SIMD_EPSILON) && (m_baseInertia[1] >= SIMD_EPSILON) && (m_baseInertia[2] >= SIMD_EPSILON))
- {
- result.setAngular(rhs.getAngular() / m_baseInertia);
- }
- else
- {
- result.setAngular(btVector3(0, 0, 0));
- }
- if (m_baseMass >= SIMD_EPSILON)
- {
- result.setLinear(rhs.getLinear() / m_baseMass);
- }
- else
- {
- result.setLinear(btVector3(0, 0, 0));
- }
- }
- else
- {
- /// Special routine for calculating the inverse of a spatial inertia matrix
- ///the 6x6 matrix is stored as 4 blocks of 3x3 matrices
- if (!m_cachedInertiaValid)
- {
- result.setLinear(btVector3(0, 0, 0));
- result.setAngular(btVector3(0, 0, 0));
- result.setVector(btVector3(0, 0, 0), btVector3(0, 0, 0));
- return;
- }
- btMatrix3x3 Binv = m_cachedInertiaTopRight.inverse() * -1.f;
- btMatrix3x3 tmp = m_cachedInertiaLowerRight * Binv;
- btMatrix3x3 invIupper_right = (tmp * m_cachedInertiaTopLeft + m_cachedInertiaLowerLeft).inverse();
- tmp = invIupper_right * m_cachedInertiaLowerRight;
- btMatrix3x3 invI_upper_left = (tmp * Binv);
- btMatrix3x3 invI_lower_right = (invI_upper_left).transpose();
- tmp = m_cachedInertiaTopLeft * invI_upper_left;
- tmp[0][0] -= 1.0;
- tmp[1][1] -= 1.0;
- tmp[2][2] -= 1.0;
- btMatrix3x3 invI_lower_left = (Binv * tmp);
-
- //multiply result = invI * rhs
- {
- btVector3 vtop = invI_upper_left * rhs.getLinear();
- btVector3 tmp;
- tmp = invIupper_right * rhs.getAngular();
- vtop += tmp;
- btVector3 vbot = invI_lower_left * rhs.getLinear();
- tmp = invI_lower_right * rhs.getAngular();
- vbot += tmp;
- result.setVector(vtop, vbot);
- }
- }
-}
-
-void btMultiBody::mulMatrix(const btScalar *pA, const btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const
-{
- for (int row = 0; row < rowsA; row++)
- {
- for (int col = 0; col < colsB; col++)
- {
- pC[row * colsB + col] = 0.f;
- for (int inner = 0; inner < rowsB; inner++)
- {
- pC[row * colsB + col] += pA[row * colsA + inner] * pB[col + inner * colsB];
- }
- }
- }
-}
-
-void btMultiBody::calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
- btAlignedObjectArray<btScalar> &scratch_r, btAlignedObjectArray<btVector3> &scratch_v) const
-{
- // Temporary matrices/vectors -- use scratch space from caller
- // so that we don't have to keep reallocating every frame
-
- int num_links = getNumLinks();
- scratch_r.resize(m_dofCount);
- scratch_v.resize(4 * num_links + 4);
-
- btScalar *r_ptr = m_dofCount ? &scratch_r[0] : 0;
- btVector3 *v_ptr = &scratch_v[0];
-
- // zhat_i^A (scratch space)
- btSpatialForceVector *zeroAccSpatFrc = (btSpatialForceVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
-
- // rot_from_parent (cached from calcAccelerations)
- const btMatrix3x3 *rot_from_parent = &m_matrixBuf[0];
-
- // hhat (cached), accel (scratch)
- // hhat is NOT stored for the base (but ahat is)
- const btSpatialForceVector *h = (btSpatialForceVector *)(m_dofCount > 0 ? &m_vectorBuf[0] : 0);
- btSpatialMotionVector *spatAcc = (btSpatialMotionVector *)v_ptr;
- v_ptr += num_links * 2 + 2;
-
- // Y_i (scratch), invD_i (cached)
- const btScalar *invD = m_dofCount > 0 ? &m_realBuf[6 + m_dofCount] : 0;
- btScalar *Y = r_ptr;
- ////////////////
- //aux variables
- btScalar invD_times_Y[6]; //D^{-1} * Y [dofxdof x dofx1 = dofx1] <=> D^{-1} * u; better moved to buffers since it is recalced in calcAccelerationDeltasMultiDof; num_dof of btScalar would cover all bodies
- btSpatialMotionVector result; //holds results of the SolveImatrix op; it is a spatial motion vector (accel)
- btScalar Y_minus_hT_a[6]; //Y - h^{T} * a; it's dofx1 for each body so a single 6x1 temp is enough
- btSpatialForceVector spatForceVecTemps[6]; //6 temporary spatial force vectors
- btSpatialTransformationMatrix fromParent;
- /////////////////
-
- // First 'upward' loop.
- // Combines CompTreeLinkVelocities and InitTreeLinks from Mirtich.
-
- // Fill in zero_acc
- // -- set to force/torque on the base, zero otherwise
- if (isBaseStaticOrKinematic())
- {
- zeroAccSpatFrc[0].setZero();
- }
- else
- {
- //test forces
- fromParent.m_rotMat = rot_from_parent[0];
- fromParent.transformRotationOnly(btSpatialForceVector(-force[0], -force[1], -force[2], -force[3], -force[4], -force[5]), zeroAccSpatFrc[0]);
- }
- for (int i = 0; i < num_links; ++i)
- {
- zeroAccSpatFrc[i + 1].setZero();
- }
-
- // 'Downward' loop.
- // (part of TreeForwardDynamics in Mirtich.)
- for (int i = num_links - 1; i >= 0; --i)
- {
- if(isLinkAndAllAncestorsKinematic(i))
- continue;
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- Y[m_links[i].m_dofOffset + dof] = force[6 + m_links[i].m_dofOffset + dof] - m_links[i].m_axes[dof].dot(zeroAccSpatFrc[i + 1]);
- }
-
- btVector3 in_top, in_bottom, out_top, out_bottom;
- const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- invD_times_Y[dof] = 0.f;
-
- for (int dof2 = 0; dof2 < m_links[i].m_dofCount; ++dof2)
- {
- invD_times_Y[dof] += invDi[dof * m_links[i].m_dofCount + dof2] * Y[m_links[i].m_dofOffset + dof2];
- }
- }
-
- // Zp += pXi * (Zi + hi*Yi/Di)
- spatForceVecTemps[0] = zeroAccSpatFrc[i + 1];
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- spatForceVecTemps[0] += hDof * invD_times_Y[dof];
- }
-
- fromParent.transformInverse(spatForceVecTemps[0], spatForceVecTemps[1]);
-
- zeroAccSpatFrc[parent + 1] += spatForceVecTemps[1];
- }
-
- // ptr to the joint accel part of the output
- btScalar *joint_accel = output + 6;
-
- // Second 'upward' loop
- // (part of TreeForwardDynamics in Mirtich)
-
- if (isBaseStaticOrKinematic())
- {
- spatAcc[0].setZero();
- }
- else
- {
- solveImatrix(zeroAccSpatFrc[0], result);
- spatAcc[0] = -result;
- }
-
- // now do the loop over the m_links
- for (int i = 0; i < num_links; ++i)
- {
- if(isLinkAndAllAncestorsKinematic(i))
- continue;
- const int parent = m_links[i].m_parent;
- fromParent.m_rotMat = rot_from_parent[i + 1];
- fromParent.m_trnVec = m_links[i].m_cachedRVector;
-
- fromParent.transform(spatAcc[parent + 1], spatAcc[i + 1]);
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- {
- const btSpatialForceVector &hDof = h[m_links[i].m_dofOffset + dof];
- //
- Y_minus_hT_a[dof] = Y[m_links[i].m_dofOffset + dof] - spatAcc[i + 1].dot(hDof);
- }
-
- const btScalar *invDi = &invD[m_links[i].m_dofOffset * m_links[i].m_dofOffset];
- mulMatrix(const_cast<btScalar *>(invDi), Y_minus_hT_a, m_links[i].m_dofCount, m_links[i].m_dofCount, m_links[i].m_dofCount, 1, &joint_accel[m_links[i].m_dofOffset]);
-
- for (int dof = 0; dof < m_links[i].m_dofCount; ++dof)
- spatAcc[i + 1] += m_links[i].m_axes[dof] * joint_accel[m_links[i].m_dofOffset + dof];
- }
-
- // transform base accelerations back to the world frame.
- btVector3 omegadot_out;
- omegadot_out = rot_from_parent[0].transpose() * spatAcc[0].getAngular();
- output[0] = omegadot_out[0];
- output[1] = omegadot_out[1];
- output[2] = omegadot_out[2];
-
- btVector3 vdot_out;
- vdot_out = rot_from_parent[0].transpose() * spatAcc[0].getLinear();
- output[3] = vdot_out[0];
- output[4] = vdot_out[1];
- output[5] = vdot_out[2];
-
- /////////////////
- //printf("delta = [");
- //for(int dof = 0; dof < getNumDofs() + 6; ++dof)
- // printf("%.2f ", output[dof]);
- //printf("]\n");
- /////////////////
-}
-void btMultiBody::predictPositionsMultiDof(btScalar dt)
-{
- int num_links = getNumLinks();
- if(!isBaseKinematic())
- {
- // step position by adding dt * velocity
- //btVector3 v = getBaseVel();
- //m_basePos += dt * v;
- //
- btScalar *pBasePos;
- btScalar *pBaseVel = &m_realBuf[3]; //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
-
- // reset to current position
- for (int i = 0; i < 3; ++i)
- {
- m_basePos_interpolate[i] = m_basePos[i];
- }
- pBasePos = m_basePos_interpolate;
-
- pBasePos[0] += dt * pBaseVel[0];
- pBasePos[1] += dt * pBaseVel[1];
- pBasePos[2] += dt * pBaseVel[2];
- }
-
- ///////////////////////////////
- //local functor for quaternion integration (to avoid error prone redundancy)
- struct
- {
- //"exponential map" based on btTransformUtil::integrateTransform(..)
- void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
- {
- //baseBody => quat is alias and omega is global coor
- //!baseBody => quat is alibi and omega is local coor
-
- btVector3 axis;
- btVector3 angvel;
-
- if (!baseBody)
- angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
- else
- angvel = omega;
-
- btScalar fAngle = angvel.length();
- //limit the angular motion
- if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
- }
-
- if (fAngle < btScalar(0.001))
- {
- // use Taylor's expansions of sync function
- axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
- }
-
- if (!baseBody)
- quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
- else
- quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
- //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
-
- quat.normalize();
- }
- } pQuatUpdateFun;
- ///////////////////////////////
-
- //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
- //
- if(!isBaseKinematic())
- {
- btScalar *pBaseQuat;
-
- // reset to current orientation
- for (int i = 0; i < 4; ++i)
- {
- m_baseQuat_interpolate[i] = m_baseQuat[i];
- }
- pBaseQuat = m_baseQuat_interpolate;
-
- btScalar *pBaseOmega = &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
- //
- btQuaternion baseQuat;
- baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
- btVector3 baseOmega;
- baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
- pQuatUpdateFun(baseOmega, baseQuat, true, dt);
- pBaseQuat[0] = baseQuat.x();
- pBaseQuat[1] = baseQuat.y();
- pBaseQuat[2] = baseQuat.z();
- pBaseQuat[3] = baseQuat.w();
- }
-
- // Finally we can update m_jointPos for each of the m_links
- for (int i = 0; i < num_links; ++i)
- {
- btScalar *pJointPos;
- pJointPos = &m_links[i].m_jointPos_interpolate[0];
-
- if (m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic())
- {
- switch (m_links[i].m_jointType)
- {
- case btMultibodyLink::ePrismatic:
- case btMultibodyLink::eRevolute:
- {
- pJointPos[0] = m_links[i].m_jointPos[0];
- break;
- }
- case btMultibodyLink::eSpherical:
- {
- for (int j = 0; j < 4; ++j)
- {
- pJointPos[j] = m_links[i].m_jointPos[j];
- }
- break;
- }
- case btMultibodyLink::ePlanar:
- {
- for (int j = 0; j < 3; ++j)
- {
- pJointPos[j] = m_links[i].m_jointPos[j];
- }
- break;
- }
- default:
- break;
- }
- }
- else
- {
- btScalar *pJointVel = getJointVelMultiDof(i);
-
- switch (m_links[i].m_jointType)
- {
- case btMultibodyLink::ePrismatic:
- case btMultibodyLink::eRevolute:
- {
- //reset to current pos
- pJointPos[0] = m_links[i].m_jointPos[0];
- btScalar jointVel = pJointVel[0];
- pJointPos[0] += dt * jointVel;
- break;
- }
- case btMultibodyLink::eSpherical:
- {
- //reset to current pos
-
- for (int j = 0; j < 4; ++j)
- {
- pJointPos[j] = m_links[i].m_jointPos[j];
- }
-
- btVector3 jointVel;
- jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
- btQuaternion jointOri;
- jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
- pQuatUpdateFun(jointVel, jointOri, false, dt);
- pJointPos[0] = jointOri.x();
- pJointPos[1] = jointOri.y();
- pJointPos[2] = jointOri.z();
- pJointPos[3] = jointOri.w();
- break;
- }
- case btMultibodyLink::ePlanar:
- {
- for (int j = 0; j < 3; ++j)
- {
- pJointPos[j] = m_links[i].m_jointPos[j];
- }
- pJointPos[0] += dt * getJointVelMultiDof(i)[0];
-
- btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
- btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
- pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
- pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
- break;
- }
- default:
- {
- }
- }
- }
-
- m_links[i].updateInterpolationCacheMultiDof();
- }
-}
-
-void btMultiBody::stepPositionsMultiDof(btScalar dt, btScalar *pq, btScalar *pqd)
-{
- int num_links = getNumLinks();
- if(!isBaseKinematic())
- {
- // step position by adding dt * velocity
- //btVector3 v = getBaseVel();
- //m_basePos += dt * v;
- //
- btScalar *pBasePos = (pq ? &pq[4] : m_basePos);
- btScalar *pBaseVel = (pqd ? &pqd[3] : &m_realBuf[3]); //note: the !pqd case assumes m_realBuf holds with base velocity at 3,4,5 (should be wrapped for safety)
-
- pBasePos[0] += dt * pBaseVel[0];
- pBasePos[1] += dt * pBaseVel[1];
- pBasePos[2] += dt * pBaseVel[2];
- }
-
- ///////////////////////////////
- //local functor for quaternion integration (to avoid error prone redundancy)
- struct
- {
- //"exponential map" based on btTransformUtil::integrateTransform(..)
- void operator()(const btVector3 &omega, btQuaternion &quat, bool baseBody, btScalar dt)
- {
- //baseBody => quat is alias and omega is global coor
- //!baseBody => quat is alibi and omega is local coor
-
- btVector3 axis;
- btVector3 angvel;
-
- if (!baseBody)
- angvel = quatRotate(quat, omega); //if quat is not m_baseQuat, it is alibi => ok
- else
- angvel = omega;
-
- btScalar fAngle = angvel.length();
- //limit the angular motion
- if (fAngle * dt > ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = btScalar(0.5) * SIMD_HALF_PI / dt;
- }
-
- if (fAngle < btScalar(0.001))
- {
- // use Taylor's expansions of sync function
- axis = angvel * (btScalar(0.5) * dt - (dt * dt * dt) * (btScalar(0.020833333333)) * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (btSin(btScalar(0.5) * fAngle * dt) / fAngle);
- }
-
- if (!baseBody)
- quat = btQuaternion(axis.x(), axis.y(), axis.z(), btCos(fAngle * dt * btScalar(0.5))) * quat;
- else
- quat = quat * btQuaternion(-axis.x(), -axis.y(), -axis.z(), btCos(fAngle * dt * btScalar(0.5)));
- //equivalent to: quat = (btQuaternion(axis.x(),axis.y(),axis.z(),btCos( fAngle*dt*btScalar(0.5) )) * quat.inverse()).inverse();
-
- quat.normalize();
- }
- } pQuatUpdateFun;
- ///////////////////////////////
-
- //pQuatUpdateFun(getBaseOmega(), m_baseQuat, true, dt);
- //
- if(!isBaseKinematic())
- {
- btScalar *pBaseQuat = pq ? pq : m_baseQuat;
- btScalar *pBaseOmega = pqd ? pqd : &m_realBuf[0]; //note: the !pqd case assumes m_realBuf starts with base omega (should be wrapped for safety)
- //
- btQuaternion baseQuat;
- baseQuat.setValue(pBaseQuat[0], pBaseQuat[1], pBaseQuat[2], pBaseQuat[3]);
- btVector3 baseOmega;
- baseOmega.setValue(pBaseOmega[0], pBaseOmega[1], pBaseOmega[2]);
- pQuatUpdateFun(baseOmega, baseQuat, true, dt);
- pBaseQuat[0] = baseQuat.x();
- pBaseQuat[1] = baseQuat.y();
- pBaseQuat[2] = baseQuat.z();
- pBaseQuat[3] = baseQuat.w();
-
- //printf("pBaseOmega = %.4f %.4f %.4f\n", pBaseOmega->x(), pBaseOmega->y(), pBaseOmega->z());
- //printf("pBaseVel = %.4f %.4f %.4f\n", pBaseVel->x(), pBaseVel->y(), pBaseVel->z());
- //printf("baseQuat = %.4f %.4f %.4f %.4f\n", pBaseQuat->x(), pBaseQuat->y(), pBaseQuat->z(), pBaseQuat->w());
- }
-
- if (pq)
- pq += 7;
- if (pqd)
- pqd += 6;
-
- // Finally we can update m_jointPos for each of the m_links
- for (int i = 0; i < num_links; ++i)
- {
- if (!(m_links[i].m_collider && m_links[i].m_collider->isStaticOrKinematic()))
- {
- btScalar *pJointPos;
- pJointPos= (pq ? pq : &m_links[i].m_jointPos[0]);
-
- btScalar *pJointVel = (pqd ? pqd : getJointVelMultiDof(i));
-
- switch (m_links[i].m_jointType)
- {
- case btMultibodyLink::ePrismatic:
- case btMultibodyLink::eRevolute:
- {
- //reset to current pos
- btScalar jointVel = pJointVel[0];
- pJointPos[0] += dt * jointVel;
- break;
- }
- case btMultibodyLink::eSpherical:
- {
- //reset to current pos
- btVector3 jointVel;
- jointVel.setValue(pJointVel[0], pJointVel[1], pJointVel[2]);
- btQuaternion jointOri;
- jointOri.setValue(pJointPos[0], pJointPos[1], pJointPos[2], pJointPos[3]);
- pQuatUpdateFun(jointVel, jointOri, false, dt);
- pJointPos[0] = jointOri.x();
- pJointPos[1] = jointOri.y();
- pJointPos[2] = jointOri.z();
- pJointPos[3] = jointOri.w();
- break;
- }
- case btMultibodyLink::ePlanar:
- {
- pJointPos[0] += dt * getJointVelMultiDof(i)[0];
-
- btVector3 q0_coors_qd1qd2 = getJointVelMultiDof(i)[1] * m_links[i].getAxisBottom(1) + getJointVelMultiDof(i)[2] * m_links[i].getAxisBottom(2);
- btVector3 no_q0_coors_qd1qd2 = quatRotate(btQuaternion(m_links[i].getAxisTop(0), pJointPos[0]), q0_coors_qd1qd2);
- pJointPos[1] += m_links[i].getAxisBottom(1).dot(no_q0_coors_qd1qd2) * dt;
- pJointPos[2] += m_links[i].getAxisBottom(2).dot(no_q0_coors_qd1qd2) * dt;
-
- break;
- }
- default:
- {
- }
- }
- }
-
- m_links[i].updateCacheMultiDof(pq);
-
- if (pq)
- pq += m_links[i].m_posVarCount;
- if (pqd)
- pqd += m_links[i].m_dofCount;
- }
-}
-
-void btMultiBody::fillConstraintJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal_ang,
- const btVector3 &normal_lin,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r1,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const
-{
- // temporary space
- int num_links = getNumLinks();
- int m_dofCount = getNumDofs();
- scratch_v.resize(3 * num_links + 3); //(num_links + base) offsets + (num_links + base) normals_lin + (num_links + base) normals_ang
- scratch_m.resize(num_links + 1);
-
- btVector3 *v_ptr = &scratch_v[0];
- btVector3 *p_minus_com_local = v_ptr;
- v_ptr += num_links + 1;
- btVector3 *n_local_lin = v_ptr;
- v_ptr += num_links + 1;
- btVector3 *n_local_ang = v_ptr;
- v_ptr += num_links + 1;
- btAssert(v_ptr - &scratch_v[0] == scratch_v.size());
-
- //scratch_r.resize(m_dofCount);
- //btScalar *results = m_dofCount > 0 ? &scratch_r[0] : 0;
-
- scratch_r1.resize(m_dofCount+num_links);
- btScalar * results = m_dofCount > 0 ? &scratch_r1[0] : 0;
- btScalar* links = num_links? &scratch_r1[m_dofCount] : 0;
- int numLinksChildToRoot=0;
- int l = link;
- while (l != -1)
- {
- links[numLinksChildToRoot++]=l;
- l = m_links[l].m_parent;
- }
-
- btMatrix3x3 *rot_from_world = &scratch_m[0];
-
- const btVector3 p_minus_com_world = contact_point - m_basePos;
- const btVector3 &normal_lin_world = normal_lin; //convenience
- const btVector3 &normal_ang_world = normal_ang;
-
- rot_from_world[0] = btMatrix3x3(m_baseQuat);
-
- // omega coeffients first.
- btVector3 omega_coeffs_world;
- omega_coeffs_world = p_minus_com_world.cross(normal_lin_world);
- jac[0] = omega_coeffs_world[0] + normal_ang_world[0];
- jac[1] = omega_coeffs_world[1] + normal_ang_world[1];
- jac[2] = omega_coeffs_world[2] + normal_ang_world[2];
- // then v coefficients
- jac[3] = normal_lin_world[0];
- jac[4] = normal_lin_world[1];
- jac[5] = normal_lin_world[2];
-
- //create link-local versions of p_minus_com and normal
- p_minus_com_local[0] = rot_from_world[0] * p_minus_com_world;
- n_local_lin[0] = rot_from_world[0] * normal_lin_world;
- n_local_ang[0] = rot_from_world[0] * normal_ang_world;
-
- // Set remaining jac values to zero for now.
- for (int i = 6; i < 6 + m_dofCount; ++i)
- {
- jac[i] = 0;
- }
-
- // Qdot coefficients, if necessary.
- if (num_links > 0 && link > -1)
- {
- // TODO: (Also, we are making 3 separate calls to this function, for the normal & the 2 friction directions,
- // which is resulting in repeated work being done...)
-
- // calculate required normals & positions in the local frames.
- for (int a = 0; a < numLinksChildToRoot; a++)
- {
- int i = links[numLinksChildToRoot-1-a];
- // transform to local frame
- const int parent = m_links[i].m_parent;
- const btMatrix3x3 mtx(m_links[i].m_cachedRotParentToThis);
- rot_from_world[i + 1] = mtx * rot_from_world[parent + 1];
-
- n_local_lin[i + 1] = mtx * n_local_lin[parent + 1];
- n_local_ang[i + 1] = mtx * n_local_ang[parent + 1];
- p_minus_com_local[i + 1] = mtx * p_minus_com_local[parent + 1] - m_links[i].m_cachedRVector;
-
- // calculate the jacobian entry
- switch (m_links[i].m_jointType)
- {
- case btMultibodyLink::eRevolute:
- {
- results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
- break;
- }
- case btMultibodyLink::ePrismatic:
- {
- results[m_links[i].m_dofOffset] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(0));
- break;
- }
- case btMultibodyLink::eSpherical:
- {
- results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(1).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(1));
- results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(2).cross(p_minus_com_local[i + 1]) + m_links[i].getAxisBottom(2));
-
- results[m_links[i].m_dofOffset + 0] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(0));
- results[m_links[i].m_dofOffset + 1] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(1));
- results[m_links[i].m_dofOffset + 2] += n_local_ang[i + 1].dot(m_links[i].getAxisTop(2));
-
- break;
- }
- case btMultibodyLink::ePlanar:
- {
- results[m_links[i].m_dofOffset + 0] = n_local_lin[i + 1].dot(m_links[i].getAxisTop(0).cross(p_minus_com_local[i + 1])); // + m_links[i].getAxisBottom(0));
- results[m_links[i].m_dofOffset + 1] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(1));
- results[m_links[i].m_dofOffset + 2] = n_local_lin[i + 1].dot(m_links[i].getAxisBottom(2));
-
- break;
- }
- default:
- {
- }
- }
- }
-
- // Now copy through to output.
- //printf("jac[%d] = ", link);
- while (link != -1)
- {
- for (int dof = 0; dof < m_links[link].m_dofCount; ++dof)
- {
- jac[6 + m_links[link].m_dofOffset + dof] = results[m_links[link].m_dofOffset + dof];
- //printf("%.2f\t", jac[6 + m_links[link].m_dofOffset + dof]);
- }
-
- link = m_links[link].m_parent;
- }
- //printf("]\n");
- }
-}
-
-void btMultiBody::wakeUp()
-{
- m_sleepTimer = 0;
- m_awake = true;
-}
-
-void btMultiBody::goToSleep()
-{
- m_awake = false;
-}
-
-void btMultiBody::checkMotionAndSleepIfRequired(btScalar timestep)
-{
- extern bool gDisableDeactivation;
- if (!m_canSleep || gDisableDeactivation)
- {
- m_awake = true;
- m_sleepTimer = 0;
- return;
- }
-
-
-
- // motion is computed as omega^2 + v^2 + (sum of squares of joint velocities)
- btScalar motion = 0;
- {
- for (int i = 0; i < 6 + m_dofCount; ++i)
- motion += m_realBuf[i] * m_realBuf[i];
- }
-
- if (motion < m_sleepEpsilon)
- {
- m_sleepTimer += timestep;
- if (m_sleepTimer > m_sleepTimeout)
- {
- goToSleep();
- }
- }
- else
- {
- m_sleepTimer = 0;
- if (m_canWakeup)
- {
- if (!m_awake)
- wakeUp();
- }
- }
-}
-
-void btMultiBody::forwardKinematics(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
-{
- int num_links = getNumLinks();
-
- // Cached 3x3 rotation matrices from parent frame to this frame.
- btMatrix3x3 *rot_from_parent = (btMatrix3x3 *)&m_matrixBuf[0];
-
- rot_from_parent[0] = btMatrix3x3(m_baseQuat); //m_baseQuat assumed to be alias!?
-
- for (int i = 0; i < num_links; ++i)
- {
- rot_from_parent[i + 1] = btMatrix3x3(m_links[i].m_cachedRotParentToThis);
- }
-
- int nLinks = getNumLinks();
- ///base + num m_links
- world_to_local.resize(nLinks + 1);
- local_origin.resize(nLinks + 1);
-
- world_to_local[0] = getWorldToBaseRot();
- local_origin[0] = getBasePos();
-
- for (int k = 0; k < getNumLinks(); k++)
- {
- const int parent = getParent(k);
- world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
- local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
- }
-
- for (int link = 0; link < getNumLinks(); link++)
- {
- int index = link + 1;
-
- btVector3 posr = local_origin[index];
- btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
- getLink(link).m_cachedWorldTransform = tr;
- }
-}
-
-void btMultiBody::updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
-{
- world_to_local.resize(getNumLinks() + 1);
- local_origin.resize(getNumLinks() + 1);
-
- world_to_local[0] = getWorldToBaseRot();
- local_origin[0] = getBasePos();
-
- if (getBaseCollider())
- {
- btVector3 posr = local_origin[0];
- // float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
-
- getBaseCollider()->setWorldTransform(tr);
- getBaseCollider()->setInterpolationWorldTransform(tr);
- }
-
- for (int k = 0; k < getNumLinks(); k++)
- {
- const int parent = getParent(k);
- world_to_local[k + 1] = getParentToLocalRot(k) * world_to_local[parent + 1];
- local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getRVector(k)));
- }
-
- for (int m = 0; m < getNumLinks(); m++)
- {
- btMultiBodyLinkCollider *col = getLink(m).m_collider;
- if (col)
- {
- int link = col->m_link;
- btAssert(link == m);
-
- int index = link + 1;
-
- btVector3 posr = local_origin[index];
- // float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
-
- col->setWorldTransform(tr);
- col->setInterpolationWorldTransform(tr);
- }
- }
-}
-
-void btMultiBody::updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> &world_to_local, btAlignedObjectArray<btVector3> &local_origin)
-{
- world_to_local.resize(getNumLinks() + 1);
- local_origin.resize(getNumLinks() + 1);
-
- if(isBaseKinematic()){
- world_to_local[0] = getWorldToBaseRot();
- local_origin[0] = getBasePos();
- }
- else
- {
- world_to_local[0] = getInterpolateWorldToBaseRot();
- local_origin[0] = getInterpolateBasePos();
- }
-
- if (getBaseCollider())
- {
- btVector3 posr = local_origin[0];
- // float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4] = {-world_to_local[0].x(), -world_to_local[0].y(), -world_to_local[0].z(), world_to_local[0].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
-
- getBaseCollider()->setInterpolationWorldTransform(tr);
- }
-
- for (int k = 0; k < getNumLinks(); k++)
- {
- const int parent = getParent(k);
- world_to_local[k + 1] = getInterpolateParentToLocalRot(k) * world_to_local[parent + 1];
- local_origin[k + 1] = local_origin[parent + 1] + (quatRotate(world_to_local[k + 1].inverse(), getInterpolateRVector(k)));
- }
-
- for (int m = 0; m < getNumLinks(); m++)
- {
- btMultiBodyLinkCollider *col = getLink(m).m_collider;
- if (col)
- {
- int link = col->m_link;
- btAssert(link == m);
-
- int index = link + 1;
-
- btVector3 posr = local_origin[index];
- // float pos[4]={posr.x(),posr.y(),posr.z(),1};
- btScalar quat[4] = {-world_to_local[index].x(), -world_to_local[index].y(), -world_to_local[index].z(), world_to_local[index].w()};
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(posr);
- tr.setRotation(btQuaternion(quat[0], quat[1], quat[2], quat[3]));
-
- col->setInterpolationWorldTransform(tr);
- }
- }
-}
-
-int btMultiBody::calculateSerializeBufferSize() const
-{
- int sz = sizeof(btMultiBodyData);
- return sz;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char *btMultiBody::serialize(void *dataBuffer, class btSerializer *serializer) const
-{
- btMultiBodyData *mbd = (btMultiBodyData *)dataBuffer;
- getBasePos().serialize(mbd->m_baseWorldPosition);
- getWorldToBaseRot().inverse().serialize(mbd->m_baseWorldOrientation);
- getBaseVel().serialize(mbd->m_baseLinearVelocity);
- getBaseOmega().serialize(mbd->m_baseAngularVelocity);
-
- mbd->m_baseMass = this->getBaseMass();
- getBaseInertia().serialize(mbd->m_baseInertia);
- {
- char *name = (char *)serializer->findNameForPointer(m_baseName);
- mbd->m_baseName = (char *)serializer->getUniquePointer(name);
- if (mbd->m_baseName)
- {
- serializer->serializeName(name);
- }
- }
- mbd->m_numLinks = this->getNumLinks();
- if (mbd->m_numLinks)
- {
- int sz = sizeof(btMultiBodyLinkData);
- int numElem = mbd->m_numLinks;
- btChunk *chunk = serializer->allocate(sz, numElem);
- btMultiBodyLinkData *memPtr = (btMultiBodyLinkData *)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_jointType = getLink(i).m_jointType;
- memPtr->m_dofCount = getLink(i).m_dofCount;
- memPtr->m_posVarCount = getLink(i).m_posVarCount;
-
- getLink(i).m_inertiaLocal.serialize(memPtr->m_linkInertia);
-
- getLink(i).m_absFrameTotVelocity.m_topVec.serialize(memPtr->m_absFrameTotVelocityTop);
- getLink(i).m_absFrameTotVelocity.m_bottomVec.serialize(memPtr->m_absFrameTotVelocityBottom);
- getLink(i).m_absFrameLocVelocity.m_topVec.serialize(memPtr->m_absFrameLocVelocityTop);
- getLink(i).m_absFrameLocVelocity.m_bottomVec.serialize(memPtr->m_absFrameLocVelocityBottom);
-
- memPtr->m_linkMass = getLink(i).m_mass;
- memPtr->m_parentIndex = getLink(i).m_parent;
- memPtr->m_jointDamping = getLink(i).m_jointDamping;
- memPtr->m_jointFriction = getLink(i).m_jointFriction;
- memPtr->m_jointLowerLimit = getLink(i).m_jointLowerLimit;
- memPtr->m_jointUpperLimit = getLink(i).m_jointUpperLimit;
- memPtr->m_jointMaxForce = getLink(i).m_jointMaxForce;
- memPtr->m_jointMaxVelocity = getLink(i).m_jointMaxVelocity;
-
- getLink(i).m_eVector.serialize(memPtr->m_parentComToThisPivotOffset);
- getLink(i).m_dVector.serialize(memPtr->m_thisPivotToThisComOffset);
- getLink(i).m_zeroRotParentToThis.serialize(memPtr->m_zeroRotParentToThis);
- btAssert(memPtr->m_dofCount <= 3);
- for (int dof = 0; dof < getLink(i).m_dofCount; dof++)
- {
- getLink(i).getAxisBottom(dof).serialize(memPtr->m_jointAxisBottom[dof]);
- getLink(i).getAxisTop(dof).serialize(memPtr->m_jointAxisTop[dof]);
-
- memPtr->m_jointTorque[dof] = getLink(i).m_jointTorque[dof];
- memPtr->m_jointVel[dof] = getJointVelMultiDof(i)[dof];
- }
- int numPosVar = getLink(i).m_posVarCount;
- for (int posvar = 0; posvar < numPosVar; posvar++)
- {
- memPtr->m_jointPos[posvar] = getLink(i).m_jointPos[posvar];
- }
-
- {
- char *name = (char *)serializer->findNameForPointer(m_links[i].m_linkName);
- memPtr->m_linkName = (char *)serializer->getUniquePointer(name);
- if (memPtr->m_linkName)
- {
- serializer->serializeName(name);
- }
- }
- {
- char *name = (char *)serializer->findNameForPointer(m_links[i].m_jointName);
- memPtr->m_jointName = (char *)serializer->getUniquePointer(name);
- if (memPtr->m_jointName)
- {
- serializer->serializeName(name);
- }
- }
- memPtr->m_linkCollider = (btCollisionObjectData *)serializer->getUniquePointer(getLink(i).m_collider);
- }
- serializer->finalizeChunk(chunk, btMultiBodyLinkDataName, BT_ARRAY_CODE, (void *)&m_links[0]);
- }
- mbd->m_links = mbd->m_numLinks ? (btMultiBodyLinkData *)serializer->getUniquePointer((void *)&m_links[0]) : 0;
-
- // Fill padding with zeros to appease msan.
-#ifdef BT_USE_DOUBLE_PRECISION
- memset(mbd->m_padding, 0, sizeof(mbd->m_padding));
-#endif
-
- return btMultiBodyDataName;
-}
-
-void btMultiBody::saveKinematicState(btScalar timeStep)
-{
- //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
- if (m_kinematic_calculate_velocity && timeStep != btScalar(0.))
- {
- btVector3 linearVelocity, angularVelocity;
- btTransformUtil::calculateVelocity(getInterpolateBaseWorldTransform(), getBaseWorldTransform(), timeStep, linearVelocity, angularVelocity);
- setBaseVel(linearVelocity);
- setBaseOmega(angularVelocity);
- setInterpolateBaseWorldTransform(getBaseWorldTransform());
- }
-}
-
-void btMultiBody::setLinkDynamicType(const int i, int type)
-{
- if (i == -1)
- {
- setBaseDynamicType(type);
- }
- else if (i >= 0 && i < getNumLinks())
- {
- if (m_links[i].m_collider)
- {
- m_links[i].m_collider->setDynamicType(type);
- }
- }
-}
-
-bool btMultiBody::isLinkStaticOrKinematic(const int i) const
-{
- if (i == -1)
- {
- return isBaseStaticOrKinematic();
- }
- else
- {
- if (m_links[i].m_collider)
- return m_links[i].m_collider->isStaticOrKinematic();
- }
- return false;
-}
-
-bool btMultiBody::isLinkKinematic(const int i) const
-{
- if (i == -1)
- {
- return isBaseKinematic();
- }
- else
- {
- if (m_links[i].m_collider)
- return m_links[i].m_collider->isKinematic();
- }
- return false;
-}
-
-bool btMultiBody::isLinkAndAllAncestorsStaticOrKinematic(const int i) const
-{
- int link = i;
- while (link != -1) {
- if (!isLinkStaticOrKinematic(link))
- return false;
- link = m_links[link].m_parent;
- }
- return isBaseStaticOrKinematic();
-}
-
-bool btMultiBody::isLinkAndAllAncestorsKinematic(const int i) const
-{
- int link = i;
- while (link != -1) {
- if (!isLinkKinematic(link))
- return false;
- link = m_links[link].m_parent;
- }
- return isBaseKinematic();
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
deleted file mode 100644
index 345970d261..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBody.h
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
- * PURPOSE:
- * Class representing an articulated rigid body. Stores the body's
- * current state, allows forces and torques to be set, handles
- * timestepping and implements Featherstone's algorithm.
- *
- * COPYRIGHT:
- * Copyright (C) Stephen Thompson, <stephen@solarflare.org.uk>, 2011-2013
- * Portions written By Erwin Coumans: connection to LCP solver, various multibody constraints, replacing Eigen math library by Bullet LinearMath and a dedicated 6x6 matrix inverse (solveImatrix)
- * Portions written By Jakub Stepien: support for multi-DOF constraints, introduction of spatial algebra and several other improvements
-
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- */
-
-#ifndef BT_MULTIBODY_H
-#define BT_MULTIBODY_H
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btQuaternion.h"
-#include "LinearMath/btMatrix3x3.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-///serialization data, don't change them if you are not familiar with the details of the serialization mechanisms
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btMultiBodyData btMultiBodyDoubleData
-#define btMultiBodyDataName "btMultiBodyDoubleData"
-#define btMultiBodyLinkData btMultiBodyLinkDoubleData
-#define btMultiBodyLinkDataName "btMultiBodyLinkDoubleData"
-#else
-#define btMultiBodyData btMultiBodyFloatData
-#define btMultiBodyDataName "btMultiBodyFloatData"
-#define btMultiBodyLinkData btMultiBodyLinkFloatData
-#define btMultiBodyLinkDataName "btMultiBodyLinkFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-#include "btMultiBodyLink.h"
-class btMultiBodyLinkCollider;
-
-ATTRIBUTE_ALIGNED16(class)
-btMultiBody
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- //
- // initialization
- //
-
- btMultiBody(int n_links, // NOT including the base
- btScalar mass, // mass of base
- const btVector3 &inertia, // inertia of base, in base frame; assumed diagonal
- bool fixedBase, // whether the base is fixed (true) or can move (false)
- bool canSleep, bool deprecatedMultiDof = true);
-
- virtual ~btMultiBody();
-
- //note: fixed link collision with parent is always disabled
- void setupFixed(int i, //linkIndex
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset, bool deprecatedDisableParentCollision = true);
-
- void setupPrismatic(int i,
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis,
- const btVector3 &jointAxis,
- const btVector3 &parentComToThisPivotOffset,
- const btVector3 &thisPivotToThisComOffset,
- bool disableParentCollision);
-
- void setupRevolute(int i, // 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parentIndex,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &jointAxis, // in my frame
- const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
- const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
- bool disableParentCollision = false);
-
- void setupSpherical(int i, // linkIndex, 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &parentComToThisPivotOffset, // vector from parent COM to joint axis, in PARENT frame
- const btVector3 &thisPivotToThisComOffset, // vector from joint axis to my COM, in MY frame
- bool disableParentCollision = false);
-
- void setupPlanar(int i, // 0 to num_links-1
- btScalar mass,
- const btVector3 &inertia,
- int parent,
- const btQuaternion &rotParentToThis, // rotate points in parent frame to this frame, when q = 0
- const btVector3 &rotationAxis,
- const btVector3 &parentComToThisComOffset, // vector from parent COM to this COM, in PARENT frame
- bool disableParentCollision = false);
-
- const btMultibodyLink &getLink(int index) const
- {
- return m_links[index];
- }
-
- btMultibodyLink &getLink(int index)
- {
- return m_links[index];
- }
-
- void setBaseCollider(btMultiBodyLinkCollider * collider) //collider can be NULL to disable collision for the base
- {
- m_baseCollider = collider;
- }
- const btMultiBodyLinkCollider *getBaseCollider() const
- {
- return m_baseCollider;
- }
- btMultiBodyLinkCollider *getBaseCollider()
- {
- return m_baseCollider;
- }
-
- const btMultiBodyLinkCollider *getLinkCollider(int index) const
- {
- if (index >= 0 && index < getNumLinks())
- {
- return getLink(index).m_collider;
- }
- return 0;
- }
-
- btMultiBodyLinkCollider *getLinkCollider(int index)
- {
- if (index >= 0 && index < getNumLinks())
- {
- return getLink(index).m_collider;
- }
- return 0;
- }
-
- //
- // get parent
- // input: link num from 0 to num_links-1
- // output: link num from 0 to num_links-1, OR -1 to mean the base.
- //
- int getParent(int link_num) const;
-
- //
- // get number of m_links, masses, moments of inertia
- //
-
- int getNumLinks() const { return m_links.size(); }
- int getNumDofs() const { return m_dofCount; }
- int getNumPosVars() const { return m_posVarCnt; }
- btScalar getBaseMass() const { return m_baseMass; }
- const btVector3 &getBaseInertia() const { return m_baseInertia; }
- btScalar getLinkMass(int i) const;
- const btVector3 &getLinkInertia(int i) const;
-
- //
- // change mass (incomplete: can only change base mass and inertia at present)
- //
-
- void setBaseMass(btScalar mass) { m_baseMass = mass; }
- void setBaseInertia(const btVector3 &inertia) { m_baseInertia = inertia; }
-
- //
- // get/set pos/vel/rot/omega for the base link
- //
-
- const btVector3 &getBasePos() const
- {
- return m_basePos;
- } // in world frame
- const btVector3 getBaseVel() const
- {
- return btVector3(m_realBuf[3], m_realBuf[4], m_realBuf[5]);
- } // in world frame
- const btQuaternion &getWorldToBaseRot() const
- {
- return m_baseQuat;
- }
-
- const btVector3 &getInterpolateBasePos() const
- {
- return m_basePos_interpolate;
- } // in world frame
- const btQuaternion &getInterpolateWorldToBaseRot() const
- {
- return m_baseQuat_interpolate;
- }
-
- // rotates world vectors into base frame
- btVector3 getBaseOmega() const { return btVector3(m_realBuf[0], m_realBuf[1], m_realBuf[2]); } // in world frame
-
- void setBasePos(const btVector3 &pos)
- {
- m_basePos = pos;
- if(!isBaseKinematic())
- m_basePos_interpolate = pos;
- }
-
- void setInterpolateBasePos(const btVector3 &pos)
- {
- m_basePos_interpolate = pos;
- }
-
- void setBaseWorldTransform(const btTransform &tr)
- {
- setBasePos(tr.getOrigin());
- setWorldToBaseRot(tr.getRotation().inverse());
- }
-
- btTransform getBaseWorldTransform() const
- {
- btTransform tr;
- tr.setOrigin(getBasePos());
- tr.setRotation(getWorldToBaseRot().inverse());
- return tr;
- }
-
- void setInterpolateBaseWorldTransform(const btTransform &tr)
- {
- setInterpolateBasePos(tr.getOrigin());
- setInterpolateWorldToBaseRot(tr.getRotation().inverse());
- }
-
- btTransform getInterpolateBaseWorldTransform() const
- {
- btTransform tr;
- tr.setOrigin(getInterpolateBasePos());
- tr.setRotation(getInterpolateWorldToBaseRot().inverse());
- return tr;
- }
-
- void setBaseVel(const btVector3 &vel)
- {
- m_realBuf[3] = vel[0];
- m_realBuf[4] = vel[1];
- m_realBuf[5] = vel[2];
- }
-
- void setWorldToBaseRot(const btQuaternion &rot)
- {
- m_baseQuat = rot; //m_baseQuat asumed to ba alias!?
- if(!isBaseKinematic())
- m_baseQuat_interpolate = rot;
- }
-
- void setInterpolateWorldToBaseRot(const btQuaternion &rot)
- {
- m_baseQuat_interpolate = rot;
- }
-
- void setBaseOmega(const btVector3 &omega)
- {
- m_realBuf[0] = omega[0];
- m_realBuf[1] = omega[1];
- m_realBuf[2] = omega[2];
- }
-
- void saveKinematicState(btScalar timeStep);
-
- //
- // get/set pos/vel for child m_links (i = 0 to num_links-1)
- //
-
- btScalar getJointPos(int i) const;
- btScalar getJointVel(int i) const;
-
- btScalar *getJointVelMultiDof(int i);
- btScalar *getJointPosMultiDof(int i);
-
- const btScalar *getJointVelMultiDof(int i) const;
- const btScalar *getJointPosMultiDof(int i) const;
-
- void setJointPos(int i, btScalar q);
- void setJointVel(int i, btScalar qdot);
- void setJointPosMultiDof(int i, const double *q);
- void setJointVelMultiDof(int i, const double *qdot);
- void setJointPosMultiDof(int i, const float *q);
- void setJointVelMultiDof(int i, const float *qdot);
-
- //
- // direct access to velocities as a vector of 6 + num_links elements.
- // (omega first, then v, then joint velocities.)
- //
- const btScalar *getVelocityVector() const
- {
- return &m_realBuf[0];
- }
-
- const btScalar *getDeltaVelocityVector() const
- {
- return &m_deltaV[0];
- }
-
- const btScalar *getSplitVelocityVector() const
- {
- return &m_splitV[0];
- }
- /* btScalar * getVelocityVector()
- {
- return &real_buf[0];
- }
- */
-
- //
- // get the frames of reference (positions and orientations) of the child m_links
- // (i = 0 to num_links-1)
- //
-
- const btVector3 &getRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
- const btQuaternion &getParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
- const btVector3 &getInterpolateRVector(int i) const; // vector from COM(parent(i)) to COM(i), in frame i's coords
- const btQuaternion &getInterpolateParentToLocalRot(int i) const; // rotates vectors in frame parent(i) to vectors in frame i.
-
- //
- // transform vectors in local frame of link i to world frame (or vice versa)
- //
- btVector3 localPosToWorld(int i, const btVector3 &local_pos) const;
- btVector3 localDirToWorld(int i, const btVector3 &local_dir) const;
- btVector3 worldPosToLocal(int i, const btVector3 &world_pos) const;
- btVector3 worldDirToLocal(int i, const btVector3 &world_dir) const;
-
- //
- // transform a frame in local coordinate to a frame in world coordinate
- //
- btMatrix3x3 localFrameToWorld(int i, const btMatrix3x3 &local_frame) const;
-
-
- //
- // set external forces and torques. Note all external forces/torques are given in the WORLD frame.
- //
-
- void clearForcesAndTorques();
- void clearConstraintForces();
-
- void clearVelocities();
-
- void addBaseForce(const btVector3 &f)
- {
- m_baseForce += f;
- }
- void addBaseTorque(const btVector3 &t) { m_baseTorque += t; }
- void addLinkForce(int i, const btVector3 &f);
- void addLinkTorque(int i, const btVector3 &t);
-
- void addBaseConstraintForce(const btVector3 &f)
- {
- m_baseConstraintForce += f;
- }
- void addBaseConstraintTorque(const btVector3 &t) { m_baseConstraintTorque += t; }
- void addLinkConstraintForce(int i, const btVector3 &f);
- void addLinkConstraintTorque(int i, const btVector3 &t);
-
- void addJointTorque(int i, btScalar Q);
- void addJointTorqueMultiDof(int i, int dof, btScalar Q);
- void addJointTorqueMultiDof(int i, const btScalar *Q);
-
- const btVector3 &getBaseForce() const { return m_baseForce; }
- const btVector3 &getBaseTorque() const { return m_baseTorque; }
- const btVector3 &getLinkForce(int i) const;
- const btVector3 &getLinkTorque(int i) const;
- btScalar getJointTorque(int i) const;
- btScalar *getJointTorqueMultiDof(int i);
-
- //
- // dynamics routines.
- //
-
- // timestep the velocities (given the external forces/torques set using addBaseForce etc).
- // also sets up caches for calcAccelerationDeltas.
- //
- // Note: the caller must provide three vectors which are used as
- // temporary scratch space. The idea here is to reduce dynamic
- // memory allocation: the same scratch vectors can be re-used
- // again and again for different Multibodies, instead of each
- // btMultiBody allocating (and then deallocating) their own
- // individual scratch buffers. This gives a considerable speed
- // improvement, at least on Windows (where dynamic memory
- // allocation appears to be fairly slow).
- //
-
- void computeAccelerationsArticulatedBodyAlgorithmMultiDof(btScalar dt,
- btAlignedObjectArray<btScalar> & scratch_r,
- btAlignedObjectArray<btVector3> & scratch_v,
- btAlignedObjectArray<btMatrix3x3> & scratch_m,
- bool isConstraintPass,
- bool jointFeedbackInWorldSpace,
- bool jointFeedbackInJointFrame
- );
-
- ///stepVelocitiesMultiDof is deprecated, use computeAccelerationsArticulatedBodyAlgorithmMultiDof instead
- //void stepVelocitiesMultiDof(btScalar dt,
- // btAlignedObjectArray<btScalar> & scratch_r,
- // btAlignedObjectArray<btVector3> & scratch_v,
- // btAlignedObjectArray<btMatrix3x3> & scratch_m,
- // bool isConstraintPass = false)
- //{
- // computeAccelerationsArticulatedBodyAlgorithmMultiDof(dt, scratch_r, scratch_v, scratch_m, isConstraintPass, false, false);
- //}
-
- // calcAccelerationDeltasMultiDof
- // input: force vector (in same format as jacobian, i.e.:
- // 3 torque values, 3 force values, num_links joint torque values)
- // output: 3 omegadot values, 3 vdot values, num_links q_double_dot values
- // (existing contents of output array are replaced)
- // calcAccelerationDeltasMultiDof must have been called first.
- void calcAccelerationDeltasMultiDof(const btScalar *force, btScalar *output,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v) const;
-
- void applyDeltaVeeMultiDof2(const btScalar *delta_vee, btScalar multiplier)
- {
- for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_deltaV[dof] += delta_vee[dof] * multiplier;
- }
- }
- void applyDeltaSplitVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
- {
- for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_splitV[dof] += delta_vee[dof] * multiplier;
- }
- }
- void addSplitV()
- {
- applyDeltaVeeMultiDof(&m_splitV[0], 1);
- }
- void substractSplitV()
- {
- applyDeltaVeeMultiDof(&m_splitV[0], -1);
-
- for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_splitV[dof] = 0.f;
- }
- }
- void processDeltaVeeMultiDof2()
- {
- applyDeltaVeeMultiDof(&m_deltaV[0], 1);
-
- for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_deltaV[dof] = 0.f;
- }
- }
-
- void applyDeltaVeeMultiDof(const btScalar *delta_vee, btScalar multiplier)
- {
- //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- // printf("%.4f ", delta_vee[dof]*multiplier);
- //printf("\n");
-
- //btScalar sum = 0;
- //for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- //{
- // sum += delta_vee[dof]*multiplier*delta_vee[dof]*multiplier;
- //}
- //btScalar l = btSqrt(sum);
-
- //if (l>m_maxAppliedImpulse)
- //{
- // multiplier *= m_maxAppliedImpulse/l;
- //}
-
- for (int dof = 0; dof < 6 + getNumDofs(); ++dof)
- {
- m_realBuf[dof] += delta_vee[dof] * multiplier;
- btClamp(m_realBuf[dof], -m_maxCoordinateVelocity, m_maxCoordinateVelocity);
- }
- }
-
- // timestep the positions (given current velocities).
- void stepPositionsMultiDof(btScalar dt, btScalar *pq = 0, btScalar *pqd = 0);
-
- // predict the positions
- void predictPositionsMultiDof(btScalar dt);
-
- //
- // contacts
- //
-
- // This routine fills out a contact constraint jacobian for this body.
- // the 'normal' supplied must be -n for body1 or +n for body2 of the contact.
- // 'normal' & 'contact_point' are both given in world coordinates.
-
- void fillContactJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const { fillConstraintJacobianMultiDof(link, contact_point, btVector3(0, 0, 0), normal, jac, scratch_r, scratch_v, scratch_m); }
-
- //a more general version of fillContactJacobianMultiDof which does not assume..
- //.. that the constraint in question is contact or, to be more precise, constrains linear velocity only
- void fillConstraintJacobianMultiDof(int link,
- const btVector3 &contact_point,
- const btVector3 &normal_ang,
- const btVector3 &normal_lin,
- btScalar *jac,
- btAlignedObjectArray<btScalar> &scratch_r,
- btAlignedObjectArray<btVector3> &scratch_v,
- btAlignedObjectArray<btMatrix3x3> &scratch_m) const;
-
- //
- // sleeping
- //
- void setCanSleep(bool canSleep)
- {
- if (m_canWakeup)
- {
- m_canSleep = canSleep;
- }
- }
-
- bool getCanSleep() const
- {
- return m_canSleep;
- }
-
- bool getCanWakeup() const
- {
- return m_canWakeup;
- }
-
- void setCanWakeup(bool canWakeup)
- {
- m_canWakeup = canWakeup;
- }
- bool isAwake() const
- {
- return m_awake;
- }
- void wakeUp();
- void goToSleep();
- void checkMotionAndSleepIfRequired(btScalar timestep);
-
- bool hasFixedBase() const;
-
- bool isBaseKinematic() const;
-
- bool isBaseStaticOrKinematic() const;
-
- // set the dynamic type in the base's collision flags.
- void setBaseDynamicType(int dynamicType);
-
- void setFixedBase(bool fixedBase)
- {
- m_fixedBase = fixedBase;
- if(m_fixedBase)
- setBaseDynamicType(btCollisionObject::CF_STATIC_OBJECT);
- else
- setBaseDynamicType(btCollisionObject::CF_DYNAMIC_OBJECT);
- }
-
- int getCompanionId() const
- {
- return m_companionId;
- }
- void setCompanionId(int id)
- {
- //printf("for %p setCompanionId(%d)\n",this, id);
- m_companionId = id;
- }
-
- void setNumLinks(int numLinks) //careful: when changing the number of m_links, make sure to re-initialize or update existing m_links
- {
- m_links.resize(numLinks);
- }
-
- btScalar getLinearDamping() const
- {
- return m_linearDamping;
- }
- void setLinearDamping(btScalar damp)
- {
- m_linearDamping = damp;
- }
- btScalar getAngularDamping() const
- {
- return m_angularDamping;
- }
- void setAngularDamping(btScalar damp)
- {
- m_angularDamping = damp;
- }
-
- bool getUseGyroTerm() const
- {
- return m_useGyroTerm;
- }
- void setUseGyroTerm(bool useGyro)
- {
- m_useGyroTerm = useGyro;
- }
- btScalar getMaxCoordinateVelocity() const
- {
- return m_maxCoordinateVelocity;
- }
- void setMaxCoordinateVelocity(btScalar maxVel)
- {
- m_maxCoordinateVelocity = maxVel;
- }
-
- btScalar getMaxAppliedImpulse() const
- {
- return m_maxAppliedImpulse;
- }
- void setMaxAppliedImpulse(btScalar maxImp)
- {
- m_maxAppliedImpulse = maxImp;
- }
- void setHasSelfCollision(bool hasSelfCollision)
- {
- m_hasSelfCollision = hasSelfCollision;
- }
- bool hasSelfCollision() const
- {
- return m_hasSelfCollision;
- }
-
- void finalizeMultiDof();
-
- void useRK4Integration(bool use) { m_useRK4 = use; }
- bool isUsingRK4Integration() const { return m_useRK4; }
- void useGlobalVelocities(bool use) { m_useGlobalVelocities = use; }
- bool isUsingGlobalVelocities() const { return m_useGlobalVelocities; }
-
- bool isPosUpdated() const
- {
- return __posUpdated;
- }
- void setPosUpdated(bool updated)
- {
- __posUpdated = updated;
- }
-
- //internalNeedsJointFeedback is for internal use only
- bool internalNeedsJointFeedback() const
- {
- return m_internalNeedsJointFeedback;
- }
- void forwardKinematics(btAlignedObjectArray<btQuaternion>& world_to_local, btAlignedObjectArray<btVector3> & local_origin);
-
- void compTreeLinkVelocities(btVector3 * omega, btVector3 * vel) const;
-
- void updateCollisionObjectWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
- void updateCollisionObjectInterpolationWorldTransforms(btAlignedObjectArray<btQuaternion> & world_to_local, btAlignedObjectArray<btVector3> & local_origin);
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char *serialize(void *dataBuffer, class btSerializer *serializer) const;
-
- const char *getBaseName() const
- {
- return m_baseName;
- }
- ///memory of setBaseName needs to be manager by user
- void setBaseName(const char *name)
- {
- m_baseName = name;
- }
-
- ///users can point to their objects, userPointer is not used by Bullet
- void *getUserPointer() const
- {
- return m_userObjectPointer;
- }
-
- int getUserIndex() const
- {
- return m_userIndex;
- }
-
- int getUserIndex2() const
- {
- return m_userIndex2;
- }
- ///users can point to their objects, userPointer is not used by Bullet
- void setUserPointer(void *userPointer)
- {
- m_userObjectPointer = userPointer;
- }
-
- ///users can point to their objects, userPointer is not used by Bullet
- void setUserIndex(int index)
- {
- m_userIndex = index;
- }
-
- void setUserIndex2(int index)
- {
- m_userIndex2 = index;
- }
-
- static void spatialTransform(const btMatrix3x3 &rotation_matrix, // rotates vectors in 'from' frame to vectors in 'to' frame
- const btVector3 &displacement, // vector from origin of 'from' frame to origin of 'to' frame, in 'to' coordinates
- const btVector3 &top_in, // top part of input vector
- const btVector3 &bottom_in, // bottom part of input vector
- btVector3 &top_out, // top part of output vector
- btVector3 &bottom_out); // bottom part of output vector
-
- void setLinkDynamicType(const int i, int type);
-
- bool isLinkStaticOrKinematic(const int i) const;
-
- bool isLinkKinematic(const int i) const;
-
- bool isLinkAndAllAncestorsStaticOrKinematic(const int i) const;
-
- bool isLinkAndAllAncestorsKinematic(const int i) const;
-
- void setSleepThreshold(btScalar sleepThreshold)
- {
- m_sleepEpsilon = sleepThreshold;
- }
-
- void setSleepTimeout(btScalar sleepTimeout)
- {
- this->m_sleepTimeout = sleepTimeout;
- }
-
-
-private:
- btMultiBody(const btMultiBody &); // not implemented
- void operator=(const btMultiBody &); // not implemented
-
- void solveImatrix(const btVector3 &rhs_top, const btVector3 &rhs_bot, btScalar result[6]) const;
- void solveImatrix(const btSpatialForceVector &rhs, btSpatialMotionVector &result) const;
-
- void updateLinksDofOffsets()
- {
- int dofOffset = 0, cfgOffset = 0;
- for (int bidx = 0; bidx < m_links.size(); ++bidx)
- {
- m_links[bidx].m_dofOffset = dofOffset;
- m_links[bidx].m_cfgOffset = cfgOffset;
- dofOffset += m_links[bidx].m_dofCount;
- cfgOffset += m_links[bidx].m_posVarCount;
- }
- }
-
- void mulMatrix(const btScalar *pA, const btScalar *pB, int rowsA, int colsA, int rowsB, int colsB, btScalar *pC) const;
-
-private:
- btMultiBodyLinkCollider *m_baseCollider; //can be NULL
- const char *m_baseName; //memory needs to be manager by user!
-
- btVector3 m_basePos; // position of COM of base (world frame)
- btVector3 m_basePos_interpolate; // position of interpolated COM of base (world frame)
- btQuaternion m_baseQuat; // rotates world points into base frame
- btQuaternion m_baseQuat_interpolate;
-
- btScalar m_baseMass; // mass of the base
- btVector3 m_baseInertia; // inertia of the base (in local frame; diagonal)
-
- btVector3 m_baseForce; // external force applied to base. World frame.
- btVector3 m_baseTorque; // external torque applied to base. World frame.
-
- btVector3 m_baseConstraintForce; // external force applied to base. World frame.
- btVector3 m_baseConstraintTorque; // external torque applied to base. World frame.
-
- btAlignedObjectArray<btMultibodyLink> m_links; // array of m_links, excluding the base. index from 0 to num_links-1.
-
- //
- // realBuf:
- // offset size array
- // 0 6 + num_links v (base_omega; base_vel; joint_vels) MULTIDOF [sysdof x sysdof for D matrices (TOO MUCH!) + pos_delta which is sys-cfg sized]
- // 6+num_links num_links D
- //
- // vectorBuf:
- // offset size array
- // 0 num_links h_top
- // num_links num_links h_bottom
- //
- // matrixBuf:
- // offset size array
- // 0 num_links+1 rot_from_parent
- //
- btAlignedObjectArray<btScalar> m_splitV;
- btAlignedObjectArray<btScalar> m_deltaV;
- btAlignedObjectArray<btScalar> m_realBuf;
- btAlignedObjectArray<btVector3> m_vectorBuf;
- btAlignedObjectArray<btMatrix3x3> m_matrixBuf;
-
- btMatrix3x3 m_cachedInertiaTopLeft;
- btMatrix3x3 m_cachedInertiaTopRight;
- btMatrix3x3 m_cachedInertiaLowerLeft;
- btMatrix3x3 m_cachedInertiaLowerRight;
- bool m_cachedInertiaValid;
-
- bool m_fixedBase;
-
- // Sleep parameters.
- bool m_awake;
- bool m_canSleep;
- bool m_canWakeup;
- btScalar m_sleepTimer;
- btScalar m_sleepEpsilon;
- btScalar m_sleepTimeout;
-
- void *m_userObjectPointer;
- int m_userIndex2;
- int m_userIndex;
-
- int m_companionId;
- btScalar m_linearDamping;
- btScalar m_angularDamping;
- bool m_useGyroTerm;
- btScalar m_maxAppliedImpulse;
- btScalar m_maxCoordinateVelocity;
- bool m_hasSelfCollision;
-
- bool __posUpdated;
- int m_dofCount, m_posVarCnt;
-
- bool m_useRK4, m_useGlobalVelocities;
- //for global velocities, see 8.3.2B Proposed resolution in Jakub Stepien PhD Thesis
- //https://drive.google.com/file/d/0Bz3vEa19XOYGNWdZWGpMdUdqVmZ5ZVBOaEh4ZnpNaUxxZFNV/view?usp=sharing
-
- ///the m_needsJointFeedback gets updated/computed during the stepVelocitiesMultiDof and it for internal usage only
- bool m_internalNeedsJointFeedback;
-
- //If enabled, calculate the velocity based on kinematic transform changes. Currently only implemented for the base.
- bool m_kinematic_calculate_velocity;
-};
-
-struct btMultiBodyLinkDoubleData
-{
- btQuaternionDoubleData m_zeroRotParentToThis;
- btVector3DoubleData m_parentComToThisPivotOffset;
- btVector3DoubleData m_thisPivotToThisComOffset;
- btVector3DoubleData m_jointAxisTop[6];
- btVector3DoubleData m_jointAxisBottom[6];
-
- btVector3DoubleData m_linkInertia; // inertia of the base (in local frame; diagonal)
- btVector3DoubleData m_absFrameTotVelocityTop;
- btVector3DoubleData m_absFrameTotVelocityBottom;
- btVector3DoubleData m_absFrameLocVelocityTop;
- btVector3DoubleData m_absFrameLocVelocityBottom;
-
- double m_linkMass;
- int m_parentIndex;
- int m_jointType;
-
- int m_dofCount;
- int m_posVarCount;
- double m_jointPos[7];
- double m_jointVel[6];
- double m_jointTorque[6];
-
- double m_jointDamping;
- double m_jointFriction;
- double m_jointLowerLimit;
- double m_jointUpperLimit;
- double m_jointMaxForce;
- double m_jointMaxVelocity;
-
- char *m_linkName;
- char *m_jointName;
- btCollisionObjectDoubleData *m_linkCollider;
- char *m_paddingPtr;
-};
-
-struct btMultiBodyLinkFloatData
-{
- btQuaternionFloatData m_zeroRotParentToThis;
- btVector3FloatData m_parentComToThisPivotOffset;
- btVector3FloatData m_thisPivotToThisComOffset;
- btVector3FloatData m_jointAxisTop[6];
- btVector3FloatData m_jointAxisBottom[6];
- btVector3FloatData m_linkInertia; // inertia of the base (in local frame; diagonal)
- btVector3FloatData m_absFrameTotVelocityTop;
- btVector3FloatData m_absFrameTotVelocityBottom;
- btVector3FloatData m_absFrameLocVelocityTop;
- btVector3FloatData m_absFrameLocVelocityBottom;
-
- int m_dofCount;
- float m_linkMass;
- int m_parentIndex;
- int m_jointType;
-
- float m_jointPos[7];
- float m_jointVel[6];
- float m_jointTorque[6];
- int m_posVarCount;
- float m_jointDamping;
- float m_jointFriction;
- float m_jointLowerLimit;
- float m_jointUpperLimit;
- float m_jointMaxForce;
- float m_jointMaxVelocity;
-
- char *m_linkName;
- char *m_jointName;
- btCollisionObjectFloatData *m_linkCollider;
- char *m_paddingPtr;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btMultiBodyDoubleData
-{
- btVector3DoubleData m_baseWorldPosition;
- btQuaternionDoubleData m_baseWorldOrientation;
- btVector3DoubleData m_baseLinearVelocity;
- btVector3DoubleData m_baseAngularVelocity;
- btVector3DoubleData m_baseInertia; // inertia of the base (in local frame; diagonal)
- double m_baseMass;
- int m_numLinks;
- char m_padding[4];
-
- char *m_baseName;
- btMultiBodyLinkDoubleData *m_links;
- btCollisionObjectDoubleData *m_baseCollider;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btMultiBodyFloatData
-{
- btVector3FloatData m_baseWorldPosition;
- btQuaternionFloatData m_baseWorldOrientation;
- btVector3FloatData m_baseLinearVelocity;
- btVector3FloatData m_baseAngularVelocity;
-
- btVector3FloatData m_baseInertia; // inertia of the base (in local frame; diagonal)
- float m_baseMass;
- int m_numLinks;
-
- char *m_baseName;
- btMultiBodyLinkFloatData *m_links;
- btCollisionObjectFloatData *m_baseCollider;
-};
-
-#endif
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
deleted file mode 100644
index 00d5fd5609..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-#include "btMultiBodyConstraint.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "btMultiBodyPoint2Point.h" //for testing (BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST macro)
-
-btMultiBodyConstraint::btMultiBodyConstraint(btMultiBody* bodyA, btMultiBody* bodyB, int linkA, int linkB, int numRows, bool isUnilateral, int type)
- : m_bodyA(bodyA),
- m_bodyB(bodyB),
- m_linkA(linkA),
- m_linkB(linkB),
- m_type(type),
- m_numRows(numRows),
- m_jacSizeA(0),
- m_jacSizeBoth(0),
- m_isUnilateral(isUnilateral),
- m_numDofsFinalized(-1),
- m_maxAppliedImpulse(100)
-{
-}
-
-void btMultiBodyConstraint::updateJacobianSizes()
-{
- if (m_bodyA)
- {
- m_jacSizeA = (6 + m_bodyA->getNumDofs());
- }
-
- if (m_bodyB)
- {
- m_jacSizeBoth = m_jacSizeA + 6 + m_bodyB->getNumDofs();
- }
- else
- m_jacSizeBoth = m_jacSizeA;
-}
-
-void btMultiBodyConstraint::allocateJacobiansMultiDof()
-{
- updateJacobianSizes();
-
- m_posOffset = ((1 + m_jacSizeBoth) * m_numRows);
- m_data.resize((2 + m_jacSizeBoth) * m_numRows);
-}
-
-btMultiBodyConstraint::~btMultiBodyConstraint()
-{
-}
-
-void btMultiBodyConstraint::applyDeltaVee(btMultiBodyJacobianData& data, btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
-{
- for (int i = 0; i < ndof; ++i)
- data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
-}
-
-btScalar btMultiBodyConstraint::fillMultiBodyConstraint(btMultiBodySolverConstraint& solverConstraint,
- btMultiBodyJacobianData& data,
- btScalar* jacOrgA, btScalar* jacOrgB,
- const btVector3& constraintNormalAng,
- const btVector3& constraintNormalLin,
- const btVector3& posAworld, const btVector3& posBworld,
- btScalar posError,
- const btContactSolverInfo& infoGlobal,
- btScalar lowerLimit, btScalar upperLimit,
- bool angConstraint,
- btScalar relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip,
- btScalar damping)
-{
- solverConstraint.m_multiBodyA = m_bodyA;
- solverConstraint.m_multiBodyB = m_bodyB;
- solverConstraint.m_linkA = m_linkA;
- solverConstraint.m_linkB = m_linkB;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
-
- btSolverBody* bodyA = multiBodyA ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdA);
- btSolverBody* bodyB = multiBodyB ? 0 : &data.m_solverBodyPool->at(solverConstraint.m_solverBodyIdB);
-
- btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
- btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
-
- btVector3 rel_pos1, rel_pos2; //these two used to be inited to posAworld and posBworld (respectively) but it does not seem necessary
- if (bodyA)
- rel_pos1 = posAworld - bodyA->getWorldTransform().getOrigin();
- if (bodyB)
- rel_pos2 = posBworld - bodyB->getWorldTransform().getOrigin();
-
- if (multiBodyA)
- {
- if (solverConstraint.m_linkA < 0)
- {
- rel_pos1 = posAworld - multiBodyA->getBasePos();
- }
- else
- {
- rel_pos1 = posAworld - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofA = multiBodyA->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
-
- if (solverConstraint.m_deltaVelAindex < 0)
- {
- solverConstraint.m_deltaVelAindex = data.m_deltaVelocities.size();
- multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofA);
- }
- else
- {
- btAssert(data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
- }
-
- //determine jacobian of this 1D constraint in terms of multibodyA's degrees of freedom
- //resize..
- solverConstraint.m_jacAindex = data.m_jacobians.size();
- data.m_jacobians.resize(data.m_jacobians.size() + ndofA);
- //copy/determine
- if (jacOrgA)
- {
- for (int i = 0; i < ndofA; i++)
- data.m_jacobians[solverConstraint.m_jacAindex + i] = jacOrgA[i];
- }
- else
- {
- btScalar* jac1 = &data.m_jacobians[solverConstraint.m_jacAindex];
- //multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
- multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, posAworld, constraintNormalAng, constraintNormalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
- }
-
- //determine the velocity response of multibodyA to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
- //resize..
- data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofA); //=> each constraint row has the constrained tree dofs allocated in m_deltaVelocitiesUnitImpulse
- btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
- btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- //determine..
- multiBodyA->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacAindex], delta, data.scratch_r, data.scratch_v);
-
- btVector3 torqueAxis0;
- if (angConstraint)
- {
- torqueAxis0 = constraintNormalAng;
- }
- else
- {
- torqueAxis0 = rel_pos1.cross(constraintNormalLin);
- }
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = constraintNormalLin;
- }
- else //if(rb0)
- {
- btVector3 torqueAxis0;
- if (angConstraint)
- {
- torqueAxis0 = constraintNormalAng;
- }
- else
- {
- torqueAxis0 = rel_pos1.cross(constraintNormalLin);
- }
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = constraintNormalLin;
- }
-
- if (multiBodyB)
- {
- if (solverConstraint.m_linkB < 0)
- {
- rel_pos2 = posBworld - multiBodyB->getBasePos();
- }
- else
- {
- rel_pos2 = posBworld - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofB = multiBodyB->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex < 0)
- {
- solverConstraint.m_deltaVelBindex = data.m_deltaVelocities.size();
- multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- data.m_deltaVelocities.resize(data.m_deltaVelocities.size() + ndofB);
- }
-
- //determine jacobian of this 1D constraint in terms of multibodyB's degrees of freedom
- //resize..
- solverConstraint.m_jacBindex = data.m_jacobians.size();
- data.m_jacobians.resize(data.m_jacobians.size() + ndofB);
- //copy/determine..
- if (jacOrgB)
- {
- for (int i = 0; i < ndofB; i++)
- data.m_jacobians[solverConstraint.m_jacBindex + i] = jacOrgB[i];
- }
- else
- {
- //multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
- multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, posBworld, -constraintNormalAng, -constraintNormalLin, &data.m_jacobians[solverConstraint.m_jacBindex], data.scratch_r, data.scratch_v, data.scratch_m);
- }
-
- //determine velocity response of multibodyB to reaction impulses of this constraint (i.e. A[i,i] for i=1,...n_con: multibody's inverse inertia with respect to this 1D constraint)
- //resize..
- data.m_deltaVelocitiesUnitImpulse.resize(data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
- btAssert(data.m_jacobians.size() == data.m_deltaVelocitiesUnitImpulse.size());
- btScalar* delta = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- //determine..
- multiBodyB->calcAccelerationDeltasMultiDof(&data.m_jacobians[solverConstraint.m_jacBindex], delta, data.scratch_r, data.scratch_v);
-
- btVector3 torqueAxis1;
- if (angConstraint)
- {
- torqueAxis1 = constraintNormalAng;
- }
- else
- {
- torqueAxis1 = rel_pos2.cross(constraintNormalLin);
- }
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -constraintNormalLin;
- }
- else //if(rb1)
- {
- btVector3 torqueAxis1;
- if (angConstraint)
- {
- torqueAxis1 = constraintNormalAng;
- }
- else
- {
- torqueAxis1 = rel_pos2.cross(constraintNormalLin);
- }
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -constraintNormalLin;
- }
- {
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- btScalar* jacB = 0;
- btScalar* jacA = 0;
- btScalar* deltaVelA = 0;
- btScalar* deltaVelB = 0;
- int ndofA = 0;
- //determine the "effective mass" of the constrained multibodyA with respect to this 1D constraint (i.e. 1/A[i,i])
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
- deltaVelA = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- {
- btScalar j = jacA[i];
- btScalar l = deltaVelA[i];
- denom0 += j * l;
- }
- }
- else if (rb0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- if (angConstraint)
- {
- denom0 = constraintNormalAng.dot(solverConstraint.m_angularComponentA);
- }
- else
- {
- denom0 = rb0->getInvMass() + constraintNormalLin.dot(vec);
- }
- }
- //
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
- deltaVelB = &data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- {
- btScalar j = jacB[i];
- btScalar l = deltaVelB[i];
- denom1 += j * l;
- }
- }
- else if (rb1)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- if (angConstraint)
- {
- denom1 = constraintNormalAng.dot(-solverConstraint.m_angularComponentB);
- }
- else
- {
- denom1 = rb1->getInvMass() + constraintNormalLin.dot(vec);
- }
- }
-
- //
- btScalar d = denom0 + denom1;
- if (d > SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation / (d);
- }
- else
- {
- //disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
- }
-
- //compute rhs and remaining solverConstraint fields
- btScalar penetration = isFriction ? 0 : posError;
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
- {
- btVector3 vel1, vel2;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* jacA = &data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- }
- else if (rb0)
- {
- rel_vel += rb0->getLinearVelocity().dot(solverConstraint.m_contactNormal1);
- rel_vel += rb0->getAngularVelocity().dot(solverConstraint.m_relpos1CrossNormal);
- }
- if (multiBodyB)
- {
- ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* jacB = &data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
- }
- else if (rb1)
- {
- rel_vel += rb1->getLinearVelocity().dot(solverConstraint.m_contactNormal2);
- rel_vel += rb1->getAngularVelocity().dot(solverConstraint.m_relpos2CrossNormal);
- }
-
- solverConstraint.m_friction = 0.f; //cp.m_combinedFriction;
- }
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- btScalar positionalError = 0.f;
- btScalar velocityError = (desiredVelocity - rel_vel) * damping;
-
- btScalar erp = infoGlobal.m_erp2;
-
- //split impulse is not implemented yet for btMultiBody*
- //if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- erp = infoGlobal.m_erp;
- }
-
- positionalError = -penetration * erp / infoGlobal.m_timeStep;
-
- btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
-
- //split impulse is not implemented yet for btMultiBody*
-
- // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- }
- /*else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- */
-
- solverConstraint.m_cfm = 0.f;
- solverConstraint.m_lowerLimit = lowerLimit;
- solverConstraint.m_upperLimit = upperLimit;
- }
-
- return rel_vel;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h
deleted file mode 100644
index 1aaa07b69e..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraint.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_CONSTRAINT_H
-#define BT_MULTIBODY_CONSTRAINT_H
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "btMultiBody.h"
-
-
-//Don't change any of the existing enum values, so add enum types at the end for serialization compatibility
-enum btTypedMultiBodyConstraintType
-{
- MULTIBODY_CONSTRAINT_LIMIT=3,
- MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR,
- MULTIBODY_CONSTRAINT_GEAR,
- MULTIBODY_CONSTRAINT_POINT_TO_POINT,
- MULTIBODY_CONSTRAINT_SLIDER,
- MULTIBODY_CONSTRAINT_SPHERICAL_MOTOR,
- MULTIBODY_CONSTRAINT_FIXED,
-
- MAX_MULTIBODY_CONSTRAINT_TYPE,
-};
-
-class btMultiBody;
-struct btSolverInfo;
-
-#include "btMultiBodySolverConstraint.h"
-
-struct btMultiBodyJacobianData
-{
- btAlignedObjectArray<btScalar> m_jacobians;
- btAlignedObjectArray<btScalar> m_deltaVelocitiesUnitImpulse; //holds the joint-space response of the corresp. tree to the test impulse in each constraint space dimension
- btAlignedObjectArray<btScalar> m_deltaVelocities; //holds joint-space vectors of all the constrained trees accumulating the effect of corrective impulses applied in SI
- btAlignedObjectArray<btScalar> scratch_r;
- btAlignedObjectArray<btVector3> scratch_v;
- btAlignedObjectArray<btMatrix3x3> scratch_m;
- btAlignedObjectArray<btSolverBody>* m_solverBodyPool;
- int m_fixedBodyId;
-};
-
-ATTRIBUTE_ALIGNED16(class)
-btMultiBodyConstraint
-{
-protected:
- btMultiBody* m_bodyA;
- btMultiBody* m_bodyB;
- int m_linkA;
- int m_linkB;
-
- int m_type; //btTypedMultiBodyConstraintType
-
- int m_numRows;
- int m_jacSizeA;
- int m_jacSizeBoth;
- int m_posOffset;
-
- bool m_isUnilateral;
- int m_numDofsFinalized;
- btScalar m_maxAppliedImpulse;
-
- // warning: the data block lay out is not consistent for all constraints
- // data block laid out as follows:
- // cached impulses. (one per row.)
- // jacobians. (interleaved, row1 body1 then row1 body2 then row2 body 1 etc)
- // positions. (one per row.)
- btAlignedObjectArray<btScalar> m_data;
-
- void applyDeltaVee(btMultiBodyJacobianData & data, btScalar * delta_vee, btScalar impulse, int velocityIndex, int ndof);
-
- btScalar fillMultiBodyConstraint(btMultiBodySolverConstraint & solverConstraint,
- btMultiBodyJacobianData & data,
- btScalar * jacOrgA, btScalar * jacOrgB,
- const btVector3& constraintNormalAng,
-
- const btVector3& constraintNormalLin,
- const btVector3& posAworld, const btVector3& posBworld,
- btScalar posError,
- const btContactSolverInfo& infoGlobal,
- btScalar lowerLimit, btScalar upperLimit,
- bool angConstraint = false,
-
- btScalar relaxation = 1.f,
- bool isFriction = false, btScalar desiredVelocity = 0, btScalar cfmSlip = 0, btScalar damping = 1.0);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultiBodyConstraint(btMultiBody * bodyA, btMultiBody * bodyB, int linkA, int linkB, int numRows, bool isUnilateral, int type);
- virtual ~btMultiBodyConstraint();
-
- void updateJacobianSizes();
- void allocateJacobiansMultiDof();
-
- int getConstraintType() const
- {
- return m_type;
- }
- //many constraints have setFrameInB/setPivotInB. Will use 'getConstraintType' later.
- virtual void setFrameInB(const btMatrix3x3& frameInB) {}
- virtual void setPivotInB(const btVector3& pivotInB) {}
-
- virtual void finalizeMultiDof() = 0;
-
- virtual int getIslandIdA() const = 0;
- virtual int getIslandIdB() const = 0;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
- btMultiBodyJacobianData & data,
- const btContactSolverInfo& infoGlobal) = 0;
-
- int getNumRows() const
- {
- return m_numRows;
- }
-
- btMultiBody* getMultiBodyA()
- {
- return m_bodyA;
- }
- btMultiBody* getMultiBodyB()
- {
- return m_bodyB;
- }
-
- int getLinkA() const
- {
- return m_linkA;
- }
- int getLinkB() const
- {
- return m_linkB;
- }
- void internalSetAppliedImpulse(int dof, btScalar appliedImpulse)
- {
- btAssert(dof >= 0);
- btAssert(dof < getNumRows());
- m_data[dof] = appliedImpulse;
- }
-
- btScalar getAppliedImpulse(int dof)
- {
- btAssert(dof >= 0);
- btAssert(dof < getNumRows());
- return m_data[dof];
- }
- // current constraint position
- // constraint is pos >= 0 for unilateral, or pos = 0 for bilateral
- // NOTE: ignored position for friction rows.
- btScalar getPosition(int row) const
- {
- return m_data[m_posOffset + row];
- }
-
- void setPosition(int row, btScalar pos)
- {
- m_data[m_posOffset + row] = pos;
- }
-
- bool isUnilateral() const
- {
- return m_isUnilateral;
- }
-
- // jacobian blocks.
- // each of size 6 + num_links. (jacobian2 is null if no body2.)
- // format: 3 'omega' coefficients, 3 'v' coefficients, then the 'qdot' coefficients.
- btScalar* jacobianA(int row)
- {
- return &m_data[m_numRows + row * m_jacSizeBoth];
- }
- const btScalar* jacobianA(int row) const
- {
- return &m_data[m_numRows + (row * m_jacSizeBoth)];
- }
- btScalar* jacobianB(int row)
- {
- return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
- }
- const btScalar* jacobianB(int row) const
- {
- return &m_data[m_numRows + (row * m_jacSizeBoth) + m_jacSizeA];
- }
-
- btScalar getMaxAppliedImpulse() const
- {
- return m_maxAppliedImpulse;
- }
- void setMaxAppliedImpulse(btScalar maxImp)
- {
- m_maxAppliedImpulse = maxImp;
- }
-
- virtual void debugDraw(class btIDebugDraw * drawer) = 0;
-
- virtual void setGearRatio(btScalar ratio) {}
- virtual void setGearAuxLink(int gearAuxLink) {}
- virtual void setRelativePositionTarget(btScalar relPosTarget) {}
- virtual void setErp(btScalar erp) {}
-};
-
-#endif //BT_MULTIBODY_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
deleted file mode 100644
index 2788367431..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btMultiBodyConstraintSolver.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "btMultiBodyLinkCollider.h"
-
-#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
-#include "btMultiBodyConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-
-#include "LinearMath/btQuickprof.h"
-#include "BulletDynamics/Featherstone/btMultiBodySolverConstraint.h"
-#include "LinearMath/btScalar.h"
-
-btScalar btMultiBodyConstraintSolver::solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- btScalar leastSquaredResidual = btSequentialImpulseConstraintSolver::solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- //solve featherstone non-contact constraints
- btScalar nonContactResidual = 0;
- //printf("m_multiBodyNonContactConstraints = %d\n",m_multiBodyNonContactConstraints.size());
- for (int i = 0; i < infoGlobal.m_numNonContactInnerIterations; ++i)
- {
- // reset the nonContactResdual to 0 at start of each inner iteration
- nonContactResidual = 0;
- for (int j = 0; j < m_multiBodyNonContactConstraints.size(); j++)
- {
- int index = iteration & 1 ? j : m_multiBodyNonContactConstraints.size() - 1 - j;
-
- btMultiBodySolverConstraint& constraint = m_multiBodyNonContactConstraints[index];
-
- btScalar residual = resolveSingleConstraintRowGeneric(constraint);
- nonContactResidual = btMax(nonContactResidual, residual * residual);
-
- if (constraint.m_multiBodyA)
- constraint.m_multiBodyA->setPosUpdated(false);
- if (constraint.m_multiBodyB)
- constraint.m_multiBodyB->setPosUpdated(false);
- }
- }
- leastSquaredResidual = btMax(leastSquaredResidual, nonContactResidual);
-
- //solve featherstone normal contact
- for (int j0 = 0; j0 < m_multiBodyNormalContactConstraints.size(); j0++)
- {
- int index = j0; //iteration&1? j0 : m_multiBodyNormalContactConstraints.size()-1-j0;
-
- btMultiBodySolverConstraint& constraint = m_multiBodyNormalContactConstraints[index];
- btScalar residual = 0.f;
-
- if (iteration < infoGlobal.m_numIterations)
- {
- residual = resolveSingleConstraintRowGeneric(constraint);
- }
-
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
-
- if (constraint.m_multiBodyA)
- constraint.m_multiBodyA->setPosUpdated(false);
- if (constraint.m_multiBodyB)
- constraint.m_multiBodyB->setPosUpdated(false);
- }
-
- //solve featherstone frictional contact
- if (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0))
- {
- for (int j1 = 0; j1 < this->m_multiBodySpinningFrictionContactConstraints.size(); j1++)
- {
- if (iteration < infoGlobal.m_numIterations)
- {
- int index = j1;
-
- btMultiBodySolverConstraint& frictionConstraint = m_multiBodySpinningFrictionContactConstraints[index];
- btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
- //adjust friction limits here
- if (totalImpulse > btScalar(0))
- {
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
-
- if (frictionConstraint.m_multiBodyA)
- frictionConstraint.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraint.m_multiBodyB)
- frictionConstraint.m_multiBodyB->setPosUpdated(false);
- }
- }
- }
-
- for (int j1 = 0; j1 < this->m_multiBodyTorsionalFrictionContactConstraints.size(); j1++)
- {
- if (iteration < infoGlobal.m_numIterations)
- {
- int index = j1; //iteration&1? j1 : m_multiBodyTorsionalFrictionContactConstraints.size()-1-j1;
-
- btMultiBodySolverConstraint& frictionConstraint = m_multiBodyTorsionalFrictionContactConstraints[index];
- btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
- j1++;
- int index2 = j1;
- btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyTorsionalFrictionContactConstraints[index2];
- //adjust friction limits here
- if (totalImpulse > btScalar(0) && frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
- {
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
- frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
- frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
-
- btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
-
- if (frictionConstraint.m_multiBodyA)
- frictionConstraint.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraint.m_multiBodyB)
- frictionConstraint.m_multiBodyB->setPosUpdated(false);
-
- if (frictionConstraintB.m_multiBodyA)
- frictionConstraintB.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraintB.m_multiBodyB)
- frictionConstraintB.m_multiBodyB->setPosUpdated(false);
- }
- }
- }
-
- for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
- {
- if (iteration < infoGlobal.m_numIterations)
- {
- int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
- btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
-
- btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
- j1++;
- int index2 = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
- btMultiBodySolverConstraint& frictionConstraintB = m_multiBodyFrictionContactConstraints[index2];
- btAssert(frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex);
-
- if (frictionConstraint.m_frictionIndex == frictionConstraintB.m_frictionIndex)
- {
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
- frictionConstraintB.m_lowerLimit = -(frictionConstraintB.m_friction * totalImpulse);
- frictionConstraintB.m_upperLimit = frictionConstraintB.m_friction * totalImpulse;
- btScalar residual = resolveConeFrictionConstraintRows(frictionConstraint, frictionConstraintB);
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
-
- if (frictionConstraintB.m_multiBodyA)
- frictionConstraintB.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraintB.m_multiBodyB)
- frictionConstraintB.m_multiBodyB->setPosUpdated(false);
-
- if (frictionConstraint.m_multiBodyA)
- frictionConstraint.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraint.m_multiBodyB)
- frictionConstraint.m_multiBodyB->setPosUpdated(false);
- }
- }
- }
- }
- else
- {
- for (int j1 = 0; j1 < this->m_multiBodyFrictionContactConstraints.size(); j1++)
- {
- if (iteration < infoGlobal.m_numIterations)
- {
- int index = j1; //iteration&1? j1 : m_multiBodyFrictionContactConstraints.size()-1-j1;
-
- btMultiBodySolverConstraint& frictionConstraint = m_multiBodyFrictionContactConstraints[index];
- btScalar totalImpulse = m_multiBodyNormalContactConstraints[frictionConstraint.m_frictionIndex].m_appliedImpulse;
- //adjust friction limits here
- if (totalImpulse > btScalar(0))
- {
- frictionConstraint.m_lowerLimit = -(frictionConstraint.m_friction * totalImpulse);
- frictionConstraint.m_upperLimit = frictionConstraint.m_friction * totalImpulse;
- btScalar residual = resolveSingleConstraintRowGeneric(frictionConstraint);
- leastSquaredResidual = btMax(leastSquaredResidual, residual * residual);
-
- if (frictionConstraint.m_multiBodyA)
- frictionConstraint.m_multiBodyA->setPosUpdated(false);
- if (frictionConstraint.m_multiBodyB)
- frictionConstraint.m_multiBodyB->setPosUpdated(false);
- }
- }
- }
- }
- return leastSquaredResidual;
-}
-
-btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- m_multiBodyNonContactConstraints.resize(0);
- m_multiBodyNormalContactConstraints.resize(0);
- m_multiBodyFrictionContactConstraints.resize(0);
- m_multiBodyTorsionalFrictionContactConstraints.resize(0);
- m_multiBodySpinningFrictionContactConstraints.resize(0);
-
- m_data.m_jacobians.resize(0);
- m_data.m_deltaVelocitiesUnitImpulse.resize(0);
- m_data.m_deltaVelocities.resize(0);
-
- for (int i = 0; i < numBodies; i++)
- {
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(bodies[i]);
- if (fcA)
- {
- fcA->m_multiBody->setCompanionId(-1);
- }
- }
-
- btScalar val = btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- return val;
-}
-
-void btMultiBodyConstraintSolver::applyDeltaVee(btScalar* delta_vee, btScalar impulse, int velocityIndex, int ndof)
-{
- for (int i = 0; i < ndof; ++i)
- m_data.m_deltaVelocities[velocityIndex + i] += delta_vee[i] * impulse;
-}
-
-btScalar btMultiBodyConstraintSolver::resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c)
-{
- btScalar deltaImpulse = c.m_rhs - btScalar(c.m_appliedImpulse) * c.m_cfm;
- btScalar deltaVelADotn = 0;
- btScalar deltaVelBDotn = 0;
- btSolverBody* bodyA = 0;
- btSolverBody* bodyB = 0;
- int ndofA = 0;
- int ndofB = 0;
-
- if (c.m_multiBodyA)
- {
- ndofA = c.m_multiBodyA->getNumDofs() + 6;
- for (int i = 0; i < ndofA; ++i)
- deltaVelADotn += m_data.m_jacobians[c.m_jacAindex + i] * m_data.m_deltaVelocities[c.m_deltaVelAindex + i];
- }
- else if (c.m_solverBodyIdA >= 0)
- {
- bodyA = &m_tmpSolverBodyPool[c.m_solverBodyIdA];
- deltaVelADotn += c.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + c.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
- }
-
- if (c.m_multiBodyB)
- {
- ndofB = c.m_multiBodyB->getNumDofs() + 6;
- for (int i = 0; i < ndofB; ++i)
- deltaVelBDotn += m_data.m_jacobians[c.m_jacBindex + i] * m_data.m_deltaVelocities[c.m_deltaVelBindex + i];
- }
- else if (c.m_solverBodyIdB >= 0)
- {
- bodyB = &m_tmpSolverBodyPool[c.m_solverBodyIdB];
- deltaVelBDotn += c.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + c.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
- }
-
- deltaImpulse -= deltaVelADotn * c.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
- deltaImpulse -= deltaVelBDotn * c.m_jacDiagABInv;
- const btScalar sum = btScalar(c.m_appliedImpulse) + deltaImpulse;
-
- if (sum < c.m_lowerLimit)
- {
- deltaImpulse = c.m_lowerLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_lowerLimit;
- }
- else if (sum > c.m_upperLimit)
- {
- deltaImpulse = c.m_upperLimit - c.m_appliedImpulse;
- c.m_appliedImpulse = c.m_upperLimit;
- }
- else
- {
- c.m_appliedImpulse = sum;
- }
-
- if (c.m_multiBodyA)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- c.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (c.m_solverBodyIdA >= 0)
- {
- bodyA->internalApplyImpulse(c.m_contactNormal1 * bodyA->internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- }
- if (c.m_multiBodyB)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse, c.m_deltaVelBindex, ndofB);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- c.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (c.m_solverBodyIdB >= 0)
- {
- bodyB->internalApplyImpulse(c.m_contactNormal2 * bodyB->internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- }
- btScalar deltaVel = deltaImpulse / c.m_jacDiagABInv;
- return deltaVel;
-}
-
-btScalar btMultiBodyConstraintSolver::resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB)
-{
- int ndofA = 0;
- int ndofB = 0;
- btSolverBody* bodyA = 0;
- btSolverBody* bodyB = 0;
- btScalar deltaImpulseB = 0.f;
- btScalar sumB = 0.f;
- {
- deltaImpulseB = cB.m_rhs - btScalar(cB.m_appliedImpulse) * cB.m_cfm;
- btScalar deltaVelADotn = 0;
- btScalar deltaVelBDotn = 0;
- if (cB.m_multiBodyA)
- {
- ndofA = cB.m_multiBodyA->getNumDofs() + 6;
- for (int i = 0; i < ndofA; ++i)
- deltaVelADotn += m_data.m_jacobians[cB.m_jacAindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelAindex + i];
- }
- else if (cB.m_solverBodyIdA >= 0)
- {
- bodyA = &m_tmpSolverBodyPool[cB.m_solverBodyIdA];
- deltaVelADotn += cB.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cB.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
- }
-
- if (cB.m_multiBodyB)
- {
- ndofB = cB.m_multiBodyB->getNumDofs() + 6;
- for (int i = 0; i < ndofB; ++i)
- deltaVelBDotn += m_data.m_jacobians[cB.m_jacBindex + i] * m_data.m_deltaVelocities[cB.m_deltaVelBindex + i];
- }
- else if (cB.m_solverBodyIdB >= 0)
- {
- bodyB = &m_tmpSolverBodyPool[cB.m_solverBodyIdB];
- deltaVelBDotn += cB.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cB.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
- }
-
- deltaImpulseB -= deltaVelADotn * cB.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
- deltaImpulseB -= deltaVelBDotn * cB.m_jacDiagABInv;
- sumB = btScalar(cB.m_appliedImpulse) + deltaImpulseB;
- }
-
- btScalar deltaImpulseA = 0.f;
- btScalar sumA = 0.f;
- const btMultiBodySolverConstraint& cA = cA1;
- {
- {
- deltaImpulseA = cA.m_rhs - btScalar(cA.m_appliedImpulse) * cA.m_cfm;
- btScalar deltaVelADotn = 0;
- btScalar deltaVelBDotn = 0;
- if (cA.m_multiBodyA)
- {
- ndofA = cA.m_multiBodyA->getNumDofs() + 6;
- for (int i = 0; i < ndofA; ++i)
- deltaVelADotn += m_data.m_jacobians[cA.m_jacAindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelAindex + i];
- }
- else if (cA.m_solverBodyIdA >= 0)
- {
- bodyA = &m_tmpSolverBodyPool[cA.m_solverBodyIdA];
- deltaVelADotn += cA.m_contactNormal1.dot(bodyA->internalGetDeltaLinearVelocity()) + cA.m_relpos1CrossNormal.dot(bodyA->internalGetDeltaAngularVelocity());
- }
-
- if (cA.m_multiBodyB)
- {
- ndofB = cA.m_multiBodyB->getNumDofs() + 6;
- for (int i = 0; i < ndofB; ++i)
- deltaVelBDotn += m_data.m_jacobians[cA.m_jacBindex + i] * m_data.m_deltaVelocities[cA.m_deltaVelBindex + i];
- }
- else if (cA.m_solverBodyIdB >= 0)
- {
- bodyB = &m_tmpSolverBodyPool[cA.m_solverBodyIdB];
- deltaVelBDotn += cA.m_contactNormal2.dot(bodyB->internalGetDeltaLinearVelocity()) + cA.m_relpos2CrossNormal.dot(bodyB->internalGetDeltaAngularVelocity());
- }
-
- deltaImpulseA -= deltaVelADotn * cA.m_jacDiagABInv; //m_jacDiagABInv = 1./denom
- deltaImpulseA -= deltaVelBDotn * cA.m_jacDiagABInv;
- sumA = btScalar(cA.m_appliedImpulse) + deltaImpulseA;
- }
- }
-
- if (sumA * sumA + sumB * sumB >= cA.m_lowerLimit * cB.m_lowerLimit)
- {
- btScalar angle = btAtan2(sumA, sumB);
- btScalar sumAclipped = btFabs(cA.m_lowerLimit * btSin(angle));
- btScalar sumBclipped = btFabs(cB.m_lowerLimit * btCos(angle));
-
- if (sumA < -sumAclipped)
- {
- deltaImpulseA = -sumAclipped - cA.m_appliedImpulse;
- cA.m_appliedImpulse = -sumAclipped;
- }
- else if (sumA > sumAclipped)
- {
- deltaImpulseA = sumAclipped - cA.m_appliedImpulse;
- cA.m_appliedImpulse = sumAclipped;
- }
- else
- {
- cA.m_appliedImpulse = sumA;
- }
-
- if (sumB < -sumBclipped)
- {
- deltaImpulseB = -sumBclipped - cB.m_appliedImpulse;
- cB.m_appliedImpulse = -sumBclipped;
- }
- else if (sumB > sumBclipped)
- {
- deltaImpulseB = sumBclipped - cB.m_appliedImpulse;
- cB.m_appliedImpulse = sumBclipped;
- }
- else
- {
- cB.m_appliedImpulse = sumB;
- }
- //deltaImpulseA = sumAclipped-cA.m_appliedImpulse;
- //cA.m_appliedImpulse = sumAclipped;
- //deltaImpulseB = sumBclipped-cB.m_appliedImpulse;
- //cB.m_appliedImpulse = sumBclipped;
- }
- else
- {
- cA.m_appliedImpulse = sumA;
- cB.m_appliedImpulse = sumB;
- }
-
- if (cA.m_multiBodyA)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA, cA.m_deltaVelAindex, ndofA);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cA.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacAindex], deltaImpulseA);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (cA.m_solverBodyIdA >= 0)
- {
- bodyA->internalApplyImpulse(cA.m_contactNormal1 * bodyA->internalGetInvMass(), cA.m_angularComponentA, deltaImpulseA);
- }
- if (cA.m_multiBodyB)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA, cA.m_deltaVelBindex, ndofB);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cA.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cA.m_jacBindex], deltaImpulseA);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (cA.m_solverBodyIdB >= 0)
- {
- bodyB->internalApplyImpulse(cA.m_contactNormal2 * bodyB->internalGetInvMass(), cA.m_angularComponentB, deltaImpulseA);
- }
-
- if (cB.m_multiBodyA)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB, cB.m_deltaVelAindex, ndofA);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cB.m_multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacAindex], deltaImpulseB);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (cB.m_solverBodyIdA >= 0)
- {
- bodyA->internalApplyImpulse(cB.m_contactNormal1 * bodyA->internalGetInvMass(), cB.m_angularComponentA, deltaImpulseB);
- }
- if (cB.m_multiBodyB)
- {
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB, cB.m_deltaVelBindex, ndofB);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- cB.m_multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[cB.m_jacBindex], deltaImpulseB);
-#endif //DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else if (cB.m_solverBodyIdB >= 0)
- {
- bodyB->internalApplyImpulse(cB.m_contactNormal2 * bodyB->internalGetInvMass(), cB.m_angularComponentB, deltaImpulseB);
- }
-
- btScalar deltaVel = deltaImpulseA / cA.m_jacDiagABInv + deltaImpulseB / cB.m_jacDiagABInv;
- return deltaVel;
-}
-
-void btMultiBodyConstraintSolver::setupMultiBodyContactConstraint(btMultiBodySolverConstraint& solverConstraint, const btVector3& contactNormal, const btScalar& appliedImpulse, btManifoldPoint& cp, const btContactSolverInfo& infoGlobal, btScalar& relaxation, bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
-{
- BT_PROFILE("setupMultiBodyContactConstraint");
- btVector3 rel_pos1;
- btVector3 rel_pos2;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
- btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
-
- btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
- btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
-
- if (bodyA)
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- if (bodyB)
- rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = infoGlobal.m_sor;
-
- btScalar invTimeStep = btScalar(1) / infoGlobal.m_timeStep;
-
- //cfm = 1 / ( dt * kp + kd )
- //erp = dt * kp / ( dt * kp + kd )
-
- btScalar cfm;
- btScalar erp;
- if (isFriction)
- {
- cfm = infoGlobal.m_frictionCFM;
- erp = infoGlobal.m_frictionERP;
- }
- else
- {
- cfm = infoGlobal.m_globalCfm;
- erp = infoGlobal.m_erp2;
-
- if ((cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM) || (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP))
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_CFM)
- cfm = cp.m_contactCFM;
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_HAS_CONTACT_ERP)
- erp = cp.m_contactERP;
- }
- else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_CONTACT_STIFFNESS_DAMPING)
- {
- btScalar denom = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1 + cp.m_combinedContactDamping1);
- if (denom < SIMD_EPSILON)
- {
- denom = SIMD_EPSILON;
- }
- cfm = btScalar(1) / denom;
- erp = (infoGlobal.m_timeStep * cp.m_combinedContactStiffness1) / denom;
- }
- }
- }
-
- cfm *= invTimeStep;
-
- if (multiBodyA)
- {
- if (solverConstraint.m_linkA < 0)
- {
- rel_pos1 = pos1 - multiBodyA->getBasePos();
- }
- else
- {
- rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
- }
- const int ndofA = multiBodyA->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
-
- if (solverConstraint.m_deltaVelAindex < 0)
- {
- solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
- multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
- }
- else
- {
- btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
- }
-
- solverConstraint.m_jacAindex = m_data.m_jacobians.size();
- m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- multiBodyA->fillContactJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), contactNormal, jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = contactNormal;
- }
- else
- {
- btVector3 torqueAxis0 = rel_pos1.cross(contactNormal);
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = contactNormal;
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
- }
-
- if (multiBodyB)
- {
- if (solverConstraint.m_linkB < 0)
- {
- rel_pos2 = pos2 - multiBodyB->getBasePos();
- }
- else
- {
- rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofB = multiBodyB->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex < 0)
- {
- solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
- multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
- }
-
- solverConstraint.m_jacBindex = m_data.m_jacobians.size();
-
- m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- multiBodyB->fillContactJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -contactNormal, &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -contactNormal;
- }
- else
- {
- btVector3 torqueAxis1 = rel_pos2.cross(contactNormal);
- solverConstraint.m_relpos2CrossNormal = -torqueAxis1;
- solverConstraint.m_contactNormal2 = -contactNormal;
-
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * -torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
- }
-
- {
- btVector3 vec;
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- btScalar* jacB = 0;
- btScalar* jacA = 0;
- btScalar* lambdaA = 0;
- btScalar* lambdaB = 0;
- int ndofA = 0;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- {
- btScalar j = jacA[i];
- btScalar l = lambdaA[i];
- denom0 += j * l;
- }
- }
- else
- {
- if (rb0)
- {
- vec = (solverConstraint.m_angularComponentA).cross(rel_pos1);
- denom0 = rb0->getInvMass() + contactNormal.dot(vec);
- }
- }
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- {
- btScalar j = jacB[i];
- btScalar l = lambdaB[i];
- denom1 += j * l;
- }
- }
- else
- {
- if (rb1)
- {
- vec = (-solverConstraint.m_angularComponentB).cross(rel_pos2);
- denom1 = rb1->getInvMass() + contactNormal.dot(vec);
- }
- }
-
- btScalar d = denom0 + denom1 + cfm;
- if (d > SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation / (d);
- }
- else
- {
- //disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
- }
-
- //compute rhs and remaining solverConstraint fields
-
- btScalar restitution = 0.f;
- btScalar distance = 0;
- if (!isFriction)
- {
- distance = cp.getDistance() + infoGlobal.m_linearSlop;
- }
- else
- {
- if (cp.m_contactPointFlags & BT_CONTACT_FLAG_FRICTION_ANCHOR)
- {
- distance = (cp.getPositionWorldOnA() - cp.getPositionWorldOnB()).dot(contactNormal);
- }
- }
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
- {
- btVector3 vel1, vel2;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- }
- else
- {
- if (rb0)
- {
- rel_vel += (rb0->getVelocityInLocalPoint(rel_pos1) +
- (rb0->getTotalTorque() * rb0->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos1) +
- rb0->getTotalForce() * rb0->getInvMass() * infoGlobal.m_timeStep)
- .dot(solverConstraint.m_contactNormal1);
- }
- }
- if (multiBodyB)
- {
- ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
- }
- else
- {
- if (rb1)
- {
- rel_vel += (rb1->getVelocityInLocalPoint(rel_pos2) +
- (rb1->getTotalTorque() * rb1->getInvInertiaTensorWorld() * infoGlobal.m_timeStep).cross(rel_pos2) +
- rb1->getTotalForce() * rb1->getInvMass() * infoGlobal.m_timeStep)
- .dot(solverConstraint.m_contactNormal2);
- }
- }
-
- solverConstraint.m_friction = cp.m_combinedFriction;
-
- if (!isFriction)
- {
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- }
- }
- }
-
- {
- btScalar positionalError = 0.f;
- btScalar velocityError = restitution - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
- if (isFriction)
- {
- positionalError = -distance * erp / infoGlobal.m_timeStep;
- }
- else
- {
- if (distance > 0)
- {
- positionalError = 0;
- velocityError -= distance / infoGlobal.m_timeStep;
- }
- else
- {
- positionalError = -distance * erp / infoGlobal.m_timeStep;
- }
- }
-
- btScalar penetrationImpulse = positionalError * solverConstraint.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
-
- if (!isFriction)
- {
- // if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- }
- /*else
- {
- //split position and velocity into rhs and m_rhsPenetration
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = penetrationImpulse;
- }
- */
- solverConstraint.m_lowerLimit = 0;
- solverConstraint.m_upperLimit = 1e10f;
- }
- else
- {
- solverConstraint.m_rhs = penetrationImpulse + velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
- }
-
- solverConstraint.m_cfm = cfm * solverConstraint.m_jacDiagABInv;
- }
-
- if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
- {
- if (btFabs(cp.m_prevRHS) > 1e-5 && cp.m_prevRHS < 2* solverConstraint.m_rhs && solverConstraint.m_rhs < 2*cp.m_prevRHS)
- {
- solverConstraint.m_appliedImpulse = isFriction ? 0 : cp.m_appliedImpulse / cp.m_prevRHS * solverConstraint.m_rhs * infoGlobal.m_articulatedWarmstartingFactor;
- if (solverConstraint.m_appliedImpulse < 0)
- solverConstraint.m_appliedImpulse = 0;
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- }
-
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
-
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
- }
- else
- {
- if (rb0)
- bodyA->internalApplyImpulse(solverConstraint.m_contactNormal1 * bodyA->internalGetInvMass() * rb0->getLinearFactor(), solverConstraint.m_angularComponentA, solverConstraint.m_appliedImpulse);
- }
- if (multiBodyB)
- {
- btScalar impulse = solverConstraint.m_appliedImpulse;
- btScalar* deltaV = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
- }
- else
- {
- if (rb1)
- bodyB->internalApplyImpulse(-solverConstraint.m_contactNormal2 * bodyB->internalGetInvMass() * rb1->getLinearFactor(), -solverConstraint.m_angularComponentB, -(btScalar)solverConstraint.m_appliedImpulse);
- }
- }
- }
- else
- {
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
- }
-}
-
-void btMultiBodyConstraintSolver::setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint& solverConstraint,
- const btVector3& constraintNormal,
- btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity, btScalar cfmSlip)
-{
- BT_PROFILE("setupMultiBodyRollingFrictionConstraint");
- btVector3 rel_pos1;
- btVector3 rel_pos2;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
-
- const btVector3& pos1 = cp.getPositionWorldOnA();
- const btVector3& pos2 = cp.getPositionWorldOnB();
-
- btSolverBody* bodyA = multiBodyA ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
- btSolverBody* bodyB = multiBodyB ? 0 : &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
-
- btRigidBody* rb0 = multiBodyA ? 0 : bodyA->m_originalBody;
- btRigidBody* rb1 = multiBodyB ? 0 : bodyB->m_originalBody;
-
- if (bodyA)
- rel_pos1 = pos1 - bodyA->getWorldTransform().getOrigin();
- if (bodyB)
- rel_pos2 = pos2 - bodyB->getWorldTransform().getOrigin();
-
- relaxation = infoGlobal.m_sor;
-
- // btScalar invTimeStep = btScalar(1)/infoGlobal.m_timeStep;
-
- if (multiBodyA)
- {
- if (solverConstraint.m_linkA < 0)
- {
- rel_pos1 = pos1 - multiBodyA->getBasePos();
- }
- else
- {
- rel_pos1 = pos1 - multiBodyA->getLink(solverConstraint.m_linkA).m_cachedWorldTransform.getOrigin();
- }
- const int ndofA = multiBodyA->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelAindex = multiBodyA->getCompanionId();
-
- if (solverConstraint.m_deltaVelAindex < 0)
- {
- solverConstraint.m_deltaVelAindex = m_data.m_deltaVelocities.size();
- multiBodyA->setCompanionId(solverConstraint.m_deltaVelAindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofA);
- }
- else
- {
- btAssert(m_data.m_deltaVelocities.size() >= solverConstraint.m_deltaVelAindex + ndofA);
- }
-
- solverConstraint.m_jacAindex = m_data.m_jacobians.size();
- m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofA);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofA);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- btScalar* jac1 = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- multiBodyA->fillConstraintJacobianMultiDof(solverConstraint.m_linkA, cp.getPositionWorldOnA(), constraintNormal, btVector3(0, 0, 0), jac1, m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- btScalar* delta = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- multiBodyA->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacAindex], delta, m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis0 = constraintNormal;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
- }
- else
- {
- btVector3 torqueAxis0 = constraintNormal;
- solverConstraint.m_relpos1CrossNormal = torqueAxis0;
- solverConstraint.m_contactNormal1 = btVector3(0, 0, 0);
- solverConstraint.m_angularComponentA = rb0 ? rb0->getInvInertiaTensorWorld() * torqueAxis0 * rb0->getAngularFactor() : btVector3(0, 0, 0);
- }
-
- if (multiBodyB)
- {
- if (solverConstraint.m_linkB < 0)
- {
- rel_pos2 = pos2 - multiBodyB->getBasePos();
- }
- else
- {
- rel_pos2 = pos2 - multiBodyB->getLink(solverConstraint.m_linkB).m_cachedWorldTransform.getOrigin();
- }
-
- const int ndofB = multiBodyB->getNumDofs() + 6;
-
- solverConstraint.m_deltaVelBindex = multiBodyB->getCompanionId();
- if (solverConstraint.m_deltaVelBindex < 0)
- {
- solverConstraint.m_deltaVelBindex = m_data.m_deltaVelocities.size();
- multiBodyB->setCompanionId(solverConstraint.m_deltaVelBindex);
- m_data.m_deltaVelocities.resize(m_data.m_deltaVelocities.size() + ndofB);
- }
-
- solverConstraint.m_jacBindex = m_data.m_jacobians.size();
-
- m_data.m_jacobians.resize(m_data.m_jacobians.size() + ndofB);
- m_data.m_deltaVelocitiesUnitImpulse.resize(m_data.m_deltaVelocitiesUnitImpulse.size() + ndofB);
- btAssert(m_data.m_jacobians.size() == m_data.m_deltaVelocitiesUnitImpulse.size());
-
- multiBodyB->fillConstraintJacobianMultiDof(solverConstraint.m_linkB, cp.getPositionWorldOnB(), -constraintNormal, btVector3(0, 0, 0), &m_data.m_jacobians[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v, m_data.scratch_m);
- multiBodyB->calcAccelerationDeltasMultiDof(&m_data.m_jacobians[solverConstraint.m_jacBindex], &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex], m_data.scratch_r, m_data.scratch_v);
-
- btVector3 torqueAxis1 = -constraintNormal;
- solverConstraint.m_relpos2CrossNormal = torqueAxis1;
- solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
- }
- else
- {
- btVector3 torqueAxis1 = -constraintNormal;
- solverConstraint.m_relpos2CrossNormal = torqueAxis1;
- solverConstraint.m_contactNormal2 = -btVector3(0, 0, 0);
-
- solverConstraint.m_angularComponentB = rb1 ? rb1->getInvInertiaTensorWorld() * torqueAxis1 * rb1->getAngularFactor() : btVector3(0, 0, 0);
- }
-
- {
- btScalar denom0 = 0.f;
- btScalar denom1 = 0.f;
- btScalar* jacB = 0;
- btScalar* jacA = 0;
- btScalar* lambdaA = 0;
- btScalar* lambdaB = 0;
- int ndofA = 0;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- lambdaA = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- {
- btScalar j = jacA[i];
- btScalar l = lambdaA[i];
- denom0 += j * l;
- }
- }
- else
- {
- if (rb0)
- {
- btVector3 iMJaA = rb0 ? rb0->getInvInertiaTensorWorld() * solverConstraint.m_relpos1CrossNormal : btVector3(0, 0, 0);
- denom0 = iMJaA.dot(solverConstraint.m_relpos1CrossNormal);
- }
- }
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- lambdaB = &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- {
- btScalar j = jacB[i];
- btScalar l = lambdaB[i];
- denom1 += j * l;
- }
- }
- else
- {
- if (rb1)
- {
- btVector3 iMJaB = rb1 ? rb1->getInvInertiaTensorWorld() * solverConstraint.m_relpos2CrossNormal : btVector3(0, 0, 0);
- denom1 = iMJaB.dot(solverConstraint.m_relpos2CrossNormal);
- }
- }
-
- btScalar d = denom0 + denom1 + infoGlobal.m_globalCfm;
- if (d > SIMD_EPSILON)
- {
- solverConstraint.m_jacDiagABInv = relaxation / (d);
- }
- else
- {
- //disable the constraint row to handle singularity/redundant constraint
- solverConstraint.m_jacDiagABInv = 0.f;
- }
- }
-
- //compute rhs and remaining solverConstraint fields
-
- btScalar restitution = 0.f;
- btScalar penetration = isFriction ? 0 : cp.getDistance();
-
- btScalar rel_vel = 0.f;
- int ndofA = 0;
- int ndofB = 0;
- {
- btVector3 vel1, vel2;
- if (multiBodyA)
- {
- ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* jacA = &m_data.m_jacobians[solverConstraint.m_jacAindex];
- for (int i = 0; i < ndofA; ++i)
- rel_vel += multiBodyA->getVelocityVector()[i] * jacA[i];
- }
- else
- {
- if (rb0)
- {
- btSolverBody* solverBodyA = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdA];
- rel_vel += solverConstraint.m_contactNormal1.dot(rb0 ? solverBodyA->m_linearVelocity + solverBodyA->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos1CrossNormal.dot(rb0 ? solverBodyA->m_angularVelocity : btVector3(0, 0, 0));
- }
- }
- if (multiBodyB)
- {
- ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* jacB = &m_data.m_jacobians[solverConstraint.m_jacBindex];
- for (int i = 0; i < ndofB; ++i)
- rel_vel += multiBodyB->getVelocityVector()[i] * jacB[i];
- }
- else
- {
- if (rb1)
- {
- btSolverBody* solverBodyB = &m_tmpSolverBodyPool[solverConstraint.m_solverBodyIdB];
- rel_vel += solverConstraint.m_contactNormal2.dot(rb1 ? solverBodyB->m_linearVelocity + solverBodyB->m_externalForceImpulse : btVector3(0, 0, 0)) + solverConstraint.m_relpos2CrossNormal.dot(rb1 ? solverBodyB->m_angularVelocity : btVector3(0, 0, 0));
- }
- }
-
- solverConstraint.m_friction = combinedTorsionalFriction;
-
- if (!isFriction)
- {
- restitution = restitutionCurve(rel_vel, cp.m_combinedRestitution, infoGlobal.m_restitutionVelocityThreshold);
- if (restitution <= btScalar(0.))
- {
- restitution = 0.f;
- }
- }
- }
-
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
-
- {
- btScalar velocityError = 0 - rel_vel; // * damping; //note for friction restitution is always set to 0 (check above) so it is acutally velocityError = -rel_vel for friction
-
- btScalar velocityImpulse = velocityError * solverConstraint.m_jacDiagABInv;
-
- solverConstraint.m_rhs = velocityImpulse;
- solverConstraint.m_rhsPenetration = 0.f;
- solverConstraint.m_lowerLimit = -solverConstraint.m_friction;
- solverConstraint.m_upperLimit = solverConstraint.m_friction;
-
- solverConstraint.m_cfm = infoGlobal.m_globalCfm * solverConstraint.m_jacDiagABInv;
- }
-}
-
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- BT_PROFILE("addMultiBodyFrictionConstraint");
- btMultiBodySolverConstraint& solverConstraint = m_multiBodyFrictionContactConstraints.expandNonInitializing();
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
-
- solverConstraint.m_frictionIndex = frictionIndex;
- bool isFriction = true;
-
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
-
- int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_multiBodyA = mbA;
- if (mbA)
- solverConstraint.m_linkA = fcA->m_link;
-
- solverConstraint.m_multiBodyB = mbB;
- if (mbB)
- solverConstraint.m_linkB = fcB->m_link;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- setupMultiBodyContactConstraint(solverConstraint, normalAxis, 0, cp, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- BT_PROFILE("addMultiBodyRollingFrictionConstraint");
-
- bool useTorsionalAndConeFriction = (infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS && ((infoGlobal.m_solverMode & SOLVER_DISABLE_IMPLICIT_CONE_FRICTION) == 0));
-
- btMultiBodySolverConstraint& solverConstraint = useTorsionalAndConeFriction ? m_multiBodyTorsionalFrictionContactConstraints.expandNonInitializing() : m_multiBodyFrictionContactConstraints.expandNonInitializing();
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
-
- solverConstraint.m_frictionIndex = frictionIndex;
- bool isFriction = true;
-
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
-
- int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_multiBodyA = mbA;
- if (mbA)
- solverConstraint.m_linkA = fcA->m_link;
-
- solverConstraint.m_multiBodyB = mbB;
- if (mbB)
- solverConstraint.m_linkB = fcB->m_link;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-
-btMultiBodySolverConstraint& btMultiBodyConstraintSolver::addMultiBodySpinningFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity, btScalar cfmSlip)
-{
- BT_PROFILE("addMultiBodyRollingFrictionConstraint");
-
- btMultiBodySolverConstraint& solverConstraint = m_multiBodySpinningFrictionContactConstraints.expandNonInitializing();
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
-
- solverConstraint.m_frictionIndex = frictionIndex;
- bool isFriction = true;
-
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
-
- int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_multiBodyA = mbA;
- if (mbA)
- solverConstraint.m_linkA = fcA->m_link;
-
- solverConstraint.m_multiBodyB = mbB;
- if (mbB)
- solverConstraint.m_linkB = fcB->m_link;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- setupMultiBodyTorsionalFrictionConstraint(solverConstraint, normalAxis, cp, combinedTorsionalFriction, infoGlobal, relaxation, isFriction, desiredVelocity, cfmSlip);
- return solverConstraint;
-}
-void btMultiBodyConstraintSolver::convertMultiBodyContact(btPersistentManifold* manifold, const btContactSolverInfo& infoGlobal)
-{
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
-
- btMultiBody* mbA = fcA ? fcA->m_multiBody : 0;
- btMultiBody* mbB = fcB ? fcB->m_multiBody : 0;
-
- btCollisionObject *colObj0 = 0, *colObj1 = 0;
-
- colObj0 = (btCollisionObject*)manifold->getBody0();
- colObj1 = (btCollisionObject*)manifold->getBody1();
-
- int solverBodyIdA = mbA ? -1 : getOrInitSolverBody(*colObj0, infoGlobal.m_timeStep);
- int solverBodyIdB = mbB ? -1 : getOrInitSolverBody(*colObj1, infoGlobal.m_timeStep);
-
- // btSolverBody* solverBodyA = mbA ? 0 : &m_tmpSolverBodyPool[solverBodyIdA];
- // btSolverBody* solverBodyB = mbB ? 0 : &m_tmpSolverBodyPool[solverBodyIdB];
-
- ///avoid collision response between two static objects
- // if (!solverBodyA || (solverBodyA->m_invMass.isZero() && (!solverBodyB || solverBodyB->m_invMass.isZero())))
- // return;
-
- //only a single rollingFriction per manifold
- int rollingFriction = 4;
-
- for (int j = 0; j < manifold->getNumContacts(); j++)
- {
- btManifoldPoint& cp = manifold->getContactPoint(j);
-
- if (cp.getDistance() <= manifold->getContactProcessingThreshold())
- {
- btScalar relaxation;
-
- int frictionIndex = m_multiBodyNormalContactConstraints.size();
-
- btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints.expandNonInitializing();
-
- // btRigidBody* rb0 = btRigidBody::upcast(colObj0);
- // btRigidBody* rb1 = btRigidBody::upcast(colObj1);
- solverConstraint.m_orgConstraint = 0;
- solverConstraint.m_orgDofIndex = -1;
- solverConstraint.m_solverBodyIdA = solverBodyIdA;
- solverConstraint.m_solverBodyIdB = solverBodyIdB;
- solverConstraint.m_multiBodyA = mbA;
- if (mbA)
- solverConstraint.m_linkA = fcA->m_link;
-
- solverConstraint.m_multiBodyB = mbB;
- if (mbB)
- solverConstraint.m_linkB = fcB->m_link;
-
- solverConstraint.m_originalContactPoint = &cp;
-
- bool isFriction = false;
- setupMultiBodyContactConstraint(solverConstraint, cp.m_normalWorldOnB, cp.m_appliedImpulse, cp, infoGlobal, relaxation, isFriction);
-
- // const btVector3& pos1 = cp.getPositionWorldOnA();
- // const btVector3& pos2 = cp.getPositionWorldOnB();
-
- /////setup the friction constraints
-#define ENABLE_FRICTION
-#ifdef ENABLE_FRICTION
- solverConstraint.m_frictionIndex = m_multiBodyFrictionContactConstraints.size();
-
- ///Bullet has several options to set the friction directions
- ///By default, each contact has only a single friction direction that is recomputed automatically every frame
- ///based on the relative linear velocity.
- ///If the relative velocity is zero, it will automatically compute a friction direction.
-
- ///You can also enable two friction directions, using the SOLVER_USE_2_FRICTION_DIRECTIONS.
- ///In that case, the second friction direction will be orthogonal to both contact normal and first friction direction.
- ///
- ///If you choose SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION, then the friction will be independent from the relative projected velocity.
- ///
- ///The user can manually override the friction directions for certain contacts using a contact callback,
- ///and set the cp.m_lateralFrictionInitialized to true
- ///In that case, you can set the target relative motion in each friction direction (cp.m_contactMotion1 and cp.m_contactMotion2)
- ///this will give a conveyor belt effect
- ///
-
- btPlaneSpace1(cp.m_normalWorldOnB, cp.m_lateralFrictionDir1, cp.m_lateralFrictionDir2);
- cp.m_lateralFrictionDir1.normalize();
- cp.m_lateralFrictionDir2.normalize();
-
- if (rollingFriction > 0)
- {
- if (cp.m_combinedSpinningFriction > 0)
- {
- addMultiBodySpinningFrictionConstraint(cp.m_normalWorldOnB, manifold, frictionIndex, cp, cp.m_combinedSpinningFriction, colObj0, colObj1, relaxation, infoGlobal);
- }
- if (cp.m_combinedRollingFriction > 0)
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
-
- addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir1, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
- addMultiBodyTorsionalFrictionConstraint(cp.m_lateralFrictionDir2, manifold, frictionIndex, cp, cp.m_combinedRollingFriction, colObj0, colObj1, relaxation, infoGlobal);
- }
- rollingFriction--;
- }
- if (!(infoGlobal.m_solverMode & SOLVER_ENABLE_FRICTION_DIRECTION_CACHING) || !(cp.m_contactPointFlags & BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED))
- { /*
- cp.m_lateralFrictionDir1 = vel - cp.m_normalWorldOnB * rel_vel;
- btScalar lat_rel_vel = cp.m_lateralFrictionDir1.length2();
- if (!(infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION) && lat_rel_vel > SIMD_EPSILON)
- {
- cp.m_lateralFrictionDir1 *= 1.f/btSqrt(lat_rel_vel);
- if((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- cp.m_lateralFrictionDir2 = cp.m_lateralFrictionDir1.cross(cp.m_normalWorldOnB);
- cp.m_lateralFrictionDir2.normalize();//??
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir2,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
- }
-
- applyAnisotropicFriction(colObj0,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1,cp.m_lateralFrictionDir1,btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1,solverBodyIdA,solverBodyIdB,frictionIndex,cp,rel_pos1,rel_pos2,colObj0,colObj1, relaxation);
-
- } else
- */
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir1, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- applyAnisotropicFriction(colObj0, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- applyAnisotropicFriction(colObj1, cp.m_lateralFrictionDir2, btCollisionObject::CF_ANISOTROPIC_FRICTION);
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal);
- }
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS) && (infoGlobal.m_solverMode & SOLVER_DISABLE_VELOCITY_DEPENDENT_FRICTION_DIRECTION))
- {
- cp.m_contactPointFlags |= BT_CONTACT_FLAG_LATERAL_FRICTION_INITIALIZED;
- }
- }
- }
- else
- {
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir1, cp.m_appliedImpulseLateral1, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion1, cp.m_frictionCFM);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- addMultiBodyFrictionConstraint(cp.m_lateralFrictionDir2, cp.m_appliedImpulseLateral2, manifold, frictionIndex, cp, colObj0, colObj1, relaxation, infoGlobal, cp.m_contactMotion2, cp.m_frictionCFM);
- solverConstraint.m_appliedImpulse = 0.f;
- solverConstraint.m_appliedPushImpulse = 0.f;
- }
-
-#endif //ENABLE_FRICTION
- }
- else
- {
- // Reset quantities related to warmstart as 0.
- cp.m_appliedImpulse = 0;
- cp.m_prevRHS = 0;
- }
- }
-}
-
-void btMultiBodyConstraintSolver::convertContacts(btPersistentManifold** manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal)
-{
- for (int i = 0; i < numManifolds; i++)
- {
- btPersistentManifold* manifold = manifoldPtr[i];
- const btMultiBodyLinkCollider* fcA = btMultiBodyLinkCollider::upcast(manifold->getBody0());
- const btMultiBodyLinkCollider* fcB = btMultiBodyLinkCollider::upcast(manifold->getBody1());
- if (!fcA && !fcB)
- {
- //the contact doesn't involve any Featherstone btMultiBody, so deal with the regular btRigidBody/btCollisionObject case
- convertContact(manifold, infoGlobal);
- }
- else
- {
- convertMultiBodyContact(manifold, infoGlobal);
- }
- }
-
- //also convert the multibody constraints, if any
-
- for (int i = 0; i < m_tmpNumMultiBodyConstraints; i++)
- {
- btMultiBodyConstraint* c = m_tmpMultiBodyConstraints[i];
- m_data.m_solverBodyPool = &m_tmpSolverBodyPool;
- m_data.m_fixedBodyId = m_fixedBodyId;
-
- c->createConstraintRows(m_multiBodyNonContactConstraints, m_data, infoGlobal);
- }
-
- // Warmstart for noncontact constraints
- if (infoGlobal.m_solverMode & SOLVER_USE_ARTICULATED_WARMSTARTING)
- {
- for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
- {
- btMultiBodySolverConstraint& solverConstraint =
- m_multiBodyNonContactConstraints[i];
- solverConstraint.m_appliedImpulse =
- solverConstraint.m_orgConstraint->getAppliedImpulse(solverConstraint.m_orgDofIndex) *
- infoGlobal.m_articulatedWarmstartingFactor;
-
- btMultiBody* multiBodyA = solverConstraint.m_multiBodyA;
- btMultiBody* multiBodyB = solverConstraint.m_multiBodyB;
- if (solverConstraint.m_appliedImpulse)
- {
- if (multiBodyA)
- {
- int ndofA = multiBodyA->getNumDofs() + 6;
- btScalar* deltaV =
- &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacAindex];
- btScalar impulse = solverConstraint.m_appliedImpulse;
- multiBodyA->applyDeltaVeeMultiDof2(deltaV, impulse);
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelAindex, ndofA);
- }
- if (multiBodyB)
- {
- int ndofB = multiBodyB->getNumDofs() + 6;
- btScalar* deltaV =
- &m_data.m_deltaVelocitiesUnitImpulse[solverConstraint.m_jacBindex];
- btScalar impulse = solverConstraint.m_appliedImpulse;
- multiBodyB->applyDeltaVeeMultiDof2(deltaV, impulse);
- applyDeltaVee(deltaV, impulse, solverConstraint.m_deltaVelBindex, ndofB);
- }
- }
- }
- }
- else
- {
- for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
- {
- btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
- solverConstraint.m_appliedImpulse = 0;
- }
- }
-}
-
-btScalar btMultiBodyConstraintSolver::solveGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
-{
- //printf("btMultiBodyConstraintSolver::solveGroup: numBodies=%d, numConstraints=%d\n", numBodies, numConstraints);
- return btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
-}
-
-#if 0
-static void applyJointFeedback(btMultiBodyJacobianData& data, const btMultiBodySolverConstraint& solverConstraint, int jacIndex, btMultiBody* mb, btScalar appliedImpulse)
-{
- if (appliedImpulse!=0 && mb->internalNeedsJointFeedback())
- {
- //todo: get rid of those temporary memory allocations for the joint feedback
- btAlignedObjectArray<btScalar> forceVector;
- int numDofsPlusBase = 6+mb->getNumDofs();
- forceVector.resize(numDofsPlusBase);
- for (int i=0;i<numDofsPlusBase;i++)
- {
- forceVector[i] = data.m_jacobians[jacIndex+i]*appliedImpulse;
- }
- btAlignedObjectArray<btScalar> output;
- output.resize(numDofsPlusBase);
- bool applyJointFeedback = true;
- mb->calcAccelerationDeltasMultiDof(&forceVector[0],&output[0],data.scratch_r,data.scratch_v,applyJointFeedback);
- }
-}
-#endif
-
-void btMultiBodyConstraintSolver::writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint& c, btScalar deltaTime)
-{
-#if 1
-
- //bod->addBaseForce(m_gravity * bod->getBaseMass());
- //bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
-
- if (c.m_orgConstraint)
- {
- c.m_orgConstraint->internalSetAppliedImpulse(c.m_orgDofIndex, c.m_appliedImpulse);
- }
-
- if (c.m_multiBodyA)
- {
- c.m_multiBodyA->setCompanionId(-1);
- btVector3 force = c.m_contactNormal1 * (c.m_appliedImpulse / deltaTime);
- btVector3 torque = c.m_relpos1CrossNormal * (c.m_appliedImpulse / deltaTime);
- if (c.m_linkA < 0)
- {
- c.m_multiBodyA->addBaseConstraintForce(force);
- c.m_multiBodyA->addBaseConstraintTorque(torque);
- }
- else
- {
- c.m_multiBodyA->addLinkConstraintForce(c.m_linkA, force);
- //b3Printf("force = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
- c.m_multiBodyA->addLinkConstraintTorque(c.m_linkA, torque);
- }
- }
-
- if (c.m_multiBodyB)
- {
- {
- c.m_multiBodyB->setCompanionId(-1);
- btVector3 force = c.m_contactNormal2 * (c.m_appliedImpulse / deltaTime);
- btVector3 torque = c.m_relpos2CrossNormal * (c.m_appliedImpulse / deltaTime);
- if (c.m_linkB < 0)
- {
- c.m_multiBodyB->addBaseConstraintForce(force);
- c.m_multiBodyB->addBaseConstraintTorque(torque);
- }
- else
- {
- {
- c.m_multiBodyB->addLinkConstraintForce(c.m_linkB, force);
- //b3Printf("t = %f,%f,%f\n",force[0],force[1],force[2]);//[0],torque[1],torque[2]);
- c.m_multiBodyB->addLinkConstraintTorque(c.m_linkB, torque);
- }
- }
- }
- }
-#endif
-
-#ifndef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
-
- if (c.m_multiBodyA)
- {
- c.m_multiBodyA->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], c.m_appliedImpulse);
- }
-
- if (c.m_multiBodyB)
- {
- c.m_multiBodyB->applyDeltaVeeMultiDof(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], c.m_appliedImpulse);
- }
-#endif
-}
-
-btScalar btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("btMultiBodyConstraintSolver::solveGroupCacheFriendlyFinish");
- int numPoolConstraints = m_multiBodyNormalContactConstraints.size();
-
- //write back the delta v to the multi bodies, either as applied impulse (direct velocity change)
- //or as applied force, so we can measure the joint reaction forces easier
- for (int i = 0; i < numPoolConstraints; i++)
- {
- btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[i];
- writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
-
- writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex], infoGlobal.m_timeStep);
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- writeBackSolverBodyToMultiBody(m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1], infoGlobal.m_timeStep);
- }
- }
-
- for (int i = 0; i < m_multiBodyNonContactConstraints.size(); i++)
- {
- btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
- writeBackSolverBodyToMultiBody(solverConstraint, infoGlobal.m_timeStep);
- }
-
-
- {
- BT_PROFILE("warm starting write back");
- for (int j = 0; j < numPoolConstraints; j++)
- {
- const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
- btManifoldPoint* pt = (btManifoldPoint*)solverConstraint.m_originalContactPoint;
- btAssert(pt);
- pt->m_appliedImpulse = solverConstraint.m_appliedImpulse;
- pt->m_prevRHS = solverConstraint.m_rhs;
- pt->m_appliedImpulseLateral1 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse;
-
- //printf("pt->m_appliedImpulseLateral1 = %f\n", pt->m_appliedImpulseLateral1);
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- pt->m_appliedImpulseLateral2 = m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex + 1].m_appliedImpulse;
- } else
- {
- pt->m_appliedImpulseLateral2 = 0;
- }
- }
- }
-
-#if 0
- //multibody joint feedback
- {
- BT_PROFILE("multi body joint feedback");
- for (int j=0;j<numPoolConstraints;j++)
- {
- const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNormalContactConstraints[j];
-
- //apply the joint feedback into all links of the btMultiBody
- //todo: double-check the signs of the applied impulse
-
- if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
- {
- applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
- }
- if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
- {
- applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
- }
-#if 0
- if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA->isMultiDof())
- {
- applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacAindex,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyA,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
-
- }
- if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB->isMultiDof())
- {
- applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex],
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_jacBindex,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_multiBodyB,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
- }
-
- if ((infoGlobal.m_solverMode & SOLVER_USE_2_FRICTION_DIRECTIONS))
- {
- if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA->isMultiDof())
- {
- applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacAindex,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyA,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
- }
-
- if (m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB && m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB->isMultiDof())
- {
- applyJointFeedback(m_data,m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1],
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_jacBindex,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_multiBodyB,
- m_multiBodyFrictionContactConstraints[solverConstraint.m_frictionIndex+1].m_appliedImpulse*btSimdScalar(-1./infoGlobal.m_timeStep));
- }
- }
-#endif
- }
-
- for (int i=0;i<m_multiBodyNonContactConstraints.size();i++)
- {
- const btMultiBodySolverConstraint& solverConstraint = m_multiBodyNonContactConstraints[i];
- if(solverConstraint.m_multiBodyA && solverConstraint.m_multiBodyA->isMultiDof())
- {
- applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacAindex,solverConstraint.m_multiBodyA, solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
- }
- if(solverConstraint.m_multiBodyB && solverConstraint.m_multiBodyB->isMultiDof())
- {
- applyJointFeedback(m_data,solverConstraint, solverConstraint.m_jacBindex,solverConstraint.m_multiBodyB,solverConstraint.m_appliedImpulse*btSimdScalar(1./infoGlobal.m_timeStep));
- }
- }
- }
-
- numPoolConstraints = m_multiBodyNonContactConstraints.size();
-
-#if 0
- //@todo: m_originalContactPoint is not initialized for btMultiBodySolverConstraint
- for (int i=0;i<numPoolConstraints;i++)
- {
- const btMultiBodySolverConstraint& c = m_multiBodyNonContactConstraints[i];
-
- btTypedConstraint* constr = (btTypedConstraint*)c.m_originalContactPoint;
- btJointFeedback* fb = constr->getJointFeedback();
- if (fb)
- {
- fb->m_appliedForceBodyA += c.m_contactNormal1*c.m_appliedImpulse*constr->getRigidBodyA().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedForceBodyB += c.m_contactNormal2*c.m_appliedImpulse*constr->getRigidBodyB().getLinearFactor()/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyA += c.m_relpos1CrossNormal* constr->getRigidBodyA().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep;
- fb->m_appliedTorqueBodyB += c.m_relpos2CrossNormal* constr->getRigidBodyB().getAngularFactor()*c.m_appliedImpulse/infoGlobal.m_timeStep; /*RGM ???? */
-
- }
-
- constr->internalSetAppliedImpulse(c.m_appliedImpulse);
- if (btFabs(c.m_appliedImpulse)>=constr->getBreakingImpulseThreshold())
- {
- constr->setEnabled(false);
- }
-
- }
-#endif
-#endif
-
- return btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyFinish(bodies, numBodies, infoGlobal);
-}
-
-void btMultiBodyConstraintSolver::solveMultiBodyGroup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
-{
- //printf("solveMultiBodyGroup: numBodies=%d, numConstraints=%d, numManifolds=%d, numMultiBodyConstraints=%d\n", numBodies, numConstraints, numManifolds, numMultiBodyConstraints);
-
- //printf("solveMultiBodyGroup start\n");
- m_tmpMultiBodyConstraints = multiBodyConstraints;
- m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
-
- btSequentialImpulseConstraintSolver::solveGroup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer, dispatcher);
-
- m_tmpMultiBodyConstraints = 0;
- m_tmpNumMultiBodyConstraints = 0;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
deleted file mode 100644
index f584360e2b..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_CONSTRAINT_SOLVER_H
-#define BT_MULTIBODY_CONSTRAINT_SOLVER_H
-
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-#include "btMultiBodySolverConstraint.h"
-
-#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
-
-class btMultiBody;
-
-#include "btMultiBodyConstraint.h"
-
-ATTRIBUTE_ALIGNED16(class)
-btMultiBodyConstraintSolver : public btSequentialImpulseConstraintSolver
-{
-protected:
- btMultiBodyConstraintArray m_multiBodyNonContactConstraints;
-
- btMultiBodyConstraintArray m_multiBodyNormalContactConstraints;
- btMultiBodyConstraintArray m_multiBodyFrictionContactConstraints;
- btMultiBodyConstraintArray m_multiBodyTorsionalFrictionContactConstraints;
- btMultiBodyConstraintArray m_multiBodySpinningFrictionContactConstraints;
-
- btMultiBodyJacobianData m_data;
-
- //temp storage for multi body constraints for a specific island/group called by 'solveGroup'
- btMultiBodyConstraint** m_tmpMultiBodyConstraints;
- int m_tmpNumMultiBodyConstraints;
-
- btScalar resolveSingleConstraintRowGeneric(const btMultiBodySolverConstraint& c);
-
- //solve 2 friction directions and clamp against the implicit friction cone
- btScalar resolveConeFrictionConstraintRows(const btMultiBodySolverConstraint& cA1, const btMultiBodySolverConstraint& cB);
-
- void convertContacts(btPersistentManifold * *manifoldPtr, int numManifolds, const btContactSolverInfo& infoGlobal);
-
- btMultiBodySolverConstraint& addMultiBodyFrictionConstraint(const btVector3& normalAxis, const btScalar& appliedImpulse, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp, btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
- btMultiBodySolverConstraint& addMultiBodyTorsionalFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
- btMultiBodySolverConstraint& addMultiBodySpinningFrictionConstraint(const btVector3& normalAxis, btPersistentManifold* manifold, int frictionIndex, btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- btCollisionObject* colObj0, btCollisionObject* colObj1, btScalar relaxation, const btContactSolverInfo& infoGlobal, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
- void setupMultiBodyJointLimitConstraint(btMultiBodySolverConstraint & constraintRow,
- btScalar * jacA, btScalar * jacB,
- btScalar penetration, btScalar combinedFrictionCoeff, btScalar combinedRestitutionCoeff,
- const btContactSolverInfo& infoGlobal);
-
- void setupMultiBodyContactConstraint(btMultiBodySolverConstraint & solverConstraint,
- const btVector3& contactNormal,
- const btScalar& appliedImpulse,
- btManifoldPoint& cp,
- const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
- //either rolling or spinning friction
- void setupMultiBodyTorsionalFrictionConstraint(btMultiBodySolverConstraint & solverConstraint,
- const btVector3& contactNormal,
- btManifoldPoint& cp,
- btScalar combinedTorsionalFriction,
- const btContactSolverInfo& infoGlobal,
- btScalar& relaxation,
- bool isFriction, btScalar desiredVelocity = 0, btScalar cfmSlip = 0);
-
- void convertMultiBodyContact(btPersistentManifold * manifold, const btContactSolverInfo& infoGlobal);
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- // virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
- virtual btScalar solveSingleIteration(int iteration, btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- void applyDeltaVee(btScalar * deltaV, btScalar impulse, int velocityIndex, int ndof);
- void writeBackSolverBodyToMultiBody(btMultiBodySolverConstraint & constraint, btScalar deltaTime);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- ///this method should not be called, it was just used during porting/integration of Featherstone btMultiBody, providing backwards compatibility but no support for btMultiBodyConstraint (only contact constraints)
- virtual btScalar solveGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
- virtual btScalar solveGroupCacheFriendlyFinish(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
-
- virtual void solveMultiBodyGroup(btCollisionObject * *bodies, int numBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
-};
-
-#endif //BT_MULTIBODY_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
deleted file mode 100644
index e7af332eb3..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp
+++ /dev/null
@@ -1,895 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btMultiBodyDynamicsWorld.h"
-#include "btMultiBodyConstraintSolver.h"
-#include "btMultiBody.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-#include "LinearMath/btQuickprof.h"
-#include "btMultiBodyConstraint.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btSerializer.h"
-
-void btMultiBodyDynamicsWorld::addMultiBody(btMultiBody* body, int group, int mask)
-{
- m_multiBodies.push_back(body);
-}
-
-void btMultiBodyDynamicsWorld::removeMultiBody(btMultiBody* body)
-{
- m_multiBodies.remove(body);
-}
-
-void btMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
- predictMultiBodyTransforms(timeStep);
-
-}
-void btMultiBodyDynamicsWorld::calculateSimulationIslands()
-{
- BT_PROFILE("calculateSimulationIslands");
-
- getSimulationIslandManager()->updateActivationState(getCollisionWorld(), getCollisionWorld()->getDispatcher());
-
- {
- //merge islands based on speculative contact manifolds too
- for (int i = 0; i < this->m_predictiveManifolds.size(); i++)
- {
- btPersistentManifold* manifold = m_predictiveManifolds[i];
-
- const btCollisionObject* colObj0 = manifold->getBody0();
- const btCollisionObject* colObj1 = manifold->getBody1();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
- }
- }
- }
-
- {
- int i;
- int numConstraints = int(m_constraints.size());
- for (i = 0; i < numConstraints; i++)
- {
- btTypedConstraint* constraint = m_constraints[i];
- if (constraint->isEnabled())
- {
- const btRigidBody* colObj0 = &constraint->getRigidBodyA();
- const btRigidBody* colObj1 = &constraint->getRigidBodyB();
-
- if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
- ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
- {
- getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(), (colObj1)->getIslandTag());
- }
- }
- }
- }
-
- //merge islands linked by Featherstone link colliders
- for (int i = 0; i < m_multiBodies.size(); i++)
- {
- btMultiBody* body = m_multiBodies[i];
- {
- btMultiBodyLinkCollider* prev = body->getBaseCollider();
-
- for (int b = 0; b < body->getNumLinks(); b++)
- {
- btMultiBodyLinkCollider* cur = body->getLink(b).m_collider;
-
- if (((cur) && (!(cur)->isStaticOrKinematicObject())) &&
- ((prev) && (!(prev)->isStaticOrKinematicObject())))
- {
- int tagPrev = prev->getIslandTag();
- int tagCur = cur->getIslandTag();
- getSimulationIslandManager()->getUnionFind().unite(tagPrev, tagCur);
- }
- if (cur && !cur->isStaticOrKinematicObject())
- prev = cur;
- }
- }
- }
-
- //merge islands linked by multibody constraints
- {
- for (int i = 0; i < this->m_multiBodyConstraints.size(); i++)
- {
- btMultiBodyConstraint* c = m_multiBodyConstraints[i];
- int tagA = c->getIslandIdA();
- int tagB = c->getIslandIdB();
- if (tagA >= 0 && tagB >= 0)
- getSimulationIslandManager()->getUnionFind().unite(tagA, tagB);
- }
- }
-
- //Store the island id in each body
- getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
-}
-
-void btMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
-{
- BT_PROFILE("btMultiBodyDynamicsWorld::updateActivationState");
-
- for (int i = 0; i < m_multiBodies.size(); i++)
- {
- btMultiBody* body = m_multiBodies[i];
- if (body)
- {
- body->checkMotionAndSleepIfRequired(timeStep);
- if (!body->isAwake())
- {
- btMultiBodyLinkCollider* col = body->getBaseCollider();
- if (col && col->getActivationState() == ACTIVE_TAG)
- {
- if (body->hasFixedBase())
- {
- col->setActivationState(FIXED_BASE_MULTI_BODY);
- } else
- {
- col->setActivationState(WANTS_DEACTIVATION);
- }
-
- col->setDeactivationTime(0.f);
- }
- for (int b = 0; b < body->getNumLinks(); b++)
- {
- btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
- if (col && col->getActivationState() == ACTIVE_TAG)
- {
- col->setActivationState(WANTS_DEACTIVATION);
- col->setDeactivationTime(0.f);
- }
- }
- }
- else
- {
- btMultiBodyLinkCollider* col = body->getBaseCollider();
- if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState(ACTIVE_TAG);
-
- for (int b = 0; b < body->getNumLinks(); b++)
- {
- btMultiBodyLinkCollider* col = body->getLink(b).m_collider;
- if (col && col->getActivationState() != DISABLE_DEACTIVATION)
- col->setActivationState(ACTIVE_TAG);
- }
- }
- }
- }
-
- btDiscreteDynamicsWorld::updateActivationState(timeStep);
-}
-
-void btMultiBodyDynamicsWorld::getAnalyticsData(btAlignedObjectArray<btSolverAnalyticsData>& islandAnalyticsData) const
-{
- islandAnalyticsData = m_solverMultiBodyIslandCallback->m_islandAnalyticsData;
-}
-
-btMultiBodyDynamicsWorld::btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
- : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
- m_multiBodyConstraintSolver(constraintSolver)
-{
- //split impulse is not yet supported for Featherstone hierarchies
- // getSolverInfo().m_splitImpulse = false;
- getSolverInfo().m_solverMode |= SOLVER_USE_2_FRICTION_DIRECTIONS;
- m_solverMultiBodyIslandCallback = new MultiBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
-}
-
-btMultiBodyDynamicsWorld::~btMultiBodyDynamicsWorld()
-{
- delete m_solverMultiBodyIslandCallback;
-}
-
-void btMultiBodyDynamicsWorld::setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
-{
- m_multiBodyConstraintSolver = solver;
- m_solverMultiBodyIslandCallback->setMultiBodyConstraintSolver(solver);
- btDiscreteDynamicsWorld::setConstraintSolver(solver);
-}
-
-void btMultiBodyDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
-{
- if (solver->getSolverType() == BT_MULTIBODY_SOLVER)
- {
- m_multiBodyConstraintSolver = (btMultiBodyConstraintSolver*)solver;
- }
- btDiscreteDynamicsWorld::setConstraintSolver(solver);
-}
-
-void btMultiBodyDynamicsWorld::forwardKinematics()
-{
- for (int b = 0; b < m_multiBodies.size(); b++)
- {
- btMultiBody* bod = m_multiBodies[b];
- bod->forwardKinematics(m_scratch_world_to_local, m_scratch_local_origin);
- }
-}
-void btMultiBodyDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
-{
- solveExternalForces(solverInfo);
- buildIslands();
- solveInternalConstraints(solverInfo);
-}
-
-void btMultiBodyDynamicsWorld::buildIslands()
-{
- m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverMultiBodyIslandCallback);
-}
-
-void btMultiBodyDynamicsWorld::solveInternalConstraints(btContactSolverInfo& solverInfo)
-{
- /// solve all the constraints for this island
- m_solverMultiBodyIslandCallback->processConstraints();
- m_constraintSolver->allSolved(solverInfo, m_debugDrawer);
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- if (bod->internalNeedsJointFeedback())
- {
- if (!bod->isUsingRK4Integration())
- {
- if (bod->internalNeedsJointFeedback())
- {
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
- }
- }
- }
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->processDeltaVeeMultiDof2();
- }
-}
-
-void btMultiBodyDynamicsWorld::solveExternalForces(btContactSolverInfo& solverInfo)
-{
- forwardKinematics();
-
- BT_PROFILE("solveConstraints");
-
- clearMultiBodyConstraintForces();
-
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
-
- m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i = 0; i < m_multiBodyConstraints.size(); i++)
- {
- m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
- }
- m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
-
- btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
-
- m_solverMultiBodyIslandCallback->setup(&solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
- m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
-
-#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- {
- BT_PROFILE("btMultiBody addForce");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- bod->addBaseForce(m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- } //if (!isSleeping)
- }
- }
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-
- {
- BT_PROFILE("btMultiBody stepVelocities");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
- bool doNotUpdatePos = false;
- bool isConstraintPass = false;
- {
- if (!bod->isUsingRK4Integration())
- {
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(solverInfo.m_timeStep,
- m_scratch_r, m_scratch_v, m_scratch_m,isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- else
- {
- //
- int numDofs = bod->getNumDofs() + 6;
- int numPosVars = bod->getNumPosVars() + 7;
- btAlignedObjectArray<btScalar> scratch_r2;
- scratch_r2.resize(2 * numPosVars + 8 * numDofs);
- //convenience
- btScalar* pMem = &scratch_r2[0];
- btScalar* scratch_q0 = pMem;
- pMem += numPosVars;
- btScalar* scratch_qx = pMem;
- pMem += numPosVars;
- btScalar* scratch_qd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qd3 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd0 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd1 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd2 = pMem;
- pMem += numDofs;
- btScalar* scratch_qdd3 = pMem;
- pMem += numDofs;
- btAssert((pMem - (2 * numPosVars + 8 * numDofs)) == &scratch_r2[0]);
-
- /////
- //copy q0 to scratch_q0 and qd0 to scratch_qd0
- scratch_q0[0] = bod->getWorldToBaseRot().x();
- scratch_q0[1] = bod->getWorldToBaseRot().y();
- scratch_q0[2] = bod->getWorldToBaseRot().z();
- scratch_q0[3] = bod->getWorldToBaseRot().w();
- scratch_q0[4] = bod->getBasePos().x();
- scratch_q0[5] = bod->getBasePos().y();
- scratch_q0[6] = bod->getBasePos().z();
- //
- for (int link = 0; link < bod->getNumLinks(); ++link)
- {
- for (int dof = 0; dof < bod->getLink(link).m_posVarCount; ++dof)
- scratch_q0[7 + bod->getLink(link).m_cfgOffset + dof] = bod->getLink(link).m_jointPos[dof];
- }
- //
- for (int dof = 0; dof < numDofs; ++dof)
- scratch_qd0[dof] = bod->getVelocityVector()[dof];
- ////
- struct
- {
- btMultiBody* bod;
- btScalar *scratch_qx, *scratch_q0;
-
- void operator()()
- {
- for (int dof = 0; dof < bod->getNumPosVars() + 7; ++dof)
- scratch_qx[dof] = scratch_q0[dof];
- }
- } pResetQx = {bod, scratch_qx, scratch_q0};
- //
- struct
- {
- void operator()(btScalar dt, const btScalar* pDer, const btScalar* pCurVal, btScalar* pVal, int size)
- {
- for (int i = 0; i < size; ++i)
- pVal[i] = pCurVal[i] + dt * pDer[i];
- }
-
- } pEulerIntegrate;
- //
- struct
- {
- void operator()(btMultiBody* pBody, const btScalar* pData)
- {
- btScalar* pVel = const_cast<btScalar*>(pBody->getVelocityVector());
-
- for (int i = 0; i < pBody->getNumDofs() + 6; ++i)
- pVel[i] = pData[i];
- }
- } pCopyToVelocityVector;
- //
- struct
- {
- void operator()(const btScalar* pSrc, btScalar* pDst, int start, int size)
- {
- for (int i = 0; i < size; ++i)
- pDst[i] = pSrc[start + i];
- }
- } pCopy;
- //
-
- btScalar h = solverInfo.m_timeStep;
-#define output &m_scratch_r[bod->getNumDofs()]
- //calc qdd0 from: q0 & qd0
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd0, 0, numDofs);
- //calc q1 = q0 + h/2 * qd0
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd0);
- //calc qd1 = qd0 + h/2 * qdd0
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd0, scratch_qd0, scratch_qd1, numDofs);
- //
- //calc qdd1 from: q1 & qd1
- pCopyToVelocityVector(bod, scratch_qd1);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd1, 0, numDofs);
- //calc q2 = q0 + h/2 * qd1
- pResetQx();
- bod->stepPositionsMultiDof(btScalar(.5) * h, scratch_qx, scratch_qd1);
- //calc qd2 = qd0 + h/2 * qdd1
- pEulerIntegrate(btScalar(.5) * h, scratch_qdd1, scratch_qd0, scratch_qd2, numDofs);
- //
- //calc qdd2 from: q2 & qd2
- pCopyToVelocityVector(bod, scratch_qd2);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd2, 0, numDofs);
- //calc q3 = q0 + h * qd2
- pResetQx();
- bod->stepPositionsMultiDof(h, scratch_qx, scratch_qd2);
- //calc qd3 = qd0 + h * qdd2
- pEulerIntegrate(h, scratch_qdd2, scratch_qd0, scratch_qd3, numDofs);
- //
- //calc qdd3 from: q3 & qd3
- pCopyToVelocityVector(bod, scratch_qd3);
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0., m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- pCopy(output, scratch_qdd3, 0, numDofs);
-
- //
- //calc q = q0 + h/6(qd0 + 2*(qd1 + qd2) + qd3)
- //calc qd = qd0 + h/6(qdd0 + 2*(qdd1 + qdd2) + qdd3)
- btAlignedObjectArray<btScalar> delta_q;
- delta_q.resize(numDofs);
- btAlignedObjectArray<btScalar> delta_qd;
- delta_qd.resize(numDofs);
- for (int i = 0; i < numDofs; ++i)
- {
- delta_q[i] = h / btScalar(6.) * (scratch_qd0[i] + 2 * scratch_qd1[i] + 2 * scratch_qd2[i] + scratch_qd3[i]);
- delta_qd[i] = h / btScalar(6.) * (scratch_qdd0[i] + 2 * scratch_qdd1[i] + 2 * scratch_qdd2[i] + scratch_qdd3[i]);
- //delta_q[i] = h*scratch_qd0[i];
- //delta_qd[i] = h*scratch_qdd0[i];
- }
- //
- pCopyToVelocityVector(bod, scratch_qd0);
- bod->applyDeltaVeeMultiDof(&delta_qd[0], 1);
- //
- if (!doNotUpdatePos)
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
-
- for (int i = 0; i < numDofs; ++i)
- pRealBuf[i] = delta_q[i];
-
- //bod->stepPositionsMultiDof(1, 0, &delta_q[0]);
- bod->setPosUpdated(true);
- }
-
- //ugly hack which resets the cached data to t0 (needed for constraint solver)
- {
- for (int link = 0; link < bod->getNumLinks(); ++link)
- bod->getLink(link).updateCacheMultiDof();
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(0, m_scratch_r, m_scratch_v, m_scratch_m,
- isConstraintPass,getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
-
-#ifndef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- bod->clearForcesAndTorques();
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- } //if (!isSleeping)
- }
- }
-}
-
-
-void btMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
-{
- btDiscreteDynamicsWorld::integrateTransforms(timeStep);
- integrateMultiBodyTransforms(timeStep);
-}
-
-void btMultiBodyDynamicsWorld::integrateMultiBodyTransforms(btScalar timeStep)
-{
- BT_PROFILE("btMultiBody stepPositions");
- //integrate and update the Featherstone hierarchies
-
- for (int b = 0; b < m_multiBodies.size(); b++)
- {
- btMultiBody* bod = m_multiBodies[b];
- bool isSleeping = false;
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- bod->addSplitV();
- int nLinks = bod->getNumLinks();
-
- ///base + num m_links
- if (!bod->isPosUpdated())
- bod->stepPositionsMultiDof(timeStep);
- else
- {
- btScalar* pRealBuf = const_cast<btScalar*>(bod->getVelocityVector());
- pRealBuf += 6 + bod->getNumDofs() + bod->getNumDofs() * bod->getNumDofs();
-
- bod->stepPositionsMultiDof(1, 0, pRealBuf);
- bod->setPosUpdated(false);
- }
-
-
- m_scratch_world_to_local.resize(nLinks + 1);
- m_scratch_local_origin.resize(nLinks + 1);
- bod->updateCollisionObjectWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
- bod->substractSplitV();
- }
- else
- {
- bod->clearVelocities();
- }
- }
-}
-
-void btMultiBodyDynamicsWorld::predictMultiBodyTransforms(btScalar timeStep)
-{
- BT_PROFILE("btMultiBody stepPositions");
- //integrate and update the Featherstone hierarchies
-
- for (int b = 0; b < m_multiBodies.size(); b++)
- {
- btMultiBody* bod = m_multiBodies[b];
- bool isSleeping = false;
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- int nLinks = bod->getNumLinks();
- bod->predictPositionsMultiDof(timeStep);
- m_scratch_world_to_local.resize(nLinks + 1);
- m_scratch_local_origin.resize(nLinks + 1);
- bod->updateCollisionObjectInterpolationWorldTransforms(m_scratch_world_to_local, m_scratch_local_origin);
- }
- else
- {
- bod->clearVelocities();
- }
- }
-}
-
-void btMultiBodyDynamicsWorld::addMultiBodyConstraint(btMultiBodyConstraint* constraint)
-{
- m_multiBodyConstraints.push_back(constraint);
-}
-
-void btMultiBodyDynamicsWorld::removeMultiBodyConstraint(btMultiBodyConstraint* constraint)
-{
- m_multiBodyConstraints.remove(constraint);
-}
-
-void btMultiBodyDynamicsWorld::debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint)
-{
- constraint->debugDraw(getDebugDrawer());
-}
-
-void btMultiBodyDynamicsWorld::debugDrawWorld()
-{
- BT_PROFILE("btMultiBodyDynamicsWorld debugDrawWorld");
-
- btDiscreteDynamicsWorld::debugDrawWorld();
-
- bool drawConstraints = false;
- if (getDebugDrawer())
- {
- int mode = getDebugDrawer()->getDebugMode();
- if (mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
- {
- drawConstraints = true;
- }
-
- if (drawConstraints)
- {
- BT_PROFILE("btMultiBody debugDrawWorld");
-
- for (int c = 0; c < m_multiBodyConstraints.size(); c++)
- {
- btMultiBodyConstraint* constraint = m_multiBodyConstraints[c];
- debugDrawMultiBodyConstraint(constraint);
- }
-
- for (int b = 0; b < m_multiBodies.size(); b++)
- {
- btMultiBody* bod = m_multiBodies[b];
- bod->forwardKinematics(m_scratch_world_to_local1, m_scratch_local_origin1);
-
- if (mode & btIDebugDraw::DBG_DrawFrames)
- {
- getDebugDrawer()->drawTransform(bod->getBaseWorldTransform(), 0.1);
- }
-
- for (int m = 0; m < bod->getNumLinks(); m++)
- {
- const btTransform& tr = bod->getLink(m).m_cachedWorldTransform;
- if (mode & btIDebugDraw::DBG_DrawFrames)
- {
- getDebugDrawer()->drawTransform(tr, 0.1);
- }
- //draw the joint axis
- if (bod->getLink(m).m_jointType == btMultibodyLink::eRevolute)
- {
- btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_topVec) * 0.1;
-
- btVector4 color(0, 0, 0, 1); //1,1,1);
- btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from, to, color);
- }
- if (bod->getLink(m).m_jointType == btMultibodyLink::eFixed)
- {
- btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
-
- btVector4 color(0, 0, 0, 1); //1,1,1);
- btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from, to, color);
- }
- if (bod->getLink(m).m_jointType == btMultibodyLink::ePrismatic)
- {
- btVector3 vec = quatRotate(tr.getRotation(), bod->getLink(m).m_axes[0].m_bottomVec) * 0.1;
-
- btVector4 color(0, 0, 0, 1); //1,1,1);
- btVector3 from = vec + tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- btVector3 to = tr.getOrigin() - quatRotate(tr.getRotation(), bod->getLink(m).m_dVector);
- getDebugDrawer()->drawLine(from, to, color);
- }
- }
- }
- }
- }
-}
-
-void btMultiBodyDynamicsWorld::applyGravity()
-{
- btDiscreteDynamicsWorld::applyGravity();
-#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- BT_PROFILE("btMultiBody addGravity");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- bod->addBaseForce(m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, m_gravity * bod->getLinkMass(j));
- }
- } //if (!isSleeping)
- }
-#endif //BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-}
-
-void btMultiBodyDynamicsWorld::clearMultiBodyConstraintForces()
-{
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->clearConstraintForces();
- }
-}
-void btMultiBodyDynamicsWorld::clearMultiBodyForces()
-{
- {
- // BT_PROFILE("clearMultiBodyForces");
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->clearForcesAndTorques();
- }
- }
- }
-}
-void btMultiBodyDynamicsWorld::clearForces()
-{
- btDiscreteDynamicsWorld::clearForces();
-
-#ifdef BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
- clearMultiBodyForces();
-#endif
-}
-
-void btMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
-{
- serializer->startSerialization();
-
- serializeDynamicsWorldInfo(serializer);
-
- serializeMultiBodies(serializer);
-
- serializeRigidBodies(serializer);
-
- serializeCollisionObjects(serializer);
-
- serializeContactManifolds(serializer);
-
- serializer->finishSerialization();
-}
-
-void btMultiBodyDynamicsWorld::serializeMultiBodies(btSerializer* serializer)
-{
- int i;
- //serialize all collision objects
- for (i = 0; i < m_multiBodies.size(); i++)
- {
- btMultiBody* mb = m_multiBodies[i];
- {
- int len = mb->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = mb->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_MULTIBODY_CODE, mb);
- }
- }
-
- //serialize all multibody links (collision objects)
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_MB_LINKCOLLIDER_CODE, colObj);
- }
- }
-}
-
-void btMultiBodyDynamicsWorld::saveKinematicState(btScalar timeStep)
-{
- btDiscreteDynamicsWorld::saveKinematicState(timeStep);
- for(int i = 0; i < m_multiBodies.size(); i++)
- {
- btMultiBody* body = m_multiBodies[i];
- if(body->isBaseKinematic())
- body->saveKinematicState(timeStep);
- }
-}
-
-//
-//void btMultiBodyDynamicsWorld::setSplitIslands(bool split)
-//{
-// m_islandManager->setSplitIslands(split);
-//}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
deleted file mode 100644
index d2d76c8b92..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_DYNAMICS_WORLD_H
-#define BT_MULTIBODY_DYNAMICS_WORLD_H
-
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
-#include "BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h"
-
-#define BT_USE_VIRTUAL_CLEARFORCES_AND_GRAVITY
-
-class btMultiBody;
-class btMultiBodyConstraint;
-class btMultiBodyConstraintSolver;
-struct MultiBodyInplaceSolverIslandCallback;
-
-///The btMultiBodyDynamicsWorld adds Featherstone multi body dynamics to Bullet
-///This implementation is still preliminary/experimental.
-class btMultiBodyDynamicsWorld : public btDiscreteDynamicsWorld
-{
-protected:
- btAlignedObjectArray<btMultiBody*> m_multiBodies;
- btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
- btAlignedObjectArray<btMultiBodyConstraint*> m_sortedMultiBodyConstraints;
- btMultiBodyConstraintSolver* m_multiBodyConstraintSolver;
- MultiBodyInplaceSolverIslandCallback* m_solverMultiBodyIslandCallback;
-
- //cached data to avoid memory allocations
- btAlignedObjectArray<btQuaternion> m_scratch_world_to_local;
- btAlignedObjectArray<btVector3> m_scratch_local_origin;
- btAlignedObjectArray<btQuaternion> m_scratch_world_to_local1;
- btAlignedObjectArray<btVector3> m_scratch_local_origin1;
- btAlignedObjectArray<btScalar> m_scratch_r;
- btAlignedObjectArray<btVector3> m_scratch_v;
- btAlignedObjectArray<btMatrix3x3> m_scratch_m;
-
- virtual void calculateSimulationIslands();
- virtual void updateActivationState(btScalar timeStep);
-
-
- virtual void serializeMultiBodies(btSerializer* serializer);
-
-public:
- btMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration);
-
- virtual ~btMultiBodyDynamicsWorld();
-
- virtual void solveConstraints(btContactSolverInfo& solverInfo);
-
- virtual void addMultiBody(btMultiBody* body, int group = btBroadphaseProxy::DefaultFilter, int mask = btBroadphaseProxy::AllFilter);
-
- virtual void removeMultiBody(btMultiBody* body);
-
- virtual int getNumMultibodies() const
- {
- return m_multiBodies.size();
- }
-
- btMultiBody* getMultiBody(int mbIndex)
- {
- return m_multiBodies[mbIndex];
- }
-
- const btMultiBody* getMultiBody(int mbIndex) const
- {
- return m_multiBodies[mbIndex];
- }
-
- virtual void addMultiBodyConstraint(btMultiBodyConstraint* constraint);
-
- virtual int getNumMultiBodyConstraints() const
- {
- return m_multiBodyConstraints.size();
- }
-
- virtual btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex)
- {
- return m_multiBodyConstraints[constraintIndex];
- }
-
- virtual const btMultiBodyConstraint* getMultiBodyConstraint(int constraintIndex) const
- {
- return m_multiBodyConstraints[constraintIndex];
- }
-
- virtual void removeMultiBodyConstraint(btMultiBodyConstraint* constraint);
-
- virtual void integrateTransforms(btScalar timeStep);
- void integrateMultiBodyTransforms(btScalar timeStep);
- void predictMultiBodyTransforms(btScalar timeStep);
-
- virtual void predictUnconstraintMotion(btScalar timeStep);
- virtual void debugDrawWorld();
-
- virtual void debugDrawMultiBodyConstraint(btMultiBodyConstraint* constraint);
-
- void forwardKinematics();
- virtual void clearForces();
- virtual void clearMultiBodyConstraintForces();
- virtual void clearMultiBodyForces();
- virtual void applyGravity();
-
- virtual void serialize(btSerializer* serializer);
- virtual void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver);
- virtual void setConstraintSolver(btConstraintSolver* solver);
- virtual void getAnalyticsData(btAlignedObjectArray<struct btSolverAnalyticsData>& m_islandAnalyticsData) const;
-
- virtual void solveExternalForces(btContactSolverInfo& solverInfo);
- virtual void solveInternalConstraints(btContactSolverInfo& solverInfo);
- void buildIslands();
-
- virtual void saveKinematicState(btScalar timeStep);
-};
-#endif //BT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
deleted file mode 100644
index df2abbe97a..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodyFixedConstraint.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
-#include "LinearMath/btIDebugDraw.h"
-
-#define BTMBFIXEDCONSTRAINT_DIM 6
-
-btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- : btMultiBodyConstraint(body, 0, link, -1, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB)
-{
- m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-btMultiBodyFixedConstraint::btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBFIXEDCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_FIXED),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB)
-{
- m_data.resize(BTMBFIXEDCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-void btMultiBodyFixedConstraint::finalizeMultiDof()
-{
- //not implemented yet
- btAssert(0);
-}
-
-btMultiBodyFixedConstraint::~btMultiBodyFixedConstraint()
-{
-}
-
-int btMultiBodyFixedConstraint::getIslandIdA() const
-{
- if (m_rigidBodyA)
- return m_rigidBodyA->getIslandTag();
-
- if (m_bodyA)
- {
- if (m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodyFixedConstraint::getIslandIdB() const
-{
- if (m_rigidBodyB)
- return m_rigidBodyB->getIslandTag();
- if (m_bodyB)
- {
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodyFixedConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
-{
- int numDim = BTMBFIXEDCONSTRAINT_DIM;
- for (int i = 0; i < numDim; i++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal1.setValue(0, 0, 0);
- constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal2.setValue(0, 0, 0);
- constraintRow.m_angularComponentA.setValue(0, 0, 0);
- constraintRow.m_angularComponentB.setValue(0, 0, 0);
-
- constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
- constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
-
- // Convert local points back to world
- btVector3 pivotAworld = m_pivotInA;
- btMatrix3x3 frameAworld = m_frameInA;
- if (m_rigidBodyA)
- {
- constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- frameAworld = frameAworld.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
- }
- else
- {
- if (m_bodyA)
- {
- pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
- }
- }
- btVector3 pivotBworld = m_pivotInB;
- btMatrix3x3 frameBworld = m_frameInB;
- if (m_rigidBodyB)
- {
- constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- frameBworld = frameBworld.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
- }
- else
- {
- if (m_bodyB)
- {
- pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- frameBworld = m_bodyB->localFrameToWorld(m_linkB, frameBworld);
- }
- }
-
- btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
- btVector3 angleDiff;
- btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
-
- btVector3 constraintNormalLin(0, 0, 0);
- btVector3 constraintNormalAng(0, 0, 0);
- btScalar posError = 0.0;
- if (i < 3)
- {
- constraintNormalLin[i] = 1;
- posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse);
- }
- else
- { //i>=3
- constraintNormalAng = frameAworld.getColumn(i % 3);
- posError = angleDiff[i % 3];
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
- }
- }
-}
-
-void btMultiBodyFixedConstraint::debugDraw(class btIDebugDraw* drawer)
-{
- btTransform tr;
- tr.setIdentity();
-
- if (m_rigidBodyA)
- {
- btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyA)
- {
- btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- tr.setOrigin(pivotAworld);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_rigidBodyB)
- {
- // that ideally should draw the same frame
- btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyB)
- {
- btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- tr.setOrigin(pivotBworld);
- drawer->drawTransform(tr, 0.1);
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
deleted file mode 100644
index adb1cb47da..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyFixedConstraint.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_FIXED_CONSTRAINT_H
-#define BT_MULTIBODY_FIXED_CONSTRAINT_H
-
-#include "btMultiBodyConstraint.h"
-
-class btMultiBodyFixedConstraint : public btMultiBodyConstraint
-{
-protected:
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
-
-public:
- btMultiBodyFixedConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
- btMultiBodyFixedConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
-
- virtual ~btMultiBodyFixedConstraint();
-
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
-
- const btVector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- virtual void setPivotInB(const btVector3& pivotInB)
- {
- m_pivotInB = pivotInB;
- }
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
-
- virtual void debugDraw(class btIDebugDraw* drawer);
-};
-
-#endif //BT_MULTIBODY_FIXED_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
deleted file mode 100644
index ee02cf9b07..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodyGearConstraint.h"
-#include "btMultiBody.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-btMultiBodyGearConstraint::btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB)
- : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, 1, false, MULTIBODY_CONSTRAINT_GEAR),
- m_gearRatio(1),
- m_gearAuxLink(-1),
- m_erp(0),
- m_relativePositionTarget(0)
-{
-}
-
-void btMultiBodyGearConstraint::finalizeMultiDof()
-{
- allocateJacobiansMultiDof();
-
- m_numDofsFinalized = m_jacSizeBoth;
-}
-
-btMultiBodyGearConstraint::~btMultiBodyGearConstraint()
-{
-}
-
-int btMultiBodyGearConstraint::getIslandIdA() const
-{
- if (m_bodyA)
- {
- if (m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodyGearConstraint::getIslandIdB() const
-{
- if (m_bodyB)
- {
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodyGearConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
-{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
- if (m_numDofsFinalized != m_jacSizeBoth)
- {
- finalizeMultiDof();
- }
-
- //don't crash
- if (m_numDofsFinalized != m_jacSizeBoth)
- return;
-
- if (m_maxAppliedImpulse == 0.f)
- return;
-
- // note: we rely on the fact that data.m_jacobians are
- // always initialized to zero by the Constraint ctor
- int linkDoF = 0;
- unsigned int offsetA = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
- unsigned int offsetB = 6 + (m_bodyB->getLink(m_linkB).m_dofOffset + linkDoF);
-
- // row 0: the lower bound
- jacobianA(0)[offsetA] = 1;
- jacobianB(0)[offsetB] = m_gearRatio;
-
- btScalar posError = 0;
- const btVector3 dummy(0, 0, 0);
-
- btScalar kp = 1;
- btScalar kd = 1;
- int numRows = getNumRows();
-
- for (int row = 0; row < numRows; row++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
-
- int dof = 0;
- btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
- btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
- btScalar auxVel = 0;
-
- if (m_gearAuxLink >= 0)
- {
- auxVel = m_bodyA->getJointVelMultiDof(m_gearAuxLink)[dof];
- }
- currentVelocity += auxVel;
- if (m_erp != 0)
- {
- btScalar currentPositionA = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
- if (m_gearAuxLink >= 0)
- {
- currentPositionA -= m_bodyA->getJointPosMultiDof(m_gearAuxLink)[dof];
- }
- btScalar currentPositionB = m_gearRatio * m_bodyA->getJointPosMultiDof(m_linkB)[dof];
- btScalar diff = currentPositionB + currentPositionA;
- btScalar desiredPositionDiff = this->m_relativePositionTarget;
- posError = -m_erp * (desiredPositionDiff - diff);
- }
-
- btScalar desiredRelativeVelocity = auxVel;
-
- fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, desiredRelativeVelocity);
-
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = row;
- {
- //expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
- switch (m_bodyA->getLink(m_linkA).m_jointType)
- {
- case btMultibodyLink::eRevolute:
- {
- constraintRow.m_contactNormal1.setZero();
- constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
-
- break;
- }
- case btMultibodyLink::ePrismatic:
- {
- btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1 = prismaticAxisInWorld;
- constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
- constraintRow.m_relpos1CrossNormal.setZero();
- constraintRow.m_relpos2CrossNormal.setZero();
- break;
- }
- default:
- {
- btAssert(0);
- }
- };
- }
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
deleted file mode 100644
index 31888fbc68..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyGearConstraint.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_GEAR_CONSTRAINT_H
-#define BT_MULTIBODY_GEAR_CONSTRAINT_H
-
-#include "btMultiBodyConstraint.h"
-
-class btMultiBodyGearConstraint : public btMultiBodyConstraint
-{
-protected:
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
- btScalar m_gearRatio;
- int m_gearAuxLink;
- btScalar m_erp;
- btScalar m_relativePositionTarget;
-
-public:
- //btMultiBodyGearConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
- btMultiBodyGearConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB);
-
- virtual ~btMultiBodyGearConstraint();
-
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
-
- const btVector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- virtual void setPivotInB(const btVector3& pivotInB)
- {
- m_pivotInB = pivotInB;
- }
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
-
- virtual void debugDraw(class btIDebugDraw* drawer)
- {
- //todo(erwincoumans)
- }
-
- virtual void setGearRatio(btScalar gearRatio)
- {
- m_gearRatio = gearRatio;
- }
- virtual void setGearAuxLink(int gearAuxLink)
- {
- m_gearAuxLink = gearAuxLink;
- }
- virtual void setRelativePositionTarget(btScalar relPosTarget)
- {
- m_relativePositionTarget = relPosTarget;
- }
- virtual void setErp(btScalar erp)
- {
- m_erp = erp;
- }
-};
-
-#endif //BT_MULTIBODY_GEAR_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
deleted file mode 100644
index 3169b86e61..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyInplaceSolverIslandCallback.h
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
-#define BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H
-
-#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
-#include "btMultiBodyConstraintSolver.h"
-
-SIMD_FORCE_INLINE int btGetConstraintIslandId2(const btTypedConstraint* lhs)
-{
- int islandId;
-
- const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
- const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
- islandId = rcolObj0.getIslandTag() >= 0 ? rcolObj0.getIslandTag() : rcolObj1.getIslandTag();
- return islandId;
-}
-class btSortConstraintOnIslandPredicate2
-{
-public:
- bool operator()(const btTypedConstraint* lhs, const btTypedConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetConstraintIslandId2(rhs);
- lIslandId0 = btGetConstraintIslandId2(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-SIMD_FORCE_INLINE int btGetMultiBodyConstraintIslandId(const btMultiBodyConstraint* lhs)
-{
- int islandId;
-
- int islandTagA = lhs->getIslandIdA();
- int islandTagB = lhs->getIslandIdB();
- islandId = islandTagA >= 0 ? islandTagA : islandTagB;
- return islandId;
-}
-
-class btSortMultiBodyConstraintOnIslandPredicate
-{
-public:
- bool operator()(const btMultiBodyConstraint* lhs, const btMultiBodyConstraint* rhs) const
- {
- int rIslandId0, lIslandId0;
- rIslandId0 = btGetMultiBodyConstraintIslandId(rhs);
- lIslandId0 = btGetMultiBodyConstraintIslandId(lhs);
- return lIslandId0 < rIslandId0;
- }
-};
-
-struct MultiBodyInplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
-{
-
- btContactSolverInfo* m_solverInfo;
- btMultiBodyConstraintSolver* m_solver;
- btMultiBodyConstraint** m_multiBodySortedConstraints;
- int m_numMultiBodyConstraints;
-
- btTypedConstraint** m_sortedConstraints;
- int m_numConstraints;
- btIDebugDraw* m_debugDrawer;
- btDispatcher* m_dispatcher;
-
- btAlignedObjectArray<btCollisionObject*> m_bodies;
- btAlignedObjectArray<btCollisionObject*> m_softBodies;
- btAlignedObjectArray<btPersistentManifold*> m_manifolds;
- btAlignedObjectArray<btTypedConstraint*> m_constraints;
- btAlignedObjectArray<btMultiBodyConstraint*> m_multiBodyConstraints;
-
- btAlignedObjectArray<btSolverAnalyticsData> m_islandAnalyticsData;
-
- MultiBodyInplaceSolverIslandCallback(btMultiBodyConstraintSolver* solver,
- btDispatcher* dispatcher)
- : m_solverInfo(NULL),
- m_solver(solver),
- m_multiBodySortedConstraints(NULL),
- m_numConstraints(0),
- m_debugDrawer(NULL),
- m_dispatcher(dispatcher)
- {
- }
-
- MultiBodyInplaceSolverIslandCallback& operator=(const MultiBodyInplaceSolverIslandCallback& other)
- {
- btAssert(0);
- (void)other;
- return *this;
- }
-
- SIMD_FORCE_INLINE virtual void setup(btContactSolverInfo* solverInfo, btTypedConstraint** sortedConstraints, int numConstraints, btMultiBodyConstraint** sortedMultiBodyConstraints, int numMultiBodyConstraints, btIDebugDraw* debugDrawer)
- {
- m_islandAnalyticsData.clear();
- btAssert(solverInfo);
- m_solverInfo = solverInfo;
-
- m_multiBodySortedConstraints = sortedMultiBodyConstraints;
- m_numMultiBodyConstraints = numMultiBodyConstraints;
- m_sortedConstraints = sortedConstraints;
- m_numConstraints = numConstraints;
-
- m_debugDrawer = debugDrawer;
- m_bodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-
- void setMultiBodyConstraintSolver(btMultiBodyConstraintSolver* solver)
- {
- m_solver = solver;
- }
-
- virtual void processIsland(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifolds, int numManifolds, int islandId)
- {
- if (islandId < 0)
- {
- ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
- m_solver->solveMultiBodyGroup(bodies, numBodies, manifolds, numManifolds, m_sortedConstraints, m_numConstraints, &m_multiBodySortedConstraints[0], m_numConstraints, *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_solverInfo->m_reportSolverAnalytics&1)
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- }
- else
- {
- //also add all non-contact constraints/joints for this island
- btTypedConstraint** startConstraint = 0;
- btMultiBodyConstraint** startMultiBodyConstraint = 0;
-
- int numCurConstraints = 0;
- int numCurMultiBodyConstraints = 0;
-
- int i;
-
- //find the first constraint for this island
-
- for (i = 0; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- startConstraint = &m_sortedConstraints[i];
- break;
- }
- }
- //count the number of constraints in this island
- for (; i < m_numConstraints; i++)
- {
- if (btGetConstraintIslandId2(m_sortedConstraints[i]) == islandId)
- {
- numCurConstraints++;
- }
- }
-
- for (i = 0; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- startMultiBodyConstraint = &m_multiBodySortedConstraints[i];
- break;
- }
- }
- //count the number of multi body constraints in this island
- for (; i < m_numMultiBodyConstraints; i++)
- {
- if (btGetMultiBodyConstraintIslandId(m_multiBodySortedConstraints[i]) == islandId)
- {
- numCurMultiBodyConstraints++;
- }
- }
-
- //if (m_solverInfo->m_minimumSolverBatchSize<=1)
- //{
- // m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,*m_solverInfo,m_debugDrawer,m_dispatcher);
- //} else
- {
- for (i = 0; i < numBodies; i++)
- {
- bool isSoftBodyType = (bodies[i]->getInternalType() & btCollisionObject::CO_SOFT_BODY);
- if (!isSoftBodyType)
- {
- m_bodies.push_back(bodies[i]);
- }
- else
- {
- m_softBodies.push_back(bodies[i]);
- }
- }
- for (i = 0; i < numManifolds; i++)
- m_manifolds.push_back(manifolds[i]);
- for (i = 0; i < numCurConstraints; i++)
- m_constraints.push_back(startConstraint[i]);
-
- for (i = 0; i < numCurMultiBodyConstraints; i++)
- m_multiBodyConstraints.push_back(startMultiBodyConstraint[i]);
-
- if ((m_multiBodyConstraints.size() + m_constraints.size() + m_manifolds.size()) > m_solverInfo->m_minimumSolverBatchSize)
- {
- processConstraints(islandId);
- }
- else
- {
- //printf("deferred\n");
- }
- }
- }
- }
-
- virtual void processConstraints(int islandId=-1)
- {
- btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
- btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
- btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
- btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
-
- //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
-
- m_solver->solveMultiBodyGroup(bodies, m_bodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics&1))
- {
- m_solver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- m_bodies.resize(0);
- m_softBodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-};
-
-
-#endif /*BT_MULTIBODY_INPLACE_SOLVER_ISLAND_CALLBACK_H */
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
deleted file mode 100644
index d943019e71..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointFeedback.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-Copyright (c) 2015 Google Inc.
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_JOINT_FEEDBACK_H
-#define BT_MULTIBODY_JOINT_FEEDBACK_H
-
-#include "LinearMath/btSpatialAlgebra.h"
-
-struct btMultiBodyJointFeedback
-{
- btSpatialForceVector m_reactionForces;
-};
-
-#endif //BT_MULTIBODY_JOINT_FEEDBACK_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
deleted file mode 100644
index 94b36ac108..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodyJointLimitConstraint.h"
-#include "btMultiBody.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-btMultiBodyJointLimitConstraint::btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper)
- //:btMultiBodyConstraint(body,0,link,-1,2,true),
- : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 2, true, MULTIBODY_CONSTRAINT_LIMIT),
- m_lowerBound(lower),
- m_upperBound(upper)
-{
-}
-
-void btMultiBodyJointLimitConstraint::finalizeMultiDof()
-{
- // the data.m_jacobians never change, so may as well
- // initialize them here
-
- allocateJacobiansMultiDof();
-
- unsigned int offset = 6 + m_bodyA->getLink(m_linkA).m_dofOffset;
-
- // row 0: the lower bound
- jacobianA(0)[offset] = 1;
- // row 1: the upper bound
- //jacobianA(1)[offset] = -1;
- jacobianB(1)[offset] = -1;
-
- m_numDofsFinalized = m_jacSizeBoth;
-}
-
-btMultiBodyJointLimitConstraint::~btMultiBodyJointLimitConstraint()
-{
-}
-
-int btMultiBodyJointLimitConstraint::getIslandIdA() const
-{
- if (m_bodyA)
- {
- if (m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodyJointLimitConstraint::getIslandIdB() const
-{
- if (m_bodyB)
- {
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodyJointLimitConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
-{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
- if (m_numDofsFinalized != m_jacSizeBoth)
- {
- finalizeMultiDof();
- }
-
- // row 0: the lower bound
- setPosition(0, m_bodyA->getJointPos(m_linkA) - m_lowerBound); //multidof: this is joint-type dependent
-
- // row 1: the upper bound
- setPosition(1, m_upperBound - m_bodyA->getJointPos(m_linkA));
-
- for (int row = 0; row < getNumRows(); row++)
- {
- btScalar penetration = getPosition(row);
-
- //todo: consider adding some safety threshold here
- if (penetration > 0)
- {
- continue;
- }
- btScalar direction = row ? -1 : 1;
-
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = row;
-
- constraintRow.m_multiBodyA = m_bodyA;
- constraintRow.m_multiBodyB = m_bodyB;
- const btScalar posError = 0; //why assume it's zero?
- const btVector3 dummy(0, 0, 0);
-
- btScalar rel_vel = fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, 0, m_maxAppliedImpulse);
-
- {
- //expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
- switch (m_bodyA->getLink(m_linkA).m_jointType)
- {
- case btMultibodyLink::eRevolute:
- {
- constraintRow.m_contactNormal1.setZero();
- constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
-
- break;
- }
- case btMultibodyLink::ePrismatic:
- {
- btVector3 prismaticAxisInWorld = direction * quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1 = prismaticAxisInWorld;
- constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
- constraintRow.m_relpos1CrossNormal.setZero();
- constraintRow.m_relpos2CrossNormal.setZero();
-
- break;
- }
- default:
- {
- btAssert(0);
- }
- };
- }
-
- {
- btScalar positionalError = 0.f;
- btScalar velocityError = -rel_vel; // * damping;
- btScalar erp = infoGlobal.m_erp2;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- erp = infoGlobal.m_erp;
- }
- if (penetration > 0)
- {
- positionalError = 0;
- velocityError = -penetration / infoGlobal.m_timeStep;
- }
- else
- {
- positionalError = -penetration * erp / infoGlobal.m_timeStep;
- }
-
- btScalar penetrationImpulse = positionalError * constraintRow.m_jacDiagABInv;
- btScalar velocityImpulse = velocityError * constraintRow.m_jacDiagABInv;
- if (!infoGlobal.m_splitImpulse || (penetration > infoGlobal.m_splitImpulsePenetrationThreshold))
- {
- //combine position and velocity into rhs
- constraintRow.m_rhs = penetrationImpulse + velocityImpulse;
- constraintRow.m_rhsPenetration = 0.f;
- }
- else
- {
- //split position and velocity into rhs and m_rhsPenetration
- constraintRow.m_rhs = velocityImpulse;
- constraintRow.m_rhsPenetration = penetrationImpulse;
- }
- }
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
deleted file mode 100644
index b810692b4c..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
-#define BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
-
-#include "btMultiBodyConstraint.h"
-struct btSolverInfo;
-
-class btMultiBodyJointLimitConstraint : public btMultiBodyConstraint
-{
-protected:
- btScalar m_lowerBound;
- btScalar m_upperBound;
-
-public:
- btMultiBodyJointLimitConstraint(btMultiBody* body, int link, btScalar lower, btScalar upper);
- virtual ~btMultiBodyJointLimitConstraint();
-
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- virtual void debugDraw(class btIDebugDraw* drawer)
- {
- //todo(erwincoumans)
- }
- btScalar getLowerBound() const
- {
- return m_lowerBound;
- }
- btScalar getUpperBound() const
- {
- return m_upperBound;
- }
- void setLowerBound(btScalar lower)
- {
- m_lowerBound = lower;
- }
- void setUpperBound(btScalar upper)
- {
- m_upperBound = upper;
- }
-};
-
-#endif //BT_MULTIBODY_JOINT_LIMIT_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
deleted file mode 100644
index fec9b03213..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodyJointMotor.h"
-#include "btMultiBody.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse)
- : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true, MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR),
- m_desiredVelocity(desiredVelocity),
- m_desiredPosition(0),
- m_kd(1.),
- m_kp(0),
- m_erp(1),
- m_rhsClamp(SIMD_INFINITY)
-{
- m_maxAppliedImpulse = maxMotorImpulse;
- // the data.m_jacobians never change, so may as well
- // initialize them here
-}
-
-void btMultiBodyJointMotor::finalizeMultiDof()
-{
- allocateJacobiansMultiDof();
- // note: we rely on the fact that data.m_jacobians are
- // always initialized to zero by the Constraint ctor
- int linkDoF = 0;
- unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
-
- // row 0: the lower bound
- // row 0: the lower bound
- jacobianA(0)[offset] = 1;
-
- m_numDofsFinalized = m_jacSizeBoth;
-}
-
-btMultiBodyJointMotor::btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse)
- //:btMultiBodyConstraint(body,0,link,-1,1,true),
- : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 1, true, MULTIBODY_CONSTRAINT_1DOF_JOINT_MOTOR),
- m_desiredVelocity(desiredVelocity),
- m_desiredPosition(0),
- m_kd(1.),
- m_kp(0),
- m_erp(1),
- m_rhsClamp(SIMD_INFINITY)
-{
- btAssert(linkDoF < body->getLink(link).m_dofCount);
-
- m_maxAppliedImpulse = maxMotorImpulse;
-}
-btMultiBodyJointMotor::~btMultiBodyJointMotor()
-{
-}
-
-int btMultiBodyJointMotor::getIslandIdA() const
-{
- if (this->m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- {
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodyJointMotor::getIslandIdB() const
-{
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- {
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodyJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
-{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
- if (m_numDofsFinalized != m_jacSizeBoth)
- {
- finalizeMultiDof();
- }
-
- //don't crash
- if (m_numDofsFinalized != m_jacSizeBoth)
- return;
-
- if (m_maxAppliedImpulse == 0.f)
- return;
-
- const btScalar posError = 0;
- const btVector3 dummy(0, 0, 0);
-
- for (int row = 0; row < getNumRows(); row++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
-
- int dof = 0;
- btScalar currentPosition = m_bodyA->getJointPosMultiDof(m_linkA)[dof];
- btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
- btScalar positionStabiliationTerm = m_erp * (m_desiredPosition - currentPosition) / infoGlobal.m_timeStep;
-
- btScalar velocityError = (m_desiredVelocity - currentVelocity);
- btScalar rhs = m_kp * positionStabiliationTerm + currentVelocity + m_kd * velocityError;
- if (rhs > m_rhsClamp)
- {
- rhs = m_rhsClamp;
- }
- if (rhs < -m_rhsClamp)
- {
- rhs = -m_rhsClamp;
- }
-
- fillMultiBodyConstraint(constraintRow, data, jacobianA(row), jacobianB(row), dummy, dummy, dummy, dummy, posError, infoGlobal, -m_maxAppliedImpulse, m_maxAppliedImpulse, false, 1, false, rhs);
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = row;
- {
- //expect either prismatic or revolute joint type for now
- btAssert((m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eRevolute) || (m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::ePrismatic));
- switch (m_bodyA->getLink(m_linkA).m_jointType)
- {
- case btMultibodyLink::eRevolute:
- {
- constraintRow.m_contactNormal1.setZero();
- constraintRow.m_contactNormal2.setZero();
- btVector3 revoluteAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_topVec);
- constraintRow.m_relpos1CrossNormal = revoluteAxisInWorld;
- constraintRow.m_relpos2CrossNormal = -revoluteAxisInWorld;
-
- break;
- }
- case btMultibodyLink::ePrismatic:
- {
- btVector3 prismaticAxisInWorld = quatRotate(m_bodyA->getLink(m_linkA).m_cachedWorldTransform.getRotation(), m_bodyA->getLink(m_linkA).m_axes[0].m_bottomVec);
- constraintRow.m_contactNormal1 = prismaticAxisInWorld;
- constraintRow.m_contactNormal2 = -prismaticAxisInWorld;
- constraintRow.m_relpos1CrossNormal.setZero();
- constraintRow.m_relpos2CrossNormal.setZero();
-
- break;
- }
- default:
- {
- btAssert(0);
- }
- };
- }
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
deleted file mode 100644
index 1aca36352e..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyJointMotor.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_JOINT_MOTOR_H
-#define BT_MULTIBODY_JOINT_MOTOR_H
-
-#include "btMultiBodyConstraint.h"
-struct btSolverInfo;
-
-class btMultiBodyJointMotor : public btMultiBodyConstraint
-{
-protected:
- btScalar m_desiredVelocity;
- btScalar m_desiredPosition;
- btScalar m_kd;
- btScalar m_kp;
- btScalar m_erp;
- btScalar m_rhsClamp; //maximum error
-
-public:
- btMultiBodyJointMotor(btMultiBody* body, int link, btScalar desiredVelocity, btScalar maxMotorImpulse);
- btMultiBodyJointMotor(btMultiBody* body, int link, int linkDoF, btScalar desiredVelocity, btScalar maxMotorImpulse);
- virtual ~btMultiBodyJointMotor();
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- virtual void setVelocityTarget(btScalar velTarget, btScalar kd = 1.f)
- {
- m_desiredVelocity = velTarget;
- m_kd = kd;
- }
-
- virtual void setPositionTarget(btScalar posTarget, btScalar kp = 1.f)
- {
- m_desiredPosition = posTarget;
- m_kp = kp;
- }
-
- virtual void setErp(btScalar erp)
- {
- m_erp = erp;
- }
- virtual btScalar getErp() const
- {
- return m_erp;
- }
- virtual void setRhsClamp(btScalar rhsClamp)
- {
- m_rhsClamp = rhsClamp;
- }
- virtual void debugDraw(class btIDebugDraw* drawer)
- {
- //todo(erwincoumans)
- }
-};
-
-#endif //BT_MULTIBODY_JOINT_MOTOR_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
deleted file mode 100644
index 5a1429340f..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLink.h
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_LINK_H
-#define BT_MULTIBODY_LINK_H
-
-#include "LinearMath/btQuaternion.h"
-#include "LinearMath/btVector3.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-enum btMultiBodyLinkFlags
-{
- BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION = 1,
- BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION = 2,
-};
-
-//both defines are now permanently enabled
-#define BT_MULTIBODYLINK_INCLUDE_PLANAR_JOINTS
-#define TEST_SPATIAL_ALGEBRA_LAYER
-
-//
-// Various spatial helper functions
-//
-
-//namespace {
-
-#include "LinearMath/btSpatialAlgebra.h"
-
-//}
-
-//
-// Link struct
-//
-
-struct btMultibodyLink
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btScalar m_mass; // mass of link
- btVector3 m_inertiaLocal; // inertia of link (local frame; diagonal)
-
- int m_parent; // index of the parent link (assumed to be < index of this link), or -1 if parent is the base link.
-
- btQuaternion m_zeroRotParentToThis; // rotates vectors in parent-frame to vectors in local-frame (when q=0). constant.
-
- btVector3 m_dVector; // vector from the inboard joint pos to this link's COM. (local frame.) constant.
- //this is set to zero for planar joint (see also m_eVector comment)
-
- // m_eVector is constant, but depends on the joint type:
- // revolute, fixed, prismatic, spherical: vector from parent's COM to the pivot point, in PARENT's frame.
- // planar: vector from COM of parent to COM of this link, WHEN Q = 0. (local frame.)
- // todo: fix the planar so it is consistent with the other joints
-
- btVector3 m_eVector;
-
- btSpatialMotionVector m_absFrameTotVelocity, m_absFrameLocVelocity;
-
- enum eFeatherstoneJointType
- {
- eRevolute = 0,
- ePrismatic = 1,
- eSpherical = 2,
- ePlanar = 3,
- eFixed = 4,
- eInvalid
- };
-
- // "axis" = spatial joint axis (Mirtich Defn 9 p104). (expressed in local frame.) constant.
- // for prismatic: m_axesTop[0] = zero;
- // m_axesBottom[0] = unit vector along the joint axis.
- // for revolute: m_axesTop[0] = unit vector along the rotation axis (u);
- // m_axesBottom[0] = u cross m_dVector (i.e. COM linear motion due to the rotation at the joint)
- //
- // for spherical: m_axesTop[0][1][2] (u1,u2,u3) form a 3x3 identity matrix (3 rotation axes)
- // m_axesBottom[0][1][2] cross u1,u2,u3 (i.e. COM linear motion due to the rotation at the joint)
- //
- // for planar: m_axesTop[0] = unit vector along the rotation axis (u); defines the plane of motion
- // m_axesTop[1][2] = zero
- // m_axesBottom[0] = zero
- // m_axesBottom[1][2] = unit vectors along the translational axes on that plane
- btSpatialMotionVector m_axes[6];
- void setAxisTop(int dof, const btVector3 &axis) { m_axes[dof].m_topVec = axis; }
- void setAxisBottom(int dof, const btVector3 &axis)
- {
- m_axes[dof].m_bottomVec = axis;
- }
- void setAxisTop(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
- {
- m_axes[dof].m_topVec.setValue(x, y, z);
- }
- void setAxisBottom(int dof, const btScalar &x, const btScalar &y, const btScalar &z)
- {
- m_axes[dof].m_bottomVec.setValue(x, y, z);
- }
- const btVector3 &getAxisTop(int dof) const { return m_axes[dof].m_topVec; }
- const btVector3 &getAxisBottom(int dof) const { return m_axes[dof].m_bottomVec; }
-
- int m_dofOffset, m_cfgOffset;
-
- btQuaternion m_cachedRotParentToThis; // rotates vectors in parent frame to vectors in local frame
- btVector3 m_cachedRVector; // vector from COM of parent to COM of this link, in local frame.
-
- // predicted verstion
- btQuaternion m_cachedRotParentToThis_interpolate; // rotates vectors in parent frame to vectors in local frame
- btVector3 m_cachedRVector_interpolate; // vector from COM of parent to COM of this link, in local frame.
-
- btVector3 m_appliedForce; // In WORLD frame
- btVector3 m_appliedTorque; // In WORLD frame
-
- btVector3 m_appliedConstraintForce; // In WORLD frame
- btVector3 m_appliedConstraintTorque; // In WORLD frame
-
- btScalar m_jointPos[7];
- btScalar m_jointPos_interpolate[7];
-
- //m_jointTorque is the joint torque applied by the user using 'addJointTorque'.
- //It gets set to zero after each internal stepSimulation call
- btScalar m_jointTorque[6];
-
- class btMultiBodyLinkCollider *m_collider;
- int m_flags;
-
- int m_dofCount, m_posVarCount; //redundant but handy
-
- eFeatherstoneJointType m_jointType;
-
- struct btMultiBodyJointFeedback *m_jointFeedback;
-
- btTransform m_cachedWorldTransform; //this cache is updated when calling btMultiBody::forwardKinematics
-
- const char *m_linkName; //m_linkName memory needs to be managed by the developer/user!
- const char *m_jointName; //m_jointName memory needs to be managed by the developer/user!
- const void *m_userPtr; //m_userPtr ptr needs to be managed by the developer/user!
-
- btScalar m_jointDamping; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual damping.
- btScalar m_jointFriction; //todo: implement this internally. It is unused for now, it is set by a URDF loader. User can apply manual friction using a velocity motor.
- btScalar m_jointLowerLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointUpperLimit; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointMaxForce; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
- btScalar m_jointMaxVelocity; //todo: implement this internally. It is unused for now, it is set by a URDF loader.
-
- // ctor: set some sensible defaults
- btMultibodyLink()
- : m_mass(1),
- m_parent(-1),
- m_zeroRotParentToThis(0, 0, 0, 1),
- m_cachedRotParentToThis(0, 0, 0, 1),
- m_cachedRotParentToThis_interpolate(0, 0, 0, 1),
- m_collider(0),
- m_flags(0),
- m_dofCount(0),
- m_posVarCount(0),
- m_jointType(btMultibodyLink::eInvalid),
- m_jointFeedback(0),
- m_linkName(0),
- m_jointName(0),
- m_userPtr(0),
- m_jointDamping(0),
- m_jointFriction(0),
- m_jointLowerLimit(0),
- m_jointUpperLimit(0),
- m_jointMaxForce(0),
- m_jointMaxVelocity(0)
- {
- m_inertiaLocal.setValue(1, 1, 1);
- setAxisTop(0, 0., 0., 0.);
- setAxisBottom(0, 1., 0., 0.);
- m_dVector.setValue(0, 0, 0);
- m_eVector.setValue(0, 0, 0);
- m_cachedRVector.setValue(0, 0, 0);
- m_cachedRVector_interpolate.setValue(0, 0, 0);
- m_appliedForce.setValue(0, 0, 0);
- m_appliedTorque.setValue(0, 0, 0);
- m_appliedConstraintForce.setValue(0, 0, 0);
- m_appliedConstraintTorque.setValue(0, 0, 0);
- //
- m_jointPos[0] = m_jointPos[1] = m_jointPos[2] = m_jointPos[4] = m_jointPos[5] = m_jointPos[6] = 0.f;
- m_jointPos[3] = 1.f; //"quat.w"
- m_jointTorque[0] = m_jointTorque[1] = m_jointTorque[2] = m_jointTorque[3] = m_jointTorque[4] = m_jointTorque[5] = 0.f;
- m_cachedWorldTransform.setIdentity();
- }
-
- // routine to update m_cachedRotParentToThis and m_cachedRVector
- void updateCacheMultiDof(btScalar *pq = 0)
- {
- btScalar *pJointPos = (pq ? pq : &m_jointPos[0]);
- btQuaternion& cachedRot = m_cachedRotParentToThis;
- btVector3& cachedVector = m_cachedRVector;
- switch (m_jointType)
- {
- case eRevolute:
- {
- cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
-
- break;
- }
- case ePrismatic:
- {
- // m_cachedRotParentToThis never changes, so no need to update
- cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
-
- break;
- }
- case eSpherical:
- {
- cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- case ePlanar:
- {
- cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- case eFixed:
- {
- cachedRot = m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- default:
- {
- //invalid type
- btAssert(0);
- }
- }
- m_cachedRotParentToThis_interpolate = m_cachedRotParentToThis;
- m_cachedRVector_interpolate = m_cachedRVector;
- }
-
- void updateInterpolationCacheMultiDof()
- {
- btScalar *pJointPos = &m_jointPos_interpolate[0];
-
- btQuaternion& cachedRot = m_cachedRotParentToThis_interpolate;
- btVector3& cachedVector = m_cachedRVector_interpolate;
- switch (m_jointType)
- {
- case eRevolute:
- {
- cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector);
-
- break;
- }
- case ePrismatic:
- {
- // m_cachedRotParentToThis never changes, so no need to update
- cachedVector = m_dVector + quatRotate(m_cachedRotParentToThis, m_eVector) + pJointPos[0] * getAxisBottom(0);
-
- break;
- }
- case eSpherical:
- {
- cachedRot = btQuaternion(pJointPos[0], pJointPos[1], pJointPos[2], -pJointPos[3]) * m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- case ePlanar:
- {
- cachedRot = btQuaternion(getAxisTop(0), -pJointPos[0]) * m_zeroRotParentToThis;
- cachedVector = quatRotate(btQuaternion(getAxisTop(0), -pJointPos[0]), pJointPos[1] * getAxisBottom(1) + pJointPos[2] * getAxisBottom(2)) + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- case eFixed:
- {
- cachedRot = m_zeroRotParentToThis;
- cachedVector = m_dVector + quatRotate(cachedRot, m_eVector);
-
- break;
- }
- default:
- {
- //invalid type
- btAssert(0);
- }
- }
- }
-
-
-
-};
-
-#endif //BT_MULTIBODY_LINK_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
deleted file mode 100644
index 3dc35a5814..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyLinkCollider.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_FEATHERSTONE_LINK_COLLIDER_H
-#define BT_FEATHERSTONE_LINK_COLLIDER_H
-
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-#include "btMultiBody.h"
-#include "LinearMath/btSerializer.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btMultiBodyLinkColliderData btMultiBodyLinkColliderDoubleData
-#define btMultiBodyLinkColliderDataName "btMultiBodyLinkColliderDoubleData"
-#else
-#define btMultiBodyLinkColliderData btMultiBodyLinkColliderFloatData
-#define btMultiBodyLinkColliderDataName "btMultiBodyLinkColliderFloatData"
-#endif
-
-class btMultiBodyLinkCollider : public btCollisionObject
-{
- //protected:
-public:
- btMultiBody* m_multiBody;
- int m_link;
-
- virtual ~btMultiBodyLinkCollider()
- {
-
- }
- btMultiBodyLinkCollider(btMultiBody* multiBody, int link)
- : m_multiBody(multiBody),
- m_link(link)
- {
- m_checkCollideWith = true;
- //we need to remove the 'CF_STATIC_OBJECT' flag, otherwise links/base doesn't merge islands
- //this means that some constraints might point to bodies that are not in the islands, causing crashes
- //if (link>=0 || (multiBody && !multiBody->hasFixedBase()))
- {
- m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
- }
- // else
- //{
- // m_collisionFlags |= (btCollisionObject::CF_STATIC_OBJECT);
- //}
-
- m_internalType = CO_FEATHERSTONE_LINK;
- }
- static btMultiBodyLinkCollider* upcast(btCollisionObject* colObj)
- {
- if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
- return (btMultiBodyLinkCollider*)colObj;
- return 0;
- }
- static const btMultiBodyLinkCollider* upcast(const btCollisionObject* colObj)
- {
- if (colObj->getInternalType() & btCollisionObject::CO_FEATHERSTONE_LINK)
- return (btMultiBodyLinkCollider*)colObj;
- return 0;
- }
-
- virtual bool checkCollideWithOverride(const btCollisionObject* co) const
- {
- const btMultiBodyLinkCollider* other = btMultiBodyLinkCollider::upcast(co);
- if (!other)
- return true;
- if (other->m_multiBody != this->m_multiBody)
- return true;
- if (!m_multiBody->hasSelfCollision())
- return false;
-
- //check if 'link' has collision disabled
- if (m_link >= 0)
- {
- const btMultibodyLink& link = m_multiBody->getLink(this->m_link);
- if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
- {
- int parent_of_this = m_link;
- while (1)
- {
- if (parent_of_this == -1)
- break;
- parent_of_this = m_multiBody->getLink(parent_of_this).m_parent;
- if (parent_of_this == other->m_link)
- {
- return false;
- }
- }
- }
- else if (link.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
- {
- if (link.m_parent == other->m_link)
- return false;
- }
- }
-
- if (other->m_link >= 0)
- {
- const btMultibodyLink& otherLink = other->m_multiBody->getLink(other->m_link);
- if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_ALL_PARENT_COLLISION)
- {
- int parent_of_other = other->m_link;
- while (1)
- {
- if (parent_of_other == -1)
- break;
- parent_of_other = m_multiBody->getLink(parent_of_other).m_parent;
- if (parent_of_other == this->m_link)
- return false;
- }
- }
- else if (otherLink.m_flags & BT_MULTIBODYLINKFLAGS_DISABLE_PARENT_COLLISION)
- {
- if (otherLink.m_parent == this->m_link)
- return false;
- }
- }
- return true;
- }
-
- bool isStaticOrKinematic() const
- {
- return isStaticOrKinematicObject();
- }
-
- bool isKinematic() const
- {
- return isKinematicObject();
- }
-
- void setDynamicType(int dynamicType)
- {
- int oldFlags = getCollisionFlags();
- oldFlags &= ~(btCollisionObject::CF_STATIC_OBJECT | btCollisionObject::CF_KINEMATIC_OBJECT);
- setCollisionFlags(oldFlags | dynamicType);
- }
-
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-};
-
-// clang-format off
-
-struct btMultiBodyLinkColliderFloatData
-{
- btCollisionObjectFloatData m_colObjData;
- btMultiBodyFloatData *m_multiBody;
- int m_link;
- char m_padding[4];
-};
-
-struct btMultiBodyLinkColliderDoubleData
-{
- btCollisionObjectDoubleData m_colObjData;
- btMultiBodyDoubleData *m_multiBody;
- int m_link;
- char m_padding[4];
-};
-
-// clang-format on
-
-SIMD_FORCE_INLINE int btMultiBodyLinkCollider::calculateSerializeBufferSize() const
-{
- return sizeof(btMultiBodyLinkColliderData);
-}
-
-SIMD_FORCE_INLINE const char* btMultiBodyLinkCollider::serialize(void* dataBuffer, class btSerializer* serializer) const
-{
- btMultiBodyLinkColliderData* dataOut = (btMultiBodyLinkColliderData*)dataBuffer;
- btCollisionObject::serialize(&dataOut->m_colObjData, serializer);
-
- dataOut->m_link = this->m_link;
- dataOut->m_multiBody = (btMultiBodyData*)serializer->getUniquePointer(m_multiBody);
-
- // Fill padding with zeros to appease msan.
- memset(dataOut->m_padding, 0, sizeof(dataOut->m_padding));
-
- return btMultiBodyLinkColliderDataName;
-}
-
-#endif //BT_FEATHERSTONE_LINK_COLLIDER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
deleted file mode 100644
index f2186a93e9..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp
+++ /dev/null
@@ -1,966 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2018 Google Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h"
-
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-#include "BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h"
-
-#define DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
-
-static bool interleaveContactAndFriction1 = false;
-
-struct btJointNode1
-{
- int jointIndex; // pointer to enclosing dxJoint object
- int otherBodyIndex; // *other* body this joint is connected to
- int nextJointNodeIndex; //-1 for null
- int constraintRowIndex;
-};
-
-// Helper function to compute a delta velocity in the constraint space.
-static btScalar computeDeltaVelocityInConstraintSpace(
- const btVector3& angularDeltaVelocity,
- const btVector3& contactNormal,
- btScalar invMass,
- const btVector3& angularJacobian,
- const btVector3& linearJacobian)
-{
- return angularDeltaVelocity.dot(angularJacobian) + contactNormal.dot(linearJacobian) * invMass;
-}
-
-// Faster version of computeDeltaVelocityInConstraintSpace that can be used when contactNormal and linearJacobian are
-// identical.
-static btScalar computeDeltaVelocityInConstraintSpace(
- const btVector3& angularDeltaVelocity,
- btScalar invMass,
- const btVector3& angularJacobian)
-{
- return angularDeltaVelocity.dot(angularJacobian) + invMass;
-}
-
-// Helper function to compute a delta velocity in the constraint space.
-static btScalar computeDeltaVelocityInConstraintSpace(const btScalar* deltaVelocity, const btScalar* jacobian, int size)
-{
- btScalar result = 0;
- for (int i = 0; i < size; ++i)
- result += deltaVelocity[i] * jacobian[i];
-
- return result;
-}
-
-static btScalar computeConstraintMatrixDiagElementMultiBody(
- const btAlignedObjectArray<btSolverBody>& solverBodyPool,
- const btMultiBodyJacobianData& data,
- const btMultiBodySolverConstraint& constraint)
-{
- btScalar ret = 0;
-
- const btMultiBody* multiBodyA = constraint.m_multiBodyA;
- const btMultiBody* multiBodyB = constraint.m_multiBodyB;
-
- if (multiBodyA)
- {
- const btScalar* jacA = &data.m_jacobians[constraint.m_jacAindex];
- const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
- const int ndofA = multiBodyA->getNumDofs() + 6;
- ret += computeDeltaVelocityInConstraintSpace(deltaA, jacA, ndofA);
- }
- else
- {
- const int solverBodyIdA = constraint.m_solverBodyIdA;
- btAssert(solverBodyIdA != -1);
- const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
- const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
- ret += computeDeltaVelocityInConstraintSpace(
- constraint.m_relpos1CrossNormal,
- invMassA,
- constraint.m_angularComponentA);
- }
-
- if (multiBodyB)
- {
- const btScalar* jacB = &data.m_jacobians[constraint.m_jacBindex];
- const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
- const int ndofB = multiBodyB->getNumDofs() + 6;
- ret += computeDeltaVelocityInConstraintSpace(deltaB, jacB, ndofB);
- }
- else
- {
- const int solverBodyIdB = constraint.m_solverBodyIdB;
- btAssert(solverBodyIdB != -1);
- const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
- const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
- ret += computeDeltaVelocityInConstraintSpace(
- constraint.m_relpos2CrossNormal,
- invMassB,
- constraint.m_angularComponentB);
- }
-
- return ret;
-}
-
-static btScalar computeConstraintMatrixOffDiagElementMultiBody(
- const btAlignedObjectArray<btSolverBody>& solverBodyPool,
- const btMultiBodyJacobianData& data,
- const btMultiBodySolverConstraint& constraint,
- const btMultiBodySolverConstraint& offDiagConstraint)
-{
- btScalar offDiagA = btScalar(0);
-
- const btMultiBody* multiBodyA = constraint.m_multiBodyA;
- const btMultiBody* multiBodyB = constraint.m_multiBodyB;
- const btMultiBody* offDiagMultiBodyA = offDiagConstraint.m_multiBodyA;
- const btMultiBody* offDiagMultiBodyB = offDiagConstraint.m_multiBodyB;
-
- // Assumed at least one system is multibody
- btAssert(multiBodyA || multiBodyB);
- btAssert(offDiagMultiBodyA || offDiagMultiBodyB);
-
- if (offDiagMultiBodyA)
- {
- const btScalar* offDiagJacA = &data.m_jacobians[offDiagConstraint.m_jacAindex];
-
- if (offDiagMultiBodyA == multiBodyA)
- {
- const int ndofA = multiBodyA->getNumDofs() + 6;
- const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
- offDiagA += computeDeltaVelocityInConstraintSpace(deltaA, offDiagJacA, ndofA);
- }
- else if (offDiagMultiBodyA == multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
- offDiagA += computeDeltaVelocityInConstraintSpace(deltaB, offDiagJacA, ndofB);
- }
- }
- else
- {
- const int solverBodyIdA = constraint.m_solverBodyIdA;
- const int solverBodyIdB = constraint.m_solverBodyIdB;
-
- const int offDiagSolverBodyIdA = offDiagConstraint.m_solverBodyIdA;
- btAssert(offDiagSolverBodyIdA != -1);
-
- if (offDiagSolverBodyIdA == solverBodyIdA)
- {
- btAssert(solverBodyIdA != -1);
- const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
- const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
- offDiagA += computeDeltaVelocityInConstraintSpace(
- offDiagConstraint.m_relpos1CrossNormal,
- offDiagConstraint.m_contactNormal1,
- invMassA, constraint.m_angularComponentA,
- constraint.m_contactNormal1);
- }
- else if (offDiagSolverBodyIdA == solverBodyIdB)
- {
- btAssert(solverBodyIdB != -1);
- const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
- const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
- offDiagA += computeDeltaVelocityInConstraintSpace(
- offDiagConstraint.m_relpos1CrossNormal,
- offDiagConstraint.m_contactNormal1,
- invMassB,
- constraint.m_angularComponentB,
- constraint.m_contactNormal2);
- }
- }
-
- if (offDiagMultiBodyB)
- {
- const btScalar* offDiagJacB = &data.m_jacobians[offDiagConstraint.m_jacBindex];
-
- if (offDiagMultiBodyB == multiBodyA)
- {
- const int ndofA = multiBodyA->getNumDofs() + 6;
- const btScalar* deltaA = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacAindex];
- offDiagA += computeDeltaVelocityInConstraintSpace(deltaA, offDiagJacB, ndofA);
- }
- else if (offDiagMultiBodyB == multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- const btScalar* deltaB = &data.m_deltaVelocitiesUnitImpulse[constraint.m_jacBindex];
- offDiagA += computeDeltaVelocityInConstraintSpace(deltaB, offDiagJacB, ndofB);
- }
- }
- else
- {
- const int solverBodyIdA = constraint.m_solverBodyIdA;
- const int solverBodyIdB = constraint.m_solverBodyIdB;
-
- const int offDiagSolverBodyIdB = offDiagConstraint.m_solverBodyIdB;
- btAssert(offDiagSolverBodyIdB != -1);
-
- if (offDiagSolverBodyIdB == solverBodyIdA)
- {
- btAssert(solverBodyIdA != -1);
- const btSolverBody* solverBodyA = &solverBodyPool[solverBodyIdA];
- const btScalar invMassA = solverBodyA->m_originalBody ? solverBodyA->m_originalBody->getInvMass() : 0.0;
- offDiagA += computeDeltaVelocityInConstraintSpace(
- offDiagConstraint.m_relpos2CrossNormal,
- offDiagConstraint.m_contactNormal2,
- invMassA, constraint.m_angularComponentA,
- constraint.m_contactNormal1);
- }
- else if (offDiagSolverBodyIdB == solverBodyIdB)
- {
- btAssert(solverBodyIdB != -1);
- const btSolverBody* solverBodyB = &solverBodyPool[solverBodyIdB];
- const btScalar invMassB = solverBodyB->m_originalBody ? solverBodyB->m_originalBody->getInvMass() : 0.0;
- offDiagA += computeDeltaVelocityInConstraintSpace(
- offDiagConstraint.m_relpos2CrossNormal,
- offDiagConstraint.m_contactNormal2,
- invMassB, constraint.m_angularComponentB,
- constraint.m_contactNormal2);
- }
- }
-
- return offDiagA;
-}
-
-void btMultiBodyMLCPConstraintSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
-{
- createMLCPFastRigidBody(infoGlobal);
- createMLCPFastMultiBody(infoGlobal);
-}
-
-void btMultiBodyMLCPConstraintSolver::createMLCPFastRigidBody(const btContactSolverInfo& infoGlobal)
-{
- int numContactRows = interleaveContactAndFriction1 ? 3 : 1;
-
- int numConstraintRows = m_allConstraintPtrArray.size();
-
- if (numConstraintRows == 0)
- return;
-
- int n = numConstraintRows;
- {
- BT_PROFILE("init b (rhs)");
- m_b.resize(numConstraintRows);
- m_bSplit.resize(numConstraintRows);
- m_b.setZero();
- m_bSplit.setZero();
- for (int i = 0; i < numConstraintRows; i++)
- {
- btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
- if (!btFuzzyZero(jacDiag))
- {
- btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
- btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
- m_b[i] = rhs / jacDiag;
- m_bSplit[i] = rhsPenetration / jacDiag;
- }
- }
- }
-
- // btScalar* w = 0;
- // int nub = 0;
-
- m_lo.resize(numConstraintRows);
- m_hi.resize(numConstraintRows);
-
- {
- BT_PROFILE("init lo/ho");
-
- for (int i = 0; i < numConstraintRows; i++)
- {
- if (0) //m_limitDependencies[i]>=0)
- {
- m_lo[i] = -BT_INFINITY;
- m_hi[i] = BT_INFINITY;
- }
- else
- {
- m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
- m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
- }
- }
- }
-
- //
- int m = m_allConstraintPtrArray.size();
-
- int numBodies = m_tmpSolverBodyPool.size();
- btAlignedObjectArray<int> bodyJointNodeArray;
- {
- BT_PROFILE("bodyJointNodeArray.resize");
- bodyJointNodeArray.resize(numBodies, -1);
- }
- btAlignedObjectArray<btJointNode1> jointNodeArray;
- {
- BT_PROFILE("jointNodeArray.reserve");
- jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
- }
-
- btMatrixXu& J3 = m_scratchJ3;
- {
- BT_PROFILE("J3.resize");
- J3.resize(2 * m, 8);
- }
- btMatrixXu& JinvM3 = m_scratchJInvM3;
- {
- BT_PROFILE("JinvM3.resize/setZero");
-
- JinvM3.resize(2 * m, 8);
- JinvM3.setZero();
- J3.setZero();
- }
- int cur = 0;
- int rowOffset = 0;
- btAlignedObjectArray<int>& ofs = m_scratchOfs;
- {
- BT_PROFILE("ofs resize");
- ofs.resize(0);
- ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
- }
- {
- BT_PROFILE("Compute J and JinvM");
- int c = 0;
-
- int numRows = 0;
-
- for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
- {
- ofs[c] = rowOffset;
- int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
- if (orgBodyA)
- {
- {
- int slotA = -1;
- //find free jointNode slot for sbA
- slotA = jointNodeArray.size();
- jointNodeArray.expand(); //NonInitializing();
- int prevSlot = bodyJointNodeArray[sbA];
- bodyJointNodeArray[sbA] = slotA;
- jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
- jointNodeArray[slotA].jointIndex = c;
- jointNodeArray[slotA].constraintRowIndex = i;
- jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
- }
- for (int row = 0; row < numRows; row++, cur++)
- {
- btVector3 normalInvMass = m_allConstraintPtrArray[i + row]->m_contactNormal1 * orgBodyA->getInvMass();
- btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
-
- for (int r = 0; r < 3; r++)
- {
- J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal1[r]);
- J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal[r]);
- JinvM3.setElem(cur, r, normalInvMass[r]);
- JinvM3.setElem(cur, r + 4, relPosCrossNormalInvInertia[r]);
- }
- J3.setElem(cur, 3, 0);
- JinvM3.setElem(cur, 3, 0);
- J3.setElem(cur, 7, 0);
- JinvM3.setElem(cur, 7, 0);
- }
- }
- else
- {
- cur += numRows;
- }
- if (orgBodyB)
- {
- {
- int slotB = -1;
- //find free jointNode slot for sbA
- slotB = jointNodeArray.size();
- jointNodeArray.expand(); //NonInitializing();
- int prevSlot = bodyJointNodeArray[sbB];
- bodyJointNodeArray[sbB] = slotB;
- jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
- jointNodeArray[slotB].jointIndex = c;
- jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1;
- jointNodeArray[slotB].constraintRowIndex = i;
- }
-
- for (int row = 0; row < numRows; row++, cur++)
- {
- btVector3 normalInvMassB = m_allConstraintPtrArray[i + row]->m_contactNormal2 * orgBodyB->getInvMass();
- btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
-
- for (int r = 0; r < 3; r++)
- {
- J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal2[r]);
- J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal[r]);
- JinvM3.setElem(cur, r, normalInvMassB[r]);
- JinvM3.setElem(cur, r + 4, relPosInvInertiaB[r]);
- }
- J3.setElem(cur, 3, 0);
- JinvM3.setElem(cur, 3, 0);
- J3.setElem(cur, 7, 0);
- JinvM3.setElem(cur, 7, 0);
- }
- }
- else
- {
- cur += numRows;
- }
- rowOffset += numRows;
- }
- }
-
- //compute JinvM = J*invM.
- const btScalar* JinvM = JinvM3.getBufferPointer();
-
- const btScalar* Jptr = J3.getBufferPointer();
- {
- BT_PROFILE("m_A.resize");
- m_A.resize(n, n);
- }
-
- {
- BT_PROFILE("m_A.setZero");
- m_A.setZero();
- }
- int c = 0;
- {
- int numRows = 0;
- BT_PROFILE("Compute A");
- for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
- {
- int row__ = ofs[c];
- int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
-
- const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
-
- {
- int startJointNodeA = bodyJointNodeArray[sbA];
- while (startJointNodeA >= 0)
- {
- int j0 = jointNodeArray[startJointNodeA].jointIndex;
- int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
- if (j0 < c)
- {
- int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8 * numRowsOther : 0;
- //printf("%d joint i %d and j0: %d: ",count++,i,j0);
- m_A.multiplyAdd2_p8r(JinvMrow,
- Jptr + 2 * 8 * (size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__, ofs[j0]);
- }
- startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
- }
- }
-
- {
- int startJointNodeB = bodyJointNodeArray[sbB];
- while (startJointNodeB >= 0)
- {
- int j1 = jointNodeArray[startJointNodeB].jointIndex;
- int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
-
- if (j1 < c)
- {
- int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8 * numRowsOther : 0;
- m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)numRows,
- Jptr + 2 * 8 * (size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__, ofs[j1]);
- }
- startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
- }
- }
- }
-
- {
- BT_PROFILE("compute diagonal");
- // compute diagonal blocks of m_A
-
- int row__ = 0;
- int numJointRows = m_allConstraintPtrArray.size();
-
- int jj = 0;
- for (; row__ < numJointRows;)
- {
- //int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
-
- const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
- const btScalar* Jrow = Jptr + 2 * 8 * (size_t)row__;
- m_A.multiply2_p8r(JinvMrow, Jrow, infom, infom, row__, row__);
- if (orgBodyB)
- {
- m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)infom, Jrow + 8 * (size_t)infom, infom, infom, row__, row__);
- }
- row__ += infom;
- jj++;
- }
- }
- }
-
- if (1)
- {
- // add cfm to the diagonal of m_A
- for (int i = 0; i < m_A.rows(); ++i)
- {
- m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
- }
- }
-
- ///fill the upper triangle of the matrix, to make it symmetric
- {
- BT_PROFILE("fill the upper triangle ");
- m_A.copyLowerToUpperTriangle();
- }
-
- {
- BT_PROFILE("resize/init x");
- m_x.resize(numConstraintRows);
- m_xSplit.resize(numConstraintRows);
-
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
- {
- const btSolverConstraint& c = *m_allConstraintPtrArray[i];
- m_x[i] = c.m_appliedImpulse;
- m_xSplit[i] = c.m_appliedPushImpulse;
- }
- }
- else
- {
- m_x.setZero();
- m_xSplit.setZero();
- }
- }
-}
-
-void btMultiBodyMLCPConstraintSolver::createMLCPFastMultiBody(const btContactSolverInfo& infoGlobal)
-{
- const int multiBodyNumConstraints = m_multiBodyAllConstraintPtrArray.size();
-
- if (multiBodyNumConstraints == 0)
- return;
-
- // 1. Compute b
- {
- BT_PROFILE("init b (rhs)");
-
- m_multiBodyB.resize(multiBodyNumConstraints);
- m_multiBodyB.setZero();
-
- for (int i = 0; i < multiBodyNumConstraints; ++i)
- {
- const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
- const btScalar jacDiag = constraint.m_jacDiagABInv;
-
- if (!btFuzzyZero(jacDiag))
- {
- // Note that rhsPenetration is currently always zero because the split impulse hasn't been implemented for multibody yet.
- const btScalar rhs = constraint.m_rhs;
- m_multiBodyB[i] = rhs / jacDiag;
- }
- }
- }
-
- // 2. Compute lo and hi
- {
- BT_PROFILE("init lo/ho");
-
- m_multiBodyLo.resize(multiBodyNumConstraints);
- m_multiBodyHi.resize(multiBodyNumConstraints);
-
- for (int i = 0; i < multiBodyNumConstraints; ++i)
- {
- const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
- m_multiBodyLo[i] = constraint.m_lowerLimit;
- m_multiBodyHi[i] = constraint.m_upperLimit;
- }
- }
-
- // 3. Construct A matrix by using the impulse testing
- {
- BT_PROFILE("Compute A");
-
- {
- BT_PROFILE("m_A.resize");
- m_multiBodyA.resize(multiBodyNumConstraints, multiBodyNumConstraints);
- }
-
- for (int i = 0; i < multiBodyNumConstraints; ++i)
- {
- // Compute the diagonal of A, which is A(i, i)
- const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
- const btScalar diagA = computeConstraintMatrixDiagElementMultiBody(m_tmpSolverBodyPool, m_data, constraint);
- m_multiBodyA.setElem(i, i, diagA);
-
- // Computes the off-diagonals of A:
- // a. The rest of i-th row of A, from A(i, i+1) to A(i, n)
- // b. The rest of i-th column of A, from A(i+1, i) to A(n, i)
- for (int j = i + 1; j < multiBodyNumConstraints; ++j)
- {
- const btMultiBodySolverConstraint& offDiagConstraint = *m_multiBodyAllConstraintPtrArray[j];
- const btScalar offDiagA = computeConstraintMatrixOffDiagElementMultiBody(m_tmpSolverBodyPool, m_data, constraint, offDiagConstraint);
-
- // Set the off-diagonal values of A. Note that A is symmetric.
- m_multiBodyA.setElem(i, j, offDiagA);
- m_multiBodyA.setElem(j, i, offDiagA);
- }
- }
- }
-
- // Add CFM to the diagonal of m_A
- for (int i = 0; i < m_multiBodyA.rows(); ++i)
- {
- m_multiBodyA.setElem(i, i, m_multiBodyA(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
- }
-
- // 4. Initialize x
- {
- BT_PROFILE("resize/init x");
-
- m_multiBodyX.resize(multiBodyNumConstraints);
-
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- for (int i = 0; i < multiBodyNumConstraints; ++i)
- {
- const btMultiBodySolverConstraint& constraint = *m_multiBodyAllConstraintPtrArray[i];
- m_multiBodyX[i] = constraint.m_appliedImpulse;
- }
- }
- else
- {
- m_multiBodyX.setZero();
- }
- }
-}
-
-bool btMultiBodyMLCPConstraintSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
-{
- bool result = true;
-
- if (m_A.rows() != 0)
- {
- // If using split impulse, we solve 2 separate (M)LCPs
- if (infoGlobal.m_splitImpulse)
- {
- const btMatrixXu Acopy = m_A;
- const btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
- // TODO(JS): Do we really need these copies when solveMLCP takes them as const?
-
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
- if (result)
- result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo, m_hi, limitDependenciesCopy, infoGlobal.m_numIterations);
- }
- else
- {
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
- }
- }
-
- if (!result)
- return false;
-
- if (m_multiBodyA.rows() != 0)
- {
- result = m_solver->solveMLCP(m_multiBodyA, m_multiBodyB, m_multiBodyX, m_multiBodyLo, m_multiBodyHi, m_multiBodyLimitDependencies, infoGlobal.m_numIterations);
- }
-
- return result;
-}
-
-btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlySetup(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer)
-{
- // 1. Setup for rigid-bodies
- btMultiBodyConstraintSolver::solveGroupCacheFriendlySetup(
- bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- // 2. Setup for multi-bodies
- // a. Collect all different kinds of constraint as pointers into one array, m_allConstraintPtrArray
- // b. Set the index array for frictional contact constraints, m_limitDependencies
- {
- BT_PROFILE("gather constraint data");
-
- int dindex = 0;
-
- const int numRigidBodyConstraints = m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size();
- const int numMultiBodyConstraints = m_multiBodyNonContactConstraints.size() + m_multiBodyNormalContactConstraints.size() + m_multiBodyFrictionContactConstraints.size();
-
- m_allConstraintPtrArray.resize(0);
- m_multiBodyAllConstraintPtrArray.resize(0);
-
- // i. Setup for rigid bodies
-
- m_limitDependencies.resize(numRigidBodyConstraints);
-
- for (int i = 0; i < m_tmpSolverNonContactConstraintPool.size(); ++i)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- }
-
- int firstContactConstraintOffset = dindex;
-
- // The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
- if (interleaveContactAndFriction1)
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
- {
- const int numFrictionPerContact = m_tmpSolverContactConstraintPool.size() == m_tmpSolverContactFrictionConstraintPool.size() ? 1 : 2;
-
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact]);
- int findex = (m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact].m_frictionIndex * (1 + numFrictionPerContact));
- m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
- if (numFrictionPerContact == 2)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact + 1]);
- m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
- }
- }
- }
- else
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- }
- for (int i = 0; i < m_tmpSolverContactFrictionConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
- m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex + firstContactConstraintOffset;
- }
- }
-
- if (!m_allConstraintPtrArray.size())
- {
- m_A.resize(0, 0);
- m_b.resize(0);
- m_x.resize(0);
- m_lo.resize(0);
- m_hi.resize(0);
- }
-
- // ii. Setup for multibodies
-
- dindex = 0;
-
- m_multiBodyLimitDependencies.resize(numMultiBodyConstraints);
-
- for (int i = 0; i < m_multiBodyNonContactConstraints.size(); ++i)
- {
- m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNonContactConstraints[i]);
- m_multiBodyLimitDependencies[dindex++] = -1;
- }
-
- firstContactConstraintOffset = dindex;
-
- // The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
- if (interleaveContactAndFriction1)
- {
- for (int i = 0; i < m_multiBodyNormalContactConstraints.size(); ++i)
- {
- const int numtiBodyNumFrictionPerContact = m_multiBodyNormalContactConstraints.size() == m_multiBodyFrictionContactConstraints.size() ? 1 : 2;
-
- m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNormalContactConstraints[i]);
- m_multiBodyLimitDependencies[dindex++] = -1;
-
- btMultiBodySolverConstraint& frictionContactConstraint1 = m_multiBodyFrictionContactConstraints[i * numtiBodyNumFrictionPerContact];
- m_multiBodyAllConstraintPtrArray.push_back(&frictionContactConstraint1);
-
- const int findex = (frictionContactConstraint1.m_frictionIndex * (1 + numtiBodyNumFrictionPerContact)) + firstContactConstraintOffset;
-
- m_multiBodyLimitDependencies[dindex++] = findex;
-
- if (numtiBodyNumFrictionPerContact == 2)
- {
- btMultiBodySolverConstraint& frictionContactConstraint2 = m_multiBodyFrictionContactConstraints[i * numtiBodyNumFrictionPerContact + 1];
- m_multiBodyAllConstraintPtrArray.push_back(&frictionContactConstraint2);
-
- m_multiBodyLimitDependencies[dindex++] = findex;
- }
- }
- }
- else
- {
- for (int i = 0; i < m_multiBodyNormalContactConstraints.size(); ++i)
- {
- m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyNormalContactConstraints[i]);
- m_multiBodyLimitDependencies[dindex++] = -1;
- }
- for (int i = 0; i < m_multiBodyFrictionContactConstraints.size(); ++i)
- {
- m_multiBodyAllConstraintPtrArray.push_back(&m_multiBodyFrictionContactConstraints[i]);
- m_multiBodyLimitDependencies[dindex++] = m_multiBodyFrictionContactConstraints[i].m_frictionIndex + firstContactConstraintOffset;
- }
- }
-
- if (!m_multiBodyAllConstraintPtrArray.size())
- {
- m_multiBodyA.resize(0, 0);
- m_multiBodyB.resize(0);
- m_multiBodyX.resize(0);
- m_multiBodyLo.resize(0);
- m_multiBodyHi.resize(0);
- }
- }
-
- // Construct MLCP terms
- {
- BT_PROFILE("createMLCPFast");
- createMLCPFast(infoGlobal);
- }
-
- return btScalar(0);
-}
-
-btScalar btMultiBodyMLCPConstraintSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- bool result = true;
- {
- BT_PROFILE("solveMLCP");
- result = solveMLCP(infoGlobal);
- }
-
- // Fallback to btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations if the solution isn't valid.
- if (!result)
- {
- m_fallback++;
- return btMultiBodyConstraintSolver::solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- }
-
- {
- BT_PROFILE("process MLCP results");
-
- for (int i = 0; i < m_allConstraintPtrArray.size(); ++i)
- {
- const btSolverConstraint& c = *m_allConstraintPtrArray[i];
-
- const btScalar deltaImpulse = m_x[i] - c.m_appliedImpulse;
- c.m_appliedImpulse = m_x[i];
-
- int sbA = c.m_solverBodyIdA;
- int sbB = c.m_solverBodyIdB;
-
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
-
- solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
-
- if (infoGlobal.m_splitImpulse)
- {
- const btScalar deltaPushImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
- solverBodyA.internalApplyPushImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaPushImpulse);
- solverBodyB.internalApplyPushImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaPushImpulse);
- c.m_appliedPushImpulse = m_xSplit[i];
- }
- }
-
- for (int i = 0; i < m_multiBodyAllConstraintPtrArray.size(); ++i)
- {
- btMultiBodySolverConstraint& c = *m_multiBodyAllConstraintPtrArray[i];
-
- const btScalar deltaImpulse = m_multiBodyX[i] - c.m_appliedImpulse;
- c.m_appliedImpulse = m_multiBodyX[i];
-
- btMultiBody* multiBodyA = c.m_multiBodyA;
- if (multiBodyA)
- {
- const int ndofA = multiBodyA->getNumDofs() + 6;
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse, c.m_deltaVelAindex, ndofA);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- multiBodyA->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacAindex], deltaImpulse);
-#endif // DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else
- {
- const int sbA = c.m_solverBodyIdA;
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
- solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- }
-
- btMultiBody* multiBodyB = c.m_multiBodyB;
- if (multiBodyB)
- {
- const int ndofB = multiBodyB->getNumDofs() + 6;
- applyDeltaVee(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse, c.m_deltaVelBindex, ndofB);
-#ifdef DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- //note: update of the actual velocities (below) in the multibody does not have to happen now since m_deltaVelocities can be applied after all iterations
- //it would make the multibody solver more like the regular one with m_deltaVelocities being equivalent to btSolverBody::m_deltaLinearVelocity/m_deltaAngularVelocity
- multiBodyB->applyDeltaVeeMultiDof2(&m_data.m_deltaVelocitiesUnitImpulse[c.m_jacBindex], deltaImpulse);
-#endif // DIRECTLY_UPDATE_VELOCITY_DURING_SOLVER_ITERATIONS
- }
- else
- {
- const int sbB = c.m_solverBodyIdB;
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
- solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- }
- }
- }
-
- return btScalar(0);
-}
-
-btMultiBodyMLCPConstraintSolver::btMultiBodyMLCPConstraintSolver(btMLCPSolverInterface* solver)
- : m_solver(solver), m_fallback(0)
-{
- // Do nothing
-}
-
-btMultiBodyMLCPConstraintSolver::~btMultiBodyMLCPConstraintSolver()
-{
- // Do nothing
-}
-
-void btMultiBodyMLCPConstraintSolver::setMLCPSolver(btMLCPSolverInterface* solver)
-{
- m_solver = solver;
-}
-
-int btMultiBodyMLCPConstraintSolver::getNumFallbacks() const
-{
- return m_fallback;
-}
-
-void btMultiBodyMLCPConstraintSolver::setNumFallbacks(int num)
-{
- m_fallback = num;
-}
-
-btConstraintSolverType btMultiBodyMLCPConstraintSolver::getSolverType() const
-{
- return BT_MLCP_SOLVER;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
deleted file mode 100644
index 77fdb86bb9..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2018 Google Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
-#define BT_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
-
-#include "LinearMath/btMatrixX.h"
-#include "LinearMath/btThreads.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
-
-class btMLCPSolverInterface;
-class btMultiBody;
-
-class btMultiBodyMLCPConstraintSolver : public btMultiBodyConstraintSolver
-{
-protected:
- /// \name MLCP Formulation for Rigid Bodies
- /// \{
-
- /// A matrix in the MLCP formulation
- btMatrixXu m_A;
-
- /// b vector in the MLCP formulation.
- btVectorXu m_b;
-
- /// Constraint impulse, which is an output of MLCP solving.
- btVectorXu m_x;
-
- /// Lower bound of constraint impulse, \c m_x.
- btVectorXu m_lo;
-
- /// Upper bound of constraint impulse, \c m_x.
- btVectorXu m_hi;
-
- /// \}
-
- /// \name Cache Variables for Split Impulse for Rigid Bodies
- /// When using 'split impulse' we solve two separate (M)LCPs
- /// \{
-
- /// Split impulse Cache vector corresponding to \c m_b.
- btVectorXu m_bSplit;
-
- /// Split impulse cache vector corresponding to \c m_x.
- btVectorXu m_xSplit;
-
- /// \}
-
- /// \name MLCP Formulation for Multibodies
- /// \{
-
- /// A matrix in the MLCP formulation
- btMatrixXu m_multiBodyA;
-
- /// b vector in the MLCP formulation.
- btVectorXu m_multiBodyB;
-
- /// Constraint impulse, which is an output of MLCP solving.
- btVectorXu m_multiBodyX;
-
- /// Lower bound of constraint impulse, \c m_x.
- btVectorXu m_multiBodyLo;
-
- /// Upper bound of constraint impulse, \c m_x.
- btVectorXu m_multiBodyHi;
-
- /// \}
-
- /// Indices of normal contact constraint associated with frictional contact constraint for rigid bodies.
- ///
- /// This is used by the MLCP solver to update the upper bounds of frictional contact impulse given intermediate
- /// normal contact impulse. For example, i-th element represents the index of a normal constraint that is
- /// accosiated with i-th frictional contact constraint if i-th constraint is a frictional contact constraint.
- /// Otherwise, -1.
- btAlignedObjectArray<int> m_limitDependencies;
-
- /// Indices of normal contact constraint associated with frictional contact constraint for multibodies.
- ///
- /// This is used by the MLCP solver to update the upper bounds of frictional contact impulse given intermediate
- /// normal contact impulse. For example, i-th element represents the index of a normal constraint that is
- /// accosiated with i-th frictional contact constraint if i-th constraint is a frictional contact constraint.
- /// Otherwise, -1.
- btAlignedObjectArray<int> m_multiBodyLimitDependencies;
-
- /// Array of all the rigid body constraints
- btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
-
- /// Array of all the multibody constraints
- btAlignedObjectArray<btMultiBodySolverConstraint*> m_multiBodyAllConstraintPtrArray;
-
- /// MLCP solver
- btMLCPSolverInterface* m_solver;
-
- /// Count of fallbacks of using btSequentialImpulseConstraintSolver, which happens when the MLCP solver fails.
- int m_fallback;
-
- /// \name MLCP Scratch Variables
- /// The following scratch variables are not stateful -- contents are cleared prior to each use.
- /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
- /// that multiple instances of the solver can be run in parallel.
- ///
- /// \{
-
- /// Cache variable for constraint Jacobian matrix.
- btMatrixXu m_scratchJ3;
-
- /// Cache variable for constraint Jacobian times inverse mass matrix.
- btMatrixXu m_scratchJInvM3;
-
- /// Cache variable for offsets.
- btAlignedObjectArray<int> m_scratchOfs;
-
- /// \}
-
- /// Constructs MLCP terms, which are \c m_A, \c m_b, \c m_lo, and \c m_hi.
- virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
-
- /// Constructs MLCP terms for constraints of two rigid bodies
- void createMLCPFastRigidBody(const btContactSolverInfo& infoGlobal);
-
- /// Constructs MLCP terms for constraints of two multi-bodies or one rigid body and one multibody
- void createMLCPFastMultiBody(const btContactSolverInfo& infoGlobal);
-
- /// Solves MLCP and returns the success
- virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
-
- // Documentation inherited
- btScalar solveGroupCacheFriendlySetup(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer) BT_OVERRIDE;
-
- // Documentation inherited
- btScalar solveGroupCacheFriendlyIterations(
- btCollisionObject** bodies,
- int numBodies,
- btPersistentManifold** manifoldPtr,
- int numManifolds,
- btTypedConstraint** constraints,
- int numConstraints,
- const btContactSolverInfo& infoGlobal,
- btIDebugDraw* debugDrawer) ;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR()
-
- /// Constructor
- ///
- /// \param[in] solver MLCP solver. Assumed it's not null.
- /// \param[in] maxLCPSize Maximum size of LCP to solve using MLCP solver. If the MLCP size exceeds this number, sequaltial impulse method will be used.
- explicit btMultiBodyMLCPConstraintSolver(btMLCPSolverInterface* solver);
-
- /// Destructor
- virtual ~btMultiBodyMLCPConstraintSolver();
-
- /// Sets MLCP solver. Assumed it's not null.
- void setMLCPSolver(btMLCPSolverInterface* solver);
-
- /// Returns the number of fallbacks of using btSequentialImpulseConstraintSolver, which happens when the MLCP
- /// solver fails.
- int getNumFallbacks() const;
-
- /// Sets the number of fallbacks. This function may be used to reset the number to zero.
- void setNumFallbacks(int num);
-
- /// Returns the constraint solver type.
- virtual btConstraintSolverType getSolverType() const;
-};
-
-#endif // BT_MULTIBODY_MLCP_CONSTRAINT_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
deleted file mode 100644
index f51e69deb1..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodyPoint2Point.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "LinearMath/btIDebugDraw.h"
-
-#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
-#define BTMBP2PCONSTRAINT_DIM 3
-#else
-#define BTMBP2PCONSTRAINT_DIM 6
-#endif
-
-btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB)
- : btMultiBodyConstraint(body, 0, link, -1, BTMBP2PCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_POINT_TO_POINT),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB)
-{
- m_data.resize(BTMBP2PCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-btMultiBodyPoint2Point::btMultiBodyPoint2Point(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB)
- : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBP2PCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_POINT_TO_POINT),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB)
-{
- m_data.resize(BTMBP2PCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-void btMultiBodyPoint2Point::finalizeMultiDof()
-{
- //not implemented yet
- btAssert(0);
-}
-
-btMultiBodyPoint2Point::~btMultiBodyPoint2Point()
-{
-}
-
-int btMultiBodyPoint2Point::getIslandIdA() const
-{
- if (m_rigidBodyA)
- return m_rigidBodyA->getIslandTag();
-
- if (m_bodyA)
- {
- if (m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodyPoint2Point::getIslandIdB() const
-{
- if (m_rigidBodyB)
- return m_rigidBodyB->getIslandTag();
- if (m_bodyB)
- {
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodyPoint2Point::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
-{
- // int i=1;
- int numDim = BTMBP2PCONSTRAINT_DIM;
- for (int i = 0; i < numDim; i++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- //memset(&constraintRow,0xffffffff,sizeof(btMultiBodySolverConstraint));
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal1.setValue(0, 0, 0);
- constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal2.setValue(0, 0, 0);
- constraintRow.m_angularComponentA.setValue(0, 0, 0);
- constraintRow.m_angularComponentB.setValue(0, 0, 0);
-
- constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
- constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
-
- btVector3 contactNormalOnB(0, 0, 0);
-#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
- contactNormalOnB[i] = -1;
-#else
- contactNormalOnB[i % 3] = -1;
-#endif
-
- // Convert local points back to world
- btVector3 pivotAworld = m_pivotInA;
- if (m_rigidBodyA)
- {
- constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- }
- else
- {
- if (m_bodyA)
- pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- }
- btVector3 pivotBworld = m_pivotInB;
- if (m_rigidBodyB)
- {
- constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- }
- else
- {
- if (m_bodyB)
- pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- }
-
- btScalar posError = i < 3 ? (pivotAworld - pivotBworld).dot(contactNormalOnB) : 0;
-
-#ifndef BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
-
- fillMultiBodyConstraint(constraintRow, data, 0, 0, btVector3(0, 0, 0),
- contactNormalOnB, pivotAworld, pivotBworld, //sucks but let it be this way "for the time being"
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse);
- //@todo: support the case of btMultiBody versus btRigidBody,
- //see btPoint2PointConstraint::getInfo2NonVirtual
-#else
- const btVector3 dummy(0, 0, 0);
-
- btAssert(m_bodyA->isMultiDof());
-
- btScalar* jac1 = jacobianA(i);
- const btVector3& normalAng = i >= 3 ? contactNormalOnB : dummy;
- const btVector3& normalLin = i < 3 ? contactNormalOnB : dummy;
-
- m_bodyA->filConstraintJacobianMultiDof(m_linkA, pivotAworld, normalAng, normalLin, jac1, data.scratch_r, data.scratch_v, data.scratch_m);
-
- fillMultiBodyConstraint(constraintRow, data, jac1, 0,
- dummy, dummy, dummy, //sucks but let it be this way "for the time being"
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse);
-#endif
- }
-}
-
-void btMultiBodyPoint2Point::debugDraw(class btIDebugDraw* drawer)
-{
- btTransform tr;
- tr.setIdentity();
-
- if (m_rigidBodyA)
- {
- btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyA)
- {
- btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- tr.setOrigin(pivotAworld);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_rigidBodyB)
- {
- // that ideally should draw the same frame
- btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyB)
- {
- btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- tr.setOrigin(pivotBworld);
- drawer->drawTransform(tr, 0.1);
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
deleted file mode 100644
index ef03a557ec..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodyPoint2Point.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_POINT2POINT_H
-#define BT_MULTIBODY_POINT2POINT_H
-
-#include "btMultiBodyConstraint.h"
-
-//#define BTMBP2PCONSTRAINT_BLOCK_ANGULAR_MOTION_TEST
-
-ATTRIBUTE_ALIGNED16(class)
-btMultiBodyPoint2Point : public btMultiBodyConstraint
-{
-protected:
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultiBodyPoint2Point(btMultiBody * body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB);
- btMultiBodyPoint2Point(btMultiBody * bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB);
-
- virtual ~btMultiBodyPoint2Point();
-
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray & constraintRows,
- btMultiBodyJacobianData & data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- virtual void setPivotInB(const btVector3& pivotInB)
- {
- m_pivotInB = pivotInB;
- }
-
- virtual void debugDraw(class btIDebugDraw * drawer);
-};
-
-#endif //BT_MULTIBODY_POINT2POINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
deleted file mode 100644
index 48ec1d5af2..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodySliderConstraint.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
-#include "LinearMath/btIDebugDraw.h"
-
-#define BTMBSLIDERCONSTRAINT_DIM 5
-#define EPSILON 0.000001
-
-btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
- : btMultiBodyConstraint(body, 0, link, -1, BTMBSLIDERCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_SLIDER),
- m_rigidBodyA(0),
- m_rigidBodyB(bodyB),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_jointAxis(jointAxis)
-{
- m_data.resize(BTMBSLIDERCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-btMultiBodySliderConstraint::btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis)
- : btMultiBodyConstraint(bodyA, bodyB, linkA, linkB, BTMBSLIDERCONSTRAINT_DIM, false, MULTIBODY_CONSTRAINT_SLIDER),
- m_rigidBodyA(0),
- m_rigidBodyB(0),
- m_pivotInA(pivotInA),
- m_pivotInB(pivotInB),
- m_frameInA(frameInA),
- m_frameInB(frameInB),
- m_jointAxis(jointAxis)
-{
- m_data.resize(BTMBSLIDERCONSTRAINT_DIM); //at least store the applied impulses
-}
-
-void btMultiBodySliderConstraint::finalizeMultiDof()
-{
- //not implemented yet
- btAssert(0);
-}
-
-btMultiBodySliderConstraint::~btMultiBodySliderConstraint()
-{
-}
-
-int btMultiBodySliderConstraint::getIslandIdA() const
-{
- if (m_rigidBodyA)
- return m_rigidBodyA->getIslandTag();
-
- if (m_bodyA)
- {
- if (m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodySliderConstraint::getIslandIdB() const
-{
- if (m_rigidBodyB)
- return m_rigidBodyB->getIslandTag();
- if (m_bodyB)
- {
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-void btMultiBodySliderConstraint::createConstraintRows(btMultiBodyConstraintArray& constraintRows, btMultiBodyJacobianData& data, const btContactSolverInfo& infoGlobal)
-{
- // Convert local points back to world
- btVector3 pivotAworld = m_pivotInA;
- btMatrix3x3 frameAworld = m_frameInA;
- btVector3 jointAxis = m_jointAxis;
- if (m_rigidBodyA)
- {
- pivotAworld = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- frameAworld = m_frameInA.transpose() * btMatrix3x3(m_rigidBodyA->getOrientation());
- jointAxis = quatRotate(m_rigidBodyA->getOrientation(), m_jointAxis);
- }
- else if (m_bodyA)
- {
- pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- frameAworld = m_bodyA->localFrameToWorld(m_linkA, m_frameInA);
- jointAxis = m_bodyA->localDirToWorld(m_linkA, m_jointAxis);
- }
- btVector3 pivotBworld = m_pivotInB;
- btMatrix3x3 frameBworld = m_frameInB;
- if (m_rigidBodyB)
- {
- pivotBworld = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- frameBworld = m_frameInB.transpose() * btMatrix3x3(m_rigidBodyB->getOrientation());
- }
- else if (m_bodyB)
- {
- pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- frameBworld = m_bodyB->localFrameToWorld(m_linkB, m_frameInB);
- }
-
- btVector3 constraintAxis[2];
- for (int i = 0; i < 3; ++i)
- {
- constraintAxis[0] = frameAworld.getColumn(i).cross(jointAxis);
- if (constraintAxis[0].safeNorm() > EPSILON)
- {
- constraintAxis[0] = constraintAxis[0].normalized();
- constraintAxis[1] = jointAxis.cross(constraintAxis[0]);
- constraintAxis[1] = constraintAxis[1].normalized();
- break;
- }
- }
-
- btMatrix3x3 relRot = frameAworld.inverse() * frameBworld;
- btVector3 angleDiff;
- btGeneric6DofSpring2Constraint::matrixToEulerXYZ(relRot, angleDiff);
-
- int numDim = BTMBSLIDERCONSTRAINT_DIM;
- for (int i = 0; i < numDim; i++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = i;
- constraintRow.m_relpos1CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal1.setValue(0, 0, 0);
- constraintRow.m_relpos2CrossNormal.setValue(0, 0, 0);
- constraintRow.m_contactNormal2.setValue(0, 0, 0);
- constraintRow.m_angularComponentA.setValue(0, 0, 0);
- constraintRow.m_angularComponentB.setValue(0, 0, 0);
-
- constraintRow.m_solverBodyIdA = data.m_fixedBodyId;
- constraintRow.m_solverBodyIdB = data.m_fixedBodyId;
-
- if (m_rigidBodyA)
- {
- constraintRow.m_solverBodyIdA = m_rigidBodyA->getCompanionId();
- }
- if (m_rigidBodyB)
- {
- constraintRow.m_solverBodyIdB = m_rigidBodyB->getCompanionId();
- }
-
- btVector3 constraintNormalLin(0, 0, 0);
- btVector3 constraintNormalAng(0, 0, 0);
- btScalar posError = 0.0;
- if (i < 2)
- {
- constraintNormalLin = constraintAxis[i];
- posError = (pivotAworld - pivotBworld).dot(constraintNormalLin);
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse);
- }
- else
- { //i>=2
- constraintNormalAng = frameAworld.getColumn(i % 3);
- posError = angleDiff[i % 3];
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- constraintNormalLin, pivotAworld, pivotBworld,
- posError,
- infoGlobal,
- -m_maxAppliedImpulse, m_maxAppliedImpulse, true);
- }
- }
-}
-
-void btMultiBodySliderConstraint::debugDraw(class btIDebugDraw* drawer)
-{
- btTransform tr;
- tr.setIdentity();
-
- if (m_rigidBodyA)
- {
- btVector3 pivot = m_rigidBodyA->getCenterOfMassTransform() * m_pivotInA;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyA)
- {
- btVector3 pivotAworld = m_bodyA->localPosToWorld(m_linkA, m_pivotInA);
- tr.setOrigin(pivotAworld);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_rigidBodyB)
- {
- // that ideally should draw the same frame
- btVector3 pivot = m_rigidBodyB->getCenterOfMassTransform() * m_pivotInB;
- tr.setOrigin(pivot);
- drawer->drawTransform(tr, 0.1);
- }
- if (m_bodyB)
- {
- btVector3 pivotBworld = m_bodyB->localPosToWorld(m_linkB, m_pivotInB);
- tr.setOrigin(pivotBworld);
- drawer->drawTransform(tr, 0.1);
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
deleted file mode 100644
index b192b6f8f3..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySliderConstraint.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_SLIDER_CONSTRAINT_H
-#define BT_MULTIBODY_SLIDER_CONSTRAINT_H
-
-#include "btMultiBodyConstraint.h"
-
-class btMultiBodySliderConstraint : public btMultiBodyConstraint
-{
-protected:
- btRigidBody* m_rigidBodyA;
- btRigidBody* m_rigidBodyB;
- btVector3 m_pivotInA;
- btVector3 m_pivotInB;
- btMatrix3x3 m_frameInA;
- btMatrix3x3 m_frameInB;
- btVector3 m_jointAxis;
-
-public:
- btMultiBodySliderConstraint(btMultiBody* body, int link, btRigidBody* bodyB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
- btMultiBodySliderConstraint(btMultiBody* bodyA, int linkA, btMultiBody* bodyB, int linkB, const btVector3& pivotInA, const btVector3& pivotInB, const btMatrix3x3& frameInA, const btMatrix3x3& frameInB, const btVector3& jointAxis);
-
- virtual ~btMultiBodySliderConstraint();
-
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- const btVector3& getPivotInA() const
- {
- return m_pivotInA;
- }
-
- void setPivotInA(const btVector3& pivotInA)
- {
- m_pivotInA = pivotInA;
- }
-
- const btVector3& getPivotInB() const
- {
- return m_pivotInB;
- }
-
- virtual void setPivotInB(const btVector3& pivotInB)
- {
- m_pivotInB = pivotInB;
- }
-
- const btMatrix3x3& getFrameInA() const
- {
- return m_frameInA;
- }
-
- void setFrameInA(const btMatrix3x3& frameInA)
- {
- m_frameInA = frameInA;
- }
-
- const btMatrix3x3& getFrameInB() const
- {
- return m_frameInB;
- }
-
- virtual void setFrameInB(const btMatrix3x3& frameInB)
- {
- m_frameInB = frameInB;
- }
-
- const btVector3& getJointAxis() const
- {
- return m_jointAxis;
- }
-
- void setJointAxis(const btVector3& jointAxis)
- {
- m_jointAxis = jointAxis;
- }
-
- virtual void debugDraw(class btIDebugDraw* drawer);
-};
-
-#endif //BT_MULTIBODY_SLIDER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
deleted file mode 100644
index deed3e2a12..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySolverConstraint.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MULTIBODY_SOLVER_CONSTRAINT_H
-#define BT_MULTIBODY_SOLVER_CONSTRAINT_H
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-class btMultiBody;
-class btMultiBodyConstraint;
-#include "BulletDynamics/ConstraintSolver/btSolverBody.h"
-#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
-
-///1D constraint along a normal axis between bodyA and bodyB. It can be combined to solve contact and friction constraints.
-ATTRIBUTE_ALIGNED16(struct)
-btMultiBodySolverConstraint
-{
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btMultiBodySolverConstraint() : m_solverBodyIdA(-1), m_multiBodyA(0), m_linkA(-1), m_solverBodyIdB(-1), m_multiBodyB(0), m_linkB(-1), m_orgConstraint(0), m_orgDofIndex(-1)
- {
- }
-
- int m_deltaVelAindex; //more generic version of m_relpos1CrossNormal/m_contactNormal1
- int m_jacAindex;
- int m_deltaVelBindex;
- int m_jacBindex;
-
- btVector3 m_relpos1CrossNormal;
- btVector3 m_contactNormal1;
- btVector3 m_relpos2CrossNormal;
- btVector3 m_contactNormal2; //usually m_contactNormal2 == -m_contactNormal1, but not always
-
- btVector3 m_angularComponentA;
- btVector3 m_angularComponentB;
-
- mutable btSimdScalar m_appliedPushImpulse;
- mutable btSimdScalar m_appliedImpulse;
-
- btScalar m_friction;
- btScalar m_jacDiagABInv;
- btScalar m_rhs;
- btScalar m_cfm;
-
- btScalar m_lowerLimit;
- btScalar m_upperLimit;
- btScalar m_rhsPenetration;
- union {
- void* m_originalContactPoint;
- btScalar m_unusedPadding4;
- };
-
- int m_overrideNumSolverIterations;
- int m_frictionIndex;
-
- int m_solverBodyIdA;
- btMultiBody* m_multiBodyA;
- int m_linkA;
-
- int m_solverBodyIdB;
- btMultiBody* m_multiBodyB;
- int m_linkB;
-
- //for writing back applied impulses
- btMultiBodyConstraint* m_orgConstraint;
- int m_orgDofIndex;
-
- enum btSolverConstraintType
- {
- BT_SOLVER_CONTACT_1D = 0,
- BT_SOLVER_FRICTION_1D
- };
-};
-
-typedef btAlignedObjectArray<btMultiBodySolverConstraint> btMultiBodyConstraintArray;
-
-#endif //BT_MULTIBODY_SOLVER_CONSTRAINT_H
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp
deleted file mode 100644
index 00a7ef3579..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2018 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#include "btMultiBodySphericalJointMotor.h"
-#include "btMultiBody.h"
-#include "btMultiBodyLinkCollider.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "LinearMath/btTransformUtil.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.h"
-
-btMultiBodySphericalJointMotor::btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse)
- : btMultiBodyConstraint(body, body, link, body->getLink(link).m_parent, 3, true, MULTIBODY_CONSTRAINT_SPHERICAL_MOTOR),
- m_desiredVelocity(0, 0, 0),
- m_desiredPosition(0,0,0,1),
- m_use_multi_dof_params(false),
- m_kd(1., 1., 1.),
- m_kp(0.2, 0.2, 0.2),
- m_erp(1),
- m_rhsClamp(SIMD_INFINITY),
- m_maxAppliedImpulseMultiDof(maxMotorImpulse, maxMotorImpulse, maxMotorImpulse),
- m_damping(1.0, 1.0, 1.0)
-{
-
- m_maxAppliedImpulse = maxMotorImpulse;
-}
-
-
-void btMultiBodySphericalJointMotor::finalizeMultiDof()
-{
- allocateJacobiansMultiDof();
- // note: we rely on the fact that data.m_jacobians are
- // always initialized to zero by the Constraint ctor
- int linkDoF = 0;
- unsigned int offset = 6 + (m_bodyA->getLink(m_linkA).m_dofOffset + linkDoF);
-
- // row 0: the lower bound
- // row 0: the lower bound
- jacobianA(0)[offset] = 1;
-
- m_numDofsFinalized = m_jacSizeBoth;
-}
-
-
-btMultiBodySphericalJointMotor::~btMultiBodySphericalJointMotor()
-{
-}
-
-int btMultiBodySphericalJointMotor::getIslandIdA() const
-{
- if (this->m_linkA < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyA->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyA->getLink(m_linkA).m_collider)
- {
- return m_bodyA->getLink(m_linkA).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-int btMultiBodySphericalJointMotor::getIslandIdB() const
-{
- if (m_linkB < 0)
- {
- btMultiBodyLinkCollider* col = m_bodyB->getBaseCollider();
- if (col)
- return col->getIslandTag();
- }
- else
- {
- if (m_bodyB->getLink(m_linkB).m_collider)
- {
- return m_bodyB->getLink(m_linkB).m_collider->getIslandTag();
- }
- }
- return -1;
-}
-
-void btMultiBodySphericalJointMotor::createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal)
-{
- // only positions need to be updated -- data.m_jacobians and force
- // directions were set in the ctor and never change.
-
- if (m_numDofsFinalized != m_jacSizeBoth)
- {
- finalizeMultiDof();
- }
-
- //don't crash
- if (m_numDofsFinalized != m_jacSizeBoth)
- return;
-
-
- if (m_maxAppliedImpulse == 0.f)
- return;
-
- const btScalar posError = 0;
- const btVector3 dummy(0, 0, 0);
-
-
- btVector3 axis[3] = { btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(0, 0, 1) };
-
- btQuaternion desiredQuat = m_desiredPosition;
- btQuaternion currentQuat(m_bodyA->getJointPosMultiDof(m_linkA)[0],
- m_bodyA->getJointPosMultiDof(m_linkA)[1],
- m_bodyA->getJointPosMultiDof(m_linkA)[2],
- m_bodyA->getJointPosMultiDof(m_linkA)[3]);
-
-btQuaternion relRot = currentQuat.inverse() * desiredQuat;
- btVector3 angleDiff;
- btGeneric6DofSpring2Constraint::matrixToEulerXYZ(btMatrix3x3(relRot), angleDiff);
-
-
-
- for (int row = 0; row < getNumRows(); row++)
- {
- btMultiBodySolverConstraint& constraintRow = constraintRows.expandNonInitializing();
-
- int dof = row;
-
- btScalar currentVelocity = m_bodyA->getJointVelMultiDof(m_linkA)[dof];
- btScalar desiredVelocity = this->m_desiredVelocity[row];
-
- double kd = m_use_multi_dof_params ? m_kd[row % 3] : m_kd[0];
- btScalar velocityError = (desiredVelocity - currentVelocity) * kd;
-
- btMatrix3x3 frameAworld;
- frameAworld.setIdentity();
- frameAworld = m_bodyA->localFrameToWorld(m_linkA, frameAworld);
- btScalar posError = 0;
- {
- btAssert(m_bodyA->getLink(m_linkA).m_jointType == btMultibodyLink::eSpherical);
- switch (m_bodyA->getLink(m_linkA).m_jointType)
- {
- case btMultibodyLink::eSpherical:
- {
- btVector3 constraintNormalAng = frameAworld.getColumn(row % 3);
- double kp = m_use_multi_dof_params ? m_kp[row % 3] : m_kp[0];
- posError = kp*angleDiff[row % 3];
- double max_applied_impulse = m_use_multi_dof_params ? m_maxAppliedImpulseMultiDof[row % 3] : m_maxAppliedImpulse;
- fillMultiBodyConstraint(constraintRow, data, 0, 0, constraintNormalAng,
- btVector3(0,0,0), dummy, dummy,
- posError,
- infoGlobal,
- -max_applied_impulse, max_applied_impulse, true,
- 1.0, false, 0, 0,
- m_damping[row % 3]);
- constraintRow.m_orgConstraint = this;
- constraintRow.m_orgDofIndex = row;
- break;
- }
- default:
- {
- btAssert(0);
- }
- };
- }
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h b/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h
deleted file mode 100644
index bdeccc2e24..0000000000
--- a/thirdparty/bullet/BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2018 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///This file was written by Erwin Coumans
-
-#ifndef BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
-#define BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
-
-#include "btMultiBodyConstraint.h"
-struct btSolverInfo;
-
-class btMultiBodySphericalJointMotor : public btMultiBodyConstraint
-{
-protected:
- btVector3 m_desiredVelocity;
- btQuaternion m_desiredPosition;
- bool m_use_multi_dof_params;
- btVector3 m_kd;
- btVector3 m_kp;
- btScalar m_erp;
- btScalar m_rhsClamp; //maximum error
- btVector3 m_maxAppliedImpulseMultiDof;
- btVector3 m_damping;
-
-public:
- btMultiBodySphericalJointMotor(btMultiBody* body, int link, btScalar maxMotorImpulse);
-
- virtual ~btMultiBodySphericalJointMotor();
- virtual void finalizeMultiDof();
-
- virtual int getIslandIdA() const;
- virtual int getIslandIdB() const;
-
- virtual void createConstraintRows(btMultiBodyConstraintArray& constraintRows,
- btMultiBodyJacobianData& data,
- const btContactSolverInfo& infoGlobal);
-
- virtual void setVelocityTarget(const btVector3& velTarget, btScalar kd = 1.0)
- {
- m_desiredVelocity = velTarget;
- m_kd = btVector3(kd, kd, kd);
- m_use_multi_dof_params = false;
- }
-
- virtual void setVelocityTargetMultiDof(const btVector3& velTarget, const btVector3& kd = btVector3(1.0, 1.0, 1.0))
- {
- m_desiredVelocity = velTarget;
- m_kd = kd;
- m_use_multi_dof_params = true;
- }
-
- virtual void setPositionTarget(const btQuaternion& posTarget, btScalar kp =1.f)
- {
- m_desiredPosition = posTarget;
- m_kp = btVector3(kp, kp, kp);
- m_use_multi_dof_params = false;
- }
-
- virtual void setPositionTargetMultiDof(const btQuaternion& posTarget, const btVector3& kp = btVector3(1.f, 1.f, 1.f))
- {
- m_desiredPosition = posTarget;
- m_kp = kp;
- m_use_multi_dof_params = true;
- }
-
- virtual void setErp(btScalar erp)
- {
- m_erp = erp;
- }
- virtual btScalar getErp() const
- {
- return m_erp;
- }
- virtual void setRhsClamp(btScalar rhsClamp)
- {
- m_rhsClamp = rhsClamp;
- }
-
- btScalar getMaxAppliedImpulseMultiDof(int i) const
- {
- return m_maxAppliedImpulseMultiDof[i];
- }
-
- void setMaxAppliedImpulseMultiDof(const btVector3& maxImp)
- {
- m_maxAppliedImpulseMultiDof = maxImp;
- m_use_multi_dof_params = true;
- }
-
- btScalar getDamping(int i) const
- {
- return m_damping[i];
- }
-
- void setDamping(const btVector3& damping)
- {
- m_damping = damping;
- }
-
- virtual void debugDraw(class btIDebugDraw* drawer)
- {
- //todo(erwincoumans)
- }
-};
-
-#endif //BT_MULTIBODY_SPHERICAL_JOINT_MOTOR_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
deleted file mode 100644
index 98ecdc0794..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.cpp
+++ /dev/null
@@ -1,2158 +0,0 @@
-/*************************************************************************
-* *
-* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
-* All rights reserved. Email: russ@q12.org Web: www.q12.org *
-* *
-* This library is free software; you can redistribute it and/or *
-* modify it under the terms of EITHER: *
-* (1) The GNU Lesser General Public License as published by the Free *
-* Software Foundation; either version 2.1 of the License, or (at *
-* your option) any later version. The text of the GNU Lesser *
-* General Public License is included with this library in the *
-* file LICENSE.TXT. *
-* (2) The BSD-style license that is included with this library in *
-* the file LICENSE-BSD.TXT. *
-* *
-* This library is distributed in the hope that it will be useful, *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of *
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
-* LICENSE.TXT and LICENSE-BSD.TXT for more details. *
-* *
-*************************************************************************/
-
-/*
-
-
-THE ALGORITHM
--------------
-
-solve A*x = b+w, with x and w subject to certain LCP conditions.
-each x(i),w(i) must lie on one of the three line segments in the following
-diagram. each line segment corresponds to one index set :
-
- w(i)
- /|\ | :
- | | :
- | |i in N :
- w>0 | |state[i]=0 :
- | | :
- | | : i in C
- w=0 + +-----------------------+
- | : |
- | : |
- w<0 | : |i in N
- | : |state[i]=1
- | : |
- | : |
- +-------|-----------|-----------|----------> x(i)
- lo 0 hi
-
-the Dantzig algorithm proceeds as follows:
- for i=1:n
- * if (x(i),w(i)) is not on the line, push x(i) and w(i) positive or
- negative towards the line. as this is done, the other (x(j),w(j))
- for j<i are constrained to be on the line. if any (x,w) reaches the
- end of a line segment then it is switched between index sets.
- * i is added to the appropriate index set depending on what line segment
- it hits.
-
-we restrict lo(i) <= 0 and hi(i) >= 0. this makes the algorithm a bit
-simpler, because the starting point for x(i),w(i) is always on the dotted
-line x=0 and x will only ever increase in one direction, so it can only hit
-two out of the three line segments.
-
-
-NOTES
------
-
-this is an implementation of "lcp_dantzig2_ldlt.m" and "lcp_dantzig_lohi.m".
-the implementation is split into an LCP problem object (btLCP) and an LCP
-driver function. most optimization occurs in the btLCP object.
-
-a naive implementation of the algorithm requires either a lot of data motion
-or a lot of permutation-array lookup, because we are constantly re-ordering
-rows and columns. to avoid this and make a more optimized algorithm, a
-non-trivial data structure is used to represent the matrix A (this is
-implemented in the fast version of the btLCP object).
-
-during execution of this algorithm, some indexes in A are clamped (set C),
-some are non-clamped (set N), and some are "don't care" (where x=0).
-A,x,b,w (and other problem vectors) are permuted such that the clamped
-indexes are first, the unclamped indexes are next, and the don't-care
-indexes are last. this permutation is recorded in the array `p'.
-initially p = 0..n-1, and as the rows and columns of A,x,b,w are swapped,
-the corresponding elements of p are swapped.
-
-because the C and N elements are grouped together in the rows of A, we can do
-lots of work with a fast dot product function. if A,x,etc were not permuted
-and we only had a permutation array, then those dot products would be much
-slower as we would have a permutation array lookup in some inner loops.
-
-A is accessed through an array of row pointers, so that element (i,j) of the
-permuted matrix is A[i][j]. this makes row swapping fast. for column swapping
-we still have to actually move the data.
-
-during execution of this algorithm we maintain an L*D*L' factorization of
-the clamped submatrix of A (call it `AC') which is the top left nC*nC
-submatrix of A. there are two ways we could arrange the rows/columns in AC.
-
-(1) AC is always permuted such that L*D*L' = AC. this causes a problem
-when a row/column is removed from C, because then all the rows/columns of A
-between the deleted index and the end of C need to be rotated downward.
-this results in a lot of data motion and slows things down.
-(2) L*D*L' is actually a factorization of a *permutation* of AC (which is
-itself a permutation of the underlying A). this is what we do - the
-permutation is recorded in the vector C. call this permutation A[C,C].
-when a row/column is removed from C, all we have to do is swap two
-rows/columns and manipulate C.
-
-*/
-
-#include "btDantzigLCP.h"
-
-#include <string.h> //memcpy
-
-bool s_error = false;
-
-//***************************************************************************
-// code generation parameters
-
-#define btLCP_FAST // use fast btLCP object
-
-// option 1 : matrix row pointers (less data copying)
-#define BTROWPTRS
-#define BTATYPE btScalar **
-#define BTAROW(i) (m_A[i])
-
-// option 2 : no matrix row pointers (slightly faster inner loops)
-//#define NOROWPTRS
-//#define BTATYPE btScalar *
-//#define BTAROW(i) (m_A+(i)*m_nskip)
-
-#define BTNUB_OPTIMIZATIONS
-
-/* solve L*X=B, with B containing 1 right hand sides.
- * L is an n*n lower triangular matrix with ones on the diagonal.
- * L is stored by rows and its leading dimension is lskip.
- * B is an n*1 matrix that contains the right hand sides.
- * B is stored by columns and its leading dimension is also lskip.
- * B is overwritten with X.
- * this processes blocks of 2*2.
- * if this is in the factorizer source file, n must be a multiple of 2.
- */
-
-static void btSolveL1_1(const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11, m11, Z21, m21, p1, q1, p2, *ex;
- const btScalar *ell;
- int i, j;
- /* compute all 2 x 1 blocks of X */
- for (i = 0; i < n; i += 2)
- {
- /* compute all 2 x 1 block of X, from rows i..i+2-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- Z21 = 0;
- ell = L + i * lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 2; j >= 0; j -= 2)
- {
- /* compute outer product and add it to the Z matrix */
- p1 = ell[0];
- q1 = ex[0];
- m11 = p1 * q1;
- p2 = ell[lskip1];
- m21 = p2 * q1;
- Z11 += m11;
- Z21 += m21;
- /* compute outer product and add it to the Z matrix */
- p1 = ell[1];
- q1 = ex[1];
- m11 = p1 * q1;
- p2 = ell[1 + lskip1];
- m21 = p2 * q1;
- /* advance pointers */
- ell += 2;
- ex += 2;
- Z11 += m11;
- Z21 += m21;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 2;
- for (; j > 0; j--)
- {
- /* compute outer product and add it to the Z matrix */
- p1 = ell[0];
- q1 = ex[0];
- m11 = p1 * q1;
- p2 = ell[lskip1];
- m21 = p2 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- Z11 += m11;
- Z21 += m21;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1 * Z11;
- ex[1] = Z21;
- /* end of outer loop */
- }
-}
-
-/* solve L*X=B, with B containing 2 right hand sides.
- * L is an n*n lower triangular matrix with ones on the diagonal.
- * L is stored by rows and its leading dimension is lskip.
- * B is an n*2 matrix that contains the right hand sides.
- * B is stored by columns and its leading dimension is also lskip.
- * B is overwritten with X.
- * this processes blocks of 2*2.
- * if this is in the factorizer source file, n must be a multiple of 2.
- */
-
-static void btSolveL1_2(const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11, m11, Z12, m12, Z21, m21, Z22, m22, p1, q1, p2, q2, *ex;
- const btScalar *ell;
- int i, j;
- /* compute all 2 x 2 blocks of X */
- for (i = 0; i < n; i += 2)
- {
- /* compute all 2 x 2 block of X, from rows i..i+2-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- Z12 = 0;
- Z21 = 0;
- Z22 = 0;
- ell = L + i * lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 2; j >= 0; j -= 2)
- {
- /* compute outer product and add it to the Z matrix */
- p1 = ell[0];
- q1 = ex[0];
- m11 = p1 * q1;
- q2 = ex[lskip1];
- m12 = p1 * q2;
- p2 = ell[lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- /* compute outer product and add it to the Z matrix */
- p1 = ell[1];
- q1 = ex[1];
- m11 = p1 * q1;
- q2 = ex[1 + lskip1];
- m12 = p1 * q2;
- p2 = ell[1 + lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- /* advance pointers */
- ell += 2;
- ex += 2;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 2;
- for (; j > 0; j--)
- {
- /* compute outer product and add it to the Z matrix */
- p1 = ell[0];
- q1 = ex[0];
- m11 = p1 * q1;
- q2 = ex[lskip1];
- m12 = p1 * q2;
- p2 = ell[lskip1];
- m21 = p2 * q1;
- m22 = p2 * q2;
- /* advance pointers */
- ell += 1;
- ex += 1;
- Z11 += m11;
- Z12 += m12;
- Z21 += m21;
- Z22 += m22;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- Z12 = ex[lskip1] - Z12;
- ex[lskip1] = Z12;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1 * Z11;
- ex[1] = Z21;
- Z22 = ex[1 + lskip1] - Z22 - p1 * Z12;
- ex[1 + lskip1] = Z22;
- /* end of outer loop */
- }
-}
-
-void btFactorLDLT(btScalar *A, btScalar *d, int n, int nskip1)
-{
- int i, j;
- btScalar sum, *ell, *dee, dd, p1, p2, q1, q2, Z11, m11, Z21, m21, Z22, m22;
- if (n < 1) return;
-
- for (i = 0; i <= n - 2; i += 2)
- {
- /* solve L*(D*l)=a, l is scaled elements in 2 x i block at A(i,0) */
- btSolveL1_2(A, A + i * nskip1, i, nskip1);
- /* scale the elements in a 2 x i block at A(i,0), and also */
- /* compute Z = the outer product matrix that we'll need. */
- Z11 = 0;
- Z21 = 0;
- Z22 = 0;
- ell = A + i * nskip1;
- dee = d;
- for (j = i - 6; j >= 0; j -= 6)
- {
- p1 = ell[0];
- p2 = ell[nskip1];
- dd = dee[0];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[0] = q1;
- ell[nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[1];
- p2 = ell[1 + nskip1];
- dd = dee[1];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[1] = q1;
- ell[1 + nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[2];
- p2 = ell[2 + nskip1];
- dd = dee[2];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[2] = q1;
- ell[2 + nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[3];
- p2 = ell[3 + nskip1];
- dd = dee[3];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[3] = q1;
- ell[3 + nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[4];
- p2 = ell[4 + nskip1];
- dd = dee[4];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[4] = q1;
- ell[4 + nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- p1 = ell[5];
- p2 = ell[5 + nskip1];
- dd = dee[5];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[5] = q1;
- ell[5 + nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- ell += 6;
- dee += 6;
- }
- /* compute left-over iterations */
- j += 6;
- for (; j > 0; j--)
- {
- p1 = ell[0];
- p2 = ell[nskip1];
- dd = dee[0];
- q1 = p1 * dd;
- q2 = p2 * dd;
- ell[0] = q1;
- ell[nskip1] = q2;
- m11 = p1 * q1;
- m21 = p2 * q1;
- m22 = p2 * q2;
- Z11 += m11;
- Z21 += m21;
- Z22 += m22;
- ell++;
- dee++;
- }
- /* solve for diagonal 2 x 2 block at A(i,i) */
- Z11 = ell[0] - Z11;
- Z21 = ell[nskip1] - Z21;
- Z22 = ell[1 + nskip1] - Z22;
- dee = d + i;
- /* factorize 2 x 2 block Z,dee */
- /* factorize row 1 */
- dee[0] = btRecip(Z11);
- /* factorize row 2 */
- sum = 0;
- q1 = Z21;
- q2 = q1 * dee[0];
- Z21 = q2;
- sum += q1 * q2;
- dee[1] = btRecip(Z22 - sum);
- /* done factorizing 2 x 2 block */
- ell[nskip1] = Z21;
- }
- /* compute the (less than 2) rows at the bottom */
- switch (n - i)
- {
- case 0:
- break;
-
- case 1:
- btSolveL1_1(A, A + i * nskip1, i, nskip1);
- /* scale the elements in a 1 x i block at A(i,0), and also */
- /* compute Z = the outer product matrix that we'll need. */
- Z11 = 0;
- ell = A + i * nskip1;
- dee = d;
- for (j = i - 6; j >= 0; j -= 6)
- {
- p1 = ell[0];
- dd = dee[0];
- q1 = p1 * dd;
- ell[0] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- p1 = ell[1];
- dd = dee[1];
- q1 = p1 * dd;
- ell[1] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- p1 = ell[2];
- dd = dee[2];
- q1 = p1 * dd;
- ell[2] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- p1 = ell[3];
- dd = dee[3];
- q1 = p1 * dd;
- ell[3] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- p1 = ell[4];
- dd = dee[4];
- q1 = p1 * dd;
- ell[4] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- p1 = ell[5];
- dd = dee[5];
- q1 = p1 * dd;
- ell[5] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- ell += 6;
- dee += 6;
- }
- /* compute left-over iterations */
- j += 6;
- for (; j > 0; j--)
- {
- p1 = ell[0];
- dd = dee[0];
- q1 = p1 * dd;
- ell[0] = q1;
- m11 = p1 * q1;
- Z11 += m11;
- ell++;
- dee++;
- }
- /* solve for diagonal 1 x 1 block at A(i,i) */
- Z11 = ell[0] - Z11;
- dee = d + i;
- /* factorize 1 x 1 block Z,dee */
- /* factorize row 1 */
- dee[0] = btRecip(Z11);
- /* done factorizing 1 x 1 block */
- break;
-
- //default: *((char*)0)=0; /* this should never happen! */
- }
-}
-
-/* solve L*X=B, with B containing 1 right hand sides.
- * L is an n*n lower triangular matrix with ones on the diagonal.
- * L is stored by rows and its leading dimension is lskip.
- * B is an n*1 matrix that contains the right hand sides.
- * B is stored by columns and its leading dimension is also lskip.
- * B is overwritten with X.
- * this processes blocks of 4*4.
- * if this is in the factorizer source file, n must be a multiple of 4.
- */
-
-void btSolveL1(const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11, Z21, Z31, Z41, p1, q1, p2, p3, p4, *ex;
- const btScalar *ell;
- int lskip2, lskip3, i, j;
- /* compute lskip values */
- lskip2 = 2 * lskip1;
- lskip3 = 3 * lskip1;
- /* compute all 4 x 1 blocks of X */
- for (i = 0; i <= n - 4; i += 4)
- {
- /* compute all 4 x 1 block of X, from rows i..i+4-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- Z21 = 0;
- Z31 = 0;
- Z41 = 0;
- ell = L + i * lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 12; j >= 0; j -= 12)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- p2 = ell[lskip1];
- p3 = ell[lskip2];
- p4 = ell[lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[1];
- q1 = ex[1];
- p2 = ell[1 + lskip1];
- p3 = ell[1 + lskip2];
- p4 = ell[1 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[2];
- q1 = ex[2];
- p2 = ell[2 + lskip1];
- p3 = ell[2 + lskip2];
- p4 = ell[2 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[3];
- q1 = ex[3];
- p2 = ell[3 + lskip1];
- p3 = ell[3 + lskip2];
- p4 = ell[3 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[4];
- q1 = ex[4];
- p2 = ell[4 + lskip1];
- p3 = ell[4 + lskip2];
- p4 = ell[4 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[5];
- q1 = ex[5];
- p2 = ell[5 + lskip1];
- p3 = ell[5 + lskip2];
- p4 = ell[5 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[6];
- q1 = ex[6];
- p2 = ell[6 + lskip1];
- p3 = ell[6 + lskip2];
- p4 = ell[6 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[7];
- q1 = ex[7];
- p2 = ell[7 + lskip1];
- p3 = ell[7 + lskip2];
- p4 = ell[7 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[8];
- q1 = ex[8];
- p2 = ell[8 + lskip1];
- p3 = ell[8 + lskip2];
- p4 = ell[8 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[9];
- q1 = ex[9];
- p2 = ell[9 + lskip1];
- p3 = ell[9 + lskip2];
- p4 = ell[9 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[10];
- q1 = ex[10];
- p2 = ell[10 + lskip1];
- p3 = ell[10 + lskip2];
- p4 = ell[10 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* load p and q values */
- p1 = ell[11];
- q1 = ex[11];
- p2 = ell[11 + lskip1];
- p3 = ell[11 + lskip2];
- p4 = ell[11 + lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* advance pointers */
- ell += 12;
- ex += 12;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 12;
- for (; j > 0; j--)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- p2 = ell[lskip1];
- p3 = ell[lskip2];
- p4 = ell[lskip3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- Z21 += p2 * q1;
- Z31 += p3 * q1;
- Z41 += p4 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[lskip1];
- Z21 = ex[1] - Z21 - p1 * Z11;
- ex[1] = Z21;
- p1 = ell[lskip2];
- p2 = ell[1 + lskip2];
- Z31 = ex[2] - Z31 - p1 * Z11 - p2 * Z21;
- ex[2] = Z31;
- p1 = ell[lskip3];
- p2 = ell[1 + lskip3];
- p3 = ell[2 + lskip3];
- Z41 = ex[3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
- ex[3] = Z41;
- /* end of outer loop */
- }
- /* compute rows at end that are not a multiple of block size */
- for (; i < n; i++)
- {
- /* compute all 1 x 1 block of X, from rows i..i+1-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- ell = L + i * lskip1;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 12; j >= 0; j -= 12)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[1];
- q1 = ex[1];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[2];
- q1 = ex[2];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[3];
- q1 = ex[3];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[4];
- q1 = ex[4];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[5];
- q1 = ex[5];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[6];
- q1 = ex[6];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[7];
- q1 = ex[7];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[8];
- q1 = ex[8];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[9];
- q1 = ex[9];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[10];
- q1 = ex[10];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* load p and q values */
- p1 = ell[11];
- q1 = ex[11];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* advance pointers */
- ell += 12;
- ex += 12;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 12;
- for (; j > 0; j--)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- /* compute outer product and add it to the Z matrix */
- Z11 += p1 * q1;
- /* advance pointers */
- ell += 1;
- ex += 1;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- }
-}
-
-/* solve L^T * x=b, with b containing 1 right hand side.
- * L is an n*n lower triangular matrix with ones on the diagonal.
- * L is stored by rows and its leading dimension is lskip.
- * b is an n*1 matrix that contains the right hand side.
- * b is overwritten with x.
- * this processes blocks of 4.
- */
-
-void btSolveL1T(const btScalar *L, btScalar *B, int n, int lskip1)
-{
- /* declare variables - Z matrix, p and q vectors, etc */
- btScalar Z11, m11, Z21, m21, Z31, m31, Z41, m41, p1, q1, p2, p3, p4, *ex;
- const btScalar *ell;
- int lskip2, i, j;
- // int lskip3;
- /* special handling for L and B because we're solving L1 *transpose* */
- L = L + (n - 1) * (lskip1 + 1);
- B = B + n - 1;
- lskip1 = -lskip1;
- /* compute lskip values */
- lskip2 = 2 * lskip1;
- //lskip3 = 3*lskip1;
- /* compute all 4 x 1 blocks of X */
- for (i = 0; i <= n - 4; i += 4)
- {
- /* compute all 4 x 1 block of X, from rows i..i+4-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- Z21 = 0;
- Z31 = 0;
- Z41 = 0;
- ell = L - i;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 4; j >= 0; j -= 4)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- p2 = ell[-1];
- p3 = ell[-2];
- p4 = ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-1];
- p2 = ell[-1];
- p3 = ell[-2];
- p4 = ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-2];
- p2 = ell[-1];
- p3 = ell[-2];
- p4 = ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-3];
- p2 = ell[-1];
- p3 = ell[-2];
- p4 = ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- ex -= 4;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 4;
- for (; j > 0; j--)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- p2 = ell[-1];
- p3 = ell[-2];
- p4 = ell[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- m21 = p2 * q1;
- m31 = p3 * q1;
- m41 = p4 * q1;
- ell += lskip1;
- ex -= 1;
- Z11 += m11;
- Z21 += m21;
- Z31 += m31;
- Z41 += m41;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- p1 = ell[-1];
- Z21 = ex[-1] - Z21 - p1 * Z11;
- ex[-1] = Z21;
- p1 = ell[-2];
- p2 = ell[-2 + lskip1];
- Z31 = ex[-2] - Z31 - p1 * Z11 - p2 * Z21;
- ex[-2] = Z31;
- p1 = ell[-3];
- p2 = ell[-3 + lskip1];
- p3 = ell[-3 + lskip2];
- Z41 = ex[-3] - Z41 - p1 * Z11 - p2 * Z21 - p3 * Z31;
- ex[-3] = Z41;
- /* end of outer loop */
- }
- /* compute rows at end that are not a multiple of block size */
- for (; i < n; i++)
- {
- /* compute all 1 x 1 block of X, from rows i..i+1-1 */
- /* set the Z matrix to 0 */
- Z11 = 0;
- ell = L - i;
- ex = B;
- /* the inner loop that computes outer products and adds them to Z */
- for (j = i - 4; j >= 0; j -= 4)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-1];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-2];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- Z11 += m11;
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[-3];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- ex -= 4;
- Z11 += m11;
- /* end of inner loop */
- }
- /* compute left-over iterations */
- j += 4;
- for (; j > 0; j--)
- {
- /* load p and q values */
- p1 = ell[0];
- q1 = ex[0];
- /* compute outer product and add it to the Z matrix */
- m11 = p1 * q1;
- ell += lskip1;
- ex -= 1;
- Z11 += m11;
- }
- /* finish computing the X(i) block */
- Z11 = ex[0] - Z11;
- ex[0] = Z11;
- }
-}
-
-void btVectorScale(btScalar *a, const btScalar *d, int n)
-{
- btAssert(a && d && n >= 0);
- for (int i = 0; i < n; i++)
- {
- a[i] *= d[i];
- }
-}
-
-void btSolveLDLT(const btScalar *L, const btScalar *d, btScalar *b, int n, int nskip)
-{
- btAssert(L && d && b && n > 0 && nskip >= n);
- btSolveL1(L, b, n, nskip);
- btVectorScale(b, d, n);
- btSolveL1T(L, b, n, nskip);
-}
-
-//***************************************************************************
-
-// swap row/column i1 with i2 in the n*n matrix A. the leading dimension of
-// A is nskip. this only references and swaps the lower triangle.
-// if `do_fast_row_swaps' is nonzero and row pointers are being used, then
-// rows will be swapped by exchanging row pointers. otherwise the data will
-// be copied.
-
-static void btSwapRowsAndCols(BTATYPE A, int n, int i1, int i2, int nskip,
- int do_fast_row_swaps)
-{
- btAssert(A && n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n &&
- nskip >= n && i1 < i2);
-
-#ifdef BTROWPTRS
- btScalar *A_i1 = A[i1];
- btScalar *A_i2 = A[i2];
- for (int i = i1 + 1; i < i2; ++i)
- {
- btScalar *A_i_i1 = A[i] + i1;
- A_i1[i] = *A_i_i1;
- *A_i_i1 = A_i2[i];
- }
- A_i1[i2] = A_i1[i1];
- A_i1[i1] = A_i2[i1];
- A_i2[i1] = A_i2[i2];
- // swap rows, by swapping row pointers
- if (do_fast_row_swaps)
- {
- A[i1] = A_i2;
- A[i2] = A_i1;
- }
- else
- {
- // Only swap till i2 column to match A plain storage variant.
- for (int k = 0; k <= i2; ++k)
- {
- btScalar tmp = A_i1[k];
- A_i1[k] = A_i2[k];
- A_i2[k] = tmp;
- }
- }
- // swap columns the hard way
- for (int j = i2 + 1; j < n; ++j)
- {
- btScalar *A_j = A[j];
- btScalar tmp = A_j[i1];
- A_j[i1] = A_j[i2];
- A_j[i2] = tmp;
- }
-#else
- btScalar *A_i1 = A + i1 * nskip;
- btScalar *A_i2 = A + i2 * nskip;
- for (int k = 0; k < i1; ++k)
- {
- btScalar tmp = A_i1[k];
- A_i1[k] = A_i2[k];
- A_i2[k] = tmp;
- }
- btScalar *A_i = A_i1 + nskip;
- for (int i = i1 + 1; i < i2; A_i += nskip, ++i)
- {
- btScalar tmp = A_i2[i];
- A_i2[i] = A_i[i1];
- A_i[i1] = tmp;
- }
- {
- btScalar tmp = A_i1[i1];
- A_i1[i1] = A_i2[i2];
- A_i2[i2] = tmp;
- }
- btScalar *A_j = A_i2 + nskip;
- for (int j = i2 + 1; j < n; A_j += nskip, ++j)
- {
- btScalar tmp = A_j[i1];
- A_j[i1] = A_j[i2];
- A_j[i2] = tmp;
- }
-#endif
-}
-
-// swap two indexes in the n*n LCP problem. i1 must be <= i2.
-
-static void btSwapProblem(BTATYPE A, btScalar *x, btScalar *b, btScalar *w, btScalar *lo,
- btScalar *hi, int *p, bool *state, int *findex,
- int n, int i1, int i2, int nskip,
- int do_fast_row_swaps)
-{
- btScalar tmpr;
- int tmpi;
- bool tmpb;
- btAssert(n > 0 && i1 >= 0 && i2 >= 0 && i1 < n && i2 < n && nskip >= n && i1 <= i2);
- if (i1 == i2) return;
-
- btSwapRowsAndCols(A, n, i1, i2, nskip, do_fast_row_swaps);
-
- tmpr = x[i1];
- x[i1] = x[i2];
- x[i2] = tmpr;
-
- tmpr = b[i1];
- b[i1] = b[i2];
- b[i2] = tmpr;
-
- tmpr = w[i1];
- w[i1] = w[i2];
- w[i2] = tmpr;
-
- tmpr = lo[i1];
- lo[i1] = lo[i2];
- lo[i2] = tmpr;
-
- tmpr = hi[i1];
- hi[i1] = hi[i2];
- hi[i2] = tmpr;
-
- tmpi = p[i1];
- p[i1] = p[i2];
- p[i2] = tmpi;
-
- tmpb = state[i1];
- state[i1] = state[i2];
- state[i2] = tmpb;
-
- if (findex)
- {
- tmpi = findex[i1];
- findex[i1] = findex[i2];
- findex[i2] = tmpi;
- }
-}
-
-//***************************************************************************
-// btLCP manipulator object. this represents an n*n LCP problem.
-//
-// two index sets C and N are kept. each set holds a subset of
-// the variable indexes 0..n-1. an index can only be in one set.
-// initially both sets are empty.
-//
-// the index set C is special: solutions to A(C,C)\A(C,i) can be generated.
-
-//***************************************************************************
-// fast implementation of btLCP. see the above definition of btLCP for
-// interface comments.
-//
-// `p' records the permutation of A,x,b,w,etc. p is initially 1:n and is
-// permuted as the other vectors/matrices are permuted.
-//
-// A,x,b,w,lo,hi,state,findex,p,c are permuted such that sets C,N have
-// contiguous indexes. the don't-care indexes follow N.
-//
-// an L*D*L' factorization is maintained of A(C,C), and whenever indexes are
-// added or removed from the set C the factorization is updated.
-// thus L*D*L'=A[C,C], i.e. a permuted top left nC*nC submatrix of A.
-// the leading dimension of the matrix L is always `nskip'.
-//
-// at the start there may be other indexes that are unbounded but are not
-// included in `nub'. btLCP will permute the matrix so that absolutely all
-// unbounded vectors are at the start. thus there may be some initial
-// permutation.
-//
-// the algorithms here assume certain patterns, particularly with respect to
-// index transfer.
-
-#ifdef btLCP_FAST
-
-struct btLCP
-{
- const int m_n;
- const int m_nskip;
- int m_nub;
- int m_nC, m_nN; // size of each index set
- BTATYPE const m_A; // A rows
- btScalar *const m_x, *const m_b, *const m_w, *const m_lo, *const m_hi; // permuted LCP problem data
- btScalar *const m_L, *const m_d; // L*D*L' factorization of set C
- btScalar *const m_Dell, *const m_ell, *const m_tmp;
- bool *const m_state;
- int *const m_findex, *const m_p, *const m_C;
-
- btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
- btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
- btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
- bool *_state, int *_findex, int *p, int *c, btScalar **Arows);
- int getNub() const { return m_nub; }
- void transfer_i_to_C(int i);
- void transfer_i_to_N(int i) { m_nN++; } // because we can assume C and N span 1:i-1
- void transfer_i_from_N_to_C(int i);
- void transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch);
- int numC() const { return m_nC; }
- int numN() const { return m_nN; }
- int indexC(int i) const { return i; }
- int indexN(int i) const { return i + m_nC; }
- btScalar Aii(int i) const { return BTAROW(i)[i]; }
- btScalar AiC_times_qC(int i, btScalar *q) const { return btLargeDot(BTAROW(i), q, m_nC); }
- btScalar AiN_times_qN(int i, btScalar *q) const { return btLargeDot(BTAROW(i) + m_nC, q + m_nC, m_nN); }
- void pN_equals_ANC_times_qC(btScalar *p, btScalar *q);
- void pN_plusequals_ANi(btScalar *p, int i, int sign = 1);
- void pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q);
- void pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q);
- void solve1(btScalar *a, int i, int dir = 1, int only_transfer = 0);
- void unpermute();
-};
-
-btLCP::btLCP(int _n, int _nskip, int _nub, btScalar *_Adata, btScalar *_x, btScalar *_b, btScalar *_w,
- btScalar *_lo, btScalar *_hi, btScalar *l, btScalar *_d,
- btScalar *_Dell, btScalar *_ell, btScalar *_tmp,
- bool *_state, int *_findex, int *p, int *c, btScalar **Arows) : m_n(_n), m_nskip(_nskip), m_nub(_nub), m_nC(0), m_nN(0),
-#ifdef BTROWPTRS
- m_A(Arows),
-#else
- m_A(_Adata),
-#endif
- m_x(_x),
- m_b(_b),
- m_w(_w),
- m_lo(_lo),
- m_hi(_hi),
- m_L(l),
- m_d(_d),
- m_Dell(_Dell),
- m_ell(_ell),
- m_tmp(_tmp),
- m_state(_state),
- m_findex(_findex),
- m_p(p),
- m_C(c)
-{
- {
- btSetZero(m_x, m_n);
- }
-
- {
-#ifdef BTROWPTRS
- // make matrix row pointers
- btScalar *aptr = _Adata;
- BTATYPE A = m_A;
- const int n = m_n, nskip = m_nskip;
- for (int k = 0; k < n; aptr += nskip, ++k) A[k] = aptr;
-#endif
- }
-
- {
- int *p = m_p;
- const int n = m_n;
- for (int k = 0; k < n; ++k) p[k] = k; // initially unpermuted
- }
-
- /*
- // for testing, we can do some random swaps in the area i > nub
- {
- const int n = m_n;
- const int nub = m_nub;
- if (nub < n) {
- for (int k=0; k<100; k++) {
- int i1,i2;
- do {
- i1 = dRandInt(n-nub)+nub;
- i2 = dRandInt(n-nub)+nub;
- }
- while (i1 > i2);
- //printf ("--> %d %d\n",i1,i2);
- btSwapProblem (m_A,m_x,m_b,m_w,m_lo,m_hi,m_p,m_state,m_findex,n,i1,i2,m_nskip,0);
- }
- }
- */
-
- // permute the problem so that *all* the unbounded variables are at the
- // start, i.e. look for unbounded variables not included in `nub'. we can
- // potentially push up `nub' this way and get a bigger initial factorization.
- // note that when we swap rows/cols here we must not just swap row pointers,
- // as the initial factorization relies on the data being all in one chunk.
- // variables that have findex >= 0 are *not* considered to be unbounded even
- // if lo=-inf and hi=inf - this is because these limits may change during the
- // solution process.
-
- {
- int *findex = m_findex;
- btScalar *lo = m_lo, *hi = m_hi;
- const int n = m_n;
- for (int k = m_nub; k < n; ++k)
- {
- if (findex && findex[k] >= 0) continue;
- if (lo[k] == -BT_INFINITY && hi[k] == BT_INFINITY)
- {
- btSwapProblem(m_A, m_x, m_b, m_w, lo, hi, m_p, m_state, findex, n, m_nub, k, m_nskip, 0);
- m_nub++;
- }
- }
- }
-
- // if there are unbounded variables at the start, factorize A up to that
- // point and solve for x. this puts all indexes 0..nub-1 into C.
- if (m_nub > 0)
- {
- const int nub = m_nub;
- {
- btScalar *Lrow = m_L;
- const int nskip = m_nskip;
- for (int j = 0; j < nub; Lrow += nskip, ++j) memcpy(Lrow, BTAROW(j), (j + 1) * sizeof(btScalar));
- }
- btFactorLDLT(m_L, m_d, nub, m_nskip);
- memcpy(m_x, m_b, nub * sizeof(btScalar));
- btSolveLDLT(m_L, m_d, m_x, nub, m_nskip);
- btSetZero(m_w, nub);
- {
- int *C = m_C;
- for (int k = 0; k < nub; ++k) C[k] = k;
- }
- m_nC = nub;
- }
-
- // permute the indexes > nub such that all findex variables are at the end
- if (m_findex)
- {
- const int nub = m_nub;
- int *findex = m_findex;
- int num_at_end = 0;
- for (int k = m_n - 1; k >= nub; k--)
- {
- if (findex[k] >= 0)
- {
- btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, findex, m_n, k, m_n - 1 - num_at_end, m_nskip, 1);
- num_at_end++;
- }
- }
- }
-
- // print info about indexes
- /*
- {
- const int n = m_n;
- const int nub = m_nub;
- for (int k=0; k<n; k++) {
- if (k<nub) printf ("C");
- else if (m_lo[k]==-BT_INFINITY && m_hi[k]==BT_INFINITY) printf ("c");
- else printf (".");
- }
- printf ("\n");
- }
- */
-}
-
-void btLCP::transfer_i_to_C(int i)
-{
- {
- if (m_nC > 0)
- {
- // ell,Dell were computed by solve1(). note, ell = D \ L1solve (L,A(i,C))
- {
- const int nC = m_nC;
- btScalar *const Ltgt = m_L + nC * m_nskip, *ell = m_ell;
- for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j];
- }
- const int nC = m_nC;
- m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
- }
- else
- {
- m_d[0] = btRecip(BTAROW(i)[i]);
- }
-
- btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
-
- const int nC = m_nC;
- m_C[nC] = nC;
- m_nC = nC + 1; // nC value is outdated after this line
- }
-}
-
-void btLCP::transfer_i_from_N_to_C(int i)
-{
- {
- if (m_nC > 0)
- {
- {
- btScalar *const aptr = BTAROW(i);
- btScalar *Dell = m_Dell;
- const int *C = m_C;
-#ifdef BTNUB_OPTIMIZATIONS
- // if nub>0, initial part of aptr unpermuted
- const int nub = m_nub;
- int j = 0;
- for (; j < nub; ++j) Dell[j] = aptr[j];
- const int nC = m_nC;
- for (; j < nC; ++j) Dell[j] = aptr[C[j]];
-#else
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
-#endif
- }
- btSolveL1(m_L, m_Dell, m_nC, m_nskip);
- {
- const int nC = m_nC;
- btScalar *const Ltgt = m_L + nC * m_nskip;
- btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
- for (int j = 0; j < nC; ++j) Ltgt[j] = ell[j] = Dell[j] * d[j];
- }
- const int nC = m_nC;
- m_d[nC] = btRecip(BTAROW(i)[i] - btLargeDot(m_ell, m_Dell, nC));
- }
- else
- {
- m_d[0] = btRecip(BTAROW(i)[i]);
- }
-
- btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, m_nC, i, m_nskip, 1);
-
- const int nC = m_nC;
- m_C[nC] = nC;
- m_nN--;
- m_nC = nC + 1; // nC value is outdated after this line
- }
-
- // @@@ TO DO LATER
- // if we just finish here then we'll go back and re-solve for
- // delta_x. but actually we can be more efficient and incrementally
- // update delta_x here. but if we do this, we wont have ell and Dell
- // to use in updating the factorization later.
-}
-
-void btRemoveRowCol(btScalar *A, int n, int nskip, int r)
-{
- btAssert(A && n > 0 && nskip >= n && r >= 0 && r < n);
- if (r >= n - 1) return;
- if (r > 0)
- {
- {
- const size_t move_size = (n - r - 1) * sizeof(btScalar);
- btScalar *Adst = A + r;
- for (int i = 0; i < r; Adst += nskip, ++i)
- {
- btScalar *Asrc = Adst + 1;
- memmove(Adst, Asrc, move_size);
- }
- }
- {
- const size_t cpy_size = r * sizeof(btScalar);
- btScalar *Adst = A + r * nskip;
- for (int i = r; i < (n - 1); ++i)
- {
- btScalar *Asrc = Adst + nskip;
- memcpy(Adst, Asrc, cpy_size);
- Adst = Asrc;
- }
- }
- }
- {
- const size_t cpy_size = (n - r - 1) * sizeof(btScalar);
- btScalar *Adst = A + r * (nskip + 1);
- for (int i = r; i < (n - 1); ++i)
- {
- btScalar *Asrc = Adst + (nskip + 1);
- memcpy(Adst, Asrc, cpy_size);
- Adst = Asrc - 1;
- }
- }
-}
-
-void btLDLTAddTL(btScalar *L, btScalar *d, const btScalar *a, int n, int nskip, btAlignedObjectArray<btScalar> &scratch)
-{
- btAssert(L && d && a && n > 0 && nskip >= n);
-
- if (n < 2) return;
- scratch.resize(2 * nskip);
- btScalar *W1 = &scratch[0];
-
- btScalar *W2 = W1 + nskip;
-
- W1[0] = btScalar(0.0);
- W2[0] = btScalar(0.0);
- for (int j = 1; j < n; ++j)
- {
- W1[j] = W2[j] = (btScalar)(a[j] * SIMDSQRT12);
- }
- btScalar W11 = (btScalar)((btScalar(0.5) * a[0] + 1) * SIMDSQRT12);
- btScalar W21 = (btScalar)((btScalar(0.5) * a[0] - 1) * SIMDSQRT12);
-
- btScalar alpha1 = btScalar(1.0);
- btScalar alpha2 = btScalar(1.0);
-
- {
- btScalar dee = d[0];
- btScalar alphanew = alpha1 + (W11 * W11) * dee;
- btAssert(alphanew != btScalar(0.0));
- dee /= alphanew;
- btScalar gamma1 = W11 * dee;
- dee *= alpha1;
- alpha1 = alphanew;
- alphanew = alpha2 - (W21 * W21) * dee;
- dee /= alphanew;
- //btScalar gamma2 = W21 * dee;
- alpha2 = alphanew;
- btScalar k1 = btScalar(1.0) - W21 * gamma1;
- btScalar k2 = W21 * gamma1 * W11 - W21;
- btScalar *ll = L + nskip;
- for (int p = 1; p < n; ll += nskip, ++p)
- {
- btScalar Wp = W1[p];
- btScalar ell = *ll;
- W1[p] = Wp - W11 * ell;
- W2[p] = k1 * Wp + k2 * ell;
- }
- }
-
- btScalar *ll = L + (nskip + 1);
- for (int j = 1; j < n; ll += nskip + 1, ++j)
- {
- btScalar k1 = W1[j];
- btScalar k2 = W2[j];
-
- btScalar dee = d[j];
- btScalar alphanew = alpha1 + (k1 * k1) * dee;
- btAssert(alphanew != btScalar(0.0));
- dee /= alphanew;
- btScalar gamma1 = k1 * dee;
- dee *= alpha1;
- alpha1 = alphanew;
- alphanew = alpha2 - (k2 * k2) * dee;
- dee /= alphanew;
- btScalar gamma2 = k2 * dee;
- dee *= alpha2;
- d[j] = dee;
- alpha2 = alphanew;
-
- btScalar *l = ll + nskip;
- for (int p = j + 1; p < n; l += nskip, ++p)
- {
- btScalar ell = *l;
- btScalar Wp = W1[p] - k1 * ell;
- ell += gamma1 * Wp;
- W1[p] = Wp;
- Wp = W2[p] - k2 * ell;
- ell -= gamma2 * Wp;
- W2[p] = Wp;
- *l = ell;
- }
- }
-}
-
-#define _BTGETA(i, j) (A[i][j])
-//#define _GETA(i,j) (A[(i)*nskip+(j)])
-#define BTGETA(i, j) ((i > j) ? _BTGETA(i, j) : _BTGETA(j, i))
-
-inline size_t btEstimateLDLTAddTLTmpbufSize(int nskip)
-{
- return nskip * 2 * sizeof(btScalar);
-}
-
-void btLDLTRemove(btScalar **A, const int *p, btScalar *L, btScalar *d,
- int n1, int n2, int r, int nskip, btAlignedObjectArray<btScalar> &scratch)
-{
- btAssert(A && p && L && d && n1 > 0 && n2 > 0 && r >= 0 && r < n2 &&
- n1 >= n2 && nskip >= n1);
-#ifdef BT_DEBUG
- for (int i = 0; i < n2; ++i)
- btAssert(p[i] >= 0 && p[i] < n1);
-#endif
-
- if (r == n2 - 1)
- {
- return; // deleting last row/col is easy
- }
- else
- {
- size_t LDLTAddTL_size = btEstimateLDLTAddTLTmpbufSize(nskip);
- btAssert(LDLTAddTL_size % sizeof(btScalar) == 0);
- scratch.resize(nskip * 2 + n2);
- btScalar *tmp = &scratch[0];
- if (r == 0)
- {
- btScalar *a = (btScalar *)((char *)tmp + LDLTAddTL_size);
- const int p_0 = p[0];
- for (int i = 0; i < n2; ++i)
- {
- a[i] = -BTGETA(p[i], p_0);
- }
- a[0] += btScalar(1.0);
- btLDLTAddTL(L, d, a, n2, nskip, scratch);
- }
- else
- {
- btScalar *t = (btScalar *)((char *)tmp + LDLTAddTL_size);
- {
- btScalar *Lcurr = L + r * nskip;
- for (int i = 0; i < r; ++Lcurr, ++i)
- {
- btAssert(d[i] != btScalar(0.0));
- t[i] = *Lcurr / d[i];
- }
- }
- btScalar *a = t + r;
- {
- btScalar *Lcurr = L + r * nskip;
- const int *pp_r = p + r, p_r = *pp_r;
- const int n2_minus_r = n2 - r;
- for (int i = 0; i < n2_minus_r; Lcurr += nskip, ++i)
- {
- a[i] = btLargeDot(Lcurr, t, r) - BTGETA(pp_r[i], p_r);
- }
- }
- a[0] += btScalar(1.0);
- btLDLTAddTL(L + r * nskip + r, d + r, a, n2 - r, nskip, scratch);
- }
- }
-
- // snip out row/column r from L and d
- btRemoveRowCol(L, n2, nskip, r);
- if (r < (n2 - 1)) memmove(d + r, d + r + 1, (n2 - r - 1) * sizeof(btScalar));
-}
-
-void btLCP::transfer_i_from_C_to_N(int i, btAlignedObjectArray<btScalar> &scratch)
-{
- {
- int *C = m_C;
- // remove a row/column from the factorization, and adjust the
- // indexes (black magic!)
- int last_idx = -1;
- const int nC = m_nC;
- int j = 0;
- for (; j < nC; ++j)
- {
- if (C[j] == nC - 1)
- {
- last_idx = j;
- }
- if (C[j] == i)
- {
- btLDLTRemove(m_A, C, m_L, m_d, m_n, nC, j, m_nskip, scratch);
- int k;
- if (last_idx == -1)
- {
- for (k = j + 1; k < nC; ++k)
- {
- if (C[k] == nC - 1)
- {
- break;
- }
- }
- btAssert(k < nC);
- }
- else
- {
- k = last_idx;
- }
- C[k] = C[j];
- if (j < (nC - 1)) memmove(C + j, C + j + 1, (nC - j - 1) * sizeof(int));
- break;
- }
- }
- btAssert(j < nC);
-
- btSwapProblem(m_A, m_x, m_b, m_w, m_lo, m_hi, m_p, m_state, m_findex, m_n, i, nC - 1, m_nskip, 1);
-
- m_nN++;
- m_nC = nC - 1; // nC value is outdated after this line
- }
-}
-
-void btLCP::pN_equals_ANC_times_qC(btScalar *p, btScalar *q)
-{
- // we could try to make this matrix-vector multiplication faster using
- // outer product matrix tricks, e.g. with the dMultidotX() functions.
- // but i tried it and it actually made things slower on random 100x100
- // problems because of the overhead involved. so we'll stick with the
- // simple method for now.
- const int nC = m_nC;
- btScalar *ptgt = p + nC;
- const int nN = m_nN;
- for (int i = 0; i < nN; ++i)
- {
- ptgt[i] = btLargeDot(BTAROW(i + nC), q, nC);
- }
-}
-
-void btLCP::pN_plusequals_ANi(btScalar *p, int i, int sign)
-{
- const int nC = m_nC;
- btScalar *aptr = BTAROW(i) + nC;
- btScalar *ptgt = p + nC;
- if (sign > 0)
- {
- const int nN = m_nN;
- for (int j = 0; j < nN; ++j) ptgt[j] += aptr[j];
- }
- else
- {
- const int nN = m_nN;
- for (int j = 0; j < nN; ++j) ptgt[j] -= aptr[j];
- }
-}
-
-void btLCP::pC_plusequals_s_times_qC(btScalar *p, btScalar s, btScalar *q)
-{
- const int nC = m_nC;
- for (int i = 0; i < nC; ++i)
- {
- p[i] += s * q[i];
- }
-}
-
-void btLCP::pN_plusequals_s_times_qN(btScalar *p, btScalar s, btScalar *q)
-{
- const int nC = m_nC;
- btScalar *ptgt = p + nC, *qsrc = q + nC;
- const int nN = m_nN;
- for (int i = 0; i < nN; ++i)
- {
- ptgt[i] += s * qsrc[i];
- }
-}
-
-void btLCP::solve1(btScalar *a, int i, int dir, int only_transfer)
-{
- // the `Dell' and `ell' that are computed here are saved. if index i is
- // later added to the factorization then they can be reused.
- //
- // @@@ question: do we need to solve for entire delta_x??? yes, but
- // only if an x goes below 0 during the step.
-
- if (m_nC > 0)
- {
- {
- btScalar *Dell = m_Dell;
- int *C = m_C;
- btScalar *aptr = BTAROW(i);
-#ifdef BTNUB_OPTIMIZATIONS
- // if nub>0, initial part of aptr[] is guaranteed unpermuted
- const int nub = m_nub;
- int j = 0;
- for (; j < nub; ++j) Dell[j] = aptr[j];
- const int nC = m_nC;
- for (; j < nC; ++j) Dell[j] = aptr[C[j]];
-#else
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) Dell[j] = aptr[C[j]];
-#endif
- }
- btSolveL1(m_L, m_Dell, m_nC, m_nskip);
- {
- btScalar *ell = m_ell, *Dell = m_Dell, *d = m_d;
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) ell[j] = Dell[j] * d[j];
- }
-
- if (!only_transfer)
- {
- btScalar *tmp = m_tmp, *ell = m_ell;
- {
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) tmp[j] = ell[j];
- }
- btSolveL1T(m_L, tmp, m_nC, m_nskip);
- if (dir > 0)
- {
- int *C = m_C;
- btScalar *tmp = m_tmp;
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) a[C[j]] = -tmp[j];
- }
- else
- {
- int *C = m_C;
- btScalar *tmp = m_tmp;
- const int nC = m_nC;
- for (int j = 0; j < nC; ++j) a[C[j]] = tmp[j];
- }
- }
- }
-}
-
-void btLCP::unpermute()
-{
- // now we have to un-permute x and w
- {
- memcpy(m_tmp, m_x, m_n * sizeof(btScalar));
- btScalar *x = m_x, *tmp = m_tmp;
- const int *p = m_p;
- const int n = m_n;
- for (int j = 0; j < n; ++j) x[p[j]] = tmp[j];
- }
- {
- memcpy(m_tmp, m_w, m_n * sizeof(btScalar));
- btScalar *w = m_w, *tmp = m_tmp;
- const int *p = m_p;
- const int n = m_n;
- for (int j = 0; j < n; ++j) w[p[j]] = tmp[j];
- }
-}
-
-#endif // btLCP_FAST
-
-//***************************************************************************
-// an optimized Dantzig LCP driver routine for the lo-hi LCP problem.
-
-bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b,
- btScalar *outer_w, int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratchMem)
-{
- s_error = false;
-
- // printf("btSolveDantzigLCP n=%d\n",n);
- btAssert(n > 0 && A && x && b && lo && hi && nub >= 0 && nub <= n);
- btAssert(outer_w);
-
-#ifdef BT_DEBUG
- {
- // check restrictions on lo and hi
- for (int k = 0; k < n; ++k)
- btAssert(lo[k] <= 0 && hi[k] >= 0);
- }
-#endif
-
- // if all the variables are unbounded then we can just factor, solve,
- // and return
- if (nub >= n)
- {
- int nskip = (n);
- btFactorLDLT(A, outer_w, n, nskip);
- btSolveLDLT(A, outer_w, b, n, nskip);
- memcpy(x, b, n * sizeof(btScalar));
-
- return !s_error;
- }
-
- const int nskip = (n);
- scratchMem.L.resize(n * nskip);
-
- scratchMem.d.resize(n);
-
- btScalar *w = outer_w;
- scratchMem.delta_w.resize(n);
- scratchMem.delta_x.resize(n);
- scratchMem.Dell.resize(n);
- scratchMem.ell.resize(n);
- scratchMem.Arows.resize(n);
- scratchMem.p.resize(n);
- scratchMem.C.resize(n);
-
- // for i in N, state[i] is 0 if x(i)==lo(i) or 1 if x(i)==hi(i)
- scratchMem.state.resize(n);
-
- // create LCP object. note that tmp is set to delta_w to save space, this
- // optimization relies on knowledge of how tmp is used, so be careful!
- btLCP lcp(n, nskip, nub, A, x, b, w, lo, hi, &scratchMem.L[0], &scratchMem.d[0], &scratchMem.Dell[0], &scratchMem.ell[0], &scratchMem.delta_w[0], &scratchMem.state[0], findex, &scratchMem.p[0], &scratchMem.C[0], &scratchMem.Arows[0]);
- int adj_nub = lcp.getNub();
-
- // loop over all indexes adj_nub..n-1. for index i, if x(i),w(i) satisfy the
- // LCP conditions then i is added to the appropriate index set. otherwise
- // x(i),w(i) is driven either +ve or -ve to force it to the valid region.
- // as we drive x(i), x(C) is also adjusted to keep w(C) at zero.
- // while driving x(i) we maintain the LCP conditions on the other variables
- // 0..i-1. we do this by watching out for other x(i),w(i) values going
- // outside the valid region, and then switching them between index sets
- // when that happens.
-
- bool hit_first_friction_index = false;
- for (int i = adj_nub; i < n; ++i)
- {
- s_error = false;
- // the index i is the driving index and indexes i+1..n-1 are "dont care",
- // i.e. when we make changes to the system those x's will be zero and we
- // don't care what happens to those w's. in other words, we only consider
- // an (i+1)*(i+1) sub-problem of A*x=b+w.
-
- // if we've hit the first friction index, we have to compute the lo and
- // hi values based on the values of x already computed. we have been
- // permuting the indexes, so the values stored in the findex vector are
- // no longer valid. thus we have to temporarily unpermute the x vector.
- // for the purposes of this computation, 0*infinity = 0 ... so if the
- // contact constraint's normal force is 0, there should be no tangential
- // force applied.
-
- if (!hit_first_friction_index && findex && findex[i] >= 0)
- {
- // un-permute x into delta_w, which is not being used at the moment
- for (int j = 0; j < n; ++j) scratchMem.delta_w[scratchMem.p[j]] = x[j];
-
- // set lo and hi values
- for (int k = i; k < n; ++k)
- {
- btScalar wfk = scratchMem.delta_w[findex[k]];
- if (wfk == 0)
- {
- hi[k] = 0;
- lo[k] = 0;
- }
- else
- {
- hi[k] = btFabs(hi[k] * wfk);
- lo[k] = -hi[k];
- }
- }
- hit_first_friction_index = true;
- }
-
- // thus far we have not even been computing the w values for indexes
- // greater than i, so compute w[i] now.
- w[i] = lcp.AiC_times_qC(i, x) + lcp.AiN_times_qN(i, x) - b[i];
-
- // if lo=hi=0 (which can happen for tangential friction when normals are
- // 0) then the index will be assigned to set N with some state. however,
- // set C's line has zero size, so the index will always remain in set N.
- // with the "normal" switching logic, if w changed sign then the index
- // would have to switch to set C and then back to set N with an inverted
- // state. this is pointless, and also computationally expensive. to
- // prevent this from happening, we use the rule that indexes with lo=hi=0
- // will never be checked for set changes. this means that the state for
- // these indexes may be incorrect, but that doesn't matter.
-
- // see if x(i),w(i) is in a valid region
- if (lo[i] == 0 && w[i] >= 0)
- {
- lcp.transfer_i_to_N(i);
- scratchMem.state[i] = false;
- }
- else if (hi[i] == 0 && w[i] <= 0)
- {
- lcp.transfer_i_to_N(i);
- scratchMem.state[i] = true;
- }
- else if (w[i] == 0)
- {
- // this is a degenerate case. by the time we get to this test we know
- // that lo != 0, which means that lo < 0 as lo is not allowed to be +ve,
- // and similarly that hi > 0. this means that the line segment
- // corresponding to set C is at least finite in extent, and we are on it.
- // NOTE: we must call lcp.solve1() before lcp.transfer_i_to_C()
- lcp.solve1(&scratchMem.delta_x[0], i, 0, 1);
-
- lcp.transfer_i_to_C(i);
- }
- else
- {
- // we must push x(i) and w(i)
- for (;;)
- {
- int dir;
- btScalar dirf;
- // find direction to push on x(i)
- if (w[i] <= 0)
- {
- dir = 1;
- dirf = btScalar(1.0);
- }
- else
- {
- dir = -1;
- dirf = btScalar(-1.0);
- }
-
- // compute: delta_x(C) = -dir*A(C,C)\A(C,i)
- lcp.solve1(&scratchMem.delta_x[0], i, dir);
-
- // note that delta_x[i] = dirf, but we wont bother to set it
-
- // compute: delta_w = A*delta_x ... note we only care about
- // delta_w(N) and delta_w(i), the rest is ignored
- lcp.pN_equals_ANC_times_qC(&scratchMem.delta_w[0], &scratchMem.delta_x[0]);
- lcp.pN_plusequals_ANi(&scratchMem.delta_w[0], i, dir);
- scratchMem.delta_w[i] = lcp.AiC_times_qC(i, &scratchMem.delta_x[0]) + lcp.Aii(i) * dirf;
-
- // find largest step we can take (size=s), either to drive x(i),w(i)
- // to the valid LCP region or to drive an already-valid variable
- // outside the valid region.
-
- int cmd = 1; // index switching command
- int si = 0; // si = index to switch if cmd>3
- btScalar s = -w[i] / scratchMem.delta_w[i];
- if (dir > 0)
- {
- if (hi[i] < BT_INFINITY)
- {
- btScalar s2 = (hi[i] - x[i]) * dirf; // was (hi[i]-x[i])/dirf // step to x(i)=hi(i)
- if (s2 < s)
- {
- s = s2;
- cmd = 3;
- }
- }
- }
- else
- {
- if (lo[i] > -BT_INFINITY)
- {
- btScalar s2 = (lo[i] - x[i]) * dirf; // was (lo[i]-x[i])/dirf // step to x(i)=lo(i)
- if (s2 < s)
- {
- s = s2;
- cmd = 2;
- }
- }
- }
-
- {
- const int numN = lcp.numN();
- for (int k = 0; k < numN; ++k)
- {
- const int indexN_k = lcp.indexN(k);
- if (!scratchMem.state[indexN_k] ? scratchMem.delta_w[indexN_k] < 0 : scratchMem.delta_w[indexN_k] > 0)
- {
- // don't bother checking if lo=hi=0
- if (lo[indexN_k] == 0 && hi[indexN_k] == 0) continue;
- btScalar s2 = -w[indexN_k] / scratchMem.delta_w[indexN_k];
- if (s2 < s)
- {
- s = s2;
- cmd = 4;
- si = indexN_k;
- }
- }
- }
- }
-
- {
- const int numC = lcp.numC();
- for (int k = adj_nub; k < numC; ++k)
- {
- const int indexC_k = lcp.indexC(k);
- if (scratchMem.delta_x[indexC_k] < 0 && lo[indexC_k] > -BT_INFINITY)
- {
- btScalar s2 = (lo[indexC_k] - x[indexC_k]) / scratchMem.delta_x[indexC_k];
- if (s2 < s)
- {
- s = s2;
- cmd = 5;
- si = indexC_k;
- }
- }
- if (scratchMem.delta_x[indexC_k] > 0 && hi[indexC_k] < BT_INFINITY)
- {
- btScalar s2 = (hi[indexC_k] - x[indexC_k]) / scratchMem.delta_x[indexC_k];
- if (s2 < s)
- {
- s = s2;
- cmd = 6;
- si = indexC_k;
- }
- }
- }
- }
-
- //static char* cmdstring[8] = {0,"->C","->NL","->NH","N->C",
- // "C->NL","C->NH"};
- //printf ("cmd=%d (%s), si=%d\n",cmd,cmdstring[cmd],(cmd>3) ? si : i);
-
- // if s <= 0 then we've got a problem. if we just keep going then
- // we're going to get stuck in an infinite loop. instead, just cross
- // our fingers and exit with the current solution.
- if (s <= btScalar(0.0))
- {
- // printf("LCP internal error, s <= 0 (s=%.4e)",(double)s);
- if (i < n)
- {
- btSetZero(x + i, n - i);
- btSetZero(w + i, n - i);
- }
- s_error = true;
- break;
- }
-
- // apply x = x + s * delta_x
- lcp.pC_plusequals_s_times_qC(x, s, &scratchMem.delta_x[0]);
- x[i] += s * dirf;
-
- // apply w = w + s * delta_w
- lcp.pN_plusequals_s_times_qN(w, s, &scratchMem.delta_w[0]);
- w[i] += s * scratchMem.delta_w[i];
-
- // void *tmpbuf;
- // switch indexes between sets if necessary
- switch (cmd)
- {
- case 1: // done
- w[i] = 0;
- lcp.transfer_i_to_C(i);
- break;
- case 2: // done
- x[i] = lo[i];
- scratchMem.state[i] = false;
- lcp.transfer_i_to_N(i);
- break;
- case 3: // done
- x[i] = hi[i];
- scratchMem.state[i] = true;
- lcp.transfer_i_to_N(i);
- break;
- case 4: // keep going
- w[si] = 0;
- lcp.transfer_i_from_N_to_C(si);
- break;
- case 5: // keep going
- x[si] = lo[si];
- scratchMem.state[si] = false;
- lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
- break;
- case 6: // keep going
- x[si] = hi[si];
- scratchMem.state[si] = true;
- lcp.transfer_i_from_C_to_N(si, scratchMem.m_scratch);
- break;
- }
-
- if (cmd <= 3) break;
- } // for (;;)
- } // else
-
- if (s_error)
- {
- break;
- }
- } // for (int i=adj_nub; i<n; ++i)
-
- lcp.unpermute();
-
- return !s_error;
-}
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h
deleted file mode 100644
index 8d9b2a13e9..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigLCP.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*************************************************************************
- * *
- * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
- * All rights reserved. Email: russ@q12.org Web: www.q12.org *
- * *
- * This library is free software; you can redistribute it and/or *
- * modify it under the terms of *
- * The BSD-style license that is included with this library in *
- * the file LICENSE-BSD.TXT. *
- * *
- * This library is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
- * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
- * *
- *************************************************************************/
-
-/*
-
-given (A,b,lo,hi), solve the LCP problem: A*x = b+w, where each x(i),w(i)
-satisfies one of
- (1) x = lo, w >= 0
- (2) x = hi, w <= 0
- (3) lo < x < hi, w = 0
-A is a matrix of dimension n*n, everything else is a vector of size n*1.
-lo and hi can be +/- dInfinity as needed. the first `nub' variables are
-unbounded, i.e. hi and lo are assumed to be +/- dInfinity.
-
-we restrict lo(i) <= 0 and hi(i) >= 0.
-
-the original data (A,b) may be modified by this function.
-
-if the `findex' (friction index) parameter is nonzero, it points to an array
-of index values. in this case constraints that have findex[i] >= 0 are
-special. all non-special constraints are solved for, then the lo and hi values
-for the special constraints are set:
- hi[i] = abs( hi[i] * x[findex[i]] )
- lo[i] = -hi[i]
-and the solution continues. this mechanism allows a friction approximation
-to be implemented. the first `nub' variables are assumed to have findex < 0.
-
-*/
-
-#ifndef _BT_LCP_H_
-#define _BT_LCP_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btAlignedObjectArray.h"
-
-struct btDantzigScratchMemory
-{
- btAlignedObjectArray<btScalar> m_scratch;
- btAlignedObjectArray<btScalar> L;
- btAlignedObjectArray<btScalar> d;
- btAlignedObjectArray<btScalar> delta_w;
- btAlignedObjectArray<btScalar> delta_x;
- btAlignedObjectArray<btScalar> Dell;
- btAlignedObjectArray<btScalar> ell;
- btAlignedObjectArray<btScalar *> Arows;
- btAlignedObjectArray<int> p;
- btAlignedObjectArray<int> C;
- btAlignedObjectArray<bool> state;
-};
-
-//return false if solving failed
-bool btSolveDantzigLCP(int n, btScalar *A, btScalar *x, btScalar *b, btScalar *w,
- int nub, btScalar *lo, btScalar *hi, int *findex, btDantzigScratchMemory &scratch);
-
-#endif //_BT_LCP_H_
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h
deleted file mode 100644
index 1f669751ce..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btDantzigSolver.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_DANTZIG_SOLVER_H
-#define BT_DANTZIG_SOLVER_H
-
-#include "btMLCPSolverInterface.h"
-#include "btDantzigLCP.h"
-
-class btDantzigSolver : public btMLCPSolverInterface
-{
-protected:
- btScalar m_acceptableUpperLimitSolution;
-
- btAlignedObjectArray<char> m_tempBuffer;
-
- btAlignedObjectArray<btScalar> m_A;
- btAlignedObjectArray<btScalar> m_b;
- btAlignedObjectArray<btScalar> m_x;
- btAlignedObjectArray<btScalar> m_lo;
- btAlignedObjectArray<btScalar> m_hi;
- btAlignedObjectArray<int> m_dependencies;
- btDantzigScratchMemory m_scratchMemory;
-
-public:
- btDantzigSolver()
- : m_acceptableUpperLimitSolution(btScalar(1000))
- {
- }
-
- virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
- {
- bool result = true;
- int n = b.rows();
- if (n)
- {
- int nub = 0;
- btAlignedObjectArray<btScalar> ww;
- ww.resize(n);
-
- const btScalar* Aptr = A.getBufferPointer();
- m_A.resize(n * n);
- for (int i = 0; i < n * n; i++)
- {
- m_A[i] = Aptr[i];
- }
-
- m_b.resize(n);
- m_x.resize(n);
- m_lo.resize(n);
- m_hi.resize(n);
- m_dependencies.resize(n);
- for (int i = 0; i < n; i++)
- {
- m_lo[i] = lo[i];
- m_hi[i] = hi[i];
- m_b[i] = b[i];
- m_x[i] = x[i];
- m_dependencies[i] = limitDependency[i];
- }
-
- result = btSolveDantzigLCP(n, &m_A[0], &m_x[0], &m_b[0], &ww[0], nub, &m_lo[0], &m_hi[0], &m_dependencies[0], m_scratchMemory);
- if (!result)
- return result;
-
- // printf("numAllocas = %d\n",numAllocas);
- for (int i = 0; i < n; i++)
- {
- volatile btScalar xx = m_x[i];
- if (xx != m_x[i])
- return false;
- if (x[i] >= m_acceptableUpperLimitSolution)
- {
- return false;
- }
-
- if (x[i] <= -m_acceptableUpperLimitSolution)
- {
- return false;
- }
- }
-
- for (int i = 0; i < n; i++)
- {
- x[i] = m_x[i];
- }
- }
-
- return result;
- }
-};
-
-#endif //BT_DANTZIG_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
deleted file mode 100644
index 954ffaed75..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-/* Copyright (C) 2004-2013 MBSim Development Team
-
-Code was converted for the Bullet Continuous Collision Detection and Physics Library
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//The original version is here
-//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
-//This file is re-distributed under the ZLib license, with permission of the original author
-//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
-//STL/std::vector replaced by btAlignedObjectArray
-
-#include "btLemkeAlgorithm.h"
-
-#undef BT_DEBUG_OSTREAM
-#ifdef BT_DEBUG_OSTREAM
-using namespace std;
-#endif //BT_DEBUG_OSTREAM
-
-btScalar btMachEps()
-{
- static bool calculated = false;
- static btScalar machEps = btScalar(1.);
- if (!calculated)
- {
- do
- {
- machEps /= btScalar(2.0);
- // If next epsilon yields 1, then break, because current
- // epsilon is the machine epsilon.
- } while ((btScalar)(1.0 + (machEps / btScalar(2.0))) != btScalar(1.0));
- // printf( "\nCalculated Machine epsilon: %G\n", machEps );
- calculated = true;
- }
- return machEps;
-}
-
-btScalar btEpsRoot()
-{
- static btScalar epsroot = 0.;
- static bool alreadyCalculated = false;
-
- if (!alreadyCalculated)
- {
- epsroot = btSqrt(btMachEps());
- alreadyCalculated = true;
- }
- return epsroot;
-}
-
-btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
-{
- steps = 0;
-
- int dim = m_q.size();
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 1)
- {
- cout << "Dimension = " << dim << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- btVectorXu solutionVector(2 * dim);
- solutionVector.setZero();
-
- //, INIT, 0.);
-
- btMatrixXu ident(dim, dim);
- ident.setIdentity();
-#ifdef BT_DEBUG_OSTREAM
- cout << m_M << std::endl;
-#endif
-
- btMatrixXu mNeg = m_M.negative();
-
- btMatrixXu A(dim, 2 * dim + 2);
- //
- A.setSubMatrix(0, 0, dim - 1, dim - 1, ident);
- A.setSubMatrix(0, dim, dim - 1, 2 * dim - 1, mNeg);
- A.setSubMatrix(0, 2 * dim, dim - 1, 2 * dim, -1.f);
- A.setSubMatrix(0, 2 * dim + 1, dim - 1, 2 * dim + 1, m_q);
-
-#ifdef BT_DEBUG_OSTREAM
- cout << A << std::endl;
-#endif //BT_DEBUG_OSTREAM
-
- // btVectorXu q_;
- // q_ >> A(0, 2 * dim + 1, dim - 1, 2 * dim + 1);
-
- btAlignedObjectArray<int> basis;
- //At first, all w-values are in the basis
- for (int i = 0; i < dim; i++)
- basis.push_back(i);
-
- int pivotRowIndex = -1;
- btScalar minValue = 1e30f;
- bool greaterZero = true;
- for (int i = 0; i < dim; i++)
- {
- btScalar v = A(i, 2 * dim + 1);
- if (v < minValue)
- {
- minValue = v;
- pivotRowIndex = i;
- }
- if (v < 0)
- greaterZero = false;
- }
-
- // int pivotRowIndex = q_.minIndex();//minIndex(q_); // first row is that with lowest q-value
- int z0Row = pivotRowIndex; // remember the col of z0 for ending algorithm afterwards
- int pivotColIndex = 2 * dim; // first col is that of z0
-
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 3)
- {
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- cout << "Basis: ";
- for (int i = 0; i < basis.size(); i++)
- cout << basis[i] << " ";
- cout << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- if (!greaterZero)
- {
- if (maxloops == 0)
- {
- maxloops = 100;
- // maxloops = UINT_MAX; //TODO: not a really nice way, problem is: maxloops should be 2^dim (=1<<dim), but this could exceed UINT_MAX and thus the result would be 0 and therefore the lemke algorithm wouldn't start but probably would find a solution within less then UINT_MAX steps. Therefore this constant is used as a upper border right now...
- }
-
- /*start looping*/
- for (steps = 0; steps < maxloops; steps++)
- {
- GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 3)
- {
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- cout << "Basis: ";
- for (int i = 0; i < basis.size(); i++)
- cout << basis[i] << " ";
- cout << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- int pivotColIndexOld = pivotColIndex;
-
- /*find new column index */
- if (basis[pivotRowIndex] < dim) //if a w-value left the basis get in the correspondent z-value
- pivotColIndex = basis[pivotRowIndex] + dim;
- else
- //else do it the other way round and get in the corresponding w-value
- pivotColIndex = basis[pivotRowIndex] - dim;
-
- /*the column becomes part of the basis*/
- basis[pivotRowIndex] = pivotColIndexOld;
-
- pivotRowIndex = findLexicographicMinimum(A, pivotColIndex);
-
- if (z0Row == pivotRowIndex)
- { //if z0 leaves the basis the solution is found --> one last elimination step is necessary
- GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
- basis[pivotRowIndex] = pivotColIndex; //update basis
- break;
- }
- }
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 1)
- {
- cout << "Number of loops: " << steps << endl;
- cout << "Number of maximal loops: " << maxloops << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- if (!validBasis(basis))
- {
- info = -1;
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 1)
- cerr << "Lemke-Algorithm ended with Ray-Termination (no valid solution)." << endl;
-#endif //BT_DEBUG_OSTREAM
-
- return solutionVector;
- }
- }
-#ifdef BT_DEBUG_OSTREAM
- if (DEBUGLEVEL >= 2)
- {
- // cout << "A: " << A << endl;
- cout << "pivotRowIndex " << pivotRowIndex << endl;
- cout << "pivotColIndex " << pivotColIndex << endl;
- }
-#endif //BT_DEBUG_OSTREAM
-
- for (int i = 0; i < basis.size(); i++)
- {
- solutionVector[basis[i]] = A(i, 2 * dim + 1); //q_[i];
- }
-
- info = 0;
-
- return solutionVector;
-}
-
-int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex)
-{
- int RowIndex = 0;
- int dim = A.rows();
- btAlignedObjectArray<btVectorXu> Rows;
- for (int row = 0; row < dim; row++)
- {
- btVectorXu vec(dim + 1);
- vec.setZero(); //, INIT, 0.)
- Rows.push_back(vec);
- btScalar a = A(row, pivotColIndex);
- if (a > 0)
- {
- Rows[row][0] = A(row, 2 * dim + 1) / a;
- Rows[row][1] = A(row, 2 * dim) / a;
- for (int j = 2; j < dim + 1; j++)
- Rows[row][j] = A(row, j - 1) / a;
-
-#ifdef BT_DEBUG_OSTREAM
- // if (DEBUGLEVEL) {
- // cout << "Rows(" << row << ") = " << Rows[row] << endl;
- // }
-#endif
- }
- }
-
- for (int i = 0; i < Rows.size(); i++)
- {
- if (Rows[i].nrm2() > 0.)
- {
- int j = 0;
- for (; j < Rows.size(); j++)
- {
- if (i != j)
- {
- if (Rows[j].nrm2() > 0.)
- {
- btVectorXu test(dim + 1);
- for (int ii = 0; ii < dim + 1; ii++)
- {
- test[ii] = Rows[j][ii] - Rows[i][ii];
- }
-
- //=Rows[j] - Rows[i]
- if (!LexicographicPositive(test))
- break;
- }
- }
- }
-
- if (j == Rows.size())
- {
- RowIndex += i;
- break;
- }
- }
- }
-
- return RowIndex;
-}
-
-bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu& v)
-{
- int i = 0;
- // if (DEBUGLEVEL)
- // cout << "v " << v << endl;
-
- while (i < v.size() - 1 && fabs(v[i]) < btMachEps())
- i++;
- if (v[i] > 0)
- return true;
-
- return false;
-}
-
-void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)
-{
- btScalar a = -1 / A(pivotRowIndex, pivotColumnIndex);
-#ifdef BT_DEBUG_OSTREAM
- cout << A << std::endl;
-#endif
-
- for (int i = 0; i < A.rows(); i++)
- {
- if (i != pivotRowIndex)
- {
- for (int j = 0; j < A.cols(); j++)
- {
- if (j != pivotColumnIndex)
- {
- btScalar v = A(i, j);
- v += A(pivotRowIndex, j) * A(i, pivotColumnIndex) * a;
- A.setElem(i, j, v);
- }
- }
- }
- }
-
-#ifdef BT_DEBUG_OSTREAM
- cout << A << std::endl;
-#endif //BT_DEBUG_OSTREAM
- for (int i = 0; i < A.cols(); i++)
- {
- A.mulElem(pivotRowIndex, i, -a);
- }
-#ifdef BT_DEBUG_OSTREAM
- cout << A << std::endl;
-#endif //#ifdef BT_DEBUG_OSTREAM
-
- for (int i = 0; i < A.rows(); i++)
- {
- if (i != pivotRowIndex)
- {
- A.setElem(i, pivotColumnIndex, 0);
- }
- }
-#ifdef BT_DEBUG_OSTREAM
- cout << A << std::endl;
-#endif //#ifdef BT_DEBUG_OSTREAM
-}
-
-bool btLemkeAlgorithm::greaterZero(const btVectorXu& vector)
-{
- bool isGreater = true;
- for (int i = 0; i < vector.size(); i++)
- {
- if (vector[i] < 0)
- {
- isGreater = false;
- break;
- }
- }
-
- return isGreater;
-}
-
-bool btLemkeAlgorithm::validBasis(const btAlignedObjectArray<int>& basis)
-{
- bool isValid = true;
- for (int i = 0; i < basis.size(); i++)
- {
- if (basis[i] >= basis.size() * 2)
- { //then z0 is in the base
- isValid = false;
- break;
- }
- }
-
- return isValid;
-}
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
deleted file mode 100644
index 3c6bf72a23..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeAlgorithm.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright (C) 2004-2013 MBSim Development Team
-
-Code was converted for the Bullet Continuous Collision Detection and Physics Library
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-//The original version is here
-//https://code.google.com/p/mbsim-env/source/browse/trunk/kernel/mbsim/numerics/linear_complementarity_problem/lemke_algorithm.cc
-//This file is re-distributed under the ZLib license, with permission of the original author (Kilian Grundl)
-//Math library was replaced from fmatvec to a the file src/LinearMath/btMatrixX.h
-//STL/std::vector replaced by btAlignedObjectArray
-
-#ifndef BT_NUMERICS_LEMKE_ALGORITHM_H_
-#define BT_NUMERICS_LEMKE_ALGORITHM_H_
-
-#include "LinearMath/btMatrixX.h"
-
-#include <vector> //todo: replace by btAlignedObjectArray
-
-class btLemkeAlgorithm
-{
-public:
- btLemkeAlgorithm(const btMatrixXu& M_, const btVectorXu& q_, const int& DEBUGLEVEL_ = 0) : DEBUGLEVEL(DEBUGLEVEL_)
- {
- setSystem(M_, q_);
- }
-
- /* GETTER / SETTER */
- /**
- * \brief return info of solution process
- */
- int getInfo()
- {
- return info;
- }
-
- /**
- * \brief get the number of steps until the solution was found
- */
- int getSteps(void)
- {
- return steps;
- }
-
- /**
- * \brief set system with Matrix M and vector q
- */
- void setSystem(const btMatrixXu& M_, const btVectorXu& q_)
- {
- m_M = M_;
- m_q = q_;
- }
- /***************************************************/
-
- /**
- * \brief solve algorithm adapted from : Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd)
- */
- btVectorXu solve(unsigned int maxloops = 0);
-
- virtual ~btLemkeAlgorithm()
- {
- }
-
-protected:
- int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex);
- bool LexicographicPositive(const btVectorXu& v);
- void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
- bool greaterZero(const btVectorXu& vector);
- bool validBasis(const btAlignedObjectArray<int>& basis);
-
- btMatrixXu m_M;
- btVectorXu m_q;
-
- /**
- * \brief number of steps until the Lemke algorithm found a solution
- */
- unsigned int steps;
-
- /**
- * \brief define level of debug output
- */
- int DEBUGLEVEL;
-
- /**
- * \brief did the algorithm find a solution
- *
- * -1 : not successful
- * 0 : successful
- */
- int info;
-};
-
-#endif /* BT_NUMERICS_LEMKE_ALGORITHM_H_ */
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
deleted file mode 100644
index f18c4ea41b..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btLemkeSolver.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_LEMKE_SOLVER_H
-#define BT_LEMKE_SOLVER_H
-
-#include "btMLCPSolverInterface.h"
-#include "btLemkeAlgorithm.h"
-
-///The btLemkeSolver is based on "Fast Implementation of Lemke’s Algorithm for Rigid Body Contact Simulation (John E. Lloyd) "
-///It is a slower but more accurate solver. Increase the m_maxLoops for better convergence, at the cost of more CPU time.
-///The original implementation of the btLemkeAlgorithm was done by Kilian Grundl from the MBSim team
-class btLemkeSolver : public btMLCPSolverInterface
-{
-protected:
-public:
- btScalar m_maxValue;
- int m_debugLevel;
- int m_maxLoops;
- bool m_useLoHighBounds;
-
- btLemkeSolver()
- : m_maxValue(100000),
- m_debugLevel(0),
- m_maxLoops(1000),
- m_useLoHighBounds(true)
- {
- }
- virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
- {
- if (m_useLoHighBounds)
- {
- BT_PROFILE("btLemkeSolver::solveMLCP");
- int n = A.rows();
- if (0 == n)
- return true;
-
- bool fail = false;
-
- btVectorXu solution(n);
- btVectorXu q1;
- q1.resize(n);
- for (int row = 0; row < n; row++)
- {
- q1[row] = -b[row];
- }
-
- // cout << "A" << endl;
- // cout << A << endl;
-
- /////////////////////////////////////
-
- //slow matrix inversion, replace with LU decomposition
- btMatrixXu A1;
- btMatrixXu B(n, n);
- {
- //BT_PROFILE("inverse(slow)");
- A1.resize(A.rows(), A.cols());
- for (int row = 0; row < A.rows(); row++)
- {
- for (int col = 0; col < A.cols(); col++)
- {
- A1.setElem(row, col, A(row, col));
- }
- }
-
- btMatrixXu matrix;
- matrix.resize(n, 2 * n);
- for (int row = 0; row < n; row++)
- {
- for (int col = 0; col < n; col++)
- {
- matrix.setElem(row, col, A1(row, col));
- }
- }
-
- btScalar ratio, a;
- int i, j, k;
- for (i = 0; i < n; i++)
- {
- for (j = n; j < 2 * n; j++)
- {
- if (i == (j - n))
- matrix.setElem(i, j, 1.0);
- else
- matrix.setElem(i, j, 0.0);
- }
- }
- for (i = 0; i < n; i++)
- {
- for (j = 0; j < n; j++)
- {
- if (i != j)
- {
- btScalar v = matrix(i, i);
- if (btFuzzyZero(v))
- {
- a = 0.000001f;
- }
- ratio = matrix(j, i) / matrix(i, i);
- for (k = 0; k < 2 * n; k++)
- {
- matrix.addElem(j, k, -ratio * matrix(i, k));
- }
- }
- }
- }
- for (i = 0; i < n; i++)
- {
- a = matrix(i, i);
- if (btFuzzyZero(a))
- {
- a = 0.000001f;
- }
- btScalar invA = 1.f / a;
- for (j = 0; j < 2 * n; j++)
- {
- matrix.mulElem(i, j, invA);
- }
- }
-
- for (int row = 0; row < n; row++)
- {
- for (int col = 0; col < n; col++)
- {
- B.setElem(row, col, matrix(row, n + col));
- }
- }
- }
-
- btMatrixXu b1(n, 1);
-
- btMatrixXu M(n * 2, n * 2);
- for (int row = 0; row < n; row++)
- {
- b1.setElem(row, 0, -b[row]);
- for (int col = 0; col < n; col++)
- {
- btScalar v = B(row, col);
- M.setElem(row, col, v);
- M.setElem(n + row, n + col, v);
- M.setElem(n + row, col, -v);
- M.setElem(row, n + col, -v);
- }
- }
-
- btMatrixXu Bb1 = B * b1;
- // q = [ (-B*b1 - lo)' (hi + B*b1)' ]'
-
- btVectorXu qq;
- qq.resize(n * 2);
- for (int row = 0; row < n; row++)
- {
- qq[row] = -Bb1(row, 0) - lo[row];
- qq[n + row] = Bb1(row, 0) + hi[row];
- }
-
- btVectorXu z1;
-
- btMatrixXu y1;
- y1.resize(n, 1);
- btLemkeAlgorithm lemke(M, qq, m_debugLevel);
- {
- //BT_PROFILE("lemke.solve");
- lemke.setSystem(M, qq);
- z1 = lemke.solve(m_maxLoops);
- }
- for (int row = 0; row < n; row++)
- {
- y1.setElem(row, 0, z1[2 * n + row] - z1[3 * n + row]);
- }
- btMatrixXu y1_b1(n, 1);
- for (int i = 0; i < n; i++)
- {
- y1_b1.setElem(i, 0, y1(i, 0) - b1(i, 0));
- }
-
- btMatrixXu x1;
-
- x1 = B * (y1_b1);
-
- for (int row = 0; row < n; row++)
- {
- solution[row] = x1(row, 0); //n];
- }
-
- int errorIndexMax = -1;
- int errorIndexMin = -1;
- float errorValueMax = -1e30;
- float errorValueMin = 1e30;
-
- for (int i = 0; i < n; i++)
- {
- x[i] = solution[i];
- volatile btScalar check = x[i];
- if (x[i] != check)
- {
- //printf("Lemke result is #NAN\n");
- x.setZero();
- return false;
- }
-
- //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
- //we need to figure out why it happens, and fix it, or detect it properly)
- if (x[i] > m_maxValue)
- {
- if (x[i] > errorValueMax)
- {
- fail = true;
- errorIndexMax = i;
- errorValueMax = x[i];
- }
- ////printf("x[i] = %f,",x[i]);
- }
- if (x[i] < -m_maxValue)
- {
- if (x[i] < errorValueMin)
- {
- errorIndexMin = i;
- errorValueMin = x[i];
- fail = true;
- //printf("x[i] = %f,",x[i]);
- }
- }
- }
- if (fail)
- {
- int m_errorCountTimes = 0;
- if (errorIndexMin < 0)
- errorValueMin = 0.f;
- if (errorIndexMax < 0)
- errorValueMax = 0.f;
- m_errorCountTimes++;
- // printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin,errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
- for (int i = 0; i < n; i++)
- {
- x[i] = 0.f;
- }
- }
- return !fail;
- }
- else
-
- {
- int dimension = A.rows();
- if (0 == dimension)
- return true;
-
- // printf("================ solving using Lemke/Newton/Fixpoint\n");
-
- btVectorXu q;
- q.resize(dimension);
- for (int row = 0; row < dimension; row++)
- {
- q[row] = -b[row];
- }
-
- btLemkeAlgorithm lemke(A, q, m_debugLevel);
-
- lemke.setSystem(A, q);
-
- btVectorXu solution = lemke.solve(m_maxLoops);
-
- //check solution
-
- bool fail = false;
- int errorIndexMax = -1;
- int errorIndexMin = -1;
- float errorValueMax = -1e30;
- float errorValueMin = 1e30;
-
- for (int i = 0; i < dimension; i++)
- {
- x[i] = solution[i + dimension];
- volatile btScalar check = x[i];
- if (x[i] != check)
- {
- x.setZero();
- return false;
- }
-
- //this is some hack/safety mechanism, to discard invalid solutions from the Lemke solver
- //we need to figure out why it happens, and fix it, or detect it properly)
- if (x[i] > m_maxValue)
- {
- if (x[i] > errorValueMax)
- {
- fail = true;
- errorIndexMax = i;
- errorValueMax = x[i];
- }
- ////printf("x[i] = %f,",x[i]);
- }
- if (x[i] < -m_maxValue)
- {
- if (x[i] < errorValueMin)
- {
- errorIndexMin = i;
- errorValueMin = x[i];
- fail = true;
- //printf("x[i] = %f,",x[i]);
- }
- }
- }
- if (fail)
- {
- static int errorCountTimes = 0;
- if (errorIndexMin < 0)
- errorValueMin = 0.f;
- if (errorIndexMax < 0)
- errorValueMax = 0.f;
- printf("Error (x[%d] = %f, x[%d] = %f), resetting %d times\n", errorIndexMin, errorValueMin, errorIndexMax, errorValueMax, errorCountTimes++);
- for (int i = 0; i < dimension; i++)
- {
- x[i] = 0.f;
- }
- }
-
- return !fail;
- }
- return true;
- }
-};
-
-#endif //BT_LEMKE_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
deleted file mode 100644
index ed4e0b686d..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.cpp
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#include "btMLCPSolver.h"
-#include "LinearMath/btMatrixX.h"
-#include "LinearMath/btQuickprof.h"
-#include "btSolveProjectedGaussSeidel.h"
-
-btMLCPSolver::btMLCPSolver(btMLCPSolverInterface* solver)
- : m_solver(solver),
- m_fallback(0)
-{
-}
-
-btMLCPSolver::~btMLCPSolver()
-{
-}
-
-bool gUseMatrixMultiply = false;
-bool interleaveContactAndFriction = false;
-
-btScalar btMLCPSolver::solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodiesUnUsed, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlySetup(bodies, numBodiesUnUsed, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- {
- BT_PROFILE("gather constraint data");
-
- int numFrictionPerContact = m_tmpSolverContactConstraintPool.size() == m_tmpSolverContactFrictionConstraintPool.size() ? 1 : 2;
-
- // int numBodies = m_tmpSolverBodyPool.size();
- m_allConstraintPtrArray.resize(0);
- m_limitDependencies.resize(m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
- btAssert(m_limitDependencies.size() == m_tmpSolverNonContactConstraintPool.size() + m_tmpSolverContactConstraintPool.size() + m_tmpSolverContactFrictionConstraintPool.size());
- // printf("m_limitDependencies.size() = %d\n",m_limitDependencies.size());
-
- int dindex = 0;
- for (int i = 0; i < m_tmpSolverNonContactConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverNonContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- }
-
- ///The btSequentialImpulseConstraintSolver moves all friction constraints at the very end, we can also interleave them instead
-
- int firstContactConstraintOffset = dindex;
-
- if (interleaveContactAndFriction)
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact]);
- int findex = (m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact].m_frictionIndex * (1 + numFrictionPerContact));
- m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
- if (numFrictionPerContact == 2)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i * numFrictionPerContact + 1]);
- m_limitDependencies[dindex++] = findex + firstContactConstraintOffset;
- }
- }
- }
- else
- {
- for (int i = 0; i < m_tmpSolverContactConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactConstraintPool[i]);
- m_limitDependencies[dindex++] = -1;
- }
- for (int i = 0; i < m_tmpSolverContactFrictionConstraintPool.size(); i++)
- {
- m_allConstraintPtrArray.push_back(&m_tmpSolverContactFrictionConstraintPool[i]);
- m_limitDependencies[dindex++] = m_tmpSolverContactFrictionConstraintPool[i].m_frictionIndex + firstContactConstraintOffset;
- }
- }
-
- if (!m_allConstraintPtrArray.size())
- {
- m_A.resize(0, 0);
- m_b.resize(0);
- m_x.resize(0);
- m_lo.resize(0);
- m_hi.resize(0);
- return 0.f;
- }
- }
-
- if (gUseMatrixMultiply)
- {
- BT_PROFILE("createMLCP");
- createMLCP(infoGlobal);
- }
- else
- {
- BT_PROFILE("createMLCPFast");
- createMLCPFast(infoGlobal);
- }
-
- return 0.f;
-}
-
-bool btMLCPSolver::solveMLCP(const btContactSolverInfo& infoGlobal)
-{
- bool result = true;
-
- if (m_A.rows() == 0)
- return true;
-
- //if using split impulse, we solve 2 separate (M)LCPs
- if (infoGlobal.m_splitImpulse)
- {
- btMatrixXu Acopy = m_A;
- btAlignedObjectArray<int> limitDependenciesCopy = m_limitDependencies;
- // printf("solve first LCP\n");
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
- if (result)
- result = m_solver->solveMLCP(Acopy, m_bSplit, m_xSplit, m_lo, m_hi, limitDependenciesCopy, infoGlobal.m_numIterations);
- }
- else
- {
- result = m_solver->solveMLCP(m_A, m_b, m_x, m_lo, m_hi, m_limitDependencies, infoGlobal.m_numIterations);
- }
- return result;
-}
-
-struct btJointNode
-{
- int jointIndex; // pointer to enclosing dxJoint object
- int otherBodyIndex; // *other* body this joint is connected to
- int nextJointNodeIndex; //-1 for null
- int constraintRowIndex;
-};
-
-void btMLCPSolver::createMLCPFast(const btContactSolverInfo& infoGlobal)
-{
- int numContactRows = interleaveContactAndFriction ? 3 : 1;
-
- int numConstraintRows = m_allConstraintPtrArray.size();
- int n = numConstraintRows;
- {
- BT_PROFILE("init b (rhs)");
- m_b.resize(numConstraintRows);
- m_bSplit.resize(numConstraintRows);
- m_b.setZero();
- m_bSplit.setZero();
- for (int i = 0; i < numConstraintRows; i++)
- {
- btScalar jacDiag = m_allConstraintPtrArray[i]->m_jacDiagABInv;
- if (!btFuzzyZero(jacDiag))
- {
- btScalar rhs = m_allConstraintPtrArray[i]->m_rhs;
- btScalar rhsPenetration = m_allConstraintPtrArray[i]->m_rhsPenetration;
- m_b[i] = rhs / jacDiag;
- m_bSplit[i] = rhsPenetration / jacDiag;
- }
- }
- }
-
- // btScalar* w = 0;
- // int nub = 0;
-
- m_lo.resize(numConstraintRows);
- m_hi.resize(numConstraintRows);
-
- {
- BT_PROFILE("init lo/ho");
-
- for (int i = 0; i < numConstraintRows; i++)
- {
- if (0) //m_limitDependencies[i]>=0)
- {
- m_lo[i] = -BT_INFINITY;
- m_hi[i] = BT_INFINITY;
- }
- else
- {
- m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
- m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
- }
- }
- }
-
- //
- int m = m_allConstraintPtrArray.size();
-
- int numBodies = m_tmpSolverBodyPool.size();
- btAlignedObjectArray<int> bodyJointNodeArray;
- {
- BT_PROFILE("bodyJointNodeArray.resize");
- bodyJointNodeArray.resize(numBodies, -1);
- }
- btAlignedObjectArray<btJointNode> jointNodeArray;
- {
- BT_PROFILE("jointNodeArray.reserve");
- jointNodeArray.reserve(2 * m_allConstraintPtrArray.size());
- }
-
- btMatrixXu& J3 = m_scratchJ3;
- {
- BT_PROFILE("J3.resize");
- J3.resize(2 * m, 8);
- }
- btMatrixXu& JinvM3 = m_scratchJInvM3;
- {
- BT_PROFILE("JinvM3.resize/setZero");
-
- JinvM3.resize(2 * m, 8);
- JinvM3.setZero();
- J3.setZero();
- }
- int cur = 0;
- int rowOffset = 0;
- btAlignedObjectArray<int>& ofs = m_scratchOfs;
- {
- BT_PROFILE("ofs resize");
- ofs.resize(0);
- ofs.resizeNoInitialize(m_allConstraintPtrArray.size());
- }
- {
- BT_PROFILE("Compute J and JinvM");
- int c = 0;
-
- int numRows = 0;
-
- for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
- {
- ofs[c] = rowOffset;
- int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
- if (orgBodyA)
- {
- {
- int slotA = -1;
- //find free jointNode slot for sbA
- slotA = jointNodeArray.size();
- jointNodeArray.expand(); //NonInitializing();
- int prevSlot = bodyJointNodeArray[sbA];
- bodyJointNodeArray[sbA] = slotA;
- jointNodeArray[slotA].nextJointNodeIndex = prevSlot;
- jointNodeArray[slotA].jointIndex = c;
- jointNodeArray[slotA].constraintRowIndex = i;
- jointNodeArray[slotA].otherBodyIndex = orgBodyB ? sbB : -1;
- }
- for (int row = 0; row < numRows; row++, cur++)
- {
- btVector3 normalInvMass = m_allConstraintPtrArray[i + row]->m_contactNormal1 * orgBodyA->getInvMass();
- btVector3 relPosCrossNormalInvInertia = m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal * orgBodyA->getInvInertiaTensorWorld();
-
- for (int r = 0; r < 3; r++)
- {
- J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal1[r]);
- J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos1CrossNormal[r]);
- JinvM3.setElem(cur, r, normalInvMass[r]);
- JinvM3.setElem(cur, r + 4, relPosCrossNormalInvInertia[r]);
- }
- J3.setElem(cur, 3, 0);
- JinvM3.setElem(cur, 3, 0);
- J3.setElem(cur, 7, 0);
- JinvM3.setElem(cur, 7, 0);
- }
- }
- else
- {
- cur += numRows;
- }
- if (orgBodyB)
- {
- {
- int slotB = -1;
- //find free jointNode slot for sbA
- slotB = jointNodeArray.size();
- jointNodeArray.expand(); //NonInitializing();
- int prevSlot = bodyJointNodeArray[sbB];
- bodyJointNodeArray[sbB] = slotB;
- jointNodeArray[slotB].nextJointNodeIndex = prevSlot;
- jointNodeArray[slotB].jointIndex = c;
- jointNodeArray[slotB].otherBodyIndex = orgBodyA ? sbA : -1;
- jointNodeArray[slotB].constraintRowIndex = i;
- }
-
- for (int row = 0; row < numRows; row++, cur++)
- {
- btVector3 normalInvMassB = m_allConstraintPtrArray[i + row]->m_contactNormal2 * orgBodyB->getInvMass();
- btVector3 relPosInvInertiaB = m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal * orgBodyB->getInvInertiaTensorWorld();
-
- for (int r = 0; r < 3; r++)
- {
- J3.setElem(cur, r, m_allConstraintPtrArray[i + row]->m_contactNormal2[r]);
- J3.setElem(cur, r + 4, m_allConstraintPtrArray[i + row]->m_relpos2CrossNormal[r]);
- JinvM3.setElem(cur, r, normalInvMassB[r]);
- JinvM3.setElem(cur, r + 4, relPosInvInertiaB[r]);
- }
- J3.setElem(cur, 3, 0);
- JinvM3.setElem(cur, 3, 0);
- J3.setElem(cur, 7, 0);
- JinvM3.setElem(cur, 7, 0);
- }
- }
- else
- {
- cur += numRows;
- }
- rowOffset += numRows;
- }
- }
-
- //compute JinvM = J*invM.
- const btScalar* JinvM = JinvM3.getBufferPointer();
-
- const btScalar* Jptr = J3.getBufferPointer();
- {
- BT_PROFILE("m_A.resize");
- m_A.resize(n, n);
- }
-
- {
- BT_PROFILE("m_A.setZero");
- m_A.setZero();
- }
- int c = 0;
- {
- int numRows = 0;
- BT_PROFILE("Compute A");
- for (int i = 0; i < m_allConstraintPtrArray.size(); i += numRows, c++)
- {
- int row__ = ofs[c];
- int sbA = m_allConstraintPtrArray[i]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- numRows = i < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[c].m_numConstraintRows : numContactRows;
-
- const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
-
- {
- int startJointNodeA = bodyJointNodeArray[sbA];
- while (startJointNodeA >= 0)
- {
- int j0 = jointNodeArray[startJointNodeA].jointIndex;
- int cr0 = jointNodeArray[startJointNodeA].constraintRowIndex;
- if (j0 < c)
- {
- int numRowsOther = cr0 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j0].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cr0]->m_solverBodyIdB == sbA) ? 8 * numRowsOther : 0;
- //printf("%d joint i %d and j0: %d: ",count++,i,j0);
- m_A.multiplyAdd2_p8r(JinvMrow,
- Jptr + 2 * 8 * (size_t)ofs[j0] + ofsother, numRows, numRowsOther, row__, ofs[j0]);
- }
- startJointNodeA = jointNodeArray[startJointNodeA].nextJointNodeIndex;
- }
- }
-
- {
- int startJointNodeB = bodyJointNodeArray[sbB];
- while (startJointNodeB >= 0)
- {
- int j1 = jointNodeArray[startJointNodeB].jointIndex;
- int cj1 = jointNodeArray[startJointNodeB].constraintRowIndex;
-
- if (j1 < c)
- {
- int numRowsOther = cj1 < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[j1].m_numConstraintRows : numContactRows;
- size_t ofsother = (m_allConstraintPtrArray[cj1]->m_solverBodyIdB == sbB) ? 8 * numRowsOther : 0;
- m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)numRows,
- Jptr + 2 * 8 * (size_t)ofs[j1] + ofsother, numRows, numRowsOther, row__, ofs[j1]);
- }
- startJointNodeB = jointNodeArray[startJointNodeB].nextJointNodeIndex;
- }
- }
- }
-
- {
- BT_PROFILE("compute diagonal");
- // compute diagonal blocks of m_A
-
- int row__ = 0;
- int numJointRows = m_allConstraintPtrArray.size();
-
- int jj = 0;
- for (; row__ < numJointRows;)
- {
- //int sbA = m_allConstraintPtrArray[row__]->m_solverBodyIdA;
- int sbB = m_allConstraintPtrArray[row__]->m_solverBodyIdB;
- // btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- const unsigned int infom = row__ < m_tmpSolverNonContactConstraintPool.size() ? m_tmpConstraintSizesPool[jj].m_numConstraintRows : numContactRows;
-
- const btScalar* JinvMrow = JinvM + 2 * 8 * (size_t)row__;
- const btScalar* Jrow = Jptr + 2 * 8 * (size_t)row__;
- m_A.multiply2_p8r(JinvMrow, Jrow, infom, infom, row__, row__);
- if (orgBodyB)
- {
- m_A.multiplyAdd2_p8r(JinvMrow + 8 * (size_t)infom, Jrow + 8 * (size_t)infom, infom, infom, row__, row__);
- }
- row__ += infom;
- jj++;
- }
- }
- }
-
- if (1)
- {
- // add cfm to the diagonal of m_A
- for (int i = 0; i < m_A.rows(); ++i)
- {
- m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
- }
- }
-
- ///fill the upper triangle of the matrix, to make it symmetric
- {
- BT_PROFILE("fill the upper triangle ");
- m_A.copyLowerToUpperTriangle();
- }
-
- {
- BT_PROFILE("resize/init x");
- m_x.resize(numConstraintRows);
- m_xSplit.resize(numConstraintRows);
-
- if (infoGlobal.m_solverMode & SOLVER_USE_WARMSTARTING)
- {
- for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
- {
- const btSolverConstraint& c = *m_allConstraintPtrArray[i];
- m_x[i] = c.m_appliedImpulse;
- m_xSplit[i] = c.m_appliedPushImpulse;
- }
- }
- else
- {
- m_x.setZero();
- m_xSplit.setZero();
- }
- }
-}
-
-void btMLCPSolver::createMLCP(const btContactSolverInfo& infoGlobal)
-{
- int numBodies = this->m_tmpSolverBodyPool.size();
- int numConstraintRows = m_allConstraintPtrArray.size();
-
- m_b.resize(numConstraintRows);
- if (infoGlobal.m_splitImpulse)
- m_bSplit.resize(numConstraintRows);
-
- m_bSplit.setZero();
- m_b.setZero();
-
- for (int i = 0; i < numConstraintRows; i++)
- {
- if (m_allConstraintPtrArray[i]->m_jacDiagABInv)
- {
- m_b[i] = m_allConstraintPtrArray[i]->m_rhs / m_allConstraintPtrArray[i]->m_jacDiagABInv;
- if (infoGlobal.m_splitImpulse)
- m_bSplit[i] = m_allConstraintPtrArray[i]->m_rhsPenetration / m_allConstraintPtrArray[i]->m_jacDiagABInv;
- }
- }
-
- btMatrixXu& Minv = m_scratchMInv;
- Minv.resize(6 * numBodies, 6 * numBodies);
- Minv.setZero();
- for (int i = 0; i < numBodies; i++)
- {
- const btSolverBody& rb = m_tmpSolverBodyPool[i];
- const btVector3& invMass = rb.m_invMass;
- setElem(Minv, i * 6 + 0, i * 6 + 0, invMass[0]);
- setElem(Minv, i * 6 + 1, i * 6 + 1, invMass[1]);
- setElem(Minv, i * 6 + 2, i * 6 + 2, invMass[2]);
- btRigidBody* orgBody = m_tmpSolverBodyPool[i].m_originalBody;
-
- for (int r = 0; r < 3; r++)
- for (int c = 0; c < 3; c++)
- setElem(Minv, i * 6 + 3 + r, i * 6 + 3 + c, orgBody ? orgBody->getInvInertiaTensorWorld()[r][c] : 0);
- }
-
- btMatrixXu& J = m_scratchJ;
- J.resize(numConstraintRows, 6 * numBodies);
- J.setZero();
-
- m_lo.resize(numConstraintRows);
- m_hi.resize(numConstraintRows);
-
- for (int i = 0; i < numConstraintRows; i++)
- {
- m_lo[i] = m_allConstraintPtrArray[i]->m_lowerLimit;
- m_hi[i] = m_allConstraintPtrArray[i]->m_upperLimit;
-
- int bodyIndex0 = m_allConstraintPtrArray[i]->m_solverBodyIdA;
- int bodyIndex1 = m_allConstraintPtrArray[i]->m_solverBodyIdB;
- if (m_tmpSolverBodyPool[bodyIndex0].m_originalBody)
- {
- setElem(J, i, 6 * bodyIndex0 + 0, m_allConstraintPtrArray[i]->m_contactNormal1[0]);
- setElem(J, i, 6 * bodyIndex0 + 1, m_allConstraintPtrArray[i]->m_contactNormal1[1]);
- setElem(J, i, 6 * bodyIndex0 + 2, m_allConstraintPtrArray[i]->m_contactNormal1[2]);
- setElem(J, i, 6 * bodyIndex0 + 3, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[0]);
- setElem(J, i, 6 * bodyIndex0 + 4, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[1]);
- setElem(J, i, 6 * bodyIndex0 + 5, m_allConstraintPtrArray[i]->m_relpos1CrossNormal[2]);
- }
- if (m_tmpSolverBodyPool[bodyIndex1].m_originalBody)
- {
- setElem(J, i, 6 * bodyIndex1 + 0, m_allConstraintPtrArray[i]->m_contactNormal2[0]);
- setElem(J, i, 6 * bodyIndex1 + 1, m_allConstraintPtrArray[i]->m_contactNormal2[1]);
- setElem(J, i, 6 * bodyIndex1 + 2, m_allConstraintPtrArray[i]->m_contactNormal2[2]);
- setElem(J, i, 6 * bodyIndex1 + 3, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[0]);
- setElem(J, i, 6 * bodyIndex1 + 4, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[1]);
- setElem(J, i, 6 * bodyIndex1 + 5, m_allConstraintPtrArray[i]->m_relpos2CrossNormal[2]);
- }
- }
-
- btMatrixXu& J_transpose = m_scratchJTranspose;
- J_transpose = J.transpose();
-
- btMatrixXu& tmp = m_scratchTmp;
- //Minv.printMatrix("Minv=");
- {
- {
- BT_PROFILE("J*Minv");
- tmp = J * Minv;
- }
- {
- BT_PROFILE("J*tmp");
- m_A = tmp * J_transpose;
- }
- }
- //J.printMatrix("J");
- if (1)
- {
- // add cfm to the diagonal of m_A
- for (int i = 0; i < m_A.rows(); ++i)
- {
- m_A.setElem(i, i, m_A(i, i) + infoGlobal.m_globalCfm / infoGlobal.m_timeStep);
- }
- }
-
- m_x.resize(numConstraintRows);
- if (infoGlobal.m_splitImpulse)
- m_xSplit.resize(numConstraintRows);
- // m_x.setZero();
-
- for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
- {
- const btSolverConstraint& c = *m_allConstraintPtrArray[i];
- m_x[i] = c.m_appliedImpulse;
- if (infoGlobal.m_splitImpulse)
- m_xSplit[i] = c.m_appliedPushImpulse;
- }
-}
-
-btScalar btMLCPSolver::solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- bool result = true;
- {
- BT_PROFILE("solveMLCP");
- // printf("m_A(%d,%d)\n", m_A.rows(),m_A.cols());
- result = solveMLCP(infoGlobal);
- }
-
- //check if solution is valid, and otherwise fallback to btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations
- if (result)
- {
- BT_PROFILE("process MLCP results");
- for (int i = 0; i < m_allConstraintPtrArray.size(); i++)
- {
- {
- btSolverConstraint& c = *m_allConstraintPtrArray[i];
- int sbA = c.m_solverBodyIdA;
- int sbB = c.m_solverBodyIdB;
- //btRigidBody* orgBodyA = m_tmpSolverBodyPool[sbA].m_originalBody;
- // btRigidBody* orgBodyB = m_tmpSolverBodyPool[sbB].m_originalBody;
-
- btSolverBody& solverBodyA = m_tmpSolverBodyPool[sbA];
- btSolverBody& solverBodyB = m_tmpSolverBodyPool[sbB];
-
- {
- btScalar deltaImpulse = m_x[i] - c.m_appliedImpulse;
- c.m_appliedImpulse = m_x[i];
- solverBodyA.internalApplyImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- solverBodyB.internalApplyImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- }
-
- if (infoGlobal.m_splitImpulse)
- {
- btScalar deltaImpulse = m_xSplit[i] - c.m_appliedPushImpulse;
- solverBodyA.internalApplyPushImpulse(c.m_contactNormal1 * solverBodyA.internalGetInvMass(), c.m_angularComponentA, deltaImpulse);
- solverBodyB.internalApplyPushImpulse(c.m_contactNormal2 * solverBodyB.internalGetInvMass(), c.m_angularComponentB, deltaImpulse);
- c.m_appliedPushImpulse = m_xSplit[i];
- }
- }
- }
- }
- else
- {
- // printf("m_fallback = %d\n",m_fallback);
- m_fallback++;
- btSequentialImpulseConstraintSolver::solveGroupCacheFriendlyIterations(bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- }
-
- return 0.f;
-}
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h
deleted file mode 100644
index 510ae59e58..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolver.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_MLCP_SOLVER_H
-#define BT_MLCP_SOLVER_H
-
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-#include "LinearMath/btMatrixX.h"
-#include "BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h"
-
-class btMLCPSolver : public btSequentialImpulseConstraintSolver
-{
-protected:
- btMatrixXu m_A;
- btVectorXu m_b;
- btVectorXu m_x;
- btVectorXu m_lo;
- btVectorXu m_hi;
-
- ///when using 'split impulse' we solve two separate (M)LCPs
- btVectorXu m_bSplit;
- btVectorXu m_xSplit;
- btVectorXu m_bSplit1;
- btVectorXu m_xSplit2;
-
- btAlignedObjectArray<int> m_limitDependencies;
- btAlignedObjectArray<btSolverConstraint*> m_allConstraintPtrArray;
- btMLCPSolverInterface* m_solver;
- int m_fallback;
-
- /// The following scratch variables are not stateful -- contents are cleared prior to each use.
- /// They are only cached here to avoid extra memory allocations and deallocations and to ensure
- /// that multiple instances of the solver can be run in parallel.
- btMatrixXu m_scratchJ3;
- btMatrixXu m_scratchJInvM3;
- btAlignedObjectArray<int> m_scratchOfs;
- btMatrixXu m_scratchMInv;
- btMatrixXu m_scratchJ;
- btMatrixXu m_scratchJTranspose;
- btMatrixXu m_scratchTmp;
-
- virtual btScalar solveGroupCacheFriendlySetup(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
- virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies, int numBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
- virtual void createMLCP(const btContactSolverInfo& infoGlobal);
- virtual void createMLCPFast(const btContactSolverInfo& infoGlobal);
-
- //return true is it solves the problem successfully
- virtual bool solveMLCP(const btContactSolverInfo& infoGlobal);
-
-public:
- btMLCPSolver(btMLCPSolverInterface* solver);
- virtual ~btMLCPSolver();
-
- void setMLCPSolver(btMLCPSolverInterface* solver)
- {
- m_solver = solver;
- }
-
- int getNumFallbacks() const
- {
- return m_fallback;
- }
- void setNumFallbacks(int num)
- {
- m_fallback = num;
- }
-
- virtual btConstraintSolverType getSolverType() const
- {
- return BT_MLCP_SOLVER;
- }
-};
-
-#endif //BT_MLCP_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
deleted file mode 100644
index 6b0465b88d..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btMLCPSolverInterface.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_MLCP_SOLVER_INTERFACE_H
-#define BT_MLCP_SOLVER_INTERFACE_H
-
-#include "LinearMath/btMatrixX.h"
-
-class btMLCPSolverInterface
-{
-public:
- virtual ~btMLCPSolverInterface()
- {
- }
-
- //return true is it solves the problem successfully
- virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true) = 0;
-};
-
-#endif //BT_MLCP_SOLVER_INTERFACE_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h
deleted file mode 100644
index 7f8eec3f6e..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btPATHSolver.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_PATH_SOLVER_H
-#define BT_PATH_SOLVER_H
-
-//#define BT_USE_PATH
-#ifdef BT_USE_PATH
-
-extern "C"
-{
-#include "PATH/SimpleLCP.h"
-#include "PATH/License.h"
-#include "PATH/Error_Interface.h"
-};
-void __stdcall MyError(Void *data, Char *msg)
-{
- printf("Path Error: %s\n", msg);
-}
-void __stdcall MyWarning(Void *data, Char *msg)
-{
- printf("Path Warning: %s\n", msg);
-}
-
-Error_Interface e;
-
-#include "btMLCPSolverInterface.h"
-#include "Dantzig/lcp.h"
-
-class btPathSolver : public btMLCPSolverInterface
-{
-public:
- btPathSolver()
- {
- License_SetString("2069810742&Courtesy_License&&&USR&2013&14_12_2011&1000&PATH&GEN&31_12_2013&0_0_0&0&0_0");
- e.error_data = 0;
- e.warning = MyWarning;
- e.error = MyError;
- Error_SetInterface(&e);
- }
-
- virtual bool solveMLCP(const btMatrixXu &A, const btVectorXu &b, btVectorXu &x, const btVectorXu &lo, const btVectorXu &hi, const btAlignedObjectArray<int> &limitDependency, int numIterations, bool useSparsity = true)
- {
- MCP_Termination status;
-
- int numVariables = b.rows();
- if (0 == numVariables)
- return true;
-
- /* - variables - the number of variables in the problem
- - m_nnz - the number of nonzeros in the M matrix
- - m_i - a vector of size m_nnz containing the row indices for M
- - m_j - a vector of size m_nnz containing the column indices for M
- - m_ij - a vector of size m_nnz containing the data for M
- - q - a vector of size variables
- - lb - a vector of size variables containing the lower bounds on x
- - ub - a vector of size variables containing the upper bounds on x
- */
- btAlignedObjectArray<double> values;
- btAlignedObjectArray<int> rowIndices;
- btAlignedObjectArray<int> colIndices;
-
- for (int i = 0; i < A.rows(); i++)
- {
- for (int j = 0; j < A.cols(); j++)
- {
- if (A(i, j) != 0.f)
- {
- //add 1, because Path starts at 1, instead of 0
- rowIndices.push_back(i + 1);
- colIndices.push_back(j + 1);
- values.push_back(A(i, j));
- }
- }
- }
- int numNonZero = rowIndices.size();
- btAlignedObjectArray<double> zResult;
- zResult.resize(numVariables);
- btAlignedObjectArray<double> rhs;
- btAlignedObjectArray<double> upperBounds;
- btAlignedObjectArray<double> lowerBounds;
- for (int i = 0; i < numVariables; i++)
- {
- upperBounds.push_back(hi[i]);
- lowerBounds.push_back(lo[i]);
- rhs.push_back(-b[i]);
- }
-
- SimpleLCP(numVariables, numNonZero, &rowIndices[0], &colIndices[0], &values[0], &rhs[0], &lowerBounds[0], &upperBounds[0], &status, &zResult[0]);
-
- if (status != MCP_Solved)
- {
- static const char *gReturnMsgs[] = {
- "Invalid return",
- "MCP_Solved: The problem was solved",
- "MCP_NoProgress: A stationary point was found",
- "MCP_MajorIterationLimit: Major iteration limit met",
- "MCP_MinorIterationLimit: Cumulative minor iteration limit met",
- "MCP_TimeLimit: Ran out of time",
- "MCP_UserInterrupt: Control-C, typically",
- "MCP_BoundError: Problem has a bound error",
- "MCP_DomainError: Could not find starting point",
- "MCP_Infeasible: Problem has no solution",
- "MCP_Error: An error occurred within the code",
- "MCP_LicenseError: License could not be found",
- "MCP_OK"};
-
- printf("ERROR: The PATH MCP solver failed: %s\n", gReturnMsgs[(unsigned int)status]); // << std::endl;
- printf("using Projected Gauss Seidel fallback\n");
-
- return false;
- }
- else
- {
- for (int i = 0; i < numVariables; i++)
- {
- x[i] = zResult[i];
- //check for #NAN
- if (x[i] != zResult[i])
- return false;
- }
- return true;
- }
- }
-};
-
-#endif //BT_USE_PATH
-
-#endif //BT_PATH_SOLVER_H
diff --git a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h b/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
deleted file mode 100644
index c3f4ec3997..0000000000
--- a/thirdparty/bullet/BulletDynamics/MLCPSolvers/btSolveProjectedGaussSeidel.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
-#define BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
-
-#include "btMLCPSolverInterface.h"
-
-///This solver is mainly for debug/learning purposes: it is functionally equivalent to the btSequentialImpulseConstraintSolver solver, but much slower (it builds the full LCP matrix)
-class btSolveProjectedGaussSeidel : public btMLCPSolverInterface
-{
-public:
- btScalar m_leastSquaresResidualThreshold;
- btScalar m_leastSquaresResidual;
-
- btSolveProjectedGaussSeidel()
- : m_leastSquaresResidualThreshold(0),
- m_leastSquaresResidual(0)
- {
- }
-
- virtual bool solveMLCP(const btMatrixXu& A, const btVectorXu& b, btVectorXu& x, const btVectorXu& lo, const btVectorXu& hi, const btAlignedObjectArray<int>& limitDependency, int numIterations, bool useSparsity = true)
- {
- if (!A.rows())
- return true;
- //the A matrix is sparse, so compute the non-zero elements
- A.rowComputeNonZeroElements();
-
- //A is a m-n matrix, m rows, n columns
- btAssert(A.rows() == b.rows());
-
- int i, j, numRows = A.rows();
-
- btScalar delta;
-
- for (int k = 0; k < numIterations; k++)
- {
- m_leastSquaresResidual = 0.f;
- for (i = 0; i < numRows; i++)
- {
- delta = 0.0f;
- if (useSparsity)
- {
- for (int h = 0; h < A.m_rowNonZeroElements1[i].size(); h++)
- {
- j = A.m_rowNonZeroElements1[i][h];
- if (j != i) //skip main diagonal
- {
- delta += A(i, j) * x[j];
- }
- }
- }
- else
- {
- for (j = 0; j < i; j++)
- delta += A(i, j) * x[j];
- for (j = i + 1; j < numRows; j++)
- delta += A(i, j) * x[j];
- }
-
- btScalar aDiag = A(i, i);
- btScalar xOld = x[i];
- x[i] = (b[i] - delta) / aDiag;
- btScalar s = 1.f;
-
- if (limitDependency[i] >= 0)
- {
- s = x[limitDependency[i]];
- if (s < 0)
- s = 1;
- }
-
- if (x[i] < lo[i] * s)
- x[i] = lo[i] * s;
- if (x[i] > hi[i] * s)
- x[i] = hi[i] * s;
- btScalar diff = x[i] - xOld;
- m_leastSquaresResidual += diff * diff;
- }
-
- btScalar eps = m_leastSquaresResidualThreshold;
- if ((m_leastSquaresResidual < eps) || (k >= (numIterations - 1)))
- {
-#ifdef VERBOSE_PRINTF_RESIDUAL
- printf("totalLenSqr = %f at iteration #%d\n", m_leastSquaresResidual, k);
-#endif
- break;
- }
- }
- return true;
- }
-};
-
-#endif //BT_SOLVE_PROJECTED_GAUSS_SEIDEL_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
deleted file mode 100644
index fc70d8e637..0000000000
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.cpp
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
-*/
-
-#include "LinearMath/btVector3.h"
-#include "btRaycastVehicle.h"
-
-#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
-#include "LinearMath/btQuaternion.h"
-#include "BulletDynamics/Dynamics/btDynamicsWorld.h"
-#include "btVehicleRaycaster.h"
-#include "btWheelInfo.h"
-#include "LinearMath/btMinMax.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
-
-#define ROLLING_INFLUENCE_FIX
-
-btRigidBody& btActionInterface::getFixedBody()
-{
- static btRigidBody s_fixed(0, 0, 0);
- s_fixed.setMassProps(btScalar(0.), btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));
- return s_fixed;
-}
-
-btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster)
- : m_vehicleRaycaster(raycaster),
- m_pitchControl(btScalar(0.))
-{
- m_chassisBody = chassis;
- m_indexRightAxis = 0;
- m_indexUpAxis = 2;
- m_indexForwardAxis = 1;
- defaultInit(tuning);
-}
-
-void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
-{
- (void)tuning;
- m_currentVehicleSpeedKmHour = btScalar(0.);
- m_steeringValue = btScalar(0.);
-}
-
-btRaycastVehicle::~btRaycastVehicle()
-{
-}
-
-//
-// basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
-//
-btWheelInfo& btRaycastVehicle::addWheel(const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel)
-{
- btWheelInfoConstructionInfo ci;
-
- ci.m_chassisConnectionCS = connectionPointCS;
- ci.m_wheelDirectionCS = wheelDirectionCS0;
- ci.m_wheelAxleCS = wheelAxleCS;
- ci.m_suspensionRestLength = suspensionRestLength;
- ci.m_wheelRadius = wheelRadius;
- ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
- ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
- ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
- ci.m_frictionSlip = tuning.m_frictionSlip;
- ci.m_bIsFrontWheel = isFrontWheel;
- ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
- ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
-
- m_wheelInfo.push_back(btWheelInfo(ci));
-
- btWheelInfo& wheel = m_wheelInfo[getNumWheels() - 1];
-
- updateWheelTransformsWS(wheel, false);
- updateWheelTransform(getNumWheels() - 1, false);
- return wheel;
-}
-
-const btTransform& btRaycastVehicle::getWheelTransformWS(int wheelIndex) const
-{
- btAssert(wheelIndex < getNumWheels());
- const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
- return wheel.m_worldTransform;
-}
-
-void btRaycastVehicle::updateWheelTransform(int wheelIndex, bool interpolatedTransform)
-{
- btWheelInfo& wheel = m_wheelInfo[wheelIndex];
- updateWheelTransformsWS(wheel, interpolatedTransform);
- btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
- const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
- btVector3 fwd = up.cross(right);
- fwd = fwd.normalize();
- // up = right.cross(fwd);
- // up.normalize();
-
- //rotate around steering over de wheelAxleWS
- btScalar steering = wheel.m_steering;
-
- btQuaternion steeringOrn(up, steering); //wheel.m_steering);
- btMatrix3x3 steeringMat(steeringOrn);
-
- btQuaternion rotatingOrn(right, -wheel.m_rotation);
- btMatrix3x3 rotatingMat(rotatingOrn);
-
- btMatrix3x3 basis2;
- basis2[0][m_indexRightAxis] = -right[0];
- basis2[1][m_indexRightAxis] = -right[1];
- basis2[2][m_indexRightAxis] = -right[2];
-
- basis2[0][m_indexUpAxis] = up[0];
- basis2[1][m_indexUpAxis] = up[1];
- basis2[2][m_indexUpAxis] = up[2];
-
- basis2[0][m_indexForwardAxis] = fwd[0];
- basis2[1][m_indexForwardAxis] = fwd[1];
- basis2[2][m_indexForwardAxis] = fwd[2];
-
- wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
- wheel.m_worldTransform.setOrigin(
- wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength);
-}
-
-void btRaycastVehicle::resetSuspension()
-{
- int i;
- for (i = 0; i < m_wheelInfo.size(); i++)
- {
- btWheelInfo& wheel = m_wheelInfo[i];
- wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
-
- wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
- //wheel_info.setContactFriction(btScalar(0.0));
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
- }
-}
-
-void btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform)
-{
- wheel.m_raycastInfo.m_isInContact = false;
-
- btTransform chassisTrans = getChassisWorldTransform();
- if (interpolatedTransform && (getRigidBody()->getMotionState()))
- {
- getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
- }
-
- wheel.m_raycastInfo.m_hardPointWS = chassisTrans(wheel.m_chassisConnectionPointCS);
- wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() * wheel.m_wheelDirectionCS;
- wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
-}
-
-btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
-{
- updateWheelTransformsWS(wheel, false);
-
- btScalar depth = -1;
-
- btScalar raylen = wheel.getSuspensionRestLength() + wheel.m_wheelsRadius;
-
- btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
- const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
- wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
- const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
-
- btScalar param = btScalar(0.);
-
- btVehicleRaycaster::btVehicleRaycasterResult rayResults;
-
- btAssert(m_vehicleRaycaster);
-
- void* object = m_vehicleRaycaster->castRay(source, target, rayResults);
-
- wheel.m_raycastInfo.m_groundObject = 0;
-
- if (object)
- {
- param = rayResults.m_distFraction;
- depth = raylen * rayResults.m_distFraction;
- wheel.m_raycastInfo.m_contactNormalWS = rayResults.m_hitNormalInWorld;
- wheel.m_raycastInfo.m_isInContact = true;
-
- wheel.m_raycastInfo.m_groundObject = &getFixedBody(); ///@todo for driving on dynamic/movable objects!;
- //wheel.m_raycastInfo.m_groundObject = object;
-
- btScalar hitDistance = param * raylen;
- wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
- //clamp on max suspension travel
-
- btScalar minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm * btScalar(0.01);
- btScalar maxSuspensionLength = wheel.getSuspensionRestLength() + wheel.m_maxSuspensionTravelCm * btScalar(0.01);
- if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
- {
- wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
- }
- if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
- {
- wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
- }
-
- wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
-
- btScalar denominator = wheel.m_raycastInfo.m_contactNormalWS.dot(wheel.m_raycastInfo.m_wheelDirectionWS);
-
- btVector3 chassis_velocity_at_contactPoint;
- btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
-
- chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
-
- btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
-
- if (denominator >= btScalar(-0.1))
- {
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
- }
- else
- {
- btScalar inv = btScalar(-1.) / denominator;
- wheel.m_suspensionRelativeVelocity = projVel * inv;
- wheel.m_clippedInvContactDotSuspension = inv;
- }
- }
- else
- {
- //put wheel info as in rest position
- wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
- wheel.m_suspensionRelativeVelocity = btScalar(0.0);
- wheel.m_raycastInfo.m_contactNormalWS = -wheel.m_raycastInfo.m_wheelDirectionWS;
- wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
- }
-
- return depth;
-}
-
-const btTransform& btRaycastVehicle::getChassisWorldTransform() const
-{
- /*if (getRigidBody()->getMotionState())
- {
- btTransform chassisWorldTrans;
- getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
- return chassisWorldTrans;
- }
- */
-
- return getRigidBody()->getCenterOfMassTransform();
-}
-
-void btRaycastVehicle::updateVehicle(btScalar step)
-{
- {
- for (int i = 0; i < getNumWheels(); i++)
- {
- updateWheelTransform(i, false);
- }
- }
-
- m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
-
- const btTransform& chassisTrans = getChassisWorldTransform();
-
- btVector3 forwardW(
- chassisTrans.getBasis()[0][m_indexForwardAxis],
- chassisTrans.getBasis()[1][m_indexForwardAxis],
- chassisTrans.getBasis()[2][m_indexForwardAxis]);
-
- if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
- {
- m_currentVehicleSpeedKmHour *= btScalar(-1.);
- }
-
- //
- // simulate suspension
- //
-
- int i = 0;
- for (i = 0; i < m_wheelInfo.size(); i++)
- {
- //btScalar depth;
- //depth =
- rayCast(m_wheelInfo[i]);
- }
-
- updateSuspension(step);
-
- for (i = 0; i < m_wheelInfo.size(); i++)
- {
- //apply suspension force
- btWheelInfo& wheel = m_wheelInfo[i];
-
- btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
-
- if (suspensionForce > wheel.m_maxSuspensionForce)
- {
- suspensionForce = wheel.m_maxSuspensionForce;
- }
- btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
- btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
-
- getRigidBody()->applyImpulse(impulse, relpos);
- }
-
- updateFriction(step);
-
- for (i = 0; i < m_wheelInfo.size(); i++)
- {
- btWheelInfo& wheel = m_wheelInfo[i];
- btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
- btVector3 vel = getRigidBody()->getVelocityInLocalPoint(relpos);
-
- if (wheel.m_raycastInfo.m_isInContact)
- {
- const btTransform& chassisWorldTransform = getChassisWorldTransform();
-
- btVector3 fwd(
- chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
- chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
- chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
-
- btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
- fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
-
- btScalar proj2 = fwd.dot(vel);
-
- wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
- wheel.m_rotation += wheel.m_deltaRotation;
- }
- else
- {
- wheel.m_rotation += wheel.m_deltaRotation;
- }
-
- wheel.m_deltaRotation *= btScalar(0.99); //damping of rotation when not in contact
- }
-}
-
-void btRaycastVehicle::setSteeringValue(btScalar steering, int wheel)
-{
- btAssert(wheel >= 0 && wheel < getNumWheels());
-
- btWheelInfo& wheelInfo = getWheelInfo(wheel);
- wheelInfo.m_steering = steering;
-}
-
-btScalar btRaycastVehicle::getSteeringValue(int wheel) const
-{
- return getWheelInfo(wheel).m_steering;
-}
-
-void btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
-{
- btAssert(wheel >= 0 && wheel < getNumWheels());
- btWheelInfo& wheelInfo = getWheelInfo(wheel);
- wheelInfo.m_engineForce = force;
-}
-
-const btWheelInfo& btRaycastVehicle::getWheelInfo(int index) const
-{
- btAssert((index >= 0) && (index < getNumWheels()));
-
- return m_wheelInfo[index];
-}
-
-btWheelInfo& btRaycastVehicle::getWheelInfo(int index)
-{
- btAssert((index >= 0) && (index < getNumWheels()));
-
- return m_wheelInfo[index];
-}
-
-void btRaycastVehicle::setBrake(btScalar brake, int wheelIndex)
-{
- btAssert((wheelIndex >= 0) && (wheelIndex < getNumWheels()));
- getWheelInfo(wheelIndex).m_brake = brake;
-}
-
-void btRaycastVehicle::updateSuspension(btScalar deltaTime)
-{
- (void)deltaTime;
-
- btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
-
- for (int w_it = 0; w_it < getNumWheels(); w_it++)
- {
- btWheelInfo& wheel_info = m_wheelInfo[w_it];
-
- if (wheel_info.m_raycastInfo.m_isInContact)
- {
- btScalar force;
- // Spring
- {
- btScalar susp_length = wheel_info.getSuspensionRestLength();
- btScalar current_length = wheel_info.m_raycastInfo.m_suspensionLength;
-
- btScalar length_diff = (susp_length - current_length);
-
- force = wheel_info.m_suspensionStiffness * length_diff * wheel_info.m_clippedInvContactDotSuspension;
- }
-
- // Damper
- {
- btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
- {
- btScalar susp_damping;
- if (projected_rel_vel < btScalar(0.0))
- {
- susp_damping = wheel_info.m_wheelsDampingCompression;
- }
- else
- {
- susp_damping = wheel_info.m_wheelsDampingRelaxation;
- }
- force -= susp_damping * projected_rel_vel;
- }
- }
-
- // RESULT
- wheel_info.m_wheelsSuspensionForce = force * chassisMass;
- if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
- {
- wheel_info.m_wheelsSuspensionForce = btScalar(0.);
- }
- }
- else
- {
- wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
- }
- }
-}
-
-struct btWheelContactPoint
-{
- btRigidBody* m_body0;
- btRigidBody* m_body1;
- btVector3 m_frictionPositionWorld;
- btVector3 m_frictionDirectionWorld;
- btScalar m_jacDiagABInv;
- btScalar m_maxImpulse;
-
- btWheelContactPoint(btRigidBody* body0, btRigidBody* body1, const btVector3& frictionPosWorld, const btVector3& frictionDirectionWorld, btScalar maxImpulse)
- : m_body0(body0),
- m_body1(body1),
- m_frictionPositionWorld(frictionPosWorld),
- m_frictionDirectionWorld(frictionDirectionWorld),
- m_maxImpulse(maxImpulse)
- {
- btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
- btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld, frictionDirectionWorld);
- btScalar relaxation = 1.f;
- m_jacDiagABInv = relaxation / (denom0 + denom1);
- }
-};
-
-btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround);
-btScalar calcRollingFriction(btWheelContactPoint& contactPoint, int numWheelsOnGround)
-{
- btScalar j1 = 0.f;
-
- const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
-
- btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition();
- btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
-
- btScalar maxImpulse = contactPoint.m_maxImpulse;
-
- btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
- btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
- btVector3 vel = vel1 - vel2;
-
- btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
-
- // calculate j that moves us to zero relative velocity
- j1 = -vrel * contactPoint.m_jacDiagABInv / btScalar(numWheelsOnGround);
- btSetMin(j1, maxImpulse);
- btSetMax(j1, -maxImpulse);
-
- return j1;
-}
-
-btScalar sideFrictionStiffness2 = btScalar(1.0);
-void btRaycastVehicle::updateFriction(btScalar timeStep)
-{
- //calculate the impulse, so that the wheels don't move sidewards
- int numWheel = getNumWheels();
- if (!numWheel)
- return;
-
- m_forwardWS.resize(numWheel);
- m_axle.resize(numWheel);
- m_forwardImpulse.resize(numWheel);
- m_sideImpulse.resize(numWheel);
-
- int numWheelsOnGround = 0;
-
- //collapse all those loops into one!
- for (int i = 0; i < getNumWheels(); i++)
- {
- btWheelInfo& wheelInfo = m_wheelInfo[i];
- class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
- if (groundObject)
- numWheelsOnGround++;
- m_sideImpulse[i] = btScalar(0.);
- m_forwardImpulse[i] = btScalar(0.);
- }
-
- {
- for (int i = 0; i < getNumWheels(); i++)
- {
- btWheelInfo& wheelInfo = m_wheelInfo[i];
-
- class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
-
- if (groundObject)
- {
- const btTransform& wheelTrans = getWheelTransformWS(i);
-
- btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
- m_axle[i] = -btVector3(
- wheelBasis0[0][m_indexRightAxis],
- wheelBasis0[1][m_indexRightAxis],
- wheelBasis0[2][m_indexRightAxis]);
-
- const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
- btScalar proj = m_axle[i].dot(surfNormalWS);
- m_axle[i] -= surfNormalWS * proj;
- m_axle[i] = m_axle[i].normalize();
-
- m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
- m_forwardWS[i].normalize();
-
- resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
- *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
- btScalar(0.), m_axle[i], m_sideImpulse[i], timeStep);
-
- m_sideImpulse[i] *= sideFrictionStiffness2;
- }
- }
- }
-
- btScalar sideFactor = btScalar(1.);
- btScalar fwdFactor = 0.5;
-
- bool sliding = false;
- {
- for (int wheel = 0; wheel < getNumWheels(); wheel++)
- {
- btWheelInfo& wheelInfo = m_wheelInfo[wheel];
- class btRigidBody* groundObject = (class btRigidBody*)wheelInfo.m_raycastInfo.m_groundObject;
-
- btScalar rollingFriction = 0.f;
-
- if (groundObject)
- {
- if (wheelInfo.m_engineForce != 0.f)
- {
- rollingFriction = wheelInfo.m_engineForce * timeStep;
- }
- else
- {
- btScalar defaultRollingFrictionImpulse = 0.f;
- btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
- btWheelContactPoint contactPt(m_chassisBody, groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, m_forwardWS[wheel], maxImpulse);
- btAssert(numWheelsOnGround > 0);
- rollingFriction = calcRollingFriction(contactPt, numWheelsOnGround);
- }
- }
-
- //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
-
- m_forwardImpulse[wheel] = btScalar(0.);
- m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
-
- if (groundObject)
- {
- m_wheelInfo[wheel].m_skidInfo = btScalar(1.);
-
- btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
- btScalar maximpSide = maximp;
-
- btScalar maximpSquared = maximp * maximpSide;
-
- m_forwardImpulse[wheel] = rollingFriction; //wheelInfo.m_engineForce* timeStep;
-
- btScalar x = (m_forwardImpulse[wheel]) * fwdFactor;
- btScalar y = (m_sideImpulse[wheel]) * sideFactor;
-
- btScalar impulseSquared = (x * x + y * y);
-
- if (impulseSquared > maximpSquared)
- {
- sliding = true;
-
- btScalar factor = maximp / btSqrt(impulseSquared);
-
- m_wheelInfo[wheel].m_skidInfo *= factor;
- }
- }
- }
- }
-
- if (sliding)
- {
- for (int wheel = 0; wheel < getNumWheels(); wheel++)
- {
- if (m_sideImpulse[wheel] != btScalar(0.))
- {
- if (m_wheelInfo[wheel].m_skidInfo < btScalar(1.))
- {
- m_forwardImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
- m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
- }
- }
- }
- }
-
- // apply the impulses
- {
- for (int wheel = 0; wheel < getNumWheels(); wheel++)
- {
- btWheelInfo& wheelInfo = m_wheelInfo[wheel];
-
- btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS -
- m_chassisBody->getCenterOfMassPosition();
-
- if (m_forwardImpulse[wheel] != btScalar(0.))
- {
- m_chassisBody->applyImpulse(m_forwardWS[wheel] * (m_forwardImpulse[wheel]), rel_pos);
- }
- if (m_sideImpulse[wheel] != btScalar(0.))
- {
- class btRigidBody* groundObject = (class btRigidBody*)m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
-
- btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS -
- groundObject->getCenterOfMassPosition();
-
- btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
-
-#if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT.
- btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis);
- rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f - wheelInfo.m_rollInfluence));
-#else
- rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
-#endif
- m_chassisBody->applyImpulse(sideImp, rel_pos);
-
- //apply friction impulse on the ground
- groundObject->applyImpulse(-sideImp, rel_pos2);
- }
- }
- }
-}
-
-void btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
-{
- for (int v = 0; v < this->getNumWheels(); v++)
- {
- btVector3 wheelColor(0, 1, 1);
- if (getWheelInfo(v).m_raycastInfo.m_isInContact)
- {
- wheelColor.setValue(0, 0, 1);
- }
- else
- {
- wheelColor.setValue(1, 0, 1);
- }
-
- btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
-
- btVector3 axle = btVector3(
- getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
- getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
- getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
-
- //debug wheels (cylinders)
- debugDrawer->drawLine(wheelPosWS, wheelPosWS + axle, wheelColor);
- debugDrawer->drawLine(wheelPosWS, getWheelInfo(v).m_raycastInfo.m_contactPointWS, wheelColor);
- }
-}
-
-void* btDefaultVehicleRaycaster::castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result)
-{
- // RayResultCallback& resultCallback;
-
- btCollisionWorld::ClosestRayResultCallback rayCallback(from, to);
-
- m_dynamicsWorld->rayTest(from, to, rayCallback);
-
- if (rayCallback.hasHit())
- {
- const btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
- if (body && body->hasContactResponse())
- {
- result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
- result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
- result.m_hitNormalInWorld.normalize();
- result.m_distFraction = rayCallback.m_closestHitFraction;
- return (void*)body;
- }
- }
- return 0;
-}
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h b/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
deleted file mode 100644
index 99d6894e56..0000000000
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btRaycastVehicle.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
-*/
-#ifndef BT_RAYCASTVEHICLE_H
-#define BT_RAYCASTVEHICLE_H
-
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
-#include "btVehicleRaycaster.h"
-class btDynamicsWorld;
-#include "LinearMath/btAlignedObjectArray.h"
-#include "btWheelInfo.h"
-#include "BulletDynamics/Dynamics/btActionInterface.h"
-
-//class btVehicleTuning;
-
-///rayCast vehicle, very special constraint that turn a rigidbody into a vehicle.
-class btRaycastVehicle : public btActionInterface
-{
- btAlignedObjectArray<btVector3> m_forwardWS;
- btAlignedObjectArray<btVector3> m_axle;
- btAlignedObjectArray<btScalar> m_forwardImpulse;
- btAlignedObjectArray<btScalar> m_sideImpulse;
-
- ///backwards compatibility
- int m_userConstraintType;
- int m_userConstraintId;
-
-public:
- class btVehicleTuning
- {
- public:
- btVehicleTuning()
- : m_suspensionStiffness(btScalar(5.88)),
- m_suspensionCompression(btScalar(0.83)),
- m_suspensionDamping(btScalar(0.88)),
- m_maxSuspensionTravelCm(btScalar(500.)),
- m_frictionSlip(btScalar(10.5)),
- m_maxSuspensionForce(btScalar(6000.))
- {
- }
- btScalar m_suspensionStiffness;
- btScalar m_suspensionCompression;
- btScalar m_suspensionDamping;
- btScalar m_maxSuspensionTravelCm;
- btScalar m_frictionSlip;
- btScalar m_maxSuspensionForce;
- };
-
-private:
- btVehicleRaycaster* m_vehicleRaycaster;
- btScalar m_pitchControl;
- btScalar m_steeringValue;
- btScalar m_currentVehicleSpeedKmHour;
-
- btRigidBody* m_chassisBody;
-
- int m_indexRightAxis;
- int m_indexUpAxis;
- int m_indexForwardAxis;
-
- void defaultInit(const btVehicleTuning& tuning);
-
-public:
- //constructor to create a car from an existing rigidbody
- btRaycastVehicle(const btVehicleTuning& tuning, btRigidBody* chassis, btVehicleRaycaster* raycaster);
-
- virtual ~btRaycastVehicle();
-
- ///btActionInterface interface
- virtual void updateAction(btCollisionWorld* collisionWorld, btScalar step)
- {
- (void)collisionWorld;
- updateVehicle(step);
- }
-
- ///btActionInterface interface
- void debugDraw(btIDebugDraw* debugDrawer);
-
- const btTransform& getChassisWorldTransform() const;
-
- btScalar rayCast(btWheelInfo& wheel);
-
- virtual void updateVehicle(btScalar step);
-
- void resetSuspension();
-
- btScalar getSteeringValue(int wheel) const;
-
- void setSteeringValue(btScalar steering, int wheel);
-
- void applyEngineForce(btScalar force, int wheel);
-
- const btTransform& getWheelTransformWS(int wheelIndex) const;
-
- void updateWheelTransform(int wheelIndex, bool interpolatedTransform = true);
-
- // void setRaycastWheelInfo( int wheelIndex , bool isInContact, const btVector3& hitPoint, const btVector3& hitNormal,btScalar depth);
-
- btWheelInfo& addWheel(const btVector3& connectionPointCS0, const btVector3& wheelDirectionCS0, const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius, const btVehicleTuning& tuning, bool isFrontWheel);
-
- inline int getNumWheels() const
- {
- return int(m_wheelInfo.size());
- }
-
- btAlignedObjectArray<btWheelInfo> m_wheelInfo;
-
- const btWheelInfo& getWheelInfo(int index) const;
-
- btWheelInfo& getWheelInfo(int index);
-
- void updateWheelTransformsWS(btWheelInfo& wheel, bool interpolatedTransform = true);
-
- void setBrake(btScalar brake, int wheelIndex);
-
- void setPitchControl(btScalar pitch)
- {
- m_pitchControl = pitch;
- }
-
- void updateSuspension(btScalar deltaTime);
-
- virtual void updateFriction(btScalar timeStep);
-
- inline btRigidBody* getRigidBody()
- {
- return m_chassisBody;
- }
-
- const btRigidBody* getRigidBody() const
- {
- return m_chassisBody;
- }
-
- inline int getRightAxis() const
- {
- return m_indexRightAxis;
- }
- inline int getUpAxis() const
- {
- return m_indexUpAxis;
- }
-
- inline int getForwardAxis() const
- {
- return m_indexForwardAxis;
- }
-
- ///Worldspace forward vector
- btVector3 getForwardVector() const
- {
- const btTransform& chassisTrans = getChassisWorldTransform();
-
- btVector3 forwardW(
- chassisTrans.getBasis()[0][m_indexForwardAxis],
- chassisTrans.getBasis()[1][m_indexForwardAxis],
- chassisTrans.getBasis()[2][m_indexForwardAxis]);
-
- return forwardW;
- }
-
- ///Velocity of vehicle (positive if velocity vector has same direction as foward vector)
- btScalar getCurrentSpeedKmHour() const
- {
- return m_currentVehicleSpeedKmHour;
- }
-
- virtual void setCoordinateSystem(int rightIndex, int upIndex, int forwardIndex)
- {
- m_indexRightAxis = rightIndex;
- m_indexUpAxis = upIndex;
- m_indexForwardAxis = forwardIndex;
- }
-
- ///backwards compatibility
- int getUserConstraintType() const
- {
- return m_userConstraintType;
- }
-
- void setUserConstraintType(int userConstraintType)
- {
- m_userConstraintType = userConstraintType;
- };
-
- void setUserConstraintId(int uid)
- {
- m_userConstraintId = uid;
- }
-
- int getUserConstraintId() const
- {
- return m_userConstraintId;
- }
-};
-
-class btDefaultVehicleRaycaster : public btVehicleRaycaster
-{
- btDynamicsWorld* m_dynamicsWorld;
-
-public:
- btDefaultVehicleRaycaster(btDynamicsWorld* world)
- : m_dynamicsWorld(world)
- {
- }
-
- virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result);
-};
-
-#endif //BT_RAYCASTVEHICLE_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h b/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
deleted file mode 100644
index 2c44ce546c..0000000000
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btVehicleRaycaster.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2005 Erwin Coumans http://bulletphysics.org
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
-*/
-#ifndef BT_VEHICLE_RAYCASTER_H
-#define BT_VEHICLE_RAYCASTER_H
-
-#include "LinearMath/btVector3.h"
-
-/// btVehicleRaycaster is provides interface for between vehicle simulation and raycasting
-struct btVehicleRaycaster
-{
- virtual ~btVehicleRaycaster()
- {
- }
- struct btVehicleRaycasterResult
- {
- btVehicleRaycasterResult() : m_distFraction(btScalar(-1.)){};
- btVector3 m_hitPointInWorld;
- btVector3 m_hitNormalInWorld;
- btScalar m_distFraction;
- };
-
- virtual void* castRay(const btVector3& from, const btVector3& to, btVehicleRaycasterResult& result) = 0;
-};
-
-#endif //BT_VEHICLE_RAYCASTER_H
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
deleted file mode 100644
index d5c12f223b..0000000000
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
-*/
-#include "btWheelInfo.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h" // for pointvelocity
-
-btScalar btWheelInfo::getSuspensionRestLength() const
-{
- return m_suspensionRestLength1;
-}
-
-void btWheelInfo::updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo)
-{
- (void)raycastInfo;
-
- if (m_raycastInfo.m_isInContact)
-
- {
- btScalar project = m_raycastInfo.m_contactNormalWS.dot(m_raycastInfo.m_wheelDirectionWS);
- btVector3 chassis_velocity_at_contactPoint;
- btVector3 relpos = m_raycastInfo.m_contactPointWS - chassis.getCenterOfMassPosition();
- chassis_velocity_at_contactPoint = chassis.getVelocityInLocalPoint(relpos);
- btScalar projVel = m_raycastInfo.m_contactNormalWS.dot(chassis_velocity_at_contactPoint);
- if (project >= btScalar(-0.1))
- {
- m_suspensionRelativeVelocity = btScalar(0.0);
- m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
- }
- else
- {
- btScalar inv = btScalar(-1.) / project;
- m_suspensionRelativeVelocity = projVel * inv;
- m_clippedInvContactDotSuspension = inv;
- }
- }
-
- else // Not in contact : position wheel in a nice (rest length) position
- {
- m_raycastInfo.m_suspensionLength = this->getSuspensionRestLength();
- m_suspensionRelativeVelocity = btScalar(0.0);
- m_raycastInfo.m_contactNormalWS = -m_raycastInfo.m_wheelDirectionWS;
- m_clippedInvContactDotSuspension = btScalar(1.0);
- }
-}
diff --git a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h b/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h
deleted file mode 100644
index af88b8ff83..0000000000
--- a/thirdparty/bullet/BulletDynamics/Vehicle/btWheelInfo.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies.
- * Erwin Coumans makes no representations about the suitability
- * of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
-*/
-#ifndef BT_WHEEL_INFO_H
-#define BT_WHEEL_INFO_H
-
-#include "LinearMath/btVector3.h"
-#include "LinearMath/btTransform.h"
-
-class btRigidBody;
-
-struct btWheelInfoConstructionInfo
-{
- btVector3 m_chassisConnectionCS;
- btVector3 m_wheelDirectionCS;
- btVector3 m_wheelAxleCS;
- btScalar m_suspensionRestLength;
- btScalar m_maxSuspensionTravelCm;
- btScalar m_wheelRadius;
-
- btScalar m_suspensionStiffness;
- btScalar m_wheelsDampingCompression;
- btScalar m_wheelsDampingRelaxation;
- btScalar m_frictionSlip;
- btScalar m_maxSuspensionForce;
- bool m_bIsFrontWheel;
-};
-
-/// btWheelInfo contains information per wheel about friction and suspension.
-struct btWheelInfo
-{
- struct RaycastInfo
- {
- //set by raycaster
- btVector3 m_contactNormalWS; //contactnormal
- btVector3 m_contactPointWS; //raycast hitpoint
- btScalar m_suspensionLength;
- btVector3 m_hardPointWS; //raycast starting point
- btVector3 m_wheelDirectionWS; //direction in worldspace
- btVector3 m_wheelAxleWS; // axle in worldspace
- bool m_isInContact;
- void* m_groundObject; //could be general void* ptr
- };
-
- RaycastInfo m_raycastInfo;
-
- btTransform m_worldTransform;
-
- btVector3 m_chassisConnectionPointCS; //const
- btVector3 m_wheelDirectionCS; //const
- btVector3 m_wheelAxleCS; // const or modified by steering
- btScalar m_suspensionRestLength1; //const
- btScalar m_maxSuspensionTravelCm;
- btScalar getSuspensionRestLength() const;
- btScalar m_wheelsRadius; //const
- btScalar m_suspensionStiffness; //const
- btScalar m_wheelsDampingCompression; //const
- btScalar m_wheelsDampingRelaxation; //const
- btScalar m_frictionSlip;
- btScalar m_steering;
- btScalar m_rotation;
- btScalar m_deltaRotation;
- btScalar m_rollInfluence;
- btScalar m_maxSuspensionForce;
-
- btScalar m_engineForce;
-
- btScalar m_brake;
-
- bool m_bIsFrontWheel;
-
- void* m_clientInfo; //can be used to store pointer to sync transforms...
-
- btWheelInfo() {}
-
- btWheelInfo(btWheelInfoConstructionInfo& ci)
-
- {
- m_suspensionRestLength1 = ci.m_suspensionRestLength;
- m_maxSuspensionTravelCm = ci.m_maxSuspensionTravelCm;
-
- m_wheelsRadius = ci.m_wheelRadius;
- m_suspensionStiffness = ci.m_suspensionStiffness;
- m_wheelsDampingCompression = ci.m_wheelsDampingCompression;
- m_wheelsDampingRelaxation = ci.m_wheelsDampingRelaxation;
- m_chassisConnectionPointCS = ci.m_chassisConnectionCS;
- m_wheelDirectionCS = ci.m_wheelDirectionCS;
- m_wheelAxleCS = ci.m_wheelAxleCS;
- m_frictionSlip = ci.m_frictionSlip;
- m_steering = btScalar(0.);
- m_engineForce = btScalar(0.);
- m_rotation = btScalar(0.);
- m_deltaRotation = btScalar(0.);
- m_brake = btScalar(0.);
- m_rollInfluence = btScalar(0.1);
- m_bIsFrontWheel = ci.m_bIsFrontWheel;
- m_maxSuspensionForce = ci.m_maxSuspensionForce;
- }
-
- void updateWheel(const btRigidBody& chassis, RaycastInfo& raycastInfo);
-
- btScalar m_clippedInvContactDotSuspension;
- btScalar m_suspensionRelativeVelocity;
- //calculated by suspension
- btScalar m_wheelsSuspensionForce;
- btScalar m_skidInfo;
-};
-
-#endif //BT_WHEEL_INFO_H
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp
deleted file mode 100644
index b662b80152..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfig.hpp
+++ /dev/null
@@ -1,107 +0,0 @@
-///@file Configuration for Inverse Dynamics Library,
-/// such as choice of linear algebra library and underlying scalar type
-#ifndef IDCONFIG_HPP_
-#define IDCONFIG_HPP_
-
-// If true, enable jacobian calculations.
-// This adds a 3xN matrix to every body, + 2 3-Vectors.
-// so it is not advised for large systems if it is not absolutely necessary.
-// Also, this is not required for standard inverse dynamics calculations.
-// Will only work with vector math libraries that support 3xN matrices.
-#define BT_ID_WITH_JACOBIANS
-
-// If we have a custom configuration, compile without using other parts of bullet.
-#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
-#include <cmath>
-#define BT_ID_WO_BULLET
-#define BT_ID_SQRT(x) std::sqrt(x)
-#define BT_ID_FABS(x) std::fabs(x)
-#define BT_ID_COS(x) std::cos(x)
-#define BT_ID_SIN(x) std::sin(x)
-#define BT_ID_ATAN2(x, y) std::atan2(x, y)
-#define BT_ID_POW(x, y) std::pow(x, y)
-#define BT_ID_SNPRINTF snprintf
-#define BT_ID_PI M_PI
-#define BT_ID_USE_DOUBLE_PRECISION
-#else
-#define BT_ID_SQRT(x) btSqrt(x)
-#define BT_ID_FABS(x) btFabs(x)
-#define BT_ID_COS(x) btCos(x)
-#define BT_ID_SIN(x) btSin(x)
-#define BT_ID_ATAN2(x, y) btAtan2(x, y)
-#define BT_ID_POW(x, y) btPow(x, y)
-#define BT_ID_PI SIMD_PI
-#ifdef _WIN32
-#define BT_ID_SNPRINTF _snprintf
-#else
-#define BT_ID_SNPRINTF snprintf
-#endif //
-#endif
-// error messages
-#include "IDErrorMessages.hpp"
-
-#ifdef BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H
-/*
-#include "IDConfigEigen.hpp"
-#include "IDConfigBuiltin.hpp"
-*/
-#define INVDYN_INCLUDE_HELPER_2(x) #x
-#define INVDYN_INCLUDE_HELPER(x) INVDYN_INCLUDE_HELPER_2(x)
-#include INVDYN_INCLUDE_HELPER(BT_CUSTOM_INVERSE_DYNAMICS_CONFIG_H)
-#ifndef btInverseDynamics
-#error "custom inverse dynamics config, but no custom namespace defined"
-#endif
-
-#define BT_ID_MAX(a, b) std::max(a, b)
-#define BT_ID_MIN(a, b) std::min(a, b)
-
-#else
-#define btInverseDynamics btInverseDynamicsBullet3
-// Use default configuration with bullet's types
-// Use the same scalar type as rest of bullet library
-#include "LinearMath/btScalar.h"
-typedef btScalar idScalar;
-#include "LinearMath/btMinMax.h"
-#define BT_ID_MAX(a, b) btMax(a, b)
-#define BT_ID_MIN(a, b) btMin(a, b)
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define BT_ID_USE_DOUBLE_PRECISION
-#endif
-
-#ifndef BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
-
-// use bullet types for arrays and array indices
-#include "Bullet3Common/b3AlignedObjectArray.h"
-// this is to make it work with C++2003, otherwise we could do this:
-// template <typename T>
-// using idArray = b3AlignedObjectArray<T>;
-template <typename T>
-struct idArray
-{
- typedef b3AlignedObjectArray<T> type;
-};
-typedef int idArrayIdx;
-#define ID_DECLARE_ALIGNED_ALLOCATOR() B3_DECLARE_ALIGNED_ALLOCATOR()
-
-#else // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
-
-#include "LinearMath/btAlignedObjectArray.h"
-template <typename T>
-struct idArray
-{
- typedef btAlignedObjectArray<T> type;
-};
-typedef int idArrayIdx;
-#define ID_DECLARE_ALIGNED_ALLOCATOR() BT_DECLARE_ALIGNED_ALLOCATOR()
-
-#endif // BT_USE_INVERSE_DYNAMICS_WITH_BULLET2
-
-// use bullet's allocator functions
-#define idMalloc btAllocFunc
-#define idFree btFreeFunc
-
-#define ID_LINEAR_MATH_USE_BULLET
-#include "details/IDLinearMathInterface.hpp"
-#endif
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp
deleted file mode 100644
index 6392367924..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfigBuiltin.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-///@file Configuration for Inverse Dynamics Library without external dependencies
-#ifndef INVDYNCONFIG_BUILTIN_HPP_
-#define INVDYNCONFIG_BUILTIN_HPP_
-#define btInverseDynamics btInverseDynamicsBuiltin
-#ifdef BT_USE_DOUBLE_PRECISION
-// choose double/single precision version
-typedef double idScalar;
-#else
-typedef float idScalar;
-#endif
-// use std::vector for arrays
-#include <vector>
-// this is to make it work with C++2003, otherwise we could do this
-// template <typename T>
-// using idArray = std::vector<T>;
-template <typename T>
-struct idArray
-{
- typedef std::vector<T> type;
-};
-typedef std::vector<int>::size_type idArrayIdx;
-// default to standard malloc/free
-#include <cstdlib>
-#define idMalloc ::malloc
-#define idFree ::free
-// currently not aligned at all...
-#define ID_DECLARE_ALIGNED_ALLOCATOR() \
- inline void* operator new(std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
- inline void operator delete(void* ptr) { idFree(ptr); } \
- inline void* operator new(std::size_t, void* ptr) { return ptr; } \
- inline void operator delete(void*, void*) {} \
- inline void* operator new[](std::size_t sizeInBytes) { return idMalloc(sizeInBytes); } \
- inline void operator delete[](void* ptr) { idFree(ptr); } \
- inline void* operator new[](std::size_t, void* ptr) { return ptr; } \
- inline void operator delete[](void*, void*) {}
-
-#include "details/IDMatVec.hpp"
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp b/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp
deleted file mode 100644
index cfb308ee55..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDConfigEigen.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-///@file Configuration for Inverse Dynamics Library with Eigen
-#ifndef INVDYNCONFIG_EIGEN_HPP_
-#define INVDYNCONFIG_EIGEN_HPP_
-#define btInverseDynamics btInverseDynamicsEigen
-#ifdef BT_USE_DOUBLE_PRECISION
-// choose double/single precision version
-typedef double idScalar;
-#else
-typedef float idScalar;
-#endif
-
-// use std::vector for arrays
-#include <vector>
-// this is to make it work with C++2003, otherwise we could do this
-// template <typename T>
-// using idArray = std::vector<T>;
-template <typename T>
-struct idArray
-{
- typedef std::vector<T> type;
-};
-typedef std::vector<int>::size_type idArrayIdx;
-// default to standard malloc/free
-#include <cstdlib>
-#define ID_DECLARE_ALIGNED_ALLOCATOR() EIGEN_MAKE_ALIGNED_OPERATOR_NEW
-// Note on interfaces:
-// Eigen::Matrix has data(), to get c-array storage
-// HOWEVER: default storage is column-major!
-#define ID_LINEAR_MATH_USE_EIGEN
-#include "Eigen/Eigen"
-#include "details/IDEigenInterface.hpp"
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp b/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp
deleted file mode 100644
index 5a98f01498..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDErrorMessages.hpp
+++ /dev/null
@@ -1,31 +0,0 @@
-///@file error message utility functions
-#ifndef IDUTILS_HPP_
-#define IDUTILS_HPP_
-#include <cstring>
-/// name of file being compiled, without leading path components
-#define __INVDYN_FILE_WO_DIR__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
-
-#if !defined(BT_ID_WO_BULLET) && !defined(BT_USE_INVERSE_DYNAMICS_WITH_BULLET2)
-#include "Bullet3Common/b3Logging.h"
-#define bt_id_error_message(...) b3Error(__VA_ARGS__)
-#define bt_id_warning_message(...) b3Warning(__VA_ARGS__)
-#define id_printf(...) b3Printf(__VA_ARGS__)
-#else // BT_ID_WO_BULLET
-#include <cstdio>
-/// print error message with file/line information
-#define bt_id_error_message(...) \
- do \
- { \
- fprintf(stderr, "[Error:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
- fprintf(stderr, __VA_ARGS__); \
- } while (0)
-/// print warning message with file/line information
-#define bt_id_warning_message(...) \
- do \
- { \
- fprintf(stderr, "[Warning:%s:%d] ", __INVDYN_FILE_WO_DIR__, __LINE__); \
- fprintf(stderr, __VA_ARGS__); \
- } while (0)
-#define id_printf(...) printf(__VA_ARGS__)
-#endif // BT_ID_WO_BULLET
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp b/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp
deleted file mode 100644
index 2f120ed489..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDMath.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-#include "IDMath.hpp"
-
-#include <cmath>
-#include <limits>
-
-namespace btInverseDynamics
-{
-static const idScalar kIsZero = 5 * std::numeric_limits<idScalar>::epsilon();
-// requirements for axis length deviation from 1.0
-// experimentally set from random euler angle rotation matrices
-static const idScalar kAxisLengthEpsilon = 10 * kIsZero;
-
-void setZero(vec3 &v)
-{
- v(0) = 0;
- v(1) = 0;
- v(2) = 0;
-}
-
-void setZero(vecx &v)
-{
- for (int i = 0; i < v.size(); i++)
- {
- v(i) = 0;
- }
-}
-
-void setZero(mat33 &m)
-{
- m(0, 0) = 0;
- m(0, 1) = 0;
- m(0, 2) = 0;
- m(1, 0) = 0;
- m(1, 1) = 0;
- m(1, 2) = 0;
- m(2, 0) = 0;
- m(2, 1) = 0;
- m(2, 2) = 0;
-}
-
-void skew(vec3 &v, mat33 *result)
-{
- (*result)(0, 0) = 0.0;
- (*result)(0, 1) = -v(2);
- (*result)(0, 2) = v(1);
- (*result)(1, 0) = v(2);
- (*result)(1, 1) = 0.0;
- (*result)(1, 2) = -v(0);
- (*result)(2, 0) = -v(1);
- (*result)(2, 1) = v(0);
- (*result)(2, 2) = 0.0;
-}
-
-idScalar maxAbs(const vecx &v)
-{
- idScalar result = 0.0;
- for (int i = 0; i < v.size(); i++)
- {
- const idScalar tmp = BT_ID_FABS(v(i));
- if (tmp > result)
- {
- result = tmp;
- }
- }
- return result;
-}
-
-idScalar maxAbs(const vec3 &v)
-{
- idScalar result = 0.0;
- for (int i = 0; i < 3; i++)
- {
- const idScalar tmp = BT_ID_FABS(v(i));
- if (tmp > result)
- {
- result = tmp;
- }
- }
- return result;
-}
-
-#if (defined BT_ID_HAVE_MAT3X)
-idScalar maxAbsMat3x(const mat3x &m)
-{
- // only used for tests -- so just loop here for portability
- idScalar result = 0.0;
- for (idArrayIdx col = 0; col < m.cols(); col++)
- {
- for (idArrayIdx row = 0; row < 3; row++)
- {
- result = BT_ID_MAX(result, std::fabs(m(row, col)));
- }
- }
- return result;
-}
-
-void mul(const mat33 &a, const mat3x &b, mat3x *result)
-{
- if (b.cols() != result->cols())
- {
- bt_id_error_message("size missmatch. b.cols()= %d, result->cols()= %d\n",
- static_cast<int>(b.cols()), static_cast<int>(result->cols()));
- abort();
- }
-
- for (idArrayIdx col = 0; col < b.cols(); col++)
- {
- const idScalar x = a(0, 0) * b(0, col) + a(0, 1) * b(1, col) + a(0, 2) * b(2, col);
- const idScalar y = a(1, 0) * b(0, col) + a(1, 1) * b(1, col) + a(1, 2) * b(2, col);
- const idScalar z = a(2, 0) * b(0, col) + a(2, 1) * b(1, col) + a(2, 2) * b(2, col);
- setMat3xElem(0, col, x, result);
- setMat3xElem(1, col, y, result);
- setMat3xElem(2, col, z, result);
- }
-}
-void add(const mat3x &a, const mat3x &b, mat3x *result)
-{
- if (a.cols() != b.cols())
- {
- bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
- static_cast<int>(a.cols()), static_cast<int>(b.cols()));
- abort();
- }
- for (idArrayIdx col = 0; col < b.cols(); col++)
- {
- for (idArrayIdx row = 0; row < 3; row++)
- {
- setMat3xElem(row, col, a(row, col) + b(row, col), result);
- }
- }
-}
-void sub(const mat3x &a, const mat3x &b, mat3x *result)
-{
- if (a.cols() != b.cols())
- {
- bt_id_error_message("size missmatch. a.cols()= %d, b.cols()= %d\n",
- static_cast<int>(a.cols()), static_cast<int>(b.cols()));
- abort();
- }
- for (idArrayIdx col = 0; col < b.cols(); col++)
- {
- for (idArrayIdx row = 0; row < 3; row++)
- {
- setMat3xElem(row, col, a(row, col) - b(row, col), result);
- }
- }
-}
-#endif
-
-mat33 transformX(const idScalar &alpha)
-{
- mat33 T;
- const idScalar cos_alpha = BT_ID_COS(alpha);
- const idScalar sin_alpha = BT_ID_SIN(alpha);
- // [1 0 0]
- // [0 c s]
- // [0 -s c]
- T(0, 0) = 1.0;
- T(0, 1) = 0.0;
- T(0, 2) = 0.0;
-
- T(1, 0) = 0.0;
- T(1, 1) = cos_alpha;
- T(1, 2) = sin_alpha;
-
- T(2, 0) = 0.0;
- T(2, 1) = -sin_alpha;
- T(2, 2) = cos_alpha;
-
- return T;
-}
-
-mat33 transformY(const idScalar &beta)
-{
- mat33 T;
- const idScalar cos_beta = BT_ID_COS(beta);
- const idScalar sin_beta = BT_ID_SIN(beta);
- // [c 0 -s]
- // [0 1 0]
- // [s 0 c]
- T(0, 0) = cos_beta;
- T(0, 1) = 0.0;
- T(0, 2) = -sin_beta;
-
- T(1, 0) = 0.0;
- T(1, 1) = 1.0;
- T(1, 2) = 0.0;
-
- T(2, 0) = sin_beta;
- T(2, 1) = 0.0;
- T(2, 2) = cos_beta;
-
- return T;
-}
-
-mat33 transformZ(const idScalar &gamma)
-{
- mat33 T;
- const idScalar cos_gamma = BT_ID_COS(gamma);
- const idScalar sin_gamma = BT_ID_SIN(gamma);
- // [ c s 0]
- // [-s c 0]
- // [ 0 0 1]
- T(0, 0) = cos_gamma;
- T(0, 1) = sin_gamma;
- T(0, 2) = 0.0;
-
- T(1, 0) = -sin_gamma;
- T(1, 1) = cos_gamma;
- T(1, 2) = 0.0;
-
- T(2, 0) = 0.0;
- T(2, 1) = 0.0;
- T(2, 2) = 1.0;
-
- return T;
-}
-
-mat33 tildeOperator(const vec3 &v)
-{
- mat33 m;
- m(0, 0) = 0.0;
- m(0, 1) = -v(2);
- m(0, 2) = v(1);
- m(1, 0) = v(2);
- m(1, 1) = 0.0;
- m(1, 2) = -v(0);
- m(2, 0) = -v(1);
- m(2, 1) = v(0);
- m(2, 2) = 0.0;
- return m;
-}
-
-void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3 *r, mat33 *T)
-{
- const idScalar sa = BT_ID_SIN(alpha);
- const idScalar ca = BT_ID_COS(alpha);
- const idScalar st = BT_ID_SIN(theta);
- const idScalar ct = BT_ID_COS(theta);
-
- (*r)(0) = a;
- (*r)(1) = -sa * d;
- (*r)(2) = ca * d;
-
- (*T)(0, 0) = ct;
- (*T)(0, 1) = -st;
- (*T)(0, 2) = 0.0;
-
- (*T)(1, 0) = st * ca;
- (*T)(1, 1) = ct * ca;
- (*T)(1, 2) = -sa;
-
- (*T)(2, 0) = st * sa;
- (*T)(2, 1) = ct * sa;
- (*T)(2, 2) = ca;
-}
-
-void bodyTParentFromAxisAngle(const vec3 &axis, const idScalar &angle, mat33 *T)
-{
- const idScalar c = BT_ID_COS(angle);
- const idScalar s = -BT_ID_SIN(angle);
- const idScalar one_m_c = 1.0 - c;
-
- const idScalar &x = axis(0);
- const idScalar &y = axis(1);
- const idScalar &z = axis(2);
-
- (*T)(0, 0) = x * x * one_m_c + c;
- (*T)(0, 1) = x * y * one_m_c - z * s;
- (*T)(0, 2) = x * z * one_m_c + y * s;
-
- (*T)(1, 0) = x * y * one_m_c + z * s;
- (*T)(1, 1) = y * y * one_m_c + c;
- (*T)(1, 2) = y * z * one_m_c - x * s;
-
- (*T)(2, 0) = x * z * one_m_c - y * s;
- (*T)(2, 1) = y * z * one_m_c + x * s;
- (*T)(2, 2) = z * z * one_m_c + c;
-}
-
-bool isPositiveDefinite(const mat33 &m)
-{
- // test if all upper left determinants are positive
- if (m(0, 0) <= 0)
- { // upper 1x1
- return false;
- }
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) <= 0)
- { // upper 2x2
- return false;
- }
- if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
- m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
- {
- return false;
- }
- return true;
-}
-
-bool isPositiveSemiDefinite(const mat33 &m)
-{
- // test if all upper left determinants are positive
- if (m(0, 0) < 0)
- { // upper 1x1
- return false;
- }
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < 0)
- { // upper 2x2
- return false;
- }
- if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
- m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < 0)
- {
- return false;
- }
- return true;
-}
-
-bool isPositiveSemiDefiniteFuzzy(const mat33 &m)
-{
- // test if all upper left determinants are positive
- if (m(0, 0) < -kIsZero)
- { // upper 1x1
- return false;
- }
- if (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0) < -kIsZero)
- { // upper 2x2
- return false;
- }
- if ((m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) -
- m(0, 1) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
- m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0))) < -kIsZero)
- {
- return false;
- }
- return true;
-}
-
-idScalar determinant(const mat33 &m)
-{
- return m(0, 0) * m(1, 1) * m(2, 2) + m(0, 1) * m(1, 2) * m(2, 0) + m(0, 2) * m(1, 0) * m(2, 1) -
- m(0, 2) * m(1, 1) * m(2, 0) - m(0, 0) * m(1, 2) * m(2, 1) - m(0, 1) * m(1, 0) * m(2, 2);
-}
-
-bool isValidInertiaMatrix(const mat33 &I, const int index, bool has_fixed_joint)
-{
- // TODO(Thomas) do we really want this?
- // in cases where the inertia tensor about the center of mass is zero,
- // the determinant of the inertia tensor about the joint axis is almost
- // zero and can have a very small negative value.
- if (!isPositiveSemiDefiniteFuzzy(I))
- {
- bt_id_error_message(
- "invalid inertia matrix for body %d, not positive definite "
- "(fixed joint)\n",
- index);
- bt_id_error_message(
- "matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
-
- return false;
- }
-
- // check triangle inequality, must have I(i,i)+I(j,j)>=I(k,k)
- if (!has_fixed_joint)
- {
- if (I(0, 0) + I(1, 1) < I(2, 2))
- {
- bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
- bt_id_error_message(
- "matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
- return false;
- }
- if (I(0, 0) + I(1, 1) < I(2, 2))
- {
- bt_id_error_message("invalid inertia tensor for body %d, I(0,0) + I(1,1) < I(2,2)\n", index);
- bt_id_error_message(
- "matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
- return false;
- }
- if (I(1, 1) + I(2, 2) < I(0, 0))
- {
- bt_id_error_message("invalid inertia tensor for body %d, I(1,1) + I(2,2) < I(0,0)\n", index);
- bt_id_error_message(
- "matrix is:\n"
- "[%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e;\n"
- "%.20e %.20e %.20e]\n",
- I(0, 0), I(0, 1), I(0, 2), I(1, 0), I(1, 1), I(1, 2), I(2, 0), I(2, 1),
- I(2, 2));
- return false;
- }
- }
- // check positive/zero diagonal elements
- for (int i = 0; i < 3; i++)
- {
- if (I(i, i) < 0)
- { // accept zero
- bt_id_error_message("invalid inertia tensor, I(%d,%d)= %e <0\n", i, i, I(i, i));
- return false;
- }
- }
- // check symmetry
- if (BT_ID_FABS(I(1, 0) - I(0, 1)) > kIsZero)
- {
- bt_id_error_message(
- "invalid inertia tensor for body %d I(1,0)!=I(0,1). I(1,0)-I(0,1)= "
- "%e\n",
- index, I(1, 0) - I(0, 1));
- return false;
- }
- if (BT_ID_FABS(I(2, 0) - I(0, 2)) > kIsZero)
- {
- bt_id_error_message(
- "invalid inertia tensor for body %d I(2,0)!=I(0,2). I(2,0)-I(0,2)= "
- "%e\n",
- index, I(2, 0) - I(0, 2));
- return false;
- }
- if (BT_ID_FABS(I(1, 2) - I(2, 1)) > kIsZero)
- {
- bt_id_error_message("invalid inertia tensor body %d I(1,2)!=I(2,1). I(1,2)-I(2,1)= %e\n", index,
- I(1, 2) - I(2, 1));
- return false;
- }
- return true;
-}
-
-bool isValidTransformMatrix(const mat33 &m)
-{
-#define print_mat(x) \
- bt_id_error_message("matrix is [%e, %e, %e; %e, %e, %e; %e, %e, %e]\n", x(0, 0), x(0, 1), x(0, 2), \
- x(1, 0), x(1, 1), x(1, 2), x(2, 0), x(2, 1), x(2, 2))
-
- // check for unit length column vectors
- for (int i = 0; i < 3; i++)
- {
- const idScalar length_minus_1 =
- BT_ID_FABS(m(0, i) * m(0, i) + m(1, i) * m(1, i) + m(2, i) * m(2, i) - 1.0);
- if (length_minus_1 > kAxisLengthEpsilon)
- {
- bt_id_error_message(
- "Not a valid rotation matrix (column %d not unit length)\n"
- "column = [%.18e %.18e %.18e]\n"
- "length-1.0= %.18e\n",
- i, m(0, i), m(1, i), m(2, i), length_minus_1);
- print_mat(m);
- return false;
- }
- }
- // check for orthogonal column vectors
- if (BT_ID_FABS(m(0, 0) * m(0, 1) + m(1, 0) * m(1, 1) + m(2, 0) * m(2, 1)) > kAxisLengthEpsilon)
- {
- bt_id_error_message("Not a valid rotation matrix (columns 0 and 1 not orthogonal)\n");
- print_mat(m);
- return false;
- }
- if (BT_ID_FABS(m(0, 0) * m(0, 2) + m(1, 0) * m(1, 2) + m(2, 0) * m(2, 2)) > kAxisLengthEpsilon)
- {
- bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
- print_mat(m);
- return false;
- }
- if (BT_ID_FABS(m(0, 1) * m(0, 2) + m(1, 1) * m(1, 2) + m(2, 1) * m(2, 2)) > kAxisLengthEpsilon)
- {
- bt_id_error_message("Not a valid rotation matrix (columns 0 and 2 not orthogonal)\n");
- print_mat(m);
- return false;
- }
- // check determinant (rotation not reflection)
- if (determinant(m) <= 0)
- {
- bt_id_error_message("Not a valid rotation matrix (determinant <=0)\n");
- print_mat(m);
- return false;
- }
- return true;
-}
-
-bool isUnitVector(const vec3 &vector)
-{
- return BT_ID_FABS(vector(0) * vector(0) + vector(1) * vector(1) + vector(2) * vector(2) - 1.0) <
- kIsZero;
-}
-
-vec3 rpyFromMatrix(const mat33 &rot)
-{
- vec3 rpy;
- rpy(2) = BT_ID_ATAN2(-rot(1, 0), rot(0, 0));
- rpy(1) = BT_ID_ATAN2(rot(2, 0), BT_ID_COS(rpy(2)) * rot(0, 0) - BT_ID_SIN(rpy(0)) * rot(1, 0));
- rpy(0) = BT_ID_ATAN2(-rot(2, 0), rot(2, 2));
- return rpy;
-}
-} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp b/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp
deleted file mode 100644
index 40bee5302b..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/IDMath.hpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/// @file Math utility functions used in inverse dynamics library.
-/// Defined here as they may not be provided by the math library.
-
-#ifndef IDMATH_HPP_
-#define IDMATH_HPP_
-#include "IDConfig.hpp"
-
-namespace btInverseDynamics
-{
-/// set all elements to zero
-void setZero(vec3& v);
-/// set all elements to zero
-void setZero(vecx& v);
-/// set all elements to zero
-void setZero(mat33& m);
-/// create a skew symmetric matrix from a vector (useful for cross product abstraction, e.g. v x a = V * a)
-void skew(vec3& v, mat33* result);
-/// return maximum absolute value
-idScalar maxAbs(const vecx& v);
-#ifndef ID_LINEAR_MATH_USE_EIGEN
-/// return maximum absolute value
-idScalar maxAbs(const vec3& v);
-#endif //ID_LINEAR_MATH_USE_EIGEN
-
-#if (defined BT_ID_HAVE_MAT3X)
-idScalar maxAbsMat3x(const mat3x& m);
-void setZero(mat3x& m);
-// define math functions on mat3x here to avoid allocations in operators.
-void mul(const mat33& a, const mat3x& b, mat3x* result);
-void add(const mat3x& a, const mat3x& b, mat3x* result);
-void sub(const mat3x& a, const mat3x& b, mat3x* result);
-#endif
-
-/// get offset vector & transform matrix from DH parameters
-/// TODO: add documentation
-void getVecMatFromDH(idScalar theta, idScalar d, idScalar a, idScalar alpha, vec3* r, mat33* T);
-
-/// Check if a 3x3 matrix is positive definite
-/// @param m a 3x3 matrix
-/// @return true if m>0, false otherwise
-bool isPositiveDefinite(const mat33& m);
-
-/// Check if a 3x3 matrix is positive semi definite
-/// @param m a 3x3 matrix
-/// @return true if m>=0, false otherwise
-bool isPositiveSemiDefinite(const mat33& m);
-/// Check if a 3x3 matrix is positive semi definite within numeric limits
-/// @param m a 3x3 matrix
-/// @return true if m>=-eps, false otherwise
-bool isPositiveSemiDefiniteFuzzy(const mat33& m);
-
-/// Determinant of 3x3 matrix
-/// NOTE: implemented here for portability, as determinant operation
-/// will be implemented differently for various matrix/vector libraries
-/// @param m a 3x3 matrix
-/// @return det(m)
-idScalar determinant(const mat33& m);
-
-/// Test if a 3x3 matrix satisfies some properties of inertia matrices
-/// @param I a 3x3 matrix
-/// @param index body index (for error messages)
-/// @param has_fixed_joint: if true, positive semi-definite matrices are accepted
-/// @return true if I satisfies inertia matrix properties, false otherwise.
-bool isValidInertiaMatrix(const mat33& I, int index, bool has_fixed_joint);
-
-/// Check if a 3x3 matrix is a valid transform (rotation) matrix
-/// @param m a 3x3 matrix
-/// @return true if m is a rotation matrix, false otherwise
-bool isValidTransformMatrix(const mat33& m);
-/// Transform matrix from parent to child frame,
-/// when the child frame is rotated about @param axis by @angle
-/// (mathematically positive)
-/// @param axis the axis of rotation
-/// @param angle rotation angle
-/// @param T pointer to transform matrix
-void bodyTParentFromAxisAngle(const vec3& axis, const idScalar& angle, mat33* T);
-
-/// Check if this is a unit vector
-/// @param vector
-/// @return true if |vector|=1 within numeric limits
-bool isUnitVector(const vec3& vector);
-
-/// @input a vector in R^3
-/// @returns corresponding spin tensor
-mat33 tildeOperator(const vec3& v);
-/// @param alpha angle in radians
-/// @returns transform matrix for ratation with @param alpha about x-axis
-mat33 transformX(const idScalar& alpha);
-/// @param beta angle in radians
-/// @returns transform matrix for ratation with @param beta about y-axis
-mat33 transformY(const idScalar& beta);
-/// @param gamma angle in radians
-/// @returns transform matrix for ratation with @param gamma about z-axis
-mat33 transformZ(const idScalar& gamma);
-///calculate rpy angles (x-y-z Euler angles) from a given rotation matrix
-/// @param rot rotation matrix
-/// @returns x-y-z Euler angles
-vec3 rpyFromMatrix(const mat33& rot);
-} // namespace btInverseDynamics
-#endif // IDMATH_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
deleted file mode 100644
index 9326b0d098..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.cpp
+++ /dev/null
@@ -1,548 +0,0 @@
-#include "MultiBodyTree.hpp"
-
-#include <cmath>
-#include <limits>
-#include <vector>
-
-#include "IDMath.hpp"
-#include "details/MultiBodyTreeImpl.hpp"
-#include "details/MultiBodyTreeInitCache.hpp"
-
-namespace btInverseDynamics
-{
-MultiBodyTree::MultiBodyTree()
- : m_is_finalized(false),
- m_mass_parameters_are_valid(true),
- m_accept_invalid_mass_parameters(false),
- m_impl(0x0),
- m_init_cache(0x0)
-{
- m_init_cache = new InitCache();
-}
-
-MultiBodyTree::~MultiBodyTree()
-{
- delete m_impl;
- delete m_init_cache;
-}
-
-void MultiBodyTree::setAcceptInvalidMassParameters(bool flag)
-{
- m_accept_invalid_mass_parameters = flag;
-}
-
-bool MultiBodyTree::getAcceptInvalidMassProperties() const
-{
- return m_accept_invalid_mass_parameters;
-}
-
-int MultiBodyTree::getBodyOrigin(const int body_index, vec3 *world_origin) const
-{
- return m_impl->getBodyOrigin(body_index, world_origin);
-}
-
-int MultiBodyTree::getBodyCoM(const int body_index, vec3 *world_com) const
-{
- return m_impl->getBodyCoM(body_index, world_com);
-}
-
-int MultiBodyTree::getBodyTransform(const int body_index, mat33 *world_T_body) const
-{
- return m_impl->getBodyTransform(body_index, world_T_body);
-}
-int MultiBodyTree::getBodyAngularVelocity(const int body_index, vec3 *world_omega) const
-{
- return m_impl->getBodyAngularVelocity(body_index, world_omega);
-}
-int MultiBodyTree::getBodyLinearVelocity(const int body_index, vec3 *world_velocity) const
-{
- return m_impl->getBodyLinearVelocity(body_index, world_velocity);
-}
-
-int MultiBodyTree::getBodyLinearVelocityCoM(const int body_index, vec3 *world_velocity) const
-{
- return m_impl->getBodyLinearVelocityCoM(body_index, world_velocity);
-}
-
-int MultiBodyTree::getBodyAngularAcceleration(const int body_index, vec3 *world_dot_omega) const
-{
- return m_impl->getBodyAngularAcceleration(body_index, world_dot_omega);
-}
-int MultiBodyTree::getBodyLinearAcceleration(const int body_index, vec3 *world_acceleration) const
-{
- return m_impl->getBodyLinearAcceleration(body_index, world_acceleration);
-}
-
-int MultiBodyTree::getParentRParentBodyRef(const int body_index, vec3 *r) const
-{
- return m_impl->getParentRParentBodyRef(body_index, r);
-}
-
-int MultiBodyTree::getBodyTParentRef(const int body_index, mat33 *T) const
-{
- return m_impl->getBodyTParentRef(body_index, T);
-}
-
-int MultiBodyTree::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
-{
- return m_impl->getBodyAxisOfMotion(body_index, axis);
-}
-
-void MultiBodyTree::printTree() { m_impl->printTree(); }
-void MultiBodyTree::printTreeData() { m_impl->printTreeData(); }
-
-int MultiBodyTree::numBodies() const { return m_impl->m_num_bodies; }
-
-int MultiBodyTree::numDoFs() const { return m_impl->m_num_dofs; }
-
-int MultiBodyTree::calculateInverseDynamics(const vecx &q, const vecx &u, const vecx &dot_u,
- vecx *joint_forces)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateInverseDynamics(q, u, dot_u, joint_forces))
- {
- bt_id_error_message("error in inverse dynamics calculation\n");
- return -1;
- }
- return 0;
-}
-
-int MultiBodyTree::calculateMassMatrix(const vecx &q, const bool update_kinematics,
- const bool initialize_matrix,
- const bool set_lower_triangular_matrix, matxx *mass_matrix)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 ==
- m_impl->calculateMassMatrix(q, update_kinematics, initialize_matrix,
- set_lower_triangular_matrix, mass_matrix))
- {
- bt_id_error_message("error in mass matrix calculation\n");
- return -1;
- }
- return 0;
-}
-
-int MultiBodyTree::calculateMassMatrix(const vecx &q, matxx *mass_matrix)
-{
- return calculateMassMatrix(q, true, true, true, mass_matrix);
-}
-
-int MultiBodyTree::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u)
-{
- vec3 world_gravity(m_impl->m_world_gravity);
- // temporarily set gravity to zero, to ensure we get the actual accelerations
- setZero(m_impl->m_world_gravity);
-
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateKinematics(q, u, dot_u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY_ACCELERATION))
- {
- bt_id_error_message("error in kinematics calculation\n");
- return -1;
- }
-
- m_impl->m_world_gravity = world_gravity;
- return 0;
-}
-
-int MultiBodyTree::calculatePositionKinematics(const vecx &q)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateKinematics(q, q, q,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
- {
- bt_id_error_message("error in kinematics calculation\n");
- return -1;
- }
- return 0;
-}
-
-int MultiBodyTree::calculatePositionAndVelocityKinematics(const vecx &q, const vecx &u)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateKinematics(q, u, u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
- {
- bt_id_error_message("error in kinematics calculation\n");
- return -1;
- }
- return 0;
-}
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-int MultiBodyTree::calculateJacobians(const vecx &q, const vecx &u)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateJacobians(q, u,
- MultiBodyTree::MultiBodyImpl::POSITION_VELOCITY))
- {
- bt_id_error_message("error in jacobian calculation\n");
- return -1;
- }
- return 0;
-}
-
-int MultiBodyTree::calculateJacobians(const vecx &q)
-{
- if (false == m_is_finalized)
- {
- bt_id_error_message("system has not been initialized\n");
- return -1;
- }
- if (-1 == m_impl->calculateJacobians(q, q,
- MultiBodyTree::MultiBodyImpl::POSITION_ONLY))
- {
- bt_id_error_message("error in jacobian calculation\n");
- return -1;
- }
- return 0;
-}
-
-int MultiBodyTree::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
-{
- return m_impl->getBodyDotJacobianTransU(body_index, world_dot_jac_trans_u);
-}
-
-int MultiBodyTree::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
-{
- return m_impl->getBodyDotJacobianRotU(body_index, world_dot_jac_rot_u);
-}
-
-int MultiBodyTree::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
-{
- return m_impl->getBodyJacobianTrans(body_index, world_jac_trans);
-}
-
-int MultiBodyTree::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
-{
- return m_impl->getBodyJacobianRot(body_index, world_jac_rot);
-}
-
-#endif
-
-int MultiBodyTree::addBody(int body_index, int parent_index, JointType joint_type,
- const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
- const vec3 &body_axis_of_motion_, idScalar mass,
- const vec3 &body_r_body_com, const mat33 &body_I_body,
- const int user_int, void *user_ptr)
-{
- if (body_index < 0)
- {
- bt_id_error_message("body index must be positive (got %d)\n", body_index);
- return -1;
- }
- vec3 body_axis_of_motion(body_axis_of_motion_);
- switch (joint_type)
- {
- case REVOLUTE:
- case PRISMATIC:
- // check if axis is unit vector
- if (!isUnitVector(body_axis_of_motion))
- {
- bt_id_warning_message(
- "axis of motion not a unit axis ([%f %f %f]), will use normalized vector\n",
- body_axis_of_motion(0), body_axis_of_motion(1), body_axis_of_motion(2));
- idScalar length = BT_ID_SQRT(BT_ID_POW(body_axis_of_motion(0), 2) +
- BT_ID_POW(body_axis_of_motion(1), 2) +
- BT_ID_POW(body_axis_of_motion(2), 2));
- if (length < BT_ID_SQRT(std::numeric_limits<idScalar>::min()))
- {
- bt_id_error_message("axis of motion vector too short (%e)\n", length);
- return -1;
- }
- body_axis_of_motion = (1.0 / length) * body_axis_of_motion;
- }
- break;
- case FIXED:
- break;
- case FLOATING:
- break;
- case SPHERICAL:
- break;
- default:
- bt_id_error_message("unknown joint type %d\n", joint_type);
- return -1;
- }
-
- // sanity check for mass properties. Zero mass is OK.
- if (mass < 0)
- {
- m_mass_parameters_are_valid = false;
- bt_id_error_message("Body %d has invalid mass %e\n", body_index, mass);
- if (!m_accept_invalid_mass_parameters)
- {
- return -1;
- }
- }
-
- if (!isValidInertiaMatrix(body_I_body, body_index, FIXED == joint_type))
- {
- m_mass_parameters_are_valid = false;
- // error message printed in function call
- if (!m_accept_invalid_mass_parameters)
- {
- return -1;
- }
- }
-
- if (!isValidTransformMatrix(body_T_parent_ref))
- {
- return -1;
- }
-
- return m_init_cache->addBody(body_index, parent_index, joint_type, parent_r_parent_body_ref,
- body_T_parent_ref, body_axis_of_motion, mass, body_r_body_com,
- body_I_body, user_int, user_ptr);
-}
-
-int MultiBodyTree::getParentIndex(const int body_index, int *parent_index) const
-{
- return m_impl->getParentIndex(body_index, parent_index);
-}
-
-int MultiBodyTree::getUserInt(const int body_index, int *user_int) const
-{
- return m_impl->getUserInt(body_index, user_int);
-}
-
-int MultiBodyTree::getUserPtr(const int body_index, void **user_ptr) const
-{
- return m_impl->getUserPtr(body_index, user_ptr);
-}
-
-int MultiBodyTree::setUserInt(const int body_index, const int user_int)
-{
- return m_impl->setUserInt(body_index, user_int);
-}
-
-int MultiBodyTree::setUserPtr(const int body_index, void *const user_ptr)
-{
- return m_impl->setUserPtr(body_index, user_ptr);
-}
-
-int MultiBodyTree::finalize()
-{
- const int &num_bodies = m_init_cache->numBodies();
- const int &num_dofs = m_init_cache->numDoFs();
-
- if (num_dofs < 0)
- {
- bt_id_error_message("Need num_dofs>=1, but num_dofs= %d\n", num_dofs);
- //return -1;
- }
-
- // 1 allocate internal MultiBody structure
- m_impl = new MultiBodyImpl(num_bodies, num_dofs);
-
- // 2 build new index set assuring index(parent) < index(child)
- if (-1 == m_init_cache->buildIndexSets())
- {
- return -1;
- }
- m_init_cache->getParentIndexArray(&m_impl->m_parent_index);
-
- // 3 setup internal kinematic and dynamic data
- for (int index = 0; index < num_bodies; index++)
- {
- InertiaData inertia;
- JointData joint;
- if (-1 == m_init_cache->getInertiaData(index, &inertia))
- {
- return -1;
- }
- if (-1 == m_init_cache->getJointData(index, &joint))
- {
- return -1;
- }
-
- RigidBody &rigid_body = m_impl->m_body_list[index];
-
- rigid_body.m_mass = inertia.m_mass;
- rigid_body.m_body_mass_com = inertia.m_mass * inertia.m_body_pos_body_com;
- rigid_body.m_body_I_body = inertia.m_body_I_body;
- rigid_body.m_joint_type = joint.m_type;
- rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
- rigid_body.m_body_T_parent_ref = joint.m_child_T_parent_ref;
- rigid_body.m_parent_pos_parent_body_ref = joint.m_parent_pos_parent_child_ref;
- rigid_body.m_joint_type = joint.m_type;
-
- int user_int;
- if (-1 == m_init_cache->getUserInt(index, &user_int))
- {
- return -1;
- }
- if (-1 == m_impl->setUserInt(index, user_int))
- {
- return -1;
- }
-
- void *user_ptr;
- if (-1 == m_init_cache->getUserPtr(index, &user_ptr))
- {
- return -1;
- }
- if (-1 == m_impl->setUserPtr(index, user_ptr))
- {
- return -1;
- }
-
- // Set joint Jacobians. Note that the dimension is always 3x1 here to avoid variable sized
- // matrices.
- switch (rigid_body.m_joint_type)
- {
- case REVOLUTE:
- rigid_body.m_Jac_JR(0) = joint.m_child_axis_of_motion(0);
- rigid_body.m_Jac_JR(1) = joint.m_child_axis_of_motion(1);
- rigid_body.m_Jac_JR(2) = joint.m_child_axis_of_motion(2);
- rigid_body.m_Jac_JT(0) = 0.0;
- rigid_body.m_Jac_JT(1) = 0.0;
- rigid_body.m_Jac_JT(2) = 0.0;
- break;
- case PRISMATIC:
- rigid_body.m_Jac_JR(0) = 0.0;
- rigid_body.m_Jac_JR(1) = 0.0;
- rigid_body.m_Jac_JR(2) = 0.0;
- rigid_body.m_Jac_JT(0) = joint.m_child_axis_of_motion(0);
- rigid_body.m_Jac_JT(1) = joint.m_child_axis_of_motion(1);
- rigid_body.m_Jac_JT(2) = joint.m_child_axis_of_motion(2);
- break;
- case FIXED:
- // NOTE/TODO: dimension really should be zero ..
- rigid_body.m_Jac_JR(0) = 0.0;
- rigid_body.m_Jac_JR(1) = 0.0;
- rigid_body.m_Jac_JR(2) = 0.0;
- rigid_body.m_Jac_JT(0) = 0.0;
- rigid_body.m_Jac_JT(1) = 0.0;
- rigid_body.m_Jac_JT(2) = 0.0;
- break;
- case SPHERICAL:
- // NOTE/TODO: this is not really correct.
- // the Jacobians should be 3x3 matrices here !
- rigid_body.m_Jac_JR(0) = 0.0;
- rigid_body.m_Jac_JR(1) = 0.0;
- rigid_body.m_Jac_JR(2) = 0.0;
- rigid_body.m_Jac_JT(0) = 0.0;
- rigid_body.m_Jac_JT(1) = 0.0;
- rigid_body.m_Jac_JT(2) = 0.0;
- break;
- case FLOATING:
- // NOTE/TODO: this is not really correct.
- // the Jacobians should be 3x3 matrices here !
- rigid_body.m_Jac_JR(0) = 0.0;
- rigid_body.m_Jac_JR(1) = 0.0;
- rigid_body.m_Jac_JR(2) = 0.0;
- rigid_body.m_Jac_JT(0) = 0.0;
- rigid_body.m_Jac_JT(1) = 0.0;
- rigid_body.m_Jac_JT(2) = 0.0;
- break;
- default:
- bt_id_error_message("unsupported joint type %d\n", rigid_body.m_joint_type);
- return -1;
- }
- }
-
- // 4 assign degree of freedom indices & build per-joint-type index arrays
- if (-1 == m_impl->generateIndexSets())
- {
- bt_id_error_message("generating index sets\n");
- return -1;
- }
-
- // 5 do some pre-computations ..
- m_impl->calculateStaticData();
-
- // 6. make sure all user forces are set to zero, as this might not happen
- // in the vector ctors.
- m_impl->clearAllUserForcesAndMoments();
-
- m_is_finalized = true;
- return 0;
-}
-
-int MultiBodyTree::setGravityInWorldFrame(const vec3 &gravity)
-{
- return m_impl->setGravityInWorldFrame(gravity);
-}
-
-int MultiBodyTree::getJointType(const int body_index, JointType *joint_type) const
-{
- return m_impl->getJointType(body_index, joint_type);
-}
-
-int MultiBodyTree::getJointTypeStr(const int body_index, const char **joint_type) const
-{
- return m_impl->getJointTypeStr(body_index, joint_type);
-}
-
-int MultiBodyTree::getDoFOffset(const int body_index, int *q_offset) const
-{
- return m_impl->getDoFOffset(body_index, q_offset);
-}
-
-int MultiBodyTree::setBodyMass(const int body_index, idScalar mass)
-{
- return m_impl->setBodyMass(body_index, mass);
-}
-
-int MultiBodyTree::setBodyFirstMassMoment(const int body_index, const vec3 &first_mass_moment)
-{
- return m_impl->setBodyFirstMassMoment(body_index, first_mass_moment);
-}
-
-int MultiBodyTree::setBodySecondMassMoment(const int body_index, const mat33 &second_mass_moment)
-{
- return m_impl->setBodySecondMassMoment(body_index, second_mass_moment);
-}
-
-int MultiBodyTree::getBodyMass(const int body_index, idScalar *mass) const
-{
- return m_impl->getBodyMass(body_index, mass);
-}
-
-int MultiBodyTree::getBodyFirstMassMoment(const int body_index, vec3 *first_mass_moment) const
-{
- return m_impl->getBodyFirstMassMoment(body_index, first_mass_moment);
-}
-
-int MultiBodyTree::getBodySecondMassMoment(const int body_index, mat33 *second_mass_moment) const
-{
- return m_impl->getBodySecondMassMoment(body_index, second_mass_moment);
-}
-
-void MultiBodyTree::clearAllUserForcesAndMoments() { m_impl->clearAllUserForcesAndMoments(); }
-
-int MultiBodyTree::addUserForce(const int body_index, const vec3 &body_force)
-{
- return m_impl->addUserForce(body_index, body_force);
-}
-
-int MultiBodyTree::addUserMoment(const int body_index, const vec3 &body_moment)
-{
- return m_impl->addUserMoment(body_index, body_moment);
-}
-
-} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp b/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp
deleted file mode 100644
index 7b852f976c..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/MultiBodyTree.hpp
+++ /dev/null
@@ -1,367 +0,0 @@
-#ifndef MULTIBODYTREE_HPP_
-#define MULTIBODYTREE_HPP_
-
-#include "IDConfig.hpp"
-#include "IDMath.hpp"
-
-namespace btInverseDynamics
-{
-/// Enumeration of supported joint types
-enum JointType
-{
- /// no degree of freedom, moves with parent
- FIXED = 0,
- /// one rotational degree of freedom relative to parent
- REVOLUTE,
- /// one translational degree of freedom relative to parent
- PRISMATIC,
- /// six degrees of freedom relative to parent
- FLOATING,
- /// three degrees of freedom, relative to parent
- SPHERICAL
-};
-
-/// Interface class for calculating inverse dynamics for tree structured
-/// multibody systems
-///
-/// Note on degrees of freedom
-/// The q vector contains the generalized coordinate set defining the tree's configuration.
-/// Every joint adds elements that define the corresponding link's frame pose relative to
-/// its parent. For the joint types that is:
-/// - FIXED: none
-/// - REVOLUTE: angle of rotation [rad]
-/// - PRISMATIC: displacement [m]
-/// - FLOATING: Euler x-y-z angles [rad] and displacement in body-fixed frame of parent [m]
-/// (in that order)
-/// - SPHERICAL: Euler x-y-z angles [rad]
-/// The u vector contains the generalized speeds, which are
-/// - FIXED: none
-/// - REVOLUTE: time derivative of angle of rotation [rad/s]
-/// - PRISMATIC: time derivative of displacement [m/s]
-/// - FLOATING: angular velocity [rad/s] (*not* time derivative of rpy angles)
-/// and time derivative of displacement in parent frame [m/s]
-// - SPHERICAL: angular velocity [rad/s]
-///
-/// The q and u vectors are obtained by stacking contributions of all bodies in one
-/// vector in the order of body indices.
-///
-/// Note on generalized forces: analogous to u, i.e.,
-/// - FIXED: none
-/// - REVOLUTE: moment [Nm], about joint axis
-/// - PRISMATIC: force [N], along joint axis
-/// - FLOATING: moment vector [Nm] and force vector [N], both in body-fixed frame
-/// (in that order)
-/// - SPHERICAL: moment vector [Nm]
-/// TODO - force element interface (friction, springs, dampers, etc)
-/// - gears and motor inertia
-class MultiBodyTree
-{
-public:
- ID_DECLARE_ALIGNED_ALLOCATOR();
- /// The contructor.
- /// Initialization & allocation is via addBody and buildSystem calls.
- MultiBodyTree();
- /// the destructor. This also deallocates all memory
- ~MultiBodyTree();
-
- /// Add body to the system. this allocates memory and not real-time safe.
- /// This only adds the data to an initial cache. After all bodies have been
- /// added,
- /// the system is setup using the buildSystem call
- /// @param body_index index of the body to be added. Must >=0, <number of bodies,
- /// and index of parent must be < index of body
- /// @param parent_index index of the parent body
- /// The root of the tree has index 0 and its parent (the world frame)
- /// is assigned index -1
- /// the rotation and translation relative to the parent are taken as
- /// pose of the root body relative to the world frame. Other parameters
- /// are ignored
- /// @param JointType type of joint connecting the body to the parent
- /// @param mass the mass of the body
- /// @param body_r_body_com the center of mass of the body relative to and
- /// described in
- /// the body fixed frame, which is located in the joint axis connecting
- /// the body to its parent
- /// @param body_I_body the moment of inertia of the body w.r.t the body-fixed
- /// frame
- /// (ie, the reference point is the origin of the body-fixed frame and
- /// the matrix is written
- /// w.r.t. those unit vectors)
- /// @param parent_r_parent_body_ref position of joint relative to the parent
- /// body's reference frame
- /// for q=0, written in the parent bodies reference frame
- /// @param body_axis_of_motion translation/rotation axis in body-fixed frame.
- /// Ignored for joints that are not revolute or prismatic.
- /// must be a unit vector.
- /// @param body_T_parent_ref transform matrix from parent to body reference
- /// frame for q=0.
- /// This is the matrix transforming a vector represented in the
- /// parent's reference frame into one represented
- /// in this body's reference frame.
- /// ie, if parent_vec is a vector in R^3 whose components are w.r.t to
- /// the parent's reference frame,
- /// then the same vector written w.r.t. this body's frame (for q=0) is
- /// given by
- /// body_vec = parent_R_body_ref * parent_vec
- /// @param user_ptr pointer to user data
- /// @param user_int pointer to user integer
- /// @return 0 on success, -1 on error
- int addBody(int body_index, int parent_index, JointType joint_type,
- const vec3& parent_r_parent_body_ref, const mat33& body_T_parent_ref,
- const vec3& body_axis_of_motion, idScalar mass, const vec3& body_r_body_com,
- const mat33& body_I_body, const int user_int, void* user_ptr);
- /// set policy for invalid mass properties
- /// @param flag if true, invalid mass properties are accepted,
- /// the default is false
- void setAcceptInvalidMassParameters(bool flag);
- /// @return the mass properties policy flag
- bool getAcceptInvalidMassProperties() const;
- /// build internal data structures
- /// call this after all bodies have been added via addBody
- /// @return 0 on success, -1 on error
- int finalize();
- /// pretty print ascii description of tree to stdout
- void printTree();
- /// print tree data to stdout
- void printTreeData();
- /// Calculate joint forces for given generalized state & derivatives.
- /// This also updates kinematic terms computed in calculateKinematics.
- /// If gravity is not set to zero, acceleration terms will contain
- /// gravitational acceleration.
- /// @param q generalized coordinates
- /// @param u generalized velocities. In the general case, u=T(q)*dot(q) and dim(q)>=dim(u)
- /// @param dot_u time derivative of u
- /// @param joint_forces this is where the resulting joint forces will be
- /// stored. dim(joint_forces) = dim(u)
- /// @return 0 on success, -1 on error
- int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
- vecx* joint_forces);
- /// Calculate joint space mass matrix
- /// @param q generalized coordinates
- /// @param initialize_matrix if true, initialize mass matrix with zero.
- /// If mass_matrix is initialized to zero externally and only used
- /// for mass matrix computations for the same system, it is safe to
- /// set this to false.
- /// @param set_lower_triangular_matrix if true, the lower triangular section of mass_matrix
- /// is also populated, otherwise not.
- /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
- /// @return -1 on error, 0 on success
- int calculateMassMatrix(const vecx& q, const bool update_kinematics,
- const bool initialize_matrix, const bool set_lower_triangular_matrix,
- matxx* mass_matrix);
-
- /// Calculate joint space mass matrix.
- /// This version will update kinematics, initialize all mass_matrix elements to zero and
- /// populate all mass matrix entries.
- /// @param q generalized coordinates
- /// @param mass_matrix matrix for storing the output (should be dim(q)xdim(q))
- /// @return -1 on error, 0 on success
- int calculateMassMatrix(const vecx& q, matxx* mass_matrix);
-
- /// Calculates kinematics also calculated in calculateInverseDynamics,
- /// but not dynamics.
- /// This function ensures that correct accelerations are computed that do not
- /// contain gravitational acceleration terms.
- /// Does not calculate Jacobians, but only vector quantities (positions, velocities & accelerations)
- int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u);
- /// Calculate position kinematics
- int calculatePositionKinematics(const vecx& q);
- /// Calculate position and velocity kinematics
- int calculatePositionAndVelocityKinematics(const vecx& q, const vecx& u);
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// Calculate Jacobians (dvel/du), as well as velocity-dependent accelearation components
- /// d(Jacobian)/dt*u
- /// This function assumes that calculateInverseDynamics was called, or calculateKinematics,
- /// or calculatePositionAndVelocityKinematics
- int calculateJacobians(const vecx& q, const vecx& u);
- /// Calculate Jacobians (dvel/du)
- /// This function assumes that calculateInverseDynamics was called, or
- /// one of the calculateKineamtics functions
- int calculateJacobians(const vecx& q);
-#endif // BT_ID_HAVE_MAT3X
-
- /// set gravitational acceleration
- /// the default is [0;0;-9.8] in the world frame
- /// @param gravity the gravitational acceleration in world frame
- /// @return 0 on success, -1 on error
- int setGravityInWorldFrame(const vec3& gravity);
- /// returns number of bodies in tree
- int numBodies() const;
- /// returns number of mechanical degrees of freedom (dimension of q-vector)
- int numDoFs() const;
- /// get origin of a body-fixed frame, represented in world frame
- /// @param body_index index for frame/body
- /// @param world_origin pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyOrigin(const int body_index, vec3* world_origin) const;
- /// get center of mass of a body, represented in world frame
- /// @param body_index index for frame/body
- /// @param world_com pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyCoM(const int body_index, vec3* world_com) const;
- /// get transform from of a body-fixed frame to the world frame
- /// @param body_index index for frame/body
- /// @param world_T_body pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyTransform(const int body_index, mat33* world_T_body) const;
- /// get absolute angular velocity for a body, represented in the world frame
- /// @param body_index index for frame/body
- /// @param world_omega pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
- /// get linear velocity of a body, represented in world frame
- /// @param body_index index for frame/body
- /// @param world_velocity pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
- /// get linear velocity of a body's CoM, represented in world frame
- /// (not required for inverse dynamics, provided for convenience)
- /// @param body_index index for frame/body
- /// @param world_vel_com pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
- /// get origin of a body-fixed frame, represented in world frame
- /// @param body_index index for frame/body
- /// @param world_origin pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
- /// get origin of a body-fixed frame, represented in world frame
- /// NOTE: this will include the gravitational acceleration, so the actual acceleration is
- /// obtainened by setting gravitational acceleration to zero, or subtracting it.
- /// @param body_index index for frame/body
- /// @param world_origin pointer for return data
- /// @return 0 on success, -1 on error
- int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- // get translational jacobian, in world frame (dworld_velocity/du)
- int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
- // get rotational jacobian, in world frame (dworld_omega/du)
- int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
- // get product of translational jacobian derivative * generatlized velocities
- int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
- // get product of rotational jacobian derivative * generatlized velocities
- int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
-#endif // BT_ID_HAVE_MAT3X
-
- /// returns the (internal) index of body
- /// @param body_index is the index of a body
- /// @param parent_index pointer to where parent index will be stored
- /// @return 0 on success, -1 on error
- int getParentIndex(const int body_index, int* parent_index) const;
- /// get joint type
- /// @param body_index index of the body
- /// @param joint_type the corresponding joint type
- /// @return 0 on success, -1 on failure
- int getJointType(const int body_index, JointType* joint_type) const;
- /// get joint type as string
- /// @param body_index index of the body
- /// @param joint_type string naming the corresponding joint type
- /// @return 0 on success, -1 on failure
- int getJointTypeStr(const int body_index, const char** joint_type) const;
- /// get offset translation to parent body (see addBody)
- /// @param body_index index of the body
- /// @param r the offset translation (see above)
- /// @return 0 on success, -1 on failure
- int getParentRParentBodyRef(const int body_index, vec3* r) const;
- /// get offset rotation to parent body (see addBody)
- /// @param body_index index of the body
- /// @param T the transform (see above)
- /// @return 0 on success, -1 on failure
- int getBodyTParentRef(const int body_index, mat33* T) const;
- /// get axis of motion (see addBody)
- /// @param body_index index of the body
- /// @param axis the axis (see above)
- /// @return 0 on success, -1 on failure
- int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
- /// get offset for degrees of freedom of this body into the q-vector
- /// @param body_index index of the body
- /// @param q_offset offset the q vector
- /// @return -1 on error, 0 on success
- int getDoFOffset(const int body_index, int* q_offset) const;
- /// get user integer. not used by the library.
- /// @param body_index index of the body
- /// @param user_int the user integer
- /// @return 0 on success, -1 on error
- int getUserInt(const int body_index, int* user_int) const;
- /// get user pointer. not used by the library.
- /// @param body_index index of the body
- /// @param user_ptr the user pointer
- /// @return 0 on success, -1 on error
- int getUserPtr(const int body_index, void** user_ptr) const;
- /// set user integer. not used by the library.
- /// @param body_index index of the body
- /// @param user_int the user integer
- /// @return 0 on success, -1 on error
- int setUserInt(const int body_index, const int user_int);
- /// set user pointer. not used by the library.
- /// @param body_index index of the body
- /// @param user_ptr the user pointer
- /// @return 0 on success, -1 on error
- int setUserPtr(const int body_index, void* const user_ptr);
- /// set mass for a body
- /// @param body_index index of the body
- /// @param mass the mass to set
- /// @return 0 on success, -1 on failure
- int setBodyMass(const int body_index, const idScalar mass);
- /// set first moment of mass for a body
- /// (mass * center of mass, in body fixed frame, relative to joint)
- /// @param body_index index of the body
- /// @param first_mass_moment the vector to set
- /// @return 0 on success, -1 on failure
- int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
- /// set second moment of mass for a body
- /// (moment of inertia, in body fixed frame, relative to joint)
- /// @param body_index index of the body
- /// @param second_mass_moment the inertia matrix
- /// @return 0 on success, -1 on failure
- int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
- /// get mass for a body
- /// @param body_index index of the body
- /// @param mass the mass
- /// @return 0 on success, -1 on failure
- int getBodyMass(const int body_index, idScalar* mass) const;
- /// get first moment of mass for a body
- /// (mass * center of mass, in body fixed frame, relative to joint)
- /// @param body_index index of the body
- /// @param first_moment the vector
- /// @return 0 on success, -1 on failure
- int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
- /// get second moment of mass for a body
- /// (moment of inertia, in body fixed frame, relative to joint)
- /// @param body_index index of the body
- /// @param second_mass_moment the inertia matrix
- /// @return 0 on success, -1 on failure
- int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
- /// set all user forces and moments to zero
- void clearAllUserForcesAndMoments();
- /// Add an external force to a body, acting at the origin of the body-fixed frame.
- /// Calls to addUserForce are cumulative. Set the user force and moment to zero
- /// via clearAllUserForcesAndMoments()
- /// @param body_force the force represented in the body-fixed frame of reference
- /// @return 0 on success, -1 on error
- int addUserForce(const int body_index, const vec3& body_force);
- /// Add an external moment to a body.
- /// Calls to addUserMoment are cumulative. Set the user force and moment to zero
- /// via clearAllUserForcesAndMoments()
- /// @param body_moment the moment represented in the body-fixed frame of reference
- /// @return 0 on success, -1 on error
- int addUserMoment(const int body_index, const vec3& body_moment);
-
-private:
- // flag indicating if system has been initialized
- bool m_is_finalized;
- // flag indicating if mass properties are physically valid
- bool m_mass_parameters_are_valid;
- // flag defining if unphysical mass parameters are accepted
- bool m_accept_invalid_mass_parameters;
- // This struct implements the inverse dynamics calculations
- class MultiBodyImpl;
- MultiBodyImpl* m_impl;
- // cache data structure for initialization
- class InitCache;
- InitCache* m_init_cache;
-};
-} // namespace btInverseDynamics
-#endif // MULTIBODYTREE_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp
deleted file mode 100644
index fe4f102513..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDEigenInterface.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef INVDYNEIGENINTERFACE_HPP_
-#define INVDYNEIGENINTERFACE_HPP_
-#include "../IDConfig.hpp"
-namespace btInverseDynamics
-{
-#define BT_ID_HAVE_MAT3X
-
-#ifdef BT_USE_DOUBLE_PRECISION
-typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
-typedef Eigen::Matrix<double, 3, 1, Eigen::DontAlign> vec3;
-typedef Eigen::Matrix<double, 3, 3, Eigen::DontAlign> mat33;
-typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
-typedef Eigen::Matrix<double, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
-#else
-typedef Eigen::Matrix<float, Eigen::Dynamic, 1, Eigen::DontAlign> vecx;
-typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> vec3;
-typedef Eigen::Matrix<float, 3, 3, Eigen::DontAlign> mat33;
-typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> matxx;
-typedef Eigen::Matrix<float, 3, Eigen::Dynamic, Eigen::DontAlign> mat3x;
-#endif
-
-inline void resize(mat3x &m, Eigen::Index size)
-{
- m.resize(3, size);
- m.setZero();
-}
-
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx *m)
-{
- (*m)(row, col) = val;
-}
-
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x *m)
-{
- (*m)(row, col) = val;
-}
-
-} // namespace btInverseDynamics
-#endif // INVDYNEIGENINTERFACE_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp
deleted file mode 100644
index 0c398a3727..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDLinearMathInterface.hpp
+++ /dev/null
@@ -1,202 +0,0 @@
-#ifndef IDLINEARMATHINTERFACE_HPP_
-#define IDLINEARMATHINTERFACE_HPP_
-
-#include <cstdlib>
-
-#include "../IDConfig.hpp"
-
-#include "../../LinearMath/btMatrix3x3.h"
-#include "../../LinearMath/btVector3.h"
-#include "../../LinearMath/btMatrixX.h"
-#define BT_ID_HAVE_MAT3X
-
-namespace btInverseDynamics
-{
-class vec3;
-class vecx;
-class mat33;
-typedef btMatrixX<idScalar> matxx;
-
-class vec3 : public btVector3
-{
-public:
- vec3() : btVector3() {}
- vec3(const btVector3& btv) { *this = btv; }
- idScalar& operator()(int i) { return (*this)[i]; }
- const idScalar& operator()(int i) const { return (*this)[i]; }
- int size() const { return 3; }
- const vec3& operator=(const btVector3& rhs)
- {
- *static_cast<btVector3*>(this) = rhs;
- return *this;
- }
-};
-
-class mat33 : public btMatrix3x3
-{
-public:
- mat33() : btMatrix3x3() {}
- mat33(const btMatrix3x3& btm) { *this = btm; }
- idScalar& operator()(int i, int j) { return (*this)[i][j]; }
- const idScalar& operator()(int i, int j) const { return (*this)[i][j]; }
- const mat33& operator=(const btMatrix3x3& rhs)
- {
- *static_cast<btMatrix3x3*>(this) = rhs;
- return *this;
- }
- friend mat33 operator*(const idScalar& s, const mat33& a);
- friend mat33 operator/(const mat33& a, const idScalar& s);
-};
-
-inline mat33 operator/(const mat33& a, const idScalar& s) { return a * (1.0 / s); }
-
-inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
-
-class vecx : public btVectorX<idScalar>
-{
-public:
- vecx(int size) : btVectorX<idScalar>(size) {}
- const vecx& operator=(const btVectorX<idScalar>& rhs)
- {
- *static_cast<btVectorX<idScalar>*>(this) = rhs;
- return *this;
- }
-
- idScalar& operator()(int i) { return (*this)[i]; }
- const idScalar& operator()(int i) const { return (*this)[i]; }
-
- friend vecx operator*(const vecx& a, const idScalar& s);
- friend vecx operator*(const idScalar& s, const vecx& a);
-
- friend vecx operator+(const vecx& a, const vecx& b);
- friend vecx operator-(const vecx& a, const vecx& b);
- friend vecx operator/(const vecx& a, const idScalar& s);
-};
-
-inline vecx operator*(const vecx& a, const idScalar& s)
-{
- vecx result(a.size());
- for (int i = 0; i < result.size(); i++)
- {
- result(i) = a(i) * s;
- }
- return result;
-}
-inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
-inline vecx operator+(const vecx& a, const vecx& b)
-{
- vecx result(a.size());
- // TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size())
- {
- bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
- abort();
- }
- for (int i = 0; i < a.size(); i++)
- {
- result(i) = a(i) + b(i);
- }
-
- return result;
-}
-
-inline vecx operator-(const vecx& a, const vecx& b)
-{
- vecx result(a.size());
- // TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size())
- {
- bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
- abort();
- }
- for (int i = 0; i < a.size(); i++)
- {
- result(i) = a(i) - b(i);
- }
- return result;
-}
-inline vecx operator/(const vecx& a, const idScalar& s)
-{
- vecx result(a.size());
- for (int i = 0; i < result.size(); i++)
- {
- result(i) = a(i) / s;
- }
-
- return result;
-}
-
-// use btMatrixX to implement 3xX matrix
-class mat3x : public matxx
-{
-public:
- mat3x() {}
- mat3x(const mat3x& rhs)
- {
- matxx::resize(rhs.rows(), rhs.cols());
- *this = rhs;
- }
- mat3x(int rows, int cols) : matxx(3, cols)
- {
- }
- void operator=(const mat3x& rhs)
- {
- if (m_cols != rhs.m_cols)
- {
- bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
- abort();
- }
- for (int i = 0; i < rows(); i++)
- {
- for (int k = 0; k < cols(); k++)
- {
- setElem(i, k, rhs(i, k));
- }
- }
- }
- void setZero()
- {
- matxx::setZero();
- }
-};
-
-inline vec3 operator*(const mat3x& a, const vecx& b)
-{
- vec3 result;
- if (a.cols() != b.size())
- {
- bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
- abort();
- }
- result(0) = 0.0;
- result(1) = 0.0;
- result(2) = 0.0;
- for (int i = 0; i < b.size(); i++)
- {
- for (int k = 0; k < 3; k++)
- {
- result(k) += a(k, i) * b(i);
- }
- }
- return result;
-}
-
-inline void resize(mat3x& m, idArrayIdx size)
-{
- m.resize(3, size);
- m.setZero();
-}
-
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
-{
- m->setElem(row, col, val);
-}
-
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
-{
- m->setElem(row, col, val);
-}
-
-} // namespace btInverseDynamics
-
-#endif // IDLINEARMATHINTERFACE_HPP_
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp b/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp
deleted file mode 100644
index 1c786095e7..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/IDMatVec.hpp
+++ /dev/null
@@ -1,489 +0,0 @@
-/// @file Built-In Matrix-Vector functions
-#ifndef IDMATVEC_HPP_
-#define IDMATVEC_HPP_
-
-#include <cstdlib>
-
-#include "../IDConfig.hpp"
-#define BT_ID_HAVE_MAT3X
-
-namespace btInverseDynamics
-{
-class vec3;
-class vecx;
-class mat33;
-class matxx;
-class mat3x;
-
-/// This is a very basic implementation to enable stand-alone use of the library.
-/// The implementation is not really optimized and misses many features that you would
-/// want from a "fully featured" linear math library.
-class vec3
-{
-public:
- idScalar& operator()(int i) { return m_data[i]; }
- const idScalar& operator()(int i) const { return m_data[i]; }
- const int size() const { return 3; }
- const vec3& operator=(const vec3& rhs);
- const vec3& operator+=(const vec3& b);
- const vec3& operator-=(const vec3& b);
- vec3 cross(const vec3& b) const;
- idScalar dot(const vec3& b) const;
-
- friend vec3 operator*(const mat33& a, const vec3& b);
- friend vec3 operator*(const vec3& a, const idScalar& s);
- friend vec3 operator*(const idScalar& s, const vec3& a);
-
- friend vec3 operator+(const vec3& a, const vec3& b);
- friend vec3 operator-(const vec3& a, const vec3& b);
- friend vec3 operator/(const vec3& a, const idScalar& s);
-
-private:
- idScalar m_data[3];
-};
-
-class mat33
-{
-public:
- idScalar& operator()(int i, int j) { return m_data[3 * i + j]; }
- const idScalar& operator()(int i, int j) const { return m_data[3 * i + j]; }
- const mat33& operator=(const mat33& rhs);
- mat33 transpose() const;
- const mat33& operator+=(const mat33& b);
- const mat33& operator-=(const mat33& b);
-
- friend mat33 operator*(const mat33& a, const mat33& b);
- friend vec3 operator*(const mat33& a, const vec3& b);
- friend mat33 operator*(const mat33& a, const idScalar& s);
- friend mat33 operator*(const idScalar& s, const mat33& a);
- friend mat33 operator+(const mat33& a, const mat33& b);
- friend mat33 operator-(const mat33& a, const mat33& b);
- friend mat33 operator/(const mat33& a, const idScalar& s);
-
-private:
- // layout is [0,1,2;3,4,5;6,7,8]
- idScalar m_data[9];
-};
-
-class vecx
-{
-public:
- vecx(int size) : m_size(size)
- {
- m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * size));
- }
- ~vecx() { idFree(m_data); }
- const vecx& operator=(const vecx& rhs);
- idScalar& operator()(int i) { return m_data[i]; }
- const idScalar& operator()(int i) const { return m_data[i]; }
- const int& size() const { return m_size; }
-
- friend vecx operator*(const vecx& a, const idScalar& s);
- friend vecx operator*(const idScalar& s, const vecx& a);
-
- friend vecx operator+(const vecx& a, const vecx& b);
- friend vecx operator-(const vecx& a, const vecx& b);
- friend vecx operator/(const vecx& a, const idScalar& s);
-
-private:
- int m_size;
- idScalar* m_data;
-};
-
-class matxx
-{
-public:
- matxx()
- {
- m_data = 0x0;
- m_cols = 0;
- m_rows = 0;
- }
- matxx(int rows, int cols) : m_rows(rows), m_cols(cols)
- {
- m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * rows * cols));
- }
- ~matxx() { idFree(m_data); }
- idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
- const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
- const int& rows() const { return m_rows; }
- const int& cols() const { return m_cols; }
-
-private:
- int m_rows;
- int m_cols;
- idScalar* m_data;
-};
-
-class mat3x
-{
-public:
- mat3x()
- {
- m_data = 0x0;
- m_cols = 0;
- }
- mat3x(const mat3x& rhs)
- {
- m_cols = rhs.m_cols;
- allocate();
- *this = rhs;
- }
- mat3x(int rows, int cols) : m_cols(cols)
- {
- allocate();
- };
- void operator=(const mat3x& rhs)
- {
- if (m_cols != rhs.m_cols)
- {
- bt_id_error_message("size missmatch, cols= %d but rhs.cols= %d\n", cols(), rhs.cols());
- abort();
- }
- for (int i = 0; i < 3 * m_cols; i++)
- {
- m_data[i] = rhs.m_data[i];
- }
- }
-
- ~mat3x()
- {
- free();
- }
- idScalar& operator()(int row, int col) { return m_data[row * m_cols + col]; }
- const idScalar& operator()(int row, int col) const { return m_data[row * m_cols + col]; }
- int rows() const { return m_rows; }
- const int& cols() const { return m_cols; }
- void resize(int rows, int cols)
- {
- m_cols = cols;
- free();
- allocate();
- }
- void setZero()
- {
- memset(m_data, 0x0, sizeof(idScalar) * m_rows * m_cols);
- }
- // avoid operators that would allocate -- use functions sub/add/mul in IDMath.hpp instead
-private:
- void allocate() { m_data = static_cast<idScalar*>(idMalloc(sizeof(idScalar) * m_rows * m_cols)); }
- void free() { idFree(m_data); }
- enum
- {
- m_rows = 3
- };
- int m_cols;
- idScalar* m_data;
-};
-
-inline void resize(mat3x& m, idArrayIdx size)
-{
- m.resize(3, size);
- m.setZero();
-}
-
-//////////////////////////////////////////////////
-// Implementations
-inline const vec3& vec3::operator=(const vec3& rhs)
-{
- if (&rhs != this)
- {
- memcpy(m_data, rhs.m_data, 3 * sizeof(idScalar));
- }
- return *this;
-}
-
-inline vec3 vec3::cross(const vec3& b) const
-{
- vec3 result;
- result.m_data[0] = m_data[1] * b.m_data[2] - m_data[2] * b.m_data[1];
- result.m_data[1] = m_data[2] * b.m_data[0] - m_data[0] * b.m_data[2];
- result.m_data[2] = m_data[0] * b.m_data[1] - m_data[1] * b.m_data[0];
-
- return result;
-}
-
-inline idScalar vec3::dot(const vec3& b) const
-{
- return m_data[0] * b.m_data[0] + m_data[1] * b.m_data[1] + m_data[2] * b.m_data[2];
-}
-
-inline const mat33& mat33::operator=(const mat33& rhs)
-{
- if (&rhs != this)
- {
- memcpy(m_data, rhs.m_data, 9 * sizeof(idScalar));
- }
- return *this;
-}
-inline mat33 mat33::transpose() const
-{
- mat33 result;
- result.m_data[0] = m_data[0];
- result.m_data[1] = m_data[3];
- result.m_data[2] = m_data[6];
- result.m_data[3] = m_data[1];
- result.m_data[4] = m_data[4];
- result.m_data[5] = m_data[7];
- result.m_data[6] = m_data[2];
- result.m_data[7] = m_data[5];
- result.m_data[8] = m_data[8];
-
- return result;
-}
-
-inline mat33 operator*(const mat33& a, const mat33& b)
-{
- mat33 result;
- result.m_data[0] =
- a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[3] + a.m_data[2] * b.m_data[6];
- result.m_data[1] =
- a.m_data[0] * b.m_data[1] + a.m_data[1] * b.m_data[4] + a.m_data[2] * b.m_data[7];
- result.m_data[2] =
- a.m_data[0] * b.m_data[2] + a.m_data[1] * b.m_data[5] + a.m_data[2] * b.m_data[8];
- result.m_data[3] =
- a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[3] + a.m_data[5] * b.m_data[6];
- result.m_data[4] =
- a.m_data[3] * b.m_data[1] + a.m_data[4] * b.m_data[4] + a.m_data[5] * b.m_data[7];
- result.m_data[5] =
- a.m_data[3] * b.m_data[2] + a.m_data[4] * b.m_data[5] + a.m_data[5] * b.m_data[8];
- result.m_data[6] =
- a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[3] + a.m_data[8] * b.m_data[6];
- result.m_data[7] =
- a.m_data[6] * b.m_data[1] + a.m_data[7] * b.m_data[4] + a.m_data[8] * b.m_data[7];
- result.m_data[8] =
- a.m_data[6] * b.m_data[2] + a.m_data[7] * b.m_data[5] + a.m_data[8] * b.m_data[8];
-
- return result;
-}
-
-inline const mat33& mat33::operator+=(const mat33& b)
-{
- for (int i = 0; i < 9; i++)
- {
- m_data[i] += b.m_data[i];
- }
-
- return *this;
-}
-
-inline const mat33& mat33::operator-=(const mat33& b)
-{
- for (int i = 0; i < 9; i++)
- {
- m_data[i] -= b.m_data[i];
- }
- return *this;
-}
-
-inline vec3 operator*(const mat33& a, const vec3& b)
-{
- vec3 result;
-
- result.m_data[0] =
- a.m_data[0] * b.m_data[0] + a.m_data[1] * b.m_data[1] + a.m_data[2] * b.m_data[2];
- result.m_data[1] =
- a.m_data[3] * b.m_data[0] + a.m_data[4] * b.m_data[1] + a.m_data[5] * b.m_data[2];
- result.m_data[2] =
- a.m_data[6] * b.m_data[0] + a.m_data[7] * b.m_data[1] + a.m_data[8] * b.m_data[2];
-
- return result;
-}
-
-inline const vec3& vec3::operator+=(const vec3& b)
-{
- for (int i = 0; i < 3; i++)
- {
- m_data[i] += b.m_data[i];
- }
- return *this;
-}
-
-inline const vec3& vec3::operator-=(const vec3& b)
-{
- for (int i = 0; i < 3; i++)
- {
- m_data[i] -= b.m_data[i];
- }
- return *this;
-}
-
-inline mat33 operator*(const mat33& a, const idScalar& s)
-{
- mat33 result;
- for (int i = 0; i < 9; i++)
- {
- result.m_data[i] = a.m_data[i] * s;
- }
- return result;
-}
-
-inline mat33 operator*(const idScalar& s, const mat33& a) { return a * s; }
-
-inline vec3 operator*(const vec3& a, const idScalar& s)
-{
- vec3 result;
- for (int i = 0; i < 3; i++)
- {
- result.m_data[i] = a.m_data[i] * s;
- }
- return result;
-}
-inline vec3 operator*(const idScalar& s, const vec3& a) { return a * s; }
-
-inline mat33 operator+(const mat33& a, const mat33& b)
-{
- mat33 result;
- for (int i = 0; i < 9; i++)
- {
- result.m_data[i] = a.m_data[i] + b.m_data[i];
- }
- return result;
-}
-inline vec3 operator+(const vec3& a, const vec3& b)
-{
- vec3 result;
- for (int i = 0; i < 3; i++)
- {
- result.m_data[i] = a.m_data[i] + b.m_data[i];
- }
- return result;
-}
-
-inline mat33 operator-(const mat33& a, const mat33& b)
-{
- mat33 result;
- for (int i = 0; i < 9; i++)
- {
- result.m_data[i] = a.m_data[i] - b.m_data[i];
- }
- return result;
-}
-inline vec3 operator-(const vec3& a, const vec3& b)
-{
- vec3 result;
- for (int i = 0; i < 3; i++)
- {
- result.m_data[i] = a.m_data[i] - b.m_data[i];
- }
- return result;
-}
-
-inline mat33 operator/(const mat33& a, const idScalar& s)
-{
- mat33 result;
- for (int i = 0; i < 9; i++)
- {
- result.m_data[i] = a.m_data[i] / s;
- }
- return result;
-}
-
-inline vec3 operator/(const vec3& a, const idScalar& s)
-{
- vec3 result;
- for (int i = 0; i < 3; i++)
- {
- result.m_data[i] = a.m_data[i] / s;
- }
- return result;
-}
-
-inline const vecx& vecx::operator=(const vecx& rhs)
-{
- if (size() != rhs.size())
- {
- bt_id_error_message("size missmatch, size()= %d but rhs.size()= %d\n", size(), rhs.size());
- abort();
- }
- if (&rhs != this)
- {
- memcpy(m_data, rhs.m_data, rhs.size() * sizeof(idScalar));
- }
- return *this;
-}
-inline vecx operator*(const vecx& a, const idScalar& s)
-{
- vecx result(a.size());
- for (int i = 0; i < result.size(); i++)
- {
- result.m_data[i] = a.m_data[i] * s;
- }
- return result;
-}
-inline vecx operator*(const idScalar& s, const vecx& a) { return a * s; }
-inline vecx operator+(const vecx& a, const vecx& b)
-{
- vecx result(a.size());
- // TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size())
- {
- bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
- abort();
- }
- for (int i = 0; i < a.size(); i++)
- {
- result.m_data[i] = a.m_data[i] + b.m_data[i];
- }
-
- return result;
-}
-inline vecx operator-(const vecx& a, const vecx& b)
-{
- vecx result(a.size());
- // TODO: error handling for a.size() != b.size()??
- if (a.size() != b.size())
- {
- bt_id_error_message("size missmatch. a.size()= %d, b.size()= %d\n", a.size(), b.size());
- abort();
- }
- for (int i = 0; i < a.size(); i++)
- {
- result.m_data[i] = a.m_data[i] - b.m_data[i];
- }
- return result;
-}
-inline vecx operator/(const vecx& a, const idScalar& s)
-{
- vecx result(a.size());
- for (int i = 0; i < result.size(); i++)
- {
- result.m_data[i] = a.m_data[i] / s;
- }
-
- return result;
-}
-
-inline vec3 operator*(const mat3x& a, const vecx& b)
-{
- vec3 result;
- if (a.cols() != b.size())
- {
- bt_id_error_message("size missmatch. a.cols()= %d, b.size()= %d\n", a.cols(), b.size());
- abort();
- }
- result(0) = 0.0;
- result(1) = 0.0;
- result(2) = 0.0;
- for (int i = 0; i < b.size(); i++)
- {
- for (int k = 0; k < 3; k++)
- {
- result(k) += a(k, i) * b(i);
- }
- }
- return result;
-}
-
-inline void setMatxxElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, matxx* m)
-{
- (*m)(row, col) = val;
-}
-
-inline void setMat3xElem(const idArrayIdx row, const idArrayIdx col, const idScalar val, mat3x* m)
-{
- (*m)(row, col) = val;
-}
-
-} // namespace btInverseDynamics
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
deleted file mode 100644
index ec9a562295..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.cpp
+++ /dev/null
@@ -1,1286 +0,0 @@
-#include "MultiBodyTreeImpl.hpp"
-
-namespace btInverseDynamics
-{
-MultiBodyTree::MultiBodyImpl::MultiBodyImpl(int num_bodies_, int num_dofs_)
- : m_num_bodies(num_bodies_), m_num_dofs(num_dofs_)
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- ,
- m_m3x(3, m_num_dofs)
-#endif
-{
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- resize(m_m3x, m_num_dofs);
-#endif
- m_body_list.resize(num_bodies_);
- m_parent_index.resize(num_bodies_);
- m_child_indices.resize(num_bodies_);
- m_user_int.resize(num_bodies_);
- m_user_ptr.resize(num_bodies_);
-
- m_world_gravity(0) = 0.0;
- m_world_gravity(1) = 0.0;
- m_world_gravity(2) = -9.8;
-}
-
-const char *MultiBodyTree::MultiBodyImpl::jointTypeToString(const JointType &type) const
-{
- switch (type)
- {
- case FIXED:
- return "fixed";
- case REVOLUTE:
- return "revolute";
- case PRISMATIC:
- return "prismatic";
- case FLOATING:
- return "floating";
- case SPHERICAL:
- return "spherical";
- }
- return "error: invalid";
-}
-
-inline void indent(const int &level)
-{
- for (int j = 0; j < level; j++)
- id_printf(" "); // indent
-}
-
-void MultiBodyTree::MultiBodyImpl::printTree()
-{
- id_printf("body %.2d[%s]: root\n", 0, jointTypeToString(m_body_list[0].m_joint_type));
- printTree(0, 0);
-}
-
-void MultiBodyTree::MultiBodyImpl::printTreeData()
-{
- for (idArrayIdx i = 0; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- id_printf("body: %d\n", static_cast<int>(i));
- id_printf("type: %s\n", jointTypeToString(body.m_joint_type));
- id_printf("q_index= %d\n", body.m_q_index);
- id_printf("Jac_JR= [%f;%f;%f]\n", body.m_Jac_JR(0), body.m_Jac_JR(1), body.m_Jac_JR(2));
- id_printf("Jac_JT= [%f;%f;%f]\n", body.m_Jac_JT(0), body.m_Jac_JT(1), body.m_Jac_JT(2));
-
- id_printf("mass = %f\n", body.m_mass);
- id_printf("mass * com = [%f %f %f]\n", body.m_body_mass_com(0), body.m_body_mass_com(1),
- body.m_body_mass_com(2));
- id_printf(
- "I_o= [%f %f %f;\n"
- " %f %f %f;\n"
- " %f %f %f]\n",
- body.m_body_I_body(0, 0), body.m_body_I_body(0, 1), body.m_body_I_body(0, 2),
- body.m_body_I_body(1, 0), body.m_body_I_body(1, 1), body.m_body_I_body(1, 2),
- body.m_body_I_body(2, 0), body.m_body_I_body(2, 1), body.m_body_I_body(2, 2));
-
- id_printf("parent_pos_parent_body_ref= [%f %f %f]\n", body.m_parent_pos_parent_body_ref(0),
- body.m_parent_pos_parent_body_ref(1), body.m_parent_pos_parent_body_ref(2));
- }
-}
-int MultiBodyTree::MultiBodyImpl::bodyNumDoFs(const JointType &type) const
-{
- switch (type)
- {
- case FIXED:
- return 0;
- case REVOLUTE:
- case PRISMATIC:
- return 1;
- case FLOATING:
- return 6;
- case SPHERICAL:
- return 3;
- }
- bt_id_error_message("unknown joint type %d\n", type);
- return 0;
-}
-
-void MultiBodyTree::MultiBodyImpl::printTree(int index, int indentation)
-{
- // this is adapted from URDF2Bullet.
- // TODO: fix this and print proper graph (similar to git --log --graph)
- int num_children = m_child_indices[index].size();
-
- indentation += 2;
- int count = 0;
-
- for (int i = 0; i < num_children; i++)
- {
- int child_index = m_child_indices[index][i];
- indent(indentation);
- id_printf("body %.2d[%s]: %.2d is child no. %d (qi= %d .. %d) \n", index,
- jointTypeToString(m_body_list[index].m_joint_type), child_index, (count++) + 1,
- m_body_list[index].m_q_index,
- m_body_list[index].m_q_index + bodyNumDoFs(m_body_list[index].m_joint_type));
- // first grandchild
- printTree(child_index, indentation);
- }
-}
-
-int MultiBodyTree::MultiBodyImpl::setGravityInWorldFrame(const vec3 &gravity)
-{
- m_world_gravity = gravity;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::generateIndexSets()
-{
- m_body_revolute_list.resize(0);
- m_body_prismatic_list.resize(0);
- int q_index = 0;
- for (idArrayIdx i = 0; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- body.m_q_index = -1;
- switch (body.m_joint_type)
- {
- case REVOLUTE:
- m_body_revolute_list.push_back(i);
- body.m_q_index = q_index;
- q_index++;
- break;
- case PRISMATIC:
- m_body_prismatic_list.push_back(i);
- body.m_q_index = q_index;
- q_index++;
- break;
- case FIXED:
- // do nothing
- break;
- case FLOATING:
- m_body_floating_list.push_back(i);
- body.m_q_index = q_index;
- q_index += 6;
- break;
- case SPHERICAL:
- m_body_spherical_list.push_back(i);
- body.m_q_index = q_index;
- q_index += 3;
- break;
- default:
- bt_id_error_message("unsupported joint type %d\n", body.m_joint_type);
- return -1;
- }
- }
- // sanity check
- if (q_index != m_num_dofs)
- {
- bt_id_error_message("internal error, q_index= %d but num_dofs %d\n", q_index, m_num_dofs);
- return -1;
- }
-
- m_child_indices.resize(m_body_list.size());
-
- for (idArrayIdx child = 1; child < m_parent_index.size(); child++)
- {
- const int &parent = m_parent_index[child];
- if (parent >= 0 && parent < (static_cast<int>(m_parent_index.size()) - 1))
- {
- m_child_indices[parent].push_back(child);
- }
- else
- {
- if (-1 == parent)
- {
- // multiple bodies are directly linked to the environment, ie, not a single root
- bt_id_error_message("building index sets parent(%zu)= -1 (multiple roots)\n", child);
- }
- else
- {
- // should never happen
- bt_id_error_message(
- "building index sets. parent_index[%zu]= %d, but m_parent_index.size()= %d\n",
- child, parent, static_cast<int>(m_parent_index.size()));
- }
- return -1;
- }
- }
-
- return 0;
-}
-
-void MultiBodyTree::MultiBodyImpl::calculateStaticData()
-{
- // relative kinematics that are not a function of q, u, dot_u
- for (idArrayIdx i = 0; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- switch (body.m_joint_type)
- {
- case REVOLUTE:
- body.m_parent_vel_rel(0) = 0;
- body.m_parent_vel_rel(1) = 0;
- body.m_parent_vel_rel(2) = 0;
- body.m_parent_acc_rel(0) = 0;
- body.m_parent_acc_rel(1) = 0;
- body.m_parent_acc_rel(2) = 0;
- body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
- break;
- case PRISMATIC:
- body.m_body_T_parent = body.m_body_T_parent_ref;
- body.m_parent_Jac_JT = body.m_body_T_parent_ref.transpose() * body.m_Jac_JT;
- body.m_body_ang_vel_rel(0) = 0;
- body.m_body_ang_vel_rel(1) = 0;
- body.m_body_ang_vel_rel(2) = 0;
- body.m_body_ang_acc_rel(0) = 0;
- body.m_body_ang_acc_rel(1) = 0;
- body.m_body_ang_acc_rel(2) = 0;
- break;
- case FIXED:
- body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
- body.m_body_T_parent = body.m_body_T_parent_ref;
- body.m_body_ang_vel_rel(0) = 0;
- body.m_body_ang_vel_rel(1) = 0;
- body.m_body_ang_vel_rel(2) = 0;
- body.m_parent_vel_rel(0) = 0;
- body.m_parent_vel_rel(1) = 0;
- body.m_parent_vel_rel(2) = 0;
- body.m_body_ang_acc_rel(0) = 0;
- body.m_body_ang_acc_rel(1) = 0;
- body.m_body_ang_acc_rel(2) = 0;
- body.m_parent_acc_rel(0) = 0;
- body.m_parent_acc_rel(1) = 0;
- body.m_parent_acc_rel(2) = 0;
- break;
- case FLOATING:
- // no static data
- break;
- case SPHERICAL:
- //todo: review
- body.m_parent_pos_parent_body = body.m_parent_pos_parent_body_ref;
- body.m_parent_vel_rel(0) = 0;
- body.m_parent_vel_rel(1) = 0;
- body.m_parent_vel_rel(2) = 0;
- body.m_parent_acc_rel(0) = 0;
- body.m_parent_acc_rel(1) = 0;
- body.m_parent_acc_rel(2) = 0;
- break;
- }
-
- // resize & initialize jacobians to zero.
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- body.m_body_dot_Jac_T_u(0) = 0.0;
- body.m_body_dot_Jac_T_u(1) = 0.0;
- body.m_body_dot_Jac_T_u(2) = 0.0;
- body.m_body_dot_Jac_R_u(0) = 0.0;
- body.m_body_dot_Jac_R_u(1) = 0.0;
- body.m_body_dot_Jac_R_u(2) = 0.0;
- resize(body.m_body_Jac_T, m_num_dofs);
- resize(body.m_body_Jac_R, m_num_dofs);
- body.m_body_Jac_T.setZero();
- body.m_body_Jac_R.setZero();
-#endif //
- }
-}
-
-int MultiBodyTree::MultiBodyImpl::calculateInverseDynamics(const vecx &q, const vecx &u,
- const vecx &dot_u, vecx *joint_forces)
-{
- if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs ||
- joint_forces->size() != m_num_dofs)
- {
- bt_id_error_message(
- "wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d, dim(joint_forces)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
- static_cast<int>(dot_u.size()), static_cast<int>(joint_forces->size()));
- return -1;
- }
- // 1. relative kinematics
- if (-1 == calculateKinematics(q, u, dot_u, POSITION_VELOCITY_ACCELERATION))
- {
- bt_id_error_message("error in calculateKinematics\n");
- return -1;
- }
- // 2. update contributions to equations of motion for every body.
- for (idArrayIdx i = 0; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- // 3.4 update dynamic terms (rate of change of angular & linear momentum)
- body.m_eom_lhs_rotational =
- body.m_body_I_body * body.m_body_ang_acc + body.m_body_mass_com.cross(body.m_body_acc) +
- body.m_body_ang_vel.cross(body.m_body_I_body * body.m_body_ang_vel) -
- body.m_body_moment_user;
- body.m_eom_lhs_translational =
- body.m_body_ang_acc.cross(body.m_body_mass_com) + body.m_mass * body.m_body_acc +
- body.m_body_ang_vel.cross(body.m_body_ang_vel.cross(body.m_body_mass_com)) -
- body.m_body_force_user;
- }
-
- // 3. calculate full set of forces at parent joint
- // (not directly calculating the joint force along the free direction
- // simplifies inclusion of fixed joints.
- // An alternative would be to fuse bodies in a pre-processing step,
- // but that would make changing masses online harder (eg, payload masses
- // added with fixed joints to a gripper)
- // Also, this enables adding zero weight bodies as a way to calculate frame poses
- // for force elements, etc.
-
- for (int body_idx = m_body_list.size() - 1; body_idx >= 0; body_idx--)
- {
- // sum of forces and moments acting on this body from its children
- vec3 sum_f_children;
- vec3 sum_m_children;
- setZero(sum_f_children);
- setZero(sum_m_children);
- for (idArrayIdx child_list_idx = 0; child_list_idx < m_child_indices[body_idx].size();
- child_list_idx++)
- {
- const RigidBody &child = m_body_list[m_child_indices[body_idx][child_list_idx]];
- vec3 child_joint_force_in_this_frame =
- child.m_body_T_parent.transpose() * child.m_force_at_joint;
- sum_f_children -= child_joint_force_in_this_frame;
- sum_m_children -= child.m_body_T_parent.transpose() * child.m_moment_at_joint +
- child.m_parent_pos_parent_body.cross(child_joint_force_in_this_frame);
- }
- RigidBody &body = m_body_list[body_idx];
-
- body.m_force_at_joint = body.m_eom_lhs_translational - sum_f_children;
- body.m_moment_at_joint = body.m_eom_lhs_rotational - sum_m_children;
- }
-
- // 4. Calculate Joint forces.
- // These are the components of force_at_joint/moment_at_joint
- // in the free directions given by Jac_JT/Jac_JR
- // 4.1 revolute joints
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_revolute_list[i]];
- // (*joint_forces)(body.m_q_index) = body.m_Jac_JR.transpose() * body.m_moment_at_joint;
- (*joint_forces)(body.m_q_index) = body.m_Jac_JR.dot(body.m_moment_at_joint);
- }
- // 4.2 for prismatic joints
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_prismatic_list[i]];
- // (*joint_forces)(body.m_q_index) = body.m_Jac_JT.transpose() * body.m_force_at_joint;
- (*joint_forces)(body.m_q_index) = body.m_Jac_JT.dot(body.m_force_at_joint);
- }
- // 4.3 floating bodies (6-DoF joints)
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_floating_list[i]];
- (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
- (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
- (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
-
- (*joint_forces)(body.m_q_index + 3) = body.m_force_at_joint(0);
- (*joint_forces)(body.m_q_index + 4) = body.m_force_at_joint(1);
- (*joint_forces)(body.m_q_index + 5) = body.m_force_at_joint(2);
- }
-
- // 4.4 spherical bodies (3-DoF joints)
- for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
- {
- //todo: review
- RigidBody &body = m_body_list[m_body_spherical_list[i]];
- (*joint_forces)(body.m_q_index + 0) = body.m_moment_at_joint(0);
- (*joint_forces)(body.m_q_index + 1) = body.m_moment_at_joint(1);
- (*joint_forces)(body.m_q_index + 2) = body.m_moment_at_joint(2);
- }
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::calculateKinematics(const vecx &q, const vecx &u, const vecx &dot_u,
- const KinUpdateType type)
-{
- if (q.size() != m_num_dofs || u.size() != m_num_dofs || dot_u.size() != m_num_dofs)
- {
- bt_id_error_message(
- "wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d, dim(dot_u)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()),
- static_cast<int>(dot_u.size()));
- return -1;
- }
- if (type != POSITION_ONLY && type != POSITION_VELOCITY && type != POSITION_VELOCITY_ACCELERATION)
- {
- bt_id_error_message("invalid type %d\n", type);
- return -1;
- }
-
- // 1. update relative kinematics
- // 1.1 for revolute
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_revolute_list[i]];
- mat33 T;
- bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &T);
- body.m_body_T_parent = T * body.m_body_T_parent_ref;
- if (type >= POSITION_VELOCITY)
- {
- body.m_body_ang_vel_rel = body.m_Jac_JR * u(body.m_q_index);
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- body.m_body_ang_acc_rel = body.m_Jac_JR * dot_u(body.m_q_index);
- }
- }
- // 1.2 for prismatic
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_prismatic_list[i]];
- body.m_parent_pos_parent_body =
- body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
- if (type >= POSITION_VELOCITY)
- {
- body.m_parent_vel_rel =
- body.m_body_T_parent_ref.transpose() * body.m_Jac_JT * u(body.m_q_index);
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- body.m_parent_acc_rel = body.m_parent_Jac_JT * dot_u(body.m_q_index);
- }
- }
- // 1.3 fixed joints: nothing to do
- // 1.4 6dof joints:
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_floating_list[i]];
-
- body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
- transformY(q(body.m_q_index + 1)) *
- transformX(q(body.m_q_index));
- body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
- body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
- body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
- body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
-
- if (type >= POSITION_VELOCITY)
- {
- body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
- body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
- body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
-
- body.m_parent_vel_rel(0) = u(body.m_q_index + 3);
- body.m_parent_vel_rel(1) = u(body.m_q_index + 4);
- body.m_parent_vel_rel(2) = u(body.m_q_index + 5);
-
- body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
- body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
- body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
-
- body.m_parent_acc_rel(0) = dot_u(body.m_q_index + 3);
- body.m_parent_acc_rel(1) = dot_u(body.m_q_index + 4);
- body.m_parent_acc_rel(2) = dot_u(body.m_q_index + 5);
-
- body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
- }
- }
-
- for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
- {
- //todo: review
- RigidBody &body = m_body_list[m_body_spherical_list[i]];
-
- mat33 T;
-
- T = transformX(q(body.m_q_index)) *
- transformY(q(body.m_q_index + 1)) *
- transformZ(q(body.m_q_index + 2));
- body.m_body_T_parent = T * body.m_body_T_parent_ref;
-
- body.m_parent_pos_parent_body(0)=0;
- body.m_parent_pos_parent_body(1)=0;
- body.m_parent_pos_parent_body(2)=0;
-
- body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
-
- if (type >= POSITION_VELOCITY)
- {
- body.m_body_ang_vel_rel(0) = u(body.m_q_index + 0);
- body.m_body_ang_vel_rel(1) = u(body.m_q_index + 1);
- body.m_body_ang_vel_rel(2) = u(body.m_q_index + 2);
- body.m_parent_vel_rel = body.m_body_T_parent.transpose() * body.m_parent_vel_rel;
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- body.m_body_ang_acc_rel(0) = dot_u(body.m_q_index + 0);
- body.m_body_ang_acc_rel(1) = dot_u(body.m_q_index + 1);
- body.m_body_ang_acc_rel(2) = dot_u(body.m_q_index + 2);
- body.m_parent_acc_rel = body.m_body_T_parent.transpose() * body.m_parent_acc_rel;
- }
- }
-
- // 2. absolute kinematic quantities (vector valued)
- // NOTE: this should be optimized by specializing for different body types
- // (e.g., relative rotation is always zero for prismatic joints, etc.)
-
- // calculations for root body
- {
- RigidBody &body = m_body_list[0];
- // 3.1 update absolute positions and orientations:
- // will be required if we add force elements (eg springs between bodies,
- // or contacts)
- // not required right now, added here for debugging purposes
- body.m_body_pos = body.m_body_T_parent * body.m_parent_pos_parent_body;
- body.m_body_T_world = body.m_body_T_parent;
-
- if (type >= POSITION_VELOCITY)
- {
- // 3.2 update absolute velocities
- body.m_body_ang_vel = body.m_body_ang_vel_rel;
- body.m_body_vel = body.m_parent_vel_rel;
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- // 3.3 update absolute accelerations
- // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
- body.m_body_ang_acc = body.m_body_ang_acc_rel;
- body.m_body_acc = body.m_body_T_parent * body.m_parent_acc_rel;
- // add gravitational acceleration to root body
- // this is an efficient way to add gravitational terms,
- // but it does mean that the kinematics are no longer
- // correct at the acceleration level
- // NOTE: To get correct acceleration kinematics, just set world_gravity to zero
- body.m_body_acc = body.m_body_acc - body.m_body_T_parent * m_world_gravity;
- }
- }
-
- for (idArrayIdx i = 1; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- RigidBody &parent = m_body_list[m_parent_index[i]];
- // 2.1 update absolute positions and orientations:
- // will be required if we add force elements (eg springs between bodies,
- // or contacts) not required right now added here for debugging purposes
- body.m_body_pos =
- body.m_body_T_parent * (parent.m_body_pos + body.m_parent_pos_parent_body);
- body.m_body_T_world = body.m_body_T_parent * parent.m_body_T_world;
-
- if (type >= POSITION_VELOCITY)
- {
- // 2.2 update absolute velocities
- body.m_body_ang_vel =
- body.m_body_T_parent * parent.m_body_ang_vel + body.m_body_ang_vel_rel;
-
- body.m_body_vel =
- body.m_body_T_parent *
- (parent.m_body_vel + parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body) +
- body.m_parent_vel_rel);
- }
- if (type >= POSITION_VELOCITY_ACCELERATION)
- {
- // 2.3 update absolute accelerations
- // NOTE: assumption: dot(J_JR) = 0; true here, but not for general joints
- body.m_body_ang_acc =
- body.m_body_T_parent * parent.m_body_ang_acc -
- body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel) +
- body.m_body_ang_acc_rel;
- body.m_body_acc =
- body.m_body_T_parent *
- (parent.m_body_acc + parent.m_body_ang_acc.cross(body.m_parent_pos_parent_body) +
- parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
- 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel) + body.m_parent_acc_rel);
- }
- }
-
- return 0;
-}
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-
-void MultiBodyTree::MultiBodyImpl::addRelativeJacobianComponent(RigidBody &body)
-{
- const int &idx = body.m_q_index;
- switch (body.m_joint_type)
- {
- case FIXED:
- break;
- case REVOLUTE:
- setMat3xElem(0, idx, body.m_Jac_JR(0), &body.m_body_Jac_R);
- setMat3xElem(1, idx, body.m_Jac_JR(1), &body.m_body_Jac_R);
- setMat3xElem(2, idx, body.m_Jac_JR(2), &body.m_body_Jac_R);
- break;
- case PRISMATIC:
- setMat3xElem(0, idx, body.m_body_T_parent_ref(0, 0) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 0) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 0) * body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- setMat3xElem(1, idx, body.m_body_T_parent_ref(0, 1) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 1) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 1) * body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- setMat3xElem(2, idx, body.m_body_T_parent_ref(0, 2) * body.m_Jac_JT(0) + body.m_body_T_parent_ref(1, 2) * body.m_Jac_JT(1) + body.m_body_T_parent_ref(2, 2) * body.m_Jac_JT(2),
- &body.m_body_Jac_T);
- break;
- case FLOATING:
- setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
- setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
- setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
- // body_Jac_T = body_T_parent.transpose();
- setMat3xElem(0, idx + 3, body.m_body_T_parent(0, 0), &body.m_body_Jac_T);
- setMat3xElem(0, idx + 4, body.m_body_T_parent(1, 0), &body.m_body_Jac_T);
- setMat3xElem(0, idx + 5, body.m_body_T_parent(2, 0), &body.m_body_Jac_T);
-
- setMat3xElem(1, idx + 3, body.m_body_T_parent(0, 1), &body.m_body_Jac_T);
- setMat3xElem(1, idx + 4, body.m_body_T_parent(1, 1), &body.m_body_Jac_T);
- setMat3xElem(1, idx + 5, body.m_body_T_parent(2, 1), &body.m_body_Jac_T);
-
- setMat3xElem(2, idx + 3, body.m_body_T_parent(0, 2), &body.m_body_Jac_T);
- setMat3xElem(2, idx + 4, body.m_body_T_parent(1, 2), &body.m_body_Jac_T);
- setMat3xElem(2, idx + 5, body.m_body_T_parent(2, 2), &body.m_body_Jac_T);
-
- break;
- case SPHERICAL:
- //todo: review
- setMat3xElem(0, idx + 0, 1.0, &body.m_body_Jac_R);
- setMat3xElem(1, idx + 1, 1.0, &body.m_body_Jac_R);
- setMat3xElem(2, idx + 2, 1.0, &body.m_body_Jac_R);
- break;
- }
-}
-
-int MultiBodyTree::MultiBodyImpl::calculateJacobians(const vecx &q, const vecx &u, const KinUpdateType type)
-{
- if (q.size() != m_num_dofs || u.size() != m_num_dofs)
- {
- bt_id_error_message(
- "wrong vector dimension. system has %d DOFs,\n"
- "but dim(q)= %d, dim(u)= %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(u.size()));
- return -1;
- }
- if (type != POSITION_ONLY && type != POSITION_VELOCITY)
- {
- bt_id_error_message("invalid type %d\n", type);
- return -1;
- }
-
- addRelativeJacobianComponent(m_body_list[0]);
- for (idArrayIdx i = 1; i < m_body_list.size(); i++)
- {
- RigidBody &body = m_body_list[i];
- RigidBody &parent = m_body_list[m_parent_index[i]];
-
- mul(body.m_body_T_parent, parent.m_body_Jac_R, &body.m_body_Jac_R);
- body.m_body_Jac_T = parent.m_body_Jac_T;
- mul(tildeOperator(body.m_parent_pos_parent_body), parent.m_body_Jac_R, &m_m3x);
- sub(body.m_body_Jac_T, m_m3x, &body.m_body_Jac_T);
-
- addRelativeJacobianComponent(body);
- mul(body.m_body_T_parent, body.m_body_Jac_T, &body.m_body_Jac_T);
-
- if (type >= POSITION_VELOCITY)
- {
- body.m_body_dot_Jac_R_u = body.m_body_T_parent * parent.m_body_dot_Jac_R_u -
- body.m_body_ang_vel_rel.cross(body.m_body_T_parent * parent.m_body_ang_vel);
- body.m_body_dot_Jac_T_u = body.m_body_T_parent *
- (parent.m_body_dot_Jac_T_u + parent.m_body_dot_Jac_R_u.cross(body.m_parent_pos_parent_body) +
- parent.m_body_ang_vel.cross(parent.m_body_ang_vel.cross(body.m_parent_pos_parent_body)) +
- 2.0 * parent.m_body_ang_vel.cross(body.m_parent_vel_rel));
- }
- }
- return 0;
-}
-#endif
-
-static inline void setThreeDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
-{
- switch (dof)
- {
- // rotational part
- case 0:
- Jac_JR(0) = 1;
- Jac_JR(1) = 0;
- Jac_JR(2) = 0;
- setZero(Jac_JT);
- break;
- case 1:
- Jac_JR(0) = 0;
- Jac_JR(1) = 1;
- Jac_JR(2) = 0;
- setZero(Jac_JT);
- break;
- case 2:
- Jac_JR(0) = 0;
- Jac_JR(1) = 0;
- Jac_JR(2) = 1;
- setZero(Jac_JT);
- break;
- }
-}
-
-static inline void setSixDoFJacobians(const int dof, vec3 &Jac_JR, vec3 &Jac_JT)
-{
- switch (dof)
- {
- // rotational part
- case 0:
- Jac_JR(0) = 1;
- Jac_JR(1) = 0;
- Jac_JR(2) = 0;
- setZero(Jac_JT);
- break;
- case 1:
- Jac_JR(0) = 0;
- Jac_JR(1) = 1;
- Jac_JR(2) = 0;
- setZero(Jac_JT);
- break;
- case 2:
- Jac_JR(0) = 0;
- Jac_JR(1) = 0;
- Jac_JR(2) = 1;
- setZero(Jac_JT);
- break;
- // translational part
- case 3:
- setZero(Jac_JR);
- Jac_JT(0) = 1;
- Jac_JT(1) = 0;
- Jac_JT(2) = 0;
- break;
- case 4:
- setZero(Jac_JR);
- Jac_JT(0) = 0;
- Jac_JT(1) = 1;
- Jac_JT(2) = 0;
- break;
- case 5:
- setZero(Jac_JR);
- Jac_JT(0) = 0;
- Jac_JT(1) = 0;
- Jac_JT(2) = 1;
- break;
- }
-}
-
-static inline int jointNumDoFs(const JointType &type)
-{
- switch (type)
- {
- case FIXED:
- return 0;
- case REVOLUTE:
- case PRISMATIC:
- return 1;
- case FLOATING:
- return 6;
- case SPHERICAL:
- return 3;
- }
- // this should never happen
- bt_id_error_message("invalid joint type\n");
- // TODO add configurable abort/crash function
- abort();
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::calculateMassMatrix(const vecx &q, const bool update_kinematics,
- const bool initialize_matrix,
- const bool set_lower_triangular_matrix,
- matxx *mass_matrix)
-{
- // This calculates the joint space mass matrix for the multibody system.
- // The algorithm is essentially an implementation of "method 3"
- // in "Efficient Dynamic Simulation of Robotic Mechanisms" (Walker and Orin, 1982)
- // (Later named "Composite Rigid Body Algorithm" by Featherstone).
- //
- // This implementation, however, handles branched systems and uses a formulation centered
- // on the origin of the body-fixed frame to avoid re-computing various quantities at the com.
-
- if (q.size() != m_num_dofs || mass_matrix->rows() != m_num_dofs ||
- mass_matrix->cols() != m_num_dofs)
- {
- bt_id_error_message(
- "Dimension error. System has %d DOFs,\n"
- "but dim(q)= %d, dim(mass_matrix)= %d x %d\n",
- m_num_dofs, static_cast<int>(q.size()), static_cast<int>(mass_matrix->rows()),
- static_cast<int>(mass_matrix->cols()));
- return -1;
- }
-
- // TODO add optimized zeroing function?
- if (initialize_matrix)
- {
- for (int i = 0; i < m_num_dofs; i++)
- {
- for (int j = 0; j < m_num_dofs; j++)
- {
- setMatxxElem(i, j, 0.0, mass_matrix);
- }
- }
- }
-
- if (update_kinematics)
- {
- // 1. update relative kinematics
- // 1.1 for revolute joints
- for (idArrayIdx i = 0; i < m_body_revolute_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_revolute_list[i]];
- // from reference orientation (q=0) of body-fixed frame to current orientation
- mat33 body_T_body_ref;
- bodyTParentFromAxisAngle(body.m_Jac_JR, q(body.m_q_index), &body_T_body_ref);
- body.m_body_T_parent = body_T_body_ref * body.m_body_T_parent_ref;
- }
- // 1.2 for prismatic joints
- for (idArrayIdx i = 0; i < m_body_prismatic_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_prismatic_list[i]];
- // body.m_body_T_parent= fixed
- body.m_parent_pos_parent_body =
- body.m_parent_pos_parent_body_ref + body.m_parent_Jac_JT * q(body.m_q_index);
- }
- // 1.3 fixed joints: nothing to do
- // 1.4 6dof joints:
- for (idArrayIdx i = 0; i < m_body_floating_list.size(); i++)
- {
- RigidBody &body = m_body_list[m_body_floating_list[i]];
-
- body.m_body_T_parent = transformZ(q(body.m_q_index + 2)) *
- transformY(q(body.m_q_index + 1)) *
- transformX(q(body.m_q_index));
- body.m_parent_pos_parent_body(0) = q(body.m_q_index + 3);
- body.m_parent_pos_parent_body(1) = q(body.m_q_index + 4);
- body.m_parent_pos_parent_body(2) = q(body.m_q_index + 5);
-
- body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
- }
-
- for (idArrayIdx i = 0; i < m_body_spherical_list.size(); i++)
- {
- //todo: review
- RigidBody &body = m_body_list[m_body_spherical_list[i]];
-
- mat33 T;
-
- T = transformX(q(body.m_q_index)) *
- transformY(q(body.m_q_index + 1)) *
- transformZ(q(body.m_q_index + 2));
- body.m_body_T_parent = T * body.m_body_T_parent_ref;
-
- body.m_parent_pos_parent_body(0)=0;
- body.m_parent_pos_parent_body(1)=0;
- body.m_parent_pos_parent_body(2)=0;
-
- body.m_parent_pos_parent_body = body.m_body_T_parent * body.m_parent_pos_parent_body;
- }
- }
- for (int i = m_body_list.size() - 1; i >= 0; i--)
- {
- RigidBody &body = m_body_list[i];
- // calculate mass, center of mass and inertia of "composite rigid body",
- // ie, sub-tree starting at current body
- body.m_subtree_mass = body.m_mass;
- body.m_body_subtree_mass_com = body.m_body_mass_com;
- body.m_body_subtree_I_body = body.m_body_I_body;
-
- for (idArrayIdx c = 0; c < m_child_indices[i].size(); c++)
- {
- RigidBody &child = m_body_list[m_child_indices[i][c]];
- mat33 body_T_child = child.m_body_T_parent.transpose();
-
- body.m_subtree_mass += child.m_subtree_mass;
- body.m_body_subtree_mass_com += body_T_child * child.m_body_subtree_mass_com +
- child.m_parent_pos_parent_body * child.m_subtree_mass;
- body.m_body_subtree_I_body +=
- body_T_child * child.m_body_subtree_I_body * child.m_body_T_parent;
-
- if (child.m_subtree_mass > 0)
- {
- // Shift the reference point for the child subtree inertia using the
- // Huygens-Steiner ("parallel axis") theorem.
- // (First shift from child origin to child com, then from there to this body's
- // origin)
- vec3 r_com = body_T_child * child.m_body_subtree_mass_com / child.m_subtree_mass;
- mat33 tilde_r_child_com = tildeOperator(r_com);
- mat33 tilde_r_body_com = tildeOperator(child.m_parent_pos_parent_body + r_com);
- body.m_body_subtree_I_body +=
- child.m_subtree_mass *
- (tilde_r_child_com * tilde_r_child_com - tilde_r_body_com * tilde_r_body_com);
- }
- }
- }
-
- for (int i = m_body_list.size() - 1; i >= 0; i--)
- {
- const RigidBody &body = m_body_list[i];
-
- // determine DoF-range for body
- const int q_index_min = body.m_q_index;
- const int q_index_max = q_index_min + jointNumDoFs(body.m_joint_type) - 1;
- // loop over the DoFs used by this body
- // local joint jacobians (ok as is for 1-DoF joints)
- vec3 Jac_JR = body.m_Jac_JR;
- vec3 Jac_JT = body.m_Jac_JT;
- for (int col = q_index_max; col >= q_index_min; col--)
- {
- // set jacobians for 6-DoF joints
- if (FLOATING == body.m_joint_type)
- {
- setSixDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
- }
- if (SPHERICAL == body.m_joint_type)
- {
- //todo: review
- setThreeDoFJacobians(col - q_index_min, Jac_JR, Jac_JT);
- }
-
- vec3 body_eom_rot =
- body.m_body_subtree_I_body * Jac_JR + body.m_body_subtree_mass_com.cross(Jac_JT);
- vec3 body_eom_trans =
- body.m_subtree_mass * Jac_JT - body.m_body_subtree_mass_com.cross(Jac_JR);
- setMatxxElem(col, col, Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans), mass_matrix);
-
- // rest of the mass matrix column upwards
- {
- // 1. for multi-dof joints, rest of the dofs of this body
- for (int row = col - 1; row >= q_index_min; row--)
- {
- if (SPHERICAL == body.m_joint_type)
- {
- //todo: review
- setThreeDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
- const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
- setMatxxElem(col, row, Mrc, mass_matrix);
- }
- if (FLOATING == body.m_joint_type)
- {
- setSixDoFJacobians(row - q_index_min, Jac_JR, Jac_JT);
- const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
- setMatxxElem(col, row, Mrc, mass_matrix);
- }
- }
- // 2. ancestor dofs
- int child_idx = i;
- int parent_idx = m_parent_index[i];
- while (parent_idx >= 0)
- {
- const RigidBody &child_body = m_body_list[child_idx];
- const RigidBody &parent_body = m_body_list[parent_idx];
-
- const mat33 parent_T_child = child_body.m_body_T_parent.transpose();
- body_eom_rot = parent_T_child * body_eom_rot;
- body_eom_trans = parent_T_child * body_eom_trans;
- body_eom_rot += child_body.m_parent_pos_parent_body.cross(body_eom_trans);
-
- const int parent_body_q_index_min = parent_body.m_q_index;
- const int parent_body_q_index_max =
- parent_body_q_index_min + jointNumDoFs(parent_body.m_joint_type) - 1;
- vec3 Jac_JR = parent_body.m_Jac_JR;
- vec3 Jac_JT = parent_body.m_Jac_JT;
- for (int row = parent_body_q_index_max; row >= parent_body_q_index_min; row--)
- {
- if (SPHERICAL == parent_body.m_joint_type)
- {
- //todo: review
- setThreeDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
- }
- // set jacobians for 6-DoF joints
- if (FLOATING == parent_body.m_joint_type)
- {
- setSixDoFJacobians(row - parent_body_q_index_min, Jac_JR, Jac_JT);
- }
- const double Mrc = Jac_JR.dot(body_eom_rot) + Jac_JT.dot(body_eom_trans);
- setMatxxElem(col, row, Mrc, mass_matrix);
- }
-
- child_idx = parent_idx;
- parent_idx = m_parent_index[child_idx];
- }
- }
- }
- }
-
- if (set_lower_triangular_matrix)
- {
- for (int col = 0; col < m_num_dofs; col++)
- {
- for (int row = 0; row < col; row++)
- {
- setMatxxElem(row, col, (*mass_matrix)(col, row), mass_matrix);
- }
- }
- }
- return 0;
-}
-
-// utility macro
-#define CHECK_IF_BODY_INDEX_IS_VALID(index) \
- do \
- { \
- if (index < 0 || index >= m_num_bodies) \
- { \
- bt_id_error_message("invalid index %d (num_bodies= %d)\n", index, m_num_bodies); \
- return -1; \
- } \
- } while (0)
-
-int MultiBodyTree::MultiBodyImpl::getParentIndex(const int body_index, int *p)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *p = m_parent_index[body_index];
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getUserInt(const int body_index, int *user_int) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *user_int = m_user_int[body_index];
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getUserPtr(const int body_index, void **user_ptr) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *user_ptr = m_user_ptr[body_index];
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::setUserInt(const int body_index, const int user_int)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_user_int[body_index] = user_int;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::setUserPtr(const int body_index, void *const user_ptr)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_user_ptr[body_index] = user_ptr;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyOrigin(int body_index, vec3 *world_origin) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_origin = body.m_body_T_world.transpose() * body.m_body_pos;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyCoM(int body_index, vec3 *world_com) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- if (body.m_mass > 0)
- {
- *world_com = body.m_body_T_world.transpose() *
- (body.m_body_pos + body.m_body_mass_com / body.m_mass);
- }
- else
- {
- *world_com = body.m_body_T_world.transpose() * (body.m_body_pos);
- }
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyTransform(int body_index, mat33 *world_T_body) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_T_body = body.m_body_T_world.transpose();
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodyAngularVelocity(int body_index, vec3 *world_omega) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_omega = body.m_body_T_world.transpose() * body.m_body_ang_vel;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocity(int body_index,
- vec3 *world_velocity) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_velocity = body.m_body_T_world.transpose() * body.m_body_vel;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyLinearVelocityCoM(int body_index,
- vec3 *world_velocity) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- vec3 com;
- if (body.m_mass > 0)
- {
- com = body.m_body_mass_com / body.m_mass;
- }
- else
- {
- com(0) = 0;
- com(1) = 0;
- com(2) = 0;
- }
-
- *world_velocity =
- body.m_body_T_world.transpose() * (body.m_body_vel + body.m_body_ang_vel.cross(com));
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyAngularAcceleration(int body_index,
- vec3 *world_dot_omega) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_dot_omega = body.m_body_T_world.transpose() * body.m_body_ang_acc;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodyLinearAcceleration(int body_index,
- vec3 *world_acceleration) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_acceleration = body.m_body_T_world.transpose() * body.m_body_acc;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getJointType(const int body_index, JointType *joint_type) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *joint_type = m_body_list[body_index].m_joint_type;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getJointTypeStr(const int body_index,
- const char **joint_type) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *joint_type = jointTypeToString(m_body_list[body_index].m_joint_type);
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getParentRParentBodyRef(const int body_index, vec3 *r) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *r = m_body_list[body_index].m_parent_pos_parent_body_ref;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyTParentRef(const int body_index, mat33 *T) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *T = m_body_list[body_index].m_body_T_parent_ref;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyAxisOfMotion(const int body_index, vec3 *axis) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- if (m_body_list[body_index].m_joint_type == REVOLUTE)
- {
- *axis = m_body_list[body_index].m_Jac_JR;
- return 0;
- }
- if (m_body_list[body_index].m_joint_type == PRISMATIC)
- {
- *axis = m_body_list[body_index].m_Jac_JT;
- return 0;
- }
- setZero(*axis);
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getDoFOffset(const int body_index, int *q_index) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *q_index = m_body_list[body_index].m_q_index;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::setBodyMass(const int body_index, const idScalar mass)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_body_list[body_index].m_mass = mass;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::setBodyFirstMassMoment(const int body_index,
- const vec3 &first_mass_moment)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_body_list[body_index].m_body_mass_com = first_mass_moment;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::setBodySecondMassMoment(const int body_index,
- const mat33 &second_mass_moment)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_body_list[body_index].m_body_I_body = second_mass_moment;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodyMass(const int body_index, idScalar *mass) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *mass = m_body_list[body_index].m_mass;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodyFirstMassMoment(const int body_index,
- vec3 *first_mass_moment) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *first_mass_moment = m_body_list[body_index].m_body_mass_com;
- return 0;
-}
-int MultiBodyTree::MultiBodyImpl::getBodySecondMassMoment(const int body_index,
- mat33 *second_mass_moment) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- *second_mass_moment = m_body_list[body_index].m_body_I_body;
- return 0;
-}
-
-void MultiBodyTree::MultiBodyImpl::clearAllUserForcesAndMoments()
-{
- for (int index = 0; index < m_num_bodies; index++)
- {
- RigidBody &body = m_body_list[index];
- setZero(body.m_body_force_user);
- setZero(body.m_body_moment_user);
- }
-}
-
-int MultiBodyTree::MultiBodyImpl::addUserForce(const int body_index, const vec3 &body_force)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_body_list[body_index].m_body_force_user += body_force;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::addUserMoment(const int body_index, const vec3 &body_moment)
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- m_body_list[body_index].m_body_moment_user += body_moment;
- return 0;
-}
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
-int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianTransU(const int body_index, vec3 *world_dot_jac_trans_u) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_dot_jac_trans_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_T_u;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyDotJacobianRotU(const int body_index, vec3 *world_dot_jac_rot_u) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- *world_dot_jac_rot_u = body.m_body_T_world.transpose() * body.m_body_dot_Jac_R_u;
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyJacobianTrans(const int body_index, mat3x *world_jac_trans) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- mul(body.m_body_T_world.transpose(), body.m_body_Jac_T, world_jac_trans);
- return 0;
-}
-
-int MultiBodyTree::MultiBodyImpl::getBodyJacobianRot(const int body_index, mat3x *world_jac_rot) const
-{
- CHECK_IF_BODY_INDEX_IS_VALID(body_index);
- const RigidBody &body = m_body_list[body_index];
- mul(body.m_body_T_world.transpose(), body.m_body_Jac_R, world_jac_rot);
- return 0;
-}
-
-#endif
-} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
deleted file mode 100644
index eabdbe161b..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeImpl.hpp
+++ /dev/null
@@ -1,288 +0,0 @@
-// The structs and classes defined here provide a basic inverse fynamics implementation used
-// by MultiBodyTree
-// User interaction should be through MultiBodyTree
-
-#ifndef MULTI_BODY_REFERENCE_IMPL_HPP_
-#define MULTI_BODY_REFERENCE_IMPL_HPP_
-
-#include "../IDConfig.hpp"
-#include "../MultiBodyTree.hpp"
-
-namespace btInverseDynamics
-{
-/// Structure for for rigid body mass properties, connectivity and kinematic state
-/// all vectors and matrices are in body-fixed frame, if not indicated otherwise.
-/// The body-fixed frame is located in the joint connecting the body to its parent.
-struct RigidBody
-{
- ID_DECLARE_ALIGNED_ALLOCATOR();
- // 1 Inertial properties
- /// Mass
- idScalar m_mass;
- /// Mass times center of gravity in body-fixed frame
- vec3 m_body_mass_com;
- /// Moment of inertia w.r.t. body-fixed frame
- mat33 m_body_I_body;
-
- // 2 dynamic properties
- /// Left-hand side of the body equation of motion, translational part
- vec3 m_eom_lhs_translational;
- /// Left-hand side of the body equation of motion, rotational part
- vec3 m_eom_lhs_rotational;
- /// Force acting at the joint when the body is cut from its parent;
- /// includes impressed joint force in J_JT direction,
- /// as well as constraint force,
- /// in body-fixed frame
- vec3 m_force_at_joint;
- /// Moment acting at the joint when the body is cut from its parent;
- /// includes impressed joint moment in J_JR direction, and constraint moment
- /// in body-fixed frame
- vec3 m_moment_at_joint;
- /// external (user provided) force acting at the body-fixed frame's origin, written in that
- /// frame
- vec3 m_body_force_user;
- /// external (user provided) moment acting at the body-fixed frame's origin, written in that
- /// frame
- vec3 m_body_moment_user;
- // 3 absolute kinematic properties
- /// Position of body-fixed frame relative to world frame
- /// this is currently only for debugging purposes
- vec3 m_body_pos;
- /// Absolute velocity of body-fixed frame
- vec3 m_body_vel;
- /// Absolute acceleration of body-fixed frame
- /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
- /// acceleration!
- vec3 m_body_acc;
- /// Absolute angular velocity
- vec3 m_body_ang_vel;
- /// Absolute angular acceleration
- /// NOTE: if gravitational acceleration is not zero, this is the accelation PLUS gravitational
- /// acceleration!
- vec3 m_body_ang_acc;
-
- // 4 relative kinematic properties.
- // these are in the parent body frame
- /// Transform from world to body-fixed frame;
- /// this is currently only for debugging purposes
- mat33 m_body_T_world;
- /// Transform from parent to body-fixed frame
- mat33 m_body_T_parent;
- /// Vector from parent to child frame in parent frame
- vec3 m_parent_pos_parent_body;
- /// Relative angular velocity
- vec3 m_body_ang_vel_rel;
- /// Relative linear velocity
- vec3 m_parent_vel_rel;
- /// Relative angular acceleration
- vec3 m_body_ang_acc_rel;
- /// Relative linear acceleration
- vec3 m_parent_acc_rel;
-
- // 5 Data describing the joint type and geometry
- /// Type of joint
- JointType m_joint_type;
- /// Position of joint frame (body-fixed frame at q=0) relative to the parent frame
- /// Components are in body-fixed frame of the parent
- vec3 m_parent_pos_parent_body_ref;
- /// Orientation of joint frame (body-fixed frame at q=0) relative to the parent frame
- mat33 m_body_T_parent_ref;
- /// Joint rotational Jacobian, ie, the partial derivative of the body-fixed frames absolute
- /// angular velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
- /// For revolute joints this is the joint axis, for prismatic joints it is a null matrix.
- /// (NOTE: dimensions will have to be dynamic for additional joint types!)
- vec3 m_Jac_JR;
- /// Joint translational Jacobian, ie, the partial derivative of the body-fixed frames absolute
- /// linear velocity w.r.t. the generalized velocity of this body's relative degree of freedom.
- /// For prismatic joints this is the joint axis, for revolute joints it is a null matrix.
- /// (NOTE: dimensions might have to be dynamic for additional joint types!)
- vec3 m_Jac_JT;
- /// m_Jac_JT in the parent frame, it, m_body_T_parent_ref.transpose()*m_Jac_JT
- vec3 m_parent_Jac_JT;
- /// Start of index range for the position degree(s) of freedom describing this body's motion
- /// relative to
- /// its parent. The indices are wrt the multibody system's q-vector of generalized coordinates.
- int m_q_index;
-
- // 6 Scratch data for mass matrix computation using "composite rigid body algorithm"
- /// mass of the subtree rooted in this body
- idScalar m_subtree_mass;
- /// center of mass * mass for subtree rooted in this body, in body-fixed frame
- vec3 m_body_subtree_mass_com;
- /// moment of inertia of subtree rooted in this body, w.r.t. body origin, in body-fixed frame
- mat33 m_body_subtree_I_body;
-
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// translational jacobian in body-fixed frame d(m_body_vel)/du
- mat3x m_body_Jac_T;
- /// rotationsl jacobian in body-fixed frame d(m_body_ang_vel)/du
- mat3x m_body_Jac_R;
- /// components of linear acceleration depending on u
- /// (same as is d(m_Jac_T)/dt*u)
- vec3 m_body_dot_Jac_T_u;
- /// components of angular acceleration depending on u
- /// (same as is d(m_Jac_T)/dt*u)
- vec3 m_body_dot_Jac_R_u;
-#endif
-};
-
-/// The MBS implements a tree structured multibody system
-class MultiBodyTree::MultiBodyImpl
-{
- friend class MultiBodyTree;
-
-public:
- ID_DECLARE_ALIGNED_ALLOCATOR();
-
- enum KinUpdateType
- {
- POSITION_ONLY,
- POSITION_VELOCITY,
- POSITION_VELOCITY_ACCELERATION
- };
-
- /// constructor
- /// @param num_bodies the number of bodies in the system
- /// @param num_dofs number of degrees of freedom in the system
- MultiBodyImpl(int num_bodies_, int num_dofs_);
-
- /// \copydoc MultiBodyTree::calculateInverseDynamics
- int calculateInverseDynamics(const vecx& q, const vecx& u, const vecx& dot_u,
- vecx* joint_forces);
- ///\copydoc MultiBodyTree::calculateMassMatrix
- int calculateMassMatrix(const vecx& q, const bool update_kinematics,
- const bool initialize_matrix, const bool set_lower_triangular_matrix,
- matxx* mass_matrix);
- /// calculate kinematics (vector quantities)
- /// Depending on type, update positions only, positions & velocities, or positions, velocities
- /// and accelerations.
- int calculateKinematics(const vecx& q, const vecx& u, const vecx& dot_u, const KinUpdateType type);
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- /// calculate jacobians and (if type == POSITION_VELOCITY), also velocity-dependent accelration terms.
- int calculateJacobians(const vecx& q, const vecx& u, const KinUpdateType type);
- /// \copydoc MultiBodyTree::getBodyDotJacobianTransU
- int getBodyDotJacobianTransU(const int body_index, vec3* world_dot_jac_trans_u) const;
- /// \copydoc MultiBodyTree::getBodyDotJacobianRotU
- int getBodyDotJacobianRotU(const int body_index, vec3* world_dot_jac_rot_u) const;
- /// \copydoc MultiBodyTree::getBodyJacobianTrans
- int getBodyJacobianTrans(const int body_index, mat3x* world_jac_trans) const;
- /// \copydoc MultiBodyTree::getBodyJacobianRot
- int getBodyJacobianRot(const int body_index, mat3x* world_jac_rot) const;
- /// Add relative Jacobian component from motion relative to parent body
- /// @param body the body to add the Jacobian component for
- void addRelativeJacobianComponent(RigidBody& body);
-#endif
- /// generate additional index sets from the parent_index array
- /// @return -1 on error, 0 on success
- int generateIndexSets();
- /// set gravity acceleration in world frame
- /// @param gravity gravity vector in the world frame
- /// @return 0 on success, -1 on error
- int setGravityInWorldFrame(const vec3& gravity);
- /// pretty print tree
- void printTree();
- /// print tree data
- void printTreeData();
- /// initialize fixed data
- void calculateStaticData();
- /// \copydoc MultiBodyTree::getBodyFrame
- int getBodyFrame(const int index, vec3* world_origin, mat33* body_T_world) const;
- /// \copydoc MultiBodyTree::getParentIndex
- int getParentIndex(const int body_index, int* m_parent_index);
- /// \copydoc MultiBodyTree::getJointType
- int getJointType(const int body_index, JointType* joint_type) const;
- /// \copydoc MultiBodyTree::getJointTypeStr
- int getJointTypeStr(const int body_index, const char** joint_type) const;
- /// \copydoc MultiBodyTree::getParentRParentBodyRef
- int getParentRParentBodyRef(const int body_index, vec3* r) const;
- /// \copydoc MultiBodyTree::getBodyTParentRef
- int getBodyTParentRef(const int body_index, mat33* T) const;
- /// \copydoc MultiBodyTree::getBodyAxisOfMotion
- int getBodyAxisOfMotion(const int body_index, vec3* axis) const;
- /// \copydoc MultiBodyTree:getDoFOffset
- int getDoFOffset(const int body_index, int* q_index) const;
- /// \copydoc MultiBodyTree::getBodyOrigin
- int getBodyOrigin(const int body_index, vec3* world_origin) const;
- /// \copydoc MultiBodyTree::getBodyCoM
- int getBodyCoM(const int body_index, vec3* world_com) const;
- /// \copydoc MultiBodyTree::getBodyTransform
- int getBodyTransform(const int body_index, mat33* world_T_body) const;
- /// \copydoc MultiBodyTree::getBodyAngularVelocity
- int getBodyAngularVelocity(const int body_index, vec3* world_omega) const;
- /// \copydoc MultiBodyTree::getBodyLinearVelocity
- int getBodyLinearVelocity(const int body_index, vec3* world_velocity) const;
- /// \copydoc MultiBodyTree::getBodyLinearVelocityCoM
- int getBodyLinearVelocityCoM(const int body_index, vec3* world_velocity) const;
- /// \copydoc MultiBodyTree::getBodyAngularAcceleration
- int getBodyAngularAcceleration(const int body_index, vec3* world_dot_omega) const;
- /// \copydoc MultiBodyTree::getBodyLinearAcceleration
- int getBodyLinearAcceleration(const int body_index, vec3* world_acceleration) const;
- /// \copydoc MultiBodyTree::getUserInt
- int getUserInt(const int body_index, int* user_int) const;
- /// \copydoc MultiBodyTree::getUserPtr
- int getUserPtr(const int body_index, void** user_ptr) const;
- /// \copydoc MultiBodyTree::setUserInt
- int setUserInt(const int body_index, const int user_int);
- /// \copydoc MultiBodyTree::setUserPtr
- int setUserPtr(const int body_index, void* const user_ptr);
- ///\copydoc MultiBodytTree::setBodyMass
- int setBodyMass(const int body_index, const idScalar mass);
- ///\copydoc MultiBodytTree::setBodyFirstMassMoment
- int setBodyFirstMassMoment(const int body_index, const vec3& first_mass_moment);
- ///\copydoc MultiBodytTree::setBodySecondMassMoment
- int setBodySecondMassMoment(const int body_index, const mat33& second_mass_moment);
- ///\copydoc MultiBodytTree::getBodyMass
- int getBodyMass(const int body_index, idScalar* mass) const;
- ///\copydoc MultiBodytTree::getBodyFirstMassMoment
- int getBodyFirstMassMoment(const int body_index, vec3* first_mass_moment) const;
- ///\copydoc MultiBodytTree::getBodySecondMassMoment
- int getBodySecondMassMoment(const int body_index, mat33* second_mass_moment) const;
- /// \copydoc MultiBodyTree::clearAllUserForcesAndMoments
- void clearAllUserForcesAndMoments();
- /// \copydoc MultiBodyTree::addUserForce
- int addUserForce(const int body_index, const vec3& body_force);
- /// \copydoc MultiBodyTree::addUserMoment
- int addUserMoment(const int body_index, const vec3& body_moment);
-
-private:
- // debug function. print tree structure to stdout
- void printTree(int index, int indentation);
- // get string representation of JointType (for debugging)
- const char* jointTypeToString(const JointType& type) const;
- // get number of degrees of freedom from joint type
- int bodyNumDoFs(const JointType& type) const;
- // number of bodies in the system
- int m_num_bodies;
- // number of degrees of freedom
- int m_num_dofs;
- // Gravitational acceleration (in world frame)
- vec3 m_world_gravity;
- // vector of bodies in the system
- // body 0 is used as an environment body and is allways fixed.
- // The bodies are ordered such that a parent body always has an index
- // smaller than its child.
- idArray<RigidBody>::type m_body_list;
- // Parent_index[i] is the index for i's parent body in body_list.
- // This fully describes the tree.
- idArray<int>::type m_parent_index;
- // child_indices[i] contains a vector of indices of
- // all children of the i-th body
- idArray<idArray<int>::type>::type m_child_indices;
- // Indices of rotary joints
- idArray<int>::type m_body_revolute_list;
- // Indices of prismatic joints
- idArray<int>::type m_body_prismatic_list;
- // Indices of floating joints
- idArray<int>::type m_body_floating_list;
- // Indices of spherical joints
- idArray<int>::type m_body_spherical_list;
- // a user-provided integer
- idArray<int>::type m_user_int;
- // a user-provided pointer
- idArray<void*>::type m_user_ptr;
-#if (defined BT_ID_HAVE_MAT3X) && (defined BT_ID_WITH_JACOBIANS)
- mat3x m_m3x;
-#endif
-};
-} // namespace btInverseDynamics
-#endif
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
deleted file mode 100644
index a718db051e..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#include "MultiBodyTreeInitCache.hpp"
-
-namespace btInverseDynamics
-{
-MultiBodyTree::InitCache::InitCache()
-{
- m_inertias.resize(0);
- m_joints.resize(0);
- m_num_dofs = 0;
- m_root_index = -1;
-}
-
-int MultiBodyTree::InitCache::addBody(const int body_index, const int parent_index,
- const JointType joint_type,
- const vec3& parent_r_parent_body_ref,
- const mat33& body_T_parent_ref,
- const vec3& body_axis_of_motion, const idScalar mass,
- const vec3& body_r_body_com, const mat33& body_I_body,
- const int user_int, void* user_ptr)
-{
- switch (joint_type)
- {
- case REVOLUTE:
- case PRISMATIC:
- m_num_dofs += 1;
- break;
- case FIXED:
- // does not add a degree of freedom
- // m_num_dofs+=0;
- break;
- case SPHERICAL:
- m_num_dofs += 3;
- break;
- case FLOATING:
- m_num_dofs += 6;
- break;
- default:
- bt_id_error_message("unknown joint type %d\n", joint_type);
- return -1;
- }
-
- if (-1 == parent_index)
- {
- if (m_root_index >= 0)
- {
- bt_id_error_message("trying to add body %d as root, but already added %d as root body\n",
- body_index, m_root_index);
- return -1;
- }
- m_root_index = body_index;
- }
-
- JointData joint;
- joint.m_child = body_index;
- joint.m_parent = parent_index;
- joint.m_type = joint_type;
- joint.m_parent_pos_parent_child_ref = parent_r_parent_body_ref;
- joint.m_child_T_parent_ref = body_T_parent_ref;
- joint.m_child_axis_of_motion = body_axis_of_motion;
-
- InertiaData body;
- body.m_mass = mass;
- body.m_body_pos_body_com = body_r_body_com;
- body.m_body_I_body = body_I_body;
-
- m_inertias.push_back(body);
- m_joints.push_back(joint);
- m_user_int.push_back(user_int);
- m_user_ptr.push_back(user_ptr);
- return 0;
-}
-int MultiBodyTree::InitCache::getInertiaData(const int index, InertiaData* inertia) const
-{
- if (index < 0 || index > static_cast<int>(m_inertias.size()))
- {
- bt_id_error_message("index out of range\n");
- return -1;
- }
-
- *inertia = m_inertias[index];
- return 0;
-}
-
-int MultiBodyTree::InitCache::getUserInt(const int index, int* user_int) const
-{
- if (index < 0 || index > static_cast<int>(m_user_int.size()))
- {
- bt_id_error_message("index out of range\n");
- return -1;
- }
- *user_int = m_user_int[index];
- return 0;
-}
-
-int MultiBodyTree::InitCache::getUserPtr(const int index, void** user_ptr) const
-{
- if (index < 0 || index > static_cast<int>(m_user_ptr.size()))
- {
- bt_id_error_message("index out of range\n");
- return -1;
- }
- *user_ptr = m_user_ptr[index];
- return 0;
-}
-
-int MultiBodyTree::InitCache::getJointData(const int index, JointData* joint) const
-{
- if (index < 0 || index > static_cast<int>(m_joints.size()))
- {
- bt_id_error_message("index out of range\n");
- return -1;
- }
- *joint = m_joints[index];
- return 0;
-}
-
-int MultiBodyTree::InitCache::buildIndexSets()
-{
- // NOTE: This function assumes that proper indices were provided
- // User2InternalIndex from utils can be used to facilitate this.
-
- m_parent_index.resize(numBodies());
- for (idArrayIdx j = 0; j < m_joints.size(); j++)
- {
- const JointData& joint = m_joints[j];
- m_parent_index[joint.m_child] = joint.m_parent;
- }
-
- return 0;
-}
-} // namespace btInverseDynamics
diff --git a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp b/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
deleted file mode 100644
index dbdb3ff604..0000000000
--- a/thirdparty/bullet/BulletInverseDynamics/details/MultiBodyTreeInitCache.hpp
+++ /dev/null
@@ -1,113 +0,0 @@
-#ifndef MULTIBODYTREEINITCACHE_HPP_
-#define MULTIBODYTREEINITCACHE_HPP_
-
-#include "../IDConfig.hpp"
-#include "../IDMath.hpp"
-#include "../MultiBodyTree.hpp"
-
-namespace btInverseDynamics
-{
-/// Mass properties of a rigid body
-struct InertiaData
-{
- ID_DECLARE_ALIGNED_ALLOCATOR();
-
- /// mass
- idScalar m_mass;
- /// vector from body-fixed frame to center of mass,
- /// in body-fixed frame, multiplied by the mass
- vec3 m_body_pos_body_com;
- /// moment of inertia w.r.t. the origin of the body-fixed
- /// frame, represented in that frame
- mat33 m_body_I_body;
-};
-
-/// Joint properties
-struct JointData
-{
- ID_DECLARE_ALIGNED_ALLOCATOR();
-
- /// type of joint
- JointType m_type;
- /// index of parent body
- int m_parent;
- /// index of child body
- int m_child;
- /// vector from parent's body-fixed frame to child's body-fixed
- /// frame for q=0, written in the parent's body fixed frame
- vec3 m_parent_pos_parent_child_ref;
- /// Transform matrix converting vectors written in the parent's frame
- /// into vectors written in the child's frame for q=0
- /// ie, child_vector = child_T_parent_ref * parent_vector;
- mat33 m_child_T_parent_ref;
- /// Axis of motion for 1 degree-of-freedom joints,
- /// written in the child's frame
- /// For revolute joints, the q-value is positive for a positive
- /// rotation about this axis.
- /// For prismatic joints, the q-value is positive for a positive
- /// translation is this direction.
- vec3 m_child_axis_of_motion;
-};
-
-/// Data structure to store data passed by the user.
-/// This is used in MultiBodyTree::finalize to build internal data structures.
-class MultiBodyTree::InitCache
-{
-public:
- ID_DECLARE_ALIGNED_ALLOCATOR();
- /// constructor
- InitCache();
- ///\copydoc MultiBodyTree::addBody
- int addBody(const int body_index, const int parent_index, const JointType joint_type,
- const vec3 &parent_r_parent_body_ref, const mat33 &body_T_parent_ref,
- const vec3 &body_axis_of_motion, idScalar mass, const vec3 &body_r_body_com,
- const mat33 &body_I_body, const int user_int, void *user_ptr);
- /// build index arrays
- /// @return 0 on success, -1 on failure
- int buildIndexSets();
- /// @return number of degrees of freedom
- int numDoFs() const { return m_num_dofs; }
- /// @return number of bodies
- int numBodies() const { return m_inertias.size(); }
- /// get inertia data for index
- /// @param index of the body
- /// @param inertia pointer for return data
- /// @return 0 on success, -1 on failure
- int getInertiaData(const int index, InertiaData *inertia) const;
- /// get joint data for index
- /// @param index of the body
- /// @param joint pointer for return data
- /// @return 0 on success, -1 on failure
- int getJointData(const int index, JointData *joint) const;
- /// get parent index array (paren_index[i] is the index of the parent of i)
- /// @param parent_index pointer for return data
- void getParentIndexArray(idArray<int>::type *parent_index) { *parent_index = m_parent_index; }
- /// get user integer
- /// @param index body index
- /// @param user_int user integer
- /// @return 0 on success, -1 on failure
- int getUserInt(const int index, int *user_int) const;
- /// get user pointer
- /// @param index body index
- /// @param user_int user pointer
- /// @return 0 on success, -1 on failure
- int getUserPtr(const int index, void **user_ptr) const;
-
-private:
- // vector of bodies
- idArray<InertiaData>::type m_inertias;
- // vector of joints
- idArray<JointData>::type m_joints;
- // number of mechanical degrees of freedom
- int m_num_dofs;
- // parent index array
- idArray<int>::type m_parent_index;
- // user integers
- idArray<int>::type m_user_int;
- // user pointers
- idArray<void *>::type m_user_ptr;
- // index of root body (or -1 if not set)
- int m_root_index;
-};
-} // namespace btInverseDynamics
-#endif // MULTIBODYTREEINITCACHE_HPP_
diff --git a/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h b/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
deleted file mode 100644
index 01c7e93a1b..0000000000
--- a/thirdparty/bullet/BulletSoftBody/DeformableBodyInplaceSolverIslandCallback.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// DeformableBodyInplaceSolverIslandCallback.h
-// BulletSoftBody
-//
-// Created by Xuchen Han on 12/16/19.
-//
-
-#ifndef DeformableBodyInplaceSolverIslandCallback_h
-#define DeformableBodyInplaceSolverIslandCallback_h
-
-struct DeformableBodyInplaceSolverIslandCallback : public MultiBodyInplaceSolverIslandCallback
-{
- btDeformableMultiBodyConstraintSolver* m_deformableSolver;
-
- DeformableBodyInplaceSolverIslandCallback(btDeformableMultiBodyConstraintSolver* solver,
- btDispatcher* dispatcher)
- : MultiBodyInplaceSolverIslandCallback(solver, dispatcher), m_deformableSolver(solver)
- {
- }
-
- virtual void processConstraints(int islandId = -1)
- {
- btCollisionObject** bodies = m_bodies.size() ? &m_bodies[0] : 0;
- btCollisionObject** softBodies = m_softBodies.size() ? &m_softBodies[0] : 0;
- btPersistentManifold** manifold = m_manifolds.size() ? &m_manifolds[0] : 0;
- btTypedConstraint** constraints = m_constraints.size() ? &m_constraints[0] : 0;
- btMultiBodyConstraint** multiBodyConstraints = m_multiBodyConstraints.size() ? &m_multiBodyConstraints[0] : 0;
-
- //printf("mb contacts = %d, mb constraints = %d\n", mbContacts, m_multiBodyConstraints.size());
-
- m_deformableSolver->solveDeformableBodyGroup(bodies, m_bodies.size(), softBodies, m_softBodies.size(), manifold, m_manifolds.size(), constraints, m_constraints.size(), multiBodyConstraints, m_multiBodyConstraints.size(), *m_solverInfo, m_debugDrawer, m_dispatcher);
- if (m_bodies.size() && (m_solverInfo->m_reportSolverAnalytics & 1))
- {
- m_deformableSolver->m_analyticsData.m_islandId = islandId;
- m_islandAnalyticsData.push_back(m_solver->m_analyticsData);
- }
- m_bodies.resize(0);
- m_softBodies.resize(0);
- m_manifolds.resize(0);
- m_constraints.resize(0);
- m_multiBodyConstraints.resize(0);
- }
-};
-
-#endif /* DeformableBodyInplaceSolverIslandCallback_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btCGProjection.h b/thirdparty/bullet/BulletSoftBody/btCGProjection.h
deleted file mode 100644
index e05970664c..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btCGProjection.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_CG_PROJECTION_H
-#define BT_CG_PROJECTION_H
-
-#include "btSoftBody.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-
-struct DeformableContactConstraint
-{
- const btSoftBody::Node* m_node;
- btAlignedObjectArray<const btSoftBody::RContact*> m_contact;
- btAlignedObjectArray<btVector3> m_total_normal_dv;
- btAlignedObjectArray<btVector3> m_total_tangent_dv;
- btAlignedObjectArray<bool> m_static;
- btAlignedObjectArray<bool> m_can_be_dynamic;
-
- DeformableContactConstraint(const btSoftBody::RContact& rcontact) : m_node(rcontact.m_node)
- {
- append(rcontact);
- }
-
- DeformableContactConstraint() : m_node(NULL)
- {
- m_contact.push_back(NULL);
- }
-
- void append(const btSoftBody::RContact& rcontact)
- {
- m_contact.push_back(&rcontact);
- m_total_normal_dv.push_back(btVector3(0, 0, 0));
- m_total_tangent_dv.push_back(btVector3(0, 0, 0));
- m_static.push_back(false);
- m_can_be_dynamic.push_back(true);
- }
-
- void replace(const btSoftBody::RContact& rcontact)
- {
- m_contact.clear();
- m_total_normal_dv.clear();
- m_total_tangent_dv.clear();
- m_static.clear();
- m_can_be_dynamic.clear();
- append(rcontact);
- }
-
- ~DeformableContactConstraint()
- {
- }
-};
-
-class btCGProjection
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- typedef btAlignedObjectArray<btAlignedObjectArray<btVector3> > TVArrayStack;
- typedef btAlignedObjectArray<btAlignedObjectArray<btScalar> > TArrayStack;
- btAlignedObjectArray<btSoftBody*>& m_softBodies;
- const btScalar& m_dt;
- // map from node indices to node pointers
- const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
-
- btCGProjection(btAlignedObjectArray<btSoftBody*>& softBodies, const btScalar& dt)
- : m_softBodies(softBodies), m_dt(dt)
- {
- }
-
- virtual ~btCGProjection()
- {
- }
-
- // apply the constraints
- virtual void project(TVStack& x) = 0;
-
- virtual void setConstraints() = 0;
-
- // update the constraints
- virtual btScalar update() = 0;
-
- virtual void reinitialize(bool nodeUpdated)
- {
- }
-
- virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
- {
- m_nodes = nodes;
- }
-};
-
-#endif /* btCGProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h b/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
deleted file mode 100644
index bcd5e6b519..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btConjugateGradient.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_CONJUGATE_GRADIENT_H
-#define BT_CONJUGATE_GRADIENT_H
-#include "btKrylovSolver.h"
-template <class MatrixX>
-class btConjugateGradient : public btKrylovSolver<MatrixX>
-{
- typedef btAlignedObjectArray<btVector3> TVStack;
- typedef btKrylovSolver<MatrixX> Base;
- TVStack r, p, z, temp;
-
-public:
- btConjugateGradient(const int max_it_in)
- : btKrylovSolver<MatrixX>(max_it_in, SIMD_EPSILON)
- {
- }
-
- virtual ~btConjugateGradient() {}
-
- // return the number of iterations taken
- int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
- {
- BT_PROFILE("CGSolve");
- btAssert(x.size() == b.size());
- reinitialize(b);
- temp = b;
- A.project(temp);
- p = temp;
- A.precondition(p, z);
- btScalar d0 = this->dot(z, temp);
- d0 = btMin(btScalar(1), d0);
- // r = b - A * x --with assigned dof zeroed out
- A.multiply(x, temp);
- r = this->sub(b, temp);
- A.project(r);
- // z = M^(-1) * r
- A.precondition(r, z);
- A.project(z);
- btScalar r_dot_z = this->dot(z, r);
- if (r_dot_z <= Base::m_tolerance * d0)
- {
- if (verbose)
- {
- std::cout << "Iteration = 0" << std::endl;
- std::cout << "Two norm of the residual = " << r_dot_z << std::endl;
- }
- return 0;
- }
- p = z;
- btScalar r_dot_z_new = r_dot_z;
- for (int k = 1; k <= Base::m_maxIterations; k++)
- {
- // temp = A*p
- A.multiply(p, temp);
- A.project(temp);
- if (this->dot(p, temp) < 0)
- {
- if (verbose)
- std::cout << "Encountered negative direction in CG!" << std::endl;
- if (k == 1)
- {
- x = b;
- }
- return k;
- }
- // alpha = r^T * z / (p^T * A * p)
- btScalar alpha = r_dot_z_new / this->dot(p, temp);
- // x += alpha * p;
- this->multAndAddTo(alpha, p, x);
- // r -= alpha * temp;
- this->multAndAddTo(-alpha, temp, r);
- // z = M^(-1) * r
- A.precondition(r, z);
- r_dot_z = r_dot_z_new;
- r_dot_z_new = this->dot(r, z);
- if (r_dot_z_new < Base::m_tolerance * d0)
- {
- if (verbose)
- {
- std::cout << "ConjugateGradient iterations " << k << " residual = " << r_dot_z_new << std::endl;
- }
- return k;
- }
-
- btScalar beta = r_dot_z_new / r_dot_z;
- p = this->multAndAdd(beta, p, z);
- }
- if (verbose)
- {
- std::cout << "ConjugateGradient max iterations reached " << Base::m_maxIterations << " error = " << r_dot_z_new << std::endl;
- }
- return Base::m_maxIterations;
- }
-
- void reinitialize(const TVStack& b)
- {
- r.resize(b.size());
- p.resize(b.size());
- z.resize(b.size());
- temp.resize(b.size());
- }
-};
-#endif /* btConjugateGradient_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h b/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h
deleted file mode 100644
index 6146120365..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btConjugateResidual.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_CONJUGATE_RESIDUAL_H
-#define BT_CONJUGATE_RESIDUAL_H
-#include "btKrylovSolver.h"
-
-template <class MatrixX>
-class btConjugateResidual : public btKrylovSolver<MatrixX>
-{
- typedef btAlignedObjectArray<btVector3> TVStack;
- typedef btKrylovSolver<MatrixX> Base;
- TVStack r, p, z, temp_p, temp_r, best_x;
- // temp_r = A*r
- // temp_p = A*p
- // z = M^(-1) * temp_p = M^(-1) * A * p
- btScalar best_r;
-
-public:
- btConjugateResidual(const int max_it_in)
- : Base(max_it_in, 1e-8)
- {
- }
-
- virtual ~btConjugateResidual() {}
-
- // return the number of iterations taken
- int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false)
- {
- BT_PROFILE("CRSolve");
- btAssert(x.size() == b.size());
- reinitialize(b);
- // r = b - A * x --with assigned dof zeroed out
- A.multiply(x, temp_r); // borrow temp_r here to store A*x
- r = this->sub(b, temp_r);
- // z = M^(-1) * r
- A.precondition(r, z); // borrow z to store preconditioned r
- r = z;
- btScalar residual_norm = this->norm(r);
- if (residual_norm <= Base::m_tolerance)
- {
- return 0;
- }
- p = r;
- btScalar r_dot_Ar, r_dot_Ar_new;
- // temp_p = A*p
- A.multiply(p, temp_p);
- // temp_r = A*r
- temp_r = temp_p;
- r_dot_Ar = this->dot(r, temp_r);
- for (int k = 1; k <= Base::m_maxIterations; k++)
- {
- // z = M^(-1) * Ap
- A.precondition(temp_p, z);
- // alpha = r^T * A * r / (Ap)^T * M^-1 * Ap)
- btScalar alpha = r_dot_Ar / this->dot(temp_p, z);
- // x += alpha * p;
- this->multAndAddTo(alpha, p, x);
- // r -= alpha * z;
- this->multAndAddTo(-alpha, z, r);
- btScalar norm_r = this->norm(r);
- if (norm_r < best_r)
- {
- best_x = x;
- best_r = norm_r;
- if (norm_r < Base::m_tolerance)
- {
- return k;
- }
- }
- // temp_r = A * r;
- A.multiply(r, temp_r);
- r_dot_Ar_new = this->dot(r, temp_r);
- btScalar beta = r_dot_Ar_new / r_dot_Ar;
- r_dot_Ar = r_dot_Ar_new;
- // p = beta*p + r;
- p = this->multAndAdd(beta, p, r);
- // temp_p = beta*temp_p + temp_r;
- temp_p = this->multAndAdd(beta, temp_p, temp_r);
- }
- if (verbose)
- {
- std::cout << "ConjugateResidual max iterations reached, residual = " << best_r << std::endl;
- }
- x = best_x;
- return Base::m_maxIterations;
- }
-
- void reinitialize(const TVStack& b)
- {
- r.resize(b.size());
- p.resize(b.size());
- z.resize(b.size());
- temp_p.resize(b.size());
- temp_r.resize(b.size());
- best_x.resize(b.size());
- best_r = SIMD_INFINITY;
- }
-};
-#endif /* btConjugateResidual_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
deleted file mode 100644
index 5a79ef86e2..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btCollisionShape.h"
-
-#include "btDefaultSoftBodySolver.h"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-#include "BulletSoftBody/btSoftBody.h"
-
-btDefaultSoftBodySolver::btDefaultSoftBodySolver()
-{
- // Initial we will clearly need to update solver constants
- // For now this is global for the cloths linked with this solver - we should probably make this body specific
- // for performance in future once we understand more clearly when constants need to be updated
- m_updateSolverConstants = true;
-}
-
-btDefaultSoftBodySolver::~btDefaultSoftBodySolver()
-{
-}
-
-// In this case the data is already in the soft bodies so there is no need for us to do anything
-void btDefaultSoftBodySolver::copyBackToSoftBodies(bool bMove)
-{
-}
-
-void btDefaultSoftBodySolver::optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate)
-{
- m_softBodySet.copyFromArray(softBodies);
-}
-
-void btDefaultSoftBodySolver::updateSoftBodies()
-{
- for (int i = 0; i < m_softBodySet.size(); i++)
- {
- btSoftBody *psb = (btSoftBody *)m_softBodySet[i];
- if (psb->isActive())
- {
- psb->integrateMotion();
- }
- }
-} // updateSoftBodies
-
-bool btDefaultSoftBodySolver::checkInitialized()
-{
- return true;
-}
-
-void btDefaultSoftBodySolver::solveConstraints(btScalar solverdt)
-{
- // Solve constraints for non-solver softbodies
- for (int i = 0; i < m_softBodySet.size(); ++i)
- {
- btSoftBody *psb = static_cast<btSoftBody *>(m_softBodySet[i]);
- if (psb->isActive())
- {
- psb->solveConstraints();
- }
- }
-} // btDefaultSoftBodySolver::solveConstraints
-
-void btDefaultSoftBodySolver::copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer)
-{
- // Currently only support CPU output buffers
- // TODO: check for DX11 buffers. Take all offsets into the same DX11 buffer
- // and use them together on a single kernel call if possible by setting up a
- // per-cloth target buffer array for the copy kernel.
-
- if (vertexBuffer->getBufferType() == btVertexBufferDescriptor::CPU_BUFFER)
- {
- const btAlignedObjectArray<btSoftBody::Node> &clothVertices(softBody->m_nodes);
- int numVertices = clothVertices.size();
-
- const btCPUVertexBufferDescriptor *cpuVertexBuffer = static_cast<btCPUVertexBufferDescriptor *>(vertexBuffer);
- float *basePointer = cpuVertexBuffer->getBasePointer();
-
- if (vertexBuffer->hasVertexPositions())
- {
- const int vertexOffset = cpuVertexBuffer->getVertexOffset();
- const int vertexStride = cpuVertexBuffer->getVertexStride();
- float *vertexPointer = basePointer + vertexOffset;
-
- for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
- {
- btVector3 position = clothVertices[vertexIndex].m_x;
- *(vertexPointer + 0) = (float)position.getX();
- *(vertexPointer + 1) = (float)position.getY();
- *(vertexPointer + 2) = (float)position.getZ();
- vertexPointer += vertexStride;
- }
- }
- if (vertexBuffer->hasNormals())
- {
- const int normalOffset = cpuVertexBuffer->getNormalOffset();
- const int normalStride = cpuVertexBuffer->getNormalStride();
- float *normalPointer = basePointer + normalOffset;
-
- for (int vertexIndex = 0; vertexIndex < numVertices; ++vertexIndex)
- {
- btVector3 normal = clothVertices[vertexIndex].m_n;
- *(normalPointer + 0) = (float)normal.getX();
- *(normalPointer + 1) = (float)normal.getY();
- *(normalPointer + 2) = (float)normal.getZ();
- normalPointer += normalStride;
- }
- }
- }
-} // btDefaultSoftBodySolver::copySoftBodyToVertexBuffer
-
-void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, btSoftBody *otherSoftBody)
-{
- softBody->defaultCollisionHandler(otherSoftBody);
-}
-
-// For the default solver just leave the soft body to do its collision processing
-void btDefaultSoftBodySolver::processCollision(btSoftBody *softBody, const btCollisionObjectWrapper *collisionObjectWrap)
-{
- softBody->defaultCollisionHandler(collisionObjectWrap);
-} // btDefaultSoftBodySolver::processCollision
-
-void btDefaultSoftBodySolver::predictMotion(btScalar timeStep)
-{
- for (int i = 0; i < m_softBodySet.size(); ++i)
- {
- btSoftBody *psb = m_softBodySet[i];
-
- if (psb->isActive())
- {
- psb->predictMotion(timeStep);
- }
- }
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
deleted file mode 100644
index 3965b07c58..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDefaultSoftBodySolver.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_BODY_DEFAULT_SOLVER_H
-#define BT_SOFT_BODY_DEFAULT_SOLVER_H
-
-#include "BulletSoftBody/btSoftBodySolvers.h"
-#include "btSoftBodySolverVertexBuffer.h"
-struct btCollisionObjectWrapper;
-
-class btDefaultSoftBodySolver : public btSoftBodySolver
-{
-protected:
- /** Variable to define whether we need to update solver constants on the next iteration */
- bool m_updateSolverConstants;
-
- btAlignedObjectArray<btSoftBody *> m_softBodySet;
-
-public:
- btDefaultSoftBodySolver();
-
- virtual ~btDefaultSoftBodySolver();
-
- virtual SolverTypes getSolverType() const
- {
- return DEFAULT_SOLVER;
- }
-
- virtual bool checkInitialized();
-
- virtual void updateSoftBodies();
-
- virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false);
-
- virtual void copyBackToSoftBodies(bool bMove = true);
-
- virtual void solveConstraints(btScalar solverdt);
-
- virtual void predictMotion(btScalar solverdt);
-
- virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer);
-
- virtual void processCollision(btSoftBody *, const btCollisionObjectWrapper *);
-
- virtual void processCollision(btSoftBody *, btSoftBody *);
-};
-
-#endif // #ifndef BT_ACCELERATED_SOFT_BODY_CPU_SOLVER_H
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
deleted file mode 100644
index 2455ed2138..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "btDeformableBackwardEulerObjective.h"
-#include "btPreconditioner.h"
-#include "LinearMath/btQuickprof.h"
-
-btDeformableBackwardEulerObjective::btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody*>& softBodies, const TVStack& backup_v)
- : m_softBodies(softBodies), m_projection(softBodies), m_backupVelocity(backup_v), m_implicit(false)
-{
- m_massPreconditioner = new MassPreconditioner(m_softBodies);
- m_KKTPreconditioner = new KKTPreconditioner(m_softBodies, m_projection, m_lf, m_dt, m_implicit);
- m_preconditioner = m_KKTPreconditioner;
-}
-
-btDeformableBackwardEulerObjective::~btDeformableBackwardEulerObjective()
-{
- delete m_KKTPreconditioner;
- delete m_massPreconditioner;
-}
-
-void btDeformableBackwardEulerObjective::reinitialize(bool nodeUpdated, btScalar dt)
-{
- BT_PROFILE("reinitialize");
- if (dt > 0)
- {
- setDt(dt);
- }
- if (nodeUpdated)
- {
- updateId();
- }
- for (int i = 0; i < m_lf.size(); ++i)
- {
- m_lf[i]->reinitialize(nodeUpdated);
- }
- btMatrix3x3 I;
- I.setIdentity();
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (psb->m_nodes[j].m_im > 0)
- psb->m_nodes[j].m_effectiveMass = I * (1.0 / psb->m_nodes[j].m_im);
- }
- }
- m_projection.reinitialize(nodeUpdated);
- // m_preconditioner->reinitialize(nodeUpdated);
-}
-
-void btDeformableBackwardEulerObjective::setDt(btScalar dt)
-{
- m_dt = dt;
-}
-
-void btDeformableBackwardEulerObjective::multiply(const TVStack& x, TVStack& b) const
-{
- BT_PROFILE("multiply");
- // add in the mass term
- size_t counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- b[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : x[counter] / node.m_im;
- ++counter;
- }
- }
-
- for (int i = 0; i < m_lf.size(); ++i)
- {
- // add damping matrix
- m_lf[i]->addScaledDampingForceDifferential(-m_dt, x, b);
- // Always integrate picking force implicitly for stability.
- if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
- {
- m_lf[i]->addScaledElasticForceDifferential(-m_dt * m_dt, x, b);
- }
- }
- int offset = m_nodes.size();
- for (int i = offset; i < b.size(); ++i)
- {
- b[i].setZero();
- }
- // add in the lagrange multiplier terms
-
- for (int c = 0; c < m_projection.m_lagrangeMultipliers.size(); ++c)
- {
- // C^T * lambda
- const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[c];
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- for (int j = 0; j < lm.m_num_constraints; ++j)
- {
- b[lm.m_indices[i]] += x[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
- }
- }
- // C * x
- for (int d = 0; d < lm.m_num_constraints; ++d)
- {
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- b[offset + c][d] += lm.m_weights[i] * x[lm.m_indices[i]].dot(lm.m_dirs[d]);
- }
- }
- }
-}
-
-void btDeformableBackwardEulerObjective::updateVelocity(const TVStack& dv)
-{
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btSoftBody::Node& node = psb->m_nodes[j];
- node.m_v = m_backupVelocity[node.index] + dv[node.index];
- }
- }
-}
-
-void btDeformableBackwardEulerObjective::applyForce(TVStack& force, bool setZero)
-{
- size_t counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- counter += psb->m_nodes.size();
- continue;
- }
- if (m_implicit)
- {
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (psb->m_nodes[j].m_im != 0)
- {
- psb->m_nodes[j].m_v += psb->m_nodes[j].m_effectiveMass_inv * force[counter++];
- }
- }
- }
- else
- {
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btScalar one_over_mass = (psb->m_nodes[j].m_im == 0) ? 0 : psb->m_nodes[j].m_im;
- psb->m_nodes[j].m_v += one_over_mass * force[counter++];
- }
- }
- }
- if (setZero)
- {
- for (int i = 0; i < force.size(); ++i)
- force[i].setZero();
- }
-}
-
-void btDeformableBackwardEulerObjective::computeResidual(btScalar dt, TVStack& residual)
-{
- BT_PROFILE("computeResidual");
- // add implicit force
- for (int i = 0; i < m_lf.size(); ++i)
- {
- // Always integrate picking force implicitly for stability.
- if (m_implicit || m_lf[i]->getForceType() == BT_MOUSE_PICKING_FORCE)
- {
- m_lf[i]->addScaledForces(dt, residual);
- }
- else
- {
- m_lf[i]->addScaledDampingForce(dt, residual);
- }
- }
- // m_projection.project(residual);
-}
-
-btScalar btDeformableBackwardEulerObjective::computeNorm(const TVStack& residual) const
-{
- btScalar mag = 0;
- for (int i = 0; i < residual.size(); ++i)
- {
- mag += residual[i].length2();
- }
- return std::sqrt(mag);
-}
-
-btScalar btDeformableBackwardEulerObjective::totalEnergy(btScalar dt)
-{
- btScalar e = 0;
- for (int i = 0; i < m_lf.size(); ++i)
- {
- e += m_lf[i]->totalEnergy(dt);
- }
- return e;
-}
-
-void btDeformableBackwardEulerObjective::applyExplicitForce(TVStack& force)
-{
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- m_softBodies[i]->advanceDeformation();
- }
- if (m_implicit)
- {
- // apply forces except gravity force
- btVector3 gravity;
- for (int i = 0; i < m_lf.size(); ++i)
- {
- if (m_lf[i]->getForceType() == BT_GRAVITY_FORCE)
- {
- gravity = static_cast<btDeformableGravityForce*>(m_lf[i])->m_gravity;
- }
- else
- {
- m_lf[i]->addScaledForces(m_dt, force);
- }
- }
- for (int i = 0; i < m_lf.size(); ++i)
- {
- m_lf[i]->addScaledHessian(m_dt);
- }
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- // add gravity explicitly
- psb->m_nodes[j].m_v += m_dt * psb->m_gravityFactor * gravity;
- }
- }
- }
- }
- else
- {
- for (int i = 0; i < m_lf.size(); ++i)
- {
- m_lf[i]->addScaledExplicitForce(m_dt, force);
- }
- }
- // calculate inverse mass matrix for all nodes
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (psb->m_nodes[j].m_im > 0)
- {
- psb->m_nodes[j].m_effectiveMass_inv = psb->m_nodes[j].m_effectiveMass.inverse();
- }
- }
- }
- }
- applyForce(force, true);
-}
-
-void btDeformableBackwardEulerObjective::initialGuess(TVStack& dv, const TVStack& residual)
-{
- size_t counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- dv[counter] = psb->m_nodes[j].m_im * residual[counter];
- ++counter;
- }
- }
-}
-
-//set constraints as projections
-void btDeformableBackwardEulerObjective::setConstraints(const btContactSolverInfo& infoGlobal)
-{
- m_projection.setConstraints(infoGlobal);
-}
-
-void btDeformableBackwardEulerObjective::applyDynamicFriction(TVStack& r)
-{
- m_projection.applyDynamicFriction(r);
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h b/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
deleted file mode 100644
index eb05b9f010..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableBackwardEulerObjective.h
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_BACKWARD_EULER_OBJECTIVE_H
-#define BT_BACKWARD_EULER_OBJECTIVE_H
-//#include "btConjugateGradient.h"
-#include "btDeformableLagrangianForce.h"
-#include "btDeformableMassSpringForce.h"
-#include "btDeformableGravityForce.h"
-#include "btDeformableCorotatedForce.h"
-#include "btDeformableMousePickingForce.h"
-#include "btDeformableLinearElasticityForce.h"
-#include "btDeformableNeoHookeanForce.h"
-#include "btDeformableContactProjection.h"
-#include "btPreconditioner.h"
-#include "btDeformableMultiBodyDynamicsWorld.h"
-#include "LinearMath/btQuickprof.h"
-
-class btDeformableBackwardEulerObjective
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btScalar m_dt;
- btAlignedObjectArray<btDeformableLagrangianForce*> m_lf;
- btAlignedObjectArray<btSoftBody*>& m_softBodies;
- Preconditioner* m_preconditioner;
- btDeformableContactProjection m_projection;
- const TVStack& m_backupVelocity;
- btAlignedObjectArray<btSoftBody::Node*> m_nodes;
- bool m_implicit;
- MassPreconditioner* m_massPreconditioner;
- KKTPreconditioner* m_KKTPreconditioner;
-
- btDeformableBackwardEulerObjective(btAlignedObjectArray<btSoftBody*>& softBodies, const TVStack& backup_v);
-
- virtual ~btDeformableBackwardEulerObjective();
-
- void initialize() {}
-
- // compute the rhs for CG solve, i.e, add the dt scaled implicit force to residual
- void computeResidual(btScalar dt, TVStack& residual);
-
- // add explicit force to the velocity
- void applyExplicitForce(TVStack& force);
-
- // apply force to velocity and optionally reset the force to zero
- void applyForce(TVStack& force, bool setZero);
-
- // compute the norm of the residual
- btScalar computeNorm(const TVStack& residual) const;
-
- // compute one step of the solve (there is only one solve if the system is linear)
- void computeStep(TVStack& dv, const TVStack& residual, const btScalar& dt);
-
- // perform A*x = b
- void multiply(const TVStack& x, TVStack& b) const;
-
- // set initial guess for CG solve
- void initialGuess(TVStack& dv, const TVStack& residual);
-
- // reset data structure and reset dt
- void reinitialize(bool nodeUpdated, btScalar dt);
-
- void setDt(btScalar dt);
-
- // add friction force to residual
- void applyDynamicFriction(TVStack& r);
-
- // add dv to velocity
- void updateVelocity(const TVStack& dv);
-
- //set constraints as projections
- void setConstraints(const btContactSolverInfo& infoGlobal);
-
- // update the projections and project the residual
- void project(TVStack& r)
- {
- BT_PROFILE("project");
- m_projection.project(r);
- }
-
- // perform precondition M^(-1) x = b
- void precondition(const TVStack& x, TVStack& b)
- {
- m_preconditioner->operator()(x, b);
- }
-
- // reindex all the vertices
- virtual void updateId()
- {
- size_t node_id = 0;
- size_t face_id = 0;
- m_nodes.clear();
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].index = node_id;
- m_nodes.push_back(&psb->m_nodes[j]);
- ++node_id;
- }
- for (int j = 0; j < psb->m_faces.size(); ++j)
- {
- psb->m_faces[j].m_index = face_id;
- ++face_id;
- }
- }
- }
-
- const btAlignedObjectArray<btSoftBody::Node*>* getIndices() const
- {
- return &m_nodes;
- }
-
- void setImplicit(bool implicit)
- {
- m_implicit = implicit;
- }
-
- // Calculate the total potential energy in the system
- btScalar totalEnergy(btScalar dt);
-
- void addLagrangeMultiplier(const TVStack& vec, TVStack& extended_vec)
- {
- extended_vec.resize(vec.size() + m_projection.m_lagrangeMultipliers.size());
- for (int i = 0; i < vec.size(); ++i)
- {
- extended_vec[i] = vec[i];
- }
- int offset = vec.size();
- for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
- {
- extended_vec[offset + i].setZero();
- }
- }
-
- void addLagrangeMultiplierRHS(const TVStack& residual, const TVStack& m_dv, TVStack& extended_residual)
- {
- extended_residual.resize(residual.size() + m_projection.m_lagrangeMultipliers.size());
- for (int i = 0; i < residual.size(); ++i)
- {
- extended_residual[i] = residual[i];
- }
- int offset = residual.size();
- for (int i = 0; i < m_projection.m_lagrangeMultipliers.size(); ++i)
- {
- const LagrangeMultiplier& lm = m_projection.m_lagrangeMultipliers[i];
- extended_residual[offset + i].setZero();
- for (int d = 0; d < lm.m_num_constraints; ++d)
- {
- for (int n = 0; n < lm.m_num_nodes; ++n)
- {
- extended_residual[offset + i][d] += lm.m_weights[n] * m_dv[lm.m_indices[n]].dot(lm.m_dirs[d]);
- }
- }
- }
- }
-
- void calculateContactForce(const TVStack& dv, const TVStack& rhs, TVStack& f)
- {
- size_t counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- f[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : dv[counter] / node.m_im;
- ++counter;
- }
- }
- for (int i = 0; i < m_lf.size(); ++i)
- {
- // add damping matrix
- m_lf[i]->addScaledDampingForceDifferential(-m_dt, dv, f);
- }
- counter = 0;
- for (; counter < f.size(); ++counter)
- {
- f[counter] = rhs[counter] - f[counter];
- }
- }
-};
-
-#endif /* btBackwardEulerObjective_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
deleted file mode 100644
index e81680f019..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.cpp
+++ /dev/null
@@ -1,506 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include <stdio.h>
-#include <limits>
-#include "btDeformableBodySolver.h"
-#include "btSoftBodyInternals.h"
-#include "LinearMath/btQuickprof.h"
-static const int kMaxConjugateGradientIterations = 300;
-btDeformableBodySolver::btDeformableBodySolver()
- : m_numNodes(0), m_cg(kMaxConjugateGradientIterations), m_cr(kMaxConjugateGradientIterations), m_maxNewtonIterations(1), m_newtonTolerance(1e-4), m_lineSearch(false), m_useProjection(false)
-{
- m_objective = new btDeformableBackwardEulerObjective(m_softBodies, m_backupVelocity);
-}
-
-btDeformableBodySolver::~btDeformableBodySolver()
-{
- delete m_objective;
-}
-
-void btDeformableBodySolver::solveDeformableConstraints(btScalar solverdt)
-{
- BT_PROFILE("solveDeformableConstraints");
- if (!m_implicit)
- {
- m_objective->computeResidual(solverdt, m_residual);
- m_objective->applyDynamicFriction(m_residual);
- if (m_useProjection)
- {
- computeStep(m_dv, m_residual);
- }
- else
- {
- TVStack rhs, x;
- m_objective->addLagrangeMultiplierRHS(m_residual, m_dv, rhs);
- m_objective->addLagrangeMultiplier(m_dv, x);
- m_objective->m_preconditioner->reinitialize(true);
- computeStep(x, rhs);
- for (int i = 0; i < m_dv.size(); ++i)
- {
- m_dv[i] = x[i];
- }
- }
- updateVelocity();
- }
- else
- {
- for (int i = 0; i < m_maxNewtonIterations; ++i)
- {
- updateState();
- // add the inertia term in the residual
- int counter = 0;
- for (int k = 0; k < m_softBodies.size(); ++k)
- {
- btSoftBody* psb = m_softBodies[k];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (psb->m_nodes[j].m_im > 0)
- {
- m_residual[counter] = (-1. / psb->m_nodes[j].m_im) * m_dv[counter];
- }
- ++counter;
- }
- }
-
- m_objective->computeResidual(solverdt, m_residual);
- if (m_objective->computeNorm(m_residual) < m_newtonTolerance && i > 0)
- {
- break;
- }
- // todo xuchenhan@: this really only needs to be calculated once
- m_objective->applyDynamicFriction(m_residual);
- if (m_lineSearch)
- {
- btScalar inner_product = computeDescentStep(m_ddv, m_residual);
- btScalar alpha = 0.01, beta = 0.5; // Boyd & Vandenberghe suggested alpha between 0.01 and 0.3, beta between 0.1 to 0.8
- btScalar scale = 2;
- btScalar f0 = m_objective->totalEnergy(solverdt) + kineticEnergy(), f1, f2;
- backupDv();
- do
- {
- scale *= beta;
- if (scale < 1e-8)
- {
- return;
- }
- updateEnergy(scale);
- f1 = m_objective->totalEnergy(solverdt) + kineticEnergy();
- f2 = f0 - alpha * scale * inner_product;
- } while (!(f1 < f2 + SIMD_EPSILON)); // if anything here is nan then the search continues
- revertDv();
- updateDv(scale);
- }
- else
- {
- computeStep(m_ddv, m_residual);
- updateDv();
- }
- for (int j = 0; j < m_numNodes; ++j)
- {
- m_ddv[j].setZero();
- m_residual[j].setZero();
- }
- }
- updateVelocity();
- }
-}
-
-btScalar btDeformableBodySolver::kineticEnergy()
-{
- btScalar ke = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btSoftBody::Node& node = psb->m_nodes[j];
- if (node.m_im > 0)
- {
- ke += m_dv[node.index].length2() * 0.5 / node.m_im;
- }
- }
- }
- return ke;
-}
-
-void btDeformableBodySolver::backupDv()
-{
- m_backup_dv.resize(m_dv.size());
- for (int i = 0; i < m_backup_dv.size(); ++i)
- {
- m_backup_dv[i] = m_dv[i];
- }
-}
-
-void btDeformableBodySolver::revertDv()
-{
- for (int i = 0; i < m_backup_dv.size(); ++i)
- {
- m_dv[i] = m_backup_dv[i];
- }
-}
-
-void btDeformableBodySolver::updateEnergy(btScalar scale)
-{
- for (int i = 0; i < m_dv.size(); ++i)
- {
- m_dv[i] = m_backup_dv[i] + scale * m_ddv[i];
- }
- updateState();
-}
-
-btScalar btDeformableBodySolver::computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose)
-{
- m_cg.solve(*m_objective, ddv, residual, false);
- btScalar inner_product = m_cg.dot(residual, m_ddv);
- btScalar res_norm = m_objective->computeNorm(residual);
- btScalar tol = 1e-5 * res_norm * m_objective->computeNorm(m_ddv);
- if (inner_product < -tol)
- {
- if (verbose)
- {
- std::cout << "Looking backwards!" << std::endl;
- }
- for (int i = 0; i < m_ddv.size(); ++i)
- {
- m_ddv[i] = -m_ddv[i];
- }
- inner_product = -inner_product;
- }
- else if (std::abs(inner_product) < tol)
- {
- if (verbose)
- {
- std::cout << "Gradient Descent!" << std::endl;
- }
- btScalar scale = m_objective->computeNorm(m_ddv) / res_norm;
- for (int i = 0; i < m_ddv.size(); ++i)
- {
- m_ddv[i] = scale * residual[i];
- }
- inner_product = scale * res_norm * res_norm;
- }
- return inner_product;
-}
-
-void btDeformableBodySolver::updateState()
-{
- updateVelocity();
- updateTempPosition();
-}
-
-void btDeformableBodySolver::updateDv(btScalar scale)
-{
- for (int i = 0; i < m_numNodes; ++i)
- {
- m_dv[i] += scale * m_ddv[i];
- }
-}
-
-void btDeformableBodySolver::computeStep(TVStack& ddv, const TVStack& residual)
-{
- if (m_useProjection)
- m_cg.solve(*m_objective, ddv, residual, false);
- else
- m_cr.solve(*m_objective, ddv, residual, false);
-}
-
-void btDeformableBodySolver::reinitialize(const btAlignedObjectArray<btSoftBody*>& softBodies, btScalar dt)
-{
- m_softBodies.copyFromArray(softBodies);
- bool nodeUpdated = updateNodes();
-
- if (nodeUpdated)
- {
- m_dv.resize(m_numNodes, btVector3(0, 0, 0));
- m_ddv.resize(m_numNodes, btVector3(0, 0, 0));
- m_residual.resize(m_numNodes, btVector3(0, 0, 0));
- m_backupVelocity.resize(m_numNodes, btVector3(0, 0, 0));
- }
-
- // need to setZero here as resize only set value for newly allocated items
- for (int i = 0; i < m_numNodes; ++i)
- {
- m_dv[i].setZero();
- m_ddv[i].setZero();
- m_residual[i].setZero();
- }
-
- if (dt > 0)
- {
- m_dt = dt;
- }
- m_objective->reinitialize(nodeUpdated, dt);
- updateSoftBodies();
-}
-
-void btDeformableBodySolver::setConstraints(const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("setConstraint");
- m_objective->setConstraints(infoGlobal);
-}
-
-btScalar btDeformableBodySolver::solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("solveContactConstraints");
- btScalar maxSquaredResidual = m_objective->m_projection.update(deformableBodies, numDeformableBodies, infoGlobal);
- return maxSquaredResidual;
-}
-
-void btDeformableBodySolver::updateVelocity()
-{
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- psb->m_maxSpeedSquared = 0;
- if (!psb->isActive())
- {
- counter += psb->m_nodes.size();
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- // set NaN to zero;
- if (m_dv[counter] != m_dv[counter])
- {
- m_dv[counter].setZero();
- }
- if (m_implicit)
- {
- psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter];
- }
- else
- {
- psb->m_nodes[j].m_v = m_backupVelocity[counter] + m_dv[counter] - psb->m_nodes[j].m_splitv;
- }
- psb->m_maxSpeedSquared = btMax(psb->m_maxSpeedSquared, psb->m_nodes[j].m_v.length2());
- ++counter;
- }
- }
-}
-
-void btDeformableBodySolver::updateTempPosition()
-{
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- counter += psb->m_nodes.size();
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + m_dt * (psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv);
- ++counter;
- }
- psb->updateDeformation();
- }
-}
-
-void btDeformableBodySolver::backupVelocity()
-{
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- m_backupVelocity[counter++] = psb->m_nodes[j].m_v;
- }
- }
-}
-
-void btDeformableBodySolver::setupDeformableSolve(bool implicit)
-{
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- counter += psb->m_nodes.size();
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (implicit)
- {
- // setting the initial guess for newton, need m_dv = v_{n+1} - v_n for dofs that are in constraint.
- if (psb->m_nodes[j].m_v == m_backupVelocity[counter])
- m_dv[counter].setZero();
- else
- m_dv[counter] = psb->m_nodes[j].m_v - psb->m_nodes[j].m_vn;
- m_backupVelocity[counter] = psb->m_nodes[j].m_vn;
- }
- else
- {
- m_dv[counter] = psb->m_nodes[j].m_v + psb->m_nodes[j].m_splitv - m_backupVelocity[counter];
- }
- psb->m_nodes[j].m_v = m_backupVelocity[counter];
- ++counter;
- }
- }
-}
-
-void btDeformableBodySolver::revertVelocity()
-{
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_v = m_backupVelocity[counter++];
- }
- }
-}
-
-bool btDeformableBodySolver::updateNodes()
-{
- int numNodes = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- numNodes += m_softBodies[i]->m_nodes.size();
- if (numNodes != m_numNodes)
- {
- m_numNodes = numNodes;
- return true;
- }
- return false;
-}
-
-void btDeformableBodySolver::predictMotion(btScalar solverdt)
-{
- // apply explicit forces to velocity
- if (m_implicit)
- {
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + psb->m_nodes[j].m_v * solverdt;
- }
- }
- }
- }
- m_objective->applyExplicitForce(m_residual);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- /* Clear contacts */
- psb->m_nodeRigidContacts.resize(0);
- psb->m_faceRigidContacts.resize(0);
- psb->m_faceNodeContacts.resize(0);
-
- if (psb->isActive())
- {
- // predict motion for collision detection
- predictDeformableMotion(psb, solverdt);
- }
- }
-}
-
-void btDeformableBodySolver::predictDeformableMotion(btSoftBody* psb, btScalar dt)
-{
- BT_PROFILE("btDeformableBodySolver::predictDeformableMotion");
- int i, ni;
-
- /* Update */
- if (psb->m_bUpdateRtCst)
- {
- psb->m_bUpdateRtCst = false;
- psb->updateConstants();
- psb->m_fdbvt.clear();
- if (psb->m_cfg.collisions & btSoftBody::fCollision::SDF_RD)
- {
- psb->initializeFaceTree();
- }
- }
-
- /* Prepare */
- psb->m_sst.sdt = dt * psb->m_cfg.timescale;
- psb->m_sst.isdt = 1 / psb->m_sst.sdt;
- psb->m_sst.velmrg = psb->m_sst.sdt * 3;
- psb->m_sst.radmrg = psb->getCollisionShape()->getMargin();
- psb->m_sst.updmrg = psb->m_sst.radmrg * (btScalar)0.25;
- /* Bounds */
- psb->updateBounds();
-
- /* Integrate */
- // do not allow particles to move more than the bounding box size
- btScalar max_v = (psb->m_bounds[1] - psb->m_bounds[0]).norm() / dt;
- for (i = 0, ni = psb->m_nodes.size(); i < ni; ++i)
- {
- btSoftBody::Node& n = psb->m_nodes[i];
- // apply drag
- n.m_v *= (1 - psb->m_cfg.drag);
- // scale velocity back
- if (m_implicit)
- {
- n.m_q = n.m_x;
- }
- else
- {
- if (n.m_v.norm() > max_v)
- {
- n.m_v.safeNormalize();
- n.m_v *= max_v;
- }
- n.m_q = n.m_x + n.m_v * dt;
- }
- n.m_splitv.setZero();
- n.m_constrained = false;
- }
-
- /* Nodes */
- psb->updateNodeTree(true, true);
- if (!psb->m_fdbvt.empty())
- {
- psb->updateFaceTree(true, true);
- }
- /* Optimize dbvt's */
- // psb->m_ndbvt.optimizeIncremental(1);
- // psb->m_fdbvt.optimizeIncremental(1);
-}
-
-void btDeformableBodySolver::updateSoftBodies()
-{
- BT_PROFILE("updateSoftBodies");
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)m_softBodies[i];
- if (psb->isActive())
- {
- psb->updateNormals();
- }
- }
-}
-
-void btDeformableBodySolver::setImplicit(bool implicit)
-{
- m_implicit = implicit;
- m_objective->setImplicit(implicit);
-}
-
-void btDeformableBodySolver::setLineSearch(bool lineSearch)
-{
- m_lineSearch = lineSearch;
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
deleted file mode 100644
index ae674d6e89..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableBodySolver.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_BODY_SOLVERS_H
-#define BT_DEFORMABLE_BODY_SOLVERS_H
-
-#include "btSoftBodySolvers.h"
-#include "btDeformableBackwardEulerObjective.h"
-#include "btDeformableMultiBodyDynamicsWorld.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-#include "btConjugateResidual.h"
-#include "btConjugateGradient.h"
-struct btCollisionObjectWrapper;
-class btDeformableBackwardEulerObjective;
-class btDeformableMultiBodyDynamicsWorld;
-
-class btDeformableBodySolver : public btSoftBodySolver
-{
- typedef btAlignedObjectArray<btVector3> TVStack;
-
-protected:
- int m_numNodes; // total number of deformable body nodes
- TVStack m_dv; // v_{n+1} - v_n
- TVStack m_backup_dv; // backed up dv
- TVStack m_ddv; // incremental dv
- TVStack m_residual; // rhs of the linear solve
- btAlignedObjectArray<btSoftBody*> m_softBodies; // all deformable bodies
- TVStack m_backupVelocity; // backed up v, equals v_n for implicit, equals v_{n+1}^* for explicit
- btScalar m_dt; // dt
- btConjugateGradient<btDeformableBackwardEulerObjective> m_cg; // CG solver
- btConjugateResidual<btDeformableBackwardEulerObjective> m_cr; // CR solver
- bool m_implicit; // use implicit scheme if true, explicit scheme if false
- int m_maxNewtonIterations; // max number of newton iterations
- btScalar m_newtonTolerance; // stop newton iterations if f(x) < m_newtonTolerance
- bool m_lineSearch; // If true, use newton's method with line search under implicit scheme
-public:
- // handles data related to objective function
- btDeformableBackwardEulerObjective* m_objective;
- bool m_useProjection;
-
- btDeformableBodySolver();
-
- virtual ~btDeformableBodySolver();
-
- virtual SolverTypes getSolverType() const
- {
- return DEFORMABLE_SOLVER;
- }
-
- // update soft body normals
- virtual void updateSoftBodies();
-
- virtual btScalar solveContactConstraints(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
-
- // solve the momentum equation
- virtual void solveDeformableConstraints(btScalar solverdt);
-
- // resize/clear data structures
- void reinitialize(const btAlignedObjectArray<btSoftBody*>& softBodies, btScalar dt);
-
- // set up contact constraints
- void setConstraints(const btContactSolverInfo& infoGlobal);
-
- // add in elastic forces and gravity to obtain v_{n+1}^* and calls predictDeformableMotion
- virtual void predictMotion(btScalar solverdt);
-
- // move to temporary position x_{n+1}^* = x_n + dt * v_{n+1}^*
- // x_{n+1}^* is stored in m_q
- void predictDeformableMotion(btSoftBody* psb, btScalar dt);
-
- // save the current velocity to m_backupVelocity
- void backupVelocity();
-
- // set m_dv and m_backupVelocity to desired value to prepare for momentum solve
- void setupDeformableSolve(bool implicit);
-
- // set the current velocity to that backed up in m_backupVelocity
- void revertVelocity();
-
- // set velocity to m_dv + m_backupVelocity
- void updateVelocity();
-
- // update the node count
- bool updateNodes();
-
- // calculate the change in dv resulting from the momentum solve
- void computeStep(TVStack& ddv, const TVStack& residual);
-
- // calculate the change in dv resulting from the momentum solve when line search is turned on
- btScalar computeDescentStep(TVStack& ddv, const TVStack& residual, bool verbose = false);
-
- virtual void copySoftBodyToVertexBuffer(const btSoftBody* const softBody, btVertexBufferDescriptor* vertexBuffer) {}
-
- // process collision between deformable and rigid
- virtual void processCollision(btSoftBody* softBody, const btCollisionObjectWrapper* collisionObjectWrap)
- {
- softBody->defaultCollisionHandler(collisionObjectWrap);
- }
-
- // process collision between deformable and deformable
- virtual void processCollision(btSoftBody* softBody, btSoftBody* otherSoftBody)
- {
- softBody->defaultCollisionHandler(otherSoftBody);
- }
-
- // If true, implicit time stepping scheme is used.
- // Otherwise, explicit time stepping scheme is used
- void setImplicit(bool implicit);
-
- // If true, newton's method with line search is used when implicit time stepping scheme is turned on
- void setLineSearch(bool lineSearch);
-
- // set temporary position x^* = x_n + dt * v
- // update the deformation gradient at position x^*
- void updateState();
-
- // set dv = dv + scale * ddv
- void updateDv(btScalar scale = 1);
-
- // set temporary position x^* = x_n + dt * v^*
- void updateTempPosition();
-
- // save the current dv to m_backup_dv;
- void backupDv();
-
- // set dv to the backed-up value
- void revertDv();
-
- // set dv = dv + scale * ddv
- // set v^* = v_n + dv
- // set temporary position x^* = x_n + dt * v^*
- // update the deformation gradient at position x^*
- void updateEnergy(btScalar scale);
-
- // calculates the appropriately scaled kinetic energy in the system, which is
- // 1/2 * dv^T * M * dv
- // used in line search
- btScalar kineticEnergy();
-
- // unused functions
- virtual void optimize(btAlignedObjectArray<btSoftBody*>& softBodies, bool forceUpdate = false) {}
- virtual void solveConstraints(btScalar dt) {}
- virtual bool checkInitialized() { return true; }
- virtual void copyBackToSoftBodies(bool bMove = true) {}
-};
-
-#endif /* btDeformableBodySolver_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
deleted file mode 100644
index 09398d79a5..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.cpp
+++ /dev/null
@@ -1,720 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "btDeformableContactConstraint.h"
-/* ================ Deformable Node Anchor =================== */
-btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& a, const btContactSolverInfo& infoGlobal)
- : m_anchor(&a), btDeformableContactConstraint(a.m_cti.m_normal, infoGlobal)
-{
-}
-
-btDeformableNodeAnchorConstraint::btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other)
- : m_anchor(other.m_anchor), btDeformableContactConstraint(other)
-{
-}
-
-btVector3 btDeformableNodeAnchorConstraint::getVa() const
-{
- const btSoftBody::sCti& cti = m_anchor->m_cti;
- btVector3 va(0, 0, 0);
- if (cti.m_colObj->hasContactResponse())
- {
- btRigidBody* rigidCol = 0;
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
-
- // grab the velocity of the rigid body
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_anchor->m_c1)) : btVector3(0, 0, 0);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- const btScalar* J_n = &m_anchor->jacobianData_normal.m_jacobians[0];
- const btScalar* J_t1 = &m_anchor->jacobianData_t1.m_jacobians[0];
- const btScalar* J_t2 = &m_anchor->jacobianData_t2.m_jacobians[0];
- const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
- const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
- // add in the normal component of the va
- btScalar vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_n[k];
- }
- va = cti.m_normal * vel;
- // add in the tangential components of the va
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_t1[k];
- }
- va += m_anchor->t1 * vel;
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_t2[k];
- }
- va += m_anchor->t2 * vel;
- }
- }
- }
- return va;
-}
-
-btScalar btDeformableNodeAnchorConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
-{
- const btSoftBody::sCti& cti = m_anchor->m_cti;
- btVector3 va = getVa();
- btVector3 vb = getVb();
- btVector3 vr = (vb - va);
- // + (m_anchor->m_node->m_x - cti.m_colObj->getWorldTransform() * m_anchor->m_local) * 10.0
- const btScalar dn = btDot(vr, vr);
- // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
- btScalar residualSquare = dn * dn;
- btVector3 impulse = m_anchor->m_c0 * vr;
- // apply impulse to deformable nodes involved and change their velocities
- applyImpulse(impulse);
-
- // apply impulse to the rigid/multibodies involved and change their velocities
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- btRigidBody* rigidCol = 0;
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- if (rigidCol)
- {
- rigidCol->applyImpulse(impulse, m_anchor->m_c1);
- }
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const btScalar* deltaV_normal = &m_anchor->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- // apply normal component of the impulse
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
- // apply tangential component of the impulse
- const btScalar* deltaV_t1 = &m_anchor->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_anchor->t1));
- const btScalar* deltaV_t2 = &m_anchor->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_anchor->t2));
- }
- }
- return residualSquare;
-}
-
-btVector3 btDeformableNodeAnchorConstraint::getVb() const
-{
- return m_anchor->m_node->m_v;
-}
-
-void btDeformableNodeAnchorConstraint::applyImpulse(const btVector3& impulse)
-{
- btVector3 dv = impulse * m_anchor->m_c2;
- m_anchor->m_node->m_v -= dv;
-}
-
-/* ================ Deformable vs. Rigid =================== */
-btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal)
- : m_contact(&c), btDeformableContactConstraint(c.m_cti.m_normal, infoGlobal)
-{
- m_total_normal_dv.setZero();
- m_total_tangent_dv.setZero();
- // The magnitude of penetration is the depth of penetration.
- m_penetration = c.m_cti.m_offset;
- m_total_split_impulse = 0;
- m_binding = false;
-}
-
-btDeformableRigidContactConstraint::btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other)
- : m_contact(other.m_contact), btDeformableContactConstraint(other), m_penetration(other.m_penetration), m_total_split_impulse(other.m_total_split_impulse), m_binding(other.m_binding)
-{
- m_total_normal_dv = other.m_total_normal_dv;
- m_total_tangent_dv = other.m_total_tangent_dv;
-}
-
-btVector3 btDeformableRigidContactConstraint::getVa() const
-{
- const btSoftBody::sCti& cti = m_contact->m_cti;
- btVector3 va(0, 0, 0);
- if (cti.m_colObj->hasContactResponse())
- {
- btRigidBody* rigidCol = 0;
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
-
- // grab the velocity of the rigid body
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- va = rigidCol ? (rigidCol->getVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
- const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
- const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
- const btScalar* local_v = multibodyLinkCol->m_multiBody->getVelocityVector();
- const btScalar* local_dv = multibodyLinkCol->m_multiBody->getDeltaVelocityVector();
- // add in the normal component of the va
- btScalar vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_n[k];
- }
- va = cti.m_normal * vel;
- // add in the tangential components of the va
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_t1[k];
- }
- va += m_contact->t1 * vel;
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += (local_v[k] + local_dv[k]) * J_t2[k];
- }
- va += m_contact->t2 * vel;
- }
- }
- }
- return va;
-}
-
-btVector3 btDeformableRigidContactConstraint::getSplitVa() const
-{
- const btSoftBody::sCti& cti = m_contact->m_cti;
- btVector3 va(0, 0, 0);
- if (cti.m_colObj->hasContactResponse())
- {
- btRigidBody* rigidCol = 0;
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
-
- // grab the velocity of the rigid body
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- va = rigidCol ? (rigidCol->getPushVelocityInLocalPoint(m_contact->m_c1)) : btVector3(0, 0, 0);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- const btScalar* J_n = &m_contact->jacobianData_normal.m_jacobians[0];
- const btScalar* J_t1 = &m_contact->jacobianData_t1.m_jacobians[0];
- const btScalar* J_t2 = &m_contact->jacobianData_t2.m_jacobians[0];
- const btScalar* local_split_v = multibodyLinkCol->m_multiBody->getSplitVelocityVector();
- // add in the normal component of the va
- btScalar vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += local_split_v[k] * J_n[k];
- }
- va = cti.m_normal * vel;
- // add in the tangential components of the va
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += local_split_v[k] * J_t1[k];
- }
- va += m_contact->t1 * vel;
- vel = 0.0;
- for (int k = 0; k < ndof; ++k)
- {
- vel += local_split_v[k] * J_t2[k];
- }
- va += m_contact->t2 * vel;
- }
- }
- }
- return va;
-}
-
-btScalar btDeformableRigidContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
-{
- const btSoftBody::sCti& cti = m_contact->m_cti;
- btVector3 va = getVa();
- btVector3 vb = getVb();
- btVector3 vr = vb - va;
- btScalar dn = btDot(vr, cti.m_normal) + m_total_normal_dv.dot(cti.m_normal) * infoGlobal.m_deformable_cfm;
- if (m_penetration > 0)
- {
- dn += m_penetration / infoGlobal.m_timeStep;
- }
- if (!infoGlobal.m_splitImpulse)
- {
- dn += m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
- }
- // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
- btVector3 impulse = m_contact->m_c0 * (vr + m_total_normal_dv * infoGlobal.m_deformable_cfm + ((m_penetration > 0) ? m_penetration / infoGlobal.m_timeStep * cti.m_normal : btVector3(0, 0, 0)));
- if (!infoGlobal.m_splitImpulse)
- {
- impulse += m_contact->m_c0 * (m_penetration * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep * cti.m_normal);
- }
- btVector3 impulse_normal = m_contact->m_c0 * (cti.m_normal * dn);
- btVector3 impulse_tangent = impulse - impulse_normal;
- if (dn > 0)
- {
- return 0;
- }
- m_binding = true;
- btScalar residualSquare = dn * dn;
- btVector3 old_total_tangent_dv = m_total_tangent_dv;
- // m_c5 is the inverse mass of the deformable node/face
- m_total_normal_dv -= m_contact->m_c5 * impulse_normal;
- m_total_tangent_dv -= m_contact->m_c5 * impulse_tangent;
-
- if (m_total_normal_dv.dot(cti.m_normal) < 0)
- {
- // separating in the normal direction
- m_binding = false;
- m_static = false;
- impulse_tangent.setZero();
- }
- else
- {
- if (m_total_normal_dv.norm() * m_contact->m_c3 < m_total_tangent_dv.norm())
- {
- // dynamic friction
- // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
- m_static = false;
- if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
- {
- m_total_tangent_dv = btVector3(0, 0, 0);
- }
- else
- {
- m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_c3;
- }
- // impulse_tangent = -btScalar(1)/m_contact->m_c2 * (m_total_tangent_dv - old_total_tangent_dv);
- impulse_tangent = m_contact->m_c5.inverse() * (old_total_tangent_dv - m_total_tangent_dv);
- }
- else
- {
- // static friction
- m_static = true;
- }
- }
- impulse = impulse_normal + impulse_tangent;
- // apply impulse to deformable nodes involved and change their velocities
- applyImpulse(impulse);
- // apply impulse to the rigid/multibodies involved and change their velocities
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- btRigidBody* rigidCol = 0;
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- if (rigidCol)
- {
- rigidCol->applyImpulse(impulse, m_contact->m_c1);
- }
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- // apply normal component of the impulse
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_normal, impulse.dot(cti.m_normal));
- if (impulse_tangent.norm() > SIMD_EPSILON)
- {
- // apply tangential component of the impulse
- const btScalar* deltaV_t1 = &m_contact->jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t1, impulse.dot(m_contact->t1));
- const btScalar* deltaV_t2 = &m_contact->jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof2(deltaV_t2, impulse.dot(m_contact->t2));
- }
- }
- }
- return residualSquare;
-}
-
-btScalar btDeformableRigidContactConstraint::solveSplitImpulse(const btContactSolverInfo& infoGlobal)
-{
- btScalar MAX_PENETRATION_CORRECTION = infoGlobal.m_deformable_maxErrorReduction;
- const btSoftBody::sCti& cti = m_contact->m_cti;
- btVector3 vb = getSplitVb();
- btVector3 va = getSplitVa();
- btScalar p = m_penetration;
- if (p > 0)
- {
- return 0;
- }
- btVector3 vr = vb - va;
- btScalar dn = btDot(vr, cti.m_normal) + p * infoGlobal.m_deformable_erp / infoGlobal.m_timeStep;
- if (dn > 0)
- {
- return 0;
- }
- if (m_total_split_impulse + dn > MAX_PENETRATION_CORRECTION)
- {
- dn = MAX_PENETRATION_CORRECTION - m_total_split_impulse;
- }
- if (m_total_split_impulse + dn < -MAX_PENETRATION_CORRECTION)
- {
- dn = -MAX_PENETRATION_CORRECTION - m_total_split_impulse;
- }
- m_total_split_impulse += dn;
-
- btScalar residualSquare = dn * dn;
- const btVector3 impulse = m_contact->m_c0 * (cti.m_normal * dn);
- applySplitImpulse(impulse);
-
- // apply split impulse to the rigid/multibodies involved and change their velocities
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- btRigidBody* rigidCol = 0;
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- if (rigidCol)
- {
- rigidCol->applyPushImpulse(impulse, m_contact->m_c1);
- }
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const btScalar* deltaV_normal = &m_contact->jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- // apply normal component of the impulse
- multibodyLinkCol->m_multiBody->applyDeltaSplitVeeMultiDof(deltaV_normal, impulse.dot(cti.m_normal));
- }
- }
- return residualSquare;
-}
-/* ================ Node vs. Rigid =================== */
-btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal)
- : m_node(contact.m_node), btDeformableRigidContactConstraint(contact, infoGlobal)
-{
-}
-
-btDeformableNodeRigidContactConstraint::btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other)
- : m_node(other.m_node), btDeformableRigidContactConstraint(other)
-{
-}
-
-btVector3 btDeformableNodeRigidContactConstraint::getVb() const
-{
- return m_node->m_v;
-}
-
-btVector3 btDeformableNodeRigidContactConstraint::getSplitVb() const
-{
- return m_node->m_splitv;
-}
-
-btVector3 btDeformableNodeRigidContactConstraint::getDv(const btSoftBody::Node* node) const
-{
- return m_total_normal_dv + m_total_tangent_dv;
-}
-
-void btDeformableNodeRigidContactConstraint::applyImpulse(const btVector3& impulse)
-{
- const btSoftBody::DeformableNodeRigidContact* contact = getContact();
- btVector3 dv = contact->m_c5 * impulse;
- contact->m_node->m_v -= dv;
-}
-
-void btDeformableNodeRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
-{
- const btSoftBody::DeformableNodeRigidContact* contact = getContact();
- btVector3 dv = contact->m_c5 * impulse;
- contact->m_node->m_splitv -= dv;
-}
-
-/* ================ Face vs. Rigid =================== */
-btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting)
- : m_face(contact.m_face), m_useStrainLimiting(useStrainLimiting), btDeformableRigidContactConstraint(contact, infoGlobal)
-{
-}
-
-btDeformableFaceRigidContactConstraint::btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other)
- : m_face(other.m_face), m_useStrainLimiting(other.m_useStrainLimiting), btDeformableRigidContactConstraint(other)
-{
-}
-
-btVector3 btDeformableFaceRigidContactConstraint::getVb() const
-{
- const btSoftBody::DeformableFaceRigidContact* contact = getContact();
- btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
- return vb;
-}
-
-btVector3 btDeformableFaceRigidContactConstraint::getDv(const btSoftBody::Node* node) const
-{
- btVector3 face_dv = m_total_normal_dv + m_total_tangent_dv;
- const btSoftBody::DeformableFaceRigidContact* contact = getContact();
- if (m_face->m_n[0] == node)
- {
- return face_dv * contact->m_weights[0];
- }
- if (m_face->m_n[1] == node)
- {
- return face_dv * contact->m_weights[1];
- }
- btAssert(node == m_face->m_n[2]);
- return face_dv * contact->m_weights[2];
-}
-
-void btDeformableFaceRigidContactConstraint::applyImpulse(const btVector3& impulse)
-{
- const btSoftBody::DeformableFaceRigidContact* contact = getContact();
- btVector3 dv = impulse * contact->m_c2;
- btSoftBody::Face* face = contact->m_face;
-
- btVector3& v0 = face->m_n[0]->m_v;
- btVector3& v1 = face->m_n[1]->m_v;
- btVector3& v2 = face->m_n[2]->m_v;
- const btScalar& im0 = face->m_n[0]->m_im;
- const btScalar& im1 = face->m_n[1]->m_im;
- const btScalar& im2 = face->m_n[2]->m_im;
- if (im0 > 0)
- v0 -= dv * contact->m_weights[0];
- if (im1 > 0)
- v1 -= dv * contact->m_weights[1];
- if (im2 > 0)
- v2 -= dv * contact->m_weights[2];
- if (m_useStrainLimiting)
- {
- btScalar relaxation = 1. / btScalar(m_infoGlobal->m_numIterations);
- btScalar m01 = (relaxation / (im0 + im1));
- btScalar m02 = (relaxation / (im0 + im2));
- btScalar m12 = (relaxation / (im1 + im2));
-#ifdef USE_STRAIN_RATE_LIMITING
- // apply strain limiting to prevent the new velocity to change the current length of the edge by more than 1%.
- btScalar p = 0.01;
- btVector3& x0 = face->m_n[0]->m_x;
- btVector3& x1 = face->m_n[1]->m_x;
- btVector3& x2 = face->m_n[2]->m_x;
- const btVector3 x_diff[3] = {x1 - x0, x2 - x0, x2 - x1};
- const btVector3 v_diff[3] = {v1 - v0, v2 - v0, v2 - v1};
- btVector3 u[3];
- btScalar x_diff_dot_u, dn[3];
- btScalar dt = m_infoGlobal->m_timeStep;
- for (int i = 0; i < 3; ++i)
- {
- btScalar x_diff_norm = x_diff[i].safeNorm();
- btScalar x_diff_norm_new = (x_diff[i] + v_diff[i] * dt).safeNorm();
- btScalar strainRate = x_diff_norm_new / x_diff_norm;
- u[i] = v_diff[i];
- u[i].safeNormalize();
- if (x_diff_norm == 0 || (1 - p <= strainRate && strainRate <= 1 + p))
- {
- dn[i] = 0;
- continue;
- }
- x_diff_dot_u = btDot(x_diff[i], u[i]);
- btScalar s;
- if (1 - p > strainRate)
- {
- s = 1 / dt * (-x_diff_dot_u - btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p - 2 * p) * x_diff_norm * x_diff_norm));
- }
- else
- {
- s = 1 / dt * (-x_diff_dot_u + btSqrt(x_diff_dot_u * x_diff_dot_u + (p * p + 2 * p) * x_diff_norm * x_diff_norm));
- }
- // x_diff_norm_new = (x_diff[i] + s * u[i] * dt).safeNorm();
- // strainRate = x_diff_norm_new/x_diff_norm;
- dn[i] = s - v_diff[i].safeNorm();
- }
- btVector3 dv0 = im0 * (m01 * u[0] * (-dn[0]) + m02 * u[1] * -(dn[1]));
- btVector3 dv1 = im1 * (m01 * u[0] * (dn[0]) + m12 * u[2] * (-dn[2]));
- btVector3 dv2 = im2 * (m12 * u[2] * (dn[2]) + m02 * u[1] * (dn[1]));
-#else
- // apply strain limiting to prevent undamped modes
- btVector3 dv0 = im0 * (m01 * (v1 - v0) + m02 * (v2 - v0));
- btVector3 dv1 = im1 * (m01 * (v0 - v1) + m12 * (v2 - v1));
- btVector3 dv2 = im2 * (m12 * (v1 - v2) + m02 * (v0 - v2));
-#endif
- v0 += dv0;
- v1 += dv1;
- v2 += dv2;
- }
-}
-
-btVector3 btDeformableFaceRigidContactConstraint::getSplitVb() const
-{
- const btSoftBody::DeformableFaceRigidContact* contact = getContact();
- btVector3 vb = (m_face->m_n[0]->m_splitv) * contact->m_bary[0] + (m_face->m_n[1]->m_splitv) * contact->m_bary[1] + (m_face->m_n[2]->m_splitv) * contact->m_bary[2];
- return vb;
-}
-
-void btDeformableFaceRigidContactConstraint::applySplitImpulse(const btVector3& impulse)
-{
- const btSoftBody::DeformableFaceRigidContact* contact = getContact();
- btVector3 dv = impulse * contact->m_c2;
- btSoftBody::Face* face = contact->m_face;
- btVector3& v0 = face->m_n[0]->m_splitv;
- btVector3& v1 = face->m_n[1]->m_splitv;
- btVector3& v2 = face->m_n[2]->m_splitv;
- const btScalar& im0 = face->m_n[0]->m_im;
- const btScalar& im1 = face->m_n[1]->m_im;
- const btScalar& im2 = face->m_n[2]->m_im;
- if (im0 > 0)
- {
- v0 -= dv * contact->m_weights[0];
- }
- if (im1 > 0)
- {
- v1 -= dv * contact->m_weights[1];
- }
- if (im2 > 0)
- {
- v2 -= dv * contact->m_weights[2];
- }
-}
-
-/* ================ Face vs. Node =================== */
-btDeformableFaceNodeContactConstraint::btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal)
- : m_node(contact.m_node), m_face(contact.m_face), m_contact(&contact), btDeformableContactConstraint(contact.m_normal, infoGlobal)
-{
- m_total_normal_dv.setZero();
- m_total_tangent_dv.setZero();
-}
-
-btVector3 btDeformableFaceNodeContactConstraint::getVa() const
-{
- return m_node->m_v;
-}
-
-btVector3 btDeformableFaceNodeContactConstraint::getVb() const
-{
- const btSoftBody::DeformableFaceNodeContact* contact = getContact();
- btVector3 vb = m_face->m_n[0]->m_v * contact->m_bary[0] + m_face->m_n[1]->m_v * contact->m_bary[1] + m_face->m_n[2]->m_v * contact->m_bary[2];
- return vb;
-}
-
-btVector3 btDeformableFaceNodeContactConstraint::getDv(const btSoftBody::Node* n) const
-{
- btVector3 dv = m_total_normal_dv + m_total_tangent_dv;
- if (n == m_node)
- return dv;
- const btSoftBody::DeformableFaceNodeContact* contact = getContact();
- if (m_face->m_n[0] == n)
- {
- return dv * contact->m_weights[0];
- }
- if (m_face->m_n[1] == n)
- {
- return dv * contact->m_weights[1];
- }
- btAssert(n == m_face->m_n[2]);
- return dv * contact->m_weights[2];
-}
-
-btScalar btDeformableFaceNodeContactConstraint::solveConstraint(const btContactSolverInfo& infoGlobal)
-{
- btVector3 va = getVa();
- btVector3 vb = getVb();
- btVector3 vr = vb - va;
- const btScalar dn = btDot(vr, m_contact->m_normal);
- // dn is the normal component of velocity diffrerence. Approximates the residual. // todo xuchenhan@: this prob needs to be scaled by dt
- btScalar residualSquare = dn * dn;
- btVector3 impulse = m_contact->m_c0 * vr;
- const btVector3 impulse_normal = m_contact->m_c0 * (m_contact->m_normal * dn);
- btVector3 impulse_tangent = impulse - impulse_normal;
-
- btVector3 old_total_tangent_dv = m_total_tangent_dv;
- // m_c2 is the inverse mass of the deformable node/face
- if (m_node->m_im > 0)
- {
- m_total_normal_dv -= impulse_normal * m_node->m_im;
- m_total_tangent_dv -= impulse_tangent * m_node->m_im;
- }
- else
- {
- m_total_normal_dv -= impulse_normal * m_contact->m_imf;
- m_total_tangent_dv -= impulse_tangent * m_contact->m_imf;
- }
-
- if (m_total_normal_dv.dot(m_contact->m_normal) > 0)
- {
- // separating in the normal direction
- m_static = false;
- m_total_tangent_dv = btVector3(0, 0, 0);
- impulse_tangent.setZero();
- }
- else
- {
- if (m_total_normal_dv.norm() * m_contact->m_friction < m_total_tangent_dv.norm())
- {
- // dynamic friction
- // with dynamic friction, the impulse are still applied to the two objects colliding, however, it does not pose a constraint in the cg solve, hence the change to dv merely serves to update velocity in the contact iterations.
- m_static = false;
- if (m_total_tangent_dv.safeNorm() < SIMD_EPSILON)
- {
- m_total_tangent_dv = btVector3(0, 0, 0);
- }
- else
- {
- m_total_tangent_dv = m_total_tangent_dv.normalized() * m_total_normal_dv.safeNorm() * m_contact->m_friction;
- }
- impulse_tangent = -btScalar(1) / m_node->m_im * (m_total_tangent_dv - old_total_tangent_dv);
- }
- else
- {
- // static friction
- m_static = true;
- }
- }
- impulse = impulse_normal + impulse_tangent;
- // apply impulse to deformable nodes involved and change their velocities
- applyImpulse(impulse);
- return residualSquare;
-}
-
-void btDeformableFaceNodeContactConstraint::applyImpulse(const btVector3& impulse)
-{
- const btSoftBody::DeformableFaceNodeContact* contact = getContact();
- btVector3 dva = impulse * contact->m_node->m_im;
- btVector3 dvb = impulse * contact->m_imf;
- if (contact->m_node->m_im > 0)
- {
- contact->m_node->m_v += dva;
- }
-
- btSoftBody::Face* face = contact->m_face;
- btVector3& v0 = face->m_n[0]->m_v;
- btVector3& v1 = face->m_n[1]->m_v;
- btVector3& v2 = face->m_n[2]->m_v;
- const btScalar& im0 = face->m_n[0]->m_im;
- const btScalar& im1 = face->m_n[1]->m_im;
- const btScalar& im2 = face->m_n[2]->m_im;
- if (im0 > 0)
- {
- v0 -= dvb * contact->m_weights[0];
- }
- if (im1 > 0)
- {
- v1 -= dvb * contact->m_weights[1];
- }
- if (im2 > 0)
- {
- v2 -= dvb * contact->m_weights[2];
- }
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
deleted file mode 100644
index 1e2c9f5bce..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableContactConstraint.h
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_CONTACT_CONSTRAINT_H
-#define BT_DEFORMABLE_CONTACT_CONSTRAINT_H
-#include "btSoftBody.h"
-
-// btDeformableContactConstraint is an abstract class specifying the method that each type of contact constraint needs to implement
-class btDeformableContactConstraint
-{
-public:
- // True if the friction is static
- // False if the friction is dynamic
- bool m_static;
- const btContactSolverInfo* m_infoGlobal;
-
- // normal of the contact
- btVector3 m_normal;
-
- btDeformableContactConstraint(const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(false), m_normal(normal), m_infoGlobal(&infoGlobal)
- {
- }
-
- btDeformableContactConstraint(bool isStatic, const btVector3& normal, const btContactSolverInfo& infoGlobal) : m_static(isStatic), m_normal(normal), m_infoGlobal(&infoGlobal)
- {
- }
-
- btDeformableContactConstraint() {}
-
- btDeformableContactConstraint(const btDeformableContactConstraint& other)
- : m_static(other.m_static), m_normal(other.m_normal), m_infoGlobal(other.m_infoGlobal)
- {
- }
-
- virtual ~btDeformableContactConstraint() {}
-
- // solve the constraint with inelastic impulse and return the error, which is the square of normal component of velocity diffrerence
- // the constraint is solved by calculating the impulse between object A and B in the contact and apply the impulse to both objects involved in the contact
- virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal) = 0;
-
- // get the velocity of the object A in the contact
- virtual btVector3 getVa() const = 0;
-
- // get the velocity of the object B in the contact
- virtual btVector3 getVb() const = 0;
-
- // get the velocity change of the soft body node in the constraint
- virtual btVector3 getDv(const btSoftBody::Node*) const = 0;
-
- // apply impulse to the soft body node and/or face involved
- virtual void applyImpulse(const btVector3& impulse) = 0;
-
- // scale the penetration depth by erp
- virtual void setPenetrationScale(btScalar scale) = 0;
-};
-
-//
-// Constraint that a certain node in the deformable objects cannot move
-class btDeformableStaticConstraint : public btDeformableContactConstraint
-{
-public:
- btSoftBody::Node* m_node;
-
- btDeformableStaticConstraint(btSoftBody::Node* node, const btContactSolverInfo& infoGlobal) : m_node(node), btDeformableContactConstraint(false, btVector3(0, 0, 0), infoGlobal)
- {
- }
- btDeformableStaticConstraint() {}
- btDeformableStaticConstraint(const btDeformableStaticConstraint& other)
- : m_node(other.m_node), btDeformableContactConstraint(other)
- {
- }
-
- virtual ~btDeformableStaticConstraint() {}
-
- virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal)
- {
- return 0;
- }
-
- virtual btVector3 getVa() const
- {
- return btVector3(0, 0, 0);
- }
-
- virtual btVector3 getVb() const
- {
- return btVector3(0, 0, 0);
- }
-
- virtual btVector3 getDv(const btSoftBody::Node* n) const
- {
- return btVector3(0, 0, 0);
- }
-
- virtual void applyImpulse(const btVector3& impulse) {}
- virtual void setPenetrationScale(btScalar scale) {}
-};
-
-//
-// Anchor Constraint between rigid and deformable node
-class btDeformableNodeAnchorConstraint : public btDeformableContactConstraint
-{
-public:
- const btSoftBody::DeformableNodeRigidAnchor* m_anchor;
-
- btDeformableNodeAnchorConstraint(const btSoftBody::DeformableNodeRigidAnchor& c, const btContactSolverInfo& infoGlobal);
- btDeformableNodeAnchorConstraint(const btDeformableNodeAnchorConstraint& other);
- btDeformableNodeAnchorConstraint() {}
- virtual ~btDeformableNodeAnchorConstraint()
- {
- }
- virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
-
- // object A is the rigid/multi body, and object B is the deformable node/face
- virtual btVector3 getVa() const;
- // get the velocity of the deformable node in contact
- virtual btVector3 getVb() const;
- virtual btVector3 getDv(const btSoftBody::Node* n) const
- {
- return btVector3(0, 0, 0);
- }
- virtual void applyImpulse(const btVector3& impulse);
-
- virtual void setPenetrationScale(btScalar scale) {}
-};
-
-//
-// Constraint between rigid/multi body and deformable objects
-class btDeformableRigidContactConstraint : public btDeformableContactConstraint
-{
-public:
- btVector3 m_total_normal_dv;
- btVector3 m_total_tangent_dv;
- btScalar m_penetration;
- btScalar m_total_split_impulse;
- bool m_binding;
- const btSoftBody::DeformableRigidContact* m_contact;
-
- btDeformableRigidContactConstraint(const btSoftBody::DeformableRigidContact& c, const btContactSolverInfo& infoGlobal);
- btDeformableRigidContactConstraint(const btDeformableRigidContactConstraint& other);
- btDeformableRigidContactConstraint() {}
- virtual ~btDeformableRigidContactConstraint()
- {
- }
-
- // object A is the rigid/multi body, and object B is the deformable node/face
- virtual btVector3 getVa() const;
-
- // get the split impulse velocity of the deformable face at the contact point
- virtual btVector3 getSplitVb() const = 0;
-
- // get the split impulse velocity of the rigid/multibdoy at the contaft
- virtual btVector3 getSplitVa() const;
-
- virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
-
- virtual void setPenetrationScale(btScalar scale)
- {
- m_penetration *= scale;
- }
-
- btScalar solveSplitImpulse(const btContactSolverInfo& infoGlobal);
-
- virtual void applySplitImpulse(const btVector3& impulse) = 0;
-};
-
-//
-// Constraint between rigid/multi body and deformable objects nodes
-class btDeformableNodeRigidContactConstraint : public btDeformableRigidContactConstraint
-{
-public:
- // the deformable node in contact
- btSoftBody::Node* m_node;
-
- btDeformableNodeRigidContactConstraint(const btSoftBody::DeformableNodeRigidContact& contact, const btContactSolverInfo& infoGlobal);
- btDeformableNodeRigidContactConstraint(const btDeformableNodeRigidContactConstraint& other);
- btDeformableNodeRigidContactConstraint() {}
- virtual ~btDeformableNodeRigidContactConstraint()
- {
- }
-
- // get the velocity of the deformable node in contact
- virtual btVector3 getVb() const;
-
- // get the split impulse velocity of the deformable face at the contact point
- virtual btVector3 getSplitVb() const;
-
- // get the velocity change of the input soft body node in the constraint
- virtual btVector3 getDv(const btSoftBody::Node*) const;
-
- // cast the contact to the desired type
- const btSoftBody::DeformableNodeRigidContact* getContact() const
- {
- return static_cast<const btSoftBody::DeformableNodeRigidContact*>(m_contact);
- }
-
- virtual void applyImpulse(const btVector3& impulse);
-
- virtual void applySplitImpulse(const btVector3& impulse);
-};
-
-//
-// Constraint between rigid/multi body and deformable objects faces
-class btDeformableFaceRigidContactConstraint : public btDeformableRigidContactConstraint
-{
-public:
- btSoftBody::Face* m_face;
- bool m_useStrainLimiting;
- btDeformableFaceRigidContactConstraint(const btSoftBody::DeformableFaceRigidContact& contact, const btContactSolverInfo& infoGlobal, bool useStrainLimiting);
- btDeformableFaceRigidContactConstraint(const btDeformableFaceRigidContactConstraint& other);
- btDeformableFaceRigidContactConstraint() : m_useStrainLimiting(false) {}
- virtual ~btDeformableFaceRigidContactConstraint()
- {
- }
-
- // get the velocity of the deformable face at the contact point
- virtual btVector3 getVb() const;
-
- // get the split impulse velocity of the deformable face at the contact point
- virtual btVector3 getSplitVb() const;
-
- // get the velocity change of the input soft body node in the constraint
- virtual btVector3 getDv(const btSoftBody::Node*) const;
-
- // cast the contact to the desired type
- const btSoftBody::DeformableFaceRigidContact* getContact() const
- {
- return static_cast<const btSoftBody::DeformableFaceRigidContact*>(m_contact);
- }
-
- virtual void applyImpulse(const btVector3& impulse);
-
- virtual void applySplitImpulse(const btVector3& impulse);
-};
-
-//
-// Constraint between deformable objects faces and deformable objects nodes
-class btDeformableFaceNodeContactConstraint : public btDeformableContactConstraint
-{
-public:
- btSoftBody::Node* m_node;
- btSoftBody::Face* m_face;
- const btSoftBody::DeformableFaceNodeContact* m_contact;
- btVector3 m_total_normal_dv;
- btVector3 m_total_tangent_dv;
-
- btDeformableFaceNodeContactConstraint(const btSoftBody::DeformableFaceNodeContact& contact, const btContactSolverInfo& infoGlobal);
- btDeformableFaceNodeContactConstraint() {}
- virtual ~btDeformableFaceNodeContactConstraint() {}
-
- virtual btScalar solveConstraint(const btContactSolverInfo& infoGlobal);
-
- // get the velocity of the object A in the contact
- virtual btVector3 getVa() const;
-
- // get the velocity of the object B in the contact
- virtual btVector3 getVb() const;
-
- // get the velocity change of the input soft body node in the constraint
- virtual btVector3 getDv(const btSoftBody::Node*) const;
-
- // cast the contact to the desired type
- const btSoftBody::DeformableFaceNodeContact* getContact() const
- {
- return static_cast<const btSoftBody::DeformableFaceNodeContact*>(m_contact);
- }
-
- virtual void applyImpulse(const btVector3& impulse);
-
- virtual void setPenetrationScale(btScalar scale) {}
-};
-#endif /* BT_DEFORMABLE_CONTACT_CONSTRAINT_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
deleted file mode 100644
index 7f67260ce6..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.cpp
+++ /dev/null
@@ -1,639 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "btDeformableContactProjection.h"
-#include "btDeformableMultiBodyDynamicsWorld.h"
-#include <algorithm>
-#include <cmath>
-btScalar btDeformableContactProjection::update(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
-{
- btScalar residualSquare = 0;
- for (int i = 0; i < numDeformableBodies; ++i)
- {
- for (int j = 0; j < m_softBodies.size(); ++j)
- {
- btCollisionObject* psb = m_softBodies[j];
- if (psb != deformableBodies[i])
- {
- continue;
- }
- for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
- {
- btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
- btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- for (int k = 0; k < m_nodeAnchorConstraints[j].size(); ++k)
- {
- btDeformableNodeAnchorConstraint& constraint = m_nodeAnchorConstraints[j][k];
- btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
- {
- btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
- btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- for (int k = 0; k < m_deformableConstraints[j].size(); ++k)
- {
- btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[j][k];
- btScalar localResidualSquare = constraint.solveConstraint(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- }
- }
- return residualSquare;
-}
-
-btScalar btDeformableContactProjection::solveSplitImpulse(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal)
-{
- btScalar residualSquare = 0;
- for (int i = 0; i < numDeformableBodies; ++i)
- {
- for (int j = 0; j < m_softBodies.size(); ++j)
- {
- btCollisionObject* psb = m_softBodies[j];
- if (psb != deformableBodies[i])
- {
- continue;
- }
- for (int k = 0; k < m_nodeRigidConstraints[j].size(); ++k)
- {
- btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[j][k];
- btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- for (int k = 0; k < m_faceRigidConstraints[j].size(); ++k)
- {
- btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[j][k];
- btScalar localResidualSquare = constraint.solveSplitImpulse(infoGlobal);
- residualSquare = btMax(residualSquare, localResidualSquare);
- }
- }
- }
- return residualSquare;
-}
-
-void btDeformableContactProjection::setConstraints(const btContactSolverInfo& infoGlobal)
-{
- BT_PROFILE("setConstraints");
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
-
- // set Dirichlet constraint
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- if (psb->m_nodes[j].m_im == 0)
- {
- btDeformableStaticConstraint static_constraint(&psb->m_nodes[j], infoGlobal);
- m_staticConstraints[i].push_back(static_constraint);
- }
- }
-
- // set up deformable anchors
- for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
- {
- btSoftBody::DeformableNodeRigidAnchor& anchor = psb->m_deformableAnchors[j];
- // skip fixed points
- if (anchor.m_node->m_im == 0)
- {
- continue;
- }
- anchor.m_c1 = anchor.m_cti.m_colObj->getWorldTransform().getBasis() * anchor.m_local;
- btDeformableNodeAnchorConstraint constraint(anchor, infoGlobal);
- m_nodeAnchorConstraints[i].push_back(constraint);
- }
-
- // set Deformable Node vs. Rigid constraint
- for (int j = 0; j < psb->m_nodeRigidContacts.size(); ++j)
- {
- const btSoftBody::DeformableNodeRigidContact& contact = psb->m_nodeRigidContacts[j];
- // skip fixed points
- if (contact.m_node->m_im == 0)
- {
- continue;
- }
- btDeformableNodeRigidContactConstraint constraint(contact, infoGlobal);
- m_nodeRigidConstraints[i].push_back(constraint);
- }
-
- // set Deformable Face vs. Rigid constraint
- for (int j = 0; j < psb->m_faceRigidContacts.size(); ++j)
- {
- const btSoftBody::DeformableFaceRigidContact& contact = psb->m_faceRigidContacts[j];
- // skip fixed faces
- if (contact.m_c2 == 0)
- {
- continue;
- }
- btDeformableFaceRigidContactConstraint constraint(contact, infoGlobal, m_useStrainLimiting);
- m_faceRigidConstraints[i].push_back(constraint);
- }
- }
-}
-
-void btDeformableContactProjection::project(TVStack& x)
-{
-#ifndef USE_MGS
- const int dim = 3;
- for (int index = 0; index < m_projectionsDict.size(); ++index)
- {
- btAlignedObjectArray<btVector3>& projectionDirs = *m_projectionsDict.getAtIndex(index);
- size_t i = m_projectionsDict.getKeyAtIndex(index).getUid1();
- if (projectionDirs.size() >= dim)
- {
- // static node
- x[i].setZero();
- continue;
- }
- else if (projectionDirs.size() == 2)
- {
- btVector3 dir0 = projectionDirs[0];
- btVector3 dir1 = projectionDirs[1];
- btVector3 free_dir = btCross(dir0, dir1);
- if (free_dir.safeNorm() < SIMD_EPSILON)
- {
- x[i] -= x[i].dot(dir0) * dir0;
- }
- else
- {
- free_dir.normalize();
- x[i] = x[i].dot(free_dir) * free_dir;
- }
- }
- else
- {
- btAssert(projectionDirs.size() == 1);
- btVector3 dir0 = projectionDirs[0];
- x[i] -= x[i].dot(dir0) * dir0;
- }
- }
-#else
- btReducedVector p(x.size());
- for (int i = 0; i < m_projections.size(); ++i)
- {
- p += (m_projections[i].dot(x) * m_projections[i]);
- }
- for (int i = 0; i < p.m_indices.size(); ++i)
- {
- x[p.m_indices[i]] -= p.m_vecs[i];
- }
-#endif
-}
-
-void btDeformableContactProjection::setProjection()
-{
-#ifndef USE_MGS
- BT_PROFILE("btDeformableContactProjection::setProjection");
- btAlignedObjectArray<btVector3> units;
- units.push_back(btVector3(1, 0, 0));
- units.push_back(btVector3(0, 1, 0));
- units.push_back(btVector3(0, 0, 1));
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < m_staticConstraints[i].size(); ++j)
- {
- int index = m_staticConstraints[i][j].m_node->index;
- m_staticConstraints[i][j].m_node->m_constrained = true;
- if (m_projectionsDict.find(index) == NULL)
- {
- m_projectionsDict.insert(index, units);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- for (int k = 0; k < 3; ++k)
- {
- projections.push_back(units[k]);
- }
- }
- }
- for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
- {
- int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
- m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
- if (m_projectionsDict.find(index) == NULL)
- {
- m_projectionsDict.insert(index, units);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- for (int k = 0; k < 3; ++k)
- {
- projections.push_back(units[k]);
- }
- }
- }
- for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
- {
- int index = m_nodeRigidConstraints[i][j].m_node->index;
- m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
- if (m_nodeRigidConstraints[i][j].m_binding)
- {
- if (m_nodeRigidConstraints[i][j].m_static)
- {
- if (m_projectionsDict.find(index) == NULL)
- {
- m_projectionsDict.insert(index, units);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- for (int k = 0; k < 3; ++k)
- {
- projections.push_back(units[k]);
- }
- }
- }
- else
- {
- if (m_projectionsDict.find(index) == NULL)
- {
- btAlignedObjectArray<btVector3> projections;
- projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
- m_projectionsDict.insert(index, projections);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- projections.push_back(m_nodeRigidConstraints[i][j].m_normal);
- }
- }
- }
- }
- for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
- {
- const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
- if (m_faceRigidConstraints[i][j].m_binding)
- {
- for (int k = 0; k < 3; ++k)
- {
- face->m_n[k]->m_constrained = true;
- }
- }
- for (int k = 0; k < 3; ++k)
- {
- btSoftBody::Node* node = face->m_n[k];
- int index = node->index;
- if (m_faceRigidConstraints[i][j].m_static)
- {
- if (m_projectionsDict.find(index) == NULL)
- {
- m_projectionsDict.insert(index, units);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- for (int l = 0; l < 3; ++l)
- {
- projections.push_back(units[l]);
- }
- }
- }
- else
- {
- if (m_projectionsDict.find(index) == NULL)
- {
- btAlignedObjectArray<btVector3> projections;
- projections.push_back(m_faceRigidConstraints[i][j].m_normal);
- m_projectionsDict.insert(index, projections);
- }
- else
- {
- btAlignedObjectArray<btVector3>& projections = *m_projectionsDict[index];
- projections.push_back(m_faceRigidConstraints[i][j].m_normal);
- }
- }
- }
- }
- }
-#else
- int dof = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- dof += m_softBodies[i]->m_nodes.size();
- }
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < m_staticConstraints[i].size(); ++j)
- {
- int index = m_staticConstraints[i][j].m_node->index;
- m_staticConstraints[i][j].m_node->m_penetration = SIMD_INFINITY;
- btAlignedObjectArray<int> indices;
- btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
- indices.push_back(index);
- vecs1.push_back(btVector3(1, 0, 0));
- vecs2.push_back(btVector3(0, 1, 0));
- vecs3.push_back(btVector3(0, 0, 1));
- m_projections.push_back(btReducedVector(dof, indices, vecs1));
- m_projections.push_back(btReducedVector(dof, indices, vecs2));
- m_projections.push_back(btReducedVector(dof, indices, vecs3));
- }
-
- for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
- {
- int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
- m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_penetration = SIMD_INFINITY;
- btAlignedObjectArray<int> indices;
- btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
- indices.push_back(index);
- vecs1.push_back(btVector3(1, 0, 0));
- vecs2.push_back(btVector3(0, 1, 0));
- vecs3.push_back(btVector3(0, 0, 1));
- m_projections.push_back(btReducedVector(dof, indices, vecs1));
- m_projections.push_back(btReducedVector(dof, indices, vecs2));
- m_projections.push_back(btReducedVector(dof, indices, vecs3));
- }
- for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
- {
- int index = m_nodeRigidConstraints[i][j].m_node->index;
- m_nodeRigidConstraints[i][j].m_node->m_penetration = -m_nodeRigidConstraints[i][j].getContact()->m_cti.m_offset;
- btAlignedObjectArray<int> indices;
- indices.push_back(index);
- btAlignedObjectArray<btVector3> vecs1, vecs2, vecs3;
- if (m_nodeRigidConstraints[i][j].m_static)
- {
- vecs1.push_back(btVector3(1, 0, 0));
- vecs2.push_back(btVector3(0, 1, 0));
- vecs3.push_back(btVector3(0, 0, 1));
- m_projections.push_back(btReducedVector(dof, indices, vecs1));
- m_projections.push_back(btReducedVector(dof, indices, vecs2));
- m_projections.push_back(btReducedVector(dof, indices, vecs3));
- }
- else
- {
- vecs1.push_back(m_nodeRigidConstraints[i][j].m_normal);
- m_projections.push_back(btReducedVector(dof, indices, vecs1));
- }
- }
- for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
- {
- const btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
- btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
- btScalar penetration = -m_faceRigidConstraints[i][j].getContact()->m_cti.m_offset;
- for (int k = 0; k < 3; ++k)
- {
- face->m_n[k]->m_penetration = btMax(face->m_n[k]->m_penetration, penetration);
- }
- if (m_faceRigidConstraints[i][j].m_static)
- {
- for (int l = 0; l < 3; ++l)
- {
- btReducedVector rv(dof);
- for (int k = 0; k < 3; ++k)
- {
- rv.m_indices.push_back(face->m_n[k]->index);
- btVector3 v(0, 0, 0);
- v[l] = bary[k];
- rv.m_vecs.push_back(v);
- rv.sort();
- }
- m_projections.push_back(rv);
- }
- }
- else
- {
- btReducedVector rv(dof);
- for (int k = 0; k < 3; ++k)
- {
- rv.m_indices.push_back(face->m_n[k]->index);
- rv.m_vecs.push_back(bary[k] * m_faceRigidConstraints[i][j].m_normal);
- rv.sort();
- }
- m_projections.push_back(rv);
- }
- }
- }
- btModifiedGramSchmidt<btReducedVector> mgs(m_projections);
- mgs.solve();
- m_projections = mgs.m_out;
-#endif
-}
-
-void btDeformableContactProjection::checkConstraints(const TVStack& x)
-{
- for (int i = 0; i < m_lagrangeMultipliers.size(); ++i)
- {
- btVector3 d(0, 0, 0);
- const LagrangeMultiplier& lm = m_lagrangeMultipliers[i];
- for (int j = 0; j < lm.m_num_constraints; ++j)
- {
- for (int k = 0; k < lm.m_num_nodes; ++k)
- {
- d[j] += lm.m_weights[k] * x[lm.m_indices[k]].dot(lm.m_dirs[j]);
- }
- }
- // printf("d = %f, %f, %f\n", d[0], d[1], d[2]);
- // printf("val = %f, %f, %f\n", lm.m_vals[0], lm.m_vals[1], lm.m_vals[2]);
- }
-}
-
-void btDeformableContactProjection::setLagrangeMultiplier()
-{
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < m_staticConstraints[i].size(); ++j)
- {
- int index = m_staticConstraints[i][j].m_node->index;
- m_staticConstraints[i][j].m_node->m_constrained = true;
- LagrangeMultiplier lm;
- lm.m_num_nodes = 1;
- lm.m_indices[0] = index;
- lm.m_weights[0] = 1.0;
- lm.m_num_constraints = 3;
- lm.m_dirs[0] = btVector3(1, 0, 0);
- lm.m_dirs[1] = btVector3(0, 1, 0);
- lm.m_dirs[2] = btVector3(0, 0, 1);
- m_lagrangeMultipliers.push_back(lm);
- }
- for (int j = 0; j < m_nodeAnchorConstraints[i].size(); ++j)
- {
- int index = m_nodeAnchorConstraints[i][j].m_anchor->m_node->index;
- m_nodeAnchorConstraints[i][j].m_anchor->m_node->m_constrained = true;
- LagrangeMultiplier lm;
- lm.m_num_nodes = 1;
- lm.m_indices[0] = index;
- lm.m_weights[0] = 1.0;
- lm.m_num_constraints = 3;
- lm.m_dirs[0] = btVector3(1, 0, 0);
- lm.m_dirs[1] = btVector3(0, 1, 0);
- lm.m_dirs[2] = btVector3(0, 0, 1);
- m_lagrangeMultipliers.push_back(lm);
- }
-
- for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
- {
- if (!m_nodeRigidConstraints[i][j].m_binding)
- {
- continue;
- }
- int index = m_nodeRigidConstraints[i][j].m_node->index;
- m_nodeRigidConstraints[i][j].m_node->m_constrained = true;
- LagrangeMultiplier lm;
- lm.m_num_nodes = 1;
- lm.m_indices[0] = index;
- lm.m_weights[0] = 1.0;
- if (m_nodeRigidConstraints[i][j].m_static)
- {
- lm.m_num_constraints = 3;
- lm.m_dirs[0] = btVector3(1, 0, 0);
- lm.m_dirs[1] = btVector3(0, 1, 0);
- lm.m_dirs[2] = btVector3(0, 0, 1);
- }
- else
- {
- lm.m_num_constraints = 1;
- lm.m_dirs[0] = m_nodeRigidConstraints[i][j].m_normal;
- }
- m_lagrangeMultipliers.push_back(lm);
- }
-
- for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
- {
- if (!m_faceRigidConstraints[i][j].m_binding)
- {
- continue;
- }
- btSoftBody::Face* face = m_faceRigidConstraints[i][j].m_face;
-
- btVector3 bary = m_faceRigidConstraints[i][j].getContact()->m_bary;
- LagrangeMultiplier lm;
- lm.m_num_nodes = 3;
-
- for (int k = 0; k < 3; ++k)
- {
- face->m_n[k]->m_constrained = true;
- lm.m_indices[k] = face->m_n[k]->index;
- lm.m_weights[k] = bary[k];
- }
- if (m_faceRigidConstraints[i][j].m_static)
- {
- face->m_pcontact[3] = 1;
- lm.m_num_constraints = 3;
- lm.m_dirs[0] = btVector3(1, 0, 0);
- lm.m_dirs[1] = btVector3(0, 1, 0);
- lm.m_dirs[2] = btVector3(0, 0, 1);
- }
- else
- {
- face->m_pcontact[3] = 0;
- lm.m_num_constraints = 1;
- lm.m_dirs[0] = m_faceRigidConstraints[i][j].m_normal;
- }
- m_lagrangeMultipliers.push_back(lm);
- }
- }
-}
-
-//
-void btDeformableContactProjection::applyDynamicFriction(TVStack& f)
-{
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- for (int j = 0; j < m_nodeRigidConstraints[i].size(); ++j)
- {
- const btDeformableNodeRigidContactConstraint& constraint = m_nodeRigidConstraints[i][j];
- const btSoftBody::Node* node = constraint.m_node;
- if (node->m_im != 0)
- {
- int index = node->index;
- f[index] += constraint.getDv(node) * (1. / node->m_im);
- }
- }
- for (int j = 0; j < m_faceRigidConstraints[i].size(); ++j)
- {
- const btDeformableFaceRigidContactConstraint& constraint = m_faceRigidConstraints[i][j];
- const btSoftBody::Face* face = constraint.getContact()->m_face;
- for (int k = 0; k < 3; ++k)
- {
- const btSoftBody::Node* node = face->m_n[k];
- if (node->m_im != 0)
- {
- int index = node->index;
- f[index] += constraint.getDv(node) * (1. / node->m_im);
- }
- }
- }
- for (int j = 0; j < m_deformableConstraints[i].size(); ++j)
- {
- const btDeformableFaceNodeContactConstraint& constraint = m_deformableConstraints[i][j];
- const btSoftBody::Face* face = constraint.getContact()->m_face;
- const btSoftBody::Node* node = constraint.getContact()->m_node;
- if (node->m_im != 0)
- {
- int index = node->index;
- f[index] += constraint.getDv(node) * (1. / node->m_im);
- }
- for (int k = 0; k < 3; ++k)
- {
- const btSoftBody::Node* node = face->m_n[k];
- if (node->m_im != 0)
- {
- int index = node->index;
- f[index] += constraint.getDv(node) * (1. / node->m_im);
- }
- }
- }
- }
-}
-
-void btDeformableContactProjection::reinitialize(bool nodeUpdated)
-{
- int N = m_softBodies.size();
- if (nodeUpdated)
- {
- m_staticConstraints.resize(N);
- m_nodeAnchorConstraints.resize(N);
- m_nodeRigidConstraints.resize(N);
- m_faceRigidConstraints.resize(N);
- m_deformableConstraints.resize(N);
- }
- for (int i = 0; i < N; ++i)
- {
- m_staticConstraints[i].clear();
- m_nodeAnchorConstraints[i].clear();
- m_nodeRigidConstraints[i].clear();
- m_faceRigidConstraints[i].clear();
- m_deformableConstraints[i].clear();
- }
-#ifndef USE_MGS
- m_projectionsDict.clear();
-#else
- m_projections.clear();
-#endif
- m_lagrangeMultipliers.clear();
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h b/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
deleted file mode 100644
index 4964eaf990..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableContactProjection.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_CONTACT_PROJECTION_H
-#define BT_CONTACT_PROJECTION_H
-#include "btCGProjection.h"
-#include "btSoftBody.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-#include "btDeformableContactConstraint.h"
-#include "LinearMath/btHashMap.h"
-#include "LinearMath/btReducedVector.h"
-#include "LinearMath/btModifiedGramSchmidt.h"
-#include <vector>
-
-struct LagrangeMultiplier
-{
- int m_num_constraints; // Number of constraints
- int m_num_nodes; // Number of nodes in these constraints
- btScalar m_weights[3]; // weights of the nodes involved, same size as m_num_nodes
- btVector3 m_dirs[3]; // Constraint directions, same size of m_num_constraints;
- int m_indices[3]; // indices of the nodes involved, same size as m_num_nodes;
-};
-
-class btDeformableContactProjection
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btAlignedObjectArray<btSoftBody*>& m_softBodies;
-
- // all constraints involving face
- btAlignedObjectArray<btDeformableContactConstraint*> m_allFaceConstraints;
-#ifndef USE_MGS
- // map from node index to projection directions
- btHashMap<btHashInt, btAlignedObjectArray<btVector3> > m_projectionsDict;
-#else
- btAlignedObjectArray<btReducedVector> m_projections;
-#endif
-
- btAlignedObjectArray<LagrangeMultiplier> m_lagrangeMultipliers;
-
- // map from node index to static constraint
- btAlignedObjectArray<btAlignedObjectArray<btDeformableStaticConstraint> > m_staticConstraints;
- // map from node index to node rigid constraint
- btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeRigidContactConstraint> > m_nodeRigidConstraints;
- // map from node index to face rigid constraint
- btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceRigidContactConstraint> > m_faceRigidConstraints;
- // map from node index to deformable constraint
- btAlignedObjectArray<btAlignedObjectArray<btDeformableFaceNodeContactConstraint> > m_deformableConstraints;
- // map from node index to node anchor constraint
- btAlignedObjectArray<btAlignedObjectArray<btDeformableNodeAnchorConstraint> > m_nodeAnchorConstraints;
-
- bool m_useStrainLimiting;
-
- btDeformableContactProjection(btAlignedObjectArray<btSoftBody*>& softBodies)
- : m_softBodies(softBodies)
- {
- }
-
- virtual ~btDeformableContactProjection()
- {
- }
-
- // apply the constraints to the rhs of the linear solve
- virtual void project(TVStack& x);
-
- // add friction force to the rhs of the linear solve
- virtual void applyDynamicFriction(TVStack& f);
-
- // update and solve the constraints
- virtual btScalar update(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
-
- // Add constraints to m_constraints. In addition, the constraints that each vertex own are recorded in m_constraintsDict.
- virtual void setConstraints(const btContactSolverInfo& infoGlobal);
-
- // Set up projections for each vertex by adding the projection direction to
- virtual void setProjection();
-
- virtual void reinitialize(bool nodeUpdated);
-
- btScalar solveSplitImpulse(btCollisionObject** deformableBodies, int numDeformableBodies, const btContactSolverInfo& infoGlobal);
-
- virtual void setLagrangeMultiplier();
-
- void checkConstraints(const TVStack& x);
-};
-#endif /* btDeformableContactProjection_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
deleted file mode 100644
index dfd85523bc..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableCorotatedForce.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_COROTATED_H
-#define BT_COROTATED_H
-
-#include "btDeformableLagrangianForce.h"
-#include "LinearMath/btPolarDecomposition.h"
-
-static inline int PolarDecomposition(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
-{
- static const btPolarDecomposition polar;
- return polar.decompose(m, q, s);
-}
-
-class btDeformableCorotatedForce : public btDeformableLagrangianForce
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btScalar m_mu, m_lambda;
- btDeformableCorotatedForce() : m_mu(1), m_lambda(1)
- {
- }
-
- btDeformableCorotatedForce(btScalar mu, btScalar lambda) : m_mu(mu), m_lambda(lambda)
- {
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- }
-
- virtual void addScaledElasticForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btMatrix3x3 P;
- firstPiola(tetra.m_F, P);
- btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose() * grad_N_hat_1st_col);
- btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
-
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
-
- // elastic force
- // explicit elastic force
- btScalar scale1 = scale * tetra.m_element_measure;
- force[id0] -= scale1 * force_on_node0;
- force[id1] -= scale1 * force_on_node123.getColumn(0);
- force[id2] -= scale1 * force_on_node123.getColumn(1);
- force[id3] -= scale1 * force_on_node123.getColumn(2);
- }
- }
- }
-
- void firstPiola(const btMatrix3x3& F, btMatrix3x3& P)
- {
- // btMatrix3x3 JFinvT = F.adjoint();
- btScalar J = F.determinant();
- P = F.adjoint().transpose() * (m_lambda * (J - 1));
- if (m_mu > SIMD_EPSILON)
- {
- btMatrix3x3 R, S;
- if (J < 1024 * SIMD_EPSILON)
- R.setIdentity();
- else
- PolarDecomposition(F, R, S); // this QR is not robust, consider using implicit shift svd
- /*https://fuchuyuan.github.io/research/svd/paper.pdf*/
- P += (F - R) * 2 * m_mu;
- }
- }
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- }
-
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_COROTATED_FORCE;
- }
-};
-
-#endif /* btCorotated_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
deleted file mode 100644
index d91867f457..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableGravityForce.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_GRAVITY_FORCE_H
-#define BT_DEFORMABLE_GRAVITY_FORCE_H
-
-#include "btDeformableLagrangianForce.h"
-
-class btDeformableGravityForce : public btDeformableLagrangianForce
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btVector3 m_gravity;
-
- btDeformableGravityForce(const btVector3& g) : m_gravity(g)
- {
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledGravityForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledGravityForce(scale, force);
- }
-
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- }
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- }
-
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
-
- virtual void addScaledGravityForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btSoftBody::Node& n = psb->m_nodes[j];
- size_t id = n.index;
- btScalar mass = (n.m_im == 0) ? 0 : 1. / n.m_im;
- btVector3 scaled_force = scale * m_gravity * mass * m_softBodies[i]->m_gravityFactor;
- force[id] += scaled_force;
- }
- }
- }
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_GRAVITY_FORCE;
- }
-
- // the gravitational potential energy
- virtual double totalEnergy(btScalar dt)
- {
- double e = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- if (node.m_im > 0)
- {
- e -= m_gravity.dot(node.m_q) / node.m_im;
- }
- }
- }
- return e;
- }
-};
-#endif /* BT_DEFORMABLE_GRAVITY_FORCE_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
deleted file mode 100644
index d58d825d1c..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableLagrangianForce.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_LAGRANGIAN_FORCE_H
-#define BT_DEFORMABLE_LAGRANGIAN_FORCE_H
-
-#include "btSoftBody.h"
-#include <LinearMath/btHashMap.h>
-#include <iostream>
-
-enum btDeformableLagrangianForceType
-{
- BT_GRAVITY_FORCE = 1,
- BT_MASSSPRING_FORCE = 2,
- BT_COROTATED_FORCE = 3,
- BT_NEOHOOKEAN_FORCE = 4,
- BT_LINEAR_ELASTICITY_FORCE = 5,
- BT_MOUSE_PICKING_FORCE = 6
-};
-
-static inline double randomDouble(double low, double high)
-{
- return low + static_cast<double>(rand()) / RAND_MAX * (high - low);
-}
-
-class btDeformableLagrangianForce
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btAlignedObjectArray<btSoftBody*> m_softBodies;
- const btAlignedObjectArray<btSoftBody::Node*>* m_nodes;
-
- btDeformableLagrangianForce()
- {
- }
-
- virtual ~btDeformableLagrangianForce() {}
-
- // add all forces
- virtual void addScaledForces(btScalar scale, TVStack& force) = 0;
-
- // add damping df
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df) = 0;
-
- // build diagonal of A matrix
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) = 0;
-
- // add elastic df
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df) = 0;
-
- // add all forces that are explicit in explicit solve
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force) = 0;
-
- // add all damping forces
- virtual void addScaledDampingForce(btScalar scale, TVStack& force) = 0;
-
- virtual void addScaledHessian(btScalar scale) {}
-
- virtual btDeformableLagrangianForceType getForceType() = 0;
-
- virtual void reinitialize(bool nodeUpdated)
- {
- }
-
- // get number of nodes that have the force
- virtual int getNumNodes()
- {
- int numNodes = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- numNodes += m_softBodies[i]->m_nodes.size();
- }
- return numNodes;
- }
-
- // add a soft body to be affected by the particular lagrangian force
- virtual void addSoftBody(btSoftBody* psb)
- {
- m_softBodies.push_back(psb);
- }
-
- virtual void removeSoftBody(btSoftBody* psb)
- {
- m_softBodies.remove(psb);
- }
-
- virtual void setIndices(const btAlignedObjectArray<btSoftBody::Node*>* nodes)
- {
- m_nodes = nodes;
- }
-
- // Calculate the incremental deformable generated from the input dx
- virtual btMatrix3x3 Ds(int id0, int id1, int id2, int id3, const TVStack& dx)
- {
- btVector3 c1 = dx[id1] - dx[id0];
- btVector3 c2 = dx[id2] - dx[id0];
- btVector3 c3 = dx[id3] - dx[id0];
- return btMatrix3x3(c1, c2, c3).transpose();
- }
-
- // Calculate the incremental deformable generated from the current velocity
- virtual btMatrix3x3 DsFromVelocity(const btSoftBody::Node* n0, const btSoftBody::Node* n1, const btSoftBody::Node* n2, const btSoftBody::Node* n3)
- {
- btVector3 c1 = n1->m_v - n0->m_v;
- btVector3 c2 = n2->m_v - n0->m_v;
- btVector3 c3 = n3->m_v - n0->m_v;
- return btMatrix3x3(c1, c2, c3).transpose();
- }
-
- // test for addScaledElasticForce function
- virtual void testDerivative()
- {
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
- }
- psb->updateDeformation();
- }
-
- TVStack dx;
- dx.resize(getNumNodes());
- TVStack dphi_dx;
- dphi_dx.resize(dx.size());
- for (int i = 0; i < dphi_dx.size(); ++i)
- {
- dphi_dx[i].setZero();
- }
- addScaledForces(-1, dphi_dx);
-
- // write down the current position
- TVStack x;
- x.resize(dx.size());
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- x[counter] = psb->m_nodes[j].m_q;
- counter++;
- }
- }
- counter = 0;
-
- // populate dx with random vectors
- for (int i = 0; i < dx.size(); ++i)
- {
- dx[i].setX(randomDouble(-1, 1));
- dx[i].setY(randomDouble(-1, 1));
- dx[i].setZ(randomDouble(-1, 1));
- }
-
- btAlignedObjectArray<double> errors;
- for (int it = 0; it < 10; ++it)
- {
- for (int i = 0; i < dx.size(); ++i)
- {
- dx[i] *= 0.5;
- }
-
- // get dphi/dx * dx
- double dphi = 0;
- for (int i = 0; i < dx.size(); ++i)
- {
- dphi += dphi_dx[i].dot(dx[i]);
- }
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter] + dx[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
- double f1 = totalElasticEnergy(0);
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter] - dx[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
-
- double f2 = totalElasticEnergy(0);
-
- //restore m_q
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
- double error = f1 - f2 - 2 * dphi;
- errors.push_back(error);
- std::cout << "Iteration = " << it << ", f1 = " << f1 << ", f2 = " << f2 << ", error = " << error << std::endl;
- }
- for (int i = 1; i < errors.size(); ++i)
- {
- std::cout << "Iteration = " << i << ", ratio = " << errors[i - 1] / errors[i] << std::endl;
- }
- }
-
- // test for addScaledElasticForce function
- virtual void testHessian()
- {
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q += btVector3(randomDouble(-.1, .1), randomDouble(-.1, .1), randomDouble(-.1, .1));
- }
- psb->updateDeformation();
- }
-
- TVStack dx;
- dx.resize(getNumNodes());
- TVStack df;
- df.resize(dx.size());
- TVStack f1;
- f1.resize(dx.size());
- TVStack f2;
- f2.resize(dx.size());
-
- // write down the current position
- TVStack x;
- x.resize(dx.size());
- int counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- x[counter] = psb->m_nodes[j].m_q;
- counter++;
- }
- }
- counter = 0;
-
- // populate dx with random vectors
- for (int i = 0; i < dx.size(); ++i)
- {
- dx[i].setX(randomDouble(-1, 1));
- dx[i].setY(randomDouble(-1, 1));
- dx[i].setZ(randomDouble(-1, 1));
- }
-
- btAlignedObjectArray<double> errors;
- for (int it = 0; it < 10; ++it)
- {
- for (int i = 0; i < dx.size(); ++i)
- {
- dx[i] *= 0.5;
- }
-
- // get df
- for (int i = 0; i < df.size(); ++i)
- {
- df[i].setZero();
- f1[i].setZero();
- f2[i].setZero();
- }
-
- //set df
- addScaledElasticForceDifferential(-1, dx, df);
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter] + dx[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
-
- //set f1
- addScaledForces(-1, f1);
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter] - dx[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
-
- //set f2
- addScaledForces(-1, f2);
-
- //restore m_q
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = x[counter];
- counter++;
- }
- psb->updateDeformation();
- }
- counter = 0;
- double error = 0;
- for (int i = 0; i < df.size(); ++i)
- {
- btVector3 error_vector = f1[i] - f2[i] - 2 * df[i];
- error += error_vector.length2();
- }
- error = btSqrt(error);
- errors.push_back(error);
- std::cout << "Iteration = " << it << ", error = " << error << std::endl;
- }
- for (int i = 1; i < errors.size(); ++i)
- {
- std::cout << "Iteration = " << i << ", ratio = " << errors[i - 1] / errors[i] << std::endl;
- }
- }
-
- //
- virtual double totalElasticEnergy(btScalar dt)
- {
- return 0;
- }
-
- //
- virtual double totalDampingEnergy(btScalar dt)
- {
- return 0;
- }
-
- // total Energy takes dt as input because certain energies depend on dt
- virtual double totalEnergy(btScalar dt)
- {
- return totalElasticEnergy(dt) + totalDampingEnergy(dt);
- }
-};
-#endif /* BT_DEFORMABLE_LAGRANGIAN_FORCE */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
deleted file mode 100644
index 971192050b..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableLinearElasticityForce.h
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_LINEAR_ELASTICITY_H
-#define BT_LINEAR_ELASTICITY_H
-
-#include "btDeformableLagrangianForce.h"
-#include "LinearMath/btQuickprof.h"
-#include "btSoftBodyInternals.h"
-#define TETRA_FLAT_THRESHOLD 0.01
-class btDeformableLinearElasticityForce : public btDeformableLagrangianForce
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btScalar m_mu, m_lambda;
- btScalar m_E, m_nu; // Young's modulus and Poisson ratio
- btScalar m_damping_alpha, m_damping_beta;
- btDeformableLinearElasticityForce() : m_mu(1), m_lambda(1), m_damping_alpha(0.01), m_damping_beta(0.01)
- {
- updateYoungsModulusAndPoissonRatio();
- }
-
- btDeformableLinearElasticityForce(btScalar mu, btScalar lambda, btScalar damping_alpha = 0.01, btScalar damping_beta = 0.01) : m_mu(mu), m_lambda(lambda), m_damping_alpha(damping_alpha), m_damping_beta(damping_beta)
- {
- updateYoungsModulusAndPoissonRatio();
- }
-
- void updateYoungsModulusAndPoissonRatio()
- {
- // conversion from Lame Parameters to Young's modulus and Poisson ratio
- // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
- m_E = m_mu * (3 * m_lambda + 2 * m_mu) / (m_lambda + m_mu);
- m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
- }
-
- void updateLameParameters()
- {
- // conversion from Young's modulus and Poisson ratio to Lame Parameters
- // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
- m_mu = m_E * 0.5 / (1 + m_nu);
- m_lambda = m_E * m_nu / ((1 + m_nu) * (1 - 2 * m_nu));
- }
-
- void setYoungsModulus(btScalar E)
- {
- m_E = E;
- updateLameParameters();
- }
-
- void setPoissonRatio(btScalar nu)
- {
- m_nu = nu;
- updateLameParameters();
- }
-
- void setDamping(btScalar damping_alpha, btScalar damping_beta)
- {
- m_damping_alpha = damping_alpha;
- m_damping_beta = damping_beta;
- }
-
- void setLameParameters(btScalar mu, btScalar lambda)
- {
- m_mu = mu;
- m_lambda = lambda;
- updateYoungsModulusAndPoissonRatio();
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledDampingForce(scale, force);
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- if (m_damping_alpha == 0 && m_damping_beta == 0)
- return;
- btScalar mu_damp = m_damping_beta * m_mu;
- btScalar lambda_damp = m_damping_beta * m_lambda;
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- bool close_to_flat = (psb->m_tetraScratches[j].m_J < TETRA_FLAT_THRESHOLD);
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
- if (!close_to_flat)
- {
- dF = psb->m_tetraScratches[j].m_corotation.transpose() * dF;
- }
- btMatrix3x3 I;
- I.setIdentity();
- btMatrix3x3 dP = (dF + dF.transpose()) * mu_damp + I * ((dF[0][0] + dF[1][1] + dF[2][2]) * lambda_damp);
- btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
- if (!close_to_flat)
- {
- df_on_node123 = psb->m_tetraScratches[j].m_corotation * df_on_node123;
- }
- btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
- // damping force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- force[id0] -= scale1 * df_on_node0;
- force[id1] -= scale1 * df_on_node123.getColumn(0);
- force[id2] -= scale1 * df_on_node123.getColumn(1);
- force[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- size_t id = node.index;
- if (node.m_im > 0)
- {
- force[id] -= scale * node.m_v / node.m_im * m_damping_alpha;
- }
- }
- }
- }
-
- virtual double totalElasticEnergy(btScalar dt)
- {
- double energy = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
- energy += tetra.m_element_measure * elasticEnergyDensity(s);
- }
- }
- return energy;
- }
-
- // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual double totalDampingEnergy(btScalar dt)
- {
- double energy = 0;
- int sz = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- sz = btMax(sz, psb->m_nodes[j].index);
- }
- }
- TVStack dampingForce;
- dampingForce.resize(sz + 1);
- for (int i = 0; i < dampingForce.size(); ++i)
- dampingForce[i].setZero();
- addScaledDampingForce(0.5, dampingForce);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- energy -= dampingForce[node.index].dot(node.m_v) / dt;
- }
- }
- return energy;
- }
-
- double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
- {
- double density = 0;
- btMatrix3x3 epsilon = (s.m_F + s.m_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
- btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
- density += m_mu * (epsilon[0].length2() + epsilon[1].length2() + epsilon[2].length2());
- density += m_lambda * trace * trace * 0.5;
- return density;
- }
-
- virtual void addScaledElasticForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- btScalar max_p = psb->m_cfg.m_maxStress;
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btMatrix3x3 P;
- firstPiola(psb->m_tetraScratches[j], P);
-#if USE_SVD
- if (max_p > 0)
- {
- // since we want to clamp the principal stress to max_p, we only need to
- // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
- btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
- if (trPTP > max_p * max_p)
- {
- btMatrix3x3 U, V;
- btVector3 sigma;
- singularValueDecomposition(P, U, sigma, V);
- sigma[0] = btMin(sigma[0], max_p);
- sigma[1] = btMin(sigma[1], max_p);
- sigma[2] = btMin(sigma[2], max_p);
- sigma[0] = btMax(sigma[0], -max_p);
- sigma[1] = btMax(sigma[1], -max_p);
- sigma[2] = btMax(sigma[2], -max_p);
- btMatrix3x3 Sigma;
- Sigma.setIdentity();
- Sigma[0][0] = sigma[0];
- Sigma[1][1] = sigma[1];
- Sigma[2][2] = sigma[2];
- P = U * Sigma * V.transpose();
- }
- }
-#endif
- // btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
- btMatrix3x3 force_on_node123 = psb->m_tetraScratches[j].m_corotation * P * tetra.m_Dm_inverse.transpose();
- btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
-
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
-
- // elastic force
- btScalar scale1 = scale * tetra.m_element_measure;
- force[id0] -= scale1 * force_on_node0;
- force[id1] -= scale1 * force_on_node123.getColumn(0);
- force[id2] -= scale1 * force_on_node123.getColumn(1);
- force[id3] -= scale1 * force_on_node123.getColumn(2);
- }
- }
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
-
- // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- if (m_damping_alpha == 0 && m_damping_beta == 0)
- return;
- btScalar mu_damp = m_damping_beta * m_mu;
- btScalar lambda_damp = m_damping_beta * m_lambda;
- int numNodes = getNumNodes();
- btAssert(numNodes <= df.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- bool close_to_flat = (psb->m_tetraScratches[j].m_J < TETRA_FLAT_THRESHOLD);
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
- if (!close_to_flat)
- {
- dF = psb->m_tetraScratches[j].m_corotation.transpose() * dF;
- }
- btMatrix3x3 I;
- I.setIdentity();
- btMatrix3x3 dP = (dF + dF.transpose()) * mu_damp + I * ((dF[0][0] + dF[1][1] + dF[2][2]) * lambda_damp);
- btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
- if (!close_to_flat)
- {
- df_on_node123 = psb->m_tetraScratches[j].m_corotation * df_on_node123;
- }
- btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
-
- // damping force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- df[id0] -= scale1 * df_on_node0;
- df[id1] -= scale1 * df_on_node123.getColumn(0);
- df[id2] -= scale1 * df_on_node123.getColumn(1);
- df[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- size_t id = node.index;
- if (node.m_im > 0)
- {
- df[id] -= scale * dv[id] / node.m_im * m_damping_alpha;
- }
- }
- }
- }
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= df.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = psb->m_tetraScratches[j].m_corotation.transpose() * Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
- btMatrix3x3 dP;
- firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
- // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
- btMatrix3x3 df_on_node123 = psb->m_tetraScratches[j].m_corotation * dP * tetra.m_Dm_inverse.transpose();
- btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
-
- // elastic force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- df[id0] -= scale1 * df_on_node0;
- df[id1] -= scale1 * df_on_node123.getColumn(0);
- df[id2] -= scale1 * df_on_node123.getColumn(1);
- df[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- }
- }
-
- void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
- {
- btMatrix3x3 corotated_F = s.m_corotation.transpose() * s.m_F;
-
- btMatrix3x3 epsilon = (corotated_F + corotated_F.transpose()) * 0.5 - btMatrix3x3::getIdentity();
- btScalar trace = epsilon[0][0] + epsilon[1][1] + epsilon[2][2];
- P = epsilon * btScalar(2) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
- }
-
- // Let P be the first piola stress.
- // This function calculates the dP = dP/dF * dF
- void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
- {
- btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
- dP = (dF + dF.transpose()) * m_mu + btMatrix3x3::getIdentity() * m_lambda * trace;
- }
-
- // Let Q be the damping stress.
- // This function calculates the dP = dQ/dF * dF
- void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
- {
- btScalar mu_damp = m_damping_beta * m_mu;
- btScalar lambda_damp = m_damping_beta * m_lambda;
- btScalar trace = (dF[0][0] + dF[1][1] + dF[2][2]);
- dP = (dF + dF.transpose()) * mu_damp + btMatrix3x3::getIdentity() * lambda_damp * trace;
- }
-
- virtual void addScaledHessian(btScalar scale)
- {
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btMatrix3x3 P;
- firstPiola(psb->m_tetraScratches[j], P); // make sure scratch is evaluated at x_n + dt * vn
- btMatrix3x3 force_on_node123 = psb->m_tetraScratches[j].m_corotation * P * tetra.m_Dm_inverse.transpose();
- btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- btScalar scale1 = scale * (scale + m_damping_beta) * tetra.m_element_measure; // stiff and stiffness-damping terms;
- node0->m_effectiveMass += OuterProduct(force_on_node0, force_on_node0) * scale1;
- node1->m_effectiveMass += OuterProduct(force_on_node123.getColumn(0), force_on_node123.getColumn(0)) * scale1;
- node2->m_effectiveMass += OuterProduct(force_on_node123.getColumn(1), force_on_node123.getColumn(1)) * scale1;
- node3->m_effectiveMass += OuterProduct(force_on_node123.getColumn(2), force_on_node123.getColumn(2)) * scale1;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btSoftBody::Node& node = psb->m_nodes[j];
- if (node.m_im > 0)
- {
- btMatrix3x3 I;
- I.setIdentity();
- node.m_effectiveMass += I * (scale * (1.0 / node.m_im) * m_damping_alpha);
- }
- }
- }
- }
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_LINEAR_ELASTICITY_FORCE;
- }
-};
-#endif /* BT_LINEAR_ELASTICITY_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
deleted file mode 100644
index 8c97bd1ba8..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMassSpringForce.h
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_MASS_SPRING_H
-#define BT_MASS_SPRING_H
-
-#include "btDeformableLagrangianForce.h"
-
-class btDeformableMassSpringForce : public btDeformableLagrangianForce
-{
- // If true, the damping force will be in the direction of the spring
- // If false, the damping force will be in the direction of the velocity
- bool m_momentum_conserving;
- btScalar m_elasticStiffness, m_dampingStiffness, m_bendingStiffness;
-
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btDeformableMassSpringForce() : m_momentum_conserving(false), m_elasticStiffness(1), m_dampingStiffness(0.05)
- {
- }
- btDeformableMassSpringForce(btScalar k, btScalar d, bool conserve_angular = true, double bending_k = -1) : m_momentum_conserving(conserve_angular), m_elasticStiffness(k), m_dampingStiffness(d), m_bendingStiffness(bending_k)
- {
- if (m_bendingStiffness < btScalar(0))
- {
- m_bendingStiffness = m_elasticStiffness;
- }
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledDampingForce(scale, force);
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- const btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- size_t id1 = node1->index;
- size_t id2 = node2->index;
-
- // damping force
- btVector3 v_diff = (node2->m_v - node1->m_v);
- btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
- if (m_momentum_conserving)
- {
- if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (node2->m_x - node1->m_x).normalized();
- scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
- }
- }
- force[id1] += scaled_force;
- force[id2] -= scaled_force;
- }
- }
- }
-
- virtual void addScaledElasticForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- const btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- btScalar r = link.m_rl;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
-
- // elastic force
- btVector3 dir = (node2->m_q - node1->m_q);
- btVector3 dir_normalized = (dir.norm() > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
- btScalar scaled_stiffness = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
- btVector3 scaled_force = scaled_stiffness * (dir - dir_normalized * r);
- force[id1] += scaled_force;
- force[id2] -= scaled_force;
- }
- }
- }
-
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- // implicit damping force differential
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- btScalar scaled_k_damp = m_dampingStiffness * scale;
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- size_t id1 = node1->index;
- size_t id2 = node2->index;
-
- btVector3 local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]);
- if (m_momentum_conserving)
- {
- if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (node2->m_x - node1->m_x).normalized();
- local_scaled_df = scaled_k_damp * (dv[id2] - dv[id1]).dot(dir) * dir;
- }
- }
- df[id1] += local_scaled_df;
- df[id2] -= local_scaled_df;
- }
- }
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA)
- {
- // implicit damping force differential
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- btScalar scaled_k_damp = m_dampingStiffness * scale;
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- if (m_momentum_conserving)
- {
- if ((node2->m_x - node1->m_x).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (node2->m_x - node1->m_x).normalized();
- for (int d = 0; d < 3; ++d)
- {
- if (node1->m_im > 0)
- diagA[id1][d] -= scaled_k_damp * dir[d] * dir[d];
- if (node2->m_im > 0)
- diagA[id2][d] -= scaled_k_damp * dir[d] * dir[d];
- }
- }
- }
- else
- {
- for (int d = 0; d < 3; ++d)
- {
- if (node1->m_im > 0)
- diagA[id1][d] -= scaled_k_damp;
- if (node2->m_im > 0)
- diagA[id2][d] -= scaled_k_damp;
- }
- }
- }
- }
- }
-
- virtual double totalElasticEnergy(btScalar dt)
- {
- double energy = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- const btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- btScalar r = link.m_rl;
-
- // elastic force
- btVector3 dir = (node2->m_q - node1->m_q);
- energy += 0.5 * m_elasticStiffness * (dir.norm() - r) * (dir.norm() - r);
- }
- }
- return energy;
- }
-
- virtual double totalDampingEnergy(btScalar dt)
- {
- double energy = 0;
- int sz = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- sz = btMax(sz, psb->m_nodes[j].index);
- }
- }
- TVStack dampingForce;
- dampingForce.resize(sz + 1);
- for (int i = 0; i < dampingForce.size(); ++i)
- dampingForce[i].setZero();
- addScaledDampingForce(0.5, dampingForce);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- energy -= dampingForce[node.index].dot(node.m_v) / dt;
- }
- }
- return energy;
- }
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- // implicit damping force differential
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- const btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_links.size(); ++j)
- {
- const btSoftBody::Link& link = psb->m_links[j];
- btSoftBody::Node* node1 = link.m_n[0];
- btSoftBody::Node* node2 = link.m_n[1];
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- btScalar r = link.m_rl;
-
- btVector3 dir = (node1->m_q - node2->m_q);
- btScalar dir_norm = dir.norm();
- btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
- btVector3 dx_diff = dx[id1] - dx[id2];
- btVector3 scaled_df = btVector3(0, 0, 0);
- btScalar scaled_k = scale * (link.m_bbending ? m_bendingStiffness : m_elasticStiffness);
- if (dir_norm > SIMD_EPSILON)
- {
- scaled_df -= scaled_k * dir_normalized.dot(dx_diff) * dir_normalized;
- scaled_df += scaled_k * dir_normalized.dot(dx_diff) * ((dir_norm - r) / dir_norm) * dir_normalized;
- scaled_df -= scaled_k * ((dir_norm - r) / dir_norm) * dx_diff;
- }
-
- df[id1] += scaled_df;
- df[id2] -= scaled_df;
- }
- }
- }
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_MASSSPRING_FORCE;
- }
-};
-
-#endif /* btMassSpring_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h
deleted file mode 100644
index 697408355c..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMousePickingForce.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_MOUSE_PICKING_FORCE_H
-#define BT_MOUSE_PICKING_FORCE_H
-
-#include "btDeformableLagrangianForce.h"
-
-class btDeformableMousePickingForce : public btDeformableLagrangianForce
-{
- // If true, the damping force will be in the direction of the spring
- // If false, the damping force will be in the direction of the velocity
- btScalar m_elasticStiffness, m_dampingStiffness;
- const btSoftBody::Face& m_face;
- btVector3 m_mouse_pos;
- btScalar m_maxForce;
-
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btDeformableMousePickingForce(btScalar k, btScalar d, const btSoftBody::Face& face, const btVector3& mouse_pos, btScalar maxForce = 0.3) : m_elasticStiffness(k), m_dampingStiffness(d), m_face(face), m_mouse_pos(mouse_pos), m_maxForce(maxForce)
- {
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledDampingForce(scale, force);
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- for (int i = 0; i < 3; ++i)
- {
- btVector3 v_diff = m_face.m_n[i]->m_v;
- btVector3 scaled_force = scale * m_dampingStiffness * v_diff;
- if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
- scaled_force = scale * m_dampingStiffness * v_diff.dot(dir) * dir;
- }
- force[m_face.m_n[i]->index] -= scaled_force;
- }
- }
-
- virtual void addScaledElasticForce(btScalar scale, TVStack& force)
- {
- btScalar scaled_stiffness = scale * m_elasticStiffness;
- for (int i = 0; i < 3; ++i)
- {
- btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
- btVector3 scaled_force = scaled_stiffness * dir;
- if (scaled_force.safeNorm() > m_maxForce)
- {
- scaled_force.safeNormalize();
- scaled_force *= m_maxForce;
- }
- force[m_face.m_n[i]->index] -= scaled_force;
- }
- }
-
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- btScalar scaled_k_damp = m_dampingStiffness * scale;
- for (int i = 0; i < 3; ++i)
- {
- btVector3 local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index];
- if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
- local_scaled_df = scaled_k_damp * dv[m_face.m_n[i]->index].dot(dir) * dir;
- }
- df[m_face.m_n[i]->index] -= local_scaled_df;
- }
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
-
- virtual double totalElasticEnergy(btScalar dt)
- {
- double energy = 0;
- for (int i = 0; i < 3; ++i)
- {
- btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
- btVector3 scaled_force = m_elasticStiffness * dir;
- if (scaled_force.safeNorm() > m_maxForce)
- {
- scaled_force.safeNormalize();
- scaled_force *= m_maxForce;
- }
- energy += 0.5 * scaled_force.dot(dir);
- }
- return energy;
- }
-
- virtual double totalDampingEnergy(btScalar dt)
- {
- double energy = 0;
- for (int i = 0; i < 3; ++i)
- {
- btVector3 v_diff = m_face.m_n[i]->m_v;
- btVector3 scaled_force = m_dampingStiffness * v_diff;
- if ((m_face.m_n[i]->m_x - m_mouse_pos).norm() > SIMD_EPSILON)
- {
- btVector3 dir = (m_face.m_n[i]->m_x - m_mouse_pos).normalized();
- scaled_force = m_dampingStiffness * v_diff.dot(dir) * dir;
- }
- energy -= scaled_force.dot(m_face.m_n[i]->m_v) / dt;
- }
- return energy;
- }
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- btScalar scaled_stiffness = scale * m_elasticStiffness;
- for (int i = 0; i < 3; ++i)
- {
- btVector3 dir = (m_face.m_n[i]->m_q - m_mouse_pos);
- btScalar dir_norm = dir.norm();
- btVector3 dir_normalized = (dir_norm > SIMD_EPSILON) ? dir.normalized() : btVector3(0, 0, 0);
- int id = m_face.m_n[i]->index;
- btVector3 dx_diff = dx[id];
- btScalar r = 0; // rest length is 0 for picking spring
- btVector3 scaled_df = btVector3(0, 0, 0);
- if (dir_norm > SIMD_EPSILON)
- {
- scaled_df -= scaled_stiffness * dir_normalized.dot(dx_diff) * dir_normalized;
- scaled_df += scaled_stiffness * dir_normalized.dot(dx_diff) * ((dir_norm - r) / dir_norm) * dir_normalized;
- scaled_df -= scaled_stiffness * ((dir_norm - r) / dir_norm) * dx_diff;
- }
- df[id] += scaled_df;
- }
- }
-
- void setMousePos(const btVector3& p)
- {
- m_mouse_pos = p;
- }
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_MOUSE_PICKING_FORCE;
- }
-};
-
-#endif /* btMassSpring_h */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
deleted file mode 100644
index 631fd5fbed..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#include "btDeformableMultiBodyConstraintSolver.h"
-#include <iostream>
-// override the iterations method to include deformable/multibody contact
-btScalar btDeformableMultiBodyConstraintSolver::solveDeformableGroupIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- {
- ///this is a special step to resolve penetrations (just for contacts)
- solveGroupCacheFriendlySplitImpulseIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
-
- int maxIterations = m_maxOverrideNumSolverIterations > infoGlobal.m_numIterations ? m_maxOverrideNumSolverIterations : infoGlobal.m_numIterations;
- for (int iteration = 0; iteration < maxIterations; iteration++)
- {
- // rigid bodies are solved using solver body velocity, but rigid/deformable contact directly uses the velocity of the actual rigid body. So we have to do the following: Solve one iteration of the rigid/rigid contact, get the updated velocity in the solver body and update the velocity of the underlying rigid body. Then solve the rigid/deformable contact. Finally, grab the (once again) updated rigid velocity and update the velocity of the wrapping solver body
-
- // solve rigid/rigid in solver body
- m_leastSquaresResidual = solveSingleIteration(iteration, bodies, numBodies, manifoldPtr, numManifolds, constraints, numConstraints, infoGlobal, debugDrawer);
- // solver body velocity -> rigid body velocity
- solverBodyWriteBack(infoGlobal);
- btScalar deformableResidual = m_deformableSolver->solveContactConstraints(deformableBodies, numDeformableBodies, infoGlobal);
- // update rigid body velocity in rigid/deformable contact
- m_leastSquaresResidual = btMax(m_leastSquaresResidual, deformableResidual);
- // solver body velocity <- rigid body velocity
- writeToSolverBody(bodies, numBodies, infoGlobal);
-
- if (m_leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || (iteration >= (maxIterations - 1)))
- {
-#ifdef VERBOSE_RESIDUAL_PRINTF
- if (iteration >= (maxIterations - 1))
- printf("residual = %f at iteration #%d\n", m_leastSquaresResidual, iteration);
-#endif
- m_analyticsData.m_numSolverCalls++;
- m_analyticsData.m_numIterationsUsed = iteration + 1;
- m_analyticsData.m_islandId = -2;
- if (numBodies > 0)
- m_analyticsData.m_islandId = bodies[0]->getCompanionId();
- m_analyticsData.m_numBodies = numBodies;
- m_analyticsData.m_numContactManifolds = numManifolds;
- m_analyticsData.m_remainingLeastSquaresResidual = m_leastSquaresResidual;
- break;
- }
- }
- }
- return 0.f;
-}
-
-void btDeformableMultiBodyConstraintSolver::solveDeformableBodyGroup(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher)
-{
- m_tmpMultiBodyConstraints = multiBodyConstraints;
- m_tmpNumMultiBodyConstraints = numMultiBodyConstraints;
-
- // inherited from MultiBodyConstraintSolver
- solveGroupCacheFriendlySetup(bodies, numBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
-
- // overriden
- solveDeformableGroupIterations(bodies, numBodies, deformableBodies, numDeformableBodies, manifold, numManifolds, constraints, numConstraints, info, debugDrawer);
-
- // inherited from MultiBodyConstraintSolver
- solveGroupCacheFriendlyFinish(bodies, numBodies, info);
-
- m_tmpMultiBodyConstraints = 0;
- m_tmpNumMultiBodyConstraints = 0;
-}
-
-void btDeformableMultiBodyConstraintSolver::writeToSolverBody(btCollisionObject** bodies, int numBodies, const btContactSolverInfo& infoGlobal)
-{
- for (int i = 0; i < numBodies; i++)
- {
- int bodyId = getOrInitSolverBody(*bodies[i], infoGlobal.m_timeStep);
-
- btRigidBody* body = btRigidBody::upcast(bodies[i]);
- if (body && body->getInvMass())
- {
- btSolverBody& solverBody = m_tmpSolverBodyPool[bodyId];
- solverBody.m_linearVelocity = body->getLinearVelocity() - solverBody.m_deltaLinearVelocity;
- solverBody.m_angularVelocity = body->getAngularVelocity() - solverBody.m_deltaAngularVelocity;
- }
- }
-}
-
-void btDeformableMultiBodyConstraintSolver::solverBodyWriteBack(const btContactSolverInfo& infoGlobal)
-{
- for (int i = 0; i < m_tmpSolverBodyPool.size(); i++)
- {
- btRigidBody* body = m_tmpSolverBodyPool[i].m_originalBody;
- if (body)
- {
- m_tmpSolverBodyPool[i].m_originalBody->setLinearVelocity(m_tmpSolverBodyPool[i].m_linearVelocity + m_tmpSolverBodyPool[i].m_deltaLinearVelocity);
- m_tmpSolverBodyPool[i].m_originalBody->setAngularVelocity(m_tmpSolverBodyPool[i].m_angularVelocity + m_tmpSolverBodyPool[i].m_deltaAngularVelocity);
- }
- }
-}
-
-void btDeformableMultiBodyConstraintSolver::solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject** bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer)
-{
- BT_PROFILE("solveGroupCacheFriendlySplitImpulseIterations");
- int iteration;
- if (infoGlobal.m_splitImpulse)
- {
- {
- for (iteration = 0; iteration < infoGlobal.m_numIterations; iteration++)
- {
- btScalar leastSquaresResidual = 0.f;
- {
- int numPoolConstraints = m_tmpSolverContactConstraintPool.size();
- int j;
- for (j = 0; j < numPoolConstraints; j++)
- {
- const btSolverConstraint& solveManifold = m_tmpSolverContactConstraintPool[m_orderTmpConstraintPool[j]];
-
- btScalar residual = resolveSplitPenetrationImpulse(m_tmpSolverBodyPool[solveManifold.m_solverBodyIdA], m_tmpSolverBodyPool[solveManifold.m_solverBodyIdB], solveManifold);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- // solve the position correction between deformable and rigid/multibody
- // btScalar residual = m_deformableSolver->solveSplitImpulse(infoGlobal);
- btScalar residual = m_deformableSolver->m_objective->m_projection.solveSplitImpulse(deformableBodies, numDeformableBodies, infoGlobal);
- leastSquaresResidual = btMax(leastSquaresResidual, residual * residual);
- }
- if (leastSquaresResidual <= infoGlobal.m_leastSquaresResidualThreshold || iteration >= (infoGlobal.m_numIterations - 1))
- {
-#ifdef VERBOSE_RESIDUAL_PRINTF
- if (iteration >= (infoGlobal.m_numIterations - 1))
- printf("split impulse residual = %f at iteration #%d\n", leastSquaresResidual, iteration);
-#endif
- break;
- }
- }
- }
- }
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
deleted file mode 100644
index 94aabce838..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyConstraintSolver.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
-#define BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H
-
-#include "btDeformableBodySolver.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.h"
-
-class btDeformableBodySolver;
-
-// btDeformableMultiBodyConstraintSolver extendsn btMultiBodyConstraintSolver to solve for the contact among rigid/multibody and deformable bodies. Notice that the following constraints
-// 1. rigid/multibody against rigid/multibody
-// 2. rigid/multibody against deforamble
-// 3. deformable against deformable
-// 4. deformable self collision
-// 5. joint constraints
-// are all coupled in this solve.
-ATTRIBUTE_ALIGNED16(class)
-btDeformableMultiBodyConstraintSolver : public btMultiBodyConstraintSolver
-{
- btDeformableBodySolver* m_deformableSolver;
-
-protected:
- // override the iterations method to include deformable/multibody contact
- // virtual btScalar solveGroupCacheFriendlyIterations(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer);
-
- // write the velocity of the the solver body to the underlying rigid body
- void solverBodyWriteBack(const btContactSolverInfo& infoGlobal);
-
- // write the velocity of the underlying rigid body to the the the solver body
- void writeToSolverBody(btCollisionObject * *bodies, int numBodies, const btContactSolverInfo& infoGlobal);
-
- virtual void solveGroupCacheFriendlySplitImpulseIterations(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
- virtual btScalar solveDeformableGroupIterations(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifoldPtr, int numManifolds, btTypedConstraint** constraints, int numConstraints, const btContactSolverInfo& infoGlobal, btIDebugDraw* debugDrawer);
-
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- void setDeformableSolver(btDeformableBodySolver * deformableSolver)
- {
- m_deformableSolver = deformableSolver;
- }
-
- virtual void solveDeformableBodyGroup(btCollisionObject * *bodies, int numBodies, btCollisionObject** deformableBodies, int numDeformableBodies, btPersistentManifold** manifold, int numManifolds, btTypedConstraint** constraints, int numConstraints, btMultiBodyConstraint** multiBodyConstraints, int numMultiBodyConstraints, const btContactSolverInfo& info, btIDebugDraw* debugDrawer, btDispatcher* dispatcher);
-};
-
-#endif /* BT_DEFORMABLE_MULTIBODY_CONSTRAINT_SOLVER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
deleted file mode 100644
index 983e622b5f..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.cpp
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-/* ====== Overview of the Deformable Algorithm ====== */
-
-/*
-A single step of the deformable body simulation contains the following main components:
-Call internalStepSimulation multiple times, to achieve 240Hz (4 steps of 60Hz).
-1. Deformable maintaintenance of rest lengths and volume preservation. Forces only depend on position: Update velocity to a temporary state v_{n+1}^* = v_n + explicit_force * dt / mass, where explicit forces include gravity and elastic forces.
-2. Detect discrete collisions between rigid and deformable bodies at position x_{n+1}^* = x_n + dt * v_{n+1}^*.
-
-3a. Solve all constraints, including LCP. Contact, position correction due to numerical drift, friction, and anchors for deformable.
-
-3b. 5 Newton steps (multiple step). Conjugent Gradient solves linear system. Deformable Damping: Then velocities of deformable bodies v_{n+1} are solved in
- M(v_{n+1} - v_{n+1}^*) = damping_force * dt / mass,
- by a conjugate gradient solver, where the damping force is implicit and depends on v_{n+1}.
- Make sure contact constraints are not violated in step b by performing velocity projections as in the paper by Baraff and Witkin https://www.cs.cmu.edu/~baraff/papers/sig98.pdf. Dynamic frictions are treated as a force and added to the rhs of the CG solve, whereas static frictions are treated as constraints similar to contact.
-4. Position is updated via x_{n+1} = x_n + dt * v_{n+1}.
-
-
-The algorithm also closely resembles the one in http://physbam.stanford.edu/~fedkiw/papers/stanford2008-03.pdf
- */
-
-#include <stdio.h>
-#include "btDeformableMultiBodyDynamicsWorld.h"
-#include "DeformableBodyInplaceSolverIslandCallback.h"
-#include "btDeformableBodySolver.h"
-#include "LinearMath/btQuickprof.h"
-#include "btSoftBodyInternals.h"
-btDeformableMultiBodyDynamicsWorld::btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver)
- : btMultiBodyDynamicsWorld(dispatcher, pairCache, (btMultiBodyConstraintSolver*)constraintSolver, collisionConfiguration),
- m_deformableBodySolver(deformableBodySolver),
- m_solverCallback(0)
-{
- m_drawFlags = fDrawFlags::Std;
- m_drawNodeTree = true;
- m_drawFaceTree = false;
- m_drawClusterTree = false;
- m_sbi.m_broadphase = pairCache;
- m_sbi.m_dispatcher = dispatcher;
- m_sbi.m_sparsesdf.Initialize();
- m_sbi.m_sparsesdf.setDefaultVoxelsz(0.005);
- m_sbi.m_sparsesdf.Reset();
-
- m_sbi.air_density = (btScalar)1.2;
- m_sbi.water_density = 0;
- m_sbi.water_offset = 0;
- m_sbi.water_normal = btVector3(0, 0, 0);
- m_sbi.m_gravity.setValue(0, -9.8, 0);
- m_internalTime = 0.0;
- m_implicit = false;
- m_lineSearch = false;
- m_useProjection = false;
- m_ccdIterations = 5;
- m_solverDeformableBodyIslandCallback = new DeformableBodyInplaceSolverIslandCallback(constraintSolver, dispatcher);
-}
-
-btDeformableMultiBodyDynamicsWorld::~btDeformableMultiBodyDynamicsWorld()
-{
- delete m_solverDeformableBodyIslandCallback;
-}
-
-void btDeformableMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
-{
- BT_PROFILE("internalSingleStepSimulation");
- if (0 != m_internalPreTickCallback)
- {
- (*m_internalPreTickCallback)(this, timeStep);
- }
- reinitialize(timeStep);
-
- // add gravity to velocity of rigid and multi bodys
- applyRigidBodyGravity(timeStep);
-
- ///apply gravity and explicit force to velocity, predict motion
- predictUnconstraintMotion(timeStep);
-
- ///perform collision detection that involves rigid/multi bodies
- btMultiBodyDynamicsWorld::performDiscreteCollisionDetection();
-
- btMultiBodyDynamicsWorld::calculateSimulationIslands();
-
- beforeSolverCallbacks(timeStep);
-
- ///solve contact constraints and then deformable bodies momemtum equation
- solveConstraints(timeStep);
-
- afterSolverCallbacks(timeStep);
-
- performDeformableCollisionDetection();
-
- applyRepulsionForce(timeStep);
-
- performGeometricCollisions(timeStep);
-
- integrateTransforms(timeStep);
-
- ///update vehicle simulation
- btMultiBodyDynamicsWorld::updateActions(timeStep);
-
- updateActivationState(timeStep);
- // End solver-wise simulation step
- // ///////////////////////////////
-}
-
-void btDeformableMultiBodyDynamicsWorld::performDeformableCollisionDetection()
-{
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- m_softBodies[i]->m_softSoftCollision = true;
- }
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- for (int j = i; j < m_softBodies.size(); ++j)
- {
- m_softBodies[i]->defaultCollisionHandler(m_softBodies[j]);
- }
- }
-
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- m_softBodies[i]->m_softSoftCollision = false;
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::updateActivationState(btScalar timeStep)
-{
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = m_softBodies[i];
- psb->updateDeactivation(timeStep);
- if (psb->wantsSleeping())
- {
- if (psb->getActivationState() == ACTIVE_TAG)
- psb->setActivationState(WANTS_DEACTIVATION);
- if (psb->getActivationState() == ISLAND_SLEEPING)
- {
- psb->setZeroVelocity();
- }
- }
- else
- {
- if (psb->getActivationState() != DISABLE_DEACTIVATION)
- psb->setActivationState(ACTIVE_TAG);
- }
- }
- btMultiBodyDynamicsWorld::updateActivationState(timeStep);
-}
-
-void btDeformableMultiBodyDynamicsWorld::applyRepulsionForce(btScalar timeStep)
-{
- BT_PROFILE("btDeformableMultiBodyDynamicsWorld::applyRepulsionForce");
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- psb->applyRepulsionForce(timeStep, true);
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::performGeometricCollisions(btScalar timeStep)
-{
- BT_PROFILE("btDeformableMultiBodyDynamicsWorld::performGeometricCollisions");
- // refit the BVH tree for CCD
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- m_softBodies[i]->updateFaceTree(true, false);
- m_softBodies[i]->updateNodeTree(true, false);
- for (int j = 0; j < m_softBodies[i]->m_faces.size(); ++j)
- {
- btSoftBody::Face& f = m_softBodies[i]->m_faces[j];
- f.m_n0 = (f.m_n[1]->m_x - f.m_n[0]->m_x).cross(f.m_n[2]->m_x - f.m_n[0]->m_x);
- }
- }
- }
-
- // clear contact points & update DBVT
- for (int r = 0; r < m_ccdIterations; ++r)
- {
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- // clear contact points in the previous iteration
- psb->m_faceNodeContacts.clear();
-
- // update m_q and normals for CCD calculation
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- psb->m_nodes[j].m_q = psb->m_nodes[j].m_x + timeStep * psb->m_nodes[j].m_v;
- }
- for (int j = 0; j < psb->m_faces.size(); ++j)
- {
- btSoftBody::Face& f = psb->m_faces[j];
- f.m_n1 = (f.m_n[1]->m_q - f.m_n[0]->m_q).cross(f.m_n[2]->m_q - f.m_n[0]->m_q);
- f.m_vn = (f.m_n[1]->m_v - f.m_n[0]->m_v).cross(f.m_n[2]->m_v - f.m_n[0]->m_v) * timeStep * timeStep;
- }
- }
- }
-
- // apply CCD to register new contact points
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- for (int j = i; j < m_softBodies.size(); ++j)
- {
- btSoftBody* psb1 = m_softBodies[i];
- btSoftBody* psb2 = m_softBodies[j];
- if (psb1->isActive() && psb2->isActive())
- {
- m_softBodies[i]->geometricCollisionHandler(m_softBodies[j]);
- }
- }
- }
-
- int penetration_count = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- penetration_count += psb->m_faceNodeContacts.size();
- }
- }
- if (penetration_count == 0)
- {
- break;
- }
-
- // apply inelastic impulse
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- psb->applyRepulsionForce(timeStep, false);
- }
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::softBodySelfCollision()
-{
- BT_PROFILE("btDeformableMultiBodyDynamicsWorld::softBodySelfCollision");
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = m_softBodies[i];
- if (psb->isActive())
- {
- psb->defaultCollisionHandler(psb);
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::positionCorrection(btScalar timeStep)
-{
- // correct the position of rigid bodies with temporary velocity generated from split impulse
- btContactSolverInfo infoGlobal;
- btVector3 zero(0, 0, 0);
- for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
- {
- btRigidBody* rb = m_nonStaticRigidBodies[i];
- //correct the position/orientation based on push/turn recovery
- btTransform newTransform;
- btVector3 pushVelocity = rb->getPushVelocity();
- btVector3 turnVelocity = rb->getTurnVelocity();
- if (pushVelocity[0] != 0.f || pushVelocity[1] != 0 || pushVelocity[2] != 0 || turnVelocity[0] != 0.f || turnVelocity[1] != 0 || turnVelocity[2] != 0)
- {
- btTransformUtil::integrateTransform(rb->getWorldTransform(), pushVelocity, turnVelocity * infoGlobal.m_splitImpulseTurnErp, timeStep, newTransform);
- rb->setWorldTransform(newTransform);
- rb->setPushVelocity(zero);
- rb->setTurnVelocity(zero);
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::integrateTransforms(btScalar timeStep)
-{
- BT_PROFILE("integrateTransforms");
- positionCorrection(timeStep);
- btMultiBodyDynamicsWorld::integrateTransforms(timeStep);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- btSoftBody::Node& node = psb->m_nodes[j];
- btScalar maxDisplacement = psb->getWorldInfo()->m_maxDisplacement;
- btScalar clampDeltaV = maxDisplacement / timeStep;
- for (int c = 0; c < 3; c++)
- {
- if (node.m_v[c] > clampDeltaV)
- {
- node.m_v[c] = clampDeltaV;
- }
- if (node.m_v[c] < -clampDeltaV)
- {
- node.m_v[c] = -clampDeltaV;
- }
- }
- node.m_x = node.m_x + timeStep * (node.m_v + node.m_splitv);
- node.m_q = node.m_x;
- node.m_vn = node.m_v;
- }
- // enforce anchor constraints
- for (int j = 0; j < psb->m_deformableAnchors.size(); ++j)
- {
- btSoftBody::DeformableNodeRigidAnchor& a = psb->m_deformableAnchors[j];
- btSoftBody::Node* n = a.m_node;
- n->m_x = a.m_cti.m_colObj->getWorldTransform() * a.m_local;
-
- // update multibody anchor info
- if (a.m_cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(a.m_cti.m_colObj);
- if (multibodyLinkCol)
- {
- btVector3 nrm;
- const btCollisionShape* shp = multibodyLinkCol->getCollisionShape();
- const btTransform& wtr = multibodyLinkCol->getWorldTransform();
- psb->m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(n->m_x),
- shp,
- nrm,
- 0);
- a.m_cti.m_normal = wtr.getBasis() * nrm;
- btVector3 normal = a.m_cti.m_normal;
- btVector3 t1 = generateUnitOrthogonalVector(normal);
- btVector3 t2 = btCross(normal, t1);
- btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
- findJacobian(multibodyLinkCol, jacobianData_normal, a.m_node->m_x, normal);
- findJacobian(multibodyLinkCol, jacobianData_t1, a.m_node->m_x, t1);
- findJacobian(multibodyLinkCol, jacobianData_t2, a.m_node->m_x, t2);
-
- btScalar* J_n = &jacobianData_normal.m_jacobians[0];
- btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
- btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
-
- btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
-
- btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
- t1.getX(), t1.getY(), t1.getZ(),
- t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- btMatrix3x3 local_impulse_matrix = (Diagonal(n->m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
- a.m_c0 = rot.transpose() * local_impulse_matrix * rot;
- a.jacobianData_normal = jacobianData_normal;
- a.jacobianData_t1 = jacobianData_t1;
- a.jacobianData_t2 = jacobianData_t2;
- a.t1 = t1;
- a.t2 = t2;
- }
- }
- }
- psb->interpolateRenderMesh();
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::solveConstraints(btScalar timeStep)
-{
- BT_PROFILE("btDeformableMultiBodyDynamicsWorld::solveConstraints");
- // save v_{n+1}^* velocity after explicit forces
- m_deformableBodySolver->backupVelocity();
-
- // set up constraints among multibodies and between multibodies and deformable bodies
- setupConstraints();
-
- // solve contact constraints
- solveContactConstraints();
-
- // set up the directions in which the velocity does not change in the momentum solve
- if (m_useProjection)
- m_deformableBodySolver->m_objective->m_projection.setProjection();
- else
- m_deformableBodySolver->m_objective->m_projection.setLagrangeMultiplier();
-
- // for explicit scheme, m_backupVelocity = v_{n+1}^*
- // for implicit scheme, m_backupVelocity = v_n
- // Here, set dv = v_{n+1} - v_n for nodes in contact
- m_deformableBodySolver->setupDeformableSolve(m_implicit);
-
- // At this point, dv should be golden for nodes in contact
- // proceed to solve deformable momentum equation
- m_deformableBodySolver->solveDeformableConstraints(timeStep);
-}
-
-void btDeformableMultiBodyDynamicsWorld::setupConstraints()
-{
- // set up constraints between multibody and deformable bodies
- m_deformableBodySolver->setConstraints(m_solverInfo);
-
- // set up constraints among multibodies
- {
- sortConstraints();
- // setup the solver callback
- btMultiBodyConstraint** sortedMultiBodyConstraints = m_sortedMultiBodyConstraints.size() ? &m_sortedMultiBodyConstraints[0] : 0;
- btTypedConstraint** constraintsPtr = getNumConstraints() ? &m_sortedConstraints[0] : 0;
- m_solverDeformableBodyIslandCallback->setup(&m_solverInfo, constraintsPtr, m_sortedConstraints.size(), sortedMultiBodyConstraints, m_sortedMultiBodyConstraints.size(), getDebugDrawer());
-
- // build islands
- m_islandManager->buildIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld());
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::sortConstraints()
-{
- m_sortedConstraints.resize(m_constraints.size());
- int i;
- for (i = 0; i < getNumConstraints(); i++)
- {
- m_sortedConstraints[i] = m_constraints[i];
- }
- m_sortedConstraints.quickSort(btSortConstraintOnIslandPredicate2());
-
- m_sortedMultiBodyConstraints.resize(m_multiBodyConstraints.size());
- for (i = 0; i < m_multiBodyConstraints.size(); i++)
- {
- m_sortedMultiBodyConstraints[i] = m_multiBodyConstraints[i];
- }
- m_sortedMultiBodyConstraints.quickSort(btSortMultiBodyConstraintOnIslandPredicate());
-}
-
-void btDeformableMultiBodyDynamicsWorld::solveContactConstraints()
-{
- // process constraints on each island
- m_islandManager->processIslands(getCollisionWorld()->getDispatcher(), getCollisionWorld(), m_solverDeformableBodyIslandCallback);
-
- // process deferred
- m_solverDeformableBodyIslandCallback->processConstraints();
- m_constraintSolver->allSolved(m_solverInfo, m_debugDrawer);
-
- // write joint feedback
- {
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- //useless? they get resized in stepVelocities once again (AND DIFFERENTLY)
- m_scratch_r.resize(bod->getNumLinks() + 1); //multidof? ("Y"s use it and it is used to store qdd)
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
-
- if (bod->internalNeedsJointFeedback())
- {
- if (!bod->isUsingRK4Integration())
- {
- if (bod->internalNeedsJointFeedback())
- {
- bool isConstraintPass = true;
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep, m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- }
- }
- }
- }
- }
-
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
- bod->processDeltaVeeMultiDof2();
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
-{
- m_softBodies.push_back(body);
-
- // Set the soft body solver that will deal with this body
- // to be the world's solver
- body->setSoftBodySolver(m_deformableBodySolver);
-
- btCollisionWorld::addCollisionObject(body,
- collisionFilterGroup,
- collisionFilterMask);
-}
-
-void btDeformableMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- BT_PROFILE("predictUnconstraintMotion");
- btMultiBodyDynamicsWorld::predictUnconstraintMotion(timeStep);
- m_deformableBodySolver->predictMotion(timeStep);
-}
-
-void btDeformableMultiBodyDynamicsWorld::reinitialize(btScalar timeStep)
-{
- m_internalTime += timeStep;
- m_deformableBodySolver->setImplicit(m_implicit);
- m_deformableBodySolver->setLineSearch(m_lineSearch);
- m_deformableBodySolver->reinitialize(m_softBodies, timeStep);
- btDispatcherInfo& dispatchInfo = btMultiBodyDynamicsWorld::getDispatchInfo();
- dispatchInfo.m_timeStep = timeStep;
- dispatchInfo.m_stepCount = 0;
- dispatchInfo.m_debugDraw = btMultiBodyDynamicsWorld::getDebugDrawer();
- btMultiBodyDynamicsWorld::getSolverInfo().m_timeStep = timeStep;
- if (m_useProjection)
- {
- m_deformableBodySolver->m_useProjection = true;
- m_deformableBodySolver->m_objective->m_projection.m_useStrainLimiting = true;
- m_deformableBodySolver->m_objective->m_preconditioner = m_deformableBodySolver->m_objective->m_massPreconditioner;
- }
- else
- {
- m_deformableBodySolver->m_useProjection = false;
- m_deformableBodySolver->m_objective->m_projection.m_useStrainLimiting = false;
- m_deformableBodySolver->m_objective->m_preconditioner = m_deformableBodySolver->m_objective->m_KKTPreconditioner;
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::debugDrawWorld()
-{
- btMultiBodyDynamicsWorld::debugDrawWorld();
-
- for (int i = 0; i < getSoftBodyArray().size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)getSoftBodyArray()[i];
- {
- btSoftBodyHelpers::DrawFrame(psb, getDebugDrawer());
- btSoftBodyHelpers::Draw(psb, getDebugDrawer(), getDrawFlags());
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::applyRigidBodyGravity(btScalar timeStep)
-{
- // Gravity is applied in stepSimulation and then cleared here and then applied here and then cleared here again
- // so that 1) gravity is applied to velocity before constraint solve and 2) gravity is applied in each substep
- // when there are multiple substeps
- btMultiBodyDynamicsWorld::applyGravity();
- // integrate rigid body gravity
- for (int i = 0; i < m_nonStaticRigidBodies.size(); ++i)
- {
- btRigidBody* rb = m_nonStaticRigidBodies[i];
- rb->integrateVelocities(timeStep);
- }
-
- // integrate multibody gravity
- {
- forwardKinematics();
- clearMultiBodyConstraintForces();
- {
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- m_scratch_r.resize(bod->getNumLinks() + 1);
- m_scratch_v.resize(bod->getNumLinks() + 1);
- m_scratch_m.resize(bod->getNumLinks() + 1);
- bool isConstraintPass = false;
- {
- if (!bod->isUsingRK4Integration())
- {
- bod->computeAccelerationsArticulatedBodyAlgorithmMultiDof(m_solverInfo.m_timeStep,
- m_scratch_r, m_scratch_v, m_scratch_m, isConstraintPass,
- getSolverInfo().m_jointFeedbackInWorldSpace,
- getSolverInfo().m_jointFeedbackInJointFrame);
- }
- else
- {
- btAssert(" RK4Integration is not supported");
- }
- }
- }
- }
- }
- }
- clearGravity();
-}
-
-void btDeformableMultiBodyDynamicsWorld::clearGravity()
-{
- BT_PROFILE("btMultiBody clearGravity");
- // clear rigid body gravity
- for (int i = 0; i < m_nonStaticRigidBodies.size(); i++)
- {
- btRigidBody* body = m_nonStaticRigidBodies[i];
- if (body->isActive())
- {
- body->clearGravity();
- }
- }
- // clear multibody gravity
- for (int i = 0; i < this->m_multiBodies.size(); i++)
- {
- btMultiBody* bod = m_multiBodies[i];
-
- bool isSleeping = false;
-
- if (bod->getBaseCollider() && bod->getBaseCollider()->getActivationState() == ISLAND_SLEEPING)
- {
- isSleeping = true;
- }
- for (int b = 0; b < bod->getNumLinks(); b++)
- {
- if (bod->getLink(b).m_collider && bod->getLink(b).m_collider->getActivationState() == ISLAND_SLEEPING)
- isSleeping = true;
- }
-
- if (!isSleeping)
- {
- bod->addBaseForce(-m_gravity * bod->getBaseMass());
-
- for (int j = 0; j < bod->getNumLinks(); ++j)
- {
- bod->addLinkForce(j, -m_gravity * bod->getLinkMass(j));
- }
- }
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::beforeSolverCallbacks(btScalar timeStep)
-{
- if (0 != m_internalTickCallback)
- {
- (*m_internalTickCallback)(this, timeStep);
- }
-
- if (0 != m_solverCallback)
- {
- (*m_solverCallback)(m_internalTime, this);
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::afterSolverCallbacks(btScalar timeStep)
-{
- if (0 != m_solverCallback)
- {
- (*m_solverCallback)(m_internalTime, this);
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::addForce(btSoftBody* psb, btDeformableLagrangianForce* force)
-{
- btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
- bool added = false;
- for (int i = 0; i < forces.size(); ++i)
- {
- if (forces[i]->getForceType() == force->getForceType())
- {
- forces[i]->addSoftBody(psb);
- added = true;
- break;
- }
- }
- if (!added)
- {
- force->addSoftBody(psb);
- force->setIndices(m_deformableBodySolver->m_objective->getIndices());
- forces.push_back(force);
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::removeForce(btSoftBody* psb, btDeformableLagrangianForce* force)
-{
- btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
- int removed_index = -1;
- for (int i = 0; i < forces.size(); ++i)
- {
- if (forces[i]->getForceType() == force->getForceType())
- {
- forces[i]->removeSoftBody(psb);
- if (forces[i]->m_softBodies.size() == 0)
- removed_index = i;
- break;
- }
- }
- if (removed_index >= 0)
- forces.removeAtIndex(removed_index);
-}
-
-void btDeformableMultiBodyDynamicsWorld::removeSoftBodyForce(btSoftBody* psb)
-{
- btAlignedObjectArray<btDeformableLagrangianForce*>& forces = m_deformableBodySolver->m_objective->m_lf;
- for (int i = 0; i < forces.size(); ++i)
- {
- forces[i]->removeSoftBody(psb);
- }
-}
-
-void btDeformableMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
-{
- removeSoftBodyForce(body);
- m_softBodies.remove(body);
- btCollisionWorld::removeCollisionObject(body);
- // force a reinitialize so that node indices get updated.
- m_deformableBodySolver->reinitialize(m_softBodies, btScalar(-1));
-}
-
-void btDeformableMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- btSoftBody* body = btSoftBody::upcast(collisionObject);
- if (body)
- removeSoftBody(body);
- else
- btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
-}
-
-int btDeformableMultiBodyDynamicsWorld::stepSimulation(btScalar timeStep, int maxSubSteps, btScalar fixedTimeStep)
-{
- startProfiling(timeStep);
-
- int numSimulationSubSteps = 0;
-
- if (maxSubSteps)
- {
- //fixed timestep with interpolation
- m_fixedTimeStep = fixedTimeStep;
- m_localTime += timeStep;
- if (m_localTime >= fixedTimeStep)
- {
- numSimulationSubSteps = int(m_localTime / fixedTimeStep);
- m_localTime -= numSimulationSubSteps * fixedTimeStep;
- }
- }
- else
- {
- //variable timestep
- fixedTimeStep = timeStep;
- m_localTime = m_latencyMotionStateInterpolation ? 0 : timeStep;
- m_fixedTimeStep = 0;
- if (btFuzzyZero(timeStep))
- {
- numSimulationSubSteps = 0;
- maxSubSteps = 0;
- }
- else
- {
- numSimulationSubSteps = 1;
- maxSubSteps = 1;
- }
- }
-
- //process some debugging flags
- if (getDebugDrawer())
- {
- btIDebugDraw* debugDrawer = getDebugDrawer();
- gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
- }
- if (numSimulationSubSteps)
- {
- //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
- int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps) ? maxSubSteps : numSimulationSubSteps;
-
- saveKinematicState(fixedTimeStep * clampedSimulationSteps);
-
- for (int i = 0; i < clampedSimulationSteps; i++)
- {
- internalSingleStepSimulation(fixedTimeStep);
- synchronizeMotionStates();
- }
- }
- else
- {
- synchronizeMotionStates();
- }
-
- clearForces();
-
-#ifndef BT_NO_PROFILE
- CProfileManager::Increment_Frame_Counter();
-#endif //BT_NO_PROFILE
-
- return numSimulationSubSteps;
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
deleted file mode 100644
index 4b7069aac7..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableMultiBodyDynamicsWorld.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
-#define BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
-
-#include "btSoftMultiBodyDynamicsWorld.h"
-#include "btDeformableLagrangianForce.h"
-#include "btDeformableMassSpringForce.h"
-#include "btDeformableBodySolver.h"
-#include "btDeformableMultiBodyConstraintSolver.h"
-#include "btSoftBodyHelpers.h"
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
-#include <functional>
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
-
-class btDeformableBodySolver;
-class btDeformableLagrangianForce;
-struct MultiBodyInplaceSolverIslandCallback;
-struct DeformableBodyInplaceSolverIslandCallback;
-class btDeformableMultiBodyConstraintSolver;
-
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
-
-class btDeformableMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
-{
- typedef btAlignedObjectArray<btVector3> TVStack;
- ///Solver classes that encapsulate multiple deformable bodies for solving
- btDeformableBodySolver* m_deformableBodySolver;
- btSoftBodyArray m_softBodies;
- int m_drawFlags;
- bool m_drawNodeTree;
- bool m_drawFaceTree;
- bool m_drawClusterTree;
- btSoftBodyWorldInfo m_sbi;
- btScalar m_internalTime;
- int m_ccdIterations;
- bool m_implicit;
- bool m_lineSearch;
- bool m_useProjection;
- DeformableBodyInplaceSolverIslandCallback* m_solverDeformableBodyIslandCallback;
-
- typedef void (*btSolverCallback)(btScalar time, btDeformableMultiBodyDynamicsWorld* world);
- btSolverCallback m_solverCallback;
-
-protected:
- virtual void internalSingleStepSimulation(btScalar timeStep);
-
- virtual void integrateTransforms(btScalar timeStep);
-
- void positionCorrection(btScalar timeStep);
-
- void solveConstraints(btScalar timeStep);
-
- void updateActivationState(btScalar timeStep);
-
- void clearGravity();
-
-public:
- btDeformableMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btDeformableMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btDeformableBodySolver* deformableBodySolver = 0);
-
- virtual int stepSimulation(btScalar timeStep, int maxSubSteps = 1, btScalar fixedTimeStep = btScalar(1.) / btScalar(60.));
-
- virtual void debugDrawWorld();
-
- void setSolverCallback(btSolverCallback cb)
- {
- m_solverCallback = cb;
- }
-
- virtual ~btDeformableMultiBodyDynamicsWorld();
-
- virtual btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld()
- {
- return (btMultiBodyDynamicsWorld*)(this);
- }
-
- virtual const btMultiBodyDynamicsWorld* getMultiBodyDynamicsWorld() const
- {
- return (const btMultiBodyDynamicsWorld*)(this);
- }
-
- virtual btDynamicsWorldType getWorldType() const
- {
- return BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD;
- }
-
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- virtual void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
-
- btSoftBodyArray& getSoftBodyArray()
- {
- return m_softBodies;
- }
-
- const btSoftBodyArray& getSoftBodyArray() const
- {
- return m_softBodies;
- }
-
- btSoftBodyWorldInfo& getWorldInfo()
- {
- return m_sbi;
- }
-
- const btSoftBodyWorldInfo& getWorldInfo() const
- {
- return m_sbi;
- }
-
- void reinitialize(btScalar timeStep);
-
- void applyRigidBodyGravity(btScalar timeStep);
-
- void beforeSolverCallbacks(btScalar timeStep);
-
- void afterSolverCallbacks(btScalar timeStep);
-
- void addForce(btSoftBody* psb, btDeformableLagrangianForce* force);
-
- void removeForce(btSoftBody* psb, btDeformableLagrangianForce* force);
-
- void removeSoftBodyForce(btSoftBody* psb);
-
- void removeSoftBody(btSoftBody* body);
-
- void removeCollisionObject(btCollisionObject* collisionObject);
-
- int getDrawFlags() const { return (m_drawFlags); }
- void setDrawFlags(int f) { m_drawFlags = f; }
-
- void setupConstraints();
-
- void performDeformableCollisionDetection();
-
- void solveMultiBodyConstraints();
-
- void solveContactConstraints();
-
- void sortConstraints();
-
- void softBodySelfCollision();
-
- void setImplicit(bool implicit)
- {
- m_implicit = implicit;
- }
-
- void setLineSearch(bool lineSearch)
- {
- m_lineSearch = lineSearch;
- }
-
- void setUseProjection(bool useProjection)
- {
- m_useProjection = useProjection;
- }
-
- void applyRepulsionForce(btScalar timeStep);
-
- void performGeometricCollisions(btScalar timeStep);
-
- struct btDeformableSingleRayCallback : public btBroadphaseRayCallback
- {
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btDeformableMultiBodyDynamicsWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btDeformableSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btDeformableMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- m_rayFromTrans.setIdentity();
- m_rayFromTrans.setOrigin(m_rayFromWorld);
- m_rayToTrans.setIdentity();
- m_rayToTrans.setOrigin(m_rayToWorld);
-
- btVector3 rayDir = (rayToWorld - rayFromWorld);
-
- rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/1e30
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
-
- m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further ray tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
-
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
-#if 0
-#ifdef RECALCULATE_AABB
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
-#else
- //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
- const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
- const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
-#endif
-#endif
- //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
- //culling already done by broadphase
- //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
- {
- m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
- }
- }
- return true;
- }
- };
-
- void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
- {
- BT_PROFILE("rayTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- btDeformableSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
-
-#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
-#else
- for (int i = 0; i < this->getNumCollisionObjects(); i++)
- {
- rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
- }
-
- void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback) const
- {
- if (collisionShape->isSoftBody())
- {
- btSoftBody* softBody = btSoftBody::upcast(collisionObject);
- if (softBody)
- {
- btSoftBody::sRayCast softResult;
- if (softBody->rayFaceTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
- {
- if (softResult.fraction <= resultCallback.m_closestHitFraction)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = 0;
- shapeInfo.m_triangleIndex = softResult.index;
- // get the normal
- btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
- btVector3 normal = -rayDir;
- normal.normalize();
- {
- normal = softBody->m_faces[softResult.index].m_normal;
- if (normal.dot(rayDir) > 0)
- {
- // normal always point toward origin of the ray
- normal = -normal;
- }
- }
-
- btCollisionWorld::LocalRayResult rayResult(collisionObject,
- &shapeInfo,
- normal,
- softResult.fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(rayResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
- }
- }
-};
-
-#endif //BT_DEFORMABLE_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h b/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
deleted file mode 100644
index 60798c5bcd..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btDeformableNeoHookeanForce.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
-Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2019 Google Inc. http://bulletphysics.org
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_NEOHOOKEAN_H
-#define BT_NEOHOOKEAN_H
-
-#include "btDeformableLagrangianForce.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btImplicitQRSVD.h"
-// This energy is as described in https://graphics.pixar.com/library/StableElasticity/paper.pdf
-class btDeformableNeoHookeanForce : public btDeformableLagrangianForce
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- btScalar m_mu, m_lambda; // Lame Parameters
- btScalar m_E, m_nu; // Young's modulus and Poisson ratio
- btScalar m_mu_damp, m_lambda_damp;
- btDeformableNeoHookeanForce() : m_mu(1), m_lambda(1)
- {
- btScalar damping = 0.05;
- m_mu_damp = damping * m_mu;
- m_lambda_damp = damping * m_lambda;
- updateYoungsModulusAndPoissonRatio();
- }
-
- btDeformableNeoHookeanForce(btScalar mu, btScalar lambda, btScalar damping = 0.05) : m_mu(mu), m_lambda(lambda)
- {
- m_mu_damp = damping * m_mu;
- m_lambda_damp = damping * m_lambda;
- updateYoungsModulusAndPoissonRatio();
- }
-
- void updateYoungsModulusAndPoissonRatio()
- {
- // conversion from Lame Parameters to Young's modulus and Poisson ratio
- // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
- m_E = m_mu * (3 * m_lambda + 2 * m_mu) / (m_lambda + m_mu);
- m_nu = m_lambda * 0.5 / (m_mu + m_lambda);
- }
-
- void updateLameParameters()
- {
- // conversion from Young's modulus and Poisson ratio to Lame Parameters
- // https://en.wikipedia.org/wiki/Lam%C3%A9_parameters
- m_mu = m_E * 0.5 / (1 + m_nu);
- m_lambda = m_E * m_nu / ((1 + m_nu) * (1 - 2 * m_nu));
- }
-
- void setYoungsModulus(btScalar E)
- {
- m_E = E;
- updateLameParameters();
- }
-
- void setPoissonRatio(btScalar nu)
- {
- m_nu = nu;
- updateLameParameters();
- }
-
- void setDamping(btScalar damping)
- {
- m_mu_damp = damping * m_mu;
- m_lambda_damp = damping * m_lambda;
- }
-
- void setLameParameters(btScalar mu, btScalar lambda)
- {
- m_mu = mu;
- m_lambda = lambda;
- updateYoungsModulusAndPoissonRatio();
- }
-
- virtual void addScaledForces(btScalar scale, TVStack& force)
- {
- addScaledDampingForce(scale, force);
- addScaledElasticForce(scale, force);
- }
-
- virtual void addScaledExplicitForce(btScalar scale, TVStack& force)
- {
- addScaledElasticForce(scale, force);
- }
-
- // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual void addScaledDampingForce(btScalar scale, TVStack& force)
- {
- if (m_mu_damp == 0 && m_lambda_damp == 0)
- return;
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = DsFromVelocity(node0, node1, node2, node3) * tetra.m_Dm_inverse;
- btMatrix3x3 I;
- I.setIdentity();
- btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0] + dF[1][1] + dF[2][2]) * m_lambda_damp;
- // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
- btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose() * grad_N_hat_1st_col);
- btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
-
- // damping force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- force[id0] -= scale1 * df_on_node0;
- force[id1] -= scale1 * df_on_node123.getColumn(0);
- force[id2] -= scale1 * df_on_node123.getColumn(1);
- force[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- }
- }
-
- virtual double totalElasticEnergy(btScalar dt)
- {
- double energy = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetraScratches.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::TetraScratch& s = psb->m_tetraScratches[j];
- energy += tetra.m_element_measure * elasticEnergyDensity(s);
- }
- }
- return energy;
- }
-
- // The damping energy is formulated as in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual double totalDampingEnergy(btScalar dt)
- {
- double energy = 0;
- int sz = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- sz = btMax(sz, psb->m_nodes[j].index);
- }
- }
- TVStack dampingForce;
- dampingForce.resize(sz + 1);
- for (int i = 0; i < dampingForce.size(); ++i)
- dampingForce[i].setZero();
- addScaledDampingForce(0.5, dampingForce);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- energy -= dampingForce[node.index].dot(node.m_v) / dt;
- }
- }
- return energy;
- }
-
- double elasticEnergyDensity(const btSoftBody::TetraScratch& s)
- {
- double density = 0;
- density += m_mu * 0.5 * (s.m_trace - 3.);
- density += m_lambda * 0.5 * (s.m_J - 1. - 0.75 * m_mu / m_lambda) * (s.m_J - 1. - 0.75 * m_mu / m_lambda);
- density -= m_mu * 0.5 * log(s.m_trace + 1);
- return density;
- }
-
- virtual void addScaledElasticForce(btScalar scale, TVStack& force)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= force.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- btScalar max_p = psb->m_cfg.m_maxStress;
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btMatrix3x3 P;
- firstPiola(psb->m_tetraScratches[j], P);
-#ifdef USE_SVD
- if (max_p > 0)
- {
- // since we want to clamp the principal stress to max_p, we only need to
- // calculate SVD when sigma_0^2 + sigma_1^2 + sigma_2^2 > max_p * max_p
- btScalar trPTP = (P[0].length2() + P[1].length2() + P[2].length2());
- if (trPTP > max_p * max_p)
- {
- btMatrix3x3 U, V;
- btVector3 sigma;
- singularValueDecomposition(P, U, sigma, V);
- sigma[0] = btMin(sigma[0], max_p);
- sigma[1] = btMin(sigma[1], max_p);
- sigma[2] = btMin(sigma[2], max_p);
- sigma[0] = btMax(sigma[0], -max_p);
- sigma[1] = btMax(sigma[1], -max_p);
- sigma[2] = btMax(sigma[2], -max_p);
- btMatrix3x3 Sigma;
- Sigma.setIdentity();
- Sigma[0][0] = sigma[0];
- Sigma[1][1] = sigma[1];
- Sigma[2][2] = sigma[2];
- P = U * Sigma * V.transpose();
- }
- }
-#endif
- // btVector3 force_on_node0 = P * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
- btMatrix3x3 force_on_node123 = P * tetra.m_Dm_inverse.transpose();
- btVector3 force_on_node0 = force_on_node123 * grad_N_hat_1st_col;
-
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
-
- // elastic force
- btScalar scale1 = scale * tetra.m_element_measure;
- force[id0] -= scale1 * force_on_node0;
- force[id1] -= scale1 * force_on_node123.getColumn(0);
- force[id2] -= scale1 * force_on_node123.getColumn(1);
- force[id3] -= scale1 * force_on_node123.getColumn(2);
- }
- }
- }
-
- // The damping matrix is calculated using the time n state as described in https://www.math.ucla.edu/~jteran/papers/GSSJT15.pdf to allow line search
- virtual void addScaledDampingForceDifferential(btScalar scale, const TVStack& dv, TVStack& df)
- {
- if (m_mu_damp == 0 && m_lambda_damp == 0)
- return;
- int numNodes = getNumNodes();
- btAssert(numNodes <= df.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = Ds(id0, id1, id2, id3, dv) * tetra.m_Dm_inverse;
- btMatrix3x3 I;
- I.setIdentity();
- btMatrix3x3 dP = (dF + dF.transpose()) * m_mu_damp + I * (dF[0][0] + dF[1][1] + dF[2][2]) * m_lambda_damp;
- // firstPiolaDampingDifferential(psb->m_tetraScratchesTn[j], dF, dP);
- // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
- btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
- btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
-
- // damping force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- df[id0] -= scale1 * df_on_node0;
- df[id1] -= scale1 * df_on_node123.getColumn(0);
- df[id2] -= scale1 * df_on_node123.getColumn(1);
- df[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- }
- }
-
- virtual void buildDampingForceDifferentialDiagonal(btScalar scale, TVStack& diagA) {}
-
- virtual void addScaledElasticForceDifferential(btScalar scale, const TVStack& dx, TVStack& df)
- {
- int numNodes = getNumNodes();
- btAssert(numNodes <= df.size());
- btVector3 grad_N_hat_1st_col = btVector3(-1, -1, -1);
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- if (!psb->isActive())
- {
- continue;
- }
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- btSoftBody::Tetra& tetra = psb->m_tetras[j];
- btSoftBody::Node* node0 = tetra.m_n[0];
- btSoftBody::Node* node1 = tetra.m_n[1];
- btSoftBody::Node* node2 = tetra.m_n[2];
- btSoftBody::Node* node3 = tetra.m_n[3];
- size_t id0 = node0->index;
- size_t id1 = node1->index;
- size_t id2 = node2->index;
- size_t id3 = node3->index;
- btMatrix3x3 dF = Ds(id0, id1, id2, id3, dx) * tetra.m_Dm_inverse;
- btMatrix3x3 dP;
- firstPiolaDifferential(psb->m_tetraScratches[j], dF, dP);
- // btVector3 df_on_node0 = dP * (tetra.m_Dm_inverse.transpose()*grad_N_hat_1st_col);
- btMatrix3x3 df_on_node123 = dP * tetra.m_Dm_inverse.transpose();
- btVector3 df_on_node0 = df_on_node123 * grad_N_hat_1st_col;
-
- // elastic force differential
- btScalar scale1 = scale * tetra.m_element_measure;
- df[id0] -= scale1 * df_on_node0;
- df[id1] -= scale1 * df_on_node123.getColumn(0);
- df[id2] -= scale1 * df_on_node123.getColumn(1);
- df[id3] -= scale1 * df_on_node123.getColumn(2);
- }
- }
- }
-
- void firstPiola(const btSoftBody::TetraScratch& s, btMatrix3x3& P)
- {
- btScalar c1 = (m_mu * (1. - 1. / (s.m_trace + 1.)));
- btScalar c2 = (m_lambda * (s.m_J - 1.) - 0.75 * m_mu);
- P = s.m_F * c1 + s.m_cofF * c2;
- }
-
- // Let P be the first piola stress.
- // This function calculates the dP = dP/dF * dF
- void firstPiolaDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
- {
- btScalar c1 = m_mu * (1. - 1. / (s.m_trace + 1.));
- btScalar c2 = (2. * m_mu) * DotProduct(s.m_F, dF) * (1. / ((1. + s.m_trace) * (1. + s.m_trace)));
- btScalar c3 = (m_lambda * DotProduct(s.m_cofF, dF));
- dP = dF * c1 + s.m_F * c2;
- addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda * (s.m_J - 1.) - 0.75 * m_mu, dP);
- dP += s.m_cofF * c3;
- }
-
- // Let Q be the damping stress.
- // This function calculates the dP = dQ/dF * dF
- void firstPiolaDampingDifferential(const btSoftBody::TetraScratch& s, const btMatrix3x3& dF, btMatrix3x3& dP)
- {
- btScalar c1 = (m_mu_damp * (1. - 1. / (s.m_trace + 1.)));
- btScalar c2 = ((2. * m_mu_damp) * DotProduct(s.m_F, dF) * (1. / ((1. + s.m_trace) * (1. + s.m_trace))));
- btScalar c3 = (m_lambda_damp * DotProduct(s.m_cofF, dF));
- dP = dF * c1 + s.m_F * c2;
- addScaledCofactorMatrixDifferential(s.m_F, dF, m_lambda_damp * (s.m_J - 1.) - 0.75 * m_mu_damp, dP);
- dP += s.m_cofF * c3;
- }
-
- btScalar DotProduct(const btMatrix3x3& A, const btMatrix3x3& B)
- {
- btScalar ans = 0;
- for (int i = 0; i < 3; ++i)
- {
- ans += A[i].dot(B[i]);
- }
- return ans;
- }
-
- // Let C(A) be the cofactor of the matrix A
- // Let H = the derivative of C(A) with respect to A evaluated at F = A
- // This function calculates H*dF
- void addScaledCofactorMatrixDifferential(const btMatrix3x3& F, const btMatrix3x3& dF, btScalar scale, btMatrix3x3& M)
- {
- M[0][0] += scale * (dF[1][1] * F[2][2] + F[1][1] * dF[2][2] - dF[2][1] * F[1][2] - F[2][1] * dF[1][2]);
- M[1][0] += scale * (dF[2][1] * F[0][2] + F[2][1] * dF[0][2] - dF[0][1] * F[2][2] - F[0][1] * dF[2][2]);
- M[2][0] += scale * (dF[0][1] * F[1][2] + F[0][1] * dF[1][2] - dF[1][1] * F[0][2] - F[1][1] * dF[0][2]);
- M[0][1] += scale * (dF[2][0] * F[1][2] + F[2][0] * dF[1][2] - dF[1][0] * F[2][2] - F[1][0] * dF[2][2]);
- M[1][1] += scale * (dF[0][0] * F[2][2] + F[0][0] * dF[2][2] - dF[2][0] * F[0][2] - F[2][0] * dF[0][2]);
- M[2][1] += scale * (dF[1][0] * F[0][2] + F[1][0] * dF[0][2] - dF[0][0] * F[1][2] - F[0][0] * dF[1][2]);
- M[0][2] += scale * (dF[1][0] * F[2][1] + F[1][0] * dF[2][1] - dF[2][0] * F[1][1] - F[2][0] * dF[1][1]);
- M[1][2] += scale * (dF[2][0] * F[0][1] + F[2][0] * dF[0][1] - dF[0][0] * F[2][1] - F[0][0] * dF[2][1]);
- M[2][2] += scale * (dF[0][0] * F[1][1] + F[0][0] * dF[1][1] - dF[1][0] * F[0][1] - F[1][0] * dF[0][1]);
- }
-
- virtual btDeformableLagrangianForceType getForceType()
- {
- return BT_NEOHOOKEAN_FORCE;
- }
-};
-#endif /* BT_NEOHOOKEAN_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btKrylovSolver.h b/thirdparty/bullet/BulletSoftBody/btKrylovSolver.h
deleted file mode 100644
index 59126b47ae..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btKrylovSolver.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_KRYLOV_SOLVER_H
-#define BT_KRYLOV_SOLVER_H
-#include <iostream>
-#include <cmath>
-#include <limits>
-#include <LinearMath/btAlignedObjectArray.h>
-#include <LinearMath/btVector3.h>
-#include <LinearMath/btScalar.h>
-#include "LinearMath/btQuickprof.h"
-
-template <class MatrixX>
-class btKrylovSolver
-{
- typedef btAlignedObjectArray<btVector3> TVStack;
-
-public:
- int m_maxIterations;
- btScalar m_tolerance;
- btKrylovSolver(int maxIterations, btScalar tolerance)
- : m_maxIterations(maxIterations), m_tolerance(tolerance)
- {
- }
-
- virtual ~btKrylovSolver() {}
-
- virtual int solve(MatrixX& A, TVStack& x, const TVStack& b, bool verbose = false) = 0;
-
- virtual void reinitialize(const TVStack& b) = 0;
-
- virtual SIMD_FORCE_INLINE TVStack sub(const TVStack& a, const TVStack& b)
- {
- // c = a-b
- btAssert(a.size() == b.size());
- TVStack c;
- c.resize(a.size());
- for (int i = 0; i < a.size(); ++i)
- {
- c[i] = a[i] - b[i];
- }
- return c;
- }
-
- virtual SIMD_FORCE_INLINE btScalar squaredNorm(const TVStack& a)
- {
- return dot(a, a);
- }
-
- virtual SIMD_FORCE_INLINE btScalar norm(const TVStack& a)
- {
- btScalar ret = 0;
- for (int i = 0; i < a.size(); ++i)
- {
- for (int d = 0; d < 3; ++d)
- {
- ret = btMax(ret, btFabs(a[i][d]));
- }
- }
- return ret;
- }
-
- virtual SIMD_FORCE_INLINE btScalar dot(const TVStack& a, const TVStack& b)
- {
- btScalar ans(0);
- for (int i = 0; i < a.size(); ++i)
- ans += a[i].dot(b[i]);
- return ans;
- }
-
- virtual SIMD_FORCE_INLINE void multAndAddTo(btScalar s, const TVStack& a, TVStack& result)
- {
- // result += s*a
- btAssert(a.size() == result.size());
- for (int i = 0; i < a.size(); ++i)
- result[i] += s * a[i];
- }
-
- virtual SIMD_FORCE_INLINE TVStack multAndAdd(btScalar s, const TVStack& a, const TVStack& b)
- {
- // result = a*s + b
- TVStack result;
- result.resize(a.size());
- for (int i = 0; i < a.size(); ++i)
- result[i] = s * a[i] + b[i];
- return result;
- }
-
- virtual SIMD_FORCE_INLINE void setTolerance(btScalar tolerance)
- {
- m_tolerance = tolerance;
- }
-};
-#endif /* BT_KRYLOV_SOLVER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btPreconditioner.h b/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
deleted file mode 100644
index 21c1106a42..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btPreconditioner.h
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- Written by Xuchen Han <xuchenhan2015@u.northwestern.edu>
-
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
-
-#ifndef BT_PRECONDITIONER_H
-#define BT_PRECONDITIONER_H
-
-class Preconditioner
-{
-public:
- typedef btAlignedObjectArray<btVector3> TVStack;
- virtual void operator()(const TVStack& x, TVStack& b) = 0;
- virtual void reinitialize(bool nodeUpdated) = 0;
- virtual ~Preconditioner() {}
-};
-
-class DefaultPreconditioner : public Preconditioner
-{
-public:
- virtual void operator()(const TVStack& x, TVStack& b)
- {
- btAssert(b.size() == x.size());
- for (int i = 0; i < b.size(); ++i)
- b[i] = x[i];
- }
- virtual void reinitialize(bool nodeUpdated)
- {
- }
-
- virtual ~DefaultPreconditioner() {}
-};
-
-class MassPreconditioner : public Preconditioner
-{
- btAlignedObjectArray<btScalar> m_inv_mass;
- const btAlignedObjectArray<btSoftBody*>& m_softBodies;
-
-public:
- MassPreconditioner(const btAlignedObjectArray<btSoftBody*>& softBodies)
- : m_softBodies(softBodies)
- {
- }
-
- virtual void reinitialize(bool nodeUpdated)
- {
- if (nodeUpdated)
- {
- m_inv_mass.clear();
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- m_inv_mass.push_back(psb->m_nodes[j].m_im);
- }
- }
- }
-
- virtual void operator()(const TVStack& x, TVStack& b)
- {
- btAssert(b.size() == x.size());
- btAssert(m_inv_mass.size() <= x.size());
- for (int i = 0; i < m_inv_mass.size(); ++i)
- {
- b[i] = x[i] * m_inv_mass[i];
- }
- for (int i = m_inv_mass.size(); i < b.size(); ++i)
- {
- b[i] = x[i];
- }
- }
-};
-
-class KKTPreconditioner : public Preconditioner
-{
- const btAlignedObjectArray<btSoftBody*>& m_softBodies;
- const btDeformableContactProjection& m_projections;
- const btAlignedObjectArray<btDeformableLagrangianForce*>& m_lf;
- TVStack m_inv_A, m_inv_S;
- const btScalar& m_dt;
- const bool& m_implicit;
-
-public:
- KKTPreconditioner(const btAlignedObjectArray<btSoftBody*>& softBodies, const btDeformableContactProjection& projections, const btAlignedObjectArray<btDeformableLagrangianForce*>& lf, const btScalar& dt, const bool& implicit)
- : m_softBodies(softBodies), m_projections(projections), m_lf(lf), m_dt(dt), m_implicit(implicit)
- {
- }
-
- virtual void reinitialize(bool nodeUpdated)
- {
- if (nodeUpdated)
- {
- int num_nodes = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- num_nodes += psb->m_nodes.size();
- }
- m_inv_A.resize(num_nodes);
- }
- buildDiagonalA(m_inv_A);
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- // printf("A[%d] = %f, %f, %f \n", i, m_inv_A[i][0], m_inv_A[i][1], m_inv_A[i][2]);
- for (int d = 0; d < 3; ++d)
- {
- m_inv_A[i][d] = (m_inv_A[i][d] == 0) ? 0.0 : 1.0 / m_inv_A[i][d];
- }
- }
- m_inv_S.resize(m_projections.m_lagrangeMultipliers.size());
- // printf("S.size() = %d \n", m_inv_S.size());
- buildDiagonalS(m_inv_A, m_inv_S);
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- // printf("S[%d] = %f, %f, %f \n", i, m_inv_S[i][0], m_inv_S[i][1], m_inv_S[i][2]);
- for (int d = 0; d < 3; ++d)
- {
- m_inv_S[i][d] = (m_inv_S[i][d] == 0) ? 0.0 : 1.0 / m_inv_S[i][d];
- }
- }
- }
-
- void buildDiagonalA(TVStack& diagA) const
- {
- size_t counter = 0;
- for (int i = 0; i < m_softBodies.size(); ++i)
- {
- btSoftBody* psb = m_softBodies[i];
- for (int j = 0; j < psb->m_nodes.size(); ++j)
- {
- const btSoftBody::Node& node = psb->m_nodes[j];
- diagA[counter] = (node.m_im == 0) ? btVector3(0, 0, 0) : btVector3(1.0 / node.m_im, 1.0 / node.m_im, 1.0 / node.m_im);
- ++counter;
- }
- }
- if (m_implicit)
- {
- printf("implicit not implemented\n");
- btAssert(false);
- }
- for (int i = 0; i < m_lf.size(); ++i)
- {
- // add damping matrix
- m_lf[i]->buildDampingForceDifferentialDiagonal(-m_dt, diagA);
- }
- }
-
- void buildDiagonalS(const TVStack& inv_A, TVStack& diagS)
- {
- for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
- {
- // S[k,k] = e_k^T * C A_d^-1 C^T * e_k
- const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
- btVector3& t = diagS[c];
- t.setZero();
- for (int j = 0; j < lm.m_num_constraints; ++j)
- {
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- for (int d = 0; d < 3; ++d)
- {
- t[j] += inv_A[lm.m_indices[i]][d] * lm.m_dirs[j][d] * lm.m_dirs[j][d] * lm.m_weights[i] * lm.m_weights[i];
- }
- }
- }
- }
- }
-//#define USE_FULL_PRECONDITIONER
-#ifndef USE_FULL_PRECONDITIONER
- virtual void operator()(const TVStack& x, TVStack& b)
- {
- btAssert(b.size() == x.size());
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- b[i] = x[i] * m_inv_A[i];
- }
- int offset = m_inv_A.size();
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- b[i + offset] = x[i + offset] * m_inv_S[i];
- }
- }
-#else
- virtual void operator()(const TVStack& x, TVStack& b)
- {
- btAssert(b.size() == x.size());
- int offset = m_inv_A.size();
-
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- b[i] = x[i] * m_inv_A[i];
- }
-
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- b[i + offset].setZero();
- }
-
- for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
- {
- const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
- // C * x
- for (int d = 0; d < lm.m_num_constraints; ++d)
- {
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- b[offset + c][d] += lm.m_weights[i] * b[lm.m_indices[i]].dot(lm.m_dirs[d]);
- }
- }
- }
-
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- b[i + offset] = b[i + offset] * m_inv_S[i];
- }
-
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- b[i].setZero();
- }
-
- for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
- {
- // C^T * lambda
- const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- for (int j = 0; j < lm.m_num_constraints; ++j)
- {
- b[lm.m_indices[i]] += b[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
- }
- }
- }
-
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- b[i] = (x[i] - b[i]) * m_inv_A[i];
- }
-
- TVStack t;
- t.resize(b.size());
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- t[i + offset] = x[i + offset] * m_inv_S[i];
- }
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- t[i].setZero();
- }
- for (int c = 0; c < m_projections.m_lagrangeMultipliers.size(); ++c)
- {
- // C^T * lambda
- const LagrangeMultiplier& lm = m_projections.m_lagrangeMultipliers[c];
- for (int i = 0; i < lm.m_num_nodes; ++i)
- {
- for (int j = 0; j < lm.m_num_constraints; ++j)
- {
- t[lm.m_indices[i]] += t[offset + c][j] * lm.m_weights[i] * lm.m_dirs[j];
- }
- }
- }
- for (int i = 0; i < m_inv_A.size(); ++i)
- {
- b[i] += t[i] * m_inv_A[i];
- }
-
- for (int i = 0; i < m_inv_S.size(); ++i)
- {
- b[i + offset] -= x[i + offset] * m_inv_S[i];
- }
- }
-#endif
-};
-
-#endif /* BT_PRECONDITIONER_H */
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
deleted file mode 100644
index d1980ea6c5..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.cpp
+++ /dev/null
@@ -1,4730 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btSoftBody implementation by Nathanael Presson
-
-#include "btSoftBodyInternals.h"
-#include "BulletSoftBody/btSoftBodySolvers.h"
-#include "btSoftBodyData.h"
-#include "LinearMath/btSerializer.h"
-#include "LinearMath/btImplicitQRSVD.h"
-#include "LinearMath/btAlignedAllocator.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include <iostream>
-//
-static inline btDbvtNode* buildTreeBottomUp(btAlignedObjectArray<btDbvtNode*>& leafNodes, btAlignedObjectArray<btAlignedObjectArray<int> >& adj)
-{
- int N = leafNodes.size();
- if (N == 0)
- {
- return NULL;
- }
- while (N > 1)
- {
- btAlignedObjectArray<bool> marked;
- btAlignedObjectArray<btDbvtNode*> newLeafNodes;
- btAlignedObjectArray<std::pair<int, int> > childIds;
- btAlignedObjectArray<btAlignedObjectArray<int> > newAdj;
- marked.resize(N);
- for (int i = 0; i < N; ++i)
- marked[i] = false;
-
- // pair adjacent nodes into new(parent) node
- for (int i = 0; i < N; ++i)
- {
- if (marked[i])
- continue;
- bool merged = false;
- for (int j = 0; j < adj[i].size(); ++j)
- {
- int n = adj[i][j];
- if (!marked[adj[i][j]])
- {
- btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
- node->parent = NULL;
- node->childs[0] = leafNodes[i];
- node->childs[1] = leafNodes[n];
- leafNodes[i]->parent = node;
- leafNodes[n]->parent = node;
- newLeafNodes.push_back(node);
- childIds.push_back(std::make_pair(i, n));
- merged = true;
- marked[n] = true;
- break;
- }
- }
- if (!merged)
- {
- newLeafNodes.push_back(leafNodes[i]);
- childIds.push_back(std::make_pair(i, -1));
- }
- marked[i] = true;
- }
- // update adjacency matrix
- newAdj.resize(newLeafNodes.size());
- for (int i = 0; i < newLeafNodes.size(); ++i)
- {
- for (int j = i + 1; j < newLeafNodes.size(); ++j)
- {
- bool neighbor = false;
- const btAlignedObjectArray<int>& leftChildNeighbors = adj[childIds[i].first];
- for (int k = 0; k < leftChildNeighbors.size(); ++k)
- {
- if (leftChildNeighbors[k] == childIds[j].first || leftChildNeighbors[k] == childIds[j].second)
- {
- neighbor = true;
- break;
- }
- }
- if (!neighbor && childIds[i].second != -1)
- {
- const btAlignedObjectArray<int>& rightChildNeighbors = adj[childIds[i].second];
- for (int k = 0; k < rightChildNeighbors.size(); ++k)
- {
- if (rightChildNeighbors[k] == childIds[j].first || rightChildNeighbors[k] == childIds[j].second)
- {
- neighbor = true;
- break;
- }
- }
- }
- if (neighbor)
- {
- newAdj[i].push_back(j);
- newAdj[j].push_back(i);
- }
- }
- }
- leafNodes = newLeafNodes;
- //this assignment leaks memory, the assignment doesn't do a deep copy, for now a manual copy
- //adj = newAdj;
- adj.clear();
- adj.resize(newAdj.size());
- for (int i = 0; i < newAdj.size(); i++)
- {
- for (int j = 0; j < newAdj[i].size(); j++)
- {
- adj[i].push_back(newAdj[i][j]);
- }
- }
- N = leafNodes.size();
- }
- return leafNodes[0];
-}
-
-//
-btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m)
- : m_softBodySolver(0), m_worldInfo(worldInfo)
-{
- /* Init */
- initDefaults();
-
- /* Default material */
- Material* pm = appendMaterial();
- pm->m_kLST = 1;
- pm->m_kAST = 1;
- pm->m_kVST = 1;
- pm->m_flags = fMaterial::Default;
-
- /* Nodes */
- const btScalar margin = getCollisionShape()->getMargin();
- m_nodes.resize(node_count);
- m_X.resize(node_count);
- for (int i = 0, ni = node_count; i < ni; ++i)
- {
- Node& n = m_nodes[i];
- ZeroInitialize(n);
- n.m_x = x ? *x++ : btVector3(0, 0, 0);
- n.m_q = n.m_x;
- n.m_im = m ? *m++ : 1;
- n.m_im = n.m_im > 0 ? 1 / n.m_im : 0;
- n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
- n.m_material = pm;
- m_X[i] = n.m_x;
- }
- updateBounds();
- setCollisionQuadrature(3);
- m_fdbvnt = 0;
-}
-
-btSoftBody::btSoftBody(btSoftBodyWorldInfo* worldInfo)
- : m_worldInfo(worldInfo)
-{
- initDefaults();
-}
-
-void btSoftBody::initDefaults()
-{
- m_internalType = CO_SOFT_BODY;
- m_cfg.aeromodel = eAeroModel::V_Point;
- m_cfg.kVCF = 1;
- m_cfg.kDG = 0;
- m_cfg.kLF = 0;
- m_cfg.kDP = 0;
- m_cfg.kPR = 0;
- m_cfg.kVC = 0;
- m_cfg.kDF = (btScalar)0.2;
- m_cfg.kMT = 0;
- m_cfg.kCHR = (btScalar)1.0;
- m_cfg.kKHR = (btScalar)0.1;
- m_cfg.kSHR = (btScalar)1.0;
- m_cfg.kAHR = (btScalar)0.7;
- m_cfg.kSRHR_CL = (btScalar)0.1;
- m_cfg.kSKHR_CL = (btScalar)1;
- m_cfg.kSSHR_CL = (btScalar)0.5;
- m_cfg.kSR_SPLT_CL = (btScalar)0.5;
- m_cfg.kSK_SPLT_CL = (btScalar)0.5;
- m_cfg.kSS_SPLT_CL = (btScalar)0.5;
- m_cfg.maxvolume = (btScalar)1;
- m_cfg.timescale = 1;
- m_cfg.viterations = 0;
- m_cfg.piterations = 1;
- m_cfg.diterations = 0;
- m_cfg.citerations = 4;
- m_cfg.drag = 0;
- m_cfg.m_maxStress = 0;
- m_cfg.collisions = fCollision::Default;
- m_pose.m_bvolume = false;
- m_pose.m_bframe = false;
- m_pose.m_volume = 0;
- m_pose.m_com = btVector3(0, 0, 0);
- m_pose.m_rot.setIdentity();
- m_pose.m_scl.setIdentity();
- m_tag = 0;
- m_timeacc = 0;
- m_bUpdateRtCst = true;
- m_bounds[0] = btVector3(0, 0, 0);
- m_bounds[1] = btVector3(0, 0, 0);
- m_worldTransform.setIdentity();
- setSolver(eSolverPresets::Positions);
-
- /* Collision shape */
- ///for now, create a collision shape internally
- m_collisionShape = new btSoftBodyCollisionShape(this);
- m_collisionShape->setMargin(0.25f);
-
- m_worldTransform.setIdentity();
-
- m_windVelocity = btVector3(0, 0, 0);
- m_restLengthScale = btScalar(1.0);
- m_dampingCoefficient = 1.0;
- m_sleepingThreshold = .04;
- m_useSelfCollision = false;
- m_collisionFlags = 0;
- m_softSoftCollision = false;
- m_maxSpeedSquared = 0;
- m_repulsionStiffness = 0.5;
- m_gravityFactor = 1;
- m_cacheBarycenter = false;
- m_fdbvnt = 0;
-}
-
-//
-btSoftBody::~btSoftBody()
-{
- //for now, delete the internal shape
- delete m_collisionShape;
- int i;
-
- releaseClusters();
- for (i = 0; i < m_materials.size(); ++i)
- btAlignedFree(m_materials[i]);
- for (i = 0; i < m_joints.size(); ++i)
- btAlignedFree(m_joints[i]);
- if (m_fdbvnt)
- delete m_fdbvnt;
-}
-
-//
-bool btSoftBody::checkLink(int node0, int node1) const
-{
- return (checkLink(&m_nodes[node0], &m_nodes[node1]));
-}
-
-//
-bool btSoftBody::checkLink(const Node* node0, const Node* node1) const
-{
- const Node* n[] = {node0, node1};
- for (int i = 0, ni = m_links.size(); i < ni; ++i)
- {
- const Link& l = m_links[i];
- if ((l.m_n[0] == n[0] && l.m_n[1] == n[1]) ||
- (l.m_n[0] == n[1] && l.m_n[1] == n[0]))
- {
- return (true);
- }
- }
- return (false);
-}
-
-//
-bool btSoftBody::checkFace(int node0, int node1, int node2) const
-{
- const Node* n[] = {&m_nodes[node0],
- &m_nodes[node1],
- &m_nodes[node2]};
- for (int i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- const Face& f = m_faces[i];
- int c = 0;
- for (int j = 0; j < 3; ++j)
- {
- if ((f.m_n[j] == n[0]) ||
- (f.m_n[j] == n[1]) ||
- (f.m_n[j] == n[2]))
- c |= 1 << j;
- else
- break;
- }
- if (c == 7) return (true);
- }
- return (false);
-}
-
-//
-btSoftBody::Material* btSoftBody::appendMaterial()
-{
- Material* pm = new (btAlignedAlloc(sizeof(Material), 16)) Material();
- if (m_materials.size() > 0)
- *pm = *m_materials[0];
- else
- ZeroInitialize(*pm);
- m_materials.push_back(pm);
- return (pm);
-}
-
-//
-void btSoftBody::appendNote(const char* text,
- const btVector3& o,
- const btVector4& c,
- Node* n0,
- Node* n1,
- Node* n2,
- Node* n3)
-{
- Note n;
- ZeroInitialize(n);
- n.m_rank = 0;
- n.m_text = text;
- n.m_offset = o;
- n.m_coords[0] = c.x();
- n.m_coords[1] = c.y();
- n.m_coords[2] = c.z();
- n.m_coords[3] = c.w();
- n.m_nodes[0] = n0;
- n.m_rank += n0 ? 1 : 0;
- n.m_nodes[1] = n1;
- n.m_rank += n1 ? 1 : 0;
- n.m_nodes[2] = n2;
- n.m_rank += n2 ? 1 : 0;
- n.m_nodes[3] = n3;
- n.m_rank += n3 ? 1 : 0;
- m_notes.push_back(n);
-}
-
-//
-void btSoftBody::appendNote(const char* text,
- const btVector3& o,
- Node* feature)
-{
- appendNote(text, o, btVector4(1, 0, 0, 0), feature);
-}
-
-//
-void btSoftBody::appendNote(const char* text,
- const btVector3& o,
- Link* feature)
-{
- static const btScalar w = 1 / (btScalar)2;
- appendNote(text, o, btVector4(w, w, 0, 0), feature->m_n[0],
- feature->m_n[1]);
-}
-
-//
-void btSoftBody::appendNote(const char* text,
- const btVector3& o,
- Face* feature)
-{
- static const btScalar w = 1 / (btScalar)3;
- appendNote(text, o, btVector4(w, w, w, 0), feature->m_n[0],
- feature->m_n[1],
- feature->m_n[2]);
-}
-
-//
-void btSoftBody::appendNode(const btVector3& x, btScalar m)
-{
- if (m_nodes.capacity() == m_nodes.size())
- {
- pointersToIndices();
- m_nodes.reserve(m_nodes.size() * 2 + 1);
- indicesToPointers();
- }
- const btScalar margin = getCollisionShape()->getMargin();
- m_nodes.push_back(Node());
- Node& n = m_nodes[m_nodes.size() - 1];
- ZeroInitialize(n);
- n.m_x = x;
- n.m_q = n.m_x;
- n.m_im = m > 0 ? 1 / m : 0;
- n.m_material = m_materials[0];
- n.m_leaf = m_ndbvt.insert(btDbvtVolume::FromCR(n.m_x, margin), &n);
-}
-
-//
-void btSoftBody::appendLink(int model, Material* mat)
-{
- Link l;
- if (model >= 0)
- l = m_links[model];
- else
- {
- ZeroInitialize(l);
- l.m_material = mat ? mat : m_materials[0];
- }
- m_links.push_back(l);
-}
-
-//
-void btSoftBody::appendLink(int node0,
- int node1,
- Material* mat,
- bool bcheckexist)
-{
- appendLink(&m_nodes[node0], &m_nodes[node1], mat, bcheckexist);
-}
-
-//
-void btSoftBody::appendLink(Node* node0,
- Node* node1,
- Material* mat,
- bool bcheckexist)
-{
- if ((!bcheckexist) || (!checkLink(node0, node1)))
- {
- appendLink(-1, mat);
- Link& l = m_links[m_links.size() - 1];
- l.m_n[0] = node0;
- l.m_n[1] = node1;
- l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
- m_bUpdateRtCst = true;
- }
-}
-
-//
-void btSoftBody::appendFace(int model, Material* mat)
-{
- Face f;
- if (model >= 0)
- {
- f = m_faces[model];
- }
- else
- {
- ZeroInitialize(f);
- f.m_material = mat ? mat : m_materials[0];
- }
- m_faces.push_back(f);
-}
-
-//
-void btSoftBody::appendFace(int node0, int node1, int node2, Material* mat)
-{
- if (node0 == node1)
- return;
- if (node1 == node2)
- return;
- if (node2 == node0)
- return;
-
- appendFace(-1, mat);
- Face& f = m_faces[m_faces.size() - 1];
- btAssert(node0 != node1);
- btAssert(node1 != node2);
- btAssert(node2 != node0);
- f.m_n[0] = &m_nodes[node0];
- f.m_n[1] = &m_nodes[node1];
- f.m_n[2] = &m_nodes[node2];
- f.m_ra = AreaOf(f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x);
- m_bUpdateRtCst = true;
-}
-
-//
-void btSoftBody::appendTetra(int model, Material* mat)
-{
- Tetra t;
- if (model >= 0)
- t = m_tetras[model];
- else
- {
- ZeroInitialize(t);
- t.m_material = mat ? mat : m_materials[0];
- }
- m_tetras.push_back(t);
-}
-
-//
-void btSoftBody::appendTetra(int node0,
- int node1,
- int node2,
- int node3,
- Material* mat)
-{
- appendTetra(-1, mat);
- Tetra& t = m_tetras[m_tetras.size() - 1];
- t.m_n[0] = &m_nodes[node0];
- t.m_n[1] = &m_nodes[node1];
- t.m_n[2] = &m_nodes[node2];
- t.m_n[3] = &m_nodes[node3];
- t.m_rv = VolumeOf(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x);
- m_bUpdateRtCst = true;
-}
-
-//
-
-void btSoftBody::appendAnchor(int node, btRigidBody* body, bool disableCollisionBetweenLinkedBodies, btScalar influence)
-{
- btVector3 local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
- appendAnchor(node, body, local, disableCollisionBetweenLinkedBodies, influence);
-}
-
-//
-void btSoftBody::appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies, btScalar influence)
-{
- if (disableCollisionBetweenLinkedBodies)
- {
- if (m_collisionDisabledObjects.findLinearSearch(body) == m_collisionDisabledObjects.size())
- {
- m_collisionDisabledObjects.push_back(body);
- }
- }
-
- Anchor a;
- a.m_node = &m_nodes[node];
- a.m_body = body;
- a.m_local = localPivot;
- a.m_node->m_battach = 1;
- a.m_influence = influence;
- m_anchors.push_back(a);
-}
-
-//
-void btSoftBody::appendDeformableAnchor(int node, btRigidBody* body)
-{
- DeformableNodeRigidAnchor c;
- btSoftBody::Node& n = m_nodes[node];
- const btScalar ima = n.m_im;
- const btScalar imb = body->getInvMass();
- btVector3 nrm;
- const btCollisionShape* shp = body->getCollisionShape();
- const btTransform& wtr = body->getWorldTransform();
- btScalar dst =
- m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(m_nodes[node].m_x),
- shp,
- nrm,
- 0);
-
- c.m_cti.m_colObj = body;
- c.m_cti.m_normal = wtr.getBasis() * nrm;
- c.m_cti.m_offset = dst;
- c.m_node = &m_nodes[node];
- const btScalar fc = m_cfg.kDF * body->getFriction();
- c.m_c2 = ima;
- c.m_c3 = fc;
- c.m_c4 = body->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = body->getInvInertiaTensorWorld();
- const btVector3 ra = n.m_x - wtr.getOrigin();
-
- c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
- c.m_c1 = ra;
- c.m_local = body->getWorldTransform().inverse() * m_nodes[node].m_x;
- c.m_node->m_battach = 1;
- m_deformableAnchors.push_back(c);
-}
-
-void btSoftBody::removeAnchor(int node)
-{
- const btSoftBody::Node& n = m_nodes[node];
- for (int i = 0; i < m_deformableAnchors.size();)
- {
- const DeformableNodeRigidAnchor& c = m_deformableAnchors[i];
- if (c.m_node == &n)
- {
- m_deformableAnchors.removeAtIndex(i);
- }
- else
- {
- i++;
- }
- }
-}
-
-//
-void btSoftBody::appendDeformableAnchor(int node, btMultiBodyLinkCollider* link)
-{
- DeformableNodeRigidAnchor c;
- btSoftBody::Node& n = m_nodes[node];
- const btScalar ima = n.m_im;
- btVector3 nrm;
- const btCollisionShape* shp = link->getCollisionShape();
- const btTransform& wtr = link->getWorldTransform();
- btScalar dst =
- m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(m_nodes[node].m_x),
- shp,
- nrm,
- 0);
- c.m_cti.m_colObj = link;
- c.m_cti.m_normal = wtr.getBasis() * nrm;
- c.m_cti.m_offset = dst;
- c.m_node = &m_nodes[node];
- const btScalar fc = m_cfg.kDF * link->getFriction();
- c.m_c2 = ima;
- c.m_c3 = fc;
- c.m_c4 = link->isStaticOrKinematicObject() ? m_cfg.kKHR : m_cfg.kCHR;
- btVector3 normal = c.m_cti.m_normal;
- btVector3 t1 = generateUnitOrthogonalVector(normal);
- btVector3 t2 = btCross(normal, t1);
- btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
- findJacobian(link, jacobianData_normal, c.m_node->m_x, normal);
- findJacobian(link, jacobianData_t1, c.m_node->m_x, t1);
- findJacobian(link, jacobianData_t2, c.m_node->m_x, t2);
-
- btScalar* J_n = &jacobianData_normal.m_jacobians[0];
- btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
- btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
-
- btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
-
- btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
- t1.getX(), t1.getY(), t1.getZ(),
- t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
- const int ndof = link->m_multiBody->getNumDofs() + 6;
- btMatrix3x3 local_impulse_matrix = (Diagonal(n.m_im) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
- c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
- c.jacobianData_normal = jacobianData_normal;
- c.jacobianData_t1 = jacobianData_t1;
- c.jacobianData_t2 = jacobianData_t2;
- c.t1 = t1;
- c.t2 = t2;
- const btVector3 ra = n.m_x - wtr.getOrigin();
- c.m_c1 = ra;
- c.m_local = link->getWorldTransform().inverse() * m_nodes[node].m_x;
- c.m_node->m_battach = 1;
- m_deformableAnchors.push_back(c);
-}
-//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1)
-{
- LJoint* pj = new (btAlignedAlloc(sizeof(LJoint), 16)) LJoint();
- pj->m_bodies[0] = body0;
- pj->m_bodies[1] = body1;
- pj->m_refs[0] = pj->m_bodies[0].xform().inverse() * specs.position;
- pj->m_refs[1] = pj->m_bodies[1].xform().inverse() * specs.position;
- pj->m_cfm = specs.cfm;
- pj->m_erp = specs.erp;
- pj->m_split = specs.split;
- m_joints.push_back(pj);
-}
-
-//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, Body body)
-{
- appendLinearJoint(specs, m_clusters[0], body);
-}
-
-//
-void btSoftBody::appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body)
-{
- appendLinearJoint(specs, m_clusters[0], body->m_clusters[0]);
-}
-
-//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1)
-{
- AJoint* pj = new (btAlignedAlloc(sizeof(AJoint), 16)) AJoint();
- pj->m_bodies[0] = body0;
- pj->m_bodies[1] = body1;
- pj->m_refs[0] = pj->m_bodies[0].xform().inverse().getBasis() * specs.axis;
- pj->m_refs[1] = pj->m_bodies[1].xform().inverse().getBasis() * specs.axis;
- pj->m_cfm = specs.cfm;
- pj->m_erp = specs.erp;
- pj->m_split = specs.split;
- pj->m_icontrol = specs.icontrol;
- m_joints.push_back(pj);
-}
-
-//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, Body body)
-{
- appendAngularJoint(specs, m_clusters[0], body);
-}
-
-//
-void btSoftBody::appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body)
-{
- appendAngularJoint(specs, m_clusters[0], body->m_clusters[0]);
-}
-
-//
-void btSoftBody::addForce(const btVector3& force)
-{
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addForce(force, i);
-}
-
-//
-void btSoftBody::addForce(const btVector3& force, int node)
-{
- Node& n = m_nodes[node];
- if (n.m_im > 0)
- {
- n.m_f += force;
- }
-}
-
-void btSoftBody::addAeroForceToNode(const btVector3& windVelocity, int nodeIndex)
-{
- btAssert(nodeIndex >= 0 && nodeIndex < m_nodes.size());
-
- const btScalar dt = m_sst.sdt;
- const btScalar kLF = m_cfg.kLF;
- const btScalar kDG = m_cfg.kDG;
- //const btScalar kPR = m_cfg.kPR;
- //const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF > 0;
- const bool as_drag = kDG > 0;
- const bool as_aero = as_lift || as_drag;
- const bool as_vaero = as_aero && (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
-
- Node& n = m_nodes[nodeIndex];
-
- if (n.m_im > 0)
- {
- btSoftBody::sMedium medium;
-
- EvaluateMedium(m_worldInfo, n.m_x, medium);
- medium.m_velocity = windVelocity;
- medium.m_density = m_worldInfo->air_density;
-
- /* Aerodynamics */
- if (as_vaero)
- {
- const btVector3 rel_v = n.m_v - medium.m_velocity;
- const btScalar rel_v_len = rel_v.length();
- const btScalar rel_v2 = rel_v.length2();
-
- if (rel_v2 > SIMD_EPSILON)
- {
- const btVector3 rel_v_nrm = rel_v.normalized();
- btVector3 nrm = n.m_n;
-
- if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSidedLiftDrag)
- {
- nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
- btVector3 fDrag(0, 0, 0);
- btVector3 fLift(0, 0, 0);
-
- btScalar n_dot_v = nrm.dot(rel_v_nrm);
- btScalar tri_area = 0.5f * n.m_area;
-
- fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
-
- // Check angle of attack
- // cos(10º) = 0.98480
- if (0 < n_dot_v && n_dot_v < 0.98480f)
- fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
-
- // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
- btVector3 del_v_by_fDrag = fDrag * n.m_im * m_sst.sdt;
- btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
- btScalar v_len2 = n.m_v.length2();
-
- if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
- {
- btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
- btScalar v_len = n.m_v.length();
- fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
- }
-
- n.m_f += fDrag;
- n.m_f += fLift;
- }
- else if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_Point || m_cfg.aeromodel == btSoftBody::eAeroModel::V_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
- {
- if (m_cfg.aeromodel == btSoftBody::eAeroModel::V_TwoSided)
- nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
-
- const btScalar dvn = btDot(rel_v, nrm);
- /* Compute forces */
- if (dvn > 0)
- {
- btVector3 force(0, 0, 0);
- const btScalar c0 = n.m_area * dvn * rel_v2 / 2;
- const btScalar c1 = c0 * medium.m_density;
- force += nrm * (-c1 * kLF);
- force += rel_v.normalized() * (-c1 * kDG);
- ApplyClampedForce(n, force, dt);
- }
- }
- }
- }
- }
-}
-
-void btSoftBody::addAeroForceToFace(const btVector3& windVelocity, int faceIndex)
-{
- const btScalar dt = m_sst.sdt;
- const btScalar kLF = m_cfg.kLF;
- const btScalar kDG = m_cfg.kDG;
- // const btScalar kPR = m_cfg.kPR;
- // const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF > 0;
- const bool as_drag = kDG > 0;
- const bool as_aero = as_lift || as_drag;
- const bool as_faero = as_aero && (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
-
- if (as_faero)
- {
- btSoftBody::Face& f = m_faces[faceIndex];
-
- btSoftBody::sMedium medium;
-
- const btVector3 v = (f.m_n[0]->m_v + f.m_n[1]->m_v + f.m_n[2]->m_v) / 3;
- const btVector3 x = (f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3;
- EvaluateMedium(m_worldInfo, x, medium);
- medium.m_velocity = windVelocity;
- medium.m_density = m_worldInfo->air_density;
- const btVector3 rel_v = v - medium.m_velocity;
- const btScalar rel_v_len = rel_v.length();
- const btScalar rel_v2 = rel_v.length2();
-
- if (rel_v2 > SIMD_EPSILON)
- {
- const btVector3 rel_v_nrm = rel_v.normalized();
- btVector3 nrm = f.m_normal;
-
- if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSidedLiftDrag)
- {
- nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
-
- btVector3 fDrag(0, 0, 0);
- btVector3 fLift(0, 0, 0);
-
- btScalar n_dot_v = nrm.dot(rel_v_nrm);
- btScalar tri_area = 0.5f * f.m_ra;
-
- fDrag = 0.5f * kDG * medium.m_density * rel_v2 * tri_area * n_dot_v * (-rel_v_nrm);
-
- // Check angle of attack
- // cos(10º) = 0.98480
- if (0 < n_dot_v && n_dot_v < 0.98480f)
- fLift = 0.5f * kLF * medium.m_density * rel_v_len * tri_area * btSqrt(1.0f - n_dot_v * n_dot_v) * (nrm.cross(rel_v_nrm).cross(rel_v_nrm));
-
- fDrag /= 3;
- fLift /= 3;
-
- for (int j = 0; j < 3; ++j)
- {
- if (f.m_n[j]->m_im > 0)
- {
- // Check if the velocity change resulted by aero drag force exceeds the current velocity of the node.
- btVector3 del_v_by_fDrag = fDrag * f.m_n[j]->m_im * m_sst.sdt;
- btScalar del_v_by_fDrag_len2 = del_v_by_fDrag.length2();
- btScalar v_len2 = f.m_n[j]->m_v.length2();
-
- if (del_v_by_fDrag_len2 >= v_len2 && del_v_by_fDrag_len2 > 0)
- {
- btScalar del_v_by_fDrag_len = del_v_by_fDrag.length();
- btScalar v_len = f.m_n[j]->m_v.length();
- fDrag *= btScalar(0.8) * (v_len / del_v_by_fDrag_len);
- }
-
- f.m_n[j]->m_f += fDrag;
- f.m_n[j]->m_f += fLift;
- }
- }
- }
- else if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_OneSided || m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
- {
- if (m_cfg.aeromodel == btSoftBody::eAeroModel::F_TwoSided)
- nrm *= (btScalar)((btDot(nrm, rel_v) < 0) ? -1 : +1);
-
- const btScalar dvn = btDot(rel_v, nrm);
- /* Compute forces */
- if (dvn > 0)
- {
- btVector3 force(0, 0, 0);
- const btScalar c0 = f.m_ra * dvn * rel_v2;
- const btScalar c1 = c0 * medium.m_density;
- force += nrm * (-c1 * kLF);
- force += rel_v.normalized() * (-c1 * kDG);
- force /= 3;
- for (int j = 0; j < 3; ++j) ApplyClampedForce(*f.m_n[j], force, dt);
- }
- }
- }
- }
-}
-
-//
-void btSoftBody::addVelocity(const btVector3& velocity)
-{
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i) addVelocity(velocity, i);
-}
-
-/* Set velocity for the entire body */
-void btSoftBody::setVelocity(const btVector3& velocity)
-{
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- if (n.m_im > 0)
- {
- n.m_v = velocity;
- n.m_vn = velocity;
- }
- }
-}
-
-//
-void btSoftBody::addVelocity(const btVector3& velocity, int node)
-{
- Node& n = m_nodes[node];
- if (n.m_im > 0)
- {
- n.m_v += velocity;
- }
-}
-
-//
-void btSoftBody::setMass(int node, btScalar mass)
-{
- m_nodes[node].m_im = mass > 0 ? 1 / mass : 0;
- m_bUpdateRtCst = true;
-}
-
-//
-btScalar btSoftBody::getMass(int node) const
-{
- return (m_nodes[node].m_im > 0 ? 1 / m_nodes[node].m_im : 0);
-}
-
-//
-btScalar btSoftBody::getTotalMass() const
-{
- btScalar mass = 0;
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- mass += getMass(i);
- }
- return (mass);
-}
-
-//
-void btSoftBody::setTotalMass(btScalar mass, bool fromfaces)
-{
- int i;
-
- if (fromfaces)
- {
- for (i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_im = 0;
- }
- for (i = 0; i < m_faces.size(); ++i)
- {
- const Face& f = m_faces[i];
- const btScalar twicearea = AreaOf(f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x);
- for (int j = 0; j < 3; ++j)
- {
- f.m_n[j]->m_im += twicearea;
- }
- }
- for (i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_im = 1 / m_nodes[i].m_im;
- }
- }
- const btScalar tm = getTotalMass();
- const btScalar itm = 1 / tm;
- for (i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_im /= itm * mass;
- }
- m_bUpdateRtCst = true;
-}
-
-//
-void btSoftBody::setTotalDensity(btScalar density)
-{
- setTotalMass(getVolume() * density, true);
-}
-
-//
-void btSoftBody::setVolumeMass(btScalar mass)
-{
- btAlignedObjectArray<btScalar> ranks;
- ranks.resize(m_nodes.size(), 0);
- int i;
-
- for (i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_im = 0;
- }
- for (i = 0; i < m_tetras.size(); ++i)
- {
- const Tetra& t = m_tetras[i];
- for (int j = 0; j < 4; ++j)
- {
- t.m_n[j]->m_im += btFabs(t.m_rv);
- ranks[int(t.m_n[j] - &m_nodes[0])] += 1;
- }
- }
- for (i = 0; i < m_nodes.size(); ++i)
- {
- if (m_nodes[i].m_im > 0)
- {
- m_nodes[i].m_im = ranks[i] / m_nodes[i].m_im;
- }
- }
- setTotalMass(mass, false);
-}
-
-//
-void btSoftBody::setVolumeDensity(btScalar density)
-{
- btScalar volume = 0;
- for (int i = 0; i < m_tetras.size(); ++i)
- {
- const Tetra& t = m_tetras[i];
- for (int j = 0; j < 4; ++j)
- {
- volume += btFabs(t.m_rv);
- }
- }
- setVolumeMass(volume * density / 6);
-}
-
-//
-btVector3 btSoftBody::getLinearVelocity()
-{
- btVector3 total_momentum = btVector3(0, 0, 0);
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- btScalar mass = m_nodes[i].m_im == 0 ? 0 : 1.0 / m_nodes[i].m_im;
- total_momentum += mass * m_nodes[i].m_v;
- }
- btScalar total_mass = getTotalMass();
- return total_mass == 0 ? total_momentum : total_momentum / total_mass;
-}
-
-//
-void btSoftBody::setLinearVelocity(const btVector3& linVel)
-{
- btVector3 old_vel = getLinearVelocity();
- btVector3 diff = linVel - old_vel;
- for (int i = 0; i < m_nodes.size(); ++i)
- m_nodes[i].m_v += diff;
-}
-
-//
-void btSoftBody::setAngularVelocity(const btVector3& angVel)
-{
- btVector3 old_vel = getLinearVelocity();
- btVector3 com = getCenterOfMass();
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_v = angVel.cross(m_nodes[i].m_x - com) + old_vel;
- }
-}
-
-//
-btTransform btSoftBody::getRigidTransform()
-{
- btVector3 t = getCenterOfMass();
- btMatrix3x3 S;
- S.setZero();
- // Get rotation that minimizes L2 difference: \sum_i || RX_i + t - x_i ||
- // It's important to make sure that S has the correct signs.
- // SVD is only unique up to the ordering of singular values.
- // SVD will manipulate U and V to ensure the ordering of singular values. If all three singular
- // vaues are negative, SVD will permute colums of U to make two of them positive.
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- S -= OuterProduct(m_X[i], t - m_nodes[i].m_x);
- }
- btVector3 sigma;
- btMatrix3x3 U, V;
- singularValueDecomposition(S, U, sigma, V);
- btMatrix3x3 R = V * U.transpose();
- btTransform trs;
- trs.setIdentity();
- trs.setOrigin(t);
- trs.setBasis(R);
- return trs;
-}
-
-//
-void btSoftBody::transformTo(const btTransform& trs)
-{
- // get the current best rigid fit
- btTransform current_transform = getRigidTransform();
- // apply transform in material space
- btTransform new_transform = trs * current_transform.inverse();
- transform(new_transform);
-}
-
-//
-void btSoftBody::transform(const btTransform& trs)
-{
- const btScalar margin = getCollisionShape()->getMargin();
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
-
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_x = trs * n.m_x;
- n.m_q = trs * n.m_q;
- n.m_n = trs.getBasis() * n.m_n;
- vol = btDbvtVolume::FromCR(n.m_x, margin);
-
- m_ndbvt.update(n.m_leaf, vol);
- }
- updateNormals();
- updateBounds();
- updateConstants();
-}
-
-//
-void btSoftBody::translate(const btVector3& trs)
-{
- btTransform t;
- t.setIdentity();
- t.setOrigin(trs);
- transform(t);
-}
-
-//
-void btSoftBody::rotate(const btQuaternion& rot)
-{
- btTransform t;
- t.setIdentity();
- t.setRotation(rot);
- transform(t);
-}
-
-//
-void btSoftBody::scale(const btVector3& scl)
-{
- const btScalar margin = getCollisionShape()->getMargin();
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
-
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_x *= scl;
- n.m_q *= scl;
- vol = btDbvtVolume::FromCR(n.m_x, margin);
- m_ndbvt.update(n.m_leaf, vol);
- }
- updateNormals();
- updateBounds();
- updateConstants();
- initializeDmInverse();
-}
-
-//
-btScalar btSoftBody::getRestLengthScale()
-{
- return m_restLengthScale;
-}
-
-//
-void btSoftBody::setRestLengthScale(btScalar restLengthScale)
-{
- for (int i = 0, ni = m_links.size(); i < ni; ++i)
- {
- Link& l = m_links[i];
- l.m_rl = l.m_rl / m_restLengthScale * restLengthScale;
- l.m_c1 = l.m_rl * l.m_rl;
- }
- m_restLengthScale = restLengthScale;
-
- if (getActivationState() == ISLAND_SLEEPING)
- activate();
-}
-
-//
-void btSoftBody::setPose(bool bvolume, bool bframe)
-{
- m_pose.m_bvolume = bvolume;
- m_pose.m_bframe = bframe;
- int i, ni;
-
- /* Weights */
- const btScalar omass = getTotalMass();
- const btScalar kmass = omass * m_nodes.size() * 1000;
- btScalar tmass = omass;
- m_pose.m_wgh.resize(m_nodes.size());
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- if (m_nodes[i].m_im <= 0) tmass += kmass;
- }
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- m_pose.m_wgh[i] = n.m_im > 0 ? 1 / (m_nodes[i].m_im * tmass) : kmass / tmass;
- }
- /* Pos */
- const btVector3 com = evaluateCom();
- m_pose.m_pos.resize(m_nodes.size());
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- m_pose.m_pos[i] = m_nodes[i].m_x - com;
- }
- m_pose.m_volume = bvolume ? getVolume() : 0;
- m_pose.m_com = com;
- m_pose.m_rot.setIdentity();
- m_pose.m_scl.setIdentity();
- /* Aqq */
- m_pose.m_aqq[0] =
- m_pose.m_aqq[1] =
- m_pose.m_aqq[2] = btVector3(0, 0, 0);
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- const btVector3& q = m_pose.m_pos[i];
- const btVector3 mq = m_pose.m_wgh[i] * q;
- m_pose.m_aqq[0] += mq.x() * q;
- m_pose.m_aqq[1] += mq.y() * q;
- m_pose.m_aqq[2] += mq.z() * q;
- }
- m_pose.m_aqq = m_pose.m_aqq.inverse();
-
- updateConstants();
-}
-
-void btSoftBody::resetLinkRestLengths()
-{
- for (int i = 0, ni = m_links.size(); i < ni; ++i)
- {
- Link& l = m_links[i];
- l.m_rl = (l.m_n[0]->m_x - l.m_n[1]->m_x).length();
- l.m_c1 = l.m_rl * l.m_rl;
- }
-}
-
-//
-btScalar btSoftBody::getVolume() const
-{
- btScalar vol = 0;
- if (m_nodes.size() > 0)
- {
- int i, ni;
-
- const btVector3 org = m_nodes[0].m_x;
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- const Face& f = m_faces[i];
- vol += btDot(f.m_n[0]->m_x - org, btCross(f.m_n[1]->m_x - org, f.m_n[2]->m_x - org));
- }
- vol /= (btScalar)6;
- }
- return (vol);
-}
-
-//
-int btSoftBody::clusterCount() const
-{
- return (m_clusters.size());
-}
-
-//
-btVector3 btSoftBody::clusterCom(const Cluster* cluster)
-{
- btVector3 com(0, 0, 0);
- for (int i = 0, ni = cluster->m_nodes.size(); i < ni; ++i)
- {
- com += cluster->m_nodes[i]->m_x * cluster->m_masses[i];
- }
- return (com * cluster->m_imass);
-}
-
-//
-btVector3 btSoftBody::clusterCom(int cluster) const
-{
- return (clusterCom(m_clusters[cluster]));
-}
-
-//
-btVector3 btSoftBody::clusterVelocity(const Cluster* cluster, const btVector3& rpos)
-{
- return (cluster->m_lv + btCross(cluster->m_av, rpos));
-}
-
-//
-void btSoftBody::clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
-{
- const btVector3 li = cluster->m_imass * impulse;
- const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
- cluster->m_vimpulses[0] += li;
- cluster->m_lv += li;
- cluster->m_vimpulses[1] += ai;
- cluster->m_av += ai;
- cluster->m_nvimpulses++;
-}
-
-//
-void btSoftBody::clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse)
-{
- const btVector3 li = cluster->m_imass * impulse;
- const btVector3 ai = cluster->m_invwi * btCross(rpos, impulse);
- cluster->m_dimpulses[0] += li;
- cluster->m_dimpulses[1] += ai;
- cluster->m_ndimpulses++;
-}
-
-//
-void btSoftBody::clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse)
-{
- if (impulse.m_asVelocity) clusterVImpulse(cluster, rpos, impulse.m_velocity);
- if (impulse.m_asDrift) clusterDImpulse(cluster, rpos, impulse.m_drift);
-}
-
-//
-void btSoftBody::clusterVAImpulse(Cluster* cluster, const btVector3& impulse)
-{
- const btVector3 ai = cluster->m_invwi * impulse;
- cluster->m_vimpulses[1] += ai;
- cluster->m_av += ai;
- cluster->m_nvimpulses++;
-}
-
-//
-void btSoftBody::clusterDAImpulse(Cluster* cluster, const btVector3& impulse)
-{
- const btVector3 ai = cluster->m_invwi * impulse;
- cluster->m_dimpulses[1] += ai;
- cluster->m_ndimpulses++;
-}
-
-//
-void btSoftBody::clusterAImpulse(Cluster* cluster, const Impulse& impulse)
-{
- if (impulse.m_asVelocity) clusterVAImpulse(cluster, impulse.m_velocity);
- if (impulse.m_asDrift) clusterDAImpulse(cluster, impulse.m_drift);
-}
-
-//
-void btSoftBody::clusterDCImpulse(Cluster* cluster, const btVector3& impulse)
-{
- cluster->m_dimpulses[0] += impulse * cluster->m_imass;
- cluster->m_ndimpulses++;
-}
-
-struct NodeLinks
-{
- btAlignedObjectArray<int> m_links;
-};
-
-//
-int btSoftBody::generateBendingConstraints(int distance, Material* mat)
-{
- int i, j;
-
- if (distance > 1)
- {
- /* Build graph */
- const int n = m_nodes.size();
- const unsigned inf = (~(unsigned)0) >> 1;
- unsigned* adj = new unsigned[n * n];
-
-#define IDX(_x_, _y_) ((_y_)*n + (_x_))
- for (j = 0; j < n; ++j)
- {
- for (i = 0; i < n; ++i)
- {
- if (i != j)
- {
- adj[IDX(i, j)] = adj[IDX(j, i)] = inf;
- }
- else
- {
- adj[IDX(i, j)] = adj[IDX(j, i)] = 0;
- }
- }
- }
- for (i = 0; i < m_links.size(); ++i)
- {
- const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
- const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
- adj[IDX(ia, ib)] = 1;
- adj[IDX(ib, ia)] = 1;
- }
-
- //special optimized case for distance == 2
- if (distance == 2)
- {
- btAlignedObjectArray<NodeLinks> nodeLinks;
-
- /* Build node links */
- nodeLinks.resize(m_nodes.size());
-
- for (i = 0; i < m_links.size(); ++i)
- {
- const int ia = (int)(m_links[i].m_n[0] - &m_nodes[0]);
- const int ib = (int)(m_links[i].m_n[1] - &m_nodes[0]);
- if (nodeLinks[ia].m_links.findLinearSearch(ib) == nodeLinks[ia].m_links.size())
- nodeLinks[ia].m_links.push_back(ib);
-
- if (nodeLinks[ib].m_links.findLinearSearch(ia) == nodeLinks[ib].m_links.size())
- nodeLinks[ib].m_links.push_back(ia);
- }
- for (int ii = 0; ii < nodeLinks.size(); ii++)
- {
- int i = ii;
-
- for (int jj = 0; jj < nodeLinks[ii].m_links.size(); jj++)
- {
- int k = nodeLinks[ii].m_links[jj];
- for (int kk = 0; kk < nodeLinks[k].m_links.size(); kk++)
- {
- int j = nodeLinks[k].m_links[kk];
- if (i != j)
- {
- const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
- btAssert(sum == 2);
- if (adj[IDX(i, j)] > sum)
- {
- adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
- }
- }
- }
- }
- }
- }
- else
- {
- ///generic Floyd's algorithm
- for (int k = 0; k < n; ++k)
- {
- for (j = 0; j < n; ++j)
- {
- for (i = j + 1; i < n; ++i)
- {
- const unsigned sum = adj[IDX(i, k)] + adj[IDX(k, j)];
- if (adj[IDX(i, j)] > sum)
- {
- adj[IDX(i, j)] = adj[IDX(j, i)] = sum;
- }
- }
- }
- }
- }
-
- /* Build links */
- int nlinks = 0;
- for (j = 0; j < n; ++j)
- {
- for (i = j + 1; i < n; ++i)
- {
- if (adj[IDX(i, j)] == (unsigned)distance)
- {
- appendLink(i, j, mat);
- m_links[m_links.size() - 1].m_bbending = 1;
- ++nlinks;
- }
- }
- }
- delete[] adj;
- return (nlinks);
- }
- return (0);
-}
-
-//
-void btSoftBody::randomizeConstraints()
-{
- unsigned long seed = 243703;
-#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
- int i, ni;
-
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- btSwap(m_links[i], m_links[NEXTRAND % ni]);
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- btSwap(m_faces[i], m_faces[NEXTRAND % ni]);
- }
-#undef NEXTRAND
-}
-
-//
-void btSoftBody::releaseCluster(int index)
-{
- Cluster* c = m_clusters[index];
- if (c->m_leaf) m_cdbvt.remove(c->m_leaf);
- c->~Cluster();
- btAlignedFree(c);
- m_clusters.remove(c);
-}
-
-//
-void btSoftBody::releaseClusters()
-{
- while (m_clusters.size() > 0) releaseCluster(0);
-}
-
-//
-int btSoftBody::generateClusters(int k, int maxiterations)
-{
- int i;
- releaseClusters();
- m_clusters.resize(btMin(k, m_nodes.size()));
- for (i = 0; i < m_clusters.size(); ++i)
- {
- m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
- m_clusters[i]->m_collide = true;
- }
- k = m_clusters.size();
- if (k > 0)
- {
- /* Initialize */
- btAlignedObjectArray<btVector3> centers;
- btVector3 cog(0, 0, 0);
- int i;
- for (i = 0; i < m_nodes.size(); ++i)
- {
- cog += m_nodes[i].m_x;
- m_clusters[(i * 29873) % m_clusters.size()]->m_nodes.push_back(&m_nodes[i]);
- }
- cog /= (btScalar)m_nodes.size();
- centers.resize(k, cog);
- /* Iterate */
- const btScalar slope = 16;
- bool changed;
- int iterations = 0;
- do
- {
- const btScalar w = 2 - btMin<btScalar>(1, iterations / slope);
- changed = false;
- iterations++;
- int i;
-
- for (i = 0; i < k; ++i)
- {
- btVector3 c(0, 0, 0);
- for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
- {
- c += m_clusters[i]->m_nodes[j]->m_x;
- }
- if (m_clusters[i]->m_nodes.size())
- {
- c /= (btScalar)m_clusters[i]->m_nodes.size();
- c = centers[i] + (c - centers[i]) * w;
- changed |= ((c - centers[i]).length2() > SIMD_EPSILON);
- centers[i] = c;
- m_clusters[i]->m_nodes.resize(0);
- }
- }
- for (i = 0; i < m_nodes.size(); ++i)
- {
- const btVector3 nx = m_nodes[i].m_x;
- int kbest = 0;
- btScalar kdist = ClusterMetric(centers[0], nx);
- for (int j = 1; j < k; ++j)
- {
- const btScalar d = ClusterMetric(centers[j], nx);
- if (d < kdist)
- {
- kbest = j;
- kdist = d;
- }
- }
- m_clusters[kbest]->m_nodes.push_back(&m_nodes[i]);
- }
- } while (changed && (iterations < maxiterations));
- /* Merge */
- btAlignedObjectArray<int> cids;
- cids.resize(m_nodes.size(), -1);
- for (i = 0; i < m_clusters.size(); ++i)
- {
- for (int j = 0; j < m_clusters[i]->m_nodes.size(); ++j)
- {
- cids[int(m_clusters[i]->m_nodes[j] - &m_nodes[0])] = i;
- }
- }
- for (i = 0; i < m_faces.size(); ++i)
- {
- const int idx[] = {int(m_faces[i].m_n[0] - &m_nodes[0]),
- int(m_faces[i].m_n[1] - &m_nodes[0]),
- int(m_faces[i].m_n[2] - &m_nodes[0])};
- for (int j = 0; j < 3; ++j)
- {
- const int cid = cids[idx[j]];
- for (int q = 1; q < 3; ++q)
- {
- const int kid = idx[(j + q) % 3];
- if (cids[kid] != cid)
- {
- if (m_clusters[cid]->m_nodes.findLinearSearch(&m_nodes[kid]) == m_clusters[cid]->m_nodes.size())
- {
- m_clusters[cid]->m_nodes.push_back(&m_nodes[kid]);
- }
- }
- }
- }
- }
- /* Master */
- if (m_clusters.size() > 1)
- {
- Cluster* pmaster = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
- pmaster->m_collide = false;
- pmaster->m_nodes.reserve(m_nodes.size());
- for (int i = 0; i < m_nodes.size(); ++i) pmaster->m_nodes.push_back(&m_nodes[i]);
- m_clusters.push_back(pmaster);
- btSwap(m_clusters[0], m_clusters[m_clusters.size() - 1]);
- }
- /* Terminate */
- for (i = 0; i < m_clusters.size(); ++i)
- {
- if (m_clusters[i]->m_nodes.size() == 0)
- {
- releaseCluster(i--);
- }
- }
- }
- else
- {
- //create a cluster for each tetrahedron (if tetrahedra exist) or each face
- if (m_tetras.size())
- {
- m_clusters.resize(m_tetras.size());
- for (i = 0; i < m_clusters.size(); ++i)
- {
- m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
- m_clusters[i]->m_collide = true;
- }
- for (i = 0; i < m_tetras.size(); i++)
- {
- for (int j = 0; j < 4; j++)
- {
- m_clusters[i]->m_nodes.push_back(m_tetras[i].m_n[j]);
- }
- }
- }
- else
- {
- m_clusters.resize(m_faces.size());
- for (i = 0; i < m_clusters.size(); ++i)
- {
- m_clusters[i] = new (btAlignedAlloc(sizeof(Cluster), 16)) Cluster();
- m_clusters[i]->m_collide = true;
- }
-
- for (i = 0; i < m_faces.size(); ++i)
- {
- for (int j = 0; j < 3; ++j)
- {
- m_clusters[i]->m_nodes.push_back(m_faces[i].m_n[j]);
- }
- }
- }
- }
-
- if (m_clusters.size())
- {
- initializeClusters();
- updateClusters();
-
- //for self-collision
- m_clusterConnectivity.resize(m_clusters.size() * m_clusters.size());
- {
- for (int c0 = 0; c0 < m_clusters.size(); c0++)
- {
- m_clusters[c0]->m_clusterIndex = c0;
- for (int c1 = 0; c1 < m_clusters.size(); c1++)
- {
- bool connected = false;
- Cluster* cla = m_clusters[c0];
- Cluster* clb = m_clusters[c1];
- for (int i = 0; !connected && i < cla->m_nodes.size(); i++)
- {
- for (int j = 0; j < clb->m_nodes.size(); j++)
- {
- if (cla->m_nodes[i] == clb->m_nodes[j])
- {
- connected = true;
- break;
- }
- }
- }
- m_clusterConnectivity[c0 + c1 * m_clusters.size()] = connected;
- }
- }
- }
- }
-
- return (m_clusters.size());
-}
-
-//
-void btSoftBody::refine(ImplicitFn* ifn, btScalar accurary, bool cut)
-{
- const Node* nbase = &m_nodes[0];
- int ncount = m_nodes.size();
- btSymMatrix<int> edges(ncount, -2);
- int newnodes = 0;
- int i, j, k, ni;
-
- /* Filter out */
- for (i = 0; i < m_links.size(); ++i)
- {
- Link& l = m_links[i];
- if (l.m_bbending)
- {
- if (!SameSign(ifn->Eval(l.m_n[0]->m_x), ifn->Eval(l.m_n[1]->m_x)))
- {
- btSwap(m_links[i], m_links[m_links.size() - 1]);
- m_links.pop_back();
- --i;
- }
- }
- }
- /* Fill edges */
- for (i = 0; i < m_links.size(); ++i)
- {
- Link& l = m_links[i];
- edges(int(l.m_n[0] - nbase), int(l.m_n[1] - nbase)) = -1;
- }
- for (i = 0; i < m_faces.size(); ++i)
- {
- Face& f = m_faces[i];
- edges(int(f.m_n[0] - nbase), int(f.m_n[1] - nbase)) = -1;
- edges(int(f.m_n[1] - nbase), int(f.m_n[2] - nbase)) = -1;
- edges(int(f.m_n[2] - nbase), int(f.m_n[0] - nbase)) = -1;
- }
- /* Intersect */
- for (i = 0; i < ncount; ++i)
- {
- for (j = i + 1; j < ncount; ++j)
- {
- if (edges(i, j) == -1)
- {
- Node& a = m_nodes[i];
- Node& b = m_nodes[j];
- const btScalar t = ImplicitSolve(ifn, a.m_x, b.m_x, accurary);
- if (t > 0)
- {
- const btVector3 x = Lerp(a.m_x, b.m_x, t);
- const btVector3 v = Lerp(a.m_v, b.m_v, t);
- btScalar m = 0;
- if (a.m_im > 0)
- {
- if (b.m_im > 0)
- {
- const btScalar ma = 1 / a.m_im;
- const btScalar mb = 1 / b.m_im;
- const btScalar mc = Lerp(ma, mb, t);
- const btScalar f = (ma + mb) / (ma + mb + mc);
- a.m_im = 1 / (ma * f);
- b.m_im = 1 / (mb * f);
- m = mc * f;
- }
- else
- {
- a.m_im /= 0.5f;
- m = 1 / a.m_im;
- }
- }
- else
- {
- if (b.m_im > 0)
- {
- b.m_im /= 0.5f;
- m = 1 / b.m_im;
- }
- else
- m = 0;
- }
- appendNode(x, m);
- edges(i, j) = m_nodes.size() - 1;
- m_nodes[edges(i, j)].m_v = v;
- ++newnodes;
- }
- }
- }
- }
- nbase = &m_nodes[0];
- /* Refine links */
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- Link& feat = m_links[i];
- const int idx[] = {int(feat.m_n[0] - nbase),
- int(feat.m_n[1] - nbase)};
- if ((idx[0] < ncount) && (idx[1] < ncount))
- {
- const int ni = edges(idx[0], idx[1]);
- if (ni > 0)
- {
- appendLink(i);
- Link* pft[] = {&m_links[i],
- &m_links[m_links.size() - 1]};
- pft[0]->m_n[0] = &m_nodes[idx[0]];
- pft[0]->m_n[1] = &m_nodes[ni];
- pft[1]->m_n[0] = &m_nodes[ni];
- pft[1]->m_n[1] = &m_nodes[idx[1]];
- }
- }
- }
- /* Refine faces */
- for (i = 0; i < m_faces.size(); ++i)
- {
- const Face& feat = m_faces[i];
- const int idx[] = {int(feat.m_n[0] - nbase),
- int(feat.m_n[1] - nbase),
- int(feat.m_n[2] - nbase)};
- for (j = 2, k = 0; k < 3; j = k++)
- {
- if ((idx[j] < ncount) && (idx[k] < ncount))
- {
- const int ni = edges(idx[j], idx[k]);
- if (ni > 0)
- {
- appendFace(i);
- const int l = (k + 1) % 3;
- Face* pft[] = {&m_faces[i],
- &m_faces[m_faces.size() - 1]};
- pft[0]->m_n[0] = &m_nodes[idx[l]];
- pft[0]->m_n[1] = &m_nodes[idx[j]];
- pft[0]->m_n[2] = &m_nodes[ni];
- pft[1]->m_n[0] = &m_nodes[ni];
- pft[1]->m_n[1] = &m_nodes[idx[k]];
- pft[1]->m_n[2] = &m_nodes[idx[l]];
- appendLink(ni, idx[l], pft[0]->m_material);
- --i;
- break;
- }
- }
- }
- }
- /* Cut */
- if (cut)
- {
- btAlignedObjectArray<int> cnodes;
- const int pcount = ncount;
- int i;
- ncount = m_nodes.size();
- cnodes.resize(ncount, 0);
- /* Nodes */
- for (i = 0; i < ncount; ++i)
- {
- const btVector3 x = m_nodes[i].m_x;
- if ((i >= pcount) || (btFabs(ifn->Eval(x)) < accurary))
- {
- const btVector3 v = m_nodes[i].m_v;
- btScalar m = getMass(i);
- if (m > 0)
- {
- m *= 0.5f;
- m_nodes[i].m_im /= 0.5f;
- }
- appendNode(x, m);
- cnodes[i] = m_nodes.size() - 1;
- m_nodes[cnodes[i]].m_v = v;
- }
- }
- nbase = &m_nodes[0];
- /* Links */
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- const int id[] = {int(m_links[i].m_n[0] - nbase),
- int(m_links[i].m_n[1] - nbase)};
- int todetach = 0;
- if (cnodes[id[0]] && cnodes[id[1]])
- {
- appendLink(i);
- todetach = m_links.size() - 1;
- }
- else
- {
- if (((ifn->Eval(m_nodes[id[0]].m_x) < accurary) &&
- (ifn->Eval(m_nodes[id[1]].m_x) < accurary)))
- todetach = i;
- }
- if (todetach)
- {
- Link& l = m_links[todetach];
- for (int j = 0; j < 2; ++j)
- {
- int cn = cnodes[int(l.m_n[j] - nbase)];
- if (cn) l.m_n[j] = &m_nodes[cn];
- }
- }
- }
- /* Faces */
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- Node** n = m_faces[i].m_n;
- if ((ifn->Eval(n[0]->m_x) < accurary) &&
- (ifn->Eval(n[1]->m_x) < accurary) &&
- (ifn->Eval(n[2]->m_x) < accurary))
- {
- for (int j = 0; j < 3; ++j)
- {
- int cn = cnodes[int(n[j] - nbase)];
- if (cn) n[j] = &m_nodes[cn];
- }
- }
- }
- /* Clean orphans */
- int nnodes = m_nodes.size();
- btAlignedObjectArray<int> ranks;
- btAlignedObjectArray<int> todelete;
- ranks.resize(nnodes, 0);
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- for (int j = 0; j < 2; ++j) ranks[int(m_links[i].m_n[j] - nbase)]++;
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- for (int j = 0; j < 3; ++j) ranks[int(m_faces[i].m_n[j] - nbase)]++;
- }
- for (i = 0; i < m_links.size(); ++i)
- {
- const int id[] = {int(m_links[i].m_n[0] - nbase),
- int(m_links[i].m_n[1] - nbase)};
- const bool sg[] = {ranks[id[0]] == 1,
- ranks[id[1]] == 1};
- if (sg[0] || sg[1])
- {
- --ranks[id[0]];
- --ranks[id[1]];
- btSwap(m_links[i], m_links[m_links.size() - 1]);
- m_links.pop_back();
- --i;
- }
- }
-#if 0
- for(i=nnodes-1;i>=0;--i)
- {
- if(!ranks[i]) todelete.push_back(i);
- }
- if(todelete.size())
- {
- btAlignedObjectArray<int>& map=ranks;
- for(int i=0;i<nnodes;++i) map[i]=i;
- PointersToIndices(this);
- for(int i=0,ni=todelete.size();i<ni;++i)
- {
- int j=todelete[i];
- int& a=map[j];
- int& b=map[--nnodes];
- m_ndbvt.remove(m_nodes[a].m_leaf);m_nodes[a].m_leaf=0;
- btSwap(m_nodes[a],m_nodes[b]);
- j=a;a=b;b=j;
- }
- IndicesToPointers(this,&map[0]);
- m_nodes.resize(nnodes);
- }
-#endif
- }
- m_bUpdateRtCst = true;
-}
-
-//
-bool btSoftBody::cutLink(const Node* node0, const Node* node1, btScalar position)
-{
- return (cutLink(int(node0 - &m_nodes[0]), int(node1 - &m_nodes[0]), position));
-}
-
-//
-bool btSoftBody::cutLink(int node0, int node1, btScalar position)
-{
- bool done = false;
- int i, ni;
- // const btVector3 d=m_nodes[node0].m_x-m_nodes[node1].m_x;
- const btVector3 x = Lerp(m_nodes[node0].m_x, m_nodes[node1].m_x, position);
- const btVector3 v = Lerp(m_nodes[node0].m_v, m_nodes[node1].m_v, position);
- const btScalar m = 1;
- appendNode(x, m);
- appendNode(x, m);
- Node* pa = &m_nodes[node0];
- Node* pb = &m_nodes[node1];
- Node* pn[2] = {&m_nodes[m_nodes.size() - 2],
- &m_nodes[m_nodes.size() - 1]};
- pn[0]->m_v = v;
- pn[1]->m_v = v;
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- const int mtch = MatchEdge(m_links[i].m_n[0], m_links[i].m_n[1], pa, pb);
- if (mtch != -1)
- {
- appendLink(i);
- Link* pft[] = {&m_links[i], &m_links[m_links.size() - 1]};
- pft[0]->m_n[1] = pn[mtch];
- pft[1]->m_n[0] = pn[1 - mtch];
- done = true;
- }
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- for (int k = 2, l = 0; l < 3; k = l++)
- {
- const int mtch = MatchEdge(m_faces[i].m_n[k], m_faces[i].m_n[l], pa, pb);
- if (mtch != -1)
- {
- appendFace(i);
- Face* pft[] = {&m_faces[i], &m_faces[m_faces.size() - 1]};
- pft[0]->m_n[l] = pn[mtch];
- pft[1]->m_n[k] = pn[1 - mtch];
- appendLink(pn[0], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
- appendLink(pn[1], pft[0]->m_n[(l + 1) % 3], pft[0]->m_material, true);
- }
- }
- }
- if (!done)
- {
- m_ndbvt.remove(pn[0]->m_leaf);
- m_ndbvt.remove(pn[1]->m_leaf);
- m_nodes.pop_back();
- m_nodes.pop_back();
- }
- return (done);
-}
-
-//
-bool btSoftBody::rayTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results)
-{
- if (m_faces.size() && m_fdbvt.empty())
- initializeFaceTree();
-
- results.body = this;
- results.fraction = 1.f;
- results.feature = eFeature::None;
- results.index = -1;
-
- return (rayTest(rayFrom, rayTo, results.fraction, results.feature, results.index, false) != 0);
-}
-
-bool btSoftBody::rayFaceTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results)
-{
- if (m_faces.size() == 0)
- return false;
- else
- {
- if (m_fdbvt.empty())
- initializeFaceTree();
- }
-
- results.body = this;
- results.fraction = 1.f;
- results.index = -1;
-
- return (rayFaceTest(rayFrom, rayTo, results.fraction, results.index) != 0);
-}
-
-//
-void btSoftBody::setSolver(eSolverPresets::_ preset)
-{
- m_cfg.m_vsequence.clear();
- m_cfg.m_psequence.clear();
- m_cfg.m_dsequence.clear();
- switch (preset)
- {
- case eSolverPresets::Positions:
- m_cfg.m_psequence.push_back(ePSolver::Anchors);
- m_cfg.m_psequence.push_back(ePSolver::RContacts);
- m_cfg.m_psequence.push_back(ePSolver::SContacts);
- m_cfg.m_psequence.push_back(ePSolver::Linear);
- break;
- case eSolverPresets::Velocities:
- m_cfg.m_vsequence.push_back(eVSolver::Linear);
-
- m_cfg.m_psequence.push_back(ePSolver::Anchors);
- m_cfg.m_psequence.push_back(ePSolver::RContacts);
- m_cfg.m_psequence.push_back(ePSolver::SContacts);
-
- m_cfg.m_dsequence.push_back(ePSolver::Linear);
- break;
- }
-}
-
-void btSoftBody::predictMotion(btScalar dt)
-{
- int i, ni;
-
- /* Update */
- if (m_bUpdateRtCst)
- {
- m_bUpdateRtCst = false;
- updateConstants();
- m_fdbvt.clear();
- if (m_cfg.collisions & fCollision::VF_SS)
- {
- initializeFaceTree();
- }
- }
-
- /* Prepare */
- m_sst.sdt = dt * m_cfg.timescale;
- m_sst.isdt = 1 / m_sst.sdt;
- m_sst.velmrg = m_sst.sdt * 3;
- m_sst.radmrg = getCollisionShape()->getMargin();
- m_sst.updmrg = m_sst.radmrg * (btScalar)0.25;
- /* Forces */
- addVelocity(m_worldInfo->m_gravity * m_sst.sdt);
- applyForces();
- /* Integrate */
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_q = n.m_x;
- btVector3 deltaV = n.m_f * n.m_im * m_sst.sdt;
- {
- btScalar maxDisplacement = m_worldInfo->m_maxDisplacement;
- btScalar clampDeltaV = maxDisplacement / m_sst.sdt;
- for (int c = 0; c < 3; c++)
- {
- if (deltaV[c] > clampDeltaV)
- {
- deltaV[c] = clampDeltaV;
- }
- if (deltaV[c] < -clampDeltaV)
- {
- deltaV[c] = -clampDeltaV;
- }
- }
- }
- n.m_v += deltaV;
- n.m_x += n.m_v * m_sst.sdt;
- n.m_f = btVector3(0, 0, 0);
- }
- /* Clusters */
- updateClusters();
- /* Bounds */
- updateBounds();
- /* Nodes */
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- vol = btDbvtVolume::FromCR(n.m_x, m_sst.radmrg);
- m_ndbvt.update(n.m_leaf,
- vol,
- n.m_v * m_sst.velmrg,
- m_sst.updmrg);
- }
- /* Faces */
- if (!m_fdbvt.empty())
- {
- for (int i = 0; i < m_faces.size(); ++i)
- {
- Face& f = m_faces[i];
- const btVector3 v = (f.m_n[0]->m_v +
- f.m_n[1]->m_v +
- f.m_n[2]->m_v) /
- 3;
- vol = VolumeOf(f, m_sst.radmrg);
- m_fdbvt.update(f.m_leaf,
- vol,
- v * m_sst.velmrg,
- m_sst.updmrg);
- }
- }
- /* Pose */
- updatePose();
- /* Match */
- if (m_pose.m_bframe && (m_cfg.kMT > 0))
- {
- const btMatrix3x3 posetrs = m_pose.m_rot;
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- if (n.m_im > 0)
- {
- const btVector3 x = posetrs * m_pose.m_pos[i] + m_pose.m_com;
- n.m_x = Lerp(n.m_x, x, m_cfg.kMT);
- }
- }
- }
- /* Clear contacts */
- m_rcontacts.resize(0);
- m_scontacts.resize(0);
- /* Optimize dbvt's */
- m_ndbvt.optimizeIncremental(1);
- m_fdbvt.optimizeIncremental(1);
- m_cdbvt.optimizeIncremental(1);
-}
-
-//
-void btSoftBody::solveConstraints()
-{
- /* Apply clusters */
- applyClusters(false);
- /* Prepare links */
-
- int i, ni;
-
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- Link& l = m_links[i];
- l.m_c3 = l.m_n[1]->m_q - l.m_n[0]->m_q;
- l.m_c2 = 1 / (l.m_c3.length2() * l.m_c0);
- }
- /* Prepare anchors */
- for (i = 0, ni = m_anchors.size(); i < ni; ++i)
- {
- Anchor& a = m_anchors[i];
- const btVector3 ra = a.m_body->getWorldTransform().getBasis() * a.m_local;
- a.m_c0 = ImpulseMatrix(m_sst.sdt,
- a.m_node->m_im,
- a.m_body->getInvMass(),
- a.m_body->getInvInertiaTensorWorld(),
- ra);
- a.m_c1 = ra;
- a.m_c2 = m_sst.sdt * a.m_node->m_im;
- a.m_body->activate();
- }
- /* Solve velocities */
- if (m_cfg.viterations > 0)
- {
- /* Solve */
- for (int isolve = 0; isolve < m_cfg.viterations; ++isolve)
- {
- for (int iseq = 0; iseq < m_cfg.m_vsequence.size(); ++iseq)
- {
- getSolver(m_cfg.m_vsequence[iseq])(this, 1);
- }
- }
- /* Update */
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_x = n.m_q + n.m_v * m_sst.sdt;
- }
- }
- /* Solve positions */
- if (m_cfg.piterations > 0)
- {
- for (int isolve = 0; isolve < m_cfg.piterations; ++isolve)
- {
- const btScalar ti = isolve / (btScalar)m_cfg.piterations;
- for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
- {
- getSolver(m_cfg.m_psequence[iseq])(this, 1, ti);
- }
- }
- const btScalar vc = m_sst.isdt * (1 - m_cfg.kDP);
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_v = (n.m_x - n.m_q) * vc;
- n.m_f = btVector3(0, 0, 0);
- }
- }
- /* Solve drift */
- if (m_cfg.diterations > 0)
- {
- const btScalar vcf = m_cfg.kVCF * m_sst.isdt;
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_q = n.m_x;
- }
- for (int idrift = 0; idrift < m_cfg.diterations; ++idrift)
- {
- for (int iseq = 0; iseq < m_cfg.m_dsequence.size(); ++iseq)
- {
- getSolver(m_cfg.m_dsequence[iseq])(this, 1, 0);
- }
- }
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- Node& n = m_nodes[i];
- n.m_v += (n.m_x - n.m_q) * vcf;
- }
- }
- /* Apply clusters */
- dampClusters();
- applyClusters(true);
-}
-
-//
-void btSoftBody::staticSolve(int iterations)
-{
- for (int isolve = 0; isolve < iterations; ++isolve)
- {
- for (int iseq = 0; iseq < m_cfg.m_psequence.size(); ++iseq)
- {
- getSolver(m_cfg.m_psequence[iseq])(this, 1, 0);
- }
- }
-}
-
-//
-void btSoftBody::solveCommonConstraints(btSoftBody** /*bodies*/, int /*count*/, int /*iterations*/)
-{
- /// placeholder
-}
-
-//
-void btSoftBody::solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies)
-{
- const int nb = bodies.size();
- int iterations = 0;
- int i;
-
- for (i = 0; i < nb; ++i)
- {
- iterations = btMax(iterations, bodies[i]->m_cfg.citerations);
- }
- for (i = 0; i < nb; ++i)
- {
- bodies[i]->prepareClusters(iterations);
- }
- for (i = 0; i < iterations; ++i)
- {
- const btScalar sor = 1;
- for (int j = 0; j < nb; ++j)
- {
- bodies[j]->solveClusters(sor);
- }
- }
- for (i = 0; i < nb; ++i)
- {
- bodies[i]->cleanupClusters();
- }
-}
-
-//
-void btSoftBody::integrateMotion()
-{
- /* Update */
- updateNormals();
-}
-
-//
-btSoftBody::RayFromToCaster::RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt)
-{
- m_rayFrom = rayFrom;
- m_rayNormalizedDirection = (rayTo - rayFrom);
- m_rayTo = rayTo;
- m_mint = mxt;
- m_face = 0;
- m_tests = 0;
-}
-
-//
-void btSoftBody::RayFromToCaster::Process(const btDbvtNode* leaf)
-{
- btSoftBody::Face& f = *(btSoftBody::Face*)leaf->data;
- const btScalar t = rayFromToTriangle(m_rayFrom, m_rayTo, m_rayNormalizedDirection,
- f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- m_mint);
- if ((t > 0) && (t < m_mint))
- {
- m_mint = t;
- m_face = &f;
- }
- ++m_tests;
-}
-
-//
-btScalar btSoftBody::RayFromToCaster::rayFromToTriangle(const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayNormalizedDirection,
- const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar maxt)
-{
- static const btScalar ceps = -SIMD_EPSILON * 10;
- static const btScalar teps = SIMD_EPSILON * 10;
-
- const btVector3 n = btCross(b - a, c - a);
- const btScalar d = btDot(a, n);
- const btScalar den = btDot(rayNormalizedDirection, n);
- if (!btFuzzyZero(den))
- {
- const btScalar num = btDot(rayFrom, n) - d;
- const btScalar t = -num / den;
- if ((t > teps) && (t < maxt))
- {
- const btVector3 hit = rayFrom + rayNormalizedDirection * t;
- if ((btDot(n, btCross(a - hit, b - hit)) > ceps) &&
- (btDot(n, btCross(b - hit, c - hit)) > ceps) &&
- (btDot(n, btCross(c - hit, a - hit)) > ceps))
- {
- return (t);
- }
- }
- }
- return (-1);
-}
-
-//
-void btSoftBody::pointersToIndices()
-{
-#define PTR2IDX(_p_, _b_) reinterpret_cast<btSoftBody::Node*>((_p_) - (_b_))
- btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
- int i, ni;
-
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- if (m_nodes[i].m_leaf)
- {
- m_nodes[i].m_leaf->data = *(void**)&i;
- }
- }
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- m_links[i].m_n[0] = PTR2IDX(m_links[i].m_n[0], base);
- m_links[i].m_n[1] = PTR2IDX(m_links[i].m_n[1], base);
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- m_faces[i].m_n[0] = PTR2IDX(m_faces[i].m_n[0], base);
- m_faces[i].m_n[1] = PTR2IDX(m_faces[i].m_n[1], base);
- m_faces[i].m_n[2] = PTR2IDX(m_faces[i].m_n[2], base);
- if (m_faces[i].m_leaf)
- {
- m_faces[i].m_leaf->data = *(void**)&i;
- }
- }
- for (i = 0, ni = m_anchors.size(); i < ni; ++i)
- {
- m_anchors[i].m_node = PTR2IDX(m_anchors[i].m_node, base);
- }
- for (i = 0, ni = m_notes.size(); i < ni; ++i)
- {
- for (int j = 0; j < m_notes[i].m_rank; ++j)
- {
- m_notes[i].m_nodes[j] = PTR2IDX(m_notes[i].m_nodes[j], base);
- }
- }
-#undef PTR2IDX
-}
-
-//
-void btSoftBody::indicesToPointers(const int* map)
-{
-#define IDX2PTR(_p_, _b_) map ? (&(_b_)[map[(((char*)_p_) - (char*)0)]]) : (&(_b_)[(((char*)_p_) - (char*)0)])
- btSoftBody::Node* base = m_nodes.size() ? &m_nodes[0] : 0;
- int i, ni;
-
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- if (m_nodes[i].m_leaf)
- {
- m_nodes[i].m_leaf->data = &m_nodes[i];
- }
- }
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- m_links[i].m_n[0] = IDX2PTR(m_links[i].m_n[0], base);
- m_links[i].m_n[1] = IDX2PTR(m_links[i].m_n[1], base);
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- m_faces[i].m_n[0] = IDX2PTR(m_faces[i].m_n[0], base);
- m_faces[i].m_n[1] = IDX2PTR(m_faces[i].m_n[1], base);
- m_faces[i].m_n[2] = IDX2PTR(m_faces[i].m_n[2], base);
- if (m_faces[i].m_leaf)
- {
- m_faces[i].m_leaf->data = &m_faces[i];
- }
- }
- for (i = 0, ni = m_anchors.size(); i < ni; ++i)
- {
- m_anchors[i].m_node = IDX2PTR(m_anchors[i].m_node, base);
- }
- for (i = 0, ni = m_notes.size(); i < ni; ++i)
- {
- for (int j = 0; j < m_notes[i].m_rank; ++j)
- {
- m_notes[i].m_nodes[j] = IDX2PTR(m_notes[i].m_nodes[j], base);
- }
- }
-#undef IDX2PTR
-}
-
-//
-int btSoftBody::rayTest(const btVector3& rayFrom, const btVector3& rayTo,
- btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const
-{
- int cnt = 0;
- btVector3 dir = rayTo - rayFrom;
-
- if (bcountonly || m_fdbvt.empty())
- { /* Full search */
-
- for (int i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- const btSoftBody::Face& f = m_faces[i];
-
- const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
- f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- mint);
- if (t > 0)
- {
- ++cnt;
- if (!bcountonly)
- {
- feature = btSoftBody::eFeature::Face;
- index = i;
- mint = t;
- }
- }
- }
- }
- else
- { /* Use dbvt */
- RayFromToCaster collider(rayFrom, rayTo, mint);
-
- btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
- if (collider.m_face)
- {
- mint = collider.m_mint;
- feature = btSoftBody::eFeature::Face;
- index = (int)(collider.m_face - &m_faces[0]);
- cnt = 1;
- }
- }
-
- for (int i = 0; i < m_tetras.size(); i++)
- {
- const btSoftBody::Tetra& tet = m_tetras[i];
- int tetfaces[4][3] = {{0, 1, 2}, {0, 1, 3}, {1, 2, 3}, {0, 2, 3}};
- for (int f = 0; f < 4; f++)
- {
- int index0 = tetfaces[f][0];
- int index1 = tetfaces[f][1];
- int index2 = tetfaces[f][2];
- btVector3 v0 = tet.m_n[index0]->m_x;
- btVector3 v1 = tet.m_n[index1]->m_x;
- btVector3 v2 = tet.m_n[index2]->m_x;
-
- const btScalar t = RayFromToCaster::rayFromToTriangle(rayFrom, rayTo, dir,
- v0, v1, v2,
- mint);
- if (t > 0)
- {
- ++cnt;
- if (!bcountonly)
- {
- feature = btSoftBody::eFeature::Tetra;
- index = i;
- mint = t;
- }
- }
- }
- }
- return (cnt);
-}
-
-int btSoftBody::rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
- btScalar& mint, int& index) const
-{
- int cnt = 0;
- { /* Use dbvt */
- RayFromToCaster collider(rayFrom, rayTo, mint);
-
- btDbvt::rayTest(m_fdbvt.m_root, rayFrom, rayTo, collider);
- if (collider.m_face)
- {
- mint = collider.m_mint;
- index = (int)(collider.m_face - &m_faces[0]);
- cnt = 1;
- }
- }
- return (cnt);
-}
-
-//
-static inline btDbvntNode* copyToDbvnt(const btDbvtNode* n)
-{
- if (n == 0)
- return 0;
- btDbvntNode* root = new btDbvntNode(n);
- if (n->isinternal())
- {
- btDbvntNode* c0 = copyToDbvnt(n->childs[0]);
- root->childs[0] = c0;
- btDbvntNode* c1 = copyToDbvnt(n->childs[1]);
- root->childs[1] = c1;
- }
- return root;
-}
-
-static inline void calculateNormalCone(btDbvntNode* root)
-{
- if (!root)
- return;
- if (root->isleaf())
- {
- const btSoftBody::Face* face = (btSoftBody::Face*)root->data;
- root->normal = face->m_normal;
- root->angle = 0;
- }
- else
- {
- btVector3 n0(0, 0, 0), n1(0, 0, 0);
- btScalar a0 = 0, a1 = 0;
- if (root->childs[0])
- {
- calculateNormalCone(root->childs[0]);
- n0 = root->childs[0]->normal;
- a0 = root->childs[0]->angle;
- }
- if (root->childs[1])
- {
- calculateNormalCone(root->childs[1]);
- n1 = root->childs[1]->normal;
- a1 = root->childs[1]->angle;
- }
- root->normal = (n0 + n1).safeNormalize();
- root->angle = btMax(a0, a1) + btAngle(n0, n1) * 0.5;
- }
-}
-
-void btSoftBody::initializeFaceTree()
-{
- BT_PROFILE("btSoftBody::initializeFaceTree");
- m_fdbvt.clear();
- // create leaf nodes;
- btAlignedObjectArray<btDbvtNode*> leafNodes;
- leafNodes.resize(m_faces.size());
- for (int i = 0; i < m_faces.size(); ++i)
- {
- Face& f = m_faces[i];
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol = VolumeOf(f, 0);
- btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
- node->parent = NULL;
- node->data = &f;
- node->childs[1] = 0;
- node->volume = vol;
- leafNodes[i] = node;
- f.m_leaf = node;
- }
- btAlignedObjectArray<btAlignedObjectArray<int> > adj;
- adj.resize(m_faces.size());
- // construct the adjacency list for triangles
- for (int i = 0; i < adj.size(); ++i)
- {
- for (int j = i + 1; j < adj.size(); ++j)
- {
- int dup = 0;
- for (int k = 0; k < 3; ++k)
- {
- for (int l = 0; l < 3; ++l)
- {
- if (m_faces[i].m_n[k] == m_faces[j].m_n[l])
- {
- ++dup;
- break;
- }
- }
- if (dup == 2)
- {
- adj[i].push_back(j);
- adj[j].push_back(i);
- }
- }
- }
- }
- m_fdbvt.m_root = buildTreeBottomUp(leafNodes, adj);
- if (m_fdbvnt)
- delete m_fdbvnt;
- m_fdbvnt = copyToDbvnt(m_fdbvt.m_root);
- updateFaceTree(false, false);
- rebuildNodeTree();
-}
-
-//
-void btSoftBody::rebuildNodeTree()
-{
- m_ndbvt.clear();
- btAlignedObjectArray<btDbvtNode*> leafNodes;
- leafNodes.resize(m_nodes.size());
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- Node& n = m_nodes[i];
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol = btDbvtVolume::FromCR(n.m_x, 0);
- btDbvtNode* node = new (btAlignedAlloc(sizeof(btDbvtNode), 16)) btDbvtNode();
- node->parent = NULL;
- node->data = &n;
- node->childs[1] = 0;
- node->volume = vol;
- leafNodes[i] = node;
- n.m_leaf = node;
- }
- btAlignedObjectArray<btAlignedObjectArray<int> > adj;
- adj.resize(m_nodes.size());
- btAlignedObjectArray<int> old_id;
- old_id.resize(m_nodes.size());
- for (int i = 0; i < m_nodes.size(); ++i)
- old_id[i] = m_nodes[i].index;
- for (int i = 0; i < m_nodes.size(); ++i)
- m_nodes[i].index = i;
- for (int i = 0; i < m_links.size(); ++i)
- {
- Link& l = m_links[i];
- adj[l.m_n[0]->index].push_back(l.m_n[1]->index);
- adj[l.m_n[1]->index].push_back(l.m_n[0]->index);
- }
- m_ndbvt.m_root = buildTreeBottomUp(leafNodes, adj);
- for (int i = 0; i < m_nodes.size(); ++i)
- m_nodes[i].index = old_id[i];
-}
-
-//
-btVector3 btSoftBody::evaluateCom() const
-{
- btVector3 com(0, 0, 0);
- if (m_pose.m_bframe)
- {
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- com += m_nodes[i].m_x * m_pose.m_wgh[i];
- }
- }
- return (com);
-}
-
-bool btSoftBody::checkContact(const btCollisionObjectWrapper* colObjWrap,
- const btVector3& x,
- btScalar margin,
- btSoftBody::sCti& cti) const
-{
- btVector3 nrm;
- const btCollisionShape* shp = colObjWrap->getCollisionShape();
- // const btRigidBody *tmpRigid = btRigidBody::upcast(colObjWrap->getCollisionObject());
- //const btTransform &wtr = tmpRigid ? tmpRigid->getWorldTransform() : colObjWrap->getWorldTransform();
- const btTransform& wtr = colObjWrap->getWorldTransform();
- //todo: check which transform is needed here
-
- btScalar dst =
- m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(x),
- shp,
- nrm,
- margin);
- if (dst < 0)
- {
- cti.m_colObj = colObjWrap->getCollisionObject();
- cti.m_normal = wtr.getBasis() * nrm;
- cti.m_offset = -btDot(cti.m_normal, x - cti.m_normal * dst);
- return (true);
- }
- return (false);
-}
-
-//
-bool btSoftBody::checkDeformableContact(const btCollisionObjectWrapper* colObjWrap,
- const btVector3& x,
- btScalar margin,
- btSoftBody::sCti& cti, bool predict) const
-{
- btVector3 nrm;
- const btCollisionShape* shp = colObjWrap->getCollisionShape();
- const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
- // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
- // but resolve contact at x_n
- btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
- : colObjWrap->getWorldTransform();
- btScalar dst =
- m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(x),
- shp,
- nrm,
- margin);
-
- if (!predict)
- {
- cti.m_colObj = colObjWrap->getCollisionObject();
- cti.m_normal = wtr.getBasis() * nrm;
- cti.m_offset = dst;
- }
- if (dst < 0)
- return true;
- return (false);
-}
-
-//
-// Compute barycentric coordinates (u, v, w) for
-// point p with respect to triangle (a, b, c)
-static void getBarycentric(const btVector3& p, btVector3& a, btVector3& b, btVector3& c, btVector3& bary)
-{
- btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
- btScalar d00 = v0.dot(v0);
- btScalar d01 = v0.dot(v1);
- btScalar d11 = v1.dot(v1);
- btScalar d20 = v2.dot(v0);
- btScalar d21 = v2.dot(v1);
- btScalar denom = d00 * d11 - d01 * d01;
- bary.setY((d11 * d20 - d01 * d21) / denom);
- bary.setZ((d00 * d21 - d01 * d20) / denom);
- bary.setX(btScalar(1) - bary.getY() - bary.getZ());
-}
-
-//
-bool btSoftBody::checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap,
- Face& f,
- btVector3& contact_point,
- btVector3& bary,
- btScalar margin,
- btSoftBody::sCti& cti, bool predict) const
-{
- btVector3 nrm;
- const btCollisionShape* shp = colObjWrap->getCollisionShape();
- const btCollisionObject* tmpCollisionObj = colObjWrap->getCollisionObject();
- // use the position x_{n+1}^* = x_n + dt * v_{n+1}^* where v_{n+1}^* = v_n + dtg for collision detect
- // but resolve contact at x_n
- btTransform wtr = (predict) ? (colObjWrap->m_preTransform != NULL ? tmpCollisionObj->getInterpolationWorldTransform() * (*colObjWrap->m_preTransform) : tmpCollisionObj->getInterpolationWorldTransform())
- : colObjWrap->getWorldTransform();
- btScalar dst;
- btGjkEpaSolver2::sResults results;
-
-// #define USE_QUADRATURE 1
-
- // use collision quadrature point
-#ifdef USE_QUADRATURE
- {
- dst = SIMD_INFINITY;
- btVector3 local_nrm;
- for (int q = 0; q < m_quads.size(); ++q)
- {
- btVector3 p;
- if (predict)
- p = BaryEval(f.m_n[0]->m_q, f.m_n[1]->m_q, f.m_n[2]->m_q, m_quads[q]);
- else
- p = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, m_quads[q]);
- btScalar local_dst = m_worldInfo->m_sparsesdf.Evaluate(
- wtr.invXform(p),
- shp,
- local_nrm,
- margin);
- if (local_dst < dst)
- {
- if (local_dst < 0 && predict)
- return true;
- dst = local_dst;
- contact_point = p;
- bary = m_quads[q];
- nrm = local_nrm;
- }
- if (!predict)
- {
- cti.m_colObj = colObjWrap->getCollisionObject();
- cti.m_normal = wtr.getBasis() * nrm;
- cti.m_offset = dst;
- }
- }
- return (dst < 0);
- }
-#endif
-
- // collision detection using x*
- btTransform triangle_transform;
- triangle_transform.setIdentity();
- triangle_transform.setOrigin(f.m_n[0]->m_q);
- btTriangleShape triangle(btVector3(0, 0, 0), f.m_n[1]->m_q - f.m_n[0]->m_q, f.m_n[2]->m_q - f.m_n[0]->m_q);
- btVector3 guess(0, 0, 0);
- const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
- btGjkEpaSolver2::SignedDistance(&triangle, triangle_transform, csh, wtr, guess, results);
- dst = results.distance - 2.0 * csh->getMargin() - margin; // margin padding so that the distance = the actual distance between face and rigid - margin of rigid - margin of deformable
- if (dst >= 0)
- return false;
-
- // Use consistent barycenter to recalculate distance.
- if (this->m_cacheBarycenter)
- {
- if (f.m_pcontact[3] != 0)
- {
- for (int i = 0; i < 3; ++i)
- bary[i] = f.m_pcontact[i];
- contact_point = BaryEval(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
- const btConvexShape* csh = static_cast<const btConvexShape*>(shp);
- btGjkEpaSolver2::SignedDistance(contact_point, margin, csh, wtr, results);
- cti.m_colObj = colObjWrap->getCollisionObject();
- dst = results.distance;
- cti.m_normal = results.normal;
- cti.m_offset = dst;
-
- //point-convex CD
- wtr = colObjWrap->getWorldTransform();
- btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
- triangle_transform.setOrigin(f.m_n[0]->m_x);
- btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
-
- dst = results.distance - csh->getMargin() - margin;
- return true;
- }
- }
-
- // Use triangle-convex CD.
- wtr = colObjWrap->getWorldTransform();
- btTriangleShape triangle2(btVector3(0, 0, 0), f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
- triangle_transform.setOrigin(f.m_n[0]->m_x);
- btGjkEpaSolver2::SignedDistance(&triangle2, triangle_transform, csh, wtr, guess, results);
- contact_point = results.witnesses[0];
- getBarycentric(contact_point, f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, bary);
-
- for (int i = 0; i < 3; ++i)
- f.m_pcontact[i] = bary[i];
-
- dst = results.distance - csh->getMargin() - margin;
- cti.m_colObj = colObjWrap->getCollisionObject();
- cti.m_normal = results.normal;
- cti.m_offset = dst;
- return true;
-}
-
-void btSoftBody::updateNormals()
-{
- const btVector3 zv(0, 0, 0);
- int i, ni;
-
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- m_nodes[i].m_n = zv;
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- btSoftBody::Face& f = m_faces[i];
- const btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x,
- f.m_n[2]->m_x - f.m_n[0]->m_x);
- f.m_normal = n;
- f.m_normal.safeNormalize();
- f.m_n[0]->m_n += n;
- f.m_n[1]->m_n += n;
- f.m_n[2]->m_n += n;
- }
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- btScalar len = m_nodes[i].m_n.length();
- if (len > SIMD_EPSILON)
- m_nodes[i].m_n /= len;
- }
-}
-
-//
-void btSoftBody::updateBounds()
-{
- /*if( m_acceleratedSoftBody )
- {
- // If we have an accelerated softbody we need to obtain the bounds correctly
- // For now (slightly hackily) just have a very large AABB
- // TODO: Write get bounds kernel
- // If that is updating in place, atomic collisions might be low (when the cloth isn't perfectly aligned to an axis) and we could
- // probably do a test and exchange reasonably efficiently.
-
- m_bounds[0] = btVector3(-1000, -1000, -1000);
- m_bounds[1] = btVector3(1000, 1000, 1000);
-
- } else {*/
- // if (m_ndbvt.m_root)
- // {
- // const btVector3& mins = m_ndbvt.m_root->volume.Mins();
- // const btVector3& maxs = m_ndbvt.m_root->volume.Maxs();
- // const btScalar csm = getCollisionShape()->getMargin();
- // const btVector3 mrg = btVector3(csm,
- // csm,
- // csm) *
- // 1; // ??? to investigate...
- // m_bounds[0] = mins - mrg;
- // m_bounds[1] = maxs + mrg;
- // if (0 != getBroadphaseHandle())
- // {
- // m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
- // m_bounds[0],
- // m_bounds[1],
- // m_worldInfo->m_dispatcher);
- // }
- // }
- // else
- // {
- // m_bounds[0] =
- // m_bounds[1] = btVector3(0, 0, 0);
- // }
- if (m_nodes.size())
- {
- btVector3 mins = m_nodes[0].m_x;
- btVector3 maxs = m_nodes[0].m_x;
- for (int i = 1; i < m_nodes.size(); ++i)
- {
- for (int d = 0; d < 3; ++d)
- {
- if (m_nodes[i].m_x[d] > maxs[d])
- maxs[d] = m_nodes[i].m_x[d];
- if (m_nodes[i].m_x[d] < mins[d])
- mins[d] = m_nodes[i].m_x[d];
- }
- }
- const btScalar csm = getCollisionShape()->getMargin();
- const btVector3 mrg = btVector3(csm,
- csm,
- csm);
- m_bounds[0] = mins - mrg;
- m_bounds[1] = maxs + mrg;
- if (0 != getBroadphaseHandle())
- {
- m_worldInfo->m_broadphase->setAabb(getBroadphaseHandle(),
- m_bounds[0],
- m_bounds[1],
- m_worldInfo->m_dispatcher);
- }
- }
- else
- {
- m_bounds[0] =
- m_bounds[1] = btVector3(0, 0, 0);
- }
-}
-
-//
-void btSoftBody::updatePose()
-{
- if (m_pose.m_bframe)
- {
- btSoftBody::Pose& pose = m_pose;
- const btVector3 com = evaluateCom();
- /* Com */
- pose.m_com = com;
- /* Rotation */
- btMatrix3x3 Apq;
- const btScalar eps = SIMD_EPSILON;
- Apq[0] = Apq[1] = Apq[2] = btVector3(0, 0, 0);
- Apq[0].setX(eps);
- Apq[1].setY(eps * 2);
- Apq[2].setZ(eps * 3);
- for (int i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- const btVector3 a = pose.m_wgh[i] * (m_nodes[i].m_x - com);
- const btVector3& b = pose.m_pos[i];
- Apq[0] += a.x() * b;
- Apq[1] += a.y() * b;
- Apq[2] += a.z() * b;
- }
- btMatrix3x3 r, s;
- PolarDecompose(Apq, r, s);
- pose.m_rot = r;
- pose.m_scl = pose.m_aqq * r.transpose() * Apq;
- if (m_cfg.maxvolume > 1)
- {
- const btScalar idet = Clamp<btScalar>(1 / pose.m_scl.determinant(),
- 1, m_cfg.maxvolume);
- pose.m_scl = Mul(pose.m_scl, idet);
- }
- }
-}
-
-//
-void btSoftBody::updateArea(bool averageArea)
-{
- int i, ni;
-
- /* Face area */
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- Face& f = m_faces[i];
- f.m_ra = AreaOf(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x);
- }
-
- /* Node area */
-
- if (averageArea)
- {
- btAlignedObjectArray<int> counts;
- counts.resize(m_nodes.size(), 0);
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- m_nodes[i].m_area = 0;
- }
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- btSoftBody::Face& f = m_faces[i];
- for (int j = 0; j < 3; ++j)
- {
- const int index = (int)(f.m_n[j] - &m_nodes[0]);
- counts[index]++;
- f.m_n[j]->m_area += btFabs(f.m_ra);
- }
- }
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- if (counts[i] > 0)
- m_nodes[i].m_area /= (btScalar)counts[i];
- else
- m_nodes[i].m_area = 0;
- }
- }
- else
- {
- // initialize node area as zero
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- m_nodes[i].m_area = 0;
- }
-
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- btSoftBody::Face& f = m_faces[i];
-
- for (int j = 0; j < 3; ++j)
- {
- f.m_n[j]->m_area += f.m_ra;
- }
- }
-
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- m_nodes[i].m_area *= 0.3333333f;
- }
- }
-}
-
-void btSoftBody::updateLinkConstants()
-{
- int i, ni;
-
- /* Links */
- for (i = 0, ni = m_links.size(); i < ni; ++i)
- {
- Link& l = m_links[i];
- Material& m = *l.m_material;
- l.m_c0 = (l.m_n[0]->m_im + l.m_n[1]->m_im) / m.m_kLST;
- }
-}
-
-void btSoftBody::updateConstants()
-{
- resetLinkRestLengths();
- updateLinkConstants();
- updateArea();
-}
-
-//
-void btSoftBody::initializeClusters()
-{
- int i;
-
- for (i = 0; i < m_clusters.size(); ++i)
- {
- Cluster& c = *m_clusters[i];
- c.m_imass = 0;
- c.m_masses.resize(c.m_nodes.size());
- for (int j = 0; j < c.m_nodes.size(); ++j)
- {
- if (c.m_nodes[j]->m_im == 0)
- {
- c.m_containsAnchor = true;
- c.m_masses[j] = BT_LARGE_FLOAT;
- }
- else
- {
- c.m_masses[j] = btScalar(1.) / c.m_nodes[j]->m_im;
- }
- c.m_imass += c.m_masses[j];
- }
- c.m_imass = btScalar(1.) / c.m_imass;
- c.m_com = btSoftBody::clusterCom(&c);
- c.m_lv = btVector3(0, 0, 0);
- c.m_av = btVector3(0, 0, 0);
- c.m_leaf = 0;
- /* Inertia */
- btMatrix3x3& ii = c.m_locii;
- ii[0] = ii[1] = ii[2] = btVector3(0, 0, 0);
- {
- int i, ni;
-
- for (i = 0, ni = c.m_nodes.size(); i < ni; ++i)
- {
- const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
- const btVector3 q = k * k;
- const btScalar m = c.m_masses[i];
- ii[0][0] += m * (q[1] + q[2]);
- ii[1][1] += m * (q[0] + q[2]);
- ii[2][2] += m * (q[0] + q[1]);
- ii[0][1] -= m * k[0] * k[1];
- ii[0][2] -= m * k[0] * k[2];
- ii[1][2] -= m * k[1] * k[2];
- }
- }
- ii[1][0] = ii[0][1];
- ii[2][0] = ii[0][2];
- ii[2][1] = ii[1][2];
-
- ii = ii.inverse();
-
- /* Frame */
- c.m_framexform.setIdentity();
- c.m_framexform.setOrigin(c.m_com);
- c.m_framerefs.resize(c.m_nodes.size());
- {
- int i;
- for (i = 0; i < c.m_framerefs.size(); ++i)
- {
- c.m_framerefs[i] = c.m_nodes[i]->m_x - c.m_com;
- }
- }
- }
-}
-
-//
-void btSoftBody::updateClusters()
-{
- BT_PROFILE("UpdateClusters");
- int i;
-
- for (i = 0; i < m_clusters.size(); ++i)
- {
- btSoftBody::Cluster& c = *m_clusters[i];
- const int n = c.m_nodes.size();
- //const btScalar invn=1/(btScalar)n;
- if (n)
- {
- /* Frame */
- const btScalar eps = btScalar(0.0001);
- btMatrix3x3 m, r, s;
- m[0] = m[1] = m[2] = btVector3(0, 0, 0);
- m[0][0] = eps * 1;
- m[1][1] = eps * 2;
- m[2][2] = eps * 3;
- c.m_com = clusterCom(&c);
- for (int i = 0; i < c.m_nodes.size(); ++i)
- {
- const btVector3 a = c.m_nodes[i]->m_x - c.m_com;
- const btVector3& b = c.m_framerefs[i];
- m[0] += a[0] * b;
- m[1] += a[1] * b;
- m[2] += a[2] * b;
- }
- PolarDecompose(m, r, s);
- c.m_framexform.setOrigin(c.m_com);
- c.m_framexform.setBasis(r);
- /* Inertia */
-#if 1 /* Constant */
- c.m_invwi = c.m_framexform.getBasis() * c.m_locii * c.m_framexform.getBasis().transpose();
-#else
-#if 0 /* Sphere */
- const btScalar rk=(2*c.m_extents.length2())/(5*c.m_imass);
- const btVector3 inertia(rk,rk,rk);
- const btVector3 iin(btFabs(inertia[0])>SIMD_EPSILON?1/inertia[0]:0,
- btFabs(inertia[1])>SIMD_EPSILON?1/inertia[1]:0,
- btFabs(inertia[2])>SIMD_EPSILON?1/inertia[2]:0);
-
- c.m_invwi=c.m_xform.getBasis().scaled(iin)*c.m_xform.getBasis().transpose();
-#else /* Actual */
- c.m_invwi[0] = c.m_invwi[1] = c.m_invwi[2] = btVector3(0, 0, 0);
- for (int i = 0; i < n; ++i)
- {
- const btVector3 k = c.m_nodes[i]->m_x - c.m_com;
- const btVector3 q = k * k;
- const btScalar m = 1 / c.m_nodes[i]->m_im;
- c.m_invwi[0][0] += m * (q[1] + q[2]);
- c.m_invwi[1][1] += m * (q[0] + q[2]);
- c.m_invwi[2][2] += m * (q[0] + q[1]);
- c.m_invwi[0][1] -= m * k[0] * k[1];
- c.m_invwi[0][2] -= m * k[0] * k[2];
- c.m_invwi[1][2] -= m * k[1] * k[2];
- }
- c.m_invwi[1][0] = c.m_invwi[0][1];
- c.m_invwi[2][0] = c.m_invwi[0][2];
- c.m_invwi[2][1] = c.m_invwi[1][2];
- c.m_invwi = c.m_invwi.inverse();
-#endif
-#endif
- /* Velocities */
- c.m_lv = btVector3(0, 0, 0);
- c.m_av = btVector3(0, 0, 0);
- {
- int i;
-
- for (i = 0; i < n; ++i)
- {
- const btVector3 v = c.m_nodes[i]->m_v * c.m_masses[i];
- c.m_lv += v;
- c.m_av += btCross(c.m_nodes[i]->m_x - c.m_com, v);
- }
- }
- c.m_lv = c.m_imass * c.m_lv * (1 - c.m_ldamping);
- c.m_av = c.m_invwi * c.m_av * (1 - c.m_adamping);
- c.m_vimpulses[0] =
- c.m_vimpulses[1] = btVector3(0, 0, 0);
- c.m_dimpulses[0] =
- c.m_dimpulses[1] = btVector3(0, 0, 0);
- c.m_nvimpulses = 0;
- c.m_ndimpulses = 0;
- /* Matching */
- if (c.m_matching > 0)
- {
- for (int j = 0; j < c.m_nodes.size(); ++j)
- {
- Node& n = *c.m_nodes[j];
- const btVector3 x = c.m_framexform * c.m_framerefs[j];
- n.m_x = Lerp(n.m_x, x, c.m_matching);
- }
- }
- /* Dbvt */
- if (c.m_collide)
- {
- btVector3 mi = c.m_nodes[0]->m_x;
- btVector3 mx = mi;
- for (int j = 1; j < n; ++j)
- {
- mi.setMin(c.m_nodes[j]->m_x);
- mx.setMax(c.m_nodes[j]->m_x);
- }
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- bounds = btDbvtVolume::FromMM(mi, mx);
- if (c.m_leaf)
- m_cdbvt.update(c.m_leaf, bounds, c.m_lv * m_sst.sdt * 3, m_sst.radmrg);
- else
- c.m_leaf = m_cdbvt.insert(bounds, &c);
- }
- }
- }
-}
-
-//
-void btSoftBody::cleanupClusters()
-{
- for (int i = 0; i < m_joints.size(); ++i)
- {
- m_joints[i]->Terminate(m_sst.sdt);
- if (m_joints[i]->m_delete)
- {
- btAlignedFree(m_joints[i]);
- m_joints.remove(m_joints[i--]);
- }
- }
-}
-
-//
-void btSoftBody::prepareClusters(int iterations)
-{
- for (int i = 0; i < m_joints.size(); ++i)
- {
- m_joints[i]->Prepare(m_sst.sdt, iterations);
- }
-}
-
-//
-void btSoftBody::solveClusters(btScalar sor)
-{
- for (int i = 0, ni = m_joints.size(); i < ni; ++i)
- {
- m_joints[i]->Solve(m_sst.sdt, sor);
- }
-}
-
-//
-void btSoftBody::applyClusters(bool drift)
-{
- BT_PROFILE("ApplyClusters");
- // const btScalar f0=m_sst.sdt;
- //const btScalar f1=f0/2;
- btAlignedObjectArray<btVector3> deltas;
- btAlignedObjectArray<btScalar> weights;
- deltas.resize(m_nodes.size(), btVector3(0, 0, 0));
- weights.resize(m_nodes.size(), 0);
- int i;
-
- if (drift)
- {
- for (i = 0; i < m_clusters.size(); ++i)
- {
- Cluster& c = *m_clusters[i];
- if (c.m_ndimpulses)
- {
- c.m_dimpulses[0] /= (btScalar)c.m_ndimpulses;
- c.m_dimpulses[1] /= (btScalar)c.m_ndimpulses;
- }
- }
- }
-
- for (i = 0; i < m_clusters.size(); ++i)
- {
- Cluster& c = *m_clusters[i];
- if (0 < (drift ? c.m_ndimpulses : c.m_nvimpulses))
- {
- const btVector3 v = (drift ? c.m_dimpulses[0] : c.m_vimpulses[0]) * m_sst.sdt;
- const btVector3 w = (drift ? c.m_dimpulses[1] : c.m_vimpulses[1]) * m_sst.sdt;
- for (int j = 0; j < c.m_nodes.size(); ++j)
- {
- const int idx = int(c.m_nodes[j] - &m_nodes[0]);
- const btVector3& x = c.m_nodes[j]->m_x;
- const btScalar q = c.m_masses[j];
- deltas[idx] += (v + btCross(w, x - c.m_com)) * q;
- weights[idx] += q;
- }
- }
- }
- for (i = 0; i < deltas.size(); ++i)
- {
- if (weights[i] > 0)
- {
- m_nodes[i].m_x += deltas[i] / weights[i];
- }
- }
-}
-
-//
-void btSoftBody::dampClusters()
-{
- int i;
-
- for (i = 0; i < m_clusters.size(); ++i)
- {
- Cluster& c = *m_clusters[i];
- if (c.m_ndamping > 0)
- {
- for (int j = 0; j < c.m_nodes.size(); ++j)
- {
- Node& n = *c.m_nodes[j];
- if (n.m_im > 0)
- {
- const btVector3 vx = c.m_lv + btCross(c.m_av, c.m_nodes[j]->m_q - c.m_com);
- if (vx.length2() <= n.m_v.length2())
- {
- n.m_v += c.m_ndamping * (vx - n.m_v);
- }
- }
- }
- }
- }
-}
-
-void btSoftBody::setSpringStiffness(btScalar k)
-{
- for (int i = 0; i < m_links.size(); ++i)
- {
- m_links[i].Feature::m_material->m_kLST = k;
- }
- m_repulsionStiffness = k;
-}
-
-void btSoftBody::setGravityFactor(btScalar gravFactor)
-{
- m_gravityFactor = gravFactor;
-}
-
-void btSoftBody::setCacheBarycenter(bool cacheBarycenter)
-{
- m_cacheBarycenter = cacheBarycenter;
-}
-
-void btSoftBody::initializeDmInverse()
-{
- btScalar unit_simplex_measure = 1. / 6.;
-
- for (int i = 0; i < m_tetras.size(); ++i)
- {
- Tetra& t = m_tetras[i];
- btVector3 c1 = t.m_n[1]->m_x - t.m_n[0]->m_x;
- btVector3 c2 = t.m_n[2]->m_x - t.m_n[0]->m_x;
- btVector3 c3 = t.m_n[3]->m_x - t.m_n[0]->m_x;
- btMatrix3x3 Dm(c1.getX(), c2.getX(), c3.getX(),
- c1.getY(), c2.getY(), c3.getY(),
- c1.getZ(), c2.getZ(), c3.getZ());
- t.m_element_measure = Dm.determinant() * unit_simplex_measure;
- t.m_Dm_inverse = Dm.inverse();
-
- // calculate the first three columns of P^{-1}
- btVector3 a = t.m_n[0]->m_x;
- btVector3 b = t.m_n[1]->m_x;
- btVector3 c = t.m_n[2]->m_x;
- btVector3 d = t.m_n[3]->m_x;
-
- btScalar det = 1 / (a[0] * b[1] * c[2] - a[0] * b[1] * d[2] - a[0] * b[2] * c[1] + a[0] * b[2] * d[1] + a[0] * c[1] * d[2] - a[0] * c[2] * d[1] + a[1] * (-b[0] * c[2] + b[0] * d[2] + b[2] * c[0] - b[2] * d[0] - c[0] * d[2] + c[2] * d[0]) + a[2] * (b[0] * c[1] - b[0] * d[1] + b[1] * (d[0] - c[0]) + c[0] * d[1] - c[1] * d[0]) - b[0] * c[1] * d[2] + b[0] * c[2] * d[1] + b[1] * c[0] * d[2] - b[1] * c[2] * d[0] - b[2] * c[0] * d[1] + b[2] * c[1] * d[0]);
-
- btScalar P11 = -b[2] * c[1] + d[2] * c[1] + b[1] * c[2] + b[2] * d[1] - c[2] * d[1] - b[1] * d[2];
- btScalar P12 = b[2] * c[0] - d[2] * c[0] - b[0] * c[2] - b[2] * d[0] + c[2] * d[0] + b[0] * d[2];
- btScalar P13 = -b[1] * c[0] + d[1] * c[0] + b[0] * c[1] + b[1] * d[0] - c[1] * d[0] - b[0] * d[1];
- btScalar P21 = a[2] * c[1] - d[2] * c[1] - a[1] * c[2] - a[2] * d[1] + c[2] * d[1] + a[1] * d[2];
- btScalar P22 = -a[2] * c[0] + d[2] * c[0] + a[0] * c[2] + a[2] * d[0] - c[2] * d[0] - a[0] * d[2];
- btScalar P23 = a[1] * c[0] - d[1] * c[0] - a[0] * c[1] - a[1] * d[0] + c[1] * d[0] + a[0] * d[1];
- btScalar P31 = -a[2] * b[1] + d[2] * b[1] + a[1] * b[2] + a[2] * d[1] - b[2] * d[1] - a[1] * d[2];
- btScalar P32 = a[2] * b[0] - d[2] * b[0] - a[0] * b[2] - a[2] * d[0] + b[2] * d[0] + a[0] * d[2];
- btScalar P33 = -a[1] * b[0] + d[1] * b[0] + a[0] * b[1] + a[1] * d[0] - b[1] * d[0] - a[0] * d[1];
- btScalar P41 = a[2] * b[1] - c[2] * b[1] - a[1] * b[2] - a[2] * c[1] + b[2] * c[1] + a[1] * c[2];
- btScalar P42 = -a[2] * b[0] + c[2] * b[0] + a[0] * b[2] + a[2] * c[0] - b[2] * c[0] - a[0] * c[2];
- btScalar P43 = a[1] * b[0] - c[1] * b[0] - a[0] * b[1] - a[1] * c[0] + b[1] * c[0] + a[0] * c[1];
-
- btVector4 p1(P11 * det, P21 * det, P31 * det, P41 * det);
- btVector4 p2(P12 * det, P22 * det, P32 * det, P42 * det);
- btVector4 p3(P13 * det, P23 * det, P33 * det, P43 * det);
-
- t.m_P_inv[0] = p1;
- t.m_P_inv[1] = p2;
- t.m_P_inv[2] = p3;
- }
-}
-
-static btScalar Dot4(const btVector4& a, const btVector4& b)
-{
- return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
-}
-
-void btSoftBody::updateDeformation()
-{
- btQuaternion q;
- for (int i = 0; i < m_tetras.size(); ++i)
- {
- btSoftBody::Tetra& t = m_tetras[i];
- btVector3 c1 = t.m_n[1]->m_q - t.m_n[0]->m_q;
- btVector3 c2 = t.m_n[2]->m_q - t.m_n[0]->m_q;
- btVector3 c3 = t.m_n[3]->m_q - t.m_n[0]->m_q;
- btMatrix3x3 Ds(c1.getX(), c2.getX(), c3.getX(),
- c1.getY(), c2.getY(), c3.getY(),
- c1.getZ(), c2.getZ(), c3.getZ());
- t.m_F = Ds * t.m_Dm_inverse;
-
- btSoftBody::TetraScratch& s = m_tetraScratches[i];
- s.m_F = t.m_F;
- s.m_J = t.m_F.determinant();
- btMatrix3x3 C = t.m_F.transpose() * t.m_F;
- s.m_trace = C[0].getX() + C[1].getY() + C[2].getZ();
- s.m_cofF = t.m_F.adjoint().transpose();
-
- btVector3 a = t.m_n[0]->m_q;
- btVector3 b = t.m_n[1]->m_q;
- btVector3 c = t.m_n[2]->m_q;
- btVector3 d = t.m_n[3]->m_q;
- btVector4 q1(a[0], b[0], c[0], d[0]);
- btVector4 q2(a[1], b[1], c[1], d[1]);
- btVector4 q3(a[2], b[2], c[2], d[2]);
- btMatrix3x3 B(Dot4(q1, t.m_P_inv[0]), Dot4(q1, t.m_P_inv[1]), Dot4(q1, t.m_P_inv[2]),
- Dot4(q2, t.m_P_inv[0]), Dot4(q2, t.m_P_inv[1]), Dot4(q2, t.m_P_inv[2]),
- Dot4(q3, t.m_P_inv[0]), Dot4(q3, t.m_P_inv[1]), Dot4(q3, t.m_P_inv[2]));
- q.setRotation(btVector3(0, 0, 1), 0);
- B.extractRotation(q, 0.01); // precision of the rotation is not very important for visual correctness.
- btMatrix3x3 Q(q);
- s.m_corotation = Q;
- }
-}
-
-void btSoftBody::advanceDeformation()
-{
- updateDeformation();
- for (int i = 0; i < m_tetras.size(); ++i)
- {
- m_tetraScratchesTn[i] = m_tetraScratches[i];
- }
-}
-//
-void btSoftBody::Joint::Prepare(btScalar dt, int)
-{
- m_bodies[0].activate();
- m_bodies[1].activate();
-}
-
-//
-void btSoftBody::LJoint::Prepare(btScalar dt, int iterations)
-{
- static const btScalar maxdrift = 4;
- Joint::Prepare(dt, iterations);
- m_rpos[0] = m_bodies[0].xform() * m_refs[0];
- m_rpos[1] = m_bodies[1].xform() * m_refs[1];
- m_drift = Clamp(m_rpos[0] - m_rpos[1], maxdrift) * m_erp / dt;
- m_rpos[0] -= m_bodies[0].xform().getOrigin();
- m_rpos[1] -= m_bodies[1].xform().getOrigin();
- m_massmatrix = ImpulseMatrix(m_bodies[0].invMass(), m_bodies[0].invWorldInertia(), m_rpos[0],
- m_bodies[1].invMass(), m_bodies[1].invWorldInertia(), m_rpos[1]);
- if (m_split > 0)
- {
- m_sdrift = m_massmatrix * (m_drift * m_split);
- m_drift *= 1 - m_split;
- }
- m_drift /= (btScalar)iterations;
-}
-
-//
-void btSoftBody::LJoint::Solve(btScalar dt, btScalar sor)
-{
- const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
- const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
- const btVector3 vr = va - vb;
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_massmatrix * (m_drift + vr * m_cfm) * sor;
- m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
- m_bodies[1].applyImpulse(impulse, m_rpos[1]);
-}
-
-//
-void btSoftBody::LJoint::Terminate(btScalar dt)
-{
- if (m_split > 0)
- {
- m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
- m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
- }
-}
-
-//
-void btSoftBody::AJoint::Prepare(btScalar dt, int iterations)
-{
- static const btScalar maxdrift = SIMD_PI / 16;
- m_icontrol->Prepare(this);
- Joint::Prepare(dt, iterations);
- m_axis[0] = m_bodies[0].xform().getBasis() * m_refs[0];
- m_axis[1] = m_bodies[1].xform().getBasis() * m_refs[1];
- m_drift = NormalizeAny(btCross(m_axis[1], m_axis[0]));
- m_drift *= btMin(maxdrift, btAcos(Clamp<btScalar>(btDot(m_axis[0], m_axis[1]), -1, +1)));
- m_drift *= m_erp / dt;
- m_massmatrix = AngularImpulseMatrix(m_bodies[0].invWorldInertia(), m_bodies[1].invWorldInertia());
- if (m_split > 0)
- {
- m_sdrift = m_massmatrix * (m_drift * m_split);
- m_drift *= 1 - m_split;
- }
- m_drift /= (btScalar)iterations;
-}
-
-//
-void btSoftBody::AJoint::Solve(btScalar dt, btScalar sor)
-{
- const btVector3 va = m_bodies[0].angularVelocity();
- const btVector3 vb = m_bodies[1].angularVelocity();
- const btVector3 vr = va - vb;
- const btScalar sp = btDot(vr, m_axis[0]);
- const btVector3 vc = vr - m_axis[0] * m_icontrol->Speed(this, sp);
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_massmatrix * (m_drift + vc * m_cfm) * sor;
- m_bodies[0].applyAImpulse(-impulse);
- m_bodies[1].applyAImpulse(impulse);
-}
-
-//
-void btSoftBody::AJoint::Terminate(btScalar dt)
-{
- if (m_split > 0)
- {
- m_bodies[0].applyDAImpulse(-m_sdrift);
- m_bodies[1].applyDAImpulse(m_sdrift);
- }
-}
-
-//
-void btSoftBody::CJoint::Prepare(btScalar dt, int iterations)
-{
- Joint::Prepare(dt, iterations);
- const bool dodrift = (m_life == 0);
- m_delete = (++m_life) > m_maxlife;
- if (dodrift)
- {
- m_drift = m_drift * m_erp / dt;
- if (m_split > 0)
- {
- m_sdrift = m_massmatrix * (m_drift * m_split);
- m_drift *= 1 - m_split;
- }
- m_drift /= (btScalar)iterations;
- }
- else
- {
- m_drift = m_sdrift = btVector3(0, 0, 0);
- }
-}
-
-//
-void btSoftBody::CJoint::Solve(btScalar dt, btScalar sor)
-{
- const btVector3 va = m_bodies[0].velocity(m_rpos[0]);
- const btVector3 vb = m_bodies[1].velocity(m_rpos[1]);
- const btVector3 vrel = va - vb;
- const btScalar rvac = btDot(vrel, m_normal);
- btSoftBody::Impulse impulse;
- impulse.m_asVelocity = 1;
- impulse.m_velocity = m_drift;
- if (rvac < 0)
- {
- const btVector3 iv = m_normal * rvac;
- const btVector3 fv = vrel - iv;
- impulse.m_velocity += iv + fv * m_friction;
- }
- impulse.m_velocity = m_massmatrix * impulse.m_velocity * sor;
-
- if (m_bodies[0].m_soft == m_bodies[1].m_soft)
- {
- if ((impulse.m_velocity.getX() == impulse.m_velocity.getX()) && (impulse.m_velocity.getY() == impulse.m_velocity.getY()) &&
- (impulse.m_velocity.getZ() == impulse.m_velocity.getZ()))
- {
- if (impulse.m_asVelocity)
- {
- if (impulse.m_velocity.length() < m_bodies[0].m_soft->m_maxSelfCollisionImpulse)
- {
- }
- else
- {
- m_bodies[0].applyImpulse(-impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[0]);
- m_bodies[1].applyImpulse(impulse * m_bodies[0].m_soft->m_selfCollisionImpulseFactor, m_rpos[1]);
- }
- }
- }
- }
- else
- {
- m_bodies[0].applyImpulse(-impulse, m_rpos[0]);
- m_bodies[1].applyImpulse(impulse, m_rpos[1]);
- }
-}
-
-//
-void btSoftBody::CJoint::Terminate(btScalar dt)
-{
- if (m_split > 0)
- {
- m_bodies[0].applyDImpulse(-m_sdrift, m_rpos[0]);
- m_bodies[1].applyDImpulse(m_sdrift, m_rpos[1]);
- }
-}
-
-//
-void btSoftBody::applyForces()
-{
- BT_PROFILE("SoftBody applyForces");
- // const btScalar dt = m_sst.sdt;
- const btScalar kLF = m_cfg.kLF;
- const btScalar kDG = m_cfg.kDG;
- const btScalar kPR = m_cfg.kPR;
- const btScalar kVC = m_cfg.kVC;
- const bool as_lift = kLF > 0;
- const bool as_drag = kDG > 0;
- const bool as_pressure = kPR != 0;
- const bool as_volume = kVC > 0;
- const bool as_aero = as_lift ||
- as_drag;
- //const bool as_vaero = as_aero &&
- // (m_cfg.aeromodel < btSoftBody::eAeroModel::F_TwoSided);
- //const bool as_faero = as_aero &&
- // (m_cfg.aeromodel >= btSoftBody::eAeroModel::F_TwoSided);
- const bool use_medium = as_aero;
- const bool use_volume = as_pressure ||
- as_volume;
- btScalar volume = 0;
- btScalar ivolumetp = 0;
- btScalar dvolumetv = 0;
- btSoftBody::sMedium medium;
- if (use_volume)
- {
- volume = getVolume();
- ivolumetp = 1 / btFabs(volume) * kPR;
- dvolumetv = (m_pose.m_volume - volume) * kVC;
- }
- /* Per vertex forces */
- int i, ni;
-
- for (i = 0, ni = m_nodes.size(); i < ni; ++i)
- {
- btSoftBody::Node& n = m_nodes[i];
- if (n.m_im > 0)
- {
- if (use_medium)
- {
- /* Aerodynamics */
- addAeroForceToNode(m_windVelocity, i);
- }
- /* Pressure */
- if (as_pressure)
- {
- n.m_f += n.m_n * (n.m_area * ivolumetp);
- }
- /* Volume */
- if (as_volume)
- {
- n.m_f += n.m_n * (n.m_area * dvolumetv);
- }
- }
- }
-
- /* Per face forces */
- for (i = 0, ni = m_faces.size(); i < ni; ++i)
- {
- // btSoftBody::Face& f=m_faces[i];
-
- /* Aerodynamics */
- addAeroForceToFace(m_windVelocity, i);
- }
-}
-
-//
-void btSoftBody::setMaxStress(btScalar maxStress)
-{
- m_cfg.m_maxStress = maxStress;
-}
-
-//
-void btSoftBody::interpolateRenderMesh()
-{
- if (m_z.size() > 0)
- {
- for (int i = 0; i < m_renderNodes.size(); ++i)
- {
- const Node* p0 = m_renderNodesParents[i][0];
- const Node* p1 = m_renderNodesParents[i][1];
- const Node* p2 = m_renderNodesParents[i][2];
- btVector3 normal = btCross(p1->m_x - p0->m_x, p2->m_x - p0->m_x);
- btVector3 unit_normal = normal.normalized();
- RenderNode& n = m_renderNodes[i];
- n.m_x.setZero();
- for (int j = 0; j < 3; ++j)
- {
- n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
- }
- n.m_x += m_z[i] * unit_normal;
- }
- }
- else
- {
- for (int i = 0; i < m_renderNodes.size(); ++i)
- {
- RenderNode& n = m_renderNodes[i];
- n.m_x.setZero();
- for (int j = 0; j < 4; ++j)
- {
- if (m_renderNodesParents[i].size())
- {
- n.m_x += m_renderNodesParents[i][j]->m_x * m_renderNodesInterpolationWeights[i][j];
- }
- }
- }
- }
-}
-
-void btSoftBody::setCollisionQuadrature(int N)
-{
- for (int i = 0; i <= N; ++i)
- {
- for (int j = 0; i + j <= N; ++j)
- {
- m_quads.push_back(btVector3(btScalar(i) / btScalar(N), btScalar(j) / btScalar(N), btScalar(N - i - j) / btScalar(N)));
- }
- }
-}
-
-//
-void btSoftBody::PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti)
-{
- BT_PROFILE("PSolve_Anchors");
- const btScalar kAHR = psb->m_cfg.kAHR * kst;
- const btScalar dt = psb->m_sst.sdt;
- for (int i = 0, ni = psb->m_anchors.size(); i < ni; ++i)
- {
- const Anchor& a = psb->m_anchors[i];
- const btTransform& t = a.m_body->getWorldTransform();
- Node& n = *a.m_node;
- const btVector3 wa = t * a.m_local;
- const btVector3 va = a.m_body->getVelocityInLocalPoint(a.m_c1) * dt;
- const btVector3 vb = n.m_x - n.m_q;
- const btVector3 vr = (va - vb) + (wa - n.m_x) * kAHR;
- const btVector3 impulse = a.m_c0 * vr * a.m_influence;
- n.m_x += impulse * a.m_c2;
- a.m_body->applyImpulse(-impulse, a.m_c1);
- }
-}
-
-//
-void btSoftBody::PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti)
-{
- BT_PROFILE("PSolve_RContacts");
- const btScalar dt = psb->m_sst.sdt;
- const btScalar mrg = psb->getCollisionShape()->getMargin();
- btMultiBodyJacobianData jacobianData;
- for (int i = 0, ni = psb->m_rcontacts.size(); i < ni; ++i)
- {
- const RContact& c = psb->m_rcontacts[i];
- const sCti& cti = c.m_cti;
- if (cti.m_colObj->hasContactResponse())
- {
- btVector3 va(0, 0, 0);
- btRigidBody* rigidCol = 0;
- btMultiBodyLinkCollider* multibodyLinkCol = 0;
- btScalar* deltaV;
-
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- rigidCol = (btRigidBody*)btRigidBody::upcast(cti.m_colObj);
- va = rigidCol ? rigidCol->getVelocityInLocalPoint(c.m_c1) * dt : btVector3(0, 0, 0);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- jacobianData.m_jacobians.resize(ndof);
- jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
- btScalar* jac = &jacobianData.m_jacobians[0];
-
- multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, c.m_node->m_x, cti.m_normal, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
- deltaV = &jacobianData.m_deltaVelocitiesUnitImpulse[0];
- multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], deltaV, jacobianData.scratch_r, jacobianData.scratch_v);
-
- btScalar vel = 0.0;
- for (int j = 0; j < ndof; ++j)
- {
- vel += multibodyLinkCol->m_multiBody->getVelocityVector()[j] * jac[j];
- }
- va = cti.m_normal * vel * dt;
- }
- }
-
- const btVector3 vb = c.m_node->m_x - c.m_node->m_q;
- const btVector3 vr = vb - va;
- const btScalar dn = btDot(vr, cti.m_normal);
- if (dn <= SIMD_EPSILON)
- {
- const btScalar dp = btMin((btDot(c.m_node->m_x, cti.m_normal) + cti.m_offset), mrg);
- const btVector3 fv = vr - (cti.m_normal * dn);
- // c0 is the impulse matrix, c3 is 1 - the friction coefficient or 0, c4 is the contact hardness coefficient
- const btVector3 impulse = c.m_c0 * ((vr - (fv * c.m_c3) + (cti.m_normal * (dp * c.m_c4))) * kst);
- c.m_node->m_x -= impulse * c.m_c2;
-
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- if (rigidCol)
- rigidCol->applyImpulse(impulse, c.m_c1);
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- if (multibodyLinkCol)
- {
- double multiplier = 0.5;
- multibodyLinkCol->m_multiBody->applyDeltaVeeMultiDof(deltaV, -impulse.length() * multiplier);
- }
- }
- }
- }
- }
-}
-
-//
-void btSoftBody::PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti)
-{
- BT_PROFILE("PSolve_SContacts");
-
- for (int i = 0, ni = psb->m_scontacts.size(); i < ni; ++i)
- {
- const SContact& c = psb->m_scontacts[i];
- const btVector3& nr = c.m_normal;
- Node& n = *c.m_node;
- Face& f = *c.m_face;
- const btVector3 p = BaryEval(f.m_n[0]->m_x,
- f.m_n[1]->m_x,
- f.m_n[2]->m_x,
- c.m_weights);
- const btVector3 q = BaryEval(f.m_n[0]->m_q,
- f.m_n[1]->m_q,
- f.m_n[2]->m_q,
- c.m_weights);
- const btVector3 vr = (n.m_x - n.m_q) - (p - q);
- btVector3 corr(0, 0, 0);
- btScalar dot = btDot(vr, nr);
- if (dot < 0)
- {
- const btScalar j = c.m_margin - (btDot(nr, n.m_x) - btDot(nr, p));
- corr += c.m_normal * j;
- }
- corr -= ProjectOnPlane(vr, nr) * c.m_friction;
- n.m_x += corr * c.m_cfm[0];
- f.m_n[0]->m_x -= corr * (c.m_cfm[1] * c.m_weights.x());
- f.m_n[1]->m_x -= corr * (c.m_cfm[1] * c.m_weights.y());
- f.m_n[2]->m_x -= corr * (c.m_cfm[1] * c.m_weights.z());
- }
-}
-
-//
-void btSoftBody::PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti)
-{
- BT_PROFILE("PSolve_Links");
- for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
- {
- Link& l = psb->m_links[i];
- if (l.m_c0 > 0)
- {
- Node& a = *l.m_n[0];
- Node& b = *l.m_n[1];
- const btVector3 del = b.m_x - a.m_x;
- const btScalar len = del.length2();
- if (l.m_c1 + len > SIMD_EPSILON)
- {
- const btScalar k = ((l.m_c1 - len) / (l.m_c0 * (l.m_c1 + len))) * kst;
- a.m_x -= del * (k * a.m_im);
- b.m_x += del * (k * b.m_im);
- }
- }
- }
-}
-
-//
-void btSoftBody::VSolve_Links(btSoftBody* psb, btScalar kst)
-{
- BT_PROFILE("VSolve_Links");
- for (int i = 0, ni = psb->m_links.size(); i < ni; ++i)
- {
- Link& l = psb->m_links[i];
- Node** n = l.m_n;
- const btScalar j = -btDot(l.m_c3, n[0]->m_v - n[1]->m_v) * l.m_c2 * kst;
- n[0]->m_v += l.m_c3 * (j * n[0]->m_im);
- n[1]->m_v -= l.m_c3 * (j * n[1]->m_im);
- }
-}
-
-//
-btSoftBody::psolver_t btSoftBody::getSolver(ePSolver::_ solver)
-{
- switch (solver)
- {
- case ePSolver::Anchors:
- return (&btSoftBody::PSolve_Anchors);
- case ePSolver::Linear:
- return (&btSoftBody::PSolve_Links);
- case ePSolver::RContacts:
- return (&btSoftBody::PSolve_RContacts);
- case ePSolver::SContacts:
- return (&btSoftBody::PSolve_SContacts);
- default:
- {
- }
- }
- return (0);
-}
-
-//
-btSoftBody::vsolver_t btSoftBody::getSolver(eVSolver::_ solver)
-{
- switch (solver)
- {
- case eVSolver::Linear:
- return (&btSoftBody::VSolve_Links);
- default:
- {
- }
- }
- return (0);
-}
-
-void btSoftBody::setSelfCollision(bool useSelfCollision)
-{
- m_useSelfCollision = useSelfCollision;
-}
-
-bool btSoftBody::useSelfCollision()
-{
- return m_useSelfCollision;
-}
-
-//
-void btSoftBody::defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap)
-{
- switch (m_cfg.collisions & fCollision::RVSmask)
- {
- case fCollision::SDF_RS:
- {
- btSoftColliders::CollideSDF_RS docollide;
- btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
- btTransform wtr = pcoWrap->getWorldTransform();
-
- const btTransform ctr = pcoWrap->getWorldTransform();
- const btScalar timemargin = (wtr.getOrigin() - ctr.getOrigin()).length();
- const btScalar basemargin = getCollisionShape()->getMargin();
- btVector3 mins;
- btVector3 maxs;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- volume;
- pcoWrap->getCollisionShape()->getAabb(pcoWrap->getWorldTransform(),
- mins,
- maxs);
- volume = btDbvtVolume::FromMM(mins, maxs);
- volume.Expand(btVector3(basemargin, basemargin, basemargin));
- docollide.psb = this;
- docollide.m_colObj1Wrap = pcoWrap;
- docollide.m_rigidBody = prb1;
-
- docollide.dynmargin = basemargin + timemargin;
- docollide.stamargin = basemargin;
- m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollide);
- }
- break;
- case fCollision::CL_RS:
- {
- btSoftColliders::CollideCL_RS collider;
- collider.ProcessColObj(this, pcoWrap);
- }
- break;
- case fCollision::SDF_RD:
- {
- btRigidBody* prb1 = (btRigidBody*)btRigidBody::upcast(pcoWrap->getCollisionObject());
- if (pcoWrap->getCollisionObject()->isActive() || this->isActive())
- {
- const btTransform wtr = pcoWrap->getWorldTransform();
- const btScalar timemargin = 0;
- const btScalar basemargin = getCollisionShape()->getMargin();
- btVector3 mins;
- btVector3 maxs;
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- volume;
- pcoWrap->getCollisionShape()->getAabb(wtr,
- mins,
- maxs);
- volume = btDbvtVolume::FromMM(mins, maxs);
- volume.Expand(btVector3(basemargin, basemargin, basemargin));
- if (m_cfg.collisions & fCollision::SDF_RDN)
- {
- btSoftColliders::CollideSDF_RD docollideNode;
- docollideNode.psb = this;
- docollideNode.m_colObj1Wrap = pcoWrap;
- docollideNode.m_rigidBody = prb1;
- docollideNode.dynmargin = basemargin + timemargin;
- docollideNode.stamargin = basemargin;
- m_ndbvt.collideTV(m_ndbvt.m_root, volume, docollideNode);
- }
-
- if (((pcoWrap->getCollisionObject()->getInternalType() == CO_RIGID_BODY) && (m_cfg.collisions & fCollision::SDF_RDF)) || ((pcoWrap->getCollisionObject()->getInternalType() == CO_FEATHERSTONE_LINK) && (m_cfg.collisions & fCollision::SDF_MDF)))
- {
- btSoftColliders::CollideSDF_RDF docollideFace;
- docollideFace.psb = this;
- docollideFace.m_colObj1Wrap = pcoWrap;
- docollideFace.m_rigidBody = prb1;
- docollideFace.dynmargin = basemargin + timemargin;
- docollideFace.stamargin = basemargin;
- m_fdbvt.collideTV(m_fdbvt.m_root, volume, docollideFace);
- }
- }
- }
- break;
- }
-}
-
-//
-void btSoftBody::defaultCollisionHandler(btSoftBody* psb)
-{
- BT_PROFILE("Deformable Collision");
- const int cf = m_cfg.collisions & psb->m_cfg.collisions;
- switch (cf & fCollision::SVSmask)
- {
- case fCollision::CL_SS:
- {
- //support self-collision if CL_SELF flag set
- if (this != psb || psb->m_cfg.collisions & fCollision::CL_SELF)
- {
- btSoftColliders::CollideCL_SS docollide;
- docollide.ProcessSoftSoft(this, psb);
- }
- }
- break;
- case fCollision::VF_SS:
- {
- //only self-collision for Cluster, not Vertex-Face yet
- if (this != psb)
- {
- btSoftColliders::CollideVF_SS docollide;
- /* common */
- docollide.mrg = getCollisionShape()->getMargin() +
- psb->getCollisionShape()->getMargin();
- /* psb0 nodes vs psb1 faces */
- docollide.psb[0] = this;
- docollide.psb[1] = psb;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- /* psb1 nodes vs psb0 faces */
- docollide.psb[0] = psb;
- docollide.psb[1] = this;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- }
- }
- break;
- case fCollision::VF_DD:
- {
- if (!psb->m_softSoftCollision)
- return;
- if (psb->isActive() || this->isActive())
- {
- if (this != psb)
- {
- btSoftColliders::CollideVF_DD docollide;
- /* common */
- docollide.mrg = getCollisionShape()->getMargin() +
- psb->getCollisionShape()->getMargin();
- /* psb0 nodes vs psb1 faces */
- if (psb->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- docollide.psb[0] = this;
- docollide.psb[1] = psb;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
-
- /* psb1 nodes vs psb0 faces */
- if (this->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- docollide.psb[0] = psb;
- docollide.psb[1] = this;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- }
- else
- {
- if (psb->useSelfCollision())
- {
- btSoftColliders::CollideFF_DD docollide;
- docollide.mrg = 2 * getCollisionShape()->getMargin();
- docollide.psb[0] = this;
- docollide.psb[1] = psb;
- if (this->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- /* psb0 faces vs psb0 faces */
- calculateNormalCone(this->m_fdbvnt);
- this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
- }
- }
- }
- }
- break;
- default:
- {
- }
- }
-}
-
-void btSoftBody::geometricCollisionHandler(btSoftBody* psb)
-{
- if (psb->isActive() || this->isActive())
- {
- if (this != psb)
- {
- btSoftColliders::CollideCCD docollide;
- /* common */
- docollide.mrg = SAFE_EPSILON; // for rounding error instead of actual margin
- docollide.dt = psb->m_sst.sdt;
- /* psb0 nodes vs psb1 faces */
- if (psb->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- docollide.psb[0] = this;
- docollide.psb[1] = psb;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- /* psb1 nodes vs psb0 faces */
- if (this->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- docollide.psb[0] = psb;
- docollide.psb[1] = this;
- docollide.psb[0]->m_ndbvt.collideTT(docollide.psb[0]->m_ndbvt.m_root,
- docollide.psb[1]->m_fdbvt.m_root,
- docollide);
- }
- else
- {
- if (psb->useSelfCollision())
- {
- btSoftColliders::CollideCCD docollide;
- docollide.mrg = SAFE_EPSILON;
- docollide.psb[0] = this;
- docollide.psb[1] = psb;
- docollide.dt = psb->m_sst.sdt;
- if (this->m_tetras.size() > 0)
- docollide.useFaceNormal = true;
- else
- docollide.useFaceNormal = false;
- /* psb0 faces vs psb0 faces */
- calculateNormalCone(this->m_fdbvnt); // should compute this outside of this scope
- this->m_fdbvt.selfCollideT(m_fdbvnt, docollide);
- }
- }
- }
-}
-
-void btSoftBody::setWindVelocity(const btVector3& velocity)
-{
- m_windVelocity = velocity;
-}
-
-const btVector3& btSoftBody::getWindVelocity()
-{
- return m_windVelocity;
-}
-
-int btSoftBody::calculateSerializeBufferSize() const
-{
- int sz = sizeof(btSoftBodyData);
- return sz;
-}
-
-///fills the dataBuffer and returns the struct name (and 0 on failure)
-const char* btSoftBody::serialize(void* dataBuffer, class btSerializer* serializer) const
-{
- btSoftBodyData* sbd = (btSoftBodyData*)dataBuffer;
-
- btCollisionObject::serialize(&sbd->m_collisionObjectData, serializer);
-
- btHashMap<btHashPtr, int> m_nodeIndexMap;
-
- sbd->m_numMaterials = m_materials.size();
- sbd->m_materials = sbd->m_numMaterials ? (SoftBodyMaterialData**)serializer->getUniquePointer((void*)&m_materials) : 0;
-
- if (sbd->m_materials)
- {
- int sz = sizeof(SoftBodyMaterialData*);
- int numElem = sbd->m_numMaterials;
- btChunk* chunk = serializer->allocate(sz, numElem);
- //SoftBodyMaterialData** memPtr = chunk->m_oldPtr;
- SoftBodyMaterialData** memPtr = (SoftBodyMaterialData**)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- btSoftBody::Material* mat = m_materials[i];
- *memPtr = mat ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)mat) : 0;
- if (!serializer->findPointer(mat))
- {
- //serialize it here
- btChunk* chunk = serializer->allocate(sizeof(SoftBodyMaterialData), 1);
- SoftBodyMaterialData* memPtr = (SoftBodyMaterialData*)chunk->m_oldPtr;
- memPtr->m_flags = mat->m_flags;
- memPtr->m_angularStiffness = mat->m_kAST;
- memPtr->m_linearStiffness = mat->m_kLST;
- memPtr->m_volumeStiffness = mat->m_kVST;
- serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_SBMATERIAL_CODE, mat);
- }
- }
- serializer->finalizeChunk(chunk, "SoftBodyMaterialData", BT_ARRAY_CODE, (void*)&m_materials);
- }
-
- sbd->m_numNodes = m_nodes.size();
- sbd->m_nodes = sbd->m_numNodes ? (SoftBodyNodeData*)serializer->getUniquePointer((void*)&m_nodes) : 0;
- if (sbd->m_nodes)
- {
- int sz = sizeof(SoftBodyNodeData);
- int numElem = sbd->m_numNodes;
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftBodyNodeData* memPtr = (SoftBodyNodeData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_nodes[i].m_f.serializeFloat(memPtr->m_accumulatedForce);
- memPtr->m_area = m_nodes[i].m_area;
- memPtr->m_attach = m_nodes[i].m_battach;
- memPtr->m_inverseMass = m_nodes[i].m_im;
- memPtr->m_material = m_nodes[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_nodes[i].m_material) : 0;
- m_nodes[i].m_n.serializeFloat(memPtr->m_normal);
- m_nodes[i].m_x.serializeFloat(memPtr->m_position);
- m_nodes[i].m_q.serializeFloat(memPtr->m_previousPosition);
- m_nodes[i].m_v.serializeFloat(memPtr->m_velocity);
- m_nodeIndexMap.insert(&m_nodes[i], i);
- }
- serializer->finalizeChunk(chunk, "SoftBodyNodeData", BT_SBNODE_CODE, (void*)&m_nodes);
- }
-
- sbd->m_numLinks = m_links.size();
- sbd->m_links = sbd->m_numLinks ? (SoftBodyLinkData*)serializer->getUniquePointer((void*)&m_links[0]) : 0;
- if (sbd->m_links)
- {
- int sz = sizeof(SoftBodyLinkData);
- int numElem = sbd->m_numLinks;
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftBodyLinkData* memPtr = (SoftBodyLinkData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_bbending = m_links[i].m_bbending;
- memPtr->m_material = m_links[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_links[i].m_material) : 0;
- memPtr->m_nodeIndices[0] = m_links[i].m_n[0] ? m_links[i].m_n[0] - &m_nodes[0] : -1;
- memPtr->m_nodeIndices[1] = m_links[i].m_n[1] ? m_links[i].m_n[1] - &m_nodes[0] : -1;
- btAssert(memPtr->m_nodeIndices[0] < m_nodes.size());
- btAssert(memPtr->m_nodeIndices[1] < m_nodes.size());
- memPtr->m_restLength = m_links[i].m_rl;
- }
- serializer->finalizeChunk(chunk, "SoftBodyLinkData", BT_ARRAY_CODE, (void*)&m_links[0]);
- }
-
- sbd->m_numFaces = m_faces.size();
- sbd->m_faces = sbd->m_numFaces ? (SoftBodyFaceData*)serializer->getUniquePointer((void*)&m_faces[0]) : 0;
- if (sbd->m_faces)
- {
- int sz = sizeof(SoftBodyFaceData);
- int numElem = sbd->m_numFaces;
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftBodyFaceData* memPtr = (SoftBodyFaceData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_material = m_faces[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_faces[i].m_material) : 0;
- m_faces[i].m_normal.serializeFloat(memPtr->m_normal);
- for (int j = 0; j < 3; j++)
- {
- memPtr->m_nodeIndices[j] = m_faces[i].m_n[j] ? m_faces[i].m_n[j] - &m_nodes[0] : -1;
- }
- memPtr->m_restArea = m_faces[i].m_ra;
- }
- serializer->finalizeChunk(chunk, "SoftBodyFaceData", BT_ARRAY_CODE, (void*)&m_faces[0]);
- }
-
- sbd->m_numTetrahedra = m_tetras.size();
- sbd->m_tetrahedra = sbd->m_numTetrahedra ? (SoftBodyTetraData*)serializer->getUniquePointer((void*)&m_tetras[0]) : 0;
- if (sbd->m_tetrahedra)
- {
- int sz = sizeof(SoftBodyTetraData);
- int numElem = sbd->m_numTetrahedra;
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftBodyTetraData* memPtr = (SoftBodyTetraData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- for (int j = 0; j < 4; j++)
- {
- m_tetras[i].m_c0[j].serializeFloat(memPtr->m_c0[j]);
- memPtr->m_nodeIndices[j] = m_tetras[i].m_n[j] ? m_tetras[i].m_n[j] - &m_nodes[0] : -1;
- }
- memPtr->m_c1 = m_tetras[i].m_c1;
- memPtr->m_c2 = m_tetras[i].m_c2;
- memPtr->m_material = m_tetras[i].m_material ? (SoftBodyMaterialData*)serializer->getUniquePointer((void*)m_tetras[i].m_material) : 0;
- memPtr->m_restVolume = m_tetras[i].m_rv;
- }
- serializer->finalizeChunk(chunk, "SoftBodyTetraData", BT_ARRAY_CODE, (void*)&m_tetras[0]);
- }
-
- sbd->m_numAnchors = m_anchors.size();
- sbd->m_anchors = sbd->m_numAnchors ? (SoftRigidAnchorData*)serializer->getUniquePointer((void*)&m_anchors[0]) : 0;
- if (sbd->m_anchors)
- {
- int sz = sizeof(SoftRigidAnchorData);
- int numElem = sbd->m_numAnchors;
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftRigidAnchorData* memPtr = (SoftRigidAnchorData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_anchors[i].m_c0.serializeFloat(memPtr->m_c0);
- m_anchors[i].m_c1.serializeFloat(memPtr->m_c1);
- memPtr->m_c2 = m_anchors[i].m_c2;
- m_anchors[i].m_local.serializeFloat(memPtr->m_localFrame);
- memPtr->m_nodeIndex = m_anchors[i].m_node ? m_anchors[i].m_node - &m_nodes[0] : -1;
-
- memPtr->m_rigidBody = m_anchors[i].m_body ? (btRigidBodyData*)serializer->getUniquePointer((void*)m_anchors[i].m_body) : 0;
- btAssert(memPtr->m_nodeIndex < m_nodes.size());
- }
- serializer->finalizeChunk(chunk, "SoftRigidAnchorData", BT_ARRAY_CODE, (void*)&m_anchors[0]);
- }
-
- sbd->m_config.m_dynamicFriction = m_cfg.kDF;
- sbd->m_config.m_baumgarte = m_cfg.kVCF;
- sbd->m_config.m_pressure = m_cfg.kPR;
- sbd->m_config.m_aeroModel = this->m_cfg.aeromodel;
- sbd->m_config.m_lift = m_cfg.kLF;
- sbd->m_config.m_drag = m_cfg.kDG;
- sbd->m_config.m_positionIterations = m_cfg.piterations;
- sbd->m_config.m_driftIterations = m_cfg.diterations;
- sbd->m_config.m_clusterIterations = m_cfg.citerations;
- sbd->m_config.m_velocityIterations = m_cfg.viterations;
- sbd->m_config.m_maxVolume = m_cfg.maxvolume;
- sbd->m_config.m_damping = m_cfg.kDP;
- sbd->m_config.m_poseMatch = m_cfg.kMT;
- sbd->m_config.m_collisionFlags = m_cfg.collisions;
- sbd->m_config.m_volume = m_cfg.kVC;
- sbd->m_config.m_rigidContactHardness = m_cfg.kCHR;
- sbd->m_config.m_kineticContactHardness = m_cfg.kKHR;
- sbd->m_config.m_softContactHardness = m_cfg.kSHR;
- sbd->m_config.m_anchorHardness = m_cfg.kAHR;
- sbd->m_config.m_timeScale = m_cfg.timescale;
- sbd->m_config.m_maxVolume = m_cfg.maxvolume;
- sbd->m_config.m_softRigidClusterHardness = m_cfg.kSRHR_CL;
- sbd->m_config.m_softKineticClusterHardness = m_cfg.kSKHR_CL;
- sbd->m_config.m_softSoftClusterHardness = m_cfg.kSSHR_CL;
- sbd->m_config.m_softRigidClusterImpulseSplit = m_cfg.kSR_SPLT_CL;
- sbd->m_config.m_softKineticClusterImpulseSplit = m_cfg.kSK_SPLT_CL;
- sbd->m_config.m_softSoftClusterImpulseSplit = m_cfg.kSS_SPLT_CL;
-
- //pose for shape matching
- {
- sbd->m_pose = (SoftBodyPoseData*)serializer->getUniquePointer((void*)&m_pose);
-
- int sz = sizeof(SoftBodyPoseData);
- btChunk* chunk = serializer->allocate(sz, 1);
- SoftBodyPoseData* memPtr = (SoftBodyPoseData*)chunk->m_oldPtr;
-
- m_pose.m_aqq.serializeFloat(memPtr->m_aqq);
- memPtr->m_bframe = m_pose.m_bframe;
- memPtr->m_bvolume = m_pose.m_bvolume;
- m_pose.m_com.serializeFloat(memPtr->m_com);
-
- memPtr->m_numPositions = m_pose.m_pos.size();
- memPtr->m_positions = memPtr->m_numPositions ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_pose.m_pos[0]) : 0;
- if (memPtr->m_numPositions)
- {
- int numElem = memPtr->m_numPositions;
- int sz = sizeof(btVector3Data);
- btChunk* chunk = serializer->allocate(sz, numElem);
- btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- m_pose.m_pos[i].serializeFloat(*memPtr);
- }
- serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_pose.m_pos[0]);
- }
- memPtr->m_restVolume = m_pose.m_volume;
- m_pose.m_rot.serializeFloat(memPtr->m_rot);
- m_pose.m_scl.serializeFloat(memPtr->m_scale);
-
- memPtr->m_numWeigts = m_pose.m_wgh.size();
- memPtr->m_weights = memPtr->m_numWeigts ? (float*)serializer->getUniquePointer((void*)&m_pose.m_wgh[0]) : 0;
- if (memPtr->m_numWeigts)
- {
- int numElem = memPtr->m_numWeigts;
- int sz = sizeof(float);
- btChunk* chunk = serializer->allocate(sz, numElem);
- float* memPtr = (float*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- *memPtr = m_pose.m_wgh[i];
- }
- serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_pose.m_wgh[0]);
- }
-
- serializer->finalizeChunk(chunk, "SoftBodyPoseData", BT_ARRAY_CODE, (void*)&m_pose);
- }
-
- //clusters for convex-cluster collision detection
-
- sbd->m_numClusters = m_clusters.size();
- sbd->m_clusters = sbd->m_numClusters ? (SoftBodyClusterData*)serializer->getUniquePointer((void*)m_clusters[0]) : 0;
- if (sbd->m_numClusters)
- {
- int numElem = sbd->m_numClusters;
- int sz = sizeof(SoftBodyClusterData);
- btChunk* chunk = serializer->allocate(sz, numElem);
- SoftBodyClusterData* memPtr = (SoftBodyClusterData*)chunk->m_oldPtr;
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_adamping = m_clusters[i]->m_adamping;
- m_clusters[i]->m_av.serializeFloat(memPtr->m_av);
- memPtr->m_clusterIndex = m_clusters[i]->m_clusterIndex;
- memPtr->m_collide = m_clusters[i]->m_collide;
- m_clusters[i]->m_com.serializeFloat(memPtr->m_com);
- memPtr->m_containsAnchor = m_clusters[i]->m_containsAnchor;
- m_clusters[i]->m_dimpulses[0].serializeFloat(memPtr->m_dimpulses[0]);
- m_clusters[i]->m_dimpulses[1].serializeFloat(memPtr->m_dimpulses[1]);
- m_clusters[i]->m_framexform.serializeFloat(memPtr->m_framexform);
- memPtr->m_idmass = m_clusters[i]->m_idmass;
- memPtr->m_imass = m_clusters[i]->m_imass;
- m_clusters[i]->m_invwi.serializeFloat(memPtr->m_invwi);
- memPtr->m_ldamping = m_clusters[i]->m_ldamping;
- m_clusters[i]->m_locii.serializeFloat(memPtr->m_locii);
- m_clusters[i]->m_lv.serializeFloat(memPtr->m_lv);
- memPtr->m_matching = m_clusters[i]->m_matching;
- memPtr->m_maxSelfCollisionImpulse = m_clusters[i]->m_maxSelfCollisionImpulse;
- memPtr->m_ndamping = m_clusters[i]->m_ndamping;
- memPtr->m_ldamping = m_clusters[i]->m_ldamping;
- memPtr->m_adamping = m_clusters[i]->m_adamping;
- memPtr->m_selfCollisionImpulseFactor = m_clusters[i]->m_selfCollisionImpulseFactor;
-
- memPtr->m_numFrameRefs = m_clusters[i]->m_framerefs.size();
- memPtr->m_numMasses = m_clusters[i]->m_masses.size();
- memPtr->m_numNodes = m_clusters[i]->m_nodes.size();
-
- memPtr->m_nvimpulses = m_clusters[i]->m_nvimpulses;
- m_clusters[i]->m_vimpulses[0].serializeFloat(memPtr->m_vimpulses[0]);
- m_clusters[i]->m_vimpulses[1].serializeFloat(memPtr->m_vimpulses[1]);
- memPtr->m_ndimpulses = m_clusters[i]->m_ndimpulses;
-
- memPtr->m_framerefs = memPtr->m_numFrameRefs ? (btVector3FloatData*)serializer->getUniquePointer((void*)&m_clusters[i]->m_framerefs[0]) : 0;
- if (memPtr->m_framerefs)
- {
- int numElem = memPtr->m_numFrameRefs;
- int sz = sizeof(btVector3FloatData);
- btChunk* chunk = serializer->allocate(sz, numElem);
- btVector3FloatData* memPtr = (btVector3FloatData*)chunk->m_oldPtr;
- for (int j = 0; j < numElem; j++, memPtr++)
- {
- m_clusters[i]->m_framerefs[j].serializeFloat(*memPtr);
- }
- serializer->finalizeChunk(chunk, "btVector3FloatData", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_framerefs[0]);
- }
-
- memPtr->m_masses = memPtr->m_numMasses ? (float*)serializer->getUniquePointer((void*)&m_clusters[i]->m_masses[0]) : 0;
- if (memPtr->m_masses)
- {
- int numElem = memPtr->m_numMasses;
- int sz = sizeof(float);
- btChunk* chunk = serializer->allocate(sz, numElem);
- float* memPtr = (float*)chunk->m_oldPtr;
- for (int j = 0; j < numElem; j++, memPtr++)
- {
- *memPtr = m_clusters[i]->m_masses[j];
- }
- serializer->finalizeChunk(chunk, "float", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_masses[0]);
- }
-
- memPtr->m_nodeIndices = memPtr->m_numNodes ? (int*)serializer->getUniquePointer((void*)&m_clusters[i]->m_nodes) : 0;
- if (memPtr->m_nodeIndices)
- {
- int numElem = memPtr->m_numMasses;
- int sz = sizeof(int);
- btChunk* chunk = serializer->allocate(sz, numElem);
- int* memPtr = (int*)chunk->m_oldPtr;
- for (int j = 0; j < numElem; j++, memPtr++)
- {
- int* indexPtr = m_nodeIndexMap.find(m_clusters[i]->m_nodes[j]);
- btAssert(indexPtr);
- *memPtr = *indexPtr;
- }
- serializer->finalizeChunk(chunk, "int", BT_ARRAY_CODE, (void*)&m_clusters[i]->m_nodes);
- }
- }
- serializer->finalizeChunk(chunk, "SoftBodyClusterData", BT_ARRAY_CODE, (void*)m_clusters[0]);
- }
-
- sbd->m_numJoints = m_joints.size();
- sbd->m_joints = m_joints.size() ? (btSoftBodyJointData*)serializer->getUniquePointer((void*)&m_joints[0]) : 0;
-
- if (sbd->m_joints)
- {
- int sz = sizeof(btSoftBodyJointData);
- int numElem = m_joints.size();
- btChunk* chunk = serializer->allocate(sz, numElem);
- btSoftBodyJointData* memPtr = (btSoftBodyJointData*)chunk->m_oldPtr;
-
- for (int i = 0; i < numElem; i++, memPtr++)
- {
- memPtr->m_jointType = (int)m_joints[i]->Type();
- m_joints[i]->m_refs[0].serializeFloat(memPtr->m_refs[0]);
- m_joints[i]->m_refs[1].serializeFloat(memPtr->m_refs[1]);
- memPtr->m_cfm = m_joints[i]->m_cfm;
- memPtr->m_erp = float(m_joints[i]->m_erp);
- memPtr->m_split = float(m_joints[i]->m_split);
- memPtr->m_delete = m_joints[i]->m_delete;
-
- for (int j = 0; j < 4; j++)
- {
- memPtr->m_relPosition[0].m_floats[j] = 0.f;
- memPtr->m_relPosition[1].m_floats[j] = 0.f;
- }
- memPtr->m_bodyA = 0;
- memPtr->m_bodyB = 0;
- if (m_joints[i]->m_bodies[0].m_soft)
- {
- memPtr->m_bodyAtype = BT_JOINT_SOFT_BODY_CLUSTER;
- memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_soft);
- }
- if (m_joints[i]->m_bodies[0].m_collisionObject)
- {
- memPtr->m_bodyAtype = BT_JOINT_COLLISION_OBJECT;
- memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_collisionObject);
- }
- if (m_joints[i]->m_bodies[0].m_rigid)
- {
- memPtr->m_bodyAtype = BT_JOINT_RIGID_BODY;
- memPtr->m_bodyA = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[0].m_rigid);
- }
-
- if (m_joints[i]->m_bodies[1].m_soft)
- {
- memPtr->m_bodyBtype = BT_JOINT_SOFT_BODY_CLUSTER;
- memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_soft);
- }
- if (m_joints[i]->m_bodies[1].m_collisionObject)
- {
- memPtr->m_bodyBtype = BT_JOINT_COLLISION_OBJECT;
- memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_collisionObject);
- }
- if (m_joints[i]->m_bodies[1].m_rigid)
- {
- memPtr->m_bodyBtype = BT_JOINT_RIGID_BODY;
- memPtr->m_bodyB = serializer->getUniquePointer((void*)m_joints[i]->m_bodies[1].m_rigid);
- }
- }
- serializer->finalizeChunk(chunk, "btSoftBodyJointData", BT_ARRAY_CODE, (void*)&m_joints[0]);
- }
-
- return btSoftBodyDataName;
-}
-
-void btSoftBody::updateDeactivation(btScalar timeStep)
-{
- if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
- return;
-
- if (m_maxSpeedSquared < m_sleepingThreshold * m_sleepingThreshold)
- {
- m_deactivationTime += timeStep;
- }
- else
- {
- m_deactivationTime = btScalar(0.);
- setActivationState(0);
- }
-}
-
-void btSoftBody::setZeroVelocity()
-{
- for (int i = 0; i < m_nodes.size(); ++i)
- {
- m_nodes[i].m_v.setZero();
- }
-}
-
-bool btSoftBody::wantsSleeping()
-{
- if (getActivationState() == DISABLE_DEACTIVATION)
- return false;
-
- //disable deactivation
- if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
- return false;
-
- if ((getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
- return true;
-
- if (m_deactivationTime > gDeactivationTime)
- {
- return true;
- }
- return false;
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
deleted file mode 100644
index dfde8fd1e4..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBody.h
+++ /dev/null
@@ -1,1394 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btSoftBody implementation by Nathanael Presson
-
-#ifndef _BT_SOFT_BODY_H
-#define _BT_SOFT_BODY_H
-
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btVector3.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-#include "BulletCollision/CollisionShapes/btConcaveShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-#include "btSparseSDF.h"
-#include "BulletCollision/BroadphaseCollision/btDbvt.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-//#ifdef BT_USE_DOUBLE_PRECISION
-//#define btRigidBodyData btRigidBodyDoubleData
-//#define btRigidBodyDataName "btRigidBodyDoubleData"
-//#else
-#define btSoftBodyData btSoftBodyFloatData
-#define btSoftBodyDataName "btSoftBodyFloatData"
-static const btScalar OVERLAP_REDUCTION_FACTOR = 0.1;
-static unsigned long seed = 243703;
-//#endif //BT_USE_DOUBLE_PRECISION
-
-class btBroadphaseInterface;
-class btDispatcher;
-class btSoftBodySolver;
-
-/* btSoftBodyWorldInfo */
-struct btSoftBodyWorldInfo
-{
- btScalar air_density;
- btScalar water_density;
- btScalar water_offset;
- btScalar m_maxDisplacement;
- btVector3 water_normal;
- btBroadphaseInterface* m_broadphase;
- btDispatcher* m_dispatcher;
- btVector3 m_gravity;
- btSparseSdf<3> m_sparsesdf;
-
- btSoftBodyWorldInfo()
- : air_density((btScalar)1.2),
- water_density(0),
- water_offset(0),
- m_maxDisplacement(1000.f), //avoid soft body from 'exploding' so use some upper threshold of maximum motion that a node can travel per frame
- water_normal(0, 0, 0),
- m_broadphase(0),
- m_dispatcher(0),
- m_gravity(0, -10, 0)
- {
- }
-};
-
-///The btSoftBody is an class to simulate cloth and volumetric soft bodies.
-///There is two-way interaction between btSoftBody and btRigidBody/btCollisionObject.
-class btSoftBody : public btCollisionObject
-{
-public:
- btAlignedObjectArray<const class btCollisionObject*> m_collisionDisabledObjects;
-
- // The solver object that handles this soft body
- btSoftBodySolver* m_softBodySolver;
-
- //
- // Enumerations
- //
-
- ///eAeroModel
- struct eAeroModel
- {
- enum _
- {
- V_Point, ///Vertex normals are oriented toward velocity
- V_TwoSided, ///Vertex normals are flipped to match velocity
- V_TwoSidedLiftDrag, ///Vertex normals are flipped to match velocity and lift and drag forces are applied
- V_OneSided, ///Vertex normals are taken as it is
- F_TwoSided, ///Face normals are flipped to match velocity
- F_TwoSidedLiftDrag, ///Face normals are flipped to match velocity and lift and drag forces are applied
- F_OneSided, ///Face normals are taken as it is
- END
- };
- };
-
- ///eVSolver : velocities solvers
- struct eVSolver
- {
- enum _
- {
- Linear, ///Linear solver
- END
- };
- };
-
- ///ePSolver : positions solvers
- struct ePSolver
- {
- enum _
- {
- Linear, ///Linear solver
- Anchors, ///Anchor solver
- RContacts, ///Rigid contacts solver
- SContacts, ///Soft contacts solver
- END
- };
- };
-
- ///eSolverPresets
- struct eSolverPresets
- {
- enum _
- {
- Positions,
- Velocities,
- Default = Positions,
- END
- };
- };
-
- ///eFeature
- struct eFeature
- {
- enum _
- {
- None,
- Node,
- Link,
- Face,
- Tetra,
- END
- };
- };
-
- typedef btAlignedObjectArray<eVSolver::_> tVSolverArray;
- typedef btAlignedObjectArray<ePSolver::_> tPSolverArray;
-
- //
- // Flags
- //
-
- ///fCollision
- struct fCollision
- {
- enum _
- {
- RVSmask = 0x000f, ///Rigid versus soft mask
- SDF_RS = 0x0001, ///SDF based rigid vs soft
- CL_RS = 0x0002, ///Cluster vs convex rigid vs soft
- SDF_RD = 0x0004, ///rigid vs deformable
-
- SVSmask = 0x00f0, ///Rigid versus soft mask
- VF_SS = 0x0010, ///Vertex vs face soft vs soft handling
- CL_SS = 0x0020, ///Cluster vs cluster soft vs soft handling
- CL_SELF = 0x0040, ///Cluster soft body self collision
- VF_DD = 0x0080, ///Vertex vs face soft vs soft handling
-
- RVDFmask = 0x0f00, /// Rigid versus deformable face mask
- SDF_RDF = 0x0100, /// GJK based Rigid vs. deformable face
- SDF_MDF = 0x0200, /// GJK based Multibody vs. deformable face
- SDF_RDN = 0x0400, /// SDF based Rigid vs. deformable node
- /* presets */
- Default = SDF_RS,
- END
- };
- };
-
- ///fMaterial
- struct fMaterial
- {
- enum _
- {
- DebugDraw = 0x0001, /// Enable debug draw
- /* presets */
- Default = DebugDraw,
- END
- };
- };
-
- //
- // API Types
- //
-
- /* sRayCast */
- struct sRayCast
- {
- btSoftBody* body; /// soft body
- eFeature::_ feature; /// feature type
- int index; /// feature index
- btScalar fraction; /// time of impact fraction (rayorg+(rayto-rayfrom)*fraction)
- };
-
- /* ImplicitFn */
- struct ImplicitFn
- {
- virtual ~ImplicitFn() {}
- virtual btScalar Eval(const btVector3& x) = 0;
- };
-
- //
- // Internal types
- //
-
- typedef btAlignedObjectArray<btScalar> tScalarArray;
- typedef btAlignedObjectArray<btVector3> tVector3Array;
-
- /* sCti is Softbody contact info */
- struct sCti
- {
- const btCollisionObject* m_colObj; /* Rigid body */
- btVector3 m_normal; /* Outward normal */
- btScalar m_offset; /* Offset from origin */
- btVector3 m_bary; /* Barycentric weights for faces */
- };
-
- /* sMedium */
- struct sMedium
- {
- btVector3 m_velocity; /* Velocity */
- btScalar m_pressure; /* Pressure */
- btScalar m_density; /* Density */
- };
-
- /* Base type */
- struct Element
- {
- void* m_tag; // User data
- Element() : m_tag(0) {}
- };
- /* Material */
- struct Material : Element
- {
- btScalar m_kLST; // Linear stiffness coefficient [0,1]
- btScalar m_kAST; // Area/Angular stiffness coefficient [0,1]
- btScalar m_kVST; // Volume stiffness coefficient [0,1]
- int m_flags; // Flags
- };
-
- /* Feature */
- struct Feature : Element
- {
- Material* m_material; // Material
- };
- /* Node */
- struct RenderNode
- {
- btVector3 m_x;
- btVector3 m_uv1;
- btVector3 m_normal;
- };
- struct Node : Feature
- {
- btVector3 m_x; // Position
- btVector3 m_q; // Previous step position/Test position
- btVector3 m_v; // Velocity
- btVector3 m_vn; // Previous step velocity
- btVector3 m_f; // Force accumulator
- btVector3 m_n; // Normal
- btScalar m_im; // 1/mass
- btScalar m_area; // Area
- btDbvtNode* m_leaf; // Leaf data
- int m_constrained; // depth of penetration
- int m_battach : 1; // Attached
- int index;
- btVector3 m_splitv; // velocity associated with split impulse
- btMatrix3x3 m_effectiveMass; // effective mass in contact
- btMatrix3x3 m_effectiveMass_inv; // inverse of effective mass
- };
- /* Link */
- ATTRIBUTE_ALIGNED16(struct)
- Link : Feature
- {
- btVector3 m_c3; // gradient
- Node* m_n[2]; // Node pointers
- btScalar m_rl; // Rest length
- int m_bbending : 1; // Bending link
- btScalar m_c0; // (ima+imb)*kLST
- btScalar m_c1; // rl^2
- btScalar m_c2; // |gradient|^2/c0
-
- BT_DECLARE_ALIGNED_ALLOCATOR();
- };
- struct RenderFace
- {
- RenderNode* m_n[3]; // Node pointers
- };
-
- /* Face */
- struct Face : Feature
- {
- Node* m_n[3]; // Node pointers
- btVector3 m_normal; // Normal
- btScalar m_ra; // Rest area
- btDbvtNode* m_leaf; // Leaf data
- btVector4 m_pcontact; // barycentric weights of the persistent contact
- btVector3 m_n0, m_n1, m_vn;
- int m_index;
- };
- /* Tetra */
- struct Tetra : Feature
- {
- Node* m_n[4]; // Node pointers
- btScalar m_rv; // Rest volume
- btDbvtNode* m_leaf; // Leaf data
- btVector3 m_c0[4]; // gradients
- btScalar m_c1; // (4*kVST)/(im0+im1+im2+im3)
- btScalar m_c2; // m_c1/sum(|g0..3|^2)
- btMatrix3x3 m_Dm_inverse; // rest Dm^-1
- btMatrix3x3 m_F;
- btScalar m_element_measure;
- btVector4 m_P_inv[3]; // first three columns of P_inv matrix
- };
-
- /* TetraScratch */
- struct TetraScratch
- {
- btMatrix3x3 m_F; // deformation gradient F
- btScalar m_trace; // trace of F^T * F
- btScalar m_J; // det(F)
- btMatrix3x3 m_cofF; // cofactor of F
- btMatrix3x3 m_corotation; // corotatio of the tetra
- };
-
- /* RContact */
- struct RContact
- {
- sCti m_cti; // Contact infos
- Node* m_node; // Owner node
- btMatrix3x3 m_c0; // Impulse matrix
- btVector3 m_c1; // Relative anchor
- btScalar m_c2; // ima*dt
- btScalar m_c3; // Friction
- btScalar m_c4; // Hardness
-
- // jacobians and unit impulse responses for multibody
- btMultiBodyJacobianData jacobianData_normal;
- btMultiBodyJacobianData jacobianData_t1;
- btMultiBodyJacobianData jacobianData_t2;
- btVector3 t1;
- btVector3 t2;
- };
-
- class DeformableRigidContact
- {
- public:
- sCti m_cti; // Contact infos
- btMatrix3x3 m_c0; // Impulse matrix
- btVector3 m_c1; // Relative anchor
- btScalar m_c2; // inverse mass of node/face
- btScalar m_c3; // Friction
- btScalar m_c4; // Hardness
- btMatrix3x3 m_c5; // inverse effective mass
-
- // jacobians and unit impulse responses for multibody
- btMultiBodyJacobianData jacobianData_normal;
- btMultiBodyJacobianData jacobianData_t1;
- btMultiBodyJacobianData jacobianData_t2;
- btVector3 t1;
- btVector3 t2;
- };
-
- class DeformableNodeRigidContact : public DeformableRigidContact
- {
- public:
- Node* m_node; // Owner node
- };
-
- class DeformableNodeRigidAnchor : public DeformableNodeRigidContact
- {
- public:
- btVector3 m_local; // Anchor position in body space
- };
-
- class DeformableFaceRigidContact : public DeformableRigidContact
- {
- public:
- Face* m_face; // Owner face
- btVector3 m_contactPoint; // Contact point
- btVector3 m_bary; // Barycentric weights
- btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
- };
-
- struct DeformableFaceNodeContact
- {
- Node* m_node; // Node
- Face* m_face; // Face
- btVector3 m_bary; // Barycentric weights
- btVector3 m_weights; // v_contactPoint * m_weights[i] = m_face->m_node[i]->m_v;
- btVector3 m_normal; // Normal
- btScalar m_margin; // Margin
- btScalar m_friction; // Friction
- btScalar m_imf; // inverse mass of the face at contact point
- btScalar m_c0; // scale of the impulse matrix;
- };
-
- /* SContact */
- struct SContact
- {
- Node* m_node; // Node
- Face* m_face; // Face
- btVector3 m_weights; // Weigths
- btVector3 m_normal; // Normal
- btScalar m_margin; // Margin
- btScalar m_friction; // Friction
- btScalar m_cfm[2]; // Constraint force mixing
- };
- /* Anchor */
- struct Anchor
- {
- Node* m_node; // Node pointer
- btVector3 m_local; // Anchor position in body space
- btRigidBody* m_body; // Body
- btScalar m_influence;
- btMatrix3x3 m_c0; // Impulse matrix
- btVector3 m_c1; // Relative anchor
- btScalar m_c2; // ima*dt
- };
- /* Note */
- struct Note : Element
- {
- const char* m_text; // Text
- btVector3 m_offset; // Offset
- int m_rank; // Rank
- Node* m_nodes[4]; // Nodes
- btScalar m_coords[4]; // Coordinates
- };
- /* Pose */
- struct Pose
- {
- bool m_bvolume; // Is valid
- bool m_bframe; // Is frame
- btScalar m_volume; // Rest volume
- tVector3Array m_pos; // Reference positions
- tScalarArray m_wgh; // Weights
- btVector3 m_com; // COM
- btMatrix3x3 m_rot; // Rotation
- btMatrix3x3 m_scl; // Scale
- btMatrix3x3 m_aqq; // Base scaling
- };
- /* Cluster */
- struct Cluster
- {
- tScalarArray m_masses;
- btAlignedObjectArray<Node*> m_nodes;
- tVector3Array m_framerefs;
- btTransform m_framexform;
- btScalar m_idmass;
- btScalar m_imass;
- btMatrix3x3 m_locii;
- btMatrix3x3 m_invwi;
- btVector3 m_com;
- btVector3 m_vimpulses[2];
- btVector3 m_dimpulses[2];
- int m_nvimpulses;
- int m_ndimpulses;
- btVector3 m_lv;
- btVector3 m_av;
- btDbvtNode* m_leaf;
- btScalar m_ndamping; /* Node damping */
- btScalar m_ldamping; /* Linear damping */
- btScalar m_adamping; /* Angular damping */
- btScalar m_matching;
- btScalar m_maxSelfCollisionImpulse;
- btScalar m_selfCollisionImpulseFactor;
- bool m_containsAnchor;
- bool m_collide;
- int m_clusterIndex;
- Cluster() : m_leaf(0), m_ndamping(0), m_ldamping(0), m_adamping(0), m_matching(0), m_maxSelfCollisionImpulse(100.f), m_selfCollisionImpulseFactor(0.01f), m_containsAnchor(false)
- {
- }
- };
- /* Impulse */
- struct Impulse
- {
- btVector3 m_velocity;
- btVector3 m_drift;
- int m_asVelocity : 1;
- int m_asDrift : 1;
- Impulse() : m_velocity(0, 0, 0), m_drift(0, 0, 0), m_asVelocity(0), m_asDrift(0) {}
- Impulse operator-() const
- {
- Impulse i = *this;
- i.m_velocity = -i.m_velocity;
- i.m_drift = -i.m_drift;
- return (i);
- }
- Impulse operator*(btScalar x) const
- {
- Impulse i = *this;
- i.m_velocity *= x;
- i.m_drift *= x;
- return (i);
- }
- };
- /* Body */
- struct Body
- {
- Cluster* m_soft;
- btRigidBody* m_rigid;
- const btCollisionObject* m_collisionObject;
-
- Body() : m_soft(0), m_rigid(0), m_collisionObject(0) {}
- Body(Cluster* p) : m_soft(p), m_rigid(0), m_collisionObject(0) {}
- Body(const btCollisionObject* colObj) : m_soft(0), m_collisionObject(colObj)
- {
- m_rigid = (btRigidBody*)btRigidBody::upcast(m_collisionObject);
- }
-
- void activate() const
- {
- if (m_rigid)
- m_rigid->activate();
- if (m_collisionObject)
- m_collisionObject->activate();
- }
- const btMatrix3x3& invWorldInertia() const
- {
- static const btMatrix3x3 iwi(0, 0, 0, 0, 0, 0, 0, 0, 0);
- if (m_rigid) return (m_rigid->getInvInertiaTensorWorld());
- if (m_soft) return (m_soft->m_invwi);
- return (iwi);
- }
- btScalar invMass() const
- {
- if (m_rigid) return (m_rigid->getInvMass());
- if (m_soft) return (m_soft->m_imass);
- return (0);
- }
- const btTransform& xform() const
- {
- static const btTransform identity = btTransform::getIdentity();
- if (m_collisionObject) return (m_collisionObject->getWorldTransform());
- if (m_soft) return (m_soft->m_framexform);
- return (identity);
- }
- btVector3 linearVelocity() const
- {
- if (m_rigid) return (m_rigid->getLinearVelocity());
- if (m_soft) return (m_soft->m_lv);
- return (btVector3(0, 0, 0));
- }
- btVector3 angularVelocity(const btVector3& rpos) const
- {
- if (m_rigid) return (btCross(m_rigid->getAngularVelocity(), rpos));
- if (m_soft) return (btCross(m_soft->m_av, rpos));
- return (btVector3(0, 0, 0));
- }
- btVector3 angularVelocity() const
- {
- if (m_rigid) return (m_rigid->getAngularVelocity());
- if (m_soft) return (m_soft->m_av);
- return (btVector3(0, 0, 0));
- }
- btVector3 velocity(const btVector3& rpos) const
- {
- return (linearVelocity() + angularVelocity(rpos));
- }
- void applyVImpulse(const btVector3& impulse, const btVector3& rpos) const
- {
- if (m_rigid) m_rigid->applyImpulse(impulse, rpos);
- if (m_soft) btSoftBody::clusterVImpulse(m_soft, rpos, impulse);
- }
- void applyDImpulse(const btVector3& impulse, const btVector3& rpos) const
- {
- if (m_rigid) m_rigid->applyImpulse(impulse, rpos);
- if (m_soft) btSoftBody::clusterDImpulse(m_soft, rpos, impulse);
- }
- void applyImpulse(const Impulse& impulse, const btVector3& rpos) const
- {
- if (impulse.m_asVelocity)
- {
- // printf("impulse.m_velocity = %f,%f,%f\n",impulse.m_velocity.getX(),impulse.m_velocity.getY(),impulse.m_velocity.getZ());
- applyVImpulse(impulse.m_velocity, rpos);
- }
- if (impulse.m_asDrift)
- {
- // printf("impulse.m_drift = %f,%f,%f\n",impulse.m_drift.getX(),impulse.m_drift.getY(),impulse.m_drift.getZ());
- applyDImpulse(impulse.m_drift, rpos);
- }
- }
- void applyVAImpulse(const btVector3& impulse) const
- {
- if (m_rigid) m_rigid->applyTorqueImpulse(impulse);
- if (m_soft) btSoftBody::clusterVAImpulse(m_soft, impulse);
- }
- void applyDAImpulse(const btVector3& impulse) const
- {
- if (m_rigid) m_rigid->applyTorqueImpulse(impulse);
- if (m_soft) btSoftBody::clusterDAImpulse(m_soft, impulse);
- }
- void applyAImpulse(const Impulse& impulse) const
- {
- if (impulse.m_asVelocity) applyVAImpulse(impulse.m_velocity);
- if (impulse.m_asDrift) applyDAImpulse(impulse.m_drift);
- }
- void applyDCImpulse(const btVector3& impulse) const
- {
- if (m_rigid) m_rigid->applyCentralImpulse(impulse);
- if (m_soft) btSoftBody::clusterDCImpulse(m_soft, impulse);
- }
- };
- /* Joint */
- struct Joint
- {
- struct eType
- {
- enum _
- {
- Linear = 0,
- Angular,
- Contact
- };
- };
- struct Specs
- {
- Specs() : erp(1), cfm(1), split(1) {}
- btScalar erp;
- btScalar cfm;
- btScalar split;
- };
- Body m_bodies[2];
- btVector3 m_refs[2];
- btScalar m_cfm;
- btScalar m_erp;
- btScalar m_split;
- btVector3 m_drift;
- btVector3 m_sdrift;
- btMatrix3x3 m_massmatrix;
- bool m_delete;
- virtual ~Joint() {}
- Joint() : m_delete(false) {}
- virtual void Prepare(btScalar dt, int iterations);
- virtual void Solve(btScalar dt, btScalar sor) = 0;
- virtual void Terminate(btScalar dt) = 0;
- virtual eType::_ Type() const = 0;
- };
- /* LJoint */
- struct LJoint : Joint
- {
- struct Specs : Joint::Specs
- {
- btVector3 position;
- };
- btVector3 m_rpos[2];
- void Prepare(btScalar dt, int iterations);
- void Solve(btScalar dt, btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return (eType::Linear); }
- };
- /* AJoint */
- struct AJoint : Joint
- {
- struct IControl
- {
- virtual ~IControl() {}
- virtual void Prepare(AJoint*) {}
- virtual btScalar Speed(AJoint*, btScalar current) { return (current); }
- static IControl* Default()
- {
- static IControl def;
- return (&def);
- }
- };
- struct Specs : Joint::Specs
- {
- Specs() : icontrol(IControl::Default()) {}
- btVector3 axis;
- IControl* icontrol;
- };
- btVector3 m_axis[2];
- IControl* m_icontrol;
- void Prepare(btScalar dt, int iterations);
- void Solve(btScalar dt, btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return (eType::Angular); }
- };
- /* CJoint */
- struct CJoint : Joint
- {
- int m_life;
- int m_maxlife;
- btVector3 m_rpos[2];
- btVector3 m_normal;
- btScalar m_friction;
- void Prepare(btScalar dt, int iterations);
- void Solve(btScalar dt, btScalar sor);
- void Terminate(btScalar dt);
- eType::_ Type() const { return (eType::Contact); }
- };
- /* Config */
- struct Config
- {
- eAeroModel::_ aeromodel; // Aerodynamic model (default: V_Point)
- btScalar kVCF; // Velocities correction factor (Baumgarte)
- btScalar kDP; // Damping coefficient [0,1]
- btScalar kDG; // Drag coefficient [0,+inf]
- btScalar kLF; // Lift coefficient [0,+inf]
- btScalar kPR; // Pressure coefficient [-inf,+inf]
- btScalar kVC; // Volume conversation coefficient [0,+inf]
- btScalar kDF; // Dynamic friction coefficient [0,1]
- btScalar kMT; // Pose matching coefficient [0,1]
- btScalar kCHR; // Rigid contacts hardness [0,1]
- btScalar kKHR; // Kinetic contacts hardness [0,1]
- btScalar kSHR; // Soft contacts hardness [0,1]
- btScalar kAHR; // Anchors hardness [0,1]
- btScalar kSRHR_CL; // Soft vs rigid hardness [0,1] (cluster only)
- btScalar kSKHR_CL; // Soft vs kinetic hardness [0,1] (cluster only)
- btScalar kSSHR_CL; // Soft vs soft hardness [0,1] (cluster only)
- btScalar kSR_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar kSK_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar kSS_SPLT_CL; // Soft vs rigid impulse split [0,1] (cluster only)
- btScalar maxvolume; // Maximum volume ratio for pose
- btScalar timescale; // Time scale
- int viterations; // Velocities solver iterations
- int piterations; // Positions solver iterations
- int diterations; // Drift solver iterations
- int citerations; // Cluster solver iterations
- int collisions; // Collisions flags
- tVSolverArray m_vsequence; // Velocity solvers sequence
- tPSolverArray m_psequence; // Position solvers sequence
- tPSolverArray m_dsequence; // Drift solvers sequence
- btScalar drag; // deformable air drag
- btScalar m_maxStress; // Maximum principle first Piola stress
- };
- /* SolverState */
- struct SolverState
- {
- //if you add new variables, always initialize them!
- SolverState()
- : sdt(0),
- isdt(0),
- velmrg(0),
- radmrg(0),
- updmrg(0)
- {
- }
- btScalar sdt; // dt*timescale
- btScalar isdt; // 1/sdt
- btScalar velmrg; // velocity margin
- btScalar radmrg; // radial margin
- btScalar updmrg; // Update margin
- };
- /// RayFromToCaster takes a ray from, ray to (instead of direction!)
- struct RayFromToCaster : btDbvt::ICollide
- {
- btVector3 m_rayFrom;
- btVector3 m_rayTo;
- btVector3 m_rayNormalizedDirection;
- btScalar m_mint;
- Face* m_face;
- int m_tests;
- RayFromToCaster(const btVector3& rayFrom, const btVector3& rayTo, btScalar mxt);
- void Process(const btDbvtNode* leaf);
-
- static /*inline*/ btScalar rayFromToTriangle(const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& rayNormalizedDirection,
- const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btScalar maxt = SIMD_INFINITY);
- };
-
- //
- // Typedefs
- //
-
- typedef void (*psolver_t)(btSoftBody*, btScalar, btScalar);
- typedef void (*vsolver_t)(btSoftBody*, btScalar);
- typedef btAlignedObjectArray<Cluster*> tClusterArray;
- typedef btAlignedObjectArray<Note> tNoteArray;
- typedef btAlignedObjectArray<Node> tNodeArray;
- typedef btAlignedObjectArray< RenderNode> tRenderNodeArray;
- typedef btAlignedObjectArray<btDbvtNode*> tLeafArray;
- typedef btAlignedObjectArray<Link> tLinkArray;
- typedef btAlignedObjectArray<Face> tFaceArray;
- typedef btAlignedObjectArray<RenderFace> tRenderFaceArray;
- typedef btAlignedObjectArray<Tetra> tTetraArray;
- typedef btAlignedObjectArray<Anchor> tAnchorArray;
- typedef btAlignedObjectArray<RContact> tRContactArray;
- typedef btAlignedObjectArray<SContact> tSContactArray;
- typedef btAlignedObjectArray<Material*> tMaterialArray;
- typedef btAlignedObjectArray<Joint*> tJointArray;
- typedef btAlignedObjectArray<btSoftBody*> tSoftBodyArray;
-
- //
- // Fields
- //
-
- Config m_cfg; // Configuration
- SolverState m_sst; // Solver state
- Pose m_pose; // Pose
- void* m_tag; // User data
- btSoftBodyWorldInfo* m_worldInfo; // World info
- tNoteArray m_notes; // Notes
- tNodeArray m_nodes; // Nodes
- tRenderNodeArray m_renderNodes; // Render Nodes
- tLinkArray m_links; // Links
- tFaceArray m_faces; // Faces
- tRenderFaceArray m_renderFaces; // Faces
- tTetraArray m_tetras; // Tetras
- btAlignedObjectArray<TetraScratch> m_tetraScratches;
- btAlignedObjectArray<TetraScratch> m_tetraScratchesTn;
- tAnchorArray m_anchors; // Anchors
- btAlignedObjectArray<DeformableNodeRigidAnchor> m_deformableAnchors;
- tRContactArray m_rcontacts; // Rigid contacts
- btAlignedObjectArray<DeformableNodeRigidContact> m_nodeRigidContacts;
- btAlignedObjectArray<DeformableFaceNodeContact> m_faceNodeContacts;
- btAlignedObjectArray<DeformableFaceRigidContact> m_faceRigidContacts;
- tSContactArray m_scontacts; // Soft contacts
- tJointArray m_joints; // Joints
- tMaterialArray m_materials; // Materials
- btScalar m_timeacc; // Time accumulator
- btVector3 m_bounds[2]; // Spatial bounds
- bool m_bUpdateRtCst; // Update runtime constants
- btDbvt m_ndbvt; // Nodes tree
- btDbvt m_fdbvt; // Faces tree
- btDbvntNode* m_fdbvnt; // Faces tree with normals
- btDbvt m_cdbvt; // Clusters tree
- tClusterArray m_clusters; // Clusters
- btScalar m_dampingCoefficient; // Damping Coefficient
- btScalar m_sleepingThreshold;
- btScalar m_maxSpeedSquared;
- btAlignedObjectArray<btVector3> m_quads; // quadrature points for collision detection
- btScalar m_repulsionStiffness;
- btScalar m_gravityFactor;
- bool m_cacheBarycenter;
- btAlignedObjectArray<btVector3> m_X; // initial positions
-
- btAlignedObjectArray<btVector4> m_renderNodesInterpolationWeights;
- btAlignedObjectArray<btAlignedObjectArray<const btSoftBody::Node*> > m_renderNodesParents;
- btAlignedObjectArray<btScalar> m_z; // vertical distance used in extrapolation
- bool m_useSelfCollision;
- bool m_softSoftCollision;
-
- btAlignedObjectArray<bool> m_clusterConnectivity; //cluster connectivity, for self-collision
-
- btVector3 m_windVelocity;
-
- btScalar m_restLengthScale;
-
- //
- // Api
- //
-
- /* ctor */
- btSoftBody(btSoftBodyWorldInfo* worldInfo, int node_count, const btVector3* x, const btScalar* m);
-
- /* ctor */
- btSoftBody(btSoftBodyWorldInfo* worldInfo);
-
- void initDefaults();
-
- /* dtor */
- virtual ~btSoftBody();
- /* Check for existing link */
-
- btAlignedObjectArray<int> m_userIndexMapping;
-
- btSoftBodyWorldInfo* getWorldInfo()
- {
- return m_worldInfo;
- }
-
- void setDampingCoefficient(btScalar damping_coeff)
- {
- m_dampingCoefficient = damping_coeff;
- }
-
- ///@todo: avoid internal softbody shape hack and move collision code to collision library
- virtual void setCollisionShape(btCollisionShape* collisionShape)
- {
- }
-
- bool checkLink(int node0,
- int node1) const;
- bool checkLink(const Node* node0,
- const Node* node1) const;
- /* Check for existring face */
- bool checkFace(int node0,
- int node1,
- int node2) const;
- /* Append material */
- Material* appendMaterial();
- /* Append note */
- void appendNote(const char* text,
- const btVector3& o,
- const btVector4& c = btVector4(1, 0, 0, 0),
- Node* n0 = 0,
- Node* n1 = 0,
- Node* n2 = 0,
- Node* n3 = 0);
- void appendNote(const char* text,
- const btVector3& o,
- Node* feature);
- void appendNote(const char* text,
- const btVector3& o,
- Link* feature);
- void appendNote(const char* text,
- const btVector3& o,
- Face* feature);
- /* Append node */
- void appendNode(const btVector3& x, btScalar m);
- /* Append link */
- void appendLink(int model = -1, Material* mat = 0);
- void appendLink(int node0,
- int node1,
- Material* mat = 0,
- bool bcheckexist = false);
- void appendLink(Node* node0,
- Node* node1,
- Material* mat = 0,
- bool bcheckexist = false);
- /* Append face */
- void appendFace(int model = -1, Material* mat = 0);
- void appendFace(int node0,
- int node1,
- int node2,
- Material* mat = 0);
- void appendTetra(int model, Material* mat);
- //
- void appendTetra(int node0,
- int node1,
- int node2,
- int node3,
- Material* mat = 0);
-
- /* Append anchor */
- void appendDeformableAnchor(int node, btRigidBody* body);
- void appendDeformableAnchor(int node, btMultiBodyLinkCollider* link);
- void appendAnchor(int node,
- btRigidBody* body, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
- void appendAnchor(int node, btRigidBody* body, const btVector3& localPivot, bool disableCollisionBetweenLinkedBodies = false, btScalar influence = 1);
- void removeAnchor(int node);
- /* Append linear joint */
- void appendLinearJoint(const LJoint::Specs& specs, Cluster* body0, Body body1);
- void appendLinearJoint(const LJoint::Specs& specs, Body body = Body());
- void appendLinearJoint(const LJoint::Specs& specs, btSoftBody* body);
- /* Append linear joint */
- void appendAngularJoint(const AJoint::Specs& specs, Cluster* body0, Body body1);
- void appendAngularJoint(const AJoint::Specs& specs, Body body = Body());
- void appendAngularJoint(const AJoint::Specs& specs, btSoftBody* body);
- /* Add force (or gravity) to the entire body */
- void addForce(const btVector3& force);
- /* Add force (or gravity) to a node of the body */
- void addForce(const btVector3& force,
- int node);
- /* Add aero force to a node of the body */
- void addAeroForceToNode(const btVector3& windVelocity, int nodeIndex);
-
- /* Add aero force to a face of the body */
- void addAeroForceToFace(const btVector3& windVelocity, int faceIndex);
-
- /* Add velocity to the entire body */
- void addVelocity(const btVector3& velocity);
-
- /* Set velocity for the entire body */
- void setVelocity(const btVector3& velocity);
-
- /* Add velocity to a node of the body */
- void addVelocity(const btVector3& velocity,
- int node);
- /* Set mass */
- void setMass(int node,
- btScalar mass);
- /* Get mass */
- btScalar getMass(int node) const;
- /* Get total mass */
- btScalar getTotalMass() const;
- /* Set total mass (weighted by previous masses) */
- void setTotalMass(btScalar mass,
- bool fromfaces = false);
- /* Set total density */
- void setTotalDensity(btScalar density);
- /* Set volume mass (using tetrahedrons) */
- void setVolumeMass(btScalar mass);
- /* Set volume density (using tetrahedrons) */
- void setVolumeDensity(btScalar density);
- /* Get the linear velocity of the center of mass */
- btVector3 getLinearVelocity();
- /* Set the linear velocity of the center of mass */
- void setLinearVelocity(const btVector3& linVel);
- /* Set the angular velocity of the center of mass */
- void setAngularVelocity(const btVector3& angVel);
- /* Get best fit rigid transform */
- btTransform getRigidTransform();
- /* Transform to given pose */
- void transformTo(const btTransform& trs);
- /* Transform */
- void transform(const btTransform& trs);
- /* Translate */
- void translate(const btVector3& trs);
- /* Rotate */
- void rotate(const btQuaternion& rot);
- /* Scale */
- void scale(const btVector3& scl);
- /* Get link resting lengths scale */
- btScalar getRestLengthScale();
- /* Scale resting length of all springs */
- void setRestLengthScale(btScalar restLength);
- /* Set current state as pose */
- void setPose(bool bvolume,
- bool bframe);
- /* Set current link lengths as resting lengths */
- void resetLinkRestLengths();
- /* Return the volume */
- btScalar getVolume() const;
- /* Cluster count */
- btVector3 getCenterOfMass() const
- {
- btVector3 com(0, 0, 0);
- for (int i = 0; i < m_nodes.size(); i++)
- {
- com += (m_nodes[i].m_x * this->getMass(i));
- }
- com /= this->getTotalMass();
- return com;
- }
- int clusterCount() const;
- /* Cluster center of mass */
- static btVector3 clusterCom(const Cluster* cluster);
- btVector3 clusterCom(int cluster) const;
- /* Cluster velocity at rpos */
- static btVector3 clusterVelocity(const Cluster* cluster, const btVector3& rpos);
- /* Cluster impulse */
- static void clusterVImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse);
- static void clusterDImpulse(Cluster* cluster, const btVector3& rpos, const btVector3& impulse);
- static void clusterImpulse(Cluster* cluster, const btVector3& rpos, const Impulse& impulse);
- static void clusterVAImpulse(Cluster* cluster, const btVector3& impulse);
- static void clusterDAImpulse(Cluster* cluster, const btVector3& impulse);
- static void clusterAImpulse(Cluster* cluster, const Impulse& impulse);
- static void clusterDCImpulse(Cluster* cluster, const btVector3& impulse);
- /* Generate bending constraints based on distance in the adjency graph */
- int generateBendingConstraints(int distance,
- Material* mat = 0);
- /* Randomize constraints to reduce solver bias */
- void randomizeConstraints();
- /* Release clusters */
- void releaseCluster(int index);
- void releaseClusters();
- /* Generate clusters (K-mean) */
- ///generateClusters with k=0 will create a convex cluster for each tetrahedron or triangle
- ///otherwise an approximation will be used (better performance)
- int generateClusters(int k, int maxiterations = 8192);
- /* Refine */
- void refine(ImplicitFn* ifn, btScalar accurary, bool cut);
- /* CutLink */
- bool cutLink(int node0, int node1, btScalar position);
- bool cutLink(const Node* node0, const Node* node1, btScalar position);
-
- ///Ray casting using rayFrom and rayTo in worldspace, (not direction!)
- bool rayTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results);
- bool rayFaceTest(const btVector3& rayFrom,
- const btVector3& rayTo,
- sRayCast& results);
- int rayFaceTest(const btVector3& rayFrom, const btVector3& rayTo,
- btScalar& mint, int& index) const;
- /* Solver presets */
- void setSolver(eSolverPresets::_ preset);
- /* predictMotion */
- void predictMotion(btScalar dt);
- /* solveConstraints */
- void solveConstraints();
- /* staticSolve */
- void staticSolve(int iterations);
- /* solveCommonConstraints */
- static void solveCommonConstraints(btSoftBody** bodies, int count, int iterations);
- /* solveClusters */
- static void solveClusters(const btAlignedObjectArray<btSoftBody*>& bodies);
- /* integrateMotion */
- void integrateMotion();
- /* defaultCollisionHandlers */
- void defaultCollisionHandler(const btCollisionObjectWrapper* pcoWrap);
- void defaultCollisionHandler(btSoftBody* psb);
- void setSelfCollision(bool useSelfCollision);
- bool useSelfCollision();
- void updateDeactivation(btScalar timeStep);
- void setZeroVelocity();
- bool wantsSleeping();
-
- //
- // Functionality to deal with new accelerated solvers.
- //
-
- /**
- * Set a wind velocity for interaction with the air.
- */
- void setWindVelocity(const btVector3& velocity);
-
- /**
- * Return the wind velocity for interaction with the air.
- */
- const btVector3& getWindVelocity();
-
- //
- // Set the solver that handles this soft body
- // Should not be allowed to get out of sync with reality
- // Currently called internally on addition to the world
- void setSoftBodySolver(btSoftBodySolver* softBodySolver)
- {
- m_softBodySolver = softBodySolver;
- }
-
- //
- // Return the solver that handles this soft body
- //
- btSoftBodySolver* getSoftBodySolver()
- {
- return m_softBodySolver;
- }
-
- //
- // Return the solver that handles this soft body
- //
- btSoftBodySolver* getSoftBodySolver() const
- {
- return m_softBodySolver;
- }
-
- //
- // Cast
- //
-
- static const btSoftBody* upcast(const btCollisionObject* colObj)
- {
- if (colObj->getInternalType() == CO_SOFT_BODY)
- return (const btSoftBody*)colObj;
- return 0;
- }
- static btSoftBody* upcast(btCollisionObject* colObj)
- {
- if (colObj->getInternalType() == CO_SOFT_BODY)
- return (btSoftBody*)colObj;
- return 0;
- }
-
- //
- // ::btCollisionObject
- //
-
- virtual void getAabb(btVector3& aabbMin, btVector3& aabbMax) const
- {
- aabbMin = m_bounds[0];
- aabbMax = m_bounds[1];
- }
- //
- // Private
- //
- void pointersToIndices();
- void indicesToPointers(const int* map = 0);
-
- int rayTest(const btVector3& rayFrom, const btVector3& rayTo,
- btScalar& mint, eFeature::_& feature, int& index, bool bcountonly) const;
- void initializeFaceTree();
- void rebuildNodeTree();
- btVector3 evaluateCom() const;
- bool checkDeformableContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
- bool checkDeformableFaceContact(const btCollisionObjectWrapper* colObjWrap, Face& f, btVector3& contact_point, btVector3& bary, btScalar margin, btSoftBody::sCti& cti, bool predict = false) const;
- bool checkContact(const btCollisionObjectWrapper* colObjWrap, const btVector3& x, btScalar margin, btSoftBody::sCti& cti) const;
- void updateNormals();
- void updateBounds();
- void updatePose();
- void updateConstants();
- void updateLinkConstants();
- void updateArea(bool averageArea = true);
- void initializeClusters();
- void updateClusters();
- void cleanupClusters();
- void prepareClusters(int iterations);
- void solveClusters(btScalar sor);
- void applyClusters(bool drift);
- void dampClusters();
- void setSpringStiffness(btScalar k);
- void setGravityFactor(btScalar gravFactor);
- void setCacheBarycenter(bool cacheBarycenter);
- void initializeDmInverse();
- void updateDeformation();
- void advanceDeformation();
- void applyForces();
- void setMaxStress(btScalar maxStress);
- void interpolateRenderMesh();
- void setCollisionQuadrature(int N);
- static void PSolve_Anchors(btSoftBody* psb, btScalar kst, btScalar ti);
- static void PSolve_RContacts(btSoftBody* psb, btScalar kst, btScalar ti);
- static void PSolve_SContacts(btSoftBody* psb, btScalar, btScalar ti);
- static void PSolve_Links(btSoftBody* psb, btScalar kst, btScalar ti);
- static void VSolve_Links(btSoftBody* psb, btScalar kst);
- static psolver_t getSolver(ePSolver::_ solver);
- static vsolver_t getSolver(eVSolver::_ solver);
- void geometricCollisionHandler(btSoftBody* psb);
-#define SAFE_EPSILON SIMD_EPSILON * 100.0
- void updateNode(btDbvtNode* node, bool use_velocity, bool margin)
- {
- if (node->isleaf())
- {
- btSoftBody::Node* n = (btSoftBody::Node*)(node->data);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
- if (use_velocity)
- {
- btVector3 points[2] = {n->m_x, n->m_x + m_sst.sdt * n->m_v};
- vol = btDbvtVolume::FromPoints(points, 2);
- vol.Expand(btVector3(pad, pad, pad));
- }
- else
- {
- vol = btDbvtVolume::FromCR(n->m_x, pad);
- }
- node->volume = vol;
- return;
- }
- else
- {
- updateNode(node->childs[0], use_velocity, margin);
- updateNode(node->childs[1], use_velocity, margin);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
- node->volume = vol;
- }
- }
-
- void updateNodeTree(bool use_velocity, bool margin)
- {
- if (m_ndbvt.m_root)
- updateNode(m_ndbvt.m_root, use_velocity, margin);
- }
-
- template <class DBVTNODE> // btDbvtNode or btDbvntNode
- void updateFace(DBVTNODE* node, bool use_velocity, bool margin)
- {
- if (node->isleaf())
- {
- btSoftBody::Face* f = (btSoftBody::Face*)(node->data);
- btScalar pad = margin ? m_sst.radmrg : SAFE_EPSILON; // use user defined margin or margin for floating point precision
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- if (use_velocity)
- {
- btVector3 points[6] = {f->m_n[0]->m_x, f->m_n[0]->m_x + m_sst.sdt * f->m_n[0]->m_v,
- f->m_n[1]->m_x, f->m_n[1]->m_x + m_sst.sdt * f->m_n[1]->m_v,
- f->m_n[2]->m_x, f->m_n[2]->m_x + m_sst.sdt * f->m_n[2]->m_v};
- vol = btDbvtVolume::FromPoints(points, 6);
- }
- else
- {
- btVector3 points[3] = {f->m_n[0]->m_x,
- f->m_n[1]->m_x,
- f->m_n[2]->m_x};
- vol = btDbvtVolume::FromPoints(points, 3);
- }
- vol.Expand(btVector3(pad, pad, pad));
- node->volume = vol;
- return;
- }
- else
- {
- updateFace(node->childs[0], use_velocity, margin);
- updateFace(node->childs[1], use_velocity, margin);
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- vol;
- Merge(node->childs[0]->volume, node->childs[1]->volume, vol);
- node->volume = vol;
- }
- }
- void updateFaceTree(bool use_velocity, bool margin)
- {
- if (m_fdbvt.m_root)
- updateFace(m_fdbvt.m_root, use_velocity, margin);
- if (m_fdbvnt)
- updateFace(m_fdbvnt, use_velocity, margin);
- }
-
- template <typename T>
- static inline T BaryEval(const T& a,
- const T& b,
- const T& c,
- const btVector3& coord)
- {
- return (a * coord.x() + b * coord.y() + c * coord.z());
- }
-
- void applyRepulsionForce(btScalar timeStep, bool applySpringForce)
- {
- btAlignedObjectArray<int> indices;
- {
- // randomize the order of repulsive force
- indices.resize(m_faceNodeContacts.size());
- for (int i = 0; i < m_faceNodeContacts.size(); ++i)
- indices[i] = i;
-#define NEXTRAND (seed = (1664525L * seed + 1013904223L) & 0xffffffff)
- int i, ni;
-
- for (i = 0, ni = indices.size(); i < ni; ++i)
- {
- btSwap(indices[i], indices[NEXTRAND % ni]);
- }
- }
- for (int k = 0; k < m_faceNodeContacts.size(); ++k)
- {
- int idx = indices[k];
- btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[idx];
- btSoftBody::Node* node = c.m_node;
- btSoftBody::Face* face = c.m_face;
- const btVector3& w = c.m_bary;
- const btVector3& n = c.m_normal;
- btVector3 l = node->m_x - BaryEval(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, w);
- btScalar d = c.m_margin - n.dot(l);
- d = btMax(btScalar(0), d);
-
- const btVector3& va = node->m_v;
- btVector3 vb = BaryEval(face->m_n[0]->m_v, face->m_n[1]->m_v, face->m_n[2]->m_v, w);
- btVector3 vr = va - vb;
- const btScalar vn = btDot(vr, n); // dn < 0 <==> opposing
- if (vn > OVERLAP_REDUCTION_FACTOR * d / timeStep)
- continue;
- btVector3 vt = vr - vn * n;
- btScalar I = 0;
- btScalar mass = node->m_im == 0 ? 0 : btScalar(1) / node->m_im;
- if (applySpringForce)
- I = -btMin(m_repulsionStiffness * timeStep * d, mass * (OVERLAP_REDUCTION_FACTOR * d / timeStep - vn));
- if (vn < 0)
- I += 0.5 * mass * vn;
- int face_penetration = 0, node_penetration = node->m_constrained;
- for (int i = 0; i < 3; ++i)
- face_penetration |= face->m_n[i]->m_constrained;
- btScalar I_tilde = 2.0 * I / (1.0 + w.length2());
-
- // double the impulse if node or face is constrained.
- if (face_penetration > 0 || node_penetration > 0)
- {
- I_tilde *= 2.0;
- }
- if (face_penetration <= 0)
- {
- for (int j = 0; j < 3; ++j)
- face->m_n[j]->m_v += w[j] * n * I_tilde * node->m_im;
- }
- if (node_penetration <= 0)
- {
- node->m_v -= I_tilde * node->m_im * n;
- }
-
- // apply frictional impulse
- btScalar vt_norm = vt.safeNorm();
- if (vt_norm > SIMD_EPSILON)
- {
- btScalar delta_vn = -2 * I * node->m_im;
- btScalar mu = c.m_friction;
- btScalar vt_new = btMax(btScalar(1) - mu * delta_vn / (vt_norm + SIMD_EPSILON), btScalar(0)) * vt_norm;
- I = 0.5 * mass * (vt_norm - vt_new);
- vt.safeNormalize();
- I_tilde = 2.0 * I / (1.0 + w.length2());
- // double the impulse if node or face is constrained.
- if (face_penetration > 0 || node_penetration > 0)
- I_tilde *= 2.0;
- if (face_penetration <= 0)
- {
- for (int j = 0; j < 3; ++j)
- face->m_n[j]->m_v += w[j] * vt * I_tilde * (face->m_n[j])->m_im;
- }
- if (node_penetration <= 0)
- {
- node->m_v -= I_tilde * node->m_im * vt;
- }
- }
- }
- }
- virtual int calculateSerializeBufferSize() const;
-
- ///fills the dataBuffer and returns the struct name (and 0 on failure)
- virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
-};
-
-#endif //_BT_SOFT_BODY_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
deleted file mode 100644
index 750718f57f..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftBodyConcaveCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionShapes/btConcaveShape.h"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
-#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
-#include "BulletCollision/CollisionShapes/btTriangleShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
-#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-#include "LinearMath/btIDebugDraw.h"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
-#include "BulletSoftBody/btSoftBody.h"
-
-#define BT_SOFTBODY_TRIANGLE_EXTRUSION btScalar(0.06) //make this configurable
-
-btSoftBodyConcaveCollisionAlgorithm::btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped)
- : btCollisionAlgorithm(ci),
- m_isSwapped(isSwapped),
- m_btSoftBodyTriangleCallback(ci.m_dispatcher1, body0Wrap, body1Wrap, isSwapped)
-{
-}
-
-btSoftBodyConcaveCollisionAlgorithm::~btSoftBodyConcaveCollisionAlgorithm()
-{
-}
-
-btSoftBodyTriangleCallback::btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped) : m_dispatcher(dispatcher),
- m_dispatchInfoPtr(0)
-{
- m_softBody = (isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject());
- m_triBody = isSwapped ? body0Wrap->getCollisionObject() : body1Wrap->getCollisionObject();
-
- //
- // create the manifold from the dispatcher 'manifold pool'
- //
- // m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
-
- clearCache();
-}
-
-btSoftBodyTriangleCallback::~btSoftBodyTriangleCallback()
-{
- clearCache();
- // m_dispatcher->releaseManifold( m_manifoldPtr );
-}
-
-void btSoftBodyTriangleCallback::clearCache()
-{
- for (int i = 0; i < m_shapeCache.size(); i++)
- {
- btTriIndex* tmp = m_shapeCache.getAtIndex(i);
- btAssert(tmp);
- btAssert(tmp->m_childShape);
- m_softBody->getWorldInfo()->m_sparsesdf.RemoveReferences(tmp->m_childShape); //necessary?
- delete tmp->m_childShape;
- }
- m_shapeCache.clear();
-}
-
-void btSoftBodyTriangleCallback::processTriangle(btVector3* triangle, int partId, int triangleIndex)
-{
- //just for debugging purposes
- //printf("triangle %d",m_triangleCount++);
-
- btCollisionAlgorithmConstructionInfo ci;
- ci.m_dispatcher1 = m_dispatcher;
-
- ///debug drawing of the overlapping triangles
- if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawWireframe))
- {
- btVector3 color(1, 1, 0);
- const btTransform& tr = m_triBody->getWorldTransform();
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]), tr(triangle[1]), color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]), tr(triangle[2]), color);
- m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]), tr(triangle[0]), color);
- }
-
- btTriIndex triIndex(partId, triangleIndex, 0);
- btHashKey<btTriIndex> triKey(triIndex.getUid());
-
- btTriIndex* shapeIndex = m_shapeCache[triKey];
- if (shapeIndex)
- {
- btCollisionShape* tm = shapeIndex->m_childShape;
- btAssert(tm);
-
- //copy over user pointers to temporary shape
- tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
-
- btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
- //btCollisionObjectWrapper triBody(0,tm, ob, btTransform::getIdentity());//ob->getWorldTransform());//??
- btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex);
- ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType); //m_manifoldPtr);
-
- colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
- colAlgo->~btCollisionAlgorithm();
- ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
-
- return;
- }
-
- //aabb filter is already applied!
-
- //btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
-
- // if (m_softBody->getCollisionShape()->getShapeType()==
- {
- // btVector3 other;
- btVector3 normal = (triangle[1] - triangle[0]).cross(triangle[2] - triangle[0]);
- normal.normalize();
- normal *= BT_SOFTBODY_TRIANGLE_EXTRUSION;
- // other=(triangle[0]+triangle[1]+triangle[2])*0.333333f;
- // other+=normal*22.f;
- btVector3 pts[6] = {triangle[0] + normal,
- triangle[1] + normal,
- triangle[2] + normal,
- triangle[0] - normal,
- triangle[1] - normal,
- triangle[2] - normal};
-
- btConvexHullShape* tm = new btConvexHullShape(&pts[0].getX(), 6);
-
- // btBU_Simplex1to4 tm(triangle[0],triangle[1],triangle[2],other);
-
- //btTriangleShape tm(triangle[0],triangle[1],triangle[2]);
- // tm.setMargin(m_collisionMarginTriangle);
-
- //copy over user pointers to temporary shape
- tm->setUserPointer(m_triBody->getCollisionShape()->getUserPointer());
-
- btCollisionObjectWrapper softBody(0, m_softBody->getCollisionShape(), m_softBody, m_softBody->getWorldTransform(), -1, -1);
- btCollisionObjectWrapper triBody(0, tm, m_triBody, m_triBody->getWorldTransform(), partId, triangleIndex); //btTransform::getIdentity());//??
-
- ebtDispatcherQueryType algoType = m_resultOut->m_closestPointDistanceThreshold > 0 ? BT_CLOSEST_POINT_ALGORITHMS : BT_CONTACT_POINT_ALGORITHMS;
- btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(&softBody, &triBody, 0, algoType); //m_manifoldPtr);
-
- colAlgo->processCollision(&softBody, &triBody, *m_dispatchInfoPtr, m_resultOut);
- colAlgo->~btCollisionAlgorithm();
- ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
-
- triIndex.m_childShape = tm;
- m_shapeCache.insert(triKey, triIndex);
- }
-}
-
-void btSoftBodyTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triBodyWrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- m_dispatchInfoPtr = &dispatchInfo;
- m_collisionMarginTriangle = collisionMarginTriangle + btScalar(BT_SOFTBODY_TRIANGLE_EXTRUSION);
- m_resultOut = resultOut;
-
- btVector3 aabbWorldSpaceMin, aabbWorldSpaceMax;
- m_softBody->getAabb(aabbWorldSpaceMin, aabbWorldSpaceMax);
- btVector3 halfExtents = (aabbWorldSpaceMax - aabbWorldSpaceMin) * btScalar(0.5);
- btVector3 softBodyCenter = (aabbWorldSpaceMax + aabbWorldSpaceMin) * btScalar(0.5);
-
- btTransform softTransform;
- softTransform.setIdentity();
- softTransform.setOrigin(softBodyCenter);
-
- btTransform convexInTriangleSpace;
- convexInTriangleSpace = triBodyWrap->getWorldTransform().inverse() * softTransform;
- btTransformAabb(halfExtents, m_collisionMarginTriangle, convexInTriangleSpace, m_aabbMin, m_aabbMax);
-}
-
-void btSoftBodyConcaveCollisionAlgorithm::clearCache()
-{
- m_btSoftBodyTriangleCallback.clearCache();
-}
-
-void btSoftBodyConcaveCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- //btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
- const btCollisionObjectWrapper* triBody = m_isSwapped ? body0Wrap : body1Wrap;
-
- if (triBody->getCollisionShape()->isConcave())
- {
- const btCollisionObject* triOb = triBody->getCollisionObject();
- const btConcaveShape* concaveShape = static_cast<const btConcaveShape*>(triOb->getCollisionShape());
-
- // if (convexBody->getCollisionShape()->isConvex())
- {
- btScalar collisionMarginTriangle = concaveShape->getMargin();
-
- // resultOut->setPersistentManifold(m_btSoftBodyTriangleCallback.m_manifoldPtr);
- m_btSoftBodyTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle, triBody, dispatchInfo, resultOut);
-
- concaveShape->processAllTriangles(&m_btSoftBodyTriangleCallback, m_btSoftBodyTriangleCallback.getAabbMin(), m_btSoftBodyTriangleCallback.getAabbMax());
-
- // resultOut->refreshContactPoints();
- }
- }
-}
-
-btScalar btSoftBodyConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
- btCollisionObject* triBody = m_isSwapped ? body0 : body1;
-
- //quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
-
- //only perform CCD above a certain threshold, this prevents blocking on the long run
- //because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
- btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
- if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
- {
- return btScalar(1.);
- }
-
- //const btVector3& from = convexbody->m_worldTransform.getOrigin();
- //btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
- //todo: only do if the motion exceeds the 'radius'
-
- btTransform triInv = triBody->getWorldTransform().inverse();
- btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
- btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
-
- struct LocalTriangleSphereCastCallback : public btTriangleCallback
- {
- btTransform m_ccdSphereFromTrans;
- btTransform m_ccdSphereToTrans;
- btTransform m_meshTransform;
-
- btScalar m_ccdSphereRadius;
- btScalar m_hitFraction;
-
- LocalTriangleSphereCastCallback(const btTransform& from, const btTransform& to, btScalar ccdSphereRadius, btScalar hitFraction)
- : m_ccdSphereFromTrans(from),
- m_ccdSphereToTrans(to),
- m_ccdSphereRadius(ccdSphereRadius),
- m_hitFraction(hitFraction)
- {
- }
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
- {
- (void)partId;
- (void)triangleIndex;
- //do a swept sphere for now
- btTransform ident;
- ident.setIdentity();
- btConvexCast::CastResult castResult;
- castResult.m_fraction = m_hitFraction;
- btSphereShape pointShape(m_ccdSphereRadius);
- btTriangleShape triShape(triangle[0], triangle[1], triangle[2]);
- btVoronoiSimplexSolver simplexSolver;
- btSubsimplexConvexCast convexCaster(&pointShape, &triShape, &simplexSolver);
- //GjkConvexCast convexCaster(&pointShape,convexShape,&simplexSolver);
- //ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
- //local space?
-
- if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans, m_ccdSphereToTrans,
- ident, ident, castResult))
- {
- if (m_hitFraction > castResult.m_fraction)
- m_hitFraction = castResult.m_fraction;
- }
- }
- };
-
- if (triBody->getCollisionShape()->isConcave())
- {
- btVector3 rayAabbMin = convexFromLocal.getOrigin();
- rayAabbMin.setMin(convexToLocal.getOrigin());
- btVector3 rayAabbMax = convexFromLocal.getOrigin();
- rayAabbMax.setMax(convexToLocal.getOrigin());
- btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
- rayAabbMin -= btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
- rayAabbMax += btVector3(ccdRadius0, ccdRadius0, ccdRadius0);
-
- btScalar curHitFraction = btScalar(1.); //is this available?
- LocalTriangleSphereCastCallback raycastCallback(convexFromLocal, convexToLocal,
- convexbody->getCcdSweptSphereRadius(), curHitFraction);
-
- raycastCallback.m_hitFraction = convexbody->getHitFraction();
-
- btCollisionObject* concavebody = triBody;
-
- btConcaveShape* triangleMesh = (btConcaveShape*)concavebody->getCollisionShape();
-
- if (triangleMesh)
- {
- triangleMesh->processAllTriangles(&raycastCallback, rayAabbMin, rayAabbMax);
- }
-
- if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
- {
- convexbody->setHitFraction(raycastCallback.m_hitFraction);
- return raycastCallback.m_hitFraction;
- }
- }
-
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
deleted file mode 100644
index 3adedbd805..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyConcaveCollisionAlgorithm.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
-#define BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
-class btDispatcher;
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-class btSoftBody;
-class btCollisionShape;
-
-#include "LinearMath/btHashMap.h"
-
-#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h" //for definition of MAX_NUM_PARTS_IN_BITS
-
-struct btTriIndex
-{
- int m_PartIdTriangleIndex;
- class btCollisionShape* m_childShape;
-
- btTriIndex(int partId, int triangleIndex, btCollisionShape* shape)
- {
- m_PartIdTriangleIndex = (partId << (31 - MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
- m_childShape = shape;
- }
-
- int getTriangleIndex() const
- {
- // Get only the lower bits where the triangle index is stored
- unsigned int x = 0;
- unsigned int y = (~(x & 0)) << (31 - MAX_NUM_PARTS_IN_BITS);
- return (m_PartIdTriangleIndex & ~(y));
- }
- int getPartId() const
- {
- // Get only the highest bits where the part index is stored
- return (m_PartIdTriangleIndex >> (31 - MAX_NUM_PARTS_IN_BITS));
- }
- int getUid() const
- {
- return m_PartIdTriangleIndex;
- }
-};
-
-///For each triangle in the concave mesh that overlaps with the AABB of a soft body (m_softBody), processTriangle is called.
-class btSoftBodyTriangleCallback : public btTriangleCallback
-{
- btSoftBody* m_softBody;
- const btCollisionObject* m_triBody;
-
- btVector3 m_aabbMin;
- btVector3 m_aabbMax;
-
- btManifoldResult* m_resultOut;
-
- btDispatcher* m_dispatcher;
- const btDispatcherInfo* m_dispatchInfoPtr;
- btScalar m_collisionMarginTriangle;
-
- btHashMap<btHashKey<btTriIndex>, btTriIndex> m_shapeCache;
-
-public:
- int m_triangleCount;
-
- // btPersistentManifold* m_manifoldPtr;
-
- btSoftBodyTriangleCallback(btDispatcher* dispatcher, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- void setTimeStepAndCounters(btScalar collisionMarginTriangle, const btCollisionObjectWrapper* triObjWrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual ~btSoftBodyTriangleCallback();
-
- virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
-
- void clearCache();
-
- SIMD_FORCE_INLINE const btVector3& getAabbMin() const
- {
- return m_aabbMin;
- }
- SIMD_FORCE_INLINE const btVector3& getAabbMax() const
- {
- return m_aabbMax;
- }
-};
-
-/// btSoftBodyConcaveCollisionAlgorithm supports collision between soft body shapes and (concave) trianges meshes.
-class btSoftBodyConcaveCollisionAlgorithm : public btCollisionAlgorithm
-{
- bool m_isSwapped;
-
- btSoftBodyTriangleCallback m_btSoftBodyTriangleCallback;
-
-public:
- btSoftBodyConcaveCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, bool isSwapped);
-
- virtual ~btSoftBodyConcaveCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- //we don't add any manifolds
- }
-
- void clearCache();
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, false);
- }
- };
-
- struct SwappedCreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftBodyConcaveCollisionAlgorithm));
- return new (mem) btSoftBodyConcaveCollisionAlgorithm(ci, body0Wrap, body1Wrap, true);
- }
- };
-};
-
-#endif //BT_SOFT_BODY_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h
deleted file mode 100644
index cec6f401ec..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyData.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFTBODY_FLOAT_DATA
-#define BT_SOFTBODY_FLOAT_DATA
-
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-struct SoftBodyMaterialData
-{
- float m_linearStiffness;
- float m_angularStiffness;
- float m_volumeStiffness;
- int m_flags;
-};
-
-struct SoftBodyNodeData
-{
- SoftBodyMaterialData *m_material;
- btVector3FloatData m_position;
- btVector3FloatData m_previousPosition;
- btVector3FloatData m_velocity;
- btVector3FloatData m_accumulatedForce;
- btVector3FloatData m_normal;
- float m_inverseMass;
- float m_area;
- int m_attach;
- int m_pad;
-};
-
-struct SoftBodyLinkData
-{
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[2]; // Node pointers
- float m_restLength; // Rest length
- int m_bbending; // Bending link
-};
-
-struct SoftBodyFaceData
-{
- btVector3FloatData m_normal; // Normal
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[3]; // Node pointers
- float m_restArea; // Rest area
-};
-
-struct SoftBodyTetraData
-{
- btVector3FloatData m_c0[4]; // gradients
- SoftBodyMaterialData *m_material;
- int m_nodeIndices[4]; // Node pointers
- float m_restVolume; // Rest volume
- float m_c1; // (4*kVST)/(im0+im1+im2+im3)
- float m_c2; // m_c1/sum(|g0..3|^2)
- int m_pad;
-};
-
-struct SoftRigidAnchorData
-{
- btMatrix3x3FloatData m_c0; // Impulse matrix
- btVector3FloatData m_c1; // Relative anchor
- btVector3FloatData m_localFrame; // Anchor position in body space
- btRigidBodyData *m_rigidBody;
- int m_nodeIndex; // Node pointer
- float m_c2; // ima*dt
-};
-
-struct SoftBodyConfigData
-{
- int m_aeroModel; // Aerodynamic model (default: V_Point)
- float m_baumgarte; // Velocities correction factor (Baumgarte)
- float m_damping; // Damping coefficient [0,1]
- float m_drag; // Drag coefficient [0,+inf]
- float m_lift; // Lift coefficient [0,+inf]
- float m_pressure; // Pressure coefficient [-inf,+inf]
- float m_volume; // Volume conversation coefficient [0,+inf]
- float m_dynamicFriction; // Dynamic friction coefficient [0,1]
- float m_poseMatch; // Pose matching coefficient [0,1]
- float m_rigidContactHardness; // Rigid contacts hardness [0,1]
- float m_kineticContactHardness; // Kinetic contacts hardness [0,1]
- float m_softContactHardness; // Soft contacts hardness [0,1]
- float m_anchorHardness; // Anchors hardness [0,1]
- float m_softRigidClusterHardness; // Soft vs rigid hardness [0,1] (cluster only)
- float m_softKineticClusterHardness; // Soft vs kinetic hardness [0,1] (cluster only)
- float m_softSoftClusterHardness; // Soft vs soft hardness [0,1] (cluster only)
- float m_softRigidClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_softKineticClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_softSoftClusterImpulseSplit; // Soft vs rigid impulse split [0,1] (cluster only)
- float m_maxVolume; // Maximum volume ratio for pose
- float m_timeScale; // Time scale
- int m_velocityIterations; // Velocities solver iterations
- int m_positionIterations; // Positions solver iterations
- int m_driftIterations; // Drift solver iterations
- int m_clusterIterations; // Cluster solver iterations
- int m_collisionFlags; // Collisions flags
-};
-
-struct SoftBodyPoseData
-{
- btMatrix3x3FloatData m_rot; // Rotation
- btMatrix3x3FloatData m_scale; // Scale
- btMatrix3x3FloatData m_aqq; // Base scaling
- btVector3FloatData m_com; // COM
-
- btVector3FloatData *m_positions; // Reference positions
- float *m_weights; // Weights
- int m_numPositions;
- int m_numWeigts;
-
- int m_bvolume; // Is valid
- int m_bframe; // Is frame
- float m_restVolume; // Rest volume
- int m_pad;
-};
-
-struct SoftBodyClusterData
-{
- btTransformFloatData m_framexform;
- btMatrix3x3FloatData m_locii;
- btMatrix3x3FloatData m_invwi;
- btVector3FloatData m_com;
- btVector3FloatData m_vimpulses[2];
- btVector3FloatData m_dimpulses[2];
- btVector3FloatData m_lv;
- btVector3FloatData m_av;
-
- btVector3FloatData *m_framerefs;
- int *m_nodeIndices;
- float *m_masses;
-
- int m_numFrameRefs;
- int m_numNodes;
- int m_numMasses;
-
- float m_idmass;
- float m_imass;
- int m_nvimpulses;
- int m_ndimpulses;
- float m_ndamping;
- float m_ldamping;
- float m_adamping;
- float m_matching;
- float m_maxSelfCollisionImpulse;
- float m_selfCollisionImpulseFactor;
- int m_containsAnchor;
- int m_collide;
- int m_clusterIndex;
-};
-
-enum btSoftJointBodyType
-{
- BT_JOINT_SOFT_BODY_CLUSTER = 1,
- BT_JOINT_RIGID_BODY,
- BT_JOINT_COLLISION_OBJECT
-};
-
-struct btSoftBodyJointData
-{
- void *m_bodyA;
- void *m_bodyB;
- btVector3FloatData m_refs[2];
- float m_cfm;
- float m_erp;
- float m_split;
- int m_delete;
- btVector3FloatData m_relPosition[2]; //linear
- int m_bodyAtype;
- int m_bodyBtype;
- int m_jointType;
- int m_pad;
-};
-
-///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
-struct btSoftBodyFloatData
-{
- btCollisionObjectFloatData m_collisionObjectData;
-
- SoftBodyPoseData *m_pose;
- SoftBodyMaterialData **m_materials;
- SoftBodyNodeData *m_nodes;
- SoftBodyLinkData *m_links;
- SoftBodyFaceData *m_faces;
- SoftBodyTetraData *m_tetrahedra;
- SoftRigidAnchorData *m_anchors;
- SoftBodyClusterData *m_clusters;
- btSoftBodyJointData *m_joints;
-
- int m_numMaterials;
- int m_numNodes;
- int m_numLinks;
- int m_numFaces;
- int m_numTetrahedra;
- int m_numAnchors;
- int m_numClusters;
- int m_numJoints;
- SoftBodyConfigData m_config;
-};
-
-#endif //BT_SOFTBODY_FLOAT_DATA
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
deleted file mode 100644
index f63e48f9a5..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.cpp
+++ /dev/null
@@ -1,1663 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btSoftBodyHelpers.cpp by Nathanael Presson
-
-#include "btSoftBodyInternals.h"
-#include <stdio.h>
-#include <string>
-#include <iostream>
-#include <sstream>
-#include <string.h>
-#include <algorithm>
-#include "btSoftBodyHelpers.h"
-#include "LinearMath/btConvexHull.h"
-#include "LinearMath/btConvexHullComputer.h"
-#include <map>
-#include <vector>
-
-static void drawVertex(btIDebugDraw* idraw,
- const btVector3& x, btScalar s, const btVector3& c)
-{
- idraw->drawLine(x - btVector3(s, 0, 0), x + btVector3(s, 0, 0), c);
- idraw->drawLine(x - btVector3(0, s, 0), x + btVector3(0, s, 0), c);
- idraw->drawLine(x - btVector3(0, 0, s), x + btVector3(0, 0, s), c);
-}
-
-//
-static void drawBox(btIDebugDraw* idraw,
- const btVector3& mins,
- const btVector3& maxs,
- const btVector3& color)
-{
- const btVector3 c[] = {btVector3(mins.x(), mins.y(), mins.z()),
- btVector3(maxs.x(), mins.y(), mins.z()),
- btVector3(maxs.x(), maxs.y(), mins.z()),
- btVector3(mins.x(), maxs.y(), mins.z()),
- btVector3(mins.x(), mins.y(), maxs.z()),
- btVector3(maxs.x(), mins.y(), maxs.z()),
- btVector3(maxs.x(), maxs.y(), maxs.z()),
- btVector3(mins.x(), maxs.y(), maxs.z())};
- idraw->drawLine(c[0], c[1], color);
- idraw->drawLine(c[1], c[2], color);
- idraw->drawLine(c[2], c[3], color);
- idraw->drawLine(c[3], c[0], color);
- idraw->drawLine(c[4], c[5], color);
- idraw->drawLine(c[5], c[6], color);
- idraw->drawLine(c[6], c[7], color);
- idraw->drawLine(c[7], c[4], color);
- idraw->drawLine(c[0], c[4], color);
- idraw->drawLine(c[1], c[5], color);
- idraw->drawLine(c[2], c[6], color);
- idraw->drawLine(c[3], c[7], color);
-}
-
-//
-static void drawTree(btIDebugDraw* idraw,
- const btDbvtNode* node,
- int depth,
- const btVector3& ncolor,
- const btVector3& lcolor,
- int mindepth,
- int maxdepth)
-{
- if (node)
- {
- if (node->isinternal() && ((depth < maxdepth) || (maxdepth < 0)))
- {
- drawTree(idraw, node->childs[0], depth + 1, ncolor, lcolor, mindepth, maxdepth);
- drawTree(idraw, node->childs[1], depth + 1, ncolor, lcolor, mindepth, maxdepth);
- }
- if (depth >= mindepth)
- {
- const btScalar scl = (btScalar)(node->isinternal() ? 1 : 1);
- const btVector3 mi = node->volume.Center() - node->volume.Extents() * scl;
- const btVector3 mx = node->volume.Center() + node->volume.Extents() * scl;
- drawBox(idraw, mi, mx, node->isleaf() ? lcolor : ncolor);
- }
- }
-}
-
-//
-template <typename T>
-static inline T sum(const btAlignedObjectArray<T>& items)
-{
- T v;
- if (items.size())
- {
- v = items[0];
- for (int i = 1, ni = items.size(); i < ni; ++i)
- {
- v += items[i];
- }
- }
- return (v);
-}
-
-//
-template <typename T, typename Q>
-static inline void add(btAlignedObjectArray<T>& items, const Q& value)
-{
- for (int i = 0, ni = items.size(); i < ni; ++i)
- {
- items[i] += value;
- }
-}
-
-//
-template <typename T, typename Q>
-static inline void mul(btAlignedObjectArray<T>& items, const Q& value)
-{
- for (int i = 0, ni = items.size(); i < ni; ++i)
- {
- items[i] *= value;
- }
-}
-
-//
-template <typename T>
-static inline T average(const btAlignedObjectArray<T>& items)
-{
- const btScalar n = (btScalar)(items.size() > 0 ? items.size() : 1);
- return (sum(items) / n);
-}
-
-#if 0
-//
- inline static btScalar tetravolume(const btVector3& x0,
- const btVector3& x1,
- const btVector3& x2,
- const btVector3& x3)
-{
- const btVector3 a=x1-x0;
- const btVector3 b=x2-x0;
- const btVector3 c=x3-x0;
- return(btDot(a,btCross(b,c)));
-}
-#endif
-
-//
-#if 0
-static btVector3 stresscolor(btScalar stress)
-{
- static const btVector3 spectrum[]= { btVector3(1,0,1),
- btVector3(0,0,1),
- btVector3(0,1,1),
- btVector3(0,1,0),
- btVector3(1,1,0),
- btVector3(1,0,0),
- btVector3(1,0,0)};
- static const int ncolors=sizeof(spectrum)/sizeof(spectrum[0])-1;
- static const btScalar one=1;
- stress=btMax<btScalar>(0,btMin<btScalar>(1,stress))*ncolors;
- const int sel=(int)stress;
- const btScalar frc=stress-sel;
- return(spectrum[sel]+(spectrum[sel+1]-spectrum[sel])*frc);
-}
-#endif
-
-//
-void btSoftBodyHelpers::Draw(btSoftBody* psb,
- btIDebugDraw* idraw,
- int drawflags)
-{
- const btScalar scl = (btScalar)0.1;
- const btScalar nscl = scl * 5;
- const btVector3 lcolor = btVector3(0, 0, 0);
- const btVector3 ncolor = btVector3(1, 1, 1);
- const btVector3 ccolor = btVector3(1, 0, 0);
- int i, j, nj;
-
- /* Clusters */
- if (0 != (drawflags & fDrawFlags::Clusters))
- {
- srand(1806);
- for (i = 0; i < psb->m_clusters.size(); ++i)
- {
- if (psb->m_clusters[i]->m_collide)
- {
- btVector3 color(rand() / (btScalar)RAND_MAX,
- rand() / (btScalar)RAND_MAX,
- rand() / (btScalar)RAND_MAX);
- color = color.normalized() * 0.75;
- btAlignedObjectArray<btVector3> vertices;
- vertices.resize(psb->m_clusters[i]->m_nodes.size());
- for (j = 0, nj = vertices.size(); j < nj; ++j)
- {
- vertices[j] = psb->m_clusters[i]->m_nodes[j]->m_x;
- }
-#define USE_NEW_CONVEX_HULL_COMPUTER
-#ifdef USE_NEW_CONVEX_HULL_COMPUTER
- btConvexHullComputer computer;
- int stride = sizeof(btVector3);
- int count = vertices.size();
- btScalar shrink = 0.f;
- btScalar shrinkClamp = 0.f;
- computer.compute(&vertices[0].getX(), stride, count, shrink, shrinkClamp);
- for (int i = 0; i < computer.faces.size(); i++)
- {
- int face = computer.faces[i];
- //printf("face=%d\n",face);
- const btConvexHullComputer::Edge* firstEdge = &computer.edges[face];
- const btConvexHullComputer::Edge* edge = firstEdge->getNextEdgeOfFace();
-
- int v0 = firstEdge->getSourceVertex();
- int v1 = firstEdge->getTargetVertex();
- while (edge != firstEdge)
- {
- int v2 = edge->getTargetVertex();
- idraw->drawTriangle(computer.vertices[v0], computer.vertices[v1], computer.vertices[v2], color, 1);
- edge = edge->getNextEdgeOfFace();
- v0 = v1;
- v1 = v2;
- };
- }
-#else
-
- HullDesc hdsc(QF_TRIANGLES, vertices.size(), &vertices[0]);
- HullResult hres;
- HullLibrary hlib;
- hdsc.mMaxVertices = vertices.size();
- hlib.CreateConvexHull(hdsc, hres);
- const btVector3 center = average(hres.m_OutputVertices);
- add(hres.m_OutputVertices, -center);
- mul(hres.m_OutputVertices, (btScalar)1);
- add(hres.m_OutputVertices, center);
- for (j = 0; j < (int)hres.mNumFaces; ++j)
- {
- const int idx[] = {hres.m_Indices[j * 3 + 0], hres.m_Indices[j * 3 + 1], hres.m_Indices[j * 3 + 2]};
- idraw->drawTriangle(hres.m_OutputVertices[idx[0]],
- hres.m_OutputVertices[idx[1]],
- hres.m_OutputVertices[idx[2]],
- color, 1);
- }
- hlib.ReleaseResult(hres);
-#endif
- }
- /* Velocities */
-#if 0
- for(int j=0;j<psb->m_clusters[i].m_nodes.size();++j)
- {
- const btSoftBody::Cluster& c=psb->m_clusters[i];
- const btVector3 r=c.m_nodes[j]->m_x-c.m_com;
- const btVector3 v=c.m_lv+btCross(c.m_av,r);
- idraw->drawLine(c.m_nodes[j]->m_x,c.m_nodes[j]->m_x+v,btVector3(1,0,0));
- }
-#endif
- /* Frame */
- // btSoftBody::Cluster& c=*psb->m_clusters[i];
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(10,0,0),btVector3(1,0,0));
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,10,0),btVector3(0,1,0));
- // idraw->drawLine(c.m_com,c.m_framexform*btVector3(0,0,10),btVector3(0,0,1));
- }
- }
- else
- {
- /* Nodes */
- if (0 != (drawflags & fDrawFlags::Nodes))
- {
- for (i = 0; i < psb->m_nodes.size(); ++i)
- {
- const btSoftBody::Node& n = psb->m_nodes[i];
- if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- idraw->drawLine(n.m_x - btVector3(scl, 0, 0), n.m_x + btVector3(scl, 0, 0), btVector3(1, 0, 0));
- idraw->drawLine(n.m_x - btVector3(0, scl, 0), n.m_x + btVector3(0, scl, 0), btVector3(0, 1, 0));
- idraw->drawLine(n.m_x - btVector3(0, 0, scl), n.m_x + btVector3(0, 0, scl), btVector3(0, 0, 1));
- }
- }
- /* Links */
- if (0 != (drawflags & fDrawFlags::Links))
- {
- for (i = 0; i < psb->m_links.size(); ++i)
- {
- const btSoftBody::Link& l = psb->m_links[i];
- if (0 == (l.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- idraw->drawLine(l.m_n[0]->m_x, l.m_n[1]->m_x, lcolor);
- }
- }
- /* Normals */
- if (0 != (drawflags & fDrawFlags::Normals))
- {
- for (i = 0; i < psb->m_nodes.size(); ++i)
- {
- const btSoftBody::Node& n = psb->m_nodes[i];
- if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 d = n.m_n * nscl;
- idraw->drawLine(n.m_x, n.m_x + d, ncolor);
- idraw->drawLine(n.m_x, n.m_x - d, ncolor * 0.5);
- }
- }
- /* Contacts */
- if (0 != (drawflags & fDrawFlags::Contacts))
- {
- static const btVector3 axis[] = {btVector3(1, 0, 0),
- btVector3(0, 1, 0),
- btVector3(0, 0, 1)};
- for (i = 0; i < psb->m_rcontacts.size(); ++i)
- {
- const btSoftBody::RContact& c = psb->m_rcontacts[i];
- const btVector3 o = c.m_node->m_x - c.m_cti.m_normal *
- (btDot(c.m_node->m_x, c.m_cti.m_normal) + c.m_cti.m_offset);
- const btVector3 x = btCross(c.m_cti.m_normal, axis[c.m_cti.m_normal.minAxis()]).normalized();
- const btVector3 y = btCross(x, c.m_cti.m_normal).normalized();
- idraw->drawLine(o - x * nscl, o + x * nscl, ccolor);
- idraw->drawLine(o - y * nscl, o + y * nscl, ccolor);
- idraw->drawLine(o, o + c.m_cti.m_normal * nscl * 3, btVector3(1, 1, 0));
- }
- }
- /* Faces */
- if (0 != (drawflags & fDrawFlags::Faces))
- {
- const btScalar scl = (btScalar)0.8;
- const btScalar alp = (btScalar)1;
- const btVector3 col(0, (btScalar)0.7, 0);
- for (i = 0; i < psb->m_faces.size(); ++i)
- {
- const btSoftBody::Face& f = psb->m_faces[i];
- if (0 == (f.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 x[] = {f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x};
- const btVector3 c = (x[0] + x[1] + x[2]) / 3;
- idraw->drawTriangle((x[0] - c) * scl + c,
- (x[1] - c) * scl + c,
- (x[2] - c) * scl + c,
- col, alp);
- }
- }
- /* Tetras */
- if (0 != (drawflags & fDrawFlags::Tetras))
- {
- const btScalar scl = (btScalar)0.8;
- const btScalar alp = (btScalar)1;
- const btVector3 col((btScalar)0.3, (btScalar)0.3, (btScalar)0.7);
- for (int i = 0; i < psb->m_tetras.size(); ++i)
- {
- const btSoftBody::Tetra& t = psb->m_tetras[i];
- if (0 == (t.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- const btVector3 x[] = {t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x};
- const btVector3 c = (x[0] + x[1] + x[2] + x[3]) / 4;
- idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[2] - c) * scl + c, col, alp);
- idraw->drawTriangle((x[0] - c) * scl + c, (x[1] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
- idraw->drawTriangle((x[1] - c) * scl + c, (x[2] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
- idraw->drawTriangle((x[2] - c) * scl + c, (x[0] - c) * scl + c, (x[3] - c) * scl + c, col, alp);
- }
- }
- }
- /* Anchors */
- if (0 != (drawflags & fDrawFlags::Anchors))
- {
- for (i = 0; i < psb->m_anchors.size(); ++i)
- {
- const btSoftBody::Anchor& a = psb->m_anchors[i];
- const btVector3 q = a.m_body->getWorldTransform() * a.m_local;
- drawVertex(idraw, a.m_node->m_x, 0.25, btVector3(1, 0, 0));
- drawVertex(idraw, q, 0.25, btVector3(0, 1, 0));
- idraw->drawLine(a.m_node->m_x, q, btVector3(1, 1, 1));
- }
- for (i = 0; i < psb->m_nodes.size(); ++i)
- {
- const btSoftBody::Node& n = psb->m_nodes[i];
- if (0 == (n.m_material->m_flags & btSoftBody::fMaterial::DebugDraw)) continue;
- if (n.m_im <= 0)
- {
- drawVertex(idraw, n.m_x, 0.25, btVector3(1, 0, 0));
- }
- }
- }
-
- /* Notes */
- if (0 != (drawflags & fDrawFlags::Notes))
- {
- for (i = 0; i < psb->m_notes.size(); ++i)
- {
- const btSoftBody::Note& n = psb->m_notes[i];
- btVector3 p = n.m_offset;
- for (int j = 0; j < n.m_rank; ++j)
- {
- p += n.m_nodes[j]->m_x * n.m_coords[j];
- }
- idraw->draw3dText(p, n.m_text);
- }
- }
- /* Node tree */
- if (0 != (drawflags & fDrawFlags::NodeTree)) DrawNodeTree(psb, idraw);
- /* Face tree */
- if (0 != (drawflags & fDrawFlags::FaceTree)) DrawFaceTree(psb, idraw);
- /* Cluster tree */
- if (0 != (drawflags & fDrawFlags::ClusterTree)) DrawClusterTree(psb, idraw);
- /* Joints */
- if (0 != (drawflags & fDrawFlags::Joints))
- {
- for (i = 0; i < psb->m_joints.size(); ++i)
- {
- const btSoftBody::Joint* pj = psb->m_joints[i];
- switch (pj->Type())
- {
- case btSoftBody::Joint::eType::Linear:
- {
- const btSoftBody::LJoint* pjl = (const btSoftBody::LJoint*)pj;
- const btVector3 a0 = pj->m_bodies[0].xform() * pjl->m_refs[0];
- const btVector3 a1 = pj->m_bodies[1].xform() * pjl->m_refs[1];
- idraw->drawLine(pj->m_bodies[0].xform().getOrigin(), a0, btVector3(1, 1, 0));
- idraw->drawLine(pj->m_bodies[1].xform().getOrigin(), a1, btVector3(0, 1, 1));
- drawVertex(idraw, a0, 0.25, btVector3(1, 1, 0));
- drawVertex(idraw, a1, 0.25, btVector3(0, 1, 1));
- }
- break;
- case btSoftBody::Joint::eType::Angular:
- {
- //const btSoftBody::AJoint* pja=(const btSoftBody::AJoint*)pj;
- const btVector3 o0 = pj->m_bodies[0].xform().getOrigin();
- const btVector3 o1 = pj->m_bodies[1].xform().getOrigin();
- const btVector3 a0 = pj->m_bodies[0].xform().getBasis() * pj->m_refs[0];
- const btVector3 a1 = pj->m_bodies[1].xform().getBasis() * pj->m_refs[1];
- idraw->drawLine(o0, o0 + a0 * 10, btVector3(1, 1, 0));
- idraw->drawLine(o0, o0 + a1 * 10, btVector3(1, 1, 0));
- idraw->drawLine(o1, o1 + a0 * 10, btVector3(0, 1, 1));
- idraw->drawLine(o1, o1 + a1 * 10, btVector3(0, 1, 1));
- break;
- }
- default:
- {
- }
- }
- }
- }
-}
-
-//
-void btSoftBodyHelpers::DrawInfos(btSoftBody* psb,
- btIDebugDraw* idraw,
- bool masses,
- bool areas,
- bool /*stress*/)
-{
- for (int i = 0; i < psb->m_nodes.size(); ++i)
- {
- const btSoftBody::Node& n = psb->m_nodes[i];
- char text[2048] = {0};
- char buff[1024];
- if (masses)
- {
- sprintf(buff, " M(%.2f)", 1 / n.m_im);
- strcat(text, buff);
- }
- if (areas)
- {
- sprintf(buff, " A(%.2f)", n.m_area);
- strcat(text, buff);
- }
- if (text[0]) idraw->draw3dText(n.m_x, text);
- }
-}
-
-//
-void btSoftBodyHelpers::DrawNodeTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
-{
- drawTree(idraw, psb->m_ndbvt.m_root, 0, btVector3(1, 0, 1), btVector3(1, 1, 1), mindepth, maxdepth);
-}
-
-//
-void btSoftBodyHelpers::DrawFaceTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
-{
- drawTree(idraw, psb->m_fdbvt.m_root, 0, btVector3(0, 1, 0), btVector3(1, 0, 0), mindepth, maxdepth);
-}
-
-//
-void btSoftBodyHelpers::DrawClusterTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth,
- int maxdepth)
-{
- drawTree(idraw, psb->m_cdbvt.m_root, 0, btVector3(0, 1, 1), btVector3(1, 0, 0), mindepth, maxdepth);
-}
-
-//The btSoftBody object from the BulletSDK includes an array of Nodes and Links. These links appear
-// to be first set up to connect a node to between 5 and 6 of its neighbors [480 links],
-//and then to the rest of the nodes after the execution of the Floyd-Warshall graph algorithm
-//[another 930 links].
-//The way the links are stored by default, we have a number of cases where adjacent links share a node in common
-// - this leads to the creation of a data dependency through memory.
-//The PSolve_Links() function reads and writes nodes as it iterates over each link.
-//So, we now have the possibility of a data dependency between iteration X
-//that processes link L with iteration X+1 that processes link L+1
-//because L and L+1 have one node in common, and iteration X updates the positions of that node,
-//and iteration X+1 reads in the position of that shared node.
-//
-//Such a memory dependency limits the ability of a modern CPU to speculate beyond
-//a certain point because it has to respect a possible dependency
-//- this prevents the CPU from making full use of its out-of-order resources.
-//If we re-order the links such that we minimize the cases where a link L and L+1 share a common node,
-//we create a temporal gap between when the node position is written,
-//and when it is subsequently read. This in turn allows the CPU to continue execution without
-//risking a dependency violation. Such a reordering would result in significant speedups on
-//modern CPUs with lots of execution resources.
-//In our testing, we see it have a tremendous impact not only on the A7,
-//but also on all x86 cores that ship with modern Macs.
-//The attached source file includes a single function (ReoptimizeLinkOrder) which can be called on a
-//btSoftBody object in the solveConstraints() function before the actual solver is invoked,
-//or right after generateBendingConstraints() once we have all 1410 links.
-
-//===================================================================
-//
-//
-// This function takes in a list of interdependent Links and tries
-// to maximize the distance between calculation
-// of dependent links. This increases the amount of parallelism that can
-// be exploited by out-of-order instruction processors with large but
-// (inevitably) finite instruction windows.
-//
-//===================================================================
-
-// A small structure to track lists of dependent link calculations
-class LinkDeps_t
-{
-public:
- int value; // A link calculation that is dependent on this one
- // Positive values = "input A" while negative values = "input B"
- LinkDeps_t* next; // Next dependence in the list
-};
-typedef LinkDeps_t* LinkDepsPtr_t;
-
-// Dependency list constants
-#define REOP_NOT_DEPENDENT -1
-#define REOP_NODE_COMPLETE -2 // Must be less than REOP_NOT_DEPENDENT
-
-void btSoftBodyHelpers::ReoptimizeLinkOrder(btSoftBody* psb /* This can be replaced by a btSoftBody pointer */)
-{
- int i, nLinks = psb->m_links.size(), nNodes = psb->m_nodes.size();
- btSoftBody::Link* lr;
- int ar, br;
- btSoftBody::Node* node0 = &(psb->m_nodes[0]);
- btSoftBody::Node* node1 = &(psb->m_nodes[1]);
- LinkDepsPtr_t linkDep;
- int readyListHead, readyListTail, linkNum, linkDepFrees, depLink;
-
- // Allocate temporary buffers
- int* nodeWrittenAt = new int[nNodes + 1]; // What link calculation produced this node's current values?
- int* linkDepA = new int[nLinks]; // Link calculation input is dependent upon prior calculation #N
- int* linkDepB = new int[nLinks];
- int* readyList = new int[nLinks]; // List of ready-to-process link calculations (# of links, maximum)
- LinkDeps_t* linkDepFreeList = new LinkDeps_t[2 * nLinks]; // Dependent-on-me list elements (2x# of links, maximum)
- LinkDepsPtr_t* linkDepListStarts = new LinkDepsPtr_t[nLinks]; // Start nodes of dependent-on-me lists, one for each link
-
- // Copy the original, unsorted links to a side buffer
- btSoftBody::Link* linkBuffer = new btSoftBody::Link[nLinks];
- memcpy(linkBuffer, &(psb->m_links[0]), sizeof(btSoftBody::Link) * nLinks);
-
- // Clear out the node setup and ready list
- for (i = 0; i < nNodes + 1; i++)
- {
- nodeWrittenAt[i] = REOP_NOT_DEPENDENT;
- }
- for (i = 0; i < nLinks; i++)
- {
- linkDepListStarts[i] = NULL;
- }
- readyListHead = readyListTail = linkDepFrees = 0;
-
- // Initial link analysis to set up data structures
- for (i = 0; i < nLinks; i++)
- {
- // Note which prior link calculations we are dependent upon & build up dependence lists
- lr = &(psb->m_links[i]);
- ar = (lr->m_n[0] - node0) / (node1 - node0);
- br = (lr->m_n[1] - node0) / (node1 - node0);
- if (nodeWrittenAt[ar] > REOP_NOT_DEPENDENT)
- {
- linkDepA[i] = nodeWrittenAt[ar];
- linkDep = &linkDepFreeList[linkDepFrees++];
- linkDep->value = i;
- linkDep->next = linkDepListStarts[nodeWrittenAt[ar]];
- linkDepListStarts[nodeWrittenAt[ar]] = linkDep;
- }
- else
- {
- linkDepA[i] = REOP_NOT_DEPENDENT;
- }
- if (nodeWrittenAt[br] > REOP_NOT_DEPENDENT)
- {
- linkDepB[i] = nodeWrittenAt[br];
- linkDep = &linkDepFreeList[linkDepFrees++];
- linkDep->value = -(i + 1);
- linkDep->next = linkDepListStarts[nodeWrittenAt[br]];
- linkDepListStarts[nodeWrittenAt[br]] = linkDep;
- }
- else
- {
- linkDepB[i] = REOP_NOT_DEPENDENT;
- }
-
- // Add this link to the initial ready list, if it is not dependent on any other links
- if ((linkDepA[i] == REOP_NOT_DEPENDENT) && (linkDepB[i] == REOP_NOT_DEPENDENT))
- {
- readyList[readyListTail++] = i;
- linkDepA[i] = linkDepB[i] = REOP_NODE_COMPLETE; // Probably not needed now
- }
-
- // Update the nodes to mark which ones are calculated by this link
- nodeWrittenAt[ar] = nodeWrittenAt[br] = i;
- }
-
- // Process the ready list and create the sorted list of links
- // -- By treating the ready list as a queue, we maximize the distance between any
- // inter-dependent node calculations
- // -- All other (non-related) nodes in the ready list will automatically be inserted
- // in between each set of inter-dependent link calculations by this loop
- i = 0;
- while (readyListHead != readyListTail)
- {
- // Use ready list to select the next link to process
- linkNum = readyList[readyListHead++];
- // Copy the next-to-calculate link back into the original link array
- psb->m_links[i++] = linkBuffer[linkNum];
-
- // Free up any link inputs that are dependent on this one
- linkDep = linkDepListStarts[linkNum];
- while (linkDep)
- {
- depLink = linkDep->value;
- if (depLink >= 0)
- {
- linkDepA[depLink] = REOP_NOT_DEPENDENT;
- }
- else
- {
- depLink = -depLink - 1;
- linkDepB[depLink] = REOP_NOT_DEPENDENT;
- }
- // Add this dependent link calculation to the ready list if *both* inputs are clear
- if ((linkDepA[depLink] == REOP_NOT_DEPENDENT) && (linkDepB[depLink] == REOP_NOT_DEPENDENT))
- {
- readyList[readyListTail++] = depLink;
- linkDepA[depLink] = linkDepB[depLink] = REOP_NODE_COMPLETE; // Probably not needed now
- }
- linkDep = linkDep->next;
- }
- }
-
- // Delete the temporary buffers
- delete[] nodeWrittenAt;
- delete[] linkDepA;
- delete[] linkDepB;
- delete[] readyList;
- delete[] linkDepFreeList;
- delete[] linkDepListStarts;
- delete[] linkBuffer;
-}
-
-//
-void btSoftBodyHelpers::DrawFrame(btSoftBody* psb,
- btIDebugDraw* idraw)
-{
- if (psb->m_pose.m_bframe)
- {
- static const btScalar ascl = 10;
- static const btScalar nscl = (btScalar)0.1;
- const btVector3 com = psb->m_pose.m_com;
- const btMatrix3x3 trs = psb->m_pose.m_rot * psb->m_pose.m_scl;
- const btVector3 Xaxis = (trs * btVector3(1, 0, 0)).normalized();
- const btVector3 Yaxis = (trs * btVector3(0, 1, 0)).normalized();
- const btVector3 Zaxis = (trs * btVector3(0, 0, 1)).normalized();
- idraw->drawLine(com, com + Xaxis * ascl, btVector3(1, 0, 0));
- idraw->drawLine(com, com + Yaxis * ascl, btVector3(0, 1, 0));
- idraw->drawLine(com, com + Zaxis * ascl, btVector3(0, 0, 1));
- for (int i = 0; i < psb->m_pose.m_pos.size(); ++i)
- {
- const btVector3 x = com + trs * psb->m_pose.m_pos[i];
- drawVertex(idraw, x, nscl, btVector3(1, 0, 1));
- }
- }
-}
-
-//
-btSoftBody* btSoftBodyHelpers::CreateRope(btSoftBodyWorldInfo& worldInfo, const btVector3& from,
- const btVector3& to,
- int res,
- int fixeds)
-{
- /* Create nodes */
- const int r = res + 2;
- btVector3* x = new btVector3[r];
- btScalar* m = new btScalar[r];
- int i;
-
- for (i = 0; i < r; ++i)
- {
- const btScalar t = i / (btScalar)(r - 1);
- x[i] = lerp(from, to, t);
- m[i] = 1;
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, r, x, m);
- if (fixeds & 1) psb->setMass(0, 0);
- if (fixeds & 2) psb->setMass(r - 1, 0);
- delete[] x;
- delete[] m;
- /* Create links */
- for (i = 1; i < r; ++i)
- {
- psb->appendLink(i - 1, i);
- }
- /* Finished */
- return (psb);
-}
-
-//
-btSoftBody* btSoftBodyHelpers::CreatePatch(btSoftBodyWorldInfo& worldInfo, const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- btScalar perturbation)
-{
-#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
- /* Create nodes */
- if ((resx < 2) || (resy < 2)) return (0);
- const int rx = resx;
- const int ry = resy;
- const int tot = rx * ry;
- btVector3* x = new btVector3[tot];
- btScalar* m = new btScalar[tot];
- int iy;
-
- for (iy = 0; iy < ry; ++iy)
- {
- const btScalar ty = iy / (btScalar)(ry - 1);
- const btVector3 py0 = lerp(corner00, corner01, ty);
- const btVector3 py1 = lerp(corner10, corner11, ty);
- for (int ix = 0; ix < rx; ++ix)
- {
- const btScalar tx = ix / (btScalar)(rx - 1);
- btScalar pert = perturbation * btScalar(rand()) / RAND_MAX;
- btVector3 temp1 = py1;
- temp1.setY(py1.getY() + pert);
- btVector3 temp = py0;
- pert = perturbation * btScalar(rand()) / RAND_MAX;
- temp.setY(py0.getY() + pert);
- x[IDX(ix, iy)] = lerp(temp, temp1, tx);
- m[IDX(ix, iy)] = 1;
- }
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
- if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
- if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
- if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
- if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
- delete[] x;
- delete[] m;
- /* Create links and faces */
- for (iy = 0; iy < ry; ++iy)
- {
- for (int ix = 0; ix < rx; ++ix)
- {
- const int idx = IDX(ix, iy);
- const bool mdx = (ix + 1) < rx;
- const bool mdy = (iy + 1) < ry;
- if (mdx) psb->appendLink(idx, IDX(ix + 1, iy));
- if (mdy) psb->appendLink(idx, IDX(ix, iy + 1));
- if (mdx && mdy)
- {
- if ((ix + iy) & 1)
- {
- psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
- psb->appendFace(IDX(ix, iy), IDX(ix + 1, iy + 1), IDX(ix, iy + 1));
- if (gendiags)
- {
- psb->appendLink(IDX(ix, iy), IDX(ix + 1, iy + 1));
- }
- }
- else
- {
- psb->appendFace(IDX(ix, iy + 1), IDX(ix, iy), IDX(ix + 1, iy));
- psb->appendFace(IDX(ix, iy + 1), IDX(ix + 1, iy), IDX(ix + 1, iy + 1));
- if (gendiags)
- {
- psb->appendLink(IDX(ix + 1, iy), IDX(ix, iy + 1));
- }
- }
- }
- }
- }
- /* Finished */
-#undef IDX
- return (psb);
-}
-
-//
-btSoftBody* btSoftBodyHelpers::CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- float* tex_coords)
-{
- /*
- *
- * corners:
- *
- * [0][0] corner00 ------- corner01 [resx][0]
- * | |
- * | |
- * [0][resy] corner10 -------- corner11 [resx][resy]
- *
- *
- *
- *
- *
- *
- * "fixedgs" map:
- *
- * corner00 --> +1
- * corner01 --> +2
- * corner10 --> +4
- * corner11 --> +8
- * upper middle --> +16
- * left middle --> +32
- * right middle --> +64
- * lower middle --> +128
- * center --> +256
- *
- *
- * tex_coords size (resx-1)*(resy-1)*12
- *
- *
- *
- * SINGLE QUAD INTERNALS
- *
- * 1) btSoftBody's nodes and links,
- * diagonal link is optional ("gendiags")
- *
- *
- * node00 ------ node01
- * | .
- * | .
- * | .
- * | .
- * | .
- * node10 node11
- *
- *
- *
- * 2) Faces:
- * two triangles,
- * UV Coordinates (hier example for single quad)
- *
- * (0,1) (0,1) (1,1)
- * 1 |\ 3 \-----| 2
- * | \ \ |
- * | \ \ |
- * | \ \ |
- * | \ \ |
- * 2 |-----\ 3 \| 1
- * (0,0) (1,0) (1,0)
- *
- *
- *
- *
- *
- *
- */
-
-#define IDX(_x_, _y_) ((_y_)*rx + (_x_))
- /* Create nodes */
- if ((resx < 2) || (resy < 2)) return (0);
- const int rx = resx;
- const int ry = resy;
- const int tot = rx * ry;
- btVector3* x = new btVector3[tot];
- btScalar* m = new btScalar[tot];
-
- int iy;
-
- for (iy = 0; iy < ry; ++iy)
- {
- const btScalar ty = iy / (btScalar)(ry - 1);
- const btVector3 py0 = lerp(corner00, corner01, ty);
- const btVector3 py1 = lerp(corner10, corner11, ty);
- for (int ix = 0; ix < rx; ++ix)
- {
- const btScalar tx = ix / (btScalar)(rx - 1);
- x[IDX(ix, iy)] = lerp(py0, py1, tx);
- m[IDX(ix, iy)] = 1;
- }
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, tot, x, m);
- if (fixeds & 1) psb->setMass(IDX(0, 0), 0);
- if (fixeds & 2) psb->setMass(IDX(rx - 1, 0), 0);
- if (fixeds & 4) psb->setMass(IDX(0, ry - 1), 0);
- if (fixeds & 8) psb->setMass(IDX(rx - 1, ry - 1), 0);
- if (fixeds & 16) psb->setMass(IDX((rx - 1) / 2, 0), 0);
- if (fixeds & 32) psb->setMass(IDX(0, (ry - 1) / 2), 0);
- if (fixeds & 64) psb->setMass(IDX(rx - 1, (ry - 1) / 2), 0);
- if (fixeds & 128) psb->setMass(IDX((rx - 1) / 2, ry - 1), 0);
- if (fixeds & 256) psb->setMass(IDX((rx - 1) / 2, (ry - 1) / 2), 0);
- delete[] x;
- delete[] m;
-
- int z = 0;
- /* Create links and faces */
- for (iy = 0; iy < ry; ++iy)
- {
- for (int ix = 0; ix < rx; ++ix)
- {
- const bool mdx = (ix + 1) < rx;
- const bool mdy = (iy + 1) < ry;
-
- int node00 = IDX(ix, iy);
- int node01 = IDX(ix + 1, iy);
- int node10 = IDX(ix, iy + 1);
- int node11 = IDX(ix + 1, iy + 1);
-
- if (mdx) psb->appendLink(node00, node01);
- if (mdy) psb->appendLink(node00, node10);
- if (mdx && mdy)
- {
- psb->appendFace(node00, node10, node11);
- if (tex_coords)
- {
- tex_coords[z + 0] = CalculateUV(resx, resy, ix, iy, 0);
- tex_coords[z + 1] = CalculateUV(resx, resy, ix, iy, 1);
- tex_coords[z + 2] = CalculateUV(resx, resy, ix, iy, 0);
- tex_coords[z + 3] = CalculateUV(resx, resy, ix, iy, 2);
- tex_coords[z + 4] = CalculateUV(resx, resy, ix, iy, 3);
- tex_coords[z + 5] = CalculateUV(resx, resy, ix, iy, 2);
- }
- psb->appendFace(node11, node01, node00);
- if (tex_coords)
- {
- tex_coords[z + 6] = CalculateUV(resx, resy, ix, iy, 3);
- tex_coords[z + 7] = CalculateUV(resx, resy, ix, iy, 2);
- tex_coords[z + 8] = CalculateUV(resx, resy, ix, iy, 3);
- tex_coords[z + 9] = CalculateUV(resx, resy, ix, iy, 1);
- tex_coords[z + 10] = CalculateUV(resx, resy, ix, iy, 0);
- tex_coords[z + 11] = CalculateUV(resx, resy, ix, iy, 1);
- }
- if (gendiags) psb->appendLink(node00, node11);
- z += 12;
- }
- }
- }
- /* Finished */
-#undef IDX
- return (psb);
-}
-
-float btSoftBodyHelpers::CalculateUV(int resx, int resy, int ix, int iy, int id)
-{
- /*
- *
- *
- * node00 --- node01
- * | |
- * node10 --- node11
- *
- *
- * ID map:
- *
- * node00 s --> 0
- * node00 t --> 1
- *
- * node01 s --> 3
- * node01 t --> 1
- *
- * node10 s --> 0
- * node10 t --> 2
- *
- * node11 s --> 3
- * node11 t --> 2
- *
- *
- */
-
- float tc = 0.0f;
- if (id == 0)
- {
- tc = (1.0f / ((resx - 1)) * ix);
- }
- else if (id == 1)
- {
- tc = (1.0f / ((resy - 1)) * (resy - 1 - iy));
- }
- else if (id == 2)
- {
- tc = (1.0f / ((resy - 1)) * (resy - 1 - iy - 1));
- }
- else if (id == 3)
- {
- tc = (1.0f / ((resx - 1)) * (ix + 1));
- }
- return tc;
-}
-//
-btSoftBody* btSoftBodyHelpers::CreateEllipsoid(btSoftBodyWorldInfo& worldInfo, const btVector3& center,
- const btVector3& radius,
- int res)
-{
- struct Hammersley
- {
- static void Generate(btVector3* x, int n)
- {
- for (int i = 0; i < n; i++)
- {
- btScalar p = 0.5, t = 0;
- for (int j = i; j; p *= 0.5, j >>= 1)
- if (j & 1) t += p;
- btScalar w = 2 * t - 1;
- btScalar a = (SIMD_PI + 2 * i * SIMD_PI) / n;
- btScalar s = btSqrt(1 - w * w);
- *x++ = btVector3(s * btCos(a), s * btSin(a), w);
- }
- }
- };
- btAlignedObjectArray<btVector3> vtx;
- vtx.resize(3 + res);
- Hammersley::Generate(&vtx[0], vtx.size());
- for (int i = 0; i < vtx.size(); ++i)
- {
- vtx[i] = vtx[i] * radius + center;
- }
- return (CreateFromConvexHull(worldInfo, &vtx[0], vtx.size()));
-}
-
-//
-btSoftBody* btSoftBodyHelpers::CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo, const btScalar* vertices,
- const int* triangles,
- int ntriangles, bool randomizeConstraints)
-{
- int maxidx = 0;
- int i, j, ni;
-
- for (i = 0, ni = ntriangles * 3; i < ni; ++i)
- {
- maxidx = btMax(triangles[i], maxidx);
- }
- ++maxidx;
- btAlignedObjectArray<bool> chks;
- btAlignedObjectArray<btVector3> vtx;
- chks.resize(maxidx * maxidx, false);
- vtx.resize(maxidx);
- for (i = 0, j = 0, ni = maxidx * 3; i < ni; ++j, i += 3)
- {
- vtx[j] = btVector3(vertices[i], vertices[i + 1], vertices[i + 2]);
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, vtx.size(), &vtx[0], 0);
- for (i = 0, ni = ntriangles * 3; i < ni; i += 3)
- {
- const int idx[] = {triangles[i], triangles[i + 1], triangles[i + 2]};
-#define IDX(_x_, _y_) ((_y_)*maxidx + (_x_))
- for (int j = 2, k = 0; k < 3; j = k++)
- {
- if (!chks[IDX(idx[j], idx[k])])
- {
- chks[IDX(idx[j], idx[k])] = true;
- chks[IDX(idx[k], idx[j])] = true;
- psb->appendLink(idx[j], idx[k]);
- }
- }
-#undef IDX
- psb->appendFace(idx[0], idx[1], idx[2]);
- }
-
- if (randomizeConstraints)
- {
- psb->randomizeConstraints();
- }
-
- return (psb);
-}
-
-//
-btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo, const btVector3* vertices,
- int nvertices, bool randomizeConstraints)
-{
- HullDesc hdsc(QF_TRIANGLES, nvertices, vertices);
- HullResult hres;
- HullLibrary hlib; /*??*/
- hdsc.mMaxVertices = nvertices;
- hlib.CreateConvexHull(hdsc, hres);
- btSoftBody* psb = new btSoftBody(&worldInfo, (int)hres.mNumOutputVertices,
- &hres.m_OutputVertices[0], 0);
- for (int i = 0; i < (int)hres.mNumFaces; ++i)
- {
- const int idx[] = {static_cast<int>(hres.m_Indices[i * 3 + 0]),
- static_cast<int>(hres.m_Indices[i * 3 + 1]),
- static_cast<int>(hres.m_Indices[i * 3 + 2])};
- if (idx[0] < idx[1]) psb->appendLink(idx[0], idx[1]);
- if (idx[1] < idx[2]) psb->appendLink(idx[1], idx[2]);
- if (idx[2] < idx[0]) psb->appendLink(idx[2], idx[0]);
- psb->appendFace(idx[0], idx[1], idx[2]);
- }
- hlib.ReleaseResult(hres);
- if (randomizeConstraints)
- {
- psb->randomizeConstraints();
- }
- return (psb);
-}
-
-static int nextLine(const char* buffer)
-{
- int numBytesRead = 0;
-
- while (*buffer != '\n')
- {
- buffer++;
- numBytesRead++;
- }
-
- if (buffer[0] == 0x0a)
- {
- buffer++;
- numBytesRead++;
- }
- return numBytesRead;
-}
-
-/* Create from TetGen .ele, .face, .node data */
-btSoftBody* btSoftBodyHelpers::CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
- const char* ele,
- const char* face,
- const char* node,
- bool bfacelinks,
- bool btetralinks,
- bool bfacesfromtetras)
-{
- btAlignedObjectArray<btVector3> pos;
- int nnode = 0;
- int ndims = 0;
- int nattrb = 0;
- int hasbounds = 0;
- int result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
- result = sscanf(node, "%d %d %d %d", &nnode, &ndims, &nattrb, &hasbounds);
- node += nextLine(node);
-
- pos.resize(nnode);
- for (int i = 0; i < pos.size(); ++i)
- {
- int index = 0;
- //int bound=0;
- float x, y, z;
- sscanf(node, "%d %f %f %f", &index, &x, &y, &z);
-
- // sn>>index;
- // sn>>x;sn>>y;sn>>z;
- node += nextLine(node);
-
- //for(int j=0;j<nattrb;++j)
- // sn>>a;
-
- //if(hasbounds)
- // sn>>bound;
-
- pos[index].setX(btScalar(x));
- pos[index].setY(btScalar(y));
- pos[index].setZ(btScalar(z));
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, nnode, &pos[0], 0);
-#if 0
-if(face&&face[0])
- {
- int nface=0;
- sf>>nface;sf>>hasbounds;
- for(int i=0;i<nface;++i)
- {
- int index=0;
- int bound=0;
- int ni[3];
- sf>>index;
- sf>>ni[0];sf>>ni[1];sf>>ni[2];
- sf>>bound;
- psb->appendFace(ni[0],ni[1],ni[2]);
- if(btetralinks)
- {
- psb->appendLink(ni[0],ni[1],0,true);
- psb->appendLink(ni[1],ni[2],0,true);
- psb->appendLink(ni[2],ni[0],0,true);
- }
- }
- }
-#endif
-
- if (ele && ele[0])
- {
- int ntetra = 0;
- int ncorner = 0;
- int neattrb = 0;
- sscanf(ele, "%d %d %d", &ntetra, &ncorner, &neattrb);
- ele += nextLine(ele);
-
- //se>>ntetra;se>>ncorner;se>>neattrb;
- for (int i = 0; i < ntetra; ++i)
- {
- int index = 0;
- int ni[4];
-
- //se>>index;
- //se>>ni[0];se>>ni[1];se>>ni[2];se>>ni[3];
- sscanf(ele, "%d %d %d %d %d", &index, &ni[0], &ni[1], &ni[2], &ni[3]);
- ele += nextLine(ele);
- //for(int j=0;j<neattrb;++j)
- // se>>a;
- psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
- if (btetralinks)
- {
- psb->appendLink(ni[0], ni[1], 0, true);
- psb->appendLink(ni[1], ni[2], 0, true);
- psb->appendLink(ni[2], ni[0], 0, true);
- psb->appendLink(ni[0], ni[3], 0, true);
- psb->appendLink(ni[1], ni[3], 0, true);
- psb->appendLink(ni[2], ni[3], 0, true);
- }
- }
- }
- psb->initializeDmInverse();
- psb->m_tetraScratches.resize(psb->m_tetras.size());
- psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
- printf("Nodes: %u\r\n", psb->m_nodes.size());
- printf("Links: %u\r\n", psb->m_links.size());
- printf("Faces: %u\r\n", psb->m_faces.size());
- printf("Tetras: %u\r\n", psb->m_tetras.size());
- return (psb);
-}
-
-btSoftBody* btSoftBodyHelpers::CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file)
-{
- std::ifstream fs;
- fs.open(vtk_file);
- btAssert(fs);
-
- typedef btAlignedObjectArray<int> Index;
- std::string line;
- btAlignedObjectArray<btVector3> X;
- btVector3 position;
- btAlignedObjectArray<Index> indices;
- bool reading_points = false;
- bool reading_tets = false;
- size_t n_points = 0;
- size_t n_tets = 0;
- size_t x_count = 0;
- size_t indices_count = 0;
- while (std::getline(fs, line))
- {
- std::stringstream ss(line);
- if (line.size() == (size_t)(0))
- {
- }
- else if (line.substr(0, 6) == "POINTS")
- {
- reading_points = true;
- reading_tets = false;
- ss.ignore(128, ' '); // ignore "POINTS"
- ss >> n_points;
- X.resize(n_points);
- }
- else if (line.substr(0, 5) == "CELLS")
- {
- reading_points = false;
- reading_tets = true;
- ss.ignore(128, ' '); // ignore "CELLS"
- ss >> n_tets;
- indices.resize(n_tets);
- }
- else if (line.substr(0, 10) == "CELL_TYPES")
- {
- reading_points = false;
- reading_tets = false;
- }
- else if (reading_points)
- {
- btScalar p;
- ss >> p;
- position.setX(p);
- ss >> p;
- position.setY(p);
- ss >> p;
- position.setZ(p);
- //printf("v %f %f %f\n", position.getX(), position.getY(), position.getZ());
- X[x_count++] = position;
- }
- else if (reading_tets)
- {
- int d;
- ss >> d;
- if (d != 4)
- {
- printf("Load deformable failed: Only Tetrahedra are supported in VTK file.\n");
- fs.close();
- return 0;
- }
- ss.ignore(128, ' '); // ignore "4"
- Index tet;
- tet.resize(4);
- for (size_t i = 0; i < 4; i++)
- {
- ss >> tet[i];
- //printf("%d ", tet[i]);
- }
- //printf("\n");
- indices[indices_count++] = tet;
- }
- }
- btSoftBody* psb = new btSoftBody(&worldInfo, n_points, &X[0], 0);
-
- for (int i = 0; i < n_tets; ++i)
- {
- const Index& ni = indices[i];
- psb->appendTetra(ni[0], ni[1], ni[2], ni[3]);
- {
- psb->appendLink(ni[0], ni[1], 0, true);
- psb->appendLink(ni[1], ni[2], 0, true);
- psb->appendLink(ni[2], ni[0], 0, true);
- psb->appendLink(ni[0], ni[3], 0, true);
- psb->appendLink(ni[1], ni[3], 0, true);
- psb->appendLink(ni[2], ni[3], 0, true);
- }
- }
-
- generateBoundaryFaces(psb);
- psb->initializeDmInverse();
- psb->m_tetraScratches.resize(psb->m_tetras.size());
- psb->m_tetraScratchesTn.resize(psb->m_tetras.size());
- printf("Nodes: %u\r\n", psb->m_nodes.size());
- printf("Links: %u\r\n", psb->m_links.size());
- printf("Faces: %u\r\n", psb->m_faces.size());
- printf("Tetras: %u\r\n", psb->m_tetras.size());
-
- fs.close();
- return psb;
-}
-
-void btSoftBodyHelpers::generateBoundaryFaces(btSoftBody* psb)
-{
- int counter = 0;
- for (int i = 0; i < psb->m_nodes.size(); ++i)
- {
- psb->m_nodes[i].index = counter++;
- }
- typedef btAlignedObjectArray<int> Index;
- btAlignedObjectArray<Index> indices;
- indices.resize(psb->m_tetras.size());
- for (int i = 0; i < indices.size(); ++i)
- {
- Index index;
- index.push_back(psb->m_tetras[i].m_n[0]->index);
- index.push_back(psb->m_tetras[i].m_n[1]->index);
- index.push_back(psb->m_tetras[i].m_n[2]->index);
- index.push_back(psb->m_tetras[i].m_n[3]->index);
- indices[i] = index;
- }
-
- std::map<std::vector<int>, std::vector<int> > dict;
- for (int i = 0; i < indices.size(); ++i)
- {
- for (int j = 0; j < 4; ++j)
- {
- std::vector<int> f;
- if (j == 0)
- {
- f.push_back(indices[i][1]);
- f.push_back(indices[i][0]);
- f.push_back(indices[i][2]);
- }
- if (j == 1)
- {
- f.push_back(indices[i][3]);
- f.push_back(indices[i][0]);
- f.push_back(indices[i][1]);
- }
- if (j == 2)
- {
- f.push_back(indices[i][3]);
- f.push_back(indices[i][1]);
- f.push_back(indices[i][2]);
- }
- if (j == 3)
- {
- f.push_back(indices[i][2]);
- f.push_back(indices[i][0]);
- f.push_back(indices[i][3]);
- }
- std::vector<int> f_sorted = f;
- std::sort(f_sorted.begin(), f_sorted.end());
- if (dict.find(f_sorted) != dict.end())
- {
- dict.erase(f_sorted);
- }
- else
- {
- dict.insert(std::make_pair(f_sorted, f));
- }
- }
- }
-
- for (std::map<std::vector<int>, std::vector<int> >::iterator it = dict.begin(); it != dict.end(); ++it)
- {
- std::vector<int> f = it->second;
- psb->appendFace(f[0], f[1], f[2]);
- //printf("f %d %d %d\n", f[0] + 1, f[1] + 1, f[2] + 1);
- }
-}
-
-//Write the surface mesh to an obj file.
-void btSoftBodyHelpers::writeObj(const char* filename, const btSoftBody* psb)
-{
- std::ofstream fs;
- fs.open(filename);
- btAssert(fs);
-
- if (psb->m_tetras.size() > 0)
- {
- // For tetrahedron mesh, we need to re-index the surface mesh for it to be in obj file/
- std::map<int, int> dict;
- for (int i = 0; i < psb->m_faces.size(); i++)
- {
- for (int d = 0; d < 3; d++)
- {
- int index = psb->m_faces[i].m_n[d]->index;
- if (dict.find(index) == dict.end())
- {
- int dict_size = dict.size();
- dict[index] = dict_size;
- fs << "v";
- for (int k = 0; k < 3; k++)
- {
- fs << " " << psb->m_nodes[index].m_x[k];
- }
- fs << "\n";
- }
- }
- }
- // Write surface mesh.
- for (int i = 0; i < psb->m_faces.size(); ++i)
- {
- fs << "f";
- for (int n = 0; n < 3; n++)
- {
- fs << " " << dict[psb->m_faces[i].m_n[n]->index] + 1;
- }
- fs << "\n";
- }
- }
- else
- {
- // For trimesh, directly write out all the nodes and faces.xs
- for (int i = 0; i < psb->m_nodes.size(); ++i)
- {
- fs << "v";
- for (int d = 0; d < 3; d++)
- {
- fs << " " << psb->m_nodes[i].m_x[d];
- }
- fs << "\n";
- }
-
- for (int i = 0; i < psb->m_faces.size(); ++i)
- {
- fs << "f";
- for (int n = 0; n < 3; n++)
- {
- fs << " " << psb->m_faces[i].m_n[n]->index + 1;
- }
- fs << "\n";
- }
- }
- fs.close();
-}
-
-void btSoftBodyHelpers::duplicateFaces(const char* filename, const btSoftBody* psb)
-{
- std::ifstream fs_read;
- fs_read.open(filename);
- std::string line;
- btVector3 pos;
- btAlignedObjectArray<btAlignedObjectArray<int> > additional_faces;
- while (std::getline(fs_read, line))
- {
- std::stringstream ss(line);
- if (line[0] == 'v')
- {
- }
- else if (line[0] == 'f')
- {
- ss.ignore();
- int id0, id1, id2;
- ss >> id0;
- ss >> id1;
- ss >> id2;
- btAlignedObjectArray<int> new_face;
- new_face.push_back(id1);
- new_face.push_back(id0);
- new_face.push_back(id2);
- additional_faces.push_back(new_face);
- }
- }
- fs_read.close();
-
- std::ofstream fs_write;
- fs_write.open(filename, std::ios_base::app);
- for (int i = 0; i < additional_faces.size(); ++i)
- {
- fs_write << "f";
- for (int n = 0; n < 3; n++)
- {
- fs_write << " " << additional_faces[i][n];
- }
- fs_write << "\n";
- }
- fs_write.close();
-}
-
-// Given a simplex with vertices a,b,c,d, find the barycentric weights of p in this simplex
-void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary)
-{
- btVector3 vap = p - a;
- btVector3 vbp = p - b;
-
- btVector3 vab = b - a;
- btVector3 vac = c - a;
- btVector3 vad = d - a;
-
- btVector3 vbc = c - b;
- btVector3 vbd = d - b;
- btScalar va6 = (vbp.cross(vbd)).dot(vbc);
- btScalar vb6 = (vap.cross(vac)).dot(vad);
- btScalar vc6 = (vap.cross(vad)).dot(vab);
- btScalar vd6 = (vap.cross(vab)).dot(vac);
- btScalar v6 = btScalar(1) / (vab.cross(vac).dot(vad));
- bary = btVector4(va6 * v6, vb6 * v6, vc6 * v6, vd6 * v6);
-}
-
-// Given a simplex with vertices a,b,c, find the barycentric weights of p in this simplex. bary[3] = 0.
-void btSoftBodyHelpers::getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary)
-{
- btVector3 v0 = b - a, v1 = c - a, v2 = p - a;
- btScalar d00 = btDot(v0, v0);
- btScalar d01 = btDot(v0, v1);
- btScalar d11 = btDot(v1, v1);
- btScalar d20 = btDot(v2, v0);
- btScalar d21 = btDot(v2, v1);
- btScalar invDenom = 1.0 / (d00 * d11 - d01 * d01);
- bary[1] = (d11 * d20 - d01 * d21) * invDenom;
- bary[2] = (d00 * d21 - d01 * d20) * invDenom;
- bary[0] = 1.0 - bary[1] - bary[2];
- bary[3] = 0;
-}
-
-// Iterate through all render nodes to find the simulation tetrahedron that contains the render node and record the barycentric weights
-// If the node is not inside any tetrahedron, assign it to the tetrahedron in which the node has the least negative barycentric weight
-void btSoftBodyHelpers::interpolateBarycentricWeights(btSoftBody* psb)
-{
- psb->m_z.resize(0);
- psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
- psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
- for (int i = 0; i < psb->m_renderNodes.size(); ++i)
- {
- const btVector3& p = psb->m_renderNodes[i].m_x;
- btVector4 bary;
- btVector4 optimal_bary;
- btScalar min_bary_weight = -1e3;
- btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
- for (int j = 0; j < psb->m_tetras.size(); ++j)
- {
- const btSoftBody::Tetra& t = psb->m_tetras[j];
- getBarycentricWeights(t.m_n[0]->m_x, t.m_n[1]->m_x, t.m_n[2]->m_x, t.m_n[3]->m_x, p, bary);
- btScalar new_min_bary_weight = bary[0];
- for (int k = 1; k < 4; ++k)
- {
- new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
- }
- if (new_min_bary_weight > min_bary_weight)
- {
- btAlignedObjectArray<const btSoftBody::Node*> parents;
- parents.push_back(t.m_n[0]);
- parents.push_back(t.m_n[1]);
- parents.push_back(t.m_n[2]);
- parents.push_back(t.m_n[3]);
- optimal_parents = parents;
- optimal_bary = bary;
- min_bary_weight = new_min_bary_weight;
- // stop searching if p is inside the tetrahedron at hand
- if (bary[0] >= 0. && bary[1] >= 0. && bary[2] >= 0. && bary[3] >= 0.)
- {
- break;
- }
- }
- }
- psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
- psb->m_renderNodesParents[i] = optimal_parents;
- }
-}
-
-// Iterate through all render nodes to find the simulation triangle that's closest to the node in the barycentric sense.
-void btSoftBodyHelpers::extrapolateBarycentricWeights(btSoftBody* psb)
-{
- psb->m_renderNodesInterpolationWeights.resize(psb->m_renderNodes.size());
- psb->m_renderNodesParents.resize(psb->m_renderNodes.size());
- psb->m_z.resize(psb->m_renderNodes.size());
- for (int i = 0; i < psb->m_renderNodes.size(); ++i)
- {
- const btVector3& p = psb->m_renderNodes[i].m_x;
- btVector4 bary;
- btVector4 optimal_bary;
- btScalar min_bary_weight = -SIMD_INFINITY;
- btAlignedObjectArray<const btSoftBody::Node*> optimal_parents;
- btScalar dist = 0, optimal_dist = 0;
- for (int j = 0; j < psb->m_faces.size(); ++j)
- {
- const btSoftBody::Face& f = psb->m_faces[j];
- btVector3 n = btCross(f.m_n[1]->m_x - f.m_n[0]->m_x, f.m_n[2]->m_x - f.m_n[0]->m_x);
- btVector3 unit_n = n.normalized();
- dist = (p - f.m_n[0]->m_x).dot(unit_n);
- btVector3 proj_p = p - dist * unit_n;
- getBarycentricWeights(f.m_n[0]->m_x, f.m_n[1]->m_x, f.m_n[2]->m_x, proj_p, bary);
- btScalar new_min_bary_weight = bary[0];
- for (int k = 1; k < 3; ++k)
- {
- new_min_bary_weight = btMin(new_min_bary_weight, bary[k]);
- }
-
- // p is out of the current best triangle, we found a traingle that's better
- bool better_than_closest_outisde = (new_min_bary_weight > min_bary_weight && min_bary_weight < 0.);
- // p is inside of the current best triangle, we found a triangle that's better
- bool better_than_best_inside = (new_min_bary_weight >= 0 && min_bary_weight >= 0 && btFabs(dist) < btFabs(optimal_dist));
-
- if (better_than_closest_outisde || better_than_best_inside)
- {
- btAlignedObjectArray<const btSoftBody::Node*> parents;
- parents.push_back(f.m_n[0]);
- parents.push_back(f.m_n[1]);
- parents.push_back(f.m_n[2]);
- optimal_parents = parents;
- optimal_bary = bary;
- optimal_dist = dist;
- min_bary_weight = new_min_bary_weight;
- }
- }
- psb->m_renderNodesInterpolationWeights[i] = optimal_bary;
- psb->m_renderNodesParents[i] = optimal_parents;
- psb->m_z[i] = optimal_dist;
- }
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
deleted file mode 100644
index 237d29761d..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyHelpers.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_BODY_HELPERS_H
-#define BT_SOFT_BODY_HELPERS_H
-
-#include "btSoftBody.h"
-#include <fstream>
-#include <string>
-//
-// Helpers
-//
-
-/* fDrawFlags */
-struct fDrawFlags
-{
- enum _
- {
- Nodes = 0x0001,
- Links = 0x0002,
- Faces = 0x0004,
- Tetras = 0x0008,
- Normals = 0x0010,
- Contacts = 0x0020,
- Anchors = 0x0040,
- Notes = 0x0080,
- Clusters = 0x0100,
- NodeTree = 0x0200,
- FaceTree = 0x0400,
- ClusterTree = 0x0800,
- Joints = 0x1000,
- /* presets */
- Std = Links + Faces + Tetras + Anchors + Notes + Joints,
- StdTetra = Std - Faces + Tetras
- };
-};
-
-struct btSoftBodyHelpers
-{
- /* Draw body */
- static void Draw(btSoftBody* psb,
- btIDebugDraw* idraw,
- int drawflags = fDrawFlags::Std);
- /* Draw body infos */
- static void DrawInfos(btSoftBody* psb,
- btIDebugDraw* idraw,
- bool masses,
- bool areas,
- bool stress);
- /* Draw node tree */
- static void DrawNodeTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth = 0,
- int maxdepth = -1);
- /* Draw face tree */
- static void DrawFaceTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth = 0,
- int maxdepth = -1);
- /* Draw cluster tree */
- static void DrawClusterTree(btSoftBody* psb,
- btIDebugDraw* idraw,
- int mindepth = 0,
- int maxdepth = -1);
- /* Draw rigid frame */
- static void DrawFrame(btSoftBody* psb,
- btIDebugDraw* idraw);
- /* Create a rope */
- static btSoftBody* CreateRope(btSoftBodyWorldInfo& worldInfo,
- const btVector3& from,
- const btVector3& to,
- int res,
- int fixeds);
- /* Create a patch */
- static btSoftBody* CreatePatch(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- btScalar perturbation = 0.);
- /* Create a patch with UV Texture Coordinates */
- static btSoftBody* CreatePatchUV(btSoftBodyWorldInfo& worldInfo,
- const btVector3& corner00,
- const btVector3& corner10,
- const btVector3& corner01,
- const btVector3& corner11,
- int resx,
- int resy,
- int fixeds,
- bool gendiags,
- float* tex_coords = 0);
- static float CalculateUV(int resx, int resy, int ix, int iy, int id);
- /* Create an ellipsoid */
- static btSoftBody* CreateEllipsoid(btSoftBodyWorldInfo& worldInfo,
- const btVector3& center,
- const btVector3& radius,
- int res);
- /* Create from trimesh */
- static btSoftBody* CreateFromTriMesh(btSoftBodyWorldInfo& worldInfo,
- const btScalar* vertices,
- const int* triangles,
- int ntriangles,
- bool randomizeConstraints = true);
- /* Create from convex-hull */
- static btSoftBody* CreateFromConvexHull(btSoftBodyWorldInfo& worldInfo,
- const btVector3* vertices,
- int nvertices,
- bool randomizeConstraints = true);
-
- /* Export TetGen compatible .smesh file */
- // static void ExportAsSMeshFile( btSoftBody* psb,
- // const char* filename);
- /* Create from TetGen .ele, .face, .node files */
- // static btSoftBody* CreateFromTetGenFile( btSoftBodyWorldInfo& worldInfo,
- // const char* ele,
- // const char* face,
- // const char* node,
- // bool bfacelinks,
- // bool btetralinks,
- // bool bfacesfromtetras);
- /* Create from TetGen .ele, .face, .node data */
- static btSoftBody* CreateFromTetGenData(btSoftBodyWorldInfo& worldInfo,
- const char* ele,
- const char* face,
- const char* node,
- bool bfacelinks,
- bool btetralinks,
- bool bfacesfromtetras);
- static btSoftBody* CreateFromVtkFile(btSoftBodyWorldInfo& worldInfo, const char* vtk_file);
-
- static void writeObj(const char* file, const btSoftBody* psb);
-
- static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, const btVector3& p, btVector4& bary);
-
- static void getBarycentricWeights(const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& p, btVector4& bary);
-
- static void interpolateBarycentricWeights(btSoftBody* psb);
-
- static void extrapolateBarycentricWeights(btSoftBody* psb);
-
- static void generateBoundaryFaces(btSoftBody* psb);
-
- static void duplicateFaces(const char* filename, const btSoftBody* psb);
- /// Sort the list of links to move link calculations that are dependent upon earlier
- /// ones as far as possible away from the calculation of those values
- /// This tends to make adjacent loop iterations not dependent upon one another,
- /// so out-of-order processors can execute instructions from multiple iterations at once
- static void ReoptimizeLinkOrder(btSoftBody* psb);
-};
-
-#endif //BT_SOFT_BODY_HELPERS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
deleted file mode 100644
index c17bbb5cd4..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyInternals.h
+++ /dev/null
@@ -1,2108 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btSoftBody implementation by Nathanael Presson
-
-#ifndef _BT_SOFT_BODY_INTERNALS_H
-#define _BT_SOFT_BODY_INTERNALS_H
-
-#include "btSoftBody.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btPolarDecomposition.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-#include "BulletDynamics/Featherstone/btMultiBodyLinkCollider.h"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.h"
-#include <string.h> //for memset
-#include <cmath>
-#include "poly34.h"
-
-// Given a multibody link, a contact point and a contact direction, fill in the jacobian data needed to calculate the velocity change given an impulse in the contact direction
-static SIMD_FORCE_INLINE void findJacobian(const btMultiBodyLinkCollider* multibodyLinkCol,
- btMultiBodyJacobianData& jacobianData,
- const btVector3& contact_point,
- const btVector3& dir)
-{
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- jacobianData.m_jacobians.resize(ndof);
- jacobianData.m_deltaVelocitiesUnitImpulse.resize(ndof);
- btScalar* jac = &jacobianData.m_jacobians[0];
-
- multibodyLinkCol->m_multiBody->fillContactJacobianMultiDof(multibodyLinkCol->m_link, contact_point, dir, jac, jacobianData.scratch_r, jacobianData.scratch_v, jacobianData.scratch_m);
- multibodyLinkCol->m_multiBody->calcAccelerationDeltasMultiDof(&jacobianData.m_jacobians[0], &jacobianData.m_deltaVelocitiesUnitImpulse[0], jacobianData.scratch_r, jacobianData.scratch_v);
-}
-static SIMD_FORCE_INLINE btVector3 generateUnitOrthogonalVector(const btVector3& u)
-{
- btScalar ux = u.getX();
- btScalar uy = u.getY();
- btScalar uz = u.getZ();
- btScalar ax = std::abs(ux);
- btScalar ay = std::abs(uy);
- btScalar az = std::abs(uz);
- btVector3 v;
- if (ax <= ay && ax <= az)
- v = btVector3(0, -uz, uy);
- else if (ay <= ax && ay <= az)
- v = btVector3(-uz, 0, ux);
- else
- v = btVector3(-uy, ux, 0);
- v.normalize();
- return v;
-}
-
-static SIMD_FORCE_INLINE bool proximityTest(const btVector3& x1, const btVector3& x2, const btVector3& x3, const btVector3& x4, const btVector3& normal, const btScalar& mrg, btVector3& bary)
-{
- btVector3 x43 = x4 - x3;
- if (std::abs(x43.dot(normal)) > mrg)
- return false;
- btVector3 x13 = x1 - x3;
- btVector3 x23 = x2 - x3;
- btScalar a11 = x13.length2();
- btScalar a22 = x23.length2();
- btScalar a12 = x13.dot(x23);
- btScalar b1 = x13.dot(x43);
- btScalar b2 = x23.dot(x43);
- btScalar det = a11 * a22 - a12 * a12;
- if (det < SIMD_EPSILON)
- return false;
- btScalar w1 = (b1 * a22 - b2 * a12) / det;
- btScalar w2 = (b2 * a11 - b1 * a12) / det;
- btScalar w3 = 1 - w1 - w2;
- btScalar delta = mrg / std::sqrt(0.5 * std::abs(x13.cross(x23).safeNorm()));
- bary = btVector3(w1, w2, w3);
- for (int i = 0; i < 3; ++i)
- {
- if (bary[i] < -delta || bary[i] > 1 + delta)
- return false;
- }
- return true;
-}
-static const int KDOP_COUNT = 13;
-static btVector3 dop[KDOP_COUNT] = {btVector3(1, 0, 0),
- btVector3(0, 1, 0),
- btVector3(0, 0, 1),
- btVector3(1, 1, 0),
- btVector3(1, 0, 1),
- btVector3(0, 1, 1),
- btVector3(1, -1, 0),
- btVector3(1, 0, -1),
- btVector3(0, 1, -1),
- btVector3(1, 1, 1),
- btVector3(1, -1, 1),
- btVector3(1, 1, -1),
- btVector3(1, -1, -1)};
-
-static inline int getSign(const btVector3& n, const btVector3& x)
-{
- btScalar d = n.dot(x);
- if (d > SIMD_EPSILON)
- return 1;
- if (d < -SIMD_EPSILON)
- return -1;
- return 0;
-}
-
-static SIMD_FORCE_INLINE bool hasSeparatingPlane(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
-{
- btVector3 hex[6] = {face->m_n[0]->m_x - node->m_x,
- face->m_n[1]->m_x - node->m_x,
- face->m_n[2]->m_x - node->m_x,
- face->m_n[0]->m_x + dt * face->m_n[0]->m_v - node->m_x,
- face->m_n[1]->m_x + dt * face->m_n[1]->m_v - node->m_x,
- face->m_n[2]->m_x + dt * face->m_n[2]->m_v - node->m_x};
- btVector3 segment = dt * node->m_v;
- for (int i = 0; i < KDOP_COUNT; ++i)
- {
- int s = getSign(dop[i], segment);
- int j = 0;
- for (; j < 6; ++j)
- {
- if (getSign(dop[i], hex[j]) == s)
- break;
- }
- if (j == 6)
- return true;
- }
- return false;
-}
-
-static SIMD_FORCE_INLINE bool nearZero(const btScalar& a)
-{
- return (a > -SAFE_EPSILON && a < SAFE_EPSILON);
-}
-static SIMD_FORCE_INLINE bool sameSign(const btScalar& a, const btScalar& b)
-{
- return (nearZero(a) || nearZero(b) || (a > SAFE_EPSILON && b > SAFE_EPSILON) || (a < -SAFE_EPSILON && b < -SAFE_EPSILON));
-}
-static SIMD_FORCE_INLINE bool diffSign(const btScalar& a, const btScalar& b)
-{
- return !sameSign(a, b);
-}
-inline btScalar evaluateBezier2(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& t, const btScalar& s)
-{
- btScalar s2 = s * s;
- btScalar t2 = t * t;
-
- return p0 * s2 + p1 * btScalar(2.0) * s * t + p2 * t2;
-}
-inline btScalar evaluateBezier(const btScalar& p0, const btScalar& p1, const btScalar& p2, const btScalar& p3, const btScalar& t, const btScalar& s)
-{
- btScalar s2 = s * s;
- btScalar s3 = s2 * s;
- btScalar t2 = t * t;
- btScalar t3 = t2 * t;
-
- return p0 * s3 + p1 * btScalar(3.0) * s2 * t + p2 * btScalar(3.0) * s * t2 + p3 * t3;
-}
-static SIMD_FORCE_INLINE bool getSigns(bool type_c, const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, const btScalar& t1, btScalar& lt0, btScalar& lt1)
-{
- if (sameSign(t0, t1))
- {
- lt0 = t0;
- lt1 = t0;
- return true;
- }
-
- if (type_c || diffSign(k0, k3))
- {
- btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
- if (t0 < -0)
- ft = -ft;
-
- if (sameSign(ft, k0))
- {
- lt0 = t1;
- lt1 = t1;
- }
- else
- {
- lt0 = t0;
- lt1 = t0;
- }
- return true;
- }
-
- if (!type_c)
- {
- btScalar ft = evaluateBezier(k0, k1, k2, k3, t0, -t1);
- if (t0 < -0)
- ft = -ft;
-
- if (diffSign(ft, k0))
- {
- lt0 = t0;
- lt1 = t1;
- return true;
- }
-
- btScalar fk = evaluateBezier2(k1 - k0, k2 - k1, k3 - k2, t0, -t1);
-
- if (sameSign(fk, k1 - k0))
- lt0 = lt1 = t1;
- else
- lt0 = lt1 = t0;
-
- return true;
- }
- return false;
-}
-
-static SIMD_FORCE_INLINE void getBernsteinCoeff(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, btScalar& k0, btScalar& k1, btScalar& k2, btScalar& k3)
-{
- const btVector3& n0 = face->m_n0;
- const btVector3& n1 = face->m_n1;
- btVector3 n_hat = n0 + n1 - face->m_vn;
- btVector3 p0ma0 = node->m_x - face->m_n[0]->m_x;
- btVector3 p1ma1 = node->m_q - face->m_n[0]->m_q;
- k0 = (p0ma0).dot(n0) * 3.0;
- k1 = (p0ma0).dot(n_hat) + (p1ma1).dot(n0);
- k2 = (p1ma1).dot(n_hat) + (p0ma0).dot(n1);
- k3 = (p1ma1).dot(n1) * 3.0;
-}
-
-static SIMD_FORCE_INLINE void polyDecomposition(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, btScalar& u0, btScalar& u1, btScalar& v0, btScalar& v1)
-{
- btScalar denom = 4.0 * (j1 - j2) * (j1 - j0) + (j2 - j0) * (j2 - j0);
- u0 = (2.0 * (j1 - j2) * (3.0 * k1 - 2.0 * k0 - k3) - (j0 - j2) * (3.0 * k2 - 2.0 * k3 - k0)) / denom;
- u1 = (2.0 * (j1 - j0) * (3.0 * k2 - 2.0 * k3 - k0) - (j2 - j0) * (3.0 * k1 - 2.0 * k0 - k3)) / denom;
- v0 = k0 - u0 * j0;
- v1 = k3 - u1 * j2;
-}
-
-static SIMD_FORCE_INLINE bool rootFindingLemma(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3)
-{
- btScalar u0, u1, v0, v1;
- btScalar j0 = 3.0 * (k1 - k0);
- btScalar j1 = 3.0 * (k2 - k1);
- btScalar j2 = 3.0 * (k3 - k2);
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (sameSign(v0, v1))
- {
- btScalar Ypa = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * v0 * (1.0 - v0) + j2 * v0 * v0; // Y'(v0)
- if (sameSign(Ypa, j0))
- {
- return (diffSign(k0, v1));
- }
- }
- return diffSign(k0, v0);
-}
-
-static SIMD_FORCE_INLINE void getJs(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Node* a, const btSoftBody::Node* b, const btSoftBody::Node* c, const btSoftBody::Node* p, const btScalar& dt, btScalar& j0, btScalar& j1, btScalar& j2)
-{
- const btVector3& a0 = a->m_x;
- const btVector3& b0 = b->m_x;
- const btVector3& c0 = c->m_x;
- const btVector3& va = a->m_v;
- const btVector3& vb = b->m_v;
- const btVector3& vc = c->m_v;
- const btVector3 a1 = a0 + dt * va;
- const btVector3 b1 = b0 + dt * vb;
- const btVector3 c1 = c0 + dt * vc;
- btVector3 n0 = (b0 - a0).cross(c0 - a0);
- btVector3 n1 = (b1 - a1).cross(c1 - a1);
- btVector3 n_hat = n0 + n1 - dt * dt * (vb - va).cross(vc - va);
- const btVector3& p0 = p->m_x;
- const btVector3& vp = p->m_v;
- btVector3 p1 = p0 + dt * vp;
- btVector3 m0 = (b0 - p0).cross(c0 - p0);
- btVector3 m1 = (b1 - p1).cross(c1 - p1);
- btVector3 m_hat = m0 + m1 - dt * dt * (vb - vp).cross(vc - vp);
- btScalar l0 = m0.dot(n0);
- btScalar l1 = 0.25 * (m0.dot(n_hat) + m_hat.dot(n0));
- btScalar l2 = btScalar(1) / btScalar(6) * (m0.dot(n1) + m_hat.dot(n_hat) + m1.dot(n0));
- btScalar l3 = 0.25 * (m_hat.dot(n1) + m1.dot(n_hat));
- btScalar l4 = m1.dot(n1);
-
- btScalar k1p = 0.25 * k0 + 0.75 * k1;
- btScalar k2p = 0.5 * k1 + 0.5 * k2;
- btScalar k3p = 0.75 * k2 + 0.25 * k3;
-
- btScalar s0 = (l1 * k0 - l0 * k1p) * 4.0;
- btScalar s1 = (l2 * k0 - l0 * k2p) * 2.0;
- btScalar s2 = (l3 * k0 - l0 * k3p) * btScalar(4) / btScalar(3);
- btScalar s3 = l4 * k0 - l0 * k3;
-
- j0 = (s1 * k0 - s0 * k1) * 3.0;
- j1 = (s2 * k0 - s0 * k2) * 1.5;
- j2 = (s3 * k0 - s0 * k3);
-}
-
-static SIMD_FORCE_INLINE bool signDetermination1Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
-{
- btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0; // Y(u0)
- btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0; // Y(v0)
-
- btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0;
- btScalar L = sameSign(sign_Ytp, k0) ? u1 : u0;
- sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
- btScalar K = (sameSign(sign_Ytp, k0)) ? v1 : v0;
- return diffSign(L, K);
-}
-
-static SIMD_FORCE_INLINE bool signDetermination2Internal(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& j0, const btScalar& j1, const btScalar& j2, const btScalar& u0, const btScalar& u1, const btScalar& v0, const btScalar& v1)
-{
- btScalar Yu0 = k0 * (1.0 - u0) * (1.0 - u0) * (1.0 - u0) + 3.0 * k1 * u0 * (1.0 - u0) * (1.0 - u0) + 3.0 * k2 * u0 * u0 * (1.0 - u0) + k3 * u0 * u0 * u0; // Y(u0)
- btScalar sign_Ytp = (u0 > u1) ? Yu0 : -Yu0, L1, L2;
- if (diffSign(sign_Ytp, k0))
- {
- L1 = u0;
- L2 = u1;
- }
- else
- {
- btScalar Yp_u0 = j0 * (1.0 - u0) * (1.0 - u0) + 2.0 * j1 * (1.0 - u0) * u0 + j2 * u0 * u0;
- if (sameSign(Yp_u0, j0))
- {
- L1 = u1;
- L2 = u1;
- }
- else
- {
- L1 = u0;
- L2 = u0;
- }
- }
- btScalar Yv0 = k0 * (1.0 - v0) * (1.0 - v0) * (1.0 - v0) + 3.0 * k1 * v0 * (1.0 - v0) * (1.0 - v0) + 3.0 * k2 * v0 * v0 * (1.0 - v0) + k3 * v0 * v0 * v0; // Y(uv0)
- sign_Ytp = (v0 > v1) ? Yv0 : -Yv0;
- btScalar K1, K2;
- if (diffSign(sign_Ytp, k0))
- {
- K1 = v0;
- K2 = v1;
- }
- else
- {
- btScalar Yp_v0 = j0 * (1.0 - v0) * (1.0 - v0) + 2.0 * j1 * (1.0 - v0) * v0 + j2 * v0 * v0;
- if (sameSign(Yp_v0, j0))
- {
- K1 = v1;
- K2 = v1;
- }
- else
- {
- K1 = v0;
- K2 = v0;
- }
- }
- return (diffSign(K1, L1) || diffSign(L2, K2));
-}
-
-static SIMD_FORCE_INLINE bool signDetermination1(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
-{
- btScalar j0, j1, j2, u0, u1, v0, v1;
- // p1
- getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
- return false;
- }
- // p2
- getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
- return false;
- }
- // p3
- getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- getSigns(true, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination1Internal(k0, k1, k2, k3, u0, u1, v0, v1))
- return false;
- }
- return true;
-}
-
-static SIMD_FORCE_INLINE bool signDetermination2(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
-{
- btScalar j0, j1, j2, u0, u1, v0, v1;
- // p1
- getJs(k0, k1, k2, k3, face->m_n[0], face->m_n[1], face->m_n[2], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- bool bt0 = true, bt1 = true;
- getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- bt0 = false;
- if (lt1 < -SAFE_EPSILON)
- bt1 = false;
- if (!bt0 && !bt1)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
- return false;
- }
- // p2
- getJs(k0, k1, k2, k3, face->m_n[1], face->m_n[2], face->m_n[0], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- bool bt0 = true, bt1 = true;
- getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- bt0 = false;
- if (lt1 < -SAFE_EPSILON)
- bt1 = false;
- if (!bt0 && !bt1)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
- return false;
- }
- // p3
- getJs(k0, k1, k2, k3, face->m_n[2], face->m_n[0], face->m_n[1], node, dt, j0, j1, j2);
- if (nearZero(j0 + j2 - j1 * 2.0))
- {
- btScalar lt0, lt1;
- bool bt0 = true, bt1 = true;
- getSigns(false, k0, k1, k2, k3, j0, j2, lt0, lt1);
- if (lt0 < -SAFE_EPSILON)
- bt0 = false;
- if (lt1 < -SAFE_EPSILON)
- bt1 = false;
- if (!bt0 && !bt1)
- return false;
- }
- else
- {
- polyDecomposition(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1);
- if (!signDetermination2Internal(k0, k1, k2, k3, j0, j1, j2, u0, u1, v0, v1))
- return false;
- }
- return true;
-}
-
-static SIMD_FORCE_INLINE bool coplanarAndInsideTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
-{
- // Coplanar test
- if (diffSign(k1 - k0, k3 - k2))
- {
- // Case b:
- if (sameSign(k0, k3) && !rootFindingLemma(k0, k1, k2, k3))
- return false;
- // inside test
- return signDetermination2(k0, k1, k2, k3, face, node, dt);
- }
- else
- {
- // Case c:
- if (sameSign(k0, k3))
- return false;
- // inside test
- return signDetermination1(k0, k1, k2, k3, face, node, dt);
- }
- return false;
-}
-static SIMD_FORCE_INLINE bool conservativeCulling(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg)
-{
- if (k0 > mrg && k1 > mrg && k2 > mrg && k3 > mrg)
- return true;
- if (k0 < -mrg && k1 < -mrg && k2 < -mrg && k3 < -mrg)
- return true;
- return false;
-}
-
-static SIMD_FORCE_INLINE bool bernsteinVFTest(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& mrg, const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt)
-{
- if (conservativeCulling(k0, k1, k2, k3, mrg))
- return false;
- return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
-}
-
-static SIMD_FORCE_INLINE void deCasteljau(const btScalar& k0, const btScalar& k1, const btScalar& k2, const btScalar& k3, const btScalar& t0, btScalar& k10, btScalar& k20, btScalar& k30, btScalar& k21, btScalar& k12)
-{
- k10 = k0 * (1.0 - t0) + k1 * t0;
- btScalar k11 = k1 * (1.0 - t0) + k2 * t0;
- k12 = k2 * (1.0 - t0) + k3 * t0;
- k20 = k10 * (1.0 - t0) + k11 * t0;
- k21 = k11 * (1.0 - t0) + k12 * t0;
- k30 = k20 * (1.0 - t0) + k21 * t0;
-}
-static SIMD_FORCE_INLINE bool bernsteinVFTest(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg)
-{
- btScalar k0, k1, k2, k3;
- getBernsteinCoeff(face, node, dt, k0, k1, k2, k3);
- if (conservativeCulling(k0, k1, k2, k3, mrg))
- return false;
- return true;
- if (diffSign(k2 - 2.0 * k1 + k0, k3 - 2.0 * k2 + k1))
- {
- btScalar k10, k20, k30, k21, k12;
- btScalar t0 = (k2 - 2.0 * k1 + k0) / (k0 - 3.0 * k1 + 3.0 * k2 - k3);
- deCasteljau(k0, k1, k2, k3, t0, k10, k20, k30, k21, k12);
- return bernsteinVFTest(k0, k10, k20, k30, mrg, face, node, dt) || bernsteinVFTest(k30, k21, k12, k3, mrg, face, node, dt);
- }
- return coplanarAndInsideTest(k0, k1, k2, k3, face, node, dt);
-}
-
-static SIMD_FORCE_INLINE bool continuousCollisionDetection(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
-{
- if (hasSeparatingPlane(face, node, dt))
- return false;
- btVector3 x21 = face->m_n[1]->m_x - face->m_n[0]->m_x;
- btVector3 x31 = face->m_n[2]->m_x - face->m_n[0]->m_x;
- btVector3 x41 = node->m_x - face->m_n[0]->m_x;
- btVector3 v21 = face->m_n[1]->m_v - face->m_n[0]->m_v;
- btVector3 v31 = face->m_n[2]->m_v - face->m_n[0]->m_v;
- btVector3 v41 = node->m_v - face->m_n[0]->m_v;
- btVector3 a = x21.cross(x31);
- btVector3 b = x21.cross(v31) + v21.cross(x31);
- btVector3 c = v21.cross(v31);
- btVector3 d = x41;
- btVector3 e = v41;
- btScalar a0 = a.dot(d);
- btScalar a1 = a.dot(e) + b.dot(d);
- btScalar a2 = c.dot(d) + b.dot(e);
- btScalar a3 = c.dot(e);
- btScalar eps = SAFE_EPSILON;
- int num_roots = 0;
- btScalar roots[3];
- if (std::abs(a3) < eps)
- {
- // cubic term is zero
- if (std::abs(a2) < eps)
- {
- if (std::abs(a1) < eps)
- {
- if (std::abs(a0) < eps)
- {
- num_roots = 2;
- roots[0] = 0;
- roots[1] = dt;
- }
- }
- else
- {
- num_roots = 1;
- roots[0] = -a0 / a1;
- }
- }
- else
- {
- num_roots = SolveP2(roots, a1 / a2, a0 / a2);
- }
- }
- else
- {
- num_roots = SolveP3(roots, a2 / a3, a1 / a3, a0 / a3);
- }
- // std::sort(roots, roots+num_roots);
- if (num_roots > 1)
- {
- if (roots[0] > roots[1])
- btSwap(roots[0], roots[1]);
- }
- if (num_roots > 2)
- {
- if (roots[0] > roots[2])
- btSwap(roots[0], roots[2]);
- if (roots[1] > roots[2])
- btSwap(roots[1], roots[2]);
- }
- for (int r = 0; r < num_roots; ++r)
- {
- double root = roots[r];
- if (root <= 0)
- continue;
- if (root > dt + SIMD_EPSILON)
- return false;
- btVector3 x1 = face->m_n[0]->m_x + root * face->m_n[0]->m_v;
- btVector3 x2 = face->m_n[1]->m_x + root * face->m_n[1]->m_v;
- btVector3 x3 = face->m_n[2]->m_x + root * face->m_n[2]->m_v;
- btVector3 x4 = node->m_x + root * node->m_v;
- btVector3 normal = (x2 - x1).cross(x3 - x1);
- normal.safeNormalize();
- if (proximityTest(x1, x2, x3, x4, normal, mrg, bary))
- return true;
- }
- return false;
-}
-static SIMD_FORCE_INLINE bool bernsteinCCD(const btSoftBody::Face* face, const btSoftBody::Node* node, const btScalar& dt, const btScalar& mrg, btVector3& bary)
-{
- if (!bernsteinVFTest(face, node, dt, mrg))
- return false;
- if (!continuousCollisionDetection(face, node, dt, 1e-6, bary))
- return false;
- return true;
-}
-
-//
-// btSymMatrix
-//
-template <typename T>
-struct btSymMatrix
-{
- btSymMatrix() : dim(0) {}
- btSymMatrix(int n, const T& init = T()) { resize(n, init); }
- void resize(int n, const T& init = T())
- {
- dim = n;
- store.resize((n * (n + 1)) / 2, init);
- }
- int index(int c, int r) const
- {
- if (c > r) btSwap(c, r);
- btAssert(r < dim);
- return ((r * (r + 1)) / 2 + c);
- }
- T& operator()(int c, int r) { return (store[index(c, r)]); }
- const T& operator()(int c, int r) const { return (store[index(c, r)]); }
- btAlignedObjectArray<T> store;
- int dim;
-};
-
-//
-// btSoftBodyCollisionShape
-//
-class btSoftBodyCollisionShape : public btConcaveShape
-{
-public:
- btSoftBody* m_body;
-
- btSoftBodyCollisionShape(btSoftBody* backptr)
- {
- m_shapeType = SOFTBODY_SHAPE_PROXYTYPE;
- m_body = backptr;
- }
-
- virtual ~btSoftBodyCollisionShape()
- {
- }
-
- void processAllTriangles(btTriangleCallback* /*callback*/, const btVector3& /*aabbMin*/, const btVector3& /*aabbMax*/) const
- {
- //not yet
- btAssert(0);
- }
-
- ///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- /* t is usually identity, except when colliding against btCompoundShape. See Issue 512 */
- const btVector3 mins = m_body->m_bounds[0];
- const btVector3 maxs = m_body->m_bounds[1];
- const btVector3 crns[] = {t * btVector3(mins.x(), mins.y(), mins.z()),
- t * btVector3(maxs.x(), mins.y(), mins.z()),
- t * btVector3(maxs.x(), maxs.y(), mins.z()),
- t * btVector3(mins.x(), maxs.y(), mins.z()),
- t * btVector3(mins.x(), mins.y(), maxs.z()),
- t * btVector3(maxs.x(), mins.y(), maxs.z()),
- t * btVector3(maxs.x(), maxs.y(), maxs.z()),
- t * btVector3(mins.x(), maxs.y(), maxs.z())};
- aabbMin = aabbMax = crns[0];
- for (int i = 1; i < 8; ++i)
- {
- aabbMin.setMin(crns[i]);
- aabbMax.setMax(crns[i]);
- }
- }
-
- virtual void setLocalScaling(const btVector3& /*scaling*/)
- {
- ///na
- }
- virtual const btVector3& getLocalScaling() const
- {
- static const btVector3 dummy(1, 1, 1);
- return dummy;
- }
- virtual void calculateLocalInertia(btScalar /*mass*/, btVector3& /*inertia*/) const
- {
- ///not yet
- btAssert(0);
- }
- virtual const char* getName() const
- {
- return "SoftBody";
- }
-};
-
-//
-// btSoftClusterCollisionShape
-//
-class btSoftClusterCollisionShape : public btConvexInternalShape
-{
-public:
- const btSoftBody::Cluster* m_cluster;
-
- btSoftClusterCollisionShape(const btSoftBody::Cluster* cluster) : m_cluster(cluster) { setMargin(0); }
-
- virtual btVector3 localGetSupportingVertex(const btVector3& vec) const
- {
- btSoftBody::Node* const* n = &m_cluster->m_nodes[0];
- btScalar d = btDot(vec, n[0]->m_x);
- int j = 0;
- for (int i = 1, ni = m_cluster->m_nodes.size(); i < ni; ++i)
- {
- const btScalar k = btDot(vec, n[i]->m_x);
- if (k > d)
- {
- d = k;
- j = i;
- }
- }
- return (n[j]->m_x);
- }
- virtual btVector3 localGetSupportingVertexWithoutMargin(const btVector3& vec) const
- {
- return (localGetSupportingVertex(vec));
- }
- //notice that the vectors should be unit length
- virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
- {
- }
-
- virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const
- {
- }
-
- virtual void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
- {
- }
-
- virtual int getShapeType() const { return SOFTBODY_SHAPE_PROXYTYPE; }
-
- //debugging
- virtual const char* getName() const { return "SOFTCLUSTER"; }
-
- virtual void setMargin(btScalar margin)
- {
- btConvexInternalShape::setMargin(margin);
- }
- virtual btScalar getMargin() const
- {
- return btConvexInternalShape::getMargin();
- }
-};
-
-//
-// Inline's
-//
-
-//
-template <typename T>
-static inline void ZeroInitialize(T& value)
-{
- memset(&value, 0, sizeof(T));
-}
-//
-template <typename T>
-static inline bool CompLess(const T& a, const T& b)
-{
- return (a < b);
-}
-//
-template <typename T>
-static inline bool CompGreater(const T& a, const T& b)
-{
- return (a > b);
-}
-//
-template <typename T>
-static inline T Lerp(const T& a, const T& b, btScalar t)
-{
- return (a + (b - a) * t);
-}
-//
-template <typename T>
-static inline T InvLerp(const T& a, const T& b, btScalar t)
-{
- return ((b + a * t - b * t) / (a * b));
-}
-//
-static inline btMatrix3x3 Lerp(const btMatrix3x3& a,
- const btMatrix3x3& b,
- btScalar t)
-{
- btMatrix3x3 r;
- r[0] = Lerp(a[0], b[0], t);
- r[1] = Lerp(a[1], b[1], t);
- r[2] = Lerp(a[2], b[2], t);
- return (r);
-}
-//
-static inline btVector3 Clamp(const btVector3& v, btScalar maxlength)
-{
- const btScalar sql = v.length2();
- if (sql > (maxlength * maxlength))
- return ((v * maxlength) / btSqrt(sql));
- else
- return (v);
-}
-//
-template <typename T>
-static inline T Clamp(const T& x, const T& l, const T& h)
-{
- return (x < l ? l : x > h ? h : x);
-}
-//
-template <typename T>
-static inline T Sq(const T& x)
-{
- return (x * x);
-}
-//
-template <typename T>
-static inline T Cube(const T& x)
-{
- return (x * x * x);
-}
-//
-template <typename T>
-static inline T Sign(const T& x)
-{
- return ((T)(x < 0 ? -1 : +1));
-}
-//
-template <typename T>
-static inline bool SameSign(const T& x, const T& y)
-{
- return ((x * y) > 0);
-}
-//
-static inline btScalar ClusterMetric(const btVector3& x, const btVector3& y)
-{
- const btVector3 d = x - y;
- return (btFabs(d[0]) + btFabs(d[1]) + btFabs(d[2]));
-}
-//
-static inline btMatrix3x3 ScaleAlongAxis(const btVector3& a, btScalar s)
-{
- const btScalar xx = a.x() * a.x();
- const btScalar yy = a.y() * a.y();
- const btScalar zz = a.z() * a.z();
- const btScalar xy = a.x() * a.y();
- const btScalar yz = a.y() * a.z();
- const btScalar zx = a.z() * a.x();
- btMatrix3x3 m;
- m[0] = btVector3(1 - xx + xx * s, xy * s - xy, zx * s - zx);
- m[1] = btVector3(xy * s - xy, 1 - yy + yy * s, yz * s - yz);
- m[2] = btVector3(zx * s - zx, yz * s - yz, 1 - zz + zz * s);
- return (m);
-}
-//
-static inline btMatrix3x3 Cross(const btVector3& v)
-{
- btMatrix3x3 m;
- m[0] = btVector3(0, -v.z(), +v.y());
- m[1] = btVector3(+v.z(), 0, -v.x());
- m[2] = btVector3(-v.y(), +v.x(), 0);
- return (m);
-}
-//
-static inline btMatrix3x3 Diagonal(btScalar x)
-{
- btMatrix3x3 m;
- m[0] = btVector3(x, 0, 0);
- m[1] = btVector3(0, x, 0);
- m[2] = btVector3(0, 0, x);
- return (m);
-}
-
-static inline btMatrix3x3 Diagonal(const btVector3& v)
-{
- btMatrix3x3 m;
- m[0] = btVector3(v.getX(), 0, 0);
- m[1] = btVector3(0, v.getY(), 0);
- m[2] = btVector3(0, 0, v.getZ());
- return (m);
-}
-
-static inline btScalar Dot(const btScalar* a, const btScalar* b, int ndof)
-{
- btScalar result = 0;
- for (int i = 0; i < ndof; ++i)
- result += a[i] * b[i];
- return result;
-}
-
-static inline btMatrix3x3 OuterProduct(const btScalar* v1, const btScalar* v2, const btScalar* v3,
- const btScalar* u1, const btScalar* u2, const btScalar* u3, int ndof)
-{
- btMatrix3x3 m;
- btScalar a11 = Dot(v1, u1, ndof);
- btScalar a12 = Dot(v1, u2, ndof);
- btScalar a13 = Dot(v1, u3, ndof);
-
- btScalar a21 = Dot(v2, u1, ndof);
- btScalar a22 = Dot(v2, u2, ndof);
- btScalar a23 = Dot(v2, u3, ndof);
-
- btScalar a31 = Dot(v3, u1, ndof);
- btScalar a32 = Dot(v3, u2, ndof);
- btScalar a33 = Dot(v3, u3, ndof);
- m[0] = btVector3(a11, a12, a13);
- m[1] = btVector3(a21, a22, a23);
- m[2] = btVector3(a31, a32, a33);
- return (m);
-}
-
-static inline btMatrix3x3 OuterProduct(const btVector3& v1, const btVector3& v2)
-{
- btMatrix3x3 m;
- btScalar a11 = v1[0] * v2[0];
- btScalar a12 = v1[0] * v2[1];
- btScalar a13 = v1[0] * v2[2];
-
- btScalar a21 = v1[1] * v2[0];
- btScalar a22 = v1[1] * v2[1];
- btScalar a23 = v1[1] * v2[2];
-
- btScalar a31 = v1[2] * v2[0];
- btScalar a32 = v1[2] * v2[1];
- btScalar a33 = v1[2] * v2[2];
- m[0] = btVector3(a11, a12, a13);
- m[1] = btVector3(a21, a22, a23);
- m[2] = btVector3(a31, a32, a33);
- return (m);
-}
-
-//
-static inline btMatrix3x3 Add(const btMatrix3x3& a,
- const btMatrix3x3& b)
-{
- btMatrix3x3 r;
- for (int i = 0; i < 3; ++i) r[i] = a[i] + b[i];
- return (r);
-}
-//
-static inline btMatrix3x3 Sub(const btMatrix3x3& a,
- const btMatrix3x3& b)
-{
- btMatrix3x3 r;
- for (int i = 0; i < 3; ++i) r[i] = a[i] - b[i];
- return (r);
-}
-//
-static inline btMatrix3x3 Mul(const btMatrix3x3& a,
- btScalar b)
-{
- btMatrix3x3 r;
- for (int i = 0; i < 3; ++i) r[i] = a[i] * b;
- return (r);
-}
-//
-static inline void Orthogonalize(btMatrix3x3& m)
-{
- m[2] = btCross(m[0], m[1]).normalized();
- m[1] = btCross(m[2], m[0]).normalized();
- m[0] = btCross(m[1], m[2]).normalized();
-}
-//
-static inline btMatrix3x3 MassMatrix(btScalar im, const btMatrix3x3& iwi, const btVector3& r)
-{
- const btMatrix3x3 cr = Cross(r);
- return (Sub(Diagonal(im), cr * iwi * cr));
-}
-
-//
-static inline btMatrix3x3 ImpulseMatrix(btScalar dt,
- btScalar ima,
- btScalar imb,
- const btMatrix3x3& iwi,
- const btVector3& r)
-{
- return (Diagonal(1 / dt) * Add(Diagonal(ima), MassMatrix(imb, iwi, r)).inverse());
-}
-
-//
-static inline btMatrix3x3 ImpulseMatrix(btScalar dt,
- const btMatrix3x3& effective_mass_inv,
- btScalar imb,
- const btMatrix3x3& iwi,
- const btVector3& r)
-{
- return (Diagonal(1 / dt) * Add(effective_mass_inv, MassMatrix(imb, iwi, r)).inverse());
- // btMatrix3x3 iimb = MassMatrix(imb, iwi, r);
- // if (iimb.determinant() == 0)
- // return effective_mass_inv.inverse();
- // return effective_mass_inv.inverse() * Add(effective_mass_inv.inverse(), iimb.inverse()).inverse() * iimb.inverse();
-}
-
-//
-static inline btMatrix3x3 ImpulseMatrix(btScalar ima, const btMatrix3x3& iia, const btVector3& ra,
- btScalar imb, const btMatrix3x3& iib, const btVector3& rb)
-{
- return (Add(MassMatrix(ima, iia, ra), MassMatrix(imb, iib, rb)).inverse());
-}
-
-//
-static inline btMatrix3x3 AngularImpulseMatrix(const btMatrix3x3& iia,
- const btMatrix3x3& iib)
-{
- return (Add(iia, iib).inverse());
-}
-
-//
-static inline btVector3 ProjectOnAxis(const btVector3& v,
- const btVector3& a)
-{
- return (a * btDot(v, a));
-}
-//
-static inline btVector3 ProjectOnPlane(const btVector3& v,
- const btVector3& a)
-{
- return (v - ProjectOnAxis(v, a));
-}
-
-//
-static inline void ProjectOrigin(const btVector3& a,
- const btVector3& b,
- btVector3& prj,
- btScalar& sqd)
-{
- const btVector3 d = b - a;
- const btScalar m2 = d.length2();
- if (m2 > SIMD_EPSILON)
- {
- const btScalar t = Clamp<btScalar>(-btDot(a, d) / m2, 0, 1);
- const btVector3 p = a + d * t;
- const btScalar l2 = p.length2();
- if (l2 < sqd)
- {
- prj = p;
- sqd = l2;
- }
- }
-}
-//
-static inline void ProjectOrigin(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- btVector3& prj,
- btScalar& sqd)
-{
- const btVector3& q = btCross(b - a, c - a);
- const btScalar m2 = q.length2();
- if (m2 > SIMD_EPSILON)
- {
- const btVector3 n = q / btSqrt(m2);
- const btScalar k = btDot(a, n);
- const btScalar k2 = k * k;
- if (k2 < sqd)
- {
- const btVector3 p = n * k;
- if ((btDot(btCross(a - p, b - p), q) > 0) &&
- (btDot(btCross(b - p, c - p), q) > 0) &&
- (btDot(btCross(c - p, a - p), q) > 0))
- {
- prj = p;
- sqd = k2;
- }
- else
- {
- ProjectOrigin(a, b, prj, sqd);
- ProjectOrigin(b, c, prj, sqd);
- ProjectOrigin(c, a, prj, sqd);
- }
- }
- }
-}
-
-//
-static inline bool rayIntersectsTriangle(const btVector3& origin, const btVector3& dir, const btVector3& v0, const btVector3& v1, const btVector3& v2, btScalar& t)
-{
- btScalar a, f, u, v;
-
- btVector3 e1 = v1 - v0;
- btVector3 e2 = v2 - v0;
- btVector3 h = dir.cross(e2);
- a = e1.dot(h);
-
- if (a > -0.00001 && a < 0.00001)
- return (false);
-
- f = btScalar(1) / a;
- btVector3 s = origin - v0;
- u = f * s.dot(h);
-
- if (u < 0.0 || u > 1.0)
- return (false);
-
- btVector3 q = s.cross(e1);
- v = f * dir.dot(q);
- if (v < 0.0 || u + v > 1.0)
- return (false);
- // at this stage we can compute t to find out where
- // the intersection point is on the line
- t = f * e2.dot(q);
- if (t > 0) // ray intersection
- return (true);
- else // this means that there is a line intersection
- // but not a ray intersection
- return (false);
-}
-
-static inline bool lineIntersectsTriangle(const btVector3& rayStart, const btVector3& rayEnd, const btVector3& p1, const btVector3& p2, const btVector3& p3, btVector3& sect, btVector3& normal)
-{
- btVector3 dir = rayEnd - rayStart;
- btScalar dir_norm = dir.norm();
- if (dir_norm < SIMD_EPSILON)
- return false;
- dir.normalize();
- btScalar t;
- bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t);
-
- if (ret)
- {
- if (t <= dir_norm)
- {
- sect = rayStart + dir * t;
- }
- else
- {
- ret = false;
- }
- }
-
- if (ret)
- {
- btVector3 n = (p3 - p1).cross(p2 - p1);
- n.safeNormalize();
- if (n.dot(dir) < 0)
- normal = n;
- else
- normal = -n;
- }
- return ret;
-}
-
-//
-template <typename T>
-static inline T BaryEval(const T& a,
- const T& b,
- const T& c,
- const btVector3& coord)
-{
- return (a * coord.x() + b * coord.y() + c * coord.z());
-}
-//
-static inline btVector3 BaryCoord(const btVector3& a,
- const btVector3& b,
- const btVector3& c,
- const btVector3& p)
-{
- const btScalar w[] = {btCross(a - p, b - p).length(),
- btCross(b - p, c - p).length(),
- btCross(c - p, a - p).length()};
- const btScalar isum = 1 / (w[0] + w[1] + w[2]);
- return (btVector3(w[1] * isum, w[2] * isum, w[0] * isum));
-}
-
-//
-inline static btScalar ImplicitSolve(btSoftBody::ImplicitFn* fn,
- const btVector3& a,
- const btVector3& b,
- const btScalar accuracy,
- const int maxiterations = 256)
-{
- btScalar span[2] = {0, 1};
- btScalar values[2] = {fn->Eval(a), fn->Eval(b)};
- if (values[0] > values[1])
- {
- btSwap(span[0], span[1]);
- btSwap(values[0], values[1]);
- }
- if (values[0] > -accuracy) return (-1);
- if (values[1] < +accuracy) return (-1);
- for (int i = 0; i < maxiterations; ++i)
- {
- const btScalar t = Lerp(span[0], span[1], values[0] / (values[0] - values[1]));
- const btScalar v = fn->Eval(Lerp(a, b, t));
- if ((t <= 0) || (t >= 1)) break;
- if (btFabs(v) < accuracy) return (t);
- if (v < 0)
- {
- span[0] = t;
- values[0] = v;
- }
- else
- {
- span[1] = t;
- values[1] = v;
- }
- }
- return (-1);
-}
-
-inline static void EvaluateMedium(const btSoftBodyWorldInfo* wfi,
- const btVector3& x,
- btSoftBody::sMedium& medium)
-{
- medium.m_velocity = btVector3(0, 0, 0);
- medium.m_pressure = 0;
- medium.m_density = wfi->air_density;
- if (wfi->water_density > 0)
- {
- const btScalar depth = -(btDot(x, wfi->water_normal) + wfi->water_offset);
- if (depth > 0)
- {
- medium.m_density = wfi->water_density;
- medium.m_pressure = depth * wfi->water_density * wfi->m_gravity.length();
- }
- }
-}
-
-//
-static inline btVector3 NormalizeAny(const btVector3& v)
-{
- const btScalar l = v.length();
- if (l > SIMD_EPSILON)
- return (v / l);
- else
- return (btVector3(0, 0, 0));
-}
-
-//
-static inline btDbvtVolume VolumeOf(const btSoftBody::Face& f,
- btScalar margin)
-{
- const btVector3* pts[] = {&f.m_n[0]->m_x,
- &f.m_n[1]->m_x,
- &f.m_n[2]->m_x};
- btDbvtVolume vol = btDbvtVolume::FromPoints(pts, 3);
- vol.Expand(btVector3(margin, margin, margin));
- return (vol);
-}
-
-//
-static inline btVector3 CenterOf(const btSoftBody::Face& f)
-{
- return ((f.m_n[0]->m_x + f.m_n[1]->m_x + f.m_n[2]->m_x) / 3);
-}
-
-//
-static inline btScalar AreaOf(const btVector3& x0,
- const btVector3& x1,
- const btVector3& x2)
-{
- const btVector3 a = x1 - x0;
- const btVector3 b = x2 - x0;
- const btVector3 cr = btCross(a, b);
- const btScalar area = cr.length();
- return (area);
-}
-
-//
-static inline btScalar VolumeOf(const btVector3& x0,
- const btVector3& x1,
- const btVector3& x2,
- const btVector3& x3)
-{
- const btVector3 a = x1 - x0;
- const btVector3 b = x2 - x0;
- const btVector3 c = x3 - x0;
- return (btDot(a, btCross(b, c)));
-}
-
-//
-
-//
-static inline void ApplyClampedForce(btSoftBody::Node& n,
- const btVector3& f,
- btScalar dt)
-{
- const btScalar dtim = dt * n.m_im;
- if ((f * dtim).length2() > n.m_v.length2())
- { /* Clamp */
- n.m_f -= ProjectOnAxis(n.m_v, f.normalized()) / dtim;
- }
- else
- { /* Apply */
- n.m_f += f;
- }
-}
-
-//
-static inline int MatchEdge(const btSoftBody::Node* a,
- const btSoftBody::Node* b,
- const btSoftBody::Node* ma,
- const btSoftBody::Node* mb)
-{
- if ((a == ma) && (b == mb)) return (0);
- if ((a == mb) && (b == ma)) return (1);
- return (-1);
-}
-
-//
-// btEigen : Extract eigen system,
-// straitforward implementation of http://math.fullerton.edu/mathews/n2003/JacobiMethodMod.html
-// outputs are NOT sorted.
-//
-struct btEigen
-{
- static int system(btMatrix3x3& a, btMatrix3x3* vectors, btVector3* values = 0)
- {
- static const int maxiterations = 16;
- static const btScalar accuracy = (btScalar)0.0001;
- btMatrix3x3& v = *vectors;
- int iterations = 0;
- vectors->setIdentity();
- do
- {
- int p = 0, q = 1;
- if (btFabs(a[p][q]) < btFabs(a[0][2]))
- {
- p = 0;
- q = 2;
- }
- if (btFabs(a[p][q]) < btFabs(a[1][2]))
- {
- p = 1;
- q = 2;
- }
- if (btFabs(a[p][q]) > accuracy)
- {
- const btScalar w = (a[q][q] - a[p][p]) / (2 * a[p][q]);
- const btScalar z = btFabs(w);
- const btScalar t = w / (z * (btSqrt(1 + w * w) + z));
- if (t == t) /* [WARNING] let hope that one does not get thrown aways by some compilers... */
- {
- const btScalar c = 1 / btSqrt(t * t + 1);
- const btScalar s = c * t;
- mulPQ(a, c, s, p, q);
- mulTPQ(a, c, s, p, q);
- mulPQ(v, c, s, p, q);
- }
- else
- break;
- }
- else
- break;
- } while ((++iterations) < maxiterations);
- if (values)
- {
- *values = btVector3(a[0][0], a[1][1], a[2][2]);
- }
- return (iterations);
- }
-
-private:
- static inline void mulTPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
- {
- const btScalar m[2][3] = {{a[p][0], a[p][1], a[p][2]},
- {a[q][0], a[q][1], a[q][2]}};
- int i;
-
- for (i = 0; i < 3; ++i) a[p][i] = c * m[0][i] - s * m[1][i];
- for (i = 0; i < 3; ++i) a[q][i] = c * m[1][i] + s * m[0][i];
- }
- static inline void mulPQ(btMatrix3x3& a, btScalar c, btScalar s, int p, int q)
- {
- const btScalar m[2][3] = {{a[0][p], a[1][p], a[2][p]},
- {a[0][q], a[1][q], a[2][q]}};
- int i;
-
- for (i = 0; i < 3; ++i) a[i][p] = c * m[0][i] - s * m[1][i];
- for (i = 0; i < 3; ++i) a[i][q] = c * m[1][i] + s * m[0][i];
- }
-};
-
-//
-// Polar decomposition,
-// "Computing the Polar Decomposition with Applications", Nicholas J. Higham, 1986.
-//
-static inline int PolarDecompose(const btMatrix3x3& m, btMatrix3x3& q, btMatrix3x3& s)
-{
- static const btPolarDecomposition polar;
- return polar.decompose(m, q, s);
-}
-
-//
-// btSoftColliders
-//
-struct btSoftColliders
-{
- //
- // ClusterBase
- //
- struct ClusterBase : btDbvt::ICollide
- {
- btScalar erp;
- btScalar idt;
- btScalar m_margin;
- btScalar friction;
- btScalar threshold;
- ClusterBase()
- {
- erp = (btScalar)1;
- idt = 0;
- m_margin = 0;
- friction = 0;
- threshold = (btScalar)0;
- }
- bool SolveContact(const btGjkEpaSolver2::sResults& res,
- btSoftBody::Body ba, const btSoftBody::Body bb,
- btSoftBody::CJoint& joint)
- {
- if (res.distance < m_margin)
- {
- btVector3 norm = res.normal;
- norm.normalize(); //is it necessary?
-
- const btVector3 ra = res.witnesses[0] - ba.xform().getOrigin();
- const btVector3 rb = res.witnesses[1] - bb.xform().getOrigin();
- const btVector3 va = ba.velocity(ra);
- const btVector3 vb = bb.velocity(rb);
- const btVector3 vrel = va - vb;
- const btScalar rvac = btDot(vrel, norm);
- btScalar depth = res.distance - m_margin;
-
- // printf("depth=%f\n",depth);
- const btVector3 iv = norm * rvac;
- const btVector3 fv = vrel - iv;
- joint.m_bodies[0] = ba;
- joint.m_bodies[1] = bb;
- joint.m_refs[0] = ra * ba.xform().getBasis();
- joint.m_refs[1] = rb * bb.xform().getBasis();
- joint.m_rpos[0] = ra;
- joint.m_rpos[1] = rb;
- joint.m_cfm = 1;
- joint.m_erp = 1;
- joint.m_life = 0;
- joint.m_maxlife = 0;
- joint.m_split = 1;
-
- joint.m_drift = depth * norm;
-
- joint.m_normal = norm;
- // printf("normal=%f,%f,%f\n",res.normal.getX(),res.normal.getY(),res.normal.getZ());
- joint.m_delete = false;
- joint.m_friction = fv.length2() < (rvac * friction * rvac * friction) ? 1 : friction;
- joint.m_massmatrix = ImpulseMatrix(ba.invMass(), ba.invWorldInertia(), joint.m_rpos[0],
- bb.invMass(), bb.invWorldInertia(), joint.m_rpos[1]);
-
- return (true);
- }
- return (false);
- }
- };
- //
- // CollideCL_RS
- //
- struct CollideCL_RS : ClusterBase
- {
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObjWrap;
-
- void Process(const btDbvtNode* leaf)
- {
- btSoftBody::Cluster* cluster = (btSoftBody::Cluster*)leaf->data;
- btSoftClusterCollisionShape cshape(cluster);
-
- const btConvexShape* rshape = (const btConvexShape*)m_colObjWrap->getCollisionShape();
-
- ///don't collide an anchored cluster with a static/kinematic object
- if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject() && cluster->m_containsAnchor)
- return;
-
- btGjkEpaSolver2::sResults res;
- if (btGjkEpaSolver2::SignedDistance(&cshape, btTransform::getIdentity(),
- rshape, m_colObjWrap->getWorldTransform(),
- btVector3(1, 0, 0), res))
- {
- btSoftBody::CJoint joint;
- if (SolveContact(res, cluster, m_colObjWrap->getCollisionObject(), joint)) //prb,joint))
- {
- btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
- *pj = joint;
- psb->m_joints.push_back(pj);
- if (m_colObjWrap->getCollisionObject()->isStaticOrKinematicObject())
- {
- pj->m_erp *= psb->m_cfg.kSKHR_CL;
- pj->m_split *= psb->m_cfg.kSK_SPLT_CL;
- }
- else
- {
- pj->m_erp *= psb->m_cfg.kSRHR_CL;
- pj->m_split *= psb->m_cfg.kSR_SPLT_CL;
- }
- }
- }
- }
- void ProcessColObj(btSoftBody* ps, const btCollisionObjectWrapper* colObWrap)
- {
- psb = ps;
- m_colObjWrap = colObWrap;
- idt = ps->m_sst.isdt;
- m_margin = m_colObjWrap->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin();
- ///Bullet rigid body uses multiply instead of minimum to determine combined friction. Some customization would be useful.
- friction = btMin(psb->m_cfg.kDF, m_colObjWrap->getCollisionObject()->getFriction());
- btVector3 mins;
- btVector3 maxs;
-
- ATTRIBUTE_ALIGNED16(btDbvtVolume)
- volume;
- colObWrap->getCollisionShape()->getAabb(colObWrap->getWorldTransform(), mins, maxs);
- volume = btDbvtVolume::FromMM(mins, maxs);
- volume.Expand(btVector3(1, 1, 1) * m_margin);
- ps->m_cdbvt.collideTV(ps->m_cdbvt.m_root, volume, *this);
- }
- };
- //
- // CollideCL_SS
- //
- struct CollideCL_SS : ClusterBase
- {
- btSoftBody* bodies[2];
- void Process(const btDbvtNode* la, const btDbvtNode* lb)
- {
- btSoftBody::Cluster* cla = (btSoftBody::Cluster*)la->data;
- btSoftBody::Cluster* clb = (btSoftBody::Cluster*)lb->data;
-
- bool connected = false;
- if ((bodies[0] == bodies[1]) && (bodies[0]->m_clusterConnectivity.size()))
- {
- connected = bodies[0]->m_clusterConnectivity[cla->m_clusterIndex + bodies[0]->m_clusters.size() * clb->m_clusterIndex];
- }
-
- if (!connected)
- {
- btSoftClusterCollisionShape csa(cla);
- btSoftClusterCollisionShape csb(clb);
- btGjkEpaSolver2::sResults res;
- if (btGjkEpaSolver2::SignedDistance(&csa, btTransform::getIdentity(),
- &csb, btTransform::getIdentity(),
- cla->m_com - clb->m_com, res))
- {
- btSoftBody::CJoint joint;
- if (SolveContact(res, cla, clb, joint))
- {
- btSoftBody::CJoint* pj = new (btAlignedAlloc(sizeof(btSoftBody::CJoint), 16)) btSoftBody::CJoint();
- *pj = joint;
- bodies[0]->m_joints.push_back(pj);
- pj->m_erp *= btMax(bodies[0]->m_cfg.kSSHR_CL, bodies[1]->m_cfg.kSSHR_CL);
- pj->m_split *= (bodies[0]->m_cfg.kSS_SPLT_CL + bodies[1]->m_cfg.kSS_SPLT_CL) / 2;
- }
- }
- }
- else
- {
- static int count = 0;
- count++;
- //printf("count=%d\n",count);
- }
- }
- void ProcessSoftSoft(btSoftBody* psa, btSoftBody* psb)
- {
- idt = psa->m_sst.isdt;
- //m_margin = (psa->getCollisionShape()->getMargin()+psb->getCollisionShape()->getMargin())/2;
- m_margin = (psa->getCollisionShape()->getMargin() + psb->getCollisionShape()->getMargin());
- friction = btMin(psa->m_cfg.kDF, psb->m_cfg.kDF);
- bodies[0] = psa;
- bodies[1] = psb;
- psa->m_cdbvt.collideTT(psa->m_cdbvt.m_root, psb->m_cdbvt.m_root, *this);
- }
- };
- //
- // CollideSDF_RS
- //
- struct CollideSDF_RS : btDbvt::ICollide
- {
- void Process(const btDbvtNode* leaf)
- {
- btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
- DoNode(*node);
- }
- void DoNode(btSoftBody::Node& n) const
- {
- const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
- btSoftBody::RContact c;
-
- if ((!n.m_battach) &&
- psb->checkContact(m_colObj1Wrap, n.m_x, m, c.m_cti))
- {
- const btScalar ima = n.m_im;
- const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
- const btScalar ms = ima + imb;
- if (ms > 0)
- {
- const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra = n.m_x - wtr.getOrigin();
- const btVector3 va = m_rigidBody ? m_rigidBody->getVelocityInLocalPoint(ra) * psb->m_sst.sdt : btVector3(0, 0, 0);
- const btVector3 vb = n.m_x - n.m_q;
- const btVector3 vr = vb - va;
- const btScalar dn = btDot(vr, c.m_cti.m_normal);
- const btVector3 fv = vr - c.m_cti.m_normal * dn;
- const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
- c.m_node = &n;
- c.m_c0 = ImpulseMatrix(psb->m_sst.sdt, ima, imb, iwi, ra);
- c.m_c1 = ra;
- c.m_c2 = ima * psb->m_sst.sdt;
- c.m_c3 = fv.length2() < (dn * fc * dn * fc) ? 0 : 1 - fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
- psb->m_rcontacts.push_back(c);
- if (m_rigidBody)
- m_rigidBody->activate();
- }
- }
- }
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObj1Wrap;
- btRigidBody* m_rigidBody;
- btScalar dynmargin;
- btScalar stamargin;
- };
-
- //
- // CollideSDF_RD
- //
- struct CollideSDF_RD : btDbvt::ICollide
- {
- void Process(const btDbvtNode* leaf)
- {
- btSoftBody::Node* node = (btSoftBody::Node*)leaf->data;
- DoNode(*node);
- }
- void DoNode(btSoftBody::Node& n) const
- {
- const btScalar m = n.m_im > 0 ? dynmargin : stamargin;
- btSoftBody::DeformableNodeRigidContact c;
-
- if (!n.m_battach)
- {
- // check for collision at x_{n+1}^*
- if (psb->checkDeformableContact(m_colObj1Wrap, n.m_q, m, c.m_cti, /*predict = */ true))
- {
- const btScalar ima = n.m_im;
- // todo: collision between multibody and fixed deformable node will be missed.
- const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
- const btScalar ms = ima + imb;
- if (ms > 0)
- {
- // resolve contact at x_n
- psb->checkDeformableContact(m_colObj1Wrap, n.m_x, m, c.m_cti, /*predict = */ false);
- btSoftBody::sCti& cti = c.m_cti;
- c.m_node = &n;
- const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
- c.m_c2 = ima;
- c.m_c3 = fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
- c.m_c5 = n.m_effectiveMass_inv;
-
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra = n.m_x - wtr.getOrigin();
-
- c.m_c0 = ImpulseMatrix(1, n.m_effectiveMass_inv, imb, iwi, ra);
- // c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
- c.m_c1 = ra;
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- btVector3 normal = cti.m_normal;
- btVector3 t1 = generateUnitOrthogonalVector(normal);
- btVector3 t2 = btCross(normal, t1);
- btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
- findJacobian(multibodyLinkCol, jacobianData_normal, c.m_node->m_x, normal);
- findJacobian(multibodyLinkCol, jacobianData_t1, c.m_node->m_x, t1);
- findJacobian(multibodyLinkCol, jacobianData_t2, c.m_node->m_x, t2);
-
- btScalar* J_n = &jacobianData_normal.m_jacobians[0];
- btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
- btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
-
- btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
-
- btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
- t1.getX(), t1.getY(), t1.getZ(),
- t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- btMatrix3x3 local_impulse_matrix = (n.m_effectiveMass_inv + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
- c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
- c.jacobianData_normal = jacobianData_normal;
- c.jacobianData_t1 = jacobianData_t1;
- c.jacobianData_t2 = jacobianData_t2;
- c.t1 = t1;
- c.t2 = t2;
- }
- }
- psb->m_nodeRigidContacts.push_back(c);
- }
- }
- }
- }
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObj1Wrap;
- btRigidBody* m_rigidBody;
- btScalar dynmargin;
- btScalar stamargin;
- };
-
- //
- // CollideSDF_RDF
- //
- struct CollideSDF_RDF : btDbvt::ICollide
- {
- void Process(const btDbvtNode* leaf)
- {
- btSoftBody::Face* face = (btSoftBody::Face*)leaf->data;
- DoNode(*face);
- }
- void DoNode(btSoftBody::Face& f) const
- {
- btSoftBody::Node* n0 = f.m_n[0];
- btSoftBody::Node* n1 = f.m_n[1];
- btSoftBody::Node* n2 = f.m_n[2];
- const btScalar m = (n0->m_im > 0 && n1->m_im > 0 && n2->m_im > 0) ? dynmargin : stamargin;
- btSoftBody::DeformableFaceRigidContact c;
- btVector3 contact_point;
- btVector3 bary;
- if (psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, true))
- {
- btScalar ima = n0->m_im + n1->m_im + n2->m_im;
- const btScalar imb = m_rigidBody ? m_rigidBody->getInvMass() : 0.f;
- // todo: collision between multibody and fixed deformable face will be missed.
- const btScalar ms = ima + imb;
- if (ms > 0)
- {
- // resolve contact at x_n
- // psb->checkDeformableFaceContact(m_colObj1Wrap, f, contact_point, bary, m, c.m_cti, /*predict = */ false);
- btSoftBody::sCti& cti = c.m_cti;
- c.m_contactPoint = contact_point;
- c.m_bary = bary;
- // todo xuchenhan@: this is assuming mass of all vertices are the same. Need to modify if mass are different for distinct vertices
- c.m_weights = btScalar(2) / (btScalar(1) + bary.length2()) * bary;
- c.m_face = &f;
- // friction is handled by the nodes to prevent sticking
- // const btScalar fc = 0;
- const btScalar fc = psb->m_cfg.kDF * m_colObj1Wrap->getCollisionObject()->getFriction();
-
- // the effective inverse mass of the face as in https://graphics.stanford.edu/papers/cloth-sig02/cloth.pdf
- ima = bary.getX() * c.m_weights.getX() * n0->m_im + bary.getY() * c.m_weights.getY() * n1->m_im + bary.getZ() * c.m_weights.getZ() * n2->m_im;
- c.m_c2 = ima;
- c.m_c3 = fc;
- c.m_c4 = m_colObj1Wrap->getCollisionObject()->isStaticOrKinematicObject() ? psb->m_cfg.kKHR : psb->m_cfg.kCHR;
- c.m_c5 = Diagonal(ima);
- if (cti.m_colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
- {
- const btTransform& wtr = m_rigidBody ? m_rigidBody->getWorldTransform() : m_colObj1Wrap->getCollisionObject()->getWorldTransform();
- static const btMatrix3x3 iwiStatic(0, 0, 0, 0, 0, 0, 0, 0, 0);
- const btMatrix3x3& iwi = m_rigidBody ? m_rigidBody->getInvInertiaTensorWorld() : iwiStatic;
- const btVector3 ra = contact_point - wtr.getOrigin();
-
- // we do not scale the impulse matrix by dt
- c.m_c0 = ImpulseMatrix(1, ima, imb, iwi, ra);
- c.m_c1 = ra;
- }
- else if (cti.m_colObj->getInternalType() == btCollisionObject::CO_FEATHERSTONE_LINK)
- {
- btMultiBodyLinkCollider* multibodyLinkCol = (btMultiBodyLinkCollider*)btMultiBodyLinkCollider::upcast(cti.m_colObj);
- if (multibodyLinkCol)
- {
- btVector3 normal = cti.m_normal;
- btVector3 t1 = generateUnitOrthogonalVector(normal);
- btVector3 t2 = btCross(normal, t1);
- btMultiBodyJacobianData jacobianData_normal, jacobianData_t1, jacobianData_t2;
- findJacobian(multibodyLinkCol, jacobianData_normal, contact_point, normal);
- findJacobian(multibodyLinkCol, jacobianData_t1, contact_point, t1);
- findJacobian(multibodyLinkCol, jacobianData_t2, contact_point, t2);
-
- btScalar* J_n = &jacobianData_normal.m_jacobians[0];
- btScalar* J_t1 = &jacobianData_t1.m_jacobians[0];
- btScalar* J_t2 = &jacobianData_t2.m_jacobians[0];
-
- btScalar* u_n = &jacobianData_normal.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t1 = &jacobianData_t1.m_deltaVelocitiesUnitImpulse[0];
- btScalar* u_t2 = &jacobianData_t2.m_deltaVelocitiesUnitImpulse[0];
-
- btMatrix3x3 rot(normal.getX(), normal.getY(), normal.getZ(),
- t1.getX(), t1.getY(), t1.getZ(),
- t2.getX(), t2.getY(), t2.getZ()); // world frame to local frame
- const int ndof = multibodyLinkCol->m_multiBody->getNumDofs() + 6;
- btMatrix3x3 local_impulse_matrix = (Diagonal(ima) + OuterProduct(J_n, J_t1, J_t2, u_n, u_t1, u_t2, ndof)).inverse();
- c.m_c0 = rot.transpose() * local_impulse_matrix * rot;
- c.jacobianData_normal = jacobianData_normal;
- c.jacobianData_t1 = jacobianData_t1;
- c.jacobianData_t2 = jacobianData_t2;
- c.t1 = t1;
- c.t2 = t2;
- }
- }
- psb->m_faceRigidContacts.push_back(c);
- }
- }
- // Set caching barycenters to be false after collision detection.
- // Only turn on when contact is static.
- f.m_pcontact[3] = 0;
- }
- btSoftBody* psb;
- const btCollisionObjectWrapper* m_colObj1Wrap;
- btRigidBody* m_rigidBody;
- btScalar dynmargin;
- btScalar stamargin;
- };
-
- //
- // CollideVF_SS
- //
- struct CollideVF_SS : btDbvt::ICollide
- {
- void Process(const btDbvtNode* lnode,
- const btDbvtNode* lface)
- {
- btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
- btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
- for (int i = 0; i < 3; ++i)
- {
- if (face->m_n[i] == node)
- continue;
- }
-
- btVector3 o = node->m_x;
- btVector3 p;
- btScalar d = SIMD_INFINITY;
- ProjectOrigin(face->m_n[0]->m_x - o,
- face->m_n[1]->m_x - o,
- face->m_n[2]->m_x - o,
- p, d);
- const btScalar m = mrg + (o - node->m_q).length() * 2;
- if (d < (m * m))
- {
- const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
- const btVector3 w = BaryCoord(n[0]->m_x, n[1]->m_x, n[2]->m_x, p + o);
- const btScalar ma = node->m_im;
- btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
- if ((n[0]->m_im <= 0) ||
- (n[1]->m_im <= 0) ||
- (n[2]->m_im <= 0))
- {
- mb = 0;
- }
- const btScalar ms = ma + mb;
- if (ms > 0)
- {
- btSoftBody::SContact c;
- c.m_normal = p / -btSqrt(d);
- c.m_margin = m;
- c.m_node = node;
- c.m_face = face;
- c.m_weights = w;
- c.m_friction = btMax(psb[0]->m_cfg.kDF, psb[1]->m_cfg.kDF);
- c.m_cfm[0] = ma / ms * psb[0]->m_cfg.kSHR;
- c.m_cfm[1] = mb / ms * psb[1]->m_cfg.kSHR;
- psb[0]->m_scontacts.push_back(c);
- }
- }
- }
- btSoftBody* psb[2];
- btScalar mrg;
- };
-
- //
- // CollideVF_DD
- //
- struct CollideVF_DD : btDbvt::ICollide
- {
- void Process(const btDbvtNode* lnode,
- const btDbvtNode* lface)
- {
- btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
- btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
- btVector3 bary;
- if (proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
- {
- const btSoftBody::Node* n[] = {face->m_n[0], face->m_n[1], face->m_n[2]};
- const btVector3 w = bary;
- const btScalar ma = node->m_im;
- btScalar mb = BaryEval(n[0]->m_im, n[1]->m_im, n[2]->m_im, w);
- if ((n[0]->m_im <= 0) ||
- (n[1]->m_im <= 0) ||
- (n[2]->m_im <= 0))
- {
- mb = 0;
- }
- const btScalar ms = ma + mb;
- if (ms > 0)
- {
- btSoftBody::DeformableFaceNodeContact c;
- c.m_normal = face->m_normal;
- if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
- c.m_normal = -face->m_normal;
- c.m_margin = mrg;
- c.m_node = node;
- c.m_face = face;
- c.m_bary = w;
- c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
- psb[0]->m_faceNodeContacts.push_back(c);
- }
- }
- }
- btSoftBody* psb[2];
- btScalar mrg;
- bool useFaceNormal;
- };
-
- //
- // CollideFF_DD
- //
- struct CollideFF_DD : btDbvt::ICollide
- {
- void Process(const btDbvntNode* lface1,
- const btDbvntNode* lface2)
- {
- btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
- btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
- if (f1 != f2)
- {
- Repel(f1, f2);
- Repel(f2, f1);
- }
- }
- void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
- {
- //#define REPEL_NEIGHBOR 1
-#ifndef REPEL_NEIGHBOR
- for (int node_id = 0; node_id < 3; ++node_id)
- {
- btSoftBody::Node* node = f1->m_n[node_id];
- for (int i = 0; i < 3; ++i)
- {
- if (f2->m_n[i] == node)
- return;
- }
- }
-#endif
- bool skip = false;
- for (int node_id = 0; node_id < 3; ++node_id)
- {
- btSoftBody::Node* node = f1->m_n[node_id];
-#ifdef REPEL_NEIGHBOR
- for (int i = 0; i < 3; ++i)
- {
- if (f2->m_n[i] == node)
- {
- skip = true;
- break;
- }
- }
- if (skip)
- {
- skip = false;
- continue;
- }
-#endif
- btSoftBody::Face* face = f2;
- btVector3 bary;
- if (!proximityTest(face->m_n[0]->m_x, face->m_n[1]->m_x, face->m_n[2]->m_x, node->m_x, face->m_normal, mrg, bary))
- continue;
- btSoftBody::DeformableFaceNodeContact c;
- c.m_normal = face->m_normal;
- if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
- c.m_normal = -face->m_normal;
- c.m_margin = mrg;
- c.m_node = node;
- c.m_face = face;
- c.m_bary = bary;
- c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
- psb[0]->m_faceNodeContacts.push_back(c);
- }
- }
- btSoftBody* psb[2];
- btScalar mrg;
- bool useFaceNormal;
- };
-
- struct CollideCCD : btDbvt::ICollide
- {
- void Process(const btDbvtNode* lnode,
- const btDbvtNode* lface)
- {
- btSoftBody::Node* node = (btSoftBody::Node*)lnode->data;
- btSoftBody::Face* face = (btSoftBody::Face*)lface->data;
- btVector3 bary;
- if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
- {
- btSoftBody::DeformableFaceNodeContact c;
- c.m_normal = face->m_normal;
- if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
- c.m_normal = -face->m_normal;
- c.m_node = node;
- c.m_face = face;
- c.m_bary = bary;
- c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
- psb[0]->m_faceNodeContacts.push_back(c);
- }
- }
- void Process(const btDbvntNode* lface1,
- const btDbvntNode* lface2)
- {
- btSoftBody::Face* f1 = (btSoftBody::Face*)lface1->data;
- btSoftBody::Face* f2 = (btSoftBody::Face*)lface2->data;
- if (f1 != f2)
- {
- Repel(f1, f2);
- Repel(f2, f1);
- }
- }
- void Repel(btSoftBody::Face* f1, btSoftBody::Face* f2)
- {
- //#define REPEL_NEIGHBOR 1
-#ifndef REPEL_NEIGHBOR
- for (int node_id = 0; node_id < 3; ++node_id)
- {
- btSoftBody::Node* node = f1->m_n[node_id];
- for (int i = 0; i < 3; ++i)
- {
- if (f2->m_n[i] == node)
- return;
- }
- }
-#endif
- bool skip = false;
- for (int node_id = 0; node_id < 3; ++node_id)
- {
- btSoftBody::Node* node = f1->m_n[node_id];
-#ifdef REPEL_NEIGHBOR
- for (int i = 0; i < 3; ++i)
- {
- if (f2->m_n[i] == node)
- {
- skip = true;
- break;
- }
- }
- if (skip)
- {
- skip = false;
- continue;
- }
-#endif
- btSoftBody::Face* face = f2;
- btVector3 bary;
- if (bernsteinCCD(face, node, dt, SAFE_EPSILON, bary))
- {
- btSoftBody::DeformableFaceNodeContact c;
- c.m_normal = face->m_normal;
- if (!useFaceNormal && c.m_normal.dot(node->m_x - face->m_n[2]->m_x) < 0)
- c.m_normal = -face->m_normal;
- c.m_node = node;
- c.m_face = face;
- c.m_bary = bary;
- c.m_friction = psb[0]->m_cfg.kDF * psb[1]->m_cfg.kDF;
- psb[0]->m_faceNodeContacts.push_back(c);
- }
- }
- }
- btSoftBody* psb[2];
- btScalar dt, mrg;
- bool useFaceNormal;
- };
-};
-#endif //_BT_SOFT_BODY_INTERNALS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
deleted file mode 100644
index 3127369ccd..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftBodyRigidBodyCollisionConfiguration.h"
-#include "btSoftRigidCollisionAlgorithm.h"
-#include "btSoftBodyConcaveCollisionAlgorithm.h"
-#include "btSoftSoftCollisionAlgorithm.h"
-
-#include "LinearMath/btPoolAllocator.h"
-
-#define ENABLE_SOFTBODY_CONCAVE_COLLISIONS 1
-
-btSoftBodyRigidBodyCollisionConfiguration::btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
- : btDefaultCollisionConfiguration(constructionInfo)
-{
- void* mem;
-
- mem = btAlignedAlloc(sizeof(btSoftSoftCollisionAlgorithm::CreateFunc), 16);
- m_softSoftCreateFunc = new (mem) btSoftSoftCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc), 16);
- m_softRigidConvexCreateFunc = new (mem) btSoftRigidCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btSoftRigidCollisionAlgorithm::CreateFunc), 16);
- m_swappedSoftRigidConvexCreateFunc = new (mem) btSoftRigidCollisionAlgorithm::CreateFunc;
- m_swappedSoftRigidConvexCreateFunc->m_swapped = true;
-
-#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
- mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc), 16);
- m_softRigidConcaveCreateFunc = new (mem) btSoftBodyConcaveCollisionAlgorithm::CreateFunc;
-
- mem = btAlignedAlloc(sizeof(btSoftBodyConcaveCollisionAlgorithm::CreateFunc), 16);
- m_swappedSoftRigidConcaveCreateFunc = new (mem) btSoftBodyConcaveCollisionAlgorithm::SwappedCreateFunc;
- m_swappedSoftRigidConcaveCreateFunc->m_swapped = true;
-#endif
-
- //replace pool by a new one, with potential larger size
-
- if (m_ownsCollisionAlgorithmPool && m_collisionAlgorithmPool)
- {
- int curElemSize = m_collisionAlgorithmPool->getElementSize();
- ///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
-
- int maxSize0 = sizeof(btSoftSoftCollisionAlgorithm);
- int maxSize1 = sizeof(btSoftRigidCollisionAlgorithm);
- int maxSize2 = sizeof(btSoftBodyConcaveCollisionAlgorithm);
-
- int collisionAlgorithmMaxElementSize = btMax(maxSize0, maxSize1);
- collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize, maxSize2);
-
- if (collisionAlgorithmMaxElementSize > curElemSize)
- {
- m_collisionAlgorithmPool->~btPoolAllocator();
- btAlignedFree(m_collisionAlgorithmPool);
- void* mem = btAlignedAlloc(sizeof(btPoolAllocator), 16);
- m_collisionAlgorithmPool = new (mem) btPoolAllocator(collisionAlgorithmMaxElementSize, constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
- }
- }
-}
-
-btSoftBodyRigidBodyCollisionConfiguration::~btSoftBodyRigidBodyCollisionConfiguration()
-{
- m_softSoftCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_softSoftCreateFunc);
-
- m_softRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_softRigidConvexCreateFunc);
-
- m_swappedSoftRigidConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_swappedSoftRigidConvexCreateFunc);
-
-#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
- m_softRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_softRigidConcaveCreateFunc);
-
- m_swappedSoftRigidConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
- btAlignedFree(m_swappedSoftRigidConcaveCreateFunc);
-#endif
-}
-
-///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
-btCollisionAlgorithmCreateFunc* btSoftBodyRigidBodyCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1)
-{
- ///try to handle the softbody interactions first
-
- if ((proxyType0 == SOFTBODY_SHAPE_PROXYTYPE) && (proxyType1 == SOFTBODY_SHAPE_PROXYTYPE))
- {
- return m_softSoftCreateFunc;
- }
-
- ///softbody versus convex
- if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConvex(proxyType1))
- {
- return m_softRigidConvexCreateFunc;
- }
-
- ///convex versus soft body
- if (btBroadphaseProxy::isConvex(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE)
- {
- return m_swappedSoftRigidConvexCreateFunc;
- }
-
-#ifdef ENABLE_SOFTBODY_CONCAVE_COLLISIONS
- ///softbody versus convex
- if (proxyType0 == SOFTBODY_SHAPE_PROXYTYPE && btBroadphaseProxy::isConcave(proxyType1))
- {
- return m_softRigidConcaveCreateFunc;
- }
-
- ///convex versus soft body
- if (btBroadphaseProxy::isConcave(proxyType0) && proxyType1 == SOFTBODY_SHAPE_PROXYTYPE)
- {
- return m_swappedSoftRigidConcaveCreateFunc;
- }
-#endif
-
- ///fallback to the regular rigid collision shape
- return btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(proxyType0, proxyType1);
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h b/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
deleted file mode 100644
index 0396a52dac..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
-#define BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
-
-#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
-
-class btVoronoiSimplexSolver;
-class btGjkEpaPenetrationDepthSolver;
-
-///btSoftBodyRigidBodyCollisionConfiguration add softbody interaction on top of btDefaultCollisionConfiguration
-class btSoftBodyRigidBodyCollisionConfiguration : public btDefaultCollisionConfiguration
-{
- //default CreationFunctions, filling the m_doubleDispatch table
- btCollisionAlgorithmCreateFunc* m_softSoftCreateFunc;
- btCollisionAlgorithmCreateFunc* m_softRigidConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConvexCreateFunc;
- btCollisionAlgorithmCreateFunc* m_softRigidConcaveCreateFunc;
- btCollisionAlgorithmCreateFunc* m_swappedSoftRigidConcaveCreateFunc;
-
-public:
- btSoftBodyRigidBodyCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
-
- virtual ~btSoftBodyRigidBodyCollisionConfiguration();
-
- ///creation of soft-soft and soft-rigid, and otherwise fallback to base class implementation
- virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0, int proxyType1);
-};
-
-#endif //BT_SOFTBODY_RIGIDBODY_COLLISION_CONFIGURATION
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h
deleted file mode 100644
index bc538db4a2..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolverVertexBuffer.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
-#define BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
-
-class btVertexBufferDescriptor
-{
-public:
- enum BufferTypes
- {
- CPU_BUFFER,
- DX11_BUFFER,
- OPENGL_BUFFER
- };
-
-protected:
- bool m_hasVertexPositions;
- bool m_hasNormals;
-
- int m_vertexOffset;
- int m_vertexStride;
-
- int m_normalOffset;
- int m_normalStride;
-
-public:
- btVertexBufferDescriptor()
- {
- m_hasVertexPositions = false;
- m_hasNormals = false;
- m_vertexOffset = 0;
- m_vertexStride = 0;
- m_normalOffset = 0;
- m_normalStride = 0;
- }
-
- virtual ~btVertexBufferDescriptor()
- {
- }
-
- virtual bool hasVertexPositions() const
- {
- return m_hasVertexPositions;
- }
-
- virtual bool hasNormals() const
- {
- return m_hasNormals;
- }
-
- /**
- * Return the type of the vertex buffer descriptor.
- */
- virtual BufferTypes getBufferType() const = 0;
-
- /**
- * Return the vertex offset in floats from the base pointer.
- */
- virtual int getVertexOffset() const
- {
- return m_vertexOffset;
- }
-
- /**
- * Return the vertex stride in number of floats between vertices.
- */
- virtual int getVertexStride() const
- {
- return m_vertexStride;
- }
-
- /**
- * Return the vertex offset in floats from the base pointer.
- */
- virtual int getNormalOffset() const
- {
- return m_normalOffset;
- }
-
- /**
- * Return the vertex stride in number of floats between vertices.
- */
- virtual int getNormalStride() const
- {
- return m_normalStride;
- }
-};
-
-class btCPUVertexBufferDescriptor : public btVertexBufferDescriptor
-{
-protected:
- float *m_basePointer;
-
-public:
- /**
- * vertexBasePointer is pointer to beginning of the buffer.
- * vertexOffset is the offset in floats to the first vertex.
- * vertexStride is the stride in floats between vertices.
- */
- btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride)
- {
- m_basePointer = basePointer;
- m_vertexOffset = vertexOffset;
- m_vertexStride = vertexStride;
- m_hasVertexPositions = true;
- }
-
- /**
- * vertexBasePointer is pointer to beginning of the buffer.
- * vertexOffset is the offset in floats to the first vertex.
- * vertexStride is the stride in floats between vertices.
- */
- btCPUVertexBufferDescriptor(float *basePointer, int vertexOffset, int vertexStride, int normalOffset, int normalStride)
- {
- m_basePointer = basePointer;
-
- m_vertexOffset = vertexOffset;
- m_vertexStride = vertexStride;
- m_hasVertexPositions = true;
-
- m_normalOffset = normalOffset;
- m_normalStride = normalStride;
- m_hasNormals = true;
- }
-
- virtual ~btCPUVertexBufferDescriptor()
- {
- }
-
- /**
- * Return the type of the vertex buffer descriptor.
- */
- virtual BufferTypes getBufferType() const
- {
- return CPU_BUFFER;
- }
-
- /**
- * Return the base pointer in memory to the first vertex.
- */
- virtual float *getBasePointer() const
- {
- return m_basePointer;
- }
-};
-
-#endif // #ifndef BT_SOFT_BODY_SOLVER_VERTEX_BUFFER_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h b/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
deleted file mode 100644
index dbb2624eee..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftBodySolvers.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_BODY_SOLVERS_H
-#define BT_SOFT_BODY_SOLVERS_H
-
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
-
-class btSoftBodyTriangleData;
-class btSoftBodyLinkData;
-class btSoftBodyVertexData;
-class btVertexBufferDescriptor;
-class btCollisionObject;
-class btSoftBody;
-
-class btSoftBodySolver
-{
-public:
- enum SolverTypes
- {
- DEFAULT_SOLVER,
- CPU_SOLVER,
- CL_SOLVER,
- CL_SIMD_SOLVER,
- DX_SOLVER,
- DX_SIMD_SOLVER,
- DEFORMABLE_SOLVER
- };
-
-protected:
- int m_numberOfPositionIterations;
- int m_numberOfVelocityIterations;
- // Simulation timescale
- float m_timeScale;
-
-public:
- btSoftBodySolver() : m_numberOfPositionIterations(10),
- m_timeScale(1)
- {
- m_numberOfVelocityIterations = 0;
- m_numberOfPositionIterations = 5;
- }
-
- virtual ~btSoftBodySolver()
- {
- }
-
- /**
- * Return the type of the solver.
- */
- virtual SolverTypes getSolverType() const = 0;
-
- /** Ensure that this solver is initialized. */
- virtual bool checkInitialized() = 0;
-
- /** Optimize soft bodies in this solver. */
- virtual void optimize(btAlignedObjectArray<btSoftBody *> &softBodies, bool forceUpdate = false) = 0;
-
- /** Copy necessary data back to the original soft body source objects. */
- virtual void copyBackToSoftBodies(bool bMove = true) = 0;
-
- /** Predict motion of soft bodies into next timestep */
- virtual void predictMotion(btScalar solverdt) = 0;
-
- /** Solve constraints for a set of soft bodies */
- virtual void solveConstraints(btScalar solverdt) = 0;
-
- /** Perform necessary per-step updates of soft bodies such as recomputing normals and bounding boxes */
- virtual void updateSoftBodies() = 0;
-
- /** Process a collision between one of the world's soft bodies and another collision object */
- virtual void processCollision(btSoftBody *, const struct btCollisionObjectWrapper *) = 0;
-
- /** Process a collision between two soft bodies */
- virtual void processCollision(btSoftBody *, btSoftBody *) = 0;
-
- /** Set the number of velocity constraint solver iterations this solver uses. */
- virtual void setNumberOfPositionIterations(int iterations)
- {
- m_numberOfPositionIterations = iterations;
- }
-
- /** Get the number of velocity constraint solver iterations this solver uses. */
- virtual int getNumberOfPositionIterations()
- {
- return m_numberOfPositionIterations;
- }
-
- /** Set the number of velocity constraint solver iterations this solver uses. */
- virtual void setNumberOfVelocityIterations(int iterations)
- {
- m_numberOfVelocityIterations = iterations;
- }
-
- /** Get the number of velocity constraint solver iterations this solver uses. */
- virtual int getNumberOfVelocityIterations()
- {
- return m_numberOfVelocityIterations;
- }
-
- /** Return the timescale that the simulation is using */
- float getTimeScale()
- {
- return m_timeScale;
- }
-
-#if 0
- /**
- * Add a collision object to be used by the indicated softbody.
- */
- virtual void addCollisionObjectForSoftBody( int clothIdentifier, btCollisionObject *collisionObject ) = 0;
-#endif
-};
-
-/**
- * Class to manage movement of data from a solver to a given target.
- * This version is abstract. Subclasses will have custom pairings for different combinations.
- */
-class btSoftBodySolverOutput
-{
-protected:
-public:
- btSoftBodySolverOutput()
- {
- }
-
- virtual ~btSoftBodySolverOutput()
- {
- }
-
- /** Output current computed vertex data to the vertex buffers for all cloths in the solver. */
- virtual void copySoftBodyToVertexBuffer(const btSoftBody *const softBody, btVertexBufferDescriptor *vertexBuffer) = 0;
-};
-
-#endif // #ifndef BT_SOFT_BODY_SOLVERS_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
deleted file mode 100644
index 329bd19d71..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.cpp
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftMultiBodyDynamicsWorld.h"
-#include "LinearMath/btQuickprof.h"
-
-//softbody & helpers
-#include "BulletSoftBody/btSoftBody.h"
-#include "BulletSoftBody/btSoftBodyHelpers.h"
-#include "BulletSoftBody/btSoftBodySolvers.h"
-#include "BulletSoftBody/btDefaultSoftBodySolver.h"
-#include "LinearMath/btSerializer.h"
-
-btSoftMultiBodyDynamicsWorld::btSoftMultiBodyDynamicsWorld(
- btDispatcher* dispatcher,
- btBroadphaseInterface* pairCache,
- btMultiBodyConstraintSolver* constraintSolver,
- btCollisionConfiguration* collisionConfiguration,
- btSoftBodySolver* softBodySolver) : btMultiBodyDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
- m_softBodySolver(softBodySolver),
- m_ownsSolver(false)
-{
- if (!m_softBodySolver)
- {
- void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
- m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
- m_ownsSolver = true;
- }
-
- m_drawFlags = fDrawFlags::Std;
- m_drawNodeTree = true;
- m_drawFaceTree = false;
- m_drawClusterTree = false;
- m_sbi.m_broadphase = pairCache;
- m_sbi.m_dispatcher = dispatcher;
- m_sbi.m_sparsesdf.Initialize();
- m_sbi.m_sparsesdf.Reset();
-
- m_sbi.air_density = (btScalar)1.2;
- m_sbi.water_density = 0;
- m_sbi.water_offset = 0;
- m_sbi.water_normal = btVector3(0, 0, 0);
- m_sbi.m_gravity.setValue(0, -10, 0);
-
- m_sbi.m_sparsesdf.Initialize();
-}
-
-btSoftMultiBodyDynamicsWorld::~btSoftMultiBodyDynamicsWorld()
-{
- if (m_ownsSolver)
- {
- m_softBodySolver->~btSoftBodySolver();
- btAlignedFree(m_softBodySolver);
- }
-}
-
-void btSoftMultiBodyDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
- {
- BT_PROFILE("predictUnconstraintMotionSoftBody");
- m_softBodySolver->predictMotion(float(timeStep));
- }
-}
-
-void btSoftMultiBodyDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
-{
- // Let the solver grab the soft bodies and if necessary optimize for it
- m_softBodySolver->optimize(getSoftBodyArray());
-
- if (!m_softBodySolver->checkInitialized())
- {
- btAssert("Solver initialization failed\n");
- }
-
- btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
-
- ///solve soft bodies constraints
- solveSoftBodiesConstraints(timeStep);
-
- //self collisions
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)m_softBodies[i];
- psb->defaultCollisionHandler(psb);
- }
-
- ///update soft bodies
- m_softBodySolver->updateSoftBodies();
-
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)m_softBodies[i];
- psb->interpolateRenderMesh();
- }
- // End solver-wise simulation step
- // ///////////////////////////////
-}
-
-void btSoftMultiBodyDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
-{
- BT_PROFILE("solveSoftConstraints");
-
- if (m_softBodies.size())
- {
- btSoftBody::solveClusters(m_softBodies);
- }
-
- // Solve constraints solver-wise
- m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
-}
-
-void btSoftMultiBodyDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
-{
- m_softBodies.push_back(body);
-
- // Set the soft body solver that will deal with this body
- // to be the world's solver
- body->setSoftBodySolver(m_softBodySolver);
-
- btCollisionWorld::addCollisionObject(body,
- collisionFilterGroup,
- collisionFilterMask);
-}
-
-void btSoftMultiBodyDynamicsWorld::removeSoftBody(btSoftBody* body)
-{
- m_softBodies.remove(body);
-
- btCollisionWorld::removeCollisionObject(body);
-}
-
-void btSoftMultiBodyDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- btSoftBody* body = btSoftBody::upcast(collisionObject);
- if (body)
- removeSoftBody(body);
- else
- btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
-}
-
-void btSoftMultiBodyDynamicsWorld::debugDrawWorld()
-{
- btMultiBodyDynamicsWorld::debugDrawWorld();
-
- if (getDebugDrawer())
- {
- int i;
- for (i = 0; i < this->m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
- {
- btSoftBodyHelpers::DrawFrame(psb, m_debugDrawer);
- btSoftBodyHelpers::Draw(psb, m_debugDrawer, m_drawFlags);
- }
-
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- if (m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb, m_debugDrawer);
- if (m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb, m_debugDrawer);
- if (m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb, m_debugDrawer);
- }
- }
- }
-}
-
-struct btSoftSingleRayCallback : public btBroadphaseRayCallback
-{
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btSoftMultiBodyDynamicsWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftMultiBodyDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- m_rayFromTrans.setIdentity();
- m_rayFromTrans.setOrigin(m_rayFromWorld);
- m_rayToTrans.setIdentity();
- m_rayToTrans.setOrigin(m_rayToWorld);
-
- btVector3 rayDir = (rayToWorld - rayFromWorld);
-
- rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/1e30
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
-
- m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further ray tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
-
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
-#if 0
-#ifdef RECALCULATE_AABB
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
-#else
- //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
- const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
- const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
-#endif
-#endif
- //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
- //culling already done by broadphase
- //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
- {
- m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
- }
- }
- return true;
- }
-};
-
-void btSoftMultiBodyDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
-{
- BT_PROFILE("rayTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
-
-#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
-#else
- for (int i = 0; i < this->getNumCollisionObjects(); i++)
- {
- rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-}
-
-void btSoftMultiBodyDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
-{
- if (collisionShape->isSoftBody())
- {
- btSoftBody* softBody = btSoftBody::upcast(collisionObject);
- if (softBody)
- {
- btSoftBody::sRayCast softResult;
- if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
- {
- if (softResult.fraction <= resultCallback.m_closestHitFraction)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = 0;
- shapeInfo.m_triangleIndex = softResult.index;
- // get the normal
- btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
- btVector3 normal = -rayDir;
- normal.normalize();
-
- if (softResult.feature == btSoftBody::eFeature::Face)
- {
- normal = softBody->m_faces[softResult.index].m_normal;
- if (normal.dot(rayDir) > 0)
- {
- // normal always point toward origin of the ray
- normal = -normal;
- }
- }
-
- btCollisionWorld::LocalRayResult rayResult(collisionObject,
- &shapeInfo,
- normal,
- softResult.fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(rayResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
- }
-}
-
-void btSoftMultiBodyDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
-{
- int i;
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
- {
- int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
- }
- }
-}
-
-void btSoftMultiBodyDynamicsWorld::serialize(btSerializer* serializer)
-{
- serializer->startSerialization();
-
- serializeDynamicsWorldInfo(serializer);
-
- serializeSoftBodies(serializer);
-
- serializeMultiBodies(serializer);
-
- serializeRigidBodies(serializer);
-
- serializeCollisionObjects(serializer);
-
- serializeContactManifolds(serializer);
-
- serializer->finishSerialization();
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
deleted file mode 100644
index f295945a6d..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftMultiBodyDynamicsWorld.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
-#define BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
-
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
-#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.h"
-#include "BulletSoftBody/btSoftBody.h"
-
-#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
-#endif
-
-class btSoftBodySolver;
-
-class btSoftMultiBodyDynamicsWorld : public btMultiBodyDynamicsWorld
-{
- btSoftBodyArray m_softBodies;
- int m_drawFlags;
- bool m_drawNodeTree;
- bool m_drawFaceTree;
- bool m_drawClusterTree;
- btSoftBodyWorldInfo m_sbi;
- ///Solver classes that encapsulate multiple soft bodies for solving
- btSoftBodySolver* m_softBodySolver;
- bool m_ownsSolver;
-
-protected:
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- virtual void internalSingleStepSimulation(btScalar timeStep);
-
- void solveSoftBodiesConstraints(btScalar timeStep);
-
- void serializeSoftBodies(btSerializer* serializer);
-
-public:
- btSoftMultiBodyDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btMultiBodyConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
-
- virtual ~btSoftMultiBodyDynamicsWorld();
-
- virtual void debugDrawWorld();
-
- void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
-
- void removeSoftBody(btSoftBody* body);
-
- ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- int getDrawFlags() const { return (m_drawFlags); }
- void setDrawFlags(int f) { m_drawFlags = f; }
-
- btSoftBodyWorldInfo& getWorldInfo()
- {
- return m_sbi;
- }
- const btSoftBodyWorldInfo& getWorldInfo() const
- {
- return m_sbi;
- }
-
- virtual btDynamicsWorldType getWorldType() const
- {
- return BT_SOFT_MULTIBODY_DYNAMICS_WORLD;
- }
-
- btSoftBodyArray& getSoftBodyArray()
- {
- return m_softBodies;
- }
-
- const btSoftBodyArray& getSoftBodyArray() const
- {
- return m_softBodies;
- }
-
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
-
- /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
- /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
- /// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
-
- virtual void serialize(btSerializer* serializer);
-};
-
-#endif //BT_SOFT_MULTIBODY_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
deleted file mode 100644
index 5b65216e4b..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftRigidCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "btSoftBody.h"
-#include "BulletSoftBody/btSoftBodySolvers.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-///TODO: include all the shapes that the softbody can collide with
-///alternatively, implement special case collision algorithms (just like for rigid collision shapes)
-
-//#include <stdio.h>
-
-btSoftRigidCollisionAlgorithm::btSoftRigidCollisionAlgorithm(btPersistentManifold* /*mf*/, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper*, const btCollisionObjectWrapper*, bool isSwapped)
- : btCollisionAlgorithm(ci),
- //m_ownManifold(false),
- //m_manifoldPtr(mf),
- m_isSwapped(isSwapped)
-{
-}
-
-btSoftRigidCollisionAlgorithm::~btSoftRigidCollisionAlgorithm()
-{
- //m_softBody->m_overlappingRigidBodies.remove(m_rigidCollisionObject);
-
- /*if (m_ownManifold)
- {
- if (m_manifoldPtr)
- m_dispatcher->releaseManifold(m_manifoldPtr);
- }
- */
-}
-
-#include <stdio.h>
-#include "LinearMath/btQuickprof.h"
-void btSoftRigidCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- BT_PROFILE("btSoftRigidCollisionAlgorithm::processCollision");
- (void)dispatchInfo;
- (void)resultOut;
- //printf("btSoftRigidCollisionAlgorithm\n");
- // const btCollisionObjectWrapper* softWrap = m_isSwapped?body1Wrap:body0Wrap;
- // const btCollisionObjectWrapper* rigidWrap = m_isSwapped?body0Wrap:body1Wrap;
- btSoftBody* softBody = m_isSwapped ? (btSoftBody*)body1Wrap->getCollisionObject() : (btSoftBody*)body0Wrap->getCollisionObject();
- const btCollisionObjectWrapper* rigidCollisionObjectWrap = m_isSwapped ? body0Wrap : body1Wrap;
-
- if (softBody->m_collisionDisabledObjects.findLinearSearch(rigidCollisionObjectWrap->getCollisionObject()) == softBody->m_collisionDisabledObjects.size())
- {
- softBody->getSoftBodySolver()->processCollision(softBody, rigidCollisionObjectWrap);
- }
-}
-
-btScalar btSoftRigidCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0, btCollisionObject* col1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut)
-{
- (void)resultOut;
- (void)dispatchInfo;
- (void)col0;
- (void)col1;
-
- //not yet
- return btScalar(1.);
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
deleted file mode 100644
index 9773af19a0..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidCollisionAlgorithm.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_RIGID_COLLISION_ALGORITHM_H
-#define BT_SOFT_RIGID_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-class btPersistentManifold;
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-
-#include "LinearMath/btVector3.h"
-class btSoftBody;
-
-/// btSoftRigidCollisionAlgorithm provides collision detection between btSoftBody and btRigidBody
-class btSoftRigidCollisionAlgorithm : public btCollisionAlgorithm
-{
- // bool m_ownManifold;
- // btPersistentManifold* m_manifoldPtr;
-
- //btSoftBody* m_softBody;
- //btCollisionObject* m_rigidCollisionObject;
-
- ///for rigid versus soft (instead of soft versus rigid), we use this swapped boolean
- bool m_isSwapped;
-
-public:
- btSoftRigidCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* col0, const btCollisionObjectWrapper* col1Wrap, bool isSwapped);
-
- virtual ~btSoftRigidCollisionAlgorithm();
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- //we don't add any manifolds
- }
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSoftRigidCollisionAlgorithm));
- if (!m_swapped)
- {
- return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, false);
- }
- else
- {
- return new (mem) btSoftRigidCollisionAlgorithm(0, ci, body0Wrap, body1Wrap, true);
- }
- }
- };
-};
-
-#endif //BT_SOFT_RIGID_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
deleted file mode 100644
index 510b731fc1..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.cpp
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftRigidDynamicsWorld.h"
-#include "LinearMath/btQuickprof.h"
-
-//softbody & helpers
-#include "btSoftBody.h"
-#include "btSoftBodyHelpers.h"
-#include "btSoftBodySolvers.h"
-#include "btDefaultSoftBodySolver.h"
-#include "LinearMath/btSerializer.h"
-
-btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(
- btDispatcher* dispatcher,
- btBroadphaseInterface* pairCache,
- btConstraintSolver* constraintSolver,
- btCollisionConfiguration* collisionConfiguration,
- btSoftBodySolver* softBodySolver) : btDiscreteDynamicsWorld(dispatcher, pairCache, constraintSolver, collisionConfiguration),
- m_softBodySolver(softBodySolver),
- m_ownsSolver(false)
-{
- if (!m_softBodySolver)
- {
- void* ptr = btAlignedAlloc(sizeof(btDefaultSoftBodySolver), 16);
- m_softBodySolver = new (ptr) btDefaultSoftBodySolver();
- m_ownsSolver = true;
- }
-
- m_drawFlags = fDrawFlags::Std;
- m_drawNodeTree = true;
- m_drawFaceTree = false;
- m_drawClusterTree = false;
- m_sbi.m_broadphase = pairCache;
- m_sbi.m_dispatcher = dispatcher;
- m_sbi.m_sparsesdf.Initialize();
- m_sbi.m_sparsesdf.Reset();
-
- m_sbi.air_density = (btScalar)1.2;
- m_sbi.water_density = 0;
- m_sbi.water_offset = 0;
- m_sbi.water_normal = btVector3(0, 0, 0);
- m_sbi.m_gravity.setValue(0, -10, 0);
-
- m_sbi.m_sparsesdf.Initialize();
-}
-
-btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld()
-{
- if (m_ownsSolver)
- {
- m_softBodySolver->~btSoftBodySolver();
- btAlignedFree(m_softBodySolver);
- }
-}
-
-void btSoftRigidDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
-{
- btDiscreteDynamicsWorld::predictUnconstraintMotion(timeStep);
- {
- BT_PROFILE("predictUnconstraintMotionSoftBody");
- m_softBodySolver->predictMotion(float(timeStep));
- }
-}
-
-void btSoftRigidDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
-{
- // Let the solver grab the soft bodies and if necessary optimize for it
- m_softBodySolver->optimize(getSoftBodyArray());
-
- if (!m_softBodySolver->checkInitialized())
- {
- btAssert("Solver initialization failed\n");
- }
-
- btDiscreteDynamicsWorld::internalSingleStepSimulation(timeStep);
-
- ///solve soft bodies constraints
- solveSoftBodiesConstraints(timeStep);
-
- //self collisions
- for (int i = 0; i < m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)m_softBodies[i];
- psb->defaultCollisionHandler(psb);
- }
-
- ///update soft bodies
- m_softBodySolver->updateSoftBodies();
-
- // End solver-wise simulation step
- // ///////////////////////////////
-}
-
-void btSoftRigidDynamicsWorld::solveSoftBodiesConstraints(btScalar timeStep)
-{
- BT_PROFILE("solveSoftConstraints");
-
- if (m_softBodies.size())
- {
- btSoftBody::solveClusters(m_softBodies);
- }
-
- // Solve constraints solver-wise
- m_softBodySolver->solveConstraints(timeStep * m_softBodySolver->getTimeScale());
-}
-
-void btSoftRigidDynamicsWorld::addSoftBody(btSoftBody* body, int collisionFilterGroup, int collisionFilterMask)
-{
- m_softBodies.push_back(body);
-
- // Set the soft body solver that will deal with this body
- // to be the world's solver
- body->setSoftBodySolver(m_softBodySolver);
-
- btCollisionWorld::addCollisionObject(body,
- collisionFilterGroup,
- collisionFilterMask);
-}
-
-void btSoftRigidDynamicsWorld::removeSoftBody(btSoftBody* body)
-{
- m_softBodies.remove(body);
-
- btCollisionWorld::removeCollisionObject(body);
-}
-
-void btSoftRigidDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
-{
- btSoftBody* body = btSoftBody::upcast(collisionObject);
- if (body)
- removeSoftBody(body);
- else
- btDiscreteDynamicsWorld::removeCollisionObject(collisionObject);
-}
-
-void btSoftRigidDynamicsWorld::debugDrawWorld()
-{
- btDiscreteDynamicsWorld::debugDrawWorld();
-
- if (getDebugDrawer())
- {
- int i;
- for (i = 0; i < this->m_softBodies.size(); i++)
- {
- btSoftBody* psb = (btSoftBody*)this->m_softBodies[i];
- if (getDebugDrawer() && (getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe)))
- {
- btSoftBodyHelpers::DrawFrame(psb, m_debugDrawer);
- btSoftBodyHelpers::Draw(psb, m_debugDrawer, m_drawFlags);
- }
-
- if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
- {
- if (m_drawNodeTree) btSoftBodyHelpers::DrawNodeTree(psb, m_debugDrawer);
- if (m_drawFaceTree) btSoftBodyHelpers::DrawFaceTree(psb, m_debugDrawer);
- if (m_drawClusterTree) btSoftBodyHelpers::DrawClusterTree(psb, m_debugDrawer);
- }
- }
- }
-}
-
-struct btSoftSingleRayCallback : public btBroadphaseRayCallback
-{
- btVector3 m_rayFromWorld;
- btVector3 m_rayToWorld;
- btTransform m_rayFromTrans;
- btTransform m_rayToTrans;
- btVector3 m_hitNormal;
-
- const btSoftRigidDynamicsWorld* m_world;
- btCollisionWorld::RayResultCallback& m_resultCallback;
-
- btSoftSingleRayCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, const btSoftRigidDynamicsWorld* world, btCollisionWorld::RayResultCallback& resultCallback)
- : m_rayFromWorld(rayFromWorld),
- m_rayToWorld(rayToWorld),
- m_world(world),
- m_resultCallback(resultCallback)
- {
- m_rayFromTrans.setIdentity();
- m_rayFromTrans.setOrigin(m_rayFromWorld);
- m_rayToTrans.setIdentity();
- m_rayToTrans.setOrigin(m_rayToWorld);
-
- btVector3 rayDir = (rayToWorld - rayFromWorld);
-
- rayDir.normalize();
- ///what about division by zero? --> just set rayDirection[i] to INF/1e30
- m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[0];
- m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[1];
- m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(1e30) : btScalar(1.0) / rayDir[2];
- m_signs[0] = m_rayDirectionInverse[0] < 0.0;
- m_signs[1] = m_rayDirectionInverse[1] < 0.0;
- m_signs[2] = m_rayDirectionInverse[2] < 0.0;
-
- m_lambda_max = rayDir.dot(m_rayToWorld - m_rayFromWorld);
- }
-
- virtual bool process(const btBroadphaseProxy* proxy)
- {
- ///terminate further ray tests, once the closestHitFraction reached zero
- if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
- return false;
-
- btCollisionObject* collisionObject = (btCollisionObject*)proxy->m_clientObject;
-
- //only perform raycast if filterMask matches
- if (m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle()))
- {
- //RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
- //btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
-#if 0
-#ifdef RECALCULATE_AABB
- btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
- collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
-#else
- //getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
- const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
- const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
-#endif
-#endif
- //btScalar hitLambda = m_resultCallback.m_closestHitFraction;
- //culling already done by broadphase
- //if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
- {
- m_world->rayTestSingle(m_rayFromTrans, m_rayToTrans,
- collisionObject,
- collisionObject->getCollisionShape(),
- collisionObject->getWorldTransform(),
- m_resultCallback);
- }
- }
- return true;
- }
-};
-
-void btSoftRigidDynamicsWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
-{
- BT_PROFILE("rayTest");
- /// use the broadphase to accelerate the search for objects, based on their aabb
- /// and for each object with ray-aabb overlap, perform an exact ray test
- btSoftSingleRayCallback rayCB(rayFromWorld, rayToWorld, this, resultCallback);
-
-#ifndef USE_BRUTEFORCE_RAYBROADPHASE
- m_broadphasePairCache->rayTest(rayFromWorld, rayToWorld, rayCB);
-#else
- for (int i = 0; i < this->getNumCollisionObjects(); i++)
- {
- rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
- }
-#endif //USE_BRUTEFORCE_RAYBROADPHASE
-}
-
-void btSoftRigidDynamicsWorld::rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback)
-{
- if (collisionShape->isSoftBody())
- {
- btSoftBody* softBody = btSoftBody::upcast(collisionObject);
- if (softBody)
- {
- btSoftBody::sRayCast softResult;
- if (softBody->rayTest(rayFromTrans.getOrigin(), rayToTrans.getOrigin(), softResult))
- {
- if (softResult.fraction <= resultCallback.m_closestHitFraction)
- {
- btCollisionWorld::LocalShapeInfo shapeInfo;
- shapeInfo.m_shapePart = 0;
- shapeInfo.m_triangleIndex = softResult.index;
- // get the normal
- btVector3 rayDir = rayToTrans.getOrigin() - rayFromTrans.getOrigin();
- btVector3 normal = -rayDir;
- normal.normalize();
-
- if (softResult.feature == btSoftBody::eFeature::Face)
- {
- normal = softBody->m_faces[softResult.index].m_normal;
- if (normal.dot(rayDir) > 0)
- {
- // normal always point toward origin of the ray
- normal = -normal;
- }
- }
-
- btCollisionWorld::LocalRayResult rayResult(collisionObject,
- &shapeInfo,
- normal,
- softResult.fraction);
- bool normalInWorldSpace = true;
- resultCallback.addSingleResult(rayResult, normalInWorldSpace);
- }
- }
- }
- }
- else
- {
- btCollisionWorld::rayTestSingle(rayFromTrans, rayToTrans, collisionObject, collisionShape, colObjWorldTransform, resultCallback);
- }
-}
-
-void btSoftRigidDynamicsWorld::serializeSoftBodies(btSerializer* serializer)
-{
- int i;
- //serialize all collision objects
- for (i = 0; i < m_collisionObjects.size(); i++)
- {
- btCollisionObject* colObj = m_collisionObjects[i];
- if (colObj->getInternalType() & btCollisionObject::CO_SOFT_BODY)
- {
- int len = colObj->calculateSerializeBufferSize();
- btChunk* chunk = serializer->allocate(len, 1);
- const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
- serializer->finalizeChunk(chunk, structType, BT_SOFTBODY_CODE, colObj);
- }
- }
-}
-
-void btSoftRigidDynamicsWorld::serialize(btSerializer* serializer)
-{
- serializer->startSerialization();
-
- serializeDynamicsWorldInfo(serializer);
-
- serializeSoftBodies(serializer);
-
- serializeRigidBodies(serializer);
-
- serializeCollisionObjects(serializer);
-
- serializer->finishSerialization();
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h b/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h
deleted file mode 100644
index be49c444d7..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftRigidDynamicsWorld.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H
-#define BT_SOFT_RIGID_DYNAMICS_WORLD_H
-
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
-#include "btSoftBody.h"
-
-typedef btAlignedObjectArray<btSoftBody*> btSoftBodyArray;
-
-class btSoftBodySolver;
-
-class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld
-{
- btSoftBodyArray m_softBodies;
- int m_drawFlags;
- bool m_drawNodeTree;
- bool m_drawFaceTree;
- bool m_drawClusterTree;
- btSoftBodyWorldInfo m_sbi;
- ///Solver classes that encapsulate multiple soft bodies for solving
- btSoftBodySolver* m_softBodySolver;
- bool m_ownsSolver;
-
-protected:
- virtual void predictUnconstraintMotion(btScalar timeStep);
-
- virtual void internalSingleStepSimulation(btScalar timeStep);
-
- void solveSoftBodiesConstraints(btScalar timeStep);
-
- void serializeSoftBodies(btSerializer* serializer);
-
-public:
- btSoftRigidDynamicsWorld(btDispatcher* dispatcher, btBroadphaseInterface* pairCache, btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration, btSoftBodySolver* softBodySolver = 0);
-
- virtual ~btSoftRigidDynamicsWorld();
-
- virtual void debugDrawWorld();
-
- void addSoftBody(btSoftBody* body, int collisionFilterGroup = btBroadphaseProxy::DefaultFilter, int collisionFilterMask = btBroadphaseProxy::AllFilter);
-
- void removeSoftBody(btSoftBody* body);
-
- ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btDiscreteDynamicsWorld::removeCollisionObject
- virtual void removeCollisionObject(btCollisionObject* collisionObject);
-
- int getDrawFlags() const { return (m_drawFlags); }
- void setDrawFlags(int f) { m_drawFlags = f; }
-
- btSoftBodyWorldInfo& getWorldInfo()
- {
- return m_sbi;
- }
- const btSoftBodyWorldInfo& getWorldInfo() const
- {
- return m_sbi;
- }
-
- virtual btDynamicsWorldType getWorldType() const
- {
- return BT_SOFT_RIGID_DYNAMICS_WORLD;
- }
-
- btSoftBodyArray& getSoftBodyArray()
- {
- return m_softBodies;
- }
-
- const btSoftBodyArray& getSoftBodyArray() const
- {
- return m_softBodies;
- }
-
- virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const;
-
- /// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
- /// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
- /// This allows more customization.
- static void rayTestSingle(const btTransform& rayFromTrans, const btTransform& rayToTrans,
- btCollisionObject* collisionObject,
- const btCollisionShape* collisionShape,
- const btTransform& colObjWorldTransform,
- RayResultCallback& resultCallback);
-
- virtual void serialize(btSerializer* serializer);
-};
-
-#endif //BT_SOFT_RIGID_DYNAMICS_WORLD_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
deleted file mode 100644
index 9c3e904f64..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btSoftSoftCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletSoftBody/btSoftBodySolvers.h"
-#include "btSoftBody.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObjectWrapper.h"
-
-#define USE_PERSISTENT_CONTACTS 1
-
-btSoftSoftCollisionAlgorithm::btSoftSoftCollisionAlgorithm(btPersistentManifold* /*mf*/, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* /*obj0*/, const btCollisionObjectWrapper* /*obj1*/)
- : btCollisionAlgorithm(ci)
-//m_ownManifold(false),
-//m_manifoldPtr(mf)
-{
-}
-
-btSoftSoftCollisionAlgorithm::~btSoftSoftCollisionAlgorithm()
-{
-}
-
-void btSoftSoftCollisionAlgorithm::processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
-{
- btSoftBody* soft0 = (btSoftBody*)body0Wrap->getCollisionObject();
- btSoftBody* soft1 = (btSoftBody*)body1Wrap->getCollisionObject();
- soft0->getSoftBodySolver()->processCollision(soft0, soft1);
-}
-
-btScalar btSoftSoftCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/, btCollisionObject* /*body1*/, const btDispatcherInfo& /*dispatchInfo*/, btManifoldResult* /*resultOut*/)
-{
- //not yet
- return 1.f;
-}
diff --git a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h b/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
deleted file mode 100644
index 6f871f5b85..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSoftSoftCollisionAlgorithm.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SOFT_SOFT_COLLISION_ALGORITHM_H
-#define BT_SOFT_SOFT_COLLISION_ALGORITHM_H
-
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
-#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
-
-class btPersistentManifold;
-class btSoftBody;
-
-///collision detection between two btSoftBody shapes
-class btSoftSoftCollisionAlgorithm : public btCollisionAlgorithm
-{
- bool m_ownManifold;
- btPersistentManifold* m_manifoldPtr;
-
- // btSoftBody* m_softBody0;
- // btSoftBody* m_softBody1;
-
-public:
- btSoftSoftCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
- : btCollisionAlgorithm(ci) {}
-
- virtual void processCollision(const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual btScalar calculateTimeOfImpact(btCollisionObject* body0, btCollisionObject* body1, const btDispatcherInfo& dispatchInfo, btManifoldResult* resultOut);
-
- virtual void getAllContactManifolds(btManifoldArray& manifoldArray)
- {
- if (m_manifoldPtr && m_ownManifold)
- manifoldArray.push_back(m_manifoldPtr);
- }
-
- btSoftSoftCollisionAlgorithm(btPersistentManifold* mf, const btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap);
-
- virtual ~btSoftSoftCollisionAlgorithm();
-
- struct CreateFunc : public btCollisionAlgorithmCreateFunc
- {
- virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, const btCollisionObjectWrapper* body0Wrap, const btCollisionObjectWrapper* body1Wrap)
- {
- int bbsize = sizeof(btSoftSoftCollisionAlgorithm);
- void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
- return new (ptr) btSoftSoftCollisionAlgorithm(0, ci, body0Wrap, body1Wrap);
- }
- };
-};
-
-#endif //BT_SOFT_SOFT_COLLISION_ALGORITHM_H
diff --git a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h b/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
deleted file mode 100644
index d611726bcd..0000000000
--- a/thirdparty/bullet/BulletSoftBody/btSparseSDF.h
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///btSparseSdf implementation by Nathanael Presson
-
-#ifndef BT_SPARSE_SDF_H
-#define BT_SPARSE_SDF_H
-
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
-
-// Fast Hash
-
-#if !defined(get16bits)
-#define get16bits(d) ((((unsigned int)(((const unsigned char*)(d))[1])) << 8) + (unsigned int)(((const unsigned char*)(d))[0]))
-#endif
-//
-// super hash function by Paul Hsieh
-//
-inline unsigned int HsiehHash(const char* data, int len)
-{
- unsigned int hash = len, tmp;
- len >>= 2;
-
- /* Main loop */
- for (; len > 0; len--)
- {
- hash += get16bits(data);
- tmp = (get16bits(data + 2) << 11) ^ hash;
- hash = (hash << 16) ^ tmp;
- data += 2 * sizeof(unsigned short);
- hash += hash >> 11;
- }
-
- /* Force "avalanching" of final 127 bits */
- hash ^= hash << 3;
- hash += hash >> 5;
- hash ^= hash << 4;
- hash += hash >> 17;
- hash ^= hash << 25;
- hash += hash >> 6;
-
- return hash;
-}
-
-template <const int CELLSIZE>
-struct btSparseSdf
-{
- //
- // Inner types
- //
- struct IntFrac
- {
- int b;
- int i;
- btScalar f;
- };
- struct Cell
- {
- btScalar d[CELLSIZE + 1][CELLSIZE + 1][CELLSIZE + 1];
- int c[3];
- int puid;
- unsigned hash;
- const btCollisionShape* pclient;
- Cell* next;
- };
- //
- // Fields
- //
-
- btAlignedObjectArray<Cell*> cells;
- btScalar voxelsz;
- btScalar m_defaultVoxelsz;
- int puid;
- int ncells;
- int m_clampCells;
- int nprobes;
- int nqueries;
-
- ~btSparseSdf()
- {
- Reset();
- }
- //
- // Methods
- //
-
- //
- void Initialize(int hashsize = 2383, int clampCells = 256 * 1024)
- {
- //avoid a crash due to running out of memory, so clamp the maximum number of cells allocated
- //if this limit is reached, the SDF is reset (at the cost of some performance during the reset)
- m_clampCells = clampCells;
- cells.resize(hashsize, 0);
- m_defaultVoxelsz = 0.25;
- Reset();
- }
- //
-
- void setDefaultVoxelsz(btScalar sz)
- {
- m_defaultVoxelsz = sz;
- }
-
- void Reset()
- {
- for (int i = 0, ni = cells.size(); i < ni; ++i)
- {
- Cell* pc = cells[i];
- cells[i] = 0;
- while (pc)
- {
- Cell* pn = pc->next;
- delete pc;
- pc = pn;
- }
- }
- voxelsz = m_defaultVoxelsz;
- puid = 0;
- ncells = 0;
- nprobes = 1;
- nqueries = 1;
- }
- //
- void GarbageCollect(int lifetime = 256)
- {
- const int life = puid - lifetime;
- for (int i = 0; i < cells.size(); ++i)
- {
- Cell*& root = cells[i];
- Cell* pp = 0;
- Cell* pc = root;
- while (pc)
- {
- Cell* pn = pc->next;
- if (pc->puid < life)
- {
- if (pp)
- pp->next = pn;
- else
- root = pn;
- delete pc;
- pc = pp;
- --ncells;
- }
- pp = pc;
- pc = pn;
- }
- }
- //printf("GC[%d]: %d cells, PpQ: %f\r\n",puid,ncells,nprobes/(btScalar)nqueries);
- nqueries = 1;
- nprobes = 1;
- ++puid; ///@todo: Reset puid's when int range limit is reached */
- /* else setup a priority list... */
- }
- //
- int RemoveReferences(btCollisionShape* pcs)
- {
- int refcount = 0;
- for (int i = 0; i < cells.size(); ++i)
- {
- Cell*& root = cells[i];
- Cell* pp = 0;
- Cell* pc = root;
- while (pc)
- {
- Cell* pn = pc->next;
- if (pc->pclient == pcs)
- {
- if (pp)
- pp->next = pn;
- else
- root = pn;
- delete pc;
- pc = pp;
- ++refcount;
- }
- pp = pc;
- pc = pn;
- }
- }
- return (refcount);
- }
- //
- btScalar Evaluate(const btVector3& x,
- const btCollisionShape* shape,
- btVector3& normal,
- btScalar margin)
- {
- /* Lookup cell */
- const btVector3 scx = x / voxelsz;
- const IntFrac ix = Decompose(scx.x());
- const IntFrac iy = Decompose(scx.y());
- const IntFrac iz = Decompose(scx.z());
- const unsigned h = Hash(ix.b, iy.b, iz.b, shape);
- Cell*& root = cells[static_cast<int>(h % cells.size())];
- Cell* c = root;
- ++nqueries;
- while (c)
- {
- ++nprobes;
- if ((c->hash == h) &&
- (c->c[0] == ix.b) &&
- (c->c[1] == iy.b) &&
- (c->c[2] == iz.b) &&
- (c->pclient == shape))
- {
- break;
- }
- else
- {
- // printf("c->hash/c[0][1][2]=%d,%d,%d,%d\n", c->hash, c->c[0], c->c[1],c->c[2]);
- //printf("h,ixb,iyb,izb=%d,%d,%d,%d\n", h,ix.b, iy.b, iz.b);
-
- c = c->next;
- }
- }
- if (!c)
- {
- ++nprobes;
- ++ncells;
- //int sz = sizeof(Cell);
- if (ncells > m_clampCells)
- {
- static int numResets = 0;
- numResets++;
- // printf("numResets=%d\n",numResets);
- Reset();
- }
-
- c = new Cell();
- c->next = root;
- root = c;
- c->pclient = shape;
- c->hash = h;
- c->c[0] = ix.b;
- c->c[1] = iy.b;
- c->c[2] = iz.b;
- BuildCell(*c);
- }
- c->puid = puid;
- /* Extract infos */
- const int o[] = {ix.i, iy.i, iz.i};
- const btScalar d[] = {c->d[o[0] + 0][o[1] + 0][o[2] + 0],
- c->d[o[0] + 1][o[1] + 0][o[2] + 0],
- c->d[o[0] + 1][o[1] + 1][o[2] + 0],
- c->d[o[0] + 0][o[1] + 1][o[2] + 0],
- c->d[o[0] + 0][o[1] + 0][o[2] + 1],
- c->d[o[0] + 1][o[1] + 0][o[2] + 1],
- c->d[o[0] + 1][o[1] + 1][o[2] + 1],
- c->d[o[0] + 0][o[1] + 1][o[2] + 1]};
- /* Normal */
-#if 1
- const btScalar gx[] = {d[1] - d[0], d[2] - d[3],
- d[5] - d[4], d[6] - d[7]};
- const btScalar gy[] = {d[3] - d[0], d[2] - d[1],
- d[7] - d[4], d[6] - d[5]};
- const btScalar gz[] = {d[4] - d[0], d[5] - d[1],
- d[7] - d[3], d[6] - d[2]};
- normal.setX(Lerp(Lerp(gx[0], gx[1], iy.f),
- Lerp(gx[2], gx[3], iy.f), iz.f));
- normal.setY(Lerp(Lerp(gy[0], gy[1], ix.f),
- Lerp(gy[2], gy[3], ix.f), iz.f));
- normal.setZ(Lerp(Lerp(gz[0], gz[1], ix.f),
- Lerp(gz[2], gz[3], ix.f), iy.f));
- normal.safeNormalize();
-#else
- normal = btVector3(d[1] - d[0], d[3] - d[0], d[4] - d[0]).normalized();
-#endif
- /* Distance */
- const btScalar d0 = Lerp(Lerp(d[0], d[1], ix.f),
- Lerp(d[3], d[2], ix.f), iy.f);
- const btScalar d1 = Lerp(Lerp(d[4], d[5], ix.f),
- Lerp(d[7], d[6], ix.f), iy.f);
- return (Lerp(d0, d1, iz.f) - margin);
- }
- //
- void BuildCell(Cell& c)
- {
- const btVector3 org = btVector3((btScalar)c.c[0],
- (btScalar)c.c[1],
- (btScalar)c.c[2]) *
- CELLSIZE * voxelsz;
- for (int k = 0; k <= CELLSIZE; ++k)
- {
- const btScalar z = voxelsz * k + org.z();
- for (int j = 0; j <= CELLSIZE; ++j)
- {
- const btScalar y = voxelsz * j + org.y();
- for (int i = 0; i <= CELLSIZE; ++i)
- {
- const btScalar x = voxelsz * i + org.x();
- c.d[i][j][k] = DistanceToShape(btVector3(x, y, z),
- c.pclient);
- }
- }
- }
- }
- //
- static inline btScalar DistanceToShape(const btVector3& x,
- const btCollisionShape* shape)
- {
- btTransform unit;
- unit.setIdentity();
- if (shape->isConvex())
- {
- btGjkEpaSolver2::sResults res;
- const btConvexShape* csh = static_cast<const btConvexShape*>(shape);
- return (btGjkEpaSolver2::SignedDistance(x, 0, csh, unit, res));
- }
- return (0);
- }
- //
- static inline IntFrac Decompose(btScalar x)
- {
- /* That one need a lot of improvements... */
- /* Remove test, faster floor... */
- IntFrac r;
- x /= CELLSIZE;
- const int o = x < 0 ? (int)(-x + 1) : 0;
- x += o;
- r.b = (int)x;
- const btScalar k = (x - r.b) * CELLSIZE;
- r.i = (int)k;
- r.f = k - r.i;
- r.b -= o;
- return (r);
- }
- //
- static inline btScalar Lerp(btScalar a, btScalar b, btScalar t)
- {
- return (a + (b - a) * t);
- }
-
- //
- static inline unsigned int Hash(int x, int y, int z, const btCollisionShape* shape)
- {
- struct btS
- {
- int x, y, z, w;
- void* p;
- };
-
- btS myset;
- //memset may be needed in case of additional (uninitialized) padding!
- //memset(&myset, 0, sizeof(btS));
-
- myset.x = x;
- myset.y = y;
- myset.z = z;
- myset.w = 0;
- myset.p = (void*)shape;
- const char* ptr = (const char*)&myset;
-
- unsigned int result = HsiehHash(ptr, sizeof(btS));
-
- return result;
- }
-};
-
-#endif //BT_SPARSE_SDF_H
diff --git a/thirdparty/bullet/BulletSoftBody/poly34.cpp b/thirdparty/bullet/BulletSoftBody/poly34.cpp
deleted file mode 100644
index ec7549c8e8..0000000000
--- a/thirdparty/bullet/BulletSoftBody/poly34.cpp
+++ /dev/null
@@ -1,447 +0,0 @@
-// poly34.cpp : solution of cubic and quartic equation
-// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
-// khash2 (at) gmail.com
-// Thanks to Alexandr Rakhmanin <rakhmanin (at) gmail.com>
-// public domain
-//
-#include <math.h>
-
-#include "poly34.h" // solution of cubic and quartic equation
-#define TwoPi 6.28318530717958648
-const btScalar eps = SIMD_EPSILON;
-
-//=============================================================================
-// _root3, root3 from http://prografix.narod.ru
-//=============================================================================
-static SIMD_FORCE_INLINE btScalar _root3(btScalar x)
-{
- btScalar s = 1.;
- while (x < 1.)
- {
- x *= 8.;
- s *= 0.5;
- }
- while (x > 8.)
- {
- x *= 0.125;
- s *= 2.;
- }
- btScalar r = 1.5;
- r -= 1. / 3. * (r - x / (r * r));
- r -= 1. / 3. * (r - x / (r * r));
- r -= 1. / 3. * (r - x / (r * r));
- r -= 1. / 3. * (r - x / (r * r));
- r -= 1. / 3. * (r - x / (r * r));
- r -= 1. / 3. * (r - x / (r * r));
- return r * s;
-}
-
-btScalar SIMD_FORCE_INLINE root3(btScalar x)
-{
- if (x > 0)
- return _root3(x);
- else if (x < 0)
- return -_root3(-x);
- else
- return 0.;
-}
-
-// x - array of size 2
-// return 2: 2 real roots x[0], x[1]
-// return 0: pair of complex roots: x[0]i*x[1]
-int SolveP2(btScalar* x, btScalar a, btScalar b)
-{ // solve equation x^2 + a*x + b = 0
- btScalar D = 0.25 * a * a - b;
- if (D >= 0)
- {
- D = sqrt(D);
- x[0] = -0.5 * a + D;
- x[1] = -0.5 * a - D;
- return 2;
- }
- x[0] = -0.5 * a;
- x[1] = sqrt(-D);
- return 0;
-}
-//---------------------------------------------------------------------------
-// x - array of size 3
-// In case 3 real roots: => x[0], x[1], x[2], return 3
-// 2 real roots: x[0], x[1], return 2
-// 1 real root : x[0], x[1] i*x[2], return 1
-int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c)
-{ // solve cubic equation x^3 + a*x^2 + b*x + c = 0
- btScalar a2 = a * a;
- btScalar q = (a2 - 3 * b) / 9;
- if (q < 0)
- q = eps;
- btScalar r = (a * (2 * a2 - 9 * b) + 27 * c) / 54;
- // equation x^3 + q*x + r = 0
- btScalar r2 = r * r;
- btScalar q3 = q * q * q;
- btScalar A, B;
- if (r2 <= (q3 + eps))
- { //<<-- FIXED!
- btScalar t = r / sqrt(q3);
- if (t < -1)
- t = -1;
- if (t > 1)
- t = 1;
- t = acos(t);
- a /= 3;
- q = -2 * sqrt(q);
- x[0] = q * cos(t / 3) - a;
- x[1] = q * cos((t + TwoPi) / 3) - a;
- x[2] = q * cos((t - TwoPi) / 3) - a;
- return (3);
- }
- else
- {
- //A =-pow(fabs(r)+sqrt(r2-q3),1./3);
- A = -root3(fabs(r) + sqrt(r2 - q3));
- if (r < 0)
- A = -A;
- B = (A == 0 ? 0 : q / A);
-
- a /= 3;
- x[0] = (A + B) - a;
- x[1] = -0.5 * (A + B) - a;
- x[2] = 0.5 * sqrt(3.) * (A - B);
- if (fabs(x[2]) < eps)
- {
- x[2] = x[1];
- return (2);
- }
- return (1);
- }
-} // SolveP3(btScalar *x,btScalar a,btScalar b,btScalar c) {
-//---------------------------------------------------------------------------
-// a>=0!
-void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b) // returns: a+i*s = sqrt(x+i*y)
-{
- btScalar r = sqrt(x * x + y * y);
- if (y == 0)
- {
- r = sqrt(r);
- if (x >= 0)
- {
- a = r;
- b = 0;
- }
- else
- {
- a = 0;
- b = r;
- }
- }
- else
- { // y != 0
- a = sqrt(0.5 * (x + r));
- b = 0.5 * y / a;
- }
-}
-//---------------------------------------------------------------------------
-int SolveP4Bi(btScalar* x, btScalar b, btScalar d) // solve equation x^4 + b*x^2 + d = 0
-{
- btScalar D = b * b - 4 * d;
- if (D >= 0)
- {
- btScalar sD = sqrt(D);
- btScalar x1 = (-b + sD) / 2;
- btScalar x2 = (-b - sD) / 2; // x2 <= x1
- if (x2 >= 0) // 0 <= x2 <= x1, 4 real roots
- {
- btScalar sx1 = sqrt(x1);
- btScalar sx2 = sqrt(x2);
- x[0] = -sx1;
- x[1] = sx1;
- x[2] = -sx2;
- x[3] = sx2;
- return 4;
- }
- if (x1 < 0) // x2 <= x1 < 0, two pair of imaginary roots
- {
- btScalar sx1 = sqrt(-x1);
- btScalar sx2 = sqrt(-x2);
- x[0] = 0;
- x[1] = sx1;
- x[2] = 0;
- x[3] = sx2;
- return 0;
- }
- // now x2 < 0 <= x1 , two real roots and one pair of imginary root
- btScalar sx1 = sqrt(x1);
- btScalar sx2 = sqrt(-x2);
- x[0] = -sx1;
- x[1] = sx1;
- x[2] = 0;
- x[3] = sx2;
- return 2;
- }
- else
- { // if( D < 0 ), two pair of compex roots
- btScalar sD2 = 0.5 * sqrt(-D);
- CSqrt(-0.5 * b, sD2, x[0], x[1]);
- CSqrt(-0.5 * b, -sD2, x[2], x[3]);
- return 0;
- } // if( D>=0 )
-} // SolveP4Bi(btScalar *x, btScalar b, btScalar d) // solve equation x^4 + b*x^2 d
-//---------------------------------------------------------------------------
-#define SWAP(a, b) \
- { \
- t = b; \
- b = a; \
- a = t; \
- }
-static void dblSort3(btScalar& a, btScalar& b, btScalar& c) // make: a <= b <= c
-{
- btScalar t;
- if (a > b)
- SWAP(a, b); // now a<=b
- if (c < b)
- {
- SWAP(b, c); // now a<=b, b<=c
- if (a > b)
- SWAP(a, b); // now a<=b
- }
-}
-//---------------------------------------------------------------------------
-int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d) // solve equation x^4 + b*x^2 + c*x + d
-{
- //if( c==0 ) return SolveP4Bi(x,b,d); // After that, c!=0
- if (fabs(c) < 1e-14 * (fabs(b) + fabs(d)))
- return SolveP4Bi(x, b, d); // After that, c!=0
-
- int res3 = SolveP3(x, 2 * b, b * b - 4 * d, -c * c); // solve resolvent
- // by Viet theorem: x1*x2*x3=-c*c not equals to 0, so x1!=0, x2!=0, x3!=0
- if (res3 > 1) // 3 real roots,
- {
- dblSort3(x[0], x[1], x[2]); // sort roots to x[0] <= x[1] <= x[2]
- // Note: x[0]*x[1]*x[2]= c*c > 0
- if (x[0] > 0) // all roots are positive
- {
- btScalar sz1 = sqrt(x[0]);
- btScalar sz2 = sqrt(x[1]);
- btScalar sz3 = sqrt(x[2]);
- // Note: sz1*sz2*sz3= -c (and not equal to 0)
- if (c > 0)
- {
- x[0] = (-sz1 - sz2 - sz3) / 2;
- x[1] = (-sz1 + sz2 + sz3) / 2;
- x[2] = (+sz1 - sz2 + sz3) / 2;
- x[3] = (+sz1 + sz2 - sz3) / 2;
- return 4;
- }
- // now: c<0
- x[0] = (-sz1 - sz2 + sz3) / 2;
- x[1] = (-sz1 + sz2 - sz3) / 2;
- x[2] = (+sz1 - sz2 - sz3) / 2;
- x[3] = (+sz1 + sz2 + sz3) / 2;
- return 4;
- } // if( x[0] > 0) // all roots are positive
- // now x[0] <= x[1] < 0, x[2] > 0
- // two pair of comlex roots
- btScalar sz1 = sqrt(-x[0]);
- btScalar sz2 = sqrt(-x[1]);
- btScalar sz3 = sqrt(x[2]);
-
- if (c > 0) // sign = -1
- {
- x[0] = -sz3 / 2;
- x[1] = (sz1 - sz2) / 2; // x[0]i*x[1]
- x[2] = sz3 / 2;
- x[3] = (-sz1 - sz2) / 2; // x[2]i*x[3]
- return 0;
- }
- // now: c<0 , sign = +1
- x[0] = sz3 / 2;
- x[1] = (-sz1 + sz2) / 2;
- x[2] = -sz3 / 2;
- x[3] = (sz1 + sz2) / 2;
- return 0;
- } // if( res3>1 ) // 3 real roots,
- // now resoventa have 1 real and pair of compex roots
- // x[0] - real root, and x[0]>0,
- // x[1]i*x[2] - complex roots,
- // x[0] must be >=0. But one times x[0]=~ 1e-17, so:
- if (x[0] < 0)
- x[0] = 0;
- btScalar sz1 = sqrt(x[0]);
- btScalar szr, szi;
- CSqrt(x[1], x[2], szr, szi); // (szr+i*szi)^2 = x[1]+i*x[2]
- if (c > 0) // sign = -1
- {
- x[0] = -sz1 / 2 - szr; // 1st real root
- x[1] = -sz1 / 2 + szr; // 2nd real root
- x[2] = sz1 / 2;
- x[3] = szi;
- return 2;
- }
- // now: c<0 , sign = +1
- x[0] = sz1 / 2 - szr; // 1st real root
- x[1] = sz1 / 2 + szr; // 2nd real root
- x[2] = -sz1 / 2;
- x[3] = szi;
- return 2;
-} // SolveP4De(btScalar *x, btScalar b, btScalar c, btScalar d) // solve equation x^4 + b*x^2 + c*x + d
-//-----------------------------------------------------------------------------
-btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d) // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
-{
- btScalar fxs = ((4 * x + 3 * a) * x + 2 * b) * x + c; // f'(x)
- if (fxs == 0)
- return x; //return 1e99; <<-- FIXED!
- btScalar fx = (((x + a) * x + b) * x + c) * x + d; // f(x)
- return x - fx / fxs;
-}
-//-----------------------------------------------------------------------------
-// x - array of size 4
-// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
-// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
-// return 0: two pair of complex roots: x[0]i*x[1], x[2]i*x[3],
-int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d)
-{ // solve equation x^4 + a*x^3 + b*x^2 + c*x + d by Dekart-Euler method
- // move to a=0:
- btScalar d1 = d + 0.25 * a * (0.25 * b * a - 3. / 64 * a * a * a - c);
- btScalar c1 = c + 0.5 * a * (0.25 * a * a - b);
- btScalar b1 = b - 0.375 * a * a;
- int res = SolveP4De(x, b1, c1, d1);
- if (res == 4)
- {
- x[0] -= a / 4;
- x[1] -= a / 4;
- x[2] -= a / 4;
- x[3] -= a / 4;
- }
- else if (res == 2)
- {
- x[0] -= a / 4;
- x[1] -= a / 4;
- x[2] -= a / 4;
- }
- else
- {
- x[0] -= a / 4;
- x[2] -= a / 4;
- }
- // one Newton step for each real root:
- if (res > 0)
- {
- x[0] = N4Step(x[0], a, b, c, d);
- x[1] = N4Step(x[1], a, b, c, d);
- }
- if (res > 2)
- {
- x[2] = N4Step(x[2], a, b, c, d);
- x[3] = N4Step(x[3], a, b, c, d);
- }
- return res;
-}
-//-----------------------------------------------------------------------------
-#define F5(t) (((((t + a) * t + b) * t + c) * t + d) * t + e)
-//-----------------------------------------------------------------------------
-btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-{
- int cnt;
- if (fabs(e) < eps)
- return 0;
-
- btScalar brd = fabs(a); // brd - border of real roots
- if (fabs(b) > brd)
- brd = fabs(b);
- if (fabs(c) > brd)
- brd = fabs(c);
- if (fabs(d) > brd)
- brd = fabs(d);
- if (fabs(e) > brd)
- brd = fabs(e);
- brd++; // brd - border of real roots
-
- btScalar x0, f0; // less than root
- btScalar x1, f1; // greater than root
- btScalar x2, f2, f2s; // next values, f(x2), f'(x2)
- btScalar dx = 0;
-
- if (e < 0)
- {
- x0 = 0;
- x1 = brd;
- f0 = e;
- f1 = F5(x1);
- x2 = 0.01 * brd;
- } // positive root
- else
- {
- x0 = -brd;
- x1 = 0;
- f0 = F5(x0);
- f1 = e;
- x2 = -0.01 * brd;
- } // negative root
-
- if (fabs(f0) < eps)
- return x0;
- if (fabs(f1) < eps)
- return x1;
-
- // now x0<x1, f(x0)<0, f(x1)>0
- // Firstly 10 bisections
- for (cnt = 0; cnt < 10; cnt++)
- {
- x2 = (x0 + x1) / 2; // next point
- //x2 = x0 - f0*(x1 - x0) / (f1 - f0); // next point
- f2 = F5(x2); // f(x2)
- if (fabs(f2) < eps)
- return x2;
- if (f2 > 0)
- {
- x1 = x2;
- f1 = f2;
- }
- else
- {
- x0 = x2;
- f0 = f2;
- }
- }
-
- // At each step:
- // x0<x1, f(x0)<0, f(x1)>0.
- // x2 - next value
- // we hope that x0 < x2 < x1, but not necessarily
- do
- {
- if (cnt++ > 50)
- break;
- if (x2 <= x0 || x2 >= x1)
- x2 = (x0 + x1) / 2; // now x0 < x2 < x1
- f2 = F5(x2); // f(x2)
- if (fabs(f2) < eps)
- return x2;
- if (f2 > 0)
- {
- x1 = x2;
- f1 = f2;
- }
- else
- {
- x0 = x2;
- f0 = f2;
- }
- f2s = (((5 * x2 + 4 * a) * x2 + 3 * b) * x2 + 2 * c) * x2 + d; // f'(x2)
- if (fabs(f2s) < eps)
- {
- x2 = 1e99;
- continue;
- }
- dx = f2 / f2s;
- x2 -= dx;
- } while (fabs(dx) > eps);
- return x2;
-} // SolveP5_1(btScalar a,btScalar b,btScalar c,btScalar d,btScalar e) // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-//-----------------------------------------------------------------------------
-int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e) // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-{
- btScalar r = x[0] = SolveP5_1(a, b, c, d, e);
- btScalar a1 = a + r, b1 = b + r * a1, c1 = c + r * b1, d1 = d + r * c1;
- return 1 + SolveP4(x + 1, a1, b1, c1, d1);
-} // SolveP5(btScalar *x,btScalar a,btScalar b,btScalar c,btScalar d,btScalar e) // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-//-----------------------------------------------------------------------------
diff --git a/thirdparty/bullet/BulletSoftBody/poly34.h b/thirdparty/bullet/BulletSoftBody/poly34.h
deleted file mode 100644
index 35a52c5fec..0000000000
--- a/thirdparty/bullet/BulletSoftBody/poly34.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// poly34.h : solution of cubic and quartic equation
-// (c) Khashin S.I. http://math.ivanovo.ac.ru/dalgebra/Khashin/index.html
-// khash2 (at) gmail.com
-
-#ifndef POLY_34
-#define POLY_34
-#include "LinearMath/btScalar.h"
-// x - array of size 2
-// return 2: 2 real roots x[0], x[1]
-// return 0: pair of complex roots: x[0]i*x[1]
-int SolveP2(btScalar* x, btScalar a, btScalar b); // solve equation x^2 + a*x + b = 0
-
-// x - array of size 3
-// return 3: 3 real roots x[0], x[1], x[2]
-// return 1: 1 real root x[0] and pair of complex roots: x[1]i*x[2]
-int SolveP3(btScalar* x, btScalar a, btScalar b, btScalar c); // solve cubic equation x^3 + a*x^2 + b*x + c = 0
-
-// x - array of size 4
-// return 4: 4 real roots x[0], x[1], x[2], x[3], possible multiple roots
-// return 2: 2 real roots x[0], x[1] and complex x[2]i*x[3],
-// return 0: two pair of complex roots: x[0]i*x[1], x[2]i*x[3],
-int SolveP4(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d); // solve equation x^4 + a*x^3 + b*x^2 + c*x + d = 0 by Dekart-Euler method
-
-// x - array of size 5
-// return 5: 5 real roots x[0], x[1], x[2], x[3], x[4], possible multiple roots
-// return 3: 3 real roots x[0], x[1], x[2] and complex x[3]i*x[4],
-// return 1: 1 real root x[0] and two pair of complex roots: x[1]i*x[2], x[3]i*x[4],
-int SolveP5(btScalar* x, btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // solve equation x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-
-//-----------------------------------------------------------------------------
-// And some additional functions for internal use.
-// Your may remove this definitions from here
-int SolveP4Bi(btScalar* x, btScalar b, btScalar d); // solve equation x^4 + b*x^2 + d = 0
-int SolveP4De(btScalar* x, btScalar b, btScalar c, btScalar d); // solve equation x^4 + b*x^2 + c*x + d = 0
-void CSqrt(btScalar x, btScalar y, btScalar& a, btScalar& b); // returns as a+i*s, sqrt(x+i*y)
-btScalar N4Step(btScalar x, btScalar a, btScalar b, btScalar c, btScalar d); // one Newton step for x^4 + a*x^3 + b*x^2 + c*x + d
-btScalar SolveP5_1(btScalar a, btScalar b, btScalar c, btScalar d, btScalar e); // return real root of x^5 + a*x^4 + b*x^3 + c*x^2 + d*x + e = 0
-#endif
diff --git a/thirdparty/bullet/LICENSE.txt b/thirdparty/bullet/LICENSE.txt
deleted file mode 100644
index 319c84e349..0000000000
--- a/thirdparty/bullet/LICENSE.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-The files in this repository are licensed under the zlib license, except for the files under 'Extras' and examples/ThirdPartyLibs.
-
-Bullet Continuous Collision Detection and Physics Library
-http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp
deleted file mode 100644
index 5f1115c402..0000000000
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btTaskScheduler.cpp
+++ /dev/null
@@ -1,792 +0,0 @@
-
-#include "LinearMath/btMinMax.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btThreads.h"
-#include "LinearMath/btQuickprof.h"
-#include <stdio.h>
-#include <algorithm>
-
-#if BT_THREADSAFE
-
-#include "btThreadSupportInterface.h"
-
-#if defined(_WIN32)
-
-#define WIN32_LEAN_AND_MEAN
-
-#include <windows.h>
-
-#endif
-
-typedef unsigned long long btU64;
-static const int kCacheLineSize = 64;
-
-void btSpinPause()
-{
-#if defined(_WIN32)
- YieldProcessor();
-#endif
-}
-
-struct WorkerThreadStatus
-{
- enum Type
- {
- kInvalid,
- kWaitingForWork,
- kWorking,
- kSleeping,
- };
-};
-
-ATTRIBUTE_ALIGNED64(class)
-WorkerThreadDirectives
-{
- static const int kMaxThreadCount = BT_MAX_THREAD_COUNT;
- // directives for all worker threads packed into a single cacheline
- char m_threadDirs[kMaxThreadCount];
-
-public:
- enum Type
- {
- kInvalid,
- kGoToSleep, // go to sleep
- kStayAwakeButIdle, // wait for not checking job queue
- kScanForJobs, // actively scan job queue for jobs
- };
- WorkerThreadDirectives()
- {
- for (int i = 0; i < kMaxThreadCount; ++i)
- {
- m_threadDirs[i] = 0;
- }
- }
-
- Type getDirective(int threadId)
- {
- btAssert(threadId < kMaxThreadCount);
- return static_cast<Type>(m_threadDirs[threadId]);
- }
-
- void setDirectiveByRange(int threadBegin, int threadEnd, Type dir)
- {
- btAssert(threadBegin < threadEnd);
- btAssert(threadEnd <= kMaxThreadCount);
- char dirChar = static_cast<char>(dir);
- for (int i = threadBegin; i < threadEnd; ++i)
- {
- m_threadDirs[i] = dirChar;
- }
- }
-};
-
-class JobQueue;
-
-ATTRIBUTE_ALIGNED64(struct)
-ThreadLocalStorage
-{
- int m_threadId;
- WorkerThreadStatus::Type m_status;
- int m_numJobsFinished;
- btSpinMutex m_mutex;
- btScalar m_sumResult;
- WorkerThreadDirectives* m_directive;
- JobQueue* m_queue;
- btClock* m_clock;
- unsigned int m_cooldownTime;
-};
-
-struct IJob
-{
- virtual void executeJob(int threadId) = 0;
-};
-
-class ParallelForJob : public IJob
-{
- const btIParallelForBody* m_body;
- int m_begin;
- int m_end;
-
-public:
- ParallelForJob(int iBegin, int iEnd, const btIParallelForBody& body)
- {
- m_body = &body;
- m_begin = iBegin;
- m_end = iEnd;
- }
- virtual void executeJob(int threadId) BT_OVERRIDE
- {
- BT_PROFILE("executeJob");
-
- // call the functor body to do the work
- m_body->forLoop(m_begin, m_end);
- }
-};
-
-class ParallelSumJob : public IJob
-{
- const btIParallelSumBody* m_body;
- ThreadLocalStorage* m_threadLocalStoreArray;
- int m_begin;
- int m_end;
-
-public:
- ParallelSumJob(int iBegin, int iEnd, const btIParallelSumBody& body, ThreadLocalStorage* tls)
- {
- m_body = &body;
- m_threadLocalStoreArray = tls;
- m_begin = iBegin;
- m_end = iEnd;
- }
- virtual void executeJob(int threadId) BT_OVERRIDE
- {
- BT_PROFILE("executeJob");
-
- // call the functor body to do the work
- btScalar val = m_body->sumLoop(m_begin, m_end);
-#if BT_PARALLEL_SUM_DETERMINISTISM
- // by truncating bits of the result, we can make the parallelSum deterministic (at the expense of precision)
- const float TRUNC_SCALE = float(1 << 19);
- val = floor(val * TRUNC_SCALE + 0.5f) / TRUNC_SCALE; // truncate some bits
-#endif
- m_threadLocalStoreArray[threadId].m_sumResult += val;
- }
-};
-
-ATTRIBUTE_ALIGNED64(class)
-JobQueue
-{
- btThreadSupportInterface* m_threadSupport;
- btCriticalSection* m_queueLock;
- btSpinMutex m_mutex;
-
- btAlignedObjectArray<IJob*> m_jobQueue;
- char* m_jobMem;
- int m_jobMemSize;
- bool m_queueIsEmpty;
- int m_tailIndex;
- int m_headIndex;
- int m_allocSize;
- bool m_useSpinMutex;
- btAlignedObjectArray<JobQueue*> m_neighborContexts;
- char m_cachePadding[kCacheLineSize]; // prevent false sharing
-
- void freeJobMem()
- {
- if (m_jobMem)
- {
- // free old
- btAlignedFree(m_jobMem);
- m_jobMem = NULL;
- }
- }
- void resizeJobMem(int newSize)
- {
- if (newSize > m_jobMemSize)
- {
- freeJobMem();
- m_jobMem = static_cast<char*>(btAlignedAlloc(newSize, kCacheLineSize));
- m_jobMemSize = newSize;
- }
- }
-
-public:
- JobQueue()
- {
- m_jobMem = NULL;
- m_jobMemSize = 0;
- m_threadSupport = NULL;
- m_queueLock = NULL;
- m_headIndex = 0;
- m_tailIndex = 0;
- m_useSpinMutex = false;
- }
- ~JobQueue()
- {
- exit();
- }
- void exit()
- {
- freeJobMem();
- if (m_queueLock && m_threadSupport)
- {
- m_threadSupport->deleteCriticalSection(m_queueLock);
- m_queueLock = NULL;
- m_threadSupport = 0;
- }
- }
-
- void init(btThreadSupportInterface * threadSup, btAlignedObjectArray<JobQueue> * contextArray)
- {
- m_threadSupport = threadSup;
- if (threadSup)
- {
- m_queueLock = m_threadSupport->createCriticalSection();
- }
- setupJobStealing(contextArray, contextArray->size());
- }
- void setupJobStealing(btAlignedObjectArray<JobQueue> * contextArray, int numActiveContexts)
- {
- btAlignedObjectArray<JobQueue>& contexts = *contextArray;
- int selfIndex = 0;
- for (int i = 0; i < contexts.size(); ++i)
- {
- if (this == &contexts[i])
- {
- selfIndex = i;
- break;
- }
- }
- int numNeighbors = btMin(2, contexts.size() - 1);
- int neighborOffsets[] = {-1, 1, -2, 2, -3, 3};
- int numOffsets = sizeof(neighborOffsets) / sizeof(neighborOffsets[0]);
- m_neighborContexts.reserve(numNeighbors);
- m_neighborContexts.resizeNoInitialize(0);
- for (int i = 0; i < numOffsets && m_neighborContexts.size() < numNeighbors; i++)
- {
- int neighborIndex = selfIndex + neighborOffsets[i];
- if (neighborIndex >= 0 && neighborIndex < numActiveContexts)
- {
- m_neighborContexts.push_back(&contexts[neighborIndex]);
- }
- }
- }
-
- bool isQueueEmpty() const { return m_queueIsEmpty; }
- void lockQueue()
- {
- if (m_useSpinMutex)
- {
- m_mutex.lock();
- }
- else
- {
- m_queueLock->lock();
- }
- }
- void unlockQueue()
- {
- if (m_useSpinMutex)
- {
- m_mutex.unlock();
- }
- else
- {
- m_queueLock->unlock();
- }
- }
- void clearQueue(int jobCount, int jobSize)
- {
- lockQueue();
- m_headIndex = 0;
- m_tailIndex = 0;
- m_allocSize = 0;
- m_queueIsEmpty = true;
- int jobBufSize = jobSize * jobCount;
- // make sure we have enough memory allocated to store jobs
- if (jobBufSize > m_jobMemSize)
- {
- resizeJobMem(jobBufSize);
- }
- // make sure job queue is big enough
- if (jobCount > m_jobQueue.capacity())
- {
- m_jobQueue.reserve(jobCount);
- }
- unlockQueue();
- m_jobQueue.resizeNoInitialize(0);
- }
- void* allocJobMem(int jobSize)
- {
- btAssert(m_jobMemSize >= (m_allocSize + jobSize));
- void* jobMem = &m_jobMem[m_allocSize];
- m_allocSize += jobSize;
- return jobMem;
- }
- void submitJob(IJob * job)
- {
- btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
- m_jobQueue.push_back(job);
- lockQueue();
- m_tailIndex++;
- m_queueIsEmpty = false;
- unlockQueue();
- }
- IJob* consumeJobFromOwnQueue()
- {
- if (m_queueIsEmpty)
- {
- // lock free path. even if this is taken erroneously it isn't harmful
- return NULL;
- }
- IJob* job = NULL;
- lockQueue();
- if (!m_queueIsEmpty)
- {
- job = m_jobQueue[m_headIndex++];
- btAssert(reinterpret_cast<char*>(job) >= &m_jobMem[0] && reinterpret_cast<char*>(job) < &m_jobMem[0] + m_allocSize);
- if (m_headIndex == m_tailIndex)
- {
- m_queueIsEmpty = true;
- }
- }
- unlockQueue();
- return job;
- }
- IJob* consumeJob()
- {
- if (IJob* job = consumeJobFromOwnQueue())
- {
- return job;
- }
- // own queue is empty, try to steal from neighbor
- for (int i = 0; i < m_neighborContexts.size(); ++i)
- {
- JobQueue* otherContext = m_neighborContexts[i];
- if (IJob* job = otherContext->consumeJobFromOwnQueue())
- {
- return job;
- }
- }
- return NULL;
- }
-};
-
-static void WorkerThreadFunc(void* userPtr)
-{
- BT_PROFILE("WorkerThreadFunc");
- ThreadLocalStorage* localStorage = (ThreadLocalStorage*)userPtr;
- JobQueue* jobQueue = localStorage->m_queue;
-
- bool shouldSleep = false;
- int threadId = localStorage->m_threadId;
- while (!shouldSleep)
- {
- // do work
- localStorage->m_mutex.lock();
- while (IJob* job = jobQueue->consumeJob())
- {
- localStorage->m_status = WorkerThreadStatus::kWorking;
- job->executeJob(threadId);
- localStorage->m_numJobsFinished++;
- }
- localStorage->m_status = WorkerThreadStatus::kWaitingForWork;
- localStorage->m_mutex.unlock();
- btU64 clockStart = localStorage->m_clock->getTimeMicroseconds();
- // while queue is empty,
- while (jobQueue->isQueueEmpty())
- {
- // todo: spin wait a bit to avoid hammering the empty queue
- btSpinPause();
- if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kGoToSleep)
- {
- shouldSleep = true;
- break;
- }
- // if jobs are incoming,
- if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs)
- {
- clockStart = localStorage->m_clock->getTimeMicroseconds(); // reset clock
- }
- else
- {
- for (int i = 0; i < 50; ++i)
- {
- btSpinPause();
- btSpinPause();
- btSpinPause();
- btSpinPause();
- if (localStorage->m_directive->getDirective(threadId) == WorkerThreadDirectives::kScanForJobs || !jobQueue->isQueueEmpty())
- {
- break;
- }
- }
- // if no jobs incoming and queue has been empty for the cooldown time, sleep
- btU64 timeElapsed = localStorage->m_clock->getTimeMicroseconds() - clockStart;
- if (timeElapsed > localStorage->m_cooldownTime)
- {
- shouldSleep = true;
- break;
- }
- }
- }
- }
- {
- BT_PROFILE("sleep");
- // go sleep
- localStorage->m_mutex.lock();
- localStorage->m_status = WorkerThreadStatus::kSleeping;
- localStorage->m_mutex.unlock();
- }
-}
-
-class btTaskSchedulerDefault : public btITaskScheduler
-{
- btThreadSupportInterface* m_threadSupport;
- WorkerThreadDirectives* m_workerDirective;
- btAlignedObjectArray<JobQueue> m_jobQueues;
- btAlignedObjectArray<JobQueue*> m_perThreadJobQueues;
- btAlignedObjectArray<ThreadLocalStorage> m_threadLocalStorage;
- btSpinMutex m_antiNestingLock; // prevent nested parallel-for
- btClock m_clock;
- int m_numThreads;
- int m_numWorkerThreads;
- int m_numActiveJobQueues;
- int m_maxNumThreads;
- int m_numJobs;
- static const int kFirstWorkerThreadId = 1;
-
-public:
- btTaskSchedulerDefault() : btITaskScheduler("ThreadSupport")
- {
- m_threadSupport = NULL;
- m_workerDirective = NULL;
- }
-
- virtual ~btTaskSchedulerDefault()
- {
- waitForWorkersToSleep();
-
- for (int i = 0; i < m_jobQueues.size(); ++i)
- {
- m_jobQueues[i].exit();
- }
-
- if (m_threadSupport)
- {
- delete m_threadSupport;
- m_threadSupport = NULL;
- }
- if (m_workerDirective)
- {
- btAlignedFree(m_workerDirective);
- m_workerDirective = NULL;
- }
- }
-
- void init()
- {
- btThreadSupportInterface::ConstructionInfo constructionInfo("TaskScheduler", WorkerThreadFunc);
- m_threadSupport = btThreadSupportInterface::create(constructionInfo);
- m_workerDirective = static_cast<WorkerThreadDirectives*>(btAlignedAlloc(sizeof(*m_workerDirective), 64));
-
- m_numWorkerThreads = m_threadSupport->getNumWorkerThreads();
- m_maxNumThreads = m_threadSupport->getNumWorkerThreads() + 1;
- m_numThreads = m_maxNumThreads;
- // ideal to have one job queue for each physical processor (except for the main thread which needs no queue)
- int numThreadsPerQueue = m_threadSupport->getLogicalToPhysicalCoreRatio();
- int numJobQueues = (numThreadsPerQueue == 1) ? (m_maxNumThreads - 1) : (m_maxNumThreads / numThreadsPerQueue);
- m_jobQueues.resize(numJobQueues);
- m_numActiveJobQueues = numJobQueues;
- for (int i = 0; i < m_jobQueues.size(); ++i)
- {
- m_jobQueues[i].init(m_threadSupport, &m_jobQueues);
- }
- m_perThreadJobQueues.resize(m_numThreads);
- for (int i = 0; i < m_numThreads; i++)
- {
- JobQueue* jq = NULL;
- // only worker threads get a job queue
- if (i > 0)
- {
- if (numThreadsPerQueue == 1)
- {
- // one queue per worker thread
- jq = &m_jobQueues[i - kFirstWorkerThreadId];
- }
- else
- {
- // 2 threads share each queue
- jq = &m_jobQueues[i / numThreadsPerQueue];
- }
- }
- m_perThreadJobQueues[i] = jq;
- }
- m_threadLocalStorage.resize(m_numThreads);
- for (int i = 0; i < m_numThreads; i++)
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- storage.m_threadId = i;
- storage.m_directive = m_workerDirective;
- storage.m_status = WorkerThreadStatus::kSleeping;
- storage.m_cooldownTime = 100; // 100 microseconds, threads go to sleep after this long if they have nothing to do
- storage.m_clock = &m_clock;
- storage.m_queue = m_perThreadJobQueues[i];
- }
- setWorkerDirectives(WorkerThreadDirectives::kGoToSleep); // no work for them yet
- setNumThreads(m_threadSupport->getCacheFriendlyNumThreads());
- }
-
- void setWorkerDirectives(WorkerThreadDirectives::Type dir)
- {
- m_workerDirective->setDirectiveByRange(kFirstWorkerThreadId, m_numThreads, dir);
- }
-
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return m_maxNumThreads;
- }
-
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
-
- virtual void setNumThreads(int numThreads) BT_OVERRIDE
- {
- m_numThreads = btMax(btMin(numThreads, int(m_maxNumThreads)), 1);
- m_numWorkerThreads = m_numThreads - 1;
- m_numActiveJobQueues = 0;
- // if there is at least 1 worker,
- if (m_numWorkerThreads > 0)
- {
- // re-setup job stealing between queues to avoid attempting to steal from an inactive job queue
- JobQueue* lastActiveContext = m_perThreadJobQueues[m_numThreads - 1];
- int iLastActiveContext = lastActiveContext - &m_jobQueues[0];
- m_numActiveJobQueues = iLastActiveContext + 1;
- for (int i = 0; i < m_jobQueues.size(); ++i)
- {
- m_jobQueues[i].setupJobStealing(&m_jobQueues, m_numActiveJobQueues);
- }
- }
- m_workerDirective->setDirectiveByRange(m_numThreads, BT_MAX_THREAD_COUNT, WorkerThreadDirectives::kGoToSleep);
- }
-
- void waitJobs()
- {
- BT_PROFILE("waitJobs");
- // have the main thread work until the job queues are empty
- int numMainThreadJobsFinished = 0;
- for (int i = 0; i < m_numActiveJobQueues; ++i)
- {
- while (IJob* job = m_jobQueues[i].consumeJob())
- {
- job->executeJob(0);
- numMainThreadJobsFinished++;
- }
- }
-
- // done with jobs for now, tell workers to rest (but not sleep)
- setWorkerDirectives(WorkerThreadDirectives::kStayAwakeButIdle);
-
- btU64 clockStart = m_clock.getTimeMicroseconds();
- // wait for workers to finish any jobs in progress
- while (true)
- {
- int numWorkerJobsFinished = 0;
- for (int iThread = kFirstWorkerThreadId; iThread < m_numThreads; ++iThread)
- {
- ThreadLocalStorage* storage = &m_threadLocalStorage[iThread];
- storage->m_mutex.lock();
- numWorkerJobsFinished += storage->m_numJobsFinished;
- storage->m_mutex.unlock();
- }
- if (numWorkerJobsFinished + numMainThreadJobsFinished == m_numJobs)
- {
- break;
- }
- btU64 timeElapsed = m_clock.getTimeMicroseconds() - clockStart;
- btAssert(timeElapsed < 1000);
- if (timeElapsed > 100000)
- {
- break;
- }
- btSpinPause();
- }
- }
-
- void wakeWorkers(int numWorkersToWake)
- {
- BT_PROFILE("wakeWorkers");
- btAssert(m_workerDirective->getDirective(1) == WorkerThreadDirectives::kScanForJobs);
- int numDesiredWorkers = btMin(numWorkersToWake, m_numWorkerThreads);
- int numActiveWorkers = 0;
- for (int iWorker = 0; iWorker < m_numWorkerThreads; ++iWorker)
- {
- // note this count of active workers is not necessarily totally reliable, because a worker thread could be
- // just about to put itself to sleep. So we may on occasion fail to wake up all the workers. It should be rare.
- ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
- if (storage.m_status != WorkerThreadStatus::kSleeping)
- {
- numActiveWorkers++;
- }
- }
- for (int iWorker = 0; iWorker < m_numWorkerThreads && numActiveWorkers < numDesiredWorkers; ++iWorker)
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[kFirstWorkerThreadId + iWorker];
- if (storage.m_status == WorkerThreadStatus::kSleeping)
- {
- m_threadSupport->runTask(iWorker, &storage);
- numActiveWorkers++;
- }
- }
- }
-
- void waitForWorkersToSleep()
- {
- BT_PROFILE("waitForWorkersToSleep");
- setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
- m_threadSupport->waitForAllTasks();
- for (int i = kFirstWorkerThreadId; i < m_numThreads; i++)
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- btAssert(storage.m_status == WorkerThreadStatus::kSleeping);
- }
- }
-
- virtual void sleepWorkerThreadsHint() BT_OVERRIDE
- {
- BT_PROFILE("sleepWorkerThreadsHint");
- // hint the task scheduler that we may not be using these threads for a little while
- setWorkerDirectives(WorkerThreadDirectives::kGoToSleep);
- }
-
- void prepareWorkerThreads()
- {
- for (int i = kFirstWorkerThreadId; i < m_numThreads; ++i)
- {
- ThreadLocalStorage& storage = m_threadLocalStorage[i];
- storage.m_mutex.lock();
- storage.m_numJobsFinished = 0;
- storage.m_mutex.unlock();
- }
- setWorkerDirectives(WorkerThreadDirectives::kScanForJobs);
- }
-
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_ThreadSupport");
- btAssert(iEnd >= iBegin);
- btAssert(grainSize >= 1);
- int iterationCount = iEnd - iBegin;
- if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
- {
- typedef ParallelForJob JobType;
- int jobCount = (iterationCount + grainSize - 1) / grainSize;
- m_numJobs = jobCount;
- btAssert(jobCount >= 2); // need more than one job for multithreading
- int jobSize = sizeof(JobType);
-
- for (int i = 0; i < m_numActiveJobQueues; ++i)
- {
- m_jobQueues[i].clearQueue(jobCount, jobSize);
- }
- // prepare worker threads for incoming work
- prepareWorkerThreads();
- // submit all of the jobs
- int iJob = 0;
- int iThread = kFirstWorkerThreadId; // first worker thread
- for (int i = iBegin; i < iEnd; i += grainSize)
- {
- btAssert(iJob < jobCount);
- int iE = btMin(i + grainSize, iEnd);
- JobQueue* jq = m_perThreadJobQueues[iThread];
- btAssert(jq);
- btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
- void* jobMem = jq->allocJobMem(jobSize);
- JobType* job = new (jobMem) ParallelForJob(i, iE, body); // placement new
- jq->submitJob(job);
- iJob++;
- iThread++;
- if (iThread >= m_numThreads)
- {
- iThread = kFirstWorkerThreadId; // first worker thread
- }
- }
- wakeWorkers(jobCount - 1);
-
- // put the main thread to work on emptying the job queue and then wait for all workers to finish
- waitJobs();
- m_antiNestingLock.unlock();
- }
- else
- {
- BT_PROFILE("parallelFor_mainThread");
- // just run on main thread
- body.forLoop(iBegin, iEnd);
- }
- }
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelSum_ThreadSupport");
- btAssert(iEnd >= iBegin);
- btAssert(grainSize >= 1);
- int iterationCount = iEnd - iBegin;
- if (iterationCount > grainSize && m_numWorkerThreads > 0 && m_antiNestingLock.tryLock())
- {
- typedef ParallelSumJob JobType;
- int jobCount = (iterationCount + grainSize - 1) / grainSize;
- m_numJobs = jobCount;
- btAssert(jobCount >= 2); // need more than one job for multithreading
- int jobSize = sizeof(JobType);
- for (int i = 0; i < m_numActiveJobQueues; ++i)
- {
- m_jobQueues[i].clearQueue(jobCount, jobSize);
- }
-
- // initialize summation
- for (int iThread = 0; iThread < m_numThreads; ++iThread)
- {
- m_threadLocalStorage[iThread].m_sumResult = btScalar(0);
- }
-
- // prepare worker threads for incoming work
- prepareWorkerThreads();
- // submit all of the jobs
- int iJob = 0;
- int iThread = kFirstWorkerThreadId; // first worker thread
- for (int i = iBegin; i < iEnd; i += grainSize)
- {
- btAssert(iJob < jobCount);
- int iE = btMin(i + grainSize, iEnd);
- JobQueue* jq = m_perThreadJobQueues[iThread];
- btAssert(jq);
- btAssert((jq - &m_jobQueues[0]) < m_numActiveJobQueues);
- void* jobMem = jq->allocJobMem(jobSize);
- JobType* job = new (jobMem) ParallelSumJob(i, iE, body, &m_threadLocalStorage[0]); // placement new
- jq->submitJob(job);
- iJob++;
- iThread++;
- if (iThread >= m_numThreads)
- {
- iThread = kFirstWorkerThreadId; // first worker thread
- }
- }
- wakeWorkers(jobCount - 1);
-
- // put the main thread to work on emptying the job queue and then wait for all workers to finish
- waitJobs();
-
- // add up all the thread sums
- btScalar sum = btScalar(0);
- for (int iThread = 0; iThread < m_numThreads; ++iThread)
- {
- sum += m_threadLocalStorage[iThread].m_sumResult;
- }
- m_antiNestingLock.unlock();
- return sum;
- }
- else
- {
- BT_PROFILE("parallelSum_mainThread");
- // just run on main thread
- return body.sumLoop(iBegin, iEnd);
- }
- }
-};
-
-btITaskScheduler* btCreateDefaultTaskScheduler()
-{
- btTaskSchedulerDefault* ts = new btTaskSchedulerDefault();
- ts->init();
- return ts;
-}
-
-#else // #if BT_THREADSAFE
-
-btITaskScheduler* btCreateDefaultTaskScheduler()
-{
- return NULL;
-}
-
-#endif // #else // #if BT_THREADSAFE
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h
deleted file mode 100644
index 1fe49335a1..0000000000
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportInterface.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_THREAD_SUPPORT_INTERFACE_H
-#define BT_THREAD_SUPPORT_INTERFACE_H
-
-class btCriticalSection
-{
-public:
- btCriticalSection() {}
- virtual ~btCriticalSection() {}
-
- virtual void lock() = 0;
- virtual void unlock() = 0;
-};
-
-class btThreadSupportInterface
-{
-public:
- virtual ~btThreadSupportInterface() {}
-
- virtual int getNumWorkerThreads() const = 0; // number of worker threads (total number of logical processors - 1)
- virtual int getCacheFriendlyNumThreads() const = 0; // the number of logical processors sharing a single L3 cache
- virtual int getLogicalToPhysicalCoreRatio() const = 0; // the number of logical processors per physical processor (usually 1 or 2)
- virtual void runTask(int threadIndex, void* userData) = 0;
- virtual void waitForAllTasks() = 0;
-
- virtual btCriticalSection* createCriticalSection() = 0;
- virtual void deleteCriticalSection(btCriticalSection* criticalSection) = 0;
-
- typedef void (*ThreadFunc)(void* userPtr);
-
- struct ConstructionInfo
- {
- ConstructionInfo(const char* uniqueName,
- ThreadFunc userThreadFunc,
- int threadStackSize = 65535)
- : m_uniqueName(uniqueName),
- m_userThreadFunc(userThreadFunc),
- m_threadStackSize(threadStackSize)
- {
- }
-
- const char* m_uniqueName;
- ThreadFunc m_userThreadFunc;
- int m_threadStackSize;
- };
-
- static btThreadSupportInterface* create(const ConstructionInfo& info);
-};
-
-#endif //BT_THREAD_SUPPORT_INTERFACE_H
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
deleted file mode 100644
index a03f6dc570..0000000000
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportPosix.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#if BT_THREADSAFE && !defined(_WIN32)
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btThreads.h"
-#include "LinearMath/btMinMax.h"
-#include "btThreadSupportInterface.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-
-#ifndef _XOPEN_SOURCE
-#define _XOPEN_SOURCE 600 //for definition of pthread_barrier_t, see http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
-#endif //_XOPEN_SOURCE
-#include <pthread.h>
-#include <semaphore.h>
-#include <unistd.h> //for sysconf
-
-///
-/// getNumHardwareThreads()
-///
-///
-/// https://stackoverflow.com/questions/150355/programmatically-find-the-number-of-cores-on-a-machine
-///
-#if __cplusplus >= 201103L
-
-#include <thread>
-
-int btGetNumHardwareThreads()
-{
- return btMax(1u, btMin(BT_MAX_THREAD_COUNT, std::thread::hardware_concurrency()));
-}
-
-#else
-
-int btGetNumHardwareThreads()
-{
- return btMax(1, btMin<int>(BT_MAX_THREAD_COUNT, sysconf(_SC_NPROCESSORS_ONLN)));
-}
-
-#endif
-
-// btThreadSupportPosix helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
-class btThreadSupportPosix : public btThreadSupportInterface
-{
-public:
- struct btThreadStatus
- {
- int m_taskId;
- int m_commandId;
- int m_status;
-
- ThreadFunc m_userThreadFunc;
- void* m_userPtr; //for taskDesc etc
-
- pthread_t thread;
- //each tread will wait until this signal to start its work
- sem_t* startSemaphore;
- btCriticalSection* m_cs;
- // this is a copy of m_mainSemaphore,
- //each tread will signal once it is finished with its work
- sem_t* m_mainSemaphore;
- unsigned long threadUsed;
- };
-
-private:
- typedef unsigned long long UINT64;
-
- btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
- // m_mainSemaphoresemaphore will signal, if and how many threads are finished with their work
- sem_t* m_mainSemaphore;
- int m_numThreads;
- UINT64 m_startedThreadsMask;
- void startThreads(const ConstructionInfo& threadInfo);
- void stopThreads();
- int waitForResponse();
- btCriticalSection* m_cs;
-public:
- btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo);
- virtual ~btThreadSupportPosix();
-
- virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
- // TODO: return the number of logical processors sharing the first L3 cache
- virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return m_numThreads + 1; }
- // TODO: detect if CPU has hyperthreading enabled
- virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return 1; }
-
- virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
- virtual void waitForAllTasks() BT_OVERRIDE;
-
- virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
- virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
-};
-
-#define checkPThreadFunction(returnValue) \
- if (0 != returnValue) \
- { \
- printf("PThread problem at line %i in file %s: %i %d\n", __LINE__, __FILE__, returnValue, errno); \
- }
-
-// The number of threads should be equal to the number of available cores
-// Todo: each worker should be linked to a single core, using SetThreadIdealProcessor.
-
-btThreadSupportPosix::btThreadSupportPosix(const ConstructionInfo& threadConstructionInfo)
-{
- m_cs = createCriticalSection();
- startThreads(threadConstructionInfo);
-}
-
-// cleanup/shutdown Libspe2
-btThreadSupportPosix::~btThreadSupportPosix()
-{
- stopThreads();
- deleteCriticalSection(m_cs);
- m_cs=0;
-}
-
-#if (defined(__APPLE__))
-#define NAMED_SEMAPHORES
-#endif
-
-static sem_t* createSem(const char* baseName)
-{
- static int semCount = 0;
-#ifdef NAMED_SEMAPHORES
- /// Named semaphore begin
- char name[32];
- snprintf(name, 32, "/%8.s-%4.d-%4.4d", baseName, getpid(), semCount++);
- sem_t* tempSem = sem_open(name, O_CREAT, 0600, 0);
-
- if (tempSem != reinterpret_cast<sem_t*>(SEM_FAILED))
- {
- // printf("Created \"%s\" Semaphore %p\n", name, tempSem);
- }
- else
- {
- //printf("Error creating Semaphore %d\n", errno);
- exit(-1);
- }
- /// Named semaphore end
-#else
- sem_t* tempSem = new sem_t;
- checkPThreadFunction(sem_init(tempSem, 0, 0));
-#endif
- return tempSem;
-}
-
-static void destroySem(sem_t* semaphore)
-{
-#ifdef NAMED_SEMAPHORES
- checkPThreadFunction(sem_close(semaphore));
-#else
- checkPThreadFunction(sem_destroy(semaphore));
- delete semaphore;
-#endif
-}
-
-static void* threadFunction(void* argument)
-{
- btThreadSupportPosix::btThreadStatus* status = (btThreadSupportPosix::btThreadStatus*)argument;
-
- while (1)
- {
- checkPThreadFunction(sem_wait(status->startSemaphore));
- void* userPtr = status->m_userPtr;
-
- if (userPtr)
- {
- btAssert(status->m_status);
- status->m_userThreadFunc(userPtr);
- status->m_cs->lock();
- status->m_status = 2;
- status->m_cs->unlock();
- checkPThreadFunction(sem_post(status->m_mainSemaphore));
- status->threadUsed++;
- }
- else
- {
- //exit Thread
- status->m_cs->lock();
- status->m_status = 3;
- status->m_cs->unlock();
- checkPThreadFunction(sem_post(status->m_mainSemaphore));
- break;
- }
- }
-
- return 0;
-}
-
-///send messages to SPUs
-void btThreadSupportPosix::runTask(int threadIndex, void* userData)
-{
- ///we should spawn an SPU task here, and in 'waitForResponse' it should wait for response of the (one of) the first tasks that finished
- btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
- btAssert(threadIndex >= 0);
- btAssert(threadIndex < m_activeThreadStatus.size());
- threadStatus.m_cs = m_cs;
- threadStatus.m_commandId = 1;
- threadStatus.m_status = 1;
- threadStatus.m_userPtr = userData;
- m_startedThreadsMask |= UINT64(1) << threadIndex;
-
- // fire event to start new task
- checkPThreadFunction(sem_post(threadStatus.startSemaphore));
-}
-
-///check for messages from SPUs
-int btThreadSupportPosix::waitForResponse()
-{
- ///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
- ///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
-
- btAssert(m_activeThreadStatus.size());
-
- // wait for any of the threads to finish
- checkPThreadFunction(sem_wait(m_mainSemaphore));
- // get at least one thread which has finished
- size_t last = -1;
-
- for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
- {
- m_cs->lock();
- bool hasFinished = (2 == m_activeThreadStatus[t].m_status);
- m_cs->unlock();
- if (hasFinished)
- {
- last = t;
- break;
- }
- }
-
- btThreadStatus& threadStatus = m_activeThreadStatus[last];
-
- btAssert(threadStatus.m_status > 1);
- threadStatus.m_status = 0;
-
- // need to find an active spu
- btAssert(last >= 0);
- m_startedThreadsMask &= ~(UINT64(1) << last);
-
- return last;
-}
-
-void btThreadSupportPosix::waitForAllTasks()
-{
- while (m_startedThreadsMask)
- {
- waitForResponse();
- }
-}
-
-void btThreadSupportPosix::startThreads(const ConstructionInfo& threadConstructionInfo)
-{
- m_numThreads = btGetNumHardwareThreads() - 1; // main thread exists already
- m_activeThreadStatus.resize(m_numThreads);
- m_startedThreadsMask = 0;
-
- m_mainSemaphore = createSem("main");
- //checkPThreadFunction(sem_wait(mainSemaphore));
-
- for (int i = 0; i < m_numThreads; i++)
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[i];
- threadStatus.startSemaphore = createSem("threadLocal");
- threadStatus.m_userPtr = 0;
- threadStatus.m_cs = m_cs;
- threadStatus.m_taskId = i;
- threadStatus.m_commandId = 0;
- threadStatus.m_status = 0;
- threadStatus.m_mainSemaphore = m_mainSemaphore;
- threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
- threadStatus.threadUsed = 0;
- checkPThreadFunction(pthread_create(&threadStatus.thread, NULL, &threadFunction, (void*)&threadStatus));
-
- }
-}
-
-///tell the task scheduler we are done with the SPU tasks
-void btThreadSupportPosix::stopThreads()
-{
- for (size_t t = 0; t < size_t(m_activeThreadStatus.size()); ++t)
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[t];
-
- threadStatus.m_userPtr = 0;
- checkPThreadFunction(sem_post(threadStatus.startSemaphore));
- checkPThreadFunction(sem_wait(m_mainSemaphore));
-
- checkPThreadFunction(pthread_join(threadStatus.thread, 0));
- destroySem(threadStatus.startSemaphore);
- }
- destroySem(m_mainSemaphore);
- m_activeThreadStatus.clear();
-}
-
-class btCriticalSectionPosix : public btCriticalSection
-{
- pthread_mutex_t m_mutex;
-
-public:
- btCriticalSectionPosix()
- {
- pthread_mutex_init(&m_mutex, NULL);
- }
- virtual ~btCriticalSectionPosix()
- {
- pthread_mutex_destroy(&m_mutex);
- }
-
- virtual void lock()
- {
- pthread_mutex_lock(&m_mutex);
- }
- virtual void unlock()
- {
- pthread_mutex_unlock(&m_mutex);
- }
-};
-
-btCriticalSection* btThreadSupportPosix::createCriticalSection()
-{
- return new btCriticalSectionPosix();
-}
-
-void btThreadSupportPosix::deleteCriticalSection(btCriticalSection* cs)
-{
- delete cs;
-}
-
-btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
-{
- return new btThreadSupportPosix(info);
-}
-
-#endif // BT_THREADSAFE && !defined( _WIN32 )
diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
deleted file mode 100644
index 5862264a67..0000000000
--- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2018 Erwin Coumans http://bulletphysics.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#if defined(_WIN32) && BT_THREADSAFE
-
-#include "LinearMath/btScalar.h"
-#include "LinearMath/btMinMax.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include "LinearMath/btThreads.h"
-#include "btThreadSupportInterface.h"
-#include <windows.h>
-#include <stdio.h>
-
-struct btProcessorInfo
-{
- int numLogicalProcessors;
- int numCores;
- int numNumaNodes;
- int numL1Cache;
- int numL2Cache;
- int numL3Cache;
- int numPhysicalPackages;
- static const int maxNumTeamMasks = 32;
- int numTeamMasks;
- UINT64 processorTeamMasks[maxNumTeamMasks];
-};
-
-UINT64 getProcessorTeamMask(const btProcessorInfo& procInfo, int procId)
-{
- UINT64 procMask = UINT64(1) << procId;
- for (int i = 0; i < procInfo.numTeamMasks; ++i)
- {
- if (procMask & procInfo.processorTeamMasks[i])
- {
- return procInfo.processorTeamMasks[i];
- }
- }
- return 0;
-}
-
-int getProcessorTeamIndex(const btProcessorInfo& procInfo, int procId)
-{
- UINT64 procMask = UINT64(1) << procId;
- for (int i = 0; i < procInfo.numTeamMasks; ++i)
- {
- if (procMask & procInfo.processorTeamMasks[i])
- {
- return i;
- }
- }
- return -1;
-}
-
-int countSetBits(ULONG64 bits)
-{
- int count = 0;
- while (bits)
- {
- if (bits & 1)
- {
- count++;
- }
- bits >>= 1;
- }
- return count;
-}
-
-typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
-
-void getProcessorInformation(btProcessorInfo* procInfo)
-{
- memset(procInfo, 0, sizeof(*procInfo));
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
- !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
- // Can't dlopen libraries on UWP.
- return;
-#else
- Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
- (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
- if (getLogicalProcInfo == NULL)
- {
- // no info
- return;
- }
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buf = NULL;
- DWORD bufSize = 0;
- while (true)
- {
- if (getLogicalProcInfo(buf, &bufSize))
- {
- break;
- }
- else
- {
- if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
- {
- if (buf)
- {
- free(buf);
- }
- buf = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(bufSize);
- }
- }
- }
-
- int len = bufSize / sizeof(*buf);
- for (int i = 0; i < len; ++i)
- {
- PSYSTEM_LOGICAL_PROCESSOR_INFORMATION info = buf + i;
- switch (info->Relationship)
- {
- case RelationNumaNode:
- procInfo->numNumaNodes++;
- break;
-
- case RelationProcessorCore:
- procInfo->numCores++;
- procInfo->numLogicalProcessors += countSetBits(info->ProcessorMask);
- break;
-
- case RelationCache:
- if (info->Cache.Level == 1)
- {
- procInfo->numL1Cache++;
- }
- else if (info->Cache.Level == 2)
- {
- procInfo->numL2Cache++;
- }
- else if (info->Cache.Level == 3)
- {
- procInfo->numL3Cache++;
- // processors that share L3 cache are considered to be on the same team
- // because they can more easily work together on the same data.
- // Large performance penalties will occur if 2 or more threads from different
- // teams attempt to frequently read and modify the same cache lines.
- //
- // On the AMD Ryzen 7 CPU for example, the 8 cores on the CPU are split into
- // 2 CCX units of 4 cores each. Each CCX has a separate L3 cache, so if both
- // CCXs are operating on the same data, many cycles will be spent keeping the
- // two caches coherent.
- if (procInfo->numTeamMasks < btProcessorInfo::maxNumTeamMasks)
- {
- procInfo->processorTeamMasks[procInfo->numTeamMasks] = info->ProcessorMask;
- procInfo->numTeamMasks++;
- }
- }
- break;
-
- case RelationProcessorPackage:
- procInfo->numPhysicalPackages++;
- break;
- }
- }
- free(buf);
-#endif
-}
-
-///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
-class btThreadSupportWin32 : public btThreadSupportInterface
-{
-public:
- struct btThreadStatus
- {
- int m_taskId;
- int m_commandId;
- int m_status;
-
- ThreadFunc m_userThreadFunc;
- void* m_userPtr; //for taskDesc etc
-
- void* m_threadHandle; //this one is calling 'Win32ThreadFunc'
-
- void* m_eventStartHandle;
- char m_eventStartHandleName[32];
-
- void* m_eventCompleteHandle;
- char m_eventCompleteHandleName[32];
- };
-
-private:
- btAlignedObjectArray<btThreadStatus> m_activeThreadStatus;
- btAlignedObjectArray<void*> m_completeHandles;
- int m_numThreads;
- DWORD_PTR m_startedThreadMask;
- btProcessorInfo m_processorInfo;
-
- void startThreads(const ConstructionInfo& threadInfo);
- void stopThreads();
- int waitForResponse();
-
-public:
- btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo);
- virtual ~btThreadSupportWin32();
-
- virtual int getNumWorkerThreads() const BT_OVERRIDE { return m_numThreads; }
- virtual int getCacheFriendlyNumThreads() const BT_OVERRIDE { return countSetBits(m_processorInfo.processorTeamMasks[0]); }
- virtual int getLogicalToPhysicalCoreRatio() const BT_OVERRIDE { return m_processorInfo.numLogicalProcessors / m_processorInfo.numCores; }
-
- virtual void runTask(int threadIndex, void* userData) BT_OVERRIDE;
- virtual void waitForAllTasks() BT_OVERRIDE;
-
- virtual btCriticalSection* createCriticalSection() BT_OVERRIDE;
- virtual void deleteCriticalSection(btCriticalSection* criticalSection) BT_OVERRIDE;
-};
-
-btThreadSupportWin32::btThreadSupportWin32(const ConstructionInfo& threadConstructionInfo)
-{
- startThreads(threadConstructionInfo);
-}
-
-btThreadSupportWin32::~btThreadSupportWin32()
-{
- stopThreads();
-}
-
-DWORD WINAPI win32threadStartFunc(LPVOID lpParam)
-{
- btThreadSupportWin32::btThreadStatus* status = (btThreadSupportWin32::btThreadStatus*)lpParam;
-
- while (1)
- {
- WaitForSingleObject(status->m_eventStartHandle, INFINITE);
- void* userPtr = status->m_userPtr;
-
- if (userPtr)
- {
- btAssert(status->m_status);
- status->m_userThreadFunc(userPtr);
- status->m_status = 2;
- SetEvent(status->m_eventCompleteHandle);
- }
- else
- {
- //exit Thread
- status->m_status = 3;
- printf("Thread with taskId %i with handle %p exiting\n", status->m_taskId, status->m_threadHandle);
- SetEvent(status->m_eventCompleteHandle);
- break;
- }
- }
- printf("Thread TERMINATED\n");
- return 0;
-}
-
-void btThreadSupportWin32::runTask(int threadIndex, void* userData)
-{
- btThreadStatus& threadStatus = m_activeThreadStatus[threadIndex];
- btAssert(threadIndex >= 0);
- btAssert(int(threadIndex) < m_activeThreadStatus.size());
-
- threadStatus.m_commandId = 1;
- threadStatus.m_status = 1;
- threadStatus.m_userPtr = userData;
- m_startedThreadMask |= DWORD_PTR(1) << threadIndex;
-
- ///fire event to start new task
- SetEvent(threadStatus.m_eventStartHandle);
-}
-
-int btThreadSupportWin32::waitForResponse()
-{
- btAssert(m_activeThreadStatus.size());
-
- int last = -1;
- DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
- btAssert(res != WAIT_FAILED);
- last = res - WAIT_OBJECT_0;
-
- btThreadStatus& threadStatus = m_activeThreadStatus[last];
- btAssert(threadStatus.m_threadHandle);
- btAssert(threadStatus.m_eventCompleteHandle);
-
- //WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
- btAssert(threadStatus.m_status > 1);
- threadStatus.m_status = 0;
-
- ///need to find an active spu
- btAssert(last >= 0);
- m_startedThreadMask &= ~(DWORD_PTR(1) << last);
-
- return last;
-}
-
-void btThreadSupportWin32::waitForAllTasks()
-{
- while (m_startedThreadMask)
- {
- waitForResponse();
- }
-}
-
-void btThreadSupportWin32::startThreads(const ConstructionInfo& threadConstructionInfo)
-{
- static int uniqueId = 0;
- uniqueId++;
- btProcessorInfo& procInfo = m_processorInfo;
- getProcessorInformation(&procInfo);
- DWORD_PTR dwProcessAffinityMask = 0;
- DWORD_PTR dwSystemAffinityMask = 0;
- if (!GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask))
- {
- dwProcessAffinityMask = 0;
- }
- ///The number of threads should be equal to the number of available cores - 1
- m_numThreads = btMin(procInfo.numLogicalProcessors, int(BT_MAX_THREAD_COUNT)) - 1; // cap to max thread count (-1 because main thread already exists)
-
- m_activeThreadStatus.resize(m_numThreads);
- m_completeHandles.resize(m_numThreads);
- m_startedThreadMask = 0;
-
- // set main thread affinity
- if (DWORD_PTR mask = dwProcessAffinityMask & getProcessorTeamMask(procInfo, 0))
- {
- SetThreadAffinityMask(GetCurrentThread(), mask);
- SetThreadIdealProcessor(GetCurrentThread(), 0);
- }
-
- for (int i = 0; i < m_numThreads; i++)
- {
- printf("starting thread %d\n", i);
-
- btThreadStatus& threadStatus = m_activeThreadStatus[i];
-
- LPSECURITY_ATTRIBUTES lpThreadAttributes = NULL;
- SIZE_T dwStackSize = threadConstructionInfo.m_threadStackSize;
- LPTHREAD_START_ROUTINE lpStartAddress = &win32threadStartFunc;
- LPVOID lpParameter = &threadStatus;
- DWORD dwCreationFlags = 0;
- LPDWORD lpThreadId = 0;
-
- threadStatus.m_userPtr = 0;
-
- sprintf(threadStatus.m_eventStartHandleName, "es%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
- threadStatus.m_eventStartHandle = CreateEventA(0, false, false, threadStatus.m_eventStartHandleName);
-
- sprintf(threadStatus.m_eventCompleteHandleName, "ec%.8s%d%d", threadConstructionInfo.m_uniqueName, uniqueId, i);
- threadStatus.m_eventCompleteHandle = CreateEventA(0, false, false, threadStatus.m_eventCompleteHandleName);
-
- m_completeHandles[i] = threadStatus.m_eventCompleteHandle;
-
- HANDLE handle = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
- //SetThreadPriority( handle, THREAD_PRIORITY_HIGHEST );
- // highest priority -- can cause erratic performance when numThreads > numCores
- // we don't want worker threads to be higher priority than the main thread or the main thread could get
- // totally shut out and unable to tell the workers to stop
- //SetThreadPriority( handle, THREAD_PRIORITY_BELOW_NORMAL );
-
- {
- int processorId = i + 1; // leave processor 0 for main thread
- DWORD_PTR teamMask = getProcessorTeamMask(procInfo, processorId);
- if (teamMask)
- {
- // bind each thread to only execute on processors of it's assigned team
- // - for single-socket Intel x86 CPUs this has no effect (only a single, shared L3 cache so there is only 1 team)
- // - for multi-socket Intel this will keep threads from migrating from one socket to another
- // - for AMD Ryzen this will keep threads from migrating from one CCX to another
- DWORD_PTR mask = teamMask & dwProcessAffinityMask;
- if (mask)
- {
- SetThreadAffinityMask(handle, mask);
- }
- }
- SetThreadIdealProcessor(handle, processorId);
- }
-
- threadStatus.m_taskId = i;
- threadStatus.m_commandId = 0;
- threadStatus.m_status = 0;
- threadStatus.m_threadHandle = handle;
- threadStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
-
- printf("started %s thread %d with threadHandle %p\n", threadConstructionInfo.m_uniqueName, i, handle);
- }
-}
-
-///tell the task scheduler we are done with the SPU tasks
-void btThreadSupportWin32::stopThreads()
-{
- for (int i = 0; i < m_activeThreadStatus.size(); i++)
- {
- btThreadStatus& threadStatus = m_activeThreadStatus[i];
- if (threadStatus.m_status > 0)
- {
- WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
- }
-
- threadStatus.m_userPtr = NULL;
- SetEvent(threadStatus.m_eventStartHandle);
- WaitForSingleObject(threadStatus.m_eventCompleteHandle, INFINITE);
-
- CloseHandle(threadStatus.m_eventCompleteHandle);
- CloseHandle(threadStatus.m_eventStartHandle);
- CloseHandle(threadStatus.m_threadHandle);
- }
-
- m_activeThreadStatus.clear();
- m_completeHandles.clear();
-}
-
-class btWin32CriticalSection : public btCriticalSection
-{
-private:
- CRITICAL_SECTION mCriticalSection;
-
-public:
- btWin32CriticalSection()
- {
- InitializeCriticalSection(&mCriticalSection);
- }
-
- ~btWin32CriticalSection()
- {
- DeleteCriticalSection(&mCriticalSection);
- }
-
- void lock()
- {
- EnterCriticalSection(&mCriticalSection);
- }
-
- void unlock()
- {
- LeaveCriticalSection(&mCriticalSection);
- }
-};
-
-btCriticalSection* btThreadSupportWin32::createCriticalSection()
-{
- unsigned char* mem = (unsigned char*)btAlignedAlloc(sizeof(btWin32CriticalSection), 16);
- btWin32CriticalSection* cs = new (mem) btWin32CriticalSection();
- return cs;
-}
-
-void btThreadSupportWin32::deleteCriticalSection(btCriticalSection* criticalSection)
-{
- criticalSection->~btCriticalSection();
- btAlignedFree(criticalSection);
-}
-
-btThreadSupportInterface* btThreadSupportInterface::create(const ConstructionInfo& info)
-{
- return new btThreadSupportWin32(info);
-}
-
-#endif //defined(_WIN32) && BT_THREADSAFE
diff --git a/thirdparty/bullet/LinearMath/btAabbUtil2.h b/thirdparty/bullet/LinearMath/btAabbUtil2.h
deleted file mode 100644
index eea49dd33f..0000000000
--- a/thirdparty/bullet/LinearMath/btAabbUtil2.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_AABB_UTIL2
-#define BT_AABB_UTIL2
-
-#include "btTransform.h"
-#include "btVector3.h"
-#include "btMinMax.h"
-
-SIMD_FORCE_INLINE void AabbExpand(btVector3& aabbMin,
- btVector3& aabbMax,
- const btVector3& expansionMin,
- const btVector3& expansionMax)
-{
- aabbMin = aabbMin + expansionMin;
- aabbMax = aabbMax + expansionMax;
-}
-
-/// conservative test for overlap between two aabbs
-SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
- const btVector3& point)
-{
- bool overlap = true;
- overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
- overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
- overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
- return overlap;
-}
-
-/// conservative test for overlap between two aabbs
-SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3& aabbMin1, const btVector3& aabbMax1,
- const btVector3& aabbMin2, const btVector3& aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
- overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
- overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
- return overlap;
-}
-
-/// conservative test for overlap between triangle and aabb
-SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3* vertices,
- const btVector3& aabbMin, const btVector3& aabbMax)
-{
- const btVector3& p1 = vertices[0];
- const btVector3& p2 = vertices[1];
- const btVector3& p3 = vertices[2];
-
- if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
- if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
-
- if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
- if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
-
- if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
- if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
- return true;
-}
-
-SIMD_FORCE_INLINE int btOutcode(const btVector3& p, const btVector3& halfExtent)
-{
- return (p.getX() < -halfExtent.getX() ? 0x01 : 0x0) |
- (p.getX() > halfExtent.getX() ? 0x08 : 0x0) |
- (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |
- (p.getY() > halfExtent.getY() ? 0x10 : 0x0) |
- (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |
- (p.getZ() > halfExtent.getZ() ? 0x20 : 0x0);
-}
-
-SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
- const btVector3& rayInvDirection,
- const unsigned int raySign[3],
- const btVector3 bounds[2],
- btScalar& tmin,
- btScalar lambda_min,
- btScalar lambda_max)
-{
- btScalar tmax, tymin, tymax, tzmin, tzmax;
- tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tmax = (bounds[1 - raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
- tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
- tymax = (bounds[1 - raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
-
- if ((tmin > tymax) || (tymin > tmax))
- return false;
-
- if (tymin > tmin)
- tmin = tymin;
-
- if (tymax < tmax)
- tmax = tymax;
-
- tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
- tzmax = (bounds[1 - raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
-
- if ((tmin > tzmax) || (tzmin > tmax))
- return false;
- if (tzmin > tmin)
- tmin = tzmin;
- if (tzmax < tmax)
- tmax = tzmax;
- return ((tmin < lambda_max) && (tmax > lambda_min));
-}
-
-SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom,
- const btVector3& rayTo,
- const btVector3& aabbMin,
- const btVector3& aabbMax,
- btScalar& param, btVector3& normal)
-{
- btVector3 aabbHalfExtent = (aabbMax - aabbMin) * btScalar(0.5);
- btVector3 aabbCenter = (aabbMax + aabbMin) * btScalar(0.5);
- btVector3 source = rayFrom - aabbCenter;
- btVector3 target = rayTo - aabbCenter;
- int sourceOutcode = btOutcode(source, aabbHalfExtent);
- int targetOutcode = btOutcode(target, aabbHalfExtent);
- if ((sourceOutcode & targetOutcode) == 0x0)
- {
- btScalar lambda_enter = btScalar(0.0);
- btScalar lambda_exit = param;
- btVector3 r = target - source;
- int i;
- btScalar normSign = 1;
- btVector3 hitNormal(0, 0, 0);
- int bit = 1;
-
- for (int j = 0; j < 2; j++)
- {
- for (i = 0; i != 3; ++i)
- {
- if (sourceOutcode & bit)
- {
- btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
- if (lambda_enter <= lambda)
- {
- lambda_enter = lambda;
- hitNormal.setValue(0, 0, 0);
- hitNormal[i] = normSign;
- }
- }
- else if (targetOutcode & bit)
- {
- btScalar lambda = (-source[i] - aabbHalfExtent[i] * normSign) / r[i];
- btSetMin(lambda_exit, lambda);
- }
- bit <<= 1;
- }
- normSign = btScalar(-1.);
- }
- if (lambda_enter <= lambda_exit)
- {
- param = lambda_enter;
- normal = hitNormal;
- return true;
- }
- }
- return false;
-}
-
-SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin, const btTransform& t, btVector3& aabbMinOut, btVector3& aabbMaxOut)
-{
- btVector3 halfExtentsWithMargin = halfExtents + btVector3(margin, margin, margin);
- btMatrix3x3 abs_b = t.getBasis().absolute();
- btVector3 center = t.getOrigin();
- btVector3 extent = halfExtentsWithMargin.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMinOut = center - extent;
- aabbMaxOut = center + extent;
-}
-
-SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin, const btVector3& localAabbMax, btScalar margin, const btTransform& trans, btVector3& aabbMinOut, btVector3& aabbMaxOut)
-{
- btAssert(localAabbMin.getX() <= localAabbMax.getX());
- btAssert(localAabbMin.getY() <= localAabbMax.getY());
- btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
- btVector3 localHalfExtents = btScalar(0.5) * (localAabbMax - localAabbMin);
- localHalfExtents += btVector3(margin, margin, margin);
-
- btVector3 localCenter = btScalar(0.5) * (localAabbMax + localAabbMin);
- btMatrix3x3 abs_b = trans.getBasis().absolute();
- btVector3 center = trans(localCenter);
- btVector3 extent = localHalfExtents.dot3(abs_b[0], abs_b[1], abs_b[2]);
- aabbMinOut = center - extent;
- aabbMaxOut = center + extent;
-}
-
-#define USE_BANCHLESS 1
-#ifdef USE_BANCHLESS
-//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
-SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
-{
- return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0]) & (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2]) & (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
- 1, 0));
-}
-#else
-SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1, const unsigned short int* aabbMax1, const unsigned short int* aabbMin2, const unsigned short int* aabbMax2)
-{
- bool overlap = true;
- overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
- overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
- overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
- return overlap;
-}
-#endif //USE_BANCHLESS
-
-#endif //BT_AABB_UTIL2
diff --git a/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp b/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp
deleted file mode 100644
index be8f8aa6d0..0000000000
--- a/thirdparty/bullet/LinearMath/btAlignedAllocator.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btAlignedAllocator.h"
-
-#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
-int gNumAlignedAllocs = 0;
-int gNumAlignedFree = 0;
-int gTotalBytesAlignedAllocs = 0; //detect memory leaks
-#endif //BT_DEBUG_MEMORY_ALLOCATIONST_DEBUG_ALLOCATIONS
-
-static void *btAllocDefault(size_t size)
-{
- return malloc(size);
-}
-
-static void btFreeDefault(void *ptr)
-{
- free(ptr);
-}
-
-static btAllocFunc *sAllocFunc = btAllocDefault;
-static btFreeFunc *sFreeFunc = btFreeDefault;
-
-#if defined(BT_HAS_ALIGNED_ALLOCATOR)
-#include <malloc.h>
-static void *btAlignedAllocDefault(size_t size, int alignment)
-{
- return _aligned_malloc(size, (size_t)alignment);
-}
-
-static void btAlignedFreeDefault(void *ptr)
-{
- _aligned_free(ptr);
-}
-#elif defined(__CELLOS_LV2__)
-#include <stdlib.h>
-
-static inline void *btAlignedAllocDefault(size_t size, int alignment)
-{
- return memalign(alignment, size);
-}
-
-static inline void btAlignedFreeDefault(void *ptr)
-{
- free(ptr);
-}
-#else
-
-static inline void *btAlignedAllocDefault(size_t size, int alignment)
-{
- void *ret;
- char *real;
- real = (char *)sAllocFunc(size + sizeof(void *) + (alignment - 1));
- if (real)
- {
- ret = btAlignPointer(real + sizeof(void *), alignment);
- *((void **)(ret)-1) = (void *)(real);
- }
- else
- {
- ret = (void *)(real);
- }
- return (ret);
-}
-
-static inline void btAlignedFreeDefault(void *ptr)
-{
- void *real;
-
- if (ptr)
- {
- real = *((void **)(ptr)-1);
- sFreeFunc(real);
- }
-}
-#endif
-
-static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
-static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
-
-void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
-{
- sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
- sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
-}
-
-void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
-{
- sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
- sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
-}
-
-#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
-
-static int allocations_id[10241024];
-static int allocations_bytes[10241024];
-static int mynumallocs = 0;
-#include <stdio.h>
-
-int btDumpMemoryLeaks()
-{
- int totalLeak = 0;
-
- for (int i = 0; i < mynumallocs; i++)
- {
- printf("Error: leaked memory of allocation #%d (%d bytes)\n", allocations_id[i], allocations_bytes[i]);
- totalLeak += allocations_bytes[i];
- }
- if (totalLeak)
- {
- printf("Error: memory leaks: %d allocations were not freed and leaked together %d bytes\n", mynumallocs, totalLeak);
- }
- return totalLeak;
-}
-//this generic allocator provides the total allocated number of bytes
-#include <stdio.h>
-
-struct btDebugPtrMagic
-{
- union {
- void **vptrptr;
- void *vptr;
- int *iptr;
- char *cptr;
- };
-};
-
-void *btAlignedAllocInternal(size_t size, int alignment, int line, const char *filename)
-{
- if (size == 0)
- {
- printf("Whaat? size==0");
- return 0;
- }
- static int allocId = 0;
-
- void *ret;
- char *real;
-
- // to find some particular memory leak, you could do something like this:
- // if (allocId==172)
- // {
- // printf("catch me!\n");
- // }
- // if (size>1024*1024)
- // {
- // printf("big alloc!%d\n", size);
- // }
-
- gTotalBytesAlignedAllocs += size;
- gNumAlignedAllocs++;
-
- int sz4prt = 4 * sizeof(void *);
-
- real = (char *)sAllocFunc(size + sz4prt + (alignment - 1));
- if (real)
- {
- ret = (void *)btAlignPointer(real + sz4prt, alignment);
- btDebugPtrMagic p;
- p.vptr = ret;
- p.cptr -= sizeof(void *);
- *p.vptrptr = (void *)real;
- p.cptr -= sizeof(void *);
- *p.iptr = size;
- p.cptr -= sizeof(void *);
- *p.iptr = allocId;
-
- allocations_id[mynumallocs] = allocId;
- allocations_bytes[mynumallocs] = size;
- mynumallocs++;
- }
- else
- {
- ret = (void *)(real); //??
- }
-
- printf("allocation %d at address %x, from %s,line %d, size %d (total allocated = %d)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs);
- allocId++;
-
- int *ptr = (int *)ret;
- *ptr = 12;
- return (ret);
-}
-
-void btAlignedFreeInternal(void *ptr, int line, const char *filename)
-{
- void *real;
-
- if (ptr)
- {
- gNumAlignedFree++;
-
- btDebugPtrMagic p;
- p.vptr = ptr;
- p.cptr -= sizeof(void *);
- real = *p.vptrptr;
- p.cptr -= sizeof(void *);
- int size = *p.iptr;
- p.cptr -= sizeof(void *);
- int allocId = *p.iptr;
-
- bool found = false;
-
- for (int i = 0; i < mynumallocs; i++)
- {
- if (allocations_id[i] == allocId)
- {
- allocations_id[i] = allocations_id[mynumallocs - 1];
- allocations_bytes[i] = allocations_bytes[mynumallocs - 1];
- mynumallocs--;
- found = true;
- break;
- }
- }
-
- gTotalBytesAlignedAllocs -= size;
-
- int diff = gNumAlignedAllocs - gNumAlignedFree;
- printf("free %d at address %x, from %s,line %d, size %d (total remain = %d in %d non-freed allocations)\n", allocId, real, filename, line, size, gTotalBytesAlignedAllocs, diff);
-
- sFreeFunc(real);
- }
- else
- {
- //printf("deleting a NULL ptr, no effect\n");
- }
-}
-
-#else //BT_DEBUG_MEMORY_ALLOCATIONS
-
-void *btAlignedAllocInternal(size_t size, int alignment)
-{
- void *ptr;
- ptr = sAlignedAllocFunc(size, alignment);
- // printf("btAlignedAllocInternal %d, %x\n",size,ptr);
- return ptr;
-}
-
-void btAlignedFreeInternal(void *ptr)
-{
- if (!ptr)
- {
- return;
- }
-
- // printf("btAlignedFreeInternal %x\n",ptr);
- sAlignedFreeFunc(ptr);
-}
-
-#endif //BT_DEBUG_MEMORY_ALLOCATIONS
diff --git a/thirdparty/bullet/LinearMath/btAlignedAllocator.h b/thirdparty/bullet/LinearMath/btAlignedAllocator.h
deleted file mode 100644
index 971f62bfb0..0000000000
--- a/thirdparty/bullet/LinearMath/btAlignedAllocator.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_ALIGNED_ALLOCATOR
-#define BT_ALIGNED_ALLOCATOR
-
-///we probably replace this with our own aligned memory allocator
-///so we replace _aligned_malloc and _aligned_free with our own
-///that is better portable and more predictable
-
-#include "btScalar.h"
-
-///BT_DEBUG_MEMORY_ALLOCATIONS preprocessor can be set in build system
-///for regression tests to detect memory leaks
-///#define BT_DEBUG_MEMORY_ALLOCATIONS 1
-#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
-
-int btDumpMemoryLeaks();
-
-#define btAlignedAlloc(a, b) \
- btAlignedAllocInternal(a, b, __LINE__, __FILE__)
-
-#define btAlignedFree(ptr) \
- btAlignedFreeInternal(ptr, __LINE__, __FILE__)
-
-void* btAlignedAllocInternal(size_t size, int alignment, int line, const char* filename);
-
-void btAlignedFreeInternal(void* ptr, int line, const char* filename);
-
-#else
-void* btAlignedAllocInternal(size_t size, int alignment);
-void btAlignedFreeInternal(void* ptr);
-
-#define btAlignedAlloc(size, alignment) btAlignedAllocInternal(size, alignment)
-#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
-
-#endif
-typedef int size_type;
-
-typedef void*(btAlignedAllocFunc)(size_t size, int alignment);
-typedef void(btAlignedFreeFunc)(void* memblock);
-typedef void*(btAllocFunc)(size_t size);
-typedef void(btFreeFunc)(void* memblock);
-
-///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
-void btAlignedAllocSetCustom(btAllocFunc* allocFunc, btFreeFunc* freeFunc);
-///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
-void btAlignedAllocSetCustomAligned(btAlignedAllocFunc* allocFunc, btAlignedFreeFunc* freeFunc);
-
-///The btAlignedAllocator is a portable class for aligned memory allocations.
-///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
-template <typename T, unsigned Alignment>
-class btAlignedAllocator
-{
- typedef btAlignedAllocator<T, Alignment> self_type;
-
-public:
- //just going down a list:
- btAlignedAllocator() {}
- /*
- btAlignedAllocator( const self_type & ) {}
- */
-
- template <typename Other>
- btAlignedAllocator(const btAlignedAllocator<Other, Alignment>&)
- {
- }
-
- typedef const T* const_pointer;
- typedef const T& const_reference;
- typedef T* pointer;
- typedef T& reference;
- typedef T value_type;
-
- pointer address(reference ref) const { return &ref; }
- const_pointer address(const_reference ref) const { return &ref; }
- pointer allocate(size_type n, const_pointer* hint = 0)
- {
- (void)hint;
- return reinterpret_cast<pointer>(btAlignedAlloc(sizeof(value_type) * n, Alignment));
- }
- void construct(pointer ptr, const value_type& value) { new (ptr) value_type(value); }
- void deallocate(pointer ptr)
- {
- btAlignedFree(reinterpret_cast<void*>(ptr));
- }
- void destroy(pointer ptr) { ptr->~value_type(); }
-
- template <typename O>
- struct rebind
- {
- typedef btAlignedAllocator<O, Alignment> other;
- };
- template <typename O>
- self_type& operator=(const btAlignedAllocator<O, Alignment>&)
- {
- return *this;
- }
-
- friend bool operator==(const self_type&, const self_type&) { return true; }
-};
-
-#endif //BT_ALIGNED_ALLOCATOR
diff --git a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h b/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
deleted file mode 100644
index b3d5d64b58..0000000000
--- a/thirdparty/bullet/LinearMath/btAlignedObjectArray.h
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_OBJECT_ARRAY__
-#define BT_OBJECT_ARRAY__
-
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
-#include "btAlignedAllocator.h"
-
-///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
-///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
-///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
-///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
-///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
-
-#define BT_USE_PLACEMENT_NEW 1
-//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
-#define BT_ALLOW_ARRAY_COPY_OPERATOR // enabling this can accidently perform deep copies of data if you are not careful
-
-#ifdef BT_USE_MEMCPY
-#include <memory.h>
-#include <string.h>
-#endif //BT_USE_MEMCPY
-
-#ifdef BT_USE_PLACEMENT_NEW
-#include <new> //for placement new
-#endif //BT_USE_PLACEMENT_NEW
-
-///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
-///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
-template <typename T>
-//template <class T>
-class btAlignedObjectArray
-{
- btAlignedAllocator<T, 16> m_allocator;
-
- int m_size;
- int m_capacity;
- T* m_data;
- //PCK: added this line
- bool m_ownsMemory;
-
-#ifdef BT_ALLOW_ARRAY_COPY_OPERATOR
-public:
- SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other)
- {
- copyFromArray(other);
- return *this;
- }
-#else //BT_ALLOW_ARRAY_COPY_OPERATOR
-private:
- SIMD_FORCE_INLINE btAlignedObjectArray<T>& operator=(const btAlignedObjectArray<T>& other);
-#endif //BT_ALLOW_ARRAY_COPY_OPERATOR
-
-protected:
- SIMD_FORCE_INLINE int allocSize(int size)
- {
- return (size ? size * 2 : 1);
- }
- SIMD_FORCE_INLINE void copy(int start, int end, T* dest) const
- {
- int i;
- for (i = start; i < end; ++i)
-#ifdef BT_USE_PLACEMENT_NEW
- new (&dest[i]) T(m_data[i]);
-#else
- dest[i] = m_data[i];
-#endif //BT_USE_PLACEMENT_NEW
- }
-
- SIMD_FORCE_INLINE void init()
- {
- //PCK: added this line
- m_ownsMemory = true;
- m_data = 0;
- m_size = 0;
- m_capacity = 0;
- }
- SIMD_FORCE_INLINE void destroy(int first, int last)
- {
- int i;
- for (i = first; i < last; i++)
- {
- m_data[i].~T();
- }
- }
-
- SIMD_FORCE_INLINE void* allocate(int size)
- {
- if (size)
- return m_allocator.allocate(size);
- return 0;
- }
-
- SIMD_FORCE_INLINE void deallocate()
- {
- if (m_data)
- {
- //PCK: enclosed the deallocation in this block
- if (m_ownsMemory)
- {
- m_allocator.deallocate(m_data);
- }
- m_data = 0;
- }
- }
-
-public:
- btAlignedObjectArray()
- {
- init();
- }
-
- ~btAlignedObjectArray()
- {
- clear();
- }
-
- ///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
- btAlignedObjectArray(const btAlignedObjectArray& otherArray)
- {
- init();
-
- int otherSize = otherArray.size();
- resize(otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
-
- /// return the number of elements in the array
- SIMD_FORCE_INLINE int size() const
- {
- return m_size;
- }
-
- SIMD_FORCE_INLINE const T& at(int n) const
- {
- btAssert(n >= 0);
- btAssert(n < size());
- return m_data[n];
- }
-
- SIMD_FORCE_INLINE T& at(int n)
- {
- btAssert(n >= 0);
- btAssert(n < size());
- return m_data[n];
- }
-
- SIMD_FORCE_INLINE const T& operator[](int n) const
- {
- btAssert(n >= 0);
- btAssert(n < size());
- return m_data[n];
- }
-
- SIMD_FORCE_INLINE T& operator[](int n)
- {
- btAssert(n >= 0);
- btAssert(n < size());
- return m_data[n];
- }
-
- ///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
- SIMD_FORCE_INLINE void clear()
- {
- destroy(0, size());
-
- deallocate();
-
- init();
- }
-
- SIMD_FORCE_INLINE void pop_back()
- {
- btAssert(m_size > 0);
- m_size--;
- m_data[m_size].~T();
- }
-
- ///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
- ///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
- SIMD_FORCE_INLINE void resizeNoInitialize(int newsize)
- {
- if (newsize > size())
- {
- reserve(newsize);
- }
- m_size = newsize;
- }
-
- SIMD_FORCE_INLINE void resize(int newsize, const T& fillData = T())
- {
- const int curSize = size();
-
- if (newsize < curSize)
- {
- for (int i = newsize; i < curSize; i++)
- {
- m_data[i].~T();
- }
- }
- else
- {
- if (newsize > curSize)
- {
- reserve(newsize);
- }
-#ifdef BT_USE_PLACEMENT_NEW
- for (int i = curSize; i < newsize; i++)
- {
- new (&m_data[i]) T(fillData);
- }
-#endif //BT_USE_PLACEMENT_NEW
- }
-
- m_size = newsize;
- }
- SIMD_FORCE_INLINE T& expandNonInitializing()
- {
- const int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
- m_size++;
-
- return m_data[sz];
- }
-
- SIMD_FORCE_INLINE T& expand(const T& fillValue = T())
- {
- const int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
- m_size++;
-#ifdef BT_USE_PLACEMENT_NEW
- new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
-#endif
-
- return m_data[sz];
- }
-
- SIMD_FORCE_INLINE void push_back(const T& _Val)
- {
- const int sz = size();
- if (sz == capacity())
- {
- reserve(allocSize(size()));
- }
-
-#ifdef BT_USE_PLACEMENT_NEW
- new (&m_data[m_size]) T(_Val);
-#else
- m_data[size()] = _Val;
-#endif //BT_USE_PLACEMENT_NEW
-
- m_size++;
- }
-
- /// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
- SIMD_FORCE_INLINE int capacity() const
- {
- return m_capacity;
- }
-
- SIMD_FORCE_INLINE void reserve(int _Count)
- { // determine new minimum length of allocated storage
- if (capacity() < _Count)
- { // not enough room, reallocate
- T* s = (T*)allocate(_Count);
-
- copy(0, size(), s);
-
- destroy(0, size());
-
- deallocate();
-
- //PCK: added this line
- m_ownsMemory = true;
-
- m_data = s;
-
- m_capacity = _Count;
- }
- }
-
- class less
- {
- public:
- bool operator()(const T& a, const T& b) const
- {
- return (a < b);
- }
- };
-
- template <typename L>
- void quickSortInternal(const L& CompareFunc, int lo, int hi)
- {
- // lo is the lower index, hi is the upper index
- // of the region of array a that is to be sorted
- int i = lo, j = hi;
- T x = m_data[(lo + hi) / 2];
-
- // partition
- do
- {
- while (CompareFunc(m_data[i], x))
- i++;
- while (CompareFunc(x, m_data[j]))
- j--;
- if (i <= j)
- {
- swap(i, j);
- i++;
- j--;
- }
- } while (i <= j);
-
- // recursion
- if (lo < j)
- quickSortInternal(CompareFunc, lo, j);
- if (i < hi)
- quickSortInternal(CompareFunc, i, hi);
- }
-
- template <typename L>
- void quickSort(const L& CompareFunc)
- {
- //don't sort 0 or 1 elements
- if (size() > 1)
- {
- quickSortInternal(CompareFunc, 0, size() - 1);
- }
- }
-
- ///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
- template <typename L>
- void downHeap(T* pArr, int k, int n, const L& CompareFunc)
- {
- /* PRE: a[k+1..N] is a heap */
- /* POST: a[k..N] is a heap */
-
- T temp = pArr[k - 1];
- /* k has child(s) */
- while (k <= n / 2)
- {
- int child = 2 * k;
-
- if ((child < n) && CompareFunc(pArr[child - 1], pArr[child]))
- {
- child++;
- }
- /* pick larger child */
- if (CompareFunc(temp, pArr[child - 1]))
- {
- /* move child up */
- pArr[k - 1] = pArr[child - 1];
- k = child;
- }
- else
- {
- break;
- }
- }
- pArr[k - 1] = temp;
- } /*downHeap*/
-
- void swap(int index0, int index1)
- {
-#ifdef BT_USE_MEMCPY
- char temp[sizeof(T)];
- memcpy(temp, &m_data[index0], sizeof(T));
- memcpy(&m_data[index0], &m_data[index1], sizeof(T));
- memcpy(&m_data[index1], temp, sizeof(T));
-#else
- T temp = m_data[index0];
- m_data[index0] = m_data[index1];
- m_data[index1] = temp;
-#endif //BT_USE_PLACEMENT_NEW
- }
-
- template <typename L>
- void heapSort(const L& CompareFunc)
- {
- /* sort a[0..N-1], N.B. 0 to N-1 */
- int k;
- int n = m_size;
- for (k = n / 2; k > 0; k--)
- {
- downHeap(m_data, k, n, CompareFunc);
- }
-
- /* a[1..N] is now a heap */
- while (n >= 1)
- {
- swap(0, n - 1); /* largest of a[0..n-1] */
-
- n = n - 1;
- /* restore a[1..i-1] heap */
- downHeap(m_data, 1, n, CompareFunc);
- }
- }
-
- ///non-recursive binary search, assumes sorted array
- int findBinarySearch(const T& key) const
- {
- int first = 0;
- int last = size() - 1;
-
- //assume sorted array
- while (first <= last)
- {
- int mid = (first + last) / 2; // compute mid point.
- if (key > m_data[mid])
- first = mid + 1; // repeat search in top half.
- else if (key < m_data[mid])
- last = mid - 1; // repeat search in bottom half.
- else
- return mid; // found it. return position /////
- }
- return size(); // failed to find key
- }
-
- int findLinearSearch(const T& key) const
- {
- int index = size();
- int i;
-
- for (i = 0; i < size(); i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- // If the key is not in the array, return -1 instead of 0,
- // since 0 also means the first element in the array.
- int findLinearSearch2(const T& key) const
- {
- int index = -1;
- int i;
-
- for (i = 0; i < size(); i++)
- {
- if (m_data[i] == key)
- {
- index = i;
- break;
- }
- }
- return index;
- }
-
- void removeAtIndex(int index)
- {
- if (index < size())
- {
- swap(index, size() - 1);
- pop_back();
- }
- }
- void remove(const T& key)
- {
- int findIndex = findLinearSearch(key);
- removeAtIndex(findIndex);
- }
-
- //PCK: whole function
- void initializeFromBuffer(void* buffer, int size, int capacity)
- {
- clear();
- m_ownsMemory = false;
- m_data = (T*)buffer;
- m_size = size;
- m_capacity = capacity;
- }
-
- void copyFromArray(const btAlignedObjectArray& otherArray)
- {
- int otherSize = otherArray.size();
- resize(otherSize);
- otherArray.copy(0, otherSize, m_data);
- }
-};
-
-#endif //BT_OBJECT_ARRAY__
diff --git a/thirdparty/bullet/LinearMath/btConvexHull.cpp b/thirdparty/bullet/LinearMath/btConvexHull.cpp
deleted file mode 100644
index e7de2a3694..0000000000
--- a/thirdparty/bullet/LinearMath/btConvexHull.cpp
+++ /dev/null
@@ -1,1120 +0,0 @@
-/*
-Stan Melax Convex Hull Computation
-Copyright (c) 2003-2006 Stan Melax http://www.melax.com/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include <string.h>
-
-#include "btConvexHull.h"
-#include "btAlignedObjectArray.h"
-#include "btMinMax.h"
-#include "btVector3.h"
-
-//----------------------------------
-
-class int3
-{
-public:
- int x, y, z;
- int3(){};
- int3(int _x, int _y, int _z)
- {
- x = _x;
- y = _y;
- z = _z;
- }
- const int &operator[](int i) const { return (&x)[i]; }
- int &operator[](int i) { return (&x)[i]; }
-};
-
-//------- btPlane ----------
-
-inline btPlane PlaneFlip(const btPlane &plane) { return btPlane(-plane.normal, -plane.dist); }
-inline int operator==(const btPlane &a, const btPlane &b) { return (a.normal == b.normal && a.dist == b.dist); }
-inline int coplanar(const btPlane &a, const btPlane &b) { return (a == b || a == PlaneFlip(b)); }
-
-//--------- Utility Functions ------
-
-btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
-btVector3 PlaneProject(const btPlane &plane, const btVector3 &point);
-
-btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2);
-btVector3 ThreePlaneIntersection(const btPlane &p0, const btPlane &p1, const btPlane &p2)
-{
- btVector3 N1 = p0.normal;
- btVector3 N2 = p1.normal;
- btVector3 N3 = p2.normal;
-
- btVector3 n2n3;
- n2n3 = N2.cross(N3);
- btVector3 n3n1;
- n3n1 = N3.cross(N1);
- btVector3 n1n2;
- n1n2 = N1.cross(N2);
-
- btScalar quotient = (N1.dot(n2n3));
-
- btAssert(btFabs(quotient) > btScalar(0.000001));
-
- quotient = btScalar(-1.) / quotient;
- n2n3 *= p0.dist;
- n3n1 *= p1.dist;
- n1n2 *= p2.dist;
- btVector3 potentialVertex = n2n3;
- potentialVertex += n3n1;
- potentialVertex += n1n2;
- potentialVertex *= quotient;
-
- btVector3 result(potentialVertex.getX(), potentialVertex.getY(), potentialVertex.getZ());
- return result;
-}
-
-btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint = NULL, btVector3 *vpoint = NULL);
-btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
-btVector3 NormalOf(const btVector3 *vert, const int n);
-
-btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
-{
- // returns the point where the line p0-p1 intersects the plane n&d
- btVector3 dif;
- dif = p1 - p0;
- btScalar dn = btDot(plane.normal, dif);
- btScalar t = -(plane.dist + btDot(plane.normal, p0)) / dn;
- return p0 + (dif * t);
-}
-
-btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
-{
- return point - plane.normal * (btDot(point, plane.normal) + plane.dist);
-}
-
-btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
-{
- // return the normal of the triangle
- // inscribed by v0, v1, and v2
- btVector3 cp = btCross(v1 - v0, v2 - v1);
- btScalar m = cp.length();
- if (m == 0) return btVector3(1, 0, 0);
- return cp * (btScalar(1.0) / m);
-}
-
-btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
-{
- btVector3 cp;
- cp = btCross(udir, vdir).normalized();
-
- btScalar distu = -btDot(cp, ustart);
- btScalar distv = -btDot(cp, vstart);
- btScalar dist = (btScalar)fabs(distu - distv);
- if (upoint)
- {
- btPlane plane;
- plane.normal = btCross(vdir, cp).normalized();
- plane.dist = -btDot(plane.normal, vstart);
- *upoint = PlaneLineIntersection(plane, ustart, ustart + udir);
- }
- if (vpoint)
- {
- btPlane plane;
- plane.normal = btCross(udir, cp).normalized();
- plane.dist = -btDot(plane.normal, ustart);
- *vpoint = PlaneLineIntersection(plane, vstart, vstart + vdir);
- }
- return dist;
-}
-
-#define COPLANAR (0)
-#define UNDER (1)
-#define OVER (2)
-#define SPLIT (OVER | UNDER)
-#define PAPERWIDTH (btScalar(0.001))
-
-btScalar planetestepsilon = PAPERWIDTH;
-
-typedef ConvexH::HalfEdge HalfEdge;
-
-ConvexH::ConvexH(int vertices_size, int edges_size, int facets_size)
-{
- vertices.resize(vertices_size);
- edges.resize(edges_size);
- facets.resize(facets_size);
-}
-
-int PlaneTest(const btPlane &p, const btVector3 &v);
-int PlaneTest(const btPlane &p, const btVector3 &v)
-{
- btScalar a = btDot(v, p.normal) + p.dist;
- int flag = (a > planetestepsilon) ? OVER : ((a < -planetestepsilon) ? UNDER : COPLANAR);
- return flag;
-}
-
-int SplitTest(ConvexH &convex, const btPlane &plane);
-int SplitTest(ConvexH &convex, const btPlane &plane)
-{
- int flag = 0;
- for (int i = 0; i < convex.vertices.size(); i++)
- {
- flag |= PlaneTest(plane, convex.vertices[i]);
- }
- return flag;
-}
-
-class VertFlag
-{
-public:
- unsigned char planetest;
- unsigned char junk;
- unsigned char undermap;
- unsigned char overmap;
-};
-class EdgeFlag
-{
-public:
- unsigned char planetest;
- unsigned char fixes;
- short undermap;
- short overmap;
-};
-class PlaneFlag
-{
-public:
- unsigned char undermap;
- unsigned char overmap;
-};
-class Coplanar
-{
-public:
- unsigned short ea;
- unsigned char v0;
- unsigned char v1;
-};
-
-template <class T>
-int maxdirfiltered(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
-{
- btAssert(count);
- int m = -1;
- for (int i = 0; i < count; i++)
- if (allow[i])
- {
- if (m == -1 || btDot(p[i], dir) > btDot(p[m], dir))
- m = i;
- }
- btAssert(m != -1);
- return m;
-}
-
-btVector3 orth(const btVector3 &v);
-btVector3 orth(const btVector3 &v)
-{
- btVector3 a = btCross(v, btVector3(0, 0, 1));
- btVector3 b = btCross(v, btVector3(0, 1, 0));
- if (a.length() > b.length())
- {
- return a.normalized();
- }
- else
- {
- return b.normalized();
- }
-}
-
-template <class T>
-int maxdirsterid(const T *p, int count, const T &dir, btAlignedObjectArray<int> &allow)
-{
- int m = -1;
- while (m == -1)
- {
- m = maxdirfiltered(p, count, dir, allow);
- if (allow[m] == 3) return m;
- T u = orth(dir);
- T v = btCross(u, dir);
- int ma = -1;
- for (btScalar x = btScalar(0.0); x <= btScalar(360.0); x += btScalar(45.0))
- {
- btScalar s = btSin(SIMD_RADS_PER_DEG * (x));
- btScalar c = btCos(SIMD_RADS_PER_DEG * (x));
- int mb = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
- if (ma == m && mb == m)
- {
- allow[m] = 3;
- return m;
- }
- if (ma != -1 && ma != mb) // Yuck - this is really ugly
- {
- int mc = ma;
- for (btScalar xx = x - btScalar(40.0); xx <= x; xx += btScalar(5.0))
- {
- btScalar s = btSin(SIMD_RADS_PER_DEG * (xx));
- btScalar c = btCos(SIMD_RADS_PER_DEG * (xx));
- int md = maxdirfiltered(p, count, dir + (u * s + v * c) * btScalar(0.025), allow);
- if (mc == m && md == m)
- {
- allow[m] = 3;
- return m;
- }
- mc = md;
- }
- }
- ma = mb;
- }
- allow[m] = 0;
- m = -1;
- }
- btAssert(0);
- return m;
-}
-
-int operator==(const int3 &a, const int3 &b);
-int operator==(const int3 &a, const int3 &b)
-{
- for (int i = 0; i < 3; i++)
- {
- if (a[i] != b[i]) return 0;
- }
- return 1;
-}
-
-int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon);
-int above(btVector3 *vertices, const int3 &t, const btVector3 &p, btScalar epsilon)
-{
- btVector3 n = TriNormal(vertices[t[0]], vertices[t[1]], vertices[t[2]]);
- return (btDot(n, p - vertices[t[0]]) > epsilon); // EPSILON???
-}
-int hasedge(const int3 &t, int a, int b);
-int hasedge(const int3 &t, int a, int b)
-{
- for (int i = 0; i < 3; i++)
- {
- int i1 = (i + 1) % 3;
- if (t[i] == a && t[i1] == b) return 1;
- }
- return 0;
-}
-int hasvert(const int3 &t, int v);
-int hasvert(const int3 &t, int v)
-{
- return (t[0] == v || t[1] == v || t[2] == v);
-}
-int shareedge(const int3 &a, const int3 &b);
-int shareedge(const int3 &a, const int3 &b)
-{
- int i;
- for (i = 0; i < 3; i++)
- {
- int i1 = (i + 1) % 3;
- if (hasedge(a, b[i1], b[i])) return 1;
- }
- return 0;
-}
-
-class btHullTriangle;
-
-class btHullTriangle : public int3
-{
-public:
- int3 n;
- int id;
- int vmax;
- btScalar rise;
- btHullTriangle(int a, int b, int c) : int3(a, b, c), n(-1, -1, -1)
- {
- vmax = -1;
- rise = btScalar(0.0);
- }
- ~btHullTriangle()
- {
- }
- int &neib(int a, int b);
-};
-
-int &btHullTriangle::neib(int a, int b)
-{
- static int er = -1;
- int i;
- for (i = 0; i < 3; i++)
- {
- int i1 = (i + 1) % 3;
- int i2 = (i + 2) % 3;
- if ((*this)[i] == a && (*this)[i1] == b) return n[i2];
- if ((*this)[i] == b && (*this)[i1] == a) return n[i2];
- }
- btAssert(0);
- return er;
-}
-void HullLibrary::b2bfix(btHullTriangle *s, btHullTriangle *t)
-{
- int i;
- for (i = 0; i < 3; i++)
- {
- int i1 = (i + 1) % 3;
- int i2 = (i + 2) % 3;
- int a = (*s)[i1];
- int b = (*s)[i2];
- btAssert(m_tris[s->neib(a, b)]->neib(b, a) == s->id);
- btAssert(m_tris[t->neib(a, b)]->neib(b, a) == t->id);
- m_tris[s->neib(a, b)]->neib(b, a) = t->neib(b, a);
- m_tris[t->neib(b, a)]->neib(a, b) = s->neib(a, b);
- }
-}
-
-void HullLibrary::removeb2b(btHullTriangle *s, btHullTriangle *t)
-{
- b2bfix(s, t);
- deAllocateTriangle(s);
-
- deAllocateTriangle(t);
-}
-
-void HullLibrary::checkit(btHullTriangle *t)
-{
- (void)t;
-
- int i;
- btAssert(m_tris[t->id] == t);
- for (i = 0; i < 3; i++)
- {
- int i1 = (i + 1) % 3;
- int i2 = (i + 2) % 3;
- int a = (*t)[i1];
- int b = (*t)[i2];
-
- // release compile fix
- (void)i1;
- (void)i2;
- (void)a;
- (void)b;
-
- btAssert(a != b);
- btAssert(m_tris[t->n[i]]->neib(b, a) == t->id);
- }
-}
-
-btHullTriangle *HullLibrary::allocateTriangle(int a, int b, int c)
-{
- void *mem = btAlignedAlloc(sizeof(btHullTriangle), 16);
- btHullTriangle *tr = new (mem) btHullTriangle(a, b, c);
- tr->id = m_tris.size();
- m_tris.push_back(tr);
-
- return tr;
-}
-
-void HullLibrary::deAllocateTriangle(btHullTriangle *tri)
-{
- btAssert(m_tris[tri->id] == tri);
- m_tris[tri->id] = NULL;
- tri->~btHullTriangle();
- btAlignedFree(tri);
-}
-
-void HullLibrary::extrude(btHullTriangle *t0, int v)
-{
- int3 t = *t0;
- int n = m_tris.size();
- btHullTriangle *ta = allocateTriangle(v, t[1], t[2]);
- ta->n = int3(t0->n[0], n + 1, n + 2);
- m_tris[t0->n[0]]->neib(t[1], t[2]) = n + 0;
- btHullTriangle *tb = allocateTriangle(v, t[2], t[0]);
- tb->n = int3(t0->n[1], n + 2, n + 0);
- m_tris[t0->n[1]]->neib(t[2], t[0]) = n + 1;
- btHullTriangle *tc = allocateTriangle(v, t[0], t[1]);
- tc->n = int3(t0->n[2], n + 0, n + 1);
- m_tris[t0->n[2]]->neib(t[0], t[1]) = n + 2;
- checkit(ta);
- checkit(tb);
- checkit(tc);
- if (hasvert(*m_tris[ta->n[0]], v)) removeb2b(ta, m_tris[ta->n[0]]);
- if (hasvert(*m_tris[tb->n[0]], v)) removeb2b(tb, m_tris[tb->n[0]]);
- if (hasvert(*m_tris[tc->n[0]], v)) removeb2b(tc, m_tris[tc->n[0]]);
- deAllocateTriangle(t0);
-}
-
-btHullTriangle *HullLibrary::extrudable(btScalar epsilon)
-{
- int i;
- btHullTriangle *t = NULL;
- for (i = 0; i < m_tris.size(); i++)
- {
- if (!t || (m_tris[i] && t->rise < m_tris[i]->rise))
- {
- t = m_tris[i];
- }
- }
- return (t->rise > epsilon) ? t : NULL;
-}
-
-int4 HullLibrary::FindSimplex(btVector3 *verts, int verts_count, btAlignedObjectArray<int> &allow)
-{
- btVector3 basis[3];
- basis[0] = btVector3(btScalar(0.01), btScalar(0.02), btScalar(1.0));
- int p0 = maxdirsterid(verts, verts_count, basis[0], allow);
- int p1 = maxdirsterid(verts, verts_count, -basis[0], allow);
- basis[0] = verts[p0] - verts[p1];
- if (p0 == p1 || basis[0] == btVector3(0, 0, 0))
- return int4(-1, -1, -1, -1);
- basis[1] = btCross(btVector3(btScalar(1), btScalar(0.02), btScalar(0)), basis[0]);
- basis[2] = btCross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)), basis[0]);
- if (basis[1].length() > basis[2].length())
- {
- basis[1].normalize();
- }
- else
- {
- basis[1] = basis[2];
- basis[1].normalize();
- }
- int p2 = maxdirsterid(verts, verts_count, basis[1], allow);
- if (p2 == p0 || p2 == p1)
- {
- p2 = maxdirsterid(verts, verts_count, -basis[1], allow);
- }
- if (p2 == p0 || p2 == p1)
- return int4(-1, -1, -1, -1);
- basis[1] = verts[p2] - verts[p0];
- basis[2] = btCross(basis[1], basis[0]).normalized();
- int p3 = maxdirsterid(verts, verts_count, basis[2], allow);
- if (p3 == p0 || p3 == p1 || p3 == p2) p3 = maxdirsterid(verts, verts_count, -basis[2], allow);
- if (p3 == p0 || p3 == p1 || p3 == p2)
- return int4(-1, -1, -1, -1);
- btAssert(!(p0 == p1 || p0 == p2 || p0 == p3 || p1 == p2 || p1 == p3 || p2 == p3));
- if (btDot(verts[p3] - verts[p0], btCross(verts[p1] - verts[p0], verts[p2] - verts[p0])) < 0)
- {
- btSwap(p2, p3);
- }
- return int4(p0, p1, p2, p3);
-}
-
-int HullLibrary::calchullgen(btVector3 *verts, int verts_count, int vlimit)
-{
- if (verts_count < 4) return 0;
- if (vlimit == 0) vlimit = 1000000000;
- int j;
- btVector3 bmin(*verts), bmax(*verts);
- btAlignedObjectArray<int> isextreme;
- isextreme.reserve(verts_count);
- btAlignedObjectArray<int> allow;
- allow.reserve(verts_count);
-
- for (j = 0; j < verts_count; j++)
- {
- allow.push_back(1);
- isextreme.push_back(0);
- bmin.setMin(verts[j]);
- bmax.setMax(verts[j]);
- }
- btScalar epsilon = (bmax - bmin).length() * btScalar(0.001);
- btAssert(epsilon != 0.0);
-
- int4 p = FindSimplex(verts, verts_count, allow);
- if (p.x == -1) return 0; // simplex failed
-
- btVector3 center = (verts[p[0]] + verts[p[1]] + verts[p[2]] + verts[p[3]]) / btScalar(4.0); // a valid interior point
- btHullTriangle *t0 = allocateTriangle(p[2], p[3], p[1]);
- t0->n = int3(2, 3, 1);
- btHullTriangle *t1 = allocateTriangle(p[3], p[2], p[0]);
- t1->n = int3(3, 2, 0);
- btHullTriangle *t2 = allocateTriangle(p[0], p[1], p[3]);
- t2->n = int3(0, 1, 3);
- btHullTriangle *t3 = allocateTriangle(p[1], p[0], p[2]);
- t3->n = int3(1, 0, 2);
- isextreme[p[0]] = isextreme[p[1]] = isextreme[p[2]] = isextreme[p[3]] = 1;
- checkit(t0);
- checkit(t1);
- checkit(t2);
- checkit(t3);
-
- for (j = 0; j < m_tris.size(); j++)
- {
- btHullTriangle *t = m_tris[j];
- btAssert(t);
- btAssert(t->vmax < 0);
- btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
- t->vmax = maxdirsterid(verts, verts_count, n, allow);
- t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
- }
- btHullTriangle *te;
- vlimit -= 4;
- while (vlimit > 0 && ((te = extrudable(epsilon)) != 0))
- {
- //int3 ti=*te;
- int v = te->vmax;
- btAssert(v != -1);
- btAssert(!isextreme[v]); // wtf we've already done this vertex
- isextreme[v] = 1;
- //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
- j = m_tris.size();
- while (j--)
- {
- if (!m_tris[j]) continue;
- int3 t = *m_tris[j];
- if (above(verts, t, verts[v], btScalar(0.01) * epsilon))
- {
- extrude(m_tris[j], v);
- }
- }
- // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
- j = m_tris.size();
- while (j--)
- {
- if (!m_tris[j]) continue;
- if (!hasvert(*m_tris[j], v)) break;
- int3 nt = *m_tris[j];
- if (above(verts, nt, center, btScalar(0.01) * epsilon) || btCross(verts[nt[1]] - verts[nt[0]], verts[nt[2]] - verts[nt[1]]).length() < epsilon * epsilon * btScalar(0.1))
- {
- btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
- btAssert(nb);
- btAssert(!hasvert(*nb, v));
- btAssert(nb->id < j);
- extrude(nb, v);
- j = m_tris.size();
- }
- }
- j = m_tris.size();
- while (j--)
- {
- btHullTriangle *t = m_tris[j];
- if (!t) continue;
- if (t->vmax >= 0) break;
- btVector3 n = TriNormal(verts[(*t)[0]], verts[(*t)[1]], verts[(*t)[2]]);
- t->vmax = maxdirsterid(verts, verts_count, n, allow);
- if (isextreme[t->vmax])
- {
- t->vmax = -1; // already done that vertex - algorithm needs to be able to terminate.
- }
- else
- {
- t->rise = btDot(n, verts[t->vmax] - verts[(*t)[0]]);
- }
- }
- vlimit--;
- }
- return 1;
-}
-
-int HullLibrary::calchull(btVector3 *verts, int verts_count, TUIntArray &tris_out, int &tris_count, int vlimit)
-{
- int rc = calchullgen(verts, verts_count, vlimit);
- if (!rc) return 0;
- btAlignedObjectArray<int> ts;
- int i;
-
- for (i = 0; i < m_tris.size(); i++)
- {
- if (m_tris[i])
- {
- for (int j = 0; j < 3; j++)
- ts.push_back((*m_tris[i])[j]);
- deAllocateTriangle(m_tris[i]);
- }
- }
- tris_count = ts.size() / 3;
- tris_out.resize(ts.size());
-
- for (i = 0; i < ts.size(); i++)
- {
- tris_out[i] = static_cast<unsigned int>(ts[i]);
- }
- m_tris.resize(0);
-
- return 1;
-}
-
-bool HullLibrary::ComputeHull(unsigned int vcount, const btVector3 *vertices, PHullResult &result, unsigned int vlimit)
-{
- int tris_count;
- int ret = calchull((btVector3 *)vertices, (int)vcount, result.m_Indices, tris_count, static_cast<int>(vlimit));
- if (!ret) return false;
- result.mIndexCount = (unsigned int)(tris_count * 3);
- result.mFaceCount = (unsigned int)tris_count;
- result.mVertices = (btVector3 *)vertices;
- result.mVcount = (unsigned int)vcount;
- return true;
-}
-
-void ReleaseHull(PHullResult &result);
-void ReleaseHull(PHullResult &result)
-{
- if (result.m_Indices.size())
- {
- result.m_Indices.clear();
- }
-
- result.mVcount = 0;
- result.mIndexCount = 0;
- result.mVertices = 0;
-}
-
-//*********************************************************************
-//*********************************************************************
-//******** HullLib header
-//*********************************************************************
-//*********************************************************************
-
-//*********************************************************************
-//*********************************************************************
-//******** HullLib implementation
-//*********************************************************************
-//*********************************************************************
-
-HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request
- HullResult &result) // contains the resulst
-{
- HullError ret = QE_FAIL;
-
- PHullResult hr;
-
- unsigned int vcount = desc.mVcount;
- if (vcount < 8) vcount = 8;
-
- btAlignedObjectArray<btVector3> vertexSource;
- vertexSource.resize(static_cast<int>(vcount));
-
- btVector3 scale;
-
- unsigned int ovcount;
-
- bool ok = CleanupVertices(desc.mVcount, desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale); // normalize point cloud, remove duplicates!
-
- if (ok)
- {
- // if ( 1 ) // scale vertices back to their original size.
- {
- for (unsigned int i = 0; i < ovcount; i++)
- {
- btVector3 &v = vertexSource[static_cast<int>(i)];
- v[0] *= scale[0];
- v[1] *= scale[1];
- v[2] *= scale[2];
- }
- }
-
- ok = ComputeHull(ovcount, &vertexSource[0], hr, desc.mMaxVertices);
-
- if (ok)
- {
- // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
- btAlignedObjectArray<btVector3> vertexScratch;
- vertexScratch.resize(static_cast<int>(hr.mVcount));
-
- BringOutYourDead(hr.mVertices, hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount);
-
- ret = QE_OK;
-
- if (desc.HasHullFlag(QF_TRIANGLES)) // if he wants the results as triangle!
- {
- result.mPolygons = false;
- result.mNumOutputVertices = ovcount;
- result.m_OutputVertices.resize(static_cast<int>(ovcount));
- result.mNumFaces = hr.mFaceCount;
- result.mNumIndices = hr.mIndexCount;
-
- result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
-
- memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
-
- if (desc.HasHullFlag(QF_REVERSE_ORDER))
- {
- const unsigned int *source = &hr.m_Indices[0];
- unsigned int *dest = &result.m_Indices[0];
-
- for (unsigned int i = 0; i < hr.mFaceCount; i++)
- {
- dest[0] = source[2];
- dest[1] = source[1];
- dest[2] = source[0];
- dest += 3;
- source += 3;
- }
- }
- else
- {
- memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int) * hr.mIndexCount);
- }
- }
- else
- {
- result.mPolygons = true;
- result.mNumOutputVertices = ovcount;
- result.m_OutputVertices.resize(static_cast<int>(ovcount));
- result.mNumFaces = hr.mFaceCount;
- result.mNumIndices = hr.mIndexCount + hr.mFaceCount;
- result.m_Indices.resize(static_cast<int>(result.mNumIndices));
- memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3) * ovcount);
-
- // if ( 1 )
- {
- const unsigned int *source = &hr.m_Indices[0];
- unsigned int *dest = &result.m_Indices[0];
- for (unsigned int i = 0; i < hr.mFaceCount; i++)
- {
- dest[0] = 3;
- if (desc.HasHullFlag(QF_REVERSE_ORDER))
- {
- dest[1] = source[2];
- dest[2] = source[1];
- dest[3] = source[0];
- }
- else
- {
- dest[1] = source[0];
- dest[2] = source[1];
- dest[3] = source[2];
- }
-
- dest += 4;
- source += 3;
- }
- }
- }
- ReleaseHull(hr);
- }
- }
-
- return ret;
-}
-
-HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
-{
- if (result.m_OutputVertices.size())
- {
- result.mNumOutputVertices = 0;
- result.m_OutputVertices.clear();
- }
- if (result.m_Indices.size())
- {
- result.mNumIndices = 0;
- result.m_Indices.clear();
- }
- return QE_OK;
-}
-
-static void addPoint(unsigned int &vcount, btVector3 *p, btScalar x, btScalar y, btScalar z)
-{
- // XXX, might be broken
- btVector3 &dest = p[vcount];
- dest[0] = x;
- dest[1] = y;
- dest[2] = z;
- vcount++;
-}
-
-btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2);
-btScalar GetDist(btScalar px, btScalar py, btScalar pz, const btScalar *p2)
-{
- btScalar dx = px - p2[0];
- btScalar dy = py - p2[1];
- btScalar dz = pz - p2[2];
-
- return dx * dx + dy * dy + dz * dz;
-}
-
-bool HullLibrary::CleanupVertices(unsigned int svcount,
- const btVector3 *svertices,
- unsigned int stride,
- unsigned int &vcount, // output number of vertices
- btVector3 *vertices, // location to store the results.
- btScalar normalepsilon,
- btVector3 &scale)
-{
- if (svcount == 0) return false;
-
- m_vertexIndexMapping.resize(0);
-
-#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
-
- vcount = 0;
-
- btScalar recip[3] = {0.f, 0.f, 0.f};
-
- if (scale)
- {
- scale[0] = 1;
- scale[1] = 1;
- scale[2] = 1;
- }
-
- btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
- btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
-
- const char *vtx = (const char *)svertices;
-
- // if ( 1 )
- {
- for (unsigned int i = 0; i < svcount; i++)
- {
- const btScalar *p = (const btScalar *)vtx;
-
- vtx += stride;
-
- for (int j = 0; j < 3; j++)
- {
- if (p[j] < bmin[j]) bmin[j] = p[j];
- if (p[j] > bmax[j]) bmax[j] = p[j];
- }
- }
- }
-
- btScalar dx = bmax[0] - bmin[0];
- btScalar dy = bmax[1] - bmin[1];
- btScalar dz = bmax[2] - bmin[2];
-
- btVector3 center;
-
- center[0] = dx * btScalar(0.5) + bmin[0];
- center[1] = dy * btScalar(0.5) + bmin[1];
- center[2] = dz * btScalar(0.5) + bmin[2];
-
- if (dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3)
- {
- btScalar len = FLT_MAX;
-
- if (dx > EPSILON && dx < len) len = dx;
- if (dy > EPSILON && dy < len) len = dy;
- if (dz > EPSILON && dz < len) len = dz;
-
- if (len == FLT_MAX)
- {
- dx = dy = dz = btScalar(0.01); // one centimeter
- }
- else
- {
- if (dx < EPSILON) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
- if (dy < EPSILON) dy = len * btScalar(0.05);
- if (dz < EPSILON) dz = len * btScalar(0.05);
- }
-
- btScalar x1 = center[0] - dx;
- btScalar x2 = center[0] + dx;
-
- btScalar y1 = center[1] - dy;
- btScalar y2 = center[1] + dy;
-
- btScalar z1 = center[2] - dz;
- btScalar z2 = center[2] + dz;
-
- addPoint(vcount, vertices, x1, y1, z1);
- addPoint(vcount, vertices, x2, y1, z1);
- addPoint(vcount, vertices, x2, y2, z1);
- addPoint(vcount, vertices, x1, y2, z1);
- addPoint(vcount, vertices, x1, y1, z2);
- addPoint(vcount, vertices, x2, y1, z2);
- addPoint(vcount, vertices, x2, y2, z2);
- addPoint(vcount, vertices, x1, y2, z2);
-
- return true; // return cube
- }
- else
- {
- if (scale)
- {
- scale[0] = dx;
- scale[1] = dy;
- scale[2] = dz;
-
- recip[0] = 1 / dx;
- recip[1] = 1 / dy;
- recip[2] = 1 / dz;
-
- center[0] *= recip[0];
- center[1] *= recip[1];
- center[2] *= recip[2];
- }
- }
-
- vtx = (const char *)svertices;
-
- for (unsigned int i = 0; i < svcount; i++)
- {
- const btVector3 *p = (const btVector3 *)vtx;
- vtx += stride;
-
- btScalar px = p->getX();
- btScalar py = p->getY();
- btScalar pz = p->getZ();
-
- if (scale)
- {
- px = px * recip[0]; // normalize
- py = py * recip[1]; // normalize
- pz = pz * recip[2]; // normalize
- }
-
- // if ( 1 )
- {
- unsigned int j;
-
- for (j = 0; j < vcount; j++)
- {
- /// XXX might be broken
- btVector3 &v = vertices[j];
-
- btScalar x = v[0];
- btScalar y = v[1];
- btScalar z = v[2];
-
- btScalar dx = btFabs(x - px);
- btScalar dy = btFabs(y - py);
- btScalar dz = btFabs(z - pz);
-
- if (dx < normalepsilon && dy < normalepsilon && dz < normalepsilon)
- {
- // ok, it is close enough to the old one
- // now let us see if it is further from the center of the point cloud than the one we already recorded.
- // in which case we keep this one instead.
-
- btScalar dist1 = GetDist(px, py, pz, center);
- btScalar dist2 = GetDist(v[0], v[1], v[2], center);
-
- if (dist1 > dist2)
- {
- v[0] = px;
- v[1] = py;
- v[2] = pz;
- }
-
- break;
- }
- }
-
- if (j == vcount)
- {
- btVector3 &dest = vertices[vcount];
- dest[0] = px;
- dest[1] = py;
- dest[2] = pz;
- vcount++;
- }
- m_vertexIndexMapping.push_back(j);
- }
- }
-
- // ok..now make sure we didn't prune so many vertices it is now invalid.
- // if ( 1 )
- {
- btScalar bmin[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
- btScalar bmax[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
-
- for (unsigned int i = 0; i < vcount; i++)
- {
- const btVector3 &p = vertices[i];
- for (int j = 0; j < 3; j++)
- {
- if (p[j] < bmin[j]) bmin[j] = p[j];
- if (p[j] > bmax[j]) bmax[j] = p[j];
- }
- }
-
- btScalar dx = bmax[0] - bmin[0];
- btScalar dy = bmax[1] - bmin[1];
- btScalar dz = bmax[2] - bmin[2];
-
- if (dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
- {
- btScalar cx = dx * btScalar(0.5) + bmin[0];
- btScalar cy = dy * btScalar(0.5) + bmin[1];
- btScalar cz = dz * btScalar(0.5) + bmin[2];
-
- btScalar len = FLT_MAX;
-
- if (dx >= EPSILON && dx < len) len = dx;
- if (dy >= EPSILON && dy < len) len = dy;
- if (dz >= EPSILON && dz < len) len = dz;
-
- if (len == FLT_MAX)
- {
- dx = dy = dz = btScalar(0.01); // one centimeter
- }
- else
- {
- if (dx < EPSILON) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
- if (dy < EPSILON) dy = len * btScalar(0.05);
- if (dz < EPSILON) dz = len * btScalar(0.05);
- }
-
- btScalar x1 = cx - dx;
- btScalar x2 = cx + dx;
-
- btScalar y1 = cy - dy;
- btScalar y2 = cy + dy;
-
- btScalar z1 = cz - dz;
- btScalar z2 = cz + dz;
-
- vcount = 0; // add box
-
- addPoint(vcount, vertices, x1, y1, z1);
- addPoint(vcount, vertices, x2, y1, z1);
- addPoint(vcount, vertices, x2, y2, z1);
- addPoint(vcount, vertices, x1, y2, z1);
- addPoint(vcount, vertices, x1, y1, z2);
- addPoint(vcount, vertices, x2, y1, z2);
- addPoint(vcount, vertices, x2, y2, z2);
- addPoint(vcount, vertices, x1, y2, z2);
-
- return true;
- }
- }
-
- return true;
-}
-
-void HullLibrary::BringOutYourDead(const btVector3 *verts, unsigned int vcount, btVector3 *overts, unsigned int &ocount, unsigned int *indices, unsigned indexcount)
-{
- btAlignedObjectArray<int> tmpIndices;
- tmpIndices.resize(m_vertexIndexMapping.size());
- int i;
-
- for (i = 0; i < m_vertexIndexMapping.size(); i++)
- {
- tmpIndices[i] = m_vertexIndexMapping[i];
- }
-
- TUIntArray usedIndices;
- usedIndices.resize(static_cast<int>(vcount));
- memset(&usedIndices[0], 0, sizeof(unsigned int) * vcount);
-
- ocount = 0;
-
- for (i = 0; i < int(indexcount); i++)
- {
- unsigned int v = indices[i]; // original array index
-
- btAssert(v >= 0 && v < vcount);
-
- if (usedIndices[static_cast<int>(v)]) // if already remapped
- {
- indices[i] = usedIndices[static_cast<int>(v)] - 1; // index to new array
- }
- else
- {
- indices[i] = ocount; // new index mapping
-
- overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
- overts[ocount][1] = verts[v][1];
- overts[ocount][2] = verts[v][2];
-
- for (int k = 0; k < m_vertexIndexMapping.size(); k++)
- {
- if (tmpIndices[k] == int(v))
- m_vertexIndexMapping[k] = ocount;
- }
-
- ocount++; // increment output vert count
-
- btAssert(ocount >= 0 && ocount <= vcount);
-
- usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
- }
- }
-}
diff --git a/thirdparty/bullet/LinearMath/btConvexHull.h b/thirdparty/bullet/LinearMath/btConvexHull.h
deleted file mode 100644
index f890d75ea1..0000000000
--- a/thirdparty/bullet/LinearMath/btConvexHull.h
+++ /dev/null
@@ -1,233 +0,0 @@
-
-/*
-Stan Melax Convex Hull Computation
-Copyright (c) 2008 Stan Melax http://www.melax.com/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
-
-#ifndef BT_CD_HULL_H
-#define BT_CD_HULL_H
-
-#include "btVector3.h"
-#include "btAlignedObjectArray.h"
-
-typedef btAlignedObjectArray<unsigned int> TUIntArray;
-
-class HullResult
-{
-public:
- HullResult(void)
- {
- mPolygons = true;
- mNumOutputVertices = 0;
- mNumFaces = 0;
- mNumIndices = 0;
- }
- bool mPolygons; // true if indices represents polygons, false indices are triangles
- unsigned int mNumOutputVertices; // number of vertices in the output hull
- btAlignedObjectArray<btVector3> m_OutputVertices; // array of vertices
- unsigned int mNumFaces; // the number of faces produced
- unsigned int mNumIndices; // the total number of indices
- btAlignedObjectArray<unsigned int> m_Indices; // pointer to indices.
-
- // If triangles, then indices are array indexes into the vertex list.
- // If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
-};
-
-enum HullFlag
-{
- QF_TRIANGLES = (1 << 0), // report results as triangles, not polygons.
- QF_REVERSE_ORDER = (1 << 1), // reverse order of the triangle indices.
- QF_DEFAULT = QF_TRIANGLES
-};
-
-class HullDesc
-{
-public:
- HullDesc(void)
- {
- mFlags = QF_DEFAULT;
- mVcount = 0;
- mVertices = 0;
- mVertexStride = sizeof(btVector3);
- mNormalEpsilon = 0.001f;
- mMaxVertices = 4096; // maximum number of points to be considered for a convex hull.
- mMaxFaces = 4096;
- };
-
- HullDesc(HullFlag flag,
- unsigned int vcount,
- const btVector3* vertices,
- unsigned int stride = sizeof(btVector3))
- {
- mFlags = flag;
- mVcount = vcount;
- mVertices = vertices;
- mVertexStride = stride;
- mNormalEpsilon = btScalar(0.001);
- mMaxVertices = 4096;
- }
-
- bool HasHullFlag(HullFlag flag) const
- {
- if (mFlags & flag) return true;
- return false;
- }
-
- void SetHullFlag(HullFlag flag)
- {
- mFlags |= flag;
- }
-
- void ClearHullFlag(HullFlag flag)
- {
- mFlags &= ~flag;
- }
-
- unsigned int mFlags; // flags to use when generating the convex hull.
- unsigned int mVcount; // number of vertices in the input point cloud
- const btVector3* mVertices; // the array of vertices.
- unsigned int mVertexStride; // the stride of each vertex, in bytes.
- btScalar mNormalEpsilon; // the epsilon for removing duplicates. This is a normalized value, if normalized bit is on.
- unsigned int mMaxVertices; // maximum number of vertices to be considered for the hull!
- unsigned int mMaxFaces;
-};
-
-enum HullError
-{
- QE_OK, // success!
- QE_FAIL // failed.
-};
-
-class btPlane
-{
-public:
- btVector3 normal;
- btScalar dist; // distance below origin - the D from plane equasion Ax+By+Cz+D=0
- btPlane(const btVector3& n, btScalar d) : normal(n), dist(d) {}
- btPlane() : normal(), dist(0) {}
-};
-
-class ConvexH
-{
-public:
- class HalfEdge
- {
- public:
- short ea; // the other half of the edge (index into edges list)
- unsigned char v; // the vertex at the start of this edge (index into vertices list)
- unsigned char p; // the facet on which this edge lies (index into facets list)
- HalfEdge() {}
- HalfEdge(short _ea, unsigned char _v, unsigned char _p) : ea(_ea), v(_v), p(_p) {}
- };
- ConvexH()
- {
- }
- ~ConvexH()
- {
- }
- btAlignedObjectArray<btVector3> vertices;
- btAlignedObjectArray<HalfEdge> edges;
- btAlignedObjectArray<btPlane> facets;
- ConvexH(int vertices_size, int edges_size, int facets_size);
-};
-
-class int4
-{
-public:
- int x, y, z, w;
- int4(){};
- int4(int _x, int _y, int _z, int _w)
- {
- x = _x;
- y = _y;
- z = _z;
- w = _w;
- }
- const int& operator[](int i) const { return (&x)[i]; }
- int& operator[](int i) { return (&x)[i]; }
-};
-
-class PHullResult
-{
-public:
- PHullResult(void)
- {
- mVcount = 0;
- mIndexCount = 0;
- mFaceCount = 0;
- mVertices = 0;
- }
-
- unsigned int mVcount;
- unsigned int mIndexCount;
- unsigned int mFaceCount;
- btVector3* mVertices;
- TUIntArray m_Indices;
-};
-
-///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
-///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
-class HullLibrary
-{
- btAlignedObjectArray<class btHullTriangle*> m_tris;
-
-public:
- btAlignedObjectArray<int> m_vertexIndexMapping;
-
- HullError CreateConvexHull(const HullDesc& desc, // describes the input request
- HullResult& result); // contains the resulst
- HullError ReleaseResult(HullResult& result); // release memory allocated for this result, we are done with it.
-
-private:
- bool ComputeHull(unsigned int vcount, const btVector3* vertices, PHullResult& result, unsigned int vlimit);
-
- class btHullTriangle* allocateTriangle(int a, int b, int c);
- void deAllocateTriangle(btHullTriangle*);
- void b2bfix(btHullTriangle* s, btHullTriangle* t);
-
- void removeb2b(btHullTriangle* s, btHullTriangle* t);
-
- void checkit(btHullTriangle* t);
-
- btHullTriangle* extrudable(btScalar epsilon);
-
- int calchull(btVector3* verts, int verts_count, TUIntArray& tris_out, int& tris_count, int vlimit);
-
- int calchullgen(btVector3* verts, int verts_count, int vlimit);
-
- int4 FindSimplex(btVector3* verts, int verts_count, btAlignedObjectArray<int>& allow);
-
- class ConvexH* ConvexHCrop(ConvexH& convex, const btPlane& slice);
-
- void extrude(class btHullTriangle* t0, int v);
-
- ConvexH* test_cube();
-
- //BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'.
- //After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
- //The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
- //The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
- void BringOutYourDead(const btVector3* verts, unsigned int vcount, btVector3* overts, unsigned int& ocount, unsigned int* indices, unsigned indexcount);
-
- bool CleanupVertices(unsigned int svcount,
- const btVector3* svertices,
- unsigned int stride,
- unsigned int& vcount, // output number of vertices
- btVector3* vertices, // location to store the results.
- btScalar normalepsilon,
- btVector3& scale);
-};
-
-#endif //BT_CD_HULL_H
diff --git a/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp b/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp
deleted file mode 100644
index 12125fd2de..0000000000
--- a/thirdparty/bullet/LinearMath/btConvexHullComputer.cpp
+++ /dev/null
@@ -1,2760 +0,0 @@
-/*
-Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include <string.h>
-
-#include "btConvexHullComputer.h"
-#include "btAlignedObjectArray.h"
-#include "btMinMax.h"
-#include "btVector3.h"
-
-#ifdef __GNUC__
-#include <stdint.h>
-#elif defined(_MSC_VER)
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-#else
-typedef int int32_t;
-typedef long long int int64_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long int uint64_t;
-#endif
-
-//The definition of USE_X86_64_ASM is moved into the build system. You can enable it manually by commenting out the following lines
-//#if (defined(__GNUC__) && defined(__x86_64__) && !defined(__ICL)) // || (defined(__ICL) && defined(_M_X64)) bug in Intel compiler, disable inline assembly
-// #define USE_X86_64_ASM
-//#endif
-
-//#define DEBUG_CONVEX_HULL
-//#define SHOW_ITERATIONS
-
-#if defined(DEBUG_CONVEX_HULL) || defined(SHOW_ITERATIONS)
-#include <stdio.h>
-#endif
-
-// Convex hull implementation based on Preparata and Hong
-// Ole Kniemeyer, MAXON Computer GmbH
-class btConvexHullInternal
-{
-public:
- class Point64
- {
- public:
- int64_t x;
- int64_t y;
- int64_t z;
-
- Point64(int64_t x, int64_t y, int64_t z) : x(x), y(y), z(z)
- {
- }
-
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
-
- int64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
- };
-
- class Point32
- {
- public:
- int32_t x;
- int32_t y;
- int32_t z;
- int index;
-
- Point32()
- {
- }
-
- Point32(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z), index(-1)
- {
- }
-
- bool operator==(const Point32& b) const
- {
- return (x == b.x) && (y == b.y) && (z == b.z);
- }
-
- bool operator!=(const Point32& b) const
- {
- return (x != b.x) || (y != b.y) || (z != b.z);
- }
-
- bool isZero()
- {
- return (x == 0) && (y == 0) && (z == 0);
- }
-
- Point64 cross(const Point32& b) const
- {
- return Point64(((int64_t)y) * b.z - ((int64_t)z) * b.y, ((int64_t)z) * b.x - ((int64_t)x) * b.z, ((int64_t)x) * b.y - ((int64_t)y) * b.x);
- }
-
- Point64 cross(const Point64& b) const
- {
- return Point64(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x);
- }
-
- int64_t dot(const Point32& b) const
- {
- return ((int64_t)x) * b.x + ((int64_t)y) * b.y + ((int64_t)z) * b.z;
- }
-
- int64_t dot(const Point64& b) const
- {
- return x * b.x + y * b.y + z * b.z;
- }
-
- Point32 operator+(const Point32& b) const
- {
- return Point32(x + b.x, y + b.y, z + b.z);
- }
-
- Point32 operator-(const Point32& b) const
- {
- return Point32(x - b.x, y - b.y, z - b.z);
- }
- };
-
- class Int128
- {
- public:
- uint64_t low;
- uint64_t high;
-
- Int128()
- {
- }
-
- Int128(uint64_t low, uint64_t high) : low(low), high(high)
- {
- }
-
- Int128(uint64_t low) : low(low), high(0)
- {
- }
-
- Int128(int64_t value) : low(value), high((value >= 0) ? 0 : (uint64_t)-1LL)
- {
- }
-
- static Int128 mul(int64_t a, int64_t b);
-
- static Int128 mul(uint64_t a, uint64_t b);
-
- Int128 operator-() const
- {
- return Int128((uint64_t) - (int64_t)low, ~high + (low == 0));
- }
-
- Int128 operator+(const Int128& b) const
- {
-#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__(
- "addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r"(result.low), [rh] "=r"(result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
- return result;
-#else
- uint64_t lo = low + b.low;
- return Int128(lo, high + b.high + (lo < low));
-#endif
- }
-
- Int128 operator-(const Int128& b) const
- {
-#ifdef USE_X86_64_ASM
- Int128 result;
- __asm__(
- "subq %[bl], %[rl]\n\t"
- "sbbq %[bh], %[rh]\n\t"
- : [rl] "=r"(result.low), [rh] "=r"(result.high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
- return result;
-#else
- return *this + -b;
-#endif
- }
-
- Int128& operator+=(const Int128& b)
- {
-#ifdef USE_X86_64_ASM
- __asm__(
- "addq %[bl], %[rl]\n\t"
- "adcq %[bh], %[rh]\n\t"
- : [rl] "=r"(low), [rh] "=r"(high)
- : "0"(low), "1"(high), [bl] "g"(b.low), [bh] "g"(b.high)
- : "cc");
-#else
- uint64_t lo = low + b.low;
- if (lo < low)
- {
- ++high;
- }
- low = lo;
- high += b.high;
-#endif
- return *this;
- }
-
- Int128& operator++()
- {
- if (++low == 0)
- {
- ++high;
- }
- return *this;
- }
-
- Int128 operator*(int64_t b) const;
-
- btScalar toScalar() const
- {
- return ((int64_t)high >= 0) ? btScalar(high) * (btScalar(0x100000000LL) * btScalar(0x100000000LL)) + btScalar(low)
- : -(-*this).toScalar();
- }
-
- int getSign() const
- {
- return ((int64_t)high < 0) ? -1 : (high || low) ? 1 : 0;
- }
-
- bool operator<(const Int128& b) const
- {
- return (high < b.high) || ((high == b.high) && (low < b.low));
- }
-
- int ucmp(const Int128& b) const
- {
- if (high < b.high)
- {
- return -1;
- }
- if (high > b.high)
- {
- return 1;
- }
- if (low < b.low)
- {
- return -1;
- }
- if (low > b.low)
- {
- return 1;
- }
- return 0;
- }
- };
-
- class Rational64
- {
- private:
- uint64_t m_numerator;
- uint64_t m_denominator;
- int sign;
-
- public:
- Rational64(int64_t numerator, int64_t denominator)
- {
- if (numerator > 0)
- {
- sign = 1;
- m_numerator = (uint64_t)numerator;
- }
- else if (numerator < 0)
- {
- sign = -1;
- m_numerator = (uint64_t)-numerator;
- }
- else
- {
- sign = 0;
- m_numerator = 0;
- }
- if (denominator > 0)
- {
- m_denominator = (uint64_t)denominator;
- }
- else if (denominator < 0)
- {
- sign = -sign;
- m_denominator = (uint64_t)-denominator;
- }
- else
- {
- m_denominator = 0;
- }
- }
-
- bool isNegativeInfinity() const
- {
- return (sign < 0) && (m_denominator == 0);
- }
-
- bool isNaN() const
- {
- return (sign == 0) && (m_denominator == 0);
- }
-
- int compare(const Rational64& b) const;
-
- btScalar toScalar() const
- {
- return sign * ((m_denominator == 0) ? SIMD_INFINITY : (btScalar)m_numerator / m_denominator);
- }
- };
-
- class Rational128
- {
- private:
- Int128 numerator;
- Int128 denominator;
- int sign;
- bool isInt64;
-
- public:
- Rational128(int64_t value)
- {
- if (value > 0)
- {
- sign = 1;
- this->numerator = value;
- }
- else if (value < 0)
- {
- sign = -1;
- this->numerator = -value;
- }
- else
- {
- sign = 0;
- this->numerator = (uint64_t)0;
- }
- this->denominator = (uint64_t)1;
- isInt64 = true;
- }
-
- Rational128(const Int128& numerator, const Int128& denominator)
- {
- sign = numerator.getSign();
- if (sign >= 0)
- {
- this->numerator = numerator;
- }
- else
- {
- this->numerator = -numerator;
- }
- int dsign = denominator.getSign();
- if (dsign >= 0)
- {
- this->denominator = denominator;
- }
- else
- {
- sign = -sign;
- this->denominator = -denominator;
- }
- isInt64 = false;
- }
-
- int compare(const Rational128& b) const;
-
- int compare(int64_t b) const;
-
- btScalar toScalar() const
- {
- return sign * ((denominator.getSign() == 0) ? SIMD_INFINITY : numerator.toScalar() / denominator.toScalar());
- }
- };
-
- class PointR128
- {
- public:
- Int128 x;
- Int128 y;
- Int128 z;
- Int128 denominator;
-
- PointR128()
- {
- }
-
- PointR128(Int128 x, Int128 y, Int128 z, Int128 denominator) : x(x), y(y), z(z), denominator(denominator)
- {
- }
-
- btScalar xvalue() const
- {
- return x.toScalar() / denominator.toScalar();
- }
-
- btScalar yvalue() const
- {
- return y.toScalar() / denominator.toScalar();
- }
-
- btScalar zvalue() const
- {
- return z.toScalar() / denominator.toScalar();
- }
- };
-
- class Edge;
- class Face;
-
- class Vertex
- {
- public:
- Vertex* next;
- Vertex* prev;
- Edge* edges;
- Face* firstNearbyFace;
- Face* lastNearbyFace;
- PointR128 point128;
- Point32 point;
- int copy;
-
- Vertex() : next(NULL), prev(NULL), edges(NULL), firstNearbyFace(NULL), lastNearbyFace(NULL), copy(-1)
- {
- }
-
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- printf("V%d (%d, %d, %d)", point.index, point.x, point.y, point.z);
- }
-
- void printGraph();
-#endif
-
- Point32 operator-(const Vertex& b) const
- {
- return point - b.point;
- }
-
- Rational128 dot(const Point64& b) const
- {
- return (point.index >= 0) ? Rational128(point.dot(b))
- : Rational128(point128.x * b.x + point128.y * b.y + point128.z * b.z, point128.denominator);
- }
-
- btScalar xvalue() const
- {
- return (point.index >= 0) ? btScalar(point.x) : point128.xvalue();
- }
-
- btScalar yvalue() const
- {
- return (point.index >= 0) ? btScalar(point.y) : point128.yvalue();
- }
-
- btScalar zvalue() const
- {
- return (point.index >= 0) ? btScalar(point.z) : point128.zvalue();
- }
-
- void receiveNearbyFaces(Vertex* src)
- {
- if (lastNearbyFace)
- {
- lastNearbyFace->nextWithSameNearbyVertex = src->firstNearbyFace;
- }
- else
- {
- firstNearbyFace = src->firstNearbyFace;
- }
- if (src->lastNearbyFace)
- {
- lastNearbyFace = src->lastNearbyFace;
- }
- for (Face* f = src->firstNearbyFace; f; f = f->nextWithSameNearbyVertex)
- {
- btAssert(f->nearbyVertex == src);
- f->nearbyVertex = this;
- }
- src->firstNearbyFace = NULL;
- src->lastNearbyFace = NULL;
- }
- };
-
- class Edge
- {
- public:
- Edge* next;
- Edge* prev;
- Edge* reverse;
- Vertex* target;
- Face* face;
- int copy;
-
- ~Edge()
- {
- next = NULL;
- prev = NULL;
- reverse = NULL;
- target = NULL;
- face = NULL;
- }
-
- void link(Edge* n)
- {
- btAssert(reverse->target == n->reverse->target);
- next = n;
- n->prev = this;
- }
-
-#ifdef DEBUG_CONVEX_HULL
- void print()
- {
- printf("E%p : %d -> %d, n=%p p=%p (0 %d\t%d\t%d) -> (%d %d %d)", this, reverse->target->point.index, target->point.index, next, prev,
- reverse->target->point.x, reverse->target->point.y, reverse->target->point.z, target->point.x, target->point.y, target->point.z);
- }
-#endif
- };
-
- class Face
- {
- public:
- Face* next;
- Vertex* nearbyVertex;
- Face* nextWithSameNearbyVertex;
- Point32 origin;
- Point32 dir0;
- Point32 dir1;
-
- Face() : next(NULL), nearbyVertex(NULL), nextWithSameNearbyVertex(NULL)
- {
- }
-
- void init(Vertex* a, Vertex* b, Vertex* c)
- {
- nearbyVertex = a;
- origin = a->point;
- dir0 = *b - *a;
- dir1 = *c - *a;
- if (a->lastNearbyFace)
- {
- a->lastNearbyFace->nextWithSameNearbyVertex = this;
- }
- else
- {
- a->firstNearbyFace = this;
- }
- a->lastNearbyFace = this;
- }
-
- Point64 getNormal()
- {
- return dir0.cross(dir1);
- }
- };
-
- template <typename UWord, typename UHWord>
- class DMul
- {
- private:
- static uint32_t high(uint64_t value)
- {
- return (uint32_t)(value >> 32);
- }
-
- static uint32_t low(uint64_t value)
- {
- return (uint32_t)value;
- }
-
- static uint64_t mul(uint32_t a, uint32_t b)
- {
- return (uint64_t)a * (uint64_t)b;
- }
-
- static void shlHalf(uint64_t& value)
- {
- value <<= 32;
- }
-
- static uint64_t high(Int128 value)
- {
- return value.high;
- }
-
- static uint64_t low(Int128 value)
- {
- return value.low;
- }
-
- static Int128 mul(uint64_t a, uint64_t b)
- {
- return Int128::mul(a, b);
- }
-
- static void shlHalf(Int128& value)
- {
- value.high = value.low;
- value.low = 0;
- }
-
- public:
- static void mul(UWord a, UWord b, UWord& resLow, UWord& resHigh)
- {
- UWord p00 = mul(low(a), low(b));
- UWord p01 = mul(low(a), high(b));
- UWord p10 = mul(high(a), low(b));
- UWord p11 = mul(high(a), high(b));
- UWord p0110 = UWord(low(p01)) + UWord(low(p10));
- p11 += high(p01);
- p11 += high(p10);
- p11 += high(p0110);
- shlHalf(p0110);
- p00 += p0110;
- if (p00 < p0110)
- {
- ++p11;
- }
- resLow = p00;
- resHigh = p11;
- }
- };
-
-private:
- class IntermediateHull
- {
- public:
- Vertex* minXy;
- Vertex* maxXy;
- Vertex* minYx;
- Vertex* maxYx;
-
- IntermediateHull() : minXy(NULL), maxXy(NULL), minYx(NULL), maxYx(NULL)
- {
- }
-
- void print();
- };
-
- enum Orientation
- {
- NONE,
- CLOCKWISE,
- COUNTER_CLOCKWISE
- };
-
- template <typename T>
- class PoolArray
- {
- private:
- T* array;
- int size;
-
- public:
- PoolArray<T>* next;
-
- PoolArray(int size) : size(size), next(NULL)
- {
- array = (T*)btAlignedAlloc(sizeof(T) * size, 16);
- }
-
- ~PoolArray()
- {
- btAlignedFree(array);
- }
-
- T* init()
- {
- T* o = array;
- for (int i = 0; i < size; i++, o++)
- {
- o->next = (i + 1 < size) ? o + 1 : NULL;
- }
- return array;
- }
- };
-
- template <typename T>
- class Pool
- {
- private:
- PoolArray<T>* arrays;
- PoolArray<T>* nextArray;
- T* freeObjects;
- int arraySize;
-
- public:
- Pool() : arrays(NULL), nextArray(NULL), freeObjects(NULL), arraySize(256)
- {
- }
-
- ~Pool()
- {
- while (arrays)
- {
- PoolArray<T>* p = arrays;
- arrays = p->next;
- p->~PoolArray<T>();
- btAlignedFree(p);
- }
- }
-
- void reset()
- {
- nextArray = arrays;
- freeObjects = NULL;
- }
-
- void setArraySize(int arraySize)
- {
- this->arraySize = arraySize;
- }
-
- T* newObject()
- {
- T* o = freeObjects;
- if (!o)
- {
- PoolArray<T>* p = nextArray;
- if (p)
- {
- nextArray = p->next;
- }
- else
- {
- p = new (btAlignedAlloc(sizeof(PoolArray<T>), 16)) PoolArray<T>(arraySize);
- p->next = arrays;
- arrays = p;
- }
- o = p->init();
- }
- freeObjects = o->next;
- return new (o) T();
- };
-
- void freeObject(T* object)
- {
- object->~T();
- object->next = freeObjects;
- freeObjects = object;
- }
- };
-
- btVector3 scaling;
- btVector3 center;
- Pool<Vertex> vertexPool;
- Pool<Edge> edgePool;
- Pool<Face> facePool;
- btAlignedObjectArray<Vertex*> originalVertices;
- int mergeStamp;
- int minAxis;
- int medAxis;
- int maxAxis;
- int usedEdgePairs;
- int maxUsedEdgePairs;
-
- static Orientation getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t);
- Edge* findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot);
- void findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1);
-
- Edge* newEdgePair(Vertex* from, Vertex* to);
-
- void removeEdgePair(Edge* edge)
- {
- Edge* n = edge->next;
- Edge* r = edge->reverse;
-
- btAssert(edge->target && r->target);
-
- if (n != edge)
- {
- n->prev = edge->prev;
- edge->prev->next = n;
- r->target->edges = n;
- }
- else
- {
- r->target->edges = NULL;
- }
-
- n = r->next;
-
- if (n != r)
- {
- n->prev = r->prev;
- r->prev->next = n;
- edge->target->edges = n;
- }
- else
- {
- edge->target->edges = NULL;
- }
-
- edgePool.freeObject(edge);
- edgePool.freeObject(r);
- usedEdgePairs--;
- }
-
- void computeInternal(int start, int end, IntermediateHull& result);
-
- bool mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1);
-
- void merge(IntermediateHull& h0, IntermediateHull& h1);
-
- btVector3 toBtVector(const Point32& v);
-
- btVector3 getBtNormal(Face* face);
-
- bool shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack);
-
-public:
- Vertex* vertexList;
-
- void compute(const void* coords, bool doubleCoords, int stride, int count);
-
- btVector3 getCoordinates(const Vertex* v);
-
- btScalar shrink(btScalar amount, btScalar clampAmount);
-};
-
-btConvexHullInternal::Int128 btConvexHullInternal::Int128::operator*(int64_t b) const
-{
- bool negative = (int64_t)high < 0;
- Int128 a = negative ? -*this : *this;
- if (b < 0)
- {
- negative = !negative;
- b = -b;
- }
- Int128 result = mul(a.low, (uint64_t)b);
- result.high += a.high * (uint64_t)b;
- return negative ? -result : result;
-}
-
-btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(int64_t a, int64_t b)
-{
- Int128 result;
-
-#ifdef USE_X86_64_ASM
- __asm__("imulq %[b]"
- : "=a"(result.low), "=d"(result.high)
- : "0"(a), [b] "r"(b)
- : "cc");
- return result;
-
-#else
- bool negative = a < 0;
- if (negative)
- {
- a = -a;
- }
- if (b < 0)
- {
- negative = !negative;
- b = -b;
- }
- DMul<uint64_t, uint32_t>::mul((uint64_t)a, (uint64_t)b, result.low, result.high);
- return negative ? -result : result;
-#endif
-}
-
-btConvexHullInternal::Int128 btConvexHullInternal::Int128::mul(uint64_t a, uint64_t b)
-{
- Int128 result;
-
-#ifdef USE_X86_64_ASM
- __asm__("mulq %[b]"
- : "=a"(result.low), "=d"(result.high)
- : "0"(a), [b] "r"(b)
- : "cc");
-
-#else
- DMul<uint64_t, uint32_t>::mul(a, b, result.low, result.high);
-#endif
-
- return result;
-}
-
-int btConvexHullInternal::Rational64::compare(const Rational64& b) const
-{
- if (sign != b.sign)
- {
- return sign - b.sign;
- }
- else if (sign == 0)
- {
- return 0;
- }
-
- // return (numerator * b.denominator > b.numerator * denominator) ? sign : (numerator * b.denominator < b.numerator * denominator) ? -sign : 0;
-
-#ifdef USE_X86_64_ASM
-
- int result;
- int64_t tmp;
- int64_t dummy;
- __asm__(
- "mulq %[bn]\n\t"
- "movq %%rax, %[tmp]\n\t"
- "movq %%rdx, %%rbx\n\t"
- "movq %[tn], %%rax\n\t"
- "mulq %[bd]\n\t"
- "subq %[tmp], %%rax\n\t"
- "sbbq %%rbx, %%rdx\n\t" // rdx:rax contains 128-bit-difference "numerator*b.denominator - b.numerator*denominator"
- "setnsb %%bh\n\t" // bh=1 if difference is non-negative, bh=0 otherwise
- "orq %%rdx, %%rax\n\t"
- "setnzb %%bl\n\t" // bl=1 if difference if non-zero, bl=0 if it is zero
- "decb %%bh\n\t" // now bx=0x0000 if difference is zero, 0xff01 if it is negative, 0x0001 if it is positive (i.e., same sign as difference)
- "shll $16, %%ebx\n\t" // ebx has same sign as difference
- : "=&b"(result), [tmp] "=&r"(tmp), "=a"(dummy)
- : "a"(m_denominator), [bn] "g"(b.m_numerator), [tn] "g"(m_numerator), [bd] "g"(b.m_denominator)
- : "%rdx", "cc");
- return result ? result ^ sign // if sign is +1, only bit 0 of result is inverted, which does not change the sign of result (and cannot result in zero)
- // if sign is -1, all bits of result are inverted, which changes the sign of result (and again cannot result in zero)
- : 0;
-
-#else
-
- return sign * Int128::mul(m_numerator, b.m_denominator).ucmp(Int128::mul(m_denominator, b.m_numerator));
-
-#endif
-}
-
-int btConvexHullInternal::Rational128::compare(const Rational128& b) const
-{
- if (sign != b.sign)
- {
- return sign - b.sign;
- }
- else if (sign == 0)
- {
- return 0;
- }
- if (isInt64)
- {
- return -b.compare(sign * (int64_t)numerator.low);
- }
-
- Int128 nbdLow, nbdHigh, dbnLow, dbnHigh;
- DMul<Int128, uint64_t>::mul(numerator, b.denominator, nbdLow, nbdHigh);
- DMul<Int128, uint64_t>::mul(denominator, b.numerator, dbnLow, dbnHigh);
-
- int cmp = nbdHigh.ucmp(dbnHigh);
- if (cmp)
- {
- return cmp * sign;
- }
- return nbdLow.ucmp(dbnLow) * sign;
-}
-
-int btConvexHullInternal::Rational128::compare(int64_t b) const
-{
- if (isInt64)
- {
- int64_t a = sign * (int64_t)numerator.low;
- return (a > b) ? 1 : (a < b) ? -1 : 0;
- }
- if (b > 0)
- {
- if (sign <= 0)
- {
- return -1;
- }
- }
- else if (b < 0)
- {
- if (sign >= 0)
- {
- return 1;
- }
- b = -b;
- }
- else
- {
- return sign;
- }
-
- return numerator.ucmp(denominator * b) * sign;
-}
-
-btConvexHullInternal::Edge* btConvexHullInternal::newEdgePair(Vertex* from, Vertex* to)
-{
- btAssert(from && to);
- Edge* e = edgePool.newObject();
- Edge* r = edgePool.newObject();
- e->reverse = r;
- r->reverse = e;
- e->copy = mergeStamp;
- r->copy = mergeStamp;
- e->target = to;
- r->target = from;
- e->face = NULL;
- r->face = NULL;
- usedEdgePairs++;
- if (usedEdgePairs > maxUsedEdgePairs)
- {
- maxUsedEdgePairs = usedEdgePairs;
- }
- return e;
-}
-
-bool btConvexHullInternal::mergeProjection(IntermediateHull& h0, IntermediateHull& h1, Vertex*& c0, Vertex*& c1)
-{
- Vertex* v0 = h0.maxYx;
- Vertex* v1 = h1.minYx;
- if ((v0->point.x == v1->point.x) && (v0->point.y == v1->point.y))
- {
- btAssert(v0->point.z < v1->point.z);
- Vertex* v1p = v1->prev;
- if (v1p == v1)
- {
- c0 = v0;
- if (v1->edges)
- {
- btAssert(v1->edges->next == v1->edges);
- v1 = v1->edges->target;
- btAssert(v1->edges->next == v1->edges);
- }
- c1 = v1;
- return false;
- }
- Vertex* v1n = v1->next;
- v1p->next = v1n;
- v1n->prev = v1p;
- if (v1 == h1.minXy)
- {
- if ((v1n->point.x < v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y < v1p->point.y)))
- {
- h1.minXy = v1n;
- }
- else
- {
- h1.minXy = v1p;
- }
- }
- if (v1 == h1.maxXy)
- {
- if ((v1n->point.x > v1p->point.x) || ((v1n->point.x == v1p->point.x) && (v1n->point.y > v1p->point.y)))
- {
- h1.maxXy = v1n;
- }
- else
- {
- h1.maxXy = v1p;
- }
- }
- }
-
- v0 = h0.maxXy;
- v1 = h1.maxXy;
- Vertex* v00 = NULL;
- Vertex* v10 = NULL;
- int32_t sign = 1;
-
- for (int side = 0; side <= 1; side++)
- {
- int32_t dx = (v1->point.x - v0->point.x) * sign;
- if (dx > 0)
- {
- while (true)
- {
- int32_t dy = v1->point.y - v0->point.y;
-
- Vertex* w0 = side ? v0->next : v0->prev;
- if (w0 != v0)
- {
- int32_t dx0 = (w0->point.x - v0->point.x) * sign;
- int32_t dy0 = w0->point.y - v0->point.y;
- if ((dy0 <= 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx <= dy * dx0))))
- {
- v0 = w0;
- dx = (v1->point.x - v0->point.x) * sign;
- continue;
- }
- }
-
- Vertex* w1 = side ? v1->next : v1->prev;
- if (w1 != v1)
- {
- int32_t dx1 = (w1->point.x - v1->point.x) * sign;
- int32_t dy1 = w1->point.y - v1->point.y;
- int32_t dxn = (w1->point.x - v0->point.x) * sign;
- if ((dxn > 0) && (dy1 < 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx < dy * dx1))))
- {
- v1 = w1;
- dx = dxn;
- continue;
- }
- }
-
- break;
- }
- }
- else if (dx < 0)
- {
- while (true)
- {
- int32_t dy = v1->point.y - v0->point.y;
-
- Vertex* w1 = side ? v1->prev : v1->next;
- if (w1 != v1)
- {
- int32_t dx1 = (w1->point.x - v1->point.x) * sign;
- int32_t dy1 = w1->point.y - v1->point.y;
- if ((dy1 >= 0) && ((dx1 == 0) || ((dx1 < 0) && (dy1 * dx <= dy * dx1))))
- {
- v1 = w1;
- dx = (v1->point.x - v0->point.x) * sign;
- continue;
- }
- }
-
- Vertex* w0 = side ? v0->prev : v0->next;
- if (w0 != v0)
- {
- int32_t dx0 = (w0->point.x - v0->point.x) * sign;
- int32_t dy0 = w0->point.y - v0->point.y;
- int32_t dxn = (v1->point.x - w0->point.x) * sign;
- if ((dxn < 0) && (dy0 > 0) && ((dx0 == 0) || ((dx0 < 0) && (dy0 * dx < dy * dx0))))
- {
- v0 = w0;
- dx = dxn;
- continue;
- }
- }
-
- break;
- }
- }
- else
- {
- int32_t x = v0->point.x;
- int32_t y0 = v0->point.y;
- Vertex* w0 = v0;
- Vertex* t;
- while (((t = side ? w0->next : w0->prev) != v0) && (t->point.x == x) && (t->point.y <= y0))
- {
- w0 = t;
- y0 = t->point.y;
- }
- v0 = w0;
-
- int32_t y1 = v1->point.y;
- Vertex* w1 = v1;
- while (((t = side ? w1->prev : w1->next) != v1) && (t->point.x == x) && (t->point.y >= y1))
- {
- w1 = t;
- y1 = t->point.y;
- }
- v1 = w1;
- }
-
- if (side == 0)
- {
- v00 = v0;
- v10 = v1;
-
- v0 = h0.minXy;
- v1 = h1.minXy;
- sign = -1;
- }
- }
-
- v0->prev = v1;
- v1->next = v0;
-
- v00->next = v10;
- v10->prev = v00;
-
- if (h1.minXy->point.x < h0.minXy->point.x)
- {
- h0.minXy = h1.minXy;
- }
- if (h1.maxXy->point.x >= h0.maxXy->point.x)
- {
- h0.maxXy = h1.maxXy;
- }
-
- h0.maxYx = h1.maxYx;
-
- c0 = v00;
- c1 = v10;
-
- return true;
-}
-
-void btConvexHullInternal::computeInternal(int start, int end, IntermediateHull& result)
-{
- int n = end - start;
- switch (n)
- {
- case 0:
- result.minXy = NULL;
- result.maxXy = NULL;
- result.minYx = NULL;
- result.maxYx = NULL;
- return;
- case 2:
- {
- Vertex* v = originalVertices[start];
- Vertex* w = v + 1;
- if (v->point != w->point)
- {
- int32_t dx = v->point.x - w->point.x;
- int32_t dy = v->point.y - w->point.y;
-
- if ((dx == 0) && (dy == 0))
- {
- if (v->point.z > w->point.z)
- {
- Vertex* t = w;
- w = v;
- v = t;
- }
- btAssert(v->point.z < w->point.z);
- v->next = v;
- v->prev = v;
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
- }
- else
- {
- v->next = w;
- v->prev = w;
- w->next = v;
- w->prev = v;
-
- if ((dx < 0) || ((dx == 0) && (dy < 0)))
- {
- result.minXy = v;
- result.maxXy = w;
- }
- else
- {
- result.minXy = w;
- result.maxXy = v;
- }
-
- if ((dy < 0) || ((dy == 0) && (dx < 0)))
- {
- result.minYx = v;
- result.maxYx = w;
- }
- else
- {
- result.minYx = w;
- result.maxYx = v;
- }
- }
-
- Edge* e = newEdgePair(v, w);
- e->link(e);
- v->edges = e;
-
- e = e->reverse;
- e->link(e);
- w->edges = e;
-
- return;
- }
- {
- Vertex* v = originalVertices[start];
- v->edges = NULL;
- v->next = v;
- v->prev = v;
-
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
- }
-
- return;
- }
-
- case 1:
- {
- Vertex* v = originalVertices[start];
- v->edges = NULL;
- v->next = v;
- v->prev = v;
-
- result.minXy = v;
- result.maxXy = v;
- result.minYx = v;
- result.maxYx = v;
-
- return;
- }
- }
-
- int split0 = start + n / 2;
- Point32 p = originalVertices[split0 - 1]->point;
- int split1 = split0;
- while ((split1 < end) && (originalVertices[split1]->point == p))
- {
- split1++;
- }
- computeInternal(start, split0, result);
- IntermediateHull hull1;
- computeInternal(split1, end, hull1);
-#ifdef DEBUG_CONVEX_HULL
- printf("\n\nMerge\n");
- result.print();
- hull1.print();
-#endif
- merge(result, hull1);
-#ifdef DEBUG_CONVEX_HULL
- printf("\n Result\n");
- result.print();
-#endif
-}
-
-#ifdef DEBUG_CONVEX_HULL
-void btConvexHullInternal::IntermediateHull::print()
-{
- printf(" Hull\n");
- for (Vertex* v = minXy; v;)
- {
- printf(" ");
- v->print();
- if (v == maxXy)
- {
- printf(" maxXy");
- }
- if (v == minYx)
- {
- printf(" minYx");
- }
- if (v == maxYx)
- {
- printf(" maxYx");
- }
- if (v->next->prev != v)
- {
- printf(" Inconsistency");
- }
- printf("\n");
- v = v->next;
- if (v == minXy)
- {
- break;
- }
- }
- if (minXy)
- {
- minXy->copy = (minXy->copy == -1) ? -2 : -1;
- minXy->printGraph();
- }
-}
-
-void btConvexHullInternal::Vertex::printGraph()
-{
- print();
- printf("\nEdges\n");
- Edge* e = edges;
- if (e)
- {
- do
- {
- e->print();
- printf("\n");
- e = e->next;
- } while (e != edges);
- do
- {
- Vertex* v = e->target;
- if (v->copy != copy)
- {
- v->copy = copy;
- v->printGraph();
- }
- e = e->next;
- } while (e != edges);
- }
-}
-#endif
-
-btConvexHullInternal::Orientation btConvexHullInternal::getOrientation(const Edge* prev, const Edge* next, const Point32& s, const Point32& t)
-{
- btAssert(prev->reverse->target == next->reverse->target);
- if (prev->next == next)
- {
- if (prev->prev == next)
- {
- Point64 n = t.cross(s);
- Point64 m = (*prev->target - *next->reverse->target).cross(*next->target - *next->reverse->target);
- btAssert(!m.isZero());
- int64_t dot = n.dot(m);
- btAssert(dot != 0);
- return (dot > 0) ? COUNTER_CLOCKWISE : CLOCKWISE;
- }
- return COUNTER_CLOCKWISE;
- }
- else if (prev->prev == next)
- {
- return CLOCKWISE;
- }
- else
- {
- return NONE;
- }
-}
-
-btConvexHullInternal::Edge* btConvexHullInternal::findMaxAngle(bool ccw, const Vertex* start, const Point32& s, const Point64& rxs, const Point64& sxrxs, Rational64& minCot)
-{
- Edge* minEdge = NULL;
-
-#ifdef DEBUG_CONVEX_HULL
- printf("find max edge for %d\n", start->point.index);
-#endif
- Edge* e = start->edges;
- if (e)
- {
- do
- {
- if (e->copy > mergeStamp)
- {
- Point32 t = *e->target - *start;
- Rational64 cot(t.dot(sxrxs), t.dot(rxs));
-#ifdef DEBUG_CONVEX_HULL
- printf(" Angle is %f (%d) for ", (float)btAtan(cot.toScalar()), (int)cot.isNaN());
- e->print();
-#endif
- if (cot.isNaN())
- {
- btAssert(ccw ? (t.dot(s) < 0) : (t.dot(s) > 0));
- }
- else
- {
- int cmp;
- if (minEdge == NULL)
- {
- minCot = cot;
- minEdge = e;
- }
- else if ((cmp = cot.compare(minCot)) < 0)
- {
- minCot = cot;
- minEdge = e;
- }
- else if ((cmp == 0) && (ccw == (getOrientation(minEdge, e, s, t) == COUNTER_CLOCKWISE)))
- {
- minEdge = e;
- }
- }
-#ifdef DEBUG_CONVEX_HULL
- printf("\n");
-#endif
- }
- e = e->next;
- } while (e != start->edges);
- }
- return minEdge;
-}
-
-void btConvexHullInternal::findEdgeForCoplanarFaces(Vertex* c0, Vertex* c1, Edge*& e0, Edge*& e1, Vertex* stop0, Vertex* stop1)
-{
- Edge* start0 = e0;
- Edge* start1 = e1;
- Point32 et0 = start0 ? start0->target->point : c0->point;
- Point32 et1 = start1 ? start1->target->point : c1->point;
- Point32 s = c1->point - c0->point;
- Point64 normal = ((start0 ? start0 : start1)->target->point - c0->point).cross(s);
- int64_t dist = c0->point.dot(normal);
- btAssert(!start1 || (start1->target->point.dot(normal) == dist));
- Point64 perp = s.cross(normal);
- btAssert(!perp.isZero());
-
-#ifdef DEBUG_CONVEX_HULL
- printf(" Advancing %d %d (%p %p, %d %d)\n", c0->point.index, c1->point.index, start0, start1, start0 ? start0->target->point.index : -1, start1 ? start1->target->point.index : -1);
-#endif
-
- int64_t maxDot0 = et0.dot(perp);
- if (e0)
- {
- while (e0->target != stop0)
- {
- Edge* e = e0->reverse->prev;
- if (e->target->point.dot(normal) < dist)
- {
- break;
- }
- btAssert(e->target->point.dot(normal) == dist);
- if (e->copy == mergeStamp)
- {
- break;
- }
- int64_t dot = e->target->point.dot(perp);
- if (dot <= maxDot0)
- {
- break;
- }
- maxDot0 = dot;
- e0 = e;
- et0 = e->target->point;
- }
- }
-
- int64_t maxDot1 = et1.dot(perp);
- if (e1)
- {
- while (e1->target != stop1)
- {
- Edge* e = e1->reverse->next;
- if (e->target->point.dot(normal) < dist)
- {
- break;
- }
- btAssert(e->target->point.dot(normal) == dist);
- if (e->copy == mergeStamp)
- {
- break;
- }
- int64_t dot = e->target->point.dot(perp);
- if (dot <= maxDot1)
- {
- break;
- }
- maxDot1 = dot;
- e1 = e;
- et1 = e->target->point;
- }
- }
-
-#ifdef DEBUG_CONVEX_HULL
- printf(" Starting at %d %d\n", et0.index, et1.index);
-#endif
-
- int64_t dx = maxDot1 - maxDot0;
- if (dx > 0)
- {
- while (true)
- {
- int64_t dy = (et1 - et0).dot(s);
-
- if (e0 && (e0->target != stop0))
- {
- Edge* f0 = e0->next->reverse;
- if (f0->copy > mergeStamp)
- {
- int64_t dx0 = (f0->target->point - et0).dot(perp);
- int64_t dy0 = (f0->target->point - et0).dot(s);
- if ((dx0 == 0) ? (dy0 < 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) >= 0)))
- {
- et0 = f0->target->point;
- dx = (et1 - et0).dot(perp);
- e0 = (e0 == start0) ? NULL : f0;
- continue;
- }
- }
- }
-
- if (e1 && (e1->target != stop1))
- {
- Edge* f1 = e1->reverse->next;
- if (f1->copy > mergeStamp)
- {
- Point32 d1 = f1->target->point - et1;
- if (d1.dot(normal) == 0)
- {
- int64_t dx1 = d1.dot(perp);
- int64_t dy1 = d1.dot(s);
- int64_t dxn = (f1->target->point - et0).dot(perp);
- if ((dxn > 0) && ((dx1 == 0) ? (dy1 < 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) > 0))))
- {
- e1 = f1;
- et1 = e1->target->point;
- dx = dxn;
- continue;
- }
- }
- else
- {
- btAssert((e1 == start1) && (d1.dot(normal) < 0));
- }
- }
- }
-
- break;
- }
- }
- else if (dx < 0)
- {
- while (true)
- {
- int64_t dy = (et1 - et0).dot(s);
-
- if (e1 && (e1->target != stop1))
- {
- Edge* f1 = e1->prev->reverse;
- if (f1->copy > mergeStamp)
- {
- int64_t dx1 = (f1->target->point - et1).dot(perp);
- int64_t dy1 = (f1->target->point - et1).dot(s);
- if ((dx1 == 0) ? (dy1 > 0) : ((dx1 < 0) && (Rational64(dy1, dx1).compare(Rational64(dy, dx)) <= 0)))
- {
- et1 = f1->target->point;
- dx = (et1 - et0).dot(perp);
- e1 = (e1 == start1) ? NULL : f1;
- continue;
- }
- }
- }
-
- if (e0 && (e0->target != stop0))
- {
- Edge* f0 = e0->reverse->prev;
- if (f0->copy > mergeStamp)
- {
- Point32 d0 = f0->target->point - et0;
- if (d0.dot(normal) == 0)
- {
- int64_t dx0 = d0.dot(perp);
- int64_t dy0 = d0.dot(s);
- int64_t dxn = (et1 - f0->target->point).dot(perp);
- if ((dxn < 0) && ((dx0 == 0) ? (dy0 > 0) : ((dx0 < 0) && (Rational64(dy0, dx0).compare(Rational64(dy, dx)) < 0))))
- {
- e0 = f0;
- et0 = e0->target->point;
- dx = dxn;
- continue;
- }
- }
- else
- {
- btAssert((e0 == start0) && (d0.dot(normal) < 0));
- }
- }
- }
-
- break;
- }
- }
-#ifdef DEBUG_CONVEX_HULL
- printf(" Advanced edges to %d %d\n", et0.index, et1.index);
-#endif
-}
-
-void btConvexHullInternal::merge(IntermediateHull& h0, IntermediateHull& h1)
-{
- if (!h1.maxXy)
- {
- return;
- }
- if (!h0.maxXy)
- {
- h0 = h1;
- return;
- }
-
- mergeStamp--;
-
- Vertex* c0 = NULL;
- Edge* toPrev0 = NULL;
- Edge* firstNew0 = NULL;
- Edge* pendingHead0 = NULL;
- Edge* pendingTail0 = NULL;
- Vertex* c1 = NULL;
- Edge* toPrev1 = NULL;
- Edge* firstNew1 = NULL;
- Edge* pendingHead1 = NULL;
- Edge* pendingTail1 = NULL;
- Point32 prevPoint;
-
- if (mergeProjection(h0, h1, c0, c1))
- {
- Point32 s = *c1 - *c0;
- Point64 normal = Point32(0, 0, -1).cross(s);
- Point64 t = s.cross(normal);
- btAssert(!t.isZero());
-
- Edge* e = c0->edges;
- Edge* start0 = NULL;
- if (e)
- {
- do
- {
- int64_t dot = (*e->target - *c0).dot(normal);
- btAssert(dot <= 0);
- if ((dot == 0) && ((*e->target - *c0).dot(t) > 0))
- {
- if (!start0 || (getOrientation(start0, e, s, Point32(0, 0, -1)) == CLOCKWISE))
- {
- start0 = e;
- }
- }
- e = e->next;
- } while (e != c0->edges);
- }
-
- e = c1->edges;
- Edge* start1 = NULL;
- if (e)
- {
- do
- {
- int64_t dot = (*e->target - *c1).dot(normal);
- btAssert(dot <= 0);
- if ((dot == 0) && ((*e->target - *c1).dot(t) > 0))
- {
- if (!start1 || (getOrientation(start1, e, s, Point32(0, 0, -1)) == COUNTER_CLOCKWISE))
- {
- start1 = e;
- }
- }
- e = e->next;
- } while (e != c1->edges);
- }
-
- if (start0 || start1)
- {
- findEdgeForCoplanarFaces(c0, c1, start0, start1, NULL, NULL);
- if (start0)
- {
- c0 = start0->target;
- }
- if (start1)
- {
- c1 = start1->target;
- }
- }
-
- prevPoint = c1->point;
- prevPoint.z++;
- }
- else
- {
- prevPoint = c1->point;
- prevPoint.x++;
- }
-
- Vertex* first0 = c0;
- Vertex* first1 = c1;
- bool firstRun = true;
-
- while (true)
- {
- Point32 s = *c1 - *c0;
- Point32 r = prevPoint - c0->point;
- Point64 rxs = r.cross(s);
- Point64 sxrxs = s.cross(rxs);
-
-#ifdef DEBUG_CONVEX_HULL
- printf("\n Checking %d %d\n", c0->point.index, c1->point.index);
-#endif
- Rational64 minCot0(0, 0);
- Edge* min0 = findMaxAngle(false, c0, s, rxs, sxrxs, minCot0);
- Rational64 minCot1(0, 0);
- Edge* min1 = findMaxAngle(true, c1, s, rxs, sxrxs, minCot1);
- if (!min0 && !min1)
- {
- Edge* e = newEdgePair(c0, c1);
- e->link(e);
- c0->edges = e;
-
- e = e->reverse;
- e->link(e);
- c1->edges = e;
- return;
- }
- else
- {
- int cmp = !min0 ? 1 : !min1 ? -1 : minCot0.compare(minCot1);
-#ifdef DEBUG_CONVEX_HULL
- printf(" -> Result %d\n", cmp);
-#endif
- if (firstRun || ((cmp >= 0) ? !minCot1.isNegativeInfinity() : !minCot0.isNegativeInfinity()))
- {
- Edge* e = newEdgePair(c0, c1);
- if (pendingTail0)
- {
- pendingTail0->prev = e;
- }
- else
- {
- pendingHead0 = e;
- }
- e->next = pendingTail0;
- pendingTail0 = e;
-
- e = e->reverse;
- if (pendingTail1)
- {
- pendingTail1->next = e;
- }
- else
- {
- pendingHead1 = e;
- }
- e->prev = pendingTail1;
- pendingTail1 = e;
- }
-
- Edge* e0 = min0;
- Edge* e1 = min1;
-
-#ifdef DEBUG_CONVEX_HULL
- printf(" Found min edges to %d %d\n", e0 ? e0->target->point.index : -1, e1 ? e1->target->point.index : -1);
-#endif
-
- if (cmp == 0)
- {
- findEdgeForCoplanarFaces(c0, c1, e0, e1, NULL, NULL);
- }
-
- if ((cmp >= 0) && e1)
- {
- if (toPrev1)
- {
- for (Edge *e = toPrev1->next, *n = NULL; e != min1; e = n)
- {
- n = e->next;
- removeEdgePair(e);
- }
- }
-
- if (pendingTail1)
- {
- if (toPrev1)
- {
- toPrev1->link(pendingHead1);
- }
- else
- {
- min1->prev->link(pendingHead1);
- firstNew1 = pendingHead1;
- }
- pendingTail1->link(min1);
- pendingHead1 = NULL;
- pendingTail1 = NULL;
- }
- else if (!toPrev1)
- {
- firstNew1 = min1;
- }
-
- prevPoint = c1->point;
- c1 = e1->target;
- toPrev1 = e1->reverse;
- }
-
- if ((cmp <= 0) && e0)
- {
- if (toPrev0)
- {
- for (Edge *e = toPrev0->prev, *n = NULL; e != min0; e = n)
- {
- n = e->prev;
- removeEdgePair(e);
- }
- }
-
- if (pendingTail0)
- {
- if (toPrev0)
- {
- pendingHead0->link(toPrev0);
- }
- else
- {
- pendingHead0->link(min0->next);
- firstNew0 = pendingHead0;
- }
- min0->link(pendingTail0);
- pendingHead0 = NULL;
- pendingTail0 = NULL;
- }
- else if (!toPrev0)
- {
- firstNew0 = min0;
- }
-
- prevPoint = c0->point;
- c0 = e0->target;
- toPrev0 = e0->reverse;
- }
- }
-
- if ((c0 == first0) && (c1 == first1))
- {
- if (toPrev0 == NULL)
- {
- pendingHead0->link(pendingTail0);
- c0->edges = pendingTail0;
- }
- else
- {
- for (Edge *e = toPrev0->prev, *n = NULL; e != firstNew0; e = n)
- {
- n = e->prev;
- removeEdgePair(e);
- }
- if (pendingTail0)
- {
- pendingHead0->link(toPrev0);
- firstNew0->link(pendingTail0);
- }
- }
-
- if (toPrev1 == NULL)
- {
- pendingTail1->link(pendingHead1);
- c1->edges = pendingTail1;
- }
- else
- {
- for (Edge *e = toPrev1->next, *n = NULL; e != firstNew1; e = n)
- {
- n = e->next;
- removeEdgePair(e);
- }
- if (pendingTail1)
- {
- toPrev1->link(pendingHead1);
- pendingTail1->link(firstNew1);
- }
- }
-
- return;
- }
-
- firstRun = false;
- }
-}
-
-class pointCmp
-{
-public:
- bool operator()(const btConvexHullInternal::Point32& p, const btConvexHullInternal::Point32& q) const
- {
- return (p.y < q.y) || ((p.y == q.y) && ((p.x < q.x) || ((p.x == q.x) && (p.z < q.z))));
- }
-};
-
-void btConvexHullInternal::compute(const void* coords, bool doubleCoords, int stride, int count)
-{
- btVector3 min(btScalar(1e30), btScalar(1e30), btScalar(1e30)), max(btScalar(-1e30), btScalar(-1e30), btScalar(-1e30));
- const char* ptr = (const char*)coords;
- if (doubleCoords)
- {
- for (int i = 0; i < count; i++)
- {
- const double* v = (const double*)ptr;
- btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
- ptr += stride;
- min.setMin(p);
- max.setMax(p);
- }
- }
- else
- {
- for (int i = 0; i < count; i++)
- {
- const float* v = (const float*)ptr;
- btVector3 p(v[0], v[1], v[2]);
- ptr += stride;
- min.setMin(p);
- max.setMax(p);
- }
- }
-
- btVector3 s = max - min;
- maxAxis = s.maxAxis();
- minAxis = s.minAxis();
- if (minAxis == maxAxis)
- {
- minAxis = (maxAxis + 1) % 3;
- }
- medAxis = 3 - maxAxis - minAxis;
-
- s /= btScalar(10216);
- if (((medAxis + 1) % 3) != maxAxis)
- {
- s *= -1;
- }
- scaling = s;
-
- if (s[0] != 0)
- {
- s[0] = btScalar(1) / s[0];
- }
- if (s[1] != 0)
- {
- s[1] = btScalar(1) / s[1];
- }
- if (s[2] != 0)
- {
- s[2] = btScalar(1) / s[2];
- }
-
- center = (min + max) * btScalar(0.5);
-
- btAlignedObjectArray<Point32> points;
- points.resize(count);
- ptr = (const char*)coords;
- if (doubleCoords)
- {
- for (int i = 0; i < count; i++)
- {
- const double* v = (const double*)ptr;
- btVector3 p((btScalar)v[0], (btScalar)v[1], (btScalar)v[2]);
- ptr += stride;
- p = (p - center) * s;
- points[i].x = (int32_t)p[medAxis];
- points[i].y = (int32_t)p[maxAxis];
- points[i].z = (int32_t)p[minAxis];
- points[i].index = i;
- }
- }
- else
- {
- for (int i = 0; i < count; i++)
- {
- const float* v = (const float*)ptr;
- btVector3 p(v[0], v[1], v[2]);
- ptr += stride;
- p = (p - center) * s;
- points[i].x = (int32_t)p[medAxis];
- points[i].y = (int32_t)p[maxAxis];
- points[i].z = (int32_t)p[minAxis];
- points[i].index = i;
- }
- }
- points.quickSort(pointCmp());
-
- vertexPool.reset();
- vertexPool.setArraySize(count);
- originalVertices.resize(count);
- for (int i = 0; i < count; i++)
- {
- Vertex* v = vertexPool.newObject();
- v->edges = NULL;
- v->point = points[i];
- v->copy = -1;
- originalVertices[i] = v;
- }
-
- points.clear();
-
- edgePool.reset();
- edgePool.setArraySize(6 * count);
-
- usedEdgePairs = 0;
- maxUsedEdgePairs = 0;
-
- mergeStamp = -3;
-
- IntermediateHull hull;
- computeInternal(0, count, hull);
- vertexList = hull.minXy;
-#ifdef DEBUG_CONVEX_HULL
- printf("max. edges %d (3v = %d)", maxUsedEdgePairs, 3 * count);
-#endif
-}
-
-btVector3 btConvexHullInternal::toBtVector(const Point32& v)
-{
- btVector3 p;
- p[medAxis] = btScalar(v.x);
- p[maxAxis] = btScalar(v.y);
- p[minAxis] = btScalar(v.z);
- return p * scaling;
-}
-
-btVector3 btConvexHullInternal::getBtNormal(Face* face)
-{
- return toBtVector(face->dir0).cross(toBtVector(face->dir1)).normalized();
-}
-
-btVector3 btConvexHullInternal::getCoordinates(const Vertex* v)
-{
- btVector3 p;
- p[medAxis] = v->xvalue();
- p[maxAxis] = v->yvalue();
- p[minAxis] = v->zvalue();
- return p * scaling + center;
-}
-
-btScalar btConvexHullInternal::shrink(btScalar amount, btScalar clampAmount)
-{
- if (!vertexList)
- {
- return 0;
- }
- int stamp = --mergeStamp;
- btAlignedObjectArray<Vertex*> stack;
- vertexList->copy = stamp;
- stack.push_back(vertexList);
- btAlignedObjectArray<Face*> faces;
-
- Point32 ref = vertexList->point;
- Int128 hullCenterX(0, 0);
- Int128 hullCenterY(0, 0);
- Int128 hullCenterZ(0, 0);
- Int128 volume(0, 0);
-
- while (stack.size() > 0)
- {
- Vertex* v = stack[stack.size() - 1];
- stack.pop_back();
- Edge* e = v->edges;
- if (e)
- {
- do
- {
- if (e->target->copy != stamp)
- {
- e->target->copy = stamp;
- stack.push_back(e->target);
- }
- if (e->copy != stamp)
- {
- Face* face = facePool.newObject();
- face->init(e->target, e->reverse->prev->target, v);
- faces.push_back(face);
- Edge* f = e;
-
- Vertex* a = NULL;
- Vertex* b = NULL;
- do
- {
- if (a && b)
- {
- int64_t vol = (v->point - ref).dot((a->point - ref).cross(b->point - ref));
- btAssert(vol >= 0);
- Point32 c = v->point + a->point + b->point + ref;
- hullCenterX += vol * c.x;
- hullCenterY += vol * c.y;
- hullCenterZ += vol * c.z;
- volume += vol;
- }
-
- btAssert(f->copy != stamp);
- f->copy = stamp;
- f->face = face;
-
- a = b;
- b = f->target;
-
- f = f->reverse->prev;
- } while (f != e);
- }
- e = e->next;
- } while (e != v->edges);
- }
- }
-
- if (volume.getSign() <= 0)
- {
- return 0;
- }
-
- btVector3 hullCenter;
- hullCenter[medAxis] = hullCenterX.toScalar();
- hullCenter[maxAxis] = hullCenterY.toScalar();
- hullCenter[minAxis] = hullCenterZ.toScalar();
- hullCenter /= 4 * volume.toScalar();
- hullCenter *= scaling;
-
- int faceCount = faces.size();
-
- if (clampAmount > 0)
- {
- btScalar minDist = SIMD_INFINITY;
- for (int i = 0; i < faceCount; i++)
- {
- btVector3 normal = getBtNormal(faces[i]);
- btScalar dist = normal.dot(toBtVector(faces[i]->origin) - hullCenter);
- if (dist < minDist)
- {
- minDist = dist;
- }
- }
-
- if (minDist <= 0)
- {
- return 0;
- }
-
- amount = btMin(amount, minDist * clampAmount);
- }
-
- unsigned int seed = 243703;
- for (int i = 0; i < faceCount; i++, seed = 1664525 * seed + 1013904223)
- {
- btSwap(faces[i], faces[seed % faceCount]);
- }
-
- for (int i = 0; i < faceCount; i++)
- {
- if (!shiftFace(faces[i], amount, stack))
- {
- return -amount;
- }
- }
-
- return amount;
-}
-
-bool btConvexHullInternal::shiftFace(Face* face, btScalar amount, btAlignedObjectArray<Vertex*> stack)
-{
- btVector3 origShift = getBtNormal(face) * -amount;
- if (scaling[0] != 0)
- {
- origShift[0] /= scaling[0];
- }
- if (scaling[1] != 0)
- {
- origShift[1] /= scaling[1];
- }
- if (scaling[2] != 0)
- {
- origShift[2] /= scaling[2];
- }
- Point32 shift((int32_t)origShift[medAxis], (int32_t)origShift[maxAxis], (int32_t)origShift[minAxis]);
- if (shift.isZero())
- {
- return true;
- }
- Point64 normal = face->getNormal();
-#ifdef DEBUG_CONVEX_HULL
- printf("\nShrinking face (%d %d %d) (%d %d %d) (%d %d %d) by (%d %d %d)\n",
- face->origin.x, face->origin.y, face->origin.z, face->dir0.x, face->dir0.y, face->dir0.z, face->dir1.x, face->dir1.y, face->dir1.z, shift.x, shift.y, shift.z);
-#endif
- int64_t origDot = face->origin.dot(normal);
- Point32 shiftedOrigin = face->origin + shift;
- int64_t shiftedDot = shiftedOrigin.dot(normal);
- btAssert(shiftedDot <= origDot);
- if (shiftedDot >= origDot)
- {
- return false;
- }
-
- Edge* intersection = NULL;
-
- Edge* startEdge = face->nearbyVertex->edges;
-#ifdef DEBUG_CONVEX_HULL
- printf("Start edge is ");
- startEdge->print();
- printf(", normal is (%lld %lld %lld), shifted dot is %lld\n", normal.x, normal.y, normal.z, shiftedDot);
-#endif
- Rational128 optDot = face->nearbyVertex->dot(normal);
- int cmp = optDot.compare(shiftedDot);
-#ifdef SHOW_ITERATIONS
- int n = 0;
-#endif
- if (cmp >= 0)
- {
- Edge* e = startEdge;
- do
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- Rational128 dot = e->target->dot(normal);
- btAssert(dot.compare(origDot) <= 0);
-#ifdef DEBUG_CONVEX_HULL
- printf("Moving downwards, edge is ");
- e->print();
- printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
-#endif
- if (dot.compare(optDot) < 0)
- {
- int c = dot.compare(shiftedDot);
- optDot = dot;
- e = e->reverse;
- startEdge = e;
- if (c < 0)
- {
- intersection = e;
- break;
- }
- cmp = c;
- }
- e = e->prev;
- } while (e != startEdge);
-
- if (!intersection)
- {
- return false;
- }
- }
- else
- {
- Edge* e = startEdge;
- do
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- Rational128 dot = e->target->dot(normal);
- btAssert(dot.compare(origDot) <= 0);
-#ifdef DEBUG_CONVEX_HULL
- printf("Moving upwards, edge is ");
- e->print();
- printf(", dot is %f (%f %lld)\n", (float)dot.toScalar(), (float)optDot.toScalar(), shiftedDot);
-#endif
- if (dot.compare(optDot) > 0)
- {
- cmp = dot.compare(shiftedDot);
- if (cmp >= 0)
- {
- intersection = e;
- break;
- }
- optDot = dot;
- e = e->reverse;
- startEdge = e;
- }
- e = e->prev;
- } while (e != startEdge);
-
- if (!intersection)
- {
- return true;
- }
- }
-
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to find initial intersection\n", n);
-#endif
-
- if (cmp == 0)
- {
- Edge* e = intersection->reverse->next;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (e->target->dot(normal).compare(shiftedDot) <= 0)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- e = e->next;
- if (e == intersection->reverse)
- {
- return true;
- }
-#ifdef DEBUG_CONVEX_HULL
- printf("Checking for outwards edge, current edge is ");
- e->print();
- printf("\n");
-#endif
- }
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to check for complete containment\n", n);
-#endif
- }
-
- Edge* firstIntersection = NULL;
- Edge* faceEdge = NULL;
- Edge* firstFaceEdge = NULL;
-
-#ifdef SHOW_ITERATIONS
- int m = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- m++;
-#endif
-#ifdef DEBUG_CONVEX_HULL
- printf("Intersecting edge is ");
- intersection->print();
- printf("\n");
-#endif
- if (cmp == 0)
- {
- Edge* e = intersection->reverse->next;
- startEdge = e;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- if (e->target->dot(normal).compare(shiftedDot) >= 0)
- {
- break;
- }
- intersection = e->reverse;
- e = e->next;
- if (e == startEdge)
- {
- return true;
- }
- }
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to advance intersection\n", n);
-#endif
- }
-
-#ifdef DEBUG_CONVEX_HULL
- printf("Advanced intersecting edge to ");
- intersection->print();
- printf(", cmp = %d\n", cmp);
-#endif
-
- if (!firstIntersection)
- {
- firstIntersection = intersection;
- }
- else if (intersection == firstIntersection)
- {
- break;
- }
-
- int prevCmp = cmp;
- Edge* prevIntersection = intersection;
- Edge* prevFaceEdge = faceEdge;
-
- Edge* e = intersection->reverse;
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- while (true)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- e = e->reverse->prev;
- btAssert(e != intersection->reverse);
- cmp = e->target->dot(normal).compare(shiftedDot);
-#ifdef DEBUG_CONVEX_HULL
- printf("Testing edge ");
- e->print();
- printf(" -> cmp = %d\n", cmp);
-#endif
- if (cmp >= 0)
- {
- intersection = e;
- break;
- }
- }
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to find other intersection of face\n", n);
-#endif
-
- if (cmp > 0)
- {
- Vertex* removed = intersection->target;
- e = intersection->reverse;
- if (e->prev == e)
- {
- removed->edges = NULL;
- }
- else
- {
- removed->edges = e->prev;
- e->prev->link(e->next);
- e->link(e);
- }
-#ifdef DEBUG_CONVEX_HULL
- printf("1: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
-
- Point64 n0 = intersection->face->getNormal();
- Point64 n1 = intersection->reverse->face->getNormal();
- int64_t m00 = face->dir0.dot(n0);
- int64_t m01 = face->dir1.dot(n0);
- int64_t m10 = face->dir0.dot(n1);
- int64_t m11 = face->dir1.dot(n1);
- int64_t r0 = (intersection->face->origin - shiftedOrigin).dot(n0);
- int64_t r1 = (intersection->reverse->face->origin - shiftedOrigin).dot(n1);
- Int128 det = Int128::mul(m00, m11) - Int128::mul(m01, m10);
- btAssert(det.getSign() != 0);
- Vertex* v = vertexPool.newObject();
- v->point.index = -1;
- v->copy = -1;
- v->point128 = PointR128(Int128::mul(face->dir0.x * r0, m11) - Int128::mul(face->dir0.x * r1, m01) + Int128::mul(face->dir1.x * r1, m00) - Int128::mul(face->dir1.x * r0, m10) + det * shiftedOrigin.x,
- Int128::mul(face->dir0.y * r0, m11) - Int128::mul(face->dir0.y * r1, m01) + Int128::mul(face->dir1.y * r1, m00) - Int128::mul(face->dir1.y * r0, m10) + det * shiftedOrigin.y,
- Int128::mul(face->dir0.z * r0, m11) - Int128::mul(face->dir0.z * r1, m01) + Int128::mul(face->dir1.z * r1, m00) - Int128::mul(face->dir1.z * r0, m10) + det * shiftedOrigin.z,
- det);
- v->point.x = (int32_t)v->point128.xvalue();
- v->point.y = (int32_t)v->point128.yvalue();
- v->point.z = (int32_t)v->point128.zvalue();
- intersection->target = v;
- v->edges = e;
-
- stack.push_back(v);
- stack.push_back(removed);
- stack.push_back(NULL);
- }
-
- if (cmp || prevCmp || (prevIntersection->reverse->next->target != intersection->target))
- {
- faceEdge = newEdgePair(prevIntersection->target, intersection->target);
- if (prevCmp == 0)
- {
- faceEdge->link(prevIntersection->reverse->next);
- }
- if ((prevCmp == 0) || prevFaceEdge)
- {
- prevIntersection->reverse->link(faceEdge);
- }
- if (cmp == 0)
- {
- intersection->reverse->prev->link(faceEdge->reverse);
- }
- faceEdge->reverse->link(intersection->reverse);
- }
- else
- {
- faceEdge = prevIntersection->reverse->next;
- }
-
- if (prevFaceEdge)
- {
- if (prevCmp > 0)
- {
- faceEdge->link(prevFaceEdge->reverse);
- }
- else if (faceEdge != prevFaceEdge->reverse)
- {
- stack.push_back(prevFaceEdge->target);
- while (faceEdge->next != prevFaceEdge->reverse)
- {
- Vertex* removed = faceEdge->next->target;
- removeEdgePair(faceEdge->next);
- stack.push_back(removed);
-#ifdef DEBUG_CONVEX_HULL
- printf("2: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
- }
- stack.push_back(NULL);
- }
- }
- faceEdge->face = face;
- faceEdge->reverse->face = intersection->face;
-
- if (!firstFaceEdge)
- {
- firstFaceEdge = faceEdge;
- }
- }
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to process all intersections\n", m);
-#endif
-
- if (cmp > 0)
- {
- firstFaceEdge->reverse->target = faceEdge->target;
- firstIntersection->reverse->link(firstFaceEdge);
- firstFaceEdge->link(faceEdge->reverse);
- }
- else if (firstFaceEdge != faceEdge->reverse)
- {
- stack.push_back(faceEdge->target);
- while (firstFaceEdge->next != faceEdge->reverse)
- {
- Vertex* removed = firstFaceEdge->next->target;
- removeEdgePair(firstFaceEdge->next);
- stack.push_back(removed);
-#ifdef DEBUG_CONVEX_HULL
- printf("3: Removed part contains (%d %d %d)\n", removed->point.x, removed->point.y, removed->point.z);
-#endif
- }
- stack.push_back(NULL);
- }
-
- btAssert(stack.size() > 0);
- vertexList = stack[0];
-
-#ifdef DEBUG_CONVEX_HULL
- printf("Removing part\n");
-#endif
-#ifdef SHOW_ITERATIONS
- n = 0;
-#endif
- int pos = 0;
- while (pos < stack.size())
- {
- int end = stack.size();
- while (pos < end)
- {
- Vertex* kept = stack[pos++];
-#ifdef DEBUG_CONVEX_HULL
- kept->print();
-#endif
- bool deeper = false;
- Vertex* removed;
- while ((removed = stack[pos++]) != NULL)
- {
-#ifdef SHOW_ITERATIONS
- n++;
-#endif
- kept->receiveNearbyFaces(removed);
- while (removed->edges)
- {
- if (!deeper)
- {
- deeper = true;
- stack.push_back(kept);
- }
- stack.push_back(removed->edges->target);
- removeEdgePair(removed->edges);
- }
- }
- if (deeper)
- {
- stack.push_back(NULL);
- }
- }
- }
-#ifdef SHOW_ITERATIONS
- printf("Needed %d iterations to remove part\n", n);
-#endif
-
- stack.resize(0);
- face->origin = shiftedOrigin;
-
- return true;
-}
-
-static int getVertexCopy(btConvexHullInternal::Vertex* vertex, btAlignedObjectArray<btConvexHullInternal::Vertex*>& vertices)
-{
- int index = vertex->copy;
- if (index < 0)
- {
- index = vertices.size();
- vertex->copy = index;
- vertices.push_back(vertex);
-#ifdef DEBUG_CONVEX_HULL
- printf("Vertex %d gets index *%d\n", vertex->point.index, index);
-#endif
- }
- return index;
-}
-
-btScalar btConvexHullComputer::compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
-{
- if (count <= 0)
- {
- vertices.clear();
- edges.clear();
- faces.clear();
- return 0;
- }
-
- btConvexHullInternal hull;
- hull.compute(coords, doubleCoords, stride, count);
-
- btScalar shift = 0;
- if ((shrink > 0) && ((shift = hull.shrink(shrink, shrinkClamp)) < 0))
- {
- vertices.clear();
- edges.clear();
- faces.clear();
- return shift;
- }
-
- vertices.resize(0);
- original_vertex_index.resize(0);
- edges.resize(0);
- faces.resize(0);
-
- btAlignedObjectArray<btConvexHullInternal::Vertex*> oldVertices;
- getVertexCopy(hull.vertexList, oldVertices);
- int copied = 0;
- while (copied < oldVertices.size())
- {
- btConvexHullInternal::Vertex* v = oldVertices[copied];
- vertices.push_back(hull.getCoordinates(v));
- original_vertex_index.push_back(v->point.index);
- btConvexHullInternal::Edge* firstEdge = v->edges;
- if (firstEdge)
- {
- int firstCopy = -1;
- int prevCopy = -1;
- btConvexHullInternal::Edge* e = firstEdge;
- do
- {
- if (e->copy < 0)
- {
- int s = edges.size();
- edges.push_back(Edge());
- edges.push_back(Edge());
- Edge* c = &edges[s];
- Edge* r = &edges[s + 1];
- e->copy = s;
- e->reverse->copy = s + 1;
- c->reverse = 1;
- r->reverse = -1;
- c->targetVertex = getVertexCopy(e->target, oldVertices);
- r->targetVertex = copied;
-#ifdef DEBUG_CONVEX_HULL
- printf(" CREATE: Vertex *%d has edge to *%d\n", copied, c->getTargetVertex());
-#endif
- }
- if (prevCopy >= 0)
- {
- edges[e->copy].next = prevCopy - e->copy;
- }
- else
- {
- firstCopy = e->copy;
- }
- prevCopy = e->copy;
- e = e->next;
- } while (e != firstEdge);
- edges[firstCopy].next = prevCopy - firstCopy;
- }
- copied++;
- }
-
- for (int i = 0; i < copied; i++)
- {
- btConvexHullInternal::Vertex* v = oldVertices[i];
- btConvexHullInternal::Edge* firstEdge = v->edges;
- if (firstEdge)
- {
- btConvexHullInternal::Edge* e = firstEdge;
- do
- {
- if (e->copy >= 0)
- {
-#ifdef DEBUG_CONVEX_HULL
- printf("Vertex *%d has edge to *%d\n", i, edges[e->copy].getTargetVertex());
-#endif
- faces.push_back(e->copy);
- btConvexHullInternal::Edge* f = e;
- do
- {
-#ifdef DEBUG_CONVEX_HULL
- printf(" Face *%d\n", edges[f->copy].getTargetVertex());
-#endif
- f->copy = -1;
- f = f->reverse->prev;
- } while (f != e);
- }
- e = e->next;
- } while (e != firstEdge);
- }
- }
-
- return shift;
-}
diff --git a/thirdparty/bullet/LinearMath/btConvexHullComputer.h b/thirdparty/bullet/LinearMath/btConvexHullComputer.h
deleted file mode 100644
index 18b26eea9a..0000000000
--- a/thirdparty/bullet/LinearMath/btConvexHullComputer.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
-Copyright (c) 2011 Ole Kniemeyer, MAXON, www.maxon.net
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_CONVEX_HULL_COMPUTER_H
-#define BT_CONVEX_HULL_COMPUTER_H
-
-#include "btVector3.h"
-#include "btAlignedObjectArray.h"
-
-/// Convex hull implementation based on Preparata and Hong
-/// See http://code.google.com/p/bullet/issues/detail?id=275
-/// Ole Kniemeyer, MAXON Computer GmbH
-class btConvexHullComputer
-{
-private:
- btScalar compute(const void* coords, bool doubleCoords, int stride, int count, btScalar shrink, btScalar shrinkClamp);
-
-public:
- class Edge
- {
- private:
- int next;
- int reverse;
- int targetVertex;
-
- friend class btConvexHullComputer;
-
- public:
- int getSourceVertex() const
- {
- return (this + reverse)->targetVertex;
- }
-
- int getTargetVertex() const
- {
- return targetVertex;
- }
-
- const Edge* getNextEdgeOfVertex() const // clockwise list of all edges of a vertex
- {
- return this + next;
- }
-
- const Edge* getNextEdgeOfFace() const // counter-clockwise list of all edges of a face
- {
- return (this + reverse)->getNextEdgeOfVertex();
- }
-
- const Edge* getReverseEdge() const
- {
- return this + reverse;
- }
- };
-
- // Vertices of the output hull
- btAlignedObjectArray<btVector3> vertices;
-
- // The original vertex index in the input coords array
- btAlignedObjectArray<int> original_vertex_index;
-
- // Edges of the output hull
- btAlignedObjectArray<Edge> edges;
-
- // Faces of the convex hull. Each entry is an index into the "edges" array pointing to an edge of the face. Faces are planar n-gons
- btAlignedObjectArray<int> faces;
-
- /*
- Compute convex hull of "count" vertices stored in "coords". "stride" is the difference in bytes
- between the addresses of consecutive vertices. If "shrink" is positive, the convex hull is shrunken
- by that amount (each face is moved by "shrink" length units towards the center along its normal).
- If "shrinkClamp" is positive, "shrink" is clamped to not exceed "shrinkClamp * innerRadius", where "innerRadius"
- is the minimum distance of a face to the center of the convex hull.
-
- The returned value is the amount by which the hull has been shrunken. If it is negative, the amount was so large
- that the resulting convex hull is empty.
-
- The output convex hull can be found in the member variables "vertices", "edges", "faces".
- */
- btScalar compute(const float* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
- {
- return compute(coords, false, stride, count, shrink, shrinkClamp);
- }
-
- // same as above, but double precision
- btScalar compute(const double* coords, int stride, int count, btScalar shrink, btScalar shrinkClamp)
- {
- return compute(coords, true, stride, count, shrink, shrinkClamp);
- }
-};
-
-#endif //BT_CONVEX_HULL_COMPUTER_H
diff --git a/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h b/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h
deleted file mode 100644
index 5e4b9a313c..0000000000
--- a/thirdparty/bullet/LinearMath/btCpuFeatureUtility.h
+++ /dev/null
@@ -1,88 +0,0 @@
-
-#ifndef BT_CPU_UTILITY_H
-#define BT_CPU_UTILITY_H
-
-#include "LinearMath/btScalar.h"
-
-#include <string.h> //memset
-#ifdef USE_SIMD
-#include <emmintrin.h>
-#ifdef BT_ALLOW_SSE4
-#include <intrin.h>
-#endif //BT_ALLOW_SSE4
-#endif //USE_SIMD
-
-#if defined BT_USE_NEON
-#define ARM_NEON_GCC_COMPATIBILITY 1
-#include <arm_neon.h>
-#include <sys/types.h>
-#include <sys/sysctl.h> //for sysctlbyname
-#endif //BT_USE_NEON
-
-///Rudimentary btCpuFeatureUtility for CPU features: only report the features that Bullet actually uses (SSE4/FMA3, NEON_HPFP)
-///We assume SSE2 in case BT_USE_SSE2 is defined in LinearMath/btScalar.h
-class btCpuFeatureUtility
-{
-public:
- enum btCpuFeature
- {
- CPU_FEATURE_FMA3 = 1,
- CPU_FEATURE_SSE4_1 = 2,
- CPU_FEATURE_NEON_HPFP = 4
- };
-
- static int getCpuFeatures()
- {
- static int capabilities = 0;
- static bool testedCapabilities = false;
- if (0 != testedCapabilities)
- {
- return capabilities;
- }
-
-#ifdef BT_USE_NEON
- {
- uint32_t hasFeature = 0;
- size_t featureSize = sizeof(hasFeature);
- int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
- if (0 == err && hasFeature)
- capabilities |= CPU_FEATURE_NEON_HPFP;
- }
-#endif //BT_USE_NEON
-
-#ifdef BT_ALLOW_SSE4
- {
- int cpuInfo[4];
- memset(cpuInfo, 0, sizeof(cpuInfo));
- unsigned long long sseExt = 0;
- __cpuid(cpuInfo, 1);
-
- bool osUsesXSAVE_XRSTORE = cpuInfo[2] & (1 << 27) || false;
- bool cpuAVXSuport = cpuInfo[2] & (1 << 28) || false;
-
- if (osUsesXSAVE_XRSTORE && cpuAVXSuport)
- {
- sseExt = _xgetbv(0);
- }
- const int OSXSAVEFlag = (1UL << 27);
- const int AVXFlag = ((1UL << 28) | OSXSAVEFlag);
- const int FMAFlag = ((1UL << 12) | AVXFlag | OSXSAVEFlag);
- if ((cpuInfo[2] & FMAFlag) == FMAFlag && (sseExt & 6) == 6)
- {
- capabilities |= btCpuFeatureUtility::CPU_FEATURE_FMA3;
- }
-
- const int SSE41Flag = (1 << 19);
- if (cpuInfo[2] & SSE41Flag)
- {
- capabilities |= btCpuFeatureUtility::CPU_FEATURE_SSE4_1;
- }
- }
-#endif //BT_ALLOW_SSE4
-
- testedCapabilities = true;
- return capabilities;
- }
-};
-
-#endif //BT_CPU_UTILITY_H
diff --git a/thirdparty/bullet/LinearMath/btDefaultMotionState.h b/thirdparty/bullet/LinearMath/btDefaultMotionState.h
deleted file mode 100644
index 14c40d36b0..0000000000
--- a/thirdparty/bullet/LinearMath/btDefaultMotionState.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef BT_DEFAULT_MOTION_STATE_H
-#define BT_DEFAULT_MOTION_STATE_H
-
-#include "btMotionState.h"
-
-///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
-ATTRIBUTE_ALIGNED16(struct)
-btDefaultMotionState : public btMotionState
-{
- btTransform m_graphicsWorldTrans;
- btTransform m_centerOfMassOffset;
- btTransform m_startWorldTrans;
- void* m_userPointer;
-
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
- btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(), const btTransform& centerOfMassOffset = btTransform::getIdentity())
- : m_graphicsWorldTrans(startTrans),
- m_centerOfMassOffset(centerOfMassOffset),
- m_startWorldTrans(startTrans),
- m_userPointer(0)
-
- {
- }
-
- ///synchronizes world transform from user to physics
- virtual void getWorldTransform(btTransform & centerOfMassWorldTrans) const
- {
- centerOfMassWorldTrans = m_graphicsWorldTrans * m_centerOfMassOffset.inverse();
- }
-
- ///synchronizes world transform from physics to user
- ///Bullet only calls the update of worldtransform for active objects
- virtual void setWorldTransform(const btTransform& centerOfMassWorldTrans)
- {
- m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset;
- }
-};
-
-#endif //BT_DEFAULT_MOTION_STATE_H
diff --git a/thirdparty/bullet/LinearMath/btGeometryUtil.cpp b/thirdparty/bullet/LinearMath/btGeometryUtil.cpp
deleted file mode 100644
index 115e3eab81..0000000000
--- a/thirdparty/bullet/LinearMath/btGeometryUtil.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btGeometryUtil.h"
-
-/*
- Make sure this dummy function never changes so that it
- can be used by probes that are checking whether the
- library is actually installed.
-*/
-extern "C"
-{
- void btBulletMathProbe();
-
- void btBulletMathProbe() {}
-}
-
-bool btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin)
-{
- int numbrushes = planeEquations.size();
- for (int i = 0; i < numbrushes; i++)
- {
- const btVector3& N1 = planeEquations[i];
- btScalar dist = btScalar(N1.dot(point)) + btScalar(N1[3]) - margin;
- if (dist > btScalar(0.))
- {
- return false;
- }
- }
- return true;
-}
-
-bool btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin)
-{
- int numvertices = vertices.size();
- for (int i = 0; i < numvertices; i++)
- {
- const btVector3& N1 = vertices[i];
- btScalar dist = btScalar(planeNormal.dot(N1)) + btScalar(planeNormal[3]) - margin;
- if (dist > btScalar(0.))
- {
- return false;
- }
- }
- return true;
-}
-
-bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations);
-
-bool notExist(const btVector3& planeEquation, const btAlignedObjectArray<btVector3>& planeEquations)
-{
- int numbrushes = planeEquations.size();
- for (int i = 0; i < numbrushes; i++)
- {
- const btVector3& N1 = planeEquations[i];
- if (planeEquation.dot(N1) > btScalar(0.999))
- {
- return false;
- }
- }
- return true;
-}
-
-void btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut)
-{
- const int numvertices = vertices.size();
- // brute force:
- for (int i = 0; i < numvertices; i++)
- {
- const btVector3& N1 = vertices[i];
-
- for (int j = i + 1; j < numvertices; j++)
- {
- const btVector3& N2 = vertices[j];
-
- for (int k = j + 1; k < numvertices; k++)
- {
- const btVector3& N3 = vertices[k];
-
- btVector3 planeEquation, edge0, edge1;
- edge0 = N2 - N1;
- edge1 = N3 - N1;
- btScalar normalSign = btScalar(1.);
- for (int ww = 0; ww < 2; ww++)
- {
- planeEquation = normalSign * edge0.cross(edge1);
- if (planeEquation.length2() > btScalar(0.0001))
- {
- planeEquation.normalize();
- if (notExist(planeEquation, planeEquationsOut))
- {
- planeEquation[3] = -planeEquation.dot(N1);
-
- //check if inside, and replace supportingVertexOut if needed
- if (areVerticesBehindPlane(planeEquation, vertices, btScalar(0.01)))
- {
- planeEquationsOut.push_back(planeEquation);
- }
- }
- }
- normalSign = btScalar(-1.);
- }
- }
- }
- }
-}
-
-void btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut)
-{
- const int numbrushes = planeEquations.size();
- // brute force:
- for (int i = 0; i < numbrushes; i++)
- {
- const btVector3& N1 = planeEquations[i];
-
- for (int j = i + 1; j < numbrushes; j++)
- {
- const btVector3& N2 = planeEquations[j];
-
- for (int k = j + 1; k < numbrushes; k++)
- {
- const btVector3& N3 = planeEquations[k];
-
- btVector3 n2n3;
- n2n3 = N2.cross(N3);
- btVector3 n3n1;
- n3n1 = N3.cross(N1);
- btVector3 n1n2;
- n1n2 = N1.cross(N2);
-
- if ((n2n3.length2() > btScalar(0.0001)) &&
- (n3n1.length2() > btScalar(0.0001)) &&
- (n1n2.length2() > btScalar(0.0001)))
- {
- //point P out of 3 plane equations:
-
- // d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )
- //P = -------------------------------------------------------------------------
- // N1 . ( N2 * N3 )
-
- btScalar quotient = (N1.dot(n2n3));
- if (btFabs(quotient) > btScalar(0.000001))
- {
- quotient = btScalar(-1.) / quotient;
- n2n3 *= N1[3];
- n3n1 *= N2[3];
- n1n2 *= N3[3];
- btVector3 potentialVertex = n2n3;
- potentialVertex += n3n1;
- potentialVertex += n1n2;
- potentialVertex *= quotient;
-
- //check if inside, and replace supportingVertexOut if needed
- if (isPointInsidePlanes(planeEquations, potentialVertex, btScalar(0.01)))
- {
- verticesOut.push_back(potentialVertex);
- }
- }
- }
- }
- }
- }
-}
diff --git a/thirdparty/bullet/LinearMath/btGeometryUtil.h b/thirdparty/bullet/LinearMath/btGeometryUtil.h
deleted file mode 100644
index 0ce5b76d92..0000000000
--- a/thirdparty/bullet/LinearMath/btGeometryUtil.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GEOMETRY_UTIL_H
-#define BT_GEOMETRY_UTIL_H
-
-#include "btVector3.h"
-#include "btAlignedObjectArray.h"
-
-///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
-class btGeometryUtil
-{
-public:
- static void getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut);
-
- static void getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations, btAlignedObjectArray<btVector3>& verticesOut);
-
- static bool isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar margin);
-
- static bool isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar margin);
-
- static bool areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar margin);
-};
-
-#endif //BT_GEOMETRY_UTIL_H
diff --git a/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h b/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h
deleted file mode 100644
index 0fcb285971..0000000000
--- a/thirdparty/bullet/LinearMath/btGrahamScan2dConvexHull.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef GRAHAM_SCAN_2D_CONVEX_HULL_H
-#define GRAHAM_SCAN_2D_CONVEX_HULL_H
-
-#include "btVector3.h"
-#include "btAlignedObjectArray.h"
-
-struct GrahamVector3 : public btVector3
-{
- GrahamVector3(const btVector3& org, int orgIndex)
- : btVector3(org),
- m_orgIndex(orgIndex)
- {
- }
- btScalar m_angle;
- int m_orgIndex;
-};
-
-struct btAngleCompareFunc
-{
- btVector3 m_anchor;
- btAngleCompareFunc(const btVector3& anchor)
- : m_anchor(anchor)
- {
- }
- bool operator()(const GrahamVector3& a, const GrahamVector3& b) const
- {
- if (a.m_angle != b.m_angle)
- return a.m_angle < b.m_angle;
- else
- {
- btScalar al = (a - m_anchor).length2();
- btScalar bl = (b - m_anchor).length2();
- if (al != bl)
- return al < bl;
- else
- {
- return a.m_orgIndex < b.m_orgIndex;
- }
- }
- }
-};
-
-inline void GrahamScanConvexHull2D(btAlignedObjectArray<GrahamVector3>& originalPoints, btAlignedObjectArray<GrahamVector3>& hull, const btVector3& normalAxis)
-{
- btVector3 axis0, axis1;
- btPlaneSpace1(normalAxis, axis0, axis1);
-
- if (originalPoints.size() <= 1)
- {
- for (int i = 0; i < originalPoints.size(); i++)
- hull.push_back(originalPoints[0]);
- return;
- }
- //step1 : find anchor point with smallest projection on axis0 and move it to first location
- for (int i = 0; i < originalPoints.size(); i++)
- {
- // const btVector3& left = originalPoints[i];
- // const btVector3& right = originalPoints[0];
- btScalar projL = originalPoints[i].dot(axis0);
- btScalar projR = originalPoints[0].dot(axis0);
- if (projL < projR)
- {
- originalPoints.swap(0, i);
- }
- }
-
- //also precompute angles
- originalPoints[0].m_angle = -1e30f;
- for (int i = 1; i < originalPoints.size(); i++)
- {
- btVector3 ar = originalPoints[i] - originalPoints[0];
- btScalar ar1 = axis1.dot(ar);
- btScalar ar0 = axis0.dot(ar);
- if (ar1 * ar1 + ar0 * ar0 < FLT_EPSILON)
- {
- originalPoints[i].m_angle = 0.0f;
- }
- else
- {
- originalPoints[i].m_angle = btAtan2Fast(ar1, ar0);
- }
- }
-
- //step 2: sort all points, based on 'angle' with this anchor
- btAngleCompareFunc comp(originalPoints[0]);
- originalPoints.quickSortInternal(comp, 1, originalPoints.size() - 1);
-
- int i;
- for (i = 0; i < 2; i++)
- hull.push_back(originalPoints[i]);
-
- //step 3: keep all 'convex' points and discard concave points (using back tracking)
- for (; i != originalPoints.size(); i++)
- {
- bool isConvex = false;
- while (!isConvex && hull.size() > 1)
- {
- btVector3& a = hull[hull.size() - 2];
- btVector3& b = hull[hull.size() - 1];
- isConvex = btCross(a - b, a - originalPoints[i]).dot(normalAxis) > 0;
- if (!isConvex)
- hull.pop_back();
- else
- hull.push_back(originalPoints[i]);
- }
-
- if (hull.size() == 1)
- {
- hull.push_back(originalPoints[i]);
- }
- }
-}
-
-#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H
diff --git a/thirdparty/bullet/LinearMath/btHashMap.h b/thirdparty/bullet/LinearMath/btHashMap.h
deleted file mode 100644
index 1fca0fb73a..0000000000
--- a/thirdparty/bullet/LinearMath/btHashMap.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_HASH_MAP_H
-#define BT_HASH_MAP_H
-
-#include <string>
-#include "btAlignedObjectArray.h"
-
-///very basic hashable string implementation, compatible with btHashMap
-struct btHashString
-{
- std::string m_string1;
- unsigned int m_hash;
-
- SIMD_FORCE_INLINE unsigned int getHash() const
- {
- return m_hash;
- }
-
- btHashString()
- {
- m_string1 = "";
- m_hash = 0;
- }
- btHashString(const char* name)
- : m_string1(name)
- {
- /* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
- static const unsigned int InitialFNV = 2166136261u;
- static const unsigned int FNVMultiple = 16777619u;
-
- /* Fowler / Noll / Vo (FNV) Hash */
- unsigned int hash = InitialFNV;
-
- for (int i = 0; m_string1.c_str()[i]; i++)
- {
- hash = hash ^ (m_string1.c_str()[i]); /* xor the low 8 bits */
- hash = hash * FNVMultiple; /* multiply by the magic number */
- }
- m_hash = hash;
- }
-
- bool equals(const btHashString& other) const
- {
- return (m_string1 == other.m_string1);
- }
-};
-
-const int BT_HASH_NULL = 0xffffffff;
-
-class btHashInt
-{
- int m_uid;
-
-public:
- btHashInt()
- {
- }
-
- btHashInt(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- void setUid1(int uid)
- {
- m_uid = uid;
- }
-
- bool equals(const btHashInt& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash() const
- {
- unsigned int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
-
- return key;
- }
-};
-
-class btHashPtr
-{
- union {
- const void* m_pointer;
- unsigned int m_hashValues[2];
- };
-
-public:
- btHashPtr(const void* ptr)
- : m_pointer(ptr)
- {
- }
-
- const void* getPointer() const
- {
- return m_pointer;
- }
-
- bool equals(const btHashPtr& other) const
- {
- return getPointer() == other.getPointer();
- }
-
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash() const
- {
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
- unsigned int key = VOID_IS_8 ? m_hashValues[0] + m_hashValues[1] : m_hashValues[0];
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-template <class Value>
-class btHashKeyPtr
-{
- int m_uid;
-
-public:
- btHashKeyPtr(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const btHashKeyPtr<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
-
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash() const
- {
- unsigned int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-template <class Value>
-class btHashKey
-{
- int m_uid;
-
-public:
- btHashKey(int uid) : m_uid(uid)
- {
- }
-
- int getUid1() const
- {
- return m_uid;
- }
-
- bool equals(const btHashKey<Value>& other) const
- {
- return getUid1() == other.getUid1();
- }
- //to our success
- SIMD_FORCE_INLINE unsigned int getHash() const
- {
- unsigned int key = m_uid;
- // Thomas Wang's hash
- key += ~(key << 15);
- key ^= (key >> 10);
- key += (key << 3);
- key ^= (key >> 6);
- key += ~(key << 11);
- key ^= (key >> 16);
- return key;
- }
-};
-
-///The btHashMap template class implements a generic and lightweight hashmap.
-///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
-template <class Key, class Value>
-class btHashMap
-{
-protected:
- btAlignedObjectArray<int> m_hashTable;
- btAlignedObjectArray<int> m_next;
-
- btAlignedObjectArray<Value> m_valueArray;
- btAlignedObjectArray<Key> m_keyArray;
-
- void growTables(const Key& /*key*/)
- {
- int newCapacity = m_valueArray.capacity();
-
- if (m_hashTable.size() < newCapacity)
- {
- //grow hashtable and next table
- int curHashtableSize = m_hashTable.size();
-
- m_hashTable.resize(newCapacity);
- m_next.resize(newCapacity);
-
- int i;
-
- for (i = 0; i < newCapacity; ++i)
- {
- m_hashTable[i] = BT_HASH_NULL;
- }
- for (i = 0; i < newCapacity; ++i)
- {
- m_next[i] = BT_HASH_NULL;
- }
-
- for (i = 0; i < curHashtableSize; i++)
- {
- //const Value& value = m_valueArray[i];
- //const Key& key = m_keyArray[i];
-
- int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity() - 1); // New hash value with new mask
- m_next[i] = m_hashTable[hashValue];
- m_hashTable[hashValue] = i;
- }
- }
- }
-
-public:
- void insert(const Key& key, const Value& value)
- {
- int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- //replace value if the key is already there
- int index = findIndex(key);
- if (index != BT_HASH_NULL)
- {
- m_valueArray[index] = value;
- return;
- }
-
- int count = m_valueArray.size();
- int oldCapacity = m_valueArray.capacity();
- m_valueArray.push_back(value);
- m_keyArray.push_back(key);
-
- int newCapacity = m_valueArray.capacity();
- if (oldCapacity < newCapacity)
- {
- growTables(key);
- //hash with new capacity
- hash = key.getHash() & (m_valueArray.capacity() - 1);
- }
- m_next[count] = m_hashTable[hash];
- m_hashTable[hash] = count;
- }
-
- void remove(const Key& key)
- {
- int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- int pairIndex = findIndex(key);
-
- if (pairIndex == BT_HASH_NULL)
- {
- return;
- }
-
- // Remove the pair from the hash table.
- int index = m_hashTable[hash];
- btAssert(index != BT_HASH_NULL);
-
- int previous = BT_HASH_NULL;
- while (index != pairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_HASH_NULL)
- {
- btAssert(m_next[previous] == pairIndex);
- m_next[previous] = m_next[pairIndex];
- }
- else
- {
- m_hashTable[hash] = m_next[pairIndex];
- }
-
- // We now move the last pair into spot of the
- // pair being removed. We need to fix the hash
- // table indices to support the move.
-
- int lastPairIndex = m_valueArray.size() - 1;
-
- // If the removed pair is the last pair, we are done.
- if (lastPairIndex == pairIndex)
- {
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- return;
- }
-
- // Remove the last pair from the hash table.
- int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity() - 1);
-
- index = m_hashTable[lastHash];
- btAssert(index != BT_HASH_NULL);
-
- previous = BT_HASH_NULL;
- while (index != lastPairIndex)
- {
- previous = index;
- index = m_next[index];
- }
-
- if (previous != BT_HASH_NULL)
- {
- btAssert(m_next[previous] == lastPairIndex);
- m_next[previous] = m_next[lastPairIndex];
- }
- else
- {
- m_hashTable[lastHash] = m_next[lastPairIndex];
- }
-
- // Copy the last pair into the remove pair's spot.
- m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
- m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
-
- // Insert the last pair into the hash table
- m_next[pairIndex] = m_hashTable[lastHash];
- m_hashTable[lastHash] = pairIndex;
-
- m_valueArray.pop_back();
- m_keyArray.pop_back();
- }
-
- int size() const
- {
- return m_valueArray.size();
- }
-
- const Value* getAtIndex(int index) const
- {
- btAssert(index < m_valueArray.size());
- btAssert(index >= 0);
- if (index >= 0 && index < m_valueArray.size())
- {
- return &m_valueArray[index];
- }
- return 0;
- }
-
- Value* getAtIndex(int index)
- {
- btAssert(index < m_valueArray.size());
- btAssert(index >= 0);
- if (index >= 0 && index < m_valueArray.size())
- {
- return &m_valueArray[index];
- }
- return 0;
- }
-
- Key getKeyAtIndex(int index)
- {
- btAssert(index < m_keyArray.size());
- btAssert(index >= 0);
- return m_keyArray[index];
- }
-
- const Key getKeyAtIndex(int index) const
- {
- btAssert(index < m_keyArray.size());
- btAssert(index >= 0);
- return m_keyArray[index];
- }
-
- Value* operator[](const Key& key)
- {
- return find(key);
- }
-
- const Value* operator[](const Key& key) const
- {
- return find(key);
- }
-
- const Value* find(const Key& key) const
- {
- int index = findIndex(key);
- if (index == BT_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
-
- Value* find(const Key& key)
- {
- int index = findIndex(key);
- if (index == BT_HASH_NULL)
- {
- return NULL;
- }
- return &m_valueArray[index];
- }
-
- int findIndex(const Key& key) const
- {
- unsigned int hash = key.getHash() & (m_valueArray.capacity() - 1);
-
- if (hash >= (unsigned int)m_hashTable.size())
- {
- return BT_HASH_NULL;
- }
-
- int index = m_hashTable[hash];
- while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
- {
- index = m_next[index];
- }
- return index;
- }
-
- void clear()
- {
- m_hashTable.clear();
- m_next.clear();
- m_valueArray.clear();
- m_keyArray.clear();
- }
-};
-
-#endif //BT_HASH_MAP_H
diff --git a/thirdparty/bullet/LinearMath/btIDebugDraw.h b/thirdparty/bullet/LinearMath/btIDebugDraw.h
deleted file mode 100644
index df4db2ff5a..0000000000
--- a/thirdparty/bullet/LinearMath/btIDebugDraw.h
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_IDEBUG_DRAW__H
-#define BT_IDEBUG_DRAW__H
-
-#include "btVector3.h"
-#include "btTransform.h"
-
-///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
-///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
-///A class that implements the btIDebugDraw interface will need to provide non-empty implementations of the the drawLine and getDebugMode methods at a minimum.
-///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
-class btIDebugDraw
-{
-public:
- ATTRIBUTE_ALIGNED16(struct)
- DefaultColors
- {
- btVector3 m_activeObject;
- btVector3 m_deactivatedObject;
- btVector3 m_wantsDeactivationObject;
- btVector3 m_disabledDeactivationObject;
- btVector3 m_disabledSimulationObject;
- btVector3 m_aabb;
- btVector3 m_contactPoint;
-
- DefaultColors()
- : m_activeObject(1, 1, 1),
- m_deactivatedObject(0, 1, 0),
- m_wantsDeactivationObject(0, 1, 1),
- m_disabledDeactivationObject(1, 0, 0),
- m_disabledSimulationObject(1, 1, 0),
- m_aabb(1, 0, 0),
- m_contactPoint(1, 1, 0)
- {
- }
- };
-
- enum DebugDrawModes
- {
- DBG_NoDebug = 0,
- DBG_DrawWireframe = 1,
- DBG_DrawAabb = 2,
- DBG_DrawFeaturesText = 4,
- DBG_DrawContactPoints = 8,
- DBG_NoDeactivation = 16,
- DBG_NoHelpText = 32,
- DBG_DrawText = 64,
- DBG_ProfileTimings = 128,
- DBG_EnableSatComparison = 256,
- DBG_DisableBulletLCP = 512,
- DBG_EnableCCD = 1024,
- DBG_DrawConstraints = (1 << 11),
- DBG_DrawConstraintLimits = (1 << 12),
- DBG_FastWireframe = (1 << 13),
- DBG_DrawNormals = (1 << 14),
- DBG_DrawFrames = (1 << 15),
- DBG_MAX_DEBUG_DRAW_MODE
- };
-
- virtual ~btIDebugDraw(){};
-
- virtual DefaultColors getDefaultColors() const
- {
- DefaultColors colors;
- return colors;
- }
- ///the default implementation for setDefaultColors has no effect. A derived class can implement it and store the colors.
- virtual void setDefaultColors(const DefaultColors& /*colors*/) {}
-
- virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) = 0;
-
- virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
- {
- (void)toColor;
- drawLine(from, to, fromColor);
- }
-
- virtual void drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
- {
- btVector3 center = transform.getOrigin();
- btVector3 up = transform.getBasis().getColumn(1);
- btVector3 axis = transform.getBasis().getColumn(0);
- btScalar minTh = -SIMD_HALF_PI;
- btScalar maxTh = SIMD_HALF_PI;
- btScalar minPs = -SIMD_HALF_PI;
- btScalar maxPs = SIMD_HALF_PI;
- btScalar stepDegrees = 30.f;
- drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
- drawSpherePatch(center, up, -axis, radius, minTh, maxTh, minPs, maxPs, color, stepDegrees, false);
- }
-
- virtual void drawSphere(const btVector3& p, btScalar radius, const btVector3& color)
- {
- btTransform tr;
- tr.setIdentity();
- tr.setOrigin(p);
- drawSphere(radius, tr, color);
- }
-
- virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& /*n0*/, const btVector3& /*n1*/, const btVector3& /*n2*/, const btVector3& color, btScalar alpha)
- {
- drawTriangle(v0, v1, v2, color, alpha);
- }
- virtual void drawTriangle(const btVector3& v0, const btVector3& v1, const btVector3& v2, const btVector3& color, btScalar /*alpha*/)
- {
- drawLine(v0, v1, color);
- drawLine(v1, v2, color);
- drawLine(v2, v0, color);
- }
-
- virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) = 0;
-
- virtual void reportErrorWarning(const char* warningString) = 0;
-
- virtual void draw3dText(const btVector3& location, const char* textString) = 0;
-
- virtual void setDebugMode(int debugMode) = 0;
-
- virtual int getDebugMode() const = 0;
-
- virtual void drawAabb(const btVector3& from, const btVector3& to, const btVector3& color)
- {
- btVector3 halfExtents = (to - from) * 0.5f;
- btVector3 center = (to + from) * 0.5f;
- int i, j;
-
- btVector3 edgecoord(1.f, 1.f, 1.f), pa, pb;
- for (i = 0; i < 4; i++)
- {
- for (j = 0; j < 3; j++)
- {
- pa = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
- edgecoord[2] * halfExtents[2]);
- pa += center;
-
- int othercoord = j % 3;
- edgecoord[othercoord] *= -1.f;
- pb = btVector3(edgecoord[0] * halfExtents[0], edgecoord[1] * halfExtents[1],
- edgecoord[2] * halfExtents[2]);
- pb += center;
-
- drawLine(pa, pb, color);
- }
- edgecoord = btVector3(-1.f, -1.f, -1.f);
- if (i < 3)
- edgecoord[i] *= -1.f;
- }
- }
- virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
- {
- btVector3 start = transform.getOrigin();
- drawLine(start, start + transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(btScalar(1.), btScalar(0.3), btScalar(0.3)));
- drawLine(start, start + transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(btScalar(0.3), btScalar(1.), btScalar(0.3)));
- drawLine(start, start + transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(btScalar(0.3), btScalar(0.3), btScalar(1.)));
- }
-
- virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle,
- const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
- {
- const btVector3& vx = axis;
- btVector3 vy = normal.cross(axis);
- btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
- int nSteps = (int)btFabs((maxAngle - minAngle) / step);
- if (!nSteps) nSteps = 1;
- btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
- if (drawSect)
- {
- drawLine(center, prev, color);
- }
- for (int i = 1; i <= nSteps; i++)
- {
- btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
- btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
- drawLine(prev, next, color);
- prev = next;
- }
- if (drawSect)
- {
- drawLine(center, prev, color);
- }
- }
- virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius,
- btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f), bool drawCenter = true)
- {
- btVector3 vA[74];
- btVector3 vB[74];
- btVector3 *pvA = vA, *pvB = vB, *pT;
- btVector3 npole = center + up * radius;
- btVector3 spole = center - up * radius;
- btVector3 arcStart;
- btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
- const btVector3& kv = up;
- const btVector3& iv = axis;
- btVector3 jv = kv.cross(iv);
- bool drawN = false;
- bool drawS = false;
- if (minTh <= -SIMD_HALF_PI)
- {
- minTh = -SIMD_HALF_PI + step;
- drawN = true;
- }
- if (maxTh >= SIMD_HALF_PI)
- {
- maxTh = SIMD_HALF_PI - step;
- drawS = true;
- }
- if (minTh > maxTh)
- {
- minTh = -SIMD_HALF_PI + step;
- maxTh = SIMD_HALF_PI - step;
- drawN = drawS = true;
- }
- int n_hor = (int)((maxTh - minTh) / step) + 1;
- if (n_hor < 2) n_hor = 2;
- btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
- bool isClosed = false;
- if (minPs > maxPs)
- {
- minPs = -SIMD_PI + step;
- maxPs = SIMD_PI;
- isClosed = true;
- }
- else if ((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
- {
- isClosed = true;
- }
- else
- {
- isClosed = false;
- }
- int n_vert = (int)((maxPs - minPs) / step) + 1;
- if (n_vert < 2) n_vert = 2;
- btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
- for (int i = 0; i < n_hor; i++)
- {
- btScalar th = minTh + btScalar(i) * step_h;
- btScalar sth = radius * btSin(th);
- btScalar cth = radius * btCos(th);
- for (int j = 0; j < n_vert; j++)
- {
- btScalar psi = minPs + btScalar(j) * step_v;
- btScalar sps = btSin(psi);
- btScalar cps = btCos(psi);
- pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
- if (i)
- {
- drawLine(pvA[j], pvB[j], color);
- }
- else if (drawS)
- {
- drawLine(spole, pvB[j], color);
- }
- if (j)
- {
- drawLine(pvB[j - 1], pvB[j], color);
- }
- else
- {
- arcStart = pvB[j];
- }
- if ((i == (n_hor - 1)) && drawN)
- {
- drawLine(npole, pvB[j], color);
- }
-
- if (drawCenter)
- {
- if (isClosed)
- {
- if (j == (n_vert - 1))
- {
- drawLine(arcStart, pvB[j], color);
- }
- }
- else
- {
- if (((!i) || (i == (n_hor - 1))) && ((!j) || (j == (n_vert - 1))))
- {
- drawLine(center, pvB[j], color);
- }
- }
- }
- }
- pT = pvA;
- pvA = pvB;
- pvB = pT;
- }
- }
-
- virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
- {
- drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
- drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
- drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
- drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
- drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
- drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
- drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
- drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
- drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
- drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
- drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
- drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
- }
- virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
- {
- drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
- drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
- drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
- drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
- }
-
- virtual void drawCapsule(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
- {
- int stepDegrees = 30;
-
- btVector3 capStart(0.f, 0.f, 0.f);
- capStart[upAxis] = -halfHeight;
-
- btVector3 capEnd(0.f, 0.f, 0.f);
- capEnd[upAxis] = halfHeight;
-
- // Draw the ends
- {
- btTransform childTransform = transform;
- childTransform.getOrigin() = transform * capStart;
- {
- btVector3 center = childTransform.getOrigin();
- btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
- btVector3 axis = -childTransform.getBasis().getColumn(upAxis);
- btScalar minTh = -SIMD_HALF_PI;
- btScalar maxTh = SIMD_HALF_PI;
- btScalar minPs = -SIMD_HALF_PI;
- btScalar maxPs = SIMD_HALF_PI;
-
- drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
- }
- }
-
- {
- btTransform childTransform = transform;
- childTransform.getOrigin() = transform * capEnd;
- {
- btVector3 center = childTransform.getOrigin();
- btVector3 up = childTransform.getBasis().getColumn((upAxis + 1) % 3);
- btVector3 axis = childTransform.getBasis().getColumn(upAxis);
- btScalar minTh = -SIMD_HALF_PI;
- btScalar maxTh = SIMD_HALF_PI;
- btScalar minPs = -SIMD_HALF_PI;
- btScalar maxPs = SIMD_HALF_PI;
- drawSpherePatch(center, up, axis, radius, minTh, maxTh, minPs, maxPs, color, btScalar(stepDegrees), false);
- }
- }
-
- // Draw some additional lines
- btVector3 start = transform.getOrigin();
-
- for (int i = 0; i < 360; i += stepDegrees)
- {
- capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
- }
- }
-
- virtual void drawCylinder(btScalar radius, btScalar halfHeight, int upAxis, const btTransform& transform, const btVector3& color)
- {
- btVector3 start = transform.getOrigin();
- btVector3 offsetHeight(0, 0, 0);
- offsetHeight[upAxis] = halfHeight;
- int stepDegrees = 30;
- btVector3 capStart(0.f, 0.f, 0.f);
- capStart[upAxis] = -halfHeight;
- btVector3 capEnd(0.f, 0.f, 0.f);
- capEnd[upAxis] = halfHeight;
-
- for (int i = 0; i < 360; i += stepDegrees)
- {
- capEnd[(upAxis + 1) % 3] = capStart[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- capEnd[(upAxis + 2) % 3] = capStart[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- drawLine(start + transform.getBasis() * capStart, start + transform.getBasis() * capEnd, color);
- }
- // Drawing top and bottom caps of the cylinder
- btVector3 yaxis(0, 0, 0);
- yaxis[upAxis] = btScalar(1.0);
- btVector3 xaxis(0, 0, 0);
- xaxis[(upAxis + 1) % 3] = btScalar(1.0);
- drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
- drawArc(start + transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, btScalar(10.0));
- }
-
- virtual void drawCone(btScalar radius, btScalar height, int upAxis, const btTransform& transform, const btVector3& color)
- {
- int stepDegrees = 30;
- btVector3 start = transform.getOrigin();
-
- btVector3 offsetHeight(0, 0, 0);
- btScalar halfHeight = height * btScalar(0.5);
- offsetHeight[upAxis] = halfHeight;
- btVector3 offsetRadius(0, 0, 0);
- offsetRadius[(upAxis + 1) % 3] = radius;
- btVector3 offset2Radius(0, 0, 0);
- offset2Radius[(upAxis + 2) % 3] = radius;
-
- btVector3 capEnd(0.f, 0.f, 0.f);
- capEnd[upAxis] = -halfHeight;
-
- for (int i = 0; i < 360; i += stepDegrees)
- {
- capEnd[(upAxis + 1) % 3] = btSin(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- capEnd[(upAxis + 2) % 3] = btCos(btScalar(i) * SIMD_RADS_PER_DEG) * radius;
- drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * capEnd, color);
- }
-
- drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offsetRadius), color);
- drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offsetRadius), color);
- drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight + offset2Radius), color);
- drawLine(start + transform.getBasis() * (offsetHeight), start + transform.getBasis() * (-offsetHeight - offset2Radius), color);
-
- // Drawing the base of the cone
- btVector3 yaxis(0, 0, 0);
- yaxis[upAxis] = btScalar(1.0);
- btVector3 xaxis(0, 0, 0);
- xaxis[(upAxis + 1) % 3] = btScalar(1.0);
- drawArc(start - transform.getBasis() * (offsetHeight), transform.getBasis() * yaxis, transform.getBasis() * xaxis, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
- }
-
- virtual void drawPlane(const btVector3& planeNormal, btScalar planeConst, const btTransform& transform, const btVector3& color)
- {
- btVector3 planeOrigin = planeNormal * planeConst;
- btVector3 vec0, vec1;
- btPlaneSpace1(planeNormal, vec0, vec1);
- btScalar vecLen = 100.f;
- btVector3 pt0 = planeOrigin + vec0 * vecLen;
- btVector3 pt1 = planeOrigin - vec0 * vecLen;
- btVector3 pt2 = planeOrigin + vec1 * vecLen;
- btVector3 pt3 = planeOrigin - vec1 * vecLen;
- drawLine(transform * pt0, transform * pt1, color);
- drawLine(transform * pt2, transform * pt3, color);
- }
-
- virtual void clearLines()
- {
- }
-
- virtual void flushLines()
- {
- }
-};
-
-#endif //BT_IDEBUG_DRAW__H
diff --git a/thirdparty/bullet/LinearMath/btImplicitQRSVD.h b/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
deleted file mode 100644
index aaedc964f6..0000000000
--- a/thirdparty/bullet/LinearMath/btImplicitQRSVD.h
+++ /dev/null
@@ -1,916 +0,0 @@
-/**
- Bullet Continuous Collision Detection and Physics Library
- Copyright (c) 2019 Google Inc. http://bulletphysics.org
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- Copyright (c) 2016 Theodore Gast, Chuyuan Fu, Chenfanfu Jiang, Joseph Teran
-
- 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.
-
- If the code is used in an article, the following paper shall be cited:
- @techreport{qrsvd:2016,
- title={Implicit-shifted Symmetric QR Singular Value Decomposition of 3x3 Matrices},
- author={Gast, Theodore and Fu, Chuyuan and Jiang, Chenfanfu and Teran, Joseph},
- year={2016},
- institution={University of California Los Angeles}
- }
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-**/
-
-#ifndef btImplicitQRSVD_h
-#define btImplicitQRSVD_h
-#include <limits>
-#include "btMatrix3x3.h"
-class btMatrix2x2
-{
-public:
- btScalar m_00, m_01, m_10, m_11;
- btMatrix2x2(): m_00(0), m_10(0), m_01(0), m_11(0)
- {
- }
- btMatrix2x2(const btMatrix2x2& other): m_00(other.m_00),m_01(other.m_01),m_10(other.m_10),m_11(other.m_11)
- {}
- btScalar& operator()(int i, int j)
- {
- if (i == 0 && j == 0)
- return m_00;
- if (i == 1 && j == 0)
- return m_10;
- if (i == 0 && j == 1)
- return m_01;
- if (i == 1 && j == 1)
- return m_11;
- btAssert(false);
- return m_00;
- }
- const btScalar& operator()(int i, int j) const
- {
- if (i == 0 && j == 0)
- return m_00;
- if (i == 1 && j == 0)
- return m_10;
- if (i == 0 && j == 1)
- return m_01;
- if (i == 1 && j == 1)
- return m_11;
- btAssert(false);
- return m_00;
- }
- void setIdentity()
- {
- m_00 = 1;
- m_11 = 1;
- m_01 = 0;
- m_10 = 0;
- }
-};
-
-static inline btScalar copySign(btScalar x, btScalar y) {
- if ((x < 0 && y > 0) || (x > 0 && y < 0))
- return -x;
- return x;
-}
-
-/**
- Class for givens rotation.
- Row rotation G*A corresponds to something like
- c -s 0
- ( s c 0 ) A
- 0 0 1
- Column rotation A G' corresponds to something like
- c -s 0
- A ( s c 0 )
- 0 0 1
-
- c and s are always computed so that
- ( c -s ) ( a ) = ( * )
- s c b ( 0 )
-
- Assume rowi<rowk.
- */
-
-class GivensRotation {
-public:
- int rowi;
- int rowk;
- btScalar c;
- btScalar s;
-
- inline GivensRotation(int rowi_in, int rowk_in)
- : rowi(rowi_in)
- , rowk(rowk_in)
- , c(1)
- , s(0)
- {
- }
-
- inline GivensRotation(btScalar a, btScalar b, int rowi_in, int rowk_in)
- : rowi(rowi_in)
- , rowk(rowk_in)
- {
- compute(a, b);
- }
-
- ~GivensRotation() {}
-
- inline void transposeInPlace()
- {
- s = -s;
- }
-
- /**
- Compute c and s from a and b so that
- ( c -s ) ( a ) = ( * )
- s c b ( 0 )
- */
- inline void compute(const btScalar a, const btScalar b)
- {
- btScalar d = a * a + b * b;
- c = 1;
- s = 0;
- if (d > SIMD_EPSILON) {
- btScalar sqrtd = btSqrt(d);
- if (sqrtd>SIMD_EPSILON)
- {
- btScalar t = btScalar(1.0)/sqrtd;
- c = a * t;
- s = -b * t;
- }
- }
- }
-
- /**
- This function computes c and s so that
- ( c -s ) ( a ) = ( 0 )
- s c b ( * )
- */
- inline void computeUnconventional(const btScalar a, const btScalar b)
- {
- btScalar d = a * a + b * b;
- c = 0;
- s = 1;
- if (d > SIMD_EPSILON) {
- btScalar t = btScalar(1.0)/btSqrt(d);
- s = a * t;
- c = b * t;
- }
- }
- /**
- Fill the R with the entries of this rotation
- */
- inline void fill(const btMatrix3x3& R) const
- {
- btMatrix3x3& A = const_cast<btMatrix3x3&>(R);
- A.setIdentity();
- A[rowi][rowi] = c;
- A[rowk][rowi] = -s;
- A[rowi][rowk] = s;
- A[rowk][rowk] = c;
- }
-
- inline void fill(const btMatrix2x2& R) const
- {
- btMatrix2x2& A = const_cast<btMatrix2x2&>(R);
- A(rowi,rowi) = c;
- A(rowk,rowi) = -s;
- A(rowi,rowk) = s;
- A(rowk,rowk) = c;
- }
-
- /**
- This function does something like
- c -s 0
- ( s c 0 ) A -> A
- 0 0 1
- It only affects row i and row k of A.
- */
- inline void rowRotation(btMatrix3x3& A) const
- {
- for (int j = 0; j < 3; j++) {
- btScalar tau1 = A[rowi][j];
- btScalar tau2 = A[rowk][j];
- A[rowi][j] = c * tau1 - s * tau2;
- A[rowk][j] = s * tau1 + c * tau2;
- }
- }
- inline void rowRotation(btMatrix2x2& A) const
- {
- for (int j = 0; j < 2; j++) {
- btScalar tau1 = A(rowi,j);
- btScalar tau2 = A(rowk,j);
- A(rowi,j) = c * tau1 - s * tau2;
- A(rowk,j) = s * tau1 + c * tau2;
- }
- }
-
- /**
- This function does something like
- c s 0
- A ( -s c 0 ) -> A
- 0 0 1
- It only affects column i and column k of A.
- */
- inline void columnRotation(btMatrix3x3& A) const
- {
- for (int j = 0; j < 3; j++) {
- btScalar tau1 = A[j][rowi];
- btScalar tau2 = A[j][rowk];
- A[j][rowi] = c * tau1 - s * tau2;
- A[j][rowk] = s * tau1 + c * tau2;
- }
- }
- inline void columnRotation(btMatrix2x2& A) const
- {
- for (int j = 0; j < 2; j++) {
- btScalar tau1 = A(j,rowi);
- btScalar tau2 = A(j,rowk);
- A(j,rowi) = c * tau1 - s * tau2;
- A(j,rowk) = s * tau1 + c * tau2;
- }
- }
-
- /**
- Multiply givens must be for same row and column
- **/
- inline void operator*=(const GivensRotation& A)
- {
- btScalar new_c = c * A.c - s * A.s;
- btScalar new_s = s * A.c + c * A.s;
- c = new_c;
- s = new_s;
- }
-
- /**
- Multiply givens must be for same row and column
- **/
- inline GivensRotation operator*(const GivensRotation& A) const
- {
- GivensRotation r(*this);
- r *= A;
- return r;
- }
-};
-
-/**
- \brief zero chasing the 3X3 matrix to bidiagonal form
- original form of H: x x 0
- x x x
- 0 0 x
- after zero chase:
- x x 0
- 0 x x
- 0 0 x
- */
-inline void zeroChase(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
-{
-
- /**
- Reduce H to of form
- x x +
- 0 x x
- 0 0 x
- */
- GivensRotation r1(H[0][0], H[1][0], 0, 1);
- /**
- Reduce H to of form
- x x 0
- 0 x x
- 0 + x
- Can calculate r2 without multiplying by r1 since both entries are in first two
- rows thus no need to divide by sqrt(a^2+b^2)
- */
- GivensRotation r2(1, 2);
- if (H[1][0] != 0)
- r2.compute(H[0][0] * H[0][1] + H[1][0] * H[1][1], H[0][0] * H[0][2] + H[1][0] * H[1][2]);
- else
- r2.compute(H[0][1], H[0][2]);
-
- r1.rowRotation(H);
-
- /* GivensRotation<T> r2(H(0, 1), H(0, 2), 1, 2); */
- r2.columnRotation(H);
- r2.columnRotation(V);
-
- /**
- Reduce H to of form
- x x 0
- 0 x x
- 0 0 x
- */
- GivensRotation r3(H[1][1], H[2][1], 1, 2);
- r3.rowRotation(H);
-
- // Save this till end for better cache coherency
- // r1.rowRotation(u_transpose);
- // r3.rowRotation(u_transpose);
- r1.columnRotation(U);
- r3.columnRotation(U);
-}
-
-/**
- \brief make a 3X3 matrix to upper bidiagonal form
- original form of H: x x x
- x x x
- x x x
- after zero chase:
- x x 0
- 0 x x
- 0 0 x
- */
-inline void makeUpperBidiag(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
-{
- U.setIdentity();
- V.setIdentity();
-
- /**
- Reduce H to of form
- x x x
- x x x
- 0 x x
- */
-
- GivensRotation r(H[1][0], H[2][0], 1, 2);
- r.rowRotation(H);
- // r.rowRotation(u_transpose);
- r.columnRotation(U);
- // zeroChase(H, u_transpose, V);
- zeroChase(H, U, V);
-}
-
-/**
- \brief make a 3X3 matrix to lambda shape
- original form of H: x x x
- * x x x
- * x x x
- after :
- * x 0 0
- * x x 0
- * x 0 x
- */
-inline void makeLambdaShape(btMatrix3x3& H, btMatrix3x3& U, btMatrix3x3& V)
-{
- U.setIdentity();
- V.setIdentity();
-
- /**
- Reduce H to of form
- * x x 0
- * x x x
- * x x x
- */
-
- GivensRotation r1(H[0][1], H[0][2], 1, 2);
- r1.columnRotation(H);
- r1.columnRotation(V);
-
- /**
- Reduce H to of form
- * x x 0
- * x x 0
- * x x x
- */
-
- r1.computeUnconventional(H[1][2], H[2][2]);
- r1.rowRotation(H);
- r1.columnRotation(U);
-
- /**
- Reduce H to of form
- * x x 0
- * x x 0
- * x 0 x
- */
-
- GivensRotation r2(H[2][0], H[2][1], 0, 1);
- r2.columnRotation(H);
- r2.columnRotation(V);
-
- /**
- Reduce H to of form
- * x 0 0
- * x x 0
- * x 0 x
- */
- r2.computeUnconventional(H[0][1], H[1][1]);
- r2.rowRotation(H);
- r2.columnRotation(U);
-}
-
-/**
- \brief 2x2 polar decomposition.
- \param[in] A matrix.
- \param[out] R Robustly a rotation matrix.
- \param[out] S_Sym Symmetric. Whole matrix is stored
-
- Polar guarantees negative sign is on the small magnitude singular value.
- S is guaranteed to be the closest one to identity.
- R is guaranteed to be the closest rotation to A.
- */
-inline void polarDecomposition(const btMatrix2x2& A,
- GivensRotation& R,
- const btMatrix2x2& S_Sym)
-{
- btScalar a = (A(0, 0) + A(1, 1)), b = (A(1, 0) - A(0, 1));
- btScalar denominator = btSqrt(a*a+b*b);
- R.c = (btScalar)1;
- R.s = (btScalar)0;
- if (denominator > SIMD_EPSILON) {
- /*
- No need to use a tolerance here because x(0) and x(1) always have
- smaller magnitude then denominator, therefore overflow never happens.
- In Bullet, we use a tolerance anyway.
- */
- R.c = a / denominator;
- R.s = -b / denominator;
- }
- btMatrix2x2& S = const_cast<btMatrix2x2&>(S_Sym);
- S = A;
- R.rowRotation(S);
-}
-
-inline void polarDecomposition(const btMatrix2x2& A,
- const btMatrix2x2& R,
- const btMatrix2x2& S_Sym)
-{
- GivensRotation r(0, 1);
- polarDecomposition(A, r, S_Sym);
- r.fill(R);
-}
-
-/**
- \brief 2x2 SVD (singular value decomposition) A=USV'
- \param[in] A Input matrix.
- \param[out] U Robustly a rotation matrix in Givens form
- \param[out] Sigma matrix of singular values sorted with decreasing magnitude. The second one can be negative.
- \param[out] V Robustly a rotation matrix in Givens form
- */
-inline void singularValueDecomposition(
- const btMatrix2x2& A,
- GivensRotation& U,
- const btMatrix2x2& Sigma,
- GivensRotation& V,
- const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
-{
- btMatrix2x2& sigma = const_cast<btMatrix2x2&>(Sigma);
- sigma.setIdentity();
- btMatrix2x2 S_Sym;
- polarDecomposition(A, U, S_Sym);
- btScalar cosine, sine;
- btScalar x = S_Sym(0, 0);
- btScalar y = S_Sym(0, 1);
- btScalar z = S_Sym(1, 1);
- if (y == 0) {
- // S is already diagonal
- cosine = 1;
- sine = 0;
- sigma(0,0) = x;
- sigma(1,1) = z;
- }
- else {
- btScalar tau = 0.5 * (x - z);
- btScalar val = tau * tau + y * y;
- if (val > SIMD_EPSILON)
- {
- btScalar w = btSqrt(val);
- // w > y > 0
- btScalar t;
- if (tau > 0) {
- // tau + w > w > y > 0 ==> division is safe
- t = y / (tau + w);
- }
- else {
- // tau - w < -w < -y < 0 ==> division is safe
- t = y / (tau - w);
- }
- cosine = btScalar(1) / btSqrt(t * t + btScalar(1));
- sine = -t * cosine;
- /*
- V = [cosine -sine; sine cosine]
- Sigma = V'SV. Only compute the diagonals for efficiency.
- Also utilize symmetry of S and don't form V yet.
- */
- btScalar c2 = cosine * cosine;
- btScalar csy = 2 * cosine * sine * y;
- btScalar s2 = sine * sine;
- sigma(0,0) = c2 * x - csy + s2 * z;
- sigma(1,1) = s2 * x + csy + c2 * z;
- } else
- {
- cosine = 1;
- sine = 0;
- sigma(0,0) = x;
- sigma(1,1) = z;
- }
- }
-
- // Sorting
- // Polar already guarantees negative sign is on the small magnitude singular value.
- if (sigma(0,0) < sigma(1,1)) {
- std::swap(sigma(0,0), sigma(1,1));
- V.c = -sine;
- V.s = cosine;
- }
- else {
- V.c = cosine;
- V.s = sine;
- }
- U *= V;
-}
-
-/**
- \brief 2x2 SVD (singular value decomposition) A=USV'
- \param[in] A Input matrix.
- \param[out] U Robustly a rotation matrix.
- \param[out] Sigma Vector of singular values sorted with decreasing magnitude. The second one can be negative.
- \param[out] V Robustly a rotation matrix.
- */
-inline void singularValueDecomposition(
- const btMatrix2x2& A,
- const btMatrix2x2& U,
- const btMatrix2x2& Sigma,
- const btMatrix2x2& V,
- const btScalar tol = 64 * std::numeric_limits<btScalar>::epsilon())
-{
- GivensRotation gv(0, 1);
- GivensRotation gu(0, 1);
- singularValueDecomposition(A, gu, Sigma, gv);
-
- gu.fill(U);
- gv.fill(V);
-}
-
-/**
- \brief compute wilkinsonShift of the block
- a1 b1
- b1 a2
- based on the wilkinsonShift formula
- mu = c + d - sign (d) \ sqrt (d*d + b*b), where d = (a-c)/2
-
- */
-inline btScalar wilkinsonShift(const btScalar a1, const btScalar b1, const btScalar a2)
-{
- btScalar d = (btScalar)0.5 * (a1 - a2);
- btScalar bs = b1 * b1;
- btScalar val = d * d + bs;
- if (val>SIMD_EPSILON)
- {
- btScalar denom = btFabs(d) + btSqrt(val);
-
- btScalar mu = a2 - copySign(bs / (denom), d);
- // T mu = a2 - bs / ( d + sign_d*sqrt (d*d + bs));
- return mu;
- }
- return a2;
-}
-
-/**
- \brief Helper function of 3X3 SVD for processing 2X2 SVD
- */
-template <int t>
-inline void process(btMatrix3x3& B, btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V)
-{
- int other = (t == 1) ? 0 : 2;
- GivensRotation u(0, 1);
- GivensRotation v(0, 1);
- sigma[other] = B[other][other];
-
- btMatrix2x2 B_sub, sigma_sub;
- if (t == 0)
- {
- B_sub.m_00 = B[0][0];
- B_sub.m_10 = B[1][0];
- B_sub.m_01 = B[0][1];
- B_sub.m_11 = B[1][1];
- sigma_sub.m_00 = sigma[0];
- sigma_sub.m_11 = sigma[1];
-// singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
- singularValueDecomposition(B_sub, u, sigma_sub, v);
- B[0][0] = B_sub.m_00;
- B[1][0] = B_sub.m_10;
- B[0][1] = B_sub.m_01;
- B[1][1] = B_sub.m_11;
- sigma[0] = sigma_sub.m_00;
- sigma[1] = sigma_sub.m_11;
- }
- else
- {
- B_sub.m_00 = B[1][1];
- B_sub.m_10 = B[2][1];
- B_sub.m_01 = B[1][2];
- B_sub.m_11 = B[2][2];
- sigma_sub.m_00 = sigma[1];
- sigma_sub.m_11 = sigma[2];
- // singularValueDecomposition(B.template block<2, 2>(t, t), u, sigma.template block<2, 1>(t, 0), v);
- singularValueDecomposition(B_sub, u, sigma_sub, v);
- B[1][1] = B_sub.m_00;
- B[2][1] = B_sub.m_10;
- B[1][2] = B_sub.m_01;
- B[2][2] = B_sub.m_11;
- sigma[1] = sigma_sub.m_00;
- sigma[2] = sigma_sub.m_11;
- }
- u.rowi += t;
- u.rowk += t;
- v.rowi += t;
- v.rowk += t;
- u.columnRotation(U);
- v.columnRotation(V);
-}
-
-/**
- \brief Helper function of 3X3 SVD for flipping signs due to flipping signs of sigma
- */
-inline void flipSign(int i, btMatrix3x3& U, btVector3& sigma)
-{
- sigma[i] = -sigma[i];
- U[0][i] = -U[0][i];
- U[1][i] = -U[1][i];
- U[2][i] = -U[2][i];
-}
-
-inline void flipSign(int i, btMatrix3x3& U)
-{
- U[0][i] = -U[0][i];
- U[1][i] = -U[1][i];
- U[2][i] = -U[2][i];
-}
-
-inline void swapCol(btMatrix3x3& A, int i, int j)
-{
- for (int d = 0; d < 3; ++d)
- std::swap(A[d][i], A[d][j]);
-}
-/**
- \brief Helper function of 3X3 SVD for sorting singular values
- */
-inline void sort(btMatrix3x3& U, btVector3& sigma, btMatrix3x3& V, int t)
-{
- if (t == 0)
- {
- // Case: sigma(0) > |sigma(1)| >= |sigma(2)|
- if (btFabs(sigma[1]) >= btFabs(sigma[2])) {
- if (sigma[1] < 0) {
- flipSign(1, U, sigma);
- flipSign(2, U, sigma);
- }
- return;
- }
-
- //fix sign of sigma for both cases
- if (sigma[2] < 0) {
- flipSign(1, U, sigma);
- flipSign(2, U, sigma);
- }
-
- //swap sigma(1) and sigma(2) for both cases
- std::swap(sigma[1], sigma[2]);
- // swap the col 1 and col 2 for U,V
- swapCol(U,1,2);
- swapCol(V,1,2);
-
- // Case: |sigma(2)| >= sigma(0) > |simga(1)|
- if (sigma[1] > sigma[0]) {
- std::swap(sigma[0], sigma[1]);
- swapCol(U,0,1);
- swapCol(V,0,1);
- }
-
- // Case: sigma(0) >= |sigma(2)| > |simga(1)|
- else {
- flipSign(2, U);
- flipSign(2, V);
- }
- }
- else if (t == 1)
- {
- // Case: |sigma(0)| >= sigma(1) > |sigma(2)|
- if (btFabs(sigma[0]) >= sigma[1]) {
- if (sigma[0] < 0) {
- flipSign(0, U, sigma);
- flipSign(2, U, sigma);
- }
- return;
- }
-
- //swap sigma(0) and sigma(1) for both cases
- std::swap(sigma[0], sigma[1]);
- swapCol(U, 0, 1);
- swapCol(V, 0, 1);
-
- // Case: sigma(1) > |sigma(2)| >= |sigma(0)|
- if (btFabs(sigma[1]) < btFabs(sigma[2])) {
- std::swap(sigma[1], sigma[2]);
- swapCol(U, 1, 2);
- swapCol(V, 1, 2);
- }
-
- // Case: sigma(1) >= |sigma(0)| > |sigma(2)|
- else {
- flipSign(1, U);
- flipSign(1, V);
- }
-
- // fix sign for both cases
- if (sigma[1] < 0) {
- flipSign(1, U, sigma);
- flipSign(2, U, sigma);
- }
- }
-}
-
-/**
- \brief 3X3 SVD (singular value decomposition) A=USV'
- \param[in] A Input matrix.
- \param[out] U is a rotation matrix.
- \param[out] sigma Diagonal matrix, sorted with decreasing magnitude. The third one can be negative.
- \param[out] V is a rotation matrix.
- */
-inline int singularValueDecomposition(const btMatrix3x3& A,
- btMatrix3x3& U,
- btVector3& sigma,
- btMatrix3x3& V,
- btScalar tol = 128*std::numeric_limits<btScalar>::epsilon())
-{
-// using std::fabs;
- btMatrix3x3 B = A;
- U.setIdentity();
- V.setIdentity();
-
- makeUpperBidiag(B, U, V);
-
- int count = 0;
- btScalar mu = (btScalar)0;
- GivensRotation r(0, 1);
-
- btScalar alpha_1 = B[0][0];
- btScalar beta_1 = B[0][1];
- btScalar alpha_2 = B[1][1];
- btScalar alpha_3 = B[2][2];
- btScalar beta_2 = B[1][2];
- btScalar gamma_1 = alpha_1 * beta_1;
- btScalar gamma_2 = alpha_2 * beta_2;
- btScalar val = alpha_1 * alpha_1 + alpha_2 * alpha_2 + alpha_3 * alpha_3 + beta_1 * beta_1 + beta_2 * beta_2;
- if (val > SIMD_EPSILON)
- {
- tol *= btMax((btScalar)0.5 * btSqrt(val), (btScalar)1);
- }
- /**
- Do implicit shift QR until A^T A is block diagonal
- */
- int max_count = 100;
-
- while (btFabs(beta_2) > tol && btFabs(beta_1) > tol
- && btFabs(alpha_1) > tol && btFabs(alpha_2) > tol
- && btFabs(alpha_3) > tol
- && count < max_count) {
- mu = wilkinsonShift(alpha_2 * alpha_2 + beta_1 * beta_1, gamma_2, alpha_3 * alpha_3 + beta_2 * beta_2);
-
- r.compute(alpha_1 * alpha_1 - mu, gamma_1);
- r.columnRotation(B);
-
- r.columnRotation(V);
- zeroChase(B, U, V);
-
- alpha_1 = B[0][0];
- beta_1 = B[0][1];
- alpha_2 = B[1][1];
- alpha_3 = B[2][2];
- beta_2 = B[1][2];
- gamma_1 = alpha_1 * beta_1;
- gamma_2 = alpha_2 * beta_2;
- count++;
- }
- /**
- Handle the cases of one of the alphas and betas being 0
- Sorted by ease of handling and then frequency
- of occurrence
-
- If B is of form
- x x 0
- 0 x 0
- 0 0 x
- */
- if (btFabs(beta_2) <= tol) {
- process<0>(B, U, sigma, V);
- sort(U, sigma, V,0);
- }
- /**
- If B is of form
- x 0 0
- 0 x x
- 0 0 x
- */
- else if (btFabs(beta_1) <= tol) {
- process<1>(B, U, sigma, V);
- sort(U, sigma, V,1);
- }
- /**
- If B is of form
- x x 0
- 0 0 x
- 0 0 x
- */
- else if (btFabs(alpha_2) <= tol) {
- /**
- Reduce B to
- x x 0
- 0 0 0
- 0 0 x
- */
- GivensRotation r1(1, 2);
- r1.computeUnconventional(B[1][2], B[2][2]);
- r1.rowRotation(B);
- r1.columnRotation(U);
-
- process<0>(B, U, sigma, V);
- sort(U, sigma, V, 0);
- }
- /**
- If B is of form
- x x 0
- 0 x x
- 0 0 0
- */
- else if (btFabs(alpha_3) <= tol) {
- /**
- Reduce B to
- x x +
- 0 x 0
- 0 0 0
- */
- GivensRotation r1(1, 2);
- r1.compute(B[1][1], B[1][2]);
- r1.columnRotation(B);
- r1.columnRotation(V);
- /**
- Reduce B to
- x x 0
- + x 0
- 0 0 0
- */
- GivensRotation r2(0, 2);
- r2.compute(B[0][0], B[0][2]);
- r2.columnRotation(B);
- r2.columnRotation(V);
-
- process<0>(B, U, sigma, V);
- sort(U, sigma, V, 0);
- }
- /**
- If B is of form
- 0 x 0
- 0 x x
- 0 0 x
- */
- else if (btFabs(alpha_1) <= tol) {
- /**
- Reduce B to
- 0 0 +
- 0 x x
- 0 0 x
- */
- GivensRotation r1(0, 1);
- r1.computeUnconventional(B[0][1], B[1][1]);
- r1.rowRotation(B);
- r1.columnRotation(U);
-
- /**
- Reduce B to
- 0 0 0
- 0 x x
- 0 + x
- */
- GivensRotation r2(0, 2);
- r2.computeUnconventional(B[0][2], B[2][2]);
- r2.rowRotation(B);
- r2.columnRotation(U);
-
- process<1>(B, U, sigma, V);
- sort(U, sigma, V, 1);
- }
-
- return count;
-}
-#endif /* btImplicitQRSVD_h */
diff --git a/thirdparty/bullet/LinearMath/btList.h b/thirdparty/bullet/LinearMath/btList.h
deleted file mode 100644
index b255938c30..0000000000
--- a/thirdparty/bullet/LinearMath/btList.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GEN_LIST_H
-#define BT_GEN_LIST_H
-
-class btGEN_Link
-{
-public:
- btGEN_Link() : m_next(0), m_prev(0) {}
- btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
-
- btGEN_Link *getNext() const { return m_next; }
- btGEN_Link *getPrev() const { return m_prev; }
-
- bool isHead() const { return m_prev == 0; }
- bool isTail() const { return m_next == 0; }
-
- void insertBefore(btGEN_Link *link)
- {
- m_next = link;
- m_prev = link->m_prev;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void insertAfter(btGEN_Link *link)
- {
- m_next = link->m_next;
- m_prev = link;
- m_next->m_prev = this;
- m_prev->m_next = this;
- }
-
- void remove()
- {
- m_next->m_prev = m_prev;
- m_prev->m_next = m_next;
- }
-
-private:
- btGEN_Link *m_next;
- btGEN_Link *m_prev;
-};
-
-class btGEN_List
-{
-public:
- btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
-
- btGEN_Link *getHead() const { return m_head.getNext(); }
- btGEN_Link *getTail() const { return m_tail.getPrev(); }
-
- void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
- void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
-
-private:
- btGEN_Link m_head;
- btGEN_Link m_tail;
-};
-
-#endif //BT_GEN_LIST_H
diff --git a/thirdparty/bullet/LinearMath/btMatrix3x3.h b/thirdparty/bullet/LinearMath/btMatrix3x3.h
deleted file mode 100644
index 9c90fee1d2..0000000000
--- a/thirdparty/bullet/LinearMath/btMatrix3x3.h
+++ /dev/null
@@ -1,1431 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MATRIX3x3_H
-#define BT_MATRIX3x3_H
-
-#include "btVector3.h"
-#include "btQuaternion.h"
-#include <stdio.h>
-
-#ifdef BT_USE_SSE
-//const __m128 ATTRIBUTE_ALIGNED16(v2220) = {2.0f, 2.0f, 2.0f, 0.0f};
-//const __m128 ATTRIBUTE_ALIGNED16(vMPPP) = {-0.0f, +0.0f, +0.0f, +0.0f};
-#define vMPPP (_mm_set_ps(+0.0f, +0.0f, +0.0f, -0.0f))
-#endif
-
-#if defined(BT_USE_SSE)
-#define v0000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f))
-#define v1000 (_mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f))
-#define v0100 (_mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f))
-#define v0010 (_mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f))
-#elif defined(BT_USE_NEON)
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0000) = {0.0f, 0.0f, 0.0f, 0.0f};
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(v1000) = {1.0f, 0.0f, 0.0f, 0.0f};
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0100) = {0.0f, 1.0f, 0.0f, 0.0f};
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(v0010) = {0.0f, 0.0f, 1.0f, 0.0f};
-#endif
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btMatrix3x3Data btMatrix3x3DoubleData
-#else
-#define btMatrix3x3Data btMatrix3x3FloatData
-#endif //BT_USE_DOUBLE_PRECISION
-
-/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
-* Make sure to only include a pure orthogonal matrix without scaling. */
-ATTRIBUTE_ALIGNED16(class)
-btMatrix3x3
-{
- ///Data storage for the matrix, each vector is a row of the matrix
- btVector3 m_el[3];
-
-public:
- /** @brief No initializaion constructor */
- btMatrix3x3() {}
-
- // explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
-
- /**@brief Constructor from Quaternion */
- explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
- /*
- template <typename btScalar>
- Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
- {
- setEulerYPR(yaw, pitch, roll);
- }
- */
- /** @brief Constructor with row major formatting */
- btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
- const btScalar& yx, const btScalar& yy, const btScalar& yz,
- const btScalar& zx, const btScalar& zy, const btScalar& zz)
- {
- setValue(xx, xy, xz,
- yx, yy, yz,
- zx, zy, zz);
- }
-
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- SIMD_FORCE_INLINE btMatrix3x3(const btSimdFloat4 v0, const btSimdFloat4 v1, const btSimdFloat4 v2)
- {
- m_el[0].mVec128 = v0;
- m_el[1].mVec128 = v1;
- m_el[2].mVec128 = v2;
- }
-
- SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
- {
- m_el[0] = v0;
- m_el[1] = v1;
- m_el[2] = v2;
- }
-
- // Copy constructor
- SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& rhs)
- {
- m_el[0].mVec128 = rhs.m_el[0].mVec128;
- m_el[1].mVec128 = rhs.m_el[1].mVec128;
- m_el[2].mVec128 = rhs.m_el[2].mVec128;
- }
-
- // Assignment Operator
- SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& m)
- {
- m_el[0].mVec128 = m.m_el[0].mVec128;
- m_el[1].mVec128 = m.m_el[1].mVec128;
- m_el[2].mVec128 = m.m_el[2].mVec128;
-
- return *this;
- }
-
-#else
-
- /** @brief Copy constructor */
- SIMD_FORCE_INLINE btMatrix3x3(const btMatrix3x3& other)
- {
- m_el[0] = other.m_el[0];
- m_el[1] = other.m_el[1];
- m_el[2] = other.m_el[2];
- }
-
- /** @brief Assignment Operator */
- SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
- {
- m_el[0] = other.m_el[0];
- m_el[1] = other.m_el[1];
- m_el[2] = other.m_el[2];
- return *this;
- }
-
- SIMD_FORCE_INLINE btMatrix3x3(const btVector3& v0, const btVector3& v1, const btVector3& v2)
- {
- m_el[0] = v0;
- m_el[1] = v1;
- m_el[2] = v2;
- }
-
-#endif
-
- /** @brief Get a column of the matrix as a vector
- * @param i Column number 0 indexed */
- SIMD_FORCE_INLINE btVector3 getColumn(int i) const
- {
- return btVector3(m_el[0][i], m_el[1][i], m_el[2][i]);
- }
-
- /** @brief Get a row of the matrix as a vector
- * @param i Row number 0 indexed */
- SIMD_FORCE_INLINE const btVector3& getRow(int i) const
- {
- btFullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Get a mutable reference to a row of the matrix as a vector
- * @param i Row number 0 indexed */
- SIMD_FORCE_INLINE btVector3& operator[](int i)
- {
- btFullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Get a const reference to a row of the matrix as a vector
- * @param i Row number 0 indexed */
- SIMD_FORCE_INLINE const btVector3& operator[](int i) const
- {
- btFullAssert(0 <= i && i < 3);
- return m_el[i];
- }
-
- /** @brief Multiply by the target matrix on the right
- * @param m Rotation matrix to be applied
- * Equivilant to this = this * m */
- btMatrix3x3& operator*=(const btMatrix3x3& m);
-
- /** @brief Adds by the target matrix on the right
- * @param m matrix to be applied
- * Equivilant to this = this + m */
- btMatrix3x3& operator+=(const btMatrix3x3& m);
-
- /** @brief Substractss by the target matrix on the right
- * @param m matrix to be applied
- * Equivilant to this = this - m */
- btMatrix3x3& operator-=(const btMatrix3x3& m);
-
- /** @brief Set from the rotational part of a 4x4 OpenGL matrix
- * @param m A pointer to the beginning of the array of scalars*/
- void setFromOpenGLSubMatrix(const btScalar* m)
- {
- m_el[0].setValue(m[0], m[4], m[8]);
- m_el[1].setValue(m[1], m[5], m[9]);
- m_el[2].setValue(m[2], m[6], m[10]);
- }
- /** @brief Set the values of the matrix explicitly (row major)
- * @param xx Top left
- * @param xy Top Middle
- * @param xz Top Right
- * @param yx Middle Left
- * @param yy Middle Middle
- * @param yz Middle Right
- * @param zx Bottom Left
- * @param zy Bottom Middle
- * @param zz Bottom Right*/
- void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz,
- const btScalar& yx, const btScalar& yy, const btScalar& yz,
- const btScalar& zx, const btScalar& zy, const btScalar& zz)
- {
- m_el[0].setValue(xx, xy, xz);
- m_el[1].setValue(yx, yy, yz);
- m_el[2].setValue(zx, zy, zz);
- }
-
- /** @brief Set the matrix from a quaternion
- * @param q The Quaternion to match */
- void setRotation(const btQuaternion& q)
- {
- btScalar d = q.length2();
- btFullAssert(d != btScalar(0.0));
- btScalar s = btScalar(2.0) / d;
-
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs, Q = q.get128();
- __m128i Qi = btCastfTo128i(Q);
- __m128 Y, Z;
- __m128 V1, V2, V3;
- __m128 V11, V21, V31;
- __m128 NQ = _mm_xor_ps(Q, btvMzeroMask);
- __m128i NQi = btCastfTo128i(NQ);
-
- V1 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 2, 3))); // Y X Z W
- V2 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(0, 0, 1, 3)); // -X -X Y W
- V3 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(2, 1, 0, 3))); // Z Y X W
- V1 = _mm_xor_ps(V1, vMPPP); // change the sign of the first element
-
- V11 = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 1, 0, 3))); // Y Y X W
- V21 = _mm_unpackhi_ps(Q, Q); // Z Z W W
- V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(0, 2, 0, 3)); // X Z -X -W
-
- V2 = V2 * V1; //
- V1 = V1 * V11; //
- V3 = V3 * V31; //
-
- V11 = _mm_shuffle_ps(NQ, Q, BT_SHUFFLE(2, 3, 1, 3)); // -Z -W Y W
- V11 = V11 * V21; //
- V21 = _mm_xor_ps(V21, vMPPP); // change the sign of the first element
- V31 = _mm_shuffle_ps(Q, NQ, BT_SHUFFLE(3, 3, 1, 3)); // W W -Y -W
- V31 = _mm_xor_ps(V31, vMPPP); // change the sign of the first element
- Y = btCastiTo128f(_mm_shuffle_epi32(NQi, BT_SHUFFLE(3, 2, 0, 3))); // -W -Z -X -W
- Z = btCastiTo128f(_mm_shuffle_epi32(Qi, BT_SHUFFLE(1, 0, 1, 3))); // Y X Y W
-
- vs = _mm_load_ss(&s);
- V21 = V21 * Y;
- V31 = V31 * Z;
-
- V1 = V1 + V11;
- V2 = V2 + V21;
- V3 = V3 + V31;
-
- vs = bt_splat3_ps(vs, 0);
- // s ready
- V1 = V1 * vs;
- V2 = V2 * vs;
- V3 = V3 * vs;
-
- V1 = V1 + v1000;
- V2 = V2 + v0100;
- V3 = V3 + v0010;
-
- m_el[0] = V1;
- m_el[1] = V2;
- m_el[2] = V3;
-#else
- btScalar xs = q.x() * s, ys = q.y() * s, zs = q.z() * s;
- btScalar wx = q.w() * xs, wy = q.w() * ys, wz = q.w() * zs;
- btScalar xx = q.x() * xs, xy = q.x() * ys, xz = q.x() * zs;
- btScalar yy = q.y() * ys, yz = q.y() * zs, zz = q.z() * zs;
- setValue(
- btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
- xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
- xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
-#endif
- }
-
- /** @brief Set the matrix from euler angles using YPR around YXZ respectively
- * @param yaw Yaw about Y axis
- * @param pitch Pitch about X axis
- * @param roll Roll about Z axis
- */
- void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
- {
- setEulerZYX(roll, pitch, yaw);
- }
-
- /** @brief Set the matrix from euler angles YPR around ZYX axes
- * @param eulerX Roll about X axis
- * @param eulerY Pitch around Y axis
- * @param eulerZ Yaw about Z axis
- *
- * These angles are used to produce a rotation matrix. The euler
- * angles are applied in ZYX order. I.e a vector is first rotated
- * about X then Y and then Z
- **/
- void setEulerZYX(btScalar eulerX, btScalar eulerY, btScalar eulerZ)
- {
- ///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
- btScalar ci(btCos(eulerX));
- btScalar cj(btCos(eulerY));
- btScalar ch(btCos(eulerZ));
- btScalar si(btSin(eulerX));
- btScalar sj(btSin(eulerY));
- btScalar sh(btSin(eulerZ));
- btScalar cc = ci * ch;
- btScalar cs = ci * sh;
- btScalar sc = si * ch;
- btScalar ss = si * sh;
-
- setValue(cj * ch, sj * sc - cs, sj * cc + ss,
- cj * sh, sj * ss + cc, sj * cs - sc,
- -sj, cj * si, cj * ci);
- }
-
- /**@brief Set the matrix to the identity */
- void setIdentity()
- {
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- m_el[0] = v1000;
- m_el[1] = v0100;
- m_el[2] = v0010;
-#else
- setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(1.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(1.0));
-#endif
- }
-
- /**@brief Set the matrix to the identity */
- void setZero()
- {
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- m_el[0] = v0000;
- m_el[1] = v0000;
- m_el[2] = v0000;
-#else
- setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(0.0));
-#endif
- }
-
- static const btMatrix3x3& getIdentity()
- {
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- static const btMatrix3x3
- identityMatrix(v1000, v0100, v0010);
-#else
- static const btMatrix3x3
- identityMatrix(
- btScalar(1.0), btScalar(0.0), btScalar(0.0),
- btScalar(0.0), btScalar(1.0), btScalar(0.0),
- btScalar(0.0), btScalar(0.0), btScalar(1.0));
-#endif
- return identityMatrix;
- }
-
- /**@brief Fill the rotational part of an OpenGL matrix and clear the shear/perspective
- * @param m The array to be filled */
- void getOpenGLSubMatrix(btScalar * m) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128* vm = (__m128*)m;
- __m128 vT;
-
- v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
- v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
-#elif defined(BT_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
- float32x4_t* vm = (float32x4_t*)m;
- float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
- float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
- float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
- float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
-
- vm[0] = v0;
- vm[1] = v1;
- vm[2] = v2;
-#else
- m[0] = btScalar(m_el[0].x());
- m[1] = btScalar(m_el[1].x());
- m[2] = btScalar(m_el[2].x());
- m[3] = btScalar(0.0);
- m[4] = btScalar(m_el[0].y());
- m[5] = btScalar(m_el[1].y());
- m[6] = btScalar(m_el[2].y());
- m[7] = btScalar(0.0);
- m[8] = btScalar(m_el[0].z());
- m[9] = btScalar(m_el[1].z());
- m[10] = btScalar(m_el[2].z());
- m[11] = btScalar(0.0);
-#endif
- }
-
- /**@brief Get the matrix represented as a quaternion
- * @param q The quaternion which will be set */
- void getRotation(btQuaternion & q) const
- {
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
- btScalar s, x;
-
- union {
- btSimdFloat4 vec;
- btScalar f[4];
- } temp;
-
- if (trace > btScalar(0.0))
- {
- x = trace + btScalar(1.0);
-
- temp.f[0] = m_el[2].y() - m_el[1].z();
- temp.f[1] = m_el[0].z() - m_el[2].x();
- temp.f[2] = m_el[1].x() - m_el[0].y();
- temp.f[3] = x;
- //temp.f[3]= s * btScalar(0.5);
- }
- else
- {
- int i, j, k;
- if (m_el[0].x() < m_el[1].y())
- {
- if (m_el[1].y() < m_el[2].z())
- {
- i = 2;
- j = 0;
- k = 1;
- }
- else
- {
- i = 1;
- j = 2;
- k = 0;
- }
- }
- else
- {
- if (m_el[0].x() < m_el[2].z())
- {
- i = 2;
- j = 0;
- k = 1;
- }
- else
- {
- i = 0;
- j = 1;
- k = 2;
- }
- }
-
- x = m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0);
-
- temp.f[3] = (m_el[k][j] - m_el[j][k]);
- temp.f[j] = (m_el[j][i] + m_el[i][j]);
- temp.f[k] = (m_el[k][i] + m_el[i][k]);
- temp.f[i] = x;
- //temp.f[i] = s * btScalar(0.5);
- }
-
- s = btSqrt(x);
- q.set128(temp.vec);
- s = btScalar(0.5) / s;
-
- q *= s;
-#else
- btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
-
- btScalar temp[4];
-
- if (trace > btScalar(0.0))
- {
- btScalar s = btSqrt(trace + btScalar(1.0));
- temp[3] = (s * btScalar(0.5));
- s = btScalar(0.5) / s;
-
- temp[0] = ((m_el[2].y() - m_el[1].z()) * s);
- temp[1] = ((m_el[0].z() - m_el[2].x()) * s);
- temp[2] = ((m_el[1].x() - m_el[0].y()) * s);
- }
- else
- {
- int i = m_el[0].x() < m_el[1].y() ? (m_el[1].y() < m_el[2].z() ? 2 : 1) : (m_el[0].x() < m_el[2].z() ? 2 : 0);
- int j = (i + 1) % 3;
- int k = (i + 2) % 3;
-
- btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
- temp[i] = s * btScalar(0.5);
- s = btScalar(0.5) / s;
-
- temp[3] = (m_el[k][j] - m_el[j][k]) * s;
- temp[j] = (m_el[j][i] + m_el[i][j]) * s;
- temp[k] = (m_el[k][i] + m_el[i][k]) * s;
- }
- q.setValue(temp[0], temp[1], temp[2], temp[3]);
-#endif
- }
-
- /**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
- * @param yaw Yaw around Y axis
- * @param pitch Pitch around X axis
- * @param roll around Z axis */
- void getEulerYPR(btScalar & yaw, btScalar & pitch, btScalar & roll) const
- {
- // first use the normal calculus
- yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
- pitch = btScalar(btAsin(-m_el[2].x()));
- roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
-
- // on pitch = +/-HalfPI
- if (btFabs(pitch) == SIMD_HALF_PI)
- {
- if (yaw > 0)
- yaw -= SIMD_PI;
- else
- yaw += SIMD_PI;
-
- if (roll > 0)
- roll -= SIMD_PI;
- else
- roll += SIMD_PI;
- }
- };
-
- /**@brief Get the matrix represented as euler angles around ZYX
- * @param yaw Yaw around Z axis
- * @param pitch Pitch around Y axis
- * @param roll around X axis
- * @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/
- void getEulerZYX(btScalar & yaw, btScalar & pitch, btScalar & roll, unsigned int solution_number = 1) const
- {
- struct Euler
- {
- btScalar yaw;
- btScalar pitch;
- btScalar roll;
- };
-
- Euler euler_out;
- Euler euler_out2; //second solution
- //get the pointer to the raw data
-
- // Check that pitch is not at a singularity
- if (btFabs(m_el[2].x()) >= 1)
- {
- euler_out.yaw = 0;
- euler_out2.yaw = 0;
-
- // From difference of angles formula
- btScalar delta = btAtan2(m_el[0].x(), m_el[0].z());
- if (m_el[2].x() > 0) //gimbal locked up
- {
- euler_out.pitch = SIMD_PI / btScalar(2.0);
- euler_out2.pitch = SIMD_PI / btScalar(2.0);
- euler_out.roll = euler_out.pitch + delta;
- euler_out2.roll = euler_out.pitch + delta;
- }
- else // gimbal locked down
- {
- euler_out.pitch = -SIMD_PI / btScalar(2.0);
- euler_out2.pitch = -SIMD_PI / btScalar(2.0);
- euler_out.roll = -euler_out.pitch + delta;
- euler_out2.roll = -euler_out.pitch + delta;
- }
- }
- else
- {
- euler_out.pitch = -btAsin(m_el[2].x());
- euler_out2.pitch = SIMD_PI - euler_out.pitch;
-
- euler_out.roll = btAtan2(m_el[2].y() / btCos(euler_out.pitch),
- m_el[2].z() / btCos(euler_out.pitch));
- euler_out2.roll = btAtan2(m_el[2].y() / btCos(euler_out2.pitch),
- m_el[2].z() / btCos(euler_out2.pitch));
-
- euler_out.yaw = btAtan2(m_el[1].x() / btCos(euler_out.pitch),
- m_el[0].x() / btCos(euler_out.pitch));
- euler_out2.yaw = btAtan2(m_el[1].x() / btCos(euler_out2.pitch),
- m_el[0].x() / btCos(euler_out2.pitch));
- }
-
- if (solution_number == 1)
- {
- yaw = euler_out.yaw;
- pitch = euler_out.pitch;
- roll = euler_out.roll;
- }
- else
- {
- yaw = euler_out2.yaw;
- pitch = euler_out2.pitch;
- roll = euler_out2.roll;
- }
- }
-
- /**@brief Create a scaled copy of the matrix
- * @param s Scaling vector The elements of the vector will scale each column */
-
- btMatrix3x3 scaled(const btVector3& s) const
- {
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- return btMatrix3x3(m_el[0] * s, m_el[1] * s, m_el[2] * s);
-#else
- return btMatrix3x3(
- m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
- m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
- m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
-#endif
- }
-
- /**@brief Return the determinant of the matrix */
- btScalar determinant() const;
- /**@brief Return the adjoint of the matrix */
- btMatrix3x3 adjoint() const;
- /**@brief Return the matrix with all values non negative */
- btMatrix3x3 absolute() const;
- /**@brief Return the transpose of the matrix */
- btMatrix3x3 transpose() const;
- /**@brief Return the inverse of the matrix */
- btMatrix3x3 inverse() const;
-
- /// Solve A * x = b, where b is a column vector. This is more efficient
- /// than computing the inverse in one-shot cases.
- ///Solve33 is from Box2d, thanks to Erin Catto,
- btVector3 solve33(const btVector3& b) const
- {
- btVector3 col1 = getColumn(0);
- btVector3 col2 = getColumn(1);
- btVector3 col3 = getColumn(2);
-
- btScalar det = btDot(col1, btCross(col2, col3));
- if (btFabs(det) > SIMD_EPSILON)
- {
- det = 1.0f / det;
- }
- btVector3 x;
- x[0] = det * btDot(b, btCross(col2, col3));
- x[1] = det * btDot(col1, btCross(b, col3));
- x[2] = det * btDot(col1, btCross(col2, b));
- return x;
- }
-
- btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
- btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
-
- SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const
- {
- return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
- }
- SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const
- {
- return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
- }
- SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const
- {
- return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
- }
-
- ///extractRotation is from "A robust method to extract the rotational part of deformations"
- ///See http://dl.acm.org/citation.cfm?doid=2994258.2994269
- ///decomposes a matrix A in a orthogonal matrix R and a
- ///symmetric matrix S:
- ///A = R*S.
- ///note that R can include both rotation and scaling.
- SIMD_FORCE_INLINE void extractRotation(btQuaternion & q, btScalar tolerance = 1.0e-9, int maxIter = 100)
- {
- int iter = 0;
- btScalar w;
- const btMatrix3x3& A = *this;
- for (iter = 0; iter < maxIter; iter++)
- {
- btMatrix3x3 R(q);
- btVector3 omega = (R.getColumn(0).cross(A.getColumn(0)) + R.getColumn(1).cross(A.getColumn(1)) + R.getColumn(2).cross(A.getColumn(2))) * (btScalar(1.0) / btFabs(R.getColumn(0).dot(A.getColumn(0)) + R.getColumn(1).dot(A.getColumn(1)) + R.getColumn(2).dot(A.getColumn(2))) +
- tolerance);
- w = omega.norm();
- if (w < tolerance)
- break;
- q = btQuaternion(btVector3((btScalar(1.0) / w) * omega), w) *
- q;
- q.normalize();
- }
- }
-
- /**@brief diagonalizes this matrix by the Jacobi method.
- * @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
- * coordinate system, i.e., old_this = rot * new_this * rot^T.
- * @param threshold See iteration
- * @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied
- * by the sum of the absolute values of the diagonal, or when maxSteps have been executed.
- *
- * Note that this matrix is assumed to be symmetric.
- */
- void diagonalize(btMatrix3x3 & rot, btScalar threshold, int maxSteps)
- {
- rot.setIdentity();
- for (int step = maxSteps; step > 0; step--)
- {
- // find off-diagonal element [p][q] with largest magnitude
- int p = 0;
- int q = 1;
- int r = 2;
- btScalar max = btFabs(m_el[0][1]);
- btScalar v = btFabs(m_el[0][2]);
- if (v > max)
- {
- q = 2;
- r = 1;
- max = v;
- }
- v = btFabs(m_el[1][2]);
- if (v > max)
- {
- p = 1;
- q = 2;
- r = 0;
- max = v;
- }
-
- btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
- if (max <= t)
- {
- if (max <= SIMD_EPSILON * t)
- {
- return;
- }
- step = 1;
- }
-
- // compute Jacobi rotation J which leads to a zero for element [p][q]
- btScalar mpq = m_el[p][q];
- btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
- btScalar theta2 = theta * theta;
- btScalar cos;
- btScalar sin;
- if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
- {
- t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
- : 1 / (theta - btSqrt(1 + theta2));
- cos = 1 / btSqrt(1 + t * t);
- sin = cos * t;
- }
- else
- {
- // approximation for large theta-value, i.e., a nearly diagonal matrix
- t = 1 / (theta * (2 + btScalar(0.5) / theta2));
- cos = 1 - btScalar(0.5) * t * t;
- sin = cos * t;
- }
-
- // apply rotation to matrix (this = J^T * this * J)
- m_el[p][q] = m_el[q][p] = 0;
- m_el[p][p] -= t * mpq;
- m_el[q][q] += t * mpq;
- btScalar mrp = m_el[r][p];
- btScalar mrq = m_el[r][q];
- m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
- m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
-
- // apply rotation to rot (rot = rot * J)
- for (int i = 0; i < 3; i++)
- {
- btVector3& row = rot[i];
- mrp = row[p];
- mrq = row[q];
- row[p] = cos * mrp - sin * mrq;
- row[q] = cos * mrq + sin * mrp;
- }
- }
- }
-
- /**@brief Calculate the matrix cofactor
- * @param r1 The first row to use for calculating the cofactor
- * @param c1 The first column to use for calculating the cofactor
- * @param r1 The second row to use for calculating the cofactor
- * @param c1 The second column to use for calculating the cofactor
- * See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
- */
- btScalar cofac(int r1, int c1, int r2, int c2) const
- {
- return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
- }
-
- void serialize(struct btMatrix3x3Data & dataOut) const;
-
- void serializeFloat(struct btMatrix3x3FloatData & dataOut) const;
-
- void deSerialize(const struct btMatrix3x3Data& dataIn);
-
- void deSerializeFloat(const struct btMatrix3x3FloatData& dataIn);
-
- void deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn);
-};
-
-SIMD_FORCE_INLINE btMatrix3x3&
-btMatrix3x3::operator*=(const btMatrix3x3& m)
-{
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 rv00, rv01, rv02;
- __m128 rv10, rv11, rv12;
- __m128 rv20, rv21, rv22;
- __m128 mv0, mv1, mv2;
-
- rv02 = m_el[0].mVec128;
- rv12 = m_el[1].mVec128;
- rv22 = m_el[2].mVec128;
-
- mv0 = _mm_and_ps(m[0].mVec128, btvFFF0fMask);
- mv1 = _mm_and_ps(m[1].mVec128, btvFFF0fMask);
- mv2 = _mm_and_ps(m[2].mVec128, btvFFF0fMask);
-
- // rv0
- rv00 = bt_splat_ps(rv02, 0);
- rv01 = bt_splat_ps(rv02, 1);
- rv02 = bt_splat_ps(rv02, 2);
-
- rv00 = _mm_mul_ps(rv00, mv0);
- rv01 = _mm_mul_ps(rv01, mv1);
- rv02 = _mm_mul_ps(rv02, mv2);
-
- // rv1
- rv10 = bt_splat_ps(rv12, 0);
- rv11 = bt_splat_ps(rv12, 1);
- rv12 = bt_splat_ps(rv12, 2);
-
- rv10 = _mm_mul_ps(rv10, mv0);
- rv11 = _mm_mul_ps(rv11, mv1);
- rv12 = _mm_mul_ps(rv12, mv2);
-
- // rv2
- rv20 = bt_splat_ps(rv22, 0);
- rv21 = bt_splat_ps(rv22, 1);
- rv22 = bt_splat_ps(rv22, 2);
-
- rv20 = _mm_mul_ps(rv20, mv0);
- rv21 = _mm_mul_ps(rv21, mv1);
- rv22 = _mm_mul_ps(rv22, mv2);
-
- rv00 = _mm_add_ps(rv00, rv01);
- rv10 = _mm_add_ps(rv10, rv11);
- rv20 = _mm_add_ps(rv20, rv21);
-
- m_el[0].mVec128 = _mm_add_ps(rv00, rv02);
- m_el[1].mVec128 = _mm_add_ps(rv10, rv12);
- m_el[2].mVec128 = _mm_add_ps(rv20, rv22);
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m_el[0].mVec128;
- v1 = m_el[1].mVec128;
- v2 = m_el[2].mVec128;
-
- mv0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
- mv1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
- mv2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- m_el[0].mVec128 = rv0;
- m_el[1].mVec128 = rv1;
- m_el[2].mVec128 = rv2;
-#else
- setValue(
- m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
- m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
- m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
-#endif
- return *this;
-}
-
-SIMD_FORCE_INLINE btMatrix3x3&
-btMatrix3x3::operator+=(const btMatrix3x3& m)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 + m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 + m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 + m.m_el[2].mVec128;
-#else
- setValue(
- m_el[0][0] + m.m_el[0][0],
- m_el[0][1] + m.m_el[0][1],
- m_el[0][2] + m.m_el[0][2],
- m_el[1][0] + m.m_el[1][0],
- m_el[1][1] + m.m_el[1][1],
- m_el[1][2] + m.m_el[1][2],
- m_el[2][0] + m.m_el[2][0],
- m_el[2][1] + m.m_el[2][1],
- m_el[2][2] + m.m_el[2][2]);
-#endif
- return *this;
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-operator*(const btMatrix3x3& m, const btScalar& k)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 vk = bt_splat_ps(_mm_load_ss((float*)&k), 0x80);
- return btMatrix3x3(
- _mm_mul_ps(m[0].mVec128, vk),
- _mm_mul_ps(m[1].mVec128, vk),
- _mm_mul_ps(m[2].mVec128, vk));
-#elif defined(BT_USE_NEON)
- return btMatrix3x3(
- vmulq_n_f32(m[0].mVec128, k),
- vmulq_n_f32(m[1].mVec128, k),
- vmulq_n_f32(m[2].mVec128, k));
-#else
- return btMatrix3x3(
- m[0].x() * k, m[0].y() * k, m[0].z() * k,
- m[1].x() * k, m[1].y() * k, m[1].z() * k,
- m[2].x() * k, m[2].y() * k, m[2].z() * k);
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-operator+(const btMatrix3x3& m1, const btMatrix3x3& m2)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- return btMatrix3x3(
- m1[0].mVec128 + m2[0].mVec128,
- m1[1].mVec128 + m2[1].mVec128,
- m1[2].mVec128 + m2[2].mVec128);
-#else
- return btMatrix3x3(
- m1[0][0] + m2[0][0],
- m1[0][1] + m2[0][1],
- m1[0][2] + m2[0][2],
-
- m1[1][0] + m2[1][0],
- m1[1][1] + m2[1][1],
- m1[1][2] + m2[1][2],
-
- m1[2][0] + m2[2][0],
- m1[2][1] + m2[2][1],
- m1[2][2] + m2[2][2]);
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-operator-(const btMatrix3x3& m1, const btMatrix3x3& m2)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- return btMatrix3x3(
- m1[0].mVec128 - m2[0].mVec128,
- m1[1].mVec128 - m2[1].mVec128,
- m1[2].mVec128 - m2[2].mVec128);
-#else
- return btMatrix3x3(
- m1[0][0] - m2[0][0],
- m1[0][1] - m2[0][1],
- m1[0][2] - m2[0][2],
-
- m1[1][0] - m2[1][0],
- m1[1][1] - m2[1][1],
- m1[1][2] - m2[1][2],
-
- m1[2][0] - m2[2][0],
- m1[2][1] - m2[2][1],
- m1[2][2] - m2[2][2]);
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3&
-btMatrix3x3::operator-=(const btMatrix3x3& m)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- m_el[0].mVec128 = m_el[0].mVec128 - m.m_el[0].mVec128;
- m_el[1].mVec128 = m_el[1].mVec128 - m.m_el[1].mVec128;
- m_el[2].mVec128 = m_el[2].mVec128 - m.m_el[2].mVec128;
-#else
- setValue(
- m_el[0][0] - m.m_el[0][0],
- m_el[0][1] - m.m_el[0][1],
- m_el[0][2] - m.m_el[0][2],
- m_el[1][0] - m.m_el[1][0],
- m_el[1][1] - m.m_el[1][1],
- m_el[1][2] - m.m_el[1][2],
- m_el[2][0] - m.m_el[2][0],
- m_el[2][1] - m.m_el[2][1],
- m_el[2][2] - m.m_el[2][2]);
-#endif
- return *this;
-}
-
-SIMD_FORCE_INLINE btScalar
-btMatrix3x3::determinant() const
-{
- return btTriple((*this)[0], (*this)[1], (*this)[2]);
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::absolute() const
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- return btMatrix3x3(
- _mm_and_ps(m_el[0].mVec128, btvAbsfMask),
- _mm_and_ps(m_el[1].mVec128, btvAbsfMask),
- _mm_and_ps(m_el[2].mVec128, btvAbsfMask));
-#elif defined(BT_USE_NEON)
- return btMatrix3x3(
- (float32x4_t)vandq_s32((int32x4_t)m_el[0].mVec128, btv3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[1].mVec128, btv3AbsMask),
- (float32x4_t)vandq_s32((int32x4_t)m_el[2].mVec128, btv3AbsMask));
-#else
- return btMatrix3x3(
- btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
- btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
- btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::transpose() const
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 v0 = m_el[0].mVec128;
- __m128 v1 = m_el[1].mVec128;
- __m128 v2 = m_el[2].mVec128; // x2 y2 z2 w2
- __m128 vT;
-
- v2 = _mm_and_ps(v2, btvFFF0fMask); // x2 y2 z2 0
-
- vT = _mm_unpackhi_ps(v0, v1); // z0 z1 * *
- v0 = _mm_unpacklo_ps(v0, v1); // x0 x1 y0 y1
-
- v1 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(2, 3, 1, 3)); // y0 y1 y2 0
- v0 = _mm_shuffle_ps(v0, v2, BT_SHUFFLE(0, 1, 0, 3)); // x0 x1 x2 0
- v2 = btCastdTo128f(_mm_move_sd(btCastfTo128d(v2), btCastfTo128d(vT))); // z0 z1 z2 0
-
- return btMatrix3x3(v0, v1, v2);
-#elif defined(BT_USE_NEON)
- // note: zeros the w channel. We can preserve it at the cost of two more vtrn instructions.
- static const uint32x2_t zMask = (const uint32x2_t){static_cast<uint32_t>(-1), 0};
- float32x4x2_t top = vtrnq_f32(m_el[0].mVec128, m_el[1].mVec128); // {x0 x1 z0 z1}, {y0 y1 w0 w1}
- float32x2x2_t bl = vtrn_f32(vget_low_f32(m_el[2].mVec128), vdup_n_f32(0.0f)); // {x2 0 }, {y2 0}
- float32x4_t v0 = vcombine_f32(vget_low_f32(top.val[0]), bl.val[0]);
- float32x4_t v1 = vcombine_f32(vget_low_f32(top.val[1]), bl.val[1]);
- float32x2_t q = (float32x2_t)vand_u32((uint32x2_t)vget_high_f32(m_el[2].mVec128), zMask);
- float32x4_t v2 = vcombine_f32(vget_high_f32(top.val[0]), q); // z0 z1 z2 0
- return btMatrix3x3(v0, v1, v2);
-#else
- return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
- m_el[0].y(), m_el[1].y(), m_el[2].y(),
- m_el[0].z(), m_el[1].z(), m_el[2].z());
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::adjoint() const
-{
- return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
- cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
- cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::inverse() const
-{
- btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
- btScalar det = (*this)[0].dot(co);
- //btFullAssert(det != btScalar(0.0));
- btAssert(det != btScalar(0.0));
- btScalar s = btScalar(1.0) / det;
- return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
- co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
- co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- // zeros w
- // static const __m128i xyzMask = (const __m128i){ -1ULL, 0xffffffffULL };
- __m128 row = m_el[0].mVec128;
- __m128 m0 = _mm_and_ps(m.getRow(0).mVec128, btvFFF0fMask);
- __m128 m1 = _mm_and_ps(m.getRow(1).mVec128, btvFFF0fMask);
- __m128 m2 = _mm_and_ps(m.getRow(2).mVec128, btvFFF0fMask);
- __m128 r0 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0));
- __m128 r1 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0x55));
- __m128 r2 = _mm_mul_ps(m0, _mm_shuffle_ps(row, row, 0xaa));
- row = m_el[1].mVec128;
- r0 = _mm_add_ps(r0, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(m1, _mm_shuffle_ps(row, row, 0xaa)));
- row = m_el[2].mVec128;
- r0 = _mm_add_ps(r0, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(m2, _mm_shuffle_ps(row, row, 0xaa)));
- return btMatrix3x3(r0, r1, r2);
-
-#elif defined BT_USE_NEON
- // zeros w
- static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
- float32x4_t m0 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(0).mVec128, xyzMask);
- float32x4_t m1 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(1).mVec128, xyzMask);
- float32x4_t m2 = (float32x4_t)vandq_u32((uint32x4_t)m.getRow(2).mVec128, xyzMask);
- float32x4_t row = m_el[0].mVec128;
- float32x4_t r0 = vmulq_lane_f32(m0, vget_low_f32(row), 0);
- float32x4_t r1 = vmulq_lane_f32(m0, vget_low_f32(row), 1);
- float32x4_t r2 = vmulq_lane_f32(m0, vget_high_f32(row), 0);
- row = m_el[1].mVec128;
- r0 = vmlaq_lane_f32(r0, m1, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32(r1, m1, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32(r2, m1, vget_high_f32(row), 0);
- row = m_el[2].mVec128;
- r0 = vmlaq_lane_f32(r0, m2, vget_low_f32(row), 0);
- r1 = vmlaq_lane_f32(r1, m2, vget_low_f32(row), 1);
- r2 = vmlaq_lane_f32(r2, m2, vget_high_f32(row), 0);
- return btMatrix3x3(r0, r1, r2);
-#else
- return btMatrix3x3(
- m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
- m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
- m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
- m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
- m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
- m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
- m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
- m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
- m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 a0 = m_el[0].mVec128;
- __m128 a1 = m_el[1].mVec128;
- __m128 a2 = m_el[2].mVec128;
-
- btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- __m128 mx = mT[0].mVec128;
- __m128 my = mT[1].mVec128;
- __m128 mz = mT[2].mVec128;
-
- __m128 r0 = _mm_mul_ps(mx, _mm_shuffle_ps(a0, a0, 0x00));
- __m128 r1 = _mm_mul_ps(mx, _mm_shuffle_ps(a1, a1, 0x00));
- __m128 r2 = _mm_mul_ps(mx, _mm_shuffle_ps(a2, a2, 0x00));
- r0 = _mm_add_ps(r0, _mm_mul_ps(my, _mm_shuffle_ps(a0, a0, 0x55)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(my, _mm_shuffle_ps(a1, a1, 0x55)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(my, _mm_shuffle_ps(a2, a2, 0x55)));
- r0 = _mm_add_ps(r0, _mm_mul_ps(mz, _mm_shuffle_ps(a0, a0, 0xaa)));
- r1 = _mm_add_ps(r1, _mm_mul_ps(mz, _mm_shuffle_ps(a1, a1, 0xaa)));
- r2 = _mm_add_ps(r2, _mm_mul_ps(mz, _mm_shuffle_ps(a2, a2, 0xaa)));
- return btMatrix3x3(r0, r1, r2);
-
-#elif defined BT_USE_NEON
- float32x4_t a0 = m_el[0].mVec128;
- float32x4_t a1 = m_el[1].mVec128;
- float32x4_t a2 = m_el[2].mVec128;
-
- btMatrix3x3 mT = m.transpose(); // we rely on transpose() zeroing w channel so that we don't have to do it here
- float32x4_t mx = mT[0].mVec128;
- float32x4_t my = mT[1].mVec128;
- float32x4_t mz = mT[2].mVec128;
-
- float32x4_t r0 = vmulq_lane_f32(mx, vget_low_f32(a0), 0);
- float32x4_t r1 = vmulq_lane_f32(mx, vget_low_f32(a1), 0);
- float32x4_t r2 = vmulq_lane_f32(mx, vget_low_f32(a2), 0);
- r0 = vmlaq_lane_f32(r0, my, vget_low_f32(a0), 1);
- r1 = vmlaq_lane_f32(r1, my, vget_low_f32(a1), 1);
- r2 = vmlaq_lane_f32(r2, my, vget_low_f32(a2), 1);
- r0 = vmlaq_lane_f32(r0, mz, vget_high_f32(a0), 0);
- r1 = vmlaq_lane_f32(r1, mz, vget_high_f32(a1), 0);
- r2 = vmlaq_lane_f32(r2, mz, vget_high_f32(a2), 0);
- return btMatrix3x3(r0, r1, r2);
-
-#else
- return btMatrix3x3(
- m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
- m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
- m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
-#endif
-}
-
-SIMD_FORCE_INLINE btVector3
-operator*(const btMatrix3x3& m, const btVector3& v)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- return v.dot3(m[0], m[1], m[2]);
-#else
- return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
-#endif
-}
-
-SIMD_FORCE_INLINE btVector3
-operator*(const btVector3& v, const btMatrix3x3& m)
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
-
- const __m128 vv = v.mVec128;
-
- __m128 c0 = bt_splat_ps(vv, 0);
- __m128 c1 = bt_splat_ps(vv, 1);
- __m128 c2 = bt_splat_ps(vv, 2);
-
- c0 = _mm_mul_ps(c0, _mm_and_ps(m[0].mVec128, btvFFF0fMask));
- c1 = _mm_mul_ps(c1, _mm_and_ps(m[1].mVec128, btvFFF0fMask));
- c0 = _mm_add_ps(c0, c1);
- c2 = _mm_mul_ps(c2, _mm_and_ps(m[2].mVec128, btvFFF0fMask));
-
- return btVector3(_mm_add_ps(c0, c2));
-#elif defined(BT_USE_NEON)
- const float32x4_t vv = v.mVec128;
- const float32x2_t vlo = vget_low_f32(vv);
- const float32x2_t vhi = vget_high_f32(vv);
-
- float32x4_t c0, c1, c2;
-
- c0 = (float32x4_t)vandq_s32((int32x4_t)m[0].mVec128, btvFFF0Mask);
- c1 = (float32x4_t)vandq_s32((int32x4_t)m[1].mVec128, btvFFF0Mask);
- c2 = (float32x4_t)vandq_s32((int32x4_t)m[2].mVec128, btvFFF0Mask);
-
- c0 = vmulq_lane_f32(c0, vlo, 0);
- c1 = vmulq_lane_f32(c1, vlo, 1);
- c2 = vmulq_lane_f32(c2, vhi, 0);
- c0 = vaddq_f32(c0, c1);
- c0 = vaddq_f32(c0, c2);
-
- return btVector3(c0);
-#else
- return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
-#endif
-}
-
-SIMD_FORCE_INLINE btMatrix3x3
-operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
-
- __m128 m10 = m1[0].mVec128;
- __m128 m11 = m1[1].mVec128;
- __m128 m12 = m1[2].mVec128;
-
- __m128 m2v = _mm_and_ps(m2[0].mVec128, btvFFF0fMask);
-
- __m128 c0 = bt_splat_ps(m10, 0);
- __m128 c1 = bt_splat_ps(m11, 0);
- __m128 c2 = bt_splat_ps(m12, 0);
-
- c0 = _mm_mul_ps(c0, m2v);
- c1 = _mm_mul_ps(c1, m2v);
- c2 = _mm_mul_ps(c2, m2v);
-
- m2v = _mm_and_ps(m2[1].mVec128, btvFFF0fMask);
-
- __m128 c0_1 = bt_splat_ps(m10, 1);
- __m128 c1_1 = bt_splat_ps(m11, 1);
- __m128 c2_1 = bt_splat_ps(m12, 1);
-
- c0_1 = _mm_mul_ps(c0_1, m2v);
- c1_1 = _mm_mul_ps(c1_1, m2v);
- c2_1 = _mm_mul_ps(c2_1, m2v);
-
- m2v = _mm_and_ps(m2[2].mVec128, btvFFF0fMask);
-
- c0 = _mm_add_ps(c0, c0_1);
- c1 = _mm_add_ps(c1, c1_1);
- c2 = _mm_add_ps(c2, c2_1);
-
- m10 = bt_splat_ps(m10, 2);
- m11 = bt_splat_ps(m11, 2);
- m12 = bt_splat_ps(m12, 2);
-
- m10 = _mm_mul_ps(m10, m2v);
- m11 = _mm_mul_ps(m11, m2v);
- m12 = _mm_mul_ps(m12, m2v);
-
- c0 = _mm_add_ps(c0, m10);
- c1 = _mm_add_ps(c1, m11);
- c2 = _mm_add_ps(c2, m12);
-
- return btMatrix3x3(c0, c1, c2);
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t rv0, rv1, rv2;
- float32x4_t v0, v1, v2;
- float32x4_t mv0, mv1, mv2;
-
- v0 = m1[0].mVec128;
- v1 = m1[1].mVec128;
- v2 = m1[2].mVec128;
-
- mv0 = (float32x4_t)vandq_s32((int32x4_t)m2[0].mVec128, btvFFF0Mask);
- mv1 = (float32x4_t)vandq_s32((int32x4_t)m2[1].mVec128, btvFFF0Mask);
- mv2 = (float32x4_t)vandq_s32((int32x4_t)m2[2].mVec128, btvFFF0Mask);
-
- rv0 = vmulq_lane_f32(mv0, vget_low_f32(v0), 0);
- rv1 = vmulq_lane_f32(mv0, vget_low_f32(v1), 0);
- rv2 = vmulq_lane_f32(mv0, vget_low_f32(v2), 0);
-
- rv0 = vmlaq_lane_f32(rv0, mv1, vget_low_f32(v0), 1);
- rv1 = vmlaq_lane_f32(rv1, mv1, vget_low_f32(v1), 1);
- rv2 = vmlaq_lane_f32(rv2, mv1, vget_low_f32(v2), 1);
-
- rv0 = vmlaq_lane_f32(rv0, mv2, vget_high_f32(v0), 0);
- rv1 = vmlaq_lane_f32(rv1, mv2, vget_high_f32(v1), 0);
- rv2 = vmlaq_lane_f32(rv2, mv2, vget_high_f32(v2), 0);
-
- return btMatrix3x3(rv0, rv1, rv2);
-
-#else
- return btMatrix3x3(
- m2.tdotx(m1[0]), m2.tdoty(m1[0]), m2.tdotz(m1[0]),
- m2.tdotx(m1[1]), m2.tdoty(m1[1]), m2.tdotz(m1[1]),
- m2.tdotx(m1[2]), m2.tdoty(m1[2]), m2.tdotz(m1[2]));
-#endif
-}
-
-/*
-SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
-return btMatrix3x3(
-m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
-m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
-m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
-m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
-m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
-m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
-m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
-m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
-m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
-}
-*/
-
-/**@brief Equality operator between two matrices
-* It will test all elements are equal. */
-SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
-{
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
-
- __m128 c0, c1, c2;
-
- c0 = _mm_cmpeq_ps(m1[0].mVec128, m2[0].mVec128);
- c1 = _mm_cmpeq_ps(m1[1].mVec128, m2[1].mVec128);
- c2 = _mm_cmpeq_ps(m1[2].mVec128, m2[2].mVec128);
-
- c0 = _mm_and_ps(c0, c1);
- c0 = _mm_and_ps(c0, c2);
-
- int m = _mm_movemask_ps((__m128)c0);
- return (0x7 == (m & 0x7));
-
-#else
- return (m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
- m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
- m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2]);
-#endif
-}
-
-///for serialization
-struct btMatrix3x3FloatData
-{
- btVector3FloatData m_el[3];
-};
-
-///for serialization
-struct btMatrix3x3DoubleData
-{
- btVector3DoubleData m_el[3];
-};
-
-SIMD_FORCE_INLINE void btMatrix3x3::serialize(struct btMatrix3x3Data& dataOut) const
-{
- for (int i = 0; i < 3; i++)
- m_el[i].serialize(dataOut.m_el[i]);
-}
-
-SIMD_FORCE_INLINE void btMatrix3x3::serializeFloat(struct btMatrix3x3FloatData& dataOut) const
-{
- for (int i = 0; i < 3; i++)
- m_el[i].serializeFloat(dataOut.m_el[i]);
-}
-
-SIMD_FORCE_INLINE void btMatrix3x3::deSerialize(const struct btMatrix3x3Data& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerialize(dataIn.m_el[i]);
-}
-
-SIMD_FORCE_INLINE void btMatrix3x3::deSerializeFloat(const struct btMatrix3x3FloatData& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerializeFloat(dataIn.m_el[i]);
-}
-
-SIMD_FORCE_INLINE void btMatrix3x3::deSerializeDouble(const struct btMatrix3x3DoubleData& dataIn)
-{
- for (int i = 0; i < 3; i++)
- m_el[i].deSerializeDouble(dataIn.m_el[i]);
-}
-
-#endif //BT_MATRIX3x3_H
diff --git a/thirdparty/bullet/LinearMath/btMatrixX.h b/thirdparty/bullet/LinearMath/btMatrixX.h
deleted file mode 100644
index bb0f0dd259..0000000000
--- a/thirdparty/bullet/LinearMath/btMatrixX.h
+++ /dev/null
@@ -1,532 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2013 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-///original version written by Erwin Coumans, October 2013
-
-#ifndef BT_MATRIX_X_H
-#define BT_MATRIX_X_H
-
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btAlignedObjectArray.h"
-#include <stdio.h>
-
-//#define BT_DEBUG_OSTREAM
-#ifdef BT_DEBUG_OSTREAM
-#include <iostream>
-#include <iomanip> // std::setw
-#endif //BT_DEBUG_OSTREAM
-
-class btIntSortPredicate
-{
-public:
- bool operator()(const int& a, const int& b) const
- {
- return a < b;
- }
-};
-
-template <typename T>
-struct btVectorX
-{
- btAlignedObjectArray<T> m_storage;
-
- btVectorX()
- {
- }
- btVectorX(int numRows)
- {
- m_storage.resize(numRows);
- }
-
- void resize(int rows)
- {
- m_storage.resize(rows);
- }
- int cols() const
- {
- return 1;
- }
- int rows() const
- {
- return m_storage.size();
- }
- int size() const
- {
- return rows();
- }
-
- T nrm2() const
- {
- T norm = T(0);
-
- int nn = rows();
-
- {
- if (nn == 1)
- {
- norm = btFabs((*this)[0]);
- }
- else
- {
- T scale = 0.0;
- T ssq = 1.0;
-
- /* The following loop is equivalent to this call to the LAPACK
- auxiliary routine: CALL SLASSQ( N, X, INCX, SCALE, SSQ ) */
-
- for (int ix = 0; ix < nn; ix++)
- {
- if ((*this)[ix] != 0.0)
- {
- T absxi = btFabs((*this)[ix]);
- if (scale < absxi)
- {
- T temp;
- temp = scale / absxi;
- ssq = ssq * (temp * temp) + BT_ONE;
- scale = absxi;
- }
- else
- {
- T temp;
- temp = absxi / scale;
- ssq += temp * temp;
- }
- }
- }
- norm = scale * sqrt(ssq);
- }
- }
- return norm;
- }
- void setZero()
- {
- if (m_storage.size())
- {
- // for (int i=0;i<m_storage.size();i++)
- // m_storage[i]=0;
- //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
- btSetZero(&m_storage[0], m_storage.size());
- }
- }
- const T& operator[](int index) const
- {
- return m_storage[index];
- }
-
- T& operator[](int index)
- {
- return m_storage[index];
- }
-
- T* getBufferPointerWritable()
- {
- return m_storage.size() ? &m_storage[0] : 0;
- }
-
- const T* getBufferPointer() const
- {
- return m_storage.size() ? &m_storage[0] : 0;
- }
-};
-/*
- template <typename T>
- void setElem(btMatrixX<T>& mat, int row, int col, T val)
- {
- mat.setElem(row,col,val);
- }
- */
-
-template <typename T>
-struct btMatrixX
-{
- int m_rows;
- int m_cols;
- int m_operations;
- int m_resizeOperations;
- int m_setElemOperations;
-
- btAlignedObjectArray<T> m_storage;
- mutable btAlignedObjectArray<btAlignedObjectArray<int> > m_rowNonZeroElements1;
-
- T* getBufferPointerWritable()
- {
- return m_storage.size() ? &m_storage[0] : 0;
- }
-
- const T* getBufferPointer() const
- {
- return m_storage.size() ? &m_storage[0] : 0;
- }
- btMatrixX()
- : m_rows(0),
- m_cols(0),
- m_operations(0),
- m_resizeOperations(0),
- m_setElemOperations(0)
- {
- }
- btMatrixX(int rows, int cols)
- : m_rows(rows),
- m_cols(cols),
- m_operations(0),
- m_resizeOperations(0),
- m_setElemOperations(0)
- {
- resize(rows, cols);
- }
- void resize(int rows, int cols)
- {
- m_resizeOperations++;
- m_rows = rows;
- m_cols = cols;
- {
- BT_PROFILE("m_storage.resize");
- m_storage.resize(rows * cols);
- }
- }
- int cols() const
- {
- return m_cols;
- }
- int rows() const
- {
- return m_rows;
- }
- ///we don't want this read/write operator(), because we cannot keep track of non-zero elements, use setElem instead
- /*T& operator() (int row,int col)
- {
- return m_storage[col*m_rows+row];
- }
- */
-
- void addElem(int row, int col, T val)
- {
- if (val)
- {
- if (m_storage[col + row * m_cols] == 0.f)
- {
- setElem(row, col, val);
- }
- else
- {
- m_storage[row * m_cols + col] += val;
- }
- }
- }
-
- void setElem(int row, int col, T val)
- {
- m_setElemOperations++;
- m_storage[row * m_cols + col] = val;
- }
-
- void mulElem(int row, int col, T val)
- {
- m_setElemOperations++;
- //mul doesn't change sparsity info
-
- m_storage[row * m_cols + col] *= val;
- }
-
- void copyLowerToUpperTriangle()
- {
- int count = 0;
- for (int row = 0; row < rows(); row++)
- {
- for (int col = 0; col < row; col++)
- {
- setElem(col, row, (*this)(row, col));
- count++;
- }
- }
- //printf("copyLowerToUpperTriangle copied %d elements out of %dx%d=%d\n", count,rows(),cols(),cols()*rows());
- }
-
- const T& operator()(int row, int col) const
- {
- return m_storage[col + row * m_cols];
- }
-
- void setZero()
- {
- {
- BT_PROFILE("storage=0");
- if (m_storage.size())
- {
- btSetZero(&m_storage[0], m_storage.size());
- }
- //memset(&m_storage[0],0,sizeof(T)*m_storage.size());
- //for (int i=0;i<m_storage.size();i++)
- // m_storage[i]=0;
- }
- }
-
- void setIdentity()
- {
- btAssert(rows() == cols());
-
- setZero();
- for (int row = 0; row < rows(); row++)
- {
- setElem(row, row, 1);
- }
- }
-
- void printMatrix(const char* msg) const
- {
- printf("%s ---------------------\n", msg);
- for (int i = 0; i < rows(); i++)
- {
- printf("\n");
- for (int j = 0; j < cols(); j++)
- {
- printf("%2.1f\t", (*this)(i, j));
- }
- }
- printf("\n---------------------\n");
- }
-
- void rowComputeNonZeroElements() const
- {
- m_rowNonZeroElements1.resize(rows());
- for (int i = 0; i < rows(); i++)
- {
- m_rowNonZeroElements1[i].resize(0);
- for (int j = 0; j < cols(); j++)
- {
- if ((*this)(i, j) != 0.f)
- {
- m_rowNonZeroElements1[i].push_back(j);
- }
- }
- }
- }
- btMatrixX transpose() const
- {
- //transpose is optimized for sparse matrices
- btMatrixX tr(m_cols, m_rows);
- tr.setZero();
- for (int i = 0; i < m_cols; i++)
- for (int j = 0; j < m_rows; j++)
- {
- T v = (*this)(j, i);
- if (v)
- {
- tr.setElem(i, j, v);
- }
- }
- return tr;
- }
-
- btMatrixX operator*(const btMatrixX& other)
- {
- //btMatrixX*btMatrixX implementation, brute force
- btAssert(cols() == other.rows());
-
- btMatrixX res(rows(), other.cols());
- res.setZero();
- // BT_PROFILE("btMatrixX mul");
- for (int i = 0; i < rows(); ++i)
- {
- {
- for (int j = 0; j < other.cols(); ++j)
- {
- T dotProd = 0;
- {
- {
- int c = cols();
-
- for (int k = 0; k < c; k++)
- {
- T w = (*this)(i, k);
- if (other(k, j) != 0.f)
- {
- dotProd += w * other(k, j);
- }
- }
- }
- }
- if (dotProd)
- res.setElem(i, j, dotProd);
- }
- }
- }
- return res;
- }
-
- // this assumes the 4th and 8th rows of B and C are zero.
- void multiplyAdd2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
- {
- const btScalar* bb = B;
- for (int i = 0; i < numRows; i++)
- {
- const btScalar* cc = C;
- for (int j = 0; j < numRowsOther; j++)
- {
- btScalar sum;
- sum = bb[0] * cc[0];
- sum += bb[1] * cc[1];
- sum += bb[2] * cc[2];
- sum += bb[4] * cc[4];
- sum += bb[5] * cc[5];
- sum += bb[6] * cc[6];
- addElem(row + i, col + j, sum);
- cc += 8;
- }
- bb += 8;
- }
- }
-
- void multiply2_p8r(const btScalar* B, const btScalar* C, int numRows, int numRowsOther, int row, int col)
- {
- btAssert(numRows > 0 && numRowsOther > 0 && B && C);
- const btScalar* bb = B;
- for (int i = 0; i < numRows; i++)
- {
- const btScalar* cc = C;
- for (int j = 0; j < numRowsOther; j++)
- {
- btScalar sum;
- sum = bb[0] * cc[0];
- sum += bb[1] * cc[1];
- sum += bb[2] * cc[2];
- sum += bb[4] * cc[4];
- sum += bb[5] * cc[5];
- sum += bb[6] * cc[6];
- setElem(row + i, col + j, sum);
- cc += 8;
- }
- bb += 8;
- }
- }
-
- void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const T value)
- {
- int numRows = rowend + 1 - rowstart;
- int numCols = colend + 1 - colstart;
-
- for (int row = 0; row < numRows; row++)
- {
- for (int col = 0; col < numCols; col++)
- {
- setElem(rowstart + row, colstart + col, value);
- }
- }
- }
-
- void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btMatrixX& block)
- {
- btAssert(rowend + 1 - rowstart == block.rows());
- btAssert(colend + 1 - colstart == block.cols());
- for (int row = 0; row < block.rows(); row++)
- {
- for (int col = 0; col < block.cols(); col++)
- {
- setElem(rowstart + row, colstart + col, block(row, col));
- }
- }
- }
- void setSubMatrix(int rowstart, int colstart, int rowend, int colend, const btVectorX<T>& block)
- {
- btAssert(rowend + 1 - rowstart == block.rows());
- btAssert(colend + 1 - colstart == block.cols());
- for (int row = 0; row < block.rows(); row++)
- {
- for (int col = 0; col < block.cols(); col++)
- {
- setElem(rowstart + row, colstart + col, block[row]);
- }
- }
- }
-
- btMatrixX negative()
- {
- btMatrixX neg(rows(), cols());
- for (int i = 0; i < rows(); i++)
- for (int j = 0; j < cols(); j++)
- {
- T v = (*this)(i, j);
- neg.setElem(i, j, -v);
- }
- return neg;
- }
-};
-
-typedef btMatrixX<float> btMatrixXf;
-typedef btVectorX<float> btVectorXf;
-
-typedef btMatrixX<double> btMatrixXd;
-typedef btVectorX<double> btVectorXd;
-
-#ifdef BT_DEBUG_OSTREAM
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const btMatrixX<T>& mat)
-{
- os << " [";
- //printf("%s ---------------------\n",msg);
- for (int i = 0; i < mat.rows(); i++)
- {
- for (int j = 0; j < mat.cols(); j++)
- {
- os << std::setw(12) << mat(i, j);
- }
- if (i != mat.rows() - 1)
- os << std::endl
- << " ";
- }
- os << " ]";
- //printf("\n---------------------\n");
-
- return os;
-}
-template <typename T>
-std::ostream& operator<<(std::ostream& os, const btVectorX<T>& mat)
-{
- os << " [";
- //printf("%s ---------------------\n",msg);
- for (int i = 0; i < mat.rows(); i++)
- {
- os << std::setw(12) << mat[i];
- if (i != mat.rows() - 1)
- os << std::endl
- << " ";
- }
- os << " ]";
- //printf("\n---------------------\n");
-
- return os;
-}
-
-#endif //BT_DEBUG_OSTREAM
-
-inline void setElem(btMatrixXd& mat, int row, int col, double val)
-{
- mat.setElem(row, col, val);
-}
-
-inline void setElem(btMatrixXf& mat, int row, int col, float val)
-{
- mat.setElem(row, col, val);
-}
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btVectorXu btVectorXd
-#define btMatrixXu btMatrixXd
-#else
-#define btVectorXu btVectorXf
-#define btMatrixXu btMatrixXf
-#endif //BT_USE_DOUBLE_PRECISION
-
-#endif //BT_MATRIX_H_H
diff --git a/thirdparty/bullet/LinearMath/btMinMax.h b/thirdparty/bullet/LinearMath/btMinMax.h
deleted file mode 100644
index 92fea0275a..0000000000
--- a/thirdparty/bullet/LinearMath/btMinMax.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GEN_MINMAX_H
-#define BT_GEN_MINMAX_H
-
-#include "btScalar.h"
-
-template <class T>
-SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b)
-{
- return a < b ? a : b;
-}
-
-template <class T>
-SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b)
-{
- return a > b ? a : b;
-}
-
-template <class T>
-SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub)
-{
- return a < lb ? lb : (ub < a ? ub : a);
-}
-
-template <class T>
-SIMD_FORCE_INLINE void btSetMin(T& a, const T& b)
-{
- if (b < a)
- {
- a = b;
- }
-}
-
-template <class T>
-SIMD_FORCE_INLINE void btSetMax(T& a, const T& b)
-{
- if (a < b)
- {
- a = b;
- }
-}
-
-template <class T>
-SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub)
-{
- if (a < lb)
- {
- a = lb;
- }
- else if (ub < a)
- {
- a = ub;
- }
-}
-
-#endif //BT_GEN_MINMAX_H
diff --git a/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h b/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h
deleted file mode 100644
index 33bab8d650..0000000000
--- a/thirdparty/bullet/LinearMath/btModifiedGramSchmidt.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//
-// btModifiedGramSchmidt.h
-// LinearMath
-//
-// Created by Xuchen Han on 4/4/20.
-//
-
-#ifndef btModifiedGramSchmidt_h
-#define btModifiedGramSchmidt_h
-
-#include "btReducedVector.h"
-#include "btAlignedObjectArray.h"
-#include <iostream>
-#include <cmath>
-template<class TV>
-class btModifiedGramSchmidt
-{
-public:
- btAlignedObjectArray<TV> m_in;
- btAlignedObjectArray<TV> m_out;
-
- btModifiedGramSchmidt(const btAlignedObjectArray<TV>& vecs): m_in(vecs)
- {
- m_out.resize(0);
- }
-
- void solve()
- {
- m_out.resize(m_in.size());
- for (int i = 0; i < m_in.size(); ++i)
- {
-// printf("========= starting %d ==========\n", i);
- TV v(m_in[i]);
-// v.print();
- for (int j = 0; j < i; ++j)
- {
- v = v - v.proj(m_out[j]);
-// v.print();
- }
- v.normalize();
- m_out[i] = v;
-// v.print();
- }
- }
-
- void test()
- {
- std::cout << SIMD_EPSILON << std::endl;
- printf("=======inputs=========\n");
- for (int i = 0; i < m_out.size(); ++i)
- {
- m_in[i].print();
- }
- printf("=======output=========\n");
- for (int i = 0; i < m_out.size(); ++i)
- {
- m_out[i].print();
- }
- btScalar eps = SIMD_EPSILON;
- for (int i = 0; i < m_out.size(); ++i)
- {
- for (int j = 0; j < m_out.size(); ++j)
- {
- if (i == j)
- {
- if (std::abs(1.0-m_out[i].dot(m_out[j])) > eps)// && std::abs(m_out[i].dot(m_out[j])) > eps)
- {
- printf("vec[%d] is not unit, norm squared = %f\n", i,m_out[i].dot(m_out[j]));
- }
- }
- else
- {
- if (std::abs(m_out[i].dot(m_out[j])) > eps)
- {
- printf("vec[%d] and vec[%d] is not orthogonal, dot product = %f\n", i, j, m_out[i].dot(m_out[j]));
- }
- }
- }
- }
- }
-};
-template class btModifiedGramSchmidt<btReducedVector>;
-#endif /* btModifiedGramSchmidt_h */
diff --git a/thirdparty/bullet/LinearMath/btMotionState.h b/thirdparty/bullet/LinearMath/btMotionState.h
deleted file mode 100644
index ae6a51611d..0000000000
--- a/thirdparty/bullet/LinearMath/btMotionState.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_MOTIONSTATE_H
-#define BT_MOTIONSTATE_H
-
-#include "btTransform.h"
-
-///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
-///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
-class btMotionState
-{
-public:
- virtual ~btMotionState()
- {
- }
-
- virtual void getWorldTransform(btTransform& worldTrans) const = 0;
-
- //Bullet only calls the update of worldtransform for active objects
- virtual void setWorldTransform(const btTransform& worldTrans) = 0;
-};
-
-#endif //BT_MOTIONSTATE_H
diff --git a/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp b/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp
deleted file mode 100644
index d9c72a8014..0000000000
--- a/thirdparty/bullet/LinearMath/btPolarDecomposition.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "btPolarDecomposition.h"
-#include "btMinMax.h"
-
-namespace
-{
-btScalar abs_column_sum(const btMatrix3x3& a, int i)
-{
- return btFabs(a[0][i]) + btFabs(a[1][i]) + btFabs(a[2][i]);
-}
-
-btScalar abs_row_sum(const btMatrix3x3& a, int i)
-{
- return btFabs(a[i][0]) + btFabs(a[i][1]) + btFabs(a[i][2]);
-}
-
-btScalar p1_norm(const btMatrix3x3& a)
-{
- const btScalar sum0 = abs_column_sum(a, 0);
- const btScalar sum1 = abs_column_sum(a, 1);
- const btScalar sum2 = abs_column_sum(a, 2);
- return btMax(btMax(sum0, sum1), sum2);
-}
-
-btScalar pinf_norm(const btMatrix3x3& a)
-{
- const btScalar sum0 = abs_row_sum(a, 0);
- const btScalar sum1 = abs_row_sum(a, 1);
- const btScalar sum2 = abs_row_sum(a, 2);
- return btMax(btMax(sum0, sum1), sum2);
-}
-} // namespace
-
-btPolarDecomposition::btPolarDecomposition(btScalar tolerance, unsigned int maxIterations)
- : m_tolerance(tolerance), m_maxIterations(maxIterations)
-{
-}
-
-unsigned int btPolarDecomposition::decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const
-{
- // Use the 'u' and 'h' matrices for intermediate calculations
- u = a;
- h = a.inverse();
-
- for (unsigned int i = 0; i < m_maxIterations; ++i)
- {
- const btScalar h_1 = p1_norm(h);
- const btScalar h_inf = pinf_norm(h);
- const btScalar u_1 = p1_norm(u);
- const btScalar u_inf = pinf_norm(u);
-
- const btScalar h_norm = h_1 * h_inf;
- const btScalar u_norm = u_1 * u_inf;
-
- // The matrix is effectively singular so we cannot invert it
- if (btFuzzyZero(h_norm) || btFuzzyZero(u_norm))
- break;
-
- const btScalar gamma = btPow(h_norm / u_norm, 0.25f);
- const btScalar inv_gamma = btScalar(1.0) / gamma;
-
- // Determine the delta to 'u'
- const btMatrix3x3 delta = (u * (gamma - btScalar(2.0)) + h.transpose() * inv_gamma) * btScalar(0.5);
-
- // Update the matrices
- u += delta;
- h = u.inverse();
-
- // Check for convergence
- if (p1_norm(delta) <= m_tolerance * u_1)
- {
- h = u.transpose() * a;
- h = (h + h.transpose()) * 0.5;
- return i;
- }
- }
-
- // The algorithm has failed to converge to the specified tolerance, but we
- // want to make sure that the matrices returned are in the right form.
- h = u.transpose() * a;
- h = (h + h.transpose()) * 0.5;
-
- return m_maxIterations;
-}
-
-unsigned int btPolarDecomposition::maxIterations() const
-{
- return m_maxIterations;
-}
-
-unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h)
-{
- static btPolarDecomposition polar;
- return polar.decompose(a, u, h);
-}
diff --git a/thirdparty/bullet/LinearMath/btPolarDecomposition.h b/thirdparty/bullet/LinearMath/btPolarDecomposition.h
deleted file mode 100644
index bf29140a14..0000000000
--- a/thirdparty/bullet/LinearMath/btPolarDecomposition.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef POLARDECOMPOSITION_H
-#define POLARDECOMPOSITION_H
-
-#include "btMatrix3x3.h"
-
-/**
- * This class is used to compute the polar decomposition of a matrix. In
- * general, the polar decomposition factorizes a matrix, A, into two parts: a
- * unitary matrix (U) and a positive, semi-definite Hermitian matrix (H).
- * However, in this particular implementation the original matrix, A, is
- * required to be a square 3x3 matrix with real elements. This means that U will
- * be an orthogonal matrix and H with be a positive-definite, symmetric matrix.
- */
-class btPolarDecomposition
-{
-public:
- /**
- * Creates an instance with optional parameters.
- *
- * @param tolerance - the tolerance used to determine convergence of the
- * algorithm
- * @param maxIterations - the maximum number of iterations used to achieve
- * convergence
- */
- btPolarDecomposition(btScalar tolerance = btScalar(0.0001),
- unsigned int maxIterations = 16);
-
- /**
- * Decomposes a matrix into orthogonal and symmetric, positive-definite
- * parts. If the number of iterations returned by this function is equal to
- * the maximum number of iterations, the algorithm has failed to converge.
- *
- * @param a - the original matrix
- * @param u - the resulting orthogonal matrix
- * @param h - the resulting symmetric matrix
- *
- * @return the number of iterations performed by the algorithm.
- */
- unsigned int decompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h) const;
-
- /**
- * Returns the maximum number of iterations that this algorithm will perform
- * to achieve convergence.
- *
- * @return maximum number of iterations
- */
- unsigned int maxIterations() const;
-
-private:
- btScalar m_tolerance;
- unsigned int m_maxIterations;
-};
-
-/**
- * This functions decomposes the matrix 'a' into two parts: an orthogonal matrix
- * 'u' and a symmetric, positive-definite matrix 'h'. If the number of
- * iterations returned by this function is equal to
- * btPolarDecomposition::DEFAULT_MAX_ITERATIONS, the algorithm has failed to
- * converge.
- *
- * @param a - the original matrix
- * @param u - the resulting orthogonal matrix
- * @param h - the resulting symmetric matrix
- *
- * @return the number of iterations performed by the algorithm.
- */
-unsigned int polarDecompose(const btMatrix3x3& a, btMatrix3x3& u, btMatrix3x3& h);
-
-#endif // POLARDECOMPOSITION_H
diff --git a/thirdparty/bullet/LinearMath/btPoolAllocator.h b/thirdparty/bullet/LinearMath/btPoolAllocator.h
deleted file mode 100644
index 4e7b49660a..0000000000
--- a/thirdparty/bullet/LinearMath/btPoolAllocator.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef _BT_POOL_ALLOCATOR_H
-#define _BT_POOL_ALLOCATOR_H
-
-#include "btScalar.h"
-#include "btAlignedAllocator.h"
-#include "btThreads.h"
-
-///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
-class btPoolAllocator
-{
- int m_elemSize;
- int m_maxElements;
- int m_freeCount;
- void* m_firstFree;
- unsigned char* m_pool;
- btSpinMutex m_mutex; // only used if BT_THREADSAFE
-
-public:
- btPoolAllocator(int elemSize, int maxElements)
- : m_elemSize(elemSize),
- m_maxElements(maxElements)
- {
- m_pool = (unsigned char*)btAlignedAlloc(static_cast<unsigned int>(m_elemSize * m_maxElements), 16);
-
- unsigned char* p = m_pool;
- m_firstFree = p;
- m_freeCount = m_maxElements;
- int count = m_maxElements;
- while (--count)
- {
- *(void**)p = (p + m_elemSize);
- p += m_elemSize;
- }
- *(void**)p = 0;
- }
-
- ~btPoolAllocator()
- {
- btAlignedFree(m_pool);
- }
-
- int getFreeCount() const
- {
- return m_freeCount;
- }
-
- int getUsedCount() const
- {
- return m_maxElements - m_freeCount;
- }
-
- int getMaxCount() const
- {
- return m_maxElements;
- }
-
- void* allocate(int size)
- {
- // release mode fix
- (void)size;
- btMutexLock(&m_mutex);
- btAssert(!size || size <= m_elemSize);
- //btAssert(m_freeCount>0); // should return null if all full
- void* result = m_firstFree;
- if (NULL != m_firstFree)
- {
- m_firstFree = *(void**)m_firstFree;
- --m_freeCount;
- }
- btMutexUnlock(&m_mutex);
- return result;
- }
-
- bool validPtr(void* ptr)
- {
- if (ptr)
- {
- if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
- {
- return true;
- }
- }
- return false;
- }
-
- void freeMemory(void* ptr)
- {
- if (ptr)
- {
- btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
-
- btMutexLock(&m_mutex);
- *(void**)ptr = m_firstFree;
- m_firstFree = ptr;
- ++m_freeCount;
- btMutexUnlock(&m_mutex);
- }
- }
-
- int getElementSize() const
- {
- return m_elemSize;
- }
-
- unsigned char* getPoolAddress()
- {
- return m_pool;
- }
-
- const unsigned char* getPoolAddress() const
- {
- return m_pool;
- }
-};
-
-#endif //_BT_POOL_ALLOCATOR_H
diff --git a/thirdparty/bullet/LinearMath/btQuadWord.h b/thirdparty/bullet/LinearMath/btQuadWord.h
deleted file mode 100644
index ab2d3175ad..0000000000
--- a/thirdparty/bullet/LinearMath/btQuadWord.h
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMD_QUADWORD_H
-#define BT_SIMD_QUADWORD_H
-
-#include "btScalar.h"
-#include "btMinMax.h"
-
-#if defined(__CELLOS_LV2) && defined(__SPU__)
-#include <altivec.h>
-#endif
-
-/**@brief The btQuadWord class is base class for btVector3 and btQuaternion.
- * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
- */
-#ifndef USE_LIBSPE2
-ATTRIBUTE_ALIGNED16(class)
-btQuadWord
-#else
-class btQuadWord
-#endif
-{
-protected:
-#if defined(__SPU__) && defined(__CELLOS_LV2__)
- union {
- vec_float4 mVec128;
- btScalar m_floats[4];
- };
-
-public:
- vec_float4 get128() const
- {
- return mVec128;
- }
-
-protected:
-#else //__CELLOS_LV2__ __SPU__
-
-#if defined(BT_USE_SSE) || defined(BT_USE_NEON)
- union {
- btSimdFloat4 mVec128;
- btScalar m_floats[4];
- };
-
-public:
- SIMD_FORCE_INLINE btSimdFloat4 get128() const
- {
- return mVec128;
- }
- SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
- {
- mVec128 = v128;
- }
-#else
- btScalar m_floats[4];
-#endif // BT_USE_SSE
-
-#endif //__CELLOS_LV2__ __SPU__
-
-public:
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
-
- // Set Vector
- SIMD_FORCE_INLINE btQuadWord(const btSimdFloat4 vec)
- {
- mVec128 = vec;
- }
-
- // Copy constructor
- SIMD_FORCE_INLINE btQuadWord(const btQuadWord& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- // Assignment Operator
- SIMD_FORCE_INLINE btQuadWord&
- operator=(const btQuadWord& v)
- {
- mVec128 = v.mVec128;
-
- return *this;
- }
-
-#endif
-
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
- /**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
- /**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
- /**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
- /**@brief Return the w value */
- SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
-
- //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
- //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
- ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
- SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
-
- SIMD_FORCE_INLINE bool operator==(const btQuadWord& other) const
- {
-#ifdef BT_USE_SSE
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3] == other.m_floats[3]) &&
- (m_floats[2] == other.m_floats[2]) &&
- (m_floats[1] == other.m_floats[1]) &&
- (m_floats[0] == other.m_floats[0]));
-#endif
- }
-
- SIMD_FORCE_INLINE bool operator!=(const btQuadWord& other) const
- {
- return !(*this == other);
- }
-
- /**@brief Set x,y,z and zero w
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = 0.f;
- }
-
- /* void getValue(btScalar *m) const
- {
- m[0] = m_floats[0];
- m[1] = m_floats[1];
- m[2] = m_floats[2];
- }
-*/
- /**@brief Set the values
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = _w;
- }
- /**@brief No initialization constructor */
- SIMD_FORCE_INLINE btQuadWord()
- // :m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
- {
- }
-
- /**@brief Three argument constructor (zeros w)
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
- SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = 0.0f;
- }
-
- /**@brief Initializing constructor
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- SIMD_FORCE_INLINE btQuadWord(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- {
- m_floats[0] = _x, m_floats[1] = _y, m_floats[2] = _z, m_floats[3] = _w;
- }
-
- /**@brief Set each element to the max of the current values and the values of another btQuadWord
- * @param other The other btQuadWord to compare with
- */
- SIMD_FORCE_INLINE void setMax(const btQuadWord& other)
- {
-#ifdef BT_USE_SSE
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
-#else
- btSetMax(m_floats[0], other.m_floats[0]);
- btSetMax(m_floats[1], other.m_floats[1]);
- btSetMax(m_floats[2], other.m_floats[2]);
- btSetMax(m_floats[3], other.m_floats[3]);
-#endif
- }
- /**@brief Set each element to the min of the current values and the values of another btQuadWord
- * @param other The other btQuadWord to compare with
- */
- SIMD_FORCE_INLINE void setMin(const btQuadWord& other)
- {
-#ifdef BT_USE_SSE
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
-#else
- btSetMin(m_floats[0], other.m_floats[0]);
- btSetMin(m_floats[1], other.m_floats[1]);
- btSetMin(m_floats[2], other.m_floats[2]);
- btSetMin(m_floats[3], other.m_floats[3]);
-#endif
- }
-};
-
-#endif //BT_SIMD_QUADWORD_H
diff --git a/thirdparty/bullet/LinearMath/btQuaternion.h b/thirdparty/bullet/LinearMath/btQuaternion.h
deleted file mode 100644
index 53e8169b80..0000000000
--- a/thirdparty/bullet/LinearMath/btQuaternion.h
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SIMD__QUATERNION_H_
-#define BT_SIMD__QUATERNION_H_
-
-#include "btVector3.h"
-#include "btQuadWord.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btQuaternionData btQuaternionDoubleData
-#define btQuaternionDataName "btQuaternionDoubleData"
-#else
-#define btQuaternionData btQuaternionFloatData
-#define btQuaternionDataName "btQuaternionFloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-#ifdef BT_USE_SSE
-
-//const __m128 ATTRIBUTE_ALIGNED16(vOnes) = {1.0f, 1.0f, 1.0f, 1.0f};
-#define vOnes (_mm_set_ps(1.0f, 1.0f, 1.0f, 1.0f))
-
-#endif
-
-#if defined(BT_USE_SSE)
-
-#define vQInv (_mm_set_ps(+0.0f, -0.0f, -0.0f, -0.0f))
-#define vPPPM (_mm_set_ps(-0.0f, +0.0f, +0.0f, +0.0f))
-
-#elif defined(BT_USE_NEON)
-
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(vQInv) = {-0.0f, -0.0f, -0.0f, +0.0f};
-const btSimdFloat4 ATTRIBUTE_ALIGNED16(vPPPM) = {+0.0f, +0.0f, +0.0f, -0.0f};
-
-#endif
-
-/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
-class btQuaternion : public btQuadWord
-{
-public:
- /**@brief No initialization constructor */
- btQuaternion() {}
-
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- // Set Vector
- SIMD_FORCE_INLINE btQuaternion(const btSimdFloat4 vec)
- {
- mVec128 = vec;
- }
-
- // Copy constructor
- SIMD_FORCE_INLINE btQuaternion(const btQuaternion& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- // Assignment Operator
- SIMD_FORCE_INLINE btQuaternion&
- operator=(const btQuaternion& v)
- {
- mVec128 = v.mVec128;
-
- return *this;
- }
-
-#endif
-
- // template <typename btScalar>
- // explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
- /**@brief Constructor from scalars */
- btQuaternion(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- : btQuadWord(_x, _y, _z, _w)
- {
- }
- /**@brief Axis angle Constructor
- * @param axis The axis which the rotation is around
- * @param angle The magnitude of the rotation around the angle (Radians) */
- btQuaternion(const btVector3& _axis, const btScalar& _angle)
- {
- setRotation(_axis, _angle);
- }
- /**@brief Constructor from Euler angles
- * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
- * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
- * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
- btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
- {
-#ifndef BT_EULER_DEFAULT_ZYX
- setEuler(yaw, pitch, roll);
-#else
- setEulerZYX(yaw, pitch, roll);
-#endif
- }
- /**@brief Set the rotation using axis angle notation
- * @param axis The axis around which to rotate
- * @param angle The magnitude of the rotation in Radians */
- void setRotation(const btVector3& axis, const btScalar& _angle)
- {
- btScalar d = axis.length();
- btAssert(d != btScalar(0.0));
- btScalar s = btSin(_angle * btScalar(0.5)) / d;
- setValue(axis.x() * s, axis.y() * s, axis.z() * s,
- btCos(_angle * btScalar(0.5)));
- }
- /**@brief Set the quaternion using Euler angles
- * @param yaw Angle around Y
- * @param pitch Angle around X
- * @param roll Angle around Z */
- void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
- {
- btScalar halfYaw = btScalar(yaw) * btScalar(0.5);
- btScalar halfPitch = btScalar(pitch) * btScalar(0.5);
- btScalar halfRoll = btScalar(roll) * btScalar(0.5);
- btScalar cosYaw = btCos(halfYaw);
- btScalar sinYaw = btSin(halfYaw);
- btScalar cosPitch = btCos(halfPitch);
- btScalar sinPitch = btSin(halfPitch);
- btScalar cosRoll = btCos(halfRoll);
- btScalar sinRoll = btSin(halfRoll);
- setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
- sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
- }
- /**@brief Set the quaternion using euler angles
- * @param yaw Angle around Z
- * @param pitch Angle around Y
- * @param roll Angle around X */
- void setEulerZYX(const btScalar& yawZ, const btScalar& pitchY, const btScalar& rollX)
- {
- btScalar halfYaw = btScalar(yawZ) * btScalar(0.5);
- btScalar halfPitch = btScalar(pitchY) * btScalar(0.5);
- btScalar halfRoll = btScalar(rollX) * btScalar(0.5);
- btScalar cosYaw = btCos(halfYaw);
- btScalar sinYaw = btSin(halfYaw);
- btScalar cosPitch = btCos(halfPitch);
- btScalar sinPitch = btSin(halfPitch);
- btScalar cosRoll = btCos(halfRoll);
- btScalar sinRoll = btSin(halfRoll);
- setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
- cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
- cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
- cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
- }
-
- /**@brief Get the euler angles from this quaternion
- * @param yaw Angle around Z
- * @param pitch Angle around Y
- * @param roll Angle around X */
- void getEulerZYX(btScalar& yawZ, btScalar& pitchY, btScalar& rollX) const
- {
- btScalar squ;
- btScalar sqx;
- btScalar sqy;
- btScalar sqz;
- btScalar sarg;
- sqx = m_floats[0] * m_floats[0];
- sqy = m_floats[1] * m_floats[1];
- sqz = m_floats[2] * m_floats[2];
- squ = m_floats[3] * m_floats[3];
- sarg = btScalar(-2.) * (m_floats[0] * m_floats[2] - m_floats[3] * m_floats[1]);
-
- // If the pitch angle is PI/2 or -PI/2, we can only compute
- // the sum roll + yaw. However, any combination that gives
- // the right sum will produce the correct orientation, so we
- // set rollX = 0 and compute yawZ.
- if (sarg <= -btScalar(0.99999))
- {
- pitchY = btScalar(-0.5) * SIMD_PI;
- rollX = 0;
- yawZ = btScalar(2) * btAtan2(m_floats[0], -m_floats[1]);
- }
- else if (sarg >= btScalar(0.99999))
- {
- pitchY = btScalar(0.5) * SIMD_PI;
- rollX = 0;
- yawZ = btScalar(2) * btAtan2(-m_floats[0], m_floats[1]);
- }
- else
- {
- pitchY = btAsin(sarg);
- rollX = btAtan2(2 * (m_floats[1] * m_floats[2] + m_floats[3] * m_floats[0]), squ - sqx - sqy + sqz);
- yawZ = btAtan2(2 * (m_floats[0] * m_floats[1] + m_floats[3] * m_floats[2]), squ + sqx - sqy - sqz);
- }
- }
-
- /**@brief Add two quaternions
- * @param q The quaternion to add to this one */
- SIMD_FORCE_INLINE btQuaternion& operator+=(const btQuaternion& q)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_add_ps(mVec128, q.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vaddq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] += q.x();
- m_floats[1] += q.y();
- m_floats[2] += q.z();
- m_floats[3] += q.m_floats[3];
-#endif
- return *this;
- }
-
- /**@brief Subtract out a quaternion
- * @param q The quaternion to subtract from this one */
- btQuaternion& operator-=(const btQuaternion& q)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_sub_ps(mVec128, q.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vsubq_f32(mVec128, q.mVec128);
-#else
- m_floats[0] -= q.x();
- m_floats[1] -= q.y();
- m_floats[2] -= q.z();
- m_floats[3] -= q.m_floats[3];
-#endif
- return *this;
- }
-
- /**@brief Scale this quaternion
- * @param s The scalar to scale by */
- btQuaternion& operator*=(const btScalar& s)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0); // (S S S S)
- mVec128 = _mm_mul_ps(mVec128, vs);
-#elif defined(BT_USE_NEON)
- mVec128 = vmulq_n_f32(mVec128, s);
-#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
- m_floats[3] *= s;
-#endif
- return *this;
- }
-
- /**@brief Multiply this quaternion by q on the right
- * @param q The other quaternion
- * Equivilant to this = this * q */
- btQuaternion& operator*=(const btQuaternion& q)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vQ2 = q.get128();
-
- __m128 A1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(0, 1, 2, 0));
- __m128 B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0));
-
- A1 = A1 * B1;
-
- __m128 A2 = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 1));
- __m128 B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- B1 = bt_pshufd_ps(mVec128, BT_SHUFFLE(2, 0, 1, 2));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
-
- B1 = B1 * B2; // A3 *= B3
-
- mVec128 = bt_splat_ps(mVec128, 3); // A0
- mVec128 = mVec128 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- mVec128 = mVec128 - B1; // AB03 = AB0 - AB3
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- mVec128 = mVec128 + A1; // AB03 + AB12
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t vQ1 = mVec128;
- float32x4_t vQ2 = q.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- mVec128 = A0;
-#else
- setValue(
- m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
- m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
- m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
- m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
-#endif
- return *this;
- }
- /**@brief Return the dot product between this quaternion and another
- * @param q The other quaternion */
- btScalar dot(const btQuaternion& q) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vd;
-
- vd = _mm_mul_ps(mVec128, q.mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
- vd = _mm_add_ps(vd, t);
- t = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, t);
-
- return _mm_cvtss_f32(vd);
-#elif defined(BT_USE_NEON)
- float32x4_t vd = vmulq_f32(mVec128, q.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_high_f32(vd));
- x = vpadd_f32(x, x);
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * q.x() +
- m_floats[1] * q.y() +
- m_floats[2] * q.z() +
- m_floats[3] * q.m_floats[3];
-#endif
- }
-
- /**@brief Return the length squared of the quaternion */
- btScalar length2() const
- {
- return dot(*this);
- }
-
- /**@brief Return the length of the quaternion */
- btScalar length() const
- {
- return btSqrt(length2());
- }
- btQuaternion& safeNormalize()
- {
- btScalar l2 = length2();
- if (l2 > SIMD_EPSILON)
- {
- normalize();
- }
- return *this;
- }
- /**@brief Normalize the quaternion
- * Such that x^2 + y^2 + z^2 +w^2 = 1 */
- btQuaternion& normalize()
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vd;
-
- vd = _mm_mul_ps(mVec128, mVec128);
-
- __m128 t = _mm_movehl_ps(vd, vd);
- vd = _mm_add_ps(vd, t);
- t = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, t);
-
- vd = _mm_sqrt_ss(vd);
- vd = _mm_div_ss(vOnes, vd);
- vd = bt_pshufd_ps(vd, 0); // splat
- mVec128 = _mm_mul_ps(mVec128, vd);
-
- return *this;
-#else
- return *this /= length();
-#endif
- }
-
- /**@brief Return a scaled version of this quaternion
- * @param s The scale factor */
- SIMD_FORCE_INLINE btQuaternion
- operator*(const btScalar& s) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
-
- return btQuaternion(_mm_mul_ps(mVec128, vs));
-#elif defined(BT_USE_NEON)
- return btQuaternion(vmulq_n_f32(mVec128, s));
-#else
- return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
-#endif
- }
-
- /**@brief Return an inversely scaled versionof this quaternion
- * @param s The inverse scale factor */
- btQuaternion operator/(const btScalar& s) const
- {
- btAssert(s != btScalar(0.0));
- return *this * (btScalar(1.0) / s);
- }
-
- /**@brief Inversely scale this quaternion
- * @param s The scale factor */
- btQuaternion& operator/=(const btScalar& s)
- {
- btAssert(s != btScalar(0.0));
- return *this *= btScalar(1.0) / s;
- }
-
- /**@brief Return a normalized version of this quaternion */
- btQuaternion normalized() const
- {
- return *this / length();
- }
- /**@brief Return the ***half*** angle between this quaternion and the other
- * @param q The other quaternion */
- btScalar angle(const btQuaternion& q) const
- {
- btScalar s = btSqrt(length2() * q.length2());
- btAssert(s != btScalar(0.0));
- return btAcos(dot(q) / s);
- }
-
- /**@brief Return the angle between this quaternion and the other along the shortest path
- * @param q The other quaternion */
- btScalar angleShortestPath(const btQuaternion& q) const
- {
- btScalar s = btSqrt(length2() * q.length2());
- btAssert(s != btScalar(0.0));
- if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
- return btAcos(dot(-q) / s) * btScalar(2.0);
- else
- return btAcos(dot(q) / s) * btScalar(2.0);
- }
-
- /**@brief Return the angle [0, 2Pi] of rotation represented by this quaternion */
- btScalar getAngle() const
- {
- btScalar s = btScalar(2.) * btAcos(m_floats[3]);
- return s;
- }
-
- /**@brief Return the angle [0, Pi] of rotation represented by this quaternion along the shortest path */
- btScalar getAngleShortestPath() const
- {
- btScalar s;
- if (m_floats[3] >= 0)
- s = btScalar(2.) * btAcos(m_floats[3]);
- else
- s = btScalar(2.) * btAcos(-m_floats[3]);
- return s;
- }
-
- /**@brief Return the axis of the rotation represented by this quaternion */
- btVector3 getAxis() const
- {
- btScalar s_squared = 1.f - m_floats[3] * m_floats[3];
-
- if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
- return btVector3(1.0, 0.0, 0.0); // Arbitrary
- btScalar s = 1.f / btSqrt(s_squared);
- return btVector3(m_floats[0] * s, m_floats[1] * s, m_floats[2] * s);
- }
-
- /**@brief Return the inverse of this quaternion */
- btQuaternion inverse() const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btQuaternion(_mm_xor_ps(mVec128, vQInv));
-#elif defined(BT_USE_NEON)
- return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)vQInv));
-#else
- return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
-#endif
- }
-
- /**@brief Return the sum of this quaternion and the other
- * @param q2 The other quaternion */
- SIMD_FORCE_INLINE btQuaternion
- operator+(const btQuaternion& q2) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btQuaternion(_mm_add_ps(mVec128, q2.mVec128));
-#elif defined(BT_USE_NEON)
- return btQuaternion(vaddq_f32(mVec128, q2.mVec128));
-#else
- const btQuaternion& q1 = *this;
- return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
-#endif
- }
-
- /**@brief Return the difference between this quaternion and the other
- * @param q2 The other quaternion */
- SIMD_FORCE_INLINE btQuaternion
- operator-(const btQuaternion& q2) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btQuaternion(_mm_sub_ps(mVec128, q2.mVec128));
-#elif defined(BT_USE_NEON)
- return btQuaternion(vsubq_f32(mVec128, q2.mVec128));
-#else
- const btQuaternion& q1 = *this;
- return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
-#endif
- }
-
- /**@brief Return the negative of this quaternion
- * This simply negates each element */
- SIMD_FORCE_INLINE btQuaternion operator-() const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btQuaternion(_mm_xor_ps(mVec128, btvMzeroMask));
-#elif defined(BT_USE_NEON)
- return btQuaternion((btSimdFloat4)veorq_s32((int32x4_t)mVec128, (int32x4_t)btvMzeroMask));
-#else
- const btQuaternion& q2 = *this;
- return btQuaternion(-q2.x(), -q2.y(), -q2.z(), -q2.m_floats[3]);
-#endif
- }
- /**@todo document this and it's use */
- SIMD_FORCE_INLINE btQuaternion farthest(const btQuaternion& qd) const
- {
- btQuaternion diff, sum;
- diff = *this - qd;
- sum = *this + qd;
- if (diff.dot(diff) > sum.dot(sum))
- return qd;
- return (-qd);
- }
-
- /**@todo document this and it's use */
- SIMD_FORCE_INLINE btQuaternion nearest(const btQuaternion& qd) const
- {
- btQuaternion diff, sum;
- diff = *this - qd;
- sum = *this + qd;
- if (diff.dot(diff) < sum.dot(sum))
- return qd;
- return (-qd);
- }
-
- /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
- * @param q The other quaternion to interpolate with
- * @param t The ratio between this and q to interpolate. If t = 0 the result is this, if t=1 the result is q.
- * Slerp interpolates assuming constant velocity. */
- btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
- {
- const btScalar magnitude = btSqrt(length2() * q.length2());
- btAssert(magnitude > btScalar(0));
-
- const btScalar product = dot(q) / magnitude;
- const btScalar absproduct = btFabs(product);
-
- if (absproduct < btScalar(1.0 - SIMD_EPSILON))
- {
- // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
- const btScalar theta = btAcos(absproduct);
- const btScalar d = btSin(theta);
- btAssert(d > btScalar(0));
-
- const btScalar sign = (product < 0) ? btScalar(-1) : btScalar(1);
- const btScalar s0 = btSin((btScalar(1.0) - t) * theta) / d;
- const btScalar s1 = btSin(sign * t * theta) / d;
-
- return btQuaternion(
- (m_floats[0] * s0 + q.x() * s1),
- (m_floats[1] * s0 + q.y() * s1),
- (m_floats[2] * s0 + q.z() * s1),
- (m_floats[3] * s0 + q.w() * s1));
- }
- else
- {
- return *this;
- }
- }
-
- static const btQuaternion& getIdentity()
- {
- static const btQuaternion identityQuat(btScalar(0.), btScalar(0.), btScalar(0.), btScalar(1.));
- return identityQuat;
- }
-
- SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
-
- SIMD_FORCE_INLINE void serialize(struct btQuaternionData& dataOut) const;
-
- SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionFloatData& dataIn);
-
- SIMD_FORCE_INLINE void deSerialize(const struct btQuaternionDoubleData& dataIn);
-
- SIMD_FORCE_INLINE void serializeFloat(struct btQuaternionFloatData& dataOut) const;
-
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btQuaternionFloatData& dataIn);
-
- SIMD_FORCE_INLINE void serializeDouble(struct btQuaternionDoubleData& dataOut) const;
-
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btQuaternionDoubleData& dataIn);
-};
-
-/**@brief Return the product of two quaternions */
-SIMD_FORCE_INLINE btQuaternion
-operator*(const btQuaternion& q1, const btQuaternion& q2)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vQ1 = q1.get128();
- __m128 vQ2 = q2.get128();
- __m128 A0, A1, B1, A2, B2;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0)); // X Y z x // vtrn
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0)); // W W W X // vdup vext
-
- A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1)); // Y Z X Y // vext
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1)); // z x Y Y // vtrn vdup
-
- A2 = A2 * B2;
-
- B1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2)); // z x Y Z // vtrn vext
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2)); // Y Z x z // vext vtrn
-
- B1 = B1 * B2; // A3 *= B3
-
- A0 = bt_splat_ps(vQ1, 3); // A0
- A0 = A0 * vQ2; // A0 * B0
-
- A1 = A1 + A2; // AB12
- A0 = A0 - B1; // AB03 = AB0 - AB3
-
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A0 = A0 + A1; // AB03 + AB12
-
- return btQuaternion(A0);
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t vQ1 = q1.get128();
- float32x4_t vQ2 = q2.get128();
- float32x4_t A0, A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
- A0 = vmulq_lane_f32(vQ2, vget_high_f32(vQ1), 1); // A0 * B0
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
- A0 = vsubq_f32(A0, A3); // AB03 = AB0 - AB3
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
- A0 = vaddq_f32(A0, A1); // AB03 + AB12
-
- return btQuaternion(A0);
-
-#else
- return btQuaternion(
- q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
- q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
- q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
- q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z());
-#endif
-}
-
-SIMD_FORCE_INLINE btQuaternion
-operator*(const btQuaternion& q, const btVector3& w)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vQ1 = q.get128();
- __m128 vQ2 = w.get128();
- __m128 A1, B1, A2, B2, A3, B3;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(3, 3, 3, 0));
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(0, 1, 2, 0));
-
- A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
- B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
-
- A3 = A3 * B3; // A3 *= B3
-
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
- return btQuaternion(A1);
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t vQ1 = q.get128();
- float32x4_t vQ2 = w.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1wx, vQ2zx, vQ1yz, vQ2yz, vQ1zx, vQ2xz;
-
- vQ1wx = vext_f32(vget_high_f32(vQ1), vget_low_f32(vQ1), 1);
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
- }
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ1), 1), vQ1wx); // W W W X
- B1 = vcombine_f32(vget_low_f32(vQ2), vQ2zx); // X Y z x
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
- return btQuaternion(A1);
-
-#else
- return btQuaternion(
- q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
- q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
- q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
- -q.x() * w.x() - q.y() * w.y() - q.z() * w.z());
-#endif
-}
-
-SIMD_FORCE_INLINE btQuaternion
-operator*(const btVector3& w, const btQuaternion& q)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vQ1 = w.get128();
- __m128 vQ2 = q.get128();
- __m128 A1, B1, A2, B2, A3, B3;
-
- A1 = bt_pshufd_ps(vQ1, BT_SHUFFLE(0, 1, 2, 0)); // X Y z x
- B1 = bt_pshufd_ps(vQ2, BT_SHUFFLE(3, 3, 3, 0)); // W W W X
-
- A1 = A1 * B1;
-
- A2 = bt_pshufd_ps(vQ1, BT_SHUFFLE(1, 2, 0, 1));
- B2 = bt_pshufd_ps(vQ2, BT_SHUFFLE(2, 0, 1, 1));
-
- A2 = A2 * B2;
-
- A3 = bt_pshufd_ps(vQ1, BT_SHUFFLE(2, 0, 1, 2));
- B3 = bt_pshufd_ps(vQ2, BT_SHUFFLE(1, 2, 0, 2));
-
- A3 = A3 * B3; // A3 *= B3
-
- A1 = A1 + A2; // AB12
- A1 = _mm_xor_ps(A1, vPPPM); // change sign of the last element
- A1 = A1 - A3; // AB123 = AB12 - AB3
-
- return btQuaternion(A1);
-
-#elif defined(BT_USE_NEON)
-
- float32x4_t vQ1 = w.get128();
- float32x4_t vQ2 = q.get128();
- float32x4_t A1, B1, A2, B2, A3, B3;
- float32x2_t vQ1zx, vQ2wx, vQ1yz, vQ2zx, vQ2yz, vQ2xz;
-
- {
- float32x2x2_t tmp;
-
- tmp = vtrn_f32(vget_high_f32(vQ1), vget_low_f32(vQ1)); // {z x}, {w y}
- vQ1zx = tmp.val[0];
-
- tmp = vtrn_f32(vget_high_f32(vQ2), vget_low_f32(vQ2)); // {z x}, {w y}
- vQ2zx = tmp.val[0];
- }
- vQ2wx = vext_f32(vget_high_f32(vQ2), vget_low_f32(vQ2), 1);
-
- vQ1yz = vext_f32(vget_low_f32(vQ1), vget_high_f32(vQ1), 1);
-
- vQ2yz = vext_f32(vget_low_f32(vQ2), vget_high_f32(vQ2), 1);
- vQ2xz = vext_f32(vQ2zx, vQ2zx, 1);
-
- A1 = vcombine_f32(vget_low_f32(vQ1), vQ1zx); // X Y z x
- B1 = vcombine_f32(vdup_lane_f32(vget_high_f32(vQ2), 1), vQ2wx); // W W W X
-
- A2 = vcombine_f32(vQ1yz, vget_low_f32(vQ1));
- B2 = vcombine_f32(vQ2zx, vdup_lane_f32(vget_low_f32(vQ2), 1));
-
- A3 = vcombine_f32(vQ1zx, vQ1yz); // Z X Y Z
- B3 = vcombine_f32(vQ2yz, vQ2xz); // Y Z x z
-
- A1 = vmulq_f32(A1, B1);
- A2 = vmulq_f32(A2, B2);
- A3 = vmulq_f32(A3, B3); // A3 *= B3
-
- A1 = vaddq_f32(A1, A2); // AB12 = AB1 + AB2
-
- // change the sign of the last element
- A1 = (btSimdFloat4)veorq_s32((int32x4_t)A1, (int32x4_t)vPPPM);
-
- A1 = vsubq_f32(A1, A3); // AB123 = AB12 - AB3
-
- return btQuaternion(A1);
-
-#else
- return btQuaternion(
- +w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
- +w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
- +w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
- -w.x() * q.x() - w.y() * q.y() - w.z() * q.z());
-#endif
-}
-
-/**@brief Calculate the dot product between two quaternions */
-SIMD_FORCE_INLINE btScalar
-dot(const btQuaternion& q1, const btQuaternion& q2)
-{
- return q1.dot(q2);
-}
-
-/**@brief Return the length of a quaternion */
-SIMD_FORCE_INLINE btScalar
-length(const btQuaternion& q)
-{
- return q.length();
-}
-
-/**@brief Return the angle between two quaternions*/
-SIMD_FORCE_INLINE btScalar
-btAngle(const btQuaternion& q1, const btQuaternion& q2)
-{
- return q1.angle(q2);
-}
-
-/**@brief Return the inverse of a quaternion*/
-SIMD_FORCE_INLINE btQuaternion
-inverse(const btQuaternion& q)
-{
- return q.inverse();
-}
-
-/**@brief Return the result of spherical linear interpolation betwen two quaternions
- * @param q1 The first quaternion
- * @param q2 The second quaternion
- * @param t The ration between q1 and q2. t = 0 return q1, t=1 returns q2
- * Slerp assumes constant velocity between positions. */
-SIMD_FORCE_INLINE btQuaternion
-slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t)
-{
- return q1.slerp(q2, t);
-}
-
-SIMD_FORCE_INLINE btVector3
-quatRotate(const btQuaternion& rotation, const btVector3& v)
-{
- btQuaternion q = rotation * v;
- q *= rotation.inverse();
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_and_ps(q.get128(), btvFFF0fMask));
-#elif defined(BT_USE_NEON)
- return btVector3((float32x4_t)vandq_s32((int32x4_t)q.get128(), btvFFF0Mask));
-#else
- return btVector3(q.getX(), q.getY(), q.getZ());
-#endif
-}
-
-SIMD_FORCE_INLINE btQuaternion
-shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
-{
- btVector3 c = v0.cross(v1);
- btScalar d = v0.dot(v1);
-
- if (d < -1.0 + SIMD_EPSILON)
- {
- btVector3 n, unused;
- btPlaneSpace1(v0, n, unused);
- return btQuaternion(n.x(), n.y(), n.z(), 0.0f); // just pick any vector that is orthogonal to v0
- }
-
- btScalar s = btSqrt((1.0f + d) * 2.0f);
- btScalar rs = 1.0f / s;
-
- return btQuaternion(c.getX() * rs, c.getY() * rs, c.getZ() * rs, s * 0.5f);
-}
-
-SIMD_FORCE_INLINE btQuaternion
-shortestArcQuatNormalize2(btVector3& v0, btVector3& v1)
-{
- v0.normalize();
- v1.normalize();
- return shortestArcQuat(v0, v1);
-}
-
-struct btQuaternionFloatData
-{
- float m_floats[4];
-};
-
-struct btQuaternionDoubleData
-{
- double m_floats[4];
-};
-
-SIMD_FORCE_INLINE void btQuaternion::serializeFloat(struct btQuaternionFloatData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = float(m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btQuaternion::deSerializeFloat(const struct btQuaternionFloatData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btQuaternion::serializeDouble(struct btQuaternionDoubleData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = double(m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btQuaternion::deSerializeDouble(const struct btQuaternionDoubleData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btQuaternion::serialize(struct btQuaternionData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = m_floats[i];
-}
-
-SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionFloatData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
-}
-
-SIMD_FORCE_INLINE void btQuaternion::deSerialize(const struct btQuaternionDoubleData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
-}
-
-#endif //BT_SIMD__QUATERNION_H_
diff --git a/thirdparty/bullet/LinearMath/btQuickprof.cpp b/thirdparty/bullet/LinearMath/btQuickprof.cpp
deleted file mode 100644
index 33b51eb763..0000000000
--- a/thirdparty/bullet/LinearMath/btQuickprof.cpp
+++ /dev/null
@@ -1,805 +0,0 @@
-/*
-
-***************************************************************************************************
-**
-** profile.cpp
-**
-** Real-Time Hierarchical Profiling for Game Programming Gems 3
-**
-** by Greg Hjelstrom & Byon Garrabrant
-**
-***************************************************************************************************/
-
-// Credits: The Clock class was inspired by the Timer classes in
-// Ogre (www.ogre3d.org).
-
-#include "btQuickprof.h"
-#include "btThreads.h"
-
-#ifdef __CELLOS_LV2__
-#include <sys/sys_time.h>
-#include <sys/time_util.h>
-#include <stdio.h>
-#endif
-
-#if defined(SUNOS) || defined(__SUNOS__)
-#include <stdio.h>
-#endif
-#ifdef __APPLE__
-#include <mach/mach_time.h>
-#include <TargetConditionals.h>
-#endif
-
-#if defined(WIN32) || defined(_WIN32)
-
-#define BT_USE_WINDOWS_TIMERS
-#define WIN32_LEAN_AND_MEAN
-#define NOWINRES
-#define NOMCX
-#define NOIME
-
-#ifdef _XBOX
-#include <Xtl.h>
-#else //_XBOX
-#include <windows.h>
-
-#if WINVER < 0x0602
-#define GetTickCount64 GetTickCount
-#endif
-
-#endif //_XBOX
-
-#include <time.h>
-
-#else //_WIN32
-#include <sys/time.h>
-
-#ifdef BT_LINUX_REALTIME
-//required linking against rt (librt)
-#include <time.h>
-#endif //BT_LINUX_REALTIME
-
-#endif //_WIN32
-
-#define mymin(a, b) (a > b ? a : b)
-
-struct btClockData
-{
-#ifdef BT_USE_WINDOWS_TIMERS
- LARGE_INTEGER mClockFrequency;
- LONGLONG mStartTick;
- LARGE_INTEGER mStartTime;
-#else
-#ifdef __CELLOS_LV2__
- uint64_t mStartTime;
-#else
-#ifdef __APPLE__
- uint64_t mStartTimeNano;
-#endif
- struct timeval mStartTime;
-#endif
-#endif //__CELLOS_LV2__
-};
-
-///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
-btClock::btClock()
-{
- m_data = new btClockData;
-#ifdef BT_USE_WINDOWS_TIMERS
- QueryPerformanceFrequency(&m_data->mClockFrequency);
-#endif
- reset();
-}
-
-btClock::~btClock()
-{
- delete m_data;
-}
-
-btClock::btClock(const btClock& other)
-{
- m_data = new btClockData;
- *m_data = *other.m_data;
-}
-
-btClock& btClock::operator=(const btClock& other)
-{
- *m_data = *other.m_data;
- return *this;
-}
-
-/// Resets the initial reference time.
-void btClock::reset()
-{
-#ifdef BT_USE_WINDOWS_TIMERS
- QueryPerformanceCounter(&m_data->mStartTime);
- m_data->mStartTick = GetTickCount64();
-#else
-#ifdef __CELLOS_LV2__
-
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET(newTime);
- m_data->mStartTime = newTime;
-#else
-#ifdef __APPLE__
- m_data->mStartTimeNano = mach_absolute_time();
-#endif
- gettimeofday(&m_data->mStartTime, 0);
-#endif
-#endif
-}
-
-/// Returns the time in ms since the last call to reset or since
-/// the btClock was created.
-unsigned long long int btClock::getTimeMilliseconds()
-{
-#ifdef BT_USE_WINDOWS_TIMERS
- LARGE_INTEGER currentTime;
- QueryPerformanceCounter(&currentTime);
- LONGLONG elapsedTime = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- // Compute the number of millisecond ticks elapsed.
- unsigned long msecTicks = (unsigned long)(1000 * elapsedTime /
- m_data->mClockFrequency.QuadPart);
-
- return msecTicks;
-#else
-
-#ifdef __CELLOS_LV2__
- uint64_t freq = sys_time_get_timebase_frequency();
- double dFreq = ((double)freq) / 1000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- SYS_TIMEBASE_GET(newTime);
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
-
- return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
-#else
-
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
-#endif //__CELLOS_LV2__
-#endif
-}
-
-/// Returns the time in us since the last call to reset or since
-/// the Clock was created.
-unsigned long long int btClock::getTimeMicroseconds()
-{
-#ifdef BT_USE_WINDOWS_TIMERS
- //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
- LARGE_INTEGER currentTime, elapsedTime;
-
- QueryPerformanceCounter(&currentTime);
- elapsedTime.QuadPart = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- elapsedTime.QuadPart *= 1000000;
- elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
-
- return (unsigned long long)elapsedTime.QuadPart;
-#else
-
-#ifdef __CELLOS_LV2__
- uint64_t freq = sys_time_get_timebase_frequency();
- double dFreq = ((double)freq) / 1000000.0;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET(newTime);
-
- return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
-#else
-
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec);
-#endif //__CELLOS_LV2__
-#endif
-}
-
-unsigned long long int btClock::getTimeNanoseconds()
-{
-#ifdef BT_USE_WINDOWS_TIMERS
- //see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx
- LARGE_INTEGER currentTime, elapsedTime;
-
- QueryPerformanceCounter(&currentTime);
- elapsedTime.QuadPart = currentTime.QuadPart -
- m_data->mStartTime.QuadPart;
- elapsedTime.QuadPart *= 1000000000;
- elapsedTime.QuadPart /= m_data->mClockFrequency.QuadPart;
-
- return (unsigned long long)elapsedTime.QuadPart;
-#else
-
-#ifdef __CELLOS_LV2__
- uint64_t freq = sys_time_get_timebase_frequency();
- double dFreq = ((double)freq) / 1e9;
- typedef uint64_t ClockSize;
- ClockSize newTime;
- //__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
- SYS_TIMEBASE_GET(newTime);
-
- return (unsigned long int)((double(newTime - m_data->mStartTime)) / dFreq);
-#else
-#ifdef __APPLE__
- uint64_t ticks = mach_absolute_time() - m_data->mStartTimeNano;
- static long double conversion = 0.0L;
- if (0.0L == conversion)
- {
- // attempt to get conversion to nanoseconds
- mach_timebase_info_data_t info;
- int err = mach_timebase_info(&info);
- if (err)
- {
- btAssert(0);
- conversion = 1.;
- }
- conversion = info.numer / info.denom;
- }
- return (ticks * conversion);
-
-#else //__APPLE__
-
-#ifdef BT_LINUX_REALTIME
- timespec ts;
- clock_gettime(CLOCK_REALTIME, &ts);
- return 1000000000 * ts.tv_sec + ts.tv_nsec;
-#else
- struct timeval currentTime;
- gettimeofday(&currentTime, 0);
- return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1e9 +
- (currentTime.tv_usec - m_data->mStartTime.tv_usec) * 1000;
-#endif //BT_LINUX_REALTIME
-
-#endif //__APPLE__
-#endif //__CELLOS_LV2__
-#endif
-}
-
-/// Returns the time in s since the last call to reset or since
-/// the Clock was created.
-btScalar btClock::getTimeSeconds()
-{
- static const btScalar microseconds_to_seconds = btScalar(0.000001);
- return btScalar(getTimeMicroseconds()) * microseconds_to_seconds;
-}
-
-#ifndef BT_NO_PROFILE
-
-static btClock gProfileClock;
-
-inline void Profile_Get_Ticks(unsigned long int* ticks)
-{
- *ticks = (unsigned long int)gProfileClock.getTimeMicroseconds();
-}
-
-inline float Profile_Get_Tick_Rate(void)
-{
- // return 1000000.f;
- return 1000.f;
-}
-
-/***************************************************************************************************
-**
-** CProfileNode
-**
-***************************************************************************************************/
-
-/***********************************************************************************************
- * INPUT: *
- * name - pointer to a static string which is the name of this profile node *
- * parent - parent pointer *
- * *
- * WARNINGS: *
- * The name is assumed to be a static pointer, only the pointer is stored and compared for *
- * efficiency reasons. *
- *=============================================================================================*/
-CProfileNode::CProfileNode(const char* name, CProfileNode* parent) : Name(name),
- TotalCalls(0),
- TotalTime(0),
- StartTime(0),
- RecursionCounter(0),
- Parent(parent),
- Child(NULL),
- Sibling(NULL),
- m_userPtr(0)
-{
- Reset();
-}
-
-void CProfileNode::CleanupMemory()
-{
- delete (Child);
- Child = NULL;
- delete (Sibling);
- Sibling = NULL;
-}
-
-CProfileNode::~CProfileNode(void)
-{
- CleanupMemory();
-}
-
-/***********************************************************************************************
- * INPUT: *
- * name - static string pointer to the name of the node we are searching for *
- * *
- * WARNINGS: *
- * All profile names are assumed to be static strings so this function uses pointer compares *
- * to find the named node. *
- *=============================================================================================*/
-CProfileNode* CProfileNode::Get_Sub_Node(const char* name)
-{
- // Try to find this sub node
- CProfileNode* child = Child;
- while (child)
- {
- if (child->Name == name)
- {
- return child;
- }
- child = child->Sibling;
- }
-
- // We didn't find it, so add it
-
- CProfileNode* node = new CProfileNode(name, this);
- node->Sibling = Child;
- Child = node;
- return node;
-}
-
-void CProfileNode::Reset(void)
-{
- TotalCalls = 0;
- TotalTime = 0.0f;
-
- if (Child)
- {
- Child->Reset();
- }
- if (Sibling)
- {
- Sibling->Reset();
- }
-}
-
-void CProfileNode::Call(void)
-{
- TotalCalls++;
- if (RecursionCounter++ == 0)
- {
- Profile_Get_Ticks(&StartTime);
- }
-}
-
-bool CProfileNode::Return(void)
-{
- if (--RecursionCounter == 0 && TotalCalls != 0)
- {
- unsigned long int time;
- Profile_Get_Ticks(&time);
-
- time -= StartTime;
- TotalTime += (float)time / Profile_Get_Tick_Rate();
- }
- return (RecursionCounter == 0);
-}
-
-/***************************************************************************************************
-**
-** CProfileIterator
-**
-***************************************************************************************************/
-CProfileIterator::CProfileIterator(CProfileNode* start)
-{
- CurrentParent = start;
- CurrentChild = CurrentParent->Get_Child();
-}
-
-void CProfileIterator::First(void)
-{
- CurrentChild = CurrentParent->Get_Child();
-}
-
-void CProfileIterator::Next(void)
-{
- CurrentChild = CurrentChild->Get_Sibling();
-}
-
-bool CProfileIterator::Is_Done(void)
-{
- return CurrentChild == NULL;
-}
-
-void CProfileIterator::Enter_Child(int index)
-{
- CurrentChild = CurrentParent->Get_Child();
- while ((CurrentChild != NULL) && (index != 0))
- {
- index--;
- CurrentChild = CurrentChild->Get_Sibling();
- }
-
- if (CurrentChild != NULL)
- {
- CurrentParent = CurrentChild;
- CurrentChild = CurrentParent->Get_Child();
- }
-}
-
-void CProfileIterator::Enter_Parent(void)
-{
- if (CurrentParent->Get_Parent() != NULL)
- {
- CurrentParent = CurrentParent->Get_Parent();
- }
- CurrentChild = CurrentParent->Get_Child();
-}
-
-/***************************************************************************************************
-**
-** CProfileManager
-**
-***************************************************************************************************/
-
-CProfileNode gRoots[BT_QUICKPROF_MAX_THREAD_COUNT] = {
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL),
- CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL), CProfileNode("Root", NULL)};
-
-CProfileNode* gCurrentNodes[BT_QUICKPROF_MAX_THREAD_COUNT] =
- {
- &gRoots[0],
- &gRoots[1],
- &gRoots[2],
- &gRoots[3],
- &gRoots[4],
- &gRoots[5],
- &gRoots[6],
- &gRoots[7],
- &gRoots[8],
- &gRoots[9],
- &gRoots[10],
- &gRoots[11],
- &gRoots[12],
- &gRoots[13],
- &gRoots[14],
- &gRoots[15],
- &gRoots[16],
- &gRoots[17],
- &gRoots[18],
- &gRoots[19],
- &gRoots[20],
- &gRoots[21],
- &gRoots[22],
- &gRoots[23],
- &gRoots[24],
- &gRoots[25],
- &gRoots[26],
- &gRoots[27],
- &gRoots[28],
- &gRoots[29],
- &gRoots[30],
- &gRoots[31],
- &gRoots[32],
- &gRoots[33],
- &gRoots[34],
- &gRoots[35],
- &gRoots[36],
- &gRoots[37],
- &gRoots[38],
- &gRoots[39],
- &gRoots[40],
- &gRoots[41],
- &gRoots[42],
- &gRoots[43],
- &gRoots[44],
- &gRoots[45],
- &gRoots[46],
- &gRoots[47],
- &gRoots[48],
- &gRoots[49],
- &gRoots[50],
- &gRoots[51],
- &gRoots[52],
- &gRoots[53],
- &gRoots[54],
- &gRoots[55],
- &gRoots[56],
- &gRoots[57],
- &gRoots[58],
- &gRoots[59],
- &gRoots[60],
- &gRoots[61],
- &gRoots[62],
- &gRoots[63],
-};
-
-int CProfileManager::FrameCounter = 0;
-unsigned long int CProfileManager::ResetTime = 0;
-
-CProfileIterator* CProfileManager::Get_Iterator(void)
-{
- int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
- return 0;
-
- return new CProfileIterator(&gRoots[threadIndex]);
-}
-
-void CProfileManager::CleanupMemory(void)
-{
- for (int i = 0; i < BT_QUICKPROF_MAX_THREAD_COUNT; i++)
- {
- gRoots[i].CleanupMemory();
- }
-}
-
-/***********************************************************************************************
- * CProfileManager::Start_Profile -- Begin a named profile *
- * *
- * Steps one level deeper into the tree, if a child already exists with the specified name *
- * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
- * *
- * INPUT: *
- * name - name of this profiling record *
- * *
- * WARNINGS: *
- * The string used is assumed to be a static string; pointer compares are used throughout *
- * the profiling code for efficiency. *
- *=============================================================================================*/
-void CProfileManager::Start_Profile(const char* name)
-{
- int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
- return;
-
- if (name != gCurrentNodes[threadIndex]->Get_Name())
- {
- gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Sub_Node(name);
- }
-
- gCurrentNodes[threadIndex]->Call();
-}
-
-/***********************************************************************************************
- * CProfileManager::Stop_Profile -- Stop timing and record the results. *
- *=============================================================================================*/
-void CProfileManager::Stop_Profile(void)
-{
- int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
- return;
-
- // Return will indicate whether we should back up to our parent (we may
- // be profiling a recursive function)
- if (gCurrentNodes[threadIndex]->Return())
- {
- gCurrentNodes[threadIndex] = gCurrentNodes[threadIndex]->Get_Parent();
- }
-}
-
-/***********************************************************************************************
- * CProfileManager::Reset -- Reset the contents of the profiling system *
- * *
- * This resets everything except for the tree structure. All of the timing data is reset. *
- *=============================================================================================*/
-void CProfileManager::Reset(void)
-{
- gProfileClock.reset();
- int threadIndex = btQuickprofGetCurrentThreadIndex2();
- if ((threadIndex < 0) || threadIndex >= BT_QUICKPROF_MAX_THREAD_COUNT)
- return;
- gRoots[threadIndex].Reset();
- gRoots[threadIndex].Call();
- FrameCounter = 0;
- Profile_Get_Ticks(&ResetTime);
-}
-
-/***********************************************************************************************
- * CProfileManager::Increment_Frame_Counter -- Increment the frame counter *
- *=============================================================================================*/
-void CProfileManager::Increment_Frame_Counter(void)
-{
- FrameCounter++;
-}
-
-/***********************************************************************************************
- * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset *
- *=============================================================================================*/
-float CProfileManager::Get_Time_Since_Reset(void)
-{
- unsigned long int time;
- Profile_Get_Ticks(&time);
- time -= ResetTime;
- return (float)time / Profile_Get_Tick_Rate();
-}
-
-#include <stdio.h>
-
-void CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
-{
- profileIterator->First();
- if (profileIterator->Is_Done())
- return;
-
- float accumulated_time = 0, parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
- int i;
- int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
- for (i = 0; i < spacing; i++) printf(".");
- printf("----------------------------------\n");
- for (i = 0; i < spacing; i++) printf(".");
- printf("Profiling: %s (total running time: %.3f ms) ---\n", profileIterator->Get_Current_Parent_Name(), parent_time);
- float totalTime = 0.f;
-
- int numChildren = 0;
-
- for (i = 0; !profileIterator->Is_Done(); i++, profileIterator->Next())
- {
- numChildren++;
- float current_total_time = profileIterator->Get_Current_Total_Time();
- accumulated_time += current_total_time;
- float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
- {
- int i;
- for (i = 0; i < spacing; i++) printf(".");
- }
- printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n", i, profileIterator->Get_Current_Name(), fraction, (current_total_time / (double)frames_since_reset), profileIterator->Get_Current_Total_Calls());
- totalTime += current_total_time;
- //recurse into children
- }
-
- if (parent_time < accumulated_time)
- {
- //printf("what's wrong\n");
- }
- for (i = 0; i < spacing; i++) printf(".");
- printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:", parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
-
- for (i = 0; i < numChildren; i++)
- {
- profileIterator->Enter_Child(i);
- dumpRecursive(profileIterator, spacing + 3);
- profileIterator->Enter_Parent();
- }
-}
-
-void CProfileManager::dumpAll()
-{
- CProfileIterator* profileIterator = 0;
- profileIterator = CProfileManager::Get_Iterator();
-
- dumpRecursive(profileIterator, 0);
-
- CProfileManager::Release_Iterator(profileIterator);
-}
-
-
-void btEnterProfileZoneDefault(const char* name)
-{
-}
-void btLeaveProfileZoneDefault()
-{
-}
-
-#else
-void btEnterProfileZoneDefault(const char* name)
-{
-}
-void btLeaveProfileZoneDefault()
-{
-}
-#endif //BT_NO_PROFILE
-
-
-// clang-format off
-#if defined(_WIN32) && (defined(__MINGW32__) || defined(__MINGW64__))
- #define BT_HAVE_TLS 1
-#elif __APPLE__ && !TARGET_OS_IPHONE
- // TODO: Modern versions of iOS support TLS now with updated version checking.
- #define BT_HAVE_TLS 1
-#elif __linux__
- #define BT_HAVE_TLS 1
-#elif defined(__FreeBSD__) || defined(__NetBSD__)
- // TODO: At the moment disabling purposely OpenBSD, albeit tls support exists but not fully functioning
- #define BT_HAVE_TLS 1
-#endif
-
-// __thread is broken on Andorid clang until r12b. See
-// https://github.com/android-ndk/ndk/issues/8
-#if defined(__ANDROID__) && defined(__clang__)
- #if __has_include(<android/ndk-version.h>)
- #include <android/ndk-version.h>
- #endif // __has_include(<android/ndk-version.h>)
- #if defined(__NDK_MAJOR__) && \
- ((__NDK_MAJOR__ < 12) || ((__NDK_MAJOR__ == 12) && (__NDK_MINOR__ < 1)))
- #undef BT_HAVE_TLS
- #endif
-#endif // defined(__ANDROID__) && defined(__clang__)
-// clang-format on
-
-unsigned int btQuickprofGetCurrentThreadIndex2()
-{
- const unsigned int kNullIndex = ~0U;
-
-#if BT_THREADSAFE
- return btGetCurrentThreadIndex();
-#else
-#if defined(BT_HAVE_TLS)
- static __thread unsigned int sThreadIndex = kNullIndex;
-#elif defined(_WIN32)
- __declspec(thread) static unsigned int sThreadIndex = kNullIndex;
-#else
- unsigned int sThreadIndex = 0;
- return -1;
-#endif
-
- static int gThreadCounter = 0;
-
- if (sThreadIndex == kNullIndex)
- {
- sThreadIndex = gThreadCounter++;
- }
- return sThreadIndex;
-#endif //BT_THREADSAFE
-}
-
-static btEnterProfileZoneFunc* bts_enterFunc = btEnterProfileZoneDefault;
-static btLeaveProfileZoneFunc* bts_leaveFunc = btLeaveProfileZoneDefault;
-
-void btEnterProfileZone(const char* name)
-{
- (bts_enterFunc)(name);
-}
-void btLeaveProfileZone()
-{
- (bts_leaveFunc)();
-}
-
-btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc()
-{
- return bts_enterFunc;
-}
-btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc()
-{
- return bts_leaveFunc;
-}
-
-void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc)
-{
- bts_enterFunc = enterFunc;
-}
-void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc)
-{
- bts_leaveFunc = leaveFunc;
-}
-
-CProfileSample::CProfileSample(const char* name)
-{
- btEnterProfileZone(name);
-}
-
-CProfileSample::~CProfileSample(void)
-{
- btLeaveProfileZone();
-}
diff --git a/thirdparty/bullet/LinearMath/btQuickprof.h b/thirdparty/bullet/LinearMath/btQuickprof.h
deleted file mode 100644
index 990d401d50..0000000000
--- a/thirdparty/bullet/LinearMath/btQuickprof.h
+++ /dev/null
@@ -1,200 +0,0 @@
-
-/***************************************************************************************************
-**
-** Real-Time Hierarchical Profiling for Game Programming Gems 3
-**
-** by Greg Hjelstrom & Byon Garrabrant
-**
-***************************************************************************************************/
-
-// Credits: The Clock class was inspired by the Timer classes in
-// Ogre (www.ogre3d.org).
-
-#ifndef BT_QUICK_PROF_H
-#define BT_QUICK_PROF_H
-
-#include "btScalar.h"
-#define USE_BT_CLOCK 1
-
-#ifdef USE_BT_CLOCK
-
-///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
-class btClock
-{
-public:
- btClock();
-
- btClock(const btClock& other);
- btClock& operator=(const btClock& other);
-
- ~btClock();
-
- /// Resets the initial reference time.
- void reset();
-
- /// Returns the time in ms since the last call to reset or since
- /// the btClock was created.
- unsigned long long int getTimeMilliseconds();
-
- /// Returns the time in us since the last call to reset or since
- /// the Clock was created.
- unsigned long long int getTimeMicroseconds();
-
- unsigned long long int getTimeNanoseconds();
-
- /// Returns the time in s since the last call to reset or since
- /// the Clock was created.
- btScalar getTimeSeconds();
-
-private:
- struct btClockData* m_data;
-};
-
-#endif //USE_BT_CLOCK
-
-typedef void(btEnterProfileZoneFunc)(const char* msg);
-typedef void(btLeaveProfileZoneFunc)();
-
-btEnterProfileZoneFunc* btGetCurrentEnterProfileZoneFunc();
-btLeaveProfileZoneFunc* btGetCurrentLeaveProfileZoneFunc();
-
-void btSetCustomEnterProfileZoneFunc(btEnterProfileZoneFunc* enterFunc);
-void btSetCustomLeaveProfileZoneFunc(btLeaveProfileZoneFunc* leaveFunc);
-
-#ifndef BT_ENABLE_PROFILE
-#define BT_NO_PROFILE 1
-#endif //BT_NO_PROFILE
-
-const unsigned int BT_QUICKPROF_MAX_THREAD_COUNT = 64;
-
-//btQuickprofGetCurrentThreadIndex will return -1 if thread index cannot be determined,
-//otherwise returns thread index in range [0..maxThreads]
-unsigned int btQuickprofGetCurrentThreadIndex2();
-
-#ifndef BT_NO_PROFILE
-
-
-#include <stdio.h> //@todo remove this, backwards compatibility
-
-#include "btAlignedAllocator.h"
-#include <new>
-
-///A node in the Profile Hierarchy Tree
-class CProfileNode
-{
-public:
- CProfileNode(const char* name, CProfileNode* parent);
- ~CProfileNode(void);
-
- CProfileNode* Get_Sub_Node(const char* name);
-
- CProfileNode* Get_Parent(void) { return Parent; }
- CProfileNode* Get_Sibling(void) { return Sibling; }
- CProfileNode* Get_Child(void) { return Child; }
-
- void CleanupMemory();
- void Reset(void);
- void Call(void);
- bool Return(void);
-
- const char* Get_Name(void) { return Name; }
- int Get_Total_Calls(void) { return TotalCalls; }
- float Get_Total_Time(void) { return TotalTime; }
- void* GetUserPointer() const { return m_userPtr; }
- void SetUserPointer(void* ptr) { m_userPtr = ptr; }
-
-protected:
- const char* Name;
- int TotalCalls;
- float TotalTime;
- unsigned long int StartTime;
- int RecursionCounter;
-
- CProfileNode* Parent;
- CProfileNode* Child;
- CProfileNode* Sibling;
- void* m_userPtr;
-};
-
-///An iterator to navigate through the tree
-class CProfileIterator
-{
-public:
- // Access all the children of the current parent
- void First(void);
- void Next(void);
- bool Is_Done(void);
- bool Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
-
- void Enter_Child(int index); // Make the given child the new parent
- void Enter_Largest_Child(void); // Make the largest child the new parent
- void Enter_Parent(void); // Make the current parent's parent the new parent
-
- // Access the current child
- const char* Get_Current_Name(void) { return CurrentChild->Get_Name(); }
- int Get_Current_Total_Calls(void) { return CurrentChild->Get_Total_Calls(); }
- float Get_Current_Total_Time(void) { return CurrentChild->Get_Total_Time(); }
-
- void* Get_Current_UserPointer(void) { return CurrentChild->GetUserPointer(); }
- void Set_Current_UserPointer(void* ptr) { CurrentChild->SetUserPointer(ptr); }
- // Access the current parent
- const char* Get_Current_Parent_Name(void) { return CurrentParent->Get_Name(); }
- int Get_Current_Parent_Total_Calls(void) { return CurrentParent->Get_Total_Calls(); }
- float Get_Current_Parent_Total_Time(void) { return CurrentParent->Get_Total_Time(); }
-
-protected:
- CProfileNode* CurrentParent;
- CProfileNode* CurrentChild;
-
- CProfileIterator(CProfileNode* start);
- friend class CProfileManager;
-};
-
-///The Manager for the Profile system
-class CProfileManager
-{
-public:
- static void Start_Profile(const char* name);
- static void Stop_Profile(void);
-
- static void CleanupMemory(void);
- // {
- // Root.CleanupMemory();
- // }
-
- static void Reset(void);
- static void Increment_Frame_Counter(void);
- static int Get_Frame_Count_Since_Reset(void) { return FrameCounter; }
- static float Get_Time_Since_Reset(void);
-
- static CProfileIterator* Get_Iterator(void);
- // {
- //
- // return new CProfileIterator( &Root );
- // }
- static void Release_Iterator(CProfileIterator* iterator) { delete (iterator); }
-
- static void dumpRecursive(CProfileIterator* profileIterator, int spacing);
-
- static void dumpAll();
-
-private:
- static int FrameCounter;
- static unsigned long int ResetTime;
-};
-
-#endif //#ifndef BT_NO_PROFILE
-
-///ProfileSampleClass is a simple way to profile a function's scope
-///Use the BT_PROFILE macro at the start of scope to time
-class CProfileSample
-{
-public:
- CProfileSample(const char* name);
-
- ~CProfileSample(void);
-};
-
-#define BT_PROFILE(name) CProfileSample __profile(name)
-
-#endif //BT_QUICK_PROF_H
diff --git a/thirdparty/bullet/LinearMath/btRandom.h b/thirdparty/bullet/LinearMath/btRandom.h
deleted file mode 100644
index e659af8605..0000000000
--- a/thirdparty/bullet/LinearMath/btRandom.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_GEN_RANDOM_H
-#define BT_GEN_RANDOM_H
-
-#ifdef MT19937
-
-#include <limits.h>
-#include <mt19937.h>
-
-#define GEN_RAND_MAX UINT_MAX
-
-SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { init_genrand(seed); }
-SIMD_FORCE_INLINE unsigned int GEN_rand() { return genrand_int32(); }
-
-#else
-
-#include <stdlib.h>
-
-#define GEN_RAND_MAX RAND_MAX
-
-SIMD_FORCE_INLINE void GEN_srand(unsigned int seed) { srand(seed); }
-SIMD_FORCE_INLINE unsigned int GEN_rand() { return rand(); }
-
-#endif
-
-#endif //BT_GEN_RANDOM_H
diff --git a/thirdparty/bullet/LinearMath/btReducedVector.cpp b/thirdparty/bullet/LinearMath/btReducedVector.cpp
deleted file mode 100644
index 1539584e7e..0000000000
--- a/thirdparty/bullet/LinearMath/btReducedVector.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// btReducedVector.cpp
-// LinearMath
-//
-// Created by Xuchen Han on 4/4/20.
-//
-#include <stdio.h>
-#include "btReducedVector.h"
-#include <cmath>
-
-// returns the projection of this onto other
-btReducedVector btReducedVector::proj(const btReducedVector& other) const
-{
- btReducedVector ret(m_sz);
- btScalar other_length2 = other.length2();
- if (other_length2 < SIMD_EPSILON)
- {
- return ret;
- }
- return other*(this->dot(other))/other_length2;
-}
-
-void btReducedVector::normalize()
-{
- if (this->length2() < SIMD_EPSILON)
- {
- m_indices.clear();
- m_vecs.clear();
- return;
- }
- *this /= std::sqrt(this->length2());
-}
-
-bool btReducedVector::testAdd() const
-{
- int sz = 5;
- btAlignedObjectArray<int> id1;
- id1.push_back(1);
- id1.push_back(3);
- btAlignedObjectArray<btVector3> v1;
- v1.push_back(btVector3(1,0,1));
- v1.push_back(btVector3(3,1,5));
- btAlignedObjectArray<int> id2;
- id2.push_back(2);
- id2.push_back(3);
- id2.push_back(5);
- btAlignedObjectArray<btVector3> v2;
- v2.push_back(btVector3(2,3,1));
- v2.push_back(btVector3(3,4,9));
- v2.push_back(btVector3(0,4,0));
- btAlignedObjectArray<int> id3;
- id3.push_back(1);
- id3.push_back(2);
- id3.push_back(3);
- id3.push_back(5);
- btAlignedObjectArray<btVector3> v3;
- v3.push_back(btVector3(1,0,1));
- v3.push_back(btVector3(2,3,1));
- v3.push_back(btVector3(6,5,14));
- v3.push_back(btVector3(0,4,0));
- btReducedVector rv1(sz, id1, v1);
- btReducedVector rv2(sz, id2, v2);
- btReducedVector ans(sz, id3, v3);
- bool ret = ((ans == rv1+rv2) && (ans == rv2+rv1));
- if (!ret)
- printf("btReducedVector testAdd failed\n");
- return ret;
-}
-
-bool btReducedVector::testMinus() const
-{
- int sz = 5;
- btAlignedObjectArray<int> id1;
- id1.push_back(1);
- id1.push_back(3);
- btAlignedObjectArray<btVector3> v1;
- v1.push_back(btVector3(1,0,1));
- v1.push_back(btVector3(3,1,5));
- btAlignedObjectArray<int> id2;
- id2.push_back(2);
- id2.push_back(3);
- id2.push_back(5);
- btAlignedObjectArray<btVector3> v2;
- v2.push_back(btVector3(2,3,1));
- v2.push_back(btVector3(3,4,9));
- v2.push_back(btVector3(0,4,0));
- btAlignedObjectArray<int> id3;
- id3.push_back(1);
- id3.push_back(2);
- id3.push_back(3);
- id3.push_back(5);
- btAlignedObjectArray<btVector3> v3;
- v3.push_back(btVector3(-1,-0,-1));
- v3.push_back(btVector3(2,3,1));
- v3.push_back(btVector3(0,3,4));
- v3.push_back(btVector3(0,4,0));
- btReducedVector rv1(sz, id1, v1);
- btReducedVector rv2(sz, id2, v2);
- btReducedVector ans(sz, id3, v3);
- bool ret = (ans == rv2-rv1);
- if (!ret)
- printf("btReducedVector testMinus failed\n");
- return ret;
-}
-
-bool btReducedVector::testDot() const
-{
- int sz = 5;
- btAlignedObjectArray<int> id1;
- id1.push_back(1);
- id1.push_back(3);
- btAlignedObjectArray<btVector3> v1;
- v1.push_back(btVector3(1,0,1));
- v1.push_back(btVector3(3,1,5));
- btAlignedObjectArray<int> id2;
- id2.push_back(2);
- id2.push_back(3);
- id2.push_back(5);
- btAlignedObjectArray<btVector3> v2;
- v2.push_back(btVector3(2,3,1));
- v2.push_back(btVector3(3,4,9));
- v2.push_back(btVector3(0,4,0));
- btReducedVector rv1(sz, id1, v1);
- btReducedVector rv2(sz, id2, v2);
- btScalar ans = 58;
- bool ret = (ans == rv2.dot(rv1) && ans == rv1.dot(rv2));
- ans = 14+16+9+16+81;
- ret &= (ans==rv2.dot(rv2));
-
- if (!ret)
- printf("btReducedVector testDot failed\n");
- return ret;
-}
-
-bool btReducedVector::testMultiply() const
-{
- int sz = 5;
- btAlignedObjectArray<int> id1;
- id1.push_back(1);
- id1.push_back(3);
- btAlignedObjectArray<btVector3> v1;
- v1.push_back(btVector3(1,0,1));
- v1.push_back(btVector3(3,1,5));
- btScalar s = 2;
- btReducedVector rv1(sz, id1, v1);
- btAlignedObjectArray<int> id2;
- id2.push_back(1);
- id2.push_back(3);
- btAlignedObjectArray<btVector3> v2;
- v2.push_back(btVector3(2,0,2));
- v2.push_back(btVector3(6,2,10));
- btReducedVector ans(sz, id2, v2);
- bool ret = (ans == rv1*s);
- if (!ret)
- printf("btReducedVector testMultiply failed\n");
- return ret;
-}
-
-void btReducedVector::test() const
-{
- bool ans = testAdd() && testMinus() && testDot() && testMultiply();
- if (ans)
- {
- printf("All tests passed\n");
- }
- else
- {
- printf("Tests failed\n");
- }
-}
diff --git a/thirdparty/bullet/LinearMath/btReducedVector.h b/thirdparty/bullet/LinearMath/btReducedVector.h
deleted file mode 100644
index 313a4271f0..0000000000
--- a/thirdparty/bullet/LinearMath/btReducedVector.h
+++ /dev/null
@@ -1,320 +0,0 @@
-//
-// btReducedVectors.h
-// BulletLinearMath
-//
-// Created by Xuchen Han on 4/4/20.
-//
-#ifndef btReducedVectors_h
-#define btReducedVectors_h
-#include "btVector3.h"
-#include "btMatrix3x3.h"
-#include "btAlignedObjectArray.h"
-#include <stdio.h>
-#include <vector>
-#include <algorithm>
-struct TwoInts
-{
- int a,b;
-};
-inline bool operator<(const TwoInts& A, const TwoInts& B)
-{
- return A.b < B.b;
-}
-
-
-// A helper vector type used for CG projections
-class btReducedVector
-{
-public:
- btAlignedObjectArray<int> m_indices;
- btAlignedObjectArray<btVector3> m_vecs;
- int m_sz; // all m_indices value < m_sz
-public:
- btReducedVector():m_sz(0)
- {
- m_indices.resize(0);
- m_vecs.resize(0);
- m_indices.clear();
- m_vecs.clear();
- }
-
- btReducedVector(int sz): m_sz(sz)
- {
- m_indices.resize(0);
- m_vecs.resize(0);
- m_indices.clear();
- m_vecs.clear();
- }
-
- btReducedVector(int sz, const btAlignedObjectArray<int>& indices, const btAlignedObjectArray<btVector3>& vecs): m_sz(sz), m_indices(indices), m_vecs(vecs)
- {
- }
-
- void simplify()
- {
- btAlignedObjectArray<int> old_indices(m_indices);
- btAlignedObjectArray<btVector3> old_vecs(m_vecs);
- m_indices.resize(0);
- m_vecs.resize(0);
- m_indices.clear();
- m_vecs.clear();
- for (int i = 0; i < old_indices.size(); ++i)
- {
- if (old_vecs[i].length2() > SIMD_EPSILON)
- {
- m_indices.push_back(old_indices[i]);
- m_vecs.push_back(old_vecs[i]);
- }
- }
- }
-
- btReducedVector operator+(const btReducedVector& other)
- {
- btReducedVector ret(m_sz);
- int i=0, j=0;
- while (i < m_indices.size() && j < other.m_indices.size())
- {
- if (m_indices[i] < other.m_indices[j])
- {
- ret.m_indices.push_back(m_indices[i]);
- ret.m_vecs.push_back(m_vecs[i]);
- ++i;
- }
- else if (m_indices[i] > other.m_indices[j])
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(other.m_vecs[j]);
- ++j;
- }
- else
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(m_vecs[i] + other.m_vecs[j]);
- ++i; ++j;
- }
- }
- while (i < m_indices.size())
- {
- ret.m_indices.push_back(m_indices[i]);
- ret.m_vecs.push_back(m_vecs[i]);
- ++i;
- }
- while (j < other.m_indices.size())
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(other.m_vecs[j]);
- ++j;
- }
- ret.simplify();
- return ret;
- }
-
- btReducedVector operator-()
- {
- btReducedVector ret(m_sz);
- for (int i = 0; i < m_indices.size(); ++i)
- {
- ret.m_indices.push_back(m_indices[i]);
- ret.m_vecs.push_back(-m_vecs[i]);
- }
- ret.simplify();
- return ret;
- }
-
- btReducedVector operator-(const btReducedVector& other)
- {
- btReducedVector ret(m_sz);
- int i=0, j=0;
- while (i < m_indices.size() && j < other.m_indices.size())
- {
- if (m_indices[i] < other.m_indices[j])
- {
- ret.m_indices.push_back(m_indices[i]);
- ret.m_vecs.push_back(m_vecs[i]);
- ++i;
- }
- else if (m_indices[i] > other.m_indices[j])
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(-other.m_vecs[j]);
- ++j;
- }
- else
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(m_vecs[i] - other.m_vecs[j]);
- ++i; ++j;
- }
- }
- while (i < m_indices.size())
- {
- ret.m_indices.push_back(m_indices[i]);
- ret.m_vecs.push_back(m_vecs[i]);
- ++i;
- }
- while (j < other.m_indices.size())
- {
- ret.m_indices.push_back(other.m_indices[j]);
- ret.m_vecs.push_back(-other.m_vecs[j]);
- ++j;
- }
- ret.simplify();
- return ret;
- }
-
- bool operator==(const btReducedVector& other) const
- {
- if (m_sz != other.m_sz)
- return false;
- if (m_indices.size() != other.m_indices.size())
- return false;
- for (int i = 0; i < m_indices.size(); ++i)
- {
- if (m_indices[i] != other.m_indices[i] || m_vecs[i] != other.m_vecs[i])
- {
- return false;
- }
- }
- return true;
- }
-
- bool operator!=(const btReducedVector& other) const
- {
- return !(*this == other);
- }
-
- btReducedVector& operator=(const btReducedVector& other)
- {
- if (this == &other)
- {
- return *this;
- }
- m_sz = other.m_sz;
- m_indices.copyFromArray(other.m_indices);
- m_vecs.copyFromArray(other.m_vecs);
- return *this;
- }
-
- btScalar dot(const btReducedVector& other) const
- {
- btScalar ret = 0;
- int j = 0;
- for (int i = 0; i < m_indices.size(); ++i)
- {
- while (j < other.m_indices.size() && other.m_indices[j] < m_indices[i])
- {
- ++j;
- }
- if (j < other.m_indices.size() && other.m_indices[j] == m_indices[i])
- {
- ret += m_vecs[i].dot(other.m_vecs[j]);
-// ++j;
- }
- }
- return ret;
- }
-
- btScalar dot(const btAlignedObjectArray<btVector3>& other) const
- {
- btScalar ret = 0;
- for (int i = 0; i < m_indices.size(); ++i)
- {
- ret += m_vecs[i].dot(other[m_indices[i]]);
- }
- return ret;
- }
-
- btScalar length2() const
- {
- return this->dot(*this);
- }
-
- void normalize();
-
- // returns the projection of this onto other
- btReducedVector proj(const btReducedVector& other) const;
-
- bool testAdd() const;
-
- bool testMinus() const;
-
- bool testDot() const;
-
- bool testMultiply() const;
-
- void test() const;
-
- void print() const
- {
- for (int i = 0; i < m_indices.size(); ++i)
- {
- printf("%d: (%f, %f, %f)/", m_indices[i], m_vecs[i][0],m_vecs[i][1],m_vecs[i][2]);
- }
- printf("\n");
- }
-
-
- void sort()
- {
- std::vector<TwoInts> tuples;
- for (int i = 0; i < m_indices.size(); ++i)
- {
- TwoInts ti;
- ti.a = i;
- ti.b = m_indices[i];
- tuples.push_back(ti);
- }
- std::sort(tuples.begin(), tuples.end());
- btAlignedObjectArray<int> new_indices;
- btAlignedObjectArray<btVector3> new_vecs;
- for (size_t i = 0; i < tuples.size(); ++i)
- {
- new_indices.push_back(tuples[i].b);
- new_vecs.push_back(m_vecs[tuples[i].a]);
- }
- m_indices = new_indices;
- m_vecs = new_vecs;
- }
-};
-
-SIMD_FORCE_INLINE btReducedVector operator*(const btReducedVector& v, btScalar s)
-{
- btReducedVector ret(v.m_sz);
- for (int i = 0; i < v.m_indices.size(); ++i)
- {
- ret.m_indices.push_back(v.m_indices[i]);
- ret.m_vecs.push_back(s*v.m_vecs[i]);
- }
- ret.simplify();
- return ret;
-}
-
-SIMD_FORCE_INLINE btReducedVector operator*(btScalar s, const btReducedVector& v)
-{
- return v*s;
-}
-
-SIMD_FORCE_INLINE btReducedVector operator/(const btReducedVector& v, btScalar s)
-{
- return v * (1.0/s);
-}
-
-SIMD_FORCE_INLINE btReducedVector& operator/=(btReducedVector& v, btScalar s)
-{
- v = v/s;
- return v;
-}
-
-SIMD_FORCE_INLINE btReducedVector& operator+=(btReducedVector& v1, const btReducedVector& v2)
-{
- v1 = v1+v2;
- return v1;
-}
-
-SIMD_FORCE_INLINE btReducedVector& operator-=(btReducedVector& v1, const btReducedVector& v2)
-{
- v1 = v1-v2;
- return v1;
-}
-
-#endif /* btReducedVectors_h */
diff --git a/thirdparty/bullet/LinearMath/btScalar.h b/thirdparty/bullet/LinearMath/btScalar.h
deleted file mode 100644
index b239217bb6..0000000000
--- a/thirdparty/bullet/LinearMath/btScalar.h
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
-Copyright (c) 2003-2009 Erwin Coumans http://bullet.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SCALAR_H
-#define BT_SCALAR_H
-
-#ifdef BT_MANAGED_CODE
-//Aligned data types not supported in managed code
-#pragma unmanaged
-#endif
-
-#include <math.h>
-#include <stdlib.h> //size_t for MSVC 6.0
-#include <float.h>
-
-/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
-#define BT_BULLET_VERSION 317
-
-inline int btGetVersion()
-{
- return BT_BULLET_VERSION;
-}
-
-inline int btIsDoublePrecision()
-{
- #ifdef BT_USE_DOUBLE_PRECISION
- return true;
- #else
- return false;
- #endif
-}
-
-
-// The following macro "BT_NOT_EMPTY_FILE" can be put into a file
-// in order suppress the MS Visual C++ Linker warning 4221
-//
-// warning LNK4221: no public symbols found; archive member will be inaccessible
-//
-// This warning occurs on PC and XBOX when a file compiles out completely
-// has no externally visible symbols which may be dependant on configuration
-// #defines and options.
-//
-// see more https://stackoverflow.com/questions/1822887/what-is-the-best-way-to-eliminate-ms-visual-c-linker-warning-warning-lnk422
-
-#if defined(_MSC_VER)
-#define BT_NOT_EMPTY_FILE_CAT_II(p, res) res
-#define BT_NOT_EMPTY_FILE_CAT_I(a, b) BT_NOT_EMPTY_FILE_CAT_II(~, a##b)
-#define BT_NOT_EMPTY_FILE_CAT(a, b) BT_NOT_EMPTY_FILE_CAT_I(a, b)
-#define BT_NOT_EMPTY_FILE \
- namespace \
- { \
- char BT_NOT_EMPTY_FILE_CAT(NoEmptyFileDummy, __COUNTER__); \
- }
-#else
-#define BT_NOT_EMPTY_FILE
-#endif
-
-// clang and most formatting tools don't support indentation of preprocessor guards, so turn it off
-// clang-format off
-#if defined(DEBUG) || defined (_DEBUG)
- #define BT_DEBUG
-#endif
-
-#ifdef _WIN32
- #if defined(__GNUC__) // it should handle both MINGW and CYGWIN
- #define SIMD_FORCE_INLINE __inline__ __attribute__((always_inline))
- #define ATTRIBUTE_ALIGNED16(a) a __attribute__((aligned(16)))
- #define ATTRIBUTE_ALIGNED64(a) a __attribute__((aligned(64)))
- #define ATTRIBUTE_ALIGNED128(a) a __attribute__((aligned(128)))
- #elif ( defined(_MSC_VER) && _MSC_VER < 1300 )
- #define SIMD_FORCE_INLINE inline
- #define ATTRIBUTE_ALIGNED16(a) a
- #define ATTRIBUTE_ALIGNED64(a) a
- #define ATTRIBUTE_ALIGNED128(a) a
- #elif defined(_M_ARM)
- #define SIMD_FORCE_INLINE __forceinline
- #define ATTRIBUTE_ALIGNED16(a) __declspec() a
- #define ATTRIBUTE_ALIGNED64(a) __declspec() a
- #define ATTRIBUTE_ALIGNED128(a) __declspec () a
- #else//__MINGW32__
- //#define BT_HAS_ALIGNED_ALLOCATOR
- #pragma warning(disable : 4324) // disable padding warning
-// #pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
- #pragma warning(disable:4996) //Turn off warnings about deprecated C routines
-// #pragma warning(disable:4786) // Disable the "debug name too long" warning
-
- #define SIMD_FORCE_INLINE __forceinline
- #define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
- #define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
- #define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
- #ifdef _XBOX
- #define BT_USE_VMX128
-
- #include <ppcintrinsics.h>
- #define BT_HAVE_NATIVE_FSEL
- #define btFsel(a,b,c) __fsel((a),(b),(c))
- #else
-
-#if defined (_M_ARM)
- //Do not turn SSE on for ARM (may want to turn on BT_USE_NEON however)
-#elif (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
-
-#ifdef __clang__
-#define __BT_DISABLE_SSE__
-#endif
-#ifndef __BT_DISABLE_SSE__
- #if _MSC_VER>1400
- #define BT_USE_SIMD_VECTOR3
- #endif
- #define BT_USE_SSE
-#endif//__BT_DISABLE_SSE__
- #ifdef BT_USE_SSE
-
-#if (_MSC_FULL_VER >= 170050727)//Visual Studio 2012 can compile SSE4/FMA3 (but SSE4/FMA3 is not enabled by default)
- #define BT_ALLOW_SSE4
-#endif //(_MSC_FULL_VER >= 160040219)
-
- //BT_USE_SSE_IN_API is disabled under Windows by default, because
- //it makes it harder to integrate Bullet into your application under Windows
- //(structured embedding Bullet structs/classes need to be 16-byte aligned)
- //with relatively little performance gain
- //If you are not embedded Bullet data in your classes, or make sure that you align those classes on 16-byte boundaries
- //you can manually enable this line or set it in the build system for a bit of performance gain (a few percent, dependent on usage)
- //#define BT_USE_SSE_IN_API
- #endif //BT_USE_SSE
- #include <emmintrin.h>
-#endif
-
- #endif//_XBOX
-
- #endif //__MINGW32__
-
- #ifdef BT_DEBUG
- #ifdef _MSC_VER
- #include <stdio.h>
- #define btAssert(x) { if(!(x)){printf("Assert " __FILE__ ":%u (%s)\n", __LINE__, #x);__debugbreak(); }}
- #else//_MSC_VER
- #include <assert.h>
- #define btAssert assert
- #endif//_MSC_VER
- #else
- #define btAssert(x)
- #endif
- //btFullAssert is optional, slows down a lot
- #define btFullAssert(x)
-
- #define btLikely(_c) _c
- #define btUnlikely(_c) _c
-
-#else//_WIN32
-
- #if defined (__CELLOS_LV2__)
- #define SIMD_FORCE_INLINE inline __attribute__((always_inline))
- #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
- #ifdef BT_DEBUG
- #ifdef __SPU__
- #include <spu_printf.h>
- #define printf spu_printf
- #define btAssert(x) {if(!(x)){printf("Assert " __FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
- #else
- #define btAssert assert
- #endif
-
- #else//BT_DEBUG
- #define btAssert(x)
- #endif//BT_DEBUG
- //btFullAssert is optional, slows down a lot
- #define btFullAssert(x)
-
- #define btLikely(_c) _c
- #define btUnlikely(_c) _c
-
- #else//defined (__CELLOS_LV2__)
-
- #ifdef USE_LIBSPE2
-
- #define SIMD_FORCE_INLINE __inline
- #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
- #ifdef BT_DEBUG
- #define btAssert assert
- #else
- #define btAssert(x)
- #endif
- //btFullAssert is optional, slows down a lot
- #define btFullAssert(x)
-
-
- #define btLikely(_c) __builtin_expect((_c), 1)
- #define btUnlikely(_c) __builtin_expect((_c), 0)
-
-
- #else//USE_LIBSPE2
- //non-windows systems
-
- #if (defined (__APPLE__) && (!defined (BT_USE_DOUBLE_PRECISION)))
- #if defined (__i386__) || defined (__x86_64__)
- #define BT_USE_SIMD_VECTOR3
- #define BT_USE_SSE
- //BT_USE_SSE_IN_API is enabled on Mac OSX by default, because memory is automatically aligned on 16-byte boundaries
- //if apps run into issues, we will disable the next line
- #define BT_USE_SSE_IN_API
- #ifdef BT_USE_SSE
- // include appropriate SSE level
- #if defined (__SSE4_1__)
- #include <smmintrin.h>
- #elif defined (__SSSE3__)
- #include <tmmintrin.h>
- #elif defined (__SSE3__)
- #include <pmmintrin.h>
- #else
- #include <emmintrin.h>
- #endif
- #endif //BT_USE_SSE
- #elif defined( __ARM_NEON__ )
- #ifdef __clang__
- #define BT_USE_NEON 1
- #define BT_USE_SIMD_VECTOR3
-
- #if defined BT_USE_NEON && defined (__clang__)
- #include <arm_neon.h>
- #endif//BT_USE_NEON
- #endif //__clang__
- #endif//__arm__
-
- #define SIMD_FORCE_INLINE inline __attribute__ ((always_inline))
- ///@todo: check out alignment methods for other platforms/compilers
- #define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- #define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- #define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #ifndef assert
- #include <assert.h>
- #endif
-
- #if defined(DEBUG) || defined (_DEBUG)
- #if defined (__i386__) || defined (__x86_64__)
- #include <stdio.h>
- #define btAssert(x)\
- {\
- if(!(x))\
- {\
- printf("Assert %s in line %d, file %s\n",#x, __LINE__, __FILE__);\
- asm volatile ("int3");\
- }\
- }
- #else//defined (__i386__) || defined (__x86_64__)
- #define btAssert assert
- #endif//defined (__i386__) || defined (__x86_64__)
- #else//defined(DEBUG) || defined (_DEBUG)
- #define btAssert(x)
- #endif//defined(DEBUG) || defined (_DEBUG)
-
- //btFullAssert is optional, slows down a lot
- #define btFullAssert(x)
- #define btLikely(_c) _c
- #define btUnlikely(_c) _c
-
- #else//__APPLE__
-
- #define SIMD_FORCE_INLINE inline
- ///@todo: check out alignment methods for other platforms/compilers
- ///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
- ///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
- ///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
- #define ATTRIBUTE_ALIGNED16(a) a
- #define ATTRIBUTE_ALIGNED64(a) a
- #define ATTRIBUTE_ALIGNED128(a) a
- #ifndef assert
- #include <assert.h>
- #endif
-
- #if defined(DEBUG) || defined (_DEBUG)
- #define btAssert assert
- #else
- #define btAssert(x)
- #endif
-
- //btFullAssert is optional, slows down a lot
- #define btFullAssert(x)
- #define btLikely(_c) _c
- #define btUnlikely(_c) _c
- #endif //__APPLE__
- #endif // LIBSPE2
- #endif //__CELLOS_LV2__
-#endif//_WIN32
-
-
-///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
-#if defined(BT_USE_DOUBLE_PRECISION)
- typedef double btScalar;
- //this number could be bigger in double precision
- #define BT_LARGE_FLOAT 1e30
-#else
- typedef float btScalar;
- //keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
- #define BT_LARGE_FLOAT 1e18f
-#endif
-
-#ifdef BT_USE_SSE
- typedef __m128 btSimdFloat4;
-#endif //BT_USE_SSE
-
-#if defined(BT_USE_SSE)
- //#if defined BT_USE_SSE_IN_API && defined (BT_USE_SSE)
- #ifdef _WIN32
-
- #ifndef BT_NAN
- static int btNanMask = 0x7F800001;
- #define BT_NAN (*(float *)&btNanMask)
- #endif
-
- #ifndef BT_INFINITY
- static int btInfinityMask = 0x7F800000;
- #define BT_INFINITY (*(float *)&btInfinityMask)
- inline int btGetInfinityMask() //suppress stupid compiler warning
- {
- return btInfinityMask;
- }
- #endif
-
-
-
- //use this, in case there are clashes (such as xnamath.h)
- #ifndef BT_NO_SIMD_OPERATOR_OVERLOADS
- inline __m128 operator+(const __m128 A, const __m128 B)
- {
- return _mm_add_ps(A, B);
- }
-
- inline __m128 operator-(const __m128 A, const __m128 B)
- {
- return _mm_sub_ps(A, B);
- }
-
- inline __m128 operator*(const __m128 A, const __m128 B)
- {
- return _mm_mul_ps(A, B);
- }
- #endif //BT_NO_SIMD_OPERATOR_OVERLOADS
-
- #define btCastfTo128i(a) (_mm_castps_si128(a))
- #define btCastfTo128d(a) (_mm_castps_pd(a))
- #define btCastiTo128f(a) (_mm_castsi128_ps(a))
- #define btCastdTo128f(a) (_mm_castpd_ps(a))
- #define btCastdTo128i(a) (_mm_castpd_si128(a))
- #define btAssign128(r0, r1, r2, r3) _mm_setr_ps(r0, r1, r2, r3)
-
- #else //_WIN32
-
- #define btCastfTo128i(a) ((__m128i)(a))
- #define btCastfTo128d(a) ((__m128d)(a))
- #define btCastiTo128f(a) ((__m128)(a))
- #define btCastdTo128f(a) ((__m128)(a))
- #define btCastdTo128i(a) ((__m128i)(a))
- #define btAssign128(r0, r1, r2, r3) \
- (__m128) { r0, r1, r2, r3 }
- #define BT_INFINITY INFINITY
- #define BT_NAN NAN
- #endif //_WIN32
-#else//BT_USE_SSE
-
- #ifdef BT_USE_NEON
- #include <arm_neon.h>
-
- typedef float32x4_t btSimdFloat4;
- #define BT_INFINITY INFINITY
- #define BT_NAN NAN
- #define btAssign128(r0, r1, r2, r3) \
- (float32x4_t) { r0, r1, r2, r3 }
- #else //BT_USE_NEON
-
- #ifndef BT_INFINITY
- struct btInfMaskConverter
- {
- union {
- float mask;
- int intmask;
- };
- btInfMaskConverter(int _mask = 0x7F800000)
- : intmask(_mask)
- {
- }
- };
- static btInfMaskConverter btInfinityMask = 0x7F800000;
- #define BT_INFINITY (btInfinityMask.mask)
- inline int btGetInfinityMask() //suppress stupid compiler warning
- {
- return btInfinityMask.intmask;
- }
- #endif
- #endif //BT_USE_NEON
-
-#endif //BT_USE_SSE
-
-#ifdef BT_USE_NEON
- #include <arm_neon.h>
-
- typedef float32x4_t btSimdFloat4;
- #define BT_INFINITY INFINITY
- #define BT_NAN NAN
- #define btAssign128(r0, r1, r2, r3) \
- (float32x4_t) { r0, r1, r2, r3 }
-#endif//BT_USE_NEON
-
-#define BT_DECLARE_ALIGNED_ALLOCATOR() \
- SIMD_FORCE_INLINE void *operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
- SIMD_FORCE_INLINE void operator delete(void *ptr) { btAlignedFree(ptr); } \
- SIMD_FORCE_INLINE void *operator new(size_t, void *ptr) { return ptr; } \
- SIMD_FORCE_INLINE void operator delete(void *, void *) {} \
- SIMD_FORCE_INLINE void *operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes, 16); } \
- SIMD_FORCE_INLINE void operator delete[](void *ptr) { btAlignedFree(ptr); } \
- SIMD_FORCE_INLINE void *operator new[](size_t, void *ptr) { return ptr; } \
- SIMD_FORCE_INLINE void operator delete[](void *, void *) {}
-
-#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
-
- SIMD_FORCE_INLINE btScalar btSqrt(btScalar x)
- {
- return sqrt(x);
- }
- SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
- SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
- SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
- SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
- SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
- {
- if (x < btScalar(-1)) x = btScalar(-1);
- if (x > btScalar(1)) x = btScalar(1);
- return acos(x);
- }
- SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
- {
- if (x < btScalar(-1)) x = btScalar(-1);
- if (x > btScalar(1)) x = btScalar(1);
- return asin(x);
- }
- SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
- SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
- SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
- SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
- SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return pow(x, y); }
- SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmod(x, y); }
-
-#else//BT_USE_DOUBLE_PRECISION
-
- SIMD_FORCE_INLINE btScalar btSqrt(btScalar y)
- {
- #ifdef USE_APPROXIMATION
- #ifdef __LP64__
- float xhalf = 0.5f * y;
- int i = *(int *)&y;
- i = 0x5f375a86 - (i >> 1);
- y = *(float *)&i;
- y = y * (1.5f - xhalf * y * y);
- y = y * (1.5f - xhalf * y * y);
- y = y * (1.5f - xhalf * y * y);
- y = 1 / y;
- return y;
- #else
- double x, z, tempf;
- unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
- tempf = y;
- *tfptr = (0xbfcdd90a - *tfptr) >> 1; /* estimate of 1/sqrt(y) */
- x = tempf;
- z = y * btScalar(0.5);
- x = (btScalar(1.5) * x) - (x * x) * (x * z); /* iteration formula */
- x = (btScalar(1.5) * x) - (x * x) * (x * z);
- x = (btScalar(1.5) * x) - (x * x) * (x * z);
- x = (btScalar(1.5) * x) - (x * x) * (x * z);
- x = (btScalar(1.5) * x) - (x * x) * (x * z);
- return x * y;
- #endif
- #else
- return sqrtf(y);
- #endif
- }
- SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
- SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
- SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
- SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
- SIMD_FORCE_INLINE btScalar btAcos(btScalar x)
- {
- if (x < btScalar(-1))
- x = btScalar(-1);
- if (x > btScalar(1))
- x = btScalar(1);
- return acosf(x);
- }
- SIMD_FORCE_INLINE btScalar btAsin(btScalar x)
- {
- if (x < btScalar(-1))
- x = btScalar(-1);
- if (x > btScalar(1))
- x = btScalar(1);
- return asinf(x);
- }
- SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
- SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
- SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
- SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
- SIMD_FORCE_INLINE btScalar btPow(btScalar x, btScalar y) { return powf(x, y); }
- SIMD_FORCE_INLINE btScalar btFmod(btScalar x, btScalar y) { return fmodf(x, y); }
-
-#endif//BT_USE_DOUBLE_PRECISION
-
-#define SIMD_PI btScalar(3.1415926535897932384626433832795029)
-#define SIMD_2_PI (btScalar(2.0) * SIMD_PI)
-#define SIMD_HALF_PI (SIMD_PI * btScalar(0.5))
-#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
-#define SIMD_DEGS_PER_RAD (btScalar(360.0) / SIMD_2_PI)
-#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
-#define btRecipSqrt(x) ((btScalar)(btScalar(1.0) / btSqrt(btScalar(x)))) /* reciprocal square root */
-#define btRecip(x) (btScalar(1.0) / btScalar(x))
-
-#ifdef BT_USE_DOUBLE_PRECISION
- #define SIMD_EPSILON DBL_EPSILON
- #define SIMD_INFINITY DBL_MAX
- #define BT_ONE 1.0
- #define BT_ZERO 0.0
- #define BT_TWO 2.0
- #define BT_HALF 0.5
-#else
- #define SIMD_EPSILON FLT_EPSILON
- #define SIMD_INFINITY FLT_MAX
- #define BT_ONE 1.0f
- #define BT_ZERO 0.0f
- #define BT_TWO 2.0f
- #define BT_HALF 0.5f
-#endif
-
-// clang-format on
-
-SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x)
-{
- btScalar coeff_1 = SIMD_PI / 4.0f;
- btScalar coeff_2 = 3.0f * coeff_1;
- btScalar abs_y = btFabs(y);
- btScalar angle;
- if (x >= 0.0f)
- {
- btScalar r = (x - abs_y) / (x + abs_y);
- angle = coeff_1 - coeff_1 * r;
- }
- else
- {
- btScalar r = (x + abs_y) / (abs_y - x);
- angle = coeff_2 - coeff_1 * r;
- }
- return (y < 0.0f) ? -angle : angle;
-}
-
-SIMD_FORCE_INLINE bool btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
-
-SIMD_FORCE_INLINE bool btEqual(btScalar a, btScalar eps)
-{
- return (((a) <= eps) && !((a) < -eps));
-}
-SIMD_FORCE_INLINE bool btGreaterEqual(btScalar a, btScalar eps)
-{
- return (!((a) <= eps));
-}
-
-SIMD_FORCE_INLINE int btIsNegative(btScalar x)
-{
- return x < btScalar(0.0) ? 1 : 0;
-}
-
-SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
-SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
-
-#define BT_DECLARE_HANDLE(name) \
- typedef struct name##__ \
- { \
- int unused; \
- } * name
-
-#ifndef btFsel
-SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
-{
- return a >= 0 ? b : c;
-}
-#endif
-#define btFsels(a, b, c) (btScalar) btFsel(a, b, c)
-
-SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
-{
- long int i = 1;
- const char *p = (const char *)&i;
- if (p[0] == 1) // Lowest address contains the least significant byte
- return true;
- else
- return false;
-}
-
-///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
-///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
-SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero)
-{
- // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
- // Rely on positive value or'ed with its negative having sign bit on
- // and zero value or'ed with its negative (which is still zero) having sign bit off
- // Use arithmetic shift right, shifting the sign bit through all 32 bits
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
-}
-SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
-{
- unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
- unsigned testEqz = ~testNz;
- return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
-}
-SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
-{
-#ifdef BT_HAVE_NATIVE_FSEL
- return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
-#else
- return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero;
-#endif
-}
-
-template <typename T>
-SIMD_FORCE_INLINE void btSwap(T &a, T &b)
-{
- T tmp = a;
- a = b;
- b = tmp;
-}
-
-//PCK: endian swapping functions
-SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
-{
- return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
-}
-
-SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
-{
- return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
-}
-
-SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
-{
- return btSwapEndian((unsigned)val);
-}
-
-SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
-{
- return btSwapEndian((unsigned short)val);
-}
-
-///btSwapFloat uses using char pointers to swap the endianness
-////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
-///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754.
-///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception.
-///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you.
-///so instead of returning a float/double, we return integer/long long integer
-SIMD_FORCE_INLINE unsigned int btSwapEndianFloat(float d)
-{
- unsigned int a = 0;
- unsigned char *dst = (unsigned char *)&a;
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
- return a;
-}
-
-// unswap using char pointers
-SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a)
-{
- float d = 0.0f;
- unsigned char *src = (unsigned char *)&a;
- unsigned char *dst = (unsigned char *)&d;
-
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
-
- return d;
-}
-
-// swap using char pointers
-SIMD_FORCE_INLINE void btSwapEndianDouble(double d, unsigned char *dst)
-{
- unsigned char *src = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
-}
-
-// unswap using char pointers
-SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src)
-{
- double d = 0.0;
- unsigned char *dst = (unsigned char *)&d;
-
- dst[0] = src[7];
- dst[1] = src[6];
- dst[2] = src[5];
- dst[3] = src[4];
- dst[4] = src[3];
- dst[5] = src[2];
- dst[6] = src[1];
- dst[7] = src[0];
-
- return d;
-}
-
-template <typename T>
-SIMD_FORCE_INLINE void btSetZero(T *a, int n)
-{
- T *acurr = a;
- size_t ncurr = n;
- while (ncurr > 0)
- {
- *(acurr++) = 0;
- --ncurr;
- }
-}
-
-SIMD_FORCE_INLINE btScalar btLargeDot(const btScalar *a, const btScalar *b, int n)
-{
- btScalar p0, q0, m0, p1, q1, m1, sum;
- sum = 0;
- n -= 2;
- while (n >= 0)
- {
- p0 = a[0];
- q0 = b[0];
- m0 = p0 * q0;
- p1 = a[1];
- q1 = b[1];
- m1 = p1 * q1;
- sum += m0;
- sum += m1;
- a += 2;
- b += 2;
- n -= 2;
- }
- n += 2;
- while (n > 0)
- {
- sum += (*a) * (*b);
- a++;
- b++;
- n--;
- }
- return sum;
-}
-
-// returns normalized value in range [-SIMD_PI, SIMD_PI]
-SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians)
-{
- angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
- if (angleInRadians < -SIMD_PI)
- {
- return angleInRadians + SIMD_2_PI;
- }
- else if (angleInRadians > SIMD_PI)
- {
- return angleInRadians - SIMD_2_PI;
- }
- else
- {
- return angleInRadians;
- }
-}
-
-///rudimentary class to provide type info
-struct btTypedObject
-{
- btTypedObject(int objectType)
- : m_objectType(objectType)
- {
- }
- int m_objectType;
- inline int getObjectType() const
- {
- return m_objectType;
- }
-};
-
-///align a pointer to the provided alignment, upwards
-template <typename T>
-T *btAlignPointer(T *unalignedPtr, size_t alignment)
-{
- struct btConvertPointerSizeT
- {
- union {
- T *ptr;
- size_t integer;
- };
- };
- btConvertPointerSizeT converter;
-
- const size_t bit_mask = ~(alignment - 1);
- converter.ptr = unalignedPtr;
- converter.integer += alignment - 1;
- converter.integer &= bit_mask;
- return converter.ptr;
-}
-
-#endif //BT_SCALAR_H
diff --git a/thirdparty/bullet/LinearMath/btSerializer.cpp b/thirdparty/bullet/LinearMath/btSerializer.cpp
deleted file mode 100644
index 068836f2c4..0000000000
--- a/thirdparty/bullet/LinearMath/btSerializer.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-char sBulletDNAstr[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
-char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
-char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
-char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
-char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
-char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
-char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
-char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
-char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
-char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
-char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
-char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
-char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
-char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
-char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
-char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
-char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
-char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
-char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
-char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
-char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
-char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
-char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
-char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
-char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
-char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
-char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
-char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
-char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
-char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
-char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
-char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
-char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
-char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
-char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
-char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
-char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
-char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
-char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
-char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
-char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
-char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
-char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
-char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
-char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
-char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
-char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
-char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
-char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
-char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
-char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
-char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
-char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
-char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
-char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
-char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
-char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
-char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),
-char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),
-char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),
-char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
-char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(111),
-char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(76),char(111),char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(66),char(91),char(52),char(93),char(0),
-char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),
-char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(78),char(111),char(114),char(109),
-char(97),char(108),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
-char(110),char(68),char(105),char(114),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(68),char(105),char(114),char(50),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
-char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
-char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
-char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
-char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
-char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
-char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
-char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
-char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
-char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
-char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
-char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
-char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
-char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
-char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
-char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
-char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
-char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
-char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
-char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
-char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
-char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
-char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
-char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
-char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
-char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
-char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
-char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
-char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
-char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
-char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
-char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
-char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
-char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
-char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
-char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
-char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
-char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
-char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
-char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
-char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
-char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
-char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
-char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
-char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
-char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
-char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
-char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
-char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
-char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
-char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
-char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
-char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
-char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
-char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
-char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
-char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
-char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
-char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
-char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
-char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
-char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
-char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
-char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
-char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
-char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
-char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
-char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
-char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
-char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
-char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
-char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
-char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
-char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
-char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
-char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
-char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
-char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
-char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
-char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
-char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
-char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
-char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
-char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
-char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
-char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
-char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
-char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
-char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
-char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
-char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
-char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
-char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
-char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
-char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
-char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
-char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
-char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
-char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
-char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
-char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
-char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
-char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
-char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
-char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
-char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
-char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
-char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
-char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
-char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
-char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
-char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
-char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
-char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
-char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
-char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
-char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
-char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
-char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
-char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
-char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
-char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
-char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
-char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
-char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
-char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
-char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
-char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
-char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
-char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
-char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
-char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
-char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
-char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
-char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
-char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
-char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
-char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
-char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
-char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
-char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
-char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
-char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
-char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
-char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
-char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
-char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
-char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
-char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
-char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
-char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
-char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
-char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
-char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
-char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
-char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
-char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
-char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
-char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
-char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
-char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
-char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
-char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
-char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
-char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
-char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
-char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
-char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
-char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
-char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
-char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
-char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
-char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
-char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
-char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
-char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
-char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
-char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
-char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
-char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
-char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
-char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
-char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
-char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
-char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
-char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
-char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
-char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
-char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
-char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
-char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
-char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
-char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
-char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
-char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
-char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
-char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
-char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
-char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
-char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
-char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
-char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
-char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
-char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
-char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
-char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
-char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
-char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
-char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
-char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
-char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
-char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
-char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
-char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
-char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
-char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
-char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
-char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
-char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
-char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
-char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
-char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
-char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
-char(12),char(0),char(36),char(0),char(8),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
-char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(84),char(0),char(-124),char(0),char(12),char(0),char(52),char(0),char(52),char(0),
-char(20),char(0),char(64),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(32),char(0),char(28),char(0),char(60),char(0),char(56),char(0),
-char(76),char(0),char(76),char(0),char(24),char(0),char(60),char(0),char(60),char(0),char(60),char(0),char(16),char(0),char(16),char(6),char(-24),char(1),char(72),char(3),
-char(16),char(1),char(64),char(0),char(68),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(-8),char(1),char(-72),char(3),char(8),char(0),
-char(52),char(0),char(52),char(0),char(0),char(0),char(68),char(0),char(84),char(0),char(-124),char(0),char(116),char(0),char(92),char(1),char(-36),char(0),char(-116),char(1),
-char(124),char(1),char(-44),char(0),char(-4),char(0),char(-52),char(1),char(92),char(1),char(116),char(2),char(-124),char(2),char(-76),char(4),char(-52),char(0),char(108),char(1),
-char(92),char(0),char(-116),char(0),char(16),char(0),char(100),char(0),char(20),char(0),char(36),char(0),char(100),char(0),char(92),char(0),char(104),char(0),char(-64),char(0),
-char(92),char(1),char(104),char(0),char(-68),char(1),char(112),char(3),char(-56),char(1),char(-68),char(0),char(100),char(0),char(28),char(1),char(-12),char(1),char(0),char(0),
-char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
-char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
-char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
-char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
-char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
-char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
-char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
-char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
-char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
-char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
-char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
-char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
-char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
-char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
-char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
-char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
-char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
-char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
-char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
-char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
-char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
-char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
-char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
-char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
-char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
-char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
-char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
-char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
-char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
-char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
-char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
-char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
-char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
-char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
-char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
-char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
-char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
-char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
-char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
-char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
-char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
-char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
-char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
-char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
-char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
-char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
-char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
-char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
-char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
-char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
-char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
-char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
-char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
-char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
-char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
-char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
-char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
-char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
-char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
-char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
-char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
-char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
-char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
-char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
-char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
-char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
-char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
-char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
-char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
-char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
-char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
-char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
-char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
-char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
-char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
-char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
-char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
-char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
-char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
-char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
-char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
-char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
-char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
-char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
-char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
-char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
-char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
-char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
-char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
-char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
-char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
-char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
-char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
-char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
-char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
-char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
-char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
-char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
-char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
-char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
-char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
-char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
-char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
-char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
-char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
-char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
-char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
-char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
-char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
-char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
-char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
-char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
-char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
-char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
-char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
-char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
-char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
-char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
-char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
-char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
-char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
-char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
-char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
-char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
-char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
-char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
-char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
-char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
-char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
-char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
-char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
-char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
-char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
-char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
-char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
-char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
-char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
-char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
-char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
-char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
-char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
-char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
-char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
-char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
-char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
-char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
-char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
-char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
-char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
-char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
-char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
-char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
-char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
-char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
-char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
-char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
-char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
-char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
-char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
-char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
-char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
-char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
-char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
-char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
-char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
-char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
-char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
-char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
-char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
-char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
-char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
-char(0),char(0),char(37),char(0),};
-int sBulletDNAlen= sizeof(sBulletDNAstr);
diff --git a/thirdparty/bullet/LinearMath/btSerializer.h b/thirdparty/bullet/LinearMath/btSerializer.h
deleted file mode 100644
index f18442f23d..0000000000
--- a/thirdparty/bullet/LinearMath/btSerializer.h
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_SERIALIZER_H
-#define BT_SERIALIZER_H
-
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
-#include "btHashMap.h"
-
-#if !defined(__CELLOS_LV2__) && !defined(__MWERKS__)
-#include <memory.h>
-#endif
-#include <string.h>
-
-extern char sBulletDNAstr[];
-extern int sBulletDNAlen;
-extern char sBulletDNAstr64[];
-extern int sBulletDNAlen64;
-
-SIMD_FORCE_INLINE int btStrLen(const char* str)
-{
- if (!str)
- return (0);
- int len = 0;
-
- while (*str != 0)
- {
- str++;
- len++;
- }
-
- return len;
-}
-
-class btChunk
-{
-public:
- int m_chunkCode;
- int m_length;
- void* m_oldPtr;
- int m_dna_nr;
- int m_number;
-};
-
-enum btSerializationFlags
-{
- BT_SERIALIZE_NO_BVH = 1,
- BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
- BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4,
- BT_SERIALIZE_CONTACT_MANIFOLDS = 8,
-};
-
-class btSerializer
-{
-public:
- virtual ~btSerializer() {}
-
- virtual const unsigned char* getBufferPointer() const = 0;
-
- virtual int getCurrentBufferSize() const = 0;
-
- virtual btChunk* allocate(size_t size, int numElements) = 0;
-
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr) = 0;
-
- virtual void* findPointer(void* oldPtr) = 0;
-
- virtual void* getUniquePointer(void* oldPtr) = 0;
-
- virtual void startSerialization() = 0;
-
- virtual void finishSerialization() = 0;
-
- virtual const char* findNameForPointer(const void* ptr) const = 0;
-
- virtual void registerNameForPointer(const void* ptr, const char* name) = 0;
-
- virtual void serializeName(const char* ptr) = 0;
-
- virtual int getSerializationFlags() const = 0;
-
- virtual void setSerializationFlags(int flags) = 0;
-
- virtual int getNumChunks() const = 0;
-
- virtual const btChunk* getChunk(int chunkIndex) const = 0;
-};
-
-#define BT_HEADER_LENGTH 12
-#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined(__PPC__) || defined(__ppc__) || defined(__BIG_ENDIAN__)
-#define BT_MAKE_ID(a, b, c, d) ((int)(a) << 24 | (int)(b) << 16 | (c) << 8 | (d))
-#else
-#define BT_MAKE_ID(a, b, c, d) ((int)(d) << 24 | (int)(c) << 16 | (b) << 8 | (a))
-#endif
-
-#define BT_MULTIBODY_CODE BT_MAKE_ID('M', 'B', 'D', 'Y')
-#define BT_MB_LINKCOLLIDER_CODE BT_MAKE_ID('M', 'B', 'L', 'C')
-#define BT_SOFTBODY_CODE BT_MAKE_ID('S', 'B', 'D', 'Y')
-#define BT_COLLISIONOBJECT_CODE BT_MAKE_ID('C', 'O', 'B', 'J')
-#define BT_RIGIDBODY_CODE BT_MAKE_ID('R', 'B', 'D', 'Y')
-#define BT_CONSTRAINT_CODE BT_MAKE_ID('C', 'O', 'N', 'S')
-#define BT_BOXSHAPE_CODE BT_MAKE_ID('B', 'O', 'X', 'S')
-#define BT_QUANTIZED_BVH_CODE BT_MAKE_ID('Q', 'B', 'V', 'H')
-#define BT_TRIANLGE_INFO_MAP BT_MAKE_ID('T', 'M', 'A', 'P')
-#define BT_SHAPE_CODE BT_MAKE_ID('S', 'H', 'A', 'P')
-#define BT_ARRAY_CODE BT_MAKE_ID('A', 'R', 'A', 'Y')
-#define BT_SBMATERIAL_CODE BT_MAKE_ID('S', 'B', 'M', 'T')
-#define BT_SBNODE_CODE BT_MAKE_ID('S', 'B', 'N', 'D')
-#define BT_DYNAMICSWORLD_CODE BT_MAKE_ID('D', 'W', 'L', 'D')
-#define BT_CONTACTMANIFOLD_CODE BT_MAKE_ID('C', 'O', 'N', 'T')
-#define BT_DNA_CODE BT_MAKE_ID('D', 'N', 'A', '1')
-
-struct btPointerUid
-{
- union {
- void* m_ptr;
- int m_uniqueIds[2];
- };
-};
-
-struct btBulletSerializedArrays
-{
- btBulletSerializedArrays()
- {
- }
- btAlignedObjectArray<struct btQuantizedBvhDoubleData*> m_bvhsDouble;
- btAlignedObjectArray<struct btQuantizedBvhFloatData*> m_bvhsFloat;
- btAlignedObjectArray<struct btCollisionShapeData*> m_colShapeData;
- btAlignedObjectArray<struct btDynamicsWorldDoubleData*> m_dynamicWorldInfoDataDouble;
- btAlignedObjectArray<struct btDynamicsWorldFloatData*> m_dynamicWorldInfoDataFloat;
- btAlignedObjectArray<struct btRigidBodyDoubleData*> m_rigidBodyDataDouble;
- btAlignedObjectArray<struct btRigidBodyFloatData*> m_rigidBodyDataFloat;
- btAlignedObjectArray<struct btCollisionObjectDoubleData*> m_collisionObjectDataDouble;
- btAlignedObjectArray<struct btCollisionObjectFloatData*> m_collisionObjectDataFloat;
- btAlignedObjectArray<struct btTypedConstraintFloatData*> m_constraintDataFloat;
- btAlignedObjectArray<struct btTypedConstraintDoubleData*> m_constraintDataDouble;
- btAlignedObjectArray<struct btTypedConstraintData*> m_constraintData; //for backwards compatibility
- btAlignedObjectArray<struct btSoftBodyFloatData*> m_softBodyFloatData;
- btAlignedObjectArray<struct btSoftBodyDoubleData*> m_softBodyDoubleData;
-};
-
-///The btDefaultSerializer is the main Bullet serialization class.
-///The constructor takes an optional argument for backwards compatibility, it is recommended to leave this empty/zero.
-class btDefaultSerializer : public btSerializer
-{
-protected:
- btAlignedObjectArray<char*> mTypes;
- btAlignedObjectArray<short*> mStructs;
- btAlignedObjectArray<short> mTlens;
- btHashMap<btHashInt, int> mStructReverse;
- btHashMap<btHashString, int> mTypeLookup;
-
- btHashMap<btHashPtr, void*> m_chunkP;
-
- btHashMap<btHashPtr, const char*> m_nameMap;
-
- btHashMap<btHashPtr, btPointerUid> m_uniquePointers;
- int m_uniqueIdGenerator;
-
- int m_totalSize;
- unsigned char* m_buffer;
- bool m_ownsBuffer;
- int m_currentSize;
- void* m_dna;
- int m_dnaLength;
-
- int m_serializationFlags;
-
- btAlignedObjectArray<btChunk*> m_chunkPtrs;
-
-protected:
- virtual void* findPointer(void* oldPtr)
- {
- void** ptr = m_chunkP.find(oldPtr);
- if (ptr && *ptr)
- return *ptr;
- return 0;
- }
-
- virtual void writeDNA()
- {
- btChunk* dnaChunk = allocate(m_dnaLength, 1);
- memcpy(dnaChunk->m_oldPtr, m_dna, m_dnaLength);
- finalizeChunk(dnaChunk, "DNA1", BT_DNA_CODE, m_dna);
- }
-
- int getReverseType(const char* type) const
- {
- btHashString key(type);
- const int* valuePtr = mTypeLookup.find(key);
- if (valuePtr)
- return *valuePtr;
-
- return -1;
- }
-
- void initDNA(const char* bdnaOrg, int dnalen)
- {
- ///was already initialized
- if (m_dna)
- return;
-
- int littleEndian = 1;
- littleEndian = ((char*)&littleEndian)[0];
-
- m_dna = btAlignedAlloc(dnalen, 16);
- memcpy(m_dna, bdnaOrg, dnalen);
- m_dnaLength = dnalen;
-
- int* intPtr = 0;
- short* shtPtr = 0;
- char* cp = 0;
- int dataLen = 0;
- intPtr = (int*)m_dna;
-
- /*
- SDNA (4 bytes) (magic number)
- NAME (4 bytes)
- <nr> (4 bytes) amount of names (int)
- <string>
- <string>
- */
-
- if (strncmp((const char*)m_dna, "SDNA", 4) == 0)
- {
- // skip ++ NAME
- intPtr++;
- intPtr++;
- }
-
- // Parse names
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
-
- dataLen = *intPtr;
-
- intPtr++;
-
- cp = (char*)intPtr;
- int i;
- for (i = 0; i < dataLen; i++)
- {
- while (*cp) cp++;
- cp++;
- }
- cp = btAlignPointer(cp, 4);
-
- /*
- TYPE (4 bytes)
- <nr> amount of types (int)
- <string>
- <string>
- */
-
- intPtr = (int*)cp;
- btAssert(strncmp(cp, "TYPE", 4) == 0);
- intPtr++;
-
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
-
- dataLen = *intPtr;
- intPtr++;
-
- cp = (char*)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mTypes.push_back(cp);
- while (*cp) cp++;
- cp++;
- }
-
- cp = btAlignPointer(cp, 4);
-
- /*
- TLEN (4 bytes)
- <len> (short) the lengths of types
- <len>
- */
-
- // Parse type lens
- intPtr = (int*)cp;
- btAssert(strncmp(cp, "TLEN", 4) == 0);
- intPtr++;
-
- dataLen = (int)mTypes.size();
-
- shtPtr = (short*)intPtr;
- for (i = 0; i < dataLen; i++, shtPtr++)
- {
- if (!littleEndian)
- shtPtr[0] = btSwapEndian(shtPtr[0]);
- mTlens.push_back(shtPtr[0]);
- }
-
- if (dataLen & 1) shtPtr++;
-
- /*
- STRC (4 bytes)
- <nr> amount of structs (int)
- <typenr>
- <nr_of_elems>
- <typenr>
- <namenr>
- <typenr>
- <namenr>
- */
-
- intPtr = (int*)shtPtr;
- cp = (char*)intPtr;
- btAssert(strncmp(cp, "STRC", 4) == 0);
- intPtr++;
-
- if (!littleEndian)
- *intPtr = btSwapEndian(*intPtr);
- dataLen = *intPtr;
- intPtr++;
-
- shtPtr = (short*)intPtr;
- for (i = 0; i < dataLen; i++)
- {
- mStructs.push_back(shtPtr);
-
- if (!littleEndian)
- {
- shtPtr[0] = btSwapEndian(shtPtr[0]);
- shtPtr[1] = btSwapEndian(shtPtr[1]);
-
- int len = shtPtr[1];
- shtPtr += 2;
-
- for (int a = 0; a < len; a++, shtPtr += 2)
- {
- shtPtr[0] = btSwapEndian(shtPtr[0]);
- shtPtr[1] = btSwapEndian(shtPtr[1]);
- }
- }
- else
- {
- shtPtr += (2 * shtPtr[1]) + 2;
- }
- }
-
- // build reverse lookups
- for (i = 0; i < (int)mStructs.size(); i++)
- {
- short* strc = mStructs.at(i);
- mStructReverse.insert(strc[0], i);
- mTypeLookup.insert(btHashString(mTypes[strc[0]]), i);
- }
- }
-
-public:
- btHashMap<btHashPtr, void*> m_skipPointers;
-
- btDefaultSerializer(int totalSize = 0, unsigned char* buffer = 0)
- : m_uniqueIdGenerator(0),
- m_totalSize(totalSize),
- m_currentSize(0),
- m_dna(0),
- m_dnaLength(0),
- m_serializationFlags(0)
- {
- if (buffer == 0)
- {
- m_buffer = m_totalSize ? (unsigned char*)btAlignedAlloc(totalSize, 16) : 0;
- m_ownsBuffer = true;
- }
- else
- {
- m_buffer = buffer;
- m_ownsBuffer = false;
- }
-
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
-#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
-#if _WIN64
- initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
-#else
- btAssert(0);
-#endif
- }
- else
- {
-#ifndef _WIN64
- initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
-#else
- btAssert(0);
-#endif
- }
-
-#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- if (VOID_IS_8)
- {
- initDNA((const char*)sBulletDNAstr64, sBulletDNAlen64);
- }
- else
- {
- initDNA((const char*)sBulletDNAstr, sBulletDNAlen);
- }
-#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
- }
-
- virtual ~btDefaultSerializer()
- {
- if (m_buffer && m_ownsBuffer)
- btAlignedFree(m_buffer);
- if (m_dna)
- btAlignedFree(m_dna);
- }
-
- static int getMemoryDnaSizeInBytes()
- {
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
-
- if (VOID_IS_8)
- {
- return sBulletDNAlen64;
- }
- return sBulletDNAlen;
- }
- static const char* getMemoryDna()
- {
- const bool VOID_IS_8 = ((sizeof(void*) == 8));
- if (VOID_IS_8)
- {
- return (const char*)sBulletDNAstr64;
- }
- return (const char*)sBulletDNAstr;
- }
-
- void insertHeader()
- {
- writeHeader(m_buffer);
- m_currentSize += BT_HEADER_LENGTH;
- }
-
- void writeHeader(unsigned char* buffer) const
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- memcpy(buffer, "BULLETd", 7);
-#else
- memcpy(buffer, "BULLETf", 7);
-#endif //BT_USE_DOUBLE_PRECISION
-
- int littleEndian = 1;
- littleEndian = ((char*)&littleEndian)[0];
-
- if (sizeof(void*) == 8)
- {
- buffer[7] = '-';
- }
- else
- {
- buffer[7] = '_';
- }
-
- if (littleEndian)
- {
- buffer[8] = 'v';
- }
- else
- {
- buffer[8] = 'V';
- }
-
- buffer[9] = '3';
- buffer[10] = '1';
- buffer[11] = '7';
- }
-
- virtual void startSerialization()
- {
- m_uniqueIdGenerator = 1;
- if (m_totalSize)
- {
- unsigned char* buffer = internalAlloc(BT_HEADER_LENGTH);
- writeHeader(buffer);
- }
- }
-
- virtual void finishSerialization()
- {
- writeDNA();
-
- //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
- if (!m_totalSize)
- {
- if (m_buffer)
- btAlignedFree(m_buffer);
-
- m_currentSize += BT_HEADER_LENGTH;
- m_buffer = (unsigned char*)btAlignedAlloc(m_currentSize, 16);
-
- unsigned char* currentPtr = m_buffer;
- writeHeader(m_buffer);
- currentPtr += BT_HEADER_LENGTH;
- for (int i = 0; i < m_chunkPtrs.size(); i++)
- {
- int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length;
- memcpy(currentPtr, m_chunkPtrs[i], curLength);
- btAlignedFree(m_chunkPtrs[i]);
- currentPtr += curLength;
- }
- }
-
- mTypes.clear();
- mStructs.clear();
- mTlens.clear();
- mStructReverse.clear();
- mTypeLookup.clear();
- m_skipPointers.clear();
- m_chunkP.clear();
- m_nameMap.clear();
- m_uniquePointers.clear();
- m_chunkPtrs.clear();
- }
-
- virtual void* getUniquePointer(void* oldPtr)
- {
- btAssert(m_uniqueIdGenerator >= 0);
- if (!oldPtr)
- return 0;
-
- btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
- if (uptr)
- {
- return uptr->m_ptr;
- }
-
- void** ptr2 = m_skipPointers[oldPtr];
- if (ptr2)
- {
- return 0;
- }
-
- m_uniqueIdGenerator++;
-
- btPointerUid uid;
- uid.m_uniqueIds[0] = m_uniqueIdGenerator;
- uid.m_uniqueIds[1] = m_uniqueIdGenerator;
- m_uniquePointers.insert(oldPtr, uid);
- return uid.m_ptr;
- }
-
- virtual const unsigned char* getBufferPointer() const
- {
- return m_buffer;
- }
-
- virtual int getCurrentBufferSize() const
- {
- return m_currentSize;
- }
-
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
- {
- if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- btAssert(!findPointer(oldPtr));
- }
-
- chunk->m_dna_nr = getReverseType(structType);
-
- chunk->m_chunkCode = chunkCode;
-
- void* uniquePtr = getUniquePointer(oldPtr);
-
- m_chunkP.insert(oldPtr, uniquePtr); //chunk->m_oldPtr);
- chunk->m_oldPtr = uniquePtr; //oldPtr;
- }
-
- virtual unsigned char* internalAlloc(size_t size)
- {
- unsigned char* ptr = 0;
-
- if (m_totalSize)
- {
- ptr = m_buffer + m_currentSize;
- m_currentSize += int(size);
- btAssert(m_currentSize < m_totalSize);
- }
- else
- {
- ptr = (unsigned char*)btAlignedAlloc(size, 16);
- m_currentSize += int(size);
- }
- return ptr;
- }
-
- virtual btChunk* allocate(size_t size, int numElements)
- {
- unsigned char* ptr = internalAlloc(int(size) * numElements + sizeof(btChunk));
-
- unsigned char* data = ptr + sizeof(btChunk);
-
- btChunk* chunk = (btChunk*)ptr;
- chunk->m_chunkCode = 0;
- chunk->m_oldPtr = data;
- chunk->m_length = int(size) * numElements;
- chunk->m_number = numElements;
-
- m_chunkPtrs.push_back(chunk);
-
- return chunk;
- }
-
- virtual const char* findNameForPointer(const void* ptr) const
- {
- const char* const* namePtr = m_nameMap.find(ptr);
- if (namePtr && *namePtr)
- return *namePtr;
- return 0;
- }
-
- virtual void registerNameForPointer(const void* ptr, const char* name)
- {
- m_nameMap.insert(ptr, name);
- }
-
- virtual void serializeName(const char* name)
- {
- if (name)
- {
- //don't serialize name twice
- if (findPointer((void*)name))
- return;
-
- int len = btStrLen(name);
- if (len)
- {
- int newLen = len + 1;
- int padding = ((newLen + 3) & ~3) - newLen;
- newLen += padding;
-
- //serialize name string now
- btChunk* chunk = allocate(sizeof(char), newLen);
- char* destinationName = (char*)chunk->m_oldPtr;
- for (int i = 0; i < len; i++)
- {
- destinationName[i] = name[i];
- }
- destinationName[len] = 0;
- finalizeChunk(chunk, "char", BT_ARRAY_CODE, (void*)name);
- }
- }
- }
-
- virtual int getSerializationFlags() const
- {
- return m_serializationFlags;
- }
-
- virtual void setSerializationFlags(int flags)
- {
- m_serializationFlags = flags;
- }
- int getNumChunks() const
- {
- return m_chunkPtrs.size();
- }
-
- const btChunk* getChunk(int chunkIndex) const
- {
- return m_chunkPtrs[chunkIndex];
- }
-};
-
-///In general it is best to use btDefaultSerializer,
-///in particular when writing the data to disk or sending it over the network.
-///The btInMemorySerializer is experimental and only suitable in a few cases.
-///The btInMemorySerializer takes a shortcut and can be useful to create a deep-copy
-///of objects. There will be a demo on how to use the btInMemorySerializer.
-#ifdef ENABLE_INMEMORY_SERIALIZER
-
-struct btInMemorySerializer : public btDefaultSerializer
-{
- btHashMap<btHashPtr, btChunk*> m_uid2ChunkPtr;
- btHashMap<btHashPtr, void*> m_orgPtr2UniqueDataPtr;
- btHashMap<btHashString, const void*> m_names2Ptr;
-
- btBulletSerializedArrays m_arrays;
-
- btInMemorySerializer(int totalSize = 0, unsigned char* buffer = 0)
- : btDefaultSerializer(totalSize, buffer)
- {
- }
-
- virtual void startSerialization()
- {
- m_uid2ChunkPtr.clear();
- //todo: m_arrays.clear();
- btDefaultSerializer::startSerialization();
- }
-
- btChunk* findChunkFromUniquePointer(void* uniquePointer)
- {
- btChunk** chkPtr = m_uid2ChunkPtr[uniquePointer];
- if (chkPtr)
- {
- return *chkPtr;
- }
- return 0;
- }
-
- virtual void registerNameForPointer(const void* ptr, const char* name)
- {
- btDefaultSerializer::registerNameForPointer(ptr, name);
- m_names2Ptr.insert(name, ptr);
- }
-
- virtual void finishSerialization()
- {
- }
-
- virtual void* getUniquePointer(void* oldPtr)
- {
- if (oldPtr == 0)
- return 0;
-
- // void* uniquePtr = getUniquePointer(oldPtr);
- btChunk* chunk = findChunkFromUniquePointer(oldPtr);
- if (chunk)
- {
- return chunk->m_oldPtr;
- }
- else
- {
- const char* n = (const char*)oldPtr;
- const void** ptr = m_names2Ptr[n];
- if (ptr)
- {
- return oldPtr;
- }
- else
- {
- void** ptr2 = m_skipPointers[oldPtr];
- if (ptr2)
- {
- return 0;
- }
- else
- {
- //If this assert hit, serialization happened in the wrong order
- // 'getUniquePointer'
- btAssert(0);
- }
- }
- return 0;
- }
- return oldPtr;
- }
-
- virtual void finalizeChunk(btChunk* chunk, const char* structType, int chunkCode, void* oldPtr)
- {
- if (!(m_serializationFlags & BT_SERIALIZE_NO_DUPLICATE_ASSERT))
- {
- btAssert(!findPointer(oldPtr));
- }
-
- chunk->m_dna_nr = getReverseType(structType);
- chunk->m_chunkCode = chunkCode;
- //void* uniquePtr = getUniquePointer(oldPtr);
- m_chunkP.insert(oldPtr, oldPtr); //chunk->m_oldPtr);
- // chunk->m_oldPtr = uniquePtr;//oldPtr;
-
- void* uid = findPointer(oldPtr);
- m_uid2ChunkPtr.insert(uid, chunk);
-
- switch (chunk->m_chunkCode)
- {
- case BT_SOFTBODY_CODE:
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_softBodyDoubleData.push_back((btSoftBodyDoubleData*)chunk->m_oldPtr);
-#else
- m_arrays.m_softBodyFloatData.push_back((btSoftBodyFloatData*)chunk->m_oldPtr);
-#endif
- break;
- }
- case BT_COLLISIONOBJECT_CODE:
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_collisionObjectDataDouble.push_back((btCollisionObjectDoubleData*)chunk->m_oldPtr);
-#else //BT_USE_DOUBLE_PRECISION
- m_arrays.m_collisionObjectDataFloat.push_back((btCollisionObjectFloatData*)chunk->m_oldPtr);
-#endif //BT_USE_DOUBLE_PRECISION
- break;
- }
- case BT_RIGIDBODY_CODE:
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_rigidBodyDataDouble.push_back((btRigidBodyDoubleData*)chunk->m_oldPtr);
-#else
- m_arrays.m_rigidBodyDataFloat.push_back((btRigidBodyFloatData*)chunk->m_oldPtr);
-#endif //BT_USE_DOUBLE_PRECISION
- break;
- };
- case BT_CONSTRAINT_CODE:
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_constraintDataDouble.push_back((btTypedConstraintDoubleData*)chunk->m_oldPtr);
-#else
- m_arrays.m_constraintDataFloat.push_back((btTypedConstraintFloatData*)chunk->m_oldPtr);
-#endif
- break;
- }
- case BT_QUANTIZED_BVH_CODE:
- {
-#ifdef BT_USE_DOUBLE_PRECISION
- m_arrays.m_bvhsDouble.push_back((btQuantizedBvhDoubleData*)chunk->m_oldPtr);
-#else
- m_arrays.m_bvhsFloat.push_back((btQuantizedBvhFloatData*)chunk->m_oldPtr);
-#endif
- break;
- }
-
- case BT_SHAPE_CODE:
- {
- btCollisionShapeData* shapeData = (btCollisionShapeData*)chunk->m_oldPtr;
- m_arrays.m_colShapeData.push_back(shapeData);
- break;
- }
- case BT_TRIANLGE_INFO_MAP:
- case BT_ARRAY_CODE:
- case BT_SBMATERIAL_CODE:
- case BT_SBNODE_CODE:
- case BT_DYNAMICSWORLD_CODE:
- case BT_DNA_CODE:
- {
- break;
- }
- default:
- {
- }
- };
- }
-
- int getNumChunks() const
- {
- return m_uid2ChunkPtr.size();
- }
-
- const btChunk* getChunk(int chunkIndex) const
- {
- return *m_uid2ChunkPtr.getAtIndex(chunkIndex);
- }
-};
-#endif //ENABLE_INMEMORY_SERIALIZER
-
-#endif //BT_SERIALIZER_H
diff --git a/thirdparty/bullet/LinearMath/btSerializer64.cpp b/thirdparty/bullet/LinearMath/btSerializer64.cpp
deleted file mode 100644
index 6c4bc7031f..0000000000
--- a/thirdparty/bullet/LinearMath/btSerializer64.cpp
+++ /dev/null
@@ -1,692 +0,0 @@
-char sBulletDNAstr64[]= {
-char(83),char(68),char(78),char(65),char(78),char(65),char(77),char(69),char(-74),char(1),char(0),char(0),char(109),char(95),char(115),char(105),char(122),char(101),char(0),char(109),
-char(95),char(99),char(97),char(112),char(97),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(100),char(97),char(116),char(97),char(0),char(109),char(95),
-char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(115),char(0),char(109),char(95),char(99),char(111),
-char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(115),char(0),char(42),char(102),char(105),char(114),char(115),char(116),char(0),char(42),char(108),char(97),char(115),
-char(116),char(0),char(109),char(95),char(102),char(108),char(111),char(97),char(116),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(108),char(91),char(51),
-char(93),char(0),char(109),char(95),char(98),char(97),char(115),char(105),char(115),char(0),char(109),char(95),char(111),char(114),char(105),char(103),char(105),char(110),char(0),char(109),
-char(95),char(114),char(111),char(111),char(116),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),
-char(116),char(114),char(101),char(101),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),
-char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(91),char(51),char(93),char(0),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(65),char(97),char(98),char(98),char(77),char(97),char(120),char(91),char(51),char(93),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),
-char(105),char(110),char(79),char(114),char(103),char(0),char(109),char(95),char(97),char(97),char(98),char(98),char(77),char(97),char(120),char(79),char(114),char(103),char(0),char(109),
-char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(115),char(117),char(98),char(80),char(97),
-char(114),char(116),char(0),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),
-char(95),char(112),char(97),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(101),char(115),char(99),char(97),char(112),char(101),char(73),char(110),char(100),char(101),
-char(120),char(79),char(114),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(98),
-char(118),char(104),char(65),char(97),char(98),char(98),char(77),char(105),char(110),char(0),char(109),char(95),char(98),char(118),char(104),char(65),char(97),char(98),char(98),char(77),
-char(97),char(120),char(0),char(109),char(95),char(98),char(118),char(104),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),
-char(0),char(109),char(95),char(99),char(117),char(114),char(78),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),char(117),char(115),
-char(101),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(110),char(117),char(109),char(67),
-char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(76),char(101),char(97),char(102),char(78),char(111),char(100),char(101),char(115),char(0),char(109),
-char(95),char(110),char(117),char(109),char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),
-char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(99),char(111),char(110),char(116),char(105),char(103),char(117),char(111),
-char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),
-char(122),char(101),char(100),char(67),char(111),char(110),char(116),char(105),char(103),char(117),char(111),char(117),char(115),char(78),char(111),char(100),char(101),char(115),char(80),char(116),
-char(114),char(0),char(42),char(109),char(95),char(115),char(117),char(98),char(84),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(80),char(116),char(114),char(0),
-char(109),char(95),char(116),char(114),char(97),char(118),char(101),char(114),char(115),char(97),char(108),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(110),char(117),
-char(109),char(83),char(117),char(98),char(116),char(114),char(101),char(101),char(72),char(101),char(97),char(100),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(110),
-char(97),char(109),char(101),char(0),char(109),char(95),char(115),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(112),char(97),
-char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(83),char(99),char(97),
-char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(108),char(97),char(110),char(101),char(78),char(111),char(114),char(109),char(97),char(108),char(0),char(109),
-char(95),char(112),char(108),char(97),char(110),char(101),char(67),char(111),char(110),char(115),char(116),char(97),char(110),char(116),char(0),char(109),char(95),char(105),char(109),char(112),
-char(108),char(105),char(99),char(105),char(116),char(83),char(104),char(97),char(112),char(101),char(68),char(105),char(109),char(101),char(110),char(115),char(105),char(111),char(110),char(115),
-char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(109),
-char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(0),char(109),char(95),char(112),char(111),char(115),char(0),char(109),char(95),char(114),char(97),char(100),
-char(105),char(117),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),char(110),char(97),char(108),
-char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(42),char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(80),char(111),
-char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),char(108),char(111),char(99),
-char(97),char(108),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(65),char(114),char(114),char(97),char(121),char(83),char(105),char(122),char(101),char(0),
-char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(0),char(109),char(95),char(112),char(97),char(100),char(91),char(50),char(93),char(0),char(109),char(95),char(118),
-char(97),char(108),char(117),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(112),char(97),char(100),char(0),char(42),char(109),char(95),char(118),char(101),
-char(114),char(116),char(105),char(99),char(101),char(115),char(51),char(102),char(0),char(42),char(109),char(95),char(118),char(101),char(114),char(116),char(105),char(99),char(101),char(115),
-char(51),char(100),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(51),char(50),char(0),char(42),char(109),char(95),char(51),
-char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(42),char(109),char(95),char(51),char(105),char(110),char(100),char(105),char(99),char(101),
-char(115),char(56),char(0),char(42),char(109),char(95),char(105),char(110),char(100),char(105),char(99),char(101),char(115),char(49),char(54),char(0),char(109),char(95),char(110),char(117),
-char(109),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(101),char(114),char(116),
-char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(115),char(80),char(116),char(114),
-char(0),char(109),char(95),char(115),char(99),char(97),char(108),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(101),char(115),char(104),
-char(80),char(97),char(114),char(116),char(115),char(0),char(109),char(95),char(109),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),
-char(101),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(70),char(108),char(111),char(97),char(116),char(66),
-char(118),char(104),char(0),char(42),char(109),char(95),char(113),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(68),char(111),char(117),char(98),char(108),
-char(101),char(66),char(118),char(104),char(0),char(42),char(109),char(95),char(116),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),
-char(77),char(97),char(112),char(0),char(109),char(95),char(112),char(97),char(100),char(51),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(114),char(105),char(109),
-char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(116),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(0),char(109),
-char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),char(97),char(112),char(101),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),
-char(105),char(108),char(100),char(77),char(97),char(114),char(103),char(105),char(110),char(0),char(42),char(109),char(95),char(99),char(104),char(105),char(108),char(100),char(83),char(104),
-char(97),char(112),char(101),char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(104),char(105),char(108),char(100),char(83),char(104),char(97),
-char(112),char(101),char(115),char(0),char(109),char(95),char(117),char(112),char(65),char(120),char(105),char(115),char(0),char(109),char(95),char(117),char(112),char(73),char(110),char(100),
-char(101),char(120),char(0),char(109),char(95),char(102),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(48),char(86),
-char(49),char(65),char(110),char(103),char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(49),char(86),char(50),char(65),char(110),char(103),
-char(108),char(101),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(86),char(50),char(86),char(48),char(65),char(110),char(103),char(108),char(101),char(0),char(42),
-char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(110),char(101),
-char(120),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),char(118),char(97),char(108),char(117),char(101),char(65),char(114),char(114),char(97),char(121),char(80),
-char(116),char(114),char(0),char(42),char(109),char(95),char(107),char(101),char(121),char(65),char(114),char(114),char(97),char(121),char(80),char(116),char(114),char(0),char(109),char(95),
-char(99),char(111),char(110),char(118),char(101),char(120),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(112),char(108),char(97),char(110),
-char(97),char(114),char(69),char(112),char(115),char(105),char(108),char(111),char(110),char(0),char(109),char(95),char(101),char(113),char(117),char(97),char(108),char(86),char(101),char(114),
-char(116),char(101),char(120),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(101),char(100),char(103),char(101),char(68),
-char(105),char(115),char(116),char(97),char(110),char(99),char(101),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(122),
-char(101),char(114),char(111),char(65),char(114),char(101),char(97),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(110),
-char(101),char(120),char(116),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(104),char(97),char(115),char(104),char(84),char(97),char(98),char(108),char(101),char(83),
-char(105),char(122),char(101),char(0),char(109),char(95),char(110),char(117),char(109),char(86),char(97),char(108),char(117),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(75),char(101),char(121),char(115),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(111),
-char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(76),char(111),char(99),char(97),char(108),char(80),char(111),char(105),char(110),char(116),char(66),char(91),char(52),char(93),char(0),
-char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),
-char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(65),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(78),char(111),char(114),char(109),
-char(97),char(108),char(87),char(111),char(114),char(108),char(100),char(79),char(110),char(66),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),
-char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
-char(110),char(68),char(105),char(114),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),
-char(101),char(76),char(97),char(116),char(101),char(114),char(97),char(108),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(68),char(105),char(114),char(50),
-char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(68),char(105),char(115),char(116),
-char(97),char(110),char(99),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
-char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),char(114),char(101),char(118),char(82),char(72),char(83),char(91),char(52),char(93),
-char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),
-char(100),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(111),char(108),char(108),char(105),char(110),char(103),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(83),char(112),char(105),char(110),char(110),char(105),char(110),char(103),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),
-char(105),char(111),char(110),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(80),
-char(97),char(114),char(116),char(73),char(100),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(80),char(97),char(114),char(116),char(73),char(100),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),
-char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(73),char(110),char(100),char(101),char(120),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),
-char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(111),char(105),char(110),
-char(116),char(70),char(108),char(97),char(103),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),
-char(104),char(101),char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),
-char(114),char(97),char(108),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),
-char(65),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(76),char(97),char(116),char(101),char(114),char(97),
-char(108),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),char(110),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),
-char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(77),char(111),char(116),char(105),char(111),
-char(110),char(50),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(67),char(70),char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),
-char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(49),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),
-char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(69),char(82),char(80),char(91),char(52),char(93),char(0),char(109),
-char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(67),char(111),char(109),char(98),char(105),char(110),char(101),char(100),char(67),
-char(111),char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),char(95),
-char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(67),char(70),
-char(77),char(91),char(52),char(93),char(0),char(109),char(95),char(112),char(111),char(105),char(110),char(116),char(67),char(97),char(99),char(104),char(101),char(76),char(105),char(102),
-char(101),char(84),char(105),char(109),char(101),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(97),char(99),char(104),char(101),char(100),
-char(80),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),
-char(65),char(0),char(109),char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(66),char(0),char(109),char(95),char(105),
-char(110),char(100),char(101),char(120),char(49),char(97),char(0),char(109),char(95),char(111),char(98),char(106),char(101),char(99),char(116),char(84),char(121),char(112),char(101),char(0),
-char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(66),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),char(99),char(116),char(80),char(114),char(111),char(99),
-char(101),char(115),char(115),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(42),char(109),char(95),char(98),
-char(111),char(100),char(121),char(48),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(49),char(0),char(109),char(95),char(103),char(105),char(109),char(112),
-char(97),char(99),char(116),char(83),char(117),char(98),char(84),char(121),char(112),char(101),char(0),char(42),char(109),char(95),char(117),char(110),char(115),char(99),char(97),char(108),
-char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(70),char(108),char(111),char(97),char(116),char(80),char(116),char(114),char(0),char(42),char(109),char(95),
-char(117),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),char(110),char(116),char(115),char(68),char(111),char(117),char(98),char(108),char(101),
-char(80),char(116),char(114),char(0),char(109),char(95),char(110),char(117),char(109),char(85),char(110),char(115),char(99),char(97),char(108),char(101),char(100),char(80),char(111),char(105),
-char(110),char(116),char(115),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(51),char(91),char(52),char(93),char(0),char(42),char(109),
-char(95),char(98),char(114),char(111),char(97),char(100),char(112),char(104),char(97),char(115),char(101),char(72),char(97),char(110),char(100),char(108),char(101),char(0),char(42),char(109),
-char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(42),char(109),char(95),char(114),
-char(111),char(111),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(0),char(109),char(95),
-char(119),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),
-char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(87),char(111),char(114),char(108),char(100),char(84),char(114),char(97),char(110),char(115),
-char(102),char(111),char(114),char(109),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),
-char(76),char(105),char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(105),char(110),char(116),
-char(101),char(114),char(112),char(111),char(108),char(97),char(116),char(105),char(111),char(110),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),
-char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),char(70),
-char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(100),char(101),char(97),char(99),char(116),char(105),char(118),char(97),char(116),char(105),
-char(111),char(110),char(84),char(105),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),
-char(114),char(111),char(108),char(108),char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),
-char(110),char(116),char(97),char(99),char(116),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(99),char(111),char(110),char(116),char(97),
-char(99),char(116),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(116),
-char(117),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(104),char(105),char(116),char(70),char(114),char(97),char(99),char(116),char(105),char(111),char(110),char(0),
-char(109),char(95),char(99),char(99),char(100),char(83),char(119),char(101),char(112),char(116),char(83),char(112),char(104),char(101),char(114),char(101),char(82),char(97),char(100),char(105),
-char(117),char(115),char(0),char(109),char(95),char(99),char(99),char(100),char(77),char(111),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),
-char(111),char(108),char(100),char(0),char(109),char(95),char(104),char(97),char(115),char(65),char(110),char(105),char(115),char(111),char(116),char(114),char(111),char(112),char(105),char(99),
-char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(70),char(108),char(97),char(103),char(115),char(0),char(109),char(95),char(105),char(115),char(108),char(97),char(110),char(100),char(84),char(97),char(103),char(49),char(0),char(109),
-char(95),char(99),char(111),char(109),char(112),char(97),char(110),char(105),char(111),char(110),char(73),char(100),char(0),char(109),char(95),char(97),char(99),char(116),char(105),char(118),
-char(97),char(116),char(105),char(111),char(110),char(83),char(116),char(97),char(116),char(101),char(49),char(0),char(109),char(95),char(105),char(110),char(116),char(101),char(114),char(110),
-char(97),char(108),char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(99),char(104),char(101),char(99),char(107),char(67),char(111),char(108),char(108),char(105),char(100),
-char(101),char(87),char(105),char(116),char(104),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(70),char(105),char(108),
-char(116),char(101),char(114),char(71),char(114),char(111),char(117),char(112),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),
-char(70),char(105),char(108),char(116),char(101),char(114),char(77),char(97),char(115),char(107),char(0),char(109),char(95),char(117),char(110),char(105),char(113),char(117),char(101),char(73),
-char(100),char(0),char(109),char(95),char(116),char(97),char(117),char(0),char(109),char(95),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
-char(116),char(105),char(109),char(101),char(83),char(116),char(101),char(112),char(0),char(109),char(95),char(109),char(97),char(120),char(69),char(114),char(114),char(111),char(114),char(82),
-char(101),char(100),char(117),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(115),char(111),char(114),char(0),char(109),char(95),char(101),char(114),char(112),
-char(0),char(109),char(95),char(101),char(114),char(112),char(50),char(0),char(109),char(95),char(103),char(108),char(111),char(98),char(97),char(108),char(67),char(102),char(109),char(0),
-char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(80),char(101),char(110),char(101),char(116),char(114),
-char(97),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(115),char(112),char(108),
-char(105),char(116),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(117),char(114),char(110),char(69),char(114),char(112),char(0),char(109),char(95),char(108),
-char(105),char(110),char(101),char(97),char(114),char(83),char(108),char(111),char(112),char(0),char(109),char(95),char(119),char(97),char(114),char(109),char(115),char(116),char(97),char(114),
-char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(97),char(114),char(116),char(105),char(99),char(117),char(108),
-char(97),char(116),char(101),char(100),char(87),char(97),char(114),char(109),char(115),char(116),char(97),char(114),char(116),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
-char(111),char(114),char(0),char(109),char(95),char(109),char(97),char(120),char(71),char(121),char(114),char(111),char(115),char(99),char(111),char(112),char(105),char(99),char(70),char(111),
-char(114),char(99),char(101),char(0),char(109),char(95),char(115),char(105),char(110),char(103),char(108),char(101),char(65),char(120),char(105),char(115),char(82),char(111),char(108),char(108),
-char(105),char(110),char(103),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),
-char(0),char(109),char(95),char(110),char(117),char(109),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(115),
-char(111),char(108),char(118),char(101),char(114),char(77),char(111),char(100),char(101),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(105),char(110),char(103),char(67),
-char(111),char(110),char(116),char(97),char(99),char(116),char(82),char(101),char(115),char(116),char(105),char(116),char(117),char(116),char(105),char(111),char(110),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(109),char(105),char(110),char(105),char(109),char(117),char(109),char(83),char(111),char(108),char(118),
-char(101),char(114),char(66),char(97),char(116),char(99),char(104),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(0),
-char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),
-char(114),char(116),char(105),char(97),char(84),char(101),char(110),char(115),char(111),char(114),char(87),char(111),char(114),char(108),char(100),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),
-char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(70),char(97),char(99),char(116),char(111),
-char(114),char(0),char(109),char(95),char(103),char(114),char(97),char(118),char(105),char(116),char(121),char(95),char(97),char(99),char(99),char(101),char(108),char(101),char(114),char(97),
-char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(105),char(110),char(118),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(76),char(111),char(99),
-char(97),char(108),char(0),char(109),char(95),char(116),char(111),char(116),char(97),char(108),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(116),char(111),
-char(116),char(97),char(108),char(84),char(111),char(114),char(113),char(117),char(101),char(0),char(109),char(95),char(105),char(110),char(118),char(101),char(114),char(115),char(101),char(77),
-char(97),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),
-char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(97),
-char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),
-char(111),char(114),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(76),char(105),char(110),char(101),char(97),
-char(114),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),
-char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),
-char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(83),char(113),char(114),char(0),
-char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(65),char(110),char(103),char(117),char(108),char(97),char(114),char(68),
-char(97),char(109),char(112),char(105),char(110),char(103),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),
-char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),
-char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(108),char(101),char(101),char(112),char(105),char(110),char(103),char(84),char(104),char(114),char(101),
-char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(97),char(100),char(100),char(105),char(116),char(105),char(111),char(110),char(97),char(108),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(82),char(111),char(119),char(115),char(0),char(110),char(117),char(98),char(0),char(42),char(109),char(95),char(114),char(98),char(65),char(0),char(42),char(109),char(95),
-char(114),char(98),char(66),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(84),char(121),char(112),char(101),char(0),char(109),char(95),char(117),char(115),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(73),char(100),char(0),char(109),char(95),char(110),char(101),char(101),char(100),char(115),char(70),char(101),char(101),char(100),char(98),char(97),char(99),char(107),char(0),
-char(109),char(95),char(97),char(112),char(112),char(108),char(105),char(101),char(100),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(100),
-char(98),char(103),char(68),char(114),char(97),char(119),char(83),char(105),char(122),char(101),char(0),char(109),char(95),char(100),char(105),char(115),char(97),char(98),char(108),char(101),
-char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(115),char(66),char(101),char(116),char(119),char(101),char(101),char(110),char(76),char(105),char(110),
-char(107),char(101),char(100),char(66),char(111),char(100),char(105),char(101),char(115),char(0),char(109),char(95),char(111),char(118),char(101),char(114),char(114),char(105),char(100),char(101),
-char(78),char(117),char(109),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),
-char(109),char(95),char(98),char(114),char(101),char(97),char(107),char(105),char(110),char(103),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(84),char(104),char(114),
-char(101),char(115),char(104),char(111),char(108),char(100),char(0),char(109),char(95),char(105),char(115),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(0),char(112),
-char(97),char(100),char(100),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(116),char(121),char(112),char(101),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),
-char(65),char(0),char(109),char(95),char(112),char(105),char(118),char(111),char(116),char(73),char(110),char(66),char(0),char(109),char(95),char(114),char(98),char(65),char(70),char(114),
-char(97),char(109),char(101),char(0),char(109),char(95),char(114),char(98),char(66),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(117),char(115),char(101),
-char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),char(65),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(79),char(110),char(108),char(121),char(0),char(109),char(95),char(101),char(110),char(97),char(98),char(108),char(101),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(0),char(109),char(95),char(109),char(111),char(116),char(111),char(114),char(84),char(97),
-char(114),char(103),char(101),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(109),char(97),char(120),char(77),char(111),
-char(116),char(111),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(108),char(111),char(119),char(101),char(114),char(76),char(105),
-char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),
-char(105),char(109),char(105),char(116),char(83),char(111),char(102),char(116),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(98),char(105),char(97),char(115),char(70),
-char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(114),char(101),char(108),char(97),char(120),char(97),char(116),char(105),char(111),char(110),char(70),char(97),
-char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(112),char(97),char(100),char(100),char(105),char(110),char(103),char(49),char(91),char(52),char(93),char(0),char(109),
-char(95),char(115),char(119),char(105),char(110),char(103),char(83),char(112),char(97),char(110),char(49),char(0),char(109),char(95),char(115),char(119),char(105),char(110),char(103),char(83),
-char(112),char(97),char(110),char(50),char(0),char(109),char(95),char(116),char(119),char(105),char(115),char(116),char(83),char(112),char(97),char(110),char(0),char(109),char(95),char(108),
-char(105),char(110),char(101),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),char(117),char(115),char(101),
-char(76),char(105),char(110),char(101),char(97),char(114),char(82),char(101),char(102),char(101),char(114),char(101),char(110),char(99),char(101),char(70),char(114),char(97),char(109),char(101),
-char(65),char(0),char(109),char(95),char(117),char(115),char(101),char(79),char(102),char(102),char(115),char(101),char(116),char(70),char(111),char(114),char(67),char(111),char(110),char(115),
-char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(54),char(100),char(111),char(102),char(68),char(97),
-char(116),char(97),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(69),char(110),char(97),char(98),char(108),char(101),char(100),char(91),char(54),
-char(93),char(0),char(109),char(95),char(101),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
-char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),
-char(115),char(91),char(54),char(93),char(0),char(109),char(95),char(115),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),
-char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),
-char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),
-char(101),char(97),char(114),char(83),char(116),char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),
-char(111),char(116),char(111),char(114),char(69),char(82),char(80),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(111),char(116),char(111),
-char(114),char(67),char(70),char(77),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),
-char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(77),char(97),char(120),char(77),
-char(111),char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),
-char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(108),char(105),char(110),char(101),
-char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(105),
-char(110),char(101),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),char(105),char(110),char(116),
-char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),char(111),char(116),char(111),char(114),
-char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(101),char(114),char(118),char(111),char(77),char(111),char(116),
-char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),
-char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),
-char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
-char(91),char(52),char(93),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(66),char(111),char(117),char(110),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),
-char(114),char(83),char(116),char(111),char(112),char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),
-char(111),char(112),char(67),char(70),char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),
-char(69),char(82),char(80),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(111),char(116),char(111),char(114),char(67),char(70),
-char(77),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(84),char(97),char(114),char(103),char(101),char(116),char(86),char(101),char(108),
-char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(77),char(97),char(120),char(77),char(111),
-char(116),char(111),char(114),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),
-char(114),char(118),char(111),char(84),char(97),char(114),char(103),char(101),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),
-char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),
-char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),
-char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(113),char(117),char(105),char(108),char(105),char(98),char(114),char(105),char(117),char(109),char(80),char(111),
-char(105),char(110),char(116),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(69),char(110),char(97),char(98),char(108),char(101),char(77),
-char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(101),char(114),
-char(118),char(111),char(77),char(111),char(116),char(111),char(114),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(69),char(110),char(97),char(98),char(108),char(101),char(83),char(112),char(114),char(105),char(110),char(103),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),
-char(103),char(117),char(108),char(97),char(114),char(83),char(112),char(114),char(105),char(110),char(103),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
-char(76),char(105),char(109),char(105),char(116),char(101),char(100),char(91),char(52),char(93),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),
-char(83),char(112),char(114),char(105),char(110),char(103),char(68),char(97),char(109),char(112),char(105),char(110),char(103),char(76),char(105),char(109),char(105),char(116),char(101),char(100),
-char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(111),char(116),char(97),char(116),char(101),char(79),char(114),char(100),char(101),char(114),char(0),char(109),char(95),
-char(97),char(120),char(105),char(115),char(73),char(110),char(65),char(0),char(109),char(95),char(97),char(120),char(105),char(115),char(73),char(110),char(66),char(0),char(109),char(95),
-char(114),char(97),char(116),char(105),char(111),char(0),char(109),char(95),char(108),char(105),char(110),char(101),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),
-char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),char(103),char(117),char(108),char(97),char(114),char(83),char(116),char(105),char(102),char(102),char(110),char(101),
-char(115),char(115),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(83),char(116),char(105),char(102),char(102),char(110),char(101),char(115),char(115),
-char(0),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(0),char(109),char(95),char(112),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(114),char(101),char(118),char(105),char(111),char(117),char(115),char(80),char(111),char(115),char(105),char(116),char(105),
-char(111),char(110),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(97),char(99),char(99),char(117),
-char(109),char(117),char(108),char(97),char(116),char(101),char(100),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(110),char(111),char(114),char(109),char(97),
-char(108),char(0),char(109),char(95),char(97),char(114),char(101),char(97),char(0),char(109),char(95),char(97),char(116),char(116),char(97),char(99),char(104),char(0),char(109),char(95),
-char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(114),char(101),char(115),
-char(116),char(76),char(101),char(110),char(103),char(116),char(104),char(0),char(109),char(95),char(98),char(98),char(101),char(110),char(100),char(105),char(110),char(103),char(0),char(109),
-char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(51),char(93),char(0),char(109),char(95),char(114),char(101),
-char(115),char(116),char(65),char(114),char(101),char(97),char(0),char(109),char(95),char(99),char(48),char(91),char(52),char(93),char(0),char(109),char(95),char(110),char(111),char(100),
-char(101),char(73),char(110),char(100),char(105),char(99),char(101),char(115),char(91),char(52),char(93),char(0),char(109),char(95),char(114),char(101),char(115),char(116),char(86),char(111),
-char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(99),char(49),char(0),char(109),char(95),char(99),char(50),char(0),char(109),char(95),char(99),char(48),char(0),
-char(109),char(95),char(108),char(111),char(99),char(97),char(108),char(70),char(114),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(114),char(105),char(103),char(105),
-char(100),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),char(100),char(101),char(120),char(0),char(109),char(95),
-char(97),char(101),char(114),char(111),char(77),char(111),char(100),char(101),char(108),char(0),char(109),char(95),char(98),char(97),char(117),char(109),char(103),char(97),char(114),char(116),
-char(101),char(0),char(109),char(95),char(100),char(114),char(97),char(103),char(0),char(109),char(95),char(108),char(105),char(102),char(116),char(0),char(109),char(95),char(112),char(114),
-char(101),char(115),char(115),char(117),char(114),char(101),char(0),char(109),char(95),char(118),char(111),char(108),char(117),char(109),char(101),char(0),char(109),char(95),char(100),char(121),
-char(110),char(97),char(109),char(105),char(99),char(70),char(114),char(105),char(99),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(112),char(111),char(115),char(101),
-char(77),char(97),char(116),char(99),char(104),char(0),char(109),char(95),char(114),char(105),char(103),char(105),char(100),char(67),char(111),char(110),char(116),char(97),char(99),char(116),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(107),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(111),
-char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),
-char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(97),char(110),
-char(99),char(104),char(111),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(82),
-char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),
-char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),char(108),char(117),char(115),char(116),char(101),char(114),
-char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(72),char(97),char(114),char(100),char(110),char(101),char(115),char(115),char(0),char(109),char(95),char(115),char(111),char(102),
-char(116),char(82),char(105),char(103),char(105),char(100),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),
-char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(115),char(111),char(102),char(116),char(75),char(105),char(110),char(101),char(116),char(105),char(99),char(67),
-char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),
-char(95),char(115),char(111),char(102),char(116),char(83),char(111),char(102),char(116),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(109),char(112),char(117),
-char(108),char(115),char(101),char(83),char(112),char(108),char(105),char(116),char(0),char(109),char(95),char(109),char(97),char(120),char(86),char(111),char(108),char(117),char(109),char(101),
-char(0),char(109),char(95),char(116),char(105),char(109),char(101),char(83),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(118),char(101),char(108),char(111),char(99),
-char(105),char(116),char(121),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(112),char(111),char(115),char(105),
-char(116),char(105),char(111),char(110),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(100),char(114),char(105),
-char(102),char(116),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),
-char(101),char(114),char(73),char(116),char(101),char(114),char(97),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),char(114),char(111),char(116),char(0),char(109),
-char(95),char(115),char(99),char(97),char(108),char(101),char(0),char(109),char(95),char(97),char(113),char(113),char(0),char(109),char(95),char(99),char(111),char(109),char(0),char(42),
-char(109),char(95),char(112),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(42),char(109),char(95),char(119),char(101),char(105),char(103),char(104),
-char(116),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(80),char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(87),char(101),char(105),char(103),char(116),char(115),char(0),char(109),char(95),char(98),char(118),char(111),char(108),char(117),char(109),char(101),char(0),
-char(109),char(95),char(98),char(102),char(114),char(97),char(109),char(101),char(0),char(109),char(95),char(102),char(114),char(97),char(109),char(101),char(120),char(102),char(111),char(114),
-char(109),char(0),char(109),char(95),char(108),char(111),char(99),char(105),char(105),char(0),char(109),char(95),char(105),char(110),char(118),char(119),char(105),char(0),char(109),char(95),
-char(118),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(100),char(105),char(109),char(112),char(117),
-char(108),char(115),char(101),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(108),char(118),char(0),char(109),char(95),char(97),char(118),char(0),char(42),char(109),
-char(95),char(102),char(114),char(97),char(109),char(101),char(114),char(101),char(102),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(73),char(110),
-char(100),char(105),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(109),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(117),
-char(109),char(70),char(114),char(97),char(109),char(101),char(82),char(101),char(102),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(78),char(111),char(100),char(101),
-char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(77),char(97),char(115),char(115),char(101),char(115),char(0),char(109),char(95),char(105),char(100),char(109),char(97),
-char(115),char(115),char(0),char(109),char(95),char(105),char(109),char(97),char(115),char(115),char(0),char(109),char(95),char(110),char(118),char(105),char(109),char(112),char(117),char(108),
-char(115),char(101),char(115),char(0),char(109),char(95),char(110),char(100),char(105),char(109),char(112),char(117),char(108),char(115),char(101),char(115),char(0),char(109),char(95),char(110),
-char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(108),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),
-char(95),char(97),char(100),char(97),char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(109),char(97),char(116),char(99),char(104),char(105),char(110),char(103),
-char(0),char(109),char(95),char(109),char(97),char(120),char(83),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(73),
-char(109),char(112),char(117),char(108),char(115),char(101),char(0),char(109),char(95),char(115),char(101),char(108),char(102),char(67),char(111),char(108),char(108),char(105),char(115),char(105),
-char(111),char(110),char(73),char(109),char(112),char(117),char(108),char(115),char(101),char(70),char(97),char(99),char(116),char(111),char(114),char(0),char(109),char(95),char(99),char(111),
-char(110),char(116),char(97),char(105),char(110),char(115),char(65),char(110),char(99),char(104),char(111),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(108),char(105),
-char(100),char(101),char(0),char(109),char(95),char(99),char(108),char(117),char(115),char(116),char(101),char(114),char(73),char(110),char(100),char(101),char(120),char(0),char(42),char(109),
-char(95),char(98),char(111),char(100),char(121),char(65),char(0),char(42),char(109),char(95),char(98),char(111),char(100),char(121),char(66),char(0),char(109),char(95),char(114),char(101),
-char(102),char(115),char(91),char(50),char(93),char(0),char(109),char(95),char(99),char(102),char(109),char(0),char(109),char(95),char(115),char(112),char(108),char(105),char(116),char(0),
-char(109),char(95),char(100),char(101),char(108),char(101),char(116),char(101),char(0),char(109),char(95),char(114),char(101),char(108),char(80),char(111),char(115),char(105),char(116),char(105),
-char(111),char(110),char(91),char(50),char(93),char(0),char(109),char(95),char(98),char(111),char(100),char(121),char(65),char(116),char(121),char(112),char(101),char(0),char(109),char(95),
-char(98),char(111),char(100),char(121),char(66),char(116),char(121),char(112),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(84),char(121),char(112),
-char(101),char(0),char(42),char(109),char(95),char(112),char(111),char(115),char(101),char(0),char(42),char(42),char(109),char(95),char(109),char(97),char(116),char(101),char(114),char(105),
-char(97),char(108),char(115),char(0),char(42),char(109),char(95),char(110),char(111),char(100),char(101),char(115),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
-char(115),char(0),char(42),char(109),char(95),char(102),char(97),char(99),char(101),char(115),char(0),char(42),char(109),char(95),char(116),char(101),char(116),char(114),char(97),char(104),
-char(101),char(100),char(114),char(97),char(0),char(42),char(109),char(95),char(97),char(110),char(99),char(104),char(111),char(114),char(115),char(0),char(42),char(109),char(95),char(99),
-char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(77),char(97),char(116),char(101),char(114),char(105),char(97),char(108),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(76),char(105),
-char(110),char(107),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(70),char(97),char(99),char(101),char(115),char(0),char(109),char(95),char(110),char(117),char(109),
-char(84),char(101),char(116),char(114),char(97),char(104),char(101),char(100),char(114),char(97),char(0),char(109),char(95),char(110),char(117),char(109),char(65),char(110),char(99),char(104),
-char(111),char(114),char(115),char(0),char(109),char(95),char(110),char(117),char(109),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(115),char(0),char(109),char(95),
-char(110),char(117),char(109),char(74),char(111),char(105),char(110),char(116),char(115),char(0),char(109),char(95),char(99),char(111),char(110),char(102),char(105),char(103),char(0),char(109),
-char(95),char(122),char(101),char(114),char(111),char(82),char(111),char(116),char(80),char(97),char(114),char(101),char(110),char(116),char(84),char(111),char(84),char(104),char(105),char(115),
-char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(67),char(111),char(109),char(84),char(111),char(84),char(104),char(105),char(115),char(80),char(105),
-char(118),char(111),char(116),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(116),char(104),char(105),char(115),char(80),char(105),char(118),char(111),
-char(116),char(84),char(111),char(84),char(104),char(105),char(115),char(67),char(111),char(109),char(79),char(102),char(102),char(115),char(101),char(116),char(0),char(109),char(95),char(106),
-char(111),char(105),char(110),char(116),char(65),char(120),char(105),char(115),char(84),char(111),char(112),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),
-char(110),char(116),char(65),char(120),char(105),char(115),char(66),char(111),char(116),char(116),char(111),char(109),char(91),char(54),char(93),char(0),char(109),char(95),char(108),char(105),
-char(110),char(107),char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),
-char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),
-char(70),char(114),char(97),char(109),char(101),char(84),char(111),char(116),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),
-char(111),char(109),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),char(99),char(86),char(101),char(108),char(111),
-char(99),char(105),char(116),char(121),char(84),char(111),char(112),char(0),char(109),char(95),char(97),char(98),char(115),char(70),char(114),char(97),char(109),char(101),char(76),char(111),
-char(99),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(66),char(111),char(116),char(116),char(111),char(109),char(0),char(109),char(95),char(108),char(105),
-char(110),char(107),char(77),char(97),char(115),char(115),char(0),char(109),char(95),char(112),char(97),char(114),char(101),char(110),char(116),char(73),char(110),char(100),char(101),char(120),
-char(0),char(109),char(95),char(100),char(111),char(102),char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(112),char(111),char(115),char(86),char(97),char(114),
-char(67),char(111),char(117),char(110),char(116),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(80),char(111),char(115),char(91),char(55),char(93),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(86),char(101),char(108),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(84),char(111),char(114),char(113),char(117),char(101),char(91),char(54),char(93),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(68),char(97),
-char(109),char(112),char(105),char(110),char(103),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(70),char(114),char(105),char(99),char(116),char(105),char(111),
-char(110),char(0),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(76),char(111),char(119),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),
-char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(85),char(112),char(112),char(101),char(114),char(76),char(105),char(109),char(105),char(116),char(0),char(109),char(95),
-char(106),char(111),char(105),char(110),char(116),char(77),char(97),char(120),char(70),char(111),char(114),char(99),char(101),char(0),char(109),char(95),char(106),char(111),char(105),char(110),
-char(116),char(77),char(97),char(120),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(42),char(109),char(95),char(108),char(105),char(110),char(107),
-char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(106),char(111),char(105),char(110),char(116),char(78),char(97),char(109),char(101),char(0),char(42),char(109),
-char(95),char(108),char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(42),char(109),char(95),char(112),char(97),char(100),
-char(100),char(105),char(110),char(103),char(80),char(116),char(114),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(80),
-char(111),char(115),char(105),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(87),char(111),char(114),char(108),char(100),char(79),
-char(114),char(105),char(101),char(110),char(116),char(97),char(116),char(105),char(111),char(110),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(76),char(105),char(110),
-char(101),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(65),char(110),
-char(103),char(117),char(108),char(97),char(114),char(86),char(101),char(108),char(111),char(99),char(105),char(116),char(121),char(0),char(109),char(95),char(98),char(97),char(115),char(101),
-char(73),char(110),char(101),char(114),char(116),char(105),char(97),char(0),char(109),char(95),char(98),char(97),char(115),char(101),char(77),char(97),char(115),char(115),char(0),char(42),
-char(109),char(95),char(98),char(97),char(115),char(101),char(78),char(97),char(109),char(101),char(0),char(42),char(109),char(95),char(98),char(97),char(115),char(101),char(67),char(111),
-char(108),char(108),char(105),char(100),char(101),char(114),char(0),char(109),char(95),char(99),char(111),char(108),char(79),char(98),char(106),char(68),char(97),char(116),char(97),char(0),
-char(42),char(109),char(95),char(109),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(0),char(109),char(95),char(108),char(105),char(110),char(107),char(0),
-char(84),char(89),char(80),char(69),char(99),char(0),char(0),char(0),char(99),char(104),char(97),char(114),char(0),char(117),char(99),char(104),char(97),char(114),char(0),char(115),
-char(104),char(111),char(114),char(116),char(0),char(117),char(115),char(104),char(111),char(114),char(116),char(0),char(105),char(110),char(116),char(0),char(108),char(111),char(110),char(103),
-char(0),char(117),char(108),char(111),char(110),char(103),char(0),char(102),char(108),char(111),char(97),char(116),char(0),char(100),char(111),char(117),char(98),char(108),char(101),char(0),
-char(118),char(111),char(105),char(100),char(0),char(80),char(111),char(105),char(110),char(116),char(101),char(114),char(65),char(114),char(114),char(97),char(121),char(0),char(98),char(116),
-char(80),char(104),char(121),char(115),char(105),char(99),char(115),char(83),char(121),char(115),char(116),char(101),char(109),char(0),char(76),char(105),char(115),char(116),char(66),char(97),
-char(115),char(101),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(86),char(101),char(99),char(116),char(111),char(114),char(51),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(70),char(108),char(111),char(97),char(116),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(116),char(101),char(114),char(110),char(105),char(111),char(110),char(68),char(111),char(117),char(98),
-char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(97),char(116),char(114),char(105),char(120),char(51),char(120),char(51),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),char(114),
-char(109),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(97),char(110),char(115),char(102),char(111),
-char(114),char(109),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(66),char(118),char(104),char(83),char(117),
-char(98),char(116),char(114),char(101),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),
-char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(79),char(112),char(116),char(105),char(109),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),char(116),char(105),char(122),
-char(101),char(100),char(66),char(118),char(104),char(78),char(111),char(100),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(81),char(117),char(97),char(110),
-char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(81),char(117),char(97),char(110),char(116),char(105),char(122),char(101),char(100),char(66),char(118),char(104),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),
-char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(83),char(104),char(97),char(112),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),char(97),char(116),char(105),char(99),char(80),char(108),char(97),char(110),char(101),char(83),char(104),char(97),
-char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(118),char(101),char(120),char(73),char(110),char(116),char(101),char(114),
-char(110),char(97),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(115),char(105),char(116),
-char(105),char(111),char(110),char(65),char(110),char(100),char(82),char(97),char(100),char(105),char(117),char(115),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),
-char(83),char(112),char(104),char(101),char(114),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(104),char(111),char(114),char(116),char(73),char(110),
-char(116),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(104),char(97),char(114),char(73),char(110),char(100),char(101),char(120),char(84),char(114),char(105),char(112),char(108),char(101),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(77),char(101),char(115),char(104),char(80),char(97),char(114),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(116),
-char(114),char(105),char(100),char(105),char(110),char(103),char(77),char(101),char(115),char(104),char(73),char(110),char(116),char(101),char(114),char(102),char(97),char(99),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),
-char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),
-char(102),char(111),char(77),char(97),char(112),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(99),char(97),char(108),char(101),char(100),char(84),char(114),
-char(105),char(97),char(110),char(103),char(108),char(101),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),char(67),char(104),char(105),char(108),char(100),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(109),char(112),char(111),char(117),char(110),char(100),char(83),char(104),char(97),char(112),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(121),char(108),char(105),char(110),char(100),char(101),char(114),char(83),char(104),char(97),char(112),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(67),char(97),char(112),char(115),char(117),char(108),char(101),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(84),char(114),char(105),char(97),char(110),char(103),char(108),char(101),char(73),char(110),char(102),char(111),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),
-char(110),char(79),char(98),char(106),char(101),char(99),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(80),char(101),char(114),char(115),char(105),char(115),char(116),char(101),char(110),char(116),char(77),char(97),char(110),char(105),char(102),char(111),char(108),char(100),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(108),char(108),char(105),char(115),char(105),char(111),char(110),char(79),
-char(98),char(106),char(101),char(99),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(73),char(109),
-char(112),char(97),char(99),char(116),char(77),char(101),char(115),char(104),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(67),char(111),char(110),char(118),char(101),char(120),char(72),char(117),char(108),char(108),char(83),char(104),char(97),char(112),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(116),char(97),char(99),char(116),char(83),
-char(111),char(108),char(118),char(101),char(114),char(73),char(110),char(102),char(111),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),
-char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),char(68),char(111),char(117),char(98),char(108),char(101),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(68),char(121),char(110),char(97),char(109),char(105),char(99),char(115),char(87),char(111),char(114),char(108),char(100),
-char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),
-char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),
-char(100),char(121),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(115),char(116),
-char(114),char(97),char(105),char(110),char(116),char(73),char(110),char(102),char(111),char(49),char(0),char(98),char(116),char(84),char(121),char(112),char(101),char(100),char(67),char(111),
-char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),
-char(84),char(121),char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(82),char(105),char(103),char(105),char(100),char(66),char(111),char(100),char(121),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(84),char(121),
-char(112),char(101),char(100),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),
-char(97),char(116),char(97),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),
-char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(80),
-char(111),char(105),char(110),char(116),char(50),char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(80),char(111),char(105),char(110),char(116),char(50),
-char(80),char(111),char(105),char(110),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),
-char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(72),char(105),char(110),char(103),
-char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(72),char(105),char(110),char(103),char(101),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),
-char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),
-char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(0),char(98),char(116),char(67),char(111),char(110),char(101),char(84),char(119),char(105),char(115),char(116),char(67),char(111),char(110),char(115),char(116),char(114),char(97),
-char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),
-char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),
-char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),
-char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),
-char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),
-char(114),char(105),char(110),char(103),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),
-char(68),char(97),char(116),char(97),char(50),char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),
-char(112),char(114),char(105),char(110),char(103),char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(71),char(101),char(110),char(101),char(114),char(105),char(99),char(54),char(68),char(111),char(102),char(83),char(112),char(114),char(105),char(110),char(103),
-char(50),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),
-char(97),char(50),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),
-char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(108),char(105),char(100),char(101),char(114),char(67),char(111),char(110),char(115),char(116),char(114),
-char(97),char(105),char(110),char(116),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(71),char(101),char(97),
-char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(71),char(101),char(97),char(114),char(67),char(111),char(110),char(115),char(116),char(114),char(97),char(105),char(110),char(116),char(68),char(111),char(117),
-char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(77),char(97),char(116),char(101),
-char(114),char(105),char(97),char(108),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(78),char(111),char(100),
-char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(97),
-char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(70),char(97),char(99),char(101),char(68),char(97),char(116),char(97),char(0),
-char(83),char(111),char(102),char(116),char(66),char(111),char(100),char(121),char(84),char(101),char(116),char(114),char(97),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(82),char(105),char(103),char(105),char(100),char(65),char(110),char(99),char(104),char(111),char(114),char(68),char(97),char(116),char(97),char(0),char(83),char(111),
-char(102),char(116),char(66),char(111),char(100),char(121),char(67),char(111),char(110),char(102),char(105),char(103),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),
-char(116),char(66),char(111),char(100),char(121),char(80),char(111),char(115),char(101),char(68),char(97),char(116),char(97),char(0),char(83),char(111),char(102),char(116),char(66),char(111),
-char(100),char(121),char(67),char(108),char(117),char(115),char(116),char(101),char(114),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(74),char(111),char(105),char(110),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(83),char(111),char(102),char(116),
-char(66),char(111),char(100),char(121),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),
-char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),
-char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(70),char(108),char(111),char(97),char(116),
-char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(68),char(111),char(117),char(98),
-char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(70),char(108),
-char(111),char(97),char(116),char(68),char(97),char(116),char(97),char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),
-char(105),char(110),char(107),char(67),char(111),char(108),char(108),char(105),char(100),char(101),char(114),char(70),char(108),char(111),char(97),char(116),char(68),char(97),char(116),char(97),
-char(0),char(98),char(116),char(77),char(117),char(108),char(116),char(105),char(66),char(111),char(100),char(121),char(76),char(105),char(110),char(107),char(67),char(111),char(108),char(108),
-char(105),char(100),char(101),char(114),char(68),char(111),char(117),char(98),char(108),char(101),char(68),char(97),char(116),char(97),char(0),char(0),char(84),char(76),char(69),char(78),
-char(1),char(0),char(1),char(0),char(2),char(0),char(2),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(0),char(0),
-char(16),char(0),char(48),char(0),char(16),char(0),char(16),char(0),char(32),char(0),char(16),char(0),char(32),char(0),char(48),char(0),char(96),char(0),char(64),char(0),
-char(-128),char(0),char(20),char(0),char(48),char(0),char(80),char(0),char(16),char(0),char(96),char(0),char(-112),char(0),char(16),char(0),char(56),char(0),char(56),char(0),
-char(20),char(0),char(72),char(0),char(4),char(0),char(4),char(0),char(8),char(0),char(4),char(0),char(56),char(0),char(32),char(0),char(80),char(0),char(72),char(0),
-char(96),char(0),char(80),char(0),char(32),char(0),char(64),char(0),char(64),char(0),char(64),char(0),char(16),char(0),char(24),char(6),char(-8),char(1),char(80),char(3),
-char(32),char(1),char(72),char(0),char(80),char(0),char(-96),char(0),char(88),char(0),char(-64),char(0),char(104),char(0),char(8),char(2),char(-56),char(3),char(8),char(0),
-char(64),char(0),char(64),char(0),char(0),char(0),char(80),char(0),char(96),char(0),char(-112),char(0),char(-128),char(0),char(104),char(1),char(-24),char(0),char(-104),char(1),
-char(-120),char(1),char(-32),char(0),char(8),char(1),char(-40),char(1),char(104),char(1),char(-128),char(2),char(-112),char(2),char(-64),char(4),char(-40),char(0),char(120),char(1),
-char(104),char(0),char(-104),char(0),char(16),char(0),char(104),char(0),char(24),char(0),char(40),char(0),char(104),char(0),char(96),char(0),char(104),char(0),char(-56),char(0),
-char(104),char(1),char(112),char(0),char(-16),char(1),char(-128),char(3),char(-40),char(1),char(-56),char(0),char(112),char(0),char(48),char(1),char(8),char(2),char(0),char(0),
-char(83),char(84),char(82),char(67),char(88),char(0),char(0),char(0),char(10),char(0),char(3),char(0),char(4),char(0),char(0),char(0),char(4),char(0),char(1),char(0),
-char(9),char(0),char(2),char(0),char(11),char(0),char(3),char(0),char(10),char(0),char(3),char(0),char(10),char(0),char(4),char(0),char(10),char(0),char(5),char(0),
-char(12),char(0),char(2),char(0),char(9),char(0),char(6),char(0),char(9),char(0),char(7),char(0),char(13),char(0),char(1),char(0),char(7),char(0),char(8),char(0),
-char(14),char(0),char(1),char(0),char(8),char(0),char(8),char(0),char(15),char(0),char(1),char(0),char(7),char(0),char(8),char(0),char(16),char(0),char(1),char(0),
-char(8),char(0),char(8),char(0),char(17),char(0),char(1),char(0),char(13),char(0),char(9),char(0),char(18),char(0),char(1),char(0),char(14),char(0),char(9),char(0),
-char(19),char(0),char(2),char(0),char(17),char(0),char(10),char(0),char(13),char(0),char(11),char(0),char(20),char(0),char(2),char(0),char(18),char(0),char(10),char(0),
-char(14),char(0),char(11),char(0),char(21),char(0),char(4),char(0),char(4),char(0),char(12),char(0),char(4),char(0),char(13),char(0),char(2),char(0),char(14),char(0),
-char(2),char(0),char(15),char(0),char(22),char(0),char(6),char(0),char(13),char(0),char(16),char(0),char(13),char(0),char(17),char(0),char(4),char(0),char(18),char(0),
-char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),char(23),char(0),char(6),char(0),char(14),char(0),char(16),char(0),
-char(14),char(0),char(17),char(0),char(4),char(0),char(18),char(0),char(4),char(0),char(19),char(0),char(4),char(0),char(20),char(0),char(0),char(0),char(21),char(0),
-char(24),char(0),char(3),char(0),char(2),char(0),char(14),char(0),char(2),char(0),char(15),char(0),char(4),char(0),char(22),char(0),char(25),char(0),char(12),char(0),
-char(13),char(0),char(23),char(0),char(13),char(0),char(24),char(0),char(13),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),
-char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),char(22),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(21),char(0),char(32),char(0),
-char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(26),char(0),char(12),char(0),char(14),char(0),char(23),char(0),char(14),char(0),char(24),char(0),
-char(14),char(0),char(25),char(0),char(4),char(0),char(26),char(0),char(4),char(0),char(27),char(0),char(4),char(0),char(28),char(0),char(4),char(0),char(29),char(0),
-char(23),char(0),char(30),char(0),char(24),char(0),char(31),char(0),char(4),char(0),char(33),char(0),char(4),char(0),char(34),char(0),char(21),char(0),char(32),char(0),
-char(27),char(0),char(3),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(36),char(0),char(0),char(0),char(37),char(0),char(28),char(0),char(5),char(0),
-char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(40),char(0),char(7),char(0),char(41),char(0),char(0),char(0),char(21),char(0),
-char(29),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(13),char(0),char(39),char(0),char(13),char(0),char(42),char(0),char(7),char(0),char(43),char(0),
-char(4),char(0),char(44),char(0),char(30),char(0),char(2),char(0),char(13),char(0),char(45),char(0),char(7),char(0),char(46),char(0),char(31),char(0),char(4),char(0),
-char(29),char(0),char(47),char(0),char(30),char(0),char(48),char(0),char(4),char(0),char(49),char(0),char(0),char(0),char(37),char(0),char(32),char(0),char(1),char(0),
-char(4),char(0),char(50),char(0),char(33),char(0),char(2),char(0),char(2),char(0),char(50),char(0),char(0),char(0),char(51),char(0),char(34),char(0),char(2),char(0),
-char(2),char(0),char(52),char(0),char(0),char(0),char(51),char(0),char(35),char(0),char(2),char(0),char(0),char(0),char(52),char(0),char(0),char(0),char(53),char(0),
-char(36),char(0),char(8),char(0),char(13),char(0),char(54),char(0),char(14),char(0),char(55),char(0),char(32),char(0),char(56),char(0),char(34),char(0),char(57),char(0),
-char(35),char(0),char(58),char(0),char(33),char(0),char(59),char(0),char(4),char(0),char(60),char(0),char(4),char(0),char(61),char(0),char(37),char(0),char(4),char(0),
-char(36),char(0),char(62),char(0),char(13),char(0),char(63),char(0),char(4),char(0),char(64),char(0),char(0),char(0),char(37),char(0),char(38),char(0),char(7),char(0),
-char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),char(25),char(0),char(66),char(0),char(26),char(0),char(67),char(0),char(39),char(0),char(68),char(0),
-char(7),char(0),char(43),char(0),char(0),char(0),char(69),char(0),char(40),char(0),char(2),char(0),char(38),char(0),char(70),char(0),char(13),char(0),char(39),char(0),
-char(41),char(0),char(4),char(0),char(19),char(0),char(71),char(0),char(27),char(0),char(72),char(0),char(4),char(0),char(73),char(0),char(7),char(0),char(74),char(0),
-char(42),char(0),char(4),char(0),char(27),char(0),char(38),char(0),char(41),char(0),char(75),char(0),char(4),char(0),char(76),char(0),char(7),char(0),char(43),char(0),
-char(43),char(0),char(3),char(0),char(29),char(0),char(47),char(0),char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(44),char(0),char(3),char(0),
-char(29),char(0),char(47),char(0),char(4),char(0),char(78),char(0),char(0),char(0),char(37),char(0),char(45),char(0),char(3),char(0),char(29),char(0),char(47),char(0),
-char(4),char(0),char(77),char(0),char(0),char(0),char(37),char(0),char(46),char(0),char(4),char(0),char(4),char(0),char(79),char(0),char(7),char(0),char(80),char(0),
-char(7),char(0),char(81),char(0),char(7),char(0),char(82),char(0),char(39),char(0),char(14),char(0),char(4),char(0),char(83),char(0),char(4),char(0),char(84),char(0),
-char(46),char(0),char(85),char(0),char(4),char(0),char(86),char(0),char(7),char(0),char(87),char(0),char(7),char(0),char(88),char(0),char(7),char(0),char(89),char(0),
-char(7),char(0),char(90),char(0),char(7),char(0),char(91),char(0),char(4),char(0),char(92),char(0),char(4),char(0),char(93),char(0),char(4),char(0),char(94),char(0),
-char(4),char(0),char(95),char(0),char(0),char(0),char(37),char(0),char(47),char(0),char(39),char(0),char(14),char(0),char(96),char(0),char(14),char(0),char(97),char(0),
-char(14),char(0),char(98),char(0),char(14),char(0),char(99),char(0),char(14),char(0),char(100),char(0),char(14),char(0),char(101),char(0),char(14),char(0),char(102),char(0),
-char(8),char(0),char(103),char(0),char(8),char(0),char(104),char(0),char(8),char(0),char(105),char(0),char(8),char(0),char(106),char(0),char(8),char(0),char(107),char(0),
-char(8),char(0),char(108),char(0),char(8),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
-char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(8),char(0),char(115),char(0),char(8),char(0),char(116),char(0),char(8),char(0),char(117),char(0),
-char(8),char(0),char(118),char(0),char(8),char(0),char(119),char(0),char(8),char(0),char(120),char(0),char(8),char(0),char(121),char(0),char(8),char(0),char(122),char(0),
-char(8),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
-char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(8),char(0),char(-126),char(0),char(8),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
-char(48),char(0),char(-124),char(0),char(48),char(0),char(-123),char(0),char(49),char(0),char(39),char(0),char(13),char(0),char(96),char(0),char(13),char(0),char(97),char(0),
-char(13),char(0),char(98),char(0),char(13),char(0),char(99),char(0),char(13),char(0),char(100),char(0),char(13),char(0),char(101),char(0),char(13),char(0),char(102),char(0),
-char(7),char(0),char(103),char(0),char(7),char(0),char(104),char(0),char(7),char(0),char(105),char(0),char(7),char(0),char(106),char(0),char(7),char(0),char(107),char(0),
-char(7),char(0),char(108),char(0),char(7),char(0),char(109),char(0),char(4),char(0),char(110),char(0),char(4),char(0),char(111),char(0),char(4),char(0),char(112),char(0),
-char(4),char(0),char(113),char(0),char(4),char(0),char(114),char(0),char(7),char(0),char(115),char(0),char(7),char(0),char(116),char(0),char(7),char(0),char(117),char(0),
-char(7),char(0),char(118),char(0),char(7),char(0),char(119),char(0),char(7),char(0),char(120),char(0),char(7),char(0),char(121),char(0),char(7),char(0),char(122),char(0),
-char(7),char(0),char(123),char(0),char(4),char(0),char(124),char(0),char(4),char(0),char(125),char(0),char(4),char(0),char(126),char(0),char(4),char(0),char(127),char(0),
-char(4),char(0),char(-128),char(0),char(4),char(0),char(-127),char(0),char(7),char(0),char(-126),char(0),char(7),char(0),char(-125),char(0),char(4),char(0),char(44),char(0),
-char(50),char(0),char(-124),char(0),char(50),char(0),char(-123),char(0),char(51),char(0),char(5),char(0),char(27),char(0),char(38),char(0),char(37),char(0),char(65),char(0),
-char(13),char(0),char(39),char(0),char(7),char(0),char(43),char(0),char(4),char(0),char(-122),char(0),char(52),char(0),char(5),char(0),char(29),char(0),char(47),char(0),
-char(13),char(0),char(-121),char(0),char(14),char(0),char(-120),char(0),char(4),char(0),char(-119),char(0),char(0),char(0),char(-118),char(0),char(48),char(0),char(29),char(0),
-char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(20),char(0),char(-114),char(0),
-char(20),char(0),char(-113),char(0),char(14),char(0),char(-112),char(0),char(14),char(0),char(-111),char(0),char(14),char(0),char(-110),char(0),char(8),char(0),char(-125),char(0),
-char(8),char(0),char(-109),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-107),char(0),char(8),char(0),char(-106),char(0),char(8),char(0),char(-105),char(0),
-char(8),char(0),char(-104),char(0),char(8),char(0),char(-103),char(0),char(8),char(0),char(-102),char(0),char(8),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
-char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
-char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(50),char(0),char(29),char(0),
-char(9),char(0),char(-117),char(0),char(9),char(0),char(-116),char(0),char(27),char(0),char(-115),char(0),char(0),char(0),char(35),char(0),char(19),char(0),char(-114),char(0),
-char(19),char(0),char(-113),char(0),char(13),char(0),char(-112),char(0),char(13),char(0),char(-111),char(0),char(13),char(0),char(-110),char(0),char(7),char(0),char(-125),char(0),
-char(7),char(0),char(-109),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-107),char(0),char(7),char(0),char(-106),char(0),char(7),char(0),char(-105),char(0),
-char(7),char(0),char(-104),char(0),char(7),char(0),char(-103),char(0),char(7),char(0),char(-102),char(0),char(7),char(0),char(-101),char(0),char(4),char(0),char(-100),char(0),
-char(4),char(0),char(-99),char(0),char(4),char(0),char(-98),char(0),char(4),char(0),char(-97),char(0),char(4),char(0),char(-96),char(0),char(4),char(0),char(-95),char(0),
-char(4),char(0),char(-94),char(0),char(4),char(0),char(-93),char(0),char(4),char(0),char(-92),char(0),char(4),char(0),char(-91),char(0),char(53),char(0),char(23),char(0),
-char(8),char(0),char(-90),char(0),char(8),char(0),char(-89),char(0),char(8),char(0),char(-108),char(0),char(8),char(0),char(-88),char(0),char(8),char(0),char(-104),char(0),
-char(8),char(0),char(-87),char(0),char(8),char(0),char(-86),char(0),char(8),char(0),char(-85),char(0),char(8),char(0),char(-84),char(0),char(8),char(0),char(-83),char(0),
-char(8),char(0),char(-82),char(0),char(8),char(0),char(-81),char(0),char(8),char(0),char(-80),char(0),char(8),char(0),char(-79),char(0),char(8),char(0),char(-78),char(0),
-char(8),char(0),char(-77),char(0),char(8),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),
-char(4),char(0),char(-72),char(0),char(4),char(0),char(-71),char(0),char(0),char(0),char(37),char(0),char(54),char(0),char(22),char(0),char(7),char(0),char(-90),char(0),
-char(7),char(0),char(-89),char(0),char(7),char(0),char(-108),char(0),char(7),char(0),char(-88),char(0),char(7),char(0),char(-104),char(0),char(7),char(0),char(-87),char(0),
-char(7),char(0),char(-86),char(0),char(7),char(0),char(-85),char(0),char(7),char(0),char(-84),char(0),char(7),char(0),char(-83),char(0),char(7),char(0),char(-82),char(0),
-char(7),char(0),char(-81),char(0),char(7),char(0),char(-80),char(0),char(7),char(0),char(-79),char(0),char(7),char(0),char(-78),char(0),char(7),char(0),char(-77),char(0),
-char(7),char(0),char(-76),char(0),char(4),char(0),char(-75),char(0),char(4),char(0),char(-74),char(0),char(4),char(0),char(-73),char(0),char(4),char(0),char(-72),char(0),
-char(4),char(0),char(-71),char(0),char(55),char(0),char(2),char(0),char(53),char(0),char(-70),char(0),char(14),char(0),char(-69),char(0),char(56),char(0),char(2),char(0),
-char(54),char(0),char(-70),char(0),char(13),char(0),char(-69),char(0),char(57),char(0),char(21),char(0),char(50),char(0),char(-68),char(0),char(17),char(0),char(-67),char(0),
-char(13),char(0),char(-66),char(0),char(13),char(0),char(-65),char(0),char(13),char(0),char(-64),char(0),char(13),char(0),char(-63),char(0),char(13),char(0),char(-69),char(0),
-char(13),char(0),char(-62),char(0),char(13),char(0),char(-61),char(0),char(13),char(0),char(-60),char(0),char(13),char(0),char(-59),char(0),char(7),char(0),char(-58),char(0),
-char(7),char(0),char(-57),char(0),char(7),char(0),char(-56),char(0),char(7),char(0),char(-55),char(0),char(7),char(0),char(-54),char(0),char(7),char(0),char(-53),char(0),
-char(7),char(0),char(-52),char(0),char(7),char(0),char(-51),char(0),char(7),char(0),char(-50),char(0),char(4),char(0),char(-49),char(0),char(58),char(0),char(22),char(0),
-char(48),char(0),char(-68),char(0),char(18),char(0),char(-67),char(0),char(14),char(0),char(-66),char(0),char(14),char(0),char(-65),char(0),char(14),char(0),char(-64),char(0),
-char(14),char(0),char(-63),char(0),char(14),char(0),char(-69),char(0),char(14),char(0),char(-62),char(0),char(14),char(0),char(-61),char(0),char(14),char(0),char(-60),char(0),
-char(14),char(0),char(-59),char(0),char(8),char(0),char(-58),char(0),char(8),char(0),char(-57),char(0),char(8),char(0),char(-56),char(0),char(8),char(0),char(-55),char(0),
-char(8),char(0),char(-54),char(0),char(8),char(0),char(-53),char(0),char(8),char(0),char(-52),char(0),char(8),char(0),char(-51),char(0),char(8),char(0),char(-50),char(0),
-char(4),char(0),char(-49),char(0),char(0),char(0),char(37),char(0),char(59),char(0),char(2),char(0),char(4),char(0),char(-48),char(0),char(4),char(0),char(-47),char(0),
-char(60),char(0),char(13),char(0),char(57),char(0),char(-46),char(0),char(57),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),
-char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),
-char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(61),char(0),char(13),char(0),
-char(62),char(0),char(-46),char(0),char(62),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),
-char(4),char(0),char(-43),char(0),char(4),char(0),char(-42),char(0),char(7),char(0),char(-41),char(0),char(7),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),
-char(4),char(0),char(-38),char(0),char(7),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(63),char(0),char(14),char(0),char(58),char(0),char(-46),char(0),
-char(58),char(0),char(-45),char(0),char(0),char(0),char(35),char(0),char(4),char(0),char(-127),char(0),char(4),char(0),char(-44),char(0),char(4),char(0),char(-43),char(0),
-char(4),char(0),char(-42),char(0),char(8),char(0),char(-41),char(0),char(8),char(0),char(-40),char(0),char(4),char(0),char(-39),char(0),char(4),char(0),char(-38),char(0),
-char(8),char(0),char(-37),char(0),char(4),char(0),char(-36),char(0),char(0),char(0),char(-35),char(0),char(64),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),
-char(13),char(0),char(-33),char(0),char(13),char(0),char(-32),char(0),char(65),char(0),char(3),char(0),char(63),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),
-char(14),char(0),char(-32),char(0),char(66),char(0),char(3),char(0),char(61),char(0),char(-34),char(0),char(14),char(0),char(-33),char(0),char(14),char(0),char(-32),char(0),
-char(67),char(0),char(13),char(0),char(61),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),
-char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),
-char(7),char(0),char(-23),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(68),char(0),char(13),char(0),
-char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),
-char(4),char(0),char(-27),char(0),char(7),char(0),char(-26),char(0),char(7),char(0),char(-25),char(0),char(7),char(0),char(-24),char(0),char(7),char(0),char(-23),char(0),
-char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(69),char(0),char(14),char(0),char(63),char(0),char(-34),char(0),
-char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(4),char(0),char(-29),char(0),char(4),char(0),char(-28),char(0),char(4),char(0),char(-27),char(0),
-char(8),char(0),char(-26),char(0),char(8),char(0),char(-25),char(0),char(8),char(0),char(-24),char(0),char(8),char(0),char(-23),char(0),char(8),char(0),char(-22),char(0),
-char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(0),char(0),char(-19),char(0),char(70),char(0),char(10),char(0),char(63),char(0),char(-34),char(0),
-char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(8),char(0),char(-18),char(0),char(8),char(0),char(-17),char(0),char(8),char(0),char(-16),char(0),
-char(8),char(0),char(-22),char(0),char(8),char(0),char(-21),char(0),char(8),char(0),char(-20),char(0),char(8),char(0),char(-89),char(0),char(71),char(0),char(11),char(0),
-char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(7),char(0),char(-18),char(0),char(7),char(0),char(-17),char(0),
-char(7),char(0),char(-16),char(0),char(7),char(0),char(-22),char(0),char(7),char(0),char(-21),char(0),char(7),char(0),char(-20),char(0),char(7),char(0),char(-89),char(0),
-char(0),char(0),char(21),char(0),char(72),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),
-char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
-char(4),char(0),char(-10),char(0),char(73),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),
-char(14),char(0),char(-15),char(0),char(14),char(0),char(-14),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),char(4),char(0),char(-11),char(0),
-char(4),char(0),char(-10),char(0),char(74),char(0),char(5),char(0),char(72),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),char(7),char(0),char(-7),char(0),
-char(7),char(0),char(-6),char(0),char(7),char(0),char(-5),char(0),char(75),char(0),char(5),char(0),char(73),char(0),char(-9),char(0),char(4),char(0),char(-8),char(0),
-char(8),char(0),char(-7),char(0),char(8),char(0),char(-6),char(0),char(8),char(0),char(-5),char(0),char(76),char(0),char(41),char(0),char(61),char(0),char(-34),char(0),
-char(19),char(0),char(-31),char(0),char(19),char(0),char(-30),char(0),char(13),char(0),char(-15),char(0),char(13),char(0),char(-14),char(0),char(13),char(0),char(-4),char(0),
-char(13),char(0),char(-3),char(0),char(13),char(0),char(-2),char(0),char(13),char(0),char(-1),char(0),char(13),char(0),char(0),char(1),char(13),char(0),char(1),char(1),
-char(13),char(0),char(2),char(1),char(13),char(0),char(3),char(1),char(13),char(0),char(4),char(1),char(13),char(0),char(5),char(1),char(13),char(0),char(6),char(1),
-char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),
-char(0),char(0),char(-19),char(0),char(13),char(0),char(-13),char(0),char(13),char(0),char(-12),char(0),char(13),char(0),char(12),char(1),char(13),char(0),char(13),char(1),
-char(13),char(0),char(14),char(1),char(13),char(0),char(15),char(1),char(13),char(0),char(16),char(1),char(13),char(0),char(17),char(1),char(13),char(0),char(18),char(1),
-char(13),char(0),char(19),char(1),char(13),char(0),char(20),char(1),char(13),char(0),char(21),char(1),char(13),char(0),char(22),char(1),char(0),char(0),char(23),char(1),
-char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),
-char(77),char(0),char(41),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),char(20),char(0),char(-30),char(0),char(14),char(0),char(-15),char(0),
-char(14),char(0),char(-14),char(0),char(14),char(0),char(-4),char(0),char(14),char(0),char(-3),char(0),char(14),char(0),char(-2),char(0),char(14),char(0),char(-1),char(0),
-char(14),char(0),char(0),char(1),char(14),char(0),char(1),char(1),char(14),char(0),char(2),char(1),char(14),char(0),char(3),char(1),char(14),char(0),char(4),char(1),
-char(14),char(0),char(5),char(1),char(14),char(0),char(6),char(1),char(0),char(0),char(7),char(1),char(0),char(0),char(8),char(1),char(0),char(0),char(9),char(1),
-char(0),char(0),char(10),char(1),char(0),char(0),char(11),char(1),char(0),char(0),char(-19),char(0),char(14),char(0),char(-13),char(0),char(14),char(0),char(-12),char(0),
-char(14),char(0),char(12),char(1),char(14),char(0),char(13),char(1),char(14),char(0),char(14),char(1),char(14),char(0),char(15),char(1),char(14),char(0),char(16),char(1),
-char(14),char(0),char(17),char(1),char(14),char(0),char(18),char(1),char(14),char(0),char(19),char(1),char(14),char(0),char(20),char(1),char(14),char(0),char(21),char(1),
-char(14),char(0),char(22),char(1),char(0),char(0),char(23),char(1),char(0),char(0),char(24),char(1),char(0),char(0),char(25),char(1),char(0),char(0),char(26),char(1),
-char(0),char(0),char(27),char(1),char(4),char(0),char(28),char(1),char(78),char(0),char(9),char(0),char(61),char(0),char(-34),char(0),char(19),char(0),char(-31),char(0),
-char(19),char(0),char(-30),char(0),char(7),char(0),char(-15),char(0),char(7),char(0),char(-14),char(0),char(7),char(0),char(-13),char(0),char(7),char(0),char(-12),char(0),
-char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(79),char(0),char(9),char(0),char(63),char(0),char(-34),char(0),char(20),char(0),char(-31),char(0),
-char(20),char(0),char(-30),char(0),char(8),char(0),char(-15),char(0),char(8),char(0),char(-14),char(0),char(8),char(0),char(-13),char(0),char(8),char(0),char(-12),char(0),
-char(4),char(0),char(-11),char(0),char(4),char(0),char(-10),char(0),char(80),char(0),char(5),char(0),char(60),char(0),char(-34),char(0),char(13),char(0),char(29),char(1),
-char(13),char(0),char(30),char(1),char(7),char(0),char(31),char(1),char(0),char(0),char(37),char(0),char(81),char(0),char(4),char(0),char(63),char(0),char(-34),char(0),
-char(14),char(0),char(29),char(1),char(14),char(0),char(30),char(1),char(8),char(0),char(31),char(1),char(82),char(0),char(4),char(0),char(7),char(0),char(32),char(1),
-char(7),char(0),char(33),char(1),char(7),char(0),char(34),char(1),char(4),char(0),char(79),char(0),char(83),char(0),char(10),char(0),char(82),char(0),char(35),char(1),
-char(13),char(0),char(36),char(1),char(13),char(0),char(37),char(1),char(13),char(0),char(38),char(1),char(13),char(0),char(39),char(1),char(13),char(0),char(40),char(1),
-char(7),char(0),char(-58),char(0),char(7),char(0),char(41),char(1),char(4),char(0),char(42),char(1),char(4),char(0),char(53),char(0),char(84),char(0),char(4),char(0),
-char(82),char(0),char(35),char(1),char(4),char(0),char(43),char(1),char(7),char(0),char(44),char(1),char(4),char(0),char(45),char(1),char(85),char(0),char(4),char(0),
-char(13),char(0),char(40),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(46),char(1),char(7),char(0),char(47),char(1),char(86),char(0),char(7),char(0),
-char(13),char(0),char(48),char(1),char(82),char(0),char(35),char(1),char(4),char(0),char(49),char(1),char(7),char(0),char(50),char(1),char(7),char(0),char(51),char(1),
-char(7),char(0),char(52),char(1),char(4),char(0),char(53),char(0),char(87),char(0),char(6),char(0),char(17),char(0),char(53),char(1),char(13),char(0),char(51),char(1),
-char(13),char(0),char(54),char(1),char(62),char(0),char(55),char(1),char(4),char(0),char(56),char(1),char(7),char(0),char(52),char(1),char(88),char(0),char(26),char(0),
-char(4),char(0),char(57),char(1),char(7),char(0),char(58),char(1),char(7),char(0),char(-89),char(0),char(7),char(0),char(59),char(1),char(7),char(0),char(60),char(1),
-char(7),char(0),char(61),char(1),char(7),char(0),char(62),char(1),char(7),char(0),char(63),char(1),char(7),char(0),char(64),char(1),char(7),char(0),char(65),char(1),
-char(7),char(0),char(66),char(1),char(7),char(0),char(67),char(1),char(7),char(0),char(68),char(1),char(7),char(0),char(69),char(1),char(7),char(0),char(70),char(1),
-char(7),char(0),char(71),char(1),char(7),char(0),char(72),char(1),char(7),char(0),char(73),char(1),char(7),char(0),char(74),char(1),char(7),char(0),char(75),char(1),
-char(7),char(0),char(76),char(1),char(4),char(0),char(77),char(1),char(4),char(0),char(78),char(1),char(4),char(0),char(79),char(1),char(4),char(0),char(80),char(1),
-char(4),char(0),char(-99),char(0),char(89),char(0),char(12),char(0),char(17),char(0),char(81),char(1),char(17),char(0),char(82),char(1),char(17),char(0),char(83),char(1),
-char(13),char(0),char(84),char(1),char(13),char(0),char(85),char(1),char(7),char(0),char(86),char(1),char(4),char(0),char(87),char(1),char(4),char(0),char(88),char(1),
-char(4),char(0),char(89),char(1),char(4),char(0),char(90),char(1),char(7),char(0),char(50),char(1),char(4),char(0),char(53),char(0),char(90),char(0),char(27),char(0),
-char(19),char(0),char(91),char(1),char(17),char(0),char(92),char(1),char(17),char(0),char(93),char(1),char(13),char(0),char(84),char(1),char(13),char(0),char(94),char(1),
-char(13),char(0),char(95),char(1),char(13),char(0),char(96),char(1),char(13),char(0),char(97),char(1),char(13),char(0),char(98),char(1),char(4),char(0),char(99),char(1),
-char(7),char(0),char(100),char(1),char(4),char(0),char(101),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(103),char(1),char(7),char(0),char(104),char(1),
-char(7),char(0),char(105),char(1),char(4),char(0),char(106),char(1),char(4),char(0),char(107),char(1),char(7),char(0),char(108),char(1),char(7),char(0),char(109),char(1),
-char(7),char(0),char(110),char(1),char(7),char(0),char(111),char(1),char(7),char(0),char(112),char(1),char(7),char(0),char(113),char(1),char(4),char(0),char(114),char(1),
-char(4),char(0),char(115),char(1),char(4),char(0),char(116),char(1),char(91),char(0),char(12),char(0),char(9),char(0),char(117),char(1),char(9),char(0),char(118),char(1),
-char(13),char(0),char(119),char(1),char(7),char(0),char(120),char(1),char(7),char(0),char(-85),char(0),char(7),char(0),char(121),char(1),char(4),char(0),char(122),char(1),
-char(13),char(0),char(123),char(1),char(4),char(0),char(124),char(1),char(4),char(0),char(125),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(53),char(0),
-char(92),char(0),char(19),char(0),char(50),char(0),char(-68),char(0),char(89),char(0),char(127),char(1),char(82),char(0),char(-128),char(1),char(83),char(0),char(-127),char(1),
-char(84),char(0),char(-126),char(1),char(85),char(0),char(-125),char(1),char(86),char(0),char(-124),char(1),char(87),char(0),char(-123),char(1),char(90),char(0),char(-122),char(1),
-char(91),char(0),char(-121),char(1),char(4),char(0),char(-120),char(1),char(4),char(0),char(102),char(1),char(4),char(0),char(-119),char(1),char(4),char(0),char(-118),char(1),
-char(4),char(0),char(-117),char(1),char(4),char(0),char(-116),char(1),char(4),char(0),char(-115),char(1),char(4),char(0),char(-114),char(1),char(88),char(0),char(-113),char(1),
-char(93),char(0),char(28),char(0),char(16),char(0),char(-112),char(1),char(14),char(0),char(-111),char(1),char(14),char(0),char(-110),char(1),char(14),char(0),char(-109),char(1),
-char(14),char(0),char(-108),char(1),char(14),char(0),char(-107),char(1),char(14),char(0),char(-106),char(1),char(14),char(0),char(-105),char(1),char(14),char(0),char(-104),char(1),
-char(14),char(0),char(-103),char(1),char(8),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(4),char(0),char(-100),char(1),
-char(4),char(0),char(-99),char(1),char(8),char(0),char(-98),char(1),char(8),char(0),char(-97),char(1),char(8),char(0),char(-96),char(1),char(8),char(0),char(-95),char(1),
-char(8),char(0),char(-94),char(1),char(8),char(0),char(-93),char(1),char(8),char(0),char(-92),char(1),char(8),char(0),char(-91),char(1),char(8),char(0),char(-90),char(1),
-char(0),char(0),char(-89),char(1),char(0),char(0),char(-88),char(1),char(48),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(94),char(0),char(28),char(0),
-char(15),char(0),char(-112),char(1),char(13),char(0),char(-111),char(1),char(13),char(0),char(-110),char(1),char(13),char(0),char(-109),char(1),char(13),char(0),char(-108),char(1),
-char(13),char(0),char(-107),char(1),char(13),char(0),char(-106),char(1),char(13),char(0),char(-105),char(1),char(13),char(0),char(-104),char(1),char(13),char(0),char(-103),char(1),
-char(4),char(0),char(-100),char(1),char(7),char(0),char(-102),char(1),char(4),char(0),char(-101),char(1),char(4),char(0),char(126),char(1),char(7),char(0),char(-98),char(1),
-char(7),char(0),char(-97),char(1),char(7),char(0),char(-96),char(1),char(4),char(0),char(-99),char(1),char(7),char(0),char(-95),char(1),char(7),char(0),char(-94),char(1),
-char(7),char(0),char(-93),char(1),char(7),char(0),char(-92),char(1),char(7),char(0),char(-91),char(1),char(7),char(0),char(-90),char(1),char(0),char(0),char(-89),char(1),
-char(0),char(0),char(-88),char(1),char(50),char(0),char(-87),char(1),char(0),char(0),char(-86),char(1),char(95),char(0),char(11),char(0),char(14),char(0),char(-85),char(1),
-char(16),char(0),char(-84),char(1),char(14),char(0),char(-83),char(1),char(14),char(0),char(-82),char(1),char(14),char(0),char(-81),char(1),char(8),char(0),char(-80),char(1),
-char(4),char(0),char(-119),char(1),char(0),char(0),char(37),char(0),char(0),char(0),char(-79),char(1),char(93),char(0),char(-126),char(1),char(48),char(0),char(-78),char(1),
-char(96),char(0),char(10),char(0),char(13),char(0),char(-85),char(1),char(15),char(0),char(-84),char(1),char(13),char(0),char(-83),char(1),char(13),char(0),char(-82),char(1),
-char(13),char(0),char(-81),char(1),char(7),char(0),char(-80),char(1),char(4),char(0),char(-119),char(1),char(0),char(0),char(-79),char(1),char(94),char(0),char(-126),char(1),
-char(50),char(0),char(-78),char(1),char(97),char(0),char(4),char(0),char(50),char(0),char(-77),char(1),char(96),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
-char(0),char(0),char(37),char(0),char(98),char(0),char(4),char(0),char(48),char(0),char(-77),char(1),char(95),char(0),char(-76),char(1),char(4),char(0),char(-75),char(1),
-char(0),char(0),char(37),char(0),};
-int sBulletDNAlen64= sizeof(sBulletDNAstr64);
diff --git a/thirdparty/bullet/LinearMath/btSpatialAlgebra.h b/thirdparty/bullet/LinearMath/btSpatialAlgebra.h
deleted file mode 100644
index 6ad67a1081..0000000000
--- a/thirdparty/bullet/LinearMath/btSpatialAlgebra.h
+++ /dev/null
@@ -1,389 +0,0 @@
-/*
-Copyright (c) 2003-2015 Erwin Coumans, Jakub Stepien
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-///These spatial algebra classes are used for btMultiBody,
-///see BulletDynamics/Featherstone
-
-#ifndef BT_SPATIAL_ALGEBRA_H
-#define BT_SPATIAL_ALGEBRA_H
-
-#include "btMatrix3x3.h"
-
-struct btSpatialForceVector
-{
- btVector3 m_topVec, m_bottomVec;
- //
- btSpatialForceVector() { setZero(); }
- btSpatialForceVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(linear), m_bottomVec(angular) {}
- btSpatialForceVector(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
- {
- setValue(ax, ay, az, lx, ly, lz);
- }
- //
- void setVector(const btVector3 &angular, const btVector3 &linear)
- {
- m_topVec = linear;
- m_bottomVec = angular;
- }
- void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
- {
- m_bottomVec.setValue(ax, ay, az);
- m_topVec.setValue(lx, ly, lz);
- }
- //
- void addVector(const btVector3 &angular, const btVector3 &linear)
- {
- m_topVec += linear;
- m_bottomVec += angular;
- }
- void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
- {
- m_bottomVec[0] += ax;
- m_bottomVec[1] += ay;
- m_bottomVec[2] += az;
- m_topVec[0] += lx;
- m_topVec[1] += ly;
- m_topVec[2] += lz;
- }
- //
- const btVector3 &getLinear() const { return m_topVec; }
- const btVector3 &getAngular() const { return m_bottomVec; }
- //
- void setLinear(const btVector3 &linear) { m_topVec = linear; }
- void setAngular(const btVector3 &angular) { m_bottomVec = angular; }
- //
- void addAngular(const btVector3 &angular) { m_bottomVec += angular; }
- void addLinear(const btVector3 &linear) { m_topVec += linear; }
- //
- void setZero()
- {
- m_topVec.setZero();
- m_bottomVec.setZero();
- }
- //
- btSpatialForceVector &operator+=(const btSpatialForceVector &vec)
- {
- m_topVec += vec.m_topVec;
- m_bottomVec += vec.m_bottomVec;
- return *this;
- }
- btSpatialForceVector &operator-=(const btSpatialForceVector &vec)
- {
- m_topVec -= vec.m_topVec;
- m_bottomVec -= vec.m_bottomVec;
- return *this;
- }
- btSpatialForceVector operator-(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec - vec.m_bottomVec, m_topVec - vec.m_topVec); }
- btSpatialForceVector operator+(const btSpatialForceVector &vec) const { return btSpatialForceVector(m_bottomVec + vec.m_bottomVec, m_topVec + vec.m_topVec); }
- btSpatialForceVector operator-() const { return btSpatialForceVector(-m_bottomVec, -m_topVec); }
- btSpatialForceVector operator*(const btScalar &s) const { return btSpatialForceVector(s * m_bottomVec, s * m_topVec); }
- //btSpatialForceVector & operator = (const btSpatialForceVector &vec) { m_topVec = vec.m_topVec; m_bottomVec = vec.m_bottomVec; return *this; }
-};
-
-struct btSpatialMotionVector
-{
- btVector3 m_topVec, m_bottomVec;
- //
- btSpatialMotionVector() { setZero(); }
- btSpatialMotionVector(const btVector3 &angular, const btVector3 &linear) : m_topVec(angular), m_bottomVec(linear) {}
- //
- void setVector(const btVector3 &angular, const btVector3 &linear)
- {
- m_topVec = angular;
- m_bottomVec = linear;
- }
- void setValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
- {
- m_topVec.setValue(ax, ay, az);
- m_bottomVec.setValue(lx, ly, lz);
- }
- //
- void addVector(const btVector3 &angular, const btVector3 &linear)
- {
- m_topVec += linear;
- m_bottomVec += angular;
- }
- void addValue(const btScalar &ax, const btScalar &ay, const btScalar &az, const btScalar &lx, const btScalar &ly, const btScalar &lz)
- {
- m_topVec[0] += ax;
- m_topVec[1] += ay;
- m_topVec[2] += az;
- m_bottomVec[0] += lx;
- m_bottomVec[1] += ly;
- m_bottomVec[2] += lz;
- }
- //
- const btVector3 &getAngular() const { return m_topVec; }
- const btVector3 &getLinear() const { return m_bottomVec; }
- //
- void setAngular(const btVector3 &angular) { m_topVec = angular; }
- void setLinear(const btVector3 &linear) { m_bottomVec = linear; }
- //
- void addAngular(const btVector3 &angular) { m_topVec += angular; }
- void addLinear(const btVector3 &linear) { m_bottomVec += linear; }
- //
- void setZero()
- {
- m_topVec.setZero();
- m_bottomVec.setZero();
- }
- //
- btScalar dot(const btSpatialForceVector &b) const
- {
- return m_bottomVec.dot(b.m_topVec) + m_topVec.dot(b.m_bottomVec);
- }
- //
- template <typename SpatialVectorType>
- void cross(const SpatialVectorType &b, SpatialVectorType &out) const
- {
- out.m_topVec = m_topVec.cross(b.m_topVec);
- out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
- }
- template <typename SpatialVectorType>
- SpatialVectorType cross(const SpatialVectorType &b) const
- {
- SpatialVectorType out;
- out.m_topVec = m_topVec.cross(b.m_topVec);
- out.m_bottomVec = m_bottomVec.cross(b.m_topVec) + m_topVec.cross(b.m_bottomVec);
- return out;
- }
- //
- btSpatialMotionVector &operator+=(const btSpatialMotionVector &vec)
- {
- m_topVec += vec.m_topVec;
- m_bottomVec += vec.m_bottomVec;
- return *this;
- }
- btSpatialMotionVector &operator-=(const btSpatialMotionVector &vec)
- {
- m_topVec -= vec.m_topVec;
- m_bottomVec -= vec.m_bottomVec;
- return *this;
- }
- btSpatialMotionVector &operator*=(const btScalar &s)
- {
- m_topVec *= s;
- m_bottomVec *= s;
- return *this;
- }
- btSpatialMotionVector operator-(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec - vec.m_topVec, m_bottomVec - vec.m_bottomVec); }
- btSpatialMotionVector operator+(const btSpatialMotionVector &vec) const { return btSpatialMotionVector(m_topVec + vec.m_topVec, m_bottomVec + vec.m_bottomVec); }
- btSpatialMotionVector operator-() const { return btSpatialMotionVector(-m_topVec, -m_bottomVec); }
- btSpatialMotionVector operator*(const btScalar &s) const { return btSpatialMotionVector(s * m_topVec, s * m_bottomVec); }
-};
-
-struct btSymmetricSpatialDyad
-{
- btMatrix3x3 m_topLeftMat, m_topRightMat, m_bottomLeftMat;
- //
- btSymmetricSpatialDyad() { setIdentity(); }
- btSymmetricSpatialDyad(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat) { setMatrix(topLeftMat, topRightMat, bottomLeftMat); }
- //
- void setMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
- {
- m_topLeftMat = topLeftMat;
- m_topRightMat = topRightMat;
- m_bottomLeftMat = bottomLeftMat;
- }
- //
- void addMatrix(const btMatrix3x3 &topLeftMat, const btMatrix3x3 &topRightMat, const btMatrix3x3 &bottomLeftMat)
- {
- m_topLeftMat += topLeftMat;
- m_topRightMat += topRightMat;
- m_bottomLeftMat += bottomLeftMat;
- }
- //
- void setIdentity()
- {
- m_topLeftMat.setIdentity();
- m_topRightMat.setIdentity();
- m_bottomLeftMat.setIdentity();
- }
- //
- btSymmetricSpatialDyad &operator-=(const btSymmetricSpatialDyad &mat)
- {
- m_topLeftMat -= mat.m_topLeftMat;
- m_topRightMat -= mat.m_topRightMat;
- m_bottomLeftMat -= mat.m_bottomLeftMat;
- return *this;
- }
- //
- btSpatialForceVector operator*(const btSpatialMotionVector &vec)
- {
- return btSpatialForceVector(m_bottomLeftMat * vec.m_topVec + m_topLeftMat.transpose() * vec.m_bottomVec, m_topLeftMat * vec.m_topVec + m_topRightMat * vec.m_bottomVec);
- }
-};
-
-struct btSpatialTransformationMatrix
-{
- btMatrix3x3 m_rotMat; //btMatrix3x3 m_trnCrossMat;
- btVector3 m_trnVec;
- //
- enum eOutputOperation
- {
- None = 0,
- Add = 1,
- Subtract = 2
- };
- //
- template <typename SpatialVectorType>
- void transform(const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
- {
- if (outOp == None)
- {
- outVec.m_topVec = m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec = -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
- }
- else if (outOp == Add)
- {
- outVec.m_topVec += m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec += -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
- }
- else if (outOp == Subtract)
- {
- outVec.m_topVec -= m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec -= -m_trnVec.cross(outVec.m_topVec) + m_rotMat * inVec.m_bottomVec;
- }
- }
-
- template <typename SpatialVectorType>
- void transformRotationOnly(const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
- {
- if (outOp == None)
- {
- outVec.m_topVec = m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec = m_rotMat * inVec.m_bottomVec;
- }
- else if (outOp == Add)
- {
- outVec.m_topVec += m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec += m_rotMat * inVec.m_bottomVec;
- }
- else if (outOp == Subtract)
- {
- outVec.m_topVec -= m_rotMat * inVec.m_topVec;
- outVec.m_bottomVec -= m_rotMat * inVec.m_bottomVec;
- }
- }
-
- template <typename SpatialVectorType>
- void transformInverse(const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
- {
- if (outOp == None)
- {
- outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec = m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
- }
- else if (outOp == Add)
- {
- outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec += m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
- }
- else if (outOp == Subtract)
- {
- outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec -= m_rotMat.transpose() * (inVec.m_bottomVec + m_trnVec.cross(inVec.m_topVec));
- }
- }
-
- template <typename SpatialVectorType>
- void transformInverseRotationOnly(const SpatialVectorType &inVec,
- SpatialVectorType &outVec,
- eOutputOperation outOp = None)
- {
- if (outOp == None)
- {
- outVec.m_topVec = m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec = m_rotMat.transpose() * inVec.m_bottomVec;
- }
- else if (outOp == Add)
- {
- outVec.m_topVec += m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec += m_rotMat.transpose() * inVec.m_bottomVec;
- }
- else if (outOp == Subtract)
- {
- outVec.m_topVec -= m_rotMat.transpose() * inVec.m_topVec;
- outVec.m_bottomVec -= m_rotMat.transpose() * inVec.m_bottomVec;
- }
- }
-
- void transformInverse(const btSymmetricSpatialDyad &inMat,
- btSymmetricSpatialDyad &outMat,
- eOutputOperation outOp = None)
- {
- const btMatrix3x3 r_cross(0, -m_trnVec[2], m_trnVec[1],
- m_trnVec[2], 0, -m_trnVec[0],
- -m_trnVec[1], m_trnVec[0], 0);
-
- if (outOp == None)
- {
- outMat.m_topLeftMat = m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
- outMat.m_topRightMat = m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
- outMat.m_bottomLeftMat = m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
- }
- else if (outOp == Add)
- {
- outMat.m_topLeftMat += m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
- outMat.m_topRightMat += m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
- outMat.m_bottomLeftMat += m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
- }
- else if (outOp == Subtract)
- {
- outMat.m_topLeftMat -= m_rotMat.transpose() * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) * m_rotMat;
- outMat.m_topRightMat -= m_rotMat.transpose() * inMat.m_topRightMat * m_rotMat;
- outMat.m_bottomLeftMat -= m_rotMat.transpose() * (r_cross * (inMat.m_topLeftMat - inMat.m_topRightMat * r_cross) + inMat.m_bottomLeftMat - inMat.m_topLeftMat.transpose() * r_cross) * m_rotMat;
- }
- }
-
- template <typename SpatialVectorType>
- SpatialVectorType operator*(const SpatialVectorType &vec)
- {
- SpatialVectorType out;
- transform(vec, out);
- return out;
- }
-};
-
-template <typename SpatialVectorType>
-void symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b, btSymmetricSpatialDyad &out)
-{
- //output op maybe?
-
- out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
- out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
- out.m_topLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
- //maybe simple a*spatTranspose(a) would be nicer?
-}
-
-template <typename SpatialVectorType>
-btSymmetricSpatialDyad symmetricSpatialOuterProduct(const SpatialVectorType &a, const SpatialVectorType &b)
-{
- btSymmetricSpatialDyad out;
-
- out.m_topLeftMat = outerProduct(a.m_topVec, b.m_bottomVec);
- out.m_topRightMat = outerProduct(a.m_topVec, b.m_topVec);
- out.m_bottomLeftMat = outerProduct(a.m_bottomVec, b.m_bottomVec);
-
- return out;
- //maybe simple a*spatTranspose(a) would be nicer?
-}
-
-#endif //BT_SPATIAL_ALGEBRA_H
diff --git a/thirdparty/bullet/LinearMath/btStackAlloc.h b/thirdparty/bullet/LinearMath/btStackAlloc.h
deleted file mode 100644
index 3fc2084976..0000000000
--- a/thirdparty/bullet/LinearMath/btStackAlloc.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-/*
-StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
-Nov.2006
-*/
-
-#ifndef BT_STACK_ALLOC
-#define BT_STACK_ALLOC
-
-#include "btScalar.h" //for btAssert
-#include "btAlignedAllocator.h"
-
-///The btBlock class is an internal structure for the btStackAlloc memory allocator.
-struct btBlock
-{
- btBlock* previous;
- unsigned char* address;
-};
-
-///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
-class btStackAlloc
-{
-public:
- btStackAlloc(unsigned int size)
- {
- ctor();
- create(size);
- }
- ~btStackAlloc() { destroy(); }
-
- inline void create(unsigned int size)
- {
- destroy();
- data = (unsigned char*)btAlignedAlloc(size, 16);
- totalsize = size;
- }
- inline void destroy()
- {
- btAssert(usedsize == 0);
- //Raise(L"StackAlloc is still in use");
-
- if (usedsize == 0)
- {
- if (!ischild && data)
- btAlignedFree(data);
-
- data = 0;
- usedsize = 0;
- }
- }
-
- int getAvailableMemory() const
- {
- return static_cast<int>(totalsize - usedsize);
- }
-
- unsigned char* allocate(unsigned int size)
- {
- const unsigned int nus(usedsize + size);
- if (nus < totalsize)
- {
- usedsize = nus;
- return (data + (usedsize - size));
- }
- btAssert(0);
- //&& (L"Not enough memory"));
-
- return (0);
- }
- SIMD_FORCE_INLINE btBlock* beginBlock()
- {
- btBlock* pb = (btBlock*)allocate(sizeof(btBlock));
- pb->previous = current;
- pb->address = data + usedsize;
- current = pb;
- return (pb);
- }
- SIMD_FORCE_INLINE void endBlock(btBlock* block)
- {
- btAssert(block == current);
- //Raise(L"Unmatched blocks");
- if (block == current)
- {
- current = block->previous;
- usedsize = (unsigned int)((block->address - data) - sizeof(btBlock));
- }
- }
-
-private:
- void ctor()
- {
- data = 0;
- totalsize = 0;
- usedsize = 0;
- current = 0;
- ischild = false;
- }
- unsigned char* data;
- unsigned int totalsize;
- unsigned int usedsize;
- btBlock* current;
- bool ischild;
-};
-
-#endif //BT_STACK_ALLOC
diff --git a/thirdparty/bullet/LinearMath/btThreads.cpp b/thirdparty/bullet/LinearMath/btThreads.cpp
deleted file mode 100644
index 69a86799fa..0000000000
--- a/thirdparty/bullet/LinearMath/btThreads.cpp
+++ /dev/null
@@ -1,792 +0,0 @@
-/*
-Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#include "btThreads.h"
-#include "btQuickprof.h"
-#include <algorithm> // for min and max
-
-#if BT_USE_OPENMP && BT_THREADSAFE
-
-#include <omp.h>
-
-#endif // #if BT_USE_OPENMP && BT_THREADSAFE
-
-#if BT_USE_PPL && BT_THREADSAFE
-
-// use Microsoft Parallel Patterns Library (installed with Visual Studio 2010 and later)
-#include <ppl.h> // if you get a compile error here, check whether your version of Visual Studio includes PPL
-// Visual Studio 2010 and later should come with it
-#include <concrtrm.h> // for GetProcessorCount()
-
-#endif // #if BT_USE_PPL && BT_THREADSAFE
-
-#if BT_USE_TBB && BT_THREADSAFE
-
-// use Intel Threading Building Blocks for thread management
-#define __TBB_NO_IMPLICIT_LINKAGE 1
-#include <tbb/tbb.h>
-#include <tbb/task_scheduler_init.h>
-#include <tbb/parallel_for.h>
-#include <tbb/blocked_range.h>
-
-#endif // #if BT_USE_TBB && BT_THREADSAFE
-
-#if BT_THREADSAFE
-//
-// Lightweight spin-mutex based on atomics
-// Using ordinary system-provided mutexes like Windows critical sections was noticeably slower
-// presumably because when it fails to lock at first it would sleep the thread and trigger costly
-// context switching.
-//
-
-#if __cplusplus >= 201103L
-
-// for anything claiming full C++11 compliance, use C++11 atomics
-// on GCC or Clang you need to compile with -std=c++11
-#define USE_CPP11_ATOMICS 1
-
-#elif defined(_MSC_VER)
-
-// on MSVC, use intrinsics instead
-#define USE_MSVC_INTRINSICS 1
-
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))
-
-// available since GCC 4.7 and some versions of clang
-// todo: check for clang
-#define USE_GCC_BUILTIN_ATOMICS 1
-
-#elif defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
-
-// available since GCC 4.1
-#define USE_GCC_BUILTIN_ATOMICS_OLD 1
-
-#endif
-
-#if USE_CPP11_ATOMICS
-
-#include <atomic>
-#include <thread>
-
-#define THREAD_LOCAL_STATIC thread_local static
-
-bool btSpinMutex::tryLock()
-{
- std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
- int expected = 0;
- return std::atomic_compare_exchange_weak_explicit(aDest, &expected, int(1), std::memory_order_acq_rel, std::memory_order_acquire);
-}
-
-void btSpinMutex::lock()
-{
- // note: this lock does not sleep the thread.
- while (!tryLock())
- {
- // spin
- }
-}
-
-void btSpinMutex::unlock()
-{
- std::atomic<int>* aDest = reinterpret_cast<std::atomic<int>*>(&mLock);
- std::atomic_store_explicit(aDest, int(0), std::memory_order_release);
-}
-
-#elif USE_MSVC_INTRINSICS
-
-#define WIN32_LEAN_AND_MEAN
-
-#include <windows.h>
-#include <intrin.h>
-
-#define THREAD_LOCAL_STATIC __declspec(thread) static
-
-bool btSpinMutex::tryLock()
-{
- volatile long* aDest = reinterpret_cast<long*>(&mLock);
- return (0 == _InterlockedCompareExchange(aDest, 1, 0));
-}
-
-void btSpinMutex::lock()
-{
- // note: this lock does not sleep the thread
- while (!tryLock())
- {
- // spin
- }
-}
-
-void btSpinMutex::unlock()
-{
- volatile long* aDest = reinterpret_cast<long*>(&mLock);
- _InterlockedExchange(aDest, 0);
-}
-
-#elif USE_GCC_BUILTIN_ATOMICS
-
-#define THREAD_LOCAL_STATIC static __thread
-
-bool btSpinMutex::tryLock()
-{
- int expected = 0;
- bool weak = false;
- const int memOrderSuccess = __ATOMIC_ACQ_REL;
- const int memOrderFail = __ATOMIC_ACQUIRE;
- return __atomic_compare_exchange_n(&mLock, &expected, int(1), weak, memOrderSuccess, memOrderFail);
-}
-
-void btSpinMutex::lock()
-{
- // note: this lock does not sleep the thread
- while (!tryLock())
- {
- // spin
- }
-}
-
-void btSpinMutex::unlock()
-{
- __atomic_store_n(&mLock, int(0), __ATOMIC_RELEASE);
-}
-
-#elif USE_GCC_BUILTIN_ATOMICS_OLD
-
-#define THREAD_LOCAL_STATIC static __thread
-
-bool btSpinMutex::tryLock()
-{
- return __sync_bool_compare_and_swap(&mLock, int(0), int(1));
-}
-
-void btSpinMutex::lock()
-{
- // note: this lock does not sleep the thread
- while (!tryLock())
- {
- // spin
- }
-}
-
-void btSpinMutex::unlock()
-{
- // write 0
- __sync_fetch_and_and(&mLock, int(0));
-}
-
-#else //#elif USE_MSVC_INTRINSICS
-
-#error "no threading primitives defined -- unknown platform"
-
-#endif //#else //#elif USE_MSVC_INTRINSICS
-
-#else //#if BT_THREADSAFE
-
-// These should not be called ever
-void btSpinMutex::lock()
-{
- btAssert(!"unimplemented btSpinMutex::lock() called");
-}
-
-void btSpinMutex::unlock()
-{
- btAssert(!"unimplemented btSpinMutex::unlock() called");
-}
-
-bool btSpinMutex::tryLock()
-{
- btAssert(!"unimplemented btSpinMutex::tryLock() called");
- return true;
-}
-
-#define THREAD_LOCAL_STATIC static
-
-#endif // #else //#if BT_THREADSAFE
-
-struct ThreadsafeCounter
-{
- unsigned int mCounter;
- btSpinMutex mMutex;
-
- ThreadsafeCounter()
- {
- mCounter = 0;
- --mCounter; // first count should come back 0
- }
-
- unsigned int getNext()
- {
- // no need to optimize this with atomics, it is only called ONCE per thread!
- mMutex.lock();
- mCounter++;
- if (mCounter >= BT_MAX_THREAD_COUNT)
- {
- btAssert(!"thread counter exceeded");
- // wrap back to the first worker index
- mCounter = 1;
- }
- unsigned int val = mCounter;
- mMutex.unlock();
- return val;
- }
-};
-
-static btITaskScheduler* gBtTaskScheduler=0;
-static int gThreadsRunningCounter = 0; // useful for detecting if we are trying to do nested parallel-for calls
-static btSpinMutex gThreadsRunningCounterMutex;
-static ThreadsafeCounter gThreadCounter;
-
-//
-// BT_DETECT_BAD_THREAD_INDEX tries to detect when there are multiple threads assigned the same thread index.
-//
-// BT_DETECT_BAD_THREAD_INDEX is a developer option to test if
-// certain assumptions about how the task scheduler manages its threads
-// holds true.
-// The main assumption is:
-// - when the threadpool is resized, the task scheduler either
-// 1. destroys all worker threads and creates all new ones in the correct number, OR
-// 2. never destroys a worker thread
-//
-// We make that assumption because we can't easily enumerate the worker threads of a task scheduler
-// to assign nice sequential thread-indexes. We also do not get notified if a worker thread is destroyed,
-// so we can't tell when a thread-index is no longer being used.
-// We allocate thread-indexes as needed with a sequential global thread counter.
-//
-// Our simple thread-counting scheme falls apart if the task scheduler destroys some threads but
-// continues to re-use other threads and the application repeatedly resizes the thread pool of the
-// task scheduler.
-// In order to prevent the thread-counter from exceeding the global max (BT_MAX_THREAD_COUNT), we
-// wrap the thread counter back to 1. This should only happen if the worker threads have all been
-// destroyed and re-created.
-//
-// BT_DETECT_BAD_THREAD_INDEX only works for Win32 right now,
-// but could be adapted to work with pthreads
-#define BT_DETECT_BAD_THREAD_INDEX 0
-
-#if BT_DETECT_BAD_THREAD_INDEX
-
-typedef DWORD ThreadId_t;
-const static ThreadId_t kInvalidThreadId = 0;
-ThreadId_t gDebugThreadIds[BT_MAX_THREAD_COUNT];
-
-static ThreadId_t getDebugThreadId()
-{
- return GetCurrentThreadId();
-}
-
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
-
-// return a unique index per thread, main thread is 0, worker threads are in [1, BT_MAX_THREAD_COUNT)
-unsigned int btGetCurrentThreadIndex()
-{
- const unsigned int kNullIndex = ~0U;
- THREAD_LOCAL_STATIC unsigned int sThreadIndex = kNullIndex;
- if (sThreadIndex == kNullIndex)
- {
- sThreadIndex = gThreadCounter.getNext();
- btAssert(sThreadIndex < BT_MAX_THREAD_COUNT);
- }
-#if BT_DETECT_BAD_THREAD_INDEX
- if (gBtTaskScheduler && sThreadIndex > 0)
- {
- ThreadId_t tid = getDebugThreadId();
- // if not set
- if (gDebugThreadIds[sThreadIndex] == kInvalidThreadId)
- {
- // set it
- gDebugThreadIds[sThreadIndex] = tid;
- }
- else
- {
- if (gDebugThreadIds[sThreadIndex] != tid)
- {
- // this could indicate the task scheduler is breaking our assumptions about
- // how threads are managed when threadpool is resized
- btAssert(!"there are 2 or more threads with the same thread-index!");
- __debugbreak();
- }
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
- return sThreadIndex;
-}
-
-bool btIsMainThread()
-{
- return btGetCurrentThreadIndex() == 0;
-}
-
-void btResetThreadIndexCounter()
-{
- // for when all current worker threads are destroyed
- btAssert(btIsMainThread());
- gThreadCounter.mCounter = 0;
-}
-
-btITaskScheduler::btITaskScheduler(const char* name)
-{
- m_name = name;
- m_savedThreadCounter = 0;
- m_isActive = false;
-}
-
-void btITaskScheduler::activate()
-{
- // gThreadCounter is used to assign a thread-index to each worker thread in a task scheduler.
- // The main thread is always thread-index 0, and worker threads are numbered from 1 to 63 (BT_MAX_THREAD_COUNT-1)
- // The thread-indexes need to be unique amongst the threads that can be running simultaneously.
- // Since only one task scheduler can be used at a time, it is OK for a pair of threads that belong to different
- // task schedulers to share the same thread index because they can't be running at the same time.
- // So each task scheduler needs to keep its own thread counter value
- if (!m_isActive)
- {
- gThreadCounter.mCounter = m_savedThreadCounter; // restore saved thread counter
- m_isActive = true;
- }
-}
-
-void btITaskScheduler::deactivate()
-{
- if (m_isActive)
- {
- m_savedThreadCounter = gThreadCounter.mCounter; // save thread counter
- m_isActive = false;
- }
-}
-
-void btPushThreadsAreRunning()
-{
- gThreadsRunningCounterMutex.lock();
- gThreadsRunningCounter++;
- gThreadsRunningCounterMutex.unlock();
-}
-
-void btPopThreadsAreRunning()
-{
- gThreadsRunningCounterMutex.lock();
- gThreadsRunningCounter--;
- gThreadsRunningCounterMutex.unlock();
-}
-
-bool btThreadsAreRunning()
-{
- return gThreadsRunningCounter != 0;
-}
-
-void btSetTaskScheduler(btITaskScheduler* ts)
-{
- int threadId = btGetCurrentThreadIndex(); // make sure we call this on main thread at least once before any workers run
- if (threadId != 0)
- {
- btAssert(!"btSetTaskScheduler must be called from the main thread!");
- return;
- }
- if (gBtTaskScheduler)
- {
- // deactivate old task scheduler
- gBtTaskScheduler->deactivate();
- }
- gBtTaskScheduler = ts;
- if (ts)
- {
- // activate new task scheduler
- ts->activate();
- }
-}
-
-btITaskScheduler* btGetTaskScheduler()
-{
- return gBtTaskScheduler;
-}
-
-void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body)
-{
-#if BT_THREADSAFE
-
-#if BT_DETECT_BAD_THREAD_INDEX
- if (!btThreadsAreRunning())
- {
- // clear out thread ids
- for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
- {
- gDebugThreadIds[i] = kInvalidThreadId;
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
-
- btAssert(gBtTaskScheduler != NULL); // call btSetTaskScheduler() with a valid task scheduler first!
- gBtTaskScheduler->parallelFor(iBegin, iEnd, grainSize, body);
-
-#else // #if BT_THREADSAFE
-
- // non-parallel version of btParallelFor
- btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
- body.forLoop(iBegin, iEnd);
-
-#endif // #if BT_THREADSAFE
-}
-
-btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body)
-{
-#if BT_THREADSAFE
-
-#if BT_DETECT_BAD_THREAD_INDEX
- if (!btThreadsAreRunning())
- {
- // clear out thread ids
- for (int i = 0; i < BT_MAX_THREAD_COUNT; ++i)
- {
- gDebugThreadIds[i] = kInvalidThreadId;
- }
- }
-#endif // #if BT_DETECT_BAD_THREAD_INDEX
-
- btAssert(gBtTaskScheduler != NULL); // call btSetTaskScheduler() with a valid task scheduler first!
- return gBtTaskScheduler->parallelSum(iBegin, iEnd, grainSize, body);
-
-#else // #if BT_THREADSAFE
-
- // non-parallel version of btParallelSum
- btAssert(!"called btParallelFor in non-threadsafe build. enable BT_THREADSAFE");
- return body.sumLoop(iBegin, iEnd);
-
-#endif //#else // #if BT_THREADSAFE
-}
-
-///
-/// btTaskSchedulerSequential -- non-threaded implementation of task scheduler
-/// (really just useful for testing performance of single threaded vs multi)
-///
-class btTaskSchedulerSequential : public btITaskScheduler
-{
-public:
- btTaskSchedulerSequential() : btITaskScheduler("Sequential") {}
- virtual int getMaxNumThreads() const BT_OVERRIDE { return 1; }
- virtual int getNumThreads() const BT_OVERRIDE { return 1; }
- virtual void setNumThreads(int numThreads) BT_OVERRIDE {}
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_sequential");
- body.forLoop(iBegin, iEnd);
- }
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelSum_sequential");
- return body.sumLoop(iBegin, iEnd);
- }
-};
-
-#if BT_USE_OPENMP && BT_THREADSAFE
-///
-/// btTaskSchedulerOpenMP -- wrapper around OpenMP task scheduler
-///
-class btTaskSchedulerOpenMP : public btITaskScheduler
-{
- int m_numThreads;
-
-public:
- btTaskSchedulerOpenMP() : btITaskScheduler("OpenMP")
- {
- m_numThreads = 0;
- }
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return omp_get_max_threads();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads(int numThreads) BT_OVERRIDE
- {
- // With OpenMP, because it is a standard with various implementations, we can't
- // know for sure if every implementation has the same behavior of destroying all
- // previous threads when resizing the threadpool
- m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
- omp_set_num_threads(1); // hopefully, all previous threads get destroyed here
- omp_set_num_threads(m_numThreads);
- m_savedThreadCounter = 0;
- if (m_isActive)
- {
- btResetThreadIndexCounter();
- }
- }
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_OpenMP");
- btPushThreadsAreRunning();
-#pragma omp parallel for schedule(static, 1)
- for (int i = iBegin; i < iEnd; i += grainSize)
- {
- BT_PROFILE("OpenMP_forJob");
- body.forLoop(i, (std::min)(i + grainSize, iEnd));
- }
- btPopThreadsAreRunning();
- }
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_OpenMP");
- btPushThreadsAreRunning();
- btScalar sum = btScalar(0);
-#pragma omp parallel for schedule(static, 1) reduction(+ \
- : sum)
- for (int i = iBegin; i < iEnd; i += grainSize)
- {
- BT_PROFILE("OpenMP_sumJob");
- sum += body.sumLoop(i, (std::min)(i + grainSize, iEnd));
- }
- btPopThreadsAreRunning();
- return sum;
- }
-};
-#endif // #if BT_USE_OPENMP && BT_THREADSAFE
-
-#if BT_USE_TBB && BT_THREADSAFE
-///
-/// btTaskSchedulerTBB -- wrapper around Intel Threaded Building Blocks task scheduler
-///
-class btTaskSchedulerTBB : public btITaskScheduler
-{
- int m_numThreads;
- tbb::task_scheduler_init* m_tbbSchedulerInit;
-
-public:
- btTaskSchedulerTBB() : btITaskScheduler("IntelTBB")
- {
- m_numThreads = 0;
- m_tbbSchedulerInit = NULL;
- }
- ~btTaskSchedulerTBB()
- {
- if (m_tbbSchedulerInit)
- {
- delete m_tbbSchedulerInit;
- m_tbbSchedulerInit = NULL;
- }
- }
-
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return tbb::task_scheduler_init::default_num_threads();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads(int numThreads) BT_OVERRIDE
- {
- m_numThreads = (std::max)(1, (std::min)(int(BT_MAX_THREAD_COUNT), numThreads));
- if (m_tbbSchedulerInit)
- {
- // destroys all previous threads
- delete m_tbbSchedulerInit;
- m_tbbSchedulerInit = NULL;
- }
- m_tbbSchedulerInit = new tbb::task_scheduler_init(m_numThreads);
- m_savedThreadCounter = 0;
- if (m_isActive)
- {
- btResetThreadIndexCounter();
- }
- }
- struct ForBodyAdapter
- {
- const btIParallelForBody* mBody;
-
- ForBodyAdapter(const btIParallelForBody* body) : mBody(body) {}
- void operator()(const tbb::blocked_range<int>& range) const
- {
- BT_PROFILE("TBB_forJob");
- mBody->forLoop(range.begin(), range.end());
- }
- };
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_TBB");
- ForBodyAdapter tbbBody(&body);
- btPushThreadsAreRunning();
- tbb::parallel_for(tbb::blocked_range<int>(iBegin, iEnd, grainSize),
- tbbBody,
- tbb::simple_partitioner());
- btPopThreadsAreRunning();
- }
- struct SumBodyAdapter
- {
- const btIParallelSumBody* mBody;
- btScalar mSum;
-
- SumBodyAdapter(const btIParallelSumBody* body) : mBody(body), mSum(btScalar(0)) {}
- SumBodyAdapter(const SumBodyAdapter& src, tbb::split) : mBody(src.mBody), mSum(btScalar(0)) {}
- void join(const SumBodyAdapter& src) { mSum += src.mSum; }
- void operator()(const tbb::blocked_range<int>& range)
- {
- BT_PROFILE("TBB_sumJob");
- mSum += mBody->sumLoop(range.begin(), range.end());
- }
- };
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelSum_TBB");
- SumBodyAdapter tbbBody(&body);
- btPushThreadsAreRunning();
- tbb::parallel_deterministic_reduce(tbb::blocked_range<int>(iBegin, iEnd, grainSize), tbbBody);
- btPopThreadsAreRunning();
- return tbbBody.mSum;
- }
-};
-#endif // #if BT_USE_TBB && BT_THREADSAFE
-
-#if BT_USE_PPL && BT_THREADSAFE
-///
-/// btTaskSchedulerPPL -- wrapper around Microsoft Parallel Patterns Lib task scheduler
-///
-class btTaskSchedulerPPL : public btITaskScheduler
-{
- int m_numThreads;
- concurrency::combinable<btScalar> m_sum; // for parallelSum
-public:
- btTaskSchedulerPPL() : btITaskScheduler("PPL")
- {
- m_numThreads = 0;
- }
- virtual int getMaxNumThreads() const BT_OVERRIDE
- {
- return concurrency::GetProcessorCount();
- }
- virtual int getNumThreads() const BT_OVERRIDE
- {
- return m_numThreads;
- }
- virtual void setNumThreads(int numThreads) BT_OVERRIDE
- {
- // capping the thread count for PPL due to a thread-index issue
- const int maxThreadCount = (std::min)(int(BT_MAX_THREAD_COUNT), 31);
- m_numThreads = (std::max)(1, (std::min)(maxThreadCount, numThreads));
- using namespace concurrency;
- if (CurrentScheduler::Id() != -1)
- {
- CurrentScheduler::Detach();
- }
- SchedulerPolicy policy;
- {
- // PPL seems to destroy threads when threadpool is shrunk, but keeps reusing old threads
- // force it to destroy old threads
- policy.SetConcurrencyLimits(1, 1);
- CurrentScheduler::Create(policy);
- CurrentScheduler::Detach();
- }
- policy.SetConcurrencyLimits(m_numThreads, m_numThreads);
- CurrentScheduler::Create(policy);
- m_savedThreadCounter = 0;
- if (m_isActive)
- {
- btResetThreadIndexCounter();
- }
- }
- struct ForBodyAdapter
- {
- const btIParallelForBody* mBody;
- int mGrainSize;
- int mIndexEnd;
-
- ForBodyAdapter(const btIParallelForBody* body, int grainSize, int end) : mBody(body), mGrainSize(grainSize), mIndexEnd(end) {}
- void operator()(int i) const
- {
- BT_PROFILE("PPL_forJob");
- mBody->forLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
- }
- };
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelFor_PPL");
- // PPL dispatch
- ForBodyAdapter pplBody(&body, grainSize, iEnd);
- btPushThreadsAreRunning();
- // note: MSVC 2010 doesn't support partitioner args, so avoid them
- concurrency::parallel_for(iBegin,
- iEnd,
- grainSize,
- pplBody);
- btPopThreadsAreRunning();
- }
- struct SumBodyAdapter
- {
- const btIParallelSumBody* mBody;
- concurrency::combinable<btScalar>* mSum;
- int mGrainSize;
- int mIndexEnd;
-
- SumBodyAdapter(const btIParallelSumBody* body, concurrency::combinable<btScalar>* sum, int grainSize, int end) : mBody(body), mSum(sum), mGrainSize(grainSize), mIndexEnd(end) {}
- void operator()(int i) const
- {
- BT_PROFILE("PPL_sumJob");
- mSum->local() += mBody->sumLoop(i, (std::min)(i + mGrainSize, mIndexEnd));
- }
- };
- static btScalar sumFunc(btScalar a, btScalar b) { return a + b; }
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) BT_OVERRIDE
- {
- BT_PROFILE("parallelSum_PPL");
- m_sum.clear();
- SumBodyAdapter pplBody(&body, &m_sum, grainSize, iEnd);
- btPushThreadsAreRunning();
- // note: MSVC 2010 doesn't support partitioner args, so avoid them
- concurrency::parallel_for(iBegin,
- iEnd,
- grainSize,
- pplBody);
- btPopThreadsAreRunning();
- return m_sum.combine(sumFunc);
- }
-};
-#endif // #if BT_USE_PPL && BT_THREADSAFE
-
-// create a non-threaded task scheduler (always available)
-btITaskScheduler* btGetSequentialTaskScheduler()
-{
- static btTaskSchedulerSequential sTaskScheduler;
- return &sTaskScheduler;
-}
-
-// create an OpenMP task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetOpenMPTaskScheduler()
-{
-#if BT_USE_OPENMP && BT_THREADSAFE
- static btTaskSchedulerOpenMP sTaskScheduler;
- return &sTaskScheduler;
-#else
- return NULL;
-#endif
-}
-
-// create an Intel TBB task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetTBBTaskScheduler()
-{
-#if BT_USE_TBB && BT_THREADSAFE
- static btTaskSchedulerTBB sTaskScheduler;
- return &sTaskScheduler;
-#else
- return NULL;
-#endif
-}
-
-// create a PPL task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetPPLTaskScheduler()
-{
-#if BT_USE_PPL && BT_THREADSAFE
- static btTaskSchedulerPPL sTaskScheduler;
- return &sTaskScheduler;
-#else
- return NULL;
-#endif
-}
diff --git a/thirdparty/bullet/LinearMath/btThreads.h b/thirdparty/bullet/LinearMath/btThreads.h
deleted file mode 100644
index b2227e1724..0000000000
--- a/thirdparty/bullet/LinearMath/btThreads.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
-Copyright (c) 2003-2014 Erwin Coumans http://bullet.googlecode.com
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_THREADS_H
-#define BT_THREADS_H
-
-#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
-
-#if defined(_MSC_VER) && _MSC_VER >= 1600
-// give us a compile error if any signatures of overriden methods is changed
-#define BT_OVERRIDE override
-#endif
-
-#ifndef BT_OVERRIDE
-#define BT_OVERRIDE
-#endif
-
-// Don't set this to larger than 64, without modifying btThreadSupportPosix
-// and btThreadSupportWin32. They use UINT64 bit-masks.
-const unsigned int BT_MAX_THREAD_COUNT = 64; // only if BT_THREADSAFE is 1
-
-// for internal use only
-bool btIsMainThread();
-bool btThreadsAreRunning();
-unsigned int btGetCurrentThreadIndex();
-void btResetThreadIndexCounter(); // notify that all worker threads have been destroyed
-
-///
-/// btSpinMutex -- lightweight spin-mutex implemented with atomic ops, never puts
-/// a thread to sleep because it is designed to be used with a task scheduler
-/// which has one thread per core and the threads don't sleep until they
-/// run out of tasks. Not good for general purpose use.
-///
-class btSpinMutex
-{
- int mLock;
-
-public:
- btSpinMutex()
- {
- mLock = 0;
- }
- void lock();
- void unlock();
- bool tryLock();
-};
-
-//
-// NOTE: btMutex* is for internal Bullet use only
-//
-// If BT_THREADSAFE is undefined or 0, should optimize away to nothing.
-// This is good because for the single-threaded build of Bullet, any calls
-// to these functions will be optimized out.
-//
-// However, for users of the multi-threaded build of Bullet this is kind
-// of bad because if you call any of these functions from external code
-// (where BT_THREADSAFE is undefined) you will get unexpected race conditions.
-//
-SIMD_FORCE_INLINE void btMutexLock(btSpinMutex* mutex)
-{
-#if BT_THREADSAFE
- mutex->lock();
-#else
- (void)mutex;
-#endif // #if BT_THREADSAFE
-}
-
-SIMD_FORCE_INLINE void btMutexUnlock(btSpinMutex* mutex)
-{
-#if BT_THREADSAFE
- mutex->unlock();
-#else
- (void)mutex;
-#endif // #if BT_THREADSAFE
-}
-
-SIMD_FORCE_INLINE bool btMutexTryLock(btSpinMutex* mutex)
-{
-#if BT_THREADSAFE
- return mutex->tryLock();
-#else
- (void)mutex;
- return true;
-#endif // #if BT_THREADSAFE
-}
-
-//
-// btIParallelForBody -- subclass this to express work that can be done in parallel
-//
-class btIParallelForBody
-{
-public:
- virtual ~btIParallelForBody() {}
- virtual void forLoop(int iBegin, int iEnd) const = 0;
-};
-
-//
-// btIParallelSumBody -- subclass this to express work that can be done in parallel
-// and produces a sum over all loop elements
-//
-class btIParallelSumBody
-{
-public:
- virtual ~btIParallelSumBody() {}
- virtual btScalar sumLoop(int iBegin, int iEnd) const = 0;
-};
-
-//
-// btITaskScheduler -- subclass this to implement a task scheduler that can dispatch work to
-// worker threads
-//
-class btITaskScheduler
-{
-public:
- btITaskScheduler(const char* name);
- virtual ~btITaskScheduler() {}
- const char* getName() const { return m_name; }
-
- virtual int getMaxNumThreads() const = 0;
- virtual int getNumThreads() const = 0;
- virtual void setNumThreads(int numThreads) = 0;
- virtual void parallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body) = 0;
- virtual btScalar parallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body) = 0;
- virtual void sleepWorkerThreadsHint() {} // hint the task scheduler that we may not be using these threads for a little while
-
- // internal use only
- virtual void activate();
- virtual void deactivate();
-
-protected:
- const char* m_name;
- unsigned int m_savedThreadCounter;
- bool m_isActive;
-};
-
-// set the task scheduler to use for all calls to btParallelFor()
-// NOTE: you must set this prior to using any of the multi-threaded "Mt" classes
-void btSetTaskScheduler(btITaskScheduler* ts);
-
-// get the current task scheduler
-btITaskScheduler* btGetTaskScheduler();
-
-// get non-threaded task scheduler (always available)
-btITaskScheduler* btGetSequentialTaskScheduler();
-
-// create a default task scheduler (Win32 or pthreads based)
-btITaskScheduler* btCreateDefaultTaskScheduler();
-
-// get OpenMP task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetOpenMPTaskScheduler();
-
-// get Intel TBB task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetTBBTaskScheduler();
-
-// get PPL task scheduler (if available, otherwise returns null)
-btITaskScheduler* btGetPPLTaskScheduler();
-
-// btParallelFor -- call this to dispatch work like a for-loop
-// (iterations may be done out of order, so no dependencies are allowed)
-void btParallelFor(int iBegin, int iEnd, int grainSize, const btIParallelForBody& body);
-
-// btParallelSum -- call this to dispatch work like a for-loop, returns the sum of all iterations
-// (iterations may be done out of order, so no dependencies are allowed)
-btScalar btParallelSum(int iBegin, int iEnd, int grainSize, const btIParallelSumBody& body);
-
-#endif
diff --git a/thirdparty/bullet/LinearMath/btTransform.h b/thirdparty/bullet/LinearMath/btTransform.h
deleted file mode 100644
index 6f2f99818c..0000000000
--- a/thirdparty/bullet/LinearMath/btTransform.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRANSFORM_H
-#define BT_TRANSFORM_H
-
-#include "btMatrix3x3.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btTransformData btTransformDoubleData
-#else
-#define btTransformData btTransformFloatData
-#endif
-
-/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
- *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
-ATTRIBUTE_ALIGNED16(class)
-btTransform
-{
- ///Storage for the rotation
- btMatrix3x3 m_basis;
- ///Storage for the translation
- btVector3 m_origin;
-
-public:
- /**@brief No initialization constructor */
- btTransform() {}
- /**@brief Constructor from btQuaternion (optional btVector3 )
- * @param q Rotation from quaternion
- * @param c Translation from Vector (default 0,0,0) */
- explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q,
- const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
- : m_basis(q),
- m_origin(c)
- {
- }
-
- /**@brief Constructor from btMatrix3x3 (optional btVector3)
- * @param b Rotation from Matrix
- * @param c Translation from Vector default (0,0,0)*/
- explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b,
- const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
- : m_basis(b),
- m_origin(c)
- {
- }
- /**@brief Copy constructor */
- SIMD_FORCE_INLINE btTransform(const btTransform& other)
- : m_basis(other.m_basis),
- m_origin(other.m_origin)
- {
- }
- /**@brief Assignment Operator */
- SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
- {
- m_basis = other.m_basis;
- m_origin = other.m_origin;
- return *this;
- }
-
- /**@brief Set the current transform as the value of the product of two transforms
- * @param t1 Transform 1
- * @param t2 Transform 2
- * This = Transform1 * Transform2 */
- SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2)
- {
- m_basis = t1.m_basis * t2.m_basis;
- m_origin = t1(t2.m_origin);
- }
-
- /* void multInverseLeft(const btTransform& t1, const btTransform& t2) {
- btVector3 v = t2.m_origin - t1.m_origin;
- m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
- m_origin = v * t1.m_basis;
- }
- */
-
- /**@brief Return the transform of the vector */
- SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
- {
- return x.dot3(m_basis[0], m_basis[1], m_basis[2]) + m_origin;
- }
-
- /**@brief Return the transform of the vector */
- SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
- {
- return (*this)(x);
- }
-
- /**@brief Return the transform of the btQuaternion */
- SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
- {
- return getRotation() * q;
- }
-
- /**@brief Return the basis matrix for the rotation */
- SIMD_FORCE_INLINE btMatrix3x3& getBasis() { return m_basis; }
- /**@brief Return the basis matrix for the rotation */
- SIMD_FORCE_INLINE const btMatrix3x3& getBasis() const { return m_basis; }
-
- /**@brief Return the origin vector translation */
- SIMD_FORCE_INLINE btVector3& getOrigin() { return m_origin; }
- /**@brief Return the origin vector translation */
- SIMD_FORCE_INLINE const btVector3& getOrigin() const { return m_origin; }
-
- /**@brief Return a quaternion representing the rotation */
- btQuaternion getRotation() const
- {
- btQuaternion q;
- m_basis.getRotation(q);
- return q;
- }
-
- /**@brief Set from an array
- * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void setFromOpenGLMatrix(const btScalar* m)
- {
- m_basis.setFromOpenGLSubMatrix(m);
- m_origin.setValue(m[12], m[13], m[14]);
- }
-
- /**@brief Fill an array representation
- * @param m A pointer to a 16 element array (12 rotation(row major padded on the right by 1), and 3 translation */
- void getOpenGLMatrix(btScalar * m) const
- {
- m_basis.getOpenGLSubMatrix(m);
- m[12] = m_origin.x();
- m[13] = m_origin.y();
- m[14] = m_origin.z();
- m[15] = btScalar(1.0);
- }
-
- /**@brief Set the translational element
- * @param origin The vector to set the translation to */
- SIMD_FORCE_INLINE void setOrigin(const btVector3& origin)
- {
- m_origin = origin;
- }
-
- SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
-
- /**@brief Set the rotational element by btMatrix3x3 */
- SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
- {
- m_basis = basis;
- }
-
- /**@brief Set the rotational element by btQuaternion */
- SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
- {
- m_basis.setRotation(q);
- }
-
- /**@brief Set this transformation to the identity */
- void setIdentity()
- {
- m_basis.setIdentity();
- m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
- }
-
- /**@brief Multiply this Transform by another(this = this * another)
- * @param t The other transform */
- btTransform& operator*=(const btTransform& t)
- {
- m_origin += m_basis * t.m_origin;
- m_basis *= t.m_basis;
- return *this;
- }
-
- /**@brief Return the inverse of this transform */
- btTransform inverse() const
- {
- btMatrix3x3 inv = m_basis.transpose();
- return btTransform(inv, inv * -m_origin);
- }
-
- /**@brief Return the inverse of this transform times the other transform
- * @param t The other transform
- * return this.inverse() * the other */
- btTransform inverseTimes(const btTransform& t) const;
-
- /**@brief Return the product of this transform and the other */
- btTransform operator*(const btTransform& t) const;
-
- /**@brief Return an identity transform */
- static const btTransform& getIdentity()
- {
- static const btTransform identityTransform(btMatrix3x3::getIdentity());
- return identityTransform;
- }
-
- void serialize(struct btTransformData & dataOut) const;
-
- void serializeFloat(struct btTransformFloatData & dataOut) const;
-
- void deSerialize(const struct btTransformData& dataIn);
-
- void deSerializeDouble(const struct btTransformDoubleData& dataIn);
-
- void deSerializeFloat(const struct btTransformFloatData& dataIn);
-};
-
-SIMD_FORCE_INLINE btVector3
-btTransform::invXform(const btVector3& inVec) const
-{
- btVector3 v = inVec - m_origin;
- return (m_basis.transpose() * v);
-}
-
-SIMD_FORCE_INLINE btTransform
-btTransform::inverseTimes(const btTransform& t) const
-{
- btVector3 v = t.getOrigin() - m_origin;
- return btTransform(m_basis.transposeTimes(t.m_basis),
- v * m_basis);
-}
-
-SIMD_FORCE_INLINE btTransform
- btTransform::operator*(const btTransform& t) const
-{
- return btTransform(m_basis * t.m_basis,
- (*this)(t.m_origin));
-}
-
-/**@brief Test if two transforms have all elements equal */
-SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
-{
- return (t1.getBasis() == t2.getBasis() &&
- t1.getOrigin() == t2.getOrigin());
-}
-
-///for serialization
-struct btTransformFloatData
-{
- btMatrix3x3FloatData m_basis;
- btVector3FloatData m_origin;
-};
-
-struct btTransformDoubleData
-{
- btMatrix3x3DoubleData m_basis;
- btVector3DoubleData m_origin;
-};
-
-SIMD_FORCE_INLINE void btTransform::serialize(btTransformData& dataOut) const
-{
- m_basis.serialize(dataOut.m_basis);
- m_origin.serialize(dataOut.m_origin);
-}
-
-SIMD_FORCE_INLINE void btTransform::serializeFloat(btTransformFloatData& dataOut) const
-{
- m_basis.serializeFloat(dataOut.m_basis);
- m_origin.serializeFloat(dataOut.m_origin);
-}
-
-SIMD_FORCE_INLINE void btTransform::deSerialize(const btTransformData& dataIn)
-{
- m_basis.deSerialize(dataIn.m_basis);
- m_origin.deSerialize(dataIn.m_origin);
-}
-
-SIMD_FORCE_INLINE void btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
-{
- m_basis.deSerializeFloat(dataIn.m_basis);
- m_origin.deSerializeFloat(dataIn.m_origin);
-}
-
-SIMD_FORCE_INLINE void btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
-{
- m_basis.deSerializeDouble(dataIn.m_basis);
- m_origin.deSerializeDouble(dataIn.m_origin);
-}
-
-#endif //BT_TRANSFORM_H
diff --git a/thirdparty/bullet/LinearMath/btTransformUtil.h b/thirdparty/bullet/LinearMath/btTransformUtil.h
deleted file mode 100644
index b874dd6807..0000000000
--- a/thirdparty/bullet/LinearMath/btTransformUtil.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_TRANSFORM_UTIL_H
-#define BT_TRANSFORM_UTIL_H
-
-#include "btTransform.h"
-#define ANGULAR_MOTION_THRESHOLD btScalar(0.5) * SIMD_HALF_PI
-
-SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents, const btVector3& supportDir)
-{
- return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
- supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
- supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
-}
-
-/// Utils related to temporal transforms
-class btTransformUtil
-{
-public:
- static void integrateTransform(const btTransform& curTrans, const btVector3& linvel, const btVector3& angvel, btScalar timeStep, btTransform& predictedTransform)
- {
- predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
- // #define QUATERNION_DERIVATIVE
-#ifdef QUATERNION_DERIVATIVE
- btQuaternion predictedOrn = curTrans.getRotation();
- predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
- predictedOrn.safeNormalize();
-#else
- //Exponential map
- //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
-
- btVector3 axis;
- btScalar fAngle2 = angvel.length2();
- btScalar fAngle = 0;
- if (fAngle2 > SIMD_EPSILON)
- {
- fAngle = btSqrt(fAngle2);
- }
-
- //limit the angular motion
- if (fAngle * timeStep > ANGULAR_MOTION_THRESHOLD)
- {
- fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
- }
-
- if (fAngle < btScalar(0.001))
- {
- // use Taylor's expansions of sync function
- axis = angvel * (btScalar(0.5) * timeStep - (timeStep * timeStep * timeStep) * (btScalar(0.020833333333)) * fAngle * fAngle);
- }
- else
- {
- // sync(fAngle) = sin(c*fAngle)/t
- axis = angvel * (btSin(btScalar(0.5) * fAngle * timeStep) / fAngle);
- }
- btQuaternion dorn(axis.x(), axis.y(), axis.z(), btCos(fAngle * timeStep * btScalar(0.5)));
- btQuaternion orn0 = curTrans.getRotation();
-
- btQuaternion predictedOrn = dorn * orn0;
- predictedOrn.safeNormalize();
-#endif
- if (predictedOrn.length2() > SIMD_EPSILON)
- {
- predictedTransform.setRotation(predictedOrn);
- }
- else
- {
- predictedTransform.setBasis(curTrans.getBasis());
- }
- }
-
- static void calculateVelocityQuaternion(const btVector3& pos0, const btVector3& pos1, const btQuaternion& orn0, const btQuaternion& orn1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
- {
- linVel = (pos1 - pos0) / timeStep;
- btVector3 axis;
- btScalar angle;
- if (orn0 != orn1)
- {
- calculateDiffAxisAngleQuaternion(orn0, orn1, axis, angle);
- angVel = axis * angle / timeStep;
- }
- else
- {
- angVel.setValue(0, 0, 0);
- }
- }
-
- static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0, const btQuaternion& orn1a, btVector3& axis, btScalar& angle)
- {
- btQuaternion orn1 = orn0.nearest(orn1a);
- btQuaternion dorn = orn1 * orn0.inverse();
- angle = dorn.getAngle();
- axis = btVector3(dorn.x(), dorn.y(), dorn.z());
- axis[3] = btScalar(0.);
- //check for axis length
- btScalar len = axis.length2();
- if (len < SIMD_EPSILON * SIMD_EPSILON)
- axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
- else
- axis /= btSqrt(len);
- }
-
- static void calculateVelocity(const btTransform& transform0, const btTransform& transform1, btScalar timeStep, btVector3& linVel, btVector3& angVel)
- {
- linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
- btVector3 axis;
- btScalar angle;
- calculateDiffAxisAngle(transform0, transform1, axis, angle);
- angVel = axis * angle / timeStep;
- }
-
- static void calculateDiffAxisAngle(const btTransform& transform0, const btTransform& transform1, btVector3& axis, btScalar& angle)
- {
- btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
- btQuaternion dorn;
- dmat.getRotation(dorn);
-
- ///floating point inaccuracy can lead to w component > 1..., which breaks
- dorn.normalize();
-
- angle = dorn.getAngle();
- axis = btVector3(dorn.x(), dorn.y(), dorn.z());
- axis[3] = btScalar(0.);
- //check for axis length
- btScalar len = axis.length2();
- if (len < SIMD_EPSILON * SIMD_EPSILON)
- axis = btVector3(btScalar(1.), btScalar(0.), btScalar(0.));
- else
- axis /= btSqrt(len);
- }
-};
-
-///The btConvexSeparatingDistanceUtil can help speed up convex collision detection
-///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
-class btConvexSeparatingDistanceUtil
-{
- btQuaternion m_ornA;
- btQuaternion m_ornB;
- btVector3 m_posA;
- btVector3 m_posB;
-
- btVector3 m_separatingNormal;
-
- btScalar m_boundingRadiusA;
- btScalar m_boundingRadiusB;
- btScalar m_separatingDistance;
-
-public:
- btConvexSeparatingDistanceUtil(btScalar boundingRadiusA, btScalar boundingRadiusB)
- : m_boundingRadiusA(boundingRadiusA),
- m_boundingRadiusB(boundingRadiusB),
- m_separatingDistance(0.f)
- {
- }
-
- btScalar getConservativeSeparatingDistance()
- {
- return m_separatingDistance;
- }
-
- void updateSeparatingDistance(const btTransform& transA, const btTransform& transB)
- {
- const btVector3& toPosA = transA.getOrigin();
- const btVector3& toPosB = transB.getOrigin();
- btQuaternion toOrnA = transA.getRotation();
- btQuaternion toOrnB = transB.getRotation();
-
- if (m_separatingDistance > 0.f)
- {
- btVector3 linVelA, angVelA, linVelB, angVelB;
- btTransformUtil::calculateVelocityQuaternion(m_posA, toPosA, m_ornA, toOrnA, btScalar(1.), linVelA, angVelA);
- btTransformUtil::calculateVelocityQuaternion(m_posB, toPosB, m_ornB, toOrnB, btScalar(1.), linVelB, angVelB);
- btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
- btVector3 relLinVel = (linVelB - linVelA);
- btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
- if (relLinVelocLength < 0.f)
- {
- relLinVelocLength = 0.f;
- }
-
- btScalar projectedMotion = maxAngularProjectedVelocity + relLinVelocLength;
- m_separatingDistance -= projectedMotion;
- }
-
- m_posA = toPosA;
- m_posB = toPosB;
- m_ornA = toOrnA;
- m_ornB = toOrnB;
- }
-
- void initSeparatingDistance(const btVector3& separatingVector, btScalar separatingDistance, const btTransform& transA, const btTransform& transB)
- {
- m_separatingDistance = separatingDistance;
-
- if (m_separatingDistance > 0.f)
- {
- m_separatingNormal = separatingVector;
-
- const btVector3& toPosA = transA.getOrigin();
- const btVector3& toPosB = transB.getOrigin();
- btQuaternion toOrnA = transA.getRotation();
- btQuaternion toOrnB = transB.getRotation();
- m_posA = toPosA;
- m_posB = toPosB;
- m_ornA = toOrnA;
- m_ornB = toOrnB;
- }
- }
-};
-
-#endif //BT_TRANSFORM_UTIL_H
diff --git a/thirdparty/bullet/LinearMath/btVector3.cpp b/thirdparty/bullet/LinearMath/btVector3.cpp
deleted file mode 100644
index 13111157af..0000000000
--- a/thirdparty/bullet/LinearMath/btVector3.cpp
+++ /dev/null
@@ -1,1664 +0,0 @@
-/*
- Copyright (c) 2011 Apple Inc.
- http://continuousphysics.com/Bullet/
-
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
-
- This source version has been altered.
- */
-
-#if defined(_WIN32) || defined(__i386__)
-#define BT_USE_SSE_IN_API
-#endif
-
-#include "btVector3.h"
-
-#if defined BT_USE_SIMD_VECTOR3
-
-#if DEBUG
-#include <string.h> //for memset
-#endif
-
-#ifdef __APPLE__
-#include <stdint.h>
-typedef float float4 __attribute__((vector_size(16)));
-#else
-#define float4 __m128
-#endif
-//typedef uint32_t uint4 __attribute__ ((vector_size(16)));
-
-#if defined BT_USE_SSE || defined _WIN32
-
-#define LOG2_ARRAY_SIZE 6
-#define STACK_ARRAY_COUNT (1UL << LOG2_ARRAY_SIZE)
-
-#include <emmintrin.h>
-
-long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-long _maxdot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- const float4 *vertices = (const float4 *)vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
- float4 dotMax = btAssign128(-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY);
- float4 vvec = _mm_loadu_ps(vec);
- float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa)); /// zzzz
- float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
-
- long maxIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[STACK_ARRAY_COUNT];
-
-#if DEBUG
- //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
-#endif
-
- size_t index;
- float4 max;
- // Faster loop without cleanup code for full tiles
- for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
- {
- max = dotMax;
-
- for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new max
- if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
- {
- // copy the new max across all lanes of our max accumulator
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
-
- dotMax = max;
-
- // find first occurrence of that max
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
- {
- }
- // record where it is.
- maxIndex = 4 * index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- max = dotMax;
- index = 0;
-
- if (btUnlikely(count > 16))
- {
- for (; index + 4 <= count / 4; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
-
- // It is too costly to keep the index of the max here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4 * index;
- if (localCount)
- {
-#ifdef __APPLE__
- float4 t0, t1, t2, t3, t4;
- float4 *sap = &stack_array[index + localCount / 4];
- vertices += localCount; // counter the offset
- size_t byteIndex = -(localCount) * sizeof(float);
- //AT&T Code style assembly
- asm volatile(
- ".align 4 \n\
- 0: movaps %[max], %[t2] // move max out of the way to avoid propagating NaNs in max \n\
- movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
- movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
- movaps %[t0], %[max] // vertices[0] \n\
- movlhps %[t1], %[max] // x0y0x1y1 \n\
- movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
- movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
- mulps %[vLo], %[max] // x0y0x1y1 * vLo \n\
- movhlps %[t0], %[t1] // z0w0z1w1 \n\
- movaps %[t3], %[t0] // vertices[2] \n\
- movlhps %[t4], %[t0] // x2y2x3y3 \n\
- mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
- movhlps %[t3], %[t4] // z2w2z3w3 \n\
- shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
- mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
- movaps %[max], %[t3] // x0y0x1y1 * vLo \n\
- shufps $0x88, %[t0], %[max] // x0x1x2x3 * vLo.x \n\
- shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
- addps %[t3], %[max] // x + y \n\
- addps %[t1], %[max] // x + y + z \n\
- movaps %[max], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
- maxps %[t2], %[max] // record max, restore max \n\
- add $16, %[byteIndex] // advance loop counter\n\
- jnz 0b \n\
- "
- : [max] "+x"(max), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
- : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
- : "memory", "cc");
- index += localCount / 4;
-#else
- {
- for (unsigned int i = 0; i < localCount / 4; i++, index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
- }
- }
-#endif //__APPLE__
- }
-
- // process the last few points
- if (count & 3)
- {
- float4 v0, v1, v2, x, y, z;
- switch (count & 3)
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
- lo0 = lo0 * vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
- z = z * vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1 * vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy * vLo;
- z = _mm_shuffle_ps(z, z, 0xa8);
- x = _mm_shuffle_ps(xy, xy, 0xa8);
- y = _mm_shuffle_ps(xy, xy, 0xfd);
- z = z * vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps(xy, xy, 0xaa);
- xy = xy * vLo;
- z = z * vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- max = _mm_max_ps(x, max); // control the order here so that max is never NaN even if x is nan
- index++;
- }
-
- // if we found a new max.
- if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(max, dotMax)))
- { // we found a new max. Search for it
- // find max across the max vector, place in all elements of max -- big latency hit here
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0x4e));
- max = _mm_max_ps(max, (float4)_mm_shuffle_ps(max, max, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotMax = max;
-
- // scan for the first occurence of max in the array
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], max))); index++) // local_count must be a multiple of 4
- {
- }
- maxIndex = 4 * index + segment + indexTable[test];
- }
-
- _mm_store_ss(dotResult, dotMax);
- return maxIndex;
-}
-
-long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult);
-
-long _mindot_large(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- const float4 *vertices = (const float4 *)vv;
- static const unsigned char indexTable[16] = {(unsigned char)-1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0};
- float4 dotmin = btAssign128(BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY);
- float4 vvec = _mm_loadu_ps(vec);
- float4 vHi = btCastiTo128f(_mm_shuffle_epi32(btCastfTo128i(vvec), 0xaa)); /// zzzz
- float4 vLo = _mm_movelh_ps(vvec, vvec); /// xyxy
-
- long minIndex = -1L;
-
- size_t segment = 0;
- float4 stack_array[STACK_ARRAY_COUNT];
-
-#if DEBUG
- //memset( stack_array, -1, STACK_ARRAY_COUNT * sizeof(stack_array[0]) );
-#endif
-
- size_t index;
- float4 min;
- // Faster loop without cleanup code for full tiles
- for (segment = 0; segment + STACK_ARRAY_COUNT * 4 <= count; segment += STACK_ARRAY_COUNT * 4)
- {
- min = dotmin;
-
- for (index = 0; index < STACK_ARRAY_COUNT; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
-
- // If we found a new min
- if (0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
- {
- // copy the new min across all lanes of our min accumulator
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
-
- dotmin = min;
-
- // find first occurrence of that min
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
- {
- }
- // record where it is.
- minIndex = 4 * index + segment + indexTable[test];
- }
- }
-
- // account for work we've already done
- count -= segment;
-
- // Deal with the last < STACK_ARRAY_COUNT vectors
- min = dotmin;
- index = 0;
-
- if (btUnlikely(count > 16))
- {
- for (; index + 4 <= count / 4; index += 4)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 1] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 2] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
- v3 = vertices[3];
- vertices += 4;
-
- lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- z = _mm_shuffle_ps(hi0, hi1, 0x88);
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index + 3] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
-
- // It is too costly to keep the index of the min here. We will look for it again later. We save a lot of work this way.
- }
- }
-
- size_t localCount = (count & -4L) - 4 * index;
- if (localCount)
- {
-#ifdef __APPLE__
- vertices += localCount; // counter the offset
- float4 t0, t1, t2, t3, t4;
- size_t byteIndex = -(localCount) * sizeof(float);
- float4 *sap = &stack_array[index + localCount / 4];
-
- asm volatile(
- ".align 4 \n\
- 0: movaps %[min], %[t2] // move min out of the way to avoid propagating NaNs in min \n\
- movaps (%[vertices], %[byteIndex], 4), %[t0] // vertices[0] \n\
- movaps 16(%[vertices], %[byteIndex], 4), %[t1] // vertices[1] \n\
- movaps %[t0], %[min] // vertices[0] \n\
- movlhps %[t1], %[min] // x0y0x1y1 \n\
- movaps 32(%[vertices], %[byteIndex], 4), %[t3] // vertices[2] \n\
- movaps 48(%[vertices], %[byteIndex], 4), %[t4] // vertices[3] \n\
- mulps %[vLo], %[min] // x0y0x1y1 * vLo \n\
- movhlps %[t0], %[t1] // z0w0z1w1 \n\
- movaps %[t3], %[t0] // vertices[2] \n\
- movlhps %[t4], %[t0] // x2y2x3y3 \n\
- movhlps %[t3], %[t4] // z2w2z3w3 \n\
- mulps %[vLo], %[t0] // x2y2x3y3 * vLo \n\
- shufps $0x88, %[t4], %[t1] // z0z1z2z3 \n\
- mulps %[vHi], %[t1] // z0z1z2z3 * vHi \n\
- movaps %[min], %[t3] // x0y0x1y1 * vLo \n\
- shufps $0x88, %[t0], %[min] // x0x1x2x3 * vLo.x \n\
- shufps $0xdd, %[t0], %[t3] // y0y1y2y3 * vLo.y \n\
- addps %[t3], %[min] // x + y \n\
- addps %[t1], %[min] // x + y + z \n\
- movaps %[min], (%[sap], %[byteIndex]) // record result for later scrutiny \n\
- minps %[t2], %[min] // record min, restore min \n\
- add $16, %[byteIndex] // advance loop counter\n\
- jnz 0b \n\
- "
- : [min] "+x"(min), [t0] "=&x"(t0), [t1] "=&x"(t1), [t2] "=&x"(t2), [t3] "=&x"(t3), [t4] "=&x"(t4), [byteIndex] "+r"(byteIndex)
- : [vLo] "x"(vLo), [vHi] "x"(vHi), [vertices] "r"(vertices), [sap] "r"(sap)
- : "memory", "cc");
- index += localCount / 4;
-#else
- {
- for (unsigned int i = 0; i < localCount / 4; i++, index++)
- { // do four dot products at a time. Carefully avoid touching the w element.
- float4 v0 = vertices[0];
- float4 v1 = vertices[1];
- float4 v2 = vertices[2];
- float4 v3 = vertices[3];
- vertices += 4;
-
- float4 lo0 = _mm_movelh_ps(v0, v1); // x0y0x1y1
- float4 hi0 = _mm_movehl_ps(v1, v0); // z0?0z1?1
- float4 lo1 = _mm_movelh_ps(v2, v3); // x2y2x3y3
- float4 hi1 = _mm_movehl_ps(v3, v2); // z2?2z3?3
-
- lo0 = lo0 * vLo;
- lo1 = lo1 * vLo;
- float4 z = _mm_shuffle_ps(hi0, hi1, 0x88);
- float4 x = _mm_shuffle_ps(lo0, lo1, 0x88);
- float4 y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- z = z * vHi;
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that max is never NaN even if x is nan
- }
- }
-
-#endif
- }
-
- // process the last few points
- if (count & 3)
- {
- float4 v0, v1, v2, x, y, z;
- switch (count & 3)
- {
- case 3:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- v2 = vertices[2];
-
- // Calculate 3 dot products, transpose, duplicate v2
- float4 lo0 = _mm_movelh_ps(v0, v1); // xyxy.lo
- float4 hi0 = _mm_movehl_ps(v1, v0); // z?z?.lo
- lo0 = lo0 * vLo;
- z = _mm_shuffle_ps(hi0, v2, 0xa8); // z0z1z2z2
- z = z * vHi;
- float4 lo1 = _mm_movelh_ps(v2, v2); // xyxy
- lo1 = lo1 * vLo;
- x = _mm_shuffle_ps(lo0, lo1, 0x88);
- y = _mm_shuffle_ps(lo0, lo1, 0xdd);
- }
- break;
- case 2:
- {
- v0 = vertices[0];
- v1 = vertices[1];
- float4 xy = _mm_movelh_ps(v0, v1);
- z = _mm_movehl_ps(v1, v0);
- xy = xy * vLo;
- z = _mm_shuffle_ps(z, z, 0xa8);
- x = _mm_shuffle_ps(xy, xy, 0xa8);
- y = _mm_shuffle_ps(xy, xy, 0xfd);
- z = z * vHi;
- }
- break;
- case 1:
- {
- float4 xy = vertices[0];
- z = _mm_shuffle_ps(xy, xy, 0xaa);
- xy = xy * vLo;
- z = z * vHi;
- x = _mm_shuffle_ps(xy, xy, 0);
- y = _mm_shuffle_ps(xy, xy, 0x55);
- }
- break;
- }
- x = x + y;
- x = x + z;
- stack_array[index] = x;
- min = _mm_min_ps(x, min); // control the order here so that min is never NaN even if x is nan
- index++;
- }
-
- // if we found a new min.
- if (0 == segment || 0xf != _mm_movemask_ps((float4)_mm_cmpeq_ps(min, dotmin)))
- { // we found a new min. Search for it
- // find min across the min vector, place in all elements of min -- big latency hit here
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0x4e));
- min = _mm_min_ps(min, (float4)_mm_shuffle_ps(min, min, 0xb1));
-
- // It is slightly faster to do this part in scalar code when count < 8. However, the common case for
- // this where it actually makes a difference is handled in the early out at the top of the function,
- // so it is less than a 1% difference here. I opted for improved code size, fewer branches and reduced
- // complexity, and removed it.
-
- dotmin = min;
-
- // scan for the first occurence of min in the array
- size_t test;
- for (index = 0; 0 == (test = _mm_movemask_ps(_mm_cmpeq_ps(stack_array[index], min))); index++) // local_count must be a multiple of 4
- {
- }
- minIndex = 4 * index + segment + indexTable[test];
- }
-
- _mm_store_ss(dotResult, dotmin);
- return minIndex;
-}
-
-#elif defined BT_USE_NEON
-
-#define ARM_NEON_GCC_COMPATIBILITY 1
-#include <arm_neon.h>
-#include <sys/types.h>
-#include <sys/sysctl.h> //for sysctlbyname
-
-static long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult);
-static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult);
-
-long (*_maxdot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _maxdot_large_sel;
-long (*_mindot_large)(const float *vv, const float *vec, unsigned long count, float *dotResult) = _mindot_large_sel;
-
-static inline uint32_t btGetCpuCapabilities(void)
-{
- static uint32_t capabilities = 0;
- static bool testedCapabilities = false;
-
- if (0 == testedCapabilities)
- {
- uint32_t hasFeature = 0;
- size_t featureSize = sizeof(hasFeature);
- int err = sysctlbyname("hw.optional.neon_hpfp", &hasFeature, &featureSize, NULL, 0);
-
- if (0 == err && hasFeature)
- capabilities |= 0x2000;
-
- testedCapabilities = true;
- }
-
- return capabilities;
-}
-
-static long _maxdot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- if (btGetCpuCapabilities() & 0x2000)
- _maxdot_large = _maxdot_large_v1;
- else
- _maxdot_large = _maxdot_large_v0;
-
- return _maxdot_large(vv, vec, count, dotResult);
-}
-
-static long _mindot_large_sel(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- if (btGetCpuCapabilities() & 0x2000)
- _mindot_large = _mindot_large_v1;
- else
- _mindot_large = _mindot_large_v0;
-
- return _mindot_large(vv, vec, count, dotResult);
-}
-
-#if defined __arm__
-#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r; asm( "vld1.f32 {%0}, [%1, :128]!\n" : "=w" (_r), "+r" (_ptr) ); /*return*/ _r; })
-#else
-//support 64bit arm
-#define vld1q_f32_aligned_postincrement(_ptr) ({ float32x4_t _r = ((float32x4_t*)(_ptr))[0]; (_ptr) = (const float*) ((const char*)(_ptr) + 16L); /*return*/ _r; })
-#endif
-
-long _maxdot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMaxLo = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
- float32x2_t dotMaxHi = (float32x2_t){-BT_INFINITY, -BT_INFINITY};
- uint32x2_t indexLo = (uint32x2_t){0, 1};
- uint32x2_t indexHi = (uint32x2_t){2, 3};
- uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- const uint32x2_t four = (uint32x2_t){4, 4};
-
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- xy0 = vmul_f32(vget_low_f32(v0), vLo);
- xy1 = vmul_f32(vget_low_f32(v1), vLo);
- xy2 = vmul_f32(vget_low_f32(v2), vLo);
- xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32(z0.val[0], vHi);
- zHi = vmul_f32(z1.val[0], vHi);
-
- rLo = vpadd_f32(xy0, xy1);
- rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vcgt_f32(rLo, dotMaxLo);
- maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- uint32x2_t maskHi = vcgt_f32(rHi, dotMaxHi);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- dotMaxHi = vbsl_f32(maskHi, rHi, dotMaxHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32(z0, vHi);
- float32x2_t rLo = vpadd_f32(xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vcgt_f32(rLo, dotMaxLo);
- dotMaxLo = vbsl_f32(maskLo, rLo, dotMaxLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32(dotMaxHi, dotMaxLo);
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMaxHi = vdup_lane_f32(dotMaxLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vcgt_f32(dotMaxHi, dotMaxLo);
- dotMaxLo = vbsl_f32(mask, dotMaxHi, dotMaxLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32(dotMaxLo, 0);
- return vget_lane_u32(iLo, 0);
-}
-
-long _maxdot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
- uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- float32x4_t maxDot = (float32x4_t){-BT_INFINITY, -BT_INFINITY, -BT_INFINITY, -BT_INFINITY};
-
- unsigned long i = 0;
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32(z0, z1);
- z = vmulq_f32(zb.val[0], vHi);
- xy = vuzpq_f32(xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z0);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32(z, vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcgtq_f32(x, maxDot);
- maxDot = vbslq_f32(mask, x, maxDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vcgt_f32(vget_high_f32(maxDot), vget_low_f32(maxDot));
- float32x2_t maxDot2 = vbsl_f32(mask, vget_high_f32(maxDot), vget_low_f32(maxDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t maxDotO = vdup_lane_f32(maxDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vcgt_f32(maxDotO, maxDot2);
- maxDot2 = vbsl_f32(mask, maxDotO, maxDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32(maxDot2, 0);
- return vget_lane_u32(index2, 0);
-}
-
-long _mindot_large_v0(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- unsigned long i = 0;
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x2_t vLo = vget_low_f32(vvec);
- float32x2_t vHi = vdup_lane_f32(vget_high_f32(vvec), 0);
- float32x2_t dotMinLo = (float32x2_t){BT_INFINITY, BT_INFINITY};
- float32x2_t dotMinHi = (float32x2_t){BT_INFINITY, BT_INFINITY};
- uint32x2_t indexLo = (uint32x2_t){0, 1};
- uint32x2_t indexHi = (uint32x2_t){2, 3};
- uint32x2_t iLo = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- uint32x2_t iHi = (uint32x2_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- const uint32x2_t four = (uint32x2_t){4, 4};
-
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- xy0 = vmul_f32(vget_low_f32(v0), vLo);
- xy1 = vmul_f32(vget_low_f32(v1), vLo);
- xy2 = vmul_f32(vget_low_f32(v2), vLo);
- xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- zLo = vmul_f32(z0.val[0], vHi);
- zHi = vmul_f32(z1.val[0], vHi);
-
- rLo = vpadd_f32(xy0, xy1);
- rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- maskLo = vclt_f32(rLo, dotMinLo);
- maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
- float32x2_t xy3 = vmul_f32(vget_low_f32(v3), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2x2_t z1 = vtrn_f32(vget_high_f32(v2), vget_high_f32(v3));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(z1.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy3);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- indexLo = vadd_u32(indexLo, four);
- indexHi = vadd_u32(indexHi, four);
- }
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
- float32x2_t xy2 = vmul_f32(vget_low_f32(v2), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
- float32x2_t zHi = vmul_f32(vdup_lane_f32(vget_high_f32(v2), 0), vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- float32x2_t rHi = vpadd_f32(xy2, xy2);
- rLo = vadd_f32(rLo, zLo);
- rHi = vadd_f32(rHi, zHi);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- uint32x2_t maskHi = vclt_f32(rHi, dotMinHi);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- dotMinHi = vbsl_f32(maskHi, rHi, dotMinHi);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- iHi = vbsl_u32(maskHi, indexHi, iHi);
- }
- break;
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t xy1 = vmul_f32(vget_low_f32(v1), vLo);
-
- float32x2x2_t z0 = vtrn_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x2_t zLo = vmul_f32(z0.val[0], vHi);
-
- float32x2_t rLo = vpadd_f32(xy0, xy1);
- rLo = vadd_f32(rLo, zLo);
-
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x2_t xy0 = vmul_f32(vget_low_f32(v0), vLo);
- float32x2_t z0 = vdup_lane_f32(vget_high_f32(v0), 0);
- float32x2_t zLo = vmul_f32(z0, vHi);
- float32x2_t rLo = vpadd_f32(xy0, xy0);
- rLo = vadd_f32(rLo, zLo);
- uint32x2_t maskLo = vclt_f32(rLo, dotMinLo);
- dotMinLo = vbsl_f32(maskLo, rLo, dotMinLo);
- iLo = vbsl_u32(maskLo, indexLo, iLo);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32(dotMinHi, dotMinLo);
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- // select best answer between even and odd results
- dotMinHi = vdup_lane_f32(dotMinLo, 1);
- iHi = vdup_lane_u32(iLo, 1);
- mask = vclt_f32(dotMinHi, dotMinLo);
- dotMinLo = vbsl_f32(mask, dotMinHi, dotMinLo);
- iLo = vbsl_u32(mask, iHi, iLo);
-
- *dotResult = vget_lane_f32(dotMinLo, 0);
- return vget_lane_u32(iLo, 0);
-}
-
-long _mindot_large_v1(const float *vv, const float *vec, unsigned long count, float *dotResult)
-{
- float32x4_t vvec = vld1q_f32_aligned_postincrement(vec);
- float32x4_t vLo = vcombine_f32(vget_low_f32(vvec), vget_low_f32(vvec));
- float32x4_t vHi = vdupq_lane_f32(vget_high_f32(vvec), 0);
- const uint32x4_t four = (uint32x4_t){4, 4, 4, 4};
- uint32x4_t local_index = (uint32x4_t){0, 1, 2, 3};
- uint32x4_t index = (uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1)};
- float32x4_t minDot = (float32x4_t){BT_INFINITY, BT_INFINITY, BT_INFINITY, BT_INFINITY};
-
- unsigned long i = 0;
- for (; i + 8 <= count; i += 8)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
-
- v0 = vld1q_f32_aligned_postincrement(vv);
- v1 = vld1q_f32_aligned_postincrement(vv);
- v2 = vld1q_f32_aligned_postincrement(vv);
- v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- zb = vuzpq_f32(z0, z1);
- z = vmulq_f32(zb.val[0], vHi);
- xy = vuzpq_f32(xy0, xy1);
- x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- for (; i + 4 <= count; i += 4)
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v3 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v3));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v3));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
-
- switch (count & 3)
- {
- case 3:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v2 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- float32x4_t xy1 = vcombine_f32(vget_low_f32(v2), vget_low_f32(v2));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
- float32x4_t z1 = vcombine_f32(vget_high_f32(v2), vget_high_f32(v2));
-
- xy0 = vmulq_f32(xy0, vLo);
- xy1 = vmulq_f32(xy1, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z1);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy1);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 2:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
- float32x4_t v1 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v1));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z0 = vcombine_f32(vget_high_f32(v0), vget_high_f32(v1));
-
- xy0 = vmulq_f32(xy0, vLo);
-
- float32x4x2_t zb = vuzpq_f32(z0, z0);
- float32x4_t z = vmulq_f32(zb.val[0], vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- case 1:
- {
- float32x4_t v0 = vld1q_f32_aligned_postincrement(vv);
-
- // the next two lines should resolve to a single vswp d, d
- float32x4_t xy0 = vcombine_f32(vget_low_f32(v0), vget_low_f32(v0));
- // the next two lines should resolve to a single vswp d, d
- float32x4_t z = vdupq_lane_f32(vget_high_f32(v0), 0);
-
- xy0 = vmulq_f32(xy0, vLo);
-
- z = vmulq_f32(z, vHi);
- float32x4x2_t xy = vuzpq_f32(xy0, xy0);
- float32x4_t x = vaddq_f32(xy.val[0], xy.val[1]);
- x = vaddq_f32(x, z);
-
- uint32x4_t mask = vcltq_f32(x, minDot);
- minDot = vbslq_f32(mask, x, minDot);
- index = vbslq_u32(mask, local_index, index);
- local_index = vaddq_u32(local_index, four);
- }
- break;
-
- default:
- break;
- }
-
- // select best answer between hi and lo results
- uint32x2_t mask = vclt_f32(vget_high_f32(minDot), vget_low_f32(minDot));
- float32x2_t minDot2 = vbsl_f32(mask, vget_high_f32(minDot), vget_low_f32(minDot));
- uint32x2_t index2 = vbsl_u32(mask, vget_high_u32(index), vget_low_u32(index));
-
- // select best answer between even and odd results
- float32x2_t minDotO = vdup_lane_f32(minDot2, 1);
- uint32x2_t indexHi = vdup_lane_u32(index2, 1);
- mask = vclt_f32(minDotO, minDot2);
- minDot2 = vbsl_f32(mask, minDotO, minDot2);
- index2 = vbsl_u32(mask, indexHi, index2);
-
- *dotResult = vget_lane_f32(minDot2, 0);
- return vget_lane_u32(index2, 0);
-}
-
-#else
-#error Unhandled __APPLE__ arch
-#endif
-
-#endif /* __APPLE__ */
diff --git a/thirdparty/bullet/LinearMath/btVector3.h b/thirdparty/bullet/LinearMath/btVector3.h
deleted file mode 100644
index d65ed9808d..0000000000
--- a/thirdparty/bullet/LinearMath/btVector3.h
+++ /dev/null
@@ -1,1336 +0,0 @@
-/*
-Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BT_VECTOR3_H
-#define BT_VECTOR3_H
-
-//#include <stdint.h>
-#include "btScalar.h"
-#include "btMinMax.h"
-#include "btAlignedAllocator.h"
-
-#ifdef BT_USE_DOUBLE_PRECISION
-#define btVector3Data btVector3DoubleData
-#define btVector3DataName "btVector3DoubleData"
-#else
-#define btVector3Data btVector3FloatData
-#define btVector3DataName "btVector3FloatData"
-#endif //BT_USE_DOUBLE_PRECISION
-
-#if defined BT_USE_SSE
-
-//typedef uint32_t __m128i __attribute__ ((vector_size(16)));
-
-#ifdef _MSC_VER
-#pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
-#endif
-
-#define BT_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
-//#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
-#define bt_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
-#define bt_splat3_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, 3))
-#define bt_splat_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, _i))
-
-#define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define btvAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
-#define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
-#define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
-#define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
-#define btvxyzMaskf btvFFF0fMask
-#define btvAbsfMask btCastiTo128f(btvAbsMask)
-
-//there is an issue with XCode 3.2 (LCx errors)
-#define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f))
-#define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
-#define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
-#define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
-
-//const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
-//const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
-//const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
-//const __m128 ATTRIBUTE_ALIGNED16(v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
-
-#endif
-
-#ifdef BT_USE_NEON
-
-const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
-const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast<int32_t>(0xFFFFFFFF),
- static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
-const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
-const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
-
-#endif
-
-/**@brief btVector3 can be used to represent 3D points and vectors.
- * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
- * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
- */
-ATTRIBUTE_ALIGNED16(class)
-btVector3
-{
-public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
-
-#if defined(__SPU__) && defined(__CELLOS_LV2__)
- btScalar m_floats[4];
-
-public:
- SIMD_FORCE_INLINE const vec_float4& get128() const
- {
- return *((const vec_float4*)&m_floats[0]);
- }
-
-public:
-#else //__CELLOS_LV2__ __SPU__
-#if defined(BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
- union {
- btSimdFloat4 mVec128;
- btScalar m_floats[4];
- };
- SIMD_FORCE_INLINE btSimdFloat4 get128() const
- {
- return mVec128;
- }
- SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
- {
- mVec128 = v128;
- }
-#else
- btScalar m_floats[4];
-#endif
-#endif //__CELLOS_LV2__ __SPU__
-
-public:
- /**@brief No initialization constructor */
- SIMD_FORCE_INLINE btVector3()
- {
- }
-
- /**@brief Constructor from scalars
- * @param x X value
- * @param y Y value
- * @param z Z value
- */
- SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = btScalar(0.f);
- }
-
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- // Set Vector
- SIMD_FORCE_INLINE btVector3(btSimdFloat4 v)
- {
- mVec128 = v;
- }
-
- // Copy constructor
- SIMD_FORCE_INLINE btVector3(const btVector3& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- // Assignment Operator
- SIMD_FORCE_INLINE btVector3&
- operator=(const btVector3& v)
- {
- mVec128 = v.mVec128;
-
- return *this;
- }
-#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
-
- /**@brief Add a vector to this one
- * @param The vector to add to this one */
- SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_add_ps(mVec128, v.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vaddq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] += v.m_floats[0];
- m_floats[1] += v.m_floats[1];
- m_floats[2] += v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Subtract a vector from this one
- * @param The vector to subtract */
- SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_sub_ps(mVec128, v.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vsubq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] -= v.m_floats[0];
- m_floats[1] -= v.m_floats[1];
- m_floats[2] -= v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Scale the vector
- * @param s Scale factor */
- SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- mVec128 = _mm_mul_ps(mVec128, vs);
-#elif defined(BT_USE_NEON)
- mVec128 = vmulq_n_f32(mVec128, s);
-#else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
-#endif
- return *this;
- }
-
- /**@brief Inversely scale the vector
- * @param s Scale factor to divide by */
- SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
- {
- btFullAssert(s != btScalar(0.0));
-
-#if 0 //defined(BT_USE_SSE_IN_API)
-// this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(v1110, vs);
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
-
- mVec128 = _mm_mul_ps(mVec128, vs);
-
- return *this;
-#else
- return *this *= btScalar(1.0) / s;
-#endif
- }
-
- /**@brief Return the dot product
- * @param v The other vector in the dot product */
- SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
- return _mm_cvtss_f32(vd);
-#elif defined(BT_USE_NEON)
- float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
- x = vadd_f32(x, vget_high_f32(vd));
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * v.m_floats[0] +
- m_floats[1] * v.m_floats[1] +
- m_floats[2] * v.m_floats[2];
-#endif
- }
-
- /**@brief Return the length of the vector squared */
- SIMD_FORCE_INLINE btScalar length2() const
- {
- return dot(*this);
- }
-
- /**@brief Return the length of the vector */
- SIMD_FORCE_INLINE btScalar length() const
- {
- return btSqrt(length2());
- }
-
- /**@brief Return the norm (length) of the vector */
- SIMD_FORCE_INLINE btScalar norm() const
- {
- return length();
- }
-
- /**@brief Return the norm (length) of the vector */
- SIMD_FORCE_INLINE btScalar safeNorm() const
- {
- btScalar d = length2();
- //workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
- if (d > SIMD_EPSILON)
- return btSqrt(d);
- return btScalar(0);
- }
-
- /**@brief Return the distance squared between the ends of this and another vector
- * This is symantically treating the vector like a point */
- SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
-
- /**@brief Return the distance between the ends of this and another vector
- * This is symantically treating the vector like a point */
- SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
-
- SIMD_FORCE_INLINE btVector3& safeNormalize()
- {
- btScalar l2 = length2();
- //triNormal.normalize();
- if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
- {
- (*this) /= btSqrt(l2);
- }
- else
- {
- setValue(1, 0, 0);
- }
- return *this;
- }
-
- /**@brief Normalize this vector
- * x^2 + y^2 + z^2 = 1 */
- SIMD_FORCE_INLINE btVector3& normalize()
- {
- btAssert(!fuzzyZero());
-
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- // dot product first
- __m128 vd = _mm_mul_ps(mVec128, mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
-
-#if 0
- vd = _mm_sqrt_ss(vd);
- vd = _mm_div_ss(v1110, vd);
- vd = bt_splat_ps(vd, 0x80);
- mVec128 = _mm_mul_ps(mVec128, vd);
-#else
-
- // NR step 1/sqrt(x) - vd is x, y is output
- y = _mm_rsqrt_ss(vd); // estimate
-
- // one step NR
- z = v1_5;
- vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
- //x2 = vd;
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
- z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
-
- y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
-
- y = bt_splat_ps(y, 0x80);
- mVec128 = _mm_mul_ps(mVec128, y);
-
-#endif
-
- return *this;
-#else
- return *this /= length();
-#endif
- }
-
- /**@brief Return a normalized version of this vector */
- SIMD_FORCE_INLINE btVector3 normalized() const;
-
- /**@brief Return a rotated version of this vector
- * @param wAxis The axis to rotate about
- * @param angle The angle to rotate by */
- SIMD_FORCE_INLINE btVector3 rotate(const btVector3& wAxis, const btScalar angle) const;
-
- /**@brief Return the angle between this and another vector
- * @param v The other vector */
- SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
- {
- btScalar s = btSqrt(length2() * v.length2());
- btFullAssert(s != btScalar(0.0));
- return btAcos(dot(v) / s);
- }
-
- /**@brief Return a vector with the absolute values of each element */
- SIMD_FORCE_INLINE btVector3 absolute() const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
-#elif defined(BT_USE_NEON)
- return btVector3(vabsq_f32(mVec128));
-#else
- return btVector3(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
- btFabs(m_floats[2]));
-#endif
- }
-
- /**@brief Return the cross product between this and another vector
- * @param v The other vector */
- SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 T, V;
-
- T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
- V = _mm_mul_ps(V, mVec128);
- T = _mm_mul_ps(T, v.mVec128);
- V = _mm_sub_ps(V, T);
-
- V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
- return btVector3(V);
-#elif defined(BT_USE_NEON)
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(mVec128);
- float32x2_t Vlow = vget_low_f32(v.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
-
- V = vmulq_f32(V, mVec128);
- T = vmulq_f32(T, v.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
- V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
-
- return btVector3(V);
-#else
- return btVector3(
- m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
- m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
- m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
-#endif
- }
-
- SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- // cross:
- __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
-
- V = _mm_mul_ps(V, v1.mVec128);
- T = _mm_mul_ps(T, v2.mVec128);
- V = _mm_sub_ps(V, T);
-
- V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
-
- // dot:
- V = _mm_mul_ps(V, mVec128);
- __m128 z = _mm_movehl_ps(V, V);
- __m128 y = _mm_shuffle_ps(V, V, 0x55);
- V = _mm_add_ss(V, y);
- V = _mm_add_ss(V, z);
- return _mm_cvtss_f32(V);
-
-#elif defined(BT_USE_NEON)
- // cross:
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(v1.mVec128);
- float32x2_t Vlow = vget_low_f32(v2.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
-
- V = vmulq_f32(V, v1.mVec128);
- T = vmulq_f32(T, v2.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
-
- // dot:
- V = vmulq_f32(mVec128, V);
- float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
- x = vadd_f32(x, vget_high_f32(V));
- return vget_lane_f32(x, 0);
-#else
- return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
- m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
- m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
-#endif
- }
-
- /**@brief Return the axis with the smallest value
- * Note return values are 0,1,2 for x, y, or z */
- SIMD_FORCE_INLINE int minAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
- }
-
- /**@brief Return the axis with the largest value
- * Note return values are 0,1,2 for x, y, or z */
- SIMD_FORCE_INLINE int maxAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
- }
-
- SIMD_FORCE_INLINE int furthestAxis() const
- {
- return absolute().minAxis();
- }
-
- SIMD_FORCE_INLINE int closestAxis() const
- {
- return absolute().maxAxis();
- }
-
- SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
- btScalar s = btScalar(1.0) - rt;
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
- vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
- __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
- __m128 tmp3 = _mm_add_ps(r0, r1);
- mVec128 = tmp3;
-#elif defined(BT_USE_NEON)
- float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
- vl = vmulq_n_f32(vl, rt);
- mVec128 = vaddq_f32(vl, v0.mVec128);
-#else
- btScalar s = btScalar(1.0) - rt;
- m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
- m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
- m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
- //don't do the unused w component
- // m_co[3] = s * v0[3] + rt * v1[3];
-#endif
- }
-
- /**@brief Return the linear interpolation between this and another vector
- * @param v The other vector
- * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
- SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
- vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
- __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
- vl = _mm_mul_ps(vl, vt);
- vl = _mm_add_ps(vl, mVec128);
-
- return btVector3(vl);
-#elif defined(BT_USE_NEON)
- float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
- vl = vmulq_n_f32(vl, t);
- vl = vaddq_f32(vl, mVec128);
-
- return btVector3(vl);
-#else
- return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
-#endif
- }
-
- /**@brief Elementwise multiply this vector by the other
- * @param v The other vector */
- SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_mul_ps(mVec128, v.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vmulq_f32(mVec128, v.mVec128);
-#else
- m_floats[0] *= v.m_floats[0];
- m_floats[1] *= v.m_floats[1];
- m_floats[2] *= v.m_floats[2];
-#endif
- return *this;
- }
-
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
- /**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
- /**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
- /**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
- /**@brief Return the w value */
- SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
-
- //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
- //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
- ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
- SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
-
- SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
-#else
- return ((m_floats[3] == other.m_floats[3]) &&
- (m_floats[2] == other.m_floats[2]) &&
- (m_floats[1] == other.m_floats[1]) &&
- (m_floats[0] == other.m_floats[0]));
-#endif
- }
-
- SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
- {
- return !(*this == other);
- }
-
- /**@brief Set each element to the max of the current values and the values of another btVector3
- * @param other The other btVector3 to compare with
- */
- SIMD_FORCE_INLINE void setMax(const btVector3& other)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
-#else
- btSetMax(m_floats[0], other.m_floats[0]);
- btSetMax(m_floats[1], other.m_floats[1]);
- btSetMax(m_floats[2], other.m_floats[2]);
- btSetMax(m_floats[3], other.w());
-#endif
- }
-
- /**@brief Set each element to the min of the current values and the values of another btVector3
- * @param other The other btVector3 to compare with
- */
- SIMD_FORCE_INLINE void setMin(const btVector3& other)
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
-#elif defined(BT_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
-#else
- btSetMin(m_floats[0], other.m_floats[0]);
- btSetMin(m_floats[1], other.m_floats[1]);
- btSetMin(m_floats[2], other.m_floats[2]);
- btSetMin(m_floats[3], other.w());
-#endif
- }
-
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = btScalar(0.f);
- }
-
- void getSkewSymmetricMatrix(btVector3 * v0, btVector3 * v1, btVector3 * v2) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
-
- __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
- __m128 V0 = _mm_xor_ps(btvMzeroMask, V);
- __m128 V2 = _mm_movelh_ps(V0, V);
-
- __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
-
- V0 = _mm_shuffle_ps(V0, V, 0xDB);
- V2 = _mm_shuffle_ps(V2, V, 0xF9);
-
- v0->mVec128 = V0;
- v1->mVec128 = V1;
- v2->mVec128 = V2;
-#else
- v0->setValue(0., -z(), y());
- v1->setValue(z(), 0., -x());
- v2->setValue(-y(), x(), 0.);
-#endif
- }
-
- void setZero()
- {
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
-#elif defined(BT_USE_NEON)
- int32x4_t vi = vdupq_n_s32(0);
- mVec128 = vreinterpretq_f32_s32(vi);
-#else
- setValue(btScalar(0.), btScalar(0.), btScalar(0.));
-#endif
- }
-
- SIMD_FORCE_INLINE bool isZero() const
- {
- return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
- }
-
- SIMD_FORCE_INLINE bool fuzzyZero() const
- {
- return length2() < SIMD_EPSILON * SIMD_EPSILON;
- }
-
- SIMD_FORCE_INLINE void serialize(struct btVector3Data & dataOut) const;
-
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3DoubleData& dataIn);
-
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3FloatData& dataIn);
-
- SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData & dataOut) const;
-
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
-
- SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData & dataOut) const;
-
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
-
- /**@brief returns index of maximum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The maximum dot product */
- SIMD_FORCE_INLINE long maxDot(const btVector3* array, long array_count, btScalar& dotOut) const;
-
- /**@brief returns index of minimum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The minimum dot product */
- SIMD_FORCE_INLINE long minDot(const btVector3* array, long array_count, btScalar& dotOut) const;
-
- /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
- SIMD_FORCE_INLINE btVector3 dot3(const btVector3& v0, const btVector3& v1, const btVector3& v2) const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
-
- __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
- __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
- __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
- __m128 b0 = _mm_unpacklo_ps(a0, a1);
- __m128 b1 = _mm_unpackhi_ps(a0, a1);
- __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
- __m128 r = _mm_movelh_ps(b0, b2);
- r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
- a2 = _mm_and_ps(a2, btvxyzMaskf);
- r = _mm_add_ps(r, btCastdTo128f(_mm_move_sd(btCastfTo128d(a2), btCastfTo128d(b1))));
- return btVector3(r);
-
-#elif defined(BT_USE_NEON)
- static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
- float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
- float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
- float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
- float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
- a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
- float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
- float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
- return btVector3(vcombine_f32(b0, b1));
-#else
- return btVector3(dot(v0), dot(v1), dot(v2));
-#endif
- }
-};
-
-/**@brief Return the sum of two vectors (Point symantics)*/
-SIMD_FORCE_INLINE btVector3
-operator+(const btVector3& v1, const btVector3& v2)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
-#elif defined(BT_USE_NEON)
- return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
-#else
- return btVector3(
- v1.m_floats[0] + v2.m_floats[0],
- v1.m_floats[1] + v2.m_floats[1],
- v1.m_floats[2] + v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the elementwise product of two vectors */
-SIMD_FORCE_INLINE btVector3
-operator*(const btVector3& v1, const btVector3& v2)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
-#elif defined(BT_USE_NEON)
- return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
-#else
- return btVector3(
- v1.m_floats[0] * v2.m_floats[0],
- v1.m_floats[1] * v2.m_floats[1],
- v1.m_floats[2] * v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the difference between two vectors */
-SIMD_FORCE_INLINE btVector3
-operator-(const btVector3& v1, const btVector3& v2)
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
-
- // without _mm_and_ps this code causes slowdown in Concave moving
- __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
- return btVector3(_mm_and_ps(r, btvFFF0fMask));
-#elif defined(BT_USE_NEON)
- float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
- return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
-#else
- return btVector3(
- v1.m_floats[0] - v2.m_floats[0],
- v1.m_floats[1] - v2.m_floats[1],
- v1.m_floats[2] - v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the negative of the vector */
-SIMD_FORCE_INLINE btVector3
-operator-(const btVector3& v)
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
- return btVector3(_mm_and_ps(r, btvFFF0fMask));
-#elif defined(BT_USE_NEON)
- return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
-#else
- return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
-#endif
-}
-
-/**@brief Return the vector scaled by s */
-SIMD_FORCE_INLINE btVector3
-operator*(const btVector3& v, const btScalar& s)
-{
-#if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- return btVector3(_mm_mul_ps(v.mVec128, vs));
-#elif defined(BT_USE_NEON)
- float32x4_t r = vmulq_n_f32(v.mVec128, s);
- return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
-#else
- return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
-#endif
-}
-
-/**@brief Return the vector scaled by s */
-SIMD_FORCE_INLINE btVector3
-operator*(const btScalar& s, const btVector3& v)
-{
- return v * s;
-}
-
-/**@brief Return the vector inversely scaled by s */
-SIMD_FORCE_INLINE btVector3
-operator/(const btVector3& v, const btScalar& s)
-{
- btFullAssert(s != btScalar(0.0));
-#if 0 //defined(BT_USE_SSE_IN_API)
-// this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(v1110, vs);
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
-
- return btVector3(_mm_mul_ps(v.mVec128, vs));
-#else
- return v * (btScalar(1.0) / s);
-#endif
-}
-
-/**@brief Return the vector inversely scaled by s */
-SIMD_FORCE_INLINE btVector3
-operator/(const btVector3& v1, const btVector3& v2)
-{
-#if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
- vec = _mm_and_ps(vec, btvFFF0fMask);
- return btVector3(vec);
-#elif defined(BT_USE_NEON)
- float32x4_t x, y, v, m;
-
- x = v1.mVec128;
- y = v2.mVec128;
-
- v = vrecpeq_f32(y); // v ~ 1/y
- m = vrecpsq_f32(y, v); // m = (2-v*y)
- v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
- m = vrecpsq_f32(y, v); // mm = (2-vv*y)
- v = vmulq_f32(v, x); // x*vv
- v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
-
- return btVector3(v);
-#else
- return btVector3(
- v1.m_floats[0] / v2.m_floats[0],
- v1.m_floats[1] / v2.m_floats[1],
- v1.m_floats[2] / v2.m_floats[2]);
-#endif
-}
-
-/**@brief Return the dot product between two vectors */
-SIMD_FORCE_INLINE btScalar
-btDot(const btVector3& v1, const btVector3& v2)
-{
- return v1.dot(v2);
-}
-
-/**@brief Return the distance squared between two vectors */
-SIMD_FORCE_INLINE btScalar
-btDistance2(const btVector3& v1, const btVector3& v2)
-{
- return v1.distance2(v2);
-}
-
-/**@brief Return the distance between two vectors */
-SIMD_FORCE_INLINE btScalar
-btDistance(const btVector3& v1, const btVector3& v2)
-{
- return v1.distance(v2);
-}
-
-/**@brief Return the angle between two vectors */
-SIMD_FORCE_INLINE btScalar
-btAngle(const btVector3& v1, const btVector3& v2)
-{
- return v1.angle(v2);
-}
-
-/**@brief Return the cross product of two vectors */
-SIMD_FORCE_INLINE btVector3
-btCross(const btVector3& v1, const btVector3& v2)
-{
- return v1.cross(v2);
-}
-
-SIMD_FORCE_INLINE btScalar
-btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
-{
- return v1.triple(v2, v3);
-}
-
-/**@brief Return the linear interpolation between two vectors
- * @param v1 One vector
- * @param v2 The other vector
- * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
-SIMD_FORCE_INLINE btVector3
-lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
-{
- return v1.lerp(v2, t);
-}
-
-SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
-{
- return (v - *this).length2();
-}
-
-SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
-{
- return (v - *this).length();
-}
-
-SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
-{
- btVector3 nrm = *this;
-
- return nrm.normalize();
-}
-
-SIMD_FORCE_INLINE btVector3 btVector3::rotate(const btVector3& wAxis, const btScalar _angle) const
-{
- // wAxis must be a unit lenght vector
-
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
-
- __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
- btScalar ssin = btSin(_angle);
- __m128 C = wAxis.cross(mVec128).mVec128;
- O = _mm_and_ps(O, btvFFF0fMask);
- btScalar scos = btCos(_angle);
-
- __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
- __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
-
- __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
- __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
- O = _mm_add_ps(O, Y);
- vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
- O = _mm_add_ps(O, Z);
- vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
-
- vsin = vsin * C;
- O = O * wAxis.mVec128;
- __m128 X = mVec128 - O;
-
- O = O + vsin;
- vcos = vcos * X;
- O = O + vcos;
-
- return btVector3(O);
-#else
- btVector3 o = wAxis * wAxis.dot(*this);
- btVector3 _x = *this - o;
- btVector3 _y;
-
- _y = wAxis.cross(*this);
-
- return (o + _x * btCos(_angle) + _y * btSin(_angle));
-#endif
-}
-
-SIMD_FORCE_INLINE long btVector3::maxDot(const btVector3* array, long array_count, btScalar& dotOut) const
-{
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
-#if defined _WIN32 || defined(BT_USE_SSE)
- const long scalar_cutoff = 10;
- long _maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#endif
- if (array_count < scalar_cutoff)
-#endif
- {
- btScalar maxDot1 = -SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for (i = 0; i < array_count; i++)
- {
- btScalar dot = array[i].dot(*this);
-
- if (dot > maxDot1)
- {
- maxDot1 = dot;
- ptIndex = i;
- }
- }
-
- dotOut = maxDot1;
- return ptIndex;
- }
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- return _maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
-#endif
-}
-
-SIMD_FORCE_INLINE long btVector3::minDot(const btVector3* array, long array_count, btScalar& dotOut) const
-{
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
-#if defined BT_USE_SSE
- const long scalar_cutoff = 10;
- long _mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
-#else
-#error unhandled arch!
-#endif
-
- if (array_count < scalar_cutoff)
-#endif
- {
- btScalar minDot = SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
-
- for (i = 0; i < array_count; i++)
- {
- btScalar dot = array[i].dot(*this);
-
- if (dot < minDot)
- {
- minDot = dot;
- ptIndex = i;
- }
- }
-
- dotOut = minDot;
-
- return ptIndex;
- }
-#if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- return _mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
-#endif //BT_USE_SIMD_VECTOR3
-}
-
-class btVector4 : public btVector3
-{
-public:
- SIMD_FORCE_INLINE btVector4() {}
-
- SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- : btVector3(_x, _y, _z)
- {
- m_floats[3] = _w;
- }
-
-#if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
- {
- mVec128 = vec;
- }
-
- SIMD_FORCE_INLINE btVector4(const btVector3& rhs)
- {
- mVec128 = rhs.mVec128;
- }
-
- SIMD_FORCE_INLINE btVector4&
- operator=(const btVector4& v)
- {
- mVec128 = v.mVec128;
- return *this;
- }
-#endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
-
- SIMD_FORCE_INLINE btVector4 absolute4() const
- {
-#if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
-#elif defined(BT_USE_NEON)
- return btVector4(vabsq_f32(mVec128));
-#else
- return btVector4(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
- btFabs(m_floats[2]),
- btFabs(m_floats[3]));
-#endif
- }
-
- btScalar getW() const { return m_floats[3]; }
-
- SIMD_FORCE_INLINE int maxAxis4() const
- {
- int maxIndex = -1;
- btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
- if (m_floats[0] > maxVal)
- {
- maxIndex = 0;
- maxVal = m_floats[0];
- }
- if (m_floats[1] > maxVal)
- {
- maxIndex = 1;
- maxVal = m_floats[1];
- }
- if (m_floats[2] > maxVal)
- {
- maxIndex = 2;
- maxVal = m_floats[2];
- }
- if (m_floats[3] > maxVal)
- {
- maxIndex = 3;
- }
-
- return maxIndex;
- }
-
- SIMD_FORCE_INLINE int minAxis4() const
- {
- int minIndex = -1;
- btScalar minVal = btScalar(BT_LARGE_FLOAT);
- if (m_floats[0] < minVal)
- {
- minIndex = 0;
- minVal = m_floats[0];
- }
- if (m_floats[1] < minVal)
- {
- minIndex = 1;
- minVal = m_floats[1];
- }
- if (m_floats[2] < minVal)
- {
- minIndex = 2;
- minVal = m_floats[2];
- }
- if (m_floats[3] < minVal)
- {
- minIndex = 3;
- }
-
- return minIndex;
- }
-
- SIMD_FORCE_INLINE int closestAxis4() const
- {
- return absolute4().maxAxis4();
- }
-
- /**@brief Set x,y,z and zero w
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
-
- /* void getValue(btScalar *m) const
- {
- m[0] = m_floats[0];
- m[1] = m_floats[1];
- m[2] =m_floats[2];
- }
-*/
- /**@brief Set the values
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = _w;
- }
-};
-
-///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
-{
-#ifdef BT_USE_DOUBLE_PRECISION
- unsigned char* dest = (unsigned char*)&destVal;
- const unsigned char* src = (const unsigned char*)&sourceVal;
- dest[0] = src[7];
- dest[1] = src[6];
- dest[2] = src[5];
- dest[3] = src[4];
- dest[4] = src[3];
- dest[5] = src[2];
- dest[6] = src[1];
- dest[7] = src[0];
-#else
- unsigned char* dest = (unsigned char*)&destVal;
- const unsigned char* src = (const unsigned char*)&sourceVal;
- dest[0] = src[3];
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
-#endif //BT_USE_DOUBLE_PRECISION
-}
-///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
-{
- for (int i = 0; i < 4; i++)
- {
- btSwapScalarEndian(sourceVec[i], destVec[i]);
- }
-}
-
-///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
-SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
-{
- btVector3 swappedVec;
- for (int i = 0; i < 4; i++)
- {
- btSwapScalarEndian(vector[i], swappedVec[i]);
- }
- vector = swappedVec;
-}
-
-template <class T>
-SIMD_FORCE_INLINE void btPlaneSpace1(const T& n, T& p, T& q)
-{
- if (btFabs(n[2]) > SIMDSQRT12)
- {
- // choose p in y-z plane
- btScalar a = n[1] * n[1] + n[2] * n[2];
- btScalar k = btRecipSqrt(a);
- p[0] = 0;
- p[1] = -n[2] * k;
- p[2] = n[1] * k;
- // set q = n x p
- q[0] = a * k;
- q[1] = -n[0] * p[2];
- q[2] = n[0] * p[1];
- }
- else
- {
- // choose p in x-y plane
- btScalar a = n[0] * n[0] + n[1] * n[1];
- btScalar k = btRecipSqrt(a);
- p[0] = -n[1] * k;
- p[1] = n[0] * k;
- p[2] = 0;
- // set q = n x p
- q[0] = -n[2] * p[1];
- q[1] = n[2] * p[0];
- q[2] = a * k;
- }
-}
-
-struct btVector3FloatData
-{
- float m_floats[4];
-};
-
-struct btVector3DoubleData
-{
- double m_floats[4];
-};
-
-SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = float(m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = double(m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
-}
-
-SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
-{
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = m_floats[i];
-}
-
-SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3FloatData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
-}
-
-SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3DoubleData& dataIn)
-{
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
-}
-
-#endif //BT_VECTOR3_H
diff --git a/thirdparty/bullet/VERSION.txt b/thirdparty/bullet/VERSION.txt
deleted file mode 100644
index 78c8a7428a..0000000000
--- a/thirdparty/bullet/VERSION.txt
+++ /dev/null
@@ -1 +0,0 @@
-3.17
diff --git a/thirdparty/bullet/btBulletCollisionAll.cpp b/thirdparty/bullet/btBulletCollisionAll.cpp
deleted file mode 100644
index 4a3ec8dd6f..0000000000
--- a/thirdparty/bullet/btBulletCollisionAll.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#include "BulletCollision/BroadphaseCollision/btAxisSweep3.cpp"
-#include "BulletCollision/BroadphaseCollision/btDbvt.cpp"
-#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp"
-#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp"
-#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp"
-#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp"
-#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp"
-#include "BulletCollision/BroadphaseCollision/btDispatcher.cpp"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp"
-#include "BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp"
-#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btHashedSimplePairCache.cpp"
-#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btCompoundCompoundCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp"
-#include "BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btManifoldResult.cpp"
-#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp"
-#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp"
-#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp"
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcherMt.cpp"
-#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.cpp"
-#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp"
-#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.cpp"
-#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp"
-#include "BulletCollision/CollisionDispatch/btUnionFind.cpp"
-#include "BulletCollision/CollisionDispatch/btCollisionWorldImporter.cpp"
-#include "BulletCollision/CollisionDispatch/btGhostObject.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btConvexCast.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp"
-#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp"
-#include "BulletCollision/CollisionShapes/btBox2dShape.cpp"
-#include "BulletCollision/CollisionShapes/btConvexPolyhedron.cpp"
-#include "BulletCollision/CollisionShapes/btShapeHull.cpp"
-#include "BulletCollision/CollisionShapes/btBoxShape.cpp"
-#include "BulletCollision/CollisionShapes/btConvexShape.cpp"
-#include "BulletCollision/CollisionShapes/btSphereShape.cpp"
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp"
-#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.cpp"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.cpp"
-#include "BulletCollision/CollisionShapes/btCylinderShape.cpp"
-#include "BulletCollision/CollisionShapes/btStridingMeshInterface.cpp"
-#include "BulletCollision/CollisionShapes/btCollisionShape.cpp"
-#include "BulletCollision/CollisionShapes/btEmptyShape.cpp"
-#include "BulletCollision/CollisionShapes/btTetrahedronShape.cpp"
-#include "BulletCollision/CollisionShapes/btCompoundShape.cpp"
-#include "BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleBuffer.cpp"
-#include "BulletCollision/CollisionShapes/btConcaveShape.cpp"
-#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleCallback.cpp"
-#include "BulletCollision/CollisionShapes/btConeShape.cpp"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp"
-#include "BulletCollision/CollisionShapes/btConvex2dShape.cpp"
-#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp"
-#include "BulletCollision/CollisionShapes/btConvexHullShape.cpp"
-#include "BulletCollision/CollisionShapes/btOptimizedBvh.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleMesh.cpp"
-#include "BulletCollision/CollisionShapes/btConvexInternalShape.cpp"
-#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp"
-#include "BulletCollision/CollisionShapes/btTriangleMeshShape.cpp"
-#include "BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp"
-#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp"
-#include "BulletCollision/CollisionShapes/btSdfCollisionShape.cpp"
-#include "BulletCollision/CollisionShapes/btMiniSDF.cpp"
-#include "BulletCollision/CollisionShapes/btUniformScalingShape.cpp"
-#include "BulletCollision/Gimpact/btContactProcessing.cpp"
-#include "BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp"
-#include "BulletCollision/Gimpact/btTriangleShapeEx.cpp"
-#include "BulletCollision/Gimpact/gim_memory.cpp"
-#include "BulletCollision/Gimpact/btGImpactBvh.cpp"
-#include "BulletCollision/Gimpact/btGImpactShape.cpp"
-#include "BulletCollision/Gimpact/gim_box_set.cpp"
-#include "BulletCollision/Gimpact/gim_tri_collision.cpp"
-#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp"
-#include "BulletCollision/Gimpact/btGenericPoolAllocator.cpp"
-#include "BulletCollision/Gimpact/gim_contact.cpp"
diff --git a/thirdparty/bullet/btBulletCollisionCommon.h b/thirdparty/bullet/btBulletCollisionCommon.h
deleted file mode 100644
index 4f523756a7..0000000000
--- a/thirdparty/bullet/btBulletCollisionCommon.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BULLET_COLLISION_COMMON_H
-#define BULLET_COLLISION_COMMON_H
-
-///Common headerfile includes for Bullet Collision Detection
-
-///Bullet's btCollisionWorld and btCollisionObject definitions
-#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
-#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
-
-///Collision Shapes
-#include "BulletCollision/CollisionShapes/btBoxShape.h"
-#include "BulletCollision/CollisionShapes/btSphereShape.h"
-#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
-#include "BulletCollision/CollisionShapes/btCylinderShape.h"
-#include "BulletCollision/CollisionShapes/btConeShape.h"
-#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
-#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
-#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
-#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
-#include "BulletCollision/CollisionShapes/btCompoundShape.h"
-#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
-#include "BulletCollision/CollisionShapes/btEmptyShape.h"
-#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
-#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
-
-///Narrowphase Collision Detector
-#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
-
-//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
-#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
-
-///Dispatching and generation of collision pairs (broadphase)
-#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
-#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
-#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
-#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
-
-///Math library & Utils
-#include "LinearMath/btQuaternion.h"
-#include "LinearMath/btTransform.h"
-#include "LinearMath/btDefaultMotionState.h"
-#include "LinearMath/btQuickprof.h"
-#include "LinearMath/btIDebugDraw.h"
-#include "LinearMath/btSerializer.h"
-
-#endif //BULLET_COLLISION_COMMON_H
diff --git a/thirdparty/bullet/btBulletDynamicsAll.cpp b/thirdparty/bullet/btBulletDynamicsAll.cpp
deleted file mode 100644
index a8069e30ae..0000000000
--- a/thirdparty/bullet/btBulletDynamicsAll.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp"
-#include "BulletDynamics/Dynamics/btRigidBody.cpp"
-#include "BulletDynamics/Dynamics/btSimulationIslandManagerMt.cpp"
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorldMt.cpp"
-#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp"
-#include "BulletDynamics/ConstraintSolver/btBatchedConstraints.cpp"
-#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btSliderConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btContactConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btFixedConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btHingeConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btTypedConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btGearConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btNNCGConstraintSolver.cpp"
-#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpring2Constraint.cpp"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.cpp"
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolverMt.cpp"
-#include "BulletDynamics/MLCPSolvers/btDantzigLCP.cpp"
-#include "BulletDynamics/MLCPSolvers/btLemkeAlgorithm.cpp"
-#include "BulletDynamics/MLCPSolvers/btMLCPSolver.cpp"
-#include "BulletDynamics/Featherstone/btMultiBody.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyDynamicsWorld.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyJointMotor.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyGearConstraint.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraint.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyFixedConstraint.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyPoint2Point.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyConstraintSolver.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyMLCPConstraintSolver.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodyJointLimitConstraint.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodySliderConstraint.cpp"
-#include "BulletDynamics/Featherstone/btMultiBodySphericalJointMotor.cpp"
-#include "BulletDynamics/Vehicle/btRaycastVehicle.cpp"
-#include "BulletDynamics/Vehicle/btWheelInfo.cpp"
-#include "BulletDynamics/Character/btKinematicCharacterController.cpp"
-
diff --git a/thirdparty/bullet/btBulletDynamicsCommon.h b/thirdparty/bullet/btBulletDynamicsCommon.h
deleted file mode 100644
index a421fa4461..0000000000
--- a/thirdparty/bullet/btBulletDynamicsCommon.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Bullet Continuous Collision Detection and Physics Library
-Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
-
-This software is provided 'as-is', without any express or implied warranty.
-In no event will the authors be held liable for any damages arising from the use of this software.
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it freely,
-subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
-2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
-3. This notice may not be removed or altered from any source distribution.
-*/
-
-#ifndef BULLET_DYNAMICS_COMMON_H
-#define BULLET_DYNAMICS_COMMON_H
-
-///Common headerfile includes for Bullet Dynamics, including Collision Detection
-#include "btBulletCollisionCommon.h"
-
-#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h"
-
-#include "BulletDynamics/Dynamics/btSimpleDynamicsWorld.h"
-#include "BulletDynamics/Dynamics/btRigidBody.h"
-
-#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btGeneric6DofSpringConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btUniversalConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btHinge2Constraint.h"
-#include "BulletDynamics/ConstraintSolver/btGearConstraint.h"
-#include "BulletDynamics/ConstraintSolver/btFixedConstraint.h"
-
-#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
-
-///Vehicle simulation, with wheel contact simulated by raycasts
-#include "BulletDynamics/Vehicle/btRaycastVehicle.h"
-
-#endif //BULLET_DYNAMICS_COMMON_H
diff --git a/thirdparty/bullet/btLinearMathAll.cpp b/thirdparty/bullet/btLinearMathAll.cpp
deleted file mode 100644
index d05a19e630..0000000000
--- a/thirdparty/bullet/btLinearMathAll.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "LinearMath/btAlignedAllocator.cpp"
-#include "LinearMath/btGeometryUtil.cpp"
-#include "LinearMath/btSerializer.cpp"
-#include "LinearMath/btVector3.cpp"
-#include "LinearMath/btConvexHull.cpp"
-#include "LinearMath/btPolarDecomposition.cpp"
-#include "LinearMath/btSerializer64.cpp"
-#include "LinearMath/btConvexHullComputer.cpp"
-#include "LinearMath/btQuickprof.cpp"
-#include "LinearMath/btThreads.cpp"
-#include "LinearMath/btReducedVector.cpp"
-#include "LinearMath/TaskScheduler/btTaskScheduler.cpp"
-#include "LinearMath/TaskScheduler/btThreadSupportPosix.cpp"
-#include "LinearMath/TaskScheduler/btThreadSupportWin32.cpp"
-
diff --git a/thirdparty/bullet/clew/clew.c b/thirdparty/bullet/clew/clew.c
deleted file mode 100644
index 90caced535..0000000000
--- a/thirdparty/bullet/clew/clew.c
+++ /dev/null
@@ -1,374 +0,0 @@
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009 Organic Vectory B.V.
-// Written by George van Venrooij
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file license.txt)
-//////////////////////////////////////////////////////////////////////////
-
-#include "clew.h"
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#define VC_EXTRALEAN
-#include <windows.h>
-
-typedef HMODULE CLEW_DYNLIB_HANDLE;
-
-#define CLEW_DYNLIB_OPEN LoadLibraryA
-#define CLEW_DYNLIB_CLOSE FreeLibrary
-#define CLEW_DYNLIB_IMPORT GetProcAddress
-#else
-#include <dlfcn.h>
-
-typedef void* CLEW_DYNLIB_HANDLE;
-
-#define CLEW_DYNLIB_OPEN(path) dlopen(path, RTLD_NOW | RTLD_GLOBAL)
-#define CLEW_DYNLIB_CLOSE dlclose
-#define CLEW_DYNLIB_IMPORT dlsym
-#endif
-
-#include <stdlib.h>
-
-//! \brief module handle
-static CLEW_DYNLIB_HANDLE module = NULL;
-
-// Variables holding function entry points
-PFNCLGETPLATFORMIDS __clewGetPlatformIDs = NULL;
-PFNCLGETPLATFORMINFO __clewGetPlatformInfo = NULL;
-PFNCLGETDEVICEIDS __clewGetDeviceIDs = NULL;
-PFNCLGETDEVICEINFO __clewGetDeviceInfo = NULL;
-PFNCLCREATECONTEXT __clewCreateContext = NULL;
-PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType = NULL;
-PFNCLRETAINCONTEXT __clewRetainContext = NULL;
-PFNCLRELEASECONTEXT __clewReleaseContext = NULL;
-PFNCLGETCONTEXTINFO __clewGetContextInfo = NULL;
-PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue = NULL;
-PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue = NULL;
-PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue = NULL;
-PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo = NULL;
-#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
-PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty = NULL;
-#endif
-PFNCLCREATEBUFFER __clewCreateBuffer = NULL;
-PFNCLCREATESUBBUFFER __clewCreateSubBuffer = NULL;
-PFNCLCREATEIMAGE2D __clewCreateImage2D = NULL;
-PFNCLCREATEIMAGE3D __clewCreateImage3D = NULL;
-PFNCLRETAINMEMOBJECT __clewRetainMemObject = NULL;
-PFNCLRELEASEMEMOBJECT __clewReleaseMemObject = NULL;
-PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats = NULL;
-PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo = NULL;
-PFNCLGETIMAGEINFO __clewGetImageInfo = NULL;
-PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback = NULL;
-PFNCLCREATESAMPLER __clewCreateSampler = NULL;
-PFNCLRETAINSAMPLER __clewRetainSampler = NULL;
-PFNCLRELEASESAMPLER __clewReleaseSampler = NULL;
-PFNCLGETSAMPLERINFO __clewGetSamplerInfo = NULL;
-PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource = NULL;
-PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary = NULL;
-PFNCLRETAINPROGRAM __clewRetainProgram = NULL;
-PFNCLRELEASEPROGRAM __clewReleaseProgram = NULL;
-PFNCLBUILDPROGRAM __clewBuildProgram = NULL;
-PFNCLUNLOADCOMPILER __clewUnloadCompiler = NULL;
-PFNCLGETPROGRAMINFO __clewGetProgramInfo = NULL;
-PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo = NULL;
-PFNCLCREATEKERNEL __clewCreateKernel = NULL;
-PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram = NULL;
-PFNCLRETAINKERNEL __clewRetainKernel = NULL;
-PFNCLRELEASEKERNEL __clewReleaseKernel = NULL;
-PFNCLSETKERNELARG __clewSetKernelArg = NULL;
-PFNCLGETKERNELINFO __clewGetKernelInfo = NULL;
-PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo = NULL;
-PFNCLWAITFOREVENTS __clewWaitForEvents = NULL;
-PFNCLGETEVENTINFO __clewGetEventInfo = NULL;
-PFNCLCREATEUSEREVENT __clewCreateUserEvent = NULL;
-PFNCLRETAINEVENT __clewRetainEvent = NULL;
-PFNCLRELEASEEVENT __clewReleaseEvent = NULL;
-PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus = NULL;
-PFNCLSETEVENTCALLBACK __clewSetEventCallback = NULL;
-PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo = NULL;
-PFNCLFLUSH __clewFlush = NULL;
-PFNCLFINISH __clewFinish = NULL;
-PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer = NULL;
-PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect = NULL;
-PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer = NULL;
-PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect = NULL;
-PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer = NULL;
-PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage = NULL;
-PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage = NULL;
-PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage = NULL;
-PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect = NULL;
-PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer = NULL;
-PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage = NULL;
-PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer = NULL;
-PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage = NULL;
-PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject = NULL;
-PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel = NULL;
-PFNCLENQUEUETASK __clewEnqueueTask = NULL;
-PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel = NULL;
-PFNCLENQUEUEMARKER __clewEnqueueMarker = NULL;
-PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents = NULL;
-PFNCLENQUEUEBARRIER __clewEnqueueBarrier = NULL;
-PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress = NULL;
-
-void clewExit(void)
-{
- if (module != NULL)
- {
- // Ignore errors
- CLEW_DYNLIB_CLOSE(module);
- module = NULL;
- }
-}
-
-int clewInit(const char* path)
-{
- int error = 0;
-
- // Check if already initialized
- if (module != NULL)
- {
- return CLEW_SUCCESS;
- }
-
- // Load library
- module = CLEW_DYNLIB_OPEN(path);
-
- // Check for errors
- if (module == NULL)
- {
- return CLEW_ERROR_OPEN_FAILED;
- }
-
- // Set unloading
- error = atexit(clewExit);
-
- if (error)
- {
- // Failure queuing atexit, shutdown with error
- CLEW_DYNLIB_CLOSE(module);
- module = NULL;
-
- return CLEW_ERROR_ATEXIT_FAILED;
- }
-
- // Determine function entry-points
- __clewGetPlatformIDs = (PFNCLGETPLATFORMIDS)CLEW_DYNLIB_IMPORT(module, "clGetPlatformIDs");
- __clewGetPlatformInfo = (PFNCLGETPLATFORMINFO)CLEW_DYNLIB_IMPORT(module, "clGetPlatformInfo");
- __clewGetDeviceIDs = (PFNCLGETDEVICEIDS)CLEW_DYNLIB_IMPORT(module, "clGetDeviceIDs");
- __clewGetDeviceInfo = (PFNCLGETDEVICEINFO)CLEW_DYNLIB_IMPORT(module, "clGetDeviceInfo");
- __clewCreateContext = (PFNCLCREATECONTEXT)CLEW_DYNLIB_IMPORT(module, "clCreateContext");
- __clewCreateContextFromType = (PFNCLCREATECONTEXTFROMTYPE)CLEW_DYNLIB_IMPORT(module, "clCreateContextFromType");
- __clewRetainContext = (PFNCLRETAINCONTEXT)CLEW_DYNLIB_IMPORT(module, "clRetainContext");
- __clewReleaseContext = (PFNCLRELEASECONTEXT)CLEW_DYNLIB_IMPORT(module, "clReleaseContext");
- __clewGetContextInfo = (PFNCLGETCONTEXTINFO)CLEW_DYNLIB_IMPORT(module, "clGetContextInfo");
- __clewCreateCommandQueue = (PFNCLCREATECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clCreateCommandQueue");
- __clewRetainCommandQueue = (PFNCLRETAINCOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clRetainCommandQueue");
- __clewReleaseCommandQueue = (PFNCLRELEASECOMMANDQUEUE)CLEW_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
- __clewGetCommandQueueInfo = (PFNCLGETCOMMANDQUEUEINFO)CLEW_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
-#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
- __clewSetCommandQueueProperty = (PFNCLSETCOMMANDQUEUEPROPERTY)CLEW_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
-#endif
- __clewCreateBuffer = (PFNCLCREATEBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateSubBuffer = (PFNCLCREATESUBBUFFER)CLEW_DYNLIB_IMPORT(module, "clCreateBuffer");
- __clewCreateImage2D = (PFNCLCREATEIMAGE2D)CLEW_DYNLIB_IMPORT(module, "clCreateImage2D");
- __clewCreateImage3D = (PFNCLCREATEIMAGE3D)CLEW_DYNLIB_IMPORT(module, "clCreateImage3D");
- __clewRetainMemObject = (PFNCLRETAINMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clRetainMemObject");
- __clewReleaseMemObject = (PFNCLRELEASEMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clReleaseMemObject");
- __clewGetSupportedImageFormats = (PFNCLGETSUPPORTEDIMAGEFORMATS)CLEW_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
- __clewGetMemObjectInfo = (PFNCLGETMEMOBJECTINFO)CLEW_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
- __clewGetImageInfo = (PFNCLGETIMAGEINFO)CLEW_DYNLIB_IMPORT(module, "clGetImageInfo");
- __clewSetMemObjectDestructorCallback = (PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetMemObjectDestructorCallback");
- __clewCreateSampler = (PFNCLCREATESAMPLER)CLEW_DYNLIB_IMPORT(module, "clCreateSampler");
- __clewRetainSampler = (PFNCLRETAINSAMPLER)CLEW_DYNLIB_IMPORT(module, "clRetainSampler");
- __clewReleaseSampler = (PFNCLRELEASESAMPLER)CLEW_DYNLIB_IMPORT(module, "clReleaseSampler");
- __clewGetSamplerInfo = (PFNCLGETSAMPLERINFO)CLEW_DYNLIB_IMPORT(module, "clGetSamplerInfo");
- __clewCreateProgramWithSource = (PFNCLCREATEPROGRAMWITHSOURCE)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
- __clewCreateProgramWithBinary = (PFNCLCREATEPROGRAMWITHBINARY)CLEW_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
- __clewRetainProgram = (PFNCLRETAINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clRetainProgram");
- __clewReleaseProgram = (PFNCLRELEASEPROGRAM)CLEW_DYNLIB_IMPORT(module, "clReleaseProgram");
- __clewBuildProgram = (PFNCLBUILDPROGRAM)CLEW_DYNLIB_IMPORT(module, "clBuildProgram");
- __clewUnloadCompiler = (PFNCLUNLOADCOMPILER)CLEW_DYNLIB_IMPORT(module, "clUnloadCompiler");
- __clewGetProgramInfo = (PFNCLGETPROGRAMINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramInfo");
- __clewGetProgramBuildInfo = (PFNCLGETPROGRAMBUILDINFO)CLEW_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
- __clewCreateKernel = (PFNCLCREATEKERNEL)CLEW_DYNLIB_IMPORT(module, "clCreateKernel");
- __clewCreateKernelsInProgram = (PFNCLCREATEKERNELSINPROGRAM)CLEW_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
- __clewRetainKernel = (PFNCLRETAINKERNEL)CLEW_DYNLIB_IMPORT(module, "clRetainKernel");
- __clewReleaseKernel = (PFNCLRELEASEKERNEL)CLEW_DYNLIB_IMPORT(module, "clReleaseKernel");
- __clewSetKernelArg = (PFNCLSETKERNELARG)CLEW_DYNLIB_IMPORT(module, "clSetKernelArg");
- __clewGetKernelInfo = (PFNCLGETKERNELINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelInfo");
- __clewGetKernelWorkGroupInfo = (PFNCLGETKERNELWORKGROUPINFO)CLEW_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
- __clewWaitForEvents = (PFNCLWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clWaitForEvents");
- __clewGetEventInfo = (PFNCLGETEVENTINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventInfo");
- __clewCreateUserEvent = (PFNCLCREATEUSEREVENT)CLEW_DYNLIB_IMPORT(module, "clCreateUserEvent");
- __clewRetainEvent = (PFNCLRETAINEVENT)CLEW_DYNLIB_IMPORT(module, "clRetainEvent");
- __clewReleaseEvent = (PFNCLRELEASEEVENT)CLEW_DYNLIB_IMPORT(module, "clReleaseEvent");
- __clewSetUserEventStatus = (PFNCLSETUSEREVENTSTATUS)CLEW_DYNLIB_IMPORT(module, "clSetUserEventStatus");
- __clewSetEventCallback = (PFNCLSETEVENTCALLBACK)CLEW_DYNLIB_IMPORT(module, "clSetEventCallback");
- __clewGetEventProfilingInfo = (PFNCLGETEVENTPROFILINGINFO)CLEW_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
- __clewFlush = (PFNCLFLUSH)CLEW_DYNLIB_IMPORT(module, "clFlush");
- __clewFinish = (PFNCLFINISH)CLEW_DYNLIB_IMPORT(module, "clFinish");
- __clewEnqueueReadBuffer = (PFNCLENQUEUEREADBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
- __clewEnqueueReadBufferRect = (PFNCLENQUEUEREADBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadBufferRect");
- __clewEnqueueWriteBuffer = (PFNCLENQUEUEWRITEBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
- __clewEnqueueWriteBufferRect = (PFNCLENQUEUEWRITEBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteBufferRect");
- __clewEnqueueCopyBuffer = (PFNCLENQUEUECOPYBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
- __clewEnqueueCopyBufferRect = (PFNCLENQUEUECOPYBUFFERRECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferRect");
- __clewEnqueueReadImage = (PFNCLENQUEUEREADIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueReadImage");
- __clewEnqueueWriteImage = (PFNCLENQUEUEWRITEIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
- __clewEnqueueCopyImage = (PFNCLENQUEUECOPYIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
- __clewEnqueueCopyImageToBuffer = (PFNCLENQUEUECOPYIMAGETOBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
- __clewEnqueueCopyBufferToImage = (PFNCLENQUEUECOPYBUFFERTOIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
- __clewEnqueueMapBuffer = (PFNCLENQUEUEMAPBUFFER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
- __clewEnqueueMapImage = (PFNCLENQUEUEMAPIMAGE)CLEW_DYNLIB_IMPORT(module, "clEnqueueMapImage");
- __clewEnqueueUnmapMemObject = (PFNCLENQUEUEUNMAPMEMOBJECT)CLEW_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
- __clewEnqueueNDRangeKernel = (PFNCLENQUEUENDRANGEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
- __clewEnqueueTask = (PFNCLENQUEUETASK)CLEW_DYNLIB_IMPORT(module, "clEnqueueTask");
- __clewEnqueueNativeKernel = (PFNCLENQUEUENATIVEKERNEL)CLEW_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
- __clewEnqueueMarker = (PFNCLENQUEUEMARKER)CLEW_DYNLIB_IMPORT(module, "clEnqueueMarker");
- __clewEnqueueWaitForEvents = (PFNCLENQUEUEWAITFOREVENTS)CLEW_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
- __clewEnqueueBarrier = (PFNCLENQUEUEBARRIER)CLEW_DYNLIB_IMPORT(module, "clEnqueueBarrier");
- __clewGetExtensionFunctionAddress = (PFNCLGETEXTENSIONFUNCTIONADDRESS)CLEW_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
-
- return CLEW_SUCCESS;
-}
-
-const char* clewErrorString(cl_int error)
-{
- static const char* strings[] =
- {
- // Error Codes
- "CL_SUCCESS" // 0
- ,
- "CL_DEVICE_NOT_FOUND" // -1
- ,
- "CL_DEVICE_NOT_AVAILABLE" // -2
- ,
- "CL_COMPILER_NOT_AVAILABLE" // -3
- ,
- "CL_MEM_OBJECT_ALLOCATION_FAILURE" // -4
- ,
- "CL_OUT_OF_RESOURCES" // -5
- ,
- "CL_OUT_OF_HOST_MEMORY" // -6
- ,
- "CL_PROFILING_INFO_NOT_AVAILABLE" // -7
- ,
- "CL_MEM_COPY_OVERLAP" // -8
- ,
- "CL_IMAGE_FORMAT_MISMATCH" // -9
- ,
- "CL_IMAGE_FORMAT_NOT_SUPPORTED" // -10
- ,
- "CL_BUILD_PROGRAM_FAILURE" // -11
- ,
- "CL_MAP_FAILURE" // -12
-
- ,
- "" // -13
- ,
- "" // -14
- ,
- "" // -15
- ,
- "" // -16
- ,
- "" // -17
- ,
- "" // -18
- ,
- "" // -19
-
- ,
- "" // -20
- ,
- "" // -21
- ,
- "" // -22
- ,
- "" // -23
- ,
- "" // -24
- ,
- "" // -25
- ,
- "" // -26
- ,
- "" // -27
- ,
- "" // -28
- ,
- "" // -29
-
- ,
- "CL_INVALID_VALUE" // -30
- ,
- "CL_INVALID_DEVICE_TYPE" // -31
- ,
- "CL_INVALID_PLATFORM" // -32
- ,
- "CL_INVALID_DEVICE" // -33
- ,
- "CL_INVALID_CONTEXT" // -34
- ,
- "CL_INVALID_QUEUE_PROPERTIES" // -35
- ,
- "CL_INVALID_COMMAND_QUEUE" // -36
- ,
- "CL_INVALID_HOST_PTR" // -37
- ,
- "CL_INVALID_MEM_OBJECT" // -38
- ,
- "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR" // -39
- ,
- "CL_INVALID_IMAGE_SIZE" // -40
- ,
- "CL_INVALID_SAMPLER" // -41
- ,
- "CL_INVALID_BINARY" // -42
- ,
- "CL_INVALID_BUILD_OPTIONS" // -43
- ,
- "CL_INVALID_PROGRAM" // -44
- ,
- "CL_INVALID_PROGRAM_EXECUTABLE" // -45
- ,
- "CL_INVALID_KERNEL_NAME" // -46
- ,
- "CL_INVALID_KERNEL_DEFINITION" // -47
- ,
- "CL_INVALID_KERNEL" // -48
- ,
- "CL_INVALID_ARG_INDEX" // -49
- ,
- "CL_INVALID_ARG_VALUE" // -50
- ,
- "CL_INVALID_ARG_SIZE" // -51
- ,
- "CL_INVALID_KERNEL_ARGS" // -52
- ,
- "CL_INVALID_WORK_DIMENSION" // -53
- ,
- "CL_INVALID_WORK_GROUP_SIZE" // -54
- ,
- "CL_INVALID_WORK_ITEM_SIZE" // -55
- ,
- "CL_INVALID_GLOBAL_OFFSET" // -56
- ,
- "CL_INVALID_EVENT_WAIT_LIST" // -57
- ,
- "CL_INVALID_EVENT" // -58
- ,
- "CL_INVALID_OPERATION" // -59
- ,
- "CL_INVALID_GL_OBJECT" // -60
- ,
- "CL_INVALID_BUFFER_SIZE" // -61
- ,
- "CL_INVALID_MIP_LEVEL" // -62
- ,
- "CL_INVALID_GLOBAL_WORK_SIZE" // -63
- };
-
- return strings[-error];
-}
diff --git a/thirdparty/bullet/clew/clew.h b/thirdparty/bullet/clew/clew.h
deleted file mode 100644
index cba8585233..0000000000
--- a/thirdparty/bullet/clew/clew.h
+++ /dev/null
@@ -1,2708 +0,0 @@
-#ifndef CLEW_HPP_INCLUDED
-#define CLEW_HPP_INCLUDED
-
-//////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2009-2011 Organic Vectory B.V., KindDragon
-// Written by George van Venrooij
-//
-// Distributed under the MIT License.
-//////////////////////////////////////////////////////////////////////////
-
-//! \file clew.h
-//! \brief OpenCL run-time loader header
-//!
-//! This file contains a copy of the contents of CL.H and CL_PLATFORM.H from the
-//! official OpenCL spec. The purpose of this code is to load the OpenCL dynamic
-//! library at run-time and thus allow the executable to function on many
-//! platforms regardless of the vendor of the OpenCL driver actually installed.
-//! Some of the techniques used here were inspired by work done in the GLEW
-//! library (http://glew.sourceforge.net/)
-
-// Run-time dynamic linking functionality based on concepts used in GLEW
-#ifdef __OPENCL_CL_H
-#error cl.h included before clew.h
-#endif
-
-#ifdef __OPENCL_CL_PLATFORM_H
-#error cl_platform.h included before clew.h
-#endif
-
-// Prevent cl.h inclusion
-#define __OPENCL_CL_H
-// Prevent cl_platform.h inclusion
-#define __CL_PLATFORM_H
-
-/*******************************************************************************
-* Copyright (c) 2008-2010 The Khronos Group Inc.
-*
-* Permission is hereby granted, free of charge, to any person obtaining a
-* copy of this software and/or associated documentation files (the
-* "Materials"), to deal in the Materials without restriction, including
-* without limitation the rights to use, copy, modify, merge, publish,
-* distribute, sublicense, and/or sell copies of the Materials, and to
-* permit persons to whom the Materials are 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 Materials.
-*
-* THE MATERIALS ARE 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
-* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
-******************************************************************************/
-#ifdef __APPLE__
-/* Contains #defines for AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER below */
-#include <AvailabilityMacros.h>
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#if defined(_WIN32)
-#define CL_API_ENTRY
-#define CL_API_CALL __stdcall
-#define CL_CALLBACK __stdcall
-#else
-#define CL_API_ENTRY
-#define CL_API_CALL
-#define CL_CALLBACK
-#endif
- //disabled the APPLE thing, don't know why it is there, is just causes tons of warnings
-
-#ifdef __APPLE1__
-#define CL_EXTENSION_WEAK_LINK __attribute__((weak_import))
-#define CL_API_SUFFIX__VERSION_1_0 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
-#define CL_EXT_SUFFIX__VERSION_1_0 CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
-#define CL_API_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
-#define CL_EXT_SUFFIX__VERSION_1_1 CL_EXTENSION_WEAK_LINK
-#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED CL_EXTENSION_WEAK_LINK AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER
-#else
-#define CL_EXTENSION_WEAK_LINK
-#define CL_API_SUFFIX__VERSION_1_0
-#define CL_EXT_SUFFIX__VERSION_1_0
-#define CL_API_SUFFIX__VERSION_1_1
-#define CL_EXT_SUFFIX__VERSION_1_1
-#define CL_EXT_SUFFIX__VERSION_1_0_DEPRECATED
-#endif
-
-#if (defined(_WIN32) && defined(_MSC_VER))
-
- /* scalar types */
- typedef signed __int8 cl_char;
- typedef unsigned __int8 cl_uchar;
- typedef signed __int16 cl_short;
- typedef unsigned __int16 cl_ushort;
- typedef signed __int32 cl_int;
- typedef unsigned __int32 cl_uint;
- typedef signed __int64 cl_long;
- typedef unsigned __int64 cl_ulong;
-
- typedef unsigned __int16 cl_half;
- typedef float cl_float;
- typedef double cl_double;
-
-/* Macro names and corresponding values defined by OpenCL */
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127 - 1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767 - 1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647 - 1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#define CL_FLT_MAX 340282346638528859811704183484516925440.0f
-#define CL_FLT_MIN 1.175494350822287507969e-38f
-#define CL_FLT_EPSILON 0x1.0p-23f
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#define CL_DBL_MAX 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0
-#define CL_DBL_MIN 2.225073858507201383090e-308
-#define CL_DBL_EPSILON 2.220446049250313080847e-16
-
-#define CL_M_E 2.718281828459045090796
-#define CL_M_LOG2E 1.442695040888963387005
-#define CL_M_LOG10E 0.434294481903251816668
-#define CL_M_LN2 0.693147180559945286227
-#define CL_M_LN10 2.302585092994045901094
-#define CL_M_PI 3.141592653589793115998
-#define CL_M_PI_2 1.570796326794896557999
-#define CL_M_PI_4 0.785398163397448278999
-#define CL_M_1_PI 0.318309886183790691216
-#define CL_M_2_PI 0.636619772367581382433
-#define CL_M_2_SQRTPI 1.128379167095512558561
-#define CL_M_SQRT2 1.414213562373095145475
-#define CL_M_SQRT1_2 0.707106781186547572737
-
-#define CL_M_E_F 2.71828174591064f
-#define CL_M_LOG2E_F 1.44269502162933f
-#define CL_M_LOG10E_F 0.43429449200630f
-#define CL_M_LN2_F 0.69314718246460f
-#define CL_M_LN10_F 2.30258512496948f
-#define CL_M_PI_F 3.14159274101257f
-#define CL_M_PI_2_F 1.57079637050629f
-#define CL_M_PI_4_F 0.78539818525314f
-#define CL_M_1_PI_F 0.31830987334251f
-#define CL_M_2_PI_F 0.63661974668503f
-#define CL_M_2_SQRTPI_F 1.12837922573090f
-#define CL_M_SQRT2_F 1.41421353816986f
-#define CL_M_SQRT1_2_F 0.70710676908493f
-
-#define CL_NAN (CL_INFINITY - CL_INFINITY)
-#define CL_HUGE_VALF ((cl_float)1e50)
-#define CL_HUGE_VAL ((cl_double)1e500)
-#define CL_MAXFLOAT CL_FLT_MAX
-#define CL_INFINITY CL_HUGE_VALF
-
-#else
-
-#include <stdint.h>
-
-/* scalar types */
-typedef int8_t cl_char;
-typedef uint8_t cl_uchar;
-typedef int16_t cl_short __attribute__((aligned(2)));
-typedef uint16_t cl_ushort __attribute__((aligned(2)));
-typedef int32_t cl_int __attribute__((aligned(4)));
-typedef uint32_t cl_uint __attribute__((aligned(4)));
-typedef int64_t cl_long __attribute__((aligned(8)));
-typedef uint64_t cl_ulong __attribute__((aligned(8)));
-
-typedef uint16_t cl_half __attribute__((aligned(2)));
-typedef float cl_float __attribute__((aligned(4)));
-typedef double cl_double __attribute__((aligned(8)));
-
-/* Macro names and corresponding values defined by OpenCL */
-#define CL_CHAR_BIT 8
-#define CL_SCHAR_MAX 127
-#define CL_SCHAR_MIN (-127 - 1)
-#define CL_CHAR_MAX CL_SCHAR_MAX
-#define CL_CHAR_MIN CL_SCHAR_MIN
-#define CL_UCHAR_MAX 255
-#define CL_SHRT_MAX 32767
-#define CL_SHRT_MIN (-32767 - 1)
-#define CL_USHRT_MAX 65535
-#define CL_INT_MAX 2147483647
-#define CL_INT_MIN (-2147483647 - 1)
-#define CL_UINT_MAX 0xffffffffU
-#define CL_LONG_MAX ((cl_long)0x7FFFFFFFFFFFFFFFLL)
-#define CL_LONG_MIN ((cl_long)-0x7FFFFFFFFFFFFFFFLL - 1LL)
-#define CL_ULONG_MAX ((cl_ulong)0xFFFFFFFFFFFFFFFFULL)
-
-#define CL_FLT_DIG 6
-#define CL_FLT_MANT_DIG 24
-#define CL_FLT_MAX_10_EXP +38
-#define CL_FLT_MAX_EXP +128
-#define CL_FLT_MIN_10_EXP -37
-#define CL_FLT_MIN_EXP -125
-#define CL_FLT_RADIX 2
-#define CL_FLT_MAX 0x1.fffffep127f
-#define CL_FLT_MIN 0x1.0p-126f
-#define CL_FLT_EPSILON 0x1.0p-23f
-
-#define CL_DBL_DIG 15
-#define CL_DBL_MANT_DIG 53
-#define CL_DBL_MAX_10_EXP +308
-#define CL_DBL_MAX_EXP +1024
-#define CL_DBL_MIN_10_EXP -307
-#define CL_DBL_MIN_EXP -1021
-#define CL_DBL_RADIX 2
-#define CL_DBL_MAX 0x1.fffffffffffffp1023
-#define CL_DBL_MIN 0x1.0p-1022
-#define CL_DBL_EPSILON 0x1.0p-52
-
-#define CL_M_E 2.718281828459045090796
-#define CL_M_LOG2E 1.442695040888963387005
-#define CL_M_LOG10E 0.434294481903251816668
-#define CL_M_LN2 0.693147180559945286227
-#define CL_M_LN10 2.302585092994045901094
-#define CL_M_PI 3.141592653589793115998
-#define CL_M_PI_2 1.570796326794896557999
-#define CL_M_PI_4 0.785398163397448278999
-#define CL_M_1_PI 0.318309886183790691216
-#define CL_M_2_PI 0.636619772367581382433
-#define CL_M_2_SQRTPI 1.128379167095512558561
-#define CL_M_SQRT2 1.414213562373095145475
-#define CL_M_SQRT1_2 0.707106781186547572737
-
-#define CL_M_E_F 2.71828174591064f
-#define CL_M_LOG2E_F 1.44269502162933f
-#define CL_M_LOG10E_F 0.43429449200630f
-#define CL_M_LN2_F 0.69314718246460f
-#define CL_M_LN10_F 2.30258512496948f
-#define CL_M_PI_F 3.14159274101257f
-#define CL_M_PI_2_F 1.57079637050629f
-#define CL_M_PI_4_F 0.78539818525314f
-#define CL_M_1_PI_F 0.31830987334251f
-#define CL_M_2_PI_F 0.63661974668503f
-#define CL_M_2_SQRTPI_F 1.12837922573090f
-#define CL_M_SQRT2_F 1.41421353816986f
-#define CL_M_SQRT1_2_F 0.70710676908493f
-
-#if defined(__GNUC__)
-#define CL_HUGE_VALF __builtin_huge_valf()
-#define CL_HUGE_VAL __builtin_huge_val()
-#define CL_NAN __builtin_nanf("")
-#else
-#define CL_HUGE_VALF ((cl_float)1e50)
-#define CL_HUGE_VAL ((cl_double)1e500)
-float nanf(const char *);
-#define CL_NAN nanf("")
-#endif
-#define CL_MAXFLOAT CL_FLT_MAX
-#define CL_INFINITY CL_HUGE_VALF
-
-#endif
-
-#include <stddef.h>
-
- /* Mirror types to GL types. Mirror types allow us to avoid deciding which headers to load based on whether we are using GL or GLES here. */
- typedef unsigned int cl_GLuint;
- typedef int cl_GLint;
- typedef unsigned int cl_GLenum;
-
- /*
- * Vector types
- *
- * Note: OpenCL requires that all types be naturally aligned.
- * This means that vector types must be naturally aligned.
- * For example, a vector of four floats must be aligned to
- * a 16 byte boundary (calculated as 4 * the natural 4-byte
- * alignment of the float). The alignment qualifiers here
- * will only function properly if your compiler supports them
- * and if you don't actively work to defeat them. For example,
- * in order for a cl_float4 to be 16 byte aligned in a struct,
- * the start of the struct must itself be 16-byte aligned.
- *
- * Maintaining proper alignment is the user's responsibility.
- */
-
-#ifdef _MSC_VER
-#if defined(_M_IX86)
-#if _M_IX86_FP >= 0
-#define __SSE__
-#endif
-#if _M_IX86_FP >= 1
-#define __SSE2__
-#endif
-#elif defined(_M_X64)
-#define __SSE__
-#define __SSE2__
-#endif
-#endif
-
-/* Define basic vector types */
-#if defined(__VEC__)
-#include <altivec.h> /* may be omitted depending on compiler. AltiVec spec provides no way to detect whether the header is required. */
- typedef vector unsigned char __cl_uchar16;
- typedef vector signed char __cl_char16;
- typedef vector unsigned short __cl_ushort8;
- typedef vector signed short __cl_short8;
- typedef vector unsigned int __cl_uint4;
- typedef vector signed int __cl_int4;
- typedef vector float __cl_float4;
-#define __CL_UCHAR16__ 1
-#define __CL_CHAR16__ 1
-#define __CL_USHORT8__ 1
-#define __CL_SHORT8__ 1
-#define __CL_UINT4__ 1
-#define __CL_INT4__ 1
-#define __CL_FLOAT4__ 1
-#endif
-
-#if defined(__SSE__)
-#if defined(__MINGW64__)
-#include <intrin.h>
-#else
-#include <xmmintrin.h>
-#endif
-#if defined(__GNUC__) && !defined(__ICC)
- typedef float __cl_float4 __attribute__((vector_size(16)));
-#else
- typedef __m128 __cl_float4;
-#endif
-#define __CL_FLOAT4__ 1
-#endif
-
-#if defined(__SSE2__)
-#if defined(__MINGW64__)
-#include <intrin.h>
-#else
-#include <emmintrin.h>
-#endif
-#if defined(__GNUC__) && !defined(__ICC)
- typedef cl_uchar __cl_uchar16 __attribute__((vector_size(16)));
- typedef cl_char __cl_char16 __attribute__((vector_size(16)));
- typedef cl_ushort __cl_ushort8 __attribute__((vector_size(16)));
- typedef cl_short __cl_short8 __attribute__((vector_size(16)));
- typedef cl_uint __cl_uint4 __attribute__((vector_size(16)));
- typedef cl_int __cl_int4 __attribute__((vector_size(16)));
- typedef cl_ulong __cl_ulong2 __attribute__((vector_size(16)));
- typedef cl_long __cl_long2 __attribute__((vector_size(16)));
- typedef cl_double __cl_double2 __attribute__((vector_size(16)));
-#else
- typedef __m128i __cl_uchar16;
- typedef __m128i __cl_char16;
- typedef __m128i __cl_ushort8;
- typedef __m128i __cl_short8;
- typedef __m128i __cl_uint4;
- typedef __m128i __cl_int4;
- typedef __m128i __cl_ulong2;
- typedef __m128i __cl_long2;
- typedef __m128d __cl_double2;
-#endif
-#define __CL_UCHAR16__ 1
-#define __CL_CHAR16__ 1
-#define __CL_USHORT8__ 1
-#define __CL_SHORT8__ 1
-#define __CL_INT4__ 1
-#define __CL_UINT4__ 1
-#define __CL_ULONG2__ 1
-#define __CL_LONG2__ 1
-#define __CL_DOUBLE2__ 1
-#endif
-
-#if defined(__MMX__)
-#include <mmintrin.h>
-#if defined(__GNUC__) && !defined(__ICC)
- typedef cl_uchar __cl_uchar8 __attribute__((vector_size(8)));
- typedef cl_char __cl_char8 __attribute__((vector_size(8)));
- typedef cl_ushort __cl_ushort4 __attribute__((vector_size(8)));
- typedef cl_short __cl_short4 __attribute__((vector_size(8)));
- typedef cl_uint __cl_uint2 __attribute__((vector_size(8)));
- typedef cl_int __cl_int2 __attribute__((vector_size(8)));
- typedef cl_ulong __cl_ulong1 __attribute__((vector_size(8)));
- typedef cl_long __cl_long1 __attribute__((vector_size(8)));
- typedef cl_float __cl_float2 __attribute__((vector_size(8)));
-#else
- typedef __m64 __cl_uchar8;
- typedef __m64 __cl_char8;
- typedef __m64 __cl_ushort4;
- typedef __m64 __cl_short4;
- typedef __m64 __cl_uint2;
- typedef __m64 __cl_int2;
- typedef __m64 __cl_ulong1;
- typedef __m64 __cl_long1;
- typedef __m64 __cl_float2;
-#endif
-#define __CL_UCHAR8__ 1
-#define __CL_CHAR8__ 1
-#define __CL_USHORT4__ 1
-#define __CL_SHORT4__ 1
-#define __CL_INT2__ 1
-#define __CL_UINT2__ 1
-#define __CL_ULONG1__ 1
-#define __CL_LONG1__ 1
-#define __CL_FLOAT2__ 1
-#endif
-
-#if defined(__AVX__)
-#if defined(__MINGW64__)
-#include <intrin.h>
-#else
-#include <immintrin.h>
-#endif
-#if defined(__GNUC__) && !defined(__ICC)
- typedef cl_float __cl_float8 __attribute__((vector_size(32)));
- typedef cl_double __cl_double4 __attribute__((vector_size(32)));
-#else
- typedef __m256 __cl_float8;
- typedef __m256d __cl_double4;
-#endif
-#define __CL_FLOAT8__ 1
-#define __CL_DOUBLE4__ 1
-#endif
-
-/* Define alignment keys */
-#if defined(__GNUC__)
-#define CL_ALIGNED(_x) __attribute__((aligned(_x)))
-#elif defined(_WIN32) && (_MSC_VER)
-/* Alignment keys neutered on windows because MSVC can't swallow function arguments with alignment requirements */
-/* http://msdn.microsoft.com/en-us/library/373ak2y1%28VS.71%29.aspx */
-/* #include <crtdefs.h> */
-/* #define CL_ALIGNED(_x) _CRT_ALIGN(_x) */
-#define CL_ALIGNED(_x)
-#else
-#warning Need to implement some method to align data here
-#define CL_ALIGNED(_x)
-#endif
-
-/* Indicate whether .xyzw, .s0123 and .hi.lo are supported */
-#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || (defined(_MSC_VER) && !defined(__STDC__))
-/* .xyzw and .s0123...{f|F} are supported */
-#define CL_HAS_NAMED_VECTOR_FIELDS 1
-/* .hi and .lo are supported */
-#define CL_HAS_HI_LO_VECTOR_FIELDS 1
-
-#define CL_NAMED_STRUCT_SUPPORTED
-#endif
-
-#if defined(CL_NAMED_STRUCT_SUPPORTED) && defined(_MSC_VER)
-#define __extension__ __pragma(warning(suppress : 4201))
-#endif
-
- /* Define cl_vector types */
-
- /* ---- cl_charn ---- */
- typedef union {
- cl_char CL_ALIGNED(2) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_char x, y;
- };
- __extension__ struct
- {
- cl_char s0, s1;
- };
- __extension__ struct
- {
- cl_char lo, hi;
- };
-#endif
-#if defined(__CL_CHAR2__)
- __cl_char2 v2;
-#endif
- } cl_char2;
-
- typedef union {
- cl_char CL_ALIGNED(4) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_char x, y, z, w;
- };
- __extension__ struct
- {
- cl_char s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_char2 lo, hi;
- };
-#endif
-#if defined(__CL_CHAR2__)
- __cl_char2 v2[2];
-#endif
-#if defined(__CL_CHAR4__)
- __cl_char4 v4;
-#endif
- } cl_char4;
-
- /* cl_char3 is identical in size, alignment and behavior to cl_char4. See section 6.1.5. */
- typedef cl_char4 cl_char3;
-
- typedef union {
- cl_char CL_ALIGNED(8) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_char x, y, z, w;
- };
- __extension__ struct
- {
- cl_char s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_char4 lo, hi;
- };
-#endif
-#if defined(__CL_CHAR2__)
- __cl_char2 v2[4];
-#endif
-#if defined(__CL_CHAR4__)
- __cl_char4 v4[2];
-#endif
-#if defined(__CL_CHAR8__)
- __cl_char8 v8;
-#endif
- } cl_char8;
-
- typedef union {
- cl_char CL_ALIGNED(16) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_char x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_char s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_char8 lo, hi;
- };
-#endif
-#if defined(__CL_CHAR2__)
- __cl_char2 v2[8];
-#endif
-#if defined(__CL_CHAR4__)
- __cl_char4 v4[4];
-#endif
-#if defined(__CL_CHAR8__)
- __cl_char8 v8[2];
-#endif
-#if defined(__CL_CHAR16__)
- __cl_char16 v16;
-#endif
- } cl_char16;
-
- /* ---- cl_ucharn ---- */
- typedef union {
- cl_uchar CL_ALIGNED(2) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uchar x, y;
- };
- __extension__ struct
- {
- cl_uchar s0, s1;
- };
- __extension__ struct
- {
- cl_uchar lo, hi;
- };
-#endif
-#if defined(__cl_uchar2__)
- __cl_uchar2 v2;
-#endif
- } cl_uchar2;
-
- typedef union {
- cl_uchar CL_ALIGNED(4) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uchar x, y, z, w;
- };
- __extension__ struct
- {
- cl_uchar s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_uchar2 lo, hi;
- };
-#endif
-#if defined(__CL_UCHAR2__)
- __cl_uchar2 v2[2];
-#endif
-#if defined(__CL_UCHAR4__)
- __cl_uchar4 v4;
-#endif
- } cl_uchar4;
-
- /* cl_uchar3 is identical in size, alignment and behavior to cl_uchar4. See section 6.1.5. */
- typedef cl_uchar4 cl_uchar3;
-
- typedef union {
- cl_uchar CL_ALIGNED(8) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uchar x, y, z, w;
- };
- __extension__ struct
- {
- cl_uchar s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_uchar4 lo, hi;
- };
-#endif
-#if defined(__CL_UCHAR2__)
- __cl_uchar2 v2[4];
-#endif
-#if defined(__CL_UCHAR4__)
- __cl_uchar4 v4[2];
-#endif
-#if defined(__CL_UCHAR8__)
- __cl_uchar8 v8;
-#endif
- } cl_uchar8;
-
- typedef union {
- cl_uchar CL_ALIGNED(16) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uchar x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_uchar s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_uchar8 lo, hi;
- };
-#endif
-#if defined(__CL_UCHAR2__)
- __cl_uchar2 v2[8];
-#endif
-#if defined(__CL_UCHAR4__)
- __cl_uchar4 v4[4];
-#endif
-#if defined(__CL_UCHAR8__)
- __cl_uchar8 v8[2];
-#endif
-#if defined(__CL_UCHAR16__)
- __cl_uchar16 v16;
-#endif
- } cl_uchar16;
-
- /* ---- cl_shortn ---- */
- typedef union {
- cl_short CL_ALIGNED(4) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_short x, y;
- };
- __extension__ struct
- {
- cl_short s0, s1;
- };
- __extension__ struct
- {
- cl_short lo, hi;
- };
-#endif
-#if defined(__CL_SHORT2__)
- __cl_short2 v2;
-#endif
- } cl_short2;
-
- typedef union {
- cl_short CL_ALIGNED(8) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_short x, y, z, w;
- };
- __extension__ struct
- {
- cl_short s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_short2 lo, hi;
- };
-#endif
-#if defined(__CL_SHORT2__)
- __cl_short2 v2[2];
-#endif
-#if defined(__CL_SHORT4__)
- __cl_short4 v4;
-#endif
- } cl_short4;
-
- /* cl_short3 is identical in size, alignment and behavior to cl_short4. See section 6.1.5. */
- typedef cl_short4 cl_short3;
-
- typedef union {
- cl_short CL_ALIGNED(16) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_short x, y, z, w;
- };
- __extension__ struct
- {
- cl_short s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_short4 lo, hi;
- };
-#endif
-#if defined(__CL_SHORT2__)
- __cl_short2 v2[4];
-#endif
-#if defined(__CL_SHORT4__)
- __cl_short4 v4[2];
-#endif
-#if defined(__CL_SHORT8__)
- __cl_short8 v8;
-#endif
- } cl_short8;
-
- typedef union {
- cl_short CL_ALIGNED(32) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_short x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_short s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_short8 lo, hi;
- };
-#endif
-#if defined(__CL_SHORT2__)
- __cl_short2 v2[8];
-#endif
-#if defined(__CL_SHORT4__)
- __cl_short4 v4[4];
-#endif
-#if defined(__CL_SHORT8__)
- __cl_short8 v8[2];
-#endif
-#if defined(__CL_SHORT16__)
- __cl_short16 v16;
-#endif
- } cl_short16;
-
- /* ---- cl_ushortn ---- */
- typedef union {
- cl_ushort CL_ALIGNED(4) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ushort x, y;
- };
- __extension__ struct
- {
- cl_ushort s0, s1;
- };
- __extension__ struct
- {
- cl_ushort lo, hi;
- };
-#endif
-#if defined(__CL_USHORT2__)
- __cl_ushort2 v2;
-#endif
- } cl_ushort2;
-
- typedef union {
- cl_ushort CL_ALIGNED(8) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ushort x, y, z, w;
- };
- __extension__ struct
- {
- cl_ushort s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_ushort2 lo, hi;
- };
-#endif
-#if defined(__CL_USHORT2__)
- __cl_ushort2 v2[2];
-#endif
-#if defined(__CL_USHORT4__)
- __cl_ushort4 v4;
-#endif
- } cl_ushort4;
-
- /* cl_ushort3 is identical in size, alignment and behavior to cl_ushort4. See section 6.1.5. */
- typedef cl_ushort4 cl_ushort3;
-
- typedef union {
- cl_ushort CL_ALIGNED(16) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ushort x, y, z, w;
- };
- __extension__ struct
- {
- cl_ushort s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_ushort4 lo, hi;
- };
-#endif
-#if defined(__CL_USHORT2__)
- __cl_ushort2 v2[4];
-#endif
-#if defined(__CL_USHORT4__)
- __cl_ushort4 v4[2];
-#endif
-#if defined(__CL_USHORT8__)
- __cl_ushort8 v8;
-#endif
- } cl_ushort8;
-
- typedef union {
- cl_ushort CL_ALIGNED(32) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ushort x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_ushort s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_ushort8 lo, hi;
- };
-#endif
-#if defined(__CL_USHORT2__)
- __cl_ushort2 v2[8];
-#endif
-#if defined(__CL_USHORT4__)
- __cl_ushort4 v4[4];
-#endif
-#if defined(__CL_USHORT8__)
- __cl_ushort8 v8[2];
-#endif
-#if defined(__CL_USHORT16__)
- __cl_ushort16 v16;
-#endif
- } cl_ushort16;
-
- /* ---- cl_intn ---- */
- typedef union {
- cl_int CL_ALIGNED(8) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_int x, y;
- };
- __extension__ struct
- {
- cl_int s0, s1;
- };
- __extension__ struct
- {
- cl_int lo, hi;
- };
-#endif
-#if defined(__CL_INT2__)
- __cl_int2 v2;
-#endif
- } cl_int2;
-
- typedef union {
- cl_int CL_ALIGNED(16) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_int x, y, z, w;
- };
- __extension__ struct
- {
- cl_int s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_int2 lo, hi;
- };
-#endif
-#if defined(__CL_INT2__)
- __cl_int2 v2[2];
-#endif
-#if defined(__CL_INT4__)
- __cl_int4 v4;
-#endif
- } cl_int4;
-
- /* cl_int3 is identical in size, alignment and behavior to cl_int4. See section 6.1.5. */
- typedef cl_int4 cl_int3;
-
- typedef union {
- cl_int CL_ALIGNED(32) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_int x, y, z, w;
- };
- __extension__ struct
- {
- cl_int s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_int4 lo, hi;
- };
-#endif
-#if defined(__CL_INT2__)
- __cl_int2 v2[4];
-#endif
-#if defined(__CL_INT4__)
- __cl_int4 v4[2];
-#endif
-#if defined(__CL_INT8__)
- __cl_int8 v8;
-#endif
- } cl_int8;
-
- typedef union {
- cl_int CL_ALIGNED(64) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_int x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_int s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_int8 lo, hi;
- };
-#endif
-#if defined(__CL_INT2__)
- __cl_int2 v2[8];
-#endif
-#if defined(__CL_INT4__)
- __cl_int4 v4[4];
-#endif
-#if defined(__CL_INT8__)
- __cl_int8 v8[2];
-#endif
-#if defined(__CL_INT16__)
- __cl_int16 v16;
-#endif
- } cl_int16;
-
- /* ---- cl_uintn ---- */
- typedef union {
- cl_uint CL_ALIGNED(8) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uint x, y;
- };
- __extension__ struct
- {
- cl_uint s0, s1;
- };
- __extension__ struct
- {
- cl_uint lo, hi;
- };
-#endif
-#if defined(__CL_UINT2__)
- __cl_uint2 v2;
-#endif
- } cl_uint2;
-
- typedef union {
- cl_uint CL_ALIGNED(16) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uint x, y, z, w;
- };
- __extension__ struct
- {
- cl_uint s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_uint2 lo, hi;
- };
-#endif
-#if defined(__CL_UINT2__)
- __cl_uint2 v2[2];
-#endif
-#if defined(__CL_UINT4__)
- __cl_uint4 v4;
-#endif
- } cl_uint4;
-
- /* cl_uint3 is identical in size, alignment and behavior to cl_uint4. See section 6.1.5. */
- typedef cl_uint4 cl_uint3;
-
- typedef union {
- cl_uint CL_ALIGNED(32) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uint x, y, z, w;
- };
- __extension__ struct
- {
- cl_uint s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_uint4 lo, hi;
- };
-#endif
-#if defined(__CL_UINT2__)
- __cl_uint2 v2[4];
-#endif
-#if defined(__CL_UINT4__)
- __cl_uint4 v4[2];
-#endif
-#if defined(__CL_UINT8__)
- __cl_uint8 v8;
-#endif
- } cl_uint8;
-
- typedef union {
- cl_uint CL_ALIGNED(64) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_uint x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_uint s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_uint8 lo, hi;
- };
-#endif
-#if defined(__CL_UINT2__)
- __cl_uint2 v2[8];
-#endif
-#if defined(__CL_UINT4__)
- __cl_uint4 v4[4];
-#endif
-#if defined(__CL_UINT8__)
- __cl_uint8 v8[2];
-#endif
-#if defined(__CL_UINT16__)
- __cl_uint16 v16;
-#endif
- } cl_uint16;
-
- /* ---- cl_longn ---- */
- typedef union {
- cl_long CL_ALIGNED(16) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_long x, y;
- };
- __extension__ struct
- {
- cl_long s0, s1;
- };
- __extension__ struct
- {
- cl_long lo, hi;
- };
-#endif
-#if defined(__CL_LONG2__)
- __cl_long2 v2;
-#endif
- } cl_long2;
-
- typedef union {
- cl_long CL_ALIGNED(32) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_long x, y, z, w;
- };
- __extension__ struct
- {
- cl_long s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_long2 lo, hi;
- };
-#endif
-#if defined(__CL_LONG2__)
- __cl_long2 v2[2];
-#endif
-#if defined(__CL_LONG4__)
- __cl_long4 v4;
-#endif
- } cl_long4;
-
- /* cl_long3 is identical in size, alignment and behavior to cl_long4. See section 6.1.5. */
- typedef cl_long4 cl_long3;
-
- typedef union {
- cl_long CL_ALIGNED(64) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_long x, y, z, w;
- };
- __extension__ struct
- {
- cl_long s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_long4 lo, hi;
- };
-#endif
-#if defined(__CL_LONG2__)
- __cl_long2 v2[4];
-#endif
-#if defined(__CL_LONG4__)
- __cl_long4 v4[2];
-#endif
-#if defined(__CL_LONG8__)
- __cl_long8 v8;
-#endif
- } cl_long8;
-
- typedef union {
- cl_long CL_ALIGNED(128) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_long x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_long s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_long8 lo, hi;
- };
-#endif
-#if defined(__CL_LONG2__)
- __cl_long2 v2[8];
-#endif
-#if defined(__CL_LONG4__)
- __cl_long4 v4[4];
-#endif
-#if defined(__CL_LONG8__)
- __cl_long8 v8[2];
-#endif
-#if defined(__CL_LONG16__)
- __cl_long16 v16;
-#endif
- } cl_long16;
-
- /* ---- cl_ulongn ---- */
- typedef union {
- cl_ulong CL_ALIGNED(16) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ulong x, y;
- };
- __extension__ struct
- {
- cl_ulong s0, s1;
- };
- __extension__ struct
- {
- cl_ulong lo, hi;
- };
-#endif
-#if defined(__CL_ULONG2__)
- __cl_ulong2 v2;
-#endif
- } cl_ulong2;
-
- typedef union {
- cl_ulong CL_ALIGNED(32) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ulong x, y, z, w;
- };
- __extension__ struct
- {
- cl_ulong s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_ulong2 lo, hi;
- };
-#endif
-#if defined(__CL_ULONG2__)
- __cl_ulong2 v2[2];
-#endif
-#if defined(__CL_ULONG4__)
- __cl_ulong4 v4;
-#endif
- } cl_ulong4;
-
- /* cl_ulong3 is identical in size, alignment and behavior to cl_ulong4. See section 6.1.5. */
- typedef cl_ulong4 cl_ulong3;
-
- typedef union {
- cl_ulong CL_ALIGNED(64) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ulong x, y, z, w;
- };
- __extension__ struct
- {
- cl_ulong s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_ulong4 lo, hi;
- };
-#endif
-#if defined(__CL_ULONG2__)
- __cl_ulong2 v2[4];
-#endif
-#if defined(__CL_ULONG4__)
- __cl_ulong4 v4[2];
-#endif
-#if defined(__CL_ULONG8__)
- __cl_ulong8 v8;
-#endif
- } cl_ulong8;
-
- typedef union {
- cl_ulong CL_ALIGNED(128) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_ulong x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_ulong s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_ulong8 lo, hi;
- };
-#endif
-#if defined(__CL_ULONG2__)
- __cl_ulong2 v2[8];
-#endif
-#if defined(__CL_ULONG4__)
- __cl_ulong4 v4[4];
-#endif
-#if defined(__CL_ULONG8__)
- __cl_ulong8 v8[2];
-#endif
-#if defined(__CL_ULONG16__)
- __cl_ulong16 v16;
-#endif
- } cl_ulong16;
-
- /* --- cl_floatn ---- */
-
- typedef union {
- cl_float CL_ALIGNED(8) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_float x, y;
- };
- __extension__ struct
- {
- cl_float s0, s1;
- };
- __extension__ struct
- {
- cl_float lo, hi;
- };
-#endif
-#if defined(__CL_FLOAT2__)
- __cl_float2 v2;
-#endif
- } cl_float2;
-
- typedef union {
- cl_float CL_ALIGNED(16) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_float x, y, z, w;
- };
- __extension__ struct
- {
- cl_float s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_float2 lo, hi;
- };
-#endif
-#if defined(__CL_FLOAT2__)
- __cl_float2 v2[2];
-#endif
-#if defined(__CL_FLOAT4__)
- __cl_float4 v4;
-#endif
- } cl_float4;
-
- /* cl_float3 is identical in size, alignment and behavior to cl_float4. See section 6.1.5. */
- typedef cl_float4 cl_float3;
-
- typedef union {
- cl_float CL_ALIGNED(32) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_float x, y, z, w;
- };
- __extension__ struct
- {
- cl_float s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_float4 lo, hi;
- };
-#endif
-#if defined(__CL_FLOAT2__)
- __cl_float2 v2[4];
-#endif
-#if defined(__CL_FLOAT4__)
- __cl_float4 v4[2];
-#endif
-#if defined(__CL_FLOAT8__)
- __cl_float8 v8;
-#endif
- } cl_float8;
-
- typedef union {
- cl_float CL_ALIGNED(64) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_float x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_float s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_float8 lo, hi;
- };
-#endif
-#if defined(__CL_FLOAT2__)
- __cl_float2 v2[8];
-#endif
-#if defined(__CL_FLOAT4__)
- __cl_float4 v4[4];
-#endif
-#if defined(__CL_FLOAT8__)
- __cl_float8 v8[2];
-#endif
-#if defined(__CL_FLOAT16__)
- __cl_float16 v16;
-#endif
- } cl_float16;
-
- /* --- cl_doublen ---- */
-
- typedef union {
- cl_double CL_ALIGNED(16) s[2];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_double x, y;
- };
- __extension__ struct
- {
- cl_double s0, s1;
- };
- __extension__ struct
- {
- cl_double lo, hi;
- };
-#endif
-#if defined(__CL_DOUBLE2__)
- __cl_double2 v2;
-#endif
- } cl_double2;
-
- typedef union {
- cl_double CL_ALIGNED(32) s[4];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_double x, y, z, w;
- };
- __extension__ struct
- {
- cl_double s0, s1, s2, s3;
- };
- __extension__ struct
- {
- cl_double2 lo, hi;
- };
-#endif
-#if defined(__CL_DOUBLE2__)
- __cl_double2 v2[2];
-#endif
-#if defined(__CL_DOUBLE4__)
- __cl_double4 v4;
-#endif
- } cl_double4;
-
- /* cl_double3 is identical in size, alignment and behavior to cl_double4. See section 6.1.5. */
- typedef cl_double4 cl_double3;
-
- typedef union {
- cl_double CL_ALIGNED(64) s[8];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_double x, y, z, w;
- };
- __extension__ struct
- {
- cl_double s0, s1, s2, s3, s4, s5, s6, s7;
- };
- __extension__ struct
- {
- cl_double4 lo, hi;
- };
-#endif
-#if defined(__CL_DOUBLE2__)
- __cl_double2 v2[4];
-#endif
-#if defined(__CL_DOUBLE4__)
- __cl_double4 v4[2];
-#endif
-#if defined(__CL_DOUBLE8__)
- __cl_double8 v8;
-#endif
- } cl_double8;
-
- typedef union {
- cl_double CL_ALIGNED(128) s[16];
-#if defined(CL_NAMED_STRUCT_SUPPORTED)
- __extension__ struct
- {
- cl_double x, y, z, w, __spacer4, __spacer5, __spacer6, __spacer7, __spacer8, __spacer9, sa, sb, sc, sd, se, sf;
- };
- __extension__ struct
- {
- cl_double s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sA, sB, sC, sD, sE, sF;
- };
- __extension__ struct
- {
- cl_double8 lo, hi;
- };
-#endif
-#if defined(__CL_DOUBLE2__)
- __cl_double2 v2[8];
-#endif
-#if defined(__CL_DOUBLE4__)
- __cl_double4 v4[4];
-#endif
-#if defined(__CL_DOUBLE8__)
- __cl_double8 v8[2];
-#endif
-#if defined(__CL_DOUBLE16__)
- __cl_double16 v16;
-#endif
- } cl_double16;
-
-/* Macro to facilitate debugging
- * Usage:
- * Place CL_PROGRAM_STRING_DEBUG_INFO on the line before the first line of your source.
- * The first line ends with: CL_PROGRAM_STRING_BEGIN \"
- * Each line thereafter of OpenCL C source must end with: \n\
- * The last line ends in ";
- *
- * Example:
- *
- * const char *my_program = CL_PROGRAM_STRING_BEGIN "\
- * kernel void foo( int a, float * b ) \n\
- * { \n\
- * // my comment \n\
- * *b[ get_global_id(0)] = a; \n\
- * } \n\
- * ";
- *
- * This should correctly set up the line, (column) and file information for your source
- * string so you can do source level debugging.
- */
-#define __CL_STRINGIFY(_x) #_x
-#define _CL_STRINGIFY(_x) __CL_STRINGIFY(_x)
-#define CL_PROGRAM_STRING_DEBUG_INFO "#line " _CL_STRINGIFY(__LINE__) " \"" __FILE__ "\" \n\n"
-
- // CL.h contents
- /******************************************************************************/
-
- typedef struct _cl_platform_id *cl_platform_id;
- typedef struct _cl_device_id *cl_device_id;
- typedef struct _cl_context *cl_context;
- typedef struct _cl_command_queue *cl_command_queue;
- typedef struct _cl_mem *cl_mem;
- typedef struct _cl_program *cl_program;
- typedef struct _cl_kernel *cl_kernel;
- typedef struct _cl_event *cl_event;
- typedef struct _cl_sampler *cl_sampler;
-
- typedef cl_uint cl_bool; /* WARNING! Unlike cl_ types in cl_platform.h, cl_bool is not guaranteed to be the same size as the bool in kernels. */
- typedef cl_ulong cl_bitfield;
- typedef cl_bitfield cl_device_type;
- typedef cl_uint cl_platform_info;
- typedef cl_uint cl_device_info;
- typedef cl_bitfield cl_device_fp_config;
- typedef cl_uint cl_device_mem_cache_type;
- typedef cl_uint cl_device_local_mem_type;
- typedef cl_bitfield cl_device_exec_capabilities;
- typedef cl_bitfield cl_command_queue_properties;
-
- typedef intptr_t cl_context_properties;
- typedef cl_uint cl_context_info;
- typedef cl_uint cl_command_queue_info;
- typedef cl_uint cl_channel_order;
- typedef cl_uint cl_channel_type;
- typedef cl_bitfield cl_mem_flags;
- typedef cl_uint cl_mem_object_type;
- typedef cl_uint cl_mem_info;
- typedef cl_uint cl_image_info;
- typedef cl_uint cl_buffer_create_type;
- typedef cl_uint cl_addressing_mode;
- typedef cl_uint cl_filter_mode;
- typedef cl_uint cl_sampler_info;
- typedef cl_bitfield cl_map_flags;
- typedef cl_uint cl_program_info;
- typedef cl_uint cl_program_build_info;
- typedef cl_int cl_build_status;
- typedef cl_uint cl_kernel_info;
- typedef cl_uint cl_kernel_work_group_info;
- typedef cl_uint cl_event_info;
- typedef cl_uint cl_command_type;
- typedef cl_uint cl_profiling_info;
-
- typedef struct _cl_image_format
- {
- cl_channel_order image_channel_order;
- cl_channel_type image_channel_data_type;
- } cl_image_format;
-
- typedef struct _cl_buffer_region
- {
- size_t origin;
- size_t size;
- } cl_buffer_region;
-
-/******************************************************************************/
-
-/* Error Codes */
-#define CL_SUCCESS 0
-#define CL_DEVICE_NOT_FOUND -1
-#define CL_DEVICE_NOT_AVAILABLE -2
-#define CL_COMPILER_NOT_AVAILABLE -3
-#define CL_MEM_OBJECT_ALLOCATION_FAILURE -4
-#define CL_OUT_OF_RESOURCES -5
-#define CL_OUT_OF_HOST_MEMORY -6
-#define CL_PROFILING_INFO_NOT_AVAILABLE -7
-#define CL_MEM_COPY_OVERLAP -8
-#define CL_IMAGE_FORMAT_MISMATCH -9
-#define CL_IMAGE_FORMAT_NOT_SUPPORTED -10
-#define CL_BUILD_PROGRAM_FAILURE -11
-#define CL_MAP_FAILURE -12
-#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13
-#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14
-
-#define CL_INVALID_VALUE -30
-#define CL_INVALID_DEVICE_TYPE -31
-#define CL_INVALID_PLATFORM -32
-#define CL_INVALID_DEVICE -33
-#define CL_INVALID_CONTEXT -34
-#define CL_INVALID_QUEUE_PROPERTIES -35
-#define CL_INVALID_COMMAND_QUEUE -36
-#define CL_INVALID_HOST_PTR -37
-#define CL_INVALID_MEM_OBJECT -38
-#define CL_INVALID_IMAGE_FORMAT_DESCRIPTOR -39
-#define CL_INVALID_IMAGE_SIZE -40
-#define CL_INVALID_SAMPLER -41
-#define CL_INVALID_BINARY -42
-#define CL_INVALID_BUILD_OPTIONS -43
-#define CL_INVALID_PROGRAM -44
-#define CL_INVALID_PROGRAM_EXECUTABLE -45
-#define CL_INVALID_KERNEL_NAME -46
-#define CL_INVALID_KERNEL_DEFINITION -47
-#define CL_INVALID_KERNEL -48
-#define CL_INVALID_ARG_INDEX -49
-#define CL_INVALID_ARG_VALUE -50
-#define CL_INVALID_ARG_SIZE -51
-#define CL_INVALID_KERNEL_ARGS -52
-#define CL_INVALID_WORK_DIMENSION -53
-#define CL_INVALID_WORK_GROUP_SIZE -54
-#define CL_INVALID_WORK_ITEM_SIZE -55
-#define CL_INVALID_GLOBAL_OFFSET -56
-#define CL_INVALID_EVENT_WAIT_LIST -57
-#define CL_INVALID_EVENT -58
-#define CL_INVALID_OPERATION -59
-#define CL_INVALID_GL_OBJECT -60
-#define CL_INVALID_BUFFER_SIZE -61
-#define CL_INVALID_MIP_LEVEL -62
-#define CL_INVALID_GLOBAL_WORK_SIZE -63
-#define CL_INVALID_PROPERTY -64
-
-/* OpenCL Version */
-#define CL_VERSION_1_0 1
-#define CL_VERSION_1_1 1
-
-/* cl_bool */
-#define CL_FALSE 0
-#define CL_TRUE 1
-
-/* cl_platform_info */
-#define CL_PLATFORM_PROFILE 0x0900
-#define CL_PLATFORM_VERSION 0x0901
-#define CL_PLATFORM_NAME 0x0902
-#define CL_PLATFORM_VENDOR 0x0903
-#define CL_PLATFORM_EXTENSIONS 0x0904
-
-/* cl_device_type - bitfield */
-#define CL_DEVICE_TYPE_DEFAULT (1 << 0)
-#define CL_DEVICE_TYPE_CPU (1 << 1)
-#define CL_DEVICE_TYPE_GPU (1 << 2)
-#define CL_DEVICE_TYPE_ACCELERATOR (1 << 3)
-#define CL_DEVICE_TYPE_ALL 0xFFFFFFFF
-
-/* cl_device_info */
-#define CL_DEVICE_TYPE 0x1000
-#define CL_DEVICE_VENDOR_ID 0x1001
-#define CL_DEVICE_MAX_COMPUTE_UNITS 0x1002
-#define CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS 0x1003
-#define CL_DEVICE_MAX_WORK_GROUP_SIZE 0x1004
-#define CL_DEVICE_MAX_WORK_ITEM_SIZES 0x1005
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR 0x1006
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT 0x1007
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT 0x1008
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG 0x1009
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT 0x100A
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE 0x100B
-#define CL_DEVICE_MAX_CLOCK_FREQUENCY 0x100C
-#define CL_DEVICE_ADDRESS_BITS 0x100D
-#define CL_DEVICE_MAX_READ_IMAGE_ARGS 0x100E
-#define CL_DEVICE_MAX_WRITE_IMAGE_ARGS 0x100F
-#define CL_DEVICE_MAX_MEM_ALLOC_SIZE 0x1010
-#define CL_DEVICE_IMAGE2D_MAX_WIDTH 0x1011
-#define CL_DEVICE_IMAGE2D_MAX_HEIGHT 0x1012
-#define CL_DEVICE_IMAGE3D_MAX_WIDTH 0x1013
-#define CL_DEVICE_IMAGE3D_MAX_HEIGHT 0x1014
-#define CL_DEVICE_IMAGE3D_MAX_DEPTH 0x1015
-#define CL_DEVICE_IMAGE_SUPPORT 0x1016
-#define CL_DEVICE_MAX_PARAMETER_SIZE 0x1017
-#define CL_DEVICE_MAX_SAMPLERS 0x1018
-#define CL_DEVICE_MEM_BASE_ADDR_ALIGN 0x1019
-#define CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE 0x101A
-#define CL_DEVICE_SINGLE_FP_CONFIG 0x101B
-#define CL_DEVICE_GLOBAL_MEM_CACHE_TYPE 0x101C
-#define CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE 0x101D
-#define CL_DEVICE_GLOBAL_MEM_CACHE_SIZE 0x101E
-#define CL_DEVICE_GLOBAL_MEM_SIZE 0x101F
-#define CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE 0x1020
-#define CL_DEVICE_MAX_CONSTANT_ARGS 0x1021
-#define CL_DEVICE_LOCAL_MEM_TYPE 0x1022
-#define CL_DEVICE_LOCAL_MEM_SIZE 0x1023
-#define CL_DEVICE_ERROR_CORRECTION_SUPPORT 0x1024
-#define CL_DEVICE_PROFILING_TIMER_RESOLUTION 0x1025
-#define CL_DEVICE_ENDIAN_LITTLE 0x1026
-#define CL_DEVICE_AVAILABLE 0x1027
-#define CL_DEVICE_COMPILER_AVAILABLE 0x1028
-#define CL_DEVICE_EXECUTION_CAPABILITIES 0x1029
-#define CL_DEVICE_QUEUE_PROPERTIES 0x102A
-#define CL_DEVICE_NAME 0x102B
-#define CL_DEVICE_VENDOR 0x102C
-#define CL_DRIVER_VERSION 0x102D
-#define CL_DEVICE_PROFILE 0x102E
-#define CL_DEVICE_VERSION 0x102F
-#define CL_DEVICE_EXTENSIONS 0x1030
-#define CL_DEVICE_PLATFORM 0x1031
-/* 0x1032 reserved for CL_DEVICE_DOUBLE_FP_CONFIG */
-/* 0x1033 reserved for CL_DEVICE_HALF_FP_CONFIG */
-#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034
-#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B
-#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C
-#define CL_DEVICE_OPENCL_C_VERSION 0x103D
-
-/* cl_device_fp_config - bitfield */
-#define CL_FP_DENORM (1 << 0)
-#define CL_FP_INF_NAN (1 << 1)
-#define CL_FP_ROUND_TO_NEAREST (1 << 2)
-#define CL_FP_ROUND_TO_ZERO (1 << 3)
-#define CL_FP_ROUND_TO_INF (1 << 4)
-#define CL_FP_FMA (1 << 5)
-#define CL_FP_SOFT_FLOAT (1 << 6)
-
-/* cl_device_mem_cache_type */
-#define CL_NONE 0x0
-#define CL_READ_ONLY_CACHE 0x1
-#define CL_READ_WRITE_CACHE 0x2
-
-/* cl_device_local_mem_type */
-#define CL_LOCAL 0x1
-#define CL_GLOBAL 0x2
-
-/* cl_device_exec_capabilities - bitfield */
-#define CL_EXEC_KERNEL (1 << 0)
-#define CL_EXEC_NATIVE_KERNEL (1 << 1)
-
-/* cl_command_queue_properties - bitfield */
-#define CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE (1 << 0)
-#define CL_QUEUE_PROFILING_ENABLE (1 << 1)
-
-/* cl_context_info */
-#define CL_CONTEXT_REFERENCE_COUNT 0x1080
-#define CL_CONTEXT_DEVICES 0x1081
-#define CL_CONTEXT_PROPERTIES 0x1082
-#define CL_CONTEXT_NUM_DEVICES 0x1083
-
-/* cl_context_info + cl_context_properties */
-#define CL_CONTEXT_PLATFORM 0x1084
-
-/* cl_command_queue_info */
-#define CL_QUEUE_CONTEXT 0x1090
-#define CL_QUEUE_DEVICE 0x1091
-#define CL_QUEUE_REFERENCE_COUNT 0x1092
-#define CL_QUEUE_PROPERTIES 0x1093
-
-/* cl_mem_flags - bitfield */
-#define CL_MEM_READ_WRITE (1 << 0)
-#define CL_MEM_WRITE_ONLY (1 << 1)
-#define CL_MEM_READ_ONLY (1 << 2)
-#define CL_MEM_USE_HOST_PTR (1 << 3)
-#define CL_MEM_ALLOC_HOST_PTR (1 << 4)
-#define CL_MEM_COPY_HOST_PTR (1 << 5)
-
-/* cl_channel_order */
-#define CL_R 0x10B0
-#define CL_A 0x10B1
-#define CL_RG 0x10B2
-#define CL_RA 0x10B3
-#define CL_RGB 0x10B4
-#define CL_RGBA 0x10B5
-#define CL_BGRA 0x10B6
-#define CL_ARGB 0x10B7
-#define CL_INTENSITY 0x10B8
-#define CL_LUMINANCE 0x10B9
-#define CL_Rx 0x10BA
-#define CL_RGx 0x10BB
-#define CL_RGBx 0x10BC
-
-/* cl_channel_type */
-#define CL_SNORM_INT8 0x10D0
-#define CL_SNORM_INT16 0x10D1
-#define CL_UNORM_INT8 0x10D2
-#define CL_UNORM_INT16 0x10D3
-#define CL_UNORM_SHORT_565 0x10D4
-#define CL_UNORM_SHORT_555 0x10D5
-#define CL_UNORM_INT_101010 0x10D6
-#define CL_SIGNED_INT8 0x10D7
-#define CL_SIGNED_INT16 0x10D8
-#define CL_SIGNED_INT32 0x10D9
-#define CL_UNSIGNED_INT8 0x10DA
-#define CL_UNSIGNED_INT16 0x10DB
-#define CL_UNSIGNED_INT32 0x10DC
-#define CL_HALF_FLOAT 0x10DD
-#define CL_FLOAT 0x10DE
-
-/* cl_mem_object_type */
-#define CL_MEM_OBJECT_BUFFER 0x10F0
-#define CL_MEM_OBJECT_IMAGE2D 0x10F1
-#define CL_MEM_OBJECT_IMAGE3D 0x10F2
-
-/* cl_mem_info */
-#define CL_MEM_TYPE 0x1100
-#define CL_MEM_FLAGS 0x1101
-#define CL_MEM_SIZE 0x1102
-#define CL_MEM_HOST_PTR 0x1103
-#define CL_MEM_MAP_COUNT 0x1104
-#define CL_MEM_REFERENCE_COUNT 0x1105
-#define CL_MEM_CONTEXT 0x1106
-#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107
-#define CL_MEM_OFFSET 0x1108
-
-/* cl_image_info */
-#define CL_IMAGE_FORMAT 0x1110
-#define CL_IMAGE_ELEMENT_SIZE 0x1111
-#define CL_IMAGE_ROW_PITCH 0x1112
-#define CL_IMAGE_SLICE_PITCH 0x1113
-#define CL_IMAGE_WIDTH 0x1114
-#define CL_IMAGE_HEIGHT 0x1115
-#define CL_IMAGE_DEPTH 0x1116
-
-/* cl_addressing_mode */
-#define CL_ADDRESS_NONE 0x1130
-#define CL_ADDRESS_CLAMP_TO_EDGE 0x1131
-#define CL_ADDRESS_CLAMP 0x1132
-#define CL_ADDRESS_REPEAT 0x1133
-#define CL_ADDRESS_MIRRORED_REPEAT 0x1134
-
-/* cl_filter_mode */
-#define CL_FILTER_NEAREST 0x1140
-#define CL_FILTER_LINEAR 0x1141
-
-/* cl_sampler_info */
-#define CL_SAMPLER_REFERENCE_COUNT 0x1150
-#define CL_SAMPLER_CONTEXT 0x1151
-#define CL_SAMPLER_NORMALIZED_COORDS 0x1152
-#define CL_SAMPLER_ADDRESSING_MODE 0x1153
-#define CL_SAMPLER_FILTER_MODE 0x1154
-
-/* cl_map_flags - bitfield */
-#define CL_MAP_READ (1 << 0)
-#define CL_MAP_WRITE (1 << 1)
-
-/* cl_program_info */
-#define CL_PROGRAM_REFERENCE_COUNT 0x1160
-#define CL_PROGRAM_CONTEXT 0x1161
-#define CL_PROGRAM_NUM_DEVICES 0x1162
-#define CL_PROGRAM_DEVICES 0x1163
-#define CL_PROGRAM_SOURCE 0x1164
-#define CL_PROGRAM_BINARY_SIZES 0x1165
-#define CL_PROGRAM_BINARIES 0x1166
-
-/* cl_program_build_info */
-#define CL_PROGRAM_BUILD_STATUS 0x1181
-#define CL_PROGRAM_BUILD_OPTIONS 0x1182
-#define CL_PROGRAM_BUILD_LOG 0x1183
-
-/* cl_build_status */
-#define CL_BUILD_SUCCESS 0
-#define CL_BUILD_NONE -1
-#define CL_BUILD_ERROR -2
-#define CL_BUILD_IN_PROGRESS -3
-
-/* cl_kernel_info */
-#define CL_KERNEL_FUNCTION_NAME 0x1190
-#define CL_KERNEL_NUM_ARGS 0x1191
-#define CL_KERNEL_REFERENCE_COUNT 0x1192
-#define CL_KERNEL_CONTEXT 0x1193
-#define CL_KERNEL_PROGRAM 0x1194
-
-/* cl_kernel_work_group_info */
-#define CL_KERNEL_WORK_GROUP_SIZE 0x11B0
-#define CL_KERNEL_COMPILE_WORK_GROUP_SIZE 0x11B1
-#define CL_KERNEL_LOCAL_MEM_SIZE 0x11B2
-#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3
-#define CL_KERNEL_PRIVATE_MEM_SIZE 0x11B4
-
-/* cl_event_info */
-#define CL_EVENT_COMMAND_QUEUE 0x11D0
-#define CL_EVENT_COMMAND_TYPE 0x11D1
-#define CL_EVENT_REFERENCE_COUNT 0x11D2
-#define CL_EVENT_COMMAND_EXECUTION_STATUS 0x11D3
-#define CL_EVENT_CONTEXT 0x11D4
-
-/* cl_command_type */
-#define CL_COMMAND_NDRANGE_KERNEL 0x11F0
-#define CL_COMMAND_TASK 0x11F1
-#define CL_COMMAND_NATIVE_KERNEL 0x11F2
-#define CL_COMMAND_READ_BUFFER 0x11F3
-#define CL_COMMAND_WRITE_BUFFER 0x11F4
-#define CL_COMMAND_COPY_BUFFER 0x11F5
-#define CL_COMMAND_READ_IMAGE 0x11F6
-#define CL_COMMAND_WRITE_IMAGE 0x11F7
-#define CL_COMMAND_COPY_IMAGE 0x11F8
-#define CL_COMMAND_COPY_IMAGE_TO_BUFFER 0x11F9
-#define CL_COMMAND_COPY_BUFFER_TO_IMAGE 0x11FA
-#define CL_COMMAND_MAP_BUFFER 0x11FB
-#define CL_COMMAND_MAP_IMAGE 0x11FC
-#define CL_COMMAND_UNMAP_MEM_OBJECT 0x11FD
-#define CL_COMMAND_MARKER 0x11FE
-#define CL_COMMAND_ACQUIRE_GL_OBJECTS 0x11FF
-#define CL_COMMAND_RELEASE_GL_OBJECTS 0x1200
-#define CL_COMMAND_READ_BUFFER_RECT 0x1201
-#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202
-#define CL_COMMAND_COPY_BUFFER_RECT 0x1203
-#define CL_COMMAND_USER 0x1204
-
-/* command execution status */
-#define CL_COMPLETE 0x0
-#define CL_RUNNING 0x1
-#define CL_SUBMITTED 0x2
-#define CL_QUEUED 0x3
-
-/* cl_buffer_create_type */
-#define CL_BUFFER_CREATE_TYPE_REGION 0x1220
-
-/* cl_profiling_info */
-#define CL_PROFILING_COMMAND_QUEUED 0x1280
-#define CL_PROFILING_COMMAND_SUBMIT 0x1281
-#define CL_PROFILING_COMMAND_START 0x1282
-#define CL_PROFILING_COMMAND_END 0x1283
-
- /********************************************************************************************************/
-
- /********************************************************************************************************/
-
- /* Function signature typedef's */
-
- /* Platform API */
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETPLATFORMIDS)(cl_uint /* num_entries */,
- cl_platform_id * /* platforms */,
- cl_uint * /* num_platforms */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETPLATFORMINFO)(cl_platform_id /* platform */,
- cl_platform_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Device APIs */
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETDEVICEIDS)(cl_platform_id /* platform */,
- cl_device_type /* device_type */,
- cl_uint /* num_entries */,
- cl_device_id * /* devices */,
- cl_uint * /* num_devices */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETDEVICEINFO)(cl_device_id /* device */,
- cl_device_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- // Context APIs
- typedef CL_API_ENTRY cl_context(CL_API_CALL *
- PFNCLCREATECONTEXT)(const cl_context_properties * /* properties */,
- cl_uint /* num_devices */,
- const cl_device_id * /* devices */,
- void(CL_CALLBACK * /* pfn_notify */)(const char *, const void *, size_t, void *),
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_context(CL_API_CALL *
- PFNCLCREATECONTEXTFROMTYPE)(const cl_context_properties * /* properties */,
- cl_device_type /* device_type */,
- void(CL_CALLBACK * /* pfn_notify*/)(const char *, const void *, size_t, void *),
- void * /* user_data */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINCONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASECONTEXT)(cl_context /* context */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETCONTEXTINFO)(cl_context /* context */,
- cl_context_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Command Queue APIs */
- typedef CL_API_ENTRY cl_command_queue(CL_API_CALL *
- PFNCLCREATECOMMANDQUEUE)(cl_context /* context */,
- cl_device_id /* device */,
- cl_command_queue_properties /* properties */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINCOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASECOMMANDQUEUE)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETCOMMANDQUEUEINFO)(cl_command_queue /* command_queue */,
- cl_command_queue_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLSETCOMMANDQUEUEPROPERTY)(cl_command_queue /* command_queue */,
- cl_command_queue_properties /* properties */,
- cl_bool /* enable */,
- cl_command_queue_properties * /* old_properties */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Memory Object APIs */
- typedef CL_API_ENTRY cl_mem(CL_API_CALL *
- PFNCLCREATEBUFFER)(cl_context /* context */,
- cl_mem_flags /* flags */,
- size_t /* size */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_mem(CL_API_CALL *
- PFNCLCREATESUBBUFFER)(cl_mem /* buffer */,
- cl_mem_flags /* flags */,
- cl_buffer_create_type /* buffer_create_type */,
- const void * /* buffer_create_info */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_mem(CL_API_CALL *
- PFNCLCREATEIMAGE2D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_row_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_mem(CL_API_CALL *
- PFNCLCREATEIMAGE3D)(cl_context /* context */,
- cl_mem_flags /* flags */,
- const cl_image_format * /* image_format */,
- size_t /* image_width */,
- size_t /* image_height */,
- size_t /* image_depth */,
- size_t /* image_row_pitch */,
- size_t /* image_slice_pitch */,
- void * /* host_ptr */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASEMEMOBJECT)(cl_mem /* memobj */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETSUPPORTEDIMAGEFORMATS)(cl_context /* context */,
- cl_mem_flags /* flags */,
- cl_mem_object_type /* image_type */,
- cl_uint /* num_entries */,
- cl_image_format * /* image_formats */,
- cl_uint * /* num_image_formats */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETMEMOBJECTINFO)(cl_mem /* memobj */,
- cl_mem_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETIMAGEINFO)(cl_mem /* image */,
- cl_image_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLSETMEMOBJECTDESTRUCTORCALLBACK)(cl_mem /* memobj */,
- void(CL_CALLBACK * /*pfn_notify*/)(cl_mem /* memobj */, void * /*user_data*/),
- void * /*user_data */) CL_API_SUFFIX__VERSION_1_1;
-
- /* Sampler APIs */
- typedef CL_API_ENTRY cl_sampler(CL_API_CALL *
- PFNCLCREATESAMPLER)(cl_context /* context */,
- cl_bool /* normalized_coords */,
- cl_addressing_mode /* addressing_mode */,
- cl_filter_mode /* filter_mode */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINSAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASESAMPLER)(cl_sampler /* sampler */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETSAMPLERINFO)(cl_sampler /* sampler */,
- cl_sampler_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Program Object APIs */
- typedef CL_API_ENTRY cl_program(CL_API_CALL *
- PFNCLCREATEPROGRAMWITHSOURCE)(cl_context /* context */,
- cl_uint /* count */,
- const char ** /* strings */,
- const size_t * /* lengths */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_program(CL_API_CALL *
- PFNCLCREATEPROGRAMWITHBINARY)(cl_context /* context */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const size_t * /* lengths */,
- const unsigned char ** /* binaries */,
- cl_int * /* binary_status */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASEPROGRAM)(cl_program /* program */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLBUILDPROGRAM)(cl_program /* program */,
- cl_uint /* num_devices */,
- const cl_device_id * /* device_list */,
- const char * /* options */,
- void(CL_CALLBACK * /* pfn_notify */)(cl_program /* program */, void * /* user_data */),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLUNLOADCOMPILER)(void) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETPROGRAMINFO)(cl_program /* program */,
- cl_program_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETPROGRAMBUILDINFO)(cl_program /* program */,
- cl_device_id /* device */,
- cl_program_build_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Kernel Object APIs */
- typedef CL_API_ENTRY cl_kernel(CL_API_CALL *
- PFNCLCREATEKERNEL)(cl_program /* program */,
- const char * /* kernel_name */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLCREATEKERNELSINPROGRAM)(cl_program /* program */,
- cl_uint /* num_kernels */,
- cl_kernel * /* kernels */,
- cl_uint * /* num_kernels_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASEKERNEL)(cl_kernel /* kernel */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLSETKERNELARG)(cl_kernel /* kernel */,
- cl_uint /* arg_index */,
- size_t /* arg_size */,
- const void * /* arg_value */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETKERNELINFO)(cl_kernel /* kernel */,
- cl_kernel_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETKERNELWORKGROUPINFO)(cl_kernel /* kernel */,
- cl_device_id /* device */,
- cl_kernel_work_group_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- // Event Object APIs
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLWAITFOREVENTS)(cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETEVENTINFO)(cl_event /* event */,
- cl_event_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_event(CL_API_CALL *
- PFNCLCREATEUSEREVENT)(cl_context /* context */,
- cl_int * /* errcode_ret */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRETAINEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLRELEASEEVENT)(cl_event /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLSETUSEREVENTSTATUS)(cl_event /* event */,
- cl_int /* execution_status */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLSETEVENTCALLBACK)(cl_event /* event */,
- cl_int /* command_exec_callback_type */,
- void(CL_CALLBACK * /* pfn_notify */)(cl_event, cl_int, void *),
- void * /* user_data */) CL_API_SUFFIX__VERSION_1_1;
-
- /* Profiling APIs */
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLGETEVENTPROFILINGINFO)(cl_event /* event */,
- cl_profiling_info /* param_name */,
- size_t /* param_value_size */,
- void * /* param_value */,
- size_t * /* param_value_size_ret */) CL_API_SUFFIX__VERSION_1_0;
-
- // Flush and Finish APIs
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLFLUSH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLFINISH)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
- /* Enqueued Commands APIs */
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEREADBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- size_t /* offset */,
- size_t /* cb */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEREADBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_read */,
- const size_t * /* buffer_origin */,
- const size_t * /* host_origin */,
- const size_t * /* region */,
- size_t /* buffer_row_pitch */,
- size_t /* buffer_slice_pitch */,
- size_t /* host_row_pitch */,
- size_t /* host_slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEWRITEBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- size_t /* offset */,
- size_t /* cb */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEWRITEBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_write */,
- const size_t * /* buffer_origin */,
- const size_t * /* host_origin */,
- const size_t * /* region */,
- size_t /* buffer_row_pitch */,
- size_t /* buffer_slice_pitch */,
- size_t /* host_row_pitch */,
- size_t /* host_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUECOPYBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- size_t /* src_offset */,
- size_t /* dst_offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUECOPYBUFFERRECT)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin */,
- const size_t * /* dst_origin */,
- const size_t * /* region */,
- size_t /* src_row_pitch */,
- size_t /* src_slice_pitch */,
- size_t /* dst_row_pitch */,
- size_t /* dst_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_1;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEREADIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_read */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* row_pitch */,
- size_t /* slice_pitch */,
- void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEWRITEIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_write */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t /* input_row_pitch */,
- size_t /* input_slice_pitch */,
- const void * /* ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUECOPYIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_image */,
- const size_t * /* src_origin[3] */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUECOPYIMAGETOBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* src_image */,
- cl_mem /* dst_buffer */,
- const size_t * /* src_origin[3] */,
- const size_t * /* region[3] */,
- size_t /* dst_offset */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUECOPYBUFFERTOIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* src_buffer */,
- cl_mem /* dst_image */,
- size_t /* src_offset */,
- const size_t * /* dst_origin[3] */,
- const size_t * /* region[3] */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY void *(CL_API_CALL *
- PFNCLENQUEUEMAPBUFFER)(cl_command_queue /* command_queue */,
- cl_mem /* buffer */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- size_t /* offset */,
- size_t /* cb */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY void *(CL_API_CALL *
- PFNCLENQUEUEMAPIMAGE)(cl_command_queue /* command_queue */,
- cl_mem /* image */,
- cl_bool /* blocking_map */,
- cl_map_flags /* map_flags */,
- const size_t * /* origin[3] */,
- const size_t * /* region[3] */,
- size_t * /* image_row_pitch */,
- size_t * /* image_slice_pitch */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */,
- cl_int * /* errcode_ret */)CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEUNMAPMEMOBJECT)(cl_command_queue /* command_queue */,
- cl_mem /* memobj */,
- void * /* mapped_ptr */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUENDRANGEKERNEL)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* work_dim */,
- const size_t * /* global_work_offset */,
- const size_t * /* global_work_size */,
- const size_t * /* local_work_size */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUETASK)(cl_command_queue /* command_queue */,
- cl_kernel /* kernel */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUENATIVEKERNEL)(cl_command_queue /* command_queue */,
- void (*user_func)(void *),
- void * /* args */,
- size_t /* cb_args */,
- cl_uint /* num_mem_objects */,
- const cl_mem * /* mem_list */,
- const void ** /* args_mem_loc */,
- cl_uint /* num_events_in_wait_list */,
- const cl_event * /* event_wait_list */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEMARKER)(cl_command_queue /* command_queue */,
- cl_event * /* event */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEWAITFOREVENTS)(cl_command_queue /* command_queue */,
- cl_uint /* num_events */,
- const cl_event * /* event_list */) CL_API_SUFFIX__VERSION_1_0;
-
- typedef CL_API_ENTRY cl_int(CL_API_CALL *
- PFNCLENQUEUEBARRIER)(cl_command_queue /* command_queue */) CL_API_SUFFIX__VERSION_1_0;
-
- // Extension function access
- //
- // Returns the extension function address for the given function name,
- // or NULL if a valid function can not be found. The client must
- // check to make sure the address is not NULL, before using or
- // calling the returned function address.
- //
- typedef CL_API_ENTRY void *(CL_API_CALL *PFNCLGETEXTENSIONFUNCTIONADDRESS)(const char * /* func_name */)CL_API_SUFFIX__VERSION_1_0;
-
-#define CLEW_STATIC
-
-#ifdef CLEW_STATIC
-#define CLEWAPI extern
-#else
-#ifdef CLEW_BUILD
-#define CLEWAPI extern __declspec(dllexport)
-#else
-#define CLEWAPI extern __declspec(dllimport)
-#endif
-#endif
-
-#if defined(_WIN32)
-#define CLEW_FUN_EXPORT extern
-#else
-#define CLEW_FUN_EXPORT CLEWAPI
-#endif
-
-#define CLEW_GET_FUN(x) x
-
- // Variables holding function entry points
- CLEW_FUN_EXPORT PFNCLGETPLATFORMIDS __clewGetPlatformIDs;
- CLEW_FUN_EXPORT PFNCLGETPLATFORMINFO __clewGetPlatformInfo;
- CLEW_FUN_EXPORT PFNCLGETDEVICEIDS __clewGetDeviceIDs;
- CLEW_FUN_EXPORT PFNCLGETDEVICEINFO __clewGetDeviceInfo;
- CLEW_FUN_EXPORT PFNCLCREATECONTEXT __clewCreateContext;
- CLEW_FUN_EXPORT PFNCLCREATECONTEXTFROMTYPE __clewCreateContextFromType;
- CLEW_FUN_EXPORT PFNCLRETAINCONTEXT __clewRetainContext;
- CLEW_FUN_EXPORT PFNCLRELEASECONTEXT __clewReleaseContext;
- CLEW_FUN_EXPORT PFNCLGETCONTEXTINFO __clewGetContextInfo;
- CLEW_FUN_EXPORT PFNCLCREATECOMMANDQUEUE __clewCreateCommandQueue;
- CLEW_FUN_EXPORT PFNCLRETAINCOMMANDQUEUE __clewRetainCommandQueue;
- CLEW_FUN_EXPORT PFNCLRELEASECOMMANDQUEUE __clewReleaseCommandQueue;
- CLEW_FUN_EXPORT PFNCLGETCOMMANDQUEUEINFO __clewGetCommandQueueInfo;
-#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
- CLEW_FUN_EXPORT PFNCLSETCOMMANDQUEUEPROPERTY __clewSetCommandQueueProperty;
-#endif
- CLEW_FUN_EXPORT PFNCLCREATEBUFFER __clewCreateBuffer;
- CLEW_FUN_EXPORT PFNCLCREATESUBBUFFER __clewCreateSubBuffer;
- CLEW_FUN_EXPORT PFNCLCREATEIMAGE2D __clewCreateImage2D;
- CLEW_FUN_EXPORT PFNCLCREATEIMAGE3D __clewCreateImage3D;
- CLEW_FUN_EXPORT PFNCLRETAINMEMOBJECT __clewRetainMemObject;
- CLEW_FUN_EXPORT PFNCLRELEASEMEMOBJECT __clewReleaseMemObject;
- CLEW_FUN_EXPORT PFNCLGETSUPPORTEDIMAGEFORMATS __clewGetSupportedImageFormats;
- CLEW_FUN_EXPORT PFNCLGETMEMOBJECTINFO __clewGetMemObjectInfo;
- CLEW_FUN_EXPORT PFNCLGETIMAGEINFO __clewGetImageInfo;
- CLEW_FUN_EXPORT PFNCLSETMEMOBJECTDESTRUCTORCALLBACK __clewSetMemObjectDestructorCallback;
- CLEW_FUN_EXPORT PFNCLCREATESAMPLER __clewCreateSampler;
- CLEW_FUN_EXPORT PFNCLRETAINSAMPLER __clewRetainSampler;
- CLEW_FUN_EXPORT PFNCLRELEASESAMPLER __clewReleaseSampler;
- CLEW_FUN_EXPORT PFNCLGETSAMPLERINFO __clewGetSamplerInfo;
- CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHSOURCE __clewCreateProgramWithSource;
- CLEW_FUN_EXPORT PFNCLCREATEPROGRAMWITHBINARY __clewCreateProgramWithBinary;
- CLEW_FUN_EXPORT PFNCLRETAINPROGRAM __clewRetainProgram;
- CLEW_FUN_EXPORT PFNCLRELEASEPROGRAM __clewReleaseProgram;
- CLEW_FUN_EXPORT PFNCLBUILDPROGRAM __clewBuildProgram;
- CLEW_FUN_EXPORT PFNCLUNLOADCOMPILER __clewUnloadCompiler;
- CLEW_FUN_EXPORT PFNCLGETPROGRAMINFO __clewGetProgramInfo;
- CLEW_FUN_EXPORT PFNCLGETPROGRAMBUILDINFO __clewGetProgramBuildInfo;
- CLEW_FUN_EXPORT PFNCLCREATEKERNEL __clewCreateKernel;
- CLEW_FUN_EXPORT PFNCLCREATEKERNELSINPROGRAM __clewCreateKernelsInProgram;
- CLEW_FUN_EXPORT PFNCLRETAINKERNEL __clewRetainKernel;
- CLEW_FUN_EXPORT PFNCLRELEASEKERNEL __clewReleaseKernel;
- CLEW_FUN_EXPORT PFNCLSETKERNELARG __clewSetKernelArg;
- CLEW_FUN_EXPORT PFNCLGETKERNELINFO __clewGetKernelInfo;
- CLEW_FUN_EXPORT PFNCLGETKERNELWORKGROUPINFO __clewGetKernelWorkGroupInfo;
- CLEW_FUN_EXPORT PFNCLWAITFOREVENTS __clewWaitForEvents;
- CLEW_FUN_EXPORT PFNCLGETEVENTINFO __clewGetEventInfo;
- CLEW_FUN_EXPORT PFNCLCREATEUSEREVENT __clewCreateUserEvent;
- CLEW_FUN_EXPORT PFNCLRETAINEVENT __clewRetainEvent;
- CLEW_FUN_EXPORT PFNCLRELEASEEVENT __clewReleaseEvent;
- CLEW_FUN_EXPORT PFNCLSETUSEREVENTSTATUS __clewSetUserEventStatus;
- CLEW_FUN_EXPORT PFNCLSETEVENTCALLBACK __clewSetEventCallback;
- CLEW_FUN_EXPORT PFNCLGETEVENTPROFILINGINFO __clewGetEventProfilingInfo;
- CLEW_FUN_EXPORT PFNCLFLUSH __clewFlush;
- CLEW_FUN_EXPORT PFNCLFINISH __clewFinish;
- CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFER __clewEnqueueReadBuffer;
- CLEW_FUN_EXPORT PFNCLENQUEUEREADBUFFERRECT __clewEnqueueReadBufferRect;
- CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFER __clewEnqueueWriteBuffer;
- CLEW_FUN_EXPORT PFNCLENQUEUEWRITEBUFFERRECT __clewEnqueueWriteBufferRect;
- CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFER __clewEnqueueCopyBuffer;
- CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERRECT __clewEnqueueCopyBufferRect;
- CLEW_FUN_EXPORT PFNCLENQUEUEREADIMAGE __clewEnqueueReadImage;
- CLEW_FUN_EXPORT PFNCLENQUEUEWRITEIMAGE __clewEnqueueWriteImage;
- CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGE __clewEnqueueCopyImage;
- CLEW_FUN_EXPORT PFNCLENQUEUECOPYIMAGETOBUFFER __clewEnqueueCopyImageToBuffer;
- CLEW_FUN_EXPORT PFNCLENQUEUECOPYBUFFERTOIMAGE __clewEnqueueCopyBufferToImage;
- CLEW_FUN_EXPORT PFNCLENQUEUEMAPBUFFER __clewEnqueueMapBuffer;
- CLEW_FUN_EXPORT PFNCLENQUEUEMAPIMAGE __clewEnqueueMapImage;
- CLEW_FUN_EXPORT PFNCLENQUEUEUNMAPMEMOBJECT __clewEnqueueUnmapMemObject;
- CLEW_FUN_EXPORT PFNCLENQUEUENDRANGEKERNEL __clewEnqueueNDRangeKernel;
- CLEW_FUN_EXPORT PFNCLENQUEUETASK __clewEnqueueTask;
- CLEW_FUN_EXPORT PFNCLENQUEUENATIVEKERNEL __clewEnqueueNativeKernel;
- CLEW_FUN_EXPORT PFNCLENQUEUEMARKER __clewEnqueueMarker;
- CLEW_FUN_EXPORT PFNCLENQUEUEWAITFOREVENTS __clewEnqueueWaitForEvents;
- CLEW_FUN_EXPORT PFNCLENQUEUEBARRIER __clewEnqueueBarrier;
- CLEW_FUN_EXPORT PFNCLGETEXTENSIONFUNCTIONADDRESS __clewGetExtensionFunctionAddress;
-
-#define clGetPlatformIDs CLEW_GET_FUN(__clewGetPlatformIDs)
-#define clGetPlatformInfo CLEW_GET_FUN(__clewGetPlatformInfo)
-#define clGetDeviceIDs CLEW_GET_FUN(__clewGetDeviceIDs)
-#define clGetDeviceInfo CLEW_GET_FUN(__clewGetDeviceInfo)
-#define clCreateContext CLEW_GET_FUN(__clewCreateContext)
-#define clCreateContextFromType CLEW_GET_FUN(__clewCreateContextFromType)
-#define clRetainContext CLEW_GET_FUN(__clewRetainContext)
-#define clReleaseContext CLEW_GET_FUN(__clewReleaseContext)
-#define clGetContextInfo CLEW_GET_FUN(__clewGetContextInfo)
-#define clCreateCommandQueue CLEW_GET_FUN(__clewCreateCommandQueue)
-#define clRetainCommandQueue CLEW_GET_FUN(__clewRetainCommandQueue)
-#define clReleaseCommandQueue CLEW_GET_FUN(__clewReleaseCommandQueue)
-#define clGetCommandQueueInfo CLEW_GET_FUN(__clewGetCommandQueueInfo)
-#ifdef CL_USE_DEPRECATED_OPENCL_1_0_APIS
-#warning CL_USE_DEPRECATED_OPENCL_1_0_APIS is defined. These APIs are unsupported and untested in OpenCL 1.1!
-/*
- * WARNING:
- * This API introduces mutable state into the OpenCL implementation. It has been REMOVED
- * to better facilitate thread safety. The 1.0 API is not thread safe. It is not tested by the
- * OpenCL 1.1 conformance test, and consequently may not work or may not work dependably.
- * It is likely to be non-performant. Use of this API is not advised. Use at your own risk.
- *
- * Software developers previously relying on this API are instructed to set the command queue
- * properties when creating the queue, instead.
- */
-#define clSetCommandQueueProperty CLEW_GET_FUN(__clewSetCommandQueueProperty)
-#endif /* CL_USE_DEPRECATED_OPENCL_1_0_APIS */
-#define clCreateBuffer CLEW_GET_FUN(__clewCreateBuffer)
-#define clCreateSubBuffer CLEW_GET_FUN(__clewCreateSubBuffer)
-#define clCreateImage2D CLEW_GET_FUN(__clewCreateImage2D)
-#define clCreateImage3D CLEW_GET_FUN(__clewCreateImage3D)
-#define clRetainMemObject CLEW_GET_FUN(__clewRetainMemObject)
-#define clReleaseMemObject CLEW_GET_FUN(__clewReleaseMemObject)
-#define clGetSupportedImageFormats CLEW_GET_FUN(__clewGetSupportedImageFormats)
-#define clGetMemObjectInfo CLEW_GET_FUN(__clewGetMemObjectInfo)
-#define clGetImageInfo CLEW_GET_FUN(__clewGetImageInfo)
-#define clSetMemObjectDestructorCallback CLEW_GET_FUN(__clewSetMemObjectDestructorCallback)
-#define clCreateSampler CLEW_GET_FUN(__clewCreateSampler)
-#define clRetainSampler CLEW_GET_FUN(__clewRetainSampler)
-#define clReleaseSampler CLEW_GET_FUN(__clewReleaseSampler)
-#define clGetSamplerInfo CLEW_GET_FUN(__clewGetSamplerInfo)
-#define clCreateProgramWithSource CLEW_GET_FUN(__clewCreateProgramWithSource)
-#define clCreateProgramWithBinary CLEW_GET_FUN(__clewCreateProgramWithBinary)
-#define clRetainProgram CLEW_GET_FUN(__clewRetainProgram)
-#define clReleaseProgram CLEW_GET_FUN(__clewReleaseProgram)
-#define clBuildProgram CLEW_GET_FUN(__clewBuildProgram)
-#define clUnloadCompiler CLEW_GET_FUN(__clewUnloadCompiler)
-#define clGetProgramInfo CLEW_GET_FUN(__clewGetProgramInfo)
-#define clGetProgramBuildInfo CLEW_GET_FUN(__clewGetProgramBuildInfo)
-#define clCreateKernel CLEW_GET_FUN(__clewCreateKernel)
-#define clCreateKernelsInProgram CLEW_GET_FUN(__clewCreateKernelsInProgram)
-#define clRetainKernel CLEW_GET_FUN(__clewRetainKernel)
-#define clReleaseKernel CLEW_GET_FUN(__clewReleaseKernel)
-#define clSetKernelArg CLEW_GET_FUN(__clewSetKernelArg)
-#define clGetKernelInfo CLEW_GET_FUN(__clewGetKernelInfo)
-#define clGetKernelWorkGroupInfo CLEW_GET_FUN(__clewGetKernelWorkGroupInfo)
-#define clWaitForEvents CLEW_GET_FUN(__clewWaitForEvents)
-#define clGetEventInfo CLEW_GET_FUN(__clewGetEventInfo)
-#define clCreateUserEvent CLEW_GET_FUN(__clewCreateUserEvent)
-#define clRetainEvent CLEW_GET_FUN(__clewRetainEvent)
-#define clReleaseEvent CLEW_GET_FUN(__clewReleaseEvent)
-#define clSetUserEventStatus CLEW_GET_FUN(__clewSetUserEventStatus)
-#define clSetEventCallback CLEW_GET_FUN(__clewSetEventCallback)
-#define clGetEventProfilingInfo CLEW_GET_FUN(__clewGetEventProfilingInfo)
-#define clFlush CLEW_GET_FUN(__clewFlush)
-#define clFinish CLEW_GET_FUN(__clewFinish)
-#define clEnqueueReadBuffer CLEW_GET_FUN(__clewEnqueueReadBuffer)
-#define clEnqueueReadBufferRect CLEW_GET_FUN(__clewEnqueueReadBufferRect)
-#define clEnqueueWriteBuffer CLEW_GET_FUN(__clewEnqueueWriteBuffer)
-#define clEnqueueWriteBufferRect CLEW_GET_FUN(__clewEnqueueWriteBufferRect)
-#define clEnqueueCopyBuffer CLEW_GET_FUN(__clewEnqueueCopyBuffer)
-#define clEnqueueCopyBufferRect CLEW_GET_FUN(__clewEnqueueCopyBufferRect)
-#define clEnqueueReadImage CLEW_GET_FUN(__clewEnqueueReadImage)
-#define clEnqueueWriteImage CLEW_GET_FUN(__clewEnqueueWriteImage)
-#define clEnqueueCopyImage CLEW_GET_FUN(__clewEnqueueCopyImage)
-#define clEnqueueCopyImageToBuffer CLEW_GET_FUN(__clewEnqueueCopyImageToBuffer)
-#define clEnqueueCopyBufferToImage CLEW_GET_FUN(__clewEnqueueCopyBufferToImage)
-#define clEnqueueMapBuffer CLEW_GET_FUN(__clewEnqueueMapBuffer)
-#define clEnqueueMapImage CLEW_GET_FUN(__clewEnqueueMapImage)
-#define clEnqueueUnmapMemObject CLEW_GET_FUN(__clewEnqueueUnmapMemObject)
-#define clEnqueueNDRangeKernel CLEW_GET_FUN(__clewEnqueueNDRangeKernel)
-#define clEnqueueTask CLEW_GET_FUN(__clewEnqueueTask)
-#define clEnqueueNativeKernel CLEW_GET_FUN(__clewEnqueueNativeKernel)
-#define clEnqueueMarker CLEW_GET_FUN(__clewEnqueueMarker)
-#define clEnqueueWaitForEvents CLEW_GET_FUN(__clewEnqueueWaitForEvents)
-#define clEnqueueBarrier CLEW_GET_FUN(__clewEnqueueBarrier)
-#define clGetExtensionFunctionAddress CLEW_GET_FUN(__clewGetExtensionFunctionAddress)
-
-#define CLEW_SUCCESS 0 //!< Success error code
-#define CLEW_ERROR_OPEN_FAILED -1 //!< Error code for failing to open the dynamic library
-#define CLEW_ERROR_ATEXIT_FAILED -2 //!< Error code for failing to queue the closing of the dynamic library to atexit()
-
- //! \brief Load OpenCL dynamic library and set function entry points
- int clewInit(const char *);
-
- //! \brief Exit clew and unload OpenCL dynamic library
- void clewExit();
-
- //! \brief Convert an OpenCL error code to its string equivalent
- const char *clewErrorString(cl_int error);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // CLEW_HPP_INCLUDED
diff --git a/thirdparty/bullet/patches/bullet-fix-warnings.patch b/thirdparty/bullet/patches/bullet-fix-warnings.patch
deleted file mode 100644
index 69cde1b16e..0000000000
--- a/thirdparty/bullet/patches/bullet-fix-warnings.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-diff --git a/thirdparty/bullet/BulletSoftBody/btSoftBody.h b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
-index f578487b8c..dfde8fd1e4 100644
---- a/thirdparty/bullet/BulletSoftBody/btSoftBody.h
-+++ b/thirdparty/bullet/BulletSoftBody/btSoftBody.h
-@@ -1317,8 +1317,8 @@ public:
- }
- for (int k = 0; k < m_faceNodeContacts.size(); ++k)
- {
-- int i = indices[k];
-- btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[i];
-+ int idx = indices[k];
-+ btSoftBody::DeformableFaceNodeContact& c = m_faceNodeContacts[idx];
- btSoftBody::Node* node = c.m_node;
- btSoftBody::Face* face = c.m_face;
- const btVector3& w = c.m_bary;
-diff --git a/thirdparty/bullet/LinearMath/btSerializer.h b/thirdparty/bullet/LinearMath/btSerializer.h
-index ce4fc34e20..11592d2ccd 100644
---- a/thirdparty/bullet/LinearMath/btSerializer.h
-+++ b/thirdparty/bullet/LinearMath/btSerializer.h
-@@ -499,7 +499,6 @@ public:
- writeDNA();
-
- //if we didn't pre-allocate a buffer, we need to create a contiguous buffer now
-- int mysize = 0;
- if (!m_totalSize)
- {
- if (m_buffer)
-@@ -511,14 +510,12 @@ public:
- unsigned char* currentPtr = m_buffer;
- writeHeader(m_buffer);
- currentPtr += BT_HEADER_LENGTH;
-- mysize += BT_HEADER_LENGTH;
- for (int i = 0; i < m_chunkPtrs.size(); i++)
- {
- int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length;
- memcpy(currentPtr, m_chunkPtrs[i], curLength);
- btAlignedFree(m_chunkPtrs[i]);
- currentPtr += curLength;
-- mysize += curLength;
- }
- }
-
diff --git a/thirdparty/bullet/patches/fix-win32-scheduler-uwp.patch b/thirdparty/bullet/patches/fix-win32-scheduler-uwp.patch
deleted file mode 100644
index c65db49388..0000000000
--- a/thirdparty/bullet/patches/fix-win32-scheduler-uwp.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-diff --git a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
-index 922e449cce..5862264a67 100644
---- a/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
-+++ b/thirdparty/bullet/LinearMath/TaskScheduler/btThreadSupportWin32.cpp
-@@ -82,6 +82,11 @@ typedef BOOL(WINAPI* Pfn_GetLogicalProcessorInformation)(PSYSTEM_LOGICAL_PROCESS
- void getProcessorInformation(btProcessorInfo* procInfo)
- {
- memset(procInfo, 0, sizeof(*procInfo));
-+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
-+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-+ // Can't dlopen libraries on UWP.
-+ return;
-+#else
- Pfn_GetLogicalProcessorInformation getLogicalProcInfo =
- (Pfn_GetLogicalProcessorInformation)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation");
- if (getLogicalProcInfo == NULL)
-@@ -160,6 +165,7 @@ void getProcessorInformation(btProcessorInfo* procInfo)
- }
- }
- free(buf);
-+#endif
- }
-
- ///btThreadSupportWin32 helps to initialize/shutdown libspe2, start/stop SPU tasks and communication
diff --git a/thirdparty/certs/ca-certificates.crt b/thirdparty/certs/ca-certificates.crt
index 7f89e81d01..036f630d5b 100644
--- a/thirdparty/certs/ca-certificates.crt
+++ b/thirdparty/certs/ca-certificates.crt
@@ -1,7 +1,7 @@
##
## Bundle of CA Root Certificates
##
-## Certificate data from Mozilla as of: Mon Nov 1 15:39:58 2021 GMT
+## Certificate data from Mozilla as of: Tue Jul 19 14:20:01 2022 GMT
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
@@ -13,8 +13,8 @@
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##
-## Conversion done with mk-ca-bundle.pl version 1.28.
-## SHA256: bb36818a81feaa4cca61101e6d6276cd09e972efcb08112dfed846918ca41d7f
+## Conversion done with mk-ca-bundle.pl version 1.29.
+## SHA256: 9bf3799611fb58197f61d45e71ce3dc19f30e7dd73731915872ce5108a7bb066
##
@@ -39,28 +39,6 @@ hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
-GlobalSign Root CA - R2
-=======================
------BEGIN CERTIFICATE-----
-MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
-YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
-bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
-aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
-bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
-ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
-s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
-S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
-TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
-ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
-FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
-YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
-BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
-9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
-01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
-9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
-TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
------END CERTIFICATE-----
-
Entrust.net Premium 2048 Secure Server CA
=========================================
-----BEGIN CERTIFICATE-----
@@ -573,28 +551,6 @@ PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
-----END CERTIFICATE-----
-Cybertrust Global Root
-======================
------BEGIN CERTIFICATE-----
-MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
-ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
-MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
-ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-+Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
-0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
-AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
-89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
-8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
-BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
-MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
-A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
-lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
-5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
-hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
-X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
-WL1WMRJOEcgh4LMRkWXbtKaIOM5V
------END CERTIFICATE-----
-
ePKI Root Certification Authority
=================================
-----BEGIN CERTIFICATE-----
@@ -1037,60 +993,6 @@ tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
-----END CERTIFICATE-----
-EC-ACC
-======
------BEGIN CERTIFICATE-----
-MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
-BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
-ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
-VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
-CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
-BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
-MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
-SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
-Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
-cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
-w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
-ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
-HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
-E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
-0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
-VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
-Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
-dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
-lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
-Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
-l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
-E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
-5EI=
------END CERTIFICATE-----
-
-Hellenic Academic and Research Institutions RootCA 2011
-=======================================================
------BEGIN CERTIFICATE-----
-MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
-O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
-aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
-AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
-IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
-IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
-1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
-71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
-8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
-3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
-MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
-MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
-b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
-XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
-TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
-/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
-7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
------END CERTIFICATE-----
-
Actalis Authentication Root CA
==============================
-----BEGIN CERTIFICATE-----
@@ -1737,20 +1639,6 @@ HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
-----END CERTIFICATE-----
-GlobalSign ECC Root CA - R4
-===========================
------BEGIN CERTIFICATE-----
-MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
-R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
-EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
-R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
-EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
-OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
-AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
-MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
-JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
------END CERTIFICATE-----
-
GlobalSign ECC Root CA - R5
===========================
-----BEGIN CERTIFICATE-----
@@ -2472,96 +2360,6 @@ AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk
AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
-----END CERTIFICATE-----
-GTS Root R1
-===========
------BEGIN CERTIFICATE-----
-MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
-EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
-b3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
-A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIi
-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx
-9vaMf/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7r
-aKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnW
-r4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqM
-LnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly
-4cpk9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr
-06zqkUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
-wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om
-3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNu
-JLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
-VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEM
-BQADggIBADiWCu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
-d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6ZXPYfcX3v73sv
-fuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZRgyFmxhE+885H7pwoHyXa/6xm
-ld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9b
-gsiG1eGZbYwE8na6SfZu6W0eX6DvJ4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq
-4BjFbkerQUIpm/ZgDdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWEr
-tXvM+SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyyF62ARPBo
-pY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9SQ98POyDGCBDTtWTurQ0
-sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdwsE3PYJ/HQcu51OyLemGhmW/HGY0dVHLql
-CFF1pkgl
------END CERTIFICATE-----
-
-GTS Root R2
-===========
------BEGIN CERTIFICATE-----
-MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQG
-EwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJv
-b3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAG
-A1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIi
-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTuk
-k3LvCvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo
-7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWI
-m8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5Gm
-dFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbu
-ak7MkogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscsz
-cTJGr61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
-Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73Vululycsl
-aVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy
-5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
-VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEM
-BQADggIBALZp8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
-vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiTz9D2PGcDFWEJ
-+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiApJiS4wGWAqoC7o87xdFtCjMw
-c3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvbpxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3Da
-WsYDQvTtN6LwG1BUSw7YhN4ZKJmBR64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5r
-n/WkhLx3+WuXrD5RRaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56Gtmwfu
-Nmsk0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC5AwiWVIQ
-7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiFizoHCBy69Y9Vmhh1fuXs
-gWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLnyOd/xCxgXS/Dr55FBcOEArf9LAhST4Ld
-o/DUhgkC
------END CERTIFICATE-----
-
-GTS Root R3
-===========
------BEGIN CERTIFICATE-----
-MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
-UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
-UjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
-ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcq
-hkjOPQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUU
-Rout736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24Cej
-QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP
-0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFukfCPAlaUs3L6JbyO5o91lAFJekazInXJ0
-glMLfalAvWhgxeG4VDvBNhcl2MG9AjEAnjWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOa
-KaqW04MjyaR7YbPMAuhd
------END CERTIFICATE-----
-
-GTS Root R4
-===========
------BEGIN CERTIFICATE-----
-MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJV
-UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
-UjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
-ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcq
-hkjOPQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa
-6zzuhXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqj
-QjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV
-2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0CMRw3J5QdCHojXohw0+WbhXRIjVhLfoI
-N+4Zba3bssx9BzT1YBkstTTZbyACMANxsbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11x
-zPKwTdb+mciUqXWi4w==
------END CERTIFICATE-----
-
UCA Global G2 Root
==================
-----BEGIN CERTIFICATE-----
@@ -3230,3 +3028,433 @@ ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW
rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw
CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps
-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud
+DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w
+gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j
+b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A
+bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL
+4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb
+LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il
+I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP
+cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA
+LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A
+lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH
+9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf
+NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE
+ZycPvEJdvSRUDewdcAZfpLz6IHxV
+-----END CERTIFICATE-----
+
+vTrus ECC Root CA
+=================
+-----BEGIN CERTIFICATE-----
+MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE
+BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS
+b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa
+BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw
+EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c
+ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n
+TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT
+QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL
+YgmRWAD5Tfs0aNoJrSEGGJTO
+-----END CERTIFICATE-----
+
+vTrus Root CA
+=============
+-----BEGIN CERTIFICATE-----
+MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG
+A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv
+b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG
+A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots
+SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI
+ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF
+XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA
+YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70
+kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2
+AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu
+/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu
+1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO
+9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg
+scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC
+AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd
+nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr
+jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4
+8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn
+xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg
+icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4
+sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW
+nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc
+SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H
+l3s=
+-----END CERTIFICATE-----
+
+ISRG Root X2
+============
+-----BEGIN CERTIFICATE-----
+MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV
+UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT
+UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT
+MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS
+RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H
+ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb
+d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF
+cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5
+U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn
+-----END CERTIFICATE-----
+
+HiPKI Root CA - G1
+==================
+-----BEGIN CERTIFICATE-----
+MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ
+IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT
+AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg
+Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0
+o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k
+wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE
+YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA
+GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
+hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj
+1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4
+9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/
+Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF
+8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD
+AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi
+7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl
+tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE
+wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q
+JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv
+5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz
+jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg
+hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb
+yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/
+yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ==
+-----END CERTIFICATE-----
+
+GlobalSign ECC Root CA - R4
+===========================
+-----BEGIN CERTIFICATE-----
+MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i
+YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds
+b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW
+ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E
+BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI
+KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg
+UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
+-----END CERTIFICATE-----
+
+GTS Root R1
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0
+xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w
+B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW
+nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk
+9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq
+kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A
+K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX
+V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW
+cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD
+ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
+QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi
+ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar
+J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci
+NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me
+LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF
+fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+
+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3
+FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3
+gm3c
+-----END CERTIFICATE-----
+
+GTS Root R2
+===========
+-----BEGIN CERTIFICATE-----
+MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV
+UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg
+UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE
+ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl
+e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb
+a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS
++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M
+kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG
+r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q
+S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV
+J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL
+dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD
+ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
+0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh
+swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel
+/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn
+jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5
+9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M
+7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8
+0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR
+WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW
+HYbL
+-----END CERTIFICATE-----
+
+GTS Root R3
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq
+Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT
+L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV
+11RZt+cRLInUue4X
+-----END CERTIFICATE-----
+
+GTS Root R4
+===========
+-----BEGIN CERTIFICATE-----
+MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi
+MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw
+HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ
+R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO
+PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA
+MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1
+PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C
+r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh
+4rsUecrNIdSUtUlD
+-----END CERTIFICATE-----
+
+Telia Root CA v2
+================
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT
+AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2
+MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK
+DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7
+6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q
+9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn
+pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl
+tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW
+5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr
+RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E
+BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4
+M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau
+BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W
+xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ
+8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5
+tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H
+eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C
+y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC
+QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15
+h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70
+sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9
+xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ
+raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc=
+-----END CERTIFICATE-----
+
+D-TRUST BR Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7
+dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu
+QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom
+AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87
+-----END CERTIFICATE-----
+
+D-TRUST EV Root CA 1 2020
+=========================
+-----BEGIN CERTIFICATE-----
+MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE
+RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy
+MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV
+BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG
+ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8
+ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ
+raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL
+MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu
+bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP
+PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD
+AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR
+AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW
+-----END CERTIFICATE-----
+
+DigiCert TLS ECC P384 Root G5
+=============================
+-----BEGIN CERTIFICATE-----
+MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4
+NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg
+Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd
+lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj
+n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB
+/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds
+Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx
+AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA==
+-----END CERTIFICATE-----
+
+DigiCert TLS RSA4096 Root G5
+============================
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG
+EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0
+MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2
+IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8
+7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU
+AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces
+tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa
+zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV
+DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q
+TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy
+z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/
+MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk
+wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E
+FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw
+GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN
+lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN
+MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/
+u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G
+OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh
+47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU
+FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ
+yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP
+bEtoL8pU9ozaMv7Da4M/OMZ+
+-----END CERTIFICATE-----
+
+Certainly Root R1
+=================
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE
+BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN
+MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy
+dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O
+5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl
+8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl
+DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI
+XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN
+KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ
+AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb
+rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1
+VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS
+p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz
+HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d
+8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v
+MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB
+GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+
+gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH
+JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7
+fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw
+x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S
+X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8=
+-----END CERTIFICATE-----
+
+Certainly Root E1
+=================
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV
+UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0
+MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu
+bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4
+fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9
+YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E
+AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8
+rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA RSA v3
+=============================
+-----BEGIN CERTIFICATE-----
+MIIF8zCCA9ugAwIBAgIUDU3FzRYilZYIfrgLfxUGNPt5EDQwDQYJKoZIhvcNAQELBQAwgYAxCzAJ
+BgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAb
+BgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290
+IENBIFJTQSB2MzAeFw0yMDAzMTgwOTA3MTdaFw00NTAzMTIwOTA3MTdaMIGAMQswCQYDVQQGEwJU
+UjEPMA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRF
+LVR1Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBSU0Eg
+djMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCiZvCJt3J77gnJY9LTQ91ew6aEOErx
+jYG7FL1H6EAX8z3DeEVypi6Q3po61CBxyryfHUuXCscxuj7X/iWpKo429NEvx7epXTPcMHD4QGxL
+sqYxYdE0PD0xesevxKenhOGXpOhL9hd87jwH7eKKV9y2+/hDJVDqJ4GohryPUkqWOmAalrv9c/SF
+/YP9f4RtNGx/ardLAQO/rWm31zLZ9Vdq6YaCPqVmMbMWPcLzJmAy01IesGykNz709a/r4d+ABs8q
+QedmCeFLl+d3vSFtKbZnwy1+7dZ5ZdHPOrbRsV5WYVB6Ws5OUDGAA5hH5+QYfERaxqSzO8bGwzrw
+bMOLyKSRBfP12baqBqG3q+Sx6iEUXIOk/P+2UNOMEiaZdnDpwA+mdPy70Bt4znKS4iicvObpCdg6
+04nmvi533wEKb5b25Y08TVJ2Glbhc34XrD2tbKNSEhhw5oBOM/J+JjKsBY04pOZ2PJ8QaQ5tndLB
+eSBrW88zjdGUdjXnXVXHt6woq0bM5zshtQoK5EpZ3IE1S0SVEgpnpaH/WwAH0sDM+T/8nzPyAPiM
+bIedBi3x7+PmBvrFZhNb/FAHnnGGstpvdDDPk1Po3CLW3iAfYY2jLqN4MpBs3KwytQXk9TwzDdbg
+h3cXTJ2w2AmoDVf3RIXwyAS+XF1a4xeOVGNpf0l0ZAWMowIDAQABo2MwYTAPBgNVHRMBAf8EBTAD
+AQH/MB8GA1UdIwQYMBaAFLK0ruYt9ybVqnUtdkvAG1Mh0EjvMB0GA1UdDgQWBBSytK7mLfcm1ap1
+LXZLwBtTIdBI7zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIBAImocn+M684uGMQQ
+gC0QDP/7FM0E4BQ8Tpr7nym/Ip5XuYJzEmMmtcyQ6dIqKe6cLcwsmb5FJ+Sxce3kOJUxQfJ9emN4
+38o2Fi+CiJ+8EUdPdk3ILY7r3y18Tjvarvbj2l0Upq7ohUSdBm6O++96SmotKygY/r+QLHUWnw/q
+ln0F7psTpURs+APQ3SPh/QMSEgj0GDSz4DcLdxEBSL9htLX4GdnLTeqjjO/98Aa1bZL0SmFQhO3s
+SdPkvmjmLuMxC1QLGpLWgti2omU8ZgT5Vdps+9u1FGZNlIM7zR6mK7L+d0CGq+ffCsn99t2HVhjY
+sCxVYJb6CH5SkPVLpi6HfMsg2wY+oF0Dd32iPBMbKaITVaA9FCKvb7jQmhty3QUBjYZgv6Rn7rWl
+DdF/5horYmbDB7rnoEgcOMPpRfunf/ztAmgayncSd6YAVSgU7NbHEqIbZULpkejLPoeJVF3Zr52X
+nGnnCv8PWniLYypMfUeUP95L6VPQMPHF9p5J3zugkaOj/s1YzOrfr28oO6Bpm4/srK4rVJ2bBLFH
+IK+WEj5jlB0E5y67hscMmoi/dkfv97ALl2bSRM9gUgfh1SxKOidhd8rXj+eHDjD/DLsE4mHDosiX
+YY60MGo8bcIHX0pzLz/5FooBZu+6kcpSV3uu1OYP3Qt6f4ueJiDPO++BcYNZ
+-----END CERTIFICATE-----
+
+E-Tugra Global Root CA ECC v3
+=============================
+-----BEGIN CERTIFICATE-----
+MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV
+BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB
+IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1
+Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2
+w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31
+Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ
+zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO
+PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W
+Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3
+-----END CERTIFICATE-----
diff --git a/thirdparty/doctest/doctest.h b/thirdparty/doctest/doctest.h
index 42eb039979..aa2724c738 100644
--- a/thirdparty/doctest/doctest.h
+++ b/thirdparty/doctest/doctest.h
@@ -11,7 +11,7 @@
// https://opensource.org/licenses/MIT
//
// The documentation can be found at the library's page:
-// https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md
+// https://github.com/doctest/doctest/blob/master/doc/markdown/readme.md
//
// =================================================================================================
// =================================================================================================
@@ -48,8 +48,16 @@
#define DOCTEST_VERSION_MAJOR 2
#define DOCTEST_VERSION_MINOR 4
-#define DOCTEST_VERSION_PATCH 6
-#define DOCTEST_VERSION_STR "2.4.6"
+#define DOCTEST_VERSION_PATCH 9
+
+// util we need here
+#define DOCTEST_TOSTR_IMPL(x) #x
+#define DOCTEST_TOSTR(x) DOCTEST_TOSTR_IMPL(x)
+
+#define DOCTEST_VERSION_STR \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MAJOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_MINOR) "." \
+ DOCTEST_TOSTR(DOCTEST_VERSION_PATCH)
#define DOCTEST_VERSION \
(DOCTEST_VERSION_MAJOR * 10000 + DOCTEST_VERSION_MINOR * 100 + DOCTEST_VERSION_PATCH)
@@ -60,6 +68,12 @@
// ideas for the version stuff are taken from here: https://github.com/cxxstuff/cxx_detect
+#ifdef _MSC_VER
+#define DOCTEST_CPLUSPLUS _MSVC_LANG
+#else
+#define DOCTEST_CPLUSPLUS __cplusplus
+#endif
+
#define DOCTEST_COMPILER(MAJOR, MINOR, PATCH) ((MAJOR)*10000000 + (MINOR)*100000 + (PATCH))
// GCC/Clang and GCC/MSVC are mutually exclusive, but Clang/MSVC are not because of clang-cl...
@@ -137,85 +151,92 @@
// == COMPILER WARNINGS ============================================================================
// =================================================================================================
+// both the header and the implementation suppress all of these,
+// so it only makes sense to aggregrate them like so
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING_PUSH \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat") \
+ DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic") \
+ \
+ DOCTEST_GCC_SUPPRESS_WARNING_PUSH \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast") \
+ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") \
+ \
+ DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
+ /* these 4 also disabled globally via cmake: */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4514) /* unreferenced inline function has been removed */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4571) /* SEH related */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4710) /* function not inlined */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4711) /* function selected for inline expansion*/ \
+ /* */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4616) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4619) /* invalid compiler warning */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4996) /* The compiler encountered a deprecated declaration */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4706) /* assignment within conditional expression */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4512) /* 'class' : assignment operator could not be generated */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4127) /* conditional expression is constant */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4640) /* construction of local static object not thread-safe */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ /* static analysis */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26439) /* Function may not throw. Declare it 'noexcept' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26495) /* Always initialize a member variable */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26451) /* Arithmetic overflow ... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26444) /* Avoid unnamed objects with custom ctor and dtor... */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(26812) /* Prefer 'enum class' over 'enum' */
+
+#define DOCTEST_SUPPRESS_COMMON_WARNINGS_POP \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP \
+ DOCTEST_GCC_SUPPRESS_WARNING_POP \
+ DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wnon-virtual-dtor")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wdeprecated")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
-DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
-DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
DOCTEST_GCC_SUPPRESS_WARNING("-Wctor-dtor-privacy")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
DOCTEST_GCC_SUPPRESS_WARNING("-Wnon-virtual-dtor")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-promo")
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
-DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
-DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
-DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
-DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
-DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
-DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
-DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding
-DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
DOCTEST_MSVC_SUPPRESS_WARNING(4623) // default constructor was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
-// static analysis
-DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
-DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
-DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
-DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtr...
-DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
-
-// 4548 - expression before comma has no effect; expected expression with side - effect
-// 4265 - class has virtual functions, but destructor is not virtual
-// 4986 - exception specification does not match previous declaration
-// 4350 - behavior change: 'member1' called instead of 'member2'
-// 4668 - 'x' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
-// 4365 - conversion from 'int' to 'unsigned long', signed/unsigned mismatch
-// 4774 - format string expected in argument 'x' is not a string literal
-// 4820 - padding in structs
-
-// only 4 should be disabled globally:
-// - 4514 # unreferenced inline function has been removed
-// - 4571 # SEH related
-// - 4710 # function not inlined
-// - 4711 # function 'x' selected for automatic inline expansion
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN \
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH \
- DOCTEST_MSVC_SUPPRESS_WARNING(4548) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4265) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4986) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4350) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4668) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4365) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4774) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4820) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4625) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4626) \
- DOCTEST_MSVC_SUPPRESS_WARNING(5027) \
- DOCTEST_MSVC_SUPPRESS_WARNING(5026) \
- DOCTEST_MSVC_SUPPRESS_WARNING(4623) \
- DOCTEST_MSVC_SUPPRESS_WARNING(5039) \
- DOCTEST_MSVC_SUPPRESS_WARNING(5045) \
- DOCTEST_MSVC_SUPPRESS_WARNING(5105)
+ DOCTEST_MSVC_SUPPRESS_WARNING(4548) /* before comma no effect; expected side - effect */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4265) /* virtual functions, but destructor is not virtual */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4986) /* exception specification does not match previous */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4350) /* 'member1' called instead of 'member2' */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4668) /* not defined as a preprocessor macro */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4365) /* signed/unsigned mismatch */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4774) /* format string not a string literal */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4820) /* padding */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4625) /* copy constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4626) /* assignment operator was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5027) /* move assignment operator implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5026) /* move constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4623) /* default constructor was implicitly deleted */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5039) /* pointer to pot. throwing function passed to extern C */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5045) /* Spectre mitigation for memory load */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(5105) /* macro producing 'defined' has undefined behavior */ \
+ DOCTEST_MSVC_SUPPRESS_WARNING(4738) /* storing float result in memory, loss of performance */
#define DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END DOCTEST_MSVC_SUPPRESS_WARNING_POP
@@ -228,6 +249,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
// GCC C++11 feature support table: https://gcc.gnu.org/projects/cxx-status.html
// MSVC version table:
// https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering
+// MSVC++ 14.3 (17) _MSC_VER == 1930 (Visual Studio 2022)
// MSVC++ 14.2 (16) _MSC_VER == 1920 (Visual Studio 2019)
// MSVC++ 14.1 (15) _MSC_VER == 1910 (Visual Studio 2017)
// MSVC++ 14.0 _MSC_VER == 1900 (Visual Studio 2015)
@@ -237,6 +259,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
// MSVC++ 9.0 _MSC_VER == 1500 (Visual Studio 2008)
// MSVC++ 8.0 _MSC_VER == 1400 (Visual Studio 2005)
+// Universal Windows Platform support
+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
+#define DOCTEST_CONFIG_NO_WINDOWS_SEH
+#endif // WINAPI_FAMILY
#if DOCTEST_MSVC && !defined(DOCTEST_CONFIG_WINDOWS_SEH)
#define DOCTEST_CONFIG_WINDOWS_SEH
#endif // MSVC
@@ -245,7 +271,7 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#endif // DOCTEST_CONFIG_NO_WINDOWS_SEH
#if !defined(_WIN32) && !defined(__QNX__) && !defined(DOCTEST_CONFIG_POSIX_SIGNALS) && \
- !defined(__EMSCRIPTEN__)
+ !defined(__EMSCRIPTEN__) && !defined(__wasi__)
#define DOCTEST_CONFIG_POSIX_SIGNALS
#endif // _WIN32
#if defined(DOCTEST_CONFIG_NO_POSIX_SIGNALS) && defined(DOCTEST_CONFIG_POSIX_SIGNALS)
@@ -253,7 +279,8 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#endif // DOCTEST_CONFIG_NO_POSIX_SIGNALS
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
-#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND)
+#if !defined(__cpp_exceptions) && !defined(__EXCEPTIONS) && !defined(_CPPUNWIND) \
+ || defined(__wasi__)
#define DOCTEST_CONFIG_NO_EXCEPTIONS
#endif // no exceptions
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
@@ -268,6 +295,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#define DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS && !DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
+#ifdef __wasi__
+#define DOCTEST_CONFIG_NO_MULTITHREADING
+#endif
+
#if defined(DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN) && !defined(DOCTEST_CONFIG_IMPLEMENT)
#define DOCTEST_CONFIG_IMPLEMENT
#endif // DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
@@ -295,6 +326,16 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#define DOCTEST_INTERFACE
#endif // DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
+// needed for extern template instantiations
+// see https://github.com/fmtlib/fmt/issues/2228
+#if DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL
+#define DOCTEST_INTERFACE_DEF DOCTEST_INTERFACE
+#else // DOCTEST_MSVC
+#define DOCTEST_INTERFACE_DECL DOCTEST_INTERFACE
+#define DOCTEST_INTERFACE_DEF
+#endif // DOCTEST_MSVC
+
#define DOCTEST_EMPTY
#if DOCTEST_MSVC
@@ -312,17 +353,46 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#endif
#ifndef DOCTEST_NORETURN
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NORETURN
+#else // DOCTEST_MSVC
#define DOCTEST_NORETURN [[noreturn]]
+#endif // DOCTEST_MSVC
#endif // DOCTEST_NORETURN
#ifndef DOCTEST_NOEXCEPT
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_NOEXCEPT
+#else // DOCTEST_MSVC
#define DOCTEST_NOEXCEPT noexcept
+#endif // DOCTEST_MSVC
#endif // DOCTEST_NOEXCEPT
+#ifndef DOCTEST_CONSTEXPR
+#if DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_CONSTEXPR const
+#define DOCTEST_CONSTEXPR_FUNC inline
+#else // DOCTEST_MSVC
+#define DOCTEST_CONSTEXPR constexpr
+#define DOCTEST_CONSTEXPR_FUNC constexpr
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_CONSTEXPR
+
// =================================================================================================
// == FEATURE DETECTION END ========================================================================
// =================================================================================================
+#define DOCTEST_DECLARE_INTERFACE(name) \
+ virtual ~name(); \
+ name() = default; \
+ name(const name&) = delete; \
+ name(name&&) = delete; \
+ name& operator=(const name&) = delete; \
+ name& operator=(name&&) = delete;
+
+#define DOCTEST_DEFINE_INTERFACE(name) \
+ name::~name() = default;
+
// internal macros for string concatenation and anonymous variable name generation
#define DOCTEST_CAT_IMPL(s1, s2) s1##s2
#define DOCTEST_CAT(s1, s2) DOCTEST_CAT_IMPL(s1, s2)
@@ -332,8 +402,6 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#define DOCTEST_ANONYMOUS(x) DOCTEST_CAT(x, __LINE__)
#endif // __COUNTER__
-#define DOCTEST_TOSTR(x) #x
-
#ifndef DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
#define DOCTEST_REF_WRAP(x) x&
#else // DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE
@@ -347,31 +415,39 @@ DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
#define DOCTEST_PLATFORM_IPHONE
#elif defined(_WIN32)
#define DOCTEST_PLATFORM_WINDOWS
+#elif defined(__wasi__)
+#define DOCTEST_PLATFORM_WASI
#else // DOCTEST_PLATFORM
#define DOCTEST_PLATFORM_LINUX
#endif // DOCTEST_PLATFORM
-#define DOCTEST_GLOBAL_NO_WARNINGS(var) \
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
- DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-variable") \
- static const int var DOCTEST_UNUSED // NOLINT(fuchsia-statically-constructed-objects,cert-err58-cpp)
-#define DOCTEST_GLOBAL_NO_WARNINGS_END() DOCTEST_CLANG_SUPPRESS_WARNING_POP
+namespace doctest { namespace detail {
+ static DOCTEST_CONSTEXPR int consume(const int*, int) noexcept { return 0; }
+}}
+
+#define DOCTEST_GLOBAL_NO_WARNINGS(var, ...) \
+ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wglobal-constructors") \
+ static const int var = doctest::detail::consume(&var, __VA_ARGS__); \
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
#ifndef DOCTEST_BREAK_INTO_DEBUGGER
// should probably take a look at https://github.com/scottt/debugbreak
#ifdef DOCTEST_PLATFORM_LINUX
#if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
// Break at the location of the failing check if possible
-#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
#else
#include <signal.h>
#define DOCTEST_BREAK_INTO_DEBUGGER() raise(SIGTRAP)
#endif
#elif defined(DOCTEST_PLATFORM_MAC)
#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(__i386)
-#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT (hicpp-no-assembler)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("int $3\n" : :) // NOLINT(hicpp-no-assembler)
+#elif defined(__ppc__) || defined(__ppc64__)
+// https://www.cocoawithlove.com/2008/03/break-into-debugger.html
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n": : : "memory","r0","r3","r4") // NOLINT(hicpp-no-assembler)
#else
-#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT (hicpp-no-assembler)
+#define DOCTEST_BREAK_INTO_DEBUGGER() __asm__("brk #0"); // NOLINT(hicpp-no-assembler)
#endif
#elif DOCTEST_MSVC
#define DOCTEST_BREAK_INTO_DEBUGGER() __debugbreak()
@@ -387,54 +463,66 @@ DOCTEST_GCC_SUPPRESS_WARNING_POP
// this is kept here for backwards compatibility since the config option was changed
#ifdef DOCTEST_CONFIG_USE_IOSFWD
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
#endif // DOCTEST_CONFIG_USE_IOSFWD
+// for clang - always include ciso646 (which drags some std stuff) because
+// we want to check if we are using libc++ with the _LIBCPP_VERSION macro in
+// which case we don't want to forward declare stuff from std - for reference:
+// https://github.com/doctest/doctest/issues/126
+// https://github.com/doctest/doctest/issues/356
+#if DOCTEST_CLANG
+#include <ciso646>
+#ifdef _LIBCPP_VERSION
+#ifndef DOCTEST_CONFIG_USE_STD_HEADERS
+#define DOCTEST_CONFIG_USE_STD_HEADERS
+#endif
+#endif // _LIBCPP_VERSION
+#endif // clang
+
#ifdef DOCTEST_CONFIG_USE_STD_HEADERS
#ifndef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#define DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
-#include <iosfwd>
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <cstddef>
#include <ostream>
+#include <istream>
+DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#else // DOCTEST_CONFIG_USE_STD_HEADERS
-#if DOCTEST_CLANG
-// to detect if libc++ is being used with clang (the _LIBCPP_VERSION identifier)
-#include <ciso646>
-#endif // clang
-
-#ifdef _LIBCPP_VERSION
-#define DOCTEST_STD_NAMESPACE_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
-#define DOCTEST_STD_NAMESPACE_END _LIBCPP_END_NAMESPACE_STD
-#else // _LIBCPP_VERSION
-#define DOCTEST_STD_NAMESPACE_BEGIN namespace std {
-#define DOCTEST_STD_NAMESPACE_END }
-#endif // _LIBCPP_VERSION
-
// Forward declaring 'X' in namespace std is not permitted by the C++ Standard.
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4643)
-DOCTEST_STD_NAMESPACE_BEGIN // NOLINT (cert-dcl58-cpp)
-typedef decltype(nullptr) nullptr_t;
+namespace std { // NOLINT(cert-dcl58-cpp)
+typedef decltype(nullptr) nullptr_t; // NOLINT(modernize-use-using)
+typedef decltype(sizeof(void*)) size_t; // NOLINT(modernize-use-using)
template <class charT>
struct char_traits;
template <>
struct char_traits<char>;
template <class charT, class traits>
-class basic_ostream;
-typedef basic_ostream<char, char_traits<char>> ostream;
+class basic_ostream; // NOLINT(fuchsia-virtual-inheritance)
+typedef basic_ostream<char, char_traits<char>> ostream; // NOLINT(modernize-use-using)
+template<class traits>
+// NOLINTNEXTLINE
+basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&, const char*);
+template <class charT, class traits>
+class basic_istream;
+typedef basic_istream<char, char_traits<char>> istream; // NOLINT(modernize-use-using)
template <class... Types>
class tuple;
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
-// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
-template <class _Ty>
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+template <class Ty>
class allocator;
-template <class _Elem, class _Traits, class _Alloc>
+template <class Elem, class Traits, class Alloc>
class basic_string;
using string = basic_string<char, char_traits<char>, allocator<char>>;
#endif // VS 2019
-DOCTEST_STD_NAMESPACE_END
+} // namespace std
DOCTEST_MSVC_SUPPRESS_WARNING_POP
@@ -446,8 +534,14 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP
namespace doctest {
+using std::size_t;
+
DOCTEST_INTERFACE extern bool is_running_in_test;
+#ifndef DOCTEST_CONFIG_STRING_SIZE_TYPE
+#define DOCTEST_CONFIG_STRING_SIZE_TYPE unsigned
+#endif
+
// A 24 byte string class (can be as small as 17 for x64 and 13 for x86) that can hold strings with length
// of up to 23 chars on the stack before going on the heap - the last byte of the buffer is used for:
// - "is small" bit - the highest bit - if "0" then it is small - otherwise its "1" (128)
@@ -460,7 +554,6 @@ DOCTEST_INTERFACE extern bool is_running_in_test;
// TODO:
// - optimizations - like not deleting memory unnecessarily in operator= and etc.
// - resize/reserve/clear
-// - substr
// - replace
// - back/front
// - iterator stuff
@@ -470,63 +563,84 @@ DOCTEST_INTERFACE extern bool is_running_in_test;
// - relational operators as free functions - taking const char* as one of the params
class DOCTEST_INTERFACE String
{
- static const unsigned len = 24; //!OCLINT avoid private static members
- static const unsigned last = len - 1; //!OCLINT avoid private static members
+public:
+ using size_type = DOCTEST_CONFIG_STRING_SIZE_TYPE;
+
+private:
+ static DOCTEST_CONSTEXPR size_type len = 24; //!OCLINT avoid private static members
+ static DOCTEST_CONSTEXPR size_type last = len - 1; //!OCLINT avoid private static members
struct view // len should be more than sizeof(view) - because of the final byte for flags
{
char* ptr;
- unsigned size;
- unsigned capacity;
+ size_type size;
+ size_type capacity;
};
union
{
- char buf[len];
+ char buf[len]; // NOLINT(*-avoid-c-arrays)
view data;
};
- bool isOnStack() const { return (buf[last] & 128) == 0; }
- void setOnHeap();
- void setLast(unsigned in = last);
+ char* allocate(size_type sz);
+
+ bool isOnStack() const noexcept { return (buf[last] & 128) == 0; }
+ void setOnHeap() noexcept;
+ void setLast(size_type in = last) noexcept;
+ void setSize(size_type sz) noexcept;
void copy(const String& other);
public:
- String();
+ static DOCTEST_CONSTEXPR size_type npos = static_cast<size_type>(-1);
+
+ String() noexcept;
~String();
// cppcheck-suppress noExplicitConstructor
String(const char* in);
- String(const char* in, unsigned in_size);
+ String(const char* in, size_type in_size);
+
+ String(std::istream& in, size_type in_size);
String(const String& other);
String& operator=(const String& other);
String& operator+=(const String& other);
- String operator+(const String& other) const;
- String(String&& other);
- String& operator=(String&& other);
+ String(String&& other) noexcept;
+ String& operator=(String&& other) noexcept;
- char operator[](unsigned i) const;
- char& operator[](unsigned i);
+ char operator[](size_type i) const;
+ char& operator[](size_type i);
// the only functions I'm willing to leave in the interface - available for inlining
const char* c_str() const { return const_cast<String*>(this)->c_str(); } // NOLINT
char* c_str() {
- if(isOnStack())
+ if (isOnStack()) {
return reinterpret_cast<char*>(buf);
+ }
return data.ptr;
}
- unsigned size() const;
- unsigned capacity() const;
+ size_type size() const;
+ size_type capacity() const;
+
+ String substr(size_type pos, size_type cnt = npos) &&;
+ String substr(size_type pos, size_type cnt = npos) const &;
+
+ size_type find(char ch, size_type pos = 0) const;
+ size_type rfind(char ch, size_type pos = npos) const;
int compare(const char* other, bool no_case = false) const;
int compare(const String& other, bool no_case = false) const;
+
+friend DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
};
+DOCTEST_INTERFACE String operator+(const String& lhs, const String& rhs);
+
DOCTEST_INTERFACE bool operator==(const String& lhs, const String& rhs);
DOCTEST_INTERFACE bool operator!=(const String& lhs, const String& rhs);
DOCTEST_INTERFACE bool operator<(const String& lhs, const String& rhs);
@@ -534,7 +648,21 @@ DOCTEST_INTERFACE bool operator>(const String& lhs, const String& rhs);
DOCTEST_INTERFACE bool operator<=(const String& lhs, const String& rhs);
DOCTEST_INTERFACE bool operator>=(const String& lhs, const String& rhs);
-DOCTEST_INTERFACE std::ostream& operator<<(std::ostream& s, const String& in);
+class DOCTEST_INTERFACE Contains {
+public:
+ explicit Contains(const String& string);
+
+ bool checkWith(const String& other) const;
+
+ String string;
+};
+
+DOCTEST_INTERFACE String toString(const Contains& in);
+
+DOCTEST_INTERFACE bool operator==(const String& lhs, const Contains& rhs);
+DOCTEST_INTERFACE bool operator==(const Contains& lhs, const String& rhs);
+DOCTEST_INTERFACE bool operator!=(const String& lhs, const Contains& rhs);
+DOCTEST_INTERFACE bool operator!=(const Contains& lhs, const String& rhs);
namespace Color {
enum Enum
@@ -607,7 +735,7 @@ namespace assertType {
DT_WARN_THROWS_WITH = is_throws_with | is_warn,
DT_CHECK_THROWS_WITH = is_throws_with | is_check,
DT_REQUIRE_THROWS_WITH = is_throws_with | is_require,
-
+
DT_WARN_THROWS_WITH_AS = is_throws_with | is_throws_as | is_warn,
DT_CHECK_THROWS_WITH_AS = is_throws_with | is_throws_as | is_check,
DT_REQUIRE_THROWS_WITH_AS = is_throws_with | is_throws_as | is_require,
@@ -688,9 +816,27 @@ struct DOCTEST_INTERFACE AssertData
String m_decomp;
// for specific exception-related asserts
- bool m_threw_as;
- const char* m_exception_type;
- const char* m_exception_string;
+ bool m_threw_as;
+ const char* m_exception_type;
+
+ class DOCTEST_INTERFACE StringContains {
+ private:
+ Contains content;
+ bool isContains;
+
+ public:
+ StringContains(const String& str) : content(str), isContains(false) { }
+ StringContains(Contains cntn) : content(static_cast<Contains&&>(cntn)), isContains(true) { }
+
+ bool check(const String& str) { return isContains ? (content == str) : (content.string == str); }
+
+ operator const String&() const { return content.string; }
+
+ const char* c_str() const { return content.string.c_str(); }
+ } m_exception_string;
+
+ AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string);
};
struct DOCTEST_INTERFACE MessageData
@@ -707,13 +853,13 @@ struct DOCTEST_INTERFACE SubcaseSignature
const char* m_file;
int m_line;
+ bool operator==(const SubcaseSignature& other) const;
bool operator<(const SubcaseSignature& other) const;
};
struct DOCTEST_INTERFACE IContextScope
{
- IContextScope();
- virtual ~IContextScope();
+ DOCTEST_DECLARE_INTERFACE(IContextScope)
virtual void stringify(std::ostream*) const = 0;
};
@@ -723,9 +869,8 @@ namespace detail {
struct ContextOptions //!OCLINT too many fields
{
- std::ostream* cout; // stdout stream - std::cout by default
- std::ostream* cerr; // stderr stream - std::cerr by default
- String binary_name; // the test binary name
+ std::ostream* cout = nullptr; // stdout stream
+ String binary_name; // the test binary name
const detail::TestCase* currentTest = nullptr;
@@ -744,9 +889,12 @@ struct ContextOptions //!OCLINT too many fields
bool case_sensitive; // if filtering should be case sensitive
bool exit; // if the program should be exited after the tests are ran/whatever
bool duration; // print the time duration of each test case
+ bool minimal; // minimal console output (only test failures)
+ bool quiet; // no console output
bool no_throw; // to skip exceptions-related assertion macros
bool no_exitcode; // if the framework should return 0 as the exitcode
bool no_run; // to not run the tests at all (can be done with an "*" exclude)
+ bool no_intro; // to not print the intro of the framework
bool no_version; // to not print the version of the framework
bool no_colors; // if output to the console should be colorized
bool force_colors; // forces the use of colors even when a tty cannot be detected
@@ -768,150 +916,184 @@ struct ContextOptions //!OCLINT too many fields
};
namespace detail {
- template <bool CONDITION, typename TYPE = void>
- struct enable_if
- {};
+ namespace types {
+#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
+ using namespace std;
+#else
+ template <bool COND, typename T = void>
+ struct enable_if { };
- template <typename TYPE>
- struct enable_if<true, TYPE>
- { typedef TYPE type; };
+ template <typename T>
+ struct enable_if<true, T> { using type = T; };
- // clang-format off
- template<class T> struct remove_reference { typedef T type; };
- template<class T> struct remove_reference<T&> { typedef T type; };
- template<class T> struct remove_reference<T&&> { typedef T type; };
+ struct true_type { static DOCTEST_CONSTEXPR bool value = true; };
+ struct false_type { static DOCTEST_CONSTEXPR bool value = false; };
- template<typename T, typename U = T&&> U declval(int);
+ template <typename T> struct remove_reference { using type = T; };
+ template <typename T> struct remove_reference<T&> { using type = T; };
+ template <typename T> struct remove_reference<T&&> { using type = T; };
- template<typename T> T declval(long);
+ template <typename T> struct is_rvalue_reference : false_type { };
+ template <typename T> struct is_rvalue_reference<T&&> : true_type { };
- template<typename T> auto declval() DOCTEST_NOEXCEPT -> decltype(declval<T>(0)) ;
+ template<typename T> struct remove_const { using type = T; };
+ template <typename T> struct remove_const<const T> { using type = T; };
+
+ // Compiler intrinsics
+ template <typename T> struct is_enum { static DOCTEST_CONSTEXPR bool value = __is_enum(T); };
+ template <typename T> struct underlying_type { using type = __underlying_type(T); };
+
+ template <typename T> struct is_pointer : false_type { };
+ template <typename T> struct is_pointer<T*> : true_type { };
+
+ template <typename T> struct is_array : false_type { };
+ // NOLINTNEXTLINE(*-avoid-c-arrays)
+ template <typename T, size_t SIZE> struct is_array<T[SIZE]> : true_type { };
+#endif
+ }
- template<class T> struct is_lvalue_reference { const static bool value=false; };
- template<class T> struct is_lvalue_reference<T&> { const static bool value=true; };
+ // <utility>
+ template <typename T>
+ T&& declval();
template <class T>
- inline T&& forward(typename remove_reference<T>::type& t) DOCTEST_NOEXCEPT
- {
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type& t) DOCTEST_NOEXCEPT {
return static_cast<T&&>(t);
}
template <class T>
- inline T&& forward(typename remove_reference<T>::type&& t) DOCTEST_NOEXCEPT
- {
- static_assert(!is_lvalue_reference<T>::value,
- "Can not forward an rvalue as an lvalue.");
+ DOCTEST_CONSTEXPR_FUNC T&& forward(typename types::remove_reference<T>::type&& t) DOCTEST_NOEXCEPT {
return static_cast<T&&>(t);
}
- template<class T> struct remove_const { typedef T type; };
- template<class T> struct remove_const<const T> { typedef T type; };
-#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
- template<class T> struct is_enum : public std::is_enum<T> {};
- template<class T> struct underlying_type : public std::underlying_type<T> {};
-#else
- // Use compiler intrinsics
- template<class T> struct is_enum { constexpr static bool value = __is_enum(T); };
- template<class T> struct underlying_type { typedef __underlying_type(T) type; };
-#endif
- // clang-format on
+ template <typename T>
+ struct deferred_false : types::false_type { };
+
+// MSVS 2015 :(
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+ template <typename T, typename = void>
+ struct has_global_insertion_operator : types::false_type { };
template <typename T>
- struct deferred_false
- // cppcheck-suppress unusedStructMember
- { static const bool value = false; };
-
- namespace has_insertion_operator_impl {
- std::ostream &os();
- template<class T>
- DOCTEST_REF_WRAP(T) val();
-
- template<class, class = void>
- struct check {
- static constexpr bool value = false;
- };
+ struct has_global_insertion_operator<T, decltype(::operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
- template<class T>
- struct check<T, decltype(os() << val<T>(), void())> {
- static constexpr bool value = true;
- };
- } // namespace has_insertion_operator_impl
+ template <typename T, typename = void>
+ struct has_insertion_operator { static DOCTEST_CONSTEXPR bool value = has_global_insertion_operator<T>::value; };
- template<class T>
- using has_insertion_operator = has_insertion_operator_impl::check<const T>;
+ template <typename T, bool global>
+ struct insert_hack;
- DOCTEST_INTERFACE void my_memcpy(void* dest, const void* src, unsigned num);
+ template <typename T>
+ struct insert_hack<T, true> {
+ static void insert(std::ostream& os, const T& t) { ::operator<<(os, t); }
+ };
+
+ template <typename T>
+ struct insert_hack<T, false> {
+ static void insert(std::ostream& os, const T& t) { operator<<(os, t); }
+ };
+
+ template <typename T>
+ using insert_hack_t = insert_hack<T, has_global_insertion_operator<T>::value>;
+#else
+ template <typename T, typename = void>
+ struct has_insertion_operator : types::false_type { };
+#endif
+
+template <typename T>
+struct has_insertion_operator<T, decltype(operator<<(declval<std::ostream&>(), declval<const T&>()), void())> : types::true_type { };
- DOCTEST_INTERFACE std::ostream* getTlsOss(); // returns a thread-local ostringstream
- DOCTEST_INTERFACE String getTlsOssResult();
+ DOCTEST_INTERFACE std::ostream* tlssPush();
+ DOCTEST_INTERFACE String tlssPop();
template <bool C>
- struct StringMakerBase
- {
+ struct StringMakerBase {
template <typename T>
static String convert(const DOCTEST_REF_WRAP(T)) {
+#ifdef DOCTEST_CONFIG_REQUIRE_STRINGIFICATION_FOR_ALL_USED_TYPES
+ static_assert(deferred_false<T>::value, "No stringification detected for type T. See string conversion manual");
+#endif
return "{?}";
}
};
- template <>
- struct StringMakerBase<true>
- {
- template <typename T>
- static String convert(const DOCTEST_REF_WRAP(T) in) {
- *getTlsOss() << in;
- return getTlsOssResult();
- }
- };
-
- DOCTEST_INTERFACE String rawMemoryToString(const void* object, unsigned size);
+ template <typename T>
+ struct filldata;
template <typename T>
- String rawMemoryToString(const DOCTEST_REF_WRAP(T) object) {
- return rawMemoryToString(&object, sizeof(object));
+ void filloss(std::ostream* stream, const T& in) {
+ filldata<T>::fill(stream, in);
+ }
+
+ template <typename T, size_t N>
+ void filloss(std::ostream* stream, const T (&in)[N]) { // NOLINT(*-avoid-c-arrays)
+ // T[N], T(&)[N], T(&&)[N] have same behaviour.
+ // Hence remove reference.
+ filloss<typename types::remove_reference<decltype(in)>::type>(stream, in);
}
template <typename T>
- const char* type_to_string() {
- return "<>";
+ String toStream(const T& in) {
+ std::ostream* stream = tlssPush();
+ filloss(stream, in);
+ return tlssPop();
}
+
+ template <>
+ struct StringMakerBase<true> {
+ template <typename T>
+ static String convert(const DOCTEST_REF_WRAP(T) in) {
+ return toStream(in);
+ }
+ };
} // namespace detail
template <typename T>
-struct StringMaker : public detail::StringMakerBase<detail::has_insertion_operator<T>::value>
+struct StringMaker : public detail::StringMakerBase<
+ detail::has_insertion_operator<T>::value || detail::types::is_pointer<T>::value || detail::types::is_array<T>::value>
{};
-template <typename T>
-struct StringMaker<T*>
-{
- template <typename U>
- static String convert(U* p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
- }
-};
+#ifndef DOCTEST_STRINGIFY
+#ifdef DOCTEST_CONFIG_DOUBLE_STRINGIFY
+#define DOCTEST_STRINGIFY(...) toString(toString(__VA_ARGS__))
+#else
+#define DOCTEST_STRINGIFY(...) toString(__VA_ARGS__)
+#endif
+#endif
-template <typename R, typename C>
-struct StringMaker<R C::*>
-{
- static String convert(R C::*p) {
- if(p)
- return detail::rawMemoryToString(p);
- return "NULL";
- }
-};
+template <typename T>
+String toString() {
+#if DOCTEST_MSVC >= 0 && DOCTEST_CLANG == 0 && DOCTEST_GCC == 0
+ String ret = __FUNCSIG__; // class doctest::String __cdecl doctest::toString<TYPE>(void)
+ String::size_type beginPos = ret.find('<');
+ return ret.substr(beginPos + 1, ret.size() - beginPos - static_cast<String::size_type>(sizeof(">(void)")));
+#else
+ String ret = __PRETTY_FUNCTION__; // doctest::String toString() [with T = TYPE]
+ String::size_type begin = ret.find('=') + 2;
+ return ret.substr(begin, ret.size() - begin - 1);
+#endif
+}
-template <typename T, typename detail::enable_if<!detail::is_enum<T>::value, bool>::type = true>
+template <typename T, typename detail::types::enable_if<!detail::types::is_enum<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
return StringMaker<T>::convert(value);
}
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-DOCTEST_INTERFACE String toString(char* in);
DOCTEST_INTERFACE String toString(const char* in);
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+
+#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
+DOCTEST_INTERFACE String toString(const std::string& in);
+#endif // VS 2019
+
+DOCTEST_INTERFACE String toString(String in);
+
+DOCTEST_INTERFACE String toString(std::nullptr_t);
+
DOCTEST_INTERFACE String toString(bool in);
+
DOCTEST_INTERFACE String toString(float in);
DOCTEST_INTERFACE String toString(double in);
DOCTEST_INTERFACE String toString(double long in);
@@ -919,40 +1101,85 @@ DOCTEST_INTERFACE String toString(double long in);
DOCTEST_INTERFACE String toString(char in);
DOCTEST_INTERFACE String toString(char signed in);
DOCTEST_INTERFACE String toString(char unsigned in);
-DOCTEST_INTERFACE String toString(int short in);
-DOCTEST_INTERFACE String toString(int short unsigned in);
-DOCTEST_INTERFACE String toString(int in);
-DOCTEST_INTERFACE String toString(int unsigned in);
-DOCTEST_INTERFACE String toString(int long in);
-DOCTEST_INTERFACE String toString(int long unsigned in);
-DOCTEST_INTERFACE String toString(int long long in);
-DOCTEST_INTERFACE String toString(int long long unsigned in);
-DOCTEST_INTERFACE String toString(std::nullptr_t in);
-
-template <typename T, typename detail::enable_if<detail::is_enum<T>::value, bool>::type = true>
+DOCTEST_INTERFACE String toString(short in);
+DOCTEST_INTERFACE String toString(short unsigned in);
+DOCTEST_INTERFACE String toString(signed in);
+DOCTEST_INTERFACE String toString(unsigned in);
+DOCTEST_INTERFACE String toString(long in);
+DOCTEST_INTERFACE String toString(long unsigned in);
+DOCTEST_INTERFACE String toString(long long in);
+DOCTEST_INTERFACE String toString(long long unsigned in);
+
+template <typename T, typename detail::types::enable_if<detail::types::is_enum<T>::value, bool>::type = true>
String toString(const DOCTEST_REF_WRAP(T) value) {
- typedef typename detail::underlying_type<T>::type UT;
- return toString(static_cast<UT>(value));
+ using UT = typename detail::types::underlying_type<T>::type;
+ return (DOCTEST_STRINGIFY(static_cast<UT>(value)));
}
-#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
-// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
-DOCTEST_INTERFACE String toString(const std::string& in);
-#endif // VS 2019
+namespace detail {
+ template <typename T>
+ struct filldata
+ {
+ static void fill(std::ostream* stream, const T& in) {
+#if defined(_MSC_VER) && _MSC_VER <= 1900
+ insert_hack_t<T>::insert(*stream, in);
+#else
+ operator<<(*stream, in);
+#endif
+ }
+ };
+
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
+// NOLINTBEGIN(*-avoid-c-arrays)
+ template <typename T, size_t N>
+ struct filldata<T[N]> {
+ static void fill(std::ostream* stream, const T(&in)[N]) {
+ *stream << "[";
+ for (size_t i = 0; i < N; i++) {
+ if (i != 0) { *stream << ", "; }
+ *stream << (DOCTEST_STRINGIFY(in[i]));
+ }
+ *stream << "]";
+ }
+ };
+// NOLINTEND(*-avoid-c-arrays)
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+
+ // Specialized since we don't want the terminating null byte!
+// NOLINTBEGIN(*-avoid-c-arrays)
+ template <size_t N>
+ struct filldata<const char[N]> {
+ static void fill(std::ostream* stream, const char (&in)[N]) {
+ *stream << String(in, in[N - 1] ? N : N - 1);
+ } // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+ };
+// NOLINTEND(*-avoid-c-arrays)
+
+ template <>
+ struct filldata<const void*> {
+ static void fill(std::ostream* stream, const void* in);
+ };
+
+ template <typename T>
+ struct filldata<T*> {
+ static void fill(std::ostream* stream, const T* in) {
+ filldata<const void*>::fill(stream, in);
+ }
+ };
+}
-class DOCTEST_INTERFACE Approx
+struct DOCTEST_INTERFACE Approx
{
-public:
- explicit Approx(double value);
+ Approx(double value);
Approx operator()(double value) const;
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
template <typename T>
explicit Approx(const T& value,
- typename detail::enable_if<std::is_constructible<double, T>::value>::type* =
+ typename detail::types::enable_if<std::is_constructible<double, T>::value>::type* =
static_cast<T*>(nullptr)) {
- *this = Approx(static_cast<double>(value));
+ *this = static_cast<double>(value);
}
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
@@ -960,7 +1187,7 @@ public:
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
template <typename T>
- typename detail::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
+ typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type epsilon(
const T& newEpsilon) {
m_epsilon = static_cast<double>(newEpsilon);
return *this;
@@ -971,7 +1198,7 @@ public:
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
template <typename T>
- typename detail::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
+ typename std::enable_if<std::is_constructible<double, T>::value, Approx&>::type scale(
const T& newScale) {
m_scale = static_cast<double>(newScale);
return *this;
@@ -992,30 +1219,27 @@ public:
DOCTEST_INTERFACE friend bool operator> (double lhs, const Approx & rhs);
DOCTEST_INTERFACE friend bool operator> (const Approx & lhs, double rhs);
- DOCTEST_INTERFACE friend String toString(const Approx& in);
-
#ifdef DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
#define DOCTEST_APPROX_PREFIX \
- template <typename T> friend typename detail::enable_if<std::is_constructible<double, T>::value, bool>::type
+ template <typename T> friend typename std::enable_if<std::is_constructible<double, T>::value, bool>::type
- DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(double(lhs), rhs); }
+ DOCTEST_APPROX_PREFIX operator==(const T& lhs, const Approx& rhs) { return operator==(static_cast<double>(lhs), rhs); }
DOCTEST_APPROX_PREFIX operator==(const Approx& lhs, const T& rhs) { return operator==(rhs, lhs); }
DOCTEST_APPROX_PREFIX operator!=(const T& lhs, const Approx& rhs) { return !operator==(lhs, rhs); }
DOCTEST_APPROX_PREFIX operator!=(const Approx& lhs, const T& rhs) { return !operator==(rhs, lhs); }
- DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return double(lhs) < rhs.m_value || lhs == rhs; }
- DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < double(rhs) || lhs == rhs; }
- DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return double(lhs) > rhs.m_value || lhs == rhs; }
- DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > double(rhs) || lhs == rhs; }
- DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return double(lhs) < rhs.m_value && lhs != rhs; }
- DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < double(rhs) && lhs != rhs; }
- DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return double(lhs) > rhs.m_value && lhs != rhs; }
- DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > double(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator<=(const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator>=(const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) || lhs == rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) < rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator< (const Approx& lhs, const T& rhs) { return lhs.m_value < static_cast<double>(rhs) && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const T& lhs, const Approx& rhs) { return static_cast<double>(lhs) > rhs.m_value && lhs != rhs; }
+ DOCTEST_APPROX_PREFIX operator> (const Approx& lhs, const T& rhs) { return lhs.m_value > static_cast<double>(rhs) && lhs != rhs; }
#undef DOCTEST_APPROX_PREFIX
#endif // DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
// clang-format on
-private:
double m_epsilon;
double m_scale;
double m_value;
@@ -1025,18 +1249,35 @@ DOCTEST_INTERFACE String toString(const Approx& in);
DOCTEST_INTERFACE const ContextOptions* getContextOptions();
-#if !defined(DOCTEST_CONFIG_DISABLE)
+template <typename F>
+struct DOCTEST_INTERFACE_DECL IsNaN
+{
+ F value; bool flipped;
+ IsNaN(F f, bool flip = false) : value(f), flipped(flip) { }
+ IsNaN<F> operator!() const { return { value, !flipped }; }
+ operator bool() const;
+};
+#ifndef __MINGW32__
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<float>;
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<double>;
+extern template struct DOCTEST_INTERFACE_DECL IsNaN<long double>;
+#endif
+DOCTEST_INTERFACE String toString(IsNaN<float> in);
+DOCTEST_INTERFACE String toString(IsNaN<double> in);
+DOCTEST_INTERFACE String toString(IsNaN<double long> in);
+
+#ifndef DOCTEST_CONFIG_DISABLE
namespace detail {
// clang-format off
#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- template<class T> struct decay_array { typedef T type; };
- template<class T, unsigned N> struct decay_array<T[N]> { typedef T* type; };
- template<class T> struct decay_array<T[]> { typedef T* type; };
+ template<class T> struct decay_array { using type = T; };
+ template<class T, unsigned N> struct decay_array<T[N]> { using type = T*; };
+ template<class T> struct decay_array<T[]> { using type = T*; };
- template<class T> struct not_char_pointer { enum { value = 1 }; };
- template<> struct not_char_pointer<char*> { enum { value = 0 }; };
- template<> struct not_char_pointer<const char*> { enum { value = 0 }; };
+ template<class T> struct not_char_pointer { static DOCTEST_CONSTEXPR value = 1; };
+ template<> struct not_char_pointer<char*> { static DOCTEST_CONSTEXPR value = 0; };
+ template<> struct not_char_pointer<const char*> { static DOCTEST_CONSTEXPR value = 0; };
template<class T> struct can_use_op : public not_char_pointer<typename decay_array<T>::type> {};
#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
@@ -1059,16 +1300,22 @@ namespace detail {
bool m_entered = false;
Subcase(const String& name, const char* file, int line);
+ Subcase(const Subcase&) = delete;
+ Subcase(Subcase&&) = delete;
+ Subcase& operator=(const Subcase&) = delete;
+ Subcase& operator=(Subcase&&) = delete;
~Subcase();
operator bool() const;
+
+ private:
+ bool checkFilters();
};
template <typename L, typename R>
String stringifyBinaryExpr(const DOCTEST_REF_WRAP(L) lhs, const char* op,
const DOCTEST_REF_WRAP(R) rhs) {
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- return toString(lhs) + op + toString(rhs);
+ return (DOCTEST_STRINGIFY(lhs)) + op + (DOCTEST_STRINGIFY(rhs));
}
#if DOCTEST_CLANG && DOCTEST_CLANG < DOCTEST_COMPILER(3, 6, 0)
@@ -1079,12 +1326,12 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
// If not it doesn't find the operator or if the operator at global scope is defined after
// this template, the template won't be instantiated due to SFINAE. Once the template is not
// instantiated it can look for global operator using normal conversions.
-#define SFINAE_OP(ret,op) decltype(doctest::detail::declval<L>() op doctest::detail::declval<R>(),static_cast<ret>(0))
+#define SFINAE_OP(ret,op) decltype((void)(doctest::detail::declval<L>() op doctest::detail::declval<R>()),ret{})
#define DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(op, op_str, op_macro) \
template <typename R> \
- DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
- bool res = op_macro(doctest::detail::forward<L>(lhs), doctest::detail::forward<R>(rhs)); \
+ DOCTEST_NOINLINE SFINAE_OP(Result,op) operator op(R&& rhs) { \
+ bool res = op_macro(doctest::detail::forward<const L>(lhs), doctest::detail::forward<R>(rhs)); \
if(m_at & assertType::is_false) \
res = !res; \
if(!res || doctest::getContextOptions()->success) \
@@ -1103,11 +1350,12 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
return *this; \
}
- struct DOCTEST_INTERFACE Result
+ struct DOCTEST_INTERFACE Result // NOLINT(*-member-init)
{
bool m_passed;
String m_decomp;
+ Result() = default; // TODO: Why do we need this? (To remove NOLINT)
Result(bool passed, const String& decomposition = String());
// forbidding some expressions based on this table: https://en.cppreference.com/w/cpp/language/operator_precedence
@@ -1164,8 +1412,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
#ifndef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
#define DOCTEST_COMPARISON_RETURN_TYPE bool
#else // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-#define DOCTEST_COMPARISON_RETURN_TYPE typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+#define DOCTEST_COMPARISON_RETURN_TYPE typename types::enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
inline bool eq(const char* lhs, const char* rhs) { return String(lhs) == String(rhs); }
inline bool ne(const char* lhs, const char* rhs) { return String(lhs) != String(rhs); }
inline bool lt(const char* lhs, const char* rhs) { return String(lhs) < String(rhs); }
@@ -1213,26 +1460,26 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-comparison")
assertType::Enum m_at;
explicit Expression_lhs(L&& in, assertType::Enum at)
- : lhs(doctest::detail::forward<L>(in))
+ : lhs(static_cast<L&&>(in))
, m_at(at) {}
DOCTEST_NOINLINE operator Result() {
-// this is needed only foc MSVC 2015:
-// https://ci.appveyor.com/project/onqtam/doctest/builds/38181202
+// this is needed only for MSVC 2015
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4800) // 'int': forcing value to bool
bool res = static_cast<bool>(lhs);
DOCTEST_MSVC_SUPPRESS_WARNING_POP
- if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ if(m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
res = !res;
+ }
- if(!res || getContextOptions()->success)
- return Result(res, toString(lhs));
- return Result(res);
+ if(!res || getContextOptions()->success) {
+ return { res, (DOCTEST_STRINGIFY(lhs)) };
+ }
+ return { res };
}
- /* This is required for user-defined conversions from Expression_lhs to L */
- //operator L() const { return lhs; }
- operator L() const { return lhs; }
+ /* This is required for user-defined conversions from Expression_lhs to L */
+ operator L() const { return lhs; }
// clang-format off
DOCTEST_DO_BINARY_EXPRESSION_COMPARISON(==, " == ", DOCTEST_CMP_EQ) //!OCLINT bitwise operator in conditional
@@ -1289,22 +1536,27 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
// https://github.com/catchorg/Catch2/issues/870
// https://github.com/catchorg/Catch2/issues/565
template <typename L>
- Expression_lhs<L> operator<<(L &&operand) {
- return Expression_lhs<L>(doctest::detail::forward<L>(operand), m_at);
+ Expression_lhs<L> operator<<(L&& operand) {
+ return Expression_lhs<L>(static_cast<L&&>(operand), m_at);
+ }
+
+ template <typename L,typename types::enable_if<!doctest::detail::types::is_rvalue_reference<L>::value,void >::type* = nullptr>
+ Expression_lhs<const L&> operator<<(const L &operand) {
+ return Expression_lhs<const L&>(operand, m_at);
}
};
struct DOCTEST_INTERFACE TestSuite
{
- const char* m_test_suite;
- const char* m_description;
- bool m_skip;
- bool m_no_breaks;
- bool m_no_output;
- bool m_may_fail;
- bool m_should_fail;
- int m_expected_failures;
- double m_timeout;
+ const char* m_test_suite = nullptr;
+ const char* m_description = nullptr;
+ bool m_skip = false;
+ bool m_no_breaks = false;
+ bool m_no_output = false;
+ bool m_may_fail = false;
+ bool m_should_fail = false;
+ int m_expected_failures = 0;
+ double m_timeout = 0;
TestSuite& operator*(const char* in);
@@ -1315,25 +1567,28 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
}
};
- typedef void (*funcType)();
+ using funcType = void (*)();
struct DOCTEST_INTERFACE TestCase : public TestCaseData
{
funcType m_test; // a function pointer to the test case
- const char* m_type; // for templated test cases - gets appended to the real name
+ String m_type; // for templated test cases - gets appended to the real name
int m_template_id; // an ID used to distinguish between the different versions of a templated test case
String m_full_name; // contains the name (only for templated test cases!) + the template type
TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
- const char* type = "", int template_id = -1);
+ const String& type = String(), int template_id = -1);
TestCase(const TestCase& other);
+ TestCase(TestCase&&) = delete;
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
TestCase& operator=(const TestCase& other);
DOCTEST_MSVC_SUPPRESS_WARNING_POP
+ TestCase& operator=(TestCase&&) = delete;
+
TestCase& operator*(const char* in);
template <typename T>
@@ -1343,6 +1598,8 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
}
bool operator<(const TestCase& other) const;
+
+ ~TestCase() = default;
};
// forward declarations of functions used by the macros
@@ -1382,27 +1639,36 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
struct DOCTEST_INTERFACE ResultBuilder : public AssertData
{
ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
- const char* exception_type = "", const char* exception_string = "");
+ const char* exception_type = "", const String& exception_string = "");
+
+ ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string);
void setResult(const Result& res);
template <int comparison, typename L, typename R>
- DOCTEST_NOINLINE void binary_assert(const DOCTEST_REF_WRAP(L) lhs,
+ DOCTEST_NOINLINE bool binary_assert(const DOCTEST_REF_WRAP(L) lhs,
const DOCTEST_REF_WRAP(R) rhs) {
m_failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
- if(m_failed || getContextOptions()->success)
+ if (m_failed || getContextOptions()->success) {
m_decomp = stringifyBinaryExpr(lhs, ", ", rhs);
+ }
+ return !m_failed;
}
template <typename L>
- DOCTEST_NOINLINE void unary_assert(const DOCTEST_REF_WRAP(L) val) {
+ DOCTEST_NOINLINE bool unary_assert(const DOCTEST_REF_WRAP(L) val) {
m_failed = !val;
- if(m_at & assertType::is_false) //!OCLINT bitwise operator in conditional
+ if (m_at & assertType::is_false) { //!OCLINT bitwise operator in conditional
m_failed = !m_failed;
+ }
+
+ if (m_failed || getContextOptions()->success) {
+ m_decomp = (DOCTEST_STRINGIFY(val));
+ }
- if(m_failed || getContextOptions()->success)
- m_decomp = toString(val);
+ return !m_failed;
}
void translateException();
@@ -1422,8 +1688,8 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_INTERFACE void failed_out_of_a_testing_context(const AssertData& ad);
- DOCTEST_INTERFACE void decomp_assert(assertType::Enum at, const char* file, int line,
- const char* expr, Result result);
+ DOCTEST_INTERFACE bool decomp_assert(assertType::Enum at, const char* file, int line,
+ const char* expr, const Result& result);
#define DOCTEST_ASSERT_OUT_OF_TESTS(decomp) \
do { \
@@ -1438,7 +1704,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
if(checkIfShouldThrow(at)) \
throwException(); \
} \
- return; \
+ return !failed; \
} \
} while(false)
@@ -1453,7 +1719,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
throwException()
template <int comparison, typename L, typename R>
- DOCTEST_NOINLINE void binary_assert(assertType::Enum at, const char* file, int line,
+ DOCTEST_NOINLINE bool binary_assert(assertType::Enum at, const char* file, int line,
const char* expr, const DOCTEST_REF_WRAP(L) lhs,
const DOCTEST_REF_WRAP(R) rhs) {
bool failed = !RelationalComparator<comparison, L, R>()(lhs, rhs);
@@ -1464,10 +1730,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
// ###################################################################################
DOCTEST_ASSERT_OUT_OF_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
DOCTEST_ASSERT_IN_TESTS(stringifyBinaryExpr(lhs, ", ", rhs));
+ return !failed;
}
template <typename L>
- DOCTEST_NOINLINE void unary_assert(assertType::Enum at, const char* file, int line,
+ DOCTEST_NOINLINE bool unary_assert(assertType::Enum at, const char* file, int line,
const char* expr, const DOCTEST_REF_WRAP(L) val) {
bool failed = !val;
@@ -1478,14 +1745,14 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
// IF THE DEBUGGER BREAKS HERE - GO 1 LEVEL UP IN THE CALLSTACK FOR THE FAILING ASSERT
// THIS IS THE EFFECT OF HAVING 'DOCTEST_CONFIG_SUPER_FAST_ASSERTS' DEFINED
// ###################################################################################
- DOCTEST_ASSERT_OUT_OF_TESTS(toString(val));
- DOCTEST_ASSERT_IN_TESTS(toString(val));
+ DOCTEST_ASSERT_OUT_OF_TESTS((DOCTEST_STRINGIFY(val)));
+ DOCTEST_ASSERT_IN_TESTS((DOCTEST_STRINGIFY(val)));
+ return !failed;
}
struct DOCTEST_INTERFACE IExceptionTranslator
{
- IExceptionTranslator();
- virtual ~IExceptionTranslator();
+ DOCTEST_DECLARE_INTERFACE(IExceptionTranslator)
virtual bool translate(String&) const = 0;
};
@@ -1501,7 +1768,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
try {
throw; // lgtm [cpp/rethrow-no-exception]
// cppcheck-suppress catchExceptionByValue
- } catch(T ex) { // NOLINT
+ } catch(const T& ex) {
res = m_translateFunction(ex); //!OCLINT parameter reassignment
return true;
} catch(...) {} //!OCLINT - empty catch statement
@@ -1516,95 +1783,70 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_INTERFACE void registerExceptionTranslatorImpl(const IExceptionTranslator* et);
- template <bool C>
- struct StringStreamBase
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << toString(in);
- }
-
- // always treat char* as a string in this context - no matter
- // if DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING is defined
- static void convert(std::ostream* s, const char* in) { *s << String(in); }
- };
-
- template <>
- struct StringStreamBase<true>
- {
- template <typename T>
- static void convert(std::ostream* s, const T& in) {
- *s << in;
- }
- };
+ // ContextScope base class used to allow implementing methods of ContextScope
+ // that don't depend on the template parameter in doctest.cpp.
+ struct DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
+ ContextScopeBase(const ContextScopeBase&) = delete;
- template <typename T>
- struct StringStream : public StringStreamBase<has_insertion_operator<T>::value>
- {};
+ ContextScopeBase& operator=(const ContextScopeBase&) = delete;
+ ContextScopeBase& operator=(ContextScopeBase&&) = delete;
- template <typename T>
- void toStream(std::ostream* s, const T& value) {
- StringStream<T>::convert(s, value);
- }
+ ~ContextScopeBase() override = default;
-#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, char* in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, const char* in);
-#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- DOCTEST_INTERFACE void toStream(std::ostream* s, bool in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, float in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, double long in);
-
- DOCTEST_INTERFACE void toStream(std::ostream* s, char in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char signed in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, char unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int short unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long unsigned in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long in);
- DOCTEST_INTERFACE void toStream(std::ostream* s, int long long unsigned in);
-
- // ContextScope base class used to allow implementing methods of ContextScope
- // that don't depend on the template parameter in doctest.cpp.
- class DOCTEST_INTERFACE ContextScopeBase : public IContextScope {
protected:
ContextScopeBase();
+ ContextScopeBase(ContextScopeBase&& other) noexcept;
void destroy();
+ bool need_to_destroy{true};
};
template <typename L> class ContextScope : public ContextScopeBase
{
- const L lambda_;
+ L lambda_;
public:
explicit ContextScope(const L &lambda) : lambda_(lambda) {}
+ explicit ContextScope(L&& lambda) : lambda_(static_cast<L&&>(lambda)) { }
+
+ ContextScope(const ContextScope&) = delete;
+ ContextScope(ContextScope&&) noexcept = default;
- ContextScope(ContextScope &&other) : lambda_(other.lambda_) {}
+ ContextScope& operator=(const ContextScope&) = delete;
+ ContextScope& operator=(ContextScope&&) = delete;
void stringify(std::ostream* s) const override { lambda_(s); }
- ~ContextScope() override { destroy(); }
+ ~ContextScope() override {
+ if (need_to_destroy) {
+ destroy();
+ }
+ }
};
struct DOCTEST_INTERFACE MessageBuilder : public MessageData
{
std::ostream* m_stream;
+ bool logged = false;
MessageBuilder(const char* file, int line, assertType::Enum severity);
- MessageBuilder() = delete;
+
+ MessageBuilder(const MessageBuilder&) = delete;
+ MessageBuilder(MessageBuilder&&) = delete;
+
+ MessageBuilder& operator=(const MessageBuilder&) = delete;
+ MessageBuilder& operator=(MessageBuilder&&) = delete;
+
~MessageBuilder();
// the preferred way of chaining parameters for stringification
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4866)
template <typename T>
MessageBuilder& operator,(const T& in) {
- toStream(m_stream, in);
+ *m_stream << (DOCTEST_STRINGIFY(in));
return *this;
}
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
// kept here just for backwards-compatibility - the comma operator should be preferred now
template <typename T>
@@ -1620,7 +1862,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
bool log();
void react();
};
-
+
template <typename L>
ContextScope<L> MakeContextScope(const L &lambda) {
return ContextScope<L>(lambda);
@@ -1673,7 +1915,7 @@ int registerExceptionTranslator(String (*)(T)) {
#endif // DOCTEST_CONFIG_DISABLE
namespace detail {
- typedef void (*assert_handler)(const AssertData&);
+ using assert_handler = void (*)(const AssertData&);
struct ContextState;
} // namespace detail
@@ -1686,12 +1928,19 @@ class DOCTEST_INTERFACE Context
public:
explicit Context(int argc = 0, const char* const* argv = nullptr);
- ~Context();
+ Context(const Context&) = delete;
+ Context(Context&&) = delete;
+
+ Context& operator=(const Context&) = delete;
+ Context& operator=(Context&&) = delete;
+
+ ~Context(); // NOLINT(performance-trivially-destructible)
void applyCommandLine(int argc, const char* const* argv);
void addFilter(const char* filter, const char* value);
void clearFilters();
+ void setOption(const char* option, bool value);
void setOption(const char* option, int value);
void setOption(const char* option, const char* value);
@@ -1701,6 +1950,8 @@ public:
void setAssertHandler(detail::assert_handler ah);
+ void setCout(std::ostream* out);
+
int run();
};
@@ -1727,6 +1978,7 @@ struct DOCTEST_INTERFACE CurrentTestCaseStats
int numAssertsFailedCurrentTest;
double seconds;
int failure_flags; // use TestCaseFailureReason::Enum
+ bool testCaseSuccess;
};
struct DOCTEST_INTERFACE TestCaseException
@@ -1790,8 +2042,7 @@ struct DOCTEST_INTERFACE IReporter
// or isn't in the execution range (between first and last) (safe to cache a pointer to the input)
virtual void test_case_skipped(const TestCaseData&) = 0;
- // doctest will not be managing the lifetimes of reporters given to it but this would still be nice to have
- virtual ~IReporter();
+ DOCTEST_DECLARE_INTERFACE(IReporter)
// can obtain all currently active contexts and stringify them if one wishes to do so
static int get_num_active_contexts();
@@ -1803,7 +2054,7 @@ struct DOCTEST_INTERFACE IReporter
};
namespace detail {
- typedef IReporter* (*reporterCreatorFunc)(const ContextOptions&);
+ using reporterCreatorFunc = IReporter* (*)(const ContextOptions&);
DOCTEST_INTERFACE void registerReporterImpl(const char* name, int prio, reporterCreatorFunc c, bool isReporter);
@@ -1820,14 +2071,30 @@ int registerReporter(const char* name, int priority, bool isReporter) {
}
} // namespace doctest
+#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
+#define DOCTEST_FUNC_EMPTY [] { return false; }()
+#else
+#define DOCTEST_FUNC_EMPTY (void)0
+#endif
+
// if registering is not disabled
-#if !defined(DOCTEST_CONFIG_DISABLE)
+#ifndef DOCTEST_CONFIG_DISABLE
+
+#ifdef DOCTEST_CONFIG_ASSERTS_RETURN_VALUES
+#define DOCTEST_FUNC_SCOPE_BEGIN [&]
+#define DOCTEST_FUNC_SCOPE_END ()
+#define DOCTEST_FUNC_SCOPE_RET(v) return v
+#else
+#define DOCTEST_FUNC_SCOPE_BEGIN do
+#define DOCTEST_FUNC_SCOPE_END while(false)
+#define DOCTEST_FUNC_SCOPE_RET(v) (void)0
+#endif
// common code in asserts - for convenience
-#define DOCTEST_ASSERT_LOG_AND_REACT(b) \
- if(b.log()) \
- DOCTEST_BREAK_INTO_DEBUGGER(); \
- b.react()
+#define DOCTEST_ASSERT_LOG_REACT_RETURN(b) \
+ if(b.log()) DOCTEST_BREAK_INTO_DEBUGGER(); \
+ b.react(); \
+ DOCTEST_FUNC_SCOPE_RET(!b.m_failed)
#ifdef DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#define DOCTEST_WRAP_IN_TRY(x) x;
@@ -1835,7 +2102,7 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_WRAP_IN_TRY(x) \
try { \
x; \
- } catch(...) { _DOCTEST_RB.translateException(); }
+ } catch(...) { DOCTEST_RB.translateException(); }
#endif // DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS
#ifdef DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS
@@ -1849,27 +2116,26 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// registers the test by initializing a dummy var with a function
#define DOCTEST_REGISTER_FUNCTION(global_prefix, f, decorators) \
- global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
+ global_prefix DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT */ \
doctest::detail::regTest( \
doctest::detail::TestCase( \
f, __FILE__, __LINE__, \
doctest_detail_test_suite_ns::getCurrentTestSuite()) * \
- decorators); \
- DOCTEST_GLOBAL_NO_WARNINGS_END()
+ decorators))
#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, decorators) \
- namespace { \
+ namespace { /* NOLINT */ \
struct der : public base \
{ \
void f(); \
}; \
- static void func() { \
+ static inline DOCTEST_NOINLINE void func() { \
der v; \
v.f(); \
} \
DOCTEST_REGISTER_FUNCTION(DOCTEST_EMPTY, func, decorators) \
} \
- inline DOCTEST_NOINLINE void der::f()
+ inline DOCTEST_NOINLINE void der::f() // NOLINT(misc-definitions-in-headers)
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION(f, decorators) \
static void f(); \
@@ -1878,18 +2144,18 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(f, proxy, decorators) \
static doctest::detail::funcType proxy() { return f; } \
- DOCTEST_REGISTER_FUNCTION(inline const, proxy(), decorators) \
+ DOCTEST_REGISTER_FUNCTION(inline, proxy(), decorators) \
static void f()
// for registering tests
#define DOCTEST_TEST_CASE(decorators) \
- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
// for registering tests in classes - requires C++17 for inline variables!
-#if __cplusplus >= 201703L || (DOCTEST_MSVC >= DOCTEST_COMPILER(19, 12, 0) && _MSVC_LANG >= 201703L)
+#if DOCTEST_CPLUSPLUS >= 201703L
#define DOCTEST_TEST_CASE_CLASS(decorators) \
- DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), \
- DOCTEST_ANONYMOUS(_DOCTEST_ANON_PROXY_), \
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION_IN_CLASS(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_PROXY_), \
decorators)
#else // DOCTEST_TEST_CASE_CLASS
#define DOCTEST_TEST_CASE_CLASS(...) \
@@ -1898,26 +2164,25 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// for registering tests with a fixture
#define DOCTEST_TEST_CASE_FIXTURE(c, decorators) \
- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), c, \
- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), decorators)
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), c, \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), decorators)
// for converting types to strings without the <typeinfo> header and demangling
-#define DOCTEST_TYPE_TO_STRING_IMPL(...) \
- template <> \
- inline const char* type_to_string<__VA_ARGS__>() { \
- return "<" #__VA_ARGS__ ">"; \
- }
-#define DOCTEST_TYPE_TO_STRING(...) \
- namespace doctest { namespace detail { \
- DOCTEST_TYPE_TO_STRING_IMPL(__VA_ARGS__) \
+#define DOCTEST_TYPE_TO_STRING_AS(str, ...) \
+ namespace doctest { \
+ template <> \
+ inline String toString<__VA_ARGS__>() { \
+ return str; \
} \
} \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ static_assert(true, "")
+
+#define DOCTEST_TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING_AS(#__VA_ARGS__, __VA_ARGS__)
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, iter, func) \
template <typename T> \
static void func(); \
- namespace { \
+ namespace { /* NOLINT */ \
template <typename Tuple> \
struct iter; \
template <typename Type, typename... Rest> \
@@ -1926,7 +2191,7 @@ int registerReporter(const char* name, int priority, bool isReporter) {
iter(const char* file, unsigned line, int index) { \
doctest::detail::regTest(doctest::detail::TestCase(func<Type>, file, line, \
doctest_detail_test_suite_ns::getCurrentTestSuite(), \
- doctest::detail::type_to_string<Type>(), \
+ doctest::toString<Type>(), \
int(line) * 1000 + index) \
* dec); \
iter<std::tuple<Rest...>>(file, line, index + 1); \
@@ -1943,20 +2208,20 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(dec, T, id) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(id, ITERATOR), \
- DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_))
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_))
#define DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, anon, ...) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY)) = \
- doctest::detail::instantiationHelper(DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0));\
- DOCTEST_GLOBAL_NO_WARNINGS_END()
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_CAT(anon, DUMMY), /* NOLINT(cert-err58-cpp, fuchsia-statically-constructed-objects) */ \
+ doctest::detail::instantiationHelper( \
+ DOCTEST_CAT(id, ITERATOR)<__VA_ARGS__>(__FILE__, __LINE__, 0)))
#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), std::tuple<__VA_ARGS__>) \
+ static_assert(true, "")
#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__) \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_TEST_CASE_TEMPLATE_INSTANTIATE_IMPL(id, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__) \
+ static_assert(true, "")
#define DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, anon, ...) \
DOCTEST_TEST_CASE_TEMPLATE_DEFINE_IMPL(dec, T, DOCTEST_CAT(anon, ITERATOR), anon); \
@@ -1965,17 +2230,17 @@ int registerReporter(const char* name, int priority, bool isReporter) {
static void anon()
#define DOCTEST_TEST_CASE_TEMPLATE(dec, T, ...) \
- DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_), __VA_ARGS__)
+ DOCTEST_TEST_CASE_TEMPLATE_IMPL(dec, T, DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_), __VA_ARGS__)
// for subcases
#define DOCTEST_SUBCASE(name) \
- if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
+ if(const doctest::detail::Subcase & DOCTEST_ANONYMOUS(DOCTEST_ANON_SUBCASE_) DOCTEST_UNUSED = \
doctest::detail::Subcase(name, __FILE__, __LINE__))
// for grouping tests in test suites by using code blocks
#define DOCTEST_TEST_SUITE_IMPL(decorators, ns_name) \
namespace ns_name { namespace doctest_detail_test_suite_ns { \
- static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() { \
+ static DOCTEST_NOINLINE doctest::detail::TestSuite& getCurrentTestSuite() noexcept { \
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4640) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wexit-time-destructors") \
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmissing-field-initializers") \
@@ -1995,53 +2260,53 @@ int registerReporter(const char* name, int priority, bool isReporter) {
namespace ns_name
#define DOCTEST_TEST_SUITE(decorators) \
- DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(_DOCTEST_ANON_SUITE_))
+ DOCTEST_TEST_SUITE_IMPL(decorators, DOCTEST_ANONYMOUS(DOCTEST_ANON_SUITE_))
// for starting a testsuite block
#define DOCTEST_TEST_SUITE_BEGIN(decorators) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
- doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators); \
- DOCTEST_GLOBAL_NO_WARNINGS_END() \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * decorators)) \
+ static_assert(true, "")
// for ending a testsuite block
#define DOCTEST_TEST_SUITE_END \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_VAR_)) = \
- doctest::detail::setTestSuite(doctest::detail::TestSuite() * ""); \
- DOCTEST_GLOBAL_NO_WARNINGS_END() \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_VAR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::detail::setTestSuite(doctest::detail::TestSuite() * "")) \
+ using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
// for registering exception translators
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(translatorName, signature) \
inline doctest::String translatorName(signature); \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)) = \
- doctest::registerExceptionTranslator(translatorName); \
- DOCTEST_GLOBAL_NO_WARNINGS_END() \
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerExceptionTranslator(translatorName)) \
doctest::String translatorName(signature)
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
- DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_), \
+ DOCTEST_REGISTER_EXCEPTION_TRANSLATOR_IMPL(DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_), \
signature)
// for registering reporters
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
- doctest::registerReporter<reporter>(name, priority, true); \
- DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerReporter<reporter>(name, priority, true)) \
+ static_assert(true, "")
// for registering listeners
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter) \
- DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(_DOCTEST_ANON_REPORTER_)) = \
- doctest::registerReporter<reporter>(name, priority, false); \
- DOCTEST_GLOBAL_NO_WARNINGS_END() typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ DOCTEST_GLOBAL_NO_WARNINGS(DOCTEST_ANONYMOUS(DOCTEST_ANON_REPORTER_), /* NOLINT(cert-err58-cpp) */ \
+ doctest::registerReporter<reporter>(name, priority, false)) \
+ static_assert(true, "")
-// for logging
+// clang-format off
+// for logging - disabling formatting because it's important to have these on 2 separate lines - see PR #557
#define DOCTEST_INFO(...) \
- DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_), \
+ DOCTEST_INFO_IMPL(DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_), \
+ DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_OTHER_), \
__VA_ARGS__)
+// clang-format on
#define DOCTEST_INFO_IMPL(mb_name, s_name, ...) \
- auto DOCTEST_ANONYMOUS(_DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
+ auto DOCTEST_ANONYMOUS(DOCTEST_CAPTURE_) = doctest::detail::MakeContextScope( \
[&](std::ostream* s_name) { \
doctest::detail::MessageBuilder mb_name(__FILE__, __LINE__, doctest::assertType::is_warn); \
mb_name.m_stream = s_name; \
@@ -2051,16 +2316,18 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_CAPTURE(x) DOCTEST_INFO(#x " := ", x)
#define DOCTEST_ADD_AT_IMPL(type, file, line, mb, ...) \
- do { \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
doctest::detail::MessageBuilder mb(file, line, doctest::assertType::type); \
mb * __VA_ARGS__; \
- DOCTEST_ASSERT_LOG_AND_REACT(mb); \
- } while(false)
+ if(mb.log()) \
+ DOCTEST_BREAK_INTO_DEBUGGER(); \
+ mb.react(); \
+ } DOCTEST_FUNC_SCOPE_END
// clang-format off
-#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
-#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
-#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(_DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_MESSAGE_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_warn, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_CHECK_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_check, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
+#define DOCTEST_ADD_FAIL_AT(file, line, ...) DOCTEST_ADD_AT_IMPL(is_require, file, line, DOCTEST_ANONYMOUS(DOCTEST_MESSAGE_), __VA_ARGS__)
// clang-format on
#define DOCTEST_MESSAGE(...) DOCTEST_ADD_MESSAGE_AT(__FILE__, __LINE__, __VA_ARGS__)
@@ -2073,18 +2340,37 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_ASSERT_IMPLEMENT_2(assert_type, ...) \
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Woverloaded-shift-op-parentheses") \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, #__VA_ARGS__); \
- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.setResult( \
+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.setResult( \
doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
- << __VA_ARGS__)) \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB) \
+ << __VA_ARGS__)) /* NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks) */ \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB) \
DOCTEST_CLANG_SUPPRESS_WARNING_POP
#define DOCTEST_ASSERT_IMPLEMENT_1(assert_type, ...) \
- do { \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
DOCTEST_ASSERT_IMPLEMENT_2(assert_type, __VA_ARGS__); \
- } while(false)
+ } DOCTEST_FUNC_SCOPE_END // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
+
+#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY( \
+ DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
+ __VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ __LINE__, #__VA_ARGS__); \
+ DOCTEST_WRAP_IN_TRY(DOCTEST_RB.unary_assert(__VA_ARGS__)) \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
@@ -2098,6 +2384,14 @@ int registerReporter(const char* name, int priority, bool isReporter) {
doctest::detail::ExpressionDecomposer(doctest::assertType::assert_type) \
<< __VA_ARGS__) DOCTEST_CLANG_SUPPRESS_WARNING_POP
+#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \
+ doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
+ doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
+
+#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
+ doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \
+ #__VA_ARGS__, __VA_ARGS__)
+
#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
#define DOCTEST_WARN(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_WARN, __VA_ARGS__)
@@ -2108,51 +2402,83 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_ASSERT_IMPLEMENT_1(DT_REQUIRE_FALSE, __VA_ARGS__)
// clang-format off
-#define DOCTEST_WARN_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } while(false)
-#define DOCTEST_CHECK_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } while(false)
-#define DOCTEST_REQUIRE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } while(false)
-#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } while(false)
-#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } while(false)
-#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } while(false)
+#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_WARN_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_CHECK_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_ASSERT_IMPLEMENT_2(DT_REQUIRE_FALSE, cond); } DOCTEST_FUNC_SCOPE_END
// clang-format on
+#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
+#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
+#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
+#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
+#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
+#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
+#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
+#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
+#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
+#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
+#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
+#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
+#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
+#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
+#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
+#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
+
+#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
+#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
#define DOCTEST_ASSERT_THROWS_AS(expr, assert_type, message, ...) \
- do { \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
if(!doctest::getContextOptions()->no_throw) { \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, #expr, #__VA_ARGS__, message); \
try { \
DOCTEST_CAST_TO_VOID(expr) \
- } catch(const typename doctest::detail::remove_const< \
- typename doctest::detail::remove_reference<__VA_ARGS__>::type>::type&) { \
- _DOCTEST_RB.translateException(); \
- _DOCTEST_RB.m_threw_as = true; \
- } catch(...) { _DOCTEST_RB.translateException(); } \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } catch(const typename doctest::detail::types::remove_const< \
+ typename doctest::detail::types::remove_reference<__VA_ARGS__>::type>::type&) {\
+ DOCTEST_RB.translateException(); \
+ DOCTEST_RB.m_threw_as = true; \
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } else { /* NOLINT(*-else-after-return) */ \
+ DOCTEST_FUNC_SCOPE_RET(false); \
} \
- } while(false)
+ } DOCTEST_FUNC_SCOPE_END
#define DOCTEST_ASSERT_THROWS_WITH(expr, expr_str, assert_type, ...) \
- do { \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
if(!doctest::getContextOptions()->no_throw) { \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, expr_str, "", __VA_ARGS__); \
try { \
DOCTEST_CAST_TO_VOID(expr) \
- } catch(...) { _DOCTEST_RB.translateException(); } \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } else { /* NOLINT(*-else-after-return) */ \
+ DOCTEST_FUNC_SCOPE_RET(false); \
} \
- } while(false)
+ } DOCTEST_FUNC_SCOPE_END
#define DOCTEST_ASSERT_NOTHROW(assert_type, ...) \
- do { \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
+ DOCTEST_FUNC_SCOPE_BEGIN { \
+ doctest::detail::ResultBuilder DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
__LINE__, #__VA_ARGS__); \
try { \
DOCTEST_CAST_TO_VOID(__VA_ARGS__) \
- } catch(...) { _DOCTEST_RB.translateException(); } \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
- } while(false)
+ } catch(...) { DOCTEST_RB.translateException(); } \
+ DOCTEST_ASSERT_LOG_REACT_RETURN(DOCTEST_RB); \
+ } DOCTEST_FUNC_SCOPE_END
// clang-format off
#define DOCTEST_WARN_THROWS(...) DOCTEST_ASSERT_THROWS_WITH((__VA_ARGS__), #__VA_ARGS__, DT_WARN_THROWS, "")
@@ -2175,166 +2501,23 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_CHECK_NOTHROW, __VA_ARGS__)
#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_ASSERT_NOTHROW(DT_REQUIRE_NOTHROW, __VA_ARGS__)
-#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } while(false)
-#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } while(false)
-#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } while(false)
-#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } while(false)
-#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } while(false)
-#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } while(false)
-#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } while(false)
-#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } while(false)
-#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } while(false)
-#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } while(false)
-#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } while(false)
-#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } while(false)
-#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } while(false)
-#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } while(false)
-#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) do { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } while(false)
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_AS(expr, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH(expr, with); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_WARN_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_CHECK_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_SCOPE_BEGIN { DOCTEST_INFO(__VA_ARGS__); DOCTEST_REQUIRE_NOTHROW(expr); } DOCTEST_FUNC_SCOPE_END
// clang-format on
-#ifndef DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
-#define DOCTEST_BINARY_ASSERT(assert_type, comp, ...) \
- do { \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
- __LINE__, #__VA_ARGS__); \
- DOCTEST_WRAP_IN_TRY( \
- _DOCTEST_RB.binary_assert<doctest::detail::binaryAssertComparison::comp>( \
- __VA_ARGS__)) \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
- } while(false)
-
-#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
- do { \
- doctest::detail::ResultBuilder _DOCTEST_RB(doctest::assertType::assert_type, __FILE__, \
- __LINE__, #__VA_ARGS__); \
- DOCTEST_WRAP_IN_TRY(_DOCTEST_RB.unary_assert(__VA_ARGS__)) \
- DOCTEST_ASSERT_LOG_AND_REACT(_DOCTEST_RB); \
- } while(false)
-
-#else // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
-#define DOCTEST_BINARY_ASSERT(assert_type, comparison, ...) \
- doctest::detail::binary_assert<doctest::detail::binaryAssertComparison::comparison>( \
- doctest::assertType::assert_type, __FILE__, __LINE__, #__VA_ARGS__, __VA_ARGS__)
-
-#define DOCTEST_UNARY_ASSERT(assert_type, ...) \
- doctest::detail::unary_assert(doctest::assertType::assert_type, __FILE__, __LINE__, \
- #__VA_ARGS__, __VA_ARGS__)
-
-#endif // DOCTEST_CONFIG_SUPER_FAST_ASSERTS
-
-#define DOCTEST_WARN_EQ(...) DOCTEST_BINARY_ASSERT(DT_WARN_EQ, eq, __VA_ARGS__)
-#define DOCTEST_CHECK_EQ(...) DOCTEST_BINARY_ASSERT(DT_CHECK_EQ, eq, __VA_ARGS__)
-#define DOCTEST_REQUIRE_EQ(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_EQ, eq, __VA_ARGS__)
-#define DOCTEST_WARN_NE(...) DOCTEST_BINARY_ASSERT(DT_WARN_NE, ne, __VA_ARGS__)
-#define DOCTEST_CHECK_NE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_NE, ne, __VA_ARGS__)
-#define DOCTEST_REQUIRE_NE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_NE, ne, __VA_ARGS__)
-#define DOCTEST_WARN_GT(...) DOCTEST_BINARY_ASSERT(DT_WARN_GT, gt, __VA_ARGS__)
-#define DOCTEST_CHECK_GT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GT, gt, __VA_ARGS__)
-#define DOCTEST_REQUIRE_GT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GT, gt, __VA_ARGS__)
-#define DOCTEST_WARN_LT(...) DOCTEST_BINARY_ASSERT(DT_WARN_LT, lt, __VA_ARGS__)
-#define DOCTEST_CHECK_LT(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LT, lt, __VA_ARGS__)
-#define DOCTEST_REQUIRE_LT(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LT, lt, __VA_ARGS__)
-#define DOCTEST_WARN_GE(...) DOCTEST_BINARY_ASSERT(DT_WARN_GE, ge, __VA_ARGS__)
-#define DOCTEST_CHECK_GE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_GE, ge, __VA_ARGS__)
-#define DOCTEST_REQUIRE_GE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_GE, ge, __VA_ARGS__)
-#define DOCTEST_WARN_LE(...) DOCTEST_BINARY_ASSERT(DT_WARN_LE, le, __VA_ARGS__)
-#define DOCTEST_CHECK_LE(...) DOCTEST_BINARY_ASSERT(DT_CHECK_LE, le, __VA_ARGS__)
-#define DOCTEST_REQUIRE_LE(...) DOCTEST_BINARY_ASSERT(DT_REQUIRE_LE, le, __VA_ARGS__)
-
-#define DOCTEST_WARN_UNARY(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY, __VA_ARGS__)
-#define DOCTEST_CHECK_UNARY(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY, __VA_ARGS__)
-#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY, __VA_ARGS__)
-#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_WARN_UNARY_FALSE, __VA_ARGS__)
-#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_CHECK_UNARY_FALSE, __VA_ARGS__)
-#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_UNARY_ASSERT(DT_REQUIRE_UNARY_FALSE, __VA_ARGS__)
-
-#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
-
-#undef DOCTEST_WARN_THROWS
-#undef DOCTEST_CHECK_THROWS
-#undef DOCTEST_REQUIRE_THROWS
-#undef DOCTEST_WARN_THROWS_AS
-#undef DOCTEST_CHECK_THROWS_AS
-#undef DOCTEST_REQUIRE_THROWS_AS
-#undef DOCTEST_WARN_THROWS_WITH
-#undef DOCTEST_CHECK_THROWS_WITH
-#undef DOCTEST_REQUIRE_THROWS_WITH
-#undef DOCTEST_WARN_THROWS_WITH_AS
-#undef DOCTEST_CHECK_THROWS_WITH_AS
-#undef DOCTEST_REQUIRE_THROWS_WITH_AS
-#undef DOCTEST_WARN_NOTHROW
-#undef DOCTEST_CHECK_NOTHROW
-#undef DOCTEST_REQUIRE_NOTHROW
-
-#undef DOCTEST_WARN_THROWS_MESSAGE
-#undef DOCTEST_CHECK_THROWS_MESSAGE
-#undef DOCTEST_REQUIRE_THROWS_MESSAGE
-#undef DOCTEST_WARN_THROWS_AS_MESSAGE
-#undef DOCTEST_CHECK_THROWS_AS_MESSAGE
-#undef DOCTEST_REQUIRE_THROWS_AS_MESSAGE
-#undef DOCTEST_WARN_THROWS_WITH_MESSAGE
-#undef DOCTEST_CHECK_THROWS_WITH_MESSAGE
-#undef DOCTEST_REQUIRE_THROWS_WITH_MESSAGE
-#undef DOCTEST_WARN_THROWS_WITH_AS_MESSAGE
-#undef DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE
-#undef DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE
-#undef DOCTEST_WARN_NOTHROW_MESSAGE
-#undef DOCTEST_CHECK_NOTHROW_MESSAGE
-#undef DOCTEST_REQUIRE_NOTHROW_MESSAGE
-
-#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
-
-#define DOCTEST_WARN_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_NOTHROW(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-
-#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
-
-#undef DOCTEST_REQUIRE
-#undef DOCTEST_REQUIRE_FALSE
-#undef DOCTEST_REQUIRE_MESSAGE
-#undef DOCTEST_REQUIRE_FALSE_MESSAGE
-#undef DOCTEST_REQUIRE_EQ
-#undef DOCTEST_REQUIRE_NE
-#undef DOCTEST_REQUIRE_GT
-#undef DOCTEST_REQUIRE_LT
-#undef DOCTEST_REQUIRE_GE
-#undef DOCTEST_REQUIRE_LE
-#undef DOCTEST_REQUIRE_UNARY
-#undef DOCTEST_REQUIRE_UNARY_FALSE
-
-#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
-
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
// =================================================================================================
@@ -2344,7 +2527,7 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#else // DOCTEST_CONFIG_DISABLE
#define DOCTEST_IMPLEMENT_FIXTURE(der, base, func, name) \
- namespace { \
+ namespace /* NOLINT */ { \
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
struct der : public base \
{ void f(); }; \
@@ -2358,51 +2541,48 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// for registering tests
#define DOCTEST_TEST_CASE(name) \
- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
// for registering tests in classes
#define DOCTEST_TEST_CASE_CLASS(name) \
- DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+ DOCTEST_CREATE_AND_REGISTER_FUNCTION(DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
// for registering tests with a fixture
#define DOCTEST_TEST_CASE_FIXTURE(x, name) \
- DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(_DOCTEST_ANON_CLASS_), x, \
- DOCTEST_ANONYMOUS(_DOCTEST_ANON_FUNC_), name)
+ DOCTEST_IMPLEMENT_FIXTURE(DOCTEST_ANONYMOUS(DOCTEST_ANON_CLASS_), x, \
+ DOCTEST_ANONYMOUS(DOCTEST_ANON_FUNC_), name)
// for converting types to strings without the <typeinfo> header and demangling
-#define DOCTEST_TYPE_TO_STRING(...) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
-#define DOCTEST_TYPE_TO_STRING_IMPL(...)
+#define DOCTEST_TYPE_TO_STRING_AS(str, ...) static_assert(true, "")
+#define DOCTEST_TYPE_TO_STRING(...) static_assert(true, "")
// for typed tests
#define DOCTEST_TEST_CASE_TEMPLATE(name, type, ...) \
template <typename type> \
- inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
#define DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, type, id) \
template <typename type> \
- inline void DOCTEST_ANONYMOUS(_DOCTEST_ANON_TMP_)()
-
-#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+ inline void DOCTEST_ANONYMOUS(DOCTEST_ANON_TMP_)()
-#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) \
- typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#define DOCTEST_TEST_CASE_TEMPLATE_INVOKE(id, ...) static_assert(true, "")
+#define DOCTEST_TEST_CASE_TEMPLATE_APPLY(id, ...) static_assert(true, "")
// for subcases
#define DOCTEST_SUBCASE(name)
// for a testsuite block
-#define DOCTEST_TEST_SUITE(name) namespace
+#define DOCTEST_TEST_SUITE(name) namespace // NOLINT
// for starting a testsuite block
-#define DOCTEST_TEST_SUITE_BEGIN(name) typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#define DOCTEST_TEST_SUITE_BEGIN(name) static_assert(true, "")
// for ending a testsuite block
-#define DOCTEST_TEST_SUITE_END typedef int DOCTEST_ANONYMOUS(_DOCTEST_ANON_FOR_SEMICOLON_)
+#define DOCTEST_TEST_SUITE_END using DOCTEST_ANONYMOUS(DOCTEST_ANON_FOR_SEMICOLON_) = int
#define DOCTEST_REGISTER_EXCEPTION_TRANSLATOR(signature) \
template <typename DOCTEST_UNUSED_TEMPLATE_TYPE> \
- static inline doctest::String DOCTEST_ANONYMOUS(_DOCTEST_ANON_TRANSLATOR_)(signature)
+ static inline doctest::String DOCTEST_ANONYMOUS(DOCTEST_ANON_TRANSLATOR_)(signature)
#define DOCTEST_REGISTER_REPORTER(name, priority, reporter)
#define DOCTEST_REGISTER_LISTENER(name, priority, reporter)
@@ -2416,80 +2596,253 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#define DOCTEST_FAIL_CHECK(...) (static_cast<void>(0))
#define DOCTEST_FAIL(...) (static_cast<void>(0))
-#define DOCTEST_WARN(...) (static_cast<void>(0))
-#define DOCTEST_CHECK(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE(...) (static_cast<void>(0))
-#define DOCTEST_WARN_FALSE(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_FALSE(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_FALSE(...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_MESSAGE(cond, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_MESSAGE(cond, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_MESSAGE(cond, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS(...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_NOTHROW(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_NOTHROW(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_NOTHROW(...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) (static_cast<void>(0))
-#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_EQ(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_EQ(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_EQ(...) (static_cast<void>(0))
-#define DOCTEST_WARN_NE(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_NE(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_NE(...) (static_cast<void>(0))
-#define DOCTEST_WARN_GT(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_GT(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_GT(...) (static_cast<void>(0))
-#define DOCTEST_WARN_LT(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_LT(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_LT(...) (static_cast<void>(0))
-#define DOCTEST_WARN_GE(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_GE(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_GE(...) (static_cast<void>(0))
-#define DOCTEST_WARN_LE(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_LE(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_LE(...) (static_cast<void>(0))
-
-#define DOCTEST_WARN_UNARY(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_UNARY(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_UNARY(...) (static_cast<void>(0))
-#define DOCTEST_WARN_UNARY_FALSE(...) (static_cast<void>(0))
-#define DOCTEST_CHECK_UNARY_FALSE(...) (static_cast<void>(0))
-#define DOCTEST_REQUIRE_UNARY_FALSE(...) (static_cast<void>(0))
+#if defined(DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED) \
+ && defined(DOCTEST_CONFIG_ASSERTS_RETURN_VALUES)
+
+#define DOCTEST_WARN(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_CHECK(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_REQUIRE(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_WARN_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_CHECK_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_FALSE(...) [&] { return !(__VA_ARGS__); }()
+
+#define DOCTEST_WARN_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_CHECK_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) [&] { return cond; }()
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) [&] { return !(cond); }()
+
+namespace doctest {
+namespace detail {
+#define DOCTEST_RELATIONAL_OP(name, op) \
+ template <typename L, typename R> \
+ bool name(const DOCTEST_REF_WRAP(L) lhs, const DOCTEST_REF_WRAP(R) rhs) { return lhs op rhs; }
+
+ DOCTEST_RELATIONAL_OP(eq, ==)
+ DOCTEST_RELATIONAL_OP(ne, !=)
+ DOCTEST_RELATIONAL_OP(lt, <)
+ DOCTEST_RELATIONAL_OP(gt, >)
+ DOCTEST_RELATIONAL_OP(le, <=)
+ DOCTEST_RELATIONAL_OP(ge, >=)
+} // namespace detail
+} // namespace doctest
+
+#define DOCTEST_WARN_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_CHECK_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_EQ(...) [&] { return doctest::detail::eq(__VA_ARGS__); }()
+#define DOCTEST_WARN_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_CHECK_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_NE(...) [&] { return doctest::detail::ne(__VA_ARGS__); }()
+#define DOCTEST_WARN_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_CHECK_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_LT(...) [&] { return doctest::detail::lt(__VA_ARGS__); }()
+#define DOCTEST_WARN_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_CHECK_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_GT(...) [&] { return doctest::detail::gt(__VA_ARGS__); }()
+#define DOCTEST_WARN_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_CHECK_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_LE(...) [&] { return doctest::detail::le(__VA_ARGS__); }()
+#define DOCTEST_WARN_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_CHECK_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_GE(...) [&] { return doctest::detail::ge(__VA_ARGS__); }()
+#define DOCTEST_WARN_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_CHECK_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_REQUIRE_UNARY(...) [&] { return __VA_ARGS__; }()
+#define DOCTEST_WARN_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_CHECK_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) [&] { return !(__VA_ARGS__); }()
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#define DOCTEST_WARN_THROWS_WITH(expr, with, ...) [] { static_assert(false, "Exception translation is not available when doctest is disabled."); return false; }()
+#define DOCTEST_CHECK_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_WARN_THROWS_WITH(,,)
+
+#define DOCTEST_WARN_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_CHECK_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_REQUIRE_THROWS(...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_WARN_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_WARN_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_CHECK_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_REQUIRE_NOTHROW(...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return false; } catch (...) { return true; } }()
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) [&] { try { expr; } catch (__VA_ARGS__) { return true; } catch (...) { } return false; }()
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) [&] { try { __VA_ARGS__; return true; } catch (...) { return false; } }()
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#else // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
+
+#define DOCTEST_WARN(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_FALSE(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_FALSE_MESSAGE(cond, ...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_EQ(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_GT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_LT(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_GE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_LE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_LE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_LE(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_UNARY(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_UNARY_FALSE(...) DOCTEST_FUNC_EMPTY
+
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#define DOCTEST_WARN_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_FUNC_EMPTY
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_FUNC_EMPTY
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#endif // DOCTEST_CONFIG_EVALUATE_ASSERTS_EVEN_WHEN_DISABLED
#endif // DOCTEST_CONFIG_DISABLE
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS
+
+#ifdef DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#define DOCTEST_EXCEPTION_EMPTY_FUNC DOCTEST_FUNC_EMPTY
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+#define DOCTEST_EXCEPTION_EMPTY_FUNC [] { static_assert(false, "Exceptions are disabled! " \
+ "Use DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS if you want to compile with exceptions disabled."); return false; }()
+
+#undef DOCTEST_REQUIRE
+#undef DOCTEST_REQUIRE_FALSE
+#undef DOCTEST_REQUIRE_MESSAGE
+#undef DOCTEST_REQUIRE_FALSE_MESSAGE
+#undef DOCTEST_REQUIRE_EQ
+#undef DOCTEST_REQUIRE_NE
+#undef DOCTEST_REQUIRE_GT
+#undef DOCTEST_REQUIRE_LT
+#undef DOCTEST_REQUIRE_GE
+#undef DOCTEST_REQUIRE_LE
+#undef DOCTEST_REQUIRE_UNARY
+#undef DOCTEST_REQUIRE_UNARY_FALSE
+
+#define DOCTEST_REQUIRE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_FALSE_MESSAGE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_EQ DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_GT DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_LT DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_GE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_LE DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_UNARY DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_UNARY_FALSE DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS
+
+#define DOCTEST_WARN_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_AS(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_AS(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NOTHROW(...) DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#define DOCTEST_WARN_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_AS_MESSAGE(expr, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_MESSAGE(expr, with, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_THROWS_WITH_AS_MESSAGE(expr, with, ex, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_WARN_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_CHECK_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+#define DOCTEST_REQUIRE_NOTHROW_MESSAGE(expr, ...) DOCTEST_EXCEPTION_EMPTY_FUNC
+
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+
// clang-format off
// KEPT FOR BACKWARDS COMPATIBILITY - FORWARDING TO THE RIGHT MACROS
#define DOCTEST_FAST_WARN_EQ DOCTEST_WARN_EQ
@@ -2536,11 +2889,12 @@ int registerReporter(const char* name, int priority, bool isReporter) {
// clang-format on
// == SHORT VERSIONS OF THE MACROS
-#if !defined(DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES)
+#ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
#define TEST_CASE(name) DOCTEST_TEST_CASE(name)
#define TEST_CASE_CLASS(name) DOCTEST_TEST_CASE_CLASS(name)
#define TEST_CASE_FIXTURE(x, name) DOCTEST_TEST_CASE_FIXTURE(x, name)
+#define TYPE_TO_STRING_AS(str, ...) DOCTEST_TYPE_TO_STRING_AS(str, __VA_ARGS__)
#define TYPE_TO_STRING(...) DOCTEST_TYPE_TO_STRING(__VA_ARGS__)
#define TEST_CASE_TEMPLATE(name, T, ...) DOCTEST_TEST_CASE_TEMPLATE(name, T, __VA_ARGS__)
#define TEST_CASE_TEMPLATE_DEFINE(name, T, id) DOCTEST_TEST_CASE_TEMPLATE_DEFINE(name, T, id)
@@ -2673,39 +3027,19 @@ int registerReporter(const char* name, int priority, bool isReporter) {
#endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
-#if !defined(DOCTEST_CONFIG_DISABLE)
+#ifndef DOCTEST_CONFIG_DISABLE
// this is here to clear the 'current test suite' for the current translation unit - at the top
DOCTEST_TEST_SUITE_END();
-// add stringification for primitive/fundamental types
-namespace doctest { namespace detail {
- DOCTEST_TYPE_TO_STRING_IMPL(bool)
- DOCTEST_TYPE_TO_STRING_IMPL(float)
- DOCTEST_TYPE_TO_STRING_IMPL(double)
- DOCTEST_TYPE_TO_STRING_IMPL(long double)
- DOCTEST_TYPE_TO_STRING_IMPL(char)
- DOCTEST_TYPE_TO_STRING_IMPL(signed char)
- DOCTEST_TYPE_TO_STRING_IMPL(unsigned char)
-#if !DOCTEST_MSVC || defined(_NATIVE_WCHAR_T_DEFINED)
- DOCTEST_TYPE_TO_STRING_IMPL(wchar_t)
-#endif // not MSVC or wchar_t support enabled
- DOCTEST_TYPE_TO_STRING_IMPL(short int)
- DOCTEST_TYPE_TO_STRING_IMPL(unsigned short int)
- DOCTEST_TYPE_TO_STRING_IMPL(int)
- DOCTEST_TYPE_TO_STRING_IMPL(unsigned int)
- DOCTEST_TYPE_TO_STRING_IMPL(long int)
- DOCTEST_TYPE_TO_STRING_IMPL(unsigned long int)
- DOCTEST_TYPE_TO_STRING_IMPL(long long int)
- DOCTEST_TYPE_TO_STRING_IMPL(unsigned long long int)
-}} // namespace doctest::detail
-
#endif // DOCTEST_CONFIG_DISABLE
DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP
DOCTEST_GCC_SUPPRESS_WARNING_POP
+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
+
#endif // DOCTEST_LIBRARY_INCLUDED
#ifndef DOCTEST_SINGLE_HEADER
@@ -2725,13 +3059,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wunused-macros")
DOCTEST_CLANG_SUPPRESS_WARNING_POP
+DOCTEST_SUPPRESS_COMMON_WARNINGS_PUSH
+
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wunknown-pragmas")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wpadded")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wweak-vtables")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wglobal-constructors")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wexit-time-destructors")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-prototypes")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wsign-conversion")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wshorten-64-to-32")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-variable-declarations")
@@ -2739,65 +3071,35 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wswitch-enum")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wcovered-switch-default")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-noreturn")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-local-typedef")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wdisabled-macro-expansion")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-braces")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wmissing-field-initializers")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat")
-DOCTEST_CLANG_SUPPRESS_WARNING("-Wc++98-compat-pedantic")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
DOCTEST_CLANG_SUPPRESS_WARNING("-Wnonportable-system-include-path")
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
-DOCTEST_GCC_SUPPRESS_WARNING("-Wunknown-pragmas")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wpragmas")
DOCTEST_GCC_SUPPRESS_WARNING("-Wconversion")
-DOCTEST_GCC_SUPPRESS_WARNING("-Weffc++")
DOCTEST_GCC_SUPPRESS_WARNING("-Wsign-conversion")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-overflow")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wstrict-aliasing")
DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-field-initializers")
DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-braces")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wmissing-declarations")
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch")
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-enum")
DOCTEST_GCC_SUPPRESS_WARNING("-Wswitch-default")
DOCTEST_GCC_SUPPRESS_WARNING("-Wunsafe-loop-optimizations")
DOCTEST_GCC_SUPPRESS_WARNING("-Wold-style-cast")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-local-typedefs")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wuseless-cast")
DOCTEST_GCC_SUPPRESS_WARNING("-Wunused-function")
DOCTEST_GCC_SUPPRESS_WARNING("-Wmultiple-inheritance")
-DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
DOCTEST_GCC_SUPPRESS_WARNING("-Wsuggest-attribute")
DOCTEST_MSVC_SUPPRESS_WARNING_PUSH
-DOCTEST_MSVC_SUPPRESS_WARNING(4616) // invalid compiler warning
-DOCTEST_MSVC_SUPPRESS_WARNING(4619) // invalid compiler warning
-DOCTEST_MSVC_SUPPRESS_WARNING(4996) // The compiler encountered a deprecated declaration
DOCTEST_MSVC_SUPPRESS_WARNING(4267) // 'var' : conversion from 'x' to 'y', possible loss of data
-DOCTEST_MSVC_SUPPRESS_WARNING(4706) // assignment within conditional expression
-DOCTEST_MSVC_SUPPRESS_WARNING(4512) // 'class' : assignment operator could not be generated
-DOCTEST_MSVC_SUPPRESS_WARNING(4127) // conditional expression is constant
DOCTEST_MSVC_SUPPRESS_WARNING(4530) // C++ exception handler used, but unwind semantics not enabled
DOCTEST_MSVC_SUPPRESS_WARNING(4577) // 'noexcept' used with no exception handling mode specified
DOCTEST_MSVC_SUPPRESS_WARNING(4774) // format string expected in argument is not a string literal
DOCTEST_MSVC_SUPPRESS_WARNING(4365) // conversion from 'int' to 'unsigned', signed/unsigned mismatch
-DOCTEST_MSVC_SUPPRESS_WARNING(4820) // padding in structs
-DOCTEST_MSVC_SUPPRESS_WARNING(4640) // construction of local static object is not thread-safe
DOCTEST_MSVC_SUPPRESS_WARNING(5039) // pointer to potentially throwing function passed to extern C
-DOCTEST_MSVC_SUPPRESS_WARNING(5045) // Spectre mitigation stuff
-DOCTEST_MSVC_SUPPRESS_WARNING(4626) // assignment operator was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(5027) // move assignment operator was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(5026) // move constructor was implicitly defined as deleted
-DOCTEST_MSVC_SUPPRESS_WARNING(4625) // copy constructor was implicitly defined as deleted
DOCTEST_MSVC_SUPPRESS_WARNING(4800) // forcing value to bool 'true' or 'false' (performance warning)
-// static analysis
-DOCTEST_MSVC_SUPPRESS_WARNING(26439) // This kind of function may not throw. Declare it 'noexcept'
-DOCTEST_MSVC_SUPPRESS_WARNING(26495) // Always initialize a member variable
-DOCTEST_MSVC_SUPPRESS_WARNING(26451) // Arithmetic overflow ...
-DOCTEST_MSVC_SUPPRESS_WARNING(26444) // Avoid unnamed objects with custom construction and dtor...
-DOCTEST_MSVC_SUPPRESS_WARNING(26812) // Prefer 'enum class' over 'enum'
+DOCTEST_MSVC_SUPPRESS_WARNING(5245) // unreferenced function with internal linkage has been removed
DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
@@ -2805,7 +3107,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <ctime>
#include <cmath>
#include <climits>
-// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/onqtam/doctest/pull/37
+// borland (Embarcadero) compiler requires math.h and not cmath - https://github.com/doctest/doctest/pull/37
#ifdef __BORLANDC__
#include <math.h>
#endif // __BORLANDC__
@@ -2821,16 +3123,27 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#include <algorithm>
#include <iomanip>
#include <vector>
+#ifndef DOCTEST_CONFIG_NO_MULTITHREADING
#include <atomic>
#include <mutex>
+#define DOCTEST_DECLARE_MUTEX(name) std::mutex name;
+#define DOCTEST_DECLARE_STATIC_MUTEX(name) static DOCTEST_DECLARE_MUTEX(name)
+#define DOCTEST_LOCK_MUTEX(name) std::lock_guard<std::mutex> DOCTEST_ANONYMOUS(DOCTEST_ANON_LOCK_)(name);
+#else // DOCTEST_CONFIG_NO_MULTITHREADING
+#define DOCTEST_DECLARE_MUTEX(name)
+#define DOCTEST_DECLARE_STATIC_MUTEX(name)
+#define DOCTEST_LOCK_MUTEX(name)
+#endif // DOCTEST_CONFIG_NO_MULTITHREADING
#include <set>
#include <map>
+#include <unordered_set>
#include <exception>
#include <stdexcept>
#include <csignal>
#include <cfloat>
#include <cctype>
#include <cstdint>
+#include <string>
#ifdef DOCTEST_PLATFORM_MAC
#include <sys/types.h>
@@ -2863,7 +3176,7 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_BEGIN
#endif // DOCTEST_PLATFORM_WINDOWS
-// this is a fix for https://github.com/onqtam/doctest/issues/348
+// this is a fix for https://github.com/doctest/doctest/issues/348
// https://mail.gnome.org/archives/xml/2012-January/msg00000.html
#if !defined(HAVE_UNISTD_H) && !defined(STDOUT_FILENO)
#define STDOUT_FILENO fileno(stdout)
@@ -2885,8 +3198,12 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#endif
#ifndef DOCTEST_THREAD_LOCAL
+#if defined(DOCTEST_CONFIG_NO_MULTITHREADING) || DOCTEST_MSVC && (DOCTEST_MSVC < DOCTEST_COMPILER(19, 0, 0))
+#define DOCTEST_THREAD_LOCAL
+#else // DOCTEST_MSVC
#define DOCTEST_THREAD_LOCAL thread_local
-#endif
+#endif // DOCTEST_MSVC
+#endif // DOCTEST_THREAD_LOCAL
#ifndef DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES
#define DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES 32
@@ -2906,12 +3223,34 @@ DOCTEST_MAKE_STD_HEADERS_CLEAN_FROM_WARNINGS_ON_WALL_END
#define DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
#endif
+#ifndef DOCTEST_CDECL
+#define DOCTEST_CDECL __cdecl
+#endif
+
namespace doctest {
bool is_running_in_test = false;
namespace {
using namespace detail;
+
+ template <typename Ex>
+ DOCTEST_NORETURN void throw_exception(Ex const& e) {
+#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
+ throw e;
+#else // DOCTEST_CONFIG_NO_EXCEPTIONS
+ std::cerr << "doctest will terminate because it needed to throw an exception.\n"
+ << "The message was: " << e.what() << '\n';
+ std::terminate();
+#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
+ }
+
+#ifndef DOCTEST_INTERNAL_ERROR
+#define DOCTEST_INTERNAL_ERROR(msg) \
+ throw_exception(std::logic_error( \
+ __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
+#endif // DOCTEST_INTERNAL_ERROR
+
// case insensitive strcmp
int stricmp(const char* a, const char* b) {
for(;; a++, b++) {
@@ -2921,20 +3260,6 @@ namespace {
}
}
- template <typename T>
- String fpToString(T value, int precision) {
- std::ostringstream oss;
- oss << std::setprecision(precision) << std::fixed << value;
- std::string d = oss.str();
- size_t i = d.find_last_not_of('0');
- if(i != std::string::npos && i != d.size() - 1) {
- if(d[i] == '.')
- i++;
- d = d.substr(0, i + 1);
- }
- return d.c_str();
- }
-
struct Endianness
{
enum Arch
@@ -2955,36 +3280,35 @@ namespace {
} // namespace
namespace detail {
- void my_memcpy(void* dest, const void* src, unsigned num) { memcpy(dest, src, num); }
-
- String rawMemoryToString(const void* object, unsigned size) {
- // Reverse order for little endian architectures
- int i = 0, end = static_cast<int>(size), inc = 1;
- if(Endianness::which() == Endianness::Little) {
- i = end - 1;
- end = inc = -1;
- }
-
- unsigned const char* bytes = static_cast<unsigned const char*>(object);
- std::ostringstream oss;
- oss << "0x" << std::setfill('0') << std::hex;
- for(; i != end; i += inc)
- oss << std::setw(2) << static_cast<unsigned>(bytes[i]);
- return oss.str().c_str();
- }
+ DOCTEST_THREAD_LOCAL class
+ {
+ std::vector<std::streampos> stack;
+ std::stringstream ss;
+
+ public:
+ std::ostream* push() {
+ stack.push_back(ss.tellp());
+ return &ss;
+ }
+
+ String pop() {
+ if (stack.empty())
+ DOCTEST_INTERNAL_ERROR("TLSS was empty when trying to pop!");
- DOCTEST_THREAD_LOCAL std::ostringstream g_oss; // NOLINT(cert-err58-cpp)
+ std::streampos pos = stack.back();
+ stack.pop_back();
+ unsigned sz = static_cast<unsigned>(ss.tellp() - pos);
+ ss.rdbuf()->pubseekpos(pos, std::ios::in | std::ios::out);
+ return String(ss, sz);
+ }
+ } g_oss;
- std::ostream* getTlsOss() {
- g_oss.clear(); // there shouldn't be anything worth clearing in the flags
- g_oss.str(""); // the slow way of resetting a string stream
- //g_oss.seekp(0); // optimal reset - as seen here: https://stackoverflow.com/a/624291/3162383
- return &g_oss;
+ std::ostream* tlssPush() {
+ return g_oss.push();
}
- String getTlsOssResult() {
- //g_oss << std::ends; // needed - as shown here: https://stackoverflow.com/a/624291/3162383
- return g_oss.str().c_str();
+ String tlssPop() {
+ return g_oss.pop();
}
#ifndef DOCTEST_CONFIG_DISABLE
@@ -2993,20 +3317,19 @@ namespace timer_large_integer
{
#if defined(DOCTEST_PLATFORM_WINDOWS)
- typedef ULONGLONG type;
+ using type = ULONGLONG;
#else // DOCTEST_PLATFORM_WINDOWS
- using namespace std;
- typedef uint64_t type;
+ using type = std::uint64_t;
#endif // DOCTEST_PLATFORM_WINDOWS
}
-typedef timer_large_integer::type ticks_t;
+using ticks_t = timer_large_integer::type;
#ifdef DOCTEST_CONFIG_GETCURRENTTICKS
ticks_t getCurrentTicks() { return DOCTEST_CONFIG_GETCURRENTTICKS(); }
#elif defined(DOCTEST_PLATFORM_WINDOWS)
ticks_t getCurrentTicks() {
- static LARGE_INTEGER hz = {0}, hzo = {0};
+ static LARGE_INTEGER hz = { {0} }, hzo = { {0} };
if(!hz.QuadPart) {
QueryPerformanceFrequency(&hz);
QueryPerformanceCounter(&hzo);
@@ -3038,9 +3361,17 @@ typedef timer_large_integer::type ticks_t;
ticks_t m_ticks = 0;
};
-#ifdef DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
+#ifdef DOCTEST_CONFIG_NO_MULTITHREADING
template <typename T>
- using AtomicOrMultiLaneAtomic = std::atomic<T>;
+ using Atomic = T;
+#else // DOCTEST_CONFIG_NO_MULTITHREADING
+ template <typename T>
+ using Atomic = std::atomic<T>;
+#endif // DOCTEST_CONFIG_NO_MULTITHREADING
+
+#if defined(DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS) || defined(DOCTEST_CONFIG_NO_MULTITHREADING)
+ template <typename T>
+ using MultiLaneAtomic = Atomic<T>;
#else // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
// Provides a multilane implementation of an atomic variable that supports add, sub, load,
// store. Instead of using a single atomic variable, this splits up into multiple ones,
@@ -3057,8 +3388,8 @@ typedef timer_large_integer::type ticks_t;
{
struct CacheLineAlignedAtomic
{
- std::atomic<T> atomic{};
- char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(std::atomic<T>)];
+ Atomic<T> atomic{};
+ char padding[DOCTEST_MULTI_LANE_ATOMICS_CACHE_LINE_SIZE - sizeof(Atomic<T>)];
};
CacheLineAlignedAtomic m_atomics[DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES];
@@ -3088,7 +3419,7 @@ typedef timer_large_integer::type ticks_t;
return result;
}
- T operator=(T desired) DOCTEST_NOEXCEPT {
+ T operator=(T desired) DOCTEST_NOEXCEPT { // lgtm [cpp/assignment-does-not-return-this]
store(desired);
return desired;
}
@@ -3103,7 +3434,7 @@ typedef timer_large_integer::type ticks_t;
private:
// Each thread has a different atomic that it operates on. If more than NumLanes threads
- // use this, some will use the same atomic. So performance will degrate a bit, but still
+ // use this, some will use the same atomic. So performance will degrade a bit, but still
// everything will work.
//
// The logic here is a bit tricky. The call should be as fast as possible, so that there
@@ -3114,24 +3445,21 @@ typedef timer_large_integer::type ticks_t;
// assigned in a round-robin fashion.
// 3. This tlsLaneIdx is stored in the thread local data, so it is directly available with
// little overhead.
- std::atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
- static std::atomic<size_t> laneCounter;
+ Atomic<T>& myAtomic() DOCTEST_NOEXCEPT {
+ static Atomic<size_t> laneCounter;
DOCTEST_THREAD_LOCAL size_t tlsLaneIdx =
laneCounter++ % DOCTEST_MULTI_LANE_ATOMICS_THREAD_LANES;
return m_atomics[tlsLaneIdx].atomic;
}
};
-
- template <typename T>
- using AtomicOrMultiLaneAtomic = MultiLaneAtomic<T>;
#endif // DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS
// this holds both parameters from the command line and runtime data for tests
struct ContextState : ContextOptions, TestRunStats, CurrentTestCaseStats
{
- AtomicOrMultiLaneAtomic<int> numAssertsCurrentTest_atomic;
- AtomicOrMultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
+ MultiLaneAtomic<int> numAssertsCurrentTest_atomic;
+ MultiLaneAtomic<int> numAssertsFailedCurrentTest_atomic;
std::vector<std::vector<String>> filters = decltype(filters)(9); // 9 different filters
@@ -3144,11 +3472,12 @@ typedef timer_large_integer::type ticks_t;
std::vector<String> stringifiedContexts; // logging from INFO() due to an exception
// stuff for subcases
- std::vector<SubcaseSignature> subcasesStack;
- std::set<decltype(subcasesStack)> subcasesPassed;
- int subcasesCurrentMaxLevel;
- bool should_reenter;
- std::atomic<bool> shouldLogCurrentException;
+ bool reachedLeaf;
+ std::vector<SubcaseSignature> subcaseStack;
+ std::vector<SubcaseSignature> nextSubcaseStack;
+ std::unordered_set<unsigned long long> fullyTraversedSubcases;
+ size_t currentSubcaseDepth;
+ Atomic<bool> shouldLogCurrentException;
void resetRunData() {
numTestCases = 0;
@@ -3198,7 +3527,8 @@ typedef timer_large_integer::type ticks_t;
(TestCaseFailureReason::FailedExactlyNumTimes & failure_flags);
// if any subcase has failed - the whole test case has failed
- if(failure_flags && !ok_to_fail)
+ testCaseSuccess = !(failure_flags && !ok_to_fail);
+ if(!testCaseSuccess)
numTestCasesFailed++;
}
};
@@ -3213,23 +3543,37 @@ typedef timer_large_integer::type ticks_t;
#endif // DOCTEST_CONFIG_DISABLE
} // namespace detail
-void String::setOnHeap() { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
-void String::setLast(unsigned in) { buf[last] = char(in); }
+char* String::allocate(size_type sz) {
+ if (sz <= last) {
+ buf[sz] = '\0';
+ setLast(last - sz);
+ return buf;
+ } else {
+ setOnHeap();
+ data.size = sz;
+ data.capacity = data.size + 1;
+ data.ptr = new char[data.capacity];
+ data.ptr[sz] = '\0';
+ return data.ptr;
+ }
+}
+
+void String::setOnHeap() noexcept { *reinterpret_cast<unsigned char*>(&buf[last]) = 128; }
+void String::setLast(size_type in) noexcept { buf[last] = char(in); }
+void String::setSize(size_type sz) noexcept {
+ if (isOnStack()) { buf[sz] = '\0'; setLast(last - sz); }
+ else { data.ptr[sz] = '\0'; data.size = sz; }
+}
void String::copy(const String& other) {
- using namespace std;
if(other.isOnStack()) {
memcpy(buf, other.buf, len);
} else {
- setOnHeap();
- data.size = other.data.size;
- data.capacity = data.size + 1;
- data.ptr = new char[data.capacity];
- memcpy(data.ptr, other.data.ptr, data.size + 1);
+ memcpy(allocate(other.data.size), other.data.ptr, other.data.size);
}
}
-String::String() {
+String::String() noexcept {
buf[0] = '\0';
setLast();
}
@@ -3237,26 +3581,17 @@ String::String() {
String::~String() {
if(!isOnStack())
delete[] data.ptr;
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-}
+} // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
String::String(const char* in)
: String(in, strlen(in)) {}
-String::String(const char* in, unsigned in_size) {
- using namespace std;
- if(in_size <= last) {
- memcpy(buf, in, in_size);
- buf[in_size] = '\0';
- setLast(last - in_size);
- } else {
- setOnHeap();
- data.size = in_size;
- data.capacity = data.size + 1;
- data.ptr = new char[data.capacity];
- memcpy(data.ptr, in, in_size);
- data.ptr[in_size] = '\0';
- }
+String::String(const char* in, size_type in_size) {
+ memcpy(allocate(in_size), in, in_size);
+}
+
+String::String(std::istream& in, size_type in_size) {
+ in.read(allocate(in_size), in_size);
}
String::String(const String& other) { copy(other); }
@@ -3273,10 +3608,9 @@ String& String::operator=(const String& other) {
}
String& String::operator+=(const String& other) {
- const unsigned my_old_size = size();
- const unsigned other_size = other.size();
- const unsigned total_size = my_old_size + other_size;
- using namespace std;
+ const size_type my_old_size = size();
+ const size_type other_size = other.size();
+ const size_type total_size = my_old_size + other_size;
if(isOnStack()) {
if(total_size < len) {
// append to the current stack space
@@ -3323,18 +3657,13 @@ String& String::operator+=(const String& other) {
return *this;
}
-// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-String String::operator+(const String& other) const { return String(*this) += other; }
-
-String::String(String&& other) {
- using namespace std;
+String::String(String&& other) noexcept {
memcpy(buf, other.buf, len);
other.buf[0] = '\0';
other.setLast();
}
-String& String::operator=(String&& other) {
- using namespace std;
+String& String::operator=(String&& other) noexcept {
if(this != &other) {
if(!isOnStack())
delete[] data.ptr;
@@ -3345,30 +3674,60 @@ String& String::operator=(String&& other) {
return *this;
}
-char String::operator[](unsigned i) const {
- return const_cast<String*>(this)->operator[](i); // NOLINT
+char String::operator[](size_type i) const {
+ return const_cast<String*>(this)->operator[](i);
}
-char& String::operator[](unsigned i) {
+char& String::operator[](size_type i) {
if(isOnStack())
return reinterpret_cast<char*>(buf)[i];
return data.ptr[i];
}
DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wmaybe-uninitialized")
-unsigned String::size() const {
+String::size_type String::size() const {
if(isOnStack())
- return last - (unsigned(buf[last]) & 31); // using "last" would work only if "len" is 32
+ return last - (size_type(buf[last]) & 31); // using "last" would work only if "len" is 32
return data.size;
}
DOCTEST_GCC_SUPPRESS_WARNING_POP
-unsigned String::capacity() const {
+String::size_type String::capacity() const {
if(isOnStack())
return len;
return data.capacity;
}
+String String::substr(size_type pos, size_type cnt) && {
+ cnt = std::min(cnt, size() - 1 - pos);
+ char* cptr = c_str();
+ memmove(cptr, cptr + pos, cnt);
+ setSize(cnt);
+ return std::move(*this);
+}
+
+String String::substr(size_type pos, size_type cnt) const & {
+ cnt = std::min(cnt, size() - 1 - pos);
+ return String{ c_str() + pos, cnt };
+}
+
+String::size_type String::find(char ch, size_type pos) const {
+ const char* begin = c_str();
+ const char* end = begin + size();
+ const char* it = begin + pos;
+ for (; it < end && *it != ch; it++);
+ if (it < end) { return static_cast<size_type>(it - begin); }
+ else { return npos; }
+}
+
+String::size_type String::rfind(char ch, size_type pos) const {
+ const char* begin = c_str();
+ const char* it = begin + std::min(pos, size() - 1);
+ for (; it >= begin && *it != ch; it--);
+ if (it >= begin) { return static_cast<size_type>(it - begin); }
+ else { return npos; }
+}
+
int String::compare(const char* other, bool no_case) const {
if(no_case)
return doctest::stricmp(c_str(), other);
@@ -3379,17 +3738,32 @@ int String::compare(const String& other, bool no_case) const {
return compare(other.c_str(), no_case);
}
-// clang-format off
+String operator+(const String& lhs, const String& rhs) { return String(lhs) += rhs; }
+
bool operator==(const String& lhs, const String& rhs) { return lhs.compare(rhs) == 0; }
bool operator!=(const String& lhs, const String& rhs) { return lhs.compare(rhs) != 0; }
bool operator< (const String& lhs, const String& rhs) { return lhs.compare(rhs) < 0; }
bool operator> (const String& lhs, const String& rhs) { return lhs.compare(rhs) > 0; }
bool operator<=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) < 0 : true; }
bool operator>=(const String& lhs, const String& rhs) { return (lhs != rhs) ? lhs.compare(rhs) > 0 : true; }
-// clang-format on
std::ostream& operator<<(std::ostream& s, const String& in) { return s << in.c_str(); }
+Contains::Contains(const String& str) : string(str) { }
+
+bool Contains::checkWith(const String& other) const {
+ return strstr(other.c_str(), string.c_str()) != nullptr;
+}
+
+String toString(const Contains& in) {
+ return "Contains( " + in.string + " )";
+}
+
+bool operator==(const String& lhs, const Contains& rhs) { return rhs.checkWith(lhs); }
+bool operator==(const Contains& lhs, const String& rhs) { return lhs.checkWith(rhs); }
+bool operator!=(const String& lhs, const Contains& rhs) { return !rhs.checkWith(lhs); }
+bool operator!=(const Contains& lhs, const String& rhs) { return !lhs.checkWith(rhs); }
+
namespace {
void color_to_stream(std::ostream&, Color::Enum) DOCTEST_BRANCH_ON_DISABLED({}, ;)
} // namespace
@@ -3403,64 +3777,42 @@ namespace Color {
// clang-format off
const char* assertString(assertType::Enum at) {
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4062) // enum 'x' in switch of enum 'y' is not handled
- switch(at) { //!OCLINT missing default in switch statements
- case assertType::DT_WARN : return "WARN";
- case assertType::DT_CHECK : return "CHECK";
- case assertType::DT_REQUIRE : return "REQUIRE";
-
- case assertType::DT_WARN_FALSE : return "WARN_FALSE";
- case assertType::DT_CHECK_FALSE : return "CHECK_FALSE";
- case assertType::DT_REQUIRE_FALSE : return "REQUIRE_FALSE";
-
- case assertType::DT_WARN_THROWS : return "WARN_THROWS";
- case assertType::DT_CHECK_THROWS : return "CHECK_THROWS";
- case assertType::DT_REQUIRE_THROWS : return "REQUIRE_THROWS";
-
- case assertType::DT_WARN_THROWS_AS : return "WARN_THROWS_AS";
- case assertType::DT_CHECK_THROWS_AS : return "CHECK_THROWS_AS";
- case assertType::DT_REQUIRE_THROWS_AS : return "REQUIRE_THROWS_AS";
-
- case assertType::DT_WARN_THROWS_WITH : return "WARN_THROWS_WITH";
- case assertType::DT_CHECK_THROWS_WITH : return "CHECK_THROWS_WITH";
- case assertType::DT_REQUIRE_THROWS_WITH : return "REQUIRE_THROWS_WITH";
-
- case assertType::DT_WARN_THROWS_WITH_AS : return "WARN_THROWS_WITH_AS";
- case assertType::DT_CHECK_THROWS_WITH_AS : return "CHECK_THROWS_WITH_AS";
- case assertType::DT_REQUIRE_THROWS_WITH_AS : return "REQUIRE_THROWS_WITH_AS";
-
- case assertType::DT_WARN_NOTHROW : return "WARN_NOTHROW";
- case assertType::DT_CHECK_NOTHROW : return "CHECK_NOTHROW";
- case assertType::DT_REQUIRE_NOTHROW : return "REQUIRE_NOTHROW";
-
- case assertType::DT_WARN_EQ : return "WARN_EQ";
- case assertType::DT_CHECK_EQ : return "CHECK_EQ";
- case assertType::DT_REQUIRE_EQ : return "REQUIRE_EQ";
- case assertType::DT_WARN_NE : return "WARN_NE";
- case assertType::DT_CHECK_NE : return "CHECK_NE";
- case assertType::DT_REQUIRE_NE : return "REQUIRE_NE";
- case assertType::DT_WARN_GT : return "WARN_GT";
- case assertType::DT_CHECK_GT : return "CHECK_GT";
- case assertType::DT_REQUIRE_GT : return "REQUIRE_GT";
- case assertType::DT_WARN_LT : return "WARN_LT";
- case assertType::DT_CHECK_LT : return "CHECK_LT";
- case assertType::DT_REQUIRE_LT : return "REQUIRE_LT";
- case assertType::DT_WARN_GE : return "WARN_GE";
- case assertType::DT_CHECK_GE : return "CHECK_GE";
- case assertType::DT_REQUIRE_GE : return "REQUIRE_GE";
- case assertType::DT_WARN_LE : return "WARN_LE";
- case assertType::DT_CHECK_LE : return "CHECK_LE";
- case assertType::DT_REQUIRE_LE : return "REQUIRE_LE";
-
- case assertType::DT_WARN_UNARY : return "WARN_UNARY";
- case assertType::DT_CHECK_UNARY : return "CHECK_UNARY";
- case assertType::DT_REQUIRE_UNARY : return "REQUIRE_UNARY";
- case assertType::DT_WARN_UNARY_FALSE : return "WARN_UNARY_FALSE";
- case assertType::DT_CHECK_UNARY_FALSE : return "CHECK_UNARY_FALSE";
- case assertType::DT_REQUIRE_UNARY_FALSE : return "REQUIRE_UNARY_FALSE";
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4061) // enum 'x' in switch of enum 'y' is not explicitely handled
+ #define DOCTEST_GENERATE_ASSERT_TYPE_CASE(assert_type) case assertType::DT_ ## assert_type: return #assert_type
+ #define DOCTEST_GENERATE_ASSERT_TYPE_CASES(assert_type) \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN_ ## assert_type); \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK_ ## assert_type); \
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE_ ## assert_type)
+ switch(at) {
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(WARN);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(CHECK);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASE(REQUIRE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(FALSE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_AS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(THROWS_WITH_AS);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(NOTHROW);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(EQ);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(NE);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(GT);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(LT);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(GE);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(LE);
+
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY);
+ DOCTEST_GENERATE_ASSERT_TYPE_CASES(UNARY_FALSE);
+
+ default: DOCTEST_INTERNAL_ERROR("Tried stringifying invalid assert type!");
}
DOCTEST_MSVC_SUPPRESS_WARNING_POP
- return "";
}
// clang-format on
@@ -3494,6 +3846,12 @@ const char* skipPathFromFilename(const char* file) {
DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_GCC_SUPPRESS_WARNING_POP
+bool SubcaseSignature::operator==(const SubcaseSignature& other) const {
+ return m_line == other.m_line
+ && std::strcmp(m_file, other.m_file) == 0
+ && m_name == other.m_name;
+}
+
bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
if(m_line != other.m_line)
return m_line < other.m_line;
@@ -3502,45 +3860,53 @@ bool SubcaseSignature::operator<(const SubcaseSignature& other) const {
return m_name.compare(other.m_name) < 0;
}
-IContextScope::IContextScope() = default;
-IContextScope::~IContextScope() = default;
+DOCTEST_DEFINE_INTERFACE(IContextScope)
-#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-String toString(char* in) { return toString(static_cast<const char*>(in)); }
-// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
-String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
-#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
-String toString(bool in) { return in ? "true" : "false"; }
-String toString(float in) { return fpToString(in, 5) + "f"; }
-String toString(double in) { return fpToString(in, 10); }
-String toString(double long in) { return fpToString(in, 15); }
-
-#define DOCTEST_TO_STRING_OVERLOAD(type, fmt) \
- String toString(type in) { \
- char buf[64]; \
- std::sprintf(buf, fmt, in); \
- return buf; \
+namespace detail {
+ void filldata<const void*>::fill(std::ostream* stream, const void* in) {
+ if (in) { *stream << in; }
+ else { *stream << "nullptr"; }
}
-DOCTEST_TO_STRING_OVERLOAD(char, "%d")
-DOCTEST_TO_STRING_OVERLOAD(char signed, "%d")
-DOCTEST_TO_STRING_OVERLOAD(char unsigned, "%u")
-DOCTEST_TO_STRING_OVERLOAD(int short, "%d")
-DOCTEST_TO_STRING_OVERLOAD(int short unsigned, "%u")
-DOCTEST_TO_STRING_OVERLOAD(int, "%d")
-DOCTEST_TO_STRING_OVERLOAD(unsigned, "%u")
-DOCTEST_TO_STRING_OVERLOAD(int long, "%ld")
-DOCTEST_TO_STRING_OVERLOAD(int long unsigned, "%lu")
-DOCTEST_TO_STRING_OVERLOAD(int long long, "%lld")
-DOCTEST_TO_STRING_OVERLOAD(int long long unsigned, "%llu")
+ template <typename T>
+ String toStreamLit(T t) {
+ std::ostream* os = tlssPush();
+ os->operator<<(t);
+ return tlssPop();
+ }
+}
-String toString(std::nullptr_t) { return "NULL"; }
+#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
+String toString(const char* in) { return String("\"") + (in ? in : "{null string}") + "\""; }
+#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
#if DOCTEST_MSVC >= DOCTEST_COMPILER(19, 20, 0)
-// see this issue on why this is needed: https://github.com/onqtam/doctest/issues/183
+// see this issue on why this is needed: https://github.com/doctest/doctest/issues/183
String toString(const std::string& in) { return in.c_str(); }
#endif // VS 2019
+String toString(String in) { return in; }
+
+String toString(std::nullptr_t) { return "nullptr"; }
+
+String toString(bool in) { return in ? "true" : "false"; }
+
+String toString(float in) { return toStreamLit(in); }
+String toString(double in) { return toStreamLit(in); }
+String toString(double long in) { return toStreamLit(in); }
+
+String toString(char in) { return toStreamLit(static_cast<signed>(in)); }
+String toString(char signed in) { return toStreamLit(static_cast<signed>(in)); }
+String toString(char unsigned in) { return toStreamLit(static_cast<unsigned>(in)); }
+String toString(short in) { return toStreamLit(in); }
+String toString(short unsigned in) { return toStreamLit(in); }
+String toString(signed in) { return toStreamLit(in); }
+String toString(unsigned in) { return toStreamLit(in); }
+String toString(long in) { return toStreamLit(in); }
+String toString(long unsigned in) { return toStreamLit(in); }
+String toString(long long in) { return toStreamLit(in); }
+String toString(long long unsigned in) { return toStreamLit(in); }
+
Approx::Approx(double value)
: m_epsilon(static_cast<double>(std::numeric_limits<float>::epsilon()) * 100)
, m_scale(1.0)
@@ -3580,11 +3946,25 @@ bool operator>(double lhs, const Approx& rhs) { return lhs > rhs.m_value && lhs
bool operator>(const Approx& lhs, double rhs) { return lhs.m_value > rhs && lhs != rhs; }
String toString(const Approx& in) {
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
- return String("Approx( ") + doctest::toString(in.m_value) + " )";
+ return "Approx( " + doctest::toString(in.m_value) + " )";
}
const ContextOptions* getContextOptions() { return DOCTEST_BRANCH_ON_DISABLED(nullptr, g_cs); }
+DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4738)
+template <typename F>
+IsNaN<F>::operator bool() const {
+ return std::isnan(value) ^ flipped;
+}
+DOCTEST_MSVC_SUPPRESS_WARNING_POP
+template struct DOCTEST_INTERFACE_DEF IsNaN<float>;
+template struct DOCTEST_INTERFACE_DEF IsNaN<double>;
+template struct DOCTEST_INTERFACE_DEF IsNaN<long double>;
+template <typename F>
+String toString(IsNaN<F> in) { return String(in.flipped ? "! " : "") + "IsNaN( " + doctest::toString(in.value) + " )"; }
+String toString(IsNaN<float> in) { return toString<float>(in); }
+String toString(IsNaN<double> in) { return toString<double>(in); }
+String toString(IsNaN<double long> in) { return toString<double long>(in); }
+
} // namespace doctest
#ifdef DOCTEST_CONFIG_DISABLE
@@ -3594,15 +3974,15 @@ Context::~Context() = default;
void Context::applyCommandLine(int, const char* const*) {}
void Context::addFilter(const char*, const char*) {}
void Context::clearFilters() {}
+void Context::setOption(const char*, bool) {}
void Context::setOption(const char*, int) {}
void Context::setOption(const char*, const char*) {}
bool Context::shouldExit() { return false; }
void Context::setAsDefaultForAssertsOutOfTestCases() {}
void Context::setAssertHandler(detail::assert_handler) {}
+void Context::setCout(std::ostream*) {}
int Context::run() { return 0; }
-IReporter::~IReporter() = default;
-
int IReporter::get_num_active_contexts() { return 0; }
const IContextScope* const* IReporter::get_active_contexts() { return nullptr; }
int IReporter::get_num_stringified_contexts() { return 0; }
@@ -3635,7 +4015,7 @@ namespace doctest {
namespace {
// the int (priority) is part of the key for automatic sorting - sadly one can register a
// reporter with a duplicate name and a different priority but hopefully that won't happen often :|
- typedef std::map<std::pair<int, String>, reporterCreatorFunc> reporterMap;
+ using reporterMap = std::map<std::pair<int, String>, reporterCreatorFunc>;
reporterMap& getReporters() {
static reporterMap data;
@@ -3667,8 +4047,8 @@ namespace detail {
#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
DOCTEST_NORETURN void throwException() {
g_cs->shouldLogCurrentException = false;
- throw TestFailureException();
- } // NOLINT(cert-err60-cpp)
+ throw TestFailureException(); // NOLINT(hicpp-exception-baseclass)
+ }
#else // DOCTEST_CONFIG_NO_EXCEPTIONS
void throwException() {}
#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
@@ -3714,91 +4094,132 @@ namespace {
return !*wild;
}
- //// C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
- //unsigned hashStr(unsigned const char* str) {
- // unsigned long hash = 5381;
- // char c;
- // while((c = *str++))
- // hash = ((hash << 5) + hash) + c; // hash * 33 + c
- // return hash;
- //}
-
// checks if the name matches any of the filters (and can be configured what to do when empty)
bool matchesAny(const char* name, const std::vector<String>& filters, bool matchEmpty,
- bool caseSensitive) {
- if(filters.empty() && matchEmpty)
+ bool caseSensitive) {
+ if (filters.empty() && matchEmpty)
return true;
- for(auto& curr : filters)
- if(wildcmp(name, curr.c_str(), caseSensitive))
+ for (auto& curr : filters)
+ if (wildcmp(name, curr.c_str(), caseSensitive))
return true;
return false;
}
-} // namespace
-namespace detail {
- Subcase::Subcase(const String& name, const char* file, int line)
- : m_signature({name, file, line}) {
- auto* s = g_cs;
+ unsigned long long hash(unsigned long long a, unsigned long long b) {
+ return (a << 5) + b;
+ }
- // check subcase filters
- if(s->subcasesStack.size() < size_t(s->subcase_filter_levels)) {
- if(!matchesAny(m_signature.m_name.c_str(), s->filters[6], true, s->case_sensitive))
- return;
- if(matchesAny(m_signature.m_name.c_str(), s->filters[7], false, s->case_sensitive))
- return;
- }
-
- // if a Subcase on the same level has already been entered
- if(s->subcasesStack.size() < size_t(s->subcasesCurrentMaxLevel)) {
- s->should_reenter = true;
- return;
- }
+ // C string hash function (djb2) - taken from http://www.cse.yorku.ca/~oz/hash.html
+ unsigned long long hash(const char* str) {
+ unsigned long long hash = 5381;
+ char c;
+ while ((c = *str++))
+ hash = ((hash << 5) + hash) + c; // hash * 33 + c
+ return hash;
+ }
- // push the current signature to the stack so we can check if the
- // current stack + the current new subcase have been traversed
- s->subcasesStack.push_back(m_signature);
- if(s->subcasesPassed.count(s->subcasesStack) != 0) {
- // pop - revert to previous stack since we've already passed this
- s->subcasesStack.pop_back();
- return;
+ unsigned long long hash(const SubcaseSignature& sig) {
+ return hash(hash(hash(sig.m_file), hash(sig.m_name.c_str())), sig.m_line);
+ }
+
+ unsigned long long hash(const std::vector<SubcaseSignature>& sigs, size_t count) {
+ unsigned long long running = 0;
+ auto end = sigs.begin() + count;
+ for (auto it = sigs.begin(); it != end; it++) {
+ running = hash(running, hash(*it));
}
+ return running;
+ }
- s->subcasesCurrentMaxLevel = s->subcasesStack.size();
- m_entered = true;
+ unsigned long long hash(const std::vector<SubcaseSignature>& sigs) {
+ unsigned long long running = 0;
+ for (const SubcaseSignature& sig : sigs) {
+ running = hash(running, hash(sig));
+ }
+ return running;
+ }
+} // namespace
+namespace detail {
+ bool Subcase::checkFilters() {
+ if (g_cs->subcaseStack.size() < size_t(g_cs->subcase_filter_levels)) {
+ if (!matchesAny(m_signature.m_name.c_str(), g_cs->filters[6], true, g_cs->case_sensitive))
+ return true;
+ if (matchesAny(m_signature.m_name.c_str(), g_cs->filters[7], false, g_cs->case_sensitive))
+ return true;
+ }
+ return false;
+ }
- DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ Subcase::Subcase(const String& name, const char* file, int line)
+ : m_signature({name, file, line}) {
+ if (!g_cs->reachedLeaf) {
+ if (g_cs->nextSubcaseStack.size() <= g_cs->subcaseStack.size()
+ || g_cs->nextSubcaseStack[g_cs->subcaseStack.size()] == m_signature) {
+ // Going down.
+ if (checkFilters()) { return; }
+
+ g_cs->subcaseStack.push_back(m_signature);
+ g_cs->currentSubcaseDepth++;
+ m_entered = true;
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ }
+ } else {
+ if (g_cs->subcaseStack[g_cs->currentSubcaseDepth] == m_signature) {
+ // This subcase is reentered via control flow.
+ g_cs->currentSubcaseDepth++;
+ m_entered = true;
+ DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_start, m_signature);
+ } else if (g_cs->nextSubcaseStack.size() <= g_cs->currentSubcaseDepth
+ && g_cs->fullyTraversedSubcases.find(hash(hash(g_cs->subcaseStack, g_cs->currentSubcaseDepth), hash(m_signature)))
+ == g_cs->fullyTraversedSubcases.end()) {
+ if (checkFilters()) { return; }
+ // This subcase is part of the one to be executed next.
+ g_cs->nextSubcaseStack.clear();
+ g_cs->nextSubcaseStack.insert(g_cs->nextSubcaseStack.end(),
+ g_cs->subcaseStack.begin(), g_cs->subcaseStack.begin() + g_cs->currentSubcaseDepth);
+ g_cs->nextSubcaseStack.push_back(m_signature);
+ }
+ }
}
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
- DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
Subcase::~Subcase() {
- if(m_entered) {
- // only mark the subcase stack as passed if no subcases have been skipped
- if(g_cs->should_reenter == false)
- g_cs->subcasesPassed.insert(g_cs->subcasesStack);
- g_cs->subcasesStack.pop_back();
+ if (m_entered) {
+ g_cs->currentSubcaseDepth--;
+
+ if (!g_cs->reachedLeaf) {
+ // Leaf.
+ g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
+ g_cs->nextSubcaseStack.clear();
+ g_cs->reachedLeaf = true;
+ } else if (g_cs->nextSubcaseStack.empty()) {
+ // All children are finished.
+ g_cs->fullyTraversedSubcases.insert(hash(g_cs->subcaseStack));
+ }
#if defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411L && (!defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
if(std::uncaught_exceptions() > 0
#else
if(std::uncaught_exception()
#endif
- && g_cs->shouldLogCurrentException) {
+ && g_cs->shouldLogCurrentException) {
DOCTEST_ITERATE_THROUGH_REPORTERS(
test_case_exception, {"exception thrown in subcase - will translate later "
- "when the whole test case has been exited (cannot "
- "translate while there is an active exception)",
- false});
+ "when the whole test case has been exited (cannot "
+ "translate while there is an active exception)",
+ false});
g_cs->shouldLogCurrentException = false;
}
+
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
}
}
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP
Subcase::operator bool() const { return m_entered; }
@@ -3812,20 +4233,11 @@ namespace detail {
TestSuite& TestSuite::operator*(const char* in) {
m_test_suite = in;
- // clear state
- m_description = nullptr;
- m_skip = false;
- m_no_breaks = false;
- m_no_output = false;
- m_may_fail = false;
- m_should_fail = false;
- m_expected_failures = 0;
- m_timeout = 0;
return *this;
}
TestCase::TestCase(funcType test, const char* file, unsigned line, const TestSuite& test_suite,
- const char* type, int template_id) {
+ const String& type, int template_id) {
m_file = file;
m_line = line;
m_name = nullptr; // will be later overridden in operator*
@@ -3850,10 +4262,8 @@ namespace detail {
}
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(26434) // hides a non-virtual function
- DOCTEST_MSVC_SUPPRESS_WARNING(26437) // Do not slice
TestCase& TestCase::operator=(const TestCase& other) {
- static_cast<TestCaseData&>(*this) = static_cast<const TestCaseData&>(other);
-
+ TestCaseData::operator=(other);
m_test = other.m_test;
m_type = other.m_type;
m_template_id = other.m_template_id;
@@ -3869,7 +4279,7 @@ namespace detail {
m_name = in;
// make a new name with an appended type for templated test case
if(m_template_id != -1) {
- m_full_name = String(m_name) + m_type;
+ m_full_name = String(m_name) + "<" + m_type + ">";
// redirect the name to point to the newly constructed full name
m_name = m_full_name.c_str();
}
@@ -3925,29 +4335,6 @@ namespace {
return suiteOrderComparator(lhs, rhs);
}
-#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
- HANDLE g_stdoutHandle;
- WORD g_origFgAttrs;
- WORD g_origBgAttrs;
- bool g_attrsInitted = false;
-
- int colors_init() {
- if(!g_attrsInitted) {
- g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- g_attrsInitted = true;
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- GetConsoleScreenBufferInfo(g_stdoutHandle, &csbiInfo);
- g_origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
- BACKGROUND_BLUE | BACKGROUND_INTENSITY);
- g_origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
- FOREGROUND_BLUE | FOREGROUND_INTENSITY);
- }
- return 0;
- }
-
- int dumy_init_console_colors = colors_init();
-#endif // DOCTEST_CONFIG_COLORS_WINDOWS
-
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
void color_to_stream(std::ostream& s, Color::Enum code) {
static_cast<void>(s); // for DOCTEST_CONFIG_COLORS_NONE or DOCTEST_CONFIG_COLORS_WINDOWS
@@ -3981,10 +4368,26 @@ namespace {
#ifdef DOCTEST_CONFIG_COLORS_WINDOWS
if(g_no_colors ||
- (isatty(fileno(stdout)) == false && getContextOptions()->force_colors == false))
+ (_isatty(_fileno(stdout)) == false && getContextOptions()->force_colors == false))
return;
-#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(g_stdoutHandle, x | g_origBgAttrs)
+ static struct ConsoleHelper {
+ HANDLE stdoutHandle;
+ WORD origFgAttrs;
+ WORD origBgAttrs;
+
+ ConsoleHelper() {
+ stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
+ GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
+ origFgAttrs = csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED |
+ BACKGROUND_BLUE | BACKGROUND_INTENSITY);
+ origBgAttrs = csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED |
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ }
+ } ch;
+
+#define DOCTEST_SET_ATTR(x) SetConsoleTextAttribute(ch.stdoutHandle, x | ch.origBgAttrs)
// clang-format off
switch (code) {
@@ -4001,7 +4404,7 @@ namespace {
case Color::BrightWhite: DOCTEST_SET_ATTR(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE); break;
case Color::None:
case Color::Bright: // invalid
- default: DOCTEST_SET_ATTR(g_origFgAttrs);
+ default: DOCTEST_SET_ATTR(ch.origFgAttrs);
}
// clang-format on
#endif // DOCTEST_CONFIG_COLORS_WINDOWS
@@ -4118,35 +4521,22 @@ namespace detail {
getExceptionTranslators().push_back(et);
}
-#ifdef DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- void toStream(std::ostream* s, char* in) { *s << in; }
- void toStream(std::ostream* s, const char* in) { *s << in; }
-#endif // DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING
- void toStream(std::ostream* s, bool in) { *s << std::boolalpha << in << std::noboolalpha; }
- void toStream(std::ostream* s, float in) { *s << in; }
- void toStream(std::ostream* s, double in) { *s << in; }
- void toStream(std::ostream* s, double long in) { *s << in; }
-
- void toStream(std::ostream* s, char in) { *s << in; }
- void toStream(std::ostream* s, char signed in) { *s << in; }
- void toStream(std::ostream* s, char unsigned in) { *s << in; }
- void toStream(std::ostream* s, int short in) { *s << in; }
- void toStream(std::ostream* s, int short unsigned in) { *s << in; }
- void toStream(std::ostream* s, int in) { *s << in; }
- void toStream(std::ostream* s, int unsigned in) { *s << in; }
- void toStream(std::ostream* s, int long in) { *s << in; }
- void toStream(std::ostream* s, int long unsigned in) { *s << in; }
- void toStream(std::ostream* s, int long long in) { *s << in; }
- void toStream(std::ostream* s, int long long unsigned in) { *s << in; }
-
DOCTEST_THREAD_LOCAL std::vector<IContextScope*> g_infoContexts; // for logging with INFO()
ContextScopeBase::ContextScopeBase() {
g_infoContexts.push_back(this);
}
- DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
- DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
+ ContextScopeBase::ContextScopeBase(ContextScopeBase&& other) noexcept {
+ if (other.need_to_destroy) {
+ other.destroy();
+ }
+ other.need_to_destroy = false;
+ g_infoContexts.push_back(this);
+ }
+
+ DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4996) // std::uncaught_exception is deprecated in C++17
+ DOCTEST_GCC_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
// destroy cannot be inlined into the destructor because that would mean calling stringify after
@@ -4165,8 +4555,8 @@ namespace detail {
g_infoContexts.pop_back();
}
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
- DOCTEST_GCC_SUPPRESS_WARNING_POP
+ DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ DOCTEST_GCC_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP
} // namespace detail
namespace {
@@ -4207,10 +4597,10 @@ namespace {
static LONG CALLBACK handleException(PEXCEPTION_POINTERS ExceptionInfo) {
// Multiple threads may enter this filter/handler at once. We want the error message to be printed on the
// console just once no matter how many threads have crashed.
- static std::mutex mutex;
+ DOCTEST_DECLARE_STATIC_MUTEX(mutex)
static bool execute = true;
{
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
if(execute) {
bool reported = false;
for(size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
@@ -4313,7 +4703,7 @@ namespace {
static unsigned int prev_abort_behavior;
static int prev_report_mode;
static _HFILE prev_report_file;
- static void (*prev_sigabrt_handler)(int);
+ static void (DOCTEST_CDECL *prev_sigabrt_handler)(int);
static std::terminate_handler original_terminate_handler;
static bool isSet;
static ULONG guaranteeSize;
@@ -4325,7 +4715,7 @@ namespace {
unsigned int FatalConditionHandler::prev_abort_behavior;
int FatalConditionHandler::prev_report_mode;
_HFILE FatalConditionHandler::prev_report_file;
- void (*FatalConditionHandler::prev_sigabrt_handler)(int);
+ void (DOCTEST_CDECL *FatalConditionHandler::prev_sigabrt_handler)(int);
std::terminate_handler FatalConditionHandler::original_terminate_handler;
bool FatalConditionHandler::isSet = false;
ULONG FatalConditionHandler::guaranteeSize = 0;
@@ -4383,7 +4773,7 @@ namespace {
sigStack.ss_flags = 0;
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = {};
- sa.sa_handler = handleSignal; // NOLINT
+ sa.sa_handler = handleSignal;
sa.sa_flags = SA_ONSTACK;
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
@@ -4422,7 +4812,7 @@ namespace {
#define DOCTEST_OUTPUT_DEBUG_STRING(text) ::OutputDebugStringA(text)
#else
// TODO: integration with XCode and other IDEs
-#define DOCTEST_OUTPUT_DEBUG_STRING(text) // NOLINT(clang-diagnostic-unused-macros)
+#define DOCTEST_OUTPUT_DEBUG_STRING(text)
#endif // Platform
void addAssert(assertType::Enum at) {
@@ -4441,8 +4831,8 @@ namespace {
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_exception, {message.c_str(), true});
- while(g_cs->subcasesStack.size()) {
- g_cs->subcasesStack.pop_back();
+ while (g_cs->subcaseStack.size()) {
+ g_cs->subcaseStack.pop_back();
DOCTEST_ITERATE_THROUGH_REPORTERS(subcase_end, DOCTEST_EMPTY);
}
@@ -4454,25 +4844,26 @@ namespace {
}
#endif // DOCTEST_CONFIG_POSIX_SIGNALS || DOCTEST_CONFIG_WINDOWS_SEH
} // namespace
-namespace detail {
- ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
- const char* exception_type, const char* exception_string) {
- m_test_case = g_cs->currentTest;
- m_at = at;
- m_file = file;
- m_line = line;
- m_expr = expr;
- m_failed = true;
- m_threw = false;
- m_threw_as = false;
- m_exception_type = exception_type;
- m_exception_string = exception_string;
+AssertData::AssertData(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const StringContains& exception_string)
+ : m_test_case(g_cs->currentTest), m_at(at), m_file(file), m_line(line), m_expr(expr),
+ m_failed(true), m_threw(false), m_threw_as(false), m_exception_type(exception_type),
+ m_exception_string(exception_string) {
#if DOCTEST_MSVC
- if(m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
- ++m_expr;
+ if (m_expr[0] == ' ') // this happens when variadic macros are disabled under MSVC
+ ++m_expr;
#endif // MSVC
- }
+}
+
+namespace detail {
+ ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const String& exception_string)
+ : AssertData(at, file, line, expr, exception_type, exception_string) { }
+
+ ResultBuilder::ResultBuilder(assertType::Enum at, const char* file, int line, const char* expr,
+ const char* exception_type, const Contains& exception_string)
+ : AssertData(at, file, line, expr, exception_type, exception_string) { }
void ResultBuilder::setResult(const Result& res) {
m_decomp = res.m_decomp;
@@ -4488,17 +4879,17 @@ namespace detail {
if(m_at & assertType::is_throws) { //!OCLINT bitwise operator in conditional
m_failed = !m_threw;
} else if((m_at & assertType::is_throws_as) && (m_at & assertType::is_throws_with)) { //!OCLINT
- m_failed = !m_threw_as || (m_exception != m_exception_string);
+ m_failed = !m_threw_as || !m_exception_string.check(m_exception);
} else if(m_at & assertType::is_throws_as) { //!OCLINT bitwise operator in conditional
m_failed = !m_threw_as;
} else if(m_at & assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
- m_failed = m_exception != m_exception_string;
+ m_failed = !m_exception_string.check(m_exception);
} else if(m_at & assertType::is_nothrow) { //!OCLINT bitwise operator in conditional
m_failed = m_threw;
}
if(m_exception.size())
- m_exception = String("\"") + m_exception + "\"";
+ m_exception = "\"" + m_exception + "\"";
if(is_running_in_test) {
addAssert(m_at);
@@ -4526,8 +4917,8 @@ namespace detail {
std::abort();
}
- void decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
- Result result) {
+ bool decomp_assert(assertType::Enum at, const char* file, int line, const char* expr,
+ const Result& result) {
bool failed = !result.m_passed;
// ###################################################################################
@@ -4536,21 +4927,29 @@ namespace detail {
// ###################################################################################
DOCTEST_ASSERT_OUT_OF_TESTS(result.m_decomp);
DOCTEST_ASSERT_IN_TESTS(result.m_decomp);
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
+ return !failed;
}
MessageBuilder::MessageBuilder(const char* file, int line, assertType::Enum severity) {
- m_stream = getTlsOss();
+ m_stream = tlssPush();
m_file = file;
m_line = line;
m_severity = severity;
}
- IExceptionTranslator::IExceptionTranslator() = default;
- IExceptionTranslator::~IExceptionTranslator() = default;
+ MessageBuilder::~MessageBuilder() {
+ if (!logged)
+ tlssPop();
+ }
+
+ DOCTEST_DEFINE_INTERFACE(IExceptionTranslator)
bool MessageBuilder::log() {
- m_string = getTlsOssResult();
+ if (!logged) {
+ m_string = tlssPop();
+ logged = true;
+ }
+
DOCTEST_ITERATE_THROUGH_REPORTERS(log_message, *this);
const bool isWarn = m_severity & assertType::is_warn;
@@ -4569,29 +4968,10 @@ namespace detail {
if(m_severity & assertType::is_require) //!OCLINT bitwise operator in conditional
throwException();
}
-
- MessageBuilder::~MessageBuilder() = default;
} // namespace detail
namespace {
using namespace detail;
- template <typename Ex>
- DOCTEST_NORETURN void throw_exception(Ex const& e) {
-#ifndef DOCTEST_CONFIG_NO_EXCEPTIONS
- throw e;
-#else // DOCTEST_CONFIG_NO_EXCEPTIONS
- std::cerr << "doctest will terminate because it needed to throw an exception.\n"
- << "The message was: " << e.what() << '\n';
- std::terminate();
-#endif // DOCTEST_CONFIG_NO_EXCEPTIONS
- }
-
-#ifndef DOCTEST_INTERNAL_ERROR
-#define DOCTEST_INTERNAL_ERROR(msg) \
- throw_exception(std::logic_error( \
- __FILE__ ":" DOCTEST_TOSTR(__LINE__) ": Internal doctest error: " msg))
-#endif // DOCTEST_INTERNAL_ERROR
-
// clang-format off
// =================================================================================================
@@ -4673,10 +5053,10 @@ namespace {
void ensureTagClosed();
- private:
-
void writeDeclaration();
+ private:
+
void newlineIfNecessary();
bool m_tagIsOpen = false;
@@ -4865,7 +5245,7 @@ namespace {
XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
{
- writeDeclaration();
+ // writeDeclaration(); // called explicitly by the reporters that use the writer class - see issue #627
}
XmlWriter::~XmlWriter() {
@@ -4976,8 +5356,8 @@ namespace {
struct XmlReporter : public IReporter
{
- XmlWriter xml;
- std::mutex mutex;
+ XmlWriter xml;
+ DOCTEST_DECLARE_MUTEX(mutex)
// caching pointers/references to objects of these types - safe to do
const ContextOptions& opt;
@@ -5054,7 +5434,8 @@ namespace {
xml.scopedElement("TestCase").writeAttribute("name", in.data[i]->m_name)
.writeAttribute("testsuite", in.data[i]->m_test_suite)
.writeAttribute("filename", skipPathFromFilename(in.data[i]->m_file.c_str()))
- .writeAttribute("line", line(in.data[i]->m_line));
+ .writeAttribute("line", line(in.data[i]->m_line))
+ .writeAttribute("skipped", in.data[i]->m_skip);
}
xml.scopedElement("OverallResultsTestCases")
.writeAttribute("unskipped", in.run_stats->numTestCasesPassingFilters);
@@ -5070,6 +5451,8 @@ namespace {
}
void test_run_start() override {
+ xml.writeDeclaration();
+
// remove .exe extension - mainly to have the same output on UNIX and Windows
std::string binary_name = skipPathFromFilename(opt.binary_name.c_str());
#ifdef DOCTEST_PLATFORM_WINDOWS
@@ -5124,7 +5507,8 @@ namespace {
xml.startElement("OverallResultsAsserts")
.writeAttribute("successes",
st.numAssertsCurrentTest - st.numAssertsFailedCurrentTest)
- .writeAttribute("failures", st.numAssertsFailedCurrentTest);
+ .writeAttribute("failures", st.numAssertsFailedCurrentTest)
+ .writeAttribute("test_case_success", st.testCaseSuccess);
if(opt.duration)
xml.writeAttribute("duration", st.seconds);
if(tc->m_expected_failures)
@@ -5135,7 +5519,7 @@ namespace {
}
void test_case_exception(const TestCaseException& e) override {
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
xml.scopedElement("Exception")
.writeAttribute("crash", e.is_crash)
@@ -5143,8 +5527,6 @@ namespace {
}
void subcase_start(const SubcaseSignature& in) override {
- std::lock_guard<std::mutex> lock(mutex);
-
xml.startElement("SubCase")
.writeAttribute("name", in.m_name)
.writeAttribute("filename", skipPathFromFilename(in.m_file))
@@ -5158,7 +5540,7 @@ namespace {
if(!rb.m_failed && !opt.success)
return;
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
xml.startElement("Expression")
.writeAttribute("success", !rb.m_failed)
@@ -5174,7 +5556,7 @@ namespace {
if(rb.m_at & assertType::is_throws_as)
xml.scopedElement("ExpectedException").writeText(rb.m_exception_type);
if(rb.m_at & assertType::is_throws_with)
- xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string);
+ xml.scopedElement("ExpectedExceptionString").writeText(rb.m_exception_string.c_str());
if((rb.m_at & assertType::is_normal) && !rb.m_threw)
xml.scopedElement("Expanded").writeText(rb.m_decomp.c_str());
@@ -5184,7 +5566,7 @@ namespace {
}
void log_message(const MessageData& mb) override {
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
xml.startElement("Message")
.writeAttribute("type", failureString(mb.m_severity))
@@ -5220,7 +5602,8 @@ namespace {
} else if((rb.m_at & assertType::is_throws_as) &&
(rb.m_at & assertType::is_throws_with)) { //!OCLINT
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
- << rb.m_exception_string << "\", " << rb.m_exception_type << " ) " << Color::None;
+ << rb.m_exception_string.c_str()
+ << "\", " << rb.m_exception_type << " ) " << Color::None;
if(rb.m_threw) {
if(!rb.m_failed) {
s << "threw as expected!\n";
@@ -5241,7 +5624,8 @@ namespace {
} else if(rb.m_at &
assertType::is_throws_with) { //!OCLINT bitwise operator in conditional
s << Color::Cyan << assertString(rb.m_at) << "( " << rb.m_expr << ", \""
- << rb.m_exception_string << "\" ) " << Color::None
+ << rb.m_exception_string.c_str()
+ << "\" ) " << Color::None
<< (rb.m_threw ? (!rb.m_failed ? "threw as expected!" :
"threw a DIFFERENT exception: ") :
"did NOT throw at all!")
@@ -5266,8 +5650,8 @@ namespace {
// - more attributes in tags
struct JUnitReporter : public IReporter
{
- XmlWriter xml;
- std::mutex mutex;
+ XmlWriter xml;
+ DOCTEST_DECLARE_MUTEX(mutex)
Timer timer;
std::vector<String> deepestSubcaseStackNames;
@@ -5363,9 +5747,13 @@ namespace {
// WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
// =========================================================================================
- void report_query(const QueryData&) override {}
+ void report_query(const QueryData&) override {
+ xml.writeDeclaration();
+ }
- void test_run_start() override {}
+ void test_run_start() override {
+ xml.writeDeclaration();
+ }
void test_run_end(const TestRunStats& p) override {
// remove .exe extension - mainly to have the same output on UNIX and Windows
@@ -5435,12 +5823,11 @@ namespace {
}
void test_case_exception(const TestCaseException& e) override {
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
testCaseData.addError("exception", e.error_string.c_str());
}
void subcase_start(const SubcaseSignature& in) override {
- std::lock_guard<std::mutex> lock(mutex);
deepestSubcaseStackNames.push_back(in.m_name);
}
@@ -5450,7 +5837,7 @@ namespace {
if(!rb.m_failed) // report only failures & ignore the `success` option
return;
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
std::ostringstream os;
os << skipPathFromFilename(rb.m_file) << (opt.gnu_file_line ? ":" : "(")
@@ -5501,7 +5888,7 @@ namespace {
bool hasLoggedCurrentTestStart;
std::vector<SubcaseSignature> subcasesStack;
size_t currentSubcaseLevel;
- std::mutex mutex;
+ DOCTEST_DECLARE_MUTEX(mutex)
// caching pointers/references to objects of these types - safe to do
const ContextOptions& opt;
@@ -5606,9 +5993,11 @@ namespace {
}
void printIntro() {
- printVersion();
- s << Color::Cyan << "[doctest] " << Color::None
- << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
+ if(opt.no_intro == false) {
+ printVersion();
+ s << Color::Cyan << "[doctest] " << Color::None
+ << "run with \"--" DOCTEST_OPTIONS_PREFIX_DISPLAY "help\" for options\n";
+ }
}
void printHelp() {
@@ -5693,12 +6082,18 @@ namespace {
<< Whitespace(sizePrefixDisplay*1) << "exits after the tests finish\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "d, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "duration=<bool> "
<< Whitespace(sizePrefixDisplay*1) << "prints the time duration of each test\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "m, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "minimal=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "minimal console output (only failures)\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "q, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "quiet=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "no console output\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nt, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-throw=<bool> "
<< Whitespace(sizePrefixDisplay*1) << "skips exceptions-related assert checks\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ne, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-exitcode=<bool> "
<< Whitespace(sizePrefixDisplay*1) << "returns (or exits) always with success\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nr, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-run=<bool> "
<< Whitespace(sizePrefixDisplay*1) << "skips all runtime doctest operations\n";
+ s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "ni, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-intro=<bool> "
+ << Whitespace(sizePrefixDisplay*1) << "omit the framework intro in the output\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nv, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-version=<bool> "
<< Whitespace(sizePrefixDisplay*1) << "omit the framework version in the output\n";
s << " -" DOCTEST_OPTIONS_PREFIX_DISPLAY "nc, --" DOCTEST_OPTIONS_PREFIX_DISPLAY "no-colors=<bool> "
@@ -5736,22 +6131,6 @@ namespace {
printReporters(getReporters(), "reporters");
}
- void list_query_results() {
- separator_to_stream();
- if(opt.count || opt.list_test_cases) {
- s << Color::Cyan << "[doctest] " << Color::None
- << "unskipped test cases passing the current filters: "
- << g_cs->numTestCasesPassingFilters << "\n";
- } else if(opt.list_test_suites) {
- s << Color::Cyan << "[doctest] " << Color::None
- << "unskipped test cases passing the current filters: "
- << g_cs->numTestCasesPassingFilters << "\n";
- s << Color::Cyan << "[doctest] " << Color::None
- << "test suites with unskipped test cases passing the current filters: "
- << g_cs->numTestSuitesPassingFilters << "\n";
- }
- }
-
// =========================================================================================
// WHAT FOLLOWS ARE OVERRIDES OF THE VIRTUAL METHODS OF THE REPORTER INTERFACE
// =========================================================================================
@@ -5797,9 +6176,15 @@ namespace {
}
}
- void test_run_start() override { printIntro(); }
+ void test_run_start() override {
+ if(!opt.minimal)
+ printIntro();
+ }
void test_run_end(const TestRunStats& p) override {
+ if(opt.minimal && p.numTestCasesFailed == 0)
+ return;
+
separator_to_stream();
s << std::dec;
@@ -5849,7 +6234,7 @@ namespace {
// log the preamble of the test case only if there is something
// else to print - something other than that an assert has failed
if(opt.duration ||
- (st.failure_flags && st.failure_flags != TestCaseFailureReason::AssertFailure))
+ (st.failure_flags && st.failure_flags != static_cast<int>(TestCaseFailureReason::AssertFailure)))
logTestStart();
if(opt.duration)
@@ -5880,6 +6265,7 @@ namespace {
}
void test_case_exception(const TestCaseException& e) override {
+ DOCTEST_LOCK_MUTEX(mutex)
if(tc->m_no_output)
return;
@@ -5904,14 +6290,12 @@ namespace {
}
void subcase_start(const SubcaseSignature& subc) override {
- std::lock_guard<std::mutex> lock(mutex);
subcasesStack.push_back(subc);
++currentSubcaseLevel;
hasLoggedCurrentTestStart = false;
}
void subcase_end() override {
- std::lock_guard<std::mutex> lock(mutex);
--currentSubcaseLevel;
hasLoggedCurrentTestStart = false;
}
@@ -5920,7 +6304,7 @@ namespace {
if((!rb.m_failed && !opt.success) || tc->m_no_output)
return;
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
logTestStart();
@@ -5936,7 +6320,7 @@ namespace {
if(tc->m_no_output)
return;
- std::lock_guard<std::mutex> lock(mutex);
+ DOCTEST_LOCK_MUTEX(mutex)
logTestStart();
@@ -6047,18 +6431,42 @@ namespace {
std::vector<String>& res) {
String filtersString;
if(parseOption(argc, argv, pattern, &filtersString)) {
- // tokenize with "," as a separator
- // cppcheck-suppress strtokCalled
- DOCTEST_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wdeprecated-declarations")
- auto pch = std::strtok(filtersString.c_str(), ","); // modifies the string
- while(pch != nullptr) {
- if(strlen(pch))
- res.push_back(pch);
- // uses the strtok() internal state to go to the next token
- // cppcheck-suppress strtokCalled
- pch = std::strtok(nullptr, ",");
+ // tokenize with "," as a separator, unless escaped with backslash
+ std::ostringstream s;
+ auto flush = [&s, &res]() {
+ auto string = s.str();
+ if(string.size() > 0) {
+ res.push_back(string.c_str());
+ }
+ s.str("");
+ };
+
+ bool seenBackslash = false;
+ const char* current = filtersString.c_str();
+ const char* end = current + strlen(current);
+ while(current != end) {
+ char character = *current++;
+ if(seenBackslash) {
+ seenBackslash = false;
+ if(character == ',' || character == '\\') {
+ s.put(character);
+ continue;
+ }
+ s.put('\\');
+ }
+ if(character == '\\') {
+ seenBackslash = true;
+ } else if(character == ',') {
+ flush();
+ } else {
+ s.put(character);
+ }
+ }
+
+ if(seenBackslash) {
+ s.put('\\');
}
- DOCTEST_CLANG_SUPPRESS_WARNING_POP
+ flush();
return true;
}
return false;
@@ -6077,30 +6485,30 @@ namespace {
if(!parseOption(argc, argv, pattern, &parsedValue))
return false;
- if(type == 0) {
+ if(type) {
+ // integer
+ // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
+ int theInt = std::atoi(parsedValue.c_str());
+ if (theInt != 0) {
+ res = theInt; //!OCLINT parameter reassignment
+ return true;
+ }
+ } else {
// boolean
- const char positive[][5] = {"1", "true", "on", "yes"}; // 5 - strlen("true") + 1
- const char negative[][6] = {"0", "false", "off", "no"}; // 6 - strlen("false") + 1
+ const char positive[][5] = { "1", "true", "on", "yes" }; // 5 - strlen("true") + 1
+ const char negative[][6] = { "0", "false", "off", "no" }; // 6 - strlen("false") + 1
// if the value matches any of the positive/negative possibilities
- for(unsigned i = 0; i < 4; i++) {
- if(parsedValue.compare(positive[i], true) == 0) {
+ for (unsigned i = 0; i < 4; i++) {
+ if (parsedValue.compare(positive[i], true) == 0) {
res = 1; //!OCLINT parameter reassignment
return true;
}
- if(parsedValue.compare(negative[i], true) == 0) {
+ if (parsedValue.compare(negative[i], true) == 0) {
res = 0; //!OCLINT parameter reassignment
return true;
}
}
- } else {
- // integer
- // TODO: change this to use std::stoi or something else! currently it uses undefined behavior - assumes '0' on failed parse...
- int theInt = std::atoi(parsedValue.c_str()); // NOLINT
- if(theInt != 0) {
- res = theInt; //!OCLINT parameter reassignment
- return true;
- }
}
return false;
}
@@ -6191,9 +6599,12 @@ void Context::parseArgs(int argc, const char* const* argv, bool withDefaults) {
DOCTEST_PARSE_AS_BOOL_OR_FLAG("case-sensitive", "cs", case_sensitive, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("exit", "e", exit, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("duration", "d", duration, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("minimal", "m", minimal, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("quiet", "q", quiet, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-throw", "nt", no_throw, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-exitcode", "ne", no_exitcode, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-run", "nr", no_run, false);
+ DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-intro", "ni", no_intro, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-version", "nv", no_version, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("no-colors", "nc", no_colors, false);
DOCTEST_PARSE_AS_BOOL_OR_FLAG("force-colors", "fc", force_colors, false);
@@ -6257,10 +6668,14 @@ void Context::clearFilters() {
curr.clear();
}
-// allows the user to override procedurally the int/bool options from the command line
+// allows the user to override procedurally the bool options from the command line
+void Context::setOption(const char* option, bool value) {
+ setOption(option, value ? "true" : "false");
+}
+
+// allows the user to override procedurally the int options from the command line
void Context::setOption(const char* option, int value) {
setOption(option, toString(value).c_str());
- // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
}
// allows the user to override procedurally the string options from the command line
@@ -6277,6 +6692,31 @@ void Context::setAsDefaultForAssertsOutOfTestCases() { g_cs = p; }
void Context::setAssertHandler(detail::assert_handler ah) { p->ah = ah; }
+void Context::setCout(std::ostream* out) { p->cout = out; }
+
+static class DiscardOStream : public std::ostream
+{
+private:
+ class : public std::streambuf
+ {
+ private:
+ // allowing some buffering decreases the amount of calls to overflow
+ char buf[1024];
+
+ protected:
+ std::streamsize xsputn(const char_type*, std::streamsize count) override { return count; }
+
+ int_type overflow(int_type ch) override {
+ setp(std::begin(buf), std::end(buf));
+ return traits_type::not_eof(ch);
+ }
+ } discardBuf;
+
+public:
+ DiscardOStream()
+ : std::ostream(&discardBuf) {}
+} discardOut;
+
// the main function that does all the filtering and test running
int Context::run() {
using namespace detail;
@@ -6290,15 +6730,18 @@ int Context::run() {
g_no_colors = p->no_colors;
p->resetRunData();
- // stdout by default
- p->cout = &std::cout;
- p->cerr = &std::cerr;
-
- // or to a file if specified
std::fstream fstr;
- if(p->out.size()) {
- fstr.open(p->out.c_str(), std::fstream::out);
- p->cout = &fstr;
+ if(p->cout == nullptr) {
+ if(p->quiet) {
+ p->cout = &discardOut;
+ } else if(p->out.size()) {
+ // to a file if specified
+ fstr.open(p->out.c_str(), std::fstream::out);
+ p->cout = &fstr;
+ } else {
+ // stdout by default
+ p->cout = &std::cout;
+ }
}
FatalConditionHandler::allocateAltStackMem();
@@ -6370,7 +6813,7 @@ int Context::run() {
// random_shuffle implementation
const auto first = &testArray[0];
for(size_t i = testArray.size() - 1; i > 0; --i) {
- int idxToSwap = std::rand() % (i + 1); // NOLINT
+ int idxToSwap = std::rand() % (i + 1);
const auto temp = first[i];
@@ -6457,7 +6900,7 @@ int Context::run() {
p->numAssertsFailedCurrentTest_atomic = 0;
p->numAssertsCurrentTest_atomic = 0;
- p->subcasesPassed.clear();
+ p->fullyTraversedSubcases.clear();
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_start, tc);
@@ -6467,9 +6910,10 @@ int Context::run() {
do {
// reset some of the fields for subcases (except for the set of fully passed ones)
- p->should_reenter = false;
- p->subcasesCurrentMaxLevel = 0;
- p->subcasesStack.clear();
+ p->reachedLeaf = false;
+ // May not be empty if previous subcase exited via exception.
+ p->subcaseStack.clear();
+ p->currentSubcaseDepth = 0;
p->shouldLogCurrentException = true;
@@ -6503,9 +6947,9 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP
p->failure_flags |= TestCaseFailureReason::TooManyFailedAsserts;
}
- if(p->should_reenter && run_test)
+ if(!p->nextSubcaseStack.empty() && run_test)
DOCTEST_ITERATE_THROUGH_REPORTERS(test_case_reenter, tc);
- if(!p->should_reenter)
+ if(p->nextSubcaseStack.empty())
run_test = false;
} while(run_test);
@@ -6531,17 +6975,10 @@ DOCTEST_MSVC_SUPPRESS_WARNING_POP
DOCTEST_ITERATE_THROUGH_REPORTERS(report_query, qdata);
}
- // see these issues on the reasoning for this:
- // - https://github.com/onqtam/doctest/issues/143#issuecomment-414418903
- // - https://github.com/onqtam/doctest/issues/126
- auto DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS = []() DOCTEST_NOINLINE
- { std::cout << std::string(); };
- DOCTEST_FIX_FOR_MACOS_LIBCPP_IOSFWD_STRING_LINK_ERRORS();
-
return cleanup_and_return();
}
-IReporter::~IReporter() = default;
+DOCTEST_DEFINE_INTERFACE(IReporter)
int IReporter::get_num_active_contexts() { return detail::g_infoContexts.size(); }
const IContextScope* const* IReporter::get_active_contexts() {
@@ -6576,5 +7013,7 @@ DOCTEST_CLANG_SUPPRESS_WARNING_POP
DOCTEST_MSVC_SUPPRESS_WARNING_POP
DOCTEST_GCC_SUPPRESS_WARNING_POP
+DOCTEST_SUPPRESS_COMMON_WARNINGS_POP
+
#endif // DOCTEST_LIBRARY_IMPLEMENTATION
#endif // DOCTEST_CONFIG_IMPLEMENT
diff --git a/thirdparty/enet/godot.cpp b/thirdparty/enet/godot.cpp
index 93d3b3bbff..d2fcc4642e 100644
--- a/thirdparty/enet/godot.cpp
+++ b/thirdparty/enet/godot.cpp
@@ -259,7 +259,7 @@ public:
class ENetDTLSServer : public ENetGodotSocket {
Ref<DTLSServer> server;
Ref<UDPServer> udp_server;
- Map<String, Ref<PacketPeerDTLS>> peers;
+ HashMap<String, Ref<PacketPeerDTLS>> peers;
int last_service = 0;
IPAddress local_address;
@@ -331,15 +331,16 @@ public:
List<String> remove;
Error err = ERR_BUSY;
// TODO this needs to be fair!
- for (Map<String, Ref<PacketPeerDTLS>>::Element *E = peers.front(); E; E = E->next()) {
- Ref<PacketPeerDTLS> peer = E->get();
+
+ for (KeyValue<String, Ref<PacketPeerDTLS>> & E : peers) {
+ Ref<PacketPeerDTLS> peer = E.value;
peer->poll();
if (peer->get_status() == PacketPeerDTLS::STATUS_HANDSHAKING) {
continue;
} else if (peer->get_status() != PacketPeerDTLS::STATUS_CONNECTED) {
// Peer disconnected, removing it.
- remove.push_back(E->key());
+ remove.push_back(E.key);
continue;
}
@@ -348,12 +349,12 @@ public:
err = peer->get_packet(&buffer, r_read);
if (err != OK || p_len < r_read) {
// Something wrong with this peer, removing it.
- remove.push_back(E->key());
+ remove.push_back(E.key);
err = FAILED;
continue;
}
- Vector<String> s = E->key().rsplit(":", false, 1);
+ Vector<String> s = E.key.rsplit(":", false, 1);
ERR_CONTINUE(s.size() != 2); // BUG!
memcpy(p_buffer, buffer, r_read);
@@ -376,8 +377,8 @@ public:
}
void close() {
- for (Map<String, Ref<PacketPeerDTLS>>::Element *E = peers.front(); E; E = E->next()) {
- E->get()->disconnect_from_peer();
+ for (KeyValue<String, Ref<PacketPeerDTLS>> &E : peers) {
+ E.value->disconnect_from_peer();
}
peers.clear();
udp_server->stop();
diff --git a/thirdparty/etcpak/AUTHORS.txt b/thirdparty/etcpak/AUTHORS.txt
index e7bae62c85..675b4eb2a9 100644
--- a/thirdparty/etcpak/AUTHORS.txt
+++ b/thirdparty/etcpak/AUTHORS.txt
@@ -1,3 +1,5 @@
Bartosz Taudul <wolf@nereid.pl>
Daniel Jungmann <el.3d.source@gmail.com>
Florian Penzkofer <fp@nullptr.de>
+Jae-Ho Nah <nahjaeho@gmail.com>
+Marcin Åawicki <marcin.lawicki@gmail.com>
diff --git a/thirdparty/etcpak/LICENSE.txt b/thirdparty/etcpak/LICENSE.txt
index 59e85d6ea5..9c71039b9b 100644
--- a/thirdparty/etcpak/LICENSE.txt
+++ b/thirdparty/etcpak/LICENSE.txt
@@ -1,6 +1,6 @@
etcpak, an extremely fast ETC compression utility (https://github.com/wolfpld/etcpak)
-Copyright (c) 2013-2021, Bartosz Taudul <wolf@nereid.pl>
+Copyright (c) 2013-2022, Bartosz Taudul <wolf@nereid.pl>
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/etcpak/ProcessRGB.cpp b/thirdparty/etcpak/ProcessRGB.cpp
index d60164bcc8..4dc3bf23af 100644
--- a/thirdparty/etcpak/ProcessRGB.cpp
+++ b/thirdparty/etcpak/ProcessRGB.cpp
@@ -28,6 +28,10 @@
# define _bswap64(x) __builtin_bswap64(x)
#endif
+static const uint32_t MaxError = 1065369600; // ((38+76+14) * 255)^2
+// common T-/H-mode table
+static uint8_t tableTH[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
+
// thresholds for the early compression-mode decision scheme
// default: 0.03, 0.09, and 0.38
float ecmd_threshold[3] = { 0.03f, 0.09f, 0.38f };
@@ -36,13 +40,17 @@ static const uint8_t ModeUndecided = 0;
static const uint8_t ModePlanar = 0x1;
static const uint8_t ModeTH = 0x2;
+const unsigned int R = 2;
+const unsigned int G = 1;
+const unsigned int B = 0;
+
struct Luma
{
#ifdef __AVX2__
float max, min;
uint8_t minIdx = 255, maxIdx = 255;
__m128i luma8;
-#elif defined __ARM_NEON
+#elif defined __ARM_NEON && defined __aarch64__
float max, min;
uint8_t minIdx = 255, maxIdx = 255;
uint8x16_t luma8;
@@ -52,8 +60,206 @@ struct Luma
#endif
};
+#ifdef __AVX2__
+struct Plane
+{
+ uint64_t plane;
+ uint64_t error;
+ __m256i sum4;
+};
+#endif
+
+#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__)
+struct Channels
+{
+#ifdef __AVX2__
+ __m128i r8, g8, b8;
+#elif defined __ARM_NEON && defined __aarch64__
+ uint8x16x2_t r, g, b;
+#endif
+};
+#endif
+
namespace
{
+static etcpak_force_inline uint8_t clamp( uint8_t min, int16_t val, uint8_t max )
+{
+ return val < min ? min : ( val > max ? max : val );
+}
+
+static etcpak_force_inline uint8_t clampMin( uint8_t min, int16_t val )
+{
+ return val < min ? min : val;
+}
+
+static etcpak_force_inline uint8_t clampMax( int16_t val, uint8_t max )
+{
+ return val > max ? max : val;
+}
+
+// slightly faster than std::sort
+static void insertionSort( uint8_t* arr1, uint8_t* arr2 )
+{
+ for( uint8_t i = 1; i < 16; ++i )
+ {
+ uint8_t value = arr1[i];
+ uint8_t hole = i;
+
+ for( ; hole > 0 && value < arr1[hole - 1]; --hole )
+ {
+ arr1[hole] = arr1[hole - 1];
+ arr2[hole] = arr2[hole - 1];
+ }
+ arr1[hole] = value;
+ arr2[hole] = i;
+ }
+}
+
+//converts indices from |a0|a1|e0|e1|i0|i1|m0|m1|b0|b1|f0|f1|j0|j1|n0|n1|c0|c1|g0|g1|k0|k1|o0|o1|d0|d1|h0|h1|l0|l1|p0|p1| previously used by T- and H-modes
+// into |p0|o0|n0|m0|l0|k0|j0|i0|h0|g0|f0|e0|d0|c0|b0|a0|p1|o1|n1|m1|l1|k1|j1|i1|h1|g1|f1|e1|d1|c1|b1|a1| which should be used for all modes.
+// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
+static etcpak_force_inline int indexConversion( int pixelIndices )
+{
+ int correctIndices = 0;
+ int LSB[4][4];
+ int MSB[4][4];
+ int shift = 0;
+ for( int y = 3; y >= 0; y-- )
+ {
+ for( int x = 3; x >= 0; x-- )
+ {
+ LSB[x][y] = ( pixelIndices >> shift ) & 1;
+ shift++;
+ MSB[x][y] = ( pixelIndices >> shift ) & 1;
+ shift++;
+ }
+ }
+ shift = 0;
+ for( int x = 0; x < 4; x++ )
+ {
+ for( int y = 0; y < 4; y++ )
+ {
+ correctIndices |= ( LSB[x][y] << shift );
+ correctIndices |= ( MSB[x][y] << ( 16 + shift ) );
+ shift++;
+ }
+ }
+ return correctIndices;
+}
+
+// Swapping two RGB-colors
+// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
+static etcpak_force_inline void swapColors( uint8_t( colors )[2][3] )
+{
+ uint8_t temp = colors[0][R];
+ colors[0][R] = colors[1][R];
+ colors[1][R] = temp;
+
+ temp = colors[0][G];
+ colors[0][G] = colors[1][G];
+ colors[1][G] = temp;
+
+ temp = colors[0][B];
+ colors[0][B] = colors[1][B];
+ colors[1][B] = temp;
+}
+
+
+// calculates quantized colors for T or H modes
+void compressColor( uint8_t( currColor )[2][3], uint8_t( quantColor )[2][3], bool t_mode )
+{
+ if( t_mode )
+ {
+ quantColor[0][R] = clampMax( 15 * ( currColor[0][R] + 8 ) / 255, 15 );
+ quantColor[0][G] = clampMax( 15 * ( currColor[0][G] + 8 ) / 255, 15 );
+ quantColor[0][B] = clampMax( 15 * ( currColor[0][B] + 8 ) / 255, 15 );
+ }
+ else // clamped to [1,14] to get a wider range
+ {
+ quantColor[0][R] = clamp( 1, 15 * ( currColor[0][R] + 8 ) / 255, 14 );
+ quantColor[0][G] = clamp( 1, 15 * ( currColor[0][G] + 8 ) / 255, 14 );
+ quantColor[0][B] = clamp( 1, 15 * ( currColor[0][B] + 8 ) / 255, 14 );
+ }
+
+ // clamped to [1,14] to get a wider range
+ quantColor[1][R] = clamp( 1, 15 * ( currColor[1][R] + 8 ) / 255, 14 );
+ quantColor[1][G] = clamp( 1, 15 * ( currColor[1][G] + 8 ) / 255, 14 );
+ quantColor[1][B] = clamp( 1, 15 * ( currColor[1][B] + 8 ) / 255, 14 );
+}
+
+// three decoding functions come from ETCPACK v2.74 and are slightly changed.
+static etcpak_force_inline void decompressColor( uint8_t( colorsRGB444 )[2][3], uint8_t( colors )[2][3] )
+{
+ // The color should be retrieved as:
+ //
+ // c = round(255/(r_bits^2-1))*comp_color
+ //
+ // This is similar to bit replication
+ //
+ // Note -- this code only work for bit replication from 4 bits and up --- 3 bits needs
+ // two copy operations.
+ colors[0][R] = ( colorsRGB444[0][R] << 4 ) | colorsRGB444[0][R];
+ colors[0][G] = ( colorsRGB444[0][G] << 4 ) | colorsRGB444[0][G];
+ colors[0][B] = ( colorsRGB444[0][B] << 4 ) | colorsRGB444[0][B];
+ colors[1][R] = ( colorsRGB444[1][R] << 4 ) | colorsRGB444[1][R];
+ colors[1][G] = ( colorsRGB444[1][G] << 4 ) | colorsRGB444[1][G];
+ colors[1][B] = ( colorsRGB444[1][B] << 4 ) | colorsRGB444[1][B];
+}
+
+// calculates the paint colors from the block colors
+// using a distance d and one of the H- or T-patterns.
+static void calculatePaintColors59T( uint8_t d, uint8_t( colors )[2][3], uint8_t( pColors )[4][3] )
+{
+ //////////////////////////////////////////////
+ //
+ // C3 C1 C4----C1---C2
+ // | | |
+ // | | |
+ // |-------| |
+ // | | |
+ // | | |
+ // C4 C2 C3
+ //
+ //////////////////////////////////////////////
+
+ // C4
+ pColors[3][R] = clampMin( 0, colors[1][R] - tableTH[d] );
+ pColors[3][G] = clampMin( 0, colors[1][G] - tableTH[d] );
+ pColors[3][B] = clampMin( 0, colors[1][B] - tableTH[d] );
+
+ // C3
+ pColors[0][R] = colors[0][R];
+ pColors[0][G] = colors[0][G];
+ pColors[0][B] = colors[0][B];
+ // C2
+ pColors[1][R] = clampMax( colors[1][R] + tableTH[d], 255 );
+ pColors[1][G] = clampMax( colors[1][G] + tableTH[d], 255 );
+ pColors[1][B] = clampMax( colors[1][B] + tableTH[d], 255 );
+ // C1
+ pColors[2][R] = colors[1][R];
+ pColors[2][G] = colors[1][G];
+ pColors[2][B] = colors[1][B];
+}
+
+static void calculatePaintColors58H( uint8_t d, uint8_t( colors )[2][3], uint8_t( pColors )[4][3] )
+{
+ pColors[3][R] = clampMin( 0, colors[1][R] - tableTH[d] );
+ pColors[3][G] = clampMin( 0, colors[1][G] - tableTH[d] );
+ pColors[3][B] = clampMin( 0, colors[1][B] - tableTH[d] );
+
+ // C1
+ pColors[0][R] = clampMax( colors[0][R] + tableTH[d], 255 );
+ pColors[0][G] = clampMax( colors[0][G] + tableTH[d], 255 );
+ pColors[0][B] = clampMax( colors[0][B] + tableTH[d], 255 );
+ // C2
+ pColors[1][R] = clampMin( 0, colors[0][R] - tableTH[d] );
+ pColors[1][G] = clampMin( 0, colors[0][G] - tableTH[d] );
+ pColors[1][B] = clampMin( 0, colors[0][B] - tableTH[d] );
+ // C3
+ pColors[2][R] = clampMax( colors[1][R] + tableTH[d], 255 );
+ pColors[2][G] = clampMax( colors[1][G] + tableTH[d], 255 );
+ pColors[2][B] = clampMax( colors[1][B] + tableTH[d], 255 );
+}
#if defined _MSC_VER && !defined __clang__
static etcpak_force_inline unsigned long _bit_scan_forward( unsigned long mask )
@@ -586,127 +792,107 @@ static etcpak_force_inline __m128i r6g7b6_AVX2(__m128 cof, __m128 chf, __m128 cv
return _mm_shuffle_epi8(cohv5, _mm_setr_epi8(6, 5, 4, -1, 2, 1, 0, -1, 10, 9, 8, -1, -1, -1, -1, -1));
}
-struct Plane
+static etcpak_force_inline Plane Planar_AVX2( const Channels& ch, uint8_t& mode, bool useHeuristics )
{
- uint64_t plane;
- uint64_t error;
- __m256i sum4;
-};
-
-static etcpak_force_inline Plane Planar_AVX2( const uint8_t* src, const uint8_t mode )
-{
- __m128i d0 = _mm_loadu_si128(((__m128i*)src) + 0);
- __m128i d1 = _mm_loadu_si128(((__m128i*)src) + 1);
- __m128i d2 = _mm_loadu_si128(((__m128i*)src) + 2);
- __m128i d3 = _mm_loadu_si128(((__m128i*)src) + 3);
-
- __m128i rgb0 = _mm_shuffle_epi8(d0, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1));
- __m128i rgb1 = _mm_shuffle_epi8(d1, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1));
- __m128i rgb2 = _mm_shuffle_epi8(d2, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1));
- __m128i rgb3 = _mm_shuffle_epi8(d3, _mm_setr_epi8(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, -1, -1, -1, -1));
-
- __m128i rg0 = _mm_unpacklo_epi32(rgb0, rgb1);
- __m128i rg1 = _mm_unpacklo_epi32(rgb2, rgb3);
- __m128i b0 = _mm_unpackhi_epi32(rgb0, rgb1);
- __m128i b1 = _mm_unpackhi_epi32(rgb2, rgb3);
-
- // swap channels
- __m128i b8 = _mm_unpacklo_epi64(rg0, rg1);
- __m128i g8 = _mm_unpackhi_epi64(rg0, rg1);
- __m128i r8 = _mm_unpacklo_epi64(b0, b1);
+ __m128i t0 = _mm_sad_epu8( ch.r8, _mm_setzero_si128() );
+ __m128i t1 = _mm_sad_epu8( ch.g8, _mm_setzero_si128() );
+ __m128i t2 = _mm_sad_epu8( ch.b8, _mm_setzero_si128() );
- __m128i t0 = _mm_sad_epu8(r8, _mm_setzero_si128());
- __m128i t1 = _mm_sad_epu8(g8, _mm_setzero_si128());
- __m128i t2 = _mm_sad_epu8(b8, _mm_setzero_si128());
+ __m128i r8s = _mm_shuffle_epi8( ch.r8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) );
+ __m128i g8s = _mm_shuffle_epi8( ch.g8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) );
+ __m128i b8s = _mm_shuffle_epi8( ch.b8, _mm_set_epi8( 0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0 ) );
- __m128i r8s = _mm_shuffle_epi8(r8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0));
- __m128i g8s = _mm_shuffle_epi8(g8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0));
- __m128i b8s = _mm_shuffle_epi8(b8, _mm_set_epi8(0xF, 0xE, 0xB, 0xA, 0x7, 0x6, 0x3, 0x2, 0xD, 0xC, 0x9, 0x8, 0x5, 0x4, 0x1, 0x0));
+ __m128i s0 = _mm_sad_epu8( r8s, _mm_setzero_si128() );
+ __m128i s1 = _mm_sad_epu8( g8s, _mm_setzero_si128() );
+ __m128i s2 = _mm_sad_epu8( b8s, _mm_setzero_si128() );
- __m128i s0 = _mm_sad_epu8(r8s, _mm_setzero_si128());
- __m128i s1 = _mm_sad_epu8(g8s, _mm_setzero_si128());
- __m128i s2 = _mm_sad_epu8(b8s, _mm_setzero_si128());
+ __m256i sr0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t0 ), s0, 1 );
+ __m256i sg0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t1 ), s1, 1 );
+ __m256i sb0 = _mm256_insertf128_si256( _mm256_castsi128_si256( t2 ), s2, 1 );
- __m256i sr0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t0), s0, 1);
- __m256i sg0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t1), s1, 1);
- __m256i sb0 = _mm256_insertf128_si256(_mm256_castsi128_si256(t2), s2, 1);
+ __m256i sr1 = _mm256_slli_epi64( sr0, 32 );
+ __m256i sg1 = _mm256_slli_epi64( sg0, 16 );
- __m256i sr1 = _mm256_slli_epi64(sr0, 32);
- __m256i sg1 = _mm256_slli_epi64(sg0, 16);
+ __m256i srb = _mm256_or_si256( sr1, sb0 );
+ __m256i srgb = _mm256_or_si256( srb, sg1 );
- __m256i srb = _mm256_or_si256(sr1, sb0);
- __m256i srgb = _mm256_or_si256(srb, sg1);
+ if( mode != ModePlanar && useHeuristics )
+ {
+ Plane plane;
+ plane.sum4 = _mm256_permute4x64_epi64( srgb, _MM_SHUFFLE( 2, 3, 0, 1 ) );
+ return plane;
+ }
- __m128i t3 = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(t0), _mm_castsi128_ps(t1), _MM_SHUFFLE(2, 0, 2, 0)));
- __m128i t4 = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3, 1, 2, 0));
- __m128i t5 = _mm_hadd_epi32(t3, t4);
- __m128i t6 = _mm_shuffle_epi32(t5, _MM_SHUFFLE(1, 1, 1, 1));
- __m128i t7 = _mm_shuffle_epi32(t5, _MM_SHUFFLE(2, 2, 2, 2));
+ __m128i t3 = _mm_castps_si128( _mm_shuffle_ps( _mm_castsi128_ps( t0 ), _mm_castsi128_ps( t1 ), _MM_SHUFFLE( 2, 0, 2, 0 ) ) );
+ __m128i t4 = _mm_shuffle_epi32( t2, _MM_SHUFFLE( 3, 1, 2, 0 ) );
+ __m128i t5 = _mm_hadd_epi32( t3, t4 );
+ __m128i t6 = _mm_shuffle_epi32( t5, _MM_SHUFFLE( 1, 1, 1, 1 ) );
+ __m128i t7 = _mm_shuffle_epi32( t5, _MM_SHUFFLE( 2, 2, 2, 2 ) );
- __m256i sr = _mm256_broadcastw_epi16(t5);
- __m256i sg = _mm256_broadcastw_epi16(t6);
- __m256i sb = _mm256_broadcastw_epi16(t7);
+ __m256i sr = _mm256_broadcastw_epi16( t5 );
+ __m256i sg = _mm256_broadcastw_epi16( t6 );
+ __m256i sb = _mm256_broadcastw_epi16( t7 );
- __m256i r08 = _mm256_cvtepu8_epi16(r8);
- __m256i g08 = _mm256_cvtepu8_epi16(g8);
- __m256i b08 = _mm256_cvtepu8_epi16(b8);
+ __m256i r08 = _mm256_cvtepu8_epi16( ch.r8 );
+ __m256i g08 = _mm256_cvtepu8_epi16( ch.g8 );
+ __m256i b08 = _mm256_cvtepu8_epi16( ch.b8 );
- __m256i r16 = _mm256_slli_epi16(r08, 4);
- __m256i g16 = _mm256_slli_epi16(g08, 4);
- __m256i b16 = _mm256_slli_epi16(b08, 4);
+ __m256i r16 = _mm256_slli_epi16( r08, 4 );
+ __m256i g16 = _mm256_slli_epi16( g08, 4 );
+ __m256i b16 = _mm256_slli_epi16( b08, 4 );
- __m256i difR0 = _mm256_sub_epi16(r16, sr);
- __m256i difG0 = _mm256_sub_epi16(g16, sg);
- __m256i difB0 = _mm256_sub_epi16(b16, sb);
+ __m256i difR0 = _mm256_sub_epi16( r16, sr );
+ __m256i difG0 = _mm256_sub_epi16( g16, sg );
+ __m256i difB0 = _mm256_sub_epi16( b16, sb );
- __m256i difRyz = _mm256_madd_epi16(difR0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255));
- __m256i difGyz = _mm256_madd_epi16(difG0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255));
- __m256i difByz = _mm256_madd_epi16(difB0, _mm256_set_epi16(255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255));
+ __m256i difRyz = _mm256_madd_epi16( difR0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) );
+ __m256i difGyz = _mm256_madd_epi16( difG0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) );
+ __m256i difByz = _mm256_madd_epi16( difB0, _mm256_set_epi16( 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255, 255, 85, -85, -255 ) );
- __m256i difRxz = _mm256_madd_epi16(difR0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255));
- __m256i difGxz = _mm256_madd_epi16(difG0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255));
- __m256i difBxz = _mm256_madd_epi16(difB0, _mm256_set_epi16(255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255));
+ __m256i difRxz = _mm256_madd_epi16( difR0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) );
+ __m256i difGxz = _mm256_madd_epi16( difG0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) );
+ __m256i difBxz = _mm256_madd_epi16( difB0, _mm256_set_epi16( 255, 255, 255, 255, 85, 85, 85, 85, -85, -85, -85, -85, -255, -255, -255, -255 ) );
- __m256i difRGyz = _mm256_hadd_epi32(difRyz, difGyz);
- __m256i difByzxz = _mm256_hadd_epi32(difByz, difBxz);
+ __m256i difRGyz = _mm256_hadd_epi32( difRyz, difGyz );
+ __m256i difByzxz = _mm256_hadd_epi32( difByz, difBxz );
- __m256i difRGxz = _mm256_hadd_epi32(difRxz, difGxz);
+ __m256i difRGxz = _mm256_hadd_epi32( difRxz, difGxz );
- __m128i sumRGyz = _mm_add_epi32(_mm256_castsi256_si128(difRGyz), _mm256_extracti128_si256(difRGyz, 1));
- __m128i sumByzxz = _mm_add_epi32(_mm256_castsi256_si128(difByzxz), _mm256_extracti128_si256(difByzxz, 1));
- __m128i sumRGxz = _mm_add_epi32(_mm256_castsi256_si128(difRGxz), _mm256_extracti128_si256(difRGxz, 1));
+ __m128i sumRGyz = _mm_add_epi32( _mm256_castsi256_si128( difRGyz ), _mm256_extracti128_si256( difRGyz, 1 ) );
+ __m128i sumByzxz = _mm_add_epi32( _mm256_castsi256_si128( difByzxz ), _mm256_extracti128_si256( difByzxz, 1 ) );
+ __m128i sumRGxz = _mm_add_epi32( _mm256_castsi256_si128( difRGxz ), _mm256_extracti128_si256( difRGxz, 1 ) );
- __m128i sumRGByz = _mm_hadd_epi32(sumRGyz, sumByzxz);
- __m128i sumRGByzxz = _mm_hadd_epi32(sumRGxz, sumByzxz);
+ __m128i sumRGByz = _mm_hadd_epi32( sumRGyz, sumByzxz );
+ __m128i sumRGByzxz = _mm_hadd_epi32( sumRGxz, sumByzxz );
- __m128i sumRGBxz = _mm_shuffle_epi32(sumRGByzxz, _MM_SHUFFLE(2, 3, 1, 0));
+ __m128i sumRGBxz = _mm_shuffle_epi32( sumRGByzxz, _MM_SHUFFLE( 2, 3, 1, 0 ) );
- __m128 sumRGByzf = _mm_cvtepi32_ps(sumRGByz);
- __m128 sumRGBxzf = _mm_cvtepi32_ps(sumRGBxz);
+ __m128 sumRGByzf = _mm_cvtepi32_ps( sumRGByz );
+ __m128 sumRGBxzf = _mm_cvtepi32_ps( sumRGBxz );
- const float value = (255 * 255 * 8.0f + 85 * 85 * 8.0f) * 16.0f;
+ const float value = ( 255 * 255 * 8.0f + 85 * 85 * 8.0f ) * 16.0f;
- __m128 scale = _mm_set1_ps(-4.0f / value);
+ __m128 scale = _mm_set1_ps( -4.0f / value );
- __m128 af = _mm_mul_ps(sumRGBxzf, scale);
- __m128 bf = _mm_mul_ps(sumRGByzf, scale);
+ __m128 af = _mm_mul_ps( sumRGBxzf, scale );
+ __m128 bf = _mm_mul_ps( sumRGByzf, scale );
- __m128 df = _mm_mul_ps(_mm_cvtepi32_ps(t5), _mm_set1_ps(4.0f / 16.0f));
+ __m128 df = _mm_mul_ps( _mm_cvtepi32_ps( t5 ), _mm_set1_ps( 4.0f / 16.0f ) );
// calculating the three colors RGBO, RGBH, and RGBV. RGB = df - af * x - bf * y;
- __m128 cof0 = _mm_fnmadd_ps(af, _mm_set1_ps(-255.0f), _mm_fnmadd_ps(bf, _mm_set1_ps(-255.0f), df));
- __m128 chf0 = _mm_fnmadd_ps(af, _mm_set1_ps( 425.0f), _mm_fnmadd_ps(bf, _mm_set1_ps(-255.0f), df));
- __m128 cvf0 = _mm_fnmadd_ps(af, _mm_set1_ps(-255.0f), _mm_fnmadd_ps(bf, _mm_set1_ps( 425.0f), df));
+ __m128 cof0 = _mm_fnmadd_ps( af, _mm_set1_ps( -255.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( -255.0f ), df ) );
+ __m128 chf0 = _mm_fnmadd_ps( af, _mm_set1_ps( 425.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( -255.0f ), df ) );
+ __m128 cvf0 = _mm_fnmadd_ps( af, _mm_set1_ps( -255.0f ), _mm_fnmadd_ps( bf, _mm_set1_ps( 425.0f ), df ) );
// convert to r6g7b6
- __m128i cohv = r6g7b6_AVX2(cof0, chf0, cvf0);
+ __m128i cohv = r6g7b6_AVX2( cof0, chf0, cvf0 );
- uint64_t rgbho = _mm_extract_epi64(cohv, 0);
- uint32_t rgbv0 = _mm_extract_epi32(cohv, 2);
+ uint64_t rgbho = _mm_extract_epi64( cohv, 0 );
+ uint32_t rgbv0 = _mm_extract_epi32( cohv, 2 );
// Error calculation
uint64_t error = 0;
- if( mode != ModePlanar )
+ if( !useHeuristics )
{
auto ro0 = ( rgbho >> 48 ) & 0x3F;
auto go0 = ( rgbho >> 40 ) & 0x7F;
@@ -820,7 +1006,15 @@ static etcpak_force_inline Plane Planar_AVX2( const uint8_t* src, const uint8_t
Plane plane;
plane.plane = result;
- plane.error = error;
+ if( useHeuristics )
+ {
+ plane.error = 0;
+ mode = ModePlanar;
+ }
+ else
+ {
+ plane.error = error;
+ }
plane.sum4 = _mm256_permute4x64_epi64(srgb, _MM_SHUFFLE(2, 3, 0, 1));
return plane;
@@ -1570,7 +1764,7 @@ static etcpak_force_inline uint8_t convert7(float f)
return (i + 9 - ((i + 9) >> 8) - ((i + 6) >> 8)) >> 2;
}
-static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t* src, const uint8_t mode )
+static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t* src, const uint8_t mode, bool useHeuristics )
{
int32_t r = 0;
int32_t g = 0;
@@ -1645,7 +1839,7 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar( const uint8_t*
// Error calculation
uint64_t error = 0;
- if( ModePlanar != mode )
+ if( ModePlanar != mode && useHeuristics )
{
auto ro0 = coR;
auto go0 = coG;
@@ -1756,7 +1950,7 @@ static etcpak_force_inline int16x8_t Planar_NEON_SumWide( uint8x16_t src )
uint16x4_t accu2 = vpadd_u16( accu4, accu4 );
uint16x4_t accu1 = vpadd_u16( accu2, accu2 );
return vreinterpretq_s16_u16( vcombine_u16( accu1, accu1 ) );
-#else
+#else
return vdupq_n_s16( vaddvq_u16( accu8 ) );
#endif
}
@@ -1783,7 +1977,7 @@ static etcpak_force_inline int16x4_t convert7_NEON( int32x4_t x )
return vshr_n_s16( vsub_s16( vsub_s16( p9, vshr_n_s16( p9, 8 ) ), vshr_n_s16( p6, 8 ) ), 2 );
}
-static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint8_t* src, const uint8_t mode )
+static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint8_t* src, const uint8_t mode, bool useHeuristics )
{
uint8x16x4_t srcBlock = vld4q_u8( src );
@@ -1828,7 +2022,7 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint
int16x4_t c_hvox_g_8 = vorr_s16( vshr_n_s16( c_hvox_g_7, 6 ), vshl_n_s16( c_hvox_g_7, 1 ) );
uint64_t error = 0;
- if( mode != ModePlanar )
+ if( mode != ModePlanar && useHeuristics )
{
int16x4_t rec_gxbr_o = vext_s16( c_hvox_g_8, vget_high_s16( c_hvoo_br_8 ), 3 );
@@ -1924,6 +2118,376 @@ static etcpak_force_inline std::pair<uint64_t, uint64_t> Planar_NEON( const uint
#endif
+#ifdef __AVX2__
+uint32_t calculateErrorTH( bool tMode, uint8_t( colorsRGB444 )[2][3], uint8_t& dist, uint32_t& pixIndices, uint8_t startDist, __m128i r8, __m128i g8, __m128i b8 )
+#else
+uint32_t calculateErrorTH( bool tMode, uint8_t* src, uint8_t( colorsRGB444 )[2][3], uint8_t& dist, uint32_t& pixIndices, uint8_t startDist )
+#endif
+{
+ uint32_t blockErr = 0, bestBlockErr = MaxError;
+
+ uint32_t pixColors;
+ uint8_t possibleColors[4][3];
+ uint8_t colors[2][3];
+
+ decompressColor( colorsRGB444, colors );
+
+#ifdef __AVX2__
+ __m128i reverseMask = _mm_set_epi8( 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 );
+#endif
+
+ // test distances
+ for( uint8_t d = startDist; d < 8; ++d )
+ {
+ if( d >= 2 && dist == d - 2 ) break;
+
+ blockErr = 0;
+ pixColors = 0;
+
+ if( tMode )
+ {
+ calculatePaintColors59T( d, colors, possibleColors );
+ }
+ else
+ {
+ calculatePaintColors58H( d, colors, possibleColors );
+ }
+
+#ifdef __AVX2__
+ // RGB ordering
+ __m128i b8Rev = _mm_shuffle_epi8( b8, reverseMask );
+ __m128i g8Rev = _mm_shuffle_epi8( g8, reverseMask );
+ __m128i r8Rev = _mm_shuffle_epi8( r8, reverseMask );
+
+ // extends 3x128 bits RGB into 3x256 bits RGB for error comparisions
+ static const __m128i zero = _mm_setzero_si128();
+ __m128i b8Lo = _mm_unpacklo_epi8( b8Rev, zero );
+ __m128i g8Lo = _mm_unpacklo_epi8( g8Rev, zero );
+ __m128i r8Lo = _mm_unpacklo_epi8( r8Rev, zero );
+ __m128i b8Hi = _mm_unpackhi_epi8( b8Rev, zero );
+ __m128i g8Hi = _mm_unpackhi_epi8( g8Rev, zero );
+ __m128i r8Hi = _mm_unpackhi_epi8( r8Rev, zero );
+
+ __m256i b8 = _mm256_set_m128i( b8Hi, b8Lo );
+ __m256i g8 = _mm256_set_m128i( g8Hi, g8Lo );
+ __m256i r8 = _mm256_set_m128i( r8Hi, r8Lo );
+
+ // caculates differences between the pixel colrs and the palette colors
+ __m256i diffb = _mm256_abs_epi16( _mm256_sub_epi16( b8, _mm256_set1_epi16( possibleColors[0][B] ) ) );
+ __m256i diffg = _mm256_abs_epi16( _mm256_sub_epi16( g8, _mm256_set1_epi16( possibleColors[0][G] ) ) );
+ __m256i diffr = _mm256_abs_epi16( _mm256_sub_epi16( r8, _mm256_set1_epi16( possibleColors[0][R] ) ) );
+
+ // luma-based error calculations
+ static const __m256i bWeight = _mm256_set1_epi16( 14 );
+ static const __m256i gWeight = _mm256_set1_epi16( 76 );
+ static const __m256i rWeight = _mm256_set1_epi16( 38 );
+
+ diffb = _mm256_mullo_epi16( diffb, bWeight );
+ diffg = _mm256_mullo_epi16( diffg, gWeight );
+ diffr = _mm256_mullo_epi16( diffr, rWeight );
+
+ // obtains the error with the current palette color
+ __m256i lowestPixErr = _mm256_add_epi16( _mm256_add_epi16( diffb, diffg ), diffr );
+
+ // error calucations with the remaining three palette colors
+ static const uint32_t masks[4] = { 0, 0x55555555, 0xAAAAAAAA, 0xFFFFFFFF };
+ for( uint8_t c = 1; c < 4; c++ )
+ {
+ __m256i diffb = _mm256_abs_epi16( _mm256_sub_epi16( b8, _mm256_set1_epi16( possibleColors[c][B] ) ) );
+ __m256i diffg = _mm256_abs_epi16( _mm256_sub_epi16( g8, _mm256_set1_epi16( possibleColors[c][G] ) ) );
+ __m256i diffr = _mm256_abs_epi16( _mm256_sub_epi16( r8, _mm256_set1_epi16( possibleColors[c][R] ) ) );
+
+ diffb = _mm256_mullo_epi16( diffb, bWeight );
+ diffg = _mm256_mullo_epi16( diffg, gWeight );
+ diffr = _mm256_mullo_epi16( diffr, rWeight );
+
+ // error comparison with the previous best color
+ __m256i pixErrors = _mm256_add_epi16( _mm256_add_epi16( diffb, diffg ), diffr );
+ __m256i minErr = _mm256_min_epu16( lowestPixErr, pixErrors );
+ __m256i cmpRes = _mm256_cmpeq_epi16( pixErrors, minErr );
+ lowestPixErr = minErr;
+
+ // update pixel colors
+ uint32_t updPixColors = _mm256_movemask_epi8( cmpRes );
+ uint32_t prevPixColors = pixColors & ~updPixColors;
+ uint32_t mskPixColors = masks[c] & updPixColors;
+ pixColors = prevPixColors | mskPixColors;
+ }
+
+ // accumulate the block error
+ alignas( 32 ) uint16_t pixErr16[16] = { 0, };
+ _mm256_storeu_si256( (__m256i*)pixErr16, lowestPixErr );
+ for( uint8_t p = 0; p < 16; p++ )
+ {
+ blockErr += (int)( pixErr16[p] ) * pixErr16[p];
+ }
+#else
+ for( size_t y = 0; y < 4; ++y )
+ {
+ for( size_t x = 0; x < 4; ++x )
+ {
+ uint32_t bestPixErr = MaxError;
+ pixColors <<= 2; // Make room for next value
+
+ // Loop possible block colors
+ for( uint8_t c = 0; c < 4; ++c )
+ {
+ int diff[3];
+ diff[R] = src[4 * ( x * 4 + y ) + R] - possibleColors[c][R];
+ diff[G] = src[4 * ( x * 4 + y ) + G] - possibleColors[c][G];
+ diff[B] = src[4 * ( x * 4 + y ) + B] - possibleColors[c][B];
+
+ const uint32_t err = 38 * abs( diff[R] ) + 76 * abs( diff[G] ) + 14 * abs( diff[B] );
+ uint32_t pixErr = err * err;
+
+ // Choose best error
+ if( pixErr < bestPixErr )
+ {
+ bestPixErr = pixErr;
+ pixColors ^= ( pixColors & 3 ); // Reset the two first bits
+ pixColors |= c;
+ }
+ }
+ blockErr += bestPixErr;
+ }
+ }
+#endif
+
+ if( blockErr < bestBlockErr )
+ {
+ bestBlockErr = blockErr;
+ dist = d;
+ pixIndices = pixColors;
+ }
+ }
+
+ return bestBlockErr;
+}
+
+
+// main T-/H-mode compression function
+#ifdef __AVX2__
+uint32_t compressBlockTH( uint8_t* src, Luma& l, uint32_t& compressed1, uint32_t& compressed2, bool& tMode, __m128i r8, __m128i g8, __m128i b8 )
+#else
+uint32_t compressBlockTH( uint8_t *src, Luma& l, uint32_t& compressed1, uint32_t& compressed2, bool &tMode )
+#endif
+{
+#ifdef __AVX2__
+ alignas( 8 ) uint8_t luma[16] = { 0, };
+ _mm_storeu_si128 ( (__m128i* )luma, l.luma8 );
+#elif defined __ARM_NEON && defined __aarch64__
+ alignas( 8 ) uint8_t luma[16] = { 0 };
+ vst1q_u8( luma, l.luma8 );
+#else
+ uint8_t* luma = l.val;
+#endif
+
+ uint8_t pixIdx[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ // 1) sorts the pairs of (luma, pix_idx)
+ insertionSort( luma, pixIdx );
+
+ // 2) finds the min (left+right)
+ uint8_t minSumRangeIdx = 0;
+ uint16_t minSumRangeValue;
+ uint16_t sum;
+ static const uint8_t diffBonus[15] = {8, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 8};
+ const int16_t temp = luma[15] - luma[0];
+
+ minSumRangeValue = luma[15] - luma[1] + diffBonus[0];
+ for( uint8_t i = 1; i < 14; i++ )
+ {
+ sum = temp - luma[i+1] + luma[i] + diffBonus[i];
+ if( minSumRangeValue > sum )
+ {
+ minSumRangeValue = sum;
+ minSumRangeIdx = i;
+ }
+ }
+
+ sum = luma[14] - luma[0] + diffBonus[14];
+ if( minSumRangeValue > sum )
+ {
+ minSumRangeValue = sum;
+ minSumRangeIdx = 14;
+ }
+ uint8_t lRange, rRange;
+
+ lRange = luma[minSumRangeIdx] - luma[0];
+ rRange = luma[15] - luma[minSumRangeIdx + 1];
+
+ // 3) sets a proper mode
+ bool swap = false;
+ if( lRange >= rRange )
+ {
+ if( lRange >= rRange * 2 )
+ {
+ swap = true;
+ tMode = true;
+ }
+ }
+ else
+ {
+ if( lRange * 2 <= rRange ) tMode = true;
+ }
+ // 4) calculates the two base colors
+ uint8_t rangeIdx[4] = { pixIdx[0], pixIdx[minSumRangeIdx], pixIdx[minSumRangeIdx + 1], pixIdx[15] };
+
+ uint16_t r[4], g[4], b[4];
+ for( uint8_t i = 0; i < 4; ++i )
+ {
+ uint8_t idx = rangeIdx[i] * 4;
+ b[i] = src[idx];
+ g[i] = src[idx + 1];
+ r[i] = src[idx + 2];
+ }
+
+ uint8_t mid_rgb[2][3];
+ if( swap )
+ {
+ mid_rgb[1][B] = ( b[0] + b[1] ) / 2;
+ mid_rgb[1][G] = ( g[0] + g[1] ) / 2;
+ mid_rgb[1][R] = ( r[0] + r[1] ) / 2;
+
+ uint16_t sum_rgb[3] = { 0, 0, 0 };
+ for( uint8_t i = minSumRangeIdx + 1; i < 16; i++ )
+ {
+ uint8_t idx = pixIdx[i] * 4;
+ sum_rgb[B] += src[idx];
+ sum_rgb[G] += src[idx + 1];
+ sum_rgb[R] += src[idx + 2];
+ }
+ const uint8_t temp = 15 - minSumRangeIdx;
+ mid_rgb[0][B] = sum_rgb[B] / temp;
+ mid_rgb[0][G] = sum_rgb[G] / temp;
+ mid_rgb[0][R] = sum_rgb[R] / temp;
+ }
+ else
+ {
+ mid_rgb[0][B] = (b[0] + b[1]) / 2;
+ mid_rgb[0][G] = (g[0] + g[1]) / 2;
+ mid_rgb[0][R] = (r[0] + r[1]) / 2;
+ if( tMode )
+ {
+ uint16_t sum_rgb[3] = { 0, 0, 0 };
+ for( uint8_t i = minSumRangeIdx + 1; i < 16; i++ )
+ {
+ uint8_t idx = pixIdx[i] * 4;
+ sum_rgb[B] += src[idx];
+ sum_rgb[G] += src[idx + 1];
+ sum_rgb[R] += src[idx + 2];
+ }
+ const uint8_t temp = 15 - minSumRangeIdx;
+ mid_rgb[1][B] = sum_rgb[B] / temp;
+ mid_rgb[1][G] = sum_rgb[G] / temp;
+ mid_rgb[1][R] = sum_rgb[R] / temp;
+ }
+ else
+ {
+ mid_rgb[1][B] = (b[2] + b[3]) / 2;
+ mid_rgb[1][G] = (g[2] + g[3]) / 2;
+ mid_rgb[1][R] = (r[2] + r[3]) / 2;
+ }
+ }
+
+ // 5) sets the start distance index
+ uint32_t startDistCandidate;
+ uint32_t avgDist;
+ if( tMode )
+ {
+ if( swap )
+ {
+ avgDist = ( b[1] - b[0] + g[1] - g[0] + r[1] - r[0] ) / 6;
+ }
+ else
+ {
+ avgDist = ( b[3] - b[2] + g[3] - g[2] + r[3] - r[2] ) / 6;
+ }
+ }
+ else
+ {
+ avgDist = ( b[1] - b[0] + g[1] - g[0] + r[1] - r[0] + b[3] - b[2] + g[3] - g[2] + r[3] - r[2] ) / 12;
+ }
+
+ if( avgDist <= 16)
+ {
+ startDistCandidate = 0;
+ }
+ else if( avgDist <= 23 )
+ {
+ startDistCandidate = 1;
+ }
+ else if( avgDist <= 32 )
+ {
+ startDistCandidate = 2;
+ }
+ else if( avgDist <= 41 )
+ {
+ startDistCandidate = 3;
+ }
+ else
+ {
+ startDistCandidate = 4;
+ }
+
+ uint32_t bestErr = MaxError;
+ uint32_t bestPixIndices;
+ uint8_t bestDist = 10;
+ uint8_t colorsRGB444[2][3];
+ compressColor( mid_rgb, colorsRGB444, tMode );
+ compressed1 = 0;
+
+ // 6) finds the best candidate with the lowest error
+#ifdef __AVX2__
+ // Vectorized ver
+ bestErr = calculateErrorTH( tMode, colorsRGB444, bestDist, bestPixIndices, startDistCandidate, r8, g8, b8 );
+#else
+ // Scalar ver
+ bestErr = calculateErrorTH( tMode, src, colorsRGB444, bestDist, bestPixIndices, startDistCandidate );
+#endif
+
+ // 7) outputs the final T or H block
+ if( tMode )
+ {
+ // Put the compress params into the compression block
+ compressed1 |= ( colorsRGB444[0][R] & 0xf ) << 23;
+ compressed1 |= ( colorsRGB444[0][G] & 0xf ) << 19;
+ compressed1 |= ( colorsRGB444[0][B] ) << 15;
+ compressed1 |= ( colorsRGB444[1][R] ) << 11;
+ compressed1 |= ( colorsRGB444[1][G] ) << 7;
+ compressed1 |= ( colorsRGB444[1][B] ) << 3;
+ compressed1 |= bestDist & 0x7;
+ }
+ else
+ {
+ int bestRGB444ColPacked[2];
+ bestRGB444ColPacked[0] = (colorsRGB444[0][R] << 8) + (colorsRGB444[0][G] << 4) + colorsRGB444[0][B];
+ bestRGB444ColPacked[1] = (colorsRGB444[1][R] << 8) + (colorsRGB444[1][G] << 4) + colorsRGB444[1][B];
+ if( ( bestRGB444ColPacked[0] >= bestRGB444ColPacked[1] ) ^ ( ( bestDist & 1 ) == 1 ) )
+ {
+ swapColors( colorsRGB444 );
+ // Reshuffle pixel indices to to exchange C1 with C3, and C2 with C4
+ bestPixIndices = ( 0x55555555 & bestPixIndices ) | ( 0xaaaaaaaa & ( ~bestPixIndices ) );
+ }
+
+ // Put the compress params into the compression block
+ compressed1 |= ( colorsRGB444[0][R] & 0xf ) << 22;
+ compressed1 |= ( colorsRGB444[0][G] & 0xf ) << 18;
+ compressed1 |= ( colorsRGB444[0][B] & 0xf ) << 14;
+ compressed1 |= ( colorsRGB444[1][R] & 0xf ) << 10;
+ compressed1 |= ( colorsRGB444[1][G] & 0xf ) << 6;
+ compressed1 |= ( colorsRGB444[1][B] & 0xf ) << 2;
+ compressed1 |= ( bestDist >> 1 ) & 0x3;
+ }
+
+ bestPixIndices = indexConversion( bestPixIndices );
+ compressed2 = 0;
+ compressed2 = ( compressed2 & ~( ( 0x2 << 31 ) - 1 ) ) | ( bestPixIndices & ( ( 2 << 31 ) - 1 ) );
+
+ return bestErr;
+}
+//#endif
+
template<class T, class S>
static etcpak_force_inline uint64_t EncodeSelectors( uint64_t d, const T terr[2][8], const S tsel[16][8], const uint32_t* id, const uint64_t value, const uint64_t error)
{
@@ -2025,7 +2589,7 @@ static inline int16_t hMax( __m128i buffer, uint8_t& idx )
return result;
}
-#elif defined __ARM_NEON
+#elif defined __ARM_NEON && defined __aarch64__
static inline int16_t hMax( uint8x16_t buffer, uint8_t& idx )
{
const uint8_t max = vmaxvq_u8( buffer );
@@ -2072,7 +2636,7 @@ static inline int16_t hMin( __m128i buffer, uint8_t& idx )
idx = _tzcnt_u32( _mm_movemask_epi8( mask ) );
return result;
}
-#elif defined __ARM_NEON
+#elif defined __ARM_NEON && defined __aarch64__
static inline int16_t hMin( uint8x16_t buffer, uint8_t& idx )
{
const uint8_t min = vminvq_u8( buffer );
@@ -2109,8 +2673,153 @@ static inline int16_t hMin( uint8x16_t buffer, uint8_t& idx )
}
#endif
-static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma )
+// During search it is not convenient to store the bits the way they are stored in the
+// file format. Hence, after search, it is converted to this format.
+// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
+static inline void stuff59bits( unsigned int thumbT59W1, unsigned int thumbT59W2, unsigned int& thumbTW1, unsigned int& thumbTW2 )
{
+ // Put bits in twotimer configuration for 59 (red overflows)
+ //
+ // Go from this bit layout:
+ //
+ // |63 62 61 60 59|58 57 56 55|54 53 52 51|50 49 48 47|46 45 44 43|42 41 40 39|38 37 36 35|34 33 32|
+ // |----empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|--dist--|
+ //
+ // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
+ // |----------------------------------------index bits---------------------------------------------|
+ //
+ //
+ // To this:
+ //
+ // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+ // -----------------------------------------------------------------------------------------------
+ // |// // //|R0a |//|R0b |G0 |B0 |R1 |G1 |B1 |da |df|db|
+ // -----------------------------------------------------------------------------------------------
+ //
+ // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
+ // |----------------------------------------index bits---------------------------------------------|
+ //
+ // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+ // -----------------------------------------------------------------------------------------------
+ // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp|
+ // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt|
+ // ------------------------------------------------------------------------------------------------
+
+ uint8_t R0a;
+ uint8_t bit, a, b, c, d, bits;
+
+ R0a = ( thumbT59W1 >> 25 ) & 0x3;
+
+ // Fix middle part
+ thumbTW1 = thumbT59W1 << 1;
+ // Fix R0a (top two bits of R0)
+ thumbTW1 = ( thumbTW1 & ~( 0x3 << 27 ) ) | ( ( R0a & 0x3 ) << 27 );
+ // Fix db (lowest bit of d)
+ thumbTW1 = ( thumbTW1 & ~0x1 ) | ( thumbT59W1 & 0x1 );
+
+ // Make sure that red overflows:
+ a = ( thumbTW1 >> 28 ) & 0x1;
+ b = ( thumbTW1 >> 27 ) & 0x1;
+ c = ( thumbTW1 >> 25 ) & 0x1;
+ d = ( thumbTW1 >> 24 ) & 0x1;
+
+ // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
+ // The following logical expression checks for the presence of any of those:
+ bit = ( a & c ) | ( !a & b & c & d ) | ( a & b & !c & d );
+ bits = 0xf * bit;
+ thumbTW1 = ( thumbTW1 & ~( 0x7 << 29 ) ) | ( bits & 0x7 ) << 29;
+ thumbTW1 = ( thumbTW1 & ~( 0x1 << 26 ) ) | ( !bit & 0x1 ) << 26;
+
+ // Set diffbit
+ thumbTW1 = ( thumbTW1 & ~0x2 ) | 0x2;
+ thumbTW2 = thumbT59W2;
+}
+
+// During search it is not convenient to store the bits the way they are stored in the
+// file format. Hence, after search, it is converted to this format.
+// NO WARRANTY --- SEE STATEMENT IN TOP OF FILE (C) Ericsson AB 2005-2013. All Rights Reserved.
+static inline void stuff58bits( unsigned int thumbH58W1, unsigned int thumbH58W2, unsigned int& thumbHW1, unsigned int& thumbHW2 )
+{
+ // Put bits in twotimer configuration for 58 (red doesn't overflow, green does)
+ //
+ // Go from this bit layout:
+ //
+ //
+ // |63 62 61 60 59 58|57 56 55 54|53 52 51 50|49 48 47 46|45 44 43 42|41 40 39 38|37 36 35 34|33 32|
+ // |-------empty-----|---red 0---|--green 0--|--blue 0---|---red 1---|--green 1--|--blue 1---|d2 d1|
+ //
+ // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
+ // |---------------------------------------index bits----------------------------------------------|
+ //
+ // To this:
+ //
+ // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+ // -----------------------------------------------------------------------------------------------
+ // |//|R0 |G0 |// // //|G0|B0|//|B0b |R1 |G1 |B0 |d2|df|d1|
+ // -----------------------------------------------------------------------------------------------
+ //
+ // |31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00|
+ // |---------------------------------------index bits----------------------------------------------|
+ //
+ // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+ // -----------------------------------------------------------------------------------------------
+ // | base col1 | dcol 2 | base col1 | dcol 2 | base col 1 | dcol 2 | table | table |df|fp|
+ // | R1' (5 bits) | dR2 | G1' (5 bits) | dG2 | B1' (5 bits) | dB2 | cw 1 | cw 2 |bt|bt|
+ // -----------------------------------------------------------------------------------------------
+ //
+ //
+ // Thus, what we are really doing is going from this bit layout:
+ //
+ //
+ // |63 62 61 60 59 58|57 56 55 54 53 52 51|50 49|48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33|32 |
+ // |-------empty-----|part0---------------|part1|part2------------------------------------------|part3|
+ //
+ // To this:
+ //
+ // 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32
+ // --------------------------------------------------------------------------------------------------|
+ // |//|part0 |// // //|part1|//|part2 |df|part3|
+ // --------------------------------------------------------------------------------------------------|
+
+ unsigned int part0, part1, part2, part3;
+ uint8_t bit, a, b, c, d, bits;
+
+ // move parts
+ part0 = ( thumbH58W1 >> 19 ) & 0x7f;
+ part1 = ( thumbH58W1 >> 17 ) & 0x3;
+ part2 = ( thumbH58W1 >> 1 ) & 0xffff;
+ part3 = thumbH58W1 & 0x1;
+ thumbHW1 = 0;
+ thumbHW1 = ( thumbHW1 & ~( 0x7f << 24 ) ) | ( ( part0 & 0x7f ) << 24 );
+ thumbHW1 = ( thumbHW1 & ~( 0x3 << 19 ) ) | ( ( part1 & 0x3 ) << 19 );
+ thumbHW1 = ( thumbHW1 & ~( 0xffff << 2 ) ) | ( ( part2 & 0xffff ) << 2 );
+ thumbHW1 = ( thumbHW1 & ~0x1 ) | ( part3 & 0x1 );
+
+ // Make sure that red does not overflow:
+ bit = ( thumbHW1 >> 30 ) & 0x1;
+ thumbHW1 = ( thumbHW1 & ~( 0x1 << 31 ) ) | ( ( !bit & 0x1 ) << 31 );
+
+ // Make sure that green overflows:
+ a = ( thumbHW1 >> 20 ) & 0x1;
+ b = ( thumbHW1 >> 19 ) & 0x1;
+ c = ( thumbHW1 >> 17 ) & 0x1;
+ d = ( thumbHW1 >> 16 ) & 0x1;
+ // The following bit abcd bit sequences should be padded with ones: 0111, 1010, 1011, 1101, 1110, 1111
+ // The following logical expression checks for the presence of any of those:
+ bit = ( a & c ) | ( !a & b & c & d ) | ( a & b & !c & d );
+ bits = 0xf * bit;
+ thumbHW1 = ( thumbHW1 & ~( 0x7 << 21 ) ) | ( ( bits & 0x7 ) << 21 );
+ thumbHW1 = ( thumbHW1 & ~( 0x1 << 18 ) ) | ( ( !bit & 0x1 ) << 18 );
+
+ // Set diffbit
+ thumbHW1 = ( thumbHW1 & ~0x2 ) | 0x2;
+ thumbHW2 = thumbH58W2;
+}
+
+#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__)
+static etcpak_force_inline Channels GetChannels( const uint8_t* src )
+{
+ Channels ch;
#ifdef __AVX2__
__m128i d0 = _mm_loadu_si128( ( (__m128i*)src ) + 0 );
__m128i d1 = _mm_loadu_si128( ( (__m128i*)src ) + 1 );
@@ -2128,30 +2837,10 @@ static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma )
__m128i b1 = _mm_unpackhi_epi32( rgb2, rgb3 );
// swap channels
- __m128i b8 = _mm_unpacklo_epi64( rg0, rg1 );
- __m128i g8 = _mm_unpackhi_epi64( rg0, rg1 );
- __m128i r8 = _mm_unpacklo_epi64( b0, b1 );
-
- __m256i b16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( b8 ), _mm256_set1_epi16( 14 ) );
- __m256i g16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( g8 ), _mm256_set1_epi16( 76 ) );
- __m256i r16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( r8 ), _mm256_set1_epi16( 38 ) );
-
- __m256i luma_16bit = _mm256_add_epi16( _mm256_add_epi16( g16_luma, r16_luma ), b16_luma );
- __m256i luma_8bit_m256i = _mm256_srli_epi16( luma_16bit, 7 );
- __m128i luma_8bit_lo = _mm256_extractf128_si256( luma_8bit_m256i, 0 );
- __m128i luma_8bit_hi = _mm256_extractf128_si256( luma_8bit_m256i, 1 );
-
- static const __m128i interleaving_mask_lo = _mm_set_epi8( 15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0 );
- static const __m128i interleaving_mask_hi = _mm_set_epi8( 14, 12, 10, 8, 6, 4, 2, 0, 15, 13, 11, 9, 7, 5, 3, 1 );
- __m128i luma_8bit_lo_moved = _mm_shuffle_epi8( luma_8bit_lo, interleaving_mask_lo );
- __m128i luma_8bit_hi_moved = _mm_shuffle_epi8( luma_8bit_hi, interleaving_mask_hi );
- __m128i luma_8bit = _mm_or_si128( luma_8bit_hi_moved, luma_8bit_lo_moved );
- luma.luma8 = luma_8bit;
-
- // min/max calculation
- luma.min = hMin( luma_8bit, luma.minIdx ) * 0.00392156f;
- luma.max = hMax( luma_8bit, luma.maxIdx ) * 0.00392156f;
-#elif defined __ARM_NEON
+ ch.b8 = _mm_unpacklo_epi64( rg0, rg1 );
+ ch.g8 = _mm_unpackhi_epi64( rg0, rg1 );
+ ch.r8 = _mm_unpacklo_epi64( b0, b1 );
+#elif defined __ARM_NEON && defined __aarch64__
//load pixel data into 4 rows
uint8x16_t px0 = vld1q_u8( src + 0 );
uint8x16_t px1 = vld1q_u8( src + 16 );
@@ -2172,12 +2861,48 @@ static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma )
uint8x16x2_t red = vzipq_u8( rr, uint8x16_t() );
uint8x16x2_t grn = vzipq_u8( gg, uint8x16_t() );
uint8x16x2_t blu = vzipq_u8( bb, uint8x16_t() );
- uint16x8_t red0 = vmulq_n_u16( vreinterpretq_u16_u8( red.val[0] ), 14 );
- uint16x8_t red1 = vmulq_n_u16( vreinterpretq_u16_u8( red.val[1] ), 14 );
- uint16x8_t grn0 = vmulq_n_u16( vreinterpretq_u16_u8( grn.val[0] ), 76 );
- uint16x8_t grn1 = vmulq_n_u16( vreinterpretq_u16_u8( grn.val[1] ), 76 );
- uint16x8_t blu0 = vmulq_n_u16( vreinterpretq_u16_u8( blu.val[0] ), 38 );
- uint16x8_t blu1 = vmulq_n_u16( vreinterpretq_u16_u8( blu.val[1] ), 38 );
+ ch.r = red;
+ ch.b = blu;
+ ch.g = grn;
+#endif
+ return ch;
+}
+#endif
+
+#if defined __AVX2__ || (defined __ARM_NEON && defined __aarch64__)
+static etcpak_force_inline void CalculateLuma( Channels& ch, Luma& luma )
+#else
+static etcpak_force_inline void CalculateLuma( const uint8_t* src, Luma& luma )
+#endif
+{
+#ifdef __AVX2__
+ __m256i b16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.b8 ), _mm256_set1_epi16( 14 ) );
+ __m256i g16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.g8 ), _mm256_set1_epi16( 76 ) );
+ __m256i r16_luma = _mm256_mullo_epi16( _mm256_cvtepu8_epi16( ch.r8 ), _mm256_set1_epi16( 38 ) );
+
+ __m256i luma_16bit = _mm256_add_epi16( _mm256_add_epi16( g16_luma, r16_luma ), b16_luma );
+ __m256i luma_8bit_m256i = _mm256_srli_epi16( luma_16bit, 7 );
+ __m128i luma_8bit_lo = _mm256_extractf128_si256( luma_8bit_m256i, 0 );
+ __m128i luma_8bit_hi = _mm256_extractf128_si256( luma_8bit_m256i, 1 );
+
+ static const __m128i interleaving_mask_lo = _mm_set_epi8( 15, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 0 );
+ static const __m128i interleaving_mask_hi = _mm_set_epi8( 14, 12, 10, 8, 6, 4, 2, 0, 15, 13, 11, 9, 7, 5, 3, 1 );
+ __m128i luma_8bit_lo_moved = _mm_shuffle_epi8( luma_8bit_lo, interleaving_mask_lo );
+ __m128i luma_8bit_hi_moved = _mm_shuffle_epi8( luma_8bit_hi, interleaving_mask_hi );
+ __m128i luma_8bit = _mm_or_si128( luma_8bit_hi_moved, luma_8bit_lo_moved );
+ luma.luma8 = luma_8bit;
+
+ // min/max calculation
+ luma.min = hMin( luma_8bit, luma.minIdx ) * 0.00392156f;
+ luma.max = hMax( luma_8bit, luma.maxIdx ) * 0.00392156f;
+#elif defined __ARM_NEON && defined __aarch64__
+ //load pixel data into 4 rows
+ uint16x8_t red0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.r.val[0] ), 14 );
+ uint16x8_t red1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.r.val[1] ), 14 );
+ uint16x8_t grn0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.g.val[0] ), 76 );
+ uint16x8_t grn1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.g.val[1] ), 76 );
+ uint16x8_t blu0 = vmulq_n_u16( vreinterpretq_u16_u8( ch.b.val[0] ), 38 );
+ uint16x8_t blu1 = vmulq_n_u16( vreinterpretq_u16_u8( ch.b.val[1] ), 38 );
//calculate luma for rows 0,1 and 2,3
uint16x8_t lum_r01 = vaddq_u16( vaddq_u16( red0, grn0 ), blu0 );
@@ -2253,7 +2978,7 @@ static etcpak_force_inline uint8_t SelectModeETC2( const Luma& luma )
{
return ModeTH;
}
- return 0;
+ return ModeUndecided;
}
static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool useHeuristics )
@@ -2267,33 +2992,33 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us
#endif
uint8_t mode = ModeUndecided;
+ Luma luma;
+#ifdef __AVX2__
+ Channels ch = GetChannels( src );
if( useHeuristics )
{
- Luma luma;
- CalculateLuma( src, luma );
+ CalculateLuma( ch, luma );
mode = SelectModeETC2( luma );
}
-#ifdef __AVX2__
- auto plane = Planar_AVX2( src, mode );
+ auto plane = Planar_AVX2( ch, mode, useHeuristics );
if( useHeuristics && mode == ModePlanar ) return plane.plane;
- alignas(32) v4i a[8];
-
+ alignas( 32 ) v4i a[8];
__m128i err0 = PrepareAverages_AVX2( a, plane.sum4 );
// Get index of minimum error (err0)
- __m128i err1 = _mm_shuffle_epi32(err0, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i err1 = _mm_shuffle_epi32( err0, _MM_SHUFFLE( 2, 3, 0, 1 ) );
__m128i errMin0 = _mm_min_epu32(err0, err1);
- __m128i errMin1 = _mm_shuffle_epi32(errMin0, _MM_SHUFFLE(1, 0, 3, 2));
- __m128i errMin2 = _mm_min_epu32(errMin1, errMin0);
+ __m128i errMin1 = _mm_shuffle_epi32( errMin0, _MM_SHUFFLE( 1, 0, 3, 2 ) );
+ __m128i errMin2 = _mm_min_epu32( errMin1, errMin0 );
- __m128i errMask = _mm_cmpeq_epi32(errMin2, err0);
+ __m128i errMask = _mm_cmpeq_epi32( errMin2, err0 );
- uint32_t mask = _mm_movemask_epi8(errMask);
+ uint32_t mask = _mm_movemask_epi8( errMask );
- size_t idx = _bit_scan_forward(mask) >> 2;
+ size_t idx = _bit_scan_forward( mask ) >> 2;
d = EncodeAverages_AVX2( a, idx );
@@ -2309,12 +3034,54 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us
FindBestFit_2x4_AVX2( terr, tsel, a, idx * 2, src );
}
- return EncodeSelectors_AVX2( d, terr, tsel, (idx % 2) == 1, plane.plane, plane.error );
+ if( useHeuristics )
+ {
+ if( mode == ModeTH )
+ {
+ uint64_t result = 0;
+ uint64_t error = 0;
+ uint32_t compressed[4] = { 0, 0, 0, 0 };
+ bool tMode = false;
+
+ error = compressBlockTH( (uint8_t*)src, luma, compressed[0], compressed[1], tMode, ch.r8, ch.g8, ch.b8 );
+ if( tMode )
+ {
+ stuff59bits( compressed[0], compressed[1], compressed[2], compressed[3] );
+ }
+ else
+ {
+ stuff58bits( compressed[0], compressed[1], compressed[2], compressed[3] );
+ }
+
+ result = (uint32_t)_bswap( compressed[2] );
+ result |= static_cast<uint64_t>( _bswap( compressed[3] ) ) << 32;
+
+ plane.plane = result;
+ plane.error = error;
+ }
+ else
+ {
+ plane.plane = 0;
+ plane.error = MaxError;
+ }
+ }
+
+ return EncodeSelectors_AVX2( d, terr, tsel, ( idx % 2 ) == 1, plane.plane, plane.error );
#else
+ if( useHeuristics )
+ {
+#if defined __ARM_NEON && defined __aarch64__
+ Channels ch = GetChannels( src );
+ CalculateLuma( ch, luma );
+#else
+ CalculateLuma( src, luma );
+#endif
+ mode = SelectModeETC2( luma );
+ }
#ifdef __ARM_NEON
- auto result = Planar_NEON( src, mode );
+ auto result = Planar_NEON( src, mode, useHeuristics );
#else
- auto result = Planar( src, mode );
+ auto result = Planar( src, mode, useHeuristics );
#endif
if( result.second == 0 ) return result.first;
@@ -2333,6 +3100,33 @@ static etcpak_force_inline uint64_t ProcessRGB_ETC2( const uint8_t* src, bool us
auto id = g_id[idx];
FindBestFit( terr, tsel, a, id, src );
+ if( useHeuristics )
+ {
+ if( mode == ModeTH )
+ {
+ uint32_t compressed[4] = { 0, 0, 0, 0 };
+ bool tMode = false;
+
+ result.second = compressBlockTH( (uint8_t*)src, luma, compressed[0], compressed[1], tMode );
+ if( tMode )
+ {
+ stuff59bits( compressed[0], compressed[1], compressed[2], compressed[3] );
+ }
+ else
+ {
+ stuff58bits( compressed[0], compressed[1], compressed[2], compressed[3] );
+ }
+
+ result.first = (uint32_t)_bswap( compressed[2] );
+ result.first |= static_cast<uint64_t>( _bswap( compressed[3] ) ) << 32;
+ }
+ else
+ {
+ result.first = 0;
+ result.second = MaxError;
+ }
+ }
+
return EncodeSelectors( d, terr, tsel, id, result.first, result.second );
#endif
}
@@ -2422,9 +3216,9 @@ etcpak_force_inline static uint16x8_t ErrorProbe_EAC_NEON( uint8x8_t recVal, uin
uint8x8_t srcValWide;
#ifndef __aarch64__
if( Index < 8 )
- srcValWide = vdup_lane_u8( vget_low_u8( alphaBlock ), ClampConstant( Index, 0, 8 ) );
+ srcValWide = vdup_lane_u8( vget_low_u8( alphaBlock ), ClampConstant( Index, 0, 7 ) );
else
- srcValWide = vdup_lane_u8( vget_high_u8( alphaBlock ), ClampConstant( Index - 8, 0, 8 ) );
+ srcValWide = vdup_lane_u8( vget_high_u8( alphaBlock ), ClampConstant( Index - 8, 0, 7 ) );
#else
srcValWide = vdup_laneq_u8( alphaBlock, Index );
#endif
@@ -2462,9 +3256,9 @@ etcpak_force_inline static int16x8_t WidenMultiplier_EAC_NEON( int16x8_t multipl
constexpr int Lane = GetMulSel( Index );
#ifndef __aarch64__
if( Lane < 4 )
- return vdupq_lane_s16( vget_low_s16( multipliers ), ClampConstant( Lane, 0, 4 ) );
+ return vdupq_lane_s16( vget_low_s16( multipliers ), ClampConstant( Lane, 0, 3 ) );
else
- return vdupq_lane_s16( vget_high_s16( multipliers ), ClampConstant( Lane - 4, 0, 4 ) );
+ return vdupq_lane_s16( vget_high_s16( multipliers ), ClampConstant( Lane - 4, 0, 3 ) );
#else
return vdupq_laneq_s16( multipliers, Lane );
#endif
diff --git a/thirdparty/fonts/DroidSansFallback.ttf b/thirdparty/fonts/DroidSansFallback.ttf
deleted file mode 100644
index 206621fc6c..0000000000
--- a/thirdparty/fonts/DroidSansFallback.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/DroidSansFallback.woff2 b/thirdparty/fonts/DroidSansFallback.woff2
new file mode 100644
index 0000000000..9dd49d6281
--- /dev/null
+++ b/thirdparty/fonts/DroidSansFallback.woff2
Binary files differ
diff --git a/thirdparty/fonts/DroidSansJapanese.ttf b/thirdparty/fonts/DroidSansJapanese.ttf
deleted file mode 100644
index 412fa3de05..0000000000
--- a/thirdparty/fonts/DroidSansJapanese.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/DroidSansJapanese.woff2 b/thirdparty/fonts/DroidSansJapanese.woff2
new file mode 100644
index 0000000000..96eaf5ce72
--- /dev/null
+++ b/thirdparty/fonts/DroidSansJapanese.woff2
Binary files differ
diff --git a/thirdparty/fonts/JetBrainsMono_Regular.ttf b/thirdparty/fonts/JetBrainsMono_Regular.ttf
deleted file mode 100644
index 8da8aa4051..0000000000
--- a/thirdparty/fonts/JetBrainsMono_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/JetBrainsMono_Regular.woff2 b/thirdparty/fonts/JetBrainsMono_Regular.woff2
new file mode 100644
index 0000000000..490104645b
--- /dev/null
+++ b/thirdparty/fonts/JetBrainsMono_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf b/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf
deleted file mode 100644
index 5576af7fee..0000000000
--- a/thirdparty/fonts/NotoNaskhArabicUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Bold.woff2 b/thirdparty/fonts/NotoNaskhArabicUI_Bold.woff2
new file mode 100644
index 0000000000..72358d6eb1
--- /dev/null
+++ b/thirdparty/fonts/NotoNaskhArabicUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf b/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf
deleted file mode 100644
index 9b7a93d136..0000000000
--- a/thirdparty/fonts/NotoNaskhArabicUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoNaskhArabicUI_Regular.woff2 b/thirdparty/fonts/NotoNaskhArabicUI_Regular.woff2
new file mode 100644
index 0000000000..1195d4174e
--- /dev/null
+++ b/thirdparty/fonts/NotoNaskhArabicUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf b/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf
deleted file mode 100644
index dc61efefd5..0000000000
--- a/thirdparty/fonts/NotoSansBengaliUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengaliUI_Bold.woff2 b/thirdparty/fonts/NotoSansBengaliUI_Bold.woff2
new file mode 100644
index 0000000000..03adf85fdc
--- /dev/null
+++ b/thirdparty/fonts/NotoSansBengaliUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengaliUI_Regular.ttf b/thirdparty/fonts/NotoSansBengaliUI_Regular.ttf
deleted file mode 100644
index d43c292ad6..0000000000
--- a/thirdparty/fonts/NotoSansBengaliUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansBengaliUI_Regular.woff2 b/thirdparty/fonts/NotoSansBengaliUI_Regular.woff2
new file mode 100644
index 0000000000..a6a3ffa3a7
--- /dev/null
+++ b/thirdparty/fonts/NotoSansBengaliUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf b/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf
deleted file mode 100644
index 74791aa469..0000000000
--- a/thirdparty/fonts/NotoSansDevanagariUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Bold.woff2 b/thirdparty/fonts/NotoSansDevanagariUI_Bold.woff2
new file mode 100644
index 0000000000..6c835712cb
--- /dev/null
+++ b/thirdparty/fonts/NotoSansDevanagariUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf b/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf
deleted file mode 100644
index e48dced0c9..0000000000
--- a/thirdparty/fonts/NotoSansDevanagariUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansDevanagariUI_Regular.woff2 b/thirdparty/fonts/NotoSansDevanagariUI_Regular.woff2
new file mode 100644
index 0000000000..486896e6e9
--- /dev/null
+++ b/thirdparty/fonts/NotoSansDevanagariUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansGeorgian_Bold.ttf b/thirdparty/fonts/NotoSansGeorgian_Bold.ttf
deleted file mode 100644
index 5443d04cfa..0000000000
--- a/thirdparty/fonts/NotoSansGeorgian_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansGeorgian_Bold.woff2 b/thirdparty/fonts/NotoSansGeorgian_Bold.woff2
new file mode 100644
index 0000000000..104afa150c
--- /dev/null
+++ b/thirdparty/fonts/NotoSansGeorgian_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansGeorgian_Regular.ttf b/thirdparty/fonts/NotoSansGeorgian_Regular.ttf
deleted file mode 100644
index 9bfc8d9675..0000000000
--- a/thirdparty/fonts/NotoSansGeorgian_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansGeorgian_Regular.woff2 b/thirdparty/fonts/NotoSansGeorgian_Regular.woff2
new file mode 100644
index 0000000000..0a7b9e878b
--- /dev/null
+++ b/thirdparty/fonts/NotoSansGeorgian_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Bold.ttf b/thirdparty/fonts/NotoSansHebrew_Bold.ttf
deleted file mode 100644
index 08ef5dc749..0000000000
--- a/thirdparty/fonts/NotoSansHebrew_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Bold.woff2 b/thirdparty/fonts/NotoSansHebrew_Bold.woff2
new file mode 100644
index 0000000000..96c5ae1349
--- /dev/null
+++ b/thirdparty/fonts/NotoSansHebrew_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Regular.ttf b/thirdparty/fonts/NotoSansHebrew_Regular.ttf
deleted file mode 100644
index 0a89e9d21f..0000000000
--- a/thirdparty/fonts/NotoSansHebrew_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansHebrew_Regular.woff2 b/thirdparty/fonts/NotoSansHebrew_Regular.woff2
new file mode 100644
index 0000000000..17eadedc6f
--- /dev/null
+++ b/thirdparty/fonts/NotoSansHebrew_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf b/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf
deleted file mode 100644
index 42e5d56f3f..0000000000
--- a/thirdparty/fonts/NotoSansMalayalamUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansMalayalamUI_Bold.woff2 b/thirdparty/fonts/NotoSansMalayalamUI_Bold.woff2
new file mode 100644
index 0000000000..5f6bacb0c3
--- /dev/null
+++ b/thirdparty/fonts/NotoSansMalayalamUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansMalayalamUI_Regular.ttf b/thirdparty/fonts/NotoSansMalayalamUI_Regular.ttf
deleted file mode 100644
index 37f3591706..0000000000
--- a/thirdparty/fonts/NotoSansMalayalamUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansMalayalamUI_Regular.woff2 b/thirdparty/fonts/NotoSansMalayalamUI_Regular.woff2
new file mode 100644
index 0000000000..c54a82a874
--- /dev/null
+++ b/thirdparty/fonts/NotoSansMalayalamUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf b/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf
deleted file mode 100644
index 36323f79ef..0000000000
--- a/thirdparty/fonts/NotoSansOriyaUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansOriyaUI_Bold.woff2 b/thirdparty/fonts/NotoSansOriyaUI_Bold.woff2
new file mode 100644
index 0000000000..b7e34302e2
--- /dev/null
+++ b/thirdparty/fonts/NotoSansOriyaUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansOriyaUI_Regular.ttf b/thirdparty/fonts/NotoSansOriyaUI_Regular.ttf
deleted file mode 100644
index 7b50a71620..0000000000
--- a/thirdparty/fonts/NotoSansOriyaUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansOriyaUI_Regular.woff2 b/thirdparty/fonts/NotoSansOriyaUI_Regular.woff2
new file mode 100644
index 0000000000..e64090cd77
--- /dev/null
+++ b/thirdparty/fonts/NotoSansOriyaUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf b/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf
deleted file mode 100644
index ecfff97e05..0000000000
--- a/thirdparty/fonts/NotoSansSinhalaUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansSinhalaUI_Bold.woff2 b/thirdparty/fonts/NotoSansSinhalaUI_Bold.woff2
new file mode 100644
index 0000000000..01dbd1bc8f
--- /dev/null
+++ b/thirdparty/fonts/NotoSansSinhalaUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansSinhalaUI_Regular.ttf b/thirdparty/fonts/NotoSansSinhalaUI_Regular.ttf
deleted file mode 100644
index a4b297d691..0000000000
--- a/thirdparty/fonts/NotoSansSinhalaUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansSinhalaUI_Regular.woff2 b/thirdparty/fonts/NotoSansSinhalaUI_Regular.woff2
new file mode 100644
index 0000000000..504c9d0809
--- /dev/null
+++ b/thirdparty/fonts/NotoSansSinhalaUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTamilUI_Bold.ttf b/thirdparty/fonts/NotoSansTamilUI_Bold.ttf
deleted file mode 100644
index 16bcd57081..0000000000
--- a/thirdparty/fonts/NotoSansTamilUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTamilUI_Bold.woff2 b/thirdparty/fonts/NotoSansTamilUI_Bold.woff2
new file mode 100644
index 0000000000..96967b0cce
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTamilUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTamilUI_Regular.ttf b/thirdparty/fonts/NotoSansTamilUI_Regular.ttf
deleted file mode 100644
index e65aeb8d0b..0000000000
--- a/thirdparty/fonts/NotoSansTamilUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTamilUI_Regular.woff2 b/thirdparty/fonts/NotoSansTamilUI_Regular.woff2
new file mode 100644
index 0000000000..e9b2bee582
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTamilUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf b/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf
deleted file mode 100644
index 16ac368795..0000000000
--- a/thirdparty/fonts/NotoSansTeluguUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTeluguUI_Bold.woff2 b/thirdparty/fonts/NotoSansTeluguUI_Bold.woff2
new file mode 100644
index 0000000000..2885bf991d
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTeluguUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTeluguUI_Regular.ttf b/thirdparty/fonts/NotoSansTeluguUI_Regular.ttf
deleted file mode 100644
index 5394a28cfe..0000000000
--- a/thirdparty/fonts/NotoSansTeluguUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansTeluguUI_Regular.woff2 b/thirdparty/fonts/NotoSansTeluguUI_Regular.woff2
new file mode 100644
index 0000000000..ac5e66d8f6
--- /dev/null
+++ b/thirdparty/fonts/NotoSansTeluguUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Bold.ttf b/thirdparty/fonts/NotoSansThaiUI_Bold.ttf
deleted file mode 100644
index 5d998f9215..0000000000
--- a/thirdparty/fonts/NotoSansThaiUI_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Bold.woff2 b/thirdparty/fonts/NotoSansThaiUI_Bold.woff2
new file mode 100644
index 0000000000..202995c066
--- /dev/null
+++ b/thirdparty/fonts/NotoSansThaiUI_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Regular.ttf b/thirdparty/fonts/NotoSansThaiUI_Regular.ttf
deleted file mode 100644
index 8e317961d1..0000000000
--- a/thirdparty/fonts/NotoSansThaiUI_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSansThaiUI_Regular.woff2 b/thirdparty/fonts/NotoSansThaiUI_Regular.woff2
new file mode 100644
index 0000000000..2fb284f21f
--- /dev/null
+++ b/thirdparty/fonts/NotoSansThaiUI_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Bold.ttf b/thirdparty/fonts/NotoSans_Bold.ttf
deleted file mode 100644
index 1db7886e94..0000000000
--- a/thirdparty/fonts/NotoSans_Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Bold.woff2 b/thirdparty/fonts/NotoSans_Bold.woff2
new file mode 100644
index 0000000000..36a5b89999
--- /dev/null
+++ b/thirdparty/fonts/NotoSans_Bold.woff2
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Regular.ttf b/thirdparty/fonts/NotoSans_Regular.ttf
deleted file mode 100644
index 0a01a062f0..0000000000
--- a/thirdparty/fonts/NotoSans_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/NotoSans_Regular.woff2 b/thirdparty/fonts/NotoSans_Regular.woff2
new file mode 100644
index 0000000000..d449eed8d7
--- /dev/null
+++ b/thirdparty/fonts/NotoSans_Regular.woff2
Binary files differ
diff --git a/thirdparty/fonts/OpenSans_SemiBold.ttf b/thirdparty/fonts/OpenSans_SemiBold.ttf
deleted file mode 100644
index 54e7059cf3..0000000000
--- a/thirdparty/fonts/OpenSans_SemiBold.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/fonts/OpenSans_SemiBold.woff2 b/thirdparty/fonts/OpenSans_SemiBold.woff2
new file mode 100644
index 0000000000..5d14a36656
--- /dev/null
+++ b/thirdparty/fonts/OpenSans_SemiBold.woff2
Binary files differ
diff --git a/thirdparty/freetype/include/freetype/config/ftconfig.h b/thirdparty/freetype/include/freetype/config/ftconfig.h
index 65effcbe63..c696e900a6 100644
--- a/thirdparty/freetype/include/freetype/config/ftconfig.h
+++ b/thirdparty/freetype/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
*
* ANSI-specific configuration file (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/config/ftheader.h b/thirdparty/freetype/include/freetype/config/ftheader.h
index e46d314e33..a8c6833df7 100644
--- a/thirdparty/freetype/include/freetype/config/ftheader.h
+++ b/thirdparty/freetype/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
*
* Build macros of the FreeType 2 library.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -777,6 +777,18 @@
#define FT_COLOR_H <freetype/ftcolor.h>
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_OTSVG_H
+ *
+ * @description:
+ * A macro used in `#include` statements to name the file containing the
+ * FreeType~2 API which handles the OpenType 'SVG~' glyphs.
+ */
+#define FT_OTSVG_H <freetype/otsvg.h>
+
+
/* */
/* These header files don't need to be included by the user. */
diff --git a/thirdparty/freetype/include/freetype/config/ftmodule.h b/thirdparty/freetype/include/freetype/config/ftmodule.h
index d4ba3f784d..b315baba8a 100644
--- a/thirdparty/freetype/include/freetype/config/ftmodule.h
+++ b/thirdparty/freetype/include/freetype/config/ftmodule.h
@@ -28,5 +28,6 @@ FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class )
+FT_USE_MODULE( FT_Renderer_Class, ft_svg_renderer_class )
/* EOF */
diff --git a/thirdparty/freetype/include/freetype/config/ftoption.h b/thirdparty/freetype/include/freetype/config/ftoption.h
index 4227fd376e..c5bde243b1 100644
--- a/thirdparty/freetype/include/freetype/config/ftoption.h
+++ b/thirdparty/freetype/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
*
* User-selectable configuration macros (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -219,6 +219,10 @@ FT_BEGIN_HEADER
* If you use a build system like cmake or the `configure` script,
* options set by those programs have precedence, overwriting the value
* here with the configured one.
+ *
+ * If you use the GNU make build system directly (that is, without the
+ * `configure` script) and you define this macro, you also have to pass
+ * `SYSTEM_ZLIB=yes` as an argument to make.
*/
/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */
@@ -525,6 +529,20 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * OpenType SVG Glyph Support
+ *
+ * Setting this macro enables support for OpenType SVG glyphs. By
+ * default, FreeType can only fetch SVG documents. However, it can also
+ * render them if external rendering hook functions are plugged in at
+ * runtime.
+ *
+ * More details on the hooks can be found in file `otsvg.h`.
+ */
+#define FT_CONFIG_OPTION_SVG
+
+
+ /**************************************************************************
+ *
* Error Strings
*
* If this macro is set, `FT_Error_String` will return meaningful
@@ -1002,8 +1020,8 @@ FT_BEGIN_HEADER
#error "Invalid CFF darkening parameters!"
#endif
-FT_END_HEADER
+FT_END_HEADER
#endif /* FTOPTION_H_ */
diff --git a/thirdparty/freetype/include/freetype/config/ftstdlib.h b/thirdparty/freetype/include/freetype/config/ftstdlib.h
index 6ee412a074..7958c2a5f7 100644
--- a/thirdparty/freetype/include/freetype/config/ftstdlib.h
+++ b/thirdparty/freetype/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
* ANSI-specific library and header configuration file (specification
* only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/config/integer-types.h b/thirdparty/freetype/include/freetype/config/integer-types.h
index 5ef09f1978..d9d2638d1e 100644
--- a/thirdparty/freetype/include/freetype/config/integer-types.h
+++ b/thirdparty/freetype/include/freetype/config/integer-types.h
@@ -4,7 +4,7 @@
*
* FreeType integer types definitions.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -221,9 +221,10 @@
#define FT_INT64 __int64
#define FT_UINT64 unsigned __int64
-#elif defined( __WATCOMC__ ) /* Watcom C++ */
+#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1100 /* Watcom C++ */
- /* Watcom doesn't provide 64-bit data types */
+#define FT_INT64 long long int
+#define FT_UINT64 unsigned long long int
#elif defined( __MWERKS__ ) /* Metrowerks CodeWarrior */
diff --git a/thirdparty/freetype/include/freetype/config/mac-support.h b/thirdparty/freetype/include/freetype/config/mac-support.h
index ef58d8b3f0..e42c9fe410 100644
--- a/thirdparty/freetype/include/freetype/config/mac-support.h
+++ b/thirdparty/freetype/include/freetype/config/mac-support.h
@@ -4,7 +4,7 @@
*
* Mac/OS X support configuration header.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/config/public-macros.h b/thirdparty/freetype/include/freetype/config/public-macros.h
index 9fbb3274a0..0074134f1d 100644
--- a/thirdparty/freetype/include/freetype/config/public-macros.h
+++ b/thirdparty/freetype/include/freetype/config/public-macros.h
@@ -4,7 +4,7 @@
*
* Define a set of compiler macros used in public FreeType headers.
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/freetype.h b/thirdparty/freetype/include/freetype/freetype.h
index f6c66b94ae..aa1a4fe389 100644
--- a/thirdparty/freetype/include/freetype/freetype.h
+++ b/thirdparty/freetype/include/freetype/freetype.h
@@ -4,7 +4,7 @@
*
* FreeType high-level API and common types (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -153,6 +153,9 @@ FT_BEGIN_HEADER
* FT_FACE_FLAG_GLYPH_NAMES
* FT_FACE_FLAG_EXTERNAL_STREAM
* FT_FACE_FLAG_HINTER
+ * FT_FACE_FLAG_SVG
+ * FT_FACE_FLAG_SBIX
+ * FT_FACE_FLAG_SBIX_OVERLAY
*
* FT_HAS_HORIZONTAL
* FT_HAS_VERTICAL
@@ -161,6 +164,9 @@ FT_BEGIN_HEADER
* FT_HAS_GLYPH_NAMES
* FT_HAS_COLOR
* FT_HAS_MULTIPLE_MASTERS
+ * FT_HAS_SVG
+ * FT_HAS_SBIX
+ * FT_HAS_SBIX_OVERLAY
*
* FT_IS_SFNT
* FT_IS_SCALABLE
@@ -225,6 +231,7 @@ FT_BEGIN_HEADER
* FT_LOAD_NO_SCALE
* FT_LOAD_NO_HINTING
* FT_LOAD_NO_BITMAP
+ * FT_LOAD_SBITS_ONLY
* FT_LOAD_NO_AUTOHINT
* FT_LOAD_COLOR
*
@@ -522,13 +529,15 @@ FT_BEGIN_HEADER
* size.
*
* @note:
- * An @FT_Face has one _active_ @FT_Size object that is used by functions
- * like @FT_Load_Glyph to determine the scaling transformation that in
- * turn is used to load and hint glyphs and metrics.
+ * An @FT_Face has one _active_ `FT_Size` object that is used by
+ * functions like @FT_Load_Glyph to determine the scaling transformation
+ * that in turn is used to load and hint glyphs and metrics.
*
- * You can use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size
+ * A newly created `FT_Size` object contains only meaningless zero values.
+ * You must use @FT_Set_Char_Size, @FT_Set_Pixel_Sizes, @FT_Request_Size
* or even @FT_Select_Size to change the content (i.e., the scaling
- * values) of the active @FT_Size.
+ * values) of the active `FT_Size`. Otherwise, the scaling and hinting
+ * will not be performed.
*
* You can use @FT_New_Size to create additional size objects for a given
* @FT_Face, but they won't be used by other functions until you activate
@@ -1228,6 +1237,19 @@ FT_BEGIN_HEADER
* altered with @FT_Set_MM_Design_Coordinates,
* @FT_Set_Var_Design_Coordinates, or @FT_Set_Var_Blend_Coordinates.
* This flag is unset by a call to @FT_Set_Named_Instance.
+ *
+ * FT_FACE_FLAG_SVG ::
+ * [Since 2.12] The face has an 'SVG~' OpenType table.
+ *
+ * FT_FACE_FLAG_SBIX ::
+ * [Since 2.12] The face has an 'sbix' OpenType table *and* outlines.
+ * For such fonts, @FT_FACE_FLAG_SCALABLE is not set by default to
+ * retain backward compatibility.
+ *
+ * FT_FACE_FLAG_SBIX_OVERLAY ::
+ * [Since 2.12] The face has an 'sbix' OpenType table where outlines
+ * should be drawn on top of bitmap strikes.
+ *
*/
#define FT_FACE_FLAG_SCALABLE ( 1L << 0 )
#define FT_FACE_FLAG_FIXED_SIZES ( 1L << 1 )
@@ -1245,6 +1267,9 @@ FT_BEGIN_HEADER
#define FT_FACE_FLAG_TRICKY ( 1L << 13 )
#define FT_FACE_FLAG_COLOR ( 1L << 14 )
#define FT_FACE_FLAG_VARIATION ( 1L << 15 )
+#define FT_FACE_FLAG_SVG ( 1L << 16 )
+#define FT_FACE_FLAG_SBIX ( 1L << 17 )
+#define FT_FACE_FLAG_SBIX_OVERLAY ( 1L << 18 )
/**************************************************************************
@@ -1487,6 +1512,124 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * @macro:
+ * FT_HAS_SVG
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains an 'SVG~'
+ * OpenType table.
+ *
+ * @since:
+ * 2.12
+ */
+#define FT_HAS_SVG( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SVG ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_SBIX
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains an 'sbix'
+ * OpenType table *and* outline glyphs.
+ *
+ * Currently, FreeType only supports bitmap glyphs in PNG format for this
+ * table (i.e., JPEG and TIFF formats are unsupported, as are
+ * Apple-specific formats not part of the OpenType specification).
+ *
+ * @note:
+ * For backward compatibility, a font with an 'sbix' table is treated as
+ * a bitmap-only face. Using @FT_Open_Face with
+ * @FT_PARAM_TAG_IGNORE_SBIX, an application can switch off 'sbix'
+ * handling so that the face is treated as an ordinary outline font with
+ * scalable outlines.
+ *
+ * Here is some pseudo code that roughly illustrates how to implement
+ * 'sbix' handling according to the OpenType specification.
+ *
+ * ```
+ * if ( FT_HAS_SBIX( face ) )
+ * {
+ * // open font as a scalable one without sbix handling
+ * FT_Face face2;
+ * FT_Parameter param = { FT_PARAM_TAG_IGNORE_SBIX, NULL };
+ * FT_Open_Args args = { FT_OPEN_PARAMS | ...,
+ * ...,
+ * 1, &param };
+ *
+ *
+ * FT_Open_Face( library, &args, 0, &face2 );
+ *
+ * <sort `face->available_size` as necessary into
+ * `preferred_sizes`[*]>
+ *
+ * for ( i = 0; i < face->num_fixed_sizes; i++ )
+ * {
+ * size = preferred_sizes[i].size;
+ *
+ * error = FT_Set_Pixel_Sizes( face, size, size );
+ * <error handling omitted>
+ *
+ * // check whether we have a glyph in a bitmap strike
+ * error = FT_Load_Glyph( face,
+ * glyph_index,
+ * FT_LOAD_SBITS_ONLY |
+ * FT_LOAD_BITMAP_METRICS_ONLY );
+ * if ( error == FT_Err_Invalid_Argument )
+ * continue;
+ * else if ( error )
+ * <other error handling omitted>
+ * else
+ * break;
+ * }
+ *
+ * if ( i != face->num_fixed_sizes )
+ * <load embedded bitmap with `FT_Load_Glyph`,
+ * scale it, display it, etc.>
+ *
+ * if ( i == face->num_fixed_sizes ||
+ * FT_HAS_SBIX_OVERLAY( face ) )
+ * <use `face2` to load outline glyph with `FT_Load_Glyph`,
+ * scale it, display it on top of the bitmap, etc.>
+ * }
+ * ```
+ *
+ * [*] Assuming a target value of 400dpi and available strike sizes 100,
+ * 200, 300, and 400dpi, a possible order might be [400, 200, 300, 100]:
+ * scaling 200dpi to 400dpi usually gives better results than scaling
+ * 300dpi to 400dpi; it is also much faster. However, scaling 100dpi to
+ * 400dpi can yield a too pixelated result, thus the preference might be
+ * 300dpi over 100dpi.
+ *
+ * @since:
+ * 2.12
+ */
+#define FT_HAS_SBIX( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX ) )
+
+
+ /**************************************************************************
+ *
+ * @macro:
+ * FT_HAS_SBIX_OVERLAY
+ *
+ * @description:
+ * A macro that returns true whenever a face object contains an 'sbix'
+ * OpenType table with bit~1 in its `flags` field set, instructing the
+ * application to overlay the bitmap strike with the corresponding
+ * outline glyph. See @FT_HAS_SBIX for pseudo code how to use it.
+ *
+ * @since:
+ * 2.12
+ */
+#define FT_HAS_SBIX_OVERLAY( face ) \
+ ( !!( (face)->face_flags & FT_FACE_FLAG_SBIX_OVERLAY ) )
+
+
+ /**************************************************************************
+ *
* @enum:
* FT_STYLE_FLAG_XXX
*
@@ -2702,8 +2845,8 @@ FT_BEGIN_HEADER
* 'https://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'.
*
* Contrary to @FT_Set_Char_Size, this function doesn't have special code
- * to normalize zero-valued widths, heights, or resolutions (which lead
- * to errors in most cases).
+ * to normalize zero-valued widths, heights, or resolutions, which are
+ * treated as @FT_LOAD_NO_SCALE.
*
* Don't use this function if you are using the FreeType cache API.
*/
@@ -2819,7 +2962,7 @@ FT_BEGIN_HEADER
*
* load_flags ::
* A flag indicating what to load for this glyph. The @FT_LOAD_XXX
- * constants can be used to control the glyph loading process (e.g.,
+ * flags can be used to control the glyph loading process (e.g.,
* whether the outline should be scaled, whether to load bitmaps or
* not, whether to hint the outline, etc).
*
@@ -2827,8 +2970,10 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * The loaded glyph may be transformed. See @FT_Set_Transform for the
- * details.
+ * For proper scaling and hinting, the active @FT_Size object owned by
+ * the face has to be meaningfully initialized by calling
+ * @FT_Set_Char_Size before this function, for example. The loaded
+ * glyph may be transformed. See @FT_Set_Transform for the details.
*
* For subsetted CID-keyed fonts, `FT_Err_Invalid_Argument` is returned
* for invalid CID values (this is, for CID values that don't have a
@@ -2918,6 +3063,8 @@ FT_BEGIN_HEADER
*
* FT_LOAD_NO_SCALE ::
* Don't scale the loaded outline glyph but keep it in font units.
+ * This flag is also assumed if @FT_Size owned by the face was not
+ * properly initialized.
*
* This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
* unsets @FT_LOAD_RENDER.
@@ -2948,6 +3095,15 @@ FT_BEGIN_HEADER
*
* @FT_LOAD_NO_SCALE always sets this flag.
*
+ * FT_LOAD_SBITS_ONLY ::
+ * [Since 2.12] This is the opposite of @FT_LOAD_NO_BITMAP, more or
+ * less: @FT_Load_Glyph returns `FT_Err_Invalid_Argument` if the face
+ * contains a bitmap strike for the given size (or the strike selected
+ * by @FT_Select_Size) but there is no glyph in the strike.
+ *
+ * Note that this load flag was part of FreeType since version 2.0.6
+ * but previously tagged as internal.
+ *
* FT_LOAD_VERTICAL_LAYOUT ::
* Load the glyph for vertical text layout. In particular, the
* `advance` value in the @FT_GlyphSlotRec structure is set to the
@@ -3004,21 +3160,31 @@ FT_BEGIN_HEADER
* Disable the auto-hinter. See also the note below.
*
* FT_LOAD_COLOR ::
- * Load colored glyphs. There are slight differences depending on the
- * font format.
- *
- * [Since 2.5] Load embedded color bitmap images. The resulting color
- * bitmaps, if available, will have the @FT_PIXEL_MODE_BGRA format,
- * with pre-multiplied color channels. If the flag is not set and
- * color bitmaps are found, they are converted to 256-level gray
- * bitmaps, using the @FT_PIXEL_MODE_GRAY format.
- *
- * [Since 2.10, experimental] If the glyph index contains an entry in
+ * Load colored glyphs. FreeType searches in the following order;
+ * there are slight differences depending on the font format.
+ *
+ * [Since 2.5] Load embedded color bitmap images (provided
+ * @FT_LOAD_NO_BITMAP is not set). The resulting color bitmaps, if
+ * available, have the @FT_PIXEL_MODE_BGRA format, with pre-multiplied
+ * color channels. If the flag is not set and color bitmaps are found,
+ * they are converted to 256-level gray bitmaps, using the
+ * @FT_PIXEL_MODE_GRAY format.
+ *
+ * [Since 2.12] If the glyph index maps to an entry in the face's
+ * 'SVG~' table, load the associated SVG document from this table and
+ * set the `format` field of @FT_GlyphSlotRec to @FT_GLYPH_FORMAT_SVG.
+ * Note that FreeType itself can't render SVG documents; however, the
+ * library provides hooks to seamlessly integrate an external renderer.
+ * See sections @ot_svg_driver and @svg_fonts for more.
+ *
+ * [Since 2.10, experimental] If the glyph index maps to an entry in
* the face's 'COLR' table with a 'CPAL' palette table (as defined in
* the OpenType specification), make @FT_Render_Glyph provide a default
* blending of the color glyph layers associated with the glyph index,
* using the same bitmap format as embedded color bitmap images. This
- * is mainly for convenience; for full control of color layers use
+ * is mainly for convenience and works only for glyphs in 'COLR' v0
+ * tables (or glyphs in 'COLR' v1 tables that exclusively use v0
+ * features). For full control of color layers use
* @FT_Get_Color_Glyph_Layer and FreeType's color functions like
* @FT_Palette_Select instead of setting @FT_LOAD_COLOR for rendering
* so that the client application can handle blending by itself.
@@ -3069,19 +3235,20 @@ FT_BEGIN_HEADER
*
*/
#define FT_LOAD_DEFAULT 0x0
-#define FT_LOAD_NO_SCALE ( 1L << 0 )
-#define FT_LOAD_NO_HINTING ( 1L << 1 )
-#define FT_LOAD_RENDER ( 1L << 2 )
-#define FT_LOAD_NO_BITMAP ( 1L << 3 )
-#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 )
-#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 )
-#define FT_LOAD_CROP_BITMAP ( 1L << 6 )
-#define FT_LOAD_PEDANTIC ( 1L << 7 )
-#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 )
+#define FT_LOAD_NO_SCALE ( 1L << 0 )
+#define FT_LOAD_NO_HINTING ( 1L << 1 )
+#define FT_LOAD_RENDER ( 1L << 2 )
+#define FT_LOAD_NO_BITMAP ( 1L << 3 )
+#define FT_LOAD_VERTICAL_LAYOUT ( 1L << 4 )
+#define FT_LOAD_FORCE_AUTOHINT ( 1L << 5 )
+#define FT_LOAD_CROP_BITMAP ( 1L << 6 )
+#define FT_LOAD_PEDANTIC ( 1L << 7 )
+#define FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ( 1L << 9 )
#define FT_LOAD_NO_RECURSE ( 1L << 10 )
#define FT_LOAD_IGNORE_TRANSFORM ( 1L << 11 )
#define FT_LOAD_MONOCHROME ( 1L << 12 )
#define FT_LOAD_LINEAR_DESIGN ( 1L << 13 )
+#define FT_LOAD_SBITS_ONLY ( 1L << 14 )
#define FT_LOAD_NO_AUTOHINT ( 1L << 15 )
/* Bits 16-19 are used by `FT_LOAD_TARGET_` */
#define FT_LOAD_COLOR ( 1L << 20 )
@@ -3091,8 +3258,8 @@ FT_BEGIN_HEADER
/* */
/* used internally only by certain font drivers */
-#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 )
-#define FT_LOAD_SBITS_ONLY ( 1L << 14 )
+#define FT_LOAD_ADVANCE_ONLY ( 1L << 8 )
+#define FT_LOAD_SVG_ONLY ( 1L << 23 )
/**************************************************************************
@@ -3370,6 +3537,44 @@ FT_BEGIN_HEADER
* }
*
* ```
+ *
+ * FreeType has two rasterizers for generating SDF, namely:
+ *
+ * 1. `sdf` for generating SDF directly from glyph's outline, and
+ *
+ * 2. `bsdf` for generating SDF from rasterized bitmaps.
+ *
+ * Depending on the glyph type (i.e., outline or bitmap), one of the two
+ * rasterizers is chosen at runtime and used for generating SDFs. To
+ * force the use of `bsdf` you should render the glyph with any of the
+ * FreeType's other rendering modes (e.g., `FT_RENDER_MODE_NORMAL`) and
+ * then re-render with `FT_RENDER_MODE_SDF`.
+ *
+ * There are some issues with stability and possible failures of the SDF
+ * renderers (specifically `sdf`).
+ *
+ * 1. The `sdf` rasterizer is sensitive to really small features (e.g.,
+ * sharp turns that are less than 1~pixel) and imperfections in the
+ * glyph's outline, causing artifacts in the final output.
+ *
+ * 2. The `sdf` rasterizer has limited support for handling intersecting
+ * contours and *cannot* handle self-intersecting contours whatsoever.
+ * Self-intersection happens when a single connected contour intersect
+ * itself at some point; having these in your font definitely pose a
+ * problem to the rasterizer and cause artifacts, too.
+ *
+ * 3. Generating SDF for really small glyphs may result in undesirable
+ * output; the pixel grid (which stores distance information) becomes
+ * too coarse.
+ *
+ * 4. Since the output buffer is normalized, precision at smaller spreads
+ * is greater than precision at larger spread values because the
+ * output range of [0..255] gets mapped to a smaller SDF range. A
+ * spread of~2 should be sufficient in most cases.
+ *
+ * Points (1) and (2) can be avoided by using the `bsdf` rasterizer,
+ * which is more stable than the `sdf` rasterizer in general.
+ *
*/
typedef enum FT_Render_Mode_
{
@@ -3410,7 +3615,7 @@ FT_BEGIN_HEADER
* @FT_Render_Mode for a list of possible values.
*
* If @FT_RENDER_MODE_NORMAL is used, a previous call of @FT_Load_Glyph
- * with flag @FT_LOAD_COLOR makes FT_Render_Glyph provide a default
+ * with flag @FT_LOAD_COLOR makes `FT_Render_Glyph` provide a default
* blending of colored glyph layers associated with the current glyph
* slot (provided the font contains such layers) instead of rendering
* the glyph slot's outline. This is an experimental feature; see
@@ -3420,9 +3625,6 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * To get meaningful results, font scaling values must be set with
- * functions like @FT_Set_Char_Size before calling `FT_Render_Glyph`.
- *
* When FreeType outputs a bitmap of a glyph, it really outputs an alpha
* coverage map. If a pixel is completely covered by a filled-in
* outline, the bitmap contains 0xFF at that pixel, meaning that
@@ -4739,7 +4941,7 @@ FT_BEGIN_HEADER
*
*/
#define FREETYPE_MAJOR 2
-#define FREETYPE_MINOR 11
+#define FREETYPE_MINOR 12
#define FREETYPE_PATCH 1
diff --git a/thirdparty/freetype/include/freetype/ftadvanc.h b/thirdparty/freetype/include/freetype/ftadvanc.h
index 3a13bd3de4..8ce4846668 100644
--- a/thirdparty/freetype/include/freetype/ftadvanc.h
+++ b/thirdparty/freetype/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (specification only).
*
- * Copyright (C) 2008-2021 by
+ * Copyright (C) 2008-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbbox.h b/thirdparty/freetype/include/freetype/ftbbox.h
index 713aedb15f..768478f399 100644
--- a/thirdparty/freetype/include/freetype/ftbbox.h
+++ b/thirdparty/freetype/include/freetype/ftbbox.h
@@ -4,7 +4,7 @@
*
* FreeType exact bbox computation (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbdf.h b/thirdparty/freetype/include/freetype/ftbdf.h
index c428506405..04d6094f75 100644
--- a/thirdparty/freetype/include/freetype/ftbdf.h
+++ b/thirdparty/freetype/include/freetype/ftbdf.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing BDF-specific strings (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbitmap.h b/thirdparty/freetype/include/freetype/ftbitmap.h
index 11c45b0ed2..c3462dadc5 100644
--- a/thirdparty/freetype/include/freetype/ftbitmap.h
+++ b/thirdparty/freetype/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftbzip2.h b/thirdparty/freetype/include/freetype/ftbzip2.h
index afd2a82afb..c85305806f 100644
--- a/thirdparty/freetype/include/freetype/ftbzip2.h
+++ b/thirdparty/freetype/include/freetype/ftbzip2.h
@@ -4,7 +4,7 @@
*
* Bzip2-compressed stream support.
*
- * Copyright (C) 2010-2021 by
+ * Copyright (C) 2010-2022 by
* Joel Klinghed.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftcache.h b/thirdparty/freetype/include/freetype/ftcache.h
index 70399a328a..ecbbd7b8fb 100644
--- a/thirdparty/freetype/include/freetype/ftcache.h
+++ b/thirdparty/freetype/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
*
* FreeType Cache subsystem (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftchapters.h b/thirdparty/freetype/include/freetype/ftchapters.h
index 4f32cc88c8..6a9733ad7c 100644
--- a/thirdparty/freetype/include/freetype/ftchapters.h
+++ b/thirdparty/freetype/include/freetype/ftchapters.h
@@ -62,6 +62,7 @@
* cid_fonts
* pfr_fonts
* winfnt_fonts
+ * svg_fonts
* font_formats
* gasp_table
*
@@ -82,6 +83,7 @@
* t1_cid_driver
* tt_driver
* pcf_driver
+ * ot_svg_driver
* properties
* parameter_tags
* lcd_rendering
diff --git a/thirdparty/freetype/include/freetype/ftcid.h b/thirdparty/freetype/include/freetype/ftcid.h
index 9a415bd98b..d80108387a 100644
--- a/thirdparty/freetype/include/freetype/ftcid.h
+++ b/thirdparty/freetype/include/freetype/ftcid.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information (specification).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* Dereg Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftcolor.h b/thirdparty/freetype/include/freetype/ftcolor.h
index 08dbac0ccc..3edaee4ec1 100644
--- a/thirdparty/freetype/include/freetype/ftcolor.h
+++ b/thirdparty/freetype/include/freetype/ftcolor.h
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (specification).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -528,14 +528,14 @@ FT_BEGIN_HEADER
* @fields:
* num_color_stops ::
* The number of color stops for the requested glyph index. Set by
- * @FT_Get_Colorline_Stops.
+ * @FT_Get_Paint.
*
* current_color_stop ::
* The current color stop. Set by @FT_Get_Colorline_Stops.
*
* p ::
- * An opaque pointer into 'COLR' table data. The caller must set this
- * to `NULL` before the first call of @FT_Get_Colorline_Stops.
+ * An opaque pointer into 'COLR' table data. Set by @FT_Get_Paint.
+ * Updated by @FT_Get_Colorline_Stops.
*
* @since:
* 2.11 -- **currently experimental only!** There might be changes
diff --git a/thirdparty/freetype/include/freetype/ftdriver.h b/thirdparty/freetype/include/freetype/ftdriver.h
index 4936639056..0dc91e8b40 100644
--- a/thirdparty/freetype/include/freetype/ftdriver.h
+++ b/thirdparty/freetype/include/freetype/ftdriver.h
@@ -4,7 +4,7 @@
*
* FreeType API for controlling driver modules (specification only).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -212,16 +212,14 @@ FT_BEGIN_HEADER
* @description:
* While FreeType's TrueType driver doesn't expose API functions by
* itself, it is possible to control its behaviour with @FT_Property_Set
- * and @FT_Property_Get. The following lists the available properties
- * together with the necessary macros and structures.
- *
- * The TrueType driver's module name is 'truetype'.
+ * and @FT_Property_Get.
*
- * A single property @interpreter-version is available, as documented in
- * the @properties section.
+ * The TrueType driver's module name is 'truetype'; a single property
+ * @interpreter-version is available, as documented in the @properties
+ * section.
*
- * We start with a list of definitions, kindly provided by Greg
- * Hitchcock.
+ * To help understand the differences between interpreter versions, we
+ * introduce a list of definitions, kindly provided by Greg Hitchcock.
*
* _Bi-Level Rendering_
*
@@ -303,6 +301,31 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @section:
+ * ot_svg_driver
+ *
+ * @title:
+ * The SVG driver
+ *
+ * @abstract:
+ * Controlling the external rendering of OT-SVG glyphs.
+ *
+ * @description:
+ * By default, FreeType can only load the 'SVG~' table of OpenType fonts
+ * if configuration macro `FT_CONFIG_OPTION_SVG` is defined. To make it
+ * render SVG glyphs, an external SVG rendering library is needed. All
+ * details on the interface between FreeType and the external library
+ * via function hooks can be found in section @svg_fonts.
+ *
+ * The OT-SVG driver's module name is 'ot-svg'; it supports a single
+ * property called @svg-hooks, documented below in the @properties
+ * section.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @section:
* properties
*
* @title:
@@ -801,6 +824,40 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @property:
+ * svg-hooks
+ *
+ * @description:
+ * Set up the interface between FreeType and an extern SVG rendering
+ * library like 'librsvg'. All details on the function hooks can be
+ * found in section @svg_fonts.
+ *
+ * @example:
+ * The following example code expects that the four hook functions
+ * `svg_*` are defined elsewhere. Error handling is omitted, too.
+ *
+ * ```
+ * FT_Library library;
+ * SVG_RendererHooks hooks = {
+ * (SVG_Lib_Init_Func)svg_init,
+ * (SVG_Lib_Free_Func)svg_free,
+ * (SVG_Lib_Render_Func)svg_render,
+ * (SVG_Lib_Preset_Slot_Func)svg_preset_slot };
+ *
+ *
+ * FT_Init_FreeType( &library );
+ *
+ * FT_Property_Set( library, "ot-svg",
+ * "svg-hooks", &hooks );
+ * ```
+ *
+ * @since:
+ * 2.12
+ */
+
+
+ /**************************************************************************
+ *
+ * @property:
* glyph-to-script-map
*
* @description:
diff --git a/thirdparty/freetype/include/freetype/fterrdef.h b/thirdparty/freetype/include/freetype/fterrdef.h
index 6e9c4ccb97..a3acfce430 100644
--- a/thirdparty/freetype/include/freetype/fterrdef.h
+++ b/thirdparty/freetype/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
*
* FreeType error codes (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -101,6 +101,8 @@
"too many hints" )
FT_ERRORDEF_( Invalid_Pixel_Size, 0x17,
"invalid pixel size" )
+ FT_ERRORDEF_( Invalid_SVG_Document, 0x18,
+ "invalid SVG document" )
/* handle errors */
@@ -234,6 +236,8 @@
"found FDEF or IDEF opcode in glyf bytecode" )
FT_ERRORDEF_( Missing_Bitmap, 0x9D,
"missing bitmap in strike" )
+ FT_ERRORDEF_( Missing_SVG_Hooks, 0x9E,
+ "SVG hooks have not been set" )
/* CFF, CID, and Type 1 errors */
diff --git a/thirdparty/freetype/include/freetype/fterrors.h b/thirdparty/freetype/include/freetype/fterrors.h
index 151941dde0..ff1b375d7d 100644
--- a/thirdparty/freetype/include/freetype/fterrors.h
+++ b/thirdparty/freetype/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
*
* FreeType error code handling (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftfntfmt.h b/thirdparty/freetype/include/freetype/ftfntfmt.h
index 8e68a4a3ac..77d553578b 100644
--- a/thirdparty/freetype/include/freetype/ftfntfmt.h
+++ b/thirdparty/freetype/include/freetype/ftfntfmt.h
@@ -4,7 +4,7 @@
*
* Support functions for font formats.
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftgasp.h b/thirdparty/freetype/include/freetype/ftgasp.h
index 76c45eb3b1..d4ab9b32db 100644
--- a/thirdparty/freetype/include/freetype/ftgasp.h
+++ b/thirdparty/freetype/include/freetype/ftgasp.h
@@ -4,7 +4,7 @@
*
* Access of TrueType's 'gasp' table (specification).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftglyph.h b/thirdparty/freetype/include/freetype/ftglyph.h
index 26b32ed6be..6b77bd3d2a 100644
--- a/thirdparty/freetype/include/freetype/ftglyph.h
+++ b/thirdparty/freetype/include/freetype/ftglyph.h
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -126,7 +126,7 @@ FT_BEGIN_HEADER
*
* @description:
* A handle to an object used to model a bitmap glyph image. This is a
- * sub-class of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec.
+ * 'sub-class' of @FT_Glyph, and a pointer to @FT_BitmapGlyphRec.
*/
typedef struct FT_BitmapGlyphRec_* FT_BitmapGlyph;
@@ -142,7 +142,7 @@ FT_BEGIN_HEADER
*
* @fields:
* root ::
- * The root @FT_Glyph fields.
+ * The root fields of @FT_Glyph.
*
* left ::
* The left-side bearing, i.e., the horizontal distance from the
@@ -181,7 +181,7 @@ FT_BEGIN_HEADER
*
* @description:
* A handle to an object used to model an outline glyph image. This is a
- * sub-class of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec.
+ * 'sub-class' of @FT_Glyph, and a pointer to @FT_OutlineGlyphRec.
*/
typedef struct FT_OutlineGlyphRec_* FT_OutlineGlyph;
@@ -224,6 +224,92 @@ FT_BEGIN_HEADER
/**************************************************************************
*
+ * @type:
+ * FT_SvgGlyph
+ *
+ * @description:
+ * A handle to an object used to model an SVG glyph. This is a
+ * 'sub-class' of @FT_Glyph, and a pointer to @FT_SvgGlyphRec.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef struct FT_SvgGlyphRec_* FT_SvgGlyph;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SvgGlyphRec
+ *
+ * @description:
+ * A structure used for OT-SVG glyphs. This is a 'sub-class' of
+ * @FT_GlyphRec.
+ *
+ * @fields:
+ * root ::
+ * The root @FT_GlyphRec fields.
+ *
+ * svg_document ::
+ * A pointer to the SVG document.
+ *
+ * svg_document_length ::
+ * The length of `svg_document`.
+ *
+ * glyph_index ::
+ * The index of the glyph to be rendered.
+ *
+ * metrics ::
+ * A metrics object storing the size information.
+ *
+ * units_per_EM ::
+ * The size of the EM square.
+ *
+ * start_glyph_id ::
+ * The first glyph ID in the glyph range covered by this document.
+ *
+ * end_glyph_id ::
+ * The last glyph ID in the glyph range covered by this document.
+ *
+ * transform ::
+ * A 2x2 transformation matrix to apply to the glyph while rendering
+ * it.
+ *
+ * delta ::
+ * Translation to apply to the glyph while rendering.
+ *
+ * @note:
+ * The Glyph Management API requires @FT_Glyph or its 'sub-class' to have
+ * all the information needed to completely define the glyph's rendering.
+ * Outline-based glyphs can directly apply transformations to the outline
+ * but this is not possible for an SVG document that hasn't been parsed.
+ * Therefore, the transformation is stored along with the document. In
+ * the absence of a 'ViewBox' or 'Width'/'Height' attribute, the size of
+ * the ViewPort should be assumed to be 'units_per_EM'.
+ */
+ typedef struct FT_SvgGlyphRec_
+ {
+ FT_GlyphRec root;
+
+ FT_Byte* svg_document;
+ FT_ULong svg_document_length;
+
+ FT_UInt glyph_index;
+
+ FT_Size_Metrics metrics;
+ FT_UShort units_per_EM;
+
+ FT_UShort start_glyph_id;
+ FT_UShort end_glyph_id;
+
+ FT_Matrix transform;
+ FT_Vector delta;
+
+ } FT_SvgGlyphRec;
+
+
+ /**************************************************************************
+ *
* @function:
* FT_New_Glyph
*
@@ -498,9 +584,9 @@ FT_BEGIN_HEADER
* The glyph image is translated with the `origin` vector before
* rendering.
*
- * The first parameter is a pointer to an @FT_Glyph handle, that will be
+ * The first parameter is a pointer to an @FT_Glyph handle that will be
* _replaced_ by this function (with newly allocated data). Typically,
- * you would use (omitting error handling):
+ * you would do something like the following (omitting error handling).
*
* ```
* FT_Glyph glyph;
@@ -517,7 +603,7 @@ FT_BEGIN_HEADER
* if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
* {
* error = FT_Glyph_To_Bitmap( &glyph, FT_RENDER_MODE_NORMAL,
- * 0, 1 );
+ * 0, 1 );
* if ( error ) // `glyph' unchanged
* ...
* }
@@ -532,7 +618,7 @@ FT_BEGIN_HEADER
* FT_Done_Glyph( glyph );
* ```
*
- * Here is another example, again without error handling:
+ * Here is another example, again without error handling.
*
* ```
* FT_Glyph glyphs[MAX_GLYPHS]
diff --git a/thirdparty/freetype/include/freetype/ftgxval.h b/thirdparty/freetype/include/freetype/ftgxval.h
index 21bbbde2ae..2d3f382acf 100644
--- a/thirdparty/freetype/include/freetype/ftgxval.h
+++ b/thirdparty/freetype/include/freetype/ftgxval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO, Redhat K.K,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/ftgzip.h b/thirdparty/freetype/include/freetype/ftgzip.h
index ba82baba64..0880290f9e 100644
--- a/thirdparty/freetype/include/freetype/ftgzip.h
+++ b/thirdparty/freetype/include/freetype/ftgzip.h
@@ -4,7 +4,7 @@
*
* Gzip-compressed stream support.
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftimage.h b/thirdparty/freetype/include/freetype/ftimage.h
index 88533b8409..7f2d721cdc 100644
--- a/thirdparty/freetype/include/freetype/ftimage.h
+++ b/thirdparty/freetype/include/freetype/ftimage.h
@@ -5,7 +5,7 @@
* FreeType glyph image formats and default raster interface
* (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -401,11 +401,11 @@ FT_BEGIN_HEADER
* information.
*
* FT_OUTLINE_OVERLAP ::
- * This flag indicates that this outline contains overlapping contrours
- * and the anti-aliased renderer should perform oversampling to
- * mitigate possible artifacts. This flag should _not_ be set for
- * well designed glyphs without overlaps because it quadruples the
- * rendering time.
+ * [Since 2.10.3] This flag indicates that this outline contains
+ * overlapping contours and the anti-aliased renderer should perform
+ * oversampling to mitigate possible artifacts. This flag should _not_
+ * be set for well designed glyphs without overlaps because it quadruples
+ * the rendering time.
*
* FT_OUTLINE_HIGH_PRECISION ::
* This flag indicates that the scan-line converter should try to
@@ -741,6 +741,10 @@ FT_BEGIN_HEADER
* contours. Some Type~1 fonts, like those in the Hershey family,
* contain glyphs in this format. These are described as @FT_Outline,
* but FreeType isn't currently capable of rendering them correctly.
+ *
+ * FT_GLYPH_FORMAT_SVG ::
+ * [Since 2.12] The glyph is represented by an SVG document in the
+ * 'SVG~' table.
*/
typedef enum FT_Glyph_Format_
{
@@ -749,7 +753,8 @@ FT_BEGIN_HEADER
FT_IMAGE_TAG( FT_GLYPH_FORMAT_COMPOSITE, 'c', 'o', 'm', 'p' ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_BITMAP, 'b', 'i', 't', 's' ),
FT_IMAGE_TAG( FT_GLYPH_FORMAT_OUTLINE, 'o', 'u', 't', 'l' ),
- FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' )
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_PLOTTER, 'p', 'l', 'o', 't' ),
+ FT_IMAGE_TAG( FT_GLYPH_FORMAT_SVG, 'S', 'V', 'G', ' ' )
} FT_Glyph_Format;
diff --git a/thirdparty/freetype/include/freetype/ftincrem.h b/thirdparty/freetype/include/freetype/ftincrem.h
index 229b947bd8..3b3d93c2d3 100644
--- a/thirdparty/freetype/include/freetype/ftincrem.h
+++ b/thirdparty/freetype/include/freetype/ftincrem.h
@@ -4,7 +4,7 @@
*
* FreeType incremental loading (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlcdfil.h b/thirdparty/freetype/include/freetype/ftlcdfil.h
index 18e2544175..c767c6cb48 100644
--- a/thirdparty/freetype/include/freetype/ftlcdfil.h
+++ b/thirdparty/freetype/include/freetype/ftlcdfil.h
@@ -5,7 +5,7 @@
* FreeType API for color filtering of subpixel bitmap glyphs
* (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlist.h b/thirdparty/freetype/include/freetype/ftlist.h
index 55f015977a..4dca2bf163 100644
--- a/thirdparty/freetype/include/freetype/ftlist.h
+++ b/thirdparty/freetype/include/freetype/ftlist.h
@@ -4,7 +4,7 @@
*
* Generic list support for FreeType (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlogging.h b/thirdparty/freetype/include/freetype/ftlogging.h
index a558b85faf..7213dc30a8 100644
--- a/thirdparty/freetype/include/freetype/ftlogging.h
+++ b/thirdparty/freetype/include/freetype/ftlogging.h
@@ -4,7 +4,7 @@
*
* Additional debugging APIs.
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftlzw.h b/thirdparty/freetype/include/freetype/ftlzw.h
index fce1c9c4bb..3d7cfd52f7 100644
--- a/thirdparty/freetype/include/freetype/ftlzw.h
+++ b/thirdparty/freetype/include/freetype/ftlzw.h
@@ -4,7 +4,7 @@
*
* LZW-compressed stream support.
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmac.h b/thirdparty/freetype/include/freetype/ftmac.h
index 607af9b589..3dd61d0fe1 100644
--- a/thirdparty/freetype/include/freetype/ftmac.h
+++ b/thirdparty/freetype/include/freetype/ftmac.h
@@ -4,7 +4,7 @@
*
* Additional Mac-specific API.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmm.h b/thirdparty/freetype/include/freetype/ftmm.h
index 32579e997f..c74ce618cb 100644
--- a/thirdparty/freetype/include/freetype/ftmm.h
+++ b/thirdparty/freetype/include/freetype/ftmm.h
@@ -4,7 +4,7 @@
*
* FreeType Multiple Master font interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -47,6 +47,9 @@ FT_BEGIN_HEADER
* MM fonts, others will work with all three types. They are similar
* enough that a consistent interface makes sense.
*
+ * For Adobe MM fonts, macro @FT_IS_SFNT returns false. For GX and
+ * OpenType variation fonts, it returns true.
+ *
*/
diff --git a/thirdparty/freetype/include/freetype/ftmodapi.h b/thirdparty/freetype/include/freetype/ftmodapi.h
index b77d356de9..b78db724c7 100644
--- a/thirdparty/freetype/include/freetype/ftmodapi.h
+++ b/thirdparty/freetype/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
*
* FreeType modules public interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftmoderr.h b/thirdparty/freetype/include/freetype/ftmoderr.h
index b417cd5ab7..88d2917771 100644
--- a/thirdparty/freetype/include/freetype/ftmoderr.h
+++ b/thirdparty/freetype/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
*
* FreeType module error offsets (specification).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftotval.h b/thirdparty/freetype/include/freetype/ftotval.h
index 00f9727859..172fcf2402 100644
--- a/thirdparty/freetype/include/freetype/ftotval.h
+++ b/thirdparty/freetype/include/freetype/ftotval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating OpenType tables (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftoutln.h b/thirdparty/freetype/include/freetype/ftoutln.h
index 6bb5f809a9..46ebf9371b 100644
--- a/thirdparty/freetype/include/freetype/ftoutln.h
+++ b/thirdparty/freetype/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
* Support for the FT_Outline type used to store glyph shapes of
* most scalable font formats (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -109,11 +109,13 @@ FT_BEGIN_HEADER
* FreeType error code. 0~means success.
*
* @note:
- * A contour that contains a single point only is represented by a 'move
- * to' operation followed by 'line to' to the same point. In most cases,
- * it is best to filter this out before using the outline for stroking
- * purposes (otherwise it would result in a visible dot when round caps
- * are used).
+ * Degenerate contours, segments, and Bezier arcs may be reported. In
+ * most cases, it is best to filter these out before using the outline
+ * for stroking or other path modification purposes (which may cause
+ * degenerate segments to become non-degenrate and visible, like when
+ * stroke caps are used or the path is otherwise outset). Some glyph
+ * outlines may contain deliberate degenerate single points for mark
+ * attachement.
*
* Similarly, the function returns success for an empty outline also
* (doing nothing, this is, not calling any emitter); if necessary, you
diff --git a/thirdparty/freetype/include/freetype/ftparams.h b/thirdparty/freetype/include/freetype/ftparams.h
index 04a3f44126..72080f396a 100644
--- a/thirdparty/freetype/include/freetype/ftparams.h
+++ b/thirdparty/freetype/include/freetype/ftparams.h
@@ -4,7 +4,7 @@
*
* FreeType API for possible FT_Parameter tags (specification only).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -115,6 +115,21 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @enum:
+ * FT_PARAM_TAG_IGNORE_SBIX
+ *
+ * @description:
+ * A tag for @FT_Parameter to make @FT_Open_Face ignore an 'sbix' table
+ * while loading a font. Use this if @FT_FACE_FLAG_SBIX is set and you
+ * want to access the outline glyphs in the font.
+ *
+ */
+#define FT_PARAM_TAG_IGNORE_SBIX \
+ FT_MAKE_TAG( 'i', 's', 'b', 'x' )
+
+
+ /**************************************************************************
+ *
+ * @enum:
* FT_PARAM_TAG_LCD_FILTER_WEIGHTS
*
* @description:
diff --git a/thirdparty/freetype/include/freetype/ftpfr.h b/thirdparty/freetype/include/freetype/ftpfr.h
index fbdb14c202..428e327061 100644
--- a/thirdparty/freetype/include/freetype/ftpfr.h
+++ b/thirdparty/freetype/include/freetype/ftpfr.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing PFR-specific data (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftrender.h b/thirdparty/freetype/include/freetype/ftrender.h
index 48d489d496..0fab3f8c2a 100644
--- a/thirdparty/freetype/include/freetype/ftrender.h
+++ b/thirdparty/freetype/include/freetype/ftrender.h
@@ -4,7 +4,7 @@
*
* FreeType renderer modules public interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsizes.h b/thirdparty/freetype/include/freetype/ftsizes.h
index 22366393b8..e30938d862 100644
--- a/thirdparty/freetype/include/freetype/ftsizes.h
+++ b/thirdparty/freetype/include/freetype/ftsizes.h
@@ -4,7 +4,7 @@
*
* FreeType size objects management (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsnames.h b/thirdparty/freetype/include/freetype/ftsnames.h
index c7f6581cb3..384096a585 100644
--- a/thirdparty/freetype/include/freetype/ftsnames.h
+++ b/thirdparty/freetype/include/freetype/ftsnames.h
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftstroke.h b/thirdparty/freetype/include/freetype/ftstroke.h
index 88b2a8a4ed..12c006d3fb 100644
--- a/thirdparty/freetype/include/freetype/ftstroke.h
+++ b/thirdparty/freetype/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
*
* FreeType path stroker (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsynth.h b/thirdparty/freetype/include/freetype/ftsynth.h
index 861dcb5ac5..afc40b1d84 100644
--- a/thirdparty/freetype/include/freetype/ftsynth.h
+++ b/thirdparty/freetype/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
* FreeType synthesizing code for emboldening and slanting
* (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftsystem.h b/thirdparty/freetype/include/freetype/ftsystem.h
index e5abb85a85..5f8aec7b7c 100644
--- a/thirdparty/freetype/include/freetype/ftsystem.h
+++ b/thirdparty/freetype/include/freetype/ftsystem.h
@@ -4,7 +4,7 @@
*
* FreeType low-level system interface definition (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fttrigon.h b/thirdparty/freetype/include/freetype/fttrigon.h
index dbe7b0d388..4e8d871dec 100644
--- a/thirdparty/freetype/include/freetype/fttrigon.h
+++ b/thirdparty/freetype/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (specification).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/fttypes.h b/thirdparty/freetype/include/freetype/fttypes.h
index 699bd003c0..29f32fbb26 100644
--- a/thirdparty/freetype/include/freetype/fttypes.h
+++ b/thirdparty/freetype/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
*
* FreeType simple types definitions (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/ftwinfnt.h b/thirdparty/freetype/include/freetype/ftwinfnt.h
index f30f447d84..294f85ae0d 100644
--- a/thirdparty/freetype/include/freetype/ftwinfnt.h
+++ b/thirdparty/freetype/include/freetype/ftwinfnt.h
@@ -4,7 +4,7 @@
*
* FreeType API for accessing Windows fnt-specific data.
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/autohint.h b/thirdparty/freetype/include/freetype/internal/autohint.h
index 01585f5edf..aedf48984d 100644
--- a/thirdparty/freetype/include/freetype/internal/autohint.h
+++ b/thirdparty/freetype/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
*
* High-level 'autohint' module-specific interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/cffotypes.h b/thirdparty/freetype/include/freetype/internal/cffotypes.h
index a91dd556ca..700f586c41 100644
--- a/thirdparty/freetype/include/freetype/internal/cffotypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cffotypes.h
@@ -4,7 +4,7 @@
*
* Basic OpenType/CFF object type definitions (specification).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/cfftypes.h b/thirdparty/freetype/include/freetype/internal/cfftypes.h
index 99e8d41368..23d26c1b34 100644
--- a/thirdparty/freetype/include/freetype/internal/cfftypes.h
+++ b/thirdparty/freetype/include/freetype/internal/cfftypes.h
@@ -5,7 +5,7 @@
* Basic OpenType/CFF type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/compiler-macros.h b/thirdparty/freetype/include/freetype/internal/compiler-macros.h
index d8b61b3dc9..66fa13c3c5 100644
--- a/thirdparty/freetype/include/freetype/internal/compiler-macros.h
+++ b/thirdparty/freetype/include/freetype/internal/compiler-macros.h
@@ -4,7 +4,7 @@
*
* Compiler-specific macro definitions used internally by FreeType.
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -299,10 +299,12 @@ FT_BEGIN_HEADER
#define FT_CALLBACK_DEF( x ) static x
#endif
-#if defined( __i386__ )
+#if defined( __GNUC__ ) && defined( __i386__ )
#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __attribute__(( cdecl ))
-#elif defined( _M_IX86 )
+#elif defined( _MSC_VER ) && defined( _M_IX86 )
#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __cdecl
+#elif defined( __WATCOMC__ ) && __WATCOMC__ >= 1240
+#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __watcall
#else
#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x )
#endif
diff --git a/thirdparty/freetype/include/freetype/internal/ftcalc.h b/thirdparty/freetype/include/freetype/internal/ftcalc.h
index f88e055318..e6a87db94e 100644
--- a/thirdparty/freetype/include/freetype/internal/ftcalc.h
+++ b/thirdparty/freetype/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
*
* Arithmetic computations (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -408,6 +408,19 @@ FT_BEGIN_HEADER
#endif
+#elif defined( __WATCOMC__ ) && defined( __386__ )
+
+ extern __inline FT_Int32
+ FT_MSB_i386( FT_UInt32 x );
+
+#pragma aux FT_MSB_i386 = \
+ "bsr eax, eax" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+
+#define FT_MSB( x ) FT_MSB_i386( x )
+
#elif defined( __DECC ) || defined( __DECCXX )
#include <builtins.h>
diff --git a/thirdparty/freetype/include/freetype/internal/ftdebug.h b/thirdparty/freetype/include/freetype/internal/ftdebug.h
index 5e8d9294a2..f05b1395cb 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdebug.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
*
* Debugging and logging component (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftdrv.h b/thirdparty/freetype/include/freetype/internal/ftdrv.h
index 0db323d5ab..9459a9a190 100644
--- a/thirdparty/freetype/include/freetype/internal/ftdrv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftdrv.h
@@ -4,7 +4,7 @@
*
* FreeType internal font driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftgloadr.h b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
index fea931c3aa..f73b6631c8 100644
--- a/thirdparty/freetype/include/freetype/internal/ftgloadr.h
+++ b/thirdparty/freetype/include/freetype/internal/ftgloadr.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftmemory.h b/thirdparty/freetype/include/freetype/internal/ftmemory.h
index e20d949696..10d753aa5e 100644
--- a/thirdparty/freetype/include/freetype/internal/ftmemory.h
+++ b/thirdparty/freetype/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
*
* The FreeType memory management macros (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftobjs.h b/thirdparty/freetype/include/freetype/internal/ftobjs.h
index e52a26aa06..1c779ceaeb 100644
--- a/thirdparty/freetype/include/freetype/internal/ftobjs.h
+++ b/thirdparty/freetype/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -418,7 +418,8 @@ FT_BEGIN_HEADER
* initializing the glyph slot.
*/
-#define FT_GLYPH_OWN_BITMAP 0x1U
+#define FT_GLYPH_OWN_BITMAP 0x1U
+#define FT_GLYPH_OWN_GZIP_SVG 0x2U
typedef struct FT_Slot_InternalRec_
{
diff --git a/thirdparty/freetype/include/freetype/internal/ftpsprop.h b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
index d94d0d7e4b..47373211cb 100644
--- a/thirdparty/freetype/include/freetype/internal/ftpsprop.h
+++ b/thirdparty/freetype/include/freetype/internal/ftpsprop.h
@@ -4,7 +4,7 @@
*
* Get and set properties of PostScript drivers (specification).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftrfork.h b/thirdparty/freetype/include/freetype/internal/ftrfork.h
index 1c56d6ceb7..165e67f245 100644
--- a/thirdparty/freetype/include/freetype/internal/ftrfork.h
+++ b/thirdparty/freetype/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO and Redhat K.K.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftserv.h b/thirdparty/freetype/include/freetype/internal/ftserv.h
index fa82c31fcd..78996d9c85 100644
--- a/thirdparty/freetype/include/freetype/internal/ftserv.h
+++ b/thirdparty/freetype/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
*
* The FreeType services (specification only).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/ftstream.h b/thirdparty/freetype/include/freetype/internal/ftstream.h
index 7f3af120c2..aa51fe5a87 100644
--- a/thirdparty/freetype/include/freetype/internal/ftstream.h
+++ b/thirdparty/freetype/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
*
* Stream handling (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/fttrace.h b/thirdparty/freetype/include/freetype/internal/fttrace.h
index 3307556bff..43c6a8713b 100644
--- a/thirdparty/freetype/include/freetype/internal/fttrace.h
+++ b/thirdparty/freetype/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
*
* Tracing handling (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -49,6 +49,9 @@ FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */
FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */
FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */
+ /* ot-svg module */
+FT_TRACE_DEF( otsvg ) /* OT-SVG renderer (ftsvg.c) */
+
/* cache sub-system */
FT_TRACE_DEF( cache ) /* cache sub-system (ftcache.c, etc.) */
@@ -61,6 +64,7 @@ FT_TRACE_DEF( ttbdf ) /* TrueType embedded BDF (ttbdf.c) */
FT_TRACE_DEF( ttcmap ) /* charmap handler (ttcmap.c) */
FT_TRACE_DEF( ttcolr ) /* glyph layer table (ttcolr.c) */
FT_TRACE_DEF( ttcpal ) /* color palette table (ttcpal.c) */
+FT_TRACE_DEF( ttsvg ) /* OpenType SVG table (ttsvg.c) */
FT_TRACE_DEF( ttkern ) /* kerning handler (ttkern.c) */
FT_TRACE_DEF( ttload ) /* basic TrueType tables (ttload.c) */
FT_TRACE_DEF( ttmtx ) /* metrics-related tables (ttmtx.c) */
diff --git a/thirdparty/freetype/include/freetype/internal/ftvalid.h b/thirdparty/freetype/include/freetype/internal/ftvalid.h
index 7bdfa62f32..171c2cb6f5 100644
--- a/thirdparty/freetype/include/freetype/internal/ftvalid.h
+++ b/thirdparty/freetype/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
*
* FreeType validation support (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/psaux.h b/thirdparty/freetype/include/freetype/internal/psaux.h
index 6c6399aa16..48ec1df963 100644
--- a/thirdparty/freetype/include/freetype/internal/psaux.h
+++ b/thirdparty/freetype/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
* Auxiliary functions and data structures related to PostScript fonts
* (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/pshints.h b/thirdparty/freetype/include/freetype/internal/pshints.h
index 9dbb0776b0..5de83e4565 100644
--- a/thirdparty/freetype/include/freetype/internal/pshints.h
+++ b/thirdparty/freetype/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
* recorders (specification only). These are used to support native
* T1/T2 hints in the 'type1', 'cid', and 'cff' font drivers.
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svbdf.h b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
index 879aa61383..06e3b531c8 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svbdf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svbdf.h
@@ -4,7 +4,7 @@
*
* The FreeType BDF services (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
index f6424e424d..1dea6bcda9 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcfftl.h
@@ -4,7 +4,7 @@
*
* The FreeType CFF tables loader service (specification).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svcid.h b/thirdparty/freetype/include/freetype/internal/services/svcid.h
index 7ef5afd0b7..acf9178d0a 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svcid.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svcid.h
@@ -4,7 +4,7 @@
*
* The FreeType CID font services (specification).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
index cc87fc122d..a7280319c5 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svfntfmt.h
@@ -4,7 +4,7 @@
*
* The FreeType font format service (specification only).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgldict.h b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
index 4256f14a04..489021d897 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgldict.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgldict.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph dictionary services (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svgxval.h b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
index f36d55602a..59ae411b55 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svgxval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svgxval.h
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/internal/services/svkern.h b/thirdparty/freetype/include/freetype/internal/services/svkern.h
index 99dc2d97a3..c567acad46 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svkern.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svkern.h
@@ -4,7 +4,7 @@
*
* The FreeType Kerning service (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmetric.h b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
index b9c95a7c9c..7accdc46ff 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmetric.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmetric.h
@@ -4,7 +4,7 @@
*
* The FreeType services for metrics variations (specification).
*
- * Copyright (C) 2016-2021 by
+ * Copyright (C) 2016-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svmm.h b/thirdparty/freetype/include/freetype/internal/services/svmm.h
index 8eac3a3fe3..c6394890ac 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svmm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svmm.h
@@ -4,7 +4,7 @@
*
* The FreeType Multiple Masters and GX var services (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svotval.h b/thirdparty/freetype/include/freetype/internal/services/svotval.h
index 7afb49e824..3c72d1f855 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svotval.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svotval.h
@@ -4,7 +4,7 @@
*
* The FreeType OpenType validation service (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpfr.h b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
index 98442bf83d..bde0ed3545 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpfr.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpfr.h
@@ -4,7 +4,7 @@
*
* Internal PFR service functions (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
index 5a25c5a58a..05f6291e13 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpostnm.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript name services (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svprop.h b/thirdparty/freetype/include/freetype/internal/services/svprop.h
index 9b71000c52..29c568640b 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svprop.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svprop.h
@@ -4,7 +4,7 @@
*
* The FreeType property service (specification).
*
- * Copyright (C) 2012-2021 by
+ * Copyright (C) 2012-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
index 346f5e2a7c..7d586587a5 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpscmap.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript charmap service (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
index 49aa4d565d..6e45f3272d 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svpsinfo.h
@@ -4,7 +4,7 @@
*
* The FreeType PostScript info service (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
index 4306cbc1b7..03938a562b 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svsfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType SFNT table loading service (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
index 775b6bcf20..a0b1bbd2f3 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttcmap.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType/sfnt cmap extra information service.
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* Masatake YAMATO, Redhat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/include/freetype/internal/services/svtteng.h b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
index 964934284d..f8396eb08c 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svtteng.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svtteng.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType engine query service (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
index 4268467b75..982630c0aa 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svttglyf.h
@@ -4,7 +4,7 @@
*
* The FreeType TrueType glyph service.
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
index aa70aa44db..950f4a8824 100644
--- a/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/services/svwinfnt.h
@@ -4,7 +4,7 @@
*
* The FreeType Windows FNT/FONT service (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/sfnt.h b/thirdparty/freetype/include/freetype/internal/sfnt.h
index bf4c7e09fe..c67b47e860 100644
--- a/thirdparty/freetype/include/freetype/internal/sfnt.h
+++ b/thirdparty/freetype/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
*
* High-level 'sfnt' driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -314,6 +314,33 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @functype:
+ * TT_Load_Svg_Doc_Func
+ *
+ * @description:
+ * Scan the SVG document list to find the document containing the glyph
+ * that has the ID 'glyph*XXX*', where *XXX* is the value of
+ * `glyph_index` as a decimal integer.
+ *
+ * @inout:
+ * glyph ::
+ * The glyph slot from which pointers to the SVG document list is to be
+ * grabbed. The results are stored back in the slot.
+ *
+ * @input:
+ * glyph_index ::
+ * The index of the glyph that is to be looked up.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ */
+ typedef FT_Error
+ (*TT_Load_Svg_Doc_Func)( FT_GlyphSlot glyph,
+ FT_UInt glyph_index );
+
+
+ /**************************************************************************
+ *
+ * @functype:
* TT_Set_SBit_Strike_Func
*
* @description:
@@ -946,6 +973,11 @@ FT_BEGIN_HEADER
TT_Get_Name_Func get_name;
TT_Get_Name_ID_Func get_name_id;
+ /* OpenType SVG Support */
+ TT_Load_Table_Func load_svg;
+ TT_Free_Table_Func free_svg;
+ TT_Load_Svg_Doc_Func load_svg_doc;
+
} SFNT_Interface;
@@ -997,7 +1029,10 @@ FT_BEGIN_HEADER
colr_blend_, \
get_metrics_, \
get_name_, \
- get_name_id_ ) \
+ get_name_id_, \
+ load_svg_, \
+ free_svg_, \
+ load_svg_doc_ ) \
static const SFNT_Interface class_ = \
{ \
goto_table_, \
@@ -1042,7 +1077,10 @@ FT_BEGIN_HEADER
colr_blend_, \
get_metrics_, \
get_name_, \
- get_name_id_ \
+ get_name_id_, \
+ load_svg_, \
+ free_svg_, \
+ load_svg_doc_ \
};
diff --git a/thirdparty/freetype/include/freetype/internal/svginterface.h b/thirdparty/freetype/include/freetype/internal/svginterface.h
new file mode 100644
index 0000000000..1b325e5e9d
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/internal/svginterface.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+ *
+ * svginterface.h
+ *
+ * Interface of ot-svg module (specification only).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef SVGINTERFACE_H_
+#define SVGINTERFACE_H_
+
+#include <ft2build.h>
+#include <freetype/otsvg.h>
+
+
+FT_BEGIN_HEADER
+
+ typedef FT_Error
+ (*Preset_Bitmap_Func)( FT_Module module,
+ FT_GlyphSlot slot,
+ FT_Bool cache );
+
+ typedef struct SVG_Interface_
+ {
+ Preset_Bitmap_Func preset_slot;
+
+ } SVG_Interface;
+
+ typedef SVG_Interface* SVG_Service;
+
+FT_END_HEADER
+
+#endif /* SVGINTERFACE_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/internal/t1types.h b/thirdparty/freetype/include/freetype/internal/t1types.h
index 023c5d08a2..b6a3de14d0 100644
--- a/thirdparty/freetype/include/freetype/internal/t1types.h
+++ b/thirdparty/freetype/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
* Basic Type1/Type2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/internal/tttypes.h b/thirdparty/freetype/include/freetype/internal/tttypes.h
index 651131c8d3..df719387b5 100644
--- a/thirdparty/freetype/include/freetype/internal/tttypes.h
+++ b/thirdparty/freetype/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1390,8 +1390,8 @@ FT_BEGIN_HEADER
* hdmx_record_size ::
* The size of a single hdmx record.
*
- * hdmx_record_sizes ::
- * An array holding the ppem sizes available in the 'hdmx' table.
+ * hdmx_records ::
+ * A array of pointers to the 'hdmx' table records sorted by ppem.
*
* sbit_table ::
* A pointer to the font's embedded bitmap location table.
@@ -1605,7 +1605,7 @@ FT_BEGIN_HEADER
FT_ULong hdmx_table_size;
FT_UInt hdmx_record_count;
FT_ULong hdmx_record_size;
- FT_Byte* hdmx_record_sizes;
+ FT_Byte** hdmx_records;
FT_Byte* sbit_table;
FT_ULong sbit_table_size;
@@ -1644,6 +1644,9 @@ FT_BEGIN_HEADER
void* cpal;
void* colr;
+ /* since 2.12 */
+ void* svg;
+
} TT_FaceRec;
@@ -1769,6 +1772,9 @@ FT_BEGIN_HEADER
/* since version 2.6.2 */
FT_ListRec composites;
+ /* since version 2.11.2 */
+ FT_Byte* widthp;
+
} TT_LoaderRec;
diff --git a/thirdparty/freetype/include/freetype/internal/wofftypes.h b/thirdparty/freetype/include/freetype/internal/wofftypes.h
index c460107c4d..94804fa72f 100644
--- a/thirdparty/freetype/include/freetype/internal/wofftypes.h
+++ b/thirdparty/freetype/include/freetype/internal/wofftypes.h
@@ -5,7 +5,7 @@
* Basic WOFF/WOFF2 type definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/otsvg.h b/thirdparty/freetype/include/freetype/otsvg.h
new file mode 100644
index 0000000000..2caadfdeeb
--- /dev/null
+++ b/thirdparty/freetype/include/freetype/otsvg.h
@@ -0,0 +1,336 @@
+/****************************************************************************
+ *
+ * otsvg.h
+ *
+ * Interface for OT-SVG support related things (specification).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+#ifndef OTSVG_H_
+#define OTSVG_H_
+
+#include <freetype/freetype.h>
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+
+FT_BEGIN_HEADER
+
+
+ /**************************************************************************
+ *
+ * @section:
+ * svg_fonts
+ *
+ * @title:
+ * OpenType SVG Fonts
+ *
+ * @abstract:
+ * OT-SVG API between FreeType and an external SVG rendering library.
+ *
+ * @description:
+ * This section describes the four hooks necessary to render SVG
+ * 'documents' that are contained in an OpenType font's 'SVG~' table.
+ *
+ * For more information on the implementation, see our standard hooks
+ * based on 'librsvg' in the [FreeType Demo
+ * Programs](https://gitlab.freedesktop.org/freetype/freetype-demos)
+ * repository.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * SVG_Lib_Init_Func
+ *
+ * @description:
+ * A callback that is called when the first OT-SVG glyph is rendered in
+ * the lifetime of an @FT_Library object. In a typical implementation,
+ * one would want to allocate a structure and point the `data_pointer`
+ * to it and perform any library initializations that might be needed.
+ *
+ * @inout:
+ * data_pointer ::
+ * The SVG rendering module stores a pointer variable that can be used
+ * by clients to store any data that needs to be shared across
+ * different hooks. `data_pointer` is essentially a pointer to that
+ * pointer such that it can be written to as well as read from.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef FT_Error
+ (*SVG_Lib_Init_Func)( FT_Pointer *data_pointer );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * SVG_Lib_Free_Func
+ *
+ * @description:
+ * A callback that is called when the `ot-svg` module is being freed.
+ * It is only called if the init hook was called earlier. This means
+ * that neither the init nor the free hook is called if no OT-SVG glyph
+ * is rendered.
+ *
+ * In a typical implementation, one would want to free any state
+ * structure that was allocated in the init hook and perform any
+ * library-related closure that might be needed.
+ *
+ * @inout:
+ * data_pointer ::
+ * The SVG rendering module stores a pointer variable that can be used
+ * by clients to store any data that needs to be shared across
+ * different hooks. `data_pointer` is essentially a pointer to that
+ * pointer such that it can be written to as well as read from.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef void
+ (*SVG_Lib_Free_Func)( FT_Pointer *data_pointer );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * SVG_Lib_Render_Func
+ *
+ * @description:
+ * A callback that is called to render an OT-SVG glyph. This callback
+ * hook is called right after the preset hook @SVG_Lib_Preset_Slot_Func
+ * has been called with `cache` set to `TRUE`. The data necessary to
+ * render is available through the handle @FT_SVG_Document, which is set
+ * in the `other` field of @FT_GlyphSlotRec.
+ *
+ * The render hook is expected to render the SVG glyph to the bitmap
+ * buffer that is allocated already at `slot->bitmap.buffer`. It also
+ * sets the `num_grays` value as well as `slot->format`.
+ *
+ * @input:
+ * slot ::
+ * The slot to render.
+ *
+ * @inout:
+ * data_pointer ::
+ * The SVG rendering module stores a pointer variable that can be used
+ * by clients to store any data that needs to be shared across
+ * different hooks. `data_pointer` is essentially a pointer to that
+ * pointer such that it can be written to as well as read from.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef FT_Error
+ (*SVG_Lib_Render_Func)( FT_GlyphSlot slot,
+ FT_Pointer *data_pointer );
+
+
+ /**************************************************************************
+ *
+ * @functype:
+ * SVG_Lib_Preset_Slot_Func
+ *
+ * @description:
+ * A callback that is called to preset the glyph slot. It is called from
+ * two places.
+ *
+ * 1. When `FT_Load_Glyph` needs to preset the glyph slot.
+ *
+ * 2. Right before the `svg` module calls the render callback hook.
+ *
+ * When it is the former, the argument `cache` is set to `FALSE`. When
+ * it is the latter, the argument `cache` is set to `TRUE`. This
+ * distinction has been made because many calculations that are necessary
+ * for presetting a glyph slot are the same needed later for the render
+ * callback hook. Thus, if `cache` is `TRUE`, the hook can _cache_ those
+ * calculations in a memory block referenced by the state pointer.
+ *
+ * This hook is expected to preset the slot by setting parameters such as
+ * `bitmap_left`, `bitmap_top`, `width`, `rows`, `pitch`, and
+ * `pixel_mode`. It is also expected to set all the metrics for the slot
+ * including the vertical advance if it is not already set. Typically,
+ * fonts have horizontal advances but not vertical ones. If those are
+ * available, they had already been set, otherwise they have to be
+ * estimated and set manually. The hook must take into account the
+ * transformations that have been set, and translate the transformation
+ * matrices into the SVG coordinate system, as the original matrix is
+ * intended for the TTF/CFF coordinate system.
+ *
+ * @input:
+ * slot ::
+ * The glyph slot that has the SVG document loaded.
+ *
+ * cache ::
+ * See description.
+ *
+ * @inout:
+ * data_pointer ::
+ * The SVG rendering module stores a pointer variable that can be used
+ * by clients to store any data that needs to be shared across
+ * different hooks. `data_pointer` is essentially a pointer to that
+ * pointer such that it can be written to as well as read from.
+ *
+ * @return:
+ * FreeType error code. 0 means success.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef FT_Error
+ (*SVG_Lib_Preset_Slot_Func)( FT_GlyphSlot slot,
+ FT_Bool cache,
+ FT_Pointer *state );
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * SVG_RendererHooks
+ *
+ * @description:
+ * A structure that stores the four hooks needed to render OT-SVG glyphs
+ * properly. The structure is publicly used to set the hooks via the
+ * @svg-hooks driver property.
+ *
+ * The behavior of each hook is described in its documentation. One
+ * thing to note is that the preset hook and the render hook often need
+ * to do the same operations; therefore, it's better to cache the
+ * intermediate data in a state structure to avoid calculating it twice.
+ * For example, in the preset hook one can draw the glyph on a recorder
+ * surface and later create a bitmap surface from it in the render hook.
+ *
+ * All four hooks must be non-NULL.
+ *
+ * @fields:
+ * init_svg ::
+ * The initialization hook.
+ *
+ * free_svg ::
+ * The cleanup hook.
+ *
+ * render_hook ::
+ * The render hook.
+ *
+ * preset_slot ::
+ * The preset hook.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef struct SVG_RendererHooks_
+ {
+ SVG_Lib_Init_Func init_svg;
+ SVG_Lib_Free_Func free_svg;
+ SVG_Lib_Render_Func render_svg;
+
+ SVG_Lib_Preset_Slot_Func preset_slot;
+
+ } SVG_RendererHooks;
+
+
+ /**************************************************************************
+ *
+ * @struct:
+ * FT_SVG_DocumentRec
+ *
+ * @description:
+ * A structure that models one SVG document.
+ *
+ * @fields:
+ * svg_document ::
+ * A pointer to the SVG document.
+ *
+ * svg_document_length ::
+ * The length of `svg_document`.
+ *
+ * metrics ::
+ * A metrics object storing the size information.
+ *
+ * units_per_EM ::
+ * The size of the EM square.
+ *
+ * start_glyph_id ::
+ * The first glyph ID in the glyph range covered by this document.
+ *
+ * end_glyph_id ::
+ * The last glyph ID in the glyph range covered by this document.
+ *
+ * transform ::
+ * A 2x2 transformation matrix to apply to the glyph while rendering
+ * it.
+ *
+ * delta ::
+ * The translation to apply to the glyph while rendering.
+ *
+ * @note:
+ * When an @FT_GlyphSlot object `slot` is passed down to a renderer, the
+ * renderer can only access the `metrics` and `units_per_EM` fields via
+ * `slot->face`. However, when @FT_Glyph_To_Bitmap sets up a dummy
+ * object, it has no way to set a `face` object. Thus, metrics
+ * information and `units_per_EM` (which is necessary for OT-SVG) has to
+ * be stored separately.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef struct FT_SVG_DocumentRec_
+ {
+ FT_Byte* svg_document;
+ FT_ULong svg_document_length;
+
+ FT_Size_Metrics metrics;
+ FT_UShort units_per_EM;
+
+ FT_UShort start_glyph_id;
+ FT_UShort end_glyph_id;
+
+ FT_Matrix transform;
+ FT_Vector delta;
+
+ } FT_SVG_DocumentRec;
+
+
+ /**************************************************************************
+ *
+ * @type:
+ * FT_SVG_Document
+ *
+ * @description:
+ * A handle to an @FT_SVG_DocumentRec object.
+ *
+ * @since:
+ * 2.12
+ */
+ typedef struct FT_SVG_DocumentRec_* FT_SVG_Document;
+
+
+FT_END_HEADER
+
+#endif /* OTSVG_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/include/freetype/t1tables.h b/thirdparty/freetype/include/freetype/t1tables.h
index a5f6ae7210..4068b204a9 100644
--- a/thirdparty/freetype/include/freetype/t1tables.h
+++ b/thirdparty/freetype/include/freetype/t1tables.h
@@ -5,7 +5,7 @@
* Basic Type 1/Type 2 tables definitions and interface (specification
* only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -453,22 +453,22 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @function:
- * FT_Has_PS_Glyph_Names
+ * FT_Has_PS_Glyph_Names
*
* @description:
- * Return true if a given face provides reliable PostScript glyph names.
- * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that
- * certain fonts (mostly TrueType) contain incorrect glyph name tables.
+ * Return true if a given face provides reliable PostScript glyph names.
+ * This is similar to using the @FT_HAS_GLYPH_NAMES macro, except that
+ * certain fonts (mostly TrueType) contain incorrect glyph name tables.
*
- * When this function returns true, the caller is sure that the glyph
- * names returned by @FT_Get_Glyph_Name are reliable.
+ * When this function returns true, the caller is sure that the glyph
+ * names returned by @FT_Get_Glyph_Name are reliable.
*
* @input:
- * face ::
- * face handle
+ * face ::
+ * face handle
*
* @return:
- * Boolean. True if glyph names are reliable.
+ * Boolean. True if glyph names are reliable.
*
*/
FT_EXPORT( FT_Int )
@@ -478,30 +478,40 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @function:
- * FT_Get_PS_Font_Info
+ * FT_Get_PS_Font_Info
*
* @description:
- * Retrieve the @PS_FontInfoRec structure corresponding to a given
- * PostScript font.
+ * Retrieve the @PS_FontInfoRec structure corresponding to a given
+ * PostScript font.
*
* @input:
- * face ::
- * PostScript face handle.
+ * face ::
+ * PostScript face handle.
*
* @output:
- * afont_info ::
- * Output font info structure pointer.
+ * afont_info ::
+ * A pointer to a @PS_FontInfoRec object.
*
* @return:
- * FreeType error code. 0~means success.
+ * FreeType error code. 0~means success.
*
* @note:
- * String pointers within the @PS_FontInfoRec structure are owned by the
- * face and don't need to be freed by the caller. Missing entries in
- * the font's FontInfo dictionary are represented by `NULL` pointers.
+ * String pointers within the @PS_FontInfoRec structure are owned by the
+ * face and don't need to be freed by the caller. Missing entries in the
+ * font's FontInfo dictionary are represented by `NULL` pointers.
+ *
+ * The following font formats support this feature: 'Type~1', 'Type~42',
+ * 'CFF', 'CID~Type~1'. For other font formats this function returns the
+ * `FT_Err_Invalid_Argument` error code.
*
- * If the font's format is not PostScript-based, this function will
- * return the `FT_Err_Invalid_Argument` error code.
+ * @example:
+ * ```
+ * PS_FontInfoRec font_info;
+ *
+ *
+ * error = FT_Get_PS_Font_Info( face, &font_info );
+ * ...
+ * ```
*
*/
FT_EXPORT( FT_Error )
@@ -512,29 +522,39 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @function:
- * FT_Get_PS_Font_Private
+ * FT_Get_PS_Font_Private
*
* @description:
- * Retrieve the @PS_PrivateRec structure corresponding to a given
- * PostScript font.
+ * Retrieve the @PS_PrivateRec structure corresponding to a given
+ * PostScript font.
*
* @input:
- * face ::
- * PostScript face handle.
+ * face ::
+ * PostScript face handle.
*
* @output:
- * afont_private ::
- * Output private dictionary structure pointer.
+ * afont_private ::
+ * A pointer to a @PS_PrivateRec object.
*
* @return:
- * FreeType error code. 0~means success.
+ * FreeType error code. 0~means success.
*
* @note:
- * The string pointers within the @PS_PrivateRec structure are owned by
- * the face and don't need to be freed by the caller.
+ * The string pointers within the @PS_PrivateRec structure are owned by
+ * the face and don't need to be freed by the caller.
*
- * If the font's format is not PostScript-based, this function returns
- * the `FT_Err_Invalid_Argument` error code.
+ * Only the 'Type~1' font format supports this feature. For other font
+ * formats this function returns the `FT_Err_Invalid_Argument` error
+ * code.
+ *
+ * @example:
+ * ```
+ * PS_PrivateRec font_private;
+ *
+ *
+ * error = FT_Get_PS_Font_Private( face, &font_private );
+ * ...
+ * ```
*
*/
FT_EXPORT( FT_Error )
@@ -693,67 +713,67 @@ FT_BEGIN_HEADER
/**************************************************************************
*
* @function:
- * FT_Get_PS_Font_Value
+ * FT_Get_PS_Font_Value
*
* @description:
- * Retrieve the value for the supplied key from a PostScript font.
+ * Retrieve the value for the supplied key from a PostScript font.
*
* @input:
- * face ::
- * PostScript face handle.
+ * face ::
+ * PostScript face handle.
*
- * key ::
- * An enumeration value representing the dictionary key to retrieve.
+ * key ::
+ * An enumeration value representing the dictionary key to retrieve.
*
- * idx ::
- * For array values, this specifies the index to be returned.
+ * idx ::
+ * For array values, this specifies the index to be returned.
*
- * value ::
- * A pointer to memory into which to write the value.
+ * value ::
+ * A pointer to memory into which to write the value.
*
- * valen_len ::
- * The size, in bytes, of the memory supplied for the value.
+ * valen_len ::
+ * The size, in bytes, of the memory supplied for the value.
*
* @output:
- * value ::
- * The value matching the above key, if it exists.
+ * value ::
+ * The value matching the above key, if it exists.
*
* @return:
- * The amount of memory (in bytes) required to hold the requested value
- * (if it exists, -1 otherwise).
+ * The amount of memory (in bytes) required to hold the requested value
+ * (if it exists, -1 otherwise).
*
* @note:
- * The values returned are not pointers into the internal structures of
- * the face, but are 'fresh' copies, so that the memory containing them
- * belongs to the calling application. This also enforces the
- * 'read-only' nature of these values, i.e., this function cannot be
- * used to manipulate the face.
+ * The values returned are not pointers into the internal structures of
+ * the face, but are 'fresh' copies, so that the memory containing them
+ * belongs to the calling application. This also enforces the
+ * 'read-only' nature of these values, i.e., this function cannot be
+ * used to manipulate the face.
*
- * `value` is a void pointer because the values returned can be of
- * various types.
+ * `value` is a void pointer because the values returned can be of
+ * various types.
*
- * If either `value` is `NULL` or `value_len` is too small, just the
- * required memory size for the requested entry is returned.
+ * If either `value` is `NULL` or `value_len` is too small, just the
+ * required memory size for the requested entry is returned.
*
- * The `idx` parameter is used, not only to retrieve elements of, for
- * example, the FontMatrix or FontBBox, but also to retrieve name keys
- * from the CharStrings dictionary, and the charstrings themselves. It
- * is ignored for atomic values.
+ * The `idx` parameter is used, not only to retrieve elements of, for
+ * example, the FontMatrix or FontBBox, but also to retrieve name keys
+ * from the CharStrings dictionary, and the charstrings themselves. It
+ * is ignored for atomic values.
*
- * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To
- * get the value as in the font stream, you need to divide by 65536000.0
- * (to remove the FT_Fixed scale, and the x1000 scale).
+ * `PS_DICT_BLUE_SCALE` returns a value that is scaled up by 1000. To
+ * get the value as in the font stream, you need to divide by 65536000.0
+ * (to remove the FT_Fixed scale, and the x1000 scale).
*
- * IMPORTANT: Only key/value pairs read by the FreeType interpreter can
- * be retrieved. So, for example, PostScript procedures such as NP, ND,
- * and RD are not available. Arbitrary keys are, obviously, not be
- * available either.
+ * IMPORTANT: Only key/value pairs read by the FreeType interpreter can
+ * be retrieved. So, for example, PostScript procedures such as NP, ND,
+ * and RD are not available. Arbitrary keys are, obviously, not be
+ * available either.
*
- * If the font's format is not PostScript-based, this function returns
- * the `FT_Err_Invalid_Argument` error code.
+ * If the font's format is not PostScript-based, this function returns
+ * the `FT_Err_Invalid_Argument` error code.
*
* @since:
- * 2.4.8
+ * 2.4.8
*
*/
FT_EXPORT( FT_Long )
diff --git a/thirdparty/freetype/include/freetype/ttnameid.h b/thirdparty/freetype/include/freetype/ttnameid.h
index a09950f542..37b505a05b 100644
--- a/thirdparty/freetype/include/freetype/ttnameid.h
+++ b/thirdparty/freetype/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
*
* TrueType name ID definitions (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/tttables.h b/thirdparty/freetype/include/freetype/tttables.h
index c33d99059d..21664df7b3 100644
--- a/thirdparty/freetype/include/freetype/tttables.h
+++ b/thirdparty/freetype/include/freetype/tttables.h
@@ -5,7 +5,7 @@
* Basic SFNT/TrueType tables definitions and interface
* (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/include/freetype/tttags.h b/thirdparty/freetype/include/freetype/tttags.h
index 47ccc6ddf4..8b807641b8 100644
--- a/thirdparty/freetype/include/freetype/tttags.h
+++ b/thirdparty/freetype/include/freetype/tttags.h
@@ -4,7 +4,7 @@
*
* Tags for TrueType and OpenType tables (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -95,6 +95,7 @@ FT_BEGIN_HEADER
#define TTAG_sbix FT_MAKE_TAG( 's', 'b', 'i', 'x' )
#define TTAG_sfnt FT_MAKE_TAG( 's', 'f', 'n', 't' )
#define TTAG_SING FT_MAKE_TAG( 'S', 'I', 'N', 'G' )
+#define TTAG_SVG FT_MAKE_TAG( 'S', 'V', 'G', ' ' )
#define TTAG_trak FT_MAKE_TAG( 't', 'r', 'a', 'k' )
#define TTAG_true FT_MAKE_TAG( 't', 'r', 'u', 'e' )
#define TTAG_ttc FT_MAKE_TAG( 't', 't', 'c', ' ' )
diff --git a/thirdparty/freetype/include/ft2build.h b/thirdparty/freetype/include/ft2build.h
index 62686b1b20..2543ac435a 100644
--- a/thirdparty/freetype/include/ft2build.h
+++ b/thirdparty/freetype/include/ft2build.h
@@ -4,7 +4,7 @@
*
* FreeType 2 build and setup macros.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/patches/fix_gcc_lto_build.diff b/thirdparty/freetype/patches/fix_gcc_lto_build.diff
new file mode 100644
index 0000000000..3c22b464c2
--- /dev/null
+++ b/thirdparty/freetype/patches/fix_gcc_lto_build.diff
@@ -0,0 +1,34 @@
+diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
+index 622035aa79..5d9e1600b7 100644
+--- a/thirdparty/freetype/src/smooth/ftgrays.c
++++ b/thirdparty/freetype/src/smooth/ftgrays.c
+@@ -1907,6 +1907,9 @@ typedef ptrdiff_t FT_PtrDist;
+ 0 /* delta */
+ )
+
++// -- GODOT start --
++ static volatile int _lto_dummy = 0;
++// -- GODOT end --
+
+ static int
+ gray_convert_glyph_inner( RAS_ARG,
+@@ -1928,6 +1931,9 @@ typedef ptrdiff_t FT_PtrDist;
+ ras.max_ey,
+ ras.cell_null - ras.cell_free,
+ ras.cell_null - ras.cell_free == 1 ? "" : "s" ));
++// -- GODOT start --
++ _lto_dummy = error; // Prevents LTO from removing this branch.
++// -- GODOT end --
+ }
+ else
+ {
+@@ -1935,6 +1941,9 @@ typedef ptrdiff_t FT_PtrDist;
+
+ FT_TRACE7(( "band [%d..%d]: to be bisected\n",
+ ras.min_ey, ras.max_ey ));
++// -- GODOT start --
++ _lto_dummy = error; // Prevents LTO from removing this branch.
++// -- GODOT end --
+ }
+
+ return error;
diff --git a/thirdparty/freetype/src/autofit/afblue.c b/thirdparty/freetype/src/autofit/afblue.c
index c9e8045c18..b986eb4a13 100644
--- a/thirdparty/freetype/src/autofit/afblue.c
+++ b/thirdparty/freetype/src/autofit/afblue.c
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afblue.cin b/thirdparty/freetype/src/autofit/afblue.cin
index 071e80b031..f7e27ad8e5 100644
--- a/thirdparty/freetype/src/autofit/afblue.cin
+++ b/thirdparty/freetype/src/autofit/afblue.cin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afblue.dat b/thirdparty/freetype/src/autofit/afblue.dat
deleted file mode 100644
index 1aa9b26de9..0000000000
--- a/thirdparty/freetype/src/autofit/afblue.dat
+++ /dev/null
@@ -1,1121 +0,0 @@
-// afblue.dat
-//
-// Auto-fitter data for blue strings.
-//
-// Copyright (C) 2013-2021 by
-// David Turner, Robert Wilhelm, and Werner Lemberg.
-//
-// This file is part of the FreeType project, and may only be used,
-// modified, and distributed under the terms of the FreeType project
-// license, LICENSE.TXT. By continuing to use, modify, or distribute
-// this file you indicate that you have read the license and
-// understand and accept it fully.
-
-
-// This file contains data specific to blue zones. It gets processed by
-// a script to simulate `jagged arrays', with enumeration values holding
-// offsets into the arrays.
-//
-// The format of the file is rather simple: A section starts with three
-// labels separated by whitespace and followed by a colon (everything in a
-// single line); the first label gives the name of the enumeration template,
-// the second the name of the array template, and the third the name of the
-// `maximum' template. The script then fills the corresponding templates
-// (indicated by `@' characters around the name).
-//
-// A section contains one or more data records. Each data record consists
-// of two or more lines. The first line holds the enumeration name, and the
-// remaining lines the corresponding array data.
-//
-// There are two possible representations for array data.
-//
-// - A string of characters or character clusters (for example, representing
-// Aksharas, Devanagari syllables) in UTF-8 encoding enclosed in double
-// quotes, using C syntax, where the elements are separated by spaces.
-// There can be only one string per line, thus the starting and ending
-// double quote must be the first and last character in the line,
-// respectively, ignoring whitespace before and after the string. If
-// there are multiple strings (in multiple lines), they are concatenated
-// to a single string. In the output, a string gets represented as a
-// series of singles bytes, followed by a zero byte. The enumeration
-// values simply hold byte offsets to the start of the corresponding
-// strings.
-//
-// For strings, the `maximum' template holds the maximum number of
-// non-space characters in all strings.
-//
-// - Data blocks enclosed in balanced braces, which get copied verbatim and
-// which can span multiple lines. The opening brace of a block must be
-// the first character of a line (ignoring whitespace), and the closing
-// brace the last (ignoring whitespace also). The script appends a comma
-// character after each block and counts the number of blocks to set the
-// enumeration values.
-//
-// For data blocks, the `maximum' template holds the maximum number of
-// array elements.
-//
-// A section can contain either strings only or data blocks only.
-//
-// A comment line starts with `//'; it gets removed. A preprocessor
-// directive line (using the standard syntax of `cpp') starts with `#' and
-// gets copied verbatim to both the enumeration and the array. Whitespace
-// outside of a string is insignificant.
-//
-// Preprocessor directives are ignored while the script computes maximum
-// values; this essentially means that the maximum values can easily be too
-// large. Given that the purpose of those values is to create local
-// fixed-size arrays at compile time for further processing of the blue zone
-// data, this isn't a problem. Note the final zero byte of a string is not
-// counted. Note also that the count holds the number of UTF-8 encoded
-// characters, not bytes.
-
-
-// The blue zone string data, to be used in the blue stringsets below.
-
-AF_BLUE_STRING_ENUM AF_BLUE_STRINGS_ARRAY AF_BLUE_STRING_MAX_LEN:
-
- AF_BLUE_STRING_ADLAM_CAPITAL_TOP
- "𞤌 𞤅 𞤈 𞤠𞤔 𞤚"
- AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM
- "𞤂 𞤖"
- AF_BLUE_STRING_ADLAM_SMALL_TOP
- "𞤬 𞤮 𞤻 𞤼 𞤾"
- AF_BLUE_STRING_ADLAM_SMALL_BOTTOM
- "𞤤 𞤨 𞤩 𞤭 𞤴 𞤸 𞤺 𞥀"
-
- AF_BLUE_STRING_ARABIC_TOP
- "ا إ ل ك ط ظ"
- AF_BLUE_STRING_ARABIC_BOTTOM
- "ت ث ط ظ ك"
- // We don't necessarily have access to medial forms via Unicode in case
- // Arabic presentational forms are missing. The only character that is
- // guaranteed to have the same vertical position with joining (this is,
- // non-isolated) forms is U+0640, ARABIC TATWEEL, which must join both
- // round and flat curves.
- AF_BLUE_STRING_ARABIC_JOIN
- "Ù€"
-
- AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP
- "Ô± Õ„ Õ’ Õ Ô² Ô³ Ô´ Õ•"
- AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM
- "Õ’ Õˆ Ô´ Õƒ Õ‡ Õ Õ Õ•"
- AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER
- "Õ¥ Õ§ Õ« Õ´ Õ¾ Ö† Õ³"
- AF_BLUE_STRING_ARMENIAN_SMALL_TOP
- "Õ¡ Õµ Ö‚ Õ½ Õ£ Õ· Ö€ Ö…"
- AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM
- "Õ° Õ¸ Õ³ Õ¡ Õ¥ Õ® Õ½ Ö…"
- AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER
- "Õ¢ Õ¨ Õ« Õ¬ Õ² Õº Öƒ Ö"
-
- AF_BLUE_STRING_AVESTAN_TOP
- "𬀠ð¬ ð¬ ð¬›"
- AF_BLUE_STRING_AVESTAN_BOTTOM
- "𬀠ð¬"
-
- AF_BLUE_STRING_BAMUM_TOP
- "ꚧ ꚨ ê›› ꛉ ê› ê›ˆ ꛫ ꛯ"
- AF_BLUE_STRING_BAMUM_BOTTOM
- "ꚭ ꚳ ꚶ ꛬ ꚢ ꚽ ꛯ ꛲"
-
- AF_BLUE_STRING_BENGALI_BASE
- "অ ড ত ন ব ভ ল ক"
- AF_BLUE_STRING_BENGALI_TOP
- "ই ট ঠ ি ী ৈ ৗ"
- AF_BLUE_STRING_BENGALI_HEAD
- "ও ঠড ত ন ব ল ক"
-
- AF_BLUE_STRING_BUHID_TOP
- "á áˆ"
- AF_BLUE_STRING_BUHID_LARGE
- "á… áŠ áŽ"
- AF_BLUE_STRING_BUHID_SMALL
- "ႠრበáŒ"
- AF_BLUE_STRING_BUHID_BOTTOM
- "ဠრᆠበዠá á‘"
-
- AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP
- "á—œ á–´ á á’£ á‘« á‘Ž ᔑ á—°"
- AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM
- "ᗶ ᖵ ᒧ რᑌ ᒠᔑ ᗢ"
- AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP
- "ᓓ ᓕ ᓀ ᓂ ᓄ ᕄ ᕆ ᘣ"
- AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM
- "ᕃ ᓂ ᓀ ᕂ ᓗ ᓚ ᕆ ᘣ"
- AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP
- "᪠ᙆ ᣘ ᢠᒾ ᣗ ᔆ"
- AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM
- "ᙆ ᗮ ᒻ ហᔆ ᒡ ᒢ ᓑ"
-
- AF_BLUE_STRING_CARIAN_TOP
- "ðŠ§ ðŠ« ðŠ¬ ðŠ­ ðŠ± ðŠº ðŠ¼ ðŠ¿"
- AF_BLUE_STRING_CARIAN_BOTTOM
- "ðŠ£ ðŠ§ ðŠ· ð‹€ ðŠ« ðŠ¸ ð‹‰"
-
- AF_BLUE_STRING_CHAKMA_TOP
- "𑄃 𑄅 𑄉 𑄙 𑄗"
- AF_BLUE_STRING_CHAKMA_BOTTOM
- "ð‘„… ð‘„› ð‘„ ð‘„— ð‘„“"
- AF_BLUE_STRING_CHAKMA_DESCENDER
- "𑄖𑄳𑄢 𑄘𑄳𑄢 𑄙𑄳𑄢 𑄤𑄳𑄢 𑄥𑄳𑄢"
-
- AF_BLUE_STRING_CHEROKEE_CAPITAL
- "ᆠᎻ Ꭼ რᎤ ᣠᎦ á•"
- AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER
- "ê®’ ꮤ ꮶ ê­´ ê­¾ ê®— ê® ê®¿"
- AF_BLUE_STRING_CHEROKEE_SMALL
- "ꮖ ꭼ ꮓ ꮠ ꮳ ꭶ ꮥ ꮻ"
- AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER
- "á¸ ê® ê­¹ ê­»"
-
- AF_BLUE_STRING_COPTIC_CAPITAL_TOP
- "Ⲍ Ⲏ Ⲡ Ⳟ Ⲟ ⲠⲤ Ⳋ"
- AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM
- "ⳠⳘ Ⳟ Ⲏ Ⲟ ⲠⳜ Ⲱ"
- AF_BLUE_STRING_COPTIC_SMALL_TOP
- "ⲠⲠⲡ ⳟ ⲟ ⲑ ⲥ ⳋ"
- AF_BLUE_STRING_COPTIC_SMALL_BOTTOM
- "ⳑ ⳙ ⳟ Ⲡⲟ ⲑ ⳠⳒ"
-
- AF_BLUE_STRING_CYPRIOT_TOP
- "ð  ð ™ ð ³ ð ± ð … ð “ ð £ ð ¦"
- AF_BLUE_STRING_CYPRIOT_BOTTOM
- "ð ƒ ð Š ð › ð £ ð ³ ð µ ð "
- AF_BLUE_STRING_CYPRIOT_SMALL
- "ð ˆ ð  ð –"
-
- AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP
- "Б В Е П З О С Э"
- AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM
- "Б В Е Ш З О С Э"
- AF_BLUE_STRING_CYRILLIC_SMALL
- "Ñ… п н ш е з о Ñ"
- AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER
- "р у ф"
-
- AF_BLUE_STRING_DESERET_CAPITAL_TOP
- "ð‚ ð„ ð‹ ð— ð‘"
- AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM
- "ð€ ð‚ ð„ ð— ð›"
- AF_BLUE_STRING_DESERET_SMALL_TOP
- "ðª ð¬ ð³ ð¿ ð¹"
- AF_BLUE_STRING_DESERET_SMALL_BOTTOM
- "ð¨ ðª ð¬ ð¿ ð‘ƒ"
-
- AF_BLUE_STRING_DEVANAGARI_BASE
- "क न म उ छ ट ठ ड"
- AF_BLUE_STRING_DEVANAGARI_TOP
- "ई ठओ औ ि ी ो ौ"
- // note that some fonts have extreme variation in the height of the
- // round head elements; for this reason we also define the `base'
- // blue zone, which must be always present
- AF_BLUE_STRING_DEVANAGARI_HEAD
- "क म अ आ थ ध भ श"
- AF_BLUE_STRING_DEVANAGARI_BOTTOM
- "ॠृ"
-
- AF_BLUE_STRING_ETHIOPIC_TOP
- "ሀ ሃ ዘ á ማ በ á‹‹ á‹"
- AF_BLUE_STRING_ETHIOPIC_BOTTOM
- "ለ ሠበ ዘ ሀ ሪ ዠጨ"
-
- AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP
- "გ დ ე ვ თ ი რღ"
- AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM
- "რზ მ ს შ ძ ხ პ"
- AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER
- "ს ხ ქ ზ მ შ ჩ წ"
- AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER
- "ე ვ ჟ ტ უ ფ ქ ყ"
-
- AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP
- "Ⴑ Ⴇ Ⴙ Ⴜ Ⴄ Ⴅ Ⴓ Ⴚ"
- AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM
- "Ⴄ Ⴅ Ⴇ Ⴈ Ⴆ Ⴑ Ⴊ Ⴋ"
-
- AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP
- "â´ â´— â´‚ â´„ â´… â´‡ â´” â´–"
- AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM
- "ⴈ ⴌ ⴖ ⴎ ⴃ ⴆ ⴋ ⴢ"
- AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER
- "â´ â´‘ â´“ â´• â´™ â´› â´¡ â´£"
- AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER
- "â´„ â´… â´” â´• â´ â´‚ â´˜ â´"
-
- AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP
- "Ნ Ჟ Ჳ Ჸ Გ Ე ᲠᲴ"
- AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM
- "Ი Ჲ ᲠᲩ Მ Შ Ჯ Ჽ"
-
- AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP
- "â°… â°” â°ª â°„ â°‚ â°Š â°« â°‹"
- AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM
- "â°… â°„ â°‚ â°ª â°ž â°¡ â°Š â°”"
- AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP
- "ⰵ ⱄ ⱚ ⰴ ⰲ ⰺ ⱛ ⰻ"
- AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM
- "ⰵ ⰴ ⰲ ⱚ ⱎ ⱑ ⰺ ⱄ"
-
- AF_BLUE_STRING_GOTHIC_TOP
- "ðŒ² ðŒ¶ ð€ ð„ ðŒ´ ðƒ ðˆ ðŒ¾"
- AF_BLUE_STRING_GOTHIC_BOTTOM
- "ðŒ¶ ðŒ´ ðƒ ðˆ"
-
- AF_BLUE_STRING_GREEK_CAPITAL_TOP
- "Γ Β Ε Ζ Θ Ο Ω"
- AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM
- "Β Δ Ζ Ξ Θ Ο"
- AF_BLUE_STRING_GREEK_SMALL_BETA_TOP
- "β θ δ ζ λ ξ"
- AF_BLUE_STRING_GREEK_SMALL
- "α ε ι ο π σ τ ω"
- AF_BLUE_STRING_GREEK_SMALL_DESCENDER
- "β γ η μ Ï Ï† χ ψ"
-
- AF_BLUE_STRING_GUJARATI_TOP
- "ત ન ઋ ઌ છ ટ ર ૦"
- AF_BLUE_STRING_GUJARATI_BOTTOM
- "ખ ગ ઘ ઞ ઇ ઈ ઠ જ"
- AF_BLUE_STRING_GUJARATI_ASCENDER
- "ઈ ઊ િ à«€ લી શà«àªšàª¿ જિ સી"
- AF_BLUE_STRING_GUJARATI_DESCENDER
- "ૠૃ ૄ ખૠછૃ છૄ"
- AF_BLUE_STRING_GUJARATI_DIGIT_TOP
- "૦ ૧ ૨ ૩ ૭"
-
- AF_BLUE_STRING_GURMUKHI_BASE
- "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
- AF_BLUE_STRING_GURMUKHI_HEAD
- "ਕ ਗ ਙ ਚ ਜ ਤ ਧ ਸ"
- AF_BLUE_STRING_GURMUKHI_TOP
- "ਇ ਈ ਉ ਠਓ ੳ ਿ ੀ"
- AF_BLUE_STRING_GURMUKHI_BOTTOM
- "ਅ ਠਓ ਗ ਜ ਠ ਰ ਸ"
- AF_BLUE_STRING_GURMUKHI_DIGIT_TOP
- "੦ ੧ ੨ ੩ ੭"
-
- AF_BLUE_STRING_HEBREW_TOP
- "ב ד ×” ×— ך ×› × ×¡"
- AF_BLUE_STRING_HEBREW_BOTTOM
- "ב ט ×› × ×¡ צ"
- AF_BLUE_STRING_HEBREW_DESCENDER
- "ק ך ן ף ץ"
-
- AF_BLUE_STRING_KANNADA_TOP
- "ಇ ಊ ಠಣ ಸಾ ನಾ ದಾ ರಾ"
- AF_BLUE_STRING_KANNADA_BOTTOM
- "ಅ ಉ ಎ ಲ ೦ ೨ ೬ ೭"
-
- AF_BLUE_STRING_KAYAH_LI_TOP
- "꤅ ê¤ ê¤ ê¤‹ ꤀ ê¤"
- AF_BLUE_STRING_KAYAH_LI_BOTTOM
- "꤈ ꤘ ꤀ ê¤ ê¤¢"
- AF_BLUE_STRING_KAYAH_LI_ASCENDER
- "ꤖ ꤡ"
- AF_BLUE_STRING_KAYAH_LI_DESCENDER
- "ꤑ ꤜ ꤞ"
- AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER
- "ꤑ꤬ ꤜ꤭ ꤔ꤬"
-
- AF_BLUE_STRING_KHMER_TOP
- "ហទ ន ឧ ឩ ា"
- AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP
- "ក្ក ក្ហក្គ ក្áž"
- AF_BLUE_STRING_KHMER_BOTTOM
- "ហឃ ច ឋ ប ម យ ឲ"
- AF_BLUE_STRING_KHMER_DESCENDER
- "ážáŸ’ážš រៀ ឲ្យ អឿ"
- AF_BLUE_STRING_KHMER_LARGE_DESCENDER
- "ន្ážáŸ’រៃ ង្ážáŸ’áž™ ក្បៀ ច្រៀ ន្ážáž¿ ល្បឿ"
-
- AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP
- "᧠ ᧡"
- AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM
- "᧶ ᧹"
-
- AF_BLUE_STRING_LAO_TOP
- "າ ດ ອ ມ ລ ວ ຣ ງ"
- AF_BLUE_STRING_LAO_BOTTOM
- "າ ອ ບ ຠຣ ຮ ວ ຢ"
- AF_BLUE_STRING_LAO_ASCENDER
- "ປ ຢ ຟ àº"
- AF_BLUE_STRING_LAO_LARGE_ASCENDER
- "ໂ ໄ ໃ"
- AF_BLUE_STRING_LAO_DESCENDER
- "ງ ຊ ຖ ຽ ໆ ຯ"
-
- AF_BLUE_STRING_LATIN_CAPITAL_TOP
- "T H E Z O C Q S"
- AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM
- "H E Z L O C U S"
- AF_BLUE_STRING_LATIN_SMALL_F_TOP
- "f i j k d b h"
- AF_BLUE_STRING_LATIN_SMALL_TOP
- "u v x z o e s c"
- AF_BLUE_STRING_LATIN_SMALL_BOTTOM
- "n r x z o e s c"
- AF_BLUE_STRING_LATIN_SMALL_DESCENDER
- "p q g j y"
-
- // we assume that both the subscript and superscript ranges
- // don't contain oldstyle digits (actually, most fonts probably
- // have digits only in those ranges)
- AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP
- "₀ ₃ ₅ ₇ ₈"
- AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM
- "₀ ₠₂ ₃ ₈"
- AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP
- "áµ¢ â±¼ â‚• â‚– â‚—"
- AF_BLUE_STRING_LATIN_SUBS_SMALL
- "₠ₑ ₒ ₓ ₙ ₛ ᵥ ᵤ ᵣ"
- AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER
- "ᵦ ᵧ ᵨ ᵩ ₚ"
-
- AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP
- "Ⱐ³ ⵠⷠᵀ ᴴ ᴱ ᴼ"
- AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM
- "Ⱐ¹ ² ³ á´± á´¸ á´¼ áµ"
- AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP
- "ᵇ ᵈ áµ Ê° ʲ ᶠ â±"
- AF_BLUE_STRING_LATIN_SUPS_SMALL
- "ᵉ ᵒ ʳ ˢ ˣ ᶜ ᶻ"
- AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER
- "áµ– ʸ áµ"
-
- AF_BLUE_STRING_LISU_TOP
- "ꓡ ꓧ ꓱ ꓶ ꓩ ꓚ ꓵ ꓳ"
- AF_BLUE_STRING_LISU_BOTTOM
- "ꓕ ꓜ ꓞ ꓡ ꓛ ꓢ ꓳ ꓴ"
-
- AF_BLUE_STRING_MALAYALAM_TOP
- "à´’ à´Ÿ à´  à´± à´š à´ª à´šàµà´š à´ªàµà´ª"
- AF_BLUE_STRING_MALAYALAM_BOTTOM
- "à´Ÿ à´  à´§ à´¶ à´˜ à´š à´¥ à´²"
-
- AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP
- "𖹀 𖹠𖹂 𖹃 𖹠𖹚 𖹟"
- AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM
- "𖹀 𖹠𖹂 𖹃 𖹠𖹚 𖹒 𖹓"
- AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP
- "𖹤 𖹬 𖹧 𖹴 𖹶 𖹾"
- AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP
- "𖹠 𖹡 𖹢 𖹹 𖹳 𖹮"
- AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM
- "𖹠 𖹡 𖹢 𖹳 𖹭 𖹽"
- AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER
- "𖹥 𖹨 𖹩"
- AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP
- "𖺀 ð–º… 𖺈 𖺄 ð–º"
-
- AF_BLUE_STRING_MONGOLIAN_TOP_BASE
- "á ³ á ´ á ¶ á ½ á¡‚ á¡Š â€á¡¡â€ â€á¡³â€"
- AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE
- "ᡃ"
-
- AF_BLUE_STRING_MYANMAR_TOP
- "ဠဂ င ဒ ဠᥠአá‹"
- AF_BLUE_STRING_MYANMAR_BOTTOM
- "င ဎ ဒ ပ ဗ ဠአá‹"
- AF_BLUE_STRING_MYANMAR_ASCENDER
- "ဩ ြ á á ᆠါ ိ"
- AF_BLUE_STRING_MYANMAR_DESCENDER
- "ဉ ည ဥ ဩ ဨ á‚ á… á‰"
-
- AF_BLUE_STRING_NKO_TOP
- "ß ß‰ ß’ ߟ ß– ßœ ß  ߥ"
- AF_BLUE_STRING_NKO_BOTTOM
- "߀ ߘ ߡ ߠ ߥ"
- AF_BLUE_STRING_NKO_SMALL_TOP
- "ß ß› ß‹"
- AF_BLUE_STRING_NKO_SMALL_BOTTOM
- "ߎ ß ß› ß‹"
-
- AF_BLUE_STRING_OL_CHIKI
- "ᱛ ᱜ ᱠᱡ ᱢ ᱥ"
-
- AF_BLUE_STRING_OLD_TURKIC_TOP
- "ð°— ð°˜ ð°§"
- AF_BLUE_STRING_OLD_TURKIC_BOTTOM
- "ð°‰ ð°— ð°¦ ð°§"
-
- AF_BLUE_STRING_OSAGE_CAPITAL_TOP
- "ð’¾ ð“ ð“’ ð““ ð’» ð“‚ ð’µ ð“†"
- AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM
- "ð’° ð“ ð“‚ ð’¿ ð“Ž ð’¹"
- AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER
- "ð’¼ ð’½ ð’¾"
- AF_BLUE_STRING_OSAGE_SMALL_TOP
- "𓵠𓶠𓺠𓻠ð“ 𓣠𓪠ð“®"
- AF_BLUE_STRING_OSAGE_SMALL_BOTTOM
- "𓘠𓚠𓣠𓵠𓡠𓧠𓪠ð“¶"
- AF_BLUE_STRING_OSAGE_SMALL_ASCENDER
- "𓤠𓦠𓸠𓹠ð“›"
- AF_BLUE_STRING_OSAGE_SMALL_DESCENDER
- "𓤠𓥠ð“¦"
-
- AF_BLUE_STRING_OSMANYA_TOP
- "ð’† ð’‰ ð’ ð’’ ð’˜ ð’› ð’  ð’£"
- AF_BLUE_STRING_OSMANYA_BOTTOM
- "ð’€ ð’‚ ð’† ð’ˆ ð’Š ð’’ ð’  ð’©"
-
- AF_BLUE_STRING_ROHINGYA_TOP
- "ð´ƒ ð´€ ð´† ð´– ð´•"
- AF_BLUE_STRING_ROHINGYA_BOTTOM
- "ð´” ð´– ð´• ð´‘ ð´"
- AF_BLUE_STRING_ROHINGYA_JOIN
- "Ù€"
-
- AF_BLUE_STRING_SAURASHTRA_TOP
- "ꢜ ꢞ ꢳ ꢂ ꢖ ꢒ ê¢ ê¢›"
- AF_BLUE_STRING_SAURASHTRA_BOTTOM
- "ꢂ ꢨ ꢺ ꢤ ꢎ"
-
- AF_BLUE_STRING_SHAVIAN_TOP
- "ð‘• ð‘™"
- AF_BLUE_STRING_SHAVIAN_BOTTOM
- "𑔠𑖠𑗠𑹠ð‘»"
- AF_BLUE_STRING_SHAVIAN_DESCENDER
- "ð‘Ÿ ð‘£"
- AF_BLUE_STRING_SHAVIAN_SMALL_TOP
- "𑱠𑲠𑳠𑴠𑸠𑺠ð‘¼"
- AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM
- "ð‘´ ð‘» ð‘¹"
-
- AF_BLUE_STRING_SINHALA_TOP
- "ඉ ක චඳ ප ය ල ෆ"
- AF_BLUE_STRING_SINHALA_BOTTOM
- "එ ඔ චජ ට ථ ධ ර"
- AF_BLUE_STRING_SINHALA_DESCENDER
- "ද ඳ උ ල තූ තු බු දු"
-
- AF_BLUE_STRING_SUNDANESE_TOP
- "ᮋ ᮞ ᮮ ᮽ ᮰ ᮈ"
- AF_BLUE_STRING_SUNDANESE_BOTTOM
- "ᮄ ᮔ ᮕ ᮗ ᮰ ᮆ ᮈ ᮉ"
- AF_BLUE_STRING_SUNDANESE_DESCENDER
- "ᮼ ᳄"
-
- AF_BLUE_STRING_TAI_VIET_TOP
- "ꪆ ꪔ ꪒ ꪖ ꪫ"
- AF_BLUE_STRING_TAI_VIET_BOTTOM
- "ꪉ ꪫ ꪮ"
-
- AF_BLUE_STRING_TAMIL_TOP
- "உ ஒ ஓ ற ஈ க ங ச"
- AF_BLUE_STRING_TAMIL_BOTTOM
- "க ச ல ஶ உ ங ட ப"
-
- AF_BLUE_STRING_TELUGU_TOP
- "ఇ ఌ ఙ ఞ ణ ఱ ౯"
- AF_BLUE_STRING_TELUGU_BOTTOM
- "అ క చ ర ఽ ౨ ౬"
-
- AF_BLUE_STRING_THAI_TOP
- "บ เ ๠อ ภา"
- AF_BLUE_STRING_THAI_BOTTOM
- "บ ป ษ ฯ อ ย ฮ"
- AF_BLUE_STRING_THAI_ASCENDER
- "ป ภฟ"
- AF_BLUE_STRING_THAI_LARGE_ASCENDER
- "โ ใ ไ"
- AF_BLUE_STRING_THAI_DESCENDER
- "ฎ ภฤ ฦ"
- AF_BLUE_STRING_THAI_LARGE_DESCENDER
- "ภà¸"
- AF_BLUE_STRING_THAI_DIGIT_TOP
- "๠๑ ๓"
-
- AF_BLUE_STRING_TIFINAGH
- "ⵔ ⵙ ⵛ ⵞ ⴵ ⴼ ⴹ ⵎ"
-
- AF_BLUE_STRING_VAI_TOP
- "ê— ê˜– ꘙ ꘜ ê–œ ê– ê”… ê•¢"
- AF_BLUE_STRING_VAI_BOTTOM
- "ê— ê˜– ꘙ ê—ž ê”… ê•¢ ê–œ ꔆ"
-
-
-#ifdef AF_CONFIG_OPTION_CJK
-
- AF_BLUE_STRING_CJK_TOP
- "他 们 你 來 們 到 和 地"
- " 对 å° å°± 席 我 æ—¶ 時 會"
- " æ¥ ç‚º 能 舰 說 说 è¿™ 這"
- " 齊 |"
- " 军 åŒ å·² æ„¿ æ—¢ 星 是 景"
- " æ°‘ ç…§ 现 ç¾ ç† ç”¨ ç½® è¦"
- " è» é‚£ é… é‡Œ é–‹ é›· 露 é¢"
- " 顾"
- AF_BLUE_STRING_CJK_BOTTOM
- "个 为 人 他 以 们 你 來"
- " 個 們 到 å’Œ 大 对 å° å°±"
- " 我 æ—¶ 時 有 æ¥ ç‚º è¦ èªª"
- " 说 |"
- " 主 些 å›  它 想 æ„ ç† ç”Ÿ"
- " 當 看 ç€ ç½® 者 自 è‘— 裡"
- " 过 还 è¿› 進 éŽ é“ é‚„ 里"
- " é¢"
-
-#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
-
- AF_BLUE_STRING_CJK_LEFT
- " 些 们 你 來 們 到 和 地"
- " 她 将 將 就 年 得 情 最"
- " æ · 樣 ç† èƒ½ 說 说 è¿™ 這"
- " 通 |"
- " å³ å— å§ å¬ å‘¢ å“ å“ å—Ž"
- " 师 師 收 断 斷 明 眼 間"
- " é—´ é™… 陈 é™ é™¤ 陳 éš éš›"
- " 隨"
- AF_BLUE_STRING_CJK_RIGHT
- "事 å‰ å­¸ å°† å°‡ 情 想 或"
- " 政 斯 新 样 樣 民 沒 没"
- " 然 特 现 ç¾ çƒ ç¬¬ 經 è°"
- " èµ· |"
- " 例 別 别 制 动 å‹• å— å—Ž"
- " 增 指 明 æœ æœŸ æž„ 物 ç¡®"
- " ç§ èª¿ è°ƒ è²» è´¹ é‚£ 都 é–“"
- " é—´"
-
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
-
-#endif /* AF_CONFIG_OPTION_CJK */
-
-
-// The blue zone stringsets, as used in the script styles, cf. `afstyles.h'.
-//
-// The AF_BLUE_PROPERTY_XXX flags are defined in `afblue.h'; here some
-// explanations.
-//
-// A blue zone in general is defined by a reference and an overshoot line.
-// During the hinting process, all coordinate values between those two lines
-// are set equal to the reference value, provided that the blue zone is not
-// wider than 0.75 pixels (otherwise the blue zone gets ignored). All
-// entries must have `AF_BLUE_STRING_MAX' as the final line.
-//
-// During the glyph analysis, edges are sorted from bottom to top, and then
-// sequentially checked, edge by edge, against the blue zones in the order
-// given below.
-//
-//
-// latin auto-hinter
-// -----------------
-//
-// Characters in a blue string are automatically classified as having a flat
-// (reference) or a round (overshoot) extremum. The blue zone is then set
-// up by the mean values of all flat extrema and all round extrema,
-// respectively. Only horizontal blue zones (i.e., adjusting vertical
-// coordinate values) are supported.
-//
-// Some scripts like Khmer need character composition to get all necessary
-// blue zones, since Unicode only provides an abstract data model that
-// doesn't represent all possible glyph shapes. For such character
-// clusters, the HarfBuzz library is used to convert them into the
-// corresponding glyphs. The largest glyph element (where `largest' can be
-// either `largest ascender' or `largest descender') then defines the
-// corresponding flat or round extremum.
-//
-// For the latin auto-hinter, the overshoot should be larger than the
-// reference for top zones, and vice versa for bottom zones.
-//
-// LATIN_TOP
-// Take the maximum flat and round coordinate values of the blue string
-// characters for computing the blue zone's reference and overshoot
-// values.
-//
-// If not set, take the minimum values.
-//
-// Mutually exclusive with `LATIN_SUB_TOP'.
-//
-// LATIN_SUB_TOP
-// For all glyphs of a character cluster, compute the maximum flat
-// and round coordinate values of each component, then take the
-// smallest of the maximum values. The idea is to get the top of
-// subscript glyphs, as used in Khmer, for example. Note that
-// this mechanism doesn't work for ordinary ligatures.
-//
-// This flags indicates a secondary blue zone: It gets removed if
-// there is a non-LATIN_SUB_TOP blue zone at the same coordinate
-// value (after scaling).
-//
-// Mutually exclusive with `LATIN_TOP'.
-//
-// LATIN_NEUTRAL
-// Ignore round extrema and define the blue zone with flat values only.
-// Both top and bottom of contours can match. This is useful for
-// scripts like Devanagari where vowel signs attach to the base
-// character and are implemented as components of composite glyphs.
-//
-// If not set, both round and flat extrema are taken into account.
-// Additionally, only the top or the bottom of a contour can match,
-// depending on the LATIN_TOP flag.
-//
-// Neutral blue zones should always follow non-neutral blue zones.
-//
-// LATIN_X_HEIGHT
-// Scale all glyphs vertically from the corresponding script to make the
-// reference line of this blue zone align on the grid. The scaling
-// takes place before all other blue zones get aligned to the grid.
-// Only one blue character string of a script style can have this flag.
-//
-// LATIN_LONG
-// Apply an additional constraint for blue zone values: Don't
-// necessarily use the extremum as-is but a segment of the topmost (or
-// bottommost) contour that is longer than a heuristic threshold, and
-// which is not too far away vertically from the real extremum. This
-// ensures that small bumps in the outline are ignored (for example, the
-// `vertical serifs' found in many Hebrew glyph designs).
-//
-// The segment must be at least EM/25 font units long, and the distance
-// to the extremum must be smaller than EM/4.
-//
-//
-// cjk auto-hinter
-// ---------------
-//
-// Characters in a blue string are *not* automatically classified. Instead,
-// first come the characters used for the overshoot value, then the
-// character `|', then the characters used for the reference value
-// (everything separated by space characters). The blue zone is then set up
-// by the mean values of all reference values and all overshoot values,
-// respectively. Both horizontal and vertical blue zones (i.e., adjusting
-// vertical and horizontal coordinate values, respectively) are supported.
-//
-// For the cjk auto-hinter, the overshoot should be smaller than the
-// reference for top zones, and vice versa for bottom zones.
-//
-// CJK_TOP
-// Take the maximum flat and round coordinate values of the blue string
-// characters. If not set, take the minimum values.
-//
-// CJK_RIGHT
-// A synonym for CJK_TOP. If CJK_HORIZ is set, this flag indicates the
-// right blue zone, taking horizontal maximum values.
-//
-// CJK_HORIZ
-// Define a blue zone for horizontal hinting (i.e., vertical blue
-// zones). If not set, this is a blue zone for vertical hinting.
-
-
-AF_BLUE_STRINGSET_ENUM AF_BLUE_STRINGSETS_ARRAY AF_BLUE_STRINGSET_MAX_LEN:
-
- AF_BLUE_STRINGSET_ADLM
- { AF_BLUE_STRING_ADLAM_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ADLAM_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_ADLAM_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_ADLAM_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_ARAB
- { AF_BLUE_STRING_ARABIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ARABIC_BOTTOM, 0 }
- { AF_BLUE_STRING_ARABIC_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_ARMN
- { AF_BLUE_STRING_ARMENIAN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ARMENIAN_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_ARMENIAN_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ARMENIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_ARMENIAN_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_ARMENIAN_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_AVST
- { AF_BLUE_STRING_AVESTAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_AVESTAN_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_BAMU
- { AF_BLUE_STRING_BAMUM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_BAMUM_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_BENG
- { AF_BLUE_STRING_BENGALI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_BENGALI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_BENGALI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_NEUTRAL |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_BENGALI_BASE, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_BUHD
- { AF_BLUE_STRING_BUHID_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_BUHID_LARGE, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_BUHID_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_BUHID_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CAKM
- { AF_BLUE_STRING_CHAKMA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CHAKMA_BOTTOM, 0 }
- { AF_BLUE_STRING_CHAKMA_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CANS
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_BOTTOM, 0 }
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CANADIAN_SYLLABICS_SUPS_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CARI
- { AF_BLUE_STRING_CARIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CARIAN_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CHER
- { AF_BLUE_STRING_CHEROKEE_CAPITAL, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CHEROKEE_CAPITAL, 0 }
- { AF_BLUE_STRING_CHEROKEE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CHEROKEE_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_CHEROKEE_SMALL, 0 }
- { AF_BLUE_STRING_CHEROKEE_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_COPT
- { AF_BLUE_STRING_COPTIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_COPTIC_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_COPTIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_COPTIC_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CPRT
- { AF_BLUE_STRING_CYPRIOT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CYPRIOT_BOTTOM, 0 }
- { AF_BLUE_STRING_CYPRIOT_SMALL, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CYPRIOT_SMALL, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_CYRL
- { AF_BLUE_STRING_CYRILLIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_CYRILLIC_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_CYRILLIC_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_CYRILLIC_SMALL, 0 }
- { AF_BLUE_STRING_CYRILLIC_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_DEVA
- { AF_BLUE_STRING_DEVANAGARI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_DEVANAGARI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_DEVANAGARI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_NEUTRAL |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_DEVANAGARI_BASE, 0 }
- { AF_BLUE_STRING_DEVANAGARI_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_DSRT
- { AF_BLUE_STRING_DESERET_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_DESERET_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_DESERET_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_DESERET_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_ETHI
- { AF_BLUE_STRING_ETHIOPIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ETHIOPIC_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GEOR
- { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_BOTTOM, 0 }
- { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GEORGIAN_MKHEDRULI_DESCENDER, 0 }
- { AF_BLUE_STRING_GEORGIAN_MTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GEORGIAN_MTAVRULI_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GEOK
- { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GEORGIAN_ASOMTAVRULI_BOTTOM, 0 }
- { AF_BLUE_STRING_GEORGIAN_NUSKHURI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GEORGIAN_NUSKHURI_BOTTOM, 0 }
- { AF_BLUE_STRING_GEORGIAN_NUSKHURI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GEORGIAN_NUSKHURI_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GLAG
- { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GLAGOLITIC_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_GLAGOLITIC_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GLAGOLITIC_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GOTH
- { AF_BLUE_STRING_GOTHIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GOTHIC_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GREK
- { AF_BLUE_STRING_GREEK_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GREEK_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_GREEK_SMALL_BETA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GREEK_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GREEK_SMALL, 0 }
- { AF_BLUE_STRING_GREEK_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GUJR
- { AF_BLUE_STRING_GUJARATI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GUJARATI_BOTTOM, 0 }
- { AF_BLUE_STRING_GUJARATI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GUJARATI_DESCENDER, 0 }
- { AF_BLUE_STRING_GUJARATI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_GURU
- { AF_BLUE_STRING_GURMUKHI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GURMUKHI_HEAD, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_GURMUKHI_BASE, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_NEUTRAL |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_GURMUKHI_BOTTOM, 0 }
- { AF_BLUE_STRING_GURMUKHI_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_HEBR
- { AF_BLUE_STRING_HEBREW_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_LONG }
- { AF_BLUE_STRING_HEBREW_BOTTOM, 0 }
- { AF_BLUE_STRING_HEBREW_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_KNDA
- { AF_BLUE_STRING_KANNADA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_KANNADA_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_KALI
- { AF_BLUE_STRING_KAYAH_LI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_KAYAH_LI_BOTTOM, 0 }
- { AF_BLUE_STRING_KAYAH_LI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_KAYAH_LI_DESCENDER, 0 }
- { AF_BLUE_STRING_KAYAH_LI_LARGE_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_KHMR
- { AF_BLUE_STRING_KHMER_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_KHMER_SUBSCRIPT_TOP, AF_BLUE_PROPERTY_LATIN_SUB_TOP }
- { AF_BLUE_STRING_KHMER_BOTTOM, 0 }
- { AF_BLUE_STRING_KHMER_DESCENDER, 0 }
- { AF_BLUE_STRING_KHMER_LARGE_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_KHMS
- { AF_BLUE_STRING_KHMER_SYMBOLS_WAXING_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_KHMER_SYMBOLS_WANING_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_LAO
- { AF_BLUE_STRING_LAO_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_LAO_BOTTOM, 0 }
- { AF_BLUE_STRING_LAO_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LAO_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LAO_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_LATN
- { AF_BLUE_STRING_LATIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_LATIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_LATIN_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_LATIN_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_LATB
- { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_SUBS_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_LATIN_SUBS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_SUBS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_LATIN_SUBS_SMALL, 0 }
- { AF_BLUE_STRING_LATIN_SUBS_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_LATP
- { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_SUPS_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_LATIN_SUPS_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LATIN_SUPS_SMALL, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_LATIN_SUPS_SMALL, 0 }
- { AF_BLUE_STRING_LATIN_SUPS_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_LISU
- { AF_BLUE_STRING_LISU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_LISU_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_MLYM
- { AF_BLUE_STRING_MALAYALAM_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MALAYALAM_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_MEDF
- { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MEDEFAIDRIN_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_F_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MEDEFAIDRIN_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MEDEFAIDRIN_DIGIT_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_MONG
- { AF_BLUE_STRING_MONGOLIAN_TOP_BASE, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MONGOLIAN_BOTTOM_BASE, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_MYMR
- { AF_BLUE_STRING_MYANMAR_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_MYANMAR_BOTTOM, 0 }
- { AF_BLUE_STRING_MYANMAR_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_MYANMAR_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_NKOO
- { AF_BLUE_STRING_NKO_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_NKO_BOTTOM, 0 }
- { AF_BLUE_STRING_NKO_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_NKO_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_NONE
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_OLCK
- { AF_BLUE_STRING_OL_CHIKI, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_OL_CHIKI, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_ORKH
- { AF_BLUE_STRING_OLD_TURKIC_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_OLD_TURKIC_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_OSGE
- { AF_BLUE_STRING_OSAGE_CAPITAL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_OSAGE_CAPITAL_BOTTOM, 0 }
- { AF_BLUE_STRING_OSAGE_CAPITAL_DESCENDER, 0 }
- { AF_BLUE_STRING_OSAGE_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_OSAGE_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_OSAGE_SMALL_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_OSAGE_SMALL_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_OSMA
- { AF_BLUE_STRING_OSMANYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_OSMANYA_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_ROHG
- { AF_BLUE_STRING_ROHINGYA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_ROHINGYA_BOTTOM, 0 }
- { AF_BLUE_STRING_ROHINGYA_JOIN, AF_BLUE_PROPERTY_LATIN_NEUTRAL }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_SAUR
- { AF_BLUE_STRING_SAURASHTRA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_SAURASHTRA_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_SHAW
- { AF_BLUE_STRING_SHAVIAN_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_SHAVIAN_BOTTOM, 0 }
- { AF_BLUE_STRING_SHAVIAN_DESCENDER, 0 }
- { AF_BLUE_STRING_SHAVIAN_SMALL_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_SHAVIAN_SMALL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_SINH
- { AF_BLUE_STRING_SINHALA_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_SINHALA_BOTTOM, 0 }
- { AF_BLUE_STRING_SINHALA_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_SUND
- { AF_BLUE_STRING_SUNDANESE_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_SUNDANESE_BOTTOM, 0 }
- { AF_BLUE_STRING_SUNDANESE_DESCENDER, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_TAML
- { AF_BLUE_STRING_TAMIL_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_TAMIL_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_TAVT
- { AF_BLUE_STRING_TAI_VIET_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_TAI_VIET_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_TELU
- { AF_BLUE_STRING_TELUGU_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_TELUGU_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_THAI
- { AF_BLUE_STRING_THAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP |
- AF_BLUE_PROPERTY_LATIN_X_HEIGHT }
- { AF_BLUE_STRING_THAI_BOTTOM, 0 }
- { AF_BLUE_STRING_THAI_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_THAI_LARGE_ASCENDER, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_THAI_DESCENDER, 0 }
- { AF_BLUE_STRING_THAI_LARGE_DESCENDER, 0 }
- { AF_BLUE_STRING_THAI_DIGIT_TOP, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_TFNG
- { AF_BLUE_STRING_TIFINAGH, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_TIFINAGH, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
- AF_BLUE_STRINGSET_VAII
- { AF_BLUE_STRING_VAI_TOP, AF_BLUE_PROPERTY_LATIN_TOP }
- { AF_BLUE_STRING_VAI_BOTTOM, 0 }
- { AF_BLUE_STRING_MAX, 0 }
-
-#ifdef AF_CONFIG_OPTION_CJK
-
- AF_BLUE_STRINGSET_HANI
- { AF_BLUE_STRING_CJK_TOP, AF_BLUE_PROPERTY_CJK_TOP }
- { AF_BLUE_STRING_CJK_BOTTOM, 0 }
-#ifdef AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT
- { AF_BLUE_STRING_CJK_LEFT, AF_BLUE_PROPERTY_CJK_HORIZ }
- { AF_BLUE_STRING_CJK_RIGHT, AF_BLUE_PROPERTY_CJK_HORIZ |
- AF_BLUE_PROPERTY_CJK_RIGHT }
-#endif /* AF_CONFIG_OPTION_CJK_BLUE_HANI_VERT */
- { AF_BLUE_STRING_MAX, 0 }
-
-#endif /* AF_CONFIG_OPTION_CJK */
-
-
-// END
diff --git a/thirdparty/freetype/src/autofit/afblue.h b/thirdparty/freetype/src/autofit/afblue.h
index 311c9e3afd..0e56abb94d 100644
--- a/thirdparty/freetype/src/autofit/afblue.h
+++ b/thirdparty/freetype/src/autofit/afblue.h
@@ -7,7 +7,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afblue.hin b/thirdparty/freetype/src/autofit/afblue.hin
index 5186914937..f9fd5aa3b4 100644
--- a/thirdparty/freetype/src/autofit/afblue.hin
+++ b/thirdparty/freetype/src/autofit/afblue.hin
@@ -4,7 +4,7 @@
*
* Auto-fitter data for blue strings (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afcjk.c b/thirdparty/freetype/src/autofit/afcjk.c
index 7e46b6b1ef..1853a17f5c 100644
--- a/thirdparty/freetype/src/autofit/afcjk.c
+++ b/thirdparty/freetype/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -843,7 +843,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
AF_Direction major_dir = axis->major_dir;
AF_Segment seg1, seg2;
FT_Pos len_threshold;
@@ -1005,7 +1005,7 @@
AF_CJKAxis laxis = &((AF_CJKMetrics)hints->metrics)->axis[dim];
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
AF_Segment seg;
FT_Fixed scale;
@@ -1153,7 +1153,7 @@
*/
{
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
AF_Edge edge;
@@ -1291,7 +1291,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edge = axis->edges;
- AF_Edge edge_limit = edge + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges );
AF_CJKAxis cjk = &metrics->axis[dim];
FT_Fixed scale = cjk->scale;
FT_Pos best_dist0; /* initial threshold */
@@ -1798,7 +1798,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
FT_PtrDist n_edges;
AF_Edge edge;
AF_Edge anchor = NULL;
@@ -2177,7 +2177,7 @@
{
AF_AxisHints axis = & hints->axis[dim];
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
AF_Edge edge;
FT_Bool snapping;
diff --git a/thirdparty/freetype/src/autofit/afcjk.h b/thirdparty/freetype/src/autofit/afcjk.h
index 58aa298dad..bf948bcec0 100644
--- a/thirdparty/freetype/src/autofit/afcjk.h
+++ b/thirdparty/freetype/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for CJK writing system (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afcover.h b/thirdparty/freetype/src/autofit/afcover.h
index c7ae1e9a8a..be71fe39de 100644
--- a/thirdparty/freetype/src/autofit/afcover.h
+++ b/thirdparty/freetype/src/autofit/afcover.h
@@ -4,7 +4,7 @@
*
* Auto-fitter coverages (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afdummy.c b/thirdparty/freetype/src/autofit/afdummy.c
index a36b56f784..5fdbfcfd42 100644
--- a/thirdparty/freetype/src/autofit/afdummy.c
+++ b/thirdparty/freetype/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afdummy.h b/thirdparty/freetype/src/autofit/afdummy.h
index b58849fe50..4dddbd5215 100644
--- a/thirdparty/freetype/src/autofit/afdummy.h
+++ b/thirdparty/freetype/src/autofit/afdummy.h
@@ -5,7 +5,7 @@
* Auto-fitter dummy routines to be used if no hinting should be
* performed (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aferrors.h b/thirdparty/freetype/src/autofit/aferrors.h
index 09bed66395..d31b1a9c88 100644
--- a/thirdparty/freetype/src/autofit/aferrors.h
+++ b/thirdparty/freetype/src/autofit/aferrors.h
@@ -4,7 +4,7 @@
*
* Autofitter error codes (specification only).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afglobal.c b/thirdparty/freetype/src/autofit/afglobal.c
index b805b3b0e5..87a3fbfb0f 100644
--- a/thirdparty/freetype/src/autofit/afglobal.c
+++ b/thirdparty/freetype/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
*
* Auto-fitter routines to compute global hinting values (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -337,11 +337,13 @@
/* we allocate an AF_FaceGlobals structure together */
/* with the glyph_styles array */
- if ( FT_ALLOC( globals,
- sizeof ( *globals ) +
- (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
+ if ( FT_QALLOC( globals,
+ sizeof ( *globals ) +
+ (FT_ULong)face->num_glyphs * sizeof ( FT_UShort ) ) )
goto Exit;
+ FT_ZERO( &globals->metrics );
+
globals->face = face;
globals->glyph_count = face->num_glyphs;
/* right after the globals structure come the glyph styles */
diff --git a/thirdparty/freetype/src/autofit/afglobal.h b/thirdparty/freetype/src/autofit/afglobal.h
index cd97e716c4..f7ebf8d57a 100644
--- a/thirdparty/freetype/src/autofit/afglobal.h
+++ b/thirdparty/freetype/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
* Auto-fitter routines to compute global hinting values
* (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afhints.c b/thirdparty/freetype/src/autofit/afhints.c
index 5506afda22..ae7d10528d 100644
--- a/thirdparty/freetype/src/autofit/afhints.c
+++ b/thirdparty/freetype/src/autofit/afhints.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1316,7 +1316,7 @@
{
AF_AxisHints axis = & hints->axis[dim];
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
AF_Segment seg;
@@ -1393,7 +1393,7 @@
AF_Point point_limit = points + hints->num_points;
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
FT_UInt touch_flag;
diff --git a/thirdparty/freetype/src/autofit/afhints.h b/thirdparty/freetype/src/autofit/afhints.h
index 38d2847d71..96001cd80d 100644
--- a/thirdparty/freetype/src/autofit/afhints.h
+++ b/thirdparty/freetype/src/autofit/afhints.h
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afindic.c b/thirdparty/freetype/src/autofit/afindic.c
index 064c300ed7..5bf0b5f945 100644
--- a/thirdparty/freetype/src/autofit/afindic.c
+++ b/thirdparty/freetype/src/autofit/afindic.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for Indic writing system (body).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afindic.h b/thirdparty/freetype/src/autofit/afindic.h
index 3e46724112..59ae11a677 100644
--- a/thirdparty/freetype/src/autofit/afindic.h
+++ b/thirdparty/freetype/src/autofit/afindic.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for Indic writing system
* (specification).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aflatin.c b/thirdparty/freetype/src/autofit/aflatin.c
index 5e81d771a4..bed0ccee08 100644
--- a/thirdparty/freetype/src/autofit/aflatin.c
+++ b/thirdparty/freetype/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
*
* Auto-fitter hinting routines for latin writing system (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -200,7 +200,7 @@
(AF_Dimension)dim );
seg = axhints->segments;
- limit = seg + axhints->num_segments;
+ limit = FT_OFFSET( seg, axhints->num_segments );
for ( ; seg < limit; seg++ )
{
@@ -1989,7 +1989,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
FT_Pos len_threshold, len_score, dist_score, max_width;
AF_Segment seg1, seg2;
@@ -2134,7 +2134,7 @@
FT_Bool top_to_bottom_hinting = 0;
AF_Segment segments = axis->segments;
- AF_Segment segment_limit = segments + axis->num_segments;
+ AF_Segment segment_limit = FT_OFFSET( segments, axis->num_segments );
AF_Segment seg;
#if 0
@@ -2500,7 +2500,7 @@
{
AF_AxisHints axis = &hints->axis[AF_DIMENSION_VERT];
AF_Edge edge = axis->edges;
- AF_Edge edge_limit = edge + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edge, axis->num_edges );
AF_LatinAxis latin = &metrics->axis[AF_DIMENSION_VERT];
FT_Fixed scale = latin->scale;
@@ -2993,7 +2993,7 @@
{
AF_AxisHints axis = &hints->axis[dim];
AF_Edge edges = axis->edges;
- AF_Edge edge_limit = edges + axis->num_edges;
+ AF_Edge edge_limit = FT_OFFSET( edges, axis->num_edges );
FT_PtrDist n_edges;
AF_Edge edge;
AF_Edge anchor = NULL;
diff --git a/thirdparty/freetype/src/autofit/aflatin.h b/thirdparty/freetype/src/autofit/aflatin.h
index d6b919ef84..facc663450 100644
--- a/thirdparty/freetype/src/autofit/aflatin.h
+++ b/thirdparty/freetype/src/autofit/aflatin.h
@@ -5,7 +5,7 @@
* Auto-fitter hinting routines for latin writing system
* (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afloader.c b/thirdparty/freetype/src/autofit/afloader.c
index a06d49ad7e..e55183a509 100644
--- a/thirdparty/freetype/src/autofit/afloader.c
+++ b/thirdparty/freetype/src/autofit/afloader.c
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afloader.h b/thirdparty/freetype/src/autofit/afloader.h
index b4936a8722..b345e46395 100644
--- a/thirdparty/freetype/src/autofit/afloader.h
+++ b/thirdparty/freetype/src/autofit/afloader.h
@@ -4,7 +4,7 @@
*
* Auto-fitter glyph loading routines (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afmodule.c b/thirdparty/freetype/src/autofit/afmodule.c
index 76f9b3733b..1b14ae682e 100644
--- a/thirdparty/freetype/src/autofit/afmodule.c
+++ b/thirdparty/freetype/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afmodule.h b/thirdparty/freetype/src/autofit/afmodule.h
index c5bd468201..1d1bfaf544 100644
--- a/thirdparty/freetype/src/autofit/afmodule.h
+++ b/thirdparty/freetype/src/autofit/afmodule.h
@@ -4,7 +4,7 @@
*
* Auto-fitter module implementation (specification).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afranges.c b/thirdparty/freetype/src/autofit/afranges.c
index e06f182dd0..2de1991a57 100644
--- a/thirdparty/freetype/src/autofit/afranges.c
+++ b/thirdparty/freetype/src/autofit/afranges.c
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afranges.h b/thirdparty/freetype/src/autofit/afranges.h
index 841d630aab..acd01faf68 100644
--- a/thirdparty/freetype/src/autofit/afranges.h
+++ b/thirdparty/freetype/src/autofit/afranges.h
@@ -4,7 +4,7 @@
*
* Auto-fitter Unicode script ranges (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afscript.h b/thirdparty/freetype/src/autofit/afscript.h
index af78d573e1..172b598069 100644
--- a/thirdparty/freetype/src/autofit/afscript.h
+++ b/thirdparty/freetype/src/autofit/afscript.h
@@ -4,7 +4,7 @@
*
* Auto-fitter scripts (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afshaper.c b/thirdparty/freetype/src/autofit/afshaper.c
index 5d078937e1..298480d864 100644
--- a/thirdparty/freetype/src/autofit/afshaper.c
+++ b/thirdparty/freetype/src/autofit/afshaper.c
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (body).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afshaper.h b/thirdparty/freetype/src/autofit/afshaper.h
index cf3f81342f..558f03bdef 100644
--- a/thirdparty/freetype/src/autofit/afshaper.h
+++ b/thirdparty/freetype/src/autofit/afshaper.h
@@ -4,7 +4,7 @@
*
* HarfBuzz interface for accessing OpenType features (specification).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afstyles.h b/thirdparty/freetype/src/autofit/afstyles.h
index 64c808c581..9080b9fb65 100644
--- a/thirdparty/freetype/src/autofit/afstyles.h
+++ b/thirdparty/freetype/src/autofit/afstyles.h
@@ -4,7 +4,7 @@
*
* Auto-fitter styles (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/aftypes.h b/thirdparty/freetype/src/autofit/aftypes.h
index 1d792b9476..754aad7ba4 100644
--- a/thirdparty/freetype/src/autofit/aftypes.h
+++ b/thirdparty/freetype/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
*
* Auto-fitter types (specification only).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afws-decl.h b/thirdparty/freetype/src/autofit/afws-decl.h
index c10dd57e7b..c93845ef95 100644
--- a/thirdparty/freetype/src/autofit/afws-decl.h
+++ b/thirdparty/freetype/src/autofit/afws-decl.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing system declarations (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/afws-iter.h b/thirdparty/freetype/src/autofit/afws-iter.h
index 55714203e3..9cda3509bc 100644
--- a/thirdparty/freetype/src/autofit/afws-iter.h
+++ b/thirdparty/freetype/src/autofit/afws-iter.h
@@ -4,7 +4,7 @@
*
* Auto-fitter writing systems iterator (specification only).
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/autofit/autofit.c b/thirdparty/freetype/src/autofit/autofit.c
index 7e692b4de9..3d78a9b335 100644
--- a/thirdparty/freetype/src/autofit/autofit.c
+++ b/thirdparty/freetype/src/autofit/autofit.c
@@ -4,7 +4,7 @@
*
* Auto-fitter module (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftadvanc.c b/thirdparty/freetype/src/base/ftadvanc.c
index f20b9928aa..fc6b428817 100644
--- a/thirdparty/freetype/src/base/ftadvanc.c
+++ b/thirdparty/freetype/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
*
* Quick computation of advance widths (body).
*
- * Copyright (C) 2008-2021 by
+ * Copyright (C) 2008-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbase.c b/thirdparty/freetype/src/base/ftbase.c
index 7366bc46db..cd1056890f 100644
--- a/thirdparty/freetype/src/base/ftbase.c
+++ b/thirdparty/freetype/src/base/ftbase.c
@@ -4,7 +4,7 @@
*
* Single object library component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbase.h b/thirdparty/freetype/src/base/ftbase.h
index 963ff93d68..f873566f22 100644
--- a/thirdparty/freetype/src/base/ftbase.h
+++ b/thirdparty/freetype/src/base/ftbase.h
@@ -4,7 +4,7 @@
*
* Private functions used in the `base' module (specification).
*
- * Copyright (C) 2008-2021 by
+ * Copyright (C) 2008-2022 by
* David Turner, Robert Wilhelm, Werner Lemberg, and suzuki toshiya.
*
* This file is part of the FreeType project, and may only be used,
@@ -28,6 +28,7 @@ FT_BEGIN_HEADER
FT_DECLARE_GLYPH( ft_bitmap_glyph_class )
FT_DECLARE_GLYPH( ft_outline_glyph_class )
+ FT_DECLARE_GLYPH( ft_svg_glyph_class )
#ifdef FT_CONFIG_OPTION_MAC_FONTS
diff --git a/thirdparty/freetype/src/base/ftbbox.c b/thirdparty/freetype/src/base/ftbbox.c
index 4db29cbf83..30aedf780c 100644
--- a/thirdparty/freetype/src/base/ftbbox.c
+++ b/thirdparty/freetype/src/base/ftbbox.c
@@ -4,7 +4,7 @@
*
* FreeType bbox computation (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/base/ftbdf.c b/thirdparty/freetype/src/base/ftbdf.c
index f93ca8eb75..4f22113d7e 100644
--- a/thirdparty/freetype/src/base/ftbdf.c
+++ b/thirdparty/freetype/src/base/ftbdf.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing BDF-specific strings (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftbitmap.c b/thirdparty/freetype/src/base/ftbitmap.c
index 2146d3e364..7825895ad6 100644
--- a/thirdparty/freetype/src/base/ftbitmap.c
+++ b/thirdparty/freetype/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
*
* FreeType utility functions for bitmaps (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -480,7 +480,7 @@
* A gamma of 2.2 is fair to assume. And then, we need to
* undo the premultiplication too.
*
- * https://accessibility.kde.org/hsl-adjusted.php
+ * http://www.brucelindbloom.com/index.html?WorkingSpaceInfo.html#SideNotes
*
* We do the computation with integers only, applying a gamma of 2.0.
* We guarantee 32-bit arithmetic to avoid overflow but the resulting
@@ -488,9 +488,9 @@
*
*/
- l = ( 4732UL /* 0.0722 * 65536 */ * bgra[0] * bgra[0] +
- 46871UL /* 0.7152 * 65536 */ * bgra[1] * bgra[1] +
- 13933UL /* 0.2126 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
+ l = ( 4731UL /* 0.072186 * 65536 */ * bgra[0] * bgra[0] +
+ 46868UL /* 0.715158 * 65536 */ * bgra[1] * bgra[1] +
+ 13937UL /* 0.212656 * 65536 */ * bgra[2] * bgra[2] ) >> 16;
/*
* Final transparency can be determined as follows.
diff --git a/thirdparty/freetype/src/base/ftcalc.c b/thirdparty/freetype/src/base/ftcalc.c
index 9df8e4010d..6c1e7fbd45 100644
--- a/thirdparty/freetype/src/base/ftcalc.c
+++ b/thirdparty/freetype/src/base/ftcalc.c
@@ -4,7 +4,7 @@
*
* Arithmetic computations (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftcid.c b/thirdparty/freetype/src/base/ftcid.c
index 216ee2b3e4..b882ca3de0 100644
--- a/thirdparty/freetype/src/base/ftcid.c
+++ b/thirdparty/freetype/src/base/ftcid.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing CID font information.
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* Derek Clegg and Michael Toftdal.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftcolor.c b/thirdparty/freetype/src/base/ftcolor.c
index 3ef3256b20..0edf379b43 100644
--- a/thirdparty/freetype/src/base/ftcolor.c
+++ b/thirdparty/freetype/src/base/ftcolor.c
@@ -4,7 +4,7 @@
*
* FreeType's glyph color management (body).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftdbgmem.c b/thirdparty/freetype/src/base/ftdbgmem.c
index 4f5c1e7697..1df83c404d 100644
--- a/thirdparty/freetype/src/base/ftdbgmem.c
+++ b/thirdparty/freetype/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
*
* Memory debugger (body).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftdebug.c b/thirdparty/freetype/src/base/ftdebug.c
index 3485791306..648fff44ed 100644
--- a/thirdparty/freetype/src/base/ftdebug.c
+++ b/thirdparty/freetype/src/base/ftdebug.c
@@ -4,7 +4,7 @@
*
* Debugging and logging component (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fterrors.c b/thirdparty/freetype/src/base/fterrors.c
index 14649268f8..5846fefc91 100644
--- a/thirdparty/freetype/src/base/fterrors.c
+++ b/thirdparty/freetype/src/base/fterrors.c
@@ -4,7 +4,7 @@
*
* FreeType API for error code handling.
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* Armin Hasitzka, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftfntfmt.c b/thirdparty/freetype/src/base/ftfntfmt.c
index 4e1b830190..e69c1e0684 100644
--- a/thirdparty/freetype/src/base/ftfntfmt.c
+++ b/thirdparty/freetype/src/base/ftfntfmt.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for font formats (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftfstype.c b/thirdparty/freetype/src/base/ftfstype.c
index 57e904d6f4..009d58c57d 100644
--- a/thirdparty/freetype/src/base/ftfstype.c
+++ b/thirdparty/freetype/src/base/ftfstype.c
@@ -4,7 +4,7 @@
*
* FreeType utility file to access FSType data (body).
*
- * Copyright (C) 2008-2021 by
+ * Copyright (C) 2008-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftgasp.c b/thirdparty/freetype/src/base/ftgasp.c
index b744f0a465..7567e3077a 100644
--- a/thirdparty/freetype/src/base/ftgasp.c
+++ b/thirdparty/freetype/src/base/ftgasp.c
@@ -4,7 +4,7 @@
*
* Access of TrueType's `gasp' table (body).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftgloadr.c b/thirdparty/freetype/src/base/ftgloadr.c
index 83ce0660ae..f05abdee81 100644
--- a/thirdparty/freetype/src/base/ftgloadr.c
+++ b/thirdparty/freetype/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph loader (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftglyph.c b/thirdparty/freetype/src/base/ftglyph.c
index e2c6f73f80..571dca1a96 100644
--- a/thirdparty/freetype/src/base/ftglyph.c
+++ b/thirdparty/freetype/src/base/ftglyph.c
@@ -4,7 +4,7 @@
*
* FreeType convenience functions to handle glyphs (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -34,6 +34,7 @@
#include <freetype/ftoutln.h>
#include <freetype/ftbitmap.h>
#include <freetype/internal/ftobjs.h>
+#include <freetype/otsvg.h>
#include "ftbase.h"
@@ -277,6 +278,240 @@
)
+#ifdef FT_CONFIG_OPTION_SVG
+
+ /*************************************************************************/
+ /*************************************************************************/
+ /**** ****/
+ /**** FT_SvgGlyph support ****/
+ /**** ****/
+ /*************************************************************************/
+ /*************************************************************************/
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_svg_glyph_init( FT_Glyph svg_glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_ULong doc_length;
+ FT_SVG_Document document;
+ FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
+
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = FT_GLYPH( glyph )->library->memory;
+
+
+ if ( slot->format != FT_GLYPH_FORMAT_SVG )
+ {
+ error = FT_THROW( Invalid_Glyph_Format );
+ goto Exit;
+ }
+
+ if ( slot->other == NULL )
+ {
+ error = FT_THROW( Invalid_Slot_Handle );
+ goto Exit;
+ }
+
+ document = (FT_SVG_Document)slot->other;
+
+ if ( document->svg_document_length == 0 )
+ {
+ error = FT_THROW( Invalid_Slot_Handle );
+ goto Exit;
+ }
+
+ /* allocate a new document */
+ doc_length = document->svg_document_length;
+ if ( FT_QALLOC( glyph->svg_document, doc_length ) )
+ goto Exit;
+ glyph->svg_document_length = doc_length;
+
+ glyph->glyph_index = slot->glyph_index;
+
+ glyph->metrics = document->metrics;
+ glyph->units_per_EM = document->units_per_EM;
+
+ glyph->start_glyph_id = document->start_glyph_id;
+ glyph->end_glyph_id = document->end_glyph_id;
+
+ glyph->transform = document->transform;
+ glyph->delta = document->delta;
+
+ /* copy the document into glyph */
+ FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_svg_glyph_done( FT_Glyph svg_glyph )
+ {
+ FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
+ FT_Memory memory = svg_glyph->library->memory;
+
+
+ /* just free the memory */
+ FT_FREE( glyph->svg_document );
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_svg_glyph_copy( FT_Glyph svg_source,
+ FT_Glyph svg_target )
+ {
+ FT_SvgGlyph source = (FT_SvgGlyph)svg_source;
+ FT_SvgGlyph target = (FT_SvgGlyph)svg_target;
+
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = FT_GLYPH( source )->library->memory;
+
+
+ if ( svg_source->format != FT_GLYPH_FORMAT_SVG )
+ {
+ error = FT_THROW( Invalid_Glyph_Format );
+ goto Exit;
+ }
+
+ if ( source->svg_document_length == 0 )
+ {
+ error = FT_THROW( Invalid_Slot_Handle );
+ goto Exit;
+ }
+
+ target->glyph_index = source->glyph_index;
+
+ target->svg_document_length = source->svg_document_length;
+
+ target->metrics = source->metrics;
+ target->units_per_EM = source->units_per_EM;
+
+ target->start_glyph_id = source->start_glyph_id;
+ target->end_glyph_id = source->end_glyph_id;
+
+ target->transform = source->transform;
+ target->delta = source->delta;
+
+ /* allocate space for the SVG document */
+ if ( FT_QALLOC( target->svg_document, target->svg_document_length ) )
+ goto Exit;
+
+ /* copy the document */
+ FT_MEM_COPY( target->svg_document,
+ source->svg_document,
+ target->svg_document_length );
+
+ Exit:
+ return error;
+ }
+
+
+ FT_CALLBACK_DEF( void )
+ ft_svg_glyph_transform( FT_Glyph svg_glyph,
+ const FT_Matrix* _matrix,
+ const FT_Vector* _delta )
+ {
+ FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
+ FT_Matrix* matrix = (FT_Matrix*)_matrix;
+ FT_Vector* delta = (FT_Vector*)_delta;
+
+ FT_Matrix tmp_matrix;
+ FT_Vector tmp_delta;
+
+ FT_Matrix a, b;
+ FT_Pos x, y;
+
+
+ if ( !matrix )
+ {
+ tmp_matrix.xx = 0x10000;
+ tmp_matrix.xy = 0;
+ tmp_matrix.yx = 0;
+ tmp_matrix.yy = 0x10000;
+
+ matrix = &tmp_matrix;
+ }
+
+ if ( !delta )
+ {
+ tmp_delta.x = 0;
+ tmp_delta.y = 0;
+
+ delta = &tmp_delta;
+ }
+
+ a = glyph->transform;
+ b = *matrix;
+ FT_Matrix_Multiply( &b, &a );
+
+ x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ),
+ FT_MulFix( matrix->xy, glyph->delta.y ) ),
+ delta->x );
+ y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ),
+ FT_MulFix( matrix->yy, glyph->delta.y ) ),
+ delta->y );
+
+ glyph->delta.x = x;
+ glyph->delta.y = y;
+
+ glyph->transform = a;
+ }
+
+
+ FT_CALLBACK_DEF( FT_Error )
+ ft_svg_glyph_prepare( FT_Glyph svg_glyph,
+ FT_GlyphSlot slot )
+ {
+ FT_SvgGlyph glyph = (FT_SvgGlyph)svg_glyph;
+
+ FT_Error error = FT_Err_Ok;
+ FT_Memory memory = svg_glyph->library->memory;
+
+ FT_SVG_Document document = NULL;
+
+
+ if ( FT_NEW( document ) )
+ return error;
+
+ document->svg_document = glyph->svg_document;
+ document->svg_document_length = glyph->svg_document_length;
+
+ document->metrics = glyph->metrics;
+ document->units_per_EM = glyph->units_per_EM;
+
+ document->start_glyph_id = glyph->start_glyph_id;
+ document->end_glyph_id = glyph->end_glyph_id;
+
+ document->transform = glyph->transform;
+ document->delta = glyph->delta;
+
+ slot->format = FT_GLYPH_FORMAT_SVG;
+ slot->glyph_index = glyph->glyph_index;
+ slot->other = document;
+
+ return error;
+ }
+
+
+ FT_DEFINE_GLYPH(
+ ft_svg_glyph_class,
+
+ sizeof ( FT_SvgGlyphRec ),
+ FT_GLYPH_FORMAT_SVG,
+
+ ft_svg_glyph_init, /* FT_Glyph_InitFunc glyph_init */
+ ft_svg_glyph_done, /* FT_Glyph_DoneFunc glyph_done */
+ ft_svg_glyph_copy, /* FT_Glyph_CopyFunc glyph_copy */
+ ft_svg_glyph_transform, /* FT_Glyph_TransformFunc glyph_transform */
+ NULL, /* FT_Glyph_GetBBoxFunc glyph_bbox */
+ ft_svg_glyph_prepare /* FT_Glyph_PrepareFunc glyph_prepare */
+ )
+
+#endif /* FT_CONFIG_OPTION_SVG */
+
+
/*************************************************************************/
/*************************************************************************/
/**** ****/
@@ -377,6 +612,12 @@
else if ( format == FT_GLYPH_FORMAT_OUTLINE )
clazz = &ft_outline_glyph_class;
+#ifdef FT_CONFIG_OPTION_SVG
+ /* if it is an SVG glyph */
+ else if ( format == FT_GLYPH_FORMAT_SVG )
+ clazz = &ft_svg_glyph_class;
+#endif
+
else
{
/* try to find a renderer that supports the glyph image format */
@@ -595,6 +836,16 @@
if ( !error )
error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
+#ifdef FT_CONFIG_OPTION_SVG
+ if ( clazz == &ft_svg_glyph_class )
+ {
+ FT_Memory memory = library->memory;
+
+
+ FT_FREE( dummy.other );
+ }
+#endif
+
#if 1
if ( !destroy && origin )
{
diff --git a/thirdparty/freetype/src/base/ftgxval.c b/thirdparty/freetype/src/base/ftgxval.c
index e9567f77f3..5598a11c6d 100644
--- a/thirdparty/freetype/src/base/ftgxval.c
+++ b/thirdparty/freetype/src/base/ftgxval.c
@@ -4,7 +4,7 @@
*
* FreeType API for validating TrueTypeGX/AAT tables (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO, Redhat K.K,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/base/fthash.c b/thirdparty/freetype/src/base/fthash.c
index 449b03a5c1..313bbbb4b2 100644
--- a/thirdparty/freetype/src/base/fthash.c
+++ b/thirdparty/freetype/src/base/fthash.c
@@ -243,7 +243,7 @@
nn = *bp;
if ( !nn )
{
- if ( FT_NEW( nn ) )
+ if ( FT_QNEW( nn ) )
goto Exit;
*bp = nn;
diff --git a/thirdparty/freetype/src/base/ftinit.c b/thirdparty/freetype/src/base/ftinit.c
index a2d2b933c0..0f29a6017e 100644
--- a/thirdparty/freetype/src/base/ftinit.c
+++ b/thirdparty/freetype/src/base/ftinit.c
@@ -4,7 +4,7 @@
*
* FreeType initialization layer (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftlcdfil.c b/thirdparty/freetype/src/base/ftlcdfil.c
index 488b913e63..e72f6d668d 100644
--- a/thirdparty/freetype/src/base/ftlcdfil.c
+++ b/thirdparty/freetype/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
*
* FreeType API for color filtering of subpixel bitmap glyphs (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftmac.c b/thirdparty/freetype/src/base/ftmac.c
index 36a860979e..21f1894ad3 100644
--- a/thirdparty/freetype/src/base/ftmac.c
+++ b/thirdparty/freetype/src/base/ftmac.c
@@ -8,7 +8,7 @@
* This file is for Mac OS X only; see builds/mac/ftoldmac.c for
* classic platforms built by MPW.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* Just van Rossum, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -105,7 +105,7 @@
/* Don't want warnings about our own use of deprecated functions. */
#define FT_DEPRECATED_ATTRIBUTE
-#include FT_MAC_H
+#include <freetype/ftmac.h>
#ifndef kATSOptionFlagsUnRestrictedScope /* since Mac OS X 10.1 */
#define kATSOptionFlagsUnRestrictedScope kATSOptionFlagsDefault
@@ -314,7 +314,7 @@
NULL, NULL, NULL ) )
return ( OSType ) 0;
- return ((FInfo *)(info.finderInfo))->fdType;
+ return ( (FInfo *)( info.finderInfo ) )->fdType;
}
@@ -462,7 +462,7 @@
if ( ps_name_len != 0 )
{
- ft_memcpy(ps_name, names[0] + 1, ps_name_len);
+ ft_memcpy( ps_name, names[0] + 1, ps_name_len );
ps_name[ps_name_len] = 0;
}
if ( style->indexes[face_index] > 1 &&
diff --git a/thirdparty/freetype/src/base/ftmm.c b/thirdparty/freetype/src/base/ftmm.c
index fc5d4ecc8d..dbbd87c9b9 100644
--- a/thirdparty/freetype/src/base/ftmm.c
+++ b/thirdparty/freetype/src/base/ftmm.c
@@ -4,7 +4,7 @@
*
* Multiple Master font support (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftobjs.c b/thirdparty/freetype/src/base/ftobjs.c
index 883f1a8970..eeda69c3ed 100644
--- a/thirdparty/freetype/src/base/ftobjs.c
+++ b/thirdparty/freetype/src/base/ftobjs.c
@@ -4,7 +4,7 @@
*
* The FreeType private base classes (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -19,6 +19,7 @@
#include <freetype/ftlist.h>
#include <freetype/ftoutln.h>
#include <freetype/ftfntfmt.h>
+#include <freetype/otsvg.h>
#include <freetype/internal/ftvalid.h>
#include <freetype/internal/ftobjs.h>
@@ -27,6 +28,7 @@
#include <freetype/internal/ftstream.h>
#include <freetype/internal/sfnt.h> /* for SFNT_Load_Table_Func */
#include <freetype/internal/psaux.h> /* for PS_Driver */
+#include <freetype/internal/svginterface.h>
#include <freetype/tttables.h>
#include <freetype/tttags.h>
@@ -328,6 +330,19 @@
if ( !error && clazz->init_slot )
error = clazz->init_slot( slot );
+#ifdef FT_CONFIG_OPTION_SVG
+ /* if SVG table exists, allocate the space in `slot->other` */
+ if ( slot->face->face_flags & FT_FACE_FLAG_SVG )
+ {
+ FT_SVG_Document document = NULL;
+
+
+ if ( FT_NEW( document ) )
+ goto Exit;
+ slot->other = document;
+ }
+#endif
+
Exit:
return error;
}
@@ -372,7 +387,18 @@
FT_Pos width, height, pitch;
- if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
+ if ( slot->format == FT_GLYPH_FORMAT_SVG )
+ {
+ FT_Module module;
+ SVG_Service svg_service;
+
+
+ module = FT_Get_Module( slot->library, "ot-svg" );
+ svg_service = (SVG_Service)module->clazz->module_interface;
+
+ return (FT_Bool)svg_service->preset_slot( module, slot, FALSE );
+ }
+ else if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
return 1;
if ( origin )
@@ -564,8 +590,27 @@
slot->subglyphs = NULL;
slot->control_data = NULL;
slot->control_len = 0;
- slot->other = NULL;
- slot->format = FT_GLYPH_FORMAT_NONE;
+
+#ifndef FT_CONFIG_OPTION_SVG
+ slot->other = NULL;
+#else
+ if ( !( slot->face->face_flags & FT_FACE_FLAG_SVG ) )
+ slot->other = NULL;
+ else
+ {
+ if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
+ {
+ FT_Memory memory = slot->face->memory;
+ FT_SVG_Document doc = (FT_SVG_Document)slot->other;
+
+
+ FT_FREE( doc->svg_document );
+ slot->internal->load_flags &= ~FT_GLYPH_OWN_GZIP_SVG;
+ }
+ }
+#endif
+
+ slot->format = FT_GLYPH_FORMAT_NONE;
slot->linearHoriAdvance = 0;
slot->linearVertAdvance = 0;
@@ -583,6 +628,23 @@
FT_Driver_Class clazz = driver->clazz;
FT_Memory memory = driver->root.memory;
+#ifdef FT_CONFIG_OPTION_SVG
+ if ( slot->face->face_flags & FT_FACE_FLAG_SVG )
+ {
+ /* free memory in case SVG was there */
+ if ( slot->internal->flags & FT_GLYPH_OWN_GZIP_SVG )
+ {
+ FT_SVG_Document doc = (FT_SVG_Document)slot->other;
+
+
+ FT_FREE( doc->svg_document );
+
+ slot->internal->flags &= ~FT_GLYPH_OWN_GZIP_SVG;
+ }
+
+ FT_FREE( slot->other );
+ }
+#endif
if ( clazz->done_slot )
clazz->done_slot( slot );
@@ -858,6 +920,11 @@
library = driver->root.library;
hinter = library->auto_hinter;
+ /* undefined scale means no scale */
+ if ( face->size->metrics.x_ppem == 0 ||
+ face->size->metrics.y_ppem == 0 )
+ load_flags |= FT_LOAD_NO_SCALE;
+
/* resolve load flags dependencies */
if ( load_flags & FT_LOAD_NO_RECURSE )
@@ -947,11 +1014,21 @@
FT_AutoHinter_Interface hinting;
- /* try to load embedded bitmaps first if available */
- /* */
- /* XXX: This is really a temporary hack that should disappear */
- /* promptly with FreeType 2.1! */
- /* */
+ /* XXX: The use of the `FT_LOAD_XXX_ONLY` flags is not very */
+ /* elegant. */
+
+ /* try to load SVG documents if available */
+ if ( FT_HAS_SVG( face ) )
+ {
+ error = driver->clazz->load_glyph( slot, face->size,
+ glyph_index,
+ load_flags | FT_LOAD_SVG_ONLY );
+
+ if ( !error && slot->format == FT_GLYPH_FORMAT_SVG )
+ goto Load_Ok;
+ }
+
+ /* try to load embedded bitmaps if available */
if ( FT_HAS_FIXED_SIZES( face ) &&
( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
{
@@ -1597,7 +1674,6 @@
FT_FREE( stream->base );
stream->size = 0;
- stream->base = NULL;
stream->close = NULL;
}
@@ -2451,6 +2527,16 @@
#endif
+ /* only use lower 31 bits together with sign bit */
+ if ( face_index > 0 )
+ face_index &= 0x7FFFFFFFL;
+ else
+ {
+ face_index = -face_index;
+ face_index &= 0x7FFFFFFFL;
+ face_index = -face_index;
+ }
+
#ifdef FT_DEBUG_LEVEL_TRACE
FT_TRACE3(( "FT_Open_Face: " ));
if ( face_index < 0 )
@@ -3323,6 +3409,9 @@
if ( !face )
return FT_THROW( Invalid_Face_Handle );
+ if ( !face->size )
+ return FT_THROW( Invalid_Size_Handle );
+
if ( !req || req->width < 0 || req->height < 0 ||
req->type >= FT_SIZE_REQUEST_TYPE_MAX )
return FT_THROW( Invalid_Argument );
@@ -4474,7 +4563,7 @@
render->glyph_format = clazz->glyph_format;
/* allocate raster object if needed */
- if ( clazz->raster_class->raster_new )
+ if ( clazz->raster_class && clazz->raster_class->raster_new )
{
error = clazz->raster_class->raster_new( memory, &render->raster );
if ( error )
@@ -4484,6 +4573,11 @@
render->render = clazz->render_glyph;
}
+#ifdef FT_CONFIG_OPTION_SVG
+ if ( clazz->glyph_format == FT_GLYPH_FORMAT_SVG )
+ render->render = clazz->render_glyph;
+#endif
+
/* add to list */
node->data = module;
FT_List_Add( &library->renderers, node );
@@ -5729,7 +5823,7 @@
SFNT_Service sfnt;
- if ( !face || !paint || !paint )
+ if ( !face || !paint )
return 0;
if ( !FT_IS_SFNT( face ) )
diff --git a/thirdparty/freetype/src/base/ftotval.c b/thirdparty/freetype/src/base/ftotval.c
index 0f748d006c..f336e96227 100644
--- a/thirdparty/freetype/src/base/ftotval.c
+++ b/thirdparty/freetype/src/base/ftotval.c
@@ -4,7 +4,7 @@
*
* FreeType API for validating OpenType tables (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftoutln.c b/thirdparty/freetype/src/base/ftoutln.c
index 98c6ca16e6..624df03ad8 100644
--- a/thirdparty/freetype/src/base/ftoutln.c
+++ b/thirdparty/freetype/src/base/ftoutln.c
@@ -4,7 +4,7 @@
*
* FreeType outline management (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftpatent.c b/thirdparty/freetype/src/base/ftpatent.c
index cd192d33bd..353ed2b531 100644
--- a/thirdparty/freetype/src/base/ftpatent.c
+++ b/thirdparty/freetype/src/base/ftpatent.c
@@ -5,7 +5,7 @@
* FreeType API for checking patented TrueType bytecode instructions
* (body). Obsolete, retained for backward compatibility.
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftpfr.c b/thirdparty/freetype/src/base/ftpfr.c
index 5afd5a183f..9e748f06e6 100644
--- a/thirdparty/freetype/src/base/ftpfr.c
+++ b/thirdparty/freetype/src/base/ftpfr.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing PFR-specific data (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftpsprop.c b/thirdparty/freetype/src/base/ftpsprop.c
index 3655ae97ec..81fcee08f6 100644
--- a/thirdparty/freetype/src/base/ftpsprop.c
+++ b/thirdparty/freetype/src/base/ftpsprop.c
@@ -5,7 +5,7 @@
* Get and set properties of PostScript drivers (body).
* See `ftdriver.h' for available properties.
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftrfork.c b/thirdparty/freetype/src/base/ftrfork.c
index cb7e94ddb0..356998d3fa 100644
--- a/thirdparty/freetype/src/base/ftrfork.c
+++ b/thirdparty/freetype/src/base/ftrfork.c
@@ -4,7 +4,7 @@
*
* Embedded resource forks accessor (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO and Redhat K.K.
*
* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
@@ -402,17 +402,17 @@
FT_Long *result_offset );
- CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table,
- ft_raccess_guess_rec)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double)
- CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk)
+ CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table,
+ ft_raccess_guess_rec )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double )
+ CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk )
CONST_FT_RFORK_RULE_ARRAY_END
@@ -868,9 +868,7 @@
const char* tmp;
const char* slash;
size_t new_length;
- FT_Error error = FT_Err_Ok;
-
- FT_UNUSED( error );
+ FT_Error error;
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
diff --git a/thirdparty/freetype/src/base/ftsnames.c b/thirdparty/freetype/src/base/ftsnames.c
index 44dba66638..3bf20c389b 100644
--- a/thirdparty/freetype/src/base/ftsnames.c
+++ b/thirdparty/freetype/src/base/ftsnames.c
@@ -7,7 +7,7 @@
*
* This is _not_ used to retrieve glyph names!
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftstream.c b/thirdparty/freetype/src/base/ftstream.c
index 5992998ba3..cc926565c3 100644
--- a/thirdparty/freetype/src/base/ftstream.c
+++ b/thirdparty/freetype/src/base/ftstream.c
@@ -4,7 +4,7 @@
*
* I/O stream support (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftstroke.c b/thirdparty/freetype/src/base/ftstroke.c
index 37e9649411..aa983f940f 100644
--- a/thirdparty/freetype/src/base/ftstroke.c
+++ b/thirdparty/freetype/src/base/ftstroke.c
@@ -4,7 +4,7 @@
*
* FreeType path stroker (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftsynth.c b/thirdparty/freetype/src/base/ftsynth.c
index 73565b1307..10bbe0dfda 100644
--- a/thirdparty/freetype/src/base/ftsynth.c
+++ b/thirdparty/freetype/src/base/ftsynth.c
@@ -4,7 +4,7 @@
*
* FreeType synthesizing code for emboldening and slanting (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftsystem.c b/thirdparty/freetype/src/base/ftsystem.c
index 9beb7e245d..d8826b2367 100644
--- a/thirdparty/freetype/src/base/ftsystem.c
+++ b/thirdparty/freetype/src/base/ftsystem.c
@@ -4,7 +4,7 @@
*
* ANSI-specific FreeType low-level system interface (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fttrigon.c b/thirdparty/freetype/src/base/fttrigon.c
index 0ca6d7810a..6964edb0f5 100644
--- a/thirdparty/freetype/src/base/fttrigon.c
+++ b/thirdparty/freetype/src/base/fttrigon.c
@@ -4,7 +4,7 @@
*
* FreeType trigonometric functions (body).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/fttype1.c b/thirdparty/freetype/src/base/fttype1.c
index 0d0afbcef0..de3d5a48bd 100644
--- a/thirdparty/freetype/src/base/fttype1.c
+++ b/thirdparty/freetype/src/base/fttype1.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for PS names support (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftutil.c b/thirdparty/freetype/src/base/ftutil.c
index 3142faee98..5a91382580 100644
--- a/thirdparty/freetype/src/base/ftutil.c
+++ b/thirdparty/freetype/src/base/ftutil.c
@@ -4,7 +4,7 @@
*
* FreeType utility file for memory and list management (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/base/ftver.rc b/thirdparty/freetype/src/base/ftver.rc
deleted file mode 100644
index a3d05b3780..0000000000
--- a/thirdparty/freetype/src/base/ftver.rc
+++ /dev/null
@@ -1,61 +0,0 @@
-/***************************************************************************/
-/* */
-/* ftver.rc */
-/* */
-/* FreeType VERSIONINFO resource for Windows DLLs. */
-/* */
-/* Copyright (C) 2018-2021 by */
-/* David Turner, Robert Wilhelm, and Werner Lemberg. */
-/* */
-/* This file is part of the FreeType project, and may only be used, */
-/* modified, and distributed under the terms of the FreeType project */
-/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
-/* this file you indicate that you have read the license and */
-/* understand and accept it fully. */
-/* */
-/***************************************************************************/
-
-
-#include<windows.h>
-
-#define FT_VERSION 2,11,1,0
-#define FT_VERSION_STR "2.11.1"
-
-VS_VERSION_INFO VERSIONINFO
-FILEVERSION FT_VERSION
-PRODUCTVERSION FT_VERSION
-FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
-#ifdef _DEBUG
-FILEFLAGS VS_FF_DEBUG
-#endif
-#ifdef DLL_EXPORT
-FILETYPE VFT_DLL
-#define FT_FILENAME "freetype.dll"
-#else
-FILETYPE VFT_STATIC_LIB
-#define FT_FILENAME "freetype.lib"
-#endif
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904E4"
- BEGIN
- VALUE "CompanyName", "The FreeType Project"
- VALUE "FileDescription", "Font Rendering Library"
- VALUE "FileVersion", FT_VERSION_STR
- VALUE "ProductName", "FreeType"
- VALUE "ProductVersion", FT_VERSION_STR
- VALUE "LegalCopyright", "\251 2000-2021 The FreeType Project www.freetype.org. All rights reserved."
- VALUE "InternalName", "freetype"
- VALUE "OriginalFilename", FT_FILENAME
- END
- END
-
- BLOCK "VarFileInfo"
- BEGIN
- /* The following line should only be modified for localized versions. */
- /* It consists of any number of WORD,WORD pairs, with each pair */
- /* describing a "language,codepage" combination supported by the file. */
- VALUE "Translation", 0x409, 1252
- END
-END
diff --git a/thirdparty/freetype/src/base/ftwinfnt.c b/thirdparty/freetype/src/base/ftwinfnt.c
index 98f197afdc..193f7fa048 100644
--- a/thirdparty/freetype/src/base/ftwinfnt.c
+++ b/thirdparty/freetype/src/base/ftwinfnt.c
@@ -4,7 +4,7 @@
*
* FreeType API for accessing Windows FNT specific info (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/bdf/README b/thirdparty/freetype/src/bdf/README
deleted file mode 100644
index 996ac2d2aa..0000000000
--- a/thirdparty/freetype/src/bdf/README
+++ /dev/null
@@ -1,148 +0,0 @@
- FreeType font driver for BDF fonts
-
- Francesco Zappa Nardelli
- <francesco.zappa.nardelli@ens.fr>
-
-
-Introduction
-************
-
-BDF (Bitmap Distribution Format) is a bitmap font format defined by Adobe,
-which is intended to be easily understood by both humans and computers.
-This code implements a BDF driver for the FreeType library, following the
-Adobe Specification V 2.2. The specification of the BDF font format is
-available from Adobe's web site:
-
- https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5005.BDF_Spec.pdf
-
-Many good bitmap fonts in bdf format come with XFree86 (www.XFree86.org).
-They do not define vertical metrics, because the X Consortium BDF
-specification has removed them.
-
-
-Encodings
-*********
-
-The variety of encodings that accompanies bdf fonts appears to encompass the
-small set defined in freetype.h. On the other hand, two properties that
-specify encoding and registry are usually defined in bdf fonts.
-
-I decided to make these two properties directly accessible, leaving to the
-client application the work of interpreting them. For instance:
-
-
- #include FT_INTERNAL_BDF_TYPES_H
-
- FT_Face face;
- BDF_Public_Face bdfface;
-
-
- FT_New_Face( library, ..., &face );
-
- bdfface = (BDF_Public_Face)face;
-
- if ( ( bdfface->charset_registry == "ISO10646" ) &&
- ( bdfface->charset_encoding == "1" ) )
- [..]
-
-
-Thus the driver always exports `ft_encoding_none' as face->charmap.encoding.
-FT_Get_Char_Index's behavior is unmodified, that is, it converts the ULong
-value given as argument into the corresponding glyph number.
-
-If the two properties are not available, Adobe Standard Encoding should be
-assumed.
-
-
-Anti-Aliased Bitmaps
-********************
-
-The driver supports an extension to the BDF format as used in Mark Leisher's
-xmbdfed bitmap font editor. Microsoft's SBIT tool expects bitmap fonts in
-that format for adding anti-aliased them to TrueType fonts. It introduces a
-fourth field to the `SIZE' keyword which gives the bpp value (bits per
-pixel) of the glyph data in the font. Possible values are 1 (the default),
-2 (four gray levels), 4 (16 gray levels), and 8 (256 gray levels). The
-driver returns either a bitmap with 1 bit per pixel or a pixmap with 8bits
-per pixel (using 4, 16, and 256 gray levels, respectively).
-
-
-Known problems
-**************
-
-- A font is entirely loaded into memory. Obviously, this is not the Right
- Thing(TM). If you have big fonts I suggest you convert them into PCF
- format (using the bdftopcf utility): the PCF font drive of FreeType can
- perform incremental glyph loading.
-
-When I have some time, I will implement on-demand glyph parsing.
-
-- Except for encodings properties, client applications have no visibility of
- the PCF_Face object. This means that applications cannot directly access
- font tables and must trust FreeType.
-
-- Currently, glyph names are ignored.
-
- I plan to give full visibility of the BDF_Face object in an upcoming
- revision of the driver, thus implementing also glyph names.
-
-- As I have never seen a BDF font that defines vertical metrics, vertical
- metrics are (parsed and) discarded. If you own a BDF font that defines
- vertical metrics, please let me know (I will implement them in 5-10
- minutes).
-
-
-License
-*******
-
-Copyright (C) 2001-2002 by Francesco Zappa Nardelli
-
-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.
-
-*** Portions of the driver (that is, bdflib.c and bdf.h):
-
-Copyright 2000 Computing Research Labs, New Mexico State University
-Copyright 2001-2002, 2011 Francesco Zappa Nardelli
-
-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 COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY 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.
-
-
-Credits
-*******
-
-This driver is based on excellent Mark Leisher's bdf library. If you
-find something good in this driver you should probably thank him, not
-me.
diff --git a/thirdparty/freetype/src/bdf/bdflib.c b/thirdparty/freetype/src/bdf/bdflib.c
index b65c8a2f3e..6603148a02 100644
--- a/thirdparty/freetype/src/bdf/bdflib.c
+++ b/thirdparty/freetype/src/bdf/bdflib.c
@@ -613,7 +613,7 @@
if ( FT_QREALLOC( buf, buf_size, new_size ) )
goto Exit;
- cursor = (ptrdiff_t)buf_size;
+ cursor = avail;
buf_size = new_size;
}
else
@@ -623,7 +623,6 @@
FT_MEM_MOVE( buf, buf + start, bytes );
cursor = bytes;
- avail -= bytes;
start = 0;
}
refill = 1;
@@ -1175,7 +1174,6 @@
font->props_size + 1 ) )
goto Exit;
- fp = font->props + font->props_size;
font->props_size++;
}
@@ -1537,8 +1535,6 @@
/* kept. */
FT_FREE( p->glyph_name );
}
-
- p->glyph_name = NULL;
}
/* Clear the flags that might be added when width and height are */
@@ -1953,7 +1949,7 @@
}
}
- if ( FT_ALLOC( p->font->internal, sizeof ( FT_HashRec ) ) )
+ if ( FT_QALLOC( p->font->internal, sizeof ( FT_HashRec ) ) )
goto Exit;
error = ft_hash_str_init( (FT_Hash)p->font->internal, memory );
if ( error )
diff --git a/thirdparty/freetype/src/bzip2/ftbzip2.c b/thirdparty/freetype/src/bzip2/ftbzip2.c
index 296cea088b..ab2da7e62b 100644
--- a/thirdparty/freetype/src/bzip2/ftbzip2.c
+++ b/thirdparty/freetype/src/bzip2/ftbzip2.c
@@ -8,7 +8,7 @@
* parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2010-2021 by
+ * Copyright (C) 2010-2022 by
* Joel Klinghed.
*
* based on `src/gzip/ftgzip.c'
@@ -57,8 +57,9 @@
/* it is better to use FreeType memory routines instead of raw
'malloc/free' */
- typedef void *(* alloc_func)(void*, int, int);
- typedef void (* free_func)(void*, void*);
+ typedef void* (*alloc_func)( void*, int, int );
+ typedef void (*free_func) ( void*, void* );
+
static void*
ft_bzip2_alloc( FT_Memory memory,
@@ -102,10 +103,11 @@
FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
- FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
- FT_ULong pos; /* position in output */
+ FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
+ FT_ULong pos; /* position in output */
FT_Byte* cursor;
FT_Byte* limit;
+ FT_Bool reset; /* reset before next read */
} FT_BZip2FileRec, *FT_BZip2File;
@@ -153,6 +155,7 @@
zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
+ zip->reset = 0;
/* check .bz2 header */
{
@@ -228,6 +231,7 @@
zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
zip->cursor = zip->limit;
zip->pos = 0;
+ zip->reset = 0;
BZ2_bzDecompressInit( bzstream, 0, 0 );
}
@@ -302,18 +306,23 @@
err = BZ2_bzDecompress( bzstream );
- if ( err == BZ_STREAM_END )
+ if ( err != BZ_OK )
{
- zip->limit = (FT_Byte*)bzstream->next_out;
- if ( zip->limit == zip->cursor )
- error = FT_THROW( Invalid_Stream_Operation );
- break;
- }
- else if ( err != BZ_OK )
- {
- zip->limit = zip->cursor;
- error = FT_THROW( Invalid_Stream_Operation );
- break;
+ zip->reset = 1;
+
+ if ( err == BZ_STREAM_END )
+ {
+ zip->limit = (FT_Byte*)bzstream->next_out;
+ if ( zip->limit == zip->cursor )
+ error = FT_THROW( Invalid_Stream_Operation );
+ break;
+ }
+ else
+ {
+ zip->limit = zip->cursor;
+ error = FT_THROW( Invalid_Stream_Operation );
+ break;
+ }
}
}
@@ -363,9 +372,9 @@
FT_Error error;
- /* Reset inflate stream if we're seeking backwards. */
- /* Yes, that is not too efficient, but it saves memory :-) */
- if ( pos < zip->pos )
+ /* Reset inflate stream if seeking backwards or bzip reported an error. */
+ /* Yes, that is not too efficient, but it saves memory :-) */
+ if ( pos < zip->pos || zip->reset )
{
error = ft_bzip2_file_reset( zip );
if ( error )
diff --git a/thirdparty/freetype/src/cache/ftcache.c b/thirdparty/freetype/src/cache/ftcache.c
index ddd3e43c02..e26b44a700 100644
--- a/thirdparty/freetype/src/cache/ftcache.c
+++ b/thirdparty/freetype/src/cache/ftcache.c
@@ -4,7 +4,7 @@
*
* The FreeType Caching sub-system (body only).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcbasic.c b/thirdparty/freetype/src/cache/ftcbasic.c
index 1760c5fbd4..635b17d074 100644
--- a/thirdparty/freetype/src/cache/ftcbasic.c
+++ b/thirdparty/freetype/src/cache/ftcbasic.c
@@ -4,7 +4,7 @@
*
* The FreeType basic cache interface (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -26,6 +26,7 @@
#include "ftccback.h"
#include "ftcerror.h"
+#undef FT_COMPONENT
#define FT_COMPONENT cache
@@ -182,7 +183,8 @@
if ( !error )
{
if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP ||
- face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+ face->glyph->format == FT_GLYPH_FORMAT_OUTLINE ||
+ face->glyph->format == FT_GLYPH_FORMAT_SVG )
{
/* ok, copy it */
FT_Glyph glyph;
diff --git a/thirdparty/freetype/src/cache/ftccache.c b/thirdparty/freetype/src/cache/ftccache.c
index 5bbf329298..ab4ad2faa2 100644
--- a/thirdparty/freetype/src/cache/ftccache.c
+++ b/thirdparty/freetype/src/cache/ftccache.c
@@ -4,7 +4,7 @@
*
* The FreeType internal cache interface (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccache.h b/thirdparty/freetype/src/cache/ftccache.h
index 4849b92352..ae0ae8b172 100644
--- a/thirdparty/freetype/src/cache/ftccache.h
+++ b/thirdparty/freetype/src/cache/ftccache.h
@@ -4,7 +4,7 @@
*
* FreeType internal cache interface (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -210,7 +210,7 @@ FT_BEGIN_HEADER
#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error ) \
FT_BEGIN_STMNT \
FTC_Node *_bucket, *_pnode, _node; \
- FTC_Cache _cache = FTC_CACHE(cache); \
+ FTC_Cache _cache = FTC_CACHE( cache ); \
FT_Offset _hash = (FT_Offset)(hash); \
FTC_Node_CompareFunc _nodcomp = (FTC_Node_CompareFunc)(nodecmp); \
FT_Bool _list_changed = FALSE; \
diff --git a/thirdparty/freetype/src/cache/ftccback.h b/thirdparty/freetype/src/cache/ftccback.h
index 8185fe3738..ba01af2e78 100644
--- a/thirdparty/freetype/src/cache/ftccback.h
+++ b/thirdparty/freetype/src/cache/ftccback.h
@@ -4,7 +4,7 @@
*
* Callback functions of the caching sub-system (specification only).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftccmap.c b/thirdparty/freetype/src/cache/ftccmap.c
index 40b449b9cc..0ee1834e27 100644
--- a/thirdparty/freetype/src/cache/ftccmap.c
+++ b/thirdparty/freetype/src/cache/ftccmap.c
@@ -4,7 +4,7 @@
*
* FreeType CharMap cache (body)
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -116,7 +116,7 @@
FT_UInt nn;
- if ( !FT_NEW( node ) )
+ if ( !FT_QNEW( node ) )
{
node->face_id = query->face_id;
node->cmap_index = query->cmap_index;
diff --git a/thirdparty/freetype/src/cache/ftcerror.h b/thirdparty/freetype/src/cache/ftcerror.h
index 2c6faf65e2..44e74d36b4 100644
--- a/thirdparty/freetype/src/cache/ftcerror.h
+++ b/thirdparty/freetype/src/cache/ftcerror.h
@@ -4,7 +4,7 @@
*
* Caching sub-system error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcglyph.c b/thirdparty/freetype/src/cache/ftcglyph.c
index 52771c7a8a..f826c8dd8e 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.c
+++ b/thirdparty/freetype/src/cache/ftcglyph.c
@@ -4,7 +4,7 @@
*
* FreeType Glyph Image (FT_Glyph) cache (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcglyph.h b/thirdparty/freetype/src/cache/ftcglyph.h
index cf00cdc7b8..cbb8077739 100644
--- a/thirdparty/freetype/src/cache/ftcglyph.h
+++ b/thirdparty/freetype/src/cache/ftcglyph.h
@@ -4,7 +4,7 @@
*
* FreeType abstract glyph cache (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -140,8 +140,8 @@ FT_BEGIN_HEADER
} FTC_FamilyRec, *FTC_Family;
-#define FTC_FAMILY(x) ( (FTC_Family)(x) )
-#define FTC_FAMILY_P(x) ( (FTC_Family*)(x) )
+#define FTC_FAMILY( x ) ( (FTC_Family)(x) )
+#define FTC_FAMILY_P( x ) ( (FTC_Family*)(x) )
typedef struct FTC_GNodeRec_
@@ -245,7 +245,7 @@ FT_BEGIN_HEADER
#define FTC_GCACHE_CLASS( x ) ((FTC_GCacheClass)(x))
#define FTC_CACHE_GCACHE_CLASS( x ) \
- FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
+ FTC_GCACHE_CLASS( FTC_CACHE( x )->org_class )
#define FTC_CACHE_FAMILY_CLASS( x ) \
( (FTC_MruListClass)FTC_CACHE_GCACHE_CLASS( x )->family_class )
diff --git a/thirdparty/freetype/src/cache/ftcimage.c b/thirdparty/freetype/src/cache/ftcimage.c
index 3f12a654b2..39ce61a511 100644
--- a/thirdparty/freetype/src/cache/ftcimage.c
+++ b/thirdparty/freetype/src/cache/ftcimage.c
@@ -4,7 +4,7 @@
*
* FreeType Image cache (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -64,7 +64,7 @@
FTC_INode inode = NULL;
- if ( !FT_NEW( inode ) )
+ if ( !FT_QNEW( inode ) )
{
FTC_GNode gnode = FTC_GNODE( inode );
FTC_Family family = gquery->family;
@@ -74,6 +74,7 @@
/* initialize its inner fields */
FTC_GNode_Init( gnode, gindex, family );
+ inode->glyph = NULL;
/* we will now load the glyph image */
error = clazz->family_load_glyph( family, gindex, cache,
diff --git a/thirdparty/freetype/src/cache/ftcimage.h b/thirdparty/freetype/src/cache/ftcimage.h
index 8b28d6f00b..55270a436c 100644
--- a/thirdparty/freetype/src/cache/ftcimage.h
+++ b/thirdparty/freetype/src/cache/ftcimage.h
@@ -4,7 +4,7 @@
*
* FreeType Generic Image cache (specification)
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -51,8 +51,8 @@ FT_BEGIN_HEADER
} FTC_INodeRec, *FTC_INode;
#define FTC_INODE( x ) ( (FTC_INode)( x ) )
-#define FTC_INODE_GINDEX( x ) FTC_GNODE(x)->gindex
-#define FTC_INODE_FAMILY( x ) FTC_GNODE(x)->family
+#define FTC_INODE_GINDEX( x ) FTC_GNODE( x )->gindex
+#define FTC_INODE_FAMILY( x ) FTC_GNODE( x )->family
typedef FT_Error
(*FTC_IFamily_LoadGlyphFunc)( FTC_Family family,
@@ -72,7 +72,7 @@ FT_BEGIN_HEADER
#define FTC_IFAMILY_CLASS( x ) ((FTC_IFamilyClass)(x))
#define FTC_CACHE_IFAMILY_CLASS( x ) \
- FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS(x)->family_class )
+ FTC_IFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class )
/* can be used as a @FTC_Node_FreeFunc */
diff --git a/thirdparty/freetype/src/cache/ftcmanag.c b/thirdparty/freetype/src/cache/ftcmanag.c
index 512de8a3fc..49f037aa73 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.c
+++ b/thirdparty/freetype/src/cache/ftcmanag.c
@@ -4,7 +4,7 @@
*
* FreeType Cache Manager (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmanag.h b/thirdparty/freetype/src/cache/ftcmanag.h
index 99aa926369..5c67af30bc 100644
--- a/thirdparty/freetype/src/cache/ftcmanag.h
+++ b/thirdparty/freetype/src/cache/ftcmanag.h
@@ -4,7 +4,7 @@
*
* FreeType Cache Manager (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcmru.c b/thirdparty/freetype/src/cache/ftcmru.c
index 2cac6f9d3a..6a14ae36e9 100644
--- a/thirdparty/freetype/src/cache/ftcmru.c
+++ b/thirdparty/freetype/src/cache/ftcmru.c
@@ -4,7 +4,7 @@
*
* FreeType MRU support (body).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -262,7 +262,9 @@
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
- else if ( FT_QALLOC( node, list->clazz.node_size ) )
+
+ /* zero new node in case of node_init failure */
+ else if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
diff --git a/thirdparty/freetype/src/cache/ftcmru.h b/thirdparty/freetype/src/cache/ftcmru.h
index 6befde307f..4fcadef477 100644
--- a/thirdparty/freetype/src/cache/ftcmru.h
+++ b/thirdparty/freetype/src/cache/ftcmru.h
@@ -4,7 +4,7 @@
*
* Simple MRU list-cache (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cache/ftcsbits.c b/thirdparty/freetype/src/cache/ftcsbits.c
index 362999fce0..4a8b1963eb 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.c
+++ b/thirdparty/freetype/src/cache/ftcsbits.c
@@ -4,7 +4,7 @@
*
* FreeType sbits manager (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -171,7 +171,7 @@
sbit->xadvance = (FT_Char)xadvance;
sbit->yadvance = (FT_Char)yadvance;
sbit->format = (FT_Byte)bitmap->pixel_mode;
- sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
+ sbit->max_grays = (FT_Byte)( bitmap->num_grays - 1 );
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
@@ -233,7 +233,7 @@
goto Exit;
}
- if ( !FT_NEW( snode ) )
+ if ( !FT_QNEW( snode ) )
{
FT_UInt count, start;
@@ -248,7 +248,9 @@
snode->count = count;
for ( node_count = 0; node_count < count; node_count++ )
{
- snode->sbits[node_count].width = 255;
+ snode->sbits[node_count].width = 255;
+ snode->sbits[node_count].height = 0;
+ snode->sbits[node_count].buffer = NULL;
}
error = ftc_snode_load( snode,
diff --git a/thirdparty/freetype/src/cache/ftcsbits.h b/thirdparty/freetype/src/cache/ftcsbits.h
index 9f2d5fb33c..8f10070457 100644
--- a/thirdparty/freetype/src/cache/ftcsbits.h
+++ b/thirdparty/freetype/src/cache/ftcsbits.h
@@ -4,7 +4,7 @@
*
* A small-bitmap cache (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -61,7 +61,7 @@ FT_BEGIN_HEADER
typedef const FTC_SFamilyClassRec* FTC_SFamilyClass;
-#define FTC_SFAMILY_CLASS( x ) ((FTC_SFamilyClass)(x))
+#define FTC_SFAMILY_CLASS( x ) ( (FTC_SFamilyClass)(x) )
#define FTC_CACHE_SFAMILY_CLASS( x ) \
FTC_SFAMILY_CLASS( FTC_CACHE_GCACHE_CLASS( x )->family_class )
diff --git a/thirdparty/freetype/src/cff/cff.c b/thirdparty/freetype/src/cff/cff.c
index c2ffea3d0d..1ac0beb06a 100644
--- a/thirdparty/freetype/src/cff/cff.c
+++ b/thirdparty/freetype/src/cff/cff.c
@@ -4,7 +4,7 @@
*
* FreeType OpenType driver component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffcmap.c b/thirdparty/freetype/src/cff/cffcmap.c
index ff1aae69ef..2d667a7248 100644
--- a/thirdparty/freetype/src/cff/cffcmap.c
+++ b/thirdparty/freetype/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -81,7 +81,7 @@
if ( char_code < 255 )
{
- FT_UInt code = (FT_UInt)(char_code + 1);
+ FT_UInt code = (FT_UInt)( char_code + 1 );
for (;;)
diff --git a/thirdparty/freetype/src/cff/cffcmap.h b/thirdparty/freetype/src/cff/cffcmap.h
index 221e255afb..2818d3c6fe 100644
--- a/thirdparty/freetype/src/cff/cffcmap.h
+++ b/thirdparty/freetype/src/cff/cffcmap.h
@@ -4,7 +4,7 @@
*
* CFF character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffdrivr.c b/thirdparty/freetype/src/cff/cffdrivr.c
index 59210f37c5..d945afdfe8 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.c
+++ b/thirdparty/freetype/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
*
* OpenType font driver implementation (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffdrivr.h b/thirdparty/freetype/src/cff/cffdrivr.h
index fce92bbb00..a312003be7 100644
--- a/thirdparty/freetype/src/cff/cffdrivr.h
+++ b/thirdparty/freetype/src/cff/cffdrivr.h
@@ -4,7 +4,7 @@
*
* High-level OpenType driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cfferrs.h b/thirdparty/freetype/src/cff/cfferrs.h
index b507ec8bb7..90d32897c7 100644
--- a/thirdparty/freetype/src/cff/cfferrs.h
+++ b/thirdparty/freetype/src/cff/cfferrs.h
@@ -4,7 +4,7 @@
*
* CFF error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffgload.c b/thirdparty/freetype/src/cff/cffgload.c
index 97e8f9c1c6..7586b886f1 100644
--- a/thirdparty/freetype/src/cff/cffgload.c
+++ b/thirdparty/freetype/src/cff/cffgload.c
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -29,6 +29,14 @@
#include "cfferrs.h"
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#define IS_DEFAULT_INSTANCE( _face ) \
+ ( !( FT_IS_NAMED_INSTANCE( _face ) || \
+ FT_IS_VARIATION( _face ) ) )
+#else
+#define IS_DEFAULT_INSTANCE( _face ) 1
+#endif
+
/**************************************************************************
*
@@ -67,7 +75,7 @@
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
- CFF_Font cff = (CFF_Font)(face->extra.data);
+ CFF_Font cff = (CFF_Font)( face->extra.data );
return cff_index_access_element( &cff->charstrings_index, glyph_index,
@@ -103,7 +111,7 @@
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
- CFF_Font cff = (CFF_Font)(face->extra.data);
+ CFF_Font cff = (CFF_Font)( face->extra.data );
cff_index_forget_element( &cff->charstrings_index, pointer );
@@ -255,8 +263,8 @@
if ( size->strike_index != 0xFFFFFFFFUL &&
- sfnt->load_eblc &&
- ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
+ IS_DEFAULT_INSTANCE( size->root.face ) )
{
TT_SBit_MetricsRec metrics;
@@ -346,6 +354,76 @@
if ( load_flags & FT_LOAD_SBITS_ONLY )
return FT_THROW( Invalid_Argument );
+#ifdef FT_CONFIG_OPTION_SVG
+ /* check for OT-SVG */
+ if ( ( load_flags & FT_LOAD_COLOR ) &&
+ ( (TT_Face)glyph->root.face )->svg )
+ {
+ /*
+ * We load the SVG document and try to grab the advances from the
+ * table. For the bearings we rely on the presetting hook to do that.
+ */
+
+ FT_Short dummy;
+ FT_UShort advanceX;
+ FT_UShort advanceY;
+ SFNT_Service sfnt;
+
+
+ if ( size && (size->root.metrics.x_ppem < 1 ||
+ size->root.metrics.y_ppem < 1 ) )
+ {
+ error = FT_THROW( Invalid_Size_Handle );
+ return error;
+ }
+
+ FT_TRACE3(( "Trying to load SVG glyph\n" ));
+
+ sfnt = (SFNT_Service)((TT_Face)glyph->root.face)->sfnt;
+ error = sfnt->load_svg_doc( (FT_GlyphSlot)glyph, glyph_index );
+ if ( !error )
+ {
+ FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+
+ glyph->root.format = FT_GLYPH_FORMAT_SVG;
+
+ /*
+ * If horizontal or vertical advances are not present in the table,
+ * this is a problem with the font since the standard requires them.
+ * However, we are graceful and calculate the values by ourselves
+ * for the vertical case.
+ */
+ sfnt->get_metrics( face,
+ FALSE,
+ glyph_index,
+ &dummy,
+ &advanceX );
+ sfnt->get_metrics( face,
+ TRUE,
+ glyph_index,
+ &dummy,
+ &advanceY );
+
+ advanceX =
+ (FT_UShort)FT_MulDiv( advanceX,
+ glyph->root.face->size->metrics.x_ppem,
+ glyph->root.face->units_per_EM );
+ advanceY =
+ (FT_UShort)FT_MulDiv( advanceY,
+ glyph->root.face->size->metrics.y_ppem,
+ glyph->root.face->units_per_EM );
+
+ glyph->root.metrics.horiAdvance = advanceX << 6;
+ glyph->root.metrics.vertAdvance = advanceY << 6;
+
+ return error;
+ }
+
+ FT_TRACE3(( "Failed to load SVG glyph\n" ));
+ }
+
+#endif /* FT_CONFIG_OPTION_SVG */
+
/* if we have a CID subfont, use its matrix (which has already */
/* been multiplied with the root matrix) */
diff --git a/thirdparty/freetype/src/cff/cffgload.h b/thirdparty/freetype/src/cff/cffgload.h
index d0d6a6fa08..33616b9684 100644
--- a/thirdparty/freetype/src/cff/cffgload.h
+++ b/thirdparty/freetype/src/cff/cffgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffload.c b/thirdparty/freetype/src/cff/cffload.c
index 3c3f6fe502..d6f8a1013d 100644
--- a/thirdparty/freetype/src/cff/cffload.c
+++ b/thirdparty/freetype/src/cff/cffload.c
@@ -4,7 +4,7 @@
*
* OpenType and CFF data/program tables loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffload.h b/thirdparty/freetype/src/cff/cffload.h
index 20f9296c4f..a3cc642b77 100644
--- a/thirdparty/freetype/src/cff/cffload.h
+++ b/thirdparty/freetype/src/cff/cffload.h
@@ -4,7 +4,7 @@
*
* OpenType & CFF data/program tables loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffobjs.c b/thirdparty/freetype/src/cff/cffobjs.c
index 3a4d47dbdd..fa42accb65 100644
--- a/thirdparty/freetype/src/cff/cffobjs.c
+++ b/thirdparty/freetype/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
*
* OpenType objects manager (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -411,9 +411,7 @@
FT_String* result;
- (void)FT_STRDUP( result, source );
-
- FT_UNUSED( error );
+ FT_MEM_STRDUP( result, source );
return result;
}
diff --git a/thirdparty/freetype/src/cff/cffobjs.h b/thirdparty/freetype/src/cff/cffobjs.h
index 149a8a2f0a..d48c1cded9 100644
--- a/thirdparty/freetype/src/cff/cffobjs.h
+++ b/thirdparty/freetype/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
*
* OpenType objects manager (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffparse.c b/thirdparty/freetype/src/cff/cffparse.c
index dde55e95c2..2536a21866 100644
--- a/thirdparty/freetype/src/cff/cffparse.c
+++ b/thirdparty/freetype/src/cff/cffparse.c
@@ -4,7 +4,7 @@
*
* CFF token stream parser (body)
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cffparse.h b/thirdparty/freetype/src/cff/cffparse.h
index a28ab52200..55b6fe6e7c 100644
--- a/thirdparty/freetype/src/cff/cffparse.h
+++ b/thirdparty/freetype/src/cff/cffparse.h
@@ -4,7 +4,7 @@
*
* CFF token stream parser (specification)
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cff/cfftoken.h b/thirdparty/freetype/src/cff/cfftoken.h
index eef30690c4..15237de9e5 100644
--- a/thirdparty/freetype/src/cff/cfftoken.h
+++ b/thirdparty/freetype/src/cff/cfftoken.h
@@ -4,7 +4,7 @@
*
* CFF token definitions (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/ciderrs.h b/thirdparty/freetype/src/cid/ciderrs.h
index 2d762d9e1d..d07da5a01d 100644
--- a/thirdparty/freetype/src/cid/ciderrs.h
+++ b/thirdparty/freetype/src/cid/ciderrs.h
@@ -4,7 +4,7 @@
*
* CID error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidgload.c b/thirdparty/freetype/src/cid/cidgload.c
index a46d063dfe..24d37d3295 100644
--- a/thirdparty/freetype/src/cid/cidgload.c
+++ b/thirdparty/freetype/src/cid/cidgload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 Glyph Loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidgload.h b/thirdparty/freetype/src/cid/cidgload.h
index 8b515efa01..c06bb29d3d 100644
--- a/thirdparty/freetype/src/cid/cidgload.h
+++ b/thirdparty/freetype/src/cid/cidgload.h
@@ -4,7 +4,7 @@
*
* OpenType Glyph Loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidload.c b/thirdparty/freetype/src/cid/cidload.c
index 496219de80..fe8fa1abff 100644
--- a/thirdparty/freetype/src/cid/cidload.c
+++ b/thirdparty/freetype/src/cid/cidload.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidload.h b/thirdparty/freetype/src/cid/cidload.h
index ee1d486505..90ced9280b 100644
--- a/thirdparty/freetype/src/cid/cidload.h
+++ b/thirdparty/freetype/src/cid/cidload.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 font loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidobjs.c b/thirdparty/freetype/src/cid/cidobjs.c
index e3c29c22f6..c39de6369c 100644
--- a/thirdparty/freetype/src/cid/cidobjs.c
+++ b/thirdparty/freetype/src/cid/cidobjs.c
@@ -4,7 +4,7 @@
*
* CID objects manager (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidobjs.h b/thirdparty/freetype/src/cid/cidobjs.h
index 32f59cbcce..fd76a1cba5 100644
--- a/thirdparty/freetype/src/cid/cidobjs.h
+++ b/thirdparty/freetype/src/cid/cidobjs.h
@@ -4,7 +4,7 @@
*
* CID objects manager (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidparse.c b/thirdparty/freetype/src/cid/cidparse.c
index 852c9b6b96..cfc820561f 100644
--- a/thirdparty/freetype/src/cid/cidparse.c
+++ b/thirdparty/freetype/src/cid/cidparse.c
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidparse.h b/thirdparty/freetype/src/cid/cidparse.h
index fbc437bc38..ba363f7803 100644
--- a/thirdparty/freetype/src/cid/cidparse.h
+++ b/thirdparty/freetype/src/cid/cidparse.h
@@ -4,7 +4,7 @@
*
* CID-keyed Type1 parser (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidriver.c b/thirdparty/freetype/src/cid/cidriver.c
index a0898dfa2f..a63c01064a 100644
--- a/thirdparty/freetype/src/cid/cidriver.c
+++ b/thirdparty/freetype/src/cid/cidriver.c
@@ -4,7 +4,7 @@
*
* CID driver interface (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidriver.h b/thirdparty/freetype/src/cid/cidriver.h
index 3ff5f78e11..5073b7a8eb 100644
--- a/thirdparty/freetype/src/cid/cidriver.h
+++ b/thirdparty/freetype/src/cid/cidriver.h
@@ -4,7 +4,7 @@
*
* High-level CID driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/cidtoken.h b/thirdparty/freetype/src/cid/cidtoken.h
index 84c8258014..7640137eac 100644
--- a/thirdparty/freetype/src/cid/cidtoken.h
+++ b/thirdparty/freetype/src/cid/cidtoken.h
@@ -4,7 +4,7 @@
*
* CID token definitions (specification only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/cid/type1cid.c b/thirdparty/freetype/src/cid/type1cid.c
index 5405ecffc8..b32c261376 100644
--- a/thirdparty/freetype/src/cid/type1cid.c
+++ b/thirdparty/freetype/src/cid/type1cid.c
@@ -4,7 +4,7 @@
*
* FreeType OpenType driver component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/gxvalid/README b/thirdparty/freetype/src/gxvalid/README
deleted file mode 100644
index 7fb0296282..0000000000
--- a/thirdparty/freetype/src/gxvalid/README
+++ /dev/null
@@ -1,532 +0,0 @@
-gxvalid: TrueType GX validator
-==============================
-
-
-1. What is this
----------------
-
- `gxvalid' is a module to validate TrueType GX tables: a collection of
- additional tables in TrueType font which are used by `QuickDraw GX
- Text', Apple Advanced Typography (AAT). In addition, gxvalid can
- validates `kern' tables which have been extended for AAT. Like the
- otvalid module, gxvalid uses FreeType 2's validator framework
- (ftvalid).
-
- You can link gxvalid with your program; before running your own layout
- engine, gxvalid validates a font file. As the result, you can remove
- error-checking code from the layout engine. It is also possible to
- use gxvalid as a stand-alone font validator; the `ftvalid' test
- program included in the ft2demo bundle calls gxvalid internally.
- A stand-alone font validator may be useful for font developers.
-
- This documents documents the following issues.
-
- - supported TrueType GX tables
- - fundamental validation limitations
- - permissive error handling of broken GX tables
- - `kern' table issue.
-
-
-2. Supported tables
--------------------
-
- The following GX tables are currently supported.
-
- bsln
- feat
- just
- kern(*)
- lcar
- mort
- morx
- opbd
- prop
- trak
-
- The following GX tables are currently unsupported.
-
- cvar
- fdsc
- fmtx
- fvar
- gvar
- Zapf
-
- The following GX tables won't be supported.
-
- acnt(**)
- hsty(***)
-
- The following undocumented tables in TrueType fonts designed for Apple
- platform aren't handled either.
-
- addg
- CVTM
- TPNM
- umif
-
-
- *) The `kern' validator handles both the classic and the new kern
- formats; the former is supported on both Microsoft and Apple
- platforms, while the latter is supported on Apple platforms.
-
- **) `acnt' tables are not supported by currently available Apple font
- tools.
-
- ***) There is one more Apple extension, `hsty', but it is for
- Newton-OS, not GX (Newton-OS is a platform by Apple, but it can
- use sfnt- housed bitmap fonts only). Therefore, it should be
- excluded from `Apple platform' in the context of TrueType.
- gxvalid ignores it as Apple font tools do so.
-
-
- We have checked 183 fonts bundled with MacOS 9.1, MacOS 9.2, MacOS
- 10.0, MacOS X 10.1, MSIE for MacOS, and AppleWorks 6.0. In addition,
- we have checked 67 Dynalab fonts (designed for MacOS) and 189 Ricoh
- fonts (designed for Windows and MacOS dual platforms). The number of
- fonts including TrueType GX tables are as follows.
-
- bsln: 76
- feat: 191
- just: 84
- kern: 59
- lcar: 4
- mort: 326
- morx: 19
- opbd: 4
- prop: 114
- trak: 16
-
- Dynalab and Ricoh fonts don't have GX tables except of `feat' and
- `mort'.
-
-
-3. Fundamental validation limitations
--------------------------------------
-
- TrueType GX provides layout information to libraries for font
- rasterizers and text layout. gxvalid can check whether the layout
- data in a font is conformant to the TrueType GX format specified by
- Apple. But gxvalid cannot check a how QuickDraw GX/AAT renderer uses
- the stored information.
-
- 3-1. Validation of State Machine activity
- -----------------------------------------
-
- QuickDraw GX/AAT uses a `State Machine' to provide `stateful' layout
- features, and TrueType GX stores the state transition diagram of
- this `State Machine' in a `StateTable' data structure. While the
- State Machine receives a series of glyph IDs, the State Machine
- starts with `start of text' state, walks around various states and
- generates various layout information to the renderer, and finally
- reaches the `end of text' state.
-
- gxvalid can check essential errors like:
-
- - possibility of state transitions to undefined states
- - existence of glyph IDs that the State Machine doesn't know how
- to handle
- - the State Machine cannot compute the layout information from
- given diagram
-
- These errors can be checked within finite steps, and without the
- State Machine itself, because these are `expression' errors of state
- transition diagram.
-
- There is no limitation about how long the State Machine walks
- around, so validation of the algorithm in the state transition
- diagram requires infinite steps, even if we had a State Machine in
- gxvalid. Therefore, the following errors and problems cannot be
- checked.
-
- - existence of states which the State Machine never transits to
- - the possibility that the State Machine never reaches `end of
- text'
- - the possibility of stack underflow/overflow in the State Machine
- (in ligature and contextual glyph substitutions, the State
- Machine can store 16 glyphs onto its stack)
-
- In addition, gxvalid doesn't check `temporary glyph IDs' used in the
- chained State Machines (in `mort' and `morx' tables). If a layout
- feature is implemented by a single State Machine, a glyph ID
- converted by the State Machine is passed to the glyph renderer, thus
- it should not point to an undefined glyph ID. But if a layout
- feature is implemented by chained State Machines, a component State
- Machine (if it is not the final one) is permitted to generate
- undefined glyph IDs for temporary use, because it is handled by next
- component State Machine and not by the glyph renderer. To validate
- such temporary glyph IDs, gxvalid must stack all undefined glyph IDs
- which can occur in the output of the previous State Machine and
- search them in the `ClassTable' structure of the current State
- Machine. It is too complex to list all possible glyph IDs from the
- StateTable, especially from a ligature substitution table.
-
- 3-2. Validation of relationship between multiple layout features
- ----------------------------------------------------------------
-
- gxvalid does not validate the relationship between multiple layout
- features at all.
-
- If multiple layout features are defined in TrueType GX tables,
- possible interactions, overrides, and conflicts between layout
- features are implicitly given in the font too. For example, there
- are several predefined spacing control features:
-
- - Text Spacing (Proportional/Monospace/Half-width/Normal)
- - Number Spacing (Monospaced-numbers/Proportional-numbers)
- - Kana Spacing (Full-width/Proportional)
- - Ideographic Spacing (Full-width/Proportional)
- - CJK Roman Spacing (Half-width/Proportional/Default-roman
- /Full-width-roman/Proportional)
-
- If all layout features are independently managed, we can activate
- inconsistent typographic rules like `Text Spacing=Monospace' and
- `Ideographic Spacing=Proportional' at the same time.
-
- The combinations of layout features is managed by a 32bit integer
- (one bit each for selector setting), so we can define relationships
- between up to 32 features, theoretically. But if one feature
- setting affects another feature setting, we need typographic
- priority rules to validate the relationship. Unfortunately, the
- TrueType GX format specification does not give such information even
- for predefined features.
-
-
-4. Permissive error handling of broken GX tables
-------------------------------------------------
-
- When Apple's font rendering system finds an inconsistency, like a
- specification violation or an unspecified value in a TrueType GX
- table, it does not always return error. In most cases, the rendering
- engine silently ignores such wrong values or even whole tables. In
- fact, MacOS is shipped with fonts including broken GX/AAT tables, but
- no harmful effects due to `officially broken' fonts are observed by
- end-users.
-
- gxvalid is designed to continue the validation process as long as
- possible. When gxvalid find wrong values, gxvalid warns it at least,
- and takes a fallback procedure if possible. The fallback procedure
- depends on the debug level.
-
- We used the following three tools to investigate Apple's error handling.
-
- - FontValidator (for MacOS 8.5 - 9.2) resource fork font
- - ftxvalidator (for MacOS X 10.1 -) dfont or naked-sfnt
- - ftxdumperfuser (for MacOS X 10.1 -) dfont or naked-sfnt
-
- However, all tests were done on a PowerPC based Macintosh; at present,
- we have not checked those tools on a m68k-based Macintosh.
-
- In total, we checked 183 fonts bundled to MacOS 9.1, MacOS 9.2, MacOS
- 10.0, MacOS X 10.1, MSIE for MacOS, and AppleWorks 6.0. These fonts
- are distributed officially, but many broken GX/AAT tables were found
- by Apple's font tools. In the following, we list typical violation of
- the GX specification, in fonts officially distributed with those Apple
- systems.
-
- 4-1. broken BinSrchHeader (19/183)
- ----------------------------------
-
- `BinSrchHeader' is a header of a data array for m68k platforms to
- access memory efficiently. Although there are only two independent
- parameters for real (`unitSize' and `nUnits'), BinSrchHeader has
- three additional parameters which can be calculated from `unitSize'
- and `nUnits', for fast setup. Apple font tools ignore them
- silently, so gxvalid warns if it finds and inconsistency, and always
- continues validation. The additional parameters are ignored
- regardless of the consistency.
-
- 19 fonts include such inconsistencies; all breaks are in the
- BinSrchHeader structure of the `kern' table.
-
- 4-2. too-short LookupTable (5/183)
- ----------------------------------
-
- LookupTable format 0 is a simple array to get a value from a given
- GID (glyph ID); the index of this array is a GID too. Therefore,
- the length of the array is expected to be same as the maximum GID
- value defined in the `maxp' table, but there are some fonts whose
- LookupTable format 0 is too short to cover all GIDs. FontValidator
- ignores this error silently, ftxvalidator and ftxdumperfuser both
- warn and continue. Similar problems are found in format 3 subtables
- of `kern'. gxvalid warns always and abort if the validation level
- is set to FT_VALIDATE_PARANOID.
-
- 5 fonts include too-short kern format 0 subtables.
- 1 font includes too-short kern format 3 subtable.
-
- 4-3. broken LookupTable format 2 (1/183)
- ----------------------------------------
-
- LookupTable format 2, subformat 4 covers the GID space by a
- collection of segments which are specified by `firstGlyph' and
- `lastGlyph'. Some fonts store `firstGlyph' and `lastGlyph' in
- reverse order, so the segment specification is broken. Apple font
- tools ignore this error silently; a broken segment is ignored as if
- it did not exist. gxvalid warns and normalize the segment at
- FT_VALIDATE_DEFAULT, or ignore the segment at FT_VALIDATE_TIGHT, or
- abort at FT_VALIDATE_PARANOID.
-
- 1 font includes broken LookupTable format 2, in the `just' table.
-
- *) It seems that all fonts manufactured by ITC for AppleWorks have
- this error.
-
- 4-4. bad bracketing in glyph property (14/183)
- ----------------------------------------------
-
- GX/AAT defines a `bracketing' property of the glyphs in the `prop'
- table, to control layout features of strings enclosed inside and
- outside of brackets. Some fonts give inappropriate bracket
- properties to glyphs. Apple font tools warn about this error;
- gxvalid warns too and aborts at FT_VALIDATE_PARANOID.
-
- 14 fonts include wrong bracket properties.
-
-
- 4-5. invalid feature number (117/183)
- -------------------------------------
-
- The GX/AAT extension can include 255 different layout features,
- but popular layout features are predefined (see
- https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html).
- Some fonts include feature numbers which are incompatible with the
- predefined feature registry.
-
- In our survey, there are 140 fonts including `feat' table.
-
- a) 67 fonts use a feature number which should not be used.
- b) 117 fonts set the wrong feature range (nSetting). This is mostly
- found in the `mort' and `morx' tables.
-
- Apple font tools give no warning, although they cannot recognize
- what the feature is. At FT_VALIDATE_DEFAULT, gxvalid warns but
- continues in both cases (a, b). At FT_VALIDATE_TIGHT, gxvalid warns
- and aborts for (a), but continues for (b). At FT_VALIDATE_PARANOID,
- gxvalid warns and aborts in both cases (a, b).
-
- 4-6. invalid prop version (10/183)
- ----------------------------------
-
- As most TrueType GX tables, the `prop' table must start with a 32bit
- version identifier: 0x00010000, 0x00020000 or 0x00030000. But some
- fonts store nonsense binary data instead. When Apple font tools
- find them, they abort the processing immediately, and the data which
- follows is unhandled. gxvalid does the same.
-
- 10 fonts include broken `prop' version.
-
- All of these fonts are classic TrueType fonts for the Japanese
- script, manufactured by Apple.
-
- 4-7. unknown resource name (2/183)
- ------------------------------------
-
- NOTE: THIS IS NOT A TRUETYPE GX ERROR.
-
- If a TrueType font is stored in the resource fork or in dfont
- format, the data must be tagged as `sfnt' in the resource fork index
- to invoke TrueType font handler for the data. But the TrueType font
- data in `Keyboard.dfont' is tagged as `kbd', and that in
- `LastResort.dfont' is tagged as `lst'. Apple font tools can detect
- that the data is in TrueType format and successfully validate them.
- Maybe this is possible because they are known to be dfont. The
- current implementation of the resource fork driver of FreeType
- cannot do that, thus gxvalid cannot validate them.
-
- 2 fonts use an unknown tag for the TrueType font resource.
-
-5. `kern' table issues
-----------------------
-
- In common terminology of TrueType, `kern' is classified as a basic and
- platform-independent table. But there are Apple extensions of `kern',
- and there is an extension which requires a GX state machine for
- contextual kerning. Therefore, gxvalid includes a special validator
- for `kern' tables. Unfortunately, there is no exact algorithm to
- check Apple's extension, so gxvalid includes a heuristic algorithm to
- find the proper validation routines for all possible data formats,
- including the data format for Microsoft. By calling
- classic_kern_validate() instead of gxv_validate(), you can specify the
- `kern' format explicitly. However, current FreeType2 uses Microsoft
- `kern' format only, others are ignored (and should be handled in a
- library one level higher than FreeType).
-
- 5-1. History
- ------------
-
- The original 16bit version of `kern' was designed by Apple in the
- pre-GX era, and it was also approved by Microsoft. Afterwards,
- Apple designed a new 32bit version of the `kern' table. According
- to the documentation, the difference between the 16bit and 32bit
- version is only the size of variables in the `kern' header. In the
- following, we call the original 16bit version as `classic', and
- 32bit version as `new'.
-
- 5-2. Versions and dialects which should be differentiated
- ---------------------------------------------------------
-
- The `kern' table consists of a table header and several subtables.
- The version number which identifies a `classic' or a `new' version
- is explicitly written in the table header, but there are
- undocumented differences between Microsoft's and Apple's formats.
- It is called a `dialect' in the following. There are three cases
- which should be handled: the new Apple-dialect, the classic
- Apple-dialect, and the classic Microsoft-dialect. An analysis of
- the formats and the auto detection algorithm of gxvalid is described
- in the following.
-
- 5-2-1. Version detection: classic and new kern
- ----------------------------------------------
-
- According to Apple TrueType specification, there are only two
- differences between the classic and the new:
-
- - The `kern' table header starts with the version number.
- The classic version starts with 0x0000 (16bit),
- the new version starts with 0x00010000 (32bit).
-
- - In the `kern' table header, the number of subtables follows
- the version number.
- In the classic version, it is stored as a 16bit value.
- In the new version, it is stored as a 32bit value.
-
- From Apple font tool's output (DumpKERN is also tested in addition
- to the three Apple font tools in above), there is another
- undocumented difference. In the new version, the subtable header
- includes a 16bit variable named `tupleIndex' which does not exist
- in the classic version.
-
- The new version can store all subtable formats (0, 1, 2, and 3),
- but the Apple TrueType specification does not mention the subtable
- formats available in the classic version.
-
- 5-2-2. Available subtable formats in classic version
- ----------------------------------------------------
-
- Although the Apple TrueType specification recommends to use the
- classic version in the case if the font is designed for both the
- Apple and Microsoft platforms, it does not document the available
- subtable formats in the classic version.
-
- According to the Microsoft TrueType specification, the subtable
- format assured for Windows and OS/2 support is only subtable
- format 0. The Microsoft TrueType specification also describes
- subtable format 2, but does not mention which platforms support
- it. Subtable formats 1, 3, and higher are documented as reserved
- for future use. Therefore, the classic version can store subtable
- formats 0 and 2, at least. `ttfdump.exe', a font tool provided by
- Microsoft, ignores the subtable format written in the subtable
- header, and parses the table as if all subtables are in format 0.
-
- `kern' subtable format 1 uses a StateTable, so it cannot be
- utilized without a GX State Machine. Therefore, it is reasonable
- to assume that format 1 (and 3) were introduced after Apple had
- introduced GX and moved to the new 32bit version.
-
- 5-2-3. Apple and Microsoft dialects
- -----------------------------------
-
- The `kern' subtable has a 16bit `coverage' field to describe
- kerning attributes, but bit interpretations by Apple and Microsoft
- are different: For example, Apple uses bits 0-7 to identify the
- subtable, while Microsoft uses bits 8-15.
-
- In addition, due to the output of DumpKERN and FontValidator,
- Apple's bit interpretations of coverage in classic and new version
- are incompatible also. In summary, there are three dialects:
- classic Apple dialect, classic Microsoft dialect, and new Apple
- dialect. The classic Microsoft dialect and the new Apple dialect
- are documented by each vendors' TrueType font specification, but
- the documentation for classic Apple dialect is not available.
-
- For example, in the new Apple dialect, bit 15 is documented as
- `set to 1 if the kerning is vertical'. On the other hand, in
- classic Microsoft dialect, bit 1 is documented as `set to 1 if the
- kerning is horizontal'. From the outputs of DumpKERN and
- FontValidator, classic Apple dialect recognizes 15 as `set to 1
- when the kerning is horizontal'. From the results of similar
- experiments, classic Apple dialect seems to be the Endian reverse
- of the classic Microsoft dialect.
-
- As a conclusion it must be noted that no font tool can identify
- classic Apple dialect or classic Microsoft dialect automatically.
-
- 5-2-4. gxvalid auto dialect detection algorithm
- -----------------------------------------------
-
- The first 16 bits of the `kern' table are enough to identify the
- version:
-
- - if the first 16 bits are 0x0000, the `kern' table is in
- classic Apple dialect or classic Microsoft dialect
- - if the first 16 bits are 0x0001, and next 16 bits are 0x0000,
- the kern table is in new Apple dialect.
-
- If the `kern' table is a classic one, the 16bit `coverage' field
- is checked next. Firstly, the coverage bits are decoded for the
- classic Apple dialect using the following bit masks (this is based
- on DumpKERN output):
-
- 0x8000: 1=horizontal, 0=vertical
- 0x4000: not used
- 0x2000: 1=cross-stream, 0=normal
- 0x1FF0: reserved
- 0x000F: subtable format
-
- If any of reserved bits are set or the subtable bits is
- interpreted as format 1 or 3, we take it as `impossible in classic
- Apple dialect' and retry, using the classic Microsoft dialect.
-
- The most popular coverage in new Apple-dialect: 0x8000,
- The most popular coverage in classic Apple-dialect: 0x0000,
- The most popular coverage in classic Microsoft dialect: 0x0001.
-
- 5-3. Tested fonts
- -----------------
-
- We checked 59 fonts bundled with MacOS and 38 fonts bundled with
- Windows, where all font include a `kern' table.
-
- - fonts bundled with MacOS
- * new Apple dialect
- format 0: 18
- format 2: 1
- format 3: 1
- * classic Apple dialect
- format 0: 14
- * classic Microsoft dialect
- format 0: 15
-
- - fonts bundled with Windows
- * classic Microsoft dialect
- format 0: 38
-
- It looks strange that classic Microsoft-dialect fonts are bundled to
- MacOS: they come from MSIE for MacOS, except of MarkerFelt.dfont.
-
-
- ACKNOWLEDGEMENT
- ---------------
-
- Some parts of gxvalid are derived from both the `gxlayout' module and
- the `otvalid' module. Development of gxlayout was supported by the
- Information-technology Promotion Agency(IPA), Japan.
-
- The detailed analysis of undefined glyph ID utilization in `mort' and
- `morx' tables is provided by George Williams.
-
-------------------------------------------------------------------------
-
-Copyright (C) 2004-2021 by
-suzuki toshiya, Masatake YAMATO, Red hat K.K.,
-David Turner, Robert Wilhelm, and Werner Lemberg.
-
-This file is part of the FreeType project, and may only be used,
-modified, and distributed under the terms of the FreeType project
-license, LICENSE.TXT. By continuing to use, modify, or distribute this
-file you indicate that you have read the license and understand and
-accept it fully.
-
-
---- end of README ---
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.c b/thirdparty/freetype/src/gxvalid/gxvalid.c
index 309d517443..9f380337c9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.c
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.c
@@ -4,7 +4,7 @@
*
* FreeType validator for TrueTypeGX/AAT tables (body only).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvalid.h b/thirdparty/freetype/src/gxvalid/gxvalid.h
index 2c41c28668..170fde3406 100644
--- a/thirdparty/freetype/src/gxvalid/gxvalid.h
+++ b/thirdparty/freetype/src/gxvalid/gxvalid.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT table validation (specification only).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvbsln.c b/thirdparty/freetype/src/gxvalid/gxvbsln.c
index af69cb51df..9784d18c5d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvbsln.c
+++ b/thirdparty/freetype/src/gxvalid/gxvbsln.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT bsln table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.c b/thirdparty/freetype/src/gxvalid/gxvcommn.c
index 18e42b0cd8..999cba4e4c 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.c
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common tables validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
@@ -1033,7 +1033,7 @@
GXV_NAME_ENTER( "StateArray" );
GXV_TRACE(( "parse %d bytes by stateSize=%d maxClassID=%d\n",
- (int)(*length_p), stateSize, (int)(maxClassID) ));
+ (int)( *length_p ), stateSize, (int)maxClassID ));
/*
* 2 states are predefined and must be described in StateArray:
@@ -1418,7 +1418,7 @@
GXV_NAME_ENTER( "XStateArray" );
GXV_TRACE(( "parse % 3d bytes by stateSize=% 3d maxClassID=% 3d\n",
- (int)(*length_p), (int)stateSize, (int)(maxClassID) ));
+ (int)( *length_p ), (int)stateSize, (int)maxClassID ));
/*
* 2 states are predefined and must be described:
diff --git a/thirdparty/freetype/src/gxvalid/gxvcommn.h b/thirdparty/freetype/src/gxvalid/gxvcommn.h
index b79b641142..794cf0a447 100644
--- a/thirdparty/freetype/src/gxvalid/gxvcommn.h
+++ b/thirdparty/freetype/src/gxvalid/gxvcommn.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common tables validation (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxverror.h b/thirdparty/freetype/src/gxvalid/gxverror.h
index d20d395680..8d2faac808 100644
--- a/thirdparty/freetype/src/gxvalid/gxverror.h
+++ b/thirdparty/freetype/src/gxvalid/gxverror.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT validation module error codes (specification only).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.c b/thirdparty/freetype/src/gxvalid/gxvfeat.c
index 0a8e2f201a..77200564ee 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT feat table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfeat.h b/thirdparty/freetype/src/gxvalid/gxvfeat.h
index f6d28fa71c..3deeb521dd 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfeat.h
+++ b/thirdparty/freetype/src/gxvalid/gxvfeat.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT feat table validation (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvfgen.c b/thirdparty/freetype/src/gxvalid/gxvfgen.c
index b47cd0f7ba..57f11a8412 100644
--- a/thirdparty/freetype/src/gxvalid/gxvfgen.c
+++ b/thirdparty/freetype/src/gxvalid/gxvfgen.c
@@ -5,7 +5,7 @@
* Generate feature registry data for gxv `feat' validator.
* This program is derived from gxfeatreg.c in gxlayout.
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Masatake YAMATO and Redhat K.K.
*
* This file may only be used,
diff --git a/thirdparty/freetype/src/gxvalid/gxvjust.c b/thirdparty/freetype/src/gxvalid/gxvjust.c
index ec289b8ebf..6af2c79c84 100644
--- a/thirdparty/freetype/src/gxvalid/gxvjust.c
+++ b/thirdparty/freetype/src/gxvalid/gxvjust.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT just table validation (body).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvkern.c b/thirdparty/freetype/src/gxvalid/gxvkern.c
index 542e8bc095..f0804e37b9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvkern.c
+++ b/thirdparty/freetype/src/gxvalid/gxvkern.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT kern table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvlcar.c b/thirdparty/freetype/src/gxvalid/gxvlcar.c
index 9db839ba8a..be6e491f9f 100644
--- a/thirdparty/freetype/src/gxvalid/gxvlcar.c
+++ b/thirdparty/freetype/src/gxvalid/gxvlcar.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT lcar table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.c b/thirdparty/freetype/src/gxvalid/gxvmod.c
index 1a11426ccb..8c505dd23f 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.c
@@ -4,7 +4,7 @@
*
* FreeType's TrueTypeGX/AAT validation module implementation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmod.h b/thirdparty/freetype/src/gxvalid/gxvmod.h
index 90e0c10a28..1758d4c86e 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmod.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmod.h
@@ -5,7 +5,7 @@
* FreeType's TrueTypeGX/AAT validation module implementation
* (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.c b/thirdparty/freetype/src/gxvalid/gxvmort.c
index d0db7f4d2d..01a77d6a5d 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT mort table validation (body).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort.h b/thirdparty/freetype/src/gxvalid/gxvmort.h
index de5ab4ef02..1a1d8961b5 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmort.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common definition for mort table (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort0.c b/thirdparty/freetype/src/gxvalid/gxvmort0.c
index 0c695aa4c7..fa6c7368f7 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort0.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type0 (Indic Script Rearrangement) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort1.c b/thirdparty/freetype/src/gxvalid/gxvmort1.c
index 0af22362f1..170acee2c7 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort1.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type1 (Contextual Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort2.c b/thirdparty/freetype/src/gxvalid/gxvmort2.c
index 73f418ea1e..faf446741b 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort2.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type2 (Ligature Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort4.c b/thirdparty/freetype/src/gxvalid/gxvmort4.c
index 1b0dd3edab..12555da82a 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort4.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type4 (Non-Contextual Glyph Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmort5.c b/thirdparty/freetype/src/gxvalid/gxvmort5.c
index cfbf31208c..48caac4347 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmort5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmort5.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT mort table validation
* body for type5 (Contextual Glyph Insertion) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.c b/thirdparty/freetype/src/gxvalid/gxvmorx.c
index babff51866..4b848b1e10 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT morx table validation (body).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx.h b/thirdparty/freetype/src/gxvalid/gxvmorx.h
index f155f18460..a849d573b3 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx.h
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx.h
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT common definition for morx table (specification).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx0.c b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
index e93cea9cca..7eb27d143e 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx0.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx0.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type0 (Indic Script Rearrangement) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx1.c b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
index d380f8d1ad..6ffbf151bb 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx1.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx1.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type1 (Contextual Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx2.c b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
index e7e008f069..eb79e9b408 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx2.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx2.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type2 (Ligature Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx4.c b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
index e632e8d42a..30c602cb8a 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx4.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx4.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for "morx" type4 (Non-Contextual Glyph Substitution) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvmorx5.c b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
index 5ad33976d7..afdef05a89 100644
--- a/thirdparty/freetype/src/gxvalid/gxvmorx5.c
+++ b/thirdparty/freetype/src/gxvalid/gxvmorx5.c
@@ -5,7 +5,7 @@
* TrueTypeGX/AAT morx table validation
* body for type5 (Contextual Glyph Insertion) subtable.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvopbd.c b/thirdparty/freetype/src/gxvalid/gxvopbd.c
index 7a2feab468..a6b04a4b17 100644
--- a/thirdparty/freetype/src/gxvalid/gxvopbd.c
+++ b/thirdparty/freetype/src/gxvalid/gxvopbd.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT opbd table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvprop.c b/thirdparty/freetype/src/gxvalid/gxvprop.c
index 98cd368845..bf1ed112fd 100644
--- a/thirdparty/freetype/src/gxvalid/gxvprop.c
+++ b/thirdparty/freetype/src/gxvalid/gxvprop.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT prop table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gxvalid/gxvtrak.c b/thirdparty/freetype/src/gxvalid/gxvtrak.c
index c1ed92872d..93ac3e76a9 100644
--- a/thirdparty/freetype/src/gxvalid/gxvtrak.c
+++ b/thirdparty/freetype/src/gxvalid/gxvtrak.c
@@ -4,7 +4,7 @@
*
* TrueTypeGX/AAT trak table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
diff --git a/thirdparty/freetype/src/gzip/adler32.c b/thirdparty/freetype/src/gzip/adler32.c
index c53f9dd125..aa032e1ddf 100644
--- a/thirdparty/freetype/src/gzip/adler32.c
+++ b/thirdparty/freetype/src/gzip/adler32.c
@@ -1,48 +1,192 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-2002 Mark Adler
+ * Copyright (C) 1995-2011, 2016 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
-#include "zlib.h"
+#include "zutil.h"
-#define BASE 65521L /* largest prime smaller than 65536 */
+#ifndef Z_FREETYPE
+local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
+#endif
+
+#define BASE 65521U /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
+/* use NO_DIVIDE if your processor does not do division in hardware --
+ try it both ways to see which is faster */
+#ifdef NO_DIVIDE
+/* note that this assumes BASE is 65521, where 65536 % 65521 == 15
+ (thank you to John Reiser for pointing this out) */
+# define CHOP(a) \
+ do { \
+ unsigned long tmp = a >> 16; \
+ a &= 0xffffUL; \
+ a += (tmp << 4) - tmp; \
+ } while (0)
+# define MOD28(a) \
+ do { \
+ CHOP(a); \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+# define MOD(a) \
+ do { \
+ CHOP(a); \
+ MOD28(a); \
+ } while (0)
+# define MOD63(a) \
+ do { /* this assumes a is not negative */ \
+ z_off64_t tmp = a >> 32; \
+ a &= 0xffffffffL; \
+ a += (tmp << 8) - (tmp << 5) + tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ tmp = a >> 16; \
+ a &= 0xffffL; \
+ a += (tmp << 4) - tmp; \
+ if (a >= BASE) a -= BASE; \
+ } while (0)
+#else
+# define MOD(a) a %= BASE
+# define MOD28(a) a %= BASE
+# define MOD63(a) a %= BASE
+#endif
+
/* ========================================================================= */
-ZEXPORT(uLong) adler32( /* adler, buf, len) */
+uLong ZEXPORT adler32_z(
uLong adler,
const Bytef *buf,
- uInt len )
+ z_size_t len)
{
- unsigned long s1 = adler & 0xffff;
- unsigned long s2 = (adler >> 16) & 0xffff;
- int k;
+ unsigned long sum2;
+ unsigned n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[0];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
- if (buf == Z_NULL) return 1L;
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf == Z_NULL)
+ return 1L;
- while (len > 0) {
- k = len < NMAX ? len : NMAX;
- len -= k;
- while (k >= 16) {
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ MOD28(sum2); /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX / 16; /* NMAX is divisible by 16 */
+ do {
+ DO16(buf); /* 16 sums unrolled */
+ buf += 16;
+ } while (--n);
+ MOD(adler);
+ MOD(sum2);
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
DO16(buf);
buf += 16;
- k -= 16;
}
- if (k != 0) do {
- s1 += *buf++;
- s2 += s1;
- } while (--k);
- s1 %= BASE;
- s2 %= BASE;
+ while (len--) {
+ adler += *buf++;
+ sum2 += adler;
+ }
+ MOD(adler);
+ MOD(sum2);
}
- return (s2 << 16) | s1;
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32(
+ uLong adler,
+ const Bytef *buf,
+ uInt len)
+{
+ return adler32_z(adler, buf, len);
+}
+
+#ifndef Z_FREETYPE
+
+/* ========================================================================= */
+local uLong adler32_combine_(
+ uLong adler1,
+ uLong adler2,
+ z_off64_t len2)
+{
+ unsigned long sum1;
+ unsigned long sum2;
+ unsigned rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffffUL;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ MOD63(len2); /* assumes len2 >= 0 */
+ rem = (unsigned)len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ MOD(sum2);
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
}
+
+/* ========================================================================= */
+uLong ZEXPORT adler32_combine(
+ uLong adler1,
+ uLong adler2,
+ z_off_t len2)
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+uLong ZEXPORT adler32_combine64(
+ uLong adler1,
+ uLong adler2,
+ z_off64_t len2)
+{
+ return adler32_combine_(adler1, adler2, len2);
+}
+
+#endif /* !Z_FREETYPE */
diff --git a/thirdparty/freetype/src/gzip/crc32.c b/thirdparty/freetype/src/gzip/crc32.c
new file mode 100644
index 0000000000..2ddc32d1fb
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/crc32.c
@@ -0,0 +1,1116 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
+ */
+
+/* @(#) $Id$ */
+
+/*
+ Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
+ protection on the static variables used to control the first-use generation
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ first call get_crc_table() to initialize the tables before allowing more than
+ one thread to use crc32().
+
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
+ */
+
+#ifdef MAKECRCH
+# include <stdio.h>
+# ifndef DYNAMIC_CRC_TABLE
+# define DYNAMIC_CRC_TABLE
+# endif /* !DYNAMIC_CRC_TABLE */
+#endif /* MAKECRCH */
+
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
+
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
+#endif
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
+#else
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
+
+/* Local functions. */
+local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
+local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
+
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(
+ z_word_t word)
+{
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
+
+#ifdef DYNAMIC_CRC_TABLE
+
+local z_crc_t FAR crc_table[256];
+local z_crc_t FAR x2n_table[32];
+local void make_crc_table OF((void));
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
+#endif
+#ifdef MAKECRCH
+ local void write_table OF((FILE *, const z_crc_t FAR *, int));
+ local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
+ local void write_table64 OF((FILE *, const z_word_t FAR *, int));
+#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+local void once OF((once_t *, void (*)(void)));
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include <stdatomic.h>
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set OF((int volatile *));
+local int test_and_set(
+ int volatile *flag)
+{
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
+/*
+ Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+ Polynomials over GF(2) are represented in binary, one bit per coefficient,
+ with the lowest powers in the most significant bit. Then adding polynomials
+ is just exclusive-or, and multiplying a polynomial by x is a right shift by
+ one. If we call the above polynomial p, and represent a byte as the
+ polynomial q, also with the lowest power in the most significant bit (so the
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
+ where a mod b means the remainder after dividing a by b.
+
+ This calculation is done using the shift-register method of multiplying and
+ taking the remainder. The register is initialized to zero, and for each
+ incoming bit, x^32 is added mod p to the register if the bit is a one (where
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
+local void make_crc_table()
+{
+ unsigned i, j, n;
+ z_crc_t p;
+
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
+ }
+
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
+#ifdef MAKECRCH
+ {
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
+ FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
+
+ out = fopen("crc32.h", "w");
+ if (out == NULL) return;
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
+ }
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
+ fclose(out);
+ }
+#endif /* MAKECRCH */
+}
+
+#ifdef MAKECRCH
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(
+ FILE *out,
+ const z_crc_t FAR *table,
+ int k)
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n]),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(
+ FILE *out,
+ const z_word_t FAR *table,
+ int k)
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(
+ FILE *out,
+ const z_word_t FAR *table,
+ int k)
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main()
+{
+ make_crc_table();
+ return 0;
+}
+
+#endif /* MAKECRCH */
+
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(ltl, big, n, w)
+ z_crc_t ltl[][256];
+ z_word_t big[][256];
+ int n;
+ int w;
+{
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
+#else /* !DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
+ */
+#include "crc32.h"
+#endif /* DYNAMIC_CRC_TABLE */
+
+/* ========================================================================
+ * Routines used for CRC calculation. Some are also required for the table
+ * generation above.
+ */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(
+ z_crc_t a,
+ z_crc_t b)
+{
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(
+ z_off64_t n,
+ unsigned k)
+{
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
+ */
+const z_crc_t FAR * ZEXPORT get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return (const z_crc_t FAR *)crc_table;
+}
+
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
+
+unsigned long ZEXPORT crc32_z(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ z_size_t len)
+{
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
+
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three
+ CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
+ }
+
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#else
+
+#ifdef W
+
+/*
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
+ */
+local z_crc_t crc_word(
+ z_word_t data)
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
+
+local z_word_t crc_word_big(
+ z_word_t data)
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32_z(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ z_size_t len)
+{
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
+
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
+
+#ifdef W
+
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
+
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianess at execution time. If the
+ compiler knows what the endianess will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
+ }
+
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
+}
+
+#endif
+
+/* ========================================================================= */
+unsigned long ZEXPORT crc32(
+ unsigned long crc,
+ const unsigned char FAR *buf,
+ uInt len)
+{
+ return crc32_z(crc, buf, len);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine64(
+ uLong crc1,
+ uLong crc2,
+ z_off64_t len2)
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ crc2;
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine(
+ uLong crc1,
+ uLong crc2,
+ z_off_t len2)
+{
+ return crc32_combine64(crc1, crc2, len2);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(
+ z_off64_t len2)
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
+}
+
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen(
+ z_off_t len2)
+{
+ return crc32_combine_gen64(len2);
+}
+
+/* ========================================================================= */
+uLong crc32_combine_op(
+ uLong crc1,
+ uLong crc2,
+ uLong op)
+{
+ return multmodp(op, crc1) ^ crc2;
+}
diff --git a/thirdparty/freetype/src/gzip/crc32.h b/thirdparty/freetype/src/gzip/crc32.h
new file mode 100644
index 0000000000..137df68d61
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/crc32.h
@@ -0,0 +1,9446 @@
+/* crc32.h -- tables for rapid CRC calculation
+ * Generated automatically by crc32.c
+ */
+
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
+#endif
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/thirdparty/freetype/src/gzip/ftgzip.c b/thirdparty/freetype/src/gzip/ftgzip.c
index 8f98a7d17b..34bbe4dafa 100644
--- a/thirdparty/freetype/src/gzip/ftgzip.c
+++ b/thirdparty/freetype/src/gzip/ftgzip.c
@@ -8,7 +8,7 @@
* parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -69,10 +69,21 @@
/* */
/* so that configuration with `FT_CONFIG_OPTION_SYSTEM_ZLIB' might */
/* include the wrong `zconf.h' file, leading to errors. */
-#include "zlib.h"
-#undef SLOW
-#define SLOW 1 /* we can't use asm-optimized sources here! */
+ /* `HAVE_HIDDEN` should be defined if */
+ /* */
+ /* __attribute__((visibility("hidden"))) */
+ /* */
+ /* is supported by the compiler, which prevents internal symbols from */
+ /* being exported by the library. */
+#if defined( __GNUC__ ) || defined( __clang__ )
+#define HAVE_HIDDEN 1
+#define ZEXPORT
+#define ZEXTERN static
+#endif
+
+#define Z_SOLO 1
+#define Z_FREETYPE 1
#if defined( _MSC_VER ) /* Visual C++ (and Intel C++) */
/* We disable the warning `conversion from XXX to YYY, */
@@ -83,24 +94,23 @@
#pragma warning( disable : 4244 )
#endif /* _MSC_VER */
- /* Urgh. `inflate_mask' must not be declared twice -- C++ doesn't like
- this. We temporarily disable it and load all necessary header files. */
-#define NO_INFLATE_MASK
-#include "zutil.h"
-#include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
-#undef NO_INFLATE_MASK
-
- /* infutil.c must be included before infcodes.c */
+#if defined( __GNUC__ )
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
#include "zutil.c"
-#include "inftrees.c"
-#include "infutil.c"
-#include "infcodes.c"
-#include "infblock.c"
+#include "inffast.c"
#include "inflate.c"
+#include "inftrees.c"
#include "adler32.c"
+#include "crc32.c"
+
+#if defined( __GNUC__ )
+#pragma GCC diagnostic pop
+#endif
#if defined( _MSC_VER )
#pragma warning( pop )
@@ -150,7 +160,7 @@
#if !defined( FT_CONFIG_OPTION_SYSTEM_ZLIB ) && !defined( USE_ZLIB_ZCALLOC )
- local voidpf
+ voidpf ZLIB_INTERNAL
zcalloc ( voidpf opaque,
unsigned items,
unsigned size )
@@ -158,7 +168,8 @@
return ft_gzip_alloc( opaque, items, size );
}
- local void
+
+ void ZLIB_INTERNAL
zcfree( voidpf opaque,
voidpf ptr )
{
@@ -751,16 +762,7 @@
stream.zfree = ft_gzip_free;
stream.opaque = memory;
- /* This is a temporary fix and will be removed once the internal
- * copy of zlib is updated to the newest version. The `|32' flag
- * is only supported in the new versions of zlib to enable gzip
- * encoded header.
- */
-#ifdef FT_CONFIG_OPTION_SYSTEM_ZLIB
err = inflateInit2( &stream, MAX_WBITS|32 );
-#else
- err = inflateInit2( &stream, MAX_WBITS );
-#endif
if ( err != Z_OK )
return FT_THROW( Invalid_Argument );
diff --git a/thirdparty/freetype/src/gzip/ftzconf.h b/thirdparty/freetype/src/gzip/ftzconf.h
index 3abf0ba03b..5e1d68a004 100644
--- a/thirdparty/freetype/src/gzip/ftzconf.h
+++ b/thirdparty/freetype/src/gzip/ftzconf.h
@@ -1,109 +1,255 @@
/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
-#ifndef _ZCONF_H
-#define _ZCONF_H
+#ifndef ZCONF_H
+#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
*/
-#ifdef Z_PREFIX
-# define deflateInit_ z_deflateInit_
-# define deflate z_deflate
-# define deflateEnd z_deflateEnd
-# define inflateInit_ z_inflateInit_
-# define inflate z_inflate
-# define inflateEnd z_inflateEnd
-# define deflateInit2_ z_deflateInit2_
-# define deflateSetDictionary z_deflateSetDictionary
-# define deflateCopy z_deflateCopy
-# define deflateReset z_deflateReset
-# define deflateParams z_deflateParams
-# define inflateInit2_ z_inflateInit2_
-# define inflateSetDictionary z_inflateSetDictionary
-# define inflateSync z_inflateSync
-# define inflateSyncPoint z_inflateSyncPoint
-# define inflateReset z_inflateReset
-# define compress z_compress
-# define compress2 z_compress2
-# define uncompress z_uncompress
-# define adler32 z_adler32
-# define crc32 z_crc32
-# define get_crc_table z_get_crc_table
-
-# define Byte z_Byte
-# define uInt z_uInt
-# define uLong z_uLong
-# define Bytef z_Bytef
-# define charf z_charf
-# define intf z_intf
-# define uIntf z_uIntf
-# define uLongf z_uLongf
-# define voidpf z_voidpf
-# define voidp z_voidp
-#endif
-
-#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
-# define WIN32
-#endif
-#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386)
-# ifndef __32BIT__
-# define __32BIT__
+#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
+# define Z_PREFIX_SET
+
+/* all linked symbols and init macros */
+# define _dist_code z__dist_code
+# define _length_code z__length_code
+# define _tr_align z__tr_align
+# define _tr_flush_bits z__tr_flush_bits
+# define _tr_flush_block z__tr_flush_block
+# define _tr_init z__tr_init
+# define _tr_stored_block z__tr_stored_block
+# define _tr_tally z__tr_tally
+# define adler32 z_adler32
+# define adler32_combine z_adler32_combine
+# define adler32_combine64 z_adler32_combine64
+# define adler32_z z_adler32_z
+# ifndef Z_SOLO
+# define compress z_compress
+# define compress2 z_compress2
+# define compressBound z_compressBound
+# endif
+# define crc32 z_crc32
+# define crc32_combine z_crc32_combine
+# define crc32_combine64 z_crc32_combine64
+# define crc32_z z_crc32_z
+# define deflate z_deflate
+# define deflateBound z_deflateBound
+# define deflateCopy z_deflateCopy
+# define deflateEnd z_deflateEnd
+# define deflateGetDictionary z_deflateGetDictionary
+# define deflateInit z_deflateInit
+# define deflateInit2 z_deflateInit2
+# define deflateInit2_ z_deflateInit2_
+# define deflateInit_ z_deflateInit_
+# define deflateParams z_deflateParams
+# define deflatePending z_deflatePending
+# define deflatePrime z_deflatePrime
+# define deflateReset z_deflateReset
+# define deflateResetKeep z_deflateResetKeep
+# define deflateSetDictionary z_deflateSetDictionary
+# define deflateSetHeader z_deflateSetHeader
+# define deflateTune z_deflateTune
+# define deflate_copyright z_deflate_copyright
+# define get_crc_table z_get_crc_table
+# ifndef Z_SOLO
+# define gz_error z_gz_error
+# define gz_intmax z_gz_intmax
+# define gz_strwinerror z_gz_strwinerror
+# define gzbuffer z_gzbuffer
+# define gzclearerr z_gzclearerr
+# define gzclose z_gzclose
+# define gzclose_r z_gzclose_r
+# define gzclose_w z_gzclose_w
+# define gzdirect z_gzdirect
+# define gzdopen z_gzdopen
+# define gzeof z_gzeof
+# define gzerror z_gzerror
+# define gzflush z_gzflush
+# define gzfread z_gzfread
+# define gzfwrite z_gzfwrite
+# define gzgetc z_gzgetc
+# define gzgetc_ z_gzgetc_
+# define gzgets z_gzgets
+# define gzoffset z_gzoffset
+# define gzoffset64 z_gzoffset64
+# define gzopen z_gzopen
+# define gzopen64 z_gzopen64
+# ifdef _WIN32
+# define gzopen_w z_gzopen_w
+# endif
+# define gzprintf z_gzprintf
+# define gzputc z_gzputc
+# define gzputs z_gzputs
+# define gzread z_gzread
+# define gzrewind z_gzrewind
+# define gzseek z_gzseek
+# define gzseek64 z_gzseek64
+# define gzsetparams z_gzsetparams
+# define gztell z_gztell
+# define gztell64 z_gztell64
+# define gzungetc z_gzungetc
+# define gzvprintf z_gzvprintf
+# define gzwrite z_gzwrite
+# endif
+# define inflate z_inflate
+# define inflateBack z_inflateBack
+# define inflateBackEnd z_inflateBackEnd
+# define inflateBackInit z_inflateBackInit
+# define inflateBackInit_ z_inflateBackInit_
+# define inflateCodesUsed z_inflateCodesUsed
+# define inflateCopy z_inflateCopy
+# define inflateEnd z_inflateEnd
+# define inflateGetDictionary z_inflateGetDictionary
+# define inflateGetHeader z_inflateGetHeader
+# define inflateInit z_inflateInit
+# define inflateInit2 z_inflateInit2
+# define inflateInit2_ z_inflateInit2_
+# define inflateInit_ z_inflateInit_
+# define inflateMark z_inflateMark
+# define inflatePrime z_inflatePrime
+# define inflateReset z_inflateReset
+# define inflateReset2 z_inflateReset2
+# define inflateResetKeep z_inflateResetKeep
+# define inflateSetDictionary z_inflateSetDictionary
+# define inflateSync z_inflateSync
+# define inflateSyncPoint z_inflateSyncPoint
+# define inflateUndermine z_inflateUndermine
+# define inflateValidate z_inflateValidate
+# define inflate_copyright z_inflate_copyright
+# define inflate_fast z_inflate_fast
+# define inflate_table z_inflate_table
+# ifndef Z_SOLO
+# define uncompress z_uncompress
+# define uncompress2 z_uncompress2
+# endif
+# define zError z_zError
+# ifndef Z_SOLO
+# define zcalloc z_zcalloc
+# define zcfree z_zcfree
+# endif
+# define zlibCompileFlags z_zlibCompileFlags
+# define zlibVersion z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+# define Byte z_Byte
+# define Bytef z_Bytef
+# define alloc_func z_alloc_func
+# define charf z_charf
+# define free_func z_free_func
+# ifndef Z_SOLO
+# define gzFile z_gzFile
# endif
+# define gz_header z_gz_header
+# define gz_headerp z_gz_headerp
+# define in_func z_in_func
+# define intf z_intf
+# define out_func z_out_func
+# define uInt z_uInt
+# define uIntf z_uIntf
+# define uLong z_uLong
+# define uLongf z_uLongf
+# define voidp z_voidp
+# define voidpc z_voidpc
+# define voidpf z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+# define gz_header_s z_gz_header_s
+# define internal_state z_internal_state
+
#endif
+
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
-
-/* WinCE doesn't have errno.h */
-#ifdef _WIN32_WCE
-# define NO_ERRNO_H
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+# define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+# define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+# ifndef WIN32
+# define WIN32
+# endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+# ifndef SYS16BIT
+# define SYS16BIT
+# endif
+# endif
#endif
-
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
-#if defined(MSDOS) && !defined(__32BIT__)
+#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
-#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC)
-# define STDC
-#endif
-#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__)
+#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
+# if __STDC_VERSION__ >= 199901L
+# ifndef STDC99
+# define STDC99
+# endif
+# endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+# define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+# define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
+# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
-# define const
+# define const /* note: need a more gentle solution here */
# endif
#endif
-/* Some Mac compilers merge all .h files incorrectly: */
-#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__)
-# define NO_DUMMY_DECL
-#endif
-
-/* Old Borland C and LCC incorrectly complains about missing returns: */
-#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500)
-# define NEED_DUMMY_RETURN
+#if defined(ZLIB_CONST) && !defined(z_const)
+# define z_const const
+#else
+# define z_const
#endif
-#if defined(__LCC__)
-# define NEED_DUMMY_RETURN
+#ifdef Z_SOLO
+ typedef unsigned long z_size_t;
+#else
+# define z_longlong long long
+# if defined(NO_SIZE_T)
+ typedef unsigned NO_SIZE_T z_size_t;
+# elif defined(STDC)
+# include <stddef.h>
+ typedef size_t z_size_t;
+# else
+ typedef unsigned long z_size_t;
+# endif
+# undef z_longlong
#endif
/* Maximum value for memLevel in deflateInit2 */
@@ -133,7 +279,7 @@
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ that is, 32K for windowBits=15 (default value) plus about 7 kilobytes
for small objects.
*/
@@ -147,75 +293,101 @@
# endif
#endif
+#ifndef Z_ARG /* function prototypes for stdarg */
+# if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# define Z_ARG(args) args
+# else
+# define Z_ARG(args) ()
+# endif
+#endif
+
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
-#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__)
- /* MSC small or medium model */
-# define SMALL_MEDIUM
-# ifdef _MSC_VER
-# define FAR _far
-# else
-# define FAR far
+#ifdef SYS16BIT
+# if defined(M_I86SM) || defined(M_I86MM)
+ /* MSC small or medium model */
+# define SMALL_MEDIUM
+# ifdef _MSC_VER
+# define FAR _far
+# else
+# define FAR far
+# endif
# endif
-#endif
-#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__))
-# ifndef __32BIT__
+# if (defined(__SMALL__) || defined(__MEDIUM__))
+ /* Turbo C small or medium model */
# define SMALL_MEDIUM
-# define FAR _far
+# ifdef __BORLANDC__
+# define FAR _far
+# else
+# define FAR far
+# endif
# endif
#endif
-/* Compile with -DZLIB_DLL for Windows DLL support */
-#if defined(ZLIB_DLL)
-# if defined(_WINDOWS) || defined(WINDOWS)
+#if defined(WINDOWS) || defined(WIN32)
+ /* If building or using zlib as a DLL, define ZLIB_DLL.
+ * This is not mandatory, but it offers a little performance increase.
+ */
+# ifdef ZLIB_DLL
+# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+# ifdef ZLIB_INTERNAL
+# define ZEXTERN extern __declspec(dllexport)
+# else
+# define ZEXTERN extern __declspec(dllimport)
+# endif
+# endif
+# endif /* ZLIB_DLL */
+ /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+ * define ZLIB_WINAPI.
+ * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+ */
+# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
-# define ZEXPORT(x) x WINAPI
+ /* No need for _export, use ZLIB.DEF instead. */
+ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+# define ZEXPORT WINAPI
# ifdef WIN32
-# define ZEXPORTVA(x) x WINAPIV
+# define ZEXPORTVA WINAPIV
# else
-# define ZEXPORTVA(x) x FAR _cdecl _export
+# define ZEXPORTVA FAR CDECL
# endif
# endif
-# if defined (__BORLANDC__)
-# if (__BORLANDC__ >= 0x0500) && defined (WIN32)
-# include <windows.h>
-# define ZEXPORT(x) x __declspec(dllexport) WINAPI
-# define ZEXPORTRVA(x) x __declspec(dllexport) WINAPIV
+#endif
+
+#if defined (__BEOS__)
+# ifdef ZLIB_DLL
+# ifdef ZLIB_INTERNAL
+# define ZEXPORT __declspec(dllexport)
+# define ZEXPORTVA __declspec(dllexport)
# else
-# if defined (_Windows) && defined (__DLL__)
-# define ZEXPORT(x) x _export
-# define ZEXPORTVA(x) x _export
-# endif
+# define ZEXPORT __declspec(dllimport)
+# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
-
+#ifndef ZEXTERN
+# define ZEXTERN extern
+#endif
#ifndef ZEXPORT
-# define ZEXPORT(x) static x
+# define ZEXPORT
#endif
#ifndef ZEXPORTVA
-# define ZEXPORTVA(x) static x
-#endif
-#ifndef ZEXTERN
-# define ZEXTERN(x) static x
-#endif
-#ifndef ZEXTERNDEF
-# define ZEXTERNDEF(x) static x
+# define ZEXPORTVA
#endif
#ifndef FAR
-# define FAR
+# define FAR
#endif
-#if !defined(MACOS) && !defined(TARGET_OS_MAC)
+#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
@@ -233,52 +405,130 @@ typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
- typedef void FAR *voidpf;
- typedef void *voidp;
+ typedef void const *voidpc;
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte const *voidpc;
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (UINT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned
+# elif (ULONG_MAX == 0xffffffffUL)
+# define Z_U4 unsigned long
+# elif (USHRT_MAX == 0xffffffffUL)
+# define Z_U4 unsigned short
+# endif
+#endif
+
+#ifdef Z_U4
+ typedef Z_U4 z_crc_t;
#else
- typedef Byte FAR *voidpf;
- typedef Byte *voidp;
+ typedef unsigned long z_crc_t;
+#endif
+
+#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_UNISTD_H
#endif
-#ifdef HAVE_UNISTD_H
-# include <sys/types.h> /* for off_t */
-# include <unistd.h> /* for SEEK_* and off_t */
-# define z_off_t off_t
+#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */
+# define Z_HAVE_STDARG_H
#endif
-#ifndef SEEK_SET
+
+#ifdef STDC
+# ifndef Z_SOLO
+# include <sys/types.h> /* for off_t */
+# endif
+#endif
+
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+# include <stdarg.h> /* for va_list */
+# endif
+#endif
+
+#ifdef _WIN32
+# ifndef Z_SOLO
+# include <stddef.h> /* for wchar_t */
+# endif
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+# undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+# define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+# ifdef VMS
+# include <unixio.h> /* for off_t */
+# endif
+# ifndef z_off_t
+# define z_off_t off_t
+# endif
+# endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+# define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+# define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+# define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
+
#ifndef z_off_t
-# define z_off_t long
+# define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+# define z_off64_t off64_t
+#else
+# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+# define z_off64_t __int64
+# else
+# define z_off64_t z_off_t
+# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
-# pragma map(deflateInit_,"DEIN")
-# pragma map(deflateInit2_,"DEIN2")
-# pragma map(deflateEnd,"DEEND")
-# pragma map(inflateInit_,"ININ")
-# pragma map(inflateInit2_,"ININ2")
-# pragma map(inflateEnd,"INEND")
-# pragma map(inflateSync,"INSY")
-# pragma map(inflateSetDictionary,"INSEDI")
-# pragma map(inflate_blocks,"INBL")
-# pragma map(inflate_blocks_new,"INBLNE")
-# pragma map(inflate_blocks_free,"INBLFR")
-# pragma map(inflate_blocks_reset,"INBLRE")
-# pragma map(inflate_codes_free,"INCOFR")
-# pragma map(inflate_codes,"INCO")
-# pragma map(inflate_fast,"INFA")
-# pragma map(inflate_flush,"INFLU")
-# pragma map(inflate_mask,"INMA")
-# pragma map(inflate_set_dictionary,"INSEDI2")
-# pragma map(inflate_copyright,"INCOPY")
-# pragma map(inflate_trees_bits,"INTRBI")
-# pragma map(inflate_trees_dynamic,"INTRDY")
-# pragma map(inflate_trees_fixed,"INTRFI")
-# pragma map(inflate_trees_free,"INTRFR")
-#endif
-
-#endif /* _ZCONF_H */
+ #pragma map(deflateInit_,"DEIN")
+ #pragma map(deflateInit2_,"DEIN2")
+ #pragma map(deflateEnd,"DEEND")
+ #pragma map(deflateBound,"DEBND")
+ #pragma map(inflateInit_,"ININ")
+ #pragma map(inflateInit2_,"ININ2")
+ #pragma map(inflateEnd,"INEND")
+ #pragma map(inflateSync,"INSY")
+ #pragma map(inflateSetDictionary,"INSEDI")
+ #pragma map(compressBound,"CMBND")
+ #pragma map(inflate_table,"INTABL")
+ #pragma map(inflate_fast,"INFA")
+ #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/thirdparty/freetype/src/gzip/gzguts.h b/thirdparty/freetype/src/gzip/gzguts.h
new file mode 100644
index 0000000000..4f09a52a7a
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/gzguts.h
@@ -0,0 +1,219 @@
+/* gzguts.h -- zlib internal header definitions for gz* operations
+ * Copyright (C) 2004-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifdef _LARGEFILE64_SOURCE
+# ifndef _LARGEFILE_SOURCE
+# define _LARGEFILE_SOURCE 1
+# endif
+# ifdef _FILE_OFFSET_BITS
+# undef _FILE_OFFSET_BITS
+# endif
+#endif
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
+
+#include <stdio.h>
+#include "zlib.h"
+#ifdef STDC
+# include <string.h>
+# include <stdlib.h>
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_SOURCE
+# define _POSIX_SOURCE
+#endif
+#include <fcntl.h>
+
+#ifdef _WIN32
+# include <stddef.h>
+#endif
+
+#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32)
+# include <io.h>
+#endif
+
+#if defined(_WIN32)
+# define WIDECHAR
+#endif
+
+#ifdef WINAPI_FAMILY
+# define open _open
+# define read _read
+# define write _write
+# define close _close
+#endif
+
+#ifdef NO_DEFLATE /* for compatibility with old definition */
+# define NO_GZCOMPRESS
+#endif
+
+#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(__CYGWIN__)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#if defined(MSDOS) && defined(__BORLANDC__) && (BORLANDC > 0x410)
+# ifndef HAVE_VSNPRINTF
+# define HAVE_VSNPRINTF
+# endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+# ifdef MSDOS
+/* vsnprintf may exist on some MS-DOS compilers (DJGPP?),
+ but for now we just assume it doesn't. */
+# define NO_vsnprintf
+# endif
+# ifdef __TURBOC__
+# define NO_vsnprintf
+# endif
+# ifdef WIN32
+/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
+# if !defined(vsnprintf) && !defined(NO_vsnprintf)
+# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
+# define vsnprintf _vsnprintf
+# endif
+# endif
+# endif
+# ifdef __SASC
+# define NO_vsnprintf
+# endif
+# ifdef VMS
+# define NO_vsnprintf
+# endif
+# ifdef __OS400__
+# define NO_vsnprintf
+# endif
+# ifdef __MVS__
+# define NO_vsnprintf
+# endif
+#endif
+
+/* unlike snprintf (which is required in C99), _snprintf does not guarantee
+ null termination of the result -- however this is only used in gzlib.c where
+ the result is assured to fit in the space provided */
+#if defined(_MSC_VER) && _MSC_VER < 1900
+# define snprintf _snprintf
+#endif
+
+#ifndef local
+# define local static
+#endif
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
+
+/* gz* functions always use library allocation functions */
+#ifndef STDC
+ extern voidp malloc OF((uInt size));
+ extern void free OF((voidpf ptr));
+#endif
+
+/* get errno and strerror definition */
+#if defined UNDER_CE
+# include <windows.h>
+# define zstrerror() gz_strwinerror((DWORD)GetLastError())
+#else
+# ifndef NO_STRERROR
+# include <errno.h>
+# define zstrerror() strerror(errno)
+# else
+# define zstrerror() "stdio error (consult errno)"
+# endif
+#endif
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+#endif
+
+/* default memLevel */
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+
+/* default i/o buffer size -- double this for output when reading (this and
+ twice this must be able to fit in an unsigned type) */
+#define GZBUFSIZE 8192
+
+/* gzip modes, also provide a little integrity check on the passed structure */
+#define GZ_NONE 0
+#define GZ_READ 7247
+#define GZ_WRITE 31153
+#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
+
+/* values for gz_state how */
+#define LOOK 0 /* look for a gzip header */
+#define COPY__ 1 /* copy input directly */
+#define GZIP 2 /* decompress a gzip stream */
+
+/* internal gzip file state data structure */
+typedef struct {
+ /* exposed contents for gzgetc() macro */
+ struct gzFile_s x; /* "x" for exposed */
+ /* x.have: number of bytes available at x.next */
+ /* x.next: next output data to deliver or write */
+ /* x.pos: current position in uncompressed data */
+ /* used for both reading and writing */
+ int mode; /* see gzip modes above */
+ int fd; /* file descriptor */
+ char *path; /* path or fd for error messages */
+ unsigned size; /* buffer size, zero if not allocated yet */
+ unsigned want; /* requested buffer size, default is GZBUFSIZE */
+ unsigned char *in; /* input buffer (double-sized when writing) */
+ unsigned char *out; /* output buffer (double-sized when reading) */
+ int direct; /* 0 if processing gzip, 1 if transparent */
+ /* just for reading */
+ int how; /* 0: get header, 1: copy, 2: decompress */
+ z_off64_t start; /* where the gzip data started, for rewinding */
+ int eof; /* true if end of input file reached */
+ int past; /* true if read requested past end */
+ /* just for writing */
+ int level; /* compression level */
+ int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
+ /* seek request */
+ z_off64_t skip; /* amount to skip (already rewound if backwards) */
+ int seek; /* true if seek request pending */
+ /* error information */
+ int err; /* error code */
+ char *msg; /* error message */
+ /* zlib inflate or deflate stream */
+ z_stream strm; /* stream structure in-place (not a pointer) */
+} gz_state;
+typedef gz_state FAR *gz_statep;
+
+/* shared functions */
+void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
+#if defined UNDER_CE
+char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
+#endif
+
+/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
+ value -- needed when comparing unsigned to z_off64_t, which is signed
+ (possible z_off64_t types off_t, off64_t, and long are all signed) */
+#ifdef INT_MAX
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
+#else
+unsigned ZLIB_INTERNAL gz_intmax OF((void));
+# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
+#endif
diff --git a/thirdparty/freetype/src/gzip/infback.c b/thirdparty/freetype/src/gzip/infback.c
new file mode 100644
index 0000000000..5fb8c67941
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/infback.c
@@ -0,0 +1,641 @@
+/* infback.c -- inflate using a call-back interface
+ * Copyright (C) 1995-2022 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ This code is largely copied from inflate.c. Normally either infback.o or
+ inflate.o would be linked into an application--not both. The interface
+ with inffast.c is retained so that optimized assembler-coded versions of
+ inflate_fast() can be used with either inflate.c or infback.c.
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+/* function prototypes */
+local void fixedtables OF((struct inflate_state FAR *state));
+
+/*
+ strm provides memory allocation functions in zalloc and zfree, or
+ Z_NULL to use the library memory allocation functions.
+
+ windowBits is in the range 8..15, and window is a user-supplied
+ window and output buffer that is 2**windowBits bytes.
+ */
+int ZEXPORT inflateBackInit_(
+ z_streamp strm,
+ int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size)
+{
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL || window == Z_NULL ||
+ windowBits < 8 || windowBits > 15)
+ return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)ZALLOC(strm, 1,
+ sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->dmax = 32768U;
+ state->wbits = (uInt)windowBits;
+ state->wsize = 1U << windowBits;
+ state->window = window;
+ state->wnext = 0;
+ state->whave = 0;
+ return Z_OK;
+}
+
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(
+ struct inflate_state FAR *state)
+{
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+/* Macros for inflateBack(): */
+
+/* Load returned state from inflate_fast() */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Set state from registers for inflate_fast() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Assure that some input is available. If input is requested, but denied,
+ then return a Z_BUF_ERROR from inflateBack(). */
+#define PULL() \
+ do { \
+ if (have == 0) { \
+ have = in(in_desc, &next); \
+ if (have == 0) { \
+ next = Z_NULL; \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflateBack()
+ with an error if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ PULL(); \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflateBack() with
+ an error. */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/* Assure that some output space is available, by writing out the window
+ if it's full. If the write fails, return from inflateBack() with a
+ Z_BUF_ERROR. */
+#define ROOM() \
+ do { \
+ if (left == 0) { \
+ put = state->window; \
+ left = state->wsize; \
+ state->whave = left; \
+ if (out(out_desc, put, left)) { \
+ ret = Z_BUF_ERROR; \
+ goto inf_leave; \
+ } \
+ } \
+ } while (0)
+
+/*
+ strm provides the memory allocation functions and window buffer on input,
+ and provides information on the unused input on return. For Z_DATA_ERROR
+ returns, strm will also provide an error message.
+
+ in() and out() are the call-back input and output functions. When
+ inflateBack() needs more input, it calls in(). When inflateBack() has
+ filled the window with output, or when it completes with data in the
+ window, it calls out() to write out the data. The application must not
+ change the provided input until in() is called again or inflateBack()
+ returns. The application must not change the window/output buffer until
+ inflateBack() returns.
+
+ in() and out() are called with a descriptor parameter provided in the
+ inflateBack() call. This parameter can be a structure that provides the
+ information required to do the read or write, as well as accumulated
+ information on the input and output such as totals and check values.
+
+ in() should return zero on failure. out() should return non-zero on
+ failure. If either in() or out() fails, than inflateBack() returns a
+ Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
+ was in() or out() that caused in the error. Otherwise, inflateBack()
+ returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
+ error, or Z_MEM_ERROR if it could not allocate memory for the state.
+ inflateBack() can also return Z_STREAM_ERROR if the input parameters
+ are not correct, i.e. strm is Z_NULL or the state was not initialized.
+ */
+int ZEXPORT inflateBack(
+ z_streamp strm,
+ in_func in,
+ void FAR *in_desc,
+ out_func out,
+ void FAR *out_desc)
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ /* Check that the strm exists and that the state was initialized */
+ if (strm == Z_NULL || strm->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* Reset the state */
+ strm->msg = Z_NULL;
+ state->mode = TYPE;
+ state->last = 0;
+ state->whave = 0;
+ next = strm->next_in;
+ have = next != Z_NULL ? strm->avail_in : 0;
+ hold = 0;
+ bits = 0;
+ put = state->window;
+ left = state->wsize;
+
+ /* Inflate until end of block marked as last */
+ for (;;)
+ switch (state->mode) {
+ case TYPE:
+ /* determine and dispatch block type */
+ if (state->last) {
+ BYTEBITS();
+ state->mode = DONE;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN; /* decode codes */
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+
+ case STORED:
+ /* get and verify stored block length */
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+
+ /* copy stored block from input to output */
+ while (state->length != 0) {
+ copy = state->length;
+ PULL();
+ ROOM();
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+
+ case TABLE:
+ /* get dynamic table entries descriptor */
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+
+ /* get code length code lengths (not a typo) */
+ state->have = 0;
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+
+ /* get length and distance code code lengths */
+ state->have = 0;
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = (unsigned)(state->lens[state->have - 1]);
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (code const FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (code const FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN;
+ /* fallthrough */
+
+ case LEN:
+ /* use inflate_fast() if we have enough input and output */
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ if (state->whave < state->wsize)
+ state->whave = state->wsize - left;
+ inflate_fast(strm, state->wsize);
+ LOAD();
+ break;
+ }
+
+ /* get a literal, length, or end-of-block code */
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ state->length = (unsigned)here.val;
+
+ /* process literal */
+ if (here.op == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ ROOM();
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ }
+
+ /* process end of block */
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+
+ /* invalid code */
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+
+ /* length code -- get extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+
+ /* get distance code */
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ }
+ DROPBITS(here.bits);
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+
+ /* get distance extra bits, if any */
+ state->extra = (unsigned)(here.op) & 15;
+ if (state->extra != 0) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ }
+ if (state->offset > state->wsize - (state->whave < state->wsize ?
+ left : 0)) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+
+ /* copy match from window to output */
+ do {
+ ROOM();
+ copy = state->wsize - state->offset;
+ if (copy < left) {
+ from = put + copy;
+ copy = left - copy;
+ }
+ else {
+ from = put - state->offset;
+ copy = left;
+ }
+ if (copy > state->length) copy = state->length;
+ state->length -= copy;
+ left -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ } while (state->length != 0);
+ break;
+
+ case DONE:
+ /* inflate stream terminated properly -- write leftover output */
+ ret = Z_STREAM_END;
+ if (left < state->wsize) {
+ if (out(out_desc, state->window, state->wsize - left))
+ ret = Z_BUF_ERROR;
+ }
+ goto inf_leave;
+
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+
+ default: /* can't happen, but makes compilers happy */
+ ret = Z_STREAM_ERROR;
+ goto inf_leave;
+ }
+
+ /* Return unused input */
+ inf_leave:
+ strm->next_in = next;
+ strm->avail_in = have;
+ return ret;
+}
+
+int ZEXPORT inflateBackEnd(
+ z_streamp strm)
+{
+ if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
+ return Z_STREAM_ERROR;
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
diff --git a/thirdparty/freetype/src/gzip/infblock.c b/thirdparty/freetype/src/gzip/infblock.c
deleted file mode 100644
index 2b4f0c2b53..0000000000
--- a/thirdparty/freetype/src/gzip/infblock.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/* infblock.c -- interpret and process block types to last block
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* Table for deflate from PKZIP's appnote.txt. */
-local const uInt border[] = { /* Order of the bit length code lengths */
- 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/*
- Notes beyond the 1.93a appnote.txt:
-
- 1. Distance pointers never point before the beginning of the output
- stream.
- 2. Distance pointers can point back across blocks, up to 32k away.
- 3. There is an implied maximum of 7 bits for the bit length table and
- 15 bits for the actual data.
- 4. If only one code exists, then it is encoded using one bit. (Zero
- would be more efficient, but perhaps a little confusing.) If two
- codes exist, they are coded using one bit each (0 and 1).
- 5. There is no way of sending zero distance codes--a dummy must be
- sent if there are none. (History: a pre 2.0 version of PKZIP would
- store blocks with no distance codes, but this was discovered to be
- too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
- zero distance codes, which is sent as one code of zero bits in
- length.
- 6. There are up to 286 literal/length codes. Code 256 represents the
- end-of-block. Note however that the static length tree defines
- 288 codes just to fill out the Huffman codes. Codes 286 and 287
- cannot be used though, since there is no length base or extra bits
- defined for them. Similarily, there are up to 30 distance codes.
- However, static trees define 32 codes (all 5 bits) to fill out the
- Huffman codes, but the last two had better not show up in the data.
- 7. Unzip can check dynamic Huffman blocks for complete code sets.
- The exception is that a single code would not be complete (see #4).
- 8. The five bits following the block type is really the number of
- literal codes sent minus 257.
- 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
- (1+6+6). Therefore, to output three times the length, you output
- three codes (1+1+1), whereas to output four times the same length,
- you only need two codes (1+3). Hmm.
- 10. In the tree reconstruction algorithm, Code = Code + Increment
- only if BitLength(i) is not zero. (Pretty obvious.)
- 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
- 12. Note: length code 284 can represent 227-258, but length code 285
- really is 258. The last length deserves its own, short code
- since it gets used a lot in very redundant files. The length
- 258 is special since 258 - 3 (the min match length) is 255.
- 13. The literal/length and distance code bit lengths are read as a
- single stream of lengths. It is possible (and advantageous) for
- a repeat code (16, 17, or 18) to go across the boundary between
- the two sets of lengths.
- */
-
-
-local void inflate_blocks_reset( /* s, z, c) */
-inflate_blocks_statef *s,
-z_streamp z,
-uLongf *c )
-{
- if (c != Z_NULL)
- *c = s->check;
- if (s->mode == BTREE || s->mode == DTREE)
- ZFREE(z, s->sub.trees.blens);
- if (s->mode == CODES)
- inflate_codes_free(s->sub.decode.codes, z);
- s->mode = TYPE;
- s->bitk = 0;
- s->bitb = 0;
- s->read = s->write = s->window;
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0);
- Tracev((stderr, "inflate: blocks reset\n"));
-}
-
-
-local inflate_blocks_statef *inflate_blocks_new( /* z, c, w) */
-z_streamp z,
-check_func c,
-uInt w )
-{
- inflate_blocks_statef *s;
-
- if ((s = (inflate_blocks_statef *)ZALLOC
- (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
- return s;
- if ((s->hufts =
- (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
- {
- ZFREE(z, s);
- return Z_NULL;
- }
- if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
- {
- ZFREE(z, s->hufts);
- ZFREE(z, s);
- return Z_NULL;
- }
- s->end = s->window + w;
- s->checkfn = c;
- s->mode = TYPE;
- Tracev((stderr, "inflate: blocks allocated\n"));
- inflate_blocks_reset(s, z, Z_NULL);
- return s;
-}
-
-
-local int inflate_blocks( /* s, z, r) */
-inflate_blocks_statef *s,
-z_streamp z,
-int r )
-{
- uInt t; /* temporary storage */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input based on current state */
- while (1) switch (s->mode)
- {
- case TYPE:
- NEEDBITS(3)
- t = (uInt)b & 7;
- s->last = t & 1;
- switch (t >> 1)
- {
- case 0: /* stored */
- Tracev((stderr, "inflate: stored block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- t = k & 7; /* go to byte boundary */
- DUMPBITS(t)
- s->mode = LENS; /* get length of stored block */
- break;
- case 1: /* fixed */
- Tracev((stderr, "inflate: fixed codes block%s\n",
- s->last ? " (last)" : ""));
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
-
- inflate_trees_fixed(&bl, &bd, (const inflate_huft**)&tl,
- (const inflate_huft**)&td, z);
- s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
- if (s->sub.decode.codes == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- }
- DUMPBITS(3)
- s->mode = CODES;
- break;
- case 2: /* dynamic */
- Tracev((stderr, "inflate: dynamic codes block%s\n",
- s->last ? " (last)" : ""));
- DUMPBITS(3)
- s->mode = TABLE;
- break;
- case 3: /* illegal */
- DUMPBITS(3)
- s->mode = BAD;
- z->msg = (char*)"invalid block type";
- r = Z_DATA_ERROR;
- LEAVE
- }
- break;
- case LENS:
- NEEDBITS(32)
- if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
- {
- s->mode = BAD;
- z->msg = (char*)"invalid stored block lengths";
- r = Z_DATA_ERROR;
- LEAVE
- }
- s->sub.left = (uInt)b & 0xffff;
- b = k = 0; /* dump bits */
- Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
- s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
- break;
- case STORED:
- if (n == 0)
- LEAVE
- NEEDOUT
- t = s->sub.left;
- if (t > n) t = n;
- if (t > m) t = m;
- zmemcpy(q, p, t);
- p += t; n -= t;
- q += t; m -= t;
- if ((s->sub.left -= t) != 0)
- break;
- Tracev((stderr, "inflate: stored end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- s->mode = s->last ? DRY : TYPE;
- break;
- case TABLE:
- NEEDBITS(14)
- s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
- if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
- {
- s->mode = BAD;
- z->msg = (char*)"too many length or distance symbols";
- r = Z_DATA_ERROR;
- LEAVE
- }
-#endif
- t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
- if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- DUMPBITS(14)
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: table sizes ok\n"));
- s->mode = BTREE;
- /* fall through */
- case BTREE:
- while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
- {
- NEEDBITS(3)
- s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
- DUMPBITS(3)
- }
- while (s->sub.trees.index < 19)
- s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
- s->sub.trees.bb = 7;
- t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
- &s->sub.trees.tb, s->hufts, z);
- if (t != Z_OK)
- {
- r = t;
- if (r == Z_DATA_ERROR)
- {
- ZFREE(z, s->sub.trees.blens);
- s->mode = BAD;
- }
- LEAVE
- }
- s->sub.trees.index = 0;
- Tracev((stderr, "inflate: bits tree ok\n"));
- s->mode = DTREE;
- /* fall through */
- case DTREE:
- while (t = s->sub.trees.table,
- s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
- {
- inflate_huft *h;
- uInt i, j, c;
-
- t = s->sub.trees.bb;
- NEEDBITS(t)
- h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
- t = h->bits;
- c = h->base;
- if (c < 16)
- {
- DUMPBITS(t)
- s->sub.trees.blens[s->sub.trees.index++] = c;
- }
- else /* c == 16..18 */
- {
- i = c == 18 ? 7 : c - 14;
- j = c == 18 ? 11 : 3;
- NEEDBITS(t + i)
- DUMPBITS(t)
- j += (uInt)b & inflate_mask[i];
- DUMPBITS(i)
- i = s->sub.trees.index;
- t = s->sub.trees.table;
- if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
- (c == 16 && i < 1))
- {
- ZFREE(z, s->sub.trees.blens);
- s->mode = BAD;
- z->msg = (char*)"invalid bit length repeat";
- r = Z_DATA_ERROR;
- LEAVE
- }
- c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
- do {
- s->sub.trees.blens[i++] = c;
- } while (--j);
- s->sub.trees.index = i;
- }
- }
- s->sub.trees.tb = Z_NULL;
- {
- uInt bl, bd;
- inflate_huft *tl, *td;
- inflate_codes_statef *c;
-
- bl = 9; /* must be <= 9 for lookahead assumptions */
- bd = 6; /* must be <= 9 for lookahead assumptions */
- t = s->sub.trees.table;
- t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
- s->sub.trees.blens, &bl, &bd, &tl, &td,
- s->hufts, z);
- if (t != Z_OK)
- {
- if (t == (uInt)Z_DATA_ERROR)
- {
- ZFREE(z, s->sub.trees.blens);
- s->mode = BAD;
- }
- r = t;
- LEAVE
- }
- Tracev((stderr, "inflate: trees ok\n"));
- if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
- {
- r = Z_MEM_ERROR;
- LEAVE
- }
- s->sub.decode.codes = c;
- }
- ZFREE(z, s->sub.trees.blens);
- s->mode = CODES;
- /* fall through */
- case CODES:
- UPDATE
- if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
- return inflate_flush(s, z, r);
- r = Z_OK;
- inflate_codes_free(s->sub.decode.codes, z);
- LOAD
- Tracev((stderr, "inflate: codes end, %lu total out\n",
- z->total_out + (q >= s->read ? q - s->read :
- (s->end - s->read) + (q - s->window))));
- if (!s->last)
- {
- s->mode = TYPE;
- break;
- }
- s->mode = DRY;
- /* fall through */
- case DRY:
- FLUSH
- if (s->read != s->write)
- LEAVE
- s->mode = DONE;
- /* fall through */
- case DONE:
- r = Z_STREAM_END;
- LEAVE
- case BAD:
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-#ifdef NEED_DUMMY_RETURN
- return 0;
-#endif
-}
-
-
-local int inflate_blocks_free( /* s, z) */
-inflate_blocks_statef *s,
-z_streamp z )
-{
- inflate_blocks_reset(s, z, Z_NULL);
- ZFREE(z, s->window);
- ZFREE(z, s->hufts);
- ZFREE(z, s);
- Tracev((stderr, "inflate: blocks freed\n"));
- return Z_OK;
-}
-
-
diff --git a/thirdparty/freetype/src/gzip/infblock.h b/thirdparty/freetype/src/gzip/infblock.h
deleted file mode 100644
index c2535a1e45..0000000000
--- a/thirdparty/freetype/src/gzip/infblock.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFBLOCK_H
-#define _INFBLOCK_H
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state FAR inflate_blocks_statef;
-
-local inflate_blocks_statef * inflate_blocks_new OF((
- z_streamp z,
- check_func c, /* check function */
- uInt w)); /* window size */
-
-local int inflate_blocks OF((
- inflate_blocks_statef *,
- z_streamp ,
- int)); /* initial return code */
-
-local void inflate_blocks_reset OF((
- inflate_blocks_statef *,
- z_streamp ,
- uLongf *)); /* check value on output */
-
-local int inflate_blocks_free OF((
- inflate_blocks_statef *,
- z_streamp));
-
-#endif /* _INFBLOCK_H */
diff --git a/thirdparty/freetype/src/gzip/infcodes.c b/thirdparty/freetype/src/gzip/infcodes.c
deleted file mode 100644
index ba30654990..0000000000
--- a/thirdparty/freetype/src/gzip/infcodes.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "inftrees.h"
-#include "infblock.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- START, /* x: set up for LEN */
- LEN, /* i: get length/literal/eob next */
- LENEXT, /* i: getting length extra (have base) */
- DIST, /* i: get distance next */
- DISTEXT, /* i: getting distance extra */
- COPY, /* o: copying bytes in window, waiting for space */
- LIT, /* o: got literal, waiting for output space */
- WASH, /* o: got eob, possibly still output waiting */
- END, /* x: got eob and all data flushed */
- BADCODE} /* x: got error */
-inflate_codes_mode;
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
- /* mode */
- inflate_codes_mode mode; /* current inflate_codes mode */
-
- /* mode dependent information */
- uInt len;
- union {
- struct {
- inflate_huft *tree; /* pointer into tree */
- uInt need; /* bits needed */
- } code; /* if LEN or DIST, where in tree */
- uInt lit; /* if LIT, literal */
- struct {
- uInt get; /* bits to get for extra */
- uInt dist; /* distance back to copy from */
- } copy; /* if EXT or COPY, where and how much */
- } sub; /* submode */
-
- /* mode independent information */
- Byte lbits; /* ltree bits decoded per branch */
- Byte dbits; /* dtree bits decoder per branch */
- inflate_huft *ltree; /* literal/length/eob tree */
- inflate_huft *dtree; /* distance tree */
-
-};
-
-
-local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */
-uInt bl, uInt bd,
-inflate_huft *tl,
-inflate_huft *td, /* need separate declaration for Borland C++ */
-z_streamp z )
-{
- inflate_codes_statef *c;
-
- if ((c = (inflate_codes_statef *)
- ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
- {
- c->mode = START;
- c->lbits = (Byte)bl;
- c->dbits = (Byte)bd;
- c->ltree = tl;
- c->dtree = td;
- Tracev((stderr, "inflate: codes new\n"));
- }
- return c;
-}
-
-
-local int inflate_codes( /* s, z, r) */
-inflate_blocks_statef *s,
-z_streamp z,
-int r )
-{
- uInt j; /* temporary storage */
- inflate_huft *t; /* temporary pointer */
- uInt e; /* extra bits or operation */
- uLong b; /* bit buffer */
- uInt k; /* bits in bit buffer */
- Bytef *p; /* input data pointer */
- uInt n; /* bytes available there */
- Bytef *q; /* output window write pointer */
- uInt m; /* bytes to end of window or read pointer */
- Bytef *f; /* pointer to copy strings from */
- inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
-
- /* copy input/output information to locals (UPDATE macro restores) */
- LOAD
-
- /* process input and output based on current state */
- while (1) switch (c->mode)
- { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
- case START: /* x: set up for LEN */
-#ifndef SLOW
- if (m >= 258 && n >= 10)
- {
- UPDATE
- r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
- LOAD
- if (r != Z_OK)
- {
- c->mode = r == Z_STREAM_END ? WASH : BADCODE;
- break;
- }
- }
-#endif /* !SLOW */
- c->sub.code.need = c->lbits;
- c->sub.code.tree = c->ltree;
- c->mode = LEN;
- /* fall through */
- case LEN: /* i: get length/literal/eob next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e == 0) /* literal */
- {
- c->sub.lit = t->base;
- Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
- "inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", t->base));
- c->mode = LIT;
- break;
- }
- if (e & 16) /* length */
- {
- c->sub.copy.get = e & 15;
- c->len = t->base;
- c->mode = LENEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t + t->base;
- break;
- }
- if (e & 32) /* end of block */
- {
- Tracevv((stderr, "inflate: end of block\n"));
- c->mode = WASH;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = (char*)"invalid literal/length code";
- r = Z_DATA_ERROR;
- LEAVE
- case LENEXT: /* i: getting length extra (have base) */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->len += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- c->sub.code.need = c->dbits;
- c->sub.code.tree = c->dtree;
- Tracevv((stderr, "inflate: length %u\n", c->len));
- c->mode = DIST;
- /* fall through */
- case DIST: /* i: get distance next */
- j = c->sub.code.need;
- NEEDBITS(j)
- t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
- DUMPBITS(t->bits)
- e = (uInt)(t->exop);
- if (e & 16) /* distance */
- {
- c->sub.copy.get = e & 15;
- c->sub.copy.dist = t->base;
- c->mode = DISTEXT;
- break;
- }
- if ((e & 64) == 0) /* next table */
- {
- c->sub.code.need = e;
- c->sub.code.tree = t + t->base;
- break;
- }
- c->mode = BADCODE; /* invalid code */
- z->msg = (char*)"invalid distance code";
- r = Z_DATA_ERROR;
- LEAVE
- case DISTEXT: /* i: getting distance extra */
- j = c->sub.copy.get;
- NEEDBITS(j)
- c->sub.copy.dist += (uInt)b & inflate_mask[j];
- DUMPBITS(j)
- Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
- c->mode = COPY;
- /* fall through */
- case COPY: /* o: copying bytes in window, waiting for space */
- f = q - c->sub.copy.dist;
- while (f < s->window) /* modulo window size-"while" instead */
- f += s->end - s->window; /* of "if" handles invalid distances */
- while (c->len)
- {
- NEEDOUT
- OUTBYTE(*f++)
- if (f == s->end)
- f = s->window;
- c->len--;
- }
- c->mode = START;
- break;
- case LIT: /* o: got literal, waiting for output space */
- NEEDOUT
- OUTBYTE(c->sub.lit)
- c->mode = START;
- break;
- case WASH: /* o: got eob, possibly more output */
- if (k > 7) /* return unused byte, if any */
- {
- Assert(k < 16, "inflate_codes grabbed too many bytes")
- k -= 8;
- n++;
- p--; /* can always return one */
- }
- FLUSH
- if (s->read != s->write)
- LEAVE
- c->mode = END;
- /* fall through */
- case END:
- r = Z_STREAM_END;
- LEAVE
- case BADCODE: /* x: got error */
- r = Z_DATA_ERROR;
- LEAVE
- default:
- r = Z_STREAM_ERROR;
- LEAVE
- }
-#ifdef NEED_DUMMY_RETURN
- return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
-#endif
-}
-
-
-local void inflate_codes_free( /* c, z) */
-inflate_codes_statef *c,
-z_streamp z )
-{
- ZFREE(z, c);
- Tracev((stderr, "inflate: codes free\n"));
-}
diff --git a/thirdparty/freetype/src/gzip/infcodes.h b/thirdparty/freetype/src/gzip/infcodes.h
deleted file mode 100644
index 154d7f896c..0000000000
--- a/thirdparty/freetype/src/gzip/infcodes.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFCODES_H
-#define _INFCODES_H
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state FAR inflate_codes_statef;
-
-local inflate_codes_statef *inflate_codes_new OF((
- uInt, uInt,
- inflate_huft *, inflate_huft *,
- z_streamp ));
-
-local int inflate_codes OF((
- inflate_blocks_statef *,
- z_streamp ,
- int));
-
-local void inflate_codes_free OF((
- inflate_codes_statef *,
- z_streamp ));
-
-#endif /* _INFCODES_H */
diff --git a/thirdparty/freetype/src/gzip/inffast.c b/thirdparty/freetype/src/gzip/inffast.c
new file mode 100644
index 0000000000..809737b13c
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/inffast.c
@@ -0,0 +1,323 @@
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2017 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#include "zutil.h"
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef ASMINF
+# pragma message("Assembler code may have bugs -- use at your own risk")
+#else
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+void ZLIB_INTERNAL inflate_fast(
+ z_streamp strm,
+ unsigned start)
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *in; /* local strm->next_in */
+ z_const unsigned char FAR *last; /* have enough input while in < last */
+ unsigned char FAR *out; /* local strm->next_out */
+ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
+ unsigned char FAR *end; /* while out < end, enough space available */
+#ifdef INFLATE_STRICT
+ unsigned dmax; /* maximum distance from zlib header */
+#endif
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
+ unsigned long hold; /* local strm->hold */
+ unsigned bits; /* local strm->bits */
+ code const FAR *lcode; /* local strm->lencode */
+ code const FAR *dcode; /* local strm->distcode */
+ unsigned lmask; /* mask for first level of length codes */
+ unsigned dmask; /* mask for first level of distance codes */
+ code const *here; /* retrieved table entry */
+ unsigned op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ unsigned len; /* match length, unused bytes */
+ unsigned dist; /* match distance */
+ unsigned char FAR *from; /* where to copy match from */
+
+ /* copy state to local variables */
+ state = (struct inflate_state FAR *)strm->state;
+ in = strm->next_in;
+ last = in + (strm->avail_in - 5);
+ out = strm->next_out;
+ beg = out - (start - strm->avail_out);
+ end = out + (strm->avail_out - 257);
+#ifdef INFLATE_STRICT
+ dmax = state->dmax;
+#endif
+ wsize = state->wsize;
+ whave = state->whave;
+ wnext = state->wnext;
+ window = state->window;
+ hold = state->hold;
+ bits = state->bits;
+ lcode = state->lencode;
+ dcode = state->distcode;
+ lmask = (1U << state->lenbits) - 1;
+ dmask = (1U << state->distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+ do {
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = lcode + (hold & lmask);
+ dolen:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op == 0) { /* literal */
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
+ }
+ else if (op & 16) { /* length base */
+ len = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ len += (unsigned)hold & ((1U << op) - 1);
+ hold >>= op;
+ bits -= op;
+ }
+ Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ here = dcode + (hold & dmask);
+ dodist:
+ op = (unsigned)(here->bits);
+ hold >>= op;
+ bits -= op;
+ op = (unsigned)(here->op);
+ if (op & 16) { /* distance base */
+ dist = (unsigned)(here->val);
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (unsigned long)(*in++) << bits;
+ bits += 8;
+ }
+ }
+ dist += (unsigned)hold & ((1U << op) - 1);
+#ifdef INFLATE_STRICT
+ if (dist > dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ hold >>= op;
+ bits -= op;
+ Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = (unsigned)(out - beg); /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state->sane) {
+ strm->msg =
+ (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ if (len <= op - whave) {
+ do {
+ *out++ = 0;
+ } while (--len);
+ continue;
+ }
+ len -= op - whave;
+ do {
+ *out++ = 0;
+ } while (--op > whave);
+ if (op == 0) {
+ from = out - dist;
+ do {
+ *out++ = *from++;
+ } while (--len);
+ continue;
+ }
+#endif
+ }
+ from = window;
+ if (wnext == 0) { /* very common case */
+ from += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ else if (wnext < op) { /* wrap around window */
+ from += wsize + wnext - op;
+ op -= wnext;
+ if (op < len) { /* some from end of window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = window;
+ if (wnext < len) { /* some from start of window */
+ op = wnext;
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ }
+ else { /* contiguous in window */
+ from += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ do {
+ *out++ = *from++;
+ } while (--op);
+ from = out - dist; /* rest from output */
+ }
+ }
+ while (len > 2) {
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ }
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ else {
+ from = out - dist; /* copy direct from output */
+ do { /* minimum length is three */
+ *out++ = *from++;
+ *out++ = *from++;
+ *out++ = *from++;
+ len -= 3;
+ } while (len > 2);
+ if (len) {
+ *out++ = *from++;
+ if (len > 1)
+ *out++ = *from++;
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = dcode + here->val + (hold & ((1U << op) - 1));
+ goto dodist;
+ }
+ else {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = lcode + here->val + (hold & ((1U << op) - 1));
+ goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->mode = TYPE;
+ break;
+ }
+ else {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ } while (in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >> 3;
+ in -= len;
+ bits -= len << 3;
+ hold &= (1U << bits) - 1;
+
+ /* update state and return */
+ strm->next_in = in;
+ strm->next_out = out;
+ strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
+ strm->avail_out = (unsigned)(out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state->hold = hold;
+ state->bits = bits;
+ return;
+}
+
+/*
+ inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
+ - Using bit fields for code structure
+ - Different op definition to avoid & for extra bits (do & for table bits)
+ - Three separate decoding do-loops for direct, window, and wnext == 0
+ - Special case for distance > 1 copies to do overlapped load and store copy
+ - Explicit branch predictions (based on measured branch probabilities)
+ - Deferring match copy and interspersed it with decoding subsequent codes
+ - Swapping literal/length else
+ - Swapping window/direct else
+ - Larger unrolled copy loops (three is about right)
+ - Moving len -= 3 statement into middle of loop
+ */
+
+#endif /* !ASMINF */
diff --git a/thirdparty/freetype/src/gzip/inffast.h b/thirdparty/freetype/src/gzip/inffast.h
new file mode 100644
index 0000000000..e5c1aa4ca8
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/inffast.h
@@ -0,0 +1,11 @@
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995-2003, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));
diff --git a/thirdparty/freetype/src/gzip/inffixed.h b/thirdparty/freetype/src/gzip/inffixed.h
index 4d4760ea00..d628327769 100644
--- a/thirdparty/freetype/src/gzip/inffixed.h
+++ b/thirdparty/freetype/src/gzip/inffixed.h
@@ -1,151 +1,94 @@
-/* inffixed.h -- table for decoding fixed codes
- * Generated automatically by the maketree.c program
- */
+ /* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by makefixed().
+ */
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
+ /* WARNING: this file should *not* be used by applications.
+ It is part of the implementation of this library and is
+ subject to change. Applications should only use zlib.h.
+ */
-local const uInt fixed_bl = 9;
-local const uInt fixed_bd = 5;
-local const inflate_huft fixed_tl[] = {
- {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
- {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
- {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
- {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
- {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
- {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
- {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
- {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
- {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
- {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
- {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
- {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
- {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
- {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
- {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
- {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
- {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
- {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
- {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
- {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
- {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
- {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
- {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
- {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
- {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
- {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
- {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
- {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
- {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
- {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
- {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
- {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
- {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
- {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
- {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
- {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
- {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
- {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
- {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
- {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
- {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
- {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
- {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
- {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
- {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
- {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
- {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
- {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
- {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
- {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
- {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
- {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
- {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
- {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
- {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
- {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
- {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
- {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
- {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
- {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
- {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
- {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
- {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
- {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
- {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
- {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
- {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
- {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
- {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
- {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
- {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
- {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
- {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
- {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
- {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
- {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
- {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
- {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
- {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
- {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
- {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
- {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
- {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
- {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
- {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
- {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
- {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
- {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
- {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
- {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
- {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
- {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
- {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
- {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
- {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
- {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
- {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
- {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
- {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
- {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
- {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
- {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
- {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
- {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
- {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
- {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
- {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
- {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
- {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
- {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
- {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
- {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
- {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
- {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
- {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
- {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
- {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
- {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
- {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
- {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
- {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
- {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
- {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
- {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
- };
-local const inflate_huft fixed_td[] = {
- {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
- {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
- {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
- {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
- {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
- {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
- {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
- {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
- };
+ static const code lenfix[512] = {
+ {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
+ {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
+ {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
+ {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
+ {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
+ {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
+ {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
+ {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
+ {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
+ {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
+ {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
+ {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
+ {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
+ {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
+ {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
+ {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
+ {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
+ {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
+ {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
+ {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
+ {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
+ {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
+ {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
+ {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
+ {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
+ {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
+ {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
+ {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
+ {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
+ {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
+ {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
+ {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
+ {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
+ {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
+ {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
+ {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
+ {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
+ {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
+ {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
+ {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
+ {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
+ {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
+ {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
+ {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
+ {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
+ {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
+ {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
+ {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
+ {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
+ {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
+ {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
+ {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
+ {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
+ {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
+ {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
+ {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
+ {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
+ {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
+ {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
+ {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
+ {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
+ {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
+ {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
+ {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
+ {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
+ {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
+ {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
+ {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
+ {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
+ {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
+ {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
+ {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
+ {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
+ {0,9,255}
+ };
+
+ static const code distfix[32] = {
+ {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
+ {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
+ {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
+ {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
+ {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
+ {22,5,193},{64,5,0}
+ };
diff --git a/thirdparty/freetype/src/gzip/inflate.c b/thirdparty/freetype/src/gzip/inflate.c
index 95e2653662..5bf5b815e5 100644
--- a/thirdparty/freetype/src/gzip/inflate.c
+++ b/thirdparty/freetype/src/gzip/inflate.c
@@ -1,283 +1,1610 @@
-/* inflate.c -- zlib interface to inflate modules
- * Copyright (C) 1995-2002 Mark Adler
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
+/*
+ * Change history:
+ *
+ * 1.2.beta0 24 Nov 2002
+ * - First version -- complete rewrite of inflate to simplify code, avoid
+ * creation of window when not needed, minimize use of window when it is
+ * needed, make inffast.c even faster, implement gzip decoding, and to
+ * improve code readability and style over the previous zlib inflate code
+ *
+ * 1.2.beta1 25 Nov 2002
+ * - Use pointers for available input and output checking in inffast.c
+ * - Remove input and output counters in inffast.c
+ * - Change inffast.c entry and loop from avail_in >= 7 to >= 6
+ * - Remove unnecessary second byte pull from length extra in inffast.c
+ * - Unroll direct copy to three copies per loop in inffast.c
+ *
+ * 1.2.beta2 4 Dec 2002
+ * - Change external routine names to reduce potential conflicts
+ * - Correct filename to inffixed.h for fixed tables in inflate.c
+ * - Make hbuf[] unsigned char to match parameter type in inflate.c
+ * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset)
+ * to avoid negation problem on Alphas (64 bit) in inflate.c
+ *
+ * 1.2.beta3 22 Dec 2002
+ * - Add comments on state->bits assertion in inffast.c
+ * - Add comments on op field in inftrees.h
+ * - Fix bug in reuse of allocated window after inflateReset()
+ * - Remove bit fields--back to byte structure for speed
+ * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths
+ * - Change post-increments to pre-increments in inflate_fast(), PPC biased?
+ * - Add compile time option, POSTINC, to use post-increments instead (Intel?)
+ * - Make MATCH copy in inflate() much faster for when inflate_fast() not used
+ * - Use local copies of stream next and avail values, as well as local bit
+ * buffer and bit count in inflate()--for speed when inflate_fast() not used
+ *
+ * 1.2.beta4 1 Jan 2003
+ * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings
+ * - Move a comment on output buffer sizes from inffast.c to inflate.c
+ * - Add comments in inffast.c to introduce the inflate_fast() routine
+ * - Rearrange window copies in inflate_fast() for speed and simplification
+ * - Unroll last copy for window match in inflate_fast()
+ * - Use local copies of window variables in inflate_fast() for speed
+ * - Pull out common wnext == 0 case for speed in inflate_fast()
+ * - Make op and len in inflate_fast() unsigned for consistency
+ * - Add FAR to lcode and dcode declarations in inflate_fast()
+ * - Simplified bad distance check in inflate_fast()
+ * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new
+ * source file infback.c to provide a call-back interface to inflate for
+ * programs like gzip and unzip -- uses window as output buffer to avoid
+ * window copying
+ *
+ * 1.2.beta5 1 Jan 2003
+ * - Improved inflateBack() interface to allow the caller to provide initial
+ * input in strm.
+ * - Fixed stored blocks bug in inflateBack()
+ *
+ * 1.2.beta6 4 Jan 2003
+ * - Added comments in inffast.c on effectiveness of POSTINC
+ * - Typecasting all around to reduce compiler warnings
+ * - Changed loops from while (1) or do {} while (1) to for (;;), again to
+ * make compilers happy
+ * - Changed type of window in inflateBackInit() to unsigned char *
+ *
+ * 1.2.beta7 27 Jan 2003
+ * - Changed many types to unsigned or unsigned short to avoid warnings
+ * - Added inflateCopy() function
+ *
+ * 1.2.0 9 Mar 2003
+ * - Changed inflateBack() interface to provide separate opaque descriptors
+ * for the in() and out() functions
+ * - Changed inflateBack() argument and in_func typedef to swap the length
+ * and buffer address return values for the input function
+ * - Check next_in and next_out for Z_NULL on entry to inflate()
+ *
+ * The history for versions after 1.2.0 are in ChangeLog in zlib distribution.
+ */
+
#include "zutil.h"
-#include "infblock.h"
-
-#define DONE INFLATE_DONE
-#define BAD INFLATE_BAD
-
-typedef enum {
- METHOD, /* waiting for method byte */
- FLAG, /* waiting for flag byte */
- DICT4, /* four dictionary check bytes to go */
- DICT3, /* three dictionary check bytes to go */
- DICT2, /* two dictionary check bytes to go */
- DICT1, /* one dictionary check byte to go */
- DICT0, /* waiting for inflateSetDictionary */
- BLOCKS, /* decompressing blocks */
- CHECK4, /* four check bytes to go */
- CHECK3, /* three check bytes to go */
- CHECK2, /* two check bytes to go */
- CHECK1, /* one check byte to go */
- DONE, /* finished check, done */
- BAD} /* got an error--stay here */
-inflate_mode;
-
-/* inflate private state */
-struct internal_state {
-
- /* mode */
- inflate_mode mode; /* current inflate mode */
-
- /* mode dependent information */
- union {
- uInt method; /* if FLAGS, method byte */
- struct {
- uLong was; /* computed check value */
- uLong need; /* stream check value */
- } check; /* if CHECK, check values to compare */
- uInt marker; /* if BAD, inflateSync's marker bytes count */
- } sub; /* submode */
-
- /* mode independent information */
- int nowrap; /* flag for no wrapper */
- uInt wbits; /* log2(window size) (8..15, defaults to 15) */
- inflate_blocks_statef
- *blocks; /* current inflate_blocks state */
-
-};
-
-
-ZEXPORT(int) inflateReset( /* z) */
-z_streamp z )
+#include "inftrees.h"
+#include "inflate.h"
+#include "inffast.h"
+
+#ifdef MAKEFIXED
+# ifndef BUILDFIXED
+# define BUILDFIXED
+# endif
+#endif
+
+/* function prototypes */
+local int inflateStateCheck OF((z_streamp strm));
+local void fixedtables OF((struct inflate_state FAR *state));
+local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
+ unsigned copy));
+#ifdef BUILDFIXED
+ void makefixed OF((void));
+#endif
+#ifndef Z_FREETYPE
+local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
+ unsigned len));
+#endif
+
+local int inflateStateCheck(
+ z_streamp strm)
{
- if (z == Z_NULL || z->state == Z_NULL)
- return Z_STREAM_ERROR;
- z->total_in = z->total_out = 0;
- z->msg = Z_NULL;
- z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
- inflate_blocks_reset(z->state->blocks, z, Z_NULL);
- Tracev((stderr, "inflate: reset\n"));
- return Z_OK;
+ struct inflate_state FAR *state;
+ if (strm == Z_NULL ||
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
+ return 1;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state == Z_NULL || state->strm != strm ||
+ state->mode < HEAD || state->mode > SYNC)
+ return 1;
+ return 0;
}
+int ZEXPORT inflateResetKeep(
+ z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ strm->total_in = strm->total_out = state->total = 0;
+ strm->msg = Z_NULL;
+ if (state->wrap) /* to support ill-conceived Java test suite */
+ strm->adler = state->wrap & 1;
+ state->mode = HEAD;
+ state->last = 0;
+ state->havedict = 0;
+ state->flags = -1;
+ state->dmax = 32768U;
+ state->head = Z_NULL;
+ state->hold = 0;
+ state->bits = 0;
+ state->lencode = state->distcode = state->next = state->codes;
+ state->sane = 1;
+ state->back = -1;
+ Tracev((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
-ZEXPORT(int) inflateEnd( /* z) */
-z_streamp z )
+int ZEXPORT inflateReset(
+ z_streamp strm)
{
- if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
- return Z_STREAM_ERROR;
- if (z->state->blocks != Z_NULL)
- inflate_blocks_free(z->state->blocks, z);
- ZFREE(z, z->state);
- z->state = Z_NULL;
- Tracev((stderr, "inflate: end\n"));
- return Z_OK;
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ state->wsize = 0;
+ state->whave = 0;
+ state->wnext = 0;
+ return inflateResetKeep(strm);
}
+int ZEXPORT inflateReset2(
+ z_streamp strm,
+ int windowBits)
+{
+ int wrap;
+ struct inflate_state FAR *state;
+
+ /* get the state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >> 4) + 5;
+#ifdef GUNZIP
+ if (windowBits < 48)
+ windowBits &= 15;
+#endif
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return Z_STREAM_ERROR;
+ if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
+ ZFREE(strm, state->window);
+ state->window = Z_NULL;
+ }
+
+ /* update state and reset the rest of it */
+ state->wrap = wrap;
+ state->wbits = (unsigned)windowBits;
+ return inflateReset(strm);
+}
-ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */
-z_streamp z,
-int w,
-const char *version,
-int stream_size )
+int ZEXPORT inflateInit2_(
+ z_streamp strm,
+ int windowBits,
+ const char *version,
+ int stream_size)
{
- if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
- stream_size != sizeof(z_stream))
- return Z_VERSION_ERROR;
-
- /* initialize state */
- if (z == Z_NULL)
- return Z_STREAM_ERROR;
- z->msg = Z_NULL;
- if (z->zalloc == Z_NULL)
- {
- z->zalloc = zcalloc;
- z->opaque = (voidpf)0;
- }
- if (z->zfree == Z_NULL) z->zfree = zcfree;
- if ((z->state = (struct internal_state FAR *)
- ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
- return Z_MEM_ERROR;
- z->state->blocks = Z_NULL;
-
- /* handle undocumented nowrap option (no zlib header or check) */
- z->state->nowrap = 0;
- if (w < 0)
- {
- w = - w;
- z->state->nowrap = 1;
- }
-
- /* set window size */
- if (w < 8 || w > 15)
- {
- inflateEnd(z);
- return Z_STREAM_ERROR;
- }
- z->state->wbits = (uInt)w;
-
- /* create inflate_blocks state */
- if ((z->state->blocks =
- inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
- == Z_NULL)
- {
- inflateEnd(z);
- return Z_MEM_ERROR;
- }
- Tracev((stderr, "inflate: allocated\n"));
-
- /* reset state */
- inflateReset(z);
- return Z_OK;
+ int ret;
+ struct inflate_state FAR *state;
+
+ if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+ stream_size != (int)(sizeof(z_stream)))
+ return Z_VERSION_ERROR;
+ if (strm == Z_NULL) return Z_STREAM_ERROR;
+ strm->msg = Z_NULL; /* in case we return an error */
+ if (strm->zalloc == (alloc_func)0) {
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zalloc = zcalloc;
+ strm->opaque = (voidpf)0;
+#endif
+ }
+ if (strm->zfree == (free_func)0)
+#ifdef Z_SOLO
+ return Z_STREAM_ERROR;
+#else
+ strm->zfree = zcfree;
+#endif
+ state = (struct inflate_state FAR *)
+ ZALLOC(strm, 1, sizeof(struct inflate_state));
+ if (state == Z_NULL) return Z_MEM_ERROR;
+ Tracev((stderr, "inflate: allocated\n"));
+ strm->state = (struct internal_state FAR *)state;
+ state->strm = strm;
+ state->window = Z_NULL;
+ state->mode = HEAD; /* to pass state test in inflateReset2() */
+ ret = inflateReset2(strm, windowBits);
+ if (ret != Z_OK) {
+ ZFREE(strm, state);
+ strm->state = Z_NULL;
+ }
+ return ret;
}
+int ZEXPORT inflateInit_(
+ z_streamp strm,
+ const char *version,
+ int stream_size)
+{
+ return inflateInit2_(strm, DEF_WBITS, version, stream_size);
+}
+#ifndef Z_FREETYPE
-#undef NEEDBYTE
-#define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
+int ZEXPORT inflatePrime(
+ z_streamp strm,
+ int bits,
+ int value)
+{
+ struct inflate_state FAR *state;
-#undef NEXTBYTE
-#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (bits < 0) {
+ state->hold = 0;
+ state->bits = 0;
+ return Z_OK;
+ }
+ if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR;
+ value &= (1L << bits) - 1;
+ state->hold += (unsigned)value << state->bits;
+ state->bits += (uInt)bits;
+ return Z_OK;
+}
+#endif /* !Z_FREETYPE */
-ZEXPORT(int) inflate( /* z, f) */
-z_streamp z,
-int f )
+/*
+ Return state with length and distance decoding tables and index sizes set to
+ fixed code decoding. Normally this returns fixed tables from inffixed.h.
+ If BUILDFIXED is defined, then instead this routine builds the tables the
+ first time it's called, and returns those tables the first time and
+ thereafter. This reduces the size of the code by about 2K bytes, in
+ exchange for a little execution time. However, BUILDFIXED should not be
+ used for threaded applications, since the rewriting of the tables and virgin
+ may not be thread-safe.
+ */
+local void fixedtables(
+ struct inflate_state FAR *state)
{
- int r;
- uInt b;
-
- if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
- return Z_STREAM_ERROR;
- f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
- r = Z_BUF_ERROR;
- while (1) switch (z->state->mode)
- {
- case METHOD:
- NEEDBYTE
- if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
- {
- z->state->mode = BAD;
- z->msg = (char*)"unknown compression method";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
- {
- z->state->mode = BAD;
- z->msg = (char*)"invalid window size";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- z->state->mode = FLAG;
- /* fall through */
- case FLAG:
- NEEDBYTE
- b = NEXTBYTE;
- if (((z->state->sub.method << 8) + b) % 31)
- {
- z->state->mode = BAD;
- z->msg = (char*)"incorrect header check";
- z->state->sub.marker = 5; /* can't try inflateSync */
- break;
- }
- Tracev((stderr, "inflate: zlib header ok\n"));
- if (!(b & PRESET_DICT))
- {
- z->state->mode = BLOCKS;
- break;
- }
- z->state->mode = DICT4;
- /* fall through */
- case DICT4:
- NEEDBYTE
- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
- z->state->mode = DICT3;
- /* fall through */
- case DICT3:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
- z->state->mode = DICT2;
- /* fall through */
- case DICT2:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
- z->state->mode = DICT1;
- /* fall through */
- case DICT1:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE;
- z->adler = z->state->sub.check.need;
- z->state->mode = DICT0;
- return Z_NEED_DICT;
- case DICT0:
- z->state->mode = BAD;
- z->msg = (char*)"need dictionary";
- z->state->sub.marker = 0; /* can try inflateSync */
- return Z_STREAM_ERROR;
- case BLOCKS:
- r = inflate_blocks(z->state->blocks, z, r);
- if (r == Z_DATA_ERROR)
- {
- z->state->mode = BAD;
- z->state->sub.marker = 0; /* can try inflateSync */
- break;
- }
- if (r == Z_OK)
- r = f;
- if (r != Z_STREAM_END)
- return r;
- r = f;
- inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
- if (z->state->nowrap)
- {
- z->state->mode = DONE;
- break;
- }
- z->state->mode = CHECK4;
- /* fall through */
- case CHECK4:
- NEEDBYTE
- z->state->sub.check.need = (uLong)NEXTBYTE << 24;
- z->state->mode = CHECK3;
- /* fall through */
- case CHECK3:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 16;
- z->state->mode = CHECK2;
- /* fall through */
- case CHECK2:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE << 8;
- z->state->mode = CHECK1;
- /* fall through */
- case CHECK1:
- NEEDBYTE
- z->state->sub.check.need += (uLong)NEXTBYTE;
-
- if (z->state->sub.check.was != z->state->sub.check.need)
- {
- z->state->mode = BAD;
- z->msg = (char*)"incorrect data check";
- z->state->sub.marker = 5; /* can't try inflateSync */
+#ifdef BUILDFIXED
+ static int virgin = 1;
+ static code *lenfix, *distfix;
+ static code fixed[544];
+
+ /* build fixed huffman tables if first call (may not be thread safe) */
+ if (virgin) {
+ unsigned sym, bits;
+ static code *next;
+
+ /* literal/length table */
+ sym = 0;
+ while (sym < 144) state->lens[sym++] = 8;
+ while (sym < 256) state->lens[sym++] = 9;
+ while (sym < 280) state->lens[sym++] = 7;
+ while (sym < 288) state->lens[sym++] = 8;
+ next = fixed;
+ lenfix = next;
+ bits = 9;
+ inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
+
+ /* distance table */
+ sym = 0;
+ while (sym < 32) state->lens[sym++] = 5;
+ distfix = next;
+ bits = 5;
+ inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
+
+ /* do this just once */
+ virgin = 0;
+ }
+#else /* !BUILDFIXED */
+# include "inffixed.h"
+#endif /* BUILDFIXED */
+ state->lencode = lenfix;
+ state->lenbits = 9;
+ state->distcode = distfix;
+ state->distbits = 5;
+}
+
+#ifdef MAKEFIXED
+#include <stdio.h>
+
+/*
+ Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also
+ defines BUILDFIXED, so the tables are built on the fly. makefixed() writes
+ those tables to stdout, which would be piped to inffixed.h. A small program
+ can simply call makefixed to do this:
+
+ void makefixed(void);
+
+ int main(void)
+ {
+ makefixed();
+ return 0;
+ }
+
+ Then that can be linked with zlib built with MAKEFIXED defined and run:
+
+ a.out > inffixed.h
+ */
+void makefixed()
+{
+ unsigned low, size;
+ struct inflate_state state;
+
+ fixedtables(&state);
+ puts(" /* inffixed.h -- table for decoding fixed codes");
+ puts(" * Generated automatically by makefixed().");
+ puts(" */");
+ puts("");
+ puts(" /* WARNING: this file should *not* be used by applications.");
+ puts(" It is part of the implementation of this library and is");
+ puts(" subject to change. Applications should only use zlib.h.");
+ puts(" */");
+ puts("");
+ size = 1U << 9;
+ printf(" static const code lenfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 7) == 0) printf("\n ");
+ printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op,
+ state.lencode[low].bits, state.lencode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+ size = 1U << 5;
+ printf("\n static const code distfix[%u] = {", size);
+ low = 0;
+ for (;;) {
+ if ((low % 6) == 0) printf("\n ");
+ printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits,
+ state.distcode[low].val);
+ if (++low == size) break;
+ putchar(',');
+ }
+ puts("\n };");
+}
+#endif /* MAKEFIXED */
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+ */
+local int updatewindow(
+ z_streamp strm,
+ const Bytef *end,
+ unsigned copy)
+{
+ struct inflate_state FAR *state;
+ unsigned dist;
+
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state->window == Z_NULL) {
+ state->window = (unsigned char FAR *)
+ ZALLOC(strm, 1U << state->wbits,
+ sizeof(unsigned char));
+ if (state->window == Z_NULL) return 1;
+ }
+
+ /* if window not in use yet, initialize */
+ if (state->wsize == 0) {
+ state->wsize = 1U << state->wbits;
+ state->wnext = 0;
+ state->whave = 0;
+ }
+
+ /* copy state->wsize or less output bytes into the circular window */
+ if (copy >= state->wsize) {
+ zmemcpy(state->window, end - state->wsize, state->wsize);
+ state->wnext = 0;
+ state->whave = state->wsize;
+ }
+ else {
+ dist = state->wsize - state->wnext;
+ if (dist > copy) dist = copy;
+ zmemcpy(state->window + state->wnext, end - copy, dist);
+ copy -= dist;
+ if (copy) {
+ zmemcpy(state->window, end - copy, copy);
+ state->wnext = copy;
+ state->whave = state->wsize;
+ }
+ else {
+ state->wnext += dist;
+ if (state->wnext == state->wsize) state->wnext = 0;
+ if (state->whave < state->wsize) state->whave += dist;
+ }
+ }
+ return 0;
+}
+
+/* Macros for inflate(): */
+
+/* check function to use adler32() for zlib or crc32() for gzip */
+#ifdef GUNZIP
+# define UPDATE_CHECK(check, buf, len) \
+ (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
+#else
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
+#endif
+
+/* check macros for header crc */
+#ifdef GUNZIP
+# define CRC2(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ check = crc32(check, hbuf, 2); \
+ } while (0)
+
+# define CRC4(check, word) \
+ do { \
+ hbuf[0] = (unsigned char)(word); \
+ hbuf[1] = (unsigned char)((word) >> 8); \
+ hbuf[2] = (unsigned char)((word) >> 16); \
+ hbuf[3] = (unsigned char)((word) >> 24); \
+ check = crc32(check, hbuf, 4); \
+ } while (0)
+#endif
+
+/* Load registers with state in inflate() for speed */
+#define LOAD() \
+ do { \
+ put = strm->next_out; \
+ left = strm->avail_out; \
+ next = strm->next_in; \
+ have = strm->avail_in; \
+ hold = state->hold; \
+ bits = state->bits; \
+ } while (0)
+
+/* Restore state from registers in inflate() */
+#define RESTORE() \
+ do { \
+ strm->next_out = put; \
+ strm->avail_out = left; \
+ strm->next_in = next; \
+ strm->avail_in = have; \
+ state->hold = hold; \
+ state->bits = bits; \
+ } while (0)
+
+/* Clear the input bit accumulator */
+#define INITBITS() \
+ do { \
+ hold = 0; \
+ bits = 0; \
+ } while (0)
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+#define PULLBYTE() \
+ do { \
+ if (have == 0) goto inf_leave; \
+ have--; \
+ hold += (unsigned long)(*next++) << bits; \
+ bits += 8; \
+ } while (0)
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+#define NEEDBITS(n) \
+ do { \
+ while (bits < (unsigned)(n)) \
+ PULLBYTE(); \
+ } while (0)
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+#define BITS(n) \
+ ((unsigned)hold & ((1U << (n)) - 1))
+
+/* Remove n bits from the bit accumulator */
+#define DROPBITS(n) \
+ do { \
+ hold >>= (n); \
+ bits -= (unsigned)(n); \
+ } while (0)
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+#define BYTEBITS() \
+ do { \
+ hold >>= bits & 7; \
+ bits -= bits & 7; \
+ } while (0)
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
break;
- }
- Tracev((stderr, "inflate: zlib check ok\n"));
- z->state->mode = DONE;
- /* fall through */
- case DONE:
- return Z_STREAM_END;
- case BAD:
- return Z_DATA_ERROR;
- default:
- return Z_STREAM_ERROR;
- }
-#ifdef NEED_DUMMY_RETURN
- return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+int ZEXPORT inflate(
+ z_streamp strm,
+ int flush)
+{
+ struct inflate_state FAR *state;
+ z_const unsigned char FAR *next; /* next input */
+ unsigned char FAR *put; /* next output */
+ unsigned have, left; /* available input and output */
+ unsigned long hold; /* bit buffer */
+ unsigned bits; /* bits in bit buffer */
+ unsigned in, out; /* save starting available input and output */
+ unsigned copy; /* number of stored or match bytes to copy */
+ unsigned char FAR *from; /* where to copy match bytes from */
+ code here; /* current decoding table entry */
+ code last; /* parent table entry */
+ unsigned len; /* length to copy for repeats, bits to drop */
+ int ret; /* return code */
+#ifdef GUNZIP
+ unsigned char hbuf[4]; /* buffer for gzip header crc calculation */
#endif
+ static const unsigned short order[19] = /* permutation of code lengths */
+ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+ if (inflateStateCheck(strm) || strm->next_out == Z_NULL ||
+ (strm->next_in == Z_NULL && strm->avail_in != 0))
+ return Z_STREAM_ERROR;
+
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */
+ LOAD();
+ in = have;
+ out = left;
+ ret = Z_OK;
+ for (;;)
+ switch (state->mode) {
+ case HEAD:
+ if (state->wrap == 0) {
+ state->mode = TYPEDO;
+ break;
+ }
+ NEEDBITS(16);
+#ifdef GUNZIP
+ if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */
+ if (state->wbits == 0)
+ state->wbits = 15;
+ state->check = crc32(0L, Z_NULL, 0);
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = FLAGS;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->done = -1;
+ if (!(state->wrap & 1) || /* check if zlib header allowed */
+#else
+ if (
+#endif
+ ((BITS(8) << 8) + (hold >> 8)) % 31) {
+ strm->msg = (char *)"incorrect header check";
+ state->mode = BAD;
+ break;
+ }
+ if (BITS(4) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ DROPBITS(4);
+ len = BITS(4) + 8;
+ if (state->wbits == 0)
+ state->wbits = len;
+ if (len > 15 || len > state->wbits) {
+ strm->msg = (char *)"invalid window size";
+ state->mode = BAD;
+ break;
+ }
+ state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
+ Tracev((stderr, "inflate: zlib header ok\n"));
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = hold & 0x200 ? DICTID : TYPE;
+ INITBITS();
+ break;
+#ifdef GUNZIP
+ case FLAGS:
+ NEEDBITS(16);
+ state->flags = (int)(hold);
+ if ((state->flags & 0xff) != Z_DEFLATED) {
+ strm->msg = (char *)"unknown compression method";
+ state->mode = BAD;
+ break;
+ }
+ if (state->flags & 0xe000) {
+ strm->msg = (char *)"unknown header flags set";
+ state->mode = BAD;
+ break;
+ }
+ if (state->head != Z_NULL)
+ state->head->text = (int)((hold >> 8) & 1);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = TIME;
+ /* fallthrough */
+ case TIME:
+ NEEDBITS(32);
+ if (state->head != Z_NULL)
+ state->head->time = hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC4(state->check, hold);
+ INITBITS();
+ state->mode = OS;
+ /* fallthrough */
+ case OS:
+ NEEDBITS(16);
+ if (state->head != Z_NULL) {
+ state->head->xflags = (int)(hold & 0xff);
+ state->head->os = (int)(hold >> 8);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ state->mode = EXLEN;
+ /* fallthrough */
+ case EXLEN:
+ if (state->flags & 0x0400) {
+ NEEDBITS(16);
+ state->length = (unsigned)(hold);
+ if (state->head != Z_NULL)
+ state->head->extra_len = (unsigned)hold;
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ CRC2(state->check, hold);
+ INITBITS();
+ }
+ else if (state->head != Z_NULL)
+ state->head->extra = Z_NULL;
+ state->mode = EXTRA;
+ /* fallthrough */
+ case EXTRA:
+ if (state->flags & 0x0400) {
+ copy = state->length;
+ if (copy > have) copy = have;
+ if (copy) {
+ if (state->head != Z_NULL &&
+ state->head->extra != Z_NULL) {
+ len = state->head->extra_len - state->length;
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+ }
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ state->length -= copy;
+ }
+ if (state->length) goto inf_leave;
+ }
+ state->length = 0;
+ state->mode = NAME;
+ /* fallthrough */
+ case NAME:
+ if (state->flags & 0x0800) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->name != Z_NULL &&
+ state->length < state->head->name_max)
+ state->head->name[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->name = Z_NULL;
+ state->length = 0;
+ state->mode = COMMENT;
+ /* fallthrough */
+ case COMMENT:
+ if (state->flags & 0x1000) {
+ if (have == 0) goto inf_leave;
+ copy = 0;
+ do {
+ len = (unsigned)(next[copy++]);
+ if (state->head != Z_NULL &&
+ state->head->comment != Z_NULL &&
+ state->length < state->head->comm_max)
+ state->head->comment[state->length++] = (Bytef)len;
+ } while (len && copy < have);
+ if ((state->flags & 0x0200) && (state->wrap & 4))
+ state->check = crc32(state->check, next, copy);
+ have -= copy;
+ next += copy;
+ if (len) goto inf_leave;
+ }
+ else if (state->head != Z_NULL)
+ state->head->comment = Z_NULL;
+ state->mode = HCRC;
+ /* fallthrough */
+ case HCRC:
+ if (state->flags & 0x0200) {
+ NEEDBITS(16);
+ if ((state->wrap & 4) && hold != (state->check & 0xffff)) {
+ strm->msg = (char *)"header crc mismatch";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ }
+ if (state->head != Z_NULL) {
+ state->head->hcrc = (int)((state->flags >> 9) & 1);
+ state->head->done = 1;
+ }
+ strm->adler = state->check = crc32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ break;
+#endif
+ case DICTID:
+ NEEDBITS(32);
+ strm->adler = state->check = ZSWAP32(hold);
+ INITBITS();
+ state->mode = DICT;
+ /* fallthrough */
+ case DICT:
+ if (state->havedict == 0) {
+ RESTORE();
+ return Z_NEED_DICT;
+ }
+ strm->adler = state->check = adler32(0L, Z_NULL, 0);
+ state->mode = TYPE;
+ /* fallthrough */
+ case TYPE:
+ if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case TYPEDO:
+ if (state->last) {
+ BYTEBITS();
+ state->mode = CHECK;
+ break;
+ }
+ NEEDBITS(3);
+ state->last = BITS(1);
+ DROPBITS(1);
+ switch (BITS(2)) {
+ case 0: /* stored block */
+ Tracev((stderr, "inflate: stored block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+ Tracev((stderr, "inflate: fixed codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = LEN_; /* decode codes */
+ if (flush == Z_TREES) {
+ DROPBITS(2);
+ goto inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+ Tracev((stderr, "inflate: dynamic codes block%s\n",
+ state->last ? " (last)" : ""));
+ state->mode = TABLE;
+ break;
+ case 3:
+ strm->msg = (char *)"invalid block type";
+ state->mode = BAD;
+ }
+ DROPBITS(2);
+ break;
+ case STORED:
+ BYTEBITS(); /* go to byte boundary */
+ NEEDBITS(32);
+ if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
+ strm->msg = (char *)"invalid stored block lengths";
+ state->mode = BAD;
+ break;
+ }
+ state->length = (unsigned)hold & 0xffff;
+ Tracev((stderr, "inflate: stored length %u\n",
+ state->length));
+ INITBITS();
+ state->mode = COPY_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case COPY_:
+ state->mode = COPY;
+ /* fallthrough */
+ case COPY:
+ copy = state->length;
+ if (copy) {
+ if (copy > have) copy = have;
+ if (copy > left) copy = left;
+ if (copy == 0) goto inf_leave;
+ zmemcpy(put, next, copy);
+ have -= copy;
+ next += copy;
+ left -= copy;
+ put += copy;
+ state->length -= copy;
+ break;
+ }
+ Tracev((stderr, "inflate: stored end\n"));
+ state->mode = TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14);
+ state->nlen = BITS(5) + 257;
+ DROPBITS(5);
+ state->ndist = BITS(5) + 1;
+ DROPBITS(5);
+ state->ncode = BITS(4) + 4;
+ DROPBITS(4);
+#ifndef PKZIP_BUG_WORKAROUND
+ if (state->nlen > 286 || state->ndist > 30) {
+ strm->msg = (char *)"too many length or distance symbols";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ state->have = 0;
+ state->mode = LENLENS;
+ /* fallthrough */
+ case LENLENS:
+ while (state->have < state->ncode) {
+ NEEDBITS(3);
+ state->lens[order[state->have++]] = (unsigned short)BITS(3);
+ DROPBITS(3);
+ }
+ while (state->have < 19)
+ state->lens[order[state->have++]] = 0;
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 7;
+ ret = inflate_table(CODES, state->lens, 19, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid code lengths set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: code lengths ok\n"));
+ state->have = 0;
+ state->mode = CODELENS;
+ /* fallthrough */
+ case CODELENS:
+ while (state->have < state->nlen + state->ndist) {
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.val < 16) {
+ DROPBITS(here.bits);
+ state->lens[state->have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ NEEDBITS(here.bits + 2);
+ DROPBITS(here.bits);
+ if (state->have == 0) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ len = state->lens[state->have - 1];
+ copy = 3 + BITS(2);
+ DROPBITS(2);
+ }
+ else if (here.val == 17) {
+ NEEDBITS(here.bits + 3);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 3 + BITS(3);
+ DROPBITS(3);
+ }
+ else {
+ NEEDBITS(here.bits + 7);
+ DROPBITS(here.bits);
+ len = 0;
+ copy = 11 + BITS(7);
+ DROPBITS(7);
+ }
+ if (state->have + copy > state->nlen + state->ndist) {
+ strm->msg = (char *)"invalid bit length repeat";
+ state->mode = BAD;
+ break;
+ }
+ while (copy--)
+ state->lens[state->have++] = (unsigned short)len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state->mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state->lens[256] == 0) {
+ strm->msg = (char *)"invalid code -- missing end-of-block";
+ state->mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state->next = state->codes;
+ state->lencode = (const code FAR *)(state->next);
+ state->lenbits = 9;
+ ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+ &(state->lenbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid literal/lengths set";
+ state->mode = BAD;
+ break;
+ }
+ state->distcode = (const code FAR *)(state->next);
+ state->distbits = 6;
+ ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
+ &(state->next), &(state->distbits), state->work);
+ if (ret) {
+ strm->msg = (char *)"invalid distances set";
+ state->mode = BAD;
+ break;
+ }
+ Tracev((stderr, "inflate: codes ok\n"));
+ state->mode = LEN_;
+ if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
+ case LEN_:
+ state->mode = LEN;
+ /* fallthrough */
+ case LEN:
+ if (have >= 6 && left >= 258) {
+ RESTORE();
+ inflate_fast(strm, out);
+ LOAD();
+ if (state->mode == TYPE)
+ state->back = -1;
+ break;
+ }
+ state->back = 0;
+ for (;;) {
+ here = state->lencode[BITS(state->lenbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->lencode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ state->length = (unsigned)here.val;
+ if ((int)(here.op) == 0) {
+ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", here.val));
+ state->mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+ Tracevv((stderr, "inflate: end of block\n"));
+ state->back = -1;
+ state->mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid literal/length code";
+ state->mode = BAD;
+ break;
+ }
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = LENEXT;
+ /* fallthrough */
+ case LENEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->length += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+ Tracevv((stderr, "inflate: length %u\n", state->length));
+ state->was = state->length;
+ state->mode = DIST;
+ /* fallthrough */
+ case DIST:
+ for (;;) {
+ here = state->distcode[BITS(state->distbits)];
+ if ((unsigned)(here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state->distcode[last.val +
+ (BITS(last.bits + last.op) >> last.bits)];
+ if ((unsigned)(last.bits + here.bits) <= bits) break;
+ PULLBYTE();
+ }
+ DROPBITS(last.bits);
+ state->back += last.bits;
+ }
+ DROPBITS(here.bits);
+ state->back += here.bits;
+ if (here.op & 64) {
+ strm->msg = (char *)"invalid distance code";
+ state->mode = BAD;
+ break;
+ }
+ state->offset = (unsigned)here.val;
+ state->extra = (unsigned)(here.op) & 15;
+ state->mode = DISTEXT;
+ /* fallthrough */
+ case DISTEXT:
+ if (state->extra) {
+ NEEDBITS(state->extra);
+ state->offset += BITS(state->extra);
+ DROPBITS(state->extra);
+ state->back += state->extra;
+ }
+#ifdef INFLATE_STRICT
+ if (state->offset > state->dmax) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#endif
+ Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state->mode = MATCH;
+ /* fallthrough */
+ case MATCH:
+ if (left == 0) goto inf_leave;
+ copy = out - left;
+ if (state->offset > copy) { /* copy from window */
+ copy = state->offset - copy;
+ if (copy > state->whave) {
+ if (state->sane) {
+ strm->msg = (char *)"invalid distance too far back";
+ state->mode = BAD;
+ break;
+ }
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ Trace((stderr, "inflate.c too far\n"));
+ copy -= state->whave;
+ if (copy > state->length) copy = state->length;
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = 0;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+#endif
+ }
+ if (copy > state->wnext) {
+ copy -= state->wnext;
+ from = state->window + (state->wsize - copy);
+ }
+ else
+ from = state->window + (state->wnext - copy);
+ if (copy > state->length) copy = state->length;
+ }
+ else { /* copy from output */
+ from = put - state->offset;
+ copy = state->length;
+ }
+ if (copy > left) copy = left;
+ left -= copy;
+ state->length -= copy;
+ do {
+ *put++ = *from++;
+ } while (--copy);
+ if (state->length == 0) state->mode = LEN;
+ break;
+ case LIT:
+ if (left == 0) goto inf_leave;
+ *put++ = (unsigned char)(state->length);
+ left--;
+ state->mode = LEN;
+ break;
+ case CHECK:
+ if (state->wrap) {
+ NEEDBITS(32);
+ out -= left;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, put - out, out);
+ out = left;
+ if ((state->wrap & 4) && (
+#ifdef GUNZIP
+ state->flags ? hold :
+#endif
+ ZSWAP32(hold)) != state->check) {
+ strm->msg = (char *)"incorrect data check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+#ifdef GUNZIP
+ state->mode = LENGTH;
+ /* fallthrough */
+ case LENGTH:
+ if (state->wrap && state->flags) {
+ NEEDBITS(32);
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
+ strm->msg = (char *)"incorrect length check";
+ state->mode = BAD;
+ break;
+ }
+ INITBITS();
+ Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+#endif
+ state->mode = DONE;
+ /* fallthrough */
+ case DONE:
+ ret = Z_STREAM_END;
+ goto inf_leave;
+ case BAD:
+ ret = Z_DATA_ERROR;
+ goto inf_leave;
+ case MEM:
+ return Z_MEM_ERROR;
+ case SYNC:
+ /* fallthrough */
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+ inf_leave:
+ RESTORE();
+ if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+ (state->mode < CHECK || flush != Z_FINISH)))
+ if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ in -= strm->avail_in;
+ out -= strm->avail_out;
+ strm->total_in += in;
+ strm->total_out += out;
+ state->total += out;
+ if ((state->wrap & 4) && out)
+ strm->adler = state->check =
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
+ strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
+ (state->mode == TYPE ? 128 : 0) +
+ (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
+ if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
+ ret = Z_BUF_ERROR;
+ return ret;
+}
+
+int ZEXPORT inflateEnd(
+ z_streamp strm)
+{
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->window != Z_NULL) ZFREE(strm, state->window);
+ ZFREE(strm, strm->state);
+ strm->state = Z_NULL;
+ Tracev((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+#ifndef Z_FREETYPE
+
+int ZEXPORT inflateGetDictionary(
+ z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength)
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+
+ /* copy dictionary */
+ if (state->whave && dictionary != Z_NULL) {
+ zmemcpy(dictionary, state->window + state->wnext,
+ state->whave - state->wnext);
+ zmemcpy(dictionary + state->whave - state->wnext,
+ state->window, state->wnext);
+ }
+ if (dictLength != Z_NULL)
+ *dictLength = state->whave;
+ return Z_OK;
+}
+
+int ZEXPORT inflateSetDictionary(
+ z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength)
+{
+ struct inflate_state FAR *state;
+ unsigned long dictid;
+ int ret;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (state->wrap != 0 && state->mode != DICT)
+ return Z_STREAM_ERROR;
+
+ /* check for correct dictionary identifier */
+ if (state->mode == DICT) {
+ dictid = adler32(0L, Z_NULL, 0);
+ dictid = adler32(dictid, dictionary, dictLength);
+ if (dictid != state->check)
+ return Z_DATA_ERROR;
+ }
+
+ /* copy dictionary to window using updatewindow(), which will amend the
+ existing dictionary if appropriate */
+ ret = updatewindow(strm, dictionary + dictLength, dictLength);
+ if (ret) {
+ state->mode = MEM;
+ return Z_MEM_ERROR;
+ }
+ state->havedict = 1;
+ Tracev((stderr, "inflate: dictionary set\n"));
+ return Z_OK;
+}
+
+int ZEXPORT inflateGetHeader(
+ z_streamp strm,
+ gz_headerp head)
+{
+ struct inflate_state FAR *state;
+
+ /* check state */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if ((state->wrap & 2) == 0) return Z_STREAM_ERROR;
+
+ /* save header structure */
+ state->head = head;
+ head->done = 0;
+ return Z_OK;
+}
+
+/*
+ Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found
+ or when out of input. When called, *have is the number of pattern bytes
+ found in order so far, in 0..3. On return *have is updated to the new
+ state. If on return *have equals four, then the pattern was found and the
+ return value is how many bytes were read including the last byte of the
+ pattern. If *have is less than four, then the pattern has not been found
+ yet and the return value is len. In the latter case, syncsearch() can be
+ called again with more data and the *have state. *have is initialized to
+ zero for the first call.
+ */
+local unsigned syncsearch(
+ unsigned FAR *have,
+ const unsigned char FAR *buf,
+ unsigned len)
+{
+ unsigned got;
+ unsigned next;
+
+ got = *have;
+ next = 0;
+ while (next < len && got < 4) {
+ if ((int)(buf[next]) == (got < 2 ? 0 : 0xff))
+ got++;
+ else if (buf[next])
+ got = 0;
+ else
+ got = 4 - got;
+ next++;
+ }
+ *have = got;
+ return next;
+}
+
+int ZEXPORT inflateSync(
+ z_streamp strm)
+{
+ unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
+ unsigned long in, out; /* temporary to save total_in and total_out */
+ unsigned char buf[4]; /* to restore bit buffer to byte string */
+ struct inflate_state FAR *state;
+
+ /* check parameters */
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR;
+
+ /* if first time, start search in bit buffer */
+ if (state->mode != SYNC) {
+ state->mode = SYNC;
+ state->hold <<= state->bits & 7;
+ state->bits -= state->bits & 7;
+ len = 0;
+ while (state->bits >= 8) {
+ buf[len++] = (unsigned char)(state->hold);
+ state->hold >>= 8;
+ state->bits -= 8;
+ }
+ state->have = 0;
+ syncsearch(&(state->have), buf, len);
+ }
+
+ /* search available input */
+ len = syncsearch(&(state->have), strm->next_in, strm->avail_in);
+ strm->avail_in -= len;
+ strm->next_in += len;
+ strm->total_in += len;
+
+ /* return no joy or set up to restart inflate() on a new block */
+ if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
+ in = strm->total_in; out = strm->total_out;
+ inflateReset(strm);
+ strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
+ state->mode = TYPE;
+ return Z_OK;
+}
+
+#endif /* !Z_FREETYPE */
+
+/*
+ Returns true if inflate is currently at the end of a block generated by
+ Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ implementation to provide an additional safety check. PPP uses
+ Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored
+ block. When decompressing, PPP checks that at the end of input packet,
+ inflate is waiting for these length bytes.
+ */
+int ZEXPORT inflateSyncPoint(
+ z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ return state->mode == STORED && state->bits == 0;
+}
+
+#ifndef Z_FREETYPE
+
+int ZEXPORT inflateCopy(
+ z_streamp dest,
+ z_streamp source)
+{
+ struct inflate_state FAR *state;
+ struct inflate_state FAR *copy;
+ unsigned char FAR *window;
+ unsigned wsize;
+
+ /* check input */
+ if (inflateStateCheck(source) || dest == Z_NULL)
+ return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)source->state;
+
+ /* allocate space */
+ copy = (struct inflate_state FAR *)
+ ZALLOC(source, 1, sizeof(struct inflate_state));
+ if (copy == Z_NULL) return Z_MEM_ERROR;
+ window = Z_NULL;
+ if (state->window != Z_NULL) {
+ window = (unsigned char FAR *)
+ ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+ if (window == Z_NULL) {
+ ZFREE(source, copy);
+ return Z_MEM_ERROR;
+ }
+ }
+
+ /* copy state */
+ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
+ zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+ copy->strm = dest;
+ if (state->lencode >= state->codes &&
+ state->lencode <= state->codes + ENOUGH - 1) {
+ copy->lencode = copy->codes + (state->lencode - state->codes);
+ copy->distcode = copy->codes + (state->distcode - state->codes);
+ }
+ copy->next = copy->codes + (state->next - state->codes);
+ if (window != Z_NULL) {
+ wsize = 1U << state->wbits;
+ zmemcpy(window, state->window, wsize);
+ }
+ copy->window = window;
+ dest->state = (struct internal_state FAR *)copy;
+ return Z_OK;
+}
+
+#endif /* !Z_FREETYPE */
+
+int ZEXPORT inflateUndermine(
+ z_streamp strm,
+ int subvert)
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+ state->sane = !subvert;
+ return Z_OK;
+#else
+ (void)subvert;
+ state->sane = 1;
+ return Z_DATA_ERROR;
+#endif
+}
+
+int ZEXPORT inflateValidate(
+ z_streamp strm,
+ int check)
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+ state = (struct inflate_state FAR *)strm->state;
+ if (check && state->wrap)
+ state->wrap |= 4;
+ else
+ state->wrap &= ~4;
+ return Z_OK;
+}
+
+#ifndef Z_FREETYPE
+
+long ZEXPORT inflateMark(
+ z_streamp strm)
+{
+ struct inflate_state FAR *state;
+
+ if (inflateStateCheck(strm))
+ return -(1L << 16);
+ state = (struct inflate_state FAR *)strm->state;
+ return (long)(((unsigned long)((long)state->back)) << 16) +
+ (state->mode == COPY ? state->length :
+ (state->mode == MATCH ? state->was - state->length : 0));
+}
+
+unsigned long ZEXPORT inflateCodesUsed(
+ z_streamp strm)
+{
+ struct inflate_state FAR *state;
+ if (inflateStateCheck(strm)) return (unsigned long)-1;
+ state = (struct inflate_state FAR *)strm->state;
+ return (unsigned long)(state->next - state->codes);
}
+#endif /* !Z_FREETYPE */
diff --git a/thirdparty/freetype/src/gzip/inflate.h b/thirdparty/freetype/src/gzip/inflate.h
new file mode 100644
index 0000000000..c6f5a52e16
--- /dev/null
+++ b/thirdparty/freetype/src/gzip/inflate.h
@@ -0,0 +1,131 @@
+/* inflate.h -- internal inflate state definition
+ * Copyright (C) 1995-2019 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef INFLATE_H
+#define INFLATE_H
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* define NO_GZIP when compiling if you want to disable gzip header and
+ trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
+ the crc code when it is not needed. For shared libraries, gzip decoding
+ should be left enabled. */
+#ifndef NO_GZIP
+# define GUNZIP
+#endif
+
+/* Possible inflate modes between inflate() calls */
+typedef enum {
+ HEAD = 16180, /* i: waiting for magic header */
+ FLAGS, /* i: waiting for method and flags (gzip) */
+ TIME, /* i: waiting for modification time (gzip) */
+ OS, /* i: waiting for extra flags and operating system (gzip) */
+ EXLEN, /* i: waiting for extra length (gzip) */
+ EXTRA, /* i: waiting for extra bytes (gzip) */
+ NAME, /* i: waiting for end of file name (gzip) */
+ COMMENT, /* i: waiting for end of comment (gzip) */
+ HCRC, /* i: waiting for header crc (gzip) */
+ DICTID, /* i: waiting for dictionary check value */
+ DICT, /* waiting for inflateSetDictionary() call */
+ TYPE, /* i: waiting for type bits, including last-flag bit */
+ TYPEDO, /* i: same, but skip check to exit inflate on new block */
+ STORED, /* i: waiting for stored size (length and complement) */
+ COPY_, /* i/o: same as COPY below, but only first time in */
+ COPY, /* i/o: waiting for input or output to copy stored block */
+ TABLE, /* i: waiting for dynamic block table lengths */
+ LENLENS, /* i: waiting for code length code lengths */
+ CODELENS, /* i: waiting for length/lit and distance code lengths */
+ LEN_, /* i: same as LEN below, but only first time in */
+ LEN, /* i: waiting for length/lit/eob code */
+ LENEXT, /* i: waiting for length extra bits */
+ DIST, /* i: waiting for distance code */
+ DISTEXT, /* i: waiting for distance extra bits */
+ MATCH, /* o: waiting for output space to copy string */
+ LIT, /* o: waiting for output space to write literal */
+ CHECK, /* i: waiting for 32-bit check value */
+ LENGTH, /* i: waiting for 32-bit length (gzip) */
+ DONE, /* finished check, done -- remain here until reset */
+ BAD, /* got a data error -- remain here until reset */
+ MEM, /* got an inflate() memory error -- remain here until reset */
+ SYNC /* looking for synchronization bytes to restart inflate() */
+} inflate_mode;
+
+/*
+ State transitions between above modes -
+
+ (most modes can go to BAD or MEM on error -- not shown for clarity)
+
+ Process header:
+ HEAD -> (gzip) or (zlib) or (raw)
+ (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
+ HCRC -> TYPE
+ (zlib) -> DICTID or TYPE
+ DICTID -> DICT -> TYPE
+ (raw) -> TYPEDO
+ Read deflate blocks:
+ TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
+ STORED -> COPY_ -> COPY -> TYPE
+ TABLE -> LENLENS -> CODELENS -> LEN_
+ LEN_ -> LEN
+ Read deflate codes in fixed or dynamic block:
+ LEN -> LENEXT or LIT or TYPE
+ LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
+ LIT -> LEN
+ Process trailer:
+ CHECK -> LENGTH -> DONE
+ */
+
+/* State maintained between inflate() calls -- approximately 7K bytes, not
+ including the allocated sliding window, which is up to 32K bytes. */
+struct inflate_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ inflate_mode mode; /* current inflate mode */
+ int last; /* true if processing last block */
+ int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
+ bit 2 true to validate check value */
+ int havedict; /* true if dictionary provided */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
+ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
+ unsigned long check; /* protected copy of check value */
+ unsigned long total; /* protected copy of output count */
+ gz_headerp head; /* where to save gzip header information */
+ /* sliding window */
+ unsigned wbits; /* log base 2 of requested window size */
+ unsigned wsize; /* window size or zero if not using window */
+ unsigned whave; /* valid bytes in the window */
+ unsigned wnext; /* window write index */
+ unsigned char FAR *window; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ unsigned long hold; /* input bit accumulator */
+ unsigned bits; /* number of bits in "in" */
+ /* for string and stored block copying */
+ unsigned length; /* literal or length of data to copy */
+ unsigned offset; /* distance back to copy string from */
+ /* for table and code decoding */
+ unsigned extra; /* extra bits needed */
+ /* fixed and dynamic code tables */
+ code const FAR *lencode; /* starting table for length/literal codes */
+ code const FAR *distcode; /* starting table for distance codes */
+ unsigned lenbits; /* index bits for lencode */
+ unsigned distbits; /* index bits for distcode */
+ /* dynamic table building */
+ unsigned ncode; /* number of code length code lengths */
+ unsigned nlen; /* number of length code lengths */
+ unsigned ndist; /* number of distance code lengths */
+ unsigned have; /* number of code lengths in lens[] */
+ code FAR *next; /* next available space in codes[] */
+ unsigned short lens[320]; /* temporary storage for code lengths */
+ unsigned short work[288]; /* work area for code table building */
+ code codes[ENOUGH]; /* space for code tables */
+ int sane; /* if false, allow invalid distance too far */
+ int back; /* bits back of last unprocessed length/lit */
+ unsigned was; /* initial length of match */
+};
+
+#endif /* INFLATE_H */
diff --git a/thirdparty/freetype/src/gzip/inftrees.c b/thirdparty/freetype/src/gzip/inftrees.c
index 56f52b1701..0b58b29b1b 100644
--- a/thirdparty/freetype/src/gzip/inftrees.c
+++ b/thirdparty/freetype/src/gzip/inftrees.c
@@ -1,20 +1,15 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2002 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
-#if !defined(BUILDFIXED) && !defined(STDC)
-# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */
-#endif
+#define MAXBITS 15
-
-#if 0
-local const char inflate_copyright[] =
- " inflate 1.1.4 Copyright 1995-2002 Mark Adler ";
-#endif
+const char inflate_copyright[] =
+ " inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -22,447 +17,288 @@ local const char inflate_copyright[] =
copyright string in the executable of your product.
*/
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-local int huft_build OF((
- uIntf *, /* code lengths in bits */
- uInt, /* number of codes */
- uInt, /* number of "simple" codes */
- const uIntf *, /* list of base values for non-simple codes */
- const uIntf *, /* list of extra bits for non-simple codes */
- inflate_huft * FAR*,/* result: starting table */
- uIntf *, /* maximum lookup bits (returns actual) */
- inflate_huft *, /* space for trees */
- uInt *, /* hufts used in space */
- uIntf * )); /* space for values */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+ */
+int ZLIB_INTERNAL inflate_table(
+ codetype type,
+ unsigned short FAR *lens,
+ unsigned codes,
+ code FAR * FAR *table,
+ unsigned FAR *bits,
+ unsigned short FAR *work)
+{
+ unsigned len; /* a code's length in bits */
+ unsigned sym; /* index of code symbols */
+ unsigned min, max; /* minimum and maximum code lengths */
+ unsigned root; /* number of index bits for root table */
+ unsigned curr; /* number of index bits for current table */
+ unsigned drop; /* code bits to drop for sub-table */
+ int left; /* number of prefix codes available */
+ unsigned used; /* code entries in table used */
+ unsigned huff; /* Huffman code */
+ unsigned incr; /* for incrementing code, index */
+ unsigned fill; /* index for replicating entries */
+ unsigned low; /* low bits for current root entry */
+ unsigned mask; /* mask for low root bits */
+ code here; /* table entry for duplication */
+ code FAR *next; /* next available space in table */
+ const unsigned short FAR *base; /* base value table to use */
+ const unsigned short FAR *extra; /* extra bits table to use */
+ unsigned match; /* use base and extra for symbol >= match */
+ unsigned short count[MAXBITS+1]; /* number of codes of each length */
+ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */
+ static const unsigned short lbase[31] = { /* Length codes 257..285 base */
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
- /* see note #13 above about 258 */
-local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
- 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
-local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
+ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
- 8193, 12289, 16385, 24577};
-local const uInt cpdext[30] = { /* Extra bits for distance codes */
- 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
- 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
- 12, 12, 13, 13};
-
-/*
- Huffman code decoding is performed using a multi-level table lookup.
- The fastest way to decode is to simply build a lookup table whose
- size is determined by the longest code. However, the time it takes
- to build this table can also be a factor if the data being decoded
- is not very long. The most common codes are necessarily the
- shortest codes, so those codes dominate the decoding time, and hence
- the speed. The idea is you can have a shorter table that decodes the
- shorter, more probable codes, and then point to subsidiary tables for
- the longer codes. The time it costs to decode the longer codes is
- then traded against the time it takes to make longer tables.
-
- This results of this trade are in the variables lbits and dbits
- below. lbits is the number of bits the first level table for literal/
- length codes can decode in one step, and dbits is the same thing for
- the distance codes. Subsequent tables are also less than or equal to
- those sizes. These values may be adjusted either when all of the
- codes are shorter than that, in which case the longest code length in
- bits is used, or when the shortest code is *longer* than the requested
- table size, in which case the length of the shortest code in bits is
- used.
-
- There are two different values for the two tables, since they code a
- different number of possibilities each. The literal/length table
- codes 286 possible values, or in a flat code, a little over eight
- bits. The distance table codes 30 possible values, or a little less
- than five bits, flat. The optimum values for speed end up being
- about one bit more than those, so lbits is 8+1 and dbits is 5+1.
- The optimum values may differ though from machine to machine, and
- possibly even between compilers. Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15 /* maximum bit length of any code */
-
-local int huft_build( /* b, n, s, d, e, t, m, hp, hn, v) */
-uIntf *b, /* code lengths in bits (all assumed <= BMAX) */
-uInt n, /* number of codes (assumed <= 288) */
-uInt s, /* number of simple-valued codes (0..s-1) */
-const uIntf *d, /* list of base values for non-simple codes */
-const uIntf *e, /* list of extra bits for non-simple codes */
-inflate_huft * FAR *t, /* result: starting table */
-uIntf *m, /* maximum lookup bits, returns actual */
-inflate_huft *hp, /* space for trees */
-uInt *hn, /* hufts used in space */
-uIntf *v /* working area: values in order of bit length */
-/* Given a list of code lengths and a maximum table size, make a set of
- tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
- if the given code set is incomplete (the tables are still built in this
- case), or Z_DATA_ERROR if the input is invalid. */
-)
-{
+ 8193, 12289, 16385, 24577, 0, 0};
+ static const unsigned short dext[32] = { /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64};
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = *bits;
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) { /* no symbols to code at all */
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)1;
+ here.val = (unsigned short)0;
+ *(*table)++ = here; /* make a table to force an error */
+ *(*table)++ = here;
+ *bits = 1;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1))
+ return -1; /* incomplete set */
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ match = 20;
+ break;
+ case LENS:
+ base = lbase;
+ extra = lext;
+ match = 257;
+ break;
+ default: /* DISTS */
+ base = dbase;
+ extra = dext;
+ match = 0;
+ }
- uInt a; /* counter for codes of length k */
- uInt c[BMAX+1]; /* bit length count table */
- uInt f; /* i repeats in table every f entries */
- int g; /* maximum code length */
- int h; /* table level */
- uInt i; /* counter, current code */
- uInt j; /* counter */
- int k; /* number of bits in current code */
- int l; /* bits per table (returned in m) */
- uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */
- uIntf *p; /* pointer into c[], b[], or v[] */
- inflate_huft *q; /* points to current table */
- struct inflate_huft_s r; /* table entry for structure assignment */
- inflate_huft *u[BMAX]; /* table stack */
- int w; /* bits before this table == (l * h) */
- uInt x[BMAX+1]; /* bit offsets, then code stack */
- uIntf *xp; /* pointer into x */
- int y; /* number of dummy codes added */
- uInt z; /* number of entries in current table */
-
-
- /* Make compiler happy */
- r.base = 0;
-
- /* Generate counts for each bit length */
- p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
- C4 /* clear c[]--assume BMAX+1 is 16 */
- p = b; i = n;
- do {
- c[*p++]++; /* assume all entries <= BMAX */
- } while (--i);
- if (c[0] == n) /* null input--all zero length codes */
- {
- *t = (inflate_huft *)Z_NULL;
- *m = 0;
- return Z_OK;
- }
-
-
- /* Find minimum and maximum length, bound *m by those */
- l = *m;
- for (j = 1; j <= BMAX; j++)
- if (c[j])
- break;
- k = j; /* minimum code length */
- if ((uInt)l < j)
- l = j;
- for (i = BMAX; i; i--)
- if (c[i])
- break;
- g = i; /* maximum code length */
- if ((uInt)l > i)
- l = i;
- *m = l;
-
-
- /* Adjust last length count to fill out codes, if needed */
- for (y = 1 << j; j < i; j++, y <<= 1)
- if ((y -= c[j]) < 0)
- return Z_DATA_ERROR;
- if ((y -= c[i]) < 0)
- return Z_DATA_ERROR;
- c[i] += y;
-
-
- /* Generate starting offsets into the value table for each length */
- x[1] = j = 0;
- p = c + 1; xp = x + 2;
- while (--i) { /* note that i == g from above */
- *xp++ = (j += *p++);
- }
-
-
- /* Make a table of values in order of bit lengths */
- p = b; i = 0;
- do {
- if ((j = *p++) != 0)
- v[x[j]++] = i;
- } while (++i < n);
- n = x[g]; /* set n to length of v */
-
-
- /* Generate the Huffman codes and for each, make the table entries */
- x[0] = i = 0; /* first Huffman code is zero */
- p = v; /* grab values in bit order */
- h = -1; /* no tables yet--level -1 */
- w = -l; /* bits decoded == (l * h) */
- u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
- q = (inflate_huft *)Z_NULL; /* ditto */
- z = 0; /* ditto */
-
- /* go through the bit lengths (k already is bits in shortest code) */
- for (; k <= g; k++)
- {
- a = c[k];
- while (a--)
- {
- /* here i is the Huffman code of length k bits for value *p */
- /* make tables up to required level */
- while (k > w + l)
- {
- h++;
- w += l; /* previous table always l bits */
-
- /* compute minimum size table less than or equal to l bits */
- z = g - w;
- z = z > (uInt)l ? (uInt)l : z; /* table size upper limit */
- if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
- { /* too few codes for k-w bit table */
- f -= a + 1; /* deduct codes from patterns left */
- xp = c + k;
- if (j < z)
- while (++j < z) /* try smaller tables up to z bits */
- {
- if ((f <<= 1) <= *++xp)
- break; /* enough codes to use up j bits */
- f -= *xp; /* else deduct codes from patterns */
- }
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = *table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = (unsigned)(-1); /* trigger new sub-table when len > root */
+ used = 1U << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here.bits = (unsigned char)(len - drop);
+ if (work[sym] + 1U < match) {
+ here.op = (unsigned char)0;
+ here.val = work[sym];
}
- z = 1 << j; /* table entries for j-bit table */
-
- /* allocate new table */
- if (*hn + z > MANY) /* (note: doesn't matter for fixed) */
- return Z_DATA_ERROR; /* overflow of MANY */
- u[h] = q = hp + *hn;
- *hn += z;
-
- /* connect to last table, if there is one */
- if (h)
- {
- x[h] = i; /* save pattern for backing up */
- r.bits = (Byte)l; /* bits to dump before this table */
- r.exop = (Byte)j; /* bits in this table */
- j = i >> (w - l);
- r.base = (uInt)(q - u[h-1] - j); /* offset to this table */
- u[h-1][j] = r; /* connect to last table */
+ else if (work[sym] >= match) {
+ here.op = (unsigned char)(extra[work[sym] - match]);
+ here.val = base[work[sym] - match];
+ }
+ else {
+ here.op = (unsigned char)(32 + 64); /* end of block */
+ here.val = 0;
}
- else
- *t = q; /* first table is returned result */
- }
-
- /* set up table entry in r */
- r.bits = (Byte)(k - w);
- if (p >= v + n)
- r.exop = 128 + 64; /* out of values--invalid code */
- else if (*p < s)
- {
- r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
- r.base = *p++; /* simple code is just the value */
- }
- else
- {
- r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
- r.base = d[*p++ - s];
- }
-
- /* fill code-like entries with r */
- f = 1 << (k - w);
- for (j = i >> w; j < z; j += f)
- q[j] = r;
-
- /* backwards increment the k-bit code i */
- for (j = 1 << (k - 1); i & j; j >>= 1)
- i ^= j;
- i ^= j;
-
- /* backup over finished tables */
- mask = (1 << w) - 1; /* needed on HP, cc -O bug */
- while ((i & mask) != x[h])
- {
- h--; /* don't need to update q */
- w -= l;
- mask = (1 << w) - 1;
- }
- }
- }
-
-
- /* Return Z_BUF_ERROR if we were given an incomplete table */
- return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1U << (len - drop);
+ fill = 1U << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ next[(huff >> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1U << (len - 1);
+ while (huff & incr)
+ incr >>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
-local int inflate_trees_bits( /* c, bb, tb, hp, z) */
-uIntf *c, /* 19 code lengths */
-uIntf *bb, /* bits tree desired/actual depth */
-inflate_huft * FAR *tb, /* bits tree result */
-inflate_huft *hp, /* space for trees */
-z_streamp z /* for messages */
-)
-{
- int r;
- uInt hn = 0; /* hufts used in space */
- uIntf *v; /* work area for huft_build */
-
- if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
- return Z_MEM_ERROR;
- r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL,
- tb, bb, hp, &hn, v);
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed dynamic bit lengths tree";
- else if (r == Z_BUF_ERROR || *bb == 0)
- {
- z->msg = (char*)"incomplete dynamic bit lengths tree";
- r = Z_DATA_ERROR;
- }
- ZFREE(z, v);
- return r;
-}
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[work[sym]];
+ }
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (int)(1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
-local int inflate_trees_dynamic( /* nl, nd, c, bl, bd, tl, td, hp, z) */
-uInt nl, /* number of literal/length codes */
-uInt nd, /* number of distance codes */
-uIntf *c, /* that many (total) code lengths */
-uIntf *bl, /* literal desired/actual bit depth */
-uIntf *bd, /* distance desired/actual bit depth */
-inflate_huft * FAR *tl, /* literal/length tree result */
-inflate_huft * FAR *td, /* distance tree result */
-inflate_huft *hp, /* space for trees */
-z_streamp z /* for messages */
-)
-{
- int r;
- uInt hn = 0; /* hufts used in space */
- uIntf *v; /* work area for huft_build */
-
- /* allocate work area */
- if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
- return Z_MEM_ERROR;
-
- /* build literal/length tree */
- r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
- if (r != Z_OK || *bl == 0)
- {
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed literal/length tree";
- else if (r != Z_MEM_ERROR)
- {
- z->msg = (char*)"incomplete literal/length tree";
- r = Z_DATA_ERROR;
- }
- ZFREE(z, v);
- return r;
- }
-
- /* build distance tree */
- r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
- if (r != Z_OK || (*bd == 0 && nl > 257))
- {
- if (r == Z_DATA_ERROR)
- z->msg = (char*)"oversubscribed distance tree";
- else if (r == Z_BUF_ERROR) {
-#if 0
- {
-#endif
-#ifdef PKZIP_BUG_WORKAROUND
- r = Z_OK;
- }
-#else
- z->msg = (char*)"incomplete distance tree";
- r = Z_DATA_ERROR;
- }
- else if (r != Z_MEM_ERROR)
- {
- z->msg = (char*)"empty distance tree with lengths";
- r = Z_DATA_ERROR;
+ /* check for enough space */
+ used += 1U << curr;
+ if ((type == LENS && used > ENOUGH_LENS) ||
+ (type == DISTS && used > ENOUGH_DISTS))
+ return 1;
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ (*table)[low].op = (unsigned char)curr;
+ (*table)[low].bits = (unsigned char)root;
+ (*table)[low].val = (unsigned short)(next - *table);
+ }
}
- ZFREE(z, v);
- return r;
-#endif
- }
-
- /* done */
- ZFREE(z, v);
- return Z_OK;
-}
-
-/* build fixed tables only once--keep them here */
-#ifdef BUILDFIXED
-local int fixed_built = 0;
-#define FIXEDH 544 /* number of hufts used by fixed tables */
-local inflate_huft fixed_mem[FIXEDH];
-local uInt fixed_bl;
-local uInt fixed_bd;
-local inflate_huft *fixed_tl;
-local inflate_huft *fixed_td;
-#else
-#include "inffixed.h"
-#endif
-
-
-local int inflate_trees_fixed( /* bl, bd, tl, td, z) */
-uIntf *bl, /* literal desired/actual bit depth */
-uIntf *bd, /* distance desired/actual bit depth */
-const inflate_huft * FAR *tl, /* literal/length tree result */
-const inflate_huft * FAR *td, /* distance tree result */
-z_streamp z /* for memory allocation */
-)
-{
-#ifdef BUILDFIXED
- /* build fixed tables if not already */
- if (!fixed_built)
- {
- int k; /* temporary variable */
- uInt f = 0; /* number of hufts used in fixed_mem */
- uIntf *c; /* length list for huft_build */
- uIntf *v; /* work area for huft_build */
-
- /* allocate memory */
- if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
- return Z_MEM_ERROR;
- if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
- {
- ZFREE(z, c);
- return Z_MEM_ERROR;
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ here.op = (unsigned char)64; /* invalid code marker */
+ here.bits = (unsigned char)(len - drop);
+ here.val = (unsigned short)0;
+ next[huff] = here;
}
- /* literal table */
- for (k = 0; k < 144; k++)
- c[k] = 8;
- for (; k < 256; k++)
- c[k] = 9;
- for (; k < 280; k++)
- c[k] = 7;
- for (; k < 288; k++)
- c[k] = 8;
- fixed_bl = 9;
- huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl,
- fixed_mem, &f, v);
-
- /* distance table */
- for (k = 0; k < 30; k++)
- c[k] = 5;
- fixed_bd = 5;
- huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd,
- fixed_mem, &f, v);
-
- /* done */
- ZFREE(z, v);
- ZFREE(z, c);
- fixed_built = 1;
- }
-#else
- FT_UNUSED(z);
-#endif
- *bl = fixed_bl;
- *bd = fixed_bd;
- *tl = fixed_tl;
- *td = fixed_td;
- return Z_OK;
+ /* set return parameters */
+ *table += used;
+ *bits = root;
+ return 0;
}
diff --git a/thirdparty/freetype/src/gzip/inftrees.h b/thirdparty/freetype/src/gzip/inftrees.h
index 07bf2aa0bf..c94eb78b5d 100644
--- a/thirdparty/freetype/src/gzip/inftrees.h
+++ b/thirdparty/freetype/src/gzip/inftrees.h
@@ -1,63 +1,67 @@
/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-2002 Mark Adler
+ * Copyright (C) 1995-2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
+#ifndef INFTREES_H
+#define INFTREES_H
+
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/
-/* Huffman code lookup table entry--this entry is four bytes for machines
- that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-#ifndef _INFTREES_H
-#define _INFTREES_H
-
-typedef struct inflate_huft_s FAR inflate_huft;
-
-struct inflate_huft_s {
- union {
- struct {
- Byte Exop; /* number of extra bits or operation */
- Byte Bits; /* number of bits in this code or subcode */
- } what;
- uInt pad; /* pad structure to a power of 2 (4 bytes for */
- } word; /* 16-bit, 8 bytes for 32-bit int's) */
- uInt base; /* literal, length base, distance base,
- or table offset */
-};
-
-/* Maximum size of dynamic tree. The maximum found in a long but non-
- exhaustive search was 1004 huft structures (850 for length/literals
- and 154 for distances, the latter actually the result of an
- exhaustive search). The actual maximum is not known, but the
- value below is more than safe. */
-#define MANY 1440
-
-local int inflate_trees_bits OF((
- uIntf *, /* 19 code lengths */
- uIntf *, /* bits tree desired/actual depth */
- inflate_huft * FAR *, /* bits tree result */
- inflate_huft *, /* space for trees */
- z_streamp)); /* for messages */
-
-local int inflate_trees_dynamic OF((
- uInt, /* number of literal/length codes */
- uInt, /* number of distance codes */
- uIntf *, /* that many (total) code lengths */
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- inflate_huft * FAR *, /* literal/length tree result */
- inflate_huft * FAR *, /* distance tree result */
- inflate_huft *, /* space for trees */
- z_streamp)); /* for messages */
-
-local int inflate_trees_fixed OF((
- uIntf *, /* literal desired/actual bit depth */
- uIntf *, /* distance desired/actual bit depth */
- const inflate_huft * FAR *, /* literal/length tree result */
- const inflate_huft * FAR *, /* distance tree result */
- z_streamp)); /* for memory allocation */
-
-#endif /* _INFTREES_H */
+/* Structure for decoding tables. Each entry provides either the
+ information needed to do the operation requested by the code that
+ indexed that table entry, or it provides a pointer to another
+ table that indexes more bits of the code. op indicates whether
+ the entry is a pointer to another table, a literal, a length or
+ distance, an end-of-block, or an invalid code. For a table
+ pointer, the low four bits of op is the number of index bits of
+ that table. For a length or distance, the low four bits of op
+ is the number of extra bits to get after the code. bits is
+ the number of bits in this code or part of the code to drop off
+ of the bit buffer. val is the actual byte to output in the case
+ of a literal, the base length or distance, or the offset from
+ the current table to the next table. Each entry is four bytes. */
+typedef struct {
+ unsigned char op; /* operation, extra bits, table bits */
+ unsigned char bits; /* bits in this part of the code */
+ unsigned short val; /* offset in table or code value */
+} code;
+
+/* op values as set by inflate_table():
+ 00000000 - literal
+ 0000tttt - table link, tttt != 0 is the number of table index bits
+ 0001eeee - length or distance, eeee is the number of extra bits
+ 01100000 - end of block
+ 01000000 - invalid code
+ */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribtution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+ The initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+#define ENOUGH_LENS 852
+#define ENOUGH_DISTS 592
+#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
+
+/* Type of code to build for inflate_table() */
+typedef enum {
+ CODES,
+ LENS,
+ DISTS
+} codetype;
+
+int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
+ unsigned codes, code FAR * FAR *table,
+ unsigned FAR *bits, unsigned short FAR *work));
+
+#endif /* INFTREES_H_ */
diff --git a/thirdparty/freetype/src/gzip/infutil.c b/thirdparty/freetype/src/gzip/infutil.c
deleted file mode 100644
index 6087b40647..0000000000
--- a/thirdparty/freetype/src/gzip/infutil.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/* inflate_util.c -- data and routines common to blocks and codes
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-#include "zutil.h"
-#include "infblock.h"
-#include "inftrees.h"
-#include "infcodes.h"
-#include "infutil.h"
-
-
-/* And'ing with mask[n] masks the lower n bits */
-local const uInt inflate_mask[17] = {
- 0x0000,
- 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
- 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush( /* s, z, r) */
-inflate_blocks_statef *s,
-z_streamp z,
-int r )
-{
- uInt n;
- Bytef *p;
- Bytef *q;
-
- /* local copies of source and destination pointers */
- p = z->next_out;
- q = s->read;
-
- /* compute number of bytes to copy as far as end of window */
- n = (uInt)((q <= s->write ? s->write : s->end) - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy as far as end of window */
- zmemcpy(p, q, n);
- p += n;
- q += n;
-
- /* see if more to copy at beginning of window */
- if (q == s->end)
- {
- /* wrap pointers */
- q = s->window;
- if (s->write == s->end)
- s->write = s->window;
-
- /* compute bytes to copy */
- n = (uInt)(s->write - q);
- if (n > z->avail_out) n = z->avail_out;
- if (n && r == Z_BUF_ERROR) r = Z_OK;
-
- /* update counters */
- z->avail_out -= n;
- z->total_out += n;
-
- /* update check information */
- if (s->checkfn != Z_NULL)
- z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
- /* copy */
- zmemcpy(p, q, n);
- p += n;
- q += n;
- }
-
- /* update pointers */
- z->next_out = p;
- s->read = q;
-
- /* done */
- return r;
-}
diff --git a/thirdparty/freetype/src/gzip/infutil.h b/thirdparty/freetype/src/gzip/infutil.h
deleted file mode 100644
index cdf18b4f90..0000000000
--- a/thirdparty/freetype/src/gzip/infutil.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995-2002 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFUTIL_H
-#define _INFUTIL_H
-
-typedef enum {
- TYPE, /* get type bits (3, including end bit) */
- LENS, /* get lengths for stored */
- STORED, /* processing stored block */
- TABLE, /* get table lengths */
- BTREE, /* get bit lengths tree for a dynamic block */
- DTREE, /* get length, distance trees for a dynamic block */
- CODES, /* processing fixed or dynamic block */
- DRY, /* output remaining window bytes */
- DONE, /* finished last block, done */
- BAD} /* got a data error--stuck here */
-inflate_block_mode;
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
- /* mode */
- inflate_block_mode mode; /* current inflate_block mode */
-
- /* mode dependent information */
- union {
- uInt left; /* if STORED, bytes left to copy */
- struct {
- uInt table; /* table lengths (14 bits) */
- uInt index; /* index into blens (or border) */
- uIntf *blens; /* bit lengths of codes */
- uInt bb; /* bit length tree depth */
- inflate_huft *tb; /* bit length decoding tree */
- } trees; /* if DTREE, decoding info for trees */
- struct {
- inflate_codes_statef
- *codes;
- } decode; /* if CODES, current state */
- } sub; /* submode */
- uInt last; /* true if this block is the last block */
-
- /* mode independent information */
- uInt bitk; /* bits in bit buffer */
- uLong bitb; /* bit buffer */
- inflate_huft *hufts; /* single malloc for tree space */
- Bytef *window; /* sliding window */
- Bytef *end; /* one byte after sliding window */
- Bytef *read; /* window read pointer */
- Bytef *write; /* window write pointer */
- check_func checkfn; /* check function */
- uLong check; /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/* update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/* get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/* output bytes */
-#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/* load local pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
-#ifndef NO_INFLATE_MASK
-local const uInt inflate_mask[17];
-#endif
-
-/* copy as much as possible from the sliding window to the output area */
-local int inflate_flush OF((
- inflate_blocks_statef *,
- z_streamp ,
- int));
-
-#endif
diff --git a/thirdparty/freetype/src/gzip/zlib.h b/thirdparty/freetype/src/gzip/zlib.h
index a4e82c6a02..d760140c2e 100644
--- a/thirdparty/freetype/src/gzip/zlib.h
+++ b/thirdparty/freetype/src/gzip/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.1.4, March 11th, 2002
+ version 1.2.12, March 11th, 2022
- Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -24,12 +24,12 @@
The data format used by the zlib library is described by RFCs (Request for
- Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
- (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
*/
-#ifndef _ZLIB_H
-#define _ZLIB_H
+#ifndef ZLIB_H
+#define ZLIB_H
#include "ftzconf.h"
@@ -37,27 +37,45 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.1.4"
+#define ZLIB_VERSION "1.2.12"
+#define ZLIB_VERNUM 0x12c0
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 12
+#define ZLIB_VER_SUBREVISION 0
/*
- The 'zlib' compression library provides in-memory compression and
- decompression functions, including integrity checks of the uncompressed
- data. This version of the library supports only one compression method
- (deflation) but other algorithms will be added later and will have the same
- stream interface.
-
- Compression can be done in a single step if the buffers are large
- enough (for example if an input file is mmap'ed), or can be done by
- repeated calls of the compression function. In the latter case, the
- application must provide more input and/or consume the output
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed data.
+ This version of the library supports only one compression method (deflation)
+ but other algorithms will be added later and will have the same stream
+ interface.
+
+ Compression can be done in a single step if the buffers are large enough,
+ or can be done by repeated calls of the compression function. In the latter
+ case, the application must provide more input and/or consume the output
(providing more output space) before each call.
- The library also supports reading and writing files in gzip (.gz) format
- with an interface similar to that of stdio.
+ The compressed data format used by default by the in-memory functions is
+ the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+ around a deflate stream, which is itself documented in RFC 1951.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio using the functions that start
+ with "gz". The gzip format is different from the zlib format. gzip is a
+ gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+ This library can optionally read and write gzip and raw deflate streams in
+ memory as well.
- The library does not install any signal handler. The decoder checks
- the consistency of the compressed data, so the library should never
- crash even in case of corrupted input.
+ The zlib format was designed to be compact and fast for use in memory
+ and on communications channels. The gzip format was designed for single-
+ file compression on file systems, has a larger header than zlib to maintain
+ directory information, and uses a different, slower check method than zlib.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never crash
+ even in the case of corrupted input.
*/
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
@@ -66,68 +84,95 @@ typedef void (*free_func) OF((voidpf opaque, voidpf address));
struct internal_state;
typedef struct z_stream_s {
- Bytef *next_in; /* next input byte */
+ z_const Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
- uLong total_in; /* total nb of input bytes read so far */
+ uLong total_in; /* total number of input bytes read so far */
- Bytef *next_out; /* next output byte should be put there */
+ Bytef *next_out; /* next output byte will go here */
uInt avail_out; /* remaining free space at next_out */
- uLong total_out; /* total nb of bytes output so far */
+ uLong total_out; /* total number of bytes output so far */
- char *msg; /* last error message, NULL if no error */
+ z_const char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */
- int data_type; /* best guess about the data type: ascii or binary */
- uLong adler; /* adler32 value of the uncompressed data */
+ int data_type; /* best guess about the data type: binary or text
+ for deflate, or the decoding state for inflate */
+ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
typedef z_stream FAR *z_streamp;
/*
- The application must update next_in and avail_in when avail_in has
- dropped to zero. It must update next_out and avail_out when avail_out
- has dropped to zero. The application must initialize zalloc, zfree and
- opaque before calling the init function. All other fields are set by the
- compression library and must not be updated by the application.
+ gzip header information passed to and from zlib routines. See RFC 1952
+ for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+ int text; /* true if compressed data believed to be text */
+ uLong time; /* modification time */
+ int xflags; /* extra flags (not used when writing a gzip file) */
+ int os; /* operating system */
+ Bytef *extra; /* pointer to extra field or Z_NULL if none */
+ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */
+ uInt extra_max; /* space at extra (only when reading header) */
+ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */
+ uInt name_max; /* space at name (only when reading header) */
+ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */
+ uInt comm_max; /* space at comment (only when reading header) */
+ int hcrc; /* true if there was or will be a header crc */
+ int done; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
- The opaque value provided by the application will be passed as the first
- parameter for calls of zalloc and zfree. This can be useful for custom
- memory management. The compression library attaches no meaning to the
+/*
+ The application must update next_in and avail_in when avail_in has dropped
+ to zero. It must update next_out and avail_out when avail_out has dropped
+ to zero. The application must initialize zalloc, zfree and opaque before
+ calling the init function. All other fields are set by the compression
+ library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
opaque value.
- zalloc must return Z_NULL if there is not enough memory for the object.
+ zalloc must return Z_NULL if there is not enough memory for the object.
If zlib is used in a multi-threaded application, zalloc and zfree must be
- thread safe.
-
- On 16-bit systems, the functions zalloc and zfree must be able to allocate
- exactly 65536 bytes, but will not be required to allocate more than this
- if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
- pointers returned by zalloc for objects of exactly 65536 bytes *must*
- have their offset normalized to zero. The default allocation function
- provided by this library ensures this (see zutil.c). To reduce memory
- requirements and avoid any allocation of 64K objects, at the expense of
- compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
- The fields total_in and total_out can be used for statistics or
- progress reports. After compression, total_in holds the total size of
- the uncompressed data and may be saved for use in the decompressor
- (particularly if the decompressor wants to decompress everything in
- a single step).
+ thread safe. In that case, zlib is thread-safe. When zalloc and zfree are
+ Z_NULL on entry to the initialization function, they are set to internal
+ routines that use the standard library functions malloc() and free().
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this if
+ the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers
+ returned by zalloc for objects of exactly 65536 bytes *must* have their
+ offset normalized to zero. The default allocation function provided by this
+ library ensures this (see zutil.c). To reduce memory requirements and avoid
+ any allocation of 64K objects, at the expense of compression ratio, compile
+ the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or progress
+ reports. After compression, total_in holds the total size of the
+ uncompressed data and may be saved for use by the decompressor (particularly
+ if the decompressor wants to decompress everything in a single step).
*/
/* constants */
#define Z_NO_FLUSH 0
-#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_PARTIAL_FLUSH 1
#define Z_SYNC_FLUSH 2
#define Z_FULL_FLUSH 3
#define Z_FINISH 4
-/* Allowed flush values; see deflate() below for details */
+#define Z_BLOCK 5
+#define Z_TREES 6
+/* Allowed flush values; see deflate() and inflate() below for details */
#define Z_OK 0
#define Z_STREAM_END 1
@@ -138,8 +183,8 @@ typedef z_stream FAR *z_streamp;
#define Z_MEM_ERROR (-4)
#define Z_BUF_ERROR (-5)
#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
*/
#define Z_NO_COMPRESSION 0
@@ -150,636 +195,1522 @@ typedef z_stream FAR *z_streamp;
#define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2
+#define Z_RLE 3
+#define Z_FIXED 4
#define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */
#define Z_BINARY 0
-#define Z_ASCII 1
+#define Z_TEXT 1
+#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */
#define Z_UNKNOWN 2
-/* Possible values of the data_type field */
+/* Possible values of the data_type field for deflate() */
#define Z_DEFLATED 8
/* The deflate compression method (the only one supported in this version) */
#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+#ifndef Z_FREETYPE
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
/* basic functions */
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
- If the first character differs, the library code actually used is
- not compatible with the zlib.h header file used by the application.
- This check is automatically made by deflateInit and inflateInit.
+ If the first character differs, the library code actually used is not
+ compatible with the zlib.h header file used by the application. This check
+ is automatically made by deflateInit and inflateInit.
*/
/*
-ZEXTERN(int) deflateInit OF((z_streamp strm, int level));
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
- Initializes the internal stream state for compression. The fields
- zalloc, zfree and opaque must be initialized before by the caller.
- If zalloc and zfree are set to Z_NULL, deflateInit updates them to
- use default allocation functions.
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller. If
+ zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+ allocation functions.
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
- 1 gives best speed, 9 gives best compression, 0 gives no compression at
- all (the input data is simply copied a block at a time).
- Z_DEFAULT_COMPRESSION requests a default compromise between speed and
- compression (currently equivalent to level 6).
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at all
+ (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION
+ requests a default compromise between speed and compression (currently
+ equivalent to level 6).
- deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
- enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if level is not a valid compression level, or
Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
- with the version assumed by the caller (ZLIB_VERSION).
- msg is set to null if there is no error message. deflateInit does not
- perform any compression: this will be done by deflate().
+ with the version assumed by the caller (ZLIB_VERSION). msg is set to null
+ if there is no error message. deflateInit does not perform any compression:
+ this will be done by deflate().
*/
-
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
/*
deflate compresses as much data as possible, and stops when the input
- buffer becomes empty or the output buffer becomes full. It may introduce some
- output latency (reading input without producing any output) except when
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
forced to flush.
- The detailed semantics are as follows. deflate performs one or both of the
+ The detailed semantics are as follows. deflate performs one or both of the
following actions:
- Compress more input starting at next_in and update next_in and avail_in
- accordingly. If not all input can be processed (because there is not
+ accordingly. If not all input can be processed (because there is not
enough room in the output buffer), next_in and avail_in are updated and
processing will resume at this point for the next call of deflate().
- - Provide more output starting at next_out and update next_out and avail_out
- accordingly. This action is forced if the parameter flush is non zero.
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
Forcing flush frequently degrades the compression ratio, so this parameter
- should be set only when necessary (in interactive applications).
- Some output may be provided even if flush is not set.
-
- Before the call of deflate(), the application should ensure that at least
- one of the actions is possible, by providing more input and/or consuming
- more output, and updating avail_in or avail_out accordingly; avail_out
- should never be zero before the call. The application can consume the
- compressed output when it wants, for example when the output buffer is full
- (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
- and with zero avail_out, it must be called again after making room in the
- output buffer because there might be more output pending.
+ should be set only when necessary. Some output may be provided even if
+ flush is zero.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating avail_in or avail_out accordingly; avail_out should
+ never be zero before the call. The application can consume the compressed
+ output when it wants, for example when the output buffer is full (avail_out
+ == 0), or after each call of deflate(). If deflate returns Z_OK and with
+ zero avail_out, it must be called again after making room in the output
+ buffer because there might be more output pending. See deflatePending(),
+ which can be used if desired to determine whether or not there is more ouput
+ in that case.
+
+ Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+ decide how much data to accumulate before producing output, in order to
+ maximize compression.
If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
flushed to the output buffer and the output is aligned on a byte boundary, so
- that the decompressor can get all input data available so far. (In particular
- avail_in is zero after the call if enough output space has been provided
- before the call.) Flushing may degrade compression for some compression
- algorithms and so it should be used only when necessary.
+ that the decompressor can get all input data available so far. (In
+ particular avail_in is zero after the call if enough output space has been
+ provided before the call.) Flushing may degrade compression for some
+ compression algorithms and so it should be used only when necessary. This
+ completes the current deflate block and follows it with an empty stored block
+ that is three bits plus filler bits to the next byte, followed by four bytes
+ (00 00 ff ff).
+
+ If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+ output buffer, but the output is not aligned to a byte boundary. All of the
+ input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+ This completes the current deflate block and follows it with an empty fixed
+ codes block that is 10 bits long. This assures that enough bytes are output
+ in order for the decompressor to finish the block before the empty fixed
+ codes block.
+
+ If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+ for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+ seven bits of the current block are held to be written as the next byte after
+ the next deflate block is completed. In this case, the decompressor may not
+ be provided enough bits at this point in order to complete decompression of
+ the data provided so far to the compressor. It may need to wait for the next
+ block to be emitted. This is for advanced applications that need to control
+ the emission of deflate blocks.
If flush is set to Z_FULL_FLUSH, all output is flushed as with
Z_SYNC_FLUSH, and the compression state is reset so that decompression can
restart from this point if previous compressed data has been damaged or if
- random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
- the compression.
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ compression.
If deflate returns with avail_out == 0, this function must be called again
with the same value of the flush parameter and more output space (updated
avail_out), until the flush is complete (deflate returns with non-zero
- avail_out).
+ avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+ avail_out is greater than six to avoid repeated flush markers due to
+ avail_out == 0 on return.
If the parameter flush is set to Z_FINISH, pending input is processed,
- pending output is flushed and deflate returns with Z_STREAM_END if there
- was enough output space; if deflate returns with Z_OK, this function must be
- called again with Z_FINISH and more output space (updated avail_out) but no
- more input data, until it returns with Z_STREAM_END or an error. After
- deflate has returned Z_STREAM_END, the only possible operations on the
- stream are deflateReset or deflateEnd.
-
- Z_FINISH can be used immediately after deflateInit if all the compression
- is to be done in a single step. In this case, avail_out must be at least
- 0.1% larger than avail_in plus 12 bytes. If deflate does not return
- Z_STREAM_END, then it must be called again as described above.
-
- deflate() sets strm->adler to the adler32 checksum of all input read
- so far (that is, total_in bytes).
-
- deflate() may update data_type if it can make a good guess about
- the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
- binary. This field is only for information purposes and does not affect
- the compression algorithm in any manner.
+ pending output is flushed and deflate returns with Z_STREAM_END if there was
+ enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this
+ function must be called again with Z_FINISH and more output space (updated
+ avail_out) but no more input data, until it returns with Z_STREAM_END or an
+ error. After deflate has returned Z_STREAM_END, the only possible operations
+ on the stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used in the first deflate call after deflateInit if all the
+ compression is to be done in a single step. In order to complete in one
+ call, avail_out must be at least the value returned by deflateBound (see
+ below). Then deflate is guaranteed to return Z_STREAM_END. If not enough
+ output space is provided, deflate will not return Z_STREAM_END, and it must
+ be called again as described above.
+
+ deflate() sets strm->adler to the Adler-32 checksum of all input read
+ so far (that is, total_in bytes). If a gzip stream is being generated, then
+ strm->adler will be the CRC-32 checksum of the input read so far. (See
+ deflateInit2 below.)
+
+ deflate() may update strm->data_type if it can make a good guess about
+ the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is
+ considered binary. This field is only for information purposes and does not
+ affect the compression algorithm in any manner.
deflate() returns Z_OK if some progress has been made (more input
processed or more output produced), Z_STREAM_END if all input has been
consumed and all output has been produced (only when flush is set to
Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
- if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
- (for example avail_in or avail_out was zero).
+ if next_in or next_out was Z_NULL or the state was inadvertently written over
+ by the application), or Z_BUF_ERROR if no progress is possible (for example
+ avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and
+ deflate() can be called again with more input and more output space to
+ continue compressing.
*/
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
/*
All dynamically allocated data structures for this stream are freed.
- This function discards any unprocessed input and does not flush any
- pending output.
+ This function discards any unprocessed input and does not flush any pending
+ output.
deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
stream state was inconsistent, Z_DATA_ERROR if the stream was freed
- prematurely (some input or output was discarded). In the error case,
- msg may be set but then points to a static string (which must not be
+ prematurely (some input or output was discarded). In the error case, msg
+ may be set but then points to a static string (which must not be
deallocated).
*/
+#endif /* !Z_FREETYPE */
/*
-ZEXTERN(int) inflateInit OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
- Initializes the internal stream state for decompression. The fields
+ Initializes the internal stream state for decompression. The fields
next_in, avail_in, zalloc, zfree and opaque must be initialized before by
- the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
- value depends on the compression method), inflateInit determines the
- compression method from the zlib header and allocates all data structures
- accordingly; otherwise the allocation will be deferred to the first call of
- inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to
- use default allocation functions.
+ the caller. In the current version of inflate, the provided input is not
+ read or consumed. The allocation of a sliding window will be deferred to
+ the first call of inflate (if the decompression does not complete on the
+ first call). If zalloc and zfree are set to Z_NULL, inflateInit updates
+ them to use default allocation functions.
inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
- version assumed by the caller. msg is set to null if there is no error
- message. inflateInit does not perform any decompression apart from reading
- the zlib header if present: this will be done by inflate(). (So next_in and
- avail_in may be modified, but next_out and avail_out are unchanged.)
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit does not perform any decompression.
+ Actual decompression will be done by inflate(). So next_in, and avail_in,
+ next_out, and avail_out are unused and unchanged. The current
+ implementation of inflateInit() does not process any header information --
+ that is deferred until inflate() is called.
*/
-ZEXTERN(int) inflate OF((z_streamp strm, int flush));
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
/*
inflate decompresses as much data as possible, and stops when the input
- buffer becomes empty or the output buffer becomes full. It may some
- introduce some output latency (reading input without producing any output)
- except when forced to flush.
+ buffer becomes empty or the output buffer becomes full. It may introduce
+ some output latency (reading input without producing any output) except when
+ forced to flush.
- The detailed semantics are as follows. inflate performs one or both of the
+ The detailed semantics are as follows. inflate performs one or both of the
following actions:
- Decompress more input starting at next_in and update next_in and avail_in
- accordingly. If not all input can be processed (because there is not
- enough room in the output buffer), next_in is updated and processing
- will resume at this point for the next call of inflate().
-
- - Provide more output starting at next_out and update next_out and avail_out
- accordingly. inflate() provides as much output as possible, until there
- is no more input data or no more space in the output buffer (see below
- about the flush parameter).
-
- Before the call of inflate(), the application should ensure that at least
- one of the actions is possible, by providing more input and/or consuming
- more output, and updating the next_* and avail_* values accordingly.
- The application can consume the uncompressed output when it wants, for
- example when the output buffer is full (avail_out == 0), or after each
- call of inflate(). If inflate returns Z_OK and with zero avail_out, it
- must be called again after making room in the output buffer because there
- might be more output pending.
-
- If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
- output as possible to the output buffer. The flushing behavior of inflate is
- not specified for values of the flush parameter other than Z_SYNC_FLUSH
- and Z_FINISH, but the current implementation actually flushes as much output
- as possible anyway.
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), then next_in and avail_in are updated
+ accordingly, and processing will resume at this point for the next call of
+ inflate().
+
+ - Generate more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there is
+ no more input data or no more space in the output buffer (see below about
+ the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming more
+ output, and updating the next_* and avail_* values accordingly. If the
+ caller of inflate() does not provide both available input and available
+ output space, it is possible that there will be no progress made. The
+ application can consume the uncompressed output when it wants, for example
+ when the output buffer is full (avail_out == 0), or after each call of
+ inflate(). If inflate returns Z_OK and with zero avail_out, it must be
+ called again after making room in the output buffer because there might be
+ more output pending.
+
+ The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+ Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much
+ output as possible to the output buffer. Z_BLOCK requests that inflate()
+ stop if and when it gets to the next deflate block boundary. When decoding
+ the zlib or gzip format, this will cause inflate() to return immediately
+ after the header and before the first block. When doing a raw inflate,
+ inflate() will go ahead and process the first block, and will return when it
+ gets to the end of that block, or when it runs out of data.
+
+ The Z_BLOCK option assists in appending to or combining deflate streams.
+ To assist in this, on return inflate() always sets strm->data_type to the
+ number of unused bits in the last byte taken from strm->next_in, plus 64 if
+ inflate() is currently decoding the last block in the deflate stream, plus
+ 128 if inflate() returned immediately after decoding an end-of-block code or
+ decoding the complete header up to just before the first byte of the deflate
+ stream. The end-of-block will not be indicated until all of the uncompressed
+ data from that block has been written to strm->next_out. The number of
+ unused bits may in general be greater than seven, except when bit 7 of
+ data_type is set, in which case the number of unused bits will be less than
+ eight. data_type is set as noted here every time inflate() returns for all
+ flush options, and so can be used to determine the amount of currently
+ consumed input in bits.
+
+ The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+ end of each deflate block header is reached, before any actual data in that
+ block is decoded. This allows the caller to determine the length of the
+ deflate block header for later use in random access within a deflate block.
+ 256 is added to the value of strm->data_type when inflate() returns
+ immediately after reaching the end of the deflate block header.
inflate() should normally be called until it returns Z_STREAM_END or an
- error. However if all decompression is to be performed in a single step
- (a single call of inflate), the parameter flush should be set to
- Z_FINISH. In this case all pending input is processed and all pending
- output is flushed; avail_out must be large enough to hold all the
- uncompressed data. (The size of the uncompressed data may have been saved
- by the compressor for this purpose.) The next operation on this stream must
- be inflateEnd to deallocate the decompression state. The use of Z_FINISH
- is never required, but can be used to inform inflate that a faster routine
- may be used for the single inflate() call.
-
- If a preset dictionary is needed at this point (see inflateSetDictionary
- below), inflate sets strm-adler to the adler32 checksum of the
- dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
- it sets strm->adler to the adler32 checksum of all output produced
- so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
- an error code as described below. At the end of the stream, inflate()
- checks that its computed adler32 checksum is equal to that saved by the
- compressor and returns Z_STREAM_END only if the checksum is correct.
+ error. However if all decompression is to be performed in a single step (a
+ single call of inflate), the parameter flush should be set to Z_FINISH. In
+ this case all pending input is processed and all pending output is flushed;
+ avail_out must be large enough to hold all of the uncompressed data for the
+ operation to complete. (The size of the uncompressed data may have been
+ saved by the compressor for this purpose.) The use of Z_FINISH is not
+ required to perform an inflation in one step. However it may be used to
+ inform inflate that a faster approach can be used for the single inflate()
+ call. Z_FINISH also informs inflate to not maintain a sliding window if the
+ stream completes, which reduces inflate's memory footprint. If the stream
+ does not complete, either because not all of the stream is provided or not
+ enough output space is provided, then a sliding window will be allocated and
+ inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+ been used.
+
+ In this implementation, inflate() always flushes as much output as
+ possible to the output buffer, and always uses the faster approach on the
+ first call. So the effects of the flush parameter in this implementation are
+ on the return value of inflate() as noted below, when inflate() returns early
+ when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+ memory for a sliding window when Z_FINISH is used.
+
+ If a preset dictionary is needed after this call (see inflateSetDictionary
+ below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+ chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+ strm->adler to the Adler-32 checksum of all output produced so far (that is,
+ total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+ below. At the end of the stream, inflate() checks that its computed Adler-32
+ checksum is equal to that saved by the compressor and returns Z_STREAM_END
+ only if the checksum is correct.
+
+ inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+ deflate data. The header type is detected automatically, if requested when
+ initializing with inflateInit2(). Any information contained in the gzip
+ header is not retained unless inflateGetHeader() is used. When processing
+ gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+ produced so far. The CRC-32 is checked against the gzip trailer, as is the
+ uncompressed length, modulo 2^32.
inflate() returns Z_OK if some progress has been made (more input processed
or more output produced), Z_STREAM_END if the end of the compressed data has
been reached and all uncompressed output has been produced, Z_NEED_DICT if a
preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
- corrupted (input stream not conforming to the zlib format or incorrect
- adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
- (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
- enough memory, Z_BUF_ERROR if no progress is possible or if there was not
- enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
- case, the application may then call inflateSync to look for a good
- compression block.
+ corrupted (input stream not conforming to the zlib format or incorrect check
+ value, in which case strm->msg points to a string with a more specific
+ error), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+ next_in or next_out was Z_NULL, or the state was inadvertently written over
+ by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR
+ if no progress was possible or if there was not enough room in the output
+ buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and
+ inflate() can be called again with more input and more output space to
+ continue decompressing. If Z_DATA_ERROR is returned, the application may
+ then call inflateSync() to look for a good compression block if a partial
+ recovery of the data is to be attempted.
*/
-ZEXTERN(int) inflateEnd OF((z_streamp strm));
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
/*
All dynamically allocated data structures for this stream are freed.
- This function discards any unprocessed input and does not flush any
- pending output.
+ This function discards any unprocessed input and does not flush any pending
+ output.
- inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
- was inconsistent. In the error case, msg may be set but then points to a
- static string (which must not be deallocated).
+ inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state
+ was inconsistent.
*/
+
/* Advanced functions */
/*
The following functions are needed only in some special applications.
*/
+#ifndef Z_FREETYPE
+
/*
-ZEXTERN(int) deflateInit2 OF((z_streamp strm,
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
int level,
int method,
int windowBits,
int memLevel,
int strategy));
- This is another version of deflateInit with more compression options. The
- fields next_in, zalloc, zfree and opaque must be initialized before by
- the caller.
+ This is another version of deflateInit with more compression options. The
+ fields zalloc, zfree and opaque must be initialized before by the caller.
- The method parameter is the compression method. It must be Z_DEFLATED in
+ The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
The windowBits parameter is the base two logarithm of the window size
(the size of the history buffer). It should be in the range 8..15 for this
- version of the library. Larger values of this parameter result in better
- compression at the expense of memory usage. The default value is 15 if
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
deflateInit is used instead.
+ For the current implementation of deflate(), a windowBits value of 8 (a
+ window size of 256 bytes) is not supported. As a result, a request for 8
+ will result in 9 (a 512-byte window). In that case, providing 8 to
+ inflateInit2() will result in an error when the zlib header with 9 is
+ checked against the initialization of inflate(). The remedy is to not use 8
+ with deflateInit2() with this initialization, or at least in that case use 9
+ with inflateInit2().
+
+ windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
+ determines the window size. deflate() will then generate raw deflate data
+ with no zlib header or trailer, and will not compute a check value.
+
+ windowBits can also be greater than 15 for optional gzip encoding. Add
+ 16 to windowBits to write a simple gzip header and trailer around the
+ compressed data instead of a zlib wrapper. The gzip header will have no
+ file name, no extra data, no comment, no modification time (set to zero), no
+ header crc, and the operating system will be set to the appropriate value,
+ if the operating system was determined at compile time. If a gzip stream is
+ being written, strm->adler is a CRC-32 instead of an Adler-32.
+
+ For raw deflate or gzip encoding, a request for a 256-byte window is
+ rejected as invalid, since only the zlib header provides a means of
+ transmitting the window size to the decompressor.
+
The memLevel parameter specifies how much memory should be allocated
- for the internal compression state. memLevel=1 uses minimum memory but
- is slow and reduces compression ratio; memLevel=9 uses maximum memory
- for optimal speed. The default value is 8. See zconf.h for total memory
- usage as a function of windowBits and memLevel.
+ for the internal compression state. memLevel=1 uses minimum memory but is
+ slow and reduces compression ratio; memLevel=9 uses maximum memory for
+ optimal speed. The default value is 8. See zconf.h for total memory usage
+ as a function of windowBits and memLevel.
- The strategy parameter is used to tune the compression algorithm. Use the
+ The strategy parameter is used to tune the compression algorithm. Use the
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
- filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
- string match). Filtered data consists mostly of small values with a
- somewhat random distribution. In this case, the compression algorithm is
- tuned to compress them better. The effect of Z_FILTERED is to force more
- Huffman coding and less string matching; it is somewhat intermediate
- between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
- the compression ratio but not the correctness of the compressed output even
- if it is not set appropriately.
-
- deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
- method). msg is set to null if there is no error message. deflateInit2 does
- not perform any compression: this will be done by deflate().
+ filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match), or Z_RLE to limit match distances to one (run-length
+ encoding). Filtered data consists mostly of small values with a somewhat
+ random distribution. In this case, the compression algorithm is tuned to
+ compress them better. The effect of Z_FILTERED is to force more Huffman
+ coding and less string matching; it is somewhat intermediate between
+ Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as
+ fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The
+ strategy parameter only affects the compression ratio but not the
+ correctness of the compressed output even if it is not set appropriately.
+ Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+ decoder for special applications.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+ method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+ incompatible with the version assumed by the caller (ZLIB_VERSION). msg is
+ set to null if there is no error message. deflateInit2 does not perform any
+ compression: this will be done by deflate().
*/
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
/*
Initializes the compression dictionary from the given byte sequence
- without producing any compressed output. This function must be called
- immediately after deflateInit, deflateInit2 or deflateReset, before any
- call of deflate. The compressor and decompressor must use exactly the same
- dictionary (see inflateSetDictionary).
+ without producing any compressed output. When using the zlib format, this
+ function must be called immediately after deflateInit, deflateInit2 or
+ deflateReset, and before any call of deflate. When doing raw deflate, this
+ function must be called either before any call of deflate, or immediately
+ after the completion of a deflate block, i.e. after all input has been
+ consumed and all output has been delivered when using any of the flush
+ options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
+ compressor and decompressor must use exactly the same dictionary (see
+ inflateSetDictionary).
The dictionary should consist of strings (byte sequences) that are likely
to be encountered later in the data to be compressed, with the most commonly
- used strings preferably put towards the end of the dictionary. Using a
+ used strings preferably put towards the end of the dictionary. Using a
dictionary is most useful when the data to be compressed is short and can be
predicted with good accuracy; the data can then be compressed better than
with the default empty dictionary.
Depending on the size of the compression data structures selected by
deflateInit or deflateInit2, a part of the dictionary may in effect be
- discarded, for example if the dictionary is larger than the window size in
- deflate or deflate2. Thus the strings most likely to be useful should be
- put at the end of the dictionary, not at the front.
+ discarded, for example if the dictionary is larger than the window size
+ provided in deflateInit or deflateInit2. Thus the strings most likely to be
+ useful should be put at the end of the dictionary, not at the front. In
+ addition, the current implementation of deflate will use at most the window
+ size minus 262 bytes of the provided dictionary.
- Upon return of this function, strm->adler is set to the Adler32 value
+ Upon return of this function, strm->adler is set to the Adler-32 value
of the dictionary; the decompressor may later use this value to determine
- which dictionary has been used by the compressor. (The Adler32 value
+ which dictionary has been used by the compressor. (The Adler-32 value
applies to the whole dictionary even if only a subset of the dictionary is
- actually used by the compressor.)
+ actually used by the compressor.) If a raw deflate was requested, then the
+ Adler-32 value is not computed and strm->adler is not set.
deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
- parameter is invalid (such as NULL dictionary) or the stream state is
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent (for example if deflate has already been called for this stream
- or if the compression method is bsort). deflateSetDictionary does not
- perform any compression: this will be done by deflate().
+ or if not at a block boundary for raw deflate). deflateSetDictionary does
+ not perform any compression: this will be done by deflate().
*/
+ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength));
+/*
+ Returns the sliding dictionary being maintained by deflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If deflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similary, if dictLength is Z_NULL, then it is not set.
+
+ deflateGetDictionary() may return a length less than the window size, even
+ when more than the window size in input has been provided. It may return up
+ to 258 bytes less in that case, due to how zlib's implementation of deflate
+ manages the sliding window and lookahead for matches, where matches can be
+ up to 258 bytes long. If the application needs the last window-size bytes of
+ input, then that would need to be saved by the application outside of zlib.
+
+ deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+ z_streamp source));
/*
Sets the destination stream as a complete copy of the source stream.
This function can be useful when several compression strategies will be
tried, for example when there are several ways of pre-processing the input
- data with a filter. The streams that will be discarded should then be freed
+ data with a filter. The streams that will be discarded should then be freed
by calling deflateEnd. Note that deflateCopy duplicates the internal
- compression state which can be quite large, so this strategy is slow and
- can consume lots of memory.
+ compression state which can be quite large, so this strategy is slow and can
+ consume lots of memory.
deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
- (such as zalloc being NULL). msg is left unchanged in both source and
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
destination.
*/
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
/*
- This function is equivalent to deflateEnd followed by deflateInit,
- but does not free and reallocate all the internal compression state.
- The stream will keep the same compression level and any other attributes
- that may have been set by deflateInit2.
+ This function is equivalent to deflateEnd followed by deflateInit, but
+ does not free and reallocate the internal compression state. The stream
+ will leave the compression level and any other attributes that may have been
+ set unchanged.
- deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
- stream state was inconsistent (such as zalloc or state being NULL).
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
*/
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+ int level,
+ int strategy));
/*
Dynamically update the compression level and compression strategy. The
- interpretation of level and strategy is as in deflateInit2. This can be
+ interpretation of level and strategy is as in deflateInit2(). This can be
used to switch between compression and straight copy of the input data, or
- to switch to a different kind of input data requiring a different
- strategy. If the compression level is changed, the input available so far
- is compressed with the old level (and may be flushed); the new level will
- take effect only at the next call of deflate().
+ to switch to a different kind of input data requiring a different strategy.
+ If the compression approach (which is a function of the level) or the
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
+
+ If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
+ not have enough output space to complete, then the parameter change will not
+ take effect. In this case, deflateParams() can be called again with the
+ same parameters and more output space to try again.
+
+ In order to assure a change in the parameters on the first try, the
+ deflate stream should be flushed using deflate() with Z_BLOCK or other flush
+ request until strm.avail_out is not zero, before calling deflateParams().
+ Then no more input data should be provided before the deflateParams() call.
+ If this is done, the old level and strategy will be applied to the data
+ compressed before deflateParams(), and the new level and strategy will be
+ applied to the the data compressed after deflateParams().
+
+ deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream
+ state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if
+ there was not enough output space to complete the compression of the
+ available input data before a change in the strategy or approach. Note that
+ in the case of a Z_BUF_ERROR, the parameters are not changed. A return
+ value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be
+ retried with more output space.
+*/
- Before the call of deflateParams, the stream state must be set as for
- a call of deflate(), since the currently available input may have to
- be compressed and flushed. In particular, strm->avail_out must be non-zero.
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+ int good_length,
+ int max_lazy,
+ int nice_length,
+ int max_chain));
+/*
+ Fine tune deflate's internal compression parameters. This should only be
+ used by someone who understands the algorithm used by zlib's deflate for
+ searching for the best matching string, and even then only by the most
+ fanatic optimizer trying to squeeze out the last compressed bit for their
+ specific input data. Read the deflate.c source code for the meaning of the
+ max_lazy, good_length, nice_length, and max_chain parameters.
+
+ deflateTune() can be called after deflateInit() or deflateInit2(), and
+ returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
- deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
- stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
- if strm->avail_out was zero.
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+ uLong sourceLen));
+/*
+ deflateBound() returns an upper bound on the compressed size after
+ deflation of sourceLen bytes. It must be called after deflateInit() or
+ deflateInit2(), and after deflateSetHeader(), if used. This would be used
+ to allocate an output buffer for deflation in a single pass, and so would be
+ called before deflate(). If that first deflate() call is provided the
+ sourceLen input bytes, an output buffer allocated to the size returned by
+ deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+ to return Z_STREAM_END. Note that it is possible for the compressed size to
+ be larger than the value returned by deflateBound() if flush options other
+ than Z_FINISH or Z_NO_FLUSH are used.
*/
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+ unsigned *pending,
+ int *bits));
+/*
+ deflatePending() returns the number of bytes and bits of output that have
+ been generated, but not yet provided in the available output. The bytes not
+ provided would be due to the available output space having being consumed.
+ The number of bits of output not provided are between 0 and 7, where they
+ await more bits to join them in order to fill out a full byte. If pending
+ or bits are Z_NULL, then those values are not set.
+
+ deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
/*
-ZEXTERN(int) inflateInit2 OF((z_streamp strm,
+ deflatePrime() inserts bits in the deflate output stream. The intent
+ is that this function is used to start off the deflate output with the bits
+ leftover from a previous deflate stream when appending to it. As such, this
+ function can only be used for raw deflate, and must be used before the first
+ deflate() call after a deflateInit2() or deflateReset(). bits must be less
+ than or equal to 16, and that many of the least significant bits of value
+ will be inserted in the output.
+
+ deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+ room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ deflateSetHeader() provides gzip header information for when a gzip
+ stream is requested by deflateInit2(). deflateSetHeader() may be called
+ after deflateInit2() or deflateReset() and before the first call of
+ deflate(). The text, time, os, extra field, name, and comment information
+ in the provided gz_header structure are written to the gzip header (xflag is
+ ignored -- the extra flags are set according to the compression level). The
+ caller must assure that, if not Z_NULL, name and comment are terminated with
+ a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+ available there. If hcrc is true, a gzip header crc is included. Note that
+ the current versions of the command-line version of gzip (up through version
+ 1.3.x) do not support header crc's, and will report that it is a "multi-part
+ gzip file" and give up.
+
+ If deflateSetHeader is not used, the default gzip header has text false,
+ the time set to zero, and os set to 255, with no extra, name, or comment
+ fields. The gzip header is returned to the default state by deflateReset().
+
+ deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
int windowBits));
- This is another version of inflateInit with an extra parameter. The
+ This is another version of inflateInit with an extra parameter. The
fields next_in, avail_in, zalloc, zfree and opaque must be initialized
before by the caller.
The windowBits parameter is the base two logarithm of the maximum window
size (the size of the history buffer). It should be in the range 8..15 for
- this version of the library. The default value is 15 if inflateInit is used
- instead. If a compressed stream with a larger window size is given as
- input, inflate() will return with the error code Z_DATA_ERROR instead of
- trying to allocate a larger window.
-
- inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
- memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
- memLevel). msg is set to null if there is no error message. inflateInit2
- does not perform any decompression apart from reading the zlib header if
- present: this will be done by inflate(). (So next_in and avail_in may be
- modified, but next_out and avail_out are unchanged.)
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. windowBits must be greater than or equal to the windowBits value
+ provided to deflateInit2() while compressing, or it must be equal to 15 if
+ deflateInit2() was not used. If a compressed stream with a larger window
+ size is given as input, inflate() will return with the error code
+ Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ windowBits can also be zero to request that inflate use the window size in
+ the zlib header of the compressed stream.
+
+ windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
+ determines the window size. inflate() will then process raw deflate data,
+ not looking for a zlib or gzip header, not generating a check value, and not
+ looking for any check values for comparison at the end of the stream. This
+ is for use with other formats that use the deflate compressed data format
+ such as zip. Those formats provide their own check values. If a custom
+ format is developed using the raw deflate format for compressed data, it is
+ recommended that a check value such as an Adler-32 or a CRC-32 be applied to
+ the uncompressed data as is done in the zlib, gzip, and zip formats. For
+ most applications, the zlib format should be used as is. Note that comments
+ above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+ windowBits can also be greater than 15 for optional gzip decoding. Add
+ 32 to windowBits to enable zlib and gzip decoding with automatic header
+ detection, or add 16 to decode only the gzip format (the zlib format will
+ return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
+ CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+ invalid, such as a null pointer to the structure. msg is set to null if
+ there is no error message. inflateInit2 does not perform any decompression
+ apart from possibly reading the zlib header if present: actual decompression
+ will be done by inflate(). (So next_in and avail_in may be modified, but
+ next_out and avail_out are unused and unchanged.) The current implementation
+ of inflateInit2() does not process any header information -- that is
+ deferred until inflate() is called.
*/
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+ const Bytef *dictionary,
+ uInt dictLength));
/*
Initializes the decompression dictionary from the given uncompressed byte
- sequence. This function must be called immediately after a call of inflate
- if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
- can be determined from the Adler32 value returned by this call of
- inflate. The compressor and decompressor must use exactly the same
- dictionary (see deflateSetDictionary).
+ sequence. This function must be called immediately after a call of inflate,
+ if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler-32 value returned by that call of inflate.
+ The compressor and decompressor must use exactly the same dictionary (see
+ deflateSetDictionary). For raw inflate, this function can be called at any
+ time to set the dictionary. If the provided dictionary is smaller than the
+ window and there is already data in the window, then the provided dictionary
+ will amend what's there. The application must insure that the dictionary
+ that was used for compression is provided.
inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
- parameter is invalid (such as NULL dictionary) or the stream state is
+ parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
- expected one (incorrect Adler32 value). inflateSetDictionary does not
+ expected one (incorrect Adler-32 value). inflateSetDictionary does not
perform any decompression: this will be done by subsequent calls of
inflate().
*/
+ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm,
+ Bytef *dictionary,
+ uInt *dictLength));
+/*
+ Returns the sliding dictionary being maintained by inflate. dictLength is
+ set to the number of bytes in the dictionary, and that many bytes are copied
+ to dictionary. dictionary must have enough space, where 32768 bytes is
+ always enough. If inflateGetDictionary() is called with dictionary equal to
+ Z_NULL, then only the dictionary length is returned, and nothing is copied.
+ Similary, if dictLength is Z_NULL, then it is not set.
+
+ inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the
+ stream state is inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
/*
- Skips invalid compressed data until a full flush point (see above the
- description of deflate with Z_FULL_FLUSH) can be found, or until all
- available input is skipped. No output is provided.
+ Skips invalid compressed data until a possible full flush point (see above
+ for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+ All full flush points have this pattern, but not all occurrences of this
+ pattern are full flush points.
+
+ inflateSync returns Z_OK if a possible full flush point has been found,
+ Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+ has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+ In the success case, the application may save the current current value of
+ total_in which indicates where valid compressed data was found. In the
+ error case, the application may repeatedly call inflateSync, providing more
+ input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+ z_streamp source));
+/*
+ Sets the destination stream as a complete copy of the source stream.
- inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
- if no more input was provided, Z_DATA_ERROR if no flush point has been found,
- or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
- case, the application may save the current value of total_in which
- indicates where valid compressed data was found. In the error case, the
- application may repeatedly call inflateSync, providing more input each time,
- until success or end of the input data.
+ This function can be useful when randomly accessing a large stream. The
+ first pass through the stream can periodically record the inflate state,
+ allowing restarting inflate at those points when randomly accessing the
+ stream.
+
+ inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being Z_NULL). msg is left unchanged in both source and
+ destination.
*/
-ZEXTERN(int) inflateReset OF((z_streamp strm));
+#endif /* !Z_FREETYPE */
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
/*
This function is equivalent to inflateEnd followed by inflateInit,
- but does not free and reallocate all the internal decompression state.
- The stream will keep attributes that may have been set by inflateInit2.
+ but does not free and reallocate the internal decompression state. The
+ stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+ int windowBits));
+/*
+ This function is the same as inflateReset, but it also permits changing
+ the wrap and window size requests. The windowBits parameter is interpreted
+ the same as it is for inflateInit2. If the window size is changed, then the
+ memory allocated for the window is freed, and the window will be reallocated
+ by inflate() if needed.
+
+ inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+ the windowBits parameter is invalid.
+*/
+
+#ifndef Z_FREETYPE
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+ int bits,
+ int value));
+/*
+ This function inserts bits in the inflate input stream. The intent is
+ that this function is used to start inflating at a bit position in the
+ middle of a byte. The provided bits will be used before any bytes are used
+ from next_in. This function should only be used with raw inflate, and
+ should be used before the first inflate() call after inflateInit2() or
+ inflateReset(). bits must be less than or equal to 16, and that many of the
+ least significant bits of value will be inserted in the input.
+
+ If bits is negative, then the input stream bit buffer is emptied. Then
+ inflatePrime() can be called again to put bits in the buffer. This is used
+ to clear out bits leftover after feeding inflate a block description prior
+ to feeding inflate codes.
+
+ inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+ This function returns two values, one in the lower 16 bits of the return
+ value, and the other in the remaining upper bits, obtained by shifting the
+ return value down 16 bits. If the upper value is -1 and the lower value is
+ zero, then inflate() is currently decoding information outside of a block.
+ If the upper value is -1 and the lower value is non-zero, then inflate is in
+ the middle of a stored block, with the lower value equaling the number of
+ bytes from the input remaining to copy. If the upper value is not -1, then
+ it is the number of bits back from the current bit position in the input of
+ the code (literal or length/distance pair) currently being processed. In
+ that case the lower value is the number of bytes already emitted for that
+ code.
+
+ A code is being processed if inflate is waiting for more input to complete
+ decoding of the code, or if it has completed decoding but is waiting for
+ more output space to write the literal or match data.
+
+ inflateMark() is used to mark locations in the input data for random
+ access, which may be at bit positions, and to note those cases where the
+ output of a code may span boundaries of random access blocks. The current
+ location in the input stream can be determined from avail_in and data_type
+ as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+ inflateMark returns the value noted above, or -65536 if the provided
+ source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+ gz_headerp head));
+/*
+ inflateGetHeader() requests that gzip header information be stored in the
+ provided gz_header structure. inflateGetHeader() may be called after
+ inflateInit2() or inflateReset(), and before the first call of inflate().
+ As inflate() processes the gzip stream, head->done is zero until the header
+ is completed, at which time head->done is set to one. If a zlib stream is
+ being decoded, then head->done is set to -1 to indicate that there will be
+ no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be
+ used to force inflate() to return immediately after header processing is
+ complete and before any actual data is decompressed.
+
+ The text, time, xflags, and os fields are filled in with the gzip header
+ contents. hcrc is set to true if there is a header CRC. (The header CRC
+ was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+ contains the maximum number of bytes to write to extra. Once done is true,
+ extra_len contains the actual extra field length, and extra contains the
+ extra field, or that field truncated if extra_max is less than extra_len.
+ If name is not Z_NULL, then up to name_max characters are written there,
+ terminated with a zero unless the length is greater than name_max. If
+ comment is not Z_NULL, then up to comm_max characters are written there,
+ terminated with a zero unless the length is greater than comm_max. When any
+ of extra, name, or comment are not Z_NULL and the respective field is not
+ present in the header, then that field is set to Z_NULL to signal its
+ absence. This allows the use of deflateSetHeader() with the returned
+ structure to duplicate the header. However if those fields are set to
+ allocated memory, then the application will need to save those pointers
+ elsewhere so that they can be eventually freed.
+
+ If inflateGetHeader is not used, then the header information is simply
+ discarded. The header is always checked for validity, including the header
+ CRC if present. inflateReset() will reset the process to discard the header
+ information. The application would need to call inflateGetHeader() again to
+ retrieve the header from the next gzip stream.
+
+ inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent.
+*/
+
+#endif /* !Z_FREETYPE */
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window));
+
+ Initialize the internal stream state for decompression using inflateBack()
+ calls. The fields zalloc, zfree and opaque in strm must be initialized
+ before the call. If zalloc and zfree are Z_NULL, then the default library-
+ derived memory allocation routines are used. windowBits is the base two
+ logarithm of the window size, in the range 8..15. window is a caller
+ supplied buffer of that size. Except for special applications where it is
+ assured that deflate was used with small window sizes, windowBits must be 15
+ and a 32K byte window must be supplied to be able to decompress general
+ deflate streams.
+
+ See inflateBack() for the usage of these routines.
+
+ inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+ the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+ allocated, or Z_VERSION_ERROR if the version of the library does not match
+ the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *,
+ z_const unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
- inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
- stream state was inconsistent (such as zalloc or state being NULL).
+#ifndef Z_FREETYPE
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+ in_func in, void FAR *in_desc,
+ out_func out, void FAR *out_desc));
+/*
+ inflateBack() does a raw inflate with a single call using a call-back
+ interface for input and output. This is potentially more efficient than
+ inflate() for file i/o applications, in that it avoids copying between the
+ output and the sliding window by simply making the window itself the output
+ buffer. inflate() can be faster on modern CPUs when used with large
+ buffers. inflateBack() trusts the application to not change the output
+ buffer passed by the output function, at least until inflateBack() returns.
+
+ inflateBackInit() must be called first to allocate the internal state
+ and to initialize the state with the user-provided window buffer.
+ inflateBack() may then be used multiple times to inflate a complete, raw
+ deflate stream with each call. inflateBackEnd() is then called to free the
+ allocated state.
+
+ A raw deflate stream is one with no zlib or gzip header or trailer.
+ This routine would normally be used in a utility that reads zip or gzip
+ files and writes out uncompressed files. The utility would decode the
+ header and process the trailer on its own, hence this routine expects only
+ the raw deflate stream to decompress. This is different from the default
+ behavior of inflate(), which expects a zlib header and trailer around the
+ deflate stream.
+
+ inflateBack() uses two subroutines supplied by the caller that are then
+ called by inflateBack() for input and output. inflateBack() calls those
+ routines until it reads a complete deflate stream and writes out all of the
+ uncompressed data, or until it encounters an error. The function's
+ parameters and return types are defined above in the in_func and out_func
+ typedefs. inflateBack() will call in(in_desc, &buf) which should return the
+ number of bytes of provided input, and a pointer to that input in buf. If
+ there is no input available, in() must return zero -- buf is ignored in that
+ case -- and inflateBack() will return a buffer error. inflateBack() will
+ call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].
+ out() should return zero on success, or non-zero on failure. If out()
+ returns non-zero, inflateBack() will return with an error. Neither in() nor
+ out() are permitted to change the contents of the window provided to
+ inflateBackInit(), which is also the buffer that out() uses to write from.
+ The length written by out() will be at most the window size. Any non-zero
+ amount of input may be provided by in().
+
+ For convenience, inflateBack() can be provided input on the first call by
+ setting strm->next_in and strm->avail_in. If that input is exhausted, then
+ in() will be called. Therefore strm->next_in must be initialized before
+ calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called
+ immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in
+ must also be initialized, and then if strm->avail_in is not zero, input will
+ initially be taken from strm->next_in[0 .. strm->avail_in - 1].
+
+ The in_desc and out_desc parameters of inflateBack() is passed as the
+ first parameter of in() and out() respectively when they are called. These
+ descriptors can be optionally used to pass any information that the caller-
+ supplied in() and out() functions need to do their job.
+
+ On return, inflateBack() will set strm->next_in and strm->avail_in to
+ pass back any unused input that was provided by the last in() call. The
+ return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+ if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+ in the deflate stream (in which case strm->msg is set to indicate the nature
+ of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+ In the case of Z_BUF_ERROR, an input or output error can be distinguished
+ using strm->next_in which will be Z_NULL only if in() returned an error. If
+ strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+ non-zero. (in() will always be called before out(), so strm->next_in is
+ assured to be defined if out() returns non-zero.) Note that inflateBack()
+ cannot return Z_OK.
*/
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+ All memory allocated by inflateBackInit() is freed.
+
+ inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+ state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+ Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+ 1.0: size of uInt
+ 3.2: size of uLong
+ 5.4: size of voidpf (pointer)
+ 7.6: size of z_off_t
+
+ Compiler, assembler, and debug options:
+ 8: ZLIB_DEBUG
+ 9: ASMV or ASMINF -- use ASM code
+ 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+ 11: 0 (reserved)
+
+ One-time table building (smaller code, but not thread-safe if true):
+ 12: BUILDFIXED -- build static block decoding tables when needed
+ 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+ 14,15: 0 (reserved)
+
+ Library content (indicates missing functionality):
+ 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+ deflate code when not needed)
+ 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+ and decode gzip streams (to avoid linking crc code)
+ 18-19: 0 (reserved)
+
+ Operation variations (changes in library functionality):
+ 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+ 21: FASTEST -- deflate algorithm with only one, lowest compression level
+ 22,23: 0 (reserved)
+
+ The sprintf variant used by gzprintf (zero is best):
+ 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+ 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+ 26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+ Remainder:
+ 27-31: 0 (reserved)
+ */
+
+#endif /* !Z_FREETYPE */
+
+#ifndef Z_SOLO
/* utility functions */
/*
- The following utility functions are implemented on top of the
- basic stream-oriented functions. To simplify the interface, some
- default options are assumed (compression level and memory usage,
- standard memory allocation functions). The source code of these
- utility functions can easily be modified if you need special options.
+ The following utility functions are implemented on top of the basic
+ stream-oriented functions. To simplify the interface, some default options
+ are assumed (compression level and memory usage, standard memory allocation
+ functions). The source code of these utility functions can be modified if
+ you need special options.
*/
+ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
/*
Compresses the source buffer into the destination buffer. sourceLen is
- the byte length of the source buffer. Upon entry, destLen is the total
- size of the destination buffer, which must be at least 0.1% larger than
- sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
- compressed buffer.
- This function can be used to compress a whole file at once if the
- input file is mmap'ed.
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data. compress() is equivalent to compress2() with a level
+ parameter of Z_DEFAULT_COMPRESSION.
+
compress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer.
*/
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen,
+ int level));
/*
- Compresses the source buffer into the destination buffer. The level
+ Compresses the source buffer into the destination buffer. The level
parameter has the same meaning as in deflateInit. sourceLen is the byte
- length of the source buffer. Upon entry, destLen is the total size of the
- destination buffer, which must be at least 0.1% larger than sourceLen plus
- 12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+ length of the source buffer. Upon entry, destLen is the total size of the
+ destination buffer, which must be at least the value returned by
+ compressBound(sourceLen). Upon exit, destLen is the actual size of the
+ compressed data.
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+ compressBound() returns an upper bound on the compressed size after
+ compress() or compress2() on sourceLen bytes. It would be used before a
+ compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong sourceLen));
/*
Decompresses the source buffer into the destination buffer. sourceLen is
- the byte length of the source buffer. Upon entry, destLen is the total
- size of the destination buffer, which must be large enough to hold the
- entire uncompressed data. (The size of the uncompressed data must have
- been saved previously by the compressor and transmitted to the decompressor
- by some mechanism outside the scope of this compression library.)
- Upon exit, destLen is the actual size of the compressed buffer.
- This function can be used to decompress a whole file at once if the
- input file is mmap'ed.
+ the byte length of the source buffer. Upon entry, destLen is the total size
+ of the destination buffer, which must be large enough to hold the entire
+ uncompressed data. (The size of the uncompressed data must have been saved
+ previously by the compressor and transmitted to the decompressor by some
+ mechanism outside the scope of this compression library.) Upon exit, destLen
+ is the actual size of the uncompressed data.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
- buffer, or Z_DATA_ERROR if the input data was corrupted.
+ buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In
+ the case where there is not enough room, uncompress() will fill the output
+ buffer with the uncompressed data up to that point.
+*/
+
+ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen,
+ const Bytef *source, uLong *sourceLen));
+/*
+ Same as uncompress, except that sourceLen is a pointer, where the
+ length of the source is *sourceLen. On return, *sourceLen is the number of
+ source bytes consumed.
+*/
+
+ /* gzip file access functions */
+
+/*
+ This library supports reading and writing files in gzip (.gz) format with
+ an interface similar to that of stdio, using the functions that start with
+ "gz". The gzip format is different from the zlib format. gzip is a gzip
+ wrapper, documented in RFC 1952, wrapped around a deflate stream.
*/
+typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
/*
- Opens a gzip (.gz) file for reading or writing. The mode parameter
- is as in fopen ("rb" or "wb") but can also include a compression level
- ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
- Huffman only compression as in "wb1h". (See the description
- of deflateInit2 for more information about the strategy parameter.)
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
+
+ "a" can be used instead of "w" to request that the gzip stream that will
+ be written be appended to the file. "+" will result in an error, since
+ reading and writing to the same gzip file is not supported. The addition of
+ "x" when writing will create the file exclusively, which fails if the file
+ already exists. On systems that support it, the addition of "e" when
+ reading or writing will set the flag to close the file on an execve() call.
+
+ These functions, as well as gzip, will read and decode a sequence of gzip
+ streams in a file. The append function of gzopen() can be used to create
+ such a file. (Also see gzflush() for another way to do this.) When
+ appending, gzopen does not test whether the file begins with a gzip stream,
+ nor does it look for the end of the gzip streams to begin appending. gzopen
+ will simply append a gzip stream to the existing file.
gzopen can be used to read a file which is not in gzip format; in this
- case gzread will directly read from the file without decompression.
+ case gzread will directly read from the file without decompression. When
+ reading, this will be detected automatically by looking for the magic two-
+ byte gzip header.
+
+ gzopen returns NULL if the file could not be opened, if there was
+ insufficient memory to allocate the gzFile state, or if an invalid mode was
+ specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+ errno can be checked to determine if the reason gzopen failed was that the
+ file could not be opened.
+*/
- gzopen returns NULL if the file could not be opened or if there was
- insufficient memory to allocate the (de)compression state; errno
- can be checked to distinguish the two cases (if errno is zero, the
- zlib error is Z_MEM_ERROR). */
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
+
+ The next call of gzclose on the returned gzFile will also close the file
+ descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+ fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+ mode);. The duplicated descriptor should be saved to avoid a leak, since
+ gzdopen does not close fd if it fails. If you are using fileno() to get the
+ file descriptor from a FILE *, then you will have to use dup() to avoid
+ double-close()ing the file descriptor. Both gzclose() and fclose() will
+ close the associated file descriptor, so they need to have different file
+ descriptors.
+
+ gzdopen returns NULL if there was insufficient memory to allocate the
+ gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+ provided, or '+' was provided), or if fd is -1. The file descriptor is not
+ used until the next gz* read, write, seek, or close operation, so gzdopen
+ will not detect if fd is invalid (unless fd is -1).
+*/
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
/*
- gzdopen() associates a gzFile with the file descriptor fd. File
- descriptors are obtained from calls like open, dup, creat, pipe or
- fileno (in the file has been previously opened with fopen).
- The mode parameter is as in gzopen.
- The next call of gzclose on the returned gzFile will also close the
- file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
- descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
- gzdopen returns NULL if there was insufficient memory to allocate
- the (de)compression state.
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
+
+ The new buffer size also affects the maximum length for gzprintf().
+
+ gzbuffer() returns 0 on success, or -1 on failure, such as being called
+ too late.
*/
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
/*
- Dynamically update the compression level or strategy. See the description
- of deflateInit2 for the meaning of these parameters.
- gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
- opened for writing.
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
+
+ gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
+ opened for writing, Z_ERRNO if there is an error writing the flushed data,
+ or Z_MEM_ERROR if there is a memory allocation error.
*/
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
- Reads the given number of uncompressed bytes from the compressed file.
- If the input file was not in gzip format, gzread copies the given number
- of bytes into the buffer.
- gzread returns the number of uncompressed bytes actually read (0 for
- end of file, -1 for error). */
+ Read and decompress up to len uncompressed bytes from file into buf. If
+ the input file is not in gzip format, gzread copies the given number of
+ bytes into the buffer directly from the file.
+
+ After reaching the end of a gzip stream in the input, gzread will continue
+ to read, looking for another gzip stream. Any number of gzip streams may be
+ concatenated in the input file, and will all be decompressed by gzread().
+ If something other than a gzip stream is encountered after a gzip stream,
+ that remaining trailing garbage is ignored (and no error is returned).
+
+ gzread can be used to read a gzip file that is being concurrently written.
+ Upon reaching the end of the input, gzread will return with the available
+ data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+ gzclearerr can be used to clear the end of file indicator in order to permit
+ gzread to be tried again. Z_OK indicates that a gzip stream was completed
+ on the last gzread. Z_BUF_ERROR indicates that the input file ended in the
+ middle of a gzip stream. Note that gzread does not return -1 in the event
+ of an incomplete gzip stream. This error is deferred until gzclose(), which
+ will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+ stream. Alternatively, gzerror can be used before gzclose to detect this
+ case.
+
+ gzread returns the number of uncompressed bytes actually read, less than
+ len for end of file, or -1 for error. If len is too large to fit in an int,
+ then nothing is read, -1 is returned, and the error state is set to
+ Z_STREAM_ERROR.
+*/
+ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
+ gzFile file));
/*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes actually written
- (0 in case of error).
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
+
+ gzfread() returns the number of full items read of size size, or zero if
+ the end of the file was reached and a full item could not be read, or if
+ there was an error. gzerror() must be consulted if zero is returned in
+ order to determine if there was an error. If the multiplication of size and
+ nitems overflows, i.e. the product does not fit in a z_size_t, then nothing
+ is read, zero is returned, and the error state is set to Z_STREAM_ERROR.
+
+ In the event that the end of file is reached and only a partial item is
+ available at the end, i.e. the remaining uncompressed data length is not a
+ multiple of size, then the final partial item is nevetheless read into buf
+ and the end-of-file flag is set. The length of the partial item read is not
+ provided, but could be inferred from the result of gztell(). This behavior
+ is the same as the behavior of fread() implementations in common libraries,
+ but it prevents the direct use of gzfread() to read a concurrently written
+ file, reseting and retrying on end-of-file, when size is not 1.
*/
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
/*
- Converts, formats, and writes the args to the compressed file under
- control of the format string, as in fprintf. gzprintf returns the number of
- uncompressed bytes actually written (0 in case of error).
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
*/
+ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
+ z_size_t nitems, gzFile file));
/*
- Writes the given null-terminated string to the compressed file, excluding
+ Compress and write nitems items of size size from buf to file, duplicating
+ the interface of stdio's fwrite(), with size_t request and return types. If
+ the library defines size_t, then z_size_t is identical to size_t. If not,
+ then z_size_t is an unsigned integer type that can contain a pointer.
+
+ gzfwrite() returns the number of full items written of size size, or zero
+ if there was an error. If the multiplication of size and nitems overflows,
+ i.e. the product does not fit in a z_size_t, then nothing is written, zero
+ is returned, and the error state is set to Z_STREAM_ERROR.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
+ uncompressed bytes actually written, or a negative zlib error code in case
+ of error. The number of uncompressed bytes written is limited to 8191, or
+ one less than the buffer size given to gzbuffer(). The caller should assure
+ that this limit is not exceeded. If it is exceeded, then gzprintf() will
+ return an error (0) with nothing written. In this case, there may also be a
+ buffer overflow with unpredictable consequences, which is possible only if
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
+ because the secure snprintf() or vsnprintf() functions were not available.
+ This can be determined using zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+ Compress and write the given null-terminated string s to file, excluding
the terminating null character.
- gzputs returns the number of characters written, or -1 in case of error.
+
+ gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
+
+ gzgets returns buf which is a null-terminated string, or it returns NULL
+ for end-of-file or in case of error. If there was an error, the contents at
+ buf are indeterminate.
*/
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
/*
- Reads bytes from the compressed file until len-1 characters are read, or
- a newline character is read and transferred to buf, or an end-of-file
- condition is encountered. The string is then terminated with a null
- character.
- gzgets returns buf, or Z_NULL in case of error.
+ Compress and write c, converted to an unsigned char, into file. gzputc
+ returns the value that was written, or -1 in case of error.
*/
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
- Writes c, converted to an unsigned char, into the compressed file.
- gzputc returns the value that was written, or -1 in case of error.
+ Read and decompress one byte from file. gzgetc returns this byte or -1
+ in case of end of file or error. This is implemented as a macro for speed.
+ As such, it does not do all of the checking the other functions do. I.e.
+ it does not check to see if file is NULL, nor whether the structure file
+ points to has been clobbered or not.
*/
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
/*
- Reads one byte from the compressed file. gzgetc returns this byte
- or -1 in case of end of file or error.
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
+ gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
+ fail if c is -1, and may fail if a character has been pushed but not read
+ yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
+ output buffer size of pushed characters is allowed. (See gzbuffer above.)
+ The pushed character will be discarded if the stream is repositioned with
+ gzseek() or gzrewind().
*/
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
/*
- Flushes all pending output into the compressed file. The parameter
- flush is as in the deflate() function. The return value is the zlib
- error number (see function gzerror below). gzflush returns Z_OK if
- the flush parameter is Z_FINISH and all output could be flushed.
- gzflush should be called only when strictly necessary because it can
- degrade compression.
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
+
+ If the flush parameter is Z_FINISH, the remaining data is written and the
+ gzip stream is completed in the output. If gzwrite() is called again, a new
+ gzip stream will be started in the output. gzread() is able to read such
+ concatenated gzip streams.
+
+ gzflush should be called only when strictly necessary because it will
+ degrade compression if called too often.
*/
/*
- Sets the starting position for the next gzread or gzwrite on the
- given compressed file. The offset represents a number of bytes in the
- uncompressed data stream. The whence parameter is defined as in lseek(2);
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+ z_off_t offset, int whence));
+
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
+ uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
+
If the file is opened for reading, this function is emulated but can be
- extremely slow. If the file is opened for writing, only forward seeks are
+ extremely slow. If the file is opened for writing, only forward seeks are
supported; gzseek then compresses a sequence of zeroes up to the new
starting position.
- gzseek returns the resulting offset location as measured in bytes from
+ gzseek returns the resulting offset location as measured in bytes from
the beginning of the uncompressed stream, or -1 in case of error, in
particular if the file is opened for writing and the new starting position
would be before the current position.
*/
+ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
/*
- Rewinds the given file. This function is supported only for reading.
+ Rewind file. This function is supported only for reading.
- gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/
/*
- Returns the starting position for the next gzread or gzwrite on the
- given compressed file. This position represents a number of bytes in the
- uncompressed data stream.
+ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
- gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
+
+ gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
+
+ If gzeof() returns true, then the read functions will return no more data,
+ unless the end-of-file indicator is reset by gzclearerr() and the input file
+ has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+ Return true (1) if file is being copied directly while reading, or false
+ (0) if file is a gzip stream being decompressed.
+
+ If the input file is empty, gzdirect() will return true, since the input
+ does not contain a gzip stream.
+
+ If gzdirect() is used immediately after gzopen() or gzdopen() it will
+ cause buffers to be allocated to allow reading the file to determine if it
+ is a gzip file. Therefore if gzbuffer() is used, it should be called before
+ gzdirect().
+
+ When writing, gzdirect() returns true (1) if transparent writing was
+ requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note:
+ gzdirect() is not needed when writing. Transparent writing must be
+ explicitly requested, so the application already knows the answer. When
+ linking statically, using gzdirect() will include all of the zlib code for
+ gzip file reading and decompression, which may not be desired.)
*/
+ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/*
- Returns 1 when EOF has previously been detected reading the given
- input stream, otherwise zero.
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
+ cannot call gzerror with file, since its structures have been deallocated.
+ gzclose must not be called more than once on the same file, just as free
+ must not be called more than once on the same allocation.
+
+ gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+ file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+ last read ended in the middle of a gzip stream, or Z_OK on success.
*/
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
/*
- Flushes all pending output if necessary, closes the compressed file
- and deallocates all the (de)compression state. The return value is the zlib
- error number (see function gzerror below).
+ Same as gzclose(), but gzclose_r() is only for use when reading, and
+ gzclose_w() is only for use when writing or appending. The advantage to
+ using these instead of gzclose() is that they avoid linking in zlib
+ compression or decompression code that is not used when only reading or only
+ writing respectively. If gzclose() is used, then both compression and
+ decompression code will be included the application when linking to a static
+ zlib library.
*/
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
/*
- Returns the error message for the last error which occurred on the
- given compressed file. errnum is set to zlib error number. If an
- error occurred in the file system and not in the compression library,
- errnum is set to Z_ERRNO and the application may consult errno
- to get the exact error code.
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
+
+ The application must not modify the returned string. Future calls to
+ this function may invalidate the previously returned string. If file is
+ closed, then the string previously returned by gzerror will no longer be
+ available.
+
+ gzerror() should be used to distinguish errors from end-of-file for those
+ functions above that do not distinguish those cases in their return values.
*/
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+ Clear the error and end-of-file flags for file. This is analogous to the
+ clearerr() function in stdio. This is useful for continuing to read a gzip
+ file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
/* checksum functions */
/*
These functions are not related to compression but are exported
- anyway because they might be useful in applications using the
- compression library.
+ anyway because they might be useful in applications using the compression
+ library.
*/
-ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));
-
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
- return the updated checksum. If buf is NULL, this function returns
- the required initial value for the checksum.
- An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
- much faster. Usage example:
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
+ much faster.
+
+ Usage example:
uLong adler = adler32(0L, Z_NULL, 0);
@@ -789,11 +1720,32 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));
if (adler != original_adler) error();
*/
+ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf,
+ z_size_t len));
+/*
+ Same as adler32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+ z_off_t len2));
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
- Update a running crc with the bytes buf[0..len-1] and return the updated
- crc. If buf is NULL, this function returns the required initial value
- for the crc. Pre- and post-conditioning (one's complement) is performed
- within this function so it shouldn't be done by the application.
+ Update a running CRC-32 with the bytes buf[0..len-1] and return the
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
+
Usage example:
uLong crc = crc32(0L, Z_NULL, 0);
@@ -804,27 +1756,213 @@ ZEXTERN(uLong) adler32 OF((uLong adler, const Bytef *buf, uInt len));
if (crc != original_crc) error();
*/
+#ifndef Z_FREETYPE
+
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
+ z_size_t len));
+/*
+ Same as crc32(), but with a size_t length.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
/* various hacks, don't look :) */
/* deflateInit and inflateInit are macros to allow checking the zlib version
* and the compiler's view of z_stream:
*/
-ZEXTERN(int) inflateInit2_ OF((z_streamp strm, int windowBits,
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
+ const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+ unsigned char FAR *window,
+ const char *version,
+ int stream_size));
+#ifdef Z_PREFIX_SET
+# define z_deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define z_inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define z_inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#else
+# define deflateInit(strm, level) \
+ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit(strm) \
+ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+# define inflateBackInit(strm, windowBits, window) \
+ inflateBackInit_((strm), (windowBits), (window), \
+ ZLIB_VERSION, (int)sizeof(z_stream))
+#endif
+
+#else /* Z_FREETYPE */
+
+
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits,
const char *version, int stream_size));
-#define deflateInit(strm, level) \
- deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
- inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
- deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
- (strategy), ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
- inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+# define inflateInit2(strm, windowBits) \
+ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+ (int)sizeof(z_stream))
+
+#endif /* Z_FREETYPE */
+
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure. Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro. The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously. They can
+ * only be used by the gzgetc() macro. You have been warned.
+ */
+struct gzFile_s {
+ unsigned have;
+ unsigned char *next;
+ z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
+#ifdef Z_PREFIX_SET
+# undef z_gzgetc
+# define z_gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#else
+# define gzgetc(g) \
+ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+ ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+# ifdef Z_PREFIX_SET
+# define z_gzopen z_gzopen64
+# define z_gzseek z_gzseek64
+# define z_gztell z_gztell64
+# define z_gzoffset z_gzoffset64
+# define z_adler32_combine z_adler32_combine64
+# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
+# else
+# define gzopen gzopen64
+# define gzseek gzseek64
+# define gztell gztell64
+# define gzoffset gzoffset64
+# define adler32_combine adler32_combine64
+# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
+# endif
+# ifndef Z_LARGE64
+ ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
+# endif
+#else
+ ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+ ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+#ifndef Z_FREETYPE
+ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
+#endif
+
+#endif /* !Z_SOLO */
+
+/* undocumented functions */
+#ifndef Z_FREETYPE
+ZEXTERN const char * ZEXPORT zError OF((int));
+ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void));
+ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
+ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
+ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
+ const char *mode));
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifndef Z_SOLO
+ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file,
+ const char *format,
+ va_list va));
+# endif
+#endif
+#endif /* !Z_FREETYPE */
#ifdef __cplusplus
}
#endif
-#endif /* _ZLIB_H */
+#endif /* ZLIB_H */
diff --git a/thirdparty/freetype/src/gzip/zutil.c b/thirdparty/freetype/src/gzip/zutil.c
index 7ad0c1f81b..a19ac2b96d 100644
--- a/thirdparty/freetype/src/gzip/zutil.c
+++ b/thirdparty/freetype/src/gzip/zutil.c
@@ -1,23 +1,155 @@
/* zutil.c -- target dependent utility functions for the compression library
- * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * Copyright (C) 1995-2017 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#include "zutil.h"
+#ifndef Z_SOLO
+# include "gzguts.h"
+#endif
-#ifndef STDC
-extern void exit OF((int));
+z_const char * const z_errmsg[10] = {
+ (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */
+ (z_const char *)"stream end", /* Z_STREAM_END 1 */
+ (z_const char *)"", /* Z_OK 0 */
+ (z_const char *)"file error", /* Z_ERRNO (-1) */
+ (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */
+ (z_const char *)"data error", /* Z_DATA_ERROR (-3) */
+ (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */
+ (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */
+ (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */
+ (z_const char *)""
+};
+
+
+const char * ZEXPORT zlibVersion()
+{
+ return ZLIB_VERSION;
+}
+
+uLong ZEXPORT zlibCompileFlags()
+{
+ uLong flags;
+
+ flags = 0;
+ switch ((int)(sizeof(uInt))) {
+ case 2: break;
+ case 4: flags += 1; break;
+ case 8: flags += 2; break;
+ default: flags += 3;
+ }
+ switch ((int)(sizeof(uLong))) {
+ case 2: break;
+ case 4: flags += 1 << 2; break;
+ case 8: flags += 2 << 2; break;
+ default: flags += 3 << 2;
+ }
+ switch ((int)(sizeof(voidpf))) {
+ case 2: break;
+ case 4: flags += 1 << 4; break;
+ case 8: flags += 2 << 4; break;
+ default: flags += 3 << 4;
+ }
+ switch ((int)(sizeof(z_off_t))) {
+ case 2: break;
+ case 4: flags += 1 << 6; break;
+ case 8: flags += 2 << 6; break;
+ default: flags += 3 << 6;
+ }
+#ifdef ZLIB_DEBUG
+ flags += 1 << 8;
+#endif
+#if defined(ASMV) || defined(ASMINF)
+ flags += 1 << 9;
+#endif
+#ifdef ZLIB_WINAPI
+ flags += 1 << 10;
+#endif
+#ifdef BUILDFIXED
+ flags += 1 << 12;
+#endif
+#ifdef DYNAMIC_CRC_TABLE
+ flags += 1 << 13;
+#endif
+#ifdef NO_GZCOMPRESS
+ flags += 1L << 16;
+#endif
+#ifdef NO_GZIP
+ flags += 1L << 17;
+#endif
+#ifdef PKZIP_BUG_WORKAROUND
+ flags += 1L << 20;
+#endif
+#ifdef FASTEST
+ flags += 1L << 21;
+#endif
+#if defined(STDC) || defined(Z_HAVE_STDARG_H)
+# ifdef NO_vsnprintf
+ flags += 1L << 25;
+# ifdef HAS_vsprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_vsnprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#else
+ flags += 1L << 24;
+# ifdef NO_snprintf
+ flags += 1L << 25;
+# ifdef HAS_sprintf_void
+ flags += 1L << 26;
+# endif
+# else
+# ifdef HAS_snprintf_void
+ flags += 1L << 26;
+# endif
+# endif
+#endif
+ return flags;
+}
+
+#ifdef ZLIB_DEBUG
+#include <stdlib.h>
+# ifndef verbose
+# define verbose 0
+# endif
+int ZLIB_INTERNAL z_verbose = verbose;
+
+void ZLIB_INTERNAL z_error (
+ char *m)
+{
+ fprintf(stderr, "%s\n", m);
+ exit(1);
+}
#endif
+/* exported to allow conversion of error code to string for compress() and
+ * uncompress()
+ */
+const char * ZEXPORT zError(
+ int err)
+{
+ return ERR_MSG(err);
+}
+
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
+ * errno. We define it as a global variable to simplify porting.
+ * Its value is always 0 and should not be used.
+ */
+ int errno = 0;
+#endif
#ifndef HAVE_MEMCPY
-void zmemcpy(dest, source, len)
- Bytef* dest;
- const Bytef* source;
- uInt len;
+void ZLIB_INTERNAL zmemcpy(
+ Bytef* dest,
+ const Bytef* source,
+ uInt len)
{
if (len == 0) return;
do {
@@ -25,10 +157,10 @@ void zmemcpy(dest, source, len)
} while (--len != 0);
}
-int zmemcmp(s1, s2, len)
- const Bytef* s1;
- const Bytef* s2;
- uInt len;
+int ZLIB_INTERNAL zmemcmp(
+ const Bytef* s1,
+ const Bytef* s2,
+ uInt len)
{
uInt j;
@@ -38,9 +170,9 @@ int zmemcmp(s1, s2, len)
return 0;
}
-void zmemzero(dest, len)
- Bytef* dest;
- uInt len;
+void ZLIB_INTERNAL zmemzero(
+ Bytef* dest,
+ uInt len)
{
if (len == 0) return;
do {
@@ -49,11 +181,13 @@ void zmemzero(dest, len)
}
#endif
-#if defined( MSDOS ) && defined( __TURBOC__ ) && !defined( MY_ZCALLOC )
-#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__)
-/* Small and medium model in Turbo C are for now limited to near allocation
- * with reduced MAX_WBITS and MAX_MEM_LEVEL
- */
+#ifndef Z_SOLO
+
+#ifdef SYS16BIT
+
+#ifdef __TURBOC__
+/* Turbo C in 16-bit mode */
+
# define MY_ZCALLOC
/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
@@ -80,11 +214,13 @@ local ptr_table table[MAX_PTR];
* a protected system like OS/2. Use Microsoft C instead.
*/
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
{
- voidpf buf = opaque; /* just to make some compilers happy */
+ voidpf buf;
ulg bsize = (ulg)items*size;
+ (void)opaque;
+
/* If we allocate less than 65520 bytes, we assume that farmalloc
* will return a usable pointer which doesn't have to be normalized.
*/
@@ -104,9 +240,12 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
return buf;
}
-void zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{
int n;
+
+ (void)opaque;
+
if (*(ush*)&ptr != 0) { /* object < 64K */
farfree(ptr);
return;
@@ -122,14 +261,13 @@ void zcfree (voidpf opaque, voidpf ptr)
next_ptr--;
return;
}
- ptr = opaque; /* just to make some compilers happy */
Assert(0, "zcfree: ptr not found");
}
-#endif
-#endif /* MSDOS && __TURBOC__ */
+
+#endif /* __TURBOC__ */
-#if defined(M_I86) && !defined(__32BIT__) && !defined( MY_ZCALLOC )
+#ifdef M_I86
/* Microsoft C in 16-bit mode */
# define MY_ZCALLOC
@@ -139,43 +277,49 @@ void zcfree (voidpf opaque, voidpf ptr)
# define _hfree hfree
#endif
-voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
+voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
{
- if (opaque) opaque = 0; /* to make compiler happy */
+ (void)opaque;
return _halloc((long)items, size);
}
-void zcfree (voidpf opaque, voidpf ptr)
+void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{
- if (opaque) opaque = 0; /* to make compiler happy */
+ (void)opaque;
_hfree(ptr);
}
-#endif /* MSC */
+#endif /* M_I86 */
+
+#endif /* SYS16BIT */
#ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC
-extern voidp ft_scalloc OF((uInt items, uInt size));
-extern void ft_sfree OF((voidpf ptr));
+extern voidp malloc OF((uInt size));
+extern voidp calloc OF((uInt items, uInt size));
+extern void free OF((voidpf ptr));
#endif
-voidpf zcalloc (opaque, items, size)
- voidpf opaque;
- unsigned items;
- unsigned size;
+voidpf ZLIB_INTERNAL zcalloc (
+ voidpf opaque,
+ unsigned items,
+ unsigned size)
{
- if (opaque) items += size - size; /* make compiler happy */
- return (voidpf)ft_scalloc(items, size);
+ (void)opaque;
+ return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
+ (voidpf)calloc(items, size);
}
-void zcfree (opaque, ptr)
- voidpf opaque;
- voidpf ptr;
+void ZLIB_INTERNAL zcfree (
+ voidpf opaque,
+ voidpf ptr)
{
- ft_sfree(ptr);
- if (opaque) return; /* make compiler happy */
+ (void)opaque;
+ free(ptr);
}
#endif /* MY_ZCALLOC */
+
+#endif /* !Z_SOLO */
diff --git a/thirdparty/freetype/src/gzip/zutil.h b/thirdparty/freetype/src/gzip/zutil.h
index c9688cd9c0..14f0f1a85e 100644
--- a/thirdparty/freetype/src/gzip/zutil.h
+++ b/thirdparty/freetype/src/gzip/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2002 Jean-loup Gailly.
+ * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -10,26 +10,31 @@
/* @(#) $Id$ */
-#ifndef _Z_UTIL_H
-#define _Z_UTIL_H
+#ifndef ZUTIL_H
+#define ZUTIL_H
+
+#ifdef HAVE_HIDDEN
+# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
+#else
+# define ZLIB_INTERNAL
+#endif
#include "zlib.h"
-#ifdef STDC
-# include <stddef.h>
+#if defined(STDC) && !defined(Z_SOLO)
+# if !(defined(_WIN32_WCE) && defined(_MSC_VER))
+# include <stddef.h>
+# endif
# include <string.h>
# include <stdlib.h>
#endif
-#ifdef NO_ERRNO_H
- extern int errno;
-#else
-# include <errno.h>
-#endif
#ifndef local
# define local static
#endif
-/* compile with -Dlocal if your debugger can't find static symbols */
+/* since "static" is used to mean two completely different things in C, we
+ define "local" for the non-static meaning of "static", for readability
+ (compile with -Dlocal if your debugger can't find static symbols) */
typedef unsigned char uch;
typedef uch FAR uchf;
@@ -37,9 +42,24 @@ typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
+extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
#define ERR_RETURN(strm,err) \
- return (strm->msg = (char*)ERR_MSG(err), (err))
+ return (strm->msg = ERR_MSG(err), (err))
/* To be used only when the state is known to be valid */
/* common constants */
@@ -69,90 +89,129 @@ typedef unsigned long ulg;
/* target dependencies */
-#ifdef MSDOS
+#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00
-# if defined(__TURBOC__) || defined(__BORLANDC__)
-# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
- /* Allow compilation with ANSI keywords only enabled */
- void _Cdecl farfree( void *block );
- void *_Cdecl farmalloc( unsigned long nbytes );
-# else
-# include <alloc.h>
+# ifndef Z_SOLO
+# if defined(__TURBOC__) || defined(__BORLANDC__)
+# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
+ /* Allow compilation with ANSI keywords only enabled */
+ void _Cdecl farfree( void *block );
+ void *_Cdecl farmalloc( unsigned long nbytes );
+# else
+# include <alloc.h>
+# endif
+# else /* MSC or DJGPP */
+# include <malloc.h>
# endif
-# else /* MSC or DJGPP */
# endif
#endif
-#ifdef OS2
-# define OS_CODE 0x06
-#endif
-
-#ifdef WIN32 /* Window 95 & Windows NT */
-# define OS_CODE 0x0b
+#ifdef AMIGA
+# define OS_CODE 1
#endif
#if defined(VAXC) || defined(VMS)
-# define OS_CODE 0x02
+# define OS_CODE 2
# define F_OPEN(name, mode) \
- ft_fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
+ fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512")
#endif
-#ifdef AMIGA
-# define OS_CODE 0x01
+#ifdef __370__
+# if __TARGET_LIB__ < 0x20000000
+# define OS_CODE 4
+# elif __TARGET_LIB__ < 0x40000000
+# define OS_CODE 11
+# else
+# define OS_CODE 8
+# endif
#endif
#if defined(ATARI) || defined(atarist)
-# define OS_CODE 0x05
+# define OS_CODE 5
+#endif
+
+#ifdef OS2
+# define OS_CODE 6
+# if defined(M_I86) && !defined(Z_SOLO)
+# include <malloc.h>
+# endif
#endif
#if defined(MACOS) || defined(TARGET_OS_MAC)
-# define OS_CODE 0x07
-# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
-# include <unix.h> /* for fdopen */
-# else
-# ifndef fdopen
-# define fdopen(fd,mode) NULL /* No fdopen() */
+# define OS_CODE 7
+# ifndef Z_SOLO
+# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os
+# include <unix.h> /* for fdopen */
+# else
+# ifndef fdopen
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# endif
# endif
# endif
#endif
-#ifdef __50SERIES /* Prime/PRIMOS */
-# define OS_CODE 0x0F
+#ifdef __acorn
+# define OS_CODE 13
+#endif
+
+#if defined(WIN32) && !defined(__CYGWIN__)
+# define OS_CODE 10
+#endif
+
+#ifdef _BEOS_
+# define OS_CODE 16
#endif
-#ifdef TOPS20
-# define OS_CODE 0x0a
+#ifdef __TOS_OS400__
+# define OS_CODE 18
+#endif
+
+#ifdef __APPLE__
+# define OS_CODE 19
#endif
#if defined(_BEOS_) || defined(RISCOS)
# define fdopen(fd,mode) NULL /* No fdopen() */
#endif
-#if (defined(_MSC_VER) && (_MSC_VER > 600))
-# define fdopen(fd,type) _fdopen(fd,type)
+#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
+# if defined(_WIN32_WCE)
+# define fdopen(fd,mode) NULL /* No fdopen() */
+# else
+# define fdopen(fd,type) _fdopen(fd,type)
+# endif
#endif
+#if defined(__BORLANDC__) && !defined(MSDOS)
+ #pragma warn -8004
+ #pragma warn -8008
+ #pragma warn -8066
+#endif
- /* Common defaults */
+#ifndef Z_FREETYPE
+
+/* provide prototypes for these when building zlib without LFS */
+#if !defined(_WIN32) && \
+ (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
+ ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#endif
+
+#endif /* !Z_FREETYPE */
+
+ /* common defaults */
#ifndef OS_CODE
-# define OS_CODE 0x03 /* assume Unix */
+# define OS_CODE 3 /* assume Unix */
#endif
#ifndef F_OPEN
-# define F_OPEN(name, mode) ft_fopen((name), (mode))
+# define F_OPEN(name, mode) fopen((name), (mode))
#endif
/* functions */
-#ifdef HAVE_STRERROR
- extern char *strerror OF((int));
-# define zstrerror(errnum) strerror(errnum)
-#else
-# define zstrerror(errnum) ""
-#endif
-
-#if defined(pyr)
+#if defined(pyr) || defined(Z_SOLO)
# define NO_MEMCPY
#endif
#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__)
@@ -176,16 +235,16 @@ typedef unsigned long ulg;
# define zmemzero(dest, len) ft_memset(dest, 0, len)
# endif
#else
- extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
- extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
- extern void zmemzero OF((Bytef* dest, uInt len));
+ void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
+ int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
+ void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
#endif
/* Diagnostic functions */
-#ifdef DEBUG
+#ifdef ZLIB_DEBUG
# include <stdio.h>
- extern int z_verbose;
- extern void z_error OF((char *m));
+ extern int ZLIB_INTERNAL z_verbose;
+ extern void ZLIB_INTERNAL z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;}
@@ -201,15 +260,19 @@ typedef unsigned long ulg;
# define Tracecv(c,x)
#endif
-
-typedef uLong (*check_func) OF((uLong check, const Bytef *buf,
- uInt len));
-local voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size));
-local void zcfree OF((voidpf opaque, voidpf ptr));
+#ifndef Z_SOLO
+ voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
+ unsigned size));
+ void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
+#endif
#define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size))
#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr))
#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-#endif /* _Z_UTIL_H */
+/* Reverse the bytes in a 32-bit value */
+#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \
+ (((q) & 0xff00) << 8) + (((q) & 0xff) << 24))
+
+#endif /* ZUTIL_H */
diff --git a/thirdparty/freetype/src/lzw/ftlzw.c b/thirdparty/freetype/src/lzw/ftlzw.c
index e112418ab1..e12efcaa56 100644
--- a/thirdparty/freetype/src/lzw/ftlzw.c
+++ b/thirdparty/freetype/src/lzw/ftlzw.c
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* Albert Chin-A-Young.
*
* based on code in `src/gzip/ftgzip.c'
@@ -369,7 +369,7 @@
FT_ZERO( stream );
stream->memory = memory;
- if ( !FT_NEW( zip ) )
+ if ( !FT_QNEW( zip ) )
{
error = ft_lzw_file_init( zip, stream, source );
if ( error )
diff --git a/thirdparty/freetype/src/lzw/ftzopen.c b/thirdparty/freetype/src/lzw/ftzopen.c
index 8b5b357f36..aaa98be211 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.c
+++ b/thirdparty/freetype/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/lzw/ftzopen.h b/thirdparty/freetype/src/lzw/ftzopen.h
index 9ada742c73..86fccfe3be 100644
--- a/thirdparty/freetype/src/lzw/ftzopen.h
+++ b/thirdparty/freetype/src/lzw/ftzopen.h
@@ -8,7 +8,7 @@
* be used to parse compressed PCF fonts, as found with many X11 server
* distributions.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.c b/thirdparty/freetype/src/otvalid/otvalid.c
index 869233ce8c..f5344ca031 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.c
+++ b/thirdparty/freetype/src/otvalid/otvalid.c
@@ -4,7 +4,7 @@
*
* FreeType validator for OpenType tables (body only).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvalid.h b/thirdparty/freetype/src/otvalid/otvalid.h
index f8ca454d6e..6274858f51 100644
--- a/thirdparty/freetype/src/otvalid/otvalid.h
+++ b/thirdparty/freetype/src/otvalid/otvalid.h
@@ -4,7 +4,7 @@
*
* OpenType table validation (specification only).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvbase.c b/thirdparty/freetype/src/otvalid/otvbase.c
index 83f998cdb1..70de653b19 100644
--- a/thirdparty/freetype/src/otvalid/otvbase.c
+++ b/thirdparty/freetype/src/otvalid/otvbase.c
@@ -4,7 +4,7 @@
*
* OpenType BASE table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.c b/thirdparty/freetype/src/otvalid/otvcommn.c
index 40624bb159..b9873ff21b 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.c
+++ b/thirdparty/freetype/src/otvalid/otvcommn.c
@@ -4,7 +4,7 @@
*
* OpenType common tables validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvcommn.h b/thirdparty/freetype/src/otvalid/otvcommn.h
index 3b096ecca8..f1e4a6a9a6 100644
--- a/thirdparty/freetype/src/otvalid/otvcommn.h
+++ b/thirdparty/freetype/src/otvalid/otvcommn.h
@@ -4,7 +4,7 @@
*
* OpenType common tables validation (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otverror.h b/thirdparty/freetype/src/otvalid/otverror.h
index 3e23234f36..8c75c58299 100644
--- a/thirdparty/freetype/src/otvalid/otverror.h
+++ b/thirdparty/freetype/src/otvalid/otverror.h
@@ -4,7 +4,7 @@
*
* OpenType validation module error codes (specification only).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgdef.c b/thirdparty/freetype/src/otvalid/otvgdef.c
index 5a160a4142..425335336d 100644
--- a/thirdparty/freetype/src/otvalid/otvgdef.c
+++ b/thirdparty/freetype/src/otvalid/otvgdef.c
@@ -4,7 +4,7 @@
*
* OpenType GDEF table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.c b/thirdparty/freetype/src/otvalid/otvgpos.c
index e0d4e420de..52e2cd1c22 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.c
+++ b/thirdparty/freetype/src/otvalid/otvgpos.c
@@ -4,7 +4,7 @@
*
* OpenType GPOS table validation (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgpos.h b/thirdparty/freetype/src/otvalid/otvgpos.h
index 176a68883f..85ef609160 100644
--- a/thirdparty/freetype/src/otvalid/otvgpos.h
+++ b/thirdparty/freetype/src/otvalid/otvgpos.h
@@ -4,7 +4,7 @@
*
* OpenType GPOS table validator (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvgsub.c b/thirdparty/freetype/src/otvalid/otvgsub.c
index b426a17449..3b6dcbb7ae 100644
--- a/thirdparty/freetype/src/otvalid/otvgsub.c
+++ b/thirdparty/freetype/src/otvalid/otvgsub.c
@@ -4,7 +4,7 @@
*
* OpenType GSUB table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvjstf.c b/thirdparty/freetype/src/otvalid/otvjstf.c
index 404dda88a1..0934716a5a 100644
--- a/thirdparty/freetype/src/otvalid/otvjstf.c
+++ b/thirdparty/freetype/src/otvalid/otvjstf.c
@@ -4,7 +4,7 @@
*
* OpenType JSTF table validation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvmath.c b/thirdparty/freetype/src/otvalid/otvmath.c
index b4bfabb62e..a59557b375 100644
--- a/thirdparty/freetype/src/otvalid/otvmath.c
+++ b/thirdparty/freetype/src/otvalid/otvmath.c
@@ -4,7 +4,7 @@
*
* OpenType MATH table validation (body).
*
- * Copyright (C) 2007-2021 by
+ * Copyright (C) 2007-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by George Williams.
diff --git a/thirdparty/freetype/src/otvalid/otvmod.c b/thirdparty/freetype/src/otvalid/otvmod.c
index b7d674b5e2..3fc2dbe504 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.c
+++ b/thirdparty/freetype/src/otvalid/otvmod.c
@@ -4,7 +4,7 @@
*
* FreeType's OpenType validation module implementation (body).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/otvalid/otvmod.h b/thirdparty/freetype/src/otvalid/otvmod.h
index 37c20e0023..2f0bcd6e44 100644
--- a/thirdparty/freetype/src/otvalid/otvmod.h
+++ b/thirdparty/freetype/src/otvalid/otvmod.h
@@ -5,7 +5,7 @@
* FreeType's OpenType validation module implementation
* (specification).
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pcf/README b/thirdparty/freetype/src/pcf/README
deleted file mode 100644
index 09ea970eda..0000000000
--- a/thirdparty/freetype/src/pcf/README
+++ /dev/null
@@ -1,96 +0,0 @@
- FreeType font driver for PCF fonts
-
- Francesco Zappa Nardelli
- <francesco.zappa.nardelli@ens.fr>
-
-
-Introduction
-************
-
-PCF (Portable Compiled Format) is a binary bitmap font format, largely used
-in X world. This code implements a PCF driver for the FreeType library.
-Glyph images are loaded into memory only on demand, thus leading to a small
-memory footprint.
-
-Information on the PCF font format can only be worked out from
-`pcfread.c', and `pcfwrite.c', to be found, for instance, in the XFree86
-(www.xfree86.org) source tree (xc/lib/font/bitmap/).
-
-Many good bitmap fonts in bdf format come with XFree86: they can be
-compiled into the pcf format using the `bdftopcf' utility.
-
-
-Supported hardware
-******************
-
-The driver has been tested on linux/x86 and sunos5.5/sparc. In both
-cases the compiler was gcc. When back in Paris, I will test it also
-on linux/alpha.
-
-
-Encodings
-*********
-
-Use `FT_Get_BDF_Charset_ID' to access the encoding and registry.
-
-The driver always exports `ft_encoding_none' as face->charmap.encoding.
-FT_Get_Char_Index() behavior is unmodified, that is, it converts the ULong
-value given as argument into the corresponding glyph number.
-
-
-Known problems
-**************
-
-- dealing explicitly with encodings breaks the uniformity of FreeType 2
- API.
-
-- except for encodings properties, client applications have no
- visibility of the PCF_Face object. This means that applications
- cannot directly access font tables and are obliged to trust
- FreeType.
-
-- currently, glyph names and ink_metrics are ignored.
-
-I plan to give full visibility of the PCF_Face object in the next
-release of the driver, thus implementing also glyph names and
-ink_metrics.
-
-- height is defined as (ascent - descent). Is this correct?
-
-- if unable to read size information from the font, PCF_Init_Face
- sets available_size->width and available_size->height to 12.
-
-- too many english grammar errors in the readme file :-(
-
-
-License
-*******
-
-Copyright (C) 2000 by Francesco Zappa Nardelli
-
-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.
-
-
-Credits
-*******
-
-Keith Packard wrote the pcf driver found in XFree86. His work is at
-the same time the specification and the sample implementation of the
-PCF format. Undoubtedly, this driver is inspired from his work.
diff --git a/thirdparty/freetype/src/pcf/pcfread.c b/thirdparty/freetype/src/pcf/pcfread.c
index e60a0a5141..f167bcb8ae 100644
--- a/thirdparty/freetype/src/pcf/pcfread.c
+++ b/thirdparty/freetype/src/pcf/pcfread.c
@@ -1034,16 +1034,6 @@ THE SOFTWARE.
enc->lastRow > 0xFF )
return FT_THROW( Invalid_Table );
- nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) *
- (FT_ULong)( enc->lastRow - enc->firstRow + 1 );
-
- if ( FT_NEW_ARRAY( enc->offset, nencoding ) )
- goto Bail;
-
- error = FT_Stream_EnterFrame( stream, 2 * nencoding );
- if ( error )
- goto Exit;
-
FT_TRACE5(( "\n" ));
defaultCharRow = enc->defaultChar >> 8;
@@ -1064,6 +1054,13 @@ THE SOFTWARE.
defaultCharCol = enc->firstCol;
}
+ nencoding = (FT_ULong)( enc->lastCol - enc->firstCol + 1 ) *
+ (FT_ULong)( enc->lastRow - enc->firstRow + 1 );
+
+ error = FT_Stream_EnterFrame( stream, 2 * nencoding );
+ if ( error )
+ goto Bail;
+
/*
* FreeType mandates that glyph index 0 is the `undefined glyph', which
* PCF calls the `default character'. However, FreeType needs glyph
@@ -1109,6 +1106,9 @@ THE SOFTWARE.
/* copy metrics of default character to index 0 */
face->metrics[0] = face->metrics[defaultCharEncodingOffset];
+ if ( FT_QNEW_ARRAY( enc->offset, nencoding ) )
+ goto Bail;
+
/* now loop over all values */
offset = enc->offset;
for ( i = enc->firstRow; i <= enc->lastRow; i++ )
@@ -1131,11 +1131,6 @@ THE SOFTWARE.
}
FT_Stream_ExitFrame( stream );
- return error;
-
- Exit:
- FT_FREE( enc->offset );
-
Bail:
return error;
}
diff --git a/thirdparty/freetype/src/pfr/pfr.c b/thirdparty/freetype/src/pfr/pfr.c
index 4058ad5652..1dd38f9393 100644
--- a/thirdparty/freetype/src/pfr/pfr.c
+++ b/thirdparty/freetype/src/pfr/pfr.c
@@ -4,7 +4,7 @@
*
* FreeType PFR driver component.
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.c b/thirdparty/freetype/src/pfr/pfrcmap.c
index 6a7f573594..6fa2417dc1 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.c
+++ b/thirdparty/freetype/src/pfr/pfrcmap.c
@@ -4,7 +4,7 @@
*
* FreeType PFR cmap handling (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrcmap.h b/thirdparty/freetype/src/pfr/pfrcmap.h
index 17c02a2b4b..afde164f9b 100644
--- a/thirdparty/freetype/src/pfr/pfrcmap.h
+++ b/thirdparty/freetype/src/pfr/pfrcmap.h
@@ -4,7 +4,7 @@
*
* FreeType PFR cmap handling (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.c b/thirdparty/freetype/src/pfr/pfrdrivr.c
index 16b8f79471..2a753c583a 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.c
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.c
@@ -4,7 +4,7 @@
*
* FreeType PFR driver interface (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrdrivr.h b/thirdparty/freetype/src/pfr/pfrdrivr.h
index 6ff16fea06..cfd749ab0e 100644
--- a/thirdparty/freetype/src/pfr/pfrdrivr.h
+++ b/thirdparty/freetype/src/pfr/pfrdrivr.h
@@ -4,7 +4,7 @@
*
* High-level Type PFR driver interface (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrerror.h b/thirdparty/freetype/src/pfr/pfrerror.h
index 255696efed..98b8f2fd58 100644
--- a/thirdparty/freetype/src/pfr/pfrerror.h
+++ b/thirdparty/freetype/src/pfr/pfrerror.h
@@ -4,7 +4,7 @@
*
* PFR error codes (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrgload.c b/thirdparty/freetype/src/pfr/pfrgload.c
index b400042a86..1b8d6cdecc 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.c
+++ b/thirdparty/freetype/src/pfr/pfrgload.c
@@ -4,7 +4,7 @@
*
* FreeType PFR glyph loader (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrgload.h b/thirdparty/freetype/src/pfr/pfrgload.h
index b726d564fc..af59296910 100644
--- a/thirdparty/freetype/src/pfr/pfrgload.h
+++ b/thirdparty/freetype/src/pfr/pfrgload.h
@@ -4,7 +4,7 @@
*
* FreeType PFR glyph loader (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrload.c b/thirdparty/freetype/src/pfr/pfrload.c
index a9c1e2834a..6bf7979750 100644
--- a/thirdparty/freetype/src/pfr/pfrload.c
+++ b/thirdparty/freetype/src/pfr/pfrload.c
@@ -4,7 +4,7 @@
*
* FreeType PFR loader (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -993,7 +993,7 @@
PFR_CHECK_SIZE( count * Size );
- if ( FT_NEW_ARRAY( phy_font->chars, count ) )
+ if ( FT_QNEW_ARRAY( phy_font->chars, count ) )
goto Fail;
for ( n = 0; n < count; n++ )
diff --git a/thirdparty/freetype/src/pfr/pfrload.h b/thirdparty/freetype/src/pfr/pfrload.h
index 4f467d1bad..5e0f451fa0 100644
--- a/thirdparty/freetype/src/pfr/pfrload.h
+++ b/thirdparty/freetype/src/pfr/pfrload.h
@@ -4,7 +4,7 @@
*
* FreeType PFR loader (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.c b/thirdparty/freetype/src/pfr/pfrobjs.c
index 3080cb650b..5a6e3979d5 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.c
+++ b/thirdparty/freetype/src/pfr/pfrobjs.c
@@ -4,7 +4,7 @@
*
* FreeType PFR object methods (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -207,7 +207,7 @@
pfrface->height = (FT_Short)( ( pfrface->units_per_EM * 12 ) / 10 );
if ( pfrface->height < pfrface->ascender - pfrface->descender )
- pfrface->height = (FT_Short)(pfrface->ascender - pfrface->descender);
+ pfrface->height = (FT_Short)( pfrface->ascender - pfrface->descender );
if ( phy_font->num_strikes > 0 )
{
diff --git a/thirdparty/freetype/src/pfr/pfrobjs.h b/thirdparty/freetype/src/pfr/pfrobjs.h
index 70b05395b8..9ffc297d59 100644
--- a/thirdparty/freetype/src/pfr/pfrobjs.h
+++ b/thirdparty/freetype/src/pfr/pfrobjs.h
@@ -4,7 +4,7 @@
*
* FreeType PFR object methods (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.c b/thirdparty/freetype/src/pfr/pfrsbit.c
index 255fd58772..8b23fa156d 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.c
+++ b/thirdparty/freetype/src/pfr/pfrsbit.c
@@ -4,7 +4,7 @@
*
* FreeType PFR bitmap loader (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrsbit.h b/thirdparty/freetype/src/pfr/pfrsbit.h
index f50d8013aa..b948a3842f 100644
--- a/thirdparty/freetype/src/pfr/pfrsbit.h
+++ b/thirdparty/freetype/src/pfr/pfrsbit.h
@@ -4,7 +4,7 @@
*
* FreeType PFR bitmap loader (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pfr/pfrtypes.h b/thirdparty/freetype/src/pfr/pfrtypes.h
index dc4fead700..d9a0c78953 100644
--- a/thirdparty/freetype/src/pfr/pfrtypes.h
+++ b/thirdparty/freetype/src/pfr/pfrtypes.h
@@ -4,7 +4,7 @@
*
* FreeType PFR data structures (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/afmparse.c b/thirdparty/freetype/src/psaux/afmparse.c
index 0ad1760518..bd86129f7e 100644
--- a/thirdparty/freetype/src/psaux/afmparse.c
+++ b/thirdparty/freetype/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
*
* AFM parser (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/afmparse.h b/thirdparty/freetype/src/psaux/afmparse.h
index 44b05b2cac..eee49e3601 100644
--- a/thirdparty/freetype/src/psaux/afmparse.h
+++ b/thirdparty/freetype/src/psaux/afmparse.h
@@ -4,7 +4,7 @@
*
* AFM parser (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/cffdecode.c b/thirdparty/freetype/src/psaux/cffdecode.c
index 29b68a8e4f..92139c93ad 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.c
+++ b/thirdparty/freetype/src/psaux/cffdecode.c
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (body).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -248,7 +248,7 @@
else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
- CFF_Font cff = (CFF_Font)(face->extra.data);
+ CFF_Font cff = (CFF_Font)( face->extra.data );
bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
diff --git a/thirdparty/freetype/src/psaux/cffdecode.h b/thirdparty/freetype/src/psaux/cffdecode.h
index b1314ed1c1..a9f6761824 100644
--- a/thirdparty/freetype/src/psaux/cffdecode.h
+++ b/thirdparty/freetype/src/psaux/cffdecode.h
@@ -4,7 +4,7 @@
*
* PostScript CFF (Type 2) decoding routines (specification).
*
- * Copyright (C) 2017-2021 by
+ * Copyright (C) 2017-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psaux.c b/thirdparty/freetype/src/psaux/psaux.c
index 2960c8b696..2ac7949479 100644
--- a/thirdparty/freetype/src/psaux/psaux.c
+++ b/thirdparty/freetype/src/psaux/psaux.c
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript driver component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxerr.h b/thirdparty/freetype/src/psaux/psauxerr.h
index e8ee29166c..1504b34ee5 100644
--- a/thirdparty/freetype/src/psaux/psauxerr.h
+++ b/thirdparty/freetype/src/psaux/psauxerr.h
@@ -4,7 +4,7 @@
*
* PS auxiliary module error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxmod.c b/thirdparty/freetype/src/psaux/psauxmod.c
index 52da23365e..113490abcd 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.c
+++ b/thirdparty/freetype/src/psaux/psauxmod.c
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psauxmod.h b/thirdparty/freetype/src/psaux/psauxmod.h
index e3e8063220..2d508edc2a 100644
--- a/thirdparty/freetype/src/psaux/psauxmod.h
+++ b/thirdparty/freetype/src/psaux/psauxmod.h
@@ -4,7 +4,7 @@
*
* FreeType auxiliary PostScript module implementation (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psconv.c b/thirdparty/freetype/src/psaux/psconv.c
index c28d65df29..9b8c0d90c3 100644
--- a/thirdparty/freetype/src/psaux/psconv.c
+++ b/thirdparty/freetype/src/psaux/psconv.c
@@ -4,7 +4,7 @@
*
* Some convenience conversions (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -535,11 +535,11 @@
if ( r & 1 )
{
- *buffer = (FT_Byte)(*buffer + c);
+ *buffer = (FT_Byte)( *buffer + c );
buffer++;
}
else
- *buffer = (FT_Byte)(c << 4);
+ *buffer = (FT_Byte)( c << 4 );
r++;
}
@@ -572,8 +572,8 @@
if ( p >= limit )
return 0;
- if ( n > (FT_UInt)(limit - p) )
- n = (FT_UInt)(limit - p);
+ if ( n > (FT_UInt)( limit - p ) )
+ n = (FT_UInt)( limit - p );
for ( r = 0; r < n; r++ )
{
diff --git a/thirdparty/freetype/src/psaux/psconv.h b/thirdparty/freetype/src/psaux/psconv.h
index cd91a7bb56..650d7c93b2 100644
--- a/thirdparty/freetype/src/psaux/psconv.h
+++ b/thirdparty/freetype/src/psaux/psconv.h
@@ -4,7 +4,7 @@
*
* Some convenience conversions (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/psintrp.c b/thirdparty/freetype/src/psaux/psintrp.c
index c550533a0f..6c640eebd5 100644
--- a/thirdparty/freetype/src/psaux/psintrp.c
+++ b/thirdparty/freetype/src/psaux/psintrp.c
@@ -1900,7 +1900,8 @@
/* WeightVector */
{
FT_UInt idx;
- PS_Blend blend = decoder->blend;
+ PS_Blend blend = decoder->blend;
+ FT_UInt len_buildchar = decoder->len_buildchar;
if ( arg_cnt != 1 || !blend )
@@ -1908,14 +1909,15 @@
idx = (FT_UInt)cf2_stack_popInt( opStack );
- if ( idx + blend->num_designs >
- decoder->len_buildchar )
+ if ( len_buildchar < blend->num_designs ||
+ len_buildchar - blend->num_designs < idx )
goto Unexpected_OtherSubr;
- ft_memcpy( &decoder->buildchar[idx],
- blend->weight_vector,
- blend->num_designs *
- sizeof ( blend->weight_vector[0] ) );
+ if ( decoder->buildchar && blend->weight_vector )
+ ft_memcpy( &decoder->buildchar[idx],
+ blend->weight_vector,
+ blend->num_designs *
+ sizeof ( blend->weight_vector[0] ) );
}
break;
diff --git a/thirdparty/freetype/src/psaux/psobjs.c b/thirdparty/freetype/src/psaux/psobjs.c
index 30f501916a..371e538020 100644
--- a/thirdparty/freetype/src/psaux/psobjs.c
+++ b/thirdparty/freetype/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -99,45 +99,31 @@
}
- static void
- shift_elements( PS_Table table,
- FT_Byte* old_base )
- {
- FT_PtrDist delta = table->block - old_base;
- FT_Byte** offset = table->elements;
- FT_Byte** limit = offset + table->max_elems;
-
-
- for ( ; offset < limit; offset++ )
- {
- if ( offset[0] )
- offset[0] += delta;
- }
- }
-
-
static FT_Error
- reallocate_t1_table( PS_Table table,
- FT_Offset new_size )
+ ps_table_realloc( PS_Table table,
+ FT_Offset new_size )
{
FT_Memory memory = table->memory;
FT_Byte* old_base = table->block;
FT_Error error;
- /* allocate new base block */
- if ( FT_ALLOC( table->block, new_size ) )
- {
- table->block = old_base;
+ /* (re)allocate the base block */
+ if ( FT_REALLOC( table->block, table->capacity, new_size ) )
return error;
- }
- /* copy elements and shift offsets */
- if ( old_base )
+ /* rebase offsets if necessary */
+ if ( old_base && table->block != old_base )
{
- FT_MEM_COPY( table->block, old_base, table->capacity );
- shift_elements( table, old_base );
- FT_FREE( old_base );
+ FT_Byte** offset = table->elements;
+ FT_Byte** limit = offset + table->max_elems;
+
+
+ for ( ; offset < limit; offset++ )
+ {
+ if ( *offset )
+ *offset = table->block + ( *offset - old_base );
+ }
}
table->capacity = new_size;
@@ -204,7 +190,7 @@
new_size = FT_PAD_CEIL( new_size, 1024 );
}
- error = reallocate_t1_table( table, new_size );
+ error = ps_table_realloc( table, new_size );
if ( error )
return error;
@@ -234,32 +220,12 @@
* @InOut:
* table ::
* The target table.
- *
- * @Note:
- * This function does NOT release the heap's memory block. It is up
- * to the caller to clean it, or reference it in its own structures.
*/
FT_LOCAL_DEF( void )
ps_table_done( PS_Table table )
{
- FT_Memory memory = table->memory;
- FT_Error error;
- FT_Byte* old_base = table->block;
-
-
- /* should never fail, because rec.cursor <= rec.size */
- if ( !old_base )
- return;
-
- if ( FT_QALLOC( table->block, table->cursor ) )
- return;
- FT_MEM_COPY( table->block, old_base, table->cursor );
- shift_elements( table, old_base );
-
- table->capacity = table->cursor;
- FT_FREE( old_base );
-
- FT_UNUSED( error );
+ /* no problem if shrinking fails */
+ ps_table_realloc( table, table->cursor );
}
@@ -552,7 +518,7 @@
if ( *cur == '<' ) /* <...> */
{
- if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */
+ if ( cur + 1 < limit && *( cur + 1 ) == '<' ) /* << */
{
cur++;
cur++;
@@ -1098,7 +1064,6 @@
{
FT_Byte* q = (FT_Byte*)objects[idx] + field->offset;
FT_Long val;
- FT_String* string = NULL;
skip_spaces( &cur, limit );
@@ -1148,8 +1113,9 @@
case T1_FIELD_TYPE_STRING:
case T1_FIELD_TYPE_KEY:
{
- FT_Memory memory = parser->memory;
- FT_UInt len = (FT_UInt)( limit - cur );
+ FT_Memory memory = parser->memory;
+ FT_UInt len = (FT_UInt)( limit - cur );
+ FT_String* string = NULL;
if ( cur >= limit )
@@ -1190,7 +1156,6 @@
FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
field->ident ));
FT_FREE( *(FT_String**)q );
- *(FT_String**)q = NULL;
}
if ( FT_QALLOC( string, len + 1 ) )
diff --git a/thirdparty/freetype/src/psaux/psobjs.h b/thirdparty/freetype/src/psaux/psobjs.h
index 99d16959a7..f01d4bd503 100644
--- a/thirdparty/freetype/src/psaux/psobjs.h
+++ b/thirdparty/freetype/src/psaux/psobjs.h
@@ -4,7 +4,7 @@
*
* Auxiliary functions for PostScript fonts (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.c b/thirdparty/freetype/src/psaux/t1cmap.c
index 3e7c577a18..f297ce75e1 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.c
+++ b/thirdparty/freetype/src/psaux/t1cmap.c
@@ -4,7 +4,7 @@
*
* Type 1 character map support (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1cmap.h b/thirdparty/freetype/src/psaux/t1cmap.h
index 8f69600ca4..460d91f590 100644
--- a/thirdparty/freetype/src/psaux/t1cmap.h
+++ b/thirdparty/freetype/src/psaux/t1cmap.h
@@ -4,7 +4,7 @@
*
* Type 1 character map support (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1decode.c b/thirdparty/freetype/src/psaux/t1decode.c
index 7e65bde632..1cdf436fa7 100644
--- a/thirdparty/freetype/src/psaux/t1decode.c
+++ b/thirdparty/freetype/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psaux/t1decode.h b/thirdparty/freetype/src/psaux/t1decode.h
index eea9d34b04..d60d61c904 100644
--- a/thirdparty/freetype/src/psaux/t1decode.h
+++ b/thirdparty/freetype/src/psaux/t1decode.h
@@ -4,7 +4,7 @@
*
* PostScript Type 1 decoding routines (specification).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.c b/thirdparty/freetype/src/pshinter/pshalgo.c
index 227caeae33..dca539766f 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.c
+++ b/thirdparty/freetype/src/pshinter/pshalgo.c
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (body).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
@@ -182,13 +182,13 @@
count = hints->num_hints;
/* allocate our tables */
- if ( FT_NEW_ARRAY( table->sort, 2 * count ) ||
- FT_NEW_ARRAY( table->hints, count ) ||
- FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
+ if ( FT_QNEW_ARRAY( table->sort, 2 * count ) ||
+ FT_QNEW_ARRAY( table->hints, count ) ||
+ FT_QNEW_ARRAY( table->zones, 2 * count + 1 ) )
goto Exit;
table->max_hints = count;
- table->sort_global = table->sort + count;
+ table->sort_global = FT_OFFSET( table->sort, count );
table->num_hints = 0;
table->num_zones = 0;
table->zone = NULL;
@@ -1167,8 +1167,8 @@
memory = glyph->memory = globals->memory;
/* allocate and setup points + contours arrays */
- if ( FT_NEW_ARRAY( glyph->points, outline->n_points ) ||
- FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
+ if ( FT_QNEW_ARRAY( glyph->points, outline->n_points ) ||
+ FT_QNEW_ARRAY( glyph->contours, outline->n_contours ) )
goto Exit;
glyph->num_points = (FT_UInt)outline->n_points;
@@ -1228,8 +1228,9 @@
FT_Pos dxi, dyi, dxo, dyo;
+ point->flags = 0;
if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
- point->flags = PSH_POINT_OFF;
+ psh_point_set_off( point );
dxi = vec[n].x - vec[n_prev].x;
dyi = vec[n].y - vec[n_prev].y;
@@ -1242,14 +1243,14 @@
point->dir_out = psh_compute_dir( dxo, dyo );
/* detect smooth points */
- if ( point->flags & PSH_POINT_OFF )
- point->flags |= PSH_POINT_SMOOTH;
+ if ( psh_point_is_off( point ) )
+ psh_point_set_smooth( point );
else if ( point->dir_in == point->dir_out )
{
if ( point->dir_out != PSH_DIR_NONE ||
psh_corner_is_flat( dxi, dyi, dxo, dyo ) )
- point->flags |= PSH_POINT_SMOOTH;
+ psh_point_set_smooth( point );
}
}
}
@@ -1547,8 +1548,9 @@
/* the accepted shift for strong points in fractional pixels */
#define PSH_STRONG_THRESHOLD 32
- /* the maximum shift value in font units */
-#define PSH_STRONG_THRESHOLD_MAXIMUM 30
+ /* the maximum shift value in font units tuned to distinguish */
+ /* between stems and serifs in URW+ font collection */
+#define PSH_STRONG_THRESHOLD_MAXIMUM 12
/* find strong points in a glyph */
@@ -1797,7 +1799,7 @@
FT_Error error;
- if ( FT_NEW_ARRAY( strongs, num_strongs ) )
+ if ( FT_QNEW_ARRAY( strongs, num_strongs ) )
return;
}
@@ -2110,14 +2112,17 @@
FT_Fixed old_x_scale = x_scale;
FT_Fixed old_y_scale = y_scale;
- FT_Fixed scaled;
- FT_Fixed fitted;
+ FT_Fixed scaled = 0;
+ FT_Fixed fitted = 0;
FT_Bool rescale = FALSE;
- scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
- fitted = FT_PIX_ROUND( scaled );
+ if ( globals->blues.normal_top.count )
+ {
+ scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
+ fitted = FT_PIX_ROUND( scaled );
+ }
if ( fitted != 0 && scaled != fitted )
{
diff --git a/thirdparty/freetype/src/pshinter/pshalgo.h b/thirdparty/freetype/src/pshinter/pshalgo.h
index 999c60192b..ab978bf6d0 100644
--- a/thirdparty/freetype/src/pshinter/pshalgo.h
+++ b/thirdparty/freetype/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
*
* PostScript hinting algorithm (specification).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshglob.c b/thirdparty/freetype/src/pshinter/pshglob.c
index 2ca0f665c6..887ea8d9c1 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.c
+++ b/thirdparty/freetype/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
* PostScript hinter global hinting management (body).
* Inspired by the new auto-hinter module.
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
@@ -650,7 +650,7 @@
FT_Error error;
- if ( !FT_NEW( globals ) )
+ if ( !FT_QNEW( globals ) )
{
FT_UInt count;
FT_Short* read;
diff --git a/thirdparty/freetype/src/pshinter/pshglob.h b/thirdparty/freetype/src/pshinter/pshglob.h
index a8f9953fa0..47247f969e 100644
--- a/thirdparty/freetype/src/pshinter/pshglob.h
+++ b/thirdparty/freetype/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
*
* PostScript hinter global hinting management.
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshinter.c b/thirdparty/freetype/src/pshinter/pshinter.c
index 705143dcdc..22315685f9 100644
--- a/thirdparty/freetype/src/pshinter/pshinter.c
+++ b/thirdparty/freetype/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript Hinting module
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshmod.c b/thirdparty/freetype/src/pshinter/pshmod.c
index 6674041f7e..a74a4fe99f 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.c
+++ b/thirdparty/freetype/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hinter module implementation (body).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshmod.h b/thirdparty/freetype/src/pshinter/pshmod.h
index 8b229bb077..cdf95b7c20 100644
--- a/thirdparty/freetype/src/pshinter/pshmod.h
+++ b/thirdparty/freetype/src/pshinter/pshmod.h
@@ -4,7 +4,7 @@
*
* PostScript hinter module interface (specification).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshnterr.h b/thirdparty/freetype/src/pshinter/pshnterr.h
index 567d765132..789afb5990 100644
--- a/thirdparty/freetype/src/pshinter/pshnterr.h
+++ b/thirdparty/freetype/src/pshinter/pshnterr.h
@@ -4,7 +4,7 @@
*
* PS Hinter error codes (specification only).
*
- * Copyright (C) 2003-2021 by
+ * Copyright (C) 2003-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/pshinter/pshrec.c b/thirdparty/freetype/src/pshinter/pshrec.c
index 1faabdaafa..2a5cffbada 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.c
+++ b/thirdparty/freetype/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
*
* FreeType PostScript hints recorder (body).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -63,16 +63,14 @@
{
FT_UInt old_max = table->max_hints;
FT_UInt new_max = count;
- FT_Error error = FT_Err_Ok;
+ FT_Error error;
- if ( new_max > old_max )
- {
- /* try to grow the table */
- new_max = FT_PAD_CEIL( new_max, 8 );
- if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
- table->max_hints = new_max;
- }
+ /* try to grow the table */
+ new_max = FT_PAD_CEIL( new_max, 8 );
+ if ( !FT_QRENEW_ARRAY( table->hints, old_max, new_max ) )
+ table->max_hints = new_max;
+
return error;
}
@@ -90,17 +88,14 @@
count = table->num_hints;
count++;
- if ( count >= table->max_hints )
+ if ( count > table->max_hints )
{
error = ps_hint_table_ensure( table, count, memory );
if ( error )
goto Exit;
}
- hint = table->hints + count - 1;
- hint->pos = 0;
- hint->len = 0;
- hint->flags = 0;
+ hint = table->hints + count - 1; /* initialized upstream */
table->num_hints = count;
@@ -136,14 +131,15 @@
FT_UInt count,
FT_Memory memory )
{
- FT_UInt old_max = ( mask->max_bits + 7 ) >> 3;
- FT_UInt new_max = ( count + 7 ) >> 3;
+ FT_UInt old_max = mask->max_bits >> 3;
+ FT_UInt new_max = ( count + 7 ) >> 3;
FT_Error error = FT_Err_Ok;
if ( new_max > old_max )
{
new_max = FT_PAD_CEIL( new_max, 8 );
+ /* added bytes are zeroed here */
if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
mask->max_bits = new_max * 8;
}
@@ -154,31 +150,15 @@
/* test a bit value in a given mask */
static FT_Int
ps_mask_test_bit( PS_Mask mask,
- FT_Int idx )
+ FT_UInt idx )
{
- if ( (FT_UInt)idx >= mask->num_bits )
+ if ( idx >= mask->num_bits )
return 0;
return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
}
- /* clear a given bit */
- static void
- ps_mask_clear_bit( PS_Mask mask,
- FT_UInt idx )
- {
- FT_Byte* p;
-
-
- if ( idx >= mask->num_bits )
- return;
-
- p = mask->bytes + ( idx >> 3 );
- p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
- }
-
-
/* set a given bit, possibly grow the mask */
static FT_Error
ps_mask_set_bit( PS_Mask mask,
@@ -269,6 +249,10 @@
mask = table->masks + count - 1;
mask->num_bits = 0;
mask->end_point = 0;
+ /* reused mask must be cleared */
+ if ( mask->max_bits )
+ FT_MEM_ZERO( mask->bytes, mask->max_bits >> 3 );
+
table->num_masks = count;
Exit:
@@ -426,7 +410,7 @@
PS_Mask mask2 = table->masks + index2;
FT_UInt count1 = mask1->num_bits;
FT_UInt count2 = mask2->num_bits;
- FT_Int delta;
+ FT_UInt delta;
if ( count2 > 0 )
@@ -437,15 +421,14 @@
/* if "count2" is greater than "count1", we need to grow the */
- /* first bitset, and clear the highest bits */
+ /* first bitset */
if ( count2 > count1 )
{
error = ps_mask_ensure( mask1, count2, memory );
if ( error )
goto Exit;
- for ( pos = count1; pos < count2; pos++ )
- ps_mask_clear_bit( mask1, pos );
+ mask1->num_bits = count2;
}
/* merge (unite) the bitsets */
@@ -467,7 +450,7 @@
mask2->end_point = 0;
/* number of masks to move */
- delta = (FT_Int)( table->num_masks - 1 - index2 );
+ delta = table->num_masks - 1 - index2;
if ( delta > 0 )
{
/* move to end of table for reuse */
@@ -476,7 +459,7 @@
ft_memmove( mask2,
mask2 + 1,
- (FT_UInt)delta * sizeof ( PS_MaskRec ) );
+ delta * sizeof ( PS_MaskRec ) );
mask2[delta] = dummy;
}
@@ -647,7 +630,7 @@
FT_Int pos,
FT_Int len,
FT_Memory memory,
- FT_Int *aindex )
+ FT_UInt *aindex )
{
FT_Error error = FT_Err_Ok;
FT_UInt flags = 0;
@@ -665,9 +648,6 @@
len = 0;
}
- if ( aindex )
- *aindex = -1;
-
/* now, lookup stem in the current hints table */
{
PS_Mask mask;
@@ -704,7 +684,7 @@
goto Exit;
if ( aindex )
- *aindex = (FT_Int)idx;
+ *aindex = idx;
}
Exit:
@@ -715,9 +695,9 @@
/* add a "hstem3/vstem3" counter to our dimension table */
static FT_Error
ps_dimension_add_counter( PS_Dimension dim,
- FT_Int hint1,
- FT_Int hint2,
- FT_Int hint3,
+ FT_UInt hint1,
+ FT_UInt hint2,
+ FT_UInt hint3,
FT_Memory memory )
{
FT_Error error = FT_Err_Ok;
@@ -744,26 +724,17 @@
}
/* now, set the bits for our hints in the counter mask */
- if ( hint1 >= 0 )
- {
- error = ps_mask_set_bit( counter, (FT_UInt)hint1, memory );
- if ( error )
- goto Exit;
- }
+ error = ps_mask_set_bit( counter, hint1, memory );
+ if ( error )
+ goto Exit;
- if ( hint2 >= 0 )
- {
- error = ps_mask_set_bit( counter, (FT_UInt)hint2, memory );
- if ( error )
- goto Exit;
- }
+ error = ps_mask_set_bit( counter, hint2, memory );
+ if ( error )
+ goto Exit;
- if ( hint3 >= 0 )
- {
- error = ps_mask_set_bit( counter, (FT_UInt)hint3, memory );
- if ( error )
- goto Exit;
- }
+ error = ps_mask_set_bit( counter, hint3, memory );
+ if ( error )
+ goto Exit;
Exit:
return error;
@@ -892,7 +863,7 @@
PS_Dimension dim;
FT_Memory memory = hints->memory;
FT_Int count;
- FT_Int idx[3];
+ FT_UInt idx[3];
/* limit "dimension" to 0..1 */
diff --git a/thirdparty/freetype/src/pshinter/pshrec.h b/thirdparty/freetype/src/pshinter/pshrec.h
index e483981d9d..a0d37979cc 100644
--- a/thirdparty/freetype/src/pshinter/pshrec.h
+++ b/thirdparty/freetype/src/pshinter/pshrec.h
@@ -4,7 +4,7 @@
*
* Postscript (Type1/Type2) hints recorder (specification).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psmodule.c b/thirdparty/freetype/src/psnames/psmodule.c
index 74adefa15b..e7d51e950e 100644
--- a/thirdparty/freetype/src/psnames/psmodule.c
+++ b/thirdparty/freetype/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
*
* psnames module implementation (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psmodule.h b/thirdparty/freetype/src/psnames/psmodule.h
index e92a975e9d..ff3eda564c 100644
--- a/thirdparty/freetype/src/psnames/psmodule.h
+++ b/thirdparty/freetype/src/psnames/psmodule.h
@@ -4,7 +4,7 @@
*
* High-level psnames module interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psnamerr.h b/thirdparty/freetype/src/psnames/psnamerr.h
index 888b76c4f6..ae56620275 100644
--- a/thirdparty/freetype/src/psnames/psnamerr.h
+++ b/thirdparty/freetype/src/psnames/psnamerr.h
@@ -4,7 +4,7 @@
*
* PS names module error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/psnames.c b/thirdparty/freetype/src/psnames/psnames.c
index e7be6707d6..c844a317fd 100644
--- a/thirdparty/freetype/src/psnames/psnames.c
+++ b/thirdparty/freetype/src/psnames/psnames.c
@@ -4,7 +4,7 @@
*
* FreeType psnames module component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/psnames/pstables.h b/thirdparty/freetype/src/psnames/pstables.h
index 0bcadca9cc..d28d580b9c 100644
--- a/thirdparty/freetype/src/psnames/pstables.h
+++ b/thirdparty/freetype/src/psnames/pstables.h
@@ -4,7 +4,7 @@
*
* PostScript glyph names.
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/ftmisc.h b/thirdparty/freetype/src/raster/ftmisc.h
index b12a051234..75fb5f8437 100644
--- a/thirdparty/freetype/src/raster/ftmisc.h
+++ b/thirdparty/freetype/src/raster/ftmisc.h
@@ -5,7 +5,7 @@
* Miscellaneous macros for stand-alone rasterizer (specification
* only).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/raster/ftraster.c b/thirdparty/freetype/src/raster/ftraster.c
index bfc059c1e8..68b0e1fdd9 100644
--- a/thirdparty/freetype/src/raster/ftraster.c
+++ b/thirdparty/freetype/src/raster/ftraster.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -2269,7 +2269,7 @@
/* This is due to the fact that, in the vast majority of cases, */
/* the span length in bytes is relatively small. */
while ( --c2 > 0 )
- *(++target) = 0xFF;
+ *( ++target ) = 0xFF;
target[1] |= f2;
}
diff --git a/thirdparty/freetype/src/raster/ftraster.h b/thirdparty/freetype/src/raster/ftraster.h
index 4affd48b51..e9ece8cf0b 100644
--- a/thirdparty/freetype/src/raster/ftraster.h
+++ b/thirdparty/freetype/src/raster/ftraster.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used
diff --git a/thirdparty/freetype/src/raster/ftrend1.c b/thirdparty/freetype/src/raster/ftrend1.c
index 236a8daf0a..f319f03d9c 100644
--- a/thirdparty/freetype/src/raster/ftrend1.c
+++ b/thirdparty/freetype/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/ftrend1.h b/thirdparty/freetype/src/raster/ftrend1.h
index e4cea53741..14ec336b11 100644
--- a/thirdparty/freetype/src/raster/ftrend1.h
+++ b/thirdparty/freetype/src/raster/ftrend1.h
@@ -4,7 +4,7 @@
*
* The FreeType glyph rasterizer interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/raster.c b/thirdparty/freetype/src/raster/raster.c
index ad81a39414..324cc5661c 100644
--- a/thirdparty/freetype/src/raster/raster.c
+++ b/thirdparty/freetype/src/raster/raster.c
@@ -4,7 +4,7 @@
*
* FreeType monochrome rasterer module component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/raster/rasterrs.h b/thirdparty/freetype/src/raster/rasterrs.h
index 852dd5bc31..8b1ebf07a3 100644
--- a/thirdparty/freetype/src/raster/rasterrs.h
+++ b/thirdparty/freetype/src/raster/rasterrs.h
@@ -4,7 +4,7 @@
*
* monochrome renderer error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sdf/ftbsdf.c b/thirdparty/freetype/src/sdf/ftbsdf.c
index 8da5c9d9e0..1328ac4988 100644
--- a/thirdparty/freetype/src/sdf/ftbsdf.c
+++ b/thirdparty/freetype/src/sdf/ftbsdf.c
@@ -4,7 +4,7 @@
*
* Signed Distance Field support for bitmap fonts (body only).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
@@ -177,11 +177,11 @@
*
* @Fields:
* dist ::
- * Vector length of the `near` parameter. Can be squared or absolute
+ * Vector length of the `prox` parameter. Can be squared or absolute
* depending on the `USE_SQUARED_DISTANCES` macro defined in file
* `ftsdfcommon.h`.
*
- * near ::
+ * prox ::
* Vector to the nearest edge. Can also be interpreted as shortest
* distance of a point.
*
@@ -194,7 +194,7 @@
typedef struct ED_
{
FT_16D16 dist;
- FT_16D16_Vec near;
+ FT_16D16_Vec prox;
FT_Byte alpha;
} ED;
@@ -595,18 +595,18 @@
worker->rows ) )
{
/* approximate the edge distance for edge pixels */
- ed[index].near = compute_edge_distance( ed + index,
+ ed[index].prox = compute_edge_distance( ed + index,
i, j,
worker->width,
worker->rows );
- ed[index].dist = VECTOR_LENGTH_16D16( ed[index].near );
+ ed[index].dist = VECTOR_LENGTH_16D16( ed[index].prox );
}
else
{
/* for non-edge pixels assign far away distances */
ed[index].dist = 400 * ONE;
- ed[index].near.x = 200 * ONE;
- ed[index].near.y = 200 * ONE;
+ ed[index].prox.x = 200 * ONE;
+ ed[index].prox.y = 200 * ONE;
}
}
}
@@ -756,8 +756,6 @@
byte = (FT_Byte)( 1 << mod );
t[t_index].alpha = pixel & byte ? 255 : 0;
-
- pixel = 0;
}
}
}
@@ -873,7 +871,7 @@
if ( dist < current->dist )
{
- dist_vec = to_check->near;
+ dist_vec = to_check->prox;
dist_vec.x += x_offset * ONE;
dist_vec.y += y_offset * ONE;
@@ -882,7 +880,7 @@
if ( dist < current->dist )
{
current->dist = dist;
- current->near = dist_vec;
+ current->prox = dist_vec;
}
}
}
@@ -1098,7 +1096,7 @@
FT_Int i, j;
FT_SDFFormat* t_buffer;
- FT_16D16 spread;
+ FT_16D16 sp_sq, spread;
if ( !worker || !target )
@@ -1118,11 +1116,13 @@
goto Exit;
}
+ spread = FT_INT_16D16( worker->params.spread );
+
#if USE_SQUARED_DISTANCES
- spread = FT_INT_16D16( worker->params.spread *
- worker->params.spread );
+ sp_sq = FT_INT_16D16( worker->params.spread *
+ worker->params.spread );
#else
- spread = FT_INT_16D16( worker->params.spread );
+ sp_sq = FT_INT_16D16( worker->params.spread );
#endif
for ( j = 0; j < r; j++ )
@@ -1138,8 +1138,8 @@
index = j * w + i;
dist = worker->distance_map[index].dist;
- if ( dist < 0 || dist > spread )
- dist = spread;
+ if ( dist < 0 || dist > sp_sq )
+ dist = sp_sq;
#if USE_SQUARED_DISTANCES
dist = square_root( dist );
diff --git a/thirdparty/freetype/src/sdf/ftsdf.c b/thirdparty/freetype/src/sdf/ftsdf.c
index f69cf49b47..ffac8bf465 100644
--- a/thirdparty/freetype/src/sdf/ftsdf.c
+++ b/thirdparty/freetype/src/sdf/ftsdf.c
@@ -4,7 +4,7 @@
*
* Signed Distance Field support for outline fonts (body).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
@@ -497,7 +497,7 @@
goto Exit;
}
- if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+ if ( !FT_QNEW( ptr ) )
{
*ptr = null_edge;
*edge = ptr;
@@ -536,7 +536,7 @@
goto Exit;
}
- if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+ if ( !FT_QNEW( ptr ) )
{
*ptr = null_contour;
*contour = ptr;
@@ -591,7 +591,7 @@
goto Exit;
}
- if ( !FT_QALLOC( ptr, sizeof ( *ptr ) ) )
+ if ( !FT_QNEW( ptr ) )
{
*ptr = null_shape;
ptr->memory = memory;
@@ -738,6 +738,18 @@
contour = shape->contours;
+ /* If the control point coincides with any of the end points */
+ /* then it is a line and should be treated as one to avoid */
+ /* unnecessary complexity later in the algorithm. */
+ if ( ( contour->last_pos.x == control_1->x &&
+ contour->last_pos.y == control_1->y ) ||
+ ( control_1->x == to->x &&
+ control_1->y == to->y ) )
+ {
+ sdf_line_to( to, user );
+ goto Exit;
+ }
+
FT_CALL( sdf_edge_new( memory, &edge ) );
edge->edge_type = SDF_EDGE_CONIC;
@@ -764,9 +776,9 @@
const FT_26D6_Vec* to,
void* user )
{
- SDF_Shape* shape = ( SDF_Shape* )user;
- SDF_Edge* edge = NULL;
- SDF_Contour* contour = NULL;
+ SDF_Shape* shape = ( SDF_Shape* )user;
+ SDF_Edge* edge = NULL;
+ SDF_Contour* contour = NULL;
FT_Error error = FT_Err_Ok;
FT_Memory memory = shape->memory;
@@ -1065,7 +1077,7 @@
static FT_Error
split_sdf_conic( FT_Memory memory,
FT_26D6_Vec* control_points,
- FT_Int max_splits,
+ FT_UInt max_splits,
SDF_Edge** out )
{
FT_Error error = FT_Err_Ok;
@@ -1134,26 +1146,41 @@
static FT_Error
split_sdf_cubic( FT_Memory memory,
FT_26D6_Vec* control_points,
- FT_Int max_splits,
+ FT_UInt max_splits,
SDF_Edge** out )
{
- FT_Error error = FT_Err_Ok;
- FT_26D6_Vec cpos[7];
- SDF_Edge* left,* right;
+ FT_Error error = FT_Err_Ok;
+ FT_26D6_Vec cpos[7];
+ SDF_Edge* left, *right;
+ const FT_26D6 threshold = ONE_PIXEL / 4;
- if ( !memory || !out )
+ if ( !memory || !out )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
- /* split the conic */
+ /* split the cubic */
cpos[0] = control_points[0];
cpos[1] = control_points[1];
cpos[2] = control_points[2];
cpos[3] = control_points[3];
+ /* If the segment is flat enough we won't get any benefit by */
+ /* splitting it further, so we can just stop splitting. */
+ /* */
+ /* Check the deviation of the Bezier curve and stop if it is */
+ /* smaller than the pre-defined `threshold` value. */
+ if ( FT_ABS( 2 * cpos[0].x - 3 * cpos[1].x + cpos[3].x ) < threshold &&
+ FT_ABS( 2 * cpos[0].y - 3 * cpos[1].y + cpos[3].y ) < threshold &&
+ FT_ABS( cpos[0].x - 3 * cpos[2].x + 2 * cpos[3].x ) < threshold &&
+ FT_ABS( cpos[0].y - 3 * cpos[2].y + 2 * cpos[3].y ) < threshold )
+ {
+ split_cubic( cpos );
+ goto Append;
+ }
+
split_cubic( cpos );
/* If max number of splits is done */
@@ -1250,13 +1277,32 @@
/* Subdivide the curve and add it to the list. */
{
FT_26D6_Vec ctrls[3];
+ FT_26D6 dx, dy;
+ FT_UInt num_splits;
ctrls[0] = edge->start_pos;
ctrls[1] = edge->control_a;
ctrls[2] = edge->end_pos;
- error = split_sdf_conic( memory, ctrls, 32, &new_edges );
+ dx = FT_ABS( ctrls[2].x + ctrls[0].x - 2 * ctrls[1].x );
+ dy = FT_ABS( ctrls[2].y + ctrls[0].y - 2 * ctrls[1].y );
+ if ( dx < dy )
+ dx = dy;
+
+ /* Calculate the number of necessary bisections. Each */
+ /* bisection causes a four-fold reduction of the deviation, */
+ /* hence we bisect the Bezier curve until the deviation */
+ /* becomes less than 1/8th of a pixel. For more details */
+ /* check file `ftgrays.c`. */
+ num_splits = 1;
+ while ( dx > ONE_PIXEL / 8 )
+ {
+ dx >>= 2;
+ num_splits <<= 1;
+ }
+
+ error = split_sdf_conic( memory, ctrls, num_splits, &new_edges );
}
break;
@@ -1277,9 +1323,11 @@
default:
error = FT_THROW( Invalid_Argument );
- goto Exit;
}
+ if ( error != FT_Err_Ok )
+ goto Exit;
+
edges = edges->next;
}
@@ -2966,7 +3014,7 @@
diff = current_dist.distance - min_dist.distance;
- if ( FT_ABS(diff ) < CORNER_CHECK_EPSILON )
+ if ( FT_ABS( diff ) < CORNER_CHECK_EPSILON )
min_dist = resolve_corner( min_dist, current_dist );
else if ( diff < 0 )
min_dist = current_dist;
@@ -3240,7 +3288,7 @@
buffer = (FT_SDFFormat*)bitmap->buffer;
if ( USE_SQUARED_DISTANCES )
- sp_sq = fixed_spread * fixed_spread;
+ sp_sq = FT_INT_16D16( (FT_Int)( spread * spread ) );
else
sp_sq = fixed_spread;
@@ -3284,6 +3332,7 @@
FT_26D6_Vec grid_point = zero_vector;
SDF_Signed_Distance dist = max_sdf;
FT_UInt index = 0;
+ FT_16D16 diff = 0;
if ( x < 0 || x >= width )
@@ -3311,7 +3360,7 @@
if ( dist.distance > sp_sq )
continue;
- /* square_root the values and fit in a 6.10 fixed-point */
+ /* take the square root of the distance if required */
if ( USE_SQUARED_DISTANCES )
dist.distance = square_root( dist.distance );
@@ -3323,11 +3372,15 @@
/* check whether the pixel is set or not */
if ( dists[index].sign == 0 )
dists[index] = dist;
- else if ( dists[index].distance > dist.distance )
- dists[index] = dist;
- else if ( FT_ABS( dists[index].distance - dist.distance )
- < CORNER_CHECK_EPSILON )
- dists[index] = resolve_corner( dists[index], dist );
+ else
+ {
+ diff = FT_ABS( dists[index].distance - dist.distance );
+
+ if ( diff <= CORNER_CHECK_EPSILON )
+ dists[index] = resolve_corner( dists[index], dist );
+ else if ( dists[index].distance > dist.distance )
+ dists[index] = dist;
+ }
}
}
diff --git a/thirdparty/freetype/src/sdf/ftsdf.h b/thirdparty/freetype/src/sdf/ftsdf.h
index 187b418af3..5f6b3f52aa 100644
--- a/thirdparty/freetype/src/sdf/ftsdf.h
+++ b/thirdparty/freetype/src/sdf/ftsdf.h
@@ -4,7 +4,7 @@
*
* Signed Distance Field support (specification).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
diff --git a/thirdparty/freetype/src/sdf/ftsdfcommon.c b/thirdparty/freetype/src/sdf/ftsdfcommon.c
index 91aa521bb3..072a36ea6c 100644
--- a/thirdparty/freetype/src/sdf/ftsdfcommon.c
+++ b/thirdparty/freetype/src/sdf/ftsdfcommon.c
@@ -4,7 +4,7 @@
*
* Auxiliary data for Signed Distance Field support (body).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
diff --git a/thirdparty/freetype/src/sdf/ftsdfcommon.h b/thirdparty/freetype/src/sdf/ftsdfcommon.h
index 44f6bba53f..af4490bbca 100644
--- a/thirdparty/freetype/src/sdf/ftsdfcommon.h
+++ b/thirdparty/freetype/src/sdf/ftsdfcommon.h
@@ -4,7 +4,7 @@
*
* Auxiliary data for Signed Distance Field support (specification).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
@@ -48,6 +48,8 @@ FT_BEGIN_HEADER
#define MIN_SPREAD 2
/* maximum spread supported by the renderer */
#define MAX_SPREAD 32
+ /* pixel size in 26.6 */
+#define ONE_PIXEL ( 1 << 6 )
/**************************************************************************
diff --git a/thirdparty/freetype/src/sdf/ftsdferrs.h b/thirdparty/freetype/src/sdf/ftsdferrs.h
index dbb113d537..b28867609a 100644
--- a/thirdparty/freetype/src/sdf/ftsdferrs.h
+++ b/thirdparty/freetype/src/sdf/ftsdferrs.h
@@ -4,7 +4,7 @@
*
* Signed Distance Field error codes (specification only).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
diff --git a/thirdparty/freetype/src/sdf/ftsdfrend.c b/thirdparty/freetype/src/sdf/ftsdfrend.c
index 30f2e62a4f..b0213a40d3 100644
--- a/thirdparty/freetype/src/sdf/ftsdfrend.c
+++ b/thirdparty/freetype/src/sdf/ftsdfrend.c
@@ -4,7 +4,7 @@
*
* Signed Distance Field renderer interface (body).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
@@ -298,15 +298,9 @@
goto Exit;
}
- /* the rows and pitch must be valid after presetting the */
- /* bitmap using outline */
+ /* nothing to render */
if ( !bitmap->rows || !bitmap->pitch )
- {
- FT_ERROR(( "ft_sdf_render: failed to preset bitmap\n" ));
-
- error = FT_THROW( Cannot_Render_Glyph );
- goto Exit;
- }
+ return FT_Err_Ok;
/* the padding will simply be equal to the `spread' */
x_pad = sdf_module->spread;
@@ -525,13 +519,9 @@
goto Exit;
}
+ /* nothing to render */
if ( !bitmap->rows || !bitmap->pitch )
- {
- FT_ERROR(( "ft_bsdf_render: invalid bitmap size\n" ));
-
- error = FT_THROW( Invalid_Argument );
- goto Exit;
- }
+ return FT_Err_Ok;
FT_Bitmap_New( &target );
diff --git a/thirdparty/freetype/src/sdf/ftsdfrend.h b/thirdparty/freetype/src/sdf/ftsdfrend.h
index bc88707ec2..cdb9c5f02f 100644
--- a/thirdparty/freetype/src/sdf/ftsdfrend.h
+++ b/thirdparty/freetype/src/sdf/ftsdfrend.h
@@ -4,7 +4,7 @@
*
* Signed Distance Field renderer interface (specification).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
diff --git a/thirdparty/freetype/src/sdf/sdf.c b/thirdparty/freetype/src/sdf/sdf.c
index 1bc3fc385c..297ba9ab02 100644
--- a/thirdparty/freetype/src/sdf/sdf.c
+++ b/thirdparty/freetype/src/sdf/sdf.c
@@ -4,7 +4,7 @@
*
* FreeType Signed Distance Field renderer module component (body only).
*
- * Copyright (C) 2020-2021 by
+ * Copyright (C) 2020-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Written by Anuj Verma.
diff --git a/thirdparty/freetype/src/sfnt/pngshim.c b/thirdparty/freetype/src/sfnt/pngshim.c
index 02fe37440c..0ce4bdb6b5 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.c
+++ b/thirdparty/freetype/src/sfnt/pngshim.c
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
@@ -367,7 +367,7 @@
}
/* transform transparency to alpha */
- if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
+ if ( png_get_valid( png, info, PNG_INFO_tRNS ) )
png_set_tRNS_to_alpha( png );
if ( bitdepth == 16 )
@@ -387,7 +387,7 @@
png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
/* recheck header after setting EXPAND options */
- png_read_update_info(png, info );
+ png_read_update_info( png, info );
png_get_IHDR( png, info,
&imgWidth, &imgHeight,
&bitdepth, &color_type, &interlace,
diff --git a/thirdparty/freetype/src/sfnt/pngshim.h b/thirdparty/freetype/src/sfnt/pngshim.h
index 89efd27545..36d749c3c3 100644
--- a/thirdparty/freetype/src/sfnt/pngshim.h
+++ b/thirdparty/freetype/src/sfnt/pngshim.h
@@ -4,7 +4,7 @@
*
* PNG Bitmap glyph support.
*
- * Copyright (C) 2013-2021 by
+ * Copyright (C) 2013-2022 by
* Google, Inc.
* Written by Stuart Gill and Behdad Esfahbod.
*
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.c b/thirdparty/freetype/src/sfnt/sfdriver.c
index d1d01c99e5..cc121e5790 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.c
+++ b/thirdparty/freetype/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -36,6 +36,10 @@
#include "ttcpal.h"
#endif
+#ifdef FT_CONFIG_OPTION_SVG
+#include "ttsvg.h"
+#endif
+
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
#include "ttpost.h"
#endif
@@ -491,15 +495,13 @@
char_type_func char_type,
FT_Bool report_invalid_characters )
{
- FT_Error error = FT_Err_Ok;
+ FT_Error error;
char* result = NULL;
FT_String* r;
FT_Char* p;
FT_UInt len;
- FT_UNUSED( error );
-
if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) )
return NULL;
@@ -550,15 +552,13 @@
char_type_func char_type,
FT_Bool report_invalid_characters )
{
- FT_Error error = FT_Err_Ok;
+ FT_Error error;
char* result = NULL;
FT_String* r;
FT_Char* p;
FT_UInt len;
- FT_UNUSED( error );
-
if ( FT_QALLOC( result, entry->stringLength + 1 ) )
return NULL;
@@ -1214,6 +1214,12 @@
#define PUT_COLOR_LAYERS( a ) NULL
#endif
+#ifdef FT_CONFIG_OPTION_SVG
+#define PUT_SVG_SUPPORT( a ) a
+#else
+#define PUT_SVG_SUPPORT( a ) NULL
+#endif
+
#define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a )
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
@@ -1308,7 +1314,14 @@
tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */
tt_face_get_name, /* TT_Get_Name_Func get_name */
- sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */
+ sfnt_get_name_id, /* TT_Get_Name_ID_Func get_name_id */
+
+ PUT_SVG_SUPPORT( tt_face_load_svg ),
+ /* TT_Load_Table_Func load_svg */
+ PUT_SVG_SUPPORT( tt_face_free_svg ),
+ /* TT_Free_Table_Func free_svg */
+ PUT_SVG_SUPPORT( tt_face_load_svg_doc )
+ /* TT_Load_Svg_Doc_Func load_svg_doc */
)
diff --git a/thirdparty/freetype/src/sfnt/sfdriver.h b/thirdparty/freetype/src/sfnt/sfdriver.h
index 8d5b5ce367..6a2e3e9c7b 100644
--- a/thirdparty/freetype/src/sfnt/sfdriver.h
+++ b/thirdparty/freetype/src/sfnt/sfdriver.h
@@ -4,7 +4,7 @@
*
* High-level SFNT driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sferrors.h b/thirdparty/freetype/src/sfnt/sferrors.h
index 78e6f03513..99ef3f9fce 100644
--- a/thirdparty/freetype/src/sfnt/sferrors.h
+++ b/thirdparty/freetype/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
*
* SFNT error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfnt.c b/thirdparty/freetype/src/sfnt/sfnt.c
index 97692cdfb0..9b3ceaedc0 100644
--- a/thirdparty/freetype/src/sfnt/sfnt.c
+++ b/thirdparty/freetype/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
*
* Single object library component.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -27,6 +27,7 @@
#include "ttcmap.c"
#include "ttcolr.c"
#include "ttcpal.c"
+#include "ttsvg.c"
#include "ttkern.c"
#include "ttload.c"
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.c b/thirdparty/freetype/src/sfnt/sfobjs.c
index 7891024790..a0da984e7a 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.c
+++ b/thirdparty/freetype/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
*
* SFNT object management (base).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -566,7 +566,7 @@
face_index = FT_ABS( face_instance_index ) & 0xFFFF;
/* value -(N+1) requests information on index N */
- if ( face_instance_index < 0 )
+ if ( face_instance_index < 0 && face_index > 0 )
face_index--;
if ( face_index >= face->ttc_header.count )
@@ -784,17 +784,23 @@
FT_Int num_params,
FT_Parameter* params )
{
- FT_Error error;
+ FT_Error error;
#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
- FT_Error psnames_error;
+ FT_Error psnames_error;
#endif
- FT_Bool has_outline;
- FT_Bool is_apple_sbit;
- FT_Bool is_apple_sbix;
- FT_Bool has_CBLC;
- FT_Bool has_CBDT;
- FT_Bool ignore_typographic_family = FALSE;
- FT_Bool ignore_typographic_subfamily = FALSE;
+
+ FT_Bool has_outline;
+ FT_Bool is_apple_sbit;
+
+ FT_Bool has_CBLC;
+ FT_Bool has_CBDT;
+ FT_Bool has_EBLC;
+ FT_Bool has_bloc;
+ FT_Bool has_sbix;
+
+ FT_Bool ignore_typographic_family = FALSE;
+ FT_Bool ignore_typographic_subfamily = FALSE;
+ FT_Bool ignore_sbix = FALSE;
SFNT_Service sfnt = (SFNT_Service)face->sfnt;
@@ -813,6 +819,8 @@
ignore_typographic_family = TRUE;
else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY )
ignore_typographic_subfamily = TRUE;
+ else if ( params[i].tag == FT_PARAM_TAG_IGNORE_SBIX )
+ ignore_sbix = TRUE;
}
}
@@ -848,14 +856,17 @@
tt_face_lookup_table( face, TTAG_CFF2 ) );
#endif
- is_apple_sbit = 0;
- is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
+ /* check which sbit formats are present */
+ has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 );
+ has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 );
+ has_EBLC = !face->goto_table( face, TTAG_EBLC, stream, 0 );
+ has_bloc = !face->goto_table( face, TTAG_bloc, stream, 0 );
+ has_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 );
- /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf'
- * outline rendered on top. We don't support that yet, so just ignore
- * the 'glyf' outline and advertise it as a bitmap-only font. */
- if ( is_apple_sbix )
- has_outline = FALSE;
+ is_apple_sbit = FALSE;
+
+ if ( ignore_sbix )
+ has_sbix = FALSE;
/* if this font doesn't contain outlines, we try to load */
/* a `bhed' table */
@@ -867,16 +878,13 @@
/* load the font header (`head' table) if this isn't an Apple */
/* sbit font file */
- if ( !is_apple_sbit || is_apple_sbix )
+ if ( !is_apple_sbit || has_sbix )
{
LOAD_( head );
if ( error )
goto Exit;
}
- has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 );
- has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 );
-
/* Ignore outlines for CBLC/CBDT fonts. */
if ( has_CBLC || has_CBDT )
has_outline = FALSE;
@@ -986,7 +994,11 @@
/* the optional tables */
/* embedded bitmap support */
- if ( sfnt->load_eblc )
+ /* TODO: Replace this clumsy check for all possible sbit tables */
+ /* with something better (for example, by passing a parameter */
+ /* to suppress 'sbix' loading). */
+ if ( sfnt->load_eblc &&
+ ( has_CBLC || has_EBLC || has_bloc || has_sbix ) )
LOAD_( eblc );
/* colored glyph support */
@@ -996,6 +1008,10 @@
LOAD_( colr );
}
+ /* OpenType-SVG glyph support */
+ if ( sfnt->load_svg )
+ LOAD_( svg );
+
/* consider the pclt, kerning, and gasp tables as optional */
LOAD_( pclt );
LOAD_( gasp );
@@ -1050,11 +1066,19 @@
*/
if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC ||
face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ||
- face->colr )
+ face->colr ||
+ face->svg )
flags |= FT_FACE_FLAG_COLOR; /* color glyphs */
if ( has_outline == TRUE )
- flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
+ {
+ /* by default (and for backward compatibility) we handle */
+ /* fonts with an 'sbix' table as bitmap-only */
+ if ( has_sbix )
+ flags |= FT_FACE_FLAG_SBIX; /* with 'sbix' bitmaps */
+ else
+ flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */
+ }
/* The sfnt driver only supports bitmap fonts natively, thus we */
/* don't set FT_FACE_FLAG_HINTER. */
@@ -1277,7 +1301,8 @@
*
* Set up metrics.
*/
- if ( FT_IS_SCALABLE( root ) )
+ if ( FT_IS_SCALABLE( root ) ||
+ FT_HAS_SBIX( root ) )
{
/* XXX What about if outline header is missing */
/* (e.g. sfnt wrapped bitmap)? */
@@ -1416,6 +1441,12 @@
sfnt->free_cpal( face );
sfnt->free_colr( face );
}
+
+#ifdef FT_CONFIG_OPTION_SVG
+ /* free SVG data */
+ if ( sfnt->free_svg )
+ sfnt->free_svg( face );
+#endif
}
#ifdef TT_CONFIG_OPTION_BDF
diff --git a/thirdparty/freetype/src/sfnt/sfobjs.h b/thirdparty/freetype/src/sfnt/sfobjs.h
index 172c47ebb4..1d99bfede4 100644
--- a/thirdparty/freetype/src/sfnt/sfobjs.h
+++ b/thirdparty/freetype/src/sfnt/sfobjs.h
@@ -4,7 +4,7 @@
*
* SFNT object management (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfwoff.c b/thirdparty/freetype/src/sfnt/sfwoff.c
index 422c816a21..0e8ec3fa93 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff.c
+++ b/thirdparty/freetype/src/sfnt/sfwoff.c
@@ -4,7 +4,7 @@
*
* WOFF format management (base).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -64,7 +64,6 @@
FT_FREE( stream->base );
stream->size = 0;
- stream->base = NULL;
stream->close = NULL;
}
diff --git a/thirdparty/freetype/src/sfnt/sfwoff.h b/thirdparty/freetype/src/sfnt/sfwoff.h
index 3fbdac0fde..5866a16194 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff.h
+++ b/thirdparty/freetype/src/sfnt/sfwoff.h
@@ -4,7 +4,7 @@
*
* WOFFF format management (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.c b/thirdparty/freetype/src/sfnt/sfwoff2.c
index 5ee8dea28a..b2855b8e72 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff2.c
+++ b/thirdparty/freetype/src/sfnt/sfwoff2.c
@@ -4,7 +4,7 @@
*
* WOFF2 format management (base).
*
- * Copyright (C) 2019-2021 by
+ * Copyright (C) 2019-2022 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -84,6 +84,8 @@
#define BBOX_STREAM 5
#define INSTRUCTION_STREAM 6
+#define HAVE_OVERLAP_SIMPLE_BITMAP 0x1
+
static void
stream_close( FT_Stream stream )
@@ -94,7 +96,6 @@
FT_FREE( stream->base );
stream->size = 0;
- stream->base = NULL;
stream->close = NULL;
}
@@ -523,6 +524,7 @@
const WOFF2_Point points,
FT_UShort n_contours,
FT_UShort instruction_len,
+ FT_Bool have_overlap,
FT_Byte* dst,
FT_ULong dst_size,
FT_ULong* glyph_size )
@@ -550,6 +552,9 @@
FT_Int dy = point.y - last_y;
+ if ( i == 0 && have_overlap )
+ flag |= GLYF_OVERLAP_SIMPLE;
+
if ( dx == 0 )
flag |= GLYF_THIS_X_IS_SAME;
else if ( dx > -256 && dx < 256 )
@@ -834,15 +839,18 @@
FT_UInt num_substreams = 7;
+ FT_UShort option_flags;
FT_UShort num_glyphs;
FT_UShort index_format;
FT_ULong expected_loca_length;
FT_UInt offset;
FT_UInt i;
FT_ULong points_size;
- FT_ULong bitmap_length;
FT_ULong glyph_buf_size;
FT_ULong bbox_bitmap_offset;
+ FT_ULong bbox_bitmap_length;
+ FT_ULong overlap_bitmap_offset = 0;
+ FT_ULong overlap_bitmap_length = 0;
const FT_ULong glyf_start = *out_offset;
FT_ULong dest_offset = *out_offset;
@@ -858,15 +866,17 @@
if ( FT_NEW_ARRAY( substreams, num_substreams ) )
goto Fail;
- if ( FT_STREAM_SKIP( 4 ) )
+ if ( FT_STREAM_SKIP( 2 ) )
+ goto Fail;
+ if ( FT_READ_USHORT( option_flags ) )
goto Fail;
if ( FT_READ_USHORT( num_glyphs ) )
goto Fail;
if ( FT_READ_USHORT( index_format ) )
goto Fail;
- FT_TRACE4(( "num_glyphs = %u; index_format = %u\n",
- num_glyphs, index_format ));
+ FT_TRACE4(( "option_flags = %u; num_glyphs = %u; index_format = %u\n",
+ option_flags, num_glyphs, index_format ));
info->num_glyphs = num_glyphs;
@@ -879,7 +889,7 @@
if ( info->loca_table->dst_length != expected_loca_length )
goto Fail;
- offset = ( 2 + num_substreams ) * 4;
+ offset = 2 + 2 + 2 + 2 + ( num_substreams * 4 );
if ( offset > info->glyf_table->TransformLength )
goto Fail;
@@ -902,6 +912,20 @@
offset += substream_size;
}
+ if ( option_flags & HAVE_OVERLAP_SIMPLE_BITMAP )
+ {
+ /* Size of overlapBitmap = floor((numGlyphs + 7) / 8) */
+ overlap_bitmap_length = ( num_glyphs + 7U ) >> 3;
+ if ( overlap_bitmap_length > info->glyf_table->TransformLength - offset )
+ goto Fail;
+
+ overlap_bitmap_offset = pos + offset;
+
+ FT_TRACE5(( " Overlap bitmap: offset = %lu; size = %lu;\n",
+ overlap_bitmap_offset, overlap_bitmap_length ));
+ offset += overlap_bitmap_length;
+ }
+
if ( FT_NEW_ARRAY( loca_values, num_glyphs + 1 ) )
goto Fail;
@@ -909,8 +933,9 @@
bbox_bitmap_offset = substreams[BBOX_STREAM].offset;
/* Size of bboxBitmap = 4 * floor((numGlyphs + 31) / 32) */
- bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2;
- substreams[BBOX_STREAM].offset += bitmap_length;
+ bbox_bitmap_length = ( ( num_glyphs + 31U ) >> 5 ) << 2;
+ /* bboxStreamSize is the combined size of bboxBitmap and bboxStream. */
+ substreams[BBOX_STREAM].offset += bbox_bitmap_length;
glyph_buf_size = WOFF2_DEFAULT_GLYPH_BUF;
if ( FT_NEW_ARRAY( glyph_buf, glyph_buf_size ) )
@@ -948,7 +973,7 @@
/* composite glyph */
FT_Bool have_instructions = FALSE;
FT_UShort instruction_size = 0;
- FT_ULong composite_size;
+ FT_ULong composite_size = 0;
FT_ULong size_needed;
FT_Byte* pointer = NULL;
@@ -1026,8 +1051,11 @@
FT_ULong flag_size;
FT_ULong triplet_size;
FT_ULong triplet_bytes_used;
- FT_Byte* flags_buf = NULL;
- FT_Byte* triplet_buf = NULL;
+ FT_Bool have_overlap = FALSE;
+ FT_Byte overlap_bitmap;
+ FT_ULong overlap_offset;
+ FT_Byte* flags_buf = NULL;
+ FT_Byte* triplet_buf = NULL;
FT_UShort instruction_size;
FT_ULong size_needed;
FT_Int end_point;
@@ -1036,6 +1064,17 @@
FT_Byte* pointer = NULL;
+ /* Set `have_overlap`. */
+ if ( overlap_bitmap_offset )
+ {
+ overlap_offset = overlap_bitmap_offset + ( i >> 3 );
+ if ( FT_STREAM_SEEK( overlap_offset ) ||
+ FT_READ_BYTE( overlap_bitmap ) )
+ goto Fail;
+ if ( overlap_bitmap & ( 0x80 >> ( i & 7 ) ) )
+ have_overlap = TRUE;
+ }
+
if ( FT_NEW_ARRAY( n_points_arr, n_contours ) )
goto Fail;
@@ -1156,6 +1195,7 @@
points,
n_contours,
instruction_size,
+ have_overlap,
glyph_buf,
glyph_buf_size,
&glyph_size ) )
@@ -2064,7 +2104,7 @@
error = FT_THROW( Invalid_Table );
goto Exit;
}
- file_offset = ROUND4(woff2.metaOffset + woff2.metaLength);
+ file_offset = ROUND4( woff2.metaOffset + woff2.metaLength );
}
if ( woff2.privOffset )
@@ -2074,7 +2114,7 @@
error = FT_THROW( Invalid_Table );
goto Exit;
}
- file_offset = ROUND4(woff2.privOffset + woff2.privLength);
+ file_offset = ROUND4( woff2.privOffset + woff2.privLength );
}
if ( file_offset != ( ROUND4( woff2.length ) ) )
@@ -2086,7 +2126,7 @@
/* Validate requested face index. */
*num_faces = woff2.num_fonts;
/* value -(N+1) requests information on index N */
- if ( *face_instance_index < 0 )
+ if ( *face_instance_index < 0 && face_index > 0 )
face_index--;
if ( face_index >= woff2.num_fonts )
diff --git a/thirdparty/freetype/src/sfnt/sfwoff2.h b/thirdparty/freetype/src/sfnt/sfwoff2.h
index fa78b02429..e84982ed9c 100644
--- a/thirdparty/freetype/src/sfnt/sfwoff2.h
+++ b/thirdparty/freetype/src/sfnt/sfwoff2.h
@@ -4,7 +4,7 @@
*
* WOFFF2 format management (specification).
*
- * Copyright (C) 2019-2021 by
+ * Copyright (C) 2019-2022 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -56,6 +56,7 @@ FT_BEGIN_HEADER
#define GLYF_REPEAT 1 << 3
#define GLYF_THIS_X_IS_SAME 1 << 4
#define GLYF_THIS_Y_IS_SAME 1 << 5
+#define GLYF_OVERLAP_SIMPLE 1 << 6
/* Other constants */
#define CONTOUR_OFFSET_END_POINT 10
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.c b/thirdparty/freetype/src/sfnt/ttbdf.c
index b8d9473a63..4d2faf2385 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.c
+++ b/thirdparty/freetype/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded BDF properties (body).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttbdf.h b/thirdparty/freetype/src/sfnt/ttbdf.h
index 91271d916f..b7b11c9bec 100644
--- a/thirdparty/freetype/src/sfnt/ttbdf.h
+++ b/thirdparty/freetype/src/sfnt/ttbdf.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded BDF properties (specification).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.c b/thirdparty/freetype/src/sfnt/ttcmap.c
index b369d83788..bfeabacb7d 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.c
+++ b/thirdparty/freetype/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -465,7 +465,7 @@
if ( subheader )
{
FT_Byte* p = subheader;
- FT_UInt idx = (FT_UInt)(char_code & 0xFF);
+ FT_UInt idx = (FT_UInt)( char_code & 0xFF );
FT_UInt start, count;
FT_Int delta;
FT_UInt offset;
diff --git a/thirdparty/freetype/src/sfnt/ttcmap.h b/thirdparty/freetype/src/sfnt/ttcmap.h
index 504fc951c4..b10860b345 100644
--- a/thirdparty/freetype/src/sfnt/ttcmap.h
+++ b/thirdparty/freetype/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
*
* TrueType character mapping table (cmap) support (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcmapc.h b/thirdparty/freetype/src/sfnt/ttcmapc.h
index 4e6cd46ba8..6822a9cd6b 100644
--- a/thirdparty/freetype/src/sfnt/ttcmapc.h
+++ b/thirdparty/freetype/src/sfnt/ttcmapc.h
@@ -4,7 +4,7 @@
*
* TT CMAP classes definitions (specification only).
*
- * Copyright (C) 2009-2021 by
+ * Copyright (C) 2009-2022 by
* Oran Agra and Mickey Gabel.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.c b/thirdparty/freetype/src/sfnt/ttcolr.c
index 8f5cc8bcd1..d54231fd64 100644
--- a/thirdparty/freetype/src/sfnt/ttcolr.c
+++ b/thirdparty/freetype/src/sfnt/ttcolr.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (body).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, Dominik Röttsches, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
@@ -522,19 +522,29 @@
else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
{
+ FT_Pos tmp;
+
+
if ( !read_color_line( child_table_p,
&apaint->u.radial_gradient.colorline ) )
return 0;
+ /* In the OpenType specification, `r0` and `r1` are defined as */
+ /* `UFWORD`. Since FreeType doesn't have a corresponding 16.16 */
+ /* format we convert to `FWORD` and replace negative values with */
+ /* (32bit) `FT_INT_MAX`. */
+
apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
- apaint->u.radial_gradient.r0 = FT_NEXT_USHORT( p ) << 16;
+ tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+ apaint->u.radial_gradient.r0 = tmp < 0 ? FT_INT_MAX : tmp;
apaint->u.radial_gradient.c1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
apaint->u.radial_gradient.c1.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
- apaint->u.radial_gradient.r1 = FT_NEXT_USHORT( p ) << 16;
+ tmp = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
+ apaint->u.radial_gradient.r1 = tmp < 0 ? FT_INT_MAX : tmp;
return 1;
}
@@ -824,7 +834,7 @@
{
Colr* colr;
- FT_Byte *p, *p1, *clip_base;
+ FT_Byte *p, *p1, *clip_base, *limit;
FT_Byte clip_list_format;
FT_ULong num_clip_boxes, i;
@@ -847,16 +857,32 @@
p = colr->clip_list;
+ /* Limit points to the first byte after the end of the color table. */
+ /* Thus, in subsequent limit checks below we need to check whether the */
+ /* read pointer is strictly greater than a position offset by certain */
+ /* field sizes to the left of that position. */
+ limit = (FT_Byte*)colr->table + colr->table_size;
+
+ /* Check whether we can extract one `uint8` and one `uint32`. */
+ if ( p > limit - ( 1 + 4 ) )
+ return 0;
+
clip_base = p;
clip_list_format = FT_NEXT_BYTE ( p );
/* Format byte used here to be able to upgrade ClipList for >16bit */
- /* glyph ids; for now we can expect it to be 0. */
+ /* glyph ids; for now we can expect it to be 0. */
if ( !( clip_list_format == 1 ) )
return 0;
num_clip_boxes = FT_NEXT_ULONG( p );
+ /* Check whether we can extract two `uint16` and one `Offset24`, */
+ /* `num_clip_boxes` times. */
+ if ( colr->table_size / ( 2 + 2 + 3 ) < num_clip_boxes ||
+ p > limit - ( 2 + 2 + 3 ) * num_clip_boxes )
+ return 0;
+
for ( i = 0; i < num_clip_boxes; ++i )
{
gid_start = FT_NEXT_USHORT( p );
@@ -867,7 +893,8 @@
{
p1 = (FT_Byte*)( clip_base + clip_box_offset );
- if ( p1 >= ( (FT_Byte*)colr->table + colr->table_size ) )
+ /* Check whether we can extract one `uint8`. */
+ if ( p1 > limit - 1 )
return 0;
format = FT_NEXT_BYTE( p1 );
@@ -875,6 +902,10 @@
if ( format > 1 )
return 0;
+ /* Check whether we can extract four `FWORD`. */
+ if ( p1 > limit - ( 2 + 2 + 2 + 2 ) )
+ return 0;
+
/* `face->root.size->metrics.x_scale` and `y_scale` are factors */
/* that scale a font unit value in integers to a 26.6 fixed value */
/* according to the requested size, see for example */
diff --git a/thirdparty/freetype/src/sfnt/ttcolr.h b/thirdparty/freetype/src/sfnt/ttcolr.h
index b81e4cb958..4200cb2976 100644
--- a/thirdparty/freetype/src/sfnt/ttcolr.h
+++ b/thirdparty/freetype/src/sfnt/ttcolr.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType colored glyph layer support (specification).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.c b/thirdparty/freetype/src/sfnt/ttcpal.c
index a0d84bca3a..9ae535cbda 100644
--- a/thirdparty/freetype/src/sfnt/ttcpal.c
+++ b/thirdparty/freetype/src/sfnt/ttcpal.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (body).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttcpal.h b/thirdparty/freetype/src/sfnt/ttcpal.h
index 1c5586855b..4717d224fc 100644
--- a/thirdparty/freetype/src/sfnt/ttcpal.h
+++ b/thirdparty/freetype/src/sfnt/ttcpal.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType color palette support (specification).
*
- * Copyright (C) 2018-2021 by
+ * Copyright (C) 2018-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Originally written by Shao Yu Zhang <shaozhang@fb.com>.
diff --git a/thirdparty/freetype/src/sfnt/ttkern.c b/thirdparty/freetype/src/sfnt/ttkern.c
index bb1922caf9..ca1c509406 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.c
+++ b/thirdparty/freetype/src/sfnt/ttkern.c
@@ -5,7 +5,7 @@
* Load the basic TrueType kerning table. This doesn't handle
* kerning data within the GPOS table at the moment.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -94,7 +94,7 @@
p_next = p;
- p += 2; /* skip version */
+ p += 2; /* skip version */
length = FT_NEXT_USHORT( p );
coverage = FT_NEXT_USHORT( p );
@@ -144,7 +144,7 @@
cur_pair = FT_NEXT_ULONG( p );
- if ( cur_pair <= old_pair )
+ if ( cur_pair < old_pair )
break;
p += 2;
@@ -187,11 +187,18 @@
FT_UInt left_glyph,
FT_UInt right_glyph )
{
- FT_Int result = 0;
- FT_UInt count, mask;
- FT_Byte* p = face->kern_table;
- FT_Byte* p_limit = p + face->kern_table_size;
+ FT_Int result = 0;
+ FT_UInt count, mask;
+ FT_Byte* p;
+ FT_Byte* p_limit;
+
+
+ if ( !face->kern_table )
+ return result;
+
+ p = face->kern_table;
+ p_limit = p + face->kern_table_size;
p += 4;
mask = 0x0001;
diff --git a/thirdparty/freetype/src/sfnt/ttkern.h b/thirdparty/freetype/src/sfnt/ttkern.h
index 3d8f1e8347..f063558313 100644
--- a/thirdparty/freetype/src/sfnt/ttkern.h
+++ b/thirdparty/freetype/src/sfnt/ttkern.h
@@ -5,7 +5,7 @@
* Load the basic TrueType kerning table. This doesn't handle
* kerning data within the GPOS table at the moment.
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttload.c b/thirdparty/freetype/src/sfnt/ttload.c
index 51416d80b4..c83bd197fe 100644
--- a/thirdparty/freetype/src/sfnt/ttload.c
+++ b/thirdparty/freetype/src/sfnt/ttload.c
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -205,7 +205,6 @@
if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
{
- nn--;
FT_TRACE2(( "check_table_dir:"
" can read only %d table%s in font (instead of %d)\n",
nn, nn == 1 ? "" : "s", sfnt->num_tables ));
diff --git a/thirdparty/freetype/src/sfnt/ttload.h b/thirdparty/freetype/src/sfnt/ttload.h
index cab15cd238..5368971c31 100644
--- a/thirdparty/freetype/src/sfnt/ttload.h
+++ b/thirdparty/freetype/src/sfnt/ttload.h
@@ -5,7 +5,7 @@
* Load the basic TrueType tables, i.e., tables that can be either in
* TTF or OTF fonts (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.c b/thirdparty/freetype/src/sfnt/ttmtx.c
index 7aece36fb0..88377327c6 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.c
+++ b/thirdparty/freetype/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (body).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttmtx.h b/thirdparty/freetype/src/sfnt/ttmtx.h
index 270170d478..1e45b949a5 100644
--- a/thirdparty/freetype/src/sfnt/ttmtx.h
+++ b/thirdparty/freetype/src/sfnt/ttmtx.h
@@ -4,7 +4,7 @@
*
* Load the metrics tables common to TTF and OTF fonts (specification).
*
- * Copyright (C) 2006-2021 by
+ * Copyright (C) 2006-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttpost.c b/thirdparty/freetype/src/sfnt/ttpost.c
index b92ca5db14..1a885a15c5 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.c
+++ b/thirdparty/freetype/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttpost.h b/thirdparty/freetype/src/sfnt/ttpost.h
index 6d65b5766c..bf9342a9f5 100644
--- a/thirdparty/freetype/src/sfnt/ttpost.h
+++ b/thirdparty/freetype/src/sfnt/ttpost.h
@@ -5,7 +5,7 @@
* PostScript name table processing for TrueType and OpenType fonts
* (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.c b/thirdparty/freetype/src/sfnt/ttsbit.c
index e9ba697dba..bf73d04e54 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.c
+++ b/thirdparty/freetype/src/sfnt/ttsbit.c
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (body).
*
- * Copyright (C) 2005-2021 by
+ * Copyright (C) 2005-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* Copyright 2013 by Google, Inc.
@@ -172,17 +172,8 @@
goto Exit;
}
-#ifdef FT_DEBUG_LEVEL_TRACE
- /* we currently don't support bit 1; however, it is better to */
- /* draw at least something... */
if ( flags == 3 )
- {
- FT_TRACE1(( "tt_face_load_sbit_strikes:"
- " sbix overlay not supported yet\n" ));
- FT_TRACE1(( " "
- " expect bad rendering results\n" ));
- }
-#endif
+ face->root.face_flags |= FT_FACE_FLAG_SBIX_OVERLAY;
/*
* Count the number of strikes available in the table. We are a bit
@@ -730,6 +721,9 @@
pitch = bitmap->pitch;
line = bitmap->buffer;
+ if ( !line )
+ goto Exit;
+
width = decoder->metrics->width;
height = decoder->metrics->height;
@@ -1577,17 +1571,34 @@
if ( !error )
{
- FT_Short abearing;
+ FT_Short abearing; /* not used here */
FT_UShort aadvance;
tt_face_get_metrics( face, FALSE, glyph_index, &abearing, &aadvance );
metrics->horiBearingX = (FT_Short)originOffsetX;
- metrics->horiBearingY = (FT_Short)( -originOffsetY + metrics->height );
+ metrics->vertBearingX = (FT_Short)originOffsetX;
+
+ metrics->horiBearingY = (FT_Short)( originOffsetY + metrics->height );
+ metrics->vertBearingY = (FT_Short)originOffsetY;
+
metrics->horiAdvance = (FT_UShort)( aadvance *
face->root.size->metrics.x_ppem /
face->header.Units_Per_EM );
+
+ if ( face->vertical_info )
+ tt_face_get_metrics( face, TRUE, glyph_index, &abearing, &aadvance );
+ else if ( face->os2.version != 0xFFFFU )
+ aadvance = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
+ face->os2.sTypoDescender );
+ else
+ aadvance = (FT_UShort)FT_ABS( face->horizontal.Ascender -
+ face->horizontal.Descender );
+
+ metrics->vertAdvance = (FT_UShort)( aadvance *
+ face->root.size->metrics.x_ppem /
+ face->header.Units_Per_EM );
}
return error;
diff --git a/thirdparty/freetype/src/sfnt/ttsbit.h b/thirdparty/freetype/src/sfnt/ttsbit.h
index 7a0ed92e92..c967bffba3 100644
--- a/thirdparty/freetype/src/sfnt/ttsbit.h
+++ b/thirdparty/freetype/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
*
* TrueType and OpenType embedded bitmap support (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/ttsvg.c b/thirdparty/freetype/src/sfnt/ttsvg.c
new file mode 100644
index 0000000000..69277da577
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttsvg.c
@@ -0,0 +1,403 @@
+/****************************************************************************
+ *
+ * ttsvg.c
+ *
+ * OpenType SVG Color (specification).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+
+ /**************************************************************************
+ *
+ * 'SVG' table specification:
+ *
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/svg
+ *
+ */
+
+#include <ft2build.h>
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/internal/ftdebug.h>
+#include <freetype/tttags.h>
+#include <freetype/ftgzip.h>
+#include <freetype/otsvg.h>
+
+
+#ifdef FT_CONFIG_OPTION_SVG
+
+#include "ttsvg.h"
+
+
+ /* NOTE: These table sizes are given by the specification. */
+#define SVG_TABLE_HEADER_SIZE (10U)
+#define SVG_DOCUMENT_RECORD_SIZE (12U)
+#define SVG_DOCUMENT_LIST_MINIMUM_SIZE (2U + SVG_DOCUMENT_RECORD_SIZE)
+#define SVG_MINIMUM_SIZE (SVG_TABLE_HEADER_SIZE + \
+ SVG_DOCUMENT_LIST_MINIMUM_SIZE)
+
+
+ typedef struct Svg_
+ {
+ FT_UShort version; /* table version (starting at 0) */
+ FT_UShort num_entries; /* number of SVG document records */
+
+ FT_Byte* svg_doc_list; /* pointer to the start of SVG Document List */
+
+ void* table; /* memory that backs up SVG */
+ FT_ULong table_size;
+
+ } Svg;
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT ttsvg
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_svg( TT_Face face,
+ FT_Stream stream )
+ {
+ FT_Error error;
+ FT_Memory memory = face->root.memory;
+
+ FT_ULong table_size;
+ FT_Byte* table = NULL;
+ FT_Byte* p = NULL;
+ Svg* svg = NULL;
+ FT_ULong offsetToSVGDocumentList;
+
+
+ error = face->goto_table( face, TTAG_SVG, stream, &table_size );
+ if ( error )
+ goto NoSVG;
+
+ if ( table_size < SVG_MINIMUM_SIZE )
+ goto InvalidTable;
+
+ if ( FT_FRAME_EXTRACT( table_size, table ) )
+ goto NoSVG;
+
+ /* Allocate memory for the SVG object */
+ if ( FT_NEW( svg ) )
+ goto NoSVG;
+
+ p = table;
+ svg->version = FT_NEXT_USHORT( p );
+ offsetToSVGDocumentList = FT_NEXT_ULONG( p );
+
+ if ( offsetToSVGDocumentList < SVG_TABLE_HEADER_SIZE ||
+ offsetToSVGDocumentList > table_size -
+ SVG_DOCUMENT_LIST_MINIMUM_SIZE )
+ goto InvalidTable;
+
+ svg->svg_doc_list = (FT_Byte*)( table + offsetToSVGDocumentList );
+
+ p = svg->svg_doc_list;
+ svg->num_entries = FT_NEXT_USHORT( p );
+
+ FT_TRACE3(( "version: %d\n", svg->version ));
+ FT_TRACE3(( "number of entries: %d\n", svg->num_entries ));
+
+ if ( offsetToSVGDocumentList +
+ svg->num_entries * SVG_DOCUMENT_RECORD_SIZE > table_size )
+ goto InvalidTable;
+
+ svg->table = table;
+ svg->table_size = table_size;
+
+ face->svg = svg;
+ face->root.face_flags |= FT_FACE_FLAG_SVG;
+
+ return FT_Err_Ok;
+
+ InvalidTable:
+ error = FT_THROW( Invalid_Table );
+
+ NoSVG:
+ FT_FRAME_RELEASE( table );
+ FT_FREE( svg );
+ face->svg = NULL;
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( void )
+ tt_face_free_svg( TT_Face face )
+ {
+ FT_Memory memory = face->root.memory;
+ FT_Stream stream = face->root.stream;
+
+ Svg* svg = (Svg*)face->svg;
+
+
+ if ( svg )
+ {
+ FT_FRAME_RELEASE( svg->table );
+ FT_FREE( svg );
+ }
+ }
+
+
+ typedef struct Svg_doc_
+ {
+ FT_UShort start_glyph_id;
+ FT_UShort end_glyph_id;
+
+ FT_ULong offset;
+ FT_ULong length;
+
+ } Svg_doc;
+
+
+ static Svg_doc
+ extract_svg_doc( FT_Byte* stream )
+ {
+ Svg_doc doc;
+
+
+ doc.start_glyph_id = FT_NEXT_USHORT( stream );
+ doc.end_glyph_id = FT_NEXT_USHORT( stream );
+
+ doc.offset = FT_NEXT_ULONG( stream );
+ doc.length = FT_NEXT_ULONG( stream );
+
+ return doc;
+ }
+
+
+ static FT_Int
+ compare_svg_doc( Svg_doc doc,
+ FT_UInt glyph_index )
+ {
+ if ( glyph_index < doc.start_glyph_id )
+ return -1;
+ else if ( glyph_index > doc.end_glyph_id )
+ return 1;
+ else
+ return 0;
+ }
+
+
+ static FT_Error
+ find_doc( FT_Byte* stream,
+ FT_UShort num_entries,
+ FT_UInt glyph_index,
+ FT_ULong *doc_offset,
+ FT_ULong *doc_length,
+ FT_UShort *start_glyph,
+ FT_UShort *end_glyph )
+ {
+ FT_Error error;
+
+ Svg_doc start_doc;
+ Svg_doc mid_doc;
+ Svg_doc end_doc;
+
+ FT_Bool found = FALSE;
+ FT_UInt i = 0;
+
+ FT_UInt start_index = 0;
+ FT_UInt end_index = num_entries - 1;
+ FT_Int comp_res;
+
+
+ /* search algorithm */
+ if ( num_entries == 0 )
+ {
+ error = FT_THROW( Invalid_Table );
+ return error;
+ }
+
+ start_doc = extract_svg_doc( stream + start_index * 12 );
+ end_doc = extract_svg_doc( stream + end_index * 12 );
+
+ if ( ( compare_svg_doc( start_doc, glyph_index ) == -1 ) ||
+ ( compare_svg_doc( end_doc, glyph_index ) == 1 ) )
+ {
+ error = FT_THROW( Invalid_Glyph_Index );
+ return error;
+ }
+
+ while ( start_index <= end_index )
+ {
+ i = ( start_index + end_index ) / 2;
+ mid_doc = extract_svg_doc( stream + i * 12 );
+ comp_res = compare_svg_doc( mid_doc, glyph_index );
+
+ if ( comp_res == 1 )
+ {
+ start_index = i + 1;
+ start_doc = extract_svg_doc( stream + start_index * 4 );
+ }
+ else if ( comp_res == -1 )
+ {
+ end_index = i - 1;
+ end_doc = extract_svg_doc( stream + end_index * 4 );
+ }
+ else
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ /* search algorithm end */
+
+ if ( found != TRUE )
+ {
+ FT_TRACE5(( "SVG glyph not found\n" ));
+ error = FT_THROW( Invalid_Glyph_Index );
+ }
+ else
+ {
+ *doc_offset = mid_doc.offset;
+ *doc_length = mid_doc.length;
+
+ *start_glyph = mid_doc.start_glyph_id;
+ *end_glyph = mid_doc.end_glyph_id;
+
+ error = FT_Err_Ok;
+ }
+
+ return error;
+ }
+
+
+ FT_LOCAL_DEF( FT_Error )
+ tt_face_load_svg_doc( FT_GlyphSlot glyph,
+ FT_UInt glyph_index )
+ {
+ FT_Byte* doc_list; /* pointer to the SVG doc list */
+ FT_UShort num_entries; /* total number of entries in doc list */
+ FT_ULong doc_offset;
+ FT_ULong doc_length;
+
+ FT_UShort start_glyph_id;
+ FT_UShort end_glyph_id;
+
+ FT_Error error = FT_Err_Ok;
+ TT_Face face = (TT_Face)glyph->face;
+ FT_Memory memory = face->root.memory;
+ Svg* svg = (Svg*)face->svg;
+
+ FT_SVG_Document svg_document = (FT_SVG_Document)glyph->other;
+
+
+ FT_ASSERT( !( svg == NULL ) );
+
+ doc_list = svg->svg_doc_list;
+ num_entries = FT_NEXT_USHORT( doc_list );
+
+ error = find_doc( doc_list, num_entries, glyph_index,
+ &doc_offset, &doc_length,
+ &start_glyph_id, &end_glyph_id );
+ if ( error != FT_Err_Ok )
+ goto Exit;
+
+ doc_list = svg->svg_doc_list; /* reset, so we can use it again */
+ doc_list = (FT_Byte*)( doc_list + doc_offset );
+
+ if ( ( doc_list[0] == 0x1F ) && ( doc_list[1] == 0x8B )
+ && ( doc_list[2] == 0x08 ) )
+ {
+#ifdef FT_CONFIG_OPTION_USE_ZLIB
+
+ FT_ULong uncomp_size;
+ FT_Byte* uncomp_buffer = NULL;
+
+
+ /*
+ * Get the size of the original document. This helps in allotting the
+ * buffer to accommodate the uncompressed version. The last 4 bytes
+ * of the compressed document are equal to the original size modulo
+ * 2^32. Since the size of SVG documents is less than 2^32 bytes we
+ * can use this accurately. The four bytes are stored in
+ * little-endian format.
+ */
+ FT_TRACE4(( "SVG document is GZIP compressed\n" ));
+ uncomp_size = (FT_ULong)doc_list[doc_length - 1] << 24 |
+ (FT_ULong)doc_list[doc_length - 2] << 16 |
+ (FT_ULong)doc_list[doc_length - 3] << 8 |
+ (FT_ULong)doc_list[doc_length - 4];
+
+ if ( FT_QALLOC( uncomp_buffer, uncomp_size ) )
+ goto Exit;
+
+ error = FT_Gzip_Uncompress( memory,
+ uncomp_buffer,
+ &uncomp_size,
+ doc_list,
+ doc_length );
+ if ( error )
+ {
+ FT_FREE( uncomp_buffer );
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ glyph->internal->flags |= FT_GLYPH_OWN_GZIP_SVG;
+
+ doc_list = uncomp_buffer;
+ doc_length = uncomp_size;
+
+#else /* !FT_CONFIG_OPTION_USE_ZLIB */
+
+ error = FT_THROW( Unimplemented_Feature );
+ goto Exit;
+
+#endif /* !FT_CONFIG_OPTION_USE_ZLIB */
+ }
+
+ svg_document->svg_document = doc_list;
+ svg_document->svg_document_length = doc_length;
+
+ svg_document->metrics = glyph->face->size->metrics;
+ svg_document->units_per_EM = glyph->face->units_per_EM;
+
+ svg_document->start_glyph_id = start_glyph_id;
+ svg_document->end_glyph_id = end_glyph_id;
+
+ svg_document->transform.xx = 0x10000;
+ svg_document->transform.xy = 0;
+ svg_document->transform.yx = 0;
+ svg_document->transform.yy = 0x10000;
+
+ svg_document->delta.x = 0;
+ svg_document->delta.y = 0;
+
+ FT_TRACE5(( "start_glyph_id: %d\n", start_glyph_id ));
+ FT_TRACE5(( "end_glyph_id: %d\n", end_glyph_id ));
+ FT_TRACE5(( "svg_document:\n" ));
+ FT_TRACE5(( " %.*s\n", (FT_UInt)doc_length, doc_list ));
+
+ glyph->other = svg_document;
+
+ Exit:
+ return error;
+ }
+
+#else /* !FT_CONFIG_OPTION_SVG */
+
+ /* ANSI C doesn't like empty source files */
+ typedef int _tt_svg_dummy;
+
+#endif /* !FT_CONFIG_OPTION_SVG */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/ttsvg.h b/thirdparty/freetype/src/sfnt/ttsvg.h
new file mode 100644
index 0000000000..7c234fd524
--- /dev/null
+++ b/thirdparty/freetype/src/sfnt/ttsvg.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ *
+ * ttsvg.h
+ *
+ * OpenType SVG Color (specification).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#ifndef TTSVG_H_
+#define TTSVG_H_
+
+#include <freetype/internal/ftstream.h>
+#include <freetype/internal/tttypes.h>
+
+
+FT_BEGIN_HEADER
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_svg( TT_Face face,
+ FT_Stream stream );
+
+ FT_LOCAL( void )
+ tt_face_free_svg( TT_Face face );
+
+ FT_LOCAL( FT_Error )
+ tt_face_load_svg_doc( FT_GlyphSlot glyph,
+ FT_UInt glyph_index );
+
+FT_END_HEADER
+
+#endif /* TTSVG_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/sfnt/woff2tags.c b/thirdparty/freetype/src/sfnt/woff2tags.c
index fe8f5cf76f..7d79fef39a 100644
--- a/thirdparty/freetype/src/sfnt/woff2tags.c
+++ b/thirdparty/freetype/src/sfnt/woff2tags.c
@@ -4,7 +4,7 @@
*
* WOFF2 Font table tags (base).
*
- * Copyright (C) 2019-2021 by
+ * Copyright (C) 2019-2022 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/sfnt/woff2tags.h b/thirdparty/freetype/src/sfnt/woff2tags.h
index 4ef0a651c3..05df85aba0 100644
--- a/thirdparty/freetype/src/sfnt/woff2tags.h
+++ b/thirdparty/freetype/src/sfnt/woff2tags.h
@@ -4,7 +4,7 @@
*
* WOFF2 Font table tags (specification).
*
- * Copyright (C) 2019-2021 by
+ * Copyright (C) 2019-2022 by
* Nikhil Ramakrishnan, David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftgrays.c b/thirdparty/freetype/src/smooth/ftgrays.c
index d982c2820b..5d9e1600b7 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.c
+++ b/thirdparty/freetype/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
*
* A new `perfect' anti-aliasing renderer (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -333,7 +333,9 @@ typedef ptrdiff_t FT_PtrDist;
#define PIXEL_BITS 8
#define ONE_PIXEL ( 1 << PIXEL_BITS )
+#undef TRUNC
#define TRUNC( x ) (TCoord)( (x) >> PIXEL_BITS )
+#undef FRACT
#define FRACT( x ) (TCoord)( (x) & ( ONE_PIXEL - 1 ) )
#if PIXEL_BITS >= 6
@@ -1905,6 +1907,9 @@ typedef ptrdiff_t FT_PtrDist;
0 /* delta */
)
+// -- GODOT start --
+ static volatile int _lto_dummy = 0;
+// -- GODOT end --
static int
gray_convert_glyph_inner( RAS_ARG,
@@ -1926,6 +1931,9 @@ typedef ptrdiff_t FT_PtrDist;
ras.max_ey,
ras.cell_null - ras.cell_free,
ras.cell_null - ras.cell_free == 1 ? "" : "s" ));
+// -- GODOT start --
+ _lto_dummy = error; // Prevents LTO from removing this branch.
+// -- GODOT end --
}
else
{
@@ -1933,6 +1941,9 @@ typedef ptrdiff_t FT_PtrDist;
FT_TRACE7(( "band [%d..%d]: to be bisected\n",
ras.min_ey, ras.max_ey ));
+// -- GODOT start --
+ _lto_dummy = error; // Prevents LTO from removing this branch.
+// -- GODOT end --
}
return error;
diff --git a/thirdparty/freetype/src/smooth/ftgrays.h b/thirdparty/freetype/src/smooth/ftgrays.h
index 3dad0498dc..13bf2baaa2 100644
--- a/thirdparty/freetype/src/smooth/ftgrays.h
+++ b/thirdparty/freetype/src/smooth/ftgrays.h
@@ -4,7 +4,7 @@
*
* FreeType smooth renderer declaration
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftsmerrs.h b/thirdparty/freetype/src/smooth/ftsmerrs.h
index dc2c40cc9f..7bc6077988 100644
--- a/thirdparty/freetype/src/smooth/ftsmerrs.h
+++ b/thirdparty/freetype/src/smooth/ftsmerrs.h
@@ -4,7 +4,7 @@
*
* smooth renderer error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.c b/thirdparty/freetype/src/smooth/ftsmooth.c
index bea3b4a800..df227c3758 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.c
+++ b/thirdparty/freetype/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (body).
*
- * Copyright (C) 2000-2021 by
+ * Copyright (C) 2000-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/ftsmooth.h b/thirdparty/freetype/src/smooth/ftsmooth.h
index 2dd81e84b8..87f09faea4 100644
--- a/thirdparty/freetype/src/smooth/ftsmooth.h
+++ b/thirdparty/freetype/src/smooth/ftsmooth.h
@@ -4,7 +4,7 @@
*
* Anti-aliasing renderer interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/smooth/smooth.c b/thirdparty/freetype/src/smooth/smooth.c
index 9e25440635..f341e8f252 100644
--- a/thirdparty/freetype/src/smooth/smooth.c
+++ b/thirdparty/freetype/src/smooth/smooth.c
@@ -4,7 +4,7 @@
*
* FreeType anti-aliasing rasterer module component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/svg/ftsvg.c b/thirdparty/freetype/src/svg/ftsvg.c
new file mode 100644
index 0000000000..55c50718f3
--- /dev/null
+++ b/thirdparty/freetype/src/svg/ftsvg.c
@@ -0,0 +1,350 @@
+/****************************************************************************
+ *
+ * ftsvg.c
+ *
+ * The FreeType SVG renderer interface (body).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#include <freetype/internal/ftdebug.h>
+#include <freetype/internal/ftserv.h>
+#include <freetype/internal/services/svprop.h>
+#include <freetype/otsvg.h>
+#include <freetype/internal/svginterface.h>
+#include <freetype/ftbbox.h>
+
+#include "ftsvg.h"
+#include "svgtypes.h"
+
+
+ /**************************************************************************
+ *
+ * The macro FT_COMPONENT is used in trace mode. It is an implicit
+ * parameter of the FT_TRACE() and FT_ERROR() macros, usued to print/log
+ * messages during execution.
+ */
+#undef FT_COMPONENT
+#define FT_COMPONENT otsvg
+
+
+#ifdef FT_CONFIG_OPTION_SVG
+
+ /* ft_svg_init */
+ static FT_Error
+ ft_svg_init( SVG_Renderer svg_module )
+ {
+ FT_Error error = FT_Err_Ok;
+
+
+ svg_module->loaded = FALSE;
+ svg_module->hooks_set = FALSE;
+
+ return error;
+ }
+
+
+ static void
+ ft_svg_done( SVG_Renderer svg_module )
+ {
+ if ( svg_module->loaded == TRUE &&
+ svg_module->hooks_set == TRUE )
+ svg_module->hooks.free_svg( &svg_module->state );
+
+ svg_module->loaded = FALSE;
+ }
+
+
+ static FT_Error
+ ft_svg_preset_slot( FT_Module module,
+ FT_GlyphSlot slot,
+ FT_Bool cache )
+ {
+ SVG_Renderer svg_renderer = (SVG_Renderer)module;
+ SVG_RendererHooks hooks = svg_renderer->hooks;
+
+
+ if ( svg_renderer->hooks_set == FALSE )
+ {
+ FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" ));
+ return FT_THROW( Missing_SVG_Hooks );
+ }
+
+ if ( svg_renderer->loaded == FALSE )
+ {
+ FT_TRACE3(( "ft_svg_preset_slot: first presetting call,"
+ " calling init hook\n" ));
+ hooks.init_svg( &svg_renderer->state );
+
+ svg_renderer->loaded = TRUE;
+ }
+
+ return hooks.preset_slot( slot, cache, &svg_renderer->state );
+ }
+
+
+ static FT_Error
+ ft_svg_render( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ FT_Render_Mode mode,
+ const FT_Vector* origin )
+ {
+ SVG_Renderer svg_renderer = (SVG_Renderer)renderer;
+
+ FT_Library library = renderer->root.library;
+ FT_Memory memory = library->memory;
+ FT_Error error;
+
+ FT_ULong size_image_buffer;
+
+ SVG_RendererHooks hooks = svg_renderer->hooks;
+
+
+ FT_UNUSED( mode );
+ FT_UNUSED( origin );
+
+ if ( mode != FT_RENDER_MODE_NORMAL )
+ return FT_THROW( Bad_Argument );
+
+ if ( svg_renderer->hooks_set == FALSE )
+ {
+ FT_TRACE1(( "Hooks are NOT set. Can't render OT-SVG glyphs\n" ));
+ return FT_THROW( Missing_SVG_Hooks );
+ }
+
+ if ( svg_renderer->loaded == FALSE )
+ {
+ FT_TRACE3(( "ft_svg_render: first rendering, calling init hook\n" ));
+ error = hooks.init_svg( &svg_renderer->state );
+
+ svg_renderer->loaded = TRUE;
+ }
+
+ ft_svg_preset_slot( (FT_Module)renderer, slot, TRUE );
+
+ size_image_buffer = (FT_ULong)slot->bitmap.pitch * slot->bitmap.rows;
+ /* No `FT_QALLOC` here since we need a clean, empty canvas */
+ /* to start with. */
+ if ( FT_ALLOC( slot->bitmap.buffer, size_image_buffer ) )
+ return error;
+
+ error = hooks.render_svg( slot, &svg_renderer->state );
+ if ( error )
+ FT_FREE( slot->bitmap.buffer );
+ else
+ slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
+
+ return error;
+ }
+
+
+ static const SVG_Interface svg_interface =
+ {
+ (Preset_Bitmap_Func)ft_svg_preset_slot
+ };
+
+
+ static FT_Error
+ ft_svg_property_set( FT_Module module,
+ const char* property_name,
+ const void* value,
+ FT_Bool value_is_string )
+ {
+ FT_Error error = FT_Err_Ok;
+ SVG_Renderer renderer = (SVG_Renderer)module;
+
+
+ if ( !ft_strcmp( property_name, "svg-hooks" ) )
+ {
+ SVG_RendererHooks* hooks;
+
+
+ if ( value_is_string == TRUE )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ hooks = (SVG_RendererHooks*)value;
+
+ if ( !hooks->init_svg ||
+ !hooks->free_svg ||
+ !hooks->render_svg ||
+ !hooks->preset_slot )
+ {
+ FT_TRACE0(( "ft_svg_property_set:"
+ " SVG rendering hooks not set because\n" ));
+ FT_TRACE0(( " "
+ " at least one function pointer is NULL\n" ));
+
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ renderer->hooks = *hooks;
+ renderer->hooks_set = TRUE;
+ }
+ else
+ error = FT_THROW( Missing_Property );
+
+ Exit:
+ return error;
+ }
+
+
+ static FT_Error
+ ft_svg_property_get( FT_Module module,
+ const char* property_name,
+ const void* value )
+ {
+ FT_Error error = FT_Err_Ok;
+ SVG_Renderer renderer = (SVG_Renderer)module;
+
+
+ if ( !ft_strcmp( property_name, "svg-hooks" ) )
+ {
+ SVG_RendererHooks* hooks = (SVG_RendererHooks*)value;
+
+
+ *hooks = renderer->hooks;
+ }
+ else
+ error = FT_THROW( Missing_Property );
+
+ return error;
+ }
+
+
+ FT_DEFINE_SERVICE_PROPERTIESREC(
+ ft_svg_service_properties,
+
+ (FT_Properties_SetFunc)ft_svg_property_set, /* set_property */
+ (FT_Properties_GetFunc)ft_svg_property_get /* get_property */
+ )
+
+
+ FT_DEFINE_SERVICEDESCREC1(
+ ft_svg_services,
+ FT_SERVICE_ID_PROPERTIES, &ft_svg_service_properties )
+
+
+ FT_CALLBACK_DEF( FT_Module_Interface )
+ ft_svg_get_interface( FT_Module module,
+ const char* ft_svg_interface )
+ {
+ FT_Module_Interface result;
+
+
+ FT_UNUSED( module );
+
+ result = ft_service_list_lookup( ft_svg_services, ft_svg_interface );
+ if ( result )
+ return result;
+
+ return 0;
+ }
+
+
+ static FT_Error
+ ft_svg_transform( FT_Renderer renderer,
+ FT_GlyphSlot slot,
+ const FT_Matrix* _matrix,
+ const FT_Vector* _delta )
+ {
+ FT_SVG_Document doc = (FT_SVG_Document)slot->other;
+ FT_Matrix* matrix = (FT_Matrix*)_matrix;
+ FT_Vector* delta = (FT_Vector*)_delta;
+
+ FT_Matrix tmp_matrix;
+ FT_Vector tmp_delta;
+
+ FT_Matrix a, b;
+ FT_Pos x, y;
+
+
+ FT_UNUSED( renderer );
+
+ if ( !matrix )
+ {
+ tmp_matrix.xx = 0x10000;
+ tmp_matrix.xy = 0;
+ tmp_matrix.yx = 0;
+ tmp_matrix.yy = 0x10000;
+
+ matrix = &tmp_matrix;
+ }
+
+ if ( !delta )
+ {
+ tmp_delta.x = 0;
+ tmp_delta.y = 0;
+
+ delta = &tmp_delta;
+ }
+
+ a = doc->transform;
+ b = *matrix;
+ FT_Matrix_Multiply( &b, &a );
+
+
+ x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, doc->delta.x ),
+ FT_MulFix( matrix->xy, doc->delta.y ) ),
+ delta->x );
+ y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, doc->delta.x ),
+ FT_MulFix( matrix->yy, doc->delta.y ) ),
+ delta->y );
+
+ doc->delta.x = x;
+ doc->delta.y = y;
+ doc->transform = a;
+
+ return FT_Err_Ok;
+ }
+
+#endif /* FT_CONFIG_OPTION_SVG */
+
+
+#ifdef FT_CONFIG_OPTION_SVG
+#define PUT_SVG_MODULE( a ) a
+#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_SVG
+#else
+#define PUT_SVG_MODULE( a ) NULL
+#define SVG_GLYPH_FORMAT FT_GLYPH_FORMAT_NONE
+#endif
+
+
+ FT_DEFINE_RENDERER(
+ ft_svg_renderer_class,
+
+ FT_MODULE_RENDERER,
+ sizeof ( SVG_RendererRec ),
+
+ "ot-svg",
+ 0x10000L,
+ 0x20000L,
+
+ (const void*)PUT_SVG_MODULE( &svg_interface ), /* module specific interface */
+
+ (FT_Module_Constructor)PUT_SVG_MODULE( ft_svg_init ), /* module_init */
+ (FT_Module_Destructor)PUT_SVG_MODULE( ft_svg_done ), /* module_done */
+ PUT_SVG_MODULE( ft_svg_get_interface ), /* get_interface */
+
+ SVG_GLYPH_FORMAT,
+
+ (FT_Renderer_RenderFunc) PUT_SVG_MODULE( ft_svg_render ), /* render_glyph */
+ (FT_Renderer_TransformFunc)PUT_SVG_MODULE( ft_svg_transform ), /* transform_glyph */
+ NULL, /* get_glyph_cbox */
+ NULL, /* set_mode */
+ NULL /* raster_class */
+ )
+
+
+/* END */
diff --git a/thirdparty/freetype/src/svg/ftsvg.h b/thirdparty/freetype/src/svg/ftsvg.h
new file mode 100644
index 0000000000..73514b8cf3
--- /dev/null
+++ b/thirdparty/freetype/src/svg/ftsvg.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+ *
+ * ftsvg.h
+ *
+ * The FreeType SVG renderer interface (specification).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#ifndef FTSVG_H_
+#define FTSVG_H_
+
+#include <ft2build.h>
+#include <freetype/ftrender.h>
+#include <freetype/internal/ftobjs.h>
+
+
+FT_BEGIN_HEADER
+
+ FT_DECLARE_RENDERER( ft_svg_renderer_class )
+
+FT_END_HEADER
+
+#endif /* FTSVG_H_ */
+
+
+/* END */
diff --git a/thirdparty/freetype/src/svg/svg.c b/thirdparty/freetype/src/svg/svg.c
new file mode 100644
index 0000000000..b7e62a418c
--- /dev/null
+++ b/thirdparty/freetype/src/svg/svg.c
@@ -0,0 +1,24 @@
+/****************************************************************************
+ *
+ * svg.c
+ *
+ * FreeType SVG renderer module component (body only).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+
+#include "svgtypes.h"
+#include "ftsvg.c"
+
+
+/* END */
diff --git a/thirdparty/freetype/src/svg/svgtypes.h b/thirdparty/freetype/src/svg/svgtypes.h
new file mode 100644
index 0000000000..34fce47a34
--- /dev/null
+++ b/thirdparty/freetype/src/svg/svgtypes.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ *
+ * svgtypes.h
+ *
+ * The FreeType SVG renderer internal types (specification).
+ *
+ * Copyright (C) 2022 by
+ * David Turner, Robert Wilhelm, Werner Lemberg, and Moazin Khatti.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT. By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
+
+#ifndef SVGTYPES_H_
+#define SVGTYPES_H_
+
+#include <ft2build.h>
+#include <freetype/internal/ftobjs.h>
+#include <freetype/ftrender.h>
+#include <freetype/otsvg.h>
+
+
+ typedef struct SVG_RendererRec_
+ {
+ FT_RendererRec root; /* this inherits FT_RendererRec */
+ FT_Bool loaded;
+ FT_Bool hooks_set;
+ SVG_RendererHooks hooks; /* this holds hooks for SVG rendering */
+ FT_Pointer state; /* a place for hooks to store state, if needed */
+
+ } SVG_RendererRec;
+
+ typedef struct SVG_RendererRec_* SVG_Renderer;
+
+#endif /* SVGTYPES_H_ */
+
+
+/* EOF */
diff --git a/thirdparty/freetype/src/truetype/truetype.c b/thirdparty/freetype/src/truetype/truetype.c
index 4232aca6ec..41c844acbb 100644
--- a/thirdparty/freetype/src/truetype/truetype.c
+++ b/thirdparty/freetype/src/truetype/truetype.c
@@ -4,7 +4,7 @@
*
* FreeType TrueType driver component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttdriver.c b/thirdparty/freetype/src/truetype/ttdriver.c
index 6fcfdb23e4..245d97cb58 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.c
+++ b/thirdparty/freetype/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
*
* TrueType font driver implementation (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttdriver.h b/thirdparty/freetype/src/truetype/ttdriver.h
index 4e6d52d22c..c477c0b1dd 100644
--- a/thirdparty/freetype/src/truetype/ttdriver.h
+++ b/thirdparty/freetype/src/truetype/ttdriver.h
@@ -4,7 +4,7 @@
*
* High-level TrueType driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/tterrors.h b/thirdparty/freetype/src/truetype/tterrors.h
index 0ce247e376..2c95ea17b2 100644
--- a/thirdparty/freetype/src/truetype/tterrors.h
+++ b/thirdparty/freetype/src/truetype/tterrors.h
@@ -4,7 +4,7 @@
*
* TrueType error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttgload.c b/thirdparty/freetype/src/truetype/ttgload.c
index 11968f6fdc..2ca63d65a3 100644
--- a/thirdparty/freetype/src/truetype/ttgload.c
+++ b/thirdparty/freetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1104,8 +1104,8 @@
for ( ; vec < limit; vec++, u++ )
{
- vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6;
- vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6;
+ vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6;
+ vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6;
}
}
else
@@ -1228,8 +1228,8 @@
p1 = gloader->base.outline.points + k;
p2 = gloader->base.outline.points + l;
- x = p1->x - p2->x;
- y = p1->y - p2->y;
+ x = SUB_LONG( p1->x, p2->x );
+ y = SUB_LONG( p1->y, p2->y );
}
else
{
@@ -2230,10 +2230,6 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
-#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
- defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
-#endif
FT_BBox bbox;
FT_Fixed y_scale;
@@ -2256,53 +2252,10 @@
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
- glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
-
- /* Adjust advance width to the value contained in the hdmx table */
- /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
- /* mode of the v40 interpreter is active. See `ttinterp.h' for */
- /* details on backward compatibility mode. */
- if (
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
- ( loader->exec && loader->exec->backward_compatibility ) ) &&
-#endif
- !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) &&
- !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
- {
- FT_Byte* widthp;
-
-
- widthp = tt_face_get_device_metrics( face,
- size->metrics->x_ppem,
- glyph_index );
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
-
- if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
- {
- FT_Bool ignore_x_mode;
-
-
- ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
- FT_RENDER_MODE_MONO );
-
- if ( widthp &&
- ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
- !ignore_x_mode ||
- SPH_OPTION_BITMAP_WIDTHS ) )
- glyph->metrics.horiAdvance = *widthp * 64;
- }
- else
-
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
- {
- if ( widthp )
- glyph->metrics.horiAdvance = *widthp * 64;
- }
- }
+ if ( loader->widthp )
+ glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
+ else
+ glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x );
/* set glyph dimensions */
glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
@@ -2735,12 +2688,58 @@
/* note that this flag can also be modified in a glyph's bytecode */
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
exec->GS.instruct_control & 4 )
- exec->ignore_x_mode = 0;
-#endif
+ exec->ignore_x_mode = FALSE;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ /*
+ * Toggle backward compatibility according to what font wants, except
+ * when
+ *
+ * 1) we have a `tricky' font that heavily relies on the interpreter to
+ * render glyphs correctly, for example DFKai-SB, or
+ * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
+ *
+ * In those cases, backward compatibility needs to be turned off to get
+ * correct rendering. The rendering is then completely up to the
+ * font's programming.
+ *
+ */
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+ subpixel_hinting_lean &&
+ !FT_IS_TRICKY( glyph->face ) )
+ exec->backward_compatibility = !( exec->GS.instruct_control & 4 );
+ else
+ exec->backward_compatibility = FALSE;
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
loader->exec = exec;
loader->instructions = exec->glyphIns;
+
+ /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
+ /* is set or backward compatibility mode of the v38 or v40 */
+ /* interpreters is active. See `ttinterp.h' for details on */
+ /* backward compatibility mode. */
+ if ( IS_HINTED( loader->load_flags ) &&
+ !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+ exec->backward_compatibility ) &&
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+ !( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ !SPH_OPTION_BITMAP_WIDTHS &&
+ FT_LOAD_TARGET_MODE( loader->load_flags ) !=
+ FT_RENDER_MODE_MONO &&
+ exec->compatible_widths ) &&
+#endif
+ !face->postscript.isFixedPitch )
+ {
+ loader->widthp = size->widthp;
+ }
+ else
+ loader->widthp = NULL;
}
#endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -2788,11 +2787,12 @@
* A function used to load a single glyph within a given glyph slot,
* for a given size.
*
- * @Input:
+ * @InOut:
* glyph ::
* A handle to a target slot object where the glyph
* will be loaded.
*
+ * @Input:
* size ::
* A handle to the source face size at which the glyph
* must be scaled/loaded.
@@ -2897,8 +2897,12 @@
}
else
{
- if ( FT_IS_SCALABLE( glyph->face ) )
+ if ( FT_IS_SCALABLE( glyph->face ) ||
+ FT_HAS_SBIX( glyph->face ) )
{
+ TT_Face face = (TT_Face)glyph->face;
+
+
/* for the bbox we need the header only */
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
@@ -2906,6 +2910,35 @@
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.vadvance;
+ /* Bitmaps from the 'sbix' table need special treatment: */
+ /* if there is a glyph contour, the bitmap origin must be */
+ /* shifted to be relative to the lower left corner of the */
+ /* glyph bounding box, also taking the left-side bearing */
+ /* (or top bearing) into account. */
+ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
+ loader.n_contours > 0 )
+ {
+ FT_Int bitmap_left;
+ FT_Int bitmap_top;
+
+
+ if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
+ {
+ /* This is a guess, since Apple's CoreText engine doesn't */
+ /* really do vertical typesetting. */
+ bitmap_left = loader.bbox.xMin;
+ bitmap_top = loader.top_bearing;
+ }
+ else
+ {
+ bitmap_left = loader.left_bearing;
+ bitmap_top = loader.bbox.yMin;
+ }
+
+ glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
+ glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6;
+ }
+
/* sanity checks: if `xxxAdvance' in the sbit metric */
/* structure isn't set, use `linearXXXAdvance' */
if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
@@ -2920,6 +2953,12 @@
}
}
+ if ( load_flags & FT_LOAD_SBITS_ONLY )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
/* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
@@ -2929,16 +2968,81 @@
goto Exit;
}
- if ( load_flags & FT_LOAD_SBITS_ONLY )
+#ifdef FT_CONFIG_OPTION_SVG
+
+ /* check for OT-SVG */
+ if ( ( load_flags & FT_LOAD_COLOR ) && ( (TT_Face)glyph->face )->svg )
+ {
+ SFNT_Service sfnt;
+
+ FT_Short leftBearing;
+ FT_Short topBearing;
+ FT_UShort advanceX;
+ FT_UShort advanceY;
+
+
+ FT_TRACE3(( "Trying to load SVG glyph\n" ));
+ sfnt = (SFNT_Service)( (TT_Face)glyph->face )->sfnt;
+
+ error = sfnt->load_svg_doc( glyph, glyph_index );
+ if ( !error )
+ {
+ TT_Face face = (TT_Face)glyph->face;
+
+
+ FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
+
+ glyph->format = FT_GLYPH_FORMAT_SVG;
+
+ sfnt->get_metrics( face,
+ FALSE,
+ glyph_index,
+ &leftBearing,
+ &advanceX );
+ sfnt->get_metrics( face,
+ TRUE,
+ glyph_index,
+ &topBearing,
+ &advanceY );
+
+ advanceX = (FT_UShort)FT_MulDiv( advanceX,
+ glyph->face->size->metrics.x_ppem,
+ glyph->face->units_per_EM );
+ advanceY = (FT_UShort)FT_MulDiv( advanceY,
+ glyph->face->size->metrics.y_ppem,
+ glyph->face->units_per_EM );
+
+ glyph->metrics.horiAdvance = advanceX << 6;
+ glyph->metrics.vertAdvance = advanceY << 6;
+
+ return error;
+ }
+
+ FT_TRACE3(( "Failed to load SVG glyph\n" ));
+ }
+
+ /* return immediately if we only want SVG glyphs */
+ if ( load_flags & FT_LOAD_SVG_ONLY )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
+#endif /* FT_CONFIG_OPTION_SVG */
+
error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
if ( error )
goto Exit;
+ /* done if we are only interested in the `hdmx` advance */
+ if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
+ !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
+ loader.widthp )
+ {
+ glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
+ goto Done;
+ }
+
glyph->format = FT_GLYPH_FORMAT_OUTLINE;
glyph->num_subglyphs = 0;
glyph->outline.flags = 0;
@@ -3017,6 +3121,7 @@
glyph->outline.n_points,
glyph->outline.flags ));
+ Done:
tt_loader_done( &loader );
Exit:
diff --git a/thirdparty/freetype/src/truetype/ttgload.h b/thirdparty/freetype/src/truetype/ttgload.h
index 78fdeaa73d..3195351f78 100644
--- a/thirdparty/freetype/src/truetype/ttgload.h
+++ b/thirdparty/freetype/src/truetype/ttgload.h
@@ -4,7 +4,7 @@
*
* TrueType Glyph Loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.c b/thirdparty/freetype/src/truetype/ttgxvar.c
index 7f2db0cbdc..6a0edef29b 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.c
+++ b/thirdparty/freetype/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.
*
* This file is part of the FreeType project, and may only be used,
@@ -151,9 +151,7 @@
FT_UInt i, j;
FT_UShort first;
FT_Memory memory = stream->memory;
- FT_Error error = FT_Err_Ok;
-
- FT_UNUSED( error );
+ FT_Error error;
*point_cnt = 0;
@@ -266,9 +264,7 @@
FT_UInt i, j;
FT_UInt bytes_used;
FT_Memory memory = stream->memory;
- FT_Error error = FT_Err_Ok;
-
- FT_UNUSED( error );
+ FT_Error error;
if ( FT_QNEW_ARRAY( deltas, delta_cnt ) )
@@ -361,14 +357,12 @@
FT_Memory memory = stream->memory;
GX_Blend blend = face->blend;
GX_AVarSegment segment;
- FT_Error error = FT_Err_Ok;
+ FT_Error error;
FT_Long version;
FT_Long axisCount;
FT_Int i, j;
FT_ULong table_len;
- FT_UNUSED( error );
-
FT_TRACE2(( "AVAR " ));
@@ -421,7 +415,6 @@
FT_FREE( blend->avar_segment[j].correspondence );
FT_FREE( blend->avar_segment );
- blend->avar_segment = NULL;
goto Exit;
}
@@ -2753,7 +2746,6 @@
/* The cvt table has been loaded already; every time we change the */
/* blend we may need to reload and remodify the cvt table. */
FT_FREE( face->cvt );
- face->cvt = NULL;
error = tt_face_load_cvt( face, face->root.stream );
break;
@@ -2772,7 +2764,6 @@
/* enforce recomputation of the PostScript name; */
FT_FREE( face->postscript_name );
- face->postscript_name = NULL;
Exit:
return error;
@@ -3476,6 +3467,7 @@
}
else
{
+ localpoints = NULL;
points = sharedpoints;
point_count = spoint_count;
}
diff --git a/thirdparty/freetype/src/truetype/ttgxvar.h b/thirdparty/freetype/src/truetype/ttgxvar.h
index ded9ea1d6d..17915f00d3 100644
--- a/thirdparty/freetype/src/truetype/ttgxvar.h
+++ b/thirdparty/freetype/src/truetype/ttgxvar.h
@@ -4,7 +4,7 @@
*
* TrueType GX Font Variation loader (specification)
*
- * Copyright (C) 2004-2021 by
+ * Copyright (C) 2004-2022 by
* David Turner, Robert Wilhelm, Werner Lemberg and George Williams.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttinterp.c b/thirdparty/freetype/src/truetype/ttinterp.c
index 731095ed0c..e16565c3a5 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.c
+++ b/thirdparty/freetype/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -5260,16 +5260,21 @@
}
}
- exc->GS.instruct_control &= ~(FT_Byte)Kf;
- exc->GS.instruct_control |= (FT_Byte)L;
+ /* INSTCTRL should only be used in the CVT program */
+ if ( exc->iniRange == tt_coderange_cvt )
+ {
+ exc->GS.instruct_control &= ~(FT_Byte)Kf;
+ exc->GS.instruct_control |= (FT_Byte)L;
+ }
- if ( K == 3 )
+ /* except to change the subpixel flags temporarily */
+ else if ( exc->iniRange == tt_coderange_glyph && K == 3 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* INSTCTRL modifying flag 3 also has an effect */
/* outside of the CVT program */
if ( SUBPIXEL_HINTING_INFINALITY )
- exc->ignore_x_mode = FT_BOOL( L == 4 );
+ exc->ignore_x_mode = !FT_BOOL( L == 4 );
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
@@ -5280,6 +5285,8 @@
exc->backward_compatibility = !FT_BOOL( L == 4 );
#endif
}
+ else if ( exc->pedantic_hinting )
+ exc->error = FT_THROW( Invalid_Reference );
}
@@ -7755,35 +7762,6 @@
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
- exc->iup_called = FALSE;
-#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
-
-#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
- /*
- * Toggle backward compatibility according to what font wants, except
- * when
- *
- * 1) we have a `tricky' font that heavily relies on the interpreter to
- * render glyphs correctly, for example DFKai-SB, or
- * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
- *
- * In those cases, backward compatibility needs to be turned off to get
- * correct rendering. The rendering is then completely up to the
- * font's programming.
- *
- */
- if ( SUBPIXEL_HINTING_MINIMAL &&
- exc->subpixel_hinting_lean &&
- !FT_IS_TRICKY( &exc->face->root ) )
- exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
- else
- exc->backward_compatibility = FALSE;
-
- exc->iupx_called = FALSE;
- exc->iupy_called = FALSE;
-#endif
-
/* We restrict the number of twilight points to a reasonable, */
/* heuristic value to avoid slow execution of malformed bytecode. */
num_twilight_points = FT_MAX( 30,
@@ -7861,6 +7839,15 @@
Compute_Funcs( exc );
Compute_Round( exc, (FT_Byte)exc->GS.round_state );
+ /* These flags cancel execution of some opcodes after IUP is called */
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+ exc->iup_called = FALSE;
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ exc->iupx_called = FALSE;
+ exc->iupy_called = FALSE;
+#endif
+
do
{
exc->opcode = exc->code[exc->IP];
diff --git a/thirdparty/freetype/src/truetype/ttinterp.h b/thirdparty/freetype/src/truetype/ttinterp.h
index 9c01ec83cb..48f618dc9d 100644
--- a/thirdparty/freetype/src/truetype/ttinterp.h
+++ b/thirdparty/freetype/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
*
* TrueType bytecode interpreter (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttobjs.c b/thirdparty/freetype/src/truetype/ttobjs.c
index 93fc548447..f4f3c69336 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.c
+++ b/thirdparty/freetype/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
*
* Objects manager (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -727,7 +727,8 @@
if ( error )
goto Exit;
- if ( FT_IS_SCALABLE( ttface ) )
+ if ( FT_IS_SCALABLE( ttface ) ||
+ FT_HAS_SBIX( ttface ) )
{
#ifdef FT_CONFIG_OPTION_INCREMENTAL
if ( !ttface->internal->incremental_interface )
@@ -1435,6 +1436,8 @@
size->ttmetrics.y_ratio = 0x10000L;
}
+ size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 );
+
size->metrics = size_metrics;
#ifdef TT_USE_BYTECODE_INTERPRETER
diff --git a/thirdparty/freetype/src/truetype/ttobjs.h b/thirdparty/freetype/src/truetype/ttobjs.h
index fd72378721..5fa239d43a 100644
--- a/thirdparty/freetype/src/truetype/ttobjs.h
+++ b/thirdparty/freetype/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
*
* Objects manager (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -282,6 +282,8 @@ FT_BEGIN_HEADER
TT_Size_Metrics ttmetrics;
+ FT_Byte* widthp; /* glyph widths from the hdmx table */
+
FT_ULong strike_index; /* 0xFFFFFFFF to indicate invalid */
#ifdef TT_USE_BYTECODE_INTERPRETER
diff --git a/thirdparty/freetype/src/truetype/ttpload.c b/thirdparty/freetype/src/truetype/ttpload.c
index 71db75ae1f..6982c717ab 100644
--- a/thirdparty/freetype/src/truetype/ttpload.c
+++ b/thirdparty/freetype/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -498,6 +498,14 @@
}
+ FT_COMPARE_DEF( int )
+ compare_ppem( const void* a,
+ const void* b )
+ {
+ return **(FT_Byte**)a - **(FT_Byte**)b;
+ }
+
+
/**************************************************************************
*
* @Function:
@@ -574,20 +582,21 @@
goto Fail;
}
- if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) )
+ if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) )
goto Fail;
- /* XXX: We do not check if the records are sorted by ppem */
- /* and cannot use binary search later. */
for ( nn = 0; nn < num_records; nn++ )
{
if ( p + record_size > limit )
break;
-
- face->hdmx_record_sizes[nn] = p[0];
- p += record_size;
+ face->hdmx_records[nn] = p;
+ p += record_size;
}
+ /* The records must be already sorted by ppem but it does not */
+ /* hurt to make sure so that the binary search works later. */
+ ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem );
+
face->hdmx_record_count = nn;
face->hdmx_table_size = table_size;
face->hdmx_record_size = record_size;
@@ -611,7 +620,7 @@
FT_Memory memory = stream->memory;
- FT_FREE( face->hdmx_record_sizes );
+ FT_FREE( face->hdmx_records );
FT_FRAME_RELEASE( face->hdmx_table );
}
@@ -619,27 +628,34 @@
/**************************************************************************
*
* Return the advance width table for a given pixel size if it is found
- * in the font's `hdmx' table (if any).
+ * in the font's `hdmx' table (if any). The records must be sorted for
+ * the binary search to work properly.
*/
FT_LOCAL_DEF( FT_Byte* )
tt_face_get_device_metrics( TT_Face face,
FT_UInt ppem,
FT_UInt gindex )
{
- FT_UInt nn;
- FT_Byte* result = NULL;
- FT_ULong record_size = face->hdmx_record_size;
- FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 );
+ FT_UInt min = 0;
+ FT_UInt max = face->hdmx_record_count;
+ FT_UInt mid;
+ FT_Byte* result = NULL;
+
+ while ( min < max )
+ {
+ mid = ( min + max ) >> 1;
- for ( nn = 0; nn < face->hdmx_record_count; nn++ )
- if ( face->hdmx_record_sizes[nn] == ppem )
+ if ( face->hdmx_records[mid][0] > ppem )
+ max = mid;
+ else if ( face->hdmx_records[mid][0] < ppem )
+ min = mid + 1;
+ else
{
- gindex += 2;
- if ( gindex < record_size )
- result = record + nn * record_size + gindex;
+ result = face->hdmx_records[mid] + 2 + gindex;
break;
}
+ }
return result;
}
diff --git a/thirdparty/freetype/src/truetype/ttpload.h b/thirdparty/freetype/src/truetype/ttpload.h
index 84c42cdaf4..fa5d96ed35 100644
--- a/thirdparty/freetype/src/truetype/ttpload.h
+++ b/thirdparty/freetype/src/truetype/ttpload.h
@@ -4,7 +4,7 @@
*
* TrueType-specific tables loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.c b/thirdparty/freetype/src/truetype/ttsubpix.c
index c484665b95..2438d3a2a2 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.c
+++ b/thirdparty/freetype/src/truetype/ttsubpix.c
@@ -4,7 +4,7 @@
*
* TrueType Subpixel Hinting.
*
- * Copyright (C) 2010-2021 by
+ * Copyright (C) 2010-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/truetype/ttsubpix.h b/thirdparty/freetype/src/truetype/ttsubpix.h
index 762b7c98a3..181f83810c 100644
--- a/thirdparty/freetype/src/truetype/ttsubpix.h
+++ b/thirdparty/freetype/src/truetype/ttsubpix.h
@@ -4,7 +4,7 @@
*
* TrueType Subpixel Hinting.
*
- * Copyright (C) 2010-2021 by
+ * Copyright (C) 2010-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1afm.c b/thirdparty/freetype/src/type1/t1afm.c
index 4c18ed1955..6009e9ee2e 100644
--- a/thirdparty/freetype/src/type1/t1afm.c
+++ b/thirdparty/freetype/src/type1/t1afm.c
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -203,7 +203,7 @@
kp->index1 = FT_Get_Char_Index( t1_face, p[0] );
kp->index2 = FT_Get_Char_Index( t1_face, p[1] );
- kp->x = (FT_Int)FT_PEEK_SHORT_LE(p + 2);
+ kp->x = (FT_Int)FT_PEEK_SHORT_LE( p + 2 );
kp->y = 0;
kp++;
diff --git a/thirdparty/freetype/src/type1/t1afm.h b/thirdparty/freetype/src/type1/t1afm.h
index 86fe45ea3e..040ed68298 100644
--- a/thirdparty/freetype/src/type1/t1afm.h
+++ b/thirdparty/freetype/src/type1/t1afm.h
@@ -4,7 +4,7 @@
*
* AFM support for Type 1 fonts (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1driver.c b/thirdparty/freetype/src/type1/t1driver.c
index f4d7a089ae..dd31545cf6 100644
--- a/thirdparty/freetype/src/type1/t1driver.c
+++ b/thirdparty/freetype/src/type1/t1driver.c
@@ -4,7 +4,7 @@
*
* Type 1 driver interface (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1driver.h b/thirdparty/freetype/src/type1/t1driver.h
index 20a827f898..9fe1940334 100644
--- a/thirdparty/freetype/src/type1/t1driver.h
+++ b/thirdparty/freetype/src/type1/t1driver.h
@@ -4,7 +4,7 @@
*
* High-level Type 1 driver interface (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1errors.h b/thirdparty/freetype/src/type1/t1errors.h
index 18ef75452b..1b87c42f18 100644
--- a/thirdparty/freetype/src/type1/t1errors.h
+++ b/thirdparty/freetype/src/type1/t1errors.h
@@ -4,7 +4,7 @@
*
* Type 1 error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1gload.c b/thirdparty/freetype/src/type1/t1gload.c
index 86649edf3a..540231561c 100644
--- a/thirdparty/freetype/src/type1/t1gload.c
+++ b/thirdparty/freetype/src/type1/t1gload.c
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1gload.h b/thirdparty/freetype/src/type1/t1gload.h
index a924d551a9..fdb985264f 100644
--- a/thirdparty/freetype/src/type1/t1gload.h
+++ b/thirdparty/freetype/src/type1/t1gload.h
@@ -4,7 +4,7 @@
*
* Type 1 Glyph Loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1load.c b/thirdparty/freetype/src/type1/t1load.c
index bb62c79902..66bebd560f 100644
--- a/thirdparty/freetype/src/type1/t1load.c
+++ b/thirdparty/freetype/src/type1/t1load.c
@@ -4,7 +4,7 @@
*
* Type 1 font loader (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
@@ -1530,8 +1530,8 @@
/* we use a T1_Table to store our charnames */
loader->num_chars = encode->num_chars = array_size;
- if ( FT_NEW_ARRAY( encode->char_index, array_size ) ||
- FT_NEW_ARRAY( encode->char_name, array_size ) ||
+ if ( FT_QNEW_ARRAY( encode->char_index, array_size ) ||
+ FT_QNEW_ARRAY( encode->char_name, array_size ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
char_table, array_size, memory ) ) )
{
@@ -1772,7 +1772,7 @@
if ( !loader->subrs_hash )
{
- if ( FT_NEW( loader->subrs_hash ) )
+ if ( FT_QNEW( loader->subrs_hash ) )
goto Fail;
error = ft_hash_num_init( loader->subrs_hash, memory );
@@ -2057,9 +2057,9 @@
name_table->elements[n][len] = '\0';
/* record index of /.notdef */
- if ( *cur == '.' &&
+ if ( *cur == '.' &&
ft_strcmp( ".notdef",
- (const char*)(name_table->elements[n]) ) == 0 )
+ (const char*)( name_table->elements[n] ) ) == 0 )
{
notdef_index = n;
notdef_found = 1;
@@ -2331,8 +2331,8 @@
/* in valid Type 1 fonts we don't see `RD' or `-|' directly */
/* since those tokens are handled by parse_subrs and */
/* parse_charstrings */
- else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
- have_integer )
+ else if ( *cur == 'R' && cur + 6 < limit && *( cur + 1 ) == 'D' &&
+ have_integer )
{
FT_ULong s;
FT_Byte* b;
@@ -2344,8 +2344,8 @@
have_integer = 0;
}
- else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
- have_integer )
+ else if ( *cur == '-' && cur + 6 < limit && *( cur + 1 ) == '|' &&
+ have_integer )
{
FT_ULong s;
FT_Byte* b;
diff --git a/thirdparty/freetype/src/type1/t1load.h b/thirdparty/freetype/src/type1/t1load.h
index ba19adb147..a6d46eb1e4 100644
--- a/thirdparty/freetype/src/type1/t1load.h
+++ b/thirdparty/freetype/src/type1/t1load.h
@@ -4,7 +4,7 @@
*
* Type 1 font loader (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1objs.c b/thirdparty/freetype/src/type1/t1objs.c
index 50dad038fd..847ae0e64b 100644
--- a/thirdparty/freetype/src/type1/t1objs.c
+++ b/thirdparty/freetype/src/type1/t1objs.c
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1objs.h b/thirdparty/freetype/src/type1/t1objs.h
index 5f103b5066..e632fb58bd 100644
--- a/thirdparty/freetype/src/type1/t1objs.h
+++ b/thirdparty/freetype/src/type1/t1objs.h
@@ -4,7 +4,7 @@
*
* Type 1 objects manager (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1parse.c b/thirdparty/freetype/src/type1/t1parse.c
index 9f226296a9..95dc97d79a 100644
--- a/thirdparty/freetype/src/type1/t1parse.c
+++ b/thirdparty/freetype/src/type1/t1parse.c
@@ -4,7 +4,7 @@
*
* Type 1 parser (body).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1parse.h b/thirdparty/freetype/src/type1/t1parse.h
index 247ff73b2c..d9c7e3b56a 100644
--- a/thirdparty/freetype/src/type1/t1parse.h
+++ b/thirdparty/freetype/src/type1/t1parse.h
@@ -4,7 +4,7 @@
*
* Type 1 parser (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/t1tokens.h b/thirdparty/freetype/src/type1/t1tokens.h
index 13ac8ac1c7..79080d9e4d 100644
--- a/thirdparty/freetype/src/type1/t1tokens.h
+++ b/thirdparty/freetype/src/type1/t1tokens.h
@@ -4,7 +4,7 @@
*
* Type 1 tokenizer (specification).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type1/type1.c b/thirdparty/freetype/src/type1/type1.c
index 003b78cb86..6f11249288 100644
--- a/thirdparty/freetype/src/type1/type1.c
+++ b/thirdparty/freetype/src/type1/type1.c
@@ -4,7 +4,7 @@
*
* FreeType Type 1 driver component (body only).
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42drivr.c b/thirdparty/freetype/src/type42/t42drivr.c
index e74ba1deba..45d8c3821b 100644
--- a/thirdparty/freetype/src/type42/t42drivr.c
+++ b/thirdparty/freetype/src/type42/t42drivr.c
@@ -4,7 +4,7 @@
*
* High-level Type 42 driver interface (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
@@ -150,22 +150,13 @@
}
- static FT_Error
- t42_ps_get_font_private( FT_Face face,
- PS_PrivateRec* afont_private )
- {
- *afont_private = ((T42_Face)face)->type1.private_dict;
-
- return FT_Err_Ok;
- }
-
-
static const FT_Service_PsInfoRec t42_service_ps_info =
{
(PS_GetFontInfoFunc) t42_ps_get_font_info, /* ps_get_font_info */
(PS_GetFontExtraFunc) t42_ps_get_font_extra, /* ps_get_font_extra */
(PS_HasGlyphNamesFunc) t42_ps_has_glyph_names, /* ps_has_glyph_names */
- (PS_GetFontPrivateFunc)t42_ps_get_font_private, /* ps_get_font_private */
+ /* Type42 fonts don't have a Private dict */
+ (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */
/* not implemented */
(PS_GetFontValueFunc) NULL /* ps_get_font_value */
};
diff --git a/thirdparty/freetype/src/type42/t42drivr.h b/thirdparty/freetype/src/type42/t42drivr.h
index c6d8a4409e..95e1207b68 100644
--- a/thirdparty/freetype/src/type42/t42drivr.h
+++ b/thirdparty/freetype/src/type42/t42drivr.h
@@ -4,7 +4,7 @@
*
* High-level Type 42 driver interface (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42error.h b/thirdparty/freetype/src/type42/t42error.h
index 470f5189a8..b278221006 100644
--- a/thirdparty/freetype/src/type42/t42error.h
+++ b/thirdparty/freetype/src/type42/t42error.h
@@ -4,7 +4,7 @@
*
* Type 42 error codes (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42objs.c b/thirdparty/freetype/src/type42/t42objs.c
index 03955e945b..da1e0732a0 100644
--- a/thirdparty/freetype/src/type42/t42objs.c
+++ b/thirdparty/freetype/src/type42/t42objs.c
@@ -4,7 +4,7 @@
*
* Type 42 objects manager (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
@@ -44,14 +44,8 @@
parser = &loader.parser;
- if ( FT_QALLOC( face->ttf_data, 12 ) )
- goto Exit;
-
- /* while parsing the font we always update `face->ttf_size' so that */
- /* even in case of buggy data (which might lead to premature end of */
- /* scanning without causing an error) the call to `FT_Open_Face' in */
- /* `T42_Face_Init' passes the correct size */
- face->ttf_size = 12;
+ face->ttf_data = NULL;
+ face->ttf_size = 0;
error = t42_parser_init( parser,
face->root.stream,
@@ -152,6 +146,11 @@
Exit:
t42_loader_done( &loader );
+ if ( error )
+ {
+ FT_FREE( face->ttf_data );
+ face->ttf_size = 0;
+ }
return error;
}
diff --git a/thirdparty/freetype/src/type42/t42objs.h b/thirdparty/freetype/src/type42/t42objs.h
index cbd344ffbd..e677996a30 100644
--- a/thirdparty/freetype/src/type42/t42objs.h
+++ b/thirdparty/freetype/src/type42/t42objs.h
@@ -4,7 +4,7 @@
*
* Type 42 objects manager (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42parse.c b/thirdparty/freetype/src/type42/t42parse.c
index ea2c5198a9..59cc519ea6 100644
--- a/thirdparty/freetype/src/type42/t42parse.c
+++ b/thirdparty/freetype/src/type42/t42parse.c
@@ -4,7 +4,7 @@
*
* Type 42 font parser (body).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
@@ -92,7 +92,7 @@
#undef T1CODE
#define T1CODE T1_FIELD_LOCATION_BBOX
- T1_FIELD_BBOX("FontBBox", xMin, 0 )
+ T1_FIELD_BBOX( "FontBBox", xMin, 0 )
T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix, 0 )
T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding, 0 )
@@ -363,8 +363,8 @@
/* we use a T1_Table to store our charnames */
loader->num_chars = encode->num_chars = count;
- if ( FT_NEW_ARRAY( encode->char_index, count ) ||
- FT_NEW_ARRAY( encode->char_name, count ) ||
+ if ( FT_QNEW_ARRAY( encode->char_index, count ) ||
+ FT_QNEW_ARRAY( encode->char_name, count ) ||
FT_SET_ERROR( psaux->ps_table_funcs->init(
char_table, count, memory ) ) )
{
@@ -538,7 +538,8 @@
FT_Byte* limit = parser->root.limit;
FT_Error error;
FT_Int num_tables = 0;
- FT_Long count;
+ FT_Long ttf_count;
+ FT_Long ttf_reserved;
FT_ULong n, string_size, old_string_size, real_size;
FT_Byte* string_buf = NULL;
@@ -546,6 +547,9 @@
T42_Load_Status status;
+ /** There should only be one sfnts array, but free any previous. */
+ FT_FREE( face->ttf_data );
+ face->ttf_size = 0;
/* The format is */
/* */
@@ -574,7 +578,10 @@
status = BEFORE_START;
string_size = 0;
old_string_size = 0;
- count = 0;
+ ttf_count = 0;
+ ttf_reserved = 12;
+ if ( FT_QALLOC( face->ttf_data, ttf_reserved ) )
+ goto Fail;
FT_TRACE2(( "\n" ));
FT_TRACE2(( "t42_parse_sfnts:\n" ));
@@ -589,6 +596,7 @@
if ( *cur == ']' )
{
parser->root.cursor++;
+ face->ttf_size = ttf_count;
goto Exit;
}
@@ -684,7 +692,7 @@
}
FT_TRACE2(( " PS string size %5lu bytes, offset 0x%08lx (%lu)\n",
- string_size, count, count ));
+ string_size, ttf_count, ttf_count ));
/* The whole TTF is now loaded into `string_buf'. We are */
/* checking its contents while copying it to `ttf_data'. */
@@ -697,43 +705,48 @@
{
case BEFORE_START:
/* load offset table, 12 bytes */
- if ( count < 12 )
+ if ( ttf_count < 12 )
{
- face->ttf_data[count++] = string_buf[n];
+ face->ttf_data[ttf_count++] = string_buf[n];
continue;
}
else
{
- num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
- status = BEFORE_TABLE_DIR;
- face->ttf_size = 12 + 16 * num_tables;
+ FT_Long ttf_reserved_prev = ttf_reserved;
+
+
+ num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
+ status = BEFORE_TABLE_DIR;
+ ttf_reserved = 12 + 16 * num_tables;
FT_TRACE2(( " SFNT directory contains %d tables\n",
num_tables ));
- if ( (FT_Long)size < face->ttf_size )
+ if ( (FT_Long)size < ttf_reserved )
{
FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
- if ( FT_QREALLOC( face->ttf_data, 12, face->ttf_size ) )
+ if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev,
+ ttf_reserved ) )
goto Fail;
}
/* fall through */
case BEFORE_TABLE_DIR:
/* the offset table is read; read the table directory */
- if ( count < face->ttf_size )
+ if ( ttf_count < ttf_reserved )
{
- face->ttf_data[count++] = string_buf[n];
+ face->ttf_data[ttf_count++] = string_buf[n];
continue;
}
else
{
int i;
FT_ULong len;
+ FT_Long ttf_reserved_prev = ttf_reserved;
FT_TRACE2(( "\n" ));
@@ -749,7 +762,7 @@
FT_TRACE2(( " %4i 0x%08lx (%lu)\n", i, len, len ));
if ( len > size ||
- face->ttf_size > (FT_Long)( size - len ) )
+ ttf_reserved > (FT_Long)( size - len ) )
{
FT_ERROR(( "t42_parse_sfnts:"
" invalid data in sfnts array\n" ));
@@ -758,30 +771,31 @@
}
/* Pad to a 4-byte boundary length */
- face->ttf_size += (FT_Long)( ( len + 3 ) & ~3U );
+ ttf_reserved += (FT_Long)( ( len + 3 ) & ~3U );
}
+ ttf_reserved += 1;
status = OTHER_TABLES;
FT_TRACE2(( "\n" ));
- FT_TRACE2(( " allocating %ld bytes\n", face->ttf_size + 1 ));
+ FT_TRACE2(( " allocating %ld bytes\n", ttf_reserved ));
FT_TRACE2(( "\n" ));
- if ( FT_QREALLOC( face->ttf_data, 12 + 16 * num_tables,
- face->ttf_size + 1 ) )
+ if ( FT_QREALLOC( face->ttf_data, ttf_reserved_prev,
+ ttf_reserved ) )
goto Fail;
}
/* fall through */
case OTHER_TABLES:
/* all other tables are just copied */
- if ( count >= face->ttf_size )
+ if ( ttf_count >= ttf_reserved )
{
FT_ERROR(( "t42_parse_sfnts: too much binary data\n" ));
error = FT_THROW( Invalid_File_Format );
goto Fail;
}
- face->ttf_data[count++] = string_buf[n];
+ face->ttf_data[ttf_count++] = string_buf[n];
}
}
@@ -795,6 +809,11 @@
parser->root.error = error;
Exit:
+ if ( parser->root.error )
+ {
+ FT_FREE( face->ttf_data );
+ face->ttf_size = 0;
+ }
if ( allocated )
FT_FREE( string_buf );
}
@@ -989,9 +1008,9 @@
name_table->elements[n][len] = '\0';
/* record index of /.notdef */
- if ( *cur == '.' &&
+ if ( *cur == '.' &&
ft_strcmp( ".notdef",
- (const char*)(name_table->elements[n]) ) == 0 )
+ (const char*)( name_table->elements[n] ) ) == 0 )
{
notdef_index = n;
notdef_found = 1;
diff --git a/thirdparty/freetype/src/type42/t42parse.h b/thirdparty/freetype/src/type42/t42parse.h
index 0fbd2b5e0b..fa633e7f1e 100644
--- a/thirdparty/freetype/src/type42/t42parse.h
+++ b/thirdparty/freetype/src/type42/t42parse.h
@@ -4,7 +4,7 @@
*
* Type 42 font parser (specification).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/t42types.h b/thirdparty/freetype/src/type42/t42types.h
index ea2f03e893..985bdfda98 100644
--- a/thirdparty/freetype/src/type42/t42types.h
+++ b/thirdparty/freetype/src/type42/t42types.h
@@ -4,7 +4,7 @@
*
* Type 42 font data types (specification only).
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* Roberto Alameda.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/type42/type42.c b/thirdparty/freetype/src/type42/type42.c
index d8d3936bdf..ccf5d472b8 100644
--- a/thirdparty/freetype/src/type42/type42.c
+++ b/thirdparty/freetype/src/type42/type42.c
@@ -4,7 +4,7 @@
*
* FreeType Type 42 driver component.
*
- * Copyright (C) 2002-2021 by
+ * Copyright (C) 2002-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/winfonts/fnterrs.h b/thirdparty/freetype/src/winfonts/fnterrs.h
index d582a9b99c..10564e107f 100644
--- a/thirdparty/freetype/src/winfonts/fnterrs.h
+++ b/thirdparty/freetype/src/winfonts/fnterrs.h
@@ -4,7 +4,7 @@
*
* Win FNT/FON error codes (specification only).
*
- * Copyright (C) 2001-2021 by
+ * Copyright (C) 2001-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
*
* This file is part of the FreeType project, and may only be used,
diff --git a/thirdparty/freetype/src/winfonts/winfnt.c b/thirdparty/freetype/src/winfonts/winfnt.c
index b4fabad283..8afd6be6e9 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.c
+++ b/thirdparty/freetype/src/winfonts/winfnt.c
@@ -4,7 +4,7 @@
*
* FreeType font driver for Windows FNT/FON files
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
* Copyright 2003 Huw D M Davies for Codeweavers
* Copyright 2007 Dmitry Timoshkov for Codeweavers
@@ -352,6 +352,10 @@
count = FT_GET_USHORT_LE();
+ FT_TRACE2(( type_id == 0x8007U ? "RT_FONTDIR count %hu\n" :
+ type_id == 0x8008U ? "RT_FONT count %hu\n" : "",
+ count ));
+
if ( type_id == 0x8008U )
{
font_count = count;
@@ -485,7 +489,7 @@
&dir_entry1 ) )
goto Exit;
- if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
+ if ( !( dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
@@ -509,7 +513,7 @@
&dir_entry2 ) )
goto Exit;
- if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
+ if ( !( dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
diff --git a/thirdparty/freetype/src/winfonts/winfnt.h b/thirdparty/freetype/src/winfonts/winfnt.h
index a7134abd9c..7e6f5915e7 100644
--- a/thirdparty/freetype/src/winfonts/winfnt.h
+++ b/thirdparty/freetype/src/winfonts/winfnt.h
@@ -4,7 +4,7 @@
*
* FreeType font driver for Windows FNT/FON files
*
- * Copyright (C) 1996-2021 by
+ * Copyright (C) 1996-2022 by
* David Turner, Robert Wilhelm, and Werner Lemberg.
* Copyright 2007 Dmitry Timoshkov for Codeweavers
*
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
new file mode 100644
index 0000000000..e52a617c86
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/Coverage.hh
@@ -0,0 +1,338 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGE_HH
+#define OT_LAYOUT_COMMON_COVERAGE_HH
+
+#include "../types.hh"
+#include "CoverageFormat1.hh"
+#include "CoverageFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template<typename Iterator>
+static inline void Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it);
+
+struct Coverage
+{
+
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CoverageFormat1_3<SmallTypes> format1;
+ CoverageFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ CoverageFormat1_3<MediumTypes>format3;
+ CoverageFormat2_4<MediumTypes>format4;
+#endif
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format)
+ {
+ case 1: return_trace (u.format1.sanitize (c));
+ case 2: return_trace (u.format2.sanitize (c));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
+ default:return_trace (true);
+ }
+ }
+
+ /* Has interface. */
+ static constexpr unsigned SENTINEL = NOT_COVERED;
+ typedef unsigned int value_t;
+ value_t operator [] (hb_codepoint_t k) const { return get (k); }
+ bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+ /* Predicate. */
+ bool operator () (hb_codepoint_t k) const { return has (k); }
+
+ unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_coverage (glyph_id);
+ case 2: return u.format2.get_coverage (glyph_id);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_coverage (glyph_id);
+ case 4: return u.format4.get_coverage (glyph_id);
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ unsigned get_population () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.get_population ();
+ case 2: return u.format2.get_population ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_population ();
+ case 4: return u.format4.get_population ();
+#endif
+ default:return NOT_COVERED;
+ }
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ unsigned count = 0;
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ count++;
+ }
+ u.format = count <= num_ranges * 3 ? 1 : 2;
+
+#ifndef HB_NO_BORING_EXPANSION
+ if (count && last > 0xFFFFu)
+ u.format += 2;
+#endif
+
+ switch (u.format)
+ {
+ case 1: return_trace (u.format1.serialize (c, glyphs));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.serialize (c, glyphs));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
+ default:return_trace (false);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto it =
+ + iter ()
+ | hb_filter (c->plan->glyph_map_gsub)
+ | hb_map_retains_sorting (c->plan->glyph_map_gsub)
+ ;
+
+ // Cache the iterator result as it will be iterated multiple times
+ // by the serialize code below.
+ hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+ Coverage_serialize (c->serializer, glyphs.iter ());
+ return_trace (bool (glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects (glyphs);
+ case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
+ default:return false;
+ }
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersects_coverage (glyphs, index);
+ case 2: return u.format2.intersects_coverage (glyphs, index);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersects_coverage (glyphs, index);
+ case 4: return u.format4.intersects_coverage (glyphs, index);
+#endif
+ default:return false;
+ }
+ }
+
+ /* Might return false if array looks unsorted.
+ * Used for faster rejection of corrupt data. */
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.collect_coverage (glyphs);
+ case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
+ default:return false;
+ }
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.intersect_set (glyphs, intersect_glyphs);
+ case 2: return u.format2.intersect_set (glyphs, intersect_glyphs);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.intersect_set (glyphs, intersect_glyphs);
+ case 4: return u.format4.intersect_set (glyphs, intersect_glyphs);
+#endif
+ default:return ;
+ }
+ }
+
+ struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
+ {
+ static constexpr bool is_sorted_iterator = true;
+ iter_t (const Coverage &c_ = Null (Coverage))
+ {
+ memset (this, 0, sizeof (*this));
+ format = c_.u.format;
+ switch (format)
+ {
+ case 1: u.format1.init (c_.u.format1); return;
+ case 2: u.format2.init (c_.u.format2); return;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: u.format3.init (c_.u.format3); return;
+ case 4: u.format4.init (c_.u.format4); return;
+#endif
+ default: return;
+ }
+ }
+ bool __more__ () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.__more__ ();
+ case 2: return u.format2.__more__ ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.__more__ ();
+ case 4: return u.format4.__more__ ();
+#endif
+ default:return false;
+ }
+ }
+ void __next__ ()
+ {
+ switch (format)
+ {
+ case 1: u.format1.__next__ (); break;
+ case 2: u.format2.__next__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: u.format3.__next__ (); break;
+ case 4: u.format4.__next__ (); break;
+#endif
+ default: break;
+ }
+ }
+ typedef hb_codepoint_t __item_t__;
+ __item_t__ __item__ () const { return get_glyph (); }
+
+ hb_codepoint_t get_glyph () const
+ {
+ switch (format)
+ {
+ case 1: return u.format1.get_glyph ();
+ case 2: return u.format2.get_glyph ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3.get_glyph ();
+ case 4: return u.format4.get_glyph ();
+#endif
+ default:return 0;
+ }
+ }
+ bool operator != (const iter_t& o) const
+ {
+ if (unlikely (format != o.format)) return true;
+ switch (format)
+ {
+ case 1: return u.format1 != o.u.format1;
+ case 2: return u.format2 != o.u.format2;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return u.format3 != o.u.format3;
+ case 4: return u.format4 != o.u.format4;
+#endif
+ default:return false;
+ }
+ }
+ iter_t __end__ () const
+ {
+ iter_t it = {};
+ it.format = format;
+ switch (format)
+ {
+ case 1: it.u.format1 = u.format1.__end__ (); break;
+ case 2: it.u.format2 = u.format2.__end__ (); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: it.u.format3 = u.format3.__end__ (); break;
+ case 4: it.u.format4 = u.format4.__end__ (); break;
+#endif
+ default: break;
+ }
+ return it;
+ }
+
+ private:
+ unsigned int format;
+ union {
+#ifndef HB_NO_BORING_EXPANSION
+ CoverageFormat2_4<MediumTypes>::iter_t format4; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<MediumTypes>::iter_t format3;
+#endif
+ CoverageFormat2_4<SmallTypes>::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
+ CoverageFormat1_3<SmallTypes>::iter_t format1;
+ } u;
+ };
+ iter_t iter () const { return iter_t (*this); }
+};
+
+template<typename Iterator>
+static inline void
+Coverage_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<Coverage> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGE_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
new file mode 100644
index 0000000000..886babd2d1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat1.hh
@@ -0,0 +1,126 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+#define NOT_COVERED ((unsigned int) -1)
+
+template <typename Types>
+struct CoverageFormat1_3
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 1 */
+ SortedArray16Of<typename Types::HBGlyphID>
+ glyphArray; /* Array of GlyphIDs--in numerical order */
+ public:
+ DEFINE_SIZE_ARRAY (4, glyphArray);
+
+ private:
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (glyphArray.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ unsigned int i;
+ glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
+ return i;
+ }
+
+ unsigned get_population () const
+ {
+ return glyphArray.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (glyphArray.serialize (c, glyphs));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ /* TODO Speed up, using hb_set_next() and bsearch()? */
+ for (const auto& g : glyphArray.as_array ())
+ if (glyphs->has (g))
+ return true;
+ return false;
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ { return glyphs->has (glyphArray[index]); }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ unsigned count = glyphArray.len;
+ for (unsigned i = 0; i < count; i++)
+ if (glyphs.has (glyphArray[i]))
+ intersect_glyphs << glyphArray[i];
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_sorted_array (glyphArray.as_array ()); }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const struct CoverageFormat1_3 &c_) { c = &c_; i = 0; }
+ bool __more__ () const { return i < c->glyphArray.len; }
+ void __next__ () { i++; }
+ hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i; }
+ iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
+
+ private:
+ const struct CoverageFormat1_3 *c;
+ unsigned int i;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
new file mode 100644
index 0000000000..4ddb2a73e4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/CoverageFormat2.hh
@@ -0,0 +1,233 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+#define OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
+
+#include "RangeRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct CoverageFormat2_4
+{
+ friend struct Coverage;
+
+ protected:
+ HBUINT16 coverageFormat; /* Format identifier--format = 2 */
+ SortedArray16Of<RangeRecord<Types>>
+ rangeRecord; /* Array of glyph ranges--ordered by
+ * Start GlyphID. rangeCount entries
+ * long */
+ public:
+ DEFINE_SIZE_ARRAY (4, rangeRecord);
+
+ private:
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (rangeRecord.sanitize (c));
+ }
+
+ unsigned int get_coverage (hb_codepoint_t glyph_id) const
+ {
+ const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
+ return likely (range.first <= range.last)
+ ? (unsigned int) range.value + (glyph_id - range.first)
+ : NOT_COVERED;
+ }
+
+ unsigned get_population () const
+ {
+ typename Types::large_int ret = 0;
+ for (const auto &r : rangeRecord)
+ ret += r.get_population ();
+ return ret > UINT_MAX ? UINT_MAX : (unsigned) ret;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c, Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+
+ /* TODO(iter) Write more efficiently? */
+
+ unsigned num_ranges = 0;
+ hb_codepoint_t last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ num_ranges++;
+ last = g;
+ }
+
+ if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+ if (!num_ranges) return_trace (true);
+
+ unsigned count = 0;
+ unsigned range = (unsigned) -1;
+ last = (hb_codepoint_t) -2;
+ for (auto g: glyphs)
+ {
+ if (last + 1 != g)
+ {
+ range++;
+ rangeRecord[range].first = g;
+ rangeRecord[range].value = count;
+ }
+ rangeRecord[range].last = g;
+ last = g;
+ count++;
+ }
+
+ return_trace (true);
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return hb_any (+ hb_iter (rangeRecord)
+ | hb_map ([glyphs] (const RangeRecord<Types> &range) { return range.intersects (*glyphs); }));
+ }
+ bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
+ {
+ auto cmp = [] (const void *pk, const void *pr) -> int
+ {
+ unsigned index = * (const unsigned *) pk;
+ const RangeRecord<Types> &range = * (const RangeRecord<Types> *) pr;
+ if (index < range.value) return -1;
+ if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
+ return 0;
+ };
+
+ auto arr = rangeRecord.as_array ();
+ unsigned idx;
+ if (hb_bsearch_impl (&idx, index,
+ arr.arrayZ, arr.length, sizeof (arr[0]),
+ (int (*)(const void *_key, const void *_item)) cmp))
+ return arr.arrayZ[idx].intersects (*glyphs);
+ return false;
+ }
+
+ template <typename IterableOut,
+ hb_requires (hb_is_sink_of (IterableOut, hb_codepoint_t))>
+ void intersect_set (const hb_set_t &glyphs, IterableOut &intersect_glyphs) const
+ {
+ for (const auto& range : rangeRecord)
+ {
+ hb_codepoint_t last = range.last;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs.next (&g) && g <= last;)
+ intersect_glyphs << g;
+ }
+ }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ {
+ for (const auto& range: rangeRecord)
+ if (unlikely (!range.collect_coverage (glyphs)))
+ return false;
+ return true;
+ }
+
+ public:
+ /* Older compilers need this to be public. */
+ struct iter_t
+ {
+ void init (const CoverageFormat2_4 &c_)
+ {
+ c = &c_;
+ coverage = 0;
+ i = 0;
+ j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
+ if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
+ {
+ /* Broken table. Skip. */
+ i = c->rangeRecord.len;
+ j = 0;
+ }
+ }
+ bool __more__ () const { return i < c->rangeRecord.len; }
+ void __next__ ()
+ {
+ if (j >= c->rangeRecord[i].last)
+ {
+ i++;
+ if (__more__ ())
+ {
+ unsigned int old = coverage;
+ j = c->rangeRecord[i].first;
+ coverage = c->rangeRecord[i].value;
+ if (unlikely (coverage != old + 1))
+ {
+ /* Broken table. Skip. Important to avoid DoS.
+ * Also, our callers depend on coverage being
+ * consecutive and monotonically increasing,
+ * ie. iota(). */
+ i = c->rangeRecord.len;
+ j = 0;
+ return;
+ }
+ }
+ else
+ j = 0;
+ return;
+ }
+ coverage++;
+ j++;
+ }
+ hb_codepoint_t get_glyph () const { return j; }
+ bool operator != (const iter_t& o) const
+ { return i != o.i || j != o.j; }
+ iter_t __end__ () const
+ {
+ iter_t it;
+ it.init (*c);
+ it.i = c->rangeRecord.len;
+ it.j = 0;
+ return it;
+ }
+
+ private:
+ const struct CoverageFormat2_4 *c;
+ unsigned int i, coverage;
+ hb_codepoint_t j;
+ };
+ private:
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh
new file mode 100644
index 0000000000..a62629fad3
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/Common/RangeRecord.hh
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
+#define OT_LAYOUT_COMMON_RANGERECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace Common {
+
+template <typename Types>
+struct RangeRecord
+{
+ typename Types::HBGlyphID first; /* First GlyphID in the range */
+ typename Types::HBGlyphID last; /* Last GlyphID in the range */
+ HBUINT16 value; /* Value */
+
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ int cmp (hb_codepoint_t g) const
+ { return g < first ? -1 : g <= last ? 0 : +1; }
+
+ unsigned get_population () const
+ {
+ if (unlikely (last < first)) return 0;
+ return (last - first + 1);
+ }
+
+ bool intersects (const hb_set_t &glyphs) const
+ { return glyphs.intersects (first, last); }
+
+ template <typename set_t>
+ bool collect_coverage (set_t *glyphs) const
+ { return glyphs->add_range (first, last); }
+};
+
+}
+}
+}
+
+// TODO(garretrieger): This was previously implemented using
+// DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (OT, RangeRecord, 9);
+// but that only works when there is only a single namespace level.
+// The macro should probably be fixed so it can work in this situation.
+extern HB_INTERNAL const unsigned char _hb_Null_OT_RangeRecord[9];
+template <typename Spec>
+struct Null<OT::Layout::Common::RangeRecord<Spec>> {
+ static OT::Layout::Common::RangeRecord<Spec> const & get_null () {
+ return *reinterpret_cast<const OT::Layout::Common::RangeRecord<Spec> *> (_hb_Null_OT_RangeRecord);
+ }
+};
+
+
+#endif // #ifndef OT_LAYOUT_COMMON_RANGERECORD_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
new file mode 100644
index 0000000000..bfe6b36afd
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Anchor.hh
@@ -0,0 +1,84 @@
+#ifndef OT_LAYOUT_GPOS_ANCHOR_HH
+#define OT_LAYOUT_GPOS_ANCHOR_HH
+
+#include "AnchorFormat1.hh"
+#include "AnchorFormat2.hh"
+#include "AnchorFormat3.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct Anchor
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AnchorFormat1 format1;
+ AnchorFormat2 format2;
+ AnchorFormat3 format3;
+ } u;
+ public:
+ DEFINE_SIZE_UNION (2, format);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!u.format.sanitize (c)) return_trace (false);
+ switch (u.format) {
+ case 1: return_trace (u.format1.sanitize (c));
+ case 2: return_trace (u.format2.sanitize (c));
+ case 3: return_trace (u.format3.sanitize (c));
+ default:return_trace (true);
+ }
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ *x = *y = 0;
+ switch (u.format) {
+ case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
+ case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
+ case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
+ default: return;
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ switch (u.format) {
+ case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ case 2:
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ // AnchorFormat 2 just containins extra hinting information, so
+ // if hints are being dropped convert to format 1.
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
+ }
+ return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
+ case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
+ c->plan->layout_variation_idx_map))));
+ default:return_trace (false);
+ }
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ switch (u.format) {
+ case 1: case 2:
+ return;
+ case 3:
+ u.format3.collect_variation_indices (c);
+ return;
+ default: return;
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHOR_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh
new file mode 100644
index 0000000000..738cc31bbf
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat1.hh
@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ public:
+ DEFINE_SIZE_STATIC (6);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat1* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ AnchorFormat1* out = c->embed<AnchorFormat1> (this);
+ if (!out) return_trace (out);
+ out->format = 1;
+ return_trace (out);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh
new file mode 100644
index 0000000000..70b4d19f53
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat2.hh
@@ -0,0 +1,58 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat2
+{
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ HBUINT16 anchorPoint; /* Index to glyph contour point */
+ public:
+ DEFINE_SIZE_STATIC (8);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+
+#ifdef HB_NO_HINTING
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+ return;
+#endif
+
+ unsigned int x_ppem = font->x_ppem;
+ unsigned int y_ppem = font->y_ppem;
+ hb_position_t cx = 0, cy = 0;
+ bool ret;
+
+ ret = (x_ppem || y_ppem) &&
+ font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
+ *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
+ *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
+ }
+
+ AnchorFormat2* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed<AnchorFormat2> (this));
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh
new file mode 100644
index 0000000000..d77b4699be
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorFormat3.hh
@@ -0,0 +1,70 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+#define OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorFormat3
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 3 */
+ FWORD xCoordinate; /* Horizontal value--in design units */
+ FWORD yCoordinate; /* Vertical value--in design units */
+ Offset16To<Device>
+ xDeviceTable; /* Offset to Device table for X
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ Offset16To<Device>
+ yDeviceTable; /* Offset to Device table for Y
+ * coordinate-- from beginning of
+ * Anchor table (may be NULL) */
+ public:
+ DEFINE_SIZE_STATIC (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
+ }
+
+ void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
+ float *x, float *y) const
+ {
+ hb_font_t *font = c->font;
+ *x = font->em_fscale_x (xCoordinate);
+ *y = font->em_fscale_y (yCoordinate);
+
+ if (font->x_ppem || font->num_coords)
+ *x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
+ if (font->y_ppem || font->num_coords)
+ *y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
+ }
+
+ AnchorFormat3* copy (hb_serialize_context_t *c,
+ const hb_map_t *layout_variation_idx_map) const
+ {
+ TRACE_SERIALIZE (this);
+ if (!layout_variation_idx_map) return_trace (nullptr);
+
+ auto *out = c->embed<AnchorFormat3> (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
+ out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
+ (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_ANCHORFORMAT3_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh
new file mode 100644
index 0000000000..c442efa1ea
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/AnchorMatrix.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+#define OT_LAYOUT_GPOS_ANCHORMATRIX_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct AnchorMatrix
+{
+ HBUINT16 rows; /* Number of rows */
+ UnsizedArrayOf<Offset16To<Anchor>>
+ matrixZ; /* Matrix of offsets to Anchor tables--
+ * from beginning of AnchorMatrix table */
+ public:
+ DEFINE_SIZE_ARRAY (2, matrixZ);
+
+ bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
+ {
+ TRACE_SANITIZE (this);
+ if (!c->check_struct (this)) return_trace (false);
+ if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
+ unsigned int count = rows * cols;
+ if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
+ for (unsigned int i = 0; i < count; i++)
+ if (!matrixZ[i].sanitize (c, this)) return_trace (false);
+ return_trace (true);
+ }
+
+ const Anchor& get_anchor (unsigned int row, unsigned int col,
+ unsigned int cols, bool *found) const
+ {
+ *found = false;
+ if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
+ *found = !matrixZ[row * cols + col].is_null ();
+ return this+matrixZ[row * cols + col];
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ Iterator index_iter) const
+ {
+ for (unsigned i : index_iter)
+ (this+matrixZ[i]).collect_variation_indices (c);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ unsigned num_rows,
+ Iterator index_iter) const
+ {
+ TRACE_SUBSET (this);
+
+ auto *out = c->serializer->start_embed (this);
+
+ if (!index_iter) return_trace (false);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ out->rows = num_rows;
+ for (const unsigned i : index_iter)
+ {
+ auto *offset = c->serializer->embed (matrixZ[i]);
+ if (!offset) return_trace (false);
+ offset->serialize_subset (c, matrixZ[i], this);
+ }
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_ANCHORMATRIX_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh
new file mode 100644
index 0000000000..d551ac2a2b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ChainContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ChainContextPos : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CHAINCONTEXTPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh
new file mode 100644
index 0000000000..e16c06729d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/Common.hh
@@ -0,0 +1,32 @@
+#ifndef OT_LAYOUT_GPOS_COMMON_HH
+#define OT_LAYOUT_GPOS_COMMON_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+enum attach_type_t {
+ ATTACH_TYPE_NONE = 0X00,
+
+ /* Each attachment should be either a mark or a cursive; can't be both. */
+ ATTACH_TYPE_MARK = 0X01,
+ ATTACH_TYPE_CURSIVE = 0X02,
+};
+
+/* buffer **position** var allocations */
+#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
+#define attach_type() var.u8[2] /* attachment type */
+/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
+
+template<typename Iterator, typename SrcLookup>
+static void SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_map_t *layout_variation_idx_map);
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_COMMON_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh
new file mode 100644
index 0000000000..2a01eaa3a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ContextPos.hh
@@ -0,0 +1,14 @@
+#ifndef OT_LAYOUT_GPOS_CONTEXTPOS_HH
+#define OT_LAYOUT_GPOS_CONTEXTPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ContextPos : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CONTEXTPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh
new file mode 100644
index 0000000000..c105cfb091
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePos.hh
@@ -0,0 +1,35 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOS_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOS_HH
+
+#include "CursivePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct CursivePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ CursivePosFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh
new file mode 100644
index 0000000000..7f58fac8b8
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/CursivePosFormat1.hh
@@ -0,0 +1,301 @@
+#ifndef OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH
+
+#include "Anchor.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct EntryExitRecord
+{
+ friend struct CursivePosFormat1;
+
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+entryAnchor).collect_variation_indices (c);
+ (src_base+exitAnchor).collect_variation_indices (c);
+ }
+
+ EntryExitRecord* subset (hb_subset_context_t *c,
+ const void *src_base) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
+ out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
+ return_trace (out);
+ }
+
+ protected:
+ Offset16To<Anchor>
+ entryAnchor; /* Offset to EntryAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ Offset16To<Anchor>
+ exitAnchor; /* Offset to ExitAnchor table--from
+ * beginning of CursivePos
+ * subtable--may be NULL */
+ public:
+ DEFINE_SIZE_STATIC (4);
+};
+
+static void
+reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) {
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ /* Stop if we see new parent in the chain. */
+ if (j == new_parent)
+ return;
+
+ reverse_cursive_minor_offset (pos, j, direction, new_parent);
+
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[j].y_offset = -pos[i].y_offset;
+ else
+ pos[j].x_offset = -pos[i].x_offset;
+
+ pos[j].attach_chain() = -chain;
+ pos[j].attach_type() = type;
+}
+
+
+struct CursivePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ Array16Of<EntryExitRecord>
+ entryExitRecord; /* Array of EntryExit records--in
+ * Coverage Index order */
+ public:
+ DEFINE_SIZE_ARRAY (6, entryExitRecord);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+
+ const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
+ if (!this_record.entryAnchor) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
+ if (!prev_record.exitAnchor)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int i = skippy_iter.idx;
+ unsigned int j = buffer->idx;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attaching glyph at %d to glyph at %d",
+ i, j);
+ }
+
+ buffer->unsafe_to_break (i, j + 1);
+ float entry_x, entry_y, exit_x, exit_y;
+ (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
+ (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
+
+ hb_glyph_position_t *pos = buffer->pos;
+
+ hb_position_t d;
+ /* Main-direction adjustment */
+ switch (c->direction) {
+ case HB_DIRECTION_LTR:
+ pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
+
+ d = roundf (entry_x) + pos[j].x_offset;
+ pos[j].x_advance -= d;
+ pos[j].x_offset -= d;
+ break;
+ case HB_DIRECTION_RTL:
+ d = roundf (exit_x) + pos[i].x_offset;
+ pos[i].x_advance -= d;
+ pos[i].x_offset -= d;
+
+ pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
+ break;
+ case HB_DIRECTION_TTB:
+ pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
+
+ d = roundf (entry_y) + pos[j].y_offset;
+ pos[j].y_advance -= d;
+ pos[j].y_offset -= d;
+ break;
+ case HB_DIRECTION_BTT:
+ d = roundf (exit_y) + pos[i].y_offset;
+ pos[i].y_advance -= d;
+ pos[i].y_offset -= d;
+
+ pos[j].y_advance = roundf (entry_y);
+ break;
+ case HB_DIRECTION_INVALID:
+ default:
+ break;
+ }
+
+ /* Cross-direction adjustment */
+
+ /* We attach child to parent (think graph theory and rooted trees whereas
+ * the root stays on baseline and each node aligns itself against its
+ * parent.
+ *
+ * Optimize things for the case of RightToLeft, as that's most common in
+ * Arabic. */
+ unsigned int child = i;
+ unsigned int parent = j;
+ hb_position_t x_offset = entry_x - exit_x;
+ hb_position_t y_offset = entry_y - exit_y;
+ if (!(c->lookup_props & LookupFlag::RightToLeft))
+ {
+ unsigned int k = child;
+ child = parent;
+ parent = k;
+ x_offset = -x_offset;
+ y_offset = -y_offset;
+ }
+
+ /* If child was already connected to someone else, walk through its old
+ * chain and reverse the link direction, such that the whole tree of its
+ * previous connection now attaches to new parent. Watch out for case
+ * where new parent is on the path from old chain...
+ */
+ reverse_cursive_minor_offset (pos, child, c->direction, parent);
+
+ pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[child].attach_chain() = (int) parent - (int) child;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[child].y_offset = y_offset;
+ else
+ pos[child].x_offset = x_offset;
+
+ /* If parent was attached to child, separate them.
+ * https://github.com/harfbuzz/harfbuzz/issues/2469
+ */
+ if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
+ {
+ pos[parent].attach_chain() = 0;
+ if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
+ pos[parent].y_offset = 0;
+ else
+ pos[parent].x_offset = 0;
+ }
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "cursive attached glyph at %d to glyph at %d",
+ i, j);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_subset_context_t *c,
+ Iterator it,
+ const void *src_base)
+ {
+ if (unlikely (!c->serializer->extend_min ((*this)))) return;
+ this->format = 1;
+ this->entryExitRecord.len = it.len ();
+
+ for (const EntryExitRecord& entry_record : + it
+ | hb_map (hb_second))
+ entry_record.subset (c, src_base);
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c->serializer, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto it =
+ + hb_zip (this+coverage, entryExitRecord)
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
+ { return hb_pair (glyph_map[p.first], p.second);})
+ ;
+
+ bool ret = bool (it);
+ out->serialize (c, it, this);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_CURSIVEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh
new file mode 100644
index 0000000000..d1808adab4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ExtensionPos.hh
@@ -0,0 +1,17 @@
+#ifndef OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+#define OT_LAYOUT_GPOS_EXTENSIONPOS_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct ExtensionPos : Extension<ExtensionPos>
+{
+ typedef struct PosLookupSubTable SubTable;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_EXTENSIONPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
new file mode 100644
index 0000000000..72829377a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/GPOS.hh
@@ -0,0 +1,171 @@
+#ifndef OT_LAYOUT_GPOS_GPOS_HH
+#define OT_LAYOUT_GPOS_GPOS_HH
+
+#include "../../../hb-ot-layout-common.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "PosLookup.hh"
+
+namespace OT {
+
+using Layout::GPOS_impl::PosLookup;
+
+namespace Layout {
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level = HB_MAX_NESTING_LEVEL);
+
+/*
+ * GPOS -- Glyph Positioning
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
+ */
+
+struct GPOS : GSUBGPOS
+{
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
+
+ using Lookup = PosLookup;
+
+ const PosLookup& get_lookup (unsigned int i) const
+ { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
+ static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
+ return GSUBGPOS::subset<PosLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (GSUBGPOS::sanitize<PosLookup> (c));
+ }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
+ {
+ if (!c->gpos_lookups->has (i)) continue;
+ const PosLookup &l = get_lookup (i);
+ l.dispatch (c);
+ }
+ }
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
+};
+
+
+static void
+propagate_attachment_offsets (hb_glyph_position_t *pos,
+ unsigned int len,
+ unsigned int i,
+ hb_direction_t direction,
+ unsigned nesting_level)
+{
+ /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
+ * offset of glyph they are attached to. */
+ int chain = pos[i].attach_chain(), type = pos[i].attach_type();
+ if (likely (!chain))
+ return;
+
+ pos[i].attach_chain() = 0;
+
+ unsigned int j = (int) i + chain;
+
+ if (unlikely (j >= len))
+ return;
+
+ if (unlikely (!nesting_level))
+ return;
+
+ propagate_attachment_offsets (pos, len, j, direction, nesting_level - 1);
+
+ assert (!!(type & GPOS_impl::ATTACH_TYPE_MARK) ^ !!(type & GPOS_impl::ATTACH_TYPE_CURSIVE));
+
+ if (type & GPOS_impl::ATTACH_TYPE_CURSIVE)
+ {
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ pos[i].y_offset += pos[j].y_offset;
+ else
+ pos[i].x_offset += pos[j].x_offset;
+ }
+ else /*if (type & GPOS_impl::ATTACH_TYPE_MARK)*/
+ {
+ pos[i].x_offset += pos[j].x_offset;
+ pos[i].y_offset += pos[j].y_offset;
+
+ assert (j < i);
+ if (HB_DIRECTION_IS_FORWARD (direction))
+ for (unsigned int k = j; k < i; k++) {
+ pos[i].x_offset -= pos[k].x_advance;
+ pos[i].y_offset -= pos[k].y_advance;
+ }
+ else
+ for (unsigned int k = j + 1; k < i + 1; k++) {
+ pos[i].x_offset += pos[k].x_advance;
+ pos[i].y_offset += pos[k].y_advance;
+ }
+ }
+}
+
+void
+GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
+}
+
+void
+GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
+{
+ //_hb_buffer_assert_gsubgpos_vars (buffer);
+}
+
+void
+GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
+{
+ _hb_buffer_assert_gsubgpos_vars (buffer);
+
+ unsigned int len;
+ hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
+ hb_direction_t direction = buffer->props.direction;
+
+ /* Handle attachments */
+ if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
+ for (unsigned i = 0; i < len; i++)
+ propagate_attachment_offsets (pos, len, i, direction);
+
+ if (unlikely (font->slant))
+ {
+ for (unsigned i = 0; i < len; i++)
+ if (unlikely (pos[i].y_offset))
+ pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
+ }
+}
+
+}
+
+struct GPOS_accelerator_t : Layout::GPOS::accelerator_t {
+ GPOS_accelerator_t (hb_face_t *face) : Layout::GPOS::accelerator_t (face) {}
+};
+
+}
+
+#endif /* OT_LAYOUT_GPOS_GPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh
new file mode 100644
index 0000000000..a2d807cc32
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/LigatureArray.hh
@@ -0,0 +1,56 @@
+#ifndef OT_LAYOUT_GPOS_LIGATUREARRAY_HH
+#define OT_LAYOUT_GPOS_LIGATUREARRAY_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+typedef AnchorMatrix LigatureAttach; /* component-major--
+ * in order of writing direction--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
+struct LigatureArray : List16OfOffset16To<LigatureAttach>
+{
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ unsigned class_count,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ for (const auto _ : + hb_zip (coverage, *this)
+ | hb_filter (glyphset, hb_first))
+ {
+ auto *matrix = out->serialize_append (c->serializer);
+ if (unlikely (!matrix)) return_trace (false);
+
+ const LigatureAttach& src = (this + _.second);
+ auto indexes =
+ + hb_range (src.rows * class_count)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
+ ;
+ matrix->serialize_subset (c,
+ _.second,
+ this,
+ src.rows,
+ indexes);
+ }
+ return_trace (this->len);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_LIGATUREARRAY_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
new file mode 100644
index 0000000000..cb5e8b2689
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkArray.hh
@@ -0,0 +1,128 @@
+#ifndef OT_LAYOUT_GPOS_MARKARRAY_HH
+#define OT_LAYOUT_GPOS_MARKARRAY_HH
+
+#include "AnchorMatrix.hh"
+#include "MarkRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
+{
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (Array16Of<MarkRecord>::sanitize (c, this));
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ unsigned int mark_index, unsigned int glyph_index,
+ const AnchorMatrix &anchors, unsigned int class_count,
+ unsigned int glyph_pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
+ unsigned int mark_class = record.klass;
+
+ const Anchor& mark_anchor = this + record.markAnchor;
+ bool found;
+ const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
+ /* If this subtable doesn't have an anchor for this base and this class,
+ * return false such that the subsequent subtables have a chance at it. */
+ if (unlikely (!found)) return_trace (false);
+
+ float mark_x, mark_y, base_x, base_y;
+
+ buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
+ mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
+ glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attaching mark glyph at %d to glyph at %d",
+ c->buffer->idx, glyph_pos);
+ }
+
+ hb_glyph_position_t &o = buffer->cur_pos();
+ o.x_offset = roundf (base_x - mark_x);
+ o.y_offset = roundf (base_y - mark_y);
+ o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "attached mark glyph at %d to glyph at %d",
+ c->buffer->idx, glyph_pos);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool subset (hb_subset_context_t *c,
+ Iterator coverage,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto* out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ auto mark_iter =
+ + hb_zip (coverage, this->iter ())
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ unsigned new_length = 0;
+ for (const auto& mark_record : mark_iter) {
+ if (unlikely (!mark_record.subset (c, this, klass_mapping)))
+ return_trace (false);
+ new_length++;
+ }
+
+ if (unlikely (!c->serializer->check_assign (out->len, new_length,
+ HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
+ return_trace (false);
+
+ return_trace (true);
+ }
+};
+
+HB_INTERNAL inline
+void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
+ const MarkArray &mark_array,
+ const hb_set_t &glyphset,
+ hb_map_t* klass_mapping /* INOUT */)
+{
+ hb_set_t orig_classes;
+
+ + hb_zip (mark_coverage, mark_array)
+ | hb_filter (glyphset, hb_first)
+ | hb_map (hb_second)
+ | hb_map (&MarkRecord::get_class)
+ | hb_sink (orig_classes)
+ ;
+
+ unsigned idx = 0;
+ for (auto klass : orig_classes.iter ())
+ {
+ if (klass_mapping->has (klass)) continue;
+ klass_mapping->set (klass, idx);
+ idx++;
+ }
+}
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKARRAY_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
new file mode 100644
index 0000000000..c99b6b2e4b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePos.hh
@@ -0,0 +1,41 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOS_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOS_HH
+
+#include "MarkBasePosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkBasePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkBasePosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkBasePosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
new file mode 100644
index 0000000000..ebb8c31c67
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkBasePosFormat1.hh
@@ -0,0 +1,219 @@
+#ifndef OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH
+
+#include "MarkArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix BaseArray; /* base-major--
+ * in order of BaseCoverage Index--,
+ * mark-minor--
+ * ordered by class--zero-based. */
+
+template <typename Types>
+struct MarkBasePosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to MarkCoverage table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<Coverage>
+ baseCoverage; /* Offset to BaseCoverage table--from
+ * beginning of MarkBasePos subtable */
+ HBUINT16 classCount; /* Number of classes defined for marks */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkBasePos subtable */
+ typename Types::template OffsetTo<BaseArray>
+ baseArray; /* Offset to BaseArray table--from
+ * beginning of MarkBasePos subtable */
+
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ baseCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ baseArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+baseCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : base_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+ (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return_trace (false);
+
+ /* Now we search backwards for a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
+ do {
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* We only want to attach to the first of a MultipleSubst sequence.
+ * https://github.com/harfbuzz/harfbuzz/issues/740
+ * Reject others...
+ * ...but stop if we find a mark in the MultipleSubst sequence:
+ * https://github.com/harfbuzz/harfbuzz/issues/1020 */
+ if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
+ 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
+ (skippy_iter.idx == 0 ||
+ _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
+ !_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
+ _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
+ ))
+ break;
+ skippy_iter.reject ();
+ } while (true);
+
+ /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
+ //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+
+ unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
+ if (base_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ unsigned basecount = (this+baseArray).rows;
+ auto base_iter =
+ + hb_zip (this+baseCoverage, hb_range (basecount))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + base_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> base_indexes;
+ for (const unsigned row : + base_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (base_indexes)
+ ;
+ }
+
+ out->baseArray.serialize_subset (c, baseArray, this,
+ base_iter.len (),
+ base_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKBASEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
new file mode 100644
index 0000000000..8a4de9ffaa
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPos.hh
@@ -0,0 +1,41 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOS_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOS_HH
+
+#include "MarkLigPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkLigPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkLigPosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkLigPosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
new file mode 100644
index 0000000000..1a8021237e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkLigPosFormat1.hh
@@ -0,0 +1,206 @@
+#ifndef OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH
+
+#include "LigatureArray.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct MarkLigPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ markCoverage; /* Offset to Mark Coverage table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<Coverage>
+ ligatureCoverage; /* Offset to Ligature Coverage
+ * table--from beginning of MarkLigPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ markArray; /* Offset to MarkArray table--from
+ * beginning of MarkLigPos subtable */
+ typename Types::template OffsetTo<LigatureArray>
+ ligatureArray; /* Offset to LigatureArray table--from
+ * beginning of MarkLigPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ markCoverage.sanitize (c, this) &&
+ ligatureCoverage.sanitize (c, this) &&
+ markArray.sanitize (c, this) &&
+ ligatureArray.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+markCoverage).intersects (glyphs) &&
+ (this+ligatureCoverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
+
+ unsigned ligcount = (this+ligatureArray).len;
+ auto lig_iter =
+ + hb_zip (this+ligatureCoverage, hb_range (ligcount))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ for (const unsigned i : lig_iter)
+ {
+ hb_sorted_vector_t<unsigned> lig_indexes;
+ unsigned row_count = lig_array[i].rows;
+ for (unsigned row : + hb_range (row_count))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (lig_indexes)
+ ;
+ }
+
+ lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+markCoverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark_index == NOT_COVERED)) return_trace (false);
+
+ /* Now we search backwards for a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
+ //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
+
+ unsigned int j = skippy_iter.idx;
+ unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
+ if (lig_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ const LigatureArray& lig_array = this+ligatureArray;
+ const LigatureAttach& lig_attach = lig_array[lig_index];
+
+ /* Find component to attach to */
+ unsigned int comp_count = lig_attach.rows;
+ if (unlikely (!comp_count))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ /* We must now check whether the ligature ID of the current mark glyph
+ * is identical to the ligature ID of the found ligature. If yes, we
+ * can directly use the component index. If not, we attach the mark
+ * glyph to the last component of the ligature. */
+ unsigned int comp_index;
+ unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ if (lig_id && lig_id == mark_id && mark_comp > 0)
+ comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
+ else
+ comp_index = comp_count - 1;
+
+ return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark_iter =
+ + hb_zip (this+markCoverage, this+markArray)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ auto new_mark_coverage =
+ + mark_iter
+ | hb_map_retains_sorting (hb_first)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
+ return_trace (false);
+
+ out->markArray.serialize_subset (c, markArray, this,
+ (this+markCoverage).iter (),
+ &klass_mapping);
+
+ auto new_ligature_coverage =
+ + hb_iter (this + ligatureCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
+ return_trace (false);
+
+ out->ligatureArray.serialize_subset (c, ligatureArray, this,
+ hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
+
+ return_trace (true);
+ }
+
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKLIGPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
new file mode 100644
index 0000000000..74b5105c42
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPos.hh
@@ -0,0 +1,42 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOS_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOS_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkMarkPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MarkMarkPosFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MarkMarkPosFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
new file mode 100644
index 0000000000..fbcebb8044
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
@@ -0,0 +1,228 @@
+#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
+
+#include "MarkMarkPosFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef AnchorMatrix Mark2Array; /* mark2-major--
+ * in order of Mark2Coverage Index--,
+ * mark1-minor--
+ * ordered by class--zero-based. */
+
+template <typename Types>
+struct MarkMarkPosFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ mark1Coverage; /* Offset to Combining Mark1 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ typename Types::template OffsetTo<Coverage>
+ mark2Coverage; /* Offset to Combining Mark2 Coverage
+ * table--from beginning of MarkMarkPos
+ * subtable */
+ HBUINT16 classCount; /* Number of defined mark classes */
+ typename Types::template OffsetTo<MarkArray>
+ mark1Array; /* Offset to Mark1Array table--from
+ * beginning of MarkMarkPos subtable */
+ typename Types::template OffsetTo<Mark2Array>
+ mark2Array; /* Offset to Mark2Array table--from
+ * beginning of MarkMarkPos subtable */
+ public:
+ DEFINE_SIZE_STATIC (4 + 4 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ mark1Coverage.sanitize (c, this) &&
+ mark2Coverage.sanitize (c, this) &&
+ mark1Array.sanitize (c, this) &&
+ mark2Array.sanitize (c, this, (unsigned int) classCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+mark1Coverage).intersects (glyphs) &&
+ (this+mark2Coverage).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
+ ;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
+
+ unsigned mark2_count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2_count))
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : mark2_iter)
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+ (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+mark1Coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (mark1_index == NOT_COVERED)) return_trace (false);
+
+ /* now we search backwards for a suitable mark glyph until a non-mark glyph */
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
+ unsigned unsafe_from;
+ if (!skippy_iter.prev (&unsafe_from))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ unsigned int j = skippy_iter.idx;
+
+ unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
+ unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
+ unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
+ unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
+
+ if (likely (id1 == id2))
+ {
+ if (id1 == 0) /* Marks belonging to the same base. */
+ goto good;
+ else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
+ goto good;
+ }
+ else
+ {
+ /* If ligature ids don't match, it may be the case that one of the marks
+ * itself is a ligature. In which case match. */
+ if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
+ goto good;
+ }
+
+ /* Didn't match. */
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+
+ good:
+ unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
+ if (mark2_index == NOT_COVERED)
+ {
+ buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
+ return_trace (false);
+ }
+
+ return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass_mapping;
+ Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
+
+ if (!klass_mapping.get_population ()) return_trace (false);
+ out->classCount = klass_mapping.get_population ();
+
+ auto mark1_iter =
+ + hb_zip (this+mark1Coverage, this+mark1Array)
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + mark1_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ out->mark1Array.serialize_subset (c, mark1Array, this,
+ (this+mark1Coverage).iter (),
+ &klass_mapping);
+
+ unsigned mark2count = (this+mark2Array).rows;
+ auto mark2_iter =
+ + hb_zip (this+mark2Coverage, hb_range (mark2count))
+ | hb_filter (glyphset, hb_first)
+ ;
+
+ new_coverage.reset ();
+ + mark2_iter
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
+ return_trace (false);
+
+ hb_sorted_vector_t<unsigned> mark2_indexes;
+ for (const unsigned row : + mark2_iter
+ | hb_map (hb_second))
+ {
+ + hb_range ((unsigned) classCount)
+ | hb_filter (klass_mapping)
+ | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
+ | hb_sink (mark2_indexes)
+ ;
+ }
+
+ out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
+
+ return_trace (true);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh
new file mode 100644
index 0000000000..7a514453ae
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/MarkRecord.hh
@@ -0,0 +1,52 @@
+#ifndef OT_LAYOUT_GPOS_MARKRECORD_HH
+#define OT_LAYOUT_GPOS_MARKRECORD_HH
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct MarkRecord
+{
+ friend struct MarkArray;
+
+ protected:
+ HBUINT16 klass; /* Class defined for this mark */
+ Offset16To<Anchor>
+ markAnchor; /* Offset to Anchor table--from
+ * beginning of MarkArray table */
+ public:
+ DEFINE_SIZE_STATIC (4);
+
+ unsigned get_class () const { return (unsigned) klass; }
+ bool sanitize (hb_sanitize_context_t *c, const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
+ }
+
+ MarkRecord *subset (hb_subset_context_t *c,
+ const void *src_base,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (nullptr);
+
+ out->klass = klass_mapping->get (klass);
+ out->markAnchor.serialize_subset (c, markAnchor, src_base);
+ return_trace (out);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *src_base) const
+ {
+ (src_base+markAnchor).collect_variation_indices (c);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_MARKRECORD_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
new file mode 100644
index 0000000000..72bfc43dc4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPos.hh
@@ -0,0 +1,46 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOS_HH
+#define OT_LAYOUT_GPOS_PAIRPOS_HH
+
+#include "PairPosFormat1.hh"
+#include "PairPosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PairPos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ PairPosFormat1_3<SmallTypes> format1;
+ PairPosFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ PairPosFormat1_3<MediumTypes> format3;
+ PairPosFormat2_4<MediumTypes> format4;
+#endif
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOS_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
new file mode 100644
index 0000000000..3cb207281d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat1.hh
@@ -0,0 +1,193 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
+
+#include "PairSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairPosFormat1_3
+{
+ using PairSet = GPOS_impl::PairSet<Types>;
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat[2]; /* [0] Defines the types of data in
+ * ValueRecord1--for the first glyph
+ * in the pair--may be zero (0) */
+ /* [1] Defines the types of data in
+ * ValueRecord2--for the second glyph
+ * in the pair--may be zero (0) */
+ Array16Of<typename Types::template OffsetTo<PairSet>>
+ pairSet; /* Array of PairSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (8 + Types::size, pairSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!c->check_struct (this)) return_trace (false);
+
+ unsigned int len1 = valueFormat[0].get_len ();
+ unsigned int len2 = valueFormat[1].get_len ();
+ typename PairSet::sanitize_closure_t closure =
+ {
+ valueFormat,
+ len1,
+ 1 + len1 + len2
+ };
+
+ return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([glyphs, this] (const typename Types::template OffsetTo<PairSet> &_)
+ { return (this+_).intersects (glyphs, valueFormat); })
+ | hb_any
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
+
+ auto it =
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (c->glyph_set, hb_first)
+ | hb_map (hb_second)
+ ;
+
+ if (!it) return;
+ + it
+ | hb_map (hb_add (this))
+ | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ unsigned int count = pairSet.len;
+ for (unsigned int i = 0; i < count; i++)
+ (this+pairSet[i]).collect_glyphs (c, valueFormat);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+ out->valueFormat[0] = valueFormat[0];
+ out->valueFormat[1] = valueFormat[1];
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ {
+ hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
+ out->valueFormat[0] = newFormats.first;
+ out->valueFormat[1] = newFormats.second;
+ }
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+
+ + hb_zip (this+coverage, pairSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([this, c, out] (const typename Types::template OffsetTo<PairSet>& _)
+ {
+ auto snap = c->serializer->snapshot ();
+ auto *o = out->pairSet.serialize_append (c->serializer);
+ if (unlikely (!o)) return false;
+ bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
+ if (!ret)
+ {
+ out->pairSet.pop ();
+ c->serializer->revert (snap);
+ }
+ return ret;
+ },
+ hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+
+ return_trace (bool (new_coverage));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
+ {
+ unsigned len1 = valueFormat[0].get_len ();
+ unsigned len2 = valueFormat[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+ for (const auto & _ :
+ + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
+ {
+ const PairSet& set = (this + _);
+ const PairValueRecord *record = &set.firstPairValueRecord;
+
+ for (unsigned i = 0; i < set.len; i++)
+ {
+ if (record->intersects (glyphset))
+ {
+ format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
+ format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
+ }
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT1_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
new file mode 100644
index 0000000000..a80fe0c226
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairPosFormat2.hh
@@ -0,0 +1,328 @@
+#ifndef OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+template <typename Types>
+struct PairPosFormat2_4
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat1; /* ValueRecord definition--for the
+ * first glyph of the pair--may be zero
+ * (0) */
+ ValueFormat valueFormat2; /* ValueRecord definition--for the
+ * second glyph of the pair--may be
+ * zero (0) */
+ typename Types::template OffsetTo<ClassDef>
+ classDef1; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the first glyph of the pair */
+ typename Types::template OffsetTo<ClassDef>
+ classDef2; /* Offset to ClassDef table--from
+ * beginning of PairPos subtable--for
+ * the second glyph of the pair */
+ HBUINT16 class1Count; /* Number of classes in ClassDef1
+ * table--includes Class0 */
+ HBUINT16 class2Count; /* Number of classes in ClassDef2
+ * table--includes Class0 */
+ ValueRecord values; /* Matrix of value pairs:
+ * class1-major, class2-minor,
+ * Each entry has value1 and value2 */
+ public:
+ DEFINE_SIZE_ARRAY (10 + 3 * Types::size, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && coverage.sanitize (c, this)
+ && classDef1.sanitize (c, this)
+ && classDef2.sanitize (c, this))) return_trace (false);
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ unsigned int stride = len1 + len2;
+ unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
+ unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
+ return_trace (c->check_range ((const void *) values,
+ count,
+ record_size) &&
+ valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
+ valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return (this+coverage).intersects (glyphs) &&
+ (this+classDef2).intersects (glyphs);
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!intersects (c->glyph_set)) return;
+ if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
+
+ hb_set_t klass1_glyphs, klass2_glyphs;
+ if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
+ if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
+
+ hb_set_t class1_set, class2_set;
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
+ {
+ if (!klass1_glyphs.has (cp)) class1_set.add (0);
+ else
+ {
+ unsigned klass1 = (this+classDef1).get (cp);
+ class1_set.add (klass1);
+ }
+ }
+
+ class2_set.add (0);
+ for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
+ {
+ unsigned klass2 = (this+classDef2).get (cp);
+ class2_set.add (klass2);
+ }
+
+ if (class1_set.is_empty ()
+ || class2_set.is_empty ()
+ || (class2_set.get_population() == 1 && class2_set.has(0)))
+ return;
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
+ for (const unsigned class1_idx : class1_set.iter ())
+ {
+ for (const unsigned class2_idx : class2_set.iter ())
+ {
+ unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ if (valueFormat1.has_device ())
+ valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
+
+ if (valueFormat2.has_device ())
+ valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
+ }
+ }
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
+ skippy_iter.reset (buffer->idx, 1);
+ unsigned unsafe_to;
+ if (!skippy_iter.next (&unsafe_to))
+ {
+ buffer->unsafe_to_concat (buffer->idx, unsafe_to);
+ return_trace (false);
+ }
+
+ unsigned int len1 = valueFormat1.get_len ();
+ unsigned int len2 = valueFormat2.get_len ();
+ unsigned int record_len = len1 + len2;
+
+ unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
+ unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
+ if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
+ {
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+ return_trace (false);
+ }
+
+ const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
+
+ bool applied_first = false, applied_second = false;
+
+
+ /* Isolate simple kerning and apply it half to each side.
+ * Results in better cursor positinoing / underline drawing.
+ *
+ * Disabled, because causes issues... :-(
+ * https://github.com/harfbuzz/harfbuzz/issues/3408
+ * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
+ */
+#ifndef HB_SPLIT_KERN
+ if (0)
+#endif
+ {
+ if (!len2)
+ {
+ const hb_direction_t dir = buffer->props.direction;
+ const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
+ const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
+ unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
+ if (backward)
+ mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
+ /* Add Devices. */
+ mask |= mask << 4;
+
+ if (valueFormat1 & ~mask)
+ goto bail;
+
+ /* Is simple kern. Apply value on an empty position slot,
+ * then split it between sides. */
+
+ hb_glyph_position_t pos{};
+ if (valueFormat1.apply_value (c, this, v, pos))
+ {
+ hb_position_t *src = &pos.x_advance;
+ hb_position_t *dst1 = &buffer->cur_pos().x_advance;
+ hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
+ unsigned i = horizontal ? 0 : 1;
+
+ hb_position_t kern = src[i];
+ hb_position_t kern1 = kern >> 1;
+ hb_position_t kern2 = kern - kern1;
+
+ if (!backward)
+ {
+ dst1[i] += kern1;
+ dst2[i] += kern2;
+ dst2[i + 2] += kern2;
+ }
+ else
+ {
+ dst1[i] += kern1;
+ dst1[i + 2] += src[i + 2] - kern2;
+ dst2[i] += kern2;
+ }
+
+ applied_first = applied_second = kern != 0;
+ goto success;
+ }
+ goto boring;
+ }
+ }
+ bail:
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerning glyphs at %d,%d",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
+ applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
+ applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, skippy_iter.idx);
+ }
+
+ success:
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
+ else
+ boring:
+ buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
+
+
+ buffer->idx = skippy_iter.idx;
+ if (len2)
+ buffer->idx++;
+
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_map_t klass1_map;
+ out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
+ out->class1Count = klass1_map.get_population ();
+
+ hb_map_t klass2_map;
+ out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
+ out->class2Count = klass2_map.get_population ();
+
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
+ if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ newFormats = compute_effective_value_formats (klass1_map, klass2_map);
+
+ out->valueFormat1 = newFormats.first;
+ out->valueFormat2 = newFormats.second;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
+ valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
+ }
+ }
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (this+coverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ out->coverage.serialize_serialize (c->serializer, it);
+ return_trace (out->class1Count && out->class2Count && bool (it));
+ }
+
+
+ hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
+ const hb_map_t& klass2_map) const
+ {
+ unsigned len1 = valueFormat1.get_len ();
+ unsigned len2 = valueFormat2.get_len ();
+
+ unsigned format1 = 0;
+ unsigned format2 = 0;
+
+ for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
+ {
+ for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
+ {
+ unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
+ format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
+ format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
+ }
+ }
+
+ return hb_pair (format1, format2);
+ }
+};
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRPOSFORMAT2_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
new file mode 100644
index 0000000000..4578fbd1d6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh
@@ -0,0 +1,189 @@
+#ifndef OT_LAYOUT_GPOS_PAIRSET_HH
+#define OT_LAYOUT_GPOS_PAIRSET_HH
+
+#include "PairValueRecord.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairSet
+{
+ template <typename Types2>
+ friend struct PairPosFormat1_3;
+
+ using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
+
+ protected:
+ HBUINT16 len; /* Number of PairValueRecords */
+ PairValueRecord firstPairValueRecord;
+ /* Array of PairValueRecords--ordered
+ * by GlyphID of the second glyph */
+ public:
+ DEFINE_SIZE_MIN (2);
+
+ struct sanitize_closure_t
+ {
+ const ValueFormat *valueFormats;
+ unsigned int len1; /* valueFormats[0].get_len() */
+ unsigned int stride; /* 1 + len1 + len2 */
+ };
+
+ bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(c->check_struct (this)
+ && c->check_range (&firstPairValueRecord,
+ len,
+ HBUINT16::static_size,
+ closure->stride))) return_trace (false);
+
+ unsigned int count = len;
+ const PairValueRecord *record = &firstPairValueRecord;
+ return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
+ closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
+ }
+
+ bool intersects (const hb_set_t *glyphs,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned int count = len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ if (glyphs->has (record->secondGlyph))
+ return true;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ return false;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ c->input->add_array (&record->secondGlyph, len, record_size);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats) const
+ {
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (c->glyph_set->has (record->secondGlyph))
+ { record->collect_variation_indices (c, valueFormats, this); }
+
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c,
+ const ValueFormat *valueFormats,
+ unsigned int pos) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int len1 = valueFormats[0].get_len ();
+ unsigned int len2 = valueFormats[1].get_len ();
+ unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
+
+ const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
+ &firstPairValueRecord,
+ len,
+ record_size);
+ if (record)
+ {
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerning glyphs at %d,%d",
+ c->buffer->idx, pos);
+ }
+
+ bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
+ bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "kerned glyphs at %d,%d",
+ c->buffer->idx, pos);
+ }
+
+ if (applied_first || applied_second)
+ buffer->unsafe_to_break (buffer->idx, pos + 1);
+ if (len2)
+ pos++;
+
+ buffer->idx = pos;
+ return_trace (true);
+ }
+ buffer->unsafe_to_concat (buffer->idx, pos + 1);
+ return_trace (false);
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const ValueFormat valueFormats[2],
+ const ValueFormat newFormats[2]) const
+ {
+ TRACE_SUBSET (this);
+ auto snap = c->serializer->snapshot ();
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->len = 0;
+
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned len1 = valueFormats[0].get_len ();
+ unsigned len2 = valueFormats[1].get_len ();
+ unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
+
+ typename PairValueRecord::context_t context =
+ {
+ this,
+ valueFormats,
+ newFormats,
+ len1,
+ &glyph_map,
+ c->plan->layout_variation_idx_map
+ };
+
+ const PairValueRecord *record = &firstPairValueRecord;
+ unsigned count = len, num = 0;
+ for (unsigned i = 0; i < count; i++)
+ {
+ if (glyphset.has (record->secondGlyph)
+ && record->subset (c, &context)) num++;
+ record = &StructAtOffset<const PairValueRecord> (record, record_size);
+ }
+
+ out->len = num;
+ if (!num) c->serializer->revert (snap);
+ return_trace (num);
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRSET_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh
new file mode 100644
index 0000000000..bd95abde16
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairValueRecord.hh
@@ -0,0 +1,99 @@
+#ifndef OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+#define OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
+
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+
+template <typename Types>
+struct PairValueRecord
+{
+ template <typename Types2>
+ friend struct PairSet;
+
+ protected:
+ typename Types::HBGlyphID
+ secondGlyph; /* GlyphID of second glyph in the
+ * pair--first glyph is listed in the
+ * Coverage table */
+ ValueRecord values; /* Positioning data for the first glyph
+ * followed by for second glyph */
+ public:
+ DEFINE_SIZE_ARRAY (Types::size, values);
+
+ int cmp (hb_codepoint_t k) const
+ { return secondGlyph.cmp (k); }
+
+ struct context_t
+ {
+ const void *base;
+ const ValueFormat *valueFormats;
+ const ValueFormat *newFormats;
+ unsigned len1; /* valueFormats[0].get_len() */
+ const hb_map_t *glyph_map;
+ const hb_map_t *layout_variation_idx_map;
+ };
+
+ bool subset (hb_subset_context_t *c,
+ context_t *closure) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *s = c->serializer;
+ auto *out = s->start_embed (*this);
+ if (unlikely (!s->extend_min (out))) return_trace (false);
+
+ out->secondGlyph = (*closure->glyph_map)[secondGlyph];
+
+ closure->valueFormats[0].copy_values (s,
+ closure->newFormats[0],
+ closure->base, &values[0],
+ closure->layout_variation_idx_map);
+ closure->valueFormats[1].copy_values (s,
+ closure->newFormats[1],
+ closure->base,
+ &values[closure->len1],
+ closure->layout_variation_idx_map);
+
+ return_trace (true);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const ValueFormat *valueFormats,
+ const void *base) const
+ {
+ unsigned record1_len = valueFormats[0].get_len ();
+ unsigned record2_len = valueFormats[1].get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
+
+ if (valueFormats[0].has_device ())
+ valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
+
+ if (valueFormats[1].has_device ())
+ valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
+ }
+
+ bool intersects (const hb_set_t& glyphset) const
+ {
+ return glyphset.has(secondGlyph);
+ }
+
+ const Value* get_values_1 () const
+ {
+ return &values[0];
+ }
+
+ const Value* get_values_2 (ValueFormat format1) const
+ {
+ return &values[format1.get_len ()];
+ }
+};
+
+
+}
+}
+}
+
+#endif // OT_LAYOUT_GPOS_PAIRVALUERECORD_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh
new file mode 100644
index 0000000000..c4e57bb543
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookup.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUP_HH
+#define OT_LAYOUT_GPOS_POSLOOKUP_HH
+
+#include "PosLookupSubTable.hh"
+#include "../../../hb-ot-layout-common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookup : Lookup
+{
+ using SubTable = PosLookupSubTable;
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ bool is_reverse () const
+ {
+ return false;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { return dispatch (c); }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ template <typename context_t>
+ static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_POSLOOKUP_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh
new file mode 100644
index 0000000000..c19fbc323f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/PosLookupSubTable.hh
@@ -0,0 +1,79 @@
+#ifndef OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH
+
+#include "SinglePos.hh"
+#include "PairPos.hh"
+#include "CursivePos.hh"
+#include "MarkBasePos.hh"
+#include "MarkLigPos.hh"
+#include "MarkMarkPos.hh"
+#include "ContextPos.hh"
+#include "ChainContextPos.hh"
+#include "ExtensionPos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct PosLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct PosLookup;
+
+ enum Type {
+ Single = 1,
+ Pair = 2,
+ Cursive = 3,
+ MarkBase = 4,
+ MarkLig = 5,
+ MarkMark = 6,
+ Context = 7,
+ ChainContext = 8,
+ Extension = 9
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
+ case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
+ case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+
+ protected:
+ union {
+ SinglePos single;
+ PairPos pair;
+ CursivePos cursive;
+ MarkBasePos markBase;
+ MarkLigPos markLig;
+ MarkMarkPos markMark;
+ ContextPos context;
+ ChainContextPos chainContext;
+ ExtensionPos extension;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GPOS_POSLOOKUPSUBTABLE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh
new file mode 100644
index 0000000000..702f578b3c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePos.hh
@@ -0,0 +1,95 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOS_HH
+#define OT_LAYOUT_GPOS_SINGLEPOS_HH
+
+#include "SinglePosFormat1.hh"
+#include "SinglePosFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePos
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SinglePosFormat1 format1;
+ SinglePosFormat2 format2;
+ } u;
+
+ public:
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned get_format (Iterator glyph_val_iter_pairs)
+ {
+ hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
+
+ for (const auto iter : glyph_val_iter_pairs)
+ for (const auto _ : hb_zip (iter.second, first_val_iter))
+ if (_.first != _.second)
+ return 2;
+
+ return 1;
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup* src,
+ Iterator glyph_val_iter_pairs,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ if (unlikely (!c->extend_min (u.format))) return;
+ unsigned format = 2;
+ ValueFormat new_format = src->get_value_format ();
+
+ if (glyph_val_iter_pairs)
+ format = get_format (glyph_val_iter_pairs);
+
+ u.format = format;
+ switch (u.format) {
+ case 1: u.format1.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
+ case 2: u.format2.serialize (c,
+ src,
+ glyph_val_iter_pairs,
+ new_format,
+ layout_variation_idx_map);
+ return;
+ default:return;
+ }
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+
+template<typename Iterator, typename SrcLookup>
+static void
+SinglePos_serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ const hb_map_t *layout_variation_idx_map)
+{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh
new file mode 100644
index 0000000000..7cbdf6dc6c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat1.hh
@@ -0,0 +1,138 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH
+
+#include "Common.hh"
+#include "ValueFormat.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ ValueRecord values; /* Defines positioning
+ * value(s)--applied to all glyphs in
+ * the Coverage table */
+ public:
+ DEFINE_SIZE_ARRAY (6, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_value (c, this, values));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (*c->glyph_set, intersection);
+ if (!intersection) return;
+
+ valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %d",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this, values, buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %d",
+ c->buffer->idx);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ if (unlikely (!c->extend_min (this))) return;
+ if (unlikely (!c->check_assign (valueFormat,
+ newFormat,
+ HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+
+ for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
+ {
+ src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
+ // Only serialize the first entry in the iterator, the rest are assumed to
+ // be the same.
+ break;
+ }
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
+
+ auto it =
+ + hb_iter (intersection)
+ | hb_map_retains_sorting (glyph_map)
+ | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh
new file mode 100644
index 0000000000..518fa9dcb0
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/SinglePosFormat2.hh
@@ -0,0 +1,154 @@
+#ifndef OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+#define OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+struct SinglePosFormat2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of subtable */
+ ValueFormat valueFormat; /* Defines the types of data in the
+ * ValueRecord */
+ HBUINT16 valueCount; /* Number of ValueRecords */
+ ValueRecord values; /* Array of ValueRecords--positioning
+ * values applied to glyphs */
+ public:
+ DEFINE_SIZE_ARRAY (8, values);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) &&
+ coverage.sanitize (c, this) &&
+ valueFormat.sanitize_values (c, this, values, valueCount));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
+ {
+ if (!valueFormat.has_device ()) return;
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (c->glyph_set, hb_first)
+ ;
+
+ if (!it) return;
+
+ unsigned sub_length = valueFormat.get_len ();
+ const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
+
+ for (unsigned i : + it
+ | hb_map (hb_second))
+ valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
+
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ ValueFormat get_value_format () const { return valueFormat; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_buffer_t *buffer = c->buffer;
+ unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (likely (index >= valueCount)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioning glyph at %d",
+ c->buffer->idx);
+ }
+
+ valueFormat.apply_value (c, this,
+ &values[index * valueFormat.get_len ()],
+ buffer->cur_pos());
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "positioned glyph at %d",
+ c->buffer->idx);
+ }
+
+ buffer->idx++;
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ typename SrcLookup,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ const SrcLookup *src,
+ Iterator it,
+ ValueFormat newFormat,
+ const hb_map_t *layout_variation_idx_map)
+ {
+ auto out = c->extend_min (this);
+ if (unlikely (!out)) return;
+ if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
+ if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
+
+ + it
+ | hb_map (hb_second)
+ | hb_apply ([&] (hb_array_t<const Value> _)
+ { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
+ ;
+
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ coverage.serialize_serialize (c, glyphs);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ unsigned sub_length = valueFormat.get_len ();
+ auto values_array = values.as_array (valueCount * sub_length);
+
+ auto it =
+ + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
+ | hb_filter (glyphset, hb_first)
+ | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
+ {
+ return hb_pair (glyph_map[_.first],
+ values_array.sub_array (_.second * sub_length,
+ sub_length));
+ })
+ ;
+
+ bool ret = bool (it);
+ SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
+ return_trace (ret);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GPOS_SINGLEPOSFORMAT2_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh
new file mode 100644
index 0000000000..b29f287bce
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GPOS/ValueFormat.hh
@@ -0,0 +1,329 @@
+#ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
+#define OT_LAYOUT_GPOS_VALUEFORMAT_HH
+
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GPOS_impl {
+
+typedef HBUINT16 Value;
+
+typedef UnsizedArrayOf<Value> ValueRecord;
+
+struct ValueFormat : HBUINT16
+{
+ enum Flags {
+ xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
+ yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
+ xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
+ yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
+ xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
+ yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
+ xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
+ yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
+ ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
+ reserved = 0xF000u, /* For future use */
+
+ devices = 0x00F0u /* Mask for having any Device table */
+ };
+
+/* All fields are options. Only those available advance the value pointer. */
+#if 0
+ HBINT16 xPlacement; /* Horizontal adjustment for
+ * placement--in design units */
+ HBINT16 yPlacement; /* Vertical adjustment for
+ * placement--in design units */
+ HBINT16 xAdvance; /* Horizontal adjustment for
+ * advance--in design units (only used
+ * for horizontal writing) */
+ HBINT16 yAdvance; /* Vertical adjustment for advance--in
+ * design units (only used for vertical
+ * writing) */
+ Offset16To<Device> xPlaDevice; /* Offset to Device table for
+ * horizontal placement--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
+ * placement--measured from beginning
+ * of PosTable (may be NULL) */
+ Offset16To<Device> xAdvDevice; /* Offset to Device table for
+ * horizontal advance--measured from
+ * beginning of PosTable (may be NULL) */
+ Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
+ * advance--measured from beginning of
+ * PosTable (may be NULL) */
+#endif
+
+ IntType& operator = (uint16_t i) { v = i; return *this; }
+
+ unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
+ unsigned int get_size () const { return get_len () * Value::static_size; }
+
+ bool apply_value (hb_ot_apply_context_t *c,
+ const void *base,
+ const Value *values,
+ hb_glyph_position_t &glyph_pos) const
+ {
+ bool ret = false;
+ unsigned int format = *this;
+ if (!format) return ret;
+
+ hb_font_t *font = c->font;
+ bool horizontal =
+#ifndef HB_NO_VERTICAL
+ HB_DIRECTION_IS_HORIZONTAL (c->direction)
+#else
+ true
+#endif
+ ;
+
+ if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
+ if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
+ if (format & xAdvance) {
+ if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
+ values++;
+ }
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (format & yAdvance) {
+ if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
+ values++;
+ }
+
+ if (!has_device ()) return ret;
+
+ bool use_x_device = font->x_ppem || font->num_coords;
+ bool use_y_device = font->y_ppem || font->num_coords;
+
+ if (!use_x_device && !use_y_device) return ret;
+
+ const VariationStore &store = c->var_store;
+ auto *cache = c->var_store_cache;
+
+ /* pixel -> fractional pixel */
+ if (format & xPlaDevice) {
+ if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yPlaDevice) {
+ if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ if (format & xAdvDevice) {
+ if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store, cache);
+ values++;
+ }
+ if (format & yAdvDevice) {
+ /* y_advance values grow downward but font-space grows upward, hence negation */
+ if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store, cache);
+ values++;
+ }
+ return ret;
+ }
+
+ unsigned int get_effective_format (const Value *values) const
+ {
+ unsigned int format = *this;
+ for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
+ if (format & flag) should_drop (*values++, (Flags) flag, &format);
+ }
+
+ return format;
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ unsigned int get_effective_format (Iterator it) const {
+ unsigned int new_format = 0;
+
+ for (const hb_array_t<const Value>& values : it)
+ new_format = new_format | get_effective_format (&values);
+
+ return new_format;
+ }
+
+ void copy_values (hb_serialize_context_t *c,
+ unsigned int new_format,
+ const void *base,
+ const Value *values,
+ const hb_map_t *layout_variation_idx_map) const
+ {
+ unsigned int format = *this;
+ if (!format) return;
+
+ if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
+ if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
+ if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
+ if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
+
+ if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
+ }
+
+ void copy_value (hb_serialize_context_t *c,
+ unsigned int new_format,
+ Flags flag,
+ Value value) const
+ {
+ // Filter by new format.
+ if (!(new_format & flag)) return;
+ c->copy (value);
+ }
+
+ void collect_variation_indices (hb_collect_variation_indices_context_t *c,
+ const void *base,
+ const hb_array_t<const Value>& values) const
+ {
+ unsigned format = *this;
+ unsigned i = 0;
+ if (format & xPlacement) i++;
+ if (format & yPlacement) i++;
+ if (format & xAdvance) i++;
+ if (format & yAdvance) i++;
+ if (format & xPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::yPlaDevice)
+ {
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::xAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+
+ if (format & ValueFormat::yAdvDevice)
+ {
+
+ (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
+ i++;
+ }
+ }
+
+ private:
+ bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ unsigned int format = *this;
+
+ if (format & xPlacement) values++;
+ if (format & yPlacement) values++;
+ if (format & xAdvance) values++;
+ if (format & yAdvance) values++;
+
+ if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+ if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
+
+ return true;
+ }
+
+ static inline Offset16To<Device>& get_device (Value* value)
+ {
+ return *static_cast<Offset16To<Device> *> (value);
+ }
+ static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *static_cast<const Offset16To<Device> *> (value);
+ }
+
+ bool copy_device (hb_serialize_context_t *c, const void *base,
+ const Value *src_value, const hb_map_t *layout_variation_idx_map) const
+ {
+ Value *dst_value = c->copy (*src_value);
+
+ if (!dst_value) return false;
+ if (*dst_value == 0) return true;
+
+ *dst_value = 0;
+ c->push ();
+ if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
+ {
+ c->add_link (*dst_value, c->pop_pack ());
+ return true;
+ }
+ else
+ {
+ c->pop_discard ();
+ return false;
+ }
+ }
+
+ static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
+ {
+ if (worked) *worked |= bool (*value);
+ return *reinterpret_cast<const HBINT16 *> (value);
+ }
+
+ public:
+
+ bool has_device () const
+ {
+ unsigned int format = *this;
+ return (format & devices) != 0;
+ }
+
+ bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
+ }
+
+ bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
+ {
+ TRACE_SANITIZE (this);
+ unsigned int len = get_len ();
+
+ if (!c->check_range (values, count, get_size ())) return_trace (false);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values += len;
+ }
+
+ return_trace (true);
+ }
+
+ /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
+ bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
+ {
+ TRACE_SANITIZE (this);
+
+ if (!has_device ()) return_trace (true);
+
+ for (unsigned int i = 0; i < count; i++) {
+ if (!sanitize_value_devices (c, base, values))
+ return_trace (false);
+ values += stride;
+ }
+
+ return_trace (true);
+ }
+
+ private:
+
+ void should_drop (Value value, Flags flag, unsigned int* format) const
+ {
+ if (value) return;
+ *format = *format & ~flag;
+ }
+
+};
+
+}
+}
+}
+
+#endif // #ifndef OT_LAYOUT_GPOS_VALUEFORMAT_HH
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
new file mode 100644
index 0000000000..4a9e9672eb
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSet.hh
@@ -0,0 +1,126 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESET_HH
+#define OT_LAYOUT_GSUB_ALTERNATESET_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct AlternateSet
+{
+ protected:
+ Array16Of<typename Types::HBGlyphID>
+ alternates; /* Array of alternate GlyphIDs--in
+ * arbitrary order */
+ public:
+ DEFINE_SIZE_ARRAY (2, alternates);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (alternates.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_any (alternates, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (alternates.arrayZ, alternates.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = alternates.len;
+
+ if (unlikely (!count)) return_trace (false);
+
+ hb_mask_t glyph_mask = c->buffer->cur().mask;
+ hb_mask_t lookup_mask = c->lookup_mask;
+
+ /* Note: This breaks badly if two features enabled this lookup together. */
+ unsigned int shift = hb_ctz (lookup_mask);
+ unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
+
+ /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
+ if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
+ {
+ /* Maybe we can do better than unsafe-to-break all; but since we are
+ * changing random state, it would be hard to track that. Good 'nough. */
+ c->buffer->unsafe_to_break (0, c->buffer->len);
+ alt_index = c->random_number () % count + 1;
+ }
+
+ if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (alternate substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph (alternates[alt_index - 1]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (alternate substitution)",
+ c->buffer->idx - 1);
+ }
+
+ return_trace (true);
+ }
+
+ unsigned
+ get_alternates (unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ {
+ if (alternates.len && alternate_count)
+ {
+ + alternates.sub_array (start_offset, alternate_count)
+ | hb_sink (hb_array (alternate_glyphs, *alternate_count))
+ ;
+ }
+ return alternates.len;
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator alts)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (alternates.serialize (c, alts));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_iter (alternates)
+ | hb_filter (glyphset)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it) &&
+ out->alternates);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESET_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
new file mode 100644
index 0000000000..37406179a2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubst.hh
@@ -0,0 +1,62 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBST_HH
+
+#include "AlternateSubstFormat1.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct AlternateSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ AlternateSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ AlternateSubstFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
+ * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+
+ /* TODO subset() should choose format. */
+
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
new file mode 100644
index 0000000000..adec65d586
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/AlternateSubstFormat1.hh
@@ -0,0 +1,128 @@
+#ifndef OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH
+
+#include "AlternateSet.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct AlternateSubstFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<typename Types::template OffsetTo<AlternateSet<Types>>>
+ alternateSet; /* Array of AlternateSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, alternateSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.closure (c); })
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const AlternateSet<Types> &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ unsigned
+ get_glyph_alternates (hb_codepoint_t gid,
+ unsigned start_offset,
+ unsigned *alternate_count /* IN/OUT. May be NULL. */,
+ hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
+ { return (this+alternateSet[(this+coverage).get_coverage (gid)])
+ .get_alternates (start_offset, alternate_count, alternate_glyphs); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+alternateSet[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int alternate_len = alternate_len_list[i];
+ if (unlikely (!alternateSet[i]
+ .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+ return_trace (false);
+ alternate_glyphs_list += alternate_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, alternateSet)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_ALTERNATESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
new file mode 100644
index 0000000000..08fd779f73
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ChainContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct ChainContextSubst : ChainContext {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CHAINCONTEXTSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
new file mode 100644
index 0000000000..968bba0481
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Common.hh
@@ -0,0 +1,21 @@
+#ifndef OT_LAYOUT_GSUB_COMMON_HH
+#define OT_LAYOUT_GSUB_COMMON_HH
+
+#include "../../../hb-serialize.hh"
+#include "../../../hb-ot-layout-gsubgpos.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
+
+template<typename Iterator>
+static void SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it);
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_COMMON_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
new file mode 100644
index 0000000000..9f8cb46b5e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ContextSubst.hh
@@ -0,0 +1,18 @@
+#ifndef OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+#define OT_LAYOUT_GSUB_CONTEXTSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct ContextSubst : Context {};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_CONTEXTSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
new file mode 100644
index 0000000000..831a7dfa2d
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ExtensionSubst.hh
@@ -0,0 +1,22 @@
+#ifndef OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+#define OT_LAYOUT_GSUB_EXTENSIONSUBST_HH
+
+// TODO(garretrieger): move to new layout.
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct ExtensionSubst : Extension<ExtensionSubst>
+{
+ typedef struct SubstLookupSubTable SubTable;
+ bool is_reverse () const;
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_EXTENSIONSUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
new file mode 100644
index 0000000000..c0ff098f49
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/GSUB.hh
@@ -0,0 +1,61 @@
+#ifndef OT_LAYOUT_GSUB_GSUB_HH
+#define OT_LAYOUT_GSUB_GSUB_HH
+
+#include "../../../hb-ot-layout-gsubgpos.hh"
+#include "Common.hh"
+#include "SubstLookup.hh"
+
+namespace OT {
+
+using Layout::GSUB_impl::SubstLookup;
+
+namespace Layout {
+
+/*
+ * GSUB -- Glyph Substitution
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
+ */
+
+struct GSUB : GSUBGPOS
+{
+ using Lookup = SubstLookup;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
+
+ const SubstLookup& get_lookup (unsigned int i) const
+ { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
+ return GSUBGPOS::subset<SubstLookup> (&l);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (GSUBGPOS::sanitize<SubstLookup> (c));
+ }
+
+ HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
+ hb_face_t *face) const;
+
+ void closure_lookups (hb_face_t *face,
+ const hb_set_t *glyphs,
+ hb_set_t *lookup_indexes /* IN/OUT */) const
+ { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
+
+ typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
+};
+
+
+}
+
+struct GSUB_accelerator_t : Layout::GSUB::accelerator_t {
+ GSUB_accelerator_t (hb_face_t *face) : Layout::GSUB::accelerator_t (face) {}
+};
+
+
+}
+
+#endif /* OT_LAYOUT_GSUB_GSUB_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
new file mode 100644
index 0000000000..f373d921b5
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Ligature.hh
@@ -0,0 +1,187 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURE_HH
+#define OT_LAYOUT_GSUB_LIGATURE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct Ligature
+{
+ protected:
+ typename Types::HBGlyphID
+ ligGlyph; /* GlyphID of ligature to substitute */
+ HeadlessArrayOf<typename Types::HBGlyphID>
+ component; /* Array of component GlyphIDs--start
+ * with the second component--ordered
+ * in writing direction */
+ public:
+ DEFINE_SIZE_ARRAY (Types::size + 2, component);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (component, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+ c->output->add (ligGlyph);
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->input->add_array (component.arrayZ, component.get_length ());
+ c->output->add (ligGlyph);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ if (c->len != component.lenP1)
+ return false;
+
+ for (unsigned int i = 1; i < c->len; i++)
+ if (likely (c->glyphs[i] != component[i]))
+ return false;
+
+ return true;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = component.lenP1;
+
+ if (unlikely (!count)) return_trace (false);
+
+ /* Special-case to make it in-place and not consider this
+ * as a "ligated" substitution. */
+ if (unlikely (count == 1))
+ {
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (ligature substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph (ligGlyph);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (ligature substitution)",
+ c->buffer->idx - 1);
+ }
+
+ return_trace (true);
+ }
+
+ unsigned int total_component_count = 0;
+
+ unsigned int match_end = 0;
+ unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
+
+ if (likely (!match_input (c, count,
+ &component[1],
+ match_glyph,
+ nullptr,
+ &match_end,
+ match_positions,
+ &total_component_count)))
+ {
+ c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
+ return_trace (false);
+ }
+
+ unsigned pos = 0;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ unsigned delta = c->buffer->sync_so_far ();
+
+ pos = c->buffer->idx;
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ match_end += delta;
+ for (unsigned i = 0; i < count; i++)
+ {
+ match_positions[i] += delta;
+ if (i)
+ *p++ = ',';
+ sprintf (p, "%u", match_positions[i]);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "ligating glyphs at %s",
+ buf);
+ }
+
+ ligate_input (c,
+ count,
+ match_positions,
+ match_end,
+ ligGlyph,
+ total_component_count);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "ligated glyph at %d",
+ pos);
+ }
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ hb_codepoint_t ligature,
+ Iterator components /* Starting from second */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ ligGlyph = ligature;
+ if (unlikely (!component.serialize (c, components))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ auto it =
+ + hb_iter (component)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer,
+ glyph_map[ligGlyph],
+ it)); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
new file mode 100644
index 0000000000..637cec7137
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSet.hh
@@ -0,0 +1,119 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESET_HH
+#define OT_LAYOUT_GSUB_LIGATURESET_HH
+
+#include "Common.hh"
+#include "Ligature.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct LigatureSet
+{
+ protected:
+ Array16OfOffset16To<Ligature<Types>>
+ ligature; /* Array LigatureSet tables
+ * ordered by preference */
+ public:
+ DEFINE_SIZE_ARRAY (2, ligature);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (ligature.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([glyphs] (const Ligature<Types> &_) { return _.intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature<Types> &_) { _.closure (c); })
+ ;
+ }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Ligature<Types> &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ return
+ + hb_iter (ligature)
+ | hb_map (hb_add (this))
+ | hb_map ([c] (const Ligature<Types> &_) { return _.would_apply (c); })
+ | hb_any
+ ;
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int num_ligs = ligature.len;
+ for (unsigned int i = 0; i < num_ligs; i++)
+ {
+ const auto &lig = this+ligature[i];
+ if (lig.apply (c)) return_trace (true);
+ }
+
+ return_trace (false);
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_array_t<const HBGlyphID16> ligatures,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
+ for (unsigned int i = 0; i < ligatures.length; i++)
+ {
+ unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
+ if (unlikely (!ligature[i].serialize_serialize (c,
+ ligatures[i],
+ component_list.sub_array (0, component_count))))
+ return_trace (false);
+ component_list += component_count;
+ }
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ + hb_iter (ligature)
+ | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
+ | hb_drain
+ ;
+
+ if (bool (out->ligature))
+ // Ensure Coverage table is always packed after this.
+ c->serializer->add_virtual_link (coverage_idx);
+
+ return_trace (bool (out->ligature));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESET_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
new file mode 100644
index 0000000000..63707972a8
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubst.hh
@@ -0,0 +1,71 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBST_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBST_HH
+
+#include "Common.hh"
+#include "LigatureSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct LigatureSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ LigatureSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ LigatureSubstFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ /* TODO This function is only used by small GIDs, and not updated to 24bit GIDs. Should
+ * be done by using iterators. While at it perhaps using iterator of arrays of hb_codepoint_t
+ * instead. */
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list));
+ default:return_trace (false);
+ }
+ }
+
+ /* TODO subset() should choose format. */
+
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
new file mode 100644
index 0000000000..32b642c38a
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/LigatureSubstFormat1.hh
@@ -0,0 +1,166 @@
+#ifndef OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "LigatureSet.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct LigatureSubstFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<typename Types::template OffsetTo<LigatureSet<Types>>>
+ ligatureSet; /* Array LigatureSet tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (4 + Types::size, ligatureSet);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ return
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (*glyphs, hb_first)
+ | hb_map (hb_second)
+ | hb_map ([this, glyphs] (const typename Types::template OffsetTo<LigatureSet<Types>> &_)
+ { return (this+_).intersects (glyphs); })
+ | hb_any
+ ;
+ }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.closure (c); })
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const LigatureSet<Types> &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ {
+ unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
+ if (likely (index == NOT_COVERED)) return false;
+
+ const auto &lig_set = this+ligatureSet[index];
+ return lig_set.would_apply (c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const auto &lig_set = this+ligatureSet[index];
+ return_trace (lig_set.apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < first_glyphs.length; i++)
+ {
+ unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+ if (unlikely (!ligatureSet[i]
+ .serialize_serialize (c,
+ ligatures_list.sub_array (0, ligature_count),
+ component_count_list.sub_array (0, ligature_count),
+ component_list))) return_trace (false);
+ ligatures_list += ligature_count;
+ component_count_list += ligature_count;
+ }
+ return_trace (coverage.serialize_serialize (c, first_glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ // Due to a bug in some older versions of windows 7 the Coverage table must be
+ // packed after the LigatureSet and Ligature tables, so serialize Coverage first
+ // which places it last in the packed order.
+ hb_set_t new_coverage;
+ + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
+ | hb_filter (glyphset, hb_first)
+ | hb_filter ([&] (const LigatureSet<Types>& _) {
+ return _.intersects (&glyphset);
+ }, hb_second)
+ | hb_map (hb_first)
+ | hb_sink (new_coverage);
+
+ if (!c->serializer->push<Coverage> ()
+ ->serialize (c->serializer,
+ + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
+ {
+ c->serializer->pop_discard ();
+ return_trace (false);
+ }
+
+ unsigned coverage_idx = c->serializer->pop_pack ();
+ c->serializer->add_link (out->coverage, coverage_idx);
+
+ + hb_zip (this+coverage, ligatureSet)
+ | hb_filter (new_coverage, hb_first)
+ | hb_map (hb_second)
+ // to ensure that the repacker always orders the coverage table after the LigatureSet
+ // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
+ // the coverage table object idx is passed down to facilitate this.
+ | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
+ ;
+
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_LIGATURESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
new file mode 100644
index 0000000000..98f2f5fe7a
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubst.hh
@@ -0,0 +1,64 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBST_HH
+
+#include "Common.hh"
+#include "MultipleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct MultipleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ MultipleSubstFormat1_2<SmallTypes> format1;
+#ifndef HB_NO_BORING_EXPANSION
+ MultipleSubstFormat1_2<MediumTypes> format2;
+#endif
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ /* TODO This function is unused and not updated to 24bit GIDs. Should be done by using
+ * iterators. While at it perhaps using iterator of arrays of hb_codepoint_t instead. */
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned int format = 1;
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
+ default:return_trace (false);
+ }
+ }
+
+ /* TODO subset() should choose format. */
+
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
new file mode 100644
index 0000000000..89a04ec3b1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/MultipleSubstFormat1.hh
@@ -0,0 +1,121 @@
+#ifndef OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+#include "Sequence.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct MultipleSubstFormat1_2
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<typename Types::template OffsetTo<Sequence<Types>>>
+ sequence; /* Array of Sequence tables
+ * ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_ARRAY (4 + Types::size, sequence);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return true; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence<Types> &_) { _.closure (c); })
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, sequence)
+ | hb_map (hb_second)
+ | hb_map (hb_add (this))
+ | hb_apply ([c] (const Sequence<Types> &_) { _.collect_glyphs (c); })
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ return_trace ((this+sequence[index]).apply (c));
+ }
+
+ bool serialize (hb_serialize_context_t *c,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
+ for (unsigned int i = 0; i < glyphs.length; i++)
+ {
+ unsigned int substitute_len = substitute_len_list[i];
+ if (unlikely (!sequence[i]
+ .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+ return_trace (false);
+ substitute_glyphs_list += substitute_len;
+ }
+ return_trace (coverage.serialize_serialize (c, glyphs));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+ out->format = format;
+
+ hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+ + hb_zip (this+coverage, sequence)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
+ | hb_map (hb_first)
+ | hb_map (glyph_map)
+ | hb_sink (new_coverage)
+ ;
+ out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
+ return_trace (bool (new_coverage));
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_MULTIPLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
new file mode 100644
index 0000000000..48e208efb9
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubst.hh
@@ -0,0 +1,36 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH
+
+#include "Common.hh"
+#include "ReverseChainSingleSubstFormat1.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct ReverseChainSingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ ReverseChainSingleSubstFormat1 format1;
+ } u;
+
+ public:
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
new file mode 100644
index 0000000000..a23e92028e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
@@ -0,0 +1,244 @@
+#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct ReverseChainSingleSubstFormat1
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ Offset16To<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of table */
+ Array16OfOffset16To<Coverage>
+ backtrack; /* Array of coverage tables
+ * in backtracking sequence, in glyph
+ * sequence order */
+ Array16OfOffset16To<Coverage>
+ lookaheadX; /* Array of coverage tables
+ * in lookahead sequence, in glyph
+ * sequence order */
+ Array16Of<HBGlyphID16>
+ substituteX; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+ public:
+ DEFINE_SIZE_MIN (10);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
+ return_trace (false);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ if (!lookahead.sanitize (c, this))
+ return_trace (false);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ if (!(this+coverage).intersects (glyphs))
+ return false;
+
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+backtrack[i]).intersects (glyphs))
+ return false;
+
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (!(this+lookahead[i]).intersects (glyphs))
+ return false;
+
+ return true;
+ }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ if (!intersects (c->glyphs)) return;
+
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+
+ unsigned int count;
+
+ count = backtrack.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
+
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ count = lookahead.len;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
+
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+ count = substitute.len;
+ c->output->add_array (substitute.arrayZ, substitute.len);
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
+ return_trace (false); /* No chaining to this type */
+
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ unsigned int start_index = 0, end_index = 0;
+ if (match_backtrack (c,
+ backtrack.len, (HBUINT16 *) backtrack.arrayZ,
+ match_coverage, this,
+ &start_index) &&
+ match_lookahead (c,
+ lookahead.len, (HBUINT16 *) lookahead.arrayZ,
+ match_coverage, this,
+ c->buffer->idx + 1, &end_index))
+ {
+ c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replacing glyph at %d (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph_inplace (substitute[index]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (reverse chaining substitution)",
+ c->buffer->idx);
+ }
+
+ /* Note: We DON'T decrease buffer->idx. The main loop does it
+ * for us. This is useful for preventing surprises if someone
+ * calls us through a Context lookup. */
+ return_trace (true);
+ }
+ else
+ {
+ c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
+ return_trace (false);
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
+ {
+ TRACE_SERIALIZE (this);
+ auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
+
+ if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
+ return_trace (false);
+
+ for (auto& offset : it) {
+ auto *o = out->serialize_append (c->serializer);
+ if (unlikely (!o) || !o->serialize_subset (c, offset, this))
+ return_trace (false);
+ }
+
+ return_trace (true);
+ }
+
+ template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
+ hb_requires (hb_is_iterator (BacktrackIterator)),
+ hb_requires (hb_is_iterator (LookaheadIterator))>
+ bool serialize (hb_subset_context_t *c,
+ Iterator coverage_subst_iter,
+ BacktrackIterator backtrack_iter,
+ LookaheadIterator lookahead_iter) const
+ {
+ TRACE_SERIALIZE (this);
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->check_success (out))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
+ if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
+
+ if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
+ if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
+
+ auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
+ auto substitutes =
+ + coverage_subst_iter
+ | hb_map (hb_second)
+ ;
+
+ auto glyphs =
+ + coverage_subst_iter
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
+ return_trace (false);
+
+ if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
+ return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
+ const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
+ }
+};
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
new file mode 100644
index 0000000000..3d84a5e6ea
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/Sequence.hh
@@ -0,0 +1,165 @@
+#ifndef OT_LAYOUT_GSUB_SEQUENCE_HH
+#define OT_LAYOUT_GSUB_SEQUENCE_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct Sequence
+{
+ protected:
+ Array16Of<typename Types::HBGlyphID>
+ substitute; /* String of GlyphIDs to substitute */
+ public:
+ DEFINE_SIZE_ARRAY (2, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return hb_all (substitute, glyphs); }
+
+ void closure (hb_closure_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ { c->output->add_array (substitute.arrayZ, substitute.len); }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int count = substitute.len;
+
+ /* Special-case to make it in-place and not consider this
+ * as a "multiplied" substitution. */
+ if (unlikely (count == 1))
+ {
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph (substitute.arrayZ[0]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (multiple subtitution)",
+ c->buffer->idx - 1);
+ }
+
+ return_trace (true);
+ }
+ /* Spec disallows this, but Uniscribe allows it.
+ * https://github.com/harfbuzz/harfbuzz/issues/253 */
+ else if (unlikely (count == 0))
+ {
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleting glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
+ c->buffer->delete_glyph ();
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "deleted glyph at %d (multiple substitution)",
+ c->buffer->idx);
+ }
+
+ return_trace (true);
+ }
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "multiplying glyph at %d",
+ c->buffer->idx);
+ }
+
+ unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
+ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
+ unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ /* If is attached to a ligature, don't disturb that.
+ * https://github.com/harfbuzz/harfbuzz/issues/3069 */
+ if (!lig_id)
+ _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
+ c->output_glyph_for_component (substitute.arrayZ[i], klass);
+ }
+ c->buffer->skip_glyph ();
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+
+ char buf[HB_MAX_CONTEXT_LENGTH * 16] = {0};
+ char *p = buf;
+
+ for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
+ {
+ if (buf < p)
+ *p++ = ',';
+ sprintf (p, "%u", i);
+ p += strlen(p);
+ }
+
+ c->buffer->message (c->font,
+ "multiplied glyphs at %s",
+ buf);
+ }
+
+ return_trace (true);
+ }
+
+ template <typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator subst)
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (substitute.serialize (c, subst));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ if (!intersects (&glyphset)) return_trace (false);
+
+ auto it =
+ + hb_iter (substitute)
+ | hb_map (glyph_map)
+ ;
+
+ auto *out = c->serializer->start_embed (*this);
+ return_trace (out->serialize (c->serializer, it));
+ }
+};
+
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SEQUENCE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
new file mode 100644
index 0000000000..6942e6997f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubst.hh
@@ -0,0 +1,103 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBST_HH
+#define OT_LAYOUT_GSUB_SINGLESUBST_HH
+
+#include "Common.hh"
+#include "SingleSubstFormat1.hh"
+#include "SingleSubstFormat2.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct SingleSubst
+{
+ protected:
+ union {
+ HBUINT16 format; /* Format identifier */
+ SingleSubstFormat1_3<SmallTypes> format1;
+ SingleSubstFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BORING_EXPANSION
+ SingleSubstFormat1_3<MediumTypes> format3;
+ SingleSubstFormat2_4<MediumTypes> format4;
+#endif
+ } u;
+
+ public:
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+#endif
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ const hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (u.format))) return_trace (false);
+ unsigned format = 2;
+ unsigned delta = 0;
+ if (glyphs)
+ {
+ format = 1;
+ hb_codepoint_t mask = 0xFFFFu;
+
+#ifndef HB_NO_BORING_EXPANSION
+ if (+ glyphs
+ | hb_map_retains_sorting (hb_first)
+ | hb_filter ([] (hb_codepoint_t gid) { return gid > 0xFFFFu; }))
+ {
+ format += 2;
+ mask = 0xFFFFFFu;
+ }
+#endif
+
+ auto get_delta = [=] (hb_codepoint_pair_t _)
+ { return (unsigned) (_.second - _.first) & mask; };
+ delta = get_delta (*glyphs);
+ if (!hb_all (++(+glyphs), delta, get_delta)) format += 1;
+ }
+
+ u.format = format;
+ switch (u.format) {
+ case 1: return_trace (u.format1.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 2: return_trace (u.format2.serialize (c, glyphs));
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: return_trace (u.format3.serialize (c,
+ + glyphs
+ | hb_map_retains_sorting (hb_first),
+ delta));
+ case 4: return_trace (u.format4.serialize (c, glyphs));
+#endif
+ default:return_trace (false);
+ }
+ }
+};
+
+template<typename Iterator>
+static void
+SingleSubst_serialize (hb_serialize_context_t *c,
+ Iterator it)
+{ c->start_embed<SingleSubst> ()->serialize (c, it); }
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBST_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
new file mode 100644
index 0000000000..4b17243d81
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat1.hh
@@ -0,0 +1,163 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct SingleSubstFormat1_3
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 1 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ typename Types::HBUINT
+ deltaGlyphID; /* Add to original GlyphID to get
+ * substitute GlyphID, modulo 0x10000 */
+
+ public:
+ DEFINE_SIZE_STATIC (2 + 2 * Types::size);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
+ }
+
+ hb_codepoint_t get_mask () const
+ { return (1 << (8 * Types::size)) - 1; }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (c->parent_active_glyphs (), intersection);
+
+ /* In degenerate fuzzer-found fonts, but not real fonts,
+ * this table can keep adding new glyphs in each round of closure.
+ * Refuse to close-over, if it maps glyph range to overlapping range. */
+ hb_codepoint_t min_before = intersection.get_min ();
+ hb_codepoint_t max_before = intersection.get_max ();
+ hb_codepoint_t min_after = (min_before + d) & mask;
+ hb_codepoint_t max_after = (max_before + d) & mask;
+ if ((this+coverage).get_population () >= max_before - min_before &&
+ ((min_before <= min_after && min_after <= max_before) ||
+ (min_before <= max_after && max_after <= max_before)))
+ return;
+
+ + hb_iter (intersection)
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
+ | hb_sink (c->output)
+ ;
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ + hb_iter (this+coverage)
+ | hb_map ([d, mask] (hb_codepoint_t g) { return (g + d) & mask; })
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
+ unsigned int index = (this+coverage).get_coverage (glyph_id);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ glyph_id = (glyph_id + d) & mask;
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (single substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph (glyph_id);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (single substitution)",
+ c->buffer->idx - 1);
+ }
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator glyphs,
+ unsigned delta)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ hb_codepoint_t d = deltaGlyphID;
+ hb_codepoint_t mask = get_mask ();
+
+ hb_set_t intersection;
+ (this+coverage).intersect_set (glyphset, intersection);
+
+ auto it =
+ + hb_iter (intersection)
+ | hb_map_retains_sorting ([d, mask] (hb_codepoint_t g) {
+ return hb_codepoint_pair_t (g,
+ (g + d) & mask); })
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT1_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
new file mode 100644
index 0000000000..fb1e90d03e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SingleSubstFormat2.hh
@@ -0,0 +1,136 @@
+#ifndef OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+#define OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH
+
+#include "Common.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+template <typename Types>
+struct SingleSubstFormat2_4
+{
+ protected:
+ HBUINT16 format; /* Format identifier--format = 2 */
+ typename Types::template OffsetTo<Coverage>
+ coverage; /* Offset to Coverage table--from
+ * beginning of Substitution table */
+ Array16Of<typename Types::HBGlyphID>
+ substitute; /* Array of substitute
+ * GlyphIDs--ordered by Coverage Index */
+
+ public:
+ DEFINE_SIZE_ARRAY (4 + Types::size, substitute);
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ { return (this+coverage).intersects (glyphs); }
+
+ bool may_have_non_1to1 () const
+ { return false; }
+
+ void closure (hb_closure_context_t *c) const
+ {
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (c->parent_active_glyphs (), hb_first)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+
+ }
+
+ void closure_lookups (hb_closure_lookups_context_t *c) const {}
+
+ void collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
+ + hb_zip (this+coverage, substitute)
+ | hb_map (hb_second)
+ | hb_sink (c->output)
+ ;
+ }
+
+ const Coverage &get_coverage () const { return this+coverage; }
+
+ bool would_apply (hb_would_apply_context_t *c) const
+ { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
+ if (likely (index == NOT_COVERED)) return_trace (false);
+
+ if (unlikely (index >= substitute.len)) return_trace (false);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "replacing glyph at %d (single substitution)",
+ c->buffer->idx);
+ }
+
+ c->replace_glyph (substitute[index]);
+
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ c->buffer->message (c->font,
+ "replaced glyph at %d (single substitution)",
+ c->buffer->idx - 1);
+ }
+
+ return_trace (true);
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_sorted_source_of (Iterator,
+ hb_codepoint_pair_t))>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it)
+ {
+ TRACE_SERIALIZE (this);
+ auto substitutes =
+ + it
+ | hb_map (hb_second)
+ ;
+ auto glyphs =
+ + it
+ | hb_map_retains_sorting (hb_first)
+ ;
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+ if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
+ return_trace (true);
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+ auto it =
+ + hb_zip (this+coverage, substitute)
+ | hb_filter (glyphset, hb_first)
+ | hb_filter (glyphset, hb_second)
+ | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const typename Types::HBGlyphID &> p) -> hb_codepoint_pair_t
+ { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
+ ;
+
+ bool ret = bool (it);
+ SingleSubst_serialize (c->serializer, it);
+ return_trace (ret);
+ }
+};
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SINGLESUBSTFORMAT2_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
new file mode 100644
index 0000000000..320685b868
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookup.hh
@@ -0,0 +1,223 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUP_HH
+
+#include "Common.hh"
+#include "SubstLookupSubTable.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct SubstLookup : Lookup
+{
+ using SubTable = SubstLookupSubTable;
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ { return Lookup::sanitize<SubTable> (c); }
+
+ const SubTable& get_subtable (unsigned int i) const
+ { return Lookup::get_subtable<SubTable> (i); }
+
+ static inline bool lookup_type_is_reverse (unsigned int lookup_type)
+ { return lookup_type == SubTable::ReverseChainSingle; }
+
+ bool is_reverse () const
+ {
+ unsigned int type = get_type ();
+ if (unlikely (type == SubTable::Extension))
+ return get_subtable (0).u.extension.is_reverse ();
+ return lookup_type_is_reverse (type);
+ }
+
+ bool may_have_non_1to1 () const
+ {
+ hb_have_non_1to1_context_t c;
+ return dispatch (&c);
+ }
+
+ bool apply (hb_ot_apply_context_t *c) const
+ {
+ TRACE_APPLY (this);
+ return_trace (dispatch (c));
+ }
+
+ bool intersects (const hb_set_t *glyphs) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c);
+ }
+
+ hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
+ {
+ if (!c->should_visit_lookup (this_index))
+ return hb_closure_context_t::default_return_value ();
+
+ c->set_recurse_func (dispatch_closure_recurse_func);
+
+ hb_closure_context_t::return_t ret = dispatch (c);
+
+ c->flush ();
+
+ return ret;
+ }
+
+ hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
+ {
+ if (c->is_lookup_visited (this_index))
+ return hb_closure_lookups_context_t::default_return_value ();
+
+ c->set_lookup_visited (this_index);
+ if (!intersects (c->glyphs))
+ {
+ c->set_lookup_inactive (this_index);
+ return hb_closure_lookups_context_t::default_return_value ();
+ }
+
+ hb_closure_lookups_context_t::return_t ret = dispatch (c);
+ return ret;
+ }
+
+ hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
+ {
+ c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
+ return dispatch (c);
+ }
+
+ template <typename set_t>
+ void collect_coverage (set_t *glyphs) const
+ {
+ hb_collect_coverage_context_t<set_t> c (glyphs);
+ dispatch (&c);
+ }
+
+ bool would_apply (hb_would_apply_context_t *c,
+ const hb_ot_layout_lookup_accelerator_t *accel) const
+ {
+ if (unlikely (!c->len)) return false;
+ if (!accel->may_have (c->glyphs[0])) return false;
+ return dispatch (c);
+ }
+
+ template<typename Glyphs, typename Substitutes,
+ hb_requires (hb_is_sorted_source_of (Glyphs,
+ const hb_codepoint_t) &&
+ hb_is_source_of (Substitutes,
+ const hb_codepoint_t))>
+ bool serialize_single (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ Glyphs glyphs,
+ Substitutes substitutes)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_multiple (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> substitute_len_list,
+ hb_array_t<const HBGlyphID16> substitute_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.multiple.
+ serialize (c,
+ glyphs,
+ substitute_len_list,
+ substitute_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_alternate (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> glyphs,
+ hb_array_t<const unsigned int> alternate_len_list,
+ hb_array_t<const HBGlyphID16> alternate_glyphs_list)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
+
+ if (c->push<SubTable> ()->u.alternate.
+ serialize (c,
+ glyphs,
+ alternate_len_list,
+ alternate_glyphs_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ bool serialize_ligature (hb_serialize_context_t *c,
+ uint32_t lookup_props,
+ hb_sorted_array_t<const HBGlyphID16> first_glyphs,
+ hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+ hb_array_t<const HBGlyphID16> ligatures_list,
+ hb_array_t<const unsigned int> component_count_list,
+ hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
+ {
+ TRACE_SERIALIZE (this);
+ if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
+ if (c->push<SubTable> ()->u.ligature.
+ serialize (c,
+ first_glyphs,
+ ligature_per_first_glyph_count_list,
+ ligatures_list,
+ component_count_list,
+ component_list))
+ {
+ c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
+ return_trace (true);
+ }
+ c->pop_discard ();
+ return_trace (false);
+ }
+
+ template <typename context_t>
+ static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
+
+ static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
+
+ static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
+ {
+ if (!c->should_visit_lookup (lookup_index))
+ return hb_empty_t ();
+
+ hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
+
+ /* While in theory we should flush here, it will cause timeouts because a recursive
+ * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
+ * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
+ //c->flush ();
+
+ return ret;
+ }
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
+
+ bool subset (hb_subset_context_t *c) const
+ { return Lookup::subset<SubTable> (c); }
+};
+
+
+}
+}
+}
+
+#endif /* OT_LAYOUT_GSUB_SUBSTLOOKUP_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
new file mode 100644
index 0000000000..a525fba039
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/GSUB/SubstLookupSubTable.hh
@@ -0,0 +1,77 @@
+#ifndef OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+#define OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH
+
+#include "Common.hh"
+#include "SingleSubst.hh"
+#include "MultipleSubst.hh"
+#include "AlternateSubst.hh"
+#include "LigatureSubst.hh"
+#include "ContextSubst.hh"
+#include "ChainContextSubst.hh"
+#include "ExtensionSubst.hh"
+#include "ReverseChainSingleSubst.hh"
+
+namespace OT {
+namespace Layout {
+namespace GSUB_impl {
+
+struct SubstLookupSubTable
+{
+ friend struct ::OT::Lookup;
+ friend struct SubstLookup;
+
+ protected:
+ union {
+ SingleSubst single;
+ MultipleSubst multiple;
+ AlternateSubst alternate;
+ LigatureSubst ligature;
+ ContextSubst context;
+ ChainContextSubst chainContext;
+ ExtensionSubst extension;
+ ReverseChainSingleSubst reverseChainContextSingle;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (0);
+
+ enum Type {
+ Single = 1,
+ Multiple = 2,
+ Alternate = 3,
+ Ligature = 4,
+ Context = 5,
+ ChainContext = 6,
+ Extension = 7,
+ ReverseChainSingle = 8
+ };
+
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, lookup_type);
+ switch (lookup_type) {
+ case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
+ case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
+ case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
+ case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
+ case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
+ case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
+ case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
+ case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
+ {
+ hb_intersects_context_t c (glyphs);
+ return dispatch (&c, lookup_type);
+ }
+};
+
+
+}
+}
+}
+
+#endif /* HB_OT_LAYOUT_GSUB_SUBSTLOOKUPSUBTABLE_HH */
diff --git a/thirdparty/harfbuzz/src/OT/Layout/types.hh b/thirdparty/harfbuzz/src/OT/Layout/types.hh
new file mode 100644
index 0000000000..6a43403e94
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/Layout/types.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2007,2008,2009 Red Hat, Inc.
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Red Hat Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Garret Rieger
+ */
+
+#ifndef OT_LAYOUT_TYPES_HH
+#define OT_LAYOUT_TYPES_HH
+
+namespace OT {
+namespace Layout {
+
+struct SmallTypes {
+ static constexpr unsigned size = 2;
+ using large_int = uint32_t;
+ using HBUINT = HBUINT16;
+ using HBGlyphID = HBGlyphID16;
+ using Offset = Offset16;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset16To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array16Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray16Of<Type>;
+};
+
+struct MediumTypes {
+ static constexpr unsigned size = 3;
+ using large_int = uint64_t;
+ using HBUINT = HBUINT24;
+ using HBGlyphID = HBGlyphID24;
+ using Offset = Offset24;
+ template <typename Type, bool has_null=true>
+ using OffsetTo = OT::Offset24To<Type, has_null>;
+ template <typename Type>
+ using ArrayOf = OT::Array24Of<Type>;
+ template <typename Type>
+ using SortedArrayOf = OT::SortedArray24Of<Type>;
+};
+
+}
+}
+
+#endif /* OT_LAYOUT_TYPES_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
new file mode 100644
index 0000000000..98c2ee4e73
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
@@ -0,0 +1,298 @@
+#ifndef OT_GLYF_COMPOSITEGLYPH_HH
+#define OT_GLYF_COMPOSITEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct CompositeGlyphRecord
+{
+ protected:
+ enum composite_glyph_flag_t
+ {
+ ARG_1_AND_2_ARE_WORDS = 0x0001,
+ ARGS_ARE_XY_VALUES = 0x0002,
+ ROUND_XY_TO_GRID = 0x0004,
+ WE_HAVE_A_SCALE = 0x0008,
+ MORE_COMPONENTS = 0x0020,
+ WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
+ WE_HAVE_A_TWO_BY_TWO = 0x0080,
+ WE_HAVE_INSTRUCTIONS = 0x0100,
+ USE_MY_METRICS = 0x0200,
+ OVERLAP_COMPOUND = 0x0400,
+ SCALED_COMPONENT_OFFSET = 0x0800,
+ UNSCALED_COMPONENT_OFFSET = 0x1000,
+#ifndef HB_NO_BEYOND_64K
+ GID_IS_24BIT = 0x2000
+#endif
+ };
+
+ public:
+ unsigned int get_size () const
+ {
+ unsigned int size = min_size;
+ /* glyphIndex is 24bit instead of 16bit */
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT) size += HBGlyphID24::static_size - HBGlyphID16::static_size;
+#endif
+ /* arg1 and 2 are int16 */
+ if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
+ /* arg1 and 2 are int8 */
+ else size += 2;
+
+ /* One x 16 bit (scale) */
+ if (flags & WE_HAVE_A_SCALE) size += 2;
+ /* Two x 16 bit (xscale, yscale) */
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
+ /* Four x 16 bit (xscale, scale01, scale10, yscale) */
+ else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
+
+ return size;
+ }
+
+ void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
+ void set_overlaps_flag ()
+ {
+ flags = (uint16_t) flags | OVERLAP_COMPOUND;
+ }
+
+ bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
+
+ bool has_more () const { return flags & MORE_COMPONENTS; }
+ bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
+ bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
+ void get_anchor_points (unsigned int &point1, unsigned int &point2) const
+ {
+ const auto *p = &StructAfter<const HBUINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ point1 = ((const HBUINT16 *) p)[0];
+ point2 = ((const HBUINT16 *) p)[1];
+ }
+ else
+ {
+ point1 = p[0];
+ point2 = p[1];
+ }
+ }
+
+ void transform_points (contour_point_vector_t &points) const
+ {
+ float matrix[4];
+ contour_point_t trans;
+ if (get_transformation (matrix, trans))
+ {
+ if (scaled_offsets ())
+ {
+ points.translate (trans);
+ points.transform (matrix);
+ }
+ else
+ {
+ points.transform (matrix);
+ points.translate (trans);
+ }
+ }
+ }
+
+ protected:
+ bool scaled_offsets () const
+ { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
+
+ bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
+ {
+ matrix[0] = matrix[3] = 1.f;
+ matrix[1] = matrix[2] = 0.f;
+
+ const auto *p = &StructAfter<const HBINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+ int tx, ty;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ tx = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ ty = *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ else
+ {
+ tx = *p++;
+ ty = *p++;
+ }
+ if (is_anchored ()) tx = ty = 0;
+
+ trans.init ((float) tx, (float) ty);
+
+ {
+ const F2DOT14 *points = (const F2DOT14 *) p;
+ if (flags & WE_HAVE_A_SCALE)
+ {
+ matrix[0] = matrix[3] = points[0].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[3] = points[1].to_float ();
+ return true;
+ }
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ {
+ matrix[0] = points[0].to_float ();
+ matrix[1] = points[1].to_float ();
+ matrix[2] = points[2].to_float ();
+ matrix[3] = points[3].to_float ();
+ return true;
+ }
+ }
+ return tx || ty;
+ }
+
+ public:
+ hb_codepoint_t get_gid () const
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ return StructAfter<const HBGlyphID24> (flags);
+ else
+#endif
+ return StructAfter<const HBGlyphID16> (flags);
+ }
+ void set_gid (hb_codepoint_t gid)
+ {
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ StructAfter<HBGlyphID24> (flags) = gid;
+ else
+#endif
+ /* TODO assert? */
+ StructAfter<HBGlyphID16> (flags) = gid;
+ }
+
+ protected:
+ HBUINT16 flags;
+ HBUINT24 pad;
+ public:
+ DEFINE_SIZE_MIN (4);
+};
+
+struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphRecord &>
+{
+ typedef const CompositeGlyphRecord *__item_t__;
+ composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
+ glyph (glyph_), current (nullptr), current_size (0)
+ {
+ set_current (current_);
+ }
+
+ composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
+
+ item_t __item__ () const { return *current; }
+ bool __more__ () const { return current; }
+ void __next__ ()
+ {
+ if (!current->has_more ()) { current = nullptr; return; }
+
+ set_current (&StructAtOffset<CompositeGlyphRecord> (current, current_size));
+ }
+ composite_iter_t __end__ () const { return composite_iter_t (); }
+ bool operator != (const composite_iter_t& o) const
+ { return current != o.current; }
+
+
+ void set_current (__item_t__ current_)
+ {
+ if (!glyph.check_range (current_, CompositeGlyphRecord::min_size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+ unsigned size = current_->get_size ();
+ if (!glyph.check_range (current_, size))
+ {
+ current = nullptr;
+ current_size = 0;
+ return;
+ }
+
+ current = current_;
+ current_size = size;
+ }
+
+ private:
+ hb_bytes_t glyph;
+ __item_t__ current;
+ unsigned current_size;
+};
+
+struct CompositeGlyph
+{
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ composite_iter_t iter () const
+ { return composite_iter_t (bytes, &StructAfter<CompositeGlyphRecord, GlyphHeader> (header)); }
+
+ unsigned int instructions_length (hb_bytes_t bytes) const
+ {
+ unsigned int start = bytes.length;
+ unsigned int end = bytes.length;
+ const CompositeGlyphRecord *last = nullptr;
+ for (auto &item : iter ())
+ last = &item;
+ if (unlikely (!last)) return 0;
+
+ if (last->has_instructions ())
+ start = (char *) last - &bytes + last->get_size ();
+ if (unlikely (start > end)) return 0;
+ return end - start;
+ }
+
+ /* Trimming for composites not implemented.
+ * If removing hints it falls out of that. */
+ const hb_bytes_t trim_padding () const { return bytes; }
+
+ void drop_hints ()
+ {
+ for (const auto &_ : iter ())
+ const_cast<CompositeGlyphRecord &> (_).drop_instructions_flag ();
+ }
+
+ /* Chop instructions off the end */
+ void drop_hints_bytes (hb_bytes_t &dest_start) const
+ { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
+
+ void set_overlaps_flag ()
+ {
+ CompositeGlyphRecord& glyph_chain = const_cast<CompositeGlyphRecord &> (
+ StructAfter<CompositeGlyphRecord, GlyphHeader> (header));
+ if (!bytes.check_range(&glyph_chain, CompositeGlyphRecord::min_size))
+ return;
+ glyph_chain.set_overlaps_flag ();
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_COMPOSITEGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
new file mode 100644
index 0000000000..3efe538f37
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
@@ -0,0 +1,235 @@
+#ifndef OT_GLYF_GLYPH_HH
+#define OT_GLYF_GLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+#include "GlyphHeader.hh"
+#include "SimpleGlyph.hh"
+#include "CompositeGlyph.hh"
+
+
+namespace OT {
+
+struct glyf_accelerator_t;
+
+namespace glyf_impl {
+
+
+enum phantom_point_index_t
+{
+ PHANTOM_LEFT = 0,
+ PHANTOM_RIGHT = 1,
+ PHANTOM_TOP = 2,
+ PHANTOM_BOTTOM = 3,
+ PHANTOM_COUNT = 4
+};
+
+struct Glyph
+{
+ enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
+
+ public:
+ composite_iter_t get_composite_iterator () const
+ {
+ if (type != COMPOSITE) return composite_iter_t ();
+ return CompositeGlyph (*header, bytes).iter ();
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ switch (type) {
+ case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
+ case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
+ default: return bytes;
+ }
+ }
+
+ void drop_hints ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
+ default: return;
+ }
+ }
+
+ void set_overlaps_flag ()
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
+ default: return;
+ }
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ switch (type) {
+ case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
+ case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
+ default: return;
+ }
+ }
+
+ /* Note: Recursively calls itself.
+ * all_points includes phantom points
+ */
+ template <typename accelerator_t>
+ bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
+ contour_point_vector_t &all_points /* OUT */,
+ bool phantom_only = false,
+ unsigned int depth = 0) const
+ {
+ if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
+ contour_point_vector_t stack_points;
+ bool inplace = type == SIMPLE && all_points.length == 0;
+ /* Load into all_points if it's empty, as an optimization. */
+ contour_point_vector_t &points = inplace ? all_points : stack_points;
+
+ switch (type) {
+ case COMPOSITE:
+ {
+ /* pseudo component points for each component in composite glyph */
+ unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
+ if (unlikely (!points.resize (num_points))) return false;
+ break;
+ }
+ case SIMPLE:
+ if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
+ return false;
+ break;
+ }
+
+ /* Init phantom points */
+ if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
+ hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
+ {
+ int lsb = 0;
+ int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
+ (int) header->xMin - lsb : 0;
+ int tsb = 0;
+ int v_orig = (int) header->yMax +
+#ifndef HB_NO_VERTICAL
+ ((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
+#else
+ 0
+#endif
+ ;
+ unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid);
+ unsigned v_adv =
+#ifndef HB_NO_VERTICAL
+ glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid)
+#else
+ - font->face->get_upem ()
+#endif
+ ;
+ phantoms[PHANTOM_LEFT].x = h_delta;
+ phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
+ phantoms[PHANTOM_TOP].y = v_orig;
+ phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
+ }
+
+#ifndef HB_NO_VAR
+ glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
+#endif
+
+ switch (type) {
+ case SIMPLE:
+ if (!inplace)
+ all_points.extend (points.as_array ());
+ break;
+ case COMPOSITE:
+ {
+ contour_point_vector_t comp_points;
+ unsigned int comp_index = 0;
+ for (auto &item : get_composite_iterator ())
+ {
+ comp_points.reset ();
+ if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
+ .get_points (font, glyf_accelerator, comp_points,
+ phantom_only, depth + 1)))
+ return false;
+
+ /* Copy phantom points from component if USE_MY_METRICS flag set */
+ if (item.is_use_my_metrics ())
+ for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
+ phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
+
+ /* Apply component transformation & translation */
+ item.transform_points (comp_points);
+
+ /* Apply translation from gvar */
+ comp_points.translate (points[comp_index]);
+
+ if (item.is_anchored ())
+ {
+ unsigned int p1, p2;
+ item.get_anchor_points (p1, p2);
+ if (likely (p1 < all_points.length && p2 < comp_points.length))
+ {
+ contour_point_t delta;
+ delta.init (all_points[p1].x - comp_points[p2].x,
+ all_points[p1].y - comp_points[p2].y);
+
+ comp_points.translate (delta);
+ }
+ }
+
+ all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
+
+ comp_index++;
+ }
+
+ all_points.extend (phantoms);
+ } break;
+ default:
+ all_points.extend (phantoms);
+ }
+
+ if (depth == 0) /* Apply at top level */
+ {
+ /* Undocumented rasterizer behavior:
+ * Shift points horizontally by the updated left side bearing
+ */
+ contour_point_t delta;
+ delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
+ if (delta.x) all_points.translate (delta);
+ }
+
+ return !all_points.in_error ();
+ }
+
+ bool get_extents_without_var_scaled (hb_font_t *font, const glyf_accelerator_t &glyf_accelerator,
+ hb_glyph_extents_t *extents) const
+ {
+ if (type == EMPTY) return true; /* Empty glyph; zero extents. */
+ return header->get_extents_without_var_scaled (font, glyf_accelerator, gid, extents);
+ }
+
+ hb_bytes_t get_bytes () const { return bytes; }
+
+ Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
+ hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
+ header (bytes.as<GlyphHeader> ()),
+ gid (gid_)
+ {
+ int num_contours = header->numberOfContours;
+ if (unlikely (num_contours == 0)) type = EMPTY;
+ else if (num_contours > 0) type = SIMPLE;
+ else type = COMPOSITE; /* negative numbers */
+ }
+
+ protected:
+ hb_bytes_t bytes;
+ const GlyphHeader *header;
+ hb_codepoint_t gid;
+ unsigned type;
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh
new file mode 100644
index 0000000000..e4a9168b79
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/GlyphHeader.hh
@@ -0,0 +1,50 @@
+#ifndef OT_GLYF_GLYPHHEADER_HH
+#define OT_GLYF_GLYPHHEADER_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct GlyphHeader
+{
+ bool has_data () const { return numberOfContours; }
+
+ template <typename accelerator_t>
+ bool get_extents_without_var_scaled (hb_font_t *font, const accelerator_t &glyf_accelerator,
+ hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
+ /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
+ int lsb = hb_min (xMin, xMax);
+ (void) glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
+ extents->x_bearing = font->em_scale_x (lsb);
+ extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
+ extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
+ extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
+
+ return true;
+ }
+
+ HBINT16 numberOfContours;
+ /* If the number of contours is
+ * greater than or equal to zero,
+ * this is a simple glyph; if negative,
+ * this is a composite glyph. */
+ FWORD xMin; /* Minimum x for coordinate data. */
+ FWORD yMin; /* Minimum y for coordinate data. */
+ FWORD xMax; /* Maximum x for coordinate data. */
+ FWORD yMax; /* Maximum y for coordinate data. */
+ public:
+ DEFINE_SIZE_STATIC (10);
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYPHHEADER_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
new file mode 100644
index 0000000000..6df978cf13
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
@@ -0,0 +1,216 @@
+#ifndef OT_GLYF_SIMPLEGLYPH_HH
+#define OT_GLYF_SIMPLEGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct SimpleGlyph
+{
+ enum simple_glyph_flag_t
+ {
+ FLAG_ON_CURVE = 0x01,
+ FLAG_X_SHORT = 0x02,
+ FLAG_Y_SHORT = 0x04,
+ FLAG_REPEAT = 0x08,
+ FLAG_X_SAME = 0x10,
+ FLAG_Y_SAME = 0x20,
+ FLAG_OVERLAP_SIMPLE = 0x40,
+ FLAG_RESERVED2 = 0x80
+ };
+
+ const GlyphHeader &header;
+ hb_bytes_t bytes;
+ SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
+ header (header_), bytes (bytes_) {}
+
+ unsigned int instruction_len_offset () const
+ { return GlyphHeader::static_size + 2 * header.numberOfContours; }
+
+ unsigned int length (unsigned int instruction_len) const
+ { return instruction_len_offset () + 2 + instruction_len; }
+
+ unsigned int instructions_length () const
+ {
+ unsigned int instruction_length_offset = instruction_len_offset ();
+ if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
+
+ const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
+ /* Out of bounds of the current glyph */
+ if (unlikely (length (instructionLength) > bytes.length)) return 0;
+ return instructionLength;
+ }
+
+ const hb_bytes_t trim_padding () const
+ {
+ /* based on FontTools _g_l_y_f.py::trim */
+ const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
+ const uint8_t *glyph_end = glyph + bytes.length;
+ /* simple glyph w/contours, possibly trimmable */
+ glyph += instruction_len_offset ();
+
+ if (unlikely (glyph + 2 >= glyph_end)) return hb_bytes_t ();
+ unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
+ unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
+
+ glyph += 2 + num_instructions;
+
+ unsigned int coord_bytes = 0;
+ unsigned int coords_with_flags = 0;
+ while (glyph < glyph_end)
+ {
+ uint8_t flag = *glyph;
+ glyph++;
+
+ unsigned int repeat = 1;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (glyph >= glyph_end)) return hb_bytes_t ();
+ repeat = *glyph + 1;
+ glyph++;
+ }
+
+ unsigned int xBytes, yBytes;
+ xBytes = yBytes = 0;
+ if (flag & FLAG_X_SHORT) xBytes = 1;
+ else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
+
+ if (flag & FLAG_Y_SHORT) yBytes = 1;
+ else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
+
+ coord_bytes += (xBytes + yBytes) * repeat;
+ coords_with_flags += repeat;
+ if (coords_with_flags >= num_coordinates) break;
+ }
+
+ if (unlikely (coords_with_flags != num_coordinates)) return hb_bytes_t ();
+ return bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph));
+ }
+
+ /* zero instruction length */
+ void drop_hints ()
+ {
+ GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
+ (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
+ }
+
+ void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
+ {
+ unsigned int instructions_len = instructions_length ();
+ unsigned int glyph_length = length (instructions_len);
+ dest_start = bytes.sub_array (0, glyph_length - instructions_len);
+ dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
+ }
+
+ void set_overlaps_flag ()
+ {
+ if (unlikely (!header.numberOfContours)) return;
+
+ unsigned flags_offset = length (instructions_length ());
+ if (unlikely (flags_offset + 1 > bytes.length)) return;
+
+ HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
+ first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
+ }
+
+ static bool read_flags (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end)
+ {
+ unsigned count = points_.length;
+ for (unsigned int i = 0; i < count;)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ uint8_t flag = *p++;
+ points_.arrayZ[i++].flag = flag;
+ if (flag & FLAG_REPEAT)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ unsigned int repeat_count = *p++;
+ unsigned stop = hb_min (i + repeat_count, count);
+ for (; i < stop;)
+ points_.arrayZ[i++].flag = flag;
+ }
+ }
+ return true;
+ }
+
+ static bool read_points (const HBUINT8 *&p /* IN/OUT */,
+ contour_point_vector_t &points_ /* IN/OUT */,
+ const HBUINT8 *end,
+ float contour_point_t::*m,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag)
+ {
+ int v = 0;
+
+ unsigned count = points_.length;
+ for (unsigned i = 0; i < count; i++)
+ {
+ unsigned flag = points_[i].flag;
+ if (flag & short_flag)
+ {
+ if (unlikely (p + 1 > end)) return false;
+ if (flag & same_flag)
+ v += *p++;
+ else
+ v -= *p++;
+ }
+ else
+ {
+ if (!(flag & same_flag))
+ {
+ if (unlikely (p + HBINT16::static_size > end)) return false;
+ v += *(const HBINT16 *) p;
+ p += HBINT16::static_size;
+ }
+ }
+ points_.arrayZ[i].*m = v;
+ }
+ return true;
+ }
+
+ bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
+ bool phantom_only = false) const
+ {
+ const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
+ int num_contours = header.numberOfContours;
+ assert (num_contours);
+ /* One extra item at the end, for the instruction-count below. */
+ if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours]))) return false;
+ unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
+
+ points_.alloc (num_points + 4); // Allocate for phantom points, to avoid a possible copy
+ if (!points_.resize (num_points)) return false;
+ if (phantom_only) return true;
+
+ for (int i = 0; i < num_contours; i++)
+ points_[endPtsOfContours[i]].is_end_point = true;
+
+ /* Skip instructions */
+ const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
+ endPtsOfContours[num_contours]);
+
+ if (unlikely ((const char *) p < bytes.arrayZ)) return false; /* Unlikely overflow */
+ const HBUINT8 *end = (const HBUINT8 *) (bytes.arrayZ + bytes.length);
+ if (unlikely (p >= end)) return false;
+
+ /* Read x & y coordinates */
+ return read_flags (p, points_, end)
+ && read_points (p, points_, end, &contour_point_t::x,
+ FLAG_X_SHORT, FLAG_X_SAME)
+ && read_points (p, points_, end, &contour_point_t::y,
+ FLAG_Y_SHORT, FLAG_Y_SAME);
+ }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SIMPLEGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
new file mode 100644
index 0000000000..7ae8fe3078
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
@@ -0,0 +1,72 @@
+#ifndef OT_GLYF_SUBSETGLYPH_HH
+#define OT_GLYF_SUBSETGLYPH_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct SubsetGlyph
+{
+ hb_codepoint_t new_gid;
+ hb_codepoint_t old_gid;
+ Glyph source_glyph;
+ hb_bytes_t dest_start; /* region of source_glyph to copy first */
+ hb_bytes_t dest_end; /* region of source_glyph to copy second */
+
+ bool serialize (hb_serialize_context_t *c,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan) const
+ {
+ TRACE_SERIALIZE (this);
+
+ hb_bytes_t dest_glyph = dest_start.copy (c);
+ dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
+ unsigned int pad_length = use_short_loca ? padding () : 0;
+ DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
+
+ HBUINT8 pad;
+ pad = 0;
+ while (pad_length > 0)
+ {
+ c->embed (pad);
+ pad_length--;
+ }
+
+ if (unlikely (!dest_glyph.length)) return_trace (true);
+
+ /* update components gids */
+ for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
+ {
+ hb_codepoint_t new_gid;
+ if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
+ const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
+ }
+
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ Glyph (dest_glyph).drop_hints ();
+
+ if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
+ Glyph (dest_glyph).set_overlaps_flag ();
+
+ return_trace (true);
+ }
+
+ void drop_hints_bytes ()
+ { source_glyph.drop_hints_bytes (dest_start, dest_end); }
+
+ unsigned int length () const { return dest_start.length + dest_end.length; }
+ /* pad to 2 to ensure 2-byte loca will be ok */
+ unsigned int padding () const { return length () % 2; }
+ unsigned int padded_size () const { return length () + padding (); }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_SUBSETGLYPH_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
new file mode 100644
index 0000000000..f51f7a81fc
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
@@ -0,0 +1,90 @@
+#ifndef OT_GLYF_GLYF_HELPERS_HH
+#define OT_GLYF_GLYF_HELPERS_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-subset-plan.hh"
+
+#include "loca.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+template<typename IteratorIn, typename IteratorOut,
+ hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
+ hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
+static void
+_write_loca (IteratorIn it, bool short_offsets, IteratorOut dest)
+{
+ unsigned right_shift = short_offsets ? 1 : 0;
+ unsigned int offset = 0;
+ dest << 0;
+ + it
+ | hb_map ([=, &offset] (unsigned int padded_size)
+ {
+ offset += padded_size;
+ DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
+ return offset >> right_shift;
+ })
+ | hb_sink (dest)
+ ;
+}
+
+static bool
+_add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
+{
+ hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
+ hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
+ hb_blob_destroy (head_blob);
+
+ if (unlikely (!head_prime_blob))
+ return false;
+
+ head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
+ head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
+ bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
+
+ hb_blob_destroy (head_prime_blob);
+ return success;
+}
+
+template<typename Iterator,
+ hb_requires (hb_is_source_of (Iterator, unsigned int))>
+static bool
+_add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
+{
+ unsigned num_offsets = padded_offsets.len () + 1;
+ unsigned entry_size = use_short_loca ? 2 : 4;
+ char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
+
+ if (unlikely (!loca_prime_data)) return false;
+
+ DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
+ entry_size, num_offsets, entry_size * num_offsets);
+
+ if (use_short_loca)
+ _write_loca (padded_offsets, true, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
+ else
+ _write_loca (padded_offsets, false, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
+
+ hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
+ entry_size * num_offsets,
+ HB_MEMORY_MODE_WRITABLE,
+ loca_prime_data,
+ hb_free);
+
+ bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
+ && _add_head_and_set_loca_version (plan, use_short_loca);
+
+ hb_blob_destroy (loca_blob);
+ return result;
+}
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HELPERS_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
new file mode 100644
index 0000000000..bcaf44fc1e
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
@@ -0,0 +1,397 @@
+#ifndef OT_GLYF_GLYF_HH
+#define OT_GLYF_GLYF_HH
+
+
+#include "../../hb-open-type.hh"
+#include "../../hb-ot-head-table.hh"
+#include "../../hb-ot-hmtx-table.hh"
+#include "../../hb-ot-var-gvar-table.hh"
+#include "../../hb-draw.hh"
+
+#include "glyf-helpers.hh"
+#include "Glyph.hh"
+#include "SubsetGlyph.hh"
+#include "loca.hh"
+#include "path-builder.hh"
+
+
+namespace OT {
+
+
+/*
+ * glyf -- TrueType Glyph Data
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
+ */
+#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
+
+
+struct glyf
+{
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ /* Runtime checks as eager sanitizing each glyph is costy */
+ return_trace (true);
+ }
+
+ /* requires source of SubsetGlyph complains the identifier isn't declared */
+ template <typename Iterator>
+ bool serialize (hb_serialize_context_t *c,
+ Iterator it,
+ bool use_short_loca,
+ const hb_subset_plan_t *plan)
+ {
+ TRACE_SERIALIZE (this);
+ unsigned init_len = c->length ();
+ for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
+
+ /* As a special case when all glyph in the font are empty, add a zero byte
+ * to the table, so that OTS doesn’t reject it, and to make the table work
+ * on Windows as well.
+ * See https://github.com/khaledhosny/ots/issues/52 */
+ if (init_len == c->length ())
+ {
+ HBUINT8 empty_byte;
+ empty_byte = 0;
+ c->copy (empty_byte);
+ }
+ return_trace (true);
+ }
+
+ /* Byte region(s) per glyph to output
+ unpadded, hints removed if so requested
+ If we fail to process a glyph we produce an empty (0-length) glyph */
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ glyf *glyf_prime = c->serializer->start_embed <glyf> ();
+ if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
+
+ hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
+ _populate_subset_glyphs (c->plan, &glyphs);
+
+ auto padded_offsets =
+ + hb_iter (glyphs)
+ | hb_map (&glyf_impl::SubsetGlyph::padded_size)
+ ;
+
+ unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
+ bool use_short_loca = max_offset < 0x1FFFF;
+
+
+ glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
+ if (!use_short_loca) {
+ padded_offsets =
+ + hb_iter (glyphs)
+ | hb_map (&glyf_impl::SubsetGlyph::length)
+ ;
+ }
+
+
+ if (unlikely (c->serializer->in_error ())) return_trace (false);
+ return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
+ padded_offsets,
+ use_short_loca)));
+ }
+
+ void
+ _populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Glyphs data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+struct glyf_accelerator_t
+{
+ glyf_accelerator_t (hb_face_t *face)
+ {
+ short_offset = false;
+ num_glyphs = 0;
+ loca_table = nullptr;
+ glyf_table = nullptr;
+#ifndef HB_NO_VAR
+ gvar = nullptr;
+#endif
+ hmtx = nullptr;
+#ifndef HB_NO_VERTICAL
+ vmtx = nullptr;
+#endif
+ const OT::head &head = *face->table.head;
+ if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
+ /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
+ return;
+ short_offset = 0 == head.indexToLocFormat;
+
+ loca_table = face->table.loca.get_blob (); // Needs no destruct!
+ glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
+#ifndef HB_NO_VAR
+ gvar = face->table.gvar;
+#endif
+ hmtx = face->table.hmtx;
+#ifndef HB_NO_VERTICAL
+ vmtx = face->table.vmtx;
+#endif
+
+ num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
+ num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
+ }
+ ~glyf_accelerator_t ()
+ {
+ glyf_table.destroy ();
+ }
+
+ bool has_data () const { return num_glyphs; }
+
+ protected:
+ template<typename T>
+ bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
+ {
+ if (gid >= num_glyphs) return false;
+
+ /* Making this allocfree is not that easy
+ https://github.com/harfbuzz/harfbuzz/issues/2095
+ mostly because of gvar handling in VF fonts,
+ perhaps a separate path for non-VF fonts can be considered */
+ contour_point_vector_t all_points;
+
+ bool phantom_only = !consumer.is_consuming_contour_points ();
+ if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
+ return false;
+
+ if (consumer.is_consuming_contour_points ())
+ {
+ unsigned count = all_points.length;
+ assert (count >= glyf_impl::PHANTOM_COUNT);
+ count -= glyf_impl::PHANTOM_COUNT;
+ for (unsigned point_index = 0; point_index < count; point_index++)
+ consumer.consume_point (all_points[point_index]);
+ consumer.points_end ();
+ }
+
+ /* Where to write phantoms, nullptr if not requested */
+ contour_point_t *phantoms = consumer.get_phantoms_sink ();
+ if (phantoms)
+ for (unsigned i = 0; i < glyf_impl::PHANTOM_COUNT; ++i)
+ phantoms[i] = all_points[all_points.length - glyf_impl::PHANTOM_COUNT + i];
+
+ return true;
+ }
+
+#ifndef HB_NO_VAR
+ struct points_aggregator_t
+ {
+ hb_font_t *font;
+ hb_glyph_extents_t *extents;
+ contour_point_t *phantoms;
+ bool scaled;
+
+ struct contour_bounds_t
+ {
+ contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
+
+ void add (const contour_point_t &p)
+ {
+ min_x = hb_min (min_x, p.x);
+ min_y = hb_min (min_y, p.y);
+ max_x = hb_max (max_x, p.x);
+ max_y = hb_max (max_y, p.y);
+ }
+
+ bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
+
+ void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scaled)
+ {
+ if (unlikely (empty ()))
+ {
+ extents->width = 0;
+ extents->x_bearing = 0;
+ extents->height = 0;
+ extents->y_bearing = 0;
+ return;
+ }
+ if (scaled)
+ {
+ extents->x_bearing = font->em_scalef_x (min_x);
+ extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
+ extents->y_bearing = font->em_scalef_y (max_y);
+ extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
+ }
+ else
+ {
+ extents->x_bearing = roundf (min_x);
+ extents->width = roundf (max_x - extents->x_bearing);
+ extents->y_bearing = roundf (max_y);
+ extents->height = roundf (min_y - extents->y_bearing);
+ }
+ }
+
+ protected:
+ float min_x, min_y, max_x, max_y;
+ } bounds;
+
+ points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_, bool scaled_)
+ {
+ font = font_;
+ extents = extents_;
+ phantoms = phantoms_;
+ scaled = scaled_;
+ if (extents) bounds = contour_bounds_t ();
+ }
+
+ void consume_point (const contour_point_t &point) { bounds.add (point); }
+ void points_end () { bounds.get_extents (font, extents, scaled); }
+
+ bool is_consuming_contour_points () { return extents; }
+ contour_point_t *get_phantoms_sink () { return phantoms; }
+ };
+
+ public:
+ unsigned
+ get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
+ {
+ if (unlikely (gid >= num_glyphs)) return 0;
+
+ bool success = false;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (font->num_coords)
+ success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false));
+
+ if (unlikely (!success))
+ return
+#ifndef HB_NO_VERTICAL
+ is_vertical ? vmtx->get_advance_without_var_unscaled (gid) :
+#endif
+ hmtx->get_advance_without_var_unscaled (gid);
+
+ float result = is_vertical
+ ? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y
+ : phantoms[glyf_impl::PHANTOM_RIGHT].x - phantoms[glyf_impl::PHANTOM_LEFT].x;
+ return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
+ }
+
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+ hb_glyph_extents_t extents;
+
+ contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
+ if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false))))
+ return false;
+
+ *lsb = is_vertical
+ ? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
+ : roundf (phantoms[glyf_impl::PHANTOM_LEFT].x);
+ return true;
+ }
+#endif
+
+ public:
+ bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
+ {
+ if (unlikely (gid >= num_glyphs)) return false;
+
+#ifndef HB_NO_VAR
+ if (font->num_coords)
+ return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true));
+#endif
+ return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
+ }
+
+ const glyf_impl::Glyph
+ glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
+ {
+ if (unlikely (gid >= num_glyphs)) return glyf_impl::Glyph ();
+
+ unsigned int start_offset, end_offset;
+
+ if (short_offset)
+ {
+ const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
+ start_offset = 2 * offsets[gid];
+ end_offset = 2 * offsets[gid + 1];
+ }
+ else
+ {
+ const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
+ start_offset = offsets[gid];
+ end_offset = offsets[gid + 1];
+ }
+
+ if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
+ return glyf_impl::Glyph ();
+
+ glyf_impl::Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
+ end_offset - start_offset), gid);
+ return needs_padding_removal ? glyf_impl::Glyph (glyph.trim_padding (), gid) : glyph;
+ }
+
+ bool
+ get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
+ { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); }
+
+#ifndef HB_NO_VAR
+ const gvar_accelerator_t *gvar;
+#endif
+ const hmtx_accelerator_t *hmtx;
+#ifndef HB_NO_VERTICAL
+ const vmtx_accelerator_t *vmtx;
+#endif
+
+ private:
+ bool short_offset;
+ unsigned int num_glyphs;
+ hb_blob_ptr_t<loca> loca_table;
+ hb_blob_ptr_t<glyf> glyf_table;
+};
+
+
+inline void
+glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
+ hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
+{
+ OT::glyf_accelerator_t glyf (plan->source);
+
+ + hb_range (plan->num_output_glyphs ())
+ | hb_map ([&] (hb_codepoint_t new_gid)
+ {
+ glyf_impl::SubsetGlyph subset_glyph = {0};
+ subset_glyph.new_gid = new_gid;
+
+ /* should never fail: all old gids should be mapped */
+ if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
+ return subset_glyph;
+
+ if (new_gid == 0 &&
+ !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
+ subset_glyph.source_glyph = glyf_impl::Glyph ();
+ else
+ subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
+ if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
+ subset_glyph.drop_hints_bytes ();
+ else
+ subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
+ return subset_glyph;
+ })
+ | hb_sink (glyphs)
+ ;
+}
+
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_GLYF_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/loca.hh b/thirdparty/harfbuzz/src/OT/glyf/loca.hh
new file mode 100644
index 0000000000..4481cba8ed
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/loca.hh
@@ -0,0 +1,43 @@
+#ifndef OT_GLYF_LOCA_HH
+#define OT_GLYF_LOCA_HH
+
+
+#include "../../hb-open-type.hh"
+
+
+namespace OT {
+
+
+/*
+ * loca -- Index to Location
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
+ */
+#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
+
+struct loca
+{
+ friend struct glyf;
+ friend struct glyf_accelerator_t;
+
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
+
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (true);
+ }
+
+ protected:
+ UnsizedArrayOf<HBUINT8>
+ dataZ; /* Location data. */
+ public:
+ DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
+ * check the size externally, allow Null() object of it by
+ * defining it _MIN instead. */
+};
+
+
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_LOCA_HH */
diff --git a/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh b/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh
new file mode 100644
index 0000000000..9bfc45a1a6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/OT/glyf/path-builder.hh
@@ -0,0 +1,135 @@
+#ifndef OT_GLYF_PATH_BUILDER_HH
+#define OT_GLYF_PATH_BUILDER_HH
+
+
+#include "../../hb.hh"
+
+
+namespace OT {
+namespace glyf_impl {
+
+
+struct path_builder_t
+{
+ hb_font_t *font;
+ hb_draw_session_t *draw_session;
+
+ struct optional_point_t
+ {
+ optional_point_t () {}
+ optional_point_t (float x_, float y_) : has_data (true), x (x_), y (y_) {}
+ operator bool () const { return has_data; }
+
+ bool has_data = false;
+ float x = 0.;
+ float y = 0.;
+
+ optional_point_t lerp (optional_point_t p, float t)
+ { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
+ } first_oncurve, first_offcurve, last_offcurve;
+
+ path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
+ {
+ font = font_;
+ draw_session = &draw_session_;
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ }
+
+ /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
+ See also:
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
+ * https://stackoverflow.com/a/20772557 */
+ void consume_point (const contour_point_t &point)
+ {
+ bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
+ optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
+ if (!first_oncurve)
+ {
+ if (is_on_curve)
+ {
+ first_oncurve = p;
+ draw_session->move_to (p.x, p.y);
+ }
+ else
+ {
+ if (first_offcurve)
+ {
+ optional_point_t mid = first_offcurve.lerp (p, .5f);
+ first_oncurve = mid;
+ last_offcurve = p;
+ draw_session->move_to (mid.x, mid.y);
+ }
+ else
+ first_offcurve = p;
+ }
+ }
+ else
+ {
+ if (last_offcurve)
+ {
+ if (is_on_curve)
+ {
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ p.x, p.y);
+ last_offcurve = optional_point_t ();
+ }
+ else
+ {
+ optional_point_t mid = last_offcurve.lerp (p, .5f);
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = p;
+ }
+ }
+ else
+ {
+ if (is_on_curve)
+ draw_session->line_to (p.x, p.y);
+ else
+ last_offcurve = p;
+ }
+ }
+
+ if (point.is_end_point)
+ {
+ if (first_offcurve && last_offcurve)
+ {
+ optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ mid.x, mid.y);
+ last_offcurve = optional_point_t ();
+ /* now check the rest */
+ }
+
+ if (first_offcurve && first_oncurve)
+ draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else if (last_offcurve && first_oncurve)
+ draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
+ first_oncurve.x, first_oncurve.y);
+ else if (first_oncurve)
+ draw_session->line_to (first_oncurve.x, first_oncurve.y);
+ else if (first_offcurve)
+ {
+ float x = first_offcurve.x, y = first_offcurve.y;
+ draw_session->move_to (x, y);
+ draw_session->quadratic_to (x, y, x, y);
+ }
+
+ /* Getting ready for the next contour */
+ first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
+ draw_session->close_path ();
+ }
+ }
+ void points_end () {}
+
+ bool is_consuming_contour_points () { return true; }
+ contour_point_t *get_phantoms_sink () { return nullptr; }
+};
+
+
+} /* namespace glyf_impl */
+} /* namespace OT */
+
+
+#endif /* OT_GLYF_PATH_BUILDER_HH */
diff --git a/thirdparty/harfbuzz/src/graph/coverage-graph.hh b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
new file mode 100644
index 0000000000..1d9fd0eb5b
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/coverage-graph.hh
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../OT/Layout/Common/Coverage.hh"
+
+#ifndef GRAPH_COVERAGE_GRAPH_HH
+#define GRAPH_COVERAGE_GRAPH_HH
+
+namespace graph {
+
+struct CoverageFormat1 : public OT::Layout::Common::CoverageFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + glyphArray.get_size () - glyphArray.len.get_size ();
+ }
+};
+
+struct CoverageFormat2 : public OT::Layout::Common::CoverageFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ constexpr unsigned min_size = OT::Layout::Common::CoverageFormat2_4<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+ return vertex_len >= min_size + rangeRecord.get_size () - rangeRecord.len.get_size ();
+ }
+};
+
+struct Coverage : public OT::Layout::Common::Coverage
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Layout::Common::Coverage::min_size) return false;
+ switch (u.format)
+ {
+ case 1: return ((CoverageFormat1*)this)->sanitize (vertex);
+ case 2: return ((CoverageFormat2*)this)->sanitize (vertex);
+#ifndef HB_NO_BORING_EXPANSION
+ // Not currently supported
+ case 3:
+ case 4:
+#endif
+ default: return false;
+ }
+ }
+};
+
+
+}
+
+#endif // GRAPH_COVERAGE_GRAPH_HH
diff --git a/thirdparty/harfbuzz/src/graph/graph.hh b/thirdparty/harfbuzz/src/graph/graph.hh
new file mode 100644
index 0000000000..b3aef558a2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/graph.hh
@@ -0,0 +1,1046 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "../hb-set.hh"
+#include "../hb-priority-queue.hh"
+#include "../hb-serialize.hh"
+
+#ifndef GRAPH_GRAPH_HH
+#define GRAPH_GRAPH_HH
+
+namespace graph {
+
+/**
+ * Represents a serialized table in the form of a graph.
+ * Provides methods for modifying and reordering the graph.
+ */
+struct graph_t
+{
+ struct vertex_t
+ {
+ hb_serialize_context_t::object_t obj;
+ int64_t distance = 0 ;
+ int64_t space = 0 ;
+ hb_vector_t<unsigned> parents;
+ unsigned start = 0;
+ unsigned end = 0;
+ unsigned priority = 0;
+
+ friend void swap (vertex_t& a, vertex_t& b)
+ {
+ hb_swap (a.obj, b.obj);
+ hb_swap (a.distance, b.distance);
+ hb_swap (a.space, b.space);
+ hb_swap (a.parents, b.parents);
+ hb_swap (a.start, b.start);
+ hb_swap (a.end, b.end);
+ hb_swap (a.priority, b.priority);
+ }
+
+ bool is_shared () const
+ {
+ return parents.length > 1;
+ }
+
+ unsigned incoming_edges () const
+ {
+ return parents.length;
+ }
+
+ void remove_parent (unsigned parent_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] != parent_index) continue;
+ parents.remove (i);
+ break;
+ }
+ }
+
+ void remove_real_link (unsigned child_index, const void* offset)
+ {
+ for (unsigned i = 0; i < obj.real_links.length; i++)
+ {
+ auto& link = obj.real_links[i];
+ if (link.objidx != child_index)
+ continue;
+
+ if ((obj.head + link.position) != offset)
+ continue;
+
+ obj.real_links.remove (i);
+ return;
+ }
+ }
+
+ void remap_parents (const hb_vector_t<unsigned>& id_map)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ parents[i] = id_map[parents[i]];
+ }
+
+ void remap_parent (unsigned old_index, unsigned new_index)
+ {
+ for (unsigned i = 0; i < parents.length; i++)
+ {
+ if (parents[i] == old_index)
+ parents[i] = new_index;
+ }
+ }
+
+ bool is_leaf () const
+ {
+ return !obj.real_links.length && !obj.virtual_links.length;
+ }
+
+ bool raise_priority ()
+ {
+ if (has_max_priority ()) return false;
+ priority++;
+ return true;
+ }
+
+ bool has_max_priority () const {
+ return priority >= 3;
+ }
+
+ size_t table_size () const {
+ return obj.tail - obj.head;
+ }
+
+ int64_t modified_distance (unsigned order) const
+ {
+ // TODO(garretrieger): once priority is high enough, should try
+ // setting distance = 0 which will force to sort immediately after
+ // it's parent where possible.
+
+ int64_t modified_distance =
+ hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
+ if (has_max_priority ()) {
+ modified_distance = 0;
+ }
+ return (modified_distance << 18) | (0x003FFFF & order);
+ }
+
+ int64_t distance_modifier () const
+ {
+ if (!priority) return 0;
+ int64_t table_size = obj.tail - obj.head;
+
+ if (priority == 1)
+ return -table_size / 2;
+
+ return -table_size;
+ }
+ };
+
+ /*
+ * A topological sorting of an object graph. Ordered
+ * in reverse serialization order (first object in the
+ * serialization is at the end of the list). This matches
+ * the 'packed' object stack used internally in the
+ * serializer
+ */
+ template<typename T>
+ graph_t (const T& objects)
+ : parents_invalid (true),
+ distance_invalid (true),
+ positions_invalid (true),
+ successful (true)
+ {
+ num_roots_for_space_.push (1);
+ bool removed_nil = false;
+ vertices_.alloc (objects.length);
+ vertices_scratch_.alloc (objects.length);
+ for (unsigned i = 0; i < objects.length; i++)
+ {
+ // TODO(grieger): check all links point to valid objects.
+
+ // If this graph came from a serialization buffer object 0 is the
+ // nil object. We don't need it for our purposes here so drop it.
+ if (i == 0 && !objects[i])
+ {
+ removed_nil = true;
+ continue;
+ }
+
+ vertex_t* v = vertices_.push ();
+ if (check_success (!vertices_.in_error ()))
+ v->obj = *objects[i];
+ if (!removed_nil) continue;
+ // Fix indices to account for removed nil object.
+ for (auto& l : v->obj.all_links_writer ()) {
+ l.objidx--;
+ }
+ }
+ }
+
+ ~graph_t ()
+ {
+ vertices_.fini ();
+ }
+
+ bool in_error () const
+ {
+ return !successful ||
+ vertices_.in_error () ||
+ num_roots_for_space_.in_error ();
+ }
+
+ const vertex_t& root () const
+ {
+ return vertices_[root_idx ()];
+ }
+
+ unsigned root_idx () const
+ {
+ // Object graphs are in reverse order, the first object is at the end
+ // of the vector. Since the graph is topologically sorted it's safe to
+ // assume the first object has no incoming edges.
+ return vertices_.length - 1;
+ }
+
+ const hb_serialize_context_t::object_t& object (unsigned i) const
+ {
+ return vertices_[i].obj;
+ }
+
+ /*
+ * Generates a new topological sorting of graph ordered by the shortest
+ * distance to each node if positions are marked as invalid.
+ */
+ void sort_shortest_distance_if_needed ()
+ {
+ if (!positions_invalid) return;
+ sort_shortest_distance ();
+ }
+
+
+ /*
+ * Generates a new topological sorting of graph ordered by the shortest
+ * distance to each node.
+ */
+ void sort_shortest_distance ()
+ {
+ positions_invalid = true;
+
+ if (vertices_.length <= 1) {
+ // Graph of 1 or less doesn't need sorting.
+ return;
+ }
+
+ update_distances ();
+
+ hb_priority_queue_t queue;
+ hb_vector_t<vertex_t> &sorted_graph = vertices_scratch_;
+ if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
+ hb_vector_t<unsigned> id_map;
+ if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
+
+ hb_vector_t<unsigned> removed_edges;
+ if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
+ update_parents ();
+
+ queue.insert (root ().modified_distance (0), root_idx ());
+ int new_id = root_idx ();
+ unsigned order = 1;
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_id = queue.pop_minimum().second;
+
+ hb_swap (sorted_graph[new_id], vertices_[next_id]);
+ const vertex_t& next = sorted_graph[new_id];
+
+ id_map[next_id] = new_id--;
+
+ for (const auto& link : next.obj.all_links ()) {
+ removed_edges[link.objidx]++;
+ if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
+ // Add the order that the links were encountered to the priority.
+ // This ensures that ties between priorities objects are broken in a consistent
+ // way. More specifically this is set up so that if a set of objects have the same
+ // distance they'll be added to the topological order in the order that they are
+ // referenced from the parent object.
+ queue.insert (vertices_[link.objidx].modified_distance (order++),
+ link.objidx);
+ }
+ }
+
+ check_success (!queue.in_error ());
+ check_success (!sorted_graph.in_error ());
+
+ remap_all_obj_indices (id_map, &sorted_graph);
+ hb_swap (vertices_, sorted_graph);
+
+ if (!check_success (new_id == -1))
+ print_orphaned_nodes ();
+ }
+
+ /*
+ * Finds the set of nodes (placed into roots) that should be assigned unique spaces.
+ * More specifically this looks for the top most 24 bit or 32 bit links in the graph.
+ * Some special casing is done that is specific to the layout of GSUB/GPOS tables.
+ */
+ void find_space_roots (hb_set_t& visited, hb_set_t& roots)
+ {
+ int root_index = (int) root_idx ();
+ for (int i = root_index; i >= 0; i--)
+ {
+ if (visited.has (i)) continue;
+
+ // Only real links can form 32 bit spaces
+ for (auto& l : vertices_[i].obj.real_links)
+ {
+ if (l.is_signed || l.width < 3)
+ continue;
+
+ if (i == root_index && l.width == 3)
+ // Ignore 24bit links from the root node, this skips past the single 24bit
+ // pointer to the lookup list.
+ continue;
+
+ if (l.width == 3)
+ {
+ // A 24bit offset forms a root, unless there is 32bit offsets somewhere
+ // in it's subgraph, then those become the roots instead. This is to make sure
+ // that extension subtables beneath a 24bit lookup become the spaces instead
+ // of the offset to the lookup.
+ hb_set_t sub_roots;
+ find_32bit_roots (l.objidx, sub_roots);
+ if (sub_roots) {
+ for (unsigned sub_root_idx : sub_roots) {
+ roots.add (sub_root_idx);
+ find_subgraph (sub_root_idx, visited);
+ }
+ continue;
+ }
+ }
+
+ roots.add (l.objidx);
+ find_subgraph (l.objidx, visited);
+ }
+ }
+ }
+
+ unsigned index_for_offset(unsigned node_idx, const void* offset) const
+ {
+ const auto& node = object (node_idx);
+ if (offset < node.head || offset >= node.tail) return -1;
+
+ for (const auto& link : node.real_links)
+ {
+ if (offset != node.head + link.position)
+ continue;
+ return link.objidx;
+ }
+
+ return -1;
+ }
+
+
+ /*
+ * Assign unique space numbers to each connected subgraph of 24 bit and/or 32 bit offset(s).
+ * Currently, this is implemented specifically tailored to the structure of a GPOS/GSUB
+ * (including with 24bit offsets) table.
+ */
+ bool assign_spaces ()
+ {
+ update_parents ();
+
+ hb_set_t visited;
+ hb_set_t roots;
+ find_space_roots (visited, roots);
+
+ // Mark everything not in the subgraphs of the roots as visited. This prevents
+ // subgraphs from being connected via nodes not in those subgraphs.
+ visited.invert ();
+
+ if (!roots) return false;
+
+ while (roots)
+ {
+ unsigned next = HB_SET_VALUE_INVALID;
+ if (unlikely (!check_success (!roots.in_error ()))) break;
+ if (!roots.next (&next)) break;
+
+ hb_set_t connected_roots;
+ find_connected_nodes (next, roots, visited, connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ isolate_subgraph (connected_roots);
+ if (unlikely (!check_success (!connected_roots.in_error ()))) break;
+
+ unsigned next_space = this->next_space ();
+ num_roots_for_space_.push (0);
+ for (unsigned root : connected_roots)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
+ vertices_[root].space = next_space;
+ num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+
+ // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
+ // into the 32 bit space as needed, instead of using isolation.
+ }
+
+
+
+ return true;
+ }
+
+ /*
+ * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
+ * that originate from outside of the subgraph will be removed by duplicating the linked to
+ * object.
+ *
+ * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
+ */
+ bool isolate_subgraph (hb_set_t& roots)
+ {
+ update_parents ();
+ hb_map_t subgraph;
+
+ // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
+ // set the subgraph incoming edge count to match all of root_idx's incoming edges
+ hb_set_t parents;
+ for (unsigned root_idx : roots)
+ {
+ subgraph.set (root_idx, wide_parents (root_idx, parents));
+ find_subgraph (root_idx, subgraph);
+ }
+
+ unsigned original_root_idx = root_idx ();
+ hb_map_t index_map;
+ bool made_changes = false;
+ for (auto entry : subgraph.iter ())
+ {
+ const auto& node = vertices_[entry.first];
+ unsigned subgraph_incoming_edges = entry.second;
+
+ if (subgraph_incoming_edges < node.incoming_edges ())
+ {
+ // Only de-dup objects with incoming links from outside the subgraph.
+ made_changes = true;
+ duplicate_subgraph (entry.first, index_map);
+ }
+ }
+
+ if (!made_changes)
+ return false;
+
+ if (original_root_idx != root_idx ()
+ && parents.has (original_root_idx))
+ {
+ // If the root idx has changed since parents was determined, update root idx in parents
+ parents.add (root_idx ());
+ parents.del (original_root_idx);
+ }
+
+ auto new_subgraph =
+ + subgraph.keys ()
+ | hb_map([&] (unsigned node_idx) {
+ const unsigned *v;
+ if (index_map.has (node_idx, &v)) return *v;
+ return node_idx;
+ })
+ ;
+
+ remap_obj_indices (index_map, new_subgraph);
+ remap_obj_indices (index_map, parents.iter (), true);
+
+ // Update roots set with new indices as needed.
+ unsigned next = HB_SET_VALUE_INVALID;
+ while (roots.next (&next))
+ {
+ const unsigned *v;
+ if (index_map.has (next, &v))
+ {
+ roots.del (next);
+ roots.add (*v);
+ }
+ }
+
+ return true;
+ }
+
+ void find_subgraph (unsigned node_idx, hb_map_t& subgraph)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ const unsigned *v;
+ if (subgraph.has (link.objidx, &v))
+ {
+ subgraph.set (link.objidx, *v + 1);
+ continue;
+ }
+ subgraph.set (link.objidx, 1);
+ find_subgraph (link.objidx, subgraph);
+ }
+ }
+
+ void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
+ {
+ if (subgraph.has (node_idx)) return;
+ subgraph.add (node_idx);
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ find_subgraph (link.objidx, subgraph);
+ }
+
+ size_t find_subgraph_size (unsigned node_idx, hb_set_t& subgraph, unsigned max_depth = -1)
+ {
+ if (subgraph.has (node_idx)) return 0;
+ subgraph.add (node_idx);
+
+ const auto& o = vertices_[node_idx].obj;
+ size_t size = o.tail - o.head;
+ if (max_depth == 0)
+ return size;
+
+ for (const auto& link : o.all_links ())
+ size += find_subgraph_size (link.objidx, subgraph, max_depth - 1);
+ return size;
+ }
+
+ /*
+ * Finds the topmost children of 32bit offsets in the subgraph starting
+ * at node_idx. Found indices are placed into 'found'.
+ */
+ void find_32bit_roots (unsigned node_idx, hb_set_t& found)
+ {
+ for (const auto& link : vertices_[node_idx].obj.all_links ())
+ {
+ if (!link.is_signed && link.width == 4) {
+ found.add (link.objidx);
+ continue;
+ }
+ find_32bit_roots (link.objidx, found);
+ }
+ }
+
+ /*
+ * Moves the child of old_parent_idx pointed to by old_offset to a new
+ * vertex at the new_offset.
+ */
+ template<typename O>
+ void move_child (unsigned old_parent_idx,
+ const O* old_offset,
+ unsigned new_parent_idx,
+ const O* new_offset)
+ {
+ distance_invalid = true;
+ positions_invalid = true;
+
+ auto& old_v = vertices_[old_parent_idx];
+ auto& new_v = vertices_[new_parent_idx];
+
+ unsigned child_id = index_for_offset (old_parent_idx,
+ old_offset);
+
+ auto* new_link = new_v.obj.real_links.push ();
+ new_link->width = O::static_size;
+ new_link->objidx = child_id;
+ new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
+
+ auto& child = vertices_[child_id];
+ child.parents.push (new_parent_idx);
+
+ old_v.remove_real_link (child_id, old_offset);
+ child.remove_parent (old_parent_idx);
+ }
+
+ /*
+ * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
+ * links. index_map is updated with mappings from old id to new id. If a duplication has already
+ * been performed for a given index, then it will be skipped.
+ */
+ void duplicate_subgraph (unsigned node_idx, hb_map_t& index_map)
+ {
+ if (index_map.has (node_idx))
+ return;
+
+ index_map.set (node_idx, duplicate (node_idx));
+ for (const auto& l : object (node_idx).all_links ()) {
+ duplicate_subgraph (l.objidx, index_map);
+ }
+ }
+
+ /*
+ * Creates a copy of node_idx and returns it's new index.
+ */
+ unsigned duplicate (unsigned node_idx)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ auto& child = vertices_[node_idx];
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = child.obj.head;
+ clone->obj.tail = child.obj.tail;
+ clone->distance = child.distance;
+ clone->space = child.space;
+ clone->parents.reset ();
+
+ unsigned clone_idx = vertices_.length - 2;
+ for (const auto& l : child.obj.real_links)
+ {
+ clone->obj.real_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+ for (const auto& l : child.obj.virtual_links)
+ {
+ clone->obj.virtual_links.push (l);
+ vertices_[l.objidx].parents.push (clone_idx);
+ }
+
+ check_success (!clone->obj.real_links.in_error ());
+ check_success (!clone->obj.virtual_links.in_error ());
+
+ // The last object is the root of the graph, so swap back the root to the end.
+ // The root's obj idx does change, however since it's root nothing else refers to it.
+ // all other obj idx's will be unaffected.
+ hb_swap (vertices_[vertices_.length - 2], *clone);
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root ().obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Creates a copy of child and re-assigns the link from
+ * parent to the clone. The copy is a shallow copy, objects
+ * linked from child are not duplicated.
+ */
+ bool duplicate (unsigned parent_idx, unsigned child_idx)
+ {
+ update_parents ();
+
+ unsigned links_to_child = 0;
+ for (const auto& l : vertices_[parent_idx].obj.all_links ())
+ {
+ if (l.objidx == child_idx) links_to_child++;
+ }
+
+ if (vertices_[child_idx].incoming_edges () <= links_to_child)
+ {
+ // Can't duplicate this node, doing so would orphan the original one as all remaining links
+ // to child are from parent.
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
+ parent_idx, child_idx);
+ return false;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
+ parent_idx, child_idx);
+
+ unsigned clone_idx = duplicate (child_idx);
+ if (clone_idx == (unsigned) -1) return false;
+ // duplicate shifts the root node idx, so if parent_idx was root update it.
+ if (parent_idx == clone_idx) parent_idx++;
+
+ auto& parent = vertices_[parent_idx];
+ for (auto& l : parent.obj.all_links_writer ())
+ {
+ if (l.objidx != child_idx)
+ continue;
+
+ reassign_link (l, parent_idx, clone_idx);
+ }
+
+ return true;
+ }
+
+
+ /*
+ * Adds a new node to the graph, not connected to anything.
+ */
+ unsigned new_node (char* head, char* tail)
+ {
+ positions_invalid = true;
+ distance_invalid = true;
+
+ auto* clone = vertices_.push ();
+ if (vertices_.in_error ()) {
+ return -1;
+ }
+
+ clone->obj.head = head;
+ clone->obj.tail = tail;
+ clone->distance = 0;
+ clone->space = 0;
+
+ unsigned clone_idx = vertices_.length - 2;
+
+ // The last object is the root of the graph, so swap back the root to the end.
+ // The root's obj idx does change, however since it's root nothing else refers to it.
+ // all other obj idx's will be unaffected.
+ hb_swap (vertices_[vertices_.length - 2], *clone);
+
+ // Since the root moved, update the parents arrays of all children on the root.
+ for (const auto& l : root ().obj.all_links ())
+ vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
+
+ return clone_idx;
+ }
+
+ /*
+ * Raises the sorting priority of all children.
+ */
+ bool raise_childrens_priority (unsigned parent_idx)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
+ parent_idx);
+ // This operation doesn't change ordering until a sort is run, so no need
+ // to invalidate positions. It does not change graph structure so no need
+ // to update distances or edge counts.
+ auto& parent = vertices_[parent_idx].obj;
+ bool made_change = false;
+ for (auto& l : parent.all_links_writer ())
+ made_change |= vertices_[l.objidx].raise_priority ();
+ return made_change;
+ }
+
+ void print_orphaned_nodes ()
+ {
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
+ parents_invalid = true;
+ update_parents();
+
+ for (unsigned i = 0; i < root_idx (); i++)
+ {
+ const auto& v = vertices_[i];
+ if (!v.parents)
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
+ }
+ }
+
+ unsigned num_roots_for_space (unsigned space) const
+ {
+ return num_roots_for_space_[space];
+ }
+
+ unsigned next_space () const
+ {
+ return num_roots_for_space_.length;
+ }
+
+ void move_to_new_space (const hb_set_t& indices)
+ {
+ num_roots_for_space_.push (0);
+ unsigned new_space = num_roots_for_space_.length - 1;
+
+ for (unsigned index : indices) {
+ auto& node = vertices_[index];
+ num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
+ num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
+ node.space = new_space;
+ distance_invalid = true;
+ positions_invalid = true;
+ }
+ }
+
+ unsigned space_for (unsigned index, unsigned* root = nullptr) const
+ {
+ const auto& node = vertices_[index];
+ if (node.space)
+ {
+ if (root != nullptr)
+ *root = index;
+ return node.space;
+ }
+
+ if (!node.parents)
+ {
+ if (root)
+ *root = index;
+ return 0;
+ }
+
+ return space_for (node.parents[0], root);
+ }
+
+ void err_other_error () { this->successful = false; }
+
+ size_t total_size_in_bytes () const {
+ size_t total_size = 0;
+ for (unsigned i = 0; i < vertices_.length; i++) {
+ size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
+ total_size += size;
+ }
+ return total_size;
+ }
+
+
+ private:
+
+ /*
+ * Returns the numbers of incoming edges that are 24 or 32 bits wide.
+ */
+ unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
+ {
+ unsigned count = 0;
+ hb_set_t visited;
+ for (unsigned p : vertices_[node_idx].parents)
+ {
+ if (visited.has (p)) continue;
+ visited.add (p);
+
+ // Only real links can be wide
+ for (const auto& l : vertices_[p].obj.real_links)
+ {
+ if (l.objidx == node_idx
+ && (l.width == 3 || l.width == 4)
+ && !l.is_signed)
+ {
+ count++;
+ parents.add (p);
+ }
+ }
+ }
+ return count;
+ }
+
+ bool check_success (bool success)
+ { return this->successful && (success || ((void) err_other_error (), false)); }
+
+ public:
+ /*
+ * Creates a map from objid to # of incoming edges.
+ */
+ void update_parents ()
+ {
+ if (!parents_invalid) return;
+
+ for (unsigned i = 0; i < vertices_.length; i++)
+ vertices_[i].parents.reset ();
+
+ for (unsigned p = 0; p < vertices_.length; p++)
+ {
+ for (auto& l : vertices_[p].obj.all_links ())
+ {
+ vertices_[l.objidx].parents.push (p);
+ }
+ }
+
+ parents_invalid = false;
+ }
+
+ /*
+ * compute the serialized start and end positions for each vertex.
+ */
+ void update_positions ()
+ {
+ if (!positions_invalid) return;
+
+ unsigned current_pos = 0;
+ for (int i = root_idx (); i >= 0; i--)
+ {
+ auto& v = vertices_[i];
+ v.start = current_pos;
+ current_pos += v.obj.tail - v.obj.head;
+ v.end = current_pos;
+ }
+
+ positions_invalid = false;
+ }
+
+ /*
+ * Finds the distance to each object in the graph
+ * from the initial node.
+ */
+ void update_distances ()
+ {
+ if (!distance_invalid) return;
+
+ // Uses Dijkstra's algorithm to find all of the shortest distances.
+ // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
+ //
+ // Implementation Note:
+ // Since our priority queue doesn't support fast priority decreases
+ // we instead just add new entries into the queue when a priority changes.
+ // Redundant ones are filtered out later on by the visited set.
+ // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
+ // for practical performance this is faster then using a more advanced queue
+ // (such as a fibonacci queue) with a fast decrease priority.
+ for (unsigned i = 0; i < vertices_.length; i++)
+ {
+ if (i == vertices_.length - 1)
+ vertices_[i].distance = 0;
+ else
+ vertices_[i].distance = hb_int_max (int64_t);
+ }
+
+ hb_priority_queue_t queue;
+ queue.insert (0, vertices_.length - 1);
+
+ hb_vector_t<bool> visited;
+ visited.resize (vertices_.length);
+
+ while (!queue.in_error () && !queue.is_empty ())
+ {
+ unsigned next_idx = queue.pop_minimum ().second;
+ if (visited[next_idx]) continue;
+ const auto& next = vertices_[next_idx];
+ int64_t next_distance = vertices_[next_idx].distance;
+ visited[next_idx] = true;
+
+ for (const auto& link : next.obj.all_links ())
+ {
+ if (visited[link.objidx]) continue;
+
+ const auto& child = vertices_[link.objidx].obj;
+ unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
+ int64_t child_weight = (child.tail - child.head) +
+ ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
+ int64_t child_distance = next_distance + child_weight;
+
+ if (child_distance < vertices_[link.objidx].distance)
+ {
+ vertices_[link.objidx].distance = child_distance;
+ queue.insert (child_distance, link.objidx);
+ }
+ }
+ }
+
+ check_success (!queue.in_error ());
+ if (!check_success (queue.is_empty ()))
+ {
+ print_orphaned_nodes ();
+ return;
+ }
+
+ distance_invalid = false;
+ }
+
+ private:
+ /*
+ * Updates a link in the graph to point to a different object. Corrects the
+ * parents vector on the previous and new child nodes.
+ */
+ void reassign_link (hb_serialize_context_t::object_t::link_t& link,
+ unsigned parent_idx,
+ unsigned new_idx)
+ {
+ unsigned old_idx = link.objidx;
+ link.objidx = new_idx;
+ vertices_[old_idx].remove_parent (parent_idx);
+ vertices_[new_idx].parents.push (parent_idx);
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
+ */
+ template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
+ void remap_obj_indices (const hb_map_t& id_map,
+ Iterator subgraph,
+ bool only_wide = false)
+ {
+ if (!id_map) return;
+ for (unsigned i : subgraph)
+ {
+ for (auto& link : vertices_[i].obj.all_links_writer ())
+ {
+ const unsigned *v;
+ if (!id_map.has (link.objidx, &v)) continue;
+ if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
+
+ reassign_link (link, i, *v);
+ }
+ }
+ }
+
+ /*
+ * Updates all objidx's in all links using the provided mapping.
+ */
+ void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
+ hb_vector_t<vertex_t>* sorted_graph) const
+ {
+ for (unsigned i = 0; i < sorted_graph->length; i++)
+ {
+ (*sorted_graph)[i].remap_parents (id_map);
+ for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
+ {
+ link.objidx = id_map[link.objidx];
+ }
+ }
+ }
+
+ /*
+ * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
+ * For this search the graph is treated as being undirected.
+ *
+ * Connected targets will be added to connected and removed from targets. All visited nodes
+ * will be added to visited.
+ */
+ void find_connected_nodes (unsigned start_idx,
+ hb_set_t& targets,
+ hb_set_t& visited,
+ hb_set_t& connected)
+ {
+ if (unlikely (!check_success (!visited.in_error ()))) return;
+ if (visited.has (start_idx)) return;
+ visited.add (start_idx);
+
+ if (targets.has (start_idx))
+ {
+ targets.del (start_idx);
+ connected.add (start_idx);
+ }
+
+ const auto& v = vertices_[start_idx];
+
+ // Graph is treated as undirected so search children and parents of start_idx
+ for (const auto& l : v.obj.all_links ())
+ find_connected_nodes (l.objidx, targets, visited, connected);
+
+ for (unsigned p : v.parents)
+ find_connected_nodes (p, targets, visited, connected);
+ }
+
+ public:
+ // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
+ hb_vector_t<vertex_t> vertices_;
+ hb_vector_t<vertex_t> vertices_scratch_;
+ private:
+ bool parents_invalid;
+ bool distance_invalid;
+ bool positions_invalid;
+ bool successful;
+ hb_vector_t<unsigned> num_roots_for_space_;
+};
+
+}
+
+#endif // GRAPH_GRAPH_HH
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc
new file mode 100644
index 0000000000..e0ff6ff85f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "gsubgpos-graph.hh"
+
+namespace graph {
+
+gsubgpos_graph_context_t::gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_)
+ : table_tag (table_tag_),
+ graph (graph_),
+ lookup_list_index (0),
+ lookups (),
+ buffers ()
+{
+ if (table_tag_ != HB_OT_TAG_GPOS
+ && table_tag_ != HB_OT_TAG_GSUB)
+ return;
+
+ GSTAR* gstar = graph::GSTAR::graph_to_gstar (graph_);
+ if (gstar) {
+ gstar->find_lookups (graph, lookups);
+ lookup_list_index = gstar->get_lookup_list_index (graph_);
+ }
+}
+
+unsigned gsubgpos_graph_context_t::create_node (unsigned size)
+{
+ char* buffer = (char*) hb_calloc (1, size);
+ if (!buffer)
+ return -1;
+
+ buffers.push (buffer);
+
+ return graph.new_node (buffer, buffer + size);
+}
+
+unsigned gsubgpos_graph_context_t::num_non_ext_subtables () {
+ unsigned count = 0;
+ for (auto l : lookups.values ())
+ {
+ if (l->is_extension (table_tag)) continue;
+ count += l->number_of_subtables ();
+ }
+ return count;
+}
+
+}
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh
new file mode 100644
index 0000000000..49b24198ff
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-context.hh
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
+
+#ifndef GRAPH_GSUBGPOS_CONTEXT_HH
+#define GRAPH_GSUBGPOS_CONTEXT_HH
+
+namespace graph {
+
+struct Lookup;
+
+struct gsubgpos_graph_context_t
+{
+ hb_tag_t table_tag;
+ graph_t& graph;
+ unsigned lookup_list_index;
+ hb_hashmap_t<unsigned, graph::Lookup*> lookups;
+ hb_vector_t<char*> buffers;
+
+ HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
+ graph_t& graph_);
+
+ ~gsubgpos_graph_context_t ()
+ {
+ for (char* b : buffers)
+ hb_free (b);
+ }
+
+ HB_INTERNAL unsigned create_node (unsigned size);
+
+ void add_buffer (char* buffer)
+ {
+ buffers.push (buffer);
+ }
+
+ private:
+ HB_INTERNAL unsigned num_non_ext_subtables ();
+};
+
+}
+
+#endif // GRAPH_GSUBGPOS_CONTEXT
diff --git a/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
new file mode 100644
index 0000000000..afa1152c44
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
@@ -0,0 +1,351 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#include "graph.hh"
+#include "../hb-ot-layout-gsubgpos.hh"
+#include "../OT/Layout/GSUB/ExtensionSubst.hh"
+#include "gsubgpos-context.hh"
+#include "pairpos-graph.hh"
+
+#ifndef GRAPH_GSUBGPOS_GRAPH_HH
+#define GRAPH_GSUBGPOS_GRAPH_HH
+
+namespace graph {
+
+struct Lookup;
+
+template<typename T>
+struct ExtensionFormat1 : public OT::ExtensionFormat1<T>
+{
+ void reset(unsigned type)
+ {
+ this->format = 1;
+ this->extensionLookupType = type;
+ this->extensionOffset = 0;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ return vertex_len >= OT::ExtensionFormat1<T>::static_size;
+ }
+
+ unsigned get_lookup_type () const
+ {
+ return this->extensionLookupType;
+ }
+
+ unsigned get_subtable_index (graph_t& graph, unsigned this_index) const
+ {
+ return graph.index_for_offset (this_index, &this->extensionOffset);
+ }
+};
+
+struct Lookup : public OT::Lookup
+{
+ unsigned number_of_subtables () const
+ {
+ return subTable.len;
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::Lookup::min_size) return false;
+ return vertex_len >= this->get_size ();
+ }
+
+ bool is_extension (hb_tag_t table_tag) const
+ {
+ return lookupType == extension_type (table_tag);
+ }
+
+ bool make_extension (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ unsigned ext_type = extension_type (c.table_tag);
+ if (!ext_type || is_extension (c.table_tag))
+ {
+ // NOOP
+ return true;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ "Promoting lookup type %u (obj %u) to extension.",
+ type,
+ this_index);
+
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ if (!make_subtable_extension (c,
+ this_index,
+ subtable_index))
+ return false;
+ }
+
+ lookupType = ext_type;
+ return true;
+ }
+
+ bool split_subtables_if_needed (gsubgpos_graph_context_t& c,
+ unsigned this_index)
+ {
+ unsigned type = lookupType;
+ bool is_ext = is_extension (c.table_tag);
+
+ if (c.table_tag != HB_OT_TAG_GPOS)
+ return true;
+
+ if (!is_ext && type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
+ return true;
+
+ hb_vector_t<unsigned> all_new_subtables;
+ for (unsigned i = 0; i < subTable.len; i++)
+ {
+ unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
+ if (is_ext) {
+ unsigned ext_subtable_index = subtable_index;
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
+ c.graph.object (ext_subtable_index).head;
+ if (!extension->sanitize (c.graph.vertices_[ext_subtable_index]))
+ continue;
+
+ subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index);
+ type = extension->get_lookup_type ();
+ if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair)
+ continue;
+ }
+
+ PairPos* pairPos = (PairPos*) c.graph.object (subtable_index).head;
+ if (!pairPos->sanitize (c.graph.vertices_[subtable_index])) continue;
+
+ hb_vector_t<unsigned> new_sub_tables = pairPos->split_subtables (c, subtable_index);
+ if (new_sub_tables.in_error ()) return false;
+ + new_sub_tables.iter() | hb_sink (all_new_subtables);
+ }
+
+ if (all_new_subtables)
+ add_sub_tables (c, this_index, type, all_new_subtables);
+
+ return true;
+ }
+
+ void add_sub_tables (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned type,
+ hb_vector_t<unsigned>& subtable_indices)
+ {
+ bool is_ext = is_extension (c.table_tag);
+ auto& v = c.graph.vertices_[this_index];
+
+ size_t new_size = v.table_size ()
+ + subtable_indices.length * OT::Offset16::static_size;
+ char* buffer = (char*) hb_calloc (1, new_size);
+ c.add_buffer (buffer);
+ memcpy (buffer, v.obj.head, v.table_size());
+
+ v.obj.head = buffer;
+ v.obj.tail = buffer + new_size;
+
+ Lookup* new_lookup = (Lookup*) buffer;
+
+ new_lookup->subTable.len = subTable.len + subtable_indices.length;
+ unsigned offset_index = subTable.len;
+ for (unsigned subtable_id : subtable_indices)
+ {
+ if (is_ext)
+ {
+ unsigned ext_id = create_extension_subtable (c, subtable_id, type);
+ c.graph.vertices_[subtable_id].parents.push (ext_id);
+ subtable_id = ext_id;
+ }
+
+ auto* link = v.obj.real_links.push ();
+ link->width = 2;
+ link->objidx = subtable_id;
+ link->position = (char*) &new_lookup->subTable[offset_index++] -
+ (char*) new_lookup;
+ c.graph.vertices_[subtable_id].parents.push (this_index);
+ }
+
+ // The head location of the lookup has changed, invalidating the lookups map entry
+ // in the context. Update the map.
+ c.lookups.set (this_index, new_lookup);
+ }
+
+ unsigned create_extension_subtable (gsubgpos_graph_context_t& c,
+ unsigned subtable_index,
+ unsigned type)
+ {
+ unsigned extension_size = OT::ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>::static_size;
+
+ unsigned ext_index = c.create_node (extension_size);
+ if (ext_index == (unsigned) -1)
+ return -1;
+
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
+ (ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*) ext_vertex.obj.head;
+ extension->reset (type);
+
+ // Make extension point at the subtable.
+ auto* l = ext_vertex.obj.real_links.push ();
+
+ l->width = 4;
+ l->objidx = subtable_index;
+ l->position = 4;
+
+ return ext_index;
+ }
+
+ bool make_subtable_extension (gsubgpos_graph_context_t& c,
+ unsigned lookup_index,
+ unsigned subtable_index)
+ {
+ unsigned type = lookupType;
+
+ unsigned ext_index = create_extension_subtable(c, subtable_index, type);
+ if (ext_index == (unsigned) -1)
+ return false;
+
+ auto& lookup_vertex = c.graph.vertices_[lookup_index];
+ for (auto& l : lookup_vertex.obj.real_links.writer ())
+ {
+ if (l.objidx == subtable_index)
+ // Change lookup to point at the extension.
+ l.objidx = ext_index;
+ }
+
+ // Make extension point at the subtable.
+ auto& ext_vertex = c.graph.vertices_[ext_index];
+ auto& subtable_vertex = c.graph.vertices_[subtable_index];
+ ext_vertex.parents.push (lookup_index);
+ subtable_vertex.remap_parent (lookup_index, ext_index);
+
+ return true;
+ }
+
+ private:
+ unsigned extension_type (hb_tag_t table_tag) const
+ {
+ switch (table_tag)
+ {
+ case HB_OT_TAG_GPOS: return 9;
+ case HB_OT_TAG_GSUB: return 7;
+ default: return 0;
+ }
+ }
+};
+
+template <typename T>
+struct LookupList : public OT::LookupList<T>
+{
+ bool sanitize (const graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < OT::LookupList<T>::min_size) return false;
+ return vertex_len >= OT::LookupList<T>::item_size * this->len;
+ }
+};
+
+struct GSTAR : public OT::GSUBGPOS
+{
+ static GSTAR* graph_to_gstar (graph_t& graph)
+ {
+ const auto& r = graph.root ();
+
+ GSTAR* gstar = (GSTAR*) r.obj.head;
+ if (!gstar->sanitize (r))
+ return nullptr;
+
+ return gstar;
+ }
+
+ const void* get_lookup_list_field_offset () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_lookup_list_offset ();
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: return u.version2.get_lookup_list_offset ();
+#endif
+ default: return 0;
+ }
+ }
+
+ bool sanitize (const graph_t::vertex_t& vertex)
+ {
+ int64_t len = vertex.obj.tail - vertex.obj.head;
+ if (len < OT::GSUBGPOS::min_size) return false;
+ return len >= get_size ();
+ }
+
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ switch (u.version.major) {
+ case 1: find_lookups<SmallTypes> (graph, lookups); break;
+#ifndef HB_NO_BORING_EXPANSION
+ case 2: find_lookups<MediumTypes> (graph, lookups); break;
+#endif
+ }
+ }
+
+ unsigned get_lookup_list_index (graph_t& graph)
+ {
+ return graph.index_for_offset (graph.root_idx (),
+ get_lookup_list_field_offset());
+ }
+
+ template<typename Types>
+ void find_lookups (graph_t& graph,
+ hb_hashmap_t<unsigned, Lookup*>& lookups /* OUT */)
+ {
+ unsigned lookup_list_idx = get_lookup_list_index (graph);
+
+ const LookupList<Types>* lookupList =
+ (const LookupList<Types>*) graph.object (lookup_list_idx).head;
+ if (!lookupList->sanitize (graph.vertices_[lookup_list_idx]))
+ return;
+
+ for (unsigned i = 0; i < lookupList->len; i++)
+ {
+ unsigned lookup_idx = graph.index_for_offset (lookup_list_idx, &(lookupList->arrayZ[i]));
+ Lookup* lookup = (Lookup*) graph.object (lookup_idx).head;
+ if (!lookup->sanitize (graph.vertices_[lookup_idx])) continue;
+ lookups.set (lookup_idx, lookup);
+ }
+ }
+};
+
+
+
+
+}
+
+#endif /* GRAPH_GSUBGPOS_GRAPH_HH */
diff --git a/thirdparty/harfbuzz/src/graph/pairpos-graph.hh b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
new file mode 100644
index 0000000000..3ca4fc701c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/pairpos-graph.hh
@@ -0,0 +1,299 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_PAIRPOS_GRAPH_HH
+#define GRAPH_PAIRPOS_GRAPH_HH
+
+#include "coverage-graph.hh"
+#include "../OT/Layout/GPOS/PairPos.hh"
+#include "../OT/Layout/GPOS/PosLookupSubTable.hh"
+
+namespace graph {
+
+struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ unsigned min_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size;
+ if (vertex_len < min_size) return false;
+
+ return vertex_len >=
+ min_size + pairSet.get_size () - pairSet.len.get_size();
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ hb_set_t visited;
+
+ const unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ const unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+ + coverage_size;
+
+ unsigned accumulated = base_size;
+ hb_vector_t<unsigned> split_points;
+ for (unsigned i = 0; i < pairSet.len; i++)
+ {
+ unsigned pair_set_index = pair_set_graph_index (c, this_index, i);
+ accumulated += c.graph.find_subgraph_size (pair_set_index, visited);
+ accumulated += SmallTypes::size; // for PairSet offset.
+
+ // TODO(garretrieger): don't count the size of the largest pairset against the limit, since
+ // it will be packed last in the order and does not contribute to
+ // the 64kb limit.
+
+ if (accumulated > (1 << 16))
+ {
+ split_points.push (i);
+ accumulated = base_size;
+ visited.clear (); // Pretend node sharing isn't allowed between splits.
+ }
+ }
+
+ return do_split (c, this_index, split_points);
+ }
+
+ private:
+
+ // Split this PairPos into two or more PairPos's. split_points defines
+ // the indices (first index to include in the new table) to split at.
+ // Returns the object id's of the newly created PairPos subtables.
+ hb_vector_t<unsigned> do_split (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ const hb_vector_t<unsigned> split_points)
+ {
+ hb_vector_t<unsigned> new_objects;
+ if (!split_points)
+ return new_objects;
+
+ for (unsigned i = 0; i < split_points.length; i++)
+ {
+ unsigned start = split_points[i];
+ unsigned end = (i < split_points.length - 1) ? split_points[i + 1] : pairSet.len;
+ unsigned id = clone_range (c, this_index, start, end);
+
+ if (id == (unsigned) -1)
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ return new_objects;
+ }
+ new_objects.push (id);
+ }
+
+ if (!shrink (c, this_index, split_points[0]))
+ {
+ new_objects.reset ();
+ new_objects.allocated = -1; // mark error
+ }
+
+ return new_objects;
+ }
+
+ bool shrink (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned count)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Shrinking PairPosFormat1 (%u) to [0, %u).",
+ this_index,
+ count);
+ unsigned old_count = pairSet.len;
+ if (count >= old_count)
+ return true;
+
+ pairSet.len = count;
+ c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
+
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table->sanitize (coverage_v))
+ return false;
+
+ auto new_coverage =
+ + hb_zip (coverage_table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second < count;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ return make_coverage (c, new_coverage, coverage_id, coverage_size);
+ }
+
+ // Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
+ // Returns object id of the new object.
+ unsigned clone_range (gsubgpos_graph_context_t& c,
+ unsigned this_index,
+ unsigned start, unsigned end) const
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " Cloning PairPosFormat1 (%u) range [%u, %u).", this_index, start, end);
+
+ unsigned num_pair_sets = end - start;
+ unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+ + num_pair_sets * SmallTypes::size;
+
+ unsigned pair_pos_prime_id = c.create_node (prime_size);
+ if (pair_pos_prime_id == (unsigned) -1) return -1;
+
+ PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head;
+ pair_pos_prime->format = this->format;
+ pair_pos_prime->valueFormat[0] = this->valueFormat[0];
+ pair_pos_prime->valueFormat[1] = this->valueFormat[1];
+ pair_pos_prime->pairSet.len = num_pair_sets;
+
+ for (unsigned i = start; i < end; i++)
+ {
+ c.graph.move_child<> (this_index,
+ &pairSet[i],
+ pair_pos_prime_id,
+ &pair_pos_prime->pairSet[i - start]);
+ }
+
+ unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
+ unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
+ auto& coverage_v = c.graph.vertices_[coverage_id];
+ Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
+ if (!coverage_table->sanitize (coverage_v))
+ return false;
+
+ auto new_coverage =
+ + hb_zip (coverage_table->iter (), hb_range ())
+ | hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
+ return p.second >= start && p.second < end;
+ })
+ | hb_map_retains_sorting (hb_first)
+ ;
+
+ unsigned coverage_prime_id = c.graph.new_node (nullptr, nullptr);
+ auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
+ if (!make_coverage (c, new_coverage, coverage_prime_id, coverage_size))
+ return -1;
+
+ auto* coverage_link = c.graph.vertices_[pair_pos_prime_id].obj.real_links.push ();
+ coverage_link->width = SmallTypes::size;
+ coverage_link->objidx = coverage_prime_id;
+ coverage_link->position = 2;
+ coverage_prime_vertex.parents.push (pair_pos_prime_id);
+
+ return pair_pos_prime_id;
+ }
+
+ template<typename It>
+ bool make_coverage (gsubgpos_graph_context_t& c,
+ It glyphs,
+ unsigned dest_obj,
+ unsigned max_size) const
+ {
+ char* buffer = (char*) hb_calloc (1, max_size);
+ hb_serialize_context_t serializer (buffer, max_size);
+ Coverage_serialize (&serializer, glyphs);
+ serializer.end_serialize ();
+ if (serializer.in_error ())
+ {
+ hb_free (buffer);
+ return false;
+ }
+
+ hb_bytes_t coverage_copy = serializer.copy_bytes ();
+ c.add_buffer ((char *) coverage_copy.arrayZ); // Give ownership to the context, it will cleanup the buffer.
+
+ auto& obj = c.graph.vertices_[dest_obj].obj;
+ obj.head = (char *) coverage_copy.arrayZ;
+ obj.tail = obj.head + coverage_copy.length;
+
+ hb_free (buffer);
+ return true;
+ }
+
+ unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const
+ {
+ return c.graph.index_for_offset (this_index, &pairSet[i]);
+ }
+};
+
+struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>
+{
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ // TODO(garretrieger): implement me!
+ return true;
+ }
+
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ // TODO(garretrieger): implement me!
+ return hb_vector_t<unsigned> ();
+ }
+};
+
+struct PairPos : public OT::Layout::GPOS_impl::PairPos
+{
+ hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
+ {
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+ // Don't split 24bit PairPos's.
+#endif
+ default:
+ return hb_vector_t<unsigned> ();
+ }
+ }
+
+ bool sanitize (graph_t::vertex_t& vertex) const
+ {
+ int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
+ if (vertex_len < u.format.get_size ()) return false;
+
+ switch (u.format) {
+ case 1:
+ return ((PairPosFormat1*)(&u.format1))->sanitize (vertex);
+ case 2:
+ return ((PairPosFormat2*)(&u.format2))->sanitize (vertex);
+#ifndef HB_NO_BORING_EXPANSION
+ case 3: HB_FALLTHROUGH;
+ case 4: HB_FALLTHROUGH;
+#endif
+ default:
+ // We don't handle format 3 and 4 here.
+ return false;
+ }
+ }
+};
+
+}
+
+#endif // GRAPH_PAIRPOS_GRAPH_HH
diff --git a/thirdparty/harfbuzz/src/graph/serialize.hh b/thirdparty/harfbuzz/src/graph/serialize.hh
new file mode 100644
index 0000000000..ecc6cc5aea
--- /dev/null
+++ b/thirdparty/harfbuzz/src/graph/serialize.hh
@@ -0,0 +1,249 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Garret Rieger
+ */
+
+#ifndef GRAPH_SERIALIZE_HH
+#define GRAPH_SERIALIZE_HH
+
+namespace graph {
+
+struct overflow_record_t
+{
+ unsigned parent;
+ unsigned child;
+};
+
+inline
+int64_t compute_offset (
+ const graph_t& graph,
+ unsigned parent_idx,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ const auto& parent = graph.vertices_[parent_idx];
+ const auto& child = graph.vertices_[link.objidx];
+ int64_t offset = 0;
+ switch ((hb_serialize_context_t::whence_t) link.whence) {
+ case hb_serialize_context_t::whence_t::Head:
+ offset = child.start - parent.start; break;
+ case hb_serialize_context_t::whence_t::Tail:
+ offset = child.start - parent.end; break;
+ case hb_serialize_context_t::whence_t::Absolute:
+ offset = child.start; break;
+ }
+
+ assert (offset >= link.bias);
+ offset -= link.bias;
+ return offset;
+}
+
+inline
+bool is_valid_offset (int64_t offset,
+ const hb_serialize_context_t::object_t::link_t& link)
+{
+ if (unlikely (!link.width))
+ // Virtual links can't overflow.
+ return link.is_signed || offset >= 0;
+
+ if (link.is_signed)
+ {
+ if (link.width == 4)
+ return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
+ else
+ return offset >= -(1 << 15) && offset < (1 << 15);
+ }
+ else
+ {
+ if (link.width == 4)
+ return offset >= 0 && offset < ((int64_t) 1 << 32);
+ else if (link.width == 3)
+ return offset >= 0 && offset < ((int32_t) 1 << 24);
+ else
+ return offset >= 0 && offset < (1 << 16);
+ }
+}
+
+/*
+ * Will any offsets overflow on graph when it's serialized?
+ */
+inline bool
+will_overflow (graph_t& graph,
+ hb_vector_t<overflow_record_t>* overflows = nullptr)
+{
+ if (overflows) overflows->resize (0);
+ graph.update_positions ();
+
+ const auto& vertices = graph.vertices_;
+ for (int parent_idx = vertices.length - 1; parent_idx >= 0; parent_idx--)
+ {
+ // Don't need to check virtual links for overflow
+ for (const auto& link : vertices[parent_idx].obj.real_links)
+ {
+ int64_t offset = compute_offset (graph, parent_idx, link);
+ if (is_valid_offset (offset, link))
+ continue;
+
+ if (!overflows) return true;
+
+ overflow_record_t r;
+ r.parent = parent_idx;
+ r.child = link.objidx;
+ overflows->push (r);
+ }
+ }
+
+ if (!overflows) return false;
+ return overflows->length;
+}
+
+inline
+void print_overflows (graph_t& graph,
+ const hb_vector_t<overflow_record_t>& overflows)
+{
+ if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
+
+ graph.update_parents ();
+ int limit = 10;
+ for (const auto& o : overflows)
+ {
+ if (!limit--) break;
+ const auto& parent = graph.vertices_[o.parent];
+ const auto& child = graph.vertices_[o.child];
+ DEBUG_MSG (SUBSET_REPACK, nullptr,
+ " overflow from "
+ "%4d (%4d in, %4d out, space %2d) => "
+ "%4d (%4d in, %4d out, space %2d)",
+ o.parent,
+ parent.incoming_edges (),
+ parent.obj.real_links.length + parent.obj.virtual_links.length,
+ graph.space_for (o.parent),
+ o.child,
+ child.incoming_edges (),
+ child.obj.real_links.length + child.obj.virtual_links.length,
+ graph.space_for (o.child));
+ }
+ if (overflows.length > 10) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
+ }
+}
+
+template <typename O> inline void
+serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
+ *offset = 0;
+ c->add_link (*offset,
+ // serializer has an extra nil object at the start of the
+ // object array. So all id's are +1 of what our id's are.
+ link.objidx + 1,
+ (hb_serialize_context_t::whence_t) link.whence,
+ link.bias);
+}
+
+inline
+void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
+ char* head,
+ hb_serialize_context_t* c)
+{
+ switch (link.width)
+ {
+ case 0:
+ // Virtual links aren't serialized.
+ return;
+ case 4:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT32> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT32> (link, head, c);
+ }
+ return;
+ case 2:
+ if (link.is_signed)
+ {
+ serialize_link_of_type<OT::HBINT16> (link, head, c);
+ } else {
+ serialize_link_of_type<OT::HBUINT16> (link, head, c);
+ }
+ return;
+ case 3:
+ serialize_link_of_type<OT::HBUINT24> (link, head, c);
+ return;
+ default:
+ // Unexpected link width.
+ assert (0);
+ }
+}
+
+/*
+ * serialize graph into the provided serialization buffer.
+ */
+inline hb_blob_t* serialize (const graph_t& graph)
+{
+ hb_vector_t<char> buffer;
+ size_t size = graph.total_size_in_bytes ();
+ if (!buffer.alloc (size)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
+ return nullptr;
+ }
+ hb_serialize_context_t c((void *) buffer, size);
+
+ c.start_serialize<void> ();
+ const auto& vertices = graph.vertices_;
+ for (unsigned i = 0; i < vertices.length; i++) {
+ c.push ();
+
+ size_t size = vertices[i].obj.tail - vertices[i].obj.head;
+ char* start = c.allocate_size <char> (size);
+ if (!start) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
+ return nullptr;
+ }
+
+ memcpy (start, vertices[i].obj.head, size);
+
+ // Only real links needs to be serialized.
+ for (const auto& link : vertices[i].obj.real_links)
+ serialize_link (link, start, &c);
+
+ // All duplications are already encoded in the graph, so don't
+ // enable sharing during packing.
+ c.pop_pack (false);
+ }
+ c.end_serialize ();
+
+ if (c.in_error ()) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
+ c.errors);
+ return nullptr;
+ }
+
+ return c.copy_blob ();
+}
+
+} // namespace graph
+
+#endif // GRAPH_SERIALIZE_HH
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
index b52844e75d..bf12d2e699 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-bsln-table.hh
@@ -42,7 +42,7 @@ struct BaselineTableFormat0Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -78,7 +78,7 @@ struct BaselineTableFormat2Part
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
index 1db0f1df92..6cbed82692 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-common.hh
@@ -415,18 +415,7 @@ struct Lookup
public:
DEFINE_SIZE_UNION (2, format);
};
-/* Lookup 0 has unbounded size (dependant on num_glyphs). So we need to defined
- * special NULL objects for Lookup<> objects, but since it's template our macros
- * don't work. So we have to hand-code them here. UGLY. */
-} /* Close namespace. */
-/* Ugly hand-coded null objects for template Lookup<> :(. */
-extern HB_INTERNAL const unsigned char _hb_Null_AAT_Lookup[2];
-template <typename T>
-struct Null<AAT::Lookup<T>> {
- static AAT::Lookup<T> const & get_null ()
- { return *reinterpret_cast<const AAT::Lookup<T> *> (_hb_Null_AAT_Lookup); }
-};
-namespace AAT {
+DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
enum { DELETED_GLYPH = 0xFFFF };
@@ -681,6 +670,13 @@ struct ObsoleteTypes
const void *base,
const T *array)
{
+ /* https://github.com/harfbuzz/harfbuzz/issues/3483 */
+ /* If offset is less than base, return an offset that would
+ * result in an address half a 32bit address-space away,
+ * to make sure sanitize fails even on 32bit builds. */
+ if (unlikely (offset < unsigned ((const char *) array - (const char *) base)))
+ return INT_MAX / T::static_size;
+
/* https://github.com/harfbuzz/harfbuzz/issues/2816 */
return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
}
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
index 573f0cf9f6..815a1fd2aa 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-feat-table.hh
@@ -62,7 +62,7 @@ struct SettingName
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
index 0bf9bd2912..57c105967d 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-just-table.hh
@@ -48,7 +48,7 @@ struct ActionSubrecordHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
HBUINT16 actionClass; /* The JustClass value associated with this
@@ -65,7 +65,7 @@ struct DecompositionAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
ActionSubrecordHeader
@@ -112,7 +112,7 @@ struct ConditionalAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -137,7 +137,7 @@ struct DuctileGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -163,7 +163,7 @@ struct RepeatedAddGlyphAction
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -294,7 +294,7 @@ struct WidthDeltaPair
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
index 0354b47d5a..995492cd5a 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-kerx-table.hh
@@ -287,7 +287,7 @@ struct KerxSubTableFormat1
* in the 'kern' table example. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.y_offset = 0;
}
@@ -310,7 +310,7 @@ struct KerxSubTableFormat1
/* CoreText doesn't do crossStream kerning in vertical. We do. */
if (v == -0x8000)
{
- o.attach_type() = ATTACH_TYPE_NONE;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_NONE;
o.attach_chain() = 0;
o.x_offset = 0;
}
@@ -567,7 +567,7 @@ struct KerxSubTableFormat4
}
break;
}
- o.attach_type() = ATTACH_TYPE_MARK;
+ o.attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_MARK;
o.attach_chain() = (int) mark - (int) buffer->idx;
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
@@ -751,7 +751,7 @@ struct KerxSubTableHeader
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -901,7 +901,7 @@ struct KerxTable
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
- pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
+ pos[i].attach_type() = OT::Layout::GPOS_impl::ATTACH_TYPE_CURSIVE;
pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
/* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
* since there needs to be a non-zero attachment for post-positioning to
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
index 2f99510925..aa4ad4cf3c 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-morx-table.hh
@@ -123,7 +123,7 @@ struct RearrangementSubtable
bool reverse_l = 3 == (m >> 4);
bool reverse_r = 3 == (m & 0x0F);
- if (end - start >= l + r)
+ if (end - start >= l + r && end-start <= HB_MAX_CONTEXT_LENGTH)
{
buffer->merge_clusters (start, hb_min (buffer->idx + 1, buffer->len));
buffer->merge_clusters (start, end);
@@ -980,6 +980,15 @@ struct Chain
setting = HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS;
goto retry;
}
+#ifndef HB_NO_AAT
+ else if (type == HB_AAT_LAYOUT_FEATURE_TYPE_LANGUAGE_TAG_TYPE && setting &&
+ /* TODO: Rudimentary language matching. */
+ hb_language_matches (map->face->table.ltag->get_language (setting - 1), map->props.language))
+ {
+ flags &= feature.disableFlags;
+ flags |= feature.enableFlags;
+ }
+#endif
}
}
return flags;
@@ -1038,12 +1047,12 @@ struct Chain
goto skip;
if (reverse)
- _hb_ot_layout_reverse_graphemes (c->buffer);
+ c->buffer->reverse ();
subtable->apply (c);
if (reverse)
- _hb_ot_layout_reverse_graphemes (c->buffer);
+ c->buffer->reverse ();
(void) c->buffer->message (c->font, "end chainsubtable %d", c->lookup_index);
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
index b1a1512821..51b650fc33 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-layout-opbd-table.hh
@@ -42,7 +42,7 @@ struct OpticalBounds
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
FWORD leftSide;
diff --git a/thirdparty/harfbuzz/src/hb-aat-layout.cc b/thirdparty/harfbuzz/src/hb-aat-layout.cc
index e2d4de2ccd..e06d286ff0 100644
--- a/thirdparty/harfbuzz/src/hb-aat-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-aat-layout.cc
@@ -108,7 +108,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('f','r','a','c'), HB_AAT_LAYOUT_FEATURE_TYPE_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DIAGONAL_FRACTIONS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_FRACTIONS},
{HB_TAG ('f','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_MONOSPACED_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('h','a','l','t'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_HALF_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
- {HB_TAG ('h','i','s','t'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
+ {HB_TAG ('h','i','s','t'), (hb_aat_layout_feature_type_t) 40, (hb_aat_layout_feature_selector_t) 0, (hb_aat_layout_feature_selector_t) 1},
{HB_TAG ('h','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_HORIZ_KANA_OFF},
{HB_TAG ('h','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_HISTORICAL_LIGATURES_OFF},
{HB_TAG ('h','n','g','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TRANSLITERATION, HB_AAT_LAYOUT_FEATURE_SELECTOR_HANJA_TO_HANGUL, HB_AAT_LAYOUT_FEATURE_SELECTOR_NO_TRANSLITERATION},
@@ -170,6 +170,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
{HB_TAG ('v','k','n','a'), HB_AAT_LAYOUT_FEATURE_TYPE_ALTERNATE_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALTERNATE_VERT_KANA_OFF},
{HB_TAG ('v','p','a','l'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_ALT_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
{HB_TAG ('v','r','t','2'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SUBSTITUTE_VERTICAL_FORMS_OFF},
+ {HB_TAG ('v','r','t','r'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_SUBSTITUTION, (hb_aat_layout_feature_selector_t) 2, (hb_aat_layout_feature_selector_t) 3},
{HB_TAG ('z','e','r','o'), HB_AAT_LAYOUT_FEATURE_TYPE_TYPOGRAPHIC_EXTRAS, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_SLASHED_ZERO_OFF},
};
@@ -228,7 +229,7 @@ hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
*
* <note>Note: does not examine the `GSUB` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -299,7 +300,7 @@ hb_aat_layout_remove_deleted_glyphs (hb_buffer_t *buffer)
*
* <note>Note: does not examine the `GPOS` table.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
@@ -332,7 +333,7 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan,
* Tests whether the specified face includes any tracking information
* in the `trak` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.3.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-aat-map.hh b/thirdparty/harfbuzz/src/hb-aat-map.hh
index 5a0fa70544..c914f58d70 100644
--- a/thirdparty/harfbuzz/src/hb-aat-map.hh
+++ b/thirdparty/harfbuzz/src/hb-aat-map.hh
@@ -52,8 +52,9 @@ struct hb_aat_map_builder_t
public:
HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_ HB_UNUSED) :
- face (face_) {}
+ const hb_segment_properties_t props_) :
+ face (face_),
+ props (props_) {}
HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
@@ -87,6 +88,7 @@ struct hb_aat_map_builder_t
public:
hb_face_t *face;
+ hb_segment_properties_t props;
public:
hb_sorted_vector_t<feature_info_t> features;
diff --git a/thirdparty/harfbuzz/src/hb-algs.hh b/thirdparty/harfbuzz/src/hb-algs.hh
index 3a3ab08046..cc37c073da 100644
--- a/thirdparty/harfbuzz/src/hb-algs.hh
+++ b/thirdparty/harfbuzz/src/hb-algs.hh
@@ -59,7 +59,7 @@
static inline constexpr T operator | (T l, T r) { return T ((unsigned) l | (unsigned) r); } \
static inline constexpr T operator & (T l, T r) { return T ((unsigned) l & (unsigned) r); } \
static inline constexpr T operator ^ (T l, T r) { return T ((unsigned) l ^ (unsigned) r); } \
- static inline constexpr T operator ~ (T r) { return T (~(unsigned int) r); } \
+ static inline constexpr unsigned operator ~ (T r) { return (~(unsigned) r); } \
static inline T& operator |= (T &l, T r) { l = l | r; return l; } \
static inline T& operator &= (T& l, T r) { l = l & r; return l; } \
static inline T& operator ^= (T& l, T r) { l = l ^ r; return l; } \
@@ -109,15 +109,16 @@ struct BEInt<Type, 2>
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
constexpr operator Type () const
{
-#if ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
defined(__BYTE_ORDER) && \
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
/* Spoon-feed the compiler a big-endian integer with alignment 1.
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
#if __BYTE_ORDER == __LITTLE_ENDIAN
- return __builtin_bswap16 (((packed_uint16_t *) this)->v);
+ return __builtin_bswap16 (((packed_uint16_t *) v)->v);
#else /* __BYTE_ORDER == __BIG_ENDIAN */
- return ((packed_uint16_t *) this)->v;
+ return ((packed_uint16_t *) v)->v;
#endif
#else
return (v[0] << 8)
@@ -150,10 +151,27 @@ struct BEInt<Type, 4>
uint8_t ((V >> 16) & 0xFF),
uint8_t ((V >> 8) & 0xFF),
uint8_t ((V ) & 0xFF)} {}
- constexpr operator Type () const { return (v[0] << 24)
- + (v[1] << 16)
- + (v[2] << 8)
- + (v[3] ); }
+
+ struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
+ constexpr operator Type () const {
+#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
+ ((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
+ defined(__BYTE_ORDER) && \
+ (__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
+ /* Spoon-feed the compiler a big-endian integer with alignment 1.
+ * https://github.com/harfbuzz/harfbuzz/pull/1398 */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ return __builtin_bswap32 (((packed_uint32_t *) v)->v);
+#else /* __BYTE_ORDER == __BIG_ENDIAN */
+ return ((packed_uint32_t *) v)->v;
+#endif
+#else
+ return (v[0] << 24)
+ + (v[1] << 16)
+ + (v[2] << 8)
+ + (v[3] );
+#endif
+ }
private: uint8_t v[4];
};
@@ -211,31 +229,26 @@ struct
}
HB_FUNCOBJ (hb_bool);
-template <typename T>
-static inline
-T hb_coerce (const T v) { return v; }
-template <typename T, typename V,
- hb_enable_if (!hb_is_same (hb_decay<T>, hb_decay<V>) && std::is_pointer<V>::value)>
-static inline
-T hb_coerce (const V v) { return *v; }
-
struct
{
private:
template <typename T> constexpr auto
- impl (const T& v, hb_priority<2>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
+ impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, hb_deref (v).hash ())
- template <typename T> constexpr auto
- impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
+ template <typename T> constexpr uint32_t
+ impl (const hb::shared_ptr<T>& v, hb_priority<1>) const
+ {
+ return v.get () ? v.get ()->hash () : 0;
+ }
+ template <typename T> constexpr uint32_t
+ impl (const hb::unique_ptr<T>& v, hb_priority<1>) const
+ {
+ return v.get () ? v.get ()->hash () : 0;
+ }
- template <typename T,
- hb_enable_if (std::is_integral<T>::value)> constexpr auto
- impl (const T& v, hb_priority<0>) const HB_AUTO_RETURN
- (
- /* Knuth's multiplicative method: */
- (uint32_t) v * 2654435761u
- )
+ template <typename T> constexpr auto
+ impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
public:
@@ -498,7 +511,7 @@ struct hb_pair_t
template <typename Q1, typename Q2,
hb_enable_if (hb_is_convertible (T1, Q1) &&
- hb_is_convertible (T2, T2))>
+ hb_is_convertible (T2, Q2))>
operator hb_pair_t<Q1, Q2> () { return hb_pair_t<Q1, Q2> (first, second); }
hb_pair_t<T1, T2> reverse () const
@@ -514,7 +527,6 @@ struct hb_pair_t
T1 first;
T2 second;
};
-#define hb_pair_t(T1,T2) hb_pair_t<T1, T2>
template <typename T1, typename T2> static inline hb_pair_t<T1, T2>
hb_pair (T1&& a, T2&& b) { return hb_pair_t<T1, T2> (a, b); }
@@ -540,14 +552,14 @@ struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a <= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a <= b ? a : b)
}
HB_FUNCOBJ (hb_min);
struct
{
template <typename T, typename T2> constexpr auto
operator () (T&& a, T2&& b) const HB_AUTO_RETURN
- (a >= b ? std::forward<T> (a) : std::forward<T2> (b))
+ (a >= b ? a : b)
}
HB_FUNCOBJ (hb_max);
struct
@@ -846,6 +858,11 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
{
return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3);
}
+template <typename T> static inline bool
+hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3, T lo4, T hi4)
+{
+ return hb_in_range (u, lo1, hi1) || hb_in_range (u, lo2, hi2) || hb_in_range (u, lo3, hi3) || hb_in_range (u, lo4, hi4);
+}
/*
@@ -956,7 +973,7 @@ void hb_qsort(void *base, size_t nel, size_t width,
[void *arg]);
*/
-#define SORT_R_SWAP(a,b,tmp) ((tmp) = (a), (a) = (b), (b) = (tmp))
+#define SORT_R_SWAP(a,b,tmp) ((void) ((tmp) = (a)), (void) ((a) = (b)), (b) = (tmp))
/* swap a and b */
/* a and b must not be equal! */
diff --git a/thirdparty/harfbuzz/src/hb-array.hh b/thirdparty/harfbuzz/src/hb-array.hh
index 1d1476d7cd..826a901819 100644
--- a/thirdparty/harfbuzz/src/hb-array.hh
+++ b/thirdparty/harfbuzz/src/hb-array.hh
@@ -56,7 +56,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
hb_array_t& operator= (const hb_array_t&) = default;
hb_array_t& operator= (hb_array_t&&) = default;
- constexpr hb_array_t (std::nullptr_t) : hb_array_t () {}
constexpr hb_array_t (Type *array_, unsigned int length_) : arrayZ (array_), length (length_) {}
template <unsigned int length_>
constexpr hb_array_t (Type (&array_)[length_]) : hb_array_t (array_, length_) {}
@@ -101,10 +100,9 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
/* Ouch. The operator== compares the contents of the array. For range-based for loops,
* it's best if we can just compare arrayZ, though comparing contents is still fast,
* but also would require that Type has operator==. As such, we optimize this operator
- * for range-based for loop and just compare arrayZ. No need to compare length, as we
- * assume we're only compared to .end(). */
+ * for range-based for loop and just compare arrayZ and length. */
bool operator != (const hb_array_t& o) const
- { return arrayZ != o.arrayZ; }
+ { return this->arrayZ != o.arrayZ || this->length != o.length; }
/* Extra operators.
*/
@@ -221,11 +219,8 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
if (end < start + 2)
return;
- for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--) {
- Type temp = arrayZ[rhs];
- arrayZ[rhs] = arrayZ[lhs];
- arrayZ[lhs] = temp;
- }
+ for (unsigned lhs = start, rhs = end - 1; lhs < rhs; lhs++, rhs--)
+ hb_swap (arrayZ[rhs], arrayZ[lhs]);
}
hb_array_t sub_array (unsigned int start_offset = 0, unsigned int *seg_count = nullptr /* IN/OUT */) const
@@ -314,7 +309,6 @@ struct hb_sorted_array_t :
hb_sorted_array_t& operator= (const hb_sorted_array_t&) = default;
hb_sorted_array_t& operator= (hb_sorted_array_t&&) = default;
- constexpr hb_sorted_array_t (std::nullptr_t) : hb_sorted_array_t () {}
constexpr hb_sorted_array_t (Type *array_, unsigned int length_) : hb_array_t<Type> (array_, length_) {}
template <unsigned int length_>
constexpr hb_sorted_array_t (Type (&array_)[length_]) : hb_array_t<Type> (array_) {}
@@ -330,6 +324,8 @@ struct hb_sorted_array_t :
{ hb_array_t<Type> (*this) = o; return *this; }
/* Iterator implementation. */
+
+ /* See comment in hb_array_of::operator != */
bool operator != (const hb_sorted_array_t& o) const
{ return this->arrayZ != o.arrayZ || this->length != o.length; }
@@ -346,7 +342,7 @@ struct hb_sorted_array_t :
unsigned int i;
return bfind (x, &i) ? &this->arrayZ[i] : not_found;
}
- template <typename T>
+ template <typename T, typename ...Ts>
const Type *bsearch (const T &x, const Type *not_found = nullptr) const
{
unsigned int i;
@@ -384,15 +380,16 @@ struct hb_sorted_array_t :
}
return false;
}
- template <typename T>
- bool bsearch_impl (const T &x, unsigned *pos) const
+ template <typename T, typename ...Ts>
+ bool bsearch_impl (const T &x, unsigned *pos, Ts... ds) const
{
return hb_bsearch_impl (pos,
x,
this->arrayZ,
this->length,
sizeof (Type),
- _hb_cmp_method<T, Type>);
+ _hb_cmp_method<T, Type, Ts...>,
+ ds...);
}
};
template <typename T> inline hb_sorted_array_t<T>
@@ -403,7 +400,7 @@ hb_sorted_array (T (&array_)[length_])
{ return hb_sorted_array_t<T> (array_); }
template <typename T>
-bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
+inline bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
{
if (o.length != this->length) return false;
for (unsigned int i = 0; i < this->length; i++) {
@@ -411,8 +408,18 @@ bool hb_array_t<T>::operator == (const hb_array_t<T> &o) const
}
return true;
}
-
-/* TODO Specialize operator== for hb_bytes_t and hb_ubytes_t. */
+template <>
+inline bool hb_array_t<const char>::operator == (const hb_array_t<const char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
+template <>
+inline bool hb_array_t<const unsigned char>::operator == (const hb_array_t<const unsigned char> &o) const
+{
+ if (o.length != this->length) return false;
+ return 0 == hb_memcmp (arrayZ, o.arrayZ, length);
+}
template <>
inline uint32_t hb_array_t<const char>::hash () const {
@@ -421,7 +428,6 @@ inline uint32_t hb_array_t<const char>::hash () const {
current = current * 31 + (uint32_t) (this->arrayZ[i] * 2654435761u);
return current;
}
-
template <>
inline uint32_t hb_array_t<const unsigned char>::hash () const {
uint32_t current = 0;
diff --git a/thirdparty/harfbuzz/src/hb-atomic.hh b/thirdparty/harfbuzz/src/hb-atomic.hh
index e640d1b586..d6dfb0f57a 100644
--- a/thirdparty/harfbuzz/src/hb-atomic.hh
+++ b/thirdparty/harfbuzz/src/hb-atomic.hh
@@ -111,6 +111,19 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
#endif
+#ifndef _hb_compiler_memory_r_barrier
+/* This we always use std::atomic for; and should never be disabled...
+ * except that MSVC gives me an internal compiler error on it. */
+#if !defined(_MSC_VER)
+#include <atomic>
+#define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
+#else
+#define _hb_compiler_memory_r_barrier() do {} while (0)
+#endif
+#endif
+
+
+
#ifndef _hb_memory_r_barrier
#define _hb_memory_r_barrier() _hb_memory_barrier ()
#endif
diff --git a/thirdparty/harfbuzz/src/hb-bimap.hh b/thirdparty/harfbuzz/src/hb-bimap.hh
index a9e1278de7..8e8c988716 100644
--- a/thirdparty/harfbuzz/src/hb-bimap.hh
+++ b/thirdparty/harfbuzz/src/hb-bimap.hh
@@ -39,6 +39,12 @@ struct hb_bimap_t
back_map.reset ();
}
+ void resize (unsigned pop)
+ {
+ forw_map.resize (pop);
+ back_map.resize (pop);
+ }
+
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
void set (hb_codepoint_t lhs, hb_codepoint_t rhs)
@@ -48,17 +54,18 @@ struct hb_bimap_t
if (unlikely (rhs == HB_MAP_VALUE_INVALID)) { del (lhs); return; }
forw_map.set (lhs, rhs);
- if (in_error ()) return;
+ if (unlikely (in_error ())) return;
back_map.set (rhs, lhs);
- if (in_error ()) forw_map.del (lhs);
+ if (unlikely (in_error ())) forw_map.del (lhs);
}
hb_codepoint_t get (hb_codepoint_t lhs) const { return forw_map.get (lhs); }
hb_codepoint_t backward (hb_codepoint_t rhs) const { return back_map.get (rhs); }
hb_codepoint_t operator [] (hb_codepoint_t lhs) const { return get (lhs); }
- bool has (hb_codepoint_t lhs, hb_codepoint_t *vp = nullptr) const { return forw_map.has (lhs, vp); }
+ bool has (hb_codepoint_t lhs) const { return forw_map.has (lhs); }
+
void del (hb_codepoint_t lhs)
{
@@ -72,7 +79,7 @@ struct hb_bimap_t
back_map.clear ();
}
- bool is_empty () const { return get_population () == 0; }
+ bool is_empty () const { return forw_map.is_empty (); }
unsigned int get_population () const { return forw_map.get_population (); }
diff --git a/thirdparty/harfbuzz/src/hb-bit-page.hh b/thirdparty/harfbuzz/src/hb-bit-page.hh
index 263be3d044..95ae1b7bf9 100644
--- a/thirdparty/harfbuzz/src/hb-bit-page.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-page.hh
@@ -40,15 +40,22 @@ struct hb_bit_page_t
bool is_empty () const
{
- for (unsigned int i = 0; i < len (); i++)
+ for (unsigned i = 0; i < len (); i++)
if (v[i])
return false;
return true;
}
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (unsigned i = 0; i < len (); i++)
+ h = h * 31 + hb_hash (v[i]);
+ return h;
+ }
void add (hb_codepoint_t g) { elt (g) |= mask (g); }
void del (hb_codepoint_t g) { elt (g) &= ~mask (g); }
- void set (hb_codepoint_t g, bool v) { if (v) add (g); else del (g); }
+ void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); }
bool get (hb_codepoint_t g) const { return elt (g) & mask (g); }
void add_range (hb_codepoint_t a, hb_codepoint_t b)
@@ -86,6 +93,72 @@ struct hb_bit_page_t
void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v)
{ if (v) add_range (a, b); else del_range (a, b); }
+
+ // Writes out page values to the array p. Returns the number of values
+ // written. At most size codepoints will be written.
+ unsigned int write (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_base = base | (i << ELT_BITS_LOG_2);
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits) {
+ *p++ = v_base | j;
+ count++;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
+ // Writes out the values NOT in this page to the array p. Returns the
+ // number of values written. At most size codepoints will be written.
+ // Returns the number of codepoints written. next_value holds the next value
+ // that should be written (if not present in this page). This is used to fill
+ // any missing value gaps between this page and the previous page, if any.
+ // next_value is updated to one more than the last value present in this page.
+ unsigned int write_inverted (uint32_t base,
+ unsigned int start_value,
+ hb_codepoint_t *p,
+ unsigned int size,
+ hb_codepoint_t *next_value) const
+ {
+ unsigned int start_v = start_value >> ELT_BITS_LOG_2;
+ unsigned int start_bit = start_value & ELT_MASK;
+ unsigned int count = 0;
+ for (unsigned i = start_v; i < len () && count < size; i++)
+ {
+ elt_t bits = v[i];
+ uint32_t v_offset = i << ELT_BITS_LOG_2;
+ for (unsigned int j = start_bit; j < ELT_BITS && count < size; j++)
+ {
+ if ((elt_t(1) << j) & bits)
+ {
+ hb_codepoint_t value = base | v_offset | j;
+ // Emit all the missing values from next_value up to value - 1.
+ for (hb_codepoint_t k = *next_value; k < value && count < size; k++)
+ {
+ *p++ = k;
+ count++;
+ }
+ // Skip over this value;
+ *next_value = value + 1;
+ }
+ }
+ start_bit = 0;
+ }
+ return count;
+ }
+
bool is_equal (const hb_bit_page_t &other) const
{
return 0 == hb_memcmp (&v, &other.v, sizeof (v));
@@ -179,6 +252,9 @@ struct hb_bit_page_t
typedef unsigned long long elt_t;
static constexpr unsigned PAGE_BITS = 512;
static_assert ((PAGE_BITS & ((PAGE_BITS) - 1)) == 0, "");
+ static constexpr unsigned PAGE_BITS_LOG_2 = 9;
+ static_assert (1 << PAGE_BITS_LOG_2 == PAGE_BITS, "");
+ static constexpr unsigned PAGE_BITMASK = PAGE_BITS - 1;
static unsigned int elt_get_min (const elt_t &elt) { return hb_ctz (elt); }
static unsigned int elt_get_max (const elt_t &elt) { return hb_bit_storage (elt) - 1; }
@@ -186,7 +262,10 @@ struct hb_bit_page_t
typedef hb_vector_size_t<elt_t, PAGE_BITS / 8> vector_t;
static constexpr unsigned ELT_BITS = sizeof (elt_t) * 8;
+ static constexpr unsigned ELT_BITS_LOG_2 = 6;
+ static_assert (1 << ELT_BITS_LOG_2 == ELT_BITS, "");
static constexpr unsigned ELT_MASK = ELT_BITS - 1;
+
static constexpr unsigned BITS = sizeof (vector_t) * 8;
static constexpr unsigned MASK = BITS - 1;
static_assert ((unsigned) PAGE_BITS == (unsigned) BITS, "");
diff --git a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
index 0832b0fc23..27fb0732ea 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set-invertible.hh
@@ -38,10 +38,10 @@ struct hb_bit_set_invertible_t
bool inverted = false;
hb_bit_set_invertible_t () = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
+ hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) : hb_bit_set_invertible_t () { hb_swap (*this, other); }
hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
- hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default;
+ hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other) { hb_swap (*this, other); return *this; }
friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
{
if (likely (!a.s.successful || !b.s.successful))
@@ -56,6 +56,7 @@ struct hb_bit_set_invertible_t
bool in_error () const { return s.in_error (); }
explicit operator bool () const { return !is_empty (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
void reset ()
{
s.reset ();
@@ -79,6 +80,8 @@ struct hb_bit_set_invertible_t
next (&v);
return v == INVALID;
}
+ uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; }
+
hb_codepoint_t get_min () const
{
hb_codepoint_t v = INVALID;
@@ -97,7 +100,7 @@ struct hb_bit_set_invertible_t
void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b)
- { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
+ { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); }
template <typename T>
void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
@@ -323,6 +326,14 @@ struct hb_bit_set_invertible_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ return inverted ? s.next_many_inverted (codepoint, out, size)
+ : s.next_many (codepoint, out, size);
+ }
+
static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
/*
diff --git a/thirdparty/harfbuzz/src/hb-bit-set.hh b/thirdparty/harfbuzz/src/hb-bit-set.hh
index a471ee48b5..4765af67ce 100644
--- a/thirdparty/harfbuzz/src/hb-bit-set.hh
+++ b/thirdparty/harfbuzz/src/hb-bit-set.hh
@@ -56,7 +56,7 @@ struct hb_bit_set_t
{
successful = true;
population = 0;
- last_page_lookup = 0;
+ last_page_lookup.set_relaxed (0);
page_map.init ();
pages.init ();
}
@@ -78,7 +78,7 @@ struct hb_bit_set_t
bool successful = true; /* Allocations successful */
mutable unsigned int population = 0;
- mutable unsigned int last_page_lookup = 0;
+ mutable hb_atomic_int_t last_page_lookup = 0;
hb_sorted_vector_t<page_map_t> page_map;
hb_vector_t<page_t> pages;
@@ -97,6 +97,13 @@ struct hb_bit_set_t
return true;
}
+ void alloc (unsigned sz)
+ {
+ sz >>= (page_t::PAGE_BITS_LOG_2 - 1);
+ pages.alloc (sz);
+ page_map.alloc (sz);
+ }
+
void reset ()
{
successful = true;
@@ -119,6 +126,14 @@ struct hb_bit_set_t
}
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (auto &map : page_map)
+ h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
+ return h;
+ }
+
private:
void dirty () { population = UINT_MAX; }
public:
@@ -203,7 +218,7 @@ struct hb_bit_set_t
bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
{
if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
- if (!count) return true;
+ if (unlikely (!count)) return true;
dirty ();
hb_codepoint_t g = *array;
hb_codepoint_t last_g = g;
@@ -222,7 +237,7 @@ struct hb_bit_set_t
if (v || page) /* The v check is to optimize out the page check if v is true. */
page->add (g);
- array = (const T *) ((const char *) array + stride);
+ array = &StructAtOffsetUnaligned<T> (array, stride);
count--;
}
while (count && (g = *array, g < end));
@@ -341,15 +356,14 @@ struct hb_bit_set_t
return;
population = other.population;
- /* TODO switch to vector operator =. */
- hb_memcpy ((void *) pages, (const void *) other.pages, count * pages.item_size);
- hb_memcpy ((void *) page_map, (const void *) other.page_map, count * page_map.item_size);
+ page_map = other.page_map;
+ pages = other.pages;
}
bool is_equal (const hb_bit_set_t &other) const
{
if (has_population () && other.has_population () &&
- get_population () != other.get_population ())
+ population != other.population)
return false;
unsigned int na = pages.length;
@@ -377,7 +391,7 @@ struct hb_bit_set_t
bool is_subset (const hb_bit_set_t &larger_set) const
{
if (has_population () && larger_set.has_population () &&
- get_population () != larger_set.get_population ())
+ population != larger_set.population)
return false;
uint32_t spi = 0;
@@ -451,12 +465,10 @@ struct hb_bit_set_t
}
public:
- template <typename Op>
- void process (const Op& op, const hb_bit_set_t &other)
+ void process_ (hb_bit_page_t::vector_t (*op) (const hb_bit_page_t::vector_t &, const hb_bit_page_t::vector_t &),
+ bool passthru_left, bool passthru_right,
+ const hb_bit_set_t &other)
{
- const bool passthru_left = op (1, 0);
- const bool passthru_right = op (0, 1);
-
if (unlikely (!successful)) return;
dirty ();
@@ -576,6 +588,15 @@ struct hb_bit_set_t
assert (!count);
resize (newCount);
}
+ template <typename Op>
+ static hb_bit_page_t::vector_t
+ op_ (const hb_bit_page_t::vector_t &a, const hb_bit_page_t::vector_t &b)
+ { return Op{} (a, b); }
+ template <typename Op>
+ void process (const Op& op, const hb_bit_set_t &other)
+ {
+ process_ (op_<Op>, op (1, 0), op (0, 1), other);
+ }
void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
@@ -593,7 +614,7 @@ struct hb_bit_set_t
const auto* page_map_array = page_map.arrayZ;
unsigned int major = get_major (*codepoint);
- unsigned int i = last_page_lookup;
+ unsigned int i = last_page_lookup.get_relaxed ();
if (unlikely (i >= page_map.length || page_map_array[i].major != major))
{
@@ -611,7 +632,7 @@ struct hb_bit_set_t
if (pages_array[current.index].next (codepoint))
{
*codepoint += current.major * page_t::PAGE_BITS;
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return true;
}
i++;
@@ -624,11 +645,11 @@ struct hb_bit_set_t
if (m != INVALID)
{
*codepoint = current.major * page_t::PAGE_BITS + m;
- last_page_lookup = i;
+ last_page_lookup.set_relaxed (i);
return true;
}
}
- last_page_lookup = 0;
+ last_page_lookup.set_relaxed (0);
*codepoint = INVALID;
return false;
}
@@ -700,6 +721,99 @@ struct hb_bit_set_t
return true;
}
+ unsigned int next_many (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup.get_relaxed ();
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (i >= page_map.length)
+ return 0; // codepoint is greater than our max element.
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ unsigned int initial_size = size;
+ for (unsigned int i = start_page; i < page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ return initial_size - size;
+ }
+
+ unsigned int next_many_inverted (hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size) const
+ {
+ unsigned int initial_size = size;
+ // By default, start at the first bit of the first page of values.
+ unsigned int start_page = 0;
+ unsigned int start_page_value = 0;
+ if (unlikely (codepoint != INVALID))
+ {
+ const auto* page_map_array = page_map.arrayZ;
+ unsigned int major = get_major (codepoint);
+ unsigned int i = last_page_lookup.get_relaxed ();
+ if (unlikely (i >= page_map.length || page_map_array[i].major != major))
+ {
+ page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST);
+ if (unlikely (i >= page_map.length))
+ {
+ // codepoint is greater than our max element.
+ while (++codepoint != INVALID && size)
+ {
+ *out++ = codepoint;
+ size--;
+ }
+ return initial_size - size;
+ }
+ }
+ start_page = i;
+ start_page_value = page_remainder (codepoint + 1);
+ if (unlikely (start_page_value == 0))
+ {
+ // The export-after value was last in the page. Start on next page.
+ start_page++;
+ start_page_value = 0;
+ }
+ }
+
+ hb_codepoint_t next_value = codepoint + 1;
+ for (unsigned int i=start_page; i<page_map.length && size; i++)
+ {
+ uint32_t base = major_start (page_map[i].major);
+ unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
+ out += n;
+ size -= n;
+ start_page_value = 0;
+ }
+ while (next_value < HB_SET_VALUE_INVALID && size) {
+ *out++ = next_value++;
+ size--;
+ }
+ return initial_size - size;
+ }
+
bool has_population () const { return population != UINT_MAX; }
unsigned int get_population () const
{
@@ -781,8 +895,20 @@ struct hb_bit_set_t
page_t *page_for (hb_codepoint_t g, bool insert = false)
{
- page_map_t map = {get_major (g), pages.length};
- unsigned int i;
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ unsigned i = last_page_lookup.get_relaxed ();
+ if (likely (i < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[i];
+ if (cached_page.major == major)
+ return &pages[cached_page.index];
+ }
+
+ page_map_t map = {major, pages.length};
if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
{
if (!insert)
@@ -797,20 +923,37 @@ struct hb_bit_set_t
(page_map.length - 1 - i) * page_map.item_size);
page_map[i] = map;
}
+
+ last_page_lookup.set_relaxed (i);
return &pages[page_map[i].index];
}
const page_t *page_for (hb_codepoint_t g) const
{
- page_map_t key = {get_major (g)};
- const page_map_t *found = page_map.bsearch (key);
- if (found)
- return &pages[found->index];
- return nullptr;
+ unsigned major = get_major (g);
+
+ /* The extra page_map length is necessary; can't just rely on vector here,
+ * since the next check would be tricked because a null page also has
+ * major==0, which we can't distinguish from an actualy major==0 page... */
+ unsigned i = last_page_lookup.get_relaxed ();
+ if (likely (i < page_map.length))
+ {
+ auto &cached_page = page_map.arrayZ[i];
+ if (cached_page.major == major)
+ return &pages[cached_page.index];
+ }
+
+ page_map_t key = {major};
+ if (!page_map.bfind (key, &i))
+ return nullptr;
+
+ last_page_lookup.set_relaxed (i);
+ return &pages[page_map[i].index];
}
page_t &page_at (unsigned int i) { return pages[page_map[i].index]; }
const page_t &page_at (unsigned int i) const { return pages[page_map[i].index]; }
- unsigned int get_major (hb_codepoint_t g) const { return g / page_t::PAGE_BITS; }
- hb_codepoint_t major_start (unsigned int major) const { return major * page_t::PAGE_BITS; }
+ unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
+ unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
+ hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
};
diff --git a/thirdparty/harfbuzz/src/hb-blob.cc b/thirdparty/harfbuzz/src/hb-blob.cc
index f120002d17..9bc12ea3fa 100644
--- a/thirdparty/harfbuzz/src/hb-blob.cc
+++ b/thirdparty/harfbuzz/src/hb-blob.cc
@@ -99,7 +99,7 @@ hb_blob_create (const char *data,
* is zero. This is in contrast to hb_blob_create(), which returns the singleton
* empty blob (as returned by hb_blob_get_empty()) if @length is zero.
*
- * Return value: New blob, or %NULL if failed. Destroy with hb_blob_destroy().
+ * Return value: New blob, or `NULL` if failed. Destroy with hb_blob_destroy().
*
* Since: 2.8.2
**/
@@ -263,8 +263,6 @@ hb_blob_destroy (hb_blob_t *blob)
{
if (!hb_object_destroy (blob)) return;
- blob->fini_shallow ();
-
hb_free (blob);
}
@@ -278,7 +276,7 @@ hb_blob_destroy (hb_blob_t *blob)
*
* Attaches a user-data key/data pair to the specified blob.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -305,7 +303,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
* Since: 0.9.2
**/
void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (blob, key);
@@ -335,7 +333,7 @@ hb_blob_make_immutable (hb_blob_t *blob)
*
* Tests whether a blob is immutable.
*
- * Return value: %true if @blob is immutable, %false otherwise
+ * Return value: `true` if @blob is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -369,7 +367,7 @@ hb_blob_get_length (hb_blob_t *blob)
*
* Fetches the data from a blob.
*
- * Returns: (transfer none) (array length=length): the byte data of @blob.
+ * Returns: (nullable) (transfer none) (array length=length): the byte data of @blob.
*
* Since: 0.9.2
**/
@@ -394,7 +392,7 @@ hb_blob_get_data (hb_blob_t *blob, unsigned int *length)
* fails.
*
* Returns: (transfer none) (array length=length): Writable blob data,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 0.9.2
**/
@@ -572,7 +570,7 @@ _open_resource_fork (const char *file_name, hb_mapped_file_t *file)
strncpy (rsrc_name, file_name, name_len);
strncpy (rsrc_name + name_len, _PATH_RSRCFORKSPEC,
- sizeof (_PATH_RSRCFORKSPEC) - 1);
+ sizeof (_PATH_RSRCFORKSPEC));
int fd = open (rsrc_name, O_RDONLY | O_BINARY, 0);
hb_free (rsrc_name);
@@ -620,7 +618,7 @@ hb_blob_create_from_file (const char *file_name)
* specified binary font file.
*
* Returns: An #hb_blob_t pointer with the content of the file,
- * or %NULL if failed.
+ * or `NULL` if failed.
*
* Since: 2.8.2
**/
@@ -631,7 +629,7 @@ hb_blob_create_from_file_or_fail (const char *file_name)
Allison Lortie permission but changed a lot to suit our need. */
#if defined(HAVE_MMAP) && !defined(HB_NO_MMAP)
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
- if (unlikely (!file)) return hb_blob_get_empty ();
+ if (unlikely (!file)) return nullptr;
int fd = open (file_name, O_RDONLY | O_BINARY, 0);
if (unlikely (fd == -1)) goto fail_without_close;
@@ -671,7 +669,7 @@ fail_without_close:
#elif defined(_WIN32) && !defined(HB_NO_MMAP)
hb_mapped_file_t *file = (hb_mapped_file_t *) hb_calloc (1, sizeof (hb_mapped_file_t));
- if (unlikely (!file)) return hb_blob_get_empty ();
+ if (unlikely (!file)) return nullptr;
HANDLE fd;
unsigned int size = strlen (file_name) + 1;
diff --git a/thirdparty/harfbuzz/src/hb-blob.h b/thirdparty/harfbuzz/src/hb-blob.h
index 203f9e19dd..4eb42314da 100644
--- a/thirdparty/harfbuzz/src/hb-blob.h
+++ b/thirdparty/harfbuzz/src/hb-blob.h
@@ -135,7 +135,7 @@ hb_blob_set_user_data (hb_blob_t *blob,
HB_EXTERN void *
-hb_blob_get_user_data (hb_blob_t *blob,
+hb_blob_get_user_data (const hb_blob_t *blob,
hb_user_data_key_t *key);
diff --git a/thirdparty/harfbuzz/src/hb-blob.hh b/thirdparty/harfbuzz/src/hb-blob.hh
index a3683a681e..b1b3b94d3d 100644
--- a/thirdparty/harfbuzz/src/hb-blob.hh
+++ b/thirdparty/harfbuzz/src/hb-blob.hh
@@ -38,7 +38,7 @@
struct hb_blob_t
{
- void fini_shallow () { destroy_user_data (); }
+ ~hb_blob_t () { destroy_user_data (); }
void destroy_user_data ()
{
@@ -61,12 +61,12 @@ struct hb_blob_t
public:
hb_object_header_t header;
- const char *data;
- unsigned int length;
- hb_memory_mode_t mode;
+ const char *data = nullptr;
+ unsigned int length = 0;
+ hb_memory_mode_t mode = (hb_memory_mode_t) 0;
- void *user_data;
- hb_destroy_func_t destroy;
+ void *user_data = nullptr;
+ hb_destroy_func_t destroy = nullptr;
};
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
index e80cfea6e7..44c802a00c 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-json.hh
@@ -32,15 +32,16 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-json.hh"
+#line 33 "hb-buffer-deserialize-json.hh"
static const unsigned char _deserialize_json_trans_keys[] = {
0u, 0u, 9u, 123u, 9u, 34u, 97u, 117u, 120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u,
48u, 57u, 9u, 125u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u,
9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 125u,
120u, 121u, 34u, 34u, 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u,
- 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
- 34u, 92u, 9u, 125u, 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u,
- 9u, 125u, 9u, 93u, 9u, 123u, 0u, 0u, 0
+ 9u, 58u, 9u, 57u, 48u, 57u, 9u, 125u, 9u, 125u, 108u, 108u, 34u, 34u, 9u, 58u,
+ 9u, 57u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 34u, 92u, 9u, 125u,
+ 34u, 92u, 9u, 125u, 9u, 125u, 34u, 34u, 9u, 58u, 9u, 57u, 9u, 125u, 9u, 93u,
+ 9u, 123u, 0u, 0u, 0
};
static const char _deserialize_json_key_spans[] = {
@@ -48,9 +49,10 @@ static const char _deserialize_json_key_spans[] = {
10, 117, 117, 117, 1, 50, 49, 10,
117, 117, 1, 1, 50, 49, 117, 117,
2, 1, 50, 49, 10, 117, 117, 1,
- 50, 49, 10, 117, 117, 1, 50, 49,
- 59, 117, 59, 117, 117, 1, 50, 49,
- 117, 85, 115, 0
+ 50, 49, 10, 117, 117, 1, 1, 50,
+ 49, 117, 117, 1, 50, 49, 59, 117,
+ 59, 117, 117, 1, 50, 49, 117, 85,
+ 115, 0
};
static const short _deserialize_json_index_offsets[] = {
@@ -58,9 +60,10 @@ static const short _deserialize_json_index_offsets[] = {
271, 282, 400, 518, 636, 638, 689, 739,
750, 868, 986, 988, 990, 1041, 1091, 1209,
1327, 1330, 1332, 1383, 1433, 1444, 1562, 1680,
- 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2083,
- 2133, 2193, 2311, 2371, 2489, 2607, 2609, 2660,
- 2710, 2828, 2914, 3030
+ 1682, 1733, 1783, 1794, 1912, 2030, 2032, 2034,
+ 2085, 2135, 2253, 2371, 2373, 2424, 2474, 2534,
+ 2652, 2712, 2830, 2948, 2950, 3001, 3051, 3169,
+ 3255, 3371
};
static const char _deserialize_json_indicies[] = {
@@ -82,28 +85,28 @@ static const char _deserialize_json_indicies[] = {
3, 3, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 4, 1,
- 5, 1, 6, 7, 1, 1, 8, 1,
+ 5, 1, 6, 7, 1, 8, 9, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 9, 1, 10, 11,
- 1, 12, 1, 12, 12, 12, 12, 12,
+ 1, 1, 1, 1, 10, 1, 11, 12,
+ 1, 13, 1, 13, 13, 13, 13, 13,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 12, 1, 1, 1, 1, 1,
+ 1, 1, 13, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 13, 1, 13, 13,
- 13, 13, 13, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 14, 1, 14, 14,
+ 14, 14, 14, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 13, 1, 1,
+ 1, 1, 1, 1, 1, 14, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 1, 1, 15, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 1,
- 17, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 1, 19, 19, 19, 19, 19,
+ 1, 1, 15, 1, 1, 16, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 1,
+ 18, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 1, 20, 20, 20, 20, 20,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 19, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 20, 1,
+ 1, 1, 20, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 21, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -113,11 +116,11 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 21,
- 1, 22, 22, 22, 22, 22, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 22,
+ 1, 23, 23, 23, 23, 23, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 22, 1, 1, 1, 1, 1, 1, 1,
+ 23, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 3, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -128,41 +131,58 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 23, 1, 19,
- 19, 19, 19, 19, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 24, 1, 20,
+ 20, 20, 20, 20, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 20, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 21, 1, 1, 1, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 22, 1, 25, 1, 25,
+ 25, 25, 25, 25, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 25, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 19, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 20, 1, 1, 1, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18,
+ 26, 1, 26, 26, 26, 26, 26, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 26, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 27, 1,
+ 1, 28, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 1, 30, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 1, 32,
+ 32, 32, 32, 32, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 32, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 33, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 21, 1, 24, 1, 24,
- 24, 24, 24, 24, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 24, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 25, 1, 25, 25, 25, 25, 25, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 34, 1, 32, 32, 32,
+ 32, 32, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 25, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 26, 1,
- 1, 27, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 1, 29, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 31,
- 31, 31, 31, 31, 1, 1, 1, 1,
+ 1, 1, 1, 1, 32, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 31, 1,
+ 33, 1, 1, 1, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 32, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -170,41 +190,41 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 34, 1, 35, 1, 36, 1, 36,
+ 36, 36, 36, 36, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 36, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 33, 1, 31, 31, 31,
- 31, 31, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 31, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 32, 1, 1, 1, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 1, 1,
+ 37, 1, 37, 37, 37, 37, 37, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 37, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 38, 39, 39, 39, 39, 39, 39,
+ 39, 39, 39, 1, 40, 40, 40, 40,
+ 40, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 40, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 41,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 33, 1, 34, 1, 35, 1, 35,
- 35, 35, 35, 35, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 35, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 36, 1, 36, 36, 36, 36, 36, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 36, 1, 1, 1, 1, 1, 1,
+ 42, 1, 40, 40, 40, 40, 40, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 37, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 1, 39, 39, 39, 39,
- 39, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 39, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 40, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 41, 1, 1,
+ 1, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -212,137 +232,130 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 42, 1,
+ 44, 45, 1, 46, 1, 46, 46, 46,
+ 46, 46, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 46, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 41, 1, 39, 39, 39, 39, 39, 1,
+ 1, 1, 1, 1, 1, 1, 47, 1,
+ 47, 47, 47, 47, 47, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 47,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 40, 1, 1,
- 1, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 48, 1, 1, 49,
+ 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 1, 51, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 1, 53, 53, 53,
+ 53, 53, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 53, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 54, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 41, 1,
- 43, 44, 1, 45, 1, 45, 45, 45,
- 45, 45, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 45, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 46, 1,
- 46, 46, 46, 46, 46, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 46,
+ 1, 55, 1, 53, 53, 53, 53, 53,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 47, 1, 1, 48,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 1, 50, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1, 52, 52, 52,
- 52, 52, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 52, 1, 1, 1,
+ 1, 1, 53, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 54, 1,
+ 1, 1, 52, 52, 52, 52, 52, 52,
+ 52, 52, 52, 52, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 53, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 55,
+ 1, 56, 1, 56, 56, 56, 56, 56,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 56, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 54, 1, 52, 52, 52, 52, 52,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 57, 1, 57, 57,
+ 57, 57, 57, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 52, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 53, 1,
- 1, 1, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 57, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 58, 1, 1, 59, 60, 60,
+ 60, 60, 60, 60, 60, 60, 60, 1,
+ 61, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 1, 63, 63, 63, 63, 63,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 63, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 64, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 54,
- 1, 55, 1, 55, 55, 55, 55, 55,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 55, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 56, 1, 56, 56,
- 56, 56, 56, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 56, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 65,
+ 1, 63, 63, 63, 63, 63, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 57, 1, 1, 58, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 1,
- 60, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 1, 62, 62, 62, 62, 62,
1, 1, 1, 1, 1, 1, 1, 1,
+ 63, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 64, 1, 1, 1,
+ 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 62, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 63, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 65, 1, 66,
+ 1, 67, 1, 67, 67, 67, 67, 67,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 67, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 64,
- 1, 62, 62, 62, 62, 62, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 68, 1, 68, 68,
+ 68, 68, 68, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 62, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 63, 1, 1, 1,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 68, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 69, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 1,
+ 71, 71, 71, 71, 71, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 71,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 72, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 1, 65,
- 1, 65, 65, 65, 65, 65, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 65, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 66, 1, 66, 66, 66, 66,
- 66, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 66, 1, 67, 1, 1,
+ 1, 1, 1, 1, 73, 1, 71, 71,
+ 71, 71, 71, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 68, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 1, 71, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70,
- 72, 70, 73, 73, 73, 73, 73, 1,
+ 1, 1, 1, 1, 1, 71, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 72, 1, 1, 1, 74, 74, 74,
+ 74, 74, 74, 74, 74, 74, 74, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 73, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 74, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -350,21 +363,33 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 73, 1, 75, 1, 75, 75,
+ 75, 75, 75, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 75, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 75, 1,
- 70, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 76,
+ 1, 76, 76, 76, 76, 76, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 76, 1, 77, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 78, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 1, 81, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80,
+ 80, 80, 80, 80, 80, 82, 80, 83,
+ 83, 83, 83, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 83, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 70, 1, 76, 76, 76, 76,
- 76, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 84, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 76, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 77,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -373,67 +398,85 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 85, 1, 80, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 78, 1, 76, 76, 76, 76, 76, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 76, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 77, 1, 1,
- 1, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 80,
+ 1, 86, 86, 86, 86, 86, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 86, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 78, 1,
- 80, 1, 80, 80, 80, 80, 80, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 80, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 88, 1, 86,
+ 86, 86, 86, 86, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 81, 1, 81, 81, 81,
- 81, 81, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 86, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 81, 1, 1, 1,
+ 1, 1, 87, 1, 1, 1, 89, 89,
+ 89, 89, 89, 89, 89, 89, 89, 89,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 82, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 1, 76,
- 76, 76, 76, 76, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 76, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 77, 1, 1, 1, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 88, 1, 90, 1, 90,
+ 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 90, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 78, 1, 85, 85, 85,
- 85, 85, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 85, 1, 1, 1,
+ 91, 1, 91, 91, 91, 91, 91, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 91, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 92, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 1, 86, 86, 86, 86,
86, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 86, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 87,
+ 1, 1, 1, 94, 94, 94, 94, 94,
+ 94, 94, 94, 94, 94, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 95, 95, 95, 95, 95, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 95, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 96, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 87, 1, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 97, 1,
+ 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -442,46 +485,52 @@ static const char _deserialize_json_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 1, 1,
- 0
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 1, 1, 0
};
static const char _deserialize_json_trans_targs[] = {
1, 0, 2, 2, 3, 4, 18, 24,
- 37, 45, 5, 12, 6, 7, 8, 9,
- 11, 9, 11, 10, 2, 49, 10, 49,
- 13, 14, 15, 16, 17, 16, 17, 10,
- 2, 49, 19, 20, 21, 22, 23, 10,
- 2, 49, 23, 25, 31, 26, 27, 28,
- 29, 30, 29, 30, 10, 2, 49, 32,
- 33, 34, 35, 36, 35, 36, 10, 2,
- 49, 38, 39, 40, 43, 44, 40, 41,
- 42, 10, 2, 49, 10, 2, 49, 44,
- 46, 47, 43, 48, 48, 49, 50, 51
+ 37, 43, 51, 5, 12, 6, 7, 8,
+ 9, 11, 9, 11, 10, 2, 55, 10,
+ 55, 13, 14, 15, 16, 17, 16, 17,
+ 10, 2, 55, 19, 20, 21, 22, 23,
+ 10, 2, 55, 23, 25, 31, 26, 27,
+ 28, 29, 30, 29, 30, 10, 2, 55,
+ 32, 33, 34, 35, 36, 35, 36, 10,
+ 2, 55, 38, 39, 40, 41, 42, 10,
+ 2, 55, 42, 44, 45, 46, 49, 50,
+ 46, 47, 48, 10, 2, 55, 10, 2,
+ 55, 50, 52, 53, 49, 54, 54, 55,
+ 56, 57
};
static const char _deserialize_json_trans_actions[] = {
0, 0, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 0, 0, 3, 3, 4, 0, 5,
- 0, 0, 2, 2, 2, 0, 0, 6,
- 6, 7, 0, 0, 0, 2, 2, 8,
- 8, 9, 0, 0, 0, 0, 0, 2,
- 2, 2, 0, 0, 10, 10, 11, 0,
- 0, 2, 2, 2, 0, 0, 12, 12,
- 13, 0, 0, 2, 14, 14, 0, 15,
- 0, 16, 16, 17, 18, 18, 19, 15,
- 0, 0, 20, 20, 21, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 2, 2, 0, 0, 3, 3, 4, 0,
+ 5, 0, 0, 2, 2, 2, 0, 0,
+ 6, 6, 7, 0, 0, 0, 2, 2,
+ 8, 8, 9, 0, 0, 0, 0, 0,
+ 2, 2, 2, 0, 0, 10, 10, 11,
+ 0, 0, 2, 2, 2, 0, 0, 12,
+ 12, 13, 0, 0, 0, 2, 2, 14,
+ 14, 15, 0, 0, 0, 2, 16, 16,
+ 0, 17, 0, 18, 18, 19, 20, 20,
+ 21, 17, 0, 0, 22, 22, 23, 0,
+ 0, 0
};
static const int deserialize_json_start = 1;
-static const int deserialize_json_first_final = 49;
+static const int deserialize_json_first_final = 55;
static const int deserialize_json_error = 0;
static const int deserialize_json_en_main = 1;
-#line 108 "hb-buffer-deserialize-json.rl"
+#line 111 "hb-buffer-deserialize-json.rl"
static hb_bool_t
@@ -508,12 +557,12 @@ _hb_buffer_deserialize_json (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 512 "hb-buffer-deserialize-json.hh"
+#line 554 "hb-buffer-deserialize-json.hh"
{
cs = deserialize_json_start;
}
-#line 517 "hb-buffer-deserialize-json.hh"
+#line 557 "hb-buffer-deserialize-json.hh"
{
int _slen;
int _trans;
@@ -561,25 +610,25 @@ _resume:
tok = p;
}
break;
- case 15:
+ case 17:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 21:
+ case 23:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 16:
+ case 18:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
break;
- case 18:
+ case 20:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
break;
@@ -604,6 +653,10 @@ _resume:
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
break;
case 14:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+ break;
+ case 16:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -611,7 +664,7 @@ _resume:
#line 55 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 20:
+ case 22:
#line 51 "hb-buffer-deserialize-json.rl"
{
tok = p;
@@ -619,12 +672,12 @@ _resume:
#line 56 "hb-buffer-deserialize-json.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 17:
+ case 19:
#line 58 "hb-buffer-deserialize-json.rl"
{
/* TODO Unescape \" and \\ if found. */
if (!hb_font_glyph_from_string (font,
- tok, p - tok,
+ tok+1, p - tok - 2, /* Skip "" */
&info.codepoint))
return false;
}
@@ -637,7 +690,7 @@ _resume:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 66 "hb-buffer-deserialize-json.rl"
{ if (!parse_uint (tok, p, &info.codepoint)) return false; }
#line 43 "hb-buffer-deserialize-json.rl"
@@ -709,7 +762,19 @@ _resume:
*end_ptr = p;
}
break;
-#line 713 "hb-buffer-deserialize-json.hh"
+ case 15:
+#line 72 "hb-buffer-deserialize-json.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-json.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+#line 735 "hb-buffer-deserialize-json.hh"
}
_again:
@@ -721,7 +786,7 @@ _again:
_out: {}
}
-#line 136 "hb-buffer-deserialize-json.rl"
+#line 139 "hb-buffer-deserialize-json.rl"
*end_ptr = p;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
index b599e9667c..8fbcdcc18c 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer-deserialize-text.hh
@@ -32,29 +32,32 @@
#include "hb.hh"
-#line 36 "hb-buffer-deserialize-text.hh"
+#line 33 "hb-buffer-deserialize-text.hh"
static const unsigned char _deserialize_text_trans_keys[] = {
0u, 0u, 9u, 91u, 85u, 85u, 43u, 43u, 48u, 102u, 9u, 85u, 48u, 57u, 45u, 57u,
- 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u, 44u, 57u,
- 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u, 9u, 124u,
+ 48u, 57u, 48u, 57u, 48u, 57u, 45u, 57u, 48u, 57u, 44u, 44u, 45u, 57u, 48u, 57u,
+ 44u, 57u, 43u, 124u, 45u, 57u, 48u, 57u, 9u, 124u, 9u, 124u, 0u, 0u, 9u, 85u,
9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
- 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 0
+ 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u, 9u, 124u,
+ 9u, 124u, 9u, 124u, 9u, 124u, 0
};
static const char _deserialize_text_key_spans[] = {
0, 83, 1, 1, 55, 77, 10, 13,
- 10, 10, 13, 10, 1, 13, 10, 14,
- 82, 13, 10, 116, 116, 0, 77, 116,
+ 10, 10, 10, 13, 10, 1, 13, 10,
+ 14, 82, 13, 10, 116, 116, 0, 77,
+ 116, 116, 116, 116, 116, 116, 116, 116,
116, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 116, 116, 116
+ 116, 116, 116
};
static const short _deserialize_text_index_offsets[] = {
0, 0, 84, 86, 88, 144, 222, 233,
- 247, 258, 269, 283, 294, 296, 310, 321,
- 336, 419, 433, 444, 561, 678, 679, 757,
- 874, 991, 1108, 1225, 1342, 1459, 1576, 1693,
- 1810, 1927, 2044, 2161, 2278
+ 247, 258, 269, 280, 294, 305, 307, 321,
+ 332, 347, 430, 444, 455, 572, 689, 690,
+ 768, 885, 1002, 1119, 1236, 1353, 1470, 1587,
+ 1704, 1821, 1938, 2055, 2172, 2289, 2406, 2523,
+ 2640, 2757, 2874
};
static const char _deserialize_text_indicies[] = {
@@ -91,50 +94,52 @@ static const char _deserialize_text_indicies[] = {
12, 12, 12, 12, 12, 12, 12, 1,
13, 14, 14, 14, 14, 14, 14, 14,
14, 14, 1, 15, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 1, 17, 1,
- 1, 18, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 1, 20, 21, 21, 21,
+ 16, 16, 16, 16, 16, 1, 17, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 1, 19, 1, 1, 20, 21, 21, 21,
21, 21, 21, 21, 21, 21, 1, 22,
- 1, 23, 1, 1, 24, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 1, 26,
+ 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 1, 24, 1, 25, 1, 1, 26,
27, 27, 27, 27, 27, 27, 27, 27,
- 27, 1, 22, 1, 1, 1, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,
- 1, 28, 28, 1, 1, 1, 1, 1,
+ 27, 1, 28, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 1, 24, 1, 1,
+ 1, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 1, 30, 30, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 28, 1, 1, 28, 1,
+ 1, 1, 1, 1, 1, 1, 30, 1,
+ 1, 30, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 30, 30, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 28, 28, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 30, 1, 31,
+ 1, 1, 32, 33, 33, 33, 33, 33,
+ 33, 33, 33, 33, 1, 34, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 1,
+ 36, 36, 36, 36, 36, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 28, 1, 29, 1, 1, 30,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 1, 32, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 1, 34, 34, 34,
- 34, 34, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 36,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 34, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 1, 1, 1, 38, 39, 1, 1,
+ 37, 37, 37, 37, 37, 37, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 1, 1,
- 1, 36, 37, 1, 1, 35, 35, 35,
- 35, 35, 35, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 35, 35, 35,
- 35, 35, 35, 1, 1, 1, 1, 1,
+ 37, 37, 37, 37, 37, 37, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 38, 1, 39, 39, 39, 39, 39, 1,
+ 1, 1, 1, 40, 1, 41, 41, 41,
+ 41, 41, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 41, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 39, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 40,
+ 1, 1, 42, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -142,24 +147,23 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 41, 1, 1,
- 7, 7, 7, 7, 7, 1, 1, 1,
+ 43, 1, 1, 7, 7, 7, 7, 7,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 7,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 7, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 4, 1, 42, 42,
- 42, 42, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 4,
+ 1, 44, 44, 44, 44, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 42, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 44, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 43, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -167,68 +171,83 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 44, 1, 42, 42, 42, 42, 42,
+ 1, 1, 1, 1, 46, 1, 44, 44,
+ 44, 44, 44, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 44, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 42, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 1,
+ 1, 1, 1, 45, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 1, 1, 1, 1,
- 43, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 44, 1,
- 47, 47, 47, 47, 47, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 47,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 48, 1, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 49, 46, 46, 50,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 51, 52, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 53, 46, 54, 54, 54,
- 54, 54, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 54, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 55,
- 1, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 56, 28, 28, 57, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 58, 59, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28,
- 60, 28, 61, 61, 61, 61, 61, 1,
+ 1, 46, 1, 49, 49, 49, 49, 49,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 49, 48, 48, 50, 48, 48,
+ 48, 48, 48, 48, 48, 51, 1, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 52,
+ 48, 48, 53, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 54, 55,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 56, 48,
+ 57, 57, 57, 57, 57, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 57,
+ 30, 30, 58, 30, 30, 30, 30, 30,
+ 30, 30, 59, 1, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 60, 30, 30, 61,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 62, 63, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 64, 30, 57, 57, 57,
+ 57, 57, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 57, 30, 30, 58,
+ 30, 30, 30, 30, 30, 30, 30, 59,
+ 1, 30, 30, 30, 65, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 30, 30,
+ 30, 60, 30, 30, 61, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 62, 63, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 64, 30, 67, 67, 67, 67, 67, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 61, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 62, 1, 1,
+ 1, 67, 1, 1, 68, 1, 1, 1,
+ 1, 1, 1, 1, 1, 69, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 63, 1,
+ 1, 1, 1, 1, 1, 1, 70, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 64, 1, 65,
- 65, 65, 65, 65, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 71, 1, 72,
+ 72, 72, 72, 72, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 65, 1,
+ 1, 1, 1, 1, 1, 1, 72, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
@@ -236,172 +255,238 @@ static const char _deserialize_text_indicies[] = {
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 40, 1, 1, 1, 1,
+ 1, 1, 1, 42, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 66, 1, 67, 67, 67, 67,
- 67, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 67, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 48, 1,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 49, 46, 46, 50, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 51,
- 52, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 46, 46, 46, 46, 53,
- 46, 68, 68, 68, 68, 68, 1, 1,
+ 1, 1, 73, 1, 74, 74, 74, 74,
+ 74, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 74, 48, 48, 50, 48,
+ 48, 48, 48, 48, 48, 48, 51, 1,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 52, 48, 48, 53, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 54,
+ 55, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 56,
+ 48, 75, 75, 75, 75, 75, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 68, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 69, 1, 1, 1, 1,
+ 75, 1, 1, 76, 1, 1, 1, 1,
+ 1, 1, 1, 77, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 70, 1, 1, 1, 1, 1, 1, 1,
+ 78, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 43, 1, 1,
+ 1, 1, 1, 1, 1, 45, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 71, 1, 72, 72,
- 72, 72, 72, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 79, 1, 80, 80,
+ 80, 80, 80, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 72, 1, 1,
+ 1, 1, 1, 1, 1, 80, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 73, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 74, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 81, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 75, 1, 72, 72, 72, 72, 72,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 82, 1, 80, 80, 80, 80, 80,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 73, 1, 1,
- 1, 1, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 80, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 74,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 81,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 75, 1,
- 68, 68, 68, 68, 68, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 68,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 69, 1, 1, 1, 1, 76,
- 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 1, 1, 1, 1, 1, 1, 70,
+ 1, 1, 1, 1, 1, 1, 82, 1,
+ 84, 84, 84, 84, 84, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 84,
+ 1, 1, 85, 1, 1, 1, 1, 1,
+ 1, 1, 86, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 43, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 71, 1, 77, 77, 77,
- 77, 77, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 87, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 88, 1, 84, 84, 84,
+ 84, 84, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 84, 1, 1, 85,
+ 1, 1, 1, 1, 1, 1, 1, 86,
+ 1, 1, 1, 1, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 77, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 87, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 88, 1, 75, 75, 75, 75, 75, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 75, 1, 1, 76, 1, 1, 1,
+ 1, 1, 1, 1, 77, 1, 1, 1,
+ 1, 89, 89, 89, 89, 89, 89, 89,
+ 89, 89, 89, 1, 1, 1, 1, 1,
1, 78, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 45, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 79, 1, 77, 77, 77, 77, 77, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 77, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 79, 1, 90,
+ 90, 90, 90, 90, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 90, 1,
+ 1, 91, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 78, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 79, 1, 61,
- 61, 61, 61, 61, 1, 1, 1, 1,
+ 1, 1, 1, 92, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 61, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 62, 1, 1, 1, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 93, 1, 90, 90, 90, 90,
+ 90, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 90, 1, 1, 91, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 35, 35, 35, 35, 35,
+ 35, 35, 35, 35, 35, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 63, 1, 1, 1, 1,
+ 92, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 93,
+ 1, 67, 67, 67, 67, 67, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 64, 1, 0
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 67, 1, 1, 68, 1, 1, 1, 1,
+ 1, 1, 1, 1, 69, 1, 1, 1,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 70, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 71, 1, 94, 94,
+ 94, 94, 94, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 94, 30, 30,
+ 58, 30, 30, 30, 30, 30, 30, 30,
+ 59, 1, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 60, 30, 30, 61, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 62, 95, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 96, 30, 94, 94, 94, 94, 94,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 94, 30, 30, 58, 30, 30,
+ 30, 30, 30, 30, 30, 59, 1, 30,
+ 30, 30, 97, 97, 97, 97, 97, 97,
+ 97, 97, 97, 97, 30, 30, 30, 60,
+ 30, 30, 61, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 62, 95,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 96, 30,
+ 0
};
static const char _deserialize_text_trans_targs[] = {
- 1, 0, 2, 25, 3, 4, 19, 5,
- 23, 24, 8, 27, 36, 27, 36, 30,
- 33, 11, 12, 15, 12, 15, 13, 14,
- 31, 32, 31, 32, 26, 18, 34, 35,
- 34, 35, 20, 19, 6, 21, 22, 20,
- 21, 22, 20, 21, 22, 24, 26, 26,
- 7, 9, 10, 16, 21, 29, 26, 7,
- 9, 10, 16, 21, 29, 28, 17, 21,
- 29, 28, 29, 29, 28, 7, 10, 29,
- 28, 7, 21, 29, 33, 28, 21, 29
+ 1, 0, 2, 26, 3, 4, 20, 5,
+ 24, 25, 8, 29, 40, 29, 40, 32,
+ 37, 33, 34, 12, 13, 16, 13, 16,
+ 14, 15, 35, 36, 35, 36, 27, 19,
+ 38, 39, 38, 39, 21, 20, 6, 22,
+ 23, 21, 22, 23, 21, 22, 23, 25,
+ 27, 27, 28, 7, 9, 11, 17, 22,
+ 31, 27, 28, 7, 9, 11, 17, 22,
+ 31, 41, 42, 30, 10, 18, 22, 31,
+ 30, 31, 31, 30, 10, 7, 11, 31,
+ 30, 22, 31, 34, 30, 10, 7, 22,
+ 31, 37, 30, 10, 22, 31, 27, 22,
+ 31, 42
};
static const char _deserialize_text_trans_actions[] = {
0, 0, 0, 0, 1, 0, 2, 0,
2, 2, 3, 4, 4, 5, 5, 4,
- 4, 3, 3, 3, 0, 0, 6, 3,
- 4, 4, 5, 5, 5, 3, 4, 4,
- 5, 5, 7, 8, 9, 7, 7, 0,
- 0, 0, 10, 10, 10, 8, 12, 13,
- 14, 14, 14, 15, 11, 11, 17, 18,
- 18, 18, 0, 16, 16, 19, 20, 19,
- 19, 0, 0, 13, 10, 21, 21, 10,
- 22, 23, 22, 22, 5, 24, 24, 24
+ 4, 4, 4, 3, 3, 3, 0, 0,
+ 6, 3, 4, 4, 5, 5, 5, 3,
+ 4, 4, 5, 5, 7, 8, 9, 7,
+ 7, 0, 0, 0, 10, 10, 10, 8,
+ 12, 13, 14, 15, 15, 15, 16, 11,
+ 11, 18, 19, 20, 20, 20, 0, 17,
+ 17, 4, 4, 21, 22, 22, 21, 21,
+ 0, 0, 13, 10, 23, 23, 23, 10,
+ 24, 24, 24, 5, 25, 26, 26, 25,
+ 25, 5, 27, 28, 27, 27, 30, 29,
+ 29, 5
};
static const char _deserialize_text_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 7, 0, 0, 0, 10,
- 10, 11, 16, 19, 0, 11, 10, 22,
- 22, 10, 24, 24, 19
+ 0, 0, 0, 0, 7, 0, 0, 0,
+ 10, 10, 11, 17, 17, 21, 0, 11,
+ 10, 24, 24, 25, 25, 10, 27, 27,
+ 21, 29, 29
};
static const int deserialize_text_start = 1;
-static const int deserialize_text_first_final = 19;
+static const int deserialize_text_first_final = 20;
static const int deserialize_text_error = 0;
static const int deserialize_text_en_main = 1;
-#line 114 "hb-buffer-deserialize-text.rl"
+#line 117 "hb-buffer-deserialize-text.rl"
static hb_bool_t
@@ -424,12 +509,12 @@ _hb_buffer_deserialize_text (hb_buffer_t *buffer,
hb_glyph_info_t info = {0};
hb_glyph_position_t pos = {0};
-#line 428 "hb-buffer-deserialize-text.hh"
+#line 506 "hb-buffer-deserialize-text.hh"
{
cs = deserialize_text_start;
}
-#line 433 "hb-buffer-deserialize-text.hh"
+#line 509 "hb-buffer-deserialize-text.hh"
{
int _slen;
int _trans;
@@ -475,10 +560,10 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 18:
+ case 20:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -489,7 +574,7 @@ _resume:
#line 66 "hb-buffer-deserialize-text.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
break;
- case 21:
+ case 23:
#line 68 "hb-buffer-deserialize-text.rl"
{ if (!parse_uint (tok, p, &info.cluster )) return false; }
break;
@@ -497,15 +582,19 @@ _resume:
#line 69 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_offset )) return false; }
break;
- case 23:
+ case 26:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
break;
- case 20:
+ case 22:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
break;
- case 15:
+ case 28:
+#line 72 "hb-buffer-deserialize-text.rl"
+ { if (!parse_int (tok, p, &pos.y_advance)) return false; }
+ break;
+ case 16:
#line 38 "hb-buffer-deserialize-text.rl"
{
memset (&info, 0, sizeof (info));
@@ -532,10 +621,10 @@ _resume:
#line 56 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_unicode ())) return false; }
break;
- case 16:
+ case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -550,6 +639,18 @@ _resume:
*end_ptr = p;
}
break;
+ case 19:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+ break;
case 7:
#line 66 "hb-buffer-deserialize-text.rl"
{if (!parse_hex (tok, p, &info.codepoint )) return false; }
@@ -574,7 +675,7 @@ _resume:
*end_ptr = p;
}
break;
- case 22:
+ case 25:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -586,7 +687,7 @@ _resume:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -598,7 +699,7 @@ _resume:
*end_ptr = p;
}
break;
- case 24:
+ case 27:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -610,6 +711,18 @@ _resume:
*end_ptr = p;
}
break;
+ case 24:
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 12:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -623,7 +736,7 @@ _resume:
#line 55 "hb-buffer-deserialize-text.rl"
{ if (unlikely (!buffer->ensure_glyphs ())) return false; }
break;
- case 14:
+ case 15:
#line 38 "hb-buffer-deserialize-text.rl"
{
memset (&info, 0, sizeof (info));
@@ -635,17 +748,17 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
return false;
}
break;
- case 17:
+ case 18:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -662,6 +775,26 @@ _resume:
*end_ptr = p;
}
break;
+ case 29:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 11:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -674,7 +807,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -689,6 +822,49 @@ _resume:
*end_ptr = p;
}
break;
+ case 14:
+#line 38 "hb-buffer-deserialize-text.rl"
+ {
+ memset (&info, 0, sizeof (info));
+ memset (&pos , 0, sizeof (pos ));
+}
+#line 51 "hb-buffer-deserialize-text.rl"
+ {
+ tok = p;
+}
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+ break;
+ case 30:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 55 "hb-buffer-deserialize-text.rl"
+ { if (unlikely (!buffer->ensure_glyphs ())) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 13:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -701,7 +877,7 @@ _resume:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -718,7 +894,7 @@ _resume:
*end_ptr = p;
}
break;
-#line 722 "hb-buffer-deserialize-text.hh"
+#line 826 "hb-buffer-deserialize-text.hh"
}
_again:
@@ -730,10 +906,10 @@ _again:
if ( p == eof )
{
switch ( _deserialize_text_eof_actions[cs] ) {
- case 16:
+ case 17:
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -772,7 +948,7 @@ _again:
*end_ptr = p;
}
break;
- case 22:
+ case 25:
#line 70 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_offset )) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -784,7 +960,7 @@ _again:
*end_ptr = p;
}
break;
- case 19:
+ case 21:
#line 71 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.x_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -796,7 +972,7 @@ _again:
*end_ptr = p;
}
break;
- case 24:
+ case 27:
#line 72 "hb-buffer-deserialize-text.rl"
{ if (!parse_int (tok, p, &pos.y_advance)) return false; }
#line 43 "hb-buffer-deserialize-text.rl"
@@ -808,6 +984,38 @@ _again:
*end_ptr = p;
}
break;
+ case 24:
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
+ case 29:
+#line 58 "hb-buffer-deserialize-text.rl"
+ {
+ /* TODO Unescape delimiters. */
+ if (!hb_font_glyph_from_string (font,
+ tok, p - tok,
+ &info.codepoint))
+ return false;
+}
+#line 73 "hb-buffer-deserialize-text.rl"
+ { if (!parse_uint (tok, p, &info.mask )) return false; }
+#line 43 "hb-buffer-deserialize-text.rl"
+ {
+ buffer->add_info (info);
+ if (unlikely (!buffer->successful))
+ return false;
+ buffer->pos[buffer->len - 1] = pos;
+ *end_ptr = p;
+}
+ break;
case 11:
#line 38 "hb-buffer-deserialize-text.rl"
{
@@ -820,7 +1028,7 @@ _again:
}
#line 58 "hb-buffer-deserialize-text.rl"
{
- /* TODO Unescape delimeters. */
+ /* TODO Unescape delimiters. */
if (!hb_font_glyph_from_string (font,
tok, p - tok,
&info.codepoint))
@@ -835,14 +1043,14 @@ _again:
*end_ptr = p;
}
break;
-#line 839 "hb-buffer-deserialize-text.hh"
+#line 953 "hb-buffer-deserialize-text.hh"
}
}
_out: {}
}
-#line 138 "hb-buffer-deserialize-text.rl"
+#line 141 "hb-buffer-deserialize-text.rl"
*end_ptr = p;
diff --git a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
index 6539b89640..d1e1775430 100644
--- a/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer-serialize.cc
@@ -31,7 +31,7 @@
#include "hb-buffer.hh"
-static const char *serialize_formats[] = {
+static const char *_hb_buffer_serialize_formats[] = {
"text",
"json",
nullptr
@@ -50,13 +50,13 @@ static const char *serialize_formats[] = {
const char **
hb_buffer_serialize_list_formats ()
{
- return serialize_formats;
+ return _hb_buffer_serialize_formats;
}
/**
* hb_buffer_serialize_format_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
*
* Parses a string into an #hb_buffer_serialize_format_t. Does not check if
* @str is a valid buffer serialization format, use
@@ -78,11 +78,11 @@ hb_buffer_serialize_format_from_string (const char *str, int len)
* hb_buffer_serialize_format_to_string:
* @format: an #hb_buffer_serialize_format_t to convert.
*
- * Converts @format to the string corresponding it, or %NULL if it is not a valid
+ * Converts @format to the string corresponding it, or `NULL` if it is not a valid
* #hb_buffer_serialize_format_t.
*
* Return value: (transfer none):
- * A %NULL terminated string corresponding to @format. Should not be freed.
+ * A `NULL` terminated string corresponding to @format. Should not be freed.
*
* Since: 0.9.7
**/
@@ -91,8 +91,8 @@ hb_buffer_serialize_format_to_string (hb_buffer_serialize_format_t format)
{
switch ((unsigned) format)
{
- case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return serialize_formats[0];
- case HB_BUFFER_SERIALIZE_FORMAT_JSON: return serialize_formats[1];
+ case HB_BUFFER_SERIALIZE_FORMAT_TEXT: return _hb_buffer_serialize_formats[0];
+ case HB_BUFFER_SERIALIZE_FORMAT_JSON: return _hb_buffer_serialize_formats[1];
default:
case HB_BUFFER_SERIALIZE_FORMAT_INVALID: return nullptr;
}
@@ -400,9 +400,9 @@ _hb_buffer_serialize_unicode_text (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If `NULL`, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -514,7 +514,7 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -637,9 +637,9 @@ _hb_buffer_serialize_invalid (hb_buffer_t *buffer,
* @buf: (out) (array length=buf_size) (element-type uint8_t): output string to
* write serialized buffer into.
* @buf_size: the size of @buf.
- * @buf_consumed: (out) (optional): if not %NULL, will be set to the number of byes written into @buf.
+ * @buf_consumed: (out) (optional): if not `NULL`, will be set to the number of bytes written into @buf.
* @font: (nullable): the #hb_font_t used to shape this buffer, needed to
- * read glyph names and extents. If %NULL, and empty font will be used.
+ * read glyph names and extents. If `NULL`, an empty font will be used.
* @format: the #hb_buffer_serialize_format_t to use for formatting the output.
* @flags: the #hb_buffer_serialize_flags_t that control what glyph properties
* to serialize.
@@ -727,7 +727,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* hb_buffer_deserialize_glyphs:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @font: (nullable): font for getting glyph IDs
@@ -736,7 +736,7 @@ parse_hex (const char *pp, const char *end, uint32_t *pv)
* Deserializes glyphs @buffer from textual representation in the format
* produced by hb_buffer_serialize_glyphs().
*
- * Return value: %true if @buf is not fully consumed, %false otherwise.
+ * Return value: `true` if @buf is not fully consumed, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -800,7 +800,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* hb_buffer_deserialize_unicode:
* @buffer: an #hb_buffer_t buffer.
* @buf: (array length=buf_len): string to deserialize
- * @buf_len: the size of @buf, or -1 if it is %NULL-terminated
+ * @buf_len: the size of @buf, or -1 if it is `NULL`-terminated
* @end_ptr: (out) (optional): output pointer to the character after last
* consumed one.
* @format: the #hb_buffer_serialize_format_t of the input @buf
@@ -808,7 +808,7 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
* Deserializes Unicode @buffer from textual representation in the format
* produced by hb_buffer_serialize_unicode().
*
- * Return value: %true if @buf is not fully consumed, %false otherwise.
+ * Return value: `true` if @buf is not fully consumed, `false` otherwise.
*
* Since: 2.7.3
**/
diff --git a/thirdparty/harfbuzz/src/hb-buffer-verify.cc b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
new file mode 100644
index 0000000000..5453e1ca94
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-buffer-verify.cc
@@ -0,0 +1,440 @@
+/*
+ * Copyright © 2022 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_BUFFER_VERIFY
+
+#include "hb-buffer.hh"
+
+
+#define BUFFER_VERIFY_ERROR "buffer verify error: "
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...) HB_PRINTF_FUNC(3, 4);
+
+static inline void
+buffer_verify_error (hb_buffer_t *buffer,
+ hb_font_t *font,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ va_start (ap, fmt);
+ if (buffer->messaging ())
+ {
+ buffer->message_impl (font, fmt, ap);
+ }
+ else
+ {
+ fprintf (stderr, "harfbuzz ");
+ vfprintf (stderr, fmt, ap);
+ fprintf (stderr, "\n");
+ }
+ va_end (ap);
+}
+
+static bool
+buffer_verify_monotone (hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ /* Check that clusters are monotone. */
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES ||
+ buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ bool is_forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ for (unsigned int i = 1; i < num_glyphs; i++)
+ if (info[i-1].cluster != info[i].cluster &&
+ (info[i-1].cluster < info[i].cluster) != is_forward)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "clusters are not monotone.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool
+buffer_verify_unsafe_to_break (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that breaking up shaping at safe-to-break is indeed safe. */
+
+ hb_buffer_t *fragment = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (fragment, (hb_buffer_flags_t (hb_buffer_get_flags (fragment) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
+
+ unsigned int num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned int num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ /* Chop text and shape fragments. */
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+ unsigned int start = 0;
+ unsigned int text_start = forward ? 0 : num_chars;
+ unsigned int text_end = text_start;
+ for (unsigned int end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end-(forward?0:1)].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK))
+ continue;
+
+ /* Shape segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ {
+ if (forward)
+ text_end = num_chars;
+ else
+ text_start = 0;
+ }
+ else
+ {
+ if (forward)
+ {
+ unsigned int cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ else
+ {
+ unsigned int cluster = info[end - 1].cluster;
+ while (text_start && text[text_start - 1].cluster >= cluster)
+ text_start--;
+ }
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+ hb_buffer_clear_contents (fragment);
+
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+
+ hb_buffer_append (fragment, text_buffer, text_start, text_end);
+ if (!hb_shape_full (font, fragment, features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return false;
+ }
+ else if (!fragment->successful || fragment->shaping_failed)
+ {
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+ return true;
+ }
+ hb_buffer_append (reconstruction, fragment, 0, -1);
+
+ start = end;
+ if (forward)
+ text_start = text_end;
+ else
+ text_end = text_start;
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-break test failed.");
+ ret = false;
+
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
+
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragment);
+
+ return ret;
+}
+
+static bool
+buffer_verify_unsafe_to_concat (hb_buffer_t *buffer,
+ hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ if (buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
+ {
+ /* Cannot perform this check without monotone clusters. */
+ return true;
+ }
+
+ /* Check that shuffling up text before shaping at safe-to-concat points
+ * is indeed safe. */
+
+ /* This is what we do:
+ *
+ * 1. We shape text once. Then segment the text at all the safe-to-concat
+ * points;
+ *
+ * 2. Then we create two buffers, one containing all the even segments and
+ * one all the odd segments.
+ *
+ * 3. Because all these segments were safe-to-concat at both ends, we
+ * expect that concatenating them and shaping should NOT change the
+ * shaping results of each segment. As such, we expect that after
+ * shaping the two buffers, we still get cluster boundaries at the
+ * segment boundaries, and that those all are safe-to-concat points.
+ * Moreover, that there are NOT any safe-to-concat points within the
+ * segments.
+ *
+ * 4. Finally, we reconstruct the shaping results of the original text by
+ * simply interleaving the shaping results of the segments from the two
+ * buffers, and assert that the total shaping results is the same as
+ * the one from original buffer in step 1.
+ */
+
+ hb_buffer_t *fragments[2] {hb_buffer_create_similar (buffer),
+ hb_buffer_create_similar (buffer)};
+ hb_buffer_set_flags (fragments[0], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[0]) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_buffer_set_flags (fragments[1], (hb_buffer_flags_t (hb_buffer_get_flags (fragments[1]) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_buffer_t *reconstruction = hb_buffer_create_similar (buffer);
+ hb_buffer_set_flags (reconstruction, (hb_buffer_flags_t (hb_buffer_get_flags (reconstruction) & ~HB_BUFFER_FLAG_VERIFY)));
+ hb_segment_properties_t props;
+ hb_buffer_get_segment_properties (buffer, &props);
+ hb_buffer_set_segment_properties (fragments[0], &props);
+ hb_buffer_set_segment_properties (fragments[1], &props);
+ hb_buffer_set_segment_properties (reconstruction, &props);
+
+ unsigned num_glyphs;
+ hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &num_glyphs);
+
+ unsigned num_chars;
+ hb_glyph_info_t *text = hb_buffer_get_glyph_infos (text_buffer, &num_chars);
+
+ bool forward = HB_DIRECTION_IS_FORWARD (hb_buffer_get_direction (buffer));
+
+ if (!forward)
+ hb_buffer_reverse (buffer);
+
+ /*
+ * Split text into segments and collect into to fragment streams.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned start = 0;
+ unsigned text_start = 0;
+ unsigned text_end = 0;
+ for (unsigned end = 1; end < num_glyphs + 1; end++)
+ {
+ if (end < num_glyphs &&
+ (info[end].cluster == info[end-1].cluster ||
+ info[end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ continue;
+
+ /* Accumulate segment corresponding to glyphs start..end. */
+ if (end == num_glyphs)
+ text_end = num_chars;
+ else
+ {
+ unsigned cluster = info[end].cluster;
+ while (text_end < num_chars && text[text_end].cluster < cluster)
+ text_end++;
+ }
+ assert (text_start < text_end);
+
+ if (0)
+ printf("start %d end %d text start %d end %d\n", start, end, text_start, text_end);
+
+#if 0
+ hb_buffer_flags_t flags = hb_buffer_get_flags (fragment);
+ if (0 < text_start)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_BOT);
+ if (text_end < num_chars)
+ flags = (hb_buffer_flags_t) (flags & ~HB_BUFFER_FLAG_EOT);
+ hb_buffer_set_flags (fragment, flags);
+#endif
+
+ hb_buffer_append (fragments[fragment_idx], text_buffer, text_start, text_end);
+
+ start = end;
+ text_start = text_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ bool ret = true;
+ hb_buffer_diff_flags_t diff;
+
+ /*
+ * Shape the two fragment streams.
+ */
+ if (!hb_shape_full (font, fragments[0], features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ ret = false;
+ goto out;
+ }
+ else if (!fragments[0]->successful || fragments[0]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
+ if (!hb_shape_full (font, fragments[1], features, num_features, shapers))
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "shaping failed while shaping fragment.");
+ ret = false;
+ goto out;
+ }
+ else if (!fragments[1]->successful || fragments[1]->shaping_failed)
+ {
+ ret = true;
+ goto out;
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (fragments[0]);
+ hb_buffer_reverse (fragments[1]);
+ }
+
+ /*
+ * Reconstruct results.
+ */
+ {
+ unsigned fragment_idx = 0;
+ unsigned fragment_start[2] {0, 0};
+ unsigned fragment_num_glyphs[2];
+ hb_glyph_info_t *fragment_info[2];
+ for (unsigned i = 0; i < 2; i++)
+ fragment_info[i] = hb_buffer_get_glyph_infos (fragments[i], &fragment_num_glyphs[i]);
+ while (fragment_start[0] < fragment_num_glyphs[0] ||
+ fragment_start[1] < fragment_num_glyphs[1])
+ {
+ unsigned fragment_end = fragment_start[fragment_idx] + 1;
+ while (fragment_end < fragment_num_glyphs[fragment_idx] &&
+ (fragment_info[fragment_idx][fragment_end].cluster == fragment_info[fragment_idx][fragment_end - 1].cluster ||
+ fragment_info[fragment_idx][fragment_end].mask & HB_GLYPH_FLAG_UNSAFE_TO_CONCAT))
+ fragment_end++;
+
+ hb_buffer_append (reconstruction, fragments[fragment_idx], fragment_start[fragment_idx], fragment_end);
+
+ fragment_start[fragment_idx] = fragment_end;
+ fragment_idx = 1 - fragment_idx;
+ }
+ }
+
+ if (!forward)
+ {
+ hb_buffer_reverse (buffer);
+ hb_buffer_reverse (reconstruction);
+ }
+
+ /*
+ * Diff results.
+ */
+ diff = hb_buffer_diff (reconstruction, buffer, (hb_codepoint_t) -1, 0);
+ if (diff)
+ {
+ buffer_verify_error (buffer, font, BUFFER_VERIFY_ERROR "unsafe-to-concat test failed.");
+ ret = false;
+
+ /* Return the reconstructed result instead so it can be inspected. */
+ hb_buffer_set_length (buffer, 0);
+ hb_buffer_append (buffer, reconstruction, 0, -1);
+ }
+
+
+out:
+ hb_buffer_destroy (reconstruction);
+ hb_buffer_destroy (fragments[0]);
+ hb_buffer_destroy (fragments[1]);
+
+ return ret;
+}
+
+bool
+hb_buffer_t::verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+{
+ bool ret = true;
+ if (!buffer_verify_monotone (this, font))
+ ret = false;
+ if (!buffer_verify_unsafe_to_break (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) != 0 &&
+ !buffer_verify_unsafe_to_concat (this, text_buffer, font, features, num_features, shapers))
+ ret = false;
+ if (!ret)
+ {
+#ifndef HB_NO_BUFFER_SERIALIZE
+ unsigned len = text_buffer->len;
+ hb_vector_t<char> bytes;
+ if (likely (bytes.resize (len * 10 + 16)))
+ {
+ hb_buffer_serialize_unicode (text_buffer,
+ 0, len,
+ bytes.arrayZ, bytes.length,
+ &len,
+ HB_BUFFER_SERIALIZE_FORMAT_TEXT,
+ HB_BUFFER_SERIALIZE_FLAG_NO_CLUSTERS);
+ buffer_verify_error (this, font, BUFFER_VERIFY_ERROR "text was: %s.", bytes.arrayZ);
+ }
+#endif
+ }
+ return ret;
+}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-buffer.cc b/thirdparty/harfbuzz/src/hb-buffer.cc
index e50afcb203..57a5ae03ed 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.cc
+++ b/thirdparty/harfbuzz/src/hb-buffer.cc
@@ -51,7 +51,7 @@
* Checks the equality of two #hb_segment_properties_t's.
*
* Return value:
- * %true if all properties of @a equal those of @b, %false otherwise.
+ * `true` if all properties of @a equal those of @b, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -81,8 +81,8 @@ hb_segment_properties_equal (const hb_segment_properties_t *a,
unsigned int
hb_segment_properties_hash (const hb_segment_properties_t *p)
{
- return (unsigned int) p->direction ^
- (unsigned int) p->script ^
+ return ((unsigned int) p->direction * 31 +
+ (unsigned int) p->script) * 31 +
(intptr_t) (p->language);
}
@@ -289,13 +289,13 @@ hb_buffer_t::clear ()
props = default_props;
successful = true;
+ shaping_failed = false;
have_output = false;
have_positions = false;
idx = 0;
len = 0;
out_len = 0;
-
out_info = info;
memset (context, 0, sizeof context);
@@ -311,6 +311,7 @@ hb_buffer_t::enter ()
{
deallocate_var_all ();
serial = 0;
+ shaping_failed = false;
scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
if (likely (!hb_unsigned_mul_overflows (len, HB_BUFFER_MAX_LEN_FACTOR)))
{
@@ -330,6 +331,7 @@ hb_buffer_t::leave ()
max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
deallocate_var_all ();
serial = 0;
+ // Intentionally not reseting shaping_failed, such that it can be inspected.
}
@@ -385,9 +387,11 @@ hb_buffer_t::clear_positions ()
hb_memset (pos, 0, sizeof (pos[0]) * len);
}
-void
+bool
hb_buffer_t::sync ()
{
+ bool ret = false;
+
assert (have_output);
assert (idx <= len);
@@ -401,11 +405,39 @@ hb_buffer_t::sync ()
info = out_info;
}
len = out_len;
+ ret = true;
reset:
have_output = false;
out_len = 0;
+ out_info = info;
idx = 0;
+
+ return ret;
+}
+
+int
+hb_buffer_t::sync_so_far ()
+{
+ bool had_output = have_output;
+ unsigned out_i = out_len;
+ unsigned i = idx;
+ unsigned old_idx = idx;
+
+ if (sync ())
+ idx = out_i;
+ else
+ idx = i;
+
+ if (had_output)
+ {
+ have_output = true;
+ out_len = idx;
+ }
+
+ assert (idx <= len);
+
+ return idx - old_idx;
}
bool
@@ -542,7 +574,8 @@ hb_buffer_t::delete_glyph ()
/* The logic here is duplicated in hb_ot_hide_default_ignorables(). */
unsigned int cluster = info[idx].cluster;
- if (idx + 1 < len && cluster == info[idx + 1].cluster)
+ if ((idx + 1 < len && cluster == info[idx + 1].cluster) ||
+ (out_len && cluster == out_info[out_len - 1].cluster))
{
/* Cluster survives; do nothing. */
goto done;
@@ -623,6 +656,7 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
HB_SEGMENT_PROPERTIES_DEFAULT,
false, /* successful */
+ true, /* shaping_failed */
false, /* have_output */
true /* have_positions */
@@ -631,16 +665,16 @@ DEFINE_NULL_INSTANCE (hb_buffer_t) =
/**
- * hb_buffer_create: (Xconstructor)
+ * hb_buffer_create:
*
* Creates a new #hb_buffer_t with all properties to defaults.
*
* Return value: (transfer full):
* A newly allocated #hb_buffer_t with a reference count of 1. The initial
* reference count should be released with hb_buffer_destroy() when you are done
- * using the #hb_buffer_t. This function never returns %NULL. If memory cannot
+ * using the #hb_buffer_t. This function never returns `NULL`. If memory cannot
* be allocated, a special #hb_buffer_t object will be returned on which
- * hb_buffer_allocation_successful() returns %false.
+ * hb_buffer_allocation_successful() returns `false`.
*
* Since: 0.9.2
**/
@@ -770,7 +804,7 @@ hb_buffer_destroy (hb_buffer_t *buffer)
*
* Attaches a user-data key/data pair to the specified buffer.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -797,7 +831,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
* Since: 0.9.2
**/
void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (buffer, key);
@@ -834,7 +868,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
* Since: 0.9.5
**/
hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer)
+hb_buffer_get_content_type (const hb_buffer_t *buffer)
{
return buffer->content_type;
}
@@ -876,7 +910,7 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer)
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer)
{
return buffer->unicode;
}
@@ -919,7 +953,7 @@ hb_buffer_set_direction (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer)
+hb_buffer_get_direction (const hb_buffer_t *buffer)
{
return buffer->props.direction;
}
@@ -963,7 +997,7 @@ hb_buffer_set_script (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer)
+hb_buffer_get_script (const hb_buffer_t *buffer)
{
return buffer->props.script;
}
@@ -1007,7 +1041,7 @@ hb_buffer_set_language (hb_buffer_t *buffer,
* Since: 0.9.2
**/
hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer)
+hb_buffer_get_language (const hb_buffer_t *buffer)
{
return buffer->props.language;
}
@@ -1043,7 +1077,7 @@ hb_buffer_set_segment_properties (hb_buffer_t *buffer,
* Since: 0.9.7
**/
void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props)
{
*props = buffer->props;
@@ -1081,7 +1115,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
* Since: 0.9.7
**/
hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer)
+hb_buffer_get_flags (const hb_buffer_t *buffer)
{
return buffer->flags;
}
@@ -1120,7 +1154,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
* Since: 0.9.42
**/
hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer)
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer)
{
return buffer->cluster_level;
}
@@ -1161,7 +1195,7 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
* Since: 0.9.31
**/
hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer)
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer)
{
return buffer->replacement;
}
@@ -1201,7 +1235,7 @@ hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
* Since: 2.0.0
**/
hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer)
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer)
{
return buffer->invisible;
}
@@ -1241,7 +1275,7 @@ hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
* Since: 3.1.0
**/
hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer)
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer)
{
return buffer->not_found;
}
@@ -1273,7 +1307,7 @@ hb_buffer_clear_contents (hb_buffer_t *buffer)
* Pre allocates memory for @buffer to fit at least @size number of items.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise
+ * `true` if @buffer memory allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1290,7 +1324,7 @@ hb_buffer_pre_allocate (hb_buffer_t *buffer, unsigned int size)
* Check if allocating memory for the buffer succeeded.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1335,7 +1369,7 @@ hb_buffer_add (hb_buffer_t *buffer,
* end.
*
* Return value:
- * %true if @buffer memory allocation succeeded, %false otherwise.
+ * `true` if @buffer memory allocation succeeded, `false` otherwise.
*
* Since: 0.9.2
**/
@@ -1381,7 +1415,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
* Since: 0.9.2
**/
unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer)
+hb_buffer_get_length (const hb_buffer_t *buffer)
{
return buffer->len;
}
@@ -1421,7 +1455,7 @@ hb_buffer_get_glyph_infos (hb_buffer_t *buffer,
* If buffer did not have positions before, the positions will be
* initialized to zeros, unless this function is called from
* within a buffer message callback (see hb_buffer_set_message_func()),
- * in which case %NULL is returned.
+ * in which case `NULL` is returned.
*
* Return value: (transfer none) (array length=length):
* The @buffer glyph position array.
@@ -1456,7 +1490,7 @@ hb_buffer_get_glyph_positions (hb_buffer_t *buffer,
* and cleared of position data when hb_buffer_clear_contents() is called.
*
* Return value:
- * %true if the @buffer has position array, %false otherwise.
+ * `true` if the @buffer has position array, `false` otherwise.
*
* Since: 2.7.3
**/
@@ -1640,10 +1674,10 @@ hb_buffer_add_utf (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): An array of UTF-8
* characters to append.
- * @text_length: The length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: The offset of the first character to add to the @buffer.
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* See hb_buffer_add_codepoints().
*
@@ -1666,10 +1700,10 @@ hb_buffer_add_utf8 (hb_buffer_t *buffer,
* hb_buffer_add_utf16:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-16 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1692,10 +1726,10 @@ hb_buffer_add_utf16 (hb_buffer_t *buffer,
* hb_buffer_add_utf32:
* @buffer: An #hb_buffer_t
* @text: (array length=text_length): An array of UTF-32 characters to append
- * @text_length: The length of the @text, or -1 if it is %NULL terminated
+ * @text_length: The length of the @text, or -1 if it is `NULL` terminated
* @item_offset: The offset of the first character to add to the @buffer
* @item_length: The number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* See hb_buffer_add_codepoints().
*
@@ -1719,10 +1753,10 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
* @buffer: An #hb_buffer_t
* @text: (array length=text_length) (element-type uint8_t): an array of UTF-8
* characters to append
- * @text_length: the length of the @text, or -1 if it is %NULL terminated
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated
* @item_offset: the offset of the first character to add to the @buffer
* @item_length: the number of characters to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated)
+ * end of @text (assuming it is `NULL` terminated)
*
* Similar to hb_buffer_add_codepoints(), but allows only access to first 256
* Unicode code points that can fit in 8-bit strings.
@@ -1745,10 +1779,10 @@ hb_buffer_add_latin1 (hb_buffer_t *buffer,
* hb_buffer_add_codepoints:
* @buffer: a #hb_buffer_t to append characters to.
* @text: (array length=text_length): an array of Unicode code points to append.
- * @text_length: the length of the @text, or -1 if it is %NULL terminated.
+ * @text_length: the length of the @text, or -1 if it is `NULL` terminated.
* @item_offset: the offset of the first code point to add to the @buffer.
* @item_length: the number of code points to add to the @buffer, or -1 for the
- * end of @text (assuming it is %NULL terminated).
+ * end of @text (assuming it is `NULL` terminated).
*
* Appends characters from @text array to @buffer. The @item_offset is the
* position of the first character from @text that will be appended, and
@@ -1789,7 +1823,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
**/
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end)
{
@@ -2085,8 +2119,16 @@ hb_buffer_set_message_func (hb_buffer_t *buffer,
bool
hb_buffer_t::message_impl (hb_font_t *font, const char *fmt, va_list ap)
{
+ assert (!have_output || (out_info == info && out_len == idx));
+
+ message_depth++;
+
char buf[100];
vsnprintf (buf, sizeof (buf), fmt, ap);
- return (bool) this->message_func (this, font, buf, this->message_data);
+ bool ret = (bool) this->message_func (this, font, buf, this->message_data);
+
+ message_depth--;
+
+ return ret;
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-buffer.h b/thirdparty/harfbuzz/src/hb-buffer.h
index 9fbd7b1ec3..c6af759fb9 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.h
+++ b/thirdparty/harfbuzz/src/hb-buffer.h
@@ -117,7 +117,7 @@ typedef struct hb_glyph_info_t {
* from there, and repeat.
* At the start of next line a similar algorithm can
* be implemented. That is: 1. Iterate forward from
- * the line-break position untill the first cluster
+ * the line-break position until the first cluster
* start position that is NOT unsafe-to-concat, 2.
* shape the segment from beginning of the line to
* that position, 3. check whether the resulting
@@ -137,7 +137,20 @@ typedef struct hb_glyph_info_t {
* clusters.
* The #HB_GLYPH_FLAG_UNSAFE_TO_BREAK flag will
* always imply this flag.
- * Since: 3.3.0
+ * To use this flag, you must enable the buffer flag
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT during
+ * shaping, otherwise the buffer flag will not be
+ * reliably produced.
+ * Since: 4.0.0
+ * @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL: In scripts that use elongation (Arabic,
+ Mongolian, Syriac, etc.), this flag signifies
+ that it is safe to insert a U+0640 TATWEEL
+ character *before* this cluster for elongation.
+ This flag does not determine the
+ script-specific elongation places, but only
+ when it is safe to do the elongation without
+ interrupting text shaping.
+ Since: 5.1.0
* @HB_GLYPH_FLAG_DEFINED: All the currently defined flags.
*
* Flags for #hb_glyph_info_t.
@@ -145,10 +158,11 @@ typedef struct hb_glyph_info_t {
* Since: 1.5.0
*/
typedef enum { /*< flags >*/
- HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
- HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_UNSAFE_TO_BREAK = 0x00000001,
+ HB_GLYPH_FLAG_UNSAFE_TO_CONCAT = 0x00000002,
+ HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL = 0x00000004,
- HB_GLYPH_FLAG_DEFINED = 0x00000003 /* OR of all defined flags */
+ HB_GLYPH_FLAG_DEFINED = 0x00000007 /* OR of all defined flags */
} hb_glyph_flags_t;
HB_EXTERN hb_glyph_flags_t
@@ -262,7 +276,7 @@ hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_bool_t replace);
HB_EXTERN void *
-hb_buffer_get_user_data (hb_buffer_t *buffer,
+hb_buffer_get_user_data (const hb_buffer_t *buffer,
hb_user_data_key_t *key);
@@ -285,7 +299,7 @@ hb_buffer_set_content_type (hb_buffer_t *buffer,
hb_buffer_content_type_t content_type);
HB_EXTERN hb_buffer_content_type_t
-hb_buffer_get_content_type (hb_buffer_t *buffer);
+hb_buffer_get_content_type (const hb_buffer_t *buffer);
HB_EXTERN void
@@ -293,21 +307,21 @@ hb_buffer_set_unicode_funcs (hb_buffer_t *buffer,
hb_unicode_funcs_t *unicode_funcs);
HB_EXTERN hb_unicode_funcs_t *
-hb_buffer_get_unicode_funcs (hb_buffer_t *buffer);
+hb_buffer_get_unicode_funcs (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_direction (hb_buffer_t *buffer,
hb_direction_t direction);
HB_EXTERN hb_direction_t
-hb_buffer_get_direction (hb_buffer_t *buffer);
+hb_buffer_get_direction (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_script (hb_buffer_t *buffer,
hb_script_t script);
HB_EXTERN hb_script_t
-hb_buffer_get_script (hb_buffer_t *buffer);
+hb_buffer_get_script (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_language (hb_buffer_t *buffer,
@@ -315,14 +329,14 @@ hb_buffer_set_language (hb_buffer_t *buffer,
HB_EXTERN hb_language_t
-hb_buffer_get_language (hb_buffer_t *buffer);
+hb_buffer_get_language (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_segment_properties (hb_buffer_t *buffer,
const hb_segment_properties_t *props);
HB_EXTERN void
-hb_buffer_get_segment_properties (hb_buffer_t *buffer,
+hb_buffer_get_segment_properties (const hb_buffer_t *buffer,
hb_segment_properties_t *props);
HB_EXTERN void
@@ -356,7 +370,24 @@ hb_buffer_guess_segment_properties (hb_buffer_t *buffer);
* @HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE:
* flag indicating that a dotted circle should
* not be inserted in the rendering of incorrect
- * character sequences (such at <0905 093E>). Since: 2.4
+ * character sequences (such at <0905 093E>). Since: 2.4.0
+ * @HB_BUFFER_FLAG_VERIFY:
+ * flag indicating that the hb_shape() call and its variants
+ * should perform various verification processes on the results
+ * of the shaping operation on the buffer. If the verification
+ * fails, then either a buffer message is sent, if a message
+ * handler is installed on the buffer, or a message is written
+ * to standard error. In either case, the shaping result might
+ * be modified to show the failed output. Since: 3.4.0
+ * @HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT:
+ * flag indicating that the @HB_GLYPH_FLAG_UNSAFE_TO_CONCAT
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced since it incurs a cost. Since: 4.0.0
+ * @HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL:
+ * flag indicating that the @HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL
+ * glyph-flag should be produced by the shaper. By default
+ * it will not be produced. Since: 5.1.0
+ * @HB_BUFFER_FLAG_DEFINED: All currently defined flags: Since: 4.4.0
*
* Flags for #hb_buffer_t.
*
@@ -368,7 +399,12 @@ typedef enum { /*< flags >*/
HB_BUFFER_FLAG_EOT = 0x00000002u, /* End-of-text */
HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES = 0x00000004u,
HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES = 0x00000008u,
- HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u
+ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE = 0x00000010u,
+ HB_BUFFER_FLAG_VERIFY = 0x00000020u,
+ HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT = 0x00000040u,
+ HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL = 0x00000080u,
+
+ HB_BUFFER_FLAG_DEFINED = 0x000000FFu
} hb_buffer_flags_t;
HB_EXTERN void
@@ -376,7 +412,7 @@ hb_buffer_set_flags (hb_buffer_t *buffer,
hb_buffer_flags_t flags);
HB_EXTERN hb_buffer_flags_t
-hb_buffer_get_flags (hb_buffer_t *buffer);
+hb_buffer_get_flags (const hb_buffer_t *buffer);
/**
* hb_buffer_cluster_level_t:
@@ -418,7 +454,7 @@ hb_buffer_set_cluster_level (hb_buffer_t *buffer,
hb_buffer_cluster_level_t cluster_level);
HB_EXTERN hb_buffer_cluster_level_t
-hb_buffer_get_cluster_level (hb_buffer_t *buffer);
+hb_buffer_get_cluster_level (const hb_buffer_t *buffer);
/**
* HB_BUFFER_REPLACEMENT_CODEPOINT_DEFAULT:
@@ -435,21 +471,21 @@ hb_buffer_set_replacement_codepoint (hb_buffer_t *buffer,
hb_codepoint_t replacement);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_replacement_codepoint (hb_buffer_t *buffer);
+hb_buffer_get_replacement_codepoint (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_invisible_glyph (hb_buffer_t *buffer,
hb_codepoint_t invisible);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_invisible_glyph (hb_buffer_t *buffer);
+hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer);
HB_EXTERN void
hb_buffer_set_not_found_glyph (hb_buffer_t *buffer,
hb_codepoint_t not_found);
HB_EXTERN hb_codepoint_t
-hb_buffer_get_not_found_glyph (hb_buffer_t *buffer);
+hb_buffer_get_not_found_glyph (const hb_buffer_t *buffer);
/*
@@ -522,7 +558,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
HB_EXTERN void
hb_buffer_append (hb_buffer_t *buffer,
- hb_buffer_t *source,
+ const hb_buffer_t *source,
unsigned int start,
unsigned int end);
@@ -531,7 +567,7 @@ hb_buffer_set_length (hb_buffer_t *buffer,
unsigned int length);
HB_EXTERN unsigned int
-hb_buffer_get_length (hb_buffer_t *buffer);
+hb_buffer_get_length (const hb_buffer_t *buffer);
/* Getting glyphs out of the buffer */
@@ -565,6 +601,7 @@ hb_buffer_normalize_glyphs (hb_buffer_t *buffer);
* @HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS: serialize glyph flags. Since: 1.5.0
* @HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES: do not serialize glyph advances,
* glyph offsets will reflect absolute glyph positions. Since: 1.8.0
+ * @HB_BUFFER_SERIALIZE_FLAG_DEFINED: All currently defined flags. Since: 4.4.0
*
* Flags that control what glyph information are serialized in hb_buffer_serialize_glyphs().
*
@@ -577,7 +614,9 @@ typedef enum { /*< flags >*/
HB_BUFFER_SERIALIZE_FLAG_NO_GLYPH_NAMES = 0x00000004u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS = 0x00000008u,
HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS = 0x00000010u,
- HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u
+ HB_BUFFER_SERIALIZE_FLAG_NO_ADVANCES = 0x00000020u,
+
+ HB_BUFFER_SERIALIZE_FLAG_DEFINED = 0x0000003Fu
} hb_buffer_serialize_flags_t;
/**
@@ -619,24 +658,24 @@ hb_buffer_serialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN unsigned int
hb_buffer_serialize_unicode (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN unsigned int
hb_buffer_serialize (hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end,
- char *buf,
- unsigned int buf_size,
- unsigned int *buf_consumed,
- hb_font_t *font,
- hb_buffer_serialize_format_t format,
- hb_buffer_serialize_flags_t flags);
+ unsigned int start,
+ unsigned int end,
+ char *buf,
+ unsigned int buf_size,
+ unsigned int *buf_consumed,
+ hb_font_t *font,
+ hb_buffer_serialize_format_t format,
+ hb_buffer_serialize_flags_t flags);
HB_EXTERN hb_bool_t
hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
@@ -648,10 +687,10 @@ hb_buffer_deserialize_glyphs (hb_buffer_t *buffer,
HB_EXTERN hb_bool_t
hb_buffer_deserialize_unicode (hb_buffer_t *buffer,
- const char *buf,
- int buf_len,
- const char **end_ptr,
- hb_buffer_serialize_format_t format);
+ const char *buf,
+ int buf_len,
+ const char **end_ptr,
+ hb_buffer_serialize_format_t format);
@@ -731,16 +770,16 @@ hb_buffer_diff (hb_buffer_t *buffer,
* hb_buffer_message_func_t:
* @buffer: An #hb_buffer_t to work upon
* @font: The #hb_font_t the @buffer is shaped with
- * @message: %NULL-terminated message passed to the function
+ * @message: `NULL`-terminated message passed to the function
* @user_data: User data pointer passed by the caller
*
* A callback method for #hb_buffer_t. The method gets called with the
* #hb_buffer_t it was set on, the #hb_font_t the buffer is shaped with and a
* message describing what step of the shaping process will be performed.
- * Returning %false from this method will skip this shaping step and move to
+ * Returning `false` from this method will skip this shaping step and move to
* the next one.
*
- * Return value: %true to perform the shaping step, %false to skip it.
+ * Return value: `true` to perform the shaping step, `false` to skip it.
*
* Since: 1.1.3
*/
diff --git a/thirdparty/harfbuzz/src/hb-buffer.hh b/thirdparty/harfbuzz/src/hb-buffer.hh
index ac45f090a5..26c3f0fac8 100644
--- a/thirdparty/harfbuzz/src/hb-buffer.hh
+++ b/thirdparty/harfbuzz/src/hb-buffer.hh
@@ -57,6 +57,7 @@
static_assert ((sizeof (hb_glyph_info_t) == 20), "");
static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), "");
+HB_MARK_AS_FLAG_T (hb_glyph_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t);
HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t);
@@ -69,12 +70,13 @@ enum hb_buffer_scratch_flags_t {
HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u,
HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u,
HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS = 0x00000020u,
+ HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000040u,
- /* Reserved for complex shapers' internal use. */
- HB_BUFFER_SCRATCH_FLAG_COMPLEX0 = 0x01000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX1 = 0x02000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX2 = 0x04000000u,
- HB_BUFFER_SCRATCH_FLAG_COMPLEX3 = 0x08000000u,
+ /* Reserved for shapers' internal use. */
+ HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER1 = 0x02000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER2 = 0x04000000u,
+ HB_BUFFER_SCRATCH_FLAG_SHAPER3 = 0x08000000u,
};
HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
@@ -106,6 +108,7 @@ struct hb_buffer_t
hb_segment_properties_t props; /* Script, language, direction */
bool successful; /* Allocations successful */
+ bool shaping_failed; /* Shaping failure */
bool have_output; /* Whether we have an output buffer going on */
bool have_positions; /* Whether we have positions */
@@ -130,9 +133,7 @@ struct hb_buffer_t
* Managed by enter / leave
*/
-#ifndef HB_NDEBUG
uint8_t allocated_var_bits;
-#endif
uint8_t serial;
hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */
unsigned int max_len; /* Maximum allowed len. */
@@ -161,38 +162,40 @@ struct hb_buffer_t
void allocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (0 == (allocated_var_bits & bits));
allocated_var_bits |= bits;
-#endif
+ }
+ bool try_allocate_var (unsigned int start, unsigned int count)
+ {
+ unsigned int end = start + count;
+ assert (end <= 8);
+ unsigned int bits = (1u<<end) - (1u<<start);
+ if (allocated_var_bits & bits)
+ return false;
+ allocated_var_bits |= bits;
+ return true;
}
void deallocate_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
allocated_var_bits &= ~bits;
-#endif
}
void assert_var (unsigned int start, unsigned int count)
{
-#ifndef HB_NDEBUG
unsigned int end = start + count;
assert (end <= 8);
- unsigned int bits = (1u<<end) - (1u<<start);
+ HB_UNUSED unsigned int bits = (1u<<end) - (1u<<start);
assert (bits == (allocated_var_bits & bits));
-#endif
}
void deallocate_var_all ()
{
-#ifndef HB_NDEBUG
allocated_var_bits = 0;
-#endif
}
hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; }
@@ -212,6 +215,20 @@ struct hb_buffer_t
HB_INTERNAL void enter ();
HB_INTERNAL void leave ();
+#ifndef HB_NO_BUFFER_VERIFY
+ HB_INTERNAL
+#endif
+ bool verify (hb_buffer_t *text_buffer,
+ hb_font_t *font,
+ const hb_feature_t *features,
+ unsigned int num_features,
+ const char * const *shapers)
+#ifndef HB_NO_BUFFER_VERIFY
+ ;
+#else
+ { return true; }
+#endif
+
unsigned int backtrack_len () const { return have_output ? out_len : idx; }
unsigned int lookahead_len () const { return len - idx; }
uint8_t next_serial () { return ++serial ? serial : ++serial; }
@@ -271,7 +288,8 @@ struct hb_buffer_t
HB_INTERNAL void guess_segment_properties ();
- HB_INTERNAL void sync ();
+ HB_INTERNAL bool sync ();
+ HB_INTERNAL int sync_so_far ();
HB_INTERNAL void clear_output ();
HB_INTERNAL void clear_positions ();
@@ -444,8 +462,21 @@ struct hb_buffer_t
start, end,
true);
}
+ void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1)
+ {
+ if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0)
+ {
+ unsafe_to_break (start, end);
+ return;
+ }
+ _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL,
+ start, end,
+ true);
+ }
void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1)
{
+ if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
+ return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
true);
@@ -458,6 +489,8 @@ struct hb_buffer_t
}
void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1)
{
+ if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0))
+ return;
_set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT,
start, end,
false, true);
@@ -531,18 +564,14 @@ struct hb_buffer_t
#ifdef HB_NO_BUFFER_MESSAGE
return true;
#else
- if (!messaging ())
+ if (likely (!messaging ()))
return true;
- message_depth++;
-
va_list ap;
va_start (ap, fmt);
bool ret = message_impl (font, fmt, ap);
va_end (ap);
- message_depth--;
-
return ret;
#endif
}
@@ -601,9 +630,10 @@ DECLARE_NULL_INSTANCE (hb_buffer_t);
#define HB_BUFFER_XALLOCATE_VAR(b, func, var) \
b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \
sizeof (b->info[0].var))
-#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
-#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
-#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
+#define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ())
+#define HB_BUFFER_TRY_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ())
+#define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ())
+#define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ())
#endif /* HB_BUFFER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-cache.hh b/thirdparty/harfbuzz/src/hb-cache.hh
index e617b75de9..d6b229ed65 100644
--- a/thirdparty/harfbuzz/src/hb-cache.hh
+++ b/thirdparty/harfbuzz/src/hb-cache.hh
@@ -32,7 +32,7 @@
/* Implements a lockfree cache for int->int functions. */
-template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+template <unsigned int key_bits=16, unsigned int value_bits=8 + 32 - key_bits, unsigned int cache_bits=8>
struct hb_cache_t
{
static_assert ((key_bits >= cache_bits), "");
diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
index 641de0eff2..5c2cb060a4 100644
--- a/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
+++ b/thirdparty/harfbuzz/src/hb-cff-interp-common.hh
@@ -248,6 +248,9 @@ struct number_t
/* byte string */
struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
{
+ hb_ubytes_t as_ubytes (unsigned l) const
+ { return hb_ubytes_t ((const unsigned char *) this, l); }
+
// encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
template <typename T, typename V>
static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
@@ -274,33 +277,10 @@ struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
/* Defining null_size allows a Null object may be created. Should be safe because:
* A descendent struct Dict uses a Null pointer to indicate a missing table,
* checked before access.
- * byte_str_t, a wrapper struct pairing a byte pointer along with its length, always
- * checks the length before access. A Null pointer is used as the initial pointer
- * along with zero length by the default ctor.
*/
DEFINE_SIZE_MIN(0);
};
-/* Holder of a section of byte string within a CFFIndex entry */
-struct byte_str_t : hb_ubytes_t
-{
- byte_str_t ()
- : hb_ubytes_t () {}
- byte_str_t (const UnsizedByteStr& s, unsigned int l)
- : hb_ubytes_t ((const unsigned char*)&s, l) {}
- byte_str_t (const unsigned char *s, unsigned int l)
- : hb_ubytes_t (s, l) {}
- byte_str_t (const hb_ubytes_t &ub) /* conversion from hb_ubytes_t */
- : hb_ubytes_t (ub) {}
-
- /* sub-string */
- byte_str_t sub_str (unsigned int offset, unsigned int len_) const
- { return byte_str_t (hb_ubytes_t::sub_array (offset, len_)); }
-
- bool check_limit (unsigned int offset, unsigned int count) const
- { return (offset + count <= length); }
-};
-
/* A byte string associated with the current offset and an error condition */
struct byte_str_ref_t
{
@@ -308,17 +288,17 @@ struct byte_str_ref_t
void init ()
{
- str = byte_str_t ();
+ str = hb_ubytes_t ();
offset = 0;
error = false;
}
void fini () {}
- byte_str_ref_t (const byte_str_t &str_, unsigned int offset_ = 0)
+ byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
: str (str_), offset (offset_), error (false) {}
- void reset (const byte_str_t &str_, unsigned int offset_ = 0)
+ void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
{
str = str_;
offset = offset_;
@@ -334,14 +314,14 @@ struct byte_str_ref_t
return str[offset + i];
}
- /* Conversion to byte_str_t */
- operator byte_str_t () const { return str.sub_str (offset, str.length - offset); }
+ /* Conversion to hb_ubytes_t */
+ operator hb_ubytes_t () const { return str.sub_array (offset, str.length - offset); }
- byte_str_t sub_str (unsigned int offset_, unsigned int len_) const
- { return str.sub_str (offset_, len_); }
+ hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
+ { return str.sub_array (offset_, len_); }
bool avail (unsigned int count=1) const
- { return (!in_error () && str.check_limit (offset, count)); }
+ { return (!in_error () && offset + count <= str.length); }
void inc (unsigned int count=1)
{
if (likely (!in_error () && (offset <= str.length) && (offset + count <= str.length)))
@@ -358,44 +338,39 @@ struct byte_str_ref_t
void set_error () { error = true; }
bool in_error () const { return error; }
- byte_str_t str;
+ hb_ubytes_t str;
unsigned int offset; /* beginning of the sub-string within str */
protected:
bool error;
};
-typedef hb_vector_t<byte_str_t> byte_str_array_t;
+using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
/* stack */
template <typename ELEM, int LIMIT>
struct cff_stack_t
{
- void init ()
- {
- error = false;
- count = 0;
- elements.init ();
- elements.resize (kSizeLimit);
- }
- void fini () { elements.fini (); }
-
ELEM& operator [] (unsigned int i)
{
- if (unlikely (i >= count)) set_error ();
+ if (unlikely (i >= count))
+ {
+ set_error ();
+ return Crap (ELEM);
+ }
return elements[i];
}
void push (const ELEM &v)
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
elements[count++] = v;
else
set_error ();
}
ELEM &push ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
return elements[count++];
else
{
@@ -424,7 +399,7 @@ struct cff_stack_t
const ELEM& peek ()
{
- if (unlikely (count < 0))
+ if (unlikely (count == 0))
{
set_error ();
return Null (ELEM);
@@ -434,7 +409,7 @@ struct cff_stack_t
void unpop ()
{
- if (likely (count < elements.length))
+ if (likely (count < LIMIT))
count++;
else
set_error ();
@@ -442,18 +417,19 @@ struct cff_stack_t
void clear () { count = 0; }
- bool in_error () const { return (error || elements.in_error ()); }
+ bool in_error () const { return (error); }
void set_error () { error = true; }
unsigned int get_count () const { return count; }
bool is_empty () const { return !count; }
- static constexpr unsigned kSizeLimit = LIMIT;
+ hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const
+ { return hb_array_t<const ELEM> (elements).sub_array (start, length); }
- protected:
- bool error;
- unsigned int count;
- hb_vector_t<ELEM> elements;
+ private:
+ bool error = false;
+ unsigned int count = 0;
+ ELEM elements[LIMIT];
};
/* argument stack */
@@ -508,9 +484,6 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
return true;
}
- hb_array_t<const ARG> get_subarray (unsigned int start) const
- { return S::elements.sub_array (start); }
-
private:
typedef cff_stack_t<ARG, 513> S;
};
@@ -518,8 +491,8 @@ struct arg_stack_t : cff_stack_t<ARG, 513>
/* an operator prefixed by its operands in a byte string */
struct op_str_t
{
+ hb_ubytes_t str;
op_code_t op;
- byte_str_t str;
};
/* base of OP_SERIALIZER */
@@ -547,11 +520,16 @@ struct parsed_values_t
}
void fini () { values.fini (); }
+ void alloc (unsigned n)
+ {
+ values.alloc (n);
+ }
+
void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
{
VAL *val = values.push ();
val->op = op;
- val->str = str_ref.str.sub_str (opStart, str_ref.offset - opStart);
+ val->str = str_ref.str.sub_array (opStart, str_ref.offset - opStart);
opStart = str_ref.offset;
}
@@ -559,14 +537,14 @@ struct parsed_values_t
{
VAL *val = values.push (v);
val->op = op;
- val->str = str_ref.sub_str ( opStart, str_ref.offset - opStart);
+ val->str = str_ref.sub_array ( opStart, str_ref.offset - opStart);
opStart = str_ref.offset;
}
bool has_op (op_code_t op) const
{
- for (unsigned int i = 0; i < get_count (); i++)
- if (get_value (i).op == op) return true;
+ for (const auto& v : values)
+ if (v.op == op) return true;
return false;
}
@@ -581,14 +559,11 @@ struct parsed_values_t
template <typename ARG=number_t>
struct interp_env_t
{
- void init (const byte_str_t &str_)
+ interp_env_t () {}
+ interp_env_t (const hb_ubytes_t &str_)
{
str_ref.reset (str_);
- argStack.init ();
- error = false;
}
- void fini () { argStack.fini (); }
-
bool in_error () const
{ return error || str_ref.in_error () || argStack.in_error (); }
@@ -622,10 +597,10 @@ struct interp_env_t
arg_stack_t<ARG>
argStack;
protected:
- bool error;
+ bool error = false;
};
-typedef interp_env_t<> num_interp_env_t;
+using num_interp_env_t = interp_env_t<>;
template <typename ARG=number_t>
struct opset_t
@@ -668,11 +643,8 @@ struct opset_t
template <typename ENV>
struct interpreter_t
{
- ~interpreter_t() { fini (); }
-
- void fini () { env.fini (); }
-
- ENV env;
+ interpreter_t (ENV& env_) : env (env_) {}
+ ENV& env;
};
} /* namespace CFF */
diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
index ef299369b5..f93c83ab45 100644
--- a/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
+++ b/thirdparty/harfbuzz/src/hb-cff-interp-cs-common.hh
@@ -57,6 +57,7 @@ struct call_context_t
/* call stack */
const unsigned int kMaxCallLimit = 10;
+const unsigned int kMaxOps = 10000;
struct call_stack_t : cff_stack_t<call_context_t, kMaxCallLimit> {};
template <typename SUBRS>
@@ -79,10 +80,10 @@ struct biased_subrs_t
unsigned int get_count () const { return subrs ? subrs->count : 0; }
unsigned int get_bias () const { return bias; }
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
if (unlikely (!subrs || index >= subrs->count))
- return Null (byte_str_t);
+ return hb_ubytes_t ();
else
return (*subrs)[index];
}
@@ -112,10 +113,9 @@ struct point_t
template <typename ARG, typename SUBRS>
struct cs_interp_env_t : interp_env_t<ARG>
{
- void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_)
+ cs_interp_env_t (const hb_ubytes_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) :
+ interp_env_t<ARG> (str)
{
- interp_env_t<ARG>::init (str);
-
context.init (str, CSType_CharString);
seen_moveto = true;
seen_hintmask = false;
@@ -123,15 +123,11 @@ struct cs_interp_env_t : interp_env_t<ARG>
vstem_count = 0;
hintmask_size = 0;
pt.set_int (0, 0);
- callStack.init ();
globalSubrs.init (globalSubrs_);
localSubrs.init (localSubrs_);
}
- void fini ()
+ ~cs_interp_env_t ()
{
- interp_env_t<ARG>::fini ();
-
- callStack.fini ();
globalSubrs.fini ();
localSubrs.fini ();
}
@@ -880,11 +876,19 @@ struct path_procs_t
template <typename ENV, typename OPSET, typename PARAM>
struct cs_interpreter_t : interpreter_t<ENV>
{
+ cs_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
SUPER::env.set_endchar (false);
+ unsigned max_ops = kMaxOps;
for (;;) {
+ if (unlikely (!--max_ops))
+ {
+ SUPER::env.set_error ();
+ break;
+ }
OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
if (unlikely (SUPER::env.in_error ()))
return false;
diff --git a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh
index a520ca3bce..79fe9b42c5 100644
--- a/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh
+++ b/thirdparty/harfbuzz/src/hb-cff-interp-dict-common.hh
@@ -179,6 +179,8 @@ struct top_dict_opset_t : dict_opset_t
template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
struct dict_interpreter_t : interpreter_t<ENV>
{
+ dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
+
bool interpret (PARAM& param)
{
param.init ();
diff --git a/thirdparty/harfbuzz/src/hb-cff1-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff1-interp-cs.hh
index 1c8762c172..b306c2ecc9 100644
--- a/thirdparty/harfbuzz/src/hb-cff1-interp-cs.hh
+++ b/thirdparty/harfbuzz/src/hb-cff1-interp-cs.hh
@@ -38,17 +38,15 @@ typedef biased_subrs_t<CFF1Subrs> cff1_biased_subrs_t;
struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
{
template <typename ACC>
- void init (const byte_str_t &str, ACC &acc, unsigned int fd)
+ cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
processed_width = false;
has_width = false;
arg_start = 0;
in_seac = false;
}
- void fini () { SUPER::fini (); }
-
void set_width (bool has_width_)
{
if (likely (!processed_width && (SUPER::argStack.get_count () > 0)))
@@ -154,7 +152,7 @@ struct cff1_cs_opset_t : cs_opset_t<number_t, OPSET, cff1_cs_interp_env_t, PARAM
};
template <typename OPSET, typename PARAM>
-struct cff1_cs_interpreter_t : cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM> {};
+using cff1_cs_interpreter_t = cs_interpreter_t<cff1_cs_interp_env_t, OPSET, PARAM>;
} /* namespace CFF */
diff --git a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
index 766183760e..d0b9e7b086 100644
--- a/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
+++ b/thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
@@ -64,14 +64,14 @@ struct blend_arg_t : number_t
typedef interp_env_t<blend_arg_t> BlendInterpEnv;
typedef biased_subrs_t<CFF2Subrs> cff2_biased_subrs_t;
-struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
+template <typename ELEM>
+struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
{
template <typename ACC>
- void init (const byte_str_t &str, ACC &acc, unsigned int fd,
- const int *coords_=nullptr, unsigned int num_coords_=0)
+ cff2_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
+ const int *coords_=nullptr, unsigned int num_coords_=0)
+ : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{
- SUPER::init (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs);
-
coords = coords_;
num_coords = num_coords_;
varStore = acc.varStore;
@@ -100,18 +100,14 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
return OpCode_return;
}
- const blend_arg_t& eval_arg (unsigned int i)
+ const ELEM& eval_arg (unsigned int i)
{
- blend_arg_t &arg = argStack[i];
- blend_arg (arg);
- return arg;
+ return SUPER::argStack[i];
}
- const blend_arg_t& pop_arg ()
+ const ELEM& pop_arg ()
{
- blend_arg_t &arg = argStack.pop ();
- blend_arg (arg);
- return arg;
+ return SUPER::argStack.pop ();
}
void process_blend ()
@@ -122,7 +118,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
if (do_blend)
{
if (unlikely (!scalars.resize (region_count)))
- set_error ();
+ SUPER::set_error ();
else
varStore->varStore.get_region_scalars (get_ivs (), coords, num_coords,
&scalars[0], region_count);
@@ -133,10 +129,10 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void process_vsindex ()
{
- unsigned int index = argStack.pop_uint ();
+ unsigned int index = SUPER::argStack.pop_uint ();
if (unlikely (seen_vsindex () || seen_blend))
{
- set_error ();
+ SUPER::set_error ();
}
else
{
@@ -151,22 +147,18 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
bool seen_vsindex () const { return seen_vsindex_; }
- protected:
- void blend_arg (blend_arg_t &arg)
+ double blend_deltas (hb_array_t<const ELEM> deltas) const
{
- if (do_blend && arg.blending ())
+ double v = 0;
+ if (do_blend)
{
- if (likely (scalars.length == arg.deltas.length))
+ if (likely (scalars.length == deltas.length))
{
- double v = arg.to_real ();
for (unsigned int i = 0; i < scalars.length; i++)
- {
- v += (double)scalars[i] * arg.deltas[i].to_real ();
- }
- arg.set_real (v);
- arg.deltas.resize (0);
+ v += (double) scalars[i] * deltas[i].to_real ();
}
}
+ return v;
}
protected:
@@ -180,22 +172,24 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<blend_arg_t, CFF2Subrs>
bool seen_vsindex_;
bool seen_blend;
- typedef cs_interp_env_t<blend_arg_t, CFF2Subrs> SUPER;
+ typedef cs_interp_env_t<ELEM, CFF2Subrs> SUPER;
};
-template <typename OPSET, typename PARAM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t, PARAM>>
-struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH>
+template <typename OPSET, typename PARAM, typename ELEM, typename PATH=path_procs_null_t<cff2_cs_interp_env_t<ELEM>, PARAM>>
+struct cff2_cs_opset_t : cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
switch (op) {
case OpCode_callsubr:
case OpCode_callgsubr:
/* a subroutine number shouldn't be a blended value */
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
SUPER::process_op (op, env, param);
break;
@@ -204,11 +198,13 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
break;
case OpCode_vsindexcs:
+#if 0
if (unlikely (env.argStack.peek ().blending ()))
{
env.set_error ();
break;
}
+#endif
OPSET::process_vsindex (env, param);
break;
@@ -217,7 +213,26 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
}
- static void process_blend (cff2_cs_interp_env_t &env, PARAM& param)
+ template <typename T = ELEM,
+ hb_enable_if (hb_is_same (T, blend_arg_t))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_blends (n, i, blends.length, blends);
+ }
+ template <typename T = ELEM,
+ hb_enable_if (!hb_is_same (T, blend_arg_t))>
+ static void process_arg_blend (cff2_cs_interp_env_t<ELEM> &env,
+ ELEM &arg,
+ const hb_array_t<const ELEM> blends,
+ unsigned n, unsigned i)
+ {
+ arg.set_real (arg.to_real () + env.blend_deltas (blends));
+ }
+
+ static void process_blend (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
unsigned int n, k;
@@ -234,26 +249,26 @@ struct cff2_cs_opset_t : cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PA
}
for (unsigned int i = 0; i < n; i++)
{
- const hb_array_t<const blend_arg_t> blends = env.argStack.get_subarray (start + n + (i * k));
- env.argStack[start + i].set_blends (n, i, k, blends);
+ const hb_array_t<const ELEM> blends = env.argStack.sub_array (start + n + (i * k), k);
+ process_arg_blend (env, env.argStack[start + i], blends, n, i);
}
/* pop off blend values leaving default values now adorned with blend values */
env.argStack.pop (k * n);
}
- static void process_vsindex (cff2_cs_interp_env_t &env, PARAM& param)
+ static void process_vsindex (cff2_cs_interp_env_t<ELEM> &env, PARAM& param)
{
env.process_vsindex ();
env.clear_args ();
}
private:
- typedef cs_opset_t<blend_arg_t, OPSET, cff2_cs_interp_env_t, PARAM, PATH> SUPER;
+ typedef cs_opset_t<ELEM, OPSET, cff2_cs_interp_env_t<ELEM>, PARAM, PATH> SUPER;
};
-template <typename OPSET, typename PARAM>
-struct cff2_cs_interpreter_t : cs_interpreter_t<cff2_cs_interp_env_t, OPSET, PARAM> {};
+template <typename OPSET, typename PARAM, typename ELEM>
+using cff2_cs_interpreter_t = cs_interpreter_t<cff2_cs_interp_env_t<ELEM>, OPSET, PARAM>;
} /* namespace CFF */
diff --git a/thirdparty/harfbuzz/src/hb-common.cc b/thirdparty/harfbuzz/src/hb-common.cc
index 249a8a8010..e6512872e8 100644
--- a/thirdparty/harfbuzz/src/hb-common.cc
+++ b/thirdparty/harfbuzz/src/hb-common.cc
@@ -108,7 +108,7 @@ _hb_options_init ()
/**
* hb_tag_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string into an #hb_tag_t. Valid tags
* are four characters. Shorter input strings will be
@@ -160,7 +160,7 @@ hb_tag_to_string (hb_tag_t tag, char *buf)
/* hb_direction_t */
-const char direction_strings[][4] = {
+static const char direction_strings[][4] = {
"ltr",
"rtl",
"ttb",
@@ -170,7 +170,7 @@ const char direction_strings[][4] = {
/**
* hb_direction_from_string:
* @str: (array length=len) (element-type uint8_t): String to convert
- * @len: Length of @str, or -1 if it is %NULL-terminated
+ * @len: Length of @str, or -1 if it is `NULL`-terminated
*
* Converts a string to an #hb_direction_t.
*
@@ -357,7 +357,7 @@ retry:
* hb_language_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing
* a BCP 47 language tag
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts @str representing a BCP 47 language tag to the corresponding
* #hb_language_t.
@@ -396,7 +396,7 @@ hb_language_from_string (const char *str, int len)
* Converts an #hb_language_t to a string.
*
* Return value: (transfer none):
- * A %NULL-terminated string representing the @language. Must not be freed by
+ * A `NULL`-terminated string representing the @language. Must not be freed by
* the caller.
*
* Since: 0.9.2
@@ -441,6 +441,38 @@ hb_language_get_default ()
return language;
}
+/**
+ * hb_language_matches:
+ * @language: The #hb_language_t to work on
+ * @specific: Another #hb_language_t
+ *
+ * Check whether a second language tag is the same or a more
+ * specific version of the provided language tag. For example,
+ * "fa_IR.utf8" is a more specific tag for "fa" or for "fa_IR".
+ *
+ * Return value: `true` if languages match, `false` otherwise.
+ *
+ * Since: 5.0.0
+ **/
+hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific)
+{
+ if (language == specific) return true;
+ if (!language || !specific) return false;
+
+ const char *l = language->s;
+ const char *s = specific->s;
+ unsigned ll = strlen (l);
+ unsigned sl = strlen (s);
+
+ if (ll > sl)
+ return false;
+
+ return strncmp (l, s, ll) == 0 &&
+ (s[ll] == '\0' || s[ll] == '-');
+}
+
/* hb_script_t */
@@ -498,7 +530,7 @@ hb_script_from_iso15924_tag (hb_tag_t tag)
* hb_script_from_string:
* @str: (array length=len) (element-type uint8_t): a string representing an
* ISO 15924 tag.
- * @len: length of the @str, or -1 if it is %NULL-terminated.
+ * @len: length of the @str, or -1 if it is `NULL`-terminated.
*
* Converts a string @str representing an ISO 15924 script tag to a
* corresponding #hb_script_t. Shorthand for hb_tag_from_string() then
@@ -693,8 +725,8 @@ hb_version_string ()
* Tests the library version against a minimum value,
* as three integer components.
*
- * Return value: %true if the library is equal to or greater than
- * the test value, %false otherwise
+ * Return value: `true` if the library is equal to or greater than
+ * the test value, `false` otherwise
*
* Since: 0.9.30
**/
@@ -881,7 +913,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
/**
* hb_feature_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @feature: (out): the #hb_feature_t to initialize with the parsed values
*
* Parses a string into a #hb_feature_t.
@@ -923,7 +955,7 @@ parse_one_feature (const char **pp, const char *end, hb_feature_t *feature)
* </informaltable>
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 0.9.5
**/
@@ -954,7 +986,7 @@ hb_feature_from_string (const char *str, int len,
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
- * Converts a #hb_feature_t into a %NULL-terminated string in the format
+ * Converts a #hb_feature_t into a `NULL`-terminated string in the format
* understood by hb_feature_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
@@ -1022,7 +1054,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
/**
* hb_variation_from_string:
* @str: (array length=len) (element-type uint8_t): a string to parse
- * @len: length of @str, or -1 if string is %NULL terminated
+ * @len: length of @str, or -1 if string is `NULL` terminated
* @variation: (out): the #hb_variation_t to initialize with the parsed values
*
* Parses a string into a #hb_variation_t.
@@ -1035,7 +1067,7 @@ parse_one_variation (const char **pp, const char *end, hb_variation_t *variation
* number. For example `wght=500`, or `slnt=-7.5`.
*
* Return value:
- * %true if @str is successfully parsed, %false otherwise
+ * `true` if @str is successfully parsed, `false` otherwise
*
* Since: 1.4.2
*/
@@ -1065,7 +1097,7 @@ hb_variation_from_string (const char *str, int len,
static inline void free_static_C_locale ();
static struct hb_C_locale_lazy_loader_t : hb_lazy_loader_t<hb_remove_pointer<hb_locale_t>,
- hb_C_locale_lazy_loader_t>
+ hb_C_locale_lazy_loader_t>
{
static hb_locale_t create ()
{
@@ -1107,7 +1139,7 @@ get_C_locale ()
* @buf: (array length=size) (out): output string
* @size: the allocated size of @buf
*
- * Converts an #hb_variation_t into a %NULL-terminated string in the format
+ * Converts an #hb_variation_t into a `NULL`-terminated string in the format
* understood by hb_variation_from_string(). The client in responsible for
* allocating big enough size for @buf, 128 bytes is more than enough.
*
diff --git a/thirdparty/harfbuzz/src/hb-common.h b/thirdparty/harfbuzz/src/hb-common.h
index 0384117a4d..7c7ad87c7c 100644
--- a/thirdparty/harfbuzz/src/hb-common.h
+++ b/thirdparty/harfbuzz/src/hb-common.h
@@ -130,6 +130,16 @@ typedef union _hb_var_int_t {
int8_t i8[4];
} hb_var_int_t;
+typedef union _hb_var_num_t {
+ float f;
+ uint32_t u32;
+ int32_t i32;
+ uint16_t u16[2];
+ int16_t i16[2];
+ uint8_t u8[4];
+ int8_t i8[4];
+} hb_var_num_t;
+
/* hb_tag_t */
@@ -316,6 +326,9 @@ hb_language_to_string (hb_language_t language);
HB_EXTERN hb_language_t
hb_language_get_default (void);
+HB_EXTERN hb_bool_t
+hb_language_matches (hb_language_t language,
+ hb_language_t specific);
/**
* hb_script_t:
@@ -481,6 +494,7 @@ hb_language_get_default (void);
* @HB_SCRIPT_TANGSA: `Tnsa`, Since: 3.0.0
* @HB_SCRIPT_TOTO: `Toto`, Since: 3.0.0
* @HB_SCRIPT_VITHKUQI: `Vith`, Since: 3.0.0
+ * @HB_SCRIPT_MATH: `Zmth`, Since: 3.4.0
* @HB_SCRIPT_INVALID: No script set
*
* Data type for scripts. Each #hb_script_t's value is an #hb_tag_t corresponding
@@ -697,6 +711,11 @@ typedef enum
HB_SCRIPT_TOTO = HB_TAG ('T','o','t','o'), /*14.0*/
HB_SCRIPT_VITHKUQI = HB_TAG ('V','i','t','h'), /*14.0*/
+ /*
+ * Since 3.4.0
+ */
+ HB_SCRIPT_MATH = HB_TAG ('Z','m','t','h'),
+
/* No script set. */
HB_SCRIPT_INVALID = HB_TAG_NONE,
diff --git a/thirdparty/harfbuzz/src/hb-config.hh b/thirdparty/harfbuzz/src/hb-config.hh
index 7d00d9088a..db8ec0e908 100644
--- a/thirdparty/harfbuzz/src/hb-config.hh
+++ b/thirdparty/harfbuzz/src/hb-config.hh
@@ -55,6 +55,7 @@
#define HB_NO_ATEXIT
#define HB_NO_BUFFER_MESSAGE
#define HB_NO_BUFFER_SERIALIZE
+#define HB_NO_BUFFER_VERIFY
#define HB_NO_BITMAP
#define HB_NO_CFF
#define HB_NO_COLOR
@@ -63,6 +64,7 @@
#define HB_NO_FACE_COLLECT_UNICODES
#define HB_NO_GETENV
#define HB_NO_HINTING
+#define HB_NO_LANGUAGE_LONG
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
#define HB_NO_LAYOUT_FEATURE_PARAMS
#define HB_NO_LAYOUT_COLLECT_GLYPHS
@@ -84,6 +86,7 @@
#ifdef HB_MINI
#define HB_NO_AAT
#define HB_NO_LEGACY
+#define HB_NO_BORING_EXPANSION
#endif
#if defined(HAVE_CONFIG_OVERRIDE_H) || defined(HB_CONFIG_OVERRIDE_H)
@@ -95,6 +98,11 @@
/* Closure of options. */
+#ifdef HB_NO_BORING_EXPANSION
+#define HB_NO_BEYOND_64K
+#define HB_NO_VARIATIONS2
+#endif
+
#ifdef HB_DISABLE_DEPRECATED
#define HB_IF_NOT_DEPRECATED(x)
#else
@@ -143,10 +151,10 @@
#endif
#ifdef HB_NO_OT_SHAPE_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
-#define HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
+#define HB_NO_OT_SHAPER_ARABIC_FALLBACK
+#define HB_NO_OT_SHAPER_HEBREW_FALLBACK
+#define HB_NO_OT_SHAPER_THAI_FALLBACK
+#define HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
#endif
#ifdef NDEBUG
@@ -161,5 +169,9 @@
#endif
#endif
+#ifdef HB_OPTIMIZE_SIZE
+#define HB_NO_OT_LAYOUT_LOOKUP_CACHE
+#endif
+
#endif /* HB_CONFIG_HH */
diff --git a/thirdparty/harfbuzz/src/hb-coretext.cc b/thirdparty/harfbuzz/src/hb-coretext.cc
index 5f383064c4..99b33c001e 100644
--- a/thirdparty/harfbuzz/src/hb-coretext.cc
+++ b/thirdparty/harfbuzz/src/hb-coretext.cc
@@ -332,7 +332,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
return nullptr;
}
- if (font->coords)
+ if (font->num_coords)
{
CFMutableDictionaryRef variations =
CFDictionaryCreateMutable (kCFAllocatorDefault,
@@ -379,37 +379,6 @@ _hb_coretext_shaper_font_data_destroy (hb_coretext_font_data_t *data)
CFRelease ((CTFontRef) data);
}
-static const hb_coretext_font_data_t *
-hb_coretext_font_data_sync (hb_font_t *font)
-{
-retry:
- const hb_coretext_font_data_t *data = font->data.coretext;
- if (unlikely (!data)) return nullptr;
-
- if (fabs (CTFontGetSize ((CTFontRef) data) - (CGFloat) font->ptem) > (CGFloat) .5)
- {
- /* XXX-MT-bug
- * Note that evaluating condition above can be dangerous if another thread
- * got here first and destructed data. That's, as always, bad use pattern.
- * If you modify the font (change font size), other threads must not be
- * using it at the same time. However, since this check is delayed to
- * when one actually tries to shape something, this is a XXX race condition
- * (and the only one we have that I know of) right now. Ie. you modify the
- * font size in one thread, then (supposedly safely) try to use it from two
- * or more threads and BOOM! I'm not sure how to fix this. We want RCU.
- */
-
- /* Drop and recreate. */
- /* If someone dropped it in the mean time, throw it away and don't touch it.
- * Otherwise, destruct it. */
- if (likely (font->data.coretext.cmpexch (const_cast<hb_coretext_font_data_t *> (data), nullptr)))
- _hb_coretext_shaper_font_data_destroy (const_cast<hb_coretext_font_data_t *> (data));
- else
- goto retry;
- }
- return font->data.coretext;
-}
-
/**
* hb_coretext_font_create:
* @ct_font: The CTFontRef to work upon
@@ -455,8 +424,8 @@ hb_coretext_font_create (CTFontRef ct_font)
CTFontRef
hb_coretext_font_get_ct_font (hb_font_t *font)
{
- const hb_coretext_font_data_t *data = hb_coretext_font_data_sync (font);
- return data ? (CTFontRef) data : nullptr;
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
+ return ct_font ? (CTFontRef) ct_font : nullptr;
}
@@ -516,7 +485,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
{
hb_face_t *face = font->face;
CGFontRef cg_font = (CGFontRef) (const void *) face->data.coretext;
- CTFontRef ct_font = (CTFontRef) hb_coretext_font_data_sync (font);
+ CTFontRef ct_font = (CTFontRef) (const void *) font->data.coretext;
CGFloat ct_font_size = CTFontGetSize (ct_font);
CGFloat x_mult = (CGFloat) font->x_scale / ct_font_size;
@@ -897,7 +866,7 @@ resize_and_retry:
DEBUG_MSG (CORETEXT, nullptr, "Num runs: %d", num_runs);
buffer->len = 0;
- uint32_t status_and = ~0, status_or = 0;
+ uint32_t status_or = 0;
CGFloat advances_so_far = 0;
/* For right-to-left runs, CoreText returns the glyphs positioned such that
* any trailing whitespace is to the left of (0,0). Adjust coordinate system
@@ -918,7 +887,6 @@ resize_and_retry:
CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex (glyph_runs, i));
CTRunStatus run_status = CTRunGetStatus (run);
status_or |= run_status;
- status_and &= run_status;
DEBUG_MSG (CORETEXT, run, "CTRunStatus: %x", run_status);
CGFloat run_advance = CTRunGetTypographicBounds (run, range_all, nullptr, nullptr, nullptr);
if (HB_DIRECTION_IS_VERTICAL (buffer->props.direction))
@@ -1107,7 +1075,8 @@ resize_and_retry:
advance = positions[j + 1].x - positions[j].x;
else /* last glyph */
advance = run_advance - (positions[j].x - positions[0].x);
- info->mask = round (advance * x_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * x_mult);
info->var1.i32 = x_offset;
info->var2.i32 = round (positions[j].y * y_mult);
info++;
@@ -1123,7 +1092,8 @@ resize_and_retry:
advance = positions[j + 1].y - positions[j].y;
else /* last glyph */
advance = run_advance - (positions[j].y - positions[0].y);
- info->mask = round (advance * y_mult);
+ /* int cast necessary to pass through negative values. */
+ info->mask = (int) round (advance * y_mult);
info->var1.i32 = round (positions[j].x * x_mult);
info->var2.i32 = y_offset;
info++;
@@ -1140,21 +1110,6 @@ resize_and_retry:
buffer->len += num_glyphs;
}
- /* Mac OS 10.6 doesn't have kCTTypesetterOptionForcedEmbeddingLevel,
- * or if it does, it doesn't respect it. So we get runs with wrong
- * directions. As such, disable the assert... It wouldn't crash, but
- * cursoring will be off...
- *
- * https://crbug.com/419769
- */
- if (false)
- {
- /* Make sure all runs had the expected direction. */
- HB_UNUSED bool backward = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
- assert (bool (status_and & kCTRunStatusRightToLeft) == backward);
- assert (bool (status_or & kCTRunStatusRightToLeft) == backward);
- }
-
buffer->clear_positions ();
unsigned int count = buffer->len;
@@ -1167,7 +1122,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
else
for (unsigned int i = 0; i < count; i++)
@@ -1176,7 +1131,7 @@ resize_and_retry:
pos->x_offset = info->var1.i32;
pos->y_offset = info->var2.i32;
- info++, pos++;
+ info++; pos++;
}
/* Fix up clusters so that we never return out-of-order indices;
@@ -1189,7 +1144,8 @@ resize_and_retry:
* This does *not* mean we'll form the same clusters as Uniscribe
* or the native OT backend, only that the cluster indices will be
* monotonic in the output buffer. */
- if (count > 1 && (status_or & kCTRunStatusNonMonotonic))
+ if (count > 1 && (status_or & kCTRunStatusNonMonotonic) &&
+ buffer->cluster_level != HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
{
hb_glyph_info_t *info = buffer->info;
if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
@@ -1213,6 +1169,10 @@ resize_and_retry:
}
}
+ /* TODO: Sometimes the above positioning code generates negative
+ * advance values. Fix them up. Example, with NotoNastaliqUrdu
+ * font and sequence ابهد. */
+
buffer->clear_glyph_flags ();
buffer->unsafe_to_break ();
diff --git a/thirdparty/harfbuzz/src/hb-cplusplus.hh b/thirdparty/harfbuzz/src/hb-cplusplus.hh
new file mode 100644
index 0000000000..c4d9d29e23
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-cplusplus.hh
@@ -0,0 +1,221 @@
+/*
+ * Copyright © 2022 Behdad Esfahbod
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_CPLUSPLUS_HH
+#define HB_CPLUSPLUS_HH
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+HB_END_DECLS
+
+#ifdef __cplusplus
+
+#include <functional>
+#include <utility>
+
+#if 0
+#if !(__cplusplus >= 201103L)
+#error "HarfBuzz C++ helpers require C++11"
+#endif
+#endif
+
+namespace hb {
+
+
+template <typename T>
+struct vtable;
+
+template <typename T>
+struct shared_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit shared_ptr (T *p = nullptr) : p (p) {}
+ shared_ptr (const shared_ptr &o) : p (v::reference (o.p)) {}
+ shared_ptr (shared_ptr &&o) : p (o.p) { o.p = nullptr; }
+ shared_ptr& operator = (const shared_ptr &o) { if (p != o.p) { destroy (); p = o.p; reference (); } return *this; }
+ shared_ptr& operator = (shared_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~shared_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+
+ void swap (shared_ptr &o) { std::swap (p, o.p); }
+ friend void swap (shared_ptr &a, shared_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () { return p; }
+ bool operator == (const shared_ptr &o) { return p == o.p; }
+ bool operator != (const shared_ptr &o) { return p != o.p; }
+
+ static T* get_empty() { return v::get_empty (); }
+ T* reference() { return v::reference (p); }
+ void destroy() { v::destroy (p); }
+ void set_user_data (hb_user_data_key_t *key,
+ void *value,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace) { v::set_user_data (p, key, value, destroy, replace); }
+ void * get_user_data (hb_user_data_key_t *key) { return v::get_user_data (p, key); }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_shared_ptr : std::false_type {};
+template<typename T> struct is_shared_ptr<shared_ptr<T>> : std::true_type {};
+
+template <typename T>
+struct unique_ptr
+{
+ using element_type = T;
+
+ using v = vtable<T>;
+
+ explicit unique_ptr (T *p = nullptr) : p (p) {}
+ unique_ptr (const unique_ptr &o) = delete;
+ unique_ptr (unique_ptr &&o) : p (o.p) { o.p = nullptr; }
+ unique_ptr& operator = (const unique_ptr &o) = delete;
+ unique_ptr& operator = (unique_ptr &&o) { v::destroy (p); p = o.p; o.p = nullptr; return *this; }
+ ~unique_ptr () { v::destroy (p); p = nullptr; }
+
+ T* get() const { return p; }
+ T* release () { T* v = p; p = nullptr; return v; }
+
+ void swap (unique_ptr &o) { std::swap (p, o.p); }
+ friend void swap (unique_ptr &a, unique_ptr &b) { std::swap (a.p, b.p); }
+
+ operator T * () const { return p; }
+ T& operator * () const { return *get (); }
+ T* operator -> () const { return get (); }
+ operator bool () { return p; }
+
+ private:
+ T *p;
+};
+
+template<typename T> struct is_unique_ptr : std::false_type {};
+template<typename T> struct is_unique_ptr<unique_ptr<T>> : std::true_type {};
+
+template <typename T,
+ T * (*_get_empty) (void),
+ T * (*_reference) (T *),
+ void (*_destroy) (T *),
+ hb_bool_t (*_set_user_data) (T *,
+ hb_user_data_key_t *,
+ void *,
+ hb_destroy_func_t,
+ hb_bool_t),
+ void * (*_get_user_data) (const T *,
+ hb_user_data_key_t *)>
+struct vtable_t
+{
+ static constexpr auto get_empty = _get_empty;
+ static constexpr auto reference = _reference;
+ static constexpr auto destroy = _destroy;
+ static constexpr auto set_user_data = _set_user_data;
+ static constexpr auto get_user_data = _get_user_data;
+};
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ &hb_##name##_get_empty, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+HB_DEFINE_VTABLE (buffer);
+HB_DEFINE_VTABLE (blob);
+HB_DEFINE_VTABLE (face);
+HB_DEFINE_VTABLE (font);
+HB_DEFINE_VTABLE (font_funcs);
+HB_DEFINE_VTABLE (map);
+HB_DEFINE_VTABLE (set);
+HB_DEFINE_VTABLE (shape_plan);
+HB_DEFINE_VTABLE (unicode_funcs);
+
+#undef HB_DEFINE_VTABLE
+
+
+#ifdef HB_SUBSET_H
+
+#define HB_DEFINE_VTABLE(name) \
+ template<> \
+ struct vtable<hb_##name##_t> \
+ : vtable_t<hb_##name##_t, \
+ nullptr, \
+ &hb_##name##_reference, \
+ &hb_##name##_destroy, \
+ &hb_##name##_set_user_data, \
+ &hb_##name##_get_user_data> {}
+
+
+HB_DEFINE_VTABLE (subset_input);
+HB_DEFINE_VTABLE (subset_plan);
+
+#undef HB_DEFINE_VTABLE
+
+#endif
+
+
+} // namespace hb
+
+/* Workaround for GCC < 7, see:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
+ * https://stackoverflow.com/a/25594741 */
+namespace std {
+
+
+template<typename T>
+struct hash<hb::shared_ptr<T>>
+{
+ std::size_t operator()(const hb::shared_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+template<typename T>
+struct hash<hb::unique_ptr<T>>
+{
+ std::size_t operator()(const hb::unique_ptr<T>& v) const noexcept
+ {
+ std::size_t h = std::hash<decltype (v.get ())>{}(v.get ());
+ return h;
+ }
+};
+
+
+} // namespace std
+
+#endif /* __cplusplus */
+
+#endif /* HB_CPLUSPLUS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-debug.hh b/thirdparty/harfbuzz/src/hb-debug.hh
index 3ac7440e80..905a46a087 100644
--- a/thirdparty/harfbuzz/src/hb-debug.hh
+++ b/thirdparty/harfbuzz/src/hb-debug.hh
@@ -460,4 +460,9 @@ struct hb_no_trace_t {
#endif
+#ifndef HB_BUFFER_MESSAGE_MORE
+#define HB_BUFFER_MESSAGE_MORE (HB_DEBUG+1)
+#endif
+
+
#endif /* HB_DEBUG_HH */
diff --git a/thirdparty/harfbuzz/src/hb-deprecated.h b/thirdparty/harfbuzz/src/hb-deprecated.h
index a130d77f77..333dc3cd4c 100644
--- a/thirdparty/harfbuzz/src/hb-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-deprecated.h
@@ -93,7 +93,7 @@ HB_BEGIN_DECLS
* This method should retrieve the glyph ID for a specified Unicode code point
* font, with an optional variation selector.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
* Deprecated: 1.2.3
*
**/
diff --git a/thirdparty/harfbuzz/src/hb-directwrite.cc b/thirdparty/harfbuzz/src/hb-directwrite.cc
index f177ff31c0..de05b7d871 100644
--- a/thirdparty/harfbuzz/src/hb-directwrite.cc
+++ b/thirdparty/harfbuzz/src/hb-directwrite.cc
@@ -43,6 +43,14 @@
* Functions for using HarfBuzz with DirectWrite fonts.
**/
+/* Declare object creator for dynamic support of DWRITE */
+typedef HRESULT (WINAPI *t_DWriteCreateFactory)(
+ DWRITE_FACTORY_TYPE factoryType,
+ REFIID iid,
+ IUnknown **factory
+);
+
+
/*
* DirectWrite font stream helpers
*/
@@ -137,6 +145,7 @@ public:
struct hb_directwrite_face_data_t
{
+ HMODULE dwrite_dll;
IDWriteFactory *dwriteFactory;
IDWriteFontFile *fontFile;
DWriteFontFileStream *fontFileStream;
@@ -158,12 +167,33 @@ _hb_directwrite_shaper_face_data_create (hb_face_t *face)
return nullptr; \
} HB_STMT_END
+ data->dwrite_dll = LoadLibrary (TEXT ("DWRITE"));
+ if (unlikely (!data->dwrite_dll))
+ FAIL ("Cannot find DWrite.DLL");
+
+ t_DWriteCreateFactory p_DWriteCreateFactory;
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
+
+ p_DWriteCreateFactory = (t_DWriteCreateFactory)
+ GetProcAddress (data->dwrite_dll, "DWriteCreateFactory");
+
+#if defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+ if (unlikely (!p_DWriteCreateFactory))
+ FAIL ("Cannot find DWriteCreateFactory().");
+
HRESULT hr;
// TODO: factory and fontFileLoader should be cached separately
IDWriteFactory* dwriteFactory;
- hr = DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
- (IUnknown**) &dwriteFactory);
+ hr = p_DWriteCreateFactory (DWRITE_FACTORY_TYPE_SHARED, __uuidof (IDWriteFactory),
+ (IUnknown**) &dwriteFactory);
if (unlikely (hr != S_OK))
FAIL ("Failed to run DWriteCreateFactory().");
@@ -227,6 +257,8 @@ _hb_directwrite_shaper_face_data_destroy (hb_directwrite_face_data_t *data)
delete data->fontFileStream;
if (data->faceBlob)
hb_blob_destroy (data->faceBlob);
+ if (data->dwrite_dll)
+ FreeLibrary (data->dwrite_dll);
if (data)
delete data;
}
@@ -241,17 +273,12 @@ struct hb_directwrite_font_data_t {};
hb_directwrite_font_data_t *
_hb_directwrite_shaper_font_data_create (hb_font_t *font)
{
- hb_directwrite_font_data_t *data = new hb_directwrite_font_data_t;
- if (unlikely (!data))
- return nullptr;
-
- return data;
+ return (hb_directwrite_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
}
void
_hb_directwrite_shaper_font_data_destroy (hb_directwrite_font_data_t *data)
{
- delete data;
}
diff --git a/thirdparty/harfbuzz/src/hb-draw.cc b/thirdparty/harfbuzz/src/hb-draw.cc
index c0af6ce013..46797e64e6 100644
--- a/thirdparty/harfbuzz/src/hb-draw.cc
+++ b/thirdparty/harfbuzz/src/hb-draw.cc
@@ -25,237 +25,342 @@
#include "hb.hh"
#ifndef HB_NO_DRAW
-#ifdef HB_EXPERIMENTAL_API
#include "hb-draw.hh"
-#include "hb-ot.h"
-#include "hb-ot-glyf-table.hh"
-#include "hb-ot-cff1-table.hh"
-#include "hb-ot-cff2-table.hh"
/**
- * hb_draw_funcs_set_move_to_func:
- * @funcs: draw functions object
- * @move_to: move-to callback
+ * SECTION:hb-draw
+ * @title: hb-draw
+ * @short_description: Glyph drawing
+ * @include: hb.h
*
- * Sets move-to callback to the draw functions object.
- *
- * Since: EXPERIMENTAL
+ * Functions for drawing (extracting) glyph shapes.
**/
-void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to)
+
+static void
+hb_draw_move_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_line_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->move_to = move_to;
+#define HB_ONE_THIRD 0.33333333f
+ dfuncs->emit_cubic_to (draw_data, *st,
+ (st->current_x + 2.f * control_x) * HB_ONE_THIRD,
+ (st->current_y + 2.f * control_y) * HB_ONE_THIRD,
+ (to_x + 2.f * control_x) * HB_ONE_THIRD,
+ (to_y + 2.f * control_y) * HB_ONE_THIRD,
+ to_x, to_y);
+#undef HB_ONE_THIRD
}
+static void
+hb_draw_cubic_to_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ float control1_x HB_UNUSED, float control1_y HB_UNUSED,
+ float control2_x HB_UNUSED, float control2_y HB_UNUSED,
+ float to_x HB_UNUSED, float to_y HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+static void
+hb_draw_close_path_nil (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data HB_UNUSED,
+ hb_draw_state_t *st HB_UNUSED,
+ void *user_data HB_UNUSED) {}
+
+
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ \
+void \
+hb_draw_funcs_set_##name##_func (hb_draw_funcs_t *dfuncs, \
+ hb_draw_##name##_func_t func, \
+ void *user_data, \
+ hb_destroy_func_t destroy) \
+{ \
+ if (hb_object_is_immutable (dfuncs)) \
+ return; \
+ \
+ if (dfuncs->destroy && dfuncs->destroy->name) \
+ dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name); \
+ \
+ if (user_data && !dfuncs->user_data) \
+ { \
+ dfuncs->user_data = (decltype (dfuncs->user_data)) hb_calloc (1, sizeof (*dfuncs->user_data)); \
+ if (unlikely (!dfuncs->user_data)) \
+ goto fail; \
+ } \
+ if (destroy && !dfuncs->destroy) \
+ { \
+ dfuncs->destroy = (decltype (dfuncs->destroy)) hb_calloc (1, sizeof (*dfuncs->destroy)); \
+ if (unlikely (!dfuncs->destroy)) \
+ goto fail; \
+ } \
+ \
+ if (func) { \
+ dfuncs->func.name = func; \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = user_data; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = destroy; \
+ } else { \
+ dfuncs->func.name = hb_draw_##name##_nil; \
+ if (dfuncs->user_data) \
+ dfuncs->user_data->name = nullptr; \
+ if (dfuncs->destroy) \
+ dfuncs->destroy->name = nullptr; \
+ } \
+ return; \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
+}
+
+HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+
/**
- * hb_draw_funcs_set_line_to_func:
- * @funcs: draw functions object
- * @line_to: line-to callback
+ * hb_draw_funcs_create:
+ *
+ * Creates a new draw callbacks object.
*
- * Sets line-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * A newly allocated #hb_draw_funcs_t with a reference count of 1. The initial
+ * reference count should be released with hb_draw_funcs_destroy when you are
+ * done using the #hb_draw_funcs_t. This function never returns `NULL`. If
+ * memory cannot be allocated, a special singleton #hb_draw_funcs_t object will
+ * be returned.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to)
+hb_draw_funcs_t *
+hb_draw_funcs_create ()
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->line_to = line_to;
+ hb_draw_funcs_t *dfuncs;
+ if (unlikely (!(dfuncs = hb_object_create<hb_draw_funcs_t> ())))
+ return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
+
+ dfuncs->func = Null (hb_draw_funcs_t).func;
+
+ return dfuncs;
}
+DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_nil,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+
/**
- * hb_draw_funcs_set_quadratic_to_func:
- * @funcs: draw functions object
- * @move_to: quadratic-to callback
+ * hb_draw_funcs_reference: (skip)
+ * @dfuncs: draw functions
+ *
+ * Increases the reference count on @dfuncs by one. This prevents @buffer from
+ * being destroyed until a matching call to hb_draw_funcs_destroy() is made.
*
- * Sets quadratic-to callback to the draw functions object.
+ * Return value: (transfer full):
+ * The referenced #hb_draw_funcs_t.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to)
+hb_draw_funcs_t *
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->quadratic_to = quadratic_to;
- funcs->is_quadratic_to_set = true;
+ return hb_object_reference (dfuncs);
}
/**
- * hb_draw_funcs_set_cubic_to_func:
- * @funcs: draw functions
- * @cubic_to: cubic-to callback
+ * hb_draw_funcs_destroy: (skip)
+ * @dfuncs: draw functions
*
- * Sets cubic-to callback to the draw functions object.
+ * Deallocate the @dfuncs.
+ * Decreases the reference count on @dfuncs by one. If the result is zero, then
+ * @dfuncs and all associated resources are freed. See hb_draw_funcs_reference().
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to)
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->cubic_to = cubic_to;
+ if (!hb_object_destroy (dfuncs)) return;
+
+ if (dfuncs->destroy)
+ {
+#define HB_DRAW_FUNC_IMPLEMENT(name) \
+ if (dfuncs->destroy->name) dfuncs->destroy->name (!dfuncs->user_data ? nullptr : dfuncs->user_data->name);
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+
+ hb_free (dfuncs->destroy);
+ hb_free (dfuncs->user_data);
+
+ hb_free (dfuncs);
}
/**
- * hb_draw_funcs_set_close_path_func:
- * @funcs: draw functions object
- * @close_path: close-path callback
+ * hb_draw_funcs_make_immutable:
+ * @dfuncs: draw functions
*
- * Sets close-path callback to the draw functions object.
+ * Makes @dfuncs object immutable.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path)
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs)
{
- if (unlikely (hb_object_is_immutable (funcs))) return;
- funcs->close_path = close_path;
-}
-
-static void
-_move_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_line_to_nil (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
-
-static void
-_quadratic_to_nil (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
-
-static void
-_cubic_to_nil (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
- hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
- hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
- void *user_data HB_UNUSED) {}
+ if (hb_object_is_immutable (dfuncs))
+ return;
-static void
-_close_path_nil (void *user_data HB_UNUSED) {}
+ hb_object_make_immutable (dfuncs);
+}
/**
- * hb_draw_funcs_create:
+ * hb_draw_funcs_is_immutable:
+ * @dfuncs: draw functions
*
- * Creates a new draw callbacks object.
+ * Checks whether @dfuncs is immutable.
*
- * Since: EXPERIMENTAL
+ * Return value: `true` if @dfuncs is immutable, `false` otherwise
+ *
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_create ()
+hb_bool_t
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs)
{
- hb_draw_funcs_t *funcs;
- if (unlikely (!(funcs = hb_object_create<hb_draw_funcs_t> ())))
- return const_cast<hb_draw_funcs_t *> (&Null (hb_draw_funcs_t));
-
- funcs->move_to = (hb_draw_move_to_func_t) _move_to_nil;
- funcs->line_to = (hb_draw_line_to_func_t) _line_to_nil;
- funcs->quadratic_to = (hb_draw_quadratic_to_func_t) _quadratic_to_nil;
- funcs->is_quadratic_to_set = false;
- funcs->cubic_to = (hb_draw_cubic_to_func_t) _cubic_to_nil;
- funcs->close_path = (hb_draw_close_path_func_t) _close_path_nil;
- return funcs;
+ return hb_object_is_immutable (dfuncs);
}
+
/**
- * hb_draw_funcs_reference:
- * @funcs: draw functions
+ * hb_draw_move_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Add to callbacks object refcount.
+ * Perform a "move-to" draw operation.
*
- * Returns: The same object.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs)
+void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- return hb_object_reference (funcs);
+ dfuncs->move_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_destroy:
- * @funcs: draw functions
+ * hb_draw_line_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Decreases refcount of callbacks object and deletes the object if it reaches
- * to zero.
+ * Perform a "line-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs)
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y)
{
- if (!hb_object_destroy (funcs)) return;
-
- hb_free (funcs);
+ dfuncs->line_to (draw_data, *st,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_make_immutable:
- * @funcs: draw functions
+ * hb_draw_quadratic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Makes funcs object immutable.
+ * Perform a "quadratic-to" draw operation.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs)
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (hb_object_is_immutable (funcs))
- return;
-
- hb_object_make_immutable (funcs);
+ dfuncs->quadratic_to (draw_data, *st,
+ control_x, control_y,
+ to_x, to_y);
}
/**
- * hb_draw_funcs_is_immutable:
- * @funcs: draw functions
+ * hb_draw_cubic_to:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
*
- * Checks whether funcs is immutable.
+ * Perform a "cubic-to" draw operation.
*
- * Returns: If is immutable.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs)
+void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
{
- return hb_object_is_immutable (funcs);
+ dfuncs->cubic_to (draw_data, *st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
}
/**
- * hb_font_draw_glyph:
- * @font: a font object
- * @glyph: a glyph id
- * @funcs: draw callbacks object
- * @user_data: parameter you like be passed to the callbacks when are called
+ * hb_draw_close_path:
+ * @dfuncs: draw functions
+ * @draw_data: associated draw data passed by the caller
+ * @st: current draw state
*
- * Draw a glyph.
+ * Perform a "close-path" draw operation.
*
- * Returns: Whether the font had the glyph and the operation completed successfully.
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
-hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs,
- void *user_data)
+void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st)
{
- if (unlikely (funcs == &Null (hb_draw_funcs_t) ||
- glyph >= font->face->get_num_glyphs ()))
- return false;
-
- draw_helper_t draw_helper (funcs, user_data);
- if (font->face->table.glyf->get_path (font, glyph, draw_helper)) return true;
-#ifndef HB_NO_CFF
- if (font->face->table.cff1->get_path (font, glyph, draw_helper)) return true;
- if (font->face->table.cff2->get_path (font, glyph, draw_helper)) return true;
-#endif
-
- return false;
+ dfuncs->close_path (draw_data, *st);
}
-#endif
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-draw.h b/thirdparty/harfbuzz/src/hb-draw.h
index f82cc34842..c45a53212a 100644
--- a/thirdparty/harfbuzz/src/hb-draw.h
+++ b/thirdparty/harfbuzz/src/hb-draw.h
@@ -33,65 +33,292 @@
HB_BEGIN_DECLS
-#ifdef HB_EXPERIMENTAL_API
-typedef void (*hb_draw_move_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_line_to_func_t) (hb_position_t to_x, hb_position_t to_y, void *user_data);
-typedef void (*hb_draw_quadratic_to_func_t) (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_cubic_to_func_t) (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y,
- void *user_data);
-typedef void (*hb_draw_close_path_func_t) (void *user_data);
+
+/**
+ * hb_draw_state_t
+ * @path_open: Whether there is an open path
+ * @path_start_x: X component of the start of current path
+ * @path_start_y: Y component of the start of current path
+ * @current_x: X component of current point
+ * @current_y: Y component of current point
+ *
+ * Current drawing state.
+ *
+ * Since: 4.0.0
+ **/
+typedef struct hb_draw_state_t {
+ hb_bool_t path_open;
+
+ float path_start_x;
+ float path_start_y;
+
+ float current_x;
+ float current_y;
+
+ /*< private >*/
+ hb_var_num_t reserved1;
+ hb_var_num_t reserved2;
+ hb_var_num_t reserved3;
+ hb_var_num_t reserved4;
+ hb_var_num_t reserved5;
+ hb_var_num_t reserved6;
+ hb_var_num_t reserved7;
+} hb_draw_state_t;
+
+/**
+ * HB_DRAW_STATE_DEFAULT:
+ *
+ * The default #hb_draw_state_t at the start of glyph drawing.
+ */
+#define HB_DRAW_STATE_DEFAULT {0, 0.f, 0.f, 0.f, 0.f, {0.}, {0.}, {0.}}
+
/**
* hb_draw_funcs_t:
*
* Glyph draw callbacks.
*
- * _move_to, _line_to and _cubic_to calls are necessary to be defined but we
- * translate _quadratic_to calls to _cubic_to if the callback isn't defined.
+ * #hb_draw_move_to_func_t, #hb_draw_line_to_func_t and
+ * #hb_draw_cubic_to_func_t calls are necessary to be defined but we translate
+ * #hb_draw_quadratic_to_func_t calls to #hb_draw_cubic_to_func_t if the
+ * callback isn't defined.
*
- * Since: EXPERIMENTAL
+ * Since: 4.0.0
**/
+
typedef struct hb_draw_funcs_t hb_draw_funcs_t;
+
+/**
+ * hb_draw_move_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "move-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_move_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_line_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "line-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_line_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_quadratic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control_x: X component of control point
+ * @control_y: Y component of control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "quadratic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_quadratic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_cubic_to_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @control1_x: X component of first control point
+ * @control1_y: Y component of first control point
+ * @control2_x: X component of second control point
+ * @control2_y: Y component of second control point
+ * @to_x: X component of target point
+ * @to_y: Y component of target point
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "cubic-to" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_cubic_to_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data);
+
+/**
+ * hb_draw_close_path_func_t:
+ * @dfuncs: draw functions object
+ * @draw_data: The data accompanying the draw functions
+ * @st: current draw state
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_draw_funcs_t to perform a "close-path" draw
+ * operation.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_draw_close_path_func_t) (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data);
+
+/**
+ * hb_draw_funcs_set_move_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): move-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets move-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *funcs,
- hb_draw_move_to_func_t move_to);
+hb_draw_funcs_set_move_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_move_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_line_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): line-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets line-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *funcs,
- hb_draw_line_to_func_t line_to);
+hb_draw_funcs_set_line_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_line_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_quadratic_to_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): quadratic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets quadratic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_quadratic_to_func_t quadratic_to);
+hb_draw_funcs_set_quadratic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_quadratic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_cubic_to_func:
+ * @dfuncs: draw functions
+ * @func: (closure user_data) (destroy destroy) (scope notified): cubic-to callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets cubic-to callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *funcs,
- hb_draw_cubic_to_func_t cubic_to);
+hb_draw_funcs_set_cubic_to_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_cubic_to_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_draw_funcs_set_close_path_func:
+ * @dfuncs: draw functions object
+ * @func: (closure user_data) (destroy destroy) (scope notified): close-path callback
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets close-path callback to the draw functions object.
+ *
+ * Since: 4.0.0
+ **/
HB_EXTERN void
-hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *funcs,
- hb_draw_close_path_func_t close_path);
+hb_draw_funcs_set_close_path_func (hb_draw_funcs_t *dfuncs,
+ hb_draw_close_path_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
HB_EXTERN hb_draw_funcs_t *
hb_draw_funcs_create (void);
HB_EXTERN hb_draw_funcs_t *
-hb_draw_funcs_reference (hb_draw_funcs_t *funcs);
+hb_draw_funcs_reference (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_destroy (hb_draw_funcs_t *funcs);
+hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs);
HB_EXTERN void
-hb_draw_funcs_make_immutable (hb_draw_funcs_t *funcs);
+hb_draw_funcs_make_immutable (hb_draw_funcs_t *dfuncs);
HB_EXTERN hb_bool_t
-hb_draw_funcs_is_immutable (hb_draw_funcs_t *funcs);
-#endif
+hb_draw_funcs_is_immutable (hb_draw_funcs_t *dfuncs);
+
+
+HB_EXTERN void
+hb_draw_move_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_line_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_quadratic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_cubic_to (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y);
+
+HB_EXTERN void
+hb_draw_close_path (hb_draw_funcs_t *dfuncs, void *draw_data,
+ hb_draw_state_t *st);
+
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-draw.hh b/thirdparty/harfbuzz/src/hb-draw.hh
index 2aa0a5b4db..768f51a875 100644
--- a/thirdparty/harfbuzz/src/hb-draw.hh
+++ b/thirdparty/harfbuzz/src/hb-draw.hh
@@ -27,113 +27,205 @@
#include "hb.hh"
-#ifdef HB_EXPERIMENTAL_API
-struct hb_draw_funcs_t
-{
- hb_object_header_t header;
- hb_draw_move_to_func_t move_to;
- hb_draw_line_to_func_t line_to;
- hb_draw_quadratic_to_func_t quadratic_to;
- bool is_quadratic_to_set;
- hb_draw_cubic_to_func_t cubic_to;
- hb_draw_close_path_func_t close_path;
-};
+/*
+ * hb_draw_funcs_t
+ */
+
+#define HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS \
+ HB_DRAW_FUNC_IMPLEMENT (move_to) \
+ HB_DRAW_FUNC_IMPLEMENT (line_to) \
+ HB_DRAW_FUNC_IMPLEMENT (quadratic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (cubic_to) \
+ HB_DRAW_FUNC_IMPLEMENT (close_path) \
+ /* ^--- Add new callbacks here */
-struct draw_helper_t
+struct hb_draw_funcs_t
{
- draw_helper_t (const hb_draw_funcs_t *funcs_, void *user_data_)
- {
- funcs = funcs_;
- user_data = user_data_;
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
- }
- ~draw_helper_t () { end_path (); }
+ hb_object_header_t header;
- void move_to (hb_position_t x, hb_position_t y)
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } func;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) void *name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } *user_data;
+
+ struct {
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ } *destroy;
+
+ void emit_move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.move_to (this, draw_data, &st,
+ to_x, to_y,
+ !user_data ? nullptr : user_data->move_to); }
+ void emit_line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
+ { func.line_to (this, draw_data, &st,
+ to_x, to_y,
+ !user_data ? nullptr : user_data->line_to); }
+ void emit_quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
+ { func.quadratic_to (this, draw_data, &st,
+ control_x, control_y,
+ to_x, to_y,
+ !user_data ? nullptr : user_data->quadratic_to); }
+ void emit_cubic_to (void *draw_data, hb_draw_state_t &st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
+ { func.cubic_to (this, draw_data, &st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y,
+ !user_data ? nullptr : user_data->cubic_to); }
+ void emit_close_path (void *draw_data, hb_draw_state_t &st)
+ { func.close_path (this, draw_data, &st,
+ !user_data ? nullptr : user_data->close_path); }
+
+
+ void move_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (path_open) end_path ();
- current_x = path_start_x = x;
- current_y = path_start_y = y;
+ if (st.path_open) close_path (draw_data, st);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
- void line_to (hb_position_t x, hb_position_t y)
+ void line_to (void *draw_data, hb_draw_state_t &st,
+ float to_x, float to_y)
{
- if (equal_to_current (x, y)) return;
- if (!path_open) start_path ();
- funcs->line_to (x, y, user_data);
- current_x = x;
- current_y = y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_line_to (draw_data, st, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
void
- quadratic_to (hb_position_t control_x, hb_position_t control_y,
- hb_position_t to_x, hb_position_t to_y)
+ quadratic_to (void *draw_data, hb_draw_state_t &st,
+ float control_x, float control_y,
+ float to_x, float to_y)
{
- if (equal_to_current (control_x, control_y) && equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- if (funcs->is_quadratic_to_set)
- funcs->quadratic_to (control_x, control_y, to_x, to_y, user_data);
- else
- funcs->cubic_to (roundf ((current_x + 2.f * control_x) / 3.f),
- roundf ((current_y + 2.f * control_y) / 3.f),
- roundf ((to_x + 2.f * control_x) / 3.f),
- roundf ((to_y + 2.f * control_y) / 3.f),
- to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_quadratic_to (draw_data, st, control_x, control_y, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
void
- cubic_to (hb_position_t control1_x, hb_position_t control1_y,
- hb_position_t control2_x, hb_position_t control2_y,
- hb_position_t to_x, hb_position_t to_y)
+ cubic_to (void *draw_data, hb_draw_state_t &st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
{
- if (equal_to_current (control1_x, control1_y) &&
- equal_to_current (control2_x, control2_y) &&
- equal_to_current (to_x, to_y))
- return;
- if (!path_open) start_path ();
- funcs->cubic_to (control1_x, control1_y, control2_x, control2_y, to_x, to_y, user_data);
- current_x = to_x;
- current_y = to_y;
+ if (!st.path_open) start_path (draw_data, st);
+ emit_cubic_to (draw_data, st, control1_x, control1_y, control2_x, control2_y, to_x, to_y);
+ st.current_x = to_x;
+ st.current_y = to_y;
}
- void end_path ()
+ void
+ close_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open)
+ if (st.path_open)
{
- if ((path_start_x != current_x) || (path_start_y != current_y))
- funcs->line_to (path_start_x, path_start_y, user_data);
- funcs->close_path (user_data);
+ if ((st.path_start_x != st.current_x) || (st.path_start_y != st.current_y))
+ emit_line_to (draw_data, st, st.path_start_x, st.path_start_y);
+ emit_close_path (draw_data, st);
}
- path_open = false;
- path_start_x = current_x = path_start_y = current_y = 0;
+ st.path_open = false;
+ st.path_start_x = st.current_x = st.path_start_y = st.current_y = 0;
}
protected:
- bool equal_to_current (hb_position_t x, hb_position_t y)
- { return current_x == x && current_y == y; }
- void start_path ()
+ void start_path (void *draw_data, hb_draw_state_t &st)
{
- if (path_open) end_path ();
- path_open = true;
- funcs->move_to (path_start_x, path_start_y, user_data);
+ assert (!st.path_open);
+ emit_move_to (draw_data, st, st.current_x, st.current_y);
+ st.path_open = true;
+ st.path_start_x = st.current_x;
+ st.path_start_y = st.current_y;
}
+};
+DECLARE_NULL_INSTANCE (hb_draw_funcs_t);
- hb_position_t path_start_x;
- hb_position_t path_start_y;
+struct hb_draw_session_t
+{
+ hb_draw_session_t (hb_draw_funcs_t *funcs_, void *draw_data_, float slant_ = 0.f)
+ : slant {slant_}, not_slanted {slant == 0.f},
+ funcs {funcs_}, draw_data {draw_data_}, st HB_DRAW_STATE_DEFAULT
+ {}
- hb_position_t current_x;
- hb_position_t current_y;
+ ~hb_draw_session_t () { close_path (); }
- bool path_open;
- const hb_draw_funcs_t *funcs;
- void *user_data;
+ void move_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->move_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->move_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void line_to (float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->line_to (draw_data, st,
+ to_x, to_y);
+ else
+ funcs->line_to (draw_data, st,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ quadratic_to (float control_x, float control_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->quadratic_to (draw_data, st,
+ control_x, control_y,
+ to_x, to_y);
+ else
+ funcs->quadratic_to (draw_data, st,
+ control_x + control_y * slant, control_y,
+ to_x + to_y * slant, to_y);
+ }
+ void
+ cubic_to (float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y)
+ {
+ if (likely (not_slanted))
+ funcs->cubic_to (draw_data, st,
+ control1_x, control1_y,
+ control2_x, control2_y,
+ to_x, to_y);
+ else
+ funcs->cubic_to (draw_data, st,
+ control1_x + control1_y * slant, control1_y,
+ control2_x + control2_y * slant, control2_y,
+ to_x + to_y * slant, to_y);
+ }
+ void close_path ()
+ {
+ funcs->close_path (draw_data, st);
+ }
+
+ protected:
+ float slant;
+ bool not_slanted;
+ hb_draw_funcs_t *funcs;
+ void *draw_data;
+ hb_draw_state_t st;
};
-#endif
#endif /* HB_DRAW_HH */
diff --git a/thirdparty/harfbuzz/src/hb-face.cc b/thirdparty/harfbuzz/src/hb-face.cc
index 5365598636..61adbdd503 100644
--- a/thirdparty/harfbuzz/src/hb-face.cc
+++ b/thirdparty/harfbuzz/src/hb-face.cc
@@ -190,7 +190,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
}
/**
- * hb_face_create: (Xconstructor)
+ * hb_face_create:
* @blob: #hb_blob_t to work upon
* @index: The index of the face within @blob
*
@@ -315,7 +315,7 @@ hb_face_destroy (hb_face_t *face)
*
* Attaches a user-data key/data pair to the given face object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -371,7 +371,7 @@ hb_face_make_immutable (hb_face_t *face)
*
* Tests whether the given face object is immutable.
*
- * Return value: %true is @face is immutable, %false otherwise
+ * Return value: `true` is @face is immutable, `false` otherwise
*
* Since: 0.9.2
**/
diff --git a/thirdparty/harfbuzz/src/hb-font.cc b/thirdparty/harfbuzz/src/hb-font.cc
index 350fcac139..856bbdda32 100644
--- a/thirdparty/harfbuzz/src/hb-font.cc
+++ b/thirdparty/harfbuzz/src/hb-font.cc
@@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-font.hh"
+#include "hb-draw.hh"
#include "hb-machinery.hh"
#include "hb-ot.h"
@@ -501,20 +502,142 @@ hb_font_get_glyph_from_name_default (hb_font_t *font,
return font->parent->get_glyph_from_name (name, len, glyph);
}
-DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+static void
+hb_font_get_glyph_shape_nil (hb_font_t *font HB_UNUSED,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+}
+
+
+typedef struct hb_font_get_glyph_shape_default_adaptor_t {
+ hb_draw_funcs_t *draw_funcs;
+ void *draw_data;
+ float x_scale;
+ float y_scale;
+} hb_font_get_glyph_shape_default_adaptor_t;
+
+static void
+hb_draw_move_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED,
+ void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ adaptor->draw_funcs->emit_move_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_line_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_line_to (adaptor->draw_data, *st,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_quadratic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float control_x, float control_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_quadratic_to (adaptor->draw_data, *st,
+ x_scale * control_x, y_scale * control_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_cubic_to_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ float control1_x, float control1_y,
+ float control2_x, float control2_y,
+ float to_x, float to_y,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+ float x_scale = adaptor->x_scale;
+ float y_scale = adaptor->y_scale;
+
+ st->current_x *= x_scale;
+ st->current_y *= y_scale;
+
+ adaptor->draw_funcs->emit_cubic_to (adaptor->draw_data, *st,
+ x_scale * control1_x, y_scale * control1_y,
+ x_scale * control2_x, y_scale * control2_y,
+ x_scale * to_x, y_scale * to_y);
+}
+
+static void
+hb_draw_close_path_default (hb_draw_funcs_t *dfuncs HB_UNUSED, void *draw_data,
+ hb_draw_state_t *st,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t *adaptor = (hb_font_get_glyph_shape_default_adaptor_t *) draw_data;
+
+ adaptor->draw_funcs->emit_close_path (adaptor->draw_data, *st);
+}
+
+static const hb_draw_funcs_t _hb_draw_funcs_default = {
HB_OBJECT_HEADER_STATIC,
{
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+#define HB_DRAW_FUNC_IMPLEMENT(name) hb_draw_##name##_default,
+ HB_DRAW_FUNCS_IMPLEMENT_CALLBACKS
+#undef HB_DRAW_FUNC_IMPLEMENT
+ }
+};
+
+static void
+hb_font_get_glyph_shape_default (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs,
+ void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ hb_font_get_glyph_shape_default_adaptor_t adaptor = {
+ draw_funcs,
+ draw_data,
+ (float) font->x_scale / (float) font->parent->x_scale,
+ (float) font->y_scale / (float) font->parent->y_scale
+ };
+
+ font->parent->get_glyph_shape (glyph,
+ const_cast<hb_draw_funcs_t *> (&_hb_draw_funcs_default),
+ &adaptor);
+}
+
+DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
+{
+ HB_OBJECT_HEADER_STATIC,
+
+ nullptr,
+ nullptr,
{
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_nil,
@@ -527,16 +650,8 @@ DEFINE_NULL_INSTANCE (hb_font_funcs_t) =
static const hb_font_funcs_t _hb_font_funcs_default = {
HB_OBJECT_HEADER_STATIC,
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
- {
-#define HB_FONT_FUNC_IMPLEMENT(name) nullptr,
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
-#undef HB_FONT_FUNC_IMPLEMENT
- },
+ nullptr,
+ nullptr,
{
{
#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_default,
@@ -548,7 +663,7 @@ static const hb_font_funcs_t _hb_font_funcs_default = {
/**
- * hb_font_funcs_create: (Xconstructor)
+ * hb_font_funcs_create:
*
* Creates a new #hb_font_funcs_t structure of font functions.
*
@@ -615,10 +730,16 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
{
if (!hb_object_destroy (ffuncs)) return;
-#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name);
- HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
+ if (ffuncs->destroy)
+ {
+#define HB_FONT_FUNC_IMPLEMENT(name) if (ffuncs->destroy->name) \
+ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name);
+ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
+ }
+
+ hb_free (ffuncs->destroy);
+ hb_free (ffuncs->user_data);
hb_free (ffuncs);
}
@@ -633,7 +754,7 @@ hb_font_funcs_destroy (hb_font_funcs_t *ffuncs)
*
* Attaches a user-data key/data pair to the specified font-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -660,8 +781,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
* Since: 0.9.2
**/
void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key)
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ffuncs, key);
}
@@ -690,7 +811,7 @@ hb_font_funcs_make_immutable (hb_font_funcs_t *ffuncs)
*
* Tests whether a font-functions structure is immutable.
*
- * Return value: %true if @ffuncs is immutable, %false otherwise
+ * Return value: `true` if @ffuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -710,24 +831,50 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \
hb_destroy_func_t destroy) \
{ \
if (hb_object_is_immutable (ffuncs)) \
+ goto fail; \
+ \
+ if (!func) \
{ \
if (destroy) \
destroy (user_data); \
- return; \
+ destroy = nullptr; \
+ user_data = nullptr; \
} \
\
- if (ffuncs->destroy.name) \
- ffuncs->destroy.name (ffuncs->user_data.name); \
+ if (ffuncs->destroy && ffuncs->destroy->name) \
+ ffuncs->destroy->name (!ffuncs->user_data ? nullptr : ffuncs->user_data->name); \
+ \
+ if (user_data && !ffuncs->user_data) \
+ { \
+ ffuncs->user_data = (decltype (ffuncs->user_data)) hb_calloc (1, sizeof (*ffuncs->user_data)); \
+ if (unlikely (!ffuncs->user_data)) \
+ goto fail; \
+ } \
+ if (destroy && !ffuncs->destroy) \
+ { \
+ ffuncs->destroy = (decltype (ffuncs->destroy)) hb_calloc (1, sizeof (*ffuncs->destroy)); \
+ if (unlikely (!ffuncs->destroy)) \
+ goto fail; \
+ } \
\
if (func) { \
ffuncs->get.f.name = func; \
- ffuncs->user_data.name = user_data; \
- ffuncs->destroy.name = destroy; \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = user_data; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = destroy; \
} else { \
ffuncs->get.f.name = hb_font_get_##name##_default; \
- ffuncs->user_data.name = nullptr; \
- ffuncs->destroy.name = nullptr; \
+ if (ffuncs->user_data) \
+ ffuncs->user_data->name = nullptr; \
+ if (ffuncs->destroy) \
+ ffuncs->destroy->name = nullptr; \
} \
+ return; \
+ \
+fail: \
+ if (destroy) \
+ destroy (user_data); \
}
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
@@ -756,7 +903,7 @@ hb_font_t::has_func (unsigned int i)
* Fetches the extents for a specified font, for horizontal
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -775,7 +922,7 @@ hb_font_get_h_extents (hb_font_t *font,
* Fetches the extents for a specified font, for vertical
* text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.1.3
**/
@@ -799,7 +946,7 @@ hb_font_get_v_extents (hb_font_t *font,
* If @variation_selector is 0, calls hb_font_get_nominal_glyph();
* otherwise calls hb_font_get_variation_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -827,7 +974,7 @@ hb_font_get_glyph (hb_font_t *font,
* for code points modified by variation selectors. For variation-selector
* support, user hb_font_get_variation_glyph() or use hb_font_get_glyph().
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -879,7 +1026,7 @@ hb_font_get_nominal_glyphs (hb_font_t *font,
* by the specified variation-selector code point, in the specified
* font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.2.3
**/
@@ -989,7 +1136,7 @@ hb_font_get_glyph_v_advances (hb_font_t* font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for horizontal text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1012,7 +1159,7 @@ hb_font_get_glyph_h_origin (hb_font_t *font,
* Fetches the (X,Y) coordinates of the origin for a glyph ID
* in the specified font, for vertical text segments.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1085,7 +1232,7 @@ hb_font_get_glyph_v_kerning (hb_font_t *font,
* Fetches the #hb_glyph_extents_t data for a glyph ID
* in the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1108,7 +1255,7 @@ hb_font_get_glyph_extents (hb_font_t *font,
* Fetches the (x,y) coordinates of a specified contour-point index
* in the specified glyph, within the specified font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1131,7 +1278,7 @@ hb_font_get_glyph_contour_point (hb_font_t *font,
*
* Fetches the glyph-name string for a glyph ID in the specified @font.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1155,7 +1302,7 @@ hb_font_get_glyph_name (hb_font_t *font,
*
* <note>Note: @len == -1 means the name string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1168,6 +1315,26 @@ hb_font_get_glyph_from_name (hb_font_t *font,
return font->get_glyph_from_name (name, len, glyph);
}
+/**
+ * hb_font_get_glyph_shape:
+ * @font: #hb_font_t to work upon
+ * @glyph: : The glyph ID
+ * @dfuncs: #hb_draw_funcs_t to draw to
+ * @draw_data: User data to pass to draw callbacks
+ *
+ * Fetches the glyph shape that corresponds to a glyph in the specified @font.
+ * The shape is returned by way of calls to the callsbacks of the @dfuncs
+ * objects, with @draw_data passed to them.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data)
+{
+ font->get_glyph_shape (glyph, dfuncs, draw_data);
+}
/* A bit higher-level, and with fallback */
@@ -1190,7 +1357,7 @@ hb_font_get_extents_for_direction (hb_font_t *font,
hb_direction_t direction,
hb_font_extents_t *extents)
{
- return font->get_extents_for_direction (direction, extents);
+ font->get_extents_for_direction (direction, extents);
}
/**
* hb_font_get_glyph_advance_for_direction:
@@ -1215,7 +1382,7 @@ hb_font_get_glyph_advance_for_direction (hb_font_t *font,
hb_position_t *x,
hb_position_t *y)
{
- return font->get_glyph_advance_for_direction (glyph, direction, x, y);
+ font->get_glyph_advance_for_direction (glyph, direction, x, y);
}
/**
* hb_font_get_glyph_advances_for_direction:
@@ -1370,7 +1537,7 @@ hb_font_get_glyph_kerning_for_direction (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1399,7 +1566,7 @@ hb_font_get_glyph_extents_for_origin (hb_font_t *font,
* Calls the appropriate direction-specific variant (horizontal
* or vertical) depending on the value of @direction.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1450,7 +1617,7 @@ hb_font_glyph_to_string (hb_font_t *font,
*
* <note>Note: @len == -1 means the string is null-terminated.</note>
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1472,6 +1639,9 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
{
HB_OBJECT_HEADER_STATIC,
+ 0, /* serial */
+ 0, /* serial_coords */
+
nullptr, /* parent */
const_cast<hb_face_t *> (&_hb_Null_hb_face_t),
@@ -1479,6 +1649,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
1000, /* y_scale */
0., /* slant */
0., /* slant_xy; */
+ 1.f, /* x_multf */
+ 1.f, /* y_multf */
1<<16, /* x_mult */
1<<16, /* y_mult */
@@ -1503,6 +1675,7 @@ _hb_font_create (hb_face_t *face)
if (unlikely (!face))
face = hb_face_get_empty ();
+
if (!(font = hb_object_create<hb_font_t> ()))
return hb_font_get_empty ();
@@ -1511,14 +1684,15 @@ _hb_font_create (hb_face_t *face)
font->face = hb_face_reference (face);
font->klass = hb_font_funcs_get_empty ();
font->data.init0 (font);
- font->x_scale = font->y_scale = hb_face_get_upem (face);
+ font->x_scale = font->y_scale = face->get_upem ();
+ font->x_multf = font->y_multf = 1.f;
font->x_mult = font->y_mult = 1 << 16;
return font;
}
/**
- * hb_font_create: (Xconstructor)
+ * hb_font_create:
* @face: a face.
*
* Constructs a new font object from the specified face.
@@ -1564,6 +1738,8 @@ _hb_font_adopt_var_coords (hb_font_t *font,
font->coords = coords;
font->design_coords = design_coords;
font->num_coords = coords_length;
+
+ font->mults_changed (); // Easiest to call this to drop cached data
}
/**
@@ -1593,7 +1769,6 @@ hb_font_create_sub_font (hb_font_t *parent)
font->x_scale = parent->x_scale;
font->y_scale = parent->y_scale;
font->slant = parent->slant;
- font->mults_changed ();
font->x_ppem = parent->x_ppem;
font->y_ppem = parent->y_ppem;
font->ptem = parent->ptem;
@@ -1616,6 +1791,8 @@ hb_font_create_sub_font (hb_font_t *parent)
}
}
+ font->mults_changed ();
+
return font;
}
@@ -1690,7 +1867,7 @@ hb_font_destroy (hb_font_t *font)
*
* Attaches a user-data key/data pair to the specified font object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1701,6 +1878,9 @@ hb_font_set_user_data (hb_font_t *font,
hb_destroy_func_t destroy /* May be NULL. */,
hb_bool_t replace)
{
+ if (!hb_object_is_immutable (font))
+ font->serial++;
+
return hb_object_set_user_data (font, key, data, destroy, replace);
}
@@ -1717,7 +1897,7 @@ hb_font_set_user_data (hb_font_t *font,
* Since: 0.9.2
**/
void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (font, key);
@@ -1749,7 +1929,7 @@ hb_font_make_immutable (hb_font_t *font)
*
* Tests whether a font object is immutable.
*
- * Return value: %true if @font is immutable, %false otherwise
+ * Return value: `true` if @font is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -1760,6 +1940,45 @@ hb_font_is_immutable (hb_font_t *font)
}
/**
+ * hb_font_get_serial:
+ * @font: #hb_font_t to work upon
+ *
+ * Returns the internal serial number of the font. The serial
+ * number is increased every time a setting on the font is
+ * changed, using a setter function.
+ *
+ * Return value: serial number
+ *
+ * Since: 4.4.0
+ **/
+unsigned int
+hb_font_get_serial (hb_font_t *font)
+{
+ return font->serial;
+}
+
+/**
+ * hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Notifies the @font that underlying font data has changed.
+ * This has the effect of increasing the serial as returned
+ * by hb_font_get_serial(), which invalidates internal caches.
+ *
+ * Since: 4.4.0
+ **/
+void
+hb_font_changed (hb_font_t *font)
+{
+ if (hb_object_is_immutable (font))
+ return;
+
+ font->serial++;
+
+ font->mults_changed ();
+}
+
+/**
* hb_font_set_parent:
* @font: #hb_font_t to work upon
* @parent: The parent font object to assign
@@ -1775,6 +1994,11 @@ hb_font_set_parent (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (parent == font->parent)
+ return;
+
+ font->serial++;
+
if (!parent)
parent = hb_font_get_empty ();
@@ -1817,6 +2041,11 @@ hb_font_set_face (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (face == font->face)
+ return;
+
+ font->serial++;
+
if (unlikely (!face))
face = hb_face_get_empty ();
@@ -1871,6 +2100,8 @@ hb_font_set_funcs (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -1908,6 +2139,8 @@ hb_font_set_funcs_data (hb_font_t *font,
return;
}
+ font->serial++;
+
if (font->destroy)
font->destroy (font->user_data);
@@ -1934,6 +2167,11 @@ hb_font_set_scale (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_scale == x_scale && font->y_scale == y_scale)
+ return;
+
+ font->serial++;
+
font->x_scale = x_scale;
font->y_scale = y_scale;
font->mults_changed ();
@@ -1976,6 +2214,11 @@ hb_font_set_ppem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->x_ppem == x_ppem && font->y_ppem == y_ppem)
+ return;
+
+ font->serial++;
+
font->x_ppem = x_ppem;
font->y_ppem = y_ppem;
}
@@ -2018,6 +2261,11 @@ hb_font_set_ptem (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ if (font->ptem == ptem)
+ return;
+
+ font->serial++;
+
font->ptem = ptem;
}
@@ -2044,12 +2292,16 @@ hb_font_get_ptem (hb_font_t *font)
* @slant: synthetic slant value.
*
* Sets the "synthetic slant" of a font. By default is zero.
- * Synthetic slant is the graphical skew that the renderer
- * applies to the font at rendering time.
+ * Synthetic slant is the graphical skew applied to the font
+ * at rendering time.
*
* HarfBuzz needs to know this value to adjust shaping results,
* metrics, and style values to match the slanted rendering.
*
+ * <note>Note: The glyph shape fetched via the
+ * hb_font_get_glyph_shape() is slanted to reflect this value
+ * as well.</note>
+ *
* <note>Note: The slant value is a ratio. For example, a
* 20% slant would be represented as a 0.2 value.</note>
*
@@ -2061,6 +2313,11 @@ hb_font_set_synthetic_slant (hb_font_t *font, float slant)
if (hb_object_is_immutable (font))
return;
+ if (font->slant == slant)
+ return;
+
+ font->serial++;
+
font->slant = slant;
font->mults_changed ();
}
@@ -2108,6 +2365,8 @@ hb_font_set_variations (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
if (!variations_length)
{
hb_font_set_var_coords_normalized (font, nullptr, 0);
@@ -2128,6 +2387,10 @@ hb_font_set_variations (hb_font_t *font,
return;
}
+ /* Initialize design coords to default from fvar. */
+ for (unsigned int i = 0; i < coords_length; i++)
+ design_coords[i] = axes[i].get_default ();
+
for (unsigned int i = 0; i < variations_length; i++)
{
const auto tag = variations[i].tag;
@@ -2167,6 +2430,8 @@ hb_font_set_var_coords_design (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2200,6 +2465,8 @@ hb_font_set_var_named_instance (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
unsigned int coords_length = hb_ot_var_named_instance_get_design_coords (font->face, instance_index, nullptr, nullptr);
float *coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
@@ -2236,6 +2503,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
if (hb_object_is_immutable (font))
return;
+ font->serial_coords = ++font->serial;
+
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
@@ -2441,12 +2710,14 @@ hb_font_funcs_set_glyph_func (hb_font_funcs_t *ffuncs,
return;
}
+ /* Since we pass it to two destroying functions. */
+ trampoline_reference (&trampoline->closure);
+
hb_font_funcs_set_nominal_glyph_func (ffuncs,
hb_font_get_nominal_glyph_trampoline,
trampoline,
trampoline_destroy);
- trampoline_reference (&trampoline->closure);
hb_font_funcs_set_variation_glyph_func (ffuncs,
hb_font_get_variation_glyph_trampoline,
trampoline,
diff --git a/thirdparty/harfbuzz/src/hb-font.h b/thirdparty/harfbuzz/src/hb-font.h
index a3bbb2e37b..e2c3df4a5a 100644
--- a/thirdparty/harfbuzz/src/hb-font.h
+++ b/thirdparty/harfbuzz/src/hb-font.h
@@ -86,8 +86,8 @@ hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
HB_EXTERN void *
-hb_font_funcs_get_user_data (hb_font_funcs_t *ffuncs,
- hb_user_data_key_t *key);
+hb_font_funcs_get_user_data (const hb_font_funcs_t *ffuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -198,7 +198,7 @@ typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
* This method should retrieve the nominal glyph ID for a specified Unicode code
* point. Glyph IDs must be returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -221,7 +221,7 @@ typedef hb_bool_t (*hb_font_get_nominal_glyph_func_t) (hb_font_t *font, void *fo
* followed by a specified Variation Selector code point. Glyph IDs must be
* returned in a #hb_codepoint_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_variation_glyph_func_t) (hb_font_t *font, void *font_data,
@@ -362,7 +362,7 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
* origin for a glyph. Each coordinate must be returned in an #hb_position_t
* output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *font_data,
@@ -434,7 +434,7 @@ typedef hb_font_get_glyph_kerning_func_t hb_font_get_glyph_h_kerning_func_t;
* This method should retrieve the extents for a specified glyph. Extents must be
* returned in an #hb_glyph_extents output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *font_data,
@@ -458,7 +458,7 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
* specified contour point in a glyph. Each coordinate must be returned as
* an #hb_position_t output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, void *font_data,
@@ -481,7 +481,7 @@ typedef hb_bool_t (*hb_font_get_glyph_contour_point_func_t) (hb_font_t *font, vo
* This method should retrieve the glyph name that corresponds to a
* glyph ID. The name should be returned in a string output parameter.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_data,
@@ -503,7 +503,7 @@ typedef hb_bool_t (*hb_font_get_glyph_name_func_t) (hb_font_t *font, void *font_
* This method should retrieve the glyph ID that corresponds to a glyph-name
* string.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *font_data,
@@ -511,6 +511,25 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
hb_codepoint_t *glyph,
void *user_data);
+/**
+ * hb_font_get_glyph_shape_func_t:
+ * @font: #hb_font_t to work upon
+ * @font_data: @font user data pointer
+ * @glyph: The glyph ID to query
+ * @draw_funcs: The draw functions to send the shape data to
+ * @draw_data: The data accompanying the draw functions
+ * @user_data: User data pointer passed by the caller
+ *
+ * A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
+ *
+ * Since: 4.0.0
+ *
+ **/
+typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data);
+
/* func setters */
@@ -770,6 +789,22 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
hb_font_get_glyph_from_name_func_t func,
void *user_data, hb_destroy_func_t destroy);
+/**
+ * hb_font_funcs_set_glyph_shape_func:
+ * @ffuncs: A font-function structure
+ * @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
+ * @user_data: Data to pass to @func
+ * @destroy: (nullable): The function to call when @user_data is not needed anymore
+ *
+ * Sets the implementation function for #hb_font_get_glyph_shape_func_t.
+ *
+ * Since: 4.0.0
+ **/
+HB_EXTERN void
+hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
+ hb_font_get_glyph_shape_func_t func,
+ void *user_data, hb_destroy_func_t destroy);
+
/* func dispatch */
HB_EXTERN hb_bool_t
@@ -850,6 +885,11 @@ hb_font_get_glyph_from_name (hb_font_t *font,
const char *name, int len, /* -1 means nul-terminated */
hb_codepoint_t *glyph);
+HB_EXTERN void
+hb_font_get_glyph_shape (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *dfuncs, void *draw_data);
+
/* high-level funcs, with fallback */
@@ -953,7 +993,7 @@ hb_font_set_user_data (hb_font_t *font,
HB_EXTERN void *
-hb_font_get_user_data (hb_font_t *font,
+hb_font_get_user_data (const hb_font_t *font,
hb_user_data_key_t *key);
HB_EXTERN void
@@ -962,6 +1002,12 @@ hb_font_make_immutable (hb_font_t *font);
HB_EXTERN hb_bool_t
hb_font_is_immutable (hb_font_t *font);
+HB_EXTERN unsigned int
+hb_font_get_serial (hb_font_t *font);
+
+HB_EXTERN void
+hb_font_changed (hb_font_t *font);
+
HB_EXTERN void
hb_font_set_parent (hb_font_t *font,
hb_font_t *parent);
@@ -1056,11 +1102,6 @@ HB_EXTERN void
hb_font_set_var_named_instance (hb_font_t *font,
unsigned instance_index);
-#ifdef HB_EXPERIMENTAL_API
-HB_EXTERN hb_bool_t
-hb_font_draw_glyph (hb_font_t *font, hb_codepoint_t glyph,
- const hb_draw_funcs_t *funcs, void *user_data);
-#endif
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-font.hh b/thirdparty/harfbuzz/src/hb-font.hh
index 0d73589e8c..bb402e23eb 100644
--- a/thirdparty/harfbuzz/src/hb-font.hh
+++ b/thirdparty/harfbuzz/src/hb-font.hh
@@ -57,6 +57,7 @@
HB_FONT_FUNC_IMPLEMENT (glyph_contour_point) \
HB_FONT_FUNC_IMPLEMENT (glyph_name) \
HB_FONT_FUNC_IMPLEMENT (glyph_from_name) \
+ HB_FONT_FUNC_IMPLEMENT (glyph_shape) \
/* ^--- Add new callbacks here */
struct hb_font_funcs_t
@@ -67,13 +68,13 @@ struct hb_font_funcs_t
#define HB_FONT_FUNC_IMPLEMENT(name) void *name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
- } user_data;
+ } *user_data;
struct {
#define HB_FONT_FUNC_IMPLEMENT(name) hb_destroy_func_t name;
HB_FONT_FUNCS_IMPLEMENT_CALLBACKS
#undef HB_FONT_FUNC_IMPLEMENT
- } destroy;
+ } *destroy;
/* Don't access these directly. Call font->get_*() instead. */
union get_t {
@@ -103,6 +104,8 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
+ unsigned int serial;
+ unsigned int serial_coords;
hb_font_t *parent;
hb_face_t *face;
@@ -111,6 +114,8 @@ struct hb_font_t
int32_t y_scale;
float slant;
float slant_xy;
+ float x_multf;
+ float y_multf;
int64_t x_mult;
int64_t y_mult;
@@ -136,10 +141,12 @@ struct hb_font_t
{ return HB_DIRECTION_IS_VERTICAL(direction) ? y_mult : x_mult; }
hb_position_t em_scale_x (int16_t v) { return em_mult (v, x_mult); }
hb_position_t em_scale_y (int16_t v) { return em_mult (v, y_mult); }
- hb_position_t em_scalef_x (float v) { return em_scalef (v, x_scale); }
- hb_position_t em_scalef_y (float v) { return em_scalef (v, y_scale); }
- float em_fscale_x (int16_t v) { return em_fscale (v, x_scale); }
- float em_fscale_y (int16_t v) { return em_fscale (v, y_scale); }
+ hb_position_t em_scalef_x (float v) { return em_multf (v, x_multf); }
+ hb_position_t em_scalef_y (float v) { return em_multf (v, y_multf); }
+ float em_fscale_x (int16_t v) { return em_fmult (v, x_multf); }
+ float em_fscale_y (int16_t v) { return em_fmult (v, y_multf); }
+ float em_fscalef_x (float v) { return em_fmultf (v, x_multf); }
+ float em_fscalef_y (float v) { return em_fmultf (v, y_multf); }
hb_position_t em_scale_dir (int16_t v, hb_direction_t direction)
{ return em_mult (v, dir_mult (direction)); }
@@ -202,14 +209,14 @@ struct hb_font_t
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_h_extents (this, user_data,
extents,
- klass->user_data.font_h_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_h_extents);
}
hb_bool_t get_font_v_extents (hb_font_extents_t *extents)
{
memset (extents, 0, sizeof (*extents));
return klass->get.f.font_v_extents (this, user_data,
extents,
- klass->user_data.font_v_extents);
+ !klass->user_data ? nullptr : klass->user_data->font_v_extents);
}
bool has_glyph (hb_codepoint_t unicode)
@@ -225,7 +232,7 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.nominal_glyph (this, user_data,
unicode, glyph,
- klass->user_data.nominal_glyph);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyph);
}
unsigned int get_nominal_glyphs (unsigned int count,
const hb_codepoint_t *first_unicode,
@@ -237,7 +244,7 @@ struct hb_font_t
count,
first_unicode, unicode_stride,
first_glyph, glyph_stride,
- klass->user_data.nominal_glyphs);
+ !klass->user_data ? nullptr : klass->user_data->nominal_glyphs);
}
hb_bool_t get_variation_glyph (hb_codepoint_t unicode, hb_codepoint_t variation_selector,
@@ -247,21 +254,21 @@ struct hb_font_t
*glyph = not_found;
return klass->get.f.variation_glyph (this, user_data,
unicode, variation_selector, glyph,
- klass->user_data.variation_glyph);
+ !klass->user_data ? nullptr : klass->user_data->variation_glyph);
}
hb_position_t get_glyph_h_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_h_advance (this, user_data,
glyph,
- klass->user_data.glyph_h_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advance);
}
hb_position_t get_glyph_v_advance (hb_codepoint_t glyph)
{
return klass->get.f.glyph_v_advance (this, user_data,
glyph,
- klass->user_data.glyph_v_advance);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advance);
}
void get_glyph_h_advances (unsigned int count,
@@ -274,7 +281,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_h_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_advances);
}
void get_glyph_v_advances (unsigned int count,
@@ -287,7 +294,7 @@ struct hb_font_t
count,
first_glyph, glyph_stride,
first_advance, advance_stride,
- klass->user_data.glyph_v_advances);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_advances);
}
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
@@ -296,7 +303,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_h_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_h_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
}
hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
@@ -305,7 +312,7 @@ struct hb_font_t
*x = *y = 0;
return klass->get.f.glyph_v_origin (this, user_data,
glyph, x, y,
- klass->user_data.glyph_v_origin);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
}
hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
@@ -316,7 +323,7 @@ struct hb_font_t
#else
return klass->get.f.glyph_h_kerning (this, user_data,
left_glyph, right_glyph,
- klass->user_data.glyph_h_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_h_kerning);
#endif
}
@@ -328,7 +335,7 @@ struct hb_font_t
#else
return klass->get.f.glyph_v_kerning (this, user_data,
top_glyph, bottom_glyph,
- klass->user_data.glyph_v_kerning);
+ !klass->user_data ? nullptr : klass->user_data->glyph_v_kerning);
#endif
}
@@ -339,7 +346,7 @@ struct hb_font_t
return klass->get.f.glyph_extents (this, user_data,
glyph,
extents,
- klass->user_data.glyph_extents);
+ !klass->user_data ? nullptr : klass->user_data->glyph_extents);
}
hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index,
@@ -349,7 +356,7 @@ struct hb_font_t
return klass->get.f.glyph_contour_point (this, user_data,
glyph, point_index,
x, y,
- klass->user_data.glyph_contour_point);
+ !klass->user_data ? nullptr : klass->user_data->glyph_contour_point);
}
hb_bool_t get_glyph_name (hb_codepoint_t glyph,
@@ -359,7 +366,7 @@ struct hb_font_t
return klass->get.f.glyph_name (this, user_data,
glyph,
name, size,
- klass->user_data.glyph_name);
+ !klass->user_data ? nullptr : klass->user_data->glyph_name);
}
hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */
@@ -370,7 +377,16 @@ struct hb_font_t
return klass->get.f.glyph_from_name (this, user_data,
name, len,
glyph,
- klass->user_data.glyph_from_name);
+ !klass->user_data ? nullptr : klass->user_data->glyph_from_name);
+ }
+
+ void get_glyph_shape (hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data)
+ {
+ klass->get.f.glyph_shape (this, user_data,
+ glyph,
+ draw_funcs, draw_data,
+ !klass->user_data ? nullptr : klass->user_data->glyph_shape);
}
@@ -432,7 +448,6 @@ struct hb_font_t
{
*x = get_glyph_h_advance (glyph) / 2;
- /* TODO cache this somehow?! */
hb_font_extents_t extents;
get_h_extents_with_fallback (&extents);
*y = extents.ascender;
@@ -616,18 +631,26 @@ struct hb_font_t
void mults_changed ()
{
- signed upem = face->get_upem ();
- x_mult = ((int64_t) x_scale << 16) / upem;
- y_mult = ((int64_t) y_scale << 16) / upem;
+ float upem = face->get_upem ();
+ x_multf = x_scale / upem;
+ y_multf = y_scale / upem;
+ bool x_neg = x_scale < 0;
+ x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
+ bool y_neg = y_scale < 0;
+ y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
+
+ data.fini ();
}
hb_position_t em_mult (int16_t v, int64_t mult)
{ return (hb_position_t) ((v * mult + 32768) >> 16); }
- hb_position_t em_scalef (float v, int scale)
- { return (hb_position_t) roundf (v * scale / face->get_upem ()); }
- float em_fscale (int16_t v, int scale)
- { return (float) v * scale / face->get_upem (); }
+ hb_position_t em_multf (float v, float mult)
+ { return (hb_position_t) roundf (em_fmultf (v, mult)); }
+ float em_fmultf (float v, float mult)
+ { return v * mult; }
+ float em_fmult (int16_t v, float mult)
+ { return (float) v * mult; }
};
DECLARE_NULL_INSTANCE (hb_font_t);
diff --git a/thirdparty/harfbuzz/src/hb-ft.cc b/thirdparty/harfbuzz/src/hb-ft.cc
index 67691e3ff3..ef073475cb 100644
--- a/thirdparty/harfbuzz/src/hb-ft.cc
+++ b/thirdparty/harfbuzz/src/hb-ft.cc
@@ -33,12 +33,16 @@
#include "hb-ft.h"
+#include "hb-draw.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-cache.hh"
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-shaper-arabic-pua.hh"
#include FT_ADVANCES_H
#include FT_MULTIPLE_MASTERS_H
+#include FT_OUTLINE_H
#include FT_TRUETYPE_TABLES_H
@@ -78,13 +82,13 @@
struct hb_ft_font_t
{
- mutable hb_mutex_t lock;
- FT_Face ft_face;
int load_flags;
bool symbol; /* Whether selected cmap is symbol cmap. */
bool unref; /* Whether to destroy ft_face when done. */
- mutable int cached_x_scale;
+ mutable hb_mutex_t lock;
+ FT_Face ft_face;
+ mutable unsigned cached_serial;
mutable hb_advance_cache_t advance_cache;
};
@@ -101,7 +105,7 @@ _hb_ft_font_create (FT_Face ft_face, bool symbol, bool unref)
ft_font->load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
- ft_font->cached_x_scale = 0;
+ ft_font->cached_serial = (unsigned) -1;
ft_font->advance_cache.init ();
return ft_font;
@@ -128,6 +132,82 @@ _hb_ft_font_destroy (void *data)
hb_free (ft_font);
}
+
+/* hb_font changed, update FT_Face. */
+static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
+{
+ float x_mult = 1.f, y_mult = 1.f;
+
+ if (font->x_scale < 0) x_mult = -x_mult;
+ if (font->y_scale < 0) y_mult = -y_mult;
+
+ if (FT_Set_Char_Size (ft_face,
+ abs (font->x_scale), abs (font->y_scale),
+ 0, 0
+#if 0
+ font->x_ppem * 72 * 64 / font->x_scale,
+ font->y_ppem * 72 * 64 / font->y_scale
+#endif
+ ) && ft_face->num_fixed_sizes)
+ {
+#ifdef HAVE_FT_GET_TRANSFORM
+ /* Bitmap font, eg. bitmap color emoji. */
+ /* TODO Pick largest size? */
+ int x_scale = ft_face->available_sizes[0].x_ppem;
+ int y_scale = ft_face->available_sizes[0].y_ppem;
+ FT_Set_Char_Size (ft_face,
+ x_scale, y_scale,
+ 0, 0);
+
+ /* This contains the sign that was previously in x_mult/y_mult. */
+ x_mult = (float) font->x_scale / x_scale;
+ y_mult = (float) font->y_scale / y_scale;
+#endif
+ }
+ else
+ { /* Shrug */ }
+
+
+ if (x_mult != 1.f || y_mult != 1.f)
+ {
+ FT_Matrix matrix = { (int) roundf (x_mult * (1<<16)), 0,
+ 0, (int) roundf (y_mult * (1<<16))};
+ FT_Set_Transform (ft_face, &matrix, nullptr);
+ }
+
+#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
+ unsigned int num_coords;
+ const float *coords = hb_font_get_var_coords_design (font, &num_coords);
+ if (num_coords)
+ {
+ FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
+ if (ft_coords)
+ {
+ for (unsigned int i = 0; i < num_coords; i++)
+ ft_coords[i] = coords[i] * 65536.f;
+ FT_Set_Var_Design_Coordinates (ft_face, num_coords, ft_coords);
+ hb_free (ft_coords);
+ }
+ }
+#endif
+}
+
+/* Check if hb_font changed, update FT_Face. */
+static inline bool
+_hb_ft_hb_font_check_changed (hb_font_t *font,
+ const hb_ft_font_t *ft_font)
+{
+ if (font->serial != ft_font->cached_serial)
+ {
+ _hb_ft_hb_font_changed (font, ft_font->ft_face);
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+ return true;
+ }
+ return false;
+}
+
+
/**
* hb_ft_font_set_load_flags:
* @font: #hb_font_t to work upon
@@ -179,13 +259,13 @@ hb_ft_font_get_load_flags (hb_font_t *font)
}
/**
- * hb_ft_font_get_face:
+ * hb_ft_font_get_face: (skip)
* @font: #hb_font_t to work upon
*
* Fetches the FT_Face associated with the specified #hb_font_t
* font object.
*
- * Return value: (nullable): the FT_Face found or %NULL
+ * Return value: (nullable): the FT_Face found or `NULL`
*
* Since: 0.9.2
**/
@@ -201,13 +281,13 @@ hb_ft_font_get_face (hb_font_t *font)
}
/**
- * hb_ft_font_lock_face:
+ * hb_ft_font_lock_face: (skip)
* @font: #hb_font_t to work upon
*
* Gets the FT_Face associated with @font, This face will be kept around until
* you call hb_ft_font_unlock_face().
*
- * Return value: (nullable): the FT_Face associated with @font or %NULL
+ * Return value: (nullable) (transfer none): the FT_Face associated with @font or `NULL`
* Since: 2.6.5
**/
FT_Face
@@ -224,7 +304,7 @@ hb_ft_font_lock_face (hb_font_t *font)
}
/**
- * hb_ft_font_unlock_face:
+ * hb_ft_font_unlock_face: (skip)
* @font: #hb_font_t to work upon
*
* Releases an FT_Face previously obtained with hb_ft_font_lock_face().
@@ -244,7 +324,7 @@ hb_ft_font_unlock_face (hb_font_t *font)
static hb_bool_t
-hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
+hb_ft_get_nominal_glyph (hb_font_t *font,
void *font_data,
hb_codepoint_t unicode,
hb_codepoint_t *glyph,
@@ -256,14 +336,29 @@ hb_ft_get_nominal_glyph (hb_font_t *font HB_UNUSED,
if (unlikely (!g))
{
- if (unlikely (ft_font->symbol) && unicode <= 0x00FFu)
+ if (unlikely (ft_font->symbol))
{
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ switch ((unsigned) font->face->table.OS2->get_font_page ()) {
+ case OT::OS2::font_page_t::FONT_PAGE_NONE:
+ if (unicode <= 0x00FFu)
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ g = FT_Get_Char_Index (ft_font->ft_face, 0xF000u + unicode);
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OT::OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_simp_map (unicode));
+ break;
+ case OT::OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ g = FT_Get_Char_Index (ft_font->ft_face, _hb_arabic_pua_trad_map (unicode));
+ break;
+#endif
+ default:
+ break;
+ }
if (!g)
return false;
}
@@ -333,13 +428,13 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
int load_flags = ft_font->load_flags;
- int mult = font->x_scale < 0 ? -1 : +1;
-
- if (font->x_scale != ft_font->cached_x_scale)
- {
- ft_font->advance_cache.clear ();
- ft_font->cached_x_scale = font->x_scale;
- }
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float mult = matrix.xx / 65536.f;
+#else
+ float mult = font->x_scale < 0 ? -1 : +1;
+#endif
for (unsigned int i = 0; i < count; i++)
{
@@ -355,7 +450,7 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
ft_font->advance_cache.set (glyph, v);
}
- *first_advance = (v * mult + (1<<9)) >> 10;
+ *first_advance = (int) (v * mult + (1<<9)) >> 10;
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
}
@@ -371,15 +466,22 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Fixed v;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_font->ft_face, &matrix, nullptr);
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Get_Advance (ft_font->ft_face, glyph, ft_font->load_flags | FT_LOAD_VERTICAL_LAYOUT, &v)))
return 0;
- if (font->y_scale < 0)
- v = -v;
+ v = (int) (y_mult * v);
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
* have a Y growing upward. Hence the extra negation. */
+
return (-v + (1<<9)) >> 10;
}
#endif
@@ -396,6 +498,15 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float x_mult = matrix.xx / 65536.f;
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float x_mult = font->x_scale < 0 ? -1 : +1;
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
@@ -405,10 +516,8 @@ hb_ft_get_glyph_v_origin (hb_font_t *font,
*x = ft_face->glyph->metrics.horiBearingX - ft_face->glyph->metrics.vertBearingX;
*y = ft_face->glyph->metrics.horiBearingY - (-ft_face->glyph->metrics.vertBearingY);
- if (font->x_scale < 0)
- *x = -*x;
- if (font->y_scale < 0)
- *y = -*y;
+ *x = (hb_position_t) (x_mult * *x);
+ *y = (hb_position_t) (y_mult * *y);
return true;
}
@@ -423,6 +532,7 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font,
void *user_data HB_UNUSED)
{
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
FT_Vector kerningv;
FT_Kerning_Mode mode = font->x_ppem ? FT_KERNING_DEFAULT : FT_KERNING_UNFITTED;
@@ -443,24 +553,24 @@ hb_ft_get_glyph_extents (hb_font_t *font,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float x_mult = matrix.xx / 65536.f;
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float x_mult = font->x_scale < 0 ? -1 : +1;
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
if (unlikely (FT_Load_Glyph (ft_face, glyph, ft_font->load_flags)))
return false;
- extents->x_bearing = ft_face->glyph->metrics.horiBearingX;
- extents->y_bearing = ft_face->glyph->metrics.horiBearingY;
- extents->width = ft_face->glyph->metrics.width;
- extents->height = -ft_face->glyph->metrics.height;
- if (font->x_scale < 0)
- {
- extents->x_bearing = -extents->x_bearing;
- extents->width = -extents->width;
- }
- if (font->y_scale < 0)
- {
- extents->y_bearing = -extents->y_bearing;
- extents->height = -extents->height;
- }
+ extents->x_bearing = (hb_position_t) (x_mult * ft_face->glyph->metrics.horiBearingX);
+ extents->y_bearing = (hb_position_t) (y_mult * ft_face->glyph->metrics.horiBearingY);
+ extents->width = (hb_position_t) (x_mult * ft_face->glyph->metrics.width);
+ extents->height = (hb_position_t) (y_mult * -ft_face->glyph->metrics.height);
+
return true;
}
@@ -553,18 +663,111 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
hb_lock_t lock (ft_font->lock);
FT_Face ft_face = ft_font->ft_face;
- metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
- metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
- metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
- if (font->y_scale < 0)
+#ifdef HAVE_FT_GET_TRANSFORM
+ FT_Matrix matrix;
+ FT_Get_Transform (ft_face, &matrix, nullptr);
+ float y_mult = matrix.yy / 65536.f;
+#else
+ float y_mult = font->y_scale < 0 ? -1 : +1;
+#endif
+
+ if (ft_face->units_per_EM != 0)
+ {
+ metrics->ascender = FT_MulFix(ft_face->ascender, ft_face->size->metrics.y_scale);
+ metrics->descender = FT_MulFix(ft_face->descender, ft_face->size->metrics.y_scale);
+ metrics->line_gap = FT_MulFix( ft_face->height, ft_face->size->metrics.y_scale ) - (metrics->ascender - metrics->descender);
+ }
+ else
{
- metrics->ascender = -metrics->ascender;
- metrics->descender = -metrics->descender;
- metrics->line_gap = -metrics->line_gap;
+ /* Bitmap-only font, eg. color bitmap font. */
+ metrics->ascender = ft_face->size->metrics.ascender;
+ metrics->descender = ft_face->size->metrics.descender;
+ metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
}
+
+ metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
+ metrics->descender = (hb_position_t) (y_mult * metrics->descender);
+ metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
+
return true;
}
+#ifndef HB_NO_DRAW
+
+static int
+_hb_ft_move_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->move_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_line_to (const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->line_to (to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_conic_to (const FT_Vector *control,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->quadratic_to (control->x, control->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static int
+_hb_ft_cubic_to (const FT_Vector *control1,
+ const FT_Vector *control2,
+ const FT_Vector *to,
+ hb_draw_session_t *drawing)
+{
+ drawing->cubic_to (control1->x, control1->y,
+ control2->x, control2->y,
+ to->x, to->y);
+ return FT_Err_Ok;
+}
+
+static void
+hb_ft_get_glyph_shape (hb_font_t *font HB_UNUSED,
+ void *font_data,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data HB_UNUSED)
+{
+ const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
+ hb_lock_t lock (ft_font->lock);
+ FT_Face ft_face = ft_font->ft_face;
+
+ if (unlikely (FT_Load_Glyph (ft_face, glyph,
+ FT_LOAD_NO_BITMAP | ft_font->load_flags)))
+ return;
+
+ if (ft_face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
+ return;
+
+ const FT_Outline_Funcs outline_funcs = {
+ (FT_Outline_MoveToFunc) _hb_ft_move_to,
+ (FT_Outline_LineToFunc) _hb_ft_line_to,
+ (FT_Outline_ConicToFunc) _hb_ft_conic_to,
+ (FT_Outline_CubicToFunc) _hb_ft_cubic_to,
+ 0, /* shift */
+ 0, /* delta */
+ };
+
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+
+ FT_Outline_Decompose (&ft_face->glyph->outline,
+ &outline_funcs,
+ &draw_session);
+}
+#endif
+
+
static inline void free_static_ft_funcs ();
static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft_font_funcs_lazy_loader_t>
@@ -596,6 +799,10 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft
hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, nullptr, nullptr);
hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, nullptr, nullptr);
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ft_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_make_immutable (funcs);
hb_atexit (free_static_ft_funcs);
@@ -878,6 +1085,34 @@ hb_ft_font_changed (hb_font_t *font)
#endif
}
#endif
+
+ ft_font->advance_cache.clear ();
+ ft_font->cached_serial = font->serial;
+}
+
+/**
+ * hb_ft_hb_font_changed:
+ * @font: #hb_font_t to work upon
+ *
+ * Refreshes the state of the underlying FT_Face of @font when the hb_font_t
+ * @font has changed.
+ * This function should be called after changing the size or
+ * variation-axis settings on the @font.
+ * This call is fast if nothing has changed on @font.
+ *
+ * Return value: true if changed, false otherwise
+ *
+ * Since: 4.4.0
+ **/
+hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font)
+{
+ if (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy)
+ return false;
+
+ hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
+
+ return _hb_ft_hb_font_check_changed (font, ft_font);
}
/**
@@ -998,35 +1233,7 @@ hb_ft_font_set_funcs (hb_font_t *font)
if (FT_Select_Charmap (ft_face, FT_ENCODING_MS_SYMBOL))
FT_Select_Charmap (ft_face, FT_ENCODING_UNICODE);
- FT_Set_Char_Size (ft_face,
- abs (font->x_scale), abs (font->y_scale),
- 0, 0);
-#if 0
- font->x_ppem * 72 * 64 / font->x_scale,
- font->y_ppem * 72 * 64 / font->y_scale);
-#endif
- if (font->x_scale < 0 || font->y_scale < 0)
- {
- FT_Matrix matrix = { font->x_scale < 0 ? -1 : +1, 0,
- 0, font->y_scale < 0 ? -1 : +1};
- FT_Set_Transform (ft_face, &matrix, nullptr);
- }
-
-#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
- unsigned int num_coords;
- const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
- if (num_coords)
- {
- FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
- if (ft_coords)
- {
- for (unsigned int i = 0; i < num_coords; i++)
- ft_coords[i] = coords[i] * 4;
- FT_Set_Var_Blend_Coordinates (ft_face, num_coords, ft_coords);
- hb_free (ft_coords);
- }
- }
-#endif
+ _hb_ft_hb_font_changed (font, ft_face);
ft_face->generic.data = blob;
ft_face->generic.finalizer = (FT_Generic_Finalizer) _release_blob;
diff --git a/thirdparty/harfbuzz/src/hb-ft.h b/thirdparty/harfbuzz/src/hb-ft.h
index bf07115ab9..6a8a7abe8c 100644
--- a/thirdparty/harfbuzz/src/hb-ft.h
+++ b/thirdparty/harfbuzz/src/hb-ft.h
@@ -122,10 +122,17 @@ hb_ft_font_set_load_flags (hb_font_t *font, int load_flags);
HB_EXTERN int
hb_ft_font_get_load_flags (hb_font_t *font);
-/* Call when size or variations settings on underlying FT_Face change. */
+/* Call when size or variations settings on underlying FT_Face changed,
+ * and you want to update the hb_font_t from it. */
HB_EXTERN void
hb_ft_font_changed (hb_font_t *font);
+/* Call when size or variations settings on underlying hb_font_t may have
+ * changed, and you want to update the FT_Face from it. This call is fast
+ * if nothing changed on hb_font_t. Returns true if changed. */
+HB_EXTERN hb_bool_t
+hb_ft_hb_font_changed (hb_font_t *font);
+
/* Makes an hb_font_t use FreeType internally to implement font functions.
* Note: this internally creates an FT_Face. Use it when you create your
* hb_face_t using hb_face_create(). */
diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.cc b/thirdparty/harfbuzz/src/hb-gobject-structs.cc
index 540b11f911..ef13f1e966 100644
--- a/thirdparty/harfbuzz/src/hb-gobject-structs.cc
+++ b/thirdparty/harfbuzz/src/hb-gobject-structs.cc
@@ -90,6 +90,7 @@ hb_gobject_##name##_get_type () \
HB_DEFINE_OBJECT_TYPE (buffer)
HB_DEFINE_OBJECT_TYPE (blob)
+HB_DEFINE_OBJECT_TYPE (draw_funcs)
HB_DEFINE_OBJECT_TYPE (face)
HB_DEFINE_OBJECT_TYPE (font)
HB_DEFINE_OBJECT_TYPE (font_funcs)
diff --git a/thirdparty/harfbuzz/src/hb-gobject-structs.h b/thirdparty/harfbuzz/src/hb-gobject-structs.h
index 63467f80df..3914a2431a 100644
--- a/thirdparty/harfbuzz/src/hb-gobject-structs.h
+++ b/thirdparty/harfbuzz/src/hb-gobject-structs.h
@@ -49,6 +49,10 @@ hb_gobject_buffer_get_type (void);
#define HB_GOBJECT_TYPE_BUFFER (hb_gobject_buffer_get_type ())
HB_EXTERN GType
+hb_gobject_draw_funcs_get_type (void);
+#define HB_GOBJECT_TYPE_DRAW_FUNCS (hb_gobject_draw_funcs_get_type ())
+
+HB_EXTERN GType
hb_gobject_face_get_type (void);
#define HB_GOBJECT_TYPE_FACE (hb_gobject_face_get_type ())
diff --git a/thirdparty/harfbuzz/src/hb-graphite2.cc b/thirdparty/harfbuzz/src/hb-graphite2.cc
index 63dc18b466..4d0e687c75 100644
--- a/thirdparty/harfbuzz/src/hb-graphite2.cc
+++ b/thirdparty/harfbuzz/src/hb-graphite2.cc
@@ -158,7 +158,7 @@ _hb_graphite2_shaper_face_data_destroy (hb_graphite2_face_data_t *data)
}
/**
- * hb_graphite2_face_get_gr_face:
+ * hb_graphite2_face_get_gr_face: (skip)
* @face: @hb_face_t to query
*
* Fetches the Graphite2 gr_face corresponding to the specified
@@ -195,10 +195,10 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
#ifndef HB_DISABLE_DEPRECATED
/**
- * hb_graphite2_font_get_gr_font:
+ * hb_graphite2_font_get_gr_font: (skip)
* @font: An #hb_font_t
*
- * Always returns %NULL. Use hb_graphite2_face_get_gr_face() instead.
+ * Always returns `NULL`. Use hb_graphite2_face_get_gr_face() instead.
*
* Return value: (nullable): Graphite2 font associated with @font.
*
@@ -223,7 +223,7 @@ struct hb_graphite2_cluster_t {
unsigned int base_glyph;
unsigned int num_glyphs;
unsigned int cluster;
- unsigned int advance;
+ int advance;
};
hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-iter.hh b/thirdparty/harfbuzz/src/hb-iter.hh
index 43a3098f65..1a3ab43de0 100644
--- a/thirdparty/harfbuzz/src/hb-iter.hh
+++ b/thirdparty/harfbuzz/src/hb-iter.hh
@@ -43,17 +43,12 @@
* is writable, then the iterator returns lvalues, otherwise it
* returns rvalues.
*
- * TODO Document more.
- *
- * If iterator implementation implements operator!=, then can be
+ * If iterator implementation implements operator!=, then it can be
* used in range-based for loop. That already happens if the iterator
* is random-access. Otherwise, the range-based for loop incurs
* one traversal to find end(), which can be avoided if written
* as a while-style for loop, or if iterator implements a faster
- * __end__() method.
- * TODO When opting in for C++17, address this by changing return
- * type of .end()?
- */
+ * __end__() method. */
/*
* Base classes for iterators.
@@ -75,10 +70,6 @@ struct hb_iter_t
iter_t* thiz () { return static_cast< iter_t *> (this); }
public:
- /* TODO:
- * Port operators below to use hb_enable_if to sniff which method implements
- * an operator and use it, and remove hb_iter_fallback_mixin_t completely. */
-
/* Operators. */
iter_t iter () const { return *thiz(); }
iter_t operator + () const { return *thiz(); }
@@ -87,8 +78,7 @@ struct hb_iter_t
explicit operator bool () const { return thiz()->__more__ (); }
unsigned len () const { return thiz()->__len__ (); }
/* The following can only be enabled if item_t is reference type. Otherwise
- * it will be returning pointer to temporary rvalue.
- * TODO Use a wrapper return type to fix for non-reference type. */
+ * it will be returning pointer to temporary rvalue. */
template <typename T = item_t,
hb_enable_if (std::is_reference<T>::value)>
hb_remove_reference<item_t>* operator -> () const { return std::addressof (**thiz()); }
@@ -263,6 +253,8 @@ struct hb_is_iterator_of
};
#define hb_is_iterator_of(Iter, Item) hb_is_iterator_of<Iter, Item>::value
#define hb_is_iterator(Iter) hb_is_iterator_of (Iter, typename Iter::item_t)
+#define hb_is_sorted_iterator_of(Iter, Item) (hb_is_iterator_of<Iter, Item>::value && Iter::is_sorted_iterator)
+#define hb_is_sorted_iterator(Iter) hb_is_sorted_iterator_of (Iter, typename Iter::item_t)
/* hb_is_iterable() */
diff --git a/thirdparty/harfbuzz/src/hb-machinery.hh b/thirdparty/harfbuzz/src/hb-machinery.hh
index 5046ac1933..ff2a99f5ed 100644
--- a/thirdparty/harfbuzz/src/hb-machinery.hh
+++ b/thirdparty/harfbuzz/src/hb-machinery.hh
@@ -176,7 +176,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
void init0 () {} /* Init, when memory is already set to 0. No-op for us. */
void init () { instance.set_relaxed (nullptr); }
- void fini () { do_destroy (instance.get ()); }
+ void fini () { do_destroy (instance.get ()); init (); }
void free_instance ()
{
@@ -194,7 +194,8 @@ struct hb_lazy_loader_t : hb_data_wrapper_t<Data, WheresData>
}
const Returned * operator -> () const { return get (); }
- const Returned & operator * () const { return *get (); }
+ template <typename U = Returned, hb_enable_if (!hb_is_same (U, void))>
+ const U & operator * () const { return *get (); }
explicit operator bool () const
{ return get_stored () != Funcs::get_null (); }
template <typename C> operator const C * () const { return get (); }
@@ -272,14 +273,19 @@ struct hb_face_lazy_loader_t : hb_lazy_loader_t<T,
hb_face_lazy_loader_t<T, WheresFace>,
hb_face_t, WheresFace> {};
-template <typename T, unsigned int WheresFace>
+template <typename T, unsigned int WheresFace, bool core=false>
struct hb_table_lazy_loader_t : hb_lazy_loader_t<T,
- hb_table_lazy_loader_t<T, WheresFace>,
+ hb_table_lazy_loader_t<T, WheresFace, core>,
hb_face_t, WheresFace,
hb_blob_t>
{
static hb_blob_t *create (hb_face_t *face)
- { return hb_sanitize_context_t ().reference_table<T> (face); }
+ {
+ auto c = hb_sanitize_context_t ();
+ if (core)
+ c.set_num_glyphs (0); // So we don't recurse ad infinitum...
+ return c.reference_table<T> (face);
+ }
static void destroy (hb_blob_t *p) { hb_blob_destroy (p); }
static const hb_blob_t *get_null ()
diff --git a/thirdparty/harfbuzz/src/hb-map.cc b/thirdparty/harfbuzz/src/hb-map.cc
index 9f1ac42846..5c5f5de59e 100644
--- a/thirdparty/harfbuzz/src/hb-map.cc
+++ b/thirdparty/harfbuzz/src/hb-map.cc
@@ -40,7 +40,7 @@
/**
- * hb_map_create: (Xconstructor)
+ * hb_map_create:
*
* Creates a new, initially empty map.
*
@@ -56,8 +56,6 @@ hb_map_create ()
if (!(map = hb_object_create<hb_map_t> ()))
return hb_map_get_empty ();
- map->init_shallow ();
-
return map;
}
@@ -107,8 +105,6 @@ hb_map_destroy (hb_map_t *map)
{
if (!hb_object_destroy (map)) return;
- map->fini_shallow ();
-
hb_free (map);
}
@@ -122,7 +118,7 @@ hb_map_destroy (hb_map_t *map)
*
* Attaches a user-data key/data pair to the specified map.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 1.7.7
**/
@@ -149,7 +145,7 @@ hb_map_set_user_data (hb_map_t *map,
* Since: 1.7.7
**/
void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (map, key);
@@ -162,7 +158,7 @@ hb_map_get_user_data (hb_map_t *map,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 1.7.7
**/
@@ -172,6 +168,25 @@ hb_map_allocation_successful (const hb_map_t *map)
return map->successful;
}
+/**
+ * hb_map_copy:
+ * @map: A map
+ *
+ * Allocate a copy of @map.
+ *
+ * Return value: Newly-allocated map.
+ *
+ * Since: 4.4.0
+ **/
+hb_map_t *
+hb_map_copy (const hb_map_t *map)
+{
+ hb_map_t *copy = hb_map_create ();
+ if (unlikely (!copy)) return nullptr;
+ copy->resize (map->population);
+ hb_copy (*map, *copy);
+ return copy;
+}
/**
* hb_map_set:
@@ -232,7 +247,7 @@ hb_map_del (hb_map_t *map,
*
* Tests whether @key is an element of @map.
*
- * Return value: %true if @key is found in @map, %false otherwise
+ * Return value: `true` if @key is found in @map, `false` otherwise
*
* Since: 1.7.7
**/
@@ -264,7 +279,7 @@ hb_map_clear (hb_map_t *map)
*
* Tests whether @map is empty (contains no elements).
*
- * Return value: %true if @map is empty
+ * Return value: `true` if @map is empty
*
* Since: 1.7.7
**/
@@ -289,3 +304,40 @@ hb_map_get_population (const hb_map_t *map)
{
return map->get_population ();
}
+
+/**
+ * hb_map_is_equal:
+ * @map: A map
+ * @other: Another map
+ *
+ * Tests whether @map and @other are equal (contain the same
+ * elements).
+ *
+ * Return value: `true` if the two maps are equal, `false` otherwise.
+ *
+ * Since: 4.3.0
+ **/
+hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other)
+{
+ return map->is_equal (*other);
+}
+
+/**
+ * hb_map_hash:
+ * @map: A map
+ *
+ * Creates a hash representing @map.
+ *
+ * Return value:
+ * A hash of @map.
+ *
+ * Since: 4.4.0
+ **/
+HB_EXTERN unsigned int
+hb_map_hash (const hb_map_t *map)
+{
+ return map->hash ();
+}
+
diff --git a/thirdparty/harfbuzz/src/hb-map.h b/thirdparty/harfbuzz/src/hb-map.h
index 6a45a7bdd5..3a067c5c73 100644
--- a/thirdparty/harfbuzz/src/hb-map.h
+++ b/thirdparty/harfbuzz/src/hb-map.h
@@ -74,7 +74,7 @@ hb_map_set_user_data (hb_map_t *map,
hb_bool_t replace);
HB_EXTERN void *
-hb_map_get_user_data (hb_map_t *map,
+hb_map_get_user_data (const hb_map_t *map,
hb_user_data_key_t *key);
@@ -82,6 +82,9 @@ hb_map_get_user_data (hb_map_t *map,
HB_EXTERN hb_bool_t
hb_map_allocation_successful (const hb_map_t *map);
+HB_EXTERN hb_map_t *
+hb_map_copy (const hb_map_t *map);
+
HB_EXTERN void
hb_map_clear (hb_map_t *map);
@@ -91,6 +94,13 @@ hb_map_is_empty (const hb_map_t *map);
HB_EXTERN unsigned int
hb_map_get_population (const hb_map_t *map);
+HB_EXTERN hb_bool_t
+hb_map_is_equal (const hb_map_t *map,
+ const hb_map_t *other);
+
+HB_EXTERN unsigned int
+hb_map_hash (const hb_map_t *map);
+
HB_EXTERN void
hb_map_set (hb_map_t *map,
hb_codepoint_t key,
diff --git a/thirdparty/harfbuzz/src/hb-map.hh b/thirdparty/harfbuzz/src/hb-map.hh
index 9341637eac..8302e3f8c7 100644
--- a/thirdparty/harfbuzz/src/hb-map.hh
+++ b/thirdparty/harfbuzz/src/hb-map.hh
@@ -34,19 +34,18 @@
* hb_hashmap_t
*/
+extern HB_INTERNAL const hb_codepoint_t minus_1;
+
template <typename K, typename V,
- typename k_invalid_t = K,
- typename v_invalid_t = V,
- k_invalid_t kINVALID = std::is_pointer<K>::value ? 0 : std::is_signed<K>::value ? hb_int_min (K) : (K) -1,
- v_invalid_t vINVALID = std::is_pointer<V>::value ? 0 : std::is_signed<V>::value ? hb_int_min (V) : (V) -1>
+ bool minus_one = false>
struct hb_hashmap_t
{
hb_hashmap_t () { init (); }
~hb_hashmap_t () { fini (); }
- hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { hb_copy (o, *this); }
+ hb_hashmap_t (const hb_hashmap_t& o) : hb_hashmap_t () { resize (population); hb_copy (o, *this); }
hb_hashmap_t (hb_hashmap_t&& o) : hb_hashmap_t () { hb_swap (*this, o); }
- hb_hashmap_t& operator= (const hb_hashmap_t& o) { hb_copy (o, *this); return *this; }
+ hb_hashmap_t& operator= (const hb_hashmap_t& o) { resize (population); hb_copy (o, *this); return *this; }
hb_hashmap_t& operator= (hb_hashmap_t&& o) { hb_swap (*this, o); return *this; }
hb_hashmap_t (std::initializer_list<hb_pair_t<K, V>> lst) : hb_hashmap_t ()
@@ -58,44 +57,53 @@ struct hb_hashmap_t
hb_requires (hb_is_iterable (Iterable))>
hb_hashmap_t (const Iterable &o) : hb_hashmap_t ()
{
- hb_copy (o, *this);
+ auto iter = hb_iter (o);
+ if (iter.is_random_access_iterator)
+ resize (hb_len (iter));
+ hb_copy (iter, *this);
}
struct item_t
{
K key;
+ uint32_t hash : 30;
+ uint32_t is_used_ : 1;
+ uint32_t is_tombstone_ : 1;
V value;
- uint32_t hash;
+
+ bool is_used () const { return is_used_; }
+ void set_used (bool is_used) { is_used_ = is_used; }
+ bool is_tombstone () const { return is_tombstone_; }
+ void set_tombstone (bool is_tombstone) { is_tombstone_ = is_tombstone; }
+ bool is_real () const { return is_used_ && !is_tombstone_; }
+
+ template <bool v = minus_one,
+ hb_enable_if (v == false)>
+ static inline const V& default_value () { return Null(V); };
+ template <bool v = minus_one,
+ hb_enable_if (v == true)>
+ static inline const V& default_value ()
+ {
+ static_assert (hb_is_same (V, hb_codepoint_t), "");
+ return minus_1;
+ };
void clear ()
{
new (std::addressof (key)) K ();
- key = hb_coerce<K> (kINVALID);
new (std::addressof (value)) V ();
- value = hb_coerce<V> (vINVALID);
hash = 0;
+ is_used_ = false;
+ is_tombstone_ = false;
}
bool operator == (const K &o) { return hb_deref (key) == hb_deref (o); }
bool operator == (const item_t &o) { return *this == o.key; }
- bool is_unused () const
- {
- const K inv = hb_coerce<K> (kINVALID);
- return key == inv;
- }
- bool is_tombstone () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value == vinv;
- }
- bool is_real () const
- {
- const K kinv = hb_coerce<K> (kINVALID);
- const V vinv = hb_coerce<V> (vINVALID);
- return key != kinv && value != vinv;
- }
hb_pair_t<K, V> get_pair() const { return hb_pair_t<K, V> (key, value); }
+ hb_pair_t<const K &, const V &> get_pair_ref() const { return hb_pair_t<const K &, const V &> (key, value); }
+
+ uint32_t total_hash () const
+ { return (hash * 31) + hb_hash (value); }
};
hb_object_header_t header;
@@ -116,21 +124,20 @@ struct hb_hashmap_t
hb_swap (a.prime, b.prime);
hb_swap (a.items, b.items);
}
- void init_shallow ()
+ void init ()
{
+ hb_object_init (this);
+
successful = true;
population = occupancy = 0;
mask = 0;
prime = 0;
items = nullptr;
}
- void init ()
- {
- hb_object_init (this);
- init_shallow ();
- }
- void fini_shallow ()
+ void fini ()
{
+ hb_object_fini (this);
+
if (likely (items)) {
unsigned size = mask + 1;
for (unsigned i = 0; i < size; i++)
@@ -140,11 +147,6 @@ struct hb_hashmap_t
}
population = occupancy = 0;
}
- void fini ()
- {
- hb_object_fini (this);
- fini_shallow ();
- }
void reset ()
{
@@ -154,11 +156,11 @@ struct hb_hashmap_t
bool in_error () const { return !successful; }
- bool resize ()
+ bool resize (unsigned new_population = 0)
{
if (unlikely (!successful)) return false;
- unsigned int power = hb_bit_storage (population * 2 + 8);
+ unsigned int power = hb_bit_storage (hb_max (population, new_population) * 2 + 8);
unsigned int new_size = 1u << power;
item_t *new_items = (item_t *) hb_malloc ((size_t) new_size * sizeof (item_t));
if (unlikely (!new_items))
@@ -196,27 +198,34 @@ struct hb_hashmap_t
return true;
}
- bool set (K key, const V& value) { return set_with_hash (key, hb_hash (key), value); }
- bool set (K key, V&& value) { return set_with_hash (key, hb_hash (key), std::move (value)); }
+ template <typename VV>
+ bool set (K key, VV&& value) { return set_with_hash (key, hb_hash (key), std::forward<VV> (value)); }
- V get (K key) const
+ const V& get (K key) const
{
- if (unlikely (!items)) return hb_coerce<V> (vINVALID);
+ if (unlikely (!items)) return item_t::default_value ();
unsigned int i = bucket_for (key);
- return items[i].is_real () && items[i] == key ? items[i].value : hb_coerce<V> (vINVALID);
+ return items[i].is_real () && items[i] == key ? items[i].value : item_t::default_value ();
}
- void del (K key) { set (key, hb_coerce<V> (vINVALID)); }
+ void del (K key) { set_with_hash (key, hb_hash (key), item_t::default_value (), true); }
/* Has interface. */
- typedef V value_t;
+ typedef const V& value_t;
value_t operator [] (K k) const { return get (k); }
- bool has (K k, V *vp = nullptr) const
+ template <typename VV=V>
+ bool has (K key, VV **vp = nullptr) const
{
- V v = (*this)[k];
- if (vp) *vp = v;
- const V vinv = hb_coerce<V> (vINVALID);
- return v != vinv;
+ if (unlikely (!items))
+ return false;
+ unsigned int i = bucket_for (key);
+ if (items[i].is_real () && items[i] == key)
+ {
+ if (vp) *vp = &items[i].value;
+ return true;
+ }
+ else
+ return false;
}
/* Projection. */
V operator () (K k) const { return get (k); }
@@ -235,6 +244,28 @@ struct hb_hashmap_t
bool is_empty () const { return population == 0; }
explicit operator bool () const { return !is_empty (); }
+ uint32_t hash () const
+ {
+ uint32_t h = 0;
+ for (const auto &item : + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real))
+ h ^= item.total_hash ();
+ return h;
+ }
+
+ bool is_equal (const hb_hashmap_t &other) const
+ {
+ if (population != other.population) return false;
+
+ for (auto pair : iter ())
+ if (get (pair.first) != pair.second)
+ return false;
+
+ return true;
+ }
+ bool operator == (const hb_hashmap_t &other) const { return is_equal (other); }
+ bool operator != (const hb_hashmap_t &other) const { return !is_equal (other); }
+
unsigned int get_population () const { return population; }
/*
@@ -246,6 +277,12 @@ struct hb_hashmap_t
| hb_filter (&item_t::is_real)
| hb_map (&item_t::get_pair)
)
+ auto iter_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::get_pair_ref)
+ )
auto keys () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
@@ -253,6 +290,12 @@ struct hb_hashmap_t
| hb_map (&item_t::key)
| hb_map (hb_ridentity)
)
+ auto keys_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::key)
+ )
auto values () const HB_AUTO_RETURN
(
+ hb_array (items, mask ? mask + 1 : 0)
@@ -260,6 +303,12 @@ struct hb_hashmap_t
| hb_map (&item_t::value)
| hb_map (hb_ridentity)
)
+ auto values_ref () const HB_AUTO_RETURN
+ (
+ + hb_array (items, mask ? mask + 1 : 0)
+ | hb_filter (&item_t::is_real)
+ | hb_map (&item_t::value)
+ )
/* Sink interface. */
hb_hashmap_t& operator << (const hb_pair_t<K, V>& v)
@@ -268,19 +317,16 @@ struct hb_hashmap_t
protected:
template <typename VV>
- bool set_with_hash (K key, uint32_t hash, VV&& value)
+ bool set_with_hash (K key, uint32_t hash, VV&& value, bool is_delete=false)
{
if (unlikely (!successful)) return false;
- const K kinv = hb_coerce<K> (kINVALID);
- if (unlikely (key == kinv)) return true;
if (unlikely ((occupancy + occupancy / 2) >= mask && !resize ())) return false;
unsigned int i = bucket_for_hash (key, hash);
- const V vinv = hb_coerce<V> (vINVALID);
- if (value == vinv && items[i].key != key)
+ if (is_delete && items[i].key != key)
return true; /* Trying to delete non-existent key. */
- if (!items[i].is_unused ())
+ if (items[i].is_used ())
{
occupancy--;
if (!items[i].is_tombstone ())
@@ -288,27 +334,30 @@ struct hb_hashmap_t
}
items[i].key = key;
- items[i].value = value;
+ items[i].value = std::forward<VV> (value);
items[i].hash = hash;
+ items[i].set_used (true);
+ items[i].set_tombstone (is_delete);
occupancy++;
- if (!items[i].is_tombstone ())
+ if (!is_delete)
population++;
return true;
}
- unsigned int bucket_for (K key) const
+ unsigned int bucket_for (const K &key) const
{
return bucket_for_hash (key, hb_hash (key));
}
- unsigned int bucket_for_hash (K key, uint32_t hash) const
+ unsigned int bucket_for_hash (const K &key, uint32_t hash) const
{
+ hash &= 0x3FFFFFFF; // We only store lower 30bit of hash
unsigned int i = hash % prime;
unsigned int step = 0;
unsigned int tombstone = (unsigned) -1;
- while (!items[i].is_unused ())
+ while (items[i].is_used ())
{
if (items[i].hash == hash && items[i] == key)
return i;
@@ -377,21 +426,16 @@ struct hb_hashmap_t
struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>
+ true>
{
using hashmap = hb_hashmap_t<hb_codepoint_t,
hb_codepoint_t,
- hb_codepoint_t,
- hb_codepoint_t,
- HB_MAP_VALUE_INVALID,
- HB_MAP_VALUE_INVALID>;
+ true>;
- hb_map_t () = default;
~hb_map_t () = default;
- hb_map_t (hb_map_t&) = default;
+ hb_map_t () : hashmap () {}
+ hb_map_t (const hb_map_t &o) : hashmap ((hashmap &) o) {}
+ hb_map_t (hb_map_t &&o) : hashmap (std::move ((hashmap &) o)) {}
hb_map_t& operator= (const hb_map_t&) = default;
hb_map_t& operator= (hb_map_t&&) = default;
hb_map_t (std::initializer_list<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> lst) : hashmap (lst) {}
@@ -400,4 +444,37 @@ struct hb_map_t : hb_hashmap_t<hb_codepoint_t,
hb_map_t (const Iterable &o) : hashmap (o) {}
};
+template <typename K, typename V>
+static inline
+hb_hashmap_t<K, V>* hb_hashmap_create ()
+{
+ using hashmap = hb_hashmap_t<K, V>;
+ hashmap* map;
+ if (!(map = hb_object_create<hashmap> ()))
+ return nullptr;
+
+ return map;
+}
+
+template <typename K, typename V>
+static inline
+void hb_hashmap_destroy (hb_hashmap_t<K, V>* map)
+{
+ if (!hb_object_destroy (map))
+ return;
+
+ hb_free (map);
+}
+
+namespace hb {
+
+template <typename K, typename V>
+struct vtable<hb_hashmap_t<K, V>>
+{
+ static constexpr auto destroy = hb_hashmap_destroy<K,V>;
+};
+
+}
+
+
#endif /* HB_MAP_HH */
diff --git a/thirdparty/harfbuzz/src/hb-meta.hh b/thirdparty/harfbuzz/src/hb-meta.hh
index 3fea5d995e..1921ccbb6d 100644
--- a/thirdparty/harfbuzz/src/hb-meta.hh
+++ b/thirdparty/harfbuzz/src/hb-meta.hh
@@ -188,6 +188,19 @@ template <> struct hb_int_max<signed long long> : hb_integral_constant<signed l
template <> struct hb_int_max<unsigned long long> : hb_integral_constant<unsigned long long, ULLONG_MAX> {};
#define hb_int_max(T) hb_int_max<T>::value
+#if defined(__GNUC__) && __GNUC__ < 5 && !defined(__clang__)
+#define hb_is_trivially_copyable(T) __has_trivial_copy(T)
+#define hb_is_trivially_copy_assignable(T) __has_trivial_assign(T)
+#define hb_is_trivially_constructible(T) __has_trivial_constructor(T)
+#define hb_is_trivially_copy_constructible(T) __has_trivial_copy_constructor(T)
+#define hb_is_trivially_destructible(T) __has_trivial_destructor(T)
+#else
+#define hb_is_trivially_copyable(T) std::is_trivially_copyable<T>::value
+#define hb_is_trivially_copy_assignable(T) std::is_trivially_copy_assignable<T>::value
+#define hb_is_trivially_constructible(T) std::is_trivially_constructible<T>::value
+#define hb_is_trivially_copy_constructible(T) std::is_trivially_copy_constructible<T>::value
+#define hb_is_trivially_destructible(T) std::is_trivially_destructible<T>::value
+#endif
/* Class traits. */
diff --git a/thirdparty/harfbuzz/src/hb-null.hh b/thirdparty/harfbuzz/src/hb-null.hh
index db38a4dfd2..0d7f4da79e 100644
--- a/thirdparty/harfbuzz/src/hb-null.hh
+++ b/thirdparty/harfbuzz/src/hb-null.hh
@@ -37,7 +37,25 @@
/* Global nul-content Null pool. Enlarge as necessary. */
-#define HB_NULL_POOL_SIZE 384
+#define HB_NULL_POOL_SIZE 448
+
+template <typename T, typename>
+struct _hb_has_min_size : hb_false_type {};
+template <typename T>
+struct _hb_has_min_size<T, hb_void_t<decltype (T::min_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_min_size = _hb_has_min_size<T, void>;
+#define hb_has_min_size(T) hb_has_min_size<T>::value
+
+template <typename T, typename>
+struct _hb_has_null_size : hb_false_type {};
+template <typename T>
+struct _hb_has_null_size<T, hb_void_t<decltype (T::null_size)>>
+ : hb_true_type {};
+template <typename T>
+using hb_has_null_size = _hb_has_null_size<T, void>;
+#define hb_has_null_size(T) hb_has_null_size<T>::value
/* Use SFINAE to sniff whether T has min_size; in which case return the larger
* of sizeof(T) and T::null_size, otherwise return sizeof(T).
@@ -108,7 +126,7 @@ struct NullHelper
/* Specializations for arbitrary-content Null objects expressed in bytes. */
#define DECLARE_NULL_NAMESPACE_BYTES(Namespace, Type) \
} /* Close namespace. */ \
- extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]; \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[hb_null_size (Namespace::Type)]; \
template <> \
struct Null<Namespace::Type> { \
static Namespace::Type const & get_null () { \
@@ -117,8 +135,19 @@ struct NullHelper
}; \
namespace Namespace { \
static_assert (true, "") /* Require semicolon after. */
+#define DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1(Namespace, Type, Size) \
+ } /* Close namespace. */ \
+ extern HB_INTERNAL const unsigned char _hb_Null_##Namespace##_##Type[Size]; \
+ template <typename Spec> \
+ struct Null<Namespace::Type<Spec>> { \
+ static Namespace::Type<Spec> const & get_null () { \
+ return *reinterpret_cast<const Namespace::Type<Spec> *> (_hb_Null_##Namespace##_##Type); \
+ } \
+ }; \
+ namespace Namespace { \
+ static_assert (true, "") /* Require semicolon after. */
#define DEFINE_NULL_NAMESPACE_BYTES(Namespace, Type) \
- const unsigned char _hb_Null_##Namespace##_##Type[Namespace::Type::null_size]
+ const unsigned char _hb_Null_##Namespace##_##Type[sizeof (_hb_Null_##Namespace##_##Type)]
/* Specializations for arbitrary-content Null objects expressed as struct initializer. */
#define DECLARE_NULL_INSTANCE(Type) \
diff --git a/thirdparty/harfbuzz/src/hb-object.hh b/thirdparty/harfbuzz/src/hb-object.hh
index 4b5bc32ade..f6c7a56991 100644
--- a/thirdparty/harfbuzz/src/hb-object.hh
+++ b/thirdparty/harfbuzz/src/hb-object.hh
@@ -222,8 +222,11 @@ static inline Type *hb_object_create ()
if (unlikely (!obj))
return obj;
+ new (obj) Type;
+
hb_object_init (obj);
hb_object_trace (obj, HB_FUNC);
+
return obj;
}
template <typename Type>
@@ -269,6 +272,9 @@ static inline bool hb_object_destroy (Type *obj)
return false;
hb_object_fini (obj);
+
+ obj->~Type ();
+
return true;
}
template <typename Type>
@@ -280,7 +286,7 @@ static inline void hb_object_fini (Type *obj)
{
user_data->fini ();
hb_free (user_data);
- user_data = nullptr;
+ obj->header.user_data.set_relaxed (nullptr);
}
}
template <typename Type>
diff --git a/thirdparty/harfbuzz/src/hb-open-type.hh b/thirdparty/harfbuzz/src/hb-open-type.hh
index 7e524177f6..d0d01a68c5 100644
--- a/thirdparty/harfbuzz/src/hb-open-type.hh
+++ b/thirdparty/harfbuzz/src/hb-open-type.hh
@@ -33,6 +33,7 @@
#include "hb-blob.hh"
#include "hb-face.hh"
#include "hb-machinery.hh"
+#include "hb-meta.hh"
#include "hb-subset.hh"
@@ -104,7 +105,7 @@ struct IntType
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
BEInt<Type, Size> v;
@@ -169,7 +170,7 @@ struct LONGDATETIME
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
HBINT32 major;
@@ -195,6 +196,10 @@ struct HBGlyphID16 : HBUINT16
{
HBGlyphID16& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
};
+struct HBGlyphID24 : HBUINT24
+{
+ HBGlyphID24& operator = (uint32_t i) { HBUINT24::operator= (i); return *this; }
+};
/* Script/language-system/feature index */
struct Index : HBUINT16 {
@@ -299,6 +304,10 @@ struct _hb_has_null<Type, true>
template <typename Type, typename OffsetType, bool has_null=true>
struct OffsetTo : Offset<OffsetType, has_null>
{
+ // Make sure Type is not unbounded; works only for types that are fully defined at OffsetTo time.
+ static_assert (has_null == false ||
+ (hb_has_null_size (Type) || !hb_has_min_size (Type)), "");
+
HB_DELETE_COPY_ASSIGN (OffsetTo);
OffsetTo () = default;
@@ -449,14 +458,16 @@ struct UnsizedArrayOf
{
unsigned int i = (unsigned int) i_;
const Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
Type *p = &arrayZ[i];
- if (unlikely (p < arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return *p;
}
@@ -518,7 +529,7 @@ struct UnsizedArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c, count))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
return_trace (false);
@@ -549,14 +560,16 @@ struct UnsizedListOfOffset16To : UnsizedArray16OfOffsetTo<Type, OffsetType, has_
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Null (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Null (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
const OffsetTo<Type, OffsetType, has_null> *p = &this->arrayZ[i];
- if (unlikely (p < this->arrayZ)) return Crap (Type); /* Overflowed. */
+ if (unlikely ((const void *) p < (const void *) this->arrayZ)) return Crap (Type); /* Overflowed. */
+ _hb_compiler_memory_r_barrier ();
return this+*p;
}
@@ -607,12 +620,14 @@ struct ArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
@@ -707,7 +722,7 @@ struct ArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = len;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -728,6 +743,7 @@ struct ArrayOf
DEFINE_SIZE_ARRAY (sizeof (LenType), arrayZ);
};
template <typename Type> using Array16Of = ArrayOf<Type, HBUINT16>;
+template <typename Type> using Array24Of = ArrayOf<Type, HBUINT24>;
template <typename Type> using Array32Of = ArrayOf<Type, HBUINT32>;
using PString = ArrayOf<HBUINT8, HBUINT8>;
@@ -737,26 +753,28 @@ template <typename Type> using Array16OfOffset32To = ArrayOf<OffsetTo<Type, HBUI
template <typename Type> using Array32OfOffset32To = ArrayOf<OffsetTo<Type, HBUINT32>, HBUINT32>;
/* Array of offsets relative to the beginning of the array itself. */
-template <typename Type>
-struct List16OfOffset16To : Array16OfOffset16To<Type>
+template <typename Type, typename OffsetType>
+struct List16OfOffsetTo : ArrayOf<OffsetTo<Type, OffsetType>, HBUINT16>
{
const Type& operator [] (int i_) const
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
const Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= this->len)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return this+this->arrayZ[i];
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- struct List16OfOffset16To<Type> *out = c->serializer->embed (*this);
+ struct List16OfOffsetTo *out = c->serializer->embed (*this);
if (unlikely (!out)) return_trace (false);
unsigned int count = this->len;
for (unsigned int i = 0; i < count; i++)
@@ -768,10 +786,13 @@ struct List16OfOffset16To : Array16OfOffset16To<Type>
bool sanitize (hb_sanitize_context_t *c, Ts&&... ds) const
{
TRACE_SANITIZE (this);
- return_trace (Array16OfOffset16To<Type>::sanitize (c, this, std::forward<Ts> (ds)...));
+ return_trace ((Array16Of<OffsetTo<Type, OffsetType>>::sanitize (c, this, std::forward<Ts> (ds)...)));
}
};
+template <typename Type>
+using List16OfOffset16To = List16OfOffsetTo<Type, HBUINT16>;
+
/* An array starting at second element. */
template <typename Type, typename LenType=HBUINT16>
struct HeadlessArrayOf
@@ -784,12 +805,14 @@ struct HeadlessArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= lenP1 || !i)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i-1];
}
unsigned int get_size () const
@@ -835,7 +858,7 @@ struct HeadlessArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -868,12 +891,14 @@ struct ArrayOfM1
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i > lenM1)) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return arrayZ[i];
}
unsigned int get_size () const
@@ -884,7 +909,7 @@ struct ArrayOfM1
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = lenM1 + 1;
for (unsigned int i = 0; i < count; i++)
if (unlikely (!c->dispatch (arrayZ[i], std::forward<Ts> (ds)...)))
@@ -960,6 +985,7 @@ struct SortedArrayOf : ArrayOf<Type, LenType>
};
template <typename Type> using SortedArray16Of = SortedArrayOf<Type, HBUINT16>;
+template <typename Type> using SortedArray24Of = SortedArrayOf<Type, HBUINT24>;
template <typename Type> using SortedArray32Of = SortedArrayOf<Type, HBUINT32>;
/*
@@ -1052,12 +1078,14 @@ struct VarSizedBinSearchArrayOf
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Null (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
Type& operator [] (int i_)
{
unsigned int i = (unsigned int) i_;
if (unlikely (i >= get_length ())) return Crap (Type);
+ _hb_compiler_memory_r_barrier ();
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
unsigned int get_length () const
@@ -1070,7 +1098,7 @@ struct VarSizedBinSearchArrayOf
{
TRACE_SANITIZE (this);
if (unlikely (!sanitize_shallow (c))) return_trace (false);
- if (!sizeof... (Ts) && std::is_trivially_copyable<Type>::value) return_trace (true);
+ if (!sizeof... (Ts) && hb_is_trivially_copyable(Type)) return_trace (true);
unsigned int count = get_length ();
for (unsigned int i = 0; i < count; i++)
if (unlikely (!(*this)[i].sanitize (c, std::forward<Ts> (ds)...)))
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
index c102c15173..ae3b83a256 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff-common.hh
@@ -46,49 +46,21 @@ template<typename Type>
static inline const Type& StructAtOffsetOrNull (const void *P, unsigned int offset)
{ return offset ? StructAtOffset<Type> (P, offset) : Null (Type); }
-inline unsigned int calcOffSize (unsigned int dataSize)
-{
- unsigned int size = 1;
- unsigned int offset = dataSize + 1;
- while (offset & ~0xFF)
- {
- size++;
- offset >>= 8;
- }
- /* format does not support size > 4; caller should handle it as an error */
- return size;
-}
-
struct code_pair_t
{
hb_codepoint_t code;
hb_codepoint_t glyph;
};
-typedef hb_vector_t<unsigned char> str_buff_t;
-struct str_buff_vec_t : hb_vector_t<str_buff_t>
-{
- unsigned int total_size () const
- {
- unsigned int size = 0;
- for (unsigned int i = 0; i < length; i++)
- size += (*this)[i].length;
- return size;
- }
-
- private:
- typedef hb_vector_t<str_buff_t> SUPER;
-};
+using str_buff_t = hb_vector_t<unsigned char>;
+using str_buff_vec_t = hb_vector_t<str_buff_t>;
/* CFF INDEX */
template <typename COUNT>
struct CFFIndex
{
- static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
- { return offSize * (count + 1); }
-
unsigned int offset_array_size () const
- { return calculate_offset_array_size (offSize, count); }
+ { return offSize * (count + 1); }
CFFIndex *copy (hb_serialize_context_t *c) const
{
@@ -100,55 +72,46 @@ struct CFFIndex
return_trace (out);
}
- bool serialize (hb_serialize_context_t *c, const CFFIndex &src)
- {
- TRACE_SERIALIZE (this);
- unsigned int size = src.get_size ();
- CFFIndex *dest = c->allocate_size<CFFIndex> (size);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &src, size);
- return_trace (true);
- }
-
bool serialize (hb_serialize_context_t *c,
unsigned int offSize_,
const byte_str_array_t &byteArray)
{
TRACE_SERIALIZE (this);
+
if (byteArray.length == 0)
{
COUNT *dest = c->allocate_min<COUNT> ();
if (unlikely (!dest)) return_trace (false);
*dest = 0;
+ return_trace (true);
}
- else
- {
- /* serialize CFFIndex header */
- if (unlikely (!c->extend_min (this))) return_trace (false);
- this->count = byteArray.length;
- this->offSize = offSize_;
- if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
- return_trace (false);
- /* serialize indices */
- unsigned int offset = 1;
- unsigned int i = 0;
- for (; i < byteArray.length; i++)
- {
- set_offset_at (i, offset);
- offset += byteArray[i].get_size ();
- }
+ /* serialize CFFIndex header */
+ if (unlikely (!c->extend_min (this))) return_trace (false);
+ this->count = byteArray.length;
+ this->offSize = offSize_;
+ if (unlikely (!c->allocate_size<HBUINT8> (offSize_ * (byteArray.length + 1))))
+ return_trace (false);
+
+ /* serialize indices */
+ unsigned int offset = 1;
+ unsigned int i = 0;
+ for (; i < byteArray.length; i++)
+ {
set_offset_at (i, offset);
+ offset += byteArray[i].get_size ();
+ }
+ set_offset_at (i, offset);
- /* serialize data */
- for (unsigned int i = 0; i < byteArray.length; i++)
- {
- const byte_str_t &bs = byteArray[i];
- unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
- if (unlikely (!dest)) return_trace (false);
- memcpy (dest, &bs[0], bs.length);
- }
+ /* serialize data */
+ for (unsigned int i = 0; i < byteArray.length; i++)
+ {
+ const hb_ubytes_t &bs = byteArray[i];
+ unsigned char *dest = c->allocate_size<unsigned char> (bs.length);
+ if (unlikely (!dest)) return_trace (false);
+ memcpy (dest, &bs[0], bs.length);
}
+
return_trace (true);
}
@@ -160,7 +123,7 @@ struct CFFIndex
byteArray.init ();
byteArray.resize (buffArray.length);
for (unsigned int i = 0; i < byteArray.length; i++)
- byteArray[i] = byte_str_t (buffArray[i].arrayZ, buffArray[i].length);
+ byteArray[i] = hb_ubytes_t (buffArray[i].arrayZ, buffArray[i].length);
bool result = this->serialize (c, offSize_, byteArray);
byteArray.fini ();
return result;
@@ -172,18 +135,9 @@ struct CFFIndex
Iterator it)
{
TRACE_SERIALIZE (this);
- if (it.len () == 0)
- {
- COUNT *dest = c->allocate_min<COUNT> ();
- if (unlikely (!dest)) return_trace (false);
- *dest = 0;
- }
- else
- {
- serialize_header(c, + it | hb_map ([] (const byte_str_t &_) { return _.length; }));
- for (const auto &_ : +it)
- _.copy (c);
- }
+ serialize_header(c, + it | hb_map ([] (const hb_ubytes_t &_) { return _.length; }));
+ for (const auto &_ : +it)
+ _.copy (c);
return_trace (true);
}
@@ -196,7 +150,7 @@ struct CFFIndex
{
auto it =
+ hb_iter (buffArray)
- | hb_map ([] (const str_buff_t &_) { return byte_str_t (_.arrayZ, _.length); })
+ | hb_map ([] (const str_buff_t &_) { return hb_ubytes_t (_.arrayZ, _.length); })
;
return serialize (c, it);
}
@@ -209,13 +163,15 @@ struct CFFIndex
TRACE_SERIALIZE (this);
unsigned total = + it | hb_reduce (hb_add, 0);
- unsigned off_size = calcOffSize (total);
+ unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
/* serialize CFFIndex header */
if (unlikely (!c->extend_min (this))) return_trace (false);
this->count = it.len ();
+ if (!this->count) return_trace (true);
+ if (unlikely (!c->extend (this->offSize))) return_trace (false);
this->offSize = off_size;
- if (unlikely (!c->allocate_size<HBUINT8> (off_size * (it.len () + 1))))
+ if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1))))
return_trace (false);
/* serialize indices */
@@ -233,6 +189,7 @@ struct CFFIndex
void set_offset_at (unsigned int index, unsigned int offset)
{
+ assert (index <= count);
HBUINT8 *p = offsets + offSize * index + offSize;
unsigned int size = offSize;
for (; size; size--)
@@ -243,11 +200,13 @@ struct CFFIndex
}
}
+ private:
unsigned int offset_at (unsigned int index) const
{
assert (index <= count);
- const HBUINT8 *p = offsets + offSize * index;
+
unsigned int size = offSize;
+ const HBUINT8 *p = offsets + size * index;
unsigned int offset = 0;
for (; size; size--)
offset = (offset << 8) + *p++;
@@ -256,72 +215,57 @@ struct CFFIndex
unsigned int length_at (unsigned int index) const
{
- if (unlikely ((offset_at (index + 1) < offset_at (index)) ||
- (offset_at (index + 1) > offset_at (count))))
+ unsigned offset0 = offset_at (index);
+ unsigned offset1 = offset_at (index + 1);
+ if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
return 0;
- return offset_at (index + 1) - offset_at (index);
+ return offset1 - offset0;
}
const unsigned char *data_base () const
- { return (const unsigned char *) this + min_size + offset_array_size (); }
-
- unsigned int data_size () const { return HBINT8::static_size; }
+ { return (const unsigned char *) this + min_size + offSize.static_size + offset_array_size (); }
+ public:
- byte_str_t operator [] (unsigned int index) const
+ hb_ubytes_t operator [] (unsigned int index) const
{
- if (unlikely (index >= count)) return Null (byte_str_t);
- return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
+ if (unlikely (index >= count)) return hb_ubytes_t ();
+ unsigned length = length_at (index);
+ if (unlikely (!length)) return hb_ubytes_t ();
+ return hb_ubytes_t (data_base () + offset_at (index) - 1, length);
}
unsigned int get_size () const
{
- if (this == &Null (CFFIndex)) return 0;
- if (count > 0)
- return min_size + offset_array_size () + (offset_at (count) - 1);
- return count.static_size; /* empty CFFIndex contains count only */
+ if (count)
+ return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
+ return min_size; /* empty CFFIndex contains count only */
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely ((c->check_struct (this) && count == 0) || /* empty INDEX */
- (c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
- c->check_array (offsets, offSize, count + 1) &&
- c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
- }
-
- protected:
- unsigned int max_offset () const
- {
- unsigned int max = 0;
- for (unsigned int i = 0; i < count + 1u; i++)
- {
- unsigned int off = offset_at (i);
- if (off > max) max = off;
- }
- return max;
+ return_trace (likely (c->check_struct (this) &&
+ (count == 0 || /* empty INDEX */
+ (count < count + 1u &&
+ c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
+ c->check_array (offsets, offSize, count + 1u) &&
+ c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count) - 1)))));
}
public:
COUNT count; /* Number of object data. Note there are (count+1) offsets */
+ private:
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
HBUINT8 offsets[HB_VAR_ARRAY];
/* The array of (count + 1) offsets into objects array (1-base). */
/* HBUINT8 data[HB_VAR_ARRAY]; Object data */
public:
- DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
+ DEFINE_SIZE_MIN (COUNT::static_size);
};
template <typename COUNT, typename TYPE>
struct CFFIndexOf : CFFIndex<COUNT>
{
- const byte_str_t operator [] (unsigned int index) const
- {
- if (likely (index < CFFIndex<COUNT>::count))
- return byte_str_t (CFFIndex<COUNT>::data_base () + CFFIndex<COUNT>::offset_at (index) - 1, CFFIndex<COUNT>::length_at (index));
- return Null (byte_str_t);
- }
-
template <typename DATA, typename PARAM1, typename PARAM2>
bool serialize (hb_serialize_context_t *c,
unsigned int offSize_,
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
index 3298fa35ae..bd9fe5d6d4 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.cc
@@ -311,10 +311,8 @@ struct bounds_t
struct cff1_extents_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
+ cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
{
- path_open = false;
- cff = _cff;
bounds.init ();
}
@@ -322,7 +320,7 @@ struct cff1_extents_param_t
void end_path () { path_open = false; }
bool is_path_open () const { return path_open; }
- bool path_open;
+ bool path_open = false;
bounds_t bounds;
const OT::cff1::accelerator_t *cff;
@@ -395,12 +393,11 @@ bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, boun
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
- cff1_extents_param_t param;
- param.init (cff);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
+ cff1_extents_param_t param (cff);
if (unlikely (!interp.interpret (param))) return false;
bounds = param.bounds;
return true;
@@ -442,13 +439,12 @@ bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff1_path_param_t
{
cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
- draw_helper_t &draw_helper_, point_t *delta_)
+ hb_draw_session_t &draw_session_, point_t *delta_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
cff = cff_;
font = font_;
delta = delta_;
@@ -458,14 +454,14 @@ struct cff1_path_param_t
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void line_to (const point_t &p)
{
point_t point = p;
if (delta) point.move (*delta);
- draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ()));
+ draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
}
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
@@ -477,15 +473,15 @@ struct cff1_path_param_t
point2.move (*delta);
point3.move (*delta);
}
- draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()),
- font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()),
- font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
+ font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
+ font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
}
- void end_path () { draw_helper->end_path (); }
+ void end_path () { draw_session->close_path (); }
hb_font_t *font;
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
point_t *delta;
const OT::cff1::accelerator_t *cff;
@@ -513,7 +509,7 @@ struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_int
};
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr);
+ hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
{
@@ -530,23 +526,23 @@ struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_pa
hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
if (unlikely (!(!env.in_seac && base && accent
- && _get_path (param.cff, param.font, base, *param.draw_helper, true)
- && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta))))
+ && _get_path (param.cff, param.font, base, *param.draw_session, true)
+ && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
env.set_error ();
}
};
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
- draw_helper_t &draw_helper, bool in_seac, point_t *delta)
+ hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
{
if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
unsigned int fd = cff->fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp;
- const byte_str_t str = (*cff->charStrings)[glyph];
- interp.env.init (str, *cff, fd);
- interp.env.set_in_seac (in_seac);
- cff1_path_param_t param (cff, font, draw_helper, delta);
+ const hb_ubytes_t str = (*cff->charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *cff, fd);
+ env.set_in_seac (in_seac);
+ cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
+ cff1_path_param_t param (cff, font, draw_session, delta);
if (unlikely (!interp.interpret (param))) return false;
/* Let's end the path specially since it is called inside seac also */
@@ -555,31 +551,25 @@ bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoin
return true;
}
-bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
return true;
#endif
- return _get_path (this, font, glyph, draw_helper);
+ return _get_path (this, font, glyph, draw_session);
}
-#endif
struct get_seac_param_t
{
- void init (const OT::cff1::accelerator_t *_cff)
- {
- cff = _cff;
- base = 0;
- accent = 0;
- }
+ get_seac_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff) {}
bool has_seac () const { return base && accent; }
const OT::cff1::accelerator_t *cff;
- hb_codepoint_t base;
- hb_codepoint_t accent;
+ hb_codepoint_t base = 0;
+ hb_codepoint_t accent = 0;
};
struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
@@ -600,11 +590,10 @@ bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_code
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd);
- get_seac_param_t param;
- param.init (this);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff1_cs_interp_env_t env (str, *this, fd);
+ cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
+ get_seac_param_t param (this);
if (unlikely (!interp.interpret (param))) return false;
if (param.has_seac ())
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
index 6fb59315c9..4aa337f78b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh
@@ -318,14 +318,21 @@ struct Charset0 {
return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0)
return 0;
else
return sids[glyph - 1];
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ for (hb_codepoint_t gid = 1; gid < num_glyphs; gid++)
+ mapping->set (gid, sids[gid - 1]);
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0)
@@ -381,20 +388,38 @@ struct Charset1_2 {
return_trace (true);
}
- hb_codepoint_t get_sid (hb_codepoint_t glyph) const
+ hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned num_glyphs) const
{
+ if (unlikely (glyph >= num_glyphs)) return 0;
if (glyph == 0) return 0;
glyph--;
for (unsigned int i = 0;; i++)
{
if (glyph <= ranges[i].nLeft)
- return (hb_codepoint_t)ranges[i].first + glyph;
+ return (hb_codepoint_t) ranges[i].first + glyph;
glyph -= (ranges[i].nLeft + 1);
}
return 0;
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ hb_codepoint_t gid = 1;
+ if (gid >= num_glyphs)
+ return;
+ for (unsigned i = 0;; i++)
+ {
+ hb_codepoint_t sid = ranges[i].first;
+ unsigned count = ranges[i].nLeft + 1;
+ for (unsigned j = 0; j < count; j++)
+ mapping->set (gid++, sid++);
+
+ if (gid >= num_glyphs)
+ break;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
if (sid == 0) return 0;
@@ -521,16 +546,26 @@ struct Charset
hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
{
- if (unlikely (glyph >= num_glyphs)) return 0;
switch (format)
{
- case 0: return u.format0.get_sid (glyph);
- case 1: return u.format1.get_sid (glyph);
- case 2: return u.format2.get_sid (glyph);
+ case 0: return u.format0.get_sid (glyph, num_glyphs);
+ case 1: return u.format1.get_sid (glyph, num_glyphs);
+ case 2: return u.format2.get_sid (glyph, num_glyphs);
default:return 0;
}
}
+ void collect_glyph_to_sid_map (hb_map_t *mapping, unsigned int num_glyphs) const
+ {
+ switch (format)
+ {
+ case 0: u.format0.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 1: u.format1.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ case 2: u.format2.collect_glyph_to_sid_map (mapping, num_glyphs); return;
+ default:return;
+ }
+ }
+
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{
switch (format)
@@ -602,6 +637,8 @@ struct cff1_top_dict_interp_env_t : num_interp_env_t
{
cff1_top_dict_interp_env_t ()
: num_interp_env_t(), prev_offset(0), last_offset(0) {}
+ cff1_top_dict_interp_env_t (const hb_ubytes_t &bytes)
+ : num_interp_env_t(bytes), prev_offset(0), last_offset(0) {}
unsigned int prev_offset;
unsigned int last_offset;
@@ -1024,11 +1061,10 @@ struct cff1
{ fini (); return; }
{ /* parse top dict */
- const byte_str_t topDictStr = (*topDictIndex)[0];
+ const hb_ubytes_t topDictStr = (*topDictIndex)[0];
if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
- cff1_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
- topDict.init ();
+ cff1_top_dict_interp_env_t env (topDictStr);
+ cff1_top_dict_interpreter_t top_interp (env);
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
}
@@ -1098,20 +1134,21 @@ struct cff1
{
for (unsigned int i = 0; i < fdCount; i++)
{
- byte_str_t fontDictStr = (*fdArray)[i];
+ hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
cff1_font_dict_values_t *font;
- cff1_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ cff1_top_dict_interp_env_t env (fontDictStr);
+ cff1_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
- if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
+ if (unlikely (fontDicts.in_error ())) { fini (); return; }
+
font->init ();
if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
PRIVDICTVAL *priv = &privateDicts[i];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env2);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1126,10 +1163,10 @@ struct cff1
cff1_top_dict_values_t *font = &topDict;
PRIVDICTVAL *priv = &privateDicts[0];
- const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
- priv_interp.env.init (privDictStr);
+ num_interp_env_t env (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp (env);
priv->init ();
if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
@@ -1194,6 +1231,19 @@ struct cff1
}
}
+ hb_map_t *create_glyph_to_sid_map () const
+ {
+ if (charset != &Null (Charset))
+ {
+ hb_map_t *mapping = hb_map_create ();
+ mapping->set (0, 0);
+ charset->collect_glyph_to_sid_map (mapping, num_glyphs);
+ return mapping;
+ }
+ else
+ return nullptr;
+ }
+
hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
{
if (charset != &Null (Charset))
@@ -1274,30 +1324,20 @@ struct cff1
{
SUPER::init (face);
+ glyph_names.set_relaxed (nullptr);
+
if (!is_valid ()) return;
if (is_CID ()) return;
- /* fill glyph_names */
- for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
- {
- hb_codepoint_t sid = glyph_to_sid (gid);
- gname_t gname;
- gname.sid = sid;
- if (sid < cff1_std_strings_length)
- gname.name = cff1_std_strings (sid);
- else
- {
- byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
- gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
- }
- if (unlikely (!gname.name.arrayZ)) { fini (); return; }
- glyph_names.push (gname);
- }
- glyph_names.qsort ();
}
~accelerator_t ()
{
- glyph_names.fini ();
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get_relaxed ();
+ if (names)
+ {
+ names->fini ();
+ hb_free (names);
+ }
SUPER::fini ();
}
@@ -1305,9 +1345,9 @@ struct cff1
bool get_glyph_name (hb_codepoint_t glyph,
char *buf, unsigned int buf_len) const
{
- if (!buf) return true;
if (unlikely (!is_valid ())) return false;
if (is_CID()) return false;
+ if (unlikely (!buf_len)) return true;
hb_codepoint_t sid = glyph_to_sid (glyph);
const char *str;
size_t str_len;
@@ -1319,7 +1359,7 @@ struct cff1
}
else
{
- byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
+ hb_ubytes_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
str = (const char *)ubyte_str.arrayZ;
str_len = ubyte_str.length;
}
@@ -1333,11 +1373,53 @@ struct cff1
bool get_glyph_from_name (const char *name, int len,
hb_codepoint_t *glyph) const
{
+ if (unlikely (!is_valid ())) return false;
+ if (is_CID()) return false;
if (len < 0) len = strlen (name);
if (unlikely (!len)) return false;
+ retry:
+ hb_sorted_vector_t<gname_t> *names = glyph_names.get ();
+ if (unlikely (!names))
+ {
+ names = (hb_sorted_vector_t<gname_t> *) hb_calloc (sizeof (hb_sorted_vector_t<gname_t>), 1);
+ if (likely (names))
+ {
+ names->init ();
+ /* TODO */
+
+ /* fill glyph names */
+ for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
+ {
+ hb_codepoint_t sid = glyph_to_sid (gid);
+ gname_t gname;
+ gname.sid = sid;
+ if (sid < cff1_std_strings_length)
+ gname.name = cff1_std_strings (sid);
+ else
+ {
+ hb_ubytes_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
+ gname.name = hb_bytes_t ((const char*) ustr.arrayZ, ustr.length);
+ }
+ if (unlikely (!gname.name.arrayZ))
+ gname.name = hb_bytes_t ("", 0); /* To avoid nullptr. */
+ names->push (gname);
+ }
+ names->qsort ();
+ }
+ if (unlikely (!glyph_names.cmpexch (nullptr, names)))
+ {
+ if (names)
+ {
+ names->fini ();
+ hb_free (names);
+ }
+ goto retry;
+ }
+ }
+
gname_t key = { hb_bytes_t (name, len), 0 };
- const gname_t *gname = glyph_names.bsearch (key);
+ const gname_t *gname = names ? names->bsearch (key) : nullptr;
if (!gname) return false;
hb_codepoint_t gid = sid_to_glyph (gname->sid);
if (!gid && gname->sid) return false;
@@ -1347,9 +1429,7 @@ struct cff1
HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
private:
struct gname_t
@@ -1361,7 +1441,7 @@ struct cff1
{
const gname_t *a = (const gname_t *)a_;
const gname_t *b = (const gname_t *)b_;
- int minlen = hb_min (a->name.length, b->name.length);
+ unsigned minlen = hb_min (a->name.length, b->name.length);
int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
if (ret) return ret;
return a->name.length - b->name.length;
@@ -1370,7 +1450,7 @@ struct cff1
int cmp (const gname_t &a) const { return cmp (&a, this); }
};
- hb_sorted_vector_t<gname_t> glyph_names;
+ mutable hb_atomic_ptr_t<hb_sorted_vector_t<gname_t>> glyph_names;
typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
index 879b7cdb23..50c76daf93 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
@@ -36,9 +36,8 @@ using namespace CFF;
struct cff2_extents_param_t
{
- void init ()
+ cff2_extents_param_t ()
{
- path_open = false;
min_x.set_int (INT_MAX);
min_y.set_int (INT_MAX);
max_x.set_int (INT_MIN);
@@ -57,22 +56,22 @@ struct cff2_extents_param_t
if (pt.y > max_y) max_y = pt.y;
}
- bool path_open;
+ bool path_open = false;
number_t min_x;
number_t min_y;
number_t max_x;
number_t max_y;
};
-struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t, cff2_extents_param_t>
+struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_cs_interp_env_t<number_t>, cff2_extents_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt)
{
param.end_path ();
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1)
{
if (!param.is_path_open ())
{
@@ -83,7 +82,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
param.update_bounds (env.get_pt ());
}
- static void curve (cff2_cs_interp_env_t &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
if (!param.is_path_open ())
{
@@ -98,7 +97,7 @@ struct cff2_path_procs_extents_t : path_procs_t<cff2_path_procs_extents_t, cff2_
}
};
-struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, cff2_path_procs_extents_t> {};
+struct cff2_cs_opset_extents_t : cff2_cs_opset_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t, cff2_path_procs_extents_t> {};
bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
hb_codepoint_t glyph,
@@ -112,11 +111,10 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_extents_t, cff2_extents_param_t, number_t> interp (env);
cff2_extents_param_t param;
- param.init ();
if (unlikely (!interp.interpret (param))) return false;
if (param.min_x >= param.max_x)
@@ -143,57 +141,56 @@ bool OT::cff2::accelerator_t::get_extents (hb_font_t *font,
return true;
}
-#ifdef HB_EXPERIMENTAL_API
struct cff2_path_param_t
{
- cff2_path_param_t (hb_font_t *font_, draw_helper_t &draw_helper_)
+ cff2_path_param_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
{
- draw_helper = &draw_helper_;
+ draw_session = &draw_session_;
font = font_;
}
void move_to (const point_t &p)
- { draw_helper->move_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->move_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void line_to (const point_t &p)
- { draw_helper->line_to (font->em_scalef_x (p.x.to_real ()), font->em_scalef_y (p.y.to_real ())); }
+ { draw_session->line_to (font->em_fscalef_x (p.x.to_real ()), font->em_fscalef_y (p.y.to_real ())); }
void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
{
- draw_helper->cubic_to (font->em_scalef_x (p1.x.to_real ()), font->em_scalef_y (p1.y.to_real ()),
- font->em_scalef_x (p2.x.to_real ()), font->em_scalef_y (p2.y.to_real ()),
- font->em_scalef_x (p3.x.to_real ()), font->em_scalef_y (p3.y.to_real ()));
+ draw_session->cubic_to (font->em_fscalef_x (p1.x.to_real ()), font->em_fscalef_y (p1.y.to_real ()),
+ font->em_fscalef_x (p2.x.to_real ()), font->em_fscalef_y (p2.y.to_real ()),
+ font->em_fscalef_x (p3.x.to_real ()), font->em_fscalef_y (p3.y.to_real ()));
}
protected:
- draw_helper_t *draw_helper;
+ hb_draw_session_t *draw_session;
hb_font_t *font;
};
-struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t, cff2_path_param_t>
+struct cff2_path_procs_path_t : path_procs_t<cff2_path_procs_path_t, cff2_cs_interp_env_t<number_t>, cff2_path_param_t>
{
- static void moveto (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt)
+ static void moveto (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt)
{
param.move_to (pt);
env.moveto (pt);
}
- static void line (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1)
+ static void line (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1)
{
param.line_to (pt1);
env.moveto (pt1);
}
- static void curve (cff2_cs_interp_env_t &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
+ static void curve (cff2_cs_interp_env_t<number_t> &env, cff2_path_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
{
param.cubic_to (pt1, pt2, pt3);
env.moveto (pt3);
}
};
-struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, cff2_path_procs_path_t> {};
+struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t, cff2_path_procs_path_t> {};
-bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const
+bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
{
#ifdef HB_NO_OT_FONT_CFF
/* XXX Remove check when this code moves to .hh file. */
@@ -203,13 +200,12 @@ bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, d
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
unsigned int fd = fdSelect->get_fd (glyph);
- cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t> interp;
- const byte_str_t str = (*charStrings)[glyph];
- interp.env.init (str, *this, fd, font->coords, font->num_coords);
- cff2_path_param_t param (font, draw_helper);
+ const hb_ubytes_t str = (*charStrings)[glyph];
+ cff2_cs_interp_env_t<number_t> env (str, *this, fd, font->coords, font->num_coords);
+ cff2_cs_interpreter_t<cff2_cs_opset_path_t, cff2_path_param_t, number_t> interp (env);
+ cff2_path_param_t param (font, draw_session);
if (unlikely (!interp.interpret (param))) return false;
return true;
}
-#endif
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
index 6e1b01c8fe..746160dc8e 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cff2-table.hh
@@ -247,12 +247,8 @@ typedef cff2_private_dict_values_base_t<num_dict_val_t> cff2_private_dict_values
struct cff2_priv_dict_interp_env_t : num_interp_env_t
{
- void init (const byte_str_t &str)
- {
- num_interp_env_t::init (str);
- ivs = 0;
- seen_vsindex = false;
- }
+ cff2_priv_dict_interp_env_t (const hb_ubytes_t &str) :
+ num_interp_env_t (str) {}
void process_vsindex ()
{
@@ -267,8 +263,8 @@ struct cff2_priv_dict_interp_env_t : num_interp_env_t
void set_ivs (unsigned int ivs_) { ivs = ivs_; }
protected:
- unsigned int ivs;
- bool seen_vsindex;
+ unsigned int ivs = 0;
+ bool seen_vsindex = false;
};
struct cff2_private_dict_opset_t : dict_opset_t
@@ -415,10 +411,10 @@ struct cff2
goto fail;
{ /* parse top dict */
- byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
+ hb_ubytes_t topDictStr = (cff2 + cff2->topDict).as_ubytes (cff2->topDictSize);
if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
- cff2_top_dict_interpreter_t top_interp;
- top_interp.env.init (topDictStr);
+ num_interp_env_t env (topDictStr);
+ cff2_top_dict_interpreter_t top_interp (env);
topDict.init ();
if (unlikely (!top_interp.interpret (topDict))) goto fail;
}
@@ -447,20 +443,20 @@ struct cff2
/* parse font dicts and gather private dicts */
for (unsigned int i = 0; i < fdCount; i++)
{
- const byte_str_t fontDictStr = (*fdArray)[i];
+ const hb_ubytes_t fontDictStr = (*fdArray)[i];
if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
cff2_font_dict_values_t *font;
- cff2_font_dict_interpreter_t font_interp;
- font_interp.env.init (fontDictStr);
+ num_interp_env_t env (fontDictStr);
+ cff2_font_dict_interpreter_t font_interp (env);
font = fontDicts.push ();
if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
font->init ();
if (unlikely (!font_interp.interpret (*font))) goto fail;
- const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
+ const hb_ubytes_t privDictStr = StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset).as_ubytes (font->privateDictInfo.size);
if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
- dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp;
- priv_interp.env.init(privDictStr);
+ cff2_priv_dict_interp_env_t env2 (privDictStr);
+ dict_interpreter_t<PRIVOPSET, PRIVDICTVAL, cff2_priv_dict_interp_env_t> priv_interp (env2);
privateDicts[i].init ();
if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
@@ -515,9 +511,7 @@ struct cff2
HB_INTERNAL bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const;
-#ifdef HB_EXPERIMENTAL_API
- HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
-#endif
+ HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
};
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
diff --git a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
index fde57cdc5b..09c9fe93f3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
@@ -27,6 +27,8 @@
#ifndef HB_OT_CMAP_TABLE_HH
#define HB_OT_CMAP_TABLE_HH
+#include "hb-ot-os2-table.hh"
+#include "hb-ot-shaper-arabic-pua.hh"
#include "hb-open-type.hh"
#include "hb-set.hh"
@@ -44,7 +46,7 @@ struct CmapSubtableFormat0
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = codepoint < 256 ? glyphIdArray[codepoint] : 0;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -109,22 +111,26 @@ struct CmapSubtableFormat4
while (it) {
// Start a new range
- start_cp = (*it).first;
- prev_run_start_cp = (*it).first;
- run_start_cp = (*it).first;
- end_cp = (*it).first;
- last_gid = (*it).second;
- run_length = 1;
- prev_delta = 0;
-
- delta = (*it).second - (*it).first;
+ {
+ const auto& pair = *it;
+ start_cp = pair.first;
+ prev_run_start_cp = start_cp;
+ run_start_cp = start_cp;
+ end_cp = start_cp;
+ last_gid = pair.second;
+ run_length = 1;
+ prev_delta = 0;
+ }
+
+ delta = last_gid - start_cp;
mode = FIRST_SUB_RANGE;
it++;
while (it) {
// Process range
- hb_codepoint_t next_cp = (*it).first;
- hb_codepoint_t next_gid = (*it).second;
+ const auto& pair = *it;
+ hb_codepoint_t next_cp = pair.first;
+ hb_codepoint_t next_gid = pair.second;
if (next_cp != end_cp + 1) {
// Current range is over, stop processing.
break;
@@ -282,23 +288,22 @@ struct CmapSubtableFormat4
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_iterator (Iterator))>
HBUINT16* serialize_rangeoffset_glyid (hb_serialize_context_t *c,
- Iterator it,
+ Iterator it,
HBUINT16 *endCode,
HBUINT16 *startCode,
HBINT16 *idDelta,
unsigned segcount)
{
- hb_hashmap_t<hb_codepoint_t, hb_codepoint_t> cp_to_gid;
- + it | hb_sink (cp_to_gid);
+ hb_map_t cp_to_gid { it };
HBUINT16 *idRangeOffset = c->allocate_size<HBUINT16> (HBUINT16::static_size * segcount);
if (unlikely (!c->check_success (idRangeOffset))) return nullptr;
if (unlikely ((char *)idRangeOffset - (char *)idDelta != (int) segcount * (int) HBINT16::static_size)) return nullptr;
for (unsigned i : + hb_range (segcount)
- | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
+ | hb_filter ([&] (const unsigned _) { return idDelta[_] == 0; }))
{
idRangeOffset[i] = 2 * (c->start_embed<HBUINT16> () - idRangeOffset - i);
for (hb_codepoint_t cp = startCode[i]; cp <= endCode[i]; cp++)
@@ -323,22 +328,31 @@ struct CmapSubtableFormat4
{ return _.first <= 0xFFFF; })
;
- if (format4_iter.len () == 0) return;
+ if (!format4_iter) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
this->format = 4;
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> cp_to_gid {
+ format4_iter
+ };
+
//serialize endCode[], startCode[], idDelta[]
HBUINT16* endCode = c->start_embed<HBUINT16> ();
- unsigned segcount = serialize_find_segcount (format4_iter);
- if (unlikely (!serialize_start_end_delta_arrays (c, format4_iter, segcount)))
+ unsigned segcount = serialize_find_segcount (cp_to_gid.iter());
+ if (unlikely (!serialize_start_end_delta_arrays (c, cp_to_gid.iter(), segcount)))
return;
HBUINT16 *startCode = endCode + segcount + 1;
HBINT16 *idDelta = ((HBINT16*)startCode) + segcount;
- HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c, format4_iter, endCode, startCode, idDelta, segcount);
+ HBUINT16 *idRangeOffset = serialize_rangeoffset_glyid (c,
+ cp_to_gid.iter (),
+ endCode,
+ startCode,
+ idDelta,
+ segcount);
if (unlikely (!c->check_success (idRangeOffset))) return;
this->length = c->length () - table_initpos;
@@ -401,7 +415,7 @@ struct CmapSubtableFormat4
2,
_hb_cmp_method<hb_codepoint_t, CustomRange, unsigned>,
this->segCount + 1);
- if (!found)
+ if (unlikely (!found))
return false;
unsigned int i = found - endCount;
@@ -421,7 +435,7 @@ struct CmapSubtableFormat4
gid += this->idDelta[i];
}
gid &= 0xFFFFu;
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -440,14 +454,14 @@ struct CmapSubtableFormat4
hb_codepoint_t start = this->startCount[i];
hb_codepoint_t end = this->endCount[i];
unsigned int rangeOffset = this->idRangeOffset[i];
+ out->add_range(start, end);
if (rangeOffset == 0)
{
for (hb_codepoint_t codepoint = start; codepoint <= end; codepoint++)
{
hb_codepoint_t gid = (codepoint + this->idDelta[i]) & 0xFFFFu;
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
else
@@ -456,11 +470,13 @@ struct CmapSubtableFormat4
{
unsigned int index = rangeOffset / 2 + (codepoint - this->startCount[i]) + i - this->segCount;
if (unlikely (index >= this->glyphIdArrayLength))
+ {
+ out->del_range (codepoint, end);
break;
+ }
hb_codepoint_t gid = this->glyphIdArray[index];
if (unlikely (!gid))
- continue;
- out->add (codepoint);
+ out->del(codepoint);
}
}
}
@@ -469,6 +485,8 @@ struct CmapSubtableFormat4
void collect_mapping (hb_set_t *unicodes, /* OUT */
hb_map_t *mapping /* OUT */) const
{
+ // TODO(grieger): optimize similar to collect_unicodes
+ // (ie. use add_range())
unsigned count = this->segCount;
if (count && this->startCount[count - 1] == 0xFFFFu)
count--; /* Skip sentinel segment. */
@@ -620,7 +638,7 @@ struct CmapSubtableTrimmed
{
/* Rely on our implicit array bound-checking. */
hb_codepoint_t gid = glyphIdArray[codepoint - startCharCode];
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -674,7 +692,7 @@ struct CmapSubtableTrimmed
};
struct CmapSubtableFormat6 : CmapSubtableTrimmed<HBUINT16> {};
-struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32 > {};
+struct CmapSubtableFormat10 : CmapSubtableTrimmed<HBUINT32> {};
template <typename T>
struct CmapSubtableLongSegmented
@@ -684,7 +702,7 @@ struct CmapSubtableLongSegmented
bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
hb_codepoint_t gid = T::group_get_glyph (groups.bsearch (codepoint), codepoint);
- if (!gid)
+ if (unlikely (!gid))
return false;
*glyph = gid;
return true;
@@ -714,7 +732,7 @@ struct CmapSubtableLongSegmented
if (unlikely ((unsigned int) (gid + end - start) >= num_glyphs))
end = start + (hb_codepoint_t) num_glyphs - gid;
- out->add_range (start, end);
+ out->add_range (start, hb_min (end, 0x10FFFFu));
}
}
@@ -722,11 +740,19 @@ struct CmapSubtableLongSegmented
hb_map_t *mapping, /* OUT */
unsigned num_glyphs) const
{
+ hb_codepoint_t last_end = 0;
for (unsigned i = 0; i < this->groups.len; i++)
{
hb_codepoint_t start = this->groups[i].startCharCode;
hb_codepoint_t end = hb_min ((hb_codepoint_t) this->groups[i].endCharCode,
(hb_codepoint_t) HB_UNICODE_MAX);
+ if (unlikely (start > end || start < last_end)) {
+ // Range is not in order and is invalid, skip it.
+ continue;
+ }
+ last_end = end;
+
+
hb_codepoint_t gid = this->groups[i].glyphID;
if (!gid)
{
@@ -778,16 +804,16 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
void serialize (hb_serialize_context_t *c,
Iterator it)
{
- if (it.len () == 0) return;
+ if (!it) return;
unsigned table_initpos = c->length ();
if (unlikely (!c->extend_min (this))) return;
- hb_codepoint_t startCharCode = 0xFFFF, endCharCode = 0xFFFF;
+ hb_codepoint_t startCharCode = (hb_codepoint_t) -1, endCharCode = (hb_codepoint_t) -1;
hb_codepoint_t glyphID = 0;
for (const auto& _ : +it)
{
- if (startCharCode == 0xFFFF)
+ if (startCharCode == (hb_codepoint_t) -1)
{
startCharCode = _.first;
endCharCode = _.first;
@@ -818,7 +844,7 @@ struct CmapSubtableFormat12 : CmapSubtableLongSegmented<CmapSubtableFormat12>
this->format = 12;
this->reserved = 0;
this->length = c->length () - table_initpos;
- this->groups.len = (this->length - min_size)/CmapSubtableLongGroup::static_size;
+ this->groups.len = (this->length - min_size) / CmapSubtableLongGroup::static_size;
}
static size_t get_sub_table_size (const hb_sorted_vector_t<CmapSubtableLongGroup> &groups_data)
@@ -883,7 +909,7 @@ struct DefaultUVS : SortedArray32Of<UnicodeValueRange>
hb_codepoint_t first = arrayZ[i].startUnicodeValue;
hb_codepoint_t last = hb_min ((hb_codepoint_t) (first + arrayZ[i].additionalCount),
(hb_codepoint_t) HB_UNICODE_MAX);
- out->add_range (first, last);
+ out->add_range (first, hb_min (last, 0x10FFFFu));
}
}
@@ -1448,6 +1474,51 @@ struct EncodingRecord
DEFINE_SIZE_STATIC (8);
};
+struct SubtableUnicodesCache {
+
+ private:
+ const void* base;
+ hb_hashmap_t<intptr_t, hb::unique_ptr<hb_set_t>> cached_unicodes;
+
+ public:
+ SubtableUnicodesCache(const void* cmap_base)
+ : base(cmap_base), cached_unicodes() {}
+
+ hb_set_t* set_for (const EncodingRecord* record)
+ {
+ if (!cached_unicodes.has ((intptr_t) record))
+ {
+ hb_set_t *s = hb_set_create ();
+ if (unlikely (s->in_error ()))
+ return hb_set_get_empty ();
+
+ (base+record->subtable).collect_unicodes (s);
+
+ if (unlikely (!cached_unicodes.set ((intptr_t) record, hb::unique_ptr<hb_set_t> {s})))
+ return hb_set_get_empty ();
+
+ return s;
+ }
+ return cached_unicodes.get ((intptr_t) record);
+ }
+
+};
+
+static inline uint_fast16_t
+_hb_symbol_pua_map (unsigned codepoint)
+{
+ if (codepoint <= 0x00FFu)
+ {
+ /* For symbol-encoded OpenType fonts, we duplicate the
+ * U+F000..F0FF range at U+0000..U+00FF. That's what
+ * Windows seems to do, and that's hinted about at:
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
+ * under "Non-Standard (Symbol) Fonts". */
+ return 0xF000u + codepoint;
+ }
+ return 0;
+}
+
struct cmap
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_cmap;
@@ -1467,6 +1538,7 @@ struct cmap
unsigned format4objidx = 0, format12objidx = 0, format14objidx = 0;
auto snap = c->snapshot ();
+ SubtableUnicodesCache unicodes_cache (base);
for (const EncodingRecord& _ : encodingrec_iter)
{
if (c->in_error ())
@@ -1475,12 +1547,11 @@ struct cmap
unsigned format = (base+_.subtable).u.format;
if (format != 4 && format != 12 && format != 14) continue;
- hb_set_t unicodes_set;
- (base+_.subtable).collect_unicodes (&unicodes_set);
+ hb_set_t* unicodes_set = unicodes_cache.set_for (&_);
if (!drop_format_4 && format == 4)
{
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 4u, base, plan, &format4objidx);
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 4u, base, plan, &format4objidx);
if (c->in_error () && c->only_overflow ())
{
// cmap4 overflowed, reset and retry serialization without format 4 subtables.
@@ -1495,8 +1566,8 @@ struct cmap
else if (format == 12)
{
- if (_can_drop (_, unicodes_set, base, + it | hb_map (hb_first), encodingrec_iter)) continue;
- c->copy (_, + it | hb_filter (unicodes_set, hb_first), 12u, base, plan, &format12objidx);
+ if (_can_drop (_, *unicodes_set, base, unicodes_cache, + it | hb_map (hb_first), encodingrec_iter)) continue;
+ c->copy (_, + it | hb_filter (*unicodes_set, hb_first), 12u, base, plan, &format12objidx);
}
else if (format == 14) c->copy (_, it, 14u, base, plan, &format14objidx);
}
@@ -1514,6 +1585,7 @@ struct cmap
bool _can_drop (const EncodingRecord& cmap12,
const hb_set_t& cmap12_unicodes,
const void* base,
+ SubtableUnicodesCache& unicodes_cache,
Iterator subset_unicodes,
EncodingRecordIterator encoding_records)
{
@@ -1544,11 +1616,10 @@ struct cmap
|| (base+_.subtable).get_language() != target_language)
continue;
- hb_set_t sibling_unicodes;
- (base+_.subtable).collect_unicodes (&sibling_unicodes);
+ hb_set_t* sibling_unicodes = unicodes_cache.set_for (&_);
auto cmap12 = + subset_unicodes | hb_filter (cmap12_unicodes);
- auto sibling = + subset_unicodes | hb_filter (sibling_unicodes);
+ auto sibling = + subset_unicodes | hb_filter (*sibling_unicodes);
for (; cmap12 && sibling; cmap12++, sibling++)
{
unsigned a = *cmap12;
@@ -1616,13 +1687,7 @@ struct cmap
if (unlikely (has_format12 && (!unicode_ucs4 && !ms_ucs4))) return_trace (false);
auto it =
- + hb_iter (c->plan->unicodes)
- | hb_map ([&] (hb_codepoint_t _)
- {
- hb_codepoint_t new_gid = HB_MAP_VALUE_INVALID;
- c->plan->new_gid_for_codepoint (_, &new_gid);
- return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, new_gid);
- })
+ + c->plan->unicode_to_new_gid_list.iter ()
| hb_filter ([&] (const hb_pair_t<hb_codepoint_t, hb_codepoint_t> _)
{ return (_.second != HB_MAP_VALUE_INVALID); })
;
@@ -1677,7 +1742,24 @@ struct cmap
this->get_glyph_data = subtable;
if (unlikely (symbol))
- this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable>;
+ {
+ switch ((unsigned) face->table.OS2->get_font_page ()) {
+ case OS2::font_page_t::FONT_PAGE_NONE:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_symbol_pua_map>;
+ break;
+#ifndef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ case OS2::font_page_t::FONT_PAGE_SIMP_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_simp_map>;
+ break;
+ case OS2::font_page_t::FONT_PAGE_TRAD_ARABIC:
+ this->get_glyph_funcZ = get_glyph_from_symbol<CmapSubtable, _hb_arabic_pua_trad_map>;
+ break;
+#endif
+ default:
+ this->get_glyph_funcZ = get_glyph_from<CmapSubtable>;
+ break;
+ }
+ }
else
{
switch (subtable->u.format) {
@@ -1759,6 +1841,7 @@ struct cmap
typedef bool (*hb_cmap_get_glyph_func_t) (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph);
+ typedef uint_fast16_t (*hb_pua_remap_func_t) (unsigned);
template <typename Type>
HB_INTERNAL static bool get_glyph_from (const void *obj,
@@ -1769,7 +1852,7 @@ struct cmap
return typed_obj->get_glyph (codepoint, glyph);
}
- template <typename Type>
+ template <typename Type, hb_pua_remap_func_t remap>
HB_INTERNAL static bool get_glyph_from_symbol (const void *obj,
hb_codepoint_t codepoint,
hb_codepoint_t *glyph)
@@ -1778,15 +1861,8 @@ struct cmap
if (likely (typed_obj->get_glyph (codepoint, glyph)))
return true;
- if (codepoint <= 0x00FFu)
- {
- /* For symbol-encoded OpenType fonts, we duplicate the
- * U+F000..F0FF range at U+0000..U+00FF. That's what
- * Windows seems to do, and that's hinted about at:
- * https://docs.microsoft.com/en-us/typography/opentype/spec/recom
- * under "Non-Standard (Symbol) Fonts". */
- return typed_obj->get_glyph (0xF000u + codepoint, glyph);
- }
+ if (hb_codepoint_t c = remap (codepoint))
+ return typed_obj->get_glyph (c, glyph);
return false;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
index dac755c02c..f01d383bdc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-colr-table.hh
@@ -145,7 +145,7 @@ struct BaseGlyphRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
public:
@@ -524,6 +524,7 @@ struct PaintSweepGradient
};
struct Paint;
+
// Paint a non-COLR glyph, filled as indicated by paint.
struct PaintGlyph
{
@@ -1152,6 +1153,8 @@ struct Paint
Variable<PaintSkewAroundCenter> paintformat31;
PaintComposite paintformat32;
} u;
+ public:
+ DEFINE_SIZE_MIN (2);
};
struct BaseGlyphPaintRecord
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
index a9deeba9a7..bcab77f79d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-cpal-table.hh
@@ -97,9 +97,10 @@ struct CPALV1Tail
c->push ();
for (const auto _ : colorLabels)
{
- if (!color_index_map->has (_)) continue;
+ const hb_codepoint_t *v;
+ if (!color_index_map->has (_, &v)) continue;
NameID new_color_idx;
- new_color_idx = color_index_map->get (_);
+ new_color_idx = *v;
if (!c->copy<NameID> (new_color_idx))
{
c->pop_discard ();
@@ -197,30 +198,38 @@ struct CPAL
public:
bool serialize (hb_serialize_context_t *c,
- const hb_array_t<const BGRAColor> &color_records,
const hb_array_t<const HBUINT16> &color_record_indices,
- const hb_map_t &color_record_index_map,
- const hb_set_t &retained_color_record_indices) const
+ const hb_array_t<const BGRAColor> &color_records,
+ const hb_vector_t<unsigned>& first_color_index_for_layer,
+ const hb_map_t& first_color_to_layer_index,
+ const hb_set_t &retained_color_indices) const
{
TRACE_SERIALIZE (this);
+ // TODO(grieger): limit total final size.
+
for (const auto idx : color_record_indices)
{
+ hb_codepoint_t layer_index = first_color_to_layer_index[idx];
+
HBUINT16 new_idx;
- if (idx == 0) new_idx = 0;
- else new_idx = color_record_index_map.get (idx);
+ new_idx = layer_index * retained_color_indices.get_population ();
if (!c->copy<HBUINT16> (new_idx)) return_trace (false);
}
c->push ();
- for (const auto _ : retained_color_record_indices.iter ())
+ for (unsigned first_color_index : first_color_index_for_layer)
{
- if (!c->copy<BGRAColor> (color_records[_]))
+ for (hb_codepoint_t color_index : retained_color_indices)
{
- c->pop_discard ();
- return_trace (false);
+ if (!c->copy<BGRAColor> (color_records[first_color_index + color_index]))
+ {
+ c->pop_discard ();
+ return_trace (false);
+ }
}
}
+
c->add_link (colorRecordsZ, c->pop_pack ());
return_trace (true);
}
@@ -228,6 +237,8 @@ struct CPAL
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
+ if (!numPalettes) return_trace (false);
+
const hb_map_t *color_index_map = c->plan->colr_palettes;
if (color_index_map->is_empty ()) return_trace (false);
@@ -242,30 +253,34 @@ struct CPAL
auto *out = c->serializer->start_embed (*this);
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
out->version = version;
out->numColors = retained_color_indices.get_population ();
out->numPalettes = numPalettes;
- const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
- hb_map_t color_record_index_map;
- hb_set_t retained_color_record_indices;
+ hb_vector_t<unsigned> first_color_index_for_layer;
+ hb_map_t first_color_to_layer_index;
- unsigned record_count = 0;
+ const hb_array_t<const HBUINT16> colorRecordIndices = colorRecordIndicesZ.as_array (numPalettes);
for (const auto first_color_record_idx : colorRecordIndices)
{
- for (unsigned retained_color_idx : retained_color_indices.iter ())
- {
- unsigned color_record_idx = first_color_record_idx + retained_color_idx;
- if (color_record_index_map.has (color_record_idx)) continue;
- color_record_index_map.set (color_record_idx, record_count);
- retained_color_record_indices.add (color_record_idx);
- record_count++;
- }
+ if (first_color_to_layer_index.has (first_color_record_idx)) continue;
+
+ first_color_index_for_layer.push (first_color_record_idx);
+ first_color_to_layer_index.set (first_color_record_idx,
+ first_color_index_for_layer.length - 1);
}
- out->numColorRecords = record_count;
+ out->numColorRecords = first_color_index_for_layer.length
+ * retained_color_indices.get_population ();
+
const hb_array_t<const BGRAColor> color_records = (this+colorRecordsZ).as_array (numColorRecords);
- if (!out->serialize (c->serializer, color_records, colorRecordIndices, color_record_index_map, retained_color_record_indices))
+ if (!out->serialize (c->serializer,
+ colorRecordIndices,
+ color_records,
+ first_color_index_for_layer,
+ first_color_to_layer_index,
+ retained_color_indices))
return_trace (false);
if (version == 1)
diff --git a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
index 9741ebd450..d0e2235fb2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-color-sbix-table.hh
@@ -298,6 +298,12 @@ struct sbix
const PNGHeader &png = *blob->as<PNGHeader>();
+ if (png.IHDR.height >= 65536 || png.IHDR.width >= 65536)
+ {
+ hb_blob_destroy (blob);
+ return false;
+ }
+
extents->x_bearing = x_offset;
extents->y_bearing = png.IHDR.height + y_offset;
extents->width = png.IHDR.width;
diff --git a/thirdparty/harfbuzz/src/hb-ot-color.cc b/thirdparty/harfbuzz/src/hb-ot-color.cc
index 16077765bd..a9ae013682 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-color.cc
@@ -61,7 +61,7 @@
*
* Tests whether a face includes a `CPAL` color-palette table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -192,7 +192,7 @@ hb_ot_color_palette_get_colors (hb_face_t *face,
*
* Tests whether a face includes any `COLR` color layers.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
@@ -239,7 +239,7 @@ hb_ot_color_glyph_get_layers (hb_face_t *face,
*
* Tests whether a face includes any `SVG` glyph images.
*
- * Return value: %true if data found, %false otherwise.
+ * Return value: `true` if data found, `false` otherwise.
*
* Since: 2.1.0
*/
@@ -279,7 +279,7 @@ hb_ot_color_glyph_reference_svg (hb_face_t *face, hb_codepoint_t glyph)
*
* Tests whether a face has PNG glyph images (either in `CBDT` or `sbix` tables).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.1.0
*/
diff --git a/thirdparty/harfbuzz/src/hb-ot-color.h b/thirdparty/harfbuzz/src/hb-ot-color.h
index c23ce4de44..d11e07e230 100644
--- a/thirdparty/harfbuzz/src/hb-ot-color.h
+++ b/thirdparty/harfbuzz/src/hb-ot-color.h
@@ -102,6 +102,10 @@ hb_ot_color_has_layers (hb_face_t *face);
*
* Pairs of glyph and color index.
*
+ * A color index of 0xFFFF does not refer to a palette
+ * color, but indicates that the foreground color should
+ * be used.
+ *
* Since: 2.1.0
**/
typedef struct hb_ot_color_layer_t {
diff --git a/thirdparty/harfbuzz/src/hb-ot-deprecated.h b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
index ce6b6fef11..5192ff73e3 100644
--- a/thirdparty/harfbuzz/src/hb-ot-deprecated.h
+++ b/thirdparty/harfbuzz/src/hb-ot-deprecated.h
@@ -50,6 +50,21 @@ HB_BEGIN_DECLS
*/
#define HB_MATH_GLYPH_PART_FLAG_EXTENDER HB_OT_MATH_GLYPH_PART_FLAG_EXTENDER
+/* https://github.com/harfbuzz/harfbuzz/pull/3417 */
+/**
+ * HB_OT_MATH_SCRIPT:
+ *
+ * Use #HB_SCRIPT_MATH or #HB_OT_TAG_MATH_SCRIPT instead.
+ *
+ * <note>Previous versions of this documentation recommended passing
+ * #HB_OT_MATH_SCRIPT to hb_buffer_set_script() to enable math shaping, but this
+ * usage is no longer supported. Use #HB_SCRIPT_MATH instead.</note>
+ *
+ * Since: 1.3.3
+ * Deprecated: 3.4.0
+ */
+#define HB_OT_MATH_SCRIPT HB_OT_TAG_MATH_SCRIPT
+
/* Like hb_ot_layout_table_find_script, but takes zero-terminated array of scripts to test */
HB_EXTERN HB_DEPRECATED_FOR (hb_ot_layout_table_select_script) hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
index eff09838af..c05034b3bb 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face-table-list.hh
@@ -32,6 +32,11 @@
#define HB_OT_FACE_TABLE_LIST_HH
#endif /* HB_OT_FACE_TABLE_LIST_HH */ /* Dummy header guards */
+#ifndef HB_OT_CORE_TABLE
+#define HB_OT_CORE_TABLE(Namespace, Type) HB_OT_TABLE (Namespace, Type)
+#define _HB_OT_CORE_TABLE_UNDEF
+#endif
+
#ifndef HB_OT_ACCELERATOR
#define HB_OT_ACCELERATOR(Namespace, Type) HB_OT_TABLE (Namespace, Type)
#define _HB_OT_ACCELERATOR_UNDEF
@@ -46,7 +51,8 @@
/* OpenType fundamentals. */
-HB_OT_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, head)
+HB_OT_CORE_TABLE (OT, maxp)
#if !defined(HB_NO_FACE_COLLECT_UNICODES) || !defined(HB_NO_OT_FONT)
HB_OT_ACCELERATOR (OT, cmap)
#endif
@@ -74,6 +80,7 @@ HB_OT_TABLE (OT, VORG)
#endif
/* TrueType outlines. */
+HB_OT_CORE_TABLE (OT, loca) // Also used to determine number of glyphs
HB_OT_ACCELERATOR (OT, glyf)
/* CFF outlines. */
@@ -138,3 +145,7 @@ HB_OT_TABLE (OT, MATH)
#ifdef _HB_OT_ACCELERATOR_UNDEF
#undef HB_OT_ACCELERATOR
#endif
+
+#ifdef _HB_OT_CORE_TABLE_UNDEF
+#undef HB_OT_CORE_TABLE
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-face.hh b/thirdparty/harfbuzz/src/hb-ot-face.hh
index e24d380bca..415dae8e20 100644
--- a/thirdparty/harfbuzz/src/hb-ot-face.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-face.hh
@@ -63,10 +63,13 @@ struct hb_ot_face_t
hb_face_t *face; /* MUST be JUST before the lazy loaders. */
#define HB_OT_TABLE(Namespace, Type) \
hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
+#define HB_OT_CORE_TABLE(Namespace, Type) \
+ hb_table_lazy_loader_t<Namespace::Type, HB_OT_TABLE_ORDER (Namespace, Type), true> Type;
#define HB_OT_ACCELERATOR(Namespace, Type) \
hb_face_lazy_loader_t<Namespace::Type##_accelerator_t, HB_OT_TABLE_ORDER (Namespace, Type)> Type;
#include "hb-ot-face-table-list.hh"
#undef HB_OT_ACCELERATOR
+#undef HB_OT_CORE_TABLE
#undef HB_OT_TABLE
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-font.cc b/thirdparty/harfbuzz/src/hb-ot-font.cc
index 9f0359a773..3f13b9994a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-font.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-font.cc
@@ -30,6 +30,7 @@
#include "hb-ot.h"
+#include "hb-cache.hh"
#include "hb-font.hh"
#include "hb-machinery.hh"
#include "hb-ot-face.hh"
@@ -58,6 +59,41 @@
* never need to call these functions directly.
**/
+struct hb_ot_font_t
+{
+ const hb_ot_face_t *ot_face;
+
+ /* h_advance caching */
+ mutable hb_atomic_int_t cached_coords_serial;
+ mutable hb_atomic_ptr_t<hb_advance_cache_t> advance_cache;
+};
+
+static hb_ot_font_t *
+_hb_ot_font_create (hb_font_t *font)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) hb_calloc (1, sizeof (hb_ot_font_t));
+ if (unlikely (!ot_font))
+ return nullptr;
+
+ ot_font->ot_face = &font->face->table;
+
+ return ot_font;
+}
+
+static void
+_hb_ot_font_destroy (void *font_data)
+{
+ hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
+
+ auto *cache = ot_font->advance_cache.get_relaxed ();
+ if (cache)
+ {
+ cache->fini ();
+ hb_free (cache);
+ }
+
+ hb_free (ot_font);
+}
static hb_bool_t
hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
@@ -66,7 +102,8 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyph (unicode, glyph);
}
@@ -80,7 +117,8 @@ hb_ot_get_nominal_glyphs (hb_font_t *font HB_UNUSED,
unsigned int glyph_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_nominal_glyphs (count,
first_unicode, unicode_stride,
first_glyph, glyph_stride);
@@ -94,7 +132,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
return ot_face->cmap->get_variation_glyph (unicode, variation_selector, glyph);
}
@@ -107,15 +146,83 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
- for (unsigned int i = 0; i < count; i++)
+#ifndef HB_NO_VAR
+ const OT::HVAR &HVAR = *hmtx.var_table;
+ const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords * count >= 128 ? varStore.create_cache () : nullptr;
+
+ bool use_cache = font->num_coords;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+ bool use_cache = false;
+#endif
+
+ hb_advance_cache_t *cache = nullptr;
+ if (use_cache)
+ {
+ retry:
+ cache = ot_font->advance_cache.get ();
+ if (unlikely (!cache))
+ {
+ cache = (hb_advance_cache_t *) hb_malloc (sizeof (hb_advance_cache_t));
+ if (unlikely (!cache))
+ {
+ use_cache = false;
+ goto out;
+ }
+
+ cache->init ();
+ if (unlikely (!ot_font->advance_cache.cmpexch (nullptr, cache)))
+ {
+ hb_free (cache);
+ goto retry;
+ }
+ ot_font->cached_coords_serial.set (font->serial_coords);
+ }
+ }
+ out:
+
+ if (!use_cache)
{
- *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+ }
+ else
+ { /* Use cache. */
+ if (ot_font->cached_coords_serial.get () != (int) font->serial_coords)
+ {
+ ot_font->advance_cache->init ();
+ ot_font->cached_coords_serial.set (font->serial_coords);
+ }
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ hb_position_t v;
+ unsigned cv;
+ if (ot_font->advance_cache->get (*first_glyph, &cv))
+ v = cv;
+ else
+ {
+ v = hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
+ ot_font->advance_cache->set (*first_glyph, v);
+ }
+ *first_advance = font->em_scale_x (v);
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
}
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
}
#ifndef HB_NO_VERTICAL
@@ -128,14 +235,43 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
unsigned advance_stride,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- for (unsigned int i = 0; i < count; i++)
+ if (vmtx.has_data ())
{
- *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font));
- first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
- first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+#ifndef HB_NO_VAR
+ const OT::VVAR &VVAR = *vmtx.var_table;
+ const OT::VariationStore &varStore = &VVAR + VVAR.varStore;
+ OT::VariationStore::cache_t *varStore_cache = font->num_coords ? varStore.create_cache () : nullptr;
+#else
+ OT::VariationStore::cache_t *varStore_cache = nullptr;
+#endif
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
+
+#ifndef HB_NO_VAR
+ OT::VariationStore::destroy_cache (varStore_cache);
+#endif
+ }
+ else
+ {
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = -(font_extents.ascender - font_extents.descender);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ *first_advance = advance;
+ first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
+ first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
+ }
}
}
#endif
@@ -149,14 +285,26 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
hb_position_t *y,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
*x = font->get_glyph_h_advance (glyph) / 2;
const OT::VORG &VORG = *ot_face->VORG;
if (VORG.has_data ())
{
- *y = font->em_scale_y (VORG.get_y_origin (glyph));
+ float delta = 0;
+
+#ifndef HB_NO_VAR
+ const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
+ const OT::VVAR &VVAR = *vmtx.var_table;
+ if (font->num_coords)
+ VVAR.get_vorg_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ &delta);
+#endif
+
+ *y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
return true;
}
@@ -164,8 +312,18 @@ hb_ot_get_glyph_v_origin (hb_font_t *font,
if (ot_face->glyf->get_extents (font, glyph, &extents))
{
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
- hb_position_t tsb = vmtx.get_side_bearing (font, glyph);
- *y = extents.y_bearing + font->em_scale_y (tsb);
+ int tsb = 0;
+ if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
+ {
+ *y = extents.y_bearing + font->em_scale_y (tsb);
+ return true;
+ }
+
+ hb_font_extents_t font_extents;
+ font->get_h_extents_with_fallback (&font_extents);
+ hb_position_t advance = font_extents.ascender - font_extents.descender;
+ int diff = advance - -extents.height;
+ *y = extents.y_bearing + (diff >> 1);
return true;
}
@@ -184,7 +342,8 @@ hb_ot_get_glyph_extents (hb_font_t *font,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
@@ -210,7 +369,9 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
+
if (ot_face->post->get_glyph_name (glyph, name, size)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_name (glyph, name, size)) return true;
@@ -224,7 +385,9 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
- const hb_ot_face_t *ot_face = (const hb_ot_face_t *) font_data;
+ const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
+ const hb_ot_face_t *ot_face = ot_font->ot_face;
+
if (ot_face->post->get_glyph_from_name (name, len, glyph)) return true;
#ifndef HB_NO_OT_FONT_CFF
if (ot_face->cff1->get_glyph_from_name (name, len, glyph)) return true;
@@ -257,6 +420,23 @@ hb_ot_get_font_v_extents (hb_font_t *font,
}
#endif
+#ifndef HB_NO_DRAW
+static void
+hb_ot_get_glyph_shape (hb_font_t *font,
+ void *font_data HB_UNUSED,
+ hb_codepoint_t glyph,
+ hb_draw_funcs_t *draw_funcs, void *draw_data,
+ void *user_data)
+{
+ hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
+ if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
+#ifndef HB_NO_CFF
+ if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
+ if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
+#endif
+}
+#endif
+
static inline void free_static_ot_funcs ();
static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t>
@@ -279,6 +459,10 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
#endif
+#ifndef HB_NO_DRAW
+ hb_font_funcs_set_glyph_shape_func (funcs, hb_ot_get_glyph_shape, nullptr, nullptr);
+#endif
+
hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, nullptr, nullptr);
//hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, nullptr, nullptr);
@@ -319,23 +503,28 @@ _hb_ot_get_font_funcs ()
void
hb_ot_font_set_funcs (hb_font_t *font)
{
+ hb_ot_font_t *ot_font = _hb_ot_font_create (font);
+ if (unlikely (!ot_font))
+ return;
+
hb_font_set_funcs (font,
_hb_ot_get_font_funcs (),
- &font->face->table,
- nullptr);
+ ot_font,
+ _hb_ot_font_destroy);
}
#ifndef HB_NO_VAR
-int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
+ int *lsb)
{
- return font->face->table.glyf->get_side_bearing_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
}
unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
{
- return font->face->table.glyf->get_advance_var (font, glyph, is_vertical);
+ return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
index 87a7d800c1..c32ff7636d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-glyf-table.hh
@@ -30,1334 +30,6 @@
#ifndef HB_OT_GLYF_TABLE_HH
#define HB_OT_GLYF_TABLE_HH
-#include "hb-open-type.hh"
-#include "hb-ot-head-table.hh"
-#include "hb-ot-hmtx-table.hh"
-#include "hb-ot-var-gvar-table.hh"
-#include "hb-draw.hh"
-
-namespace OT {
-
-
-/*
- * loca -- Index to Location
- * https://docs.microsoft.com/en-us/typography/opentype/spec/loca
- */
-#define HB_OT_TAG_loca HB_TAG('l','o','c','a')
-
-#ifndef HB_MAX_COMPOSITE_OPERATIONS
-#define HB_MAX_COMPOSITE_OPERATIONS 100000
-#endif
-
-
-struct loca
-{
- friend struct glyf;
-
- static constexpr hb_tag_t tableTag = HB_OT_TAG_loca;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- return_trace (true);
- }
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Location data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-
-/*
- * glyf -- TrueType Glyph Data
- * https://docs.microsoft.com/en-us/typography/opentype/spec/glyf
- */
-#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-
-
-struct glyf
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
-
- bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
- {
- TRACE_SANITIZE (this);
- /* Runtime checks as eager sanitizing each glyph is costy */
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_source_of (Iterator, unsigned int))>
- static bool
- _add_loca_and_head (hb_subset_plan_t * plan, Iterator padded_offsets, bool use_short_loca)
- {
- unsigned num_offsets = padded_offsets.len () + 1;
- unsigned entry_size = use_short_loca ? 2 : 4;
- char *loca_prime_data = (char *) hb_calloc (entry_size, num_offsets);
-
- if (unlikely (!loca_prime_data)) return false;
-
- DEBUG_MSG (SUBSET, nullptr, "loca entry_size %d num_offsets %d size %d",
- entry_size, num_offsets, entry_size * num_offsets);
-
- if (use_short_loca)
- _write_loca (padded_offsets, 1, hb_array ((HBUINT16 *) loca_prime_data, num_offsets));
- else
- _write_loca (padded_offsets, 0, hb_array ((HBUINT32 *) loca_prime_data, num_offsets));
-
- hb_blob_t *loca_blob = hb_blob_create (loca_prime_data,
- entry_size * num_offsets,
- HB_MEMORY_MODE_WRITABLE,
- loca_prime_data,
- hb_free);
-
- bool result = plan->add_table (HB_OT_TAG_loca, loca_blob)
- && _add_head_and_set_loca_version (plan, use_short_loca);
-
- hb_blob_destroy (loca_blob);
- return result;
- }
-
- template<typename IteratorIn, typename IteratorOut,
- hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
- hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
- static void
- _write_loca (IteratorIn it, unsigned right_shift, IteratorOut dest)
- {
- unsigned int offset = 0;
- dest << 0;
- + it
- | hb_map ([=, &offset] (unsigned int padded_size)
- {
- offset += padded_size;
- DEBUG_MSG (SUBSET, nullptr, "loca entry offset %d", offset);
- return offset >> right_shift;
- })
- | hb_sink (dest)
- ;
- }
-
- /* requires source of SubsetGlyph complains the identifier isn't declared */
- template <typename Iterator>
- bool serialize (hb_serialize_context_t *c,
- Iterator it,
- bool use_short_loca,
- const hb_subset_plan_t *plan)
- {
- TRACE_SERIALIZE (this);
- unsigned init_len = c->length ();
- for (const auto &_ : it) _.serialize (c, use_short_loca, plan);
-
- /* As a special case when all glyph in the font are empty, add a zero byte
- * to the table, so that OTS doesn’t reject it, and to make the table work
- * on Windows as well.
- * See https://github.com/khaledhosny/ots/issues/52 */
- if (init_len == c->length ())
- {
- HBUINT8 empty_byte;
- empty_byte = 0;
- c->copy (empty_byte);
- }
- return_trace (true);
- }
-
- /* Byte region(s) per glyph to output
- unpadded, hints removed if so requested
- If we fail to process a glyph we produce an empty (0-length) glyph */
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- glyf *glyf_prime = c->serializer->start_embed <glyf> ();
- if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
-
- hb_vector_t<SubsetGlyph> glyphs;
- _populate_subset_glyphs (c->plan, &glyphs);
-
- auto padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::padded_size)
- ;
-
- unsigned max_offset = + padded_offsets | hb_reduce (hb_add, 0);
- bool use_short_loca = max_offset < 0x1FFFF;
-
-
- glyf_prime->serialize (c->serializer, hb_iter (glyphs), use_short_loca, c->plan);
- if (!use_short_loca) {
- padded_offsets =
- + hb_iter (glyphs)
- | hb_map (&SubsetGlyph::length)
- ;
- }
-
-
- if (unlikely (c->serializer->in_error ())) return_trace (false);
- return_trace (c->serializer->check_success (_add_loca_and_head (c->plan,
- padded_offsets,
- use_short_loca)));
- }
-
- template <typename SubsetGlyph>
- void
- _populate_subset_glyphs (const hb_subset_plan_t *plan,
- hb_vector_t<SubsetGlyph> *glyphs /* OUT */) const
- {
- OT::glyf::accelerator_t glyf (plan->source);
-
- + hb_range (plan->num_output_glyphs ())
- | hb_map ([&] (hb_codepoint_t new_gid)
- {
- SubsetGlyph subset_glyph = {0};
- subset_glyph.new_gid = new_gid;
-
- /* should never fail: all old gids should be mapped */
- if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
- return subset_glyph;
-
- if (new_gid == 0 &&
- !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
- subset_glyph.source_glyph = Glyph ();
- else
- subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- subset_glyph.drop_hints_bytes ();
- else
- subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
- return subset_glyph;
- })
- | hb_sink (glyphs)
- ;
- }
-
- static bool
- _add_head_and_set_loca_version (hb_subset_plan_t *plan, bool use_short_loca)
- {
- hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table<head> (plan->source);
- hb_blob_t *head_prime_blob = hb_blob_copy_writable_or_fail (head_blob);
- hb_blob_destroy (head_blob);
-
- if (unlikely (!head_prime_blob))
- return false;
-
- head *head_prime = (head *) hb_blob_get_data_writable (head_prime_blob, nullptr);
- head_prime->indexToLocFormat = use_short_loca ? 0 : 1;
- bool success = plan->add_table (HB_OT_TAG_head, head_prime_blob);
-
- hb_blob_destroy (head_prime_blob);
- return success;
- }
-
- struct CompositeGlyphChain
- {
- protected:
- enum composite_glyph_flag_t
- {
- ARG_1_AND_2_ARE_WORDS = 0x0001,
- ARGS_ARE_XY_VALUES = 0x0002,
- ROUND_XY_TO_GRID = 0x0004,
- WE_HAVE_A_SCALE = 0x0008,
- MORE_COMPONENTS = 0x0020,
- WE_HAVE_AN_X_AND_Y_SCALE = 0x0040,
- WE_HAVE_A_TWO_BY_TWO = 0x0080,
- WE_HAVE_INSTRUCTIONS = 0x0100,
- USE_MY_METRICS = 0x0200,
- OVERLAP_COMPOUND = 0x0400,
- SCALED_COMPONENT_OFFSET = 0x0800,
- UNSCALED_COMPONENT_OFFSET = 0x1000
- };
-
- public:
- unsigned int get_size () const
- {
- unsigned int size = min_size;
- /* arg1 and 2 are int16 */
- if (flags & ARG_1_AND_2_ARE_WORDS) size += 4;
- /* arg1 and 2 are int8 */
- else size += 2;
-
- /* One x 16 bit (scale) */
- if (flags & WE_HAVE_A_SCALE) size += 2;
- /* Two x 16 bit (xscale, yscale) */
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) size += 4;
- /* Four x 16 bit (xscale, scale01, scale10, yscale) */
- else if (flags & WE_HAVE_A_TWO_BY_TWO) size += 8;
-
- return size;
- }
-
- void set_glyph_index (hb_codepoint_t new_gid) { glyphIndex = new_gid; }
- hb_codepoint_t get_glyph_index () const { return glyphIndex; }
-
- void drop_instructions_flag () { flags = (uint16_t) flags & ~WE_HAVE_INSTRUCTIONS; }
- void set_overlaps_flag ()
- {
- flags = (uint16_t) flags | OVERLAP_COMPOUND;
- }
-
- bool has_instructions () const { return flags & WE_HAVE_INSTRUCTIONS; }
-
- bool has_more () const { return flags & MORE_COMPONENTS; }
- bool is_use_my_metrics () const { return flags & USE_MY_METRICS; }
- bool is_anchored () const { return !(flags & ARGS_ARE_XY_VALUES); }
- void get_anchor_points (unsigned int &point1, unsigned int &point2) const
- {
- const HBUINT8 *p = &StructAfter<const HBUINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- point1 = ((const HBUINT16 *) p)[0];
- point2 = ((const HBUINT16 *) p)[1];
- }
- else
- {
- point1 = p[0];
- point2 = p[1];
- }
- }
-
- void transform_points (contour_point_vector_t &points) const
- {
- float matrix[4];
- contour_point_t trans;
- if (get_transformation (matrix, trans))
- {
- if (scaled_offsets ())
- {
- points.translate (trans);
- points.transform (matrix);
- }
- else
- {
- points.transform (matrix);
- points.translate (trans);
- }
- }
- }
-
- protected:
- bool scaled_offsets () const
- { return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
-
- bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
- {
- matrix[0] = matrix[3] = 1.f;
- matrix[1] = matrix[2] = 0.f;
-
- int tx, ty;
- const HBINT8 *p = &StructAfter<const HBINT8> (glyphIndex);
- if (flags & ARG_1_AND_2_ARE_WORDS)
- {
- tx = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- ty = *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- else
- {
- tx = *p++;
- ty = *p++;
- }
- if (is_anchored ()) tx = ty = 0;
-
- trans.init ((float) tx, (float) ty);
-
- {
- const F2DOT14 *points = (const F2DOT14 *) p;
- if (flags & WE_HAVE_A_SCALE)
- {
- matrix[0] = matrix[3] = points[0].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
- {
- matrix[0] = points[0].to_float ();
- matrix[3] = points[1].to_float ();
- return true;
- }
- else if (flags & WE_HAVE_A_TWO_BY_TWO)
- {
- matrix[0] = points[0].to_float ();
- matrix[1] = points[1].to_float ();
- matrix[2] = points[2].to_float ();
- matrix[3] = points[3].to_float ();
- return true;
- }
- }
- return tx || ty;
- }
-
- protected:
- HBUINT16 flags;
- HBGlyphID16 glyphIndex;
- public:
- DEFINE_SIZE_MIN (4);
- };
-
- struct composite_iter_t : hb_iter_with_fallback_t<composite_iter_t, const CompositeGlyphChain &>
- {
- typedef const CompositeGlyphChain *__item_t__;
- composite_iter_t (hb_bytes_t glyph_, __item_t__ current_) :
- glyph (glyph_), current (nullptr), current_size (0)
- {
- set_next (current_);
- }
-
- composite_iter_t () : glyph (hb_bytes_t ()), current (nullptr), current_size (0) {}
-
- const CompositeGlyphChain &__item__ () const { return *current; }
- bool __more__ () const { return current; }
- void __next__ ()
- {
- if (!current->has_more ()) { current = nullptr; return; }
-
- set_next (&StructAtOffset<CompositeGlyphChain> (current, current_size));
- }
- bool operator != (const composite_iter_t& o) const
- { return glyph != o.glyph || current != o.current; }
-
-
- void set_next (const CompositeGlyphChain *composite)
- {
- if (!glyph.check_range (composite, CompositeGlyphChain::min_size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
- unsigned size = composite->get_size ();
- if (!glyph.check_range (composite, size))
- {
- current = nullptr;
- current_size = 0;
- return;
- }
-
- current = composite;
- current_size = size;
- }
-
- private:
- hb_bytes_t glyph;
- __item_t__ current;
- unsigned current_size;
- };
-
- enum phantom_point_index_t
- {
- PHANTOM_LEFT = 0,
- PHANTOM_RIGHT = 1,
- PHANTOM_TOP = 2,
- PHANTOM_BOTTOM = 3,
- PHANTOM_COUNT = 4
- };
-
- struct accelerator_t;
-
- struct Glyph
- {
- enum simple_glyph_flag_t
- {
- FLAG_ON_CURVE = 0x01,
- FLAG_X_SHORT = 0x02,
- FLAG_Y_SHORT = 0x04,
- FLAG_REPEAT = 0x08,
- FLAG_X_SAME = 0x10,
- FLAG_Y_SAME = 0x20,
- FLAG_OVERLAP_SIMPLE = 0x40,
- FLAG_RESERVED2 = 0x80
- };
-
- private:
- struct GlyphHeader
- {
- bool has_data () const { return numberOfContours; }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- /* Undocumented rasterizer behavior: shift glyph to the left by (lsb - xMin), i.e., xMin = lsb */
- /* extents->x_bearing = hb_min (glyph_header.xMin, glyph_header.xMax); */
- extents->x_bearing = font->em_scale_x (glyf_accelerator.hmtx->get_side_bearing (gid));
- extents->y_bearing = font->em_scale_y (hb_max (yMin, yMax));
- extents->width = font->em_scale_x (hb_max (xMin, xMax) - hb_min (xMin, xMax));
- extents->height = font->em_scale_y (hb_min (yMin, yMax) - hb_max (yMin, yMax));
-
- return true;
- }
-
- HBINT16 numberOfContours;
- /* If the number of contours is
- * greater than or equal to zero,
- * this is a simple glyph; if negative,
- * this is a composite glyph. */
- FWORD xMin; /* Minimum x for coordinate data. */
- FWORD yMin; /* Minimum y for coordinate data. */
- FWORD xMax; /* Maximum x for coordinate data. */
- FWORD yMax; /* Maximum y for coordinate data. */
- public:
- DEFINE_SIZE_STATIC (10);
- };
-
- struct SimpleGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- SimpleGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- unsigned int instruction_len_offset () const
- { return GlyphHeader::static_size + 2 * header.numberOfContours; }
-
- unsigned int length (unsigned int instruction_len) const
- { return instruction_len_offset () + 2 + instruction_len; }
-
- unsigned int instructions_length () const
- {
- unsigned int instruction_length_offset = instruction_len_offset ();
- if (unlikely (instruction_length_offset + 2 > bytes.length)) return 0;
-
- const HBUINT16 &instructionLength = StructAtOffset<HBUINT16> (&bytes, instruction_length_offset);
- /* Out of bounds of the current glyph */
- if (unlikely (length (instructionLength) > bytes.length)) return 0;
- return instructionLength;
- }
-
- const Glyph trim_padding () const
- {
- /* based on FontTools _g_l_y_f.py::trim */
- const uint8_t *glyph = (uint8_t*) bytes.arrayZ;
- const uint8_t *glyph_end = glyph + bytes.length;
- /* simple glyph w/contours, possibly trimmable */
- glyph += instruction_len_offset ();
-
- if (unlikely (glyph + 2 >= glyph_end)) return Glyph ();
- unsigned int num_coordinates = StructAtOffset<HBUINT16> (glyph - 2, 0) + 1;
- unsigned int num_instructions = StructAtOffset<HBUINT16> (glyph, 0);
-
- glyph += 2 + num_instructions;
-
- unsigned int coord_bytes = 0;
- unsigned int coords_with_flags = 0;
- while (glyph < glyph_end)
- {
- uint8_t flag = *glyph;
- glyph++;
-
- unsigned int repeat = 1;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (glyph >= glyph_end)) return Glyph ();
- repeat = *glyph + 1;
- glyph++;
- }
-
- unsigned int xBytes, yBytes;
- xBytes = yBytes = 0;
- if (flag & FLAG_X_SHORT) xBytes = 1;
- else if ((flag & FLAG_X_SAME) == 0) xBytes = 2;
-
- if (flag & FLAG_Y_SHORT) yBytes = 1;
- else if ((flag & FLAG_Y_SAME) == 0) yBytes = 2;
-
- coord_bytes += (xBytes + yBytes) * repeat;
- coords_with_flags += repeat;
- if (coords_with_flags >= num_coordinates) break;
- }
-
- if (unlikely (coords_with_flags != num_coordinates)) return Glyph ();
- return Glyph (bytes.sub_array (0, bytes.length + coord_bytes - (glyph_end - glyph)));
- }
-
- /* zero instruction length */
- void drop_hints ()
- {
- GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
- (HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- unsigned int instructions_len = instructions_length ();
- unsigned int glyph_length = length (instructions_len);
- dest_start = bytes.sub_array (0, glyph_length - instructions_len);
- dest_end = bytes.sub_array (glyph_length, bytes.length - glyph_length);
- }
-
- void set_overlaps_flag ()
- {
- if (unlikely (!header.numberOfContours)) return;
-
- unsigned flags_offset = length (instructions_length ());
- if (unlikely (flags_offset + 1 > bytes.length)) return;
-
- HBUINT8 &first_flag = (HBUINT8 &) StructAtOffset<HBUINT16> (&bytes, flags_offset);
- first_flag = (uint8_t) first_flag | FLAG_OVERLAP_SIMPLE;
- }
-
- static bool read_points (const HBUINT8 *&p /* IN/OUT */,
- contour_point_vector_t &points_ /* IN/OUT */,
- const hb_bytes_t &bytes,
- void (* setter) (contour_point_t &_, float v),
- const simple_glyph_flag_t short_flag,
- const simple_glyph_flag_t same_flag)
- {
- float v = 0;
- for (unsigned i = 0; i < points_.length; i++)
- {
- uint8_t flag = points_[i].flag;
- if (flag & short_flag)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- if (flag & same_flag)
- v += *p++;
- else
- v -= *p++;
- }
- else
- {
- if (!(flag & same_flag))
- {
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p))) return false;
- v += *(const HBINT16 *) p;
- p += HBINT16::static_size;
- }
- }
- setter (points_[i], v);
- }
- return true;
- }
-
- bool get_contour_points (contour_point_vector_t &points_ /* OUT */,
- bool phantom_only = false) const
- {
- const HBUINT16 *endPtsOfContours = &StructAfter<HBUINT16> (header);
- int num_contours = header.numberOfContours;
- if (unlikely (!bytes.check_range (&endPtsOfContours[num_contours + 1]))) return false;
- unsigned int num_points = endPtsOfContours[num_contours - 1] + 1;
-
- points_.resize (num_points);
- for (unsigned int i = 0; i < points_.length; i++) points_[i].init ();
- if (phantom_only) return true;
-
- for (int i = 0; i < num_contours; i++)
- points_[endPtsOfContours[i]].is_end_point = true;
-
- /* Skip instructions */
- const HBUINT8 *p = &StructAtOffset<HBUINT8> (&endPtsOfContours[num_contours + 1],
- endPtsOfContours[num_contours]);
-
- /* Read flags */
- for (unsigned int i = 0; i < num_points; i++)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- uint8_t flag = *p++;
- points_[i].flag = flag;
- if (flag & FLAG_REPEAT)
- {
- if (unlikely (!bytes.check_range (p))) return false;
- unsigned int repeat_count = *p++;
- while ((repeat_count-- > 0) && (++i < num_points))
- points_[i].flag = flag;
- }
- }
-
- /* Read x & y coordinates */
- return read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.x = v; },
- FLAG_X_SHORT, FLAG_X_SAME)
- && read_points (p, points_, bytes, [] (contour_point_t &p, float v) { p.y = v; },
- FLAG_Y_SHORT, FLAG_Y_SAME);
- }
- };
-
- struct CompositeGlyph
- {
- const GlyphHeader &header;
- hb_bytes_t bytes;
- CompositeGlyph (const GlyphHeader &header_, hb_bytes_t bytes_) :
- header (header_), bytes (bytes_) {}
-
- composite_iter_t get_iterator () const
- { return composite_iter_t (bytes, &StructAfter<CompositeGlyphChain, GlyphHeader> (header)); }
-
- unsigned int instructions_length (hb_bytes_t bytes) const
- {
- unsigned int start = bytes.length;
- unsigned int end = bytes.length;
- const CompositeGlyphChain *last = nullptr;
- for (auto &item : get_iterator ())
- last = &item;
- if (unlikely (!last)) return 0;
-
- if (last->has_instructions ())
- start = (char *) last - &bytes + last->get_size ();
- if (unlikely (start > end)) return 0;
- return end - start;
- }
-
- /* Trimming for composites not implemented.
- * If removing hints it falls out of that. */
- const Glyph trim_padding () const { return Glyph (bytes); }
-
- void drop_hints ()
- {
- for (const auto &_ : get_iterator ())
- const_cast<CompositeGlyphChain &> (_).drop_instructions_flag ();
- }
-
- /* Chop instructions off the end */
- void drop_hints_bytes (hb_bytes_t &dest_start) const
- { dest_start = bytes.sub_array (0, bytes.length - instructions_length (bytes)); }
-
- void set_overlaps_flag ()
- {
- const_cast<CompositeGlyphChain &> (StructAfter<CompositeGlyphChain, GlyphHeader> (header))
- .set_overlaps_flag ();
- }
- };
-
- enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE };
-
- public:
- composite_iter_t get_composite_iterator () const
- {
- if (type != COMPOSITE) return composite_iter_t ();
- return CompositeGlyph (*header, bytes).get_iterator ();
- }
-
- const Glyph trim_padding () const
- {
- switch (type) {
- case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
- case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
- default: return bytes;
- }
- }
-
- void drop_hints ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
- default: return;
- }
- }
-
- void set_overlaps_flag ()
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
- case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
- default: return;
- }
- }
-
- void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
- {
- switch (type) {
- case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
- case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
- default: return;
- }
- }
-
- /* Note: Recursively calls itself.
- * all_points includes phantom points
- */
- bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
- contour_point_vector_t &all_points /* OUT */,
- bool phantom_only = false,
- unsigned int depth = 0) const
- {
- if (unlikely (depth > HB_MAX_NESTING_LEVEL)) return false;
- contour_point_vector_t points;
-
- switch (type) {
- case COMPOSITE:
- {
- /* pseudo component points for each component in composite glyph */
- unsigned num_points = hb_len (CompositeGlyph (*header, bytes).get_iterator ());
- if (unlikely (!points.resize (num_points))) return false;
- for (unsigned i = 0; i < points.length; i++)
- points[i].init ();
- break;
- }
- case SIMPLE:
- if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points, phantom_only)))
- return false;
- break;
- }
-
- /* Init phantom points */
- if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
- hb_array_t<contour_point_t> phantoms = points.sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
- {
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i) phantoms[i].init ();
- int h_delta = (int) header->xMin -
- glyf_accelerator.hmtx->get_side_bearing (gid);
- int v_orig = (int) header->yMax +
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_side_bearing (gid)
-#else
- 0
-#endif
- ;
- unsigned h_adv = glyf_accelerator.hmtx->get_advance (gid);
- unsigned v_adv =
-#ifndef HB_NO_VERTICAL
- glyf_accelerator.vmtx->get_advance (gid)
-#else
- - font->face->get_upem ()
-#endif
- ;
- phantoms[PHANTOM_LEFT].x = h_delta;
- phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
- phantoms[PHANTOM_TOP].y = v_orig;
- phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
- }
-
-#ifndef HB_NO_VAR
- if (unlikely (!glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ())))
- return false;
-#endif
-
- switch (type) {
- case SIMPLE:
- all_points.extend (points.as_array ());
- break;
- case COMPOSITE:
- {
- unsigned int comp_index = 0;
- for (auto &item : get_composite_iterator ())
- {
- contour_point_vector_t comp_points;
- if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_glyph_index ())
- .get_points (font, glyf_accelerator, comp_points,
- phantom_only, depth + 1)
- || comp_points.length < PHANTOM_COUNT))
- return false;
-
- /* Copy phantom points from component if USE_MY_METRICS flag set */
- if (item.is_use_my_metrics ())
- for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
- phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
-
- /* Apply component transformation & translation */
- item.transform_points (comp_points);
-
- /* Apply translation from gvar */
- comp_points.translate (points[comp_index]);
-
- if (item.is_anchored ())
- {
- unsigned int p1, p2;
- item.get_anchor_points (p1, p2);
- if (likely (p1 < all_points.length && p2 < comp_points.length))
- {
- contour_point_t delta;
- delta.init (all_points[p1].x - comp_points[p2].x,
- all_points[p1].y - comp_points[p2].y);
-
- comp_points.translate (delta);
- }
- }
-
- all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
-
- comp_index++;
- }
-
- all_points.extend (phantoms);
- } break;
- default:
- all_points.extend (phantoms);
- }
-
- if (depth == 0) /* Apply at top level */
- {
- /* Undocumented rasterizer behavior:
- * Shift points horizontally by the updated left side bearing
- */
- contour_point_t delta;
- delta.init (-phantoms[PHANTOM_LEFT].x, 0.f);
- if (delta.x) all_points.translate (delta);
- }
-
- return true;
- }
-
- bool get_extents (hb_font_t *font, const accelerator_t &glyf_accelerator,
- hb_glyph_extents_t *extents) const
- {
- if (type == EMPTY) return true; /* Empty glyph; zero extents. */
- return header->get_extents (font, glyf_accelerator, gid, extents);
- }
-
- hb_bytes_t get_bytes () const { return bytes; }
-
- Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
- hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_), gid (gid_),
- header (bytes.as<GlyphHeader> ())
- {
- int num_contours = header->numberOfContours;
- if (unlikely (num_contours == 0)) type = EMPTY;
- else if (num_contours > 0) type = SIMPLE;
- else type = COMPOSITE; /* negative numbers */
- }
-
- protected:
- hb_bytes_t bytes;
- hb_codepoint_t gid;
- const GlyphHeader *header;
- unsigned type;
- };
-
- struct accelerator_t
- {
- accelerator_t (hb_face_t *face)
- {
- short_offset = false;
- num_glyphs = 0;
- loca_table = nullptr;
- glyf_table = nullptr;
-#ifndef HB_NO_VAR
- gvar = nullptr;
-#endif
- hmtx = nullptr;
-#ifndef HB_NO_VERTICAL
- vmtx = nullptr;
-#endif
- const OT::head &head = *face->table.head;
- if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
- /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
- return;
- short_offset = 0 == head.indexToLocFormat;
-
- loca_table = hb_sanitize_context_t ().reference_table<loca> (face);
- glyf_table = hb_sanitize_context_t ().reference_table<glyf> (face);
-#ifndef HB_NO_VAR
- gvar = face->table.gvar;
-#endif
- hmtx = face->table.hmtx;
-#ifndef HB_NO_VERTICAL
- vmtx = face->table.vmtx;
-#endif
-
- num_glyphs = hb_max (1u, loca_table.get_length () / (short_offset ? 2 : 4)) - 1;
- num_glyphs = hb_min (num_glyphs, face->get_num_glyphs ());
- }
- ~accelerator_t ()
- {
- loca_table.destroy ();
- glyf_table.destroy ();
- }
-
- protected:
- template<typename T>
- bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer) const
- {
- if (gid >= num_glyphs) return false;
-
- /* Making this allocfree is not that easy
- https://github.com/harfbuzz/harfbuzz/issues/2095
- mostly because of gvar handling in VF fonts,
- perhaps a separate path for non-VF fonts can be considered */
- contour_point_vector_t all_points;
-
- bool phantom_only = !consumer.is_consuming_contour_points ();
- if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, phantom_only)))
- return false;
-
- if (consumer.is_consuming_contour_points ())
- {
- for (unsigned point_index = 0; point_index + 4 < all_points.length; ++point_index)
- consumer.consume_point (all_points[point_index]);
- consumer.points_end ();
- }
-
- /* Where to write phantoms, nullptr if not requested */
- contour_point_t *phantoms = consumer.get_phantoms_sink ();
- if (phantoms)
- for (unsigned i = 0; i < PHANTOM_COUNT; ++i)
- phantoms[i] = all_points[all_points.length - PHANTOM_COUNT + i];
-
- return true;
- }
-
-#ifndef HB_NO_VAR
- struct points_aggregator_t
- {
- hb_font_t *font;
- hb_glyph_extents_t *extents;
- contour_point_t *phantoms;
-
- struct contour_bounds_t
- {
- contour_bounds_t () { min_x = min_y = FLT_MAX; max_x = max_y = -FLT_MAX; }
-
- void add (const contour_point_t &p)
- {
- min_x = hb_min (min_x, p.x);
- min_y = hb_min (min_y, p.y);
- max_x = hb_max (max_x, p.x);
- max_y = hb_max (max_y, p.y);
- }
-
- bool empty () const { return (min_x >= max_x) || (min_y >= max_y); }
-
- void get_extents (hb_font_t *font, hb_glyph_extents_t *extents)
- {
- if (unlikely (empty ()))
- {
- extents->width = 0;
- extents->x_bearing = 0;
- extents->height = 0;
- extents->y_bearing = 0;
- return;
- }
- extents->x_bearing = font->em_scalef_x (min_x);
- extents->width = font->em_scalef_x (max_x) - extents->x_bearing;
- extents->y_bearing = font->em_scalef_y (max_y);
- extents->height = font->em_scalef_y (min_y) - extents->y_bearing;
- }
-
- protected:
- float min_x, min_y, max_x, max_y;
- } bounds;
-
- points_aggregator_t (hb_font_t *font_, hb_glyph_extents_t *extents_, contour_point_t *phantoms_)
- {
- font = font_;
- extents = extents_;
- phantoms = phantoms_;
- if (extents) bounds = contour_bounds_t ();
- }
-
- void consume_point (const contour_point_t &point) { bounds.add (point); }
- void points_end () { bounds.get_extents (font, extents); }
-
- bool is_consuming_contour_points () { return extents; }
- contour_point_t *get_phantoms_sink () { return phantoms; }
- };
-
- public:
- unsigned
- get_advance_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- bool success = false;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (likely (font->num_coords == gvar->get_axis_count ()))
- success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms));
-
- if (unlikely (!success))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_advance (gid) :
-#endif
- hmtx->get_advance (gid);
-
- float result = is_vertical
- ? phantoms[PHANTOM_TOP].y - phantoms[PHANTOM_BOTTOM].y
- : phantoms[PHANTOM_RIGHT].x - phantoms[PHANTOM_LEFT].x;
- return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
- }
-
- int get_side_bearing_var (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
- {
- if (unlikely (gid >= num_glyphs)) return 0;
-
- hb_glyph_extents_t extents;
-
- contour_point_t phantoms[PHANTOM_COUNT];
- if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms))))
- return
-#ifndef HB_NO_VERTICAL
- is_vertical ? vmtx->get_side_bearing (gid) :
-#endif
- hmtx->get_side_bearing (gid);
-
- return is_vertical
- ? ceilf (phantoms[PHANTOM_TOP].y) - extents.y_bearing
- : floorf (phantoms[PHANTOM_LEFT].x);
- }
-#endif
-
- public:
- bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
- {
- if (unlikely (gid >= num_glyphs)) return false;
-
-#ifndef HB_NO_VAR
- if (font->num_coords && font->num_coords == gvar->get_axis_count ())
- return get_points (font, gid, points_aggregator_t (font, extents, nullptr));
-#endif
- return glyph_for_gid (gid).get_extents (font, *this, extents);
- }
-
- const Glyph
- glyph_for_gid (hb_codepoint_t gid, bool needs_padding_removal = false) const
- {
- if (unlikely (gid >= num_glyphs)) return Glyph ();
-
- unsigned int start_offset, end_offset;
-
- if (short_offset)
- {
- const HBUINT16 *offsets = (const HBUINT16 *) loca_table->dataZ.arrayZ;
- start_offset = 2 * offsets[gid];
- end_offset = 2 * offsets[gid + 1];
- }
- else
- {
- const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataZ.arrayZ;
- start_offset = offsets[gid];
- end_offset = offsets[gid + 1];
- }
-
- if (unlikely (start_offset > end_offset || end_offset > glyf_table.get_length ()))
- return Glyph ();
-
- Glyph glyph (hb_bytes_t ((const char *) this->glyf_table + start_offset,
- end_offset - start_offset), gid);
- return needs_padding_removal ? glyph.trim_padding () : glyph;
- }
-
- unsigned
- add_gid_and_children (hb_codepoint_t gid,
- hb_set_t *gids_to_retain,
- unsigned depth = 0,
- unsigned operation_count = 0) const
- {
- if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
- if (unlikely (operation_count++ > HB_MAX_COMPOSITE_OPERATIONS)) return operation_count;
- /* Check if is already visited */
- if (gids_to_retain->has (gid)) return operation_count;
-
- gids_to_retain->add (gid);
-
- auto it = glyph_for_gid (gid).get_composite_iterator ();
- while (it)
- {
- auto item = *(it++);
- operation_count =
- add_gid_and_children (item.get_glyph_index (), gids_to_retain, depth, operation_count);
- }
-
- return operation_count;
- }
-
-#ifdef HB_EXPERIMENTAL_API
- struct path_builder_t
- {
- hb_font_t *font;
- draw_helper_t *draw_helper;
-
- struct optional_point_t
- {
- optional_point_t () { has_data = false; }
- optional_point_t (float x_, float y_) { x = x_; y = y_; has_data = true; }
-
- bool has_data;
- float x;
- float y;
-
- optional_point_t lerp (optional_point_t p, float t)
- { return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
- } first_oncurve, first_offcurve, last_offcurve;
-
- path_builder_t (hb_font_t *font_, draw_helper_t &draw_helper_)
- {
- font = font_;
- draw_helper = &draw_helper_;
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- }
-
- /* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
- See also:
- * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
- * https://stackoverflow.com/a/20772557 */
- void consume_point (const contour_point_t &point)
- {
- /* Skip empty contours */
- if (unlikely (point.is_end_point && !first_oncurve.has_data && !first_offcurve.has_data))
- return;
-
- bool is_on_curve = point.flag & Glyph::FLAG_ON_CURVE;
- optional_point_t p (point.x, point.y);
- if (!first_oncurve.has_data)
- {
- if (is_on_curve)
- {
- first_oncurve = p;
- draw_helper->move_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
- }
- else
- {
- if (first_offcurve.has_data)
- {
- optional_point_t mid = first_offcurve.lerp (p, .5f);
- first_oncurve = mid;
- last_offcurve = p;
- draw_helper->move_to (font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
- }
- else
- first_offcurve = p;
- }
- }
- else
- {
- if (last_offcurve.has_data)
- {
- if (is_on_curve)
- {
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (p.x), font->em_scalef_y (p.y));
- last_offcurve = optional_point_t ();
- }
- else
- {
- optional_point_t mid = last_offcurve.lerp (p, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
- last_offcurve = p;
- }
- }
- else
- {
- if (is_on_curve)
- draw_helper->line_to (font->em_scalef_x (p.x), font->em_scalef_y (p.y));
- else
- last_offcurve = p;
- }
- }
-
- if (point.is_end_point)
- {
- if (first_offcurve.has_data && last_offcurve.has_data)
- {
- optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (mid.x), font->em_scalef_y (mid.y));
- last_offcurve = optional_point_t ();
- /* now check the rest */
- }
-
- if (first_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (first_offcurve.x), font->em_scalef_y (first_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
- else if (last_offcurve.has_data && first_oncurve.has_data)
- draw_helper->quadratic_to (font->em_scalef_x (last_offcurve.x), font->em_scalef_y (last_offcurve.y),
- font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
- else if (first_oncurve.has_data)
- draw_helper->line_to (font->em_scalef_x (first_oncurve.x), font->em_scalef_y (first_oncurve.y));
-
- /* Getting ready for the next contour */
- first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
- draw_helper->end_path ();
- }
- }
- void points_end () {}
-
- bool is_consuming_contour_points () { return true; }
- contour_point_t *get_phantoms_sink () { return nullptr; }
- };
-
- bool
- get_path (hb_font_t *font, hb_codepoint_t gid, draw_helper_t &draw_helper) const
- { return get_points (font, gid, path_builder_t (font, draw_helper)); }
-#endif
-
-#ifndef HB_NO_VAR
- const gvar_accelerator_t *gvar;
-#endif
- const hmtx_accelerator_t *hmtx;
-#ifndef HB_NO_VERTICAL
- const vmtx_accelerator_t *vmtx;
-#endif
-
- private:
- bool short_offset;
- unsigned int num_glyphs;
- hb_blob_ptr_t<loca> loca_table;
- hb_blob_ptr_t<glyf> glyf_table;
- };
-
- struct SubsetGlyph
- {
- hb_codepoint_t new_gid;
- hb_codepoint_t old_gid;
- Glyph source_glyph;
- hb_bytes_t dest_start; /* region of source_glyph to copy first */
- hb_bytes_t dest_end; /* region of source_glyph to copy second */
-
- bool serialize (hb_serialize_context_t *c,
- bool use_short_loca,
- const hb_subset_plan_t *plan) const
- {
- TRACE_SERIALIZE (this);
-
- hb_bytes_t dest_glyph = dest_start.copy (c);
- dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
- unsigned int pad_length = use_short_loca ? padding () : 0;
- DEBUG_MSG (SUBSET, nullptr, "serialize %d byte glyph, width %d pad %d", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
-
- HBUINT8 pad;
- pad = 0;
- while (pad_length > 0)
- {
- c->embed (pad);
- pad_length--;
- }
-
- if (unlikely (!dest_glyph.length)) return_trace (true);
-
- /* update components gids */
- for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
- {
- hb_codepoint_t new_gid;
- if (plan->new_gid_for_old_gid (_.get_glyph_index (), &new_gid))
- const_cast<CompositeGlyphChain &> (_).set_glyph_index (new_gid);
- }
-
- if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- Glyph (dest_glyph).drop_hints ();
-
- if (plan->flags & HB_SUBSET_FLAGS_SET_OVERLAPS_FLAG)
- Glyph (dest_glyph).set_overlaps_flag ();
-
- return_trace (true);
- }
-
- void drop_hints_bytes ()
- { source_glyph.drop_hints_bytes (dest_start, dest_end); }
-
- unsigned int length () const { return dest_start.length + dest_end.length; }
- /* pad to 2 to ensure 2-byte loca will be ok */
- unsigned int padding () const { return length () % 2; }
- unsigned int padded_size () const { return length () + padding (); }
- };
-
- protected:
- UnsizedArrayOf<HBUINT8>
- dataZ; /* Glyphs data. */
- public:
- DEFINE_SIZE_MIN (0); /* In reality, this is UNBOUNDED() type; but since we always
- * check the size externally, allow Null() object of it by
- * defining it _MIN instead. */
-};
-
-struct glyf_accelerator_t : glyf::accelerator_t {
- glyf_accelerator_t (hb_face_t *face) : glyf::accelerator_t (face) {}
-};
-
-
-} /* namespace OT */
-
+#include "OT/glyf/glyf.hh"
#endif /* HB_OT_GLYF_TABLE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
index 36bffa70a5..50e4b54fde 100644
--- a/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
@@ -28,6 +28,7 @@
#define HB_OT_HMTX_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-maxp-table.hh"
#include "hb-ot-hhea-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-metrics.hh"
@@ -42,11 +43,11 @@
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
-HB_INTERNAL int
-_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+HB_INTERNAL bool
+_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb);
HB_INTERNAL unsigned
-_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
namespace OT {
@@ -61,7 +62,7 @@ struct LongMetric
};
-template <typename T, typename H>
+template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/>
struct hmtxvmtx
{
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
@@ -98,12 +99,12 @@ struct hmtxvmtx
hb_requires (hb_is_iterator (Iterator))>
void serialize (hb_serialize_context_t *c,
Iterator it,
- unsigned num_advances)
+ unsigned num_long_metrics)
{
unsigned idx = 0;
for (auto _ : it)
{
- if (idx < num_advances)
+ if (idx < num_long_metrics)
{
LongMetric lm;
lm.advance = _.first;
@@ -128,7 +129,19 @@ struct hmtxvmtx
if (unlikely (!table_prime)) return_trace (false);
accelerator_t _mtx (c->plan->source);
- unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
+ unsigned num_long_metrics;
+ {
+ /* Determine num_long_metrics to encode. */
+ auto& plan = c->plan;
+ num_long_metrics = plan->num_output_glyphs ();
+ hb_codepoint_t old_gid = 0;
+ unsigned int last_advance = plan->old_gid_for_new_gid (num_long_metrics - 1, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0;
+ while (num_long_metrics > 1 &&
+ last_advance == (plan->old_gid_for_new_gid (num_long_metrics - 2, &old_gid) ? _mtx.get_advance_without_var_unscaled (old_gid) : 0))
+ {
+ num_long_metrics--;
+ }
+ }
auto it =
+ hb_range (c->plan->num_output_glyphs ())
@@ -137,17 +150,19 @@ struct hmtxvmtx
hb_codepoint_t old_gid;
if (!c->plan->old_gid_for_new_gid (_, &old_gid))
return hb_pair (0u, 0);
- return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+ int lsb = 0;
+ (void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
+ return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
})
;
- table_prime->serialize (c->serializer, it, num_advances);
+ table_prime->serialize (c->serializer, it, num_long_metrics);
if (unlikely (c->serializer->in_error ()))
return_trace (false);
// Amend header num hmetrics
- if (unlikely (!subset_update_header (c->plan, num_advances)))
+ if (unlikely (!subset_update_header (c->plan, num_long_metrics)))
return_trace (false);
return_trace (true);
@@ -157,38 +172,48 @@ struct hmtxvmtx
{
friend struct hmtxvmtx;
- accelerator_t (hb_face_t *face,
- unsigned int default_advance_ = 0)
+ accelerator_t (hb_face_t *face)
{
- default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
+ table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag);
+
+ default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face);
- num_advances = T::is_horizontal ?
- face->table.hhea->numberOfLongMetrics :
+ /* Populate count variables and sort them out as we go */
+
+ unsigned int len = table.get_length ();
+ if (len & 1)
+ len--;
+
+ num_long_metrics = T::is_horizontal ?
+ face->table.hhea->numberOfLongMetrics :
#ifndef HB_NO_VERTICAL
- face->table.vhea->numberOfLongMetrics
+ face->table.vhea->numberOfLongMetrics
#else
- 0
+ 0
#endif
- ;
+ ;
+ if (unlikely (num_long_metrics * 4 > len))
+ num_long_metrics = len / 4;
+ len -= num_long_metrics * 4;
- table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag);
+ num_bearings = face->table.maxp->get_num_glyphs ();
- /* Cap num_metrics() and num_advances() based on table length. */
- unsigned int len = table.get_length ();
- if (unlikely (num_advances * 4 > len))
- num_advances = len / 4;
- num_metrics = num_advances + (len - 4 * num_advances) / 2;
+ if (unlikely (num_bearings < num_long_metrics))
+ num_bearings = num_long_metrics;
+ if (unlikely ((num_bearings - num_long_metrics) * 2 > len))
+ num_bearings = num_long_metrics + len / 2;
+ len -= (num_bearings - num_long_metrics) * 2;
- /* We MUST set num_metrics to zero if num_advances is zero.
+ /* We MUST set num_bearings to zero if num_long_metrics is zero.
* Our get_advance() depends on that. */
- if (unlikely (!num_advances))
- {
- num_metrics = num_advances = 0;
- table.destroy ();
- table = hb_blob_get_empty ();
- }
+ if (unlikely (!num_long_metrics))
+ num_bearings = num_long_metrics = 0;
- var_table = hb_sanitize_context_t ().reference_table<HVARVVAR> (face, T::variationsTag);
+ num_advances = num_bearings + len / 2;
+ num_glyphs = face->get_num_glyphs ();
+ if (num_glyphs < num_advances)
+ num_glyphs = num_advances;
}
~accelerator_t ()
{
@@ -196,103 +221,113 @@ struct hmtxvmtx
var_table.destroy ();
}
- int get_side_bearing (hb_codepoint_t glyph) const
+ bool has_data () const { return (bool) num_bearings; }
+
+ bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
+ int *lsb) const
{
- if (glyph < num_advances)
- return table->longMetricZ[glyph].sb;
+ if (glyph < num_long_metrics)
+ {
+ *lsb = table->longMetricZ[glyph].sb;
+ return true;
+ }
- if (unlikely (glyph >= num_metrics))
- return 0;
+ if (unlikely (glyph >= num_bearings))
+ return false;
- const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
- return bearings[glyph - num_advances];
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ *lsb = bearings[glyph - num_long_metrics];
+ return true;
}
- int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
+ bool get_leading_bearing_with_var_unscaled (hb_font_t *font,
+ hb_codepoint_t glyph,
+ int *lsb) const
{
- int side_bearing = get_side_bearing (glyph);
+ if (!font->num_coords)
+ return get_leading_bearing_without_var_unscaled (glyph, lsb);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
- return side_bearing;
-
- if (var_table.get_length ())
- return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+ float delta;
+ if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) &&
+ get_leading_bearing_without_var_unscaled (glyph, lsb))
+ {
+ *lsb += roundf (delta);
+ return true;
+ }
- return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb);
#else
- return side_bearing;
+ return false;
#endif
}
- unsigned int get_advance (hb_codepoint_t glyph) const
+ unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const
{
- if (unlikely (glyph >= num_metrics))
- {
- /* If num_metrics is zero, it means we don't have the metrics table
- * for this direction: return default advance. Otherwise, it means that the
- * glyph index is out of bound: return zero. */
- if (num_metrics)
- return 0;
- else
- return default_advance;
- }
+ /* OpenType case. */
+ if (glyph < num_bearings)
+ return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance;
+
+ /* If num_advances is zero, it means we don't have the metrics table
+ * for this direction: return default advance. Otherwise, there's a
+ * well-defined answer. */
+ if (unlikely (!num_advances))
+ return default_advance;
+
+#ifdef HB_NO_BEYOND_64K
+ return 0;
+#endif
+
+ if (unlikely (glyph >= num_glyphs))
+ return 0;
+
+ /* num_bearings <= glyph < num_glyphs;
+ * num_bearings <= num_advances */
+
+ /* TODO Optimize */
+
+ if (num_bearings == num_advances)
+ return get_advance_without_var_unscaled (num_bearings - 1);
+
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
+ const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics];
- return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
+ return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
}
- unsigned int get_advance (hb_codepoint_t glyph,
- hb_font_t *font) const
+ unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
+ hb_font_t *font,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- unsigned int advance = get_advance (glyph);
+ unsigned int advance = get_advance_without_var_unscaled (glyph);
#ifndef HB_NO_VAR
- if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ if (unlikely (glyph >= num_bearings) || !font->num_coords)
return advance;
if (var_table.get_length ())
- return advance + roundf (var_table->get_advance_var (glyph, font)); // TODO Optimize?!
+ return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
+ font->coords, font->num_coords,
+ store_cache)); // TODO Optimize?!
- return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+ return _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
#else
return advance;
#endif
}
- unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const
- {
- unsigned int num_advances = plan->num_output_glyphs ();
- unsigned int last_advance = _advance_for_new_gid (plan,
- num_advances - 1);
- while (num_advances > 1 &&
- last_advance == _advance_for_new_gid (plan,
- num_advances - 2))
- {
- num_advances--;
- }
-
- return num_advances;
- }
-
- private:
- unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
- hb_codepoint_t new_gid) const
- {
- hb_codepoint_t old_gid;
- if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
- return 0;
-
- return get_advance (old_gid);
- }
-
protected:
- unsigned int num_metrics;
- unsigned int num_advances;
+ // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
+ unsigned num_long_metrics;
+ unsigned num_bearings;
+ unsigned num_advances;
+ unsigned num_glyphs;
+
unsigned int default_advance;
- private:
+ public:
hb_blob_ptr_t<hmtxvmtx> table;
- hb_blob_ptr_t<HVARVVAR> var_table;
+ hb_blob_ptr_t<V> var_table;
};
protected:
@@ -319,16 +354,18 @@ struct hmtxvmtx
* the end. This allows a monospaced
* font to vary the side bearing
* values for each glyph. */
+/*UnsizedArrayOf<UFWORD>advancesX;*/
+ /* TODO Document. */
public:
DEFINE_SIZE_ARRAY (0, longMetricZ);
};
-struct hmtx : hmtxvmtx<hmtx, hhea> {
+struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
static constexpr bool is_horizontal = true;
};
-struct vmtx : hmtxvmtx<vmtx, vhea> {
+struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> {
static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
static constexpr bool is_horizontal = false;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
index eb4c3b46e2..8179e5acd5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-base-table.hh
@@ -41,12 +41,15 @@ namespace OT {
struct BaseCoordFormat1
{
- hb_position_t get_coord () const { return coordinate; }
+ hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
+ {
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
+ }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -58,10 +61,10 @@ struct BaseCoordFormat1
struct BaseCoordFormat2
{
- hb_position_t get_coord () const
+ hb_position_t get_coord (hb_font_t *font, hb_direction_t direction) const
{
/* TODO */
- return coordinate;
+ return HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (coordinate) : font->em_scale_x (coordinate);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -87,9 +90,10 @@ struct BaseCoordFormat3
hb_direction_t direction) const
{
const Device &device = this+deviceTable;
- return coordinate + (HB_DIRECTION_IS_VERTICAL (direction) ?
- device.get_y_delta (font, var_store) :
- device.get_x_delta (font, var_store));
+
+ return HB_DIRECTION_IS_HORIZONTAL (direction)
+ ? font->em_scale_y (coordinate) + device.get_y_delta (font, var_store)
+ : font->em_scale_x (coordinate) + device.get_x_delta (font, var_store);
}
@@ -120,8 +124,8 @@ struct BaseCoord
hb_direction_t direction) const
{
switch (u.format) {
- case 1: return u.format1.get_coord ();
- case 2: return u.format2.get_coord ();
+ case 1: return u.format1.get_coord (font, direction);
+ case 2: return u.format2.get_coord (font, direction);
case 3: return u.format3.get_coord (font, var_store, direction);
default:return 0;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index 60a1906155..0532039aad 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -35,9 +35,17 @@
#include "hb-set.hh"
#include "hb-bimap.hh"
+#include "OT/Layout/Common/Coverage.hh"
+#include "OT/Layout/types.hh"
+
+// TODO(garretrieger): cleanup these after migration.
+using OT::Layout::Common::Coverage;
+using OT::Layout::Common::RangeRecord;
+using OT::Layout::SmallTypes;
+using OT::Layout::MediumTypes;
#ifndef HB_MAX_NESTING_LEVEL
-#define HB_MAX_NESTING_LEVEL 6
+#define HB_MAX_NESTING_LEVEL 64
#endif
#ifndef HB_MAX_CONTEXT_LENGTH
#define HB_MAX_CONTEXT_LENGTH 64
@@ -46,10 +54,10 @@
/*
* The maximum number of times a lookup can be applied during shaping.
* Used to limit the number of iterations of the closure algorithm.
- * This must be larger than the number of times add_pause() is
+ * This must be larger than the number of times add_gsub_pause() is
* called in a collect_features call of any shaper.
*/
-#define HB_CLOSURE_MAX_STAGES 32
+#define HB_CLOSURE_MAX_STAGES 12
#endif
#ifndef HB_MAX_SCRIPTS
@@ -60,8 +68,8 @@
#define HB_MAX_LANGSYS 2000
#endif
-#ifndef HB_MAX_FEATURES
-#define HB_MAX_FEATURES 750
+#ifndef HB_MAX_LANGSYS_FEATURE_COUNT
+#define HB_MAX_LANGSYS_FEATURE_COUNT 50000
#endif
#ifndef HB_MAX_FEATURE_INDICES
@@ -75,77 +83,48 @@
namespace OT {
-
-#define NOT_COVERED ((unsigned int) -1)
-
-
-template<typename Iterator>
-static inline void Coverage_serialize (hb_serialize_context_t *c,
- Iterator it);
-
template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
Iterator it);
-static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
- const hb_set_t &klasses,
- bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/);
+static void ClassDef_remap_and_serialize (
+ hb_serialize_context_t *c,
+ const hb_set_t &klasses,
+ bool use_class_zero,
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/);
struct hb_prune_langsys_context_t
{
hb_prune_langsys_context_t (const void *table_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
const hb_map_t *duplicate_feature_map_,
hb_set_t *new_collected_feature_indexes_)
:table (table_),
script_langsys_map (script_langsys_map_),
duplicate_feature_map (duplicate_feature_map_),
new_feature_indexes (new_collected_feature_indexes_),
- script_count (0),langsys_count (0) {}
+ script_count (0),langsys_feature_count (0) {}
- bool visitedScript (const void *s)
- {
- if (script_count++ > HB_MAX_SCRIPTS)
- return true;
-
- return visited (s, visited_script);
- }
+ bool visitScript ()
+ { return script_count++ < HB_MAX_SCRIPTS; }
- bool visitedLangsys (const void *l)
+ bool visitLangsys (unsigned feature_count)
{
- if (langsys_count++ > HB_MAX_LANGSYS)
- return true;
-
- return visited (l, visited_langsys);
- }
-
- private:
- template <typename T>
- bool visited (const T *p, hb_set_t &visited_set)
- {
- hb_codepoint_t delta = (hb_codepoint_t) ((uintptr_t) p - (uintptr_t) table);
- if (visited_set.in_error () || visited_set.has (delta))
- return true;
-
- visited_set.add (delta);
- return false;
+ langsys_feature_count += feature_count;
+ return langsys_feature_count < HB_MAX_LANGSYS_FEATURE_COUNT;
}
public:
const void *table;
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *duplicate_feature_map;
hb_set_t *new_feature_indexes;
private:
- hb_set_t visited_script;
- hb_set_t visited_langsys;
unsigned script_count;
- unsigned langsys_count;
+ unsigned langsys_feature_count;
};
struct hb_subset_layout_context_t :
@@ -179,14 +158,14 @@ struct hb_subset_layout_context_t :
hb_subset_context_t *subset_context;
const hb_tag_t table_tag;
const hb_map_t *lookup_index_map;
- const hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map;
+ const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
const hb_map_t *feature_index_map;
unsigned cur_script_index;
hb_subset_layout_context_t (hb_subset_context_t *c_,
hb_tag_t tag_,
hb_map_t *lookup_map_,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
hb_map_t *feature_index_map_) :
subset_context (c_),
table_tag (tag_),
@@ -394,6 +373,51 @@ HB_FUNCOBJ (serialize_math_record_array);
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
*/
+struct IndexArray : Array16Of<Index>
+{
+ bool intersects (const hb_map_t *indexes) const
+ { return hb_any (*this, indexes); }
+
+ template <typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ hb_subset_layout_context_t *l,
+ Iterator it)
+ {
+ if (!it) return;
+ if (unlikely (!c->extend_min ((*this)))) return;
+
+ for (const auto _ : it)
+ {
+ if (!l->visitLookupIndex()) break;
+
+ Index i;
+ i = _;
+ c->copy (i);
+ this->len++;
+ }
+ }
+
+ unsigned int get_indexes (unsigned int start_offset,
+ unsigned int *_count /* IN/OUT */,
+ unsigned int *_indexes /* OUT */) const
+ {
+ if (_count)
+ {
+ + this->sub_array (start_offset, _count)
+ | hb_sink (hb_array (_indexes, *_count))
+ ;
+ }
+ return this->len;
+ }
+
+ void add_indexes_to (hb_set_t* output /* OUT */) const
+ {
+ output->add_array (as_array ());
+ }
+};
+
+
struct Record_sanitize_closure_t {
hb_tag_t tag;
const void *list_base;
@@ -482,364 +506,6 @@ struct RecordListOf : RecordArrayOf<Type>
}
};
-struct Feature;
-
-struct RecordListOfFeature : RecordListOf<Feature>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- + hb_zip (*this, hb_range (count))
- | hb_filter (l->feature_index_map, hb_second)
- | hb_map (hb_first)
- | hb_apply (subset_record_array (l, out, this))
- ;
- return_trace (true);
- }
-};
-
-struct Script;
-struct RecordListOfScript : RecordListOf<Script>
-{
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- unsigned count = this->len;
- for (auto _ : + hb_zip (*this, hb_range (count)))
- {
- auto snap = c->serializer->snapshot ();
- l->cur_script_index = _.second;
- bool ret = _.first.subset (l, this);
- if (!ret) c->serializer->revert (snap);
- else out->len++;
- }
-
- return_trace (true);
- }
-};
-
-struct RangeRecord
-{
- int cmp (hb_codepoint_t g) const
- { return g < first ? -1 : g <= last ? 0 : +1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- { return glyphs->intersects (first, last); }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_range (first, last); }
-
- HBGlyphID16 first; /* First GlyphID in the range */
- HBGlyphID16 last; /* Last GlyphID in the range */
- HBUINT16 value; /* Value */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, RangeRecord);
-
-
-struct IndexArray : Array16Of<Index>
-{
- bool intersects (const hb_map_t *indexes) const
- { return hb_any (*this, indexes); }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- hb_subset_layout_context_t *l,
- Iterator it)
- {
- if (!it) return;
- if (unlikely (!c->extend_min ((*this)))) return;
-
- for (const auto _ : it)
- {
- if (!l->visitLookupIndex()) break;
-
- Index i;
- i = _;
- c->copy (i);
- this->len++;
- }
- }
-
- unsigned int get_indexes (unsigned int start_offset,
- unsigned int *_count /* IN/OUT */,
- unsigned int *_indexes /* OUT */) const
- {
- if (_count)
- {
- + this->sub_array (start_offset, _count)
- | hb_sink (hb_array (_indexes, *_count))
- ;
- }
- return this->len;
- }
-
- void add_indexes_to (hb_set_t* output /* OUT */) const
- {
- output->add_array (as_array ());
- }
-};
-
-
-struct LangSys
-{
- unsigned int get_feature_count () const
- { return featureIndex.len; }
- hb_tag_t get_feature_index (unsigned int i) const
- { return featureIndex[i]; }
- unsigned int get_feature_indexes (unsigned int start_offset,
- unsigned int *feature_count /* IN/OUT */,
- unsigned int *feature_indexes /* OUT */) const
- { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
- void add_feature_indexes_to (hb_set_t *feature_indexes) const
- { featureIndex.add_indexes_to (feature_indexes); }
-
- bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
- unsigned int get_required_feature_index () const
- {
- if (reqFeatureIndex == 0xFFFFu)
- return Index::NOT_FOUND_INDEX;
- return reqFeatureIndex;
- }
-
- LangSys* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed (*this));
- }
-
- bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
- {
- if (reqFeatureIndex != o.reqFeatureIndex)
- return false;
-
- auto iter =
- + hb_iter (featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- auto o_iter =
- + hb_iter (o.featureIndex)
- | hb_filter (feature_index_map)
- | hb_map (feature_index_map)
- ;
-
- if (iter.len () != o_iter.len ())
- return false;
-
- for (const auto _ : + hb_zip (iter, o_iter))
- if (_.first != _.second) return false;
-
- return true;
- }
-
- void collect_features (hb_prune_langsys_context_t *c) const
- {
- if (!has_required_feature () && !get_feature_count ()) return;
- if (has_required_feature () &&
- c->duplicate_feature_map->has (reqFeatureIndex))
- c->new_feature_indexes->add (get_required_feature_index ());
-
- + hb_iter (featureIndex)
- | hb_filter (c->duplicate_feature_map)
- | hb_sink (c->new_feature_indexes)
- ;
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag = nullptr) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex) ? l->feature_index_map->get (reqFeatureIndex) : 0xFFFFu;
-
- if (!l->visitFeatureIndex (featureIndex.len))
- return_trace (false);
-
- auto it =
- + hb_iter (featureIndex)
- | hb_filter (l->feature_index_map)
- | hb_map (l->feature_index_map)
- ;
-
- bool ret = bool (it);
- out->featureIndex.serialize (c->serializer, l, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && featureIndex.sanitize (c));
- }
-
- Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
- * reordering table) */
- HBUINT16 reqFeatureIndex;/* Index of a feature required for this
- * language system--if no required features
- * = 0xFFFFu */
- IndexArray featureIndex; /* Array of indices into the FeatureList */
- public:
- DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
-};
-DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
-
-struct Script
-{
- unsigned int get_lang_sys_count () const
- { return langSys.len; }
- const Tag& get_lang_sys_tag (unsigned int i) const
- { return langSys.get_tag (i); }
- unsigned int get_lang_sys_tags (unsigned int start_offset,
- unsigned int *lang_sys_count /* IN/OUT */,
- hb_tag_t *lang_sys_tags /* OUT */) const
- { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
- const LangSys& get_lang_sys (unsigned int i) const
- {
- if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
- return this+langSys[i].offset;
- }
- bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
- { return langSys.find_index (tag, index); }
-
- bool has_default_lang_sys () const { return defaultLangSys != 0; }
- const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
-
- void prune_langsys (hb_prune_langsys_context_t *c,
- unsigned script_index) const
- {
- if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
- if (c->visitedScript (this)) return;
-
- if (!c->script_langsys_map->has (script_index))
- {
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!c->script_langsys_map->set (script_index, empty_set)))
- {
- hb_set_destroy (empty_set);
- return;
- }
- }
-
- unsigned langsys_count = get_lang_sys_count ();
- if (has_default_lang_sys ())
- {
- //only collect features from non-redundant langsys
- const LangSys& d = get_default_lang_sys ();
- if (!c->visitedLangsys (&d)) {
- d.collect_features (c);
- }
-
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
-
- const LangSys& l = this+_.first.offset;
- if (c->visitedLangsys (&l)) continue;
- if (l.compare (d, c->duplicate_feature_map)) continue;
-
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- else
- {
- for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
- {
- const LangSys& l = this+_.first.offset;
- if (c->visitedLangsys (&l)) continue;
- l.collect_features (c);
- c->script_langsys_map->get (script_index)->add (_.second);
- }
- }
- }
-
- bool subset (hb_subset_context_t *c,
- hb_subset_layout_context_t *l,
- const Tag *tag) const
- {
- TRACE_SUBSET (this);
- if (!l->visitScript ()) return_trace (false);
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
-
- bool defaultLang = false;
- if (has_default_lang_sys ())
- {
- c->serializer->push ();
- const LangSys& ls = this+defaultLangSys;
- bool ret = ls.subset (c, l);
- if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
- {
- c->serializer->pop_discard ();
- out->defaultLangSys = 0;
- }
- else
- {
- c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
- defaultLang = true;
- }
- }
-
- const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
- if (active_langsys)
- {
- unsigned count = langSys.len;
- + hb_zip (langSys, hb_range (count))
- | hb_filter (active_langsys, hb_second)
- | hb_map (hb_first)
- | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
- | hb_apply (subset_record_array (l, &(out->langSys), this))
- ;
- }
-
- return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
- }
-
- bool sanitize (hb_sanitize_context_t *c,
- const Record_sanitize_closure_t * = nullptr) const
- {
- TRACE_SANITIZE (this);
- return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
- }
-
- protected:
- Offset16To<LangSys>
- defaultLangSys; /* Offset to DefaultLangSys table--from
- * beginning of Script table--may be Null */
- RecordArrayOf<LangSys>
- langSys; /* Array of LangSysRecords--listed
- * alphabetically by LangSysTag */
- public:
- DEFINE_SIZE_ARRAY_SIZED (4, langSys);
-};
-
-typedef RecordListOfScript ScriptList;
-
-
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
struct FeatureParamsSize
{
@@ -1122,6 +788,7 @@ struct FeatureParams
DEFINE_SIZE_MIN (0);
};
+
struct Feature
{
unsigned int get_lookup_count () const
@@ -1217,9 +884,294 @@ struct Feature
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
};
+struct RecordListOfFeature : RecordListOf<Feature>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ + hb_zip (*this, hb_range (count))
+ | hb_filter (l->feature_index_map, hb_second)
+ | hb_map (hb_first)
+ | hb_apply (subset_record_array (l, out, this))
+ ;
+ return_trace (true);
+ }
+};
+
typedef RecordListOf<Feature> FeatureList;
+struct LangSys
+{
+ unsigned int get_feature_count () const
+ { return featureIndex.len; }
+ hb_tag_t get_feature_index (unsigned int i) const
+ { return featureIndex[i]; }
+ unsigned int get_feature_indexes (unsigned int start_offset,
+ unsigned int *feature_count /* IN/OUT */,
+ unsigned int *feature_indexes /* OUT */) const
+ { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
+ void add_feature_indexes_to (hb_set_t *feature_indexes) const
+ { featureIndex.add_indexes_to (feature_indexes); }
+
+ bool has_required_feature () const { return reqFeatureIndex != 0xFFFFu; }
+ unsigned int get_required_feature_index () const
+ {
+ if (reqFeatureIndex == 0xFFFFu)
+ return Index::NOT_FOUND_INDEX;
+ return reqFeatureIndex;
+ }
+
+ LangSys* copy (hb_serialize_context_t *c) const
+ {
+ TRACE_SERIALIZE (this);
+ return_trace (c->embed (*this));
+ }
+
+ bool compare (const LangSys& o, const hb_map_t *feature_index_map) const
+ {
+ if (reqFeatureIndex != o.reqFeatureIndex)
+ return false;
+
+ auto iter =
+ + hb_iter (featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ auto o_iter =
+ + hb_iter (o.featureIndex)
+ | hb_filter (feature_index_map)
+ | hb_map (feature_index_map)
+ ;
+
+ for (; iter && o_iter; iter++, o_iter++)
+ {
+ unsigned a = *iter;
+ unsigned b = *o_iter;
+ if (a != b) return false;
+ }
+
+ if (iter || o_iter) return false;
+
+ return true;
+ }
+
+ void collect_features (hb_prune_langsys_context_t *c) const
+ {
+ if (!has_required_feature () && !get_feature_count ()) return;
+ if (has_required_feature () &&
+ c->duplicate_feature_map->has (reqFeatureIndex))
+ c->new_feature_indexes->add (get_required_feature_index ());
+
+ + hb_iter (featureIndex)
+ | hb_filter (c->duplicate_feature_map)
+ | hb_sink (c->new_feature_indexes)
+ ;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag = nullptr) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ const unsigned *v;
+ out->reqFeatureIndex = l->feature_index_map->has (reqFeatureIndex, &v) ? *v : 0xFFFFu;
+
+ if (!l->visitFeatureIndex (featureIndex.len))
+ return_trace (false);
+
+ auto it =
+ + hb_iter (featureIndex)
+ | hb_filter (l->feature_index_map)
+ | hb_map (l->feature_index_map)
+ ;
+
+ bool ret = bool (it);
+ out->featureIndex.serialize (c->serializer, l, it);
+ return_trace (ret);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && featureIndex.sanitize (c));
+ }
+
+ Offset16 lookupOrderZ; /* = Null (reserved for an offset to a
+ * reordering table) */
+ HBUINT16 reqFeatureIndex;/* Index of a feature required for this
+ * language system--if no required features
+ * = 0xFFFFu */
+ IndexArray featureIndex; /* Array of indices into the FeatureList */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (6, featureIndex);
+};
+DECLARE_NULL_NAMESPACE_BYTES (OT, LangSys);
+
+struct Script
+{
+ unsigned int get_lang_sys_count () const
+ { return langSys.len; }
+ const Tag& get_lang_sys_tag (unsigned int i) const
+ { return langSys.get_tag (i); }
+ unsigned int get_lang_sys_tags (unsigned int start_offset,
+ unsigned int *lang_sys_count /* IN/OUT */,
+ hb_tag_t *lang_sys_tags /* OUT */) const
+ { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
+ const LangSys& get_lang_sys (unsigned int i) const
+ {
+ if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
+ return this+langSys[i].offset;
+ }
+ bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
+ { return langSys.find_index (tag, index); }
+
+ bool has_default_lang_sys () const { return defaultLangSys != 0; }
+ const LangSys& get_default_lang_sys () const { return this+defaultLangSys; }
+
+ void prune_langsys (hb_prune_langsys_context_t *c,
+ unsigned script_index) const
+ {
+ if (!has_default_lang_sys () && !get_lang_sys_count ()) return;
+ if (!c->visitScript ()) return;
+
+ if (!c->script_langsys_map->has (script_index))
+ {
+ if (unlikely (!c->script_langsys_map->set (script_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
+ return;
+ }
+
+ unsigned langsys_count = get_lang_sys_count ();
+ if (has_default_lang_sys ())
+ {
+ //only collect features from non-redundant langsys
+ const LangSys& d = get_default_lang_sys ();
+ if (c->visitLangsys (d.get_feature_count ())) {
+ d.collect_features (c);
+ }
+
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ {
+ const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ if (l.compare (d, c->duplicate_feature_map)) continue;
+
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.second);
+ }
+ }
+ else
+ {
+ for (auto _ : + hb_zip (langSys, hb_range (langsys_count)))
+ {
+ const LangSys& l = this+_.first.offset;
+ if (!c->visitLangsys (l.get_feature_count ())) continue;
+ l.collect_features (c);
+ c->script_langsys_map->get (script_index)->add (_.second);
+ }
+ }
+ }
+
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l,
+ const Tag *tag) const
+ {
+ TRACE_SUBSET (this);
+ if (!l->visitScript ()) return_trace (false);
+ if (tag && !c->plan->layout_scripts->has (*tag))
+ return false;
+
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ bool defaultLang = false;
+ if (has_default_lang_sys ())
+ {
+ c->serializer->push ();
+ const LangSys& ls = this+defaultLangSys;
+ bool ret = ls.subset (c, l);
+ if (!ret && tag && *tag != HB_TAG ('D', 'F', 'L', 'T'))
+ {
+ c->serializer->pop_discard ();
+ out->defaultLangSys = 0;
+ }
+ else
+ {
+ c->serializer->add_link (out->defaultLangSys, c->serializer->pop_pack ());
+ defaultLang = true;
+ }
+ }
+
+ const hb_set_t *active_langsys = l->script_langsys_map->get (l->cur_script_index);
+ if (active_langsys)
+ {
+ unsigned count = langSys.len;
+ + hb_zip (langSys, hb_range (count))
+ | hb_filter (active_langsys, hb_second)
+ | hb_map (hb_first)
+ | hb_filter ([=] (const Record<LangSys>& record) {return l->visitLangSys (); })
+ | hb_apply (subset_record_array (l, &(out->langSys), this))
+ ;
+ }
+
+ return_trace (bool (out->langSys.len) || defaultLang || l->table_tag == HB_OT_TAG_GSUB);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const Record_sanitize_closure_t * = nullptr) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
+ }
+
+ protected:
+ Offset16To<LangSys>
+ defaultLangSys; /* Offset to DefaultLangSys table--from
+ * beginning of Script table--may be Null */
+ RecordArrayOf<LangSys>
+ langSys; /* Array of LangSysRecords--listed
+ * alphabetically by LangSysTag */
+ public:
+ DEFINE_SIZE_ARRAY_SIZED (4, langSys);
+};
+
+struct RecordListOfScript : RecordListOf<Script>
+{
+ bool subset (hb_subset_context_t *c,
+ hb_subset_layout_context_t *l) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (*this);
+ if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned count = this->len;
+ for (auto _ : + hb_zip (*this, hb_range (count)))
+ {
+ auto snap = c->serializer->snapshot ();
+ l->cur_script_index = _.second;
+ bool ret = _.first.subset (l, this);
+ if (!ret) c->serializer->revert (snap);
+ else out->len++;
+ }
+
+ return_trace (true);
+ }
+};
+
+typedef RecordListOfScript ScriptList;
+
+
+
struct LookupFlag : HBUINT16
{
enum Flags {
@@ -1361,7 +1313,7 @@ struct Lookup
if (unlikely (!get_subtables<TSubTable> ().sanitize (c, this, get_type ())))
return_trace (false);
- if (unlikely (get_type () == TSubTable::Extension && subtables && !c->get_edit_count ()))
+ if (unlikely (get_type () == TSubTable::Extension && !c->get_edit_count ()))
{
/* The spec says all subtables of an Extension lookup should
* have the same type, which shall not be the Extension type
@@ -1381,7 +1333,7 @@ struct Lookup
return_trace (true);
}
- private:
+ protected:
HBUINT16 lookupType; /* Different enumerations for GSUB and GPOS */
HBUINT16 lookupFlag; /* Lookup qualifiers */
Array16Of<Offset16>
@@ -1393,10 +1345,11 @@ struct Lookup
DEFINE_SIZE_ARRAY (6, subTable);
};
-typedef List16OfOffset16To<Lookup> LookupList;
+template <typename Types>
+using LookupList = List16OfOffsetTo<Lookup, typename Types::HBUINT>;
-template <typename TLookup>
-struct LookupOffsetList : List16OfOffset16To<TLookup>
+template <typename TLookup, typename OffsetType>
+struct LookupOffsetList : List16OfOffsetTo<TLookup, OffsetType>
{
bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const
@@ -1426,462 +1379,16 @@ struct LookupOffsetList : List16OfOffset16To<TLookup>
* Coverage Table
*/
-struct CoverageFormat1
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- unsigned int i;
- glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
- return i;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- return_trace (glyphArray.serialize (c, glyphs));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (glyphArray.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- for (const auto& g : glyphArray.as_array ())
- if (glyphs->has (g))
- return true;
- return false;
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- { return glyphs->has (glyphArray[index]); }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- unsigned count = glyphArray.len;
- for (unsigned i = 0; i < count; i++)
- if (glyphs->has (glyphArray[i]))
- intersect_glyphs->add (glyphArray[i]);
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- { return glyphs->add_sorted_array (glyphArray.as_array ()); }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }
- void fini () {}
- bool more () const { return i < c->glyphArray.len; }
- void next () { i++; }
- hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
- bool operator != (const iter_t& o) const
- { return i != o.i || c != o.c; }
-
- private:
- const struct CoverageFormat1 *c;
- unsigned int i;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 1 */
- SortedArray16Of<HBGlyphID16>
- glyphArray; /* Array of GlyphIDs--in numerical order */
- public:
- DEFINE_SIZE_ARRAY (4, glyphArray);
-};
-
-struct CoverageFormat2
-{
- friend struct Coverage;
-
- private:
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- const RangeRecord &range = rangeRecord.bsearch (glyph_id);
- return likely (range.first <= range.last)
- ? (unsigned int) range.value + (glyph_id - range.first)
- : NOT_COVERED;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- if (unlikely (!glyphs))
- {
- rangeRecord.len = 0;
- return_trace (true);
- }
-
- /* TODO(iter) Write more efficiently? */
-
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- }
-
- if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
-
- unsigned count = 0;
- unsigned range = (unsigned) -1;
- last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- {
- range++;
- rangeRecord[range].first = g;
- rangeRecord[range].value = count;
- }
- rangeRecord[range].last = g;
- last = g;
- count++;
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (rangeRecord.sanitize (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- if (range.intersects (glyphs))
- return true;
- return false;
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- {
- if (range.value <= index &&
- index < (unsigned int) range.value + (range.last - range.first) &&
- range.intersects (glyphs))
- return true;
- else if (index < range.value)
- return false;
- }
- return false;
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- for (const auto& range : rangeRecord.as_array ())
- {
- if (!range.intersects (glyphs)) continue;
- for (hb_codepoint_t g = range.first; g <= range.last; g++)
- if (glyphs->has (g)) intersect_glyphs->add (g);
- }
- }
-
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- unsigned int count = rangeRecord.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!rangeRecord[i].collect_coverage (glyphs)))
- return false;
- return true;
- }
-
- public:
- /* Older compilers need this to be public. */
- struct iter_t
- {
- void init (const CoverageFormat2 &c_)
- {
- c = &c_;
- coverage = 0;
- i = 0;
- j = c->rangeRecord.len ? c->rangeRecord[0].first : 0;
- if (unlikely (c->rangeRecord[0].first > c->rangeRecord[0].last))
- {
- /* Broken table. Skip. */
- i = c->rangeRecord.len;
- }
- }
- void fini () {}
- bool more () const { return i < c->rangeRecord.len; }
- void next ()
- {
- if (j >= c->rangeRecord[i].last)
- {
- i++;
- if (more ())
- {
- unsigned int old = coverage;
- j = c->rangeRecord[i].first;
- coverage = c->rangeRecord[i].value;
- if (unlikely (coverage != old + 1))
- {
- /* Broken table. Skip. Important to avoid DoS.
- * Also, our callers depend on coverage being
- * consecutive and monotonically increasing,
- * ie. iota(). */
- i = c->rangeRecord.len;
- return;
- }
- }
- return;
- }
- coverage++;
- j++;
- }
- hb_codepoint_t get_glyph () const { return j; }
- bool operator != (const iter_t& o) const
- { return i != o.i || j != o.j || c != o.c; }
-
- private:
- const struct CoverageFormat2 *c;
- unsigned int i, coverage;
- hb_codepoint_t j;
- };
- private:
-
- protected:
- HBUINT16 coverageFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
- rangeRecord; /* Array of glyph ranges--ordered by
- * Start GlyphID. rangeCount entries
- * long */
- public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
-};
-
-struct Coverage
-{
- /* Has interface. */
- static constexpr unsigned SENTINEL = NOT_COVERED;
- typedef unsigned int value_t;
- value_t operator [] (hb_codepoint_t k) const { return get (k); }
- bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
- /* Predicate. */
- bool operator () (hb_codepoint_t k) const { return has (k); }
-
- unsigned int get (hb_codepoint_t k) const { return get_coverage (k); }
- unsigned int get_coverage (hb_codepoint_t glyph_id) const
- {
- switch (u.format) {
- case 1: return u.format1.get_coverage (glyph_id);
- case 2: return u.format2.get_coverage (glyph_id);
- default:return NOT_COVERED;
- }
- }
-
- template <typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c, Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
-
- unsigned count = 0;
- unsigned num_ranges = 0;
- hb_codepoint_t last = (hb_codepoint_t) -2;
- for (auto g: glyphs)
- {
- if (last + 1 != g)
- num_ranges++;
- last = g;
- count++;
- }
- u.format = count <= num_ranges * 3 ? 1 : 2;
-
- switch (u.format)
- {
- case 1: return_trace (u.format1.serialize (c, glyphs));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + iter ()
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- bool ret = bool (it);
- Coverage_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!u.format.sanitize (c)) return_trace (false);
- switch (u.format)
- {
- case 1: return_trace (u.format1.sanitize (c));
- case 2: return_trace (u.format2.sanitize (c));
- default:return_trace (true);
- }
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects (glyphs);
- case 2: return u.format2.intersects (glyphs);
- default:return false;
- }
- }
- bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersects_coverage (glyphs, index);
- case 2: return u.format2.intersects_coverage (glyphs, index);
- default:return false;
- }
- }
-
- /* Might return false if array looks unsorted.
- * Used for faster rejection of corrupt data. */
- template <typename set_t>
- bool collect_coverage (set_t *glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.collect_coverage (glyphs);
- case 2: return u.format2.collect_coverage (glyphs);
- default:return false;
- }
- }
-
- void intersected_coverage_glyphs (const hb_set_t *glyphs, hb_set_t *intersect_glyphs) const
- {
- switch (u.format)
- {
- case 1: return u.format1.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- case 2: return u.format2.intersected_coverage_glyphs (glyphs, intersect_glyphs);
- default:return ;
- }
- }
-
- struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
- {
- static constexpr bool is_sorted_iterator = true;
- iter_t (const Coverage &c_ = Null (Coverage))
- {
- memset (this, 0, sizeof (*this));
- format = c_.u.format;
- switch (format)
- {
- case 1: u.format1.init (c_.u.format1); return;
- case 2: u.format2.init (c_.u.format2); return;
- default: return;
- }
- }
- bool __more__ () const
- {
- switch (format)
- {
- case 1: return u.format1.more ();
- case 2: return u.format2.more ();
- default:return false;
- }
- }
- void __next__ ()
- {
- switch (format)
- {
- case 1: u.format1.next (); break;
- case 2: u.format2.next (); break;
- default: break;
- }
- }
- typedef hb_codepoint_t __item_t__;
- __item_t__ __item__ () const { return get_glyph (); }
-
- hb_codepoint_t get_glyph () const
- {
- switch (format)
- {
- case 1: return u.format1.get_glyph ();
- case 2: return u.format2.get_glyph ();
- default:return 0;
- }
- }
- bool operator != (const iter_t& o) const
- {
- if (format != o.format) return true;
- switch (format)
- {
- case 1: return u.format1 != o.u.format1;
- case 2: return u.format2 != o.u.format2;
- default:return false;
- }
- }
-
- private:
- unsigned int format;
- union {
- CoverageFormat2::iter_t format2; /* Put this one first since it's larger; helps shut up compiler. */
- CoverageFormat1::iter_t format1;
- } u;
- };
- iter_t iter () const { return iter_t (*this); }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CoverageFormat1 format1;
- CoverageFormat2 format2;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-template<typename Iterator>
-static inline void
-Coverage_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<Coverage> ()->serialize (c, it); }
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
const hb_set_t &klasses,
bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/)
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/)
{
if (!klass_map)
{
- ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
- | hb_map (gid_klass_map)));
+ ClassDef_serialize (c, glyph_and_klass.iter ());
return;
}
@@ -1898,24 +1405,23 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
idx++;
}
- auto it =
- + glyphs.iter ()
- | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
- {
- unsigned new_klass = klass_map->get (gid_klass_map[gid]);
- return hb_pair ((hb_codepoint_t)gid, new_klass);
- })
- ;
- c->propagate_error (glyphs, klasses);
- ClassDef_serialize (c, it);
+ for (unsigned i = 0; i < glyph_and_klass.length; i++)
+ {
+ hb_codepoint_t klass = glyph_and_klass[i].second;
+ glyph_and_klass[i].second = klass_map->get (klass);
+ }
+
+ c->propagate_error (glyph_and_klass, klasses);
+ ClassDef_serialize (c, glyph_and_klass.iter ());
}
/*
* Class Definition Table
*/
-struct ClassDefFormat1
+template <typename Types>
+struct ClassDefFormat1_3
{
friend struct ClassDef;
@@ -1926,7 +1432,7 @@ struct ClassDefFormat1
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -1964,36 +1470,37 @@ struct ClassDefFormat1
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = start + classValue.len;
- for (const hb_codepoint_t gid : + hb_range (start, end)
- | hb_filter (glyphset))
+ for (const hb_codepoint_t gid : + hb_range (start, end))
{
+ hb_codepoint_t new_gid = glyph_map[gid];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has(gid)) continue;
unsigned klass = classValue[gid - start];
if (!klass) continue;
- glyphs.push (glyph_map[gid]);
- gid_org_klass_map.set (glyph_map[gid], klass);
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
unsigned glyph_count = glyph_filter
- ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2002,6 +1509,8 @@ struct ClassDefFormat1
return_trace (c->check_struct (this) && classValue.sanitize (c));
}
+ unsigned cost () const { return 1; }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
@@ -2059,10 +1568,9 @@ struct ClassDefFormat1
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i] == k && glyphs->has (startGlyph + i))
+ if (arr[i] == klass && glyphs->has (startGlyph + i))
return true;
return false;
}
@@ -2072,17 +1580,32 @@ struct ClassDefFormat1
unsigned count = classValue.len;
if (klass == 0)
{
- hb_codepoint_t endGlyph = startGlyph + count -1;
- for (hb_codepoint_t g : glyphs->iter ())
- if (g < startGlyph || g > endGlyph)
- intersect_glyphs->add (g);
+ unsigned start_glyph = startGlyph;
+ for (unsigned g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g) && g < start_glyph;)
+ intersect_glyphs->add (g);
+
+ for (unsigned g = startGlyph + count - 1;
+ hb_set_next (glyphs, &g);)
+ intersect_glyphs->add (g);
return;
}
for (unsigned i = 0; i < count; i++)
if (classValue[i] == klass && glyphs->has (startGlyph + i))
- intersect_glyphs->add (startGlyph + i);
+ intersect_glyphs->add (startGlyph + i);
+
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ unsigned start_glyph = startGlyph;
+ unsigned end_glyph = start_glyph + count;
+ for (unsigned g = startGlyph - 1;
+ hb_set_next (glyphs, &g) && g < end_glyph;)
+ if (classValue.arrayZ[g - start_glyph] == klass)
+ intersect_glyphs->add (g);
+#endif
}
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
@@ -2103,14 +1626,16 @@ struct ClassDefFormat1
protected:
HBUINT16 classFormat; /* Format identifier--format = 1 */
- HBGlyphID16 startGlyph; /* First GlyphID of the classValueArray */
- Array16Of<HBUINT16>
+ typename Types::HBGlyphID
+ startGlyph; /* First GlyphID of the classValueArray */
+ typename Types::template ArrayOf<HBUINT16>
classValue; /* Array of Class Values--one per GlyphID */
public:
- DEFINE_SIZE_ARRAY (6, classValue);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, classValue);
};
-struct ClassDefFormat2
+template <typename Types>
+struct ClassDefFormat2_4
{
friend struct ClassDef;
@@ -2121,7 +1646,7 @@ struct ClassDefFormat2
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c,
Iterator it)
{
@@ -2139,12 +1664,12 @@ struct ClassDefFormat2
hb_codepoint_t prev_gid = (*it).first;
unsigned prev_klass = (*it).second;
- RangeRecord range_rec;
+ RangeRecord<Types> range_rec;
range_rec.first = prev_gid;
range_rec.last = prev_gid;
range_rec.value = prev_klass;
- RangeRecord *record = c->copy (range_rec);
+ auto *record = c->copy (range_rec);
if (unlikely (!record)) return_trace (false);
for (const auto gid_klass_pair : + (++it))
@@ -2182,37 +1707,41 @@ struct ClassDefFormat2
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
+ unsigned num_source_glyphs = c->plan->source->get_num_glyphs ();
unsigned count = rangeRecord.len;
for (unsigned i = 0; i < count; i++)
{
unsigned klass = rangeRecord[i].value;
if (!klass) continue;
hb_codepoint_t start = rangeRecord[i].first;
- hb_codepoint_t end = rangeRecord[i].last + 1;
+ hb_codepoint_t end = hb_min (rangeRecord[i].last + 1, num_source_glyphs);
for (hb_codepoint_t g = start; g < end; g++)
{
- if (!glyphset.has (g)) continue;
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has (g)) continue;
- glyphs.push (glyph_map[g]);
- gid_org_klass_map.set (glyph_map[g], klass);
+
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
}
+ const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
unsigned glyph_count = glyph_filter
? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2221,6 +1750,8 @@ struct ClassDefFormat2
return_trace (rangeRecord.sanitize (c));
}
+ unsigned cost () const { return hb_bit_storage ((unsigned) rangeRecord.len); /* bsearch cost */ }
+
template <typename set_t>
bool collect_coverage (set_t *glyphs) const
{
@@ -2252,7 +1783,7 @@ struct ClassDefFormat2
for (unsigned int i = 0; i < count; i++)
{
const auto& range = rangeRecord[i];
- if (range.intersects (glyphs) && range.value)
+ if (range.intersects (*glyphs) && range.value)
return true;
}
return false;
@@ -2276,12 +1807,8 @@ struct ClassDefFormat2
return true;
/* Fall through. */
}
- /* TODO Speed up, using set overlap first? */
- /* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
- const RangeRecord *arr = rangeRecord.arrayZ;
- for (unsigned int i = 0; i < count; i++)
- if (arr[i].value == k && arr[i].intersects (glyphs))
+ for (const auto &range : rangeRecord)
+ if (range.value == klass && range.intersects (*glyphs))
return true;
return false;
}
@@ -2294,43 +1821,44 @@ struct ClassDefFormat2
hb_codepoint_t g = HB_SET_VALUE_INVALID;
for (unsigned int i = 0; i < count; i++)
{
- if (!hb_set_next (glyphs, &g))
- break;
- while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first)
- {
- intersect_glyphs->add (g);
- hb_set_next (glyphs, &g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
+ while (g < rangeRecord[i].first)
+ {
+ intersect_glyphs->add (g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
}
g = rangeRecord[i].last;
}
- while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
- intersect_glyphs->add (g);
+ while (hb_set_next (glyphs, &g))
+ intersect_glyphs->add (g);
+ done:
return;
}
- hb_codepoint_t g = HB_SET_VALUE_INVALID;
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ if ((count >> 3) > glyphs->get_population ())
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g);)
+ if (rangeRecord.as_array ().bfind (g))
+ intersect_glyphs->add (g);
+ return;
+ }
+#endif
+
for (unsigned int i = 0; i < count; i++)
{
if (rangeRecord[i].value != klass) continue;
- if (g != HB_SET_VALUE_INVALID)
- {
- if (g >= rangeRecord[i].first &&
- g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- if (g > rangeRecord[i].last)
- continue;
- }
-
- g = rangeRecord[i].first - 1;
- while (hb_set_next (glyphs, &g))
- {
- if (g >= rangeRecord[i].first && g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- else if (g > rangeRecord[i].last)
- break;
- }
+ unsigned end = rangeRecord[i].last + 1;
+ for (hb_codepoint_t g = rangeRecord[i].first - 1;
+ hb_set_next (glyphs, &g) && g < end;)
+ intersect_glyphs->add (g);
}
}
@@ -2354,18 +1882,18 @@ struct ClassDefFormat2
if (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
intersect_classes->add (0);
- for (const RangeRecord& record : rangeRecord.iter ())
- if (record.intersects (glyphs))
+ for (const auto& record : rangeRecord.iter ())
+ if (record.intersects (*glyphs))
intersect_classes->add (record.value);
}
protected:
HBUINT16 classFormat; /* Format identifier--format = 2 */
- SortedArray16Of<RangeRecord>
+ typename Types::template SortedArrayOf<RangeRecord<Types>>
rangeRecord; /* Array of glyph ranges--ordered by
* Start GlyphID */
public:
- DEFINE_SIZE_ARRAY (4, rangeRecord);
+ DEFINE_SIZE_ARRAY (2 + Types::size, rangeRecord);
};
struct ClassDef
@@ -2384,12 +1912,16 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.get_class (glyph_id);
case 2: return u.format2.get_class (glyph_id);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.get_class (glyph_id);
+ case 4: return u.format4.get_class (glyph_id);
+#endif
default:return 0;
}
}
template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
+ hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
bool serialize (hb_serialize_context_t *c, Iterator it_with_class_zero)
{
TRACE_SERIALIZE (this);
@@ -2398,10 +1930,11 @@ struct ClassDef
auto it = + it_with_class_zero | hb_filter (hb_second);
unsigned format = 2;
+ hb_codepoint_t glyph_max = 0;
if (likely (it))
{
hb_codepoint_t glyph_min = (*it).first;
- hb_codepoint_t glyph_max = glyph_min;
+ glyph_max = glyph_min;
unsigned num_glyphs = 0;
unsigned num_ranges = 1;
@@ -2426,12 +1959,22 @@ struct ClassDef
if (num_glyphs && 1 + (glyph_max - glyph_min + 1) <= num_ranges * 3)
format = 1;
}
+
+#ifndef HB_NO_BEYOND_64K
+ if (glyph_max > 0xFFFFu)
+ format += 2;
+#endif
+
u.format = format;
switch (u.format)
{
case 1: return_trace (u.format1.serialize (c, it));
case 2: return_trace (u.format2.serialize (c, it));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.serialize (c, it));
+ case 4: return_trace (u.format4.serialize (c, it));
+#endif
default:return_trace (false);
}
}
@@ -2446,6 +1989,10 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
case 2: return_trace (u.format2.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+ case 4: return_trace (u.format4.subset (c, klass_map, keep_empty_table, use_class_zero, glyph_filter));
+#endif
default:return_trace (false);
}
}
@@ -2457,10 +2004,27 @@ struct ClassDef
switch (u.format) {
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 3: return_trace (u.format3.sanitize (c));
+ case 4: return_trace (u.format4.sanitize (c));
+#endif
default:return_trace (true);
}
}
+ unsigned cost () const
+ {
+ switch (u.format) {
+ case 1: return u.format1.cost ();
+ case 2: return u.format2.cost ();
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.cost ();
+ case 4: return u.format4.cost ();
+#endif
+ default:return 0u;
+ }
+ }
+
/* Might return false if array looks unsorted.
* Used for faster rejection of corrupt data. */
template <typename set_t>
@@ -2469,6 +2033,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_coverage (glyphs);
case 2: return u.format2.collect_coverage (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_coverage (glyphs);
+ case 4: return u.format4.collect_coverage (glyphs);
+#endif
default:return false;
}
}
@@ -2481,6 +2049,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.collect_class (glyphs, klass);
case 2: return u.format2.collect_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.collect_class (glyphs, klass);
+ case 4: return u.format4.collect_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2490,6 +2062,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects (glyphs);
case 2: return u.format2.intersects (glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects (glyphs);
+ case 4: return u.format4.intersects (glyphs);
+#endif
default:return false;
}
}
@@ -2498,6 +2074,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersects_class (glyphs, klass);
case 2: return u.format2.intersects_class (glyphs, klass);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersects_class (glyphs, klass);
+ case 4: return u.format4.intersects_class (glyphs, klass);
+#endif
default:return false;
}
}
@@ -2507,6 +2087,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
case 2: return u.format2.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+ case 4: return u.format4.intersected_class_glyphs (glyphs, klass, intersect_glyphs);
+#endif
default:return;
}
}
@@ -2516,6 +2100,10 @@ struct ClassDef
switch (u.format) {
case 1: return u.format1.intersected_classes (glyphs, intersect_classes);
case 2: return u.format2.intersected_classes (glyphs, intersect_classes);
+#ifndef HB_NO_BEYOND_64K
+ case 3: return u.format3.intersected_classes (glyphs, intersect_classes);
+ case 4: return u.format4.intersected_classes (glyphs, intersect_classes);
+#endif
default:return;
}
}
@@ -2523,9 +2111,13 @@ struct ClassDef
protected:
union {
- HBUINT16 format; /* Format identifier */
- ClassDefFormat1 format1;
- ClassDefFormat2 format2;
+ HBUINT16 format; /* Format identifier */
+ ClassDefFormat1_3<SmallTypes> format1;
+ ClassDefFormat2_4<SmallTypes> format2;
+#ifndef HB_NO_BEYOND_64K
+ ClassDefFormat1_3<MediumTypes>format3;
+ ClassDefFormat2_4<MediumTypes>format4;
+#endif
} u;
public:
DEFINE_SIZE_UNION (2, format);
@@ -2582,14 +2174,27 @@ struct VarRegionAxis
DEFINE_SIZE_STATIC (6);
};
+#define REGION_CACHE_ITEM_CACHE_INVALID 2.f
+
struct VarRegionList
{
+ using cache_t = float;
+
float evaluate (unsigned int region_index,
- const int *coords, unsigned int coord_len) const
+ const int *coords, unsigned int coord_len,
+ cache_t *cache = nullptr) const
{
if (unlikely (region_index >= regionCount))
return 0.;
+ float *cached_value = nullptr;
+ if (cache)
+ {
+ cached_value = &(cache[region_index]);
+ if (likely (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID))
+ return *cached_value;
+ }
+
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
float v = 1.;
@@ -2599,9 +2204,16 @@ struct VarRegionList
int coord = i < coord_len ? coords[i] : 0;
float factor = axes[i].evaluate (coord);
if (factor == 0.f)
+ {
+ if (cache)
+ *cached_value = 0.;
return 0.;
+ }
v *= factor;
}
+
+ if (cache)
+ *cached_value = v;
return v;
}
@@ -2649,7 +2261,7 @@ struct VarData
{ return regionIndices.len; }
unsigned int get_row_size () const
- { return shortCount + regionIndices.len; }
+ { return (wordCount () + regionIndices.len) * (longWords () ? 2 : 1); }
unsigned int get_size () const
{ return min_size
@@ -2659,13 +2271,17 @@ struct VarData
float get_delta (unsigned int inner,
const int *coords, unsigned int coord_count,
- const VarRegionList &regions) const
+ const VarRegionList &regions,
+ VarRegionList::cache_t *cache = nullptr) const
{
if (unlikely (inner >= itemCount))
return 0.;
unsigned int count = regionIndices.len;
- unsigned int scount = shortCount;
+ bool is_long = longWords ();
+ unsigned word_count = wordCount ();
+ unsigned int scount = is_long ? count - word_count : word_count;
+ unsigned int lcount = is_long ? word_count : 0;
const HBUINT8 *bytes = get_delta_bytes ();
const HBUINT8 *row = bytes + inner * (scount + count);
@@ -2673,16 +2289,22 @@ struct VarData
float delta = 0.;
unsigned int i = 0;
- const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (row);
+ const HBINT16 *lcursor = reinterpret_cast<const HBINT16 *> (row);
+ for (; i < lcount; i++)
+ {
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
+ delta += scalar * *lcursor++;
+ }
+ const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
for (; i < scount; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *scursor++;
}
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
for (; i < count; i++)
{
- float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
+ float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
delta += scalar * *bcursor++;
}
@@ -2706,7 +2328,7 @@ struct VarData
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) &&
regionIndices.sanitize (c) &&
- shortCount <= regionIndices.len &&
+ wordCount () <= regionIndices.len &&
c->check_range (get_delta_bytes (),
itemCount,
get_row_size ()));
@@ -2721,43 +2343,66 @@ struct VarData
if (unlikely (!c->extend_min (this))) return_trace (false);
itemCount = inner_map.get_next_value ();
- /* Optimize short count */
- unsigned short ri_count = src->regionIndices.len;
- enum delta_size_t { kZero=0, kByte, kShort };
+ /* Optimize word count */
+ unsigned ri_count = src->regionIndices.len;
+ enum delta_size_t { kZero=0, kNonWord, kWord };
hb_vector_t<delta_size_t> delta_sz;
hb_vector_t<unsigned int> ri_map; /* maps old index to new index */
delta_sz.resize (ri_count);
ri_map.resize (ri_count);
- unsigned int new_short_count = 0;
+ unsigned int new_word_count = 0;
unsigned int r;
+
+ bool has_long = false;
+ if (src->longWords ())
+ {
+ for (r = 0; r < ri_count; r++)
+ {
+ for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
+ {
+ unsigned int old = inner_map.backward (i);
+ int32_t delta = src->get_item_delta (old, r);
+ if (delta < -65536 || 65535 < delta)
+ {
+ has_long = true;
+ break;
+ }
+ }
+ }
+ }
+
+ signed min_threshold = has_long ? -65536 : -128;
+ signed max_threshold = has_long ? +65535 : +127;
for (r = 0; r < ri_count; r++)
{
delta_sz[r] = kZero;
for (unsigned int i = 0; i < inner_map.get_next_value (); i++)
{
unsigned int old = inner_map.backward (i);
- int16_t delta = src->get_item_delta (old, r);
- if (delta < -128 || 127 < delta)
+ int32_t delta = src->get_item_delta (old, r);
+ if (delta < min_threshold || max_threshold < delta)
{
- delta_sz[r] = kShort;
- new_short_count++;
+ delta_sz[r] = kWord;
+ new_word_count++;
break;
}
else if (delta != 0)
- delta_sz[r] = kByte;
+ delta_sz[r] = kNonWord;
}
}
- unsigned int short_index = 0;
- unsigned int byte_index = new_short_count;
+
+ unsigned int word_index = 0;
+ unsigned int non_word_index = new_word_count;
unsigned int new_ri_count = 0;
for (r = 0; r < ri_count; r++)
if (delta_sz[r])
{
- ri_map[r] = (delta_sz[r] == kShort)? short_index++ : byte_index++;
+ ri_map[r] = (delta_sz[r] == kWord)? word_index++ : non_word_index++;
new_ri_count++;
}
- shortCount = new_short_count;
+ wordSizeCount = new_word_count | (has_long ? 0x8000u /* LONG_WORDS */ : 0);
+
regionIndices.len = new_ri_count;
if (unlikely (!c->extend (this))) return_trace (false);
@@ -2797,28 +2442,55 @@ struct VarData
HBUINT8 *get_delta_bytes ()
{ return &StructAfter<HBUINT8> (regionIndices); }
- int16_t get_item_delta (unsigned int item, unsigned int region) const
+ int32_t get_item_delta (unsigned int item, unsigned int region) const
{
if ( item >= itemCount || unlikely (region >= regionIndices.len)) return 0;
- const HBINT8 *p = (const HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- return ((const HBINT16 *)p)[region];
+ const HBINT8 *p = (const HBINT8 *) get_delta_bytes () + item * get_row_size ();
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ return ((const HBINT32 *) p)[region];
+ else
+ return ((const HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count];
+ }
else
- return (p + HBINT16::static_size * shortCount)[region - shortCount];
+ {
+ if (region < word_count)
+ return ((const HBINT16 *) p)[region];
+ else
+ return (p + HBINT16::static_size * word_count)[region - word_count];
+ }
}
- void set_item_delta (unsigned int item, unsigned int region, int16_t delta)
+ void set_item_delta (unsigned int item, unsigned int region, int32_t delta)
{
HBINT8 *p = (HBINT8 *)get_delta_bytes () + item * get_row_size ();
- if (region < shortCount)
- ((HBINT16 *)p)[region] = delta;
+ unsigned word_count = wordCount ();
+ bool is_long = longWords ();
+ if (is_long)
+ {
+ if (region < word_count)
+ ((HBINT32 *) p)[region] = delta;
+ else
+ ((HBINT16 *)(p + HBINT32::static_size * word_count))[region - word_count] = delta;
+ }
else
- (p + HBINT16::static_size * shortCount)[region - shortCount] = delta;
+ {
+ if (region < word_count)
+ ((HBINT16 *) p)[region] = delta;
+ else
+ (p + HBINT16::static_size * word_count)[region - word_count] = delta;
+ }
}
+ bool longWords () const { return wordSizeCount & 0x8000u /* LONG_WORDS */; }
+ unsigned wordCount () const { return wordSizeCount & 0x7FFFu /* WORD_DELTA_COUNT_MASK */; }
+
protected:
HBUINT16 itemCount;
- HBUINT16 shortCount;
+ HBUINT16 wordSizeCount;
Array16Of<HBUINT16> regionIndices;
/*UnsizedArrayOf<HBUINT8>bytesX;*/
public:
@@ -2827,9 +2499,31 @@ struct VarData
struct VariationStore
{
+ using cache_t = VarRegionList::cache_t;
+
+ cache_t *create_cache () const
+ {
+#ifdef HB_NO_VAR
+ return nullptr;
+#endif
+ auto &r = this+regions;
+ unsigned count = r.regionCount;
+
+ float *cache = (float *) hb_malloc (sizeof (float) * count);
+ if (unlikely (!cache)) return nullptr;
+
+ for (unsigned i = 0; i < count; i++)
+ cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
+
+ return cache;
+ }
+
+ static void destroy_cache (cache_t *cache) { hb_free (cache); }
+
private:
float get_delta (unsigned int outer, unsigned int inner,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
#ifdef HB_NO_VAR
return 0.f;
@@ -2840,16 +2534,18 @@ struct VariationStore
return (this+dataSets[outer]).get_delta (inner,
coords, coord_count,
- this+regions);
+ this+regions,
+ cache);
}
public:
float get_delta (unsigned int index,
- const int *coords, unsigned int coord_count) const
+ const int *coords, unsigned int coord_count,
+ VarRegionList::cache_t *cache = nullptr) const
{
unsigned int outer = index >> 16;
unsigned int inner = index & 0xFFFF;
- return get_delta (outer, inner, coords, coord_count);
+ return get_delta (outer, inner, coords, coord_count, cache);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2870,6 +2566,10 @@ struct VariationStore
const hb_array_t <hb_inc_bimap_t> &inner_maps)
{
TRACE_SERIALIZE (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
+
if (unlikely (!c->extend_min (this))) return_trace (false);
unsigned int set_count = 0;
@@ -2921,6 +2621,9 @@ struct VariationStore
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
+#ifdef HB_NO_VAR
+ return_trace (false);
+#endif
VariationStore *varstore_prime = c->serializer->start_embed<VariationStore> ();
if (unlikely (!varstore_prime)) return_trace (false);
@@ -2948,7 +2651,12 @@ struct VariationStore
}
unsigned int get_region_index_count (unsigned int major) const
- { return (this+dataSets[major]).get_region_index_count (); }
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return (this+dataSets[major]).get_region_index_count ();
+ }
void get_region_scalars (unsigned int major,
const int *coords, unsigned int coord_count,
@@ -2966,7 +2674,13 @@ struct VariationStore
&scalars[0], num_scalars);
}
- unsigned int get_sub_table_count () const { return dataSets.len; }
+ unsigned int get_sub_table_count () const
+ {
+#ifdef HB_NO_VAR
+ return 0;
+#endif
+ return dataSets.len;
+ }
protected:
HBUINT16 format;
@@ -2976,6 +2690,8 @@ struct VariationStore
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
};
+#undef REGION_CACHE_ITEM_CACHE_INVALID
+
/*
* Feature Variations
*/
@@ -3443,11 +3159,15 @@ struct VariationDevice
private:
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_x (get_delta (font, store)); }
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_x (get_delta (font, store, store_cache)); }
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store) const
- { return font->em_scalef_y (get_delta (font, store)); }
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
+ { return font->em_scalef_y (get_delta (font, store, store_cache)); }
VariationDevice* copy (hb_serialize_context_t *c, const hb_map_t *layout_variation_idx_map) const
{
@@ -3481,9 +3201,11 @@ struct VariationDevice
private:
- float get_delta (hb_font_t *font, const VariationStore &store) const
+ float get_delta (hb_font_t *font,
+ const VariationStore &store,
+ VariationStore::cache_t *store_cache = nullptr) const
{
- return store.get_delta (varIdx, font->coords, font->num_coords);
+ return store.get_delta (varIdx, font->coords, font->num_coords, (VariationStore::cache_t *) store_cache);
}
protected:
@@ -3506,7 +3228,9 @@ struct DeviceHeader
struct Device
{
- hb_position_t get_x_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_x_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3516,13 +3240,15 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_x_delta (font, store);
+ return u.variation.get_x_delta (font, store, store_cache);
#endif
default:
return 0;
}
}
- hb_position_t get_y_delta (hb_font_t *font, const VariationStore &store=Null (VariationStore)) const
+ hb_position_t get_y_delta (hb_font_t *font,
+ const VariationStore &store=Null (VariationStore),
+ VariationStore::cache_t *store_cache = nullptr) const
{
switch (u.b.format)
{
@@ -3532,7 +3258,7 @@ struct Device
#endif
#ifndef HB_NO_VAR
case 0x8000:
- return u.variation.get_y_delta (font, store);
+ return u.variation.get_y_delta (font, store, store_cache);
#endif
default:
return 0;
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
index a76d644c4b..5bc26d9182 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gdef-table.hh
@@ -510,6 +510,101 @@ struct MarkGlyphSets
*/
+template <typename Types>
+struct GDEFVersion1_2
+{
+ friend struct GDEF;
+
+ protected:
+ FixedVersion<>version; /* Version of the GDEF table--currently
+ * 0x00010003u */
+ typename Types::template OffsetTo<ClassDef>
+ glyphClassDef; /* Offset to class definition table
+ * for glyph type--from beginning of
+ * GDEF header (may be Null) */
+ typename Types::template OffsetTo<AttachList>
+ attachList; /* Offset to list of glyphs with
+ * attachment points--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<LigCaretList>
+ ligCaretList; /* Offset to list of positioning points
+ * for ligature carets--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<ClassDef>
+ markAttachClassDef; /* Offset to class definition table for
+ * mark attachment type--from beginning
+ * of GDEF header (may be Null) */
+ typename Types::template OffsetTo<MarkGlyphSets>
+ markGlyphSetsDef; /* Offset to the table of mark set
+ * definitions--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010002. */
+ Offset32To<VariationStore>
+ varStore; /* Offset to the table of Item Variation
+ * Store--from beginning of GDEF
+ * header (may be NULL). Introduced
+ * in version 0x00010003. */
+ public:
+ DEFINE_SIZE_MIN (4 + 4 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
+ (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (version.sanitize (c) &&
+ glyphClassDef.sanitize (c, this) &&
+ attachList.sanitize (c, this) &&
+ ligCaretList.sanitize (c, this) &&
+ markAttachClassDef.sanitize (c, this) &&
+ (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
+ (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
+ bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
+ bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
+ bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
+
+ bool subset_markglyphsetsdef = false;
+ if (version.to_int () >= 0x00010002u)
+ {
+ subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
+ }
+
+ bool subset_varstore = false;
+ if (version.to_int () >= 0x00010003u)
+ {
+ subset_varstore = out->varStore.serialize_subset (c, varStore, this);
+ }
+
+ if (subset_varstore)
+ {
+ out->version.minor = 3;
+ } else if (subset_markglyphsetsdef) {
+ out->version.minor = 2;
+ } else {
+ out->version.minor = 0;
+ }
+
+ return_trace (subset_glyphclassdef || subset_attachlist ||
+ subset_ligcaretlist || subset_markattachclassdef ||
+ (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
+ (out->version.to_int () >= 0x00010003u && subset_varstore));
+ }
+};
+
struct GDEF
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_GDEF;
@@ -522,42 +617,190 @@ struct GDEF
ComponentGlyph = 4
};
- bool has_data () const { return version.to_int (); }
- bool has_glyph_classes () const { return glyphClassDef != 0; }
+ unsigned int get_size () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_size ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_size ();
+#endif
+ default: return u.version.static_size;
+ }
+ }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!u.version.sanitize (c))) return_trace (false);
+ switch (u.version.major) {
+ case 1: return_trace (u.version1.sanitize (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset (c);
+#endif
+ default: return false;
+ }
+ }
+
+ bool has_glyph_classes () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.glyphClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.glyphClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_glyph_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.glyphClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.glyphClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.attachList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.attachList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const AttachList &get_attach_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.attachList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.attachList;
+#endif
+ default: return Null(AttachList);
+ }
+ }
+ bool has_lig_carets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.ligCaretList != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.ligCaretList != 0;
+#endif
+ default: return false;
+ }
+ }
+ const LigCaretList &get_lig_caret_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.ligCaretList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.ligCaretList;
+#endif
+ default: return Null(LigCaretList);
+ }
+ }
+ bool has_mark_attachment_types () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.markAttachClassDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markAttachClassDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const ClassDef &get_mark_attach_class_def () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.markAttachClassDef;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markAttachClassDef;
+#endif
+ default: return Null(ClassDef);
+ }
+ }
+ bool has_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u && u.version1.markGlyphSetsDef != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.markGlyphSetsDef != 0;
+#endif
+ default: return false;
+ }
+ }
+ const MarkGlyphSets &get_mark_glyph_sets () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010002u ? this+u.version1.markGlyphSetsDef : Null(MarkGlyphSets);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.markGlyphSetsDef;
+#endif
+ default: return Null(MarkGlyphSets);
+ }
+ }
+ bool has_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u && u.version1.varStore != 0;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.varStore != 0;
+#endif
+ default: return false;
+ }
+ }
+ const VariationStore &get_var_store () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version.to_int () >= 0x00010003u ? this+u.version1.varStore : Null(VariationStore);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.varStore;
+#endif
+ default: return Null(VariationStore);
+ }
+ }
+
+
+ bool has_data () const { return u.version.to_int (); }
unsigned int get_glyph_class (hb_codepoint_t glyph) const
- { return (this+glyphClassDef).get_class (glyph); }
+ { return get_glyph_class_def ().get_class (glyph); }
void get_glyphs_in_class (unsigned int klass, hb_set_t *glyphs) const
- { (this+glyphClassDef).collect_class (glyphs, klass); }
+ { get_glyph_class_def ().collect_class (glyphs, klass); }
- bool has_mark_attachment_types () const { return markAttachClassDef != 0; }
unsigned int get_mark_attachment_type (hb_codepoint_t glyph) const
- { return (this+markAttachClassDef).get_class (glyph); }
+ { return get_mark_attach_class_def ().get_class (glyph); }
- bool has_attach_points () const { return attachList != 0; }
unsigned int get_attach_points (hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *point_count /* IN/OUT */,
unsigned int *point_array /* OUT */) const
- { return (this+attachList).get_attach_points (glyph_id, start_offset, point_count, point_array); }
+ { return get_attach_list ().get_attach_points (glyph_id, start_offset, point_count, point_array); }
- bool has_lig_carets () const { return ligCaretList != 0; }
unsigned int get_lig_carets (hb_font_t *font,
hb_direction_t direction,
hb_codepoint_t glyph_id,
unsigned int start_offset,
unsigned int *caret_count /* IN/OUT */,
hb_position_t *caret_array /* OUT */) const
- { return (this+ligCaretList).get_lig_carets (font,
- direction, glyph_id, get_var_store(),
- start_offset, caret_count, caret_array); }
+ { return get_lig_caret_list ().get_lig_carets (font,
+ direction, glyph_id, get_var_store(),
+ start_offset, caret_count, caret_array); }
- bool has_mark_sets () const { return version.to_int () >= 0x00010002u && markGlyphSetsDef != 0; }
bool mark_set_covers (unsigned int set_index, hb_codepoint_t glyph_id) const
- { return version.to_int () >= 0x00010002u && (this+markGlyphSetsDef).covers (set_index, glyph_id); }
-
- bool has_var_store () const { return version.to_int () >= 0x00010003u && varStore != 0; }
- const VariationStore &get_var_store () const
- { return version.to_int () >= 0x00010003u ? this+varStore : Null (VariationStore); }
+ { return get_mark_glyph_sets ().covers (set_index, glyph_id); }
/* glyph_props is a 16-bit integer where the lower 8-bit have bits representing
* glyph class and other bits, and high 8-bit the mark attachment type (if any).
@@ -571,7 +814,7 @@ struct GDEF
static_assert (((unsigned int) HB_OT_LAYOUT_GLYPH_PROPS_MARK == (unsigned int) LookupFlag::IgnoreMarks), "");
switch (klass) {
- default: return 0;
+ default: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
case BaseGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH;
case LigatureGlyph: return HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE;
case MarkGlyph:
@@ -599,20 +842,13 @@ struct GDEF
hb_blob_ptr_t<GDEF> table;
};
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010002u ? markGlyphSetsDef.static_size : 0) +
- (version.to_int () >= 0x00010003u ? varStore.static_size : 0);
- }
-
void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- { (this+ligCaretList).collect_variation_indices (c); }
+ { get_lig_caret_list ().collect_variation_indices (c); }
void remap_layout_variation_indices (const hb_set_t *layout_variation_indices,
hb_map_t *layout_variation_idx_map /* OUT */) const
{
- if (version.to_int () < 0x00010003u || !varStore) return;
+ if (!has_var_store ()) return;
if (layout_variation_indices->is_empty ()) return;
unsigned new_major = 0, new_minor = 0;
@@ -620,7 +856,7 @@ struct GDEF
for (unsigned idx : layout_variation_indices->iter ())
{
uint16_t major = idx >> 16;
- if (major >= (this+varStore).get_sub_table_count ()) break;
+ if (major >= get_var_store ().get_sub_table_count ()) break;
if (major != last_major)
{
new_minor = 0;
@@ -634,84 +870,16 @@ struct GDEF
}
}
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- bool subset_glyphclassdef = out->glyphClassDef.serialize_subset (c, glyphClassDef, this, nullptr, false, true);
- bool subset_attachlist = out->attachList.serialize_subset (c, attachList, this);
- bool subset_ligcaretlist = out->ligCaretList.serialize_subset (c, ligCaretList, this);
- bool subset_markattachclassdef = out->markAttachClassDef.serialize_subset (c, markAttachClassDef, this, nullptr, false, true);
-
- bool subset_markglyphsetsdef = true;
- if (version.to_int () >= 0x00010002u)
- {
- subset_markglyphsetsdef = out->markGlyphSetsDef.serialize_subset (c, markGlyphSetsDef, this);
- if (!subset_markglyphsetsdef &&
- version.to_int () == 0x00010002u)
- out->version.minor = 0;
- }
-
- bool subset_varstore = true;
- if (version.to_int () >= 0x00010003u)
- {
- subset_varstore = out->varStore.serialize_subset (c, varStore, this);
- if (!subset_varstore && version.to_int () == 0x00010003u)
- out->version.minor = 2;
- }
-
- return_trace (subset_glyphclassdef || subset_attachlist ||
- subset_ligcaretlist || subset_markattachclassdef ||
- (out->version.to_int () >= 0x00010002u && subset_markglyphsetsdef) ||
- (out->version.to_int () >= 0x00010003u && subset_varstore));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (version.sanitize (c) &&
- likely (version.major == 1) &&
- glyphClassDef.sanitize (c, this) &&
- attachList.sanitize (c, this) &&
- ligCaretList.sanitize (c, this) &&
- markAttachClassDef.sanitize (c, this) &&
- (version.to_int () < 0x00010002u || markGlyphSetsDef.sanitize (c, this)) &&
- (version.to_int () < 0x00010003u || varStore.sanitize (c, this)));
- }
-
protected:
- FixedVersion<>version; /* Version of the GDEF table--currently
- * 0x00010003u */
- Offset16To<ClassDef>
- glyphClassDef; /* Offset to class definition table
- * for glyph type--from beginning of
- * GDEF header (may be Null) */
- Offset16To<AttachList>
- attachList; /* Offset to list of glyphs with
- * attachment points--from beginning
- * of GDEF header (may be Null) */
- Offset16To<LigCaretList>
- ligCaretList; /* Offset to list of positioning points
- * for ligature carets--from beginning
- * of GDEF header (may be Null) */
- Offset16To<ClassDef>
- markAttachClassDef; /* Offset to class definition table for
- * mark attachment type--from beginning
- * of GDEF header (may be Null) */
- Offset16To<MarkGlyphSets>
- markGlyphSetsDef; /* Offset to the table of mark set
- * definitions--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010002. */
- Offset32To<VariationStore>
- varStore; /* Offset to the table of Item Variation
- * Store--from beginning of GDEF
- * header (may be NULL). Introduced
- * in version 0x00010003. */
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GDEFVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GDEFVersion1_2<MediumTypes> version2;
+#endif
+ } u;
public:
- DEFINE_SIZE_MIN (12);
+ DEFINE_SIZE_MIN (4);
};
struct GDEF_accelerator_t : GDEF::accelerator_t {
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
index 2f9186a2a7..8fe987fc50 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gpos-table.hh
@@ -29,3090 +29,14 @@
#ifndef HB_OT_LAYOUT_GPOS_TABLE_HH
#define HB_OT_LAYOUT_GPOS_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GPOS/GPOS.hh"
namespace OT {
+namespace Layout {
+namespace GPOS_impl {
-struct MarkArray;
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */);
-
-/* buffer **position** var allocations */
-#define attach_chain() var.i16[0] /* glyph to which this attaches to, relative to current glyphs; negative for going back, positive for forward. */
-#define attach_type() var.u8[2] /* attachment type */
-/* Note! if attach_chain() is zero, the value of attach_type() is irrelevant. */
-
-enum attach_type_t {
- ATTACH_TYPE_NONE = 0X00,
-
- /* Each attachment should be either a mark or a cursive; can't be both. */
- ATTACH_TYPE_MARK = 0X01,
- ATTACH_TYPE_CURSIVE = 0X02,
-};
-
-
-/* Shared Tables: ValueRecord, Anchor Table, and MarkArray */
-
-typedef HBUINT16 Value;
-
-typedef UnsizedArrayOf<Value> ValueRecord;
-
-struct ValueFormat : HBUINT16
-{
- enum Flags {
- xPlacement = 0x0001u, /* Includes horizontal adjustment for placement */
- yPlacement = 0x0002u, /* Includes vertical adjustment for placement */
- xAdvance = 0x0004u, /* Includes horizontal adjustment for advance */
- yAdvance = 0x0008u, /* Includes vertical adjustment for advance */
- xPlaDevice = 0x0010u, /* Includes horizontal Device table for placement */
- yPlaDevice = 0x0020u, /* Includes vertical Device table for placement */
- xAdvDevice = 0x0040u, /* Includes horizontal Device table for advance */
- yAdvDevice = 0x0080u, /* Includes vertical Device table for advance */
- ignored = 0x0F00u, /* Was used in TrueType Open for MM fonts */
- reserved = 0xF000u, /* For future use */
-
- devices = 0x00F0u /* Mask for having any Device table */
- };
-
-/* All fields are options. Only those available advance the value pointer. */
-#if 0
- HBINT16 xPlacement; /* Horizontal adjustment for
- * placement--in design units */
- HBINT16 yPlacement; /* Vertical adjustment for
- * placement--in design units */
- HBINT16 xAdvance; /* Horizontal adjustment for
- * advance--in design units (only used
- * for horizontal writing) */
- HBINT16 yAdvance; /* Vertical adjustment for advance--in
- * design units (only used for vertical
- * writing) */
- Offset16To<Device> xPlaDevice; /* Offset to Device table for
- * horizontal placement--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yPlaDevice; /* Offset to Device table for vertical
- * placement--measured from beginning
- * of PosTable (may be NULL) */
- Offset16To<Device> xAdvDevice; /* Offset to Device table for
- * horizontal advance--measured from
- * beginning of PosTable (may be NULL) */
- Offset16To<Device> yAdvDevice; /* Offset to Device table for vertical
- * advance--measured from beginning of
- * PosTable (may be NULL) */
-#endif
-
- IntType& operator = (uint16_t i) { v = i; return *this; }
-
- unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
- unsigned int get_size () const { return get_len () * Value::static_size; }
-
- bool apply_value (hb_ot_apply_context_t *c,
- const void *base,
- const Value *values,
- hb_glyph_position_t &glyph_pos) const
- {
- bool ret = false;
- unsigned int format = *this;
- if (!format) return ret;
-
- hb_font_t *font = c->font;
- bool horizontal =
-#ifndef HB_NO_VERTICAL
- HB_DIRECTION_IS_HORIZONTAL (c->direction)
-#else
- true
-#endif
- ;
-
- if (format & xPlacement) glyph_pos.x_offset += font->em_scale_x (get_short (values++, &ret));
- if (format & yPlacement) glyph_pos.y_offset += font->em_scale_y (get_short (values++, &ret));
- if (format & xAdvance) {
- if (likely (horizontal)) glyph_pos.x_advance += font->em_scale_x (get_short (values, &ret));
- values++;
- }
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (format & yAdvance) {
- if (unlikely (!horizontal)) glyph_pos.y_advance -= font->em_scale_y (get_short (values, &ret));
- values++;
- }
-
- if (!has_device ()) return ret;
-
- bool use_x_device = font->x_ppem || font->num_coords;
- bool use_y_device = font->y_ppem || font->num_coords;
-
- if (!use_x_device && !use_y_device) return ret;
-
- const VariationStore &store = c->var_store;
-
- /* pixel -> fractional pixel */
- if (format & xPlaDevice) {
- if (use_x_device) glyph_pos.x_offset += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yPlaDevice) {
- if (use_y_device) glyph_pos.y_offset += (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- if (format & xAdvDevice) {
- if (horizontal && use_x_device) glyph_pos.x_advance += (base + get_device (values, &ret)).get_x_delta (font, store);
- values++;
- }
- if (format & yAdvDevice) {
- /* y_advance values grow downward but font-space grows upward, hence negation */
- if (!horizontal && use_y_device) glyph_pos.y_advance -= (base + get_device (values, &ret)).get_y_delta (font, store);
- values++;
- }
- return ret;
- }
-
- unsigned int get_effective_format (const Value *values) const
- {
- unsigned int format = *this;
- for (unsigned flag = xPlacement; flag <= yAdvDevice; flag = flag << 1) {
- if (format & flag) should_drop (*values++, (Flags) flag, &format);
- }
-
- return format;
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned int get_effective_format (Iterator it) const {
- unsigned int new_format = 0;
-
- for (const hb_array_t<const Value>& values : it)
- new_format = new_format | get_effective_format (&values);
-
- return new_format;
- }
-
- void copy_values (hb_serialize_context_t *c,
- unsigned int new_format,
- const void *base,
- const Value *values,
- const hb_map_t *layout_variation_idx_map) const
- {
- unsigned int format = *this;
- if (!format) return;
-
- if (format & xPlacement) copy_value (c, new_format, xPlacement, *values++);
- if (format & yPlacement) copy_value (c, new_format, yPlacement, *values++);
- if (format & xAdvance) copy_value (c, new_format, xAdvance, *values++);
- if (format & yAdvance) copy_value (c, new_format, yAdvance, *values++);
-
- if (format & xPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yPlaDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & xAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- if (format & yAdvDevice) copy_device (c, base, values++, layout_variation_idx_map);
- }
-
- void copy_value (hb_serialize_context_t *c,
- unsigned int new_format,
- Flags flag,
- Value value) const
- {
- // Filter by new format.
- if (!(new_format & flag)) return;
- c->copy (value);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *base,
- const hb_array_t<const Value>& values) const
- {
- unsigned format = *this;
- unsigned i = 0;
- if (format & xPlacement) i++;
- if (format & yPlacement) i++;
- if (format & xAdvance) i++;
- if (format & yAdvance) i++;
- if (format & xPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yPlaDevice)
- {
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::xAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
-
- if (format & ValueFormat::yAdvDevice)
- {
-
- (base + get_device (&(values[i]))).collect_variation_indices (c->layout_variation_indices);
- i++;
- }
- }
-
- private:
- bool sanitize_value_devices (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- unsigned int format = *this;
-
- if (format & xPlacement) values++;
- if (format & yPlacement) values++;
- if (format & xAdvance) values++;
- if (format & yAdvance) values++;
-
- if ((format & xPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yPlaDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & xAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
- if ((format & yAdvDevice) && !get_device (values++).sanitize (c, base)) return false;
-
- return true;
- }
-
- static inline Offset16To<Device>& get_device (Value* value)
- {
- return *static_cast<Offset16To<Device> *> (value);
- }
- static inline const Offset16To<Device>& get_device (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *static_cast<const Offset16To<Device> *> (value);
- }
-
- bool copy_device (hb_serialize_context_t *c, const void *base,
- const Value *src_value, const hb_map_t *layout_variation_idx_map) const
- {
- Value *dst_value = c->copy (*src_value);
-
- if (!dst_value) return false;
- if (*dst_value == 0) return true;
-
- *dst_value = 0;
- c->push ();
- if ((base + get_device (src_value)).copy (c, layout_variation_idx_map))
- {
- c->add_link (*dst_value, c->pop_pack ());
- return true;
- }
- else
- {
- c->pop_discard ();
- return false;
- }
- }
-
- static inline const HBINT16& get_short (const Value* value, bool *worked=nullptr)
- {
- if (worked) *worked |= bool (*value);
- return *reinterpret_cast<const HBINT16 *> (value);
- }
-
- public:
-
- bool has_device () const
- {
- unsigned int format = *this;
- return (format & devices) != 0;
- }
-
- bool sanitize_value (hb_sanitize_context_t *c, const void *base, const Value *values) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_range (values, get_size ()) && (!has_device () || sanitize_value_devices (c, base, values)));
- }
-
- bool sanitize_values (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count) const
- {
- TRACE_SANITIZE (this);
- unsigned int len = get_len ();
-
- if (!c->check_range (values, count, get_size ())) return_trace (false);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += len;
- }
-
- return_trace (true);
- }
-
- /* Just sanitize referenced Device tables. Doesn't check the values themselves. */
- bool sanitize_values_stride_unsafe (hb_sanitize_context_t *c, const void *base, const Value *values, unsigned int count, unsigned int stride) const
- {
- TRACE_SANITIZE (this);
-
- if (!has_device ()) return_trace (true);
-
- for (unsigned int i = 0; i < count; i++) {
- if (!sanitize_value_devices (c, base, values))
- return_trace (false);
- values += stride;
- }
-
- return_trace (true);
- }
-
- private:
-
- void should_drop (Value value, Flags flag, unsigned int* format) const
- {
- if (value) return;
- *format = *format & ~flag;
- }
-
-};
-
-template<typename Iterator, typename SrcLookup>
-static void SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map);
-
-
-struct AnchorFormat1
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- AnchorFormat1* out = c->embed<AnchorFormat1> (this);
- if (!out) return_trace (out);
- out->format = 1;
- return_trace (out);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct AnchorFormat2
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
-
-#ifdef HB_NO_HINTING
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
- return;
-#endif
-
- unsigned int x_ppem = font->x_ppem;
- unsigned int y_ppem = font->y_ppem;
- hb_position_t cx = 0, cy = 0;
- bool ret;
-
- ret = (x_ppem || y_ppem) &&
- font->get_glyph_contour_point_for_origin (glyph_id, anchorPoint, HB_DIRECTION_LTR, &cx, &cy);
- *x = ret && x_ppem ? cx : font->em_fscale_x (xCoordinate);
- *y = ret && y_ppem ? cy : font->em_fscale_y (yCoordinate);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this));
- }
-
- AnchorFormat2* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- return_trace (c->embed<AnchorFormat2> (this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- HBUINT16 anchorPoint; /* Index to glyph contour point */
- public:
- DEFINE_SIZE_STATIC (8);
-};
-
-struct AnchorFormat3
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id HB_UNUSED,
- float *x, float *y) const
- {
- hb_font_t *font = c->font;
- *x = font->em_fscale_x (xCoordinate);
- *y = font->em_fscale_y (yCoordinate);
-
- if (font->x_ppem || font->num_coords)
- *x += (this+xDeviceTable).get_x_delta (font, c->var_store);
- if (font->y_ppem || font->num_coords)
- *y += (this+yDeviceTable).get_y_delta (font, c->var_store);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && xDeviceTable.sanitize (c, this) && yDeviceTable.sanitize (c, this));
- }
-
- AnchorFormat3* copy (hb_serialize_context_t *c,
- const hb_map_t *layout_variation_idx_map) const
- {
- TRACE_SERIALIZE (this);
- if (!layout_variation_idx_map) return_trace (nullptr);
-
- auto *out = c->embed<AnchorFormat3> (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->xDeviceTable.serialize_copy (c, xDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- out->yDeviceTable.serialize_copy (c, yDeviceTable, this, 0, hb_serialize_context_t::Head, layout_variation_idx_map);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- (this+xDeviceTable).collect_variation_indices (c->layout_variation_indices);
- (this+yDeviceTable).collect_variation_indices (c->layout_variation_indices);
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 3 */
- FWORD xCoordinate; /* Horizontal value--in design units */
- FWORD yCoordinate; /* Vertical value--in design units */
- Offset16To<Device>
- xDeviceTable; /* Offset to Device table for X
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- Offset16To<Device>
- yDeviceTable; /* Offset to Device table for Y
- * coordinate-- from beginning of
- * Anchor table (may be NULL) */
- public:
- DEFINE_SIZE_STATIC (10);
-};
-
-struct Anchor
-{
- void get_anchor (hb_ot_apply_context_t *c, hb_codepoint_t glyph_id,
- float *x, float *y) const
- {
- *x = *y = 0;
- switch (u.format) {
- case 1: u.format1.get_anchor (c, glyph_id, x, y); return;
- case 2: u.format2.get_anchor (c, glyph_id, x, y); return;
- case 3: u.format3.get_anchor (c, glyph_id, x, y); return;
- default: return;
- }
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!u.format.sanitize (c)) return_trace (false);
- switch (u.format) {
- case 1: return_trace (u.format1.sanitize (c));
- case 2: return_trace (u.format2.sanitize (c));
- case 3: return_trace (u.format3.sanitize (c));
- default:return_trace (true);
- }
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- switch (u.format) {
- case 1: return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- case 2:
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- // AnchorFormat 2 just containins extra hinting information, so
- // if hints are being dropped convert to format 1.
- return_trace (bool (reinterpret_cast<Anchor *> (u.format1.copy (c->serializer))));
- }
- return_trace (bool (reinterpret_cast<Anchor *> (u.format2.copy (c->serializer))));
- case 3: return_trace (bool (reinterpret_cast<Anchor *> (u.format3.copy (c->serializer,
- c->plan->layout_variation_idx_map))));
- default:return_trace (false);
- }
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- switch (u.format) {
- case 1: case 2:
- return;
- case 3:
- u.format3.collect_variation_indices (c);
- return;
- default: return;
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- AnchorFormat1 format1;
- AnchorFormat2 format2;
- AnchorFormat3 format3;
- } u;
- public:
- DEFINE_SIZE_UNION (2, format);
-};
-
-
-struct AnchorMatrix
-{
- const Anchor& get_anchor (unsigned int row, unsigned int col,
- unsigned int cols, bool *found) const
- {
- *found = false;
- if (unlikely (row >= rows || col >= cols)) return Null (Anchor);
- *found = !matrixZ[row * cols + col].is_null ();
- return this+matrixZ[row * cols + col];
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- Iterator index_iter) const
- {
- for (unsigned i : index_iter)
- (this+matrixZ[i]).collect_variation_indices (c);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- unsigned num_rows,
- Iterator index_iter) const
- {
- TRACE_SUBSET (this);
-
- auto *out = c->serializer->start_embed (this);
-
- if (!index_iter) return_trace (false);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- out->rows = num_rows;
- for (const unsigned i : index_iter)
- {
- auto *offset = c->serializer->embed (matrixZ[i]);
- if (!offset) return_trace (false);
- offset->serialize_subset (c, matrixZ[i], this);
- }
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
- {
- TRACE_SANITIZE (this);
- if (!c->check_struct (this)) return_trace (false);
- if (unlikely (hb_unsigned_mul_overflows (rows, cols))) return_trace (false);
- unsigned int count = rows * cols;
- if (!c->check_array (matrixZ.arrayZ, count)) return_trace (false);
- for (unsigned int i = 0; i < count; i++)
- if (!matrixZ[i].sanitize (c, this)) return_trace (false);
- return_trace (true);
- }
-
- HBUINT16 rows; /* Number of rows */
- UnsizedArrayOf<Offset16To<Anchor>>
- matrixZ; /* Matrix of offsets to Anchor tables--
- * from beginning of AnchorMatrix table */
- public:
- DEFINE_SIZE_ARRAY (2, matrixZ);
-};
-
-
-struct MarkRecord
-{
- friend struct MarkArray;
-
- unsigned get_class () const { return (unsigned) klass; }
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
- }
-
- MarkRecord *subset (hb_subset_context_t *c,
- const void *src_base,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->klass = klass_mapping->get (klass);
- out->markAnchor.serialize_subset (c, markAnchor, src_base);
- return_trace (out);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+markAnchor).collect_variation_indices (c);
- }
-
- protected:
- HBUINT16 klass; /* Class defined for this mark */
- Offset16To<Anchor>
- markAnchor; /* Offset to Anchor table--from
- * beginning of MarkArray table */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Coverage order */
-{
- bool apply (hb_ot_apply_context_t *c,
- unsigned int mark_index, unsigned int glyph_index,
- const AnchorMatrix &anchors, unsigned int class_count,
- unsigned int glyph_pos) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- const MarkRecord &record = Array16Of<MarkRecord>::operator[](mark_index);
- unsigned int mark_class = record.klass;
-
- const Anchor& mark_anchor = this + record.markAnchor;
- bool found;
- const Anchor& glyph_anchor = anchors.get_anchor (glyph_index, mark_class, class_count, &found);
- /* If this subtable doesn't have an anchor for this base and this class,
- * return false such that the subsequent subtables have a chance at it. */
- if (unlikely (!found)) return_trace (false);
-
- float mark_x, mark_y, base_x, base_y;
-
- buffer->unsafe_to_break (glyph_pos, buffer->idx + 1);
- mark_anchor.get_anchor (c, buffer->cur().codepoint, &mark_x, &mark_y);
- glyph_anchor.get_anchor (c, buffer->info[glyph_pos].codepoint, &base_x, &base_y);
-
- hb_glyph_position_t &o = buffer->cur_pos();
- o.x_offset = roundf (base_x - mark_x);
- o.y_offset = roundf (base_y - mark_y);
- o.attach_type() = ATTACH_TYPE_MARK;
- o.attach_chain() = (int) glyph_pos - (int) buffer->idx;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto* out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- auto mark_iter =
- + hb_zip (coverage, this->iter ())
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- ;
-
- unsigned new_length = 0;
- for (const auto& mark_record : mark_iter) {
- if (unlikely (!mark_record.subset (c, this, klass_mapping)))
- return_trace (false);
- new_length++;
- }
-
- if (unlikely (!c->serializer->check_assign (out->len, new_length,
- HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
- return_trace (false);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (Array16Of<MarkRecord>::sanitize (c, this));
- }
-};
-
-
-/* Lookups */
-
-struct SinglePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (c->glyph_set)
- ;
-
- if (!it) return;
- valueFormat.collect_variation_indices (c, this, values.as_array (valueFormat.get_len ()));
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- valueFormat.apply_value (c, this, values, buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (this))) return;
- if (unlikely (!c->check_assign (valueFormat,
- newFormat,
- HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
-
- for (const hb_array_t<const Value>& _ : + it | hb_map (hb_second))
- {
- src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map);
- // Only serialize the first entry in the iterator, the rest are assumed to
- // be the same.
- break;
- }
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- | hb_zip (hb_repeat (values.as_array (valueFormat.get_len ())))
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_value (c, this, values));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- ValueRecord values; /* Defines positioning
- * value(s)--applied to all glyphs in
- * the Coverage table */
- public:
- DEFINE_SIZE_ARRAY (6, values);
-};
-
-struct SinglePosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!valueFormat.has_device ()) return;
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (c->glyph_set, hb_first)
- ;
-
- if (!it) return;
-
- unsigned sub_length = valueFormat.get_len ();
- const hb_array_t<const Value> values_array = values.as_array (valueCount * sub_length);
-
- for (unsigned i : + it
- | hb_map (hb_second))
- valueFormat.collect_variation_indices (c, this, values_array.sub_array (i * sub_length, sub_length));
-
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- ValueFormat get_value_format () const { return valueFormat; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (likely (index >= valueCount)) return_trace (false);
-
- valueFormat.apply_value (c, this,
- &values[index * valueFormat.get_len ()],
- buffer->cur_pos());
-
- buffer->idx++;
- return_trace (true);
- }
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- ValueFormat newFormat,
- const hb_map_t *layout_variation_idx_map)
- {
- auto out = c->extend_min (this);
- if (unlikely (!out)) return;
- if (unlikely (!c->check_assign (valueFormat, newFormat, HB_SERIALIZE_ERROR_INT_OVERFLOW))) return;
- if (unlikely (!c->check_assign (valueCount, it.len (), HB_SERIALIZE_ERROR_ARRAY_OVERFLOW))) return;
-
- + it
- | hb_map (hb_second)
- | hb_apply ([&] (hb_array_t<const Value> _)
- { src->get_value_format ().copy_values (c, newFormat, src, &_, layout_variation_idx_map); })
- ;
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned sub_length = valueFormat.get_len ();
- auto values_array = values.as_array (valueCount * sub_length);
-
- auto it =
- + hb_zip (this+coverage, hb_range ((unsigned) valueCount))
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (const hb_pair_t<hb_codepoint_t, unsigned>& _)
- {
- return hb_pair (glyph_map[_.first],
- values_array.sub_array (_.second * sub_length,
- sub_length));
- })
- ;
-
- bool ret = bool (it);
- SinglePos_serialize (c->serializer, this, it, c->plan->layout_variation_idx_map);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- coverage.sanitize (c, this) &&
- valueFormat.sanitize_values (c, this, values, valueCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat; /* Defines the types of data in the
- * ValueRecord */
- HBUINT16 valueCount; /* Number of ValueRecords */
- ValueRecord values; /* Array of ValueRecords--positioning
- * values applied to glyphs */
- public:
- DEFINE_SIZE_ARRAY (8, values);
-};
-
-struct SinglePos
-{
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- unsigned get_format (Iterator glyph_val_iter_pairs)
- {
- hb_array_t<const Value> first_val_iter = hb_second (*glyph_val_iter_pairs);
-
- for (const auto iter : glyph_val_iter_pairs)
- for (const auto _ : hb_zip (iter.second, first_val_iter))
- if (_.first != _.second)
- return 2;
-
- return 1;
- }
-
-
- template<typename Iterator,
- typename SrcLookup,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_serialize_context_t *c,
- const SrcLookup* src,
- Iterator glyph_val_iter_pairs,
- const hb_map_t *layout_variation_idx_map)
- {
- if (unlikely (!c->extend_min (u.format))) return;
- unsigned format = 2;
- ValueFormat new_format = src->get_value_format ();
-
- if (glyph_val_iter_pairs)
- {
- format = get_format (glyph_val_iter_pairs);
- new_format = src->get_value_format ().get_effective_format (+ glyph_val_iter_pairs | hb_map (hb_second));
- }
-
- u.format = format;
- switch (u.format) {
- case 1: u.format1.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- case 2: u.format2.serialize (c,
- src,
- glyph_val_iter_pairs,
- new_format,
- layout_variation_idx_map);
- return;
- default:return;
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- SinglePosFormat1 format1;
- SinglePosFormat2 format2;
- } u;
-};
-
-template<typename Iterator, typename SrcLookup>
-static void
-SinglePos_serialize (hb_serialize_context_t *c,
- const SrcLookup *src,
- Iterator it,
- const hb_map_t *layout_variation_idx_map)
-{ c->start_embed<SinglePos> ()->serialize (c, src, it, layout_variation_idx_map); }
-
-
-struct PairValueRecord
-{
- friend struct PairSet;
-
- int cmp (hb_codepoint_t k) const
- { return secondGlyph.cmp (k); }
-
- struct context_t
- {
- const void *base;
- const ValueFormat *valueFormats;
- const ValueFormat *newFormats;
- unsigned len1; /* valueFormats[0].get_len() */
- const hb_map_t *glyph_map;
- const hb_map_t *layout_variation_idx_map;
- };
-
- bool subset (hb_subset_context_t *c,
- context_t *closure) const
- {
- TRACE_SERIALIZE (this);
- auto *s = c->serializer;
- auto *out = s->start_embed (*this);
- if (unlikely (!s->extend_min (out))) return_trace (false);
-
- out->secondGlyph = (*closure->glyph_map)[secondGlyph];
-
- closure->valueFormats[0].copy_values (s,
- closure->newFormats[0],
- closure->base, &values[0],
- closure->layout_variation_idx_map);
- closure->valueFormats[1].copy_values (s,
- closure->newFormats[1],
- closure->base,
- &values[closure->len1],
- closure->layout_variation_idx_map);
-
- return_trace (true);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const ValueFormat *valueFormats,
- const void *base) const
- {
- unsigned record1_len = valueFormats[0].get_len ();
- unsigned record2_len = valueFormats[1].get_len ();
- const hb_array_t<const Value> values_array = values.as_array (record1_len + record2_len);
-
- if (valueFormats[0].has_device ())
- valueFormats[0].collect_variation_indices (c, base, values_array.sub_array (0, record1_len));
-
- if (valueFormats[1].has_device ())
- valueFormats[1].collect_variation_indices (c, base, values_array.sub_array (record1_len, record2_len));
- }
-
- bool intersects (const hb_set_t& glyphset) const
- {
- return glyphset.has(secondGlyph);
- }
-
- const Value* get_values_1 () const
- {
- return &values[0];
- }
-
- const Value* get_values_2 (ValueFormat format1) const
- {
- return &values[format1.get_len ()];
- }
-
- protected:
- HBGlyphID16 secondGlyph; /* GlyphID of second glyph in the
- * pair--first glyph is listed in the
- * Coverage table */
- ValueRecord values; /* Positioning data for the first glyph
- * followed by for second glyph */
- public:
- DEFINE_SIZE_ARRAY (2, values);
-};
-
-struct PairSet
-{
- friend struct PairPosFormat1;
-
- bool intersects (const hb_set_t *glyphs,
- const ValueFormat *valueFormats) const
- {
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned int count = len;
- for (unsigned int i = 0; i < count; i++)
- {
- if (glyphs->has (record->secondGlyph))
- return true;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- return false;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c,
- const ValueFormat *valueFormats) const
- {
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- c->input->add_array (&record->secondGlyph, len, record_size);
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const ValueFormat *valueFormats) const
- {
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len;
- for (unsigned i = 0; i < count; i++)
- {
- if (c->glyph_set->has (record->secondGlyph))
- { record->collect_variation_indices (c, valueFormats, this); }
-
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- bool apply (hb_ot_apply_context_t *c,
- const ValueFormat *valueFormats,
- unsigned int pos) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int len1 = valueFormats[0].get_len ();
- unsigned int len2 = valueFormats[1].get_len ();
- unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
-
- const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
- &firstPairValueRecord,
- len,
- record_size);
- if (record)
- {
- bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
- bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, pos + 1);
- if (len2)
- pos++;
- buffer->idx = pos;
- return_trace (true);
- }
- buffer->unsafe_to_concat (buffer->idx, pos + 1);
- return_trace (false);
- }
-
- bool subset (hb_subset_context_t *c,
- const ValueFormat valueFormats[2],
- const ValueFormat newFormats[2]) const
- {
- TRACE_SUBSET (this);
- auto snap = c->serializer->snapshot ();
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->len = 0;
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- unsigned len1 = valueFormats[0].get_len ();
- unsigned len2 = valueFormats[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
-
- PairValueRecord::context_t context =
- {
- this,
- valueFormats,
- newFormats,
- len1,
- &glyph_map,
- c->plan->layout_variation_idx_map
- };
-
- const PairValueRecord *record = &firstPairValueRecord;
- unsigned count = len, num = 0;
- for (unsigned i = 0; i < count; i++)
- {
- if (glyphset.has (record->secondGlyph)
- && record->subset (c, &context)) num++;
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
-
- out->len = num;
- if (!num) c->serializer->revert (snap);
- return_trace (num);
- }
-
- struct sanitize_closure_t
- {
- const ValueFormat *valueFormats;
- unsigned int len1; /* valueFormats[0].get_len() */
- unsigned int stride; /* 1 + len1 + len2 */
- };
-
- bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && c->check_range (&firstPairValueRecord,
- len,
- HBUINT16::static_size,
- closure->stride))) return_trace (false);
-
- unsigned int count = len;
- const PairValueRecord *record = &firstPairValueRecord;
- return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
- closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
- }
-
- protected:
- HBUINT16 len; /* Number of PairValueRecords */
- PairValueRecord firstPairValueRecord;
- /* Array of PairValueRecords--ordered
- * by GlyphID of the second glyph */
- public:
- DEFINE_SIZE_MIN (2);
-};
-
-struct PairPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, pairSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([glyphs, this] (const Offset16To<PairSet> &_)
- { return (this+_).intersects (glyphs, valueFormat); })
- | hb_any
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if ((!valueFormat[0].has_device ()) && (!valueFormat[1].has_device ())) return;
-
- auto it =
- + hb_zip (this+coverage, pairSet)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- if (!it) return;
- + it
- | hb_map (hb_add (this))
- | hb_apply ([&] (const PairSet& _) { _.collect_variation_indices (c, valueFormat); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned int count = pairSet.len;
- for (unsigned int i = 0; i < count; i++)
- (this+pairSet[i]).collect_glyphs (c, valueFormat);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- return_trace ((this+pairSet[index]).apply (c, valueFormat, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
- out->valueFormat[0] = valueFormat[0];
- out->valueFormat[1] = valueFormat[1];
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- {
- hb_pair_t<unsigned, unsigned> newFormats = compute_effective_value_formats (glyphset);
- out->valueFormat[0] = newFormats.first;
- out->valueFormat[1] = newFormats.second;
- }
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
-
- + hb_zip (this+coverage, pairSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter ([this, c, out] (const Offset16To<PairSet>& _)
- {
- auto snap = c->serializer->snapshot ();
- auto *o = out->pairSet.serialize_append (c->serializer);
- if (unlikely (!o)) return false;
- bool ret = o->serialize_subset (c, _, this, valueFormat, out->valueFormat);
- if (!ret)
- {
- out->pairSet.pop ();
- c->serializer->revert (snap);
- }
- return ret;
- },
- hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
-
- return_trace (bool (new_coverage));
- }
-
-
- hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_set_t& glyphset) const
- {
- unsigned len1 = valueFormat[0].get_len ();
- unsigned len2 = valueFormat[1].get_len ();
- unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
-
- unsigned format1 = 0;
- unsigned format2 = 0;
- for (const Offset16To<PairSet>& _ :
- + hb_zip (this+coverage, pairSet) | hb_filter (glyphset, hb_first) | hb_map (hb_second))
- {
- const PairSet& set = (this + _);
- const PairValueRecord *record = &set.firstPairValueRecord;
-
- for (unsigned i = 0; i < set.len; i++)
- {
- if (record->intersects (glyphset))
- {
- format1 = format1 | valueFormat[0].get_effective_format (record->get_values_1 ());
- format2 = format2 | valueFormat[1].get_effective_format (record->get_values_2 (valueFormat[0]));
- }
- record = &StructAtOffset<const PairValueRecord> (record, record_size);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
-
- if (!c->check_struct (this)) return_trace (false);
-
- unsigned int len1 = valueFormat[0].get_len ();
- unsigned int len2 = valueFormat[1].get_len ();
- PairSet::sanitize_closure_t closure =
- {
- valueFormat,
- len1,
- 1 + len1 + len2
- };
-
- return_trace (coverage.sanitize (c, this) && pairSet.sanitize (c, this, &closure));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat[2]; /* [0] Defines the types of data in
- * ValueRecord1--for the first glyph
- * in the pair--may be zero (0) */
- /* [1] Defines the types of data in
- * ValueRecord2--for the second glyph
- * in the pair--may be zero (0) */
- Array16OfOffset16To<PairSet>
- pairSet; /* Array of PairSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (10, pairSet);
-};
-
-struct PairPosFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+coverage).intersects (glyphs) &&
- (this+classDef2).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- if (!intersects (c->glyph_set)) return;
- if ((!valueFormat1.has_device ()) && (!valueFormat2.has_device ())) return;
-
- hb_set_t klass1_glyphs, klass2_glyphs;
- if (!(this+classDef1).collect_coverage (&klass1_glyphs)) return;
- if (!(this+classDef2).collect_coverage (&klass2_glyphs)) return;
-
- hb_set_t class1_set, class2_set;
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (this + coverage))
- {
- if (!klass1_glyphs.has (cp)) class1_set.add (0);
- else
- {
- unsigned klass1 = (this+classDef1).get (cp);
- class1_set.add (klass1);
- }
- }
-
- class2_set.add (0);
- for (const unsigned cp : + c->glyph_set->iter () | hb_filter (klass2_glyphs))
- {
- unsigned klass2 = (this+classDef2).get (cp);
- class2_set.add (klass2);
- }
-
- if (class1_set.is_empty ()
- || class2_set.is_empty ()
- || (class2_set.get_population() == 1 && class2_set.has(0)))
- return;
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
- const hb_array_t<const Value> values_array = values.as_array ((unsigned)class1Count * (unsigned) class2Count * (len1 + len2));
- for (const unsigned class1_idx : class1_set.iter ())
- {
- for (const unsigned class2_idx : class2_set.iter ())
- {
- unsigned start_offset = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- if (valueFormat1.has_device ())
- valueFormat1.collect_variation_indices (c, this, values_array.sub_array (start_offset, len1));
-
- if (valueFormat2.has_device ())
- valueFormat2.collect_variation_indices (c, this, values_array.sub_array (start_offset+len1, len2));
- }
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+classDef2).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_to;
- if (!skippy_iter.next (&unsafe_to))
- {
- buffer->unsafe_to_concat (buffer->idx, unsafe_to);
- return_trace (false);
- }
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int record_len = len1 + len2;
-
- unsigned int klass1 = (this+classDef1).get_class (buffer->cur().codepoint);
- unsigned int klass2 = (this+classDef2).get_class (buffer->info[skippy_iter.idx].codepoint);
- if (unlikely (klass1 >= class1Count || klass2 >= class2Count))
- {
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
- return_trace (false);
- }
-
- const Value *v = &values[record_len * (klass1 * class2Count + klass2)];
-
- bool applied_first = false, applied_second = false;
-
-
- /* Isolate simple kerning and apply it half to each side.
- * Results in better cursor positinoing / underline drawing.
- *
- * Disabled, because causes issues... :-(
- * https://github.com/harfbuzz/harfbuzz/issues/3408
- * https://github.com/harfbuzz/harfbuzz/pull/3235#issuecomment-1029814978
- */
-#ifndef HB_SPLIT_KERN
- if (0)
-#endif
- {
- if (!len2)
- {
- const hb_direction_t dir = buffer->props.direction;
- const bool horizontal = HB_DIRECTION_IS_HORIZONTAL (dir);
- const bool backward = HB_DIRECTION_IS_BACKWARD (dir);
- unsigned mask = horizontal ? ValueFormat::xAdvance : ValueFormat::yAdvance;
- if (backward)
- mask |= mask >> 2; /* Add eg. xPlacement in RTL. */
- /* Add Devices. */
- mask |= mask << 4;
-
- if (valueFormat1 & ~mask)
- goto bail;
-
- /* Is simple kern. Apply value on an empty position slot,
- * then split it between sides. */
-
- hb_glyph_position_t pos{};
- if (valueFormat1.apply_value (c, this, v, pos))
- {
- hb_position_t *src = &pos.x_advance;
- hb_position_t *dst1 = &buffer->cur_pos().x_advance;
- hb_position_t *dst2 = &buffer->pos[skippy_iter.idx].x_advance;
- unsigned i = horizontal ? 0 : 1;
-
- hb_position_t kern = src[i];
- hb_position_t kern1 = kern >> 1;
- hb_position_t kern2 = kern - kern1;
-
- if (!backward)
- {
- dst1[i] += kern1;
- dst2[i] += kern2;
- dst2[i + 2] += kern2;
- }
- else
- {
- dst1[i] += kern1;
- dst1[i + 2] += src[i + 2] - kern2;
- dst2[i] += kern2;
- }
-
- applied_first = applied_second = kern != 0;
- goto success;
- }
- goto boring;
- }
- }
- bail:
-
-
- applied_first = valueFormat1.apply_value (c, this, v, buffer->cur_pos());
- applied_second = valueFormat2.apply_value (c, this, v + len1, buffer->pos[skippy_iter.idx]);
-
- success:
- if (applied_first || applied_second)
- buffer->unsafe_to_break (buffer->idx, skippy_iter.idx + 1);
- else
- boring:
- buffer->unsafe_to_concat (buffer->idx, skippy_iter.idx + 1);
-
-
- buffer->idx = skippy_iter.idx;
- if (len2)
- buffer->idx++;
-
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass1_map;
- out->classDef1.serialize_subset (c, classDef1, this, &klass1_map, true, true, &(this + coverage));
- out->class1Count = klass1_map.get_population ();
-
- hb_map_t klass2_map;
- out->classDef2.serialize_subset (c, classDef2, this, &klass2_map, true, false);
- out->class2Count = klass2_map.get_population ();
-
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- hb_pair_t<unsigned, unsigned> newFormats = hb_pair (valueFormat1, valueFormat2);
- if (c->plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
- newFormats = compute_effective_value_formats (klass1_map, klass2_map);
-
- out->valueFormat1 = newFormats.first;
- out->valueFormat2 = newFormats.second;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- valueFormat1.copy_values (c->serializer, newFormats.first, this, &values[idx], c->plan->layout_variation_idx_map);
- valueFormat2.copy_values (c->serializer, newFormats.second, this, &values[idx + len1], c->plan->layout_variation_idx_map);
- }
- }
-
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- out->coverage.serialize_serialize (c->serializer, it);
- return_trace (out->class1Count && out->class2Count && bool (it));
- }
-
-
- hb_pair_t<unsigned, unsigned> compute_effective_value_formats (const hb_map_t& klass1_map,
- const hb_map_t& klass2_map) const
- {
- unsigned len1 = valueFormat1.get_len ();
- unsigned len2 = valueFormat2.get_len ();
-
- unsigned format1 = 0;
- unsigned format2 = 0;
-
- for (unsigned class1_idx : + hb_range ((unsigned) class1Count) | hb_filter (klass1_map))
- {
- for (unsigned class2_idx : + hb_range ((unsigned) class2Count) | hb_filter (klass2_map))
- {
- unsigned idx = (class1_idx * (unsigned) class2Count + class2_idx) * (len1 + len2);
- format1 = format1 | valueFormat1.get_effective_format (&values[idx]);
- format2 = format2 | valueFormat2.get_effective_format (&values[idx + len1]);
- }
- }
-
- return hb_pair (format1, format2);
- }
-
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(c->check_struct (this)
- && coverage.sanitize (c, this)
- && classDef1.sanitize (c, this)
- && classDef2.sanitize (c, this))) return_trace (false);
-
- unsigned int len1 = valueFormat1.get_len ();
- unsigned int len2 = valueFormat2.get_len ();
- unsigned int stride = len1 + len2;
- unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size ();
- unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count;
- return_trace (c->check_range ((const void *) values,
- count,
- record_size) &&
- valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) &&
- valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- ValueFormat valueFormat1; /* ValueRecord definition--for the
- * first glyph of the pair--may be zero
- * (0) */
- ValueFormat valueFormat2; /* ValueRecord definition--for the
- * second glyph of the pair--may be
- * zero (0) */
- Offset16To<ClassDef>
- classDef1; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the first glyph of the pair */
- Offset16To<ClassDef>
- classDef2; /* Offset to ClassDef table--from
- * beginning of PairPos subtable--for
- * the second glyph of the pair */
- HBUINT16 class1Count; /* Number of classes in ClassDef1
- * table--includes Class0 */
- HBUINT16 class2Count; /* Number of classes in ClassDef2
- * table--includes Class0 */
- ValueRecord values; /* Matrix of value pairs:
- * class1-major, class2-minor,
- * Each entry has value1 and value2 */
- public:
- DEFINE_SIZE_ARRAY (16, values);
-};
-
-struct PairPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- PairPosFormat1 format1;
- PairPosFormat2 format2;
- } u;
-};
-
-
-struct EntryExitRecord
-{
- friend struct CursivePosFormat1;
-
- bool sanitize (hb_sanitize_context_t *c, const void *base) const
- {
- TRACE_SANITIZE (this);
- return_trace (entryAnchor.sanitize (c, base) && exitAnchor.sanitize (c, base));
- }
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c,
- const void *src_base) const
- {
- (src_base+entryAnchor).collect_variation_indices (c);
- (src_base+exitAnchor).collect_variation_indices (c);
- }
-
- EntryExitRecord* subset (hb_subset_context_t *c,
- const void *src_base) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
- out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
- return_trace (out);
- }
-
- protected:
- Offset16To<Anchor>
- entryAnchor; /* Offset to EntryAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- Offset16To<Anchor>
- exitAnchor; /* Offset to ExitAnchor table--from
- * beginning of CursivePos
- * subtable--may be NULL */
- public:
- DEFINE_SIZE_STATIC (4);
-};
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent);
-
-struct CursivePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const EntryExitRecord& record) { record.collect_variation_indices (c, this); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { if (unlikely (!(this+coverage).collect_coverage (c->input))) return; }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
-
- const EntryExitRecord &this_record = entryExitRecord[(this+coverage).get_coverage (buffer->cur().codepoint)];
- if (!this_record.entryAnchor) return_trace (false);
-
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- const EntryExitRecord &prev_record = entryExitRecord[(this+coverage).get_coverage (buffer->info[skippy_iter.idx].codepoint)];
- if (!prev_record.exitAnchor)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int i = skippy_iter.idx;
- unsigned int j = buffer->idx;
-
- buffer->unsafe_to_break (i, j);
- float entry_x, entry_y, exit_x, exit_y;
- (this+prev_record.exitAnchor).get_anchor (c, buffer->info[i].codepoint, &exit_x, &exit_y);
- (this+this_record.entryAnchor).get_anchor (c, buffer->info[j].codepoint, &entry_x, &entry_y);
-
- hb_glyph_position_t *pos = buffer->pos;
-
- hb_position_t d;
- /* Main-direction adjustment */
- switch (c->direction) {
- case HB_DIRECTION_LTR:
- pos[i].x_advance = roundf (exit_x) + pos[i].x_offset;
-
- d = roundf (entry_x) + pos[j].x_offset;
- pos[j].x_advance -= d;
- pos[j].x_offset -= d;
- break;
- case HB_DIRECTION_RTL:
- d = roundf (exit_x) + pos[i].x_offset;
- pos[i].x_advance -= d;
- pos[i].x_offset -= d;
-
- pos[j].x_advance = roundf (entry_x) + pos[j].x_offset;
- break;
- case HB_DIRECTION_TTB:
- pos[i].y_advance = roundf (exit_y) + pos[i].y_offset;
-
- d = roundf (entry_y) + pos[j].y_offset;
- pos[j].y_advance -= d;
- pos[j].y_offset -= d;
- break;
- case HB_DIRECTION_BTT:
- d = roundf (exit_y) + pos[i].y_offset;
- pos[i].y_advance -= d;
- pos[i].y_offset -= d;
-
- pos[j].y_advance = roundf (entry_y);
- break;
- case HB_DIRECTION_INVALID:
- default:
- break;
- }
-
- /* Cross-direction adjustment */
-
- /* We attach child to parent (think graph theory and rooted trees whereas
- * the root stays on baseline and each node aligns itself against its
- * parent.
- *
- * Optimize things for the case of RightToLeft, as that's most common in
- * Arabic. */
- unsigned int child = i;
- unsigned int parent = j;
- hb_position_t x_offset = entry_x - exit_x;
- hb_position_t y_offset = entry_y - exit_y;
- if (!(c->lookup_props & LookupFlag::RightToLeft))
- {
- unsigned int k = child;
- child = parent;
- parent = k;
- x_offset = -x_offset;
- y_offset = -y_offset;
- }
-
- /* If child was already connected to someone else, walk through its old
- * chain and reverse the link direction, such that the whole tree of its
- * previous connection now attaches to new parent. Watch out for case
- * where new parent is on the path from old chain...
- */
- reverse_cursive_minor_offset (pos, child, c->direction, parent);
-
- pos[child].attach_type() = ATTACH_TYPE_CURSIVE;
- pos[child].attach_chain() = (int) parent - (int) child;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
- if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction)))
- pos[child].y_offset = y_offset;
- else
- pos[child].x_offset = x_offset;
-
- /* If parent was attached to child, separate them.
- * https://github.com/harfbuzz/harfbuzz/issues/2469
- */
- if (unlikely (pos[parent].attach_chain() == -pos[child].attach_chain()))
- pos[parent].attach_chain() = 0;
-
- buffer->idx++;
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- void serialize (hb_subset_context_t *c,
- Iterator it,
- const void *src_base)
- {
- if (unlikely (!c->serializer->extend_min ((*this)))) return;
- this->format = 1;
- this->entryExitRecord.len = it.len ();
-
- for (const EntryExitRecord& entry_record : + it
- | hb_map (hb_second))
- entry_record.subset (c, src_base);
-
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
-
- coverage.serialize_serialize (c->serializer, glyphs);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- auto it =
- + hb_zip (this+coverage, entryExitRecord)
- | hb_filter (glyphset, hb_first)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const EntryExitRecord&> p) -> hb_pair_t<hb_codepoint_t, const EntryExitRecord&>
- { return hb_pair (glyph_map[p.first], p.second);})
- ;
-
- bool ret = bool (it);
- out->serialize (c, it, this);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && entryExitRecord.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of subtable */
- Array16Of<EntryExitRecord>
- entryExitRecord; /* Array of EntryExit records--in
- * Coverage Index order */
- public:
- DEFINE_SIZE_ARRAY (6, entryExitRecord);
-};
-
-struct CursivePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- CursivePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix BaseArray; /* base-major--
- * in order of BaseCoverage Index--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-static void Markclass_closure_and_remap_indexes (const Coverage &mark_coverage,
- const MarkArray &mark_array,
- const hb_set_t &glyphset,
- hb_map_t* klass_mapping /* INOUT */)
-{
- hb_set_t orig_classes;
-
- + hb_zip (mark_coverage, mark_array)
- | hb_filter (glyphset, hb_first)
- | hb_map (hb_second)
- | hb_map (&MarkRecord::get_class)
- | hb_sink (orig_classes)
- ;
-
- unsigned idx = 0;
- for (auto klass : orig_classes.iter ())
- {
- if (klass_mapping->has (klass)) continue;
- klass_mapping->set (klass, idx);
- idx++;
- }
-}
-
-struct MarkBasePosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+baseCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : base_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
- (this+baseArray).collect_variation_indices (c, base_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+baseCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
- /* Now we search backwards for a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- do {
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We only want to attach to the first of a MultipleSubst sequence.
- * https://github.com/harfbuzz/harfbuzz/issues/740
- * Reject others...
- * ...but stop if we find a mark in the MultipleSubst sequence:
- * https://github.com/harfbuzz/harfbuzz/issues/1020 */
- if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
- 0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
- (skippy_iter.idx == 0 ||
- _hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
- _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
- ))
- break;
- skippy_iter.reject ();
- } while (true);
-
- /* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
- unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
- if (base_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- unsigned basecount = (this+baseArray).rows;
- auto base_iter =
- + hb_zip (this+baseCoverage, hb_range (basecount))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + base_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->baseCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> base_indexes;
- for (const unsigned row : + base_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (base_indexes)
- ;
- }
-
- out->baseArray.serialize_subset (c, baseArray, this,
- base_iter.len (),
- base_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- baseCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- baseArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to MarkCoverage table--from
- * beginning of MarkBasePos subtable */
- Offset16To<Coverage>
- baseCoverage; /* Offset to BaseCoverage table--from
- * beginning of MarkBasePos subtable */
- HBUINT16 classCount; /* Number of classes defined for marks */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkBasePos subtable */
- Offset16To<BaseArray>
- baseArray; /* Offset to BaseArray table--from
- * beginning of MarkBasePos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkBasePos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkBasePosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix LigatureAttach; /* component-major--
- * in order of writing direction--,
- * mark-minor--
- * ordered by class--zero-based. */
-
-/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
-struct LigatureArray : List16OfOffset16To<LigatureAttach>
-{
- template <typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool subset (hb_subset_context_t *c,
- Iterator coverage,
- unsigned class_count,
- const hb_map_t *klass_mapping) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- for (const auto _ : + hb_zip (coverage, *this)
- | hb_filter (glyphset, hb_first))
- {
- auto *matrix = out->serialize_append (c->serializer);
- if (unlikely (!matrix)) return_trace (false);
-
- const LigatureAttach& src = (this + _.second);
- auto indexes =
- + hb_range (src.rows * class_count)
- | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
- ;
- matrix->serialize_subset (c,
- _.second,
- this,
- src.rows,
- indexes);
- }
- return_trace (this->len);
- }
-};
-
-struct MarkLigPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+markCoverage).intersects (glyphs) &&
- (this+ligatureCoverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+markArray)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, *c->glyph_set, &klass_mapping);
-
- unsigned ligcount = (this+ligatureArray).len;
- auto lig_iter =
- + hb_zip (this+ligatureCoverage, hb_range (ligcount))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- const LigatureArray& lig_array = this+ligatureArray;
- for (const unsigned i : lig_iter)
- {
- hb_sorted_vector_t<unsigned> lig_indexes;
- unsigned row_count = lig_array[i].rows;
- for (unsigned row : + hb_range (row_count))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (lig_indexes)
- ;
- }
-
- lig_array[i].collect_variation_indices (c, lig_indexes.iter ());
- }
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+markCoverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+ligatureCoverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+markCoverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark_index == NOT_COVERED)) return_trace (false);
-
- /* Now we search backwards for a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- /* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
- //if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
-
- unsigned int j = skippy_iter.idx;
- unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
- if (lig_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- const LigatureArray& lig_array = this+ligatureArray;
- const LigatureAttach& lig_attach = lig_array[lig_index];
-
- /* Find component to attach to */
- unsigned int comp_count = lig_attach.rows;
- if (unlikely (!comp_count))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- /* We must now check whether the ligature ID of the current mark glyph
- * is identical to the ligature ID of the found ligature. If yes, we
- * can directly use the component index. If not, we attach the mark
- * glyph to the last component of the ligature. */
- unsigned int comp_index;
- unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
- if (lig_id && lig_id == mark_id && mark_comp > 0)
- comp_index = hb_min (comp_count, _hb_glyph_info_get_lig_comp (&buffer->cur())) - 1;
- else
- comp_index = comp_count - 1;
-
- return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark_iter =
- + hb_zip (this+markCoverage, this+markArray)
- | hb_filter (glyphset, hb_first)
- ;
-
- auto new_mark_coverage =
- + mark_iter
- | hb_map_retains_sorting (hb_first)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
- return_trace (false);
-
- out->markArray.serialize_subset (c, markArray, this,
- (this+markCoverage).iter (),
- &klass_mapping);
-
- auto new_ligature_coverage =
- + hb_iter (this + ligatureCoverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
- ;
-
- if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
- return_trace (false);
-
- out->ligatureArray.serialize_subset (c, ligatureArray, this,
- hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- markCoverage.sanitize (c, this) &&
- ligatureCoverage.sanitize (c, this) &&
- markArray.sanitize (c, this) &&
- ligatureArray.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- markCoverage; /* Offset to Mark Coverage table--from
- * beginning of MarkLigPos subtable */
- Offset16To<Coverage>
- ligatureCoverage; /* Offset to Ligature Coverage
- * table--from beginning of MarkLigPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- markArray; /* Offset to MarkArray table--from
- * beginning of MarkLigPos subtable */
- Offset16To<LigatureArray>
- ligatureArray; /* Offset to LigatureArray table--from
- * beginning of MarkLigPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-
-struct MarkLigPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkLigPosFormat1 format1;
- } u;
-};
-
-
-typedef AnchorMatrix Mark2Array; /* mark2-major--
- * in order of Mark2Coverage Index--,
- * mark1-minor--
- * ordered by class--zero-based. */
-
-struct MarkMarkPosFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return (this+mark1Coverage).intersects (glyphs) &&
- (this+mark2Coverage).intersects (glyphs);
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
- ;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
-
- unsigned mark2_count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2_count))
- | hb_filter (c->glyph_set, hb_first)
- | hb_map (hb_second)
- ;
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : mark2_iter)
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
- (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
- if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
- }
-
- const Coverage &get_coverage () const { return this+mark1Coverage; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_buffer_t *buffer = c->buffer;
- unsigned int mark1_index = (this+mark1Coverage).get_coverage (buffer->cur().codepoint);
- if (likely (mark1_index == NOT_COVERED)) return_trace (false);
-
- /* now we search backwards for a suitable mark glyph until a non-mark glyph */
- hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
- skippy_iter.reset (buffer->idx, 1);
- skippy_iter.set_lookup_props (c->lookup_props & ~LookupFlag::IgnoreFlags);
- unsigned unsafe_from;
- if (!skippy_iter.prev (&unsafe_from))
- {
- buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
- return_trace (false);
- }
-
- if (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx]))
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- unsigned int j = skippy_iter.idx;
-
- unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
- unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
- unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
- unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
-
- if (likely (id1 == id2))
- {
- if (id1 == 0) /* Marks belonging to the same base. */
- goto good;
- else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
- goto good;
- }
- else
- {
- /* If ligature ids don't match, it may be the case that one of the marks
- * itself is a ligature. In which case match. */
- if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
- goto good;
- }
-
- /* Didn't match. */
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
-
- good:
- unsigned int mark2_index = (this+mark2Coverage).get_coverage (buffer->info[j].codepoint);
- if (mark2_index == NOT_COVERED)
- {
- buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
- return_trace (false);
- }
-
- return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_map_t klass_mapping;
- Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
-
- if (!klass_mapping.get_population ()) return_trace (false);
- out->classCount = klass_mapping.get_population ();
-
- auto mark1_iter =
- + hb_zip (this+mark1Coverage, this+mark1Array)
- | hb_filter (glyphset, hb_first)
- ;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + mark1_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- out->mark1Array.serialize_subset (c, mark1Array, this,
- (this+mark1Coverage).iter (),
- &klass_mapping);
-
- unsigned mark2count = (this+mark2Array).rows;
- auto mark2_iter =
- + hb_zip (this+mark2Coverage, hb_range (mark2count))
- | hb_filter (glyphset, hb_first)
- ;
-
- new_coverage.reset ();
- + mark2_iter
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
-
- if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
- return_trace (false);
-
- hb_sorted_vector_t<unsigned> mark2_indexes;
- for (const unsigned row : + mark2_iter
- | hb_map (hb_second))
- {
- + hb_range ((unsigned) classCount)
- | hb_filter (klass_mapping)
- | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
- | hb_sink (mark2_indexes)
- ;
- }
-
- out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
-
- return_trace (true);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- mark1Coverage.sanitize (c, this) &&
- mark2Coverage.sanitize (c, this) &&
- mark1Array.sanitize (c, this) &&
- mark2Array.sanitize (c, this, (unsigned int) classCount));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- mark1Coverage; /* Offset to Combining Mark1 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- Offset16To<Coverage>
- mark2Coverage; /* Offset to Combining Mark2 Coverage
- * table--from beginning of MarkMarkPos
- * subtable */
- HBUINT16 classCount; /* Number of defined mark classes */
- Offset16To<MarkArray>
- mark1Array; /* Offset to Mark1Array table--from
- * beginning of MarkMarkPos subtable */
- Offset16To<Mark2Array>
- mark2Array; /* Offset to Mark2Array table--from
- * beginning of MarkMarkPos subtable */
- public:
- DEFINE_SIZE_STATIC (12);
-};
-
-struct MarkMarkPos
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MarkMarkPosFormat1 format1;
- } u;
-};
-
-
-struct ContextPos : Context {};
-
-struct ChainContextPos : ChainContext {};
-
-struct ExtensionPos : Extension<ExtensionPos>
-{
- typedef struct PosLookupSubTable SubTable;
-};
-
-
-
-/*
- * PosLookup
- */
-
-
-struct PosLookupSubTable
-{
- friend struct Lookup;
- friend struct PosLookup;
-
- enum Type {
- Single = 1,
- Pair = 2,
- Cursive = 3,
- MarkBase = 4,
- MarkLig = 5,
- MarkMark = 6,
- Context = 7,
- ChainContext = 8,
- Extension = 9
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
- case Pair: return_trace (u.pair.dispatch (c, std::forward<Ts> (ds)...));
- case Cursive: return_trace (u.cursive.dispatch (c, std::forward<Ts> (ds)...));
- case MarkBase: return_trace (u.markBase.dispatch (c, std::forward<Ts> (ds)...));
- case MarkLig: return_trace (u.markLig.dispatch (c, std::forward<Ts> (ds)...));
- case MarkMark: return_trace (u.markMark.dispatch (c, std::forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SinglePos single;
- PairPos pair;
- CursivePos cursive;
- MarkBasePos markBase;
- MarkLigPos markLig;
- MarkMarkPos markMark;
- ContextPos context;
- ChainContextPos chainContext;
- ExtensionPos extension;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct PosLookup : Lookup
-{
- typedef struct PosLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- bool is_reverse () const
- {
- return false;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- { return dispatch (c); }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- template <typename context_t>
- static typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GPOS -- Glyph Positioning
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gpos
- */
-
-struct GPOS : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GPOS;
-
- const PosLookup& get_lookup (unsigned int i) const
- { return static_cast<const PosLookup &> (GSUBGPOS::get_lookup (i)); }
-
- static inline void position_start (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_advances (hb_font_t *font, hb_buffer_t *buffer);
- static inline void position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer);
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
- return GSUBGPOS::subset<PosLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<PosLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
- {
- for (unsigned i = 0; i < GSUBGPOS::get_lookup_count (); i++)
- {
- if (!c->gpos_lookups->has (i)) continue;
- const PosLookup &l = get_lookup (i);
- l.dispatch (c);
- }
- }
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<PosLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GPOS> accelerator_t;
-};
-
-
-static void
-reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent)
-{
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain || 0 == (type & ATTACH_TYPE_CURSIVE)))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- /* Stop if we see new parent in the chain. */
- if (j == new_parent)
- return;
-
- reverse_cursive_minor_offset (pos, j, direction, new_parent);
-
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[j].y_offset = -pos[i].y_offset;
- else
- pos[j].x_offset = -pos[i].x_offset;
-
- pos[j].attach_chain() = -chain;
- pos[j].attach_type() = type;
-}
-static void
-propagate_attachment_offsets (hb_glyph_position_t *pos,
- unsigned int len,
- unsigned int i,
- hb_direction_t direction)
-{
- /* Adjusts offsets of attached glyphs (both cursive and mark) to accumulate
- * offset of glyph they are attached to. */
- int chain = pos[i].attach_chain(), type = pos[i].attach_type();
- if (likely (!chain))
- return;
-
- pos[i].attach_chain() = 0;
-
- unsigned int j = (int) i + chain;
-
- if (unlikely (j >= len))
- return;
-
- propagate_attachment_offsets (pos, len, j, direction);
-
- assert (!!(type & ATTACH_TYPE_MARK) ^ !!(type & ATTACH_TYPE_CURSIVE));
-
- if (type & ATTACH_TYPE_CURSIVE)
- {
- if (HB_DIRECTION_IS_HORIZONTAL (direction))
- pos[i].y_offset += pos[j].y_offset;
- else
- pos[i].x_offset += pos[j].x_offset;
- }
- else /*if (type & ATTACH_TYPE_MARK)*/
- {
- pos[i].x_offset += pos[j].x_offset;
- pos[i].y_offset += pos[j].y_offset;
-
- assert (j < i);
- if (HB_DIRECTION_IS_FORWARD (direction))
- for (unsigned int k = j; k < i; k++) {
- pos[i].x_offset -= pos[k].x_advance;
- pos[i].y_offset -= pos[k].y_advance;
- }
- else
- for (unsigned int k = j + 1; k < i + 1; k++) {
- pos[i].x_offset += pos[k].x_advance;
- pos[i].y_offset += pos[k].y_advance;
- }
- }
-}
-
-void
-GPOS::position_start (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- buffer->pos[i].attach_chain() = buffer->pos[i].attach_type() = 0;
-}
-
-void
-GPOS::position_finish_advances (hb_font_t *font HB_UNUSED, hb_buffer_t *buffer HB_UNUSED)
-{
- //_hb_buffer_assert_gsubgpos_vars (buffer);
-}
-
-void
-GPOS::position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
-{
- _hb_buffer_assert_gsubgpos_vars (buffer);
-
- unsigned int len;
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions (buffer, &len);
- hb_direction_t direction = buffer->props.direction;
-
- /* Handle attachments */
- if (buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT)
- for (unsigned i = 0; i < len; i++)
- propagate_attachment_offsets (pos, len, i, direction);
-
- if (unlikely (font->slant))
- {
- for (unsigned i = 0; i < len; i++)
- if (unlikely (pos[i].y_offset))
- pos[i].x_offset += _hb_roundf (font->slant_xy * pos[i].y_offset);
- }
-}
-
-
-struct GPOS_accelerator_t : GPOS::accelerator_t {
- GPOS_accelerator_t (hb_face_t *face) : GPOS::accelerator_t (face) {}
-};
-
-
+// TODO(garretrieger): Move into new layout directory.
/* Out-of-class implementation for methods recursing */
-
#ifndef HB_NO_OT_LAYOUT
template <typename context_t>
/*static*/ typename context_t::return_t PosLookup::dispatch_recurse_func (context_t *c, unsigned int lookup_index)
@@ -3121,13 +45,16 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t PosLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+PosLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool PosLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+template <>
+inline bool PosLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const PosLookup &l = c->face->table.GPOS.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
@@ -3141,7 +68,8 @@ template <typename context_t>
}
#endif
-
+} /* namespace GPOS_impl */
+} /* namespace Layout */
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
index 0b0bc547bd..50301ff1d9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsub-table.hh
@@ -29,1727 +29,13 @@
#ifndef HB_OT_LAYOUT_GSUB_TABLE_HH
#define HB_OT_LAYOUT_GSUB_TABLE_HH
-#include "hb-ot-layout-gsubgpos.hh"
-
+#include "OT/Layout/GSUB/GSUB.hh"
namespace OT {
+namespace Layout {
+namespace GSUB_impl {
-typedef hb_pair_t<hb_codepoint_t, hb_codepoint_t> hb_codepoint_pair_t;
-
-template<typename Iterator>
-static void SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it);
-
-
-struct SingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- unsigned d = deltaGlyphID;
-
- + hb_iter (this+coverage)
- | hb_filter (c->parent_active_glyphs ())
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- unsigned d = deltaGlyphID;
- + hb_iter (this+coverage)
- | hb_map ([d] (hb_codepoint_t g) { return (g + d) & 0xFFFFu; })
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
- unsigned int index = (this+coverage).get_coverage (glyph_id);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- /* According to the Adobe Annotated OpenType Suite, result is always
- * limited to 16bit. */
- glyph_id = (glyph_id + deltaGlyphID) & 0xFFFFu;
- c->replace_glyph (glyph_id);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs,
- unsigned delta)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- c->check_assign (deltaGlyphID, delta, HB_SERIALIZE_ERROR_INT_OVERFLOW);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- hb_codepoint_t delta = deltaGlyphID;
-
- auto it =
- + hb_iter (this+coverage)
- | hb_filter (glyphset)
- | hb_map_retains_sorting ([&] (hb_codepoint_t g) {
- return hb_codepoint_pair_t (g,
- (g + delta) & 0xFFFF); })
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_codepoint_pair_t p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- HBUINT16 deltaGlyphID; /* Add to original GlyphID to get
- * substitute GlyphID, modulo 0x10000 */
- public:
- DEFINE_SIZE_STATIC (6);
-};
-
-struct SingleSubstFormat2
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, substitute)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- c->replace_glyph (substitute[index]);
-
- return_trace (true);
- }
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator it)
- {
- TRACE_SERIALIZE (this);
- auto substitutes =
- + it
- | hb_map (hb_second)
- ;
- auto glyphs =
- + it
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
- if (unlikely (!coverage.serialize_serialize (c, glyphs))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- bool ret = bool (it);
- SingleSubst_serialize (c->serializer, it);
- return_trace (ret);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16Of<HBGlyphID16>
- substitute; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, substitute);
-};
-
-struct SingleSubst
-{
-
- template<typename Iterator,
- hb_requires (hb_is_sorted_source_of (Iterator,
- const hb_codepoint_pair_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator glyphs)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned format = 2;
- unsigned delta = 0;
- if (glyphs)
- {
- format = 1;
- auto get_delta = [=] (hb_codepoint_pair_t _)
- { return (unsigned) (_.second - _.first) & 0xFFFF; };
- delta = get_delta (*glyphs);
- if (!hb_all (++(+glyphs), delta, get_delta)) format = 2;
- }
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- + glyphs
- | hb_map_retains_sorting (hb_first),
- delta));
- case 2: return_trace (u.format2.serialize (c, glyphs));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- SingleSubstFormat1 format1;
- SingleSubstFormat2 format2;
- } u;
-};
-
-template<typename Iterator>
-static void
-SingleSubst_serialize (hb_serialize_context_t *c,
- Iterator it)
-{ c->start_embed<SingleSubst> ()->serialize (c, it); }
-
-struct Sequence
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (substitute, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (substitute.arrayZ, substitute.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = substitute.len;
-
- /* Special-case to make it in-place and not consider this
- * as a "multiplied" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (substitute.arrayZ[0]);
- return_trace (true);
- }
- /* Spec disallows this, but Uniscribe allows it.
- * https://github.com/harfbuzz/harfbuzz/issues/253 */
- else if (unlikely (count == 0))
- {
- c->buffer->delete_glyph ();
- return_trace (true);
- }
-
- unsigned int klass = _hb_glyph_info_is_ligature (&c->buffer->cur()) ?
- HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH : 0;
- unsigned lig_id = _hb_glyph_info_get_lig_id (&c->buffer->cur());
-
- for (unsigned int i = 0; i < count; i++)
- {
- /* If is attached to a ligature, don't disturb that.
- * https://github.com/harfbuzz/harfbuzz/issues/3069 */
- if (!lig_id)
- _hb_glyph_info_set_lig_props_for_component (&c->buffer->cur(), i);
- c->output_glyph_for_component (substitute.arrayZ[i], klass);
- }
- c->buffer->skip_glyph ();
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator subst)
- {
- TRACE_SERIALIZE (this);
- return_trace (substitute.serialize (c, subst));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset)) return_trace (false);
-
- auto it =
- + hb_iter (substitute)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID16>
- substitute; /* String of GlyphIDs to substitute */
- public:
- DEFINE_SIZE_ARRAY (2, substitute);
-};
-
-struct MultipleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, sequence)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.closure (c); })
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, sequence)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Sequence &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+sequence[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!sequence.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int substitute_len = substitute_len_list[i];
- if (unlikely (!sequence[i]
- .serialize_serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
- return_trace (false);
- substitute_glyphs_list += substitute_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, sequence)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->sequence, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && sequence.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<Sequence>
- sequence; /* Array of Sequence tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, sequence);
-};
-
-struct MultipleSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- MultipleSubstFormat1 format1;
- } u;
-};
-
-struct AlternateSet
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_any (alternates, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- { c->output->add_array (alternates.arrayZ, alternates.len); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = alternates.len;
-
- if (unlikely (!count)) return_trace (false);
-
- hb_mask_t glyph_mask = c->buffer->cur().mask;
- hb_mask_t lookup_mask = c->lookup_mask;
-
- /* Note: This breaks badly if two features enabled this lookup together. */
- unsigned int shift = hb_ctz (lookup_mask);
- unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
-
- /* If alt_index is MAX_VALUE, randomize feature if it is the rand feature. */
- if (alt_index == HB_OT_MAP_MAX_VALUE && c->random)
- {
- /* Maybe we can do better than unsafe-to-break all; but since we are
- * changing random state, it would be hard to track that. Good 'nough. */
- c->buffer->unsafe_to_break (0, c->buffer->len);
- alt_index = c->random_number () % count + 1;
- }
-
- if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
-
- c->replace_glyph (alternates[alt_index - 1]);
-
- return_trace (true);
- }
-
- unsigned
- get_alternates (unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- {
- if (alternates.len && alternate_count)
- {
- + alternates.sub_array (start_offset, alternate_count)
- | hb_sink (hb_array (alternate_glyphs, *alternate_count))
- ;
- }
- return alternates.len;
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- Iterator alts)
- {
- TRACE_SERIALIZE (this);
- return_trace (alternates.serialize (c, alts));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto it =
- + hb_iter (alternates)
- | hb_filter (glyphset)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer, it) &&
- out->alternates);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (alternates.sanitize (c));
- }
-
- protected:
- Array16Of<HBGlyphID16>
- alternates; /* Array of alternate GlyphIDs--in
- * arbitrary order */
- public:
- DEFINE_SIZE_ARRAY (2, alternates);
-};
-
-struct AlternateSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- { return (this+coverage).intersects (glyphs); }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
- + hb_zip (this+coverage, alternateSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const AlternateSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- unsigned
- get_glyph_alternates (hb_codepoint_t gid,
- unsigned start_offset,
- unsigned *alternate_count /* IN/OUT. May be NULL. */,
- hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
- { return (this+alternateSet[(this+coverage).get_coverage (gid)])
- .get_alternates (start_offset, alternate_count, alternate_glyphs); }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- return_trace ((this+alternateSet[index]).apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!alternateSet.serialize (c, glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < glyphs.length; i++)
- {
- unsigned int alternate_len = alternate_len_list[i];
- if (unlikely (!alternateSet[i]
- .serialize_serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
- return_trace (false);
- alternate_glyphs_list += alternate_len;
- }
- return_trace (coverage.serialize_serialize (c, glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- hb_sorted_vector_t<hb_codepoint_t> new_coverage;
- + hb_zip (this+coverage, alternateSet)
- | hb_filter (glyphset, hb_first)
- | hb_filter (subset_offset_array (c, out->alternateSet, this), hb_second)
- | hb_map (hb_first)
- | hb_map (glyph_map)
- | hb_sink (new_coverage)
- ;
- out->coverage.serialize_serialize (c->serializer, new_coverage.iter ());
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && alternateSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<AlternateSet>
- alternateSet; /* Array of AlternateSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, alternateSet);
-};
-
-struct AlternateSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- AlternateSubstFormat1 format1;
- } u;
-};
-
-
-struct Ligature
-{
- bool intersects (const hb_set_t *glyphs) const
- { return hb_all (component, glyphs); }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
- c->output->add (ligGlyph);
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->input->add_array (component.arrayZ, component.get_length ());
- c->output->add (ligGlyph);
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- if (c->len != component.lenP1)
- return false;
-
- for (unsigned int i = 1; i < c->len; i++)
- if (likely (c->glyphs[i] != component[i]))
- return false;
-
- return true;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int count = component.lenP1;
-
- if (unlikely (!count)) return_trace (false);
-
- /* Special-case to make it in-place and not consider this
- * as a "ligated" substitution. */
- if (unlikely (count == 1))
- {
- c->replace_glyph (ligGlyph);
- return_trace (true);
- }
-
- unsigned int total_component_count = 0;
-
- unsigned int match_end = 0;
- unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
-
- if (likely (!match_input (c, count,
- &component[1],
- match_glyph,
- nullptr,
- &match_end,
- match_positions,
- &total_component_count)))
- {
- c->buffer->unsafe_to_concat (c->buffer->idx, match_end);
- return_trace (false);
- }
-
- ligate_input (c,
- count,
- match_positions,
- match_end,
- ligGlyph,
- total_component_count);
-
- return_trace (true);
- }
-
- template <typename Iterator,
- hb_requires (hb_is_source_of (Iterator, hb_codepoint_t))>
- bool serialize (hb_serialize_context_t *c,
- hb_codepoint_t ligature,
- Iterator components /* Starting from second */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- ligGlyph = ligature;
- if (unlikely (!component.serialize (c, components))) return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- if (!intersects (&glyphset) || !glyphset.has (ligGlyph)) return_trace (false);
- // Ensure Coverage table is always packed after this.
- c->serializer->add_virtual_link (coverage_idx);
-
- auto it =
- + hb_iter (component)
- | hb_map (glyph_map)
- ;
-
- auto *out = c->serializer->start_embed (*this);
- return_trace (out->serialize (c->serializer,
- glyph_map[ligGlyph],
- it));
- }
-
- public:
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligGlyph.sanitize (c) && component.sanitize (c));
- }
-
- protected:
- HBGlyphID16 ligGlyph; /* GlyphID of ligature to substitute */
- HeadlessArrayOf<HBGlyphID16>
- component; /* Array of component GlyphIDs--start
- * with the second component--ordered
- * in writing direction */
- public:
- DEFINE_SIZE_ARRAY (4, component);
-};
-
-struct LigatureSet
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([glyphs] (const Ligature &_) { return _.intersects (glyphs); })
- | hb_any
- ;
- }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.closure (c); })
- ;
- }
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const Ligature &_) { _.collect_glyphs (c); })
- ;
- }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- return
- + hb_iter (ligature)
- | hb_map (hb_add (this))
- | hb_map ([c] (const Ligature &_) { return _.would_apply (c); })
- | hb_any
- ;
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- unsigned int num_ligs = ligature.len;
- for (unsigned int i = 0; i < num_ligs; i++)
- {
- const Ligature &lig = this+ligature[i];
- if (lig.apply (c)) return_trace (true);
- }
-
- return_trace (false);
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_array_t<const HBGlyphID16> ligatures,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> &component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligature.serialize (c, ligatures.length))) return_trace (false);
- for (unsigned int i = 0; i < ligatures.length; i++)
- {
- unsigned int component_count = (unsigned) hb_max ((int) component_count_list[i] - 1, 0);
- if (unlikely (!ligature[i].serialize_serialize (c,
- ligatures[i],
- component_list.sub_array (0, component_count))))
- return_trace (false);
- component_list += component_count;
- }
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c, unsigned coverage_idx) const
- {
- TRACE_SUBSET (this);
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
-
- + hb_iter (ligature)
- | hb_filter (subset_offset_array (c, out->ligature, this, coverage_idx))
- | hb_drain
- ;
-
- if (bool (out->ligature))
- // Ensure Coverage table is always packed after this.
- c->serializer->add_virtual_link (coverage_idx);
-
- return_trace (bool (out->ligature));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (ligature.sanitize (c, this));
- }
-
- protected:
- Array16OfOffset16To<Ligature>
- ligature; /* Array LigatureSet tables
- * ordered by preference */
- public:
- DEFINE_SIZE_ARRAY (2, ligature);
-};
-
-struct LigatureSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- return
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (*glyphs, hb_first)
- | hb_map (hb_second)
- | hb_map ([this, glyphs] (const Offset16To<LigatureSet> &_)
- { return (this+_).intersects (glyphs); })
- | hb_any
- ;
- }
-
- bool may_have_non_1to1 () const
- { return true; }
-
- void closure (hb_closure_context_t *c) const
- {
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.closure (c); })
- ;
-
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- + hb_zip (this+coverage, ligatureSet)
- | hb_map (hb_second)
- | hb_map (hb_add (this))
- | hb_apply ([c] (const LigatureSet &_) { _.collect_glyphs (c); })
- ;
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- {
- unsigned int index = (this+coverage).get_coverage (c->glyphs[0]);
- if (likely (index == NOT_COVERED)) return false;
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return lig_set.would_apply (c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const LigatureSet &lig_set = this+ligatureSet[index];
- return_trace (lig_set.apply (c));
- }
-
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!ligatureSet.serialize (c, first_glyphs.length))) return_trace (false);
- for (unsigned int i = 0; i < first_glyphs.length; i++)
- {
- unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
- if (unlikely (!ligatureSet[i]
- .serialize_serialize (c,
- ligatures_list.sub_array (0, ligature_count),
- component_count_list.sub_array (0, ligature_count),
- component_list))) return_trace (false);
- ligatures_list += ligature_count;
- component_count_list += ligature_count;
- }
- return_trace (coverage.serialize_serialize (c, first_glyphs));
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- auto *out = c->serializer->start_embed (*this);
- if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
- out->format = format;
-
- // Due to a bug in some older versions of windows 7 the Coverage table must be
- // packed after the LigatureSet and Ligature tables, so serialize Coverage first
- // which places it last in the packed order.
- hb_set_t new_coverage;
- + hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
- | hb_filter (glyphset, hb_first)
- | hb_filter ([&] (const LigatureSet& _) {
- return _.intersects (&glyphset);
- }, hb_second)
- | hb_map (hb_first)
- | hb_sink (new_coverage);
-
- if (!c->serializer->push<Coverage> ()
- ->serialize (c->serializer,
- + new_coverage.iter () | hb_map_retains_sorting (glyph_map)))
- {
- c->serializer->pop_discard ();
- return_trace (false);
- }
-
- unsigned coverage_idx = c->serializer->pop_pack ();
- c->serializer->add_link (out->coverage, coverage_idx);
-
- + hb_zip (this+coverage, ligatureSet)
- | hb_filter (new_coverage, hb_first)
- | hb_map (hb_second)
- // to ensure that the repacker always orders the coverage table after the LigatureSet
- // and LigatureSubtable's they will be linked to the Coverage table via a virtual link
- // the coverage table object idx is passed down to facilitate this.
- | hb_apply (subset_offset_array (c, out->ligatureSet, this, coverage_idx))
- ;
-
- return_trace (bool (new_coverage));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (coverage.sanitize (c, this) && ligatureSet.sanitize (c, this));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of Substitution table */
- Array16OfOffset16To<LigatureSet>
- ligatureSet; /* Array LigatureSet tables
- * ordered by Coverage Index */
- public:
- DEFINE_SIZE_ARRAY (6, ligatureSet);
-};
-
-struct LigatureSubst
-{
- bool serialize (hb_serialize_context_t *c,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!c->extend_min (u.format))) return_trace (false);
- unsigned int format = 1;
- u.format = format;
- switch (u.format) {
- case 1: return_trace (u.format1.serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list));
- default:return_trace (false);
- }
- }
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- LigatureSubstFormat1 format1;
- } u;
-};
-
-
-struct ContextSubst : Context {};
-
-struct ChainContextSubst : ChainContext {};
-
-struct ExtensionSubst : Extension<ExtensionSubst>
-{
- typedef struct SubstLookupSubTable SubTable;
- bool is_reverse () const;
-};
-
-
-struct ReverseChainSingleSubstFormat1
-{
- bool intersects (const hb_set_t *glyphs) const
- {
- if (!(this+coverage).intersects (glyphs))
- return false;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+backtrack[i]).intersects (glyphs))
- return false;
-
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (!(this+lookahead[i]).intersects (glyphs))
- return false;
-
- return true;
- }
-
- bool may_have_non_1to1 () const
- { return false; }
-
- void closure (hb_closure_context_t *c) const
- {
- if (!intersects (c->glyphs)) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- + hb_zip (this+coverage, substitute)
- | hb_filter (c->parent_active_glyphs (), hb_first)
- | hb_map (hb_second)
- | hb_sink (c->output)
- ;
- }
-
- void closure_lookups (hb_closure_lookups_context_t *c) const {}
-
- void collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
-
- unsigned int count;
-
- count = backtrack.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- count = lookahead.len;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
-
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
- count = substitute.len;
- c->output->add_array (substitute.arrayZ, substitute.len);
- }
-
- const Coverage &get_coverage () const { return this+coverage; }
-
- bool would_apply (hb_would_apply_context_t *c) const
- { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
- return_trace (false); /* No chaining to this type */
-
- unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
- if (likely (index == NOT_COVERED)) return_trace (false);
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- if (unlikely (index >= substitute.len)) return_trace (false);
-
- unsigned int start_index = 0, end_index = 0;
- if (match_backtrack (c,
- backtrack.len, (HBUINT16 *) backtrack.arrayZ,
- match_coverage, this,
- &start_index) &&
- match_lookahead (c,
- lookahead.len, (HBUINT16 *) lookahead.arrayZ,
- match_coverage, this,
- c->buffer->idx + 1, &end_index))
- {
- c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
- c->replace_glyph_inplace (substitute[index]);
- /* Note: We DON'T decrease buffer->idx. The main loop does it
- * for us. This is useful for preventing surprises if someone
- * calls us through a Context lookup. */
- return_trace (true);
- }
- else
- {
- c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
- return_trace (false);
- }
- }
-
- template<typename Iterator,
- hb_requires (hb_is_iterator (Iterator))>
- bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
-
- if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
- return_trace (false);
-
- for (auto& offset : it) {
- auto *o = out->serialize_append (c->serializer);
- if (unlikely (!o) || !o->serialize_subset (c, offset, this))
- return_trace (false);
- }
-
- return_trace (true);
- }
-
- template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
- hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
- hb_requires (hb_is_iterator (BacktrackIterator)),
- hb_requires (hb_is_iterator (LookaheadIterator))>
- bool serialize (hb_subset_context_t *c,
- Iterator coverage_subst_iter,
- BacktrackIterator backtrack_iter,
- LookaheadIterator lookahead_iter) const
- {
- TRACE_SERIALIZE (this);
-
- auto *out = c->serializer->start_embed (this);
- if (unlikely (!c->serializer->check_success (out))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
- if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
-
- if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
- if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
-
- auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
- auto substitutes =
- + coverage_subst_iter
- | hb_map (hb_second)
- ;
-
- auto glyphs =
- + coverage_subst_iter
- | hb_map_retains_sorting (hb_first)
- ;
- if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
- return_trace (false);
-
- if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
- return_trace (false);
- return_trace (true);
- }
-
- bool subset (hb_subset_context_t *c) const
- {
- TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
-
- auto it =
- + hb_zip (this+coverage, substitute)
- | hb_filter (glyphset, hb_first)
- | hb_filter (glyphset, hb_second)
- | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
- { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
- ;
-
- return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
- return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- if (!lookahead.sanitize (c, this))
- return_trace (false);
- const Array16Of<HBGlyphID16> &substitute = StructAfter<Array16Of<HBGlyphID16>> (lookahead);
- return_trace (substitute.sanitize (c));
- }
-
- protected:
- HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
- coverage; /* Offset to Coverage table--from
- * beginning of table */
- Array16OfOffset16To<Coverage>
- backtrack; /* Array of coverage tables
- * in backtracking sequence, in glyph
- * sequence order */
- Array16OfOffset16To<Coverage>
- lookaheadX; /* Array of coverage tables
- * in lookahead sequence, in glyph
- * sequence order */
- Array16Of<HBGlyphID16>
- substituteX; /* Array of substitute
- * GlyphIDs--ordered by Coverage Index */
- public:
- DEFINE_SIZE_MIN (10);
-};
-
-struct ReverseChainSingleSubst
-{
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, u.format);
- if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
- switch (u.format) {
- case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
- default:return_trace (c->default_return_value ());
- }
- }
-
- protected:
- union {
- HBUINT16 format; /* Format identifier */
- ReverseChainSingleSubstFormat1 format1;
- } u;
-};
-
-
-
-/*
- * SubstLookup
- */
-
-struct SubstLookupSubTable
-{
- friend struct Lookup;
- friend struct SubstLookup;
-
- enum Type {
- Single = 1,
- Multiple = 2,
- Alternate = 3,
- Ligature = 4,
- Context = 5,
- ChainContext = 6,
- Extension = 7,
- ReverseChainSingle = 8
- };
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, unsigned int lookup_type, Ts&&... ds) const
- {
- TRACE_DISPATCH (this, lookup_type);
- switch (lookup_type) {
- case Single: return_trace (u.single.dispatch (c, std::forward<Ts> (ds)...));
- case Multiple: return_trace (u.multiple.dispatch (c, std::forward<Ts> (ds)...));
- case Alternate: return_trace (u.alternate.dispatch (c, std::forward<Ts> (ds)...));
- case Ligature: return_trace (u.ligature.dispatch (c, std::forward<Ts> (ds)...));
- case Context: return_trace (u.context.dispatch (c, std::forward<Ts> (ds)...));
- case ChainContext: return_trace (u.chainContext.dispatch (c, std::forward<Ts> (ds)...));
- case Extension: return_trace (u.extension.dispatch (c, std::forward<Ts> (ds)...));
- case ReverseChainSingle: return_trace (u.reverseChainContextSingle.dispatch (c, std::forward<Ts> (ds)...));
- default: return_trace (c->default_return_value ());
- }
- }
-
- bool intersects (const hb_set_t *glyphs, unsigned int lookup_type) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c, lookup_type);
- }
-
- protected:
- union {
- SingleSubst single;
- MultipleSubst multiple;
- AlternateSubst alternate;
- LigatureSubst ligature;
- ContextSubst context;
- ChainContextSubst chainContext;
- ExtensionSubst extension;
- ReverseChainSingleSubst reverseChainContextSingle;
- } u;
- public:
- DEFINE_SIZE_MIN (0);
-};
-
-
-struct SubstLookup : Lookup
-{
- typedef SubstLookupSubTable SubTable;
-
- const SubTable& get_subtable (unsigned int i) const
- { return Lookup::get_subtable<SubTable> (i); }
-
- static inline bool lookup_type_is_reverse (unsigned int lookup_type)
- { return lookup_type == SubTable::ReverseChainSingle; }
-
- bool is_reverse () const
- {
- unsigned int type = get_type ();
- if (unlikely (type == SubTable::Extension))
- return reinterpret_cast<const ExtensionSubst &> (get_subtable (0)).is_reverse ();
- return lookup_type_is_reverse (type);
- }
-
- bool may_have_non_1to1 () const
- {
- hb_have_non_1to1_context_t c;
- return dispatch (&c);
- }
-
- bool apply (hb_ot_apply_context_t *c) const
- {
- TRACE_APPLY (this);
- return_trace (dispatch (c));
- }
-
- bool intersects (const hb_set_t *glyphs) const
- {
- hb_intersects_context_t c (glyphs);
- return dispatch (&c);
- }
-
- hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
- {
- if (!c->should_visit_lookup (this_index))
- return hb_closure_context_t::default_return_value ();
-
- c->set_recurse_func (dispatch_closure_recurse_func);
-
- hb_closure_context_t::return_t ret = dispatch (c);
-
- c->flush ();
-
- return ret;
- }
-
- hb_closure_lookups_context_t::return_t closure_lookups (hb_closure_lookups_context_t *c, unsigned this_index) const
- {
- if (c->is_lookup_visited (this_index))
- return hb_closure_lookups_context_t::default_return_value ();
-
- c->set_lookup_visited (this_index);
- if (!intersects (c->glyphs))
- {
- c->set_lookup_inactive (this_index);
- return hb_closure_lookups_context_t::default_return_value ();
- }
-
- c->set_recurse_func (dispatch_closure_lookups_recurse_func);
-
- hb_closure_lookups_context_t::return_t ret = dispatch (c);
- return ret;
- }
-
- hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
- {
- c->set_recurse_func (dispatch_recurse_func<hb_collect_glyphs_context_t>);
- return dispatch (c);
- }
-
- template <typename set_t>
- void collect_coverage (set_t *glyphs) const
- {
- hb_collect_coverage_context_t<set_t> c (glyphs);
- dispatch (&c);
- }
-
- bool would_apply (hb_would_apply_context_t *c,
- const hb_ot_layout_lookup_accelerator_t *accel) const
- {
- if (unlikely (!c->len)) return false;
- if (!accel->may_have (c->glyphs[0])) return false;
- return dispatch (c);
- }
-
- static inline bool apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index);
-
- bool serialize_single (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const HBGlyphID16> substitutes)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.single.serialize (c, hb_zip (glyphs, substitutes)))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_multiple (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> substitute_len_list,
- hb_array_t<const HBGlyphID16> substitute_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.multiple.
- serialize (c,
- glyphs,
- substitute_len_list,
- substitute_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_alternate (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> glyphs,
- hb_array_t<const unsigned int> alternate_len_list,
- hb_array_t<const HBGlyphID16> alternate_glyphs_list)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
-
- if (c->push<SubTable> ()->u.alternate.
- serialize (c,
- glyphs,
- alternate_len_list,
- alternate_glyphs_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- bool serialize_ligature (hb_serialize_context_t *c,
- uint32_t lookup_props,
- hb_sorted_array_t<const HBGlyphID16> first_glyphs,
- hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
- hb_array_t<const HBGlyphID16> ligatures_list,
- hb_array_t<const unsigned int> component_count_list,
- hb_array_t<const HBGlyphID16> component_list /* Starting from second for each ligature */)
- {
- TRACE_SERIALIZE (this);
- if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
- if (c->push<SubTable> ()->u.ligature.
- serialize (c,
- first_glyphs,
- ligature_per_first_glyph_count_list,
- ligatures_list,
- component_count_list,
- component_list))
- {
- c->add_link (get_subtables<SubTable> ()[0], c->pop_pack ());
- return_trace (true);
- }
- c->pop_discard ();
- return_trace (false);
- }
-
- template <typename context_t>
- static inline typename context_t::return_t dispatch_recurse_func (context_t *c, unsigned int lookup_index);
-
- static inline typename hb_closure_context_t::return_t closure_glyphs_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index);
-
- static inline hb_closure_context_t::return_t dispatch_closure_recurse_func (hb_closure_context_t *c, unsigned lookup_index, hb_set_t *covered_seq_indices, unsigned seq_index, unsigned end_index)
- {
- if (!c->should_visit_lookup (lookup_index))
- return hb_empty_t ();
-
- hb_closure_context_t::return_t ret = closure_glyphs_recurse_func (c, lookup_index, covered_seq_indices, seq_index, end_index);
-
- /* While in theory we should flush here, it will cause timeouts because a recursive
- * lookup can keep growing the glyph set. Skip, and outer loop will retry up to
- * HB_CLOSURE_MAX_STAGES time, which should be enough for every realistic font. */
- //c->flush ();
-
- return ret;
- }
-
- HB_INTERNAL static hb_closure_lookups_context_t::return_t dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned lookup_index);
-
- template <typename context_t, typename ...Ts>
- typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
- { return Lookup::dispatch<SubTable> (c, std::forward<Ts> (ds)...); }
-
- bool subset (hb_subset_context_t *c) const
- { return Lookup::subset<SubTable> (c); }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return Lookup::sanitize<SubTable> (c); }
-};
-
-/*
- * GSUB -- Glyph Substitution
- * https://docs.microsoft.com/en-us/typography/opentype/spec/gsub
- */
-
-struct GSUB : GSUBGPOS
-{
- static constexpr hb_tag_t tableTag = HB_OT_TAG_GSUB;
-
- const SubstLookup& get_lookup (unsigned int i) const
- { return static_cast<const SubstLookup &> (GSUBGPOS::get_lookup (i)); }
-
- bool subset (hb_subset_context_t *c) const
- {
- hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
- return GSUBGPOS::subset<SubstLookup> (&l);
- }
-
- bool sanitize (hb_sanitize_context_t *c) const
- { return GSUBGPOS::sanitize<SubstLookup> (c); }
-
- HB_INTERNAL bool is_blocklisted (hb_blob_t *blob,
- hb_face_t *face) const;
-
- void closure_lookups (hb_face_t *face,
- const hb_set_t *glyphs,
- hb_set_t *lookup_indexes /* IN/OUT */) const
- { GSUBGPOS::closure_lookups<SubstLookup> (face, glyphs, lookup_indexes); }
-
- typedef GSUBGPOS::accelerator_t<GSUB> accelerator_t;
-};
-
-
-struct GSUB_accelerator_t : GSUB::accelerator_t {
- GSUB_accelerator_t (hb_face_t *face) : GSUB::accelerator_t (face) {}
-};
-
-
+// TODO(garretrieger): Move into the new layout directory.
/* Out-of-class implementation for methods recursing */
#ifndef HB_NO_OT_LAYOUT
@@ -1772,13 +58,16 @@ template <typename context_t>
return l.dispatch (c);
}
-/*static*/ inline hb_closure_lookups_context_t::return_t SubstLookup::dispatch_closure_lookups_recurse_func (hb_closure_lookups_context_t *c, unsigned this_index)
+template <>
+inline hb_closure_lookups_context_t::return_t
+SubstLookup::dispatch_recurse_func<hb_closure_lookups_context_t> (hb_closure_lookups_context_t *c, unsigned this_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (this_index);
return l.closure_lookups (c, this_index);
}
-/*static*/ bool SubstLookup::apply_recurse_func (hb_ot_apply_context_t *c, unsigned int lookup_index)
+template <>
+inline bool SubstLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply_context_t *c, unsigned int lookup_index)
{
const SubstLookup &l = c->face->table.GSUB.get_relaxed ()->table->get_lookup (lookup_index);
unsigned int saved_lookup_props = c->lookup_props;
@@ -1792,7 +81,8 @@ template <typename context_t>
}
#endif
-
+} /* namespace GSUB_impl */
+} /* namespace Layout */
} /* namespace OT */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
index 65de131f85..c77ec12fbe 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
@@ -109,14 +109,10 @@ struct hb_closure_context_t :
{
done_lookups_glyph_count->set (lookup_index, glyphs->get_population ());
- if (!done_lookups_glyph_set->get (lookup_index))
+ if (!done_lookups_glyph_set->has (lookup_index))
{
- hb_set_t* empty_set = hb_set_create ();
- if (unlikely (!done_lookups_glyph_set->set (lookup_index, empty_set)))
- {
- hb_set_destroy (empty_set);
+ if (unlikely (!done_lookups_glyph_set->set (lookup_index, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
return true;
- }
}
hb_set_clear (done_lookups_glyph_set->get (lookup_index));
@@ -154,7 +150,7 @@ struct hb_closure_context_t :
bool pop_cur_done_glyphs ()
{
- if (active_glyphs_stack.length < 1)
+ if (!active_glyphs_stack)
return false;
active_glyphs_stack.pop ();
@@ -165,21 +161,19 @@ struct hb_closure_context_t :
hb_set_t *glyphs;
hb_set_t output[1];
hb_vector_t<hb_set_t> active_glyphs_stack;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
unsigned int nesting_level_left;
hb_closure_context_t (hb_face_t *face_,
hb_set_t *glyphs_,
hb_map_t *done_lookups_glyph_count_,
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set_,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set_,
unsigned int nesting_level_left_ = HB_MAX_NESTING_LEVEL) :
face (face_),
glyphs (glyphs_),
- recurse_func (nullptr),
nesting_level_left (nesting_level_left_),
done_lookups_glyph_count (done_lookups_glyph_count_),
- done_lookups_glyph_set (done_lookups_glyph_set_),
- lookup_count (0)
+ done_lookups_glyph_set (done_lookups_glyph_set_)
{}
~hb_closure_context_t () { flush (); }
@@ -197,8 +191,8 @@ struct hb_closure_context_t :
private:
hb_map_t *done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> *done_lookups_glyph_set;
- unsigned int lookup_count;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *done_lookups_glyph_set;
+ unsigned int lookup_count = 0;
};
@@ -400,7 +394,6 @@ struct hb_collect_coverage_context_t :
set_t *set;
};
-
struct hb_ot_apply_context_t :
hb_dispatch_context_t<hb_ot_apply_context_t, bool, HB_DEBUG_APPLY>
{
@@ -408,22 +401,22 @@ struct hb_ot_apply_context_t :
{
matcher_t () :
lookup_props (0),
+ mask (-1),
ignore_zwnj (false),
ignore_zwj (false),
- mask (-1),
-#define arg1(arg) (arg) /* Remove the macro to see why it's needed! */
- syllable arg1(0),
-#undef arg1
+ per_syllable (false),
+ syllable {0},
match_func (nullptr),
match_data (nullptr) {}
- typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+ typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
void set_ignore_zwnj (bool ignore_zwnj_) { ignore_zwnj = ignore_zwnj_; }
void set_ignore_zwj (bool ignore_zwj_) { ignore_zwj = ignore_zwj_; }
void set_lookup_props (unsigned int lookup_props_) { lookup_props = lookup_props_; }
void set_mask (hb_mask_t mask_) { mask = mask_; }
- void set_syllable (uint8_t syllable_) { syllable = syllable_; }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; }
+ void set_syllable (uint8_t syllable_) { syllable = per_syllable ? syllable_ : 0; }
void set_match_func (match_func_t match_func_,
const void *match_data_)
{ match_func = match_func_; match_data = match_data_; }
@@ -434,15 +427,15 @@ struct hb_ot_apply_context_t :
MATCH_MAYBE
};
- may_match_t may_match (const hb_glyph_info_t &info,
- const HBUINT16 *glyph_data) const
+ may_match_t may_match (hb_glyph_info_t &info,
+ hb_codepoint_t glyph_data) const
{
if (!(info.mask & mask) ||
(syllable && syllable != info.syllable ()))
return MATCH_NO;
if (match_func)
- return match_func (info.codepoint, *glyph_data, match_data) ? MATCH_YES : MATCH_NO;
+ return match_func (info, glyph_data, match_data) ? MATCH_YES : MATCH_NO;
return MATCH_MAYBE;
}
@@ -469,9 +462,10 @@ struct hb_ot_apply_context_t :
protected:
unsigned int lookup_props;
+ hb_mask_t mask;
bool ignore_zwnj;
bool ignore_zwj;
- hb_mask_t mask;
+ bool per_syllable;
uint8_t syllable;
match_func_t match_func;
const void *match_data;
@@ -482,7 +476,10 @@ struct hb_ot_apply_context_t :
void init (hb_ot_apply_context_t *c_, bool context_match = false)
{
c = c_;
- match_glyph_data = nullptr;
+ match_glyph_data16 = nullptr;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
matcher.set_match_func (nullptr, nullptr);
matcher.set_lookup_props (c->lookup_props);
/* Ignore ZWNJ if we are matching GPOS, or matching GSUB context and asked to. */
@@ -490,18 +487,31 @@ struct hb_ot_apply_context_t :
/* Ignore ZWJ if we are matching context, or asked to. */
matcher.set_ignore_zwj (context_match || c->auto_zwj);
matcher.set_mask (context_match ? -1 : c->lookup_mask);
+ matcher.set_per_syllable (c->per_syllable);
}
void set_lookup_props (unsigned int lookup_props)
{
matcher.set_lookup_props (lookup_props);
}
void set_match_func (matcher_t::match_func_t match_func_,
- const void *match_data_,
- const HBUINT16 glyph_data[])
+ const void *match_data_)
{
matcher.set_match_func (match_func_, match_data_);
- match_glyph_data = glyph_data;
}
+ void set_glyph_data (const HBUINT16 glyph_data[])
+ {
+ match_glyph_data16 = glyph_data;
+#ifndef HB_NO_BEYOND_64K
+ match_glyph_data24 = nullptr;
+#endif
+ }
+#ifndef HB_NO_BEYOND_64K
+ void set_glyph_data (const HBUINT24 glyph_data[])
+ {
+ match_glyph_data16 = nullptr;
+ match_glyph_data24 = glyph_data;
+ }
+#endif
void reset (unsigned int start_index_,
unsigned int num_items_)
@@ -515,7 +525,7 @@ struct hb_ot_apply_context_t :
void reject ()
{
num_items++;
- if (match_glyph_data) match_glyph_data--;
+ backup_glyph_data ();
}
matcher_t::may_skip_t
@@ -528,19 +538,19 @@ struct hb_ot_apply_context_t :
while (idx + num_items < end)
{
idx++;
- const hb_glyph_info_t &info = c->buffer->info[idx];
+ hb_glyph_info_t &info = c->buffer->info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
continue;
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+ matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
{
num_items--;
- if (match_glyph_data) match_glyph_data++;
+ advance_glyph_data ();
return true;
}
@@ -561,19 +571,19 @@ struct hb_ot_apply_context_t :
while (idx > num_items - 1)
{
idx--;
- const hb_glyph_info_t &info = c->buffer->out_info[idx];
+ hb_glyph_info_t &info = c->buffer->out_info[idx];
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
if (unlikely (skip == matcher_t::SKIP_YES))
continue;
- matcher_t::may_match_t match = matcher.may_match (info, match_glyph_data);
+ matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
if (match == matcher_t::MATCH_YES ||
(match == matcher_t::MATCH_MAYBE &&
skip == matcher_t::SKIP_NO))
{
num_items--;
- if (match_glyph_data) match_glyph_data++;
+ advance_glyph_data ();
return true;
}
@@ -589,11 +599,43 @@ struct hb_ot_apply_context_t :
return false;
}
+ hb_codepoint_t
+ get_glyph_data ()
+ {
+ if (match_glyph_data16) return *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) return *match_glyph_data24;
+#endif
+ return 0;
+ }
+ void
+ advance_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16++;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24++;
+#endif
+ }
+ void
+ backup_glyph_data ()
+ {
+ if (match_glyph_data16) match_glyph_data16--;
+#ifndef HB_NO_BEYOND_64K
+ else
+ if (match_glyph_data24) match_glyph_data24--;
+#endif
+ }
+
unsigned int idx;
protected:
hb_ot_apply_context_t *c;
matcher_t matcher;
- const HBUINT16 *match_glyph_data;
+ const HBUINT16 *match_glyph_data16;
+#ifndef HB_NO_BEYOND_64K
+ const HBUINT24 *match_glyph_data24;
+#endif
unsigned int num_items;
unsigned int end;
@@ -609,7 +651,10 @@ struct hb_ot_apply_context_t :
return_t recurse (unsigned int sub_lookup_index)
{
if (unlikely (nesting_level_left == 0 || !recurse_func || buffer->max_ops-- <= 0))
+ {
+ buffer->shaping_failed = true;
return default_return_value ();
+ }
nesting_level_left--;
bool ret = recurse_func (this, sub_lookup_index);
@@ -619,34 +664,34 @@ struct hb_ot_apply_context_t :
skipping_iterator_t iter_input, iter_context;
+ unsigned int table_index; /* GSUB/GPOS */
hb_font_t *font;
hb_face_t *face;
hb_buffer_t *buffer;
- recurse_func_t recurse_func;
+ recurse_func_t recurse_func = nullptr;
const GDEF &gdef;
const VariationStore &var_store;
+ VariationStore::cache_t *var_store_cache;
hb_direction_t direction;
- hb_mask_t lookup_mask;
- unsigned int table_index; /* GSUB/GPOS */
- unsigned int lookup_index;
- unsigned int lookup_props;
- unsigned int nesting_level_left;
+ hb_mask_t lookup_mask = 1;
+ unsigned int lookup_index = (unsigned) -1;
+ unsigned int lookup_props = 0;
+ unsigned int nesting_level_left = HB_MAX_NESTING_LEVEL;
bool has_glyph_classes;
- bool auto_zwnj;
- bool auto_zwj;
- bool random;
-
- uint32_t random_state;
-
+ bool auto_zwnj = true;
+ bool auto_zwj = true;
+ bool per_syllable = false;
+ bool random = false;
+ uint32_t random_state = 1;
+ unsigned new_syllables = (unsigned) -1;
hb_ot_apply_context_t (unsigned int table_index_,
hb_font_t *font_,
hb_buffer_t *buffer_) :
- iter_input (), iter_context (),
+ table_index (table_index_),
font (font_), face (font->face), buffer (buffer_),
- recurse_func (nullptr),
gdef (
#ifndef HB_NO_OT_LAYOUT
*face->table.GDEF->table
@@ -655,17 +700,23 @@ struct hb_ot_apply_context_t :
#endif
),
var_store (gdef.get_var_store ()),
+ var_store_cache (
+#ifndef HB_NO_VAR
+ table_index == 1 && font->num_coords ? var_store.create_cache () : nullptr
+#else
+ nullptr
+#endif
+ ),
direction (buffer_->props.direction),
- lookup_mask (1),
- table_index (table_index_),
- lookup_index ((unsigned int) -1),
- lookup_props (0),
- nesting_level_left (HB_MAX_NESTING_LEVEL),
- has_glyph_classes (gdef.has_glyph_classes ()),
- auto_zwnj (true),
- auto_zwj (true),
- random (false),
- random_state (1) { init_iters (); }
+ has_glyph_classes (gdef.has_glyph_classes ())
+ { init_iters (); }
+
+ ~hb_ot_apply_context_t ()
+ {
+#ifndef HB_NO_VAR
+ VariationStore::destroy_cache (var_store_cache);
+#endif
+ }
void init_iters ()
{
@@ -676,6 +727,7 @@ struct hb_ot_apply_context_t :
void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
+ void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); }
void set_random (bool random_) { random = random_; }
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
void set_lookup_index (unsigned int lookup_index_) { lookup_index = lookup_index_; }
@@ -731,6 +783,9 @@ struct hb_ot_apply_context_t :
bool ligature = false,
bool component = false) const
{
+ if (new_syllables != (unsigned) -1)
+ buffer->cur().syllable() = new_syllables;
+
unsigned int props = _hb_glyph_info_get_glyph_props (&buffer->cur());
props |= HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED;
if (ligature)
@@ -785,8 +840,8 @@ struct hb_ot_apply_context_t :
};
-struct hb_get_subtables_context_t :
- hb_dispatch_context_t<hb_get_subtables_context_t>
+struct hb_accelerate_subtables_context_t :
+ hb_dispatch_context_t<hb_accelerate_subtables_context_t>
{
template <typename Type>
static inline bool apply_to (const void *obj, OT::hb_ot_apply_context_t *c)
@@ -795,15 +850,53 @@ struct hb_get_subtables_context_t :
return typed_obj->apply (c);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<1>) HB_RETURN (bool, obj->apply (c, true) )
+ template <typename T>
+ static inline auto apply_cached_ (const T *obj, OT::hb_ot_apply_context_t *c, hb_priority<0>) HB_RETURN (bool, obj->apply (c) )
+ template <typename Type>
+ static inline bool apply_cached_to (const void *obj, OT::hb_ot_apply_context_t *c)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return apply_cached_ (typed_obj, c, hb_prioritize);
+ }
+
+ template <typename T>
+ static inline auto cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<1>) HB_RETURN (bool, obj->cache_func (c, enter) )
+ template <typename T>
+ static inline bool cache_func_ (const T *obj, OT::hb_ot_apply_context_t *c, bool enter, hb_priority<0>) { return false; }
+ template <typename Type>
+ static inline bool cache_func_to (const void *obj, OT::hb_ot_apply_context_t *c, bool enter)
+ {
+ const Type *typed_obj = (const Type *) obj;
+ return cache_func_ (typed_obj, c, enter, hb_prioritize);
+ }
+#endif
+
typedef bool (*hb_apply_func_t) (const void *obj, OT::hb_ot_apply_context_t *c);
+ typedef bool (*hb_cache_func_t) (const void *obj, OT::hb_ot_apply_context_t *c, bool enter);
struct hb_applicable_t
{
+ friend struct hb_accelerate_subtables_context_t;
+ friend struct hb_ot_layout_lookup_accelerator_t;
+
template <typename T>
- void init (const T &obj_, hb_apply_func_t apply_func_)
+ void init (const T &obj_,
+ hb_apply_func_t apply_func_
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , hb_apply_func_t apply_cached_func_
+ , hb_cache_func_t cache_func_
+#endif
+ )
{
obj = &obj_;
apply_func = apply_func_;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ apply_cached_func = apply_cached_func_;
+ cache_func = cache_func_;
+#endif
digest.init ();
obj_.get_coverage ().collect_coverage (&digest);
}
@@ -812,38 +905,93 @@ struct hb_get_subtables_context_t :
{
return digest.may_have (c->buffer->cur().codepoint) && apply_func (obj, c);
}
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ bool apply_cached (OT::hb_ot_apply_context_t *c) const
+ {
+ return digest.may_have (c->buffer->cur().codepoint) && apply_cached_func (obj, c);
+ }
+ bool cache_enter (OT::hb_ot_apply_context_t *c) const
+ {
+ return cache_func (obj, c, true);
+ }
+ void cache_leave (OT::hb_ot_apply_context_t *c) const
+ {
+ cache_func (obj, c, false);
+ }
+#endif
private:
const void *obj;
hb_apply_func_t apply_func;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ hb_apply_func_t apply_cached_func;
+ hb_cache_func_t cache_func;
+#endif
hb_set_digest_t digest;
};
typedef hb_vector_t<hb_applicable_t> array_t;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ template <typename T>
+ auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
+ template <typename T>
+ auto cache_cost (const T &obj, hb_priority<0>) HB_AUTO_RETURN ( 0u )
+#endif
+
/* Dispatch interface. */
template <typename T>
return_t dispatch (const T &obj)
{
- hb_applicable_t *entry = array.push();
- entry->init (obj, apply_to<T>);
+ hb_applicable_t entry;
+
+ entry.init (obj,
+ apply_to<T>
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ , apply_cached_to<T>
+ , cache_func_to<T>
+#endif
+ );
+
+ array.push (entry);
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ /* Cache handling
+ *
+ * We allow one subtable from each lookup to use a cache. The assumption
+ * being that multiple subtables of the same lookup cannot use a cache
+ * because the resources they would use will collide. As such, we ask
+ * each subtable to tell us how much it costs (which a cache would avoid),
+ * and we allocate the cache opportunity to the costliest subtable.
+ */
+ unsigned cost = cache_cost (obj, hb_prioritize);
+ if (cost > cache_user_cost && !array.in_error ())
+ {
+ cache_user_idx = array.length - 1;
+ cache_user_cost = cost;
+ }
+#endif
+
return hb_empty_t ();
}
static return_t default_return_value () { return hb_empty_t (); }
- hb_get_subtables_context_t (array_t &array_) :
- array (array_) {}
+ hb_accelerate_subtables_context_t (array_t &array_) :
+ array (array_) {}
array_t &array;
-};
-
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned cache_user_idx = (unsigned) -1;
+ unsigned cache_user_cost = 0;
+#endif
+};
-typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
+typedef bool (*intersects_func_t) (const hb_set_t *glyphs, unsigned value, const void *data);
typedef void (*intersected_glyphs_func_t) (const hb_set_t *glyphs, const void *data, unsigned value, hb_set_t *intersected_glyphs);
-typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
-typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
+typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, unsigned value, const void *data);
+typedef bool (*match_func_t) (hb_glyph_info_t &info, unsigned value, const void *data);
struct ContextClosureFuncs
{
@@ -858,20 +1006,25 @@ struct ContextApplyFuncs
{
match_func_t match;
};
+struct ChainContextApplyFuncs
+{
+ match_func_t match[3];
+};
-static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline bool intersects_glyph (const hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
{
return glyphs->has (value);
}
-static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_class (const hb_set_t *glyphs, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
return class_def.intersects_class (glyphs, value);
}
-static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline bool intersects_coverage (const hb_set_t *glyphs, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
return (data+coverage).intersects (glyphs);
}
@@ -890,68 +1043,84 @@ static inline void intersected_coverage_glyphs (const hb_set_t *glyphs, const vo
{
Offset16To<Coverage> coverage;
coverage = value;
- (data+coverage).intersected_coverage_glyphs (glyphs, intersected_glyphs);
+ (data+coverage).intersect_set (*glyphs, *intersected_glyphs);
}
+template <typename HBUINT>
static inline bool array_is_subset_of (const hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
intersects_func_t intersects_func,
const void *intersects_data)
{
- for (const HBUINT16 &_ : + hb_iter (values, count))
+ for (const auto &_ : + hb_iter (values, count))
if (!intersects_func (glyphs, _, intersects_data)) return false;
return true;
}
-static inline void collect_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline void collect_glyph (hb_set_t *glyphs, unsigned value, const void *data HB_UNUSED)
{
glyphs->add (value);
}
-static inline void collect_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_class (hb_set_t *glyphs, unsigned value, const void *data)
{
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
class_def.collect_class (glyphs, value);
}
-static inline void collect_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
+static inline void collect_coverage (hb_set_t *glyphs, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
+ Offset16To<Coverage> coverage;
+ coverage = value;
(data+coverage).collect_coverage (glyphs);
}
+template <typename HBUINT>
static inline void collect_array (hb_collect_glyphs_context_t *c HB_UNUSED,
hb_set_t *glyphs,
unsigned int count,
- const HBUINT16 values[],
+ const HBUINT values[],
collect_glyphs_func_t collect_func,
const void *collect_data)
{
return
+ hb_iter (values, count)
- | hb_apply ([&] (const HBUINT16 &_) { collect_func (glyphs, _, collect_data); })
+ | hb_apply ([&] (const HBUINT &_) { collect_func (glyphs, _, collect_data); })
;
}
-static inline bool match_glyph (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data HB_UNUSED)
+static inline bool match_glyph (hb_glyph_info_t &info, unsigned value, const void *data HB_UNUSED)
+{
+ return info.codepoint == value;
+}
+static inline bool match_class (hb_glyph_info_t &info, unsigned value, const void *data)
{
- return glyph_id == value;
+ const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
+ return class_def.get_class (info.codepoint) == value;
}
-static inline bool match_class (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_class_cached (hb_glyph_info_t &info, unsigned value, const void *data)
{
+ unsigned klass = info.syllable();
+ if (klass < 255)
+ return klass == value;
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
- return class_def.get_class (glyph_id) == value;
+ klass = class_def.get_class (info.codepoint);
+ if (likely (klass < 255))
+ info.syllable() = klass;
+ return klass == value;
}
-static inline bool match_coverage (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data)
+static inline bool match_coverage (hb_glyph_info_t &info, unsigned value, const void *data)
{
- const Offset16To<Coverage> &coverage = (const Offset16To<Coverage>&)value;
- return (data+coverage).get_coverage (glyph_id) != NOT_COVERED;
+ Offset16To<Coverage> coverage;
+ coverage = value;
+ return (data+coverage).get_coverage (info.codepoint) != NOT_COVERED;
}
+template <typename HBUINT>
static inline bool would_match_input (hb_would_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data)
{
@@ -959,14 +1128,19 @@ static inline bool would_match_input (hb_would_apply_context_t *c,
return false;
for (unsigned int i = 1; i < count; i++)
- if (likely (!match_func (c->glyphs[i], input[i - 1], match_data)))
+ {
+ hb_glyph_info_t info;
+ info.codepoint = c->glyphs[i];
+ if (likely (!match_func (info, input[i - 1], match_data)))
return false;
+ }
return true;
}
+template <typename HBUINT>
static inline bool match_input (hb_ot_apply_context_t *c,
unsigned int count, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
match_func_t match_func,
const void *match_data,
unsigned int *end_position,
@@ -981,7 +1155,8 @@ static inline bool match_input (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
skippy_iter.reset (buffer->idx, count - 1);
- skippy_iter.set_match_func (match_func, match_data, input);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (input);
/*
* This is perhaps the trickiest part of OpenType... Remarks:
@@ -1202,9 +1377,10 @@ static inline bool ligate_input (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_backtrack (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
match_func_t match_func,
const void *match_data,
unsigned int *match_start)
@@ -1213,7 +1389,8 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (c->buffer->backtrack_len (), count);
- skippy_iter.set_match_func (match_func, match_data, backtrack);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (backtrack);
for (unsigned int i = 0; i < count; i++)
{
@@ -1229,9 +1406,10 @@ static inline bool match_backtrack (hb_ot_apply_context_t *c,
return_trace (true);
}
+template <typename HBUINT>
static inline bool match_lookahead (hb_ot_apply_context_t *c,
unsigned int count,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
match_func_t match_func,
const void *match_data,
unsigned int start_index,
@@ -1241,7 +1419,8 @@ static inline bool match_lookahead (hb_ot_apply_context_t *c,
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_context;
skippy_iter.reset (start_index - 1, count);
- skippy_iter.set_match_func (match_func, match_data, lookahead);
+ skippy_iter.set_match_func (match_func, match_data);
+ skippy_iter.set_glyph_data (lookahead);
for (unsigned int i = 0; i < count; i++)
{
@@ -1305,8 +1484,9 @@ static unsigned serialize_lookuprecord_array (hb_serialize_context_t *c,
enum ContextFormat { SimpleContext = 1, ClassBasedContext = 2, CoverageBasedContext = 3 };
+template <typename HBUINT>
static void context_closure_recurse_lookups (hb_closure_context_t *c,
- unsigned inputCount, const HBUINT16 input[],
+ unsigned inputCount, const HBUINT input[],
unsigned lookupCount,
const LookupRecord lookupRecord[] /* Array of LookupRecords--in design order */,
unsigned value,
@@ -1323,7 +1503,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
bool has_pos_glyphs = false;
hb_set_t pos_glyphs;
- if (hb_set_is_empty (covered_seq_indicies) || !hb_set_has (covered_seq_indicies, seqIndex))
+ if (!hb_set_has (covered_seq_indicies, seqIndex))
{
has_pos_glyphs = true;
if (seqIndex == 0)
@@ -1356,7 +1536,7 @@ static void context_closure_recurse_lookups (hb_closure_context_t *c,
covered_seq_indicies->add (seqIndex);
if (has_pos_glyphs) {
- c->push_cur_active_glyphs () = pos_glyphs;
+ c->push_cur_active_glyphs () = std::move (pos_glyphs);
} else {
c->push_cur_active_glyphs ().set (*c->glyphs);
}
@@ -1410,9 +1590,10 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (idx >= count)
continue;
- /* Don't recurse to ourself at same position.
- * Note that this test is too naive, it doesn't catch longer loops. */
- if (unlikely (idx == 0 && lookupRecord[i].lookupListIndex == c->lookup_index))
+ unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+
+ /* This can happen if earlier recursed lookups deleted many entries. */
+ if (unlikely (match_positions[idx] >= orig_len))
continue;
if (unlikely (!buffer->move_to (match_positions[idx])))
@@ -1421,10 +1602,28 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
if (unlikely (buffer->max_ops <= 0))
break;
- unsigned int orig_len = buffer->backtrack_len () + buffer->lookahead_len ();
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursing to lookup %u at %d",
+ (unsigned) lookupRecord[i].lookupListIndex,
+ buffer->idx);
+ }
+
if (!c->recurse (lookupRecord[i].lookupListIndex))
continue;
+ if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
+ {
+ if (buffer->have_output)
+ c->buffer->sync_so_far ();
+ c->buffer->message (c->font,
+ "recursed to lookup %u",
+ (unsigned) lookupRecord[i].lookupListIndex);
+ }
+
unsigned int new_len = buffer->backtrack_len () + buffer->lookahead_len ();
int delta = new_len - orig_len;
@@ -1447,25 +1646,27 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
* NOT the one after it.
*
* - If buffer length was decreased by n, it does not necessarily
- * mean that n match positions where removed, as there might
- * have been marks and default-ignorables in the sequence. We
- * should instead drop match positions between current-position
- * and current-position + n instead. Though, am not sure which
- * one is better. Both cases have valid uses. Sigh.
+ * mean that n match positions where removed, as there recursed-to
+ * lookup might had a different LookupFlag. Here's a constructed
+ * case of that:
+ * https://github.com/harfbuzz/harfbuzz/discussions/3538
*
* It should be possible to construct tests for both of these cases.
*/
end += delta;
- if (end <= int (match_positions[idx]))
+ if (end < int (match_positions[idx]))
{
/* End might end up being smaller than match_positions[idx] if the recursed
- * lookup ended up removing many items, more than we have had matched.
- * Just never rewind end back and get out of here.
- * https://bugs.chromium.org/p/chromium/issues/detail?id=659496 */
+ * lookup ended up removing many items.
+ * Just never rewind end beyond start of current position, since that is
+ * not possible in the recursed lookup. Also adjust delta as such.
+ *
+ * https://bugs.chromium.org/p/chromium/issues/detail?id=659496
+ * https://github.com/harfbuzz/harfbuzz/issues/1611
+ */
+ delta += match_positions[idx] - end;
end = match_positions[idx];
- /* There can't be any further changes. */
- break;
}
unsigned int next = idx + 1; /* next now is the position after the recursed lookup. */
@@ -1477,7 +1678,7 @@ static inline void apply_lookup (hb_ot_apply_context_t *c,
}
else
{
- /* NOTE: delta is negative. */
+ /* NOTE: delta is non-positive. */
delta = hb_max (delta, (int) next - (int) count);
next -= delta;
}
@@ -1523,9 +1724,10 @@ struct ContextApplyLookupContext
const void *match_data;
};
+template <typename HBUINT>
static inline bool context_intersects (const hb_set_t *glyphs,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
ContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
@@ -1533,9 +1735,10 @@ static inline bool context_intersects (const hb_set_t *glyphs,
lookup_context.funcs.intersects, lookup_context.intersects_data);
}
+template <typename HBUINT>
static inline void context_closure_lookup (hb_closure_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value, /* Index of first glyph in Coverage or Class value in ClassDef table */
@@ -1553,9 +1756,10 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
lookup_context.funcs.intersected_glyphs);
}
+template <typename HBUINT>
static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ContextCollectGlyphsLookupContext &lookup_context)
@@ -1567,9 +1771,10 @@ static inline void context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
ContextApplyLookupContext &lookup_context)
@@ -1578,9 +1783,11 @@ static inline bool context_would_apply_lookup (hb_would_apply_context_t *c,
inputCount, input,
lookup_context.funcs.match, lookup_context.match_data);
}
+
+template <typename HBUINT>
static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ContextApplyLookupContext &lookup_context)
@@ -1606,6 +1813,7 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
}
}
+template <typename Types>
struct Rule
{
bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
@@ -1619,8 +1827,8 @@ struct Rule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
context_closure_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1633,16 +1841,16 @@ struct Rule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
recurse_lookups (c, lookupCount, lookupRecord.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ContextCollectGlyphsLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
context_collect_glyphs_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1652,8 +1860,8 @@ struct Rule
bool would_apply (hb_would_apply_context_t *c,
ContextApplyLookupContext &lookup_context) const
{
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return context_would_apply_lookup (c,
inputCount, inputZ.arrayZ,
lookupCount, lookupRecord.arrayZ,
@@ -1664,8 +1872,8 @@ struct Rule
ContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array (inputCount ? inputCount - 1 : 0));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array (inputCount ? inputCount - 1 : 0));
return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
}
@@ -1678,7 +1886,7 @@ struct Rule
if (unlikely (!c->extend_min (out))) return_trace (false);
out->inputCount = inputCount;
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
for (const auto org : input)
{
HBUINT16 d;
@@ -1686,8 +1894,8 @@ struct Rule
c->copy (d);
}
- const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
- (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+ const auto &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+ (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (lookupCount), lookup_map);
return_trace (c->check_assign (out->lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
@@ -1699,7 +1907,7 @@ struct Rule
{
TRACE_SUBSET (this);
if (unlikely (!inputCount)) return_trace (false);
- const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+ const auto input = inputZ.as_array (inputCount - 1);
const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
if (!hb_all (input, mapping)) return_trace (false);
@@ -1722,7 +1930,7 @@ struct Rule
* glyph sequence--includes the first
* glyph */
HBUINT16 lookupCount; /* Number of LookupRecords */
- UnsizedArrayOf<HBUINT16>
+ UnsizedArrayOf<typename Types::HBUINT>
inputZ; /* Array of match inputs--start with
* second glyph */
/*UnsizedArrayOf<LookupRecord>
@@ -1732,8 +1940,11 @@ struct Rule
DEFINE_SIZE_ARRAY (4, inputZ);
};
+template <typename Types>
struct RuleSet
{
+ using Rule = OT::Rule<Types>;
+
bool intersects (const hb_set_t *glyphs,
ContextClosureLookupContext &lookup_context) const
{
@@ -1846,8 +2057,11 @@ struct RuleSet
};
-struct ContextFormat1
+template <typename Types>
+struct ContextFormat1_4
{
+ using RuleSet = OT::RuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ContextClosureLookupContext lookup_context = {
@@ -1871,9 +2085,8 @@ struct ContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
- cur_active_glyphs);
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (), cur_active_glyphs);
struct ContextClosureLookupContext lookup_context = {
{intersects_glyph, intersected_glyph},
@@ -1984,19 +2197,22 @@ struct ContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ContextFormat2
+template <typename Types>
+struct ContextFormat2_5
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -2011,7 +2227,7 @@ struct ContextFormat2
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -2037,8 +2253,8 @@ struct ContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
const ClassDef &class_def = this+classDef;
@@ -2053,7 +2269,7 @@ struct ContextFormat2
| hb_filter ([&] (unsigned _)
{ return class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<RuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<RuleSet>&> _)
{
const RuleSet& rule_set = this+_.second;
rule_set.closure (c, _.first, lookup_context);
@@ -2118,19 +2334,54 @@ struct ContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+classDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
const ClassDef &class_def = this+classDef;
- index = class_def.get_class (c->buffer->cur().codepoint);
- const RuleSet &rule_set = this+ruleSet[index];
+
struct ContextApplyLookupContext lookup_context = {
- {match_class},
+ {cached ? match_class_cached : match_class},
&class_def
};
+
+ if (cached && c->buffer->cur().syllable() < 255)
+ index = c->buffer->cur().syllable ();
+ else
+ {
+ index = class_def.get_class (c->buffer->cur().codepoint);
+ if (cached && index < 255)
+ c->buffer->cur().syllable() = index;
+ }
+ const RuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -2148,7 +2399,7 @@ struct ContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+classDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -2194,22 +2445,24 @@ struct ContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
classDef; /* Offset to glyph ClassDef table--from
* beginning of table */
- Array16OfOffset16To<RuleSet>
+ Array16Of<typename Types::template OffsetTo<RuleSet>>
ruleSet; /* Array of RuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (8, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 2 * Types::size, ruleSet);
};
struct ContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverageZ[0]).intersects (glyphs))
@@ -2233,8 +2486,8 @@ struct ContextFormat3
if (!(this+coverageZ[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -2326,7 +2579,7 @@ struct ContextFormat3
if (!o->serialize_subset (c, offset, this)) return_trace (false);
}
- const UnsizedArrayOf<LookupRecord>& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
+ const auto& lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>> (coverageZ.as_array (glyphCount));
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
@@ -2373,16 +2626,24 @@ struct Context
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ContextFormat1 format1;
- ContextFormat2 format2;
- ContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ContextFormat1_4<SmallTypes> format1;
+ ContextFormat2_5<SmallTypes> format2;
+ ContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ContextFormat1_4<MediumTypes> format4;
+ ContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -2404,17 +2665,18 @@ struct ChainContextCollectGlyphsLookupContext
struct ChainContextApplyLookupContext
{
- ContextApplyFuncs funcs;
+ ChainContextApplyFuncs funcs;
const void *match_data[3];
};
+template <typename HBUINT>
static inline bool chain_context_intersects (const hb_set_t *glyphs,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
ChainContextClosureLookupContext &lookup_context)
{
return array_is_subset_of (glyphs,
@@ -2428,13 +2690,14 @@ static inline bool chain_context_intersects (const hb_set_t *glyphs,
lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
}
+template <typename HBUINT>
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
unsigned value,
@@ -2454,13 +2717,14 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
lookup_context.funcs.intersected_glyphs);
}
+template <typename HBUINT>
static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ChainContextCollectGlyphsLookupContext &lookup_context)
@@ -2478,13 +2742,14 @@ static inline void chain_context_collect_glyphs_lookup (hb_collect_glyphs_contex
lookupCount, lookupRecord);
}
+template <typename HBUINT>
static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[] HB_UNUSED,
+ const HBUINT backtrack[] HB_UNUSED,
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[] HB_UNUSED,
+ const HBUINT lookahead[] HB_UNUSED,
unsigned int lookupCount HB_UNUSED,
const LookupRecord lookupRecord[] HB_UNUSED,
ChainContextApplyLookupContext &lookup_context)
@@ -2492,16 +2757,17 @@ static inline bool chain_context_would_apply_lookup (hb_would_apply_context_t *c
return (c->zero_context ? !backtrackCount && !lookaheadCount : true)
&& would_match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1]);
+ lookup_context.funcs.match[1], lookup_context.match_data[1]);
}
+template <typename HBUINT>
static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned int backtrackCount,
- const HBUINT16 backtrack[],
+ const HBUINT backtrack[],
unsigned int inputCount, /* Including the first glyph (not matched) */
- const HBUINT16 input[], /* Array of input values--start with second glyph */
+ const HBUINT input[], /* Array of input values--start with second glyph */
unsigned int lookaheadCount,
- const HBUINT16 lookahead[],
+ const HBUINT lookahead[],
unsigned int lookupCount,
const LookupRecord lookupRecord[],
ChainContextApplyLookupContext &lookup_context)
@@ -2511,11 +2777,11 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned match_positions[HB_MAX_CONTEXT_LENGTH];
if (!(match_input (c,
inputCount, input,
- lookup_context.funcs.match, lookup_context.match_data[1],
+ lookup_context.funcs.match[1], lookup_context.match_data[1],
&match_end, match_positions) && (end_index = match_end)
&& match_lookahead (c,
lookaheadCount, lookahead,
- lookup_context.funcs.match, lookup_context.match_data[2],
+ lookup_context.funcs.match[2], lookup_context.match_data[2],
match_end, &end_index)))
{
c->buffer->unsafe_to_concat (c->buffer->idx, end_index);
@@ -2525,7 +2791,7 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
unsigned start_index = c->buffer->out_len;
if (!match_backtrack (c,
backtrackCount, backtrack,
- lookup_context.funcs.match, lookup_context.match_data[0],
+ lookup_context.funcs.match[0], lookup_context.match_data[0],
&start_index))
{
c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
@@ -2540,12 +2806,13 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
return true;
}
+template <typename Types>
struct ChainRule
{
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
return chain_context_intersects (glyphs,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2558,9 +2825,9 @@ struct ChainRule
{
if (unlikely (c->lookup_limit_exceeded ())) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_closure_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2576,18 +2843,18 @@ struct ChainRule
if (unlikely (c->lookup_limit_exceeded ())) return;
if (!intersects (c->glyphs, lookup_context)) return;
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
void collect_glyphs (hb_collect_glyphs_context_t *c,
ChainContextCollectGlyphsLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
chain_context_collect_glyphs_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2599,9 +2866,9 @@ struct ChainRule
bool would_apply (hb_would_apply_context_t *c,
ChainContextApplyLookupContext &lookup_context) const
{
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return chain_context_would_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2612,9 +2879,9 @@ struct ChainRule
bool apply (hb_ot_apply_context_t *c, ChainContextApplyLookupContext &lookup_context) const
{
TRACE_APPLY (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (chain_context_apply_lookup (c,
backtrack.len, backtrack.arrayZ,
input.lenP1, input.arrayZ,
@@ -2647,22 +2914,22 @@ struct ChainRule
serialize_array (c, backtrack.len, + backtrack.iter ()
| hb_map (mapping));
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (input_map) mapping = input_map;
serialize_array (c, input.lenP1, + input.iter ()
| hb_map (mapping));
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (lookahead_map) mapping = lookahead_map;
serialize_array (c, lookahead.len, + lookahead.iter ()
| hb_map (mapping));
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
- HBUINT16* lookupCount = c->embed (&(lookupRecord.len));
+ HBUINT16* lookupCount = c->embed (&(lookup.len));
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c, lookup.as_array (), lookup_map);
return_trace (c->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -2674,8 +2941,8 @@ struct ChainRule
{
TRACE_SUBSET (this);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!backtrack_map)
{
@@ -2704,23 +2971,23 @@ struct ChainRule
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c)) return_trace (false);
- const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c)) return_trace (false);
- const Array16Of<HBUINT16> &lookahead = StructAfter<Array16Of<HBUINT16>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
protected:
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
backtrack; /* Array of backtracking values
* (to be matched before the input
* sequence) */
- HeadlessArrayOf<HBUINT16>
+ HeadlessArrayOf<typename Types::HBUINT>
inputX; /* Array of input values (start with
* second glyph) */
- Array16Of<HBUINT16>
+ Array16Of<typename Types::HBUINT>
lookaheadX; /* Array of lookahead values's (to be
* matched after the input sequence) */
Array16Of<LookupRecord>
@@ -2730,8 +2997,11 @@ struct ChainRule
DEFINE_SIZE_MIN (8);
};
+template <typename Types>
struct ChainRuleSet
{
+ using ChainRule = OT::ChainRule<Types>;
+
bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
{
return
@@ -2844,8 +3114,11 @@ struct ChainRuleSet
DEFINE_SIZE_ARRAY (2, rule);
};
-struct ChainContextFormat1
+template <typename Types>
+struct ChainContextFormat1_4
{
+ using ChainRuleSet = OT::ChainRuleSet<Types>;
+
bool intersects (const hb_set_t *glyphs) const
{
struct ChainContextClosureLookupContext lookup_context = {
@@ -2869,8 +3142,8 @@ struct ChainContextFormat1
void closure (hb_closure_context_t *c) const
{
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
struct ChainContextClosureLookupContext lookup_context = {
@@ -2927,7 +3200,7 @@ struct ChainContextFormat1
{
const ChainRuleSet &rule_set = this+ruleSet[(this+coverage).get_coverage (c->glyphs[0])];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return rule_set.would_apply (c, lookup_context);
@@ -2943,7 +3216,7 @@ struct ChainContextFormat1
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_glyph},
+ {{match_glyph, match_glyph, match_glyph}},
{nullptr, nullptr, nullptr}
};
return_trace (rule_set.apply (c, lookup_context));
@@ -2981,18 +3254,21 @@ struct ChainContextFormat1
protected:
HBUINT16 format; /* Format identifier--format = 1 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by Coverage Index */
public:
- DEFINE_SIZE_ARRAY (6, ruleSet);
+ DEFINE_SIZE_ARRAY (2 + 2 * Types::size, ruleSet);
};
-struct ChainContextFormat2
+template <typename Types>
+struct ChainContextFormat2_5
{
+ using ChainRuleSet = OT::ChainRuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
if (!(this+coverage).intersects (glyphs))
@@ -3011,7 +3287,7 @@ struct ChainContextFormat2
};
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphs, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphs, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
input_class_def.intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -3036,8 +3312,8 @@ struct ChainContextFormat2
if (!(this+coverage).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
@@ -3057,7 +3333,7 @@ struct ChainContextFormat2
| hb_filter ([&] (unsigned _)
{ return input_class_def.intersects_class (&c->parent_active_glyphs (), _); },
hb_first)
- | hb_apply ([&] (const hb_pair_t<unsigned, const Offset16To<ChainRuleSet>&> _)
+ | hb_apply ([&] (const hb_pair_t<unsigned, const typename Types::template OffsetTo<ChainRuleSet>&> _)
{
const ChainRuleSet& chainrule_set = this+_.second;
chainrule_set.closure (c, _.first, lookup_context);
@@ -3127,7 +3403,7 @@ struct ChainContextFormat2
unsigned int index = input_class_def.get_class (c->glyphs[0]);
const ChainRuleSet &rule_set = this+ruleSet[index];
struct ChainContextApplyLookupContext lookup_context = {
- {match_class},
+ {{match_class, match_class, match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
@@ -3137,7 +3413,33 @@ struct ChainContextFormat2
const Coverage &get_coverage () const { return this+coverage; }
- bool apply (hb_ot_apply_context_t *c) const
+ unsigned cache_cost () const
+ {
+ unsigned c = (this+lookaheadClassDef).cost () * ruleSet.len;
+ return c >= 4 ? c : 0;
+ }
+ bool cache_func (hb_ot_apply_context_t *c, bool enter) const
+ {
+ if (enter)
+ {
+ if (!HB_BUFFER_TRY_ALLOCATE_VAR (c->buffer, syllable))
+ return false;
+ auto &info = c->buffer->info;
+ unsigned count = c->buffer->len;
+ for (unsigned i = 0; i < count; i++)
+ info[i].syllable() = 255;
+ c->new_syllables = 255;
+ return true;
+ }
+ else
+ {
+ c->new_syllables = (unsigned) -1;
+ HB_BUFFER_DEALLOCATE_VAR (c->buffer, syllable);
+ return true;
+ }
+ }
+
+ bool apply (hb_ot_apply_context_t *c, bool cached = false) const
{
TRACE_APPLY (this);
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
@@ -3147,14 +3449,27 @@ struct ChainContextFormat2
const ClassDef &input_class_def = this+inputClassDef;
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
- index = input_class_def.get_class (c->buffer->cur().codepoint);
- const ChainRuleSet &rule_set = this+ruleSet[index];
+ /* For ChainContextFormat2_5 we cache the LookaheadClassDef instead of InputClassDef.
+ * The reason is that most heavy fonts want to identify a glyph in context and apply
+ * a lookup to it. In this scenario, the length of the input sequence is one, whereas
+ * the lookahead / backtrack are typically longer. The one glyph in input sequence is
+ * looked-up below and no input glyph is looked up in individual rules, whereas the
+ * lookahead and backtrack glyphs are tried. Since we match lookahead before backtrack,
+ * we should cache lookahead. This decisions showed a 20% improvement in shaping of
+ * the Gulzar font.
+ */
+
struct ChainContextApplyLookupContext lookup_context = {
- {match_class},
+ {{cached && &backtrack_class_def == &input_class_def ? match_class_cached : match_class,
+ cached && &input_class_def == &lookahead_class_def ? match_class_cached : match_class,
+ cached ? match_class_cached : match_class}},
{&backtrack_class_def,
&input_class_def,
&lookahead_class_def}
};
+
+ index = input_class_def.get_class (c->buffer->cur().codepoint);
+ const ChainRuleSet &rule_set = this+ruleSet[index];
return_trace (rule_set.apply (c, lookup_context));
}
@@ -3182,7 +3497,7 @@ struct ChainContextFormat2
const hb_set_t* glyphset = c->plan->glyphset_gsub ();
hb_set_t retained_coverage_glyphs;
- (this+coverage).intersected_coverage_glyphs (glyphset, &retained_coverage_glyphs);
+ (this+coverage).intersect_set (*glyphset, retained_coverage_glyphs);
hb_set_t coverage_glyph_classes;
(this+inputClassDef).intersected_classes (&retained_coverage_glyphs, &coverage_glyph_classes);
@@ -3237,38 +3552,40 @@ struct ChainContextFormat2
protected:
HBUINT16 format; /* Format identifier--format = 2 */
- Offset16To<Coverage>
+ typename Types::template OffsetTo<Coverage>
coverage; /* Offset to Coverage table--from
* beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
backtrackClassDef; /* Offset to glyph ClassDef table
* containing backtrack sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
inputClassDef; /* Offset to glyph ClassDef
* table containing input sequence
* data--from beginning of table */
- Offset16To<ClassDef>
+ typename Types::template OffsetTo<ClassDef>
lookaheadClassDef; /* Offset to glyph ClassDef table
* containing lookahead sequence
* data--from beginning of table */
- Array16OfOffset16To<ChainRuleSet>
+ Array16Of<typename Types::template OffsetTo<ChainRuleSet>>
ruleSet; /* Array of ChainRuleSet tables
* ordered by class */
public:
- DEFINE_SIZE_ARRAY (12, ruleSet);
+ DEFINE_SIZE_ARRAY (4 + 4 * Types::size, ruleSet);
};
struct ChainContextFormat3
{
+ using RuleSet = OT::RuleSet<SmallTypes>;
+
bool intersects (const hb_set_t *glyphs) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (glyphs))
return false;
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_coverage, intersected_coverage_glyphs},
ContextFormat::CoverageBasedContext,
@@ -3286,18 +3603,18 @@ struct ChainContextFormat3
void closure (hb_closure_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!(this+input[0]).intersects (c->glyphs))
return;
- hb_set_t* cur_active_glyphs = &c->push_cur_active_glyphs ();
- get_coverage ().intersected_coverage_glyphs (&c->previous_parent_active_glyphs (),
+ hb_set_t& cur_active_glyphs = c->push_cur_active_glyphs ();
+ get_coverage ().intersect_set (c->previous_parent_active_glyphs (),
cur_active_glyphs);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextClosureLookupContext lookup_context = {
{intersects_coverage, intersected_coverage_glyphs},
ContextFormat::CoverageBasedContext,
@@ -3318,9 +3635,9 @@ struct ChainContextFormat3
if (!intersects (c->glyphs))
return;
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
recurse_lookups (c, lookup.len, lookup.arrayZ);
}
@@ -3328,12 +3645,13 @@ struct ChainContextFormat3
void collect_glyphs (hb_collect_glyphs_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
(this+input[0]).collect_coverage (c->input);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
+
struct ChainContextCollectGlyphsLookupContext lookup_context = {
{collect_coverage},
{this, this, this}
@@ -3348,11 +3666,11 @@ struct ChainContextFormat3
bool would_apply (hb_would_apply_context_t *c) const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return chain_context_would_apply_lookup (c,
@@ -3364,22 +3682,22 @@ struct ChainContextFormat3
const Coverage &get_coverage () const
{
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
return this+input[0];
}
bool apply (hb_ot_apply_context_t *c) const
{
TRACE_APPLY (this);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
unsigned int index = (this+input[0]).get_coverage (c->buffer->cur().codepoint);
if (likely (index == NOT_COVERED)) return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
struct ChainContextApplyLookupContext lookup_context = {
- {match_coverage},
+ {{match_coverage, match_coverage, match_coverage}},
{this, this, this}
};
return_trace (chain_context_apply_lookup (c,
@@ -3419,21 +3737,21 @@ struct ChainContextFormat3
if (!serialize_coverage_offsets (c, backtrack.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!serialize_coverage_offsets (c, input.iter (), this))
return_trace (false);
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!serialize_coverage_offsets (c, lookahead.iter (), this))
return_trace (false);
- const Array16Of<LookupRecord> &lookupRecord = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
- HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookupRecord.len);
+ HBUINT16 *lookupCount = c->serializer->copy<HBUINT16> (lookup.len);
if (!lookupCount) return_trace (false);
- unsigned count = serialize_lookuprecord_array (c->serializer, lookupRecord.as_array (), lookup_map);
+ unsigned count = serialize_lookuprecord_array (c->serializer, lookup.as_array (), lookup_map);
return_trace (c->serializer->check_assign (*lookupCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
}
@@ -3441,12 +3759,12 @@ struct ChainContextFormat3
{
TRACE_SANITIZE (this);
if (!backtrack.sanitize (c, this)) return_trace (false);
- const Array16OfOffset16To<Coverage> &input = StructAfter<Array16OfOffset16To<Coverage>> (backtrack);
+ const auto &input = StructAfter<decltype (inputX)> (backtrack);
if (!input.sanitize (c, this)) return_trace (false);
if (!input.len) return_trace (false); /* To be consistent with Context. */
- const Array16OfOffset16To<Coverage> &lookahead = StructAfter<Array16OfOffset16To<Coverage>> (input);
+ const auto &lookahead = StructAfter<decltype (lookaheadX)> (input);
if (!lookahead.sanitize (c, this)) return_trace (false);
- const Array16Of<LookupRecord> &lookup = StructAfter<Array16Of<LookupRecord>> (lookahead);
+ const auto &lookup = StructAfter<decltype (lookupX)> (lookahead);
return_trace (lookup.sanitize (c));
}
@@ -3482,16 +3800,24 @@ struct ChainContext
case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+#ifndef HB_NO_BEYOND_64K
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ case 5: return_trace (c->dispatch (u.format5, std::forward<Ts> (ds)...));
+#endif
default:return_trace (c->default_return_value ());
}
}
protected:
union {
- HBUINT16 format; /* Format identifier */
- ChainContextFormat1 format1;
- ChainContextFormat2 format2;
- ChainContextFormat3 format3;
+ HBUINT16 format; /* Format identifier */
+ ChainContextFormat1_4<SmallTypes> format1;
+ ChainContextFormat2_5<SmallTypes> format2;
+ ChainContextFormat3 format3;
+#ifndef HB_NO_BEYOND_64K
+ ChainContextFormat1_4<MediumTypes> format4;
+ ChainContextFormat2_5<MediumTypes> format5;
+#endif
} u;
};
@@ -3616,60 +3942,273 @@ struct hb_ot_layout_lookup_accelerator_t
lookup.collect_coverage (&digest);
subtables.init ();
- OT::hb_get_subtables_context_t c_get_subtables (subtables);
- lookup.dispatch (&c_get_subtables);
+ OT::hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
+ lookup.dispatch (&c_accelerate_subtables);
+
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ cache_user_idx = c_accelerate_subtables.cache_user_idx;
+ for (unsigned i = 0; i < subtables.length; i++)
+ if (i != cache_user_idx)
+ subtables[i].apply_cached_func = subtables[i].apply_func;
+#endif
}
void fini () { subtables.fini (); }
bool may_have (hb_codepoint_t g) const
{ return digest.may_have (g); }
- bool apply (hb_ot_apply_context_t *c) const
+ bool apply (hb_ot_apply_context_t *c, bool use_cache) const
{
- for (unsigned int i = 0; i < subtables.length; i++)
- if (subtables[i].apply (c))
- return true;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ if (use_cache)
+ {
+ for (unsigned int i = 0; i < subtables.length; i++)
+ if (subtables[i].apply_cached (c))
+ return true;
+ }
+ else
+#endif
+ {
+ for (unsigned int i = 0; i < subtables.length; i++)
+ if (subtables[i].apply (c))
+ return true;
+ }
+ return false;
+ }
+
+ bool cache_enter (OT::hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ return cache_user_idx != (unsigned) -1 &&
+ subtables[cache_user_idx].cache_enter (c);
+#else
return false;
+#endif
+ }
+ void cache_leave (OT::hb_ot_apply_context_t *c) const
+ {
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ subtables[cache_user_idx].cache_leave (c);
+#endif
}
+
private:
hb_set_digest_t digest;
- hb_get_subtables_context_t::array_t subtables;
+ hb_accelerate_subtables_context_t::array_t subtables;
+#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
+ unsigned cache_user_idx = (unsigned) -1;
+#endif
+};
+
+template <typename Types>
+struct GSUBGPOSVersion1_2
+{
+ friend struct GSUBGPOS;
+
+ protected:
+ FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
+ * to 0x00010000u */
+ typename Types:: template OffsetTo<ScriptList>
+ scriptList; /* ScriptList table */
+ typename Types::template OffsetTo<FeatureList>
+ featureList; /* FeatureList table */
+ typename Types::template OffsetTo<LookupList<Types>>
+ lookupList; /* LookupList table */
+ Offset32To<FeatureVariations>
+ featureVars; /* Offset to Feature Variations
+ table--from beginning of table
+ * (may be NULL). Introduced
+ * in version 0x00010001. */
+ public:
+ DEFINE_SIZE_MIN (4 + 3 * Types::size);
+
+ unsigned int get_size () const
+ {
+ return min_size +
+ (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
+ }
+
+ const typename Types::template OffsetTo<LookupList<Types>>* get_lookup_list_offset () const
+ {
+ return &lookupList;
+ }
+
+ template <typename TLookup>
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ typedef List16OfOffsetTo<TLookup, typename Types::HBUINT> TLookupList;
+ if (unlikely (!(scriptList.sanitize (c, this) &&
+ featureList.sanitize (c, this) &&
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList).sanitize (c, this))))
+ return_trace (false);
+
+#ifndef HB_NO_VAR
+ if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
+ return_trace (false);
+#endif
+
+ return_trace (true);
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->subset_context->serializer->embed (*this);
+ if (unlikely (!out)) return_trace (false);
+
+ typedef LookupOffsetList<TLookup, typename Types::HBUINT> TLookupList;
+ reinterpret_cast<typename Types::template OffsetTo<TLookupList> &> (out->lookupList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<TLookupList> &> (lookupList),
+ this,
+ c);
+
+ reinterpret_cast<typename Types::template OffsetTo<RecordListOfFeature> &> (out->featureList)
+ .serialize_subset (c->subset_context,
+ reinterpret_cast<const typename Types::template OffsetTo<RecordListOfFeature> &> (featureList),
+ this,
+ c);
+
+ out->scriptList.serialize_subset (c->subset_context,
+ scriptList,
+ this,
+ c);
+
+#ifndef HB_NO_VAR
+ if (version.to_int () >= 0x00010001u)
+ {
+ bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
+ if (!ret && version.major == 1)
+ {
+ out->version.major = 1;
+ out->version.minor = 0;
+ }
+ }
+#endif
+
+ return_trace (true);
+ }
};
struct GSUBGPOS
{
- bool has_data () const { return version.to_int (); }
+ unsigned int get_size () const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.get_size ();
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.get_size ();
+#endif
+ default: return u.version.static_size;
+ }
+ }
+
+ template <typename TLookup>
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (unlikely (!u.version.sanitize (c))) return_trace (false);
+ switch (u.version.major) {
+ case 1: return_trace (u.version1.sanitize<TLookup> (c));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return_trace (u.version2.sanitize<TLookup> (c));
+#endif
+ default: return_trace (true);
+ }
+ }
+
+ template <typename TLookup>
+ bool subset (hb_subset_layout_context_t *c) const
+ {
+ switch (u.version.major) {
+ case 1: return u.version1.subset<TLookup> (c);
+#ifndef HB_NO_BEYOND_64K
+ case 2: return u.version2.subset<TLookup> (c);
+#endif
+ default: return false;
+ }
+ }
+
+ const ScriptList &get_script_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.scriptList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.scriptList;
+#endif
+ default: return Null (ScriptList);
+ }
+ }
+ const FeatureList &get_feature_list () const
+ {
+ switch (u.version.major) {
+ case 1: return this+u.version1.featureList;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureList;
+#endif
+ default: return Null (FeatureList);
+ }
+ }
+ unsigned int get_lookup_count () const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList).len;
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList).len;
+#endif
+ default: return 0;
+ }
+ }
+ const Lookup& get_lookup (unsigned int i) const
+ {
+ switch (u.version.major) {
+ case 1: return (this+u.version1.lookupList)[i];
+#ifndef HB_NO_BEYOND_64K
+ case 2: return (this+u.version2.lookupList)[i];
+#endif
+ default: return Null (Lookup);
+ }
+ }
+ const FeatureVariations &get_feature_variations () const
+ {
+ switch (u.version.major) {
+ case 1: return (u.version.to_int () >= 0x00010001u ? this+u.version1.featureVars : Null (FeatureVariations));
+#ifndef HB_NO_BEYOND_64K
+ case 2: return this+u.version2.featureVars;
+#endif
+ default: return Null (FeatureVariations);
+ }
+ }
+
+ bool has_data () const { return u.version.to_int (); }
unsigned int get_script_count () const
- { return (this+scriptList).len; }
+ { return get_script_list ().len; }
const Tag& get_script_tag (unsigned int i) const
- { return (this+scriptList).get_tag (i); }
+ { return get_script_list ().get_tag (i); }
unsigned int get_script_tags (unsigned int start_offset,
unsigned int *script_count /* IN/OUT */,
hb_tag_t *script_tags /* OUT */) const
- { return (this+scriptList).get_tags (start_offset, script_count, script_tags); }
+ { return get_script_list ().get_tags (start_offset, script_count, script_tags); }
const Script& get_script (unsigned int i) const
- { return (this+scriptList)[i]; }
+ { return get_script_list ()[i]; }
bool find_script_index (hb_tag_t tag, unsigned int *index) const
- { return (this+scriptList).find_index (tag, index); }
+ { return get_script_list ().find_index (tag, index); }
unsigned int get_feature_count () const
- { return (this+featureList).len; }
+ { return get_feature_list ().len; }
hb_tag_t get_feature_tag (unsigned int i) const
- { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : (this+featureList).get_tag (i); }
+ { return i == Index::NOT_FOUND_INDEX ? HB_TAG_NONE : get_feature_list ().get_tag (i); }
unsigned int get_feature_tags (unsigned int start_offset,
unsigned int *feature_count /* IN/OUT */,
hb_tag_t *feature_tags /* OUT */) const
- { return (this+featureList).get_tags (start_offset, feature_count, feature_tags); }
+ { return get_feature_list ().get_tags (start_offset, feature_count, feature_tags); }
const Feature& get_feature (unsigned int i) const
- { return (this+featureList)[i]; }
+ { return get_feature_list ()[i]; }
bool find_feature_index (hb_tag_t tag, unsigned int *index) const
- { return (this+featureList).find_index (tag, index); }
-
- unsigned int get_lookup_count () const
- { return (this+lookupList).len; }
- const Lookup& get_lookup (unsigned int i) const
- { return (this+lookupList)[i]; }
+ { return get_feature_list ().find_index (tag, index); }
bool find_variations_index (const int *coords, unsigned int num_coords,
unsigned int *index) const
@@ -3678,18 +4217,17 @@ struct GSUBGPOS
*index = FeatureVariations::NOT_FOUND_INDEX;
return false;
#endif
- return (version.to_int () >= 0x00010001u ? this+featureVars : Null (FeatureVariations))
- .find_index (coords, num_coords, index);
+ return get_feature_variations ().find_index (coords, num_coords, index);
}
const Feature& get_feature_variation (unsigned int feature_index,
unsigned int variations_index) const
{
#ifndef HB_NO_VAR
if (FeatureVariations::NOT_FOUND_INDEX != variations_index &&
- version.to_int () >= 0x00010001u)
+ u.version.to_int () >= 0x00010001u)
{
- const Feature *feature = (this+featureVars).find_substitute (variations_index,
- feature_index);
+ const Feature *feature = get_feature_variations ().find_substitute (variations_index,
+ feature_index);
if (feature)
return *feature;
}
@@ -3701,8 +4239,7 @@ struct GSUBGPOS
hb_set_t *lookup_indexes /* OUT */) const
{
#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).collect_lookups (feature_indexes, lookup_indexes);
+ get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
#endif
}
@@ -3714,6 +4251,8 @@ struct GSUBGPOS
hb_set_t visited_lookups, inactive_lookups;
OT::hb_closure_lookups_context_t c (face, glyphs, &visited_lookups, &inactive_lookups);
+ c.set_recurse_func (TLookup::template dispatch_recurse_func<hb_closure_lookups_context_t>);
+
for (unsigned lookup_index : + hb_iter (lookup_indexes))
reinterpret_cast<const TLookup &> (get_lookup (lookup_index)).closure_lookups (&c, lookup_index);
@@ -3722,7 +4261,7 @@ struct GSUBGPOS
}
void prune_langsys (const hb_map_t *duplicate_feature_map,
- hb_hashmap_t<unsigned, hb_set_t *> *script_langsys_map,
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map,
hb_set_t *new_feature_indexes /* OUT */) const
{
hb_prune_langsys_context_t c (this, script_langsys_map, duplicate_feature_map, new_feature_indexes);
@@ -3735,118 +4274,6 @@ struct GSUBGPOS
}
}
- template <typename TLookup>
- bool subset (hb_subset_layout_context_t *c) const
- {
- TRACE_SUBSET (this);
- auto *out = c->subset_context->serializer->embed (*this);
- if (unlikely (!out)) return_trace (false);
-
- typedef LookupOffsetList<TLookup> TLookupList;
- reinterpret_cast<Offset16To<TLookupList> &> (out->lookupList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList),
- this,
- c);
-
- reinterpret_cast<Offset16To<RecordListOfFeature> &> (out->featureList)
- .serialize_subset (c->subset_context,
- reinterpret_cast<const Offset16To<RecordListOfFeature> &> (featureList),
- this,
- c);
-
- out->scriptList.serialize_subset (c->subset_context,
- scriptList,
- this,
- c);
-
-#ifndef HB_NO_VAR
- if (version.to_int () >= 0x00010001u)
- {
- bool ret = out->featureVars.serialize_subset (c->subset_context, featureVars, this, c);
- if (!ret)
- {
- out->version.major = 1;
- out->version.minor = 0;
- }
- }
-#endif
-
- return_trace (true);
- }
-
- void find_duplicate_features (const hb_map_t *lookup_indices,
- const hb_set_t *feature_indices,
- hb_map_t *duplicate_feature_map /* OUT */) const
- {
- if (feature_indices->is_empty ()) return;
- hb_hashmap_t<hb_tag_t, hb_set_t *> unique_features;
- //find out duplicate features after subset
- for (unsigned i : feature_indices->iter ())
- {
- hb_tag_t t = get_feature_tag (i);
- if (t == HB_MAP_VALUE_INVALID) continue;
- if (!unique_features.has (t))
- {
- hb_set_t* indices = hb_set_create ();
- if (unlikely (indices == hb_set_get_empty () ||
- !unique_features.set (t, indices)))
- {
- hb_set_destroy (indices);
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
- return;
- }
- if (unique_features.get (t))
- unique_features.get (t)->add (i);
- duplicate_feature_map->set (i, i);
- continue;
- }
-
- bool found = false;
-
- hb_set_t* same_tag_features = unique_features.get (t);
- for (unsigned other_f_index : same_tag_features->iter ())
- {
- const Feature& f = get_feature (i);
- const Feature& other_f = get_feature (other_f_index);
-
- auto f_iter =
- + hb_iter (f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- auto other_f_iter =
- + hb_iter (other_f.lookupIndex)
- | hb_filter (lookup_indices)
- ;
-
- bool is_equal = true;
- for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
- {
- unsigned a = *f_iter;
- unsigned b = *other_f_iter;
- if (a != b) { is_equal = false; break; }
- }
-
- if (is_equal == false || f_iter || other_f_iter) continue;
-
- found = true;
- duplicate_feature_map->set (i, other_f_index);
- break;
- }
-
- if (found == false)
- {
- same_tag_features->add (i);
- duplicate_feature_map->set (i, i);
- }
- }
-
- for (auto _ : unique_features.iter ())
- hb_set_destroy (_.second);
- }
-
void prune_features (const hb_map_t *lookup_indices, /* IN */
hb_set_t *feature_indices /* IN/OUT */) const
{
@@ -3855,8 +4282,7 @@ struct GSUBGPOS
// if the FeatureVariation's table and the alternate version(s) intersect the
// set of lookup indices.
hb_set_t alternate_feature_indices;
- if (version.to_int () >= 0x00010001u)
- (this+featureVars).closure_features (lookup_indices, &alternate_feature_indices);
+ get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
if (unlikely (alternate_feature_indices.in_error()))
{
feature_indices->err ();
@@ -3889,32 +4315,6 @@ struct GSUBGPOS
}
}
- unsigned int get_size () const
- {
- return min_size +
- (version.to_int () >= 0x00010001u ? featureVars.static_size : 0);
- }
-
- template <typename TLookup>
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- typedef List16OfOffset16To<TLookup> TLookupList;
- if (unlikely (!(version.sanitize (c) &&
- likely (version.major == 1) &&
- scriptList.sanitize (c, this) &&
- featureList.sanitize (c, this) &&
- reinterpret_cast<const Offset16To<TLookupList> &> (lookupList).sanitize (c, this))))
- return_trace (false);
-
-#ifndef HB_NO_VAR
- if (unlikely (!(version.to_int () < 0x00010001u || featureVars.sanitize (c, this))))
- return_trace (false);
-#endif
-
- return_trace (true);
- }
-
template <typename T>
struct accelerator_t
{
@@ -3954,21 +4354,15 @@ struct GSUBGPOS
};
protected:
- FixedVersion<>version; /* Version of the GSUB/GPOS table--initially set
- * to 0x00010000u */
- Offset16To<ScriptList>
- scriptList; /* ScriptList table */
- Offset16To<FeatureList>
- featureList; /* FeatureList table */
- Offset16To<LookupList>
- lookupList; /* LookupList table */
- Offset32To<FeatureVariations>
- featureVars; /* Offset to Feature Variations
- table--from beginning of table
- * (may be NULL). Introduced
- * in version 0x00010001. */
+ union {
+ FixedVersion<> version; /* Version identifier */
+ GSUBGPOSVersion1_2<SmallTypes> version1;
+#ifndef HB_NO_BEYOND_64K
+ GSUBGPOSVersion1_2<MediumTypes> version2;
+#endif
+ } u;
public:
- DEFINE_SIZE_MIN (10);
+ DEFINE_SIZE_MIN (4);
};
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.cc b/thirdparty/harfbuzz/src/hb-ot-layout.cc
index a599eea6e9..f9c0daa486 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.cc
@@ -46,7 +46,7 @@
#include "hb-ot-layout-gdef-table.hh"
#include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh"
-#include "hb-ot-layout-base-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-ot-layout-base-table.hh"
#include "hb-ot-layout-jstf-table.hh" // Just so we compile it; unused otherwise.
#include "hb-ot-name-table.hh"
#include "hb-ot-os2-table.hh"
@@ -54,6 +54,9 @@
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-opbd-table.hh" // Just so we compile it; unused otherwise.
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
+
/**
* SECTION:hb-ot-layout
* @title: hb-ot-layout
@@ -76,7 +79,7 @@
* Tests whether a face includes any kerning data in the 'kern' table.
* Does NOT test for kerning lookups in the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -92,7 +95,7 @@ hb_ot_layout_has_kerning (hb_face_t *face)
* Tests whether a face includes any state-machine kerning in the 'kern' table.
* Does NOT examine the GPOS table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
bool
@@ -112,7 +115,7 @@ hb_ot_layout_has_machine_kerning (hb_face_t *face)
*
* Does NOT examine the GPOS table.
*
- * Return value: %true is data found, %false otherwise
+ * Return value: `true` is data found, `false` otherwise
*
**/
bool
@@ -258,7 +261,6 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
{
_hb_glyph_info_set_glyph_props (&buffer->info[i], gdef.get_glyph_props (buffer->info[i].codepoint));
_hb_glyph_info_clear_lig_props (&buffer->info[i]);
- buffer->info[i].syllable() = 0;
}
}
@@ -270,7 +272,7 @@ _hb_ot_layout_set_glyph_props (hb_font_t *font,
*
* Tests whether a face has any glyph classes defined in its GDEF table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -361,6 +363,13 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
* Fetches a list of the caret positions defined for a ligature glyph in the GDEF
* table of the font. The list returned will begin at the offset provided.
*
+ * Note that a ligature that is formed from n characters will have n-1
+ * caret positions. The first character is not represented in the array,
+ * since its caret position is the glyph position.
+ *
+ * The positions returned by this function are 'unshaped', and will have to
+ * be fixed up for kerning that may be applied to the ligature glyph.
+ *
* Return value: Total number of ligature caret positions for @glyph.
*
**/
@@ -382,7 +391,7 @@ hb_ot_layout_get_ligature_carets (hb_font_t *font,
*/
bool
-OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -392,7 +401,7 @@ OT::GSUB::is_blocklisted (hb_blob_t *blob HB_UNUSED,
}
bool
-OT::GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
+GPOS::is_blocklisted (hb_blob_t *blob HB_UNUSED,
hb_face_t *face HB_UNUSED) const
{
#ifdef HB_NO_OT_LAYOUT_BLOCKLIST
@@ -452,7 +461,7 @@ hb_ot_layout_table_get_script_tags (hb_face_t *face,
* Fetches the index if a given script tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the script is found, %false otherwise
+ * Return value: `true` if the script is found, `false` otherwise
*
**/
hb_bool_t
@@ -526,7 +535,7 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
* #HB_OT_LAYOUT_NO_SCRIPT_INDEX.
*
* Return value:
- * %true if one of the requested scripts is selected, %false if a fallback
+ * `true` if one of the requested scripts is selected, `false` if a fallback
* script is selected or if no scripts are selected.
*
* Since: 2.0.0
@@ -619,7 +628,7 @@ hb_ot_layout_table_get_feature_tags (hb_face_t *face,
* Fetches the index for a given feature tag in the specified face's GSUB table
* or GPOS table.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
**/
bool
hb_ot_layout_table_find_feature (hb_face_t *face,
@@ -686,7 +695,7 @@ hb_ot_layout_script_get_language_tags (hb_face_t *face,
* Fetches the index of a given language tag in the specified face's GSUB table
* or GPOS table, underneath the specified script tag.
*
- * Return value: %true if the language tag is found, %false otherwise
+ * Return value: `true` if the language tag is found, `false` otherwise
*
* Since: 0.6.0
* Deprecated: 2.0.0
@@ -721,10 +730,10 @@ hb_ot_layout_script_find_language (hb_face_t *face,
* in the specified face's GSUB or GPOS table, underneath the specified script
* index.
*
- * If none of the given language tags is found, %false is returned and
+ * If none of the given language tags is found, `false` is returned and
* @language_index is set to the default language index.
*
- * Return value: %true if one of the given language tags is found, %false otherwise
+ * Return value: `true` if one of the given language tags is found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -767,7 +776,7 @@ hb_ot_layout_script_select_language (hb_face_t *face,
* Fetches the index of a requested feature in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -798,7 +807,7 @@ hb_ot_layout_language_get_required_feature_index (hb_face_t *face,
* Fetches the tag of a requested feature index in the given face's GSUB or GPOS table,
* underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
* Since: 0.9.30
**/
@@ -908,7 +917,7 @@ hb_ot_layout_language_get_feature_tags (hb_face_t *face,
* Fetches the index of a given feature tag in the specified face's GSUB table
* or GPOS table, underneath the specified script and language.
*
- * Return value: %true if the feature is found, %false otherwise
+ * Return value: `true` if the feature is found, `false` otherwise
*
**/
hb_bool_t
@@ -999,7 +1008,7 @@ struct hb_collect_features_context_t
hb_collect_features_context_t (hb_face_t *face,
hb_tag_t table_tag,
hb_set_t *feature_indices_,
- const hb_tag_t *features)
+ const hb_tag_t *features)
: g (get_gsubgpos_table (face, table_tag)),
feature_indices (feature_indices_),
@@ -1026,7 +1035,7 @@ struct hb_collect_features_context_t
{
hb_tag_t tag = g.get_feature_tag (i);
if (features_set.has (tag))
- feature_indices_filter.add(i);
+ feature_indices_filter.add(i);
}
}
@@ -1305,7 +1314,7 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
* Fetches a list of feature variations in the specified face's GSUB table
* or GPOS table, at the specified variation coordinates.
*
- * Return value: %true if feature variations were found, %false otherwise.
+ * Return value: `true` if feature variations were found, `false` otherwise.
*
**/
hb_bool_t
@@ -1368,7 +1377,7 @@ hb_ot_layout_feature_with_variations_get_lookups (hb_face_t *face,
*
* Tests whether the specified face includes any GSUB substitutions.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
**/
hb_bool_t
@@ -1390,7 +1399,7 @@ hb_ot_layout_has_substitution (hb_face_t *face)
* Tests whether a specified lookup in the specified face would
* trigger a substitution on the given glyph sequence.
*
- * Return value: %true if a substitution would be triggered, %false otherwise
+ * Return value: `true` if a substitution would be triggered, `false` otherwise
*
* Since: 0.9.7
**/
@@ -1492,15 +1501,12 @@ hb_ot_layout_lookup_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
l.closure (&c, lookup_index);
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/**
@@ -1520,9 +1526,9 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs /* OUT */)
{
hb_map_t done_lookups_glyph_count;
- hb_hashmap_t<unsigned, hb_set_t *> done_lookups_glyph_set;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> done_lookups_glyph_set;
OT::hb_closure_context_t c (face, glyphs, &done_lookups_glyph_count, &done_lookups_glyph_set);
- const OT::GSUB& gsub = *face->table.GSUB->table;
+ const GSUB& gsub = *face->table.GSUB->table;
unsigned int iteration_count = 0;
unsigned int glyphs_length;
@@ -1542,13 +1548,10 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
}
} while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
glyphs_length != glyphs->get_population ());
-
- for (auto _ : done_lookups_glyph_set.iter ())
- hb_set_destroy (_.second);
}
/*
- * OT::GPOS
+ * GPOS
*/
@@ -1558,7 +1561,7 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
*
* Tests whether the specified face includes any GPOS positioning.
*
- * Return value: %true if the face has GPOS data, %false otherwise
+ * Return value: `true` if the face has GPOS data, `false` otherwise
*
**/
hb_bool_t
@@ -1579,7 +1582,7 @@ hb_ot_layout_has_positioning (hb_face_t *face)
void
hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_start (font, buffer);
+ GPOS::position_start (font, buffer);
}
@@ -1594,7 +1597,7 @@ hb_ot_layout_position_start (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_advances (font, buffer);
+ GPOS::position_finish_advances (font, buffer);
}
/**
@@ -1608,7 +1611,7 @@ hb_ot_layout_position_finish_advances (hb_font_t *font, hb_buffer_t *buffer)
void
hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
{
- OT::GPOS::position_finish_offsets (font, buffer);
+ GPOS::position_finish_offsets (font, buffer);
}
@@ -1631,7 +1634,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t *font, hb_buffer_t *buffer)
* For more information on this distinction, see the [`size` feature documentation](
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#tag-size).
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 0.9.10
**/
@@ -1643,7 +1646,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
unsigned int *range_start, /* OUT. May be NULL */
unsigned int *range_end /* OUT. May be NULL */)
{
- const OT::GPOS &gpos = *face->table.GPOS->table;
+ const GPOS &gpos = *face->table.GPOS->table;
const hb_tag_t tag = HB_TAG ('s','i','z','e');
unsigned int num_features = gpos.get_feature_count ();
@@ -1695,7 +1698,7 @@ hb_ot_layout_get_size_params (hb_face_t *face,
* Fetches name indices from feature parameters for "Stylistic Set" ('ssXX') or
* "Character Variant" ('cvXX') features.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.0.0
**/
@@ -1794,28 +1797,28 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
struct GSUBProxy
{
static constexpr unsigned table_index = 0u;
- static constexpr bool inplace = false;
+ static constexpr bool always_inplace = false;
typedef OT::SubstLookup Lookup;
GSUBProxy (hb_face_t *face) :
table (*face->table.GSUB->table),
accels (face->table.GSUB->accels) {}
- const OT::GSUB &table;
+ const GSUB &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
struct GPOSProxy
{
static constexpr unsigned table_index = 1u;
- static constexpr bool inplace = true;
+ static constexpr bool always_inplace = true;
typedef OT::PosLookup Lookup;
GPOSProxy (hb_face_t *face) :
table (*face->table.GPOS->table),
accels (face->table.GPOS->accels) {}
- const OT::GPOS &table;
+ const GPOS &table;
const OT::hb_ot_layout_lookup_accelerator_t *accels;
};
@@ -1824,6 +1827,8 @@ static inline bool
apply_forward (OT::hb_ot_apply_context_t *c,
const OT::hb_ot_layout_lookup_accelerator_t &accel)
{
+ bool use_cache = accel.cache_enter (c);
+
bool ret = false;
hb_buffer_t *buffer = c->buffer;
while (buffer->idx < buffer->len && buffer->successful)
@@ -1833,7 +1838,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
{
- applied = accel.apply (c);
+ applied = accel.apply (c, use_cache);
}
if (applied)
@@ -1841,6 +1846,10 @@ apply_forward (OT::hb_ot_apply_context_t *c,
else
(void) buffer->next_glyph ();
}
+
+ if (use_cache)
+ accel.cache_leave (c);
+
return ret;
}
@@ -1855,7 +1864,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
if (accel.may_have (buffer->cur().codepoint) &&
(buffer->cur().mask & c->lookup_mask) &&
c->check_glyph_property (&buffer->cur(), c->lookup_props))
- ret |= accel.apply (c);
+ ret |= accel.apply (c, false);
/* The reverse lookup doesn't "advance" cursor (for good reason). */
buffer->idx--;
@@ -1881,13 +1890,13 @@ apply_string (OT::hb_ot_apply_context_t *c,
if (likely (!lookup.is_reverse ()))
{
/* in/out forward substitution/positioning */
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->clear_output ();
buffer->idx = 0;
apply_forward (c, accel);
- if (!Proxy::inplace)
+ if (!Proxy::always_inplace)
buffer->sync ();
}
else
@@ -1908,7 +1917,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
const unsigned int table_index = proxy.table_index;
unsigned int i = 0;
OT::hb_ot_apply_context_t c (table_index, font, buffer);
- c.set_recurse_func (Proxy::Lookup::apply_recurse_func);
+ c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
for (unsigned int stage_index = 0; stage_index < stages[table_index].length; stage_index++)
{
@@ -1922,6 +1931,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
c.set_auto_zwj (lookups[table_index][i].auto_zwj);
c.set_auto_zwnj (lookups[table_index][i].auto_zwnj);
c.set_random (lookups[table_index][i].random);
+ c.set_per_syllable (lookups[table_index][i].per_syllable);
apply_string<Proxy> (&c,
proxy.table.get_lookup (lookup_index),
@@ -1960,17 +1970,88 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
#ifndef HB_NO_BASE
/**
+ * hb_ot_layout_get_horizontal_baseline_tag_for_script:
+ * @script: a script tag.
+ *
+ * Fetches the dominant horizontal baseline tag used by @script.
+ *
+ * Return value: dominant baseline tag for the @script.
+ *
+ * Since: 4.0.0
+ **/
+hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script)
+{
+ /* Keep in sync with hb_ot_layout_get_baseline_with_fallback */
+ switch ((int) script)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA:
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK:
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI:
+ case HB_SCRIPT_SIDDHAM:
+ case HB_SCRIPT_TIRHUTA:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN:
+ case HB_SCRIPT_NEWA:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO:
+ case HB_SCRIPT_ZANABAZAR_SQUARE:
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA:
+ case HB_SCRIPT_GUNJALA_GONDI:
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI:
+ return HB_OT_LAYOUT_BASELINE_TAG_HANGING;
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+ case HB_SCRIPT_HAN:
+ case HB_SCRIPT_HIRAGANA:
+ case HB_SCRIPT_KATAKANA:
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_BOPOMOFO:
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_TANGUT:
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_NUSHU:
+ /* Unicode-13.0 additions */
+ case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
+ return HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT;
+
+ default:
+ return HB_OT_LAYOUT_BASELINE_TAG_ROMAN;
+ }
+}
+
+/**
* hb_ot_layout_get_baseline:
* @font: a font
* @baseline_tag: a baseline tag
* @direction: text direction.
* @script_tag: script tag.
* @language_tag: language tag, currently unused.
- * @coord: (out): baseline value if found.
+ * @coord: (out) (nullable): baseline value if found.
*
* Fetches a baseline value from the face.
*
- * Return value: %true if found baseline value in the font.
+ * Return value: `true` if found baseline value in the font.
*
* Since: 2.6.0
**/
@@ -1982,13 +2063,231 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */)
{
- bool result = font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+ return font->face->table.BASE->get_baseline (font, baseline_tag, direction, script_tag, language_tag, coord);
+}
+
+/**
+ * hb_ot_layout_get_baseline_with_fallback:
+ * @font: a font
+ * @baseline_tag: a baseline tag
+ * @direction: text direction.
+ * @script_tag: script tag.
+ * @language_tag: language tag, currently unused.
+ * @coord: (out): baseline value if found.
+ *
+ * Fetches a baseline value from the face, and synthesizes
+ * it if the font does not have it.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */)
+{
+ if (hb_ot_layout_get_baseline (font,
+ baseline_tag,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ return;
- if (result && coord)
- *coord = HB_DIRECTION_IS_HORIZONTAL (direction) ? font->em_scale_y (*coord) : font->em_scale_x (*coord);
+ /* Synthesize missing baselines.
+ * See https://www.w3.org/TR/css-inline-3/#baseline-synthesis-fonts
+ */
+ switch (baseline_tag)
+ {
+ case HB_OT_LAYOUT_BASELINE_TAG_ROMAN:
+ *coord = 0; // FIXME origin ?
+ break;
- return result;
+ case HB_OT_LAYOUT_BASELINE_TAG_MATH:
+ {
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+ if (HB_DIRECTION_IS_HORIZONTAL (direction) &&
+ (hb_font_get_nominal_glyph (font, 0x2212u, &glyph) ||
+ hb_font_get_nominal_glyph (font, '-', &glyph)) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ {
+ *coord = extents.y_bearing + extents.height / 2;
+ }
+ else
+ {
+ hb_position_t x_height = font->y_scale / 2;
+#ifndef HB_NO_METRICS
+ hb_ot_metrics_get_position_with_fallback (font, HB_OT_METRICS_TAG_X_HEIGHT, &x_height);
+#endif
+ *coord = x_height / 2;
+ }
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT:
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT:
+ {
+ hb_position_t embox_top, embox_bottom;
+
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &embox_bottom);
+
+ if (baseline_tag == HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT)
+ *coord = embox_top + (embox_bottom - embox_top) / 10;
+ else
+ *coord = embox_bottom + (embox_top - embox_bottom) / 10;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord += HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.ascender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT:
+ if (hb_ot_layout_get_baseline (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ coord))
+ *coord -= HB_DIRECTION_IS_HORIZONTAL (direction) ? font->y_scale : font->x_scale;
+ else
+ {
+ hb_font_extents_t font_extents;
+ hb_font_get_extents_for_direction (font, direction, &font_extents);
+ *coord = font_extents.descender;
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_HANGING:
+ if (HB_DIRECTION_IS_HORIZONTAL (direction))
+ {
+ hb_codepoint_t ch;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ /* Keep in sync with hb_ot_layout_get_horizontal_baseline_for_script */
+ switch ((int) script_tag)
+ {
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI: ch = 0x0995u; break;
+ case HB_SCRIPT_DEVANAGARI: ch = 0x0915u; break;
+ case HB_SCRIPT_GUJARATI: ch = 0x0a95u; break;
+ case HB_SCRIPT_GURMUKHI: ch = 0x0a15u; break;
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN: ch = 0x0f40u; break;
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU: ch = 0x1901u; break;
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_SYLOTI_NAGRI: ch = 0xa807u; break;
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_PHAGS_PA: ch = 0xa840u; break;
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_MEETEI_MAYEK: ch = 0xabc0u; break;
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_SHARADA: ch = 0x11191u; break;
+ case HB_SCRIPT_TAKRI: ch = 0x1168cu; break;
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_MODI: ch = 0x1160eu;break;
+ case HB_SCRIPT_SIDDHAM: ch = 0x11590u; break;
+ case HB_SCRIPT_TIRHUTA: ch = 0x1148fu; break;
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_MARCHEN: ch = 0x11c72u; break;
+ case HB_SCRIPT_NEWA: ch = 0x1140eu; break;
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_SOYOMBO: ch = 0x11a5cu; break;
+ case HB_SCRIPT_ZANABAZAR_SQUARE: ch = 0x11a0bu; break;
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA: ch = 0x1180au; break;
+ case HB_SCRIPT_GUNJALA_GONDI: ch = 0x11d6cu; break;
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_NANDINAGARI: ch = 0x119b0u; break;
+ default: ch = 0; break;
+ }
+
+ if (ch &&
+ hb_font_get_nominal_glyph (font, ch, &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *coord = extents.y_bearing;
+ else
+ *coord = font->y_scale * 6 / 10; // FIXME makes assumptions about origin
+ }
+ else
+ *coord = font->x_scale * 6 / 10; // FIXME makes assumptions about origin
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL:
+ {
+ hb_position_t top, bottom;
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT,
+ direction,
+ script_tag,
+ language_tag,
+ &top);
+ hb_ot_layout_get_baseline_with_fallback (font,
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
+ direction,
+ script_tag,
+ language_tag,
+ &bottom);
+ *coord = (top + bottom) / 2;
+
+ }
+ break;
+
+ case _HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE:
+ default:
+ *coord = 0;
+ break;
+ }
}
+
#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.h b/thirdparty/harfbuzz/src/hb-ot-layout.h
index d47ba0fc92..4edddd9e0d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.h
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.h
@@ -332,31 +332,6 @@ hb_ot_layout_lookup_collect_glyphs (hb_face_t *face,
hb_set_t *glyphs_after, /* OUT. May be NULL */
hb_set_t *glyphs_output /* OUT. May be NULL */);
-#ifdef HB_NOT_IMPLEMENTED
-typedef struct
-{
- const hb_codepoint_t *before,
- unsigned int before_length,
- const hb_codepoint_t *input,
- unsigned int input_length,
- const hb_codepoint_t *after,
- unsigned int after_length,
-} hb_ot_layout_glyph_sequence_t;
-
-typedef hb_bool_t
-(*hb_ot_layout_glyph_sequence_func_t) (hb_font_t *font,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- void *user_data);
-
-HB_EXTERN void
-Xhb_ot_layout_lookup_enumerate_sequences (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int lookup_index,
- hb_ot_layout_glyph_sequence_func_t callback,
- void *user_data);
-#endif
/* Variations support */
@@ -411,19 +386,6 @@ hb_ot_layout_lookups_substitute_closure (hb_face_t *face,
hb_set_t *glyphs);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_substitute (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- unsigned int out_size,
- hb_codepoint_t *glyphs_out, /* OUT */
- unsigned int *clusters_out, /* OUT */
- unsigned int *out_length /* OUT */);
-#endif
-
-
/*
* GPOS
*/
@@ -431,15 +393,6 @@ Xhb_ot_layout_lookup_substitute (hb_font_t *font,
HB_EXTERN hb_bool_t
hb_ot_layout_has_positioning (hb_face_t *face);
-#ifdef HB_NOT_IMPLEMENTED
-/* Note: You better have GDEF when using this API, or marks won't do much. */
-HB_EXTERN hb_bool_t
-Xhb_ot_layout_lookup_position (hb_font_t *font,
- unsigned int lookup_index,
- const hb_ot_layout_glyph_sequence_t *sequence,
- hb_glyph_position_t *positions /* IN / OUT */);
-#endif
-
/* Optical 'size' feature info. Returns true if found.
* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
HB_EXTERN hb_bool_t
@@ -487,9 +440,11 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT: Ideographic character face top or right edge,
* if the direction is horizontal or vertical, respectively.
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL: The center of the ideographic character face. Since: 4.0.0
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT: Ideographic em-box bottom or left edge,
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT: Ideographic em-box top or right edge baseline,
+ * @HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL: The center of the ideographic em-box. Since: 4.0.0
* if the direction is horizontal or vertical, respectively.
* @HB_OT_LAYOUT_BASELINE_TAG_MATH: The baseline about which mathematical characters are centered.
* In vertical writing mode when mathematical characters rotated 90 degrees clockwise, are centered.
@@ -503,14 +458,19 @@ typedef enum {
HB_OT_LAYOUT_BASELINE_TAG_HANGING = HB_TAG ('h','a','n','g'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT = HB_TAG ('i','c','f','b'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_TOP_OR_RIGHT = HB_TAG ('i','c','f','t'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_CENTRAL = HB_TAG ('I','c','f','c'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_BOTTOM_OR_LEFT = HB_TAG ('i','d','e','o'),
HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_TOP_OR_RIGHT = HB_TAG ('i','d','t','p'),
+ HB_OT_LAYOUT_BASELINE_TAG_IDEO_EMBOX_CENTRAL = HB_TAG ('I','d','c','e'),
HB_OT_LAYOUT_BASELINE_TAG_MATH = HB_TAG ('m','a','t','h'),
/*< private >*/
_HB_OT_LAYOUT_BASELINE_TAG_MAX_VALUE = HB_TAG_MAX_SIGNED /*< skip >*/
} hb_ot_layout_baseline_tag_t;
+HB_EXTERN hb_ot_layout_baseline_tag_t
+hb_ot_layout_get_horizontal_baseline_tag_for_script (hb_script_t script);
+
HB_EXTERN hb_bool_t
hb_ot_layout_get_baseline (hb_font_t *font,
hb_ot_layout_baseline_tag_t baseline_tag,
@@ -519,6 +479,14 @@ hb_ot_layout_get_baseline (hb_font_t *font,
hb_tag_t language_tag,
hb_position_t *coord /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_layout_get_baseline_with_fallback (hb_font_t *font,
+ hb_ot_layout_baseline_tag_t baseline_tag,
+ hb_direction_t direction,
+ hb_tag_t script_tag,
+ hb_tag_t language_tag,
+ hb_position_t *coord /* OUT */);
+
HB_END_DECLS
#endif /* HB_OT_LAYOUT_H */
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout.hh b/thirdparty/harfbuzz/src/hb-ot-layout.hh
index ede8f007db..de06610cb5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout.hh
@@ -108,13 +108,17 @@ hb_ot_layout_delete_glyphs_inplace (hb_buffer_t *buffer,
namespace OT {
struct hb_ot_apply_context_t;
- struct SubstLookup;
struct hb_ot_layout_lookup_accelerator_t;
+namespace Layout {
+namespace GSUB_impl {
+ struct SubstLookup;
+}
+}
}
HB_INTERNAL void
hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
- const OT::SubstLookup &lookup,
+ const OT::Layout::GSUB_impl::SubstLookup &lookup,
const OT::hb_ot_layout_lookup_accelerator_t &accel);
@@ -168,17 +172,6 @@ _hb_next_syllable (hb_buffer_t *buffer, unsigned int start)
return start;
}
-static inline void
-_hb_clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- info[i].syllable() = 0;
-}
-
/* unicode_props */
@@ -485,6 +478,8 @@ static inline uint8_t
_hb_allocate_lig_id (hb_buffer_t *buffer)
{
uint8_t lig_id = buffer->next_serial () & 0x07;
+ if (unlikely (!lig_id))
+ lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
return lig_id;
}
@@ -594,13 +589,11 @@ _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
- HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
}
static inline void
_hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
{
- HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
}
@@ -610,7 +603,6 @@ _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
{
HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
HB_BUFFER_ASSERT_VAR (buffer, lig_props);
- HB_BUFFER_ASSERT_VAR (buffer, syllable);
}
/* Make sure no one directly touches our props... */
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.cc b/thirdparty/harfbuzz/src/hb-ot-map.cc
index 12ceea5785..39215b335f 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-map.cc
@@ -43,7 +43,7 @@ void hb_ot_map_t::collect_lookups (unsigned int table_index, hb_set_t *lookups_o
hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_)
+ const hb_segment_properties_t &props_)
{
memset (this, 0, sizeof (*this));
@@ -52,7 +52,7 @@ hb_ot_map_builder_t::hb_ot_map_builder_t (hb_face_t *face_,
stages[table_index].init ();
face = face_;
- props = *props_;
+ props = props_;
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip
* features not available in either table and not waste precious bits for them. */
@@ -109,6 +109,21 @@ void hb_ot_map_builder_t::add_feature (hb_tag_t tag,
info->stage[1] = current_stage[1];
}
+bool hb_ot_map_builder_t::has_feature (hb_tag_t tag)
+{
+ for (unsigned int table_index = 0; table_index < 2; table_index++)
+ {
+ if (hb_ot_layout_language_find_feature (face,
+ table_tags[table_index],
+ script_index[table_index],
+ language_index[table_index],
+ tag,
+ nullptr))
+ return true;
+ }
+ return false;
+}
+
void
hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
unsigned int table_index,
@@ -117,7 +132,8 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
hb_mask_t mask,
bool auto_zwnj,
bool auto_zwj,
- bool random)
+ bool random,
+ bool per_syllable)
{
unsigned int lookup_indices[32];
unsigned int offset, len;
@@ -145,6 +161,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m,
lookup->auto_zwnj = auto_zwnj;
lookup->auto_zwj = auto_zwj;
lookup->random = random;
+ lookup->per_syllable = per_syllable;
}
offset += len;
@@ -277,6 +294,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
map->auto_zwnj = !(info->flags & F_MANUAL_ZWNJ);
map->auto_zwj = !(info->flags & F_MANUAL_ZWJ);
map->random = !!(info->flags & F_RANDOM);
+ map->per_syllable = !!(info->flags & F_PER_SYLLABLE);
if ((info->flags & F_GLOBAL) && info->max_value == 1) {
/* Uses the global bit */
map->shift = global_bit_shift;
@@ -319,7 +337,8 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m,
m.features[i].mask,
m.features[i].auto_zwnj,
m.features[i].auto_zwj,
- m.features[i].random);
+ m.features[i].random,
+ m.features[i].per_syllable);
/* Sort lookups and merge duplicates */
if (last_num_lookups < m.lookups[table_index].length)
diff --git a/thirdparty/harfbuzz/src/hb-ot-map.hh b/thirdparty/harfbuzz/src/hb-ot-map.hh
index 5f2afae281..a7b5eec30d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-map.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-map.hh
@@ -56,6 +56,7 @@ struct hb_ot_map_t
unsigned int auto_zwnj : 1;
unsigned int auto_zwj : 1;
unsigned int random : 1;
+ unsigned int per_syllable : 1;
int cmp (const hb_tag_t tag_) const
{ return tag_ < tag ? -1 : tag_ > tag ? 1 : 0; }
@@ -66,6 +67,7 @@ struct hb_ot_map_t
unsigned short auto_zwnj : 1;
unsigned short auto_zwj : 1;
unsigned short random : 1;
+ unsigned short per_syllable : 1;
hb_mask_t mask;
HB_INTERNAL static int cmp (const void *pa, const void *pb)
@@ -137,19 +139,15 @@ struct hb_ot_map_t
return map ? map->stage[table_index] : UINT_MAX;
}
- void get_stage_lookups (unsigned int table_index, unsigned int stage,
- const struct lookup_map_t **plookups, unsigned int *lookup_count) const
+ hb_array_t<const hb_ot_map_t::lookup_map_t>
+ get_stage_lookups (unsigned int table_index, unsigned int stage) const
{
if (unlikely (stage > stages[table_index].length))
- {
- *plookups = nullptr;
- *lookup_count = 0;
- return;
- }
+ return hb_array<const hb_ot_map_t::lookup_map_t> (nullptr, 0);
+
unsigned int start = stage ? stages[table_index][stage - 1].last_lookup : 0;
unsigned int end = stage < stages[table_index].length ? stages[table_index][stage].last_lookup : lookups[table_index].length;
- *plookups = end == start ? nullptr : &lookups[table_index][start];
- *lookup_count = end - start;
+ return lookups[table_index].as_array ().sub_array (start, end - start);
}
HB_INTERNAL void collect_lookups (unsigned int table_index, hb_set_t *lookups) const;
@@ -165,7 +163,7 @@ struct hb_ot_map_t
private:
- hb_mask_t global_mask;
+ hb_mask_t global_mask = 0;
hb_sorted_vector_t<feature_map_t> features;
hb_vector_t<lookup_map_t> lookups[2]; /* GSUB/GPOS */
@@ -183,7 +181,8 @@ enum hb_ot_map_feature_flags_t
F_GLOBAL_MANUAL_JOINERS= F_GLOBAL | F_MANUAL_JOINERS,
F_GLOBAL_HAS_FALLBACK = F_GLOBAL | F_HAS_FALLBACK,
F_GLOBAL_SEARCH = 0x0010u, /* If feature not found in LangSys, look for it in global feature list and pick one. */
- F_RANDOM = 0x0020u /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_RANDOM = 0x0020u, /* Randomly select a glyph from an AlternateSubstFormat1 subtable. */
+ F_PER_SYLLABLE = 0x0040u /* Contain lookup application to within syllable. */
};
HB_MARK_AS_FLAG_T (hb_ot_map_feature_flags_t);
@@ -201,7 +200,7 @@ struct hb_ot_map_builder_t
public:
HB_INTERNAL hb_ot_map_builder_t (hb_face_t *face_,
- const hb_segment_properties_t *props_);
+ const hb_segment_properties_t &props_);
HB_INTERNAL ~hb_ot_map_builder_t ();
@@ -209,6 +208,8 @@ struct hb_ot_map_builder_t
hb_ot_map_feature_flags_t flags=F_NONE,
unsigned int value=1);
+ HB_INTERNAL bool has_feature (hb_tag_t tag);
+
void add_feature (const hb_ot_map_feature_t &feat)
{ add_feature (feat.tag, feat.flags); }
@@ -237,7 +238,8 @@ struct hb_ot_map_builder_t
hb_mask_t mask,
bool auto_zwnj = true,
bool auto_zwj = true,
- bool random = false);
+ bool random = false,
+ bool per_syllable = false);
struct feature_info_t {
hb_tag_t tag;
diff --git a/thirdparty/harfbuzz/src/hb-ot-math-table.hh b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
index 8d0b4317c3..d834d94371 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-math-table.hh
@@ -369,6 +369,37 @@ struct MathKern
return kernValue[i].get_x_value (font, this);
}
+ unsigned int get_entries (unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ const MathValueRecord* correctionHeight = mathValueRecordsZ.arrayZ;
+ const MathValueRecord* kernValue = mathValueRecordsZ.arrayZ + heightCount;
+ const unsigned int entriesCount = heightCount + 1;
+
+ if (entries_count)
+ {
+ unsigned int start = hb_min (start_offset, entriesCount);
+ unsigned int end = hb_min (start + *entries_count, entriesCount);
+ *entries_count = end - start;
+
+ for (unsigned int i = 0; i < *entries_count; i++) {
+ unsigned int j = start + i;
+
+ hb_position_t max_height;
+ if (j == heightCount) {
+ max_height = INT32_MAX;
+ } else {
+ max_height = correctionHeight[j].get_y_value (font, this);
+ }
+
+ kern_entries[i] = {max_height, kernValue[j].get_x_value (font, this)};
+ }
+ }
+ return entriesCount;
+ }
+
protected:
HBUINT16 heightCount;
UnsizedArrayOf<MathValueRecord>
@@ -423,6 +454,24 @@ struct MathKernInfoRecord
return (base+mathKern[idx]).get_value (correction_height, font);
}
+ unsigned int get_kernings (hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font,
+ const void *base) const
+ {
+ unsigned int idx = kern;
+ if (unlikely (idx >= ARRAY_LENGTH (mathKern)) || !mathKern[idx]) {
+ if (entries_count) *entries_count = 0;
+ return 0;
+ }
+ return (base+mathKern[idx]).get_entries (start_offset,
+ entries_count,
+ kern_entries,
+ font);
+ }
+
protected:
/* Offset to MathKern table for each corner -
* from the beginning of MathKernInfo table. May be NULL. */
@@ -473,6 +522,22 @@ struct MathKernInfo
return mathKernInfoRecords[index].get_kerning (kern, correction_height, font, this);
}
+ unsigned int get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ {
+ unsigned int index = (this+mathKernCoverage).get_coverage (glyph);
+ return mathKernInfoRecords[index].get_kernings (kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font,
+ this);
+ }
+
protected:
Offset16To<Coverage>
mathKernCoverage;
@@ -545,6 +610,19 @@ struct MathGlyphInfo
hb_font_t *font) const
{ return (this+mathKernInfo).get_kerning (glyph, kern, correction_height, font); }
+ hb_position_t get_kernings (hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries, /* OUT */
+ hb_font_t *font) const
+ { return (this+mathKernInfo).get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font); }
+
protected:
/* Offset to MathItalicsCorrectionInfo table -
* from the beginning of MathGlyphInfo table. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.cc b/thirdparty/harfbuzz/src/hb-ot-math.cc
index 5781d25f2a..c515867bdf 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-math.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face has a `MATH` table.
*
- * Return value: %true if the table is found, %false otherwise
+ * Return value: `true` if the table is found, `false` otherwise
*
* Since: 1.3.3
**/
@@ -142,7 +142,7 @@ hb_ot_math_get_glyph_top_accent_attachment (hb_font_t *font,
*
* Tests whether the given glyph index is an extended shape in the face.
*
- * Return value: %true if the glyph is an extended shape, %false otherwise
+ * Return value: `true` if the glyph is an extended shape, `false` otherwise
*
* Since: 1.3.3
**/
@@ -185,6 +185,51 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
}
/**
+ * hb_ot_math_get_glyph_kernings:
+ * @font: #hb_font_t to work upon
+ * @glyph: The glyph index from which to retrieve the kernings
+ * @kern: The #hb_ot_math_kern_t from which to retrieve the kernings
+ * @start_offset: offset of the first kern entry to retrieve
+ * @entries_count: (inout) (optional): Input = the maximum number of kern entries to return;
+ * Output = the actual number of kern entries returned
+ * @kern_entries: (out caller-allocates) (array length=entries_count): array of kern entries returned
+ *
+ * Fetches the raw MathKern (cut-in) data for the specified font, glyph index,
+ * and @kern. The corresponding list of kern values and correction heights is
+ * returned as a list of #hb_ot_math_kern_entry_t structs.
+ *
+ * See also #hb_ot_math_get_glyph_kerning, which handles selecting the
+ * appropriate kern value for a given correction height.
+ *
+ * <note>For a glyph with @n defined kern values (where @n > 0), there are only
+ * @n−1 defined correction heights, as each correction height defines a boundary
+ * past which the next kern value should be selected. Therefore, only the
+ * #hb_ot_math_kern_entry_t.kern_value of the uppermost #hb_ot_math_kern_entry_t
+ * actually comes from the font; its corresponding
+ * #hb_ot_math_kern_entry_t.max_correction_height is always set to
+ * <code>INT32_MAX</code>.</note>
+ *
+ * Return value: the total number of kern values available or zero
+ *
+ * Since: 3.4.0
+ **/
+unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */)
+{
+ return font->face->table.MATH->get_glyph_info().get_kernings (glyph,
+ kern,
+ start_offset,
+ entries_count,
+ kern_entries,
+ font);
+}
+
+/**
* hb_ot_math_get_glyph_variants:
* @font: #hb_font_t to work upon
* @glyph: The index of the glyph to stretch
diff --git a/thirdparty/harfbuzz/src/hb-ot-math.h b/thirdparty/harfbuzz/src/hb-ot-math.h
index d3ffa19d85..1378a0639a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-math.h
+++ b/thirdparty/harfbuzz/src/hb-ot-math.h
@@ -50,14 +50,18 @@ HB_BEGIN_DECLS
#define HB_OT_TAG_MATH HB_TAG('M','A','T','H')
/**
- * HB_OT_MATH_SCRIPT:
+ * HB_OT_TAG_MATH_SCRIPT:
*
- * OpenType script tag for math shaping, for use with
- * Use with hb_buffer_set_script().
+ * OpenType script tag, `math`, for features specific to math shaping.
*
- * Since: 1.3.3
+ * <note>#HB_OT_TAG_MATH_SCRIPT is not a valid #hb_script_t and should only be
+ * used with functions that accept raw OpenType script tags, such as
+ * #hb_ot_layout_collect_features. In other cases, #HB_SCRIPT_MATH should be
+ * used instead.</note>
+ *
+ * Since: 3.4.0
*/
-#define HB_OT_MATH_SCRIPT HB_TAG('m','a','t','h')
+#define HB_OT_TAG_MATH_SCRIPT HB_TAG('m','a','t','h')
/* Types */
@@ -205,6 +209,20 @@ typedef enum {
} hb_ot_math_kern_t;
/**
+ * hb_ot_math_kern_entry_t:
+ * @max_correction_height: The maximum height at which this entry should be used
+ * @kern_value: The kern value of the entry
+ *
+ * Data type to hold math kerning (cut-in) information for a glyph.
+ *
+ * Since: 3.4.0
+ */
+typedef struct {
+ hb_position_t max_correction_height;
+ hb_position_t kern_value;
+} hb_ot_math_kern_entry_t;
+
+/**
* hb_ot_math_glyph_variant_t:
* @glyph: The glyph index of the variant
* @advance: The advance width of the variant
@@ -281,6 +299,14 @@ hb_ot_math_get_glyph_kerning (hb_font_t *font,
hb_position_t correction_height);
HB_EXTERN unsigned int
+hb_ot_math_get_glyph_kernings (hb_font_t *font,
+ hb_codepoint_t glyph,
+ hb_ot_math_kern_t kern,
+ unsigned int start_offset,
+ unsigned int *entries_count, /* IN/OUT */
+ hb_ot_math_kern_entry_t *kern_entries /* OUT */);
+
+HB_EXTERN unsigned int
hb_ot_math_get_glyph_variants (hb_font_t *font,
hb_codepoint_t glyph,
hb_direction_t direction,
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.cc b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
index 103808cf91..5b12482b97 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.cc
@@ -71,12 +71,12 @@ _hb_ot_metrics_get_position_common (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_x (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
- face->table.TABLE->ATTR + GET_VAR, metrics_tag))), true))
+ ((void) (position && (*position = font->em_scalef_y (_fix_ascender_descender ( \
+ face->table.TABLE->ATTR + GET_VAR, metrics_tag)))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
return (face->table.OS2->use_typo_metrics () && GET_METRIC_Y (OS2, sTypoAscender)) ||
@@ -154,10 +154,10 @@ hb_ot_metrics_get_position (hb_font_t *font,
#endif
#define GET_METRIC_X(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_x (face->table.TABLE->ATTR + GET_VAR))), true))
#define GET_METRIC_Y(TABLE, ATTR) \
(face->table.TABLE->has_data () && \
- (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR)), true))
+ ((void) (position && (*position = font->em_scalef_y (face->table.TABLE->ATTR + GET_VAR))), true))
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT: return GET_METRIC_Y (OS2, usWinAscent);
case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT: return GET_METRIC_Y (OS2, usWinDescent);
@@ -238,6 +238,145 @@ hb_ot_metrics_get_position (hb_font_t *font,
}
}
+/**
+ * hb_ot_metrics_get_position_with_fallback:
+ * @font: an #hb_font_t object.
+ * @metrics_tag: tag of metrics value you like to fetch.
+ * @position: (out) (optional): result of metrics value from the font.
+ *
+ * Fetches metrics value corresponding to @metrics_tag from @font,
+ * and synthesizes a value if it the value is missing in the font.
+ *
+ * Since: 4.0.0
+ **/
+void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */)
+{
+ hb_font_extents_t font_extents;
+ hb_codepoint_t glyph;
+ hb_glyph_extents_t extents;
+
+ if (hb_ot_metrics_get_position (font, metrics_tag, position))
+ {
+ if ((metrics_tag != HB_OT_METRICS_TAG_STRIKEOUT_SIZE &&
+ metrics_tag != HB_OT_METRICS_TAG_UNDERLINE_SIZE) ||
+ *position != 0)
+ return;
+ }
+
+ switch (metrics_tag)
+ {
+ case HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_ASCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_ASCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER:
+ case HB_OT_METRICS_TAG_HORIZONTAL_CLIPPING_DESCENT:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.descender;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_DESCENDER:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.ascender;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_LTR, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_VERTICAL_LINE_GAP:
+ hb_font_get_extents_for_direction (font, HB_DIRECTION_TTB, &font_extents);
+ *position = font_extents.line_gap;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RISE:
+ *position = 1;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_RUN:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET:
+ case HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_X_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'x', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.y_bearing;
+ else
+ *position = font->y_scale / 2;
+ break;
+
+ case HB_OT_METRICS_TAG_CAP_HEIGHT:
+ if (hb_font_get_nominal_glyph (font, 'O', &glyph) &&
+ hb_font_get_glyph_extents (font, glyph, &extents))
+ *position = extents.height + 2 * extents.y_bearing;
+ else
+ *position = font->y_scale * 2 / 3;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_SIZE:
+ case HB_OT_METRICS_TAG_UNDERLINE_SIZE:
+ *position = font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_STRIKEOUT_OFFSET:
+ {
+ hb_position_t ascender;
+ hb_ot_metrics_get_position_with_fallback (font,
+ HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER,
+ &ascender);
+ *position = ascender / 2;
+ }
+ break;
+
+ case HB_OT_METRICS_TAG_UNDERLINE_OFFSET:
+ *position = - font->y_scale / 18;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_SIZE:
+ *position = font->x_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_SIZE:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_SIZE:
+ *position = font->y_scale * 10 / 12;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_X_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_X_OFFSET:
+ *position = 0;
+ break;
+
+ case HB_OT_METRICS_TAG_SUBSCRIPT_EM_Y_OFFSET:
+ case HB_OT_METRICS_TAG_SUPERSCRIPT_EM_Y_OFFSET:
+ *position = font->y_scale / 5;
+ break;
+
+ case _HB_OT_METRICS_TAG_MAX_VALUE:
+ default:
+ *position = 0;
+ break;
+ }
+}
+
#ifndef HB_NO_VAR
/**
* hb_ot_metrics_get_variation:
diff --git a/thirdparty/harfbuzz/src/hb-ot-metrics.h b/thirdparty/harfbuzz/src/hb-ot-metrics.h
index 5841fc8b0f..30de500088 100644
--- a/thirdparty/harfbuzz/src/hb-ot-metrics.h
+++ b/thirdparty/harfbuzz/src/hb-ot-metrics.h
@@ -110,6 +110,11 @@ hb_ot_metrics_get_position (hb_font_t *font,
hb_ot_metrics_tag_t metrics_tag,
hb_position_t *position /* OUT. May be NULL. */);
+HB_EXTERN void
+hb_ot_metrics_get_position_with_fallback (hb_font_t *font,
+ hb_ot_metrics_tag_t metrics_tag,
+ hb_position_t *position /* OUT */);
+
HB_EXTERN float
hb_ot_metrics_get_variation (hb_font_t *font, hb_ot_metrics_tag_t metrics_tag);
diff --git a/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh b/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
index c496dc2981..0e0f2d632a 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-name-language-static.hh
@@ -45,7 +45,7 @@ struct hb_ot_language_map_t
};
static const hb_ot_language_map_t
-hb_ms_language_map[] =
+_hb_ms_language_map[] =
{
{0x0001, "ar"}, /* ??? */
{0x0004, "zh"}, /* ??? */
@@ -298,7 +298,7 @@ hb_ms_language_map[] =
};
static const hb_ot_language_map_t
-hb_mac_language_map[] =
+_hb_mac_language_map[] =
{
{ 0, "en"}, /* English */
{ 1, "fr"}, /* French */
@@ -441,16 +441,16 @@ hb_language_t
_hb_ot_name_language_for_ms_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_ms_language_map,
- ARRAY_LENGTH (hb_ms_language_map));
+ _hb_ms_language_map,
+ ARRAY_LENGTH (_hb_ms_language_map));
}
hb_language_t
_hb_ot_name_language_for_mac_code (unsigned int code)
{
return _hb_ot_name_language_for (code,
- hb_mac_language_map,
- ARRAY_LENGTH (hb_mac_language_map));
+ _hb_mac_language_map,
+ ARRAY_LENGTH (_hb_mac_language_map));
}
#endif /* HB_OT_NAME_LANGUAGE_STATIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-name-table.hh b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
index d52367e9b1..1f2131ffcc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-name-table.hh
@@ -156,7 +156,7 @@ struct NameRecord
};
static int
-_hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
+_hb_ot_name_entry_cmp_key (const void *pa, const void *pb, bool exact)
{
const hb_ot_name_entry_t *a = (const hb_ot_name_entry_t *) pa;
const hb_ot_name_entry_t *b = (const hb_ot_name_entry_t *) pb;
@@ -169,8 +169,19 @@ _hb_ot_name_entry_cmp_key (const void *pa, const void *pb)
if (a->language == b->language) return 0;
if (!a->language) return -1;
if (!b->language) return +1;
- return strcmp (hb_language_to_string (a->language),
- hb_language_to_string (b->language));
+
+ const char *astr = hb_language_to_string (a->language);
+ const char *bstr = hb_language_to_string (b->language);
+
+ signed c = strcmp (astr, bstr);
+
+ // 'a' is the user request, and 'b' is string in the font.
+ // If eg. user asks for "en-us" and font has "en", approve.
+ if (!exact && c &&
+ hb_language_matches (b->language, a->language))
+ return 0;
+
+ return c;
}
static int
@@ -178,7 +189,7 @@ _hb_ot_name_entry_cmp (const void *pa, const void *pb)
{
/* Compare by name_id, then language, then score, then index. */
- int v = _hb_ot_name_entry_cmp_key (pa, pb);
+ int v = _hb_ot_name_entry_cmp_key (pa, pb, true);
if (v)
return v;
@@ -330,7 +341,18 @@ struct name
const hb_ot_name_entry_t *entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
this->names.length,
sizeof (hb_ot_name_entry_t),
- _hb_ot_name_entry_cmp_key);
+ _hb_ot_name_entry_cmp_key,
+ true);
+
+ if (!entry)
+ {
+ entry = hb_bsearch (key, (const hb_ot_name_entry_t *) this->names,
+ this->names.length,
+ sizeof (hb_ot_name_entry_t),
+ _hb_ot_name_entry_cmp_key,
+ false);
+ }
+
if (!entry)
return -1;
diff --git a/thirdparty/harfbuzz/src/hb-ot-name.cc b/thirdparty/harfbuzz/src/hb-ot-name.cc
index eff46ef227..c35ac5b3dc 100644
--- a/thirdparty/harfbuzz/src/hb-ot-name.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-name.cc
@@ -52,7 +52,7 @@
* array is owned by the @face and should not be modified. It can be
* used as long as @face is alive.
*
- * Returns: (out) (transfer none) (array length=num_entries): Array of available name entries.
+ * Returns: (transfer none) (array length=num_entries): Array of available name entries.
* Since: 2.1.0
**/
const hb_ot_name_entry_t *
diff --git a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
index f0035e2f04..3473afef54 100644
--- a/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-os2-table.hh
@@ -224,9 +224,11 @@ struct OS2
*max_cp = hb_min (0xFFFFu, codepoints->get_max ());
}
- /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681 */
+ /* https://github.com/Microsoft/Font-Validator/blob/520aaae/OTFontFileVal/val_OS2.cs#L644-L681
+ * https://docs.microsoft.com/en-us/typography/legacy/legacy_arabic_fonts */
enum font_page_t
{
+ FONT_PAGE_NONE = 0,
FONT_PAGE_HEBREW = 0xB100, /* Hebrew Windows 3.1 font page */
FONT_PAGE_SIMP_ARABIC = 0xB200, /* Simplified Arabic Windows 3.1 font page */
FONT_PAGE_TRAD_ARABIC = 0xB300, /* Traditional Arabic Windows 3.1 font page */
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
index 0f3cd8e24f..4d427e5431 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table-v2subset.hh
@@ -52,16 +52,16 @@ HB_INTERNAL bool postV2Tail::serialize (hb_serialize_context_t *c,
{
unsigned glyph_id = _.first;
unsigned new_index = _.second;
-
+
if (new_index < 258) continue;
if (copied_indices.has (new_index)) continue;
copied_indices.add (new_index);
-
+
hb_bytes_t s = reinterpret_cast<const post::accelerator_t*> (_post)->find_glyph_name (glyph_id);
HBUINT8 *o = c->allocate_size<HBUINT8> (HBUINT8::static_size * (s.length + 1));
if (unlikely (!o)) return_trace (false);
if (!c->check_assign (o[0], s.length, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
- memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
+ hb_memcpy (o+1, s.arrayZ, HBUINT8::static_size * s.length);
}
return_trace (true);
@@ -78,17 +78,19 @@ HB_INTERNAL bool postV2Tail::subset (hb_subset_context_t *c) const
post::accelerator_t _post (c->plan->source);
- hb_hashmap_t<hb_bytes_t, unsigned, std::nullptr_t, unsigned, nullptr, (unsigned)-1> glyph_name_to_new_index;
+ hb_hashmap_t<hb_bytes_t, unsigned, true> glyph_name_to_new_index;
for (hb_codepoint_t new_gid = 0; new_gid < num_glyphs; new_gid++)
{
hb_codepoint_t old_gid = reverse_glyph_map.get (new_gid);
unsigned old_index = glyphNameIndex[old_gid];
unsigned new_index;
+ const unsigned *new_index2;
if (old_index <= 257) new_index = old_index;
- else if (old_new_index_map.has (old_index)) new_index = old_new_index_map.get (old_index);
- else
+ else if (old_new_index_map.has (old_index, &new_index2))
{
+ new_index = *new_index2;
+ } else {
hb_bytes_t s = _post.find_glyph_name (old_gid);
new_index = glyph_name_to_new_index.get (s);
if (new_index == (unsigned)-1)
diff --git a/thirdparty/harfbuzz/src/hb-ot-post-table.hh b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
index a4844e94bc..a4c0c4aa17 100644
--- a/thirdparty/harfbuzz/src/hb-ot-post-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-post-table.hh
@@ -263,10 +263,10 @@ struct post
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) &&
- (version.to_int () == 0x00010000 ||
- (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
- version.to_int () == 0x00030000)));
+ return_trace (c->check_struct (this) &&
+ (version.to_int () == 0x00010000 ||
+ (version.to_int () == 0x00020000 && v2X.sanitize (c)) ||
+ version.to_int () == 0x00030000));
}
public:
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
deleted file mode 100644
index 78f46c1cac..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-fallback.hh
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * Copyright © 2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape.hh"
-#include "hb-ot-layout-gsub-table.hh"
-
-
-/* Features ordered the same as the entries in shaping_table rows,
- * followed by rlig. Don't change. */
-static const hb_tag_t arabic_fallback_features[] =
-{
- HB_TAG('i','n','i','t'),
- HB_TAG('m','e','d','i'),
- HB_TAG('f','i','n','a'),
- HB_TAG('i','s','o','l'),
- HB_TAG('r','l','i','g'),
-};
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font,
- unsigned int feature_index)
-{
- OT::HBGlyphID16 glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
- OT::HBGlyphID16 substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
- unsigned int num_glyphs = 0;
-
- /* Populate arrays */
- for (hb_codepoint_t u = SHAPING_TABLE_FIRST; u < SHAPING_TABLE_LAST + 1; u++)
- {
- hb_codepoint_t s = shaping_table[u - SHAPING_TABLE_FIRST][feature_index];
- hb_codepoint_t u_glyph, s_glyph;
-
- if (!s ||
- !hb_font_get_glyph (font, u, 0, &u_glyph) ||
- !hb_font_get_glyph (font, s, 0, &s_glyph) ||
- u_glyph == s_glyph ||
- u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
- continue;
-
- glyphs[num_glyphs] = u_glyph;
- substitutes[num_glyphs] = s_glyph;
-
- num_glyphs++;
- }
-
- if (!num_glyphs)
- return nullptr;
-
- /* Bubble-sort or something equally good!
- * May not be good-enough for presidential candidate interviews, but good-enough for us... */
- hb_stable_sort (&glyphs[0], num_glyphs,
- (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
- &substitutes[0]);
-
-
- /* Each glyph takes four bytes max, and there's some overhead. */
- char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
- hb_serialize_context_t c (buf, sizeof (buf));
- OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
- bool ret = lookup->serialize_single (&c,
- OT::LookupFlag::IgnoreMarks,
- hb_sorted_array (glyphs, num_glyphs),
- hb_array (substitutes, num_glyphs));
- c.end_serialize ();
-
- return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
-}
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font)
-{
- OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
- unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
- unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
- unsigned int num_first_glyphs = 0;
-
- /* We know that all our ligatures are 2-component */
- OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
- unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
- OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) * 1/* One extra component per ligature */];
- unsigned int num_ligatures = 0;
-
- /* Populate arrays */
-
- /* Sort out the first-glyphs */
- for (unsigned int first_glyph_idx = 0; first_glyph_idx < ARRAY_LENGTH (first_glyphs); first_glyph_idx++)
- {
- hb_codepoint_t first_u = ligature_table[first_glyph_idx].first;
- hb_codepoint_t first_glyph;
- if (!hb_font_get_glyph (font, first_u, 0, &first_glyph))
- continue;
- first_glyphs[num_first_glyphs] = first_glyph;
- ligature_per_first_glyph_count_list[num_first_glyphs] = 0;
- first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
- num_first_glyphs++;
- }
- hb_stable_sort (&first_glyphs[0], num_first_glyphs,
- (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
- &first_glyphs_indirection[0]);
-
- /* Now that the first-glyphs are sorted, walk again, populate ligatures. */
- for (unsigned int i = 0; i < num_first_glyphs; i++)
- {
- unsigned int first_glyph_idx = first_glyphs_indirection[i];
-
- for (unsigned int second_glyph_idx = 0; second_glyph_idx < ARRAY_LENGTH (ligature_table[0].ligatures); second_glyph_idx++)
- {
- hb_codepoint_t second_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].second;
- hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[second_glyph_idx].ligature;
- hb_codepoint_t second_glyph, ligature_glyph;
- if (!second_u ||
- !hb_font_get_glyph (font, second_u, 0, &second_glyph) ||
- !hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
- continue;
-
- ligature_per_first_glyph_count_list[i]++;
-
- ligature_list[num_ligatures] = ligature_glyph;
- component_count_list[num_ligatures] = 2;
- component_list[num_ligatures] = second_glyph;
- num_ligatures++;
- }
- }
-
- if (!num_ligatures)
- return nullptr;
-
-
- /* 16 bytes per ligature ought to be enough... */
- char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
- hb_serialize_context_t c (buf, sizeof (buf));
- OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
- bool ret = lookup->serialize_ligature (&c,
- OT::LookupFlag::IgnoreMarks,
- hb_sorted_array (first_glyphs, num_first_glyphs),
- hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
- hb_array (ligature_list, num_ligatures),
- hb_array (component_count_list, num_ligatures),
- hb_array (component_list, num_ligatures));
- c.end_serialize ();
- /* TODO sanitize the results? */
-
- return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
-}
-
-static OT::SubstLookup *
-arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- unsigned int feature_index)
-{
- if (feature_index < 4)
- return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
- else
- return arabic_fallback_synthesize_lookup_ligature (plan, font);
-}
-
-#define ARABIC_FALLBACK_MAX_LOOKUPS 5
-
-struct arabic_fallback_plan_t
-{
- unsigned int num_lookups;
- bool free_lookups;
-
- hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
- OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
- OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
-};
-
-#if defined(_WIN32) && !defined(HB_NO_WIN1256)
-#define HB_WITH_WIN1256
-#endif
-
-#ifdef HB_WITH_WIN1256
-#include "hb-ot-shape-complex-arabic-win1256.hh"
-#endif
-
-struct ManifestLookup
-{
- public:
- OT::Tag tag;
- OT::Offset16To<OT::SubstLookup> lookupOffset;
- public:
- DEFINE_SIZE_STATIC (6);
-};
-typedef OT::Array16Of<ManifestLookup> Manifest;
-
-static bool
-arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
- const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED)
-{
-#ifdef HB_WITH_WIN1256
- /* Does this font look like it's Windows-1256-encoded? */
- hb_codepoint_t g;
- if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
- hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
- hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
- hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
- hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
- return false;
-
- const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
- static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) ==
- ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), "");
- /* TODO sanitize the table? */
-
- unsigned j = 0;
- unsigned int count = manifest.len;
- for (unsigned int i = 0; i < count; i++)
- {
- fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag);
- if (fallback_plan->mask_array[j])
- {
- fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
- if (fallback_plan->lookup_array[j])
- {
- fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
- j++;
- }
- }
- }
-
- fallback_plan->num_lookups = j;
- fallback_plan->free_lookups = false;
-
- return j > 0;
-#else
- return false;
-#endif
-}
-
-static bool
-arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
- const hb_ot_shape_plan_t *plan,
- hb_font_t *font)
-{
- static_assert ((ARRAY_LENGTH_CONST(arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
- unsigned int j = 0;
- for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
- {
- fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
- if (fallback_plan->mask_array[j])
- {
- fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
- if (fallback_plan->lookup_array[j])
- {
- fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
- j++;
- }
- }
- }
-
- fallback_plan->num_lookups = j;
- fallback_plan->free_lookups = true;
-
- return j > 0;
-}
-
-static arabic_fallback_plan_t *
-arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
- hb_font_t *font)
-{
- arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_calloc (1, sizeof (arabic_fallback_plan_t));
- if (unlikely (!fallback_plan))
- return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
-
- fallback_plan->num_lookups = 0;
- fallback_plan->free_lookups = false;
-
- /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
- * in case the font has cmap entries for the presentation-forms characters. */
- if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
- return fallback_plan;
-
- /* See if this looks like a Windows-1256-encoded font. If it does, use a
- * hand-coded GSUB table. */
- if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
- return fallback_plan;
-
- assert (fallback_plan->num_lookups == 0);
- hb_free (fallback_plan);
- return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
-}
-
-static void
-arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
-{
- if (!fallback_plan || fallback_plan->num_lookups == 0)
- return;
-
- for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
- if (fallback_plan->lookup_array[i])
- {
- fallback_plan->accel_array[i].fini ();
- if (fallback_plan->free_lookups)
- hb_free (fallback_plan->lookup_array[i]);
- }
-
- hb_free (fallback_plan);
-}
-
-static void
-arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- OT::hb_ot_apply_context_t c (0, font, buffer);
- for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
- if (fallback_plan->lookup_array[i]) {
- c.set_lookup_mask (fallback_plan->mask_array[i]);
- hb_ot_layout_substitute_lookup (&c,
- *fallback_plan->lookup_array[i],
- fallback_plan->accel_array[i]);
- }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_FALLBACK_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh
deleted file mode 100644
index e6339ee72b..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-joining-list.hh
+++ /dev/null
@@ -1,47 +0,0 @@
-/* == Start of generated function == */
-/*
- * The following function is generated by running:
- *
- * ./gen-arabic-joining-list.py ArabicShaping.txt Scripts.txt
- *
- * on files with these headers:
- *
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH
-
-static bool
-has_arabic_joining (hb_script_t script)
-{
- /* List of scripts that have data in arabic-table. */
- switch ((int) script)
- {
- case HB_SCRIPT_ADLAM:
- case HB_SCRIPT_ARABIC:
- case HB_SCRIPT_CHORASMIAN:
- case HB_SCRIPT_HANIFI_ROHINGYA:
- case HB_SCRIPT_MANDAIC:
- case HB_SCRIPT_MANICHAEAN:
- case HB_SCRIPT_MONGOLIAN:
- case HB_SCRIPT_NKO:
- case HB_SCRIPT_OLD_UYGHUR:
- case HB_SCRIPT_PHAGS_PA:
- case HB_SCRIPT_PSALTER_PAHLAVI:
- case HB_SCRIPT_SOGDIAN:
- case HB_SCRIPT_SYRIAC:
- return true;
-
- default:
- return false;
- }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_JOINING_LIST_HH */
-
-/* == End of generated function == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
deleted file mode 100644
index c158964f2c..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-table.hh
+++ /dev/null
@@ -1,441 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- * UnicodeData.txt does not have a header.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH
-
-
-#define A JOINING_GROUP_ALAPH
-#define DR JOINING_GROUP_DALATH_RISH
-#define C JOINING_TYPE_C
-#define D JOINING_TYPE_D
-#define L JOINING_TYPE_L
-#define R JOINING_TYPE_R
-#define T JOINING_TYPE_T
-#define U JOINING_TYPE_U
-#define X JOINING_TYPE_X
-
-static const uint8_t joining_table[] =
-{
-
-#define joining_offset_0x0600u 0
-
- /* Arabic */
-
- /* 0600 */ U,U,U,U,U,U,X,X,U,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 0620 */ D,U,R,R,R,R,D,R,D,R,D,D,D,D,D,R,R,R,R,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 0640 */ C,D,D,D,D,D,D,D,R,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 0660 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,D,D,X,R,R,R,U,R,R,R,D,D,D,D,D,D,D,D,
- /* 0680 */ D,D,D,D,D,D,D,D,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,D,D,D,D,D,D,
- /* 06A0 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 06C0 */ R,D,D,R,R,R,R,R,R,R,R,R,D,R,D,R,D,D,R,R,X,R,X,X,X,X,X,X,X,U,X,X,
- /* 06E0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,R,R,X,X,X,X,X,X,X,X,X,X,D,D,D,X,X,D,
-
- /* Syriac */
-
- /* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,T,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
- /* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
-
- /* Arabic Supplement */
-
- /* 0740 */ D,D,D,D,D,D,D,D,D,R,R,R,D,D,D,D,
- /* 0760 */ D,D,D,D,D,D,D,D,D,D,D,R,R,D,D,D,D,R,D,R,R,D,D,D,R,R,D,D,D,D,D,D,
-
- /* FILLER */
-
- /* 0780 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 07A0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
- /* NKo */
-
- /* 07C0 */ X,X,X,X,X,X,X,X,X,X,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 07E0 */ D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,C,X,X,X,X,X,
-
- /* FILLER */
-
- /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
- /* Mandaic */
-
- /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,R,R,R,X,X,X,X,X,X,X,
-
- /* Syriac Supplement */
-
- /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,
-
- /* Arabic Extended-B */
-
- /* 0860 */ R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,
- /* 0880 */ R,R,R,C,C,C,D,U,U,D,D,D,D,D,R,X,U,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
- /* Arabic Extended-A */
-
- /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,D,D,D,D,R,D,D,D,D,D,D,
- /* 08C0 */ D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 08E0 */ X,X,U,
-
-#define joining_offset_0x1806u 739
-
- /* Mongolian */
-
- /* 1800 */ U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,
- /* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
-
-#define joining_offset_0x200cu 904
-
- /* General Punctuation */
-
- /* 2000 */ U,C,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 2020 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 2040 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 2060 */ X,X,X,X,X,X,U,U,U,U,
-
-#define joining_offset_0xa840u 998
-
- /* Phags-pa */
-
- /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
-
-#define joining_offset_0x10ac0u 1050
-
- /* Manichaean */
-
- /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
- /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
-
-#define joining_offset_0x10b80u 1098
-
- /* Psalter Pahlavi */
-
- /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
-
-#define joining_offset_0x10d00u 1146
-
- /* Hanifi Rohingya */
-
- /* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 10D20 */ D,D,R,D,
-
-#define joining_offset_0x10f30u 1182
-
- /* Sogdian */
-
- /* 10F20 */ D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,X,X,X,X,X,X,X,X,X,X,X,
- /* 10F60 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
- /* Old Uyghur */
-
- /* 10F60 */ D,D,D,D,R,R,D,D,D,D,D,D,D,D,D,D,
- /* 10F80 */ D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
- /* 10FA0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
-
- /* Chorasmian */
-
- /* 10FA0 */ D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
- /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
-
-#define joining_offset_0x110bdu 1338
-
- /* Kaithi */
-
- /* 110A0 */ U,X,X,
- /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
-
-#define joining_offset_0x1e900u 1355
-
- /* Adlam */
-
- /* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
- /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
-
-}; /* Table items: 1431; occupancy: 57% */
-
-
-static unsigned int
-joining_type (hb_codepoint_t u)
-{
- switch (u >> 12)
- {
- case 0x0u:
- if (hb_in_range<hb_codepoint_t> (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
- break;
-
- case 0x2u:
- if (hb_in_range<hb_codepoint_t> (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
- break;
-
- case 0x10u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
- break;
-
- case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x110BDu, 0x110CDu)) return joining_table[u - 0x110BDu + joining_offset_0x110bdu];
- break;
-
- case 0x1Eu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E94Bu)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
- break;
-
- default:
- break;
- }
- return X;
-}
-
-#undef A
-#undef DR
-#undef C
-#undef D
-#undef L
-#undef R
-#undef T
-#undef U
-#undef X
-
-
-static const uint16_t shaping_table[][4] =
-{
- {0x0000u, 0x0000u, 0x0000u, 0xFE80u}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
- {0x0000u, 0x0000u, 0xFE82u, 0xFE81u}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
- {0x0000u, 0x0000u, 0xFE84u, 0xFE83u}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
- {0x0000u, 0x0000u, 0xFE86u, 0xFE85u}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
- {0x0000u, 0x0000u, 0xFE88u, 0xFE87u}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
- {0xFE8Bu, 0xFE8Cu, 0xFE8Au, 0xFE89u}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
- {0x0000u, 0x0000u, 0xFE8Eu, 0xFE8Du}, /* U+0627 ARABIC LETTER ALEF */
- {0xFE91u, 0xFE92u, 0xFE90u, 0xFE8Fu}, /* U+0628 ARABIC LETTER BEH */
- {0x0000u, 0x0000u, 0xFE94u, 0xFE93u}, /* U+0629 ARABIC LETTER TEH MARBUTA */
- {0xFE97u, 0xFE98u, 0xFE96u, 0xFE95u}, /* U+062A ARABIC LETTER TEH */
- {0xFE9Bu, 0xFE9Cu, 0xFE9Au, 0xFE99u}, /* U+062B ARABIC LETTER THEH */
- {0xFE9Fu, 0xFEA0u, 0xFE9Eu, 0xFE9Du}, /* U+062C ARABIC LETTER JEEM */
- {0xFEA3u, 0xFEA4u, 0xFEA2u, 0xFEA1u}, /* U+062D ARABIC LETTER HAH */
- {0xFEA7u, 0xFEA8u, 0xFEA6u, 0xFEA5u}, /* U+062E ARABIC LETTER KHAH */
- {0x0000u, 0x0000u, 0xFEAAu, 0xFEA9u}, /* U+062F ARABIC LETTER DAL */
- {0x0000u, 0x0000u, 0xFEACu, 0xFEABu}, /* U+0630 ARABIC LETTER THAL */
- {0x0000u, 0x0000u, 0xFEAEu, 0xFEADu}, /* U+0631 ARABIC LETTER REH */
- {0x0000u, 0x0000u, 0xFEB0u, 0xFEAFu}, /* U+0632 ARABIC LETTER ZAIN */
- {0xFEB3u, 0xFEB4u, 0xFEB2u, 0xFEB1u}, /* U+0633 ARABIC LETTER SEEN */
- {0xFEB7u, 0xFEB8u, 0xFEB6u, 0xFEB5u}, /* U+0634 ARABIC LETTER SHEEN */
- {0xFEBBu, 0xFEBCu, 0xFEBAu, 0xFEB9u}, /* U+0635 ARABIC LETTER SAD */
- {0xFEBFu, 0xFEC0u, 0xFEBEu, 0xFEBDu}, /* U+0636 ARABIC LETTER DAD */
- {0xFEC3u, 0xFEC4u, 0xFEC2u, 0xFEC1u}, /* U+0637 ARABIC LETTER TAH */
- {0xFEC7u, 0xFEC8u, 0xFEC6u, 0xFEC5u}, /* U+0638 ARABIC LETTER ZAH */
- {0xFECBu, 0xFECCu, 0xFECAu, 0xFEC9u}, /* U+0639 ARABIC LETTER AIN */
- {0xFECFu, 0xFED0u, 0xFECEu, 0xFECDu}, /* U+063A ARABIC LETTER GHAIN */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063B */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063D */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0640 */
- {0xFED3u, 0xFED4u, 0xFED2u, 0xFED1u}, /* U+0641 ARABIC LETTER FEH */
- {0xFED7u, 0xFED8u, 0xFED6u, 0xFED5u}, /* U+0642 ARABIC LETTER QAF */
- {0xFEDBu, 0xFEDCu, 0xFEDAu, 0xFED9u}, /* U+0643 ARABIC LETTER KAF */
- {0xFEDFu, 0xFEE0u, 0xFEDEu, 0xFEDDu}, /* U+0644 ARABIC LETTER LAM */
- {0xFEE3u, 0xFEE4u, 0xFEE2u, 0xFEE1u}, /* U+0645 ARABIC LETTER MEEM */
- {0xFEE7u, 0xFEE8u, 0xFEE6u, 0xFEE5u}, /* U+0646 ARABIC LETTER NOON */
- {0xFEEBu, 0xFEECu, 0xFEEAu, 0xFEE9u}, /* U+0647 ARABIC LETTER HEH */
- {0x0000u, 0x0000u, 0xFEEEu, 0xFEEDu}, /* U+0648 ARABIC LETTER WAW */
- {0xFBE8u, 0xFBE9u, 0xFEF0u, 0xFEEFu}, /* U+0649 ARABIC LETTER */
- {0xFEF3u, 0xFEF4u, 0xFEF2u, 0xFEF1u}, /* U+064A ARABIC LETTER YEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064B */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064D */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0650 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0651 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0652 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0653 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0654 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0655 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0656 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0657 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0658 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0659 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065A */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065B */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065D */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0660 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0661 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0662 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0663 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0664 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0665 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0666 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0667 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0668 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0669 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066A */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066B */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066D */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0670 */
- {0x0000u, 0x0000u, 0xFB51u, 0xFB50u}, /* U+0671 ARABIC LETTER ALEF WASLA */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0672 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0673 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0674 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0675 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0676 */
- {0x0000u, 0x0000u, 0x0000u, 0xFBDDu}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0678 */
- {0xFB68u, 0xFB69u, 0xFB67u, 0xFB66u}, /* U+0679 ARABIC LETTER TTEH */
- {0xFB60u, 0xFB61u, 0xFB5Fu, 0xFB5Eu}, /* U+067A ARABIC LETTER TTEHEH */
- {0xFB54u, 0xFB55u, 0xFB53u, 0xFB52u}, /* U+067B ARABIC LETTER BEEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067D */
- {0xFB58u, 0xFB59u, 0xFB57u, 0xFB56u}, /* U+067E ARABIC LETTER PEH */
- {0xFB64u, 0xFB65u, 0xFB63u, 0xFB62u}, /* U+067F ARABIC LETTER TEHEH */
- {0xFB5Cu, 0xFB5Du, 0xFB5Bu, 0xFB5Au}, /* U+0680 ARABIC LETTER BEHEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0681 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0682 */
- {0xFB78u, 0xFB79u, 0xFB77u, 0xFB76u}, /* U+0683 ARABIC LETTER NYEH */
- {0xFB74u, 0xFB75u, 0xFB73u, 0xFB72u}, /* U+0684 ARABIC LETTER DYEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0685 */
- {0xFB7Cu, 0xFB7Du, 0xFB7Bu, 0xFB7Au}, /* U+0686 ARABIC LETTER TCHEH */
- {0xFB80u, 0xFB81u, 0xFB7Fu, 0xFB7Eu}, /* U+0687 ARABIC LETTER TCHEHEH */
- {0x0000u, 0x0000u, 0xFB89u, 0xFB88u}, /* U+0688 ARABIC LETTER DDAL */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0689 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068A */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068B */
- {0x0000u, 0x0000u, 0xFB85u, 0xFB84u}, /* U+068C ARABIC LETTER DAHAL */
- {0x0000u, 0x0000u, 0xFB83u, 0xFB82u}, /* U+068D ARABIC LETTER DDAHAL */
- {0x0000u, 0x0000u, 0xFB87u, 0xFB86u}, /* U+068E ARABIC LETTER DUL */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0690 */
- {0x0000u, 0x0000u, 0xFB8Du, 0xFB8Cu}, /* U+0691 ARABIC LETTER RREH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0692 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0693 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0694 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0695 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0696 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0697 */
- {0x0000u, 0x0000u, 0xFB8Bu, 0xFB8Au}, /* U+0698 ARABIC LETTER JEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0699 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069A */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069B */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069C */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069D */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069F */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A0 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A1 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A2 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A3 */
- {0xFB6Cu, 0xFB6Du, 0xFB6Bu, 0xFB6Au}, /* U+06A4 ARABIC LETTER VEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A5 */
- {0xFB70u, 0xFB71u, 0xFB6Fu, 0xFB6Eu}, /* U+06A6 ARABIC LETTER PEHEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A7 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A8 */
- {0xFB90u, 0xFB91u, 0xFB8Fu, 0xFB8Eu}, /* U+06A9 ARABIC LETTER KEHEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AA */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AB */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AC */
- {0xFBD5u, 0xFBD6u, 0xFBD4u, 0xFBD3u}, /* U+06AD ARABIC LETTER NG */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AE */
- {0xFB94u, 0xFB95u, 0xFB93u, 0xFB92u}, /* U+06AF ARABIC LETTER GAF */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B0 */
- {0xFB9Cu, 0xFB9Du, 0xFB9Bu, 0xFB9Au}, /* U+06B1 ARABIC LETTER NGOEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B2 */
- {0xFB98u, 0xFB99u, 0xFB97u, 0xFB96u}, /* U+06B3 ARABIC LETTER GUEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B4 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B5 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B6 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B7 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B8 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B9 */
- {0x0000u, 0x0000u, 0xFB9Fu, 0xFB9Eu}, /* U+06BA ARABIC LETTER NOON GHUNNA */
- {0xFBA2u, 0xFBA3u, 0xFBA1u, 0xFBA0u}, /* U+06BB ARABIC LETTER RNOON */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BC */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BD */
- {0xFBACu, 0xFBADu, 0xFBABu, 0xFBAAu}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BF */
- {0x0000u, 0x0000u, 0xFBA5u, 0xFBA4u}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
- {0xFBA8u, 0xFBA9u, 0xFBA7u, 0xFBA6u}, /* U+06C1 ARABIC LETTER HEH GOAL */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C2 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C3 */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C4 */
- {0x0000u, 0x0000u, 0xFBE1u, 0xFBE0u}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
- {0x0000u, 0x0000u, 0xFBDAu, 0xFBD9u}, /* U+06C6 ARABIC LETTER OE */
- {0x0000u, 0x0000u, 0xFBD8u, 0xFBD7u}, /* U+06C7 ARABIC LETTER U */
- {0x0000u, 0x0000u, 0xFBDCu, 0xFBDBu}, /* U+06C8 ARABIC LETTER YU */
- {0x0000u, 0x0000u, 0xFBE3u, 0xFBE2u}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CA */
- {0x0000u, 0x0000u, 0xFBDFu, 0xFBDEu}, /* U+06CB ARABIC LETTER VE */
- {0xFBFEu, 0xFBFFu, 0xFBFDu, 0xFBFCu}, /* U+06CC ARABIC LETTER FARSI YEH */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CD */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CE */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CF */
- {0xFBE6u, 0xFBE7u, 0xFBE5u, 0xFBE4u}, /* U+06D0 ARABIC LETTER E */
- {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06D1 */
- {0x0000u, 0x0000u, 0xFBAFu, 0xFBAEu}, /* U+06D2 ARABIC LETTER YEH BARREE */
- {0x0000u, 0x0000u, 0xFBB1u, 0xFBB0u}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
-};
-
-#define SHAPING_TABLE_FIRST 0x0621u
-#define SHAPING_TABLE_LAST 0x06D3u
-
-
-static const struct ligature_set_t {
- uint16_t first;
- struct ligature_pairs_t {
- uint16_t second;
- uint16_t ligature;
- } ligatures[4];
-} ligature_table[] =
-{
- { 0xFEDFu, {
- { 0xFE82u, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
- { 0xFE84u, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
- { 0xFE88u, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
- { 0xFE8Eu, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
- }},
- { 0xFEE0u, {
- { 0xFE82u, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
- { 0xFE84u, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
- { 0xFE88u, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
- { 0xFE8Eu, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
- }},
-};
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_TABLE_HH */
-
-/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
deleted file mode 100644
index 429974d05b..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic-win1256.hh
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * Copyright © 2014 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-
-
-/*
- * The macros in the first part of this file are generic macros that can
- * be used to define the bytes for OpenType table data in code in a
- * readable manner. We can move the macros to reside with their respective
- * struct types, but since we only use these to define one data table, the
- * Windows-1256 Arabic shaping table in this file, we keep them here.
- */
-
-
-/* First we measure, then we cut. */
-#ifndef OT_MEASURE
-#define OT_MEASURE
-#define OT_TABLE_START static const struct TABLE_NAME {
-#define OT_TABLE_END }
-#define OT_LABEL_START(Name) unsigned char Name[
-#define OT_LABEL_END ];
-#define OT_UINT8(u8) +1/*byte*/
-#define OT_UINT16(u16) +2/*bytes*/
-#else
-#undef OT_MEASURE
-#define OT_TABLE_START TABLE_NAME = {
-#define OT_TABLE_END };
-#define OT_LABEL_START(Name) {
-#define OT_LABEL_END },
-#define OT_UINT8(u8) (u8),
-#define OT_UINT16(u16) (unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
-#define OT_COUNT(Name, ItemSize) ((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
- / (unsigned int)(ItemSize) \
- /* OT_ASSERT it's divisible (and positive). */)
-#define OT_DISTANCE(From,To) ((unsigned int) \
- ((char*)(&((struct TABLE_NAME*)0)->To) - \
- (char*)(&((struct TABLE_NAME*)0)->From)) \
- /* OT_ASSERT it's positive. */)
-#endif
-
-
-#define OT_LABEL(Name) \
- OT_LABEL_END \
- OT_LABEL_START(Name)
-
-/* Whenever we receive an argument that is a list, it will expand to
- * contain commas. That cannot be passed to another macro because the
- * commas will throw off the preprocessor. The solution is to wrap
- * the passed-in argument in OT_LIST() before passing to the next macro.
- * Unfortunately this trick requires vararg macros. */
-#define OT_LIST(...) __VA_ARGS__
-
-
-/*
- * Basic Types
- */
-
-#define OT_TAG(a,b,c,d) \
- OT_UINT8(a) OT_UINT8(b) OT_UINT8(c) OT_UINT8(d)
-
-#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
- OT_UINT16(OT_DISTANCE(From, To))
-
-#define OT_GLYPHID /* GlyphID */ \
- OT_UINT16
-/* Shorthand. */
-#define G OT_GLYPHID
-
-#define OT_UARRAY(Name, Items) \
- OT_LABEL_START(Name) \
- OT_UINT16(OT_COUNT(Name##Data, 2)) \
- OT_LABEL(Name##Data) \
- Items \
- OT_LABEL_END
-
-#define OT_UHEADLESSARRAY(Name, Items) \
- OT_LABEL_START(Name) \
- OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \
- OT_LABEL(Name##Data) \
- Items \
- OT_LABEL_END
-
-
-/*
- * Common Types
- */
-
-#define OT_LOOKUP_FLAG_IGNORE_MARKS 0x08u
-
-#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
- OT_LABEL_START(Name) \
- OT_UINT16(LookupType) \
- OT_UINT16(LookupFlag) \
- OT_LABEL_END \
- OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
-
-#define OT_SUBLOOKUP(Name, SubFormat, Items) \
- OT_LABEL_START(Name) \
- OT_UINT16(SubFormat) \
- Items
-
-#define OT_COVERAGE1(Name, Items) \
- OT_LABEL_START(Name) \
- OT_UINT16(1) \
- OT_LABEL_END \
- OT_UARRAY(Name##Glyphs, OT_LIST(Items))
-
-
-/*
- * GSUB
- */
-
-#define OT_LOOKUP_TYPE_SUBST_SINGLE 1u
-#define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u
-
-#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \
- OT_SUBLOOKUP(Name, 2, \
- OT_OFFSET(Name, Name##Coverage) \
- OT_LABEL_END \
- OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
- ) \
- OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
- /* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */
-
-#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
- OT_SUBLOOKUP(Name, 1, \
- OT_OFFSET(Name, Name##Coverage) \
- OT_LABEL_END \
- OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
- ) \
- OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
- /* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */
-
-#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
- OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
-
-#define OT_LIGATURE(Name, Components, LigGlyph) \
- OT_LABEL_START(Name) \
- LigGlyph \
- OT_LABEL_END \
- OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components))
-
-/*
- *
- * Start of Windows-1256 shaping table.
- *
- */
-
-/* Table name. */
-#define TABLE_NAME arabic_win1256_gsub_lookups
-
-/* Table manifest. */
-#define MANIFEST(Items) \
- OT_LABEL_START(manifest) \
- OT_UINT16(OT_COUNT(manifestData, 6)) \
- OT_LABEL(manifestData) \
- Items \
- OT_LABEL_END
-
-#define MANIFEST_LOOKUP(Tag, Name) \
- Tag \
- OT_OFFSET(manifest, Name)
-
-
-/*
- * Table Start
- */
-OT_TABLE_START
-
-
-/*
- * Manifest
- */
-MANIFEST(
- MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup)
- MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup)
- MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup)
- MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup)
- MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup)
-)
-
-/*
- * Lookups
- */
-OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
- OT_OFFSET(initLookup, initmediSubLookup)
- OT_OFFSET(initLookup, initSubLookup)
-)
-OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
- OT_OFFSET(mediLookup, initmediSubLookup)
- OT_OFFSET(mediLookup, mediSubLookup)
- OT_OFFSET(mediLookup, medifinaLamAlefSubLookup)
-)
-OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
- OT_OFFSET(finaLookup, finaSubLookup)
- /* We don't need this one currently as the sequence inherits masks
- * from the first item. Just in case we change that in the future
- * to be smart about Arabic masks when ligating... */
- OT_OFFSET(finaLookup, medifinaLamAlefSubLookup)
-)
-OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS,
- OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup)
-)
-OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0,
- OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup)
-)
-
-/*
- * init/medi/fina forms
- */
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup,
- G(198) G(200) G(201) G(202) G(203) G(204) G(205) G(206) G(211)
- G(212) G(213) G(214) G(223) G(225) G(227) G(228) G(236) G(237),
- G(162) G(4) G(5) G(5) G(6) G(7) G(9) G(11) G(13)
- G(14) G(15) G(26) G(140) G(141) G(142) G(143) G(154) G(154)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup,
- G(218) G(219) G(221) G(222) G(229),
- G(27) G(30) G(128) G(131) G(144)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup,
- G(218) G(219) G(221) G(222) G(229),
- G(28) G(31) G(129) G(138) G(149)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup,
- G(194) G(195) G(197) G(198) G(199) G(201) G(204) G(205) G(206)
- G(218) G(219) G(229) G(236) G(237),
- G(2) G(1) G(3) G(181) G(0) G(159) G(8) G(10) G(12)
- G(29) G(127) G(152) G(160) G(156)
-)
-OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup,
- G(165) G(178) G(180) G(252),
- G(170) G(179) G(185) G(255)
-)
-
-/*
- * Lam+Alef ligatures
- */
-OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup,
- G(225),
- OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet)
-)
-OT_LIGATURE_SET(lamLigatureSet,
- OT_OFFSET(lamLigatureSet, lamInitLigature1)
- OT_OFFSET(lamLigatureSet, lamInitLigature2)
- OT_OFFSET(lamLigatureSet, lamInitLigature3)
- OT_OFFSET(lamLigatureSet, lamInitLigature4)
-)
-OT_LIGATURE(lamInitLigature1, G(199), G(165))
-OT_LIGATURE(lamInitLigature2, G(195), G(178))
-OT_LIGATURE(lamInitLigature3, G(194), G(180))
-OT_LIGATURE(lamInitLigature4, G(197), G(252))
-
-/*
- * Shadda ligatures
- */
-OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup,
- G(248),
- OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet)
-)
-OT_LIGATURE_SET(shaddaLigatureSet,
- OT_OFFSET(shaddaLigatureSet, shaddaLigature1)
- OT_OFFSET(shaddaLigatureSet, shaddaLigature2)
- OT_OFFSET(shaddaLigatureSet, shaddaLigature3)
-)
-OT_LIGATURE(shaddaLigature1, G(243), G(172))
-OT_LIGATURE(shaddaLigature2, G(245), G(173))
-OT_LIGATURE(shaddaLigature3, G(246), G(175))
-
-/*
- * Table end
- */
-OT_TABLE_END
-
-
-/*
- * Clean up
- */
-
-#undef MANIFEST
-#undef MANIFEST_LOOKUP
-
-#undef OT_TABLE_START
-#undef OT_TABLE_END
-#undef OT_LABEL_START
-#undef OT_LABEL_END
-#undef OT_UINT8
-#undef OT_UINT16
-#undef OT_COUNT
-#undef OT_DISTANCE
-
-#undef OT_LABEL
-#undef OT_LIST
-
-#undef OT_TAG
-#undef OT_OFFSET
-#undef OT_GLYPHID
-#undef G
-#undef OT_UARRAY
-#undef OT_UHEADLESSARRAY
-
-#undef OT_LOOKUP_FLAG_IGNORE_MARKS
-#undef OT_LOOKUP
-#undef OT_SUBLOOKUP
-#undef OT_COVERAGE1
-#undef OT_LOOKUP_TYPE_SUBST_SINGLE
-#undef OT_LOOKUP_TYPE_SUBST_LIGATURE
-#undef OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2
-#undef OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1
-#undef OT_LIGATURE_SET
-#undef OT_LIGATURE
-
-
-/*
- * Include a second time to get the table data...
- */
-#if 0
-#include "hb.hh" /* Make check-includes.sh happy. */
-#endif
-#ifdef OT_MEASURE
-#include "hb-ot-shape-complex-arabic-win1256.hh"
-#endif
-
-#define HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_WIN1256_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
deleted file mode 100644
index 2298aa92f2..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.cc
+++ /dev/null
@@ -1,737 +0,0 @@
-/*
- * Copyright © 2010,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-arabic.hh"
-#include "hb-ot-shape.hh"
-
-
-/* buffer var allocations */
-#define arabic_shaping_action() complex_var_u8_auxiliary() /* arabic shaping action */
-
-#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_COMPLEX0
-
-/* See:
- * https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
-#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
- (FLAG_UNSAFE (gen_cat) & \
- (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
- /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
- /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
- /*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \
- FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL)))
-
-
-/*
- * Joining types:
- */
-
-/*
- * Bits used in the joining tables
- */
-enum hb_arabic_joining_type_t {
- JOINING_TYPE_U = 0,
- JOINING_TYPE_L = 1,
- JOINING_TYPE_R = 2,
- JOINING_TYPE_D = 3,
- JOINING_TYPE_C = JOINING_TYPE_D,
- JOINING_GROUP_ALAPH = 4,
- JOINING_GROUP_DALATH_RISH = 5,
- NUM_STATE_MACHINE_COLS = 6,
-
- JOINING_TYPE_T = 7,
- JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */
-};
-
-#include "hb-ot-shape-complex-arabic-table.hh"
-
-static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
-{
- unsigned int j_type = joining_type(u);
- if (likely (j_type != JOINING_TYPE_X))
- return j_type;
-
- return (FLAG_UNSAFE(gen_cat) &
- (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
- FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
- FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
- ) ? JOINING_TYPE_T : JOINING_TYPE_U;
-}
-
-#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
-
-static const hb_tag_t arabic_features[] =
-{
- HB_TAG('i','s','o','l'),
- HB_TAG('f','i','n','a'),
- HB_TAG('f','i','n','2'),
- HB_TAG('f','i','n','3'),
- HB_TAG('m','e','d','i'),
- HB_TAG('m','e','d','2'),
- HB_TAG('i','n','i','t'),
- HB_TAG_NONE
-};
-
-
-/* Same order as the feature array */
-enum arabic_action_t {
- ISOL,
- FINA,
- FIN2,
- FIN3,
- MEDI,
- MED2,
- INIT,
-
- NONE,
-
- ARABIC_NUM_FEATURES = NONE,
-
- /* We abuse the same byte for other things... */
- STCH_FIXED,
- STCH_REPEATING,
-};
-
-static const struct arabic_state_table_entry {
- uint8_t prev_action;
- uint8_t curr_action;
- uint16_t next_state;
-} arabic_state_table[][NUM_STATE_MACHINE_COLS] =
-{
- /* jt_U, jt_L, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */
-
- /* State 0: prev was U, not willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
-
- /* State 1: prev was R or ISOL/ALAPH, not willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
-
- /* State 2: prev was D/L in ISOL form, willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
-
- /* State 3: prev was D in FINA form, willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
-
- /* State 4: prev was FINA ALAPH, not willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
-
- /* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
-
- /* State 6: prev was DALATH/RISH, not willing to join. */
- { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
-};
-
-
-static void
-arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-record_stch (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-collect_features_arabic (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* We apply features according to the Arabic spec, with pauses
- * in between most.
- *
- * The pause between init/medi/... and rlig is required. See eg:
- * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
- *
- * The pauses between init/medi/... themselves are not necessarily
- * needed as only one of those features is applied to any character.
- * The only difference it makes is when fonts have contextual
- * substitutions. We now follow the order of the spec, which makes
- * for better experience if that's what Uniscribe is doing.
- *
- * At least for Arabic, looks like Uniscribe has a pause between
- * rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't
- * work. However, testing shows that rlig and calt are applied
- * together for Mongolian in Uniscribe. As such, we only add a
- * pause for Arabic, not other scripts.
- *
- * A pause after calt is required to make KFGQPC Uthmanic Script HAFS
- * work correctly. See https://github.com/harfbuzz/harfbuzz/issues/505
- */
-
-
- map->enable_feature (HB_TAG('s','t','c','h'));
- map->add_gsub_pause (record_stch);
-
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('l','o','c','l'));
-
- map->add_gsub_pause (nullptr);
-
- for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
- {
- bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
- map->add_feature (arabic_features[i], has_fallback ? F_HAS_FALLBACK : F_NONE);
- map->add_gsub_pause (nullptr);
- }
-
- /* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script
- * however, it says a ZWJ should also mean "don't ligate". So we run
- * the main ligating features as MANUAL_ZWJ. */
-
- map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK);
-
- if (plan->props.script == HB_SCRIPT_ARABIC)
- map->add_gsub_pause (arabic_fallback_shape);
-
- /* No pause after rclt. See 98460779bae19e4d64d29461ff154b3527bf8420. */
- map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
- map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
- map->add_gsub_pause (nullptr);
-
- /* The spec includes 'cswh'. Earlier versions of Windows
- * used to enable this by default, but testing suggests
- * that Windows 8 and later do not enable it by default,
- * and spec now says 'Off by default'.
- * We disabled this in ae23c24c32.
- * Note that IranNastaliq uses this feature extensively
- * to fixup broken glyph sequences. Oh well...
- * Test case: U+0643,U+0640,U+0631. */
- //map->enable_feature (HB_TAG('c','s','w','h'));
- map->enable_feature (HB_TAG('m','s','e','t'));
-}
-
-#include "hb-ot-shape-complex-arabic-fallback.hh"
-
-struct arabic_shape_plan_t
-{
- /* The "+ 1" in the next array is to accommodate for the "NONE" command,
- * which is not an OpenType feature, but this simplifies the code by not
- * having to do a "if (... < NONE) ..." and just rely on the fact that
- * mask_array[NONE] == 0. */
- hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
-
- hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
-
- unsigned int do_fallback : 1;
- unsigned int has_stch : 1;
-};
-
-void *
-data_create_arabic (const hb_ot_shape_plan_t *plan)
-{
- arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) hb_calloc (1, sizeof (arabic_shape_plan_t));
- if (unlikely (!arabic_plan))
- return nullptr;
-
- arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
- arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
- for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
- arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
- arabic_plan->do_fallback = arabic_plan->do_fallback &&
- (FEATURE_IS_SYRIAC (arabic_features[i]) ||
- plan->map.needs_fallback (arabic_features[i]));
- }
-
- return arabic_plan;
-}
-
-void
-data_destroy_arabic (void *data)
-{
- arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
-
- arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
-
- hb_free (data);
-}
-
-static void
-arabic_joining (hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- unsigned int prev = UINT_MAX, state = 0;
-
- /* Check pre-context */
- for (unsigned int i = 0; i < buffer->context_len[0]; i++)
- {
- unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
-
- if (unlikely (this_type == JOINING_TYPE_T))
- continue;
-
- const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
- state = entry->next_state;
- break;
- }
-
- for (unsigned int i = 0; i < count; i++)
- {
- unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
-
- if (unlikely (this_type == JOINING_TYPE_T)) {
- info[i].arabic_shaping_action() = NONE;
- continue;
- }
-
- const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
-
- if (entry->prev_action != NONE && prev != UINT_MAX)
- {
- info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, i + 1);
- }
- else
- {
- if (prev == UINT_MAX)
- {
- if (this_type >= JOINING_TYPE_R)
- buffer->unsafe_to_concat_from_outbuffer (0, i + 1);
- }
- else
- {
- if (this_type >= JOINING_TYPE_R ||
- (2 <= state && state <= 5) /* States that have a possible prev_action. */)
- buffer->unsafe_to_concat (prev, i + 1);
- }
- }
-
- info[i].arabic_shaping_action() = entry->curr_action;
-
- prev = i;
- state = entry->next_state;
- }
-
- for (unsigned int i = 0; i < buffer->context_len[1]; i++)
- {
- unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
-
- if (unlikely (this_type == JOINING_TYPE_T))
- continue;
-
- const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
- if (entry->prev_action != NONE && prev != UINT_MAX)
- {
- info[prev].arabic_shaping_action() = entry->prev_action;
- buffer->unsafe_to_break (prev, buffer->len);
- }
- else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
- {
- buffer->unsafe_to_concat (prev, buffer->len);
- }
- break;
- }
-}
-
-static void
-mongolian_variation_selectors (hb_buffer_t *buffer)
-{
- /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 1; i < count; i++)
- if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu)))
- info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
-}
-
-void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
- hb_buffer_t *buffer,
- hb_script_t script)
-{
- HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
-
- arabic_joining (buffer);
- if (script == HB_SCRIPT_MONGOLIAN)
- mongolian_variation_selectors (buffer);
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
-}
-
-static void
-setup_masks_arabic (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
- setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
-}
-
-static void
-arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_ARABIC_FALLBACK
- return;
-#endif
-
- const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
-
- if (!arabic_plan->do_fallback)
- return;
-
-retry:
- arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
- if (unlikely (!fallback_plan))
- {
- /* This sucks. We need a font to build the fallback plan... */
- fallback_plan = arabic_fallback_plan_create (plan, font);
- if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
- {
- arabic_fallback_plan_destroy (fallback_plan);
- goto retry;
- }
- }
-
- arabic_fallback_plan_shape (fallback_plan, font, buffer);
-}
-
-/*
- * Stretch feature: "stch".
- * See example here:
- * https://docs.microsoft.com/en-us/typography/script-development/syriac
- * We implement this in a generic way, such that the Arabic subtending
- * marks can use it as well.
- */
-
-static void
-record_stch (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
- if (!arabic_plan->has_stch)
- return;
-
- /* 'stch' feature was just applied. Look for anything that multiplied,
- * and record it for stch treatment later. Note that rtlm, frac, etc
- * are applied before stch, but we assume that they didn't result in
- * anything multiplying into 5 pieces, so it's safe-ish... */
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if (unlikely (_hb_glyph_info_multiplied (&info[i])))
- {
- unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]);
- info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
- buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
- }
-}
-
-static void
-apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
- return;
-
- /* The Arabic shaper currently always processes in RTL mode, so we should
- * stretch / position the stretched pieces to the left / preceding glyphs. */
-
- /* We do a two pass implementation:
- * First pass calculates the exact number of extra glyphs we need,
- * We then enlarge buffer to have that much room,
- * Second pass applies the stretch, copying things to the end of buffer.
- */
-
- int sign = font->x_scale < 0 ? -1 : +1;
- unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
- enum { MEASURE, CUT } /* step_t */;
-
- for (unsigned int step = MEASURE; step <= CUT; step = step + 1)
- {
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- hb_glyph_position_t *pos = buffer->pos;
- unsigned int new_len = count + extra_glyphs_needed; // write head during CUT
- unsigned int j = new_len;
- for (unsigned int i = count; i; i--)
- {
- if (!hb_in_range<uint8_t> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
- {
- if (step == CUT)
- {
- --j;
- info[j] = info[i - 1];
- pos[j] = pos[i - 1];
- }
- continue;
- }
-
- /* Yay, justification! */
-
- hb_position_t w_total = 0; // Total to be filled
- hb_position_t w_fixed = 0; // Sum of fixed tiles
- hb_position_t w_repeating = 0; // Sum of repeating tiles
- int n_fixed = 0;
- int n_repeating = 0;
-
- unsigned int end = i;
- while (i &&
- hb_in_range<uint8_t> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
- {
- i--;
- hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
- if (info[i].arabic_shaping_action() == STCH_FIXED)
- {
- w_fixed += width;
- n_fixed++;
- }
- else
- {
- w_repeating += width;
- n_repeating++;
- }
- }
- unsigned int start = i;
- unsigned int context = i;
- while (context &&
- !hb_in_range<uint8_t> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) &&
- (_hb_glyph_info_is_default_ignorable (&info[context - 1]) ||
- HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1]))))
- {
- context--;
- w_total += pos[context].x_advance;
- }
- i++; // Don't touch i again.
-
- DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%d,%d,%d)",
- step == MEASURE ? "measuring" : "cutting", context, start, end);
- DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%d width %d", start - context, w_total);
- DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%d", n_fixed, w_fixed);
- DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
-
- /* Number of additional times to repeat each repeating tile. */
- int n_copies = 0;
-
- hb_position_t w_remaining = w_total - w_fixed;
- if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
- n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
-
- /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
- hb_position_t extra_repeat_overlap = 0;
- hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
- if (shortfall > 0 && n_repeating > 0)
- {
- ++n_copies;
- hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
- if (excess > 0)
- extra_repeat_overlap = excess / (n_copies * n_repeating);
- }
-
- if (step == MEASURE)
- {
- extra_glyphs_needed += n_copies * n_repeating;
- DEBUG_MSG (ARABIC, nullptr, "will add extra %d copies of repeating tiles", n_copies);
- }
- else
- {
- buffer->unsafe_to_break (context, end);
- hb_position_t x_offset = 0;
- for (unsigned int k = end; k > start; k--)
- {
- hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
-
- unsigned int repeat = 1;
- if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
- repeat += n_copies;
-
- DEBUG_MSG (ARABIC, nullptr, "appending %d copies of glyph %d; j=%d",
- repeat, info[k - 1].codepoint, j);
- for (unsigned int n = 0; n < repeat; n++)
- {
- x_offset -= width;
- if (n > 0)
- x_offset += extra_repeat_overlap;
- pos[k - 1].x_offset = x_offset;
- /* Append copy. */
- --j;
- info[j] = info[k - 1];
- pos[j] = pos[k - 1];
- }
- }
- }
- }
-
- if (step == MEASURE)
- {
- if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
- break;
- }
- else
- {
- assert (j == 0);
- buffer->len = new_len;
- }
- }
-}
-
-
-static void
-postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- apply_stch (plan, buffer, font);
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
-}
-
-/* https://www.unicode.org/reports/tr53/ */
-
-static hb_codepoint_t
-modifier_combining_marks[] =
-{
- 0x0654u, /* ARABIC HAMZA ABOVE */
- 0x0655u, /* ARABIC HAMZA BELOW */
- 0x0658u, /* ARABIC MARK NOON GHUNNA */
- 0x06DCu, /* ARABIC SMALL HIGH SEEN */
- 0x06E3u, /* ARABIC SMALL LOW SEEN */
- 0x06E7u, /* ARABIC SMALL HIGH YEH */
- 0x06E8u, /* ARABIC SMALL HIGH NOON */
- 0x08D3u, /* ARABIC SMALL LOW WAW */
- 0x08F3u, /* ARABIC SMALL HIGH WAW */
-};
-
-static inline bool
-info_is_mcm (const hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++)
- if (u == modifier_combining_marks[i])
- return true;
- return false;
-}
-
-static void
-reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end)
-{
- hb_glyph_info_t *info = buffer->info;
-
- DEBUG_MSG (ARABIC, buffer, "Reordering marks from %d to %d", start, end);
-
- unsigned int i = start;
- for (unsigned int cc = 220; cc <= 230; cc += 10)
- {
- DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d", cc, i);
- while (i < end && info_cc(info[i]) < cc)
- i++;
- DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d", cc, i);
-
- if (i == end)
- break;
-
- if (info_cc(info[i]) > cc)
- continue;
-
- unsigned int j = i;
- while (j < end && info_cc(info[j]) == cc && info_is_mcm (info[j]))
- j++;
-
- if (i == j)
- continue;
-
- DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d", cc, i, j);
-
- /* Shift it! */
- DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d", cc, i, j);
- hb_glyph_info_t temp[HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS];
- assert (j - i <= ARRAY_LENGTH (temp));
- buffer->merge_clusters (start, j);
- memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
- memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t));
- memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t));
-
- /* Renumber CC such that the reordered sequence is still sorted.
- * 22 and 26 are chosen because they are smaller than all Arabic categories,
- * and are folded back to 220/230 respectively during fallback mark positioning.
- *
- * We do this because the CGJ-handling logic in the normalizer relies on
- * mark sequences having an increasing order even after this reordering.
- * https://github.com/harfbuzz/harfbuzz/issues/554
- * This, however, does break some obscure sequences, where the normalizer
- * might compose a sequence that it should not. For example, in the seequence
- * ALEF, HAMZAH, MADDAH, we should NOT try to compose ALEF+MADDAH, but with this
- * renumbering, we will.
- */
- unsigned int new_start = start + j - i;
- unsigned int new_cc = cc == 220 ? HB_MODIFIED_COMBINING_CLASS_CCC22 : HB_MODIFIED_COMBINING_CLASS_CCC26;
- while (start < new_start)
- {
- _hb_glyph_info_set_modified_combining_class (&info[start], new_cc);
- start++;
- }
-
- i = j;
- }
-}
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
-{
- collect_features_arabic,
- nullptr, /* override_features */
- data_create_arabic,
- data_destroy_arabic,
- nullptr, /* preprocess_text */
- postprocess_glyphs_arabic,
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- nullptr, /* compose */
- setup_masks_arabic,
- HB_TAG_NONE, /* gpos_tag */
- reorder_marks_arabic,
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
- true, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh
deleted file mode 100644
index 5bf6ff6338..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-arabic.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_ARABIC_HH
-#define HB_OT_SHAPE_COMPLEX_ARABIC_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex.hh"
-
-
-struct arabic_shape_plan_t;
-
-HB_INTERNAL void *
-data_create_arabic (const hb_ot_shape_plan_t *plan);
-
-HB_INTERNAL void
-data_destroy_arabic (void *data);
-
-HB_INTERNAL void
-setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
- hb_buffer_t *buffer,
- hb_script_t script);
-
-#endif /* HB_OT_SHAPE_COMPLEX_ARABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc
deleted file mode 100644
index a755aea098..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-default.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright © 2010,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex.hh"
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- nullptr, /* compose */
- nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
- true, /* fallback_position */
-};
-
-/* Same as default but no mark advance zeroing / fallback positioning.
- * Dumbest shaper ever, basically. */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- nullptr, /* compose */
- nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
deleted file mode 100644
index 3bc9e9b961..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hangul.cc
+++ /dev/null
@@ -1,436 +0,0 @@
-/*
- * Copyright © 2013 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex.hh"
-
-
-/* Hangul shaper */
-
-
-/* Same order as the feature array below */
-enum {
- _JMO,
-
- LJMO,
- VJMO,
- TJMO,
-
- FIRST_HANGUL_FEATURE = LJMO,
- HANGUL_FEATURE_COUNT = TJMO + 1
-};
-
-static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] =
-{
- HB_TAG_NONE,
- HB_TAG('l','j','m','o'),
- HB_TAG('v','j','m','o'),
- HB_TAG('t','j','m','o')
-};
-
-static void
-collect_features_hangul (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
- map->add_feature (hangul_features[i]);
-}
-
-static void
-override_features_hangul (hb_ot_shape_planner_t *plan)
-{
- /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
- * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
- * in calt, which is not desirable. */
- plan->map.disable_feature (HB_TAG('c','a','l','t'));
-}
-
-struct hangul_shape_plan_t
-{
- hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
-};
-
-static void *
-data_create_hangul (const hb_ot_shape_plan_t *plan)
-{
- hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) hb_calloc (1, sizeof (hangul_shape_plan_t));
- if (unlikely (!hangul_plan))
- return nullptr;
-
- for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++)
- hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]);
-
- return hangul_plan;
-}
-
-static void
-data_destroy_hangul (void *data)
-{
- hb_free (data);
-}
-
-/* Constants for algorithmic hangul syllable [de]composition. */
-#define LBase 0x1100u
-#define VBase 0x1161u
-#define TBase 0x11A7u
-#define LCount 19u
-#define VCount 21u
-#define TCount 28u
-#define SBase 0xAC00u
-#define NCount (VCount * TCount)
-#define SCount (LCount * NCount)
-
-#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
-#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
-#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
-#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
-
-#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
-#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
-#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
-
-#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
-
-/* buffer var allocations */
-#define hangul_shaping_feature() complex_var_u8_auxiliary() /* hangul jamo shaping feature */
-
-static bool
-is_zero_width_char (hb_font_t *font,
- hb_codepoint_t unicode)
-{
- hb_codepoint_t glyph;
- return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0;
-}
-
-static void
-preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature);
-
- /* Hangul syllables come in two shapes: LV, and LVT. Of those:
- *
- * - LV can be precomposed, or decomposed. Lets call those
- * <LV> and <L,V>,
- * - LVT can be fully precomposed, partially precomposed, or
- * fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>.
- *
- * The composition / decomposition is mechanical. However, not
- * all <L,V> sequences compose, and not all <LV,T> sequences
- * compose.
- *
- * Here are the specifics:
- *
- * - <L>: U+1100..115F, U+A960..A97F
- * - <V>: U+1160..11A7, U+D7B0..D7C7
- * - <T>: U+11A8..11FF, U+D7CB..D7FB
- *
- * - Only the <L,V> sequences for some of the U+11xx ranges combine.
- * - Only <LV,T> sequences for some of the Ts in U+11xx range combine.
- *
- * Here is what we want to accomplish in this shaper:
- *
- * - If the whole syllable can be precomposed, do that,
- * - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features.
- * - If a valid syllable is followed by a Hangul tone mark, reorder the tone
- * mark to precede the whole syllable - unless it is a zero-width glyph, in
- * which case we leave it untouched, assuming it's designed to overstrike.
- *
- * That is, of the different possible syllables:
- *
- * <L>
- * <L,V>
- * <L,V,T>
- * <LV>
- * <LVT>
- * <LV, T>
- *
- * - <L> needs no work.
- *
- * - <LV> and <LVT> can stay the way they are if the font supports them, otherwise we
- * should fully decompose them if font supports.
- *
- * - <L,V> and <L,V,T> we should compose if the whole thing can be composed.
- *
- * - <LV,T> we should compose if the whole thing can be composed, otherwise we should
- * decompose.
- */
-
- buffer->clear_output ();
- unsigned int start = 0, end = 0; /* Extent of most recently seen syllable;
- * valid only if start < end
- */
- unsigned int count = buffer->len;
-
- for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
- {
- hb_codepoint_t u = buffer->cur().codepoint;
-
- if (isHangulTone (u))
- {
- /*
- * We could cache the width of the tone marks and the existence of dotted-circle,
- * but the use of the Hangul tone mark characters seems to be rare enough that
- * I didn't bother for now.
- */
- if (start < end && end == buffer->out_len)
- {
- /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
- buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
- if (unlikely (!buffer->next_glyph ())) break;
- if (!is_zero_width_char (font, u))
- {
- buffer->merge_out_clusters (start, end + 1);
- hb_glyph_info_t *info = buffer->out_info;
- hb_glyph_info_t tone = info[end];
- memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
- info[start] = tone;
- }
- }
- else
- {
- /* No valid syllable as base for tone mark; try to insert dotted circle. */
- if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) &&
- font->has_glyph (0x25CCu))
- {
- hb_codepoint_t chars[2];
- if (!is_zero_width_char (font, u))
- {
- chars[0] = u;
- chars[1] = 0x25CCu;
- } else
- {
- chars[0] = 0x25CCu;
- chars[1] = u;
- }
- (void) buffer->replace_glyphs (1, 2, chars);
- }
- else
- {
- /* No dotted circle available in the font; just leave tone mark untouched. */
- (void) buffer->next_glyph ();
- }
- }
- start = end = buffer->out_len;
- continue;
- }
-
- start = buffer->out_len; /* Remember current position as a potential syllable start;
- * will only be used if we set end to a later position.
- */
-
- if (isL (u) && buffer->idx + 1 < count)
- {
- hb_codepoint_t l = u;
- hb_codepoint_t v = buffer->cur(+1).codepoint;
- if (isV (v))
- {
- /* Have <L,V> or <L,V,T>. */
- hb_codepoint_t t = 0;
- unsigned int tindex = 0;
- if (buffer->idx + 2 < count)
- {
- t = buffer->cur(+2).codepoint;
- if (isT (t))
- tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */
- else
- t = 0; /* The next character was not a trailing jamo. */
- }
- buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2));
-
- /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */
- if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t)))
- {
- /* Try to compose; if this succeeds, end is set to start+1. */
- hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
- if (font->has_glyph (s))
- {
- (void) buffer->replace_glyphs (t ? 3 : 2, 1, &s);
- end = start + 1;
- continue;
- }
- }
-
- /* We didn't compose, either because it's an Old Hangul syllable without a
- * precomposed character in Unicode, or because the font didn't support the
- * necessary precomposed glyph.
- * Set jamo features on the individual glyphs, and advance past them.
- */
- buffer->cur().hangul_shaping_feature() = LJMO;
- (void) buffer->next_glyph ();
- buffer->cur().hangul_shaping_feature() = VJMO;
- (void) buffer->next_glyph ();
- if (t)
- {
- buffer->cur().hangul_shaping_feature() = TJMO;
- (void) buffer->next_glyph ();
- end = start + 3;
- }
- else
- end = start + 2;
- if (unlikely (!buffer->successful))
- break;
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
- buffer->merge_out_clusters (start, end);
- continue;
- }
- }
-
- else if (isCombinedS (u))
- {
- /* Have <LV>, <LVT>, or <LV,T> */
- hb_codepoint_t s = u;
- bool has_glyph = font->has_glyph (s);
- unsigned int lindex = (s - SBase) / NCount;
- unsigned int nindex = (s - SBase) % NCount;
- unsigned int vindex = nindex / TCount;
- unsigned int tindex = nindex % TCount;
-
- if (!tindex &&
- buffer->idx + 1 < count &&
- isCombiningT (buffer->cur(+1).codepoint))
- {
- /* <LV,T>, try to combine. */
- unsigned int new_tindex = buffer->cur(+1).codepoint - TBase;
- hb_codepoint_t new_s = s + new_tindex;
- if (font->has_glyph (new_s))
- {
- (void) buffer->replace_glyphs (2, 1, &new_s);
- end = start + 1;
- continue;
- }
- else
- buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
- }
-
- /* Otherwise, decompose if font doesn't support <LV> or <LVT>,
- * or if having non-combining <LV,T>. Note that we already handled
- * combining <LV,T> above. */
- if (!has_glyph ||
- (!tindex &&
- buffer->idx + 1 < count &&
- isT (buffer->cur(+1).codepoint)))
- {
- hb_codepoint_t decomposed[3] = {LBase + lindex,
- VBase + vindex,
- TBase + tindex};
- if (font->has_glyph (decomposed[0]) &&
- font->has_glyph (decomposed[1]) &&
- (!tindex || font->has_glyph (decomposed[2])))
- {
- unsigned int s_len = tindex ? 3 : 2;
- (void) buffer->replace_glyphs (1, s_len, decomposed);
-
- /* If we decomposed an LV because of a non-combining T following,
- * we want to include this T in the syllable.
- */
- if (has_glyph && !tindex)
- {
- (void) buffer->next_glyph ();
- s_len++;
- }
- if (unlikely (!buffer->successful))
- break;
-
- /* We decomposed S: apply jamo features to the individual glyphs
- * that are now in buffer->out_info.
- */
- hb_glyph_info_t *info = buffer->out_info;
- end = start + s_len;
-
- unsigned int i = start;
- info[i++].hangul_shaping_feature() = LJMO;
- info[i++].hangul_shaping_feature() = VJMO;
- if (i < end)
- info[i++].hangul_shaping_feature() = TJMO;
-
- if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
- buffer->merge_out_clusters (start, end);
- continue;
- }
- else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
- buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
- }
-
- if (has_glyph)
- {
- /* We didn't decompose the S, so just advance past it and fall through. */
- end = start + 1;
- }
- }
-
- /* Didn't find a recognizable syllable, so we leave end <= start;
- * this will prevent tone-mark reordering happening.
- */
- (void) buffer->next_glyph ();
- }
- buffer->sync ();
-}
-
-static void
-setup_masks_hangul (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data;
-
- if (likely (hangul_plan))
- {
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++, info++)
- info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()];
- }
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hangul =
-{
- collect_features_hangul,
- override_features_hangul,
- data_create_hangul,
- data_destroy_hangul,
- preprocess_text_hangul,
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
- nullptr, /* decompose */
- nullptr, /* compose */
- setup_masks_hangul,
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
deleted file mode 100644
index 334d3ded82..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-hebrew.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright © 2010,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex.hh"
-
-
-static bool
-compose_hebrew (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t a,
- hb_codepoint_t b,
- hb_codepoint_t *ab)
-{
- /* Hebrew presentation-form shaping.
- * https://bugzilla.mozilla.org/show_bug.cgi?id=728866
- * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
- * Note that some letters do not have a dagesh presForm encoded.
- */
- static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
- 0xFB30u, /* ALEF */
- 0xFB31u, /* BET */
- 0xFB32u, /* GIMEL */
- 0xFB33u, /* DALET */
- 0xFB34u, /* HE */
- 0xFB35u, /* VAV */
- 0xFB36u, /* ZAYIN */
- 0x0000u, /* HET */
- 0xFB38u, /* TET */
- 0xFB39u, /* YOD */
- 0xFB3Au, /* FINAL KAF */
- 0xFB3Bu, /* KAF */
- 0xFB3Cu, /* LAMED */
- 0x0000u, /* FINAL MEM */
- 0xFB3Eu, /* MEM */
- 0x0000u, /* FINAL NUN */
- 0xFB40u, /* NUN */
- 0xFB41u, /* SAMEKH */
- 0x0000u, /* AYIN */
- 0xFB43u, /* FINAL PE */
- 0xFB44u, /* PE */
- 0x0000u, /* FINAL TSADI */
- 0xFB46u, /* TSADI */
- 0xFB47u, /* QOF */
- 0xFB48u, /* RESH */
- 0xFB49u, /* SHIN */
- 0xFB4Au /* TAV */
- };
-
- bool found = (bool) c->unicode->compose (a, b, ab);
-
-#ifdef HB_NO_OT_SHAPE_COMPLEX_HEBREW_FALLBACK
- return found;
-#endif
-
- if (!found && !c->plan->has_gpos_mark)
- {
- /* Special-case Hebrew presentation forms that are excluded from
- * standard normalization, but wanted for old fonts. */
- switch (b) {
- case 0x05B4u: /* HIRIQ */
- if (a == 0x05D9u) { /* YOD */
- *ab = 0xFB1Du;
- found = true;
- }
- break;
- case 0x05B7u: /* patah */
- if (a == 0x05F2u) { /* YIDDISH YOD YOD */
- *ab = 0xFB1Fu;
- found = true;
- } else if (a == 0x05D0u) { /* ALEF */
- *ab = 0xFB2Eu;
- found = true;
- }
- break;
- case 0x05B8u: /* QAMATS */
- if (a == 0x05D0u) { /* ALEF */
- *ab = 0xFB2Fu;
- found = true;
- }
- break;
- case 0x05B9u: /* HOLAM */
- if (a == 0x05D5u) { /* VAV */
- *ab = 0xFB4Bu;
- found = true;
- }
- break;
- case 0x05BCu: /* DAGESH */
- if (a >= 0x05D0u && a <= 0x05EAu) {
- *ab = sDageshForms[a - 0x05D0u];
- found = (*ab != 0);
- } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
- *ab = 0xFB2Cu;
- found = true;
- } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
- *ab = 0xFB2Du;
- found = true;
- }
- break;
- case 0x05BFu: /* RAFE */
- switch (a) {
- case 0x05D1u: /* BET */
- *ab = 0xFB4Cu;
- found = true;
- break;
- case 0x05DBu: /* KAF */
- *ab = 0xFB4Du;
- found = true;
- break;
- case 0x05E4u: /* PE */
- *ab = 0xFB4Eu;
- found = true;
- break;
- }
- break;
- case 0x05C1u: /* SHIN DOT */
- if (a == 0x05E9u) { /* SHIN */
- *ab = 0xFB2Au;
- found = true;
- } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
- *ab = 0xFB2Cu;
- found = true;
- }
- break;
- case 0x05C2u: /* SIN DOT */
- if (a == 0x05E9u) { /* SHIN */
- *ab = 0xFB2Bu;
- found = true;
- } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
- *ab = 0xFB2Du;
- found = true;
- }
- break;
- }
- }
-
- return found;
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_hebrew =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- compose_hebrew,
- nullptr, /* setup_masks */
- HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
- true, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
deleted file mode 100644
index 74bf3ca0fa..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-machine.hh
+++ /dev/null
@@ -1,603 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-indic-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH
-
-#include "hb.hh"
-
-enum indic_syllable_type_t {
- indic_consonant_syllable,
- indic_vowel_syllable,
- indic_standalone_cluster,
- indic_symbol_cluster,
- indic_broken_cluster,
- indic_non_indic_cluster,
-};
-
-
-#line 45 "hb-ot-shape-complex-indic-machine.hh"
-#define indic_syllable_machine_ex_A 10u
-#define indic_syllable_machine_ex_C 1u
-#define indic_syllable_machine_ex_CM 17u
-#define indic_syllable_machine_ex_CS 19u
-#define indic_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define indic_syllable_machine_ex_H 4u
-#define indic_syllable_machine_ex_M 7u
-#define indic_syllable_machine_ex_N 3u
-#define indic_syllable_machine_ex_PLACEHOLDER 11u
-#define indic_syllable_machine_ex_RS 13u
-#define indic_syllable_machine_ex_Ra 16u
-#define indic_syllable_machine_ex_Repha 15u
-#define indic_syllable_machine_ex_SM 8u
-#define indic_syllable_machine_ex_Symbol 18u
-#define indic_syllable_machine_ex_V 2u
-#define indic_syllable_machine_ex_ZWJ 6u
-#define indic_syllable_machine_ex_ZWNJ 5u
-
-
-#line 65 "hb-ot-shape-complex-indic-machine.hh"
-static const unsigned char _indic_syllable_machine_trans_keys[] = {
- 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u,
- 4u, 13u, 4u, 8u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 6u, 6u, 16u, 16u,
- 4u, 8u, 4u, 13u, 4u, 13u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u,
- 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 4u, 13u, 8u, 8u, 5u, 7u, 5u, 8u,
- 4u, 8u, 6u, 6u, 16u, 16u, 4u, 8u, 4u, 8u, 5u, 8u, 8u, 8u, 1u, 19u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u,
- 1u, 16u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u,
- 3u, 10u, 5u, 10u, 3u, 17u, 3u, 17u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u,
- 1u, 16u, 3u, 10u, 4u, 10u, 5u, 10u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u,
- 5u, 10u, 3u, 17u, 3u, 17u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u,
- 3u, 17u, 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u,
- 4u, 10u, 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u,
- 3u, 17u, 4u, 13u, 4u, 8u, 3u, 17u, 3u, 17u, 4u, 17u, 1u, 16u, 3u, 17u,
- 1u, 16u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 1u, 16u, 3u, 10u, 4u, 10u,
- 5u, 10u, 3u, 17u, 4u, 10u, 5u, 10u, 5u, 10u, 3u, 10u, 5u, 10u, 1u, 17u,
- 3u, 17u, 1u, 17u, 4u, 13u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 3u, 10u,
- 5u, 10u, 5u, 10u, 10u, 10u, 5u, 10u, 1u, 16u, 0
-};
-
-static const char _indic_syllable_machine_key_spans[] = {
- 1, 5, 3, 4, 5, 1, 1, 5,
- 10, 5, 1, 3, 4, 5, 1, 1,
- 5, 10, 10, 10, 1, 3, 4, 5,
- 1, 1, 5, 5, 10, 1, 3, 4,
- 5, 1, 1, 5, 5, 4, 1, 19,
- 15, 15, 14, 16, 6, 6, 1, 6,
- 16, 16, 16, 8, 7, 6, 7, 6,
- 8, 6, 15, 15, 15, 15, 14, 16,
- 15, 15, 14, 16, 6, 1, 6, 16,
- 16, 8, 7, 6, 7, 6, 6, 8,
- 6, 15, 15, 5, 15, 15, 14, 16,
- 15, 16, 6, 1, 6, 16, 16, 8,
- 7, 6, 15, 7, 6, 6, 8, 6,
- 15, 10, 5, 15, 15, 14, 16, 15,
- 16, 6, 1, 6, 16, 16, 8, 7,
- 6, 15, 7, 6, 6, 8, 6, 17,
- 15, 17, 10, 6, 1, 6, 16, 8,
- 6, 6, 1, 6, 16
-};
-
-static const short _indic_syllable_machine_index_offsets[] = {
- 0, 2, 8, 12, 17, 23, 25, 27,
- 33, 44, 50, 52, 56, 61, 67, 69,
- 71, 77, 88, 99, 110, 112, 116, 121,
- 127, 129, 131, 137, 143, 154, 156, 160,
- 165, 171, 173, 175, 181, 187, 192, 194,
- 214, 230, 246, 261, 278, 285, 292, 294,
- 301, 318, 335, 352, 361, 369, 376, 384,
- 391, 400, 407, 423, 439, 455, 471, 486,
- 503, 519, 535, 550, 567, 574, 576, 583,
- 600, 617, 626, 634, 641, 649, 656, 663,
- 672, 679, 695, 711, 717, 733, 749, 764,
- 781, 797, 814, 821, 823, 830, 847, 864,
- 873, 881, 888, 904, 912, 919, 926, 935,
- 942, 958, 969, 975, 991, 1007, 1022, 1039,
- 1055, 1072, 1079, 1081, 1088, 1105, 1122, 1131,
- 1139, 1146, 1162, 1170, 1177, 1184, 1193, 1200,
- 1218, 1234, 1252, 1263, 1270, 1272, 1279, 1296,
- 1305, 1312, 1319, 1321, 1328
-};
-
-static const unsigned char _indic_syllable_machine_indicies[] = {
- 1, 0, 2, 3, 3, 4, 1, 0,
- 3, 3, 4, 0, 3, 3, 4, 1,
- 0, 5, 3, 3, 4, 1, 0, 6,
- 0, 7, 0, 8, 3, 3, 4, 1,
- 0, 2, 3, 3, 4, 1, 0, 0,
- 0, 0, 9, 0, 11, 12, 12, 13,
- 14, 10, 14, 10, 12, 12, 13, 10,
- 12, 12, 13, 14, 10, 15, 12, 12,
- 13, 14, 10, 16, 10, 17, 10, 18,
- 12, 12, 13, 14, 10, 11, 12, 12,
- 13, 14, 10, 10, 10, 10, 19, 10,
- 11, 12, 12, 13, 14, 10, 10, 10,
- 10, 20, 10, 22, 23, 23, 24, 25,
- 21, 21, 21, 21, 26, 21, 25, 21,
- 23, 23, 24, 27, 23, 23, 24, 25,
- 21, 28, 23, 23, 24, 25, 21, 29,
- 21, 30, 21, 22, 23, 23, 24, 25,
- 21, 31, 23, 23, 24, 25, 21, 33,
- 34, 34, 35, 36, 32, 32, 32, 32,
- 37, 32, 36, 32, 34, 34, 35, 32,
- 34, 34, 35, 36, 32, 38, 34, 34,
- 35, 36, 32, 39, 32, 40, 32, 33,
- 34, 34, 35, 36, 32, 41, 34, 34,
- 35, 36, 32, 23, 23, 24, 1, 0,
- 43, 42, 45, 46, 47, 48, 49, 50,
- 24, 25, 44, 51, 52, 52, 26, 44,
- 53, 54, 55, 56, 57, 44, 59, 60,
- 61, 62, 4, 1, 58, 63, 58, 58,
- 9, 58, 58, 58, 64, 58, 65, 60,
- 66, 66, 4, 1, 58, 63, 58, 58,
- 58, 58, 58, 58, 64, 58, 60, 66,
- 66, 4, 1, 58, 63, 58, 58, 58,
- 58, 58, 58, 64, 58, 45, 58, 58,
- 58, 67, 68, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 69, 69,
- 58, 1, 58, 63, 58, 63, 58, 58,
- 70, 58, 63, 58, 63, 58, 63, 58,
- 58, 58, 58, 63, 58, 45, 58, 71,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 58, 58, 58, 58, 45, 58, 45, 58,
- 58, 58, 69, 69, 58, 1, 58, 63,
- 58, 58, 58, 58, 58, 45, 58, 45,
- 58, 58, 58, 69, 68, 58, 1, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 72, 7, 73, 74, 4, 1, 58, 63,
- 58, 7, 73, 74, 4, 1, 58, 63,
- 58, 73, 73, 4, 1, 58, 63, 58,
- 75, 76, 76, 4, 1, 58, 63, 58,
- 67, 77, 58, 1, 58, 63, 58, 67,
- 58, 69, 69, 58, 1, 58, 63, 58,
- 69, 77, 58, 1, 58, 63, 58, 59,
- 60, 66, 66, 4, 1, 58, 63, 58,
- 58, 58, 58, 58, 58, 64, 58, 59,
- 60, 61, 66, 4, 1, 58, 63, 58,
- 58, 9, 58, 58, 58, 64, 58, 79,
- 80, 81, 82, 13, 14, 78, 83, 78,
- 78, 20, 78, 78, 78, 84, 78, 85,
- 80, 86, 82, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 82, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 88, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 90,
- 80, 91, 92, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 93,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 80,
- 86, 86, 13, 14, 78, 83, 78, 78,
- 78, 78, 78, 78, 84, 78, 87, 78,
- 78, 78, 94, 89, 78, 14, 78, 83,
- 78, 78, 78, 78, 78, 87, 78, 83,
- 78, 78, 95, 78, 83, 78, 83, 78,
- 83, 78, 78, 78, 78, 83, 78, 87,
- 78, 96, 78, 94, 94, 78, 14, 78,
- 83, 78, 78, 78, 78, 78, 87, 78,
- 87, 78, 78, 78, 94, 94, 78, 14,
- 78, 83, 78, 78, 78, 78, 78, 87,
- 78, 97, 17, 98, 99, 13, 14, 78,
- 83, 78, 17, 98, 99, 13, 14, 78,
- 83, 78, 98, 98, 13, 14, 78, 83,
- 78, 100, 101, 101, 13, 14, 78, 83,
- 78, 88, 102, 78, 14, 78, 83, 78,
- 94, 94, 78, 14, 78, 83, 78, 88,
- 78, 94, 94, 78, 14, 78, 83, 78,
- 94, 102, 78, 14, 78, 83, 78, 90,
- 80, 86, 86, 13, 14, 78, 83, 78,
- 78, 78, 78, 78, 78, 84, 78, 90,
- 80, 91, 86, 13, 14, 78, 83, 78,
- 78, 19, 78, 78, 78, 84, 78, 11,
- 12, 12, 13, 14, 78, 79, 80, 86,
- 82, 13, 14, 78, 83, 78, 78, 78,
- 78, 78, 78, 84, 78, 104, 48, 105,
- 105, 24, 25, 103, 51, 103, 103, 103,
- 103, 103, 103, 55, 103, 48, 105, 105,
- 24, 25, 103, 51, 103, 103, 103, 103,
- 103, 103, 55, 103, 106, 103, 103, 103,
- 107, 108, 103, 25, 103, 51, 103, 103,
- 103, 103, 103, 106, 103, 47, 48, 109,
- 110, 24, 25, 103, 51, 103, 103, 26,
- 103, 103, 103, 55, 103, 106, 103, 103,
- 103, 111, 108, 103, 25, 103, 51, 103,
- 103, 103, 103, 103, 106, 103, 51, 103,
- 103, 112, 103, 51, 103, 51, 103, 51,
- 103, 103, 103, 103, 51, 103, 106, 103,
- 113, 103, 111, 111, 103, 25, 103, 51,
- 103, 103, 103, 103, 103, 106, 103, 106,
- 103, 103, 103, 111, 111, 103, 25, 103,
- 51, 103, 103, 103, 103, 103, 106, 103,
- 114, 30, 115, 116, 24, 25, 103, 51,
- 103, 30, 115, 116, 24, 25, 103, 51,
- 103, 115, 115, 24, 25, 103, 51, 103,
- 47, 48, 105, 105, 24, 25, 103, 51,
- 103, 103, 103, 103, 103, 103, 55, 103,
- 117, 118, 118, 24, 25, 103, 51, 103,
- 107, 119, 103, 25, 103, 51, 103, 111,
- 111, 103, 25, 103, 51, 103, 107, 103,
- 111, 111, 103, 25, 103, 51, 103, 111,
- 119, 103, 25, 103, 51, 103, 47, 48,
- 109, 105, 24, 25, 103, 51, 103, 103,
- 26, 103, 103, 103, 55, 103, 22, 23,
- 23, 24, 25, 120, 120, 120, 120, 26,
- 120, 22, 23, 23, 24, 25, 120, 122,
- 123, 124, 125, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 128,
- 123, 125, 125, 35, 36, 121, 126, 121,
- 121, 121, 121, 121, 121, 127, 121, 123,
- 125, 125, 35, 36, 121, 126, 121, 121,
- 121, 121, 121, 121, 127, 121, 129, 121,
- 121, 121, 130, 131, 121, 36, 121, 126,
- 121, 121, 121, 121, 121, 129, 121, 122,
- 123, 124, 52, 35, 36, 121, 126, 121,
- 121, 37, 121, 121, 121, 127, 121, 129,
- 121, 121, 121, 132, 131, 121, 36, 121,
- 126, 121, 121, 121, 121, 121, 129, 121,
- 126, 121, 121, 133, 121, 126, 121, 126,
- 121, 126, 121, 121, 121, 121, 126, 121,
- 129, 121, 134, 121, 132, 132, 121, 36,
- 121, 126, 121, 121, 121, 121, 121, 129,
- 121, 129, 121, 121, 121, 132, 132, 121,
- 36, 121, 126, 121, 121, 121, 121, 121,
- 129, 121, 135, 40, 136, 137, 35, 36,
- 121, 126, 121, 40, 136, 137, 35, 36,
- 121, 126, 121, 136, 136, 35, 36, 121,
- 126, 121, 122, 123, 125, 125, 35, 36,
- 121, 126, 121, 121, 121, 121, 121, 121,
- 127, 121, 138, 139, 139, 35, 36, 121,
- 126, 121, 130, 140, 121, 36, 121, 126,
- 121, 132, 132, 121, 36, 121, 126, 121,
- 130, 121, 132, 132, 121, 36, 121, 126,
- 121, 132, 140, 121, 36, 121, 126, 121,
- 45, 46, 47, 48, 109, 105, 24, 25,
- 103, 51, 52, 52, 26, 103, 103, 45,
- 55, 103, 59, 141, 61, 62, 4, 1,
- 58, 63, 58, 58, 9, 58, 58, 58,
- 64, 58, 45, 46, 47, 48, 142, 143,
- 24, 144, 58, 145, 58, 52, 26, 58,
- 58, 45, 55, 58, 22, 146, 146, 24,
- 144, 58, 63, 58, 58, 26, 58, 145,
- 58, 58, 147, 58, 145, 58, 145, 58,
- 145, 58, 58, 58, 58, 145, 58, 45,
- 58, 71, 22, 146, 146, 24, 144, 58,
- 63, 58, 58, 58, 58, 58, 45, 58,
- 149, 148, 150, 150, 148, 43, 148, 151,
- 148, 150, 150, 148, 43, 148, 151, 148,
- 151, 148, 148, 152, 148, 151, 148, 151,
- 148, 151, 148, 148, 148, 148, 151, 148,
- 45, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 52, 120, 120, 120, 120, 45,
- 120, 0
-};
-
-static const unsigned char _indic_syllable_machine_trans_targs[] = {
- 39, 45, 50, 2, 51, 5, 6, 53,
- 57, 58, 39, 67, 11, 73, 68, 14,
- 15, 75, 80, 81, 84, 39, 89, 21,
- 95, 90, 98, 39, 24, 25, 97, 103,
- 39, 112, 30, 118, 113, 121, 33, 34,
- 120, 126, 39, 137, 39, 40, 60, 85,
- 87, 105, 106, 91, 107, 127, 128, 99,
- 135, 140, 39, 41, 43, 8, 59, 46,
- 54, 42, 1, 44, 48, 0, 47, 49,
- 52, 3, 4, 55, 7, 56, 39, 61,
- 63, 18, 83, 69, 76, 62, 9, 64,
- 78, 71, 65, 17, 82, 66, 10, 70,
- 72, 74, 12, 13, 77, 16, 79, 39,
- 86, 26, 88, 101, 93, 19, 104, 20,
- 92, 94, 96, 22, 23, 100, 27, 102,
- 39, 39, 108, 110, 28, 35, 114, 122,
- 109, 111, 124, 116, 29, 115, 117, 119,
- 31, 32, 123, 36, 125, 129, 130, 134,
- 131, 132, 37, 133, 39, 136, 38, 138,
- 139
-};
-
-static const char _indic_syllable_machine_trans_actions[] = {
- 1, 0, 2, 0, 2, 0, 0, 2,
- 2, 2, 3, 2, 0, 2, 0, 0,
- 0, 2, 2, 2, 2, 4, 2, 0,
- 5, 0, 5, 6, 0, 0, 5, 2,
- 7, 2, 0, 2, 0, 2, 0, 0,
- 2, 2, 8, 0, 11, 2, 2, 5,
- 0, 12, 12, 0, 2, 5, 2, 5,
- 2, 0, 13, 2, 0, 0, 2, 0,
- 2, 2, 0, 2, 2, 0, 0, 2,
- 2, 0, 0, 0, 0, 2, 14, 2,
- 0, 0, 2, 0, 2, 2, 0, 2,
- 2, 2, 2, 0, 2, 2, 0, 0,
- 2, 2, 0, 0, 0, 0, 2, 15,
- 5, 0, 5, 2, 2, 0, 5, 0,
- 0, 2, 5, 0, 0, 0, 0, 2,
- 16, 17, 2, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 0, 0, 2, 2,
- 0, 0, 0, 0, 2, 0, 18, 18,
- 0, 0, 0, 0, 19, 2, 0, 0,
- 0
-};
-
-static const char _indic_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const char _indic_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 10,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const short _indic_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 22, 22, 28, 22, 22,
- 22, 22, 22, 22, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 1, 43, 0,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, 104,
- 104, 121, 121, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 122, 104,
- 59, 59, 59, 59, 59, 59, 59, 149,
- 149, 149, 149, 149, 121
-};
-
-static const int indic_syllable_machine_start = 39;
-static const int indic_syllable_machine_first_final = 39;
-static const int indic_syllable_machine_error = -1;
-
-static const int indic_syllable_machine_en_main = 39;
-
-
-#line 46 "hb-ot-shape-complex-indic-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-indic-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_indic (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 440 "hb-ot-shape-complex-indic-machine.hh"
- {
- cs = indic_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-indic-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 456 "hb-ot-shape-complex-indic-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const unsigned char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _indic_syllable_machine_from_state_actions[cs] ) {
- case 10:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 470 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- _keys = _indic_syllable_machine_trans_keys + (cs<<1);
- _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
-
- _slen = _indic_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
- ( info[p].indic_category()) <= _keys[1] ?
- ( info[p].indic_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _indic_syllable_machine_trans_targs[_trans];
-
- if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _indic_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 11:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 13:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
- break;
- case 14:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
- break;
- case 17:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
- break;
- case 19:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
- break;
- case 15:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_broken_cluster); }}
- break;
- case 16:
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
- break;
- case 1:
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
- break;
- case 3:
-#line 94 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
- break;
- case 7:
-#line 95 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
- break;
- case 8:
-#line 96 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
- break;
- case 4:
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); }}
- break;
- case 6:
-#line 1 "NONE"
- { switch( act ) {
- case 1:
- {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
- break;
- case 5:
- {{p = ((te))-1;} found_syllable (indic_broken_cluster); }
- break;
- case 6:
- {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
- break;
- }
- }
- break;
- case 18:
-#line 1 "NONE"
- {te = p+1;}
-#line 93 "hb-ot-shape-complex-indic-machine.rl"
- {act = 1;}
- break;
- case 5:
-#line 1 "NONE"
- {te = p+1;}
-#line 97 "hb-ot-shape-complex-indic-machine.rl"
- {act = 5;}
- break;
- case 12:
-#line 1 "NONE"
- {te = p+1;}
-#line 98 "hb-ot-shape-complex-indic-machine.rl"
- {act = 6;}
- break;
-#line 573 "hb-ot-shape-complex-indic-machine.hh"
- }
-
-_again:
- switch ( _indic_syllable_machine_to_state_actions[cs] ) {
- case 9:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 582 "hb-ot-shape-complex-indic-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _indic_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-indic-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
deleted file mode 100644
index 326aa9f96e..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic-table.cc
+++ /dev/null
@@ -1,501 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # IndicPositionalCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-indic.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-
-#define ISC_A INDIC_SYLLABIC_CATEGORY_AVAGRAHA /* 17 chars; Avagraha */
-#define ISC_Bi INDIC_SYLLABIC_CATEGORY_BINDU /* 91 chars; Bindu */
-#define ISC_BJN INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER /* 20 chars; Brahmi_Joining_Number */
-#define ISC_Ca INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK /* 59 chars; Cantillation_Mark */
-#define ISC_C INDIC_SYLLABIC_CATEGORY_CONSONANT /* 2206 chars; Consonant */
-#define ISC_CD INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD /* 14 chars; Consonant_Dead */
-#define ISC_CF INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL /* 70 chars; Consonant_Final */
-#define ISC_CHL INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER /* 5 chars; Consonant_Head_Letter */
-#define ISC_CIP INDIC_SYLLABIC_CATEGORY_CONSONANT_INITIAL_POSTFIXED /* 1 chars; Consonant_Initial_Postfixed */
-#define ISC_CK INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER /* 2 chars; Consonant_Killer */
-#define ISC_CM INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL /* 31 chars; Consonant_Medial */
-#define ISC_CP INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER /* 22 chars; Consonant_Placeholder */
-#define ISC_CPR INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA /* 3 chars; Consonant_Preceding_Repha */
-#define ISC_CPrf INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED /* 10 chars; Consonant_Prefixed */
-#define ISC_CS INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED /* 94 chars; Consonant_Subjoined */
-#define ISC_CSR INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA /* 1 chars; Consonant_Succeeding_Repha */
-#define ISC_CWS INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER /* 8 chars; Consonant_With_Stacker */
-#define ISC_GM INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK /* 3 chars; Gemination_Mark */
-#define ISC_IS INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER /* 12 chars; Invisible_Stacker */
-#define ISC_ZWJ INDIC_SYLLABIC_CATEGORY_JOINER /* 1 chars; Joiner */
-#define ISC_ML INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER /* 1 chars; Modifying_Letter */
-#define ISC_ZWNJ INDIC_SYLLABIC_CATEGORY_NON_JOINER /* 1 chars; Non_Joiner */
-#define ISC_N INDIC_SYLLABIC_CATEGORY_NUKTA /* 32 chars; Nukta */
-#define ISC_Nd INDIC_SYLLABIC_CATEGORY_NUMBER /* 491 chars; Number */
-#define ISC_NJ INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER /* 1 chars; Number_Joiner */
-#define ISC_x INDIC_SYLLABIC_CATEGORY_OTHER /* 1 chars; Other */
-#define ISC_PK INDIC_SYLLABIC_CATEGORY_PURE_KILLER /* 25 chars; Pure_Killer */
-#define ISC_RS INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER /* 2 chars; Register_Shifter */
-#define ISC_SM INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER /* 25 chars; Syllable_Modifier */
-#define ISC_TL INDIC_SYLLABIC_CATEGORY_TONE_LETTER /* 7 chars; Tone_Letter */
-#define ISC_TM INDIC_SYLLABIC_CATEGORY_TONE_MARK /* 42 chars; Tone_Mark */
-#define ISC_V INDIC_SYLLABIC_CATEGORY_VIRAMA /* 27 chars; Virama */
-#define ISC_Vs INDIC_SYLLABIC_CATEGORY_VISARGA /* 35 chars; Visarga */
-#define ISC_Vo INDIC_SYLLABIC_CATEGORY_VOWEL /* 30 chars; Vowel */
-#define ISC_M INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT /* 686 chars; Vowel_Dependent */
-#define ISC_VI INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT /* 486 chars; Vowel_Independent */
-
-#define IMC_B INDIC_MATRA_CATEGORY_BOTTOM /* 352 chars; Bottom */
-#define IMC_BL INDIC_MATRA_CATEGORY_BOTTOM_AND_LEFT /* 1 chars; Bottom_And_Left */
-#define IMC_BR INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT /* 4 chars; Bottom_And_Right */
-#define IMC_L INDIC_MATRA_CATEGORY_LEFT /* 64 chars; Left */
-#define IMC_LR INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT /* 22 chars; Left_And_Right */
-#define IMC_x INDIC_MATRA_CATEGORY_NOT_APPLICABLE /* 1 chars; Not_Applicable */
-#define IMC_O INDIC_MATRA_CATEGORY_OVERSTRUCK /* 10 chars; Overstruck */
-#define IMC_R INDIC_MATRA_CATEGORY_RIGHT /* 290 chars; Right */
-#define IMC_T INDIC_MATRA_CATEGORY_TOP /* 418 chars; Top */
-#define IMC_TB INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM /* 10 chars; Top_And_Bottom */
-#define IMC_TBL INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT /* 2 chars; Top_And_Bottom_And_Left */
-#define IMC_TBR INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT /* 1 chars; Top_And_Bottom_And_Right */
-#define IMC_TL INDIC_MATRA_CATEGORY_TOP_AND_LEFT /* 6 chars; Top_And_Left */
-#define IMC_TLR INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT /* 4 chars; Top_And_Left_And_Right */
-#define IMC_TR INDIC_MATRA_CATEGORY_TOP_AND_RIGHT /* 13 chars; Top_And_Right */
-#define IMC_VOL INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT /* 19 chars; Visual_Order_Left */
-
-#pragma GCC diagnostic pop
-
-#define _(S,M) INDIC_COMBINE_CATEGORIES (ISC_##S, IMC_##M)
-
-
-static const uint16_t indic_table[] = {
-
-
-#define indic_offset_0x0028u 0
-
-
- /* Basic Latin */
-
- /* 0028 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x), _(x,x), _(x,x),
- /* 0030 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0038 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x00b0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00B0 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00B8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00C8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 00D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CP,x),
-
-#define indic_offset_0x0900u 64
-
-
- /* Devanagari */
-
- /* 0900 */ _(Bi,T), _(Bi,T), _(Bi,T), _(Vs,R), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0908 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0910 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0918 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0920 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0928 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0930 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0938 */ _(C,x), _(C,x), _(M,T), _(M,R), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0940 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(M,T), _(M,T),
- /* 0948 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(V,B), _(M,L), _(M,R),
- /* 0950 */ _(x,x), _(Ca,T), _(Ca,B), _(x,T), _(x,T), _(M,T), _(M,B), _(M,B),
- /* 0958 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0960 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0968 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0970 */ _(x,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0978 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
-
- /* Bengali */
-
- /* 0980 */ _(CP,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0988 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0990 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0998 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09A8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 09B0 */ _(C,x), _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 09B8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 09C0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 09C8 */ _(M,L), _(x,x), _(x,x), _(M,LR), _(M,LR), _(V,B), _(CD,x), _(x,x),
- /* 09D0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 09D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 09E0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 09E8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 09F0 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 09F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(Bi,x), _(x,x), _(SM,T), _(x,x),
-
- /* Gurmukhi */
-
- /* 0A00 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A08 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0A10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0A30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(x,x),
- /* 0A38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(x,x), _(M,R), _(M,L),
- /* 0A40 */ _(M,R), _(M,B), _(M,B), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T),
- /* 0A48 */ _(M,T), _(x,x), _(x,x), _(M,T), _(M,T), _(V,B), _(x,x), _(x,x),
- /* 0A50 */ _(x,x), _(Ca,B), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0A58 */ _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x),
- /* 0A60 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0A68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0A70 */ _(Bi,T), _(GM,T), _(CP,x), _(CP,x), _(x,x), _(CM,B), _(x,x), _(x,x),
- /* 0A78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Gujarati */
-
- /* 0A80 */ _(x,x), _(Bi,T), _(Bi,T), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0A88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x),
- /* 0A90 */ _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0A98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0AB0 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0AB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,L),
- /* 0AC0 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(M,T), _(x,x), _(M,T),
- /* 0AC8 */ _(M,T), _(M,TR), _(x,x), _(M,R), _(M,R), _(V,B), _(x,x), _(x,x),
- /* 0AD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0AE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0AF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0AF8 */ _(x,x), _(C,x), _(Ca,T), _(Ca,T), _(Ca,T), _(N,T), _(N,T), _(N,T),
-
- /* Oriya */
-
- /* 0B00 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(VI,x),
- /* 0B10 */ _(VI,x), _(x,x), _(x,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0B18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0B30 */ _(C,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0B38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0B40 */ _(M,R), _(M,B), _(M,B), _(M,B), _(M,B), _(x,x), _(x,x), _(M,L),
- /* 0B48 */ _(M,TL), _(x,x), _(x,x), _(M,LR),_(M,TLR), _(V,B), _(x,x), _(x,x),
- /* 0B50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,T), _(M,TR),
- /* 0B58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(C,x),
- /* 0B60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0B68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0B70 */ _(x,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0B78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Tamil */
-
- /* 0B80 */ _(x,x), _(x,x), _(Bi,T), _(ML,x), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0B88 */ _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(VI,x),
- /* 0B90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(x,x), _(x,x),
- /* 0B98 */ _(x,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(C,x), _(C,x),
- /* 0BA0 */ _(x,x), _(x,x), _(x,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x),
- /* 0BA8 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(C,x), _(C,x),
- /* 0BB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0BB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R),
- /* 0BC0 */ _(M,T), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(M,L), _(M,L),
- /* 0BC8 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T), _(x,x), _(x,x),
- /* 0BD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0BD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0BE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0BF0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0BF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Telugu */
-
- /* 0C00 */ _(Bi,T), _(Bi,R), _(Bi,R), _(Vs,R), _(Bi,T), _(VI,x), _(VI,x), _(VI,x),
- /* 0C08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C28 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0C38 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,T), _(M,T),
- /* 0C40 */ _(M,T), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,T),
- /* 0C48 */ _(M,TB), _(x,x), _(M,T), _(M,T), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0C50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,T), _(M,B), _(x,x),
- /* 0C58 */ _(C,x), _(C,x), _(C,x), _(x,x), _(x,x), _(CD,x), _(x,x), _(x,x),
- /* 0C60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0C68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0C70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0C78 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Kannada */
-
- /* 0C80 */ _(Bi,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0C88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0C90 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0C98 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CA8 */ _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0CB0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x),
- /* 0CB8 */ _(C,x), _(C,x), _(x,x), _(x,x), _(N,B), _(A,x), _(M,R), _(M,T),
- /* 0CC0 */ _(M,TR), _(M,R), _(M,R), _(M,R), _(M,R), _(x,x), _(M,T), _(M,TR),
- /* 0CC8 */ _(M,TR), _(x,x), _(M,TR), _(M,TR), _(M,T), _(V,T), _(x,x), _(x,x),
- /* 0CD0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R), _(M,R), _(x,x),
- /* 0CD8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(C,x), _(x,x),
- /* 0CE0 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0CE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0CF0 */ _(x,x),_(CWS,x),_(CWS,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0CF8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
- /* Malayalam */
-
- /* 0D00 */ _(Bi,T), _(Bi,T), _(Bi,R), _(Vs,R), _(Bi,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D08 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(VI,x), _(VI,x),
- /* 0D10 */ _(VI,x), _(x,x), _(VI,x), _(VI,x), _(VI,x), _(C,x), _(C,x), _(C,x),
- /* 0D18 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D20 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D28 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D30 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0D38 */ _(C,x), _(C,x), _(C,x), _(PK,T), _(PK,T), _(A,x), _(M,R), _(M,R),
- /* 0D40 */ _(M,R), _(M,R), _(M,R), _(M,B), _(M,B), _(x,x), _(M,L), _(M,L),
- /* 0D48 */ _(M,L), _(x,x), _(M,LR), _(M,LR), _(M,LR), _(V,T),_(CPR,T), _(x,x),
- /* 0D50 */ _(x,x), _(x,x), _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(M,R),
- /* 0D58 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x),
- /* 0D60 */ _(VI,x), _(VI,x), _(M,B), _(M,B), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0D68 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0D70 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 0D78 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x), _(CD,x),
-
- /* Sinhala */
-
- /* 0D80 */ _(x,x), _(Bi,T), _(Bi,R), _(Vs,R), _(x,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D88 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 0D90 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x),
- /* 0D98 */ _(x,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DA8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB0 */ _(C,x), _(C,x), _(x,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 0DB8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(x,x), _(C,x), _(x,x), _(x,x),
- /* 0DC0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
- /* 0DC8 */ _(x,x), _(x,x), _(V,T), _(x,x), _(x,x), _(x,x), _(x,x), _(M,R),
- /* 0DD0 */ _(M,R), _(M,R), _(M,T), _(M,T), _(M,B), _(x,x), _(M,B), _(x,x),
- /* 0DD8 */ _(M,R), _(M,L), _(M,TL), _(M,L), _(M,LR),_(M,TLR), _(M,LR), _(M,R),
- /* 0DE0 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(Nd,x), _(Nd,x),
- /* 0DE8 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 0DF0 */ _(x,x), _(x,x), _(M,R), _(M,R), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1000u 1336
-
-
- /* Myanmar */
-
- /* 1000 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1008 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1010 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1018 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1020 */ _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 1028 */ _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R), _(M,T), _(M,T), _(M,B),
- /* 1030 */ _(M,B), _(M,L), _(M,T), _(M,T), _(M,T), _(M,T), _(Bi,T), _(TM,B),
- /* 1038 */ _(Vs,R), _(IS,x), _(PK,T), _(CM,R),_(CM,TBL), _(CM,B), _(CM,B), _(C,x),
- /* 1040 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1048 */ _(Nd,x), _(Nd,x), _(x,x), _(CP,x), _(x,x), _(x,x), _(CP,x), _(x,x),
- /* 1050 */ _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(M,R), _(M,R),
- /* 1058 */ _(M,B), _(M,B), _(C,x), _(C,x), _(C,x), _(C,x), _(CM,B), _(CM,B),
- /* 1060 */ _(CM,B), _(C,x), _(M,R), _(TM,R), _(TM,R), _(C,x), _(C,x), _(M,R),
- /* 1068 */ _(M,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(C,x), _(C,x),
- /* 1070 */ _(C,x), _(M,T), _(M,T), _(M,T), _(M,T), _(C,x), _(C,x), _(C,x),
- /* 1078 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1080 */ _(C,x), _(C,x), _(CM,B), _(M,R), _(M,L), _(M,T), _(M,T), _(TM,R),
- /* 1088 */ _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,R), _(TM,B), _(C,x), _(TM,R),
- /* 1090 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 1098 */ _(Nd,x), _(Nd,x), _(TM,R), _(TM,R), _(M,R), _(M,T), _(x,x), _(x,x),
-
-#define indic_offset_0x1780u 1496
-
-
- /* Khmer */
-
- /* 1780 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1788 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1790 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 1798 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* 17A0 */ _(C,x), _(C,x), _(C,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17A8 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(VI,x),
- /* 17B0 */ _(VI,x), _(VI,x), _(VI,x), _(VI,x), _(x,x), _(x,x), _(M,R), _(M,T),
- /* 17B8 */ _(M,T), _(M,T), _(M,T), _(M,B), _(M,B), _(M,B), _(M,TL),_(M,TLR),
- /* 17C0 */ _(M,LR), _(M,L), _(M,L), _(M,L), _(M,LR), _(M,LR), _(Bi,T), _(Vs,R),
- /* 17C8 */ _(M,R), _(RS,T), _(RS,T), _(SM,T),_(CSR,T), _(CK,T), _(SM,T), _(SM,T),
- /* 17D0 */ _(SM,T), _(PK,T), _(IS,x), _(SM,T), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 17D8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(A,x), _(SM,T), _(x,x), _(x,x),
- /* 17E0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* 17E8 */ _(Nd,x), _(Nd,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x1cd0u 1608
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(x,x), _(Ca,O), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CD8 */ _(Ca,B), _(Ca,B), _(Ca,T), _(Ca,T), _(Ca,B), _(Ca,B), _(Ca,B), _(Ca,B),
- /* 1CE0 */ _(Ca,T), _(Ca,R), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O), _(x,O),
- /* 1CE8 */ _(x,O), _(x,x), _(x,x), _(x,x), _(x,x), _(x,B), _(x,x), _(x,x),
- /* 1CF0 */ _(x,x), _(x,x), _(CD,x), _(CD,x), _(Ca,T),_(CWS,x),_(CWS,x), _(Ca,R),
- /* 1CF8 */ _(Ca,x), _(Ca,x), _(CP,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2008u 1656
-
-
- /* General Punctuation */
-
- /* 2008 */ _(x,x), _(x,x), _(x,x), _(x,x),_(ZWNJ,x),_(ZWJ,x), _(x,x), _(x,x),
- /* 2010 */ _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(CP,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0x2070u 1672
-
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ _(x,x), _(x,x), _(x,x), _(x,x), _(SM,x), _(x,x), _(x,x), _(x,x),
- /* 2078 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* 2080 */ _(x,x), _(x,x), _(SM,x), _(SM,x), _(SM,x), _(x,x), _(x,x), _(x,x),
-
-#define indic_offset_0xa8e0u 1696
-
-
- /* Devanagari Extended */
-
- /* A8E0 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8E8 */ _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T), _(Ca,T),
- /* A8F0 */ _(Ca,T), _(Ca,T), _(Bi,x), _(Bi,x), _(x,x), _(x,x), _(x,x), _(x,x),
- /* A8F8 */ _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(x,x), _(VI,x), _(M,T),
-
-#define indic_offset_0xa9e0u 1728
-
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(M,T), _(x,x), _(C,x),
- /* A9E8 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* A9F0 */ _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x), _(Nd,x),
- /* A9F8 */ _(Nd,x), _(Nd,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(x,x),
-
-#define indic_offset_0xaa60u 1760
-
-
- /* Myanmar Extended-A */
-
- /* AA60 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA68 */ _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x), _(C,x),
- /* AA70 */ _(x,x), _(C,x), _(C,x), _(C,x), _(CP,x), _(CP,x), _(CP,x), _(x,x),
- /* AA78 */ _(x,x), _(x,x), _(C,x), _(TM,R), _(TM,T), _(TM,R), _(C,x), _(C,x),
-
-}; /* Table items: 1792; occupancy: 71% */
-
-uint16_t
-hb_indic_get_categories (hb_codepoint_t u)
-{
- switch (u >> 12)
- {
- case 0x0u:
- if (unlikely (u == 0x00A0u)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
- break;
-
- case 0x2u:
- if (unlikely (u == 0x25CCu)) return _(CP,x);
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
- if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
- break;
-
- default:
- break;
- }
- return _(x,x);
-}
-
-#undef _
-
-#undef ISC_A
-#undef ISC_Bi
-#undef ISC_BJN
-#undef ISC_Ca
-#undef ISC_C
-#undef ISC_CD
-#undef ISC_CF
-#undef ISC_CHL
-#undef ISC_CIP
-#undef ISC_CK
-#undef ISC_CM
-#undef ISC_CP
-#undef ISC_CPR
-#undef ISC_CPrf
-#undef ISC_CS
-#undef ISC_CSR
-#undef ISC_CWS
-#undef ISC_GM
-#undef ISC_IS
-#undef ISC_ZWJ
-#undef ISC_ML
-#undef ISC_ZWNJ
-#undef ISC_N
-#undef ISC_Nd
-#undef ISC_NJ
-#undef ISC_x
-#undef ISC_PK
-#undef ISC_RS
-#undef ISC_SM
-#undef ISC_TL
-#undef ISC_TM
-#undef ISC_V
-#undef ISC_Vs
-#undef ISC_Vo
-#undef ISC_M
-#undef ISC_VI
-
-#undef IMC_B
-#undef IMC_BL
-#undef IMC_BR
-#undef IMC_L
-#undef IMC_LR
-#undef IMC_x
-#undef IMC_O
-#undef IMC_R
-#undef IMC_T
-#undef IMC_TB
-#undef IMC_TBL
-#undef IMC_TBR
-#undef IMC_TL
-#undef IMC_TLR
-#undef IMC_TR
-#undef IMC_VOL
-
-#endif
-
-/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
deleted file mode 100644
index 4a8781c8f8..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.cc
+++ /dev/null
@@ -1,1572 +0,0 @@
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-indic.hh"
-#include "hb-ot-shape-complex-indic-machine.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
-#include "hb-ot-layout.hh"
-
-
-/*
- * Indic shaper.
- */
-
-
-/*
- * Indic configurations. Note that we do not want to keep every single script-specific
- * behavior in these tables necessarily. This should mainly be used for per-script
- * properties that are cheaper keeping here, than in the code. Ie. if, say, one and
- * only one script has an exception, that one script can be if'ed directly in the code,
- * instead of adding a new flag in these structs.
- */
-
-enum base_position_t {
- BASE_POS_LAST_SINHALA,
- BASE_POS_LAST
-};
-enum reph_position_t {
- REPH_POS_AFTER_MAIN = POS_AFTER_MAIN,
- REPH_POS_BEFORE_SUB = POS_BEFORE_SUB,
- REPH_POS_AFTER_SUB = POS_AFTER_SUB,
- REPH_POS_BEFORE_POST = POS_BEFORE_POST,
- REPH_POS_AFTER_POST = POS_AFTER_POST
-};
-enum reph_mode_t {
- REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */
- REPH_MODE_EXPLICIT, /* Reph formed out of initial Ra,H,ZWJ sequence. */
- REPH_MODE_LOG_REPHA /* Encoded Repha character, needs reordering. */
-};
-enum blwf_mode_t {
- BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */
- BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */
-};
-struct indic_config_t
-{
- hb_script_t script;
- bool has_old_spec;
- hb_codepoint_t virama;
- base_position_t base_pos;
- reph_position_t reph_pos;
- reph_mode_t reph_mode;
- blwf_mode_t blwf_mode;
-};
-
-static const indic_config_t indic_configs[] =
-{
- /* Default. Should be first. */
- {HB_SCRIPT_INVALID, false, 0,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_DEVANAGARI,true, 0x094Du,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_BENGALI, true, 0x09CDu,BASE_POS_LAST, REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,BASE_POS_LAST, REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_GUJARATI, true, 0x0ACDu,BASE_POS_LAST, REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_ORIYA, true, 0x0B4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TAMIL, true, 0x0BCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_TELUGU, true, 0x0C4Du,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_KANNADA, true, 0x0CCDu,BASE_POS_LAST, REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
- {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,BASE_POS_LAST, REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
- {HB_SCRIPT_SINHALA, false,0x0DCAu,BASE_POS_LAST_SINHALA,
- REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_PRE_AND_POST},
-};
-
-
-
-/*
- * Indic shaper.
- */
-
-static const hb_ot_map_feature_t
-indic_features[] =
-{
- /*
- * Basic features.
- * These features are applied in order, one at a time, after initial_reordering,
- * constrained to the syllable.
- */
- {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS},
- {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS},
- /*
- * Other features.
- * These features are applied all at once, after final_reordering, constrained
- * to the syllable.
- * Default Bengali font in Windows for example has intermixed
- * lookups for init,pres,abvs,blws features.
- */
- {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS},
- {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS},
-};
-
-/*
- * Must be in the same order as the indic_features array.
- */
-enum {
- _INDIC_NUKT,
- _INDIC_AKHN,
- INDIC_RPHF,
- _INDIC_RKRF,
- INDIC_PREF,
- INDIC_BLWF,
- INDIC_ABVF,
- INDIC_HALF,
- INDIC_PSTF,
- _INDIC_VATU,
- _INDIC_CJCT,
-
- INDIC_INIT,
- _INDIC_PRES,
- _INDIC_ABVS,
- _INDIC_BLWS,
- _INDIC_PSTS,
- _INDIC_HALN,
-
- INDIC_NUM_FEATURES,
- INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
-};
-
-static void
-setup_syllables_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-initial_reordering_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-final_reordering_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-collect_features_indic (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* Do this before any lookups have been applied. */
- map->add_gsub_pause (setup_syllables_indic);
-
- map->enable_feature (HB_TAG('l','o','c','l'));
- /* The Indic specs do not require ccmp, but we apply it here since if
- * there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
-
-
- unsigned int i = 0;
- map->add_gsub_pause (initial_reordering_indic);
-
- for (; i < INDIC_BASIC_FEATURES; i++) {
- map->add_feature (indic_features[i]);
- map->add_gsub_pause (nullptr);
- }
-
- map->add_gsub_pause (final_reordering_indic);
-
- for (; i < INDIC_NUM_FEATURES; i++)
- map->add_feature (indic_features[i]);
-
- map->add_gsub_pause (_hb_clear_syllables);
-}
-
-static void
-override_features_indic (hb_ot_shape_planner_t *plan)
-{
- plan->map.disable_feature (HB_TAG('l','i','g','a'));
-}
-
-
-struct indic_shape_plan_t
-{
- bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
- {
- hb_codepoint_t glyph = virama_glyph.get_relaxed ();
- if (unlikely (glyph == (hb_codepoint_t) -1))
- {
- if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
- glyph = 0;
- /* Technically speaking, the spec says we should apply 'locl' to virama too.
- * Maybe one day... */
-
- /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
- * during shape planning... Instead, overwrite it here. */
- virama_glyph.set_relaxed ((int) glyph);
- }
-
- *pglyph = glyph;
- return glyph != 0;
- }
-
- const indic_config_t *config;
-
- bool is_old_spec;
-#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
- bool uniscribe_bug_compatible;
-#else
- static constexpr bool uniscribe_bug_compatible = false;
-#endif
- mutable hb_atomic_int_t virama_glyph;
-
- hb_indic_would_substitute_feature_t rphf;
- hb_indic_would_substitute_feature_t pref;
- hb_indic_would_substitute_feature_t blwf;
- hb_indic_would_substitute_feature_t pstf;
- hb_indic_would_substitute_feature_t vatu;
-
- hb_mask_t mask_array[INDIC_NUM_FEATURES];
-};
-
-static void *
-data_create_indic (const hb_ot_shape_plan_t *plan)
-{
- indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) hb_calloc (1, sizeof (indic_shape_plan_t));
- if (unlikely (!indic_plan))
- return nullptr;
-
- indic_plan->config = &indic_configs[0];
- for (unsigned int i = 1; i < ARRAY_LENGTH (indic_configs); i++)
- if (plan->props.script == indic_configs[i].script) {
- indic_plan->config = &indic_configs[i];
- break;
- }
-
- indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
-#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
- indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
-#endif
- indic_plan->virama_glyph.set_relaxed (-1);
-
- /* Use zero-context would_substitute() matching for new-spec of the main
- * Indic scripts, and scripts with one spec only, but not for old-specs.
- * The new-spec for all dual-spec scripts says zero-context matching happens.
- *
- * However, testing with Malayalam shows that old and new spec both allow
- * context. Testing with Bengali new-spec however shows that it doesn't.
- * So, the heuristic here is the way it is. It should *only* be changed,
- * as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE.
- */
- bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM;
- indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
- indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
- indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
- indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context);
- indic_plan->vatu.init (&plan->map, HB_TAG('v','a','t','u'), zero_context);
-
- for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++)
- indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ?
- 0 : plan->map.get_1_mask (indic_features[i].tag);
-
- return indic_plan;
-}
-
-static void
-data_destroy_indic (void *data)
-{
- hb_free (data);
-}
-
-static indic_position_t
-consonant_position_from_face (const indic_shape_plan_t *indic_plan,
- const hb_codepoint_t consonant,
- const hb_codepoint_t virama,
- hb_face_t *face)
-{
- /* For old-spec, the order of glyphs is Consonant,Virama,
- * whereas for new-spec, it's Virama,Consonant. However,
- * some broken fonts (like Free Sans) simply copied lookups
- * from old-spec to new-spec without modification.
- * And oddly enough, Uniscribe seems to respect those lookups.
- * Eg. in the sequence U+0924,U+094D,U+0930, Uniscribe finds
- * base at 0. The font however, only has lookups matching
- * 930,94D in 'blwf', not the expected 94D,930 (with new-spec
- * table). As such, we simply match both sequences. Seems
- * to work.
- *
- * Vatu is done as well, for:
- * https://github.com/harfbuzz/harfbuzz/issues/1587
- */
- hb_codepoint_t glyphs[3] = {virama, consonant, virama};
- if (indic_plan->blwf.would_substitute (glyphs , 2, face) ||
- indic_plan->blwf.would_substitute (glyphs+1, 2, face) ||
- indic_plan->vatu.would_substitute (glyphs , 2, face) ||
- indic_plan->vatu.would_substitute (glyphs+1, 2, face))
- return POS_BELOW_C;
- if (indic_plan->pstf.would_substitute (glyphs , 2, face) ||
- indic_plan->pstf.would_substitute (glyphs+1, 2, face))
- return POS_POST_C;
- if (indic_plan->pref.would_substitute (glyphs , 2, face) ||
- indic_plan->pref.would_substitute (glyphs+1, 2, face))
- return POS_POST_C;
- return POS_BASE_C;
-}
-
-static void
-setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
- HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
-
- /* We cannot setup masks here. We save information about characters
- * and setup masks later on in a pause-callback. */
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- set_indic_properties (info[i]);
-}
-
-static void
-setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- find_syllables_indic (buffer);
- foreach_syllable (buffer, start, end)
- buffer->unsafe_to_break (start, end);
-}
-
-static int
-compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
- int a = pa->indic_position();
- int b = pb->indic_position();
-
- return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-
-static void
-update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
-
- if (indic_plan->config->base_pos != BASE_POS_LAST)
- return;
-
- hb_codepoint_t virama;
- if (indic_plan->load_virama_glyph (font, &virama))
- {
- hb_face_t *face = font->face;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if (info[i].indic_position() == POS_BASE_C)
- {
- hb_codepoint_t consonant = info[i].codepoint;
- info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
- }
- }
-}
-
-
-/* Rules from:
- * https://docs.microsqoft.com/en-us/typography/script-development/devanagari */
-
-static void
-initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
- hb_glyph_info_t *info = buffer->info;
-
- /* https://github.com/harfbuzz/harfbuzz/issues/435#issuecomment-335560167
- * // For compatibility with legacy usage in Kannada,
- * // Ra+h+ZWJ must behave like Ra+ZWJ+h...
- */
- if (buffer->props.script == HB_SCRIPT_KANNADA &&
- start + 3 <= end &&
- is_one_of (info[start ], FLAG (OT_Ra)) &&
- is_one_of (info[start+1], FLAG (OT_H)) &&
- is_one_of (info[start+2], FLAG (OT_ZWJ)))
- {
- buffer->merge_clusters (start+1, start+3);
- hb_glyph_info_t tmp = info[start+1];
- info[start+1] = info[start+2];
- info[start+2] = tmp;
- }
-
- /* 1. Find base consonant:
- *
- * The shaping engine finds the base consonant of the syllable, using the
- * following algorithm: starting from the end of the syllable, move backwards
- * until a consonant is found that does not have a below-base or post-base
- * form (post-base forms have to follow below-base forms), or that is not a
- * pre-base-reordering Ra, or arrive at the first consonant. The consonant
- * stopped at will be the base.
- *
- * o If the syllable starts with Ra + Halant (in a script that has Reph)
- * and has more than one consonant, Ra is excluded from candidates for
- * base consonants.
- */
-
- unsigned int base = end;
- bool has_reph = false;
-
- {
- /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
- * and has more than one consonant, Ra is excluded from candidates for
- * base consonants. */
- unsigned int limit = start;
- if (indic_plan->mask_array[INDIC_RPHF] &&
- start + 3 <= end &&
- (
- (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
- (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == OT_ZWJ)
- ))
- {
- /* See if it matches the 'rphf' feature. */
- hb_codepoint_t glyphs[3] = {info[start].codepoint,
- info[start + 1].codepoint,
- indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ?
- info[start + 2].codepoint : 0};
- if (indic_plan->rphf.would_substitute (glyphs, 2, face) ||
- (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT &&
- indic_plan->rphf.would_substitute (glyphs, 3, face)))
- {
- limit += 2;
- while (limit < end && is_joiner (info[limit]))
- limit++;
- base = start;
- has_reph = true;
- }
- } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == OT_Repha)
- {
- limit += 1;
- while (limit < end && is_joiner (info[limit]))
- limit++;
- base = start;
- has_reph = true;
- }
-
- switch (indic_plan->config->base_pos)
- {
- case BASE_POS_LAST:
- {
- /* -> starting from the end of the syllable, move backwards */
- unsigned int i = end;
- bool seen_below = false;
- do {
- i--;
- /* -> until a consonant is found */
- if (is_consonant (info[i]))
- {
- /* -> that does not have a below-base or post-base form
- * (post-base forms have to follow below-base forms), */
- if (info[i].indic_position() != POS_BELOW_C &&
- (info[i].indic_position() != POS_POST_C || seen_below))
- {
- base = i;
- break;
- }
- if (info[i].indic_position() == POS_BELOW_C)
- seen_below = true;
-
- /* -> or that is not a pre-base-reordering Ra,
- *
- * IMPLEMENTATION NOTES:
- *
- * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
- * by the logic above already.
- */
-
- /* -> or arrive at the first consonant. The consonant stopped at will
- * be the base. */
- base = i;
- }
- else
- {
- /* A ZWJ after a Halant stops the base search, and requests an explicit
- * half form.
- * A ZWJ before a Halant, requests a subjoined form instead, and hence
- * search continues. This is particularly important for Bengali
- * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
- if (start < i &&
- info[i].indic_category() == OT_ZWJ &&
- info[i - 1].indic_category() == OT_H)
- break;
- }
- } while (i > limit);
- }
- break;
-
- case BASE_POS_LAST_SINHALA:
- {
- /* Sinhala base positioning is slightly different from main Indic, in that:
- * 1. Its ZWJ behavior is different,
- * 2. We don't need to look into the font for consonant positions.
- */
-
- if (!has_reph)
- base = limit;
-
- /* Find the last base consonant that is not blocked by ZWJ. If there is
- * a ZWJ right before a base consonant, that would request a subjoined form. */
- for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
- {
- if (limit < i && info[i - 1].indic_category() == OT_ZWJ)
- break;
- else
- base = i;
- }
-
- /* Mark all subsequent consonants as below. */
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
- info[i].indic_position() = POS_BELOW_C;
- }
- break;
- }
-
- /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
- * and has more than one consonant, Ra is excluded from candidates for
- * base consonants.
- *
- * Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */
- if (has_reph && base == start && limit - base <= 2) {
- /* Have no other consonant, so Reph is not formed and Ra becomes base. */
- has_reph = false;
- }
- }
-
-
- /* 2. Decompose and reorder Matras:
- *
- * Each matra and any syllable modifier sign in the syllable are moved to the
- * appropriate position relative to the consonant(s) in the syllable. The
- * shaping engine decomposes two- or three-part matras into their constituent
- * parts before any repositioning. Matra characters are classified by which
- * consonant in a conjunct they have affinity for and are reordered to the
- * following positions:
- *
- * o Before first half form in the syllable
- * o After subjoined consonants
- * o After post-form consonant
- * o After main consonant (for above marks)
- *
- * IMPLEMENTATION NOTES:
- *
- * The normalize() routine has already decomposed matras for us, so we don't
- * need to worry about that.
- */
-
-
- /* 3. Reorder marks to canonical order:
- *
- * Adjacent nukta and halant or nukta and vedic sign are always repositioned
- * if necessary, so that the nukta is first.
- *
- * IMPLEMENTATION NOTES:
- *
- * We don't need to do this: the normalize() routine already did this for us.
- */
-
-
- /* Reorder characters */
-
- for (unsigned int i = start; i < base; i++)
- info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position());
-
- if (base < end)
- info[base].indic_position() = POS_BASE_C;
-
- /* Mark final consonants. A final consonant is one appearing after a matra.
- * Happens in Sinhala. */
- for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_M) {
- for (unsigned int j = i + 1; j < end; j++)
- if (is_consonant (info[j])) {
- info[j].indic_position() = POS_FINAL_C;
- break;
- }
- break;
- }
-
- /* Handle beginning Ra */
- if (has_reph)
- info[start].indic_position() = POS_RA_TO_BECOME_REPH;
-
- /* For old-style Indic script tags, move the first post-base Halant after
- * last consonant.
- *
- * Reports suggest that in some scripts Uniscribe does this only if there
- * is *not* a Halant after last consonant already. We know that is the
- * case for Kannada, while it reorders unconditionally in other scripts,
- * eg. Malayalam, Bengali, and Devanagari. We don't currently know about
- * other scripts, so we block Kannada.
- *
- * Kannada test case:
- * U+0C9A,U+0CCD,U+0C9A,U+0CCD
- * With some versions of Lohit Kannada.
- * https://bugs.freedesktop.org/show_bug.cgi?id=59118
- *
- * Malayalam test case:
- * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
- * With lohit-ttf-20121122/Lohit-Malayalam.ttf
- *
- * Bengali test case:
- * U+0998,U+09CD,U+09AF,U+09CD
- * With Windows XP vrinda.ttf
- * https://github.com/harfbuzz/harfbuzz/issues/1073
- *
- * Devanagari test case:
- * U+091F,U+094D,U+0930,U+094D
- * With chandas.ttf
- * https://github.com/harfbuzz/harfbuzz/issues/1071
- */
- if (indic_plan->is_old_spec)
- {
- bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
- for (unsigned int i = base + 1; i < end; i++)
- if (info[i].indic_category() == OT_H)
- {
- unsigned int j;
- for (j = end - 1; j > i; j--)
- if (is_consonant (info[j]) ||
- (disallow_double_halants && info[j].indic_category() == OT_H))
- break;
- if (info[j].indic_category() != OT_H && j > i) {
- /* Move Halant to after last consonant. */
- hb_glyph_info_t t = info[i];
- memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
- info[j] = t;
- }
- break;
- }
- }
-
- /* Attach misc marks to previous char to move with them. */
- {
- indic_position_t last_pos = POS_START;
- for (unsigned int i = start; i < end; i++)
- {
- if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (OT_N) | FLAG (OT_RS) | MEDIAL_FLAGS | FLAG (OT_H))))
- {
- info[i].indic_position() = last_pos;
- if (unlikely (info[i].indic_category() == OT_H &&
- info[i].indic_position() == POS_PRE_M))
- {
- /*
- * Uniscribe doesn't move the Halant with Left Matra.
- * TEST: U+092B,U+093F,U+094DE
- * We follow. This is important for the Sinhala
- * U+0DDA split matra since it decomposes to U+0DD9,U+0DCA
- * where U+0DD9 is a left matra and U+0DCA is the virama.
- * We don't want to move the virama with the left matra.
- * TEST: U+0D9A,U+0DDA
- */
- for (unsigned int j = i; j > start; j--)
- if (info[j - 1].indic_position() != POS_PRE_M) {
- info[i].indic_position() = info[j - 1].indic_position();
- break;
- }
- }
- } else if (info[i].indic_position() != POS_SMVD) {
- last_pos = (indic_position_t) info[i].indic_position();
- }
- }
- }
- /* For post-base consonants let them own anything before them
- * since the last consonant or matra. */
- {
- unsigned int last = base;
- for (unsigned int i = base + 1; i < end; i++)
- if (is_consonant (info[i]))
- {
- for (unsigned int j = last + 1; j < i; j++)
- if (info[j].indic_position() < POS_SMVD)
- info[j].indic_position() = info[i].indic_position();
- last = i;
- } else if (info[i].indic_category() == OT_M)
- last = i;
- }
-
-
- {
- /* Use syllable() for sort accounting temporarily. */
- unsigned int syllable = info[start].syllable();
- for (unsigned int i = start; i < end; i++)
- info[i].syllable() = i - start;
-
- /* Sit tight, rock 'n roll! */
- hb_stable_sort (info + start, end - start, compare_indic_order);
- /* Find base again */
- base = end;
- for (unsigned int i = start; i < end; i++)
- if (info[i].indic_position() == POS_BASE_C)
- {
- base = i;
- break;
- }
- /* Things are out-of-control for post base positions, they may shuffle
- * around like crazy. In old-spec mode, we move halants around, so in
- * that case merge all clusters after base. Otherwise, check the sort
- * order and merge as needed.
- * For pre-base stuff, we handle cluster issues in final reordering.
- *
- * We could use buffer->sort() for this, if there was no special
- * reordering of pre-base stuff happening later...
- * We don't want to merge_clusters all of that, which buffer->sort()
- * would. Here's a concrete example:
- *
- * Assume there's a pre-base consonant and explicit Halant before base,
- * followed by a prebase-reordering (left) Matra:
- *
- * C,H,ZWNJ,B,M
- *
- * At this point in reordering we would have:
- *
- * M,C,H,ZWNJ,B
- *
- * whereas in final reordering we will bring the Matra closer to Base:
- *
- * C,H,ZWNJ,M,B
- *
- * That's why we don't want to merge-clusters anything before the Base
- * at this point. But if something moved from after Base to before it,
- * we should merge clusters from base to them. In final-reordering, we
- * only move things around before base, and merge-clusters up to base.
- * These two merge-clusters from the two sides of base will interlock
- * to merge things correctly. See:
- * https://github.com/harfbuzz/harfbuzz/issues/2272
- */
- if (indic_plan->is_old_spec || end - start > 127)
- buffer->merge_clusters (base, end);
- else
- {
- /* Note! syllable() is a one-byte field. */
- for (unsigned int i = base; i < end; i++)
- if (info[i].syllable() != 255)
- {
- unsigned int min = i;
- unsigned int max = i;
- unsigned int j = start + info[i].syllable();
- while (j != i)
- {
- min = hb_min (min, j);
- max = hb_max (max, j);
- unsigned int next = start + info[j].syllable();
- info[j].syllable() = 255; /* So we don't process j later again. */
- j = next;
- }
- buffer->merge_clusters (hb_max (base, min), max + 1);
- }
- }
-
- /* Put syllable back in. */
- for (unsigned int i = start; i < end; i++)
- info[i].syllable() = syllable;
- }
-
- /* Setup masks now */
-
- {
- hb_mask_t mask;
-
- /* Reph */
- for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
- info[i].mask |= indic_plan->mask_array[INDIC_RPHF];
-
- /* Pre-base */
- mask = indic_plan->mask_array[INDIC_HALF];
- if (!indic_plan->is_old_spec &&
- indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
- mask |= indic_plan->mask_array[INDIC_BLWF];
- for (unsigned int i = start; i < base; i++)
- info[i].mask |= mask;
- /* Base */
- mask = 0;
- if (base < end)
- info[base].mask |= mask;
- /* Post-base */
- mask = indic_plan->mask_array[INDIC_BLWF] |
- indic_plan->mask_array[INDIC_ABVF] |
- indic_plan->mask_array[INDIC_PSTF];
- for (unsigned int i = base + 1; i < end; i++)
- info[i].mask |= mask;
- }
-
- if (indic_plan->is_old_spec &&
- buffer->props.script == HB_SCRIPT_DEVANAGARI)
- {
- /* Old-spec eye-lash Ra needs special handling. From the
- * spec:
- *
- * "The feature 'below-base form' is applied to consonants
- * having below-base forms and following the base consonant.
- * The exception is vattu, which may appear below half forms
- * as well as below the base glyph. The feature 'below-base
- * form' will be applied to all such occurrences of Ra as well."
- *
- * Test case: U+0924,U+094D,U+0930,U+094d,U+0915
- * with Sanskrit 2003 font.
- *
- * However, note that Ra,Halant,ZWJ is the correct way to
- * request eyelash form of Ra, so we wouldbn't inhibit it
- * in that sequence.
- *
- * Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
- */
- for (unsigned int i = start; i + 1 < base; i++)
- if (info[i ].indic_category() == OT_Ra &&
- info[i+1].indic_category() == OT_H &&
- (i + 2 == base ||
- info[i+2].indic_category() != OT_ZWJ))
- {
- info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
- info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
- }
- }
-
- unsigned int pref_len = 2;
- if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end)
- {
- /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
- for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
- hb_codepoint_t glyphs[2];
- for (unsigned int j = 0; j < pref_len; j++)
- glyphs[j] = info[i + j].codepoint;
- if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
- {
- for (unsigned int j = 0; j < pref_len; j++)
- info[i++].mask |= indic_plan->mask_array[INDIC_PREF];
- break;
- }
- }
- }
-
- /* Apply ZWJ/ZWNJ effects */
- for (unsigned int i = start + 1; i < end; i++)
- if (is_joiner (info[i])) {
- bool non_joiner = info[i].indic_category() == OT_ZWNJ;
- unsigned int j = i;
-
- do {
- j--;
-
- /* ZWJ/ZWNJ should disable CJCT. They do that by simply
- * being there, since we don't skip them for the CJCT
- * feature (ie. F_MANUAL_ZWJ) */
-
- /* A ZWNJ disables HALF. */
- if (non_joiner)
- info[j].mask &= ~indic_plan->mask_array[INDIC_HALF];
-
- } while (j > start && !is_consonant (info[j]));
- }
-}
-
-static void
-initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- /* We treat placeholder/dotted-circle as if they are consonants, so we
- * should just chain. Only if not in compatibility mode that is... */
-
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
- if (indic_plan->uniscribe_bug_compatible)
- {
- /* For dotted-circle, this is what Uniscribe does:
- * If dotted-circle is the last glyph, it just does nothing.
- * Ie. It doesn't form Reph. */
- if (buffer->info[end - 1].indic_category() == OT_DOTTEDCIRCLE)
- return;
- }
-
- initial_reordering_consonant_syllable (plan, face, buffer, start, end);
-}
-
-static void
-initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
- switch (syllable_type)
- {
- case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
- case indic_consonant_syllable:
- initial_reordering_consonant_syllable (plan, face, buffer, start, end);
- break;
-
- case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
- case indic_standalone_cluster:
- initial_reordering_standalone_cluster (plan, face, buffer, start, end);
- break;
-
- case indic_symbol_cluster:
- case indic_non_indic_cluster:
- break;
- }
-}
-
-static void
-initial_reordering_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (!buffer->message (font, "start reordering indic initial"))
- return;
-
- update_consonant_positions_indic (plan, font, buffer);
- hb_syllabic_insert_dotted_circles (font, buffer,
- indic_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha,
- POS_END);
-
- foreach_syllable (buffer, start, end)
- initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
-
- (void) buffer->message (font, "end reordering indic initial");
-}
-
-static void
-final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
- hb_glyph_info_t *info = buffer->info;
-
-
- /* This function relies heavily on halant glyphs. Lots of ligation
- * and possibly multiple substitutions happened prior to this
- * phase, and that might have messed up our properties. Recover
- * from a particular case of that where we're fairly sure that a
- * class of OT_H is desired but has been lost. */
- /* We don't call load_virama_glyph(), since we know it's already
- * loaded. */
- hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
- if (virama_glyph)
- {
- for (unsigned int i = start; i < end; i++)
- if (info[i].codepoint == virama_glyph &&
- _hb_glyph_info_ligated (&info[i]) &&
- _hb_glyph_info_multiplied (&info[i]))
- {
- /* This will make sure that this glyph passes is_halant() test. */
- info[i].indic_category() = OT_H;
- _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
- }
- }
-
-
- /* 4. Final reordering:
- *
- * After the localized forms and basic shaping forms GSUB features have been
- * applied (see below), the shaping engine performs some final glyph
- * reordering before applying all the remaining font features to the entire
- * syllable.
- */
-
- bool try_pref = !!indic_plan->mask_array[INDIC_PREF];
-
- /* Find base again */
- unsigned int base;
- for (base = start; base < end; base++)
- if (info[base].indic_position() >= POS_BASE_C)
- {
- if (try_pref && base + 1 < end)
- {
- for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
- {
- if (!(_hb_glyph_info_substituted (&info[i]) &&
- _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
- {
- /* Ok, this was a 'pref' candidate but didn't form any.
- * Base is around here... */
- base = i;
- while (base < end && is_halant (info[base]))
- base++;
- info[base].indic_position() = POS_BASE_C;
-
- try_pref = false;
- }
- break;
- }
- }
- /* For Malayalam, skip over unformed below- (but NOT post-) forms. */
- if (buffer->props.script == HB_SCRIPT_MALAYALAM)
- {
- for (unsigned int i = base + 1; i < end; i++)
- {
- while (i < end && is_joiner (info[i]))
- i++;
- if (i == end || !is_halant (info[i]))
- break;
- i++; /* Skip halant. */
- while (i < end && is_joiner (info[i]))
- i++;
- if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C)
- {
- base = i;
- info[base].indic_position() = POS_BASE_C;
- }
- }
- }
-
- if (start < base && info[base].indic_position() > POS_BASE_C)
- base--;
- break;
- }
- if (base == end && start < base &&
- is_one_of (info[base - 1], FLAG (OT_ZWJ)))
- base--;
- if (base < end)
- while (start < base &&
- is_one_of (info[base], (FLAG (OT_N) | FLAG (OT_H))))
- base--;
-
-
- /* o Reorder matras:
- *
- * If a pre-base matra character had been reordered before applying basic
- * features, the glyph can be moved closer to the main consonant based on
- * whether half-forms had been formed. Actual position for the matra is
- * defined as “after last standalone halant glyph, after initial matra
- * position and before the main consonantâ€. If ZWJ or ZWNJ follow this
- * halant, position is moved after it.
- *
- * IMPLEMENTATION NOTES:
- *
- * It looks like the last sentence is wrong. Testing, with Windows 7 Uniscribe
- * and Devanagari shows that the behavior is best described as:
- *
- * "If ZWJ follows this halant, matra is NOT repositioned after this halant.
- * If ZWNJ follows this halant, position is moved after it."
- *
- * Test case, with Adobe Devanagari or Nirmala UI:
- *
- * U+091F,U+094D,U+200C,U+092F,U+093F
- * (Matra moves to the middle, after ZWNJ.)
- *
- * U+091F,U+094D,U+200D,U+092F,U+093F
- * (Matra does NOT move, stays to the left.)
- *
- * https://github.com/harfbuzz/harfbuzz/issues/1070
- */
-
- if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
- {
- /* If we lost track of base, alas, position before last thingy. */
- unsigned int new_pos = base == end ? base - 2 : base - 1;
-
- /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
- * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
- * We want to position matra after them.
- */
- if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
- {
- search:
- while (new_pos > start &&
- !(is_one_of (info[new_pos], (FLAG (OT_M) | FLAG (OT_H)))))
- new_pos--;
-
- /* If we found no Halant we are done.
- * Otherwise only proceed if the Halant does
- * not belong to the Matra itself! */
- if (is_halant (info[new_pos]) &&
- info[new_pos].indic_position() != POS_PRE_M)
- {
-#if 0 // See comment above
- /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
- if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
- new_pos++;
-#endif
- if (new_pos + 1 < end)
- {
- /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
- if (info[new_pos + 1].indic_category() == OT_ZWJ)
- {
- /* Keep searching. */
- if (new_pos > start)
- {
- new_pos--;
- goto search;
- }
- }
- /* -> If ZWNJ follows this halant, position is moved after it.
- *
- * IMPLEMENTATION NOTES:
- *
- * This is taken care of by the state-machine. A Halant,ZWNJ is a terminating
- * sequence for a consonant syllable; any pre-base matras occurring after it
- * will belong to the subsequent syllable.
- */
- }
- }
- else
- new_pos = start; /* No move. */
- }
-
- if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M)
- {
- /* Now go see if there's actually any matras... */
- for (unsigned int i = new_pos; i > start; i--)
- if (info[i - 1].indic_position () == POS_PRE_M)
- {
- unsigned int old_pos = i - 1;
- if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
- base--;
-
- hb_glyph_info_t tmp = info[old_pos];
- memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
- info[new_pos] = tmp;
-
- /* Note: this merge_clusters() is intentionally *after* the reordering.
- * Indic matra reordering is special and tricky... */
- buffer->merge_clusters (new_pos, hb_min (end, base + 1));
-
- new_pos--;
- }
- } else {
- for (unsigned int i = start; i < base; i++)
- if (info[i].indic_position () == POS_PRE_M) {
- buffer->merge_clusters (i, hb_min (end, base + 1));
- break;
- }
- }
- }
-
-
- /* o Reorder reph:
- *
- * Reph’s original position is always at the beginning of the syllable,
- * (i.e. it is not reordered at the character reordering stage). However,
- * it will be reordered according to the basic-forms shaping results.
- * Possible positions for reph, depending on the script, are; after main,
- * before post-base consonant forms, and after post-base consonant forms.
- */
-
- /* Two cases:
- *
- * - If repha is encoded as a sequence of characters (Ra,H or Ra,H,ZWJ), then
- * we should only move it if the sequence ligated to the repha form.
- *
- * - If repha is encoded separately and in the logical position, we should only
- * move it if it did NOT ligate. If it ligated, it's probably the font trying
- * to make it work without the reordering.
- */
- if (start + 1 < end &&
- info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
- ((info[start].indic_category() == OT_Repha) ^
- _hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
- {
- unsigned int new_reph_pos;
- reph_position_t reph_pos = indic_plan->config->reph_pos;
-
- /* 1. If reph should be positioned after post-base consonant forms,
- * proceed to step 5.
- */
- if (reph_pos == REPH_POS_AFTER_POST)
- {
- goto reph_step_5;
- }
-
- /* 2. If the reph repositioning class is not after post-base: target
- * position is after the first explicit halant glyph between the
- * first post-reph consonant and last main consonant. If ZWJ or ZWNJ
- * are following this halant, position is moved after it. If such
- * position is found, this is the target position. Otherwise,
- * proceed to the next step.
- *
- * Note: in old-implementation fonts, where classifications were
- * fixed in shaping engine, there was no case where reph position
- * will be found on this step.
- */
- {
- new_reph_pos = start + 1;
- while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
- new_reph_pos++;
-
- if (new_reph_pos < base && is_halant (info[new_reph_pos]))
- {
- /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
- if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
- new_reph_pos++;
- goto reph_move;
- }
- }
-
- /* 3. If reph should be repositioned after the main consonant: find the
- * first consonant not ligated with main, or find the first
- * consonant that is not a potential pre-base-reordering Ra.
- */
- if (reph_pos == REPH_POS_AFTER_MAIN)
- {
- new_reph_pos = base;
- while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN)
- new_reph_pos++;
- if (new_reph_pos < end)
- goto reph_move;
- }
-
- /* 4. If reph should be positioned before post-base consonant, find
- * first post-base classified consonant not ligated with main. If no
- * consonant is found, the target position should be before the
- * first matra, syllable modifier sign or vedic sign.
- */
- /* This is our take on what step 4 is trying to say (and failing, BADLY). */
- if (reph_pos == REPH_POS_AFTER_SUB)
- {
- new_reph_pos = base;
- while (new_reph_pos + 1 < end &&
- !( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
- new_reph_pos++;
- if (new_reph_pos < end)
- goto reph_move;
- }
-
- /* 5. If no consonant is found in steps 3 or 4, move reph to a position
- * immediately before the first post-base matra, syllable modifier
- * sign or vedic sign that has a reordering class after the intended
- * reph position. For example, if the reordering position for reph
- * is post-main, it will skip above-base matras that also have a
- * post-main position.
- */
- reph_step_5:
- {
- /* Copied from step 2. */
- new_reph_pos = start + 1;
- while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
- new_reph_pos++;
-
- if (new_reph_pos < base && is_halant (info[new_reph_pos]))
- {
- /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
- if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
- new_reph_pos++;
- goto reph_move;
- }
- }
- /* See https://github.com/harfbuzz/harfbuzz/issues/2298#issuecomment-615318654 */
-
- /* 6. Otherwise, reorder reph to the end of the syllable.
- */
- {
- new_reph_pos = end - 1;
- while (new_reph_pos > start && info[new_reph_pos].indic_position() == POS_SMVD)
- new_reph_pos--;
-
- /*
- * If the Reph is to be ending up after a Matra,Halant sequence,
- * position it before that Halant so it can interact with the Matra.
- * However, if it's a plain Consonant,Halant we shouldn't do that.
- * Uniscribe doesn't do this.
- * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
- */
- if (!indic_plan->uniscribe_bug_compatible &&
- unlikely (is_halant (info[new_reph_pos])))
- {
- for (unsigned int i = base + 1; i < new_reph_pos; i++)
- if (info[i].indic_category() == OT_M) {
- /* Ok, got it. */
- new_reph_pos--;
- }
- }
-
- goto reph_move;
- }
-
- reph_move:
- {
- /* Move */
- buffer->merge_clusters (start, new_reph_pos + 1);
- hb_glyph_info_t reph = info[start];
- memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
- info[new_reph_pos] = reph;
-
- if (start < base && base <= new_reph_pos)
- base--;
- }
- }
-
-
- /* o Reorder pre-base-reordering consonants:
- *
- * If a pre-base-reordering consonant is found, reorder it according to
- * the following rules:
- */
-
- if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
- {
- for (unsigned int i = base + 1; i < end; i++)
- if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
- {
- /* 1. Only reorder a glyph produced by substitution during application
- * of the <pref> feature. (Note that a font may shape a Ra consonant with
- * the feature generally but block it in certain contexts.)
- */
- /* Note: We just check that something got substituted. We don't check that
- * the <pref> feature actually did it...
- *
- * Reorder pref only if it ligated. */
- if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
- {
- /*
- * 2. Try to find a target position the same way as for pre-base matra.
- * If it is found, reorder pre-base consonant glyph.
- *
- * 3. If position is not found, reorder immediately before main
- * consonant.
- */
-
- unsigned int new_pos = base;
- /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
- * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
- * We want to position matra after them.
- */
- if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
- {
- while (new_pos > start &&
- !(is_one_of (info[new_pos - 1], FLAG(OT_M) | FLAG (OT_H))))
- new_pos--;
- }
-
- if (new_pos > start && is_halant (info[new_pos - 1]))
- {
- /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
- if (new_pos < end && is_joiner (info[new_pos]))
- new_pos++;
- }
-
- {
- unsigned int old_pos = i;
-
- buffer->merge_clusters (new_pos, old_pos + 1);
- hb_glyph_info_t tmp = info[old_pos];
- memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
- info[new_pos] = tmp;
-
- if (new_pos <= base && base < old_pos)
- base++;
- }
- }
-
- break;
- }
- }
-
-
- /* Apply 'init' to the Left Matra if it's a word start. */
- if (info[start].indic_position () == POS_PRE_M)
- {
- if (!start ||
- !(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
- FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
- info[start].mask |= indic_plan->mask_array[INDIC_INIT];
- else
- buffer->unsafe_to_break (start - 1, start + 1);
- }
-
-
- /*
- * Finish off the clusters and go home!
- */
- if (indic_plan->uniscribe_bug_compatible)
- {
- switch ((hb_tag_t) plan->props.script)
- {
- case HB_SCRIPT_TAMIL:
- case HB_SCRIPT_SINHALA:
- break;
-
- default:
- /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil & Sinhala.
- * This means, half forms are submerged into the main consonant's cluster.
- * This is unnecessary, and makes cursor positioning harder, but that's what
- * Uniscribe does. */
- buffer->merge_clusters (start, end);
- break;
- }
- }
-}
-
-
-static void
-final_reordering_indic (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- unsigned int count = buffer->len;
- if (unlikely (!count)) return;
-
- if (buffer->message (font, "start reordering indic final")) {
- foreach_syllable (buffer, start, end)
- final_reordering_syllable_indic (plan, buffer, start, end);
- (void) buffer->message (font, "end reordering indic final");
- }
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
- HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
-}
-
-
-static void
-preprocess_text_indic (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- _hb_preprocess_text_vowel_constraints (plan, buffer, font);
-}
-
-static bool
-decompose_indic (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t ab,
- hb_codepoint_t *a,
- hb_codepoint_t *b)
-{
- switch (ab)
- {
- /* Don't decompose these. */
- case 0x0931u : return false; /* DEVANAGARI LETTER RRA */
- // https://github.com/harfbuzz/harfbuzz/issues/779
- case 0x09DCu : return false; /* BENGALI LETTER RRA */
- case 0x09DDu : return false; /* BENGALI LETTER RHA */
- case 0x0B94u : return false; /* TAMIL LETTER AU */
-
-
- /*
- * Decompose split matras that don't have Unicode decompositions.
- */
-
-#if 0
- /* Gujarati */
- /* This one has no decomposition in Unicode, but needs no decomposition either. */
- /* case 0x0AC9u : return false; */
-
- /* Oriya */
- case 0x0B57u : *a = no decomp, -> RIGHT; return true;
-#endif
- }
-
- if ((ab == 0x0DDAu || hb_in_range<hb_codepoint_t> (ab, 0x0DDCu, 0x0DDEu)))
- {
- /*
- * Sinhala split matras... Let the fun begin.
- *
- * These four characters have Unicode decompositions. However, Uniscribe
- * decomposes them "Khmer-style", that is, it uses the character itself to
- * get the second half. The first half of all four decompositions is always
- * U+0DD9.
- *
- * Now, there are buggy fonts, namely, the widely used lklug.ttf, that are
- * broken with Uniscribe. But we need to support them. As such, we only
- * do the Uniscribe-style decomposition if the character is transformed into
- * its "sec.half" form by the 'pstf' feature. Otherwise, we fall back to
- * Unicode decomposition.
- *
- * Note that we can't unconditionally use Unicode decomposition. That would
- * break some other fonts, that are designed to work with Uniscribe, and
- * don't have positioning features for the Unicode-style decomposition.
- *
- * Argh...
- *
- * The Uniscribe behavior is now documented in the newly published Sinhala
- * spec in 2012:
- *
- * https://docs.microsoft.com/en-us/typography/script-development/sinhala#shaping
- */
-
-
- const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) c->plan->data;
- hb_codepoint_t glyph;
- if (indic_plan->uniscribe_bug_compatible ||
- (c->font->get_nominal_glyph (ab, &glyph) &&
- indic_plan->pstf.would_substitute (&glyph, 1, c->font->face)))
- {
- /* Ok, safe to use Uniscribe-style decomposition. */
- *a = 0x0DD9u;
- *b = ab;
- return true;
- }
- }
-
- return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_indic (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t a,
- hb_codepoint_t b,
- hb_codepoint_t *ab)
-{
- /* Avoid recomposing split matras. */
- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
- return false;
-
- /* Composition-exclusion exceptions that we want to recompose. */
- if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
-
- return (bool) c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
-{
- collect_features_indic,
- override_features_indic,
- data_create_indic,
- data_destroy_indic,
- preprocess_text_indic,
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- decompose_indic,
- compose_indic,
- setup_masks_indic,
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
deleted file mode 100644
index dcb28a4e84..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-indic.hh
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * Copyright © 2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_INDIC_HH
-#define HB_OT_SHAPE_COMPLEX_INDIC_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-
-/* buffer var allocations */
-#define indic_category() complex_var_u8_category() /* indic_category_t */
-#define indic_position() complex_var_u8_auxiliary() /* indic_position_t */
-
-
-/* Cateories used in the OpenType spec:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari
- */
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum indic_category_t {
- OT_X = 0,
- OT_C = 1,
- OT_V = 2,
- OT_N = 3,
- OT_H = 4,
- OT_ZWNJ = 5,
- OT_ZWJ = 6,
- OT_M = 7,
- OT_SM = 8,
- /* OT_VD = 9, UNUSED; we use OT_A instead. */
- OT_A = 10,
- OT_PLACEHOLDER = 11,
- OT_DOTTEDCIRCLE = 12,
- OT_RS = 13, /* Register Shifter, used in Khmer OT spec. */
- OT_Coeng = 14, /* Khmer-style Virama. */
- OT_Repha = 15, /* Atomically-encoded logical or visual repha. */
- OT_Ra = 16,
- OT_CM = 17, /* Consonant-Medial. */
- OT_Symbol = 18, /* Avagraha, etc that take marks (SM,A,VD). */
- OT_CS = 19,
-
- /* The following are used by Khmer & Myanmar shapers. Defined
- * here for them to share. */
- OT_VAbv = 26,
- OT_VBlw = 27,
- OT_VPre = 28,
- OT_VPst = 29,
-};
-
-#define MEDIAL_FLAGS (FLAG (OT_CM))
-
-/* Note:
- *
- * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
- * cannot happen in a consonant syllable. The plus side however is, we can call the
- * consonant syllable logic from the vowel syllable function and get it all right! */
-#define CONSONANT_FLAGS (FLAG (OT_C) | FLAG (OT_CS) | FLAG (OT_Ra) | MEDIAL_FLAGS | FLAG (OT_V) | FLAG (OT_PLACEHOLDER) | FLAG (OT_DOTTEDCIRCLE))
-#define JOINER_FLAGS (FLAG (OT_ZWJ) | FLAG (OT_ZWNJ))
-
-
-/* Visual positions in a syllable from left to right. */
-enum indic_position_t {
- POS_START = 0,
-
- POS_RA_TO_BECOME_REPH = 1,
- POS_PRE_M = 2,
- POS_PRE_C = 3,
-
- POS_BASE_C = 4,
- POS_AFTER_MAIN = 5,
-
- POS_ABOVE_C = 6,
-
- POS_BEFORE_SUB = 7,
- POS_BELOW_C = 8,
- POS_AFTER_SUB = 9,
-
- POS_BEFORE_POST = 10,
- POS_POST_C = 11,
- POS_AFTER_POST = 12,
-
- POS_FINAL_C = 13,
- POS_SMVD = 14,
-
- POS_END = 15
-};
-
-/* Categories used in IndicSyllabicCategory.txt from UCD. */
-enum indic_syllabic_category_t {
- INDIC_SYLLABIC_CATEGORY_OTHER = OT_X,
-
- INDIC_SYLLABIC_CATEGORY_AVAGRAHA = OT_Symbol,
- INDIC_SYLLABIC_CATEGORY_BINDU = OT_SM,
- INDIC_SYLLABIC_CATEGORY_BRAHMI_JOINING_NUMBER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CANTILLATION_MARK = OT_A,
- INDIC_SYLLABIC_CATEGORY_CONSONANT = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_DEAD = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_FINAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_HEAD_LETTER = OT_C,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_KILLER = OT_M, /* U+17CD only. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PLACEHOLDER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PRECEDING_REPHA = OT_Repha,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_PREFIXED = OT_X, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUBJOINED = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA = OT_CM,
- INDIC_SYLLABIC_CATEGORY_CONSONANT_WITH_STACKER = OT_CS,
- INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK = OT_SM, /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- INDIC_SYLLABIC_CATEGORY_INVISIBLE_STACKER = OT_Coeng,
- INDIC_SYLLABIC_CATEGORY_JOINER = OT_ZWJ,
- INDIC_SYLLABIC_CATEGORY_MODIFYING_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_NON_JOINER = OT_ZWNJ,
- INDIC_SYLLABIC_CATEGORY_NUKTA = OT_N,
- INDIC_SYLLABIC_CATEGORY_NUMBER = OT_PLACEHOLDER,
- INDIC_SYLLABIC_CATEGORY_NUMBER_JOINER = OT_PLACEHOLDER, /* Don't care. */
- INDIC_SYLLABIC_CATEGORY_PURE_KILLER = OT_M, /* Is like a vowel matra. */
- INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER = OT_RS,
- INDIC_SYLLABIC_CATEGORY_SYLLABLE_MODIFIER = OT_SM,
- INDIC_SYLLABIC_CATEGORY_TONE_LETTER = OT_X,
- INDIC_SYLLABIC_CATEGORY_TONE_MARK = OT_N,
- INDIC_SYLLABIC_CATEGORY_VIRAMA = OT_H,
- INDIC_SYLLABIC_CATEGORY_VISARGA = OT_SM,
- INDIC_SYLLABIC_CATEGORY_VOWEL = OT_V,
- INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT = OT_M,
- INDIC_SYLLABIC_CATEGORY_VOWEL_INDEPENDENT = OT_V
-};
-
-/* Categories used in IndicSMatraCategory.txt from UCD */
-enum indic_matra_category_t {
- INDIC_MATRA_CATEGORY_NOT_APPLICABLE = POS_END,
-
- INDIC_MATRA_CATEGORY_LEFT = POS_PRE_C,
- INDIC_MATRA_CATEGORY_TOP = POS_ABOVE_C,
- INDIC_MATRA_CATEGORY_BOTTOM = POS_BELOW_C,
- INDIC_MATRA_CATEGORY_RIGHT = POS_POST_C,
-
- /* These should resolve to the position of the last part of the split sequence. */
- INDIC_MATRA_CATEGORY_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_LEFT = INDIC_MATRA_CATEGORY_BOTTOM,
- INDIC_MATRA_CATEGORY_TOP_AND_BOTTOM_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT = INDIC_MATRA_CATEGORY_TOP,
- INDIC_MATRA_CATEGORY_TOP_AND_LEFT_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
- INDIC_MATRA_CATEGORY_TOP_AND_RIGHT = INDIC_MATRA_CATEGORY_RIGHT,
-
- INDIC_MATRA_CATEGORY_OVERSTRUCK = POS_AFTER_MAIN,
- INDIC_MATRA_CATEGORY_VISUAL_ORDER_LEFT = POS_PRE_M
-};
-
-#define INDIC_COMBINE_CATEGORIES(S,M) \
- ( \
- static_assert_expr (S < 255 && M < 255) + \
- ( S | \
- ( \
- ( \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_MEDIAL || \
- S == INDIC_SYLLABIC_CATEGORY_GEMINATION_MARK || \
- S == INDIC_SYLLABIC_CATEGORY_REGISTER_SHIFTER || \
- S == INDIC_SYLLABIC_CATEGORY_CONSONANT_SUCCEEDING_REPHA || \
- S == INDIC_SYLLABIC_CATEGORY_VIRAMA || \
- S == INDIC_SYLLABIC_CATEGORY_VOWEL_DEPENDENT || \
- false \
- ? M : INDIC_MATRA_CATEGORY_NOT_APPLICABLE \
- ) << 8 \
- ) \
- ) \
- )
-
-HB_INTERNAL uint16_t
-hb_indic_get_categories (hb_codepoint_t u);
-
-
-static inline bool
-is_one_of (const hb_glyph_info_t &info, unsigned int flags)
-{
- /* If it ligated, all bets are off. */
- if (_hb_glyph_info_ligated (&info)) return false;
- return !!(FLAG_UNSAFE (info.indic_category()) & flags);
-}
-
-static inline bool
-is_joiner (const hb_glyph_info_t &info)
-{
- return is_one_of (info, JOINER_FLAGS);
-}
-
-static inline bool
-is_consonant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, CONSONANT_FLAGS);
-}
-
-static inline bool
-is_halant (const hb_glyph_info_t &info)
-{
- return is_one_of (info, FLAG (OT_H));
-}
-
-#define IN_HALF_BLOCK(u, Base) (((u) & ~0x7Fu) == (Base))
-
-#define IS_DEVA(u) (IN_HALF_BLOCK (u, 0x0900u))
-#define IS_BENG(u) (IN_HALF_BLOCK (u, 0x0980u))
-#define IS_GURU(u) (IN_HALF_BLOCK (u, 0x0A00u))
-#define IS_GUJR(u) (IN_HALF_BLOCK (u, 0x0A80u))
-#define IS_ORYA(u) (IN_HALF_BLOCK (u, 0x0B00u))
-#define IS_TAML(u) (IN_HALF_BLOCK (u, 0x0B80u))
-#define IS_TELU(u) (IN_HALF_BLOCK (u, 0x0C00u))
-#define IS_KNDA(u) (IN_HALF_BLOCK (u, 0x0C80u))
-#define IS_MLYM(u) (IN_HALF_BLOCK (u, 0x0D00u))
-#define IS_SINH(u) (IN_HALF_BLOCK (u, 0x0D80u))
-
-
-#define MATRA_POS_LEFT(u) POS_PRE_M
-#define MATRA_POS_RIGHT(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_POST : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_POST : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? (u <= 0x0C42u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_KNDA(u) ? (u < 0x0CC3u || u > 0xCD6u ? POS_BEFORE_SUB : POS_AFTER_SUB) : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_TOP(u) ( /* BENG and MLYM don't have top matras. */ \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : /* Deviate from spec */ \
- IS_GUJR(u) ? POS_AFTER_SUB : \
- IS_ORYA(u) ? POS_AFTER_MAIN : \
- IS_TAML(u) ? POS_AFTER_SUB : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-#define MATRA_POS_BOTTOM(u) ( \
- IS_DEVA(u) ? POS_AFTER_SUB : \
- IS_BENG(u) ? POS_AFTER_SUB : \
- IS_GURU(u) ? POS_AFTER_POST : \
- IS_GUJR(u) ? POS_AFTER_POST : \
- IS_ORYA(u) ? POS_AFTER_SUB : \
- IS_TAML(u) ? POS_AFTER_POST : \
- IS_TELU(u) ? POS_BEFORE_SUB : \
- IS_KNDA(u) ? POS_BEFORE_SUB : \
- IS_MLYM(u) ? POS_AFTER_POST : \
- IS_SINH(u) ? POS_AFTER_SUB : \
- /*default*/ POS_AFTER_SUB \
- )
-
-static inline indic_position_t
-matra_position_indic (hb_codepoint_t u, indic_position_t side)
-{
- switch ((int) side)
- {
- case POS_PRE_C: return MATRA_POS_LEFT (u);
- case POS_POST_C: return MATRA_POS_RIGHT (u);
- case POS_ABOVE_C: return MATRA_POS_TOP (u);
- case POS_BELOW_C: return MATRA_POS_BOTTOM (u);
- }
- return side;
-}
-
-/* XXX
- * This is a hack for now. We should move this data into the main Indic table.
- * Or completely remove it and just check in the tables.
- */
-static const hb_codepoint_t ra_chars[] = {
- 0x0930u, /* Devanagari */
- 0x09B0u, /* Bengali */
- 0x09F0u, /* Bengali */
- 0x0A30u, /* Gurmukhi */ /* No Reph */
- 0x0AB0u, /* Gujarati */
- 0x0B30u, /* Oriya */
- 0x0BB0u, /* Tamil */ /* No Reph */
- 0x0C30u, /* Telugu */ /* Reph formed only with ZWJ */
- 0x0CB0u, /* Kannada */
- 0x0D30u, /* Malayalam */ /* No Reph, Logical Repha */
-
- 0x0DBBu, /* Sinhala */ /* Reph formed only with ZWJ */
-};
-
-static inline bool
-is_ra (hb_codepoint_t u)
-{
- return hb_array (ra_chars).lfind (u);
-}
-
-static inline void
-set_indic_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- indic_category_t cat = (indic_category_t) (type & 0xFFu);
- indic_position_t pos = (indic_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- */
-
- /* The following act more like the Bindus. */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x0953u, 0x0954u)))
- cat = OT_SM;
- /* The following act like consonants. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0x0A72u, 0x0A73u,
- 0x1CF5u, 0x1CF6u)))
- cat = OT_C;
- /* TODO: The following should only be allowed after a Visarga.
- * For now, just treat them like regular tone marks. */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x1CE2u, 0x1CE8u)))
- cat = OT_A;
- /* TODO: The following should only be allowed after some of
- * the nasalization marks, maybe only for U+1CE9..U+1CF1.
- * For now, just treat them like tone marks. */
- else if (unlikely (u == 0x1CEDu))
- cat = OT_A;
- /* The following take marks in standalone clusters, similar to Avagraha. */
- else if (unlikely (hb_in_ranges<hb_codepoint_t> (u, 0xA8F2u, 0xA8F7u,
- 0x1CE9u, 0x1CECu,
- 0x1CEEu, 0x1CF1u)))
- {
- cat = OT_Symbol;
- static_assert (((int) INDIC_SYLLABIC_CATEGORY_AVAGRAHA == OT_Symbol), "");
- }
- else if (unlikely (u == 0x0A51u))
- {
- /* https://github.com/harfbuzz/harfbuzz/issues/524 */
- cat = OT_M;
- pos = POS_BELOW_C;
- }
-
- /* According to ScriptExtensions.txt, these Grantha marks may also be used in Tamil,
- * so the Indic shaper needs to know their categories. */
- else if (unlikely (u == 0x11301u || u == 0x11303u)) cat = OT_SM;
- else if (unlikely (u == 0x1133Bu || u == 0x1133Cu)) cat = OT_N;
-
- else if (unlikely (u == 0x0AFBu)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/552 */
- else if (unlikely (u == 0x0B55u)) cat = OT_N; /* https://github.com/harfbuzz/harfbuzz/issues/2849 */
-
- else if (unlikely (u == 0x0980u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/issues/538 */
- else if (unlikely (u == 0x09FCu)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/1613 */
- else if (unlikely (u == 0x0C80u)) cat = OT_PLACEHOLDER; /* https://github.com/harfbuzz/harfbuzz/pull/623 */
- else if (unlikely (hb_in_range<hb_codepoint_t> (u, 0x2010u, 0x2011u)))
- cat = OT_PLACEHOLDER;
- else if (unlikely (u == 0x25CCu)) cat = OT_DOTTEDCIRCLE;
-
-
- /*
- * Re-assign position.
- */
-
- if ((FLAG_UNSAFE (cat) & CONSONANT_FLAGS))
- {
- pos = POS_BASE_C;
- if (is_ra (u))
- cat = OT_Ra;
- }
- else if (cat == OT_M)
- {
- pos = matra_position_indic (u, pos);
- }
- else if ((FLAG_UNSAFE (cat) & (FLAG (OT_SM) /* | FLAG (OT_VD) */ | FLAG (OT_A) | FLAG (OT_Symbol))))
- {
- pos = POS_SMVD;
- }
-
- if (unlikely (u == 0x0B01u)) pos = POS_BEFORE_SUB; /* Oriya Bindu is BeforeSub in the spec. */
-
-
-
- info.indic_category() = cat;
- info.indic_position() = pos;
-}
-
-struct hb_indic_would_substitute_feature_t
-{
- void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
- {
- zero_context = zero_context_;
- map->get_stage_lookups (0/*GSUB*/,
- map->get_feature_stage (0/*GSUB*/, feature_tag),
- &lookups, &count);
- }
-
- bool would_substitute (const hb_codepoint_t *glyphs,
- unsigned int glyphs_count,
- hb_face_t *face) const
- {
- for (unsigned int i = 0; i < count; i++)
- if (hb_ot_layout_lookup_would_substitute (face, lookups[i].index, glyphs, glyphs_count, zero_context))
- return true;
- return false;
- }
-
- private:
- const hb_ot_map_t::lookup_map_t *lookups;
- unsigned int count;
- bool zero_context;
-};
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_INDIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
deleted file mode 100644
index c52f72f394..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer-machine.hh
+++ /dev/null
@@ -1,396 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-khmer-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH
-
-#include "hb.hh"
-
-enum khmer_syllable_type_t {
- khmer_consonant_syllable,
- khmer_broken_cluster,
- khmer_non_khmer_cluster,
-};
-
-
-#line 42 "hb-ot-shape-complex-khmer-machine.hh"
-#define khmer_syllable_machine_ex_C 1u
-#define khmer_syllable_machine_ex_Coeng 14u
-#define khmer_syllable_machine_ex_DOTTEDCIRCLE 12u
-#define khmer_syllable_machine_ex_PLACEHOLDER 11u
-#define khmer_syllable_machine_ex_Ra 16u
-#define khmer_syllable_machine_ex_Robatic 20u
-#define khmer_syllable_machine_ex_V 2u
-#define khmer_syllable_machine_ex_VAbv 26u
-#define khmer_syllable_machine_ex_VBlw 27u
-#define khmer_syllable_machine_ex_VPre 28u
-#define khmer_syllable_machine_ex_VPst 29u
-#define khmer_syllable_machine_ex_Xgroup 21u
-#define khmer_syllable_machine_ex_Ygroup 22u
-#define khmer_syllable_machine_ex_ZWJ 6u
-#define khmer_syllable_machine_ex_ZWNJ 5u
-
-
-#line 60 "hb-ot-shape-complex-khmer-machine.hh"
-static const unsigned char _khmer_syllable_machine_trans_keys[] = {
- 5u, 26u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u, 5u, 21u,
- 5u, 26u, 5u, 21u, 5u, 21u, 5u, 26u, 5u, 21u, 1u, 16u, 5u, 21u, 5u, 26u,
- 5u, 21u, 5u, 26u, 5u, 21u, 5u, 26u, 1u, 29u, 5u, 29u, 5u, 29u, 5u, 29u,
- 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 26u, 5u, 29u,
- 5u, 29u, 22u, 22u, 5u, 22u, 5u, 29u, 5u, 29u, 1u, 16u, 5u, 29u, 5u, 29u,
- 0
-};
-
-static const char _khmer_syllable_machine_key_spans[] = {
- 22, 17, 22, 17, 16, 17, 22, 17,
- 22, 17, 17, 22, 17, 16, 17, 22,
- 17, 22, 17, 22, 29, 25, 25, 25,
- 1, 18, 25, 25, 25, 16, 22, 25,
- 25, 1, 18, 25, 25, 16, 25, 25
-};
-
-static const short _khmer_syllable_machine_index_offsets[] = {
- 0, 23, 41, 64, 82, 99, 117, 140,
- 158, 181, 199, 217, 240, 258, 275, 293,
- 316, 334, 357, 375, 398, 428, 454, 480,
- 506, 508, 527, 553, 579, 605, 622, 645,
- 671, 697, 699, 718, 744, 770, 787, 813
-};
-
-static const char _khmer_syllable_machine_indicies[] = {
- 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 2,
- 3, 0, 0, 0, 0, 4, 0, 1,
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 3,
- 0, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 3, 0, 0, 0, 0, 4, 0,
- 5, 5, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 4, 0, 6, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 6, 0, 7, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 8, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 10, 0, 0,
- 0, 0, 4, 0, 9, 9, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 10, 0, 11, 11,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 12, 0,
- 0, 0, 0, 4, 0, 11, 11, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 0, 14,
- 14, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15,
- 13, 14, 14, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 15, 16, 16, 16, 16, 17, 16,
- 18, 18, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 17, 16, 19, 19, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 19, 16, 20, 20, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 21, 16, 22, 22, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 23, 16, 16,
- 16, 16, 17, 16, 22, 22, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 23, 16, 24, 24,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 25, 16,
- 16, 16, 16, 17, 16, 24, 24, 16,
- 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 25, 16, 14,
- 14, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 26, 15,
- 16, 16, 16, 16, 17, 16, 28, 28,
- 27, 27, 29, 29, 27, 27, 27, 27,
- 2, 2, 27, 30, 27, 28, 27, 27,
- 27, 27, 15, 19, 27, 27, 27, 17,
- 23, 25, 21, 27, 32, 32, 31, 31,
- 31, 31, 31, 31, 31, 33, 31, 31,
- 31, 31, 31, 2, 3, 6, 31, 31,
- 31, 4, 10, 12, 8, 31, 34, 34,
- 31, 31, 31, 31, 31, 31, 31, 35,
- 31, 31, 31, 31, 31, 31, 3, 6,
- 31, 31, 31, 4, 10, 12, 8, 31,
- 5, 5, 31, 31, 31, 31, 31, 31,
- 31, 35, 31, 31, 31, 31, 31, 31,
- 4, 6, 31, 31, 31, 31, 31, 31,
- 8, 31, 6, 31, 7, 7, 31, 31,
- 31, 31, 31, 31, 31, 35, 31, 31,
- 31, 31, 31, 31, 8, 6, 31, 36,
- 36, 31, 31, 31, 31, 31, 31, 31,
- 35, 31, 31, 31, 31, 31, 31, 10,
- 6, 31, 31, 31, 4, 31, 31, 8,
- 31, 37, 37, 31, 31, 31, 31, 31,
- 31, 31, 35, 31, 31, 31, 31, 31,
- 31, 12, 6, 31, 31, 31, 4, 10,
- 31, 8, 31, 34, 34, 31, 31, 31,
- 31, 31, 31, 31, 33, 31, 31, 31,
- 31, 31, 31, 3, 6, 31, 31, 31,
- 4, 10, 12, 8, 31, 28, 28, 31,
- 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 28, 31, 14, 14,
- 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 15, 38,
- 38, 38, 38, 17, 38, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 41, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 18,
- 18, 39, 39, 39, 39, 39, 39, 39,
- 41, 39, 39, 39, 39, 39, 39, 17,
- 19, 39, 39, 39, 39, 39, 39, 21,
- 39, 19, 39, 20, 20, 39, 39, 39,
- 39, 39, 39, 39, 41, 39, 39, 39,
- 39, 39, 39, 21, 19, 39, 42, 42,
- 39, 39, 39, 39, 39, 39, 39, 41,
- 39, 39, 39, 39, 39, 39, 23, 19,
- 39, 39, 39, 17, 39, 39, 21, 39,
- 43, 43, 39, 39, 39, 39, 39, 39,
- 39, 41, 39, 39, 39, 39, 39, 39,
- 25, 19, 39, 39, 39, 17, 23, 39,
- 21, 39, 44, 44, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 44, 39, 45, 45, 39, 39, 39,
- 39, 39, 39, 39, 30, 39, 39, 39,
- 39, 39, 26, 15, 19, 39, 39, 39,
- 17, 23, 25, 21, 39, 40, 40, 39,
- 39, 39, 39, 39, 39, 39, 30, 39,
- 39, 39, 39, 39, 39, 15, 19, 39,
- 39, 39, 17, 23, 25, 21, 39, 0
-};
-
-static const char _khmer_syllable_machine_trans_targs[] = {
- 20, 1, 28, 22, 23, 3, 24, 5,
- 25, 7, 26, 9, 27, 20, 10, 31,
- 20, 32, 12, 33, 14, 34, 16, 35,
- 18, 36, 39, 20, 21, 30, 37, 20,
- 0, 29, 2, 4, 6, 8, 20, 20,
- 11, 13, 15, 17, 38, 19
-};
-
-static const char _khmer_syllable_machine_trans_actions[] = {
- 1, 0, 2, 2, 2, 0, 0, 0,
- 2, 0, 2, 0, 2, 3, 0, 4,
- 5, 2, 0, 0, 0, 2, 0, 2,
- 0, 2, 4, 8, 2, 9, 0, 10,
- 0, 0, 0, 0, 0, 0, 11, 12,
- 0, 0, 0, 0, 4, 0
-};
-
-static const char _khmer_syllable_machine_to_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _khmer_syllable_machine_from_state_actions[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const unsigned char _khmer_syllable_machine_eof_trans[] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 14, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 39, 40,
- 40, 40, 40, 40, 40, 40, 40, 40
-};
-
-static const int khmer_syllable_machine_start = 20;
-static const int khmer_syllable_machine_first_final = 20;
-static const int khmer_syllable_machine_error = -1;
-
-static const int khmer_syllable_machine_en_main = 20;
-
-
-#line 43 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-
-#line 86 "hb-ot-shape-complex-khmer-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_khmer (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 266 "hb-ot-shape-complex-khmer-machine.hh"
- {
- cs = khmer_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 106 "hb-ot-shape-complex-khmer-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 282 "hb-ot-shape-complex-khmer-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
- case 7:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 296 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
- _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
-
- _slen = _khmer_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
- ( info[p].khmer_category()) <= _keys[1] ?
- ( info[p].khmer_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _khmer_syllable_machine_trans_targs[_trans];
-
- if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
- case 2:
-#line 1 "NONE"
- {te = p+1;}
- break;
- case 8:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 10:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 12:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_broken_cluster); }}
- break;
- case 11:
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
- break;
- case 1:
-#line 80 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
- break;
- case 5:
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); }}
- break;
- case 3:
-#line 1 "NONE"
- { switch( act ) {
- case 2:
- {{p = ((te))-1;} found_syllable (khmer_broken_cluster); }
- break;
- case 3:
- {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
- break;
- }
- }
- break;
- case 4:
-#line 1 "NONE"
- {te = p+1;}
-#line 81 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 2;}
- break;
- case 9:
-#line 1 "NONE"
- {te = p+1;}
-#line 82 "hb-ot-shape-complex-khmer-machine.rl"
- {act = 3;}
- break;
-#line 366 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
-_again:
- switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
- case 6:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 375 "hb-ot-shape-complex-khmer-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 114 "hb-ot-shape-complex-khmer-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
deleted file mode 100644
index 7787886857..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.cc
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-khmer.hh"
-#include "hb-ot-shape-complex-khmer-machine.hh"
-#include "hb-ot-layout.hh"
-
-
-/*
- * Khmer shaper.
- */
-
-static const hb_ot_map_feature_t
-khmer_features[] =
-{
- /*
- * Basic features.
- * These features are applied all at once, before reordering, constrained
- * to the syllable.
- */
- {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS},
- {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS},
- {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS},
- {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS},
- {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS},
- /*
- * Other features.
- * These features are applied all at once after clearing syllables.
- */
- {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
- {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
-};
-
-/*
- * Must be in the same order as the khmer_features array.
- */
-enum {
- KHMER_PREF,
- KHMER_BLWF,
- KHMER_ABVF,
- KHMER_PSTF,
- KHMER_CFAR,
-
- _KHMER_PRES,
- _KHMER_ABVS,
- _KHMER_BLWS,
- _KHMER_PSTS,
-
- KHMER_NUM_FEATURES,
- KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
-};
-
-static void
-setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-reorder_khmer (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-collect_features_khmer (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* Do this before any lookups have been applied. */
- map->add_gsub_pause (setup_syllables_khmer);
- map->add_gsub_pause (reorder_khmer);
-
- /* Testing suggests that Uniscribe does NOT pause between basic
- * features. Test with KhmerUI.ttf and the following three
- * sequences:
- *
- * U+1789,U+17BC
- * U+1789,U+17D2,U+1789
- * U+1789,U+17D2,U+1789,U+17BC
- *
- * https://github.com/harfbuzz/harfbuzz/issues/974
- */
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
-
- unsigned int i = 0;
- for (; i < KHMER_BASIC_FEATURES; i++)
- map->add_feature (khmer_features[i]);
-
- map->add_gsub_pause (_hb_clear_syllables);
-
- for (; i < KHMER_NUM_FEATURES; i++)
- map->add_feature (khmer_features[i]);
-}
-
-static void
-override_features_khmer (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* Khmer spec has 'clig' as part of required shaping features:
- * "Apply feature 'clig' to form ligatures that are desired for
- * typographical correctness.", hence in overrides... */
- map->enable_feature (HB_TAG('c','l','i','g'));
-
- /* Uniscribe does not apply 'kern' in Khmer. */
- if (hb_options ().uniscribe_bug_compatible)
- {
- map->disable_feature (HB_TAG('k','e','r','n'));
- }
-
- map->disable_feature (HB_TAG('l','i','g','a'));
-}
-
-
-struct khmer_shape_plan_t
-{
- hb_mask_t mask_array[KHMER_NUM_FEATURES];
-};
-
-static void *
-data_create_khmer (const hb_ot_shape_plan_t *plan)
-{
- khmer_shape_plan_t *khmer_plan = (khmer_shape_plan_t *) hb_calloc (1, sizeof (khmer_shape_plan_t));
- if (unlikely (!khmer_plan))
- return nullptr;
-
- for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++)
- khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ?
- 0 : plan->map.get_1_mask (khmer_features[i].tag);
-
- return khmer_plan;
-}
-
-static void
-data_destroy_khmer (void *data)
-{
- hb_free (data);
-}
-
-static void
-setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
-
- /* We cannot setup masks here. We save information about characters
- * and setup masks later on in a pause-callback. */
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- set_khmer_properties (info[i]);
-}
-
-static void
-setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- find_syllables_khmer (buffer);
- foreach_syllable (buffer, start, end)
- buffer->unsafe_to_break (start, end);
-}
-
-
-/* Rules from:
- * https://docs.microsoft.com/en-us/typography/script-development/devanagari */
-
-static void
-reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
- hb_face_t *face HB_UNUSED,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
- hb_glyph_info_t *info = buffer->info;
-
- /* Setup masks. */
- {
- /* Post-base */
- hb_mask_t mask = khmer_plan->mask_array[KHMER_BLWF] |
- khmer_plan->mask_array[KHMER_ABVF] |
- khmer_plan->mask_array[KHMER_PSTF];
- for (unsigned int i = start + 1; i < end; i++)
- info[i].mask |= mask;
- }
-
- unsigned int num_coengs = 0;
- for (unsigned int i = start + 1; i < end; i++)
- {
- /* """
- * When a COENG + (Cons | IndV) combination are found (and subscript count
- * is less than two) the character combination is handled according to the
- * subscript type of the character following the COENG.
- *
- * ...
- *
- * Subscript Type 2 - The COENG + RO characters are reordered to immediately
- * before the base glyph. Then the COENG + RO characters are assigned to have
- * the 'pref' OpenType feature applied to them.
- * """
- */
- if (info[i].khmer_category() == OT_Coeng && num_coengs <= 2 && i + 1 < end)
- {
- num_coengs++;
-
- if (info[i + 1].khmer_category() == OT_Ra)
- {
- for (unsigned int j = 0; j < 2; j++)
- info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
-
- /* Move the Coeng,Ro sequence to the start. */
- buffer->merge_clusters (start, i + 2);
- hb_glyph_info_t t0 = info[i];
- hb_glyph_info_t t1 = info[i + 1];
- memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
- info[start] = t0;
- info[start + 1] = t1;
-
- /* Mark the subsequent stuff with 'cfar'. Used in Khmer.
- * Read the feature spec.
- * This allows distinguishing the following cases with MS Khmer fonts:
- * U+1784,U+17D2,U+179A,U+17D2,U+1782
- * U+1784,U+17D2,U+1782,U+17D2,U+179A
- */
- if (khmer_plan->mask_array[KHMER_CFAR])
- for (unsigned int j = i + 2; j < end; j++)
- info[j].mask |= khmer_plan->mask_array[KHMER_CFAR];
-
- num_coengs = 2; /* Done. */
- }
- }
-
- /* Reorder left matra piece. */
- else if (info[i].khmer_category() == OT_VPre)
- {
- /* Move to the start. */
- buffer->merge_clusters (start, i + 1);
- hb_glyph_info_t t = info[i];
- memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
- info[start] = t;
- }
- }
-}
-
-static void
-reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
- hb_face_t *face,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
- switch (syllable_type)
- {
- case khmer_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
- case khmer_consonant_syllable:
- reorder_consonant_syllable (plan, face, buffer, start, end);
- break;
-
- case khmer_non_khmer_cluster:
- break;
- }
-}
-
-static void
-reorder_khmer (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (buffer->message (font, "start reordering khmer"))
- {
- hb_syllabic_insert_dotted_circles (font, buffer,
- khmer_broken_cluster,
- OT_DOTTEDCIRCLE,
- OT_Repha);
-
- foreach_syllable (buffer, start, end)
- reorder_syllable_khmer (plan, font->face, buffer, start, end);
- (void) buffer->message (font, "end reordering khmer");
- }
- HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
-}
-
-
-static bool
-decompose_khmer (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t ab,
- hb_codepoint_t *a,
- hb_codepoint_t *b)
-{
- switch (ab)
- {
- /*
- * Decompose split matras that don't have Unicode decompositions.
- */
-
- /* Khmer */
- case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true;
- case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true;
- case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true;
- case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true;
- case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true;
- }
-
- return (bool) c->unicode->decompose (ab, a, b);
-}
-
-static bool
-compose_khmer (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t a,
- hb_codepoint_t b,
- hb_codepoint_t *ab)
-{
- /* Avoid recomposing split matras. */
- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
- return false;
-
- return (bool) c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_khmer =
-{
- collect_features_khmer,
- override_features_khmer,
- data_create_khmer,
- data_destroy_khmer,
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- decompose_khmer,
- compose_khmer,
- setup_masks_khmer,
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
deleted file mode 100644
index 35bfbb64d5..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-khmer.hh
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_KHMER_HH
-#define HB_OT_SHAPE_COMPLEX_KHMER_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define khmer_category() indic_category() /* khmer_category_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum khmer_category_t
-{
- OT_Robatic = 20,
- OT_Xgroup = 21,
- OT_Ygroup = 22,
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
-};
-
-using khmer_position_t = indic_position_t;
-
-static inline void
-set_khmer_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- khmer_category_t cat = (khmer_category_t) (type & 0xFFu);
- khmer_position_t pos = (khmer_position_t) (type >> 8);
-
-
- /*
- * Re-assign category
- *
- * These categories are experimentally extracted from what Uniscribe allows.
- */
- switch (u)
- {
- case 0x179Au:
- cat = (khmer_category_t) OT_Ra;
- break;
-
- case 0x17CCu:
- case 0x17C9u:
- case 0x17CAu:
- cat = OT_Robatic;
- break;
-
- case 0x17C6u:
- case 0x17CBu:
- case 0x17CDu:
- case 0x17CEu:
- case 0x17CFu:
- case 0x17D0u:
- case 0x17D1u:
- cat = OT_Xgroup;
- break;
-
- case 0x17C7u:
- case 0x17C8u:
- case 0x17DDu:
- case 0x17D3u: /* Just guessing. Uniscribe doesn't categorize it. */
- cat = OT_Ygroup;
- break;
- }
-
- /*
- * Re-assign position.
- */
- if (cat == (khmer_category_t) OT_M)
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (khmer_category_t) OT_VPre; break;
- case POS_BELOW_C: cat = (khmer_category_t) OT_VBlw; break;
- case POS_ABOVE_C: cat = (khmer_category_t) OT_VAbv; break;
- case POS_POST_C: cat = (khmer_category_t) OT_VPst; break;
- default: assert (0);
- }
-
- info.khmer_category() = cat;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_KHMER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
deleted file mode 100644
index f4ef33004d..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar-machine.hh
+++ /dev/null
@@ -1,492 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-myanmar-machine.rl"
-/*
- * Copyright © 2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH
-
-#include "hb.hh"
-
-enum myanmar_syllable_type_t {
- myanmar_consonant_syllable,
- myanmar_punctuation_cluster,
- myanmar_broken_cluster,
- myanmar_non_myanmar_cluster,
-};
-
-
-#line 43 "hb-ot-shape-complex-myanmar-machine.hh"
-#define myanmar_syllable_machine_ex_A 10u
-#define myanmar_syllable_machine_ex_As 18u
-#define myanmar_syllable_machine_ex_C 1u
-#define myanmar_syllable_machine_ex_CS 19u
-#define myanmar_syllable_machine_ex_D 32u
-#define myanmar_syllable_machine_ex_D0 20u
-#define myanmar_syllable_machine_ex_DB 3u
-#define myanmar_syllable_machine_ex_GB 11u
-#define myanmar_syllable_machine_ex_H 4u
-#define myanmar_syllable_machine_ex_IV 2u
-#define myanmar_syllable_machine_ex_MH 21u
-#define myanmar_syllable_machine_ex_ML 33u
-#define myanmar_syllable_machine_ex_MR 22u
-#define myanmar_syllable_machine_ex_MW 23u
-#define myanmar_syllable_machine_ex_MY 24u
-#define myanmar_syllable_machine_ex_P 31u
-#define myanmar_syllable_machine_ex_PT 25u
-#define myanmar_syllable_machine_ex_Ra 16u
-#define myanmar_syllable_machine_ex_V 8u
-#define myanmar_syllable_machine_ex_VAbv 26u
-#define myanmar_syllable_machine_ex_VBlw 27u
-#define myanmar_syllable_machine_ex_VPre 28u
-#define myanmar_syllable_machine_ex_VPst 29u
-#define myanmar_syllable_machine_ex_VS 30u
-#define myanmar_syllable_machine_ex_ZWJ 6u
-#define myanmar_syllable_machine_ex_ZWNJ 5u
-
-
-#line 72 "hb-ot-shape-complex-myanmar-machine.hh"
-static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
- 1u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 5u, 29u, 5u, 8u, 5u, 29u, 3u, 25u, 5u, 25u, 5u, 25u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 33u, 1u, 16u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 29u, 3u, 29u, 3u, 29u, 3u, 30u, 3u, 29u, 3u, 33u, 3u, 33u,
- 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 3u, 33u, 1u, 33u, 1u, 32u, 8u, 8u,
- 0
-};
-
-static const char _myanmar_syllable_machine_key_spans[] = {
- 33, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 27, 27, 27, 28, 27, 31, 31, 31,
- 31, 31, 25, 4, 25, 23, 21, 21,
- 31, 27, 27, 27, 31, 16, 31, 31,
- 31, 27, 27, 27, 28, 27, 31, 31,
- 31, 31, 31, 31, 31, 33, 32, 1
-};
-
-static const short _myanmar_syllable_machine_index_offsets[] = {
- 0, 34, 66, 92, 97, 123, 147, 169,
- 191, 223, 251, 279, 307, 339, 356, 388,
- 420, 448, 476, 504, 533, 561, 593, 625,
- 657, 689, 721, 747, 752, 778, 802, 824,
- 846, 878, 906, 934, 962, 994, 1011, 1043,
- 1075, 1107, 1135, 1163, 1191, 1220, 1248, 1280,
- 1312, 1344, 1376, 1408, 1440, 1472, 1506, 1539
-};
-
-static const char _myanmar_syllable_machine_indicies[] = {
- 1, 1, 2, 3, 4, 4, 0, 5,
- 0, 6, 1, 0, 0, 0, 0, 7,
- 0, 8, 9, 0, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 1,
- 21, 0, 23, 24, 25, 25, 22, 26,
- 22, 27, 22, 22, 22, 22, 22, 22,
- 22, 28, 22, 22, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 22, 22,
- 39, 22, 25, 25, 22, 26, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 40,
- 22, 22, 22, 22, 22, 22, 33, 22,
- 22, 22, 37, 22, 25, 25, 22, 26,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 41, 22, 25, 25, 22,
- 26, 22, 33, 22, 22, 22, 22, 22,
- 22, 22, 42, 22, 22, 22, 22, 22,
- 22, 33, 22, 25, 25, 22, 26, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 42, 22, 22, 22, 22, 22, 22, 33,
- 22, 25, 25, 22, 26, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 43, 22,
- 22, 44, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 22, 22, 43, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 22, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 23,
- 22, 25, 25, 22, 26, 22, 27, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 33, 45, 22,
- 22, 37, 22, 23, 22, 25, 25, 22,
- 26, 22, 27, 22, 22, 22, 22, 22,
- 22, 22, 43, 22, 22, 22, 22, 22,
- 22, 33, 45, 22, 22, 37, 22, 22,
- 22, 43, 22, 1, 1, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 1, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 28, 22, 22, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 46, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 22, 22, 39, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 34, 35, 36, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 22, 37, 22, 23, 22, 25, 25,
- 22, 26, 22, 27, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 33, 22, 35, 22, 37, 22,
- 23, 22, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 33, 34,
- 35, 36, 37, 46, 22, 23, 22, 25,
- 25, 22, 26, 22, 27, 22, 22, 22,
- 22, 22, 22, 22, 46, 22, 22, 22,
- 22, 22, 22, 33, 34, 35, 36, 37,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 22, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 46, 22, 22, 29, 22, 22, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 47, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 22, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 29, 30, 31, 22, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 23, 24, 25, 25, 22, 26, 22,
- 27, 22, 22, 22, 22, 22, 22, 22,
- 28, 22, 22, 29, 30, 31, 32, 33,
- 34, 35, 36, 37, 22, 22, 22, 39,
- 22, 49, 49, 48, 5, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 50, 48,
- 48, 48, 48, 48, 48, 14, 48, 48,
- 48, 18, 48, 49, 49, 48, 5, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 51, 48, 49, 49, 48, 5,
- 48, 14, 48, 48, 48, 48, 48, 48,
- 48, 52, 48, 48, 48, 48, 48, 48,
- 14, 48, 49, 49, 48, 5, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 52,
- 48, 48, 48, 48, 48, 48, 14, 48,
- 49, 49, 48, 5, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 53, 48, 48,
- 54, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 48, 48, 53, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 48, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 2, 48,
- 49, 49, 48, 5, 48, 6, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 14, 55, 48, 48,
- 18, 48, 2, 48, 49, 49, 48, 5,
- 48, 6, 48, 48, 48, 48, 48, 48,
- 48, 53, 48, 48, 48, 48, 48, 48,
- 14, 55, 48, 48, 18, 48, 48, 48,
- 53, 48, 56, 56, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 56, 48, 2, 3, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 8, 48, 48, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 57, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 48,
- 48, 21, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 15, 16, 17, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 48, 18, 48, 2, 48, 49, 49, 48,
- 5, 48, 6, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 14, 48, 16, 48, 18, 48, 2,
- 48, 49, 49, 48, 5, 48, 6, 48,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 14, 15, 16,
- 17, 18, 57, 48, 2, 48, 49, 49,
- 48, 5, 48, 6, 48, 48, 48, 48,
- 48, 48, 48, 57, 48, 48, 48, 48,
- 48, 48, 14, 15, 16, 17, 18, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 48, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 57,
- 48, 48, 10, 48, 48, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 58,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 48, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 10, 11, 12, 48, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 2, 3, 49, 49, 48, 5, 48, 6,
- 48, 48, 48, 48, 48, 48, 48, 8,
- 48, 48, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 48, 48, 48, 21, 48,
- 23, 24, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 59,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 22, 22, 39, 22,
- 23, 60, 25, 25, 22, 26, 22, 27,
- 22, 22, 22, 22, 22, 22, 22, 28,
- 22, 22, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 22, 22, 22, 39, 22,
- 1, 1, 2, 3, 49, 49, 48, 5,
- 48, 6, 1, 48, 48, 48, 48, 1,
- 48, 8, 48, 48, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 48, 1,
- 21, 48, 1, 1, 61, 61, 61, 61,
- 61, 61, 61, 61, 1, 61, 61, 61,
- 61, 1, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 1, 61, 62, 61, 0
-};
-
-static const char _myanmar_syllable_machine_trans_targs[] = {
- 0, 1, 26, 37, 0, 27, 33, 51,
- 39, 54, 40, 46, 47, 48, 29, 42,
- 43, 44, 32, 50, 55, 45, 0, 2,
- 13, 0, 3, 9, 14, 15, 21, 22,
- 23, 5, 17, 18, 19, 8, 25, 20,
- 4, 6, 7, 10, 12, 11, 16, 24,
- 0, 0, 28, 30, 31, 34, 36, 35,
- 38, 41, 49, 52, 53, 0, 0
-};
-
-static const char _myanmar_syllable_machine_trans_actions[] = {
- 3, 0, 0, 0, 4, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 6, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 8, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 9, 10
-};
-
-static const char _myanmar_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const char _myanmar_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static const short _myanmar_syllable_machine_eof_trans[] = {
- 0, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 23, 23, 49, 62, 62
-};
-
-static const int myanmar_syllable_machine_start = 0;
-static const int myanmar_syllable_machine_first_final = 0;
-static const int myanmar_syllable_machine_error = -1;
-
-static const int myanmar_syllable_machine_en_main = 0;
-
-
-#line 44 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-
-#line 102 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
- for (unsigned int i = ts; i < te; i++) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-static void
-find_syllables_myanmar (hb_buffer_t *buffer)
-{
- unsigned int p, pe, eof, ts, te, act HB_UNUSED;
- int cs;
- hb_glyph_info_t *info = buffer->info;
-
-#line 382 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- cs = myanmar_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 122 "hb-ot-shape-complex-myanmar-machine.rl"
-
-
- p = 0;
- pe = eof = buffer->len;
-
- unsigned int syllable_serial = 1;
-
-#line 398 "hb-ot-shape-complex-myanmar-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 412 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
- _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
-
- _slen = _myanmar_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
- ( info[p].myanmar_category()) <= _keys[1] ?
- ( info[p].myanmar_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _myanmar_syllable_machine_trans_targs[_trans];
-
- if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
- case 6:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 4:
-#line 95 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 10:
-#line 96 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_punctuation_cluster); }}
- break;
- case 8:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 3:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
- case 5:
-#line 94 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
- break;
- case 7:
-#line 97 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_broken_cluster); }}
- break;
- case 9:
-#line 98 "hb-ot-shape-complex-myanmar-machine.rl"
- {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
- break;
-#line 462 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
-_again:
- switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 471 "hb-ot-shape-complex-myanmar-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 130 "hb-ot-shape-complex-myanmar-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
deleted file mode 100644
index e6ae75e8f2..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright © 2011,2012,2013 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-myanmar.hh"
-#include "hb-ot-shape-complex-myanmar-machine.hh"
-
-
-/*
- * Myanmar shaper.
- */
-
-static const hb_tag_t
-myanmar_basic_features[] =
-{
- /*
- * Basic features.
- * These features are applied in order, one at a time, after reordering,
- * constrained to the syllable.
- */
- HB_TAG('r','p','h','f'),
- HB_TAG('p','r','e','f'),
- HB_TAG('b','l','w','f'),
- HB_TAG('p','s','t','f'),
-};
-static const hb_tag_t
-myanmar_other_features[] =
-{
- /*
- * Other features.
- * These features are applied all at once, after clearing syllables.
- */
- HB_TAG('p','r','e','s'),
- HB_TAG('a','b','v','s'),
- HB_TAG('b','l','w','s'),
- HB_TAG('p','s','t','s'),
-};
-
-static void
-setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-reorder_myanmar (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-collect_features_myanmar (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* Do this before any lookups have been applied. */
- map->add_gsub_pause (setup_syllables_myanmar);
-
- map->enable_feature (HB_TAG('l','o','c','l'));
- /* The Indic specs do not require ccmp, but we apply it here since if
- * there is a use of it, it's typically at the beginning. */
- map->enable_feature (HB_TAG('c','c','m','p'));
-
-
- map->add_gsub_pause (reorder_myanmar);
-
- for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
- {
- map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ);
- map->add_gsub_pause (nullptr);
- }
-
- map->add_gsub_pause (_hb_clear_syllables);
-
- for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
- map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
-}
-
-static void
-setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
- HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);
-
- /* We cannot setup masks here. We save information about characters
- * and setup masks later on in a pause-callback. */
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- set_myanmar_properties (info[i]);
-}
-
-static void
-setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- find_syllables_myanmar (buffer);
- foreach_syllable (buffer, start, end)
- buffer->unsafe_to_break (start, end);
-}
-
-static int
-compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
-{
- int a = pa->myanmar_position();
- int b = pb->myanmar_position();
-
- return a < b ? -1 : a == b ? 0 : +1;
-}
-
-
-/* Rules from:
- * https://docs.microsoft.com/en-us/typography/script-development/myanmar */
-
-static void
-initial_reordering_consonant_syllable (hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- hb_glyph_info_t *info = buffer->info;
-
- unsigned int base = end;
- bool has_reph = false;
-
- {
- unsigned int limit = start;
- if (start + 3 <= end &&
- info[start ].myanmar_category() == OT_Ra &&
- info[start+1].myanmar_category() == OT_As &&
- info[start+2].myanmar_category() == OT_H)
- {
- limit += 3;
- base = start;
- has_reph = true;
- }
-
- {
- if (!has_reph)
- base = limit;
-
- for (unsigned int i = limit; i < end; i++)
- if (is_consonant (info[i]))
- {
- base = i;
- break;
- }
- }
- }
-
- /* Reorder! */
- {
- unsigned int i = start;
- for (; i < start + (has_reph ? 3 : 0); i++)
- info[i].myanmar_position() = POS_AFTER_MAIN;
- for (; i < base; i++)
- info[i].myanmar_position() = POS_PRE_C;
- if (i < end)
- {
- info[i].myanmar_position() = POS_BASE_C;
- i++;
- }
- myanmar_position_t pos = POS_AFTER_MAIN;
- /* The following loop may be ugly, but it implements all of
- * Myanmar reordering! */
- for (; i < end; i++)
- {
- if (info[i].myanmar_category() == OT_MR) /* Pre-base reordering */
- {
- info[i].myanmar_position() = POS_PRE_C;
- continue;
- }
- if (info[i].myanmar_position() < POS_BASE_C) /* Left matra */
- {
- continue;
- }
- if (info[i].myanmar_category() == OT_VS)
- {
- info[i].myanmar_position() = info[i - 1].myanmar_position();
- continue;
- }
-
- if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == OT_VBlw)
- {
- pos = POS_BELOW_C;
- info[i].myanmar_position() = pos;
- continue;
- }
-
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_A)
- {
- info[i].myanmar_position() = POS_BEFORE_SUB;
- continue;
- }
- if (pos == POS_BELOW_C && info[i].myanmar_category() == OT_VBlw)
- {
- info[i].myanmar_position() = pos;
- continue;
- }
- if (pos == POS_BELOW_C && info[i].myanmar_category() != OT_A)
- {
- pos = POS_AFTER_SUB;
- info[i].myanmar_position() = pos;
- continue;
- }
- info[i].myanmar_position() = pos;
- }
- }
-
- /* Sit tight, rock 'n roll! */
- buffer->sort (start, end, compare_myanmar_order);
-}
-
-static void
-reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_face_t *face HB_UNUSED,
- hb_buffer_t *buffer,
- unsigned int start, unsigned int end)
-{
- myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
- switch (syllable_type) {
-
- case myanmar_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
- case myanmar_consonant_syllable:
- initial_reordering_consonant_syllable (buffer, start, end);
- break;
-
- case myanmar_punctuation_cluster:
- case myanmar_non_myanmar_cluster:
- break;
- }
-}
-
-static void
-reorder_myanmar (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (buffer->message (font, "start reordering myanmar"))
- {
- hb_syllabic_insert_dotted_circles (font, buffer,
- myanmar_broken_cluster,
- OT_GB);
-
- foreach_syllable (buffer, start, end)
- reorder_syllable_myanmar (plan, font->face, buffer, start, end);
- (void) buffer->message (font, "end reordering myanmar");
- }
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
- HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar =
-{
- collect_features_myanmar,
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- nullptr, /* decompose */
- nullptr, /* compose */
- setup_masks_myanmar,
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
- false, /* fallback_position */
-};
-
-
-/* Ugly Zawgyi encoding.
- * Disable all auto processing.
- * https://github.com/harfbuzz/harfbuzz/issues/1162 */
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_myanmar_zawgyi =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- nullptr, /* preprocess_text */
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
- nullptr, /* decompose */
- nullptr, /* compose */
- nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
deleted file mode 100644
index 7fbca3878f..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-myanmar.hh
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-#define HB_OT_SHAPE_COMPLEX_MYANMAR_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-indic.hh"
-
-
-/* buffer var allocations */
-#define myanmar_category() indic_category() /* myanmar_category_t */
-#define myanmar_position() indic_position() /* myanmar_position_t */
-
-
-/* Note: This enum is duplicated in the -machine.rl source file.
- * Not sure how to avoid duplication. */
-enum myanmar_category_t {
- OT_As = 18, /* Asat */
- OT_D0 = 20, /* Digit zero */
- OT_DB = OT_N, /* Dot below */
- OT_GB = OT_PLACEHOLDER,
- OT_MH = 21, /* Various consonant medial types */
- OT_MR = 22, /* Various consonant medial types */
- OT_MW = 23, /* Various consonant medial types */
- OT_MY = 24, /* Various consonant medial types */
- OT_PT = 25, /* Pwo and other tones */
- //OT_VAbv = 26,
- //OT_VBlw = 27,
- //OT_VPre = 28,
- //OT_VPst = 29,
- OT_VS = 30, /* Variation selectors */
- OT_P = 31, /* Punctuation */
- OT_D = 32, /* Digits except zero */
- OT_ML = 33, /* Various consonant medial types */
-};
-
-using myanmar_position_t = indic_position_t;
-
-static inline void
-set_myanmar_properties (hb_glyph_info_t &info)
-{
- hb_codepoint_t u = info.codepoint;
- unsigned int type = hb_indic_get_categories (u);
- unsigned int cat = type & 0xFFu;
- myanmar_position_t pos = (myanmar_position_t) (type >> 8);
-
- /* Myanmar
- * https://docs.microsoft.com/en-us/typography/script-development/myanmar#analyze
- */
- if (unlikely (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)))
- cat = OT_VS;
-
- switch (u)
- {
- case 0x104Eu:
- cat = OT_C; /* The spec says C, IndicSyllableCategory doesn't have. */
- break;
-
- case 0x002Du: case 0x00A0u: case 0x00D7u: case 0x2012u:
- case 0x2013u: case 0x2014u: case 0x2015u: case 0x2022u:
- case 0x25CCu: case 0x25FBu: case 0x25FCu: case 0x25FDu:
- case 0x25FEu:
- cat = OT_GB;
- break;
-
- case 0x1004u: case 0x101Bu: case 0x105Au:
- cat = OT_Ra;
- break;
-
- case 0x1032u: case 0x1036u:
- cat = OT_A;
- break;
-
- case 0x1039u:
- cat = OT_H;
- break;
-
- case 0x103Au:
- cat = OT_As;
- break;
-
- case 0x1041u: case 0x1042u: case 0x1043u: case 0x1044u:
- case 0x1045u: case 0x1046u: case 0x1047u: case 0x1048u:
- case 0x1049u: case 0x1090u: case 0x1091u: case 0x1092u:
- case 0x1093u: case 0x1094u: case 0x1095u: case 0x1096u:
- case 0x1097u: case 0x1098u: case 0x1099u:
- cat = OT_D;
- break;
-
- case 0x1040u:
- cat = OT_D; /* XXX The spec says D0, but Uniscribe doesn't seem to do. */
- break;
-
- case 0x103Eu:
- cat = OT_MH;
- break;
-
- case 0x1060u:
- cat = OT_ML;
- break;
-
- case 0x103Cu:
- cat = OT_MR;
- break;
-
- case 0x103Du: case 0x1082u:
- cat = OT_MW;
- break;
-
- case 0x103Bu: case 0x105Eu: case 0x105Fu:
- cat = OT_MY;
- break;
-
- case 0x1063u: case 0x1064u: case 0x1069u: case 0x106Au:
- case 0x106Bu: case 0x106Cu: case 0x106Du: case 0xAA7Bu:
- cat = OT_PT;
- break;
-
- case 0x1038u: case 0x1087u: case 0x1088u: case 0x1089u:
- case 0x108Au: case 0x108Bu: case 0x108Cu: case 0x108Du:
- case 0x108Fu: case 0x109Au: case 0x109Bu: case 0x109Cu:
- cat = OT_SM;
- break;
-
- case 0x104Au: case 0x104Bu:
- cat = OT_P;
- break;
-
- case 0xAA74u: case 0xAA75u: case 0xAA76u:
- /* https://github.com/harfbuzz/harfbuzz/issues/218 */
- cat = OT_C;
- break;
- }
-
- if (cat == OT_M)
- {
- switch ((int) pos)
- {
- case POS_PRE_C: cat = (myanmar_category_t) OT_VPre;
- pos = POS_PRE_M; break;
- case POS_ABOVE_C: cat = (myanmar_category_t) OT_VAbv; break;
- case POS_BELOW_C: cat = (myanmar_category_t) OT_VBlw; break;
- case POS_POST_C: cat = (myanmar_category_t) OT_VPst; break;
- }
- }
-
- info.myanmar_category() = cat;
- info.myanmar_position() = pos;
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_MYANMAR_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
deleted file mode 100644
index 76092c7f38..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright © 2021 Behdad Esfahbod.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-
-void
-hb_syllabic_insert_dotted_circles (hb_font_t *font,
- hb_buffer_t *buffer,
- unsigned int broken_syllable_type,
- unsigned int dottedcircle_category,
- int repha_category,
- int dottedcircle_position)
-{
- if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
- return;
-
- /* Note: This loop is extra overhead, but should not be measurable.
- * TODO Use a buffer scratch flag to remove the loop. */
- bool has_broken_syllables = false;
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- if ((info[i].syllable() & 0x0F) == broken_syllable_type)
- {
- has_broken_syllables = true;
- break;
- }
- if (likely (!has_broken_syllables))
- return;
-
-
- hb_codepoint_t dottedcircle_glyph;
- if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
- return;
-
- hb_glyph_info_t dottedcircle = {0};
- dottedcircle.codepoint = 0x25CCu;
- dottedcircle.complex_var_u8_category() = dottedcircle_category;
- if (dottedcircle_position != -1)
- dottedcircle.complex_var_u8_auxiliary() = dottedcircle_position;
- dottedcircle.codepoint = dottedcircle_glyph;
-
- buffer->clear_output ();
-
- buffer->idx = 0;
- unsigned int last_syllable = 0;
- while (buffer->idx < buffer->len && buffer->successful)
- {
- unsigned int syllable = buffer->cur().syllable();
- if (unlikely (last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type))
- {
- last_syllable = syllable;
-
- hb_glyph_info_t ginfo = dottedcircle;
- ginfo.cluster = buffer->cur().cluster;
- ginfo.mask = buffer->cur().mask;
- ginfo.syllable() = buffer->cur().syllable();
-
- /* Insert dottedcircle after possible Repha. */
- if (repha_category != -1)
- {
- while (buffer->idx < buffer->len && buffer->successful &&
- last_syllable == buffer->cur().syllable() &&
- buffer->cur().complex_var_u8_category() == (unsigned) repha_category)
- (void) buffer->next_glyph ();
- }
-
- (void) buffer->output_info (ginfo);
- }
- else
- (void) buffer->next_glyph ();
- }
- buffer->sync ();
-}
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh
deleted file mode 100644
index b901a660d3..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-syllabic.hh
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright © 2021 Behdad Esfahbod.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
-#define HB_OT_SHAPE_COMPLEX_SYLLABIC_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex.hh"
-
-
-HB_INTERNAL void
-hb_syllabic_insert_dotted_circles (hb_font_t *font,
- hb_buffer_t *buffer,
- unsigned int broken_syllable_type,
- unsigned int dottedcircle_category,
- int repha_category = -1,
- int dottedcircle_position = -1);
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_SYLLABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
deleted file mode 100644
index a1e27a83be..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-thai.cc
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright © 2010,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex.hh"
-
-
-/* Thai / Lao shaper */
-
-
-/* PUA shaping */
-
-
-enum thai_consonant_type_t
-{
- NC,
- AC,
- RC,
- DC,
- NOT_CONSONANT,
- NUM_CONSONANT_TYPES = NOT_CONSONANT
-};
-
-static thai_consonant_type_t
-get_consonant_type (hb_codepoint_t u)
-{
- if (u == 0x0E1Bu || u == 0x0E1Du || u == 0x0E1Fu/* || u == 0x0E2Cu*/)
- return AC;
- if (u == 0x0E0Du || u == 0x0E10u)
- return RC;
- if (u == 0x0E0Eu || u == 0x0E0Fu)
- return DC;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E01u, 0x0E2Eu))
- return NC;
- return NOT_CONSONANT;
-}
-
-
-enum thai_mark_type_t
-{
- AV,
- BV,
- T,
- NOT_MARK,
- NUM_MARK_TYPES = NOT_MARK
-};
-
-static thai_mark_type_t
-get_mark_type (hb_codepoint_t u)
-{
- if (u == 0x0E31u || hb_in_range<hb_codepoint_t> (u, 0x0E34u, 0x0E37u) ||
- u == 0x0E47u || hb_in_range<hb_codepoint_t> (u, 0x0E4Du, 0x0E4Eu))
- return AV;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E38u, 0x0E3Au))
- return BV;
- if (hb_in_range<hb_codepoint_t> (u, 0x0E48u, 0x0E4Cu))
- return T;
- return NOT_MARK;
-}
-
-
-enum thai_action_t
-{
- NOP,
- SD, /* Shift combining-mark down */
- SL, /* Shift combining-mark left */
- SDL, /* Shift combining-mark down-left */
- RD /* Remove descender from base */
-};
-
-static hb_codepoint_t
-thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
-{
- struct thai_pua_mapping_t {
- hb_codepoint_t u;
- hb_codepoint_t win_pua;
- hb_codepoint_t mac_pua;
- } const *pua_mappings = nullptr;
- static const thai_pua_mapping_t SD_mappings[] = {
- {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
- {0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */
- {0x0E4Au, 0xF70Cu, 0xF891u}, /* MAI TRI */
- {0x0E4Bu, 0xF70Du, 0xF894u}, /* MAI CHATTAWA */
- {0x0E4Cu, 0xF70Eu, 0xF897u}, /* THANTHAKHAT */
- {0x0E38u, 0xF718u, 0xF89Bu}, /* SARA U */
- {0x0E39u, 0xF719u, 0xF89Cu}, /* SARA UU */
- {0x0E3Au, 0xF71Au, 0xF89Du}, /* PHINTHU */
- {0x0000u, 0x0000u, 0x0000u}
- };
- static const thai_pua_mapping_t SDL_mappings[] = {
- {0x0E48u, 0xF705u, 0xF88Cu}, /* MAI EK */
- {0x0E49u, 0xF706u, 0xF88Fu}, /* MAI THO */
- {0x0E4Au, 0xF707u, 0xF892u}, /* MAI TRI */
- {0x0E4Bu, 0xF708u, 0xF895u}, /* MAI CHATTAWA */
- {0x0E4Cu, 0xF709u, 0xF898u}, /* THANTHAKHAT */
- {0x0000u, 0x0000u, 0x0000u}
- };
- static const thai_pua_mapping_t SL_mappings[] = {
- {0x0E48u, 0xF713u, 0xF88Au}, /* MAI EK */
- {0x0E49u, 0xF714u, 0xF88Du}, /* MAI THO */
- {0x0E4Au, 0xF715u, 0xF890u}, /* MAI TRI */
- {0x0E4Bu, 0xF716u, 0xF893u}, /* MAI CHATTAWA */
- {0x0E4Cu, 0xF717u, 0xF896u}, /* THANTHAKHAT */
- {0x0E31u, 0xF710u, 0xF884u}, /* MAI HAN-AKAT */
- {0x0E34u, 0xF701u, 0xF885u}, /* SARA I */
- {0x0E35u, 0xF702u, 0xF886u}, /* SARA II */
- {0x0E36u, 0xF703u, 0xF887u}, /* SARA UE */
- {0x0E37u, 0xF704u, 0xF888u}, /* SARA UEE */
- {0x0E47u, 0xF712u, 0xF889u}, /* MAITAIKHU */
- {0x0E4Du, 0xF711u, 0xF899u}, /* NIKHAHIT */
- {0x0000u, 0x0000u, 0x0000u}
- };
- static const thai_pua_mapping_t RD_mappings[] = {
- {0x0E0Du, 0xF70Fu, 0xF89Au}, /* YO YING */
- {0x0E10u, 0xF700u, 0xF89Eu}, /* THO THAN */
- {0x0000u, 0x0000u, 0x0000u}
- };
-
- switch (action) {
- case NOP: return u;
- case SD: pua_mappings = SD_mappings; break;
- case SDL: pua_mappings = SDL_mappings; break;
- case SL: pua_mappings = SL_mappings; break;
- case RD: pua_mappings = RD_mappings; break;
- }
- for (; pua_mappings->u; pua_mappings++)
- if (pua_mappings->u == u)
- {
- hb_codepoint_t glyph;
- if (hb_font_get_glyph (font, pua_mappings->win_pua, 0, &glyph))
- return pua_mappings->win_pua;
- if (hb_font_get_glyph (font, pua_mappings->mac_pua, 0, &glyph))
- return pua_mappings->mac_pua;
- break;
- }
- return u;
-}
-
-
-static enum thai_above_state_t
-{ /* Cluster above looks like: */
- T0, /* ⣤ */
- T1, /* ⣼ */
- T2, /* ⣾ */
- T3, /* ⣿ */
- NUM_ABOVE_STATES
-} thai_above_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
-{
- T0, /* NC */
- T1, /* AC */
- T0, /* RC */
- T0, /* DC */
- T3, /* NOT_CONSONANT */
-};
-
-static const struct thai_above_state_machine_edge_t {
- thai_action_t action;
- thai_above_state_t next_state;
-} thai_above_state_machine[NUM_ABOVE_STATES][NUM_MARK_TYPES] =
-{ /*AV*/ /*BV*/ /*T*/
-/*T0*/ {{NOP,T3}, {NOP,T0}, {SD, T3}},
-/*T1*/ {{SL, T2}, {NOP,T1}, {SDL,T2}},
-/*T2*/ {{NOP,T3}, {NOP,T2}, {SL, T3}},
-/*T3*/ {{NOP,T3}, {NOP,T3}, {NOP,T3}},
-};
-
-
-static enum thai_below_state_t
-{
- B0, /* No descender */
- B1, /* Removable descender */
- B2, /* Strict descender */
- NUM_BELOW_STATES
-} thai_below_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
-{
- B0, /* NC */
- B0, /* AC */
- B1, /* RC */
- B2, /* DC */
- B2, /* NOT_CONSONANT */
-};
-
-static const struct thai_below_state_machine_edge_t {
- thai_action_t action;
- thai_below_state_t next_state;
-} thai_below_state_machine[NUM_BELOW_STATES][NUM_MARK_TYPES] =
-{ /*AV*/ /*BV*/ /*T*/
-/*B0*/ {{NOP,B0}, {NOP,B2}, {NOP, B0}},
-/*B1*/ {{NOP,B1}, {RD, B2}, {NOP, B1}},
-/*B2*/ {{NOP,B2}, {SD, B2}, {NOP, B2}},
-};
-
-
-static void
-do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_THAI_FALLBACK
- return;
-#endif
-
- thai_above_state_t above_state = thai_above_start_state[NOT_CONSONANT];
- thai_below_state_t below_state = thai_below_start_state[NOT_CONSONANT];
- unsigned int base = 0;
-
- hb_glyph_info_t *info = buffer->info;
- unsigned int count = buffer->len;
- for (unsigned int i = 0; i < count; i++)
- {
- thai_mark_type_t mt = get_mark_type (info[i].codepoint);
-
- if (mt == NOT_MARK) {
- thai_consonant_type_t ct = get_consonant_type (info[i].codepoint);
- above_state = thai_above_start_state[ct];
- below_state = thai_below_start_state[ct];
- base = i;
- continue;
- }
-
- const thai_above_state_machine_edge_t &above_edge = thai_above_state_machine[above_state][mt];
- const thai_below_state_machine_edge_t &below_edge = thai_below_state_machine[below_state][mt];
- above_state = above_edge.next_state;
- below_state = below_edge.next_state;
-
- /* At least one of the above/below actions is NOP. */
- thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action;
-
- buffer->unsafe_to_break (base, i);
- if (action == RD)
- info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font);
- else
- info[i].codepoint = thai_pua_shape (info[i].codepoint, action, font);
- }
-}
-
-
-static void
-preprocess_text_thai (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- /* This function implements the shaping logic documented here:
- *
- * https://linux.thai.net/~thep/th-otf/shaping.html
- *
- * The first shaping rule listed there is needed even if the font has Thai
- * OpenType tables. The rest do fallback positioning based on PUA codepoints.
- * We implement that only if there exist no Thai GSUB in the font.
- */
-
- /* The following is NOT specified in the MS OT Thai spec, however, it seems
- * to be what Uniscribe and other engines implement. According to Eric Muller:
- *
- * When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the
- * NIKHAHIT backwards over any tone mark (0E48-0E4B).
- *
- * <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
- *
- * This reordering is legit only when the NIKHAHIT comes from a SARA AM, not
- * when it's there to start with. The string <0E14, 0E4B, 0E4D> is probably
- * not what a user wanted, but the rendering is nevertheless nikhahit above
- * chattawa.
- *
- * Same for Lao.
- *
- * Note:
- *
- * Uniscribe also does some below-marks reordering. Namely, it positions U+0E3A
- * after U+0E38 and U+0E39. We do that by modifying the ccc for U+0E3A.
- * See unicode->modified_combining_class (). Lao does NOT have a U+0E3A
- * equivalent.
- */
-
-
- /*
- * Here are the characters of significance:
- *
- * Thai Lao
- * SARA AM: U+0E33 U+0EB3
- * SARA AA: U+0E32 U+0EB2
- * Nikhahit: U+0E4D U+0ECD
- *
- * Testing shows that Uniscribe reorder the following marks:
- * Thai: <0E31,0E34..0E37,0E47..0E4E>
- * Lao: <0EB1,0EB4..0EB7,0EC7..0ECE>
- *
- * Note how the Lao versions are the same as Thai + 0x80.
- */
-
- /* We only get one script at a time, so a script-agnostic implementation
- * is adequate here. */
-#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
-#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
-#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
-#define IS_TONE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u))
-
- buffer->clear_output ();
- unsigned int count = buffer->len;
- for (buffer->idx = 0; buffer->idx < count /* No need for: && buffer->successful */;)
- {
- hb_codepoint_t u = buffer->cur().codepoint;
- if (likely (!IS_SARA_AM (u)))
- {
- if (unlikely (!buffer->next_glyph ())) break;
- continue;
- }
-
- /* Is SARA AM. Decompose and reorder. */
- (void) buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
- _hb_glyph_info_set_continuation (&buffer->prev());
- if (unlikely (!buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)))) break;
-
- /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
- unsigned int end = buffer->out_len;
- _hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
-
- /* Ok, let's see... */
- unsigned int start = end - 2;
- while (start > 0 && IS_TONE_MARK (buffer->out_info[start - 1].codepoint))
- start--;
-
- if (start + 2 < end)
- {
- /* Move Nikhahit (end-2) to the beginning */
- buffer->merge_out_clusters (start, end);
- hb_glyph_info_t t = buffer->out_info[end - 2];
- memmove (buffer->out_info + start + 1,
- buffer->out_info + start,
- sizeof (buffer->out_info[0]) * (end - start - 2));
- buffer->out_info[start] = t;
- }
- else
- {
- /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
- * previous cluster. */
- if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
- buffer->merge_out_clusters (start - 1, end);
- }
- }
- buffer->sync ();
-
- /* If font has Thai GSUB, we are done. */
- if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])
- do_thai_pua_shaping (plan, buffer, font);
-}
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
-{
- nullptr, /* collect_features */
- nullptr, /* override_features */
- nullptr, /* data_create */
- nullptr, /* data_destroy */
- preprocess_text_thai,
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
- nullptr, /* decompose */
- nullptr, /* compose */
- nullptr, /* setup_masks */
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
- false,/* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
deleted file mode 100644
index c3920b2cc6..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-machine.hh
+++ /dev/null
@@ -1,576 +0,0 @@
-
-#line 1 "hb-ot-shape-complex-use-machine.rl"
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-syllabic.hh"
-
-/* buffer var allocations */
-#define use_category() complex_var_u8_category()
-
-#define USE(Cat) use_syllable_machine_ex_##Cat
-
-enum use_syllable_type_t {
- use_virama_terminated_cluster,
- use_sakot_terminated_cluster,
- use_standard_cluster,
- use_number_joiner_terminated_cluster,
- use_numeral_cluster,
- use_symbol_cluster,
- use_hieroglyph_cluster,
- use_broken_cluster,
- use_non_cluster,
-};
-
-
-#line 57 "hb-ot-shape-complex-use-machine.hh"
-#define use_syllable_machine_ex_B 1u
-#define use_syllable_machine_ex_CGJ 6u
-#define use_syllable_machine_ex_CMAbv 31u
-#define use_syllable_machine_ex_CMBlw 32u
-#define use_syllable_machine_ex_CS 43u
-#define use_syllable_machine_ex_FAbv 24u
-#define use_syllable_machine_ex_FBlw 25u
-#define use_syllable_machine_ex_FMAbv 45u
-#define use_syllable_machine_ex_FMBlw 46u
-#define use_syllable_machine_ex_FMPst 47u
-#define use_syllable_machine_ex_FPst 26u
-#define use_syllable_machine_ex_G 49u
-#define use_syllable_machine_ex_GB 5u
-#define use_syllable_machine_ex_H 12u
-#define use_syllable_machine_ex_HN 13u
-#define use_syllable_machine_ex_HVM 44u
-#define use_syllable_machine_ex_J 50u
-#define use_syllable_machine_ex_MAbv 27u
-#define use_syllable_machine_ex_MBlw 28u
-#define use_syllable_machine_ex_MPre 30u
-#define use_syllable_machine_ex_MPst 29u
-#define use_syllable_machine_ex_N 4u
-#define use_syllable_machine_ex_O 0u
-#define use_syllable_machine_ex_R 18u
-#define use_syllable_machine_ex_SB 51u
-#define use_syllable_machine_ex_SE 52u
-#define use_syllable_machine_ex_SMAbv 41u
-#define use_syllable_machine_ex_SMBlw 42u
-#define use_syllable_machine_ex_SUB 11u
-#define use_syllable_machine_ex_Sk 48u
-#define use_syllable_machine_ex_VAbv 33u
-#define use_syllable_machine_ex_VBlw 34u
-#define use_syllable_machine_ex_VMAbv 37u
-#define use_syllable_machine_ex_VMBlw 38u
-#define use_syllable_machine_ex_VMPre 23u
-#define use_syllable_machine_ex_VMPst 39u
-#define use_syllable_machine_ex_VPre 22u
-#define use_syllable_machine_ex_VPst 35u
-#define use_syllable_machine_ex_ZWNJ 14u
-
-
-#line 99 "hb-ot-shape-complex-use-machine.hh"
-static const unsigned char _use_syllable_machine_trans_keys[] = {
- 0u, 51u, 41u, 42u, 42u, 42u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u, 23u, 48u,
- 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
- 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u, 22u, 48u,
- 11u, 48u, 1u, 48u, 13u, 13u, 4u, 4u, 11u, 48u, 11u, 48u, 1u, 1u, 22u, 48u,
- 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u,
- 24u, 48u, 1u, 1u, 24u, 48u, 23u, 48u, 23u, 48u, 23u, 48u, 22u, 48u, 22u, 48u,
- 22u, 48u, 11u, 48u, 1u, 48u, 4u, 4u, 13u, 13u, 1u, 48u, 11u, 48u, 41u, 42u,
- 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u, 0
-};
-
-static const char _use_syllable_machine_key_spans[] = {
- 52, 2, 1, 38, 38, 1, 27, 26,
- 24, 23, 22, 2, 1, 25, 25, 25,
- 1, 25, 26, 26, 26, 27, 27, 27,
- 38, 48, 1, 1, 38, 38, 1, 27,
- 26, 24, 23, 22, 2, 1, 25, 25,
- 25, 1, 25, 26, 26, 26, 27, 27,
- 27, 38, 48, 1, 1, 48, 38, 2,
- 1, 5, 3, 4, 3
-};
-
-static const short _use_syllable_machine_index_offsets[] = {
- 0, 53, 56, 58, 97, 136, 138, 166,
- 193, 218, 242, 265, 268, 270, 296, 322,
- 348, 350, 376, 403, 430, 457, 485, 513,
- 541, 580, 629, 631, 633, 672, 711, 713,
- 741, 768, 793, 817, 840, 843, 845, 871,
- 897, 923, 925, 951, 978, 1005, 1032, 1060,
- 1088, 1116, 1155, 1204, 1206, 1208, 1257, 1296,
- 1299, 1301, 1307, 1311, 1316
-};
-
-static const char _use_syllable_machine_indicies[] = {
- 0, 1, 2, 2, 3, 4, 2, 2,
- 2, 2, 2, 5, 6, 7, 2, 2,
- 2, 2, 8, 2, 2, 2, 9, 10,
- 11, 12, 13, 14, 15, 9, 16, 17,
- 18, 19, 20, 21, 2, 22, 23, 24,
- 2, 25, 26, 27, 28, 29, 30, 31,
- 6, 32, 2, 33, 2, 0, 35, 34,
- 35, 34, 37, 38, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 39, 40, 41,
- 42, 43, 44, 45, 39, 46, 1, 47,
- 48, 49, 50, 36, 51, 52, 53, 36,
- 36, 36, 36, 54, 55, 56, 57, 38,
- 36, 37, 38, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 39, 40, 41, 42,
- 43, 44, 45, 39, 46, 47, 47, 48,
- 49, 50, 36, 51, 52, 53, 36, 36,
- 36, 36, 54, 55, 56, 57, 38, 36,
- 37, 58, 39, 40, 41, 42, 43, 36,
- 36, 36, 36, 36, 36, 48, 49, 50,
- 36, 51, 52, 53, 36, 36, 36, 36,
- 40, 55, 56, 57, 59, 36, 40, 41,
- 42, 43, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 51, 52, 53, 36,
- 36, 36, 36, 36, 55, 56, 57, 59,
- 36, 41, 42, 43, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 55, 56,
- 57, 36, 42, 43, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 55, 56,
- 57, 36, 43, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 55, 56, 57,
- 36, 55, 56, 36, 56, 36, 41, 42,
- 43, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 51, 52, 53, 36, 36,
- 36, 36, 36, 55, 56, 57, 59, 36,
- 41, 42, 43, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 52, 53,
- 36, 36, 36, 36, 36, 55, 56, 57,
- 59, 36, 41, 42, 43, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 53, 36, 36, 36, 36, 36, 55,
- 56, 57, 59, 36, 61, 60, 41, 42,
- 43, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 55, 56, 57, 59, 36,
- 40, 41, 42, 43, 36, 36, 36, 36,
- 36, 36, 48, 49, 50, 36, 51, 52,
- 53, 36, 36, 36, 36, 40, 55, 56,
- 57, 59, 36, 40, 41, 42, 43, 36,
- 36, 36, 36, 36, 36, 36, 49, 50,
- 36, 51, 52, 53, 36, 36, 36, 36,
- 40, 55, 56, 57, 59, 36, 40, 41,
- 42, 43, 36, 36, 36, 36, 36, 36,
- 36, 36, 50, 36, 51, 52, 53, 36,
- 36, 36, 36, 40, 55, 56, 57, 59,
- 36, 39, 40, 41, 42, 43, 36, 45,
- 39, 36, 36, 36, 48, 49, 50, 36,
- 51, 52, 53, 36, 36, 36, 36, 40,
- 55, 56, 57, 59, 36, 39, 40, 41,
- 42, 43, 36, 36, 39, 36, 36, 36,
- 48, 49, 50, 36, 51, 52, 53, 36,
- 36, 36, 36, 40, 55, 56, 57, 59,
- 36, 39, 40, 41, 42, 43, 44, 45,
- 39, 36, 36, 36, 48, 49, 50, 36,
- 51, 52, 53, 36, 36, 36, 36, 40,
- 55, 56, 57, 59, 36, 37, 38, 36,
- 36, 36, 36, 36, 36, 36, 36, 36,
- 39, 40, 41, 42, 43, 44, 45, 39,
- 46, 36, 47, 48, 49, 50, 36, 51,
- 52, 53, 36, 36, 36, 36, 54, 55,
- 56, 57, 38, 36, 37, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 40, 41, 42, 43, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58,
- 51, 52, 53, 58, 58, 58, 58, 58,
- 55, 56, 57, 59, 58, 63, 62, 3,
- 64, 37, 38, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 39, 40, 41, 42,
- 43, 44, 45, 39, 46, 1, 47, 48,
- 49, 50, 36, 51, 52, 53, 36, 0,
- 35, 36, 54, 55, 56, 57, 38, 36,
- 5, 6, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 9, 10, 11, 12, 13,
- 14, 15, 9, 16, 18, 18, 19, 20,
- 21, 65, 22, 23, 24, 65, 65, 65,
- 65, 28, 29, 30, 31, 6, 65, 5,
- 65, 9, 10, 11, 12, 13, 65, 65,
- 65, 65, 65, 65, 19, 20, 21, 65,
- 22, 23, 24, 65, 65, 65, 65, 10,
- 29, 30, 31, 66, 65, 10, 11, 12,
- 13, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 22, 23, 24, 65, 65,
- 65, 65, 65, 29, 30, 31, 66, 65,
- 11, 12, 13, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 29, 30, 31,
- 65, 12, 13, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 29, 30, 31,
- 65, 13, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 29, 30, 31, 65,
- 29, 30, 65, 30, 65, 11, 12, 13,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 22, 23, 24, 65, 65, 65,
- 65, 65, 29, 30, 31, 66, 65, 11,
- 12, 13, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 23, 24, 65,
- 65, 65, 65, 65, 29, 30, 31, 66,
- 65, 11, 12, 13, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 24, 65, 65, 65, 65, 65, 29, 30,
- 31, 66, 65, 67, 65, 11, 12, 13,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 29, 30, 31, 66, 65, 10,
- 11, 12, 13, 65, 65, 65, 65, 65,
- 65, 19, 20, 21, 65, 22, 23, 24,
- 65, 65, 65, 65, 10, 29, 30, 31,
- 66, 65, 10, 11, 12, 13, 65, 65,
- 65, 65, 65, 65, 65, 20, 21, 65,
- 22, 23, 24, 65, 65, 65, 65, 10,
- 29, 30, 31, 66, 65, 10, 11, 12,
- 13, 65, 65, 65, 65, 65, 65, 65,
- 65, 21, 65, 22, 23, 24, 65, 65,
- 65, 65, 10, 29, 30, 31, 66, 65,
- 9, 10, 11, 12, 13, 65, 15, 9,
- 65, 65, 65, 19, 20, 21, 65, 22,
- 23, 24, 65, 65, 65, 65, 10, 29,
- 30, 31, 66, 65, 9, 10, 11, 12,
- 13, 65, 65, 9, 65, 65, 65, 19,
- 20, 21, 65, 22, 23, 24, 65, 65,
- 65, 65, 10, 29, 30, 31, 66, 65,
- 9, 10, 11, 12, 13, 14, 15, 9,
- 65, 65, 65, 19, 20, 21, 65, 22,
- 23, 24, 65, 65, 65, 65, 10, 29,
- 30, 31, 66, 65, 5, 6, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 9,
- 10, 11, 12, 13, 14, 15, 9, 16,
- 65, 18, 19, 20, 21, 65, 22, 23,
- 24, 65, 65, 65, 65, 28, 29, 30,
- 31, 6, 65, 5, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 10, 11, 12, 13, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 22,
- 23, 24, 65, 65, 65, 65, 65, 29,
- 30, 31, 66, 65, 68, 65, 7, 65,
- 1, 65, 65, 65, 1, 65, 65, 65,
- 65, 65, 5, 6, 7, 65, 65, 65,
- 65, 65, 65, 65, 65, 9, 10, 11,
- 12, 13, 14, 15, 9, 16, 17, 18,
- 19, 20, 21, 65, 22, 23, 24, 65,
- 25, 26, 65, 28, 29, 30, 31, 6,
- 65, 5, 6, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 9, 10, 11, 12,
- 13, 14, 15, 9, 16, 17, 18, 19,
- 20, 21, 65, 22, 23, 24, 65, 65,
- 65, 65, 28, 29, 30, 31, 6, 65,
- 25, 26, 65, 26, 65, 1, 69, 69,
- 69, 1, 69, 71, 70, 32, 70, 32,
- 71, 70, 71, 70, 32, 70, 33, 70,
- 0
-};
-
-static const char _use_syllable_machine_trans_targs[] = {
- 1, 3, 0, 26, 28, 29, 30, 51,
- 53, 31, 32, 33, 34, 35, 46, 47,
- 48, 54, 49, 43, 44, 45, 38, 39,
- 40, 55, 56, 57, 50, 36, 37, 0,
- 58, 60, 0, 2, 0, 4, 5, 6,
- 7, 8, 9, 10, 21, 22, 23, 24,
- 18, 19, 20, 13, 14, 15, 25, 11,
- 12, 0, 0, 16, 0, 17, 0, 27,
- 0, 0, 41, 42, 52, 0, 0, 59
-};
-
-static const char _use_syllable_machine_trans_actions[] = {
- 0, 0, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 4,
- 0, 0, 5, 0, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 7, 8, 0, 9, 0, 10, 0,
- 11, 12, 0, 0, 0, 13, 14, 0
-};
-
-static const char _use_syllable_machine_to_state_actions[] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const char _use_syllable_machine_from_state_actions[] = {
- 2, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0
-};
-
-static const short _use_syllable_machine_eof_trans[] = {
- 0, 35, 35, 37, 37, 59, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37,
- 61, 37, 37, 37, 37, 37, 37, 37,
- 37, 59, 63, 65, 37, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 70, 71, 71, 71
-};
-
-static const int use_syllable_machine_start = 0;
-static const int use_syllable_machine_first_final = 0;
-static const int use_syllable_machine_error = -1;
-
-static const int use_syllable_machine_en_main = 0;
-
-
-#line 58 "hb-ot-shape-complex-use-machine.rl"
-
-
-
-#line 179 "hb-ot-shape-complex-use-machine.rl"
-
-
-#define found_syllable(syllable_type) \
- HB_STMT_START { \
- if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
- for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
- info[i].syllable() = (syllable_serial << 4) | syllable_type; \
- syllable_serial++; \
- if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
- } HB_STMT_END
-
-
-template <typename Iter>
-struct machine_index_t :
- hb_iter_with_fallback_t<machine_index_t<Iter>,
- typename Iter::item_t>
-{
- machine_index_t (const Iter& it) : it (it) {}
- machine_index_t (const machine_index_t& o) : it (o.it) {}
-
- static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
- static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
-
- typename Iter::item_t __item__ () const { return *it; }
- typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
- unsigned __len__ () const { return it.len (); }
- void __next__ () { ++it; }
- void __forward__ (unsigned n) { it += n; }
- void __prev__ () { --it; }
- void __rewind__ (unsigned n) { it -= n; }
- void operator = (unsigned n)
- { unsigned index = (*it).first; if (index < n) it += n - index; else if (index > n) it -= index - n; }
- void operator = (const machine_index_t& o) { *this = (*o.it).first; }
- bool operator == (const machine_index_t& o) const { return (*it).first == (*o.it).first; }
- bool operator != (const machine_index_t& o) const { return !(*this == o); }
-
- private:
- Iter it;
-};
-struct
-{
- template <typename Iter,
- hb_requires (hb_is_iterable (Iter))>
- machine_index_t<hb_iter_type<Iter>>
- operator () (Iter&& it) const
- { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
-}
-HB_FUNCOBJ (machine_index);
-
-
-
-static bool
-not_ccs_default_ignorable (const hb_glyph_info_t &i)
-{ return !(i.use_category() == USE(CGJ) && _hb_glyph_info_is_default_ignorable (&i)); }
-
-static inline void
-find_syllables_use (hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
- auto p =
- + hb_iter (info, buffer->len)
- | hb_enumerate
- | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
- hb_second)
- | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
- {
- if (p.second.use_category() == USE(ZWNJ))
- for (unsigned i = p.first + 1; i < buffer->len; ++i)
- if (not_ccs_default_ignorable (info[i]))
- return !_hb_glyph_info_is_unicode_mark (&info[i]);
- return true;
- })
- | hb_enumerate
- | machine_index
- ;
- auto pe = p + p.len ();
- auto eof = +pe;
- auto ts = +p;
- auto te = +p;
- unsigned int act HB_UNUSED;
- int cs;
-
-#line 453 "hb-ot-shape-complex-use-machine.hh"
- {
- cs = use_syllable_machine_start;
- ts = 0;
- te = 0;
- act = 0;
- }
-
-#line 263 "hb-ot-shape-complex-use-machine.rl"
-
-
- unsigned int syllable_serial = 1;
-
-#line 466 "hb-ot-shape-complex-use-machine.hh"
- {
- int _slen;
- int _trans;
- const unsigned char *_keys;
- const char *_inds;
- if ( p == pe )
- goto _test_eof;
-_resume:
- switch ( _use_syllable_machine_from_state_actions[cs] ) {
- case 2:
-#line 1 "NONE"
- {ts = p;}
- break;
-#line 480 "hb-ot-shape-complex-use-machine.hh"
- }
-
- _keys = _use_syllable_machine_trans_keys + (cs<<1);
- _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
-
- _slen = _use_syllable_machine_key_spans[cs];
- _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
- ( (*p).second.second.use_category()) <= _keys[1] ?
- ( (*p).second.second.use_category()) - _keys[0] : _slen ];
-
-_eof_trans:
- cs = _use_syllable_machine_trans_targs[_trans];
-
- if ( _use_syllable_machine_trans_actions[_trans] == 0 )
- goto _again;
-
- switch ( _use_syllable_machine_trans_actions[_trans] ) {
- case 7:
-#line 169 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_standard_cluster); }}
- break;
- case 4:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_broken_cluster); }}
- break;
- case 3:
-#line 175 "hb-ot-shape-complex-use-machine.rl"
- {te = p+1;{ found_syllable (use_non_cluster); }}
- break;
- case 8:
-#line 167 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_virama_terminated_cluster); }}
- break;
- case 9:
-#line 168 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
- break;
- case 6:
-#line 169 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_standard_cluster); }}
- break;
- case 11:
-#line 170 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
- break;
- case 10:
-#line 171 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_numeral_cluster); }}
- break;
- case 5:
-#line 172 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_symbol_cluster); }}
- break;
- case 14:
-#line 173 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
- break;
- case 12:
-#line 174 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_broken_cluster); }}
- break;
- case 13:
-#line 175 "hb-ot-shape-complex-use-machine.rl"
- {te = p;p--;{ found_syllable (use_non_cluster); }}
- break;
-#line 546 "hb-ot-shape-complex-use-machine.hh"
- }
-
-_again:
- switch ( _use_syllable_machine_to_state_actions[cs] ) {
- case 1:
-#line 1 "NONE"
- {ts = 0;}
- break;
-#line 555 "hb-ot-shape-complex-use-machine.hh"
- }
-
- if ( ++p != pe )
- goto _resume;
- _test_eof: {}
- if ( p == eof )
- {
- if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
- _trans = _use_syllable_machine_eof_trans[cs] - 1;
- goto _eof_trans;
- }
- }
-
- }
-
-#line 268 "hb-ot-shape-complex-use-machine.rl"
-
-}
-
-#undef found_syllable
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
deleted file mode 100644
index 7a3a995c8c..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use-table.hh
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* == Start of generated table == */
-/*
- * The following table is generated by running:
- *
- * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
- *
- * on files with these headers:
- *
- * # IndicSyllabicCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # IndicPositionalCategory-14.0.0.txt
- * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
- * # ArabicShaping-14.0.0.txt
- * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
- * # DerivedCoreProperties-14.0.0.txt
- * # Date: 2021-08-12, 23:12:53 GMT
- * # Blocks-14.0.0.txt
- * # Date: 2021-01-22, 23:29:00 GMT [KW]
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
- * # Override values For Indic_Syllabic_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
- * # Override values For Indic_Positional_Category
- * # Not derivable
- * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
- * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
- * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
- * # Updated for L2/19-083 by Andrew Glass 2019-05-06
- * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
- * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
- * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
- * UnicodeData.txt does not have a header.
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-#define HB_OT_SHAPE_COMPLEX_USE_TABLE_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex-use-machine.hh"
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-macros"
-#define B USE(B) /* BASE */
-#define CGJ USE(CGJ) /* CGJ */
-#define CS USE(CS) /* CONS_WITH_STACKER */
-#define G USE(G) /* HIEROGLYPH */
-#define GB USE(GB) /* BASE_OTHER */
-#define H USE(H) /* HALANT */
-#define HN USE(HN) /* HALANT_NUM */
-#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
-#define J USE(J) /* HIEROGLYPH_JOINER */
-#define N USE(N) /* BASE_NUM */
-#define O USE(O) /* OTHER */
-#define R USE(R) /* REPHA */
-#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
-#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
-#define SUB USE(SUB) /* CONS_SUB */
-#define Sk USE(Sk) /* SAKOT */
-#define ZWNJ USE(ZWNJ) /* ZWNJ */
-#define CMAbv USE(CMAbv)
-#define CMBlw USE(CMBlw)
-#define FAbv USE(FAbv)
-#define FBlw USE(FBlw)
-#define FPst USE(FPst)
-#define FMAbv USE(FMAbv)
-#define FMBlw USE(FMBlw)
-#define FMPst USE(FMPst)
-#define MAbv USE(MAbv)
-#define MBlw USE(MBlw)
-#define MPst USE(MPst)
-#define MPre USE(MPre)
-#define SMAbv USE(SMAbv)
-#define SMBlw USE(SMBlw)
-#define VAbv USE(VAbv)
-#define VBlw USE(VBlw)
-#define VPst USE(VPst)
-#define VPre USE(VPre)
-#define VMAbv USE(VMAbv)
-#define VMBlw USE(VMBlw)
-#define VMPst USE(VMPst)
-#define VMPre USE(VMPre)
-#pragma GCC diagnostic pop
-
-static const uint8_t use_table[] = {
-
-
-#define use_offset_0x0028u 0
-
-
- /* Basic Latin */
- O, O, O, O, O, GB, O, O,
- /* 0030 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x00a0u 24
-
-
- /* Latin-1 Supplement */
-
- /* 00A0 */ GB, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00B0 */ O, O, FMPst, FMPst, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00C0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 00D0 */ O, O, O, O, O, O, O, GB,
-
-#define use_offset_0x0348u 80
-
-
- /* Combining Diacritical Marks */
- O, O, O, O, O, O, O, CGJ,
-
-#define use_offset_0x0640u 88
-
-
- /* Arabic */
-
- /* 0640 */ B, O, O, O, O, O, O, O,
-
-#define use_offset_0x07c8u 96
-
-
- /* NKo */
- O, O, B, B, B, B, B, B,
- /* 07D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 07E0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 07F0 */ VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, O, O, O, B, O, O, VMAbv, O, O,
-
-#define use_offset_0x0840u 152
-
-
- /* Mandaic */
-
- /* 0840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0850 */ B, B, B, B, B, B, B, B, B, CMBlw, CMBlw, CMBlw, O, O, O, O,
-
-#define use_offset_0x0900u 184
-
-
- /* Devanagari */
-
- /* 0900 */ VMAbv, VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0930 */ B, B, B, B, B, B, B, B, B, B, VAbv, VPst, CMBlw, B, VPst, VPre,
- /* 0940 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VPst, VPst, VPst, VPst, H, VPre, VPst,
- /* 0950 */ O, VMAbv, VMBlw, O, O, VAbv, VBlw, VBlw, B, B, B, B, B, B, B, B,
- /* 0960 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0970 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Bengali */
-
- /* 0980 */ GB, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 0990 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 09A0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 09B0 */ B, O, B, O, O, O, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
- /* 09C0 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
- /* 09D0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, B, B, O, B,
- /* 09E0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 09F0 */ B, B, O, O, O, O, O, O, O, O, O, O, B, O, FMAbv, O,
-
- /* Gurmukhi */
-
- /* 0A00 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, O, O, O, O, B,
- /* 0A10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0A20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0A30 */ B, O, B, B, O, B, B, O, B, B, O, O, CMBlw, O, VPst, VPre,
- /* 0A40 */ VPst, VBlw, VBlw, O, O, O, O, VAbv, VAbv, O, O, VAbv, VAbv, H, O, O,
- /* 0A50 */ O, VMBlw, O, O, O, O, O, O, O, B, B, B, B, O, B, O,
- /* 0A60 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0A70 */ VMAbv, CMAbv, GB, GB, O, MBlw, O, O, O, O, O, O, O, O, O, O,
-
- /* Gujarati */
-
- /* 0A80 */ O, VMAbv, VMAbv, VMPst, O, B, B, B, B, B, B, B, B, B, O, B,
- /* 0A90 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0AA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0AB0 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VPre,
- /* 0AC0 */ VPst, VBlw, VBlw, VBlw, VBlw, VAbv, O, VAbv, VAbv, VAbv, O, VPst, VPst, H, O, O,
- /* 0AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 0AE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0AF0 */ O, O, O, O, O, O, O, O, O, B, VMAbv, VMAbv, VMAbv, CMAbv, CMAbv, CMAbv,
-
- /* Oriya */
-
- /* 0B00 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 0B10 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0B20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0B30 */ B, O, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
- /* 0B40 */ VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, O, O, VPre, VPre, H, O, O,
- /* 0B50 */ O, O, O, O, O, VAbv, VAbv, VAbv, O, O, O, O, B, B, O, B,
- /* 0B60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0B70 */ O, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Tamil */
-
- /* 0B80 */ O, O, VMAbv, O, O, B, B, B, B, B, B, O, O, O, B, B,
- /* 0B90 */ B, O, B, B, B, B, O, O, O, B, B, O, B, O, B, B,
- /* 0BA0 */ O, O, O, B, B, O, O, O, B, B, B, O, O, O, B, B,
- /* 0BB0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, VPst, VPst,
- /* 0BC0 */ VAbv, VPst, VPst, O, O, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, O, O,
- /* 0BD0 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, O,
- /* 0BE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0BF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Telugu */
-
- /* 0C00 */ VMAbv, VMPst, VMPst, VMPst, VMAbv, B, B, B, B, B, B, B, B, O, B, B,
- /* 0C10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0C20 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0C30 */ B, B, B, B, B, B, B, B, B, B, O, O, CMBlw, B, VAbv, VAbv,
- /* 0C40 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
- /* 0C50 */ O, O, O, O, O, VAbv, VBlw, O, B, B, B, O, O, O, O, O,
- /* 0C60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0C70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Kannada */
-
- /* 0C80 */ B, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, O, B, B,
- /* 0C90 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0CA0 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 0CB0 */ B, B, B, B, O, B, B, B, B, B, O, O, CMBlw, B, VPst, VAbv,
- /* 0CC0 */ VAbv, VPst, VPst, VPst, VPst, O, VAbv, VAbv, VAbv, O, VAbv, VAbv, VAbv, H, O, O,
- /* 0CD0 */ O, O, O, O, O, VPst, VPst, O, O, O, O, O, O, O, B, O,
- /* 0CE0 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0CF0 */ O, CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Malayalam */
-
- /* 0D00 */ VMAbv, VMAbv, VMPst, VMPst, B, B, B, B, B, B, B, B, B, O, B, B,
- /* 0D10 */ B, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D30 */ B, B, B, B, B, B, B, B, B, B, B, VAbv, VAbv, B, VPst, VPst,
- /* 0D40 */ VPst, VPst, VPst, VBlw, VBlw, O, VPre, VPre, VPre, O, VPre, VPre, VPre, H, R, O,
- /* 0D50 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, O, B,
- /* 0D60 */ B, B, VBlw, VBlw, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Sinhala */
-
- /* 0D80 */ O, VMAbv, VMPst, VMPst, O, B, B, B, B, B, B, B, B, B, B, B,
- /* 0D90 */ B, B, B, B, B, B, B, O, O, O, B, B, B, B, B, B,
- /* 0DA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0DB0 */ B, B, O, B, B, B, B, B, B, B, B, B, O, B, O, O,
- /* 0DC0 */ B, B, B, B, B, B, B, O, O, O, H, O, O, O, O, VPst,
- /* 0DD0 */ VPst, VPst, VAbv, VAbv, VBlw, O, VBlw, O, VPst, VPre, VPre, VPre, VPre, VPre, VPre, VPst,
- /* 0DE0 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
- /* 0DF0 */ O, O, VPst, VPst, O, O, O, O,
-
-#define use_offset_0x0f00u 1456
-
-
- /* Tibetan */
-
- /* 0F00 */ B, B, O, O, B, B, B, O, O, O, O, O, O, O, O, O,
- /* 0F10 */ O, O, O, O, O, O, O, O, VBlw, VBlw, O, O, O, O, O, O,
- /* 0F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F30 */ B, B, B, B, O, FBlw, O, FBlw, O, CMAbv, O, O, O, O, VPst, VPre,
- /* 0F40 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
- /* 0F50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 0F60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 0F70 */ O, CMBlw, VBlw, VAbv, VAbv, VBlw, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VMAbv, O,
- /* 0F80 */ VBlw, VAbv, VMAbv, VMAbv, VBlw, O, VMAbv, VMAbv, B, B, B, B, B, SUB, SUB, SUB,
- /* 0F90 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 0FB0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, O, O,
- /* 0FC0 */ O, O, O, O, O, O, FBlw, O,
-
-#define use_offset_0x1000u 1656
-
-
- /* Myanmar */
-
- /* 1000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1020 */ B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VAbv, VAbv, VBlw,
- /* 1030 */ VBlw, VPre, VAbv, VAbv, VAbv, VAbv, VMAbv, VMBlw, VMPst, H, VAbv, MPst, MPre, MBlw, MBlw, B,
- /* 1040 */ B, B, B, B, B, B, B, B, B, B, O, GB, O, O, GB, O,
- /* 1050 */ B, B, B, B, B, B, VPst, VPst, VBlw, VBlw, B, B, B, B, MBlw, MBlw,
- /* 1060 */ MBlw, B, VPst, VMPst, VMPst, B, B, VPst, VPst, VMPst, VMPst, VMPst, VMPst, VMPst, B, B,
- /* 1070 */ B, VAbv, VAbv, VAbv, VAbv, B, B, B, B, B, B, B, B, B, B, B,
- /* 1080 */ B, B, MBlw, VPst, VPre, VAbv, VAbv, VMPst, VMPst, VMPst, VMPst, VMPst, VMPst, VMBlw, B, VMPst,
- /* 1090 */ B, B, B, B, B, B, B, B, B, B, VMPst, VMPst, VPst, VAbv, O, O,
-
-#define use_offset_0x1700u 1816
-
-
- /* Tagalog */
-
- /* 1700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1710 */ B, B, VAbv, VBlw, VBlw, VPst, O, O, O, O, O, O, O, O, O, B,
-
- /* Hanunoo */
-
- /* 1720 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1730 */ B, B, VAbv, VBlw, VPst, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Buhid */
-
- /* 1740 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1750 */ B, B, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Tagbanwa */
-
- /* 1760 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, B, B,
- /* 1770 */ B, O, VAbv, VBlw, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Khmer */
-
- /* 1780 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1790 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 17B0 */ B, B, B, B, CGJ, CGJ, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VPre, VPre,
- /* 17C0 */ VPre, VPre, VPre, VPre, VPre, VPre, VMAbv, VMPst, VPst, VMAbv, VMAbv, FMAbv, FAbv, CMAbv, FMAbv, VMAbv,
- /* 17D0 */ FMAbv, VAbv, H, FMAbv, O, O, O, O, O, O, O, O, B, FMAbv, O, O,
- /* 17E0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 17F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Mongolian */
-
- /* 1800 */ B, O, O, O, O, O, O, B, O, O, B, CGJ, CGJ, CGJ, O, CGJ,
- /* 1810 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 1820 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1830 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1870 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
- /* 1880 */ GB, GB, GB, GB, GB, CMAbv, CMAbv, B, B, B, B, B, B, B, B, B,
- /* 1890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18A0 */ B, B, B, B, B, B, B, B, B, CMBlw, B, O, O, O, O, O,
-
-#define use_offset_0x1900u 2248
-
-
- /* Limbu */
-
- /* 1900 */ GB, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
- /* 1920 */ VAbv, VAbv, VBlw, VPst, VPst, VAbv, VAbv, VAbv, VAbv, SUB, SUB, SUB, O, O, O, O,
- /* 1930 */ FPst, FPst, VMBlw, FPst, FPst, FPst, FPst, FPst, FPst, FBlw, VMAbv, FMBlw, O, O, O, O,
- /* 1940 */ O, O, O, O, O, O, B, B, B, B, B, B, B, B, B, B,
-
- /* Tai Le */
-
- /* 1950 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1960 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, O,
- /* 1970 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
-
- /* New Tai Lue */
-
- /* 1980 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19A0 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
- /* 19B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 19C0 */ B, B, B, B, B, B, B, B, VMPst, VMPst, O, O, O, O, O, O,
- /* 19D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
- /* 19E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 19F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Buginese */
-
- /* 1A00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A10 */ B, B, B, B, B, B, B, VAbv, VAbv, VPre, VPst, VAbv, O, O, O, O,
-
- /* Tai Tham */
-
- /* 1A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1A50 */ B, B, B, B, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, SUB, SUB, SUB, O,
- /* 1A60 */ Sk, VPst, VAbv, VPst, VPst, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VAbv, VBlw, VPst, VPre, VPre,
- /* 1A70 */ VPre, VPre, VPre, VAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VAbv, VMAbv, VMAbv, O, O, VMBlw,
- /* 1A80 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 1A90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x1b00u 2664
-
-
- /* Balinese */
-
- /* 1B00 */ VMAbv, VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B30 */ B, B, B, B, CMAbv, VPst, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VPre,
- /* 1B40 */ VPre, VPre, VAbv, VAbv, H, B, B, B, B, B, B, B, B, O, O, O,
- /* 1B50 */ B, B, B, B, B, B, B, B, B, B, O, GB, GB, O, O, GB,
- /* 1B60 */ O, O, GB, O, O, O, O, O, GB, O, O, SMAbv, SMBlw, SMAbv, SMAbv, SMAbv,
- /* 1B70 */ SMAbv, SMAbv, SMAbv, SMAbv, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Sundanese */
-
- /* 1B80 */ VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BA0 */ B, SUB, SUB, SUB, VAbv, VBlw, VPre, VPst, VAbv, VAbv, VPst, H, SUB, SUB, B, B,
- /* 1BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
-
- /* Batak */
-
- /* 1BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BE0 */ B, B, B, B, B, B, CMAbv, VPst, VAbv, VAbv, VPst, VPst, VPst, VAbv, VPst, VAbv,
- /* 1BF0 */ FAbv, FAbv, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Lepcha */
-
- /* 1C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1C20 */ B, B, B, B, SUB, SUB, VPst, VPre, VPre, VPre, VPst, VPst, VBlw, FAbv, FAbv, FAbv,
- /* 1C30 */ FAbv, FAbv, FAbv, FAbv, VMPre, VMPre, FMAbv, CMBlw, O, O, O, O, O, O, O, O,
- /* 1C40 */ B, B, B, B, B, B, B, B, B, B, O, O, O, B, B, B,
-
-#define use_offset_0x1cd0u 3000
-
-
- /* Vedic Extensions */
-
- /* 1CD0 */ VMAbv, VMAbv, VMAbv, O, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMAbv, VMAbv, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 1CE0 */ VMAbv, VMPst, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, O, O, O, O, VMBlw, O, O,
- /* 1CF0 */ O, O, O, O, VMAbv, CS, CS, VMPst, VMAbv, VMAbv, GB, O, O, O, O, O,
-
-#define use_offset_0x1df8u 3048
-
-
- /* Combining Diacritical Marks Supplement */
- O, O, O, FMAbv, O, O, O, O,
-
-#define use_offset_0x2008u 3056
-
-
- /* General Punctuation */
- O, O, O, O, ZWNJ, CGJ, O, O,
- /* 2010 */ GB, GB, GB, GB, GB, O, O, O,
-
-#define use_offset_0x2070u 3072
-
-
- /* Superscripts and Subscripts */
-
- /* 2070 */ O, O, O, O, FMPst, O, O, O, O, O, O, O, O, O, O, O,
- /* 2080 */ O, O, FMPst, FMPst, FMPst, O, O, O,
-
-#define use_offset_0x20f0u 3096
-
-
- /* Combining Diacritical Marks for Symbols */
-
- /* 20F0 */ VMAbv, O, O, O, O, O, O, O,
-
-#define use_offset_0x25c8u 3104
-
-
- /* Geometric Shapes */
- O, O, O, O, B, O, O, O,
-
-#define use_offset_0x2d30u 3112
-
-
- /* Tifinagh */
-
- /* 2D30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 2D60 */ B, B, B, B, B, B, B, B, O, O, O, O, O, O, O, B,
- /* 2D70 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, H,
-
-#define use_offset_0xa800u 3192
-
-
- /* Syloti Nagri */
-
- /* A800 */ B, B, VAbv, B, B, B, H, B, B, B, B, VMAbv, B, B, B, B,
- /* A810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A820 */ B, B, B, VPst, VPst, VBlw, VAbv, VPst, O, O, O, O, VBlw, O, O, O,
- /* A830 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Phags-pa */
-
- /* A840 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A850 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A860 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A870 */ B, B, B, B, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Saurashtra */
-
- /* A880 */ VMPst, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A890 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A8B0 */ B, B, B, B, MPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst, VPst,
- /* A8C0 */ VPst, VPst, VPst, VPst, H, VMAbv, O, O, O, O, O, O, O, O, O, O,
- /* A8D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
- /* Devanagari Extended */
-
- /* A8E0 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv,
- /* A8F0 */ VMAbv, VMAbv, B, B, O, O, O, O, O, O, O, O, O, O, B, VAbv,
-
- /* Kayah Li */
-
- /* A900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A920 */ B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VAbv, VMBlw, VMBlw, VMBlw, O, O,
-
- /* Rejang */
-
- /* A930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A940 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VBlw, VBlw, VBlw, VBlw, FAbv,
- /* A950 */ FAbv, FAbv, FPst, VPst, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A960 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A970 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Javanese */
-
- /* A980 */ VMAbv, VMAbv, FAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A990 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* A9B0 */ B, B, B, CMAbv, VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VPre, VAbv, MBlw, MPst, MBlw,
- /* A9C0 */ H, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* A9D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
- /* Myanmar Extended-B */
-
- /* A9E0 */ B, B, B, B, B, VAbv, O, B, B, B, B, B, B, B, B, B,
- /* A9F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
-
- /* Cham */
-
- /* AA00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA20 */ B, B, B, B, B, B, B, B, B, VMAbv, VAbv, VAbv, VAbv, VBlw, VAbv, VPre,
- /* AA30 */ VPre, VAbv, VBlw, MPst, MPre, MAbv, MBlw, O, O, O, O, O, O, O, O, O,
- /* AA40 */ B, B, B, FAbv, B, B, B, B, B, B, B, B, FAbv, FPst, O, O,
- /* AA50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
- /* Myanmar Extended-A */
-
- /* AA60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA70 */ O, B, B, B, GB, GB, GB, O, O, O, B, VMPst, VMAbv, VMPst, B, B,
-
- /* Tai Viet */
-
- /* AA80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AA90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* AAB0 */ VAbv, B, VAbv, VAbv, VBlw, B, B, VAbv, VAbv, B, B, B, B, B, VAbv, VMAbv,
- /* AAC0 */ B, VMAbv, B, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* AAD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Meetei Mayek Extensions */
-
- /* AAE0 */ B, B, B, B, B, B, B, B, B, B, B, VPre, VBlw, VAbv, VPre, VPst,
- /* AAF0 */ O, O, O, O, O, VMPst, H, O,
-
-#define use_offset_0xabc0u 3952
-
-
- /* Meetei Mayek */
-
- /* ABC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* ABE0 */ B, B, B, VPst, VPst, VAbv, VPst, VPst, VBlw, VPst, VPst, O, VMPst, VBlw, O, O,
- /* ABF0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0xfe00u 4016
-
-
- /* Variation Selectors */
-
- /* FE00 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
-#define use_offset_0x10570u 4032
-
-
- /* Vithkuqi */
-
- /* 10570 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B,
- /* 10580 */ B, B, B, B, B, B, B, B, B, B, B, O, B, B, B, B,
- /* 10590 */ B, B, B, O, B, B, O, B, B, B, B, B, B, B, B, B,
- /* 105A0 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 105B0 */ B, B, O, B, B, B, B, B, B, B, O, B, B, O, O, O,
-
-#define use_offset_0x10a00u 4112
-
-
- /* Kharoshthi */
-
- /* 10A00 */ B, VBlw, VBlw, VBlw, O, VAbv, VBlw, O, O, O, O, O, VPst, VMBlw, VMBlw, VMAbv,
- /* 10A10 */ B, B, B, B, O, B, B, B, O, B, B, B, B, B, B, B,
- /* 10A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10A30 */ B, B, B, B, B, B, O, O, CMAbv, CMBlw, CMBlw, O, O, O, O, H,
- /* 10A40 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
-
-#define use_offset_0x10ac0u 4192
-
-
- /* Manichaean */
-
- /* 10AC0 */ B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, B,
- /* 10AD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10AE0 */ B, B, B, B, B, CMBlw, CMBlw, O, O, O, O, B, B, B, B, B,
-
-#define use_offset_0x10b80u 4240
-
-
- /* Psalter Pahlavi */
-
- /* 10B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10B90 */ B, B, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10BA0 */ O, O, O, O, O, O, O, O, O, B, B, B, B, B, B, O,
-
-#define use_offset_0x10d00u 4288
-
-
- /* Hanifi Rohingya */
-
- /* 10D00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10D20 */ B, B, B, B, VMAbv, VMAbv, VMAbv, CMAbv, O, O, O, O, O, O, O, O,
- /* 10D30 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x10e80u 4352
-
-
- /* Yezidi */
-
- /* 10E80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10E90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10EA0 */ B, B, B, B, B, B, B, B, B, B, O, VAbv, VAbv, O, O, O,
- /* 10EB0 */ B, B, O, O, O, O, O, O,
-
-#define use_offset_0x10f30u 4408
-
-
- /* Sogdian */
-
- /* 10F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F40 */ B, B, B, B, B, B, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw, VMBlw,
- /* 10F50 */ VMBlw, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
- /* 10F60 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Old Uyghur */
-
- /* 10F70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 10F80 */ B, B, CMBlw, CMBlw, CMBlw, CMBlw, O, O, O, O, O, O, O, O, O, O,
- /* 10F90 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FA0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Chorasmian */
-
- /* 10FB0 */ B, O, B, B, B, B, B, O, B, B, B, B, B, B, B, B,
- /* 10FC0 */ O, B, B, B, B, O, O, O, O, B, B, B, O, O, O, O,
- /* 10FD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 10FF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Brahmi */
-
- /* 11000 */ VMPst, VMAbv, VMPst, CS, CS, B, B, B, B, B, B, B, B, B, B, B,
- /* 11010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11030 */ B, B, B, B, B, B, B, B, VAbv, VAbv, VAbv, VAbv, VBlw, VBlw, VBlw, VBlw,
- /* 11040 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, O, O, O, O, O, O, O, O, O,
- /* 11050 */ O, O, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
- /* 11060 */ N, N, N, N, N, N, B, B, B, B, B, B, B, B, B, B,
- /* 11070 */ VAbv, B, B, VAbv, VAbv, B, O, O, O, O, O, O, O, O, O, HN,
-
- /* Kaithi */
-
- /* 11080 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 110B0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VPst, VPst, H, CMBlw, O, O, O, O, O,
- /* 110C0 */ O, O, VBlw, O, O, O, O, O,
-
-#define use_offset_0x11100u 4816
-
-
- /* Chakma */
-
- /* 11100 */ VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11120 */ B, B, B, B, B, B, B, VBlw, VBlw, VBlw, VAbv, VAbv, VPre, VBlw, VAbv, VAbv,
- /* 11130 */ VBlw, VAbv, VAbv, H, CMAbv, O, B, B, B, B, B, B, B, B, B, B,
- /* 11140 */ O, O, O, O, B, VPst, VPst, B, O, O, O, O, O, O, O, O,
-
- /* Mahajani */
-
- /* 11150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11170 */ B, B, B, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Sharada */
-
- /* 11180 */ VMAbv, VMAbv, VMPst, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111B0 */ B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv,
- /* 111C0 */ H, B, R, R, O, O, O, O, GB, FMBlw, CMBlw, VAbv, VBlw, O, VPre, VMAbv,
- /* 111D0 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
-
- /* Sinhala Archaic Numbers */
-
- /* 111E0 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 111F0 */ B, B, B, B, B, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Khojki */
-
- /* 11200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11210 */ B, B, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11220 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VBlw,
- /* 11230 */ VAbv, VAbv, VAbv, VAbv, VMAbv, H, CMAbv, CMAbv, O, O, O, O, O, O, VMAbv, O,
-
-#define use_offset_0x11280u 5136
-
-
- /* Multani */
-
- /* 11280 */ B, B, B, B, B, B, B, O, B, O, B, B, B, B, O, B,
- /* 11290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, O, B,
- /* 112A0 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
-
- /* Khudawadi */
-
- /* 112B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 112D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv,
- /* 112E0 */ VPst, VPre, VPst, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, CMBlw, VBlw, O, O, O, O, O,
- /* 112F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
- /* Grantha */
-
- /* 11300 */ VMAbv, VMAbv, VMAbv, VMAbv, O, B, B, B, B, B, B, B, B, O, O, B,
- /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst,
- /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPre, VPre, HVM, O, O,
- /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B,
- /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
- /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O,
-
-#define use_offset_0x11400u 5384
-
-
- /* Newa */
-
- /* 11400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11430 */ B, B, B, B, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv,
- /* 11440 */ VPst, VPst, H, VMAbv, VMAbv, VMPst, CMBlw, B, O, O, O, O, O, O, O, O,
- /* 11450 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, FMAbv, B,
- /* 11460 */ CS, CS, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11470 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Tirhuta */
-
- /* 11480 */ O, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11490 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 114B0 */ VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VPre, VAbv, VPre, VPre, VPst, VPre, VMAbv,
- /* 114C0 */ VMAbv, VMAbv, H, CMBlw, B, O, O, O, O, O, O, O, O, O, O, O,
- /* 114D0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x11580u 5608
-
-
- /* Siddham */
-
- /* 11580 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11590 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 115A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 115B0 */ VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VPre, VPre, VPre, VPre, VMAbv, VMAbv, VMPst, H,
- /* 115C0 */ CMBlw, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115D0 */ O, O, O, O, O, O, O, O, B, B, B, B, VBlw, VBlw, O, O,
- /* 115E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 115F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Modi */
-
- /* 11600 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11610 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11620 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11630 */ VPst, VPst, VPst, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VPst, VPst, VMAbv, VMPst, H,
- /* 11640 */ VAbv, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11650 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 11660 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11670 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Takri */
-
- /* 11680 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11690 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 116A0 */ B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMPst, VAbv, VPre, VPst,
- /* 116B0 */ VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, H, CMBlw, B, O, O, O, O, O, O, O,
- /* 116C0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 116D0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 116E0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 116F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Ahom */
-
- /* 11700 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11710 */ B, B, B, B, B, B, B, B, B, B, B, O, O, MBlw, MPre, MAbv,
- /* 11720 */ VPst, VPst, VAbv, VAbv, VBlw, VBlw, VPre, VAbv, VBlw, VAbv, VAbv, VAbv, O, O, O, O,
- /* 11730 */ B, B, B, B, B, B, B, B, B, B, B, B, O, O, O, O,
- /* 11740 */ B, B, B, B, B, B, B, O,
-
-#define use_offset_0x11800u 6064
-
-
- /* Dogra */
-
- /* 11800 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11810 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11820 */ B, B, B, B, B, B, B, B, B, B, B, B, VPst, VPre, VPst, VBlw,
- /* 11830 */ VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VMAbv, VMPst, H, CMBlw, O, O, O, O, O,
-
-#define use_offset_0x11900u 6128
-
-
- /* Dives Akuru */
-
- /* 11900 */ B, B, B, B, B, B, B, O, O, B, O, O, B, B, B, B,
- /* 11910 */ B, B, B, B, O, B, B, O, B, B, B, B, B, B, B, B,
- /* 11920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11930 */ VPst, VPst, VPst, VPst, VPst, VPre, O, VPre, VPre, O, O, VMAbv, VMAbv, VPst, H, R,
- /* 11940 */ MPst, R, MPst, CMBlw, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 11950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x119a0u 6224
-
-
- /* Nandinagari */
-
- /* 119A0 */ B, B, B, B, B, B, B, B, O, O, B, B, B, B, B, B,
- /* 119B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 119D0 */ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, O, O, VAbv, VAbv, VPst, VPst, VMPst, VMPst,
- /* 119E0 */ H, B, O, O, VPre, O, O, O, O, O, O, O, O, O, O, O,
- /* 119F0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Zanabazar Square */
-
- /* 11A00 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, B, B, B, B, B,
- /* 11A10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A30 */ B, B, B, FMBlw, VBlw, VMAbv, VMAbv, VMAbv, VMAbv, VMPst, R, MBlw, MBlw, MBlw, MBlw, GB,
- /* 11A40 */ O, O, O, O, O, GB, O, H, O, O, O, O, O, O, O, O,
-
- /* Soyombo */
-
- /* 11A50 */ B, VAbv, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VBlw, VBlw, VBlw, B, B, B, B,
- /* 11A60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11A80 */ B, B, B, B, R, R, R, R, R, R, FBlw, FBlw, FBlw, FBlw, FBlw, FBlw,
- /* 11A90 */ FBlw, FBlw, FBlw, FBlw, FBlw, FBlw, VMAbv, VMPst, CMAbv, H, O, O, O, B, O, O,
-
-#define use_offset_0x11c00u 6480
-
-
- /* Bhaiksuki */
-
- /* 11C00 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B,
- /* 11C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, VPst,
- /* 11C30 */ VAbv, VAbv, VBlw, VBlw, VBlw, VBlw, VBlw, O, VAbv, VAbv, VAbv, VAbv, VMAbv, VMAbv, VMPst, H,
- /* 11C40 */ B, O, O, O, GB, GB, O, O, O, O, O, O, O, O, O, O,
- /* 11C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
-
- /* Marchen */
-
- /* 11C70 */ O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11C90 */ O, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CA0 */ SUB, SUB, SUB, SUB, SUB, SUB, SUB, SUB, O, SUB, SUB, SUB, SUB, SUB, SUB, SUB,
- /* 11CB0 */ VBlw, VPre, VBlw, VAbv, VPst, VMAbv, VMAbv, O,
-
-#define use_offset_0x11d00u 6664
-
-
- /* Masaram Gondi */
-
- /* 11D00 */ B, B, B, B, B, B, B, O, B, B, O, B, B, B, B, B,
- /* 11D10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D30 */ B, VAbv, VAbv, VAbv, VAbv, VAbv, VBlw, O, O, O, VAbv, O, VAbv, VAbv, O, VAbv,
- /* 11D40 */ VMAbv, VMAbv, CMBlw, VAbv, VBlw, H, R, MBlw, O, O, O, O, O, O, O, O,
- /* 11D50 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
- /* Gunjala Gondi */
-
- /* 11D60 */ B, B, B, B, B, B, O, B, B, O, B, B, B, B, B, B,
- /* 11D70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11D80 */ B, B, B, B, B, B, B, B, B, B, VPst, VPst, VPst, VPst, VPst, O,
- /* 11D90 */ VAbv, VAbv, O, VPst, VPst, VMAbv, VMPst, H, O, O, O, O, O, O, O, O,
- /* 11DA0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x11ee0u 6840
-
-
- /* Makasar */
-
- /* 11EE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 11EF0 */ B, B, GB, VAbv, VBlw, VPre, VPst, O,
-
-#define use_offset_0x13000u 6864
-
-
- /* Egyptian Hieroglyphs */
-
- /* 13000 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13010 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13020 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13030 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13040 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13050 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13060 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13070 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13080 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13090 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 130F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13130 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13140 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13150 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13160 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13170 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13180 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13190 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 131F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13200 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13210 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13220 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13230 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13240 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13250 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13260 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13270 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13280 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 132F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13300 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13310 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13320 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13330 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13340 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13350 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13360 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13370 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13380 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13390 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133B0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133E0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 133F0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13400 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13410 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 13420 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, O,
-
- /* Egyptian Hieroglyph Format Controls */
-
- /* 13430 */ H, H, H, H, H, H, H, B, B, O, O, O, O, O, O, O,
-
-#define use_offset_0x16ac0u 7952
-
-
- /* Tangsa */
-
- /* 16AC0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
- /* 16AD0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 16AE0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
- /* 16AF0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Pahawh Hmong */
-
- /* 16B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16B30 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O,
-
-#define use_offset_0x16f00u 8072
-
-
- /* Miao */
-
- /* 16F00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 16F40 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, CMBlw,
- /* 16F50 */ O, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F60 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F70 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw,
- /* 16F80 */ VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, VBlw, O, O, O, O, O, O, O, VMBlw,
- /* 16F90 */ VMBlw, VMBlw, VMBlw, O, O, O, O, O,
-
-#define use_offset_0x16fe0u 8224
-
-
- /* Ideographic Symbols and Punctuation */
-
- /* 16FE0 */ O, O, O, O, B, O, O, O,
-
-#define use_offset_0x18b00u 8232
-
-
- /* Khitan Small Script */
-
- /* 18B00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18B90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BD0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BE0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18BF0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C60 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C80 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18C90 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CA0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CB0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CC0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 18CD0 */ B, B, B, B, B, B, O, O,
-
-#define use_offset_0x1bc00u 8704
-
-
- /* Duployan */
-
- /* 1BC00 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC10 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC20 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC30 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC40 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC50 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1BC60 */ B, B, B, B, B, B, B, B, B, B, B, O, O, O, O, O,
- /* 1BC70 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 1BC80 */ B, B, B, B, B, B, B, B, B, O, O, O, O, O, O, O,
- /* 1BC90 */ B, B, B, B, B, B, B, B, B, B, O, O, O, CMBlw, CMBlw, O,
-
-#define use_offset_0x1e100u 8864
-
-
- /* Nyiakeng Puachue Hmong */
-
- /* 1E100 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E110 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E120 */ B, B, B, B, B, B, B, B, B, B, B, B, B, O, O, O,
- /* 1E130 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, B, B, B, B, B, B, B, O, O,
- /* 1E140 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, B, B,
-
-#define use_offset_0x1e290u 8944
-
-
- /* Toto */
-
- /* 1E290 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2A0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, O,
- /* 1E2B0 */ O, O, O, O, O, O, O, O, O, O, O, O, O, O, O, O,
-
- /* Wancho */
-
- /* 1E2C0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2D0 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E2E0 */ B, B, B, B, B, B, B, B, B, B, B, B, VMAbv, VMAbv, VMAbv, VMAbv,
- /* 1E2F0 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0x1e900u 9056
-
-
- /* Adlam */
-
- /* 1E900 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E910 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E920 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E930 */ B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B,
- /* 1E940 */ B, B, B, B, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, CMAbv, B, O, O, O, O,
- /* 1E950 */ B, B, B, B, B, B, B, B, B, B, O, O, O, O, O, O,
-
-#define use_offset_0xe0100u 9152
-
-
- /* Variation Selectors Supplement */
-
- /* E0100 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0110 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0120 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0130 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0140 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0150 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0160 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0170 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0180 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E0190 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01A0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01B0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01C0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01D0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
- /* E01E0 */ CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ, CGJ,
-
-}; /* Table items: 9392; occupancy: 79% */
-
-static inline uint8_t
-hb_use_get_category (hb_codepoint_t u)
-{
- switch (u >> 12)
- {
- case 0x0u:
- if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return use_table[u - 0x0028u + use_offset_0x0028u];
- if (hb_in_range<hb_codepoint_t> (u, 0x00A0u, 0x00D7u)) return use_table[u - 0x00A0u + use_offset_0x00a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0348u, 0x034Fu)) return use_table[u - 0x0348u + use_offset_0x0348u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0640u, 0x0647u)) return use_table[u - 0x0640u + use_offset_0x0640u];
- if (hb_in_range<hb_codepoint_t> (u, 0x07C8u, 0x07FFu)) return use_table[u - 0x07C8u + use_offset_0x07c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0840u, 0x085Fu)) return use_table[u - 0x0840u + use_offset_0x0840u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0DF7u)) return use_table[u - 0x0900u + use_offset_0x0900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x0F00u, 0x0FC7u)) return use_table[u - 0x0F00u + use_offset_0x0f00u];
- break;
-
- case 0x1u:
- if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return use_table[u - 0x1000u + use_offset_0x1000u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1700u, 0x18AFu)) return use_table[u - 0x1700u + use_offset_0x1700u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1900u, 0x1A9Fu)) return use_table[u - 0x1900u + use_offset_0x1900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1B00u, 0x1C4Fu)) return use_table[u - 0x1B00u + use_offset_0x1b00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return use_table[u - 0x1CD0u + use_offset_0x1cd0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1DF8u, 0x1DFFu)) return use_table[u - 0x1DF8u + use_offset_0x1df8u];
- break;
-
- case 0x2u:
- if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2017u)) return use_table[u - 0x2008u + use_offset_0x2008u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return use_table[u - 0x2070u + use_offset_0x2070u];
- if (hb_in_range<hb_codepoint_t> (u, 0x20F0u, 0x20F7u)) return use_table[u - 0x20F0u + use_offset_0x20f0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x25C8u, 0x25CFu)) return use_table[u - 0x25C8u + use_offset_0x25c8u];
- if (hb_in_range<hb_codepoint_t> (u, 0x2D30u, 0x2D7Fu)) return use_table[u - 0x2D30u + use_offset_0x2d30u];
- break;
-
- case 0xAu:
- if (hb_in_range<hb_codepoint_t> (u, 0xA800u, 0xAAF7u)) return use_table[u - 0xA800u + use_offset_0xa800u];
- if (hb_in_range<hb_codepoint_t> (u, 0xABC0u, 0xABFFu)) return use_table[u - 0xABC0u + use_offset_0xabc0u];
- break;
-
- case 0xFu:
- if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return use_table[u - 0xFE00u + use_offset_0xfe00u];
- break;
-
- case 0x10u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10570u, 0x105BFu)) return use_table[u - 0x10570u + use_offset_0x10570u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10A00u, 0x10A4Fu)) return use_table[u - 0x10A00u + use_offset_0x10a00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return use_table[u - 0x10AC0u + use_offset_0x10ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return use_table[u - 0x10B80u + use_offset_0x10b80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D3Fu)) return use_table[u - 0x10D00u + use_offset_0x10d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10E80u, 0x10EB7u)) return use_table[u - 0x10E80u + use_offset_0x10e80u];
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- break;
-
- case 0x11u:
- if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x110C7u)) return use_table[u - 0x10F30u + use_offset_0x10f30u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11100u, 0x1123Fu)) return use_table[u - 0x11100u + use_offset_0x11100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11280u, 0x11377u)) return use_table[u - 0x11280u + use_offset_0x11280u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11400u, 0x114DFu)) return use_table[u - 0x11400u + use_offset_0x11400u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11580u, 0x11747u)) return use_table[u - 0x11580u + use_offset_0x11580u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11800u, 0x1183Fu)) return use_table[u - 0x11800u + use_offset_0x11800u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11900u, 0x1195Fu)) return use_table[u - 0x11900u + use_offset_0x11900u];
- if (hb_in_range<hb_codepoint_t> (u, 0x119A0u, 0x11A9Fu)) return use_table[u - 0x119A0u + use_offset_0x119a0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11C00u, 0x11CB7u)) return use_table[u - 0x11C00u + use_offset_0x11c00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11D00u, 0x11DAFu)) return use_table[u - 0x11D00u + use_offset_0x11d00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x11EE0u, 0x11EF7u)) return use_table[u - 0x11EE0u + use_offset_0x11ee0u];
- break;
-
- case 0x13u:
- if (hb_in_range<hb_codepoint_t> (u, 0x13000u, 0x1343Fu)) return use_table[u - 0x13000u + use_offset_0x13000u];
- break;
-
- case 0x16u:
- if (hb_in_range<hb_codepoint_t> (u, 0x16AC0u, 0x16B37u)) return use_table[u - 0x16AC0u + use_offset_0x16ac0u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16F00u, 0x16F97u)) return use_table[u - 0x16F00u + use_offset_0x16f00u];
- if (hb_in_range<hb_codepoint_t> (u, 0x16FE0u, 0x16FE7u)) return use_table[u - 0x16FE0u + use_offset_0x16fe0u];
- break;
-
- case 0x18u:
- if (hb_in_range<hb_codepoint_t> (u, 0x18B00u, 0x18CD7u)) return use_table[u - 0x18B00u + use_offset_0x18b00u];
- break;
-
- case 0x1Bu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1BC00u, 0x1BC9Fu)) return use_table[u - 0x1BC00u + use_offset_0x1bc00u];
- break;
-
- case 0x1Eu:
- if (hb_in_range<hb_codepoint_t> (u, 0x1E100u, 0x1E14Fu)) return use_table[u - 0x1E100u + use_offset_0x1e100u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E290u, 0x1E2FFu)) return use_table[u - 0x1E290u + use_offset_0x1e290u];
- if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E95Fu)) return use_table[u - 0x1E900u + use_offset_0x1e900u];
- break;
-
- case 0xE0u:
- if (hb_in_range<hb_codepoint_t> (u, 0xE0100u, 0xE01EFu)) return use_table[u - 0xE0100u + use_offset_0xe0100u];
- break;
-
- default:
- break;
- }
- return USE(O);
-}
-
-#undef B
-#undef CGJ
-#undef CS
-#undef G
-#undef GB
-#undef H
-#undef HN
-#undef HVM
-#undef J
-#undef N
-#undef O
-#undef R
-#undef SB
-#undef SE
-#undef SUB
-#undef Sk
-#undef ZWNJ
-#undef CMAbv
-#undef CMBlw
-#undef FAbv
-#undef FBlw
-#undef FPst
-#undef FMAbv
-#undef FMBlw
-#undef FMPst
-#undef MAbv
-#undef MBlw
-#undef MPst
-#undef MPre
-#undef SMAbv
-#undef SMBlw
-#undef VAbv
-#undef VBlw
-#undef VPst
-#undef VPre
-#undef VMAbv
-#undef VMBlw
-#undef VMPst
-#undef VMPre
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_USE_TABLE_HH */
-/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
deleted file mode 100644
index 70b637933d..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-use.cc
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright © 2015 Mozilla Foundation.
- * Copyright © 2015 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Mozilla Author(s): Jonathan Kew
- * Google Author(s): Behdad Esfahbod
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-use-machine.hh"
-#include "hb-ot-shape-complex-use-table.hh"
-#include "hb-ot-shape-complex-arabic.hh"
-#include "hb-ot-shape-complex-arabic-joining-list.hh"
-#include "hb-ot-shape-complex-vowel-constraints.hh"
-
-
-/*
- * Universal Shaping Engine.
- * https://docs.microsoft.com/en-us/typography/script-development/use
- */
-
-static const hb_tag_t
-use_basic_features[] =
-{
- /*
- * Basic features.
- * These features are applied all at once, before reordering, constrained
- * to the syllable.
- */
- HB_TAG('r','k','r','f'),
- HB_TAG('a','b','v','f'),
- HB_TAG('b','l','w','f'),
- HB_TAG('h','a','l','f'),
- HB_TAG('p','s','t','f'),
- HB_TAG('v','a','t','u'),
- HB_TAG('c','j','c','t'),
-};
-static const hb_tag_t
-use_topographical_features[] =
-{
- HB_TAG('i','s','o','l'),
- HB_TAG('i','n','i','t'),
- HB_TAG('m','e','d','i'),
- HB_TAG('f','i','n','a'),
-};
-/* Same order as use_topographical_features. */
-enum joining_form_t {
- JOINING_FORM_ISOL,
- JOINING_FORM_INIT,
- JOINING_FORM_MEDI,
- JOINING_FORM_FINA,
- _JOINING_FORM_NONE
-};
-static const hb_tag_t
-use_other_features[] =
-{
- /*
- * Other features.
- * These features are applied all at once, after reordering and
- * clearing syllables.
- */
- HB_TAG('a','b','v','s'),
- HB_TAG('b','l','w','s'),
- HB_TAG('h','a','l','n'),
- HB_TAG('p','r','e','s'),
- HB_TAG('p','s','t','s'),
-};
-
-static void
-setup_syllables_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-record_rphf_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-record_pref_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-static void
-reorder_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer);
-
-static void
-collect_features_use (hb_ot_shape_planner_t *plan)
-{
- hb_ot_map_builder_t *map = &plan->map;
-
- /* Do this before any lookups have been applied. */
- map->add_gsub_pause (setup_syllables_use);
-
- /* "Default glyph pre-processing group" */
- map->enable_feature (HB_TAG('l','o','c','l'));
- map->enable_feature (HB_TAG('c','c','m','p'));
- map->enable_feature (HB_TAG('n','u','k','t'));
- map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
-
- /* "Reordering group" */
- map->add_gsub_pause (_hb_clear_substitution_flags);
- map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
- map->add_gsub_pause (record_rphf_use);
- map->add_gsub_pause (_hb_clear_substitution_flags);
- map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
- map->add_gsub_pause (record_pref_use);
-
- /* "Orthographic unit shaping group" */
- for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
- map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ);
-
- map->add_gsub_pause (reorder_use);
- map->add_gsub_pause (_hb_clear_syllables);
-
- /* "Topographical features" */
- for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
- map->add_feature (use_topographical_features[i]);
- map->add_gsub_pause (nullptr);
-
- /* "Standard typographic presentation" */
- for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
- map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
-}
-
-struct use_shape_plan_t
-{
- hb_mask_t rphf_mask;
-
- arabic_shape_plan_t *arabic_plan;
-};
-
-static void *
-data_create_use (const hb_ot_shape_plan_t *plan)
-{
- use_shape_plan_t *use_plan = (use_shape_plan_t *) hb_calloc (1, sizeof (use_shape_plan_t));
- if (unlikely (!use_plan))
- return nullptr;
-
- use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f'));
-
- if (has_arabic_joining (plan->props.script))
- {
- use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
- if (unlikely (!use_plan->arabic_plan))
- {
- hb_free (use_plan);
- return nullptr;
- }
- }
-
- return use_plan;
-}
-
-static void
-data_destroy_use (void *data)
-{
- use_shape_plan_t *use_plan = (use_shape_plan_t *) data;
-
- if (use_plan->arabic_plan)
- data_destroy_arabic (use_plan->arabic_plan);
-
- hb_free (data);
-}
-
-static void
-setup_masks_use (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
- const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
-
- /* Do this before allocating use_category(). */
- if (use_plan->arabic_plan)
- {
- setup_masks_arabic_plan (use_plan->arabic_plan, buffer, plan->props.script);
- }
-
- HB_BUFFER_ALLOCATE_VAR (buffer, use_category);
-
- /* We cannot setup masks here. We save information about characters
- * and setup masks later on in a pause-callback. */
-
- unsigned int count = buffer->len;
- hb_glyph_info_t *info = buffer->info;
- for (unsigned int i = 0; i < count; i++)
- info[i].use_category() = hb_use_get_category (info[i].codepoint);
-}
-
-static void
-setup_rphf_mask (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer)
-{
- const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
-
- hb_mask_t mask = use_plan->rphf_mask;
- if (!mask) return;
-
- hb_glyph_info_t *info = buffer->info;
-
- foreach_syllable (buffer, start, end)
- {
- unsigned int limit = info[start].use_category() == USE(R) ? 1 : hb_min (3u, end - start);
- for (unsigned int i = start; i < start + limit; i++)
- info[i].mask |= mask;
- }
-}
-
-static void
-setup_topographical_masks (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer)
-{
- const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
- if (use_plan->arabic_plan)
- return;
-
- static_assert ((JOINING_FORM_INIT < 4 && JOINING_FORM_ISOL < 4 && JOINING_FORM_MEDI < 4 && JOINING_FORM_FINA < 4), "");
- hb_mask_t masks[4], all_masks = 0;
- for (unsigned int i = 0; i < 4; i++)
- {
- masks[i] = plan->map.get_1_mask (use_topographical_features[i]);
- if (masks[i] == plan->map.get_global_mask ())
- masks[i] = 0;
- all_masks |= masks[i];
- }
- if (!all_masks)
- return;
- hb_mask_t other_masks = ~all_masks;
-
- unsigned int last_start = 0;
- joining_form_t last_form = _JOINING_FORM_NONE;
- hb_glyph_info_t *info = buffer->info;
- foreach_syllable (buffer, start, end)
- {
- use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
- switch (syllable_type)
- {
- case use_symbol_cluster:
- case use_hieroglyph_cluster:
- case use_non_cluster:
- /* These don't join. Nothing to do. */
- last_form = _JOINING_FORM_NONE;
- break;
-
- case use_virama_terminated_cluster:
- case use_sakot_terminated_cluster:
- case use_standard_cluster:
- case use_number_joiner_terminated_cluster:
- case use_numeral_cluster:
- case use_broken_cluster:
-
- bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
-
- if (join)
- {
- /* Fixup previous syllable's form. */
- last_form = last_form == JOINING_FORM_FINA ? JOINING_FORM_MEDI : JOINING_FORM_INIT;
- for (unsigned int i = last_start; i < start; i++)
- info[i].mask = (info[i].mask & other_masks) | masks[last_form];
- }
-
- /* Form for this syllable. */
- last_form = join ? JOINING_FORM_FINA : JOINING_FORM_ISOL;
- for (unsigned int i = start; i < end; i++)
- info[i].mask = (info[i].mask & other_masks) | masks[last_form];
-
- break;
- }
-
- last_start = start;
- }
-}
-
-static void
-setup_syllables_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- find_syllables_use (buffer);
- foreach_syllable (buffer, start, end)
- buffer->unsafe_to_break (start, end);
- setup_rphf_mask (plan, buffer);
- setup_topographical_masks (plan, buffer);
-}
-
-static void
-record_rphf_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
-
- hb_mask_t mask = use_plan->rphf_mask;
- if (!mask) return;
- hb_glyph_info_t *info = buffer->info;
-
- foreach_syllable (buffer, start, end)
- {
- /* Mark a substituted repha as USE(R). */
- for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
- if (_hb_glyph_info_substituted (&info[i]))
- {
- info[i].use_category() = USE(R);
- break;
- }
- }
-}
-
-static void
-record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_font_t *font HB_UNUSED,
- hb_buffer_t *buffer)
-{
- hb_glyph_info_t *info = buffer->info;
-
- foreach_syllable (buffer, start, end)
- {
- /* Mark a substituted pref as VPre, as they behave the same way. */
- for (unsigned int i = start; i < end; i++)
- if (_hb_glyph_info_substituted (&info[i]))
- {
- info[i].use_category() = USE(VPre);
- break;
- }
- }
-}
-
-static inline bool
-is_halant_use (const hb_glyph_info_t &info)
-{
- return (info.use_category() == USE(H) || info.use_category() == USE(HVM)) &&
- !_hb_glyph_info_ligated (&info);
-}
-
-static void
-reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
-{
- use_syllable_type_t syllable_type = (use_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
- /* Only a few syllable types need reordering. */
- if (unlikely (!(FLAG_UNSAFE (syllable_type) &
- (FLAG (use_virama_terminated_cluster) |
- FLAG (use_sakot_terminated_cluster) |
- FLAG (use_standard_cluster) |
- FLAG (use_broken_cluster) |
- 0))))
- return;
-
- hb_glyph_info_t *info = buffer->info;
-
-#define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
- FLAG64 (USE(FBlw)) | \
- FLAG64 (USE(FPst)) | \
- FLAG64 (USE(MAbv)) | \
- FLAG64 (USE(MBlw)) | \
- FLAG64 (USE(MPst)) | \
- FLAG64 (USE(MPre)) | \
- FLAG64 (USE(VAbv)) | \
- FLAG64 (USE(VBlw)) | \
- FLAG64 (USE(VPst)) | \
- FLAG64 (USE(VPre)) | \
- FLAG64 (USE(VMAbv)) | \
- FLAG64 (USE(VMBlw)) | \
- FLAG64 (USE(VMPst)) | \
- FLAG64 (USE(VMPre)))
-
- /* Move things forward. */
- if (info[start].use_category() == USE(R) && end - start > 1)
- {
- /* Got a repha. Reorder it towards the end, but before the first post-base
- * glyph. */
- for (unsigned int i = start + 1; i < end; i++)
- {
- bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
- is_halant_use (info[i]);
- if (is_post_base_glyph || i == end - 1)
- {
- /* If we hit a post-base glyph, move before it; otherwise move to the
- * end. Shift things in between backward. */
-
- if (is_post_base_glyph)
- i--;
-
- buffer->merge_clusters (start, i + 1);
- hb_glyph_info_t t = info[start];
- memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
- info[i] = t;
-
- break;
- }
- }
- }
-
- /* Move things back. */
- unsigned int j = start;
- for (unsigned int i = start; i < end; i++)
- {
- uint32_t flag = FLAG_UNSAFE (info[i].use_category());
- if (is_halant_use (info[i]))
- {
- /* If we hit a halant, move after it; otherwise move to the beginning, and
- * shift things in between forward. */
- j = i + 1;
- }
- else if (((flag) & (FLAG (USE(VPre)) | FLAG (USE(VMPre)))) &&
- /* Only move the first component of a MultipleSubst. */
- 0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
- j < i)
- {
- buffer->merge_clusters (j, i + 1);
- hb_glyph_info_t t = info[i];
- memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0]));
- info[j] = t;
- }
- }
-}
-
-static void
-reorder_use (const hb_ot_shape_plan_t *plan,
- hb_font_t *font,
- hb_buffer_t *buffer)
-{
- if (buffer->message (font, "start reordering USE"))
- {
- hb_syllabic_insert_dotted_circles (font, buffer,
- use_broken_cluster,
- USE(B),
- USE(R));
-
- foreach_syllable (buffer, start, end)
- reorder_syllable_use (buffer, start, end);
-
- (void) buffer->message (font, "end reordering USE");
- }
-
- HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
-}
-
-
-static void
-preprocess_text_use (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font)
-{
- _hb_preprocess_text_vowel_constraints (plan, buffer, font);
-}
-
-static bool
-compose_use (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t a,
- hb_codepoint_t b,
- hb_codepoint_t *ab)
-{
- /* Avoid recomposing split matras. */
- if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
- return false;
-
- return (bool)c->unicode->compose (a, b, ab);
-}
-
-
-const hb_ot_complex_shaper_t _hb_ot_complex_shaper_use =
-{
- collect_features_use,
- nullptr, /* override_features */
- data_create_use,
- data_destroy_use,
- preprocess_text_use,
- nullptr, /* postprocess_glyphs */
- HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
- nullptr, /* decompose */
- compose_use,
- setup_masks_use,
- HB_TAG_NONE, /* gpos_tag */
- nullptr, /* reorder_marks */
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
- false, /* fallback_position */
-};
-
-
-#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
deleted file mode 100644
index d2cca105a4..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.cc
+++ /dev/null
@@ -1,443 +0,0 @@
-/* == Start of generated functions == */
-/*
- * The following functions are generated by running:
- *
- * ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
- *
- * on files with these headers:
- *
- * # IndicShapingInvalidCluster.txt
- * # Date: 2015-03-12, 21:17:00 GMT [AG]
- * # Date: 2019-11-08, 23:22:00 GMT [AG]
- *
- * # Scripts-14.0.0.txt
- * # Date: 2021-07-10, 00:35:31 GMT
- */
-
-#include "hb.hh"
-
-#ifndef HB_NO_OT_SHAPE
-
-#include "hb-ot-shape-complex-vowel-constraints.hh"
-
-static void
-_output_dotted_circle (hb_buffer_t *buffer)
-{
- (void) buffer->output_glyph (0x25CCu);
- _hb_glyph_info_reset_continuation (&buffer->prev());
-}
-
-static void
-_output_with_dotted_circle (hb_buffer_t *buffer)
-{
- _output_dotted_circle (buffer);
- (void) buffer->next_glyph ();
-}
-
-void
-_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
- hb_buffer_t *buffer,
- hb_font_t *font HB_UNUSED)
-{
-#ifdef HB_NO_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS
- return;
-#endif
- if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
- return;
-
- /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
- * vowel-sequences that look like another vowel. Data for each script
- * collected from the USE script development spec.
- *
- * https://github.com/harfbuzz/harfbuzz/issues/1019
- */
- buffer->clear_output ();
- unsigned int count = buffer->len;
- switch ((unsigned) buffer->props.script)
- {
- case HB_SCRIPT_DEVANAGARI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0905u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u:
- case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu:
- case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u:
- matched = true;
- break;
- }
- break;
- case 0x0906u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u:
- case 0x0948u:
- matched = true;
- break;
- }
- break;
- case 0x0909u:
- matched = 0x0941u == buffer->cur (1).codepoint;
- break;
- case 0x090Fu:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0945u: case 0x0946u: case 0x0947u:
- matched = true;
- break;
- }
- break;
- case 0x0930u:
- if (0x094Du == buffer->cur (1).codepoint &&
- buffer->idx + 2 < count &&
- 0x0907u == buffer->cur (2).codepoint)
- {
- (void) buffer->next_glyph ();
- matched = true;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_BENGALI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0985u:
- matched = 0x09BEu == buffer->cur (1).codepoint;
- break;
- case 0x098Bu:
- matched = 0x09C3u == buffer->cur (1).codepoint;
- break;
- case 0x098Cu:
- matched = 0x09E2u == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_GURMUKHI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0A05u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu:
- matched = true;
- break;
- }
- break;
- case 0x0A72u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0A3Fu: case 0x0A40u: case 0x0A47u:
- matched = true;
- break;
- }
- break;
- case 0x0A73u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0A41u: case 0x0A42u: case 0x0A4Bu:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_GUJARATI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0A85u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u:
- case 0x0AC9u: case 0x0ACBu: case 0x0ACCu:
- matched = true;
- break;
- }
- break;
- case 0x0AC5u:
- matched = 0x0ABEu == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_ORIYA:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0B05u:
- matched = 0x0B3Eu == buffer->cur (1).codepoint;
- break;
- case 0x0B0Fu: case 0x0B13u:
- matched = 0x0B57u == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_TAMIL:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- if (0x0B85u == buffer->cur ().codepoint &&
- 0x0BC2u == buffer->cur (1).codepoint)
- {
- matched = true;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_TELUGU:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0C12u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0C4Cu: case 0x0C55u:
- matched = true;
- break;
- }
- break;
- case 0x0C3Fu: case 0x0C46u: case 0x0C4Au:
- matched = 0x0C55u == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_KANNADA:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0C89u: case 0x0C8Bu:
- matched = 0x0CBEu == buffer->cur (1).codepoint;
- break;
- case 0x0C92u:
- matched = 0x0CCCu == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_MALAYALAM:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0D07u: case 0x0D09u:
- matched = 0x0D57u == buffer->cur (1).codepoint;
- break;
- case 0x0D0Eu:
- matched = 0x0D46u == buffer->cur (1).codepoint;
- break;
- case 0x0D12u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0D3Eu: case 0x0D57u:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_SINHALA:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x0D85u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0DCFu: case 0x0DD0u: case 0x0DD1u:
- matched = true;
- break;
- }
- break;
- case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u:
- matched = 0x0DDFu == buffer->cur (1).codepoint;
- break;
- case 0x0D8Du:
- matched = 0x0DD8u == buffer->cur (1).codepoint;
- break;
- case 0x0D91u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu:
- case 0x0DDDu: case 0x0DDEu:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_BRAHMI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x11005u:
- matched = 0x11038u == buffer->cur (1).codepoint;
- break;
- case 0x1100Bu:
- matched = 0x1103Eu == buffer->cur (1).codepoint;
- break;
- case 0x1100Fu:
- matched = 0x11042u == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_KHUDAWADI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x112B0u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u:
- case 0x112E8u:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_TIRHUTA:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x11481u:
- matched = 0x114B0u == buffer->cur (1).codepoint;
- break;
- case 0x1148Bu: case 0x1148Du:
- matched = 0x114BAu == buffer->cur (1).codepoint;
- break;
- case 0x114AAu:
- switch (buffer->cur (1).codepoint)
- {
- case 0x114B5u: case 0x114B6u:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_MODI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x11600u: case 0x11601u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x11639u: case 0x1163Au:
- matched = true;
- break;
- }
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- case HB_SCRIPT_TAKRI:
- for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
- {
- bool matched = false;
- switch (buffer->cur ().codepoint)
- {
- case 0x11680u:
- switch (buffer->cur (1).codepoint)
- {
- case 0x116ADu: case 0x116B4u: case 0x116B5u:
- matched = true;
- break;
- }
- break;
- case 0x11686u:
- matched = 0x116B2u == buffer->cur (1).codepoint;
- break;
- }
- (void) buffer->next_glyph ();
- if (matched) _output_with_dotted_circle (buffer);
- }
- break;
-
- default:
- break;
- }
- buffer->sync ();
-}
-
-
-#endif
-/* == End of generated functions == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh
deleted file mode 100644
index d9082d4ead..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex-vowel-constraints.hh
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright © 2018 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
-#define HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH
-
-#include "hb.hh"
-
-#include "hb-ot-shape-complex.hh"
-
-HB_INTERNAL void
-_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font);
-
-#endif /* HB_OT_SHAPE_COMPLEX_VOWEL_CONSTRAINTS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh b/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
deleted file mode 100644
index 8012a9ae94..0000000000
--- a/thirdparty/harfbuzz/src/hb-ot-shape-complex.hh
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright © 2010,2011,2012 Google, Inc.
- *
- * This is part of HarfBuzz, a text shaping library.
- *
- * Permission is hereby granted, without written agreement and without
- * license or royalty fees, to use, copy, modify, and distribute this
- * software and its documentation for any purpose, provided that the
- * above copyright notice and the following two paragraphs appear in
- * all copies of this software.
- *
- * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
- * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
- * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
- *
- * Google Author(s): Behdad Esfahbod
- */
-
-#ifndef HB_OT_SHAPE_COMPLEX_HH
-#define HB_OT_SHAPE_COMPLEX_HH
-
-#include "hb.hh"
-
-#include "hb-ot-layout.hh"
-#include "hb-ot-shape.hh"
-#include "hb-ot-shape-normalize.hh"
-
-
-/* buffer var allocations, used by complex shapers */
-#define complex_var_u8_category() var2.u8[2]
-#define complex_var_u8_auxiliary() var2.u8[3]
-
-
-#define HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS 32
-
-enum hb_ot_shape_zero_width_marks_type_t {
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
- HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
-};
-
-
-/* Master OT shaper list */
-#define HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS \
- HB_COMPLEX_SHAPER_IMPLEMENT (arabic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (default) \
- HB_COMPLEX_SHAPER_IMPLEMENT (dumber) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hangul) \
- HB_COMPLEX_SHAPER_IMPLEMENT (hebrew) \
- HB_COMPLEX_SHAPER_IMPLEMENT (indic) \
- HB_COMPLEX_SHAPER_IMPLEMENT (khmer) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar) \
- HB_COMPLEX_SHAPER_IMPLEMENT (myanmar_zawgyi) \
- HB_COMPLEX_SHAPER_IMPLEMENT (thai) \
- HB_COMPLEX_SHAPER_IMPLEMENT (use) \
- /* ^--- Add new shapers here; keep sorted. */
-
-
-struct hb_ot_complex_shaper_t
-{
- /* collect_features()
- * Called during shape_plan().
- * Shapers should use plan->map to add their features and callbacks.
- * May be NULL.
- */
- void (*collect_features) (hb_ot_shape_planner_t *plan);
-
- /* override_features()
- * Called during shape_plan().
- * Shapers should use plan->map to override features and add callbacks after
- * common features are added.
- * May be NULL.
- */
- void (*override_features) (hb_ot_shape_planner_t *plan);
-
-
- /* data_create()
- * Called at the end of shape_plan().
- * Whatever shapers return will be accessible through plan->data later.
- * If nullptr is returned, means a plan failure.
- */
- void *(*data_create) (const hb_ot_shape_plan_t *plan);
-
- /* data_destroy()
- * Called when the shape_plan is being destroyed.
- * plan->data is passed here for destruction.
- * If nullptr is returned, means a plan failure.
- * May be NULL.
- */
- void (*data_destroy) (void *data);
-
-
- /* preprocess_text()
- * Called during shape().
- * Shapers can use to modify text before shaping starts.
- * May be NULL.
- */
- void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font);
-
- /* postprocess_glyphs()
- * Called during shape().
- * Shapers can use to modify glyphs after shaping ends.
- * May be NULL.
- */
- void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font);
-
-
- hb_ot_shape_normalization_mode_t normalization_preference;
-
- /* decompose()
- * Called during shape()'s normalization.
- * May be NULL.
- */
- bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t ab,
- hb_codepoint_t *a,
- hb_codepoint_t *b);
-
- /* compose()
- * Called during shape()'s normalization.
- * May be NULL.
- */
- bool (*compose) (const hb_ot_shape_normalize_context_t *c,
- hb_codepoint_t a,
- hb_codepoint_t b,
- hb_codepoint_t *ab);
-
- /* setup_masks()
- * Called during shape().
- * Shapers should use map to get feature masks and set on buffer.
- * Shapers may NOT modify characters.
- * May be NULL.
- */
- void (*setup_masks) (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- hb_font_t *font);
-
- /* gpos_tag()
- * If not HB_TAG_NONE, then must match found GPOS script tag for
- * GPOS to be applied. Otherwise, fallback positioning will be used.
- */
- hb_tag_t gpos_tag;
-
- /* reorder_marks()
- * Called during shape().
- * Shapers can use to modify ordering of combining marks.
- * May be NULL.
- */
- void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
- hb_buffer_t *buffer,
- unsigned int start,
- unsigned int end);
-
- hb_ot_shape_zero_width_marks_type_t zero_width_marks;
-
- bool fallback_position;
-};
-
-#define HB_COMPLEX_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_complex_shaper_t _hb_ot_complex_shaper_##name;
-HB_COMPLEX_SHAPERS_IMPLEMENT_SHAPERS
-#undef HB_COMPLEX_SHAPER_IMPLEMENT
-
-
-static inline const hb_ot_complex_shaper_t *
-hb_ot_shape_complex_categorize (const hb_ot_shape_planner_t *planner)
-{
- switch ((hb_tag_t) planner->props.script)
- {
- default:
- return &_hb_ot_complex_shaper_default;
-
-
- /* Unicode-1.1 additions */
- case HB_SCRIPT_ARABIC:
-
- /* Unicode-3.0 additions */
- case HB_SCRIPT_SYRIAC:
-
- /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
- * This is because we do fallback shaping for Arabic script (and not others).
- * But note that Arabic shaping is applicable only to horizontal layout; for
- * vertical text, just use the generic shaper instead. */
- if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
- planner->props.script == HB_SCRIPT_ARABIC) &&
- HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
- return &_hb_ot_complex_shaper_arabic;
- else
- return &_hb_ot_complex_shaper_default;
-
-
- /* Unicode-1.1 additions */
- case HB_SCRIPT_THAI:
- case HB_SCRIPT_LAO:
-
- return &_hb_ot_complex_shaper_thai;
-
-
- /* Unicode-1.1 additions */
- case HB_SCRIPT_HANGUL:
-
- return &_hb_ot_complex_shaper_hangul;
-
-
- /* Unicode-1.1 additions */
- case HB_SCRIPT_HEBREW:
-
- return &_hb_ot_complex_shaper_hebrew;
-
-
- /* Unicode-1.1 additions */
- case HB_SCRIPT_BENGALI:
- case HB_SCRIPT_DEVANAGARI:
- case HB_SCRIPT_GUJARATI:
- case HB_SCRIPT_GURMUKHI:
- case HB_SCRIPT_KANNADA:
- case HB_SCRIPT_MALAYALAM:
- case HB_SCRIPT_ORIYA:
- case HB_SCRIPT_TAMIL:
- case HB_SCRIPT_TELUGU:
-
- /* Unicode-3.0 additions */
- case HB_SCRIPT_SINHALA:
-
- /* If the designer designed the font for the 'DFLT' script,
- * (or we ended up arbitrarily pick 'latn'), use the default shaper.
- * Otherwise, use the specific shaper.
- *
- * If it's indy3 tag, send to USE. */
- if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
- planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
- else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
- return &_hb_ot_complex_shaper_use;
- else
- return &_hb_ot_complex_shaper_indic;
-
- case HB_SCRIPT_KHMER:
- return &_hb_ot_complex_shaper_khmer;
-
- case HB_SCRIPT_MYANMAR:
- /* If the designer designed the font for the 'DFLT' script,
- * (or we ended up arbitrarily pick 'latn'), use the default shaper.
- * Otherwise, use the specific shaper.
- *
- * If designer designed for 'mymr' tag, also send to default
- * shaper. That's tag used from before Myanmar shaping spec
- * was developed. The shaping spec uses 'mym2' tag. */
- if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
- planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
- planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
- return &_hb_ot_complex_shaper_default;
- else
- return &_hb_ot_complex_shaper_myanmar;
-
-
-#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
- case HB_SCRIPT_MYANMAR_ZAWGYI:
- /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
-
- return &_hb_ot_complex_shaper_myanmar_zawgyi;
-
-
- /* Unicode-2.0 additions */
- case HB_SCRIPT_TIBETAN:
-
- /* Unicode-3.0 additions */
- case HB_SCRIPT_MONGOLIAN:
- //case HB_SCRIPT_SINHALA:
-
- /* Unicode-3.2 additions */
- case HB_SCRIPT_BUHID:
- case HB_SCRIPT_HANUNOO:
- case HB_SCRIPT_TAGALOG:
- case HB_SCRIPT_TAGBANWA:
-
- /* Unicode-4.0 additions */
- case HB_SCRIPT_LIMBU:
- case HB_SCRIPT_TAI_LE:
-
- /* Unicode-4.1 additions */
- case HB_SCRIPT_BUGINESE:
- case HB_SCRIPT_KHAROSHTHI:
- case HB_SCRIPT_SYLOTI_NAGRI:
- case HB_SCRIPT_TIFINAGH:
-
- /* Unicode-5.0 additions */
- case HB_SCRIPT_BALINESE:
- case HB_SCRIPT_NKO:
- case HB_SCRIPT_PHAGS_PA:
-
- /* Unicode-5.1 additions */
- case HB_SCRIPT_CHAM:
- case HB_SCRIPT_KAYAH_LI:
- case HB_SCRIPT_LEPCHA:
- case HB_SCRIPT_REJANG:
- case HB_SCRIPT_SAURASHTRA:
- case HB_SCRIPT_SUNDANESE:
-
- /* Unicode-5.2 additions */
- case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
- case HB_SCRIPT_JAVANESE:
- case HB_SCRIPT_KAITHI:
- case HB_SCRIPT_MEETEI_MAYEK:
- case HB_SCRIPT_TAI_THAM:
- case HB_SCRIPT_TAI_VIET:
-
- /* Unicode-6.0 additions */
- case HB_SCRIPT_BATAK:
- case HB_SCRIPT_BRAHMI:
- case HB_SCRIPT_MANDAIC:
-
- /* Unicode-6.1 additions */
- case HB_SCRIPT_CHAKMA:
- case HB_SCRIPT_MIAO:
- case HB_SCRIPT_SHARADA:
- case HB_SCRIPT_TAKRI:
-
- /* Unicode-7.0 additions */
- case HB_SCRIPT_DUPLOYAN:
- case HB_SCRIPT_GRANTHA:
- case HB_SCRIPT_KHOJKI:
- case HB_SCRIPT_KHUDAWADI:
- case HB_SCRIPT_MAHAJANI:
- case HB_SCRIPT_MANICHAEAN:
- case HB_SCRIPT_MODI:
- case HB_SCRIPT_PAHAWH_HMONG:
- case HB_SCRIPT_PSALTER_PAHLAVI:
- case HB_SCRIPT_SIDDHAM:
- case HB_SCRIPT_TIRHUTA:
-
- /* Unicode-8.0 additions */
- case HB_SCRIPT_AHOM:
- case HB_SCRIPT_MULTANI:
-
- /* Unicode-9.0 additions */
- case HB_SCRIPT_ADLAM:
- case HB_SCRIPT_BHAIKSUKI:
- case HB_SCRIPT_MARCHEN:
- case HB_SCRIPT_NEWA:
-
- /* Unicode-10.0 additions */
- case HB_SCRIPT_MASARAM_GONDI:
- case HB_SCRIPT_SOYOMBO:
- case HB_SCRIPT_ZANABAZAR_SQUARE:
-
- /* Unicode-11.0 additions */
- case HB_SCRIPT_DOGRA:
- case HB_SCRIPT_GUNJALA_GONDI:
- case HB_SCRIPT_HANIFI_ROHINGYA:
- case HB_SCRIPT_MAKASAR:
- case HB_SCRIPT_MEDEFAIDRIN:
- case HB_SCRIPT_OLD_SOGDIAN:
- case HB_SCRIPT_SOGDIAN:
-
- /* Unicode-12.0 additions */
- case HB_SCRIPT_ELYMAIC:
- case HB_SCRIPT_NANDINAGARI:
- case HB_SCRIPT_NYIAKENG_PUACHUE_HMONG:
- case HB_SCRIPT_WANCHO:
-
- /* Unicode-13.0 additions */
- case HB_SCRIPT_CHORASMIAN:
- case HB_SCRIPT_DIVES_AKURU:
- case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
- case HB_SCRIPT_YEZIDI:
-
- /* Unicode-14.0 additions */
- case HB_SCRIPT_CYPRO_MINOAN:
- case HB_SCRIPT_OLD_UYGHUR:
- case HB_SCRIPT_TANGSA:
- case HB_SCRIPT_TOTO:
- case HB_SCRIPT_VITHKUQI:
-
- /* If the designer designed the font for the 'DFLT' script,
- * (or we ended up arbitrarily pick 'latn'), use the default shaper.
- * Otherwise, use the specific shaper.
- * Note that for some simple scripts, there may not be *any*
- * GSUB/GPOS needed, so there may be no scripts found! */
- if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
- planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
- return &_hb_ot_complex_shaper_default;
- else
- return &_hb_ot_complex_shaper_use;
- }
-}
-
-
-#endif /* HB_OT_SHAPE_COMPLEX_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
index 671f30327f..b2eedb027b 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-fallback.cc
@@ -497,14 +497,14 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan,
#endif
#ifndef HB_DISABLE_DEPRECATED
- if (!buffer->message (font, "start fallback kern"))
- return;
-
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction) ?
!font->has_glyph_h_kerning_func () :
!font->has_glyph_v_kerning_func ())
return;
+ if (!buffer->message (font, "start fallback kern"))
+ return;
+
bool reverse = HB_DIRECTION_IS_BACKWARD (buffer->props.direction);
if (reverse)
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
index aa5a8eeaa3..7db0b25b73 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape-normalize.cc
@@ -29,7 +29,7 @@
#ifndef HB_NO_OT_SHAPE
#include "hb-ot-shape-normalize.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape.hh"
@@ -69,7 +69,7 @@
* - When a font does not support a character but supports its canonical
* decomposition, well, use the decomposition.
*
- * - The complex shapers can customize the compose and decompose functions to
+ * - The shapers can customize the compose and decompose functions to
* offload some of their requirements to the normalizer. For example, the
* Indic shaper may want to disallow recomposing of two matras.
*/
@@ -143,8 +143,7 @@ decompose (const hb_ot_shape_normalize_context_t *c, bool shortest, hb_codepoint
return 1;
}
- unsigned int ret;
- if ((ret = decompose (c, shortest, a))) {
+ if (unsigned ret = decompose (c, shortest, a)) {
if (b) {
output_char (buffer, b, b_glyph);
return ret + 1;
@@ -223,7 +222,7 @@ handle_variation_selector_cluster (const hb_ot_shape_normalize_context_t *c,
unsigned int end,
bool short_circuit HB_UNUSED)
{
- /* TODO Currently if there's a variation-selector we give-up, it's just too hard. */
+ /* Currently if there's a variation-selector we give-up on normalization, it's just too hard. */
hb_buffer_t * const buffer = c->buffer;
hb_font_t * const font = c->font;
for (; buffer->idx < end - 1 && buffer->successful;) {
@@ -395,7 +394,7 @@ _hb_ot_shape_normalize (const hb_ot_shape_plan_t *plan,
break;
/* We are going to do a O(n^2). Only do this if the sequence is short. */
- if (end - i > HB_OT_SHAPE_COMPLEX_MAX_COMBINING_MARKS) {
+ if (end - i > HB_OT_SHAPE_MAX_COMBINING_MARKS) {
i = end;
continue;
}
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.cc b/thirdparty/harfbuzz/src/hb-ot-shape.cc
index 4bd8aaf03b..7f679cfd39 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.cc
@@ -37,7 +37,7 @@
#include "hb-shaper-impl.hh"
#include "hb-ot-shape.hh"
-#include "hb-ot-shape-complex.hh"
+#include "hb-ot-shaper.hh"
#include "hb-ot-shape-fallback.hh"
#include "hb-ot-shape-normalize.hh"
@@ -47,14 +47,17 @@
#include "hb-aat-layout.hh"
+static inline bool
+_hb_codepoint_is_regional_indicator (hb_codepoint_t u)
+{ return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); }
#ifndef HB_NO_AAT_SHAPE
static inline bool
-_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props)
+_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props)
{
/* https://github.com/harfbuzz/harfbuzz/issues/2124 */
return hb_aat_layout_has_substitution (face) &&
- (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face));
+ (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face));
}
#endif
@@ -74,23 +77,23 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
unsigned int num_user_features);
hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face,
- const hb_segment_properties_t *props) :
+ const hb_segment_properties_t &props) :
face (face),
- props (*props),
+ props (props),
map (face, props),
aat_map (face, props)
#ifndef HB_NO_AAT_SHAPE
, apply_morx (_hb_apply_morx (face, props))
#endif
{
- shaper = hb_ot_shape_complex_categorize (this);
+ shaper = hb_ot_shaper_categorize (this);
script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE;
script_fallback_mark_positioning = shaper->fallback_position;
/* https://github.com/harfbuzz/harfbuzz/issues/1528 */
- if (apply_morx && shaper != &_hb_ot_complex_shaper_default)
- shaper = &_hb_ot_complex_shaper_dumber;
+ if (apply_morx && shaper != &_hb_ot_shaper_default)
+ shaper = &_hb_ot_shaper_dumber;
}
void
@@ -222,7 +225,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face,
#endif
hb_ot_shape_planner_t planner (face,
- &key->props);
+ key->props);
hb_ot_shape_collect_features (&planner,
key->user_features,
@@ -504,9 +507,9 @@ hb_set_unicode_props (hb_buffer_t *buffer)
}
/* Regional_Indicators are hairy as hell...
* https://github.com/harfbuzz/harfbuzz/issues/2265 */
- else if (unlikely (i && hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F1E6u, 0x1F1FFu)))
+ else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint)))
{
- if (hb_in_range<hb_codepoint_t> (info[i - 1].codepoint, 0x1F1E6u, 0x1F1FFu) &&
+ if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) &&
!_hb_glyph_info_is_continuation (&info[i - 1]))
_hb_glyph_info_set_continuation (&info[i]);
}
@@ -598,24 +601,33 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
* direction, so that features like ligatures will work as intended.
*
* https://github.com/harfbuzz/harfbuzz/issues/501
+ *
+ * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common.
+ * If they are present in a run of natively-RTL text, they get assigned a script
+ * with natively RTL direction, which would result in wrong shaping if we
+ * assign such native RTL direction to them then. Detect that as well.
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/3314
*/
if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR))
{
- bool found_number = false, found_letter = false;
+ bool found_number = false, found_letter = false, found_ri = false;
const auto* info = buffer->info;
const auto count = buffer->len;
for (unsigned i = 0; i < count; i++)
{
auto gc = _hb_glyph_info_get_general_category (&info[i]);
if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
- found_number = true;
+ found_number = true;
else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc))
{
- found_letter = true;
- break;
+ found_letter = true;
+ break;
}
+ else if (_hb_codepoint_is_regional_indicator (info[i].codepoint))
+ found_ri = true;
}
- if (found_number && !found_letter)
+ if ((found_number || found_ri) && !found_letter)
horiz_dir = HB_DIRECTION_LTR;
}
@@ -915,7 +927,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
+hb_ot_substitute_plan (const hb_ot_shape_context_t *c)
{
hb_buffer_t *buffer = c->buffer;
@@ -934,18 +946,24 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
_hb_buffer_allocate_gsubgpos_vars (c->buffer);
- hb_ot_substitute_complex (c);
+ hb_ot_substitute_plan (c);
+
+#ifndef HB_NO_AAT_SHAPE
+ if (c->plan->apply_morx && c->plan->apply_gpos)
+ hb_aat_layout_remove_deleted_glyphs (c->buffer);
+#endif
}
static inline void
hb_ot_substitute_post (const hb_ot_shape_context_t *c)
{
- hb_ot_hide_default_ignorables (c->buffer, c->font);
#ifndef HB_NO_AAT_SHAPE
- if (c->plan->apply_morx)
+ if (c->plan->apply_morx && !c->plan->apply_gpos)
hb_aat_layout_remove_deleted_glyphs (c->buffer);
#endif
+ hb_ot_hide_default_ignorables (c->buffer, c->font);
+
if (c->plan->shaper->postprocess_glyphs &&
c->buffer->message(c->font, "start postprocess-glyphs")) {
c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
@@ -1021,7 +1039,7 @@ hb_ot_position_default (const hb_ot_shape_context_t *c)
}
static inline void
-hb_ot_position_complex (const hb_ot_shape_context_t *c)
+hb_ot_position_plan (const hb_ot_shape_context_t *c)
{
unsigned int count = c->buffer->len;
hb_glyph_info_t *info = c->buffer->info;
@@ -1106,7 +1124,7 @@ hb_ot_position (const hb_ot_shape_context_t *c)
hb_ot_position_default (c);
- hb_ot_position_complex (c);
+ hb_ot_position_plan (c);
if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
hb_buffer_reverse (c->buffer);
@@ -1123,6 +1141,18 @@ hb_propagate_flags (hb_buffer_t *buffer)
if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
return;
+ /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things:
+ *
+ * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL,
+ * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL,
+ * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK.
+ *
+ * We couldn't make this interaction earlier. It has to be done here.
+ */
+ bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
+
+ bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0;
+
hb_glyph_info_t *info = buffer->info;
foreach_cluster (buffer, start, end)
@@ -1130,9 +1160,20 @@ hb_propagate_flags (hb_buffer_t *buffer)
unsigned int mask = 0;
for (unsigned int i = start; i < end; i++)
mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED;
- if (mask)
- for (unsigned int i = start; i < end; i++)
- info[i].mask |= mask;
+
+ if (flip_tatweel)
+ {
+ if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
+ mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL;
+ if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL)
+ mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+ }
+
+ if (clear_concat)
+ mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT;
+
+ for (unsigned int i = start; i < end; i++)
+ info[i].mask = mask;
}
}
@@ -1141,8 +1182,6 @@ hb_propagate_flags (hb_buffer_t *buffer)
static void
hb_ot_shape_internal (hb_ot_shape_context_t *c)
{
- c->buffer->enter ();
-
/* Save the original direction, we use it later. */
c->target_direction = c->buffer->props.direction;
diff --git a/thirdparty/harfbuzz/src/hb-ot-shape.hh b/thirdparty/harfbuzz/src/hb-ot-shape.hh
index e8c81015c7..cd6f15cbe2 100644
--- a/thirdparty/harfbuzz/src/hb-ot-shape.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-shape.hh
@@ -60,8 +60,10 @@ struct hb_shape_plan_key_t;
struct hb_ot_shape_plan_t
{
+ ~hb_ot_shape_plan_t () { fini (); }
+
hb_segment_properties_t props;
- const struct hb_ot_complex_shaper_t *shaper;
+ const struct hb_ot_shaper_t *shaper;
hb_ot_map_t map;
hb_aat_map_t aat_map;
const void *data;
@@ -158,10 +160,10 @@ struct hb_ot_shape_planner_t
#endif
bool script_zero_marks : 1;
bool script_fallback_mark_positioning : 1;
- const struct hb_ot_complex_shaper_t *shaper;
+ const struct hb_ot_shaper_t *shaper;
HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face,
- const hb_segment_properties_t *props);
+ const hb_segment_properties_t &props);
HB_INTERNAL void compile (hb_ot_shape_plan_t &plan,
const hb_ot_shape_plan_key_t &key);
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh
new file mode 100644
index 0000000000..b9f92f72d6
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-fallback.hh
@@ -0,0 +1,376 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_FALLBACK_HH
+#define HB_OT_SHAPER_ARABIC_FALLBACK_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shape.hh"
+#include "hb-ot-layout-gsub-table.hh"
+
+
+/* Features ordered the same as the entries in shaping_table rows,
+ * followed by rlig. Don't change.
+ *
+ * We currently support one subtable per lookup, and one lookup
+ * per feature. But we allow duplicate features, so we use that!
+ */
+static const hb_tag_t arabic_fallback_features[] =
+{
+ HB_TAG('i','n','i','t'),
+ HB_TAG('m','e','d','i'),
+ HB_TAG('f','i','n','a'),
+ HB_TAG('i','s','o','l'),
+ HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
+ HB_TAG('r','l','i','g'),
+};
+
+static OT::SubstLookup *
+arabic_fallback_synthesize_lookup_single (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font,
+ unsigned int feature_index)
+{
+ OT::HBGlyphID16 glyphs[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
+ OT::HBGlyphID16 substitutes[SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1];
+ unsigned int num_glyphs = 0;
+
+ /* Populate arrays */
+ for (hb_codepoint_t u = SHAPING_TABLE_FIRST; u < SHAPING_TABLE_LAST + 1; u++)
+ {
+ hb_codepoint_t s = shaping_table[u - SHAPING_TABLE_FIRST][feature_index];
+ hb_codepoint_t u_glyph, s_glyph;
+
+ if (!s ||
+ !hb_font_get_glyph (font, u, 0, &u_glyph) ||
+ !hb_font_get_glyph (font, s, 0, &s_glyph) ||
+ u_glyph == s_glyph ||
+ u_glyph > 0xFFFFu || s_glyph > 0xFFFFu)
+ continue;
+
+ glyphs[num_glyphs] = u_glyph;
+ substitutes[num_glyphs] = s_glyph;
+
+ num_glyphs++;
+ }
+
+ if (!num_glyphs)
+ return nullptr;
+
+ /* Bubble-sort or something equally good!
+ * May not be good-enough for presidential candidate interviews, but good-enough for us... */
+ hb_stable_sort (&glyphs[0], num_glyphs,
+ (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
+ &substitutes[0]);
+
+
+ /* Each glyph takes four bytes max, and there's some overhead. */
+ char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
+ hb_serialize_context_t c (buf, sizeof (buf));
+ OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
+ bool ret = lookup->serialize_single (&c,
+ OT::LookupFlag::IgnoreMarks,
+ hb_sorted_array (glyphs, num_glyphs),
+ hb_array (substitutes, num_glyphs));
+ c.end_serialize ();
+
+ return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
+}
+
+template <typename T>
+static OT::SubstLookup *
+arabic_fallback_synthesize_lookup_ligature (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font,
+ const T &ligature_table,
+ unsigned lookup_flags)
+{
+ OT::HBGlyphID16 first_glyphs[ARRAY_LENGTH_CONST (ligature_table)];
+ unsigned int first_glyphs_indirection[ARRAY_LENGTH_CONST (ligature_table)];
+ unsigned int ligature_per_first_glyph_count_list[ARRAY_LENGTH_CONST (first_glyphs)];
+ unsigned int num_first_glyphs = 0;
+
+ /* We know that all our ligatures have the same number of components. */
+ OT::HBGlyphID16 ligature_list[ARRAY_LENGTH_CONST (first_glyphs) * ARRAY_LENGTH_CONST(ligature_table[0].ligatures)];
+ unsigned int component_count_list[ARRAY_LENGTH_CONST (ligature_list)];
+ OT::HBGlyphID16 component_list[ARRAY_LENGTH_CONST (ligature_list) *
+ ARRAY_LENGTH_CONST (ligature_table[0].ligatures[0].components)];
+ unsigned int num_ligatures = 0;
+ unsigned int num_components = 0;
+
+ /* Populate arrays */
+
+ /* Sort out the first-glyphs */
+ for (unsigned int first_glyph_idx = 0; first_glyph_idx < ARRAY_LENGTH (first_glyphs); first_glyph_idx++)
+ {
+ hb_codepoint_t first_u = ligature_table[first_glyph_idx].first;
+ hb_codepoint_t first_glyph;
+ if (!hb_font_get_glyph (font, first_u, 0, &first_glyph))
+ continue;
+ first_glyphs[num_first_glyphs] = first_glyph;
+ ligature_per_first_glyph_count_list[num_first_glyphs] = 0;
+ first_glyphs_indirection[num_first_glyphs] = first_glyph_idx;
+ num_first_glyphs++;
+ }
+ hb_stable_sort (&first_glyphs[0], num_first_glyphs,
+ (int(*)(const OT::HBUINT16*, const OT::HBUINT16 *)) OT::HBGlyphID16::cmp,
+ &first_glyphs_indirection[0]);
+
+ /* Now that the first-glyphs are sorted, walk again, populate ligatures. */
+ for (unsigned int i = 0; i < num_first_glyphs; i++)
+ {
+ unsigned int first_glyph_idx = first_glyphs_indirection[i];
+
+ for (unsigned int ligature_idx = 0; ligature_idx < ARRAY_LENGTH (ligature_table[0].ligatures); ligature_idx++)
+ {
+ hb_codepoint_t ligature_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].ligature;
+ hb_codepoint_t ligature_glyph;
+ if (!hb_font_get_glyph (font, ligature_u, 0, &ligature_glyph))
+ continue;
+
+ const auto &components = ligature_table[first_glyph_idx].ligatures[ligature_idx].components;
+ unsigned component_count = ARRAY_LENGTH_CONST (components);
+
+ for (unsigned i = 0; i < component_count; i++)
+ {
+ hb_codepoint_t component_u = ligature_table[first_glyph_idx].ligatures[ligature_idx].components[i];
+ hb_codepoint_t component_glyph;
+ if (!component_u ||
+ !hb_font_get_glyph (font, component_u, 0, &component_glyph))
+ continue;
+
+ component_list[num_components++] = component_glyph;
+ }
+
+ component_count_list[num_ligatures] = 1 + component_count;
+ ligature_list[num_ligatures] = ligature_glyph;
+
+ ligature_per_first_glyph_count_list[i]++;
+
+ num_ligatures++;
+ }
+ }
+
+ if (!num_ligatures)
+ return nullptr;
+
+
+ /* 16 bytes per ligature ought to be enough... */
+ char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
+ hb_serialize_context_t c (buf, sizeof (buf));
+ OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
+ bool ret = lookup->serialize_ligature (&c,
+ lookup_flags,
+ hb_sorted_array (first_glyphs, num_first_glyphs),
+ hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
+ hb_array (ligature_list, num_ligatures),
+ hb_array (component_count_list, num_ligatures),
+ hb_array (component_list, num_components));
+ c.end_serialize ();
+
+ return ret && !c.in_error () ? c.copy<OT::SubstLookup> () : nullptr;
+}
+
+static OT::SubstLookup *
+arabic_fallback_synthesize_lookup (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ unsigned int feature_index)
+{
+ if (feature_index < 4)
+ return arabic_fallback_synthesize_lookup_single (plan, font, feature_index);
+ else
+ {
+ switch (feature_index) {
+ case 4: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_3_table, OT::LookupFlag::IgnoreMarks);
+ case 5: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_table, OT::LookupFlag::IgnoreMarks);
+ case 6: return arabic_fallback_synthesize_lookup_ligature (plan, font, ligature_mark_table, 0);
+ }
+ }
+ assert (false);
+ return nullptr;
+}
+
+#define ARABIC_FALLBACK_MAX_LOOKUPS ARRAY_LENGTH_CONST (arabic_fallback_features)
+
+struct arabic_fallback_plan_t
+{
+ unsigned int num_lookups;
+ bool free_lookups;
+
+ hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+ OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+ OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
+};
+
+#if defined(_WIN32) && !defined(HB_NO_WIN1256)
+#define HB_WITH_WIN1256
+#endif
+
+#ifdef HB_WITH_WIN1256
+#include "hb-ot-shaper-arabic-win1256.hh"
+#endif
+
+struct ManifestLookup
+{
+ public:
+ OT::Tag tag;
+ OT::Offset16To<OT::SubstLookup> lookupOffset;
+ public:
+ DEFINE_SIZE_STATIC (6);
+};
+typedef OT::Array16Of<ManifestLookup> Manifest;
+
+static bool
+arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUSED,
+ const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED)
+{
+#ifdef HB_WITH_WIN1256
+ /* Does this font look like it's Windows-1256-encoded? */
+ hb_codepoint_t g;
+ if (!(hb_font_get_glyph (font, 0x0627u, 0, &g) && g == 199 /* ALEF */ &&
+ hb_font_get_glyph (font, 0x0644u, 0, &g) && g == 225 /* LAM */ &&
+ hb_font_get_glyph (font, 0x0649u, 0, &g) && g == 236 /* ALEF MAKSURA */ &&
+ hb_font_get_glyph (font, 0x064Au, 0, &g) && g == 237 /* YEH */ &&
+ hb_font_get_glyph (font, 0x0652u, 0, &g) && g == 250 /* SUKUN */))
+ return false;
+
+ const Manifest &manifest = reinterpret_cast<const Manifest&> (arabic_win1256_gsub_lookups.manifest);
+ static_assert (sizeof (arabic_win1256_gsub_lookups.manifestData) <=
+ ARABIC_FALLBACK_MAX_LOOKUPS * sizeof (ManifestLookup), "");
+
+ unsigned j = 0;
+ unsigned int count = manifest.len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ fallback_plan->mask_array[j] = plan->map.get_1_mask (manifest[i].tag);
+ if (fallback_plan->mask_array[j])
+ {
+ fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
+ if (fallback_plan->lookup_array[j])
+ {
+ fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+ j++;
+ }
+ }
+ }
+
+ fallback_plan->num_lookups = j;
+ fallback_plan->free_lookups = false;
+
+ return j > 0;
+#else
+ return false;
+#endif
+}
+
+static bool
+arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
+ const hb_ot_shape_plan_t *plan,
+ hb_font_t *font)
+{
+ static_assert ((ARRAY_LENGTH_CONST (arabic_fallback_features) <= ARABIC_FALLBACK_MAX_LOOKUPS), "");
+ unsigned int j = 0;
+ for (unsigned int i = 0; i < ARRAY_LENGTH(arabic_fallback_features) ; i++)
+ {
+ fallback_plan->mask_array[j] = plan->map.get_1_mask (arabic_fallback_features[i]);
+ if (fallback_plan->mask_array[j])
+ {
+ fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
+ if (fallback_plan->lookup_array[j])
+ {
+ fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
+ j++;
+ }
+ }
+ }
+
+ fallback_plan->num_lookups = j;
+ fallback_plan->free_lookups = true;
+
+ return j > 0;
+}
+
+static arabic_fallback_plan_t *
+arabic_fallback_plan_create (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font)
+{
+ arabic_fallback_plan_t *fallback_plan = (arabic_fallback_plan_t *) hb_calloc (1, sizeof (arabic_fallback_plan_t));
+ if (unlikely (!fallback_plan))
+ return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
+
+ fallback_plan->num_lookups = 0;
+ fallback_plan->free_lookups = false;
+
+ /* Try synthesizing GSUB table using Unicode Arabic Presentation Forms,
+ * in case the font has cmap entries for the presentation-forms characters. */
+ if (arabic_fallback_plan_init_unicode (fallback_plan, plan, font))
+ return fallback_plan;
+
+ /* See if this looks like a Windows-1256-encoded font. If it does, use a
+ * hand-coded GSUB table. */
+ if (arabic_fallback_plan_init_win1256 (fallback_plan, plan, font))
+ return fallback_plan;
+
+ assert (fallback_plan->num_lookups == 0);
+ hb_free (fallback_plan);
+ return const_cast<arabic_fallback_plan_t *> (&Null (arabic_fallback_plan_t));
+}
+
+static void
+arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
+{
+ if (!fallback_plan || fallback_plan->num_lookups == 0)
+ return;
+
+ for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
+ if (fallback_plan->lookup_array[i])
+ {
+ fallback_plan->accel_array[i].fini ();
+ if (fallback_plan->free_lookups)
+ hb_free (fallback_plan->lookup_array[i]);
+ }
+
+ hb_free (fallback_plan);
+}
+
+static void
+arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ OT::hb_ot_apply_context_t c (0, font, buffer);
+ for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
+ if (fallback_plan->lookup_array[i]) {
+ c.set_lookup_mask (fallback_plan->mask_array[i]);
+ hb_ot_layout_substitute_lookup (&c,
+ *fallback_plan->lookup_array[i],
+ fallback_plan->accel_array[i]);
+ }
+}
+
+
+#endif /* HB_OT_SHAPER_ARABIC_FALLBACK_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh
new file mode 100644
index 0000000000..a5ce3a6c93
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-joining-list.hh
@@ -0,0 +1,47 @@
+/* == Start of generated function == */
+/*
+ * The following function is generated by running:
+ *
+ * ./gen-arabic-joining-list.py ArabicShaping.txt Scripts.txt
+ *
+ * on files with these headers:
+ *
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
+#define HB_OT_SHAPER_ARABIC_JOINING_LIST_HH
+
+static bool
+has_arabic_joining (hb_script_t script)
+{
+ /* List of scripts that have data in arabic-table. */
+ switch ((int) script)
+ {
+ case HB_SCRIPT_ADLAM:
+ case HB_SCRIPT_ARABIC:
+ case HB_SCRIPT_CHORASMIAN:
+ case HB_SCRIPT_HANIFI_ROHINGYA:
+ case HB_SCRIPT_MANDAIC:
+ case HB_SCRIPT_MANICHAEAN:
+ case HB_SCRIPT_MONGOLIAN:
+ case HB_SCRIPT_NKO:
+ case HB_SCRIPT_OLD_UYGHUR:
+ case HB_SCRIPT_PHAGS_PA:
+ case HB_SCRIPT_PSALTER_PAHLAVI:
+ case HB_SCRIPT_SOGDIAN:
+ case HB_SCRIPT_SYRIAC:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+
+#endif /* HB_OT_SHAPER_ARABIC_JOINING_LIST_HH */
+
+/* == End of generated function == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh
new file mode 100644
index 0000000000..ba86772f84
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-pua.hh
@@ -0,0 +1,118 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-arabic-pua.py
+ *
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_PUA_HH
+#define HB_OT_SHAPER_ARABIC_PUA_HH
+
+static const uint8_t
+_hb_arabic_u8[464] =
+{
+ 84, 86, 85, 85, 85, 85, 85,213, 16, 34, 34, 34, 34, 34, 35, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 36, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 82, 16, 0, 0, 0, 0, 1, 2, 3, 4,
+ 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 7,
+ 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 0, 0, 0, 22, 0, 23, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 16, 34, 34, 34, 35, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 66, 16, 50, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68,101, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 71, 68, 68, 68, 68, 68, 68, 68,152,186, 76, 77, 68,254, 16, 50,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 5, 6,
+ 0, 0, 0, 0, 0, 0, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 10, 0,
+ 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 23, 23, 29, 30, 31, 32, 33, 0, 0, 0, 0,
+ 0, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 36, 37, 38, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 40,
+ 41, 42, 0, 43, 44, 0, 0, 45, 46, 0, 47, 48, 49, 0, 0, 0,
+ 0, 50, 0, 0, 51, 52, 0, 53, 54, 55, 56, 57, 58, 0, 0, 0,
+ 0, 0, 59, 60, 61, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 66,
+ 0, 0, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 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, 97, 98, 99,
+};
+static const uint16_t
+_hb_arabic_u16[720] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,61728,61729,61730, 0, 0,61733, 0, 0,
+ 61736,61737,61738,61739,61790,61741,61742,61743,61872,61873,61874,61875,61876,61877,61878,61879,
+ 61880,61881,61754,61755, 0,61757, 0,61759, 0, 0, 0,61787,61788,61789, 0, 0,
+ 0, 0, 0,61731, 0, 0, 0, 0, 0, 0, 0,61732, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,61734, 0, 0, 0, 0, 0, 0, 0,61735,
+ 0, 0, 0, 0,61740, 0, 0, 0, 0, 0, 0,61755, 0, 0, 0,61759,
+ 0,61869,61765,61763,61883,61767,61882,61761,61770,61865,61772,61774,61777,61780,61783,61784,
+ 61785,61786,61792,61794,61796,61798,61800,61801,61802,61806,61810,61696,61696,61696,61696,61696,
+ 61791,61813,61816,61818,61820,61822,61921,61860,61861,61868,61864,61895,61896,61899,61892,61893,
+ 61898,61897,61894,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696,61696, 0,
+ 61744,61745,61746,61747,61748,61749,61750,61751,61752,61753, 0,61790,61790, 0, 0, 0,
+ 0, 0, 0, 0,61708,61709,61710,61711,61756,61758, 0, 0, 0, 0, 0, 0,
+ 0,61765,61766,61763,61764,61883,61883,61767,61768,61882,61871,61870,61870,61761,61762,61770,
+ 61770,61769,61769,61865,61866,61772,61772,61771,61771,61774,61774,61773,61773,61777,61776,61775,
+ 61775,61780,61779,61778,61778,61783,61782,61781,61781,61784,61784,61785,61785,61786,61786,61792,
+ 61792,61794,61794,61793,61793,61796,61796,61795,61795,61798,61798,61797,61797,61800,61800,61799,
+ 61799,61801,61801,61801,61801,61802,61802,61802,61802,61806,61805,61803,61804,61810,61809,61807,
+ 61808,61813,61813,61811,61812,61816,61816,61814,61815,61818,61818,61817,61817,61820,61820,61819,
+ 61819,61822,61822,61821,61821,61921,61921,61823,61823,61860,61859,61857,61858,61861,61861,61868,
+ 61867,61864,61863,61862,61862,61888,61889,61886,61887,61890,61891,61885,61884, 0, 0, 0,
+ 0, 0, 0, 0,61984,61985,61986, 0, 0,61989, 0, 0,61992,61993,61994,61995,
+ 62046,61997,61998,61999, 0, 0,62010,62011, 0,62013, 0,62015, 0, 0, 0,62043,
+ 0,62045, 0, 0, 0, 0, 0,61987, 0, 0, 0,61988, 0, 0, 0,61990,
+ 0, 0, 0,61991,61996, 0, 0, 0, 0, 0, 0,62011, 0, 0, 0,62015,
+ 0,62165,62021,62019,62170,62023,62169,62017,62028,62161,62032,62036,62040,62048,62052,62053,
+ 62055,62057,62059,62064,62068,62072,62078,62114,62115,62122,62126,61952,61952,61952,61952,61952,
+ 62047,62130,62134,62138,62142,62146,62150,62154,62155,62164,62160,62183,62184,62187,62180,62181,
+ 62186,62185,62182,61952,61952,61952,61952, 0,62000,62001,62002,62003,62004,62005,62006,62007,
+ 62008,62009, 0,62046,62046, 0, 0, 0,61964,61965,61966,61967,62012,62014, 0, 0,
+ 61954, 0,61981, 0, 0, 0,61955, 0,61982, 0,61956, 0, 0, 0,62111, 0,
+ 0, 0, 0,61970,61971,61972,61957, 0,61980, 0, 0, 0, 0, 0,61958, 0,
+ 61983, 0, 0, 0, 0, 0,62191, 0,62188,62189,62192, 0, 0, 0,61973, 0,
+ 0,62098, 0, 0,61974, 0, 0,62099, 0, 0,62101, 0, 0,61975, 0, 0,
+ 62100, 0, 0, 0,62080,62081,62082,62102, 0,62083,62084,62085,62103, 0, 0, 0,
+ 62106, 0,62107, 0,62108, 0, 0, 0,61976, 0, 0, 0, 0,62086,62087,62088,
+ 62109,61978,62089,62090,62091,62110,62093,62094, 0,62104, 0, 0, 0, 0,62095,62096,
+ 62097,62105, 0, 0,61977, 0, 0, 0, 0, 0,62075,62077,61968, 0, 0, 0,
+ 0,62021,62022,62019,62020,62170,62171,62023,62024,62169,62168,62166,62167,62017,62018,62028,
+ 62027,62025,62026,62161,62162,62032,62031,62029,62030,62036,62035,62033,62034,62040,62039,62037,
+ 62038,62048,62044,62041,62042,62052,62051,62049,62050,62053,62054,62055,62056,62057,62058,62059,
+ 62060,62064,62063,62061,62062,62068,62067,62065,62066,62072,62071,62069,62070,62078,62076,62073,
+ 62074,62114,62113,62079,62193,62118,62117,62115,62116,62122,62121,62119,62120,62126,62125,62123,
+ 62124,62130,62129,62127,62128,62134,62133,62131,62132,62138,62137,62135,62136,62142,62141,62139,
+ 62140,62146,62145,62143,62144,62150,62149,62147,62148,62154,62153,62151,62152,62155,62156,62164,
+ 62163,62160,62159,62157,62158,62176,62177,62174,62175,62178,62179,62172,62173, 0, 0, 0,
+};
+
+static inline unsigned
+_hb_arabic_b2 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>2]>>((i&3u)<<1))&3u;
+}
+static inline unsigned
+_hb_arabic_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_simp_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[((_hb_arabic_u8[40+(((_hb_arabic_b4(8+_hb_arabic_u8,((_hb_arabic_b2(_hb_arabic_u8,u>>3>>4>>4))<<4)+((u>>3>>4)&15u)))<<4)+((u>>3)&15u))])<<3)+((u)&7u)]:0;
+}
+static inline uint_fast16_t
+_hb_arabic_pua_trad_map (unsigned u)
+{
+ return u<65277u?_hb_arabic_u16[320+(((_hb_arabic_u8[208+(((_hb_arabic_b4(168+_hb_arabic_u8,((_hb_arabic_b4(136+_hb_arabic_u8,u>>2>>4>>4))<<4)+((u>>2>>4)&15u)))<<4)+((u>>2)&15u))])<<2)+((u)&3u))]:0;
+}
+
+#endif /* HB_OT_SHAPER_ARABIC_PUA_HH */
+
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh
new file mode 100644
index 0000000000..fd3d8645d1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-table.hh
@@ -0,0 +1,556 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-arabic-table.py ArabicShaping.txt UnicodeData.txt Blocks.txt
+ *
+ * on files with these headers:
+ *
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * UnicodeData.txt does not have a header.
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_TABLE_HH
+#define HB_OT_SHAPER_ARABIC_TABLE_HH
+
+
+#define A JOINING_GROUP_ALAPH
+#define DR JOINING_GROUP_DALATH_RISH
+#define C JOINING_TYPE_C
+#define D JOINING_TYPE_D
+#define L JOINING_TYPE_L
+#define R JOINING_TYPE_R
+#define T JOINING_TYPE_T
+#define U JOINING_TYPE_U
+#define X JOINING_TYPE_X
+
+static const uint8_t joining_table[] =
+{
+
+#define joining_offset_0x0600u 0
+
+ /* Arabic */
+
+ /* 0600 */ U,U,U,U,U,U,X,X,U,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0620 */ D,U,R,R,R,R,D,R,D,R,D,D,D,D,D,R,R,R,R,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 0640 */ C,D,D,D,D,D,D,D,R,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0660 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,D,D,X,R,R,R,U,R,R,R,D,D,D,D,D,D,D,D,
+ /* 0680 */ D,D,D,D,D,D,D,D,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,D,D,D,D,D,D,
+ /* 06A0 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 06C0 */ R,D,D,R,R,R,R,R,R,R,R,R,D,R,D,R,D,D,R,R,X,R,X,X,X,X,X,X,X,U,X,X,
+ /* 06E0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,R,R,X,X,X,X,X,X,X,X,X,X,D,D,D,X,X,D,
+
+ /* Syriac */
+
+ /* 0700 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,T,A,X,D,D,D,DR,DR,R,R,R,D,D,D,D,R,D,
+ /* 0720 */ D,D,D,D,D,D,D,D,R,D,DR,D,R,D,D,DR,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0740 */ X,X,X,X,X,X,X,X,X,X,X,X,X,R,D,D,
+
+ /* Arabic Supplement */
+
+ /* 0740 */ D,D,D,D,D,D,D,D,D,R,R,R,D,D,D,D,
+ /* 0760 */ D,D,D,D,D,D,D,D,D,D,D,R,R,D,D,D,D,R,D,R,R,D,D,D,R,R,D,D,D,D,D,D,
+
+ /* FILLER */
+
+ /* 0780 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 07A0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* NKo */
+
+ /* 07C0 */ X,X,X,X,X,X,X,X,X,X,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 07E0 */ D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,C,X,X,X,X,X,
+
+ /* FILLER */
+
+ /* 0800 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 0820 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Mandaic */
+
+ /* 0840 */ R,D,D,D,D,D,R,R,D,R,D,D,D,D,D,D,D,D,D,D,R,D,R,R,R,X,X,X,X,X,X,X,
+
+ /* Syriac Supplement */
+
+ /* 0860 */ D,U,D,D,D,D,U,R,D,R,R,X,X,X,X,X,
+
+ /* Arabic Extended-B */
+
+ /* 0860 */ R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,
+ /* 0880 */ R,R,R,C,C,C,D,U,U,D,D,D,D,D,R,X,U,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Arabic Extended-A */
+
+ /* 08A0 */ D,D,D,D,D,D,D,D,D,D,R,R,R,U,R,D,D,R,R,D,D,D,D,D,D,R,D,D,D,D,D,D,
+ /* 08C0 */ D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 08E0 */ X,X,U,
+
+#define joining_offset_0x1806u 739
+
+ /* Mongolian */
+
+ /* 1800 */ U,D,X,X,C,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 1820 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,X,X,X,X,X,X,X,
+ /* 1880 */ U,U,U,U,U,T,T,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 18A0 */ D,D,D,D,D,D,D,D,D,X,D,
+
+#define joining_offset_0x200cu 904
+
+ /* General Punctuation */
+
+ /* 2000 */ U,C,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 2020 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,U,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 2040 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 2060 */ X,X,X,X,X,X,U,U,U,U,
+
+#define joining_offset_0xa840u 998
+
+ /* Phags-pa */
+
+ /* A840 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* A860 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,L,U,
+
+#define joining_offset_0x10ac0u 1050
+
+ /* Manichaean */
+
+ /* 10AC0 */ D,D,D,D,D,R,U,R,U,R,R,U,U,L,R,R,R,R,R,D,D,D,D,L,D,D,D,D,D,R,D,D,
+ /* 10AE0 */ D,R,U,U,R,X,X,X,X,X,X,D,D,D,D,R,
+
+#define joining_offset_0x10b80u 1098
+
+ /* Psalter Pahlavi */
+
+ /* 10B80 */ D,R,D,R,R,R,D,D,D,R,D,D,R,D,R,R,D,R,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 10BA0 */ X,X,X,X,X,X,X,X,X,R,R,R,R,D,D,U,
+
+#define joining_offset_0x10d00u 1146
+
+ /* Hanifi Rohingya */
+
+ /* 10D00 */ L,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 10D20 */ D,D,R,D,
+
+#define joining_offset_0x10f30u 1182
+
+ /* Sogdian */
+
+ /* 10F20 */ D,D,D,R,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 10F40 */ D,D,D,D,D,U,X,X,X,X,X,X,X,X,X,X,X,D,D,D,R,X,X,X,X,X,X,X,X,X,X,X,
+ /* 10F60 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Old Uyghur */
+
+ /* 10F60 */ D,D,D,D,R,R,D,D,D,D,D,D,D,D,D,D,
+ /* 10F80 */ D,D,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+ /* 10FA0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
+
+ /* Chorasmian */
+
+ /* 10FA0 */ D,U,D,D,R,R,R,U,D,R,R,D,D,R,D,D,
+ /* 10FC0 */ U,D,R,R,D,U,U,U,U,R,D,L,
+
+#define joining_offset_0x110bdu 1338
+
+ /* Kaithi */
+
+ /* 110A0 */ U,X,X,
+ /* 110C0 */ X,X,X,X,X,X,X,X,X,X,X,X,X,U,
+
+#define joining_offset_0x1e900u 1355
+
+ /* Adlam */
+
+ /* 1E900 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1E920 */ D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,D,
+ /* 1E940 */ D,D,D,D,X,X,X,X,X,X,X,T,
+
+}; /* Table items: 1431; occupancy: 57% */
+
+
+static unsigned int
+joining_type (hb_codepoint_t u)
+{
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x0600u, 0x08E2u)) return joining_table[u - 0x0600u + joining_offset_0x0600u];
+ break;
+
+ case 0x1u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1806u, 0x18AAu)) return joining_table[u - 0x1806u + joining_offset_0x1806u];
+ break;
+
+ case 0x2u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x200Cu, 0x2069u)) return joining_table[u - 0x200Cu + joining_offset_0x200cu];
+ break;
+
+ case 0xAu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xA840u, 0xA873u)) return joining_table[u - 0xA840u + joining_offset_0xa840u];
+ break;
+
+ case 0x10u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x10AC0u, 0x10AEFu)) return joining_table[u - 0x10AC0u + joining_offset_0x10ac0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10B80u, 0x10BAFu)) return joining_table[u - 0x10B80u + joining_offset_0x10b80u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10D00u, 0x10D23u)) return joining_table[u - 0x10D00u + joining_offset_0x10d00u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x10F30u, 0x10FCBu)) return joining_table[u - 0x10F30u + joining_offset_0x10f30u];
+ break;
+
+ case 0x11u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x110BDu, 0x110CDu)) return joining_table[u - 0x110BDu + joining_offset_0x110bdu];
+ break;
+
+ case 0x1Eu:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1E900u, 0x1E94Bu)) return joining_table[u - 0x1E900u + joining_offset_0x1e900u];
+ break;
+
+ default:
+ break;
+ }
+ return X;
+}
+
+#undef A
+#undef DR
+#undef C
+#undef D
+#undef L
+#undef R
+#undef T
+#undef U
+#undef X
+
+
+static const uint16_t shaping_table[][4] =
+{
+ {0x0000u, 0x0000u, 0x0000u, 0xFE80u}, /* U+0621 ARABIC LETTER HAMZA ISOLATED FORM */
+ {0x0000u, 0x0000u, 0xFE82u, 0xFE81u}, /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */
+ {0x0000u, 0x0000u, 0xFE84u, 0xFE83u}, /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE86u, 0xFE85u}, /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE88u, 0xFE87u}, /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */
+ {0xFE8Bu, 0xFE8Cu, 0xFE8Au, 0xFE89u}, /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */
+ {0x0000u, 0x0000u, 0xFE8Eu, 0xFE8Du}, /* U+0627 ARABIC LETTER ALEF */
+ {0xFE91u, 0xFE92u, 0xFE90u, 0xFE8Fu}, /* U+0628 ARABIC LETTER BEH */
+ {0x0000u, 0x0000u, 0xFE94u, 0xFE93u}, /* U+0629 ARABIC LETTER TEH MARBUTA */
+ {0xFE97u, 0xFE98u, 0xFE96u, 0xFE95u}, /* U+062A ARABIC LETTER TEH */
+ {0xFE9Bu, 0xFE9Cu, 0xFE9Au, 0xFE99u}, /* U+062B ARABIC LETTER THEH */
+ {0xFE9Fu, 0xFEA0u, 0xFE9Eu, 0xFE9Du}, /* U+062C ARABIC LETTER JEEM */
+ {0xFEA3u, 0xFEA4u, 0xFEA2u, 0xFEA1u}, /* U+062D ARABIC LETTER HAH */
+ {0xFEA7u, 0xFEA8u, 0xFEA6u, 0xFEA5u}, /* U+062E ARABIC LETTER KHAH */
+ {0x0000u, 0x0000u, 0xFEAAu, 0xFEA9u}, /* U+062F ARABIC LETTER DAL */
+ {0x0000u, 0x0000u, 0xFEACu, 0xFEABu}, /* U+0630 ARABIC LETTER THAL */
+ {0x0000u, 0x0000u, 0xFEAEu, 0xFEADu}, /* U+0631 ARABIC LETTER REH */
+ {0x0000u, 0x0000u, 0xFEB0u, 0xFEAFu}, /* U+0632 ARABIC LETTER ZAIN */
+ {0xFEB3u, 0xFEB4u, 0xFEB2u, 0xFEB1u}, /* U+0633 ARABIC LETTER SEEN */
+ {0xFEB7u, 0xFEB8u, 0xFEB6u, 0xFEB5u}, /* U+0634 ARABIC LETTER SHEEN */
+ {0xFEBBu, 0xFEBCu, 0xFEBAu, 0xFEB9u}, /* U+0635 ARABIC LETTER SAD */
+ {0xFEBFu, 0xFEC0u, 0xFEBEu, 0xFEBDu}, /* U+0636 ARABIC LETTER DAD */
+ {0xFEC3u, 0xFEC4u, 0xFEC2u, 0xFEC1u}, /* U+0637 ARABIC LETTER TAH */
+ {0xFEC7u, 0xFEC8u, 0xFEC6u, 0xFEC5u}, /* U+0638 ARABIC LETTER ZAH */
+ {0xFECBu, 0xFECCu, 0xFECAu, 0xFEC9u}, /* U+0639 ARABIC LETTER AIN */
+ {0xFECFu, 0xFED0u, 0xFECEu, 0xFECDu}, /* U+063A ARABIC LETTER GHAIN */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+063F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0640 */
+ {0xFED3u, 0xFED4u, 0xFED2u, 0xFED1u}, /* U+0641 ARABIC LETTER FEH */
+ {0xFED7u, 0xFED8u, 0xFED6u, 0xFED5u}, /* U+0642 ARABIC LETTER QAF */
+ {0xFEDBu, 0xFEDCu, 0xFEDAu, 0xFED9u}, /* U+0643 ARABIC LETTER KAF */
+ {0xFEDFu, 0xFEE0u, 0xFEDEu, 0xFEDDu}, /* U+0644 ARABIC LETTER LAM */
+ {0xFEE3u, 0xFEE4u, 0xFEE2u, 0xFEE1u}, /* U+0645 ARABIC LETTER MEEM */
+ {0xFEE7u, 0xFEE8u, 0xFEE6u, 0xFEE5u}, /* U+0646 ARABIC LETTER NOON */
+ {0xFEEBu, 0xFEECu, 0xFEEAu, 0xFEE9u}, /* U+0647 ARABIC LETTER HEH */
+ {0x0000u, 0x0000u, 0xFEEEu, 0xFEEDu}, /* U+0648 ARABIC LETTER WAW */
+ {0xFBE8u, 0xFBE9u, 0xFEF0u, 0xFEEFu}, /* U+0649 ARABIC LETTER */
+ {0xFEF3u, 0xFEF4u, 0xFEF2u, 0xFEF1u}, /* U+064A ARABIC LETTER YEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+064F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0650 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0651 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0652 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0653 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0654 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0655 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0656 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0657 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0658 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0659 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+065F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0660 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0661 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0662 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0663 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0664 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0665 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0666 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0667 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0668 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0669 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+066F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0670 */
+ {0x0000u, 0x0000u, 0xFB51u, 0xFB50u}, /* U+0671 ARABIC LETTER ALEF WASLA */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0672 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0673 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0674 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0675 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0676 */
+ {0x0000u, 0x0000u, 0x0000u, 0xFBDDu}, /* U+0677 ARABIC LETTER U WITH HAMZA ABOVE ISOLATED FORM */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0678 */
+ {0xFB68u, 0xFB69u, 0xFB67u, 0xFB66u}, /* U+0679 ARABIC LETTER TTEH */
+ {0xFB60u, 0xFB61u, 0xFB5Fu, 0xFB5Eu}, /* U+067A ARABIC LETTER TTEHEH */
+ {0xFB54u, 0xFB55u, 0xFB53u, 0xFB52u}, /* U+067B ARABIC LETTER BEEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+067D */
+ {0xFB58u, 0xFB59u, 0xFB57u, 0xFB56u}, /* U+067E ARABIC LETTER PEH */
+ {0xFB64u, 0xFB65u, 0xFB63u, 0xFB62u}, /* U+067F ARABIC LETTER TEHEH */
+ {0xFB5Cu, 0xFB5Du, 0xFB5Bu, 0xFB5Au}, /* U+0680 ARABIC LETTER BEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0681 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0682 */
+ {0xFB78u, 0xFB79u, 0xFB77u, 0xFB76u}, /* U+0683 ARABIC LETTER NYEH */
+ {0xFB74u, 0xFB75u, 0xFB73u, 0xFB72u}, /* U+0684 ARABIC LETTER DYEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0685 */
+ {0xFB7Cu, 0xFB7Du, 0xFB7Bu, 0xFB7Au}, /* U+0686 ARABIC LETTER TCHEH */
+ {0xFB80u, 0xFB81u, 0xFB7Fu, 0xFB7Eu}, /* U+0687 ARABIC LETTER TCHEHEH */
+ {0x0000u, 0x0000u, 0xFB89u, 0xFB88u}, /* U+0688 ARABIC LETTER DDAL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0689 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068B */
+ {0x0000u, 0x0000u, 0xFB85u, 0xFB84u}, /* U+068C ARABIC LETTER DAHAL */
+ {0x0000u, 0x0000u, 0xFB83u, 0xFB82u}, /* U+068D ARABIC LETTER DDAHAL */
+ {0x0000u, 0x0000u, 0xFB87u, 0xFB86u}, /* U+068E ARABIC LETTER DUL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+068F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0690 */
+ {0x0000u, 0x0000u, 0xFB8Du, 0xFB8Cu}, /* U+0691 ARABIC LETTER RREH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0692 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0693 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0694 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0695 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0696 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0697 */
+ {0x0000u, 0x0000u, 0xFB8Bu, 0xFB8Au}, /* U+0698 ARABIC LETTER JEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+0699 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069A */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069B */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069C */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069D */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+069F */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A0 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A1 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A2 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A3 */
+ {0xFB6Cu, 0xFB6Du, 0xFB6Bu, 0xFB6Au}, /* U+06A4 ARABIC LETTER VEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A5 */
+ {0xFB70u, 0xFB71u, 0xFB6Fu, 0xFB6Eu}, /* U+06A6 ARABIC LETTER PEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A7 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06A8 */
+ {0xFB90u, 0xFB91u, 0xFB8Fu, 0xFB8Eu}, /* U+06A9 ARABIC LETTER KEHEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AA */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AB */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AC */
+ {0xFBD5u, 0xFBD6u, 0xFBD4u, 0xFBD3u}, /* U+06AD ARABIC LETTER NG */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06AE */
+ {0xFB94u, 0xFB95u, 0xFB93u, 0xFB92u}, /* U+06AF ARABIC LETTER GAF */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B0 */
+ {0xFB9Cu, 0xFB9Du, 0xFB9Bu, 0xFB9Au}, /* U+06B1 ARABIC LETTER NGOEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B2 */
+ {0xFB98u, 0xFB99u, 0xFB97u, 0xFB96u}, /* U+06B3 ARABIC LETTER GUEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B4 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B5 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B6 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B7 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B8 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06B9 */
+ {0x0000u, 0x0000u, 0xFB9Fu, 0xFB9Eu}, /* U+06BA ARABIC LETTER NOON GHUNNA */
+ {0xFBA2u, 0xFBA3u, 0xFBA1u, 0xFBA0u}, /* U+06BB ARABIC LETTER RNOON */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BC */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BD */
+ {0xFBACu, 0xFBADu, 0xFBABu, 0xFBAAu}, /* U+06BE ARABIC LETTER HEH DOACHASHMEE */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06BF */
+ {0x0000u, 0x0000u, 0xFBA5u, 0xFBA4u}, /* U+06C0 ARABIC LETTER HEH WITH YEH ABOVE */
+ {0xFBA8u, 0xFBA9u, 0xFBA7u, 0xFBA6u}, /* U+06C1 ARABIC LETTER HEH GOAL */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C2 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C3 */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06C4 */
+ {0x0000u, 0x0000u, 0xFBE1u, 0xFBE0u}, /* U+06C5 ARABIC LETTER KIRGHIZ OE */
+ {0x0000u, 0x0000u, 0xFBDAu, 0xFBD9u}, /* U+06C6 ARABIC LETTER OE */
+ {0x0000u, 0x0000u, 0xFBD8u, 0xFBD7u}, /* U+06C7 ARABIC LETTER U */
+ {0x0000u, 0x0000u, 0xFBDCu, 0xFBDBu}, /* U+06C8 ARABIC LETTER YU */
+ {0x0000u, 0x0000u, 0xFBE3u, 0xFBE2u}, /* U+06C9 ARABIC LETTER KIRGHIZ YU */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CA */
+ {0x0000u, 0x0000u, 0xFBDFu, 0xFBDEu}, /* U+06CB ARABIC LETTER VE */
+ {0xFBFEu, 0xFBFFu, 0xFBFDu, 0xFBFCu}, /* U+06CC ARABIC LETTER FARSI YEH */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CD */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CE */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06CF */
+ {0xFBE6u, 0xFBE7u, 0xFBE5u, 0xFBE4u}, /* U+06D0 ARABIC LETTER E */
+ {0x0000u, 0x0000u, 0x0000u, 0x0000u}, /* U+06D1 */
+ {0x0000u, 0x0000u, 0xFBAFu, 0xFBAEu}, /* U+06D2 ARABIC LETTER YEH BARREE */
+ {0x0000u, 0x0000u, 0xFBB1u, 0xFBB0u}, /* U+06D3 ARABIC LETTER YEH BARREE WITH HAMZA ABOVE */
+};
+
+#define SHAPING_TABLE_FIRST 0x0621u
+#define SHAPING_TABLE_LAST 0x06D3u
+
+
+static const struct ligature_set_t {
+ uint16_t first;
+ struct ligature_pairs_t {
+ uint16_t components[1];
+ uint16_t ligature;
+ } ligatures[14];
+} ligature_table[] =
+{
+ { 0xFE91u, {
+ { {0xFEE2u}, 0xFC08u }, /* ARABIC LIGATURE BEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFC9Fu }, /* ARABIC LIGATURE BEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFC9Cu }, /* ARABIC LIGATURE BEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFC9Du }, /* ARABIC LIGATURE BEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFC9Eu }, /* ARABIC LIGATURE BEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE92u, {
+ { {0xFEAEu}, 0xFC6Au }, /* ARABIC LIGATURE BEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC6Du }, /* ARABIC LIGATURE BEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC6Fu }, /* ARABIC LIGATURE BEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE97u, {
+ { {0xFEE2u}, 0xFC0Eu }, /* ARABIC LIGATURE TEH WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCA4u }, /* ARABIC LIGATURE TEH WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCA1u }, /* ARABIC LIGATURE TEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCA2u }, /* ARABIC LIGATURE TEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCA3u }, /* ARABIC LIGATURE TEH WITH KHAH INITIAL FORM */
+ }},
+ { 0xFE98u, {
+ { {0xFEAEu}, 0xFC70u }, /* ARABIC LIGATURE TEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC73u }, /* ARABIC LIGATURE TEH WITH NOON FINAL FORM */
+ { {0xFEF2u}, 0xFC75u }, /* ARABIC LIGATURE TEH WITH YEH FINAL FORM */
+ }},
+ { 0xFE9Bu, {
+ { {0xFEE2u}, 0xFC12u }, /* ARABIC LIGATURE THEH WITH MEEM ISOLATED FORM */
+ }},
+ { 0xFE9Fu, {
+ { {0xFEE4u}, 0xFCA8u }, /* ARABIC LIGATURE JEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA3u, {
+ { {0xFEE4u}, 0xFCAAu }, /* ARABIC LIGATURE HAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEA7u, {
+ { {0xFEE4u}, 0xFCACu }, /* ARABIC LIGATURE KHAH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB3u, {
+ { {0xFEE4u}, 0xFCB0u }, /* ARABIC LIGATURE SEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEB7u, {
+ { {0xFEE4u}, 0xFD30u }, /* ARABIC LIGATURE SHEEN WITH MEEM INITIAL FORM */
+ }},
+ { 0xFED3u, {
+ { {0xFEF2u}, 0xFC32u }, /* ARABIC LIGATURE FEH WITH YEH ISOLATED FORM */
+ }},
+ { 0xFEDFu, {
+ { {0xFE9Eu}, 0xFC3Fu }, /* ARABIC LIGATURE LAM WITH JEEM ISOLATED FORM */
+ { {0xFEA0u}, 0xFCC9u }, /* ARABIC LIGATURE LAM WITH JEEM INITIAL FORM */
+ { {0xFEA2u}, 0xFC40u }, /* ARABIC LIGATURE LAM WITH HAH ISOLATED FORM */
+ { {0xFEA4u}, 0xFCCAu }, /* ARABIC LIGATURE LAM WITH HAH INITIAL FORM */
+ { {0xFEA6u}, 0xFC41u }, /* ARABIC LIGATURE LAM WITH KHAH ISOLATED FORM */
+ { {0xFEA8u}, 0xFCCBu }, /* ARABIC LIGATURE LAM WITH KHAH INITIAL FORM */
+ { {0xFEE2u}, 0xFC42u }, /* ARABIC LIGATURE LAM WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCCCu }, /* ARABIC LIGATURE LAM WITH MEEM INITIAL FORM */
+ { {0xFEF2u}, 0xFC44u }, /* ARABIC LIGATURE LAM WITH YEH ISOLATED FORM */
+ { {0xFEECu}, 0xFCCDu }, /* ARABIC LIGATURE LAM WITH HEH INITIAL FORM */
+ { {0xFE82u}, 0xFEF5u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE ISOLATED FORM */
+ { {0xFE84u}, 0xFEF7u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM */
+ { {0xFE88u}, 0xFEF9u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW ISOLATED FORM */
+ { {0xFE8Eu}, 0xFEFBu }, /* ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM */
+ }},
+ { 0xFEE0u, {
+ { {0xFEF0u}, 0xFC86u }, /* ARABIC LIGATURE LAM WITH ALEF MAKSURA FINAL FORM */
+ { {0xFE82u}, 0xFEF6u }, /* ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE FINAL FORM */
+ { {0xFE84u}, 0xFEF8u }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM */
+ { {0xFE88u}, 0xFEFAu }, /* ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW FINAL FORM */
+ { {0xFE8Eu}, 0xFEFCu }, /* ARABIC LIGATURE LAM WITH ALEF FINAL FORM */
+ }},
+ { 0xFEE3u, {
+ { {0xFEA0u}, 0xFCCEu }, /* ARABIC LIGATURE MEEM WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCCFu }, /* ARABIC LIGATURE MEEM WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCD0u }, /* ARABIC LIGATURE MEEM WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCD1u }, /* ARABIC LIGATURE MEEM WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEE7u, {
+ { {0xFEE2u}, 0xFC4Eu }, /* ARABIC LIGATURE NOON WITH MEEM ISOLATED FORM */
+ { {0xFEE4u}, 0xFCD5u }, /* ARABIC LIGATURE NOON WITH MEEM INITIAL FORM */
+ { {0xFEA0u}, 0xFCD2u }, /* ARABIC LIGATURE NOON WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCD3u }, /* ARABIC LIGATURE NOON WITH HAH INITIAL FORM */
+ }},
+ { 0xFEE8u, {
+ { {0xFEF2u}, 0xFC8Fu }, /* ARABIC LIGATURE NOON WITH YEH FINAL FORM */
+ }},
+ { 0xFEF3u, {
+ { {0xFEA0u}, 0xFCDAu }, /* ARABIC LIGATURE YEH WITH JEEM INITIAL FORM */
+ { {0xFEA4u}, 0xFCDBu }, /* ARABIC LIGATURE YEH WITH HAH INITIAL FORM */
+ { {0xFEA8u}, 0xFCDCu }, /* ARABIC LIGATURE YEH WITH KHAH INITIAL FORM */
+ { {0xFEE4u}, 0xFCDDu }, /* ARABIC LIGATURE YEH WITH MEEM INITIAL FORM */
+ }},
+ { 0xFEF4u, {
+ { {0xFEAEu}, 0xFC91u }, /* ARABIC LIGATURE YEH WITH REH FINAL FORM */
+ { {0xFEE6u}, 0xFC94u }, /* ARABIC LIGATURE YEH WITH NOON FINAL FORM */
+ }},
+};
+
+
+static const struct ligature_mark_set_t {
+ uint16_t first;
+ struct ligature_pairs_t {
+ uint16_t components[1];
+ uint16_t ligature;
+ } ligatures[5];
+} ligature_mark_table[] =
+{
+ { 0x0651u, {
+ { {0x064Cu}, 0xFC5Eu }, /* ARABIC LIGATURE SHADDA WITH DAMMATAN ISOLATED FORM */
+ { {0x064Eu}, 0xFC60u }, /* ARABIC LIGATURE SHADDA WITH FATHA ISOLATED FORM */
+ { {0x064Fu}, 0xFC61u }, /* ARABIC LIGATURE SHADDA WITH DAMMA ISOLATED FORM */
+ { {0x0650u}, 0xFC62u }, /* ARABIC LIGATURE SHADDA WITH KASRA ISOLATED FORM */
+ { {0x064Bu}, 0xF2EEu }, /* PUA ARABIC LIGATURE SHADDA WITH FATHATAN ISOLATED FORM */
+ }},
+};
+
+
+static const struct ligature_3_set_t {
+ uint16_t first;
+ struct ligature_triplets_t {
+ uint16_t components[2];
+ uint16_t ligature;
+ } ligatures[3];
+} ligature_3_table[] =
+{
+ { 0xFEDFu, {
+ { {0xFEE4u, 0xFEA4u}, 0xFD88u}, /* ARABIC LIGATURE LAM WITH MEEM WITH HAH INITIAL FORM */
+ { {0xFEE0u, 0xFEEAu}, 0xF201u}, /* PUA ARABIC LIGATURE LELLAH ISOLATED FORM */
+ { {0xFEE4u, 0xFEA0u}, 0xF211u}, /* PUA ARABIC LIGATURE LAM WITH MEEM WITH JEEM INITIAL FORM */
+ }},
+};
+
+
+#endif /* HB_OT_SHAPER_ARABIC_TABLE_HH */
+
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh
new file mode 100644
index 0000000000..b8d481c813
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic-win1256.hh
@@ -0,0 +1,349 @@
+/*
+ * Copyright © 2014 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_WIN1256_HH
+
+
+/*
+ * The macros in the first part of this file are generic macros that can
+ * be used to define the bytes for OpenType table data in code in a
+ * readable manner. We can move the macros to reside with their respective
+ * struct types, but since we only use these to define one data table, the
+ * Windows-1256 Arabic shaping table in this file, we keep them here.
+ */
+
+
+/* First we measure, then we cut. */
+#ifndef OT_MEASURE
+#define OT_MEASURE
+#define OT_TABLE_START static const struct TABLE_NAME {
+#define OT_TABLE_END }
+#define OT_LABEL_START(Name) unsigned char Name[
+#define OT_LABEL_END ];
+#define OT_UINT8(u8) +1/*byte*/
+#define OT_UINT16(u16) +2/*bytes*/
+#else
+#undef OT_MEASURE
+#define OT_TABLE_START TABLE_NAME = {
+#define OT_TABLE_END };
+#define OT_LABEL_START(Name) {
+#define OT_LABEL_END },
+#define OT_UINT8(u8) (u8),
+#define OT_UINT16(u16) (unsigned char)((u16)>>8), (unsigned char)((u16)&0xFFu),
+#define OT_COUNT(Name, ItemSize) ((unsigned int) sizeof(((struct TABLE_NAME*)0)->Name) \
+ / (unsigned int)(ItemSize) \
+ /* OT_ASSERT it's divisible (and positive). */)
+#define OT_DISTANCE(From,To) ((unsigned int) \
+ ((char*)(&((struct TABLE_NAME*)0)->To) - \
+ (char*)(&((struct TABLE_NAME*)0)->From)) \
+ /* OT_ASSERT it's positive. */)
+#endif
+
+
+#define OT_LABEL(Name) \
+ OT_LABEL_END \
+ OT_LABEL_START(Name)
+
+/* Whenever we receive an argument that is a list, it will expand to
+ * contain commas. That cannot be passed to another macro because the
+ * commas will throw off the preprocessor. The solution is to wrap
+ * the passed-in argument in OT_LIST() before passing to the next macro.
+ * Unfortunately this trick requires vararg macros. */
+#define OT_LIST(...) __VA_ARGS__
+
+
+/*
+ * Basic Types
+ */
+
+#define OT_TAG(a,b,c,d) \
+ OT_UINT8(a) OT_UINT8(b) OT_UINT8(c) OT_UINT8(d)
+
+#define OT_OFFSET(From, To) /* Offset from From to To in bytes */ \
+ OT_UINT16(OT_DISTANCE(From, To))
+
+#define OT_GLYPHID /* GlyphID */ \
+ OT_UINT16
+/* Shorthand. */
+#define G OT_GLYPHID
+
+#define OT_UARRAY(Name, Items) \
+ OT_LABEL_START(Name) \
+ OT_UINT16(OT_COUNT(Name##Data, 2)) \
+ OT_LABEL(Name##Data) \
+ Items \
+ OT_LABEL_END
+
+#define OT_UHEADLESSARRAY(Name, Items) \
+ OT_LABEL_START(Name) \
+ OT_UINT16(OT_COUNT(Name##Data, 2) + 1) \
+ OT_LABEL(Name##Data) \
+ Items \
+ OT_LABEL_END
+
+
+/*
+ * Common Types
+ */
+
+#define OT_LOOKUP_FLAG_IGNORE_MARKS 0x08u
+
+#define OT_LOOKUP(Name, LookupType, LookupFlag, SubLookupOffsets) \
+ OT_LABEL_START(Name) \
+ OT_UINT16(LookupType) \
+ OT_UINT16(LookupFlag) \
+ OT_LABEL_END \
+ OT_UARRAY(Name##SubLookupOffsetsArray, OT_LIST(SubLookupOffsets))
+
+#define OT_SUBLOOKUP(Name, SubFormat, Items) \
+ OT_LABEL_START(Name) \
+ OT_UINT16(SubFormat) \
+ Items
+
+#define OT_COVERAGE1(Name, Items) \
+ OT_LABEL_START(Name) \
+ OT_UINT16(1) \
+ OT_LABEL_END \
+ OT_UARRAY(Name##Glyphs, OT_LIST(Items))
+
+
+/*
+ * GSUB
+ */
+
+#define OT_LOOKUP_TYPE_SUBST_SINGLE 1u
+#define OT_LOOKUP_TYPE_SUBST_LIGATURE 4u
+
+#define OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(Name, FromGlyphs, ToGlyphs) \
+ OT_SUBLOOKUP(Name, 2, \
+ OT_OFFSET(Name, Name##Coverage) \
+ OT_LABEL_END \
+ OT_UARRAY(Name##Substitute, OT_LIST(ToGlyphs)) \
+ ) \
+ OT_COVERAGE1(Name##Coverage, OT_LIST(FromGlyphs)) \
+ /* static_assert_expr (len(FromGlyphs) == len(ToGlyphs)) */
+
+#define OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(Name, FirstGlyphs, LigatureSetOffsets) \
+ OT_SUBLOOKUP(Name, 1, \
+ OT_OFFSET(Name, Name##Coverage) \
+ OT_LABEL_END \
+ OT_UARRAY(Name##LigatureSetOffsetsArray, OT_LIST(LigatureSetOffsets)) \
+ ) \
+ OT_COVERAGE1(Name##Coverage, OT_LIST(FirstGlyphs)) \
+ /* static_assert_expr (len(FirstGlyphs) == len(LigatureSetOffsets)) */
+
+#define OT_LIGATURE_SET(Name, LigatureSetOffsets) \
+ OT_UARRAY(Name, OT_LIST(LigatureSetOffsets))
+
+#define OT_LIGATURE(Name, Components, LigGlyph) \
+ OT_LABEL_START(Name) \
+ LigGlyph \
+ OT_LABEL_END \
+ OT_UHEADLESSARRAY(Name##ComponentsArray, OT_LIST(Components))
+
+/*
+ *
+ * Start of Windows-1256 shaping table.
+ *
+ */
+
+/* Table name. */
+#define TABLE_NAME arabic_win1256_gsub_lookups
+
+/* Table manifest. */
+#define MANIFEST(Items) \
+ OT_LABEL_START(manifest) \
+ OT_UINT16(OT_COUNT(manifestData, 6)) \
+ OT_LABEL(manifestData) \
+ Items \
+ OT_LABEL_END
+
+#define MANIFEST_LOOKUP(Tag, Name) \
+ Tag \
+ OT_OFFSET(manifest, Name)
+
+
+/*
+ * Table Start
+ */
+OT_TABLE_START
+
+
+/*
+ * Manifest
+ */
+MANIFEST(
+ MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligLookup)
+ MANIFEST_LOOKUP(OT_TAG('i','n','i','t'), initLookup)
+ MANIFEST_LOOKUP(OT_TAG('m','e','d','i'), mediLookup)
+ MANIFEST_LOOKUP(OT_TAG('f','i','n','a'), finaLookup)
+ MANIFEST_LOOKUP(OT_TAG('r','l','i','g'), rligMarksLookup)
+)
+
+/*
+ * Lookups
+ */
+OT_LOOKUP(initLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+ OT_OFFSET(initLookup, initmediSubLookup)
+ OT_OFFSET(initLookup, initSubLookup)
+)
+OT_LOOKUP(mediLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+ OT_OFFSET(mediLookup, initmediSubLookup)
+ OT_OFFSET(mediLookup, mediSubLookup)
+ OT_OFFSET(mediLookup, medifinaLamAlefSubLookup)
+)
+OT_LOOKUP(finaLookup, OT_LOOKUP_TYPE_SUBST_SINGLE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+ OT_OFFSET(finaLookup, finaSubLookup)
+ /* We don't need this one currently as the sequence inherits masks
+ * from the first item. Just in case we change that in the future
+ * to be smart about Arabic masks when ligating... */
+ OT_OFFSET(finaLookup, medifinaLamAlefSubLookup)
+)
+OT_LOOKUP(rligLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, OT_LOOKUP_FLAG_IGNORE_MARKS,
+ OT_OFFSET(rligLookup, lamAlefLigaturesSubLookup)
+)
+OT_LOOKUP(rligMarksLookup, OT_LOOKUP_TYPE_SUBST_LIGATURE, 0,
+ OT_OFFSET(rligMarksLookup, shaddaLigaturesSubLookup)
+)
+
+/*
+ * init/medi/fina forms
+ */
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initmediSubLookup,
+ G(198) G(200) G(201) G(202) G(203) G(204) G(205) G(206) G(211)
+ G(212) G(213) G(214) G(223) G(225) G(227) G(228) G(236) G(237),
+ G(162) G(4) G(5) G(5) G(6) G(7) G(9) G(11) G(13)
+ G(14) G(15) G(26) G(140) G(141) G(142) G(143) G(154) G(154)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(initSubLookup,
+ G(218) G(219) G(221) G(222) G(229),
+ G(27) G(30) G(128) G(131) G(144)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(mediSubLookup,
+ G(218) G(219) G(221) G(222) G(229),
+ G(28) G(31) G(129) G(138) G(149)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(finaSubLookup,
+ G(194) G(195) G(197) G(198) G(199) G(201) G(204) G(205) G(206)
+ G(218) G(219) G(229) G(236) G(237),
+ G(2) G(1) G(3) G(181) G(0) G(159) G(8) G(10) G(12)
+ G(29) G(127) G(152) G(160) G(156)
+)
+OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2(medifinaLamAlefSubLookup,
+ G(165) G(178) G(180) G(252),
+ G(170) G(179) G(185) G(255)
+)
+
+/*
+ * Lam+Alef ligatures
+ */
+OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(lamAlefLigaturesSubLookup,
+ G(225),
+ OT_OFFSET(lamAlefLigaturesSubLookup, lamLigatureSet)
+)
+OT_LIGATURE_SET(lamLigatureSet,
+ OT_OFFSET(lamLigatureSet, lamInitLigature1)
+ OT_OFFSET(lamLigatureSet, lamInitLigature2)
+ OT_OFFSET(lamLigatureSet, lamInitLigature3)
+ OT_OFFSET(lamLigatureSet, lamInitLigature4)
+)
+OT_LIGATURE(lamInitLigature1, G(199), G(165))
+OT_LIGATURE(lamInitLigature2, G(195), G(178))
+OT_LIGATURE(lamInitLigature3, G(194), G(180))
+OT_LIGATURE(lamInitLigature4, G(197), G(252))
+
+/*
+ * Shadda ligatures
+ */
+OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1(shaddaLigaturesSubLookup,
+ G(248),
+ OT_OFFSET(shaddaLigaturesSubLookup, shaddaLigatureSet)
+)
+OT_LIGATURE_SET(shaddaLigatureSet,
+ OT_OFFSET(shaddaLigatureSet, shaddaLigature1)
+ OT_OFFSET(shaddaLigatureSet, shaddaLigature2)
+ OT_OFFSET(shaddaLigatureSet, shaddaLigature3)
+)
+OT_LIGATURE(shaddaLigature1, G(243), G(172))
+OT_LIGATURE(shaddaLigature2, G(245), G(173))
+OT_LIGATURE(shaddaLigature3, G(246), G(175))
+
+/*
+ * Table end
+ */
+OT_TABLE_END
+
+
+/*
+ * Clean up
+ */
+
+#undef MANIFEST
+#undef MANIFEST_LOOKUP
+
+#undef OT_TABLE_START
+#undef OT_TABLE_END
+#undef OT_LABEL_START
+#undef OT_LABEL_END
+#undef OT_UINT8
+#undef OT_UINT16
+#undef OT_COUNT
+#undef OT_DISTANCE
+
+#undef OT_LABEL
+#undef OT_LIST
+
+#undef OT_TAG
+#undef OT_OFFSET
+#undef OT_GLYPHID
+#undef G
+#undef OT_UARRAY
+#undef OT_UHEADLESSARRAY
+
+#undef OT_LOOKUP_FLAG_IGNORE_MARKS
+#undef OT_LOOKUP
+#undef OT_SUBLOOKUP
+#undef OT_COVERAGE1
+#undef OT_LOOKUP_TYPE_SUBST_SINGLE
+#undef OT_LOOKUP_TYPE_SUBST_LIGATURE
+#undef OT_SUBLOOKUP_SINGLE_SUBST_FORMAT2
+#undef OT_SUBLOOKUP_LIGATURE_SUBST_FORMAT1
+#undef OT_LIGATURE_SET
+#undef OT_LIGATURE
+
+
+/*
+ * Include a second time to get the table data...
+ */
+#if 0
+#include "hb.hh" /* Make check-includes.sh happy. */
+#endif
+#ifdef OT_MEASURE
+#include "hb-ot-shaper-arabic-win1256.hh"
+#endif
+
+#define HB_OT_SHAPER_ARABIC_WIN1256_HH
+#endif /* HB_OT_SHAPER_ARABIC_WIN1256_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
new file mode 100644
index 0000000000..ed2748b828
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.cc
@@ -0,0 +1,752 @@
+/*
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-arabic.hh"
+#include "hb-ot-shape.hh"
+
+
+/* buffer var allocations */
+#define arabic_shaping_action() ot_shaper_var_u8_auxiliary() /* arabic shaping action */
+
+#define HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH HB_BUFFER_SCRATCH_FLAG_SHAPER0
+
+/* See:
+ * https://github.com/harfbuzz/harfbuzz/commit/6e6f82b6f3dde0fc6c3c7d991d9ec6cfff57823d#commitcomment-14248516 */
+#define HB_ARABIC_GENERAL_CATEGORY_IS_WORD(gen_cat) \
+ (FLAG_UNSAFE (gen_cat) & \
+ (FLAG (HB_UNICODE_GENERAL_CATEGORY_UNASSIGNED) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_PRIVATE_USE) | \
+ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_LOWERCASE_LETTER) |*/ \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_LETTER) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) | \
+ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_TITLECASE_LETTER) |*/ \
+ /*FLAG (HB_UNICODE_GENERAL_CATEGORY_UPPERCASE_LETTER) |*/ \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_LETTER_NUMBER) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_NUMBER) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_CURRENCY_SYMBOL) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_MATH_SYMBOL) | \
+ FLAG (HB_UNICODE_GENERAL_CATEGORY_OTHER_SYMBOL)))
+
+
+/*
+ * Joining types:
+ */
+
+/*
+ * Bits used in the joining tables
+ */
+enum hb_arabic_joining_type_t {
+ JOINING_TYPE_U = 0,
+ JOINING_TYPE_L = 1,
+ JOINING_TYPE_R = 2,
+ JOINING_TYPE_D = 3,
+ JOINING_TYPE_C = JOINING_TYPE_D,
+ JOINING_GROUP_ALAPH = 4,
+ JOINING_GROUP_DALATH_RISH = 5,
+ NUM_STATE_MACHINE_COLS = 6,
+
+ JOINING_TYPE_T = 7,
+ JOINING_TYPE_X = 8 /* means: use general-category to choose between U or T. */
+};
+
+#include "hb-ot-shaper-arabic-table.hh"
+
+static unsigned int get_joining_type (hb_codepoint_t u, hb_unicode_general_category_t gen_cat)
+{
+ unsigned int j_type = joining_type(u);
+ if (likely (j_type != JOINING_TYPE_X))
+ return j_type;
+
+ return (FLAG_UNSAFE(gen_cat) &
+ (FLAG(HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) |
+ FLAG(HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK) |
+ FLAG(HB_UNICODE_GENERAL_CATEGORY_FORMAT))
+ ) ? JOINING_TYPE_T : JOINING_TYPE_U;
+}
+
+#define FEATURE_IS_SYRIAC(tag) hb_in_range<unsigned char> ((unsigned char) (tag), '2', '3')
+
+static const hb_tag_t arabic_features[] =
+{
+ HB_TAG('i','s','o','l'),
+ HB_TAG('f','i','n','a'),
+ HB_TAG('f','i','n','2'),
+ HB_TAG('f','i','n','3'),
+ HB_TAG('m','e','d','i'),
+ HB_TAG('m','e','d','2'),
+ HB_TAG('i','n','i','t'),
+ HB_TAG_NONE
+};
+
+
+/* Same order as the feature array */
+enum arabic_action_t {
+ ISOL,
+ FINA,
+ FIN2,
+ FIN3,
+ MEDI,
+ MED2,
+ INIT,
+
+ NONE,
+
+ ARABIC_NUM_FEATURES = NONE,
+
+ /* We abuse the same byte for other things... */
+ STCH_FIXED,
+ STCH_REPEATING,
+};
+
+static const struct arabic_state_table_entry {
+ uint8_t prev_action;
+ uint8_t curr_action;
+ uint16_t next_state;
+} arabic_state_table[][NUM_STATE_MACHINE_COLS] =
+{
+ /* jt_U, jt_L, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */
+
+ /* State 0: prev was U, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,6}, },
+
+ /* State 1: prev was R or ISOL/ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN2,5}, {NONE,ISOL,6}, },
+
+ /* State 2: prev was D/L in ISOL form, willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {INIT,FINA,1}, {INIT,FINA,3}, {INIT,FINA,4}, {INIT,FINA,6}, },
+
+ /* State 3: prev was D in FINA form, willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {MEDI,FINA,1}, {MEDI,FINA,3}, {MEDI,FINA,4}, {MEDI,FINA,6}, },
+
+ /* State 4: prev was FINA ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {MED2,ISOL,1}, {MED2,ISOL,2}, {MED2,FIN2,5}, {MED2,ISOL,6}, },
+
+ /* State 5: prev was FIN2/FIN3 ALAPH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {ISOL,ISOL,1}, {ISOL,ISOL,2}, {ISOL,FIN2,5}, {ISOL,ISOL,6}, },
+
+ /* State 6: prev was DALATH/RISH, not willing to join. */
+ { {NONE,NONE,0}, {NONE,ISOL,2}, {NONE,ISOL,1}, {NONE,ISOL,2}, {NONE,FIN3,5}, {NONE,ISOL,6}, }
+};
+
+
+static void
+arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+record_stch (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+deallocate_buffer_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, arabic_shaping_action);
+}
+
+static void
+collect_features_arabic (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* We apply features according to the Arabic spec, with pauses
+ * in between most.
+ *
+ * The pause between init/medi/... and rlig is required. See eg:
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=644184
+ *
+ * The pauses between init/medi/... themselves are not necessarily
+ * needed as only one of those features is applied to any character.
+ * The only difference it makes is when fonts have contextual
+ * substitutions. We now follow the order of the spec, which makes
+ * for better experience if that's what Uniscribe is doing.
+ *
+ * At least for Arabic, looks like Uniscribe has a pause between
+ * rlig and calt. Otherwise the IranNastaliq's ALLAH ligature won't
+ * work. However, testing shows that rlig and calt are applied
+ * together for Mongolian in Uniscribe. As such, we only add a
+ * pause for Arabic, not other scripts.
+ */
+
+
+ map->enable_feature (HB_TAG('s','t','c','h'));
+ map->add_gsub_pause (record_stch);
+
+ map->enable_feature (HB_TAG('c','c','m','p'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('l','o','c','l'), F_MANUAL_ZWJ);
+
+ map->add_gsub_pause (nullptr);
+
+ for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++)
+ {
+ bool has_fallback = plan->props.script == HB_SCRIPT_ARABIC && !FEATURE_IS_SYRIAC (arabic_features[i]);
+ map->add_feature (arabic_features[i], F_MANUAL_ZWJ | (has_fallback ? F_HAS_FALLBACK : F_NONE));
+ map->add_gsub_pause (nullptr);
+ }
+ map->add_gsub_pause (deallocate_buffer_var);
+
+ /* Normally, Unicode says a ZWNJ means "don't ligate". In Arabic script
+ * however, it says a ZWJ should also mean "don't ligate". So we run
+ * the main ligating features as MANUAL_ZWJ. */
+
+ map->enable_feature (HB_TAG('r','l','i','g'), F_MANUAL_ZWJ | F_HAS_FALLBACK);
+
+ if (plan->props.script == HB_SCRIPT_ARABIC)
+ map->add_gsub_pause (arabic_fallback_shape);
+
+ map->enable_feature (HB_TAG('c','a','l','t'), F_MANUAL_ZWJ);
+ /* https://github.com/harfbuzz/harfbuzz/issues/1573 */
+ if (!map->has_feature (HB_TAG('r','c','l','t')))
+ {
+ map->add_gsub_pause (nullptr);
+ map->enable_feature (HB_TAG('r','c','l','t'), F_MANUAL_ZWJ);
+ }
+
+ map->enable_feature (HB_TAG('l','i','g','a'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('c','l','i','g'), F_MANUAL_ZWJ);
+
+ /* The spec includes 'cswh'. Earlier versions of Windows
+ * used to enable this by default, but testing suggests
+ * that Windows 8 and later do not enable it by default,
+ * and spec now says 'Off by default'.
+ * We disabled this in ae23c24c32.
+ * Note that IranNastaliq uses this feature extensively
+ * to fixup broken glyph sequences. Oh well...
+ * Test case: U+0643,U+0640,U+0631. */
+ //map->enable_feature (HB_TAG('c','s','w','h'), F_MANUAL_ZWJ);
+ map->enable_feature (HB_TAG('m','s','e','t'), F_MANUAL_ZWJ);
+}
+
+#include "hb-ot-shaper-arabic-fallback.hh"
+
+struct arabic_shape_plan_t
+{
+ /* The "+ 1" in the next array is to accommodate for the "NONE" command,
+ * which is not an OpenType feature, but this simplifies the code by not
+ * having to do a "if (... < NONE) ..." and just rely on the fact that
+ * mask_array[NONE] == 0. */
+ hb_mask_t mask_array[ARABIC_NUM_FEATURES + 1];
+
+ hb_atomic_ptr_t<arabic_fallback_plan_t> fallback_plan;
+
+ unsigned int do_fallback : 1;
+ unsigned int has_stch : 1;
+};
+
+void *
+data_create_arabic (const hb_ot_shape_plan_t *plan)
+{
+ arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) hb_calloc (1, sizeof (arabic_shape_plan_t));
+ if (unlikely (!arabic_plan))
+ return nullptr;
+
+ arabic_plan->do_fallback = plan->props.script == HB_SCRIPT_ARABIC;
+ arabic_plan->has_stch = !!plan->map.get_1_mask (HB_TAG ('s','t','c','h'));
+ for (unsigned int i = 0; i < ARABIC_NUM_FEATURES; i++) {
+ arabic_plan->mask_array[i] = plan->map.get_1_mask (arabic_features[i]);
+ arabic_plan->do_fallback = arabic_plan->do_fallback &&
+ (FEATURE_IS_SYRIAC (arabic_features[i]) ||
+ plan->map.needs_fallback (arabic_features[i]));
+ }
+
+ return arabic_plan;
+}
+
+void
+data_destroy_arabic (void *data)
+{
+ arabic_shape_plan_t *arabic_plan = (arabic_shape_plan_t *) data;
+
+ arabic_fallback_plan_destroy (arabic_plan->fallback_plan);
+
+ hb_free (data);
+}
+
+static void
+arabic_joining (hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ unsigned int prev = UINT_MAX, state = 0;
+
+ /* Check pre-context */
+ for (unsigned int i = 0; i < buffer->context_len[0]; i++)
+ {
+ unsigned int this_type = get_joining_type (buffer->context[0][i], buffer->unicode->general_category (buffer->context[0][i]));
+
+ if (unlikely (this_type == JOINING_TYPE_T))
+ continue;
+
+ const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
+ state = entry->next_state;
+ break;
+ }
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ unsigned int this_type = get_joining_type (info[i].codepoint, _hb_glyph_info_get_general_category (&info[i]));
+
+ if (unlikely (this_type == JOINING_TYPE_T)) {
+ info[i].arabic_shaping_action() = NONE;
+ continue;
+ }
+
+ const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
+
+ if (entry->prev_action != NONE && prev != UINT_MAX)
+ {
+ info[prev].arabic_shaping_action() = entry->prev_action;
+ buffer->safe_to_insert_tatweel (prev, i + 1);
+ }
+ else
+ {
+ if (prev == UINT_MAX)
+ {
+ if (this_type >= JOINING_TYPE_R)
+ buffer->unsafe_to_concat_from_outbuffer (0, i + 1);
+ }
+ else
+ {
+ if (this_type >= JOINING_TYPE_R ||
+ (2 <= state && state <= 5) /* States that have a possible prev_action. */)
+ buffer->unsafe_to_concat (prev, i + 1);
+ }
+ }
+
+ info[i].arabic_shaping_action() = entry->curr_action;
+
+ prev = i;
+ state = entry->next_state;
+ }
+
+ for (unsigned int i = 0; i < buffer->context_len[1]; i++)
+ {
+ unsigned int this_type = get_joining_type (buffer->context[1][i], buffer->unicode->general_category (buffer->context[1][i]));
+
+ if (unlikely (this_type == JOINING_TYPE_T))
+ continue;
+
+ const arabic_state_table_entry *entry = &arabic_state_table[state][this_type];
+ if (entry->prev_action != NONE && prev != UINT_MAX)
+ {
+ info[prev].arabic_shaping_action() = entry->prev_action;
+ buffer->safe_to_insert_tatweel (prev, buffer->len);
+ }
+ else if (2 <= state && state <= 5) /* States that have a possible prev_action. */
+ {
+ buffer->unsafe_to_concat (prev, buffer->len);
+ }
+ break;
+ }
+}
+
+static void
+mongolian_variation_selectors (hb_buffer_t *buffer)
+{
+ /* Copy arabic_shaping_action() from base to Mongolian variation selectors. */
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 1; i < count; i++)
+ if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0x180Bu, 0x180Du, 0x180Fu, 0x180Fu)))
+ info[i].arabic_shaping_action() = info[i - 1].arabic_shaping_action();
+}
+
+void
+setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
+ hb_buffer_t *buffer,
+ hb_script_t script)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, arabic_shaping_action);
+
+ arabic_joining (buffer);
+ if (script == HB_SCRIPT_MONGOLIAN)
+ mongolian_variation_selectors (buffer);
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ info[i].mask |= arabic_plan->mask_array[info[i].arabic_shaping_action()];
+}
+
+static void
+setup_masks_arabic (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
+ setup_masks_arabic_plan (arabic_plan, buffer, plan->props.script);
+}
+
+static void
+arabic_fallback_shape (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+#ifdef HB_NO_OT_SHAPER_ARABIC_FALLBACK
+ return;
+#endif
+
+ const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
+
+ if (!arabic_plan->do_fallback)
+ return;
+
+retry:
+ arabic_fallback_plan_t *fallback_plan = arabic_plan->fallback_plan;
+ if (unlikely (!fallback_plan))
+ {
+ /* This sucks. We need a font to build the fallback plan... */
+ fallback_plan = arabic_fallback_plan_create (plan, font);
+ if (unlikely (!arabic_plan->fallback_plan.cmpexch (nullptr, fallback_plan)))
+ {
+ arabic_fallback_plan_destroy (fallback_plan);
+ goto retry;
+ }
+ }
+
+ arabic_fallback_plan_shape (fallback_plan, font, buffer);
+}
+
+/*
+ * Stretch feature: "stch".
+ * See example here:
+ * https://docs.microsoft.com/en-us/typography/script-development/syriac
+ * We implement this in a generic way, such that the Arabic subtending
+ * marks can use it as well.
+ */
+
+static void
+record_stch (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ const arabic_shape_plan_t *arabic_plan = (const arabic_shape_plan_t *) plan->data;
+ if (!arabic_plan->has_stch)
+ return;
+
+ /* 'stch' feature was just applied. Look for anything that multiplied,
+ * and record it for stch treatment later. Note that rtlm, frac, etc
+ * are applied before stch, but we assume that they didn't result in
+ * anything multiplying into 5 pieces, so it's safe-ish... */
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ if (unlikely (_hb_glyph_info_multiplied (&info[i])))
+ {
+ unsigned int comp = _hb_glyph_info_get_lig_comp (&info[i]);
+ info[i].arabic_shaping_action() = comp % 2 ? STCH_REPEATING : STCH_FIXED;
+ buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH;
+ }
+}
+
+static void
+apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
+ return;
+
+ /* The Arabic shaper currently always processes in RTL mode, so we should
+ * stretch / position the stretched pieces to the left / preceding glyphs. */
+
+ /* We do a two pass implementation:
+ * First pass calculates the exact number of extra glyphs we need,
+ * We then enlarge buffer to have that much room,
+ * Second pass applies the stretch, copying things to the end of buffer.
+ */
+
+ int sign = font->x_scale < 0 ? -1 : +1;
+ unsigned int extra_glyphs_needed = 0; // Set during MEASURE, used during CUT
+ enum { MEASURE, CUT } /* step_t */;
+
+ for (unsigned int step = MEASURE; step <= CUT; step = step + 1)
+ {
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ hb_glyph_position_t *pos = buffer->pos;
+ unsigned int new_len = count + extra_glyphs_needed; // write head during CUT
+ unsigned int j = new_len;
+ for (unsigned int i = count; i; i--)
+ {
+ if (!hb_in_range<uint8_t> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
+ {
+ if (step == CUT)
+ {
+ --j;
+ info[j] = info[i - 1];
+ pos[j] = pos[i - 1];
+ }
+ continue;
+ }
+
+ /* Yay, justification! */
+
+ hb_position_t w_total = 0; // Total to be filled
+ hb_position_t w_fixed = 0; // Sum of fixed tiles
+ hb_position_t w_repeating = 0; // Sum of repeating tiles
+ int n_fixed = 0;
+ int n_repeating = 0;
+
+ unsigned int end = i;
+ while (i &&
+ hb_in_range<uint8_t> (info[i - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING))
+ {
+ i--;
+ hb_position_t width = font->get_glyph_h_advance (info[i].codepoint);
+ if (info[i].arabic_shaping_action() == STCH_FIXED)
+ {
+ w_fixed += width;
+ n_fixed++;
+ }
+ else
+ {
+ w_repeating += width;
+ n_repeating++;
+ }
+ }
+ unsigned int start = i;
+ unsigned int context = i;
+ while (context &&
+ !hb_in_range<uint8_t> (info[context - 1].arabic_shaping_action(), STCH_FIXED, STCH_REPEATING) &&
+ (_hb_glyph_info_is_default_ignorable (&info[context - 1]) ||
+ HB_ARABIC_GENERAL_CATEGORY_IS_WORD (_hb_glyph_info_get_general_category (&info[context - 1]))))
+ {
+ context--;
+ w_total += pos[context].x_advance;
+ }
+ i++; // Don't touch i again.
+
+ DEBUG_MSG (ARABIC, nullptr, "%s stretch at (%d,%d,%d)",
+ step == MEASURE ? "measuring" : "cutting", context, start, end);
+ DEBUG_MSG (ARABIC, nullptr, "rest of word: count=%d width %d", start - context, w_total);
+ DEBUG_MSG (ARABIC, nullptr, "fixed tiles: count=%d width=%d", n_fixed, w_fixed);
+ DEBUG_MSG (ARABIC, nullptr, "repeating tiles: count=%d width=%d", n_repeating, w_repeating);
+
+ /* Number of additional times to repeat each repeating tile. */
+ int n_copies = 0;
+
+ hb_position_t w_remaining = w_total - w_fixed;
+ if (sign * w_remaining > sign * w_repeating && sign * w_repeating > 0)
+ n_copies = (sign * w_remaining) / (sign * w_repeating) - 1;
+
+ /* See if we can improve the fit by adding an extra repeat and squeezing them together a bit. */
+ hb_position_t extra_repeat_overlap = 0;
+ hb_position_t shortfall = sign * w_remaining - sign * w_repeating * (n_copies + 1);
+ if (shortfall > 0 && n_repeating > 0)
+ {
+ ++n_copies;
+ hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
+ if (excess > 0)
+ extra_repeat_overlap = excess / (n_copies * n_repeating);
+ }
+
+ if (step == MEASURE)
+ {
+ extra_glyphs_needed += n_copies * n_repeating;
+ DEBUG_MSG (ARABIC, nullptr, "will add extra %d copies of repeating tiles", n_copies);
+ }
+ else
+ {
+ buffer->unsafe_to_break (context, end);
+ hb_position_t x_offset = 0;
+ for (unsigned int k = end; k > start; k--)
+ {
+ hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
+
+ unsigned int repeat = 1;
+ if (info[k - 1].arabic_shaping_action() == STCH_REPEATING)
+ repeat += n_copies;
+
+ DEBUG_MSG (ARABIC, nullptr, "appending %d copies of glyph %d; j=%d",
+ repeat, info[k - 1].codepoint, j);
+ for (unsigned int n = 0; n < repeat; n++)
+ {
+ x_offset -= width;
+ if (n > 0)
+ x_offset += extra_repeat_overlap;
+ pos[k - 1].x_offset = x_offset;
+ /* Append copy. */
+ --j;
+ info[j] = info[k - 1];
+ pos[j] = pos[k - 1];
+ }
+ }
+ }
+ }
+
+ if (step == MEASURE)
+ {
+ if (unlikely (!buffer->ensure (count + extra_glyphs_needed)))
+ break;
+ }
+ else
+ {
+ assert (j == 0);
+ buffer->len = new_len;
+ }
+ }
+}
+
+
+static void
+postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ apply_stch (plan, buffer, font);
+}
+
+/* https://www.unicode.org/reports/tr53/ */
+
+static hb_codepoint_t
+modifier_combining_marks[] =
+{
+ 0x0654u, /* ARABIC HAMZA ABOVE */
+ 0x0655u, /* ARABIC HAMZA BELOW */
+ 0x0658u, /* ARABIC MARK NOON GHUNNA */
+ 0x06DCu, /* ARABIC SMALL HIGH SEEN */
+ 0x06E3u, /* ARABIC SMALL LOW SEEN */
+ 0x06E7u, /* ARABIC SMALL HIGH YEH */
+ 0x06E8u, /* ARABIC SMALL HIGH NOON */
+ 0x08CAu, /* ARABIC SMALL HIGH FARSI YEH */
+ 0x08CBu, /* ARABIC SMALL HIGH YEH BARREE WITH TWO DOTS BELOW */
+ 0x08CDu, /* ARABIC SMALL HIGH ZAH */
+ 0x08CEu, /* ARABIC LARGE ROUND DOT ABOVE */
+ 0x08CFu, /* ARABIC LARGE ROUND DOT BELOW */
+ 0x08D3u, /* ARABIC SMALL LOW WAW */
+ 0x08F3u, /* ARABIC SMALL HIGH WAW */
+};
+
+static inline bool
+info_is_mcm (const hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ for (unsigned int i = 0; i < ARRAY_LENGTH (modifier_combining_marks); i++)
+ if (u == modifier_combining_marks[i])
+ return true;
+ return false;
+}
+
+static void
+reorder_marks_arabic (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start,
+ unsigned int end)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ DEBUG_MSG (ARABIC, buffer, "Reordering marks from %d to %d", start, end);
+
+ unsigned int i = start;
+ for (unsigned int cc = 220; cc <= 230; cc += 10)
+ {
+ DEBUG_MSG (ARABIC, buffer, "Looking for %d's starting at %d", cc, i);
+ while (i < end && info_cc(info[i]) < cc)
+ i++;
+ DEBUG_MSG (ARABIC, buffer, "Looking for %d's stopped at %d", cc, i);
+
+ if (i == end)
+ break;
+
+ if (info_cc(info[i]) > cc)
+ continue;
+
+ unsigned int j = i;
+ while (j < end && info_cc(info[j]) == cc && info_is_mcm (info[j]))
+ j++;
+
+ if (i == j)
+ continue;
+
+ DEBUG_MSG (ARABIC, buffer, "Found %d's from %d to %d", cc, i, j);
+
+ /* Shift it! */
+ DEBUG_MSG (ARABIC, buffer, "Shifting %d's: %d %d", cc, i, j);
+ hb_glyph_info_t temp[HB_OT_SHAPE_MAX_COMBINING_MARKS];
+ assert (j - i <= ARRAY_LENGTH (temp));
+ buffer->merge_clusters (start, j);
+ memmove (temp, &info[i], (j - i) * sizeof (hb_glyph_info_t));
+ memmove (&info[start + j - i], &info[start], (i - start) * sizeof (hb_glyph_info_t));
+ memmove (&info[start], temp, (j - i) * sizeof (hb_glyph_info_t));
+
+ /* Renumber CC such that the reordered sequence is still sorted.
+ * 22 and 26 are chosen because they are smaller than all Arabic categories,
+ * and are folded back to 220/230 respectively during fallback mark positioning.
+ *
+ * We do this because the CGJ-handling logic in the normalizer relies on
+ * mark sequences having an increasing order even after this reordering.
+ * https://github.com/harfbuzz/harfbuzz/issues/554
+ * This, however, does break some obscure sequences, where the normalizer
+ * might compose a sequence that it should not. For example, in the seequence
+ * ALEF, HAMZAH, MADDAH, we should NOT try to compose ALEF+MADDAH, but with this
+ * renumbering, we will.
+ */
+ unsigned int new_start = start + j - i;
+ unsigned int new_cc = cc == 220 ? HB_MODIFIED_COMBINING_CLASS_CCC22 : HB_MODIFIED_COMBINING_CLASS_CCC26;
+ while (start < new_start)
+ {
+ _hb_glyph_info_set_modified_combining_class (&info[start], new_cc);
+ start++;
+ }
+
+ i = j;
+ }
+}
+
+const hb_ot_shaper_t _hb_ot_shaper_arabic =
+{
+ collect_features_arabic,
+ nullptr, /* override_features */
+ data_create_arabic,
+ data_destroy_arabic,
+ nullptr, /* preprocess_text */
+ postprocess_glyphs_arabic,
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ setup_masks_arabic,
+ reorder_marks_arabic,
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
+ true, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh
new file mode 100644
index 0000000000..a025b1a399
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-arabic.hh
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2015 Mozilla Foundation.
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_ARABIC_HH
+#define HB_OT_SHAPER_ARABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper.hh"
+
+
+struct arabic_shape_plan_t;
+
+HB_INTERNAL void *
+data_create_arabic (const hb_ot_shape_plan_t *plan);
+
+HB_INTERNAL void
+data_destroy_arabic (void *data);
+
+HB_INTERNAL void
+setup_masks_arabic_plan (const arabic_shape_plan_t *arabic_plan,
+ hb_buffer_t *buffer,
+ hb_script_t script);
+
+#endif /* HB_OT_SHAPER_ARABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
new file mode 100644
index 0000000000..2f6f499eec
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-default.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper.hh"
+
+
+const hb_ot_shaper_t _hb_ot_shaper_default =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ nullptr, /* setup_masks */
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
+ true, /* fallback_position */
+};
+
+/* Same as default but no mark advance zeroing / fallback positioning.
+ * Dumbest shaper ever, basically. */
+const hb_ot_shaper_t _hb_ot_shaper_dumber =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ nullptr, /* setup_masks */
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc
new file mode 100644
index 0000000000..c90476bc46
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hangul.cc
@@ -0,0 +1,436 @@
+/*
+ * Copyright © 2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper.hh"
+
+
+/* Hangul shaper */
+
+
+/* Same order as the feature array below */
+enum {
+ _JMO,
+
+ LJMO,
+ VJMO,
+ TJMO,
+
+ FIRST_HANGUL_FEATURE = LJMO,
+ HANGUL_FEATURE_COUNT = TJMO + 1
+};
+
+static const hb_tag_t hangul_features[HANGUL_FEATURE_COUNT] =
+{
+ HB_TAG_NONE,
+ HB_TAG('l','j','m','o'),
+ HB_TAG('v','j','m','o'),
+ HB_TAG('t','j','m','o')
+};
+
+static void
+collect_features_hangul (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ for (unsigned int i = FIRST_HANGUL_FEATURE; i < HANGUL_FEATURE_COUNT; i++)
+ map->add_feature (hangul_features[i]);
+}
+
+static void
+override_features_hangul (hb_ot_shape_planner_t *plan)
+{
+ /* Uniscribe does not apply 'calt' for Hangul, and certain fonts
+ * (Noto Sans CJK, Source Sans Han, etc) apply all of jamo lookups
+ * in calt, which is not desirable. */
+ plan->map.disable_feature (HB_TAG('c','a','l','t'));
+}
+
+struct hangul_shape_plan_t
+{
+ hb_mask_t mask_array[HANGUL_FEATURE_COUNT];
+};
+
+static void *
+data_create_hangul (const hb_ot_shape_plan_t *plan)
+{
+ hangul_shape_plan_t *hangul_plan = (hangul_shape_plan_t *) hb_calloc (1, sizeof (hangul_shape_plan_t));
+ if (unlikely (!hangul_plan))
+ return nullptr;
+
+ for (unsigned int i = 0; i < HANGUL_FEATURE_COUNT; i++)
+ hangul_plan->mask_array[i] = plan->map.get_1_mask (hangul_features[i]);
+
+ return hangul_plan;
+}
+
+static void
+data_destroy_hangul (void *data)
+{
+ hb_free (data);
+}
+
+/* Constants for algorithmic hangul syllable [de]composition. */
+#define LBase 0x1100u
+#define VBase 0x1161u
+#define TBase 0x11A7u
+#define LCount 19u
+#define VCount 21u
+#define TCount 28u
+#define SBase 0xAC00u
+#define NCount (VCount * TCount)
+#define SCount (LCount * NCount)
+
+#define isCombiningL(u) (hb_in_range<hb_codepoint_t> ((u), LBase, LBase+LCount-1))
+#define isCombiningV(u) (hb_in_range<hb_codepoint_t> ((u), VBase, VBase+VCount-1))
+#define isCombiningT(u) (hb_in_range<hb_codepoint_t> ((u), TBase+1, TBase+TCount-1))
+#define isCombinedS(u) (hb_in_range<hb_codepoint_t> ((u), SBase, SBase+SCount-1))
+
+#define isL(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1100u, 0x115Fu, 0xA960u, 0xA97Cu))
+#define isV(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x1160u, 0x11A7u, 0xD7B0u, 0xD7C6u))
+#define isT(u) (hb_in_ranges<hb_codepoint_t> ((u), 0x11A8u, 0x11FFu, 0xD7CBu, 0xD7FBu))
+
+#define isHangulTone(u) (hb_in_range<hb_codepoint_t> ((u), 0x302Eu, 0x302Fu))
+
+/* buffer var allocations */
+#define hangul_shaping_feature() ot_shaper_var_u8_auxiliary() /* hangul jamo shaping feature */
+
+static bool
+is_zero_width_char (hb_font_t *font,
+ hb_codepoint_t unicode)
+{
+ hb_codepoint_t glyph;
+ return hb_font_get_glyph (font, unicode, 0, &glyph) && hb_font_get_glyph_h_advance (font, glyph) == 0;
+}
+
+static void
+preprocess_text_hangul (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, hangul_shaping_feature);
+
+ /* Hangul syllables come in two shapes: LV, and LVT. Of those:
+ *
+ * - LV can be precomposed, or decomposed. Lets call those
+ * <LV> and <L,V>,
+ * - LVT can be fully precomposed, partially precomposed, or
+ * fully decomposed. Ie. <LVT>, <LV,T>, or <L,V,T>.
+ *
+ * The composition / decomposition is mechanical. However, not
+ * all <L,V> sequences compose, and not all <LV,T> sequences
+ * compose.
+ *
+ * Here are the specifics:
+ *
+ * - <L>: U+1100..115F, U+A960..A97F
+ * - <V>: U+1160..11A7, U+D7B0..D7C7
+ * - <T>: U+11A8..11FF, U+D7CB..D7FB
+ *
+ * - Only the <L,V> sequences for some of the U+11xx ranges combine.
+ * - Only <LV,T> sequences for some of the Ts in U+11xx range combine.
+ *
+ * Here is what we want to accomplish in this shaper:
+ *
+ * - If the whole syllable can be precomposed, do that,
+ * - Otherwise, fully decompose and apply ljmo/vjmo/tjmo features.
+ * - If a valid syllable is followed by a Hangul tone mark, reorder the tone
+ * mark to precede the whole syllable - unless it is a zero-width glyph, in
+ * which case we leave it untouched, assuming it's designed to overstrike.
+ *
+ * That is, of the different possible syllables:
+ *
+ * <L>
+ * <L,V>
+ * <L,V,T>
+ * <LV>
+ * <LVT>
+ * <LV, T>
+ *
+ * - <L> needs no work.
+ *
+ * - <LV> and <LVT> can stay the way they are if the font supports them, otherwise we
+ * should fully decompose them if font supports.
+ *
+ * - <L,V> and <L,V,T> we should compose if the whole thing can be composed.
+ *
+ * - <LV,T> we should compose if the whole thing can be composed, otherwise we should
+ * decompose.
+ */
+
+ buffer->clear_output ();
+ unsigned int start = 0, end = 0; /* Extent of most recently seen syllable;
+ * valid only if start < end
+ */
+ unsigned int count = buffer->len;
+
+ for (buffer->idx = 0; buffer->idx < count && buffer->successful;)
+ {
+ hb_codepoint_t u = buffer->cur().codepoint;
+
+ if (isHangulTone (u))
+ {
+ /*
+ * We could cache the width of the tone marks and the existence of dotted-circle,
+ * but the use of the Hangul tone mark characters seems to be rare enough that
+ * I didn't bother for now.
+ */
+ if (start < end && end == buffer->out_len)
+ {
+ /* Tone mark follows a valid syllable; move it in front, unless it's zero width. */
+ buffer->unsafe_to_break_from_outbuffer (start, buffer->idx);
+ if (unlikely (!buffer->next_glyph ())) break;
+ if (!is_zero_width_char (font, u))
+ {
+ buffer->merge_out_clusters (start, end + 1);
+ hb_glyph_info_t *info = buffer->out_info;
+ hb_glyph_info_t tone = info[end];
+ memmove (&info[start + 1], &info[start], (end - start) * sizeof (hb_glyph_info_t));
+ info[start] = tone;
+ }
+ }
+ else
+ {
+ /* No valid syllable as base for tone mark; try to insert dotted circle. */
+ if (!(buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE) &&
+ font->has_glyph (0x25CCu))
+ {
+ hb_codepoint_t chars[2];
+ if (!is_zero_width_char (font, u))
+ {
+ chars[0] = u;
+ chars[1] = 0x25CCu;
+ } else
+ {
+ chars[0] = 0x25CCu;
+ chars[1] = u;
+ }
+ (void) buffer->replace_glyphs (1, 2, chars);
+ }
+ else
+ {
+ /* No dotted circle available in the font; just leave tone mark untouched. */
+ (void) buffer->next_glyph ();
+ }
+ }
+ start = end = buffer->out_len;
+ continue;
+ }
+
+ start = buffer->out_len; /* Remember current position as a potential syllable start;
+ * will only be used if we set end to a later position.
+ */
+
+ if (isL (u) && buffer->idx + 1 < count)
+ {
+ hb_codepoint_t l = u;
+ hb_codepoint_t v = buffer->cur(+1).codepoint;
+ if (isV (v))
+ {
+ /* Have <L,V> or <L,V,T>. */
+ hb_codepoint_t t = 0;
+ unsigned int tindex = 0;
+ if (buffer->idx + 2 < count)
+ {
+ t = buffer->cur(+2).codepoint;
+ if (isT (t))
+ tindex = t - TBase; /* Only used if isCombiningT (t); otherwise invalid. */
+ else
+ t = 0; /* The next character was not a trailing jamo. */
+ }
+ buffer->unsafe_to_break (buffer->idx, buffer->idx + (t ? 3 : 2));
+
+ /* We've got a syllable <L,V,T?>; see if it can potentially be composed. */
+ if (isCombiningL (l) && isCombiningV (v) && (t == 0 || isCombiningT (t)))
+ {
+ /* Try to compose; if this succeeds, end is set to start+1. */
+ hb_codepoint_t s = SBase + (l - LBase) * NCount + (v - VBase) * TCount + tindex;
+ if (font->has_glyph (s))
+ {
+ (void) buffer->replace_glyphs (t ? 3 : 2, 1, &s);
+ end = start + 1;
+ continue;
+ }
+ }
+
+ /* We didn't compose, either because it's an Old Hangul syllable without a
+ * precomposed character in Unicode, or because the font didn't support the
+ * necessary precomposed glyph.
+ * Set jamo features on the individual glyphs, and advance past them.
+ */
+ buffer->cur().hangul_shaping_feature() = LJMO;
+ (void) buffer->next_glyph ();
+ buffer->cur().hangul_shaping_feature() = VJMO;
+ (void) buffer->next_glyph ();
+ if (t)
+ {
+ buffer->cur().hangul_shaping_feature() = TJMO;
+ (void) buffer->next_glyph ();
+ end = start + 3;
+ }
+ else
+ end = start + 2;
+ if (unlikely (!buffer->successful))
+ break;
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ buffer->merge_out_clusters (start, end);
+ continue;
+ }
+ }
+
+ else if (isCombinedS (u))
+ {
+ /* Have <LV>, <LVT>, or <LV,T> */
+ hb_codepoint_t s = u;
+ bool has_glyph = font->has_glyph (s);
+ unsigned int lindex = (s - SBase) / NCount;
+ unsigned int nindex = (s - SBase) % NCount;
+ unsigned int vindex = nindex / TCount;
+ unsigned int tindex = nindex % TCount;
+
+ if (!tindex &&
+ buffer->idx + 1 < count &&
+ isCombiningT (buffer->cur(+1).codepoint))
+ {
+ /* <LV,T>, try to combine. */
+ unsigned int new_tindex = buffer->cur(+1).codepoint - TBase;
+ hb_codepoint_t new_s = s + new_tindex;
+ if (font->has_glyph (new_s))
+ {
+ (void) buffer->replace_glyphs (2, 1, &new_s);
+ end = start + 1;
+ continue;
+ }
+ else
+ buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
+ }
+
+ /* Otherwise, decompose if font doesn't support <LV> or <LVT>,
+ * or if having non-combining <LV,T>. Note that we already handled
+ * combining <LV,T> above. */
+ if (!has_glyph ||
+ (!tindex &&
+ buffer->idx + 1 < count &&
+ isT (buffer->cur(+1).codepoint)))
+ {
+ hb_codepoint_t decomposed[3] = {LBase + lindex,
+ VBase + vindex,
+ TBase + tindex};
+ if (font->has_glyph (decomposed[0]) &&
+ font->has_glyph (decomposed[1]) &&
+ (!tindex || font->has_glyph (decomposed[2])))
+ {
+ unsigned int s_len = tindex ? 3 : 2;
+ (void) buffer->replace_glyphs (1, s_len, decomposed);
+
+ /* If we decomposed an LV because of a non-combining T following,
+ * we want to include this T in the syllable.
+ */
+ if (has_glyph && !tindex)
+ {
+ (void) buffer->next_glyph ();
+ s_len++;
+ }
+ if (unlikely (!buffer->successful))
+ break;
+
+ /* We decomposed S: apply jamo features to the individual glyphs
+ * that are now in buffer->out_info.
+ */
+ hb_glyph_info_t *info = buffer->out_info;
+ end = start + s_len;
+
+ unsigned int i = start;
+ info[i++].hangul_shaping_feature() = LJMO;
+ info[i++].hangul_shaping_feature() = VJMO;
+ if (i < end)
+ info[i++].hangul_shaping_feature() = TJMO;
+
+ if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ buffer->merge_out_clusters (start, end);
+ continue;
+ }
+ else if ((!tindex && buffer->idx + 1 < count && isT (buffer->cur(+1).codepoint)))
+ buffer->unsafe_to_break (buffer->idx, buffer->idx + 2); /* Mark unsafe between LV and T. */
+ }
+
+ if (has_glyph)
+ {
+ /* We didn't decompose the S, so just advance past it and fall through. */
+ end = start + 1;
+ }
+ }
+
+ /* Didn't find a recognizable syllable, so we leave end <= start;
+ * this will prevent tone-mark reordering happening.
+ */
+ (void) buffer->next_glyph ();
+ }
+ buffer->sync ();
+}
+
+static void
+setup_masks_hangul (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ const hangul_shape_plan_t *hangul_plan = (const hangul_shape_plan_t *) plan->data;
+
+ if (likely (hangul_plan))
+ {
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++, info++)
+ info->mask |= hangul_plan->mask_array[info->hangul_shaping_feature()];
+ }
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, hangul_shaping_feature);
+}
+
+
+const hb_ot_shaper_t _hb_ot_shaper_hangul =
+{
+ collect_features_hangul,
+ override_features_hangul,
+ data_create_hangul,
+ data_destroy_hangul,
+ preprocess_text_hangul,
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ setup_masks_hangul,
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc
new file mode 100644
index 0000000000..e18edd6b3f
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-hebrew.cc
@@ -0,0 +1,211 @@
+/*
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper.hh"
+
+
+static bool
+compose_hebrew (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ /* Hebrew presentation-form shaping.
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=728866
+ * Hebrew presentation forms with dagesh, for characters U+05D0..05EA;
+ * Note that some letters do not have a dagesh presForm encoded.
+ */
+ static const hb_codepoint_t sDageshForms[0x05EAu - 0x05D0u + 1] = {
+ 0xFB30u, /* ALEF */
+ 0xFB31u, /* BET */
+ 0xFB32u, /* GIMEL */
+ 0xFB33u, /* DALET */
+ 0xFB34u, /* HE */
+ 0xFB35u, /* VAV */
+ 0xFB36u, /* ZAYIN */
+ 0x0000u, /* HET */
+ 0xFB38u, /* TET */
+ 0xFB39u, /* YOD */
+ 0xFB3Au, /* FINAL KAF */
+ 0xFB3Bu, /* KAF */
+ 0xFB3Cu, /* LAMED */
+ 0x0000u, /* FINAL MEM */
+ 0xFB3Eu, /* MEM */
+ 0x0000u, /* FINAL NUN */
+ 0xFB40u, /* NUN */
+ 0xFB41u, /* SAMEKH */
+ 0x0000u, /* AYIN */
+ 0xFB43u, /* FINAL PE */
+ 0xFB44u, /* PE */
+ 0x0000u, /* FINAL TSADI */
+ 0xFB46u, /* TSADI */
+ 0xFB47u, /* QOF */
+ 0xFB48u, /* RESH */
+ 0xFB49u, /* SHIN */
+ 0xFB4Au /* TAV */
+ };
+
+ bool found = (bool) c->unicode->compose (a, b, ab);
+
+#ifdef HB_NO_OT_SHAPER_HEBREW_FALLBACK
+ return found;
+#endif
+
+ if (!found && !c->plan->has_gpos_mark)
+ {
+ /* Special-case Hebrew presentation forms that are excluded from
+ * standard normalization, but wanted for old fonts. */
+ switch (b) {
+ case 0x05B4u: /* HIRIQ */
+ if (a == 0x05D9u) { /* YOD */
+ *ab = 0xFB1Du;
+ found = true;
+ }
+ break;
+ case 0x05B7u: /* PATAH */
+ if (a == 0x05F2u) { /* YIDDISH YOD YOD */
+ *ab = 0xFB1Fu;
+ found = true;
+ } else if (a == 0x05D0u) { /* ALEF */
+ *ab = 0xFB2Eu;
+ found = true;
+ }
+ break;
+ case 0x05B8u: /* QAMATS */
+ if (a == 0x05D0u) { /* ALEF */
+ *ab = 0xFB2Fu;
+ found = true;
+ }
+ break;
+ case 0x05B9u: /* HOLAM */
+ if (a == 0x05D5u) { /* VAV */
+ *ab = 0xFB4Bu;
+ found = true;
+ }
+ break;
+ case 0x05BCu: /* DAGESH */
+ if (a >= 0x05D0u && a <= 0x05EAu) {
+ *ab = sDageshForms[a - 0x05D0u];
+ found = (*ab != 0);
+ } else if (a == 0xFB2Au) { /* SHIN WITH SHIN DOT */
+ *ab = 0xFB2Cu;
+ found = true;
+ } else if (a == 0xFB2Bu) { /* SHIN WITH SIN DOT */
+ *ab = 0xFB2Du;
+ found = true;
+ }
+ break;
+ case 0x05BFu: /* RAFE */
+ switch (a) {
+ case 0x05D1u: /* BET */
+ *ab = 0xFB4Cu;
+ found = true;
+ break;
+ case 0x05DBu: /* KAF */
+ *ab = 0xFB4Du;
+ found = true;
+ break;
+ case 0x05E4u: /* PE */
+ *ab = 0xFB4Eu;
+ found = true;
+ break;
+ }
+ break;
+ case 0x05C1u: /* SHIN DOT */
+ if (a == 0x05E9u) { /* SHIN */
+ *ab = 0xFB2Au;
+ found = true;
+ } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+ *ab = 0xFB2Cu;
+ found = true;
+ }
+ break;
+ case 0x05C2u: /* SIN DOT */
+ if (a == 0x05E9u) { /* SHIN */
+ *ab = 0xFB2Bu;
+ found = true;
+ } else if (a == 0xFB49u) { /* SHIN WITH DAGESH */
+ *ab = 0xFB2Du;
+ found = true;
+ }
+ break;
+ }
+ }
+
+ return found;
+}
+
+static void
+reorder_marks_hebrew (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start,
+ unsigned int end)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ for (unsigned i = start + 2; i < end; i++)
+ {
+ unsigned c0 = info_cc (info[i - 2]);
+ unsigned c1 = info_cc (info[i - 1]);
+ unsigned c2 = info_cc (info[i - 0]);
+
+ if ((c0 == HB_MODIFIED_COMBINING_CLASS_CCC17 || c0 == HB_MODIFIED_COMBINING_CLASS_CCC18) /* patach or qamats */ &&
+ (c1 == HB_MODIFIED_COMBINING_CLASS_CCC10 || c1 == HB_MODIFIED_COMBINING_CLASS_CCC14) /* sheva or hiriq */ &&
+ (c2 == HB_MODIFIED_COMBINING_CLASS_CCC22 || c2 == HB_UNICODE_COMBINING_CLASS_BELOW) /* meteg or below */)
+ {
+ buffer->merge_clusters (i - 1, i + 1);
+ hb_swap (info[i - 1], info[i]);
+ break;
+ }
+ }
+
+
+}
+
+const hb_ot_shaper_t _hb_ot_shaper_hebrew =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ compose_hebrew,
+ nullptr, /* setup_masks */
+ reorder_marks_hebrew,
+ HB_TAG ('h','e','b','r'), /* gpos_tag. https://github.com/harfbuzz/harfbuzz/issues/347#issuecomment-267838368 */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
+ true, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
new file mode 100644
index 0000000000..d3a7cce3de
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-machine.hh
@@ -0,0 +1,589 @@
+
+#line 1 "hb-ot-shaper-indic-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_INDIC_MACHINE_HH
+#define HB_OT_SHAPER_INDIC_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define indic_category() ot_shaper_var_u8_category() /* indic_category_t */
+#define indic_position() ot_shaper_var_u8_auxiliary() /* indic_position_t */
+
+using indic_category_t = unsigned;
+using indic_position_t = ot_position_t;
+
+#define I_Cat(Cat) indic_syllable_machine_ex_##Cat
+
+enum indic_syllable_type_t {
+ indic_consonant_syllable,
+ indic_vowel_syllable,
+ indic_standalone_cluster,
+ indic_symbol_cluster,
+ indic_broken_cluster,
+ indic_non_indic_cluster,
+};
+
+
+#line 54 "hb-ot-shaper-indic-machine.hh"
+#define indic_syllable_machine_ex_A 9u
+#define indic_syllable_machine_ex_C 1u
+#define indic_syllable_machine_ex_CM 16u
+#define indic_syllable_machine_ex_CS 18u
+#define indic_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define indic_syllable_machine_ex_H 4u
+#define indic_syllable_machine_ex_M 7u
+#define indic_syllable_machine_ex_N 3u
+#define indic_syllable_machine_ex_PLACEHOLDER 10u
+#define indic_syllable_machine_ex_RS 12u
+#define indic_syllable_machine_ex_Ra 15u
+#define indic_syllable_machine_ex_Repha 14u
+#define indic_syllable_machine_ex_SM 8u
+#define indic_syllable_machine_ex_Symbol 17u
+#define indic_syllable_machine_ex_V 2u
+#define indic_syllable_machine_ex_VD 9u
+#define indic_syllable_machine_ex_X 0u
+#define indic_syllable_machine_ex_ZWJ 6u
+#define indic_syllable_machine_ex_ZWNJ 5u
+
+
+#line 74 "hb-ot-shaper-indic-machine.hh"
+static const unsigned char _indic_syllable_machine_trans_keys[] = {
+ 8u, 8u, 4u, 8u, 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 8u, 8u, 8u,
+ 5u, 7u, 5u, 8u, 4u, 8u, 4u, 12u, 4u, 12u, 4u, 12u, 8u, 8u, 5u, 7u,
+ 5u, 8u, 4u, 8u, 4u, 8u, 4u, 12u, 8u, 8u, 5u, 7u, 5u, 8u, 4u, 8u,
+ 4u, 8u, 5u, 8u, 8u, 8u, 1u, 18u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u,
+ 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 1u, 15u, 3u, 9u,
+ 4u, 9u, 5u, 9u, 4u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u,
+ 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u,
+ 5u, 9u, 9u, 9u, 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u,
+ 4u, 9u, 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 3u, 16u, 4u, 8u,
+ 3u, 16u, 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u,
+ 5u, 9u, 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u,
+ 5u, 9u, 5u, 9u, 3u, 9u, 5u, 9u, 3u, 16u, 4u, 12u, 4u, 8u, 3u, 16u,
+ 3u, 16u, 4u, 16u, 1u, 15u, 3u, 16u, 1u, 15u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 1u, 15u, 3u, 9u, 4u, 9u, 5u, 9u, 3u, 16u, 4u, 9u, 5u, 9u,
+ 5u, 9u, 3u, 9u, 5u, 9u, 1u, 16u, 3u, 16u, 1u, 16u, 4u, 12u, 5u, 9u,
+ 9u, 9u, 5u, 9u, 1u, 15u, 3u, 9u, 5u, 9u, 5u, 9u, 9u, 9u, 5u, 9u,
+ 1u, 15u, 0
+};
+
+static const char _indic_syllable_machine_key_spans[] = {
+ 1, 5, 3, 4, 5, 9, 5, 1,
+ 3, 4, 5, 9, 9, 9, 1, 3,
+ 4, 5, 5, 9, 1, 3, 4, 5,
+ 5, 4, 1, 18, 14, 14, 13, 15,
+ 5, 5, 1, 5, 15, 15, 15, 7,
+ 6, 5, 6, 5, 7, 5, 14, 14,
+ 14, 14, 13, 15, 14, 14, 13, 15,
+ 5, 1, 5, 15, 15, 7, 6, 5,
+ 6, 5, 5, 7, 5, 14, 14, 5,
+ 14, 14, 13, 15, 14, 15, 5, 1,
+ 5, 15, 15, 7, 6, 5, 14, 6,
+ 5, 5, 7, 5, 14, 9, 5, 14,
+ 14, 13, 15, 14, 15, 5, 1, 5,
+ 15, 15, 7, 6, 5, 14, 6, 5,
+ 5, 7, 5, 16, 14, 16, 9, 5,
+ 1, 5, 15, 7, 5, 5, 1, 5,
+ 15
+};
+
+static const short _indic_syllable_machine_index_offsets[] = {
+ 0, 2, 8, 12, 17, 23, 33, 39,
+ 41, 45, 50, 56, 66, 76, 86, 88,
+ 92, 97, 103, 109, 119, 121, 125, 130,
+ 136, 142, 147, 149, 168, 183, 198, 212,
+ 228, 234, 240, 242, 248, 264, 280, 296,
+ 304, 311, 317, 324, 330, 338, 344, 359,
+ 374, 389, 404, 418, 434, 449, 464, 478,
+ 494, 500, 502, 508, 524, 540, 548, 555,
+ 561, 568, 574, 580, 588, 594, 609, 624,
+ 630, 645, 660, 674, 690, 705, 721, 727,
+ 729, 735, 751, 767, 775, 782, 788, 803,
+ 810, 816, 822, 830, 836, 851, 861, 867,
+ 882, 897, 911, 927, 942, 958, 964, 966,
+ 972, 988, 1004, 1012, 1019, 1025, 1040, 1047,
+ 1053, 1059, 1067, 1073, 1090, 1105, 1122, 1132,
+ 1138, 1140, 1146, 1162, 1170, 1176, 1182, 1184,
+ 1190
+};
+
+static const unsigned char _indic_syllable_machine_indicies[] = {
+ 1, 0, 2, 3, 3, 4, 1, 0,
+ 3, 3, 4, 0, 3, 3, 4, 1,
+ 0, 5, 3, 3, 4, 1, 0, 2,
+ 3, 3, 4, 1, 0, 0, 0, 6,
+ 0, 8, 9, 9, 10, 11, 7, 11,
+ 7, 9, 9, 10, 7, 9, 9, 10,
+ 11, 7, 12, 9, 9, 10, 11, 7,
+ 8, 9, 9, 10, 11, 7, 7, 7,
+ 13, 7, 8, 9, 9, 10, 11, 7,
+ 7, 7, 14, 7, 16, 17, 17, 18,
+ 19, 15, 15, 15, 20, 15, 19, 15,
+ 17, 17, 18, 21, 17, 17, 18, 19,
+ 15, 16, 17, 17, 18, 19, 15, 22,
+ 17, 17, 18, 19, 15, 24, 25, 25,
+ 26, 27, 23, 23, 23, 28, 23, 27,
+ 23, 25, 25, 26, 23, 25, 25, 26,
+ 27, 23, 24, 25, 25, 26, 27, 23,
+ 29, 25, 25, 26, 27, 23, 17, 17,
+ 18, 1, 0, 31, 30, 33, 34, 35,
+ 36, 37, 38, 18, 19, 39, 40, 40,
+ 20, 32, 41, 42, 43, 44, 45, 32,
+ 47, 48, 49, 50, 4, 1, 51, 46,
+ 46, 6, 46, 46, 46, 52, 46, 53,
+ 48, 54, 54, 4, 1, 51, 46, 46,
+ 46, 46, 46, 46, 52, 46, 48, 54,
+ 54, 4, 1, 51, 46, 46, 46, 46,
+ 46, 46, 52, 46, 33, 46, 46, 46,
+ 55, 56, 46, 1, 51, 46, 46, 46,
+ 46, 46, 33, 46, 57, 57, 46, 1,
+ 51, 46, 51, 46, 46, 58, 51, 46,
+ 51, 46, 51, 46, 46, 46, 51, 46,
+ 33, 46, 59, 46, 57, 57, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 33, 46, 46, 46, 57, 57, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 33, 46, 46, 46, 57, 56, 46, 1,
+ 51, 46, 46, 46, 46, 46, 33, 46,
+ 60, 61, 62, 62, 4, 1, 51, 46,
+ 61, 62, 62, 4, 1, 51, 46, 62,
+ 62, 4, 1, 51, 46, 63, 64, 64,
+ 4, 1, 51, 46, 55, 65, 46, 1,
+ 51, 46, 55, 46, 57, 57, 46, 1,
+ 51, 46, 57, 65, 46, 1, 51, 46,
+ 47, 48, 54, 54, 4, 1, 51, 46,
+ 46, 46, 46, 46, 46, 52, 46, 47,
+ 48, 49, 54, 4, 1, 51, 46, 46,
+ 6, 46, 46, 46, 52, 46, 67, 68,
+ 69, 70, 10, 11, 71, 66, 66, 14,
+ 66, 66, 66, 72, 66, 73, 68, 74,
+ 70, 10, 11, 71, 66, 66, 66, 66,
+ 66, 66, 72, 66, 68, 74, 70, 10,
+ 11, 71, 66, 66, 66, 66, 66, 66,
+ 72, 66, 75, 66, 66, 66, 76, 77,
+ 66, 11, 71, 66, 66, 66, 66, 66,
+ 75, 66, 78, 68, 79, 80, 10, 11,
+ 71, 66, 66, 13, 66, 66, 66, 72,
+ 66, 81, 68, 74, 74, 10, 11, 71,
+ 66, 66, 66, 66, 66, 66, 72, 66,
+ 68, 74, 74, 10, 11, 71, 66, 66,
+ 66, 66, 66, 66, 72, 66, 75, 66,
+ 66, 66, 82, 77, 66, 11, 71, 66,
+ 66, 66, 66, 66, 75, 66, 71, 66,
+ 66, 83, 71, 66, 71, 66, 71, 66,
+ 66, 66, 71, 66, 75, 66, 84, 66,
+ 82, 82, 66, 11, 71, 66, 66, 66,
+ 66, 66, 75, 66, 75, 66, 66, 66,
+ 82, 82, 66, 11, 71, 66, 66, 66,
+ 66, 66, 75, 66, 85, 86, 87, 87,
+ 10, 11, 71, 66, 86, 87, 87, 10,
+ 11, 71, 66, 87, 87, 10, 11, 71,
+ 66, 88, 89, 89, 10, 11, 71, 66,
+ 76, 90, 66, 11, 71, 66, 82, 82,
+ 66, 11, 71, 66, 76, 66, 82, 82,
+ 66, 11, 71, 66, 82, 90, 66, 11,
+ 71, 66, 78, 68, 74, 74, 10, 11,
+ 71, 66, 66, 66, 66, 66, 66, 72,
+ 66, 78, 68, 79, 74, 10, 11, 71,
+ 66, 66, 13, 66, 66, 66, 72, 66,
+ 8, 9, 9, 10, 11, 66, 67, 68,
+ 74, 70, 10, 11, 71, 66, 66, 66,
+ 66, 66, 66, 72, 66, 92, 36, 93,
+ 93, 18, 19, 39, 91, 91, 91, 91,
+ 91, 91, 43, 91, 36, 93, 93, 18,
+ 19, 39, 91, 91, 91, 91, 91, 91,
+ 43, 91, 94, 91, 91, 91, 95, 96,
+ 91, 19, 39, 91, 91, 91, 91, 91,
+ 94, 91, 35, 36, 97, 98, 18, 19,
+ 39, 91, 91, 20, 91, 91, 91, 43,
+ 91, 94, 91, 91, 91, 99, 96, 91,
+ 19, 39, 91, 91, 91, 91, 91, 94,
+ 91, 39, 91, 91, 100, 39, 91, 39,
+ 91, 39, 91, 91, 91, 39, 91, 94,
+ 91, 101, 91, 99, 99, 91, 19, 39,
+ 91, 91, 91, 91, 91, 94, 91, 94,
+ 91, 91, 91, 99, 99, 91, 19, 39,
+ 91, 91, 91, 91, 91, 94, 91, 102,
+ 103, 104, 104, 18, 19, 39, 91, 103,
+ 104, 104, 18, 19, 39, 91, 104, 104,
+ 18, 19, 39, 91, 35, 36, 93, 93,
+ 18, 19, 39, 91, 91, 91, 91, 91,
+ 91, 43, 91, 105, 106, 106, 18, 19,
+ 39, 91, 95, 107, 91, 19, 39, 91,
+ 99, 99, 91, 19, 39, 91, 95, 91,
+ 99, 99, 91, 19, 39, 91, 99, 107,
+ 91, 19, 39, 91, 35, 36, 97, 93,
+ 18, 19, 39, 91, 91, 20, 91, 91,
+ 91, 43, 91, 16, 17, 17, 18, 19,
+ 108, 108, 108, 20, 108, 16, 17, 17,
+ 18, 19, 108, 110, 111, 112, 113, 26,
+ 27, 114, 109, 109, 28, 109, 109, 109,
+ 115, 109, 116, 111, 113, 113, 26, 27,
+ 114, 109, 109, 109, 109, 109, 109, 115,
+ 109, 111, 113, 113, 26, 27, 114, 109,
+ 109, 109, 109, 109, 109, 115, 109, 117,
+ 109, 109, 109, 118, 119, 109, 27, 114,
+ 109, 109, 109, 109, 109, 117, 109, 110,
+ 111, 112, 40, 26, 27, 114, 109, 109,
+ 28, 109, 109, 109, 115, 109, 117, 109,
+ 109, 109, 120, 119, 109, 27, 114, 109,
+ 109, 109, 109, 109, 117, 109, 114, 109,
+ 109, 121, 114, 109, 114, 109, 114, 109,
+ 109, 109, 114, 109, 117, 109, 122, 109,
+ 120, 120, 109, 27, 114, 109, 109, 109,
+ 109, 109, 117, 109, 117, 109, 109, 109,
+ 120, 120, 109, 27, 114, 109, 109, 109,
+ 109, 109, 117, 109, 123, 124, 125, 125,
+ 26, 27, 114, 109, 124, 125, 125, 26,
+ 27, 114, 109, 125, 125, 26, 27, 114,
+ 109, 110, 111, 113, 113, 26, 27, 114,
+ 109, 109, 109, 109, 109, 109, 115, 109,
+ 126, 127, 127, 26, 27, 114, 109, 118,
+ 128, 109, 27, 114, 109, 120, 120, 109,
+ 27, 114, 109, 118, 109, 120, 120, 109,
+ 27, 114, 109, 120, 128, 109, 27, 114,
+ 109, 33, 34, 35, 36, 97, 93, 18,
+ 19, 39, 40, 40, 20, 91, 91, 33,
+ 43, 91, 47, 129, 49, 50, 4, 1,
+ 51, 46, 46, 6, 46, 46, 46, 52,
+ 46, 33, 34, 35, 36, 130, 131, 18,
+ 132, 133, 46, 40, 20, 46, 46, 33,
+ 43, 46, 16, 134, 134, 18, 132, 51,
+ 46, 46, 20, 46, 133, 46, 46, 135,
+ 133, 46, 133, 46, 133, 46, 46, 46,
+ 133, 46, 33, 46, 59, 16, 134, 134,
+ 18, 132, 51, 46, 46, 46, 46, 46,
+ 33, 46, 137, 136, 138, 138, 136, 31,
+ 139, 136, 138, 138, 136, 31, 139, 136,
+ 139, 136, 136, 140, 139, 136, 139, 136,
+ 139, 136, 136, 136, 139, 136, 33, 108,
+ 108, 108, 108, 108, 108, 108, 108, 40,
+ 108, 108, 108, 108, 33, 108, 0
+};
+
+static const unsigned char _indic_syllable_machine_trans_targs[] = {
+ 27, 33, 38, 2, 39, 45, 46, 27,
+ 55, 8, 61, 56, 68, 69, 72, 27,
+ 77, 15, 83, 78, 86, 27, 91, 27,
+ 100, 21, 106, 101, 109, 114, 27, 125,
+ 27, 28, 48, 73, 75, 93, 94, 79,
+ 95, 115, 116, 87, 123, 128, 27, 29,
+ 31, 5, 47, 34, 42, 30, 1, 32,
+ 36, 0, 35, 37, 40, 41, 3, 43,
+ 4, 44, 27, 49, 51, 12, 71, 57,
+ 64, 50, 6, 52, 66, 59, 53, 11,
+ 70, 54, 7, 58, 60, 62, 63, 9,
+ 65, 10, 67, 27, 74, 17, 76, 89,
+ 81, 13, 92, 14, 80, 82, 84, 85,
+ 16, 88, 18, 90, 27, 27, 96, 98,
+ 19, 23, 102, 110, 97, 99, 112, 104,
+ 20, 103, 105, 107, 108, 22, 111, 24,
+ 113, 117, 118, 122, 119, 120, 25, 121,
+ 27, 124, 26, 126, 127
+};
+
+static const char _indic_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 0, 2, 2, 2, 3,
+ 2, 0, 2, 0, 2, 2, 2, 4,
+ 2, 0, 5, 0, 5, 6, 2, 7,
+ 2, 0, 2, 0, 2, 2, 8, 0,
+ 11, 2, 2, 5, 0, 12, 12, 0,
+ 2, 5, 2, 5, 2, 0, 13, 2,
+ 0, 0, 2, 0, 2, 2, 0, 2,
+ 2, 0, 0, 2, 2, 2, 0, 0,
+ 0, 2, 14, 2, 0, 0, 2, 0,
+ 2, 2, 0, 2, 2, 2, 2, 0,
+ 2, 2, 0, 0, 2, 2, 2, 0,
+ 0, 0, 2, 15, 5, 0, 5, 2,
+ 2, 0, 5, 0, 0, 2, 5, 5,
+ 0, 0, 0, 2, 16, 17, 2, 0,
+ 0, 0, 0, 2, 2, 2, 2, 2,
+ 0, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 18, 18, 0, 0, 0, 0,
+ 19, 2, 0, 0, 0
+};
+
+static const char _indic_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const char _indic_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0
+};
+
+static const short _indic_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 8, 8,
+ 8, 8, 8, 8, 8, 16, 16, 22,
+ 16, 16, 16, 24, 24, 24, 24, 24,
+ 24, 1, 31, 0, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 92, 92, 109, 109, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 92, 47, 47, 47, 47,
+ 47, 47, 47, 137, 137, 137, 137, 137,
+ 109
+};
+
+static const int indic_syllable_machine_start = 27;
+static const int indic_syllable_machine_first_final = 27;
+static const int indic_syllable_machine_error = -1;
+
+static const int indic_syllable_machine_en_main = 27;
+
+
+#line 58 "hb-ot-shaper-indic-machine.rl"
+
+
+
+#line 117 "hb-ot-shaper-indic-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_indic (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 415 "hb-ot-shaper-indic-machine.hh"
+ {
+ cs = indic_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 137 "hb-ot-shaper-indic-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 427 "hb-ot-shaper-indic-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _indic_syllable_machine_from_state_actions[cs] ) {
+ case 10:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 439 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ _keys = _indic_syllable_machine_trans_keys + (cs<<1);
+ _inds = _indic_syllable_machine_indicies + _indic_syllable_machine_index_offsets[cs];
+
+ _slen = _indic_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].indic_category()) &&
+ ( info[p].indic_category()) <= _keys[1] ?
+ ( info[p].indic_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _indic_syllable_machine_trans_targs[_trans];
+
+ if ( _indic_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _indic_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 11:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {te = p+1;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 13:
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 14:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 17:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 19:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 15:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 16:
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {te = p;p--;{ found_syllable (indic_non_indic_cluster); }}
+ break;
+ case 1:
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_consonant_syllable); }}
+ break;
+ case 3:
+#line 109 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_vowel_syllable); }}
+ break;
+ case 7:
+#line 110 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_standalone_cluster); }}
+ break;
+ case 8:
+#line 111 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_symbol_cluster); }}
+ break;
+ case 4:
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 6:
+#line 1 "NONE"
+ { switch( act ) {
+ case 1:
+ {{p = ((te))-1;} found_syllable (indic_consonant_syllable); }
+ break;
+ case 5:
+ {{p = ((te))-1;} found_syllable (indic_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 6:
+ {{p = ((te))-1;} found_syllable (indic_non_indic_cluster); }
+ break;
+ }
+ }
+ break;
+ case 18:
+#line 1 "NONE"
+ {te = p+1;}
+#line 108 "hb-ot-shaper-indic-machine.rl"
+ {act = 1;}
+ break;
+ case 5:
+#line 1 "NONE"
+ {te = p+1;}
+#line 112 "hb-ot-shaper-indic-machine.rl"
+ {act = 5;}
+ break;
+ case 12:
+#line 1 "NONE"
+ {te = p+1;}
+#line 113 "hb-ot-shaper-indic-machine.rl"
+ {act = 6;}
+ break;
+#line 521 "hb-ot-shaper-indic-machine.hh"
+ }
+
+_again:
+ switch ( _indic_syllable_machine_to_state_actions[cs] ) {
+ case 9:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 528 "hb-ot-shaper-indic-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _indic_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _indic_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 145 "hb-ot-shaper-indic-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_INDIC_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
new file mode 100644
index 0000000000..8994f3ca59
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic-table.cc
@@ -0,0 +1,560 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-indic-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt Blocks.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # IndicPositionalCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-indic.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-myanmar-machine.hh"
+
+/* indic */
+#define OT_X I_Cat(X)
+#define OT_C I_Cat(C)
+#define OT_V I_Cat(V)
+#define OT_N I_Cat(N)
+#define OT_H I_Cat(H)
+#define OT_ZWNJ I_Cat(ZWNJ)
+#define OT_ZWJ I_Cat(ZWJ)
+#define OT_M I_Cat(M)
+#define OT_SM I_Cat(SM)
+#define OT_A I_Cat(A)
+#define OT_VD I_Cat(VD)
+#define OT_PLACEHOLDER I_Cat(PLACEHOLDER)
+#define OT_DOTTEDCIRCLE I_Cat(DOTTEDCIRCLE)
+#define OT_RS I_Cat(RS)
+#define OT_Repha I_Cat(Repha)
+#define OT_Ra I_Cat(Ra)
+#define OT_CM I_Cat(CM)
+#define OT_Symbol I_Cat(Symbol)
+#define OT_CS I_Cat(CS)
+/* khmer */
+#define OT_VAbv K_Cat(VAbv)
+#define OT_VBlw K_Cat(VBlw)
+#define OT_VPre K_Cat(VPre)
+#define OT_VPst K_Cat(VPst)
+#define OT_Robatic K_Cat(Robatic)
+#define OT_Xgroup K_Cat(Xgroup)
+#define OT_Ygroup K_Cat(Ygroup)
+/* myanmar */
+static_assert (OT_VAbv == M_Cat(VAbv), "");
+static_assert (OT_VBlw == M_Cat(VBlw), "");
+static_assert (OT_VPre == M_Cat(VPre), "");
+static_assert (OT_VPst == M_Cat(VPst), "");
+#define OT_IV M_Cat(IV)
+#define OT_As M_Cat(As)
+#define OT_DB M_Cat(DB)
+#define OT_GB M_Cat(GB)
+#define OT_MH M_Cat(MH)
+#define OT_MR M_Cat(MR)
+#define OT_MW M_Cat(MW)
+#define OT_MY M_Cat(MY)
+#define OT_PT M_Cat(PT)
+#define OT_VS M_Cat(VS)
+#define OT_ML M_Cat(ML)
+
+
+#define _OT_A OT_A /* 53 chars; A */
+#define _OT_As OT_As /* 1 chars; As */
+#define _OT_C OT_C /* 478 chars; C */
+#define _OT_CM OT_CM /* 1 chars; CM */
+#define _OT_CS OT_CS /* 2 chars; CS */
+#define _OT_DC OT_DOTTEDCIRCLE /* 1 chars; DOTTEDCIRCLE */
+#define _OT_H OT_H /* 11 chars; H */
+#define _OT_M OT_M /* 143 chars; M */
+#define _OT_MH OT_MH /* 1 chars; MH */
+#define _OT_ML OT_ML /* 1 chars; ML */
+#define _OT_MR OT_MR /* 1 chars; MR */
+#define _OT_MW OT_MW /* 2 chars; MW */
+#define _OT_MY OT_MY /* 3 chars; MY */
+#define _OT_N OT_N /* 17 chars; N */
+#define _OT_GB OT_PLACEHOLDER /* 165 chars; PLACEHOLDER */
+#define _OT_PT OT_PT /* 8 chars; PT */
+#define _OT_R OT_Ra /* 14 chars; Ra */
+#define _OT_Rf OT_Repha /* 1 chars; Repha */
+#define _OT_Rt OT_Robatic /* 3 chars; Robatic */
+#define _OT_SM OT_SM /* 55 chars; SM */
+#define _OT_S OT_Symbol /* 22 chars; Symbol */
+#define _OT_V OT_V /* 172 chars; V */
+#define _OT_VA OT_VAbv /* 18 chars; VAbv */
+#define _OT_VB OT_VBlw /* 7 chars; VBlw */
+#define _OT_VL OT_VPre /* 5 chars; VPre */
+#define _OT_VR OT_VPst /* 13 chars; VPst */
+#define _OT_VS OT_VS /* 16 chars; VS */
+#define _OT_X OT_X /* 2 chars; X */
+#define _OT_Xg OT_Xgroup /* 7 chars; Xgroup */
+#define _OT_Yg OT_Ygroup /* 4 chars; Ygroup */
+#define _OT_ZWJ OT_ZWJ /* 1 chars; ZWJ */
+#define _OT_ZWNJ OT_ZWNJ /* 1 chars; ZWNJ */
+
+#define _POS_T POS_ABOVE_C /* 22 chars; ABOVE_C */
+#define _POS_A POS_AFTER_MAIN /* 3 chars; AFTER_MAIN */
+#define _POS_AP POS_AFTER_POST /* 50 chars; AFTER_POST */
+#define _POS_AS POS_AFTER_SUB /* 51 chars; AFTER_SUB */
+#define _POS_C POS_BASE_C /* 833 chars; BASE_C */
+#define _POS_BS POS_BEFORE_SUB /* 25 chars; BEFORE_SUB */
+#define _POS_B POS_BELOW_C /* 13 chars; BELOW_C */
+#define _POS_X POS_END /* 71 chars; END */
+#define _POS_R POS_POST_C /* 13 chars; POST_C */
+#define _POS_L POS_PRE_C /* 5 chars; PRE_C */
+#define _POS_LM POS_PRE_M /* 14 chars; PRE_M */
+#define _POS_SM POS_SMVD /* 129 chars; SMVD */
+
+#pragma GCC diagnostic pop
+
+#define INDIC_COMBINE_CATEGORIES(S,M) ((S) | ((M) << 8))
+
+#define _(S,M) INDIC_COMBINE_CATEGORIES (_OT_##S, _POS_##M)
+
+
+static const uint16_t indic_table[] = {
+
+
+#define indic_offset_0x0028u 0
+
+
+ /* Basic Latin */
+
+ /* 0028 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X),
+ /* 0030 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0038 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x00b0u 24
+
+
+ /* Latin-1 Supplement */
+
+ /* 00B0 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00B8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00C8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 00D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C),
+
+#define indic_offset_0x0900u 64
+
+
+ /* Devanagari */
+
+ /* 0900 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0908 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0910 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0918 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0920 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0928 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0930 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0938 */ _(C,C), _(C,C), _(M,AS), _(M,AS), _(N,X), _(S,SM), _(M,AS), _(M,LM),
+ /* 0940 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS),
+ /* 0948 */ _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(H,B), _(M,LM), _(M,AS),
+ /* 0950 */ _(X,X), _(A,SM), _(A,SM),_(SM,SM),_(SM,SM), _(M,AS), _(M,AS), _(M,AS),
+ /* 0958 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0960 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0968 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0970 */ _(X,X), _(X,X), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 0978 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+ /* Bengali */
+
+ /* 0980 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0988 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0990 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0998 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09A8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 09B0 */ _(R,C), _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 09B8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 09C0 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 09C8 */ _(M,LM), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(C,C), _(X,X),
+ /* 09D0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 09D8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 09E0 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 09E8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 09F0 */ _(R,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 09F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(X,X),_(SM,SM), _(X,X),
+
+ /* Gurmukhi */
+
+ /* 0A00 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A08 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0A10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0A30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0A38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(X,X), _(M,AP), _(M,LM),
+ /* 0A40 */ _(M,AP), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0A48 */ _(M,AP), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0A50 */ _(X,X), _(M,B), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0A58 */ _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X),
+ /* 0A60 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0A68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0A70 */_(SM,SM),_(SM,SM), _(C,C), _(C,C), _(X,X), _(CM,C), _(X,X), _(X,X),
+ /* 0A78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Gujarati */
+
+ /* 0A80 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0A88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C),
+ /* 0A90 */ _(V,C), _(V,C), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0A98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0AB0 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0AB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,LM),
+ /* 0AC0 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AS), _(X,X), _(M,AS),
+ /* 0AC8 */ _(M,AS), _(M,AP), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0AD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AE0 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0AE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0AF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0AF8 */ _(X,X), _(C,C), _(A,SM), _(N,X), _(A,SM), _(N,X), _(N,X), _(N,X),
+
+ /* Oriya */
+
+ /* 0B00 */ _(X,X),_(SM,BS),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(V,C),
+ /* 0B10 */ _(V,C), _(X,X), _(X,X), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0B18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0B30 */ _(R,C), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0B38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,AP), _(M,A),
+ /* 0B40 */ _(M,AP), _(M,AS), _(M,AS), _(M,AS), _(M,AS), _(X,X), _(X,X), _(M,LM),
+ /* 0B48 */ _(M,A), _(X,X), _(X,X), _(M,AP), _(M,AP), _(H,B), _(X,X), _(X,X),
+ /* 0B50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(N,X), _(M,A), _(M,AP),
+ /* 0B58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(C,C),
+ /* 0B60 */ _(V,C), _(V,C), _(M,AS), _(M,AS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0B68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0B70 */ _(X,X), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0B78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Tamil */
+
+ /* 0B80 */ _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0B88 */ _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(X,X), _(V,C), _(V,C),
+ /* 0B90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(X,X), _(X,X),
+ /* 0B98 */ _(X,X), _(C,C), _(C,C), _(X,X), _(C,C), _(X,X), _(C,C), _(C,C),
+ /* 0BA0 */ _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X),
+ /* 0BA8 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C),
+ /* 0BB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0BB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP), _(M,AP),
+ /* 0BC0 */ _(M,AS), _(M,AP), _(M,AP), _(X,X), _(X,X), _(X,X), _(M,LM), _(M,LM),
+ /* 0BC8 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(X,X), _(X,X),
+ /* 0BD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AP),
+ /* 0BD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BE0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0BE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0BF0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0BF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Telugu */
+
+ /* 0C00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(V,C), _(V,C), _(V,C),
+ /* 0C08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C28 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0C38 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0C40 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,BS),
+ /* 0C48 */ _(M,BS), _(X,X), _(M,BS), _(M,BS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0C50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,BS), _(M,BS), _(X,X),
+ /* 0C58 */ _(C,C), _(C,C), _(C,C), _(X,X), _(X,X), _(C,C), _(X,X), _(X,X),
+ /* 0C60 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0C68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0C70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0C78 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Kannada */
+
+ /* 0C80 */ _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(V,C), _(V,C), _(V,C),
+ /* 0C88 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0C90 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0C98 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CA8 */ _(C,C), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0CB0 */ _(R,C), _(C,C), _(C,C), _(C,C), _(X,X), _(C,C), _(C,C), _(C,C),
+ /* 0CB8 */ _(C,C), _(C,C), _(X,X), _(X,X), _(N,X), _(S,SM), _(M,BS), _(M,BS),
+ /* 0CC0 */ _(M,BS), _(M,BS), _(M,BS), _(M,AS), _(M,AS), _(X,X), _(M,BS), _(M,AS),
+ /* 0CC8 */ _(M,AS), _(X,X), _(M,AS), _(M,AS), _(M,BS), _(H,T), _(X,X), _(X,X),
+ /* 0CD0 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(M,AS), _(M,AS), _(X,X),
+ /* 0CD8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(X,X),
+ /* 0CE0 */ _(V,C), _(V,C), _(M,BS), _(M,BS), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0CE8 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0CF0 */ _(X,X), _(CS,C), _(CS,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0CF8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+ /* Malayalam */
+
+ /* 0D00 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(GB,C), _(V,C), _(V,C), _(V,C),
+ /* 0D08 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(V,C), _(V,C),
+ /* 0D10 */ _(V,C), _(X,X), _(V,C), _(V,C), _(V,C), _(C,C), _(C,C), _(C,C),
+ /* 0D18 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D20 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D28 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D30 */ _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 0D38 */ _(C,C), _(C,C), _(C,C), _(M,AS), _(M,AS), _(S,SM), _(M,AP), _(M,AP),
+ /* 0D40 */ _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(M,AP), _(X,X), _(M,LM), _(M,LM),
+ /* 0D48 */ _(M,LM), _(X,X), _(M,AP), _(M,AP), _(M,AP), _(H,T), _(Rf,X), _(X,X),
+ /* 0D50 */ _(X,X), _(X,X), _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(M,AP),
+ /* 0D58 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C),
+ /* 0D60 */ _(V,C), _(V,C), _(M,AP), _(M,AP), _(X,X), _(X,X), _(GB,C), _(GB,C),
+ /* 0D68 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 0D70 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 0D78 */ _(X,X), _(X,X), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+
+#define indic_offset_0x1000u 1216
+
+
+ /* Myanmar */
+
+ /* 1000 */ _(C,C), _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C),
+ /* 1008 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1010 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1018 */ _(C,C), _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1020 */ _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 1028 */ _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R), _(VA,T), _(VA,T), _(VB,B),
+ /* 1030 */ _(VB,B), _(VL,L), _(A,SM), _(VA,T), _(VA,T), _(VA,T), _(A,SM), _(N,X),
+ /* 1038 */_(SM,SM), _(H,X), _(As,X), _(MY,X), _(MR,X), _(MW,X), _(MH,X), _(C,C),
+ /* 1040 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1048 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X), _(C,C), _(X,X),
+ /* 1050 */ _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(VR,R), _(VR,R),
+ /* 1058 */ _(VB,B), _(VB,B), _(R,C), _(C,C), _(C,C), _(C,C), _(MY,X), _(MY,X),
+ /* 1060 */ _(ML,X), _(C,C), _(VR,R), _(PT,X), _(PT,X), _(C,C), _(C,C), _(VR,R),
+ /* 1068 */ _(VR,R), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(PT,X), _(C,C), _(C,C),
+ /* 1070 */ _(C,C), _(VA,T), _(VA,T), _(VA,T), _(VA,T), _(C,C), _(C,C), _(C,C),
+ /* 1078 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1080 */ _(C,C), _(C,C), _(MW,X), _(VR,R), _(VL,L), _(VA,T), _(VA,T),_(SM,SM),
+ /* 1088 */_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM),_(SM,SM), _(C,C),_(SM,SM),
+ /* 1090 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 1098 */ _(GB,C), _(GB,C),_(SM,SM),_(SM,SM),_(SM,SM), _(VA,T), _(X,X), _(X,X),
+
+#define indic_offset_0x1780u 1376
+
+
+ /* Khmer */
+
+ /* 1780 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1788 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1790 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 1798 */ _(C,C), _(C,C), _(R,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* 17A0 */ _(C,C), _(C,C), _(C,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17A8 */ _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C), _(V,C),
+ /* 17B0 */ _(V,C), _(V,C), _(V,C), _(V,C), _(X,X), _(X,X), _(VR,R), _(VA,T),
+ /* 17B8 */ _(VA,T), _(VA,T), _(VA,T), _(VB,B), _(VB,B), _(VB,B), _(VA,T), _(VR,R),
+ /* 17C0 */ _(VR,R), _(VL,L), _(VL,L), _(VL,L), _(VR,R), _(VR,R), _(Xg,X), _(Yg,X),
+ /* 17C8 */ _(Yg,X), _(Rt,X), _(Rt,X), _(Xg,X), _(Rt,X), _(Xg,X), _(Xg,X), _(Xg,X),
+ /* 17D0 */ _(Xg,X), _(Xg,X), _(H,X), _(Yg,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 17D8 */ _(X,X), _(GB,C), _(X,X), _(X,X), _(S,SM), _(Yg,X), _(X,X), _(X,X),
+ /* 17E0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* 17E8 */ _(GB,C), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x1cd0u 1488
+
+
+ /* Vedic Extensions */
+
+ /* 1CD0 */ _(A,SM), _(A,SM), _(A,SM), _(X,X), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CD8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* 1CE8 */ _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(A,SM), _(S,SM), _(S,SM),
+ /* 1CF0 */ _(S,SM), _(S,SM), _(C,C), _(C,C), _(A,SM), _(C,C), _(C,C), _(A,SM),
+ /* 1CF8 */ _(A,SM), _(A,SM), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2008u 1536
+
+
+ /* General Punctuation */
+
+ /* 2008 */ _(X,X), _(X,X), _(X,X), _(X,X),_(ZWNJ,X),_(ZWJ,X), _(X,X), _(X,X),
+ /* 2010 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X), _(X,X),
+ /* 2018 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2020 */ _(X,X), _(X,X), _(GB,C), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x2070u 1568
+
+
+ /* Superscripts and Subscripts */
+
+ /* 2070 */ _(X,X), _(X,X), _(X,X), _(X,X),_(SM,SM), _(X,X), _(X,X), _(X,X),
+ /* 2078 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 2080 */ _(X,X), _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X),
+
+#define indic_offset_0x25f8u 1592
+
+
+ /* Geometric Shapes */
+
+ /* 25F8 */ _(X,X), _(X,X), _(X,X), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+
+#define indic_offset_0xa8e0u 1600
+
+
+ /* Devanagari Extended */
+
+ /* A8E0 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8E8 */ _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM), _(A,SM),
+ /* A8F0 */ _(A,SM), _(A,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM), _(S,SM),
+ /* A8F8 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(V,C), _(M,AS),
+
+#define indic_offset_0xa9e0u 1632
+
+
+ /* Myanmar Extended-B */
+
+ /* A9E0 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(VA,T), _(X,X), _(C,C),
+ /* A9E8 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* A9F0 */ _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C), _(GB,C),
+ /* A9F8 */ _(GB,C), _(GB,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(X,X),
+
+#define indic_offset_0xaa60u 1664
+
+
+ /* Myanmar Extended-A */
+
+ /* AA60 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA68 */ _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C), _(C,C),
+ /* AA70 */ _(X,X), _(C,C), _(C,C), _(C,C), _(GB,C), _(GB,C), _(GB,C), _(X,X),
+ /* AA78 */ _(X,X), _(X,X), _(C,C), _(PT,X), _(N,X), _(N,X), _(C,C), _(C,C),
+
+#define indic_offset_0xfe00u 1696
+
+
+ /* Variation Selectors */
+
+ /* FE00 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+ /* FE08 */ _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X), _(VS,X),
+
+#define indic_offset_0x11300u 1712
+
+
+ /* Grantha */
+
+ /* 11300 */ _(X,X),_(SM,SM),_(SM,SM),_(SM,SM), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11308 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11310 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11318 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11320 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11328 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11330 */ _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X), _(X,X),
+ /* 11338 */ _(X,X), _(X,X), _(X,X), _(N,X), _(N,X), _(X,X), _(X,X), _(X,X),
+
+}; /* Table items: 1776; occupancy: 69% */
+
+uint16_t
+hb_indic_get_categories (hb_codepoint_t u)
+{
+ switch (u >> 12)
+ {
+ case 0x0u:
+ if (unlikely (u == 0x00A0u)) return _(GB,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x0028u, 0x003Fu)) return indic_table[u - 0x0028u + indic_offset_0x0028u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x00B0u, 0x00D7u)) return indic_table[u - 0x00B0u + indic_offset_0x00b0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x0900u, 0x0D7Fu)) return indic_table[u - 0x0900u + indic_offset_0x0900u];
+ break;
+
+ case 0x1u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x1000u, 0x109Fu)) return indic_table[u - 0x1000u + indic_offset_0x1000u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1780u, 0x17EFu)) return indic_table[u - 0x1780u + indic_offset_0x1780u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x1CD0u, 0x1CFFu)) return indic_table[u - 0x1CD0u + indic_offset_0x1cd0u];
+ break;
+
+ case 0x2u:
+ if (unlikely (u == 0x25CCu)) return _(DC,C);
+ if (hb_in_range<hb_codepoint_t> (u, 0x2008u, 0x2027u)) return indic_table[u - 0x2008u + indic_offset_0x2008u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x2070u, 0x2087u)) return indic_table[u - 0x2070u + indic_offset_0x2070u];
+ if (hb_in_range<hb_codepoint_t> (u, 0x25F8u, 0x25FFu)) return indic_table[u - 0x25F8u + indic_offset_0x25f8u];
+ break;
+
+ case 0xAu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xA8E0u, 0xA8FFu)) return indic_table[u - 0xA8E0u + indic_offset_0xa8e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xA9E0u, 0xA9FFu)) return indic_table[u - 0xA9E0u + indic_offset_0xa9e0u];
+ if (hb_in_range<hb_codepoint_t> (u, 0xAA60u, 0xAA7Fu)) return indic_table[u - 0xAA60u + indic_offset_0xaa60u];
+ break;
+
+ case 0xFu:
+ if (hb_in_range<hb_codepoint_t> (u, 0xFE00u, 0xFE0Fu)) return indic_table[u - 0xFE00u + indic_offset_0xfe00u];
+ break;
+
+ case 0x11u:
+ if (hb_in_range<hb_codepoint_t> (u, 0x11300u, 0x1133Fu)) return indic_table[u - 0x11300u + indic_offset_0x11300u];
+ break;
+
+ default:
+ break;
+ }
+ return _(X,X);
+}
+
+#undef _
+#undef INDIC_COMBINE_CATEGORIES
+
+#undef _OT_A
+#undef _OT_As
+#undef _OT_C
+#undef _OT_CM
+#undef _OT_CS
+#undef _OT_DC
+#undef _OT_H
+#undef _OT_M
+#undef _OT_MH
+#undef _OT_ML
+#undef _OT_MR
+#undef _OT_MW
+#undef _OT_MY
+#undef _OT_N
+#undef _OT_GB
+#undef _OT_PT
+#undef _OT_R
+#undef _OT_Rf
+#undef _OT_Rt
+#undef _OT_SM
+#undef _OT_S
+#undef _OT_V
+#undef _OT_VA
+#undef _OT_VB
+#undef _OT_VL
+#undef _OT_VR
+#undef _OT_VS
+#undef _OT_X
+#undef _OT_Xg
+#undef _OT_Yg
+#undef _OT_ZWJ
+#undef _OT_ZWNJ
+
+#undef _POS_T
+#undef _POS_A
+#undef _POS_AP
+#undef _POS_AS
+#undef _POS_C
+#undef _POS_BS
+#undef _POS_B
+#undef _POS_X
+#undef _POS_R
+#undef _POS_L
+#undef _POS_LM
+#undef _POS_SM
+
+#endif
+
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
new file mode 100644
index 0000000000..6eb400ab16
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.cc
@@ -0,0 +1,1540 @@
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-shaper-indic-machine.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
+#include "hb-ot-layout.hh"
+
+
+/*
+ * Indic shaper.
+ */
+
+
+static inline void
+set_indic_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.indic_category() = (indic_category_t) (type & 0xFFu);
+ info.indic_position() = (indic_position_t) (type >> 8);
+}
+
+
+static inline bool
+is_one_of (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.indic_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_INDIC (FLAG (I_Cat(C)) | FLAG (I_Cat(CS)) | FLAG (I_Cat(Ra)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(V)) | FLAG (I_Cat(PLACEHOLDER)) | FLAG (I_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, CONSONANT_FLAGS_INDIC);
+}
+
+#define JOINER_FLAGS (FLAG (I_Cat(ZWJ)) | FLAG (I_Cat(ZWNJ)))
+
+static inline bool
+is_joiner (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, JOINER_FLAGS);
+}
+
+static inline bool
+is_halant (const hb_glyph_info_t &info)
+{
+ return is_one_of (info, FLAG (I_Cat(H)));
+}
+
+struct hb_indic_would_substitute_feature_t
+{
+ void init (const hb_ot_map_t *map, hb_tag_t feature_tag, bool zero_context_)
+ {
+ zero_context = zero_context_;
+ lookups = map->get_stage_lookups (0/*GSUB*/,
+ map->get_feature_stage (0/*GSUB*/, feature_tag));
+ }
+
+ bool would_substitute (const hb_codepoint_t *glyphs,
+ unsigned int glyphs_count,
+ hb_face_t *face) const
+ {
+ for (const auto &lookup : lookups)
+ if (hb_ot_layout_lookup_would_substitute (face, lookup.index, glyphs, glyphs_count, zero_context))
+ return true;
+ return false;
+ }
+
+ private:
+ hb_array_t<const hb_ot_map_t::lookup_map_t> lookups;
+ bool zero_context;
+};
+
+
+/*
+ * Indic configurations. Note that we do not want to keep every single script-specific
+ * behavior in these tables necessarily. This should mainly be used for per-script
+ * properties that are cheaper keeping here, than in the code. Ie. if, say, one and
+ * only one script has an exception, that one script can be if'ed directly in the code,
+ * instead of adding a new flag in these structs.
+ */
+
+enum reph_position_t {
+ REPH_POS_AFTER_MAIN = POS_AFTER_MAIN,
+ REPH_POS_BEFORE_SUB = POS_BEFORE_SUB,
+ REPH_POS_AFTER_SUB = POS_AFTER_SUB,
+ REPH_POS_BEFORE_POST = POS_BEFORE_POST,
+ REPH_POS_AFTER_POST = POS_AFTER_POST
+};
+enum reph_mode_t {
+ REPH_MODE_IMPLICIT, /* Reph formed out of initial Ra,H sequence. */
+ REPH_MODE_EXPLICIT, /* Reph formed out of initial Ra,H,ZWJ sequence. */
+ REPH_MODE_LOG_REPHA /* Encoded Repha character, needs reordering. */
+};
+enum blwf_mode_t {
+ BLWF_MODE_PRE_AND_POST, /* Below-forms feature applied to pre-base and post-base. */
+ BLWF_MODE_POST_ONLY /* Below-forms feature applied to post-base only. */
+};
+struct indic_config_t
+{
+ hb_script_t script;
+ bool has_old_spec;
+ hb_codepoint_t virama;
+ reph_position_t reph_pos;
+ reph_mode_t reph_mode;
+ blwf_mode_t blwf_mode;
+};
+
+static const indic_config_t indic_configs[] =
+{
+ /* Default. Should be first. */
+ {HB_SCRIPT_INVALID, false, 0,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_DEVANAGARI,true, 0x094Du,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_BENGALI, true, 0x09CDu,REPH_POS_AFTER_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GURMUKHI, true, 0x0A4Du,REPH_POS_BEFORE_SUB, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_GUJARATI, true, 0x0ACDu,REPH_POS_BEFORE_POST,REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_ORIYA, true, 0x0B4Du,REPH_POS_AFTER_MAIN, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TAMIL, true, 0x0BCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_PRE_AND_POST},
+ {HB_SCRIPT_TELUGU, true, 0x0C4Du,REPH_POS_AFTER_POST, REPH_MODE_EXPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_KANNADA, true, 0x0CCDu,REPH_POS_AFTER_POST, REPH_MODE_IMPLICIT, BLWF_MODE_POST_ONLY},
+ {HB_SCRIPT_MALAYALAM, true, 0x0D4Du,REPH_POS_AFTER_MAIN, REPH_MODE_LOG_REPHA,BLWF_MODE_PRE_AND_POST},
+};
+
+
+static const hb_ot_map_feature_t
+indic_features[] =
+{
+ /*
+ * Basic features.
+ * These features are applied in order, one at a time, after initial_reordering,
+ * constrained to the syllable.
+ */
+ {HB_TAG('n','u','k','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','k','h','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','p','h','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('r','k','r','f'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('v','a','t','u'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','j','c','t'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ /*
+ * Other features.
+ * These features are applied all at once, after final_reordering, constrained
+ * to the syllable.
+ * Default Bengali font in Windows for example has intermixed
+ * lookups for init,pres,abvs,blws features.
+ */
+ {HB_TAG('i','n','i','t'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('h','a','l','n'), F_GLOBAL_MANUAL_JOINERS | F_PER_SYLLABLE},
+};
+
+/*
+ * Must be in the same order as the indic_features array.
+ */
+enum {
+ _INDIC_NUKT,
+ _INDIC_AKHN,
+ INDIC_RPHF,
+ _INDIC_RKRF,
+ INDIC_PREF,
+ INDIC_BLWF,
+ INDIC_ABVF,
+ INDIC_HALF,
+ INDIC_PSTF,
+ _INDIC_VATU,
+ _INDIC_CJCT,
+
+ INDIC_INIT,
+ _INDIC_PRES,
+ _INDIC_ABVS,
+ _INDIC_BLWS,
+ _INDIC_PSTS,
+ _INDIC_HALN,
+
+ INDIC_NUM_FEATURES,
+ INDIC_BASIC_FEATURES = INDIC_INIT, /* Don't forget to update this! */
+};
+
+static void
+setup_syllables_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+initial_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+final_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+collect_features_indic (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* Do this before any lookups have been applied. */
+ map->add_gsub_pause (setup_syllables_indic);
+
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ /* The Indic specs do not require ccmp, but we apply it here since if
+ * there is a use of it, it's typically at the beginning. */
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+
+
+ unsigned int i = 0;
+ map->add_gsub_pause (initial_reordering_indic);
+
+ for (; i < INDIC_BASIC_FEATURES; i++) {
+ map->add_feature (indic_features[i]);
+ map->add_gsub_pause (nullptr);
+ }
+
+ map->add_gsub_pause (final_reordering_indic);
+
+ for (; i < INDIC_NUM_FEATURES; i++)
+ map->add_feature (indic_features[i]);
+}
+
+static void
+override_features_indic (hb_ot_shape_planner_t *plan)
+{
+ plan->map.disable_feature (HB_TAG('l','i','g','a'));
+ plan->map.add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
+}
+
+
+struct indic_shape_plan_t
+{
+ bool load_virama_glyph (hb_font_t *font, hb_codepoint_t *pglyph) const
+ {
+ hb_codepoint_t glyph = virama_glyph.get_relaxed ();
+ if (unlikely (glyph == (hb_codepoint_t) -1))
+ {
+ if (!config->virama || !font->get_nominal_glyph (config->virama, &glyph))
+ glyph = 0;
+ /* Technically speaking, the spec says we should apply 'locl' to virama too.
+ * Maybe one day... */
+
+ /* Our get_nominal_glyph() function needs a font, so we can't get the virama glyph
+ * during shape planning... Instead, overwrite it here. */
+ virama_glyph.set_relaxed ((int) glyph);
+ }
+
+ *pglyph = glyph;
+ return glyph != 0;
+ }
+
+ const indic_config_t *config;
+
+ bool is_old_spec;
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
+ bool uniscribe_bug_compatible;
+#else
+ static constexpr bool uniscribe_bug_compatible = false;
+#endif
+ mutable hb_atomic_int_t virama_glyph;
+
+ hb_indic_would_substitute_feature_t rphf;
+ hb_indic_would_substitute_feature_t pref;
+ hb_indic_would_substitute_feature_t blwf;
+ hb_indic_would_substitute_feature_t pstf;
+ hb_indic_would_substitute_feature_t vatu;
+
+ hb_mask_t mask_array[INDIC_NUM_FEATURES];
+};
+
+static void *
+data_create_indic (const hb_ot_shape_plan_t *plan)
+{
+ indic_shape_plan_t *indic_plan = (indic_shape_plan_t *) hb_calloc (1, sizeof (indic_shape_plan_t));
+ if (unlikely (!indic_plan))
+ return nullptr;
+
+ indic_plan->config = &indic_configs[0];
+ for (unsigned int i = 1; i < ARRAY_LENGTH (indic_configs); i++)
+ if (plan->props.script == indic_configs[i].script) {
+ indic_plan->config = &indic_configs[i];
+ break;
+ }
+
+ indic_plan->is_old_spec = indic_plan->config->has_old_spec && ((plan->map.chosen_script[0] & 0x000000FFu) != '2');
+#ifndef HB_NO_UNISCRIBE_BUG_COMPATIBLE
+ indic_plan->uniscribe_bug_compatible = hb_options ().uniscribe_bug_compatible;
+#endif
+ indic_plan->virama_glyph.set_relaxed (-1);
+
+ /* Use zero-context would_substitute() matching for new-spec of the main
+ * Indic scripts, and scripts with one spec only, but not for old-specs.
+ * The new-spec for all dual-spec scripts says zero-context matching happens.
+ *
+ * However, testing with Malayalam shows that old and new spec both allow
+ * context. Testing with Bengali new-spec however shows that it doesn't.
+ * So, the heuristic here is the way it is. It should *only* be changed,
+ * as we discover more cases of what Windows does. DON'T TOUCH OTHERWISE.
+ */
+ bool zero_context = !indic_plan->is_old_spec && plan->props.script != HB_SCRIPT_MALAYALAM;
+ indic_plan->rphf.init (&plan->map, HB_TAG('r','p','h','f'), zero_context);
+ indic_plan->pref.init (&plan->map, HB_TAG('p','r','e','f'), zero_context);
+ indic_plan->blwf.init (&plan->map, HB_TAG('b','l','w','f'), zero_context);
+ indic_plan->pstf.init (&plan->map, HB_TAG('p','s','t','f'), zero_context);
+ indic_plan->vatu.init (&plan->map, HB_TAG('v','a','t','u'), zero_context);
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (indic_plan->mask_array); i++)
+ indic_plan->mask_array[i] = (indic_features[i].flags & F_GLOBAL) ?
+ 0 : plan->map.get_1_mask (indic_features[i].tag);
+
+ return indic_plan;
+}
+
+static void
+data_destroy_indic (void *data)
+{
+ hb_free (data);
+}
+
+static indic_position_t
+consonant_position_from_face (const indic_shape_plan_t *indic_plan,
+ const hb_codepoint_t consonant,
+ const hb_codepoint_t virama,
+ hb_face_t *face)
+{
+ /* For old-spec, the order of glyphs is Consonant,Virama,
+ * whereas for new-spec, it's Virama,Consonant. However,
+ * some broken fonts (like Free Sans) simply copied lookups
+ * from old-spec to new-spec without modification.
+ * And oddly enough, Uniscribe seems to respect those lookups.
+ * Eg. in the sequence U+0924,U+094D,U+0930, Uniscribe finds
+ * base at 0. The font however, only has lookups matching
+ * 930,94D in 'blwf', not the expected 94D,930 (with new-spec
+ * table). As such, we simply match both sequences. Seems
+ * to work.
+ *
+ * Vatu is done as well, for:
+ * https://github.com/harfbuzz/harfbuzz/issues/1587
+ */
+ hb_codepoint_t glyphs[3] = {virama, consonant, virama};
+ if (indic_plan->blwf.would_substitute (glyphs , 2, face) ||
+ indic_plan->blwf.would_substitute (glyphs+1, 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs , 2, face) ||
+ indic_plan->vatu.would_substitute (glyphs+1, 2, face))
+ return POS_BELOW_C;
+ if (indic_plan->pstf.would_substitute (glyphs , 2, face) ||
+ indic_plan->pstf.would_substitute (glyphs+1, 2, face))
+ return POS_POST_C;
+ if (indic_plan->pref.would_substitute (glyphs , 2, face) ||
+ indic_plan->pref.would_substitute (glyphs+1, 2, face))
+ return POS_POST_C;
+ return POS_BASE_C;
+}
+
+static void
+setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, indic_category);
+ HB_BUFFER_ALLOCATE_VAR (buffer, indic_position);
+
+ /* We cannot setup masks here. We save information about characters
+ * and setup masks later on in a pause-callback. */
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ set_indic_properties (info[i]);
+}
+
+static void
+setup_syllables_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+ find_syllables_indic (buffer);
+ foreach_syllable (buffer, start, end)
+ buffer->unsafe_to_break (start, end);
+}
+
+static int
+compare_indic_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
+{
+ int a = pa->indic_position();
+ int b = pb->indic_position();
+
+ return (int) a - (int) b;
+}
+
+
+
+static void
+update_consonant_positions_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+
+ hb_codepoint_t virama;
+ if (indic_plan->load_virama_glyph (font, &virama))
+ {
+ hb_face_t *face = font->face;
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ if (info[i].indic_position() == POS_BASE_C)
+ {
+ hb_codepoint_t consonant = info[i].codepoint;
+ info[i].indic_position() = consonant_position_from_face (indic_plan, consonant, virama, face);
+ }
+ }
+}
+
+
+/* Rules from:
+ * https://docs.microsqoft.com/en-us/typography/script-development/devanagari */
+
+static void
+initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ hb_glyph_info_t *info = buffer->info;
+
+ /* https://github.com/harfbuzz/harfbuzz/issues/435#issuecomment-335560167
+ * // For compatibility with legacy usage in Kannada,
+ * // Ra+h+ZWJ must behave like Ra+ZWJ+h...
+ */
+ if (buffer->props.script == HB_SCRIPT_KANNADA &&
+ start + 3 <= end &&
+ is_one_of (info[start ], FLAG (I_Cat(Ra))) &&
+ is_one_of (info[start+1], FLAG (I_Cat(H))) &&
+ is_one_of (info[start+2], FLAG (I_Cat(ZWJ))))
+ {
+ buffer->merge_clusters (start+1, start+3);
+ hb_glyph_info_t tmp = info[start+1];
+ info[start+1] = info[start+2];
+ info[start+2] = tmp;
+ }
+
+ /* 1. Find base consonant:
+ *
+ * The shaping engine finds the base consonant of the syllable, using the
+ * following algorithm: starting from the end of the syllable, move backwards
+ * until a consonant is found that does not have a below-base or post-base
+ * form (post-base forms have to follow below-base forms), or that is not a
+ * pre-base-reordering Ra, or arrive at the first consonant. The consonant
+ * stopped at will be the base.
+ *
+ * o If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants.
+ */
+
+ unsigned int base = end;
+ bool has_reph = false;
+
+ {
+ /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants. */
+ unsigned int limit = start;
+ if (indic_plan->mask_array[INDIC_RPHF] &&
+ start + 3 <= end &&
+ (
+ (indic_plan->config->reph_mode == REPH_MODE_IMPLICIT && !is_joiner (info[start + 2])) ||
+ (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT && info[start + 2].indic_category() == I_Cat(ZWJ))
+ ))
+ {
+ /* See if it matches the 'rphf' feature. */
+ hb_codepoint_t glyphs[3] = {info[start].codepoint,
+ info[start + 1].codepoint,
+ indic_plan->config->reph_mode == REPH_MODE_EXPLICIT ?
+ info[start + 2].codepoint : 0};
+ if (indic_plan->rphf.would_substitute (glyphs, 2, face) ||
+ (indic_plan->config->reph_mode == REPH_MODE_EXPLICIT &&
+ indic_plan->rphf.would_substitute (glyphs, 3, face)))
+ {
+ limit += 2;
+ while (limit < end && is_joiner (info[limit]))
+ limit++;
+ base = start;
+ has_reph = true;
+ }
+ } else if (indic_plan->config->reph_mode == REPH_MODE_LOG_REPHA && info[start].indic_category() == I_Cat(Repha))
+ {
+ limit += 1;
+ while (limit < end && is_joiner (info[limit]))
+ limit++;
+ base = start;
+ has_reph = true;
+ }
+
+ {
+ /* -> starting from the end of the syllable, move backwards */
+ unsigned int i = end;
+ bool seen_below = false;
+ do {
+ i--;
+ /* -> until a consonant is found */
+ if (is_consonant (info[i]))
+ {
+ /* -> that does not have a below-base or post-base form
+ * (post-base forms have to follow below-base forms), */
+ if (info[i].indic_position() != POS_BELOW_C &&
+ (info[i].indic_position() != POS_POST_C || seen_below))
+ {
+ base = i;
+ break;
+ }
+ if (info[i].indic_position() == POS_BELOW_C)
+ seen_below = true;
+
+ /* -> or that is not a pre-base-reordering Ra,
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * Our pre-base-reordering Ra's are marked POS_POST_C, so will be skipped
+ * by the logic above already.
+ */
+
+ /* -> or arrive at the first consonant. The consonant stopped at will
+ * be the base. */
+ base = i;
+ }
+ else
+ {
+ /* A ZWJ after a Halant stops the base search, and requests an explicit
+ * half form.
+ * A ZWJ before a Halant, requests a subjoined form instead, and hence
+ * search continues. This is particularly important for Bengali
+ * sequence Ra,H,Ya that should form Ya-Phalaa by subjoining Ya. */
+ if (start < i &&
+ info[i].indic_category() == I_Cat(ZWJ) &&
+ info[i - 1].indic_category() == I_Cat(H))
+ break;
+ }
+ } while (i > limit);
+ }
+
+ /* -> If the syllable starts with Ra + Halant (in a script that has Reph)
+ * and has more than one consonant, Ra is excluded from candidates for
+ * base consonants.
+ *
+ * Only do this for unforced Reph. (ie. not for Ra,H,ZWJ. */
+ if (has_reph && base == start && limit - base <= 2) {
+ /* Have no other consonant, so Reph is not formed and Ra becomes base. */
+ has_reph = false;
+ }
+ }
+
+
+ /* 2. Decompose and reorder Matras:
+ *
+ * Each matra and any syllable modifier sign in the syllable are moved to the
+ * appropriate position relative to the consonant(s) in the syllable. The
+ * shaping engine decomposes two- or three-part matras into their constituent
+ * parts before any repositioning. Matra characters are classified by which
+ * consonant in a conjunct they have affinity for and are reordered to the
+ * following positions:
+ *
+ * o Before first half form in the syllable
+ * o After subjoined consonants
+ * o After post-form consonant
+ * o After main consonant (for above marks)
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * The normalize() routine has already decomposed matras for us, so we don't
+ * need to worry about that.
+ */
+
+
+ /* 3. Reorder marks to canonical order:
+ *
+ * Adjacent nukta and halant or nukta and vedic sign are always repositioned
+ * if necessary, so that the nukta is first.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * We don't need to do this: the normalize() routine already did this for us.
+ */
+
+
+ /* Reorder characters */
+
+ for (unsigned int i = start; i < base; i++)
+ info[i].indic_position() = hb_min (POS_PRE_C, (indic_position_t) info[i].indic_position());
+
+ if (base < end)
+ info[base].indic_position() = POS_BASE_C;
+
+ /* Handle beginning Ra */
+ if (has_reph)
+ info[start].indic_position() = POS_RA_TO_BECOME_REPH;
+
+ /* For old-style Indic script tags, move the first post-base Halant after
+ * last consonant.
+ *
+ * Reports suggest that in some scripts Uniscribe does this only if there
+ * is *not* a Halant after last consonant already. We know that is the
+ * case for Kannada, while it reorders unconditionally in other scripts,
+ * eg. Malayalam, Bengali, and Devanagari. We don't currently know about
+ * other scripts, so we block Kannada.
+ *
+ * Kannada test case:
+ * U+0C9A,U+0CCD,U+0C9A,U+0CCD
+ * With some versions of Lohit Kannada.
+ * https://bugs.freedesktop.org/show_bug.cgi?id=59118
+ *
+ * Malayalam test case:
+ * U+0D38,U+0D4D,U+0D31,U+0D4D,U+0D31,U+0D4D
+ * With lohit-ttf-20121122/Lohit-Malayalam.ttf
+ *
+ * Bengali test case:
+ * U+0998,U+09CD,U+09AF,U+09CD
+ * With Windows XP vrinda.ttf
+ * https://github.com/harfbuzz/harfbuzz/issues/1073
+ *
+ * Devanagari test case:
+ * U+091F,U+094D,U+0930,U+094D
+ * With chandas.ttf
+ * https://github.com/harfbuzz/harfbuzz/issues/1071
+ */
+ if (indic_plan->is_old_spec)
+ {
+ bool disallow_double_halants = buffer->props.script == HB_SCRIPT_KANNADA;
+ for (unsigned int i = base + 1; i < end; i++)
+ if (info[i].indic_category() == I_Cat(H))
+ {
+ unsigned int j;
+ for (j = end - 1; j > i; j--)
+ if (is_consonant (info[j]) ||
+ (disallow_double_halants && info[j].indic_category() == I_Cat(H)))
+ break;
+ if (info[j].indic_category() != I_Cat(H) && j > i) {
+ /* Move Halant to after last consonant. */
+ hb_glyph_info_t t = info[i];
+ memmove (&info[i], &info[i + 1], (j - i) * sizeof (info[0]));
+ info[j] = t;
+ }
+ break;
+ }
+ }
+
+ /* Attach misc marks to previous char to move with them. */
+ {
+ indic_position_t last_pos = POS_START;
+ for (unsigned int i = start; i < end; i++)
+ {
+ if ((FLAG_UNSAFE (info[i].indic_category()) & (JOINER_FLAGS | FLAG (I_Cat(N)) | FLAG (I_Cat(RS)) | FLAG (I_Cat(CM)) | FLAG (I_Cat(H)))))
+ {
+ info[i].indic_position() = last_pos;
+ if (unlikely (info[i].indic_category() == I_Cat(H) &&
+ info[i].indic_position() == POS_PRE_M))
+ {
+ /*
+ * Uniscribe doesn't move the Halant with Left Matra.
+ * TEST: U+092B,U+093F,U+094D
+ * We follow.
+ */
+ for (unsigned int j = i; j > start; j--)
+ if (info[j - 1].indic_position() != POS_PRE_M) {
+ info[i].indic_position() = info[j - 1].indic_position();
+ break;
+ }
+ }
+ } else if (info[i].indic_position() != POS_SMVD) {
+ last_pos = (indic_position_t) info[i].indic_position();
+ }
+ }
+ }
+ /* For post-base consonants let them own anything before them
+ * since the last consonant or matra. */
+ {
+ unsigned int last = base;
+ for (unsigned int i = base + 1; i < end; i++)
+ if (is_consonant (info[i]))
+ {
+ for (unsigned int j = last + 1; j < i; j++)
+ if (info[j].indic_position() < POS_SMVD)
+ info[j].indic_position() = info[i].indic_position();
+ last = i;
+ } else if (info[i].indic_category() == I_Cat(M))
+ last = i;
+ }
+
+
+ {
+ /* Use syllable() for sort accounting temporarily. */
+ unsigned int syllable = info[start].syllable();
+ for (unsigned int i = start; i < end; i++)
+ info[i].syllable() = i - start;
+
+ /* Sit tight, rock 'n roll! */
+ hb_stable_sort (info + start, end - start, compare_indic_order);
+ /* Find base again */
+ base = end;
+ for (unsigned int i = start; i < end; i++)
+ if (info[i].indic_position() == POS_BASE_C)
+ {
+ base = i;
+ break;
+ }
+ /* Things are out-of-control for post base positions, they may shuffle
+ * around like crazy. In old-spec mode, we move halants around, so in
+ * that case merge all clusters after base. Otherwise, check the sort
+ * order and merge as needed.
+ * For pre-base stuff, we handle cluster issues in final reordering.
+ *
+ * We could use buffer->sort() for this, if there was no special
+ * reordering of pre-base stuff happening later...
+ * We don't want to merge_clusters all of that, which buffer->sort()
+ * would. Here's a concrete example:
+ *
+ * Assume there's a pre-base consonant and explicit Halant before base,
+ * followed by a prebase-reordering (left) Matra:
+ *
+ * C,H,ZWNJ,B,M
+ *
+ * At this point in reordering we would have:
+ *
+ * M,C,H,ZWNJ,B
+ *
+ * whereas in final reordering we will bring the Matra closer to Base:
+ *
+ * C,H,ZWNJ,M,B
+ *
+ * That's why we don't want to merge-clusters anything before the Base
+ * at this point. But if something moved from after Base to before it,
+ * we should merge clusters from base to them. In final-reordering, we
+ * only move things around before base, and merge-clusters up to base.
+ * These two merge-clusters from the two sides of base will interlock
+ * to merge things correctly. See:
+ * https://github.com/harfbuzz/harfbuzz/issues/2272
+ */
+ if (indic_plan->is_old_spec || end - start > 127)
+ buffer->merge_clusters (base, end);
+ else
+ {
+ /* Note! syllable() is a one-byte field. */
+ for (unsigned int i = base; i < end; i++)
+ if (info[i].syllable() != 255)
+ {
+ unsigned int min = i;
+ unsigned int max = i;
+ unsigned int j = start + info[i].syllable();
+ while (j != i)
+ {
+ min = hb_min (min, j);
+ max = hb_max (max, j);
+ unsigned int next = start + info[j].syllable();
+ info[j].syllable() = 255; /* So we don't process j later again. */
+ j = next;
+ }
+ buffer->merge_clusters (hb_max (base, min), max + 1);
+ }
+ }
+
+ /* Put syllable back in. */
+ for (unsigned int i = start; i < end; i++)
+ info[i].syllable() = syllable;
+ }
+
+ /* Setup masks now */
+
+ {
+ hb_mask_t mask;
+
+ /* Reph */
+ for (unsigned int i = start; i < end && info[i].indic_position() == POS_RA_TO_BECOME_REPH; i++)
+ info[i].mask |= indic_plan->mask_array[INDIC_RPHF];
+
+ /* Pre-base */
+ mask = indic_plan->mask_array[INDIC_HALF];
+ if (!indic_plan->is_old_spec &&
+ indic_plan->config->blwf_mode == BLWF_MODE_PRE_AND_POST)
+ mask |= indic_plan->mask_array[INDIC_BLWF];
+ for (unsigned int i = start; i < base; i++)
+ info[i].mask |= mask;
+ /* Base */
+ mask = 0;
+ if (base < end)
+ info[base].mask |= mask;
+ /* Post-base */
+ mask = indic_plan->mask_array[INDIC_BLWF] |
+ indic_plan->mask_array[INDIC_ABVF] |
+ indic_plan->mask_array[INDIC_PSTF];
+ for (unsigned int i = base + 1; i < end; i++)
+ info[i].mask |= mask;
+ }
+
+ if (indic_plan->is_old_spec &&
+ buffer->props.script == HB_SCRIPT_DEVANAGARI)
+ {
+ /* Old-spec eye-lash Ra needs special handling. From the
+ * spec:
+ *
+ * "The feature 'below-base form' is applied to consonants
+ * having below-base forms and following the base consonant.
+ * The exception is vattu, which may appear below half forms
+ * as well as below the base glyph. The feature 'below-base
+ * form' will be applied to all such occurrences of Ra as well."
+ *
+ * Test case: U+0924,U+094D,U+0930,U+094d,U+0915
+ * with Sanskrit 2003 font.
+ *
+ * However, note that Ra,Halant,ZWJ is the correct way to
+ * request eyelash form of Ra, so we wouldbn't inhibit it
+ * in that sequence.
+ *
+ * Test case: U+0924,U+094D,U+0930,U+094d,U+200D,U+0915
+ */
+ for (unsigned int i = start; i + 1 < base; i++)
+ if (info[i ].indic_category() == I_Cat(Ra) &&
+ info[i+1].indic_category() == I_Cat(H) &&
+ (i + 2 == base ||
+ info[i+2].indic_category() != I_Cat(ZWJ)))
+ {
+ info[i ].mask |= indic_plan->mask_array[INDIC_BLWF];
+ info[i+1].mask |= indic_plan->mask_array[INDIC_BLWF];
+ }
+ }
+
+ unsigned int pref_len = 2;
+ if (indic_plan->mask_array[INDIC_PREF] && base + pref_len < end)
+ {
+ /* Find a Halant,Ra sequence and mark it for pre-base-reordering processing. */
+ for (unsigned int i = base + 1; i + pref_len - 1 < end; i++) {
+ hb_codepoint_t glyphs[2];
+ for (unsigned int j = 0; j < pref_len; j++)
+ glyphs[j] = info[i + j].codepoint;
+ if (indic_plan->pref.would_substitute (glyphs, pref_len, face))
+ {
+ for (unsigned int j = 0; j < pref_len; j++)
+ info[i++].mask |= indic_plan->mask_array[INDIC_PREF];
+ break;
+ }
+ }
+ }
+
+ /* Apply ZWJ/ZWNJ effects */
+ for (unsigned int i = start + 1; i < end; i++)
+ if (is_joiner (info[i])) {
+ bool non_joiner = info[i].indic_category() == I_Cat(ZWNJ);
+ unsigned int j = i;
+
+ do {
+ j--;
+
+ /* ZWJ/ZWNJ should disable CJCT. They do that by simply
+ * being there, since we don't skip them for the CJCT
+ * feature (ie. F_MANUAL_ZWJ) */
+
+ /* A ZWNJ disables HALF. */
+ if (non_joiner)
+ info[j].mask &= ~indic_plan->mask_array[INDIC_HALF];
+
+ } while (j > start && !is_consonant (info[j]));
+ }
+}
+
+static void
+initial_reordering_standalone_cluster (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ /* We treat placeholder/dotted-circle as if they are consonants, so we
+ * should just chain. Only if not in compatibility mode that is... */
+
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ if (indic_plan->uniscribe_bug_compatible)
+ {
+ /* For dotted-circle, this is what Uniscribe does:
+ * If dotted-circle is the last glyph, it just does nothing.
+ * Ie. It doesn't form Reph. */
+ if (buffer->info[end - 1].indic_category() == I_Cat(DOTTEDCIRCLE))
+ return;
+ }
+
+ initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+}
+
+static void
+initial_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ indic_syllable_type_t syllable_type = (indic_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
+ switch (syllable_type)
+ {
+ case indic_vowel_syllable: /* We made the vowels look like consonants. So let's call the consonant logic! */
+ case indic_consonant_syllable:
+ initial_reordering_consonant_syllable (plan, face, buffer, start, end);
+ break;
+
+ case indic_broken_cluster: /* We already inserted dotted-circles, so just call the standalone_cluster. */
+ case indic_standalone_cluster:
+ initial_reordering_standalone_cluster (plan, face, buffer, start, end);
+ break;
+
+ case indic_symbol_cluster:
+ case indic_non_indic_cluster:
+ break;
+ }
+}
+
+static void
+initial_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ if (!buffer->message (font, "start reordering indic initial"))
+ return;
+
+ update_consonant_positions_indic (plan, font, buffer);
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ indic_broken_cluster,
+ I_Cat(DOTTEDCIRCLE),
+ I_Cat(Repha),
+ POS_END);
+
+ foreach_syllable (buffer, start, end)
+ initial_reordering_syllable_indic (plan, font->face, buffer, start, end);
+
+ (void) buffer->message (font, "end reordering indic initial");
+}
+
+static void
+final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ hb_glyph_info_t *info = buffer->info;
+
+
+ /* This function relies heavily on halant glyphs. Lots of ligation
+ * and possibly multiple substitutions happened prior to this
+ * phase, and that might have messed up our properties. Recover
+ * from a particular case of that where we're fairly sure that a
+ * class of I_Cat(H) is desired but has been lost. */
+ /* We don't call load_virama_glyph(), since we know it's already
+ * loaded. */
+ hb_codepoint_t virama_glyph = indic_plan->virama_glyph.get_relaxed ();
+ if (virama_glyph)
+ {
+ for (unsigned int i = start; i < end; i++)
+ if (info[i].codepoint == virama_glyph &&
+ _hb_glyph_info_ligated (&info[i]) &&
+ _hb_glyph_info_multiplied (&info[i]))
+ {
+ /* This will make sure that this glyph passes is_halant() test. */
+ info[i].indic_category() = I_Cat(H);
+ _hb_glyph_info_clear_ligated_and_multiplied (&info[i]);
+ }
+ }
+
+
+ /* 4. Final reordering:
+ *
+ * After the localized forms and basic shaping forms GSUB features have been
+ * applied (see below), the shaping engine performs some final glyph
+ * reordering before applying all the remaining font features to the entire
+ * syllable.
+ */
+
+ bool try_pref = !!indic_plan->mask_array[INDIC_PREF];
+
+ /* Find base again */
+ unsigned int base;
+ for (base = start; base < end; base++)
+ if (info[base].indic_position() >= POS_BASE_C)
+ {
+ if (try_pref && base + 1 < end)
+ {
+ for (unsigned int i = base + 1; i < end; i++)
+ if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
+ {
+ if (!(_hb_glyph_info_substituted (&info[i]) &&
+ _hb_glyph_info_ligated_and_didnt_multiply (&info[i])))
+ {
+ /* Ok, this was a 'pref' candidate but didn't form any.
+ * Base is around here... */
+ base = i;
+ while (base < end && is_halant (info[base]))
+ base++;
+ info[base].indic_position() = POS_BASE_C;
+
+ try_pref = false;
+ }
+ break;
+ }
+ }
+ /* For Malayalam, skip over unformed below- (but NOT post-) forms. */
+ if (buffer->props.script == HB_SCRIPT_MALAYALAM)
+ {
+ for (unsigned int i = base + 1; i < end; i++)
+ {
+ while (i < end && is_joiner (info[i]))
+ i++;
+ if (i == end || !is_halant (info[i]))
+ break;
+ i++; /* Skip halant. */
+ while (i < end && is_joiner (info[i]))
+ i++;
+ if (i < end && is_consonant (info[i]) && info[i].indic_position() == POS_BELOW_C)
+ {
+ base = i;
+ info[base].indic_position() = POS_BASE_C;
+ }
+ }
+ }
+
+ if (start < base && info[base].indic_position() > POS_BASE_C)
+ base--;
+ break;
+ }
+ if (base == end && start < base &&
+ is_one_of (info[base - 1], FLAG (I_Cat(ZWJ))))
+ base--;
+ if (base < end)
+ while (start < base &&
+ is_one_of (info[base], (FLAG (I_Cat(N)) | FLAG (I_Cat(H)))))
+ base--;
+
+
+ /* o Reorder matras:
+ *
+ * If a pre-base matra character had been reordered before applying basic
+ * features, the glyph can be moved closer to the main consonant based on
+ * whether half-forms had been formed. Actual position for the matra is
+ * defined as “after last standalone halant glyph, after initial matra
+ * position and before the main consonantâ€. If ZWJ or ZWNJ follow this
+ * halant, position is moved after it.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * It looks like the last sentence is wrong. Testing, with Windows 7 Uniscribe
+ * and Devanagari shows that the behavior is best described as:
+ *
+ * "If ZWJ follows this halant, matra is NOT repositioned after this halant.
+ * If ZWNJ follows this halant, position is moved after it."
+ *
+ * Test case, with Adobe Devanagari or Nirmala UI:
+ *
+ * U+091F,U+094D,U+200C,U+092F,U+093F
+ * (Matra moves to the middle, after ZWNJ.)
+ *
+ * U+091F,U+094D,U+200D,U+092F,U+093F
+ * (Matra does NOT move, stays to the left.)
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/1070
+ */
+
+ if (start + 1 < end && start < base) /* Otherwise there can't be any pre-base matra characters. */
+ {
+ /* If we lost track of base, alas, position before last thingy. */
+ unsigned int new_pos = base == end ? base - 2 : base - 1;
+
+ /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
+ * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
+ * We want to position matra after them.
+ */
+ if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
+ {
+ search:
+ while (new_pos > start &&
+ !(is_one_of (info[new_pos], (FLAG (I_Cat(M)) | FLAG (I_Cat(H))))))
+ new_pos--;
+
+ /* If we found no Halant we are done.
+ * Otherwise only proceed if the Halant does
+ * not belong to the Matra itself! */
+ if (is_halant (info[new_pos]) &&
+ info[new_pos].indic_position() != POS_PRE_M)
+ {
+#if 0 // See comment above
+ /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
+ if (new_pos + 1 < end && is_joiner (info[new_pos + 1]))
+ new_pos++;
+#endif
+ if (new_pos + 1 < end)
+ {
+ /* -> If ZWJ follows this halant, matra is NOT repositioned after this halant. */
+ if (info[new_pos + 1].indic_category() == I_Cat(ZWJ))
+ {
+ /* Keep searching. */
+ if (new_pos > start)
+ {
+ new_pos--;
+ goto search;
+ }
+ }
+ /* -> If ZWNJ follows this halant, position is moved after it.
+ *
+ * IMPLEMENTATION NOTES:
+ *
+ * This is taken care of by the state-machine. A Halant,ZWNJ is a terminating
+ * sequence for a consonant syllable; any pre-base matras occurring after it
+ * will belong to the subsequent syllable.
+ */
+ }
+ }
+ else
+ new_pos = start; /* No move. */
+ }
+
+ if (start < new_pos && info[new_pos].indic_position () != POS_PRE_M)
+ {
+ /* Now go see if there's actually any matras... */
+ for (unsigned int i = new_pos; i > start; i--)
+ if (info[i - 1].indic_position () == POS_PRE_M)
+ {
+ unsigned int old_pos = i - 1;
+ if (old_pos < base && base <= new_pos) /* Shouldn't actually happen. */
+ base--;
+
+ hb_glyph_info_t tmp = info[old_pos];
+ memmove (&info[old_pos], &info[old_pos + 1], (new_pos - old_pos) * sizeof (info[0]));
+ info[new_pos] = tmp;
+
+ /* Note: this merge_clusters() is intentionally *after* the reordering.
+ * Indic matra reordering is special and tricky... */
+ buffer->merge_clusters (new_pos, hb_min (end, base + 1));
+
+ new_pos--;
+ }
+ } else {
+ for (unsigned int i = start; i < base; i++)
+ if (info[i].indic_position () == POS_PRE_M) {
+ buffer->merge_clusters (i, hb_min (end, base + 1));
+ break;
+ }
+ }
+ }
+
+
+ /* o Reorder reph:
+ *
+ * Reph’s original position is always at the beginning of the syllable,
+ * (i.e. it is not reordered at the character reordering stage). However,
+ * it will be reordered according to the basic-forms shaping results.
+ * Possible positions for reph, depending on the script, are; after main,
+ * before post-base consonant forms, and after post-base consonant forms.
+ */
+
+ /* Two cases:
+ *
+ * - If repha is encoded as a sequence of characters (Ra,H or Ra,H,ZWJ), then
+ * we should only move it if the sequence ligated to the repha form.
+ *
+ * - If repha is encoded separately and in the logical position, we should only
+ * move it if it did NOT ligate. If it ligated, it's probably the font trying
+ * to make it work without the reordering.
+ */
+ if (start + 1 < end &&
+ info[start].indic_position() == POS_RA_TO_BECOME_REPH &&
+ ((info[start].indic_category() == I_Cat(Repha)) ^
+ _hb_glyph_info_ligated_and_didnt_multiply (&info[start])))
+ {
+ unsigned int new_reph_pos;
+ reph_position_t reph_pos = indic_plan->config->reph_pos;
+
+ /* 1. If reph should be positioned after post-base consonant forms,
+ * proceed to step 5.
+ */
+ if (reph_pos == REPH_POS_AFTER_POST)
+ {
+ goto reph_step_5;
+ }
+
+ /* 2. If the reph repositioning class is not after post-base: target
+ * position is after the first explicit halant glyph between the
+ * first post-reph consonant and last main consonant. If ZWJ or ZWNJ
+ * are following this halant, position is moved after it. If such
+ * position is found, this is the target position. Otherwise,
+ * proceed to the next step.
+ *
+ * Note: in old-implementation fonts, where classifications were
+ * fixed in shaping engine, there was no case where reph position
+ * will be found on this step.
+ */
+ {
+ new_reph_pos = start + 1;
+ while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
+ new_reph_pos++;
+
+ if (new_reph_pos < base && is_halant (info[new_reph_pos]))
+ {
+ /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
+ if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
+ new_reph_pos++;
+ goto reph_move;
+ }
+ }
+
+ /* 3. If reph should be repositioned after the main consonant: find the
+ * first consonant not ligated with main, or find the first
+ * consonant that is not a potential pre-base-reordering Ra.
+ */
+ if (reph_pos == REPH_POS_AFTER_MAIN)
+ {
+ new_reph_pos = base;
+ while (new_reph_pos + 1 < end && info[new_reph_pos + 1].indic_position() <= POS_AFTER_MAIN)
+ new_reph_pos++;
+ if (new_reph_pos < end)
+ goto reph_move;
+ }
+
+ /* 4. If reph should be positioned before post-base consonant, find
+ * first post-base classified consonant not ligated with main. If no
+ * consonant is found, the target position should be before the
+ * first matra, syllable modifier sign or vedic sign.
+ */
+ /* This is our take on what step 4 is trying to say (and failing, BADLY). */
+ if (reph_pos == REPH_POS_AFTER_SUB)
+ {
+ new_reph_pos = base;
+ while (new_reph_pos + 1 < end &&
+ !( FLAG_UNSAFE (info[new_reph_pos + 1].indic_position()) & (FLAG (POS_POST_C) | FLAG (POS_AFTER_POST) | FLAG (POS_SMVD))))
+ new_reph_pos++;
+ if (new_reph_pos < end)
+ goto reph_move;
+ }
+
+ /* 5. If no consonant is found in steps 3 or 4, move reph to a position
+ * immediately before the first post-base matra, syllable modifier
+ * sign or vedic sign that has a reordering class after the intended
+ * reph position. For example, if the reordering position for reph
+ * is post-main, it will skip above-base matras that also have a
+ * post-main position.
+ */
+ reph_step_5:
+ {
+ /* Copied from step 2. */
+ new_reph_pos = start + 1;
+ while (new_reph_pos < base && !is_halant (info[new_reph_pos]))
+ new_reph_pos++;
+
+ if (new_reph_pos < base && is_halant (info[new_reph_pos]))
+ {
+ /* ->If ZWJ or ZWNJ are following this halant, position is moved after it. */
+ if (new_reph_pos + 1 < base && is_joiner (info[new_reph_pos + 1]))
+ new_reph_pos++;
+ goto reph_move;
+ }
+ }
+ /* See https://github.com/harfbuzz/harfbuzz/issues/2298#issuecomment-615318654 */
+
+ /* 6. Otherwise, reorder reph to the end of the syllable.
+ */
+ {
+ new_reph_pos = end - 1;
+ while (new_reph_pos > start && info[new_reph_pos].indic_position() == POS_SMVD)
+ new_reph_pos--;
+
+ /*
+ * If the Reph is to be ending up after a Matra,Halant sequence,
+ * position it before that Halant so it can interact with the Matra.
+ * However, if it's a plain Consonant,Halant we shouldn't do that.
+ * Uniscribe doesn't do this.
+ * TEST: U+0930,U+094D,U+0915,U+094B,U+094D
+ */
+ if (!indic_plan->uniscribe_bug_compatible &&
+ unlikely (is_halant (info[new_reph_pos])))
+ {
+ for (unsigned int i = base + 1; i < new_reph_pos; i++)
+ if (info[i].indic_category() == I_Cat(M)) {
+ /* Ok, got it. */
+ new_reph_pos--;
+ }
+ }
+
+ goto reph_move;
+ }
+
+ reph_move:
+ {
+ /* Move */
+ buffer->merge_clusters (start, new_reph_pos + 1);
+ hb_glyph_info_t reph = info[start];
+ memmove (&info[start], &info[start + 1], (new_reph_pos - start) * sizeof (info[0]));
+ info[new_reph_pos] = reph;
+
+ if (start < base && base <= new_reph_pos)
+ base--;
+ }
+ }
+
+
+ /* o Reorder pre-base-reordering consonants:
+ *
+ * If a pre-base-reordering consonant is found, reorder it according to
+ * the following rules:
+ */
+
+ if (try_pref && base + 1 < end) /* Otherwise there can't be any pre-base-reordering Ra. */
+ {
+ for (unsigned int i = base + 1; i < end; i++)
+ if ((info[i].mask & indic_plan->mask_array[INDIC_PREF]) != 0)
+ {
+ /* 1. Only reorder a glyph produced by substitution during application
+ * of the <pref> feature. (Note that a font may shape a Ra consonant with
+ * the feature generally but block it in certain contexts.)
+ */
+ /* Note: We just check that something got substituted. We don't check that
+ * the <pref> feature actually did it...
+ *
+ * Reorder pref only if it ligated. */
+ if (_hb_glyph_info_ligated_and_didnt_multiply (&info[i]))
+ {
+ /*
+ * 2. Try to find a target position the same way as for pre-base matra.
+ * If it is found, reorder pre-base consonant glyph.
+ *
+ * 3. If position is not found, reorder immediately before main
+ * consonant.
+ */
+
+ unsigned int new_pos = base;
+ /* Malayalam / Tamil do not have "half" forms or explicit virama forms.
+ * The glyphs formed by 'half' are Chillus or ligated explicit viramas.
+ * We want to position matra after them.
+ */
+ if (buffer->props.script != HB_SCRIPT_MALAYALAM && buffer->props.script != HB_SCRIPT_TAMIL)
+ {
+ while (new_pos > start &&
+ !(is_one_of (info[new_pos - 1], FLAG(I_Cat(M)) | FLAG (I_Cat(H)))))
+ new_pos--;
+ }
+
+ if (new_pos > start && is_halant (info[new_pos - 1]))
+ {
+ /* -> If ZWJ or ZWNJ follow this halant, position is moved after it. */
+ if (new_pos < end && is_joiner (info[new_pos]))
+ new_pos++;
+ }
+
+ {
+ unsigned int old_pos = i;
+
+ buffer->merge_clusters (new_pos, old_pos + 1);
+ hb_glyph_info_t tmp = info[old_pos];
+ memmove (&info[new_pos + 1], &info[new_pos], (old_pos - new_pos) * sizeof (info[0]));
+ info[new_pos] = tmp;
+
+ if (new_pos <= base && base < old_pos)
+ base++;
+ }
+ }
+
+ break;
+ }
+ }
+
+
+ /* Apply 'init' to the Left Matra if it's a word start. */
+ if (info[start].indic_position () == POS_PRE_M)
+ {
+ if (!start ||
+ !(FLAG_UNSAFE (_hb_glyph_info_get_general_category (&info[start - 1])) &
+ FLAG_RANGE (HB_UNICODE_GENERAL_CATEGORY_FORMAT, HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)))
+ info[start].mask |= indic_plan->mask_array[INDIC_INIT];
+ else
+ buffer->unsafe_to_break (start - 1, start + 1);
+ }
+
+
+ /*
+ * Finish off the clusters and go home!
+ */
+ if (indic_plan->uniscribe_bug_compatible)
+ {
+ switch ((hb_tag_t) plan->props.script)
+ {
+ case HB_SCRIPT_TAMIL:
+ break;
+
+ default:
+ /* Uniscribe merges the entire syllable into a single cluster... Except for Tamil.
+ * This means, half forms are submerged into the main consonant's cluster.
+ * This is unnecessary, and makes cursor positioning harder, but that's what
+ * Uniscribe does. */
+ buffer->merge_clusters (start, end);
+ break;
+ }
+ }
+}
+
+
+static void
+final_reordering_indic (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ unsigned int count = buffer->len;
+ if (unlikely (!count)) return;
+
+ if (buffer->message (font, "start reordering indic final")) {
+ foreach_syllable (buffer, start, end)
+ final_reordering_syllable_indic (plan, buffer, start, end);
+ (void) buffer->message (font, "end reordering indic final");
+ }
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, indic_category);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, indic_position);
+}
+
+
+static void
+preprocess_text_indic (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
+ if (!indic_plan->uniscribe_bug_compatible)
+ _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+}
+
+static bool
+decompose_indic (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b)
+{
+ switch (ab)
+ {
+ /* Don't decompose these. */
+ case 0x0931u : return false; /* DEVANAGARI LETTER RRA */
+ // https://github.com/harfbuzz/harfbuzz/issues/779
+ case 0x09DCu : return false; /* BENGALI LETTER RRA */
+ case 0x09DDu : return false; /* BENGALI LETTER RHA */
+ case 0x0B94u : return false; /* TAMIL LETTER AU */
+
+
+ /*
+ * Decompose split matras that don't have Unicode decompositions.
+ */
+
+#if 0
+ /* Gujarati */
+ /* This one has no decomposition in Unicode, but needs no decomposition either. */
+ /* case 0x0AC9u : return false; */
+
+ /* Oriya */
+ case 0x0B57u : *a = no decomp, -> RIGHT; return true;
+#endif
+ }
+
+ return (bool) c->unicode->decompose (ab, a, b);
+}
+
+static bool
+compose_indic (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ /* Avoid recomposing split matras. */
+ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
+ return false;
+
+ /* Composition-exclusion exceptions that we want to recompose. */
+ if (a == 0x09AFu && b == 0x09BCu) { *ab = 0x09DFu; return true; }
+
+ return (bool) c->unicode->compose (a, b, ab);
+}
+
+
+const hb_ot_shaper_t _hb_ot_shaper_indic =
+{
+ collect_features_indic,
+ override_features_indic,
+ data_create_indic,
+ data_destroy_indic,
+ preprocess_text_indic,
+ nullptr, /* postprocess_glyphs */
+ decompose_indic,
+ compose_indic,
+ setup_masks_indic,
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh
new file mode 100644
index 0000000000..4f822c26e9
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-indic.hh
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_INDIC_HH
+#define HB_OT_SHAPER_INDIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-syllabic.hh"
+
+
+/* Visual positions in a syllable from left to right. */
+enum ot_position_t {
+ POS_START = 0,
+
+ POS_RA_TO_BECOME_REPH = 1,
+ POS_PRE_M = 2,
+ POS_PRE_C = 3,
+
+ POS_BASE_C = 4,
+ POS_AFTER_MAIN = 5,
+
+ POS_ABOVE_C = 6,
+
+ POS_BEFORE_SUB = 7,
+ POS_BELOW_C = 8,
+ POS_AFTER_SUB = 9,
+
+ POS_BEFORE_POST = 10,
+ POS_POST_C = 11,
+ POS_AFTER_POST = 12,
+
+ POS_SMVD = 13,
+
+ POS_END = 14
+};
+
+
+HB_INTERNAL uint16_t
+hb_indic_get_categories (hb_codepoint_t u);
+
+
+#endif /* HB_OT_SHAPER_INDIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
new file mode 100644
index 0000000000..2c40663bdd
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer-machine.hh
@@ -0,0 +1,428 @@
+
+#line 1 "hb-ot-shaper-khmer-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_KHMER_MACHINE_HH
+#define HB_OT_SHAPER_KHMER_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define khmer_category() ot_shaper_var_u8_category() /* khmer_category_t */
+
+using khmer_category_t = unsigned;
+
+#define K_Cat(Cat) khmer_syllable_machine_ex_##Cat
+
+enum khmer_syllable_type_t {
+ khmer_consonant_syllable,
+ khmer_broken_cluster,
+ khmer_non_khmer_cluster,
+};
+
+
+#line 49 "hb-ot-shaper-khmer-machine.hh"
+#define khmer_syllable_machine_ex_C 1u
+#define khmer_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define khmer_syllable_machine_ex_H 4u
+#define khmer_syllable_machine_ex_PLACEHOLDER 10u
+#define khmer_syllable_machine_ex_Ra 15u
+#define khmer_syllable_machine_ex_Robatic 25u
+#define khmer_syllable_machine_ex_V 2u
+#define khmer_syllable_machine_ex_VAbv 20u
+#define khmer_syllable_machine_ex_VBlw 21u
+#define khmer_syllable_machine_ex_VPre 22u
+#define khmer_syllable_machine_ex_VPst 23u
+#define khmer_syllable_machine_ex_Xgroup 26u
+#define khmer_syllable_machine_ex_Ygroup 27u
+#define khmer_syllable_machine_ex_ZWJ 6u
+#define khmer_syllable_machine_ex_ZWNJ 5u
+
+
+#line 65 "hb-ot-shaper-khmer-machine.hh"
+static const unsigned char _khmer_syllable_machine_trans_keys[] = {
+ 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 15u, 5u, 26u, 5u, 26u,
+ 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 5u, 26u, 1u, 27u, 4u, 27u, 1u, 15u,
+ 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 1u, 15u, 4u, 27u, 4u, 27u, 27u, 27u, 4u, 27u, 4u, 27u, 4u, 27u,
+ 4u, 27u, 4u, 27u, 5u, 26u, 0
+};
+
+static const char _khmer_syllable_machine_key_spans[] = {
+ 22, 22, 15, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 15, 22, 22,
+ 22, 22, 22, 22, 22, 27, 24, 15,
+ 24, 24, 1, 24, 24, 24, 24, 24,
+ 24, 15, 24, 24, 1, 24, 24, 24,
+ 24, 24, 22
+};
+
+static const short _khmer_syllable_machine_index_offsets[] = {
+ 0, 23, 46, 62, 85, 108, 131, 154,
+ 177, 200, 223, 246, 269, 292, 308, 331,
+ 354, 377, 400, 423, 446, 469, 497, 522,
+ 538, 563, 588, 590, 615, 640, 665, 690,
+ 715, 740, 756, 781, 806, 808, 833, 858,
+ 883, 908, 933
+};
+
+static const char _khmer_syllable_machine_indicies[] = {
+ 1, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 3, 4, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 5, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 5, 0, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 4, 0, 6, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 7, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 9, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0,
+ 10, 0, 9, 9, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10,
+ 0, 11, 11, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 12, 0,
+ 11, 11, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 12, 0, 1,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 0, 13, 4, 0, 15, 15,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 16, 14, 14,
+ 14, 14, 17, 18, 14, 15, 15, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 18, 19, 20, 20, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 20, 14, 15, 15, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 16, 14, 14, 14, 14,
+ 14, 18, 14, 21, 21, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 22, 22, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 23,
+ 14, 24, 24, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 16, 14, 14, 14, 14, 14, 25, 14,
+ 24, 24, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 25, 14, 26,
+ 26, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 16, 14,
+ 14, 14, 14, 14, 27, 14, 26, 26,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 27, 14, 29, 29, 28,
+ 30, 31, 31, 28, 28, 28, 13, 13,
+ 28, 28, 28, 29, 28, 28, 28, 28,
+ 16, 25, 27, 23, 28, 17, 18, 20,
+ 28, 33, 34, 34, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 12, 8, 32, 13, 4,
+ 5, 32, 35, 35, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 35, 32, 33, 36, 36, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 3,
+ 4, 5, 32, 37, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 32, 4, 5, 32, 5, 32, 37, 6,
+ 6, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 8, 32, 32, 2, 5, 32, 37,
+ 7, 7, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 8, 5, 32,
+ 37, 39, 39, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 32, 32, 8, 32, 32, 10, 5,
+ 32, 37, 40, 40, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 2, 10, 32, 8, 32, 32, 12,
+ 5, 32, 33, 38, 38, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 2, 10, 12, 8, 32, 32,
+ 4, 5, 32, 33, 38, 38, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 2, 10, 12, 8, 32,
+ 3, 4, 5, 32, 42, 42, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 42, 41, 30, 43, 43, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 17, 18, 20, 41, 44, 45, 45,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 16, 25, 27,
+ 23, 41, 41, 18, 20, 41, 20, 41,
+ 44, 21, 21, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 23, 41, 41, 16, 20,
+ 41, 44, 22, 22, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 23,
+ 20, 41, 44, 46, 46, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 16, 41, 41, 23, 41, 41,
+ 25, 20, 41, 44, 47, 47, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 16, 25, 41, 23, 41,
+ 41, 27, 20, 41, 30, 45, 45, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 16, 25, 27, 23,
+ 41, 41, 18, 20, 41, 15, 15, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 16, 48, 48, 48,
+ 48, 48, 18, 48, 0
+};
+
+static const char _khmer_syllable_machine_trans_targs[] = {
+ 21, 1, 27, 31, 25, 26, 4, 5,
+ 28, 7, 29, 9, 30, 32, 21, 12,
+ 37, 41, 35, 21, 36, 15, 16, 38,
+ 18, 39, 20, 40, 21, 22, 33, 42,
+ 21, 23, 10, 24, 0, 2, 3, 6,
+ 8, 21, 34, 11, 13, 14, 17, 19,
+ 21
+};
+
+static const char _khmer_syllable_machine_trans_actions[] = {
+ 1, 0, 2, 2, 2, 0, 0, 0,
+ 2, 0, 2, 0, 2, 2, 3, 0,
+ 2, 4, 4, 5, 0, 0, 0, 2,
+ 0, 2, 0, 2, 8, 2, 0, 9,
+ 10, 0, 0, 2, 0, 0, 0, 0,
+ 0, 11, 4, 0, 0, 0, 0, 0,
+ 12
+};
+
+static const char _khmer_syllable_machine_to_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const char _khmer_syllable_machine_from_state_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+
+static const short _khmer_syllable_machine_eof_trans[] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 15, 20, 15, 15, 15,
+ 15, 15, 15, 15, 15, 0, 33, 33,
+ 33, 33, 33, 33, 33, 33, 33, 33,
+ 33, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 49
+};
+
+static const int khmer_syllable_machine_start = 21;
+static const int khmer_syllable_machine_first_final = 21;
+static const int khmer_syllable_machine_error = -1;
+
+static const int khmer_syllable_machine_en_main = 21;
+
+
+#line 53 "hb-ot-shaper-khmer-machine.rl"
+
+
+
+#line 102 "hb-ot-shaper-khmer-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_khmer (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 287 "hb-ot-shaper-khmer-machine.hh"
+ {
+ cs = khmer_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 122 "hb-ot-shaper-khmer-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 299 "hb-ot-shaper-khmer-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _khmer_syllable_machine_from_state_actions[cs] ) {
+ case 7:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 311 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ _keys = _khmer_syllable_machine_trans_keys + (cs<<1);
+ _inds = _khmer_syllable_machine_indicies + _khmer_syllable_machine_index_offsets[cs];
+
+ _slen = _khmer_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].khmer_category()) &&
+ ( info[p].khmer_category()) <= _keys[1] ?
+ ( info[p].khmer_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _khmer_syllable_machine_trans_targs[_trans];
+
+ if ( _khmer_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _khmer_syllable_machine_trans_actions[_trans] ) {
+ case 2:
+#line 1 "NONE"
+ {te = p+1;}
+ break;
+ case 8:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p+1;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 10:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 11:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 12:
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {te = p;p--;{ found_syllable (khmer_non_khmer_cluster); }}
+ break;
+ case 1:
+#line 96 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_consonant_syllable); }}
+ break;
+ case 3:
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {{p = ((te))-1;}{ found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 5:
+#line 1 "NONE"
+ { switch( act ) {
+ case 2:
+ {{p = ((te))-1;} found_syllable (khmer_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }
+ break;
+ case 3:
+ {{p = ((te))-1;} found_syllable (khmer_non_khmer_cluster); }
+ break;
+ }
+ }
+ break;
+ case 4:
+#line 1 "NONE"
+ {te = p+1;}
+#line 97 "hb-ot-shaper-khmer-machine.rl"
+ {act = 2;}
+ break;
+ case 9:
+#line 1 "NONE"
+ {te = p+1;}
+#line 98 "hb-ot-shaper-khmer-machine.rl"
+ {act = 3;}
+ break;
+#line 368 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+_again:
+ switch ( _khmer_syllable_machine_to_state_actions[cs] ) {
+ case 6:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 375 "hb-ot-shaper-khmer-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _khmer_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _khmer_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 130 "hb-ot-shaper-khmer-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_KHMER_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
new file mode 100644
index 0000000000..d9795589fa
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-khmer.cc
@@ -0,0 +1,382 @@
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-khmer-machine.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-layout.hh"
+
+
+/*
+ * Khmer shaper.
+ */
+
+
+static const hb_ot_map_feature_t
+khmer_features[] =
+{
+ /*
+ * Basic features.
+ * These features are applied all at once, before reordering, constrained
+ * to the syllable.
+ */
+ {HB_TAG('p','r','e','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('b','l','w','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('a','b','v','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('p','s','t','f'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ {HB_TAG('c','f','a','r'), F_MANUAL_JOINERS | F_PER_SYLLABLE},
+ /*
+ * Other features.
+ * These features are applied all at once after clearing syllables.
+ */
+ {HB_TAG('p','r','e','s'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('a','b','v','s'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('b','l','w','s'), F_GLOBAL_MANUAL_JOINERS},
+ {HB_TAG('p','s','t','s'), F_GLOBAL_MANUAL_JOINERS},
+};
+
+/*
+ * Must be in the same order as the khmer_features array.
+ */
+enum {
+ KHMER_PREF,
+ KHMER_BLWF,
+ KHMER_ABVF,
+ KHMER_PSTF,
+ KHMER_CFAR,
+
+ _KHMER_PRES,
+ _KHMER_ABVS,
+ _KHMER_BLWS,
+ _KHMER_PSTS,
+
+ KHMER_NUM_FEATURES,
+ KHMER_BASIC_FEATURES = _KHMER_PRES, /* Don't forget to update this! */
+};
+
+static inline void
+set_khmer_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.khmer_category() = (khmer_category_t) (type & 0xFFu);
+}
+
+static void
+setup_syllables_khmer (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+reorder_khmer (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+collect_features_khmer (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* Do this before any lookups have been applied. */
+ map->add_gsub_pause (setup_syllables_khmer);
+ map->add_gsub_pause (reorder_khmer);
+
+ /* Testing suggests that Uniscribe does NOT pause between basic
+ * features. Test with KhmerUI.ttf and the following three
+ * sequences:
+ *
+ * U+1789,U+17BC
+ * U+1789,U+17D2,U+1789
+ * U+1789,U+17D2,U+1789,U+17BC
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/974
+ */
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+
+ unsigned int i = 0;
+ for (; i < KHMER_BASIC_FEATURES; i++)
+ map->add_feature (khmer_features[i]);
+
+ /* https://github.com/harfbuzz/harfbuzz/issues/3531 */
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
+
+ for (; i < KHMER_NUM_FEATURES; i++)
+ map->add_feature (khmer_features[i]);
+}
+
+static void
+override_features_khmer (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* Khmer spec has 'clig' as part of required shaping features:
+ * "Apply feature 'clig' to form ligatures that are desired for
+ * typographical correctness.", hence in overrides... */
+ map->enable_feature (HB_TAG('c','l','i','g'));
+
+ /* Uniscribe does not apply 'kern' in Khmer. */
+ if (hb_options ().uniscribe_bug_compatible)
+ {
+ map->disable_feature (HB_TAG('k','e','r','n'));
+ }
+
+ map->disable_feature (HB_TAG('l','i','g','a'));
+}
+
+
+struct khmer_shape_plan_t
+{
+ hb_mask_t mask_array[KHMER_NUM_FEATURES];
+};
+
+static void *
+data_create_khmer (const hb_ot_shape_plan_t *plan)
+{
+ khmer_shape_plan_t *khmer_plan = (khmer_shape_plan_t *) hb_calloc (1, sizeof (khmer_shape_plan_t));
+ if (unlikely (!khmer_plan))
+ return nullptr;
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (khmer_plan->mask_array); i++)
+ khmer_plan->mask_array[i] = (khmer_features[i].flags & F_GLOBAL) ?
+ 0 : plan->map.get_1_mask (khmer_features[i].tag);
+
+ return khmer_plan;
+}
+
+static void
+data_destroy_khmer (void *data)
+{
+ hb_free (data);
+}
+
+static void
+setup_masks_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, khmer_category);
+
+ /* We cannot setup masks here. We save information about characters
+ * and setup masks later on in a pause-callback. */
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ set_khmer_properties (info[i]);
+}
+
+static void
+setup_syllables_khmer (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+ find_syllables_khmer (buffer);
+ foreach_syllable (buffer, start, end)
+ buffer->unsafe_to_break (start, end);
+}
+
+
+/* Rules from:
+ * https://docs.microsoft.com/en-us/typography/script-development/devanagari */
+
+static void
+reorder_consonant_syllable (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ const khmer_shape_plan_t *khmer_plan = (const khmer_shape_plan_t *) plan->data;
+ hb_glyph_info_t *info = buffer->info;
+
+ /* Setup masks. */
+ {
+ /* Post-base */
+ hb_mask_t mask = khmer_plan->mask_array[KHMER_BLWF] |
+ khmer_plan->mask_array[KHMER_ABVF] |
+ khmer_plan->mask_array[KHMER_PSTF];
+ for (unsigned int i = start + 1; i < end; i++)
+ info[i].mask |= mask;
+ }
+
+ unsigned int num_coengs = 0;
+ for (unsigned int i = start + 1; i < end; i++)
+ {
+ /* """
+ * When a COENG + (Cons | IndV) combination are found (and subscript count
+ * is less than two) the character combination is handled according to the
+ * subscript type of the character following the COENG.
+ *
+ * ...
+ *
+ * Subscript Type 2 - The COENG + RO characters are reordered to immediately
+ * before the base glyph. Then the COENG + RO characters are assigned to have
+ * the 'pref' OpenType feature applied to them.
+ * """
+ */
+ if (info[i].khmer_category() == K_Cat(H) && num_coengs <= 2 && i + 1 < end)
+ {
+ num_coengs++;
+
+ if (info[i + 1].khmer_category() == K_Cat(Ra))
+ {
+ for (unsigned int j = 0; j < 2; j++)
+ info[i + j].mask |= khmer_plan->mask_array[KHMER_PREF];
+
+ /* Move the Coeng,Ro sequence to the start. */
+ buffer->merge_clusters (start, i + 2);
+ hb_glyph_info_t t0 = info[i];
+ hb_glyph_info_t t1 = info[i + 1];
+ memmove (&info[start + 2], &info[start], (i - start) * sizeof (info[0]));
+ info[start] = t0;
+ info[start + 1] = t1;
+
+ /* Mark the subsequent stuff with 'cfar'. Used in Khmer.
+ * Read the feature spec.
+ * This allows distinguishing the following cases with MS Khmer fonts:
+ * U+1784,U+17D2,U+179A,U+17D2,U+1782
+ * U+1784,U+17D2,U+1782,U+17D2,U+179A
+ */
+ if (khmer_plan->mask_array[KHMER_CFAR])
+ for (unsigned int j = i + 2; j < end; j++)
+ info[j].mask |= khmer_plan->mask_array[KHMER_CFAR];
+
+ num_coengs = 2; /* Done. */
+ }
+ }
+
+ /* Reorder left matra piece. */
+ else if (info[i].khmer_category() == K_Cat(VPre))
+ {
+ /* Move to the start. */
+ buffer->merge_clusters (start, i + 1);
+ hb_glyph_info_t t = info[i];
+ memmove (&info[start + 1], &info[start], (i - start) * sizeof (info[0]));
+ info[start] = t;
+ }
+ }
+}
+
+static void
+reorder_syllable_khmer (const hb_ot_shape_plan_t *plan,
+ hb_face_t *face,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ khmer_syllable_type_t syllable_type = (khmer_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
+ switch (syllable_type)
+ {
+ case khmer_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
+ case khmer_consonant_syllable:
+ reorder_consonant_syllable (plan, face, buffer, start, end);
+ break;
+
+ case khmer_non_khmer_cluster:
+ break;
+ }
+}
+
+static void
+reorder_khmer (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ if (buffer->message (font, "start reordering khmer"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ khmer_broken_cluster,
+ K_Cat(DOTTEDCIRCLE),
+ (unsigned) -1);
+
+ foreach_syllable (buffer, start, end)
+ reorder_syllable_khmer (plan, font->face, buffer, start, end);
+ (void) buffer->message (font, "end reordering khmer");
+ }
+ HB_BUFFER_DEALLOCATE_VAR (buffer, khmer_category);
+}
+
+
+static bool
+decompose_khmer (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b)
+{
+ switch (ab)
+ {
+ /*
+ * Decompose split matras that don't have Unicode decompositions.
+ */
+
+ /* Khmer */
+ case 0x17BEu : *a = 0x17C1u; *b= 0x17BEu; return true;
+ case 0x17BFu : *a = 0x17C1u; *b= 0x17BFu; return true;
+ case 0x17C0u : *a = 0x17C1u; *b= 0x17C0u; return true;
+ case 0x17C4u : *a = 0x17C1u; *b= 0x17C4u; return true;
+ case 0x17C5u : *a = 0x17C1u; *b= 0x17C5u; return true;
+ }
+
+ return (bool) c->unicode->decompose (ab, a, b);
+}
+
+static bool
+compose_khmer (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ /* Avoid recomposing split matras. */
+ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
+ return false;
+
+ return (bool) c->unicode->compose (a, b, ab);
+}
+
+
+const hb_ot_shaper_t _hb_ot_shaper_khmer =
+{
+ collect_features_khmer,
+ override_features_khmer,
+ data_create_khmer,
+ data_destroy_khmer,
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ decompose_khmer,
+ compose_khmer,
+ setup_masks_khmer,
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
new file mode 100644
index 0000000000..464cf796d4
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar-machine.hh
@@ -0,0 +1,553 @@
+
+#line 1 "hb-ot-shaper-myanmar-machine.rl"
+/*
+ * Copyright © 2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_MYANMAR_MACHINE_HH
+#define HB_OT_SHAPER_MYANMAR_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shaper-indic.hh"
+
+/* buffer var allocations */
+#define myanmar_category() ot_shaper_var_u8_category() /* myanmar_category_t */
+#define myanmar_position() ot_shaper_var_u8_auxiliary() /* myanmar_position_t */
+
+using myanmar_category_t = unsigned;
+using myanmar_position_t = ot_position_t;
+
+#define M_Cat(Cat) myanmar_syllable_machine_ex_##Cat
+
+enum myanmar_syllable_type_t {
+ myanmar_consonant_syllable,
+ myanmar_broken_cluster,
+ myanmar_non_myanmar_cluster,
+};
+
+
+#line 51 "hb-ot-shaper-myanmar-machine.hh"
+#define myanmar_syllable_machine_ex_A 9u
+#define myanmar_syllable_machine_ex_As 32u
+#define myanmar_syllable_machine_ex_C 1u
+#define myanmar_syllable_machine_ex_CS 18u
+#define myanmar_syllable_machine_ex_DB 3u
+#define myanmar_syllable_machine_ex_DOTTEDCIRCLE 11u
+#define myanmar_syllable_machine_ex_GB 10u
+#define myanmar_syllable_machine_ex_H 4u
+#define myanmar_syllable_machine_ex_IV 2u
+#define myanmar_syllable_machine_ex_MH 35u
+#define myanmar_syllable_machine_ex_ML 41u
+#define myanmar_syllable_machine_ex_MR 36u
+#define myanmar_syllable_machine_ex_MW 37u
+#define myanmar_syllable_machine_ex_MY 38u
+#define myanmar_syllable_machine_ex_PT 39u
+#define myanmar_syllable_machine_ex_Ra 15u
+#define myanmar_syllable_machine_ex_SM 8u
+#define myanmar_syllable_machine_ex_VAbv 20u
+#define myanmar_syllable_machine_ex_VBlw 21u
+#define myanmar_syllable_machine_ex_VPre 22u
+#define myanmar_syllable_machine_ex_VPst 23u
+#define myanmar_syllable_machine_ex_VS 40u
+#define myanmar_syllable_machine_ex_ZWJ 6u
+#define myanmar_syllable_machine_ex_ZWNJ 5u
+
+
+#line 76 "hb-ot-shaper-myanmar-machine.hh"
+static const unsigned char _myanmar_syllable_machine_trans_keys[] = {
+ 1u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+ 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 39u, 3u, 39u,
+ 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 41u,
+ 3u, 41u, 3u, 41u, 5u, 39u, 5u, 8u, 3u, 41u, 3u, 39u, 3u, 39u, 5u, 39u,
+ 5u, 39u, 3u, 39u, 3u, 39u, 3u, 41u, 5u, 39u, 1u, 15u, 3u, 41u, 3u, 39u,
+ 3u, 39u, 3u, 40u, 3u, 39u, 3u, 41u, 3u, 41u, 3u, 39u, 3u, 41u, 3u, 41u,
+ 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 3u, 41u, 1u, 41u, 1u, 15u, 0
+};
+
+static const char _myanmar_syllable_machine_key_spans[] = {
+ 41, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 37, 37,
+ 38, 37, 39, 39, 37, 39, 39, 39,
+ 39, 39, 35, 4, 39, 37, 37, 35,
+ 35, 37, 37, 39, 35, 15, 39, 37,
+ 37, 38, 37, 39, 39, 37, 39, 39,
+ 39, 39, 39, 39, 39, 41, 15
+};
+
+static const short _myanmar_syllable_machine_index_offsets[] = {
+ 0, 42, 82, 118, 123, 163, 201, 239,
+ 275, 311, 349, 387, 427, 463, 479, 517,
+ 555, 594, 632, 672, 712, 750, 790, 830,
+ 870, 910, 950, 986, 991, 1031, 1069, 1107,
+ 1143, 1179, 1217, 1255, 1295, 1331, 1347, 1387,
+ 1425, 1463, 1502, 1540, 1580, 1620, 1658, 1698,
+ 1738, 1778, 1818, 1858, 1898, 1938, 1980
+};
+
+static const char _myanmar_syllable_machine_indicies[] = {
+ 1, 1, 2, 3, 4, 4, 0, 5,
+ 6, 1, 1, 0, 0, 0, 7, 0,
+ 0, 8, 0, 9, 10, 11, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 13,
+ 0, 0, 14, 15, 16, 17, 18, 19,
+ 20, 0, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 24, 24, 21, 25, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 39, 21, 21,
+ 21, 21, 21, 21, 36, 21, 24, 24,
+ 21, 25, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 42, 21, 21, 21, 36,
+ 21, 41, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 21, 43, 21, 24, 24, 21, 25, 36,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 44, 21,
+ 21, 21, 21, 21, 21, 36, 21, 24,
+ 24, 21, 25, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 44, 21, 21, 21, 21, 21,
+ 21, 36, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 40, 21, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 40, 21,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 41, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 40, 21, 21, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 41, 21, 21, 21, 21, 21, 21, 36,
+ 21, 41, 21, 24, 24, 21, 25, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 30, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 36, 21, 1,
+ 1, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 1, 21, 22,
+ 21, 24, 24, 21, 25, 26, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 27, 28, 21, 30, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 36, 21, 22, 21, 24,
+ 24, 21, 25, 26, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 28,
+ 21, 30, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 36, 21, 22, 21, 24, 24, 21,
+ 25, 26, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 27, 28, 29, 30,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 36,
+ 45, 21, 22, 21, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 36, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 31, 21, 21,
+ 32, 33, 34, 35, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 38, 21,
+ 22, 21, 24, 24, 21, 25, 26, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 27, 28, 29, 30, 21, 21, 21,
+ 21, 21, 21, 21, 21, 45, 21, 21,
+ 21, 21, 21, 21, 36, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 21,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 45, 21, 21, 32, 21,
+ 21, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 46, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 21,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 32, 33,
+ 34, 21, 36, 21, 38, 21, 22, 23,
+ 24, 24, 21, 25, 26, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 27,
+ 28, 29, 30, 21, 21, 21, 21, 21,
+ 21, 21, 21, 31, 21, 21, 32, 33,
+ 34, 35, 36, 21, 38, 21, 48, 48,
+ 47, 5, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 49, 47, 47, 47, 47, 47, 47,
+ 18, 47, 48, 48, 47, 5, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 52,
+ 47, 47, 47, 18, 47, 51, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 47, 53, 47, 48,
+ 48, 47, 5, 18, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 54, 47, 47, 47, 47, 47,
+ 47, 18, 47, 48, 48, 47, 5, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 54, 47,
+ 47, 47, 47, 47, 47, 18, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 50, 47, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 50, 47, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 51, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 50, 47, 47, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 51, 47, 47, 47,
+ 47, 47, 47, 18, 47, 51, 47, 48,
+ 48, 47, 5, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 12, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 18, 47, 55, 55, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 55, 47, 2, 3, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 11, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 13, 47, 47, 14, 15, 16, 17, 18,
+ 19, 20, 47, 2, 47, 48, 48, 47,
+ 5, 6, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 9, 10, 47, 12,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 18,
+ 47, 2, 47, 48, 48, 47, 5, 6,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 10, 47, 12, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 18, 47, 2,
+ 47, 48, 48, 47, 5, 6, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 9, 10, 11, 12, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 18, 56, 47, 2, 47,
+ 48, 48, 47, 5, 6, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 9,
+ 10, 11, 12, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 18, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 20, 47, 2, 47, 48, 48,
+ 47, 5, 6, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 56, 47, 47, 47, 47, 47, 47,
+ 18, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 47, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 56,
+ 47, 47, 14, 47, 47, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 57,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 47, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 14, 15, 16, 47, 18, 47,
+ 20, 47, 2, 3, 48, 48, 47, 5,
+ 6, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 9, 10, 11, 12, 47,
+ 47, 47, 47, 47, 47, 47, 47, 13,
+ 47, 47, 14, 15, 16, 17, 18, 47,
+ 20, 47, 22, 23, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 58,
+ 21, 21, 32, 33, 34, 35, 36, 37,
+ 38, 21, 22, 59, 24, 24, 21, 25,
+ 26, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 27, 28, 29, 30, 21,
+ 21, 21, 21, 21, 21, 21, 21, 31,
+ 21, 21, 32, 33, 34, 35, 36, 21,
+ 38, 21, 1, 1, 2, 3, 48, 48,
+ 47, 5, 6, 1, 1, 47, 47, 47,
+ 1, 47, 47, 47, 47, 9, 10, 11,
+ 12, 47, 47, 47, 47, 47, 47, 47,
+ 47, 13, 47, 47, 14, 15, 16, 17,
+ 18, 19, 20, 47, 1, 1, 60, 60,
+ 60, 60, 60, 60, 60, 1, 1, 60,
+ 60, 60, 1, 60, 0
+};
+
+static const char _myanmar_syllable_machine_trans_targs[] = {
+ 0, 1, 26, 37, 0, 27, 29, 51,
+ 54, 39, 40, 41, 28, 43, 44, 46,
+ 47, 48, 30, 50, 45, 0, 2, 13,
+ 0, 3, 5, 14, 15, 16, 4, 18,
+ 19, 21, 22, 23, 6, 25, 20, 12,
+ 9, 10, 11, 7, 8, 17, 24, 0,
+ 0, 36, 33, 34, 35, 31, 32, 38,
+ 42, 49, 52, 53, 0
+};
+
+static const char _myanmar_syllable_machine_trans_actions[] = {
+ 3, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 5, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 7,
+ 8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9
+};
+
+static const char _myanmar_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const char _myanmar_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+static const short _myanmar_syllable_machine_eof_trans[] = {
+ 0, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 22, 22, 48, 61
+};
+
+static const int myanmar_syllable_machine_start = 0;
+static const int myanmar_syllable_machine_first_final = 0;
+static const int myanmar_syllable_machine_error = -1;
+
+static const int myanmar_syllable_machine_en_main = 0;
+
+
+#line 55 "hb-ot-shaper-myanmar-machine.rl"
+
+
+
+#line 117 "hb-ot-shaper-myanmar-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", ts, te, #syllable_type); \
+ for (unsigned int i = ts; i < te; i++) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+inline void
+find_syllables_myanmar (hb_buffer_t *buffer)
+{
+ unsigned int p, pe, eof, ts, te, act HB_UNUSED;
+ int cs;
+ hb_glyph_info_t *info = buffer->info;
+
+#line 436 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ cs = myanmar_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 137 "hb-ot-shaper-myanmar-machine.rl"
+
+
+ p = 0;
+ pe = eof = buffer->len;
+
+ unsigned int syllable_serial = 1;
+
+#line 448 "hb-ot-shaper-myanmar-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _myanmar_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 460 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ _keys = _myanmar_syllable_machine_trans_keys + (cs<<1);
+ _inds = _myanmar_syllable_machine_indicies + _myanmar_syllable_machine_index_offsets[cs];
+
+ _slen = _myanmar_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( info[p].myanmar_category()) &&
+ ( info[p].myanmar_category()) <= _keys[1] ?
+ ( info[p].myanmar_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _myanmar_syllable_machine_trans_targs[_trans];
+
+ if ( _myanmar_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _myanmar_syllable_machine_trans_actions[_trans] ) {
+ case 6:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 4:
+#line 111 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 8:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p+1;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+ case 5:
+#line 110 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_consonant_syllable); }}
+ break;
+ case 7:
+#line 112 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 9:
+#line 113 "hb-ot-shaper-myanmar-machine.rl"
+ {te = p;p--;{ found_syllable (myanmar_non_myanmar_cluster); }}
+ break;
+#line 498 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+_again:
+ switch ( _myanmar_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 505 "hb-ot-shaper-myanmar-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _myanmar_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _myanmar_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 145 "hb-ot-shaper-myanmar-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_MYANMAR_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
new file mode 100644
index 0000000000..78bd8de524
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-myanmar.cc
@@ -0,0 +1,356 @@
+/*
+ * Copyright © 2011,2012,2013 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-myanmar-machine.hh"
+#include "hb-ot-shaper-indic.hh"
+#include "hb-ot-layout.hh"
+
+
+/*
+ * Myanmar shaper.
+ */
+
+
+static const hb_tag_t
+myanmar_basic_features[] =
+{
+ /*
+ * Basic features.
+ * These features are applied in order, one at a time, after reordering,
+ * constrained to the syllable.
+ */
+ HB_TAG('r','p','h','f'),
+ HB_TAG('p','r','e','f'),
+ HB_TAG('b','l','w','f'),
+ HB_TAG('p','s','t','f'),
+};
+static const hb_tag_t
+myanmar_other_features[] =
+{
+ /*
+ * Other features.
+ * These features are applied all at once, after clearing syllables.
+ */
+ HB_TAG('p','r','e','s'),
+ HB_TAG('a','b','v','s'),
+ HB_TAG('b','l','w','s'),
+ HB_TAG('p','s','t','s'),
+};
+
+static inline void
+set_myanmar_properties (hb_glyph_info_t &info)
+{
+ hb_codepoint_t u = info.codepoint;
+ unsigned int type = hb_indic_get_categories (u);
+
+ info.myanmar_category() = (myanmar_category_t) (type & 0xFFu);
+}
+
+
+static inline bool
+is_one_of_myanmar (const hb_glyph_info_t &info, unsigned int flags)
+{
+ /* If it ligated, all bets are off. */
+ if (_hb_glyph_info_ligated (&info)) return false;
+ return !!(FLAG_UNSAFE (info.myanmar_category()) & flags);
+}
+
+/* Note:
+ *
+ * We treat Vowels and placeholders as if they were consonants. This is safe because Vowels
+ * cannot happen in a consonant syllable. The plus side however is, we can call the
+ * consonant syllable logic from the vowel syllable function and get it all right!
+ *
+ * Keep in sync with consonant_categories in the generator. */
+#define CONSONANT_FLAGS_MYANMAR (FLAG (M_Cat(C)) | FLAG (M_Cat(CS)) | FLAG (M_Cat(Ra)) | /* FLAG (M_Cat(CM)) | */ FLAG (M_Cat(IV)) | FLAG (M_Cat(GB)) | FLAG (M_Cat(DOTTEDCIRCLE)))
+
+static inline bool
+is_consonant_myanmar (const hb_glyph_info_t &info)
+{
+ return is_one_of_myanmar (info, CONSONANT_FLAGS_MYANMAR);
+}
+
+
+static void
+setup_syllables_myanmar (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+reorder_myanmar (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+collect_features_myanmar (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* Do this before any lookups have been applied. */
+ map->add_gsub_pause (setup_syllables_myanmar);
+
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ /* The Indic specs do not require ccmp, but we apply it here since if
+ * there is a use of it, it's typically at the beginning. */
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+
+
+ map->add_gsub_pause (reorder_myanmar);
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_basic_features); i++)
+ {
+ map->enable_feature (myanmar_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
+ map->add_gsub_pause (nullptr);
+ }
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
+
+ for (unsigned int i = 0; i < ARRAY_LENGTH (myanmar_other_features); i++)
+ map->enable_feature (myanmar_other_features[i], F_MANUAL_ZWJ);
+}
+
+static void
+setup_masks_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_category);
+ HB_BUFFER_ALLOCATE_VAR (buffer, myanmar_position);
+
+ /* No masks, we just save information about characters. */
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ set_myanmar_properties (info[i]);
+}
+
+static void
+setup_syllables_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+ find_syllables_myanmar (buffer);
+ foreach_syllable (buffer, start, end)
+ buffer->unsafe_to_break (start, end);
+}
+
+static int
+compare_myanmar_order (const hb_glyph_info_t *pa, const hb_glyph_info_t *pb)
+{
+ int a = pa->myanmar_position();
+ int b = pb->myanmar_position();
+
+ return (int) a - (int) b;
+}
+
+
+/* Rules from:
+ * https://docs.microsoft.com/en-us/typography/script-development/myanmar */
+
+static void
+initial_reordering_consonant_syllable (hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ unsigned int base = end;
+ bool has_reph = false;
+
+ {
+ unsigned int limit = start;
+ if (start + 3 <= end &&
+ info[start ].myanmar_category() == M_Cat(Ra) &&
+ info[start+1].myanmar_category() == M_Cat(As) &&
+ info[start+2].myanmar_category() == M_Cat(H))
+ {
+ limit += 3;
+ base = start;
+ has_reph = true;
+ }
+
+ {
+ if (!has_reph)
+ base = limit;
+
+ for (unsigned int i = limit; i < end; i++)
+ if (is_consonant_myanmar (info[i]))
+ {
+ base = i;
+ break;
+ }
+ }
+ }
+
+ /* Reorder! */
+ {
+ unsigned int i = start;
+ for (; i < start + (has_reph ? 3 : 0); i++)
+ info[i].myanmar_position() = POS_AFTER_MAIN;
+ for (; i < base; i++)
+ info[i].myanmar_position() = POS_PRE_C;
+ if (i < end)
+ {
+ info[i].myanmar_position() = POS_BASE_C;
+ i++;
+ }
+ myanmar_position_t pos = POS_AFTER_MAIN;
+ /* The following loop may be ugly, but it implements all of
+ * Myanmar reordering! */
+ for (; i < end; i++)
+ {
+ if (info[i].myanmar_category() == M_Cat(MR)) /* Pre-base reordering */
+ {
+ info[i].myanmar_position() = POS_PRE_C;
+ continue;
+ }
+ if (info[i].myanmar_category() == M_Cat(VPre)) /* Left matra */
+ {
+ info[i].myanmar_position() = POS_PRE_M;
+ continue;
+ }
+ if (info[i].myanmar_category() == M_Cat(VS))
+ {
+ info[i].myanmar_position() = info[i - 1].myanmar_position();
+ continue;
+ }
+
+ if (pos == POS_AFTER_MAIN && info[i].myanmar_category() == M_Cat(VBlw))
+ {
+ pos = POS_BELOW_C;
+ info[i].myanmar_position() = pos;
+ continue;
+ }
+
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(A))
+ {
+ info[i].myanmar_position() = POS_BEFORE_SUB;
+ continue;
+ }
+ if (pos == POS_BELOW_C && info[i].myanmar_category() == M_Cat(VBlw))
+ {
+ info[i].myanmar_position() = pos;
+ continue;
+ }
+ if (pos == POS_BELOW_C && info[i].myanmar_category() != M_Cat(A))
+ {
+ pos = POS_AFTER_SUB;
+ info[i].myanmar_position() = pos;
+ continue;
+ }
+ info[i].myanmar_position() = pos;
+ }
+ }
+
+ /* Sit tight, rock 'n roll! */
+ buffer->sort (start, end, compare_myanmar_order);
+}
+
+static void
+reorder_syllable_myanmar (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_face_t *face HB_UNUSED,
+ hb_buffer_t *buffer,
+ unsigned int start, unsigned int end)
+{
+ myanmar_syllable_type_t syllable_type = (myanmar_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
+ switch (syllable_type) {
+
+ case myanmar_broken_cluster: /* We already inserted dotted-circles, so just call the consonant_syllable. */
+ case myanmar_consonant_syllable:
+ initial_reordering_consonant_syllable (buffer, start, end);
+ break;
+
+ case myanmar_non_myanmar_cluster:
+ break;
+ }
+}
+
+static void
+reorder_myanmar (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ if (buffer->message (font, "start reordering myanmar"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ myanmar_broken_cluster,
+ M_Cat(DOTTEDCIRCLE));
+
+ foreach_syllable (buffer, start, end)
+ reorder_syllable_myanmar (plan, font->face, buffer, start, end);
+ (void) buffer->message (font, "end reordering myanmar");
+ }
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_category);
+ HB_BUFFER_DEALLOCATE_VAR (buffer, myanmar_position);
+}
+
+
+const hb_ot_shaper_t _hb_ot_shaper_myanmar =
+{
+ collect_features_myanmar,
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ setup_masks_myanmar,
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+ false, /* fallback_position */
+};
+
+
+/* Ugly Zawgyi encoding.
+ * Disable all auto processing.
+ * https://github.com/harfbuzz/harfbuzz/issues/1162 */
+const hb_ot_shaper_t _hb_ot_shaper_myanmar_zawgyi =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ nullptr, /* preprocess_text */
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ nullptr, /* setup_masks */
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_NONE,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
new file mode 100644
index 0000000000..a8e0d8e8c1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2021 Behdad Esfahbod.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-syllabic.hh"
+
+
+void
+hb_syllabic_insert_dotted_circles (hb_font_t *font,
+ hb_buffer_t *buffer,
+ unsigned int broken_syllable_type,
+ unsigned int dottedcircle_category,
+ int repha_category,
+ int dottedcircle_position)
+{
+ if (unlikely (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE))
+ return;
+ if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE)))
+ return;
+
+ hb_codepoint_t dottedcircle_glyph;
+ if (!font->get_nominal_glyph (0x25CCu, &dottedcircle_glyph))
+ return;
+
+ hb_glyph_info_t dottedcircle = {0};
+ dottedcircle.codepoint = 0x25CCu;
+ dottedcircle.ot_shaper_var_u8_category() = dottedcircle_category;
+ if (dottedcircle_position != -1)
+ dottedcircle.ot_shaper_var_u8_auxiliary() = dottedcircle_position;
+ dottedcircle.codepoint = dottedcircle_glyph;
+
+ buffer->clear_output ();
+
+ buffer->idx = 0;
+ unsigned int last_syllable = 0;
+ while (buffer->idx < buffer->len && buffer->successful)
+ {
+ unsigned int syllable = buffer->cur().syllable();
+ if (unlikely (last_syllable != syllable && (syllable & 0x0F) == broken_syllable_type))
+ {
+ last_syllable = syllable;
+
+ hb_glyph_info_t ginfo = dottedcircle;
+ ginfo.cluster = buffer->cur().cluster;
+ ginfo.mask = buffer->cur().mask;
+ ginfo.syllable() = buffer->cur().syllable();
+
+ /* Insert dottedcircle after possible Repha. */
+ if (repha_category != -1)
+ {
+ while (buffer->idx < buffer->len && buffer->successful &&
+ last_syllable == buffer->cur().syllable() &&
+ buffer->cur().ot_shaper_var_u8_category() == (unsigned) repha_category)
+ (void) buffer->next_glyph ();
+ }
+
+ (void) buffer->output_info (ginfo);
+ }
+ else
+ (void) buffer->next_glyph ();
+ }
+ buffer->sync ();
+}
+
+HB_INTERNAL void
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
+}
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
new file mode 100644
index 0000000000..e8a15bb48a
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-syllabic.hh
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2021 Behdad Esfahbod.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#ifndef HB_OT_SHAPER_SYLLABIC_HH
+#define HB_OT_SHAPER_SYLLABIC_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper.hh"
+
+
+HB_INTERNAL void
+hb_syllabic_insert_dotted_circles (hb_font_t *font,
+ hb_buffer_t *buffer,
+ unsigned int broken_syllable_type,
+ unsigned int dottedcircle_category,
+ int repha_category = -1,
+ int dottedcircle_position = -1);
+
+HB_INTERNAL void
+hb_syllabic_clear_var (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+
+#endif /* HB_OT_SHAPER_SYLLABIC_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
new file mode 100644
index 0000000000..15349b1e64
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
@@ -0,0 +1,393 @@
+/*
+ * Copyright © 2010,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper.hh"
+
+
+/* Thai / Lao shaper */
+
+
+/* PUA shaping */
+
+
+enum thai_consonant_type_t
+{
+ NC,
+ AC,
+ RC,
+ DC,
+ NOT_CONSONANT,
+ NUM_CONSONANT_TYPES = NOT_CONSONANT
+};
+
+static thai_consonant_type_t
+get_consonant_type (hb_codepoint_t u)
+{
+ if (u == 0x0E1Bu || u == 0x0E1Du || u == 0x0E1Fu/* || u == 0x0E2Cu*/)
+ return AC;
+ if (u == 0x0E0Du || u == 0x0E10u)
+ return RC;
+ if (u == 0x0E0Eu || u == 0x0E0Fu)
+ return DC;
+ if (hb_in_range<hb_codepoint_t> (u, 0x0E01u, 0x0E2Eu))
+ return NC;
+ return NOT_CONSONANT;
+}
+
+
+enum thai_mark_type_t
+{
+ AV,
+ BV,
+ T,
+ NOT_MARK,
+ NUM_MARK_TYPES = NOT_MARK
+};
+
+static thai_mark_type_t
+get_mark_type (hb_codepoint_t u)
+{
+ if (u == 0x0E31u || hb_in_range<hb_codepoint_t> (u, 0x0E34u, 0x0E37u) ||
+ u == 0x0E47u || hb_in_range<hb_codepoint_t> (u, 0x0E4Du, 0x0E4Eu))
+ return AV;
+ if (hb_in_range<hb_codepoint_t> (u, 0x0E38u, 0x0E3Au))
+ return BV;
+ if (hb_in_range<hb_codepoint_t> (u, 0x0E48u, 0x0E4Cu))
+ return T;
+ return NOT_MARK;
+}
+
+
+enum thai_action_t
+{
+ NOP,
+ SD, /* Shift combining-mark down */
+ SL, /* Shift combining-mark left */
+ SDL, /* Shift combining-mark down-left */
+ RD /* Remove descender from base */
+};
+
+static hb_codepoint_t
+thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
+{
+ struct thai_pua_mapping_t {
+ hb_codepoint_t u;
+ hb_codepoint_t win_pua;
+ hb_codepoint_t mac_pua;
+ } const *pua_mappings = nullptr;
+ static const thai_pua_mapping_t SD_mappings[] = {
+ {0x0E48u, 0xF70Au, 0xF88Bu}, /* MAI EK */
+ {0x0E49u, 0xF70Bu, 0xF88Eu}, /* MAI THO */
+ {0x0E4Au, 0xF70Cu, 0xF891u}, /* MAI TRI */
+ {0x0E4Bu, 0xF70Du, 0xF894u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF70Eu, 0xF897u}, /* THANTHAKHAT */
+ {0x0E38u, 0xF718u, 0xF89Bu}, /* SARA U */
+ {0x0E39u, 0xF719u, 0xF89Cu}, /* SARA UU */
+ {0x0E3Au, 0xF71Au, 0xF89Du}, /* PHINTHU */
+ {0x0000u, 0x0000u, 0x0000u}
+ };
+ static const thai_pua_mapping_t SDL_mappings[] = {
+ {0x0E48u, 0xF705u, 0xF88Cu}, /* MAI EK */
+ {0x0E49u, 0xF706u, 0xF88Fu}, /* MAI THO */
+ {0x0E4Au, 0xF707u, 0xF892u}, /* MAI TRI */
+ {0x0E4Bu, 0xF708u, 0xF895u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF709u, 0xF898u}, /* THANTHAKHAT */
+ {0x0000u, 0x0000u, 0x0000u}
+ };
+ static const thai_pua_mapping_t SL_mappings[] = {
+ {0x0E48u, 0xF713u, 0xF88Au}, /* MAI EK */
+ {0x0E49u, 0xF714u, 0xF88Du}, /* MAI THO */
+ {0x0E4Au, 0xF715u, 0xF890u}, /* MAI TRI */
+ {0x0E4Bu, 0xF716u, 0xF893u}, /* MAI CHATTAWA */
+ {0x0E4Cu, 0xF717u, 0xF896u}, /* THANTHAKHAT */
+ {0x0E31u, 0xF710u, 0xF884u}, /* MAI HAN-AKAT */
+ {0x0E34u, 0xF701u, 0xF885u}, /* SARA I */
+ {0x0E35u, 0xF702u, 0xF886u}, /* SARA II */
+ {0x0E36u, 0xF703u, 0xF887u}, /* SARA UE */
+ {0x0E37u, 0xF704u, 0xF888u}, /* SARA UEE */
+ {0x0E47u, 0xF712u, 0xF889u}, /* MAITAIKHU */
+ {0x0E4Du, 0xF711u, 0xF899u}, /* NIKHAHIT */
+ {0x0000u, 0x0000u, 0x0000u}
+ };
+ static const thai_pua_mapping_t RD_mappings[] = {
+ {0x0E0Du, 0xF70Fu, 0xF89Au}, /* YO YING */
+ {0x0E10u, 0xF700u, 0xF89Eu}, /* THO THAN */
+ {0x0000u, 0x0000u, 0x0000u}
+ };
+
+ switch (action) {
+ case NOP: return u;
+ case SD: pua_mappings = SD_mappings; break;
+ case SDL: pua_mappings = SDL_mappings; break;
+ case SL: pua_mappings = SL_mappings; break;
+ case RD: pua_mappings = RD_mappings; break;
+ }
+ for (; pua_mappings->u; pua_mappings++)
+ if (pua_mappings->u == u)
+ {
+ hb_codepoint_t glyph;
+ if (hb_font_get_glyph (font, pua_mappings->win_pua, 0, &glyph))
+ return pua_mappings->win_pua;
+ if (hb_font_get_glyph (font, pua_mappings->mac_pua, 0, &glyph))
+ return pua_mappings->mac_pua;
+ break;
+ }
+ return u;
+}
+
+
+static enum thai_above_state_t
+{ /* Cluster above looks like: */
+ T0, /* ⣤ */
+ T1, /* ⣼ */
+ T2, /* ⣾ */
+ T3, /* ⣿ */
+ NUM_ABOVE_STATES
+} thai_above_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
+{
+ T0, /* NC */
+ T1, /* AC */
+ T0, /* RC */
+ T0, /* DC */
+ T3, /* NOT_CONSONANT */
+};
+
+static const struct thai_above_state_machine_edge_t {
+ thai_action_t action;
+ thai_above_state_t next_state;
+} thai_above_state_machine[NUM_ABOVE_STATES][NUM_MARK_TYPES] =
+{ /*AV*/ /*BV*/ /*T*/
+/*T0*/ {{NOP,T3}, {NOP,T0}, {SD, T3}},
+/*T1*/ {{SL, T2}, {NOP,T1}, {SDL,T2}},
+/*T2*/ {{NOP,T3}, {NOP,T2}, {SL, T3}},
+/*T3*/ {{NOP,T3}, {NOP,T3}, {NOP,T3}},
+};
+
+
+static enum thai_below_state_t
+{
+ B0, /* No descender */
+ B1, /* Removable descender */
+ B2, /* Strict descender */
+ NUM_BELOW_STATES
+} thai_below_start_state[NUM_CONSONANT_TYPES + 1/* For NOT_CONSONANT */] =
+{
+ B0, /* NC */
+ B0, /* AC */
+ B1, /* RC */
+ B2, /* DC */
+ B2, /* NOT_CONSONANT */
+};
+
+static const struct thai_below_state_machine_edge_t {
+ thai_action_t action;
+ thai_below_state_t next_state;
+} thai_below_state_machine[NUM_BELOW_STATES][NUM_MARK_TYPES] =
+{ /*AV*/ /*BV*/ /*T*/
+/*B0*/ {{NOP,B0}, {NOP,B2}, {NOP, B0}},
+/*B1*/ {{NOP,B1}, {RD, B2}, {NOP, B1}},
+/*B2*/ {{NOP,B2}, {SD, B2}, {NOP, B2}},
+};
+
+
+static void
+do_thai_pua_shaping (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+#ifdef HB_NO_OT_SHAPER_THAI_FALLBACK
+ return;
+#endif
+
+ thai_above_state_t above_state = thai_above_start_state[NOT_CONSONANT];
+ thai_below_state_t below_state = thai_below_start_state[NOT_CONSONANT];
+ unsigned int base = 0;
+
+ hb_glyph_info_t *info = buffer->info;
+ unsigned int count = buffer->len;
+ for (unsigned int i = 0; i < count; i++)
+ {
+ thai_mark_type_t mt = get_mark_type (info[i].codepoint);
+
+ if (mt == NOT_MARK) {
+ thai_consonant_type_t ct = get_consonant_type (info[i].codepoint);
+ above_state = thai_above_start_state[ct];
+ below_state = thai_below_start_state[ct];
+ base = i;
+ continue;
+ }
+
+ const thai_above_state_machine_edge_t &above_edge = thai_above_state_machine[above_state][mt];
+ const thai_below_state_machine_edge_t &below_edge = thai_below_state_machine[below_state][mt];
+ above_state = above_edge.next_state;
+ below_state = below_edge.next_state;
+
+ /* At least one of the above/below actions is NOP. */
+ thai_action_t action = above_edge.action != NOP ? above_edge.action : below_edge.action;
+
+ buffer->unsafe_to_break (base, i);
+ if (action == RD)
+ info[base].codepoint = thai_pua_shape (info[base].codepoint, action, font);
+ else
+ info[i].codepoint = thai_pua_shape (info[i].codepoint, action, font);
+ }
+}
+
+
+static void
+preprocess_text_thai (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ /* This function implements the shaping logic documented here:
+ *
+ * https://linux.thai.net/~thep/th-otf/shaping.html
+ *
+ * The first shaping rule listed there is needed even if the font has Thai
+ * OpenType tables. The rest do fallback positioning based on PUA codepoints.
+ * We implement that only if there exist no Thai GSUB in the font.
+ */
+
+ /* The following is NOT specified in the MS OT Thai spec, however, it seems
+ * to be what Uniscribe and other engines implement. According to Eric Muller:
+ *
+ * When you have a SARA AM, decompose it in NIKHAHIT + SARA AA, *and* move the
+ * NIKHAHIT backwards over any above-base marks.
+ *
+ * <0E14, 0E4B, 0E33> -> <0E14, 0E4D, 0E4B, 0E32>
+ *
+ * This reordering is legit only when the NIKHAHIT comes from a SARA AM, not
+ * when it's there to start with. The string <0E14, 0E4B, 0E4D> is probably
+ * not what a user wanted, but the rendering is nevertheless nikhahit above
+ * chattawa.
+ *
+ * Same for Lao.
+ *
+ * Note:
+ *
+ * Uniscribe also does some below-marks reordering. Namely, it positions U+0E3A
+ * after U+0E38 and U+0E39. We do that by modifying the ccc for U+0E3A.
+ * See unicode->modified_combining_class (). Lao does NOT have a U+0E3A
+ * equivalent.
+ */
+
+
+ /*
+ * Here are the characters of significance:
+ *
+ * Thai Lao
+ * SARA AM: U+0E33 U+0EB3
+ * SARA AA: U+0E32 U+0EB2
+ * Nikhahit: U+0E4D U+0ECD
+ *
+ * Testing shows that Uniscribe reorder the following marks:
+ * Thai: <0E31,0E34..0E37, 0E47..0E4E>
+ * Lao: <0EB1,0EB4..0EB7,0EBB,0EC8..0ECD>
+ *
+ * Note how the Lao versions are the same as Thai + 0x80.
+ */
+
+ /* We only get one script at a time, so a script-agnostic implementation
+ * is adequate here. */
+#define IS_SARA_AM(x) (((x) & ~0x0080u) == 0x0E33u)
+#define NIKHAHIT_FROM_SARA_AM(x) ((x) - 0x0E33u + 0x0E4Du)
+#define SARA_AA_FROM_SARA_AM(x) ((x) - 1)
+#define IS_ABOVE_BASE_MARK(x) (hb_in_ranges<hb_codepoint_t> ((x) & ~0x0080u, 0x0E34u, 0x0E37u, 0x0E47u, 0x0E4Eu, 0x0E31u, 0x0E31u, 0x0E3Bu, 0x0E3Bu))
+
+ buffer->clear_output ();
+ unsigned int count = buffer->len;
+ for (buffer->idx = 0; buffer->idx < count /* No need for: && buffer->successful */;)
+ {
+ hb_codepoint_t u = buffer->cur().codepoint;
+ if (likely (!IS_SARA_AM (u)))
+ {
+ if (unlikely (!buffer->next_glyph ())) break;
+ continue;
+ }
+
+ /* Is SARA AM. Decompose and reorder. */
+ (void) buffer->output_glyph (NIKHAHIT_FROM_SARA_AM (u));
+ _hb_glyph_info_set_continuation (&buffer->prev());
+ if (unlikely (!buffer->replace_glyph (SARA_AA_FROM_SARA_AM (u)))) break;
+
+ /* Make Nikhahit be recognized as a ccc=0 mark when zeroing widths. */
+ unsigned int end = buffer->out_len;
+ _hb_glyph_info_set_general_category (&buffer->out_info[end - 2], HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK);
+
+ /* Ok, let's see... */
+ unsigned int start = end - 2;
+ while (start > 0 && IS_ABOVE_BASE_MARK (buffer->out_info[start - 1].codepoint))
+ start--;
+
+ if (start + 2 < end)
+ {
+ /* Move Nikhahit (end-2) to the beginning */
+ buffer->merge_out_clusters (start, end);
+ hb_glyph_info_t t = buffer->out_info[end - 2];
+ memmove (buffer->out_info + start + 1,
+ buffer->out_info + start,
+ sizeof (buffer->out_info[0]) * (end - start - 2));
+ buffer->out_info[start] = t;
+ }
+ else
+ {
+ /* Since we decomposed, and NIKHAHIT is combining, merge clusters with the
+ * previous cluster. */
+ if (start && buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
+ buffer->merge_out_clusters (start - 1, end);
+ }
+ }
+ buffer->sync ();
+
+ /* If font has Thai GSUB, we are done. */
+ if (plan->props.script == HB_SCRIPT_THAI && !plan->map.found_script[0])
+ do_thai_pua_shaping (plan, buffer, font);
+}
+
+const hb_ot_shaper_t _hb_ot_shaper_thai =
+{
+ nullptr, /* collect_features */
+ nullptr, /* override_features */
+ nullptr, /* data_create */
+ nullptr, /* data_destroy */
+ preprocess_text_thai,
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ nullptr, /* compose */
+ nullptr, /* setup_masks */
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_DEFAULT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE,
+ false,/* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
new file mode 100644
index 0000000000..5b3ec05616
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-machine.hh
@@ -0,0 +1,931 @@
+
+#line 1 "hb-ot-shaper-use-machine.rl"
+/*
+ * Copyright © 2015 Mozilla Foundation.
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_USE_MACHINE_HH
+#define HB_OT_SHAPER_USE_MACHINE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-syllabic.hh"
+
+/* buffer var allocations */
+#define use_category() ot_shaper_var_u8_category()
+
+#define USE(Cat) use_syllable_machine_ex_##Cat
+
+enum use_syllable_type_t {
+ use_virama_terminated_cluster,
+ use_sakot_terminated_cluster,
+ use_standard_cluster,
+ use_number_joiner_terminated_cluster,
+ use_numeral_cluster,
+ use_symbol_cluster,
+ use_hieroglyph_cluster,
+ use_broken_cluster,
+ use_non_cluster,
+};
+
+
+#line 54 "hb-ot-shaper-use-machine.hh"
+#define use_syllable_machine_ex_B 1u
+#define use_syllable_machine_ex_CGJ 6u
+#define use_syllable_machine_ex_CMAbv 31u
+#define use_syllable_machine_ex_CMBlw 32u
+#define use_syllable_machine_ex_CS 43u
+#define use_syllable_machine_ex_FAbv 24u
+#define use_syllable_machine_ex_FBlw 25u
+#define use_syllable_machine_ex_FMAbv 45u
+#define use_syllable_machine_ex_FMBlw 46u
+#define use_syllable_machine_ex_FMPst 47u
+#define use_syllable_machine_ex_FPst 26u
+#define use_syllable_machine_ex_G 49u
+#define use_syllable_machine_ex_GB 5u
+#define use_syllable_machine_ex_H 12u
+#define use_syllable_machine_ex_HN 13u
+#define use_syllable_machine_ex_HVM 53u
+#define use_syllable_machine_ex_IS 44u
+#define use_syllable_machine_ex_J 50u
+#define use_syllable_machine_ex_MAbv 27u
+#define use_syllable_machine_ex_MBlw 28u
+#define use_syllable_machine_ex_MPre 30u
+#define use_syllable_machine_ex_MPst 29u
+#define use_syllable_machine_ex_N 4u
+#define use_syllable_machine_ex_O 0u
+#define use_syllable_machine_ex_R 18u
+#define use_syllable_machine_ex_SB 51u
+#define use_syllable_machine_ex_SE 52u
+#define use_syllable_machine_ex_SMAbv 41u
+#define use_syllable_machine_ex_SMBlw 42u
+#define use_syllable_machine_ex_SUB 11u
+#define use_syllable_machine_ex_Sk 48u
+#define use_syllable_machine_ex_VAbv 33u
+#define use_syllable_machine_ex_VBlw 34u
+#define use_syllable_machine_ex_VMAbv 37u
+#define use_syllable_machine_ex_VMBlw 38u
+#define use_syllable_machine_ex_VMPre 23u
+#define use_syllable_machine_ex_VMPst 39u
+#define use_syllable_machine_ex_VPre 22u
+#define use_syllable_machine_ex_VPst 35u
+#define use_syllable_machine_ex_WJ 16u
+#define use_syllable_machine_ex_ZWNJ 14u
+
+
+#line 96 "hb-ot-shaper-use-machine.hh"
+static const unsigned char _use_syllable_machine_trans_keys[] = {
+ 0u, 53u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u,
+ 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 53u,
+ 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u, 12u, 53u,
+ 11u, 53u, 1u, 1u, 1u, 48u, 11u, 53u, 41u, 42u, 42u, 42u, 11u, 53u, 11u, 53u,
+ 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u,
+ 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u, 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u,
+ 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u,
+ 13u, 13u, 4u, 4u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u, 24u, 47u, 25u, 47u,
+ 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u, 1u, 1u, 24u, 48u,
+ 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u, 12u, 53u, 12u, 53u,
+ 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u, 11u, 53u, 11u, 53u, 1u, 53u, 23u, 48u,
+ 24u, 47u, 25u, 47u, 26u, 47u, 45u, 46u, 46u, 46u, 24u, 48u, 24u, 48u, 24u, 48u,
+ 1u, 1u, 24u, 48u, 22u, 53u, 23u, 53u, 23u, 53u, 23u, 53u, 12u, 53u, 23u, 53u,
+ 12u, 53u, 12u, 53u, 12u, 53u, 11u, 53u, 1u, 1u, 1u, 48u, 4u, 4u, 13u, 13u,
+ 1u, 53u, 11u, 53u, 41u, 42u, 42u, 42u, 1u, 5u, 50u, 52u, 49u, 52u, 49u, 51u,
+ 0
+};
+
+static const char _use_syllable_machine_key_spans[] = {
+ 54, 43, 43, 53, 26, 24, 23, 22,
+ 2, 1, 25, 25, 25, 1, 25, 32,
+ 31, 31, 31, 42, 31, 42, 42, 42,
+ 43, 1, 48, 43, 2, 1, 43, 43,
+ 53, 26, 24, 23, 22, 2, 1, 25,
+ 25, 25, 1, 25, 32, 31, 31, 31,
+ 42, 31, 42, 42, 42, 43, 1, 48,
+ 1, 1, 43, 43, 53, 26, 24, 23,
+ 22, 2, 1, 25, 25, 25, 1, 25,
+ 32, 31, 31, 31, 42, 31, 42, 42,
+ 42, 43, 1, 48, 43, 43, 53, 26,
+ 24, 23, 22, 2, 1, 25, 25, 25,
+ 1, 25, 32, 31, 31, 31, 42, 31,
+ 42, 42, 42, 43, 1, 48, 1, 1,
+ 53, 43, 2, 1, 5, 3, 4, 3
+};
+
+static const short _use_syllable_machine_index_offsets[] = {
+ 0, 55, 99, 143, 197, 224, 249, 273,
+ 296, 299, 301, 327, 353, 379, 381, 407,
+ 440, 472, 504, 536, 579, 611, 654, 697,
+ 740, 784, 786, 835, 879, 882, 884, 928,
+ 972, 1026, 1053, 1078, 1102, 1125, 1128, 1130,
+ 1156, 1182, 1208, 1210, 1236, 1269, 1301, 1333,
+ 1365, 1408, 1440, 1483, 1526, 1569, 1613, 1615,
+ 1664, 1666, 1668, 1712, 1756, 1810, 1837, 1862,
+ 1886, 1909, 1912, 1914, 1940, 1966, 1992, 1994,
+ 2020, 2053, 2085, 2117, 2149, 2192, 2224, 2267,
+ 2310, 2353, 2397, 2399, 2448, 2492, 2536, 2590,
+ 2617, 2642, 2666, 2689, 2692, 2694, 2720, 2746,
+ 2772, 2774, 2800, 2833, 2865, 2897, 2929, 2972,
+ 3004, 3047, 3090, 3133, 3177, 3179, 3228, 3230,
+ 3232, 3286, 3330, 3333, 3335, 3341, 3345, 3350
+};
+
+static const unsigned char _use_syllable_machine_indicies[] = {
+ 0, 1, 2, 2, 3, 4, 2, 2,
+ 2, 2, 2, 5, 6, 7, 2, 2,
+ 2, 2, 8, 2, 2, 2, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 2, 23, 24, 25,
+ 2, 26, 27, 28, 29, 30, 31, 32,
+ 29, 33, 2, 34, 2, 35, 2, 37,
+ 38, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 51, 52,
+ 36, 53, 54, 55, 36, 56, 57, 36,
+ 58, 59, 60, 61, 58, 36, 36, 36,
+ 36, 62, 36, 37, 38, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 49,
+ 49, 50, 51, 52, 36, 53, 54, 55,
+ 36, 36, 36, 36, 58, 59, 60, 61,
+ 58, 36, 36, 36, 36, 62, 36, 37,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 40, 41, 42,
+ 43, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 53, 54, 55, 36, 36,
+ 36, 36, 36, 59, 60, 61, 63, 36,
+ 36, 36, 36, 40, 36, 40, 41, 42,
+ 43, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 53, 54, 55, 36, 36,
+ 36, 36, 36, 59, 60, 61, 63, 36,
+ 41, 42, 43, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 59, 60, 61,
+ 36, 42, 43, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 59, 60, 61,
+ 36, 43, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 59, 60, 61, 36,
+ 59, 60, 36, 60, 36, 41, 42, 43,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 53, 54, 55, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 41,
+ 42, 43, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 54, 55, 36,
+ 36, 36, 36, 36, 59, 60, 61, 63,
+ 36, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 64, 36, 41, 42, 43,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 39,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 36, 36, 36, 40, 36,
+ 65, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 39, 40, 41, 42, 43, 36,
+ 45, 46, 36, 36, 36, 50, 51, 52,
+ 36, 53, 54, 55, 36, 36, 36, 36,
+ 36, 59, 60, 61, 63, 36, 36, 36,
+ 36, 40, 36, 40, 41, 42, 43, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 53, 54, 55, 36, 36, 36, 36,
+ 36, 59, 60, 61, 63, 36, 36, 36,
+ 36, 40, 36, 65, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 39, 40, 41,
+ 42, 43, 36, 36, 46, 36, 36, 36,
+ 50, 51, 52, 36, 53, 54, 55, 36,
+ 36, 36, 36, 36, 59, 60, 61, 63,
+ 36, 36, 36, 36, 40, 36, 65, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 39, 40, 41, 42, 43, 36, 36, 36,
+ 36, 36, 36, 50, 51, 52, 36, 53,
+ 54, 55, 36, 36, 36, 36, 36, 59,
+ 60, 61, 63, 36, 36, 36, 36, 40,
+ 36, 65, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 39, 40, 41, 42, 43,
+ 44, 45, 46, 36, 36, 36, 50, 51,
+ 52, 36, 53, 54, 55, 36, 36, 36,
+ 36, 36, 59, 60, 61, 63, 36, 36,
+ 36, 36, 40, 36, 37, 38, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 36, 49, 50, 51, 52, 36, 53, 54,
+ 55, 36, 36, 36, 36, 58, 59, 60,
+ 61, 58, 36, 36, 36, 36, 62, 36,
+ 37, 36, 37, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36, 36,
+ 40, 41, 42, 43, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 53, 54,
+ 55, 36, 36, 36, 36, 36, 59, 60,
+ 61, 63, 36, 37, 38, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 52, 36, 53, 54, 55,
+ 36, 36, 36, 36, 58, 59, 60, 61,
+ 58, 36, 36, 36, 36, 62, 36, 56,
+ 57, 36, 57, 36, 67, 68, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 69,
+ 70, 71, 72, 73, 74, 75, 76, 77,
+ 1, 78, 79, 80, 81, 66, 82, 83,
+ 84, 66, 66, 66, 66, 85, 86, 87,
+ 88, 89, 66, 66, 66, 66, 90, 66,
+ 67, 68, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 78, 79, 80,
+ 81, 66, 82, 83, 84, 66, 66, 66,
+ 66, 85, 86, 87, 88, 89, 66, 66,
+ 66, 66, 90, 66, 67, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 70, 71, 72, 73, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 82, 83, 84, 66, 66, 66, 66, 66,
+ 86, 87, 88, 91, 66, 66, 66, 66,
+ 70, 66, 70, 71, 72, 73, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 82, 83, 84, 66, 66, 66, 66, 66,
+ 86, 87, 88, 91, 66, 71, 72, 73,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 86, 87, 88, 66, 72, 73,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 86, 87, 88, 66, 73, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 86, 87, 88, 66, 86, 87, 66,
+ 87, 66, 71, 72, 73, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 82,
+ 83, 84, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 71, 72, 73, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 83, 84, 66, 66, 66, 66,
+ 66, 86, 87, 88, 91, 66, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 93, 92, 71, 72, 73, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 69, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 66, 66, 66, 70, 66, 94, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 69,
+ 70, 71, 72, 73, 66, 75, 76, 66,
+ 66, 66, 79, 80, 81, 66, 82, 83,
+ 84, 66, 66, 66, 66, 66, 86, 87,
+ 88, 91, 66, 66, 66, 66, 70, 66,
+ 70, 71, 72, 73, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 82, 83,
+ 84, 66, 66, 66, 66, 66, 86, 87,
+ 88, 91, 66, 66, 66, 66, 70, 66,
+ 94, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 69, 70, 71, 72, 73, 66,
+ 66, 76, 66, 66, 66, 79, 80, 81,
+ 66, 82, 83, 84, 66, 66, 66, 66,
+ 66, 86, 87, 88, 91, 66, 66, 66,
+ 66, 70, 66, 94, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 69, 70, 71,
+ 72, 73, 66, 66, 66, 66, 66, 66,
+ 79, 80, 81, 66, 82, 83, 84, 66,
+ 66, 66, 66, 66, 86, 87, 88, 91,
+ 66, 66, 66, 66, 70, 66, 94, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 69, 70, 71, 72, 73, 74, 75, 76,
+ 66, 66, 66, 79, 80, 81, 66, 82,
+ 83, 84, 66, 66, 66, 66, 66, 86,
+ 87, 88, 91, 66, 66, 66, 66, 70,
+ 66, 67, 68, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 69, 70, 71, 72,
+ 73, 74, 75, 76, 77, 66, 78, 79,
+ 80, 81, 66, 82, 83, 84, 66, 66,
+ 66, 66, 85, 86, 87, 88, 89, 66,
+ 66, 66, 66, 90, 66, 67, 95, 67,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 70, 71, 72,
+ 73, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 82, 83, 84, 66, 66,
+ 66, 66, 66, 86, 87, 88, 91, 66,
+ 97, 96, 3, 98, 99, 100, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 101,
+ 102, 103, 104, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 66, 115, 116,
+ 117, 66, 56, 57, 66, 118, 119, 120,
+ 88, 121, 66, 66, 66, 66, 122, 66,
+ 99, 100, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 111, 111, 112, 113,
+ 114, 66, 115, 116, 117, 66, 66, 66,
+ 66, 118, 119, 120, 88, 121, 66, 66,
+ 66, 66, 122, 66, 99, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 102, 103, 104, 105, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 115, 116, 117, 66, 66, 66, 66, 66,
+ 119, 120, 88, 123, 66, 66, 66, 66,
+ 102, 66, 102, 103, 104, 105, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 115, 116, 117, 66, 66, 66, 66, 66,
+ 119, 120, 88, 123, 66, 103, 104, 105,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 119, 120, 88, 66, 104, 105,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 119, 120, 88, 66, 105, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 119, 120, 88, 66, 119, 120, 66,
+ 120, 66, 103, 104, 105, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 115,
+ 116, 117, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 103, 104, 105, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 116, 117, 66, 66, 66, 66,
+ 66, 119, 120, 88, 123, 66, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 124, 92, 103, 104, 105, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 101, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 66, 66, 66, 102, 66, 125, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 101,
+ 102, 103, 104, 105, 66, 107, 108, 66,
+ 66, 66, 112, 113, 114, 66, 115, 116,
+ 117, 66, 66, 66, 66, 66, 119, 120,
+ 88, 123, 66, 66, 66, 66, 102, 66,
+ 102, 103, 104, 105, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 115, 116,
+ 117, 66, 66, 66, 66, 66, 119, 120,
+ 88, 123, 66, 66, 66, 66, 102, 66,
+ 125, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 101, 102, 103, 104, 105, 66,
+ 66, 108, 66, 66, 66, 112, 113, 114,
+ 66, 115, 116, 117, 66, 66, 66, 66,
+ 66, 119, 120, 88, 123, 66, 66, 66,
+ 66, 102, 66, 125, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 101, 102, 103,
+ 104, 105, 66, 66, 66, 66, 66, 66,
+ 112, 113, 114, 66, 115, 116, 117, 66,
+ 66, 66, 66, 66, 119, 120, 88, 123,
+ 66, 66, 66, 66, 102, 66, 125, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 101, 102, 103, 104, 105, 106, 107, 108,
+ 66, 66, 66, 112, 113, 114, 66, 115,
+ 116, 117, 66, 66, 66, 66, 66, 119,
+ 120, 88, 123, 66, 66, 66, 66, 102,
+ 66, 99, 100, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 101, 102, 103, 104,
+ 105, 106, 107, 108, 109, 66, 111, 112,
+ 113, 114, 66, 115, 116, 117, 66, 66,
+ 66, 66, 118, 119, 120, 88, 121, 66,
+ 66, 66, 66, 122, 66, 99, 95, 99,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 66, 66, 102, 103, 104,
+ 105, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 115, 116, 117, 66, 66,
+ 66, 66, 66, 119, 120, 88, 123, 66,
+ 99, 100, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113,
+ 114, 66, 115, 116, 117, 66, 66, 66,
+ 66, 118, 119, 120, 88, 121, 66, 66,
+ 66, 66, 122, 66, 5, 6, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 19, 19, 20, 21, 22, 126, 23, 24,
+ 25, 126, 126, 126, 126, 29, 30, 31,
+ 32, 29, 126, 126, 126, 126, 35, 126,
+ 5, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 10, 11,
+ 12, 13, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 23, 24, 25, 126,
+ 126, 126, 126, 126, 30, 31, 32, 127,
+ 126, 126, 126, 126, 10, 126, 10, 11,
+ 12, 13, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 23, 24, 25, 126,
+ 126, 126, 126, 126, 30, 31, 32, 127,
+ 126, 11, 12, 13, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 30, 31,
+ 32, 126, 12, 13, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 30, 31,
+ 32, 126, 13, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 126, 30, 31, 126, 31, 126, 11, 12,
+ 13, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 23, 24, 25, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 11, 12, 13, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 24, 25,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 127, 126, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 128, 126, 11, 12,
+ 13, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 9, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 126, 126, 126, 10,
+ 126, 129, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 9, 10, 11, 12, 13,
+ 126, 15, 16, 126, 126, 126, 20, 21,
+ 22, 126, 23, 24, 25, 126, 126, 126,
+ 126, 126, 30, 31, 32, 127, 126, 126,
+ 126, 126, 10, 126, 10, 11, 12, 13,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 23, 24, 25, 126, 126, 126,
+ 126, 126, 30, 31, 32, 127, 126, 126,
+ 126, 126, 10, 126, 129, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 9, 10,
+ 11, 12, 13, 126, 126, 16, 126, 126,
+ 126, 20, 21, 22, 126, 23, 24, 25,
+ 126, 126, 126, 126, 126, 30, 31, 32,
+ 127, 126, 126, 126, 126, 10, 126, 129,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 9, 10, 11, 12, 13, 126, 126,
+ 126, 126, 126, 126, 20, 21, 22, 126,
+ 23, 24, 25, 126, 126, 126, 126, 126,
+ 30, 31, 32, 127, 126, 126, 126, 126,
+ 10, 126, 129, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 9, 10, 11, 12,
+ 13, 14, 15, 16, 126, 126, 126, 20,
+ 21, 22, 126, 23, 24, 25, 126, 126,
+ 126, 126, 126, 30, 31, 32, 127, 126,
+ 126, 126, 126, 10, 126, 5, 6, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 126, 19, 20, 21, 22, 126, 23,
+ 24, 25, 126, 126, 126, 126, 29, 30,
+ 31, 32, 29, 126, 126, 126, 126, 35,
+ 126, 5, 126, 5, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 10, 11, 12, 13, 126, 126, 126,
+ 126, 126, 126, 126, 126, 126, 126, 23,
+ 24, 25, 126, 126, 126, 126, 126, 30,
+ 31, 32, 127, 126, 130, 126, 7, 126,
+ 1, 126, 126, 126, 1, 126, 126, 126,
+ 126, 126, 5, 6, 7, 126, 126, 126,
+ 126, 126, 126, 126, 126, 9, 10, 11,
+ 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 126, 23, 24, 25, 126,
+ 26, 27, 126, 29, 30, 31, 32, 29,
+ 126, 126, 126, 126, 35, 126, 5, 6,
+ 126, 126, 126, 126, 126, 126, 126, 126,
+ 126, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 126,
+ 23, 24, 25, 126, 126, 126, 126, 29,
+ 30, 31, 32, 29, 126, 126, 126, 126,
+ 35, 126, 26, 27, 126, 27, 126, 1,
+ 131, 131, 131, 1, 131, 133, 132, 33,
+ 132, 33, 133, 132, 133, 132, 33, 132,
+ 34, 132, 0
+};
+
+static const char _use_syllable_machine_trans_targs[] = {
+ 1, 30, 0, 56, 58, 85, 86, 110,
+ 112, 98, 87, 88, 89, 90, 102, 104,
+ 105, 106, 113, 107, 99, 100, 101, 93,
+ 94, 95, 114, 115, 116, 108, 91, 92,
+ 0, 117, 119, 109, 0, 2, 3, 15,
+ 4, 5, 6, 7, 19, 21, 22, 23,
+ 27, 24, 16, 17, 18, 10, 11, 12,
+ 28, 29, 25, 8, 9, 0, 26, 13,
+ 14, 20, 0, 31, 32, 44, 33, 34,
+ 35, 36, 48, 50, 51, 52, 53, 45,
+ 46, 47, 39, 40, 41, 54, 37, 38,
+ 0, 54, 55, 42, 0, 43, 49, 0,
+ 0, 57, 0, 59, 60, 72, 61, 62,
+ 63, 64, 76, 78, 79, 80, 84, 81,
+ 73, 74, 75, 67, 68, 69, 82, 65,
+ 66, 82, 83, 70, 71, 77, 0, 96,
+ 97, 103, 111, 0, 0, 118
+};
+
+static const char _use_syllable_machine_trans_actions[] = {
+ 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 0, 7, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 0,
+ 9, 10, 0, 0, 11, 0, 0, 12,
+ 13, 0, 14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 8, 0,
+ 0, 10, 0, 0, 0, 0, 15, 0,
+ 0, 0, 0, 16, 17, 0
+};
+
+static const char _use_syllable_machine_to_state_actions[] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const char _use_syllable_machine_from_state_actions[] = {
+ 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const short _use_syllable_machine_eof_trans[] = {
+ 0, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 37, 37, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 93, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 96, 67,
+ 97, 99, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 93, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 96, 67, 67, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 127, 127, 127, 127,
+ 127, 127, 127, 127, 132, 133, 133, 133
+};
+
+static const int use_syllable_machine_start = 0;
+static const int use_syllable_machine_first_final = 0;
+static const int use_syllable_machine_error = -1;
+
+static const int use_syllable_machine_en_main = 0;
+
+
+#line 58 "hb-ot-shaper-use-machine.rl"
+
+
+
+#line 182 "hb-ot-shaper-use-machine.rl"
+
+
+#define found_syllable(syllable_type) \
+ HB_STMT_START { \
+ if (0) fprintf (stderr, "syllable %d..%d %s\n", (*ts).second.first, (*te).second.first, #syllable_type); \
+ for (unsigned i = (*ts).second.first; i < (*te).second.first; ++i) \
+ info[i].syllable() = (syllable_serial << 4) | syllable_type; \
+ syllable_serial++; \
+ if (unlikely (syllable_serial == 16)) syllable_serial = 1; \
+ } HB_STMT_END
+
+
+template <typename Iter>
+struct machine_index_t :
+ hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t>
+{
+ machine_index_t (const Iter& it) : it (it) {}
+ machine_index_t (const machine_index_t& o) : hb_iter_with_fallback_t<machine_index_t<Iter>,
+ typename Iter::item_t> (),
+ it (o.it), is_null (o.is_null) {}
+
+ static constexpr bool is_random_access_iterator = Iter::is_random_access_iterator;
+ static constexpr bool is_sorted_iterator = Iter::is_sorted_iterator;
+
+ typename Iter::item_t __item__ () const { return *it; }
+ typename Iter::item_t __item_at__ (unsigned i) const { return it[i]; }
+ unsigned __len__ () const { return it.len (); }
+ void __next__ () { ++it; }
+ void __forward__ (unsigned n) { it += n; }
+ void __prev__ () { --it; }
+ void __rewind__ (unsigned n) { it -= n; }
+
+ void operator = (unsigned n)
+ {
+ assert (n == 0);
+ is_null = true;
+ }
+ explicit operator bool () { return !is_null; }
+
+ void operator = (const machine_index_t& o)
+ {
+ is_null = o.is_null;
+ unsigned index = (*it).first;
+ unsigned n = (*o.it).first;
+ if (index < n) it += n - index; else if (index > n) it -= index - n;
+ }
+ bool operator == (const machine_index_t& o) const
+ { return is_null ? o.is_null : !o.is_null && (*it).first == (*o.it).first; }
+ bool operator != (const machine_index_t& o) const { return !(*this == o); }
+
+ private:
+ Iter it;
+ bool is_null = false;
+};
+struct
+{
+ template <typename Iter,
+ hb_requires (hb_is_iterable (Iter))>
+ machine_index_t<hb_iter_type<Iter>>
+ operator () (Iter&& it) const
+ { return machine_index_t<hb_iter_type<Iter>> (hb_iter (it)); }
+}
+HB_FUNCOBJ (machine_index);
+
+
+
+static bool
+not_ccs_default_ignorable (const hb_glyph_info_t &i)
+{ return i.use_category() != USE(CGJ); }
+
+static inline void
+find_syllables_use (hb_buffer_t *buffer)
+{
+ hb_glyph_info_t *info = buffer->info;
+ auto p =
+ + hb_iter (info, buffer->len)
+ | hb_enumerate
+ | hb_filter ([] (const hb_glyph_info_t &i) { return not_ccs_default_ignorable (i); },
+ hb_second)
+ | hb_filter ([&] (const hb_pair_t<unsigned, const hb_glyph_info_t &> p)
+ {
+ if (p.second.use_category() == USE(ZWNJ))
+ for (unsigned i = p.first + 1; i < buffer->len; ++i)
+ if (not_ccs_default_ignorable (info[i]))
+ return !_hb_glyph_info_is_unicode_mark (&info[i]);
+ return true;
+ })
+ | hb_enumerate
+ | machine_index
+ ;
+ auto pe = p + p.len ();
+ auto eof = +pe;
+ auto ts = +p;
+ auto te = +p;
+ unsigned int act HB_UNUSED;
+ int cs;
+
+#line 773 "hb-ot-shaper-use-machine.hh"
+ {
+ cs = use_syllable_machine_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 282 "hb-ot-shaper-use-machine.rl"
+
+
+ unsigned int syllable_serial = 1;
+
+#line 782 "hb-ot-shaper-use-machine.hh"
+ {
+ int _slen;
+ int _trans;
+ const unsigned char *_keys;
+ const unsigned char *_inds;
+ if ( p == pe )
+ goto _test_eof;
+_resume:
+ switch ( _use_syllable_machine_from_state_actions[cs] ) {
+ case 2:
+#line 1 "NONE"
+ {ts = p;}
+ break;
+#line 794 "hb-ot-shaper-use-machine.hh"
+ }
+
+ _keys = _use_syllable_machine_trans_keys + (cs<<1);
+ _inds = _use_syllable_machine_indicies + _use_syllable_machine_index_offsets[cs];
+
+ _slen = _use_syllable_machine_key_spans[cs];
+ _trans = _inds[ _slen > 0 && _keys[0] <=( (*p).second.second.use_category()) &&
+ ( (*p).second.second.use_category()) <= _keys[1] ?
+ ( (*p).second.second.use_category()) - _keys[0] : _slen ];
+
+_eof_trans:
+ cs = _use_syllable_machine_trans_targs[_trans];
+
+ if ( _use_syllable_machine_trans_actions[_trans] == 0 )
+ goto _again;
+
+ switch ( _use_syllable_machine_trans_actions[_trans] ) {
+ case 9:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 6:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 4:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 3:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p+1;{ found_syllable (use_non_cluster); }}
+ break;
+ case 11:
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_sakot_terminated_cluster); }}
+ break;
+ case 7:
+#line 172 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_standard_cluster); }}
+ break;
+ case 14:
+#line 173 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_number_joiner_terminated_cluster); }}
+ break;
+ case 13:
+#line 174 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_numeral_cluster); }}
+ break;
+ case 5:
+#line 175 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_symbol_cluster); }}
+ break;
+ case 17:
+#line 176 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_hieroglyph_cluster); }}
+ break;
+ case 15:
+#line 177 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_broken_cluster); buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE; }}
+ break;
+ case 16:
+#line 178 "hb-ot-shaper-use-machine.rl"
+ {te = p;p--;{ found_syllable (use_non_cluster); }}
+ break;
+ case 12:
+#line 1 "NONE"
+ { switch( act ) {
+ case 1:
+ {{p = ((te))-1;} found_syllable (use_virama_terminated_cluster); }
+ break;
+ case 2:
+ {{p = ((te))-1;} found_syllable (use_sakot_terminated_cluster); }
+ break;
+ }
+ }
+ break;
+ case 8:
+#line 1 "NONE"
+ {te = p+1;}
+#line 170 "hb-ot-shaper-use-machine.rl"
+ {act = 1;}
+ break;
+ case 10:
+#line 1 "NONE"
+ {te = p+1;}
+#line 171 "hb-ot-shaper-use-machine.rl"
+ {act = 2;}
+ break;
+#line 866 "hb-ot-shaper-use-machine.hh"
+ }
+
+_again:
+ switch ( _use_syllable_machine_to_state_actions[cs] ) {
+ case 1:
+#line 1 "NONE"
+ {ts = 0;}
+ break;
+#line 873 "hb-ot-shaper-use-machine.hh"
+ }
+
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ if ( _use_syllable_machine_eof_trans[cs] > 0 ) {
+ _trans = _use_syllable_machine_eof_trans[cs] - 1;
+ goto _eof_trans;
+ }
+ }
+
+ }
+
+#line 287 "hb-ot-shaper-use-machine.rl"
+
+}
+
+#undef found_syllable
+
+#endif /* HB_OT_SHAPER_USE_MACHINE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
new file mode 100644
index 0000000000..e45ea30e60
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
@@ -0,0 +1,418 @@
+/* == Start of generated table == */
+/*
+ * The following table is generated by running:
+ *
+ * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt ArabicShaping.txt DerivedCoreProperties.txt UnicodeData.txt Blocks.txt Scripts.txt IndicSyllabicCategory-Additional.txt IndicPositionalCategory-Additional.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicSyllabicCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # IndicPositionalCategory-14.0.0.txt
+ * # Date: 2021-05-22, 01:01:00 GMT [KW, RP]
+ * # ArabicShaping-14.0.0.txt
+ * # Date: 2021-05-21, 01:54:00 GMT [KW, RP]
+ * # DerivedCoreProperties-14.0.0.txt
+ * # Date: 2021-08-12, 23:12:53 GMT
+ * # Blocks-14.0.0.txt
+ * # Date: 2021-01-22, 23:29:00 GMT [KW]
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
+ * # Override values For Indic_Syllabic_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
+ * # Override values For Indic_Positional_Category
+ * # Not derivable
+ * # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
+ * # Updated for Unicode 10.0 by Andrew Glass 2017-07-25
+ * # Ammended for Unicode 10.0 by Andrew Glass 2018-09-21
+ * # Updated for L2/19-083 by Andrew Glass 2019-05-06
+ * # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
+ * # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
+ * # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
+ * UnicodeData.txt does not have a header.
+ */
+
+#ifndef HB_OT_SHAPER_USE_TABLE_HH
+#define HB_OT_SHAPER_USE_TABLE_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper-use-machine.hh"
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-macros"
+#define B USE(B) /* BASE */
+#define CGJ USE(CGJ) /* CGJ */
+#define CS USE(CS) /* CONS_WITH_STACKER */
+#define G USE(G) /* HIEROGLYPH */
+#define GB USE(GB) /* BASE_OTHER */
+#define H USE(H) /* HALANT */
+#define HN USE(HN) /* HALANT_NUM */
+#define HVM USE(HVM) /* HALANT_OR_VOWEL_MODIFIER */
+#define IS USE(IS) /* INVISIBLE_STACKER */
+#define J USE(J) /* HIEROGLYPH_JOINER */
+#define N USE(N) /* BASE_NUM */
+#define O USE(O) /* OTHER */
+#define R USE(R) /* REPHA */
+#define SB USE(SB) /* HIEROGLYPH_SEGMENT_BEGIN */
+#define SE USE(SE) /* HIEROGLYPH_SEGMENT_END */
+#define SUB USE(SUB) /* CONS_SUB */
+#define Sk USE(Sk) /* SAKOT */
+#define WJ USE(WJ) /* Word_Joiner */
+#define ZWNJ USE(ZWNJ) /* ZWNJ */
+#define CMAbv USE(CMAbv)
+#define CMBlw USE(CMBlw)
+#define FAbv USE(FAbv)
+#define FBlw USE(FBlw)
+#define FPst USE(FPst)
+#define FMAbv USE(FMAbv)
+#define FMBlw USE(FMBlw)
+#define FMPst USE(FMPst)
+#define MAbv USE(MAbv)
+#define MBlw USE(MBlw)
+#define MPst USE(MPst)
+#define MPre USE(MPre)
+#define SMAbv USE(SMAbv)
+#define SMBlw USE(SMBlw)
+#define VAbv USE(VAbv)
+#define VBlw USE(VBlw)
+#define VPst USE(VPst)
+#define VPre USE(VPre)
+#define VMAbv USE(VMAbv)
+#define VMBlw USE(VMBlw)
+#define VMPst USE(VMPst)
+#define VMPre USE(VMPre)
+#pragma GCC diagnostic pop
+
+static const uint8_t
+hb_use_u8[3083] =
+{
+ 16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
+ 14, 0, 1, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 4, 2, 2,
+ 5, 6, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 17,
+ 18, 19, 20, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 2, 33, 2, 2, 2,
+ 2, 34, 35, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 37, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 38, 39, 40, 41, 42, 43, 2, 44, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 46, 2,
+ 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 48, 49, 2, 2, 2,
+ 2, 2, 2, 2, 2, 50, 51, 2, 52, 2, 2, 53, 2, 2, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63, 2, 64, 65, 2, 66, 67, 68, 69,
+ 2, 70, 2, 71, 72, 73, 74, 2, 2, 75, 76, 77, 78, 2, 79, 2,
+ 2, 80, 80, 80, 80, 80, 80, 80, 80, 81, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 82, 83, 2, 2, 2, 2, 2, 2, 2, 84,
+ 85, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 80, 80, 80, 86, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 87, 88, 2, 2, 2, 2, 2,
+ 2, 2, 2, 89, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 90, 2, 2, 91, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 93, 93, 94, 95, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 8, 9, 9, 9, 9, 0, 0, 0, 7, 10,
+ 0, 2, 2, 2, 2, 11, 12, 0, 0, 9, 13, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 15, 16, 17, 18, 19, 20, 14, 21, 22,
+ 23, 10, 24, 25, 18, 2, 2, 2, 2, 2, 18, 0, 2, 2, 2, 2,
+ 2, 0, 2, 2, 2, 2, 2, 2, 2, 26, 27, 28, 2, 2, 2, 7,
+ 28, 7, 28, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 2, 2,
+ 2, 7, 7, 0, 2, 2, 0, 15, 16, 17, 18, 29, 30, 31, 30, 32,
+ 0, 0, 0, 0, 33, 0, 0, 2, 28, 2, 0, 0, 0, 0, 0, 7,
+ 34, 10, 13, 28, 2, 2, 7, 0, 28, 7, 2, 28, 7, 2, 0, 35,
+ 16, 17, 29, 0, 25, 36, 25, 37, 0, 38, 0, 0, 0, 28, 2, 7,
+ 7, 0, 0, 0, 2, 2, 2, 2, 2, 39, 40, 41, 0, 0, 0, 0,
+ 0, 10, 13, 28, 2, 2, 2, 2, 28, 2, 28, 2, 2, 2, 2, 2,
+ 2, 7, 2, 28, 2, 2, 0, 15, 16, 17, 18, 19, 25, 20, 33, 22,
+ 0, 0, 0, 0, 0, 28, 9, 39, 42, 10, 27, 28, 2, 2, 2, 7,
+ 28, 7, 2, 28, 2, 2, 0, 15, 43, 0, 0, 25, 20, 0, 0, 2,
+ 28, 28, 0, 0, 0, 0, 0, 0, 0, 0, 44, 28, 2, 2, 7, 0,
+ 2, 7, 2, 2, 0, 28, 7, 7, 2, 0, 28, 7, 0, 2, 7, 0,
+ 2, 2, 2, 2, 2, 2, 0, 0, 21, 14, 45, 0, 46, 31, 46, 32,
+ 0, 0, 0, 0, 33, 0, 0, 0, 0, 13, 27, 47, 2, 2, 2, 7,
+ 2, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 15,
+ 20, 14, 21, 45, 20, 36, 20, 37, 0, 0, 0, 25, 29, 2, 7, 0,
+ 0, 8, 27, 28, 2, 2, 2, 7, 2, 2, 2, 28, 2, 2, 0, 15,
+ 43, 0, 0, 33, 45, 0, 0, 0, 7, 48, 49, 0, 0, 0, 0, 0,
+ 0, 9, 27, 2, 2, 2, 2, 7, 2, 2, 2, 2, 2, 2, 50, 51,
+ 21, 21, 17, 29, 46, 31, 46, 32, 52, 0, 0, 0, 33, 0, 0, 0,
+ 28, 10, 27, 28, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 2, 2,
+ 2, 2, 28, 2, 2, 2, 2, 28, 0, 2, 2, 2, 7, 0, 53, 0,
+ 33, 21, 20, 29, 29, 16, 46, 46, 23, 0, 21, 0, 0, 0, 0, 0,
+ 0, 2, 0, 2, 7, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0,
+ 0, 2, 2, 54, 54, 55, 0, 0, 16, 2, 2, 2, 2, 28, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 7, 0, 56, 19, 57, 20, 20, 18, 18,
+ 44, 19, 9, 29, 9, 2, 2, 58, 59, 59, 59, 59, 59, 60, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61,
+ 0, 0, 0, 0, 62, 0, 0, 0, 0, 2, 2, 2, 2, 2, 63, 43,
+ 57, 64, 20, 20, 65, 66, 67, 68, 69, 2, 2, 2, 2, 2, 1, 0,
+ 3, 2, 2, 2, 21, 18, 2, 2, 70, 69, 71, 72, 63, 71, 27, 27,
+ 2, 50, 20, 51, 2, 2, 2, 2, 2, 2, 73, 74, 75, 27, 27, 76,
+ 77, 2, 2, 2, 2, 2, 27, 43, 0, 2, 57, 78, 0, 0, 0, 0,
+ 28, 2, 57, 45, 0, 0, 0, 0, 0, 2, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 7, 2, 7, 57, 0, 0, 0, 0, 0,
+ 0, 2, 2, 79, 43, 20, 57, 18, 46, 46, 46, 46, 13, 80, 81, 82,
+ 83, 84, 85, 0, 0, 0, 0, 86, 0, 7, 0, 0, 28, 0, 87, 79,
+ 88, 2, 2, 2, 2, 7, 0, 0, 0, 40, 40, 89, 90, 2, 2, 2,
+ 2, 2, 2, 2, 2, 11, 7, 0, 0, 91, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 7, 20, 78, 43, 20, 92, 59, 0,
+ 0, 93, 94, 93, 93, 95, 96, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 0, 2, 2, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 0,
+ 0, 2, 2, 2, 2, 27, 0, 0, 0, 2, 2, 2, 2, 2, 7, 0,
+ 0, 2, 2, 2, 50, 97, 43, 0, 0, 2, 2, 98, 99, 100, 101, 59,
+ 61, 102, 14, 43, 20, 57, 19, 78, 46, 46, 74, 9, 9, 9, 103, 44,
+ 38, 9, 104, 72, 2, 2, 2, 2, 2, 2, 2, 105, 20, 18, 18, 20,
+ 46, 46, 20, 106, 2, 2, 2, 7, 0, 0, 0, 0, 0, 0, 107, 108,
+ 109, 109, 109, 0, 0, 0, 0, 0, 0, 104, 72, 2, 2, 2, 2, 2,
+ 2, 58, 59, 57, 23, 20, 110, 59, 2, 2, 2, 2, 105, 20, 21, 43,
+ 43, 100, 12, 0, 0, 0, 0, 0, 0, 2, 2, 59, 16, 46, 21, 111,
+ 100, 100, 100, 112, 113, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 28,
+ 2, 9, 44, 114, 114, 114, 9, 114, 114, 13, 114, 114, 114, 24, 0, 38,
+ 0, 0, 0, 115, 116, 9, 3, 0, 0, 0, 0, 0, 0, 0, 117, 0,
+ 0, 0, 0, 0, 0, 0, 4, 118, 119, 40, 40, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 119, 119, 120, 119, 119, 119, 119, 119, 119, 119,
+ 119, 0, 0, 121, 0, 0, 0, 0, 0, 0, 5, 121, 0, 0, 0, 0,
+ 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7,
+ 0, 2, 2, 2, 2, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0,
+ 122, 2, 51, 2, 106, 2, 8, 2, 2, 2, 63, 17, 14, 0, 0, 29,
+ 0, 2, 2, 0, 0, 0, 0, 0, 0, 27, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 123, 21, 21, 21, 21, 21, 21, 21, 124, 0, 0, 0, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0,
+ 50, 2, 2, 2, 20, 20, 125, 114, 0, 2, 2, 2, 126, 18, 57, 18,
+ 111, 100, 127, 0, 0, 0, 0, 0, 0, 9, 128, 2, 2, 2, 2, 2,
+ 2, 2, 129, 21, 20, 18, 46, 130, 131, 132, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 50, 28, 2, 2, 2, 2, 2, 2, 2, 2, 8, 20, 57,
+ 97, 74, 133, 134, 135, 0, 0, 0, 0, 2, 136, 2, 2, 2, 2, 137,
+ 0, 28, 2, 40, 3, 0, 77, 13, 2, 51, 20, 138, 50, 51, 2, 2,
+ 103, 8, 7, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 139, 19,
+ 23, 0, 0, 140, 141, 0, 0, 0, 0, 2, 63, 43, 21, 78, 45, 142,
+ 0, 79, 79, 79, 79, 79, 79, 79, 79, 0, 0, 0, 0, 0, 0, 0,
+ 4, 119, 119, 119, 119, 120, 0, 0, 0, 2, 2, 2, 2, 2, 7, 2,
+ 2, 2, 7, 2, 28, 2, 2, 2, 2, 2, 28, 2, 2, 2, 28, 7,
+ 0, 126, 18, 25, 29, 0, 0, 143, 144, 2, 2, 28, 2, 28, 2, 2,
+ 2, 2, 2, 2, 0, 12, 35, 0, 145, 2, 2, 11, 35, 0, 28, 2,
+ 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 2, 2,
+ 7, 2, 2, 9, 39, 0, 0, 0, 0, 2, 2, 2, 2, 2, 25, 36,
+ 0, 2, 2, 2, 114, 114, 114, 114, 114, 146, 2, 7, 0, 0, 0, 0,
+ 0, 2, 12, 12, 0, 0, 0, 0, 0, 7, 2, 2, 7, 2, 2, 2,
+ 2, 28, 2, 7, 0, 28, 2, 0, 0, 147, 148, 149, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 20, 20, 18, 18, 18, 20, 20, 132, 0, 0, 0,
+ 0, 0, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 2, 2, 2, 2,
+ 2, 51, 50, 51, 0, 0, 0, 0, 151, 9, 72, 2, 2, 2, 2, 2,
+ 2, 16, 17, 19, 14, 22, 35, 0, 0, 0, 29, 0, 0, 0, 0, 0,
+ 0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 126, 18, 20, 152,
+ 20, 19, 153, 154, 2, 2, 2, 2, 2, 0, 0, 63, 155, 0, 0, 0,
+ 0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
+ 20, 106, 156, 0, 0, 157, 158, 29, 159, 28, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 160, 42, 0, 0, 0,
+ 44, 2, 2, 2, 7, 7, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
+ 28, 2, 2, 2, 2, 2, 2, 2, 8, 16, 17, 19, 20, 161, 29, 0,
+ 0, 9, 9, 28, 2, 2, 2, 7, 28, 7, 2, 28, 2, 2, 56, 15,
+ 21, 14, 21, 45, 30, 31, 30, 32, 0, 0, 0, 0, 33, 0, 0, 0,
+ 2, 2, 21, 0, 9, 9, 9, 44, 0, 9, 9, 44, 0, 0, 0, 0,
+ 0, 2, 2, 63, 23, 18, 18, 18, 20, 21, 124, 13, 15, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 0, 0, 162, 163, 0, 0, 0, 0, 0, 0,
+ 0, 16, 17, 18, 18, 64, 97, 23, 159, 9, 164, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 2, 2, 63, 23, 18, 18, 0, 46, 46, 9,
+ 165, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 18,
+ 0, 21, 17, 18, 18, 19, 14, 80, 165, 36, 0, 0, 0, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 8, 166, 23, 18, 20, 20, 164, 7, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 41, 134, 21, 20, 18, 74, 19, 20, 0,
+ 0, 2, 2, 2, 7, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 16,
+ 17, 18, 19, 20, 103, 165, 35, 0, 0, 2, 2, 2, 7, 28, 0, 2,
+ 2, 2, 2, 28, 7, 2, 2, 2, 2, 21, 21, 16, 30, 31, 10, 167,
+ 168, 169, 170, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 2, 2,
+ 2, 63, 23, 18, 18, 0, 20, 21, 27, 106, 0, 31, 0, 0, 0, 0,
+ 0, 50, 18, 20, 20, 20, 138, 2, 2, 2, 171, 172, 9, 13, 173, 70,
+ 174, 0, 0, 1, 145, 0, 0, 0, 0, 50, 18, 20, 14, 17, 18, 2,
+ 2, 2, 2, 156, 156, 156, 175, 175, 175, 175, 175, 175, 13, 176, 0, 28,
+ 0, 20, 18, 18, 29, 20, 20, 9, 165, 0, 59, 59, 59, 59, 59, 59,
+ 59, 64, 19, 80, 44, 0, 0, 0, 0, 2, 2, 2, 7, 2, 28, 2,
+ 2, 50, 20, 20, 29, 0, 36, 20, 25, 9, 158, 177, 173, 0, 0, 0,
+ 0, 2, 2, 2, 28, 7, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
+ 45, 20, 33, 80, 66, 0, 0, 0, 0, 2, 178, 64, 45, 0, 0, 0,
+ 0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
+ 0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
+ 38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
+ 0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
+ 35, 0, 4, 119, 119, 119, 120, 0, 0, 9, 9, 9, 47, 2, 2, 2,
+ 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
+ 44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0,
+ 0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B,
+ O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
+ B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre,
+ VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre,
+ O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,
+ CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv,
+ B, O, CS, CS, O, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O,
+ CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B,
+ VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,
+ VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ,
+ CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B,
+ CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst,
+ FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,
+ VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw,
+ FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, CS,VMPst, O,FMAbv, ZWNJ, CGJ, WJ,
+ WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst,
+ VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw,
+ O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,
+ VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O,
+ HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,
+ VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv,
+ VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw,
+ FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, H, H, O, VBlw,
+};
+static const uint16_t
+hb_use_u16[768] =
+{
+ 0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 11,
+ 0, 0, 0, 0, 9, 12, 0, 0, 13, 9, 9, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 17, 25, 26, 20, 21, 27, 28, 29, 30, 31,
+ 32, 33, 21, 34, 35, 0, 17, 36, 37, 20, 21, 38, 23, 39, 17, 40,
+ 41, 42, 43, 44, 45, 46, 30, 0, 47, 48, 21, 49, 50, 51, 17, 0,
+ 52, 48, 21, 53, 50, 54, 17, 55, 56, 48, 9, 57, 58, 59, 17, 0,
+ 60, 61, 9, 62, 63, 64, 30, 65, 66, 67, 9, 68, 69, 9, 70, 71,
+ 72, 73, 74, 75, 76, 0, 0, 0, 9, 9, 77, 78, 79, 80, 81, 82,
+ 83, 84, 0, 0, 0, 0, 0, 0, 9, 85, 9, 86, 9, 87, 88, 89,
+ 9, 9, 9, 90, 91, 92, 2, 0, 93, 0, 9, 9, 9, 9, 9, 94,
+ 95, 9, 96, 0, 0, 0, 0, 0, 97, 98, 99,100, 30, 9,101,102,
+ 9, 9,103, 9,104,105, 0, 0, 9,106, 9, 9, 9,107,108,109,
+ 2, 2, 0, 0, 0, 0, 0, 0,110, 9, 9,111,112, 2,113,114,
+ 115, 9,116, 9, 9, 9,117,118, 9, 9,119,120,121, 0, 0, 0,
+ 0, 0, 0, 0, 0,122,123,124, 0, 0, 0, 0, 0, 0, 0,125,
+ 126,127,128, 0, 0, 0,129,130,131, 0, 0, 0, 0, 0, 0,132,
+ 0, 0, 0, 0,133, 0, 0, 0, 0, 0, 0, 9, 9, 9,134,135,
+ 136, 9,137, 0, 9, 9, 9,138,139, 9, 9,140,141, 2,142,143,
+ 9, 9,144, 9,145,146, 0, 0,147, 9, 9,148,149, 2,150, 98,
+ 9, 9,151,152,153, 2, 9,154, 9, 9, 9,155,156, 0,157,158,
+ 0, 0, 0, 0, 9, 9,159, 2,160, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 0, 0, 0, 0,162,
+ 0, 0, 0, 0, 0, 0, 0,163,163,164, 33,165, 0, 0, 0, 0,
+ 166,167, 9,168, 94, 0, 0, 0, 0, 0, 0, 0, 69, 9,169, 0,
+ 9,170,171, 0, 0, 0, 0, 0, 9, 9,172, 2, 0, 0, 0, 0,
+ 9, 9,173,170, 0, 0, 0, 0, 0, 0, 0, 9,174,175, 0, 9,
+ 176, 0, 0,177,178, 0, 0, 0,179, 9, 9,180,181,182,183,184,
+ 185, 9, 9,186,187, 0, 0, 0,188, 9,189,190,191, 9, 9,192,
+ 185, 9, 9,193,194,105,195,102, 9, 33,196,197, 0, 0, 0, 0,
+ 198,199, 94, 9, 9,200,201, 2,202, 20, 21,203,204,205,206,207,
+ 9, 9, 9,208,209,210,211, 0,195, 9, 9,212,213, 2, 0, 0,
+ 9, 9,214,215,216,217, 0, 0, 9, 9, 9,218,219, 2, 0, 0,
+ 9, 9,220,221, 2, 0, 0, 0, 9,222,223,103,224, 0, 0, 0,
+ 9, 9,225,226, 0, 0, 0, 0,227,228, 9,229,230, 2, 0, 0,
+ 0, 0,231, 9, 9,232,233, 0,234, 9, 9,235,236,237, 9, 9,
+ 238,239, 0, 0, 0, 0, 0, 0, 21, 9,214,240, 7, 9, 70, 18,
+ 9,241, 73,242, 0, 0, 0, 0,243, 9, 9,244,245, 2,246, 9,
+ 247,248, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,249,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 98,250, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 9, 9, 9,251, 0, 0, 0, 0,
+ 9, 9, 9, 9,252,253,254,254,255,256, 0, 0, 0, 0,257, 0,
+ 9, 9, 9, 9, 9,258, 0, 0, 9, 9, 9, 9, 9, 9,105, 70,
+ 94,259, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,260,
+ 9, 9, 70,261,262, 0, 0, 0, 0, 9,263, 0, 9, 9,264, 2,
+ 9, 9, 9, 9,265, 2, 0, 0,129,129,129,129,129,129,129,129,
+ 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
+};
+
+static inline unsigned
+hb_use_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline uint_fast8_t
+hb_use_get_category (unsigned u)
+{
+ return u<921600u?hb_use_u8[2721+(((hb_use_u8[593+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
+}
+
+#undef B
+#undef CGJ
+#undef CS
+#undef G
+#undef GB
+#undef H
+#undef HN
+#undef HVM
+#undef IS
+#undef J
+#undef N
+#undef O
+#undef R
+#undef SB
+#undef SE
+#undef SUB
+#undef Sk
+#undef WJ
+#undef ZWNJ
+#undef CMAbv
+#undef CMBlw
+#undef FAbv
+#undef FBlw
+#undef FPst
+#undef FMAbv
+#undef FMBlw
+#undef FMPst
+#undef MAbv
+#undef MBlw
+#undef MPst
+#undef MPre
+#undef SMAbv
+#undef SMBlw
+#undef VAbv
+#undef VBlw
+#undef VPst
+#undef VPre
+#undef VMAbv
+#undef VMBlw
+#undef VMPst
+#undef VMPre
+
+
+#ifdef HB_USE_TABLE_MAIN
+int main (int argc, char **argv)
+{
+ if (argc != 2)
+ {
+ for (unsigned u = 0; u < 0x10FFFFu; u++)
+ printf ("U+%04X %d\n", u, hb_use_get_category (u));
+ return 0;
+ }
+
+ hb_codepoint_t u;
+ sscanf (argv[1], "%x", &u);
+
+ printf ("%d\n", hb_use_get_category (u));
+
+ return 0;
+}
+
+#endif
+
+
+#endif /* HB_OT_SHAPER_USE_TABLE_HH */
+/* == End of generated table == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
new file mode 100644
index 0000000000..c40ec52f9c
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-use.cc
@@ -0,0 +1,504 @@
+/*
+ * Copyright © 2015 Mozilla Foundation.
+ * Copyright © 2015 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Mozilla Author(s): Jonathan Kew
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-use-machine.hh"
+#include "hb-ot-shaper-use-table.hh"
+#include "hb-ot-shaper-arabic.hh"
+#include "hb-ot-shaper-arabic-joining-list.hh"
+#include "hb-ot-shaper-vowel-constraints.hh"
+
+
+/*
+ * Universal Shaping Engine.
+ * https://docs.microsoft.com/en-us/typography/script-development/use
+ */
+
+static const hb_tag_t
+use_basic_features[] =
+{
+ /*
+ * Basic features.
+ * These features are applied all at once, before reordering, constrained
+ * to the syllable.
+ */
+ HB_TAG('r','k','r','f'),
+ HB_TAG('a','b','v','f'),
+ HB_TAG('b','l','w','f'),
+ HB_TAG('h','a','l','f'),
+ HB_TAG('p','s','t','f'),
+ HB_TAG('v','a','t','u'),
+ HB_TAG('c','j','c','t'),
+};
+static const hb_tag_t
+use_topographical_features[] =
+{
+ HB_TAG('i','s','o','l'),
+ HB_TAG('i','n','i','t'),
+ HB_TAG('m','e','d','i'),
+ HB_TAG('f','i','n','a'),
+};
+/* Same order as use_topographical_features. */
+enum joining_form_t {
+ JOINING_FORM_ISOL,
+ JOINING_FORM_INIT,
+ JOINING_FORM_MEDI,
+ JOINING_FORM_FINA,
+ _JOINING_FORM_NONE
+};
+static const hb_tag_t
+use_other_features[] =
+{
+ /*
+ * Other features.
+ * These features are applied all at once, after reordering and
+ * clearing syllables.
+ */
+ HB_TAG('a','b','v','s'),
+ HB_TAG('b','l','w','s'),
+ HB_TAG('h','a','l','n'),
+ HB_TAG('p','r','e','s'),
+ HB_TAG('p','s','t','s'),
+};
+
+static void
+setup_syllables_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+record_rphf_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+record_pref_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+static void
+reorder_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer);
+
+static void
+collect_features_use (hb_ot_shape_planner_t *plan)
+{
+ hb_ot_map_builder_t *map = &plan->map;
+
+ /* Do this before any lookups have been applied. */
+ map->add_gsub_pause (setup_syllables_use);
+
+ /* "Default glyph pre-processing group" */
+ map->enable_feature (HB_TAG('l','o','c','l'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('c','c','m','p'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('n','u','k','t'), F_PER_SYLLABLE);
+ map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
+
+ /* "Reordering group" */
+ map->add_gsub_pause (_hb_clear_substitution_flags);
+ map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
+ map->add_gsub_pause (record_rphf_use);
+ map->add_gsub_pause (_hb_clear_substitution_flags);
+ map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ | F_PER_SYLLABLE);
+ map->add_gsub_pause (record_pref_use);
+
+ /* "Orthographic unit shaping group" */
+ for (unsigned int i = 0; i < ARRAY_LENGTH (use_basic_features); i++)
+ map->enable_feature (use_basic_features[i], F_MANUAL_ZWJ | F_PER_SYLLABLE);
+
+ map->add_gsub_pause (reorder_use);
+ map->add_gsub_pause (hb_syllabic_clear_var); // Don't need syllables anymore, use stop to free buffer var
+
+ /* "Topographical features" */
+ for (unsigned int i = 0; i < ARRAY_LENGTH (use_topographical_features); i++)
+ map->add_feature (use_topographical_features[i]);
+ map->add_gsub_pause (nullptr);
+
+ /* "Standard typographic presentation" */
+ for (unsigned int i = 0; i < ARRAY_LENGTH (use_other_features); i++)
+ map->enable_feature (use_other_features[i], F_MANUAL_ZWJ);
+}
+
+struct use_shape_plan_t
+{
+ hb_mask_t rphf_mask;
+
+ arabic_shape_plan_t *arabic_plan;
+};
+
+static void *
+data_create_use (const hb_ot_shape_plan_t *plan)
+{
+ use_shape_plan_t *use_plan = (use_shape_plan_t *) hb_calloc (1, sizeof (use_shape_plan_t));
+ if (unlikely (!use_plan))
+ return nullptr;
+
+ use_plan->rphf_mask = plan->map.get_1_mask (HB_TAG('r','p','h','f'));
+
+ if (has_arabic_joining (plan->props.script))
+ {
+ use_plan->arabic_plan = (arabic_shape_plan_t *) data_create_arabic (plan);
+ if (unlikely (!use_plan->arabic_plan))
+ {
+ hb_free (use_plan);
+ return nullptr;
+ }
+ }
+
+ return use_plan;
+}
+
+static void
+data_destroy_use (void *data)
+{
+ use_shape_plan_t *use_plan = (use_shape_plan_t *) data;
+
+ if (use_plan->arabic_plan)
+ data_destroy_arabic (use_plan->arabic_plan);
+
+ hb_free (data);
+}
+
+static void
+setup_masks_use (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
+
+ /* Do this before allocating use_category(). */
+ if (use_plan->arabic_plan)
+ {
+ setup_masks_arabic_plan (use_plan->arabic_plan, buffer, plan->props.script);
+ }
+
+ HB_BUFFER_ALLOCATE_VAR (buffer, use_category);
+
+ /* We cannot setup masks here. We save information about characters
+ * and setup masks later on in a pause-callback. */
+
+ unsigned int count = buffer->len;
+ hb_glyph_info_t *info = buffer->info;
+ for (unsigned int i = 0; i < count; i++)
+ info[i].use_category() = hb_use_get_category (info[i].codepoint);
+}
+
+static void
+setup_rphf_mask (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer)
+{
+ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
+
+ hb_mask_t mask = use_plan->rphf_mask;
+ if (!mask) return;
+
+ hb_glyph_info_t *info = buffer->info;
+
+ foreach_syllable (buffer, start, end)
+ {
+ unsigned int limit = info[start].use_category() == USE(R) ? 1 : hb_min (3u, end - start);
+ for (unsigned int i = start; i < start + limit; i++)
+ info[i].mask |= mask;
+ }
+}
+
+static void
+setup_topographical_masks (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer)
+{
+ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
+ if (use_plan->arabic_plan)
+ return;
+
+ static_assert ((JOINING_FORM_INIT < 4 && JOINING_FORM_ISOL < 4 && JOINING_FORM_MEDI < 4 && JOINING_FORM_FINA < 4), "");
+ hb_mask_t masks[4], all_masks = 0;
+ for (unsigned int i = 0; i < 4; i++)
+ {
+ masks[i] = plan->map.get_1_mask (use_topographical_features[i]);
+ if (masks[i] == plan->map.get_global_mask ())
+ masks[i] = 0;
+ all_masks |= masks[i];
+ }
+ if (!all_masks)
+ return;
+ hb_mask_t other_masks = ~all_masks;
+
+ unsigned int last_start = 0;
+ joining_form_t last_form = _JOINING_FORM_NONE;
+ hb_glyph_info_t *info = buffer->info;
+ foreach_syllable (buffer, start, end)
+ {
+ use_syllable_type_t syllable_type = (use_syllable_type_t) (info[start].syllable() & 0x0F);
+ switch (syllable_type)
+ {
+ case use_hieroglyph_cluster:
+ case use_non_cluster:
+ /* These don't join. Nothing to do. */
+ last_form = _JOINING_FORM_NONE;
+ break;
+
+ case use_virama_terminated_cluster:
+ case use_sakot_terminated_cluster:
+ case use_standard_cluster:
+ case use_number_joiner_terminated_cluster:
+ case use_numeral_cluster:
+ case use_symbol_cluster:
+ case use_broken_cluster:
+
+ bool join = last_form == JOINING_FORM_FINA || last_form == JOINING_FORM_ISOL;
+
+ if (join)
+ {
+ /* Fixup previous syllable's form. */
+ last_form = last_form == JOINING_FORM_FINA ? JOINING_FORM_MEDI : JOINING_FORM_INIT;
+ for (unsigned int i = last_start; i < start; i++)
+ info[i].mask = (info[i].mask & other_masks) | masks[last_form];
+ }
+
+ /* Form for this syllable. */
+ last_form = join ? JOINING_FORM_FINA : JOINING_FORM_ISOL;
+ for (unsigned int i = start; i < end; i++)
+ info[i].mask = (info[i].mask & other_masks) | masks[last_form];
+
+ break;
+ }
+
+ last_start = start;
+ }
+}
+
+static void
+setup_syllables_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
+ find_syllables_use (buffer);
+ foreach_syllable (buffer, start, end)
+ buffer->unsafe_to_break (start, end);
+ setup_rphf_mask (plan, buffer);
+ setup_topographical_masks (plan, buffer);
+}
+
+static void
+record_rphf_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
+
+ hb_mask_t mask = use_plan->rphf_mask;
+ if (!mask) return;
+ hb_glyph_info_t *info = buffer->info;
+
+ foreach_syllable (buffer, start, end)
+ {
+ /* Mark a substituted repha as USE(R). */
+ for (unsigned int i = start; i < end && (info[i].mask & mask); i++)
+ if (_hb_glyph_info_substituted (&info[i]))
+ {
+ info[i].use_category() = USE(R);
+ break;
+ }
+ }
+}
+
+static void
+record_pref_use (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_font_t *font HB_UNUSED,
+ hb_buffer_t *buffer)
+{
+ hb_glyph_info_t *info = buffer->info;
+
+ foreach_syllable (buffer, start, end)
+ {
+ /* Mark a substituted pref as VPre, as they behave the same way. */
+ for (unsigned int i = start; i < end; i++)
+ if (_hb_glyph_info_substituted (&info[i]))
+ {
+ info[i].use_category() = USE(VPre);
+ break;
+ }
+ }
+}
+
+static inline bool
+is_halant_use (const hb_glyph_info_t &info)
+{
+ return (info.use_category() == USE(H) || info.use_category() == USE(HVM) || info.use_category() == USE(IS)) &&
+ !_hb_glyph_info_ligated (&info);
+}
+
+static void
+reorder_syllable_use (hb_buffer_t *buffer, unsigned int start, unsigned int end)
+{
+ use_syllable_type_t syllable_type = (use_syllable_type_t) (buffer->info[start].syllable() & 0x0F);
+ /* Only a few syllable types need reordering. */
+ if (unlikely (!(FLAG_UNSAFE (syllable_type) &
+ (FLAG (use_virama_terminated_cluster) |
+ FLAG (use_sakot_terminated_cluster) |
+ FLAG (use_standard_cluster) |
+ FLAG (use_symbol_cluster) |
+ FLAG (use_broken_cluster) |
+ 0))))
+ return;
+
+ hb_glyph_info_t *info = buffer->info;
+
+#define POST_BASE_FLAGS64 (FLAG64 (USE(FAbv)) | \
+ FLAG64 (USE(FBlw)) | \
+ FLAG64 (USE(FPst)) | \
+ FLAG64 (USE(MAbv)) | \
+ FLAG64 (USE(MBlw)) | \
+ FLAG64 (USE(MPst)) | \
+ FLAG64 (USE(MPre)) | \
+ FLAG64 (USE(VAbv)) | \
+ FLAG64 (USE(VBlw)) | \
+ FLAG64 (USE(VPst)) | \
+ FLAG64 (USE(VPre)) | \
+ FLAG64 (USE(VMAbv)) | \
+ FLAG64 (USE(VMBlw)) | \
+ FLAG64 (USE(VMPst)) | \
+ FLAG64 (USE(VMPre)))
+
+ /* Move things forward. */
+ if (info[start].use_category() == USE(R) && end - start > 1)
+ {
+ /* Got a repha. Reorder it towards the end, but before the first post-base
+ * glyph. */
+ for (unsigned int i = start + 1; i < end; i++)
+ {
+ bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
+ is_halant_use (info[i]);
+ if (is_post_base_glyph || i == end - 1)
+ {
+ /* If we hit a post-base glyph, move before it; otherwise move to the
+ * end. Shift things in between backward. */
+
+ if (is_post_base_glyph)
+ i--;
+
+ buffer->merge_clusters (start, i + 1);
+ hb_glyph_info_t t = info[start];
+ memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
+ info[i] = t;
+
+ break;
+ }
+ }
+ }
+
+ /* Move things back. */
+ unsigned int j = start;
+ for (unsigned int i = start; i < end; i++)
+ {
+ uint32_t flag = FLAG_UNSAFE (info[i].use_category());
+ if (is_halant_use (info[i]))
+ {
+ /* If we hit a halant, move after it; otherwise move to the beginning, and
+ * shift things in between forward. */
+ j = i + 1;
+ }
+ else if (((flag) & (FLAG (USE(VPre)) | FLAG (USE(VMPre)))) &&
+ /* Only move the first component of a MultipleSubst. */
+ 0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
+ j < i)
+ {
+ buffer->merge_clusters (j, i + 1);
+ hb_glyph_info_t t = info[i];
+ memmove (&info[j + 1], &info[j], (i - j) * sizeof (info[0]));
+ info[j] = t;
+ }
+ }
+}
+
+static void
+reorder_use (const hb_ot_shape_plan_t *plan,
+ hb_font_t *font,
+ hb_buffer_t *buffer)
+{
+ if (buffer->message (font, "start reordering USE"))
+ {
+ hb_syllabic_insert_dotted_circles (font, buffer,
+ use_broken_cluster,
+ USE(B),
+ USE(R));
+
+ foreach_syllable (buffer, start, end)
+ reorder_syllable_use (buffer, start, end);
+
+ (void) buffer->message (font, "end reordering USE");
+ }
+
+ HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
+}
+
+
+static void
+preprocess_text_use (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font)
+{
+ _hb_preprocess_text_vowel_constraints (plan, buffer, font);
+}
+
+static bool
+compose_use (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab)
+{
+ /* Avoid recomposing split matras. */
+ if (HB_UNICODE_GENERAL_CATEGORY_IS_MARK (c->unicode->general_category (a)))
+ return false;
+
+ return (bool)c->unicode->compose (a, b, ab);
+}
+
+
+const hb_ot_shaper_t _hb_ot_shaper_use =
+{
+ collect_features_use,
+ nullptr, /* override_features */
+ data_create_use,
+ data_destroy_use,
+ preprocess_text_use,
+ nullptr, /* postprocess_glyphs */
+ nullptr, /* decompose */
+ compose_use,
+ setup_masks_use,
+ nullptr, /* reorder_marks */
+ HB_TAG_NONE, /* gpos_tag */
+ HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+ false, /* fallback_position */
+};
+
+
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc
new file mode 100644
index 0000000000..be4ac813b1
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.cc
@@ -0,0 +1,443 @@
+/* == Start of generated functions == */
+/*
+ * The following functions are generated by running:
+ *
+ * ./gen-vowel-constraints.py ms-use/IndicShapingInvalidCluster.txt Scripts.txt
+ *
+ * on files with these headers:
+ *
+ * # IndicShapingInvalidCluster.txt
+ * # Date: 2015-03-12, 21:17:00 GMT [AG]
+ * # Date: 2019-11-08, 23:22:00 GMT [AG]
+ *
+ * # Scripts-14.0.0.txt
+ * # Date: 2021-07-10, 00:35:31 GMT
+ */
+
+#include "hb.hh"
+
+#ifndef HB_NO_OT_SHAPE
+
+#include "hb-ot-shaper-vowel-constraints.hh"
+
+static void
+_output_dotted_circle (hb_buffer_t *buffer)
+{
+ (void) buffer->output_glyph (0x25CCu);
+ _hb_glyph_info_reset_continuation (&buffer->prev());
+}
+
+static void
+_output_with_dotted_circle (hb_buffer_t *buffer)
+{
+ _output_dotted_circle (buffer);
+ (void) buffer->next_glyph ();
+}
+
+void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
+ hb_buffer_t *buffer,
+ hb_font_t *font HB_UNUSED)
+{
+#ifdef HB_NO_OT_SHAPER_VOWEL_CONSTRAINTS
+ return;
+#endif
+ if (buffer->flags & HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE)
+ return;
+
+ /* UGLY UGLY UGLY business of adding dotted-circle in the middle of
+ * vowel-sequences that look like another vowel. Data for each script
+ * collected from the USE script development spec.
+ *
+ * https://github.com/harfbuzz/harfbuzz/issues/1019
+ */
+ buffer->clear_output ();
+ unsigned int count = buffer->len;
+ switch ((unsigned) buffer->props.script)
+ {
+ case HB_SCRIPT_DEVANAGARI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0905u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x093Au: case 0x093Bu: case 0x093Eu: case 0x0945u:
+ case 0x0946u: case 0x0949u: case 0x094Au: case 0x094Bu:
+ case 0x094Cu: case 0x094Fu: case 0x0956u: case 0x0957u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0906u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x093Au: case 0x0945u: case 0x0946u: case 0x0947u:
+ case 0x0948u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0909u:
+ matched = 0x0941u == buffer->cur (1).codepoint;
+ break;
+ case 0x090Fu:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0945u: case 0x0946u: case 0x0947u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0930u:
+ if (0x094Du == buffer->cur (1).codepoint &&
+ buffer->idx + 2 < count &&
+ 0x0907u == buffer->cur (2).codepoint)
+ {
+ (void) buffer->next_glyph ();
+ matched = true;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_BENGALI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0985u:
+ matched = 0x09BEu == buffer->cur (1).codepoint;
+ break;
+ case 0x098Bu:
+ matched = 0x09C3u == buffer->cur (1).codepoint;
+ break;
+ case 0x098Cu:
+ matched = 0x09E2u == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_GURMUKHI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0A05u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0A3Eu: case 0x0A48u: case 0x0A4Cu:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0A72u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0A3Fu: case 0x0A40u: case 0x0A47u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0A73u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0A41u: case 0x0A42u: case 0x0A4Bu:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_GUJARATI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0A85u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0ABEu: case 0x0AC5u: case 0x0AC7u: case 0x0AC8u:
+ case 0x0AC9u: case 0x0ACBu: case 0x0ACCu:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0AC5u:
+ matched = 0x0ABEu == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_ORIYA:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0B05u:
+ matched = 0x0B3Eu == buffer->cur (1).codepoint;
+ break;
+ case 0x0B0Fu: case 0x0B13u:
+ matched = 0x0B57u == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_TAMIL:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ if (0x0B85u == buffer->cur ().codepoint &&
+ 0x0BC2u == buffer->cur (1).codepoint)
+ {
+ matched = true;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_TELUGU:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0C12u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0C4Cu: case 0x0C55u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0C3Fu: case 0x0C46u: case 0x0C4Au:
+ matched = 0x0C55u == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_KANNADA:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0C89u: case 0x0C8Bu:
+ matched = 0x0CBEu == buffer->cur (1).codepoint;
+ break;
+ case 0x0C92u:
+ matched = 0x0CCCu == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_MALAYALAM:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0D07u: case 0x0D09u:
+ matched = 0x0D57u == buffer->cur (1).codepoint;
+ break;
+ case 0x0D0Eu:
+ matched = 0x0D46u == buffer->cur (1).codepoint;
+ break;
+ case 0x0D12u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0D3Eu: case 0x0D57u:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_SINHALA:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x0D85u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0DCFu: case 0x0DD0u: case 0x0DD1u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x0D8Bu: case 0x0D8Fu: case 0x0D94u:
+ matched = 0x0DDFu == buffer->cur (1).codepoint;
+ break;
+ case 0x0D8Du:
+ matched = 0x0DD8u == buffer->cur (1).codepoint;
+ break;
+ case 0x0D91u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x0DCAu: case 0x0DD9u: case 0x0DDAu: case 0x0DDCu:
+ case 0x0DDDu: case 0x0DDEu:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_BRAHMI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x11005u:
+ matched = 0x11038u == buffer->cur (1).codepoint;
+ break;
+ case 0x1100Bu:
+ matched = 0x1103Eu == buffer->cur (1).codepoint;
+ break;
+ case 0x1100Fu:
+ matched = 0x11042u == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_KHUDAWADI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x112B0u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x112E0u: case 0x112E5u: case 0x112E6u: case 0x112E7u:
+ case 0x112E8u:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_TIRHUTA:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x11481u:
+ matched = 0x114B0u == buffer->cur (1).codepoint;
+ break;
+ case 0x1148Bu: case 0x1148Du:
+ matched = 0x114BAu == buffer->cur (1).codepoint;
+ break;
+ case 0x114AAu:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x114B5u: case 0x114B6u:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_MODI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x11600u: case 0x11601u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x11639u: case 0x1163Au:
+ matched = true;
+ break;
+ }
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ case HB_SCRIPT_TAKRI:
+ for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
+ {
+ bool matched = false;
+ switch (buffer->cur ().codepoint)
+ {
+ case 0x11680u:
+ switch (buffer->cur (1).codepoint)
+ {
+ case 0x116ADu: case 0x116B4u: case 0x116B5u:
+ matched = true;
+ break;
+ }
+ break;
+ case 0x11686u:
+ matched = 0x116B2u == buffer->cur (1).codepoint;
+ break;
+ }
+ (void) buffer->next_glyph ();
+ if (matched) _output_with_dotted_circle (buffer);
+ }
+ break;
+
+ default:
+ break;
+ }
+ buffer->sync ();
+}
+
+
+#endif
+/* == End of generated functions == */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh
new file mode 100644
index 0000000000..5a7ee1b0f2
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper-vowel-constraints.hh
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2018 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
+#define HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH
+
+#include "hb.hh"
+
+#include "hb-ot-shaper.hh"
+
+HB_INTERNAL void
+_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font);
+
+#endif /* HB_OT_SHAPER_VOWEL_CONSTRAINTS_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-shaper.hh b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
new file mode 100644
index 0000000000..e160987f83
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-ot-shaper.hh
@@ -0,0 +1,397 @@
+/*
+ * Copyright © 2010,2011,2012 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_OT_SHAPER_HH
+#define HB_OT_SHAPER_HH
+
+#include "hb.hh"
+
+#include "hb-ot-layout.hh"
+#include "hb-ot-shape.hh"
+#include "hb-ot-shape-normalize.hh"
+
+
+/* buffer var allocations, used by all OT shapers */
+#define ot_shaper_var_u8_category() var2.u8[2]
+#define ot_shaper_var_u8_auxiliary() var2.u8[3]
+
+
+#define HB_OT_SHAPE_MAX_COMBINING_MARKS 32
+
+enum hb_ot_shape_zero_width_marks_type_t {
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
+ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
+};
+
+
+/* Master OT shaper list */
+#define HB_OT_SHAPERS_IMPLEMENT_SHAPERS \
+ HB_OT_SHAPER_IMPLEMENT (arabic) \
+ HB_OT_SHAPER_IMPLEMENT (default) \
+ HB_OT_SHAPER_IMPLEMENT (dumber) \
+ HB_OT_SHAPER_IMPLEMENT (hangul) \
+ HB_OT_SHAPER_IMPLEMENT (hebrew) \
+ HB_OT_SHAPER_IMPLEMENT (indic) \
+ HB_OT_SHAPER_IMPLEMENT (khmer) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar) \
+ HB_OT_SHAPER_IMPLEMENT (myanmar_zawgyi) \
+ HB_OT_SHAPER_IMPLEMENT (thai) \
+ HB_OT_SHAPER_IMPLEMENT (use) \
+ /* ^--- Add new shapers here; keep sorted. */
+
+
+struct hb_ot_shaper_t
+{
+ /* collect_features()
+ * Called during shape_plan().
+ * Shapers should use plan->map to add their features and callbacks.
+ * May be NULL.
+ */
+ void (*collect_features) (hb_ot_shape_planner_t *plan);
+
+ /* override_features()
+ * Called during shape_plan().
+ * Shapers should use plan->map to override features and add callbacks after
+ * common features are added.
+ * May be NULL.
+ */
+ void (*override_features) (hb_ot_shape_planner_t *plan);
+
+
+ /* data_create()
+ * Called at the end of shape_plan().
+ * Whatever shapers return will be accessible through plan->data later.
+ * If nullptr is returned, means a plan failure.
+ */
+ void *(*data_create) (const hb_ot_shape_plan_t *plan);
+
+ /* data_destroy()
+ * Called when the shape_plan is being destroyed.
+ * plan->data is passed here for destruction.
+ * If nullptr is returned, means a plan failure.
+ * May be NULL.
+ */
+ void (*data_destroy) (void *data);
+
+
+ /* preprocess_text()
+ * Called during shape().
+ * Shapers can use to modify text before shaping starts.
+ * May be NULL.
+ */
+ void (*preprocess_text) (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font);
+
+ /* postprocess_glyphs()
+ * Called during shape().
+ * Shapers can use to modify glyphs after shaping ends.
+ * May be NULL.
+ */
+ void (*postprocess_glyphs) (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font);
+
+
+ /* decompose()
+ * Called during shape()'s normalization.
+ * May be NULL.
+ */
+ bool (*decompose) (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t ab,
+ hb_codepoint_t *a,
+ hb_codepoint_t *b);
+
+ /* compose()
+ * Called during shape()'s normalization.
+ * May be NULL.
+ */
+ bool (*compose) (const hb_ot_shape_normalize_context_t *c,
+ hb_codepoint_t a,
+ hb_codepoint_t b,
+ hb_codepoint_t *ab);
+
+ /* setup_masks()
+ * Called during shape().
+ * Shapers should use map to get feature masks and set on buffer.
+ * Shapers may NOT modify characters.
+ * May be NULL.
+ */
+ void (*setup_masks) (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ hb_font_t *font);
+
+ /* reorder_marks()
+ * Called during shape().
+ * Shapers can use to modify ordering of combining marks.
+ * May be NULL.
+ */
+ void (*reorder_marks) (const hb_ot_shape_plan_t *plan,
+ hb_buffer_t *buffer,
+ unsigned int start,
+ unsigned int end);
+
+ /* gpos_tag()
+ * If not HB_TAG_NONE, then must match found GPOS script tag for
+ * GPOS to be applied. Otherwise, fallback positioning will be used.
+ */
+ hb_tag_t gpos_tag;
+
+ hb_ot_shape_normalization_mode_t normalization_preference;
+
+ hb_ot_shape_zero_width_marks_type_t zero_width_marks;
+
+ bool fallback_position;
+};
+
+#define HB_OT_SHAPER_IMPLEMENT(name) extern HB_INTERNAL const hb_ot_shaper_t _hb_ot_shaper_##name;
+HB_OT_SHAPERS_IMPLEMENT_SHAPERS
+#undef HB_OT_SHAPER_IMPLEMENT
+
+
+static inline const hb_ot_shaper_t *
+hb_ot_shaper_categorize (const hb_ot_shape_planner_t *planner)
+{
+ switch ((hb_tag_t) planner->props.script)
+ {
+ default:
+ return &_hb_ot_shaper_default;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_ARABIC:
+
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_SYRIAC:
+
+ /* For Arabic script, use the Arabic shaper even if no OT script tag was found.
+ * This is because we do fallback shaping for Arabic script (and not others).
+ * But note that Arabic shaping is applicable only to horizontal layout; for
+ * vertical text, just use the generic shaper instead. */
+ if ((planner->map.chosen_script[0] != HB_OT_TAG_DEFAULT_SCRIPT ||
+ planner->props.script == HB_SCRIPT_ARABIC) &&
+ HB_DIRECTION_IS_HORIZONTAL(planner->props.direction))
+ return &_hb_ot_shaper_arabic;
+ else
+ return &_hb_ot_shaper_default;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_THAI:
+ case HB_SCRIPT_LAO:
+
+ return &_hb_ot_shaper_thai;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HANGUL:
+
+ return &_hb_ot_shaper_hangul;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_HEBREW:
+
+ return &_hb_ot_shaper_hebrew;
+
+
+ /* Unicode-1.1 additions */
+ case HB_SCRIPT_BENGALI:
+ case HB_SCRIPT_DEVANAGARI:
+ case HB_SCRIPT_GUJARATI:
+ case HB_SCRIPT_GURMUKHI:
+ case HB_SCRIPT_KANNADA:
+ case HB_SCRIPT_MALAYALAM:
+ case HB_SCRIPT_ORIYA:
+ case HB_SCRIPT_TAMIL:
+ case HB_SCRIPT_TELUGU:
+
+ /* If the designer designed the font for the 'DFLT' script,
+ * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+ * Otherwise, use the specific shaper.
+ *
+ * If it's indy3 tag, send to USE. */
+ if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+ planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+ return &_hb_ot_shaper_default;
+ else if ((planner->map.chosen_script[0] & 0x000000FF) == '3')
+ return &_hb_ot_shaper_use;
+ else
+ return &_hb_ot_shaper_indic;
+
+ case HB_SCRIPT_KHMER:
+ return &_hb_ot_shaper_khmer;
+
+ case HB_SCRIPT_MYANMAR:
+ /* If the designer designed the font for the 'DFLT' script,
+ * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+ * Otherwise, use the specific shaper.
+ *
+ * If designer designed for 'mymr' tag, also send to default
+ * shaper. That's tag used from before Myanmar shaping spec
+ * was developed. The shaping spec uses 'mym2' tag. */
+ if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+ planner->map.chosen_script[0] == HB_TAG ('l','a','t','n') ||
+ planner->map.chosen_script[0] == HB_TAG ('m','y','m','r'))
+ return &_hb_ot_shaper_default;
+ else
+ return &_hb_ot_shaper_myanmar;
+
+
+#define HB_SCRIPT_MYANMAR_ZAWGYI ((hb_script_t) HB_TAG ('Q','a','a','g'))
+ case HB_SCRIPT_MYANMAR_ZAWGYI:
+ /* https://github.com/harfbuzz/harfbuzz/issues/1162 */
+
+ return &_hb_ot_shaper_myanmar_zawgyi;
+
+
+ /* Unicode-2.0 additions */
+ case HB_SCRIPT_TIBETAN:
+
+ /* Unicode-3.0 additions */
+ case HB_SCRIPT_MONGOLIAN:
+ case HB_SCRIPT_SINHALA:
+
+ /* Unicode-3.2 additions */
+ case HB_SCRIPT_BUHID:
+ case HB_SCRIPT_HANUNOO:
+ case HB_SCRIPT_TAGALOG:
+ case HB_SCRIPT_TAGBANWA:
+
+ /* Unicode-4.0 additions */
+ case HB_SCRIPT_LIMBU:
+ case HB_SCRIPT_TAI_LE:
+
+ /* Unicode-4.1 additions */
+ case HB_SCRIPT_BUGINESE:
+ case HB_SCRIPT_KHAROSHTHI:
+ case HB_SCRIPT_SYLOTI_NAGRI:
+ case HB_SCRIPT_TIFINAGH:
+
+ /* Unicode-5.0 additions */
+ case HB_SCRIPT_BALINESE:
+ case HB_SCRIPT_NKO:
+ case HB_SCRIPT_PHAGS_PA:
+
+ /* Unicode-5.1 additions */
+ case HB_SCRIPT_CHAM:
+ case HB_SCRIPT_KAYAH_LI:
+ case HB_SCRIPT_LEPCHA:
+ case HB_SCRIPT_REJANG:
+ case HB_SCRIPT_SAURASHTRA:
+ case HB_SCRIPT_SUNDANESE:
+
+ /* Unicode-5.2 additions */
+ case HB_SCRIPT_EGYPTIAN_HIEROGLYPHS:
+ case HB_SCRIPT_JAVANESE:
+ case HB_SCRIPT_KAITHI:
+ case HB_SCRIPT_MEETEI_MAYEK:
+ case HB_SCRIPT_TAI_THAM:
+ case HB_SCRIPT_TAI_VIET:
+
+ /* Unicode-6.0 additions */
+ case HB_SCRIPT_BATAK:
+ case HB_SCRIPT_BRAHMI:
+ case HB_SCRIPT_MANDAIC:
+
+ /* Unicode-6.1 additions */
+ case HB_SCRIPT_CHAKMA:
+ case HB_SCRIPT_MIAO:
+ case HB_SCRIPT_SHARADA:
+ case HB_SCRIPT_TAKRI:
+
+ /* Unicode-7.0 additions */
+ case HB_SCRIPT_DUPLOYAN:
+ case HB_SCRIPT_GRANTHA:
+ case HB_SCRIPT_KHOJKI:
+ case HB_SCRIPT_KHUDAWADI:
+ case HB_SCRIPT_MAHAJANI:
+ case HB_SCRIPT_MANICHAEAN:
+ case HB_SCRIPT_MODI:
+ case HB_SCRIPT_PAHAWH_HMONG:
+ case HB_SCRIPT_PSALTER_PAHLAVI:
+ case HB_SCRIPT_SIDDHAM:
+ case HB_SCRIPT_TIRHUTA:
+
+ /* Unicode-8.0 additions */
+ case HB_SCRIPT_AHOM:
+ case HB_SCRIPT_MULTANI:
+
+ /* Unicode-9.0 additions */
+ case HB_SCRIPT_ADLAM:
+ case HB_SCRIPT_BHAIKSUKI:
+ case HB_SCRIPT_MARCHEN:
+ case HB_SCRIPT_NEWA:
+
+ /* Unicode-10.0 additions */
+ case HB_SCRIPT_MASARAM_GONDI:
+ case HB_SCRIPT_SOYOMBO:
+ case HB_SCRIPT_ZANABAZAR_SQUARE:
+
+ /* Unicode-11.0 additions */
+ case HB_SCRIPT_DOGRA:
+ case HB_SCRIPT_GUNJALA_GONDI:
+ case HB_SCRIPT_HANIFI_ROHINGYA:
+ case HB_SCRIPT_MAKASAR:
+ case HB_SCRIPT_MEDEFAIDRIN:
+ case HB_SCRIPT_OLD_SOGDIAN:
+ case HB_SCRIPT_SOGDIAN:
+
+ /* Unicode-12.0 additions */
+ case HB_SCRIPT_ELYMAIC:
+ case HB_SCRIPT_NANDINAGARI:
+ case HB_SCRIPT_NYIAKENG_PUACHUE_HMONG:
+ case HB_SCRIPT_WANCHO:
+
+ /* Unicode-13.0 additions */
+ case HB_SCRIPT_CHORASMIAN:
+ case HB_SCRIPT_DIVES_AKURU:
+ case HB_SCRIPT_KHITAN_SMALL_SCRIPT:
+ case HB_SCRIPT_YEZIDI:
+
+ /* Unicode-14.0 additions */
+ case HB_SCRIPT_CYPRO_MINOAN:
+ case HB_SCRIPT_OLD_UYGHUR:
+ case HB_SCRIPT_TANGSA:
+ case HB_SCRIPT_TOTO:
+ case HB_SCRIPT_VITHKUQI:
+
+ /* If the designer designed the font for the 'DFLT' script,
+ * (or we ended up arbitrarily pick 'latn'), use the default shaper.
+ * Otherwise, use the specific shaper.
+ * Note that for some simple scripts, there may not be *any*
+ * GSUB/GPOS needed, so there may be no scripts found! */
+ if (planner->map.chosen_script[0] == HB_TAG ('D','F','L','T') ||
+ planner->map.chosen_script[0] == HB_TAG ('l','a','t','n'))
+ return &_hb_ot_shaper_default;
+ else
+ return &_hb_ot_shaper_use;
+ }
+}
+
+
+#endif /* HB_OT_SHAPER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
index 41d1734b39..d83bf14219 100644
--- a/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-stat-table.hh
@@ -57,6 +57,31 @@ enum
// Reserved = 0xFFFC /* Reserved for future use — set to zero. */
};
+struct StatAxisRecord
+{
+ int cmp (hb_tag_t key) const { return tag.cmp (key); }
+
+ hb_ot_name_id_t get_name_id () const { return nameID; }
+
+ hb_tag_t get_axis_tag () const { return tag; }
+
+ bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (likely (c->check_struct (this)));
+ }
+
+ protected:
+ Tag tag; /* A tag identifying the axis of design variation. */
+ NameID nameID; /* The name ID for entries in the 'name' table that
+ * provide a display string for this axis. */
+ HBUINT16 ordering; /* A value that applications can use to determine
+ * primary sorting of face names, or for ordering
+ * of descriptors when composing family or face names. */
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
struct AxisValueFormat1
{
unsigned int get_axis_index () const { return axisIndex; }
@@ -64,10 +89,41 @@ struct AxisValueFormat1
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -92,10 +148,41 @@ struct AxisValueFormat2
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -124,10 +211,41 @@ struct AxisValueFormat3
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
+ hb_tag_t get_axis_tag (const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ unsigned axis_idx = get_axis_index ();
+ return axis_records[axis_idx].get_axis_tag ();
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_tag_t axis_tag = get_axis_tag (axis_records);
+ float axis_value = get_value ();
+
+ if (!user_axes_location->has (axis_tag) ||
+ fabsf(axis_value - user_axes_location->get (axis_tag)) < 0.001f)
+ return true;
+
+ return false;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float>* user_axes_location = c->plan->user_axes_location;
+
+ if (keep_axis_value (axis_records, user_axes_location))
+ return_trace (c->serializer->embed (this));
+
+ return_trace (false);
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -155,7 +273,7 @@ struct AxisValueRecord
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (c->check_struct (this));
}
protected:
@@ -172,12 +290,47 @@ struct AxisValueFormat4
const AxisValueRecord &get_axis_record (unsigned int axis_index) const
{ return axisValues.as_array (axisCount)[axis_index]; }
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ hb_array_t<const AxisValueRecord> axis_value_records = axisValues.as_array (axisCount);
+
+ for (const auto& rec : axis_value_records)
+ {
+ unsigned axis_idx = rec.get_axis_index ();
+ float axis_value = rec.get_value ();
+ hb_tag_t axis_tag = axis_records[axis_idx].get_axis_tag ();
+
+ if (user_axes_location->has (axis_tag) &&
+ fabsf(axis_value - user_axes_location->get (axis_tag)) > 0.001f)
+ return false;
+ }
+
+ return true;
+ }
+
+ bool subset (hb_subset_context_t *c,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location = c->plan->user_axes_location;
+ if (!keep_axis_value (axis_records, user_axes_location))
+ return_trace (false);
+
+ unsigned total_size = min_size + axisCount * AxisValueRecord::static_size;
+ auto *out = c->serializer->allocate_size<AxisValueFormat4> (total_size);
+ if (unlikely (!out)) return_trace (false);
+ memcpy (out, this, total_size);
+ return_trace (true);
+ }
+
hb_ot_name_id_t get_value_name_id () const { return valueNameID; }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (likely (c->check_struct (this) &&
+ axisValues.sanitize (c, axisCount)));
}
protected:
@@ -234,6 +387,33 @@ struct AxisValue
}
}
+ template <typename context_t, typename ...Ts>
+ typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
+ {
+ TRACE_DISPATCH (this, u.format);
+ if (unlikely (!c->may_dispatch (this, &u.format))) return_trace (c->no_dispatch_return_value ());
+ switch (u.format) {
+ case 1: return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
+ case 2: return_trace (c->dispatch (u.format2, std::forward<Ts> (ds)...));
+ case 3: return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
+ case 4: return_trace (c->dispatch (u.format4, std::forward<Ts> (ds)...));
+ default:return_trace (c->default_return_value ());
+ }
+ }
+
+ bool keep_axis_value (const hb_array_t<const StatAxisRecord> axis_records,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location) const
+ {
+ switch (u.format)
+ {
+ case 1: return u.format1.keep_axis_value (axis_records, user_axes_location);
+ case 2: return u.format2.keep_axis_value (axis_records, user_axes_location);
+ case 3: return u.format3.keep_axis_value (axis_records, user_axes_location);
+ case 4: return u.format4.keep_axis_value (axis_records, user_axes_location);
+ default:return false;
+ }
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -263,27 +443,35 @@ struct AxisValue
DEFINE_SIZE_UNION (2, format);
};
-struct StatAxisRecord
+struct AxisValueOffsetArray: UnsizedArrayOf<Offset16To<AxisValue>>
{
- int cmp (hb_tag_t key) const { return tag.cmp (key); }
+ bool subset (hb_subset_context_t *c,
+ unsigned axisValueCount,
+ unsigned& count,
+ const hb_array_t<const StatAxisRecord> axis_records) const
+ {
+ TRACE_SUBSET (this);
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!out)) return_trace (false);
- hb_ot_name_id_t get_name_id () const { return nameID; }
+ auto axisValueOffsets = as_array (axisValueCount);
+ count = 0;
+ for (const auto& offset : axisValueOffsets)
+ {
+ if (!offset) continue;
+ auto o_snap = c->serializer->snapshot ();
+ auto *o = c->serializer->embed (offset);
+ if (!o) return_trace (false);
+ if (!o->serialize_subset (c, offset, this, axis_records))
+ {
+ c->serializer->revert (o_snap);
+ continue;
+ }
+ count++;
+ }
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this)));
+ return_trace (count);
}
-
- protected:
- Tag tag; /* A tag identifying the axis of design variation. */
- NameID nameID; /* The name ID for entries in the 'name' table that
- * provide a display string for this axis. */
- HBUINT16 ordering; /* A value that applications can use to determine
- * primary sorting of face names, or for ordering
- * of descriptors when composing family or face names. */
- public:
- DEFINE_SIZE_STATIC (8);
};
struct STAT
@@ -329,7 +517,8 @@ struct STAT
return axis_value.get_value_name_id ();
}
- void collect_name_ids (hb_set_t *nameids_to_retain) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids_to_retain /* OUT */) const
{
if (!has_data ()) return;
@@ -338,13 +527,38 @@ struct STAT
| hb_sink (nameids_to_retain)
;
+ auto designAxes = get_design_axes ();
+
+ get_axis_value_offsets ()
| hb_map (hb_add (&(this + offsetToAxisValueOffsets)))
+ | hb_filter ([&] (const AxisValue& _)
+ { return _.keep_axis_value (designAxes, user_axes_location); })
| hb_map (&AxisValue::get_value_name_id)
| hb_sink (nameids_to_retain)
;
}
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+ STAT *out = c->serializer->embed (this);
+ if (unlikely (!out)) return_trace (false);
+
+ auto designAxes = get_design_axes ();
+ for (unsigned i = 0; i < (unsigned)designAxisCount; i++)
+ if (unlikely (!c->serializer->embed (designAxes[i])))
+ return_trace (false);
+
+ if (designAxisCount)
+ c->serializer->check_assign (out->designAxesOffset, this->get_size (),
+ HB_SERIALIZE_ERROR_INT_OVERFLOW);
+
+ unsigned count = 0;
+ out->offsetToAxisValueOffsets.serialize_subset (c, offsetToAxisValueOffsets, this,
+ axisValueCount, count, designAxes);
+ return_trace (c->serializer->check_assign (out->axisValueCount, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
+ }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -381,7 +595,7 @@ struct STAT
* set to zero; if designAxisCount is greater
* than zero, must be greater than zero. */
HBUINT16 axisValueCount; /* The number of axis value tables. */
- NNOffset32To<UnsizedArrayOf<Offset16To<AxisValue>>>
+ NNOffset32To<AxisValueOffsetArray>
offsetToAxisValueOffsets;
/* Offset in bytes from the beginning of
* the STAT table to the start of the design
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
index 61d2814e93..9394b90ee6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-tag-table.hh
@@ -7,1615 +7,1623 @@
* on files with these headers:
*
* <meta name="updated_at" content="2022-01-28 10:00 PM" />
- * File-Date: 2021-12-29
+ * File-Date: 2022-03-02
*/
#ifndef HB_OT_TAG_TABLE_HH
#define HB_OT_TAG_TABLE_HH
-static const LangTag ot_languages[] = {
- {"aa", HB_TAG('A','F','R',' ')}, /* Afar */
- {"aae", HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
- {"aao", HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
- {"aat", HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
- {"ab", HB_TAG('A','B','K',' ')}, /* Abkhazian */
- {"aba", HB_TAG_NONE }, /* Abé != Abaza */
- {"abh", HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
- {"abq", HB_TAG('A','B','A',' ')}, /* Abaza */
- {"abs", HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
- {"abv", HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
- {"acf", HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
- {"acf", HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
-/*{"ach", HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
- {"acm", HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
- {"acq", HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
- {"acr", HB_TAG('A','C','R',' ')}, /* Achi */
- {"acr", HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
- {"acw", HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
- {"acx", HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
- {"acy", HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
- {"ada", HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
- {"adf", HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
- {"adp", HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
-/*{"ady", HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
- {"aeb", HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
- {"aec", HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
- {"af", HB_TAG('A','F','K',' ')}, /* Afrikaans */
- {"afb", HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
- {"afk", HB_TAG_NONE }, /* Nanubae != Afrikaans */
- {"afs", HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
- {"agu", HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
- {"agw", HB_TAG_NONE }, /* Kahua != Agaw */
- {"ahg", HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
- {"aht", HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
- {"aig", HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
- {"aii", HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
- {"aii", HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
-/*{"aio", HB_TAG('A','I','O',' ')},*/ /* Aiton */
- {"aiw", HB_TAG('A','R','I',' ')}, /* Aari */
- {"ajp", HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
- {"ak", HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
- {"akb", HB_TAG('A','K','B',' ')}, /* Batak Angkola */
- {"akb", HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
- {"aln", HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
- {"als", HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
-/*{"alt", HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
- {"am", HB_TAG('A','M','H',' ')}, /* Amharic */
- {"amf", HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
- {"amw", HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
- {"an", HB_TAG('A','R','G',' ')}, /* Aragonese */
-/*{"ang", HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
- {"aoa", HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
- {"apa", HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
- {"apc", HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
- {"apd", HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
- {"apj", HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
- {"apk", HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
- {"apl", HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
- {"apm", HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
- {"apw", HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
- {"ar", HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
- {"arb", HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
- {"ari", HB_TAG_NONE }, /* Arikara != Aari */
- {"ark", HB_TAG_NONE }, /* Arikapú != Rakhine */
- {"arn", HB_TAG('M','A','P',' ')}, /* Mapudungun */
- {"arq", HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
- {"ars", HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
- {"ary", HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
- {"ary", HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
- {"arz", HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
- {"as", HB_TAG('A','S','M',' ')}, /* Assamese */
-/*{"ast", HB_TAG('A','S','T',' ')},*/ /* Asturian */
-/*{"ath", HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
- {"atj", HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
- {"atv", HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
- {"auj", HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
- {"auz", HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
- {"av", HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
- {"avl", HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
-/*{"avn", HB_TAG('A','V','N',' ')},*/ /* Avatime */
-/*{"awa", HB_TAG('A','W','A',' ')},*/ /* Awadhi */
- {"ay", HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
- {"ayc", HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
- {"ayh", HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
- {"ayl", HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
- {"ayn", HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
- {"ayp", HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
- {"ayr", HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
- {"az", HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
- {"azb", HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
- {"azb", HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
- {"azd", HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
- {"azj", HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
- {"azn", HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
- {"azz", HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
- {"ba", HB_TAG('B','S','H',' ')}, /* Bashkir */
- {"bad", HB_TAG('B','A','D','0')}, /* Banda [collection] */
- {"bag", HB_TAG_NONE }, /* Tuki != Baghelkhandi */
- {"bah", HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
- {"bai", HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
- {"bal", HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
-/*{"ban", HB_TAG('B','A','N',' ')},*/ /* Balinese */
-/*{"bar", HB_TAG('B','A','R',' ')},*/ /* Bavarian */
- {"bau", HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
- {"bbc", HB_TAG('B','B','C',' ')}, /* Batak Toba */
- {"bbc", HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
- {"bbj", HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
- {"bbp", HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
- {"bbr", HB_TAG_NONE }, /* Girawa != Berber */
- {"bbz", HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
- {"bcc", HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
- {"bch", HB_TAG_NONE }, /* Bariai != Bench */
- {"bci", HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
- {"bcl", HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
- {"bcq", HB_TAG('B','C','H',' ')}, /* Bench */
- {"bcr", HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
-/*{"bdy", HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
- {"be", HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
- {"bea", HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
- {"beb", HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
-/*{"bem", HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
- {"ber", HB_TAG('B','B','R',' ')}, /* Berber [collection] */
- {"bew", HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
- {"bfl", HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
- {"bfq", HB_TAG('B','A','D',' ')}, /* Badaga */
- {"bft", HB_TAG('B','L','T',' ')}, /* Balti */
- {"bfu", HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
- {"bfy", HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
- {"bg", HB_TAG('B','G','R',' ')}, /* Bulgarian */
-/*{"bgc", HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
- {"bgn", HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
- {"bgp", HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
- {"bgq", HB_TAG('B','G','Q',' ')}, /* Bagri */
- {"bgq", HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
- {"bgr", HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
- {"bhb", HB_TAG('B','H','I',' ')}, /* Bhili */
-/*{"bhi", HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
- {"bhk", HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
-/*{"bho", HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
- {"bhr", HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
- {"bi", HB_TAG('B','I','S',' ')}, /* Bislama */
- {"bi", HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
-/*{"bik", HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
- {"bil", HB_TAG_NONE }, /* Bile != Bilen */
- {"bin", HB_TAG('E','D','O',' ')}, /* Edo */
- {"biu", HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
-/*{"bjj", HB_TAG('B','J','J',' ')},*/ /* Kanauji */
- {"bjn", HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
- {"bjo", HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
- {"bjq", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
- {"bjs", HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
- {"bjt", HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
- {"bkf", HB_TAG_NONE }, /* Beeke != Blackfoot */
- {"bko", HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
- {"bla", HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
- {"ble", HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
- {"blg", HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
- {"bli", HB_TAG_NONE }, /* Bolia != Baluchi */
- {"blk", HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
- {"blk", HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
- {"bln", HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
- {"blt", HB_TAG_NONE }, /* Tai Dam != Balti */
- {"bm", HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
- {"bmb", HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
- {"bml", HB_TAG_NONE }, /* Bomboli != Bamileke */
- {"bmm", HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
- {"bn", HB_TAG('B','E','N',' ')}, /* Bengali */
- {"bo", HB_TAG('T','I','B',' ')}, /* Tibetan */
- {"bpd", HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
- {"bpl", HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
- {"bpq", HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
-/*{"bpy", HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
- {"bqi", HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
- {"bqk", HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
- {"br", HB_TAG('B','R','E',' ')}, /* Breton */
- {"bra", HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
- {"brc", HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
-/*{"brh", HB_TAG('B','R','H',' ')},*/ /* Brahui */
- {"bri", HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
- {"brm", HB_TAG_NONE }, /* Barambu != Burmese */
-/*{"brx", HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
- {"bs", HB_TAG('B','O','S',' ')}, /* Bosnian */
- {"bsh", HB_TAG_NONE }, /* Kati != Bashkir */
-/*{"bsk", HB_TAG('B','S','K',' ')},*/ /* Burushaski */
- {"btb", HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
- {"btd", HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
- {"btd", HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
- {"bti", HB_TAG_NONE }, /* Burate != Beti */
- {"btj", HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
-/*{"btk", HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
- {"btm", HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
- {"btm", HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
- {"bto", HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
- {"bts", HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
- {"bts", HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
- {"btx", HB_TAG('B','T','X',' ')}, /* Batak Karo */
- {"btx", HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
- {"btz", HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
- {"btz", HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
-/*{"bug", HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
- {"bum", HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
- {"bve", HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
- {"bvu", HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
- {"bwe", HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
- {"bxk", HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
- {"bxo", HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
- {"bxp", HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
- {"bxr", HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
- {"byn", HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
- {"byv", HB_TAG('B','Y','V',' ')}, /* Medumba */
- {"byv", HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
- {"bzc", HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
- {"bzj", HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
- {"bzk", HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
- {"ca", HB_TAG('C','A','T',' ')}, /* Catalan */
- {"caa", HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
- {"cac", HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
- {"caf", HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
- {"caf", HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
- {"cak", HB_TAG('C','A','K',' ')}, /* Kaqchikel */
- {"cak", HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
- {"cbk", HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
- {"cbk", HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
- {"cbl", HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
- {"ccl", HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
- {"ccm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
- {"cco", HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
- {"ccq", HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
- {"cdo", HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
- {"ce", HB_TAG('C','H','E',' ')}, /* Chechen */
-/*{"ceb", HB_TAG('C','E','B',' ')},*/ /* Cebuano */
- {"cek", HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
- {"cey", HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
- {"cfm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
- {"cfm", HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
-/*{"cgg", HB_TAG('C','G','G',' ')},*/ /* Chiga */
- {"ch", HB_TAG('C','H','A',' ')}, /* Chamorro */
- {"chf", HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
- {"chg", HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
- {"chh", HB_TAG_NONE }, /* Chinook != Chattisgarhi */
- {"chj", HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
- {"chk", HB_TAG('C','H','K','0')}, /* Chuukese */
- {"chm", HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
- {"chm", HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
- {"chn", HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
-/*{"cho", HB_TAG('C','H','O',' ')},*/ /* Choctaw */
- {"chp", HB_TAG('C','H','P',' ')}, /* Chipewyan */
- {"chp", HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
- {"chp", HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
- {"chq", HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
-/*{"chr", HB_TAG('C','H','R',' ')},*/ /* Cherokee */
-/*{"chy", HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
- {"chz", HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
- {"ciw", HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
-/*{"cja", HB_TAG('C','J','A',' ')},*/ /* Western Cham */
-/*{"cjm", HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
- {"cjy", HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
- {"cka", HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
- {"ckb", HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
- {"ckn", HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
- {"cks", HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
- {"ckt", HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
- {"ckz", HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
- {"clc", HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
- {"cld", HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
- {"cle", HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
- {"clj", HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
- {"clt", HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
- {"cmn", HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
- {"cmr", HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
- {"cnb", HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
- {"cnh", HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
- {"cnk", HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
- {"cnl", HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
- {"cnp", HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
- {"cnr", HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
- {"cnt", HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
- {"cnu", HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
- {"cnw", HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
- {"co", HB_TAG('C','O','S',' ')}, /* Corsican */
- {"coa", HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
- {"cob", HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
-/*{"cop", HB_TAG('C','O','P',' ')},*/ /* Coptic */
- {"coq", HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
- {"cpa", HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
- {"cpe", HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
- {"cpf", HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
- {"cpi", HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
-/*{"cpp", HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
- {"cpx", HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
- {"cqd", HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
- {"cqu", HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
- {"cqu", HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
- {"cr", HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
- {"crh", HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
- {"cri", HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
- {"crj", HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
- {"crj", HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
- {"crj", HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
- {"crk", HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
- {"crk", HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
- {"crk", HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
- {"crl", HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
- {"crl", HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
- {"crl", HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
- {"crm", HB_TAG('M','C','R',' ')}, /* Moose Cree */
- {"crm", HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
- {"crm", HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
- {"crp", HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
- {"crr", HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
- {"crs", HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
- {"crt", HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
- {"crx", HB_TAG('C','R','R',' ')}, /* Carrier */
- {"crx", HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
- {"cs", HB_TAG('C','S','Y',' ')}, /* Czech */
- {"csa", HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
-/*{"csb", HB_TAG('C','S','B',' ')},*/ /* Kashubian */
- {"csh", HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
- {"csj", HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
- {"csl", HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
- {"cso", HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
- {"csp", HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
- {"csv", HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
- {"csw", HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
- {"csw", HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
- {"csw", HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
- {"csy", HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
- {"ctc", HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
- {"ctd", HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
- {"cte", HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
-/*{"ctg", HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
- {"cth", HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
- {"ctl", HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
- {"cts", HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
-/*{"ctt", HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
- {"ctu", HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
- {"cu", HB_TAG('C','S','L',' ')}, /* Church Slavonic */
- {"cuc", HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
-/*{"cuk", HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
- {"cv", HB_TAG('C','H','U',' ')}, /* Chuvash */
- {"cvn", HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
- {"cwd", HB_TAG('D','C','R',' ')}, /* Woods Cree */
- {"cwd", HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
- {"cwd", HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
- {"cy", HB_TAG('W','E','L',' ')}, /* Welsh */
- {"czh", HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
- {"czo", HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
- {"czt", HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
- {"da", HB_TAG('D','A','N',' ')}, /* Danish */
-/*{"dag", HB_TAG('D','A','G',' ')},*/ /* Dagbani */
- {"dao", HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
- {"dap", HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
-/*{"dar", HB_TAG('D','A','R',' ')},*/ /* Dargwa */
-/*{"dax", HB_TAG('D','A','X',' ')},*/ /* Dayi */
- {"dcr", HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
- {"de", HB_TAG('D','E','U',' ')}, /* German */
- {"den", HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
- {"den", HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
- {"dep", HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
- {"dgo", HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
- {"dgo", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
- {"dgr", HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
- {"dhd", HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
-/*{"dhg", HB_TAG('D','H','G',' ')},*/ /* Dhangu */
- {"dhv", HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dib", HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
- {"dik", HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
- {"din", HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
- {"dip", HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
- {"diq", HB_TAG('D','I','Q',' ')}, /* Dimli */
- {"diq", HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
- {"diw", HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
- {"dje", HB_TAG('D','J','R',' ')}, /* Zarma */
- {"djk", HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
- {"djr", HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
- {"dks", HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
- {"dng", HB_TAG('D','U','N',' ')}, /* Dungan */
-/*{"dnj", HB_TAG('D','N','J',' ')},*/ /* Dan */
- {"dnk", HB_TAG_NONE }, /* Dengka != Dinka */
- {"doi", HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
- {"drh", HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
- {"dri", HB_TAG_NONE }, /* C'Lela != Dari */
- {"drw", HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
- {"drw", HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
- {"dsb", HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
- {"dty", HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
-/*{"duj", HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
- {"dun", HB_TAG_NONE }, /* Dusun Deyah != Dungan */
- {"dup", HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
- {"dv", HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
- {"dv", HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
- {"dwk", HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
- {"dwu", HB_TAG('D','U','J',' ')}, /* Dhuwal */
- {"dwy", HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
- {"dyu", HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
- {"dz", HB_TAG('D','Z','N',' ')}, /* Dzongkha */
- {"dzn", HB_TAG_NONE }, /* Dzando != Dzongkha */
- {"ecr", HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
- {"ee", HB_TAG('E','W','E',' ')}, /* Ewe */
-/*{"efi", HB_TAG('E','F','I',' ')},*/ /* Efik */
- {"ekk", HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
- {"eky", HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
- {"el", HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
- {"emk", HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
- {"emk", HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
- {"emy", HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
- {"en", HB_TAG('E','N','G',' ')}, /* English */
- {"enb", HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
- {"enf", HB_TAG('F','N','E',' ')}, /* Forest Enets */
- {"enh", HB_TAG('T','N','E',' ')}, /* Tundra Enets */
- {"eo", HB_TAG('N','T','O',' ')}, /* Esperanto */
- {"es", HB_TAG('E','S','P',' ')}, /* Spanish */
- {"esg", HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
- {"esi", HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
- {"esk", HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
-/*{"esu", HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
- {"et", HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
- {"eto", HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
- {"eu", HB_TAG('E','U','Q',' ')}, /* Basque */
- {"euq", HB_TAG_NONE }, /* Basque [collection] != Basque */
- {"eve", HB_TAG('E','V','N',' ')}, /* Even */
- {"evn", HB_TAG('E','V','K',' ')}, /* Evenki */
- {"ewo", HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
- {"eyo", HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
- {"fa", HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
- {"fab", HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
- {"fan", HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
- {"fan", HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
- {"far", HB_TAG_NONE }, /* Fataleka != Persian */
- {"fat", HB_TAG('F','A','T',' ')}, /* Fanti */
- {"fat", HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
- {"fbl", HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
- {"ff", HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
- {"ffm", HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
- {"fi", HB_TAG('F','I','N',' ')}, /* Finnish */
- {"fil", HB_TAG('P','I','L',' ')}, /* Filipino */
- {"fj", HB_TAG('F','J','I',' ')}, /* Fijian */
- {"flm", HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
- {"flm", HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
- {"fmp", HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
- {"fmp", HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
- {"fng", HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
- {"fo", HB_TAG('F','O','S',' ')}, /* Faroese */
-/*{"fon", HB_TAG('F','O','N',' ')},*/ /* Fon */
- {"fos", HB_TAG_NONE }, /* Siraya != Faroese */
- {"fpe", HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
- {"fr", HB_TAG('F','R','A',' ')}, /* French */
-/*{"frc", HB_TAG('F','R','C',' ')},*/ /* Cajun French */
-/*{"frp", HB_TAG('F','R','P',' ')},*/ /* Arpitan */
- {"fub", HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
- {"fuc", HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
- {"fue", HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
- {"fuf", HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
- {"fuf", HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
- {"fuh", HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
- {"fui", HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
- {"fuq", HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
- {"fur", HB_TAG('F','R','L',' ')}, /* Friulian */
- {"fuv", HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
- {"fuv", HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
- {"fy", HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
- {"ga", HB_TAG('I','R','I',' ')}, /* Irish */
- {"gaa", HB_TAG('G','A','D',' ')}, /* Ga */
- {"gac", HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
- {"gad", HB_TAG_NONE }, /* Gaddang != Ga */
- {"gae", HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
-/*{"gag", HB_TAG('G','A','G',' ')},*/ /* Gagauz */
- {"gal", HB_TAG_NONE }, /* Galolen != Galician */
- {"gan", HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
- {"gar", HB_TAG_NONE }, /* Galeya != Garshuni */
- {"gaw", HB_TAG_NONE }, /* Nobonob != Garhwali */
- {"gax", HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
- {"gaz", HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
- {"gbm", HB_TAG('G','A','W',' ')}, /* Garhwali */
- {"gce", HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
- {"gcf", HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
- {"gcl", HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
- {"gcr", HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
- {"gd", HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
- {"gda", HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
-/*{"gez", HB_TAG('G','E','Z',' ')},*/ /* Geez */
- {"ggo", HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
- {"gha", HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
- {"ghk", HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
- {"gho", HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
- {"gib", HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
-/*{"gih", HB_TAG('G','I','H',' ')},*/ /* Githabul */
- {"gil", HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
- {"gju", HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
- {"gkp", HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
- {"gkp", HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
- {"gl", HB_TAG('G','A','L',' ')}, /* Galician */
- {"gld", HB_TAG('N','A','N',' ')}, /* Nanai */
-/*{"glk", HB_TAG('G','L','K',' ')},*/ /* Gilaki */
- {"gmz", HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
- {"gn", HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
- {"gnb", HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
-/*{"gnn", HB_TAG('G','N','N',' ')},*/ /* Gumatj */
- {"gno", HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
- {"gnw", HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
-/*{"gog", HB_TAG('G','O','G',' ')},*/ /* Gogo */
- {"gom", HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
-/*{"gon", HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
- {"goq", HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
- {"gox", HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
- {"gpe", HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
- {"gro", HB_TAG_NONE }, /* Groma != Garo */
- {"grr", HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
- {"grt", HB_TAG('G','R','O',' ')}, /* Garo */
- {"gru", HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
- {"gsw", HB_TAG('A','L','S',' ')}, /* Alsatian */
- {"gu", HB_TAG('G','U','J',' ')}, /* Gujarati */
- {"gua", HB_TAG_NONE }, /* Shiki != Guarani */
-/*{"guc", HB_TAG('G','U','C',' ')},*/ /* Wayuu */
-/*{"guf", HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
- {"gug", HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
- {"gui", HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
- {"guk", HB_TAG('G','M','Z',' ')}, /* Gumuz */
- {"gul", HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
- {"gun", HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
-/*{"guz", HB_TAG('G','U','Z',' ')},*/ /* Gusii */
- {"gv", HB_TAG('M','N','X',' ')}, /* Manx */
- {"gwi", HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
- {"gyn", HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
- {"ha", HB_TAG('H','A','U',' ')}, /* Hausa */
- {"haa", HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
- {"hae", HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
- {"hai", HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
- {"hak", HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
- {"hal", HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
- {"har", HB_TAG('H','R','I',' ')}, /* Harari */
-/*{"haw", HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
- {"hax", HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
-/*{"hay", HB_TAG('H','A','Y',' ')},*/ /* Haya */
-/*{"haz", HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
- {"hbn", HB_TAG_NONE }, /* Heiban != Hammer-Banna */
- {"hca", HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
- {"hdn", HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
- {"he", HB_TAG('I','W','R',' ')}, /* Hebrew */
- {"hea", HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
-/*{"hei", HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
- {"hi", HB_TAG('H','I','N',' ')}, /* Hindi */
-/*{"hil", HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
- {"hji", HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
- {"hlt", HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
- {"hma", HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
- {"hmc", HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
- {"hmd", HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
- {"hmd", HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
- {"hme", HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
- {"hmg", HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
- {"hmh", HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
- {"hmi", HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
- {"hmj", HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
- {"hml", HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
- {"hmm", HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
-/*{"hmn", HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
- {"hmp", HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
- {"hmq", HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
- {"hmr", HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
- {"hms", HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
- {"hmw", HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
- {"hmy", HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
- {"hmz", HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
- {"hmz", HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
-/*{"hnd", HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
- {"hne", HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
- {"hnj", HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
- {"hno", HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
- {"ho", HB_TAG('H','M','O',' ')}, /* Hiri Motu */
- {"ho", HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
- {"hoc", HB_TAG('H','O',' ',' ')}, /* Ho */
- {"hoi", HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
- {"hoj", HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
- {"hoj", HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
- {"hr", HB_TAG('H','R','V',' ')}, /* Croatian */
- {"hra", HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
- {"hrm", HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
- {"hsb", HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
- {"hsn", HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
- {"ht", HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
- {"ht", HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
- {"hu", HB_TAG('H','U','N',' ')}, /* Hungarian */
- {"huj", HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
- {"hup", HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
- {"hus", HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
- {"hwc", HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
- {"hy", HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
- {"hy", HB_TAG('H','Y','E',' ')}, /* Armenian */
- {"hyw", HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
- {"hz", HB_TAG('H','E','R',' ')}, /* Herero */
- {"ia", HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
-/*{"iba", HB_TAG('I','B','A',' ')},*/ /* Iban */
-/*{"ibb", HB_TAG('I','B','B',' ')},*/ /* Ibibio */
- {"iby", HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
- {"icr", HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
- {"id", HB_TAG('I','N','D',' ')}, /* Indonesian */
- {"id", HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
- {"ida", HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
- {"idb", HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
- {"ie", HB_TAG('I','L','E',' ')}, /* Interlingue */
- {"ig", HB_TAG('I','B','O',' ')}, /* Igbo */
- {"igb", HB_TAG('E','B','I',' ')}, /* Ebira */
- {"ihb", HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
- {"ii", HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
- {"ijc", HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
- {"ije", HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
- {"ijn", HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
-/*{"ijo", HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
- {"ijs", HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
- {"ik", HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
- {"ike", HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
- {"ike", HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
- {"ikt", HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
-/*{"ilo", HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
- {"in", HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
- {"in", HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
- {"ing", HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
- {"inh", HB_TAG('I','N','G',' ')}, /* Ingush */
- {"io", HB_TAG('I','D','O',' ')}, /* Ido */
- {"iri", HB_TAG_NONE }, /* Rigwe != Irish */
-/*{"iru", HB_TAG('I','R','U',' ')},*/ /* Irula */
- {"is", HB_TAG('I','S','L',' ')}, /* Icelandic */
- {"ism", HB_TAG_NONE }, /* Masimasi != Inari Sami */
- {"it", HB_TAG('I','T','A',' ')}, /* Italian */
- {"itz", HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
- {"iu", HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
- {"iu", HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
- {"iw", HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
- {"ixl", HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
- {"ja", HB_TAG('J','A','N',' ')}, /* Japanese */
- {"jac", HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
- {"jak", HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
- {"jam", HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
- {"jam", HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
- {"jan", HB_TAG_NONE }, /* Jandai != Japanese */
- {"jax", HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
- {"jbe", HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
- {"jbn", HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
-/*{"jbo", HB_TAG('J','B','O',' ')},*/ /* Lojban */
-/*{"jct", HB_TAG('J','C','T',' ')},*/ /* Krymchak */
- {"jgo", HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
- {"ji", HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
- {"jii", HB_TAG_NONE }, /* Jiiddu != Yiddish */
- {"jkm", HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
- {"jkp", HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
- {"jud", HB_TAG_NONE }, /* Worodougou != Ladino */
- {"jul", HB_TAG_NONE }, /* Jirel != Jula */
- {"jv", HB_TAG('J','A','V',' ')}, /* Javanese */
- {"jvd", HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
- {"jw", HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
- {"ka", HB_TAG('K','A','T',' ')}, /* Georgian */
- {"kaa", HB_TAG('K','R','K',' ')}, /* Karakalpak */
- {"kab", HB_TAG('K','A','B','0')}, /* Kabyle */
- {"kab", HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
- {"kac", HB_TAG_NONE }, /* Kachin != Kachchi */
- {"kam", HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
- {"kar", HB_TAG('K','R','N',' ')}, /* Karen [collection] */
-/*{"kaw", HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
- {"kbd", HB_TAG('K','A','B',' ')}, /* Kabardian */
- {"kby", HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
- {"kca", HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
- {"kca", HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
- {"kca", HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
- {"kcn", HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
-/*{"kde", HB_TAG('K','D','E',' ')},*/ /* Makonde */
- {"kdr", HB_TAG('K','R','M',' ')}, /* Karaim */
- {"kdt", HB_TAG('K','U','Y',' ')}, /* Kuy */
- {"kea", HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
- {"kea", HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
- {"keb", HB_TAG_NONE }, /* Kélé != Kebena */
- {"kek", HB_TAG('K','E','K',' ')}, /* Kekchi */
- {"kek", HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
- {"kex", HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
- {"kfa", HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
- {"kfr", HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
- {"kfx", HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
- {"kfy", HB_TAG('K','M','N',' ')}, /* Kumaoni */
- {"kg", HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
- {"kge", HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
- {"kha", HB_TAG('K','S','I',' ')}, /* Khasi */
- {"khb", HB_TAG('X','B','D',' ')}, /* Lü */
- {"khk", HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
- {"khn", HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
- {"khs", HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
- {"kht", HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
- {"kht", HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
- {"khv", HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
-/*{"khw", HB_TAG('K','H','W',' ')},*/ /* Khowar */
- {"ki", HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
- {"kis", HB_TAG_NONE }, /* Kis != Kisii */
- {"kiu", HB_TAG('K','I','U',' ')}, /* Kirmanjki */
- {"kiu", HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
- {"kj", HB_TAG('K','U','A',' ')}, /* Kuanyama */
- {"kjb", HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
-/*{"kjd", HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
- {"kjh", HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
- {"kjp", HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
- {"kjp", HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
- {"kjt", HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
-/*{"kjz", HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
- {"kk", HB_TAG('K','A','Z',' ')}, /* Kazakh */
- {"kkn", HB_TAG_NONE }, /* Kon Keu != Kokni */
- {"kkz", HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
- {"kl", HB_TAG('G','R','N',' ')}, /* Greenlandic */
- {"klm", HB_TAG_NONE }, /* Migum != Kalmyk */
- {"kln", HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
- {"km", HB_TAG('K','H','M',' ')}, /* Khmer */
- {"kmb", HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
- {"kmn", HB_TAG_NONE }, /* Awtuw != Kumaoni */
- {"kmo", HB_TAG_NONE }, /* Kwoma != Komo */
- {"kmr", HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
- {"kms", HB_TAG_NONE }, /* Kamasau != Komso */
- {"kmv", HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
- {"kmw", HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
-/*{"kmz", HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
- {"kn", HB_TAG('K','A','N',' ')}, /* Kannada */
- {"knc", HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
- {"kng", HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
- {"knj", HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
- {"knn", HB_TAG('K','O','K',' ')}, /* Konkani */
- {"knr", HB_TAG_NONE }, /* Kaningra != Kanuri */
- {"ko", HB_TAG('K','O','R',' ')}, /* Korean */
- {"ko", HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
- {"kod", HB_TAG_NONE }, /* Kodi != Kodagu */
- {"koh", HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
- {"koi", HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
- {"koi", HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
-/*{"kok", HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
- {"kop", HB_TAG_NONE }, /* Waube != Komi-Permyak */
-/*{"kos", HB_TAG('K','O','S',' ')},*/ /* Kosraean */
- {"koy", HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
- {"koz", HB_TAG_NONE }, /* Korak != Komi-Zyrian */
- {"kpe", HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
- {"kpl", HB_TAG_NONE }, /* Kpala != Kpelle */
- {"kpp", HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
- {"kpv", HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
- {"kpv", HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
- {"kpy", HB_TAG('K','Y','K',' ')}, /* Koryak */
- {"kqs", HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
- {"kqy", HB_TAG('K','R','T',' ')}, /* Koorete */
- {"kr", HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
- {"krc", HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
- {"krc", HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
- {"kri", HB_TAG('K','R','I',' ')}, /* Krio */
- {"kri", HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
- {"krk", HB_TAG_NONE }, /* Kerek != Karakalpak */
-/*{"krl", HB_TAG('K','R','L',' ')},*/ /* Karelian */
- {"krm", HB_TAG_NONE }, /* Krim (retired code) != Karaim */
- {"krn", HB_TAG_NONE }, /* Sapo != Karen */
- {"krt", HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
- {"kru", HB_TAG('K','U','U',' ')}, /* Kurukh */
- {"ks", HB_TAG('K','S','H',' ')}, /* Kashmiri */
- {"ksh", HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
- {"ksi", HB_TAG_NONE }, /* Krisa != Khasi */
- {"ksm", HB_TAG_NONE }, /* Kumba != Kildin Sami */
- {"kss", HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
- {"ksw", HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
- {"ksw", HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
- {"ktb", HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
- {"ktu", HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
- {"ktw", HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
- {"ku", HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
- {"kui", HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
- {"kul", HB_TAG_NONE }, /* Kulere != Kulvi */
-/*{"kum", HB_TAG('K','U','M',' ')},*/ /* Kumyk */
- {"kuu", HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
- {"kuw", HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
- {"kuy", HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
- {"kv", HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
- {"kvb", HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
- {"kvl", HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
- {"kvq", HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
- {"kvr", HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
- {"kvt", HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
- {"kvu", HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
- {"kvy", HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
- {"kw", HB_TAG('C','O','R',' ')}, /* Cornish */
-/*{"kwk", HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
- {"kww", HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
- {"kwy", HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
- {"kxc", HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
- {"kxd", HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
- {"kxf", HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
- {"kxk", HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
- {"kxl", HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
- {"kxu", HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
- {"ky", HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
- {"kyk", HB_TAG_NONE }, /* Kamayo != Koryak */
- {"kyu", HB_TAG('K','Y','U',' ')}, /* Western Kayah */
- {"kyu", HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
- {"la", HB_TAG('L','A','T',' ')}, /* Latin */
- {"lac", HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
- {"lad", HB_TAG('J','U','D',' ')}, /* Ladino */
- {"lah", HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
- {"lak", HB_TAG_NONE }, /* Laka (Nigeria) != Lak */
- {"lam", HB_TAG_NONE }, /* Lamba != Lambani */
- {"laz", HB_TAG_NONE }, /* Aribwatsa != Laz */
- {"lb", HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
- {"lbe", HB_TAG('L','A','K',' ')}, /* Lak */
- {"lbj", HB_TAG('L','D','K',' ')}, /* Ladakhi */
- {"lbl", HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
- {"lce", HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
- {"lcf", HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
- {"ldi", HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
- {"ldk", HB_TAG_NONE }, /* Leelau != Ladakhi */
-/*{"lef", HB_TAG('L','E','F',' ')},*/ /* Lelemi */
-/*{"lez", HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
- {"lg", HB_TAG('L','U','G',' ')}, /* Ganda */
- {"li", HB_TAG('L','I','M',' ')}, /* Limburgish */
- {"lif", HB_TAG('L','M','B',' ')}, /* Limbu */
-/*{"lij", HB_TAG('L','I','J',' ')},*/ /* Ligurian */
- {"lir", HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
-/*{"lis", HB_TAG('L','I','S',' ')},*/ /* Lisu */
- {"liw", HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
- {"liy", HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
-/*{"ljp", HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
- {"lkb", HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
-/*{"lki", HB_TAG('L','K','I',' ')},*/ /* Laki */
- {"lko", HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
- {"lks", HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
- {"lld", HB_TAG('L','A','D',' ')}, /* Ladin */
- {"lma", HB_TAG_NONE }, /* East Limba != Low Mari */
- {"lmb", HB_TAG_NONE }, /* Merei != Limbu */
- {"lmn", HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
-/*{"lmo", HB_TAG('L','M','O',' ')},*/ /* Lombard */
- {"lmw", HB_TAG_NONE }, /* Lake Miwok != Lomwe */
- {"ln", HB_TAG('L','I','N',' ')}, /* Lingala */
- {"lna", HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
- {"lnl", HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
- {"lo", HB_TAG('L','A','O',' ')}, /* Lao */
-/*{"lom", HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
- {"lou", HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
-/*{"lpo", HB_TAG('L','P','O',' ')},*/ /* Lipo */
-/*{"lrc", HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
- {"lri", HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
- {"lrm", HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
- {"lrt", HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
- {"lsb", HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
- {"lsm", HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
- {"lt", HB_TAG('L','T','H',' ')}, /* Lithuanian */
- {"ltg", HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
- {"lth", HB_TAG_NONE }, /* Thur != Lithuanian */
- {"lto", HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
- {"lts", HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
- {"lu", HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
-/*{"lua", HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
-/*{"luo", HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
- {"lus", HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
- {"lus", HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
- {"luy", HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
- {"luz", HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
- {"lv", HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
- {"lvi", HB_TAG_NONE }, /* Lavi != Latvian */
- {"lvs", HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
- {"lwg", HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
- {"lzh", HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
- {"lzz", HB_TAG('L','A','Z',' ')}, /* Laz */
-/*{"mad", HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
-/*{"mag", HB_TAG('M','A','G',' ')},*/ /* Magahi */
- {"mai", HB_TAG('M','T','H',' ')}, /* Maithili */
- {"maj", HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
- {"mak", HB_TAG('M','K','R',' ')}, /* Makasar */
- {"mam", HB_TAG('M','A','M',' ')}, /* Mam */
- {"mam", HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
- {"man", HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
- {"map", HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
- {"maw", HB_TAG_NONE }, /* Mampruli != Marwari */
- {"max", HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
- {"max", HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
- {"mbf", HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
- {"mbn", HB_TAG_NONE }, /* Macaguán != Mbundu */
-/*{"mbo", HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
- {"mch", HB_TAG_NONE }, /* Maquiritari != Manchu */
- {"mcm", HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
- {"mcr", HB_TAG_NONE }, /* Menya != Moose Cree */
- {"mct", HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
- {"mde", HB_TAG_NONE }, /* Maba (Chad) != Mende */
- {"mdf", HB_TAG('M','O','K',' ')}, /* Moksha */
-/*{"mdr", HB_TAG('M','D','R',' ')},*/ /* Mandar */
- {"mdy", HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */
- {"men", HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */
- {"meo", HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
-/*{"mer", HB_TAG('M','E','R',' ')},*/ /* Meru */
- {"mfa", HB_TAG('M','F','A',' ')}, /* Pattani Malay */
- {"mfa", HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
- {"mfb", HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
- {"mfe", HB_TAG('M','F','E',' ')}, /* Morisyen */
- {"mfe", HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
- {"mfp", HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
- {"mg", HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
- {"mh", HB_TAG('M','A','H',' ')}, /* Marshallese */
- {"mhc", HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
- {"mhr", HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
- {"mhv", HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
- {"mi", HB_TAG('M','R','I',' ')}, /* Maori */
- {"min", HB_TAG('M','I','N',' ')}, /* Minangkabau */
- {"min", HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
- {"miz", HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
- {"mk", HB_TAG('M','K','D',' ')}, /* Macedonian */
- {"mkn", HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
- {"mkr", HB_TAG_NONE }, /* Malas != Makasar */
- {"mku", HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
-/*{"mkw", HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
- {"ml", HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
- {"ml", HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
- {"mle", HB_TAG_NONE }, /* Manambu != Male */
- {"mln", HB_TAG_NONE }, /* Malango != Malinke */
- {"mlq", HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
- {"mlq", HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
- {"mlr", HB_TAG_NONE }, /* Vame != Malayalam Reformed */
- {"mmr", HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
- {"mn", HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
- {"mnc", HB_TAG('M','C','H',' ')}, /* Manchu */
- {"mnd", HB_TAG_NONE }, /* Mondé != Mandinka */
- {"mng", HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
- {"mnh", HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
-/*{"mni", HB_TAG('M','N','I',' ')},*/ /* Manipuri */
- {"mnk", HB_TAG('M','N','D',' ')}, /* Mandinka */
- {"mnk", HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
- {"mnp", HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
- {"mns", HB_TAG('M','A','N',' ')}, /* Mansi */
- {"mnw", HB_TAG('M','O','N',' ')}, /* Mon */
- {"mnw", HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
- {"mnx", HB_TAG_NONE }, /* Manikion != Manx */
- {"mo", HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
- {"mo", HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
- {"mod", HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
-/*{"moh", HB_TAG('M','O','H',' ')},*/ /* Mohawk */
- {"mok", HB_TAG_NONE }, /* Morori != Moksha */
- {"mop", HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
- {"mor", HB_TAG_NONE }, /* Moro != Moroccan */
-/*{"mos", HB_TAG('M','O','S',' ')},*/ /* Mossi */
- {"mpe", HB_TAG('M','A','J',' ')}, /* Majang */
- {"mqg", HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
- {"mr", HB_TAG('M','A','R',' ')}, /* Marathi */
- {"mrh", HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
- {"mrj", HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
- {"ms", HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
- {"msc", HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
- {"msh", HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
- {"msi", HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
- {"msi", HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
- {"mt", HB_TAG('M','T','S',' ')}, /* Maltese */
- {"mth", HB_TAG_NONE }, /* Munggui != Maithili */
- {"mtr", HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
- {"mts", HB_TAG_NONE }, /* Yora != Maltese */
- {"mud", HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
- {"mui", HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
- {"mun", HB_TAG_NONE }, /* Munda [collection] != Mundari */
- {"mup", HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
- {"muq", HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
-/*{"mus", HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
- {"mvb", HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
- {"mve", HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
- {"mvf", HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
- {"mwk", HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
-/*{"mwl", HB_TAG('M','W','L',' ')},*/ /* Mirandese */
- {"mwq", HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
- {"mwr", HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
- {"mww", HB_TAG('M','W','W',' ')}, /* Hmong Daw */
- {"mww", HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
- {"my", HB_TAG('B','R','M',' ')}, /* Burmese */
- {"mym", HB_TAG('M','E','N',' ')}, /* Me’en */
-/*{"myn", HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
- {"myq", HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
- {"myv", HB_TAG('E','R','Z',' ')}, /* Erzya */
- {"mzb", HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
-/*{"mzn", HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
- {"mzs", HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
- {"na", HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
- {"nag", HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
- {"nag", HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
-/*{"nah", HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
- {"nan", HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
-/*{"nap", HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
- {"nas", HB_TAG_NONE }, /* Naasioi != Naskapi */
- {"naz", HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
- {"nb", HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
- {"nch", HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
- {"nci", HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
- {"ncj", HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
- {"ncl", HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
- {"ncr", HB_TAG_NONE }, /* Ncane != N-Cree */
- {"ncx", HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
- {"nd", HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
- {"ndb", HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
-/*{"ndc", HB_TAG('N','D','C',' ')},*/ /* Ndau */
- {"ndg", HB_TAG_NONE }, /* Ndengereko != Ndonga */
-/*{"nds", HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
- {"ne", HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
- {"nef", HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
-/*{"new", HB_TAG('N','E','W',' ')},*/ /* Newari */
- {"ng", HB_TAG('N','D','G',' ')}, /* Ndonga */
-/*{"nga", HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
- {"ngl", HB_TAG('L','M','W',' ')}, /* Lomwe */
- {"ngm", HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
- {"ngo", HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
- {"ngr", HB_TAG_NONE }, /* Engdewu != Nagari */
- {"ngu", HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
- {"nhc", HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
- {"nhd", HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
- {"nhe", HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
- {"nhg", HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
- {"nhi", HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
- {"nhk", HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
- {"nhm", HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
- {"nhn", HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
- {"nhp", HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
- {"nhq", HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
- {"nht", HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
- {"nhv", HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
- {"nhw", HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
- {"nhx", HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
- {"nhy", HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
- {"nhz", HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
- {"niq", HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
- {"nis", HB_TAG_NONE }, /* Nimi != Nisi */
-/*{"niu", HB_TAG('N','I','U',' ')},*/ /* Niuean */
- {"niv", HB_TAG('G','I','L',' ')}, /* Gilyak */
- {"njt", HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
- {"njz", HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
- {"nko", HB_TAG_NONE }, /* Nkonya != N’Ko */
- {"nkx", HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
- {"nl", HB_TAG('N','L','D',' ')}, /* Dutch */
- {"nla", HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
- {"nle", HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
- {"nln", HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
- {"nlv", HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
- {"nn", HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
- {"nnh", HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
- {"nnz", HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
- {"no", HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
- {"nod", HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
-/*{"noe", HB_TAG('N','O','E',' ')},*/ /* Nimadi */
-/*{"nog", HB_TAG('N','O','G',' ')},*/ /* Nogai */
-/*{"nov", HB_TAG('N','O','V',' ')},*/ /* Novial */
- {"npi", HB_TAG('N','E','P',' ')}, /* Nepali */
- {"npl", HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
- {"nqo", HB_TAG('N','K','O',' ')}, /* N’Ko */
- {"nr", HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
- {"nsk", HB_TAG('N','A','S',' ')}, /* Naskapi */
- {"nsm", HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
-/*{"nso", HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
- {"nsu", HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
- {"nto", HB_TAG_NONE }, /* Ntomba != Esperanto */
- {"nue", HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
- {"nuu", HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
- {"nuz", HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
- {"nv", HB_TAG('N','A','V',' ')}, /* Navajo */
- {"nv", HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
- {"nwe", HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
- {"ny", HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
- {"nyd", HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
-/*{"nym", HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
- {"nyn", HB_TAG('N','K','L',' ')}, /* Nyankole */
-/*{"nza", HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
- {"oc", HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
- {"oj", HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
-/*{"ojb", HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
- {"ojc", HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
- {"ojg", HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
- {"ojs", HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
- {"ojs", HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
- {"ojw", HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
- {"okd", HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
- {"oki", HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
- {"okm", HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
- {"okr", HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
- {"om", HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
- {"onx", HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
- {"oor", HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
- {"or", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
- {"orc", HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
- {"orn", HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
- {"oro", HB_TAG_NONE }, /* Orokolo != Oromo */
- {"orr", HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
- {"ors", HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
- {"ory", HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
- {"os", HB_TAG('O','S','S',' ')}, /* Ossetian */
- {"otw", HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
- {"oua", HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
- {"pa", HB_TAG('P','A','N',' ')}, /* Punjabi */
- {"paa", HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
-/*{"pag", HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
- {"pal", HB_TAG_NONE }, /* Pahlavi != Pali */
-/*{"pam", HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
- {"pap", HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
- {"pap", HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
- {"pas", HB_TAG_NONE }, /* Papasena != Pashto */
-/*{"pau", HB_TAG('P','A','U',' ')},*/ /* Palauan */
- {"pbt", HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
- {"pbu", HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
-/*{"pcc", HB_TAG('P','C','C',' ')},*/ /* Bouyei */
-/*{"pcd", HB_TAG('P','C','D',' ')},*/ /* Picard */
- {"pce", HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
- {"pck", HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
- {"pcm", HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
-/*{"pdc", HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
- {"pdu", HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
- {"pea", HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
- {"pel", HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
- {"pes", HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
- {"pey", HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
- {"pga", HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
- {"pga", HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
-/*{"phk", HB_TAG('P','H','K',' ')},*/ /* Phake */
- {"pi", HB_TAG('P','A','L',' ')}, /* Pali */
- {"pih", HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
- {"pih", HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
- {"pil", HB_TAG_NONE }, /* Yom != Filipino */
- {"pis", HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
- {"pkh", HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
- {"pko", HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
- {"pl", HB_TAG('P','L','K',' ')}, /* Polish */
- {"plg", HB_TAG_NONE }, /* Pilagá != Palaung */
- {"plk", HB_TAG_NONE }, /* Kohistani Shina != Polish */
- {"pll", HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
- {"pln", HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
- {"plp", HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
- {"plt", HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
- {"pml", HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
-/*{"pms", HB_TAG('P','M','S',' ')},*/ /* Piemontese */
- {"pmy", HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
-/*{"pnb", HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
- {"poc", HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
- {"poh", HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
- {"poh", HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
-/*{"pon", HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
- {"pov", HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
- {"ppa", HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
- {"pre", HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
-/*{"pro", HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
- {"prs", HB_TAG('D','R','I',' ')}, /* Dari */
- {"prs", HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
- {"ps", HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
- {"pse", HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
- {"pst", HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
- {"pt", HB_TAG('P','T','G',' ')}, /* Portuguese */
- {"pub", HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
- {"puz", HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
- {"pwo", HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
- {"pwo", HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
- {"pww", HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
- {"qu", HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
- {"qub", HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
- {"qub", HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
- {"quc", HB_TAG('Q','U','C',' ')}, /* K’iche’ */
- {"quc", HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
- {"qud", HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
- {"qud", HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
- {"quf", HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
- {"qug", HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
- {"qug", HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
- {"quh", HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
- {"quh", HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
- {"quk", HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
- {"qul", HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
- {"qul", HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
- {"qum", HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
- {"qup", HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
- {"qup", HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
- {"qur", HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
- {"qur", HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
- {"qus", HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
- {"qus", HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
- {"quv", HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
- {"quw", HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
- {"quw", HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
- {"qux", HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
- {"qux", HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
- {"quy", HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
-/*{"quz", HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
- {"qva", HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
- {"qva", HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
- {"qvc", HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
- {"qve", HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
- {"qvh", HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
- {"qvh", HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
- {"qvi", HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
- {"qvi", HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
- {"qvj", HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
- {"qvj", HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
- {"qvl", HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
- {"qvl", HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
- {"qvm", HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
- {"qvm", HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
- {"qvn", HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
- {"qvn", HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
- {"qvo", HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
- {"qvo", HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
- {"qvp", HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
- {"qvp", HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
- {"qvs", HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
- {"qvw", HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
- {"qvw", HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
- {"qvz", HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
- {"qvz", HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
- {"qwa", HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
- {"qwa", HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
- {"qwc", HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
- {"qwh", HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
- {"qwh", HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
- {"qws", HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
- {"qws", HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
- {"qwt", HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
- {"qxa", HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
- {"qxa", HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
- {"qxc", HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
- {"qxc", HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
- {"qxh", HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
- {"qxh", HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
- {"qxl", HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
- {"qxl", HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
- {"qxn", HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxn", HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
- {"qxo", HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
- {"qxo", HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
- {"qxp", HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
- {"qxr", HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
- {"qxr", HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
- {"qxt", HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
- {"qxt", HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
- {"qxu", HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
- {"qxw", HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
- {"qxw", HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
- {"rag", HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
-/*{"raj", HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
- {"ral", HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
-/*{"rar", HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
- {"rbb", HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
- {"rbl", HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
- {"rcf", HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
-/*{"rej", HB_TAG('R','E','J',' ')},*/ /* Rejang */
-/*{"rhg", HB_TAG('R','H','G',' ')},*/ /* Rohingya */
-/*{"ria", HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
- {"rif", HB_TAG('R','I','F',' ')}, /* Tarifit */
- {"rif", HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
-/*{"rit", HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
- {"rki", HB_TAG('A','R','K',' ')}, /* Rakhine */
-/*{"rkw", HB_TAG('R','K','W',' ')},*/ /* Arakwal */
- {"rm", HB_TAG('R','M','S',' ')}, /* Romansh */
- {"rmc", HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
- {"rmf", HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
- {"rml", HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
- {"rmn", HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
- {"rmo", HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
- {"rms", HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
- {"rmw", HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
- {"rmy", HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
- {"rmy", HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
- {"rmz", HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
- {"rn", HB_TAG('R','U','N',' ')}, /* Rundi */
- {"ro", HB_TAG('R','O','M',' ')}, /* Romanian */
- {"rom", HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
- {"rop", HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
- {"rtc", HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
-/*{"rtm", HB_TAG('R','T','M',' ')},*/ /* Rotuman */
- {"ru", HB_TAG('R','U','S',' ')}, /* Russian */
- {"rue", HB_TAG('R','S','Y',' ')}, /* Rusyn */
-/*{"rup", HB_TAG('R','U','P',' ')},*/ /* Aromanian */
- {"rw", HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
- {"rwr", HB_TAG('M','A','W',' ')}, /* Marwari (India) */
- {"sa", HB_TAG('S','A','N',' ')}, /* Sanskrit */
- {"sad", HB_TAG_NONE }, /* Sandawe != Sadri */
- {"sah", HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
- {"sam", HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
-/*{"sas", HB_TAG('S','A','S',' ')},*/ /* Sasak */
-/*{"sat", HB_TAG('S','A','T',' ')},*/ /* Santali */
- {"say", HB_TAG_NONE }, /* Saya != Sayisi */
- {"sc", HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
- {"scf", HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
- {"sch", HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
- {"sci", HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
- {"sck", HB_TAG('S','A','D',' ')}, /* Sadri */
-/*{"scn", HB_TAG('S','C','N',' ')},*/ /* Sicilian */
-/*{"sco", HB_TAG('S','C','O',' ')},*/ /* Scots */
- {"scs", HB_TAG('S','C','S',' ')}, /* North Slavey */
- {"scs", HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
- {"scs", HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
- {"sd", HB_TAG('S','N','D',' ')}, /* Sindhi */
- {"sdc", HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
- {"sdh", HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
- {"sdn", HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
- {"sds", HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
- {"se", HB_TAG('N','S','M',' ')}, /* Northern Sami */
- {"seh", HB_TAG('S','N','A',' ')}, /* Sena */
- {"sek", HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
-/*{"sel", HB_TAG('S','E','L',' ')},*/ /* Selkup */
- {"sez", HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
- {"sfm", HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
- {"sfm", HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
- {"sg", HB_TAG('S','G','O',' ')}, /* Sango */
-/*{"sga", HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
- {"sgc", HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
- {"sgo", HB_TAG_NONE }, /* Songa (retired code) != Sango */
-/*{"sgs", HB_TAG('S','G','S',' ')},*/ /* Samogitian */
- {"sgw", HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
- {"sh", HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
- {"sh", HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
- {"sh", HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
- {"shi", HB_TAG('S','H','I',' ')}, /* Tachelhit */
- {"shi", HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
- {"shl", HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
-/*{"shn", HB_TAG('S','H','N',' ')},*/ /* Shan */
- {"shu", HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
- {"shy", HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
- {"si", HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
- {"sib", HB_TAG_NONE }, /* Sebop != Sibe */
-/*{"sid", HB_TAG('S','I','D',' ')},*/ /* Sidamo */
- {"sig", HB_TAG_NONE }, /* Paasaal != Silte Gurage */
- {"siz", HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
- {"sjd", HB_TAG('K','S','M',' ')}, /* Kildin Sami */
- {"sjo", HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
- {"sjs", HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
- {"sk", HB_TAG('S','K','Y',' ')}, /* Slovak */
- {"skg", HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
- {"skr", HB_TAG('S','R','K',' ')}, /* Saraiki */
- {"sks", HB_TAG_NONE }, /* Maia != Skolt Sami */
- {"skw", HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
- {"sky", HB_TAG_NONE }, /* Sikaiana != Slovak */
- {"sl", HB_TAG('S','L','V',' ')}, /* Slovenian */
- {"sla", HB_TAG_NONE }, /* Slavic [collection] != Slavey */
- {"sm", HB_TAG('S','M','O',' ')}, /* Samoan */
- {"sma", HB_TAG('S','S','M',' ')}, /* Southern Sami */
- {"smj", HB_TAG('L','S','M',' ')}, /* Lule Sami */
- {"sml", HB_TAG_NONE }, /* Central Sama != Somali */
- {"smn", HB_TAG('I','S','M',' ')}, /* Inari Sami */
- {"sms", HB_TAG('S','K','S',' ')}, /* Skolt Sami */
- {"smt", HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
- {"sn", HB_TAG('S','N','A','0')}, /* Shona */
- {"snh", HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
-/*{"snk", HB_TAG('S','N','K',' ')},*/ /* Soninke */
- {"so", HB_TAG('S','M','L',' ')}, /* Somali */
- {"sog", HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
-/*{"sop", HB_TAG('S','O','P',' ')},*/ /* Songe */
- {"spv", HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
- {"spy", HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
- {"sq", HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
- {"sr", HB_TAG('S','R','B',' ')}, /* Serbian */
- {"srb", HB_TAG_NONE }, /* Sora != Serbian */
- {"src", HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
- {"srk", HB_TAG_NONE }, /* Serudung Murut != Saraiki */
- {"srm", HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
- {"srn", HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
- {"sro", HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
-/*{"srr", HB_TAG('S','R','R',' ')},*/ /* Serer */
- {"srs", HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
- {"ss", HB_TAG('S','W','Z',' ')}, /* Swati */
- {"ssh", HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
- {"ssl", HB_TAG_NONE }, /* Western Sisaala != South Slavey */
- {"ssm", HB_TAG_NONE }, /* Semnam != Southern Sami */
- {"st", HB_TAG('S','O','T',' ')}, /* Southern Sotho */
- {"sta", HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
-/*{"stq", HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
- {"stv", HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
- {"su", HB_TAG('S','U','N',' ')}, /* Sundanese */
-/*{"suk", HB_TAG('S','U','K',' ')},*/ /* Sukuma */
- {"suq", HB_TAG('S','U','R',' ')}, /* Suri */
- {"sur", HB_TAG_NONE }, /* Mwaghavul != Suri */
- {"sv", HB_TAG('S','V','E',' ')}, /* Swedish */
-/*{"sva", HB_TAG('S','V','A',' ')},*/ /* Svan */
- {"svc", HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
- {"sve", HB_TAG_NONE }, /* Serili != Swedish */
- {"sw", HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
- {"swb", HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
- {"swc", HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
- {"swh", HB_TAG('S','W','K',' ')}, /* Swahili */
- {"swk", HB_TAG_NONE }, /* Malawi Sena != Swahili */
- {"swn", HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
- {"swv", HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
-/*{"sxu", HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
- {"syc", HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
-/*{"syl", HB_TAG('S','Y','L',' ')},*/ /* Sylheti */
-/*{"syr", HB_TAG('S','Y','R',' ')},*/ /* Syriac [macrolanguage] */
-/*{"szl", HB_TAG('S','Z','L',' ')},*/ /* Silesian */
- {"ta", HB_TAG('T','A','M',' ')}, /* Tamil */
- {"taa", HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
-/*{"tab", HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
- {"taj", HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
- {"taq", HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
- {"taq", HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
- {"tas", HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
- {"tau", HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
- {"tcb", HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
- {"tce", HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
- {"tch", HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
- {"tcp", HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
- {"tcs", HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
- {"tcy", HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
- {"tcz", HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
-/*{"tdd", HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
- {"tdx", HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
- {"te", HB_TAG('T','E','L',' ')}, /* Telugu */
- {"tec", HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
- {"tem", HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
-/*{"tet", HB_TAG('T','E','T',' ')},*/ /* Tetum */
- {"tez", HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
- {"tfn", HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
- {"tg", HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
- {"tgh", HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
- {"tgj", HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
- {"tgn", HB_TAG_NONE }, /* Tandaganon != Tongan */
- {"tgr", HB_TAG_NONE }, /* Tareng != Tigre */
- {"tgx", HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
- {"tgy", HB_TAG_NONE }, /* Togoyo != Tigrinya */
- {"th", HB_TAG('T','H','A',' ')}, /* Thai */
- {"tht", HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
- {"thv", HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
- {"thv", HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
- {"thz", HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
- {"thz", HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
- {"ti", HB_TAG('T','G','Y',' ')}, /* Tigrinya */
- {"tia", HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
- {"tig", HB_TAG('T','G','R',' ')}, /* Tigre */
-/*{"tiv", HB_TAG('T','I','V',' ')},*/ /* Tiv */
-/*{"tjl", HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
- {"tjo", HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
- {"tk", HB_TAG('T','K','M',' ')}, /* Turkmen */
- {"tkg", HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
- {"tkm", HB_TAG_NONE }, /* Takelma != Turkmen */
- {"tl", HB_TAG('T','G','L',' ')}, /* Tagalog */
-/*{"tli", HB_TAG('T','L','I',' ')},*/ /* Tlingit */
- {"tmg", HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
- {"tmh", HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
- {"tmh", HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
- {"tmn", HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
- {"tmw", HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
- {"tn", HB_TAG('T','N','A',' ')}, /* Tswana */
- {"tna", HB_TAG_NONE }, /* Tacana != Tswana */
- {"tne", HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
- {"tnf", HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
- {"tnf", HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
- {"tng", HB_TAG_NONE }, /* Tobanga != Tonga */
- {"to", HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
- {"tod", HB_TAG('T','O','D','0')}, /* Toma */
- {"toi", HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
- {"toj", HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
- {"tol", HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
- {"tor", HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
- {"tpi", HB_TAG('T','P','I',' ')}, /* Tok Pisin */
- {"tpi", HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
- {"tr", HB_TAG('T','R','K',' ')}, /* Turkish */
- {"trf", HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
- {"trk", HB_TAG_NONE }, /* Turkic [collection] != Turkish */
- {"tru", HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
- {"tru", HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
- {"ts", HB_TAG('T','S','G',' ')}, /* Tsonga */
- {"tsg", HB_TAG_NONE }, /* Tausug != Tsonga */
-/*{"tsj", HB_TAG('T','S','J',' ')},*/ /* Tshangla */
- {"tt", HB_TAG('T','A','T',' ')}, /* Tatar */
- {"ttc", HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
- {"ttm", HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
- {"ttq", HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
- {"ttq", HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
- {"tua", HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
- {"tul", HB_TAG_NONE }, /* Tula != Tumbuka */
-/*{"tum", HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
- {"tuu", HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
- {"tuv", HB_TAG_NONE }, /* Turkana != Tuvin */
- {"tuy", HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
-/*{"tvl", HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
- {"tvy", HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
- {"tw", HB_TAG('T','W','I',' ')}, /* Twi */
- {"tw", HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
- {"txc", HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
- {"txy", HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
- {"ty", HB_TAG('T','H','T',' ')}, /* Tahitian */
- {"tyv", HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
-/*{"tyz", HB_TAG('T','Y','Z',' ')},*/ /* Tày */
- {"tzh", HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
- {"tzj", HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
- {"tzm", HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
- {"tzm", HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
- {"tzo", HB_TAG('T','Z','O',' ')}, /* Tzotzil */
- {"tzo", HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
- {"ubl", HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
-/*{"udm", HB_TAG('U','D','M',' ')},*/ /* Udmurt */
- {"ug", HB_TAG('U','Y','G',' ')}, /* Uyghur */
- {"uk", HB_TAG('U','K','R',' ')}, /* Ukrainian */
- {"uki", HB_TAG('K','U','I',' ')}, /* Kui (India) */
- {"uln", HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
-/*{"umb", HB_TAG('U','M','B',' ')},*/ /* Umbundu */
- {"unr", HB_TAG('M','U','N',' ')}, /* Mundari */
- {"ur", HB_TAG('U','R','D',' ')}, /* Urdu */
- {"urk", HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
- {"usp", HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
- {"uz", HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
- {"uzn", HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
- {"uzs", HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
- {"vap", HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
- {"ve", HB_TAG('V','E','N',' ')}, /* Venda */
-/*{"vec", HB_TAG('V','E','C',' ')},*/ /* Venetian */
- {"vi", HB_TAG('V','I','T',' ')}, /* Vietnamese */
- {"vic", HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
- {"vit", HB_TAG_NONE }, /* Viti != Vietnamese */
- {"vkk", HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
- {"vkp", HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
- {"vkt", HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
- {"vls", HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
- {"vmw", HB_TAG('M','A','K',' ')}, /* Makhuwa */
- {"vo", HB_TAG('V','O','L',' ')}, /* Volapük */
-/*{"vro", HB_TAG('V','R','O',' ')},*/ /* Võro */
- {"wa", HB_TAG('W','L','N',' ')}, /* Walloon */
- {"wag", HB_TAG_NONE }, /* Wa'ema != Wagdi */
-/*{"war", HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
- {"wbm", HB_TAG('W','A',' ',' ')}, /* Wa */
- {"wbr", HB_TAG('W','A','G',' ')}, /* Wagdi */
- {"wbr", HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
-/*{"wci", HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
- {"wea", HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
- {"wes", HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
- {"weu", HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
- {"wlc", HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
- {"wle", HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
- {"wlk", HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
- {"wni", HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
- {"wo", HB_TAG('W','L','F',' ')}, /* Wolof */
- {"wry", HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
- {"wsg", HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
-/*{"wtm", HB_TAG('W','T','M',' ')},*/ /* Mewati */
- {"wuu", HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
- {"xal", HB_TAG('K','L','M',' ')}, /* Kalmyk */
- {"xal", HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
- {"xan", HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
- {"xbd", HB_TAG_NONE }, /* Bindal != Lü */
- {"xh", HB_TAG('X','H','S',' ')}, /* Xhosa */
-/*{"xjb", HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
-/*{"xkf", HB_TAG('X','K','F',' ')},*/ /* Khengkha */
- {"xmg", HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
- {"xmm", HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
- {"xmm", HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
- {"xmv", HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
- {"xmw", HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
- {"xnj", HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
- {"xnq", HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
- {"xnr", HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
-/*{"xog", HB_TAG('X','O','G',' ')},*/ /* Soga */
- {"xpe", HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
- {"xpe", HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
- {"xsl", HB_TAG('S','S','L',' ')}, /* South Slavey */
- {"xsl", HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
- {"xsl", HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
- {"xst", HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
-/*{"xub", HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
-/*{"xuj", HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
- {"xup", HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
- {"xwo", HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
- {"yaj", HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
- {"yak", HB_TAG_NONE }, /* Yakama != Sakha */
-/*{"yao", HB_TAG('Y','A','O',' ')},*/ /* Yao */
-/*{"yap", HB_TAG('Y','A','P',' ')},*/ /* Yapese */
- {"yba", HB_TAG_NONE }, /* Yala != Yoruba */
- {"ybb", HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
- {"ybd", HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
- {"ydd", HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
-/*{"ygp", HB_TAG('Y','G','P',' ')},*/ /* Gepo */
- {"yi", HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
- {"yih", HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
- {"yim", HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
-/*{"yna", HB_TAG('Y','N','A',' ')},*/ /* Aluo */
- {"yo", HB_TAG('Y','B','A',' ')}, /* Yoruba */
- {"yos", HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
- {"yua", HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
- {"yue", HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
-/*{"ywq", HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
- {"za", HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
- {"zch", HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
- {"zdj", HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
-/*{"zea", HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
- {"zeh", HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
- {"zen", HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
- {"zgb", HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
- {"zgh", HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
- {"zgh", HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
- {"zgm", HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
- {"zgn", HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
- {"zh", HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
- {"zhd", HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
- {"zhn", HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
- {"zlj", HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
- {"zlm", HB_TAG('M','L','Y',' ')}, /* Malay */
- {"zln", HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
- {"zlq", HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
- {"zmi", HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
- {"zmz", HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
- {"znd", HB_TAG_NONE }, /* Zande [collection] != Zande */
- {"zne", HB_TAG('Z','N','D',' ')}, /* Zande */
- {"zom", HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
- {"zqe", HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
- {"zsm", HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
- {"zu", HB_TAG('Z','U','L',' ')}, /* Zulu */
- {"zum", HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
- {"zyb", HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
- {"zyg", HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
- {"zyj", HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
- {"zyn", HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
- {"zyp", HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
-/*{"zza", HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
- {"zzj", HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
+static const LangTag ot_languages2[] = {
+ {HB_TAG('a','a',' ',' '), HB_TAG('A','F','R',' ')}, /* Afar */
+ {HB_TAG('a','b',' ',' '), HB_TAG('A','B','K',' ')}, /* Abkhazian */
+ {HB_TAG('a','f',' ',' '), HB_TAG('A','F','K',' ')}, /* Afrikaans */
+ {HB_TAG('a','k',' ',' '), HB_TAG('A','K','A',' ')}, /* Akan [macrolanguage] */
+ {HB_TAG('a','m',' ',' '), HB_TAG('A','M','H',' ')}, /* Amharic */
+ {HB_TAG('a','n',' ',' '), HB_TAG('A','R','G',' ')}, /* Aragonese */
+ {HB_TAG('a','r',' ',' '), HB_TAG('A','R','A',' ')}, /* Arabic [macrolanguage] */
+ {HB_TAG('a','s',' ',' '), HB_TAG('A','S','M',' ')}, /* Assamese */
+ {HB_TAG('a','v',' ',' '), HB_TAG('A','V','R',' ')}, /* Avaric -> Avar */
+ {HB_TAG('a','y',' ',' '), HB_TAG('A','Y','M',' ')}, /* Aymara [macrolanguage] */
+ {HB_TAG('a','z',' ',' '), HB_TAG('A','Z','E',' ')}, /* Azerbaijani [macrolanguage] */
+ {HB_TAG('b','a',' ',' '), HB_TAG('B','S','H',' ')}, /* Bashkir */
+ {HB_TAG('b','e',' ',' '), HB_TAG('B','E','L',' ')}, /* Belarusian -> Belarussian */
+ {HB_TAG('b','g',' ',' '), HB_TAG('B','G','R',' ')}, /* Bulgarian */
+ {HB_TAG('b','i',' ',' '), HB_TAG('B','I','S',' ')}, /* Bislama */
+ {HB_TAG('b','i',' ',' '), HB_TAG('C','P','P',' ')}, /* Bislama -> Creoles */
+ {HB_TAG('b','m',' ',' '), HB_TAG('B','M','B',' ')}, /* Bambara (Bamanankan) */
+ {HB_TAG('b','n',' ',' '), HB_TAG('B','E','N',' ')}, /* Bengali */
+ {HB_TAG('b','o',' ',' '), HB_TAG('T','I','B',' ')}, /* Tibetan */
+ {HB_TAG('b','r',' ',' '), HB_TAG('B','R','E',' ')}, /* Breton */
+ {HB_TAG('b','s',' ',' '), HB_TAG('B','O','S',' ')}, /* Bosnian */
+ {HB_TAG('c','a',' ',' '), HB_TAG('C','A','T',' ')}, /* Catalan */
+ {HB_TAG('c','e',' ',' '), HB_TAG('C','H','E',' ')}, /* Chechen */
+ {HB_TAG('c','h',' ',' '), HB_TAG('C','H','A',' ')}, /* Chamorro */
+ {HB_TAG('c','o',' ',' '), HB_TAG('C','O','S',' ')}, /* Corsican */
+ {HB_TAG('c','r',' ',' '), HB_TAG('C','R','E',' ')}, /* Cree [macrolanguage] */
+ {HB_TAG('c','s',' ',' '), HB_TAG('C','S','Y',' ')}, /* Czech */
+ {HB_TAG('c','u',' ',' '), HB_TAG('C','S','L',' ')}, /* Church Slavonic */
+ {HB_TAG('c','v',' ',' '), HB_TAG('C','H','U',' ')}, /* Chuvash */
+ {HB_TAG('c','y',' ',' '), HB_TAG('W','E','L',' ')}, /* Welsh */
+ {HB_TAG('d','a',' ',' '), HB_TAG('D','A','N',' ')}, /* Danish */
+ {HB_TAG('d','e',' ',' '), HB_TAG('D','E','U',' ')}, /* German */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','I','V',' ')}, /* Divehi (Dhivehi, Maldivian) */
+ {HB_TAG('d','v',' ',' '), HB_TAG('D','H','V',' ')}, /* Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','z',' ',' '), HB_TAG('D','Z','N',' ')}, /* Dzongkha */
+ {HB_TAG('e','e',' ',' '), HB_TAG('E','W','E',' ')}, /* Ewe */
+ {HB_TAG('e','l',' ',' '), HB_TAG('E','L','L',' ')}, /* Modern Greek (1453-) -> Greek */
+ {HB_TAG('e','n',' ',' '), HB_TAG('E','N','G',' ')}, /* English */
+ {HB_TAG('e','o',' ',' '), HB_TAG('N','T','O',' ')}, /* Esperanto */
+ {HB_TAG('e','s',' ',' '), HB_TAG('E','S','P',' ')}, /* Spanish */
+ {HB_TAG('e','t',' ',' '), HB_TAG('E','T','I',' ')}, /* Estonian [macrolanguage] */
+ {HB_TAG('e','u',' ',' '), HB_TAG('E','U','Q',' ')}, /* Basque */
+ {HB_TAG('f','a',' ',' '), HB_TAG('F','A','R',' ')}, /* Persian [macrolanguage] */
+ {HB_TAG('f','f',' ',' '), HB_TAG('F','U','L',' ')}, /* Fulah [macrolanguage] */
+ {HB_TAG('f','i',' ',' '), HB_TAG('F','I','N',' ')}, /* Finnish */
+ {HB_TAG('f','j',' ',' '), HB_TAG('F','J','I',' ')}, /* Fijian */
+ {HB_TAG('f','o',' ',' '), HB_TAG('F','O','S',' ')}, /* Faroese */
+ {HB_TAG('f','r',' ',' '), HB_TAG('F','R','A',' ')}, /* French */
+ {HB_TAG('f','y',' ',' '), HB_TAG('F','R','I',' ')}, /* Western Frisian -> Frisian */
+ {HB_TAG('g','a',' ',' '), HB_TAG('I','R','I',' ')}, /* Irish */
+ {HB_TAG('g','d',' ',' '), HB_TAG('G','A','E',' ')}, /* Scottish Gaelic (Gaelic) */
+ {HB_TAG('g','l',' ',' '), HB_TAG('G','A','L',' ')}, /* Galician */
+ {HB_TAG('g','n',' ',' '), HB_TAG('G','U','A',' ')}, /* Guarani [macrolanguage] */
+ {HB_TAG('g','u',' ',' '), HB_TAG('G','U','J',' ')}, /* Gujarati */
+ {HB_TAG('g','v',' ',' '), HB_TAG('M','N','X',' ')}, /* Manx */
+ {HB_TAG('h','a',' ',' '), HB_TAG('H','A','U',' ')}, /* Hausa */
+ {HB_TAG('h','e',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew */
+ {HB_TAG('h','i',' ',' '), HB_TAG('H','I','N',' ')}, /* Hindi */
+ {HB_TAG('h','o',' ',' '), HB_TAG('H','M','O',' ')}, /* Hiri Motu */
+ {HB_TAG('h','o',' ',' '), HB_TAG('C','P','P',' ')}, /* Hiri Motu -> Creoles */
+ {HB_TAG('h','r',' ',' '), HB_TAG('H','R','V',' ')}, /* Croatian */
+ {HB_TAG('h','t',' ',' '), HB_TAG('H','A','I',' ')}, /* Haitian (Haitian Creole) */
+ {HB_TAG('h','t',' ',' '), HB_TAG('C','P','P',' ')}, /* Haitian -> Creoles */
+ {HB_TAG('h','u',' ',' '), HB_TAG('H','U','N',' ')}, /* Hungarian */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E','0')}, /* Armenian -> Armenian East */
+ {HB_TAG('h','y',' ',' '), HB_TAG('H','Y','E',' ')}, /* Armenian */
+ {HB_TAG('h','z',' ',' '), HB_TAG('H','E','R',' ')}, /* Herero */
+ {HB_TAG('i','a',' ',' '), HB_TAG('I','N','A',' ')}, /* Interlingua (International Auxiliary Language Association) */
+ {HB_TAG('i','d',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian */
+ {HB_TAG('i','d',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian -> Malay */
+ {HB_TAG('i','e',' ',' '), HB_TAG('I','L','E',' ')}, /* Interlingue */
+ {HB_TAG('i','g',' ',' '), HB_TAG('I','B','O',' ')}, /* Igbo */
+ {HB_TAG('i','i',' ',' '), HB_TAG('Y','I','M',' ')}, /* Sichuan Yi -> Yi Modern */
+ {HB_TAG('i','k',' ',' '), HB_TAG('I','P','K',' ')}, /* Inupiaq [macrolanguage] -> Inupiat */
+ {HB_TAG('i','n',' ',' '), HB_TAG('I','N','D',' ')}, /* Indonesian (retired code) */
+ {HB_TAG('i','n',' ',' '), HB_TAG('M','L','Y',' ')}, /* Indonesian (retired code) -> Malay */
+ {HB_TAG('i','o',' ',' '), HB_TAG('I','D','O',' ')}, /* Ido */
+ {HB_TAG('i','s',' ',' '), HB_TAG('I','S','L',' ')}, /* Icelandic */
+ {HB_TAG('i','t',' ',' '), HB_TAG('I','T','A',' ')}, /* Italian */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U',' ')}, /* Inuktitut [macrolanguage] */
+ {HB_TAG('i','u',' ',' '), HB_TAG('I','N','U','K')}, /* Inuktitut [macrolanguage] -> Nunavik Inuktitut */
+ {HB_TAG('i','w',' ',' '), HB_TAG('I','W','R',' ')}, /* Hebrew (retired code) */
+ {HB_TAG('j','a',' ',' '), HB_TAG('J','A','N',' ')}, /* Japanese */
+ {HB_TAG('j','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish (retired code) */
+ {HB_TAG('j','v',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese */
+ {HB_TAG('j','w',' ',' '), HB_TAG('J','A','V',' ')}, /* Javanese (retired code) */
+ {HB_TAG('k','a',' ',' '), HB_TAG('K','A','T',' ')}, /* Georgian */
+ {HB_TAG('k','g',' ',' '), HB_TAG('K','O','N','0')}, /* Kongo [macrolanguage] */
+ {HB_TAG('k','i',' ',' '), HB_TAG('K','I','K',' ')}, /* Kikuyu (Gikuyu) */
+ {HB_TAG('k','j',' ',' '), HB_TAG('K','U','A',' ')}, /* Kuanyama */
+ {HB_TAG('k','k',' ',' '), HB_TAG('K','A','Z',' ')}, /* Kazakh */
+ {HB_TAG('k','l',' ',' '), HB_TAG('G','R','N',' ')}, /* Greenlandic */
+ {HB_TAG('k','m',' ',' '), HB_TAG('K','H','M',' ')}, /* Khmer */
+ {HB_TAG('k','n',' ',' '), HB_TAG('K','A','N',' ')}, /* Kannada */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','R',' ')}, /* Korean */
+ {HB_TAG('k','o',' ',' '), HB_TAG('K','O','H',' ')}, /* Korean -> Korean Old Hangul */
+ {HB_TAG('k','r',' ',' '), HB_TAG('K','N','R',' ')}, /* Kanuri [macrolanguage] */
+ {HB_TAG('k','s',' ',' '), HB_TAG('K','S','H',' ')}, /* Kashmiri */
+ {HB_TAG('k','u',' ',' '), HB_TAG('K','U','R',' ')}, /* Kurdish [macrolanguage] */
+ {HB_TAG('k','v',' ',' '), HB_TAG('K','O','M',' ')}, /* Komi [macrolanguage] */
+ {HB_TAG('k','w',' ',' '), HB_TAG('C','O','R',' ')}, /* Cornish */
+ {HB_TAG('k','y',' ',' '), HB_TAG('K','I','R',' ')}, /* Kirghiz (Kyrgyz) */
+ {HB_TAG('l','a',' ',' '), HB_TAG('L','A','T',' ')}, /* Latin */
+ {HB_TAG('l','b',' ',' '), HB_TAG('L','T','Z',' ')}, /* Luxembourgish */
+ {HB_TAG('l','g',' ',' '), HB_TAG('L','U','G',' ')}, /* Ganda */
+ {HB_TAG('l','i',' ',' '), HB_TAG('L','I','M',' ')}, /* Limburgish */
+ {HB_TAG('l','n',' ',' '), HB_TAG('L','I','N',' ')}, /* Lingala */
+ {HB_TAG('l','o',' ',' '), HB_TAG('L','A','O',' ')}, /* Lao */
+ {HB_TAG('l','t',' ',' '), HB_TAG('L','T','H',' ')}, /* Lithuanian */
+ {HB_TAG('l','u',' ',' '), HB_TAG('L','U','B',' ')}, /* Luba-Katanga */
+ {HB_TAG('l','v',' ',' '), HB_TAG('L','V','I',' ')}, /* Latvian [macrolanguage] */
+ {HB_TAG('m','g',' ',' '), HB_TAG('M','L','G',' ')}, /* Malagasy [macrolanguage] */
+ {HB_TAG('m','h',' ',' '), HB_TAG('M','A','H',' ')}, /* Marshallese */
+ {HB_TAG('m','i',' ',' '), HB_TAG('M','R','I',' ')}, /* Maori */
+ {HB_TAG('m','k',' ',' '), HB_TAG('M','K','D',' ')}, /* Macedonian */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','A','L',' ')}, /* Malayalam -> Malayalam Traditional */
+ {HB_TAG('m','l',' ',' '), HB_TAG('M','L','R',' ')}, /* Malayalam -> Malayalam Reformed */
+ {HB_TAG('m','n',' ',' '), HB_TAG('M','N','G',' ')}, /* Mongolian [macrolanguage] */
+ {HB_TAG('m','o',' ',' '), HB_TAG('M','O','L',' ')}, /* Moldavian (retired code) */
+ {HB_TAG('m','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Moldavian (retired code) -> Romanian */
+ {HB_TAG('m','r',' ',' '), HB_TAG('M','A','R',' ')}, /* Marathi */
+ {HB_TAG('m','s',' ',' '), HB_TAG('M','L','Y',' ')}, /* Malay [macrolanguage] */
+ {HB_TAG('m','t',' ',' '), HB_TAG('M','T','S',' ')}, /* Maltese */
+ {HB_TAG('m','y',' ',' '), HB_TAG('B','R','M',' ')}, /* Burmese */
+ {HB_TAG('n','a',' ',' '), HB_TAG('N','A','U',' ')}, /* Nauru -> Nauruan */
+ {HB_TAG('n','b',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian Bokmål -> Norwegian */
+ {HB_TAG('n','d',' ',' '), HB_TAG('N','D','B',' ')}, /* North Ndebele -> Ndebele */
+ {HB_TAG('n','e',' ',' '), HB_TAG('N','E','P',' ')}, /* Nepali [macrolanguage] */
+ {HB_TAG('n','g',' ',' '), HB_TAG('N','D','G',' ')}, /* Ndonga */
+ {HB_TAG('n','l',' ',' '), HB_TAG('N','L','D',' ')}, /* Dutch */
+ {HB_TAG('n','n',' ',' '), HB_TAG('N','Y','N',' ')}, /* Norwegian Nynorsk (Nynorsk, Norwegian) */
+ {HB_TAG('n','o',' ',' '), HB_TAG('N','O','R',' ')}, /* Norwegian [macrolanguage] */
+ {HB_TAG('n','r',' ',' '), HB_TAG('N','D','B',' ')}, /* South Ndebele -> Ndebele */
+ {HB_TAG('n','v',' ',' '), HB_TAG('N','A','V',' ')}, /* Navajo */
+ {HB_TAG('n','v',' ',' '), HB_TAG('A','T','H',' ')}, /* Navajo -> Athapaskan */
+ {HB_TAG('n','y',' ',' '), HB_TAG('C','H','I',' ')}, /* Chichewa (Chewa, Nyanja) */
+ {HB_TAG('o','c',' ',' '), HB_TAG('O','C','I',' ')}, /* Occitan (post 1500) */
+ {HB_TAG('o','j',' ',' '), HB_TAG('O','J','B',' ')}, /* Ojibwa [macrolanguage] -> Ojibway */
+ {HB_TAG('o','m',' ',' '), HB_TAG('O','R','O',' ')}, /* Oromo [macrolanguage] */
+ {HB_TAG('o','r',' ',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) [macrolanguage] */
+ {HB_TAG('o','s',' ',' '), HB_TAG('O','S','S',' ')}, /* Ossetian */
+ {HB_TAG('p','a',' ',' '), HB_TAG('P','A','N',' ')}, /* Punjabi */
+ {HB_TAG('p','i',' ',' '), HB_TAG('P','A','L',' ')}, /* Pali */
+ {HB_TAG('p','l',' ',' '), HB_TAG('P','L','K',' ')}, /* Polish */
+ {HB_TAG('p','s',' ',' '), HB_TAG('P','A','S',' ')}, /* Pashto [macrolanguage] */
+ {HB_TAG('p','t',' ',' '), HB_TAG('P','T','G',' ')}, /* Portuguese */
+ {HB_TAG('q','u',' ',' '), HB_TAG('Q','U','Z',' ')}, /* Quechua [macrolanguage] */
+ {HB_TAG('r','m',' ',' '), HB_TAG('R','M','S',' ')}, /* Romansh */
+ {HB_TAG('r','n',' ',' '), HB_TAG('R','U','N',' ')}, /* Rundi */
+ {HB_TAG('r','o',' ',' '), HB_TAG('R','O','M',' ')}, /* Romanian */
+ {HB_TAG('r','u',' ',' '), HB_TAG('R','U','S',' ')}, /* Russian */
+ {HB_TAG('r','w',' ',' '), HB_TAG('R','U','A',' ')}, /* Kinyarwanda */
+ {HB_TAG('s','a',' ',' '), HB_TAG('S','A','N',' ')}, /* Sanskrit */
+ {HB_TAG('s','c',' ',' '), HB_TAG('S','R','D',' ')}, /* Sardinian [macrolanguage] */
+ {HB_TAG('s','d',' ',' '), HB_TAG('S','N','D',' ')}, /* Sindhi */
+ {HB_TAG('s','e',' ',' '), HB_TAG('N','S','M',' ')}, /* Northern Sami */
+ {HB_TAG('s','g',' ',' '), HB_TAG('S','G','O',' ')}, /* Sango */
+ {HB_TAG('s','h',' ',' '), HB_TAG('B','O','S',' ')}, /* Serbo-Croatian [macrolanguage] -> Bosnian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('H','R','V',' ')}, /* Serbo-Croatian [macrolanguage] -> Croatian */
+ {HB_TAG('s','h',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbo-Croatian [macrolanguage] -> Serbian */
+ {HB_TAG('s','i',' ',' '), HB_TAG('S','N','H',' ')}, /* Sinhala (Sinhalese) */
+ {HB_TAG('s','k',' ',' '), HB_TAG('S','K','Y',' ')}, /* Slovak */
+ {HB_TAG('s','l',' ',' '), HB_TAG('S','L','V',' ')}, /* Slovenian */
+ {HB_TAG('s','m',' ',' '), HB_TAG('S','M','O',' ')}, /* Samoan */
+ {HB_TAG('s','n',' ',' '), HB_TAG('S','N','A','0')}, /* Shona */
+ {HB_TAG('s','o',' ',' '), HB_TAG('S','M','L',' ')}, /* Somali */
+ {HB_TAG('s','q',' ',' '), HB_TAG('S','Q','I',' ')}, /* Albanian [macrolanguage] */
+ {HB_TAG('s','r',' ',' '), HB_TAG('S','R','B',' ')}, /* Serbian */
+ {HB_TAG('s','s',' ',' '), HB_TAG('S','W','Z',' ')}, /* Swati */
+ {HB_TAG('s','t',' ',' '), HB_TAG('S','O','T',' ')}, /* Southern Sotho */
+ {HB_TAG('s','u',' ',' '), HB_TAG('S','U','N',' ')}, /* Sundanese */
+ {HB_TAG('s','v',' ',' '), HB_TAG('S','V','E',' ')}, /* Swedish */
+ {HB_TAG('s','w',' ',' '), HB_TAG('S','W','K',' ')}, /* Swahili [macrolanguage] */
+ {HB_TAG('t','a',' ',' '), HB_TAG('T','A','M',' ')}, /* Tamil */
+ {HB_TAG('t','e',' ',' '), HB_TAG('T','E','L',' ')}, /* Telugu */
+ {HB_TAG('t','g',' ',' '), HB_TAG('T','A','J',' ')}, /* Tajik -> Tajiki */
+ {HB_TAG('t','h',' ',' '), HB_TAG('T','H','A',' ')}, /* Thai */
+ {HB_TAG('t','i',' ',' '), HB_TAG('T','G','Y',' ')}, /* Tigrinya */
+ {HB_TAG('t','k',' ',' '), HB_TAG('T','K','M',' ')}, /* Turkmen */
+ {HB_TAG('t','l',' ',' '), HB_TAG('T','G','L',' ')}, /* Tagalog */
+ {HB_TAG('t','n',' ',' '), HB_TAG('T','N','A',' ')}, /* Tswana */
+ {HB_TAG('t','o',' ',' '), HB_TAG('T','G','N',' ')}, /* Tonga (Tonga Islands) -> Tongan */
+ {HB_TAG('t','r',' ',' '), HB_TAG('T','R','K',' ')}, /* Turkish */
+ {HB_TAG('t','s',' ',' '), HB_TAG('T','S','G',' ')}, /* Tsonga */
+ {HB_TAG('t','t',' ',' '), HB_TAG('T','A','T',' ')}, /* Tatar */
+ {HB_TAG('t','w',' ',' '), HB_TAG('T','W','I',' ')}, /* Twi */
+ {HB_TAG('t','w',' ',' '), HB_TAG('A','K','A',' ')}, /* Twi -> Akan */
+ {HB_TAG('t','y',' ',' '), HB_TAG('T','H','T',' ')}, /* Tahitian */
+ {HB_TAG('u','g',' ',' '), HB_TAG('U','Y','G',' ')}, /* Uyghur */
+ {HB_TAG('u','k',' ',' '), HB_TAG('U','K','R',' ')}, /* Ukrainian */
+ {HB_TAG('u','r',' ',' '), HB_TAG('U','R','D',' ')}, /* Urdu */
+ {HB_TAG('u','z',' ',' '), HB_TAG('U','Z','B',' ')}, /* Uzbek [macrolanguage] */
+ {HB_TAG('v','e',' ',' '), HB_TAG('V','E','N',' ')}, /* Venda */
+ {HB_TAG('v','i',' ',' '), HB_TAG('V','I','T',' ')}, /* Vietnamese */
+ {HB_TAG('v','o',' ',' '), HB_TAG('V','O','L',' ')}, /* Volapük */
+ {HB_TAG('w','a',' ',' '), HB_TAG('W','L','N',' ')}, /* Walloon */
+ {HB_TAG('w','o',' ',' '), HB_TAG('W','L','F',' ')}, /* Wolof */
+ {HB_TAG('x','h',' ',' '), HB_TAG('X','H','S',' ')}, /* Xhosa */
+ {HB_TAG('y','i',' ',' '), HB_TAG('J','I','I',' ')}, /* Yiddish [macrolanguage] */
+ {HB_TAG('y','o',' ',' '), HB_TAG('Y','B','A',' ')}, /* Yoruba */
+ {HB_TAG('z','a',' ',' '), HB_TAG('Z','H','A',' ')}, /* Zhuang [macrolanguage] */
+ {HB_TAG('z','h',' ',' '), HB_TAG('Z','H','S',' ')}, /* Chinese, Simplified [macrolanguage] */
+ {HB_TAG('z','u',' ',' '), HB_TAG('Z','U','L',' ')}, /* Zulu */
};
+#ifndef HB_NO_LANGUAGE_LONG
+static const LangTag ot_languages3[] = {
+ {HB_TAG('a','a','e',' '), HB_TAG('S','Q','I',' ')}, /* Arbëreshë Albanian -> Albanian */
+ {HB_TAG('a','a','o',' '), HB_TAG('A','R','A',' ')}, /* Algerian Saharan Arabic -> Arabic */
+ {HB_TAG('a','a','t',' '), HB_TAG('S','Q','I',' ')}, /* Arvanitika Albanian -> Albanian */
+ {HB_TAG('a','b','a',' '), HB_TAG_NONE }, /* Abé != Abaza */
+ {HB_TAG('a','b','h',' '), HB_TAG('A','R','A',' ')}, /* Tajiki Arabic -> Arabic */
+ {HB_TAG('a','b','q',' '), HB_TAG('A','B','A',' ')}, /* Abaza */
+ {HB_TAG('a','b','s',' '), HB_TAG('C','P','P',' ')}, /* Ambonese Malay -> Creoles */
+ {HB_TAG('a','b','v',' '), HB_TAG('A','R','A',' ')}, /* Baharna Arabic -> Arabic */
+ {HB_TAG('a','c','f',' '), HB_TAG('F','A','N',' ')}, /* Saint Lucian Creole French -> French Antillean */
+ {HB_TAG('a','c','f',' '), HB_TAG('C','P','P',' ')}, /* Saint Lucian Creole French -> Creoles */
+/*{HB_TAG('a','c','h',' '), HB_TAG('A','C','H',' ')},*/ /* Acoli -> Acholi */
+ {HB_TAG('a','c','m',' '), HB_TAG('A','R','A',' ')}, /* Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','c','q',' '), HB_TAG('A','R','A',' ')}, /* Ta'izzi-Adeni Arabic -> Arabic */
+ {HB_TAG('a','c','r',' '), HB_TAG('A','C','R',' ')}, /* Achi */
+ {HB_TAG('a','c','r',' '), HB_TAG('M','Y','N',' ')}, /* Achi -> Mayan */
+ {HB_TAG('a','c','w',' '), HB_TAG('A','R','A',' ')}, /* Hijazi Arabic -> Arabic */
+ {HB_TAG('a','c','x',' '), HB_TAG('A','R','A',' ')}, /* Omani Arabic -> Arabic */
+ {HB_TAG('a','c','y',' '), HB_TAG('A','R','A',' ')}, /* Cypriot Arabic -> Arabic */
+ {HB_TAG('a','d','a',' '), HB_TAG('D','N','G',' ')}, /* Adangme -> Dangme */
+ {HB_TAG('a','d','f',' '), HB_TAG('A','R','A',' ')}, /* Dhofari Arabic -> Arabic */
+ {HB_TAG('a','d','p',' '), HB_TAG('D','Z','N',' ')}, /* Adap (retired code) -> Dzongkha */
+/*{HB_TAG('a','d','y',' '), HB_TAG('A','D','Y',' ')},*/ /* Adyghe */
+ {HB_TAG('a','e','b',' '), HB_TAG('A','R','A',' ')}, /* Tunisian Arabic -> Arabic */
+ {HB_TAG('a','e','c',' '), HB_TAG('A','R','A',' ')}, /* Saidi Arabic -> Arabic */
+ {HB_TAG('a','f','b',' '), HB_TAG('A','R','A',' ')}, /* Gulf Arabic -> Arabic */
+ {HB_TAG('a','f','k',' '), HB_TAG_NONE }, /* Nanubae != Afrikaans */
+ {HB_TAG('a','f','s',' '), HB_TAG('C','P','P',' ')}, /* Afro-Seminole Creole -> Creoles */
+ {HB_TAG('a','g','u',' '), HB_TAG('M','Y','N',' ')}, /* Aguacateco -> Mayan */
+ {HB_TAG('a','g','w',' '), HB_TAG_NONE }, /* Kahua != Agaw */
+ {HB_TAG('a','h','g',' '), HB_TAG('A','G','W',' ')}, /* Qimant -> Agaw */
+ {HB_TAG('a','h','t',' '), HB_TAG('A','T','H',' ')}, /* Ahtena -> Athapaskan */
+ {HB_TAG('a','i','g',' '), HB_TAG('C','P','P',' ')}, /* Antigua and Barbuda Creole English -> Creoles */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','W','A',' ')}, /* Assyrian Neo-Aramaic -> Swadaya Aramaic */
+ {HB_TAG('a','i','i',' '), HB_TAG('S','Y','R',' ')}, /* Assyrian Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','i','o',' '), HB_TAG('A','I','O',' ')},*/ /* Aiton */
+ {HB_TAG('a','i','w',' '), HB_TAG('A','R','I',' ')}, /* Aari */
+ {HB_TAG('a','j','p',' '), HB_TAG('A','R','A',' ')}, /* South Levantine Arabic -> Arabic */
+ {HB_TAG('a','j','t',' '), HB_TAG('A','R','A',' ')}, /* Judeo-Tunisian Arabic (retired code) -> Arabic */
+ {HB_TAG('a','k','b',' '), HB_TAG('A','K','B',' ')}, /* Batak Angkola */
+ {HB_TAG('a','k','b',' '), HB_TAG('B','T','K',' ')}, /* Batak Angkola -> Batak */
+ {HB_TAG('a','l','n',' '), HB_TAG('S','Q','I',' ')}, /* Gheg Albanian -> Albanian */
+ {HB_TAG('a','l','s',' '), HB_TAG('S','Q','I',' ')}, /* Tosk Albanian -> Albanian */
+/*{HB_TAG('a','l','t',' '), HB_TAG('A','L','T',' ')},*/ /* Southern Altai -> Altai */
+ {HB_TAG('a','m','f',' '), HB_TAG('H','B','N',' ')}, /* Hamer-Banna -> Hammer-Banna */
+ {HB_TAG('a','m','w',' '), HB_TAG('S','Y','R',' ')}, /* Western Neo-Aramaic -> Syriac */
+/*{HB_TAG('a','n','g',' '), HB_TAG('A','N','G',' ')},*/ /* Old English (ca. 450-1100) -> Anglo-Saxon */
+ {HB_TAG('a','o','a',' '), HB_TAG('C','P','P',' ')}, /* Angolar -> Creoles */
+ {HB_TAG('a','p','a',' '), HB_TAG('A','T','H',' ')}, /* Apache [collection] -> Athapaskan */
+ {HB_TAG('a','p','c',' '), HB_TAG('A','R','A',' ')}, /* North Levantine Arabic -> Arabic */
+ {HB_TAG('a','p','d',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Arabic -> Arabic */
+ {HB_TAG('a','p','j',' '), HB_TAG('A','T','H',' ')}, /* Jicarilla Apache -> Athapaskan */
+ {HB_TAG('a','p','k',' '), HB_TAG('A','T','H',' ')}, /* Kiowa Apache -> Athapaskan */
+ {HB_TAG('a','p','l',' '), HB_TAG('A','T','H',' ')}, /* Lipan Apache -> Athapaskan */
+ {HB_TAG('a','p','m',' '), HB_TAG('A','T','H',' ')}, /* Mescalero-Chiricahua Apache -> Athapaskan */
+ {HB_TAG('a','p','w',' '), HB_TAG('A','T','H',' ')}, /* Western Apache -> Athapaskan */
+ {HB_TAG('a','r','b',' '), HB_TAG('A','R','A',' ')}, /* Standard Arabic -> Arabic */
+ {HB_TAG('a','r','i',' '), HB_TAG_NONE }, /* Arikara != Aari */
+ {HB_TAG('a','r','k',' '), HB_TAG_NONE }, /* Arikapú != Rakhine */
+ {HB_TAG('a','r','n',' '), HB_TAG('M','A','P',' ')}, /* Mapudungun */
+ {HB_TAG('a','r','q',' '), HB_TAG('A','R','A',' ')}, /* Algerian Arabic -> Arabic */
+ {HB_TAG('a','r','s',' '), HB_TAG('A','R','A',' ')}, /* Najdi Arabic -> Arabic */
+ {HB_TAG('a','r','y',' '), HB_TAG('M','O','R',' ')}, /* Moroccan Arabic -> Moroccan */
+ {HB_TAG('a','r','y',' '), HB_TAG('A','R','A',' ')}, /* Moroccan Arabic -> Arabic */
+ {HB_TAG('a','r','z',' '), HB_TAG('A','R','A',' ')}, /* Egyptian Arabic -> Arabic */
+/*{HB_TAG('a','s','t',' '), HB_TAG('A','S','T',' ')},*/ /* Asturian */
+/*{HB_TAG('a','t','h',' '), HB_TAG('A','T','H',' ')},*/ /* Athapascan [collection] -> Athapaskan */
+ {HB_TAG('a','t','j',' '), HB_TAG('R','C','R',' ')}, /* Atikamekw -> R-Cree */
+ {HB_TAG('a','t','v',' '), HB_TAG('A','L','T',' ')}, /* Northern Altai -> Altai */
+ {HB_TAG('a','u','j',' '), HB_TAG('B','B','R',' ')}, /* Awjilah -> Berber */
+ {HB_TAG('a','u','z',' '), HB_TAG('A','R','A',' ')}, /* Uzbeki Arabic -> Arabic */
+ {HB_TAG('a','v','l',' '), HB_TAG('A','R','A',' ')}, /* Eastern Egyptian Bedawi Arabic -> Arabic */
+/*{HB_TAG('a','v','n',' '), HB_TAG('A','V','N',' ')},*/ /* Avatime */
+/*{HB_TAG('a','w','a',' '), HB_TAG('A','W','A',' ')},*/ /* Awadhi */
+ {HB_TAG('a','y','c',' '), HB_TAG('A','Y','M',' ')}, /* Southern Aymara -> Aymara */
+ {HB_TAG('a','y','h',' '), HB_TAG('A','R','A',' ')}, /* Hadrami Arabic -> Arabic */
+ {HB_TAG('a','y','l',' '), HB_TAG('A','R','A',' ')}, /* Libyan Arabic -> Arabic */
+ {HB_TAG('a','y','n',' '), HB_TAG('A','R','A',' ')}, /* Sanaani Arabic -> Arabic */
+ {HB_TAG('a','y','p',' '), HB_TAG('A','R','A',' ')}, /* North Mesopotamian Arabic -> Arabic */
+ {HB_TAG('a','y','r',' '), HB_TAG('A','Y','M',' ')}, /* Central Aymara -> Aymara */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','B',' ')}, /* South Azerbaijani -> Torki */
+ {HB_TAG('a','z','b',' '), HB_TAG('A','Z','E',' ')}, /* South Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','d',' '), HB_TAG('N','A','H',' ')}, /* Eastern Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','j',' '), HB_TAG('A','Z','E',' ')}, /* North Azerbaijani -> Azerbaijani */
+ {HB_TAG('a','z','n',' '), HB_TAG('N','A','H',' ')}, /* Western Durango Nahuatl -> Nahuatl */
+ {HB_TAG('a','z','z',' '), HB_TAG('N','A','H',' ')}, /* Highland Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('b','a','d',' '), HB_TAG('B','A','D','0')}, /* Banda [collection] */
+ {HB_TAG('b','a','g',' '), HB_TAG_NONE }, /* Tuki != Baghelkhandi */
+ {HB_TAG('b','a','h',' '), HB_TAG('C','P','P',' ')}, /* Bahamas Creole English -> Creoles */
+ {HB_TAG('b','a','i',' '), HB_TAG('B','M','L',' ')}, /* Bamileke [collection] */
+ {HB_TAG('b','a','l',' '), HB_TAG('B','L','I',' ')}, /* Baluchi [macrolanguage] */
+/*{HB_TAG('b','a','n',' '), HB_TAG('B','A','N',' ')},*/ /* Balinese */
+/*{HB_TAG('b','a','r',' '), HB_TAG('B','A','R',' ')},*/ /* Bavarian */
+ {HB_TAG('b','a','u',' '), HB_TAG_NONE }, /* Bada (Nigeria) != Baulé */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','B','C',' ')}, /* Batak Toba */
+ {HB_TAG('b','b','c',' '), HB_TAG('B','T','K',' ')}, /* Batak Toba -> Batak */
+ {HB_TAG('b','b','j',' '), HB_TAG('B','M','L',' ')}, /* Ghomálá' -> Bamileke */
+ {HB_TAG('b','b','p',' '), HB_TAG('B','A','D','0')}, /* West Central Banda -> Banda */
+ {HB_TAG('b','b','r',' '), HB_TAG_NONE }, /* Girawa != Berber */
+ {HB_TAG('b','b','z',' '), HB_TAG('A','R','A',' ')}, /* Babalia Creole Arabic (retired code) -> Arabic */
+ {HB_TAG('b','c','c',' '), HB_TAG('B','L','I',' ')}, /* Southern Balochi -> Baluchi */
+ {HB_TAG('b','c','h',' '), HB_TAG_NONE }, /* Bariai != Bench */
+ {HB_TAG('b','c','i',' '), HB_TAG('B','A','U',' ')}, /* Baoulé -> Baulé */
+ {HB_TAG('b','c','l',' '), HB_TAG('B','I','K',' ')}, /* Central Bikol -> Bikol */
+ {HB_TAG('b','c','q',' '), HB_TAG('B','C','H',' ')}, /* Bench */
+ {HB_TAG('b','c','r',' '), HB_TAG('A','T','H',' ')}, /* Babine -> Athapaskan */
+/*{HB_TAG('b','d','y',' '), HB_TAG('B','D','Y',' ')},*/ /* Bandjalang */
+ {HB_TAG('b','e','a',' '), HB_TAG('A','T','H',' ')}, /* Beaver -> Athapaskan */
+ {HB_TAG('b','e','b',' '), HB_TAG('B','T','I',' ')}, /* Bebele -> Beti */
+/*{HB_TAG('b','e','m',' '), HB_TAG('B','E','M',' ')},*/ /* Bemba (Zambia) */
+ {HB_TAG('b','e','r',' '), HB_TAG('B','B','R',' ')}, /* Berber [collection] */
+ {HB_TAG('b','e','w',' '), HB_TAG('C','P','P',' ')}, /* Betawi -> Creoles */
+ {HB_TAG('b','f','l',' '), HB_TAG('B','A','D','0')}, /* Banda-Ndélé -> Banda */
+ {HB_TAG('b','f','q',' '), HB_TAG('B','A','D',' ')}, /* Badaga */
+ {HB_TAG('b','f','t',' '), HB_TAG('B','L','T',' ')}, /* Balti */
+ {HB_TAG('b','f','u',' '), HB_TAG('L','A','H',' ')}, /* Gahri -> Lahuli */
+ {HB_TAG('b','f','y',' '), HB_TAG('B','A','G',' ')}, /* Bagheli -> Baghelkhandi */
+/*{HB_TAG('b','g','c',' '), HB_TAG('B','G','C',' ')},*/ /* Haryanvi */
+ {HB_TAG('b','g','n',' '), HB_TAG('B','L','I',' ')}, /* Western Balochi -> Baluchi */
+ {HB_TAG('b','g','p',' '), HB_TAG('B','L','I',' ')}, /* Eastern Balochi -> Baluchi */
+ {HB_TAG('b','g','q',' '), HB_TAG('B','G','Q',' ')}, /* Bagri */
+ {HB_TAG('b','g','q',' '), HB_TAG('R','A','J',' ')}, /* Bagri -> Rajasthani */
+ {HB_TAG('b','g','r',' '), HB_TAG('Q','I','N',' ')}, /* Bawm Chin -> Chin */
+ {HB_TAG('b','h','b',' '), HB_TAG('B','H','I',' ')}, /* Bhili */
+/*{HB_TAG('b','h','i',' '), HB_TAG('B','H','I',' ')},*/ /* Bhilali -> Bhili */
+ {HB_TAG('b','h','k',' '), HB_TAG('B','I','K',' ')}, /* Albay Bicolano (retired code) -> Bikol */
+/*{HB_TAG('b','h','o',' '), HB_TAG('B','H','O',' ')},*/ /* Bhojpuri */
+ {HB_TAG('b','h','r',' '), HB_TAG('M','L','G',' ')}, /* Bara Malagasy -> Malagasy */
+/*{HB_TAG('b','i','k',' '), HB_TAG('B','I','K',' ')},*/ /* Bikol [macrolanguage] */
+ {HB_TAG('b','i','l',' '), HB_TAG_NONE }, /* Bile != Bilen */
+ {HB_TAG('b','i','n',' '), HB_TAG('E','D','O',' ')}, /* Edo */
+ {HB_TAG('b','i','u',' '), HB_TAG('Q','I','N',' ')}, /* Biete -> Chin */
+/*{HB_TAG('b','j','j',' '), HB_TAG('B','J','J',' ')},*/ /* Kanauji */
+ {HB_TAG('b','j','n',' '), HB_TAG('M','L','Y',' ')}, /* Banjar -> Malay */
+ {HB_TAG('b','j','o',' '), HB_TAG('B','A','D','0')}, /* Mid-Southern Banda -> Banda */
+ {HB_TAG('b','j','q',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy (retired code) -> Malagasy */
+ {HB_TAG('b','j','s',' '), HB_TAG('C','P','P',' ')}, /* Bajan -> Creoles */
+ {HB_TAG('b','j','t',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Ganja -> Balante */
+ {HB_TAG('b','k','f',' '), HB_TAG_NONE }, /* Beeke != Blackfoot */
+ {HB_TAG('b','k','o',' '), HB_TAG('B','M','L',' ')}, /* Kwa' -> Bamileke */
+ {HB_TAG('b','l','a',' '), HB_TAG('B','K','F',' ')}, /* Siksika -> Blackfoot */
+ {HB_TAG('b','l','e',' '), HB_TAG('B','L','N',' ')}, /* Balanta-Kentohe -> Balante */
+ {HB_TAG('b','l','g',' '), HB_TAG('I','B','A',' ')}, /* Balau (retired code) -> Iban */
+ {HB_TAG('b','l','i',' '), HB_TAG_NONE }, /* Bolia != Baluchi */
+ {HB_TAG('b','l','k',' '), HB_TAG('B','L','K',' ')}, /* Pa’o Karen */
+ {HB_TAG('b','l','k',' '), HB_TAG('K','R','N',' ')}, /* Pa'o Karen -> Karen */
+ {HB_TAG('b','l','n',' '), HB_TAG('B','I','K',' ')}, /* Southern Catanduanes Bikol -> Bikol */
+ {HB_TAG('b','l','t',' '), HB_TAG_NONE }, /* Tai Dam != Balti */
+ {HB_TAG('b','m','b',' '), HB_TAG_NONE }, /* Bembe != Bambara (Bamanankan) */
+ {HB_TAG('b','m','l',' '), HB_TAG_NONE }, /* Bomboli != Bamileke */
+ {HB_TAG('b','m','m',' '), HB_TAG('M','L','G',' ')}, /* Northern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','p','d',' '), HB_TAG('B','A','D','0')}, /* Banda-Banda -> Banda */
+ {HB_TAG('b','p','l',' '), HB_TAG('C','P','P',' ')}, /* Broome Pearling Lugger Pidgin -> Creoles */
+ {HB_TAG('b','p','q',' '), HB_TAG('C','P','P',' ')}, /* Banda Malay -> Creoles */
+/*{HB_TAG('b','p','y',' '), HB_TAG('B','P','Y',' ')},*/ /* Bishnupriya -> Bishnupriya Manipuri */
+ {HB_TAG('b','q','i',' '), HB_TAG('L','R','C',' ')}, /* Bakhtiari -> Luri */
+ {HB_TAG('b','q','k',' '), HB_TAG('B','A','D','0')}, /* Banda-Mbrès -> Banda */
+ {HB_TAG('b','r','a',' '), HB_TAG('B','R','I',' ')}, /* Braj -> Braj Bhasha */
+ {HB_TAG('b','r','c',' '), HB_TAG('C','P','P',' ')}, /* Berbice Creole Dutch -> Creoles */
+/*{HB_TAG('b','r','h',' '), HB_TAG('B','R','H',' ')},*/ /* Brahui */
+ {HB_TAG('b','r','i',' '), HB_TAG_NONE }, /* Mokpwe != Braj Bhasha */
+ {HB_TAG('b','r','m',' '), HB_TAG_NONE }, /* Barambu != Burmese */
+/*{HB_TAG('b','r','x',' '), HB_TAG('B','R','X',' ')},*/ /* Bodo (India) */
+ {HB_TAG('b','s','h',' '), HB_TAG_NONE }, /* Kati != Bashkir */
+/*{HB_TAG('b','s','k',' '), HB_TAG('B','S','K',' ')},*/ /* Burushaski */
+ {HB_TAG('b','t','b',' '), HB_TAG('B','T','I',' ')}, /* Beti (Cameroon) (retired code) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','D',' ')}, /* Batak Dairi (Pakpak) */
+ {HB_TAG('b','t','d',' '), HB_TAG('B','T','K',' ')}, /* Batak Dairi -> Batak */
+ {HB_TAG('b','t','i',' '), HB_TAG_NONE }, /* Burate != Beti */
+ {HB_TAG('b','t','j',' '), HB_TAG('M','L','Y',' ')}, /* Bacanese Malay -> Malay */
+/*{HB_TAG('b','t','k',' '), HB_TAG('B','T','K',' ')},*/ /* Batak [collection] */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','M',' ')}, /* Batak Mandailing */
+ {HB_TAG('b','t','m',' '), HB_TAG('B','T','K',' ')}, /* Batak Mandailing -> Batak */
+ {HB_TAG('b','t','o',' '), HB_TAG('B','I','K',' ')}, /* Rinconada Bikol -> Bikol */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','S',' ')}, /* Batak Simalungun */
+ {HB_TAG('b','t','s',' '), HB_TAG('B','T','K',' ')}, /* Batak Simalungun -> Batak */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','X',' ')}, /* Batak Karo */
+ {HB_TAG('b','t','x',' '), HB_TAG('B','T','K',' ')}, /* Batak Karo -> Batak */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','Z',' ')}, /* Batak Alas-Kluet */
+ {HB_TAG('b','t','z',' '), HB_TAG('B','T','K',' ')}, /* Batak Alas-Kluet -> Batak */
+/*{HB_TAG('b','u','g',' '), HB_TAG('B','U','G',' ')},*/ /* Buginese -> Bugis */
+ {HB_TAG('b','u','m',' '), HB_TAG('B','T','I',' ')}, /* Bulu (Cameroon) -> Beti */
+ {HB_TAG('b','v','e',' '), HB_TAG('M','L','Y',' ')}, /* Berau Malay -> Malay */
+ {HB_TAG('b','v','u',' '), HB_TAG('M','L','Y',' ')}, /* Bukit Malay -> Malay */
+ {HB_TAG('b','w','e',' '), HB_TAG('K','R','N',' ')}, /* Bwe Karen -> Karen */
+ {HB_TAG('b','x','k',' '), HB_TAG('L','U','H',' ')}, /* Bukusu -> Luyia */
+ {HB_TAG('b','x','o',' '), HB_TAG('C','P','P',' ')}, /* Barikanchi -> Creoles */
+ {HB_TAG('b','x','p',' '), HB_TAG('B','T','I',' ')}, /* Bebil -> Beti */
+ {HB_TAG('b','x','r',' '), HB_TAG('R','B','U',' ')}, /* Russia Buriat -> Russian Buriat */
+ {HB_TAG('b','y','n',' '), HB_TAG('B','I','L',' ')}, /* Bilin -> Bilen */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','Y','V',' ')}, /* Medumba */
+ {HB_TAG('b','y','v',' '), HB_TAG('B','M','L',' ')}, /* Medumba -> Bamileke */
+ {HB_TAG('b','z','c',' '), HB_TAG('M','L','G',' ')}, /* Southern Betsimisaraka Malagasy -> Malagasy */
+ {HB_TAG('b','z','j',' '), HB_TAG('C','P','P',' ')}, /* Belize Kriol English -> Creoles */
+ {HB_TAG('b','z','k',' '), HB_TAG('C','P','P',' ')}, /* Nicaragua Creole English -> Creoles */
+ {HB_TAG('c','a','a',' '), HB_TAG('M','Y','N',' ')}, /* Chortí -> Mayan */
+ {HB_TAG('c','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Chuj -> Mayan */
+ {HB_TAG('c','a','f',' '), HB_TAG('C','R','R',' ')}, /* Southern Carrier -> Carrier */
+ {HB_TAG('c','a','f',' '), HB_TAG('A','T','H',' ')}, /* Southern Carrier -> Athapaskan */
+ {HB_TAG('c','a','k',' '), HB_TAG('C','A','K',' ')}, /* Kaqchikel */
+ {HB_TAG('c','a','k',' '), HB_TAG('M','Y','N',' ')}, /* Kaqchikel -> Mayan */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','B','K',' ')}, /* Chavacano -> Zamboanga Chavacano */
+ {HB_TAG('c','b','k',' '), HB_TAG('C','P','P',' ')}, /* Chavacano -> Creoles */
+ {HB_TAG('c','b','l',' '), HB_TAG('Q','I','N',' ')}, /* Bualkhaw Chin -> Chin */
+ {HB_TAG('c','c','l',' '), HB_TAG('C','P','P',' ')}, /* Cutchi-Swahili -> Creoles */
+ {HB_TAG('c','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Malay -> Creoles */
+ {HB_TAG('c','c','o',' '), HB_TAG('C','C','H','N')}, /* Comaltepec Chinantec -> Chinantec */
+ {HB_TAG('c','c','q',' '), HB_TAG('A','R','K',' ')}, /* Chaungtha (retired code) -> Rakhine */
+ {HB_TAG('c','d','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Dong Chinese -> Chinese, Simplified */
+/*{HB_TAG('c','e','b',' '), HB_TAG('C','E','B',' ')},*/ /* Cebuano */
+ {HB_TAG('c','e','k',' '), HB_TAG('Q','I','N',' ')}, /* Eastern Khumi Chin -> Chin */
+ {HB_TAG('c','e','y',' '), HB_TAG('Q','I','N',' ')}, /* Ekai Chin -> Chin */
+ {HB_TAG('c','f','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) */
+ {HB_TAG('c','f','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin -> Chin */
+/*{HB_TAG('c','g','g',' '), HB_TAG('C','G','G',' ')},*/ /* Chiga */
+ {HB_TAG('c','h','f',' '), HB_TAG('M','Y','N',' ')}, /* Tabasco Chontal -> Mayan */
+ {HB_TAG('c','h','g',' '), HB_TAG_NONE }, /* Chagatai != Chaha Gurage */
+ {HB_TAG('c','h','h',' '), HB_TAG_NONE }, /* Chinook != Chattisgarhi */
+ {HB_TAG('c','h','j',' '), HB_TAG('C','C','H','N')}, /* Ojitlán Chinantec -> Chinantec */
+ {HB_TAG('c','h','k',' '), HB_TAG('C','H','K','0')}, /* Chuukese */
+ {HB_TAG('c','h','m',' '), HB_TAG('H','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> High Mari */
+ {HB_TAG('c','h','m',' '), HB_TAG('L','M','A',' ')}, /* Mari (Russia) [macrolanguage] -> Low Mari */
+ {HB_TAG('c','h','n',' '), HB_TAG('C','P','P',' ')}, /* Chinook jargon -> Creoles */
+/*{HB_TAG('c','h','o',' '), HB_TAG('C','H','O',' ')},*/ /* Choctaw */
+ {HB_TAG('c','h','p',' '), HB_TAG('C','H','P',' ')}, /* Chipewyan */
+ {HB_TAG('c','h','p',' '), HB_TAG('S','A','Y',' ')}, /* Chipewyan -> Sayisi */
+ {HB_TAG('c','h','p',' '), HB_TAG('A','T','H',' ')}, /* Chipewyan -> Athapaskan */
+ {HB_TAG('c','h','q',' '), HB_TAG('C','C','H','N')}, /* Quiotepec Chinantec -> Chinantec */
+/*{HB_TAG('c','h','r',' '), HB_TAG('C','H','R',' ')},*/ /* Cherokee */
+/*{HB_TAG('c','h','y',' '), HB_TAG('C','H','Y',' ')},*/ /* Cheyenne */
+ {HB_TAG('c','h','z',' '), HB_TAG('C','C','H','N')}, /* Ozumacín Chinantec -> Chinantec */
+ {HB_TAG('c','i','w',' '), HB_TAG('O','J','B',' ')}, /* Chippewa -> Ojibway */
+/*{HB_TAG('c','j','a',' '), HB_TAG('C','J','A',' ')},*/ /* Western Cham */
+/*{HB_TAG('c','j','m',' '), HB_TAG('C','J','M',' ')},*/ /* Eastern Cham */
+ {HB_TAG('c','j','y',' '), HB_TAG('Z','H','S',' ')}, /* Jinyu Chinese -> Chinese, Simplified */
+ {HB_TAG('c','k','a',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Awa Chin (retired code) -> Chin */
+ {HB_TAG('c','k','b',' '), HB_TAG('K','U','R',' ')}, /* Central Kurdish -> Kurdish */
+ {HB_TAG('c','k','n',' '), HB_TAG('Q','I','N',' ')}, /* Kaang Chin -> Chin */
+ {HB_TAG('c','k','s',' '), HB_TAG('C','P','P',' ')}, /* Tayo -> Creoles */
+ {HB_TAG('c','k','t',' '), HB_TAG('C','H','K',' ')}, /* Chukot -> Chukchi */
+ {HB_TAG('c','k','z',' '), HB_TAG('M','Y','N',' ')}, /* Cakchiquel-Quiché Mixed Language -> Mayan */
+ {HB_TAG('c','l','c',' '), HB_TAG('A','T','H',' ')}, /* Chilcotin -> Athapaskan */
+ {HB_TAG('c','l','d',' '), HB_TAG('S','Y','R',' ')}, /* Chaldean Neo-Aramaic -> Syriac */
+ {HB_TAG('c','l','e',' '), HB_TAG('C','C','H','N')}, /* Lealao Chinantec -> Chinantec */
+ {HB_TAG('c','l','j',' '), HB_TAG('Q','I','N',' ')}, /* Laitu Chin -> Chin */
+ {HB_TAG('c','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Lautu Chin -> Chin */
+ {HB_TAG('c','m','n',' '), HB_TAG('Z','H','S',' ')}, /* Mandarin Chinese -> Chinese, Simplified */
+ {HB_TAG('c','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Mro-Khimi Chin -> Chin */
+ {HB_TAG('c','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Chinbon Chin -> Chin */
+ {HB_TAG('c','n','h',' '), HB_TAG('Q','I','N',' ')}, /* Hakha Chin -> Chin */
+ {HB_TAG('c','n','k',' '), HB_TAG('Q','I','N',' ')}, /* Khumi Chin -> Chin */
+ {HB_TAG('c','n','l',' '), HB_TAG('C','C','H','N')}, /* Lalana Chinantec -> Chinantec */
+ {HB_TAG('c','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Northern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','n','r',' '), HB_TAG('S','R','B',' ')}, /* Montenegrin -> Serbian */
+ {HB_TAG('c','n','t',' '), HB_TAG('C','C','H','N')}, /* Tepetotutla Chinantec -> Chinantec */
+ {HB_TAG('c','n','u',' '), HB_TAG('B','B','R',' ')}, /* Chenoua -> Berber */
+ {HB_TAG('c','n','w',' '), HB_TAG('Q','I','N',' ')}, /* Ngawn Chin -> Chin */
+ {HB_TAG('c','o','a',' '), HB_TAG('M','L','Y',' ')}, /* Cocos Islands Malay -> Malay */
+ {HB_TAG('c','o','b',' '), HB_TAG('M','Y','N',' ')}, /* Chicomuceltec -> Mayan */
+/*{HB_TAG('c','o','p',' '), HB_TAG('C','O','P',' ')},*/ /* Coptic */
+ {HB_TAG('c','o','q',' '), HB_TAG('A','T','H',' ')}, /* Coquille -> Athapaskan */
+ {HB_TAG('c','p','a',' '), HB_TAG('C','C','H','N')}, /* Palantla Chinantec -> Chinantec */
+ {HB_TAG('c','p','e',' '), HB_TAG('C','P','P',' ')}, /* English-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','f',' '), HB_TAG('C','P','P',' ')}, /* French-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','i',' '), HB_TAG('C','P','P',' ')}, /* Chinese Pidgin English -> Creoles */
+/*{HB_TAG('c','p','p',' '), HB_TAG('C','P','P',' ')},*/ /* Portuguese-based creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','p','x',' '), HB_TAG('Z','H','S',' ')}, /* Pu-Xian Chinese -> Chinese, Simplified */
+ {HB_TAG('c','q','d',' '), HB_TAG('H','M','N',' ')}, /* Chuanqiandian Cluster Miao -> Hmong */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','H',' ')}, /* Chilean Quechua (retired code) -> Quechua (Bolivia) */
+ {HB_TAG('c','q','u',' '), HB_TAG('Q','U','Z',' ')}, /* Chilean Quechua (retired code) -> Quechua */
+ {HB_TAG('c','r','h',' '), HB_TAG('C','R','T',' ')}, /* Crimean Tatar */
+ {HB_TAG('c','r','i',' '), HB_TAG('C','P','P',' ')}, /* Sãotomense -> Creoles */
+ {HB_TAG('c','r','j',' '), HB_TAG('E','C','R',' ')}, /* Southern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('Y','C','R',' ')}, /* Southern East Cree -> Y-Cree */
+ {HB_TAG('c','r','j',' '), HB_TAG('C','R','E',' ')}, /* Southern East Cree -> Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('W','C','R',' ')}, /* Plains Cree -> West-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('Y','C','R',' ')}, /* Plains Cree -> Y-Cree */
+ {HB_TAG('c','r','k',' '), HB_TAG('C','R','E',' ')}, /* Plains Cree -> Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('E','C','R',' ')}, /* Northern East Cree -> Eastern Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('Y','C','R',' ')}, /* Northern East Cree -> Y-Cree */
+ {HB_TAG('c','r','l',' '), HB_TAG('C','R','E',' ')}, /* Northern East Cree -> Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('M','C','R',' ')}, /* Moose Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('L','C','R',' ')}, /* Moose Cree -> L-Cree */
+ {HB_TAG('c','r','m',' '), HB_TAG('C','R','E',' ')}, /* Moose Cree -> Cree */
+ {HB_TAG('c','r','p',' '), HB_TAG('C','P','P',' ')}, /* Creoles and pidgins [collection] -> Creoles */
+ {HB_TAG('c','r','r',' '), HB_TAG_NONE }, /* Carolina Algonquian != Carrier */
+ {HB_TAG('c','r','s',' '), HB_TAG('C','P','P',' ')}, /* Seselwa Creole French -> Creoles */
+ {HB_TAG('c','r','t',' '), HB_TAG_NONE }, /* Iyojwa'ja Chorote != Crimean Tatar */
+ {HB_TAG('c','r','x',' '), HB_TAG('C','R','R',' ')}, /* Carrier */
+ {HB_TAG('c','r','x',' '), HB_TAG('A','T','H',' ')}, /* Carrier -> Athapaskan */
+ {HB_TAG('c','s','a',' '), HB_TAG('C','C','H','N')}, /* Chiltepec Chinantec -> Chinantec */
+/*{HB_TAG('c','s','b',' '), HB_TAG('C','S','B',' ')},*/ /* Kashubian */
+ {HB_TAG('c','s','h',' '), HB_TAG('Q','I','N',' ')}, /* Asho Chin -> Chin */
+ {HB_TAG('c','s','j',' '), HB_TAG('Q','I','N',' ')}, /* Songlai Chin -> Chin */
+ {HB_TAG('c','s','l',' '), HB_TAG_NONE }, /* Chinese Sign Language != Church Slavonic */
+ {HB_TAG('c','s','o',' '), HB_TAG('C','C','H','N')}, /* Sochiapam Chinantec -> Chinantec */
+ {HB_TAG('c','s','p',' '), HB_TAG('Z','H','S',' ')}, /* Southern Ping Chinese -> Chinese, Simplified */
+ {HB_TAG('c','s','v',' '), HB_TAG('Q','I','N',' ')}, /* Sumtu Chin -> Chin */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','C','R',' ')}, /* Swampy Cree -> N-Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('N','H','C',' ')}, /* Swampy Cree -> Norway House Cree */
+ {HB_TAG('c','s','w',' '), HB_TAG('C','R','E',' ')}, /* Swampy Cree -> Cree */
+ {HB_TAG('c','s','y',' '), HB_TAG('Q','I','N',' ')}, /* Siyin Chin -> Chin */
+ {HB_TAG('c','t','c',' '), HB_TAG('A','T','H',' ')}, /* Chetco -> Athapaskan */
+ {HB_TAG('c','t','d',' '), HB_TAG('Q','I','N',' ')}, /* Tedim Chin -> Chin */
+ {HB_TAG('c','t','e',' '), HB_TAG('C','C','H','N')}, /* Tepinapa Chinantec -> Chinantec */
+/*{HB_TAG('c','t','g',' '), HB_TAG('C','T','G',' ')},*/ /* Chittagonian */
+ {HB_TAG('c','t','h',' '), HB_TAG('Q','I','N',' ')}, /* Thaiphum Chin -> Chin */
+ {HB_TAG('c','t','l',' '), HB_TAG('C','C','H','N')}, /* Tlacoatzintepec Chinantec -> Chinantec */
+ {HB_TAG('c','t','s',' '), HB_TAG('B','I','K',' ')}, /* Northern Catanduanes Bikol -> Bikol */
+/*{HB_TAG('c','t','t',' '), HB_TAG('C','T','T',' ')},*/ /* Wayanad Chetti */
+ {HB_TAG('c','t','u',' '), HB_TAG('M','Y','N',' ')}, /* Chol -> Mayan */
+ {HB_TAG('c','u','c',' '), HB_TAG('C','C','H','N')}, /* Usila Chinantec -> Chinantec */
+/*{HB_TAG('c','u','k',' '), HB_TAG('C','U','K',' ')},*/ /* San Blas Kuna */
+ {HB_TAG('c','v','n',' '), HB_TAG('C','C','H','N')}, /* Valle Nacional Chinantec -> Chinantec */
+ {HB_TAG('c','w','d',' '), HB_TAG('D','C','R',' ')}, /* Woods Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('T','C','R',' ')}, /* Woods Cree -> TH-Cree */
+ {HB_TAG('c','w','d',' '), HB_TAG('C','R','E',' ')}, /* Woods Cree -> Cree */
+ {HB_TAG('c','z','h',' '), HB_TAG('Z','H','S',' ')}, /* Huizhou Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','o',' '), HB_TAG('Z','H','S',' ')}, /* Min Zhong Chinese -> Chinese, Simplified */
+ {HB_TAG('c','z','t',' '), HB_TAG('Q','I','N',' ')}, /* Zotung Chin -> Chin */
+/*{HB_TAG('d','a','g',' '), HB_TAG('D','A','G',' ')},*/ /* Dagbani */
+ {HB_TAG('d','a','o',' '), HB_TAG('Q','I','N',' ')}, /* Daai Chin -> Chin */
+ {HB_TAG('d','a','p',' '), HB_TAG('N','I','S',' ')}, /* Nisi (India) (retired code) */
+/*{HB_TAG('d','a','r',' '), HB_TAG('D','A','R',' ')},*/ /* Dargwa */
+/*{HB_TAG('d','a','x',' '), HB_TAG('D','A','X',' ')},*/ /* Dayi */
+ {HB_TAG('d','c','r',' '), HB_TAG('C','P','P',' ')}, /* Negerhollands -> Creoles */
+ {HB_TAG('d','e','n',' '), HB_TAG('S','L','A',' ')}, /* Slave (Athapascan) [macrolanguage] -> Slavey */
+ {HB_TAG('d','e','n',' '), HB_TAG('A','T','H',' ')}, /* Slave (Athapascan) [macrolanguage] -> Athapaskan */
+ {HB_TAG('d','e','p',' '), HB_TAG('C','P','P',' ')}, /* Pidgin Delaware -> Creoles */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','O',' ')}, /* Dogri (individual language) */
+ {HB_TAG('d','g','o',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) */
+ {HB_TAG('d','g','r',' '), HB_TAG('A','T','H',' ')}, /* Dogrib -> Athapaskan */
+ {HB_TAG('d','h','d',' '), HB_TAG('M','A','W',' ')}, /* Dhundari -> Marwari */
+/*{HB_TAG('d','h','g',' '), HB_TAG('D','H','G',' ')},*/ /* Dhangu */
+ {HB_TAG('d','h','v',' '), HB_TAG_NONE }, /* Dehu != Divehi (Dhivehi, Maldivian) (deprecated) */
+ {HB_TAG('d','i','b',' '), HB_TAG('D','N','K',' ')}, /* South Central Dinka -> Dinka */
+ {HB_TAG('d','i','k',' '), HB_TAG('D','N','K',' ')}, /* Southwestern Dinka -> Dinka */
+ {HB_TAG('d','i','n',' '), HB_TAG('D','N','K',' ')}, /* Dinka [macrolanguage] */
+ {HB_TAG('d','i','p',' '), HB_TAG('D','N','K',' ')}, /* Northeastern Dinka -> Dinka */
+ {HB_TAG('d','i','q',' '), HB_TAG('D','I','Q',' ')}, /* Dimli */
+ {HB_TAG('d','i','q',' '), HB_TAG('Z','Z','A',' ')}, /* Dimli -> Zazaki */
+ {HB_TAG('d','i','w',' '), HB_TAG('D','N','K',' ')}, /* Northwestern Dinka -> Dinka */
+ {HB_TAG('d','j','e',' '), HB_TAG('D','J','R',' ')}, /* Zarma */
+ {HB_TAG('d','j','k',' '), HB_TAG('C','P','P',' ')}, /* Eastern Maroon Creole -> Creoles */
+ {HB_TAG('d','j','r',' '), HB_TAG('D','J','R','0')}, /* Djambarrpuyngu */
+ {HB_TAG('d','k','s',' '), HB_TAG('D','N','K',' ')}, /* Southeastern Dinka -> Dinka */
+ {HB_TAG('d','n','g',' '), HB_TAG('D','U','N',' ')}, /* Dungan */
+/*{HB_TAG('d','n','j',' '), HB_TAG('D','N','J',' ')},*/ /* Dan */
+ {HB_TAG('d','n','k',' '), HB_TAG_NONE }, /* Dengka != Dinka */
+ {HB_TAG('d','o','i',' '), HB_TAG('D','G','R',' ')}, /* Dogri (macrolanguage) [macrolanguage] */
+ {HB_TAG('d','r','h',' '), HB_TAG('M','N','G',' ')}, /* Darkhat (retired code) -> Mongolian */
+ {HB_TAG('d','r','i',' '), HB_TAG_NONE }, /* C'Lela != Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('D','R','I',' ')}, /* Darwazi (retired code) -> Dari */
+ {HB_TAG('d','r','w',' '), HB_TAG('F','A','R',' ')}, /* Darwazi (retired code) -> Persian */
+ {HB_TAG('d','s','b',' '), HB_TAG('L','S','B',' ')}, /* Lower Sorbian */
+ {HB_TAG('d','t','y',' '), HB_TAG('N','E','P',' ')}, /* Dotyali -> Nepali */
+/*{HB_TAG('d','u','j',' '), HB_TAG('D','U','J',' ')},*/ /* Dhuwal (retired code) */
+ {HB_TAG('d','u','n',' '), HB_TAG_NONE }, /* Dusun Deyah != Dungan */
+ {HB_TAG('d','u','p',' '), HB_TAG('M','L','Y',' ')}, /* Duano -> Malay */
+ {HB_TAG('d','w','k',' '), HB_TAG('K','U','I',' ')}, /* Dawik Kui -> Kui */
+ {HB_TAG('d','w','u',' '), HB_TAG('D','U','J',' ')}, /* Dhuwal */
+ {HB_TAG('d','w','y',' '), HB_TAG('D','U','J',' ')}, /* Dhuwaya -> Dhuwal */
+ {HB_TAG('d','y','u',' '), HB_TAG('J','U','L',' ')}, /* Dyula -> Jula */
+ {HB_TAG('d','z','n',' '), HB_TAG_NONE }, /* Dzando != Dzongkha */
+ {HB_TAG('e','c','r',' '), HB_TAG_NONE }, /* Eteocretan != Eastern Cree */
+/*{HB_TAG('e','f','i',' '), HB_TAG('E','F','I',' ')},*/ /* Efik */
+ {HB_TAG('e','k','k',' '), HB_TAG('E','T','I',' ')}, /* Standard Estonian -> Estonian */
+ {HB_TAG('e','k','y',' '), HB_TAG('K','R','N',' ')}, /* Eastern Kayah -> Karen */
+ {HB_TAG('e','m','k',' '), HB_TAG('E','M','K',' ')}, /* Eastern Maninkakan */
+ {HB_TAG('e','m','k',' '), HB_TAG('M','N','K',' ')}, /* Eastern Maninkakan -> Maninka */
+ {HB_TAG('e','m','y',' '), HB_TAG('M','Y','N',' ')}, /* Epigraphic Mayan -> Mayan */
+ {HB_TAG('e','n','b',' '), HB_TAG('K','A','L',' ')}, /* Markweeta -> Kalenjin */
+ {HB_TAG('e','n','f',' '), HB_TAG('F','N','E',' ')}, /* Forest Enets */
+ {HB_TAG('e','n','h',' '), HB_TAG('T','N','E',' ')}, /* Tundra Enets */
+ {HB_TAG('e','s','g',' '), HB_TAG('G','O','N',' ')}, /* Aheri Gondi -> Gondi */
+ {HB_TAG('e','s','i',' '), HB_TAG('I','P','K',' ')}, /* North Alaskan Inupiatun -> Inupiat */
+ {HB_TAG('e','s','k',' '), HB_TAG('I','P','K',' ')}, /* Northwest Alaska Inupiatun -> Inupiat */
+/*{HB_TAG('e','s','u',' '), HB_TAG('E','S','U',' ')},*/ /* Central Yupik */
+ {HB_TAG('e','t','o',' '), HB_TAG('B','T','I',' ')}, /* Eton (Cameroon) -> Beti */
+ {HB_TAG('e','u','q',' '), HB_TAG_NONE }, /* Basque [collection] != Basque */
+ {HB_TAG('e','v','e',' '), HB_TAG('E','V','N',' ')}, /* Even */
+ {HB_TAG('e','v','n',' '), HB_TAG('E','V','K',' ')}, /* Evenki */
+ {HB_TAG('e','w','o',' '), HB_TAG('B','T','I',' ')}, /* Ewondo -> Beti */
+ {HB_TAG('e','y','o',' '), HB_TAG('K','A','L',' ')}, /* Keiyo -> Kalenjin */
+ {HB_TAG('f','a','b',' '), HB_TAG('C','P','P',' ')}, /* Fa d'Ambu -> Creoles */
+ {HB_TAG('f','a','n',' '), HB_TAG('F','A','N','0')}, /* Fang (Equatorial Guinea) */
+ {HB_TAG('f','a','n',' '), HB_TAG('B','T','I',' ')}, /* Fang (Equatorial Guinea) -> Beti */
+ {HB_TAG('f','a','r',' '), HB_TAG_NONE }, /* Fataleka != Persian */
+ {HB_TAG('f','a','t',' '), HB_TAG('F','A','T',' ')}, /* Fanti */
+ {HB_TAG('f','a','t',' '), HB_TAG('A','K','A',' ')}, /* Fanti -> Akan */
+ {HB_TAG('f','b','l',' '), HB_TAG('B','I','K',' ')}, /* West Albay Bikol -> Bikol */
+ {HB_TAG('f','f','m',' '), HB_TAG('F','U','L',' ')}, /* Maasina Fulfulde -> Fulah */
+ {HB_TAG('f','i','l',' '), HB_TAG('P','I','L',' ')}, /* Filipino */
+ {HB_TAG('f','l','m',' '), HB_TAG('H','A','L',' ')}, /* Halam (Falam Chin) (retired code) */
+ {HB_TAG('f','l','m',' '), HB_TAG('Q','I','N',' ')}, /* Falam Chin (retired code) -> Chin */
+ {HB_TAG('f','m','p',' '), HB_TAG('F','M','P',' ')}, /* Fe’fe’ */
+ {HB_TAG('f','m','p',' '), HB_TAG('B','M','L',' ')}, /* Fe'fe' -> Bamileke */
+ {HB_TAG('f','n','g',' '), HB_TAG('C','P','P',' ')}, /* Fanagalo -> Creoles */
+/*{HB_TAG('f','o','n',' '), HB_TAG('F','O','N',' ')},*/ /* Fon */
+ {HB_TAG('f','o','s',' '), HB_TAG_NONE }, /* Siraya != Faroese */
+ {HB_TAG('f','p','e',' '), HB_TAG('C','P','P',' ')}, /* Fernando Po Creole English -> Creoles */
+/*{HB_TAG('f','r','c',' '), HB_TAG('F','R','C',' ')},*/ /* Cajun French */
+/*{HB_TAG('f','r','p',' '), HB_TAG('F','R','P',' ')},*/ /* Arpitan */
+ {HB_TAG('f','u','b',' '), HB_TAG('F','U','L',' ')}, /* Adamawa Fulfulde -> Fulah */
+ {HB_TAG('f','u','c',' '), HB_TAG('F','U','L',' ')}, /* Pulaar -> Fulah */
+ {HB_TAG('f','u','e',' '), HB_TAG('F','U','L',' ')}, /* Borgu Fulfulde -> Fulah */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','T','A',' ')}, /* Pular -> Futa */
+ {HB_TAG('f','u','f',' '), HB_TAG('F','U','L',' ')}, /* Pular -> Fulah */
+ {HB_TAG('f','u','h',' '), HB_TAG('F','U','L',' ')}, /* Western Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','i',' '), HB_TAG('F','U','L',' ')}, /* Bagirmi Fulfulde -> Fulah */
+ {HB_TAG('f','u','q',' '), HB_TAG('F','U','L',' ')}, /* Central-Eastern Niger Fulfulde -> Fulah */
+ {HB_TAG('f','u','r',' '), HB_TAG('F','R','L',' ')}, /* Friulian */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','V',' ')}, /* Nigerian Fulfulde */
+ {HB_TAG('f','u','v',' '), HB_TAG('F','U','L',' ')}, /* Nigerian Fulfulde -> Fulah */
+ {HB_TAG('g','a','a',' '), HB_TAG('G','A','D',' ')}, /* Ga */
+ {HB_TAG('g','a','c',' '), HB_TAG('C','P','P',' ')}, /* Mixed Great Andamanese -> Creoles */
+ {HB_TAG('g','a','d',' '), HB_TAG_NONE }, /* Gaddang != Ga */
+ {HB_TAG('g','a','e',' '), HB_TAG_NONE }, /* Guarequena != Scottish Gaelic (Gaelic) */
+/*{HB_TAG('g','a','g',' '), HB_TAG('G','A','G',' ')},*/ /* Gagauz */
+ {HB_TAG('g','a','l',' '), HB_TAG_NONE }, /* Galolen != Galician */
+ {HB_TAG('g','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Gan Chinese -> Chinese, Simplified */
+ {HB_TAG('g','a','r',' '), HB_TAG_NONE }, /* Galeya != Garshuni */
+ {HB_TAG('g','a','w',' '), HB_TAG_NONE }, /* Nobonob != Garhwali */
+ {HB_TAG('g','a','x',' '), HB_TAG('O','R','O',' ')}, /* Borana-Arsi-Guji Oromo -> Oromo */
+ {HB_TAG('g','a','z',' '), HB_TAG('O','R','O',' ')}, /* West Central Oromo -> Oromo */
+ {HB_TAG('g','b','m',' '), HB_TAG('G','A','W',' ')}, /* Garhwali */
+ {HB_TAG('g','c','e',' '), HB_TAG('A','T','H',' ')}, /* Galice -> Athapaskan */
+ {HB_TAG('g','c','f',' '), HB_TAG('C','P','P',' ')}, /* Guadeloupean Creole French -> Creoles */
+ {HB_TAG('g','c','l',' '), HB_TAG('C','P','P',' ')}, /* Grenadian Creole English -> Creoles */
+ {HB_TAG('g','c','r',' '), HB_TAG('C','P','P',' ')}, /* Guianese Creole French -> Creoles */
+ {HB_TAG('g','d','a',' '), HB_TAG('R','A','J',' ')}, /* Gade Lohar -> Rajasthani */
+/*{HB_TAG('g','e','z',' '), HB_TAG('G','E','Z',' ')},*/ /* Geez */
+ {HB_TAG('g','g','o',' '), HB_TAG('G','O','N',' ')}, /* Southern Gondi (retired code) -> Gondi */
+ {HB_TAG('g','h','a',' '), HB_TAG('B','B','R',' ')}, /* Ghadamès -> Berber */
+ {HB_TAG('g','h','k',' '), HB_TAG('K','R','N',' ')}, /* Geko Karen -> Karen */
+ {HB_TAG('g','h','o',' '), HB_TAG('B','B','R',' ')}, /* Ghomara -> Berber */
+ {HB_TAG('g','i','b',' '), HB_TAG('C','P','P',' ')}, /* Gibanawa -> Creoles */
+/*{HB_TAG('g','i','h',' '), HB_TAG('G','I','H',' ')},*/ /* Githabul */
+ {HB_TAG('g','i','l',' '), HB_TAG('G','I','L','0')}, /* Kiribati (Gilbertese) */
+ {HB_TAG('g','j','u',' '), HB_TAG('R','A','J',' ')}, /* Gujari -> Rajasthani */
+ {HB_TAG('g','k','p',' '), HB_TAG('G','K','P',' ')}, /* Guinea Kpelle -> Kpelle (Guinea) */
+ {HB_TAG('g','k','p',' '), HB_TAG('K','P','L',' ')}, /* Guinea Kpelle -> Kpelle */
+ {HB_TAG('g','l','d',' '), HB_TAG('N','A','N',' ')}, /* Nanai */
+/*{HB_TAG('g','l','k',' '), HB_TAG('G','L','K',' ')},*/ /* Gilaki */
+ {HB_TAG('g','m','z',' '), HB_TAG_NONE }, /* Mgbolizhia != Gumuz */
+ {HB_TAG('g','n','b',' '), HB_TAG('Q','I','N',' ')}, /* Gangte -> Chin */
+/*{HB_TAG('g','n','n',' '), HB_TAG('G','N','N',' ')},*/ /* Gumatj */
+ {HB_TAG('g','n','o',' '), HB_TAG('G','O','N',' ')}, /* Northern Gondi -> Gondi */
+ {HB_TAG('g','n','w',' '), HB_TAG('G','U','A',' ')}, /* Western Bolivian Guaraní -> Guarani */
+/*{HB_TAG('g','o','g',' '), HB_TAG('G','O','G',' ')},*/ /* Gogo */
+ {HB_TAG('g','o','m',' '), HB_TAG('K','O','K',' ')}, /* Goan Konkani -> Konkani */
+/*{HB_TAG('g','o','n',' '), HB_TAG('G','O','N',' ')},*/ /* Gondi [macrolanguage] */
+ {HB_TAG('g','o','q',' '), HB_TAG('C','P','P',' ')}, /* Gorap -> Creoles */
+ {HB_TAG('g','o','x',' '), HB_TAG('B','A','D','0')}, /* Gobu -> Banda */
+ {HB_TAG('g','p','e',' '), HB_TAG('C','P','P',' ')}, /* Ghanaian Pidgin English -> Creoles */
+ {HB_TAG('g','r','o',' '), HB_TAG_NONE }, /* Groma != Garo */
+ {HB_TAG('g','r','r',' '), HB_TAG('B','B','R',' ')}, /* Taznatit -> Berber */
+ {HB_TAG('g','r','t',' '), HB_TAG('G','R','O',' ')}, /* Garo */
+ {HB_TAG('g','r','u',' '), HB_TAG('S','O','G',' ')}, /* Kistane -> Sodo Gurage */
+ {HB_TAG('g','s','w',' '), HB_TAG('A','L','S',' ')}, /* Alsatian */
+ {HB_TAG('g','u','a',' '), HB_TAG_NONE }, /* Shiki != Guarani */
+/*{HB_TAG('g','u','c',' '), HB_TAG('G','U','C',' ')},*/ /* Wayuu */
+/*{HB_TAG('g','u','f',' '), HB_TAG('G','U','F',' ')},*/ /* Gupapuyngu */
+ {HB_TAG('g','u','g',' '), HB_TAG('G','U','A',' ')}, /* Paraguayan Guaraní -> Guarani */
+ {HB_TAG('g','u','i',' '), HB_TAG('G','U','A',' ')}, /* Eastern Bolivian Guaraní -> Guarani */
+ {HB_TAG('g','u','k',' '), HB_TAG('G','M','Z',' ')}, /* Gumuz */
+ {HB_TAG('g','u','l',' '), HB_TAG('C','P','P',' ')}, /* Sea Island Creole English -> Creoles */
+ {HB_TAG('g','u','n',' '), HB_TAG('G','U','A',' ')}, /* Mbyá Guaraní -> Guarani */
+/*{HB_TAG('g','u','z',' '), HB_TAG('G','U','Z',' ')},*/ /* Gusii */
+ {HB_TAG('g','w','i',' '), HB_TAG('A','T','H',' ')}, /* Gwichʼin -> Athapaskan */
+ {HB_TAG('g','y','n',' '), HB_TAG('C','P','P',' ')}, /* Guyanese Creole English -> Creoles */
+ {HB_TAG('h','a','a',' '), HB_TAG('A','T','H',' ')}, /* Han -> Athapaskan */
+ {HB_TAG('h','a','e',' '), HB_TAG('O','R','O',' ')}, /* Eastern Oromo -> Oromo */
+ {HB_TAG('h','a','i',' '), HB_TAG('H','A','I','0')}, /* Haida [macrolanguage] */
+ {HB_TAG('h','a','k',' '), HB_TAG('Z','H','S',' ')}, /* Hakka Chinese -> Chinese, Simplified */
+ {HB_TAG('h','a','l',' '), HB_TAG_NONE }, /* Halang != Halam (Falam Chin) */
+ {HB_TAG('h','a','r',' '), HB_TAG('H','R','I',' ')}, /* Harari */
+/*{HB_TAG('h','a','w',' '), HB_TAG('H','A','W',' ')},*/ /* Hawaiian */
+ {HB_TAG('h','a','x',' '), HB_TAG('H','A','I','0')}, /* Southern Haida -> Haida */
+/*{HB_TAG('h','a','y',' '), HB_TAG('H','A','Y',' ')},*/ /* Haya */
+/*{HB_TAG('h','a','z',' '), HB_TAG('H','A','Z',' ')},*/ /* Hazaragi */
+ {HB_TAG('h','b','n',' '), HB_TAG_NONE }, /* Heiban != Hammer-Banna */
+ {HB_TAG('h','c','a',' '), HB_TAG('C','P','P',' ')}, /* Andaman Creole Hindi -> Creoles */
+ {HB_TAG('h','d','n',' '), HB_TAG('H','A','I','0')}, /* Northern Haida -> Haida */
+ {HB_TAG('h','e','a',' '), HB_TAG('H','M','N',' ')}, /* Northern Qiandong Miao -> Hmong */
+/*{HB_TAG('h','e','i',' '), HB_TAG('H','E','I',' ')},*/ /* Heiltsuk */
+/*{HB_TAG('h','i','l',' '), HB_TAG('H','I','L',' ')},*/ /* Hiligaynon */
+ {HB_TAG('h','j','i',' '), HB_TAG('M','L','Y',' ')}, /* Haji -> Malay */
+ {HB_TAG('h','l','t',' '), HB_TAG('Q','I','N',' ')}, /* Matu Chin -> Chin */
+ {HB_TAG('h','m','a',' '), HB_TAG('H','M','N',' ')}, /* Southern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','c',' '), HB_TAG('H','M','N',' ')}, /* Central Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','D',' ')}, /* Large Flowery Miao -> A-Hmao */
+ {HB_TAG('h','m','d',' '), HB_TAG('H','M','N',' ')}, /* Large Flowery Miao -> Hmong */
+ {HB_TAG('h','m','e',' '), HB_TAG('H','M','N',' ')}, /* Eastern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','g',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','h',' '), HB_TAG('H','M','N',' ')}, /* Southwestern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','i',' '), HB_TAG('H','M','N',' ')}, /* Northern Huishui Hmong -> Hmong */
+ {HB_TAG('h','m','j',' '), HB_TAG('H','M','N',' ')}, /* Ge -> Hmong */
+ {HB_TAG('h','m','l',' '), HB_TAG('H','M','N',' ')}, /* Luopohe Hmong -> Hmong */
+ {HB_TAG('h','m','m',' '), HB_TAG('H','M','N',' ')}, /* Central Mashan Hmong -> Hmong */
+/*{HB_TAG('h','m','n',' '), HB_TAG('H','M','N',' ')},*/ /* Hmong [macrolanguage] */
+ {HB_TAG('h','m','p',' '), HB_TAG('H','M','N',' ')}, /* Northern Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','r',' '), HB_TAG('Q','I','N',' ')}, /* Hmar -> Chin */
+ {HB_TAG('h','m','s',' '), HB_TAG('H','M','N',' ')}, /* Southern Qiandong Miao -> Hmong */
+ {HB_TAG('h','m','w',' '), HB_TAG('H','M','N',' ')}, /* Western Mashan Hmong -> Hmong */
+ {HB_TAG('h','m','y',' '), HB_TAG('H','M','N',' ')}, /* Southern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','Z',' ')}, /* Hmong Shua -> Hmong Shuat */
+ {HB_TAG('h','m','z',' '), HB_TAG('H','M','N',' ')}, /* Hmong Shua -> Hmong */
+/*{HB_TAG('h','n','d',' '), HB_TAG('H','N','D',' ')},*/ /* Southern Hindko -> Hindko */
+ {HB_TAG('h','n','e',' '), HB_TAG('C','H','H',' ')}, /* Chhattisgarhi -> Chattisgarhi */
+ {HB_TAG('h','n','j',' '), HB_TAG('H','M','N',' ')}, /* Hmong Njua -> Hmong */
+ {HB_TAG('h','n','o',' '), HB_TAG('H','N','D',' ')}, /* Northern Hindko -> Hindko */
+ {HB_TAG('h','o','c',' '), HB_TAG('H','O',' ',' ')}, /* Ho */
+ {HB_TAG('h','o','i',' '), HB_TAG('A','T','H',' ')}, /* Holikachuk -> Athapaskan */
+ {HB_TAG('h','o','j',' '), HB_TAG('H','A','R',' ')}, /* Hadothi -> Harauti */
+ {HB_TAG('h','o','j',' '), HB_TAG('R','A','J',' ')}, /* Hadothi -> Rajasthani */
+ {HB_TAG('h','r','a',' '), HB_TAG('Q','I','N',' ')}, /* Hrangkhol -> Chin */
+ {HB_TAG('h','r','m',' '), HB_TAG('H','M','N',' ')}, /* Horned Miao -> Hmong */
+ {HB_TAG('h','s','b',' '), HB_TAG('U','S','B',' ')}, /* Upper Sorbian */
+ {HB_TAG('h','s','n',' '), HB_TAG('Z','H','S',' ')}, /* Xiang Chinese -> Chinese, Simplified */
+ {HB_TAG('h','u','j',' '), HB_TAG('H','M','N',' ')}, /* Northern Guiyang Hmong -> Hmong */
+ {HB_TAG('h','u','p',' '), HB_TAG('A','T','H',' ')}, /* Hupa -> Athapaskan */
+ {HB_TAG('h','u','s',' '), HB_TAG('M','Y','N',' ')}, /* Huastec -> Mayan */
+ {HB_TAG('h','w','c',' '), HB_TAG('C','P','P',' ')}, /* Hawai'i Creole English -> Creoles */
+ {HB_TAG('h','y','w',' '), HB_TAG('H','Y','E',' ')}, /* Western Armenian -> Armenian */
+/*{HB_TAG('i','b','a',' '), HB_TAG('I','B','A',' ')},*/ /* Iban */
+/*{HB_TAG('i','b','b',' '), HB_TAG('I','B','B',' ')},*/ /* Ibibio */
+ {HB_TAG('i','b','y',' '), HB_TAG('I','J','O',' ')}, /* Ibani -> Ijo */
+ {HB_TAG('i','c','r',' '), HB_TAG('C','P','P',' ')}, /* Islander Creole English -> Creoles */
+ {HB_TAG('i','d','a',' '), HB_TAG('L','U','H',' ')}, /* Idakho-Isukha-Tiriki -> Luyia */
+ {HB_TAG('i','d','b',' '), HB_TAG('C','P','P',' ')}, /* Indo-Portuguese -> Creoles */
+ {HB_TAG('i','g','b',' '), HB_TAG('E','B','I',' ')}, /* Ebira */
+ {HB_TAG('i','h','b',' '), HB_TAG('C','P','P',' ')}, /* Iha Based Pidgin -> Creoles */
+ {HB_TAG('i','j','c',' '), HB_TAG('I','J','O',' ')}, /* Izon -> Ijo */
+ {HB_TAG('i','j','e',' '), HB_TAG('I','J','O',' ')}, /* Biseni -> Ijo */
+ {HB_TAG('i','j','n',' '), HB_TAG('I','J','O',' ')}, /* Kalabari -> Ijo */
+/*{HB_TAG('i','j','o',' '), HB_TAG('I','J','O',' ')},*/ /* Ijo [collection] */
+ {HB_TAG('i','j','s',' '), HB_TAG('I','J','O',' ')}, /* Southeast Ijo -> Ijo */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U',' ')}, /* Eastern Canadian Inuktitut -> Inuktitut */
+ {HB_TAG('i','k','e',' '), HB_TAG('I','N','U','K')}, /* Eastern Canadian Inuktitut -> Nunavik Inuktitut */
+ {HB_TAG('i','k','t',' '), HB_TAG('I','N','U',' ')}, /* Inuinnaqtun -> Inuktitut */
+/*{HB_TAG('i','l','o',' '), HB_TAG('I','L','O',' ')},*/ /* Iloko -> Ilokano */
+ {HB_TAG('i','n','g',' '), HB_TAG('A','T','H',' ')}, /* Degexit'an -> Athapaskan */
+ {HB_TAG('i','n','h',' '), HB_TAG('I','N','G',' ')}, /* Ingush */
+ {HB_TAG('i','r','i',' '), HB_TAG_NONE }, /* Rigwe != Irish */
+/*{HB_TAG('i','r','u',' '), HB_TAG('I','R','U',' ')},*/ /* Irula */
+ {HB_TAG('i','s','m',' '), HB_TAG_NONE }, /* Masimasi != Inari Sami */
+ {HB_TAG('i','t','z',' '), HB_TAG('M','Y','N',' ')}, /* Itzá -> Mayan */
+ {HB_TAG('i','x','l',' '), HB_TAG('M','Y','N',' ')}, /* Ixil -> Mayan */
+ {HB_TAG('j','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Popti' -> Mayan */
+ {HB_TAG('j','a','k',' '), HB_TAG('M','L','Y',' ')}, /* Jakun -> Malay */
+ {HB_TAG('j','a','m',' '), HB_TAG('J','A','M',' ')}, /* Jamaican Creole English -> Jamaican Creole */
+ {HB_TAG('j','a','m',' '), HB_TAG('C','P','P',' ')}, /* Jamaican Creole English -> Creoles */
+ {HB_TAG('j','a','n',' '), HB_TAG_NONE }, /* Jandai != Japanese */
+ {HB_TAG('j','a','x',' '), HB_TAG('M','L','Y',' ')}, /* Jambi Malay -> Malay */
+ {HB_TAG('j','b','e',' '), HB_TAG('B','B','R',' ')}, /* Judeo-Berber -> Berber */
+ {HB_TAG('j','b','n',' '), HB_TAG('B','B','R',' ')}, /* Nafusi -> Berber */
+/*{HB_TAG('j','b','o',' '), HB_TAG('J','B','O',' ')},*/ /* Lojban */
+/*{HB_TAG('j','c','t',' '), HB_TAG('J','C','T',' ')},*/ /* Krymchak */
+ {HB_TAG('j','g','o',' '), HB_TAG('B','M','L',' ')}, /* Ngomba -> Bamileke */
+ {HB_TAG('j','i','i',' '), HB_TAG_NONE }, /* Jiiddu != Yiddish */
+ {HB_TAG('j','k','m',' '), HB_TAG('K','R','N',' ')}, /* Mobwa Karen -> Karen */
+ {HB_TAG('j','k','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen -> Karen */
+ {HB_TAG('j','u','d',' '), HB_TAG_NONE }, /* Worodougou != Ladino */
+ {HB_TAG('j','u','l',' '), HB_TAG_NONE }, /* Jirel != Jula */
+ {HB_TAG('j','v','d',' '), HB_TAG('C','P','P',' ')}, /* Javindo -> Creoles */
+ {HB_TAG('k','a','a',' '), HB_TAG('K','R','K',' ')}, /* Karakalpak */
+ {HB_TAG('k','a','b',' '), HB_TAG('K','A','B','0')}, /* Kabyle */
+ {HB_TAG('k','a','b',' '), HB_TAG('B','B','R',' ')}, /* Kabyle -> Berber */
+ {HB_TAG('k','a','c',' '), HB_TAG_NONE }, /* Kachin != Kachchi */
+ {HB_TAG('k','a','m',' '), HB_TAG('K','M','B',' ')}, /* Kamba (Kenya) */
+ {HB_TAG('k','a','r',' '), HB_TAG('K','R','N',' ')}, /* Karen [collection] */
+/*{HB_TAG('k','a','w',' '), HB_TAG('K','A','W',' ')},*/ /* Kawi (Old Javanese) */
+ {HB_TAG('k','b','d',' '), HB_TAG('K','A','B',' ')}, /* Kabardian */
+ {HB_TAG('k','b','y',' '), HB_TAG('K','N','R',' ')}, /* Manga Kanuri -> Kanuri */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','K',' ')}, /* Khanty -> Khanty-Kazim */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','S',' ')}, /* Khanty -> Khanty-Shurishkar */
+ {HB_TAG('k','c','a',' '), HB_TAG('K','H','V',' ')}, /* Khanty -> Khanty-Vakhi */
+ {HB_TAG('k','c','n',' '), HB_TAG('C','P','P',' ')}, /* Nubi -> Creoles */
+/*{HB_TAG('k','d','e',' '), HB_TAG('K','D','E',' ')},*/ /* Makonde */
+ {HB_TAG('k','d','r',' '), HB_TAG('K','R','M',' ')}, /* Karaim */
+ {HB_TAG('k','d','t',' '), HB_TAG('K','U','Y',' ')}, /* Kuy */
+ {HB_TAG('k','e','a',' '), HB_TAG('K','E','A',' ')}, /* Kabuverdianu (Crioulo) */
+ {HB_TAG('k','e','a',' '), HB_TAG('C','P','P',' ')}, /* Kabuverdianu -> Creoles */
+ {HB_TAG('k','e','b',' '), HB_TAG_NONE }, /* Kélé != Kebena */
+ {HB_TAG('k','e','k',' '), HB_TAG('K','E','K',' ')}, /* Kekchi */
+ {HB_TAG('k','e','k',' '), HB_TAG('M','Y','N',' ')}, /* Kekchí -> Mayan */
+ {HB_TAG('k','e','x',' '), HB_TAG('K','K','N',' ')}, /* Kukna -> Kokni */
+ {HB_TAG('k','f','a',' '), HB_TAG('K','O','D',' ')}, /* Kodava -> Kodagu */
+ {HB_TAG('k','f','r',' '), HB_TAG('K','A','C',' ')}, /* Kachhi -> Kachchi */
+ {HB_TAG('k','f','x',' '), HB_TAG('K','U','L',' ')}, /* Kullu Pahari -> Kulvi */
+ {HB_TAG('k','f','y',' '), HB_TAG('K','M','N',' ')}, /* Kumaoni */
+ {HB_TAG('k','g','e',' '), HB_TAG_NONE }, /* Komering != Khutsuri Georgian */
+ {HB_TAG('k','h','a',' '), HB_TAG('K','S','I',' ')}, /* Khasi */
+ {HB_TAG('k','h','b',' '), HB_TAG('X','B','D',' ')}, /* Lü */
+ {HB_TAG('k','h','k',' '), HB_TAG('M','N','G',' ')}, /* Halh Mongolian -> Mongolian */
+ {HB_TAG('k','h','n',' '), HB_TAG_NONE }, /* Khandesi != Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','s',' '), HB_TAG_NONE }, /* Kasua != Khanty-Shurishkar */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','T',' ')}, /* Khamti -> Khamti Shan */
+ {HB_TAG('k','h','t',' '), HB_TAG('K','H','N',' ')}, /* Khamti -> Khamti Shan (Microsoft fonts) */
+ {HB_TAG('k','h','v',' '), HB_TAG_NONE }, /* Khvarshi != Khanty-Vakhi */
+/*{HB_TAG('k','h','w',' '), HB_TAG('K','H','W',' ')},*/ /* Khowar */
+ {HB_TAG('k','i','s',' '), HB_TAG_NONE }, /* Kis != Kisii */
+ {HB_TAG('k','i','u',' '), HB_TAG('K','I','U',' ')}, /* Kirmanjki */
+ {HB_TAG('k','i','u',' '), HB_TAG('Z','Z','A',' ')}, /* Kirmanjki -> Zazaki */
+ {HB_TAG('k','j','b',' '), HB_TAG('M','Y','N',' ')}, /* Q'anjob'al -> Mayan */
+/*{HB_TAG('k','j','d',' '), HB_TAG('K','J','D',' ')},*/ /* Southern Kiwai */
+ {HB_TAG('k','j','h',' '), HB_TAG('K','H','A',' ')}, /* Khakas -> Khakass */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','J','P',' ')}, /* Pwo Eastern Karen -> Eastern Pwo Karen */
+ {HB_TAG('k','j','p',' '), HB_TAG('K','R','N',' ')}, /* Pwo Eastern Karen -> Karen */
+ {HB_TAG('k','j','t',' '), HB_TAG('K','R','N',' ')}, /* Phrae Pwo Karen -> Karen */
+/*{HB_TAG('k','j','z',' '), HB_TAG('K','J','Z',' ')},*/ /* Bumthangkha */
+ {HB_TAG('k','k','n',' '), HB_TAG_NONE }, /* Kon Keu != Kokni */
+ {HB_TAG('k','k','z',' '), HB_TAG('A','T','H',' ')}, /* Kaska -> Athapaskan */
+ {HB_TAG('k','l','m',' '), HB_TAG_NONE }, /* Migum != Kalmyk */
+ {HB_TAG('k','l','n',' '), HB_TAG('K','A','L',' ')}, /* Kalenjin [macrolanguage] */
+ {HB_TAG('k','m','b',' '), HB_TAG('M','B','N',' ')}, /* Kimbundu -> Mbundu */
+ {HB_TAG('k','m','n',' '), HB_TAG_NONE }, /* Awtuw != Kumaoni */
+ {HB_TAG('k','m','o',' '), HB_TAG_NONE }, /* Kwoma != Komo */
+ {HB_TAG('k','m','r',' '), HB_TAG('K','U','R',' ')}, /* Northern Kurdish -> Kurdish */
+ {HB_TAG('k','m','s',' '), HB_TAG_NONE }, /* Kamasau != Komso */
+ {HB_TAG('k','m','v',' '), HB_TAG('C','P','P',' ')}, /* Karipúna Creole French -> Creoles */
+ {HB_TAG('k','m','w',' '), HB_TAG('K','M','O',' ')}, /* Komo (Democratic Republic of Congo) */
+/*{HB_TAG('k','m','z',' '), HB_TAG('K','M','Z',' ')},*/ /* Khorasani Turkish -> Khorasani Turkic */
+ {HB_TAG('k','n','c',' '), HB_TAG('K','N','R',' ')}, /* Central Kanuri -> Kanuri */
+ {HB_TAG('k','n','g',' '), HB_TAG('K','O','N','0')}, /* Koongo -> Kongo */
+ {HB_TAG('k','n','j',' '), HB_TAG('M','Y','N',' ')}, /* Western Kanjobal -> Mayan */
+ {HB_TAG('k','n','n',' '), HB_TAG('K','O','K',' ')}, /* Konkani */
+ {HB_TAG('k','n','r',' '), HB_TAG_NONE }, /* Kaningra != Kanuri */
+ {HB_TAG('k','o','d',' '), HB_TAG_NONE }, /* Kodi != Kodagu */
+ {HB_TAG('k','o','h',' '), HB_TAG_NONE }, /* Koyo != Korean Old Hangul */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','P',' ')}, /* Komi-Permyak */
+ {HB_TAG('k','o','i',' '), HB_TAG('K','O','M',' ')}, /* Komi-Permyak -> Komi */
+/*{HB_TAG('k','o','k',' '), HB_TAG('K','O','K',' ')},*/ /* Konkani [macrolanguage] */
+ {HB_TAG('k','o','p',' '), HB_TAG_NONE }, /* Waube != Komi-Permyak */
+/*{HB_TAG('k','o','s',' '), HB_TAG('K','O','S',' ')},*/ /* Kosraean */
+ {HB_TAG('k','o','y',' '), HB_TAG('A','T','H',' ')}, /* Koyukon -> Athapaskan */
+ {HB_TAG('k','o','z',' '), HB_TAG_NONE }, /* Korak != Komi-Zyrian */
+ {HB_TAG('k','p','e',' '), HB_TAG('K','P','L',' ')}, /* Kpelle [macrolanguage] */
+ {HB_TAG('k','p','l',' '), HB_TAG_NONE }, /* Kpala != Kpelle */
+ {HB_TAG('k','p','p',' '), HB_TAG('K','R','N',' ')}, /* Paku Karen (retired code) -> Karen */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','Z',' ')}, /* Komi-Zyrian */
+ {HB_TAG('k','p','v',' '), HB_TAG('K','O','M',' ')}, /* Komi-Zyrian -> Komi */
+ {HB_TAG('k','p','y',' '), HB_TAG('K','Y','K',' ')}, /* Koryak */
+ {HB_TAG('k','q','s',' '), HB_TAG('K','I','S',' ')}, /* Northern Kissi -> Kisii */
+ {HB_TAG('k','q','y',' '), HB_TAG('K','R','T',' ')}, /* Koorete */
+ {HB_TAG('k','r','c',' '), HB_TAG('K','A','R',' ')}, /* Karachay-Balkar -> Karachay */
+ {HB_TAG('k','r','c',' '), HB_TAG('B','A','L',' ')}, /* Karachay-Balkar -> Balkar */
+ {HB_TAG('k','r','i',' '), HB_TAG('K','R','I',' ')}, /* Krio */
+ {HB_TAG('k','r','i',' '), HB_TAG('C','P','P',' ')}, /* Krio -> Creoles */
+ {HB_TAG('k','r','k',' '), HB_TAG_NONE }, /* Kerek != Karakalpak */
+/*{HB_TAG('k','r','l',' '), HB_TAG('K','R','L',' ')},*/ /* Karelian */
+ {HB_TAG('k','r','m',' '), HB_TAG_NONE }, /* Krim (retired code) != Karaim */
+ {HB_TAG('k','r','n',' '), HB_TAG_NONE }, /* Sapo != Karen */
+ {HB_TAG('k','r','t',' '), HB_TAG('K','N','R',' ')}, /* Tumari Kanuri -> Kanuri */
+ {HB_TAG('k','r','u',' '), HB_TAG('K','U','U',' ')}, /* Kurukh */
+ {HB_TAG('k','s','h',' '), HB_TAG('K','S','H','0')}, /* Kölsch -> Ripuarian */
+ {HB_TAG('k','s','i',' '), HB_TAG_NONE }, /* Krisa != Khasi */
+ {HB_TAG('k','s','m',' '), HB_TAG_NONE }, /* Kumba != Kildin Sami */
+ {HB_TAG('k','s','s',' '), HB_TAG('K','I','S',' ')}, /* Southern Kisi -> Kisii */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','S','W',' ')}, /* S’gaw Karen */
+ {HB_TAG('k','s','w',' '), HB_TAG('K','R','N',' ')}, /* S'gaw Karen -> Karen */
+ {HB_TAG('k','t','b',' '), HB_TAG('K','E','B',' ')}, /* Kambaata -> Kebena */
+ {HB_TAG('k','t','u',' '), HB_TAG('K','O','N',' ')}, /* Kituba (Democratic Republic of Congo) -> Kikongo */
+ {HB_TAG('k','t','w',' '), HB_TAG('A','T','H',' ')}, /* Kato -> Athapaskan */
+ {HB_TAG('k','u','i',' '), HB_TAG_NONE }, /* Kuikúro-Kalapálo != Kui */
+ {HB_TAG('k','u','l',' '), HB_TAG_NONE }, /* Kulere != Kulvi */
+/*{HB_TAG('k','u','m',' '), HB_TAG('K','U','M',' ')},*/ /* Kumyk */
+ {HB_TAG('k','u','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Kuskokwim -> Athapaskan */
+ {HB_TAG('k','u','w',' '), HB_TAG('B','A','D','0')}, /* Kpagua -> Banda */
+ {HB_TAG('k','u','y',' '), HB_TAG_NONE }, /* Kuuku-Ya'u != Kuy */
+ {HB_TAG('k','v','b',' '), HB_TAG('M','L','Y',' ')}, /* Kubu -> Malay */
+ {HB_TAG('k','v','l',' '), HB_TAG('K','R','N',' ')}, /* Kayaw -> Karen */
+ {HB_TAG('k','v','q',' '), HB_TAG('K','R','N',' ')}, /* Geba Karen -> Karen */
+ {HB_TAG('k','v','r',' '), HB_TAG('M','L','Y',' ')}, /* Kerinci -> Malay */
+ {HB_TAG('k','v','t',' '), HB_TAG('K','R','N',' ')}, /* Lahta Karen -> Karen */
+ {HB_TAG('k','v','u',' '), HB_TAG('K','R','N',' ')}, /* Yinbaw Karen -> Karen */
+ {HB_TAG('k','v','y',' '), HB_TAG('K','R','N',' ')}, /* Yintale Karen -> Karen */
+/*{HB_TAG('k','w','k',' '), HB_TAG('K','W','K',' ')},*/ /* Kwakiutl -> Kwakʼwala */
+ {HB_TAG('k','w','w',' '), HB_TAG('C','P','P',' ')}, /* Kwinti -> Creoles */
+ {HB_TAG('k','w','y',' '), HB_TAG('K','O','N','0')}, /* San Salvador Kongo -> Kongo */
+ {HB_TAG('k','x','c',' '), HB_TAG('K','M','S',' ')}, /* Konso -> Komso */
+ {HB_TAG('k','x','d',' '), HB_TAG('M','L','Y',' ')}, /* Brunei -> Malay */
+ {HB_TAG('k','x','f',' '), HB_TAG('K','R','N',' ')}, /* Manumanaw Karen -> Karen */
+ {HB_TAG('k','x','k',' '), HB_TAG('K','R','N',' ')}, /* Zayein Karen -> Karen */
+ {HB_TAG('k','x','l',' '), HB_TAG('K','U','U',' ')}, /* Nepali Kurux (retired code) -> Kurukh */
+ {HB_TAG('k','x','u',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) (retired code) */
+ {HB_TAG('k','y','k',' '), HB_TAG_NONE }, /* Kamayo != Koryak */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','Y','U',' ')}, /* Western Kayah */
+ {HB_TAG('k','y','u',' '), HB_TAG('K','R','N',' ')}, /* Western Kayah -> Karen */
+ {HB_TAG('l','a','c',' '), HB_TAG('M','Y','N',' ')}, /* Lacandon -> Mayan */
+ {HB_TAG('l','a','d',' '), HB_TAG('J','U','D',' ')}, /* Ladino */
+ {HB_TAG('l','a','h',' '), HB_TAG_NONE }, /* Lahnda [macrolanguage] != Lahuli */
+ {HB_TAG('l','a','k',' '), HB_TAG_NONE }, /* Laka (Nigeria) (retired code) != Lak */
+ {HB_TAG('l','a','m',' '), HB_TAG_NONE }, /* Lamba != Lambani */
+ {HB_TAG('l','a','z',' '), HB_TAG_NONE }, /* Aribwatsa != Laz */
+ {HB_TAG('l','b','e',' '), HB_TAG('L','A','K',' ')}, /* Lak */
+ {HB_TAG('l','b','j',' '), HB_TAG('L','D','K',' ')}, /* Ladakhi */
+ {HB_TAG('l','b','l',' '), HB_TAG('B','I','K',' ')}, /* Libon Bikol -> Bikol */
+ {HB_TAG('l','c','e',' '), HB_TAG('M','L','Y',' ')}, /* Loncong -> Malay */
+ {HB_TAG('l','c','f',' '), HB_TAG('M','L','Y',' ')}, /* Lubu -> Malay */
+ {HB_TAG('l','d','i',' '), HB_TAG('K','O','N','0')}, /* Laari -> Kongo */
+ {HB_TAG('l','d','k',' '), HB_TAG_NONE }, /* Leelau != Ladakhi */
+/*{HB_TAG('l','e','f',' '), HB_TAG('L','E','F',' ')},*/ /* Lelemi */
+/*{HB_TAG('l','e','z',' '), HB_TAG('L','E','Z',' ')},*/ /* Lezghian -> Lezgi */
+ {HB_TAG('l','i','f',' '), HB_TAG('L','M','B',' ')}, /* Limbu */
+/*{HB_TAG('l','i','j',' '), HB_TAG('L','I','J',' ')},*/ /* Ligurian */
+ {HB_TAG('l','i','r',' '), HB_TAG('C','P','P',' ')}, /* Liberian English -> Creoles */
+/*{HB_TAG('l','i','s',' '), HB_TAG('L','I','S',' ')},*/ /* Lisu */
+ {HB_TAG('l','i','w',' '), HB_TAG('M','L','Y',' ')}, /* Col -> Malay */
+ {HB_TAG('l','i','y',' '), HB_TAG('B','A','D','0')}, /* Banda-Bambari -> Banda */
+/*{HB_TAG('l','j','p',' '), HB_TAG('L','J','P',' ')},*/ /* Lampung Api -> Lampung */
+ {HB_TAG('l','k','b',' '), HB_TAG('L','U','H',' ')}, /* Kabras -> Luyia */
+/*{HB_TAG('l','k','i',' '), HB_TAG('L','K','I',' ')},*/ /* Laki */
+ {HB_TAG('l','k','o',' '), HB_TAG('L','U','H',' ')}, /* Khayo -> Luyia */
+ {HB_TAG('l','k','s',' '), HB_TAG('L','U','H',' ')}, /* Kisa -> Luyia */
+ {HB_TAG('l','l','d',' '), HB_TAG('L','A','D',' ')}, /* Ladin */
+ {HB_TAG('l','m','a',' '), HB_TAG_NONE }, /* East Limba != Low Mari */
+ {HB_TAG('l','m','b',' '), HB_TAG_NONE }, /* Merei != Limbu */
+ {HB_TAG('l','m','n',' '), HB_TAG('L','A','M',' ')}, /* Lambadi -> Lambani */
+/*{HB_TAG('l','m','o',' '), HB_TAG('L','M','O',' ')},*/ /* Lombard */
+ {HB_TAG('l','m','w',' '), HB_TAG_NONE }, /* Lake Miwok != Lomwe */
+ {HB_TAG('l','n','a',' '), HB_TAG('B','A','D','0')}, /* Langbashe -> Banda */
+ {HB_TAG('l','n','l',' '), HB_TAG('B','A','D','0')}, /* South Central Banda -> Banda */
+/*{HB_TAG('l','o','m',' '), HB_TAG('L','O','M',' ')},*/ /* Loma (Liberia) */
+ {HB_TAG('l','o','u',' '), HB_TAG('C','P','P',' ')}, /* Louisiana Creole -> Creoles */
+/*{HB_TAG('l','p','o',' '), HB_TAG('L','P','O',' ')},*/ /* Lipo */
+/*{HB_TAG('l','r','c',' '), HB_TAG('L','R','C',' ')},*/ /* Northern Luri -> Luri */
+ {HB_TAG('l','r','i',' '), HB_TAG('L','U','H',' ')}, /* Marachi -> Luyia */
+ {HB_TAG('l','r','m',' '), HB_TAG('L','U','H',' ')}, /* Marama -> Luyia */
+ {HB_TAG('l','r','t',' '), HB_TAG('C','P','P',' ')}, /* Larantuka Malay -> Creoles */
+ {HB_TAG('l','s','b',' '), HB_TAG_NONE }, /* Burundian Sign Language != Lower Sorbian */
+ {HB_TAG('l','s','m',' '), HB_TAG('L','U','H',' ')}, /* Saamia -> Luyia */
+ {HB_TAG('l','t','g',' '), HB_TAG('L','V','I',' ')}, /* Latgalian -> Latvian */
+ {HB_TAG('l','t','h',' '), HB_TAG_NONE }, /* Thur != Lithuanian */
+ {HB_TAG('l','t','o',' '), HB_TAG('L','U','H',' ')}, /* Tsotso -> Luyia */
+ {HB_TAG('l','t','s',' '), HB_TAG('L','U','H',' ')}, /* Tachoni -> Luyia */
+/*{HB_TAG('l','u','a',' '), HB_TAG('L','U','A',' ')},*/ /* Luba-Lulua */
+/*{HB_TAG('l','u','o',' '), HB_TAG('L','U','O',' ')},*/ /* Luo (Kenya and Tanzania) */
+ {HB_TAG('l','u','s',' '), HB_TAG('M','I','Z',' ')}, /* Lushai -> Mizo */
+ {HB_TAG('l','u','s',' '), HB_TAG('Q','I','N',' ')}, /* Lushai -> Chin */
+ {HB_TAG('l','u','y',' '), HB_TAG('L','U','H',' ')}, /* Luyia [macrolanguage] */
+ {HB_TAG('l','u','z',' '), HB_TAG('L','R','C',' ')}, /* Southern Luri -> Luri */
+ {HB_TAG('l','v','i',' '), HB_TAG_NONE }, /* Lavi != Latvian */
+ {HB_TAG('l','v','s',' '), HB_TAG('L','V','I',' ')}, /* Standard Latvian -> Latvian */
+ {HB_TAG('l','w','g',' '), HB_TAG('L','U','H',' ')}, /* Wanga -> Luyia */
+ {HB_TAG('l','z','h',' '), HB_TAG('Z','H','T',' ')}, /* Literary Chinese -> Chinese, Traditional */
+ {HB_TAG('l','z','z',' '), HB_TAG('L','A','Z',' ')}, /* Laz */
+/*{HB_TAG('m','a','d',' '), HB_TAG('M','A','D',' ')},*/ /* Madurese -> Madura */
+/*{HB_TAG('m','a','g',' '), HB_TAG('M','A','G',' ')},*/ /* Magahi */
+ {HB_TAG('m','a','i',' '), HB_TAG('M','T','H',' ')}, /* Maithili */
+ {HB_TAG('m','a','j',' '), HB_TAG_NONE }, /* Jalapa De Díaz Mazatec != Majang */
+ {HB_TAG('m','a','k',' '), HB_TAG('M','K','R',' ')}, /* Makasar */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','A','M',' ')}, /* Mam */
+ {HB_TAG('m','a','m',' '), HB_TAG('M','Y','N',' ')}, /* Mam -> Mayan */
+ {HB_TAG('m','a','n',' '), HB_TAG('M','N','K',' ')}, /* Mandingo [macrolanguage] -> Maninka */
+ {HB_TAG('m','a','p',' '), HB_TAG_NONE }, /* Austronesian [collection] != Mapudungun */
+ {HB_TAG('m','a','w',' '), HB_TAG_NONE }, /* Mampruli != Marwari */
+ {HB_TAG('m','a','x',' '), HB_TAG('M','L','Y',' ')}, /* North Moluccan Malay -> Malay */
+ {HB_TAG('m','a','x',' '), HB_TAG('C','P','P',' ')}, /* North Moluccan Malay -> Creoles */
+ {HB_TAG('m','b','f',' '), HB_TAG('C','P','P',' ')}, /* Baba Malay -> Creoles */
+ {HB_TAG('m','b','n',' '), HB_TAG_NONE }, /* Macaguán != Mbundu */
+/*{HB_TAG('m','b','o',' '), HB_TAG('M','B','O',' ')},*/ /* Mbo (Cameroon) */
+ {HB_TAG('m','c','h',' '), HB_TAG_NONE }, /* Maquiritari != Manchu */
+ {HB_TAG('m','c','m',' '), HB_TAG('C','P','P',' ')}, /* Malaccan Creole Portuguese -> Creoles */
+ {HB_TAG('m','c','r',' '), HB_TAG_NONE }, /* Menya != Moose Cree */
+ {HB_TAG('m','c','t',' '), HB_TAG('B','T','I',' ')}, /* Mengisa -> Beti */
+ {HB_TAG('m','d','e',' '), HB_TAG_NONE }, /* Maba (Chad) != Mende */
+ {HB_TAG('m','d','f',' '), HB_TAG('M','O','K',' ')}, /* Moksha */
+/*{HB_TAG('m','d','r',' '), HB_TAG('M','D','R',' ')},*/ /* Mandar */
+ {HB_TAG('m','d','y',' '), HB_TAG('M','L','E',' ')}, /* Male (Ethiopia) */
+ {HB_TAG('m','e','n',' '), HB_TAG('M','D','E',' ')}, /* Mende (Sierra Leone) */
+ {HB_TAG('m','e','o',' '), HB_TAG('M','L','Y',' ')}, /* Kedah Malay -> Malay */
+/*{HB_TAG('m','e','r',' '), HB_TAG('M','E','R',' ')},*/ /* Meru */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','F','A',' ')}, /* Pattani Malay */
+ {HB_TAG('m','f','a',' '), HB_TAG('M','L','Y',' ')}, /* Pattani Malay -> Malay */
+ {HB_TAG('m','f','b',' '), HB_TAG('M','L','Y',' ')}, /* Bangka -> Malay */
+ {HB_TAG('m','f','e',' '), HB_TAG('M','F','E',' ')}, /* Morisyen */
+ {HB_TAG('m','f','e',' '), HB_TAG('C','P','P',' ')}, /* Morisyen -> Creoles */
+ {HB_TAG('m','f','p',' '), HB_TAG('C','P','P',' ')}, /* Makassar Malay -> Creoles */
+ {HB_TAG('m','h','c',' '), HB_TAG('M','Y','N',' ')}, /* Mocho -> Mayan */
+ {HB_TAG('m','h','r',' '), HB_TAG('L','M','A',' ')}, /* Eastern Mari -> Low Mari */
+ {HB_TAG('m','h','v',' '), HB_TAG('A','R','K',' ')}, /* Arakanese (retired code) -> Rakhine */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','I','N',' ')}, /* Minangkabau */
+ {HB_TAG('m','i','n',' '), HB_TAG('M','L','Y',' ')}, /* Minangkabau -> Malay */
+ {HB_TAG('m','i','z',' '), HB_TAG_NONE }, /* Coatzospan Mixtec != Mizo */
+ {HB_TAG('m','k','n',' '), HB_TAG('C','P','P',' ')}, /* Kupang Malay -> Creoles */
+ {HB_TAG('m','k','r',' '), HB_TAG_NONE }, /* Malas != Makasar */
+ {HB_TAG('m','k','u',' '), HB_TAG('M','N','K',' ')}, /* Konyanka Maninka -> Maninka */
+/*{HB_TAG('m','k','w',' '), HB_TAG('M','K','W',' ')},*/ /* Kituba (Congo) */
+ {HB_TAG('m','l','e',' '), HB_TAG_NONE }, /* Manambu != Male */
+ {HB_TAG('m','l','n',' '), HB_TAG_NONE }, /* Malango != Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','L','N',' ')}, /* Western Maninkakan -> Malinke */
+ {HB_TAG('m','l','q',' '), HB_TAG('M','N','K',' ')}, /* Western Maninkakan -> Maninka */
+ {HB_TAG('m','l','r',' '), HB_TAG_NONE }, /* Vame != Malayalam Reformed */
+ {HB_TAG('m','m','r',' '), HB_TAG('H','M','N',' ')}, /* Western Xiangxi Miao -> Hmong */
+ {HB_TAG('m','n','c',' '), HB_TAG('M','C','H',' ')}, /* Manchu */
+ {HB_TAG('m','n','d',' '), HB_TAG_NONE }, /* Mondé != Mandinka */
+ {HB_TAG('m','n','g',' '), HB_TAG_NONE }, /* Eastern Mnong != Mongolian */
+ {HB_TAG('m','n','h',' '), HB_TAG('B','A','D','0')}, /* Mono (Democratic Republic of Congo) -> Banda */
+/*{HB_TAG('m','n','i',' '), HB_TAG('M','N','I',' ')},*/ /* Manipuri */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','D',' ')}, /* Mandinka */
+ {HB_TAG('m','n','k',' '), HB_TAG('M','N','K',' ')}, /* Mandinka -> Maninka */
+ {HB_TAG('m','n','p',' '), HB_TAG('Z','H','S',' ')}, /* Min Bei Chinese -> Chinese, Simplified */
+ {HB_TAG('m','n','s',' '), HB_TAG('M','A','N',' ')}, /* Mansi */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N',' ')}, /* Mon */
+ {HB_TAG('m','n','w',' '), HB_TAG('M','O','N','T')}, /* Mon -> Thailand Mon */
+ {HB_TAG('m','n','x',' '), HB_TAG_NONE }, /* Manikion != Manx */
+ {HB_TAG('m','o','d',' '), HB_TAG('C','P','P',' ')}, /* Mobilian -> Creoles */
+/*{HB_TAG('m','o','h',' '), HB_TAG('M','O','H',' ')},*/ /* Mohawk */
+ {HB_TAG('m','o','k',' '), HB_TAG_NONE }, /* Morori != Moksha */
+ {HB_TAG('m','o','p',' '), HB_TAG('M','Y','N',' ')}, /* Mopán Maya -> Mayan */
+ {HB_TAG('m','o','r',' '), HB_TAG_NONE }, /* Moro != Moroccan */
+/*{HB_TAG('m','o','s',' '), HB_TAG('M','O','S',' ')},*/ /* Mossi */
+ {HB_TAG('m','p','e',' '), HB_TAG('M','A','J',' ')}, /* Majang */
+ {HB_TAG('m','q','g',' '), HB_TAG('M','L','Y',' ')}, /* Kota Bangun Kutai Malay -> Malay */
+ {HB_TAG('m','r','h',' '), HB_TAG('Q','I','N',' ')}, /* Mara Chin -> Chin */
+ {HB_TAG('m','r','j',' '), HB_TAG('H','M','A',' ')}, /* Western Mari -> High Mari */
+ {HB_TAG('m','s','c',' '), HB_TAG('M','N','K',' ')}, /* Sankaran Maninka -> Maninka */
+ {HB_TAG('m','s','h',' '), HB_TAG('M','L','G',' ')}, /* Masikoro Malagasy -> Malagasy */
+ {HB_TAG('m','s','i',' '), HB_TAG('M','L','Y',' ')}, /* Sabah Malay -> Malay */
+ {HB_TAG('m','s','i',' '), HB_TAG('C','P','P',' ')}, /* Sabah Malay -> Creoles */
+ {HB_TAG('m','t','h',' '), HB_TAG_NONE }, /* Munggui != Maithili */
+ {HB_TAG('m','t','r',' '), HB_TAG('M','A','W',' ')}, /* Mewari -> Marwari */
+ {HB_TAG('m','t','s',' '), HB_TAG_NONE }, /* Yora != Maltese */
+ {HB_TAG('m','u','d',' '), HB_TAG('C','P','P',' ')}, /* Mednyj Aleut -> Creoles */
+ {HB_TAG('m','u','i',' '), HB_TAG('M','L','Y',' ')}, /* Musi -> Malay */
+ {HB_TAG('m','u','n',' '), HB_TAG_NONE }, /* Munda [collection] != Mundari */
+ {HB_TAG('m','u','p',' '), HB_TAG('R','A','J',' ')}, /* Malvi -> Rajasthani */
+ {HB_TAG('m','u','q',' '), HB_TAG('H','M','N',' ')}, /* Eastern Xiangxi Miao -> Hmong */
+/*{HB_TAG('m','u','s',' '), HB_TAG('M','U','S',' ')},*/ /* Creek -> Muscogee */
+ {HB_TAG('m','v','b',' '), HB_TAG('A','T','H',' ')}, /* Mattole -> Athapaskan */
+ {HB_TAG('m','v','e',' '), HB_TAG('M','A','W',' ')}, /* Marwari (Pakistan) */
+ {HB_TAG('m','v','f',' '), HB_TAG('M','N','G',' ')}, /* Peripheral Mongolian -> Mongolian */
+ {HB_TAG('m','w','k',' '), HB_TAG('M','N','K',' ')}, /* Kita Maninkakan -> Maninka */
+/*{HB_TAG('m','w','l',' '), HB_TAG('M','W','L',' ')},*/ /* Mirandese */
+ {HB_TAG('m','w','q',' '), HB_TAG('Q','I','N',' ')}, /* Mün Chin -> Chin */
+ {HB_TAG('m','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari [macrolanguage] */
+ {HB_TAG('m','w','w',' '), HB_TAG('M','W','W',' ')}, /* Hmong Daw */
+ {HB_TAG('m','w','w',' '), HB_TAG('H','M','N',' ')}, /* Hmong Daw -> Hmong */
+ {HB_TAG('m','y','m',' '), HB_TAG('M','E','N',' ')}, /* Me’en */
+/*{HB_TAG('m','y','n',' '), HB_TAG('M','Y','N',' ')},*/ /* Mayan [collection] */
+ {HB_TAG('m','y','q',' '), HB_TAG('M','N','K',' ')}, /* Forest Maninka (retired code) -> Maninka */
+ {HB_TAG('m','y','v',' '), HB_TAG('E','R','Z',' ')}, /* Erzya */
+ {HB_TAG('m','z','b',' '), HB_TAG('B','B','R',' ')}, /* Tumzabt -> Berber */
+/*{HB_TAG('m','z','n',' '), HB_TAG('M','Z','N',' ')},*/ /* Mazanderani */
+ {HB_TAG('m','z','s',' '), HB_TAG('C','P','P',' ')}, /* Macanese -> Creoles */
+ {HB_TAG('n','a','g',' '), HB_TAG('N','A','G',' ')}, /* Naga Pidgin -> Naga-Assamese */
+ {HB_TAG('n','a','g',' '), HB_TAG('C','P','P',' ')}, /* Naga Pidgin -> Creoles */
+/*{HB_TAG('n','a','h',' '), HB_TAG('N','A','H',' ')},*/ /* Nahuatl [collection] */
+ {HB_TAG('n','a','n',' '), HB_TAG('Z','H','S',' ')}, /* Min Nan Chinese -> Chinese, Simplified */
+/*{HB_TAG('n','a','p',' '), HB_TAG('N','A','P',' ')},*/ /* Neapolitan */
+ {HB_TAG('n','a','s',' '), HB_TAG_NONE }, /* Naasioi != Naskapi */
+ {HB_TAG('n','a','z',' '), HB_TAG('N','A','H',' ')}, /* Coatepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','h',' '), HB_TAG('N','A','H',' ')}, /* Central Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','i',' '), HB_TAG('N','A','H',' ')}, /* Classical Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','j',' '), HB_TAG('N','A','H',' ')}, /* Northern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','l',' '), HB_TAG('N','A','H',' ')}, /* Michoacán Nahuatl -> Nahuatl */
+ {HB_TAG('n','c','r',' '), HB_TAG_NONE }, /* Ncane != N-Cree */
+ {HB_TAG('n','c','x',' '), HB_TAG('N','A','H',' ')}, /* Central Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','d','b',' '), HB_TAG_NONE }, /* Kenswei Nsei != Ndebele */
+/*{HB_TAG('n','d','c',' '), HB_TAG('N','D','C',' ')},*/ /* Ndau */
+ {HB_TAG('n','d','g',' '), HB_TAG_NONE }, /* Ndengereko != Ndonga */
+/*{HB_TAG('n','d','s',' '), HB_TAG('N','D','S',' ')},*/ /* Low Saxon */
+ {HB_TAG('n','e','f',' '), HB_TAG('C','P','P',' ')}, /* Nefamese -> Creoles */
+/*{HB_TAG('n','e','w',' '), HB_TAG('N','E','W',' ')},*/ /* Newari */
+/*{HB_TAG('n','g','a',' '), HB_TAG('N','G','A',' ')},*/ /* Ngbaka */
+ {HB_TAG('n','g','l',' '), HB_TAG('L','M','W',' ')}, /* Lomwe */
+ {HB_TAG('n','g','m',' '), HB_TAG('C','P','P',' ')}, /* Ngatik Men's Creole -> Creoles */
+ {HB_TAG('n','g','o',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (retired code) -> Sutu */
+ {HB_TAG('n','g','r',' '), HB_TAG_NONE }, /* Engdewu != Nagari */
+ {HB_TAG('n','g','u',' '), HB_TAG('N','A','H',' ')}, /* Guerrero Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','c',' '), HB_TAG('N','A','H',' ')}, /* Tabasco Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','d',' '), HB_TAG('G','U','A',' ')}, /* Chiripá -> Guarani */
+ {HB_TAG('n','h','e',' '), HB_TAG('N','A','H',' ')}, /* Eastern Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','g',' '), HB_TAG('N','A','H',' ')}, /* Tetelcingo Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','i',' '), HB_TAG('N','A','H',' ')}, /* Zacatlán-Ahuacatlán-Tepetzintla Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','k',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Cosoleacaque Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','m',' '), HB_TAG('N','A','H',' ')}, /* Morelos Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','n',' '), HB_TAG('N','A','H',' ')}, /* Central Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','p',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Pajapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','q',' '), HB_TAG('N','A','H',' ')}, /* Huaxcaleca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','t',' '), HB_TAG('N','A','H',' ')}, /* Ometepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','v',' '), HB_TAG('N','A','H',' ')}, /* Temascaltepec Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','w',' '), HB_TAG('N','A','H',' ')}, /* Western Huasteca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','x',' '), HB_TAG('N','A','H',' ')}, /* Isthmus-Mecayapan Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','y',' '), HB_TAG('N','A','H',' ')}, /* Northern Oaxaca Nahuatl -> Nahuatl */
+ {HB_TAG('n','h','z',' '), HB_TAG('N','A','H',' ')}, /* Santa María La Alta Nahuatl -> Nahuatl */
+ {HB_TAG('n','i','q',' '), HB_TAG('K','A','L',' ')}, /* Nandi -> Kalenjin */
+ {HB_TAG('n','i','s',' '), HB_TAG_NONE }, /* Nimi != Nisi */
+/*{HB_TAG('n','i','u',' '), HB_TAG('N','I','U',' ')},*/ /* Niuean */
+ {HB_TAG('n','i','v',' '), HB_TAG('G','I','L',' ')}, /* Gilyak */
+ {HB_TAG('n','j','t',' '), HB_TAG('C','P','P',' ')}, /* Ndyuka-Trio Pidgin -> Creoles */
+ {HB_TAG('n','j','z',' '), HB_TAG('N','I','S',' ')}, /* Nyishi -> Nisi */
+ {HB_TAG('n','k','o',' '), HB_TAG_NONE }, /* Nkonya != N’Ko */
+ {HB_TAG('n','k','x',' '), HB_TAG('I','J','O',' ')}, /* Nkoroo -> Ijo */
+ {HB_TAG('n','l','a',' '), HB_TAG('B','M','L',' ')}, /* Ngombale -> Bamileke */
+ {HB_TAG('n','l','e',' '), HB_TAG('L','U','H',' ')}, /* East Nyala -> Luyia */
+ {HB_TAG('n','l','n',' '), HB_TAG('N','A','H',' ')}, /* Durango Nahuatl (retired code) -> Nahuatl */
+ {HB_TAG('n','l','v',' '), HB_TAG('N','A','H',' ')}, /* Orizaba Nahuatl -> Nahuatl */
+ {HB_TAG('n','n','h',' '), HB_TAG('B','M','L',' ')}, /* Ngiemboon -> Bamileke */
+ {HB_TAG('n','n','z',' '), HB_TAG('B','M','L',' ')}, /* Nda'nda' -> Bamileke */
+ {HB_TAG('n','o','d',' '), HB_TAG('N','T','A',' ')}, /* Northern Thai -> Northern Tai */
+/*{HB_TAG('n','o','e',' '), HB_TAG('N','O','E',' ')},*/ /* Nimadi */
+/*{HB_TAG('n','o','g',' '), HB_TAG('N','O','G',' ')},*/ /* Nogai */
+/*{HB_TAG('n','o','v',' '), HB_TAG('N','O','V',' ')},*/ /* Novial */
+ {HB_TAG('n','p','i',' '), HB_TAG('N','E','P',' ')}, /* Nepali */
+ {HB_TAG('n','p','l',' '), HB_TAG('N','A','H',' ')}, /* Southeastern Puebla Nahuatl -> Nahuatl */
+ {HB_TAG('n','q','o',' '), HB_TAG('N','K','O',' ')}, /* N’Ko */
+ {HB_TAG('n','s','k',' '), HB_TAG('N','A','S',' ')}, /* Naskapi */
+ {HB_TAG('n','s','m',' '), HB_TAG_NONE }, /* Sumi Naga != Northern Sami */
+/*{HB_TAG('n','s','o',' '), HB_TAG('N','S','O',' ')},*/ /* Northern Sotho */
+ {HB_TAG('n','s','u',' '), HB_TAG('N','A','H',' ')}, /* Sierra Negra Nahuatl -> Nahuatl */
+ {HB_TAG('n','t','o',' '), HB_TAG_NONE }, /* Ntomba != Esperanto */
+ {HB_TAG('n','u','e',' '), HB_TAG('B','A','D','0')}, /* Ngundu -> Banda */
+ {HB_TAG('n','u','u',' '), HB_TAG('B','A','D','0')}, /* Ngbundu -> Banda */
+ {HB_TAG('n','u','z',' '), HB_TAG('N','A','H',' ')}, /* Tlamacazapa Nahuatl -> Nahuatl */
+ {HB_TAG('n','w','e',' '), HB_TAG('B','M','L',' ')}, /* Ngwe -> Bamileke */
+ {HB_TAG('n','y','d',' '), HB_TAG('L','U','H',' ')}, /* Nyore -> Luyia */
+/*{HB_TAG('n','y','m',' '), HB_TAG('N','Y','M',' ')},*/ /* Nyamwezi */
+ {HB_TAG('n','y','n',' '), HB_TAG('N','K','L',' ')}, /* Nyankole */
+/*{HB_TAG('n','z','a',' '), HB_TAG('N','Z','A',' ')},*/ /* Tigon Mbembe -> Mbembe Tigon */
+/*{HB_TAG('o','j','b',' '), HB_TAG('O','J','B',' ')},*/ /* Northwestern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','c',' '), HB_TAG('O','J','B',' ')}, /* Central Ojibwa -> Ojibway */
+ {HB_TAG('o','j','g',' '), HB_TAG('O','J','B',' ')}, /* Eastern Ojibwa -> Ojibway */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','C','R',' ')}, /* Severn Ojibwa -> Oji-Cree */
+ {HB_TAG('o','j','s',' '), HB_TAG('O','J','B',' ')}, /* Severn Ojibwa -> Ojibway */
+ {HB_TAG('o','j','w',' '), HB_TAG('O','J','B',' ')}, /* Western Ojibwa -> Ojibway */
+ {HB_TAG('o','k','d',' '), HB_TAG('I','J','O',' ')}, /* Okodia -> Ijo */
+ {HB_TAG('o','k','i',' '), HB_TAG('K','A','L',' ')}, /* Okiek -> Kalenjin */
+ {HB_TAG('o','k','m',' '), HB_TAG('K','O','H',' ')}, /* Middle Korean (10th-16th cent.) -> Korean Old Hangul */
+ {HB_TAG('o','k','r',' '), HB_TAG('I','J','O',' ')}, /* Kirike -> Ijo */
+ {HB_TAG('o','n','x',' '), HB_TAG('C','P','P',' ')}, /* Onin Based Pidgin -> Creoles */
+ {HB_TAG('o','o','r',' '), HB_TAG('C','P','P',' ')}, /* Oorlams -> Creoles */
+ {HB_TAG('o','r','c',' '), HB_TAG('O','R','O',' ')}, /* Orma -> Oromo */
+ {HB_TAG('o','r','n',' '), HB_TAG('M','L','Y',' ')}, /* Orang Kanaq -> Malay */
+ {HB_TAG('o','r','o',' '), HB_TAG_NONE }, /* Orokolo != Oromo */
+ {HB_TAG('o','r','r',' '), HB_TAG('I','J','O',' ')}, /* Oruma -> Ijo */
+ {HB_TAG('o','r','s',' '), HB_TAG('M','L','Y',' ')}, /* Orang Seletar -> Malay */
+ {HB_TAG('o','r','y',' '), HB_TAG('O','R','I',' ')}, /* Odia (formerly Oriya) */
+ {HB_TAG('o','t','w',' '), HB_TAG('O','J','B',' ')}, /* Ottawa -> Ojibway */
+ {HB_TAG('o','u','a',' '), HB_TAG('B','B','R',' ')}, /* Tagargrent -> Berber */
+ {HB_TAG('p','a','a',' '), HB_TAG_NONE }, /* Papuan [collection] != Palestinian Aramaic */
+/*{HB_TAG('p','a','g',' '), HB_TAG('P','A','G',' ')},*/ /* Pangasinan */
+ {HB_TAG('p','a','l',' '), HB_TAG_NONE }, /* Pahlavi != Pali */
+/*{HB_TAG('p','a','m',' '), HB_TAG('P','A','M',' ')},*/ /* Pampanga -> Pampangan */
+ {HB_TAG('p','a','p',' '), HB_TAG('P','A','P','0')}, /* Papiamento -> Papiamentu */
+ {HB_TAG('p','a','p',' '), HB_TAG('C','P','P',' ')}, /* Papiamento -> Creoles */
+ {HB_TAG('p','a','s',' '), HB_TAG_NONE }, /* Papasena != Pashto */
+/*{HB_TAG('p','a','u',' '), HB_TAG('P','A','U',' ')},*/ /* Palauan */
+ {HB_TAG('p','b','t',' '), HB_TAG('P','A','S',' ')}, /* Southern Pashto -> Pashto */
+ {HB_TAG('p','b','u',' '), HB_TAG('P','A','S',' ')}, /* Northern Pashto -> Pashto */
+/*{HB_TAG('p','c','c',' '), HB_TAG('P','C','C',' ')},*/ /* Bouyei */
+/*{HB_TAG('p','c','d',' '), HB_TAG('P','C','D',' ')},*/ /* Picard */
+ {HB_TAG('p','c','e',' '), HB_TAG('P','L','G',' ')}, /* Ruching Palaung -> Palaung */
+ {HB_TAG('p','c','k',' '), HB_TAG('Q','I','N',' ')}, /* Paite Chin -> Chin */
+ {HB_TAG('p','c','m',' '), HB_TAG('C','P','P',' ')}, /* Nigerian Pidgin -> Creoles */
+/*{HB_TAG('p','d','c',' '), HB_TAG('P','D','C',' ')},*/ /* Pennsylvania German */
+ {HB_TAG('p','d','u',' '), HB_TAG('K','R','N',' ')}, /* Kayan -> Karen */
+ {HB_TAG('p','e','a',' '), HB_TAG('C','P','P',' ')}, /* Peranakan Indonesian -> Creoles */
+ {HB_TAG('p','e','l',' '), HB_TAG('M','L','Y',' ')}, /* Pekal -> Malay */
+ {HB_TAG('p','e','s',' '), HB_TAG('F','A','R',' ')}, /* Iranian Persian -> Persian */
+ {HB_TAG('p','e','y',' '), HB_TAG('C','P','P',' ')}, /* Petjo -> Creoles */
+ {HB_TAG('p','g','a',' '), HB_TAG('A','R','A',' ')}, /* Sudanese Creole Arabic -> Arabic */
+ {HB_TAG('p','g','a',' '), HB_TAG('C','P','P',' ')}, /* Sudanese Creole Arabic -> Creoles */
+/*{HB_TAG('p','h','k',' '), HB_TAG('P','H','K',' ')},*/ /* Phake */
+ {HB_TAG('p','i','h',' '), HB_TAG('P','I','H',' ')}, /* Pitcairn-Norfolk -> Norfolk */
+ {HB_TAG('p','i','h',' '), HB_TAG('C','P','P',' ')}, /* Pitcairn-Norfolk -> Creoles */
+ {HB_TAG('p','i','l',' '), HB_TAG_NONE }, /* Yom != Filipino */
+ {HB_TAG('p','i','s',' '), HB_TAG('C','P','P',' ')}, /* Pijin -> Creoles */
+ {HB_TAG('p','k','h',' '), HB_TAG('Q','I','N',' ')}, /* Pankhu -> Chin */
+ {HB_TAG('p','k','o',' '), HB_TAG('K','A','L',' ')}, /* Pökoot -> Kalenjin */
+ {HB_TAG('p','l','g',' '), HB_TAG_NONE }, /* Pilagá != Palaung */
+ {HB_TAG('p','l','k',' '), HB_TAG_NONE }, /* Kohistani Shina != Polish */
+ {HB_TAG('p','l','l',' '), HB_TAG('P','L','G',' ')}, /* Shwe Palaung -> Palaung */
+ {HB_TAG('p','l','n',' '), HB_TAG('C','P','P',' ')}, /* Palenquero -> Creoles */
+ {HB_TAG('p','l','p',' '), HB_TAG('P','A','P',' ')}, /* Palpa (retired code) */
+ {HB_TAG('p','l','t',' '), HB_TAG('M','L','G',' ')}, /* Plateau Malagasy -> Malagasy */
+ {HB_TAG('p','m','l',' '), HB_TAG('C','P','P',' ')}, /* Lingua Franca -> Creoles */
+/*{HB_TAG('p','m','s',' '), HB_TAG('P','M','S',' ')},*/ /* Piemontese */
+ {HB_TAG('p','m','y',' '), HB_TAG('C','P','P',' ')}, /* Papuan Malay -> Creoles */
+/*{HB_TAG('p','n','b',' '), HB_TAG('P','N','B',' ')},*/ /* Western Panjabi */
+ {HB_TAG('p','o','c',' '), HB_TAG('M','Y','N',' ')}, /* Poqomam -> Mayan */
+ {HB_TAG('p','o','h',' '), HB_TAG('P','O','H',' ')}, /* Poqomchi' -> Pocomchi */
+ {HB_TAG('p','o','h',' '), HB_TAG('M','Y','N',' ')}, /* Poqomchi' -> Mayan */
+/*{HB_TAG('p','o','n',' '), HB_TAG('P','O','N',' ')},*/ /* Pohnpeian */
+ {HB_TAG('p','o','v',' '), HB_TAG('C','P','P',' ')}, /* Upper Guinea Crioulo -> Creoles */
+ {HB_TAG('p','p','a',' '), HB_TAG('B','A','G',' ')}, /* Pao (retired code) -> Baghelkhandi */
+ {HB_TAG('p','r','e',' '), HB_TAG('C','P','P',' ')}, /* Principense -> Creoles */
+/*{HB_TAG('p','r','o',' '), HB_TAG('P','R','O',' ')},*/ /* Old Provençal (to 1500) -> Provençal / Old Provençal */
+ {HB_TAG('p','r','s',' '), HB_TAG('D','R','I',' ')}, /* Dari */
+ {HB_TAG('p','r','s',' '), HB_TAG('F','A','R',' ')}, /* Dari -> Persian */
+ {HB_TAG('p','s','e',' '), HB_TAG('M','L','Y',' ')}, /* Central Malay -> Malay */
+ {HB_TAG('p','s','t',' '), HB_TAG('P','A','S',' ')}, /* Central Pashto -> Pashto */
+ {HB_TAG('p','u','b',' '), HB_TAG('Q','I','N',' ')}, /* Purum -> Chin */
+ {HB_TAG('p','u','z',' '), HB_TAG('Q','I','N',' ')}, /* Purum Naga (retired code) -> Chin */
+ {HB_TAG('p','w','o',' '), HB_TAG('P','W','O',' ')}, /* Pwo Western Karen -> Western Pwo Karen */
+ {HB_TAG('p','w','o',' '), HB_TAG('K','R','N',' ')}, /* Pwo Western Karen -> Karen */
+ {HB_TAG('p','w','w',' '), HB_TAG('K','R','N',' ')}, /* Pwo Northern Karen -> Karen */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','W','H',' ')}, /* Huallaga Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','b',' '), HB_TAG('Q','U','Z',' ')}, /* Huallaga Huánuco Quechua -> Quechua */
+ {HB_TAG('q','u','c',' '), HB_TAG('Q','U','C',' ')}, /* K’iche’ */
+ {HB_TAG('q','u','c',' '), HB_TAG('M','Y','N',' ')}, /* K'iche' -> Mayan */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','V','I',' ')}, /* Calderón Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','d',' '), HB_TAG('Q','U','Z',' ')}, /* Calderón Highland Quichua -> Quechua */
+ {HB_TAG('q','u','f',' '), HB_TAG('Q','U','Z',' ')}, /* Lambayeque Quechua -> Quechua */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','V','I',' ')}, /* Chimborazo Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','g',' '), HB_TAG('Q','U','Z',' ')}, /* Chimborazo Highland Quichua -> Quechua */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','H',' ')}, /* South Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','h',' '), HB_TAG('Q','U','Z',' ')}, /* South Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','k',' '), HB_TAG('Q','U','Z',' ')}, /* Chachapoyas Quechua -> Quechua */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','H',' ')}, /* North Bolivian Quechua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','l',' '), HB_TAG('Q','U','Z',' ')}, /* North Bolivian Quechua -> Quechua */
+ {HB_TAG('q','u','m',' '), HB_TAG('M','Y','N',' ')}, /* Sipacapense -> Mayan */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','V','I',' ')}, /* Southern Pastaza Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','p',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Pastaza Quechua -> Quechua */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','W','H',' ')}, /* Yanahuanca Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','r',' '), HB_TAG('Q','U','Z',' ')}, /* Yanahuanca Pasco Quechua -> Quechua */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','H',' ')}, /* Santiago del Estero Quichua -> Quechua (Bolivia) */
+ {HB_TAG('q','u','s',' '), HB_TAG('Q','U','Z',' ')}, /* Santiago del Estero Quichua -> Quechua */
+ {HB_TAG('q','u','v',' '), HB_TAG('M','Y','N',' ')}, /* Sacapulteco -> Mayan */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','V','I',' ')}, /* Tena Lowland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','u','w',' '), HB_TAG('Q','U','Z',' ')}, /* Tena Lowland Quichua -> Quechua */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','W','H',' ')}, /* Yauyos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','u','x',' '), HB_TAG('Q','U','Z',' ')}, /* Yauyos Quechua -> Quechua */
+ {HB_TAG('q','u','y',' '), HB_TAG('Q','U','Z',' ')}, /* Ayacucho Quechua -> Quechua */
+/*{HB_TAG('q','u','z',' '), HB_TAG('Q','U','Z',' ')},*/ /* Cusco Quechua -> Quechua */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','W','H',' ')}, /* Ambo-Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','a',' '), HB_TAG('Q','U','Z',' ')}, /* Ambo-Pasco Quechua -> Quechua */
+ {HB_TAG('q','v','c',' '), HB_TAG('Q','U','Z',' ')}, /* Cajamarca Quechua -> Quechua */
+ {HB_TAG('q','v','e',' '), HB_TAG('Q','U','Z',' ')}, /* Eastern Apurímac Quechua -> Quechua */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','W','H',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huamalíes-Dos de Mayo Huánuco Quechua -> Quechua */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','V','I',' ')}, /* Imbabura Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','i',' '), HB_TAG('Q','U','Z',' ')}, /* Imbabura Highland Quichua -> Quechua */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','V','I',' ')}, /* Loja Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','j',' '), HB_TAG('Q','U','Z',' ')}, /* Loja Highland Quichua -> Quechua */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','W','H',' ')}, /* Cajatambo North Lima Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','l',' '), HB_TAG('Q','U','Z',' ')}, /* Cajatambo North Lima Quechua -> Quechua */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','W','H',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','m',' '), HB_TAG('Q','U','Z',' ')}, /* Margos-Yarowilca-Lauricocha Quechua -> Quechua */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','W','H',' ')}, /* North Junín Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','n',' '), HB_TAG('Q','U','Z',' ')}, /* North Junín Quechua -> Quechua */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','V','I',' ')}, /* Napo Lowland Quechua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','o',' '), HB_TAG('Q','U','Z',' ')}, /* Napo Lowland Quechua -> Quechua */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','W','H',' ')}, /* Pacaraos Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','p',' '), HB_TAG('Q','U','Z',' ')}, /* Pacaraos Quechua -> Quechua */
+ {HB_TAG('q','v','s',' '), HB_TAG('Q','U','Z',' ')}, /* San Martín Quechua -> Quechua */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','W','H',' ')}, /* Huaylla Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','v','w',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylla Wanca Quechua -> Quechua */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','V','I',' ')}, /* Northern Pastaza Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','v','z',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Pastaza Quichua -> Quechua */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','W','H',' ')}, /* Corongo Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','a',' '), HB_TAG('Q','U','Z',' ')}, /* Corongo Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','c',' '), HB_TAG('Q','U','Z',' ')}, /* Classical Quechua -> Quechua */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','W','H',' ')}, /* Huaylas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','h',' '), HB_TAG('Q','U','Z',' ')}, /* Huaylas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','W','H',' ')}, /* Sihuas Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','w','s',' '), HB_TAG('Q','U','Z',' ')}, /* Sihuas Ancash Quechua -> Quechua */
+ {HB_TAG('q','w','t',' '), HB_TAG('A','T','H',' ')}, /* Kwalhioqua-Tlatskanai -> Athapaskan */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','W','H',' ')}, /* Chiquián Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','a',' '), HB_TAG('Q','U','Z',' ')}, /* Chiquián Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','W','H',' ')}, /* Chincha Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','c',' '), HB_TAG('Q','U','Z',' ')}, /* Chincha Quechua -> Quechua */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','W','H',' ')}, /* Panao Huánuco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','h',' '), HB_TAG('Q','U','Z',' ')}, /* Panao Huánuco Quechua -> Quechua */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','V','I',' ')}, /* Salasaca Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','l',' '), HB_TAG('Q','U','Z',' ')}, /* Salasaca Highland Quichua -> Quechua */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','W','H',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','n',' '), HB_TAG('Q','U','Z',' ')}, /* Northern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','W','H',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','o',' '), HB_TAG('Q','U','Z',' ')}, /* Southern Conchucos Ancash Quechua -> Quechua */
+ {HB_TAG('q','x','p',' '), HB_TAG('Q','U','Z',' ')}, /* Puno Quechua -> Quechua */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','V','I',' ')}, /* Cañar Highland Quichua -> Quechua (Ecuador) */
+ {HB_TAG('q','x','r',' '), HB_TAG('Q','U','Z',' ')}, /* Cañar Highland Quichua -> Quechua */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','W','H',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','t',' '), HB_TAG('Q','U','Z',' ')}, /* Santa Ana de Tusi Pasco Quechua -> Quechua */
+ {HB_TAG('q','x','u',' '), HB_TAG('Q','U','Z',' ')}, /* Arequipa-La Unión Quechua -> Quechua */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','W','H',' ')}, /* Jauja Wanca Quechua -> Quechua (Peru) */
+ {HB_TAG('q','x','w',' '), HB_TAG('Q','U','Z',' ')}, /* Jauja Wanca Quechua -> Quechua */
+ {HB_TAG('r','a','g',' '), HB_TAG('L','U','H',' ')}, /* Logooli -> Luyia */
+/*{HB_TAG('r','a','j',' '), HB_TAG('R','A','J',' ')},*/ /* Rajasthani [macrolanguage] */
+ {HB_TAG('r','a','l',' '), HB_TAG('Q','I','N',' ')}, /* Ralte -> Chin */
+/*{HB_TAG('r','a','r',' '), HB_TAG('R','A','R',' ')},*/ /* Rarotongan */
+ {HB_TAG('r','b','b',' '), HB_TAG('P','L','G',' ')}, /* Rumai Palaung -> Palaung */
+ {HB_TAG('r','b','l',' '), HB_TAG('B','I','K',' ')}, /* Miraya Bikol -> Bikol */
+ {HB_TAG('r','c','f',' '), HB_TAG('C','P','P',' ')}, /* Réunion Creole French -> Creoles */
+/*{HB_TAG('r','e','j',' '), HB_TAG('R','E','J',' ')},*/ /* Rejang */
+/*{HB_TAG('r','h','g',' '), HB_TAG('R','H','G',' ')},*/ /* Rohingya */
+/*{HB_TAG('r','i','a',' '), HB_TAG('R','I','A',' ')},*/ /* Riang (India) */
+ {HB_TAG('r','i','f',' '), HB_TAG('R','I','F',' ')}, /* Tarifit */
+ {HB_TAG('r','i','f',' '), HB_TAG('B','B','R',' ')}, /* Tarifit -> Berber */
+/*{HB_TAG('r','i','t',' '), HB_TAG('R','I','T',' ')},*/ /* Ritharrngu -> Ritarungo */
+ {HB_TAG('r','k','i',' '), HB_TAG('A','R','K',' ')}, /* Rakhine */
+/*{HB_TAG('r','k','w',' '), HB_TAG('R','K','W',' ')},*/ /* Arakwal */
+ {HB_TAG('r','m','c',' '), HB_TAG('R','O','Y',' ')}, /* Carpathian Romani -> Romany */
+ {HB_TAG('r','m','f',' '), HB_TAG('R','O','Y',' ')}, /* Kalo Finnish Romani -> Romany */
+ {HB_TAG('r','m','l',' '), HB_TAG('R','O','Y',' ')}, /* Baltic Romani -> Romany */
+ {HB_TAG('r','m','n',' '), HB_TAG('R','O','Y',' ')}, /* Balkan Romani -> Romany */
+ {HB_TAG('r','m','o',' '), HB_TAG('R','O','Y',' ')}, /* Sinte Romani -> Romany */
+ {HB_TAG('r','m','s',' '), HB_TAG_NONE }, /* Romanian Sign Language != Romansh */
+ {HB_TAG('r','m','w',' '), HB_TAG('R','O','Y',' ')}, /* Welsh Romani -> Romany */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','M','Y',' ')}, /* Vlax Romani */
+ {HB_TAG('r','m','y',' '), HB_TAG('R','O','Y',' ')}, /* Vlax Romani -> Romany */
+ {HB_TAG('r','m','z',' '), HB_TAG('A','R','K',' ')}, /* Marma -> Rakhine */
+ {HB_TAG('r','o','m',' '), HB_TAG('R','O','Y',' ')}, /* Romany [macrolanguage] */
+ {HB_TAG('r','o','p',' '), HB_TAG('C','P','P',' ')}, /* Kriol -> Creoles */
+ {HB_TAG('r','t','c',' '), HB_TAG('Q','I','N',' ')}, /* Rungtu Chin -> Chin */
+/*{HB_TAG('r','t','m',' '), HB_TAG('R','T','M',' ')},*/ /* Rotuman */
+ {HB_TAG('r','u','e',' '), HB_TAG('R','S','Y',' ')}, /* Rusyn */
+/*{HB_TAG('r','u','p',' '), HB_TAG('R','U','P',' ')},*/ /* Aromanian */
+ {HB_TAG('r','w','r',' '), HB_TAG('M','A','W',' ')}, /* Marwari (India) */
+ {HB_TAG('s','a','d',' '), HB_TAG_NONE }, /* Sandawe != Sadri */
+ {HB_TAG('s','a','h',' '), HB_TAG('Y','A','K',' ')}, /* Yakut -> Sakha */
+ {HB_TAG('s','a','m',' '), HB_TAG('P','A','A',' ')}, /* Samaritan Aramaic -> Palestinian Aramaic */
+/*{HB_TAG('s','a','s',' '), HB_TAG('S','A','S',' ')},*/ /* Sasak */
+/*{HB_TAG('s','a','t',' '), HB_TAG('S','A','T',' ')},*/ /* Santali */
+ {HB_TAG('s','a','y',' '), HB_TAG_NONE }, /* Saya != Sayisi */
+ {HB_TAG('s','c','f',' '), HB_TAG('C','P','P',' ')}, /* San Miguel Creole French -> Creoles */
+ {HB_TAG('s','c','h',' '), HB_TAG('Q','I','N',' ')}, /* Sakachep -> Chin */
+ {HB_TAG('s','c','i',' '), HB_TAG('C','P','P',' ')}, /* Sri Lankan Creole Malay -> Creoles */
+ {HB_TAG('s','c','k',' '), HB_TAG('S','A','D',' ')}, /* Sadri */
+/*{HB_TAG('s','c','n',' '), HB_TAG('S','C','N',' ')},*/ /* Sicilian */
+/*{HB_TAG('s','c','o',' '), HB_TAG('S','C','O',' ')},*/ /* Scots */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','C','S',' ')}, /* North Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('S','L','A',' ')}, /* North Slavey -> Slavey */
+ {HB_TAG('s','c','s',' '), HB_TAG('A','T','H',' ')}, /* North Slavey -> Athapaskan */
+ {HB_TAG('s','d','c',' '), HB_TAG('S','R','D',' ')}, /* Sassarese Sardinian -> Sardinian */
+ {HB_TAG('s','d','h',' '), HB_TAG('K','U','R',' ')}, /* Southern Kurdish -> Kurdish */
+ {HB_TAG('s','d','n',' '), HB_TAG('S','R','D',' ')}, /* Gallurese Sardinian -> Sardinian */
+ {HB_TAG('s','d','s',' '), HB_TAG('B','B','R',' ')}, /* Sened -> Berber */
+ {HB_TAG('s','e','h',' '), HB_TAG('S','N','A',' ')}, /* Sena */
+ {HB_TAG('s','e','k',' '), HB_TAG('A','T','H',' ')}, /* Sekani -> Athapaskan */
+/*{HB_TAG('s','e','l',' '), HB_TAG('S','E','L',' ')},*/ /* Selkup */
+ {HB_TAG('s','e','z',' '), HB_TAG('Q','I','N',' ')}, /* Senthang Chin -> Chin */
+ {HB_TAG('s','f','m',' '), HB_TAG('S','F','M',' ')}, /* Small Flowery Miao */
+ {HB_TAG('s','f','m',' '), HB_TAG('H','M','N',' ')}, /* Small Flowery Miao -> Hmong */
+/*{HB_TAG('s','g','a',' '), HB_TAG('S','G','A',' ')},*/ /* Old Irish (to 900) */
+ {HB_TAG('s','g','c',' '), HB_TAG('K','A','L',' ')}, /* Kipsigis -> Kalenjin */
+ {HB_TAG('s','g','o',' '), HB_TAG_NONE }, /* Songa (retired code) != Sango */
+/*{HB_TAG('s','g','s',' '), HB_TAG('S','G','S',' ')},*/ /* Samogitian */
+ {HB_TAG('s','g','w',' '), HB_TAG('C','H','G',' ')}, /* Sebat Bet Gurage -> Chaha Gurage */
+ {HB_TAG('s','h','i',' '), HB_TAG('S','H','I',' ')}, /* Tachelhit */
+ {HB_TAG('s','h','i',' '), HB_TAG('B','B','R',' ')}, /* Tachelhit -> Berber */
+ {HB_TAG('s','h','l',' '), HB_TAG('Q','I','N',' ')}, /* Shendu -> Chin */
+/*{HB_TAG('s','h','n',' '), HB_TAG('S','H','N',' ')},*/ /* Shan */
+ {HB_TAG('s','h','u',' '), HB_TAG('A','R','A',' ')}, /* Chadian Arabic -> Arabic */
+ {HB_TAG('s','h','y',' '), HB_TAG('B','B','R',' ')}, /* Tachawit -> Berber */
+ {HB_TAG('s','i','b',' '), HB_TAG_NONE }, /* Sebop != Sibe */
+/*{HB_TAG('s','i','d',' '), HB_TAG('S','I','D',' ')},*/ /* Sidamo */
+ {HB_TAG('s','i','g',' '), HB_TAG_NONE }, /* Paasaal != Silte Gurage */
+ {HB_TAG('s','i','z',' '), HB_TAG('B','B','R',' ')}, /* Siwi -> Berber */
+ {HB_TAG('s','j','d',' '), HB_TAG('K','S','M',' ')}, /* Kildin Sami */
+ {HB_TAG('s','j','o',' '), HB_TAG('S','I','B',' ')}, /* Xibe -> Sibe */
+ {HB_TAG('s','j','s',' '), HB_TAG('B','B','R',' ')}, /* Senhaja De Srair -> Berber */
+ {HB_TAG('s','k','g',' '), HB_TAG('M','L','G',' ')}, /* Sakalava Malagasy -> Malagasy */
+ {HB_TAG('s','k','r',' '), HB_TAG('S','R','K',' ')}, /* Saraiki */
+ {HB_TAG('s','k','s',' '), HB_TAG_NONE }, /* Maia != Skolt Sami */
+ {HB_TAG('s','k','w',' '), HB_TAG('C','P','P',' ')}, /* Skepi Creole Dutch -> Creoles */
+ {HB_TAG('s','k','y',' '), HB_TAG_NONE }, /* Sikaiana != Slovak */
+ {HB_TAG('s','l','a',' '), HB_TAG_NONE }, /* Slavic [collection] != Slavey */
+ {HB_TAG('s','m','a',' '), HB_TAG('S','S','M',' ')}, /* Southern Sami */
+ {HB_TAG('s','m','d',' '), HB_TAG('M','B','N',' ')}, /* Sama (retired code) -> Mbundu */
+ {HB_TAG('s','m','j',' '), HB_TAG('L','S','M',' ')}, /* Lule Sami */
+ {HB_TAG('s','m','l',' '), HB_TAG_NONE }, /* Central Sama != Somali */
+ {HB_TAG('s','m','n',' '), HB_TAG('I','S','M',' ')}, /* Inari Sami */
+ {HB_TAG('s','m','s',' '), HB_TAG('S','K','S',' ')}, /* Skolt Sami */
+ {HB_TAG('s','m','t',' '), HB_TAG('Q','I','N',' ')}, /* Simte -> Chin */
+ {HB_TAG('s','n','b',' '), HB_TAG('I','B','A',' ')}, /* Sebuyau (retired code) -> Iban */
+ {HB_TAG('s','n','h',' '), HB_TAG_NONE }, /* Shinabo (retired code) != Sinhala (Sinhalese) */
+/*{HB_TAG('s','n','k',' '), HB_TAG('S','N','K',' ')},*/ /* Soninke */
+ {HB_TAG('s','o','g',' '), HB_TAG_NONE }, /* Sogdian != Sodo Gurage */
+/*{HB_TAG('s','o','p',' '), HB_TAG('S','O','P',' ')},*/ /* Songe */
+ {HB_TAG('s','p','v',' '), HB_TAG('O','R','I',' ')}, /* Sambalpuri -> Odia (formerly Oriya) */
+ {HB_TAG('s','p','y',' '), HB_TAG('K','A','L',' ')}, /* Sabaot -> Kalenjin */
+ {HB_TAG('s','r','b',' '), HB_TAG_NONE }, /* Sora != Serbian */
+ {HB_TAG('s','r','c',' '), HB_TAG('S','R','D',' ')}, /* Logudorese Sardinian -> Sardinian */
+ {HB_TAG('s','r','k',' '), HB_TAG_NONE }, /* Serudung Murut != Saraiki */
+ {HB_TAG('s','r','m',' '), HB_TAG('C','P','P',' ')}, /* Saramaccan -> Creoles */
+ {HB_TAG('s','r','n',' '), HB_TAG('C','P','P',' ')}, /* Sranan Tongo -> Creoles */
+ {HB_TAG('s','r','o',' '), HB_TAG('S','R','D',' ')}, /* Campidanese Sardinian -> Sardinian */
+/*{HB_TAG('s','r','r',' '), HB_TAG('S','R','R',' ')},*/ /* Serer */
+ {HB_TAG('s','r','s',' '), HB_TAG('A','T','H',' ')}, /* Sarsi -> Athapaskan */
+ {HB_TAG('s','s','h',' '), HB_TAG('A','R','A',' ')}, /* Shihhi Arabic -> Arabic */
+ {HB_TAG('s','s','l',' '), HB_TAG_NONE }, /* Western Sisaala != South Slavey */
+ {HB_TAG('s','s','m',' '), HB_TAG_NONE }, /* Semnam != Southern Sami */
+ {HB_TAG('s','t','a',' '), HB_TAG('C','P','P',' ')}, /* Settla -> Creoles */
+/*{HB_TAG('s','t','q',' '), HB_TAG('S','T','Q',' ')},*/ /* Saterfriesisch -> Saterland Frisian */
+ {HB_TAG('s','t','v',' '), HB_TAG('S','I','G',' ')}, /* Silt'e -> Silte Gurage */
+/*{HB_TAG('s','u','k',' '), HB_TAG('S','U','K',' ')},*/ /* Sukuma */
+ {HB_TAG('s','u','q',' '), HB_TAG('S','U','R',' ')}, /* Suri */
+ {HB_TAG('s','u','r',' '), HB_TAG_NONE }, /* Mwaghavul != Suri */
+/*{HB_TAG('s','v','a',' '), HB_TAG('S','V','A',' ')},*/ /* Svan */
+ {HB_TAG('s','v','c',' '), HB_TAG('C','P','P',' ')}, /* Vincentian Creole English -> Creoles */
+ {HB_TAG('s','v','e',' '), HB_TAG_NONE }, /* Serili != Swedish */
+ {HB_TAG('s','w','b',' '), HB_TAG('C','M','R',' ')}, /* Maore Comorian -> Comorian */
+ {HB_TAG('s','w','c',' '), HB_TAG('S','W','K',' ')}, /* Congo Swahili -> Swahili */
+ {HB_TAG('s','w','h',' '), HB_TAG('S','W','K',' ')}, /* Swahili */
+ {HB_TAG('s','w','k',' '), HB_TAG_NONE }, /* Malawi Sena != Swahili */
+ {HB_TAG('s','w','n',' '), HB_TAG('B','B','R',' ')}, /* Sawknah -> Berber */
+ {HB_TAG('s','w','v',' '), HB_TAG('M','A','W',' ')}, /* Shekhawati -> Marwari */
+/*{HB_TAG('s','x','u',' '), HB_TAG('S','X','U',' ')},*/ /* Upper Saxon */
+ {HB_TAG('s','y','c',' '), HB_TAG('S','Y','R',' ')}, /* Classical Syriac -> Syriac */
+/*{HB_TAG('s','y','l',' '), HB_TAG('S','Y','L',' ')},*/ /* Sylheti */
+/*{HB_TAG('s','y','r',' '), HB_TAG('S','Y','R',' ')},*/ /* Syriac [macrolanguage] */
+/*{HB_TAG('s','z','l',' '), HB_TAG('S','Z','L',' ')},*/ /* Silesian */
+ {HB_TAG('t','a','a',' '), HB_TAG('A','T','H',' ')}, /* Lower Tanana -> Athapaskan */
+/*{HB_TAG('t','a','b',' '), HB_TAG('T','A','B',' ')},*/ /* Tabassaran -> Tabasaran */
+ {HB_TAG('t','a','j',' '), HB_TAG_NONE }, /* Eastern Tamang != Tajiki */
+ {HB_TAG('t','a','q',' '), HB_TAG('T','M','H',' ')}, /* Tamasheq -> Tamashek */
+ {HB_TAG('t','a','q',' '), HB_TAG('B','B','R',' ')}, /* Tamasheq -> Berber */
+ {HB_TAG('t','a','s',' '), HB_TAG('C','P','P',' ')}, /* Tay Boi -> Creoles */
+ {HB_TAG('t','a','u',' '), HB_TAG('A','T','H',' ')}, /* Upper Tanana -> Athapaskan */
+ {HB_TAG('t','c','b',' '), HB_TAG('A','T','H',' ')}, /* Tanacross -> Athapaskan */
+ {HB_TAG('t','c','e',' '), HB_TAG('A','T','H',' ')}, /* Southern Tutchone -> Athapaskan */
+ {HB_TAG('t','c','h',' '), HB_TAG('C','P','P',' ')}, /* Turks And Caicos Creole English -> Creoles */
+ {HB_TAG('t','c','p',' '), HB_TAG('Q','I','N',' ')}, /* Tawr Chin -> Chin */
+ {HB_TAG('t','c','s',' '), HB_TAG('C','P','P',' ')}, /* Torres Strait Creole -> Creoles */
+ {HB_TAG('t','c','y',' '), HB_TAG('T','U','L',' ')}, /* Tulu -> Tumbuka */
+ {HB_TAG('t','c','z',' '), HB_TAG('Q','I','N',' ')}, /* Thado Chin -> Chin */
+/*{HB_TAG('t','d','d',' '), HB_TAG('T','D','D',' ')},*/ /* Tai Nüa -> Dehong Dai */
+ {HB_TAG('t','d','x',' '), HB_TAG('M','L','G',' ')}, /* Tandroy-Mahafaly Malagasy -> Malagasy */
+ {HB_TAG('t','e','c',' '), HB_TAG('K','A','L',' ')}, /* Terik -> Kalenjin */
+ {HB_TAG('t','e','m',' '), HB_TAG('T','M','N',' ')}, /* Timne -> Temne */
+/*{HB_TAG('t','e','t',' '), HB_TAG('T','E','T',' ')},*/ /* Tetum */
+ {HB_TAG('t','e','z',' '), HB_TAG('B','B','R',' ')}, /* Tetserret -> Berber */
+ {HB_TAG('t','f','n',' '), HB_TAG('A','T','H',' ')}, /* Tanaina -> Athapaskan */
+ {HB_TAG('t','g','h',' '), HB_TAG('C','P','P',' ')}, /* Tobagonian Creole English -> Creoles */
+ {HB_TAG('t','g','j',' '), HB_TAG('N','I','S',' ')}, /* Tagin -> Nisi */
+ {HB_TAG('t','g','n',' '), HB_TAG_NONE }, /* Tandaganon != Tongan */
+ {HB_TAG('t','g','r',' '), HB_TAG_NONE }, /* Tareng != Tigre */
+ {HB_TAG('t','g','x',' '), HB_TAG('A','T','H',' ')}, /* Tagish -> Athapaskan */
+ {HB_TAG('t','g','y',' '), HB_TAG_NONE }, /* Togoyo != Tigrinya */
+ {HB_TAG('t','h','t',' '), HB_TAG('A','T','H',' ')}, /* Tahltan -> Athapaskan */
+ {HB_TAG('t','h','v',' '), HB_TAG('T','M','H',' ')}, /* Tahaggart Tamahaq -> Tamashek */
+ {HB_TAG('t','h','v',' '), HB_TAG('B','B','R',' ')}, /* Tahaggart Tamahaq -> Berber */
+ {HB_TAG('t','h','z',' '), HB_TAG('T','M','H',' ')}, /* Tayart Tamajeq -> Tamashek */
+ {HB_TAG('t','h','z',' '), HB_TAG('B','B','R',' ')}, /* Tayart Tamajeq -> Berber */
+ {HB_TAG('t','i','a',' '), HB_TAG('B','B','R',' ')}, /* Tidikelt Tamazight -> Berber */
+ {HB_TAG('t','i','g',' '), HB_TAG('T','G','R',' ')}, /* Tigre */
+/*{HB_TAG('t','i','v',' '), HB_TAG('T','I','V',' ')},*/ /* Tiv */
+/*{HB_TAG('t','j','l',' '), HB_TAG('T','J','L',' ')},*/ /* Tai Laing */
+ {HB_TAG('t','j','o',' '), HB_TAG('B','B','R',' ')}, /* Temacine Tamazight -> Berber */
+ {HB_TAG('t','k','g',' '), HB_TAG('M','L','G',' ')}, /* Tesaka Malagasy -> Malagasy */
+ {HB_TAG('t','k','m',' '), HB_TAG_NONE }, /* Takelma != Turkmen */
+/*{HB_TAG('t','l','i',' '), HB_TAG('T','L','I',' ')},*/ /* Tlingit */
+ {HB_TAG('t','m','g',' '), HB_TAG('C','P','P',' ')}, /* Ternateño -> Creoles */
+ {HB_TAG('t','m','h',' '), HB_TAG('T','M','H',' ')}, /* Tamashek [macrolanguage] */
+ {HB_TAG('t','m','h',' '), HB_TAG('B','B','R',' ')}, /* Tamashek [macrolanguage] -> Berber */
+ {HB_TAG('t','m','n',' '), HB_TAG_NONE }, /* Taman (Indonesia) != Temne */
+ {HB_TAG('t','m','w',' '), HB_TAG('M','L','Y',' ')}, /* Temuan -> Malay */
+ {HB_TAG('t','n','a',' '), HB_TAG_NONE }, /* Tacana != Tswana */
+ {HB_TAG('t','n','e',' '), HB_TAG_NONE }, /* Tinoc Kallahan (retired code) != Tundra Enets */
+ {HB_TAG('t','n','f',' '), HB_TAG('D','R','I',' ')}, /* Tangshewi (retired code) -> Dari */
+ {HB_TAG('t','n','f',' '), HB_TAG('F','A','R',' ')}, /* Tangshewi (retired code) -> Persian */
+ {HB_TAG('t','n','g',' '), HB_TAG_NONE }, /* Tobanga != Tonga */
+ {HB_TAG('t','o','d',' '), HB_TAG('T','O','D','0')}, /* Toma */
+ {HB_TAG('t','o','i',' '), HB_TAG('T','N','G',' ')}, /* Tonga (Zambia) */
+ {HB_TAG('t','o','j',' '), HB_TAG('M','Y','N',' ')}, /* Tojolabal -> Mayan */
+ {HB_TAG('t','o','l',' '), HB_TAG('A','T','H',' ')}, /* Tolowa -> Athapaskan */
+ {HB_TAG('t','o','r',' '), HB_TAG('B','A','D','0')}, /* Togbo-Vara Banda -> Banda */
+ {HB_TAG('t','p','i',' '), HB_TAG('T','P','I',' ')}, /* Tok Pisin */
+ {HB_TAG('t','p','i',' '), HB_TAG('C','P','P',' ')}, /* Tok Pisin -> Creoles */
+ {HB_TAG('t','r','f',' '), HB_TAG('C','P','P',' ')}, /* Trinidadian Creole English -> Creoles */
+ {HB_TAG('t','r','k',' '), HB_TAG_NONE }, /* Turkic [collection] != Turkish */
+ {HB_TAG('t','r','u',' '), HB_TAG('T','U','A',' ')}, /* Turoyo -> Turoyo Aramaic */
+ {HB_TAG('t','r','u',' '), HB_TAG('S','Y','R',' ')}, /* Turoyo -> Syriac */
+ {HB_TAG('t','s','g',' '), HB_TAG_NONE }, /* Tausug != Tsonga */
+/*{HB_TAG('t','s','j',' '), HB_TAG('T','S','J',' ')},*/ /* Tshangla */
+ {HB_TAG('t','t','c',' '), HB_TAG('M','Y','N',' ')}, /* Tektiteko -> Mayan */
+ {HB_TAG('t','t','m',' '), HB_TAG('A','T','H',' ')}, /* Northern Tutchone -> Athapaskan */
+ {HB_TAG('t','t','q',' '), HB_TAG('T','M','H',' ')}, /* Tawallammat Tamajaq -> Tamashek */
+ {HB_TAG('t','t','q',' '), HB_TAG('B','B','R',' ')}, /* Tawallammat Tamajaq -> Berber */
+ {HB_TAG('t','u','a',' '), HB_TAG_NONE }, /* Wiarumus != Turoyo Aramaic */
+ {HB_TAG('t','u','l',' '), HB_TAG_NONE }, /* Tula != Tumbuka */
+/*{HB_TAG('t','u','m',' '), HB_TAG('T','U','M',' ')},*/ /* Tumbuka -> Tulu */
+ {HB_TAG('t','u','u',' '), HB_TAG('A','T','H',' ')}, /* Tututni -> Athapaskan */
+ {HB_TAG('t','u','v',' '), HB_TAG_NONE }, /* Turkana != Tuvin */
+ {HB_TAG('t','u','y',' '), HB_TAG('K','A','L',' ')}, /* Tugen -> Kalenjin */
+/*{HB_TAG('t','v','l',' '), HB_TAG('T','V','L',' ')},*/ /* Tuvalu */
+ {HB_TAG('t','v','y',' '), HB_TAG('C','P','P',' ')}, /* Timor Pidgin -> Creoles */
+ {HB_TAG('t','x','c',' '), HB_TAG('A','T','H',' ')}, /* Tsetsaut -> Athapaskan */
+ {HB_TAG('t','x','y',' '), HB_TAG('M','L','G',' ')}, /* Tanosy Malagasy -> Malagasy */
+ {HB_TAG('t','y','v',' '), HB_TAG('T','U','V',' ')}, /* Tuvinian -> Tuvin */
+/*{HB_TAG('t','y','z',' '), HB_TAG('T','Y','Z',' ')},*/ /* Tày */
+ {HB_TAG('t','z','h',' '), HB_TAG('M','Y','N',' ')}, /* Tzeltal -> Mayan */
+ {HB_TAG('t','z','j',' '), HB_TAG('M','Y','N',' ')}, /* Tz'utujil -> Mayan */
+ {HB_TAG('t','z','m',' '), HB_TAG('T','Z','M',' ')}, /* Central Atlas Tamazight -> Tamazight */
+ {HB_TAG('t','z','m',' '), HB_TAG('B','B','R',' ')}, /* Central Atlas Tamazight -> Berber */
+ {HB_TAG('t','z','o',' '), HB_TAG('T','Z','O',' ')}, /* Tzotzil */
+ {HB_TAG('t','z','o',' '), HB_TAG('M','Y','N',' ')}, /* Tzotzil -> Mayan */
+ {HB_TAG('u','b','l',' '), HB_TAG('B','I','K',' ')}, /* Buhi'non Bikol -> Bikol */
+/*{HB_TAG('u','d','m',' '), HB_TAG('U','D','M',' ')},*/ /* Udmurt */
+ {HB_TAG('u','k','i',' '), HB_TAG('K','U','I',' ')}, /* Kui (India) */
+ {HB_TAG('u','l','n',' '), HB_TAG('C','P','P',' ')}, /* Unserdeutsch -> Creoles */
+/*{HB_TAG('u','m','b',' '), HB_TAG('U','M','B',' ')},*/ /* Umbundu */
+ {HB_TAG('u','n','r',' '), HB_TAG('M','U','N',' ')}, /* Mundari */
+ {HB_TAG('u','r','k',' '), HB_TAG('M','L','Y',' ')}, /* Urak Lawoi' -> Malay */
+ {HB_TAG('u','s','p',' '), HB_TAG('M','Y','N',' ')}, /* Uspanteco -> Mayan */
+ {HB_TAG('u','z','n',' '), HB_TAG('U','Z','B',' ')}, /* Northern Uzbek -> Uzbek */
+ {HB_TAG('u','z','s',' '), HB_TAG('U','Z','B',' ')}, /* Southern Uzbek -> Uzbek */
+ {HB_TAG('v','a','p',' '), HB_TAG('Q','I','N',' ')}, /* Vaiphei -> Chin */
+/*{HB_TAG('v','e','c',' '), HB_TAG('V','E','C',' ')},*/ /* Venetian */
+ {HB_TAG('v','i','c',' '), HB_TAG('C','P','P',' ')}, /* Virgin Islands Creole English -> Creoles */
+ {HB_TAG('v','i','t',' '), HB_TAG_NONE }, /* Viti != Vietnamese */
+ {HB_TAG('v','k','k',' '), HB_TAG('M','L','Y',' ')}, /* Kaur -> Malay */
+ {HB_TAG('v','k','p',' '), HB_TAG('C','P','P',' ')}, /* Korlai Creole Portuguese -> Creoles */
+ {HB_TAG('v','k','t',' '), HB_TAG('M','L','Y',' ')}, /* Tenggarong Kutai Malay -> Malay */
+ {HB_TAG('v','l','s',' '), HB_TAG('F','L','E',' ')}, /* Vlaams -> Dutch (Flemish) */
+ {HB_TAG('v','m','w',' '), HB_TAG('M','A','K',' ')}, /* Makhuwa */
+/*{HB_TAG('v','r','o',' '), HB_TAG('V','R','O',' ')},*/ /* Võro */
+ {HB_TAG('w','a','g',' '), HB_TAG_NONE }, /* Wa'ema != Wagdi */
+/*{HB_TAG('w','a','r',' '), HB_TAG('W','A','R',' ')},*/ /* Waray (Philippines) -> Waray-Waray */
+ {HB_TAG('w','b','m',' '), HB_TAG('W','A',' ',' ')}, /* Wa */
+ {HB_TAG('w','b','r',' '), HB_TAG('W','A','G',' ')}, /* Wagdi */
+ {HB_TAG('w','b','r',' '), HB_TAG('R','A','J',' ')}, /* Wagdi -> Rajasthani */
+/*{HB_TAG('w','c','i',' '), HB_TAG('W','C','I',' ')},*/ /* Waci Gbe */
+ {HB_TAG('w','e','a',' '), HB_TAG('K','R','N',' ')}, /* Wewaw -> Karen */
+ {HB_TAG('w','e','s',' '), HB_TAG('C','P','P',' ')}, /* Cameroon Pidgin -> Creoles */
+ {HB_TAG('w','e','u',' '), HB_TAG('Q','I','N',' ')}, /* Rawngtu Chin -> Chin */
+ {HB_TAG('w','l','c',' '), HB_TAG('C','M','R',' ')}, /* Mwali Comorian -> Comorian */
+ {HB_TAG('w','l','e',' '), HB_TAG('S','I','G',' ')}, /* Wolane -> Silte Gurage */
+ {HB_TAG('w','l','k',' '), HB_TAG('A','T','H',' ')}, /* Wailaki -> Athapaskan */
+ {HB_TAG('w','n','i',' '), HB_TAG('C','M','R',' ')}, /* Ndzwani Comorian -> Comorian */
+ {HB_TAG('w','r','y',' '), HB_TAG('M','A','W',' ')}, /* Merwari -> Marwari */
+ {HB_TAG('w','s','g',' '), HB_TAG('G','O','N',' ')}, /* Adilabad Gondi -> Gondi */
+/*{HB_TAG('w','t','m',' '), HB_TAG('W','T','M',' ')},*/ /* Mewati */
+ {HB_TAG('w','u','u',' '), HB_TAG('Z','H','S',' ')}, /* Wu Chinese -> Chinese, Simplified */
+ {HB_TAG('x','a','l',' '), HB_TAG('K','L','M',' ')}, /* Kalmyk */
+ {HB_TAG('x','a','l',' '), HB_TAG('T','O','D',' ')}, /* Kalmyk -> Todo */
+ {HB_TAG('x','a','n',' '), HB_TAG('S','E','K',' ')}, /* Xamtanga -> Sekota */
+ {HB_TAG('x','b','d',' '), HB_TAG_NONE }, /* Bindal != Lü */
+/*{HB_TAG('x','j','b',' '), HB_TAG('X','J','B',' ')},*/ /* Minjungbal -> Minjangbal */
+/*{HB_TAG('x','k','f',' '), HB_TAG('X','K','F',' ')},*/ /* Khengkha */
+ {HB_TAG('x','m','g',' '), HB_TAG('B','M','L',' ')}, /* Mengaka -> Bamileke */
+ {HB_TAG('x','m','m',' '), HB_TAG('M','L','Y',' ')}, /* Manado Malay -> Malay */
+ {HB_TAG('x','m','m',' '), HB_TAG('C','P','P',' ')}, /* Manado Malay -> Creoles */
+ {HB_TAG('x','m','v',' '), HB_TAG('M','L','G',' ')}, /* Antankarana Malagasy -> Malagasy */
+ {HB_TAG('x','m','w',' '), HB_TAG('M','L','G',' ')}, /* Tsimihety Malagasy -> Malagasy */
+ {HB_TAG('x','n','j',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Tanzania) -> Sutu */
+ {HB_TAG('x','n','q',' '), HB_TAG('S','X','T',' ')}, /* Ngoni (Mozambique) -> Sutu */
+ {HB_TAG('x','n','r',' '), HB_TAG('D','G','R',' ')}, /* Kangri -> Dogri (macrolanguage) */
+/*{HB_TAG('x','o','g',' '), HB_TAG('X','O','G',' ')},*/ /* Soga */
+ {HB_TAG('x','p','e',' '), HB_TAG('X','P','E',' ')}, /* Liberia Kpelle -> Kpelle (Liberia) */
+ {HB_TAG('x','p','e',' '), HB_TAG('K','P','L',' ')}, /* Liberia Kpelle -> Kpelle */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','S','L',' ')}, /* South Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('S','L','A',' ')}, /* South Slavey -> Slavey */
+ {HB_TAG('x','s','l',' '), HB_TAG('A','T','H',' ')}, /* South Slavey -> Athapaskan */
+ {HB_TAG('x','s','t',' '), HB_TAG('S','I','G',' ')}, /* Silt'e (retired code) -> Silte Gurage */
+/*{HB_TAG('x','u','b',' '), HB_TAG('X','U','B',' ')},*/ /* Betta Kurumba -> Bette Kuruma */
+/*{HB_TAG('x','u','j',' '), HB_TAG('X','U','J',' ')},*/ /* Jennu Kurumba -> Jennu Kuruma */
+ {HB_TAG('x','u','p',' '), HB_TAG('A','T','H',' ')}, /* Upper Umpqua -> Athapaskan */
+ {HB_TAG('x','w','o',' '), HB_TAG('T','O','D',' ')}, /* Written Oirat -> Todo */
+ {HB_TAG('y','a','j',' '), HB_TAG('B','A','D','0')}, /* Banda-Yangere -> Banda */
+ {HB_TAG('y','a','k',' '), HB_TAG_NONE }, /* Yakama != Sakha */
+/*{HB_TAG('y','a','o',' '), HB_TAG('Y','A','O',' ')},*/ /* Yao */
+/*{HB_TAG('y','a','p',' '), HB_TAG('Y','A','P',' ')},*/ /* Yapese */
+ {HB_TAG('y','b','a',' '), HB_TAG_NONE }, /* Yala != Yoruba */
+ {HB_TAG('y','b','b',' '), HB_TAG('B','M','L',' ')}, /* Yemba -> Bamileke */
+ {HB_TAG('y','b','d',' '), HB_TAG('A','R','K',' ')}, /* Yangbye (retired code) -> Rakhine */
+ {HB_TAG('y','d','d',' '), HB_TAG('J','I','I',' ')}, /* Eastern Yiddish -> Yiddish */
+/*{HB_TAG('y','g','p',' '), HB_TAG('Y','G','P',' ')},*/ /* Gepo */
+ {HB_TAG('y','i','h',' '), HB_TAG('J','I','I',' ')}, /* Western Yiddish -> Yiddish */
+ {HB_TAG('y','i','m',' '), HB_TAG_NONE }, /* Yimchungru Naga != Yi Modern */
+/*{HB_TAG('y','n','a',' '), HB_TAG('Y','N','A',' ')},*/ /* Aluo */
+ {HB_TAG('y','o','s',' '), HB_TAG('Q','I','N',' ')}, /* Yos (retired code) -> Chin */
+ {HB_TAG('y','u','a',' '), HB_TAG('M','Y','N',' ')}, /* Yucateco -> Mayan */
+ {HB_TAG('y','u','e',' '), HB_TAG('Z','H','H',' ')}, /* Yue Chinese -> Chinese, Traditional, Hong Kong SAR */
+/*{HB_TAG('y','w','q',' '), HB_TAG('Y','W','Q',' ')},*/ /* Wuding-Luquan Yi */
+ {HB_TAG('z','c','h',' '), HB_TAG('Z','H','A',' ')}, /* Central Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','d','j',' '), HB_TAG('C','M','R',' ')}, /* Ngazidja Comorian -> Comorian */
+/*{HB_TAG('z','e','a',' '), HB_TAG('Z','E','A',' ')},*/ /* Zeeuws -> Zealandic */
+ {HB_TAG('z','e','h',' '), HB_TAG('Z','H','A',' ')}, /* Eastern Hongshuihe Zhuang -> Zhuang */
+ {HB_TAG('z','e','n',' '), HB_TAG('B','B','R',' ')}, /* Zenaga -> Berber */
+ {HB_TAG('z','g','b',' '), HB_TAG('Z','H','A',' ')}, /* Guibei Zhuang -> Zhuang */
+ {HB_TAG('z','g','h',' '), HB_TAG('Z','G','H',' ')}, /* Standard Moroccan Tamazight */
+ {HB_TAG('z','g','h',' '), HB_TAG('B','B','R',' ')}, /* Standard Moroccan Tamazight -> Berber */
+ {HB_TAG('z','g','m',' '), HB_TAG('Z','H','A',' ')}, /* Minz Zhuang -> Zhuang */
+ {HB_TAG('z','g','n',' '), HB_TAG('Z','H','A',' ')}, /* Guibian Zhuang -> Zhuang */
+ {HB_TAG('z','h','d',' '), HB_TAG('Z','H','A',' ')}, /* Dai Zhuang -> Zhuang */
+ {HB_TAG('z','h','n',' '), HB_TAG('Z','H','A',' ')}, /* Nong Zhuang -> Zhuang */
+ {HB_TAG('z','l','j',' '), HB_TAG('Z','H','A',' ')}, /* Liujiang Zhuang -> Zhuang */
+ {HB_TAG('z','l','m',' '), HB_TAG('M','L','Y',' ')}, /* Malay */
+ {HB_TAG('z','l','n',' '), HB_TAG('Z','H','A',' ')}, /* Lianshan Zhuang -> Zhuang */
+ {HB_TAG('z','l','q',' '), HB_TAG('Z','H','A',' ')}, /* Liuqian Zhuang -> Zhuang */
+ {HB_TAG('z','m','i',' '), HB_TAG('M','L','Y',' ')}, /* Negeri Sembilan Malay -> Malay */
+ {HB_TAG('z','m','z',' '), HB_TAG('B','A','D','0')}, /* Mbandja -> Banda */
+ {HB_TAG('z','n','d',' '), HB_TAG_NONE }, /* Zande [collection] != Zande */
+ {HB_TAG('z','n','e',' '), HB_TAG('Z','N','D',' ')}, /* Zande */
+ {HB_TAG('z','o','m',' '), HB_TAG('Q','I','N',' ')}, /* Zou -> Chin */
+ {HB_TAG('z','q','e',' '), HB_TAG('Z','H','A',' ')}, /* Qiubei Zhuang -> Zhuang */
+ {HB_TAG('z','s','m',' '), HB_TAG('M','L','Y',' ')}, /* Standard Malay -> Malay */
+ {HB_TAG('z','u','m',' '), HB_TAG('L','R','C',' ')}, /* Kumzari -> Luri */
+ {HB_TAG('z','y','b',' '), HB_TAG('Z','H','A',' ')}, /* Yongbei Zhuang -> Zhuang */
+ {HB_TAG('z','y','g',' '), HB_TAG('Z','H','A',' ')}, /* Yang Zhuang -> Zhuang */
+ {HB_TAG('z','y','j',' '), HB_TAG('Z','H','A',' ')}, /* Youjiang Zhuang -> Zhuang */
+ {HB_TAG('z','y','n',' '), HB_TAG('Z','H','A',' ')}, /* Yongnan Zhuang -> Zhuang */
+ {HB_TAG('z','y','p',' '), HB_TAG('Q','I','N',' ')}, /* Zyphe Chin -> Chin */
+/*{HB_TAG('z','z','a',' '), HB_TAG('Z','Z','A',' ')},*/ /* Zazaki [macrolanguage] */
+ {HB_TAG('z','z','j',' '), HB_TAG('Z','H','A',' ')}, /* Zuojiang Zhuang -> Zhuang */
+};
+#endif
+
/**
* hb_ot_tags_from_complex_language:
* @lang_str: a BCP 47 language tag to convert.
@@ -1630,75 +1638,81 @@ static const LangTag ot_languages[] = {
*
* Return value: Whether any language systems were retrieved.
**/
-static bool
+static inline bool
hb_ot_tags_from_complex_language (const char *lang_str,
const char *limit,
unsigned int *count /* IN/OUT */,
hb_tag_t *tags /* OUT */)
{
- if (subtag_matches (lang_str, limit, "-fonnapa"))
- {
- /* Undetermined; North American Phonetic Alphabet */
- tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-polyton"))
- {
- /* Modern Greek (1453-); Polytonic Greek */
- tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-arevmda"))
- {
- /* Armenian; Western Armenian (retired code) */
- tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-provenc"))
- {
- /* Occitan (post 1500); Provençal */
- tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-fonipa"))
- {
- /* Undetermined; International Phonetic Alphabet */
- tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-geok"))
- {
- /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
- tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syre"))
+ if (limit - lang_str >= 7)
{
- /* Undetermined; Syriac (Estrangelo variant) */
- tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrj"))
- {
- /* Undetermined; Syriac (Western variant) */
- tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
- *count = 1;
- return true;
- }
- if (subtag_matches (lang_str, limit, "-syrn"))
- {
- /* Undetermined; Syriac (Eastern variant) */
- tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
- *count = 1;
- return true;
+ const char *p = strchr (lang_str, '-');
+ if (!p || p >= limit || limit - p < 5) goto out;
+ if (subtag_matches (p, limit, "-fonnapa", 8))
+ {
+ /* Undetermined; North American Phonetic Alphabet */
+ tags[0] = HB_TAG('A','P','P','H'); /* Phonetic transcription—Americanist conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-polyton", 8))
+ {
+ /* Modern Greek (1453-); Polytonic Greek */
+ tags[0] = HB_TAG('P','G','R',' '); /* Polytonic Greek */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-arevmda", 8))
+ {
+ /* Armenian; Western Armenian (retired code) */
+ tags[0] = HB_TAG('H','Y','E',' '); /* Armenian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-provenc", 8))
+ {
+ /* Occitan (post 1500); Provençal */
+ tags[0] = HB_TAG('P','R','O',' '); /* Provençal / Old Provençal */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-fonipa", 7))
+ {
+ /* Undetermined; International Phonetic Alphabet */
+ tags[0] = HB_TAG('I','P','P','H'); /* Phonetic transcription—IPA conventions */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-geok", 5))
+ {
+ /* Undetermined; Khutsuri (Asomtavruli and Nuskhuri) */
+ tags[0] = HB_TAG('K','G','E',' '); /* Khutsuri Georgian */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syre", 5))
+ {
+ /* Undetermined; Syriac (Estrangelo variant) */
+ tags[0] = HB_TAG('S','Y','R','E'); /* Syriac, Estrangela script-variant (equivalent to ISO 15924 'Syre') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrj", 5))
+ {
+ /* Undetermined; Syriac (Western variant) */
+ tags[0] = HB_TAG('S','Y','R','J'); /* Syriac, Western script-variant (equivalent to ISO 15924 'Syrj') */
+ *count = 1;
+ return true;
+ }
+ if (subtag_matches (p, limit, "-syrn", 5))
+ {
+ /* Undetermined; Syriac (Eastern variant) */
+ tags[0] = HB_TAG('S','Y','R','N'); /* Syriac, Eastern script-variant (equivalent to ISO 15924 'Syrn') */
+ *count = 1;
+ return true;
+ }
}
+out:
switch (lang_str[0])
{
case 'a':
@@ -1711,14 +1725,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'c':
- if (lang_matches (&lang_str[1], "do-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-hk", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "do-hant-mo", 10))
{
/* Min Dong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1731,14 +1745,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-hk", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant-mo", 10))
{
/* Jinyu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1751,14 +1765,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-hk", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant-mo", 10))
{
/* Mandarin Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1771,14 +1785,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Northern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1791,14 +1805,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-hk", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "px-hant-mo", 10))
{
/* Pu-Xian Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1811,14 +1825,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-hk", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant-mo", 10))
{
/* Southern Ping Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1831,14 +1845,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-hk", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant-mo", 10))
{
/* Huizhou Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1851,14 +1865,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-hk", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant-mo", 10))
{
/* Min Zhong Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -1871,112 +1885,112 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "do-hans"))
+ if (lang_matches (&lang_str[1], limit, "do-hans", 7))
{
/* Min Dong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "do-hant"))
+ if (lang_matches (&lang_str[1], limit, "do-hant", 7))
{
/* Min Dong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hans"))
+ if (lang_matches (&lang_str[1], limit, "jy-hans", 7))
{
/* Jinyu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "jy-hant"))
+ if (lang_matches (&lang_str[1], limit, "jy-hant", 7))
{
/* Jinyu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hans"))
+ if (lang_matches (&lang_str[1], limit, "mn-hans", 7))
{
/* Mandarin Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "mn-hant"))
+ if (lang_matches (&lang_str[1], limit, "mn-hant", 7))
{
/* Mandarin Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Northern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Northern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hans"))
+ if (lang_matches (&lang_str[1], limit, "px-hans", 7))
{
/* Pu-Xian Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "px-hant"))
+ if (lang_matches (&lang_str[1], limit, "px-hant", 7))
{
/* Pu-Xian Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hans"))
+ if (lang_matches (&lang_str[1], limit, "sp-hans", 7))
{
/* Southern Ping Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sp-hant"))
+ if (lang_matches (&lang_str[1], limit, "sp-hant", 7))
{
/* Southern Ping Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Huizhou Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zh-hant"))
+ if (lang_matches (&lang_str[1], limit, "zh-hant", 7))
{
/* Huizhou Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hans"))
+ if (lang_matches (&lang_str[1], limit, "zo-hans", 7))
{
/* Min Zhong Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "zo-hant"))
+ if (lang_matches (&lang_str[1], limit, "zo-hant", 7))
{
/* Min Zhong Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -1984,7 +1998,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Dong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -1992,7 +2006,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Dong Chinese; Macao */
unsigned int i;
@@ -2006,7 +2020,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "do-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Dong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2014,7 +2028,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Jinyu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2022,7 +2036,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Jinyu Chinese; Macao */
unsigned int i;
@@ -2036,7 +2050,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "jy-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Jinyu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2044,7 +2058,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Mandarin Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2052,7 +2066,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Mandarin Chinese; Macao */
unsigned int i;
@@ -2066,7 +2080,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "mn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Mandarin Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2074,7 +2088,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Northern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2082,7 +2096,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Northern Ping Chinese; Macao */
unsigned int i;
@@ -2096,7 +2110,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Northern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2104,7 +2118,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Pu-Xian Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2112,7 +2126,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Pu-Xian Chinese; Macao */
unsigned int i;
@@ -2126,7 +2140,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "px-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Pu-Xian Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2134,7 +2148,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Southern Ping Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2142,7 +2156,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Southern Ping Chinese; Macao */
unsigned int i;
@@ -2156,7 +2170,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sp-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Southern Ping Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2164,7 +2178,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Huizhou Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2172,7 +2186,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Huizhou Chinese; Macao */
unsigned int i;
@@ -2186,7 +2200,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zh-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Huizhou Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2194,7 +2208,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Zhong Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2202,7 +2216,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Zhong Chinese; Macao */
unsigned int i;
@@ -2216,7 +2230,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "zo-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Zhong Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2225,14 +2239,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'g':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Gan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Gan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2245,21 +2259,21 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Gan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Gan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "a-latg"))
+ if (lang_matches (&lang_str[1], limit, "a-latg", 6))
{
/* Irish; Latin (Gaelic variant) */
tags[0] = HB_TAG('I','R','T',' '); /* Irish Traditional */
@@ -2267,7 +2281,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Gan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2275,7 +2289,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Gan Chinese; Macao */
unsigned int i;
@@ -2289,7 +2303,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Gan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2298,14 +2312,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'h':
- if (lang_matches (&lang_str[1], "ak-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-hk", 10))
{
/* Hakka Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant-mo", 10))
{
/* Hakka Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2318,14 +2332,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-hk", 10))
{
/* Xiang Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant-mo", 10))
{
/* Xiang Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2338,28 +2352,28 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hans"))
+ if (lang_matches (&lang_str[1], limit, "ak-hans", 7))
{
/* Hakka Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "ak-hant"))
+ if (lang_matches (&lang_str[1], limit, "ak-hant", 7))
{
/* Hakka Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hans"))
+ if (lang_matches (&lang_str[1], limit, "sn-hans", 7))
{
/* Xiang Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "sn-hant"))
+ if (lang_matches (&lang_str[1], limit, "sn-hant", 7))
{
/* Xiang Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2367,7 +2381,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Hakka Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2375,7 +2389,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Hakka Chinese; Macao */
unsigned int i;
@@ -2389,7 +2403,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "ak-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Hakka Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2397,7 +2411,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Xiang Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2405,7 +2419,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Xiang Chinese; Macao */
unsigned int i;
@@ -2419,7 +2433,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "sn-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Xiang Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2457,7 +2471,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'l':
- if (lang_matches (&lang_str[1], "zh-hans"))
+ if (lang_matches (&lang_str[1], limit, "zh-hans", 7))
{
/* Literary Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2466,14 +2480,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'm':
- if (lang_matches (&lang_str[1], "np-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-hk", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "np-hant-mo", 10))
{
/* Min Bei Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2486,14 +2500,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "np-hans"))
+ if (lang_matches (&lang_str[1], limit, "np-hans", 7))
{
/* Min Bei Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "np-hant"))
+ if (lang_matches (&lang_str[1], limit, "np-hant", 7))
{
/* Min Bei Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2501,7 +2515,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Bei Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2509,7 +2523,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Bei Chinese; Macao */
unsigned int i;
@@ -2523,7 +2537,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "np-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Bei Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2531,7 +2545,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "nw-", 3)
- && subtag_matches (lang_str, limit, "-th"))
+ && subtag_matches (lang_str, limit, "-th", 3))
{
/* Mon; Thailand */
tags[0] = HB_TAG('M','O','N','T'); /* Thailand Mon */
@@ -2540,14 +2554,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'n':
- if (lang_matches (&lang_str[1], "an-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-hk", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "an-hant-mo", 10))
{
/* Min Nan Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2560,14 +2574,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "an-hans"))
+ if (lang_matches (&lang_str[1], limit, "an-hans", 7))
{
/* Min Nan Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "an-hant"))
+ if (lang_matches (&lang_str[1], limit, "an-hant", 7))
{
/* Min Nan Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2575,7 +2589,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Min Nan Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2583,7 +2597,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Min Nan Chinese; Macao */
unsigned int i;
@@ -2597,7 +2611,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "an-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Min Nan Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2621,7 +2635,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
break;
case 'r':
if (0 == strncmp (&lang_str[1], "o-", 2)
- && subtag_matches (lang_str, limit, "-md"))
+ && subtag_matches (lang_str, limit, "-md", 3))
{
/* Romanian; Moldova */
unsigned int i;
@@ -2636,14 +2650,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'w':
- if (lang_matches (&lang_str[1], "uu-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-hk", 10))
{
/* Wu Chinese; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant-mo", 10))
{
/* Wu Chinese; Han (Traditional variant); Macao */
unsigned int i;
@@ -2656,14 +2670,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = i;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hans"))
+ if (lang_matches (&lang_str[1], limit, "uu-hans", 7))
{
/* Wu Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "uu-hant"))
+ if (lang_matches (&lang_str[1], limit, "uu-hant", 7))
{
/* Wu Chinese; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2671,7 +2685,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Wu Chinese; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2679,7 +2693,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Wu Chinese; Macao */
unsigned int i;
@@ -2693,7 +2707,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "uu-", 3)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Wu Chinese; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2702,7 +2716,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'y':
- if (lang_matches (&lang_str[1], "ue-hans"))
+ if (lang_matches (&lang_str[1], limit, "ue-hans", 7))
{
/* Yue Chinese; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
@@ -2711,14 +2725,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
}
break;
case 'z':
- if (lang_matches (&lang_str[1], "h-hant-hk"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-hk", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant-mo"))
+ if (lang_matches (&lang_str[1], limit, "h-hant-mo", 9))
{
/* Chinese [macrolanguage]; Han (Traditional variant); Macao */
unsigned int i;
@@ -2738,14 +2752,14 @@ hb_ot_tags_from_complex_language (const char *lang_str,
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hans"))
+ if (lang_matches (&lang_str[1], limit, "h-hans", 6))
{
/* Chinese [macrolanguage]; Han (Simplified variant) */
tags[0] = HB_TAG('Z','H','S',' '); /* Chinese, Simplified */
*count = 1;
return true;
}
- if (lang_matches (&lang_str[1], "h-hant"))
+ if (lang_matches (&lang_str[1], limit, "h-hant", 6))
{
/* Chinese [macrolanguage]; Han (Traditional variant) */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2760,7 +2774,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-hk"))
+ && subtag_matches (lang_str, limit, "-hk", 3))
{
/* Chinese [macrolanguage]; Hong Kong */
tags[0] = HB_TAG('Z','H','H',' '); /* Chinese, Traditional, Hong Kong SAR */
@@ -2768,7 +2782,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-mo"))
+ && subtag_matches (lang_str, limit, "-mo", 3))
{
/* Chinese [macrolanguage]; Macao */
unsigned int i;
@@ -2782,7 +2796,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
return true;
}
if (0 == strncmp (&lang_str[1], "h-", 2)
- && subtag_matches (lang_str, limit, "-tw"))
+ && subtag_matches (lang_str, limit, "-tw", 3))
{
/* Chinese [macrolanguage]; Taiwan, Province of China */
tags[0] = HB_TAG('Z','H','T',' '); /* Chinese, Traditional */
@@ -2806,7 +2820,7 @@ hb_ot_tags_from_complex_language (const char *lang_str,
* Return value: The #hb_language_t corresponding to the BCP 47 language tag,
* or #HB_LANGUAGE_INVALID if @tag is not ambiguous.
**/
-static hb_language_t
+static inline hb_language_t
hb_ot_ambiguous_tag_to_language (hb_tag_t tag)
{
switch (tag)
diff --git a/thirdparty/harfbuzz/src/hb-ot-tag.cc b/thirdparty/harfbuzz/src/hb-ot-tag.cc
index 1837063af8..ceb3bf6df5 100644
--- a/thirdparty/harfbuzz/src/hb-ot-tag.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-tag.cc
@@ -41,6 +41,7 @@ hb_ot_old_tag_from_script (hb_script_t script)
switch ((hb_tag_t) script)
{
case HB_SCRIPT_INVALID: return HB_OT_TAG_DEFAULT_SCRIPT;
+ case HB_SCRIPT_MATH: return HB_OT_TAG_MATH_SCRIPT;
/* KATAKANA and HIRAGANA both map to 'kana' */
case HB_SCRIPT_HIRAGANA: return HB_TAG('k','a','n','a');
@@ -63,6 +64,8 @@ hb_ot_old_tag_to_script (hb_tag_t tag)
{
if (unlikely (tag == HB_OT_TAG_DEFAULT_SCRIPT))
return HB_SCRIPT_INVALID;
+ if (unlikely (tag == HB_OT_TAG_MATH_SCRIPT))
+ return HB_SCRIPT_MATH;
/* This side of the conversion is fully algorithmic. */
@@ -186,48 +189,48 @@ hb_ot_tag_to_script (hb_tag_t tag)
/* hb_language_t */
-static bool
+static inline bool
subtag_matches (const char *lang_str,
const char *limit,
- const char *subtag)
+ const char *subtag,
+ unsigned subtag_len)
{
+ if (likely ((unsigned) (limit - lang_str) < subtag_len))
+ return false;
+
do {
const char *s = strstr (lang_str, subtag);
if (!s || s >= limit)
return false;
- if (!ISALNUM (s[strlen (subtag)]))
+ if (!ISALNUM (s[subtag_len]))
return true;
- lang_str = s + strlen (subtag);
+ lang_str = s + subtag_len;
} while (true);
}
-static hb_bool_t
-lang_matches (const char *lang_str, const char *spec)
+static bool
+lang_matches (const char *lang_str,
+ const char *limit,
+ const char *spec,
+ unsigned spec_len)
{
- unsigned int len = strlen (spec);
+ /* Same as hb_language_matches(); duplicated. */
+
+ if (likely ((unsigned) (limit - lang_str) < spec_len))
+ return false;
- return strncmp (lang_str, spec, len) == 0 &&
- (lang_str[len] == '\0' || lang_str[len] == '-');
+ return strncmp (lang_str, spec, spec_len) == 0 &&
+ (lang_str[spec_len] == '\0' || lang_str[spec_len] == '-');
}
struct LangTag
{
- char language[4];
+ hb_tag_t language;
hb_tag_t tag;
- int cmp (const char *a) const
+ int cmp (hb_tag_t a) const
{
- const char *b = this->language;
- unsigned int da, db;
- const char *p;
-
- p = strchr (a, '-');
- da = p ? (unsigned int) (p - a) : strlen (a);
-
- p = strchr (b, '-');
- db = p ? (unsigned int) (p - b) : strlen (b);
-
- return strncmp (a, b, hb_max (da, db));
+ return a < this->language ? -1 : a > this->language ? +1 : 0;
}
int cmp (const LangTag *that) const
{ return cmp (that->language); }
@@ -262,16 +265,19 @@ hb_ot_tags_from_language (const char *lang_str,
unsigned int *count,
hb_tag_t *tags)
{
- const char *s;
- unsigned int tag_idx;
+#ifndef HB_NO_LANGUAGE_LONG
/* Check for matches of multiple subtags. */
if (hb_ot_tags_from_complex_language (lang_str, limit, count, tags))
return;
+#endif
/* Find a language matching in the first component. */
- s = strchr (lang_str, '-');
+#ifndef HB_NO_LANGUAGE_LONG
+ const char *s; s = strchr (lang_str, '-');
+#endif
{
+#ifndef HB_NO_LANGUAGE_LONG
if (s && limit - lang_str >= 6)
{
const char *extlang_end = strchr (s + 1, '-');
@@ -280,17 +286,42 @@ hb_ot_tags_from_language (const char *lang_str,
ISALPHA (s[1]))
lang_str = s + 1;
}
- if (hb_sorted_array (ot_languages).bfind (lang_str, &tag_idx))
+#endif
+ const LangTag *ot_languages = nullptr;
+ unsigned ot_languages_len = 0;
+ const char *dash = strchr (lang_str, '-');
+ unsigned first_len = dash ? dash - lang_str : limit - lang_str;
+ if (first_len == 2)
+ {
+ ot_languages = ot_languages2;
+ ot_languages_len = ARRAY_LENGTH (ot_languages2);
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ else if (first_len == 3)
+ {
+ ot_languages = ot_languages3;
+ ot_languages_len = ARRAY_LENGTH (ot_languages3);
+ }
+#endif
+
+ hb_tag_t lang_tag = hb_tag_from_string (lang_str, first_len);
+
+ static hb_atomic_int_t last_tag_idx; /* Poor man's cache. */
+ unsigned tag_idx = last_tag_idx.get_relaxed ();
+
+ if (likely (tag_idx < ot_languages_len && ot_languages[tag_idx].language == lang_tag) ||
+ hb_sorted_array (ot_languages, ot_languages_len).bfind (lang_tag, &tag_idx))
{
+ last_tag_idx.set_relaxed (tag_idx);
unsigned int i;
while (tag_idx != 0 &&
- 0 == strcmp (ot_languages[tag_idx].language, ot_languages[tag_idx - 1].language))
+ ot_languages[tag_idx].language == ot_languages[tag_idx - 1].language)
tag_idx--;
for (i = 0;
i < *count &&
- tag_idx + i < ARRAY_LENGTH (ot_languages) &&
+ tag_idx + i < ot_languages_len &&
ot_languages[tag_idx + i].tag != HB_TAG_NONE &&
- 0 == strcmp (ot_languages[tag_idx + i].language, ot_languages[tag_idx].language);
+ ot_languages[tag_idx + i].language == ot_languages[tag_idx].language;
i++)
tags[i] = ot_languages[tag_idx + i].tag;
*count = i;
@@ -298,6 +329,7 @@ hb_ot_tags_from_language (const char *lang_str,
}
}
+#ifndef HB_NO_LANGUAGE_LONG
if (!s)
s = lang_str + strlen (lang_str);
if (s - lang_str == 3) {
@@ -306,6 +338,7 @@ hb_ot_tags_from_language (const char *lang_str,
*count = 1;
return;
}
+#endif
*count = 0;
}
@@ -450,15 +483,29 @@ hb_ot_tag_to_language (hb_tag_t tag)
if (tag == HB_OT_TAG_DEFAULT_LANGUAGE)
return nullptr;
+#ifndef HB_NO_LANGUAGE_LONG
{
hb_language_t disambiguated_tag = hb_ot_ambiguous_tag_to_language (tag);
if (disambiguated_tag != HB_LANGUAGE_INVALID)
return disambiguated_tag;
}
+#endif
- for (i = 0; i < ARRAY_LENGTH (ot_languages); i++)
- if (ot_languages[i].tag == tag)
- return hb_language_from_string (ot_languages[i].language, -1);
+ char buf[4];
+ for (i = 0; i < ARRAY_LENGTH (ot_languages2); i++)
+ if (ot_languages2[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages2[i].language, buf);
+ return hb_language_from_string (buf, 2);
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ for (i = 0; i < ARRAY_LENGTH (ot_languages3); i++)
+ if (ot_languages3[i].tag == tag)
+ {
+ hb_tag_to_string (ot_languages3[i].language, buf);
+ return hb_language_from_string (buf, 3);
+ }
+#endif
/* Return a custom language in the form of "x-hbot-AABBCCDD".
* If it's three letters long, also guess it's ISO 639-3 and lower-case and
@@ -554,16 +601,28 @@ hb_ot_tags_to_script_and_language (hb_tag_t script_tag,
static inline void
test_langs_sorted ()
{
- for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages); i++)
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages2); i++)
+ {
+ int c = ot_languages2[i].cmp (&ot_languages2[i - 1]);
+ if (c > 0)
+ {
+ fprintf (stderr, "ot_languages2 not sorted at index %d: %08x %d %08x\n",
+ i, ot_languages2[i-1].language, c, ot_languages2[i].language);
+ abort();
+ }
+ }
+#ifndef HB_NO_LANGUAGE_LONG
+ for (unsigned int i = 1; i < ARRAY_LENGTH (ot_languages3); i++)
{
- int c = ot_languages[i].cmp (&ot_languages[i - 1]);
+ int c = ot_languages3[i].cmp (&ot_languages3[i - 1]);
if (c > 0)
{
- fprintf (stderr, "ot_languages not sorted at index %d: %s %d %s\n",
- i, ot_languages[i-1].language, c, ot_languages[i].language);
+ fprintf (stderr, "ot_languages3 not sorted at index %d: %08x %d %08x\n",
+ i, ot_languages3[i-1].language, c, ot_languages3[i].language);
abort();
}
}
+#endif
}
int
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
index 65f26c1d22..5946aef635 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
@@ -28,6 +28,8 @@
#define HB_OT_VAR_AVAR_TABLE_HH
#include "hb-open-type.hh"
+#include "hb-ot-var-common.hh"
+
/*
* avar -- Axis Variations
@@ -40,6 +42,28 @@
namespace OT {
+/* "Spec": https://github.com/be-fonts/boring-expansion-spec/issues/14 */
+struct avarV2Tail
+{
+ friend struct avar;
+
+ bool sanitize (hb_sanitize_context_t *c,
+ const void *base) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (varIdxMap.sanitize (c, base) &&
+ varStore.sanitize (c, base));
+ }
+
+ protected:
+ Offset32To<DeltaSetIndexMap> varIdxMap; /* Offset from the beginning of 'avar' table. */
+ Offset32To<VariationStore> varStore; /* Offset from the beginning of 'avar' table. */
+
+ public:
+ DEFINE_SIZE_STATIC (8);
+};
+
+
struct AxisValueMap
{
bool sanitize (hb_sanitize_context_t *c) const
@@ -106,12 +130,24 @@ struct avar
{
static constexpr hb_tag_t tableTag = HB_OT_TAG_avar;
+ bool has_data () const { return version.to_int (); }
+
+ const SegmentMaps* get_segment_maps () const
+ { return &firstAxisSegmentMaps; }
+
+ unsigned get_axis_count () const
+ { return axisCount; }
+
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (unlikely (!(version.sanitize (c) &&
- version.major == 1 &&
- c->check_struct (this))))
+ if (!(version.sanitize (c) &&
+ (version.major == 1
+#ifndef HB_NO_VARIATIONS2
+ || version.major == 2
+#endif
+ ) &&
+ c->check_struct (this)))
return_trace (false);
const SegmentMaps *map = &firstAxisSegmentMaps;
@@ -123,6 +159,15 @@ struct avar
map = &StructAfter<SegmentMaps> (*map);
}
+#ifndef HB_NO_VARIATIONS2
+ if (version.major < 2)
+ return_trace (true);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+ if (unlikely (!v2.sanitize (c, this)))
+ return_trace (false);
+#endif
+
return_trace (true);
}
@@ -136,6 +181,37 @@ struct avar
coords[i] = map->map (coords[i]);
map = &StructAfter<SegmentMaps> (*map);
}
+
+#ifndef HB_NO_VARIATIONS2
+ if (version.major < 2)
+ return;
+
+ for (; count < axisCount; count++)
+ map = &StructAfter<SegmentMaps> (*map);
+
+ const auto &v2 = * (const avarV2Tail *) map;
+
+ const auto &varidx_map = this+v2.varIdxMap;
+ const auto &var_store = this+v2.varStore;
+ auto *var_store_cache = var_store.create_cache ();
+
+ hb_vector_t<int> out;
+ out.alloc (coords_length);
+ for (unsigned i = 0; i < coords_length; i++)
+ {
+ int v = coords[i];
+ uint32_t varidx = varidx_map.map (i);
+ float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache);
+ v += roundf (delta);
+ v = hb_clamp (v, -(1<<14), +(1<<14));
+ out.push (v);
+ }
+
+ OT::VariationStore::destroy_cache (var_store_cache);
+
+ for (unsigned i = 0; i < coords_length; i++)
+ coords[i] = out[i];
+#endif
}
void unmap_coords (int *coords, unsigned int coords_length) const
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-common.hh b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
index 0eafb949d5..1d29e3e4f9 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-common.hh
@@ -31,12 +31,13 @@
namespace OT {
-struct DeltaSetIndexMapFormat0
+template <typename MapCountT>
+struct DeltaSetIndexMapFormat01
{
friend struct DeltaSetIndexMap;
private:
- DeltaSetIndexMapFormat0* copy (hb_serialize_context_t *c) const
+ DeltaSetIndexMapFormat01* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);
auto *out = c->start_embed (this);
@@ -128,56 +129,12 @@ struct DeltaSetIndexMapFormat0
HBUINT8 format; /* Format identifier--format = 0 */
HBUINT8 entryFormat; /* A packed field that describes the compressed
* representation of delta-set indices. */
- HBUINT16 mapCount; /* The number of mapping entries. */
+ MapCountT mapCount; /* The number of mapping entries. */
UnsizedArrayOf<HBUINT8>
mapDataZ; /* The delta-set index mapping data. */
public:
- DEFINE_SIZE_ARRAY (4, mapDataZ);
-};
-
-struct DeltaSetIndexMapFormat1
-{
- friend struct DeltaSetIndexMap;
-
- private:
- DeltaSetIndexMapFormat1* copy (hb_serialize_context_t *c) const
- {
- TRACE_SERIALIZE (this);
- auto *out = c->start_embed (this);
- if (unlikely (!out)) return_trace (nullptr);
-
- unsigned total_size = min_size + mapCount * get_width ();
- HBUINT8 *p = c->allocate_size<HBUINT8> (total_size);
- if (unlikely (!p)) return_trace (nullptr);
-
- memcpy (p, this, HBUINT8::static_size * total_size);
- return_trace (out);
- }
-
- unsigned get_map_count () const { return mapCount; }
- unsigned get_width () const { return ((entryFormat >> 4) & 3) + 1; }
- unsigned get_inner_bit_count () const { return (entryFormat & 0xF) + 1; }
-
- bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- c->check_range (mapDataZ.arrayZ,
- mapCount,
- get_width ()));
- }
-
- protected:
- HBUINT8 format; /* Format identifier--format = 1 */
- HBUINT8 entryFormat; /* A packed field that describes the compressed
- * representation of delta-set indices. */
- HBUINT32 mapCount; /* The number of mapping entries. */
- UnsizedArrayOf<HBUINT8>
- mapDataZ; /* The delta-set index mapping data. */
-
- public:
- DEFINE_SIZE_ARRAY (6, mapDataZ);
+ DEFINE_SIZE_ARRAY (2+MapCountT::static_size, mapDataZ);
};
struct DeltaSetIndexMap
@@ -186,8 +143,11 @@ struct DeltaSetIndexMap
bool serialize (hb_serialize_context_t *c, const T &plan)
{
TRACE_SERIALIZE (this);
+ unsigned length = plan.get_output_map ().length;
+ u.format = length <= 0xFFFF ? 0 : 1;
switch (u.format) {
case 0: return_trace (u.format0.serialize (c, plan));
+ case 1: return_trace (u.format1.serialize (c, plan));
default:return_trace (false);
}
}
@@ -196,6 +156,7 @@ struct DeltaSetIndexMap
{
switch (u.format) {
case 0: return (u.format0.map (v));
+ case 1: return (u.format1.map (v));
default:return v;
}
}
@@ -250,9 +211,9 @@ struct DeltaSetIndexMap
protected:
union {
- HBUINT8 format; /* Format identifier */
- DeltaSetIndexMapFormat0 format0;
- DeltaSetIndexMapFormat1 format1;
+ HBUINT8 format; /* Format identifier */
+ DeltaSetIndexMapFormat01<HBUINT16> format0;
+ DeltaSetIndexMapFormat01<HBUINT32> format1;
} u;
public:
DEFINE_SIZE_UNION (1, format);
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
index e066558683..b9b49f2287 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
@@ -96,6 +96,8 @@ struct AxisRecord
info->reserved = 0;
}
+ hb_tag_t get_axis_tag () const { return axisTag; }
+
int normalize_axis_value (float v) const
{
float min_value, default_value, max_value;
@@ -133,7 +135,6 @@ struct AxisRecord
return_trace (c->check_struct (this));
}
- protected:
void get_coordinates (float &min, float &default_, float &max) const
{
default_ = defaultValue / 65536.f;
@@ -142,6 +143,11 @@ struct AxisRecord
max = hb_max (default_, maxValue / 65536.f);
}
+ float get_default () const
+ {
+ return defaultValue / 65536.f;
+ }
+
public:
Tag axisTag; /* Tag identifying the design variation for the axis. */
protected:
@@ -213,7 +219,7 @@ struct fvar
if (!axis_index) axis_index = &i;
*axis_index = HB_OT_VAR_NO_AXIS_INDEX;
auto axes = get_axes ();
- return axes.lfind (tag, axis_index) && (axes[*axis_index].get_axis_deprecated (info), true);
+ return axes.lfind (tag, axis_index) && ((void) axes[*axis_index].get_axis_deprecated (info), true);
}
#endif
bool
@@ -221,7 +227,7 @@ struct fvar
{
unsigned i;
auto axes = get_axes ();
- return axes.lfind (tag, &i) && (axes[i].get_axis_info (i, info), true);
+ return axes.lfind (tag, &i) && ((void) axes[i].get_axis_info (i, info), true);
}
int normalize_axis_value (unsigned int axis_index, float v) const
@@ -270,24 +276,49 @@ struct fvar
return axisCount;
}
- void collect_name_ids (hb_set_t *nameids) const
+ void collect_name_ids (hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_set_t *nameids /* IN/OUT */) const
{
if (!has_data ()) return;
+ hb_map_t pinned_axes;
- + get_axes ()
- | hb_map (&AxisRecord::get_name_id)
- | hb_sink (nameids)
- ;
-
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_subfamily_name_id (_); })
- | hb_sink (nameids)
- ;
+ auto axis_records = get_axes ();
+ for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
+ {
+ hb_tag_t axis_tag = axis_records[i].get_axis_tag ();
+ if (user_axes_location->has (axis_tag))
+ {
+ pinned_axes.set (i, axis_tag);
+ continue;
+ }
+
+ nameids->add (axis_records[i].get_name_id ());
+ }
- + hb_range ((unsigned) instanceCount)
- | hb_map ([this] (const unsigned _) { return get_instance_postscript_name_id (_); })
- | hb_sink (nameids)
- ;
+ for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
+ {
+ const InstanceRecord *instance = get_instance (i);
+
+ if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount))
+ | hb_filter (pinned_axes, hb_second)
+ | hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _)
+ {
+ hb_tag_t axis_tag = pinned_axes.get (_.second);
+ float location = user_axes_location->get (axis_tag);
+ if (fabs ((double)location - (double)_.first.to_float ()) > 0.001) return true;
+ return false;
+ })
+ ))
+ continue;
+
+ nameids->add (instance->subfamilyNameID);
+
+ if (instanceSize >= axisCount * 4 + 6)
+ {
+ unsigned post_script_name_id = StructAfter<NameID> (instance->get_coordinates (axisCount));
+ if (post_script_name_id != HB_OT_NAME_ID_INVALID) nameids->add (post_script_name_id);
+ }
+ }
}
public:
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
index 539213c339..bf1039d1d6 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
@@ -45,9 +45,10 @@ struct contour_point_t
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
- uint8_t flag;
- float x, y;
- bool is_end_point;
+ float x = 0.f;
+ float y = 0.f;
+ uint8_t flag = 0;
+ bool is_end_point = false;
};
struct contour_point_vector_t : hb_vector_t<contour_point_t>
@@ -55,16 +56,24 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void extend (const hb_array_t<contour_point_t> &a)
{
unsigned int old_len = length;
- resize (old_len + a.length);
- for (unsigned int i = 0; i < a.length; i++)
- (*this)[old_len + i] = a[i];
+ if (unlikely (!resize (old_len + a.length)))
+ return;
+ auto arrayZ = this->arrayZ + old_len;
+ unsigned count = a.length;
+ for (unsigned int i = 0; i < count; i++)
+ arrayZ[i] = a.arrayZ[i];
}
void transform (const float (&matrix)[4])
{
- for (unsigned int i = 0; i < length; i++)
+ if (matrix[0] == 1.f && matrix[1] == 0.f &&
+ matrix[2] == 0.f && matrix[3] == 1.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
{
- contour_point_t &p = (*this)[i];
+ contour_point_t &p = arrayZ[i];
float x_ = p.x * matrix[0] + p.y * matrix[2];
p.y = p.x * matrix[1] + p.y * matrix[3];
p.x = x_;
@@ -73,8 +82,12 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
void translate (const contour_point_t& delta)
{
- for (unsigned int i = 0; i < length; i++)
- (*this)[i].translate (delta);
+ if (delta.x == 0.f && delta.y == 0.f)
+ return;
+ auto arrayZ = this->arrayZ;
+ unsigned count = length;
+ for (unsigned i = 0; i < count; i++)
+ arrayZ[i].translate (delta);
}
};
@@ -89,7 +102,7 @@ struct TupleVariationHeader
const TupleVariationHeader &get_next (unsigned axis_count) const
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
- float calculate_scalar (const int *coords, unsigned int coord_count,
+ float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
const hb_array_t<const F2DOT14> shared_tuples) const
{
hb_array_t<const F2DOT14> peak_tuple;
@@ -208,7 +221,7 @@ struct GlyphVariationData
{
const HBUINT8 *base = &(var_data+var_data->data);
const HBUINT8 *p = base;
- if (!unpack_points (p, shared_indices, var_data_bytes)) return false;
+ if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
data_offset = p - base;
}
return true;
@@ -258,7 +271,7 @@ struct GlyphVariationData
static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<unsigned int> &points /* OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_point_flag_t
{
@@ -266,21 +279,21 @@ struct GlyphVariationData
POINT_RUN_COUNT_MASK = 0x7F
};
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint16_t count = *p++;
if (count & POINTS_ARE_WORDS)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
}
- points.resize (count);
+ if (unlikely (!points.resize (count))) return false;
unsigned int n = 0;
uint16_t i = 0;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint16_t j;
uint8_t control = *p++;
uint16_t run_count = (control & POINT_RUN_COUNT_MASK) + 1;
@@ -288,8 +301,7 @@ struct GlyphVariationData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
+ if (unlikely (p + HBUINT16::static_size > end)) return false;
n += *(const HBUINT16 *)p;
points[i] = n;
p += HBUINT16::static_size;
@@ -299,7 +311,7 @@ struct GlyphVariationData
{
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
n += *p++;
points[i] = n;
}
@@ -311,7 +323,7 @@ struct GlyphVariationData
static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
hb_vector_t<int> &deltas /* IN/OUT */,
- const hb_bytes_t &bytes)
+ const HBUINT8 *end)
{
enum packed_delta_flag_t
{
@@ -324,7 +336,7 @@ struct GlyphVariationData
unsigned int count = deltas.length;
while (i < count)
{
- if (unlikely (!bytes.check_range (p))) return false;
+ if (unlikely (p + 1 > end)) return false;
uint8_t control = *p++;
unsigned int run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
unsigned int j;
@@ -334,16 +346,14 @@ struct GlyphVariationData
else if (control & DELTAS_ARE_WORDS)
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range ((const HBUINT16 *) p)))
- return false;
+ if (unlikely (p + HBUINT16::static_size > end)) return false;
deltas[i] = *(const HBINT16 *) p;
p += HBUINT16::static_size;
}
else
for (j = 0; j < run_count && i < count; j++, i++)
{
- if (unlikely (!bytes.check_range (p)))
- return false;
+ if (unlikely (p + 1 > end)) return false;
deltas[i] = *(const HBINT8 *) p++;
}
if (j < run_count)
@@ -390,13 +400,10 @@ struct gvar
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this) && (version.major == 1) &&
- (glyphCount == c->get_num_glyphs ()) &&
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
(is_long_offset () ?
c->check_array (get_long_offset_array (), glyphCount+1) :
- c->check_array (get_short_offset_array (), glyphCount+1)) &&
- c->check_array (((const HBUINT8*)&(this+dataZ)) + get_offset (0),
- get_offset (glyphCount) - get_offset (0)));
+ c->check_array (get_short_offset_array (), glyphCount+1)));
}
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
@@ -482,7 +489,9 @@ struct gvar
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
{
unsigned start_offset = get_offset (glyph);
- unsigned length = get_offset (glyph+1) - start_offset;
+ unsigned end_offset = get_offset (glyph+1);
+ if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
+ unsigned length = end_offset - start_offset;
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
return likely (var_data.length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t ();
}
@@ -490,7 +499,10 @@ struct gvar
bool is_long_offset () const { return flags & 1; }
unsigned get_offset (unsigned i) const
- { return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2; }
+ {
+ if (unlikely (i > glyphCount)) return 0;
+ return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
+ }
const HBUINT32 * get_long_offset_array () const { return (const HBUINT32 *) &offsetZ; }
const HBUINT16 *get_short_offset_array () const { return (const HBUINT16 *) &offsetZ; }
@@ -503,19 +515,17 @@ struct gvar
~accelerator_t () { table.destroy (); }
private:
- struct x_getter { static float get (const contour_point_t &p) { return p.x; } };
- struct y_getter { static float get (const contour_point_t &p) { return p.y; } };
- template <typename T>
static float infer_delta (const hb_array_t<contour_point_t> points,
const hb_array_t<contour_point_t> deltas,
- unsigned int target, unsigned int prev, unsigned int next)
+ unsigned int target, unsigned int prev, unsigned int next,
+ float contour_point_t::*m)
{
- float target_val = T::get (points[target]);
- float prev_val = T::get (points[prev]);
- float next_val = T::get (points[next]);
- float prev_delta = T::get (deltas[prev]);
- float next_delta = T::get (deltas[next]);
+ float target_val = points[target].*m;
+ float prev_val = points[prev].*m;
+ float next_val = points[next].*m;
+ float prev_delta = deltas[prev].*m;
+ float next_delta = deltas[next].*m;
if (prev_val == next_val)
return (prev_delta == next_delta) ? prev_delta : 0.f;
@@ -526,7 +536,7 @@ struct gvar
/* linear interpolation */
float r = (target_val - prev_val) / (next_val - prev_val);
- return (1.f - r) * prev_delta + r * next_delta;
+ return prev_delta + r * (next_delta - prev_delta);
}
static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end)
@@ -536,8 +546,7 @@ struct gvar
bool apply_deltas_to_points (hb_codepoint_t glyph, hb_font_t *font,
const hb_array_t<contour_point_t> points) const
{
- /* num_coords should exactly match gvar's axisCount due to how GlyphVariationData tuples are aligned */
- if (!font->num_coords || font->num_coords != table->axisCount) return true;
+ if (!font->num_coords) return true;
if (unlikely (glyph >= table->glyphCount)) return true;
@@ -551,21 +560,25 @@ struct gvar
/* Save original points for inferred delta calculation */
contour_point_vector_t orig_points;
- orig_points.resize (points.length);
+ if (unlikely (!orig_points.resize (points.length))) return false;
for (unsigned int i = 0; i < orig_points.length; i++)
- orig_points[i] = points[i];
+ orig_points.arrayZ[i] = points.arrayZ[i];
contour_point_vector_t deltas; /* flag is used to indicate referenced point */
- deltas.resize (points.length);
+ if (unlikely (!deltas.resize (points.length))) return false;
hb_vector_t<unsigned> end_points;
for (unsigned i = 0; i < points.length; ++i)
if (points[i].is_end_point)
end_points.push (i);
- int *coords = font->coords;
- unsigned num_coords = font->num_coords;
+ auto coords = hb_array (font->coords, font->num_coords);
+ unsigned num_coords = table->axisCount;
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
+
+ hb_vector_t<unsigned int> private_indices;
+ hb_vector_t<int> x_deltas;
+ hb_vector_t<int> y_deltas;
do
{
float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples);
@@ -575,32 +588,30 @@ struct gvar
if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
return false;
- hb_bytes_t bytes ((const char *) p, length);
- hb_vector_t<unsigned int> private_indices;
- if (iterator.current_tuple->has_private_points () &&
- !GlyphVariationData::unpack_points (p, private_indices, bytes))
+ const HBUINT8 *end = p + length;
+
+ bool has_private_points = iterator.current_tuple->has_private_points ();
+ if (has_private_points &&
+ !GlyphVariationData::unpack_points (p, private_indices, end))
return false;
- const hb_array_t<unsigned int> &indices = private_indices.length ? private_indices : shared_indices;
+ const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
bool apply_to_all = (indices.length == 0);
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
- hb_vector_t<int> x_deltas;
- x_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, x_deltas, bytes))
- return false;
- hb_vector_t<int> y_deltas;
- y_deltas.resize (num_deltas);
- if (!GlyphVariationData::unpack_deltas (p, y_deltas, bytes))
- return false;
+ if (unlikely (!x_deltas.resize (num_deltas))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, x_deltas, end))) return false;
+ if (unlikely (!y_deltas.resize (num_deltas))) return false;
+ if (unlikely (!GlyphVariationData::unpack_deltas (p, y_deltas, end))) return false;
for (unsigned int i = 0; i < deltas.length; i++)
deltas[i].init ();
for (unsigned int i = 0; i < num_deltas; i++)
{
unsigned int pt_index = apply_to_all ? i : indices[i];
- deltas[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */
- deltas[pt_index].x += x_deltas[i] * scalar;
- deltas[pt_index].y += y_deltas[i] * scalar;
+ if (unlikely (pt_index >= deltas.length)) continue;
+ deltas.arrayZ[pt_index].flag = 1; /* this point is referenced, i.e., explicit deltas specified */
+ deltas.arrayZ[pt_index].x += x_deltas.arrayZ[i] * scalar;
+ deltas.arrayZ[pt_index].y += y_deltas.arrayZ[i] * scalar;
}
/* infer deltas for unreferenced points */
@@ -644,20 +655,20 @@ struct gvar
{
i = next_index (i, start_point, end_point);
if (i == next) break;
- deltas[i].x = infer_delta<x_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
- deltas[i].y = infer_delta<y_getter> (orig_points.as_array (), deltas.as_array (), i, prev, next);
+ deltas[i].x = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::x);
+ deltas[i].y = infer_delta (orig_points.as_array (), deltas.as_array (), i, prev, next, &contour_point_t::y);
if (--unref_count == 0) goto no_more_gaps;
}
}
-no_more_gaps:
+ no_more_gaps:
start_point = end_point + 1;
}
/* apply specified / inferred deltas to points */
for (unsigned int i = 0; i < points.length; i++)
{
- points[i].x += deltas[i].x;
- points[i].y += deltas[i].y;
+ points.arrayZ[i].x += deltas.arrayZ[i].x;
+ points.arrayZ[i].y += deltas.arrayZ[i].y;
}
} while (iterator.move_to_next ());
@@ -695,7 +706,7 @@ no_more_gaps:
offsetZ; /* Offsets from the start of the GlyphVariationData array
* to each GlyphVariationData table. */
public:
- DEFINE_SIZE_MIN (20);
+ DEFINE_SIZE_ARRAY (20, offsetZ);
};
struct gvar_accelerator_t : gvar::accelerator_t {
diff --git a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
index e9d90352f0..53355c5077 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
@@ -319,23 +319,27 @@ struct HVARVVAR
hvar_plan.index_map_plans.as_array ()));
}
- float get_advance_var (hb_codepoint_t glyph, hb_font_t *font) const
+ float get_advance_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ VariationStore::cache_t *store_cache = nullptr) const
{
uint32_t varidx = (this+advMap).map (glyph);
- return (this+varStore).get_delta (varidx, font->coords, font->num_coords);
+ return (this+varStore).get_delta (varidx,
+ coords, coord_count,
+ store_cache);
}
- float get_side_bearing_var (hb_codepoint_t glyph,
- const int *coords, unsigned int coord_count) const
+ bool get_lsb_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *lsb) const
{
- if (!has_side_bearing_deltas ()) return 0.f;
+ if (!lsbMap) return false;
uint32_t varidx = (this+lsbMap).map (glyph);
- return (this+varStore).get_delta (varidx, coords, coord_count);
+ *lsb = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
}
- bool has_side_bearing_deltas () const { return lsbMap && rsbMap; }
-
- protected:
+ public:
FixedVersion<>version; /* Version of the metrics variation table
* initially set to 0x00010000u */
Offset32To<VariationStore>
@@ -387,6 +391,16 @@ struct VVAR : HVARVVAR {
bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
+ bool get_vorg_delta_unscaled (hb_codepoint_t glyph,
+ const int *coords, unsigned int coord_count,
+ float *delta) const
+ {
+ if (!vorgMap) return false;
+ uint32_t varidx = (this+vorgMap).map (glyph);
+ *delta = (this+varStore).get_delta (varidx, coords, coord_count);
+ return true;
+ }
+
protected:
Offset32To<DeltaSetIndexMap>
vorgMap; /* Offset to vertical-origin var-idx mapping. */
diff --git a/thirdparty/harfbuzz/src/hb-ot-var.cc b/thirdparty/harfbuzz/src/hb-ot-var.cc
index 0376e26b4a..f000f27263 100644
--- a/thirdparty/harfbuzz/src/hb-ot-var.cc
+++ b/thirdparty/harfbuzz/src/hb-ot-var.cc
@@ -56,7 +56,7 @@
*
* Tests whether a face includes any OpenType variation data in the `fvar` table.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 1.4.2
**/
@@ -162,7 +162,7 @@ hb_ot_var_get_axis_infos (hb_face_t *face,
* Fetches the variation-axis information corresponding to the specified axis tag
* in the specified face.
*
- * Return value: %true if data found, %false otherwise
+ * Return value: `true` if data found, `false` otherwise
*
* Since: 2.2.0
**/
diff --git a/thirdparty/harfbuzz/src/hb-priority-queue.hh b/thirdparty/harfbuzz/src/hb-priority-queue.hh
index 7d799ae906..ffb86e30ae 100644
--- a/thirdparty/harfbuzz/src/hb-priority-queue.hh
+++ b/thirdparty/harfbuzz/src/hb-priority-queue.hh
@@ -38,18 +38,11 @@
*/
struct hb_priority_queue_t
{
- HB_DELETE_COPY_ASSIGN (hb_priority_queue_t);
- hb_priority_queue_t () { init (); }
- ~hb_priority_queue_t () { fini (); }
-
private:
typedef hb_pair_t<int64_t, unsigned> item_t;
hb_vector_t<item_t> heap;
public:
- void init () { heap.init (); }
-
- void fini () { heap.fini (); }
void reset () { heap.resize (0); }
@@ -58,14 +51,17 @@ struct hb_priority_queue_t
void insert (int64_t priority, unsigned value)
{
heap.push (item_t (priority, value));
+ if (unlikely (heap.in_error ())) return;
bubble_up (heap.length - 1);
}
item_t pop_minimum ()
{
- item_t result = heap[0];
+ assert (!is_empty ());
+
+ item_t result = heap.arrayZ[0];
- heap[0] = heap[heap.length - 1];
+ heap.arrayZ[0] = heap.arrayZ[heap.length - 1];
heap.shrink (heap.length - 1);
bubble_down (0);
@@ -104,6 +100,8 @@ struct hb_priority_queue_t
void bubble_down (unsigned index)
{
+ assert (index <= heap.length);
+
unsigned left = left_child (index);
unsigned right = right_child (index);
@@ -113,11 +111,11 @@ struct hb_priority_queue_t
return;
bool has_right = right < heap.length;
- if (heap[index].first <= heap[left].first
- && (!has_right || heap[index].first <= heap[right].first))
+ if (heap.arrayZ[index].first <= heap.arrayZ[left].first
+ && (!has_right || heap[index].first <= heap.arrayZ[right].first))
return;
- if (!has_right || heap[left].first < heap[right].first)
+ if (!has_right || heap.arrayZ[left].first < heap.arrayZ[right].first)
{
swap (index, left);
bubble_down (left);
@@ -130,10 +128,12 @@ struct hb_priority_queue_t
void bubble_up (unsigned index)
{
+ assert (index <= heap.length);
+
if (index == 0) return;
unsigned parent_index = parent (index);
- if (heap[parent_index].first <= heap[index].first)
+ if (heap.arrayZ[parent_index].first <= heap.arrayZ[index].first)
return;
swap (index, parent_index);
@@ -142,9 +142,9 @@ struct hb_priority_queue_t
void swap (unsigned a, unsigned b)
{
- item_t temp = heap[a];
- heap[a] = heap[b];
- heap[b] = temp;
+ assert (a <= heap.length);
+ assert (b <= heap.length);
+ hb_swap (heap.arrayZ[a], heap.arrayZ[b]);
}
};
diff --git a/thirdparty/harfbuzz/src/hb-repacker.hh b/thirdparty/harfbuzz/src/hb-repacker.hh
index b1726d8beb..61b142238e 100644
--- a/thirdparty/harfbuzz/src/hb-repacker.hh
+++ b/thirdparty/harfbuzz/src/hb-repacker.hh
@@ -29,1084 +29,165 @@
#include "hb-open-type.hh"
#include "hb-map.hh"
-#include "hb-priority-queue.hh"
-#include "hb-serialize.hh"
#include "hb-vector.hh"
+#include "graph/graph.hh"
+#include "graph/gsubgpos-graph.hh"
+#include "graph/serialize.hh"
+
+using graph::graph_t;
/*
* For a detailed writeup on the overflow resolution algorithm see:
* docs/repacker.md
*/
-struct graph_t
+struct lookup_size_t
{
- struct vertex_t
- {
- hb_serialize_context_t::object_t obj;
- int64_t distance = 0 ;
- int64_t space = 0 ;
- hb_vector_t<unsigned> parents;
- unsigned start = 0;
- unsigned end = 0;
- unsigned priority = 0;
-
- bool is_shared () const
- {
- return parents.length > 1;
- }
-
- unsigned incoming_edges () const
- {
- return parents.length;
- }
-
- void remove_parent (unsigned parent_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] != parent_index) continue;
- parents.remove (i);
- break;
- }
- }
-
- void remap_parents (const hb_vector_t<unsigned>& id_map)
- {
- for (unsigned i = 0; i < parents.length; i++)
- parents[i] = id_map[parents[i]];
- }
-
- void remap_parent (unsigned old_index, unsigned new_index)
- {
- for (unsigned i = 0; i < parents.length; i++)
- {
- if (parents[i] == old_index)
- parents[i] = new_index;
- }
- }
-
- bool is_leaf () const
- {
- return !obj.real_links.length && !obj.virtual_links.length;
- }
-
- bool raise_priority ()
- {
- if (has_max_priority ()) return false;
- priority++;
- return true;
- }
-
- bool has_max_priority () const {
- return priority >= 3;
- }
-
- int64_t modified_distance (unsigned order) const
- {
- // TODO(garretrieger): once priority is high enough, should try
- // setting distance = 0 which will force to sort immediately after
- // it's parent where possible.
-
- int64_t modified_distance =
- hb_min (hb_max(distance + distance_modifier (), 0), 0x7FFFFFFFFFF);
- if (has_max_priority ()) {
- modified_distance = 0;
- }
- return (modified_distance << 18) | (0x003FFFF & order);
- }
-
- int64_t distance_modifier () const
- {
- if (!priority) return 0;
- int64_t table_size = obj.tail - obj.head;
-
- if (priority == 1)
- return -table_size / 2;
-
- return -table_size;
- }
- };
-
- struct overflow_record_t
- {
- unsigned parent;
- unsigned child;
- };
-
- /*
- * A topological sorting of an object graph. Ordered
- * in reverse serialization order (first object in the
- * serialization is at the end of the list). This matches
- * the 'packed' object stack used internally in the
- * serializer
- */
- graph_t (const hb_vector_t<hb_serialize_context_t::object_t *>& objects)
- : parents_invalid (true),
- distance_invalid (true),
- positions_invalid (true),
- successful (true)
- {
- num_roots_for_space_.push (1);
- bool removed_nil = false;
- for (unsigned i = 0; i < objects.length; i++)
- {
- // TODO(grieger): check all links point to valid objects.
-
- // If this graph came from a serialization buffer object 0 is the
- // nil object. We don't need it for our purposes here so drop it.
- if (i == 0 && !objects[i])
- {
- removed_nil = true;
- continue;
- }
-
- vertex_t* v = vertices_.push ();
- if (check_success (!vertices_.in_error ()))
- v->obj = *objects[i];
- if (!removed_nil) continue;
- // Fix indices to account for removed nil object.
- for (auto& l : v->obj.all_links_writer ()) {
- l.objidx--;
- }
- }
- }
-
- ~graph_t ()
- {
- vertices_.fini ();
- }
-
- bool in_error () const
- {
- return !successful ||
- vertices_.in_error () ||
- num_roots_for_space_.in_error ();
- }
-
- const vertex_t& root () const
- {
- return vertices_[root_idx ()];
- }
-
- unsigned root_idx () const
- {
- // Object graphs are in reverse order, the first object is at the end
- // of the vector. Since the graph is topologically sorted it's safe to
- // assume the first object has no incoming edges.
- return vertices_.length - 1;
- }
-
- const hb_serialize_context_t::object_t& object(unsigned i) const
- {
- return vertices_[i].obj;
- }
-
- /*
- * serialize graph into the provided serialization buffer.
- */
- hb_blob_t* serialize () const
- {
- hb_vector_t<char> buffer;
- size_t size = serialized_length ();
- if (!buffer.alloc (size)) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Unable to allocate output buffer.");
- return nullptr;
- }
- hb_serialize_context_t c((void *) buffer, size);
-
- c.start_serialize<void> ();
- for (unsigned i = 0; i < vertices_.length; i++) {
- c.push ();
-
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- char* start = c.allocate_size <char> (size);
- if (!start) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Buffer out of space.");
- return nullptr;
- }
-
- memcpy (start, vertices_[i].obj.head, size);
-
- // Only real links needs to be serialized.
- for (const auto& link : vertices_[i].obj.real_links)
- serialize_link (link, start, &c);
-
- // All duplications are already encoded in the graph, so don't
- // enable sharing during packing.
- c.pop_pack (false);
- }
- c.end_serialize ();
-
- if (c.in_error ()) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Error during serialization. Err flag: %d",
- c.errors);
- return nullptr;
- }
-
- return c.copy_blob ();
- }
-
- /*
- * Generates a new topological sorting of graph using Kahn's
- * algorithm: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms
- */
- void sort_kahn ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- hb_vector_t<unsigned> queue;
- hb_vector_t<vertex_t> sorted_graph;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.push (root_idx ());
- int new_id = vertices_.length - 1;
+ unsigned lookup_index;
+ size_t size;
+ unsigned num_subtables;
- while (!queue.in_error () && queue.length)
- {
- unsigned next_id = queue[0];
- queue.remove (0);
-
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- queue.push (link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
- }
-
- /*
- * Generates a new topological sorting of graph ordered by the shortest
- * distance to each node.
- */
- void sort_shortest_distance ()
- {
- positions_invalid = true;
-
- if (vertices_.length <= 1) {
- // Graph of 1 or less doesn't need sorting.
- return;
- }
-
- update_distances ();
-
- hb_priority_queue_t queue;
- hb_vector_t<vertex_t> sorted_graph;
- if (unlikely (!check_success (sorted_graph.resize (vertices_.length)))) return;
- hb_vector_t<unsigned> id_map;
- if (unlikely (!check_success (id_map.resize (vertices_.length)))) return;
-
- hb_vector_t<unsigned> removed_edges;
- if (unlikely (!check_success (removed_edges.resize (vertices_.length)))) return;
- update_parents ();
-
- queue.insert (root ().modified_distance (0), root_idx ());
- int new_id = root_idx ();
- unsigned order = 1;
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_id = queue.pop_minimum().second;
-
- vertex_t& next = vertices_[next_id];
- sorted_graph[new_id] = next;
- id_map[next_id] = new_id--;
-
- for (const auto& link : next.obj.all_links ()) {
- removed_edges[link.objidx]++;
- if (!(vertices_[link.objidx].incoming_edges () - removed_edges[link.objidx]))
- // Add the order that the links were encountered to the priority.
- // This ensures that ties between priorities objects are broken in a consistent
- // way. More specifically this is set up so that if a set of objects have the same
- // distance they'll be added to the topological order in the order that they are
- // referenced from the parent object.
- queue.insert (vertices_[link.objidx].modified_distance (order++),
- link.objidx);
- }
- }
-
- check_success (!queue.in_error ());
- check_success (!sorted_graph.in_error ());
- if (!check_success (new_id == -1))
- print_orphaned_nodes ();
-
- remap_all_obj_indices (id_map, &sorted_graph);
-
- hb_swap (vertices_, sorted_graph);
- sorted_graph.fini ();
- }
-
- /*
- * Assign unique space numbers to each connected subgraph of 32 bit offset(s).
- */
- bool assign_32bit_spaces ()
- {
- unsigned root_index = root_idx ();
- hb_set_t visited;
- hb_set_t roots;
- for (unsigned i = 0; i <= root_index; i++)
- {
- // Only real links can form 32 bit spaces
- for (auto& l : vertices_[i].obj.real_links)
- {
- if (l.width == 4 && !l.is_signed)
- {
- roots.add (l.objidx);
- find_subgraph (l.objidx, visited);
- }
- }
- }
-
- // Mark everything not in the subgraphs of 32 bit roots as visited.
- // This prevents 32 bit subgraphs from being connected via nodes not in the 32 bit subgraphs.
- visited.invert ();
-
- if (!roots) return false;
-
- while (roots)
- {
- unsigned next = HB_SET_VALUE_INVALID;
- if (unlikely (!check_success (!roots.in_error ()))) break;
- if (!roots.next (&next)) break;
-
- hb_set_t connected_roots;
- find_connected_nodes (next, roots, visited, connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- isolate_subgraph (connected_roots);
- if (unlikely (!check_success (!connected_roots.in_error ()))) break;
-
- unsigned next_space = this->next_space ();
- num_roots_for_space_.push (0);
- for (unsigned root : connected_roots)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Subgraph %u gets space %u", root, next_space);
- vertices_[root].space = next_space;
- num_roots_for_space_[next_space] = num_roots_for_space_[next_space] + 1;
- distance_invalid = true;
- positions_invalid = true;
- }
-
- // TODO(grieger): special case for GSUB/GPOS use extension promotions to move 16 bit space
- // into the 32 bit space as needed, instead of using isolation.
- }
-
-
-
- return true;
- }
-
- /*
- * Isolates the subgraph of nodes reachable from root. Any links to nodes in the subgraph
- * that originate from outside of the subgraph will be removed by duplicating the linked to
- * object.
- *
- * Indices stored in roots will be updated if any of the roots are duplicated to new indices.
- */
- bool isolate_subgraph (hb_set_t& roots)
+ static int cmp (const void* a, const void* b)
{
- update_parents ();
- hb_hashmap_t<unsigned, unsigned> subgraph;
-
- // incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
- // set the subgraph incoming edge count to match all of root_idx's incoming edges
- hb_set_t parents;
- for (unsigned root_idx : roots)
- {
- subgraph.set (root_idx, wide_parents (root_idx, parents));
- find_subgraph (root_idx, subgraph);
- }
-
- unsigned original_root_idx = root_idx ();
- hb_hashmap_t<unsigned, unsigned> index_map;
- bool made_changes = false;
- for (auto entry : subgraph.iter ())
- {
- const auto& node = vertices_[entry.first];
- unsigned subgraph_incoming_edges = entry.second;
-
- if (subgraph_incoming_edges < node.incoming_edges ())
- {
- // Only de-dup objects with incoming links from outside the subgraph.
- made_changes = true;
- duplicate_subgraph (entry.first, index_map);
- }
- }
-
- if (!made_changes)
- return false;
-
- if (original_root_idx != root_idx ()
- && parents.has (original_root_idx))
- {
- // If the root idx has changed since parents was determined, update root idx in parents
- parents.add (root_idx ());
- parents.del (original_root_idx);
- }
-
- auto new_subgraph =
- + subgraph.keys ()
- | hb_map([&] (unsigned node_idx) {
- if (index_map.has (node_idx)) return index_map[node_idx];
- return node_idx;
- })
- ;
-
- remap_obj_indices (index_map, new_subgraph);
- remap_obj_indices (index_map, parents.iter (), true);
-
- // Update roots set with new indices as needed.
- unsigned next = HB_SET_VALUE_INVALID;
- while (roots.next (&next))
- {
- if (index_map.has (next))
- {
- roots.del (next);
- roots.add (index_map[next]);
- }
- }
-
- return true;
+ return cmp ((const lookup_size_t*) a,
+ (const lookup_size_t*) b);
}
- void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
+ static int cmp (const lookup_size_t* a, const lookup_size_t* b)
{
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- {
- if (subgraph.has (link.objidx))
- {
- subgraph.set (link.objidx, subgraph[link.objidx] + 1);
- continue;
- }
- subgraph.set (link.objidx, 1);
- find_subgraph (link.objidx, subgraph);
+ double subtables_per_byte_a = (double) a->num_subtables / (double) a->size;
+ double subtables_per_byte_b = (double) b->num_subtables / (double) b->size;
+ if (subtables_per_byte_a == subtables_per_byte_b) {
+ return b->lookup_index - a->lookup_index;
}
- }
-
- void find_subgraph (unsigned node_idx, hb_set_t& subgraph)
- {
- if (subgraph.has (node_idx)) return;
- subgraph.add (node_idx);
- for (const auto& link : vertices_[node_idx].obj.all_links ())
- find_subgraph (link.objidx, subgraph);
- }
-
- /*
- * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
- * links. index_map is updated with mappings from old id to new id. If a duplication has already
- * been performed for a given index, then it will be skipped.
- */
- void duplicate_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& index_map)
- {
- if (index_map.has (node_idx))
- return;
- index_map.set (node_idx, duplicate (node_idx));
- for (const auto& l : object (node_idx).all_links ()) {
- duplicate_subgraph (l.objidx, index_map);
- }
+ double cmp = subtables_per_byte_b - subtables_per_byte_a;
+ if (cmp < 0) return -1;
+ if (cmp > 0) return 1;
+ return 0;
}
+};
- /*
- * Creates a copy of node_idx and returns it's new index.
- */
- unsigned duplicate (unsigned node_idx)
- {
- positions_invalid = true;
- distance_invalid = true;
-
- auto* clone = vertices_.push ();
- auto& child = vertices_[node_idx];
- if (vertices_.in_error ()) {
- return -1;
- }
-
- clone->obj.head = child.obj.head;
- clone->obj.tail = child.obj.tail;
- clone->distance = child.distance;
- clone->space = child.space;
- clone->parents.reset ();
-
- unsigned clone_idx = vertices_.length - 2;
- for (const auto& l : child.obj.real_links)
- {
- clone->obj.real_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
- }
- for (const auto& l : child.obj.virtual_links)
- {
- clone->obj.virtual_links.push (l);
- vertices_[l.objidx].parents.push (clone_idx);
- }
-
- check_success (!clone->obj.real_links.in_error ());
- check_success (!clone->obj.virtual_links.in_error ());
-
- // The last object is the root of the graph, so swap back the root to the end.
- // The root's obj idx does change, however since it's root nothing else refers to it.
- // all other obj idx's will be unaffected.
- vertex_t root = vertices_[vertices_.length - 2];
- vertices_[clone_idx] = *clone;
- vertices_[vertices_.length - 1] = root;
-
- // Since the root moved, update the parents arrays of all children on the root.
- for (const auto& l : root.obj.all_links ())
- vertices_[l.objidx].remap_parent (root_idx () - 1, root_idx ());
-
- return clone_idx;
- }
-
- /*
- * Creates a copy of child and re-assigns the link from
- * parent to the clone. The copy is a shallow copy, objects
- * linked from child are not duplicated.
- */
- bool duplicate (unsigned parent_idx, unsigned child_idx)
- {
- update_parents ();
-
- unsigned links_to_child = 0;
- for (const auto& l : vertices_[parent_idx].obj.all_links ())
- {
- if (l.objidx == child_idx) links_to_child++;
- }
-
- if (vertices_[child_idx].incoming_edges () <= links_to_child)
- {
- // Can't duplicate this node, doing so would orphan the original one as all remaining links
- // to child are from parent.
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
- parent_idx, child_idx);
+static inline
+bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // For each lookup this will check the size of subtables and split them as needed
+ // so that no subtable is at risk of overflowing. (where we support splitting for
+ // that subtable type).
+ //
+ // TODO(grieger): de-dup newly added nodes as necessary. Probably just want a full de-dup
+ // pass after this processing is done. Not super necessary as splits are
+ // only done where overflow is likely, so de-dup probably will get undone
+ // later anyways.
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
+ if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
return false;
- }
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
- parent_idx, child_idx);
-
- unsigned clone_idx = duplicate (child_idx);
- if (clone_idx == (unsigned) -1) return false;
- // duplicate shifts the root node idx, so if parent_idx was root update it.
- if (parent_idx == clone_idx) parent_idx++;
-
- auto& parent = vertices_[parent_idx];
- for (auto& l : parent.obj.all_links_writer ())
- {
- if (l.objidx != child_idx)
- continue;
-
- reassign_link (l, parent_idx, clone_idx);
- }
-
- return true;
- }
-
- /*
- * Raises the sorting priority of all children.
- */
- bool raise_childrens_priority (unsigned parent_idx)
- {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " Raising priority of all children of %d",
- parent_idx);
- // This operation doesn't change ordering until a sort is run, so no need
- // to invalidate positions. It does not change graph structure so no need
- // to update distances or edge counts.
- auto& parent = vertices_[parent_idx].obj;
- bool made_change = false;
- for (auto& l : parent.all_links_writer ())
- made_change |= vertices_[l.objidx].raise_priority ();
- return made_change;
- }
-
- /*
- * Will any offsets overflow on graph when it's serialized?
- */
- bool will_overflow (hb_vector_t<overflow_record_t>* overflows = nullptr)
- {
- if (overflows) overflows->resize (0);
- update_positions ();
-
- for (int parent_idx = vertices_.length - 1; parent_idx >= 0; parent_idx--)
- {
- // Don't need to check virtual links for overflow
- for (const auto& link : vertices_[parent_idx].obj.real_links)
- {
- int64_t offset = compute_offset (parent_idx, link);
- if (is_valid_offset (offset, link))
- continue;
-
- if (!overflows) return true;
-
- overflow_record_t r;
- r.parent = parent_idx;
- r.child = link.objidx;
- overflows->push (r);
- }
- }
-
- if (!overflows) return false;
- return overflows->length;
- }
-
- void print_orphaned_nodes ()
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
- parents_invalid = true;
- update_parents();
-
- for (unsigned i = 0; i < root_idx (); i++)
- {
- const auto& v = vertices_[i];
- if (!v.parents)
- DEBUG_MSG (SUBSET_REPACK, nullptr, "Node %u is orphaned.", i);
- }
- }
-
- void print_overflows (const hb_vector_t<overflow_record_t>& overflows)
- {
- if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
-
- update_parents ();
- int limit = 10;
- for (const auto& o : overflows)
- {
- if (!limit--) break;
- const auto& parent = vertices_[o.parent];
- const auto& child = vertices_[o.child];
- DEBUG_MSG (SUBSET_REPACK, nullptr,
- " overflow from "
- "%4d (%4d in, %4d out, space %2d) => "
- "%4d (%4d in, %4d out, space %2d)",
- o.parent,
- parent.incoming_edges (),
- parent.obj.real_links.length + parent.obj.virtual_links.length,
- space_for (o.parent),
- o.child,
- child.incoming_edges (),
- child.obj.real_links.length + child.obj.virtual_links.length,
- space_for (o.child));
- }
- if (overflows.length > 10) {
- DEBUG_MSG (SUBSET_REPACK, nullptr, " ... plus %d more overflows.", overflows.length - 10);
- }
- }
-
- unsigned num_roots_for_space (unsigned space) const
- {
- return num_roots_for_space_[space];
- }
-
- unsigned next_space () const
- {
- return num_roots_for_space_.length;
}
- void move_to_new_space (const hb_set_t& indices)
- {
- num_roots_for_space_.push (0);
- unsigned new_space = num_roots_for_space_.length - 1;
-
- for (unsigned index : indices) {
- auto& node = vertices_[index];
- num_roots_for_space_[node.space] = num_roots_for_space_[node.space] - 1;
- num_roots_for_space_[new_space] = num_roots_for_space_[new_space] + 1;
- node.space = new_space;
- distance_invalid = true;
- positions_invalid = true;
- }
- }
-
- unsigned space_for (unsigned index, unsigned* root = nullptr) const
- {
- const auto& node = vertices_[index];
- if (node.space)
- {
- if (root != nullptr)
- *root = index;
- return node.space;
- }
-
- if (!node.parents)
- {
- if (root)
- *root = index;
- return 0;
- }
-
- return space_for (node.parents[0], root);
- }
-
- void err_other_error () { this->successful = false; }
-
- private:
-
- size_t serialized_length () const {
- size_t total_size = 0;
- for (unsigned i = 0; i < vertices_.length; i++) {
- size_t size = vertices_[i].obj.tail - vertices_[i].obj.head;
- total_size += size;
- }
- return total_size;
- }
+ return true;
+}
- /*
- * Returns the numbers of incoming edges that are 32bits wide.
- */
- unsigned wide_parents (unsigned node_idx, hb_set_t& parents) const
- {
- unsigned count = 0;
+/*
+ * Analyze the lookups in a GSUB/GPOS table and decide if any should be promoted
+ * to extension lookups.
+ */
+static inline
+bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context)
+{
+ // Simple Algorithm (v1, current):
+ // 1. Calculate how many bytes each non-extension lookup consumes.
+ // 2. Select up to 64k of those to remain as non-extension (greedy, highest subtables per byte first)
+ // 3. Promote the rest.
+ //
+ // Advanced Algorithm (v2, not implemented):
+ // 1. Perform connected component analysis using lookups as roots.
+ // 2. Compute size of each connected component.
+ // 3. Select up to 64k worth of connected components to remain as non-extensions.
+ // (greedy, highest subtables per byte first)
+ // 4. Promote the rest.
+
+ // TODO(garretrieger): support extension demotion, then consider all lookups. Requires advanced algo.
+ // TODO(garretrieger): also support extension promotion during iterative resolution phase, then
+ // we can use a less conservative threshold here.
+ // TODO(grieger): skip this for the 24 bit case.
+ if (!ext_context.lookups) return true;
+
+ hb_vector_t<lookup_size_t> lookup_sizes;
+ lookup_sizes.alloc (ext_context.lookups.get_population ());
+
+ for (unsigned lookup_index : ext_context.lookups.keys ())
+ {
+ const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
hb_set_t visited;
- for (unsigned p : vertices_[node_idx].parents)
- {
- if (visited.has (p)) continue;
- visited.add (p);
-
- // Only real links can be wide
- for (const auto& l : vertices_[p].obj.real_links)
- {
- if (l.objidx == node_idx && l.width == 4 && !l.is_signed)
- {
- count++;
- parents.add (p);
- }
- }
- }
- return count;
+ lookup_sizes.push (lookup_size_t {
+ lookup_index,
+ ext_context.graph.find_subgraph_size (lookup_index, visited),
+ lookup->number_of_subtables (),
+ });
}
- bool check_success (bool success)
- { return this->successful && (success || (err_other_error (), false)); }
+ lookup_sizes.qsort ();
- /*
- * Creates a map from objid to # of incoming edges.
- */
- void update_parents ()
- {
- if (!parents_invalid) return;
-
- for (unsigned i = 0; i < vertices_.length; i++)
- vertices_[i].parents.reset ();
+ size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
+ size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups
+ size_t l3_l4_size = 0; // Lookups + SubTables
+ size_t l4_plus_size = 0; // SubTables + their descendants
- for (unsigned p = 0; p < vertices_.length; p++)
- {
- for (auto& l : vertices_[p].obj.all_links ())
- {
- vertices_[l.objidx].parents.push (p);
- }
- }
-
- parents_invalid = false;
- }
-
- /*
- * compute the serialized start and end positions for each vertex.
- */
- void update_positions ()
- {
- if (!positions_invalid) return;
-
- unsigned current_pos = 0;
- for (int i = root_idx (); i >= 0; i--)
- {
- auto& v = vertices_[i];
- v.start = current_pos;
- current_pos += v.obj.tail - v.obj.head;
- v.end = current_pos;
- }
-
- positions_invalid = false;
- }
-
- /*
- * Finds the distance to each object in the graph
- * from the initial node.
- */
- void update_distances ()
- {
- if (!distance_invalid) return;
-
- // Uses Dijkstra's algorithm to find all of the shortest distances.
- // https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
- //
- // Implementation Note:
- // Since our priority queue doesn't support fast priority decreases
- // we instead just add new entries into the queue when a priority changes.
- // Redundant ones are filtered out later on by the visited set.
- // According to https://www3.cs.stonybrook.edu/~rezaul/papers/TR-07-54.pdf
- // for practical performance this is faster then using a more advanced queue
- // (such as a fibonacci queue) with a fast decrease priority.
- for (unsigned i = 0; i < vertices_.length; i++)
- {
- if (i == vertices_.length - 1)
- vertices_[i].distance = 0;
- else
- vertices_[i].distance = hb_int_max (int64_t);
- }
-
- hb_priority_queue_t queue;
- queue.insert (0, vertices_.length - 1);
-
- hb_vector_t<bool> visited;
- visited.resize (vertices_.length);
-
- while (!queue.in_error () && !queue.is_empty ())
- {
- unsigned next_idx = queue.pop_minimum ().second;
- if (visited[next_idx]) continue;
- const auto& next = vertices_[next_idx];
- int64_t next_distance = vertices_[next_idx].distance;
- visited[next_idx] = true;
-
- for (const auto& link : next.obj.all_links ())
- {
- if (visited[link.objidx]) continue;
-
- const auto& child = vertices_[link.objidx].obj;
- unsigned link_width = link.width ? link.width : 4; // treat virtual offsets as 32 bits wide
- int64_t child_weight = (child.tail - child.head) +
- ((int64_t) 1 << (link_width * 8)) * (vertices_[link.objidx].space + 1);
- int64_t child_distance = next_distance + child_weight;
-
- if (child_distance < vertices_[link.objidx].distance)
- {
- vertices_[link.objidx].distance = child_distance;
- queue.insert (child_distance, link.objidx);
- }
- }
- }
-
- check_success (!queue.in_error ());
- if (!check_success (queue.is_empty ()))
- {
- print_orphaned_nodes ();
- return;
- }
-
- distance_invalid = false;
- }
-
- int64_t compute_offset (
- unsigned parent_idx,
- const hb_serialize_context_t::object_t::link_t& link) const
- {
- const auto& parent = vertices_[parent_idx];
- const auto& child = vertices_[link.objidx];
- int64_t offset = 0;
- switch ((hb_serialize_context_t::whence_t) link.whence) {
- case hb_serialize_context_t::whence_t::Head:
- offset = child.start - parent.start; break;
- case hb_serialize_context_t::whence_t::Tail:
- offset = child.start - parent.end; break;
- case hb_serialize_context_t::whence_t::Absolute:
- offset = child.start; break;
- }
-
- assert (offset >= link.bias);
- offset -= link.bias;
- return offset;
- }
-
- bool is_valid_offset (int64_t offset,
- const hb_serialize_context_t::object_t::link_t& link) const
- {
- if (unlikely (!link.width))
- // Virtual links can't overflow.
- return link.is_signed || offset >= 0;
-
- if (link.is_signed)
- {
- if (link.width == 4)
- return offset >= -((int64_t) 1 << 31) && offset < ((int64_t) 1 << 31);
- else
- return offset >= -(1 << 15) && offset < (1 << 15);
- }
- else
- {
- if (link.width == 4)
- return offset >= 0 && offset < ((int64_t) 1 << 32);
- else if (link.width == 3)
- return offset >= 0 && offset < ((int32_t) 1 << 24);
- else
- return offset >= 0 && offset < (1 << 16);
- }
- }
-
- /*
- * Updates a link in the graph to point to a different object. Corrects the
- * parents vector on the previous and new child nodes.
- */
- void reassign_link (hb_serialize_context_t::object_t::link_t& link,
- unsigned parent_idx,
- unsigned new_idx)
+ // Start by assuming all lookups are using extension subtables, this size will be removed later
+ // if it's decided to not make a lookup extension.
+ for (auto p : lookup_sizes)
{
- unsigned old_idx = link.objidx;
- link.objidx = new_idx;
- vertices_[old_idx].remove_parent (parent_idx);
- vertices_[new_idx].parents.push (parent_idx);
+ unsigned subtables_size = p.num_subtables * 8;
+ l3_l4_size += subtables_size;
+ l4_plus_size += subtables_size;
}
- /*
- * Updates all objidx's in all links using the provided mapping. Corrects incoming edge counts.
- */
- template<typename Iterator, hb_requires (hb_is_iterator (Iterator))>
- void remap_obj_indices (const hb_hashmap_t<unsigned, unsigned>& id_map,
- Iterator subgraph,
- bool only_wide = false)
+ bool layers_full = false;
+ for (auto p : lookup_sizes)
{
- if (!id_map) return;
- for (unsigned i : subgraph)
- {
- for (auto& link : vertices_[i].obj.all_links_writer ())
- {
- if (!id_map.has (link.objidx)) continue;
- if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
-
- reassign_link (link, i, id_map[link.objidx]);
- }
- }
- }
+ const graph::Lookup* lookup = ext_context.lookups.get(p.lookup_index);
+ if (lookup->is_extension (ext_context.table_tag))
+ // already an extension so size is counted by the loop above.
+ continue;
- /*
- * Updates all objidx's in all links using the provided mapping.
- */
- void remap_all_obj_indices (const hb_vector_t<unsigned>& id_map,
- hb_vector_t<vertex_t>* sorted_graph) const
- {
- for (unsigned i = 0; i < sorted_graph->length; i++)
+ if (!layers_full)
{
- (*sorted_graph)[i].remap_parents (id_map);
- for (auto& link : (*sorted_graph)[i].obj.all_links_writer ())
- {
- link.objidx = id_map[link.objidx];
- }
- }
- }
-
- template <typename O> void
- serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
- *offset = 0;
- c->add_link (*offset,
- // serializer has an extra nil object at the start of the
- // object array. So all id's are +1 of what our id's are.
- link.objidx + 1,
- (hb_serialize_context_t::whence_t) link.whence,
- link.bias);
- }
+ size_t lookup_size = ext_context.graph.vertices_[p.lookup_index].table_size ();
+ hb_set_t visited;
+ size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
+ size_t remaining_size = p.size - subtables_size - lookup_size;
- void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
- char* head,
- hb_serialize_context_t* c) const
- {
- switch (link.width)
- {
- case 0:
- // Virtual links aren't serialized.
- return;
- case 4:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT32> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT32> (link, head, c);
- }
- return;
- case 2:
- if (link.is_signed)
- {
- serialize_link_of_type<OT::HBINT16> (link, head, c);
- } else {
- serialize_link_of_type<OT::HBUINT16> (link, head, c);
- }
- return;
- case 3:
- serialize_link_of_type<OT::HBUINT24> (link, head, c);
- return;
- default:
- // Unexpected link width.
- assert (0);
- }
- }
+ l2_l3_size += lookup_size;
+ l3_l4_size += lookup_size + subtables_size;
+ l3_l4_size -= p.num_subtables * 8;
+ l4_plus_size += subtables_size + remaining_size;
- /*
- * Finds all nodes in targets that are reachable from start_idx, nodes in visited will be skipped.
- * For this search the graph is treated as being undirected.
- *
- * Connected targets will be added to connected and removed from targets. All visited nodes
- * will be added to visited.
- */
- void find_connected_nodes (unsigned start_idx,
- hb_set_t& targets,
- hb_set_t& visited,
- hb_set_t& connected)
- {
- if (unlikely (!check_success (!visited.in_error ()))) return;
- if (visited.has (start_idx)) return;
- visited.add (start_idx);
+ if (l2_l3_size < (1 << 16)
+ && l3_l4_size < (1 << 16)
+ && l4_plus_size < (1 << 16)) continue; // this lookup fits within all layers groups
- if (targets.has (start_idx))
- {
- targets.del (start_idx);
- connected.add (start_idx);
+ layers_full = true;
}
- const auto& v = vertices_[start_idx];
-
- // Graph is treated as undirected so search children and parents of start_idx
- for (const auto& l : v.obj.all_links ())
- find_connected_nodes (l.objidx, targets, visited, connected);
-
- for (unsigned p : v.parents)
- find_connected_nodes (p, targets, visited, connected);
+ if (!ext_context.lookups.get(p.lookup_index)->make_extension (ext_context, p.lookup_index))
+ return false;
}
- public:
- // TODO(garretrieger): make private, will need to move most of offset overflow code into graph.
- hb_vector_t<vertex_t> vertices_;
- private:
- bool parents_invalid;
- bool distance_invalid;
- bool positions_invalid;
- bool successful;
- hb_vector_t<unsigned> num_roots_for_space_;
-};
+ return true;
+}
-static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record_t>& overflows,
- graph_t& sorted_graph)
+static inline
+bool _try_isolating_subgraphs (const hb_vector_t<graph::overflow_record_t>& overflows,
+ graph_t& sorted_graph)
{
unsigned space = 0;
hb_set_t roots_to_isolate;
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
unsigned root;
unsigned overflow_space = sorted_graph.space_for (r.parent, &root);
@@ -1147,16 +228,17 @@ static bool _try_isolating_subgraphs (const hb_vector_t<graph_t::overflow_record
return true;
}
-static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& overflows,
- hb_set_t& priority_bumped_parents,
- graph_t& sorted_graph)
+static inline
+bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
+ hb_set_t& priority_bumped_parents,
+ graph_t& sorted_graph)
{
bool resolution_attempted = false;
// Try resolving the furthest overflows first.
for (int i = overflows.length - 1; i >= 0; i--)
{
- const graph_t::overflow_record_t& r = overflows[i];
+ const graph::overflow_record_t& r = overflows[i];
const auto& child = sorted_graph.vertices_[r.child];
if (child.is_shared ())
{
@@ -1207,43 +289,64 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o
* For a detailed writeup describing how the algorithm operates see:
* docs/repacker.md
*/
+template<typename T>
inline hb_blob_t*
-hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& packed,
+hb_resolve_overflows (const T& packed,
hb_tag_t table_tag,
- unsigned max_rounds = 20) {
- // Kahn sort is ~twice as fast as shortest distance sort and works for many fonts
- // so try it first to save time.
+ unsigned max_rounds = 20,
+ bool recalculate_extensions = false) {
graph_t sorted_graph (packed);
- sorted_graph.sort_kahn ();
- if (!sorted_graph.will_overflow ())
+ sorted_graph.sort_shortest_distance ();
+
+ bool will_overflow = graph::will_overflow (sorted_graph);
+ if (!will_overflow)
{
- return sorted_graph.serialize ();
+ return graph::serialize (sorted_graph);
}
- sorted_graph.sort_shortest_distance ();
-
+ graph::gsubgpos_graph_context_t ext_context (table_tag, sorted_graph);
if ((table_tag == HB_OT_TAG_GPOS
|| table_tag == HB_OT_TAG_GSUB)
- && sorted_graph.will_overflow ())
+ && will_overflow)
{
+ if (recalculate_extensions)
+ {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Splitting subtables if needed.");
+ if (!_presplit_subtables_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Subtable splitting failed.");
+ return nullptr;
+ }
+
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Promoting lookups to extensions if needed.");
+ if (!_promote_extensions_if_needed (ext_context)) {
+ DEBUG_MSG (SUBSET_REPACK, nullptr, "Extensions promotion failed.");
+ return nullptr;
+ }
+ }
+
DEBUG_MSG (SUBSET_REPACK, nullptr, "Assigning spaces to 32 bit subgraphs.");
- if (sorted_graph.assign_32bit_spaces ())
+ if (sorted_graph.assign_spaces ())
sorted_graph.sort_shortest_distance ();
+ else
+ sorted_graph.sort_shortest_distance_if_needed ();
}
unsigned round = 0;
- hb_vector_t<graph_t::overflow_record_t> overflows;
+ hb_vector_t<graph::overflow_record_t> overflows;
// TODO(garretrieger): select a good limit for max rounds.
while (!sorted_graph.in_error ()
- && sorted_graph.will_overflow (&overflows)
- && round++ < max_rounds) {
+ && graph::will_overflow (sorted_graph, &overflows)
+ && round < max_rounds) {
DEBUG_MSG (SUBSET_REPACK, nullptr, "=== Overflow resolution round %d ===", round);
- sorted_graph.print_overflows (overflows);
+ print_overflows (sorted_graph, overflows);
hb_set_t priority_bumped_parents;
if (!_try_isolating_subgraphs (overflows, sorted_graph))
{
+ // Don't count space isolation towards round limit. Only increment
+ // round counter if space isolation made no changes.
+ round++;
if (!_process_overflows (overflows, priority_bumped_parents, sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "No resolution available :(");
@@ -1260,13 +363,13 @@ hb_resolve_overflows (const hb_vector_t<hb_serialize_context_t::object_t *>& pac
return nullptr;
}
- if (sorted_graph.will_overflow ())
+ if (graph::will_overflow (sorted_graph))
{
DEBUG_MSG (SUBSET_REPACK, nullptr, "Offset overflow resolution failed.");
return nullptr;
}
- return sorted_graph.serialize ();
+ return graph::serialize (sorted_graph);
}
#endif /* HB_REPACKER_HH */
diff --git a/thirdparty/harfbuzz/src/hb-serialize.hh b/thirdparty/harfbuzz/src/hb-serialize.hh
index 6615f033c5..cecdcdeb74 100644
--- a/thirdparty/harfbuzz/src/hb-serialize.hh
+++ b/thirdparty/harfbuzz/src/hb-serialize.hh
@@ -36,6 +36,9 @@
#include "hb-map.hh"
#include "hb-pool.hh"
+#ifdef HB_EXPERIMENTAL_API
+#include "hb-subset-repacker.h"
+#endif
/*
* Serialize
@@ -70,6 +73,33 @@ struct hb_serialize_context_t
virtual_links.fini ();
}
+ object_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ object_t (const hb_object_t &o)
+ {
+ head = o.head;
+ tail = o.tail;
+ next = nullptr;
+ real_links.alloc (o.num_real_links);
+ for (unsigned i = 0 ; i < o.num_real_links; i++)
+ real_links.push (o.real_links[i]);
+
+ virtual_links.alloc (o.num_virtual_links);
+ for (unsigned i = 0; i < o.num_virtual_links; i++)
+ virtual_links.push (o.virtual_links[i]);
+ }
+#endif
+
+ friend void swap (object_t& a, object_t& b)
+ {
+ hb_swap (a.head, b.head);
+ hb_swap (a.tail, b.tail);
+ hb_swap (a.next, b.next);
+ hb_swap (a.real_links, b.real_links);
+ hb_swap (a.virtual_links, b.virtual_links);
+ }
+
bool operator == (const object_t &o) const
{
// Virtual links aren't considered for equality since they don't affect the functionality
@@ -90,11 +120,25 @@ struct hb_serialize_context_t
struct link_t
{
unsigned width: 3;
- bool is_signed: 1;
+ unsigned is_signed: 1;
unsigned whence: 2;
- unsigned position: 28;
- unsigned bias;
+ unsigned bias : 26;
+ unsigned position;
objidx_t objidx;
+
+ link_t () = default;
+
+#ifdef HB_EXPERIMENTAL_API
+ link_t (const hb_link_t &o)
+ {
+ width = o.width;
+ is_signed = 0;
+ whence = 0;
+ position = o.position;
+ bias = 0;
+ objidx = o.objidx;
+ }
+#endif
};
char *head;
@@ -651,7 +695,7 @@ struct hb_serialize_context_t
check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
}
- public: /* TODO Make private. */
+ public:
char *start, *head, *tail, *end;
unsigned int debug_depth;
hb_serialize_error_t errors;
@@ -675,9 +719,7 @@ struct hb_serialize_context_t
hb_vector_t<object_t *> packed;
/* Map view of packed objects. */
- hb_hashmap_t<const object_t *, objidx_t,
- const object_t *, objidx_t,
- nullptr, 0> packed_map;
+ hb_hashmap_t<const object_t *, objidx_t> packed_map;
};
#endif /* HB_SERIALIZE_HH */
diff --git a/thirdparty/harfbuzz/src/hb-set-digest.hh b/thirdparty/harfbuzz/src/hb-set-digest.hh
index 7d4979b73b..fab36216e4 100644
--- a/thirdparty/harfbuzz/src/hb-set-digest.hh
+++ b/thirdparty/harfbuzz/src/hb-set-digest.hh
@@ -30,7 +30,7 @@
#include "hb.hh"
/*
- * The set digests here implement various "filters" that support
+ * The set-digests here implement various "filters" that support
* "approximate member query". Conceptually these are like Bloom
* Filter and Quotient Filter, however, much smaller, faster, and
* designed to fit the requirements of our uses for glyph coverage
@@ -40,13 +40,25 @@
* set of glyphs, but fully flooded and ineffective if coverage is
* all over the place.
*
- * The frozen-set can be used instead of a digest, to trade more
- * memory for 100% accuracy, but in practice, that doesn't look like
- * an attractive trade-off.
+ * The way these are used is that the filter is first populated by
+ * a lookup's or subtable's Coverage table(s), and then when we
+ * want to apply the lookup or subtable to a glyph, before trying
+ * to apply, we ask the filter if the glyph may be covered. If it's
+ * not, we return early.
+ *
+ * We use these filters both at the lookup-level, and then again,
+ * at the subtable-level. Both have performance win.
+ *
+ * The main filter we use is a combination of three bits-pattern
+ * filters. A bits-pattern filter checks a number of bits (5 or 6)
+ * of the input number (glyph-id in this case) and checks whether
+ * its pattern is amongst the patterns of any of the accepted values.
+ * The accepted patterns are represented as a "long" integer. The
+ * check is done using four bitwise operations only.
*/
template <typename mask_t, unsigned int shift>
-struct hb_set_digest_lowest_bits_t
+struct hb_set_digest_bits_pattern_t
{
static constexpr unsigned mask_bytes = sizeof (mask_t);
static constexpr unsigned mask_bits = sizeof (mask_t) * 8;
@@ -102,7 +114,7 @@ struct hb_set_digest_lowest_bits_t
bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
bool may_have (hb_codepoint_t g) const
- { return !!(mask & mask_for (g)); }
+ { return mask & mask_for (g); }
private:
@@ -171,11 +183,11 @@ struct hb_set_digest_combiner_t
using hb_set_digest_t =
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 4>,
+ hb_set_digest_bits_pattern_t<unsigned long, 4>,
hb_set_digest_combiner_t
<
- hb_set_digest_lowest_bits_t<unsigned long, 0>,
- hb_set_digest_lowest_bits_t<unsigned long, 9>
+ hb_set_digest_bits_pattern_t<unsigned long, 0>,
+ hb_set_digest_bits_pattern_t<unsigned long, 9>
>
>
;
diff --git a/thirdparty/harfbuzz/src/hb-set.cc b/thirdparty/harfbuzz/src/hb-set.cc
index 204dbb5645..0270b21998 100644
--- a/thirdparty/harfbuzz/src/hb-set.cc
+++ b/thirdparty/harfbuzz/src/hb-set.cc
@@ -40,7 +40,7 @@
/**
- * hb_set_create: (Xconstructor)
+ * hb_set_create:
*
* Creates a new, initially empty set.
*
@@ -56,8 +56,6 @@ hb_set_create ()
if (!(set = hb_object_create<hb_set_t> ()))
return hb_set_get_empty ();
- set->init_shallow ();
-
return set;
}
@@ -107,8 +105,6 @@ hb_set_destroy (hb_set_t *set)
{
if (!hb_object_destroy (set)) return;
- set->fini_shallow ();
-
hb_free (set);
}
@@ -122,7 +118,7 @@ hb_set_destroy (hb_set_t *set)
*
* Attaches a user-data key/data pair to the specified set.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -149,7 +145,7 @@ hb_set_set_user_data (hb_set_t *set,
* Since: 0.9.2
**/
void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key)
{
return hb_object_get_user_data (set, key);
@@ -162,7 +158,7 @@ hb_set_get_user_data (hb_set_t *set,
*
* Tests whether memory allocation for a set was successful.
*
- * Return value: %true if allocation succeeded, %false otherwise
+ * Return value: `true` if allocation succeeded, `false` otherwise
*
* Since: 0.9.2
**/
@@ -186,6 +182,7 @@ hb_set_t *
hb_set_copy (const hb_set_t *set)
{
hb_set_t *copy = hb_set_create ();
+ if (unlikely (!copy)) return nullptr;
copy->set (*set);
return copy;
}
@@ -211,7 +208,7 @@ hb_set_clear (hb_set_t *set)
*
* Tests whether a set is empty (contains no elements).
*
- * Return value: %true if @set is empty
+ * Return value: `true` if @set is empty
*
* Since: 0.9.7
**/
@@ -228,7 +225,7 @@ hb_set_is_empty (const hb_set_t *set)
*
* Tests whether @codepoint belongs to @set.
*
- * Return value: %true if @codepoint is in @set, %false otherwise
+ * Return value: `true` if @codepoint is in @set, `false` otherwise
*
* Since: 0.9.2
**/
@@ -257,6 +254,29 @@ hb_set_add (hb_set_t *set,
}
/**
+ * hb_set_add_sorted_array:
+ * @set: A set
+ * @sorted_codepoints: (array length=num_codepoints): Array of codepoints to add
+ * @num_codepoints: Length of @sorted_codepoints
+ *
+ * Adds @num_codepoints codepoints to a set at once.
+ * The codepoints array must be in increasing order,
+ * with size at least @num_codepoints.
+ *
+ * Since: 4.1.0
+ */
+HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints)
+{
+ /* Immutible-safe. */
+ set->add_sorted_array (sorted_codepoints,
+ num_codepoints,
+ sizeof(hb_codepoint_t));
+}
+
+/**
* hb_set_add_range:
* @set: A set
* @first: The first element to add to @set
@@ -324,7 +344,7 @@ hb_set_del_range (hb_set_t *set,
* Tests whether @set and @other are equal (contain the same
* elements).
*
- * Return value: %true if the two sets are equal, %false otherwise.
+ * Return value: `true` if the two sets are equal, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -336,13 +356,30 @@ hb_set_is_equal (const hb_set_t *set,
}
/**
+ * hb_set_hash:
+ * @set: A set
+ *
+ * Creates a hash representing @set.
+ *
+ * Return value:
+ * A hash of @set.
+ *
+ * Since: 4.4.0
+ **/
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set)
+{
+ return set->hash ();
+}
+
+/**
* hb_set_is_subset:
* @set: A set
* @larger_set: Another set
*
* Tests whether @set is a subset of @larger_set.
*
- * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise.
+ * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise.
*
* Since: 1.8.1
**/
@@ -512,7 +549,7 @@ hb_set_get_max (const hb_set_t *set)
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next value, %false otherwise
+ * Return value: `true` if there was a next value, `false` otherwise
*
* Since: 0.9.2
**/
@@ -533,7 +570,7 @@ hb_set_next (const hb_set_t *set,
*
* Set @codepoint to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous value, %false otherwise
+ * Return value: `true` if there was a previous value, `false` otherwise
*
* Since: 1.8.0
**/
@@ -556,7 +593,7 @@ hb_set_previous (const hb_set_t *set,
*
* Set @last to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a next range, %false otherwise
+ * Return value: `true` if there was a next range, `false` otherwise
*
* Since: 0.9.7
**/
@@ -580,7 +617,7 @@ hb_set_next_range (const hb_set_t *set,
*
* Set @first to #HB_SET_VALUE_INVALID to get started.
*
- * Return value: %true if there was a previous range, %false otherwise
+ * Return value: `true` if there was a previous range, `false` otherwise
*
* Since: 1.8.0
**/
@@ -591,3 +628,28 @@ hb_set_previous_range (const hb_set_t *set,
{
return set->previous_range (first, last);
}
+
+/**
+ * hb_set_next_many:
+ * @set: A set
+ * @codepoint: Outputting codepoints starting after this one.
+ * Use #HB_SET_VALUE_INVALID to get started.
+ * @out: (array length=size): An array of codepoints to write to.
+ * @size: The maximum number of codepoints to write out.
+ *
+ * Finds the next element in @set that is greater than @codepoint. Writes out
+ * codepoints to @out, until either the set runs out of elements, or @size
+ * codepoints are written, whichever comes first.
+ *
+ * Return value: the number of values written.
+ *
+ * Since: 4.2.0
+ **/
+unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size)
+{
+ return set->next_many (codepoint, out, size);
+}
diff --git a/thirdparty/harfbuzz/src/hb-set.h b/thirdparty/harfbuzz/src/hb-set.h
index 423225bf96..93636ab5d7 100644
--- a/thirdparty/harfbuzz/src/hb-set.h
+++ b/thirdparty/harfbuzz/src/hb-set.h
@@ -77,7 +77,7 @@ hb_set_set_user_data (hb_set_t *set,
hb_bool_t replace);
HB_EXTERN void *
-hb_set_get_user_data (hb_set_t *set,
+hb_set_get_user_data (const hb_set_t *set,
hb_user_data_key_t *key);
@@ -111,6 +111,11 @@ hb_set_add_range (hb_set_t *set,
hb_codepoint_t last);
HB_EXTERN void
+hb_set_add_sorted_array (hb_set_t *set,
+ const hb_codepoint_t *sorted_codepoints,
+ unsigned int num_codepoints);
+
+HB_EXTERN void
hb_set_del (hb_set_t *set,
hb_codepoint_t codepoint);
@@ -123,6 +128,9 @@ HB_EXTERN hb_bool_t
hb_set_is_equal (const hb_set_t *set,
const hb_set_t *other);
+HB_EXTERN unsigned int
+hb_set_hash (const hb_set_t *set);
+
HB_EXTERN hb_bool_t
hb_set_is_subset (const hb_set_t *set,
const hb_set_t *larger_set);
@@ -180,6 +188,12 @@ hb_set_previous_range (const hb_set_t *set,
hb_codepoint_t *first,
hb_codepoint_t *last);
+/* Pass HB_SET_VALUE_INVALID in to get started. */
+HB_EXTERN unsigned int
+hb_set_next_many (const hb_set_t *set,
+ hb_codepoint_t codepoint,
+ hb_codepoint_t *out,
+ unsigned int size);
HB_END_DECLS
diff --git a/thirdparty/harfbuzz/src/hb-set.hh b/thirdparty/harfbuzz/src/hb-set.hh
index af02e9e12b..5d5576cb9e 100644
--- a/thirdparty/harfbuzz/src/hb-set.hh
+++ b/thirdparty/harfbuzz/src/hb-set.hh
@@ -43,8 +43,8 @@ struct hb_sparseset_t
hb_sparseset_t (const hb_sparseset_t& other) : hb_sparseset_t () { set (other); }
hb_sparseset_t (hb_sparseset_t&& other) : hb_sparseset_t () { s = std::move (other.s); }
- hb_sparseset_t& operator= (const hb_sparseset_t& other) { set (other); return *this; }
- hb_sparseset_t& operator= (hb_sparseset_t&& other) { hb_swap (*this, other); return *this; }
+ hb_sparseset_t& operator = (const hb_sparseset_t& other) { set (other); return *this; }
+ hb_sparseset_t& operator = (hb_sparseset_t&& other) { s = std::move (other.s); return *this; }
friend void swap (hb_sparseset_t& a, hb_sparseset_t& b) { hb_swap (a.s, b.s); }
hb_sparseset_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t ()
@@ -53,23 +53,21 @@ struct hb_sparseset_t
add (item);
}
template <typename Iterable,
- hb_requires (hb_is_iterable (Iterable))>
+ hb_requires (hb_is_iterable (Iterable))>
hb_sparseset_t (const Iterable &o) : hb_sparseset_t ()
{
hb_copy (o, *this);
}
- void init_shallow () { s.init (); }
void init ()
{
hb_object_init (this);
- init_shallow ();
+ s.init ();
}
- void fini_shallow () { s.fini (); }
void fini ()
{
hb_object_fini (this);
- fini_shallow ();
+ s.fini ();
}
explicit operator bool () const { return !is_empty (); }
@@ -77,10 +75,12 @@ struct hb_sparseset_t
void err () { s.err (); }
bool in_error () const { return s.in_error (); }
+ void alloc (unsigned sz) { s.alloc (sz); }
void reset () { s.reset (); }
void clear () { s.clear (); }
void invert () { s.invert (); }
bool is_empty () const { return s.is_empty (); }
+ uint32_t hash () const { return s.hash (); }
void add (hb_codepoint_t g) { s.add (g); }
bool add_range (hb_codepoint_t a, hb_codepoint_t b) { return s.add_range (a, b); }
@@ -109,6 +109,7 @@ struct hb_sparseset_t
typedef bool value_t;
value_t operator [] (hb_codepoint_t k) const { return get (k); }
bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
+
/* Predicate. */
bool operator () (hb_codepoint_t k) const { return has (k); }
@@ -124,6 +125,8 @@ struct hb_sparseset_t
void set (const hb_sparseset_t &other) { s.set (other.s); }
bool is_equal (const hb_sparseset_t &other) const { return s.is_equal (other.s); }
+ bool operator == (const hb_set_t &other) const { return is_equal (other); }
+ bool operator != (const hb_set_t &other) const { return !is_equal (other); }
bool is_subset (const hb_sparseset_t &larger_set) const { return s.is_subset (larger_set.s); }
@@ -138,6 +141,8 @@ struct hb_sparseset_t
{ return s.next_range (first, last); }
bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
{ return s.previous_range (first, last); }
+ unsigned int next_many (hb_codepoint_t codepoint, hb_codepoint_t *out, unsigned int size) const
+ { return s.next_many (codepoint, out, size); }
unsigned int get_population () const { return s.get_population (); }
hb_codepoint_t get_min () const { return s.get_min (); }
@@ -155,15 +160,18 @@ struct hb_sparseset_t
struct hb_set_t : hb_sparseset_t<hb_bit_set_invertible_t>
{
- hb_set_t () = default;
+ using sparseset = hb_sparseset_t<hb_bit_set_invertible_t>;
+
~hb_set_t () = default;
- hb_set_t (hb_set_t&) = default;
- hb_set_t& operator= (const hb_set_t&) = default;
- hb_set_t& operator= (hb_set_t&&) = default;
- hb_set_t (std::initializer_list<hb_codepoint_t> lst) : hb_sparseset_t<hb_bit_set_invertible_t> (lst) {}
+ hb_set_t () : sparseset () {};
+ hb_set_t (const hb_set_t &o) : sparseset ((sparseset &) o) {};
+ hb_set_t (hb_set_t&& o) : sparseset (std::move ((sparseset &) o)) {}
+ hb_set_t& operator = (const hb_set_t&) = default;
+ hb_set_t& operator = (hb_set_t&&) = default;
+ hb_set_t (std::initializer_list<hb_codepoint_t> lst) : sparseset (lst) {}
template <typename Iterable,
hb_requires (hb_is_iterable (Iterable))>
- hb_set_t (const Iterable &o) : hb_sparseset_t<hb_bit_set_invertible_t> (o) {}
+ hb_set_t (const Iterable &o) : sparseset (o) {}
};
static_assert (hb_set_t::INVALID == HB_SET_VALUE_INVALID, "");
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.cc b/thirdparty/harfbuzz/src/hb-shape-plan.cc
index 66332165c3..9e513c0458 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.cc
@@ -117,7 +117,7 @@ hb_shape_plan_key_t::init (bool copy,
}
else
{
- const hb_shaper_entry_t *shapers = _hb_shapers_get ();
+ const HB_UNUSED hb_shaper_entry_t *shapers = _hb_shapers_get ();
for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++)
if (false)
;
@@ -170,7 +170,7 @@ hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other)
/**
- * hb_shape_plan_create: (Xconstructor)
+ * hb_shape_plan_create:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -198,7 +198,7 @@ hb_shape_plan_create (hb_face_t *face,
}
/**
- * hb_shape_plan_create2: (Xconstructor)
+ * hb_shape_plan_create2:
* @face: #hb_face_t to use
* @props: The #hb_segment_properties_t of the segment
* @user_features: (array length=num_user_features): The list of user-selected features
@@ -231,7 +231,8 @@ hb_shape_plan_create2 (hb_face_t *face,
num_coords,
shaper_list);
- assert (props->direction != HB_DIRECTION_INVALID);
+ if (unlikely (props->direction == HB_DIRECTION_INVALID))
+ return hb_shape_plan_get_empty ();
hb_shape_plan_t *shape_plan;
@@ -317,10 +318,6 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
{
if (!hb_object_destroy (shape_plan)) return;
-#ifndef HB_NO_OT_SHAPE
- shape_plan->ot.fini ();
-#endif
- shape_plan->key.fini ();
hb_free (shape_plan);
}
@@ -334,7 +331,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan)
*
* Attaches a user-data key/data pair to the given shaping plan.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
@@ -361,8 +358,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
* Since: 0.9.7
**/
void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key)
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (shape_plan, key);
}
@@ -439,7 +436,7 @@ _hb_shape_plan_execute_internal (hb_shape_plan_t *shape_plan,
* Executes the given shaping plan on the specified buffer, using
* the given @font and @features.
*
- * Return value: %true if success, %false otherwise.
+ * Return value: `true` if success, `false` otherwise.
*
* Since: 0.9.7
**/
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.h b/thirdparty/harfbuzz/src/hb-shape-plan.h
index fc7c041899..aaf5cf9c45 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.h
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.h
@@ -102,8 +102,8 @@ hb_shape_plan_set_user_data (hb_shape_plan_t *shape_plan,
hb_bool_t replace);
HB_EXTERN void *
-hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan,
- hb_user_data_key_t *key);
+hb_shape_plan_get_user_data (const hb_shape_plan_t *shape_plan,
+ hb_user_data_key_t *key);
HB_EXTERN hb_bool_t
diff --git a/thirdparty/harfbuzz/src/hb-shape-plan.hh b/thirdparty/harfbuzz/src/hb-shape-plan.hh
index 8cb4ddb927..6fc73939b3 100644
--- a/thirdparty/harfbuzz/src/hb-shape-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-shape-plan.hh
@@ -55,7 +55,7 @@ struct hb_shape_plan_key_t
unsigned int num_coords,
const char * const *shaper_list);
- HB_INTERNAL void fini () { hb_free ((void *) user_features); }
+ HB_INTERNAL void fini () { hb_free ((void *) user_features); user_features = nullptr; }
HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other);
@@ -64,6 +64,7 @@ struct hb_shape_plan_key_t
struct hb_shape_plan_t
{
+ ~hb_shape_plan_t () { key.fini (); }
hb_object_header_t header;
hb_face_t *face_unsafe; /* We don't carry a reference to face. */
hb_shape_plan_key_t key;
diff --git a/thirdparty/harfbuzz/src/hb-shape.cc b/thirdparty/harfbuzz/src/hb-shape.cc
index c1f619c81c..547d0afc47 100644
--- a/thirdparty/harfbuzz/src/hb-shape.cc
+++ b/thirdparty/harfbuzz/src/hb-shape.cc
@@ -50,7 +50,7 @@
static inline void free_static_shaper_list ();
-static const char *nil_shaper_list[] = {nullptr};
+static const char * const nil_shaper_list[] = {nullptr};
static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
hb_shaper_list_lazy_loader_t>
@@ -73,7 +73,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t<const char *,
}
static void destroy (const char **l)
{ hb_free (l); }
- static const char ** get_null ()
+ static const char * const * get_null ()
{ return nil_shaper_list; }
} static_shaper_list;
@@ -106,12 +106,12 @@ hb_shape_list_shapers ()
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
- * @shaper_list: (array zero-terminated=1) (nullable): a %NULL-terminated
- * array of shapers to use or %NULL
+ * @shaper_list: (array zero-terminated=1) (nullable): a `NULL`-terminated
+ * array of shapers to use or `NULL`
*
- * See hb_shape() for details. If @shaper_list is not %NULL, the specified
+ * See hb_shape() for details. If @shaper_list is not `NULL`, the specified
* shapers will be used in the given order, otherwise the default shapers list
* will be used.
*
@@ -126,13 +126,45 @@ hb_shape_full (hb_font_t *font,
unsigned int num_features,
const char * const *shaper_list)
{
+ if (unlikely (!buffer->len))
+ return true;
+
+ buffer->enter ();
+
+ hb_buffer_t *text_buffer = nullptr;
+ if (buffer->flags & HB_BUFFER_FLAG_VERIFY)
+ {
+ text_buffer = hb_buffer_create ();
+ hb_buffer_append (text_buffer, buffer, 0, -1);
+ }
+
hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props,
features, num_features,
font->coords, font->num_coords,
shaper_list);
+
hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features);
+
+ if (buffer->max_ops <= 0)
+ buffer->shaping_failed = true;
+
hb_shape_plan_destroy (shape_plan);
+ if (text_buffer)
+ {
+ if (res && buffer->successful && !buffer->shaping_failed
+ && text_buffer->successful
+ && !buffer->verify (text_buffer,
+ font,
+ features,
+ num_features,
+ shaper_list))
+ res = false;
+ hb_buffer_destroy (text_buffer);
+ }
+
+ buffer->leave ();
+
return res;
}
@@ -141,11 +173,11 @@ hb_shape_full (hb_font_t *font,
* @font: an #hb_font_t to use for shaping
* @buffer: an #hb_buffer_t to shape
* @features: (array length=num_features) (nullable): an array of user
- * specified #hb_feature_t or %NULL
+ * specified #hb_feature_t or `NULL`
* @num_features: the length of @features array
*
* Shapes @buffer using @font turning its Unicode characters content to
- * positioned glyphs. If @features is not %NULL, it will be used to control the
+ * positioned glyphs. If @features is not `NULL`, it will be used to control the
* features applied during shaping. If two @features have the same tag but
* overlapping ranges the value of the feature with the higher index takes
* precedence.
diff --git a/thirdparty/harfbuzz/src/hb-shaper.cc b/thirdparty/harfbuzz/src/hb-shaper.cc
index a11ed83afd..a900ac6991 100644
--- a/thirdparty/harfbuzz/src/hb-shaper.cc
+++ b/thirdparty/harfbuzz/src/hb-shaper.cc
@@ -29,18 +29,18 @@
#include "hb-machinery.hh"
-static const hb_shaper_entry_t all_shapers[] = {
+static const hb_shaper_entry_t _hb_all_shapers[] = {
#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape},
#include "hb-shaper-list.hh"
#undef HB_SHAPER_IMPLEMENT
};
#ifndef HB_NO_SHAPER
-static_assert (0 != ARRAY_LENGTH_CONST (all_shapers), "No shaper enabled.");
+static_assert (0 != ARRAY_LENGTH_CONST (_hb_all_shapers), "No shaper enabled.");
#endif
static inline void free_static_shapers ();
-static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_t,
+static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<hb_shaper_entry_t,
hb_shapers_lazy_loader_t>
{
static hb_shaper_entry_t *create ()
@@ -49,11 +49,11 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!env || !*env)
return nullptr;
- hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (all_shapers));
+ hb_shaper_entry_t *shapers = (hb_shaper_entry_t *) hb_calloc (1, sizeof (_hb_all_shapers));
if (unlikely (!shapers))
return nullptr;
- memcpy (shapers, all_shapers, sizeof (all_shapers));
+ memcpy (shapers, _hb_all_shapers, sizeof (_hb_all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
@@ -64,7 +64,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
if (!end)
end = p + strlen (p);
- for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++)
+ for (unsigned int j = i; j < ARRAY_LENGTH_CONST (_hb_all_shapers); j++)
if (end - p == (int) strlen (shapers[j].name) &&
0 == strncmp (shapers[j].name, p, end - p))
{
@@ -85,8 +85,8 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t<const hb_shaper_entry_
return shapers;
}
- static void destroy (const hb_shaper_entry_t *p) { hb_free ((void *) p); }
- static const hb_shaper_entry_t *get_null () { return all_shapers; }
+ static void destroy (hb_shaper_entry_t *p) { hb_free (p); }
+ static const hb_shaper_entry_t *get_null () { return _hb_all_shapers; }
} static_shapers;
static inline
diff --git a/thirdparty/harfbuzz/src/hb-static.cc b/thirdparty/harfbuzz/src/hb-static.cc
index ec4b241470..af95615c16 100644
--- a/thirdparty/harfbuzz/src/hb-static.cc
+++ b/thirdparty/harfbuzz/src/hb-static.cc
@@ -33,6 +33,7 @@
#include "hb-aat-layout-feat-table.hh"
#include "hb-ot-layout-common.hh"
#include "hb-ot-cmap-table.hh"
+#include "hb-ot-glyf-table.hh"
#include "hb-ot-head-table.hh"
#include "hb-ot-maxp-table.hh"
@@ -45,27 +46,55 @@ uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof
DEFINE_NULL_NAMESPACE_BYTES (OT, Index) = {0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, VarIdx) = {0xFF,0xFF,0xFF,0xFF};
DEFINE_NULL_NAMESPACE_BYTES (OT, LangSys) = {0x00,0x00, 0xFF,0xFF, 0x00,0x00};
-DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x00,0x01, 0x00,0x00, 0x00, 0x00};
+DEFINE_NULL_NAMESPACE_BYTES (OT, RangeRecord) = {0x01};
DEFINE_NULL_NAMESPACE_BYTES (OT, CmapSubtableLongGroup) = {0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00};
DEFINE_NULL_NAMESPACE_BYTES (AAT, SettingName) = {0xFF,0xFF, 0xFF,0xFF};
-/* Hand-coded because Lookup is a template. Sad. */
-const unsigned char _hb_Null_AAT_Lookup[2] = {0xFF, 0xFF};
+DEFINE_NULL_NAMESPACE_BYTES (AAT, Lookup) = {0xFF,0xFF};
+/* hb_map_t */
+
+const hb_codepoint_t minus_1 = -1;
/* hb_face_t */
+#ifndef HB_NO_BEYOND_64K
+static inline unsigned
+load_num_glyphs_from_loca (const hb_face_t *face)
+{
+ unsigned ret = 0;
+
+ unsigned indexToLocFormat = face->table.head->indexToLocFormat;
+
+ if (indexToLocFormat <= 1)
+ {
+ bool short_offset = 0 == indexToLocFormat;
+ hb_blob_t *loca_blob = face->table.loca.get_blob ();
+ ret = hb_max (1u, loca_blob->length / (short_offset ? 2 : 4)) - 1;
+ }
+
+ return ret;
+}
+#endif
+
+static inline unsigned
+load_num_glyphs_from_maxp (const hb_face_t *face)
+{
+ return face->table.maxp->get_num_glyphs ();
+}
+
unsigned int
hb_face_t::load_num_glyphs () const
{
- hb_sanitize_context_t c = hb_sanitize_context_t ();
- c.set_num_glyphs (0); /* So we don't recurse ad infinitum. */
- hb_blob_t *maxp_blob = c.reference_table<OT::maxp> (this);
- const OT::maxp *maxp_table = maxp_blob->as<OT::maxp> ();
+ unsigned ret = 0;
+
+#ifndef HB_NO_BEYOND_64K
+ ret = hb_max (ret, load_num_glyphs_from_loca (this));
+#endif
+
+ ret = hb_max (ret, load_num_glyphs_from_maxp (this));
- unsigned int ret = maxp_table->get_num_glyphs ();
num_glyphs.set_relaxed (ret);
- hb_blob_destroy (maxp_blob);
return ret;
}
diff --git a/thirdparty/harfbuzz/src/hb-style.cc b/thirdparty/harfbuzz/src/hb-style.cc
index c0c5c4832c..c7d7d713c2 100644
--- a/thirdparty/harfbuzz/src/hb-style.cc
+++ b/thirdparty/harfbuzz/src/hb-style.cc
@@ -46,13 +46,13 @@
static inline float
_hb_angle_to_ratio (float a)
{
- return tanf (a * float (M_PI / 180.));
+ return tanf (a * float (-M_PI / 180.));
}
static inline float
_hb_ratio_to_angle (float r)
{
- return atanf (r) * float (180. / M_PI);
+ return atanf (r) * float (-180. / M_PI);
}
/**
@@ -72,8 +72,7 @@ float
hb_style_get_value (hb_font_t *font, hb_style_tag_t style_tag)
{
if (unlikely (style_tag == HB_STYLE_TAG_SLANT_RATIO))
- return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE))
- + font->slant;
+ return _hb_angle_to_ratio (hb_style_get_value (font, HB_STYLE_TAG_SLANT_ANGLE));
hb_face_t *face = font->face;
diff --git a/thirdparty/harfbuzz/src/hb-style.h b/thirdparty/harfbuzz/src/hb-style.h
index 30a6f2b878..d17d2daa5f 100644
--- a/thirdparty/harfbuzz/src/hb-style.h
+++ b/thirdparty/harfbuzz/src/hb-style.h
@@ -43,8 +43,10 @@ HB_BEGIN_DECLS
* @HB_STYLE_TAG_SLANT_ANGLE: Used to vary between upright and slanted text. Values
* must be greater than -90 and less than +90. Values can be interpreted as
* the angle, in counter-clockwise degrees, of oblique slant from whatever the
- * designer considers to be upright for that font design.
+ * designer considers to be upright for that font design. Typical right-leaning
+ * Italic fonts have a negative slant angle (typically around -12)
* @HB_STYLE_TAG_SLANT_RATIO: same as @HB_STYLE_TAG_SLANT_ANGLE expression as ratio.
+ * Typical right-leaning Italic fonts have a positive slant ratio (typically around 0.2)
* @HB_STYLE_TAG_WIDTH: Used to vary width of text from narrower to wider.
* Non-zero. Values can be interpreted as a percentage of whatever the font
* designer considers “normal width†for that font design.
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
index 18657705fa..bb9f27eec1 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-cff-common.hh
@@ -40,11 +40,12 @@ struct str_encoder_t
str_encoder_t (str_buff_t &buff_)
: buff (buff_), error (false) {}
- void reset () { buff.resize (0); }
+ void reset () { buff.reset (); }
void encode_byte (unsigned char b)
{
- if (unlikely (buff.push (b) == &Crap (unsigned char)))
+ buff.push (b);
+ if (unlikely (buff.in_error ()))
set_error ();
}
@@ -107,20 +108,18 @@ struct str_encoder_t
encode_byte (op);
}
- void copy_str (const byte_str_t &str)
+ void copy_str (const hb_ubytes_t &str)
{
unsigned int offset = buff.length;
- if (unlikely (!buff.resize (offset + str.length)))
+ /* Manually resize buffer since faster. */
+ if ((signed) (buff.length + str.length) <= buff.allocated)
+ buff.length += str.length;
+ else if (unlikely (!buff.resize (offset + str.length)))
{
set_error ();
return;
}
- if (unlikely (buff.length < offset + str.length))
- {
- set_error ();
- return;
- }
- memcpy (&buff[offset], &str[0], str.length);
+ memcpy (buff.arrayZ + offset, &str[0], str.length);
}
bool is_error () const { return error; }
@@ -253,12 +252,12 @@ struct subr_flattener_t
if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
continue;
}
- const byte_str_t str = (*acc.charStrings)[glyph];
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- cs_interpreter_t<ENV, OPSET, flatten_param_t> interp;
- interp.env.init (str, acc, fd);
+ ENV env (str, acc, fd);
+ cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
flatten_param_t param = {
flat_charstrings[i],
(bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
@@ -317,9 +316,9 @@ struct parsed_cs_op_t : op_str_t
unsigned int subr_num;
protected:
- bool drop_flag : 1;
- bool keep_flag : 1;
- bool skip_flag : 1;
+ bool drop_flag;
+ bool keep_flag;
+ bool skip_flag;
};
struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
@@ -398,19 +397,19 @@ struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
struct subr_subset_param_t
{
- void init (parsed_cs_str_t *parsed_charstring_,
- parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
- hb_set_t *global_closure_, hb_set_t *local_closure_,
- bool drop_hints_)
- {
- parsed_charstring = parsed_charstring_;
- current_parsed_str = parsed_charstring;
- parsed_global_subrs = parsed_global_subrs_;
- parsed_local_subrs = parsed_local_subrs_;
- global_closure = global_closure_;
- local_closure = local_closure_;
- drop_hints = drop_hints_;
- }
+ subr_subset_param_t (parsed_cs_str_t *parsed_charstring_,
+ parsed_cs_str_vec_t *parsed_global_subrs_,
+ parsed_cs_str_vec_t *parsed_local_subrs_,
+ hb_set_t *global_closure_,
+ hb_set_t *local_closure_,
+ bool drop_hints_) :
+ current_parsed_str (parsed_charstring_),
+ parsed_charstring (parsed_charstring_),
+ parsed_global_subrs (parsed_global_subrs_),
+ parsed_local_subrs (parsed_local_subrs_),
+ global_closure (global_closure_),
+ local_closure (local_closure_),
+ drop_hints (drop_hints_) {}
parsed_cs_str_t *get_parsed_str_for_context (call_context_t &context)
{
@@ -468,6 +467,7 @@ struct subr_remap_t : hb_inc_bimap_t
* no optimization based on usage counts. fonttools doesn't appear doing that either.
*/
+ resize (closure->get_population ());
hb_codepoint_t old_num = HB_SET_VALUE_INVALID;
while (hb_set_next (closure, &old_num))
add (old_num);
@@ -561,19 +561,21 @@ struct subr_subsetter_t
hb_codepoint_t glyph;
if (!plan->old_gid_for_new_gid (i, &glyph))
continue;
- const byte_str_t str = (*acc.charStrings)[glyph];
+ const hb_ubytes_t str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp;
- interp.env.init (str, acc, fd);
+ ENV env (str, acc, fd);
+ cs_interpreter_t<ENV, OPSET, subr_subset_param_t> interp (env);
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ parsed_charstrings[i].alloc (str.length);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
if (unlikely (!interp.interpret (param)))
return false;
@@ -593,11 +595,12 @@ struct subr_subsetter_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
drop_hints_param_t drop;
if (drop_hints_in_str (parsed_charstrings[i], param, drop))
@@ -618,11 +621,12 @@ struct subr_subsetter_t
unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount))
return false;
- subr_subset_param_t param;
- param.init (&parsed_charstrings[i],
- &parsed_global_subrs, &parsed_local_subrs[fd],
- &closures.global_closure, &closures.local_closures[fd],
- plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+ subr_subset_param_t param (&parsed_charstrings[i],
+ &parsed_global_subrs,
+ &parsed_local_subrs[fd],
+ &closures.global_closure,
+ &closures.local_closures[fd],
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
collect_subr_refs_in_str (parsed_charstrings[i], param);
}
}
@@ -849,9 +853,10 @@ struct subr_subsetter_t
bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
{
- buff.init ();
+ unsigned count = str.get_count ();
str_encoder_t encoder (buff);
encoder.reset ();
+ buff.alloc (count * 3);
/* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
* re-insert it at the beginning of charstreing */
if (str.has_prefix () && str.is_hint_dropped ())
@@ -860,7 +865,7 @@ struct subr_subsetter_t
if (str.prefix_op () != OpCode_Invalid)
encoder.encode_op (str.prefix_op ());
}
- for (unsigned int i = 0; i < str.get_count(); i++)
+ for (unsigned int i = 0; i < count; i++)
{
const parsed_cs_op_t &opstr = str.values[i];
if (!opstr.for_drop () && !opstr.for_skip ())
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff1.cc b/thirdparty/harfbuzz/src/hb-subset-cff1.cc
index 35fecd67bc..52bb13d320 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff1.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff1.cc
@@ -169,7 +169,7 @@ struct cff1_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<cff1_top_dic
supp_op.op = op;
if ( unlikely (!(opstr.str.length >= opstr.last_arg_offset + 3)))
return_trace (false);
- supp_op.str = byte_str_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
+ supp_op.str = hb_ubytes_t (&opstr.str + opstr.last_arg_offset, opstr.str.length - opstr.last_arg_offset);
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::registry]) &&
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[name_dict_values_t::ordering]) &&
copy_opstr (c, supp_op));
@@ -270,13 +270,13 @@ struct range_list_t : hb_vector_t<code_pair_t>
/* replace the first glyph ID in the "glyph" field each range with a nLeft value */
bool complete (unsigned int last_glyph)
{
- bool two_byte = false;
- for (unsigned int i = (*this).length; i > 0; i--)
+ bool two_byte = false;
+ unsigned count = this->length;
+ for (unsigned int i = count; i; i--)
{
- code_pair_t &pair = (*this)[i - 1];
- unsigned int nLeft = last_glyph - pair.glyph - 1;
- if (nLeft >= 0x100)
- two_byte = true;
+ code_pair_t &pair = arrayZ[i - 1];
+ unsigned int nLeft = last_glyph - pair.glyph - 1;
+ two_byte |= nLeft >= 0x100;
last_glyph = pair.glyph;
pair.glyph = nLeft;
}
@@ -442,6 +442,9 @@ struct cff_subset_plan {
return;
}
+ bool use_glyph_to_sid_map = plan->num_output_glyphs () > plan->source->get_num_glyphs () / 8.;
+ hb_map_t *glyph_to_sid_map = use_glyph_to_sid_map ? acc.create_glyph_to_sid_map () : nullptr;
+
unsigned int glyph;
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++)
{
@@ -451,7 +454,7 @@ struct cff_subset_plan {
/* Retain the SID for the old missing glyph ID */
old_glyph = glyph;
}
- sid = acc.glyph_to_sid (old_glyph);
+ sid = glyph_to_sid_map ? glyph_to_sid_map->get (old_glyph) : acc.glyph_to_sid (old_glyph);
if (!acc.is_CID ())
sid = sidmap.add (sid);
@@ -464,6 +467,9 @@ struct cff_subset_plan {
last_sid = sid;
}
+ if (glyph_to_sid_map)
+ hb_map_destroy (glyph_to_sid_map);
+
bool two_byte = subset_charset_ranges.complete (glyph);
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1);
diff --git a/thirdparty/harfbuzz/src/hb-subset-cff2.cc b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
index 92dd6b1d2c..08e820efcf 100644
--- a/thirdparty/harfbuzz/src/hb-subset-cff2.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-cff2.cc
@@ -67,9 +67,9 @@ struct cff2_top_dict_op_serializer_t : cff_top_dict_op_serializer_t<>
}
};
-struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t>
+struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t>
{
- static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args_and_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -97,7 +97,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
}
- static void flush_args (cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_args (cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
for (unsigned int i = 0; i < env.argStack.get_count ();)
{
@@ -122,7 +122,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
SUPER::flush_args (env, param);
}
- static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
/* flatten the default values */
str_encoder_t encoder (param.flatStr);
@@ -149,7 +149,7 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
encoder.encode_op (OpCode_blendcs);
}
- static void flush_op (op_code_t op, cff2_cs_interp_env_t &env, flatten_param_t& param)
+ static void flush_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
switch (op)
{
@@ -163,13 +163,13 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
}
private:
- typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t> SUPER;
- typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t, flatten_param_t> CSOPSET;
+ typedef cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatten_param_t, blend_arg_t> SUPER;
+ typedef cs_opset_t<blend_arg_t, cff2_cs_opset_flatten_t, cff2_cs_opset_flatten_t, cff2_cs_interp_env_t<blend_arg_t>, flatten_param_t> CSOPSET;
};
-struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t>
+struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t>
{
- static void process_op (op_code_t op, cff2_cs_interp_env_t &env, subr_subset_param_t& param)
+ static void process_op (op_code_t op, cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param)
{
switch (op) {
@@ -201,7 +201,7 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
protected:
static void process_call_subr (op_code_t op, cs_type_t type,
- cff2_cs_interp_env_t &env, subr_subset_param_t& param,
+ cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param,
cff2_biased_subrs_t& subrs, hb_set_t *closure)
{
byte_str_ref_t str_ref = env.str_ref;
@@ -212,15 +212,15 @@ struct cff2_cs_opset_subr_subset_t : cff2_cs_opset_t<cff2_cs_opset_subr_subset_t
}
private:
- typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t> SUPER;
+ typedef cff2_cs_opset_t<cff2_cs_opset_subr_subset_t, subr_subset_param_t, blend_arg_t> SUPER;
};
-struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_subr_subset_t>
+struct cff2_subr_subsetter_t : subr_subsetter_t<cff2_subr_subsetter_t, CFF2Subrs, const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_subr_subset_t>
{
cff2_subr_subsetter_t (const OT::cff2::accelerator_subset_t &acc_, const hb_subset_plan_t *plan_)
: subr_subsetter_t (acc_, plan_) {}
- static void complete_parsed_str (cff2_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
+ static void complete_parsed_str (cff2_cs_interp_env_t<blend_arg_t> &env, subr_subset_param_t& param, parsed_cs_str_t &charstring)
{
/* vsindex is inserted at the beginning of the charstring as necessary */
if (env.seen_vsindex ())
@@ -245,7 +245,7 @@ struct cff2_subset_plan {
if (desubroutinize)
{
/* Flatten global & local subrs */
- subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t, cff2_cs_opset_flatten_t>
+ subr_flattener_t<const OT::cff2::accelerator_subset_t, cff2_cs_interp_env_t<blend_arg_t>, cff2_cs_opset_flatten_t>
flattener(acc, plan);
if (!flattener.flatten (subset_charstrings))
return false;
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.cc b/thirdparty/harfbuzz/src/hb-subset-input.cc
index 4885280996..7d19496275 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-input.cc
@@ -32,7 +32,7 @@
*
* Creates a new subset input object.
*
- * Return value: (transfer full): New subset input, or %NULL if failed. Destroy
+ * Return value: (transfer full): New subset input, or `NULL` if failed. Destroy
* with hb_subset_input_destroy().
*
* Since: 1.8.0
@@ -48,7 +48,9 @@ hb_subset_input_create_or_fail (void)
for (auto& set : input->sets_iter ())
set = hb_set_create ();
- if (input->in_error ())
+ input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
+
+ if (!input->axes_location || input->in_error ())
{
hb_subset_input_destroy (input);
return nullptr;
@@ -96,7 +98,6 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('D', 'S', 'I', 'G'),
HB_TAG ('M', 'V', 'A', 'R'),
HB_TAG ('c', 'v', 'a', 'r'),
- HB_TAG ('S', 'T', 'A', 'T'),
};
input->sets.no_subset_tables->add_array (default_no_subset_tables,
ARRAY_LENGTH (default_no_subset_tables));
@@ -140,7 +141,20 @@ hb_subset_input_create_or_fail (void)
HB_TAG ('r', 't', 'l', 'a'),
HB_TAG ('r', 't', 'l', 'm'),
- //Complex shapers
+ //random
+ HB_TAG ('r', 'a', 'n', 'd'),
+
+ //justify
+ HB_TAG ('j', 'a', 'l', 't'), // HarfBuzz doesn't use; others might
+
+ //private
+ HB_TAG ('H', 'a', 'r', 'f'),
+ HB_TAG ('H', 'A', 'R', 'F'),
+ HB_TAG ('B', 'u', 'z', 'z'),
+ HB_TAG ('B', 'U', 'Z', 'Z'),
+
+ //shapers
+
//arabic
HB_TAG ('i', 'n', 'i', 't'),
HB_TAG ('m', 'e', 'd', 'i'),
@@ -190,6 +204,8 @@ hb_subset_input_create_or_fail (void)
input->sets.layout_features->add_array (default_layout_features, ARRAY_LENGTH (default_layout_features));
+ input->sets.layout_scripts->invert (); // Default to all scripts.
+
if (input->in_error ())
{
hb_subset_input_destroy (input);
@@ -231,6 +247,8 @@ hb_subset_input_destroy (hb_subset_input_t *input)
for (hb_set_t* set : input->sets_iter ())
hb_set_destroy (set);
+ hb_hashmap_destroy (input->axes_location);
+
hb_free (input);
}
@@ -329,7 +347,7 @@ hb_subset_input_set_flags (hb_subset_input_t *input,
*
* Attaches a user-data key/data pair to the given subset input object.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 2.9.0
**/
@@ -361,3 +379,56 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
{
return hb_object_get_user_data (input, key);
}
+
+#ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_VAR
+/**
+ * hb_subset_input_pin_axis_to_default: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: Tag of the axis to be pinned
+ *
+ * Pin an axis to its default location in the given subset input object.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag)
+{
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ return input->axes_location->set (axis_tag, axis_info.default_value);
+}
+
+/**
+ * hb_subset_input_pin_axis_location: (skip)
+ * @input: a #hb_subset_input_t object.
+ * @axis_tag: Tag of the axis to be pinned
+ * @axis_value: Location on the axis to be pinned at
+ *
+ * Pin an axis to a fixed location in the given subset input object.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: REPLACEME
+ **/
+hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value)
+{
+ hb_ot_var_axis_info_t axis_info;
+ if (!hb_ot_var_find_axis_info (face, axis_tag, &axis_info))
+ return false;
+
+ float val = hb_clamp(axis_value, axis_info.min_value, axis_info.max_value);
+ return input->axes_location->set (axis_tag, val);
+}
+#endif
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-input.hh b/thirdparty/harfbuzz/src/hb-subset-input.hh
index 07c0e22676..2335f0634f 100644
--- a/thirdparty/harfbuzz/src/hb-subset-input.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-input.hh
@@ -50,6 +50,7 @@ struct hb_subset_input_t
hb_set_t *name_ids;
hb_set_t *name_languages;
hb_set_t *layout_features;
+ hb_set_t *layout_scripts;
};
union {
@@ -58,6 +59,7 @@ struct hb_subset_input_t
};
unsigned flags;
+ hb_hashmap_t<hb_tag_t, float> *axes_location;
inline unsigned num_sets () const
{
@@ -76,7 +78,8 @@ struct hb_subset_input_t
if (unlikely (set_ptrs[i]->in_error ()))
return true;
}
- return false;
+
+ return axes_location->in_error ();
}
};
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.cc b/thirdparty/harfbuzz/src/hb-subset-plan.cc
index af4fcb8137..7ff66333a8 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.cc
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.cc
@@ -37,11 +37,14 @@
#include "hb-ot-color-colr-table.hh"
#include "hb-ot-color-colrv1-closure.hh"
#include "hb-ot-var-fvar-table.hh"
+#include "hb-ot-var-avar-table.hh"
#include "hb-ot-stat-table.hh"
#include "hb-ot-math-table.hh"
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
-typedef hb_hashmap_t<unsigned, hb_set_t *> script_langsys_map;
+typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
#ifndef HB_NO_SUBSET_CFF
static inline void
_add_cff_seac_components (const OT::cff1::accelerator_t &cff,
@@ -89,100 +92,171 @@ _remap_indexes (const hb_set_t *indexes,
typedef void (*layout_collect_func_t) (hb_face_t *face, hb_tag_t table_tag, const hb_tag_t *scripts, const hb_tag_t *languages, const hb_tag_t *features, hb_set_t *lookup_indexes /* OUT */);
-template <typename T>
-static void _collect_layout_indices (hb_face_t *face,
- const T& table,
- const hb_set_t *layout_features_to_retain,
- layout_collect_func_t layout_collect_func,
- hb_set_t *indices /* OUT */)
+/*
+ * Removes all tags from 'tags' that are not in filter. Additionally eliminates any duplicates.
+ * Returns true if anything was removed (not including duplicates).
+ */
+static bool _filter_tag_list(hb_vector_t<hb_tag_t>* tags, /* IN/OUT */
+ const hb_set_t* filter)
{
- hb_vector_t<hb_tag_t> features;
- if (!features.alloc (table.get_feature_count () + 1))
- return;
+ hb_vector_t<hb_tag_t> out;
+ out.alloc (tags->get_size() + 1); // +1 is to allocate room for the null terminator.
+
+ bool removed = false;
+ hb_set_t visited;
- hb_set_t visited_features;
- bool retain_all_features = true;
- for (unsigned i = 0; i < table.get_feature_count (); i++)
+ for (hb_tag_t tag : *tags)
{
- hb_tag_t tag = table.get_feature_tag (i);
if (!tag) continue;
- if (!layout_features_to_retain->has (tag))
+ if (visited.has (tag)) continue;
+
+ if (!filter->has (tag))
{
- retain_all_features = false;
+ removed = true;
continue;
}
-
- if (visited_features.has (tag))
- continue;
- features.push (tag);
- visited_features.add (tag);
+ visited.add (tag);
+ out.push (tag);
}
- if (!features)
- return;
-
// The collect function needs a null element to signal end of the array.
- features.push (0);
+ out.push (HB_TAG_NONE);
- if (retain_all_features)
- {
- // Looking for all features, trigger the faster collection method.
- layout_collect_func (face,
- T::tableTag,
- nullptr,
- nullptr,
- nullptr,
- indices);
+ hb_swap (out, *tags);
+ return removed;
+}
+
+template <typename T>
+static void _collect_layout_indices (hb_subset_plan_t *plan,
+ const T& table,
+ layout_collect_func_t layout_collect_func,
+ hb_set_t *indices /* OUT */)
+{
+ unsigned num_features = table.get_feature_count ();
+ hb_vector_t<hb_tag_t> features;
+ if (!plan->check_success (features.resize (num_features))) return;
+ table.get_feature_tags (0, &num_features, features.arrayZ);
+ bool retain_all_features = !_filter_tag_list (&features, plan->layout_features);
+
+ unsigned num_scripts = table.get_script_count ();
+ hb_vector_t<hb_tag_t> scripts;
+ if (!plan->check_success (scripts.resize (num_scripts))) return;
+ table.get_script_tags (0, &num_scripts, scripts.arrayZ);
+ bool retain_all_scripts = !_filter_tag_list (&scripts, plan->layout_scripts);
+
+ if (!plan->check_success (!features.in_error ()) || !features
+ || !plan->check_success (!scripts.in_error ()) || !scripts)
return;
- }
- layout_collect_func (face,
+ layout_collect_func (plan->source,
T::tableTag,
+ retain_all_scripts ? nullptr : scripts.arrayZ,
nullptr,
- nullptr,
- features.arrayZ,
+ retain_all_features ? nullptr : features.arrayZ,
indices);
}
+
+static inline void
+_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
+ const hb_map_t *lookup_indices,
+ const hb_set_t *feature_indices,
+ hb_map_t *duplicate_feature_map /* OUT */)
+{
+ if (feature_indices->is_empty ()) return;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_set_t>> unique_features;
+ //find out duplicate features after subset
+ for (unsigned i : feature_indices->iter ())
+ {
+ hb_tag_t t = g.get_feature_tag (i);
+ if (t == HB_MAP_VALUE_INVALID) continue;
+ if (!unique_features.has (t))
+ {
+ if (unlikely (!unique_features.set (t, hb::unique_ptr<hb_set_t> {hb_set_create ()})))
+ return;
+ if (unique_features.has (t))
+ unique_features.get (t)->add (i);
+ duplicate_feature_map->set (i, i);
+ continue;
+ }
+
+ bool found = false;
+
+ hb_set_t* same_tag_features = unique_features.get (t);
+ for (unsigned other_f_index : same_tag_features->iter ())
+ {
+ const OT::Feature& f = g.get_feature (i);
+ const OT::Feature& other_f = g.get_feature (other_f_index);
+
+ auto f_iter =
+ + hb_iter (f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
+
+ auto other_f_iter =
+ + hb_iter (other_f.lookupIndex)
+ | hb_filter (lookup_indices)
+ ;
+
+ bool is_equal = true;
+ for (; f_iter && other_f_iter; f_iter++, other_f_iter++)
+ {
+ unsigned a = *f_iter;
+ unsigned b = *other_f_iter;
+ if (a != b) { is_equal = false; break; }
+ }
+
+ if (is_equal == false || f_iter || other_f_iter) continue;
+
+ found = true;
+ duplicate_feature_map->set (i, other_f_index);
+ break;
+ }
+
+ if (found == false)
+ {
+ same_tag_features->add (i);
+ duplicate_feature_map->set (i, i);
+ }
+ }
+}
+
template <typename T>
static inline void
-_closure_glyphs_lookups_features (hb_face_t *face,
+_closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_set_t *gids_to_retain,
- const hb_set_t *layout_features_to_retain,
hb_map_t *lookups,
hb_map_t *features,
script_langsys_map *langsys_map)
{
- hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (face);
+ hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag;
hb_set_t lookup_indices;
- _collect_layout_indices<T> (face,
+ _collect_layout_indices<T> (plan,
*table,
- layout_features_to_retain,
hb_ot_layout_collect_lookups,
&lookup_indices);
if (table_tag == HB_OT_TAG_GSUB)
- hb_ot_layout_lookups_substitute_closure (face,
- &lookup_indices,
+ hb_ot_layout_lookups_substitute_closure (plan->source,
+ &lookup_indices,
gids_to_retain);
- table->closure_lookups (face,
+ table->closure_lookups (plan->source,
gids_to_retain,
- &lookup_indices);
+ &lookup_indices);
_remap_indexes (&lookup_indices, lookups);
// Collect and prune features
hb_set_t feature_indices;
- _collect_layout_indices<T> (face,
+ _collect_layout_indices<T> (plan,
*table,
- layout_features_to_retain,
hb_ot_layout_collect_features,
&feature_indices);
table->prune_features (lookups, &feature_indices);
hb_map_t duplicate_feature_map;
- table->find_duplicate_features (lookups, &feature_indices, &duplicate_feature_map);
+ _GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
feature_indices.clear ();
table->prune_langsys (&duplicate_feature_map, langsys_map, &feature_indices);
@@ -195,14 +269,14 @@ _closure_glyphs_lookups_features (hb_face_t *face,
#ifndef HB_NO_VAR
static inline void
- _collect_layout_variation_indices (hb_face_t *face,
- const hb_set_t *glyphset,
- const hb_map_t *gpos_lookups,
- hb_set_t *layout_variation_indices,
- hb_map_t *layout_variation_idx_map)
+_collect_layout_variation_indices (hb_subset_plan_t* plan,
+ const hb_set_t *glyphset,
+ const hb_map_t *gpos_lookups,
+ hb_set_t *layout_variation_indices,
+ hb_map_t *layout_variation_idx_map)
{
- hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face);
- hb_blob_ptr_t<OT::GPOS> gpos = hb_sanitize_context_t ().reference_table<OT::GPOS> (face);
+ hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
+ hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
if (!gdef->has_data ())
{
@@ -213,7 +287,7 @@ static inline void
OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
gdef->collect_variation_indices (&c);
- if (hb_ot_layout_has_positioning (face))
+ if (hb_ot_layout_has_positioning (plan->source))
gpos->collect_variation_indices (&c);
gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
@@ -240,22 +314,16 @@ static void _colr_closure (hb_face_t *face,
OT::COLR::accelerator_t colr (face);
if (!colr.is_valid ()) return;
- unsigned iteration_count = 0;
hb_set_t palette_indices, layer_indices;
- unsigned glyphs_num;
- {
- glyphs_num = glyphs_colred->get_population ();
- // Collect all glyphs referenced by COLRv0
- hb_set_t glyphset_colrv0;
- for (hb_codepoint_t gid : glyphs_colred->iter ())
- colr.closure_glyphs (gid, &glyphset_colrv0);
-
- glyphs_colred->union_ (glyphset_colrv0);
-
- //closure for COLRv1
- colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
- } while (iteration_count++ <= HB_CLOSURE_MAX_STAGES &&
- glyphs_num != glyphs_colred->get_population ());
+ // Collect all glyphs referenced by COLRv0
+ hb_set_t glyphset_colrv0;
+ for (hb_codepoint_t gid : *glyphs_colred)
+ colr.closure_glyphs (gid, &glyphset_colrv0);
+
+ glyphs_colred->union_ (glyphset_colrv0);
+
+ //closure for COLRv1
+ colr.closure_forV1 (glyphs_colred, &layer_indices, &palette_indices);
colr.closure_V0palette_indices (glyphs_colred, &palette_indices);
_remap_indexes (&layer_indices, layers_map);
@@ -263,10 +331,10 @@ static void _colr_closure (hb_face_t *face,
}
static inline void
-_math_closure (hb_face_t *face,
- hb_set_t *glyphset)
+_math_closure (hb_subset_plan_t *plan,
+ hb_set_t *glyphset)
{
- hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face);
+ hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> ();
if (math->has_data ())
math->closure_glyphs (glyphset);
math.destroy ();
@@ -277,12 +345,7 @@ static inline void
_remove_invalid_gids (hb_set_t *glyphs,
unsigned int num_glyphs)
{
- hb_codepoint_t gid = HB_SET_VALUE_INVALID;
- while (glyphs->next (&gid))
- {
- if (gid >= num_glyphs)
- glyphs->del (gid);
- }
+ glyphs->del_range (num_glyphs, HB_SET_VALUE_INVALID);
}
static void
@@ -292,12 +355,13 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
{
OT::cmap::accelerator_t cmap (plan->source);
- constexpr static const int size_threshold = 4096;
-
+ unsigned size_threshold = plan->source->get_num_glyphs ();
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
{
- /* This is the fast path if it's anticipated that size of unicodes
- * is << than the number of codepoints in the font. */
+ // This is approach to collection is faster, but can only be used if glyphs
+ // are not being explicitly added to the subset and the input unicodes set is
+ // not excessively large (eg. an inverted set).
+ plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
for (hb_codepoint_t cp : *unicodes)
{
hb_codepoint_t gid;
@@ -308,27 +372,32 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
}
}
else
{
+ // This approach is slower, but can handle adding in glyphs to the subset and will match
+ // them with cmap entries.
hb_map_t unicode_glyphid_map;
- cmap.collect_mapping (hb_set_get_empty (), &unicode_glyphid_map);
+ hb_set_t cmap_unicodes;
+ cmap.collect_mapping (&cmap_unicodes, &unicode_glyphid_map);
+ plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
+ + glyphs->get_population (),
+ cmap_unicodes.get_population ()));
- for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
- + unicode_glyphid_map.iter ())
+ for (hb_codepoint_t cp : cmap_unicodes)
{
- if (!unicodes->has (cp_gid.first) && !glyphs->has (cp_gid.second))
- continue;
+ hb_codepoint_t gid = unicode_glyphid_map[cp];
+ if (!unicodes->has (cp) && !glyphs->has (gid))
+ continue;
- plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
+ plan->codepoint_to_glyph->set (cp, gid);
+ plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
}
/* Add gids which where requested, but not mapped in cmap */
- // TODO(garretrieger):
- // Once https://github.com/harfbuzz/harfbuzz/issues/3169
- // is implemented, this can be done with union and del_range
- for (hb_codepoint_t gid : glyphs->iter ())
+ for (hb_codepoint_t gid : *glyphs)
{
if (gid >= plan->source->get_num_glyphs ())
break;
@@ -336,8 +405,41 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
}
}
- + plan->codepoint_to_glyph->keys () | hb_sink (plan->unicodes);
- + plan->codepoint_to_glyph->values () | hb_sink (plan->_glyphset_gsub);
+ auto &arr = plan->unicode_to_new_gid_list;
+ if (arr.length)
+ {
+ plan->unicodes->add_sorted_array (&arr.arrayZ->first, arr.length, sizeof (*arr.arrayZ));
+ plan->_glyphset_gsub->add_array (&arr.arrayZ->second, arr.length, sizeof (*arr.arrayZ));
+ }
+}
+
+#ifndef HB_COMPOSITE_OPERATIONS_PER_GLYPH
+#define HB_COMPOSITE_OPERATIONS_PER_GLYPH 64
+#endif
+
+static unsigned
+_glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
+ hb_codepoint_t gid,
+ hb_set_t *gids_to_retain,
+ int operation_count,
+ unsigned depth = 0)
+{
+ if (unlikely (depth++ > HB_MAX_NESTING_LEVEL)) return operation_count;
+ if (unlikely (--operation_count < 0)) return operation_count;
+ /* Check if is already visited */
+ if (gids_to_retain->has (gid)) return operation_count;
+
+ gids_to_retain->add (gid);
+
+ for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
+ operation_count =
+ _glyf_add_gid_and_children (glyf,
+ item.get_gid (),
+ gids_to_retain,
+ operation_count,
+ depth);
+
+ return operation_count;
}
static void
@@ -346,7 +448,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
bool close_over_gpos,
bool close_over_gdef)
{
- OT::glyf::accelerator_t glyf (plan->source);
+ OT::glyf_accelerator_t glyf (plan->source);
#ifndef HB_NO_SUBSET_CFF
OT::cff1::accelerator_t cff (plan->source);
#endif
@@ -358,19 +460,17 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_SUBSET_LAYOUT
if (close_over_gsub)
// closure all glyphs/lookups/features needed for GSUB substitutions.
- _closure_glyphs_lookups_features<OT::GSUB> (
- plan->source,
+ _closure_glyphs_lookups_features<GSUB> (
+ plan,
plan->_glyphset_gsub,
- plan->layout_features,
plan->gsub_lookups,
plan->gsub_features,
plan->gsub_langsys);
if (close_over_gpos)
- _closure_glyphs_lookups_features<OT::GPOS> (
- plan->source,
+ _closure_glyphs_lookups_features<GPOS> (
+ plan,
plan->_glyphset_gsub,
- plan->layout_features,
plan->gpos_lookups,
plan->gpos_features,
plan->gpos_langsys);
@@ -378,7 +478,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
- _math_closure (plan->source, plan->_glyphset_mathed);
+ _math_closure (plan, plan->_glyphset_mathed);
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
hb_set_t cur_glyphset = *plan->_glyphset_mathed;
@@ -386,23 +486,27 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
hb_set_set (plan->_glyphset_colred, &cur_glyphset);
- // Populate a full set of glyphs to retain by adding all referenced
- // composite glyphs.
- for (hb_codepoint_t gid : cur_glyphset.iter ())
- {
- glyf.add_gid_and_children (gid, plan->_glyphset);
+
+ /* Populate a full set of glyphs to retain by adding all referenced
+ * composite glyphs. */
+ if (glyf.has_data ())
+ for (hb_codepoint_t gid : cur_glyphset)
+ _glyf_add_gid_and_children (glyf, gid, plan->_glyphset,
+ cur_glyphset.get_population () * HB_COMPOSITE_OPERATIONS_PER_GLYPH);
+ else
+ plan->_glyphset->union_ (cur_glyphset);
#ifndef HB_NO_SUBSET_CFF
- if (cff.is_valid ())
+ if (cff.is_valid ())
+ for (hb_codepoint_t gid : cur_glyphset)
_add_cff_seac_components (cff, gid, plan->_glyphset);
#endif
- }
_remove_invalid_gids (plan->_glyphset, plan->source->get_num_glyphs ());
#ifndef HB_NO_VAR
if (close_over_gdef)
- _collect_layout_variation_indices (plan->source,
+ _collect_layout_variation_indices (plan,
plan->_glyphset_gsub,
plan->gpos_lookups,
plan->layout_variation_indices,
@@ -411,6 +515,20 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
}
static void
+_create_glyph_map_gsub (const hb_set_t* glyph_set_gsub,
+ const hb_map_t* glyph_map,
+ hb_map_t* out)
+{
+ + hb_iter (glyph_set_gsub)
+ | hb_map ([&] (hb_codepoint_t gid) {
+ return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid,
+ glyph_map->get (gid));
+ })
+ | hb_sink (out)
+ ;
+}
+
+static void
_create_old_gid_to_new_gid_map (const hb_face_t *face,
bool retain_gids,
const hb_set_t *all_gids_to_retain,
@@ -418,13 +536,19 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
hb_map_t *reverse_glyph_map, /* OUT */
unsigned int *num_glyphs /* OUT */)
{
+ unsigned pop = all_gids_to_retain->get_population ();
+ reverse_glyph_map->resize (pop);
+ glyph_map->resize (pop);
+
if (!retain_gids)
{
+ hb_enumerate (hb_iter (all_gids_to_retain), (hb_codepoint_t) 0)
| hb_sink (reverse_glyph_map)
;
*num_glyphs = reverse_glyph_map->get_population ();
- } else {
+ }
+ else
+ {
+ hb_iter (all_gids_to_retain)
| hb_map ([] (hb_codepoint_t _) {
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (_, _);
@@ -432,10 +556,9 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
| hb_sink (reverse_glyph_map)
;
- unsigned max_glyph =
- + hb_iter (all_gids_to_retain)
- | hb_reduce (hb_max, 0u)
- ;
+ hb_codepoint_t max_glyph = HB_SET_VALUE_INVALID;
+ hb_set_previous (all_gids_to_retain, &max_glyph);
+
*num_glyphs = max_glyph + 1;
}
@@ -447,18 +570,64 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
static void
_nameid_closure (hb_face_t *face,
- hb_set_t *nameids)
+ hb_set_t *nameids,
+ bool all_axes_pinned,
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location)
{
#ifndef HB_NO_STYLE
- face->table.STAT->collect_name_ids (nameids);
+ face->table.STAT->collect_name_ids (user_axes_location, nameids);
#endif
#ifndef HB_NO_VAR
- face->table.fvar->collect_name_ids (nameids);
+ if (!all_axes_pinned)
+ face->table.fvar->collect_name_ids (user_axes_location, nameids);
#endif
}
+#ifndef HB_NO_VAR
+static void
+_normalize_axes_location (hb_face_t *face,
+ const hb_hashmap_t<hb_tag_t, float> *user_axes_location,
+ hb_hashmap_t<hb_tag_t, int> *normalized_axes_location, /* OUT */
+ bool &all_axes_pinned)
+{
+ if (user_axes_location->is_empty ())
+ return;
+
+ hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
+
+ bool has_avar = face->table.avar->has_data ();
+ const OT::SegmentMaps *seg_maps = nullptr;
+ if (has_avar)
+ seg_maps = face->table.avar->get_segment_maps ();
+
+ bool axis_not_pinned = false;
+ unsigned axis_count = 0;
+ for (const auto& axis : axes)
+ {
+ hb_tag_t axis_tag = axis.get_axis_tag ();
+ if (!user_axes_location->has (axis_tag))
+ {
+ axis_not_pinned = true;
+ }
+ else
+ {
+ int normalized_v = axis.normalize_axis_value (user_axes_location->get (axis_tag));
+ if (has_avar && axis_count < face->table.avar->get_axis_count ())
+ {
+ normalized_v = seg_maps->map (normalized_v);
+ }
+ normalized_axes_location->set (axis_tag, normalized_v);
+ }
+ if (has_avar)
+ seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
+
+ axis_count++;
+ }
+ all_axes_pinned = !axis_not_pinned;
+}
+#endif
/**
- * hb_subset_plan_create:
+ * hb_subset_plan_create_or_fail:
* @face: font face to create the plan for.
* @input: a #hb_subset_input_t input.
*
@@ -467,25 +636,29 @@ _nameid_closure (hb_face_t *face,
* which tables and glyphs should be retained.
*
* Return value: (transfer full): New subset plan. Destroy with
- * hb_subset_plan_destroy().
+ * hb_subset_plan_destroy(). If there is a failure creating the plan
+ * nullptr will be returned.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input)
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input)
{
hb_subset_plan_t *plan;
if (unlikely (!(plan = hb_object_create<hb_subset_plan_t> ())))
- return const_cast<hb_subset_plan_t *> (&Null (hb_subset_plan_t));
+ return nullptr;
plan->successful = true;
plan->flags = input->flags;
plan->unicodes = hb_set_create ();
+
+ plan->unicode_to_new_gid_list.init ();
+
plan->name_ids = hb_set_copy (input->sets.name_ids);
- _nameid_closure (face, plan->name_ids);
plan->name_languages = hb_set_copy (input->sets.name_languages);
plan->layout_features = hb_set_copy (input->sets.layout_features);
+ plan->layout_scripts = hb_set_copy (input->sets.layout_scripts);
plan->glyphs_requested = hb_set_copy (input->sets.glyphs);
plan->drop_tables = hb_set_copy (input->sets.drop_tables);
plan->no_subset_tables = hb_set_copy (input->sets.no_subset_tables);
@@ -499,13 +672,12 @@ hb_subset_plan_create (hb_face_t *face,
plan->codepoint_to_glyph = hb_map_create ();
plan->glyph_map = hb_map_create ();
plan->reverse_glyph_map = hb_map_create ();
+ plan->glyph_map_gsub = hb_map_create ();
plan->gsub_lookups = hb_map_create ();
plan->gpos_lookups = hb_map_create ();
- if (plan->check_success (plan->gsub_langsys = hb_object_create<script_langsys_map> ()))
- plan->gsub_langsys->init_shallow ();
- if (plan->check_success (plan->gpos_langsys = hb_object_create<script_langsys_map> ()))
- plan->gpos_langsys->init_shallow ();
+ plan->check_success (plan->gsub_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
+ plan->check_success (plan->gpos_langsys = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
plan->gsub_features = hb_map_create ();
plan->gpos_features = hb_map_create ();
@@ -514,8 +686,16 @@ hb_subset_plan_create (hb_face_t *face,
plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create ();
- if (plan->in_error ()) {
- return plan;
+ plan->check_success (plan->sanitized_table_cache = hb_hashmap_create<hb_tag_t, hb::unique_ptr<hb_blob_t>> ());
+ plan->check_success (plan->axes_location = hb_hashmap_create<hb_tag_t, int> ());
+ plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
+ if (plan->user_axes_location && input->axes_location)
+ *plan->user_axes_location = *input->axes_location;
+ plan->all_axes_pinned = false;
+
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
}
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
@@ -532,6 +712,31 @@ hb_subset_plan_create (hb_face_t *face,
plan->reverse_glyph_map,
&plan->_num_output_glyphs);
+ _create_glyph_map_gsub (
+ plan->_glyphset_gsub,
+ plan->glyph_map,
+ plan->glyph_map_gsub);
+
+ // Now that we have old to new gid map update the unicode to new gid list.
+ for (unsigned i = 0; i < plan->unicode_to_new_gid_list.length; i++)
+ {
+ // Use raw array access for performance.
+ plan->unicode_to_new_gid_list.arrayZ[i].second =
+ plan->glyph_map->get(plan->unicode_to_new_gid_list.arrayZ[i].second);
+ }
+
+#ifndef HB_NO_VAR
+ _normalize_axes_location (face,
+ input->axes_location,
+ plan->axes_location,
+ plan->all_axes_pinned);
+#endif
+
+ _nameid_closure (face, plan->name_ids, plan->all_axes_pinned, plan->user_axes_location);
+ if (unlikely (plan->in_error ())) {
+ hb_subset_plan_destroy (plan);
+ return nullptr;
+ }
return plan;
}
@@ -542,7 +747,7 @@ hb_subset_plan_create (hb_face_t *face,
* Decreases the reference count on @plan, and if it reaches zero, destroys
* @plan, freeing all memory.
*
- * Since: 1.7.5
+ * Since: 4.0.0
**/
void
hb_subset_plan_destroy (hb_subset_plan_t *plan)
@@ -553,6 +758,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_set_destroy (plan->name_ids);
hb_set_destroy (plan->name_languages);
hb_set_destroy (plan->layout_features);
+ hb_set_destroy (plan->layout_scripts);
hb_set_destroy (plan->glyphs_requested);
hb_set_destroy (plan->drop_tables);
hb_set_destroy (plan->no_subset_tables);
@@ -561,6 +767,7 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_map_destroy (plan->codepoint_to_glyph);
hb_map_destroy (plan->glyph_map);
hb_map_destroy (plan->reverse_glyph_map);
+ hb_map_destroy (plan->glyph_map_gsub);
hb_set_destroy (plan->_glyphset);
hb_set_destroy (plan->_glyphset_gsub);
hb_set_destroy (plan->_glyphset_mathed);
@@ -574,25 +781,129 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_set_destroy (plan->layout_variation_indices);
hb_map_destroy (plan->layout_variation_idx_map);
- if (plan->gsub_langsys)
- {
- for (auto _ : plan->gsub_langsys->iter ())
- hb_set_destroy (_.second);
-
- hb_object_destroy (plan->gsub_langsys);
- plan->gsub_langsys->fini_shallow ();
- hb_free (plan->gsub_langsys);
- }
+ hb_hashmap_destroy (plan->gsub_langsys);
+ hb_hashmap_destroy (plan->gpos_langsys);
+ hb_hashmap_destroy (plan->axes_location);
+ hb_hashmap_destroy (plan->sanitized_table_cache);
- if (plan->gpos_langsys)
+ if (plan->user_axes_location)
{
- for (auto _ : plan->gpos_langsys->iter ())
- hb_set_destroy (_.second);
-
- hb_object_destroy (plan->gpos_langsys);
- plan->gpos_langsys->fini_shallow ();
- hb_free (plan->gpos_langsys);
+ hb_object_destroy (plan->user_axes_location);
+ hb_free (plan->user_axes_location);
}
hb_free (plan);
}
+
+/**
+ * hb_subset_plan_old_to_new_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the original font to glyphs in the
+ * subset that will be produced by @plan
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->glyph_map;
+}
+
+/**
+ * hb_subset_plan_new_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between glyphs in the subset that will be produced by
+ * @plan and the glyph in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->reverse_glyph_map;
+}
+
+/**
+ * hb_subset_plan_unicode_to_old_glyph_mapping:
+ * @plan: a subsetting plan.
+ *
+ * Returns the mapping between codepoints in the original font and the
+ * associated glyph id in the original font.
+ *
+ * Return value: (transfer none):
+ * A pointer to the #hb_map_t of the mapping.
+ *
+ * Since: 4.0.0
+ **/
+const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan)
+{
+ return plan->codepoint_to_glyph;
+}
+
+/**
+ * hb_subset_plan_reference: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ *
+ * Increases the reference count on @plan.
+ *
+ * Return value: @plan.
+ *
+ * Since: 4.0.0
+ **/
+hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan)
+{
+ return hb_object_reference (plan);
+}
+
+/**
+ * hb_subset_plan_set_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to set
+ * @data: A pointer to the user data
+ * @destroy: (nullable): A callback to call when @data is not needed anymore
+ * @replace: Whether to replace an existing data with the same key
+ *
+ * Attaches a user-data key/data pair to the given subset plan object.
+ *
+ * Return value: `true` if success, `false` otherwise
+ *
+ * Since: 4.0.0
+ **/
+hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace)
+{
+ return hb_object_set_user_data (plan, key, data, destroy, replace);
+}
+
+/**
+ * hb_subset_plan_get_user_data: (skip)
+ * @plan: a #hb_subset_plan_t object.
+ * @key: The user-data key to query
+ *
+ * Fetches the user data associated with the specified key,
+ * attached to the specified subset plan object.
+ *
+ * Return value: (transfer none): A pointer to the user data
+ *
+ * Since: 4.0.0
+ **/
+void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key)
+{
+ return hb_object_get_user_data (plan, key);
+}
diff --git a/thirdparty/harfbuzz/src/hb-subset-plan.hh b/thirdparty/harfbuzz/src/hb-subset-plan.hh
index b9244e5cb2..8912ae70d5 100644
--- a/thirdparty/harfbuzz/src/hb-subset-plan.hh
+++ b/thirdparty/harfbuzz/src/hb-subset-plan.hh
@@ -44,6 +44,7 @@ struct hb_subset_plan_t
// For each cp that we'd like to retain maps to the corresponding gid.
hb_set_t *unicodes;
+ hb_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> unicode_to_new_gid_list;
// name_ids we would like to retain
hb_set_t *name_ids;
@@ -54,6 +55,9 @@ struct hb_subset_plan_t
//layout features which will be preserved
hb_set_t *layout_features;
+ // layout scripts which will be preserved.
+ hb_set_t *layout_scripts;
+
//glyph ids requested to retain
hb_set_t *glyphs_requested;
@@ -69,6 +73,7 @@ struct hb_subset_plan_t
// Old -> New glyph id mapping
hb_map_t *glyph_map;
hb_map_t *reverse_glyph_map;
+ hb_map_t *glyph_map_gsub;
// Plan is only good for a specific source/dest so keep them with it
hb_face_t *source;
@@ -85,8 +90,8 @@ struct hb_subset_plan_t
hb_map_t *gpos_lookups;
//active langsys we'd like to retain
- hb_hashmap_t<unsigned, hb_set_t *> *gsub_langsys;
- hb_hashmap_t<unsigned, hb_set_t *> *gpos_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_langsys;
+ hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_langsys;
//active features after removing redundant langsys and prune_features
hb_map_t *gsub_features;
@@ -101,8 +106,34 @@ struct hb_subset_plan_t
//Old -> New layout item variation store delta set index mapping
hb_map_t *layout_variation_idx_map;
+ hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
+ //normalized axes location map
+ hb_hashmap_t<hb_tag_t, int> *axes_location;
+ //user specified axes location map
+ hb_hashmap_t<hb_tag_t, float> *user_axes_location;
+ bool all_axes_pinned;
+
public:
+ template<typename T>
+ hb_blob_ptr_t<T> source_table()
+ {
+ if (sanitized_table_cache
+ && !sanitized_table_cache->in_error ()
+ && sanitized_table_cache->has (T::tableTag)) {
+ return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ());
+ }
+
+ hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
+ hb_blob_t* ret = hb_blob_reference (table_blob.get ());
+
+ if (likely (sanitized_table_cache))
+ sanitized_table_cache->set (T::tableTag,
+ std::move (table_blob));
+
+ return ret;
+ }
+
bool in_error () const { return !successful; }
bool check_success(bool success)
@@ -198,13 +229,4 @@ struct hb_subset_plan_t
}
};
-typedef struct hb_subset_plan_t hb_subset_plan_t;
-
-HB_INTERNAL hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t *face,
- const hb_subset_input_t *input);
-
-HB_INTERNAL void
-hb_subset_plan_destroy (hb_subset_plan_t *plan);
-
#endif /* HB_SUBSET_PLAN_HH */
diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.cc b/thirdparty/harfbuzz/src/hb-subset-repacker.cc
new file mode 100644
index 0000000000..55ca48d709
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-subset-repacker.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+#include "hb-repacker.hh"
+
+#ifdef HB_EXPERIMENTAL_API
+
+/**
+ * hb_subset_repack_or_fail:
+ * @table_tag: tag of the table being packed, needed to allow table specific optimizations.
+ * @hb_objects: raw array of struct hb_object_t, which provides
+ * object graph info
+ * @num_hb_objs: number of hb_object_t in the hb_objects array.
+ *
+ * Given the input object graph info, repack a table to eliminate
+ * offset overflows. A nullptr is returned if the repacking attempt fails.
+ * Table specific optimizations (eg. extension promotion in GSUB/GPOS) may be performed.
+ * Passing HB_TAG_NONE will disable table specific optimizations.
+ *
+ * Since: EXPERIMENTAL
+ **/
+hb_blob_t* hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
+ unsigned num_hb_objs)
+{
+ hb_vector_t<const hb_object_t *> packed;
+ packed.alloc (num_hb_objs + 1);
+ packed.push (nullptr);
+ for (unsigned i = 0 ; i < num_hb_objs ; i++)
+ packed.push (&(hb_objects[i]));
+
+ return hb_resolve_overflows (packed,
+ table_tag,
+ 20,
+ true);
+}
+#endif
diff --git a/thirdparty/harfbuzz/src/hb-subset-repacker.h b/thirdparty/harfbuzz/src/hb-subset-repacker.h
new file mode 100644
index 0000000000..245cf60765
--- /dev/null
+++ b/thirdparty/harfbuzz/src/hb-subset-repacker.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright © 2022 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ */
+
+#ifndef HB_SUBSET_REPACKER_H
+#define HB_SUBSET_REPACKER_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#ifdef HB_EXPERIMENTAL_API
+/*
+ * struct hb_link_t
+ * width: offsetSize in bytes
+ * position: position of the offset field in bytes
+ * from beginning of subtable
+ * objidx: index of subtable
+ */
+struct hb_link_t
+{
+ unsigned width;
+ unsigned position;
+ unsigned objidx;
+};
+
+typedef struct hb_link_t hb_link_t;
+
+/*
+ * struct hb_object_t
+ * head: start of object data
+ * tail: end of object data
+ * num_real_links: num of offset field in the object
+ * real_links: pointer to array of offset info
+ * num_virtual_links: num of objects that must be packed
+ * after current object in the final serialized order
+ * virtual_links: array of virtual link info
+ */
+struct hb_object_t
+{
+ char *head;
+ char *tail;
+ unsigned num_real_links;
+ hb_link_t *real_links;
+ unsigned num_virtual_links;
+ hb_link_t *virtual_links;
+};
+
+typedef struct hb_object_t hb_object_t;
+
+HB_EXTERN hb_blob_t*
+hb_subset_repack_or_fail (hb_tag_t table_tag,
+ hb_object_t* hb_objects,
+ unsigned num_hb_objs);
+
+#endif
+
+HB_END_DECLS
+
+#endif /* HB_SUBSET_REPACKER_H */
diff --git a/thirdparty/harfbuzz/src/hb-subset.cc b/thirdparty/harfbuzz/src/hb-subset.cc
index bb46e5b97f..f62e7e895b 100644
--- a/thirdparty/harfbuzz/src/hb-subset.cc
+++ b/thirdparty/harfbuzz/src/hb-subset.cc
@@ -53,8 +53,12 @@
#include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh"
#include "hb-ot-math-table.hh"
+#include "hb-ot-stat-table.hh"
#include "hb-repacker.hh"
+using OT::Layout::GSUB;
+using OT::Layout::GPOS;
+
/**
* SECTION:hb-subset
* @title: hb-subset
@@ -76,13 +80,117 @@
* retain glyph ids option and configure the subset to pass through the layout tables untouched.
*/
+/*
+ * The list of tables in the open type spec. Used to check for tables that may need handling
+ * if we are unable to list the tables in a face.
+ */
+static hb_tag_t known_tables[] {
+ HB_TAG ('a', 'v', 'a', 'r'),
+ HB_OT_TAG_BASE,
+ HB_OT_TAG_CBDT,
+ HB_OT_TAG_CBLC,
+ HB_OT_TAG_cff1,
+ HB_OT_TAG_cff2,
+ HB_OT_TAG_cmap,
+ HB_OT_TAG_COLR,
+ HB_OT_TAG_CPAL,
+ HB_TAG ('c', 'v', 'a', 'r'),
+ HB_TAG ('c', 'v', 't', ' '),
+ HB_TAG ('D', 'S', 'I', 'G'),
+ HB_TAG ('E', 'B', 'D', 'T'),
+ HB_TAG ('E', 'B', 'L', 'C'),
+ HB_TAG ('E', 'B', 'S', 'C'),
+ HB_TAG ('f', 'p', 'g', 'm'),
+ HB_TAG ('f', 'v', 'a', 'r'),
+ HB_TAG ('g', 'a', 's', 'p'),
+ HB_OT_TAG_GDEF,
+ HB_OT_TAG_glyf,
+ HB_OT_TAG_GPOS,
+ HB_OT_TAG_GSUB,
+ HB_OT_TAG_gvar,
+ HB_OT_TAG_hdmx,
+ HB_OT_TAG_head,
+ HB_OT_TAG_hhea,
+ HB_OT_TAG_hmtx,
+ HB_OT_TAG_HVAR,
+ HB_OT_TAG_JSTF,
+ HB_TAG ('k', 'e', 'r', 'n'),
+ HB_OT_TAG_loca,
+ HB_TAG ('L', 'T', 'S', 'H'),
+ HB_OT_TAG_MATH,
+ HB_OT_TAG_maxp,
+ HB_TAG ('M', 'E', 'R', 'G'),
+ HB_TAG ('m', 'e', 't', 'a'),
+ HB_TAG ('M', 'V', 'A', 'R'),
+ HB_TAG ('P', 'C', 'L', 'T'),
+ HB_OT_TAG_post,
+ HB_TAG ('p', 'r', 'e', 'p'),
+ HB_OT_TAG_sbix,
+ HB_TAG ('S', 'T', 'A', 'T'),
+ HB_TAG ('S', 'V', 'G', ' '),
+ HB_TAG ('V', 'D', 'M', 'X'),
+ HB_OT_TAG_vhea,
+ HB_OT_TAG_vmtx,
+ HB_OT_TAG_VORG,
+ HB_OT_TAG_VVAR,
+ HB_OT_TAG_name,
+ HB_OT_TAG_OS2
+};
+
+static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag)
+{
+ hb_blob_t* blob = hb_face_reference_table (face, tag);
+ bool result = (blob == hb_blob_get_empty ());
+ hb_blob_destroy (blob);
+ return result;
+}
+
+static unsigned int
+_get_table_tags (const hb_subset_plan_t* plan,
+ unsigned int start_offset,
+ unsigned int *table_count, /* IN/OUT */
+ hb_tag_t *table_tags /* OUT */)
+{
+ unsigned num_tables = hb_face_get_table_tags (plan->source, 0, nullptr, nullptr);
+ if (num_tables)
+ return hb_face_get_table_tags (plan->source, start_offset, table_count, table_tags);
+
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking each table type we can handle for existence instead.
+ auto it =
+ hb_concat (
+ + hb_array (known_tables)
+ | hb_filter ([&] (hb_tag_t tag) {
+ return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables->has (tag);
+ })
+ | hb_map ([] (hb_tag_t tag) -> hb_tag_t { return tag; }),
+
+ plan->no_subset_tables->iter ()
+ | hb_filter([&] (hb_tag_t tag) {
+ return !_table_is_empty (plan->source, tag);
+ }));
+
+ it += start_offset;
+
+ unsigned num_written = 0;
+ while (bool (it) && num_written < *table_count)
+ table_tags[num_written++] = *it++;
+
+ *table_count = num_written;
+ return num_written;
+}
+
+
static unsigned
-_plan_estimate_subset_table_size (hb_subset_plan_t *plan, unsigned table_len)
+_plan_estimate_subset_table_size (hb_subset_plan_t *plan,
+ unsigned table_len,
+ bool same_size)
{
unsigned src_glyphs = plan->source->get_num_glyphs ();
unsigned dst_glyphs = plan->glyphset ()->get_population ();
- if (unlikely (!src_glyphs))
+ if (unlikely (!src_glyphs) || same_size)
return 512 + table_len;
return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
@@ -121,7 +229,6 @@ static
bool
_try_subset (const TableType *table,
hb_vector_t<char>* buf,
- unsigned buf_size,
hb_subset_context_t* c /* OUT */)
{
c->serializer->start_serialize<TableType> ();
@@ -134,57 +241,66 @@ _try_subset (const TableType *table,
return needed;
}
- buf_size += (buf_size >> 1) + 32;
+ unsigned buf_size = buf->allocated;
+ buf_size = buf_size * 2 + 16;
+
+
+
+
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
- if (unlikely (!buf->alloc (buf_size)))
+ if (unlikely (buf_size > c->source_blob->length * 16 ||
+ !buf->alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.",
HB_UNTAG (c->table_tag), buf_size);
return needed;
}
- c->serializer->reset (buf->arrayZ, buf_size);
- return _try_subset (table, buf, buf_size, c);
+ c->serializer->reset (buf->arrayZ, buf->allocated);
+ return _try_subset (table, buf, c);
}
template<typename TableType>
static bool
-_subset (hb_subset_plan_t *plan)
+_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{
- hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
- const TableType *table = source_blob->as<TableType> ();
+ hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
+ const TableType *table = source_blob.get ();
hb_tag_t tag = TableType::tableTag;
- if (!source_blob->data)
+ if (!source_blob.get_blob()->data)
{
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
- hb_vector_t<char> buf;
- /* TODO Not all tables are glyph-related. 'name' table size for example should not be
- * affected by number of glyphs. Accommodate that. */
- unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
+ /* Tables that we want to allocate same space as the source table. For GSUB/GPOS it's
+ * because those are expensive to subset, so giving them more room is fine. */
+ bool same_size_table = TableType::tableTag == HB_OT_TAG_GSUB ||
+ TableType::tableTag == HB_OT_TAG_GPOS ||
+ TableType::tableTag == HB_OT_TAG_name;
+
+ unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size)))
{
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
return false;
}
bool needed = false;
- hb_serialize_context_t serializer (buf.arrayZ, buf_size);
+ hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{
- hb_subset_context_t c (source_blob, plan, &serializer, tag);
- needed = _try_subset (table, &buf, buf_size, &c);
+ hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
+ needed = _try_subset (table, &buf, &c);
}
- hb_blob_destroy (source_blob);
+ source_blob.destroy ();
if (serializer.in_error () && !serializer.only_offset_overflow ())
{
@@ -217,9 +333,17 @@ _subset (hb_subset_plan_t *plan)
static bool
_is_table_present (hb_face_t *source, hb_tag_t tag)
{
+
+ if (!hb_face_get_table_tags (source, 0, nullptr, nullptr)) {
+ // If face has 0 tables associated with it, assume that it was built from
+ // hb_face_create_tables and thus is unable to list its tables. Fallback to
+ // checking if the blob associated with tag is empty.
+ return !_table_is_empty (source, tag);
+ }
+
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ while (((void) hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
if (table_tags[i] == tag)
@@ -238,6 +362,8 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
switch (tag)
{
case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
+ return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
+
case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
@@ -257,6 +383,14 @@ _should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
return true;
#endif
+ case HB_TAG ('a','v','a','r'):
+ case HB_TAG ('f','v','a','r'):
+ case HB_TAG ('g','v','a','r'):
+ case HB_OT_TAG_HVAR:
+ case HB_OT_TAG_VVAR:
+ case HB_TAG ('M','V','A','R'):
+ return plan->all_axes_pinned;
+
default:
return false;
}
@@ -272,7 +406,9 @@ _passthrough (hb_subset_plan_t *plan, hb_tag_t tag)
}
static bool
-_subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
+_subset_table (hb_subset_plan_t *plan,
+ hb_vector_t<char> &buf,
+ hb_tag_t tag)
{
if (plan->no_subset_tables->has (tag)) {
return _passthrough (plan, tag);
@@ -281,43 +417,48 @@ _subset_table (hb_subset_plan_t *plan, hb_tag_t tag)
DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
switch (tag)
{
- case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan);
- case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan);
- case HB_OT_TAG_name: return _subset<const OT::name> (plan);
+ case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan, buf);
+ case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf);
+ case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf);
case HB_OT_TAG_head:
if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
return true; /* skip head, handled by glyf */
- return _subset<const OT::head> (plan);
+ return _subset<const OT::head> (plan, buf);
case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
- case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan);
+ case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan, buf);
case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
- case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan);
- case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan);
- case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan);
+ case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan, buf);
+ case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan, buf);
+ case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan, buf);
case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
- case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan);
- case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan);
- case HB_OT_TAG_post: return _subset<const OT::post> (plan);
- case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan);
- case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan);
- case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
+ case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan, buf);
+ case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan, buf);
+ case HB_OT_TAG_post: return _subset<const OT::post> (plan, buf);
+ case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan, buf);
+ case HB_OT_TAG_CPAL: return _subset<const OT::CPAL> (plan, buf);
+ case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan, buf);
case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
- case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan);
+ case HB_OT_TAG_MATH: return _subset<const OT::MATH> (plan, buf);
#ifndef HB_NO_SUBSET_CFF
- case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
- case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan);
- case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan);
+ case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan, buf);
+ case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan, buf);
+ case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan, buf);
#endif
#ifndef HB_NO_SUBSET_LAYOUT
- case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
- case HB_OT_TAG_GSUB: return _subset<const OT::GSUB> (plan);
- case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
- case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
- case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
- case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan);
+ case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan, buf);
+ case HB_OT_TAG_GSUB: return _subset<const GSUB> (plan, buf);
+ case HB_OT_TAG_GPOS: return _subset<const GPOS> (plan, buf);
+ case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan, buf);
+ case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
+ case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
#endif
+ case HB_OT_TAG_STAT:
+ /*TODO(qxliu): change the condition as we support more complex
+ * instancing operation*/
+ if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf);
+ else return _passthrough (plan, tag);
default:
if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
@@ -343,9 +484,33 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
{
if (unlikely (!input || !source)) return hb_face_get_empty ();
- hb_subset_plan_t *plan = hb_subset_plan_create (source, input);
- if (unlikely (plan->in_error ())) {
- hb_subset_plan_destroy (plan);
+ hb_subset_plan_t *plan = hb_subset_plan_create_or_fail (source, input);
+ if (unlikely (!plan)) {
+ return nullptr;
+ }
+
+ hb_face_t * result = hb_subset_plan_execute_or_fail (plan);
+ hb_subset_plan_destroy (plan);
+ return result;
+}
+
+
+/**
+ * hb_subset_plan_execute_or_fail:
+ * @plan: a subsetting plan.
+ *
+ * Executes the provided subsetting @plan.
+ *
+ * Return value:
+ * on success returns a reference to generated font subset. If the subsetting operation fails
+ * returns nullptr.
+ *
+ * Since: 4.0.0
+ **/
+hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
+{
+ if (unlikely (!plan || plan->in_error ())) {
return nullptr;
}
@@ -353,22 +518,22 @@ hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input)
bool success = true;
hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
- while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
+ hb_vector_t<char> buf;
+ buf.alloc (4096 - 16);
+
+ while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{
for (unsigned i = 0; i < num_tables; ++i)
{
hb_tag_t tag = table_tags[i];
if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
tags_set.add (tag);
- success = _subset_table (plan, tag);
+ success = _subset_table (plan, buf, tag);
if (unlikely (!success)) goto end;
}
offset += num_tables;
}
-end:
-
- hb_face_t *result = success ? hb_face_reference (plan->dest) : nullptr;
- hb_subset_plan_destroy (plan);
- return result;
+end:
+ return success ? hb_face_reference (plan->dest) : nullptr;
}
diff --git a/thirdparty/harfbuzz/src/hb-subset.h b/thirdparty/harfbuzz/src/hb-subset.h
index 1c65a4da1c..08e52dbd2d 100644
--- a/thirdparty/harfbuzz/src/hb-subset.h
+++ b/thirdparty/harfbuzz/src/hb-subset.h
@@ -40,6 +40,15 @@ HB_BEGIN_DECLS
typedef struct hb_subset_input_t hb_subset_input_t;
/**
+ * hb_subset_plan_t:
+ *
+ * Contains information about how the subset operation will be executed.
+ * Such as mappings from the old glyph ids to the new ones in the subset.
+ */
+
+typedef struct hb_subset_plan_t hb_subset_plan_t;
+
+/**
* hb_subset_flags_t:
* @HB_SUBSET_FLAGS_DEFAULT: all flags at their default value of false.
* @HB_SUBSET_FLAGS_NO_HINTING: If set hinting instructions will be dropped in
@@ -91,6 +100,8 @@ typedef enum { /*< flags >*/
* @HB_SUBSET_SETS_NAME_LANG_ID: the set of name lang ids that will be retained.
* @HB_SUBSET_SETS_LAYOUT_FEATURE_TAG: the set of layout feature tags that will be retained
* in the subset.
+ * @HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG: the set of layout script tags that will be retained
+ * in the subset. Defaults to all tags. Since: 5.0.0
*
* List of sets that can be configured on the subset input.
*
@@ -104,6 +115,7 @@ typedef enum {
HB_SUBSET_SETS_NAME_ID,
HB_SUBSET_SETS_NAME_LANG_ID,
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG,
+ HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG,
} hb_subset_sets_t;
HB_EXTERN hb_subset_input_t *
@@ -124,7 +136,7 @@ hb_subset_input_set_user_data (hb_subset_input_t *input,
HB_EXTERN void *
hb_subset_input_get_user_data (const hb_subset_input_t *input,
- hb_user_data_key_t *key);
+ hb_user_data_key_t *key);
HB_EXTERN hb_set_t *
hb_subset_input_unicode_set (hb_subset_input_t *input);
@@ -142,9 +154,59 @@ HB_EXTERN void
hb_subset_input_set_flags (hb_subset_input_t *input,
unsigned value);
+#ifdef HB_EXPERIMENTAL_API
+#ifndef HB_NO_VAR
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag);
+
+HB_EXTERN hb_bool_t
+hb_subset_input_pin_axis_location (hb_subset_input_t *input,
+ hb_face_t *face,
+ hb_tag_t axis_tag,
+ float axis_value);
+#endif
+#endif
+
HB_EXTERN hb_face_t *
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
+HB_EXTERN hb_face_t *
+hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_create_or_fail (hb_face_t *face,
+ const hb_subset_input_t *input);
+
+HB_EXTERN void
+hb_subset_plan_destroy (hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_old_to_new_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_new_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+HB_EXTERN const hb_map_t*
+hb_subset_plan_unicode_to_old_glyph_mapping (const hb_subset_plan_t *plan);
+
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_reference (hb_subset_plan_t *plan);
+
+HB_EXTERN hb_bool_t
+hb_subset_plan_set_user_data (hb_subset_plan_t *plan,
+ hb_user_data_key_t *key,
+ void *data,
+ hb_destroy_func_t destroy,
+ hb_bool_t replace);
+
+HB_EXTERN void *
+hb_subset_plan_get_user_data (const hb_subset_plan_t *plan,
+ hb_user_data_key_t *key);
+
+
HB_END_DECLS
#endif /* HB_SUBSET_H */
diff --git a/thirdparty/harfbuzz/src/hb-ucd-table.hh b/thirdparty/harfbuzz/src/hb-ucd-table.hh
index 1a4c89c17f..14734c91ea 100644
--- a/thirdparty/harfbuzz/src/hb-ucd-table.hh
+++ b/thirdparty/harfbuzz/src/hb-ucd-table.hh
@@ -13,7 +13,7 @@
#include "hb.hh"
static const hb_script_t
-_hb_ucd_sc_map[162] =
+_hb_ucd_sc_map[163] =
{
HB_SCRIPT_COMMON, HB_SCRIPT_INHERITED,
HB_SCRIPT_UNKNOWN, HB_SCRIPT_ARABIC,
@@ -96,6 +96,7 @@ _hb_ucd_sc_map[162] =
HB_SCRIPT_YEZIDI, HB_SCRIPT_CYPRO_MINOAN,
HB_SCRIPT_OLD_UYGHUR, HB_SCRIPT_TANGSA,
HB_SCRIPT_TOTO, HB_SCRIPT_VITHKUQI,
+ HB_SCRIPT_MATH,
};
static const uint16_t
_hb_ucd_dm1_p0_map[825] =
@@ -1067,2860 +1068,6 @@ _hb_ucd_dm2_u64_map[388] =
#ifndef HB_OPTIMIZE_SIZE
static const uint8_t
-_hb_ucd_u8[33120] =
-{
- 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, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 28, 26, 29, 30, 31, 32, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 33, 34, 34, 34, 34,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 26, 56, 57, 58, 58, 58, 58, 59, 26, 26, 60, 58, 58, 58, 58, 58,
- 58, 58, 26, 61, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 26, 62, 58, 63, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 64, 26, 26, 65, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 66, 67, 68, 58, 58, 58, 58, 69, 58,
- 58, 58, 58, 58, 58, 58, 58, 70, 71, 72, 73, 74, 75, 76, 58, 77,
- 78, 79, 58, 80, 81, 58, 82, 83, 84, 85, 75, 86, 87, 88, 58, 58,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 89, 26, 26, 26, 26, 26, 26, 26, 90, 91, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 92, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 93, 58, 58, 58, 58, 58, 58, 26, 94, 58, 58,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 95, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 96, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 97,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 98,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 29, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 25, 25, 25, 21,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 21, 18, 24, 16,
- 24, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 0,
- 29, 21, 23, 23, 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24,
- 26, 25, 15, 15, 24, 5, 21, 21, 24, 15, 7, 19, 15, 15, 15, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 25, 9, 9, 9, 9, 9, 9, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 9, 5, 5,
- 5, 9, 9, 5, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 9, 9,
- 9, 9, 5, 9, 9, 5, 9, 9, 9, 5, 5, 5, 9, 9, 5, 9,
- 9, 5, 9, 5, 9, 5, 9, 9, 5, 9, 5, 5, 9, 5, 9, 9,
- 5, 9, 9, 9, 5, 9, 5, 9, 9, 5, 5, 7, 9, 5, 5, 5,
- 7, 7, 7, 7, 9, 8, 5, 9, 8, 5, 9, 8, 5, 9, 5, 9,
- 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5, 9, 5,
- 5, 9, 8, 5, 9, 5, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 9, 9, 5, 9, 9, 5,
- 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 7, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 6, 6, 6, 6, 6, 24, 24, 24, 24, 24, 24, 24, 6, 24, 6, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 9, 5, 9, 5, 6, 24, 9, 5, 2, 2, 6, 5, 5, 5, 21, 9,
- 2, 2, 2, 2, 24, 24, 9, 21, 9, 9, 9, 2, 9, 2, 9, 9,
- 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9,
- 5, 5, 9, 9, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 5, 5, 9, 5, 25, 9, 5, 9, 9, 5, 5, 9, 9, 9,
- 9, 5, 26, 12, 12, 12, 12, 12, 11, 11, 9, 5, 9, 5, 9, 5,
- 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 5,
- 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 2, 2, 6, 21, 21, 21, 21, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 17, 2, 2, 26, 26, 23,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 17, 12,
- 21, 12, 12, 21, 12, 12, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 7, 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 25, 25, 25, 21, 21, 23, 21, 21, 26, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 1, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 7, 7,
- 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 21, 7, 12, 12, 12, 12, 12, 12, 12, 1, 26, 12,
- 12, 12, 12, 12, 12, 6, 6, 12, 12, 26, 12, 12, 12, 12, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 26, 26, 7,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 1,
- 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 6, 26, 21, 21, 21, 6, 2, 2, 12, 23, 23,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 6, 12, 12, 12, 6, 12, 12, 12, 12, 12, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 2, 2, 21, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 24, 7, 7, 7, 7, 7, 7, 2,
- 1, 1, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12,
- 12, 12, 1, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10, 10, 12, 10, 10,
- 7, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 12, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 2, 2, 2, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 7, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 7, 7, 12, 12, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 23, 23, 15, 15, 15, 15, 15, 15, 26, 23, 7, 21, 12, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 2, 7, 7, 2, 2, 12, 2, 10, 10,
- 10, 12, 12, 2, 2, 2, 2, 12, 12, 2, 2, 12, 12, 12, 2, 2,
- 2, 12, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7, 7, 2, 7, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 7, 7, 7, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 12, 12, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 12, 2, 12, 12, 10, 2, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 23, 2, 2, 2, 2, 2, 2, 2, 7, 12, 12, 12, 12, 12, 12,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 12, 12, 12, 12, 2, 2, 10, 10, 2, 2, 10, 10, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 10, 2, 2, 2, 2, 7, 7, 2, 7,
- 26, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 12, 7, 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 2, 2, 2, 7, 7, 2, 7, 2, 7, 7,
- 2, 2, 2, 7, 7, 2, 2, 2, 7, 7, 7, 2, 2, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 10, 10,
- 12, 10, 10, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 12, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 26, 26, 26, 26, 26, 26, 23, 26, 2, 2, 2, 2, 2,
- 12, 10, 10, 10, 12, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 7, 12, 12,
- 12, 10, 10, 10, 10, 2, 12, 12, 12, 2, 12, 12, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 12, 12, 2, 7, 7, 7, 2, 2, 7, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 21, 15, 15, 15, 15, 15, 15, 15, 26,
- 7, 12, 10, 10, 21, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 2, 12, 7, 10, 12,
- 10, 10, 10, 10, 10, 2, 12, 10, 10, 2, 10, 10, 12, 12, 2, 2,
- 2, 2, 2, 2, 2, 10, 10, 2, 2, 2, 2, 2, 2, 7, 7, 2,
- 2, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 7, 10, 10,
- 10, 12, 12, 12, 12, 2, 10, 10, 10, 2, 10, 10, 10, 12, 7, 26,
- 2, 2, 2, 2, 7, 7, 7, 10, 15, 15, 15, 15, 15, 15, 15, 7,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 7, 7, 7, 7, 7, 7,
- 2, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 12, 2, 2, 2, 2, 10,
- 10, 10, 12, 12, 12, 2, 12, 2, 10, 10, 10, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 6, 12, 12, 12, 12, 12, 12, 12, 12, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 12, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 6, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 7, 7, 7, 7,
- 7, 26, 26, 26, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 26, 21, 26, 26, 26, 12, 12, 26, 26, 26, 26, 26, 26,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 12, 26, 12, 26, 12, 22, 18, 22, 18, 10, 10,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 12, 12, 12, 12, 12, 21, 12, 12, 7, 7, 7, 7, 7, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 2, 26, 26,
- 21, 21, 21, 21, 21, 26, 26, 26, 26, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 10, 12, 12, 10, 10, 12, 12, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 10, 10, 12, 12, 7, 7, 7, 7, 12, 12,
- 12, 7, 10, 10, 10, 7, 7, 10, 10, 10, 10, 10, 10, 10, 7, 7,
- 7, 12, 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 12, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 12, 7, 10,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 10, 10, 10, 12, 26, 26,
- 9, 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 2, 2, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 21, 6, 5, 5, 5,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 7, 2, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 2, 2, 5, 5, 5, 5, 5, 5, 2, 2,
- 17, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 26, 21, 7,
- 29, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 22, 18, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 21, 21, 14, 14,
- 14, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 12, 12, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7,
- 7, 2, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 12, 12, 10, 12, 12, 12, 12, 12, 12, 12, 10, 10,
- 10, 10, 10, 10, 10, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 21, 21, 21, 6, 21, 21, 21, 23, 7, 12, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 17, 21, 21, 21, 21, 12, 12, 12, 1, 12,
- 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 7, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2,
- 12, 12, 12, 10, 10, 10, 10, 12, 12, 10, 10, 10, 2, 2, 2, 2,
- 10, 10, 12, 10, 10, 10, 10, 10, 10, 12, 12, 12, 2, 2, 2, 2,
- 26, 2, 2, 2, 21, 21, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2,
- 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 2, 2, 2, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 10, 10, 12, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 10, 12, 10, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 10, 12, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 10,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12,
- 21, 21, 21, 21, 21, 21, 21, 6, 21, 21, 21, 21, 21, 21, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2,
- 12, 12, 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 12, 10, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10,
- 10, 10, 12, 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2,
- 21, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 21, 21, 2,
- 12, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 12, 12, 12, 7, 7,
- 7, 7, 7, 7, 7, 7, 12, 10, 12, 12, 10, 10, 10, 12, 10, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 12, 12, 12, 12,
- 12, 12, 12, 12, 10, 10, 12, 12, 2, 2, 2, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 12, 7, 7,
- 7, 7, 7, 7, 12, 7, 7, 10, 12, 12, 7, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6,
- 9, 5, 9, 5, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 2, 9, 2, 9, 2, 9, 2, 9,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 8,
- 5, 5, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 5, 24,
- 24, 24, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 24,
- 5, 5, 5, 5, 2, 2, 5, 5, 9, 9, 9, 9, 2, 24, 24, 24,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 24, 24, 24,
- 2, 2, 5, 5, 5, 2, 5, 5, 9, 9, 9, 9, 8, 24, 24, 2,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 1, 1, 1, 1, 1,
- 17, 17, 17, 17, 17, 17, 21, 21, 20, 19, 22, 20, 20, 19, 22, 20,
- 21, 21, 21, 21, 21, 21, 21, 21, 27, 28, 1, 1, 1, 1, 1, 29,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 19, 21, 21, 21, 21, 16,
- 16, 21, 21, 21, 25, 22, 18, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 25, 21, 16, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 29,
- 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 15, 6, 2, 2, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 6,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 25, 25, 25, 22, 18, 2,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
- 11, 12, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 9, 26, 26, 26, 26, 9, 26, 26, 5, 9, 9, 9, 5, 5,
- 9, 9, 9, 5, 26, 9, 26, 26, 25, 9, 9, 9, 9, 9, 26, 26,
- 26, 26, 26, 26, 9, 26, 9, 26, 9, 26, 9, 9, 9, 9, 26, 5,
- 9, 9, 9, 9, 5, 7, 7, 7, 7, 5, 26, 26, 5, 5, 9, 9,
- 25, 25, 25, 25, 25, 9, 5, 5, 5, 5, 26, 25, 26, 26, 5, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 9, 5, 14, 14, 14, 14, 15, 26, 26, 2, 2, 2, 2,
- 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 25, 25, 26, 26, 26, 26,
- 25, 26, 26, 25, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 25, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25,
- 26, 26, 25, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 26, 26, 26, 26,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 22, 18, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25,
- 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15,
- 26, 26, 26, 26, 26, 26, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 25, 25, 25, 25, 25, 25, 25, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 25,
- 26, 26, 26, 26, 26, 26, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 22, 18, 22, 18, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 25, 25, 25, 25, 25, 22, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18,
- 25, 25, 25, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 22, 18, 22, 18, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 22, 18, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 22, 18, 25, 25,
- 25, 25, 25, 25, 25, 26, 26, 25, 25, 25, 25, 25, 25, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 9, 5, 9, 9, 9, 5, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9,
- 9, 5, 9, 5, 5, 9, 5, 5, 5, 5, 5, 5, 6, 6, 9, 9,
- 9, 5, 9, 5, 5, 26, 26, 26, 26, 26, 26, 9, 5, 9, 5, 12,
- 12, 12, 9, 5, 2, 2, 2, 2, 2, 21, 21, 21, 21, 15, 21, 21,
- 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 2, 2, 5, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 6,
- 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 2,
- 21, 21, 20, 19, 20, 19, 21, 21, 21, 20, 19, 21, 20, 19, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 17, 21, 21, 17, 21, 20, 19, 21, 21,
- 20, 19, 22, 18, 22, 18, 22, 18, 22, 18, 21, 21, 21, 21, 21, 6,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 17, 17, 21, 21, 21, 21,
- 17, 21, 22, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 26, 26, 21, 21, 21, 22, 18, 22, 18, 22, 18, 22, 18, 17, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2,
- 29, 21, 21, 21, 26, 6, 7, 14, 22, 18, 22, 18, 22, 18, 22, 18,
- 22, 18, 26, 26, 22, 18, 22, 18, 22, 18, 22, 18, 17, 22, 18, 18,
- 26, 14, 14, 14, 14, 14, 14, 14, 14, 14, 12, 12, 12, 12, 10, 10,
- 17, 6, 6, 6, 6, 6, 26, 26, 14, 14, 14, 6, 7, 21, 26, 26,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 24, 24, 6, 6, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 6, 6, 6, 7,
- 2, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 26, 26, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 15, 15, 15, 15, 15, 15,
- 26, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 2, 2, 2, 2,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 7, 12,
- 11, 11, 11, 21, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 21, 6,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 6, 6, 12, 12,
- 7, 7, 7, 7, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 12, 12, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 24, 24, 24, 24, 24, 24, 24, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 24, 24, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 6, 5, 5, 5, 5, 5, 5, 5, 5, 9, 5, 9, 5, 9, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 6, 24, 24, 9, 5, 9, 5, 7,
- 9, 5, 9, 5, 5, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 9, 9, 9, 9, 5,
- 9, 9, 9, 9, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5, 9, 5,
- 9, 5, 9, 5, 9, 9, 9, 9, 5, 9, 5, 2, 2, 2, 2, 2,
- 9, 5, 2, 5, 2, 5, 9, 5, 9, 5, 2, 2, 2, 2, 2, 2,
- 2, 2, 6, 6, 6, 9, 5, 7, 6, 6, 5, 7, 7, 7, 7, 7,
- 7, 7, 12, 7, 7, 7, 12, 7, 7, 7, 7, 12, 7, 7, 7, 7,
- 7, 7, 7, 10, 10, 12, 12, 10, 26, 26, 26, 26, 12, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 26, 26, 23, 26, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 21, 21,
- 12, 12, 7, 7, 7, 7, 7, 7, 21, 21, 21, 7, 21, 7, 7, 12,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 12, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 10, 10,
- 10, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 6,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 21, 21,
- 7, 7, 7, 7, 7, 12, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 7, 7, 7, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 10,
- 10, 12, 12, 10, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 21, 21, 21, 21,
- 6, 7, 7, 7, 7, 7, 7, 26, 26, 26, 7, 10, 12, 10, 7, 7,
- 12, 7, 12, 12, 12, 7, 7, 12, 12, 7, 7, 7, 7, 7, 12, 12,
- 7, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 6, 21, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 12, 12, 10, 10,
- 21, 21, 7, 6, 6, 10, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7, 2,
- 2, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 24, 6, 6, 6, 6,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 24, 24, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 12, 10, 10, 12, 10, 10, 21, 10, 12, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 5, 5, 5, 5, 5, 2, 2, 2, 2, 2, 7, 12, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 25, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 18, 22,
- 2, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 23, 26, 26, 26,
- 21, 21, 21, 21, 21, 21, 21, 22, 18, 21, 2, 2, 2, 2, 2, 2,
- 21, 17, 17, 16, 16, 22, 18, 22, 18, 22, 18, 22, 18, 22, 18, 22,
- 18, 22, 18, 22, 18, 21, 21, 22, 18, 21, 21, 21, 21, 16, 16, 16,
- 21, 21, 21, 2, 21, 21, 21, 21, 17, 22, 18, 22, 18, 22, 18, 21,
- 21, 21, 25, 17, 25, 25, 25, 2, 21, 23, 21, 21, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 1,
- 2, 21, 21, 21, 23, 21, 21, 21, 22, 18, 21, 25, 21, 17, 21, 21,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 22, 25, 18, 25, 22,
- 18, 21, 22, 18, 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 2, 2, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 2, 2, 2,
- 23, 23, 25, 24, 26, 23, 23, 2, 26, 25, 25, 25, 25, 26, 26, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 26, 26, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7,
- 21, 21, 21, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 14, 14, 14, 14, 14, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 15, 15, 26, 26, 26, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 2, 2,
- 12, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 14, 7, 7, 7, 7, 7, 7, 7, 7, 14, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 21,
- 7, 7, 7, 7, 2, 2, 2, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 21, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 2, 2, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 2, 9, 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 2, 5, 5, 2, 2, 2,
- 6, 6, 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 2, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 2, 2, 7, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 2, 21, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 26, 26, 15, 15, 15, 15, 15, 15, 15,
- 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 15, 15, 7, 7,
- 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 12, 12, 12, 2, 12, 12, 2, 2, 2, 2, 2, 12, 12, 12, 12,
- 7, 7, 7, 7, 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 2, 2, 12, 12, 12, 2, 2, 2, 2, 12,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 21,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 15, 15, 15,
- 7, 7, 7, 7, 7, 7, 7, 7, 26, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 12, 12, 2, 2, 2, 2, 15, 15, 15, 15, 15,
- 21, 21, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 7, 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 21, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15, 15,
- 9, 9, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 15, 15, 15, 15, 15, 15,
- 7, 7, 7, 7, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 12, 12, 17, 2, 2,
- 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 15, 15, 15, 15, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 12, 12, 12, 12, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 15, 15, 15, 15, 15, 15, 15, 2, 2, 2, 2,
- 10, 12, 10, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 15, 15, 15, 15, 15, 15, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 7, 7, 12, 12, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12,
- 10, 10, 10, 12, 12, 12, 12, 10, 10, 12, 12, 21, 21, 1, 21, 21,
- 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2,
- 12, 12, 12, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 10, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 21, 21, 21, 21, 7, 10, 10, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10,
- 10, 7, 7, 7, 7, 21, 21, 21, 21, 12, 12, 12, 12, 21, 10, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 7, 21, 7, 21, 21, 21,
- 2, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 12,
- 12, 12, 10, 10, 12, 10, 12, 12, 21, 21, 21, 21, 21, 21, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 2, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 21, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 10, 10, 2, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7,
- 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 2, 12, 12, 7, 10, 10,
- 12, 10, 10, 10, 10, 2, 2, 10, 10, 2, 2, 10, 10, 10, 2, 2,
- 7, 2, 2, 2, 2, 2, 2, 10, 2, 2, 2, 2, 2, 7, 7, 7,
- 7, 7, 10, 10, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12,
- 10, 10, 12, 12, 12, 10, 12, 7, 7, 7, 7, 21, 21, 21, 21, 21,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 2, 21, 12, 7,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 10, 12, 10, 10, 10, 10, 12,
- 12, 10, 12, 12, 7, 7, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10,
- 10, 10, 12, 12, 12, 12, 2, 2, 10, 10, 10, 10, 12, 12, 10, 12,
- 12, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 7, 7, 7, 7, 12, 12, 2, 2,
- 10, 10, 10, 12, 12, 12, 12, 12, 12, 12, 12, 10, 10, 12, 10, 12,
- 12, 21, 21, 21, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 10, 12, 10, 10,
- 12, 12, 12, 12, 12, 12, 10, 12, 7, 21, 2, 2, 2, 2, 2, 2,
- 10, 10, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 15, 15, 21, 21, 21, 26,
- 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 2, 2, 2, 2,
- 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7,
- 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 2, 2, 7, 7, 7, 7,
- 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7,
- 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 2, 12, 12, 10, 12, 7,
- 10, 7, 10, 12, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 7, 7, 7, 7, 7, 7,
- 7, 10, 10, 10, 12, 12, 12, 12, 2, 2, 12, 12, 10, 10, 10, 10,
- 12, 7, 21, 7, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 7, 7, 7, 7,
- 7, 7, 7, 12, 12, 12, 12, 12, 12, 10, 7, 12, 12, 12, 12, 21,
- 21, 21, 21, 21, 21, 21, 21, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 12, 12, 12, 12, 12, 12, 10, 10, 12, 12, 12, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 21, 21, 21, 7, 21, 21,
- 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 10, 12,
- 7, 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 21, 21, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 2, 10, 12, 12, 12, 12, 12, 12,
- 12, 10, 12, 12, 10, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7,
- 7, 12, 12, 12, 12, 12, 12, 2, 2, 2, 12, 2, 12, 12, 2, 12,
- 12, 12, 12, 12, 12, 12, 7, 12, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 2, 7, 7, 2, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10, 2,
- 12, 12, 2, 10, 10, 12, 10, 12, 7, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 12, 12, 10, 10, 21, 21, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 26, 26, 26, 26, 26, 26, 26, 26, 23, 23, 23,
- 23, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 21,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2,
- 21, 21, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 21, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 21, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 21, 21, 21, 21, 21, 26, 26, 26, 26,
- 6, 6, 6, 6, 21, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 15, 15, 15, 15, 15,
- 15, 15, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 2, 7, 7, 7,
- 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 2, 2, 12,
- 7, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 12,
- 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 21, 6, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 10, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 6, 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, 6, 2, 6, 6, 2,
- 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 7, 7, 7, 7, 2, 2, 2, 2, 2, 2, 2, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 2, 26, 12, 12, 21,
- 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 2, 2, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 10, 10, 12, 12, 12, 26, 26, 26, 10, 10, 10,
- 10, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 12, 12, 12, 12, 12,
- 12, 12, 12, 26, 26, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 12, 12, 12, 12, 26, 26,
- 26, 26, 12, 12, 12, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 5,
- 5, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 2, 9, 9,
- 2, 2, 9, 2, 2, 9, 9, 2, 2, 9, 9, 9, 9, 2, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 2, 5, 2, 5, 5, 5,
- 5, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2, 2, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9, 2, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 2, 9, 9, 9, 9, 2,
- 9, 9, 9, 9, 9, 2, 9, 2, 2, 2, 9, 9, 9, 9, 9, 9,
- 9, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5,
- 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 25,
- 5, 5, 5, 5, 5, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 25,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 25, 5, 5, 5, 5, 5, 5,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 25, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 25, 5, 5, 5, 5, 5, 5, 9, 5, 2, 2, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 12, 12, 12, 12, 12, 12, 12, 26, 26, 26, 26, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 26, 26, 26,
- 26, 26, 26, 26, 26, 12, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 12, 26, 26, 21, 21, 21, 21, 21, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 12, 12, 12, 12, 12, 12, 12, 2, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12,
- 12, 12, 2, 12, 12, 2, 12, 12, 12, 12, 12, 2, 2, 2, 2, 2,
- 12, 12, 12, 12, 12, 12, 12, 6, 6, 6, 6, 6, 6, 6, 2, 2,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 7, 26,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 12, 12, 12, 12,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 23,
- 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 2,
- 7, 7, 7, 7, 7, 2, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 5, 5, 5, 5, 12, 12, 12, 12, 12, 12, 12, 6, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15, 15, 15,
- 23, 15, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2,
- 7, 7, 7, 7, 2, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2, 7, 2, 2, 2, 2,
- 2, 2, 7, 2, 2, 2, 2, 7, 2, 7, 2, 7, 2, 7, 7, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 2, 7, 2, 7, 2, 7, 2, 7,
- 2, 7, 7, 2, 7, 2, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7,
- 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 7, 7, 7, 2, 7, 2,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 2, 7, 7, 7, 2, 7, 7, 7, 7, 7, 2, 7, 7, 7, 7, 7,
- 25, 25, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2,
- 2, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 24, 24, 24, 24, 24,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 2, 2, 2, 2, 2, 2, 2, 2,
- 26, 26, 26, 26, 26, 2, 2, 2, 26, 26, 26, 26, 26, 2, 2, 2,
- 26, 26, 26, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 0, 3, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 12, 12, 13, 14, 12, 15, 16, 17, 18, 19, 20,
- 21, 22, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 24, 25,
- 0, 26, 27, 0, 28, 29, 30, 31, 32, 33, 0, 34, 0, 0, 0, 0,
- 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 37, 38, 0, 0, 0, 0,
- 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0,
- 43, 44, 45, 46, 0, 47, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 50, 0, 0, 0,
- 0, 0, 0, 51, 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 56, 0, 0, 57, 58, 59,
- 60, 61, 62, 63, 64, 65, 66, 0, 67, 68, 0, 69, 70, 71, 72, 0,
- 61, 0, 73, 74, 75, 76, 0, 0, 70, 0, 77, 78, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 79, 80, 0, 0, 0, 0, 0, 0, 0, 0, 81,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 83, 84, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 86, 0, 80, 0, 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 1, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 14, 15, 16, 17, 18, 19, 20, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 21, 0, 0, 0, 0, 0, 22, 23, 24,
- 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27,
- 28, 29, 0, 0, 0, 0, 30, 0, 0, 0, 31, 32, 33, 34, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 13, 35, 36, 0, 0, 26, 37, 38, 39, 0, 0, 0, 0, 0, 40,
- 0, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 42, 43, 1,
- 44, 45, 46, 47, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 50, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 49, 52, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 0, 49, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 56, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 58, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 59, 0, 0, 60, 61, 0, 0, 0, 0,
- 0, 0, 62, 63, 64, 0, 0, 0, 0, 0, 0, 0, 65, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68,
- 0, 0, 0, 0, 0, 0, 69, 0, 0, 0, 70, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 71,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 74, 75, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 68, 77, 0, 0, 0, 0, 0, 0, 78, 79, 80, 81, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 70, 0, 0, 0,
- 0, 82, 83, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0,
- 85, 0, 84, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 87,
- 88, 89, 90, 91, 0, 0, 0, 0, 0, 0, 0, 0, 92, 93, 94, 1,
- 1, 1, 95, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, 98,
- 99,100,101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74, 91, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 0, 0, 0,103, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 74,105,106, 0, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 91, 0,107, 0, 0, 0, 0, 70, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0, 0, 0,
- 1, 1, 91, 0, 0, 0, 0, 0, 0,108, 0, 0, 0, 0,109, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,110, 0, 76, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,111,112,113, 0, 0, 0,
- 0, 0,107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 49, 0, 0, 0, 0, 0,114, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,115,116, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 26,117, 0,118, 0, 0, 0, 0, 0,119, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 120, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,121, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,122,123, 75, 0,
- 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,107, 0, 0, 0,
- 0, 0, 76,102, 0, 0, 0, 0, 0, 0, 0,125, 0, 0, 0, 0,
- 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 53, 0, 0, 0, 0, 0,
- 0, 0,110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,126, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0, 0, 0, 0, 0, 0, 0,129, 0, 49, 0, 0,
- 26,130,130, 0, 0, 0, 0, 0, 0, 0, 0, 0,131, 0, 0, 51,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,132, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102,133, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,134, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,109, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,135,110, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 0,102, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,136, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,137, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,102, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,138, 0, 0, 0, 0, 0, 0, 0,139, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,140, 0, 0, 0, 0,141, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 142,143,144,145,146,147, 0, 0, 0,148, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0,
- 0, 0, 0, 0,139, 1, 1,150,151,117, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0,
- 0,105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,152, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105,153, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230,230,230,230,230,230,230,230,230,232,220,220,220,220,232,216,
- 220,220,220,220,220,202,202,220,220,220,220,202,202,220,220,220,
- 220,220,220,220,220,220,220,220, 1, 1, 1, 1, 1,220,220,220,
- 220,230,230,230,230,230,230,230,230,240,230,220,220,220,230,230,
- 230,220,220, 0,230,230,230,220,220,220,220,230,232,220,220,230,
- 233,234,234,233,234,234,233,230,230,230,230,230, 0, 0, 0,230,
- 230,230,230,230, 0,220,230,230,230,230,220,230,230,230,222,220,
- 230,230,230,230,230,230,220,220,220,220,220,220,230,230,220,230,
- 230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20,
- 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18, 30, 31, 32, 0,
- 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,
- 230,220,220,230,230,230,230,230,220,230,230,220, 35, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,230,230,
- 230, 0, 0,230,230,230,230,220,230, 0, 0,230,230, 0,220,230,
- 230,220, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0,230,220,230,230,
- 220,230,230,220,220,220,230,220,220,230,220,230,230,230,220,230,
- 220,230,220,230,220,230,230, 0, 0, 0, 0, 0,230,230,220,230,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0, 0,230,230, 0,230,
- 230,230,230,230,230,230,230,230, 0,230,230,230, 0,230,230,230,
- 230,230, 0, 0, 0,220,220,220, 0, 0, 0, 0,230,220,220,220,
- 230,230,230,230, 0, 0,230,230,230,230,230,220,220,220,220,220,
- 230,230,230,230,230,230, 0,220,230,230,220,230,230,220,230,230,
- 230,220,220,220, 27, 28, 29,230,230,230,220,230,230,220,220,230,
- 230,230,230,230, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,230, 0, 0, 0, 0, 0, 0, 84, 91, 0, 0, 0, 0, 9,
- 9, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0,103,103, 9, 0,
- 0, 0, 0, 0,107,107,107,107, 0, 0, 0, 0,118,118, 9, 0,
- 0, 0, 0, 0,122,122,122,122, 0, 0, 0, 0,220,220, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,220, 0,216, 0, 0,
- 0, 0, 0, 0, 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,
- 130,130, 0, 0,130, 0,230,230, 9, 0,230,230, 0, 0, 0, 0,
- 0, 0,220, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 9, 9, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,230,230,230, 0, 0, 0, 0,
- 9, 9, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
- 0,230, 0, 0, 0,228, 0, 0, 0, 0, 0, 0, 0,222,230,220,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,230,220, 0, 0, 0,
- 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,230,230,230,230,
- 230, 0, 0,220,230,230,230,230,230,220,220,220,220,220,220,230,
- 230,220, 0,220,220,230,230,220,220,230,230,230,230,230,220,230,
- 230,230,230, 0, 0, 0, 0,230,220,230,230,230,230,230,230,230,
- 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 0,230,230,230, 0, 1,220,220,220,220,220,230,230,
- 220,220,220,220,230, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0,220, 0, 0, 0, 0, 0, 0,230, 0, 0, 0,230,230, 0, 0,
- 0, 0, 0, 0,230,230,220,230,230,230,230,230,230,230,220,230,
- 230,234,214,220,202,230,230,230,230,230,230,230,230,230,230,230,
- 230,230,232,228,228,220,218,230,233,220,230,220,230,230, 1, 1,
- 230,230,230,230, 1, 1, 1,230,230, 0, 0, 0, 0,230, 0, 0,
- 0, 1, 1,230,220,230, 1, 1,220,220,220,220,230, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0,218,228,
- 232,222,224,224, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 230,230,230,230,230,230,230,230,230,230, 0, 0, 0, 0, 0, 0,
- 0, 0, 9, 0, 0, 0, 0,220,220,220, 0, 0, 0, 0, 0, 9,
- 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,230, 0,230,230,
- 220, 0, 0,230,230, 0, 0, 0, 0, 0,230,230, 0,230, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0,230,230,230,230,
- 230,230,230,220,220,220,220,220,220,220,230,230,230,230,230, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,220, 0,230,230, 1,220, 0,
- 0, 0, 0, 9, 0, 0, 0, 0, 0,230,220, 0, 0, 0, 0,230,
- 230, 0, 0, 0, 0, 0, 0, 0, 0, 0,220,220,230,230,230,220,
- 230,220,220,220, 0, 0,230,220,230,220, 0, 0, 0, 9, 7, 0,
- 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 9, 7, 0, 0, 7, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7,
- 7, 0, 0, 0,230,230,230,230,230, 0, 0, 0, 0, 0, 9, 0,
- 0, 0, 7, 0, 0, 0, 9, 7, 0, 0, 0, 0, 7, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 0, 0, 0, 0,
- 0, 9, 9, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
- 9, 9, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,230,230,230,230,
- 230,230,230, 0, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 0, 0, 0, 0,216,216, 1, 1, 1, 0, 0,
- 0,226,216,216,216,216,216, 0, 0, 0, 0, 0, 0, 0, 0,220,
- 220,220,220,220,220,220,220, 0, 0,230,230,230,230,230,220,220,
- 0, 0, 0, 0, 0, 0,230,230,230,230, 0, 0, 0, 0,230,230,
- 230, 0, 0, 0,230, 0, 0,230,230,230,230,230,230,230, 0,230,
- 230, 0,230,230,220,220,220,220,220,220,220, 0,230,230, 7, 0,
- 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
- 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17,237, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
- 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0,
- 0, 0, 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7,
- 20, 20, 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0,
- 20, 20, 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1,
- 28, 29, 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20,
- 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20,
- 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0,
- 0, 40, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 21,
- 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
- 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45,
- 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 0, 0,
- 0, 0, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 17, 19, 20, 21, 22, 23, 24, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 27, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 54, 55, 56, 57, 34, 34, 34, 34, 58, 59, 59, 60, 34,
- 34, 34, 34, 34, 34, 34, 61, 62, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 63, 64, 34, 65, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 67, 66, 68, 69, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 70, 71, 72, 34, 34,
- 34, 34, 73, 34, 34, 34, 34, 34, 34, 34, 34, 74, 75, 76, 77, 78,
- 79, 80, 34, 81, 82, 83, 34, 84, 85, 34, 86, 87, 88, 89, 17, 90,
- 91, 92, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 93, 25, 25, 25, 25, 25, 25, 25, 94,
- 95, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 96, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 97, 34, 34, 34, 34, 34, 34,
- 25, 98, 34, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 99, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34,100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
- 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 2, 2,
- 9, 9, 9, 9, 0, 9, 2, 2, 2, 2, 9, 0, 9, 0, 9, 9,
- 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 2, 2, 4, 4, 4, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2,
- 2, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 2, 2, 2, 2, 14, 14, 14, 14, 14, 14, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
- 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 0, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 0, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 2, 2, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 2, 2, 64, 64, 64, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 2, 2, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
- 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 95, 2, 2, 95, 2, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 1, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 2, 5, 5, 5, 5, 5,
- 5, 5, 5, 2, 2, 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
- 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
- 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2,
- 2, 5, 5, 5, 5, 2, 2, 2, 2, 2, 2, 2, 2, 5, 2, 2,
- 2, 2, 5, 5, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 2, 2, 11, 11, 11, 2, 11, 11, 11, 11, 11,
- 11, 2, 2, 2, 2, 11, 11, 2, 2, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2,
- 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11,
- 2, 2, 11, 2, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2,
- 2, 11, 11, 11, 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11,
- 11, 11, 11, 2, 11, 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 2, 10, 10, 10, 2, 10, 10, 10, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2,
- 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10,
- 2, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
- 2, 10, 10, 10, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10,
- 10, 10, 10, 10, 10, 10, 10, 10, 2, 2, 2, 2, 2, 2, 2, 10,
- 10, 10, 10, 10, 10, 10, 2, 21, 21, 21, 2, 21, 21, 21, 21, 21,
- 21, 21, 21, 2, 2, 21, 21, 2, 2, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
- 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21,
- 2, 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
- 2, 21, 21, 21, 2, 2, 2, 2, 2, 2, 2, 21, 21, 21, 2, 2,
- 2, 2, 21, 21, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22,
- 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
- 22, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 2, 2, 2, 2, 22, 22, 22, 22, 22, 2, 2, 2, 22, 22, 22, 2,
- 22, 22, 22, 22, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2,
- 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
- 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 2,
- 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 2, 23, 23,
- 23, 2, 2, 23, 2, 2, 23, 23, 23, 23, 2, 2, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 2, 16, 16, 16, 2, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16,
- 2, 2, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2,
- 16, 16, 16, 16, 2, 2, 2, 2, 2, 2, 2, 16, 16, 2, 2, 2,
- 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 2, 16, 16, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 20, 20, 20, 2,
- 20, 20, 20, 20, 20, 20, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 2, 36, 36, 36, 2, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 2, 36, 2, 2, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2,
- 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2, 2, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 24, 24, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 18, 18, 2, 18, 2, 18, 18, 18, 18,
- 18, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18,
- 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 2, 2, 2, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25,
- 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2,
- 2, 2, 2, 8, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 0, 8, 8, 8, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 2,
- 30, 30, 30, 30, 2, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 30, 2, 30, 30, 30, 30, 2, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 2, 2, 29, 29,
- 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 34, 2, 2, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 0, 0, 0, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 2,
- 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 45, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
- 46, 46, 46, 2, 46, 46, 46, 2, 46, 46, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 31, 31, 31, 31, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
- 2, 2, 2, 2, 2, 2, 32, 32, 0, 0, 32, 0, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 2,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 2, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, 2, 2, 52, 52, 52, 52, 52, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 58, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 2, 2, 2, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
- 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 91, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 2, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 2, 2, 2, 2, 2, 2,
- 2, 2, 93, 93, 93, 93, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 2, 2,
- 2, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
- 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 6, 6, 6, 6, 6, 6, 6, 6, 6, 2,
- 2, 2, 2, 2, 2, 2, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 2, 2, 8, 8, 8, 76, 76, 76, 76, 76, 76, 76, 76, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
- 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
- 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 9, 9, 9, 9,
- 9, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 6, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 9, 9, 9, 2, 9,
- 2, 9, 2, 9, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 2, 2, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
- 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
- 19, 19, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2, 2, 2, 2, 2, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55,
- 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 2, 2, 2, 2, 2, 55,
- 55, 55, 55, 55, 55, 55, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 2, 2,
- 2, 2, 2, 2, 2, 61, 61, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 61, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 30, 30, 30, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 1, 1, 1, 1, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 13, 13,
- 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1,
- 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 0, 0, 17, 17, 17, 2, 2, 2, 2, 2, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 26, 26, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 2, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0,
- 0, 0, 0, 0, 0, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, 39, 2, 2, 2, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, 86, 86, 86, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0,
- 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 19, 19, 2, 19, 2, 19, 19, 19, 19, 19,
- 2, 2, 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 2, 2,
- 2, 2, 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 2, 2, 2, 2,
- 2, 2, 2, 2, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
- 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
- 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
- 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 74, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, 2, 0, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
- 2, 2, 2, 2, 84, 84, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 68, 68, 68, 68, 2, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
- 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 92, 92, 92, 92, 92, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 30,
- 30, 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 19, 19, 19, 19,
- 0, 0, 2, 2, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 2, 2, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 12, 12, 2, 2, 2,
- 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 13, 13, 13, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 2, 2,
- 2, 2, 2, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 14, 14,
- 14, 14, 14, 2, 14, 2, 14, 14, 2, 14, 14, 2, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 0, 0, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
- 2, 2, 2, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 12, 12, 12, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
- 12, 12, 12, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
- 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0,
- 0, 0, 0, 0, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 49, 49, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 2, 2, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 67, 67, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118,
- 118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,
- 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 2, 2, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,
- 135,135,135,135,135,135,135,135,135,135, 2, 2, 2, 2,135,135,
- 135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,
- 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,106,106,
- 106,106,106,106,106,106,106,106,106,106,106,106,106,106, 2, 2,
- 2, 2, 2, 2, 2, 2,104,104,104,104,104,104,104,104,104,104,
- 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161,
- 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 161,161,161,161,161,161,161,161, 2,161,161,161,161,161,161,161,
- 2,161,161, 2, 2, 2,110,110,110,110,110,110,110,110,110,110,
- 110,110,110,110,110,110,110,110,110,110,110,110,110, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,110,110,110,110,110,110,110,110, 2, 2,
- 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 2, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 2, 2, 2, 2, 2, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 2, 47, 47, 2,
- 2, 2, 47, 2, 2, 47, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81, 81, 81,
- 81, 81, 81, 81, 81, 81,120,120,120,120,120,120,120,120,120,120,
- 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,116,
- 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,116,116,
- 116,116,116,116,116,116,128,128,128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
- 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 98, 98, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 2, 2,
- 2, 2, 97, 97, 97, 97, 2, 2, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2,
- 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2, 2, 57, 57,
- 57, 2, 2, 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 2,
- 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 88,117,117,117,117,117,117,117,117,117,117,
- 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
- 112,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2,112,112,112,112,112,112,112,112,112,112,112,112, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78,
- 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, 2, 2, 83, 83,
- 83, 83, 83, 83, 83, 83, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 2, 2, 2, 2, 2, 82, 82,
- 82, 82, 82, 82, 82, 82,122,122,122,122,122,122,122,122,122,122,
- 122,122,122,122,122,122,122,122, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,122,
- 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89,
- 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
- 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130,
- 130,130,130,130,130,130,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,130,130,130, 2, 2, 2, 2, 2, 2, 2,
- 130,130,130,130,130,130,144,144,144,144,144,144,144,144,144,144,
- 144,144,144,144,144,144,144,144,144,144,144,144,144,144, 2, 2,
- 2, 2, 2, 2, 2, 2,144,144,144,144,144,144,144,144,144,144,
- 2, 2, 2, 2, 2, 2,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,156,
- 2,156,156,156, 2, 2,156,156, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,147,147,
- 147,147,147,147,147,147,147,147,147,147,147,147,147,147, 2, 2,
- 2, 2, 2, 2, 2, 2,148,148,148,148,148,148,148,148,148,148,
- 148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,148,
- 2, 2, 2, 2, 2, 2,158,158,158,158,158,158,158,158,158,158,
- 158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
- 2, 2, 2, 2, 2, 2,153,153,153,153,153,153,153,153,153,153,
- 153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,153,
- 153,153, 2, 2, 2, 2,149,149,149,149,149,149,149,149,149,149,
- 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 2, 2, 2, 2, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 94, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101,101,
- 101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, 2,
- 2, 2, 2, 2, 2, 2,101,101,101,101,101,101,101,101,101,101,
- 2, 2, 2, 2, 2, 2, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 2,
- 2, 2, 2, 2, 2, 2,111,111,111,111,111,111,111,111,111,111,
- 111,111,111,111,111,111,111,111,111,111,111,111,111, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,100,100,100,100,100,100,100,100,100,100,
- 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,108,108,108,108,108,108,108,108,108,108,
- 108,108,108,108,108,108,108,108, 2,108,108,108,108,108,108,108,
- 108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,
- 108,108,108,108,108, 2,129,129,129,129,129,129,129, 2,129, 2,
- 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
- 129,129,129,129, 2,129,129,129,129,129,129,129,129,129,129,129,
- 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
- 109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,
- 109, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
- 2, 2, 2, 2, 2, 2,107,107,107,107, 2,107,107,107,107,107,
- 107,107,107, 2, 2,107,107, 2, 2,107,107,107,107,107,107,107,
- 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2,
- 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107,
- 2, 1,107,107,107,107,107,107,107,107,107, 2, 2,107,107, 2,
- 2,107,107,107, 2, 2,107, 2, 2, 2, 2, 2, 2,107, 2, 2,
- 2, 2, 2,107,107,107,107,107,107,107, 2, 2,107,107,107,107,
- 107,107,107, 2, 2, 2,107,107,107,107,107, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,137,137,137,137,137,137,137,137,137,137,
- 137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,
- 137,137, 2,137,137,137,137,137, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 124,124,124,124,124,124,124,124,124,124,124,124,124,124, 2, 2,
- 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
- 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123, 2, 2,123,123,
- 123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,123,
- 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 114,114,114,114,114,114,114,114,114,114,114, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,114,114,114,114,114,114,114,114,114,114,
- 2, 2, 2, 2, 2, 2, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102,
- 102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,
- 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126,
- 126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126, 2, 2,126,126,126,126,126,126,126,126,126,126,126,126,126,
- 126,126, 2, 2, 2, 2,126,126,126,126,126,126,126, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,142,142,142,142,142,142,142,142,142,142,
- 142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,142,
- 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125,
- 125,125,125,125,125,125,125,125,125, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2,125,154,154,154,154,154,154,154, 2, 2,154,
- 2, 2,154,154,154,154,154,154,154,154, 2,154,154, 2,154,154,
- 154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
- 154,154,154,154,154,154,154,154,154,154,154,154, 2,154,154, 2,
- 2,154,154,154,154,154,154,154,154,154,154,154,154, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,154,154,154,154,154,154,154,154,154,154,
- 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2,
- 150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,
- 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,141,141,141,141,141,141,141,141,141,141,
- 141,141,141,141,141,141,141,141,141,141,141,141,141,141, 2, 2,
- 2, 2, 2, 2, 2, 2,140,140,140,140,140,140,140,140,140,140,
- 140,140,140,140,140,140,140,140,140, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121,121,
- 121,121,121,121,121,121,121,121,121,121,121,121,121,121,121, 2,
- 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2,
- 133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,133,
- 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133,
- 133,133,133,133,133,133,133,133,133,133,133,133, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133,133,
- 133,133,133, 2, 2, 2,134,134,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134,134,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134,134, 2,134,
- 134,134,134,134,134,134,134,134,134,134,134,134,134, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138, 2,138,138,
- 2,138,138,138,138,138,138,138,138,138,138,138,138,138,138,138,
- 138,138,138,138,138,138,138,138,138,138,138,138,138, 2, 2, 2,
- 138, 2,138,138, 2,138,138,138,138,138,138,138,138,138, 2, 2,
- 2, 2, 2, 2, 2, 2,138,138,138,138,138,138,138,138,138,138,
- 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
- 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2,
- 2, 2, 2, 2, 2, 2,143,143,143,143,143,143,143,143,143,143,
- 2, 2, 2, 2, 2, 2,145,145,145,145,145,145,145,145,145,145,
- 145,145,145,145,145,145,145,145,145,145,145,145,145,145,145, 2,
- 2, 2, 2, 2, 2, 2, 86, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 2, 63, 63, 63, 63, 63, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,157,157,157,157,157,157,157,157,157,157,
- 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 80, 80, 80, 80, 80, 2, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2,
- 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127,
- 127,127,127,127,127,127,127,127,127,127,127,127,127, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 79, 79, 79, 79, 79, 79, 79, 79, 79, 2,
- 2, 2, 2, 2, 2, 2,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,115,
- 115,115,115,115,115, 2,115,115,115,115,115,115,115,115,115,115,
- 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,159,
- 159,159,159,159,159, 2,159,159,159,159,159,159,159,159,159,159,
- 2, 2, 2, 2, 2, 2,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,
- 103,103,103,103, 2, 2,103,103,103,103,103,103, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,119,119,119,119,119,119,119,119,119,119,
- 2,119,119,119,119,119,119,119, 2,119,119,119,119,119,119,119,
- 119,119,119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,
- 2, 2, 2,119,119,119,146,146,146,146,146,146,146,146,146,146,
- 146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,
- 146, 2, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 2, 2, 2, 2, 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2,
- 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136,136,
- 136,136,136,136,136,136,136,136,136,136,136,136,136,136, 2, 2,
- 2, 2, 2, 2, 2, 2,155,155,155,155,155,155,155,155,155,155,
- 155,155,155,155,155,155,155,155,155,155,155,155, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,136,136,136,136,136,136,136,136,136, 2,
- 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 17, 17, 17, 17, 17,
- 17, 17, 2, 17, 17, 2, 17, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 15, 15, 15, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 2, 2,
- 2, 2, 2, 2, 2, 2,139,139,139,139,139,139,139,139,139,139,
- 139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,139,
- 139,139, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,
- 105, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 105,105,105, 2, 2, 2,105,105,105,105,105,105,105,105,105, 2,
- 2, 2, 2, 2, 2, 2,105,105,105,105,105,105,105,105,105,105,
- 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 0, 0, 9, 9, 9, 9, 9, 9, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, 2, 0, 0, 2, 2, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
- 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 2, 2, 2,
- 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 0, 0,131,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,
- 131,131, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2,131,131,131,131,131, 2,131,131,131,131,131,131,131,131,131,
- 131,131,131,131,131,131, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 19, 19, 19, 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 2,
- 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56,
- 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,151,
- 151,151,151, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 151,151,151,151, 2, 2,151,151,151,151,151,151,151,151,151,151,
- 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,
- 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152,
- 152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,
- 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
- 30, 30, 2, 30, 30, 2, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 2,113,113,113,113,113,113,113,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113,
- 113,113,113,113,113,113,113,113,113,113,113,113,113, 2, 2, 2,
- 2, 2, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,
- 132,132, 2, 2, 2, 2,132,132,132,132,132,132,132,132,132,132,
- 2, 2, 2, 2,132,132, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
- 2, 3, 2, 3, 2, 3, 2, 3, 3, 2, 3, 2, 2, 3, 3, 3,
- 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
- 3, 3, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 3, 3,
- 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0,
- 0, 0, 0, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 2,
- 2, 2, 2, 2, 2, 2, 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
- 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 0, 0, 1, 2, 3, 4, 5, 6, 0,
- 0, 0, 0, 7, 8, 9, 10, 11, 0, 12, 0, 0, 0, 0, 13, 0,
- 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 15, 16, 0, 17, 18, 19,
- 0, 0, 0, 20, 21, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 0,
- 0, 0, 0, 27, 28, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33,
- 34, 35, 36, 37, 38, 39, 40, 0, 0, 0, 41, 0, 42, 43, 44, 45,
- 46, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 50, 51, 52, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 63, 0, 64, 0, 0, 0, 0, 0,
- 0, 0, 0, 65, 0, 0, 0, 0, 66, 0, 0, 0, 67, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69, 70, 71, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 72, 73, 74, 75, 76, 77, 78, 79, 80, 0,
-};
-static const uint16_t
-_hb_ucd_u16[11584] =
-{
- 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
- 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
- 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31,
- 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39,
- 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13,
- 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50,
- 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58,
- 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66,
- 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32,
- 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
- 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101,
- 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113,
- 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124,
- 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135,
- 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140,
- 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140,
- 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 168, 169, 48, 48, 168, 48, 48, 170, 171, 172, 48, 48,
- 48, 171, 48, 48, 48, 173, 174, 175, 48, 176, 9, 9, 9, 9, 9, 177,
- 178, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183,
- 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193,
- 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199,
- 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209,
- 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
- 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225,
- 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235,
- 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13,
- 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
- 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
- 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 280, 209, 281, 209, 209, 209, 209, 282, 209, 283, 279, 284, 209, 285, 286, 209,
- 209, 209, 287, 140, 288, 140, 271, 271, 271, 289, 209, 209, 209, 209, 290, 271,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 291, 292, 209, 209, 293,
- 209, 209, 209, 209, 209, 209, 294, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 279, 279, 279, 279, 279, 279, 279, 279, 300, 301, 279, 279, 279, 302, 279, 303,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 209, 209, 209, 279, 304, 209, 209, 305, 209, 306, 209, 209, 209, 209, 209, 209,
- 9, 9, 9, 11, 11, 11, 307, 308, 13, 13, 13, 13, 13, 13, 309, 310,
- 11, 11, 311, 48, 48, 48, 312, 313, 48, 314, 315, 315, 315, 315, 32, 32,
- 316, 317, 318, 319, 320, 321, 140, 140, 209, 322, 209, 209, 209, 209, 209, 323,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324, 140, 325,
- 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331,
- 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48,
- 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 209, 209, 209, 209,
- 48, 338, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 151, 209, 209, 209, 287, 48, 48, 229,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 339, 48, 340, 140, 13, 13, 341, 342, 13, 343, 48, 48, 48, 48, 344, 345,
- 31, 346, 347, 348, 13, 13, 13, 349, 350, 351, 352, 353, 354, 355, 140, 356,
- 357, 48, 358, 359, 48, 48, 48, 360, 361, 48, 48, 362, 363, 192, 32, 364,
- 64, 48, 365, 48, 366, 367, 48, 151, 76, 48, 48, 368, 369, 370, 371, 372,
- 48, 48, 373, 374, 375, 376, 48, 377, 48, 48, 48, 378, 379, 380, 381, 382,
- 383, 384, 315, 11, 11, 385, 386, 11, 11, 11, 11, 11, 48, 48, 387, 192,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 388, 48, 389, 48, 48, 206,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390, 390,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140,
- 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403,
- 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410,
- 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419,
- 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71,
- 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
- 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430,
- 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140,
- 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439,
- 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140,
- 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453,
- 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271,
- 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467,
- 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
- 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 271, 476, 48, 48, 477, 478, 140, 140, 140, 140,
- 48, 464, 479, 48, 62, 480, 140, 48, 481, 140, 140, 48, 482, 140, 48, 314,
- 483, 48, 48, 484, 485, 457, 486, 487, 222, 48, 48, 488, 489, 48, 196, 192,
- 490, 48, 491, 492, 493, 48, 48, 494, 222, 48, 48, 495, 496, 497, 498, 499,
- 48, 97, 500, 501, 140, 140, 140, 140, 502, 503, 504, 48, 48, 505, 506, 192,
- 507, 83, 84, 508, 509, 510, 511, 512, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 518, 519, 520, 521, 140, 140,
- 48, 48, 48, 522, 523, 192, 524, 140, 48, 48, 525, 526, 192, 140, 140, 140,
- 48, 173, 527, 528, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
- 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
- 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
- 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 557,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 100, 271, 558, 559, 560,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 207, 140, 140, 140, 140, 140, 140,
- 272, 272, 272, 272, 272, 272, 561, 562, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 388, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
- 48, 48, 200, 564, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 314, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
- 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 440,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 199, 140, 140,
- 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 206,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 324,
- 209, 209, 586, 209, 209, 209, 587, 588, 589, 209, 590, 209, 209, 209, 288, 140,
- 209, 209, 209, 209, 591, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 592,
- 209, 209, 209, 209, 209, 287, 271, 461, 140, 140, 140, 140, 140, 140, 140, 140,
- 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
- 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
- 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
- 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 628, 629, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 630, 631, 632, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 151, 633, 634, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 638, 200,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 639, 585, 140, 140,
- 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 498, 271, 271, 641, 642, 140, 140, 140, 140,
- 498, 271, 643, 644, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
- 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
- 659, 209, 209, 325, 660, 661, 324, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 662,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 663, 426, 426,
- 209, 209, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 660, 325, 427,
- 325, 209, 209, 209, 664, 176, 209, 209, 664, 209, 657, 661, 140, 140, 140, 140,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 323, 657, 665, 287, 209, 426, 288, 324, 176, 664, 287,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 666, 209, 209, 288, 140, 140, 192,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 196, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 100, 140,
- 48, 204, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
- 48, 48, 48, 48, 71, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 667, 140, 668, 668, 668, 668, 668, 668, 140, 140, 140, 140, 140, 140, 140, 140,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 669,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 391, 670,
- 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3, 4, 5, 4, 5,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0,
- 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 12, 11, 11, 11, 13, 11,
- 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 16, 17, 18, 17, 17, 19, 20, 21, 21, 22, 21, 23, 24,
- 25, 26, 27, 27, 28, 29, 27, 30, 27, 27, 27, 27, 27, 31, 27, 27,
- 32, 33, 33, 33, 34, 27, 27, 27, 35, 35, 35, 36, 37, 37, 37, 38,
- 39, 39, 40, 41, 42, 43, 44, 27, 45, 46, 27, 27, 27, 27, 47, 27,
- 48, 48, 48, 48, 48, 49, 50, 48, 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, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 109, 110, 111, 112, 109, 113, 114, 115, 116, 117, 118, 119, 120,
- 121, 122, 122, 123, 122, 124, 125, 125, 126, 127, 128, 129, 130, 131, 125, 125,
- 132, 132, 132, 132, 133, 132, 134, 135, 132, 133, 132, 136, 136, 137, 125, 125,
- 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 139, 139, 140, 139, 139, 141,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 143, 143, 143, 143, 144, 145, 143, 143, 144, 143, 143, 146, 147, 148, 143, 143,
- 143, 147, 143, 143, 143, 149, 143, 150, 143, 151, 152, 152, 152, 152, 152, 153,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 155, 156, 157, 157, 157, 157, 158, 159,
- 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 168, 168, 168, 169, 170, 170,
- 171, 172, 173, 173, 173, 173, 173, 174, 173, 173, 175, 154, 154, 154, 154, 176,
- 177, 178, 179, 179, 180, 181, 182, 183, 184, 184, 185, 184, 186, 187, 168, 168,
- 188, 189, 190, 190, 190, 191, 190, 192, 193, 193, 194, 8, 195, 125, 125, 125,
- 196, 196, 196, 196, 197, 196, 196, 198, 199, 199, 199, 199, 200, 200, 200, 201,
- 202, 202, 202, 203, 204, 205, 205, 205, 206, 139, 139, 207, 208, 209, 210, 211,
- 4, 4, 212, 4, 4, 213, 214, 215, 4, 4, 4, 216, 8, 8, 8, 8,
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
- 11, 217, 11, 11, 217, 218, 11, 219, 11, 11, 11, 220, 220, 221, 11, 222,
- 223, 0, 0, 0, 0, 0, 224, 225, 226, 227, 0, 0, 228, 8, 8, 229,
- 0, 0, 230, 231, 232, 0, 4, 4, 233, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 234, 125, 235, 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 237, 0, 238, 0, 0, 0, 0, 0, 0,
- 239, 239, 239, 239, 239, 239, 4, 4, 240, 240, 240, 240, 240, 240, 240, 241,
- 139, 139, 140, 242, 242, 242, 243, 244, 143, 245, 246, 246, 246, 246, 14, 14,
- 0, 0, 0, 0, 0, 247, 125, 125, 248, 249, 248, 248, 248, 248, 248, 250,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 251, 125, 252,
- 253, 0, 254, 255, 256, 257, 257, 257, 257, 258, 259, 260, 260, 260, 260, 261,
- 262, 263, 263, 264, 142, 142, 142, 142, 265, 0, 263, 263, 0, 0, 266, 260,
- 142, 265, 0, 0, 0, 0, 142, 267, 0, 0, 0, 0, 0, 260, 260, 268,
- 260, 260, 260, 260, 260, 269, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 0, 0, 0, 0,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, 270, 270, 270, 270, 271, 270, 270, 270, 272, 273, 273, 273,
- 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274, 274,
- 274, 274, 275, 125, 14, 14, 14, 14, 14, 14, 276, 276, 276, 276, 276, 277,
- 0, 0, 278, 4, 4, 4, 4, 4, 279, 4, 4, 4, 280, 281, 125, 282,
- 283, 283, 284, 285, 286, 286, 286, 287, 288, 288, 288, 288, 289, 290, 48, 48,
- 291, 291, 292, 293, 293, 294, 142, 295, 296, 296, 296, 296, 297, 298, 138, 299,
- 300, 300, 300, 301, 302, 303, 138, 138, 304, 304, 304, 304, 305, 306, 307, 308,
- 309, 310, 246, 4, 4, 311, 312, 152, 152, 152, 152, 152, 307, 307, 313, 314,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 315, 142, 316, 142, 142, 317,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 318, 248, 248, 248, 248, 248, 248, 319, 125, 125,
- 320, 321, 21, 322, 323, 27, 27, 27, 27, 27, 27, 27, 324, 325, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 27, 27, 326, 27, 27, 27, 27, 27, 327, 27, 27, 328, 125, 125, 27,
- 8, 285, 329, 0, 0, 330, 331, 332, 27, 27, 27, 27, 27, 27, 27, 333,
- 334, 0, 1, 2, 1, 2, 335, 259, 260, 336, 142, 265, 337, 338, 339, 340,
- 341, 342, 343, 344, 345, 345, 125, 125, 342, 342, 342, 342, 342, 342, 342, 346,
- 347, 0, 0, 348, 11, 11, 11, 11, 349, 350, 351, 125, 125, 0, 0, 352,
- 125, 125, 125, 125, 125, 125, 125, 125, 353, 354, 355, 355, 355, 356, 357, 252,
- 358, 358, 359, 360, 361, 362, 362, 363, 364, 365, 366, 366, 367, 368, 125, 125,
- 369, 369, 369, 369, 369, 370, 370, 370, 371, 372, 373, 374, 374, 375, 374, 376,
- 377, 377, 378, 379, 379, 379, 380, 381, 381, 382, 383, 384, 125, 125, 125, 125,
- 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385, 385,
- 385, 385, 385, 386, 385, 387, 388, 125, 389, 4, 4, 390, 125, 125, 125, 125,
- 391, 392, 392, 393, 394, 395, 396, 396, 397, 398, 399, 125, 125, 125, 400, 401,
- 402, 403, 404, 405, 125, 125, 125, 125, 406, 406, 407, 408, 407, 409, 407, 407,
- 410, 411, 412, 413, 414, 414, 415, 415, 416, 416, 125, 125, 417, 417, 418, 419,
- 420, 420, 420, 421, 422, 423, 424, 425, 426, 427, 428, 125, 125, 125, 125, 125,
- 429, 429, 429, 429, 430, 125, 125, 125, 431, 431, 431, 432, 431, 431, 431, 433,
- 434, 434, 435, 436, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 27, 45, 437, 437, 438, 439, 125, 125, 125, 125,
- 440, 440, 441, 442, 442, 443, 125, 444, 445, 125, 125, 446, 447, 125, 448, 449,
- 450, 450, 450, 450, 451, 452, 450, 453, 454, 454, 454, 454, 455, 456, 457, 458,
- 459, 459, 459, 460, 461, 462, 462, 463, 464, 464, 464, 464, 464, 464, 465, 466,
- 467, 468, 467, 469, 125, 125, 125, 125, 470, 471, 472, 473, 473, 473, 474, 475,
- 476, 477, 478, 479, 480, 481, 482, 483, 125, 125, 125, 125, 125, 125, 125, 125,
- 484, 484, 484, 484, 484, 485, 486, 125, 487, 487, 487, 487, 488, 489, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 490, 490, 490, 491, 490, 492, 125, 125,
- 493, 493, 493, 493, 494, 495, 496, 125, 497, 497, 497, 498, 498, 125, 125, 125,
- 499, 500, 501, 499, 502, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 503, 503, 503, 504, 125, 125, 125, 125, 125, 125, 505, 505, 505, 505, 505, 506,
- 507, 508, 509, 510, 511, 512, 125, 125, 125, 125, 513, 514, 514, 513, 515, 125,
- 516, 516, 516, 516, 517, 518, 518, 518, 518, 518, 519, 154, 520, 520, 520, 521,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 522, 523, 523, 524, 525, 523, 526, 527, 527, 528, 529, 530, 125, 125, 125, 125,
- 531, 532, 532, 533, 534, 535, 536, 537, 538, 539, 540, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 541, 542,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 543, 544, 544, 544, 545,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 547, 125, 125, 125, 125, 125, 125,
- 546, 546, 546, 546, 546, 546, 548, 549, 546, 546, 546, 546, 546, 546, 546, 546,
- 546, 546, 546, 546, 550, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 551, 551, 551, 551, 551, 551, 552,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 553, 554, 555, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, 556, 556, 557, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
- 276, 276, 276, 558, 559, 560, 561, 562, 562, 562, 562, 563, 564, 565, 566, 567,
- 568, 568, 568, 568, 569, 570, 571, 572, 568, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 573, 573, 573, 573, 573, 574, 125, 125, 125, 125, 125, 125,
- 575, 575, 575, 575, 576, 575, 575, 575, 577, 575, 125, 125, 125, 125, 578, 579,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 581,
- 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582,
- 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 582, 583, 125, 125,
- 584, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 585,
- 586, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 587, 125, 125, 588, 589, 590, 590, 590, 590, 590, 590, 590, 590, 590,
- 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 592, 592, 592, 592, 592, 592, 593, 594, 595, 596, 266, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 597, 8, 598, 0, 0, 0, 0, 0, 0, 0, 266, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 599,
- 0, 0, 600, 0, 0, 0, 601, 602, 603, 0, 604, 0, 0, 0, 235, 125,
- 11, 11, 11, 11, 605, 125, 125, 125, 125, 125, 125, 125, 125, 125, 0, 266,
- 0, 0, 0, 0, 0, 234, 0, 606, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 224, 0, 0, 0, 607, 608, 609, 610, 0, 0, 0,
- 611, 612, 0, 613, 614, 615, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 616, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 617, 0, 0, 0,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618, 618,
- 618, 618, 618, 618, 618, 618, 618, 618, 619, 620, 621, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 4, 622, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 623, 624, 625, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 626, 626, 627, 628, 629, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 630, 631, 125, 632, 632, 632, 633,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 634, 635,
- 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 636, 637, 638, 125, 125,
- 639, 639, 639, 639, 640, 641, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 334, 0, 0, 0, 642, 125, 125, 125, 125,
- 334, 0, 0, 247, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 643, 27, 644, 645, 646, 647, 648, 649, 650, 651, 652, 651, 125, 125, 125, 653,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 252, 0, 0, 0, 0, 0, 0, 266, 226, 334, 334, 334, 0, 599,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 247, 125, 125, 125, 654, 0,
- 655, 0, 0, 252, 606, 656, 599, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 657, 350, 350,
- 0, 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, 0, 0, 606, 252, 228,
- 252, 0, 0, 0, 658, 285, 0, 0, 658, 0, 247, 656, 125, 125, 125, 125,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 266, 247, 659, 234, 0, 350, 235, 599, 285, 658, 234,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 330, 0, 0, 235, 125, 125, 285,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 660, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 318, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 579, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 661, 125,
- 248, 318, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
- 248, 248, 248, 248, 662, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 663, 125, 0, 0, 0, 0, 0, 0, 125, 125, 125, 125, 125, 125, 125, 125,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
- 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
- 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
- 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
- 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
- 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
- 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
- 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
- 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
- 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
- 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
- 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
- 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
- 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
- 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
- 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
- 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
- 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
- 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
- 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
- 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
- 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
- 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
- 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
- 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
- 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
- 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
- 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
- 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
- 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
- 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
- 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
- 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
- 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
- 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
- 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
- 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
- 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
- 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
- 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
- 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
- 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
- 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
- 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
- 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
- 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
- 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
- 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
- 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
- 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
- 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
- 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
- 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
- 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
- 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
- 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
- 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
- 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
- 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
- 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
- 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
- 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
- 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
- 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
- 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
- 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
- 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
- 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
- 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
- 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
- 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
- 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
- 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
- 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
- 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
- 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
- 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
- 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
- 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
- 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
- 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
- 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
- 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
- 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
- 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
- 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
- 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
- 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
- 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
- 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
- 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
- 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
- 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
- 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
- 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
- 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
- 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
- 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
- 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
- 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
- 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
- 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
- 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
- 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
- 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
- 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
- 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
- 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
- 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
- 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
- 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
- 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
- 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
- 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
- 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
- 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
- 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
- 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
- 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
- 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
- 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
- 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
- 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
- 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
- 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
- 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
- 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
- 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
- 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
- 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
- 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
- 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
- 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
- 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
- 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
- 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
- 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
- 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-static const int16_t
-_hb_ucd_i16[196] =
-{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
-};
-
-static inline uint_fast8_t
-_hb_ucd_gc (unsigned u)
-{
- return u<1114110u?_hb_ucd_u8[2176+(((_hb_ucd_u16[((_hb_ucd_u8[u>>4>>5])<<5)+((u>>4)&31u)])<<4)+((u)&15u))]:2;
-}
-static inline uint_fast8_t
-_hb_ucd_ccc (unsigned u)
-{
- return u<125259u?_hb_ucd_u8[15332+(((_hb_ucd_u8[13892+(((_hb_ucd_u8[12912+(u>>3>>4)])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:0;
-}
-static inline unsigned
-_hb_ucd_b4 (const uint8_t* a, unsigned i)
-{
- return (a[i>>1]>>((i&1u)<<2))&15u;
-}
-static inline int_fast16_t
-_hb_ucd_bmg (unsigned u)
-{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[16692+(((_hb_ucd_b4(16564+_hb_ucd_u8,u>>2>>6))<<6)+((u>>2)&63u))])<<2)+((u)&3u)]:0;
-}
-static inline uint_fast8_t
-_hb_ucd_sc (unsigned u)
-{
- return u<918000u?_hb_ucd_u8[19446+(((_hb_ucd_u16[3168+(((_hb_ucd_u8[17652+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:2;
-}
-static inline uint_fast16_t
-_hb_ucd_dm (unsigned u)
-{
- return u<195102u?_hb_ucd_u16[6400+(((_hb_ucd_u8[30070+(u>>6)])<<6)+((u)&63u))]:0;
-}
-
-
-#elif !defined(HB_NO_UCD_UNASSIGNED)
-
-static const uint8_t
_hb_ucd_u8[17936] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
@@ -5674,10 +2821,1743 @@ _hb_ucd_dm (unsigned u)
}
+#elif !defined(HB_NO_UCD_UNASSIGNED)
+
+static const uint8_t
+_hb_ucd_u8[17564] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 11, 12, 13, 13, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 22, 22, 22, 22, 24, 7, 7,
+ 25, 26, 22, 22, 22, 27, 28, 29, 22, 30, 31, 32, 33, 34, 35, 36,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 22, 42,
+ 7, 7, 43, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 44, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 45,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 46,
+ 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, 34, 35, 36, 37, 38, 39, 34, 34, 34, 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, 64, 65, 66, 67, 68, 69, 70, 71, 69, 72, 73,
+ 69, 69, 64, 74, 64, 64, 75, 76, 77, 78, 79, 80, 81, 82, 69, 83,
+ 84, 85, 86, 87, 88, 89, 69, 69, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 90, 34, 34, 34, 34,
+ 91, 34, 34, 34, 34, 34, 34, 34, 34, 92, 34, 34, 93, 94, 95, 96,
+ 97, 98, 99,100,101,102,103,104, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,105,
+ 106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,
+ 107,107, 34, 34,108,109,110,111, 34, 34,112,113,114,115,116,117,
+ 118,119,120,121,122,123,124,125,126,127,128,129, 34, 34,130,131,
+ 132,133,134,135,136,137,138,139,140,141,142,122,143,144,145,146,
+ 147,148,149,150,151,152,153,122,154,155,122,156,157,158,159,122,
+ 160,161,162,163,164,165,122,122,166,167,168,169,122,170,122,171,
+ 34, 34, 34, 34, 34, 34, 34,172,173, 34,174,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,175,
+ 34, 34, 34, 34, 34, 34, 34, 34,176,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122, 34, 34, 34, 34,177,122,122,122,
+ 34, 34, 34, 34,178,179,180,181,122,122,122,122,182,183,184,185,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,186,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34,187,188,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,122,189,
+ 34, 34,190, 34, 34,191,122,122,122,122,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,192,193,122,122,122,122,122,122,
+ 122,122,122,122,122,122,122,122,122,122,122,122,122,122,194,195,
+ 69,196,197,198,199,200,201,122,202,203,204,205,206,207,208,209,
+ 69, 69, 69, 69,210,211,122,122,122,122,122,122,122,122,212,122,
+ 213,122,214,122,122,215,122,122,122,122,122,122,122,122,122,216,
+ 34,217,218,122,122,122,122,122,219,220,221,122,222,223,122,122,
+ 224,225,226,227,228,122, 69,229, 69, 69, 69, 69, 69,230,231,232,
+ 233,234, 69, 69,235,236, 69,237,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,238, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,239, 34,
+ 240, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34,241, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34,242,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34,243,122,122,122,122,122,122,122,122,122,122,122,
+ 34, 34, 34, 34, 34, 34,244,122,122,122,122,122,122,122,122,122,
+ 245,122,246,247,122,122,122,122,122,122,122,122,122,122,122,122,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,248,
+ 107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,249,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 4, 5, 6, 2,
+ 7, 7, 7, 7, 7, 2, 8, 9, 10, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 17, 18, 19, 1, 20, 20, 21, 22, 23, 24, 25,
+ 26, 27, 15, 2, 28, 29, 27, 30, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 31, 11, 11, 11, 32, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 33, 16, 16, 16, 16, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 34, 34, 34, 34, 34, 34, 34, 34, 16, 32, 32, 32,
+ 32, 32, 32, 32, 11, 34, 34, 16, 34, 32, 32, 11, 34, 11, 16, 11,
+ 11, 34, 32, 11, 32, 16, 11, 34, 32, 32, 32, 11, 34, 16, 32, 11,
+ 34, 11, 34, 34, 32, 35, 32, 16, 36, 36, 37, 34, 38, 37, 34, 34,
+ 34, 34, 34, 34, 34, 34, 16, 32, 34, 38, 32, 11, 32, 32, 32, 32,
+ 32, 32, 16, 16, 16, 11, 34, 32, 34, 34, 11, 32, 32, 32, 32, 32,
+ 16, 16, 39, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 41, 41, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41,
+ 40, 40, 42, 41, 41, 41, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41,
+ 43, 43, 43, 43, 43, 43, 43, 43, 32, 32, 42, 32, 44, 45, 16, 10,
+ 44, 44, 41, 46, 11, 47, 47, 11, 34, 11, 11, 11, 11, 11, 11, 11,
+ 11, 48, 11, 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 16, 34,
+ 16, 11, 32, 16, 32, 32, 32, 32, 16, 16, 32, 49, 34, 32, 34, 11,
+ 32, 50, 43, 43, 51, 32, 32, 32, 11, 34, 34, 34, 34, 34, 34, 16,
+ 48, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 47, 52, 2, 2, 2,
+ 16, 16, 16, 16, 53, 54, 55, 56, 57, 43, 43, 43, 43, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 58, 59, 60, 43, 59, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 62,
+ 36, 63, 64, 44, 44, 44, 44, 44, 65, 65, 65, 8, 9, 66, 2, 67,
+ 43, 43, 43, 43, 43, 60, 68, 2, 69, 36, 36, 36, 36, 70, 43, 43,
+ 7, 7, 7, 7, 7, 2, 2, 36, 71, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 72, 43, 43, 43, 73, 50, 43, 43, 74, 75, 76, 43, 43, 36,
+ 7, 7, 7, 7, 7, 36, 77, 78, 2, 2, 2, 2, 2, 2, 2, 79,
+ 70, 36, 36, 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 80, 62, 36,
+ 36, 36, 36, 43, 43, 43, 43, 43, 71, 44, 44, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43,
+ 43, 43, 40, 21, 2, 81, 57, 20, 36, 36, 36, 43, 43, 75, 43, 43,
+ 43, 43, 75, 43, 75, 43, 43, 44, 2, 2, 2, 2, 2, 2, 2, 64,
+ 36, 36, 36, 36, 70, 43, 44, 64, 36, 36, 36, 36, 36, 61, 44, 44,
+ 36, 36, 36, 36, 82, 36, 36, 61, 65, 44, 44, 44, 43, 43, 43, 43,
+ 36, 36, 36, 36, 83, 43, 43, 43, 43, 84, 43, 43, 43, 43, 43, 43,
+ 43, 85, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 85, 71, 86,
+ 87, 43, 43, 43, 85, 86, 87, 86, 70, 43, 43, 43, 36, 36, 36, 36,
+ 36, 43, 2, 7, 7, 7, 7, 7, 88, 36, 36, 36, 36, 36, 36, 36,
+ 70, 86, 62, 36, 36, 36, 61, 62, 61, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 36, 36, 36, 61, 61, 44, 36, 36, 44, 71, 86,
+ 87, 43, 80, 89, 90, 89, 87, 61, 44, 44, 44, 89, 44, 44, 36, 62,
+ 36, 43, 44, 7, 7, 7, 7, 7, 36, 20, 27, 27, 27, 56, 63, 80,
+ 57, 85, 62, 36, 36, 61, 44, 62, 61, 36, 62, 61, 36, 44, 80, 86,
+ 87, 80, 44, 57, 80, 57, 43, 44, 57, 44, 44, 44, 62, 36, 61, 61,
+ 44, 44, 44, 7, 7, 7, 7, 7, 43, 36, 70, 64, 44, 44, 44, 44,
+ 57, 85, 62, 36, 36, 36, 36, 62, 36, 62, 36, 36, 36, 36, 36, 36,
+ 61, 36, 62, 36, 36, 44, 71, 86, 87, 43, 43, 57, 85, 89, 87, 44,
+ 61, 44, 44, 44, 44, 44, 44, 44, 66, 44, 44, 44, 62, 43, 43, 43,
+ 57, 86, 62, 36, 36, 36, 61, 62, 61, 36, 62, 36, 36, 44, 71, 87,
+ 87, 43, 80, 89, 90, 89, 87, 44, 44, 44, 57, 85, 44, 44, 36, 62,
+ 78, 27, 27, 27, 44, 44, 44, 44, 44, 71, 62, 36, 36, 61, 44, 36,
+ 61, 36, 36, 44, 62, 61, 61, 36, 44, 62, 61, 44, 36, 61, 44, 36,
+ 36, 36, 36, 36, 36, 44, 44, 86, 85, 90, 44, 86, 90, 86, 87, 44,
+ 61, 44, 44, 89, 44, 44, 44, 44, 27, 91, 67, 67, 56, 92, 44, 44,
+ 85, 86, 71, 36, 36, 36, 61, 36, 61, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 44, 71, 43, 85, 86, 90, 43, 80, 43, 43, 44,
+ 44, 44, 57, 80, 36, 61, 62, 44, 44, 44, 44, 93, 27, 27, 27, 91,
+ 70, 86, 72, 36, 36, 36, 61, 36, 36, 36, 62, 36, 36, 44, 71, 87,
+ 86, 86, 90, 85, 90, 86, 43, 44, 44, 44, 89, 90, 44, 44, 62, 61,
+ 62, 61, 44, 44, 44, 44, 44, 44, 43, 86, 36, 36, 36, 36, 61, 36,
+ 36, 36, 36, 36, 36, 70, 71, 86, 87, 43, 80, 86, 90, 86, 87, 77,
+ 44, 44, 36, 94, 27, 27, 27, 95, 27, 27, 27, 27, 91, 36, 36, 36,
+ 57, 86, 62, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44, 36, 36, 36,
+ 36, 62, 36, 36, 36, 36, 62, 44, 36, 36, 36, 61, 44, 80, 44, 89,
+ 86, 43, 80, 80, 86, 86, 86, 86, 44, 86, 64, 44, 44, 44, 44, 44,
+ 62, 36, 36, 36, 36, 36, 36, 36, 70, 36, 43, 43, 43, 80, 44, 96,
+ 36, 36, 36, 75, 43, 43, 43, 60, 7, 7, 7, 7, 7, 2, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 62, 61, 61, 36, 36, 61, 36, 36,
+ 36, 36, 62, 62, 36, 36, 36, 36, 70, 36, 43, 43, 43, 43, 71, 44,
+ 36, 36, 61, 81, 43, 43, 43, 44, 7, 7, 7, 7, 7, 44, 36, 36,
+ 77, 67, 2, 2, 2, 2, 2, 2, 2, 97, 97, 67, 43, 67, 67, 67,
+ 7, 7, 7, 7, 7, 27, 27, 27, 27, 27, 50, 50, 50, 4, 4, 86,
+ 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 44,
+ 57, 43, 43, 43, 43, 43, 43, 85, 43, 43, 60, 43, 36, 36, 70, 43,
+ 43, 43, 43, 43, 57, 43, 43, 43, 43, 43, 43, 43, 43, 43, 80, 67,
+ 67, 67, 67, 76, 67, 67, 92, 67, 2, 2, 97, 67, 21, 64, 44, 44,
+ 36, 36, 36, 36, 36, 94, 87, 43, 85, 43, 43, 43, 87, 85, 87, 71,
+ 7, 7, 7, 7, 7, 2, 2, 2, 36, 36, 36, 86, 43, 36, 36, 43,
+ 71, 86, 98, 94, 86, 86, 86, 36, 70, 43, 71, 36, 36, 36, 36, 36,
+ 36, 85, 87, 85, 86, 86, 87, 94, 7, 7, 7, 7, 7, 86, 87, 67,
+ 11, 11, 11, 48, 44, 44, 48, 44, 16, 16, 16, 16, 16, 53, 45, 16,
+ 36, 36, 36, 36, 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44,
+ 61, 36, 36, 44, 36, 36, 36, 61, 61, 36, 36, 44, 36, 36, 36, 36,
+ 36, 36, 36, 61, 36, 36, 36, 36, 36, 36, 36, 36, 36, 61, 57, 43,
+ 2, 2, 2, 2, 99, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44,
+ 67, 67, 67, 67, 67, 44, 44, 44, 11, 11, 11, 44, 16, 16, 16, 44,
+ 101, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 77, 72,
+ 102, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,103,104, 44,
+ 36, 36, 36, 36, 36, 63, 2,105,106, 36, 36, 36, 61, 44, 44, 44,
+ 36, 43, 85, 44, 44, 44, 44, 62, 36, 43,107, 64, 44, 44, 44, 44,
+ 36, 43, 44, 44, 44, 44, 44, 44, 36, 36, 36, 36, 36, 36, 61, 36,
+ 61, 43, 44, 44, 44, 44, 44, 44, 36, 36, 43, 87, 43, 43, 43, 86,
+ 86, 86, 86, 85, 87, 43, 43, 43, 43, 43, 2, 88, 2, 66, 70, 44,
+ 7, 7, 7, 7, 7, 44, 44, 44, 27, 27, 27, 27, 27, 44, 44, 44,
+ 2, 2, 2,108, 2, 59, 43, 84, 36, 83, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 61, 44, 44, 44, 36, 36, 70, 71, 36, 36, 36, 36,
+ 36, 36, 36, 36, 70, 61, 44, 44, 36, 36, 36, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 61, 43, 85, 86, 87, 85, 86, 44, 44,
+ 86, 85, 86, 86, 87, 43, 44, 44, 92, 44, 2, 7, 7, 7, 7, 7,
+ 36, 36, 36, 36, 36, 36, 36, 44, 36, 36, 61, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 44, 44, 36, 36, 36, 36, 36, 44, 44, 44,
+ 7, 7, 7, 7, 7,100, 44, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 36, 36, 36, 70, 85, 87, 44, 2, 36, 36, 94, 85, 43, 43, 43, 80,
+ 85, 85, 87, 43, 43, 43, 85, 86, 86, 87, 43, 43, 43, 43, 80, 57,
+ 2, 2, 2, 88, 2, 2, 2, 44, 43, 43, 43, 43, 43, 43, 43,109,
+ 43, 43, 43, 43, 43, 43, 43, 80, 43, 43, 98, 36, 36, 36, 36, 36,
+ 36, 36, 85, 43, 43, 85, 85, 86, 86, 85, 98, 36, 36, 36, 61, 44,
+ 97, 67, 67, 67, 67, 50, 43, 43, 43, 43, 67, 67, 67, 67, 21, 64,
+ 43, 98, 36, 36, 36, 36, 36, 36, 94, 43, 43, 86, 43, 87, 43, 36,
+ 36, 36, 36, 85, 43, 86, 87, 87, 43, 86, 44, 44, 44, 44, 2, 2,
+ 36, 36, 86, 86, 86, 86, 43, 43, 43, 43, 86, 43, 44, 93, 2, 2,
+ 7, 7, 7, 7, 7, 44, 62, 36, 36, 36, 36, 36, 40, 40, 40, 2,
+ 16, 16, 16, 16,110, 44, 44, 44, 11, 11, 11, 11, 11, 47, 48, 11,
+ 2, 2, 2, 2, 44, 44, 44, 44, 43, 60, 43, 43, 43, 43, 43, 43,
+ 85, 43, 43, 43, 71, 36, 70, 36, 36, 36, 71, 94, 43, 61, 44, 44,
+ 16, 16, 16, 16, 16, 16, 40, 40, 40, 40, 40, 40, 40, 45, 16, 16,
+ 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16,111, 40, 40,
+ 32, 32, 32, 16, 16, 16, 16, 32, 16, 16, 16, 16, 11, 11, 11, 11,
+ 16, 16, 16, 44, 11, 11, 11, 44, 16, 16, 16, 16, 48, 48, 48, 48,
+ 16, 16, 16, 16, 16, 16, 16, 44, 16, 16, 16, 16,112,112,112,112,
+ 16, 16,110, 16, 11, 11,113,114, 41, 16,110, 16, 11, 11,113, 41,
+ 16, 16, 44, 16, 11, 11,115, 41, 16, 16, 16, 16, 11, 11,116, 41,
+ 44, 16,110, 16, 11, 11,113,117,118,118,118,118,118,119, 65, 65,
+ 120,120,120, 2,121,122,121,122, 2, 2, 2, 2,123, 65, 65,124,
+ 2, 2, 2, 2,125,126, 2,127,128, 2,129,130, 2, 2, 2, 2,
+ 2, 9,128, 2, 2, 2, 2,131, 65, 65,132, 65, 65, 65, 65, 65,
+ 133, 44, 27, 27, 27, 8,129,134, 27, 27, 27, 27, 27, 8,129,104,
+ 40, 40, 40, 40, 40, 40, 81, 44, 20, 20, 20, 20, 20, 20, 20, 20,
+ 135, 44, 44, 44, 44, 44, 44, 44, 43, 43, 43, 43, 43, 43,136, 51,
+ 109, 51,109, 43, 43, 43, 43, 43, 80, 44, 44, 44, 44, 44, 44, 44,
+ 67,137, 67,138, 67, 34, 11, 16, 11, 32,138, 67, 49, 11, 11, 67,
+ 67, 67,137,137,137, 11, 11,139, 11, 11, 35, 36, 39, 67, 16, 11,
+ 8, 8, 49, 16, 16, 26, 67,140, 27, 27, 27, 27, 27, 27, 27, 27,
+ 105,105,105,105,105,105,105,105,105,141,142,105,143, 67, 44, 44,
+ 8, 8,144, 67, 67, 8, 67, 67,144, 26, 67,144, 67, 67, 67,144,
+ 67, 67, 67, 67, 67, 67, 67, 8, 67,144,144, 67, 67, 67, 67, 67,
+ 67, 67, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 67, 67, 67, 67, 4, 4, 67, 67, 8, 67, 67, 67,145,146, 67, 67,
+ 67, 67, 67, 67, 67, 67,144, 67, 67, 67, 67, 67, 67, 26, 8, 8,
+ 8, 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8,
+ 8, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 92, 44, 44, 27, 27, 27, 27, 27, 27, 67, 67,
+ 67, 67, 67, 67, 67, 27, 27, 27, 67, 67, 67, 26, 67, 67, 67, 67,
+ 26, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 67, 8, 8, 8, 8,
+ 67, 67, 67, 67, 67, 67, 67, 26, 67, 67, 67, 67, 4, 4, 4, 4,
+ 4, 4, 4, 27, 27, 27, 27, 27, 27, 27, 67, 67, 67, 67, 67, 67,
+ 8, 8,129,147, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4,
+ 8,129,148,148,148,148,148,148,148,148,148,148,147, 8, 8, 8,
+ 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 4, 8,
+ 8, 8,144, 26, 8, 8,144, 67, 67, 67, 44, 67, 67, 67, 67, 67,
+ 67, 67, 67, 55, 67, 67, 67, 67, 32, 11, 32, 34, 34, 34, 34, 11,
+ 32, 32, 34, 16, 16, 16, 40, 11, 32, 32,140, 67, 67,138, 34,149,
+ 43, 32, 44, 44, 93, 2, 99, 2, 16, 16, 16,150, 44, 44,150, 44,
+ 36, 36, 36, 36, 44, 44, 44, 52, 64, 44, 44, 44, 44, 44, 44, 57,
+ 36, 36, 36, 61, 44, 44, 44, 44, 36, 36, 36, 61, 36, 36, 36, 61,
+ 2,121,121, 2,125,126,121, 2, 2, 2, 2, 6, 2,108,121, 2,
+ 121, 4, 4, 4, 4, 2, 2, 88, 2, 2, 2, 2, 2,120, 2, 2,
+ 108,151, 2, 2, 2, 2, 2, 2, 67, 2,152,148,148,148,153, 44,
+ 67, 67, 67, 67, 67, 55, 67, 67, 67, 67, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 44, 44, 44, 44, 44, 67, 67, 67, 67, 67, 67, 44, 44,
+ 1, 2,154,155, 4, 4, 4, 4, 4, 67, 4, 4, 4, 4,156,157,
+ 158,105,105,105,105, 43, 43, 86,159, 40, 40, 67,105,160, 63, 67,
+ 36, 36, 36, 61, 57,161,162, 69, 36, 36, 36, 36, 36, 63, 40, 69,
+ 44, 44, 62, 36, 36, 36, 36, 36, 67, 27, 27, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 92, 27, 27, 27, 27, 27, 67, 67, 67,
+ 67, 67, 67, 67, 27, 27, 27, 27,163, 27, 27, 27, 27, 27, 27, 27,
+ 36, 36, 83, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,164, 2,
+ 7, 7, 7, 7, 7, 36, 44, 44, 32, 32, 32, 32, 32, 32, 32, 70,
+ 51,165, 43, 43, 43, 43, 43, 88, 32, 32, 32, 32, 32, 32, 40, 43,
+ 36, 36, 36,105,105,105,105,105, 43, 2, 2, 2, 44, 44, 44, 44,
+ 41, 41, 41,162, 40, 40, 40, 40, 41, 32, 32, 32, 32, 32, 32, 32,
+ 16, 32, 32, 32, 32, 32, 32, 32, 45, 16, 16, 16, 34, 34, 34, 32,
+ 32, 32, 32, 32, 42,166, 34, 35, 32, 32, 16, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 11, 11, 32, 11, 11, 32, 32, 32, 32, 32, 32,
+ 32, 32, 11, 11, 34,110, 44, 44, 32,150,150, 32, 32, 44, 44, 44,
+ 44, 40,167, 35, 40, 35, 36, 36, 36, 71, 36, 71, 36, 70, 36, 36,
+ 36, 94, 87, 85, 67, 67, 80, 44, 27, 27, 27, 67,168, 44, 44, 44,
+ 36, 36, 2, 2, 44, 44, 44, 44, 86, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 86, 86, 86, 86, 86, 86, 86, 86, 43, 44, 44, 44, 44, 2,
+ 43, 36, 36, 36, 2, 72, 72, 70, 36, 36, 36, 43, 43, 43, 43, 2,
+ 36, 36, 36, 70, 43, 43, 43, 43, 43, 86, 44, 44, 44, 44, 44, 93,
+ 36, 70, 86, 43, 43, 86, 43, 86,107, 2, 2, 2, 2, 2, 2, 52,
+ 7, 7, 7, 7, 7, 44, 44, 2, 36, 36, 70, 69, 36, 36, 36, 36,
+ 7, 7, 7, 7, 7, 36, 36, 61, 36, 36, 36, 36, 70, 43, 43, 85,
+ 87, 85, 87, 80, 44, 44, 44, 44, 36, 70, 36, 36, 36, 36, 85, 44,
+ 7, 7, 7, 7, 7, 44, 2, 2, 69, 36, 36, 77, 67, 94, 85, 36,
+ 71, 43, 71, 70, 71, 36, 36, 43, 70, 61, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 62, 83, 2, 36, 36, 36, 36, 36, 94, 43, 86,
+ 2, 83,169, 80, 44, 44, 44, 44, 62, 36, 36, 61, 62, 36, 36, 61,
+ 62, 36, 36, 61, 44, 44, 44, 44, 16, 16, 16, 16, 16,114, 40, 40,
+ 16, 16, 16, 16,111, 41, 44, 44, 36, 94, 87, 86, 85,107, 87, 44,
+ 36, 36, 44, 44, 44, 44, 44, 44, 36, 36, 36, 61, 44, 62, 36, 36,
+ 170,170,170,170,170,170,170,170,171,171,171,171,171,171,171,171,
+ 16, 16, 16,110, 44, 44, 44, 44, 44,150, 16, 16, 44, 44, 62, 71,
+ 36, 36, 36, 36,172, 36, 36, 36, 36, 36, 36, 61, 36, 36, 61, 61,
+ 36, 62, 61, 36, 36, 36, 36, 36, 36, 41, 41, 41, 41, 41, 41, 41,
+ 41,117, 44, 44, 44, 44, 44, 44, 44, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 36,148, 44, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 44, 55, 36, 36, 36, 36, 36, 36,168, 67,
+ 2, 2, 2,152,130, 44, 44, 44, 6,173,174,148,148,148,148,148,
+ 148,148,130,152,130, 2,127,175, 2, 64, 2, 2,156,148,148,130,
+ 2,176, 8,177, 66, 2, 44, 44, 36, 36, 61, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 36, 61, 79, 93, 2, 3, 2, 4, 5, 6, 2,
+ 16, 16, 16, 16, 16, 17, 18,129,130, 4, 2, 36, 36, 36, 36, 36,
+ 69, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 40,
+ 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 36, 36, 44, 36, 61, 44,
+ 20,178, 56,135, 26, 8,144, 92, 44, 44, 44, 44, 79, 65, 67, 44,
+ 36, 36, 36, 36, 36, 36, 62, 36, 36, 36, 36, 36, 36, 61, 36, 62,
+ 2, 64, 44,179, 27, 27, 27, 27, 27, 27, 44, 55, 67, 67, 67, 67,
+ 105,105,143, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 27, 67, 92,
+ 67, 67, 67, 67, 67, 67, 92, 44, 92, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 67, 50, 44,180, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 44, 44, 27, 27, 44, 44, 44, 44, 62, 36,
+ 155, 36, 36, 36, 36,181, 44, 44, 36, 36, 36, 43, 43, 80, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 93, 36, 36, 44, 44, 36, 36, 36, 36,
+ 182,105,105, 44, 44, 44, 44, 44, 11, 11, 11, 11, 16, 16, 16, 16,
+ 11, 11, 44, 44, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 44, 44,
+ 36, 36, 36, 36, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44, 44, 93,
+ 11, 11, 11, 11, 11, 47, 11, 11, 11, 47, 11,150, 16, 16, 16, 16,
+ 16,150, 16, 16, 16, 16, 16, 16, 16,150, 16, 16, 16,150,110, 44,
+ 40, 40, 40, 52, 40, 40, 40, 40, 81, 40, 40, 40, 40, 81, 44, 44,
+ 36, 36, 36, 44, 61, 36, 36, 36, 36, 36, 36, 62, 61, 44, 61, 62,
+ 36, 36, 36, 93, 27, 27, 27, 27, 36, 36, 36, 77,163, 27, 27, 27,
+ 44, 44, 44,179, 27, 27, 27, 27, 36, 61, 36, 44, 44,179, 27, 27,
+ 36, 36, 36, 27, 27, 27, 44, 93, 36, 36, 36, 36, 36, 44, 44, 93,
+ 36, 36, 36, 36, 44, 44, 27, 36, 44, 27, 27, 27, 27, 27, 27, 27,
+ 70, 43, 57, 80, 44, 44, 43, 43, 36, 36, 62, 36, 62, 36, 36, 36,
+ 36, 36, 36, 44, 43, 80, 44, 57, 27, 27, 27, 27,100, 44, 44, 44,
+ 2, 2, 2, 2, 64, 44, 44, 44, 36, 36, 36, 36, 36, 36,183, 30,
+ 36, 36, 36, 36, 36, 36,183, 27, 36, 36, 36, 36, 78, 36, 36, 36,
+ 36, 36, 70, 80, 44,179, 27, 27, 2, 2, 2, 64, 44, 44, 44, 44,
+ 36, 36, 36, 44, 93, 2, 2, 2, 36, 36, 36, 44, 27, 27, 27, 27,
+ 36, 61, 44, 44, 27, 27, 27, 27, 36, 44, 44, 44, 93, 2, 64, 44,
+ 44, 44, 44, 44,179, 27, 27, 27, 11, 47, 44, 44, 44, 44, 44, 44,
+ 16,110, 44, 44, 44, 27, 27, 27, 36, 36, 43, 43, 44, 44, 44, 44,
+ 27, 27, 27, 27, 27, 27, 27,100, 36, 36, 36, 36, 36, 57,184, 44,
+ 36, 44, 44, 44, 44, 44, 44, 44, 27, 27, 27, 95, 44, 44, 44, 44,
+ 180, 27, 30, 2, 2, 44, 44, 44, 36, 43, 43, 2, 2, 44, 44, 44,
+ 36, 36,183, 27, 27, 27, 44, 44, 87, 98, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 43, 60, 2, 2, 2, 44,
+ 27, 27, 27, 7, 7, 7, 7, 7, 71, 70, 71, 44, 44, 44, 44, 57,
+ 86, 87, 43, 85, 87, 60,185, 2, 2, 80, 44, 44, 44, 44, 79, 44,
+ 43, 71, 36, 36, 36, 36, 36, 36, 36, 36, 36, 70, 43, 43, 87, 43,
+ 43, 43, 80, 7, 7, 7, 7, 7, 2, 2, 94, 98, 44, 44, 44, 44,
+ 36, 70, 2, 61, 44, 44, 44, 44, 36, 94, 86, 43, 43, 43, 43, 85,
+ 98, 36, 63, 2, 59, 43, 60, 87, 7, 7, 7, 7, 7, 63, 63, 2,
+ 179, 27, 27, 27, 27, 27, 27, 27, 27, 27,100, 44, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 86, 87, 43, 86, 85, 43, 2, 2, 2, 80,
+ 36, 36, 36, 61, 61, 36, 36, 62, 36, 36, 36, 36, 36, 36, 36, 62,
+ 36, 36, 36, 36, 63, 44, 44, 44, 36, 36, 36, 36, 36, 36, 36, 70,
+ 86, 87, 43, 43, 43, 80, 44, 44, 43, 86, 62, 36, 36, 36, 61, 62,
+ 61, 36, 62, 36, 36, 57, 71, 86, 85, 86, 90, 89, 90, 89, 86, 44,
+ 61, 44, 44, 89, 44, 44, 62, 36, 36, 86, 44, 43, 43, 43, 80, 44,
+ 43, 43, 80, 44, 44, 44, 44, 44, 36, 36, 94, 86, 43, 43, 43, 43,
+ 86, 43, 85, 71, 36, 63, 2, 2, 7, 7, 7, 7, 7, 2, 93, 71,
+ 86, 87, 43, 43, 85, 85, 86, 87, 85, 43, 36, 72, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 36, 36, 94, 86, 43, 43, 44, 86, 86, 43, 87,
+ 60, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 36, 36, 43, 44,
+ 86, 87, 43, 43, 43, 85, 87, 87, 60, 2, 61, 44, 44, 44, 44, 44,
+ 2, 2, 2, 2, 2, 2, 64, 44, 36, 36, 36, 36, 36, 70, 87, 86,
+ 43, 43, 43, 87, 63, 44, 44, 44, 86, 43, 43, 87, 43, 43, 44, 44,
+ 7, 7, 7, 7, 7, 27, 2, 97, 43, 43, 43, 43, 87, 60, 44, 44,
+ 27,100, 44, 44, 44, 44, 44, 62, 36, 36, 36, 61, 62, 44, 36, 36,
+ 36, 36, 62, 61, 36, 36, 36, 36, 86, 86, 86, 89, 90, 57, 85, 71,
+ 98, 87, 2, 64, 44, 44, 44, 44, 36, 36, 36, 36, 44, 36, 36, 36,
+ 94, 86, 43, 43, 44, 43, 86, 86, 71, 72, 90, 44, 44, 44, 44, 44,
+ 70, 43, 43, 43, 43, 71, 36, 36, 36, 70, 43, 43, 85, 70, 43, 60,
+ 2, 2, 2, 59, 44, 44, 44, 44, 70, 43, 43, 85, 87, 43, 36, 36,
+ 36, 36, 36, 36, 36, 43, 43, 43, 43, 43, 43, 85, 43, 2, 72, 2,
+ 2, 64, 44, 44, 44, 44, 44, 44, 43, 43, 43, 80, 43, 43, 43, 87,
+ 63, 2, 2, 44, 44, 44, 44, 44, 2, 36, 36, 36, 36, 36, 36, 36,
+ 44, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 89, 43, 43, 43,
+ 85, 43, 87, 80, 44, 44, 44, 44, 36, 36, 36, 61, 36, 62, 36, 36,
+ 70, 43, 43, 80, 44, 80, 43, 57, 43, 43, 43, 70, 44, 44, 44, 44,
+ 36, 36, 36, 62, 61, 36, 36, 36, 36, 36, 36, 36, 36, 86, 86, 90,
+ 43, 89, 87, 87, 61, 44, 44, 44, 36, 70, 85,107, 64, 44, 44, 44,
+ 27, 27, 91, 67, 67, 67, 56, 20,168, 67, 67, 67, 67, 67, 67, 67,
+ 67, 44, 44, 44, 44, 44, 44, 93,105,105,105,105,105,105,105,181,
+ 2, 2, 64, 44, 44, 44, 44, 44, 63, 64, 44, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65,132, 44, 44, 44, 43, 43, 60, 44, 44, 44, 44, 44,
+ 43, 43, 43, 60, 2, 2, 67, 67, 40, 40, 97, 44, 44, 44, 44, 44,
+ 7, 7, 7, 7, 7,179, 27, 27, 27, 62, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 44, 44, 62, 36, 27, 27, 27, 30, 2, 64, 44, 44,
+ 36, 36, 36, 36, 36, 61, 44, 57, 94, 86, 86, 86, 86, 86, 86, 86,
+ 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 44, 44, 44, 57,
+ 43, 74, 40, 40, 40, 40, 40, 40, 40, 88, 80, 44, 44, 44, 44, 44,
+ 86, 44, 44, 44, 44, 44, 44, 44, 40, 40, 52, 40, 40, 40, 52, 81,
+ 36, 61, 44, 44, 44, 44, 44, 44, 44, 44, 36, 36, 44, 44, 44, 44,
+ 36, 36, 36, 36, 36, 44, 50, 60, 65, 65, 44, 44, 44, 44, 44, 44,
+ 43, 43, 43, 43, 43, 43, 43, 44, 43, 43, 43, 80, 44, 44, 44, 44,
+ 67, 67, 67, 92, 55, 67, 67, 67, 67, 67,186, 87, 43, 67,186, 86,
+ 86,187, 65, 65, 65, 84, 43, 43, 43, 76, 50, 43, 43, 43, 67, 67,
+ 67, 67, 67, 67, 67, 43, 43, 67, 67, 43, 76, 44, 44, 44, 44, 44,
+ 27, 27, 44, 44, 44, 44, 44, 44, 11, 11, 11, 11, 11, 16, 16, 16,
+ 16, 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 16,
+ 16, 16,110, 16, 16, 16, 16, 16, 11, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 47, 11, 44, 47, 48, 47, 48, 11, 47, 11,
+ 11, 11, 11, 16, 16,150,150, 16, 16, 16,150, 16, 16, 16, 16, 16,
+ 16, 16, 11, 48, 11, 47, 48, 11, 11, 11, 47, 11, 11, 11, 47, 16,
+ 16, 16, 16, 16, 11, 48, 11, 47, 11, 11, 47, 47, 44, 11, 11, 11,
+ 47, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 11, 11,
+ 11, 11, 11, 16, 16, 16, 16, 16, 16, 16, 16, 44, 11, 11, 11, 11,
+ 31, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 33, 16, 16,
+ 16, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 31, 16, 16,
+ 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 31, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 33, 16, 16, 16, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16,
+ 11, 11, 11, 11, 31, 16, 16, 16, 16, 33, 16, 16, 16, 32, 44, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 43, 43, 43, 76, 67, 50, 43, 43,
+ 43, 43, 43, 43, 43, 43, 76, 67, 67, 67, 50, 67, 67, 67, 67, 67,
+ 67, 67, 76, 21, 2, 2, 44, 44, 44, 44, 44, 44, 44, 57, 43, 43,
+ 16, 16, 16, 16, 16, 39, 16, 16, 16, 16, 16, 16, 16, 16, 16,110,
+ 43, 43, 43, 80, 43, 43, 43, 43, 43, 43, 43, 43, 80, 57, 43, 43,
+ 43, 57, 80, 43, 43, 80, 44, 44, 43, 43, 43, 74, 40, 40, 40, 44,
+ 7, 7, 7, 7, 7, 44, 44, 77, 36, 36, 36, 36, 36, 36, 36, 80,
+ 36, 36, 36, 36, 36, 36, 43, 43, 7, 7, 7, 7, 7, 44, 44, 96,
+ 36, 36, 36, 61, 36, 36, 62, 61, 36, 36, 61,179, 27, 27, 27, 27,
+ 16, 16, 43, 43, 43, 74, 44, 44, 27, 27, 27, 27, 27, 27,163, 27,
+ 188, 27,100, 44, 44, 44, 44, 44, 27, 27, 27, 27, 27, 27, 27,163,
+ 27, 27, 27, 27, 27, 27, 27, 44, 36, 36, 62, 36, 36, 36, 36, 36,
+ 62, 61, 61, 62, 62, 36, 36, 36, 36, 61, 36, 36, 62, 62, 44, 44,
+ 44, 61, 44, 62, 62, 62, 62, 36, 62, 61, 61, 62, 62, 62, 62, 62,
+ 62, 61, 61, 62, 36, 61, 36, 36, 36, 61, 36, 36, 62, 36, 61, 61,
+ 36, 36, 36, 36, 36, 62, 36, 36, 62, 36, 62, 36, 36, 62, 36, 36,
+ 8, 44, 44, 44, 44, 44, 44, 44, 55, 67, 67, 67, 67, 67, 67, 67,
+ 27, 27, 27, 27, 27, 27, 91, 67, 67, 67, 67, 67, 67, 67, 67, 44,
+ 44, 44, 44, 67, 67, 67, 67, 67, 67, 92, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 92, 44, 44, 44, 67, 44, 44, 44, 44, 44, 44, 44,
+ 67, 67, 67, 67, 67, 25, 41, 41, 67, 67, 67, 67, 44, 44, 55, 67,
+ 67, 67, 67, 67, 44, 44, 44, 44, 67, 67, 92, 44, 67, 67, 92, 44,
+ 67, 92, 67, 67, 67, 67, 67, 67, 79, 44, 44, 44, 44, 44, 44, 44,
+ 65, 65, 65, 65, 65, 65, 65, 65,171,171,171,171,171,171,171, 44,
+ 171,171,171,171,171,171,171, 0, 0, 0, 29, 21, 21, 21, 23, 21,
+ 22, 18, 21, 25, 21, 17, 13, 13, 25, 25, 25, 21, 21, 9, 9, 9,
+ 9, 22, 21, 18, 24, 16, 24, 5, 5, 5, 5, 22, 25, 18, 25, 0,
+ 23, 23, 26, 21, 24, 26, 7, 20, 25, 1, 26, 24, 26, 25, 15, 15,
+ 24, 15, 7, 19, 15, 21, 9, 25, 9, 5, 5, 25, 5, 9, 5, 7,
+ 7, 7, 9, 8, 8, 5, 7, 5, 6, 6, 24, 24, 6, 24, 12, 12,
+ 2, 2, 6, 5, 9, 21, 9, 2, 2, 9, 25, 9, 26, 12, 11, 11,
+ 2, 6, 5, 21, 17, 2, 2, 26, 26, 23, 2, 12, 17, 12, 21, 12,
+ 12, 21, 7, 2, 2, 7, 7, 21, 21, 2, 1, 1, 21, 23, 26, 26,
+ 1, 21, 6, 7, 7, 12, 12, 7, 21, 7, 12, 1, 12, 6, 6, 12,
+ 12, 26, 7, 26, 26, 7, 2, 1, 12, 2, 6, 2, 24, 7, 7, 6,
+ 1, 12, 12, 10, 10, 10, 10, 12, 21, 6, 2, 10, 10, 2, 15, 26,
+ 26, 2, 2, 21, 7, 10, 15, 7, 2, 23, 21, 26, 10, 7, 21, 15,
+ 15, 2, 17, 7, 29, 7, 7, 22, 18, 2, 14, 14, 14, 7, 10, 21,
+ 17, 21, 11, 12, 5, 2, 5, 6, 8, 8, 8, 24, 5, 24, 2, 24,
+ 9, 24, 24, 2, 29, 29, 29, 1, 17, 17, 20, 19, 22, 20, 27, 28,
+ 1, 29, 21, 20, 19, 21, 21, 16, 16, 21, 25, 22, 18, 21, 21, 29,
+ 1, 2, 15, 6, 18, 6, 23, 2, 12, 11, 9, 26, 26, 9, 26, 5,
+ 5, 26, 14, 9, 5, 14, 14, 15, 25, 26, 26, 22, 18, 26, 18, 25,
+ 18, 22, 5, 12, 2, 5, 22, 21, 21, 22, 18, 17, 26, 6, 7, 14,
+ 17, 22, 18, 18, 26, 14, 17, 6, 14, 6, 12, 24, 24, 6, 26, 15,
+ 6, 21, 11, 21, 24, 9, 6, 9, 23, 26, 6, 10, 4, 4, 3, 3,
+ 7, 25, 17, 16, 16, 22, 16, 16, 25, 17, 25, 2, 25, 24, 2, 15,
+ 12, 15, 14, 2, 21, 14, 7, 15, 12, 17, 21, 1, 26, 10, 10, 1,
+ 23, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12,
+ 13, 0, 14, 0, 0, 0, 0, 0, 15, 0, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
+ 0, 21, 22, 23, 0, 0, 0, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+ 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 34, 0, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 38, 0, 0, 0, 0,
+ 0, 0, 39, 40, 0, 0, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 5,
+ 6, 7, 0, 8, 9, 10, 0, 11, 12, 13, 14, 15, 16, 17, 16, 18,
+ 16, 19, 16, 19, 16, 19, 0, 19, 16, 20, 16, 19, 21, 19, 0, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 0, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35,
+ 0, 0, 36, 0, 37, 0, 0, 0, 38, 39, 40, 41, 42, 43, 44, 45,
+ 46, 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, 49, 0, 0, 0, 0,
+ 0, 0, 0, 50, 0, 51, 0, 52, 53, 0, 54, 0, 0, 0, 0, 0,
+ 0, 55, 56, 57, 0, 0, 0, 0, 58, 0, 0, 59, 60, 61, 62, 63,
+ 0, 0, 64, 65, 0, 0, 0, 66, 0, 0, 0, 0, 67, 0, 0, 0,
+ 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69,
+ 0, 0, 0, 70, 0, 71, 0, 0, 72, 0, 0, 73, 0, 0, 0, 0,
+ 0, 0, 0, 0, 74, 0, 0, 0, 0, 0, 75, 0, 0, 76, 77, 0,
+ 0, 78, 79, 0, 80, 62, 0, 81, 82, 0, 0, 83, 84, 85, 0, 0,
+ 0, 86, 0, 87, 0, 0, 51, 88, 51, 0, 89, 0, 90, 0, 0, 0,
+ 79, 0, 0, 0, 91, 92, 0, 93, 94, 95, 96, 0, 0, 0, 0, 0,
+ 51, 0, 0, 0, 0, 97, 98, 0, 0, 0, 0, 99,100, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,101, 0, 0,102, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,103,104, 0, 0,105, 0, 0, 0, 0, 0, 0,
+ 106, 0, 0, 0,100, 0, 0, 0, 0, 0,107,108, 0, 0, 0, 0,
+ 0, 0, 0,109, 0,110, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
+ 5, 6, 7, 0, 8, 0, 0, 0, 0, 9, 10, 11, 12, 0, 0, 0,
+ 0, 13, 0, 0, 14, 15, 0, 16, 0, 17, 18, 0, 0, 19, 0, 20,
+ 21, 0, 0, 0, 0, 0, 22, 23, 0, 24, 25, 0, 0, 26, 0, 0,
+ 0, 27, 0, 0, 28, 29, 30, 31, 0, 0, 0, 32, 33, 34, 0, 0,
+ 33, 0, 0, 35, 33, 0, 0, 0, 33, 36, 0, 0, 0, 0, 0, 37,
+ 38, 0, 0, 0, 0, 0, 0, 39, 40, 0, 0, 0, 0, 0, 0, 41,
+ 42, 0, 0, 0, 0, 43, 0, 44, 0, 0, 0, 45, 46, 0, 0, 0,
+ 47, 0, 0, 0, 0, 0, 0, 48, 49, 0, 0, 0, 0, 50, 0, 0,
+ 0, 51, 0, 52, 0, 53, 0, 0, 0, 0, 54, 0, 0, 0, 0, 55,
+ 0, 56, 0, 0, 0, 0, 57, 58, 0, 0, 0, 59, 60, 0, 0, 0,
+ 0, 0, 0, 61, 52, 0, 62, 63, 0, 0, 64, 0, 0, 0, 65, 66,
+ 0, 0, 0, 67, 0, 68, 69, 70, 71, 72, 1, 73, 0, 74, 75, 76,
+ 0, 0, 77, 78, 0, 0, 0, 79, 0, 0, 1, 1, 0, 0, 80, 0,
+ 0, 81, 0, 0, 0, 0, 77, 82, 0, 83, 0, 0, 0, 0, 0, 78,
+ 84, 0, 85, 0, 52, 0, 1, 78, 0, 0, 86, 0, 0, 87, 0, 0,
+ 0, 0, 0, 88, 57, 0, 0, 0, 0, 0, 0, 89, 90, 0, 0, 84,
+ 0, 0, 33, 0, 0, 91, 0, 0, 0, 0, 92, 0, 0, 0, 0, 49,
+ 0, 0, 93, 0, 0, 0, 0, 94, 95, 0, 0, 96, 0, 0, 97, 0,
+ 0, 0, 98, 0, 0, 0, 99, 0,100, 93, 0, 0,101, 0, 0, 0,
+ 84, 0, 0,102, 0, 0, 0,103,104, 0, 0,105,106, 0, 0, 0,
+ 0, 0, 0,107, 0, 0,108, 0, 0, 0, 0,109, 33, 0,110,111,
+ 112, 35, 0, 0,113, 0, 0, 0,114, 0, 0, 0, 0, 0, 0,115,
+ 0, 0,116, 0, 0, 0, 0,117, 88, 0, 0, 0, 0, 0, 57, 0,
+ 0, 0, 0, 52,118, 0, 0, 0, 0,119, 0, 0,120, 0, 0, 0,
+ 0,118, 0, 0, 0, 0, 0,121, 0, 0, 0,122, 0, 0, 0,123,
+ 0,124, 0, 0, 0, 0,125,126,127, 0,128, 0,129, 0, 0, 0,
+ 130,131,132, 0, 0, 0, 35, 0, 0, 0,133, 0, 0,134, 0, 0,
+ 135, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 3, 4,
+ 5, 6, 7, 4, 4, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17,
+ 18, 1, 1, 1, 19, 1, 0, 0, 20, 21, 22, 1, 23, 4, 21, 24,
+ 25, 26, 27, 28, 29, 30, 0, 0, 1, 1, 31, 0, 0, 0, 32, 33,
+ 34, 35, 1, 36, 37, 0, 0, 0, 0, 38, 1, 39, 14, 39, 40, 41,
+ 42, 0, 0, 0, 43, 36, 44, 45, 21, 45, 46, 0, 0, 0, 19, 1,
+ 21, 0, 0, 47, 0, 38, 48, 1, 1, 49, 49, 50, 0, 0, 51, 0,
+ 0, 0, 52, 1, 0, 0, 38, 14, 4, 1, 1, 1, 53, 21, 43, 52,
+ 54, 21, 35, 1, 0, 0, 0, 55, 0, 0, 0, 56, 57, 58, 0, 0,
+ 0, 0, 0, 59, 0, 60, 0, 0, 0, 0, 61, 62, 0, 0, 63, 0,
+ 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 66, 0, 0, 0, 67, 0,
+ 0, 0, 68, 0, 0, 69, 70, 0, 71, 72, 73, 74, 75, 76, 0, 0,
+ 0, 77, 0, 0, 0, 78, 79, 0, 0, 0, 0, 47, 0, 0, 0, 49,
+ 0, 80, 0, 0, 0, 62, 0, 0, 63, 0, 0, 81, 0, 0, 82, 0,
+ 0, 0, 83, 0, 0, 19, 84, 0, 62, 0, 0, 0, 0, 49, 1, 85,
+ 1, 52, 15, 86, 36, 10, 21, 87, 0, 55, 0, 0, 0, 0, 19, 10,
+ 1, 0, 0, 0, 0, 0, 88, 0, 0, 89, 0, 0, 88, 0, 0, 0,
+ 0, 78, 0, 0, 87, 9, 12, 4, 90, 8, 91, 47, 0, 58, 50, 0,
+ 21, 1, 21, 92, 93, 1, 1, 1, 1, 94, 95, 96, 97, 1, 98, 58,
+ 81, 99,100, 4, 58, 0, 0, 0, 0, 0, 0, 19, 50, 0, 0, 0,
+ 0, 0, 0, 61, 0, 0,101,102, 0, 0,103, 0, 0, 1, 1, 50,
+ 0, 0, 0, 38, 0, 63, 0, 0, 0, 0, 0, 62, 0, 0,104, 68,
+ 61, 0, 0, 0, 78, 0, 0, 0,105,106, 58, 38, 81, 0, 0, 0,
+ 0, 0, 0,107, 1, 14, 4, 12, 84, 0, 0, 0, 0, 38, 87, 0,
+ 0, 0, 0,108, 0, 0,109, 61, 0,110, 0, 0, 0, 1, 0, 0,
+ 0, 0, 19, 58, 0,111, 14, 52,112, 41, 0, 0, 62, 0, 0, 61,
+ 0, 0,113, 0, 87, 0, 0, 0, 61, 62, 0, 0, 62, 0, 89, 0,
+ 0,113, 0, 0, 0, 0,114, 0, 0, 0, 78, 55, 0, 38, 1, 58,
+ 1, 58, 0, 0, 63, 89, 0, 0,115, 0, 0, 0, 55, 0, 0, 0,
+ 0,115, 0, 0, 0, 0, 61, 0, 0, 0, 0, 79, 0, 61, 0, 0,
+ 0, 0, 56, 0, 89, 80, 0, 0, 8, 91, 0, 0, 1, 87, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0,117, 0,118,119,120,121, 0,104, 4,
+ 122, 49, 23, 0, 0, 0, 38, 50, 38, 58, 0, 0, 1, 87, 1, 1,
+ 1, 1, 39, 1, 48,105, 87, 0, 0, 0, 0, 1, 4,122, 0, 0,
+ 0, 1,123, 0, 0, 0, 0, 0,230,230,230,230,230,232,220,220,
+ 220,220,232,216,220,220,220,220,220,202,202,220,220,220,220,202,
+ 202,220,220,220, 1, 1, 1, 1, 1,220,220,220,220,230,230,230,
+ 230,240,230,220,220,220,230,230,230,220,220, 0,230,230,230,220,
+ 220,220,220,230,232,220,220,230,233,234,234,233,234,234,233,230,
+ 0, 0, 0,230, 0,220,230,230,230,230,220,230,230,230,222,220,
+ 230,230,220,220,230,222,228,230, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 19, 20, 21, 22, 0, 23, 0, 24, 25, 0,230,220, 0, 18,
+ 30, 31, 32, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34,230,
+ 230,220,220,230,220,230,230,220, 35, 0, 0, 0, 0, 0,230,230,
+ 230, 0, 0,230,230, 0,220,230,230,220, 0, 0, 0, 36, 0, 0,
+ 230,220,230,230,220,220,230,220,220,230,220,230,220,230,230, 0,
+ 0,220, 0, 0,230,230, 0,230, 0,230,230,230,230,230, 0, 0,
+ 0,220,220,220,230,220,220,220,230,230, 0,220, 27, 28, 29,230,
+ 7, 0, 0, 0, 0, 9, 0, 0, 0,230,220,230,230, 0, 0, 0,
+ 0, 0,230, 0, 0, 84, 91, 0, 0, 0, 0, 9, 9, 0, 0, 0,
+ 0, 0, 9, 0,103,103, 9, 0,107,107,107,107,118,118, 9, 0,
+ 122,122,122,122,220,220, 0, 0, 0,220, 0,220, 0,216, 0, 0,
+ 0,129,130, 0,132, 0, 0, 0, 0, 0,130,130,130,130, 0, 0,
+ 130, 0,230,230, 9, 0,230,230, 0, 0,220, 0, 0, 0, 0, 7,
+ 0, 9, 9, 0, 9, 9, 0, 0, 0,230, 0, 0, 0,228, 0, 0,
+ 0,222,230,220,220, 0, 0, 0,230, 0, 0,220,230,220, 0,220,
+ 230,230,230, 0, 0, 0, 9, 9, 0, 0, 7, 0,230, 0, 1, 1,
+ 1, 0, 0, 0,230,234,214,220,202,230,230,230,230,230,232,228,
+ 228,220,218,230,233,220,230,220,230,230, 1, 1, 1, 1, 1,230,
+ 0, 1, 1,230,220,230, 1, 1, 0, 0,218,228,232,222,224,224,
+ 0, 8, 8, 0, 0, 0, 0,220,230, 0,230,230,220, 0, 0,230,
+ 0, 0, 26, 0, 0,220, 0,230,230, 1,220, 0, 0,230,220, 0,
+ 0, 0,220,220, 0, 0,230,220, 0, 9, 7, 0, 0, 7, 9, 0,
+ 0, 0, 9, 7, 6, 6, 0, 0, 0, 0, 1, 0, 0,216,216, 1,
+ 1, 1, 0, 0, 0,226,216,216,216,216,216, 0,220,220,220, 0,
+ 230,230, 7, 0, 16, 17, 17, 17, 17, 17, 17, 33, 17, 17, 17, 19,
+ 17, 17, 17, 17, 20,101, 17,113,129,169, 17, 27, 28, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17,237, 0, 1, 2, 2, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 0, 6, 7, 8, 9, 0, 0, 0, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20,
+ 0, 0, 21, 22, 0, 0, 0, 0, 23, 24, 25, 26, 0, 27, 0, 28,
+ 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 33, 34, 35, 36, 0,
+ 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 38, 39,
+ 0, 0, 0, 0, 1, 2, 40, 41, 0, 1, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 3, 4, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+ 0, 0, 7, 1, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0,
+ 0, 0, 10, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 11, 12,
+ 0, 13, 0, 14, 15, 16, 0, 0, 0, 0, 0, 1, 17, 18, 0, 19,
+ 7, 1, 0, 0, 0, 20, 20, 7, 20, 20, 20, 20, 20, 20, 20, 8,
+ 21, 0, 22, 0, 7, 23, 24, 0, 20, 20, 25, 0, 0, 0, 26, 27,
+ 1, 7, 20, 20, 20, 20, 20, 1, 28, 29, 30, 31, 0, 0, 20, 0,
+ 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 20, 20,
+ 20, 1, 0, 0, 8, 21, 32, 4, 0, 10, 0, 33, 7, 20, 20, 20,
+ 0, 0, 0, 0, 8, 34, 34, 35, 36, 34, 37, 0, 38, 1, 20, 20,
+ 0, 0, 39, 0, 1, 1, 0, 8, 21, 1, 20, 0, 0, 0, 1, 0,
+ 0, 40, 1, 1, 0, 0, 8, 21, 0, 1, 0, 1, 0, 1, 0, 0,
+ 0, 0, 26, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 7, 20, 41,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 0, 42, 43, 44, 0, 45,
+ 0, 8, 21, 0, 0, 0, 0, 0, 0, 0, 0, 46, 7, 1, 10, 1,
+ 0, 0, 0, 1, 20, 20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 34, 9, 0, 0, 20, 20, 1, 20, 20, 0, 0, 0, 0, 0,
+ 0, 0, 26, 21, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 47, 48, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 10, 11, 11, 11, 11, 12, 13, 13, 13, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 13, 22, 13, 13, 13, 13, 23, 24, 24, 25, 26, 13, 13,
+ 13, 27, 28, 29, 13, 30, 31, 32, 33, 34, 35, 36, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 37, 7, 38, 39, 7, 40, 7, 7, 7, 41, 13, 42, 7, 7, 43, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 44, 0, 0, 1,
+ 2, 2, 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, 32, 33, 34, 35, 36, 37, 37, 37, 37, 37, 38, 39, 40, 41, 42,
+ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 2, 2, 53, 54, 55, 56,
+ 57, 58, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 61, 61,
+ 59, 59, 59, 59, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 77, 78, 59, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 79, 70, 70, 70, 70, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 81, 82, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, 93, 94, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 95, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 70, 70, 97, 98, 99,100,101,101,102,103,104,105,106,107,108,109,
+ 110,111, 96,112,113,114,115,116,117,118,119,119,120,121,122,123,
+ 124,125,126,127,128,129,130,131,132, 96,133,134,135,136,137,138,
+ 139,140,141,142,143, 96,144,145, 96,146,147,148,149, 96,150,151,
+ 152,153,154,155, 96, 96,156,157,158,159, 96,160, 96,161,162,162,
+ 162,162,162,162,162,163,164,162,165, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,166,167,167,
+ 167,167,167,167,167,167,168, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,169,169,169,169,170, 96, 96, 96,171,171,
+ 171,171,172,173,174,175, 96, 96, 96, 96,176,177,178,179,180,180,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,180,
+ 180,180,180,180,180,180,180,180,180,180,180,180,180,181,180,180,
+ 180,180,180,180,182,182,182,183,184, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,185,186,187,
+ 188,189,189,190, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96,191,192, 96, 96, 96, 96, 96, 96, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,193,194, 59,195,
+ 196,197,198,199,200, 96,201,202,203, 59, 59,204, 59,205,206,206,
+ 206,206,206,207, 96, 96, 96, 96, 96, 96, 96, 96,208, 96,209, 96,
+ 210, 96, 96,211, 96, 96, 96, 96, 96, 96, 96, 96, 96,212,213,214,
+ 215, 96, 96, 96, 96, 96,216,217,218, 96,219,220, 96, 96,221,222,
+ 59,223,224, 96, 59, 59, 59, 59, 59, 59, 59,225,226,227,228,229,
+ 59, 59,230,231, 59,232, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,233, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,234, 70,235, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,236, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70,237, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70,238, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 70, 70,
+ 70, 70, 70, 70,239, 96, 96, 96, 96, 96, 96, 96, 96, 96,240, 96,
+ 241,242, 0, 1, 2, 2, 0, 1, 2, 2, 2, 3, 4, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0, 0, 0,
+ 19, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19, 0, 19, 0,
+ 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 0, 0, 0, 0, 0,
+ 26, 26, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9,
+ 9, 9, 0, 9, 9, 9, 2, 2, 9, 9, 9, 9, 0, 9, 2, 2,
+ 2, 2, 9, 0, 9, 0, 9, 9, 9, 2, 9, 2, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 9,
+ 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 6, 2, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 2, 4, 4, 4, 2, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 2, 2,
+ 2, 2, 2, 2, 2, 2, 14, 14, 14, 2, 2, 2, 2, 14, 14, 14,
+ 14, 14, 14, 2, 2, 2, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3,
+ 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 0, 3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 1, 3,
+ 3, 3, 3, 3, 3, 3, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
+ 37, 37, 37, 37, 2, 37, 37, 37, 37, 2, 2, 37, 37, 37, 38, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 2, 2, 2, 2, 2, 2, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 2, 2, 64, 64, 64, 90, 90,
+ 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 2, 2, 90, 90,
+ 90, 90, 90, 90, 90, 2, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
+ 95, 95, 2, 2, 95, 2, 37, 37, 37, 2, 2, 2, 2, 2, 3, 3,
+ 3, 3, 3, 3, 3, 2, 3, 3, 2, 2, 2, 2, 2, 2, 3, 3,
+ 0, 3, 3, 3, 3, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 1,
+ 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, 5, 5,
+ 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5, 5, 2,
+ 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2,
+ 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 2, 2, 5, 5, 5, 5,
+ 2, 2, 5, 5, 5, 5, 5, 2, 2, 5, 5, 5, 5, 2, 2, 2,
+ 2, 2, 2, 2, 2, 5, 2, 2, 2, 2, 5, 5, 2, 5, 5, 5,
+ 5, 5, 2, 2, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 11,
+ 11, 11, 2, 11, 11, 11, 11, 11, 11, 2, 2, 2, 2, 11, 11, 2,
+ 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2,
+ 11, 11, 11, 11, 11, 11, 11, 2, 11, 11, 2, 11, 11, 2, 11, 11,
+ 2, 2, 11, 2, 11, 11, 11, 2, 2, 11, 11, 11, 2, 2, 2, 11,
+ 2, 2, 2, 2, 2, 2, 2, 11, 11, 11, 11, 2, 11, 2, 2, 2,
+ 2, 2, 2, 2, 11, 11, 11, 11, 11, 11, 11, 11, 11, 2, 2, 10,
+ 10, 10, 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10,
+ 2, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 2,
+ 10, 10, 10, 10, 10, 10, 10, 2, 10, 10, 2, 10, 10, 10, 10, 10,
+ 2, 2, 10, 10, 10, 10, 10, 10, 2, 10, 10, 10, 2, 2, 10, 2,
+ 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 2, 2, 10, 10, 10, 10,
+ 2, 2, 2, 2, 2, 2, 2, 10, 10, 10, 10, 10, 10, 10, 2, 21,
+ 21, 21, 2, 21, 21, 21, 21, 21, 21, 21, 21, 2, 2, 21, 21, 2,
+ 2, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 2,
+ 21, 21, 21, 21, 21, 21, 21, 2, 21, 21, 2, 21, 21, 21, 21, 21,
+ 2, 2, 21, 21, 21, 21, 21, 2, 2, 21, 21, 21, 2, 2, 2, 2,
+ 2, 2, 2, 21, 21, 21, 2, 2, 2, 2, 21, 21, 2, 21, 21, 21,
+ 21, 21, 2, 2, 21, 21, 2, 2, 22, 22, 2, 22, 22, 22, 22, 22,
+ 22, 2, 2, 2, 22, 22, 22, 2, 22, 22, 22, 22, 2, 2, 2, 22,
+ 22, 2, 22, 2, 22, 22, 2, 2, 2, 22, 22, 2, 2, 2, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 2, 2, 2, 2, 22, 22, 22, 2,
+ 2, 2, 2, 2, 2, 22, 2, 2, 2, 2, 2, 2, 22, 22, 22, 22,
+ 22, 2, 2, 2, 2, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 2, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23,
+ 2, 2, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 2, 2, 2, 2,
+ 2, 2, 2, 23, 23, 2, 23, 23, 23, 2, 2, 23, 2, 2, 23, 23,
+ 23, 23, 2, 2, 23, 23, 2, 2, 2, 2, 2, 2, 2, 23, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 2,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 16,
+ 2, 2, 16, 16, 16, 16, 16, 2, 16, 16, 16, 16, 2, 2, 2, 2,
+ 2, 2, 2, 16, 16, 2, 16, 16, 16, 16, 2, 2, 16, 16, 2, 16,
+ 16, 2, 2, 2, 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 2, 20, 20, 20, 2, 20, 20, 20, 20, 20, 20, 2, 2,
+ 2, 2, 20, 20, 20, 20, 20, 20, 20, 20, 2, 2, 20, 20, 2, 36,
+ 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 36, 36, 2, 2, 2, 36, 36, 36, 36, 36, 36, 36, 36,
+ 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2, 2,
+ 36, 2, 2, 2, 2, 36, 36, 36, 36, 36, 36, 2, 36, 2, 2, 2,
+ 2, 2, 2, 2, 36, 36, 2, 2, 36, 36, 36, 2, 2, 2, 2, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 2, 2, 2, 2, 0, 24, 24, 24, 24, 2, 2, 2, 2, 2, 18,
+ 18, 2, 18, 2, 18, 18, 18, 18, 18, 2, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18, 18,
+ 18, 18, 18, 18, 2, 2, 18, 18, 18, 18, 18, 2, 18, 2, 18, 18,
+ 2, 2, 18, 18, 18, 18, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 2, 2, 25, 25,
+ 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 25,
+ 25, 2, 2, 2, 2, 2, 33, 33, 33, 33, 33, 33, 33, 33, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 2, 8, 2, 2,
+ 2, 2, 2, 8, 2, 2, 8, 8, 8, 0, 8, 8, 8, 8, 12, 12,
+ 12, 12, 12, 12, 12, 12, 30, 30, 30, 30, 30, 30, 30, 30, 30, 2,
+ 30, 30, 30, 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 2, 30, 30,
+ 30, 2, 2, 30, 30, 30, 30, 30, 30, 30, 30, 2, 2, 2, 30, 30,
+ 2, 2, 2, 2, 2, 2, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 2, 2, 28, 28, 28, 28, 28, 28, 28, 28, 34, 34,
+ 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 2, 2, 2, 35, 35,
+ 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35, 35, 2,
+ 2, 2, 2, 2, 2, 2, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 2, 2, 2, 2, 2, 2, 2, 2, 2, 45, 44, 44,
+ 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 2, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 2, 2, 2, 2, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 2, 46, 46, 46, 2,
+ 46, 46, 2, 2, 2, 2, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 2, 2, 31, 31, 2, 2, 2, 2, 2, 2, 32, 32,
+ 0, 0, 32, 0, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
+ 2, 2, 2, 2, 2, 2, 32, 2, 2, 2, 2, 2, 2, 2, 32, 32,
+ 32, 2, 2, 2, 2, 2, 28, 28, 28, 28, 28, 28, 2, 2, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 2, 48, 48,
+ 48, 48, 2, 2, 2, 2, 48, 2, 2, 2, 48, 48, 48, 48, 52, 52,
+ 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 2, 2, 52, 52,
+ 52, 52, 52, 2, 2, 2, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 2, 2, 2, 2, 58, 58, 2, 2, 2, 2, 2, 2, 58, 58,
+ 58, 2, 2, 2, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 2, 2, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 2, 91, 91, 91, 91, 91, 2, 2, 91, 91, 91,
+ 2, 2, 2, 2, 2, 2, 91, 91, 91, 91, 91, 91, 2, 2, 1, 1,
+ 1, 1, 1, 1, 1, 2, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 2, 2, 2, 62, 62, 62, 62, 62, 62, 62, 2, 76, 76,
+ 76, 76, 76, 76, 76, 76, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
+ 93, 93, 2, 2, 2, 2, 2, 2, 2, 2, 93, 93, 93, 93, 70, 70,
+ 70, 70, 70, 70, 70, 70, 2, 2, 2, 70, 70, 70, 70, 70, 70, 70,
+ 2, 2, 2, 70, 70, 70, 73, 73, 73, 73, 73, 73, 73, 73, 6, 2,
+ 2, 2, 2, 2, 2, 2, 8, 8, 8, 2, 2, 8, 8, 8, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9,
+ 9, 6, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9, 9, 9,
+ 19, 19, 19, 19, 9, 9, 9, 9, 9, 19, 19, 19, 19, 19, 6, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 9, 9, 9,
+ 9, 9, 9, 9, 2, 2, 2, 9, 2, 9, 2, 9, 2, 9, 9, 9,
+ 9, 9, 9, 2, 9, 9, 9, 9, 9, 9, 2, 2, 9, 9, 9, 9,
+ 9, 9, 2, 9, 9, 9, 2, 2, 9, 9, 9, 2, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 19, 2, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 2, 19, 19,
+ 19, 19, 19, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0,
+ 19, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 19, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 27, 27,
+ 27, 27, 27, 27, 27, 27, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 56, 56, 56, 56, 56, 56, 56, 56, 55, 55,
+ 55, 55, 2, 2, 2, 2, 2, 55, 55, 55, 55, 55, 55, 55, 61, 61,
+ 61, 61, 61, 61, 61, 61, 2, 2, 2, 2, 2, 2, 2, 61, 61, 2,
+ 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 2, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 2, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 2, 2, 2, 2, 13, 13, 13, 13, 13, 13, 2, 2, 0, 0,
+ 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 13, 0, 13, 0, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 13, 13,
+ 13, 13, 0, 0, 0, 0, 2, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 2, 2, 1,
+ 1, 0, 0, 15, 15, 15, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 17, 17, 17, 2, 2,
+ 2, 2, 2, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 2, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 2, 12, 12,
+ 12, 12, 12, 12, 12, 0, 17, 17, 17, 17, 17, 17, 17, 0, 39, 39,
+ 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 2, 2, 2, 39, 39,
+ 39, 39, 39, 39, 39, 2, 86, 86, 86, 86, 86, 86, 86, 86, 77, 77,
+ 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 2, 2, 2, 2, 79, 79,
+ 79, 79, 79, 79, 79, 79, 0, 0, 19, 19, 19, 19, 19, 19, 0, 0,
+ 0, 19, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 19, 19,
+ 2, 19, 2, 19, 19, 19, 19, 19, 2, 2, 2, 2, 2, 2, 2, 2,
+ 19, 19, 19, 19, 19, 19, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
+ 60, 60, 60, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 65, 65,
+ 65, 65, 65, 65, 65, 65, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75,
+ 75, 75, 75, 75, 2, 2, 2, 2, 2, 2, 2, 2, 75, 75, 75, 75,
+ 2, 2, 2, 2, 2, 2, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
+ 69, 69, 69, 69, 0, 69, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+ 74, 74, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 74, 12, 12,
+ 12, 12, 12, 2, 2, 2, 84, 84, 84, 84, 84, 84, 84, 84, 84, 84,
+ 84, 84, 84, 84, 2, 0, 84, 84, 2, 2, 2, 2, 84, 84, 33, 33,
+ 33, 33, 33, 33, 33, 2, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
+ 68, 68, 68, 68, 68, 2, 68, 68, 68, 68, 68, 68, 2, 2, 68, 68,
+ 2, 2, 68, 68, 68, 68, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 2, 2, 2, 2, 2, 2, 2, 2, 92, 92, 92, 92, 92, 87, 87,
+ 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 2, 2, 30,
+ 30, 30, 30, 30, 30, 2, 19, 19, 19, 0, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 9, 19, 19, 19, 19, 0, 0, 2, 2, 2, 2, 87, 87,
+ 87, 87, 87, 87, 2, 2, 87, 87, 2, 2, 2, 2, 2, 2, 12, 12,
+ 12, 12, 2, 2, 2, 2, 2, 2, 2, 12, 12, 12, 12, 12, 13, 13,
+ 2, 2, 2, 2, 2, 2, 19, 19, 19, 19, 19, 19, 19, 2, 2, 2,
+ 2, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 2, 14, 14, 14, 14, 14, 2, 14, 2, 14, 14,
+ 2, 14, 14, 2, 14, 14, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 2, 2,
+ 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 1, 1,
+ 1, 1, 1, 1, 6, 6, 0, 0, 0, 2, 0, 0, 0, 0, 3, 3,
+ 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 17, 17, 17,
+ 17, 17, 17, 17, 0, 0, 2, 2, 12, 12, 12, 12, 12, 12, 2, 2,
+ 12, 12, 12, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 2, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 2, 49, 49, 49, 2, 49, 49, 2, 49, 49, 49,
+ 49, 49, 49, 49, 2, 2, 49, 49, 49, 2, 2, 2, 2, 2, 0, 0,
+ 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0,
+ 0, 0, 0, 2, 2, 2, 9, 2, 2, 2, 2, 2, 2, 2, 0, 0,
+ 0, 0, 0, 1, 2, 2, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
+ 71, 71, 71, 2, 2, 2, 67, 67, 67, 67, 67, 67, 67, 67, 67, 2,
+ 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 42, 42, 42, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 2, 2, 2, 2, 2,118,118,118,118,118,118,118,118,118,118,
+ 118, 2, 2, 2, 2, 2, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 53, 53, 53, 53, 2, 53, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 2, 2, 2, 2, 59, 59, 59, 59, 59, 59, 2, 2, 40, 40,
+ 40, 40, 40, 40, 40, 40, 51, 51, 51, 51, 51, 51, 51, 51, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 2, 2, 50, 50,
+ 2, 2, 2, 2, 2, 2,135,135,135,135,135,135,135,135,135,135,
+ 135,135, 2, 2, 2, 2,106,106,106,106,106,106,106,106,104,104,
+ 104,104,104,104,104,104,104,104,104,104, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2,104,161,161,161,161,161,161,161,161,161,161,
+ 161, 2,161,161,161,161,161,161,161, 2,161,161, 2,161,161,161,
+ 2,161,161,161,161,161,161,161, 2,161,161, 2, 2, 2,110,110,
+ 110,110,110,110,110,110,110,110,110,110,110,110,110, 2,110,110,
+ 110,110,110,110, 2, 2, 19, 19, 19, 19, 19, 19, 2, 19, 19, 2,
+ 19, 19, 19, 19, 19, 19, 47, 47, 47, 47, 47, 47, 2, 2, 47, 2,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 2, 47, 47, 2, 2, 2, 47, 2, 2, 47, 81, 81,
+ 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 2, 81,120,120,
+ 120,120,120,120,120,120,116,116,116,116,116,116,116,116,116,116,
+ 116,116,116,116,116, 2, 2, 2, 2, 2, 2, 2, 2,116,128,128,
+ 128,128,128,128,128,128,128,128,128, 2,128,128, 2, 2, 2, 2,
+ 2,128,128,128,128,128, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 2, 2, 2, 66, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 2, 2, 2, 2, 2, 72, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97,
+ 97, 97, 97, 97, 97, 97, 2, 2, 2, 2, 97, 97, 97, 97, 2, 2,
+ 97, 97, 97, 97, 97, 97, 57, 57, 57, 57, 2, 57, 57, 2, 2, 2,
+ 2, 2, 57, 57, 57, 57, 57, 57, 57, 57, 2, 57, 57, 57, 2, 57,
+ 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 57, 57, 2, 2, 57, 57, 57, 2, 2, 2, 2, 57, 57, 2,
+ 2, 2, 2, 2, 2, 2, 88, 88, 88, 88, 88, 88, 88, 88,117,117,
+ 117,117,117,117,117,117,112,112,112,112,112,112,112,112,112,112,
+ 112,112,112,112,112, 2, 2, 2, 2,112,112,112,112,112, 78, 78,
+ 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 2, 2, 2, 78,
+ 78, 78, 78, 78, 78, 78, 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
+ 83, 83, 83, 83, 2, 2, 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 2, 2, 2, 2, 2,122,122,122,122,122,122,122,122,122,122,
+ 2, 2, 2, 2, 2, 2, 2,122,122,122,122, 2, 2, 2, 2,122,
+ 122,122,122,122,122,122, 89, 89, 89, 89, 89, 89, 89, 89, 89, 2,
+ 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,130,130,130,130,
+ 130, 2, 2, 2, 2, 2, 2, 2,130,130,130,130,130,130,144,144,
+ 144,144,144,144,144,144,144,144, 2, 2, 2, 2, 2, 2,156,156,
+ 156,156,156,156,156,156,156,156, 2,156,156,156, 2, 2,156,156,
+ 2, 2, 2, 2, 2, 2,147,147,147,147,147,147,147,147,148,148,
+ 148,148,148,148,148,148,148,148, 2, 2, 2, 2, 2, 2,158,158,
+ 158,158,158,158,158,158,158,158, 2, 2, 2, 2, 2, 2,153,153,
+ 153,153,153,153,153,153,153,153,153,153, 2, 2, 2, 2,149,149,
+ 149,149,149,149,149,149,149,149,149,149,149,149,149, 2, 94, 94,
+ 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 2, 2, 2, 2,
+ 94, 94, 94, 94, 94, 94, 2, 2, 2, 2, 2, 2, 2, 94, 85, 85,
+ 85, 85, 85, 85, 85, 85, 85, 85, 85, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 85, 2, 2,101,101,101,101,101,101,101,101,101, 2,
+ 2, 2, 2, 2, 2, 2,101,101, 2, 2, 2, 2, 2, 2, 96, 96,
+ 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 2, 96, 96,111,111,
+ 111,111,111,111,111,111,111,111,111,111,111,111,111, 2,100,100,
+ 100,100,100,100,100,100, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36,
+ 36, 36, 36, 2, 2, 2,108,108,108,108,108,108,108,108,108,108,
+ 2,108,108,108,108,108,108,108,108,108,108,108,108, 2,129,129,
+ 129,129,129,129,129, 2,129, 2,129,129,129,129, 2,129,129,129,
+ 129,129,129,129,129,129,129,129,129,129,129,129, 2,129,129,129,
+ 2, 2, 2, 2, 2, 2,109,109,109,109,109,109,109,109,109,109,
+ 109, 2, 2, 2, 2, 2,109,109, 2, 2, 2, 2, 2, 2,107,107,
+ 107,107, 2,107,107,107,107,107,107,107,107, 2, 2,107,107, 2,
+ 2,107,107,107,107,107,107,107,107,107,107,107,107,107,107, 2,
+ 107,107,107,107,107,107,107, 2,107,107, 2,107,107,107,107,107,
+ 2, 1,107,107,107,107,107, 2, 2,107,107,107, 2, 2,107, 2,
+ 2, 2, 2, 2, 2,107, 2, 2, 2, 2, 2,107,107,107,107,107,
+ 107,107, 2, 2,107,107,107,107,107,107,107, 2, 2, 2,137,137,
+ 137,137,137,137,137,137,137,137,137,137, 2,137,137,137,137,137,
+ 2, 2, 2, 2, 2, 2,124,124,124,124,124,124,124,124,124,124,
+ 2, 2, 2, 2, 2, 2,123,123,123,123,123,123,123,123,123,123,
+ 123,123,123,123, 2, 2,114,114,114,114,114,114,114,114,114,114,
+ 114,114,114, 2, 2, 2,114,114, 2, 2, 2, 2, 2, 2, 32, 32,
+ 32, 32, 32, 2, 2, 2,102,102,102,102,102,102,102,102,102,102,
+ 2, 2, 2, 2, 2, 2,126,126,126,126,126,126,126,126,126,126,
+ 126, 2, 2,126,126,126,126,126,126,126, 2, 2, 2, 2,126,126,
+ 126,126,126,126,126, 2,142,142,142,142,142,142,142,142,142,142,
+ 142,142, 2, 2, 2, 2,125,125,125,125,125,125,125,125,125,125,
+ 125, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,125,154,154,
+ 154,154,154,154,154, 2, 2,154, 2, 2,154,154,154,154,154,154,
+ 154,154, 2,154,154, 2,154,154,154,154,154,154,154,154,154,154,
+ 154,154,154,154, 2,154,154, 2, 2,154,154,154,154,154,154,154,
+ 2, 2, 2, 2, 2, 2,150,150,150,150,150,150,150,150, 2, 2,
+ 150,150,150,150,150,150,150,150,150,150,150, 2, 2, 2,141,141,
+ 141,141,141,141,141,141,140,140,140,140,140,140,140,140,140,140,
+ 140, 2, 2, 2, 2, 2,121,121,121,121,121,121,121,121,121, 2,
+ 2, 2, 2, 2, 2, 2,133,133,133,133,133,133,133,133,133, 2,
+ 133,133,133,133,133,133,133,133,133,133,133,133,133, 2,133,133,
+ 133,133,133,133, 2, 2,133,133,133,133,133, 2, 2, 2,134,134,
+ 134,134,134,134,134,134, 2, 2,134,134,134,134,134,134, 2,134,
+ 134,134,134,134,134,134,134,134,134,134,134,134,134, 2,138,138,
+ 138,138,138,138,138, 2,138,138, 2,138,138,138,138,138,138,138,
+ 138,138,138,138,138,138, 2, 2,138, 2,138,138, 2,138,138,138,
+ 2, 2, 2, 2, 2, 2,143,143,143,143,143,143, 2,143,143, 2,
+ 143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,143,
+ 143,143,143,143,143, 2,143,143, 2,143,143,143,143,143,143, 2,
+ 2, 2, 2, 2, 2, 2,143,143, 2, 2, 2, 2, 2, 2,145,145,
+ 145,145,145,145,145,145,145, 2, 2, 2, 2, 2, 2, 2, 86, 2,
+ 2, 2, 2, 2, 2, 2, 22, 22, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 22, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63,
+ 2, 2, 2, 2, 2, 2, 63, 63, 63, 63, 63, 63, 63, 2, 63, 63,
+ 63, 63, 63, 2, 2, 2, 63, 63, 63, 63, 2, 2, 2, 2,157,157,
+ 157,157,157,157,157,157,157,157,157, 2, 2, 2, 2, 2, 80, 80,
+ 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 2, 80, 2,
+ 2, 2, 2, 2, 2, 2,127,127,127,127,127,127,127,127,127,127,
+ 127,127,127,127,127, 2, 79, 2, 2, 2, 2, 2, 2, 2,115,115,
+ 115,115,115,115,115,115,115,115,115,115,115,115,115, 2,115,115,
+ 2, 2, 2, 2,115,115,159,159,159,159,159,159,159,159,159,159,
+ 159,159,159,159,159, 2,159,159, 2, 2, 2, 2, 2, 2,103,103,
+ 103,103,103,103,103,103,103,103,103,103,103,103, 2, 2,119,119,
+ 119,119,119,119,119,119,119,119,119,119,119,119, 2, 2,119,119,
+ 2,119,119,119,119,119, 2, 2, 2, 2, 2,119,119,119,146,146,
+ 146,146,146,146,146,146,146,146,146, 2, 2, 2, 2, 2, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99, 99, 2, 2, 2, 2, 99, 2, 2,
+ 2, 2, 2, 2, 2, 99,136,139, 13, 13,155, 2, 2, 2,136,136,
+ 136,136,136,136,136,136,155,155,155,155,155,155,155,155,155,155,
+ 155,155,155,155, 2, 2,136, 2, 2, 2, 2, 2, 2, 2, 17, 17,
+ 17, 17, 2, 17, 17, 17, 17, 17, 17, 17, 2, 17, 17, 2, 17, 15,
+ 15, 15, 15, 15, 15, 15, 17, 17, 17, 2, 2, 2, 2, 2, 15, 15,
+ 15, 2, 2, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17,139,139,
+ 139,139,139,139,139,139,139,139,139,139, 2, 2, 2, 2,105,105,
+ 105,105,105,105,105,105,105,105,105, 2, 2, 2, 2, 2,105,105,
+ 105,105,105, 2, 2, 2,105, 2, 2, 2, 2, 2, 2, 2,105,105,
+ 2, 2,105,105,105,105, 1, 1, 1, 1, 1, 1, 2, 2, 0, 0,
+ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 2, 2,
+ 0, 2, 2, 0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0,131,131,131,131,131,131,131,131,131,131,
+ 131,131, 2, 2, 2, 2, 2, 2, 2,131,131,131,131,131, 2,131,
+ 131,131,131,131,131,131, 56, 56, 56, 56, 56, 56, 56, 2, 56, 2,
+ 2, 56, 56, 56, 56, 56, 56, 56, 2, 56, 56, 2, 56, 56, 56, 56,
+ 56, 2, 2, 2, 2, 2,151,151,151,151,151,151,151,151,151,151,
+ 151,151,151, 2, 2, 2,151,151,151,151,151,151, 2, 2,151,151,
+ 2, 2, 2, 2,151,151,160,160,160,160,160,160,160,160,160,160,
+ 160,160,160,160,160, 2,152,152,152,152,152,152,152,152,152,152,
+ 2, 2, 2, 2, 2,152, 30, 30, 30, 30, 2, 30, 30, 2,113,113,
+ 113,113,113,113,113,113,113,113,113,113,113, 2, 2,113,113,113,
+ 113,113,113,113,113, 2,132,132,132,132,132,132,132,132,132,132,
+ 132,132, 2, 2, 2, 2,132,132, 2, 2, 2, 2,132,132, 3, 3,
+ 3, 3, 2, 3, 3, 3, 2, 3, 3, 2, 3, 2, 2, 3, 2, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 3,
+ 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 2, 3,
+ 2, 3, 2, 3, 3, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,
+ 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 3, 3, 2, 2,
+ 2, 2, 2, 2, 0, 0, 15, 0, 0, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 0, 0, 0, 13, 2, 2, 2, 2, 2, 2, 2, 13, 13,
+ 13, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11, 12, 13,
+ 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
+ 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32, 0, 33,
+ 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44,
+ 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0, 0, 48,
+ 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0, 66, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68, 0, 69,
+ 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 97, 98, 99,100,101,102,103, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,104, 0,
+ 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,109, 0,
+ 110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,116, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,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, 0, 0, 0,158,159,160,
+ 161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,164, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,168,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,175,176,
+ 177,178,179,180,181,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, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
+};
+static const uint16_t
+_hb_ucd_u16[9200] =
+{
+ 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 10, 11, 12,
+ 13, 13, 13, 14, 15, 13, 13, 16, 17, 18, 19, 20, 21, 22, 13, 23,
+ 13, 13, 13, 24, 25, 11, 11, 11, 11, 26, 11, 27, 28, 29, 30, 31,
+ 32, 32, 32, 32, 32, 32, 32, 33, 34, 35, 36, 11, 37, 38, 13, 39,
+ 9, 9, 9, 11, 11, 11, 13, 13, 40, 13, 13, 13, 41, 13, 13, 13,
+ 13, 13, 13, 42, 9, 43, 11, 11, 44, 45, 32, 46, 47, 48, 49, 50,
+ 51, 52, 48, 48, 53, 32, 54, 55, 48, 48, 48, 48, 48, 56, 57, 58,
+ 59, 60, 48, 32, 61, 48, 48, 48, 48, 48, 62, 63, 64, 48, 65, 66,
+ 48, 67, 68, 69, 48, 70, 71, 48, 72, 73, 48, 48, 74, 32, 75, 32,
+ 76, 48, 48, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+ 90, 83, 84, 91, 92, 93, 94, 95, 96, 97, 84, 98, 99, 100, 88, 101,
+ 102, 83, 84, 103, 104, 105, 88, 106, 107, 108, 109, 110, 111, 112, 94, 113,
+ 114, 115, 84, 116, 117, 118, 88, 119, 120, 115, 84, 121, 122, 123, 88, 124,
+ 125, 115, 48, 126, 127, 128, 88, 129, 130, 131, 48, 132, 133, 134, 94, 135,
+ 136, 48, 48, 137, 138, 139, 140, 140, 141, 48, 142, 143, 144, 145, 140, 140,
+ 146, 147, 148, 149, 150, 48, 151, 152, 153, 154, 32, 155, 156, 157, 140, 140,
+ 48, 48, 158, 159, 160, 161, 162, 163, 164, 165, 9, 9, 166, 11, 11, 167,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 168, 169, 48, 48,
+ 168, 48, 48, 170, 171, 172, 48, 48, 48, 171, 48, 48, 48, 173, 174, 175,
+ 48, 176, 9, 9, 9, 9, 9, 177, 178, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 179, 48, 180, 181, 48, 48, 48, 48, 182, 183,
+ 48, 184, 48, 185, 48, 186, 187, 188, 48, 48, 48, 189, 190, 191, 192, 193,
+ 194, 192, 48, 48, 195, 48, 48, 196, 197, 48, 198, 48, 48, 48, 48, 199,
+ 48, 200, 201, 202, 203, 48, 204, 205, 48, 48, 206, 48, 207, 208, 209, 209,
+ 48, 210, 48, 48, 48, 211, 212, 213, 192, 192, 214, 215, 216, 140, 140, 140,
+ 217, 48, 48, 218, 219, 160, 220, 221, 222, 48, 223, 64, 48, 48, 224, 225,
+ 48, 48, 226, 227, 228, 64, 48, 229, 230, 9, 9, 231, 232, 233, 234, 235,
+ 11, 11, 236, 27, 27, 27, 237, 238, 11, 239, 27, 27, 32, 32, 32, 32,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 240, 13, 13, 13, 13, 13, 13,
+ 241, 242, 241, 241, 242, 243, 241, 244, 245, 245, 245, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 261, 262, 263, 264, 265,
+ 266, 267, 268, 269, 270, 271, 272, 272, 273, 274, 275, 209, 276, 277, 209, 278,
+ 279, 279, 279, 279, 279, 279, 279, 279, 280, 209, 281, 209, 209, 209, 209, 282,
+ 209, 283, 279, 284, 209, 285, 286, 209, 209, 209, 287, 140, 288, 140, 271, 271,
+ 271, 289, 209, 209, 209, 209, 290, 271, 209, 209, 209, 209, 209, 209, 209, 209,
+ 209, 209, 209, 291, 292, 209, 209, 293, 209, 209, 209, 209, 209, 209, 294, 209,
+ 209, 209, 209, 209, 209, 209, 295, 296, 271, 297, 209, 209, 298, 279, 299, 279,
+ 300, 301, 279, 279, 279, 302, 279, 303, 209, 209, 209, 279, 304, 209, 209, 305,
+ 209, 306, 209, 209, 209, 209, 209, 209, 9, 9, 9, 11, 11, 11, 307, 308,
+ 13, 13, 13, 13, 13, 13, 309, 310, 11, 11, 311, 48, 48, 48, 312, 313,
+ 48, 314, 315, 315, 315, 315, 32, 32, 316, 317, 318, 319, 320, 321, 140, 140,
+ 209, 322, 209, 209, 209, 209, 209, 323, 209, 209, 209, 209, 209, 324, 140, 325,
+ 326, 327, 328, 329, 136, 48, 48, 48, 48, 330, 178, 48, 48, 48, 48, 331,
+ 332, 48, 48, 136, 48, 48, 48, 48, 200, 333, 48, 48, 209, 209, 323, 48,
+ 209, 334, 335, 209, 336, 337, 209, 209, 335, 209, 209, 337, 209, 209, 209, 209,
+ 48, 48, 48, 48, 209, 209, 209, 209, 48, 338, 48, 48, 48, 48, 48, 48,
+ 151, 209, 209, 209, 287, 48, 48, 229, 339, 48, 340, 140, 13, 13, 341, 342,
+ 13, 343, 48, 48, 48, 48, 344, 345, 31, 346, 347, 348, 13, 13, 13, 349,
+ 350, 351, 352, 353, 354, 355, 140, 356, 357, 48, 358, 359, 48, 48, 48, 360,
+ 361, 48, 48, 362, 363, 192, 32, 364, 64, 48, 365, 48, 366, 367, 48, 151,
+ 76, 48, 48, 368, 369, 370, 371, 372, 48, 48, 373, 374, 375, 376, 48, 377,
+ 48, 48, 48, 378, 379, 380, 381, 382, 383, 384, 315, 11, 11, 385, 386, 11,
+ 11, 11, 11, 11, 48, 48, 387, 192, 48, 48, 388, 48, 389, 48, 48, 206,
+ 390, 390, 390, 390, 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, 391, 391,
+ 48, 48, 48, 48, 48, 48, 204, 48, 48, 48, 48, 48, 48, 207, 140, 140,
+ 392, 393, 394, 395, 396, 48, 48, 48, 48, 48, 48, 397, 398, 399, 48, 48,
+ 48, 48, 48, 400, 209, 48, 48, 48, 48, 401, 48, 48, 402, 140, 140, 403,
+ 32, 404, 32, 405, 406, 407, 408, 409, 48, 48, 48, 48, 48, 48, 48, 410,
+ 411, 2, 3, 4, 5, 412, 413, 414, 48, 415, 48, 200, 416, 417, 418, 419,
+ 420, 48, 172, 421, 204, 204, 140, 140, 48, 48, 48, 48, 48, 48, 48, 71,
+ 422, 271, 271, 423, 272, 272, 272, 424, 425, 426, 427, 140, 140, 209, 209, 428,
+ 140, 140, 140, 140, 140, 140, 140, 140, 48, 151, 48, 48, 48, 100, 429, 430,
+ 48, 48, 431, 48, 432, 48, 48, 433, 48, 434, 48, 48, 435, 436, 140, 140,
+ 9, 9, 437, 11, 11, 48, 48, 48, 48, 204, 192, 9, 9, 438, 11, 439,
+ 48, 48, 440, 48, 48, 48, 441, 442, 442, 443, 444, 445, 140, 140, 140, 140,
+ 48, 48, 48, 314, 48, 199, 440, 140, 446, 27, 27, 447, 140, 140, 140, 140,
+ 448, 48, 48, 449, 48, 450, 48, 451, 48, 200, 452, 140, 140, 140, 48, 453,
+ 48, 454, 48, 455, 140, 140, 140, 140, 48, 48, 48, 456, 271, 457, 271, 271,
+ 458, 459, 48, 460, 461, 462, 48, 463, 48, 464, 140, 140, 465, 48, 466, 467,
+ 48, 48, 48, 468, 48, 469, 48, 470, 48, 471, 472, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 196, 140, 140, 140, 9, 9, 9, 473, 11, 11, 11, 474,
+ 48, 48, 475, 192, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 271, 476,
+ 48, 48, 477, 478, 140, 140, 140, 140, 48, 464, 479, 48, 62, 480, 140, 48,
+ 481, 140, 140, 48, 482, 140, 48, 314, 483, 48, 48, 484, 485, 457, 486, 487,
+ 222, 48, 48, 488, 489, 48, 196, 192, 490, 48, 491, 492, 493, 48, 48, 494,
+ 222, 48, 48, 495, 496, 497, 498, 499, 48, 97, 500, 501, 140, 140, 140, 140,
+ 502, 503, 504, 48, 48, 505, 506, 192, 507, 83, 84, 508, 509, 510, 511, 512,
+ 48, 48, 48, 513, 514, 515, 478, 140, 48, 48, 48, 516, 517, 192, 140, 140,
+ 48, 48, 518, 519, 520, 521, 140, 140, 48, 48, 48, 522, 523, 192, 524, 140,
+ 48, 48, 525, 526, 192, 140, 140, 140, 48, 173, 527, 528, 314, 140, 140, 140,
+ 48, 48, 500, 529, 140, 140, 140, 140, 140, 140, 9, 9, 11, 11, 148, 530,
+ 531, 532, 48, 533, 534, 192, 140, 140, 140, 140, 535, 48, 48, 536, 537, 140,
+ 538, 48, 48, 539, 540, 541, 48, 48, 542, 543, 544, 48, 48, 48, 48, 196,
+ 84, 48, 518, 545, 546, 148, 175, 547, 48, 548, 549, 550, 140, 140, 140, 140,
+ 551, 48, 48, 552, 553, 192, 554, 48, 555, 556, 192, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 48, 557, 140, 140, 140, 100, 271, 558, 559, 560,
+ 48, 207, 140, 140, 140, 140, 140, 140, 272, 272, 272, 272, 272, 272, 561, 562,
+ 48, 48, 48, 48, 388, 140, 140, 140, 140, 48, 48, 48, 48, 48, 48, 563,
+ 48, 48, 200, 564, 140, 140, 140, 140, 48, 48, 48, 48, 314, 140, 140, 140,
+ 48, 48, 48, 196, 48, 200, 370, 48, 48, 48, 48, 200, 192, 48, 204, 565,
+ 48, 48, 48, 566, 567, 568, 569, 570, 48, 140, 140, 140, 140, 140, 140, 140,
+ 140, 140, 140, 140, 9, 9, 11, 11, 271, 571, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 572, 573, 574, 574, 575, 576, 140, 140, 140, 140, 577, 578,
+ 48, 48, 48, 48, 48, 48, 48, 440, 48, 48, 48, 48, 48, 199, 140, 140,
+ 196, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 579,
+ 48, 48, 580, 140, 140, 580, 581, 48, 48, 48, 48, 48, 48, 48, 48, 206,
+ 48, 48, 48, 48, 48, 48, 71, 151, 196, 582, 583, 140, 140, 140, 140, 140,
+ 32, 32, 584, 32, 585, 209, 209, 209, 209, 209, 209, 209, 323, 140, 140, 140,
+ 209, 209, 209, 209, 209, 209, 209, 324, 209, 209, 586, 209, 209, 209, 587, 588,
+ 589, 209, 590, 209, 209, 209, 288, 140, 209, 209, 209, 209, 591, 140, 140, 140,
+ 140, 140, 140, 140, 140, 140, 271, 592, 209, 209, 209, 209, 209, 287, 271, 461,
+ 9, 593, 11, 594, 595, 596, 241, 9, 597, 598, 599, 600, 601, 9, 593, 11,
+ 602, 603, 11, 604, 605, 606, 607, 9, 608, 11, 9, 593, 11, 594, 595, 11,
+ 241, 9, 597, 607, 9, 608, 11, 9, 593, 11, 609, 9, 610, 611, 612, 613,
+ 11, 614, 9, 615, 616, 617, 618, 11, 619, 9, 620, 11, 621, 622, 622, 622,
+ 32, 32, 32, 623, 32, 32, 624, 625, 626, 627, 45, 140, 140, 140, 140, 140,
+ 628, 629, 140, 140, 140, 140, 140, 140, 630, 631, 632, 140, 140, 140, 140, 140,
+ 48, 48, 151, 633, 634, 140, 140, 140, 140, 48, 635, 140, 48, 48, 636, 637,
+ 140, 140, 140, 140, 140, 140, 638, 200, 48, 48, 48, 48, 639, 585, 140, 140,
+ 9, 9, 597, 11, 640, 370, 140, 140, 140, 140, 140, 140, 140, 140, 140, 498,
+ 271, 271, 641, 642, 140, 140, 140, 140, 498, 271, 643, 644, 140, 140, 140, 140,
+ 645, 48, 646, 647, 648, 649, 650, 651, 652, 206, 653, 206, 140, 140, 140, 654,
+ 209, 209, 325, 209, 209, 209, 209, 209, 209, 323, 334, 655, 655, 655, 209, 324,
+ 656, 209, 209, 209, 209, 209, 209, 209, 209, 209, 657, 140, 140, 140, 658, 209,
+ 659, 209, 209, 325, 660, 661, 324, 140, 209, 209, 209, 209, 209, 209, 209, 662,
+ 209, 209, 209, 209, 209, 663, 426, 426, 209, 209, 209, 209, 209, 209, 209, 323,
+ 209, 209, 209, 209, 209, 660, 325, 427, 325, 209, 209, 209, 664, 176, 209, 209,
+ 664, 209, 657, 661, 140, 140, 140, 140, 209, 209, 209, 209, 209, 323, 657, 665,
+ 287, 209, 426, 288, 324, 176, 664, 287, 209, 666, 209, 209, 288, 140, 140, 192,
+ 48, 48, 48, 48, 48, 48, 140, 140, 48, 48, 48, 196, 48, 48, 48, 48,
+ 48, 204, 48, 48, 48, 48, 48, 48, 48, 48, 478, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 100, 140, 48, 204, 140, 140, 140, 140, 140, 140,
+ 48, 48, 48, 48, 71, 140, 140, 140, 667, 140, 668, 668, 668, 668, 668, 668,
+ 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 140,
+ 391, 391, 391, 391, 391, 391, 391, 669, 391, 391, 391, 391, 391, 391, 391, 670,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3,
+ 0, 0, 0, 0, 0, 4, 0, 4, 2, 2, 5, 2, 2, 2, 5, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 6, 0, 0, 0, 0, 7, 8, 0, 0,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 11,
+ 12, 13, 14, 14, 15, 14, 14, 14, 14, 14, 14, 14, 16, 17, 14, 14,
+ 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 20, 21, 21, 21, 22, 20, 21, 21, 21, 21,
+ 21, 23, 24, 25, 25, 25, 25, 25, 25, 26, 25, 25, 25, 27, 28, 26,
+ 29, 30, 31, 32, 31, 31, 31, 31, 33, 34, 35, 31, 31, 31, 36, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 29, 31, 31, 31, 31,
+ 37, 38, 37, 37, 37, 37, 37, 37, 37, 39, 31, 31, 31, 31, 31, 31,
+ 40, 40, 40, 40, 40, 40, 41, 26, 42, 42, 42, 42, 42, 42, 42, 43,
+ 44, 44, 44, 44, 44, 45, 44, 46, 47, 47, 47, 48, 37, 49, 31, 31,
+ 31, 50, 51, 31, 31, 31, 31, 31, 31, 31, 31, 31, 52, 31, 31, 31,
+ 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 53, 55, 53, 53, 53,
+ 56, 57, 58, 59, 59, 60, 61, 62, 57, 63, 64, 65, 66, 59, 59, 67,
+ 68, 69, 70, 71, 71, 72, 73, 74, 69, 75, 76, 77, 78, 71, 79, 26,
+ 80, 81, 82, 83, 83, 84, 85, 86, 81, 87, 88, 26, 89, 83, 90, 91,
+ 92, 93, 94, 95, 95, 96, 97, 98, 93, 99, 100, 101, 102, 95, 95, 26,
+ 103, 104, 105, 106, 107, 104, 108, 109, 104, 105, 110, 26, 111, 108, 108, 112,
+ 113, 114, 115, 113, 113, 115, 113, 116, 114, 117, 118, 119, 120, 113, 121, 113,
+ 122, 123, 124, 122, 122, 124, 125, 126, 123, 127, 128, 128, 129, 122, 130, 26,
+ 131, 132, 133, 131, 131, 131, 131, 131, 132, 133, 134, 131, 135, 131, 131, 131,
+ 136, 137, 138, 139, 137, 137, 140, 141, 138, 142, 143, 137, 144, 137, 145, 26,
+ 146, 147, 147, 147, 147, 147, 147, 148, 147, 147, 147, 149, 26, 26, 26, 26,
+ 150, 151, 152, 152, 153, 152, 152, 154, 155, 154, 152, 156, 26, 26, 26, 26,
+ 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, 157, 157, 157, 159, 158, 157,
+ 157, 157, 157, 158, 157, 157, 157, 160, 157, 160, 161, 162, 26, 26, 26, 26,
+ 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163,
+ 163, 163, 163, 163, 164, 164, 164, 164, 165, 166, 164, 164, 164, 164, 164, 167,
+ 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 169, 169, 169, 169, 169, 169, 169, 169, 169, 170, 171, 170, 169, 169, 169, 169,
+ 169, 170, 169, 169, 169, 169, 170, 171, 170, 169, 171, 169, 169, 169, 169, 169,
+ 169, 169, 170, 169, 169, 169, 169, 169, 169, 169, 169, 172, 169, 169, 169, 173,
+ 169, 169, 169, 174, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176,
+ 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177,
+ 178, 178, 178, 179, 180, 180, 180, 180, 180, 180, 180, 180, 180, 181, 180, 182,
+ 183, 183, 184, 185, 186, 186, 187, 26, 188, 188, 189, 26, 190, 191, 192, 26,
+ 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 194, 193, 195, 193, 195,
+ 196, 197, 197, 198, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 197, 199,
+ 197, 197, 197, 197, 197, 200, 177, 177, 177, 177, 177, 177, 177, 177, 201, 26,
+ 202, 202, 202, 203, 202, 204, 202, 204, 205, 202, 206, 206, 206, 207, 208, 26,
+ 209, 209, 209, 209, 209, 210, 209, 209, 209, 211, 209, 212, 193, 193, 193, 193,
+ 213, 213, 213, 214, 215, 215, 215, 215, 215, 215, 215, 216, 215, 215, 215, 217,
+ 215, 218, 215, 218, 215, 219, 9, 9, 9, 220, 26, 26, 26, 26, 26, 26,
+ 221, 221, 221, 221, 221, 221, 221, 221, 221, 222, 221, 221, 221, 221, 221, 223,
+ 224, 224, 224, 224, 224, 224, 224, 224, 225, 225, 225, 225, 225, 225, 226, 227,
+ 228, 228, 228, 228, 228, 228, 228, 229, 228, 230, 231, 231, 231, 231, 231, 231,
+ 18, 232, 164, 164, 164, 164, 164, 233, 224, 26, 234, 9, 235, 236, 237, 238,
+ 2, 2, 2, 2, 239, 240, 2, 2, 2, 2, 2, 241, 242, 243, 2, 244,
+ 2, 2, 2, 2, 2, 2, 2, 245, 9, 9, 9, 9, 9, 9, 9, 9,
+ 14, 14, 246, 246, 14, 14, 14, 14, 246, 246, 14, 247, 14, 14, 14, 246,
+ 14, 14, 14, 14, 14, 14, 248, 14, 248, 14, 249, 250, 14, 14, 251, 252,
+ 0, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 255, 256,
+ 0, 257, 2, 258, 0, 0, 0, 0, 259, 26, 9, 9, 9, 9, 260, 26,
+ 0, 0, 0, 0, 261, 262, 4, 0, 0, 263, 0, 0, 2, 2, 2, 2,
+ 2, 264, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 257, 26, 26, 26, 0, 265, 26, 26, 0, 0, 0, 0,
+ 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266, 266,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0,
+ 0, 0, 268, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 269, 2, 2, 2, 2,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 270, 271,
+ 164, 164, 164, 164, 165, 166, 272, 272, 272, 272, 272, 272, 272, 273, 274, 273,
+ 169, 169, 171, 26, 171, 171, 171, 171, 171, 171, 171, 171, 18, 18, 18, 18,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26,
+ 276, 276, 276, 277, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 278, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 26, 26, 26, 0, 280,
+ 281, 0, 0, 0, 282, 283, 0, 284, 285, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 287, 288, 289, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 291,
+ 292, 293, 293, 293, 293, 293, 294, 168, 168, 168, 168, 168, 168, 168, 168, 168,
+ 168, 295, 0, 0, 293, 293, 293, 293, 0, 0, 0, 0, 280, 26, 290, 290,
+ 168, 168, 168, 295, 0, 0, 0, 0, 0, 0, 0, 0, 168, 168, 168, 296,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 290, 290, 290, 290, 290, 297,
+ 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 290, 0, 0, 0, 0, 0,
+ 276, 276, 276, 276, 276, 276, 276, 276, 0, 0, 0, 0, 0, 0, 0, 0,
+ 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298, 298,
+ 298, 299, 298, 298, 298, 298, 298, 298, 300, 26, 301, 301, 301, 301, 301, 301,
+ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
+ 302, 302, 302, 302, 302, 303, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 26,
+ 0, 0, 0, 0, 305, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 306, 2, 2, 2, 2, 2, 2, 2, 307, 308, 309, 26, 26, 310, 2,
+ 311, 311, 311, 311, 311, 312, 0, 313, 314, 314, 314, 314, 314, 314, 314, 26,
+ 315, 315, 315, 315, 315, 315, 315, 315, 316, 317, 315, 318, 53, 53, 53, 53,
+ 319, 319, 319, 319, 319, 320, 321, 321, 321, 321, 322, 323, 168, 168, 168, 324,
+ 325, 325, 325, 325, 325, 325, 325, 325, 325, 326, 325, 327, 163, 163, 163, 328,
+ 329, 329, 329, 329, 329, 329, 330, 26, 329, 331, 329, 332, 163, 163, 163, 163,
+ 333, 333, 333, 333, 333, 333, 333, 333, 334, 26, 26, 335, 336, 336, 337, 26,
+ 338, 338, 338, 26, 171, 171, 2, 2, 2, 2, 2, 339, 340, 341, 175, 175,
+ 175, 175, 175, 175, 175, 175, 175, 175, 336, 336, 336, 336, 336, 342, 336, 343,
+ 168, 168, 168, 168, 344, 26, 168, 168, 295, 345, 168, 168, 168, 168, 168, 344,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 279, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 346, 26, 26, 26, 26,
+ 347, 26, 348, 349, 25, 25, 350, 351, 352, 25, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 353, 26, 354, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 355, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 356, 31, 31, 31, 31, 31, 31, 357, 26, 26, 26, 26, 31, 31,
+ 9, 9, 0, 313, 9, 358, 0, 0, 0, 0, 359, 0, 257, 280, 360, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 361,
+ 362, 0, 0, 0, 1, 2, 2, 3, 1, 2, 2, 3, 363, 290, 289, 290,
+ 290, 290, 290, 364, 168, 168, 168, 295, 365, 365, 365, 366, 257, 257, 26, 367,
+ 368, 369, 368, 368, 370, 368, 368, 371, 368, 372, 368, 372, 26, 26, 26, 26,
+ 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, 373,
+ 374, 0, 0, 0, 0, 0, 375, 0, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 252, 0, 376, 377, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 378,
+ 379, 379, 379, 380, 381, 381, 381, 381, 381, 381, 382, 26, 383, 0, 0, 280,
+ 384, 384, 384, 384, 385, 386, 387, 387, 387, 388, 389, 389, 389, 389, 389, 390,
+ 391, 391, 391, 392, 393, 393, 393, 393, 394, 393, 395, 26, 26, 26, 26, 26,
+ 396, 396, 396, 396, 396, 396, 396, 396, 396, 396, 397, 397, 397, 397, 397, 397,
+ 398, 398, 398, 399, 398, 400, 401, 401, 401, 401, 402, 401, 401, 401, 401, 402,
+ 403, 403, 403, 403, 403, 26, 404, 404, 404, 404, 404, 404, 405, 406, 407, 408,
+ 407, 408, 409, 407, 410, 407, 410, 411, 26, 26, 26, 26, 26, 26, 26, 26,
+ 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412, 412,
+ 412, 412, 412, 412, 412, 412, 413, 26, 412, 412, 414, 26, 412, 26, 26, 26,
+ 415, 2, 2, 2, 2, 2, 416, 307, 26, 26, 26, 26, 26, 26, 26, 26,
+ 417, 418, 419, 419, 419, 419, 420, 421, 422, 422, 423, 422, 424, 424, 424, 424,
+ 425, 425, 425, 426, 427, 425, 26, 26, 26, 26, 26, 26, 428, 428, 429, 430,
+ 431, 431, 431, 432, 433, 433, 433, 434, 26, 26, 26, 26, 26, 26, 26, 26,
+ 435, 435, 435, 435, 436, 436, 436, 437, 436, 436, 438, 436, 436, 436, 436, 436,
+ 439, 440, 441, 442, 443, 443, 444, 445, 443, 446, 443, 446, 447, 447, 447, 447,
+ 448, 448, 448, 448, 26, 26, 26, 26, 449, 449, 449, 449, 450, 451, 450, 26,
+ 452, 452, 452, 452, 452, 452, 453, 454, 455, 455, 456, 455, 457, 457, 458, 457,
+ 459, 459, 460, 461, 26, 462, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 463, 463, 463, 463, 463, 463, 463, 463, 463, 464, 26, 26, 26, 26, 26, 26,
+ 465, 465, 465, 465, 465, 465, 466, 26, 465, 465, 465, 465, 465, 465, 466, 467,
+ 468, 468, 468, 468, 468, 26, 468, 469, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 31, 31, 31, 50,
+ 470, 470, 470, 470, 470, 471, 472, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 473, 473, 473, 473, 473, 26, 474, 474, 474, 474, 474, 475, 26, 26, 476, 476,
+ 476, 477, 26, 26, 26, 26, 478, 478, 478, 479, 26, 26, 480, 480, 481, 26,
+ 482, 482, 482, 482, 482, 482, 482, 482, 482, 483, 484, 482, 482, 482, 483, 485,
+ 486, 486, 486, 486, 486, 486, 486, 486, 487, 488, 489, 489, 489, 490, 489, 491,
+ 492, 492, 492, 492, 492, 492, 493, 492, 492, 26, 494, 494, 494, 494, 495, 26,
+ 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 496, 497, 137, 498, 26,
+ 499, 499, 500, 499, 499, 499, 499, 501, 26, 26, 26, 26, 26, 26, 26, 26,
+ 502, 503, 504, 505, 504, 506, 507, 507, 507, 507, 507, 507, 507, 508, 507, 509,
+ 510, 511, 512, 513, 513, 514, 515, 516, 511, 517, 518, 519, 520, 521, 521, 26,
+ 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 522, 523, 524, 26, 26, 26,
+ 525, 525, 525, 525, 525, 525, 525, 525, 525, 26, 525, 526, 26, 26, 26, 26,
+ 527, 527, 527, 527, 527, 527, 528, 527, 527, 527, 527, 528, 26, 26, 26, 26,
+ 529, 529, 529, 529, 529, 529, 529, 529, 530, 26, 529, 531, 197, 532, 26, 26,
+ 533, 533, 533, 533, 533, 533, 533, 534, 533, 534, 26, 26, 26, 26, 26, 26,
+ 535, 535, 535, 536, 535, 537, 535, 535, 538, 26, 26, 26, 26, 26, 26, 26,
+ 539, 539, 539, 539, 539, 539, 539, 540, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, 542, 543,
+ 544, 545, 546, 547, 547, 547, 548, 549, 544, 26, 547, 550, 26, 26, 26, 26,
+ 26, 26, 26, 26, 551, 552, 551, 551, 551, 551, 551, 552, 553, 26, 26, 26,
+ 554, 554, 554, 554, 554, 554, 554, 554, 554, 26, 555, 555, 555, 555, 555, 555,
+ 555, 555, 555, 555, 556, 26, 177, 177, 557, 557, 557, 557, 557, 557, 557, 558,
+ 559, 560, 559, 559, 559, 559, 561, 559, 562, 26, 559, 559, 559, 563, 564, 564,
+ 564, 564, 565, 564, 564, 566, 567, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 568, 569, 570, 570, 570, 570, 568, 571, 570, 26, 570, 572, 573, 574, 575, 575,
+ 575, 576, 577, 578, 575, 579, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 580, 580, 580, 581,
+ 26, 26, 26, 26, 26, 26, 582, 26, 108, 108, 108, 108, 108, 108, 583, 584,
+ 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585,
+ 585, 585, 585, 586, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 585, 587, 588, 26,
+ 585, 585, 585, 585, 585, 585, 585, 585, 589, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, 591, 26,
+ 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592, 592,
+ 592, 592, 592, 592, 592, 593, 592, 594, 26, 26, 26, 26, 26, 26, 26, 26,
+ 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595, 595,
+ 595, 595, 595, 595, 595, 595, 595, 595, 596, 26, 26, 26, 26, 26, 26, 26,
+ 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, 304,
+ 304, 304, 304, 304, 304, 304, 304, 597, 598, 598, 598, 599, 598, 600, 601, 601,
+ 601, 601, 601, 601, 601, 601, 601, 602, 601, 603, 604, 604, 604, 605, 605, 26,
+ 606, 606, 606, 606, 606, 606, 606, 606, 607, 26, 606, 608, 608, 606, 606, 609,
+ 606, 606, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 610, 610, 610, 610, 610, 610, 610, 610,
+ 610, 610, 610, 611, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 612, 612, 612, 612, 612, 612, 612, 612, 612, 613, 612, 612, 612, 612, 612, 612,
+ 612, 614, 612, 612, 26, 26, 26, 26, 26, 26, 26, 26, 615, 26, 346, 26,
+ 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616,
+ 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, 26,
+ 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617,
+ 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 618, 26, 26, 26, 26, 26,
+ 616, 619, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 620, 621,
+ 622, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286,
+ 286, 286, 286, 286, 623, 26, 26, 26, 26, 26, 624, 26, 625, 26, 626, 626,
+ 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626,
+ 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, 627,
+ 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 628, 629, 628, 630,
+ 628, 631, 628, 632, 280, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 9, 9, 9, 9, 9, 633, 9, 9, 220, 26, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 275, 26,
+ 0, 0, 0, 0, 257, 362, 0, 0, 0, 0, 0, 0, 634, 635, 0, 636,
+ 637, 638, 0, 0, 0, 639, 0, 0, 0, 0, 0, 0, 0, 265, 26, 26,
+ 14, 14, 14, 14, 14, 14, 14, 14, 246, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, 0, 280, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 257, 26, 0, 0, 0, 259,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0,
+ 0, 0, 0, 254, 640, 641, 0, 642, 643, 0, 0, 0, 0, 0, 0, 0,
+ 268, 644, 254, 254, 0, 0, 0, 645, 646, 647, 648, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 267, 0, 0, 0, 0, 0, 0,
+ 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649, 649,
+ 649, 650, 26, 651, 652, 649, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 2, 2, 2, 347, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 653, 269, 269, 654, 655, 656, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 657, 657, 657, 657, 657, 658, 657, 659, 657, 660, 26, 26, 26, 26, 26, 26,
+ 26, 26, 661, 661, 661, 662, 26, 26, 663, 663, 663, 663, 663, 663, 663, 664,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 171, 665, 169, 171,
+ 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666, 666,
+ 666, 666, 666, 666, 666, 666, 666, 666, 667, 666, 668, 26, 26, 26, 26, 26,
+ 669, 669, 669, 669, 669, 669, 669, 669, 669, 670, 669, 671, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 362, 0,
+ 0, 0, 0, 0, 0, 0, 376, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 362, 0, 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 26, 26,
+ 672, 31, 31, 31, 673, 674, 675, 676, 677, 678, 673, 679, 673, 675, 675, 680,
+ 31, 681, 31, 682, 683, 681, 31, 682, 26, 26, 26, 26, 26, 26, 51, 26,
+ 0, 0, 0, 0, 0, 280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 280, 26, 0, 257, 362, 0, 362, 0, 362, 0, 0, 0, 275, 26,
+ 0, 0, 0, 0, 0, 275, 26, 26, 26, 26, 26, 26, 684, 0, 0, 0,
+ 685, 26, 0, 0, 0, 0, 0, 280, 0, 259, 313, 26, 275, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 686, 0, 376, 0, 376,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 259, 0, 280, 259, 26,
+ 0, 280, 0, 0, 0, 0, 0, 0, 0, 26, 0, 313, 0, 0, 0, 0,
+ 0, 26, 0, 0, 0, 275, 313, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 280, 26, 0, 275, 376, 376,
+ 257, 26, 0, 0, 0, 376, 0, 265, 275, 26, 0, 313, 0, 26, 257, 26,
+ 0, 0, 359, 0, 0, 0, 0, 0, 0, 265, 26, 26, 26, 26, 0, 313,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 687, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 279, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 346, 26, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 276, 687, 26, 26, 26,
+ 276, 276, 276, 279, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 276, 276, 276, 276, 276, 276, 276, 276, 276, 688, 26, 26, 26, 26, 26, 26,
+ 689, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 939, 940, 941, 942, 946, 948, 0, 962, 969, 970, 971, 976,1001,1002,1003,1008,
+ 0,1033,1040,1041,1042,1043,1047, 0, 0,1080,1081,1082,1086,1110, 0, 0,
+ 1124,1125,1126,1127,1131,1133, 0,1147,1154,1155,1156,1161,1187,1188,1189,1193,
+ 0,1219,1226,1227,1228,1229,1233, 0, 0,1267,1268,1269,1273,1298, 0,1303,
+ 943,1128, 944,1129, 954,1139, 958,1143, 959,1144, 960,1145, 961,1146, 964,1149,
+ 0, 0, 973,1158, 974,1159, 975,1160, 983,1168, 978,1163, 988,1173, 990,1175,
+ 991,1176, 993,1178, 994,1179, 0, 0,1004,1190,1005,1191,1006,1192,1014,1199,
+ 1007, 0, 0, 0,1016,1201,1020,1206, 0,1022,1208,1025,1211,1023,1209, 0,
+ 0, 0, 0,1032,1218,1037,1223,1035,1221, 0, 0, 0,1044,1230,1045,1231,
+ 1049,1235, 0, 0,1058,1244,1064,1250,1060,1246,1066,1252,1067,1253,1072,1258,
+ 1069,1255,1077,1264,1074,1261, 0, 0,1083,1270,1084,1271,1085,1272,1088,1275,
+ 1089,1276,1096,1283,1103,1290,1111,1299,1115,1118,1307,1120,1309,1121,1310, 0,
+ 1053,1239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1093,
+ 1280, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 949,1134,1010,
+ 1195,1050,1236,1090,1277,1341,1368,1340,1367,1342,1369,1339,1366, 0,1320,1347,
+ 1418,1419,1323,1350, 0, 0, 992,1177,1018,1204,1055,1241,1416,1417,1415,1424,
+ 1202, 0, 0, 0, 987,1172, 0, 0,1031,1217,1321,1348,1322,1349,1338,1365,
+ 950,1135, 951,1136, 979,1164, 980,1165,1011,1196,1012,1197,1051,1237,1052,1238,
+ 1061,1247,1062,1248,1091,1278,1092,1279,1071,1257,1076,1263, 0, 0, 997,1182,
+ 0, 0, 0, 0, 0, 0, 945,1130, 982,1167,1337,1364,1335,1362,1046,1232,
+ 1422,1423,1113,1301, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 8, 9, 0, 10,1425, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0,1314,1427, 5,1434,1438,1443, 0,1450, 0,1455,1461,
+ 1514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1446,1458,1468,1476,1480,1486,
+ 1517, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1489,1503,1494,1500,1508, 0,
+ 0, 0, 0,1520,1521, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1526,1528, 0,1525, 0, 0, 0,1522, 0, 0, 0, 0,1536,1532,1539, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1534, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1556, 0, 0, 0, 0, 0, 0,
+ 1548,1550, 0,1547, 0, 0, 0,1567, 0, 0, 0, 0,1558,1554,1561, 0,
+ 0, 0, 0, 0, 0, 0,1568,1569, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1529,1551, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1523,1545,1524,1546, 0, 0,1527,1549, 0, 0,1570,1571,1530,1552,1531,1553,
+ 0, 0,1533,1555,1535,1557,1537,1559, 0, 0,1572,1573,1544,1566,1538,1560,
+ 1540,1562,1541,1563,1542,1564, 0, 0,1543,1565, 0, 0, 0, 0, 0, 0,
+ 0, 0,1606,1607,1609,1608,1610, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1613, 0,1611, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1612, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1620, 0, 0, 0, 0, 0, 0,
+ 0,1623, 0, 0,1624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1614,1615,1616,1617,1618,1619,1621,1622,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1628,1629, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1625,1626, 0,1627,
+ 0, 0, 0,1634, 0, 0,1635, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1630,1631,1632, 0, 0,1633, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1639, 0, 0,1638,1640, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1636,1637, 0, 0,
+ 0, 0, 0, 0,1641, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1642,1644,1643, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1645, 0, 0, 0, 0, 0, 0, 0,
+ 1646, 0, 0, 0, 0, 0, 0,1648,1649, 0,1647,1650, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1651,1653,1652, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1654, 0,1655,1657,1656, 0,
+ 0, 0, 0,1659, 0, 0, 0, 0, 0, 0, 0, 0, 0,1660, 0, 0,
+ 0, 0,1661, 0, 0, 0, 0,1662, 0, 0, 0, 0,1663, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1658, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1664, 0,1665,1673, 0,1674, 0, 0, 0, 0, 0, 0, 0,
+ 0,1666, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,1668, 0, 0, 0, 0, 0, 0, 0, 0, 0,1669, 0, 0,
+ 0, 0,1670, 0, 0, 0, 0,1671, 0, 0, 0, 0,1672, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,1667, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1675, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,1676, 0,1677, 0,1678, 0,1679, 0,1680, 0,
+ 0, 0,1681, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1682, 0,1683, 0, 0,
+ 1684,1685, 0,1686, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 953,1138, 955,1140, 956,1141, 957,1142,1324,1351, 963,1148, 965,1150, 968,1153,
+ 966,1151, 967,1152,1378,1380,1379,1381, 984,1169, 985,1170,1420,1421, 986,1171,
+ 989,1174, 995,1180, 998,1183, 996,1181, 999,1184,1000,1185,1015,1200,1329,1356,
+ 1017,1203,1019,1205,1021,1207,1024,1210,1687,1688,1027,1213,1026,1212,1028,1214,
+ 1029,1215,1030,1216,1034,1220,1036,1222,1039,1225,1038,1224,1334,1361,1336,1363,
+ 1382,1384,1383,1385,1056,1242,1057,1243,1059,1245,1063,1249,1689,1690,1065,1251,
+ 1068,1254,1070,1256,1386,1387,1388,1389,1691,1692,1073,1259,1075,1262,1079,1266,
+ 1078,1265,1095,1282,1098,1285,1097,1284,1390,1391,1392,1393,1099,1286,1100,1287,
+ 1101,1288,1102,1289,1105,1292,1104,1291,1106,1294,1107,1295,1108,1296,1114,1302,
+ 1119,1308,1122,1311,1123,1312,1186,1260,1293,1305, 0,1394, 0, 0, 0, 0,
+ 952,1137, 947,1132,1317,1344,1316,1343,1319,1346,1318,1345,1693,1695,1371,1375,
+ 1370,1374,1373,1377,1372,1376,1694,1696, 981,1166, 977,1162, 972,1157,1326,1353,
+ 1325,1352,1328,1355,1327,1354,1697,1698,1009,1194,1013,1198,1054,1240,1048,1234,
+ 1331,1358,1330,1357,1333,1360,1332,1359,1699,1700,1396,1401,1395,1400,1398,1403,
+ 1397,1402,1399,1404,1094,1281,1087,1274,1406,1411,1405,1410,1408,1413,1407,1412,
+ 1409,1414,1109,1297,1117,1306,1116,1304,1112,1300, 0, 0, 0, 0, 0, 0,
+ 1471,1472,1701,1705,1702,1706,1703,1707,1430,1431,1715,1719,1716,1720,1717,1721,
+ 1477,1478,1729,1731,1730,1732, 0, 0,1435,1436,1733,1735,1734,1736, 0, 0,
+ 1481,1482,1737,1741,1738,1742,1739,1743,1439,1440,1751,1755,1752,1756,1753,1757,
+ 1490,1491,1765,1768,1766,1769,1767,1770,1447,1448,1771,1774,1772,1775,1773,1776,
+ 1495,1496,1777,1779,1778,1780, 0, 0,1451,1452,1781,1783,1782,1784, 0, 0,
+ 1504,1505,1785,1788,1786,1789,1787,1790, 0,1459, 0,1791, 0,1792, 0,1793,
+ 1509,1510,1794,1798,1795,1799,1796,1800,1462,1463,1808,1812,1809,1813,1810,1814,
+ 1467, 21,1475, 22,1479, 23,1485, 24,1493, 27,1499, 28,1507, 29, 0, 0,
+ 1704,1708,1709,1710,1711,1712,1713,1714,1718,1722,1723,1724,1725,1726,1727,1728,
+ 1740,1744,1745,1746,1747,1748,1749,1750,1754,1758,1759,1760,1761,1762,1763,1764,
+ 1797,1801,1802,1803,1804,1805,1806,1807,1811,1815,1816,1817,1818,1819,1820,1821,
+ 1470,1469,1822,1474,1465, 0,1473,1825,1429,1428,1426, 12,1432, 0, 26, 0,
+ 0,1315,1823,1484,1466, 0,1483,1829,1433, 13,1437, 14,1441,1826,1827,1828,
+ 1488,1487,1513, 19, 0, 0,1492,1515,1445,1444,1442, 15, 0,1831,1832,1833,
+ 1502,1501,1516, 25,1497,1498,1506,1518,1457,1456,1454, 17,1453,1313, 11, 3,
+ 0, 0,1824,1512,1519, 0,1511,1830,1449, 16,1460, 18,1464, 4, 0, 0,
+ 30, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 20, 0, 0, 0, 2, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1834,1835, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1836, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1837,1839,1838,
+ 0, 0, 0, 0,1840, 0, 0, 0, 0,1841, 0, 0,1842, 0, 0, 0,
+ 0, 0, 0, 0,1843, 0,1844, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,1845, 0, 0,1846, 0, 0,1847, 0,1848, 0, 0, 0, 0, 0, 0,
+ 937, 0,1850, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1849, 936, 938,
+ 1851,1852, 0, 0,1853,1854, 0, 0,1855,1856, 0, 0, 0, 0, 0, 0,
+ 1857,1858, 0, 0,1861,1862, 0, 0,1863,1864, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1867,1868,1869,1870,
+ 1859,1860,1865,1866, 0, 0, 0, 0, 0, 0,1871,1872,1873,1874, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 33, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1875, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1877, 0,1878, 0,
+ 1879, 0,1880, 0,1881, 0,1882, 0,1883, 0,1884, 0,1885, 0,1886, 0,
+ 1887, 0,1888, 0, 0,1889, 0,1890, 0,1891, 0, 0, 0, 0, 0, 0,
+ 1892,1893, 0,1894,1895, 0,1896,1897, 0,1898,1899, 0,1900,1901, 0, 0,
+ 0, 0, 0, 0,1876, 0, 0, 0, 0, 0, 0, 0, 0, 0,1902, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1904, 0,1905, 0,
+ 1906, 0,1907, 0,1908, 0,1909, 0,1910, 0,1911, 0,1912, 0,1913, 0,
+ 1914, 0,1915, 0, 0,1916, 0,1917, 0,1918, 0, 0, 0, 0, 0, 0,
+ 1919,1920, 0,1921,1922, 0,1923,1924, 0,1925,1926, 0,1927,1928, 0, 0,
+ 0, 0, 0, 0,1903, 0, 0,1929,1930,1931,1932, 0, 0, 0,1933, 0,
+ 710, 385, 724, 715, 455, 103, 186, 825, 825, 242, 751, 205, 241, 336, 524, 601,
+ 663, 676, 688, 738, 411, 434, 474, 500, 649, 746, 799, 108, 180, 416, 482, 662,
+ 810, 275, 462, 658, 692, 344, 618, 679, 293, 388, 440, 492, 740, 116, 146, 168,
+ 368, 414, 481, 527, 606, 660, 665, 722, 781, 803, 809, 538, 553, 588, 642, 758,
+ 811, 701, 233, 299, 573, 612, 487, 540, 714, 779, 232, 267, 412, 445, 457, 585,
+ 594, 766, 167, 613, 149, 148, 560, 589, 648, 768, 708, 345, 411, 704, 105, 259,
+ 313, 496, 518, 174, 542, 120, 307, 101, 430, 372, 584, 183, 228, 529, 650, 697,
+ 424, 732, 428, 349, 632, 355, 517, 110, 135, 147, 403, 580, 624, 700, 750, 170,
+ 193, 245, 297, 374, 463, 543, 763, 801, 812, 815, 162, 384, 420, 730, 287, 330,
+ 337, 366, 459, 476, 509, 558, 591, 610, 726, 652, 734, 759, 154, 163, 198, 473,
+ 683, 697, 292, 311, 353, 423, 572, 494, 113, 217, 259, 280, 314, 499, 506, 603,
+ 608, 752, 778, 782, 788, 117, 557, 748, 774, 320, 109, 126, 260, 265, 373, 411,
+ 479, 523, 655, 737, 823, 380, 765, 161, 395, 398, 438, 451, 502, 516, 537, 583,
+ 791, 136, 340, 769, 122, 273, 446, 727, 305, 322, 400, 496, 771, 155, 190, 269,
+ 377, 391, 406, 432, 501, 519, 599, 684, 687, 749, 776, 175, 452, 191, 480, 510,
+ 659, 772, 805, 813, 397, 444, 619, 566, 568, 575, 491, 471, 707, 111, 636, 156,
+ 153, 288, 346, 578, 256, 435, 383, 729, 680, 767, 694, 295, 128, 210, 0, 0,
+ 227, 0, 379, 0, 0, 150, 493, 525, 544, 551, 552, 556, 783, 576, 604, 0,
+ 661, 0, 703, 0, 0, 735, 743, 0, 0, 0, 793, 794, 795, 808, 741, 773,
+ 118, 127, 130, 166, 169, 177, 207, 213, 215, 226, 229, 268, 270, 317, 327, 329,
+ 335, 369, 375, 381, 404, 441, 448, 458, 477, 484, 503, 539, 545, 547, 546, 548,
+ 549, 550, 554, 555, 561, 564, 569, 591, 593, 595, 598, 607, 620, 625, 625, 651,
+ 690, 695, 705, 706, 716, 717, 733, 735, 777, 786, 790, 315, 869, 623, 0, 0,
+ 102, 145, 134, 115, 129, 138, 165, 171, 207, 202, 206, 212, 227, 231, 240, 243,
+ 250, 254, 294, 296, 303, 308, 319, 325, 321, 329, 326, 335, 341, 357, 360, 362,
+ 370, 379, 388, 389, 393, 421, 424, 438, 456, 454, 458, 465, 477, 535, 485, 490,
+ 493, 507, 512, 514, 521, 522, 525, 526, 528, 533, 532, 541, 565, 569, 574, 586,
+ 591, 597, 607, 637, 647, 674, 691, 693, 695, 698, 703, 699, 705, 704, 702, 706,
+ 709, 717, 728, 736, 747, 754, 770, 777, 783, 784, 786, 787, 790, 802, 825, 848,
+ 847, 857, 55, 65, 66, 883, 892, 916, 822, 824, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1586, 0,1605,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1602,1603,1934,1935,1574,1575,
+ 1576,1577,1579,1580,1581,1583,1584, 0,1585,1587,1588,1589,1591, 0,1592, 0,
+ 1593,1594, 0,1595,1596, 0,1598,1599,1600,1601,1604,1582,1578,1590,1597, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1936, 0,1937, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1938, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1939,1940,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1941,1942, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1944,1943, 0,1945, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1946,1947, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,1948, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1949,1950,
+ 1951,1952,1953,1954,1955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,1956,1957,1958,1960,1959,
+ 1961, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 106, 104, 107, 826, 114, 118, 119, 121, 123, 124, 127, 125, 34, 830, 130, 131,
+ 132, 137, 827, 35, 133, 139, 829, 142, 143, 112, 144, 145, 924, 151, 152, 37,
+ 157, 158, 159, 160, 38, 165, 166, 169, 171, 172, 173, 174, 176, 177, 178, 179,
+ 181, 182, 182, 182, 833, 468, 184, 185, 834, 187, 188, 189, 196, 192, 194, 195,
+ 197, 199, 200, 201, 203, 204, 204, 206, 208, 209, 211, 218, 213, 219, 214, 216,
+ 153, 234, 221, 222, 223, 220, 225, 224, 230, 835, 235, 236, 237, 238, 239, 244,
+ 836, 837, 247, 248, 249, 246, 251, 39, 40, 253, 255, 255, 838, 257, 258, 259,
+ 261, 839, 262, 263, 301, 264, 41, 266, 270, 272, 271, 841, 274, 842, 277, 276,
+ 278, 281, 282, 42, 283, 284, 285, 286, 43, 843, 44, 289, 290, 291, 293, 934,
+ 298, 845, 845, 621, 300, 300, 45, 852, 894, 302, 304, 46, 306, 309, 310, 312,
+ 316, 48, 47, 317, 846, 318, 323, 324, 325, 324, 328, 329, 333, 331, 332, 334,
+ 335, 336, 338, 339, 342, 343, 347, 351, 849, 350, 348, 352, 354, 359, 850, 361,
+ 358, 356, 49, 363, 365, 367, 364, 50, 369, 371, 851, 376, 386, 378, 53, 381,
+ 52, 51, 140, 141, 387, 382, 614, 78, 388, 389, 390, 394, 392, 856, 54, 399,
+ 396, 402, 404, 858, 405, 401, 407, 55, 408, 409, 410, 413, 859, 415, 56, 417,
+ 860, 418, 57, 419, 422, 424, 425, 861, 840, 862, 426, 863, 429, 431, 427, 433,
+ 437, 441, 438, 439, 442, 443, 864, 436, 449, 450, 58, 454, 453, 865, 447, 460,
+ 866, 867, 461, 466, 465, 464, 59, 467, 470, 469, 472, 828, 475, 868, 478, 870,
+ 483, 485, 486, 871, 488, 489, 872, 873, 495, 497, 60, 498, 61, 61, 504, 505,
+ 507, 508, 511, 62, 513, 874, 515, 875, 518, 844, 520, 876, 877, 878, 63, 64,
+ 528, 880, 879, 881, 882, 530, 531, 531, 533, 66, 534, 67, 68, 884, 536, 538,
+ 541, 69, 885, 549, 886, 887, 556, 559, 70, 561, 562, 563, 888, 889, 889, 567,
+ 71, 890, 570, 571, 72, 891, 577, 73, 581, 579, 582, 893, 587, 74, 590, 592,
+ 596, 75, 895, 896, 76, 897, 600, 898, 602, 605, 607, 899, 900, 609, 901, 611,
+ 853, 77, 615, 616, 79, 617, 252, 902, 903, 854, 855, 621, 622, 731, 80, 627,
+ 626, 628, 164, 629, 630, 631, 633, 904, 632, 634, 639, 640, 635, 641, 646, 651,
+ 638, 643, 644, 645, 905, 907, 906, 81, 653, 654, 656, 911, 657, 908, 82, 83,
+ 909, 910, 84, 664, 665, 666, 667, 669, 668, 671, 670, 674, 672, 673, 675, 85,
+ 677, 678, 86, 681, 682, 912, 685, 686, 87, 689, 36, 913, 914, 88, 89, 696,
+ 702, 709, 711, 915, 712, 713, 718, 719, 917, 831, 721, 720, 723, 832, 725, 728,
+ 918, 919, 739, 742, 744, 920, 745, 753, 756, 757, 755, 760, 761, 921, 762, 90,
+ 764, 922, 91, 775, 279, 780, 923, 925, 92, 93, 785, 926, 94, 927, 787, 787,
+ 789, 928, 792, 95, 796, 797, 798, 800, 96, 929, 802, 804, 806, 97, 98, 807,
+ 930, 99, 931, 932, 933, 814, 100, 816, 817, 818, 819, 820, 821, 935, 0, 0,
+};
+static const int16_t
+_hb_ucd_i16[196] =
+{
+ 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
+ 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
+ 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
+ -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
+ 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
+ 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
+ 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
+ 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
+ -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
+ 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
+ -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
+ -1, 0, 1, -1,
+};
+
+static inline uint_fast8_t
+_hb_ucd_gc (unsigned u)
+{
+ return u<1114110u?_hb_ucd_u8[6664+(((_hb_ucd_u8[1296+(((_hb_ucd_u16[((_hb_ucd_u8[544+(((_hb_ucd_u8[u>>1>>3>>3>>4])<<4)+((u>>1>>3>>3)&15u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:2;
+}
+static inline uint_fast8_t
+_hb_ucd_ccc (unsigned u)
+{
+ return u<125259u?_hb_ucd_u8[8612+(((_hb_ucd_u8[8068+(((_hb_ucd_u8[7624+(((_hb_ucd_u8[7288+(((_hb_ucd_u8[7042+(u>>2>>2>>2>>3)])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:0;
+}
+static inline unsigned
+_hb_ucd_b4 (const uint8_t* a, unsigned i)
+{
+ return (a[i>>1]>>((i&1u)<<2))&15u;
+}
+static inline int_fast16_t
+_hb_ucd_bmg (unsigned u)
+{
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[9356+(((_hb_ucd_u8[9236+(((_hb_ucd_b4(9108+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+}
+static inline uint_fast8_t
+_hb_ucd_sc (unsigned u)
+{
+ return u<918000u?_hb_ucd_u8[10862+(((_hb_ucd_u16[2000+(((_hb_ucd_u8[10142+(((_hb_ucd_u8[9692+(u>>3>>4>>4)])<<4)+((u>>3>>4)&15u))])<<4)+((u>>3)&15u))])<<3)+((u)&7u))]:2;
+}
+static inline uint_fast16_t
+_hb_ucd_dm (unsigned u)
+{
+ return u<195102u?_hb_ucd_u16[5888+(((_hb_ucd_u8[16764+(((_hb_ucd_u8[16382+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+}
+
+
#else
static const uint8_t
-_hb_ucd_u8[13602] =
+_hb_ucd_u8[13246] =
{
0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 9, 10, 7, 7, 7, 7, 7, 11, 12, 12, 12, 13,
@@ -6145,331 +5025,309 @@ _hb_ucd_u8[13602] =
220, 0, 0,230,220, 0, 0, 0,220,220, 0, 0,230,220, 0, 9,
7, 0, 0, 7, 9, 0, 0, 0, 9, 7, 6, 6, 0, 0, 0, 0,
1, 0, 0,216,216, 1, 1, 1, 0, 0, 0,226,216,216,216,216,
- 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 17, 17, 17,
- 17, 33, 17, 17, 17, 19, 17, 17, 17, 17, 20,101, 17,113,129,169,
- 17, 27, 28, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 216, 0,220,220,220, 0,230,230, 7, 0, 16, 17, 17, 33, 17, 49,
+ 17, 17, 84, 97,135,145, 26, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17,177, 0, 1, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3,
+ 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 6, 7, 8, 3, 3, 3,
+ 3, 3, 9, 10, 11, 12, 13, 3, 3, 3, 3, 3, 3, 3, 3, 14,
+ 3, 15, 3, 3, 3, 3, 3, 3, 16, 17, 18, 19, 20, 21, 3, 3,
+ 3, 22, 23, 24, 3, 3, 3, 3, 3, 3, 25, 3, 3, 3, 3, 3,
+ 3, 3, 3, 26, 3, 3, 27, 28, 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
+ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 9, 0, 0, 0, 0, 0, 0, 9, 0, 9, 0, 0, 0, 0,
+ 0, 0, 0, 10, 11, 12, 13, 0, 0, 14, 15, 16, 6, 0, 17, 18,
+ 19, 19, 19, 20, 21, 22, 23, 24, 19, 25, 0, 26, 27, 19, 19, 28,
+ 29, 30, 0, 31, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 19,
+ 28, 0, 32, 33, 9, 34, 35, 19, 0, 0, 36, 37, 38, 39, 40, 19,
+ 0, 41, 42, 43, 44, 31, 0, 1, 45, 42, 0, 0, 0, 0, 0, 32,
+ 14, 14, 0, 0, 0, 0, 14, 0, 0, 46, 47, 47, 47, 47, 48, 49,
+ 47, 47, 47, 47, 50, 51, 52, 53, 43, 21, 0, 0, 0, 0, 0, 0,
+ 0, 54, 6, 55, 0, 14, 19, 1, 0, 0, 0, 0, 56, 57, 0, 0,
+ 0, 0, 0, 19, 58, 31, 0, 0, 0, 0, 0, 0, 0, 59, 14, 0,
+ 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 0, 0, 60, 61, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 3, 0, 4,
+ 5, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 1, 1, 0, 0, 8,
+ 9, 0, 8, 9, 0, 0, 0, 0, 8, 9, 10, 11, 12, 0, 0, 0,
+ 13, 0, 0, 0, 0, 14, 15, 16, 17, 0, 0, 0, 1, 0, 0, 18,
+ 19, 0, 0, 0, 20, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1,
+ 1, 1, 1, 1, 0, 8, 21, 9, 0, 0, 22, 0, 0, 0, 0, 1,
+ 0, 23, 24, 25, 0, 0, 26, 0, 0, 0, 8, 21, 27, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0, 1, 28, 29, 30, 0, 31, 32, 20, 1, 1,
+ 0, 0, 0, 8, 21, 9, 1, 4, 5, 0, 0, 0, 33, 9, 0, 1,
+ 1, 1, 0, 8, 21, 21, 21, 21, 34, 1, 35, 21, 21, 21, 9, 36,
+ 0, 0, 37, 38, 1, 0, 39, 0, 0, 0, 1, 0, 1, 0, 0, 0,
+ 0, 8, 21, 9, 1, 0, 0, 0, 40, 0, 8, 21, 21, 21, 21, 21,
+ 21, 21, 21, 9, 0, 1, 1, 1, 1, 8, 21, 21, 21, 9, 0, 0,
+ 0, 41, 0, 42, 43, 0, 0, 0, 1, 44, 0, 0, 0, 45, 8, 9,
+ 1, 0, 0, 0, 8, 21, 21, 21, 9, 0, 1, 0, 1, 1, 8, 21,
+ 21, 9, 0, 4, 5, 8, 9, 1, 0, 0, 0, 1, 2, 3, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 3, 3, 3, 3, 3, 3,
+ 3, 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17,237, 0, 1, 2, 2, 0, 3,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 6, 7, 8, 9, 0,
- 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 20, 0, 0, 21, 22, 0, 0, 0, 0, 23, 24,
- 25, 26, 0, 27, 0, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0,
- 0, 33, 34, 35, 36, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 38, 39, 0, 0, 0, 0, 1, 2, 40, 41, 0, 1,
- 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
- 0, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 0, 5, 0, 0, 0,
- 6, 0, 0, 0, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, 0,
- 8, 9, 0, 0, 0, 0, 0, 0, 10, 0, 0, 10, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0,
- 0, 0, 0, 0, 11, 12, 0, 13, 0, 14, 15, 16, 0, 0, 0, 0,
- 0, 1, 17, 18, 0, 19, 7, 1, 0, 0, 0, 20, 20, 7, 20, 20,
- 20, 20, 20, 20, 20, 8, 21, 0, 22, 0, 7, 23, 24, 0, 20, 20,
- 25, 0, 0, 0, 26, 27, 1, 7, 20, 20, 20, 20, 20, 1, 28, 29,
- 30, 31, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0,
- 0, 0, 0, 0, 20, 20, 20, 1, 0, 0, 8, 21, 32, 4, 0, 10,
- 0, 33, 7, 20, 20, 20, 0, 0, 0, 0, 8, 34, 34, 35, 36, 34,
- 37, 0, 38, 1, 20, 20, 0, 0, 39, 0, 1, 1, 0, 8, 21, 1,
- 20, 0, 0, 0, 1, 0, 0, 40, 1, 1, 0, 0, 8, 21, 0, 1,
- 0, 1, 0, 1, 0, 0, 0, 0, 26, 34, 34, 34, 34, 34, 34, 34,
- 34, 34, 21, 7, 20, 41, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21,
- 0, 42, 43, 44, 0, 45, 0, 8, 21, 0, 0, 0, 0, 0, 0, 0,
- 0, 46, 7, 1, 10, 1, 0, 0, 0, 1, 20, 20, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 26, 34, 9, 0, 0, 20, 20, 1, 20,
- 20, 0, 0, 0, 0, 0, 0, 0, 26, 21, 0, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 47, 48, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 9, 10, 11, 11, 11, 11, 11, 12, 12, 12,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 12, 21, 12, 12, 12, 12, 22,
- 23, 23, 23, 24, 12, 12, 12, 25, 26, 27, 12, 28, 29, 30, 31, 32,
- 33, 34, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 35,
- 12, 36, 7, 7, 37, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 38, 0, 0, 1, 2, 2, 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, 32, 33, 33, 33, 34, 35, 35, 35, 35,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 2, 2, 51, 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 57, 57, 56, 56, 56, 56, 56, 56, 58, 59, 60, 61,
- 56, 62, 62, 63, 64, 65, 66, 67, 68, 69, 70, 56, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 71,
- 62, 62, 62, 62, 72, 72, 72, 72, 72, 72, 72, 72, 72, 73, 74, 74,
- 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 62, 62, 62, 62, 88, 89, 89, 89, 90, 89,
- 91, 92, 93, 94, 95, 95, 96, 97, 87, 98, 99,100,101,102,103,104,
- 105,105,105, 2,106,107,108,109,110,111,112,113,114,115,116, 87,
- 89,117,118,119,120,121,122,123,124,125,126, 87,127,128, 87,129,
- 130,131,132, 87,133,134,135,136,137,138, 87, 87,139,140,141,142,
- 87,143, 87,144,145,145,145,145,145,145,145,145,145,145,145, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,146,147,147,147,147,147,147,147,147,147, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,148,148,148,148,
- 148, 87, 87, 87,149,149,149,149,150,151,152,152, 87, 87, 87, 87,
- 153,153,154,155,156,156,156,156,156,156,156,156,156,156,156,156,
- 156,156,156,156,156,156,156,156,156,156,157,157,157,157,156, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87,158,159,160,161,162,162,162, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,163,164, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, 87,165, 56, 56, 56,166,167, 51, 56, 56, 87, 56, 56, 56, 56,
- 56, 56, 56, 56,168,168,168,168,168,168, 87, 87, 87, 87, 87, 87,
- 87, 87, 2, 87,169, 87,170, 87, 87,171, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 33,172,172,173, 87, 87, 87, 87, 87, 56, 56, 56, 87,
- 89, 89, 87, 87, 56, 56, 56, 56,174, 87, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 62, 62, 62, 62, 62, 62, 62, 87, 87, 87, 87, 87,
- 87, 87, 87, 87, 56, 87,175,175, 0, 1, 2, 2, 0, 1, 2, 2,
- 2, 3, 4, 5, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3,
- 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6,
- 0, 0, 7, 0, 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11,
- 11, 11, 12, 11, 13, 13, 13, 13, 13, 13, 13, 13, 14, 13, 13, 13,
- 13, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16, 16, 17, 18, 18,
- 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24, 21, 21, 21, 21,
- 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21, 21, 21, 21, 21,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 0, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, 17,
+ 18, 17, 19, 20, 21, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 25, 25, 26, 27,
+ 28, 29, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 52, 53, 31,
+ 31, 31, 31, 54, 55, 55, 56, 31, 31, 31, 31, 31, 31, 31, 57, 58,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 59, 60, 31, 61, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 63, 64, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 65, 66, 67, 31, 31, 31, 31, 68, 31, 31, 31, 31, 31,
+ 31, 31, 31, 69, 70, 71, 17, 17, 72, 73, 31, 74, 75, 76, 31, 77,
+ 78, 31, 79, 80, 17, 81, 17, 17, 17, 17, 31, 31, 23, 23, 23, 23,
+ 23, 23, 31, 31, 31, 31, 31, 31, 23, 82, 31, 31, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 83, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 84, 0, 0, 1,
+ 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3,
+ 4, 4, 4, 4, 4, 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 11,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 19, 27,
+ 28, 29, 30, 30, 31, 31, 32, 32, 33, 33, 34, 34, 35, 35, 36, 36,
+ 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 42, 43, 44, 44, 45, 46,
+ 47, 47, 47, 47, 48, 48, 48, 48, 48, 48, 49, 50, 51, 51, 51, 51,
+ 51, 51, 51, 51, 51, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 51,
+ 60, 61, 62, 63, 64, 65, 66, 7, 67, 67, 68, 69, 70, 71, 72, 73,
+ 74, 75, 76, 7, 4, 4, 4, 4, 77, 77, 77, 77, 78, 79, 80, 81,
+ 82, 83, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 85, 85, 85,
+ 0, 0, 0, 0, 86, 87, 88, 88, 89, 90, 48, 91, 0, 0, 92, 92,
+ 92, 92, 92, 93, 94, 95, 96, 97, 98, 47, 99,100,101,102, 0,103,
+ 104,105, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
+ 92, 92, 92, 0,106,106,106,106,106,106,106,106,106,106,106,107,
+ 108,108,108,108,108, 11,109,110,111, 4,112, 4,113,114,115,116,
+ 117,118,119,120,121,122,123,124,125,126, 50,127, 47, 47, 47, 47,
+ 47, 47, 47, 47,128,128,128,128,128,128,128,128,128,128,128,128,
+ 92, 92, 92, 92, 92, 92, 92, 92,129,130, 19, 19, 19, 19, 19, 19,
+ 131, 19, 19, 19,132,133, 19,134,135,136,137,101,138,138,138,138,
+ 0, 77,139,140,128,128,141,142,143,144,145,146,147,148,149,150,
+ 151,152,153,153,154,154,154,154,154,154, 4, 4,155,156,157,158,
+ 159,160,161,162,163,164,165,166,167,168,169,169,170,170,171,171,
+ 172,172,128,128, 19, 19,173,173,174,175,176,177,178,178,179,180,
+ 181,182,183,184,185,185,186,187,188,189,128,128,190,190,191,191,
+ 128,128,192,192,193,194,195,195,196,196,128,128,197,197,198,198,
+ 199,199,200,200,201,202,203,204,128,128,128,128,205,206,207,207,
+ 208,209,210,210,128,128,211,211,128,128,212, 34,213,213,213,213,
+ 213,213,213,213,213,213,213,213,213,213,128,128,128,128,128,128,
+ 128,128,214,214,215,215,215,215,215,215,215,215,215,215,128,128,
+ 128,128,128,128,216,216,216,216,216,216,216,216,216,216,128,128,
+ 128,128,128,128,110,110,110,110,110,110,110,110,110,217,218,219,
+ 220,220,220,220,221,221,221,221,222,222,222,223,224,224,224,224,
+ 224,224,224,224,224,224,224,224,225,225,225,225,225,225,225,225,
+ 224,224,128,128,128,128,128,128,128,128,104,104,226,227,227,227,
+ 228,229,230,230,230,230,230,230,128,128,128,128,231,231,232, 0,
+ 128,128,128,128,128,128,128,128, 7,233, 0, 0, 0, 0, 0, 0,
+ 0,234,235, 0, 77, 77, 0, 0, 0, 0,128,128,236,236,236,236,
+ 236,236,236,236,236,236,236,236,128,128,128,128,128,128,128,128,
+ 4, 4,128,128, 86, 86,128,128,237,237,128,128,128,128,238,239,
+ 128,128,128,128,128,128,128,128,128,128, 48, 48,240,240,240,240,
+ 241,241,128,128, 0, 0, 0, 0, 0, 0,128,128, 19, 19, 19, 19,
+ 128,128,128,128,242, 0,128,128, 0, 0, 0, 0, 92, 92,128,128,
+ 128,128,128,128, 92, 92, 92, 92, 92, 92,128,128, 0, 0,128,128,
+ 7, 7, 7, 7, 0, 0, 0, 0, 1, 2, 1, 2, 0, 0, 3, 3,
+ 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 6, 0, 0, 7, 0,
+ 8, 8, 8, 8, 8, 8, 8, 9, 10, 11, 11, 11, 11, 11, 12, 11,
+ 13, 13, 13, 13, 14, 13, 13, 13, 13, 13, 13, 15, 16, 16, 16, 16,
+ 16, 17, 18, 18, 18, 18, 18, 18, 19, 20, 21, 21, 22, 23, 21, 24,
+ 21, 21, 21, 21, 21, 25, 21, 21, 26, 26, 26, 26, 26, 21, 21, 21,
+ 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 26, 21,
21, 21, 31, 21, 32, 32, 32, 32, 32, 33, 34, 32, 35, 35, 35, 35,
- 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37,
- 37, 37, 37, 37, 38, 38, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39,
- 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, 40, 40, 41, 41, 41, 41,
- 41, 41, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43, 43,
- 43, 43, 43, 43, 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46,
- 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50,
- 50, 50, 50, 51, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55,
+ 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,
+ 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,
+ 44, 44, 44, 45, 44, 44, 44, 44, 46, 46, 46, 46, 47, 47, 47, 47,
+ 47, 48, 47, 47, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51,
+ 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54,
55, 55, 55, 55, 56, 56, 57, 57, 57, 57, 58, 57, 59, 59, 60, 61,
- 62, 62, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 65, 66, 66, 66,
- 66, 66, 66, 66, 66, 66, 66, 55, 55, 55, 55, 55, 67, 67, 67, 67,
- 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 64, 64, 70, 70, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 8, 8, 8, 8, 8, 72, 72, 72, 72,
+ 62, 62, 63, 63, 64, 64, 64, 64, 65, 66, 66, 66, 66, 66, 66, 66,
+ 66, 66, 66, 55, 67, 67, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69,
+ 69, 69, 64, 64, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 8,
72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
75, 76, 76, 76, 13, 50, 50, 50, 73, 77, 78, 79, 4, 4, 80, 4,
- 4, 81, 82, 83, 4, 4, 4, 84, 8, 8, 8, 8, 11, 11, 11, 11,
- 11, 11, 11, 11, 85, 0, 0, 0, 0, 0, 0, 86, 0, 4, 0, 0,
- 0, 8, 8, 8, 0, 0, 87, 88, 89, 0, 4, 4, 6, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, 90,
- 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 4, 4, 92, 92, 92, 92,
- 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93, 53, 53, 53, 53,
- 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 0, 95, 0, 96, 97, 98, 99, 99, 99, 99,100,101,102,
- 102,102,102,103,104,104,104,105, 52, 52, 52, 52, 52, 0,104,104,
- 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106, 0, 0, 0, 0,
- 0,102,102,107,102,102,102,102,102,108, 0, 0, 94, 94, 94, 94,
- 0, 0, 0, 0,109,109,109,109,109,109,109,109,109,109,109,109,
- 109,110,110,110,111,111,111,111,111,111,111,111,111,111,111,111,
- 13, 13, 13, 13, 13, 13,112,112,112,112,112,112, 0, 0,113, 4,
- 4, 4, 4, 4,114, 4, 4, 4, 4, 4, 4, 4,115,115,115, 0,
- 116,116,116,116,117,117,117,117,117,117, 32, 32,118,118,119,120,
- 120,120, 52, 52,121,121,121,121,122,121, 49, 49,123,123,123,123,
- 123,123, 49, 49,124,124,124,124,124,124,125,125, 53, 53, 53, 4,
- 4,126,127, 54, 54, 54, 54, 54,125,125,125,125,128,128,128,128,
- 128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21,130, 21, 21, 21, 21, 8, 0,131, 0,
- 0, 0, 0, 21, 21, 21, 21, 21, 21, 21, 21,132, 0, 0, 1, 2,
- 1, 2,133,101,102,134, 52, 52, 52, 52, 0, 0,135,135,135,135,
- 135,135,135,135, 0, 0, 0, 0, 11, 11, 11, 11, 11, 0, 11, 11,
- 11, 0, 0,136,137,137,138,138,138,138,139, 0,140,140,140,141,
- 141,142,142,142,143,143,144,144,144,144,144,144,145,145,145,145,
- 145,146,146,146,147,147,147,148,148,148,148,148,149,149,149,150,
- 150,150,150,151,151,151,151,151,151,151,151,151,152,152,152,152,
- 152,152,152,152,153,153,153,153,154,154,155,155,156,156,156,156,
- 156,156,157,157,158,158,159,159,159,159,159,159,160,160,161,161,
- 161,161,161,161,162,162,162,162,162,162,163,163,164,164,164,164,
- 165,165,165,165,166,166,166,166,167,167,168,168,169,169,169,169,
- 169,169,169,169,170,170,170,170,170,170,170,170,171,171,171,171,
- 171,171,171,171,172,172,172,172,172,172,172,172,173,173,173,173,
- 173,173,173,173,174,174,174,175,175,175,175,176,176,176,176,177,
- 177,177,178,178,179,179,179,179,179,179,179,179,180,180,180,180,
- 180,181,181,181,182,182,182,182,182,183,183,183,184,184,184,184,
- 184,184,185, 43,186,186,186,186,186,186,186,186,187,187,187,188,
+ 4, 81, 82, 83, 4, 4, 4, 84, 11, 11, 11, 11, 85, 0, 0, 0,
+ 0, 0, 0, 86, 0, 4, 0, 0, 0, 8, 8, 8, 0, 0, 87, 88,
+ 89, 0, 4, 4, 6, 0, 0, 0, 90, 90, 90, 90, 91, 91, 91, 91,
+ 91, 91, 4, 4, 92, 92, 92, 92, 50, 50, 50, 93, 93, 93, 93, 93,
+ 53, 53, 13, 13, 94, 94, 94, 94, 94, 94, 94, 0, 95, 0, 96, 97,
+ 98, 99, 99, 99, 99,100,101,102,102,102,102,103,104,104,104,105,
+ 52, 0,104,104, 0, 0, 0,102, 52, 52, 0, 0, 0, 0, 52,106,
+ 0,102,102,107,102,102,102,102,102,108, 0, 0,109,109,109,109,
+ 109,110,110,110,111,111,111,111, 13, 13,112,112,112,112,112,112,
+ 0, 0,113, 4,114, 4, 4, 4,115,115,115, 0,116,116,116,116,
+ 117,117,117,117,117,117, 32, 32,118,118,119,120,120,120, 52, 52,
+ 121,121,121,121,122,121, 49, 49,123,123,123,123,123,123, 49, 49,
+ 124,124,124,124,124,124,125,125, 53, 53, 53, 4, 4,126,127, 54,
+ 125,125,125,125,128,128,128,128, 4,129, 18, 18, 18, 21, 21, 21,
+ 21, 21, 21,130, 8, 0,131, 0, 0, 0, 0, 21, 21, 21, 21,132,
+ 0, 0, 1, 2, 1, 2,133,101,102,134, 52, 52,135,135,135,135,
+ 11, 0, 11, 11, 11, 0, 0,136,137,137,138,138,138,138,139, 0,
+ 140,140,140,141,141,142,142,142,143,143,144,144,144,144,144,144,
+ 145,145,145,145,145,146,146,146,147,147,147,148,148,148,148,148,
+ 149,149,149,150,150,150,150,151,151,151,151,151,152,152,152,152,
+ 153,153,153,153,154,154,155,155,156,156,156,156,156,156,157,157,
+ 158,158,159,159,159,159,159,159,160,160,161,161,161,161,161,161,
+ 162,162,162,162,162,162,163,163,164,164,164,164,165,165,165,165,
+ 166,166,166,166,167,167,168,168,169,169,169,169,170,170,170,170,
+ 171,171,171,171,172,172,172,172,173,173,173,173,174,174,174,175,
+ 175,175,175,176,176,176,176,177,177,177,178,178,179,179,179,179,
+ 180,180,180,180,180,181,181,181,182,182,182,182,182,183,183,183,
+ 184,184,184,184,184,184,185, 43,186,186,186,186,187,187,187,188,
188,188,188,188,189,189,189,190,189,189,189,189,191,191,191,191,
- 191,191,191,191,192,192,192,192,192,192,192,192,193,193,193,193,
- 193,193,193,193,194,194,194,194,194,194, 66, 66,195,195,195,195,
- 195,195,195,195,196,196,196,196,196,196,196,196,197,197,197,197,
- 197,197,197,197,198,198,198,198,198,198,198,198,199,199,199,199,
- 199,199,199,199,200,200,200,200,200,200,200,200,201,201,201,201,
- 201,202,202,202,202,202,202, 55,203,203,203,203,204,204,204,204,
- 204,204,204,205,205,205,205,205,205,205,205,205,206,206,206,206,
- 206,206,207,207,207,207,207,207,207,207,207,207,208,208,208,208,
- 208,208,208,208,110,110,110,110, 39, 39, 39, 39,209,209,209,209,
- 209,209,209,209,210,210,210,210,210,210,210,210,211,211,211,211,
- 211,211,211,211,212,212,212,212,212,212,212,212,112,112,112,112,
- 112,112,112,112,112,112,112,112,213,213,213,214,214,214,214,214,
- 214,215,215,215,216,216,216,216,216,216,216,216,217,217,217,217,
- 217,217,217,217,218,218,218,218,218,218,218,218,218,218,218,218,
- 218,218,219, 94,220,220,220,220,220,220,220,220,221,221,221,221,
- 221,221,221,221,102,102,102,102,102,102,102,102,222, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,102,102,
- 102, 99,223,224,224,224,224,224,224,224,224,224,225,225,225,225,
- 225,225,225,225,225,225, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 0, 0, 0, 0, 0, 0, 0, 0, 0,226,227,228, 0,229, 0,
- 0, 0, 0, 0,230,230,230,230,230,230,230,230, 91, 91, 91, 91,
- 91, 91, 91, 91,231,231,231,231,231,231,231,231,232,232,232,232,
- 233,233,233,233,234,234,234,234,234,234,234,234,235,235,235,235,
- 235,235,235,235,236, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
- 8, 8, 8, 8, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0,
- 0, 0, 4, 0, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0,
- 2, 5, 6, 0, 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8,
- 8, 8, 8, 8, 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14,
- 16, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19,
- 20, 21, 20, 22, 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7,
- 7, 25, 20, 20, 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27,
- 28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,
- 32, 20, 20, 20, 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33,
- 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40,
- 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44,
- 45, 45, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48,
- 49, 49, 49, 49, 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53,
- 53, 53, 54, 53, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57,
- 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62,
- 63, 63, 63, 63, 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66,
- 67, 67, 67, 67, 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71,
- 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75,
- 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79,
- 80, 80, 80, 80, 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85,
- 0, 84, 86, 0, 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2,
- 2, 2, 92, 2, 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94,
- 0, 95, 96, 0, 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97,
- 98, 98, 98, 98, 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100,
- 0,101, 0, 0,102,100,103,104, 0, 0,100, 0,105,106,106,106,
- 106,106,106,106,106,106,107,105,108,109,109,109,109,109,109,109,
- 109,109,110,108,111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,
- 109,109,109,110,109,109, 0, 0,114,114,114,114,115,115,115,115,
- 116,116,116,116,117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,
- 118,118,118,118,119,119,119,119,120,120,120,120,121,121,121,121,
- 121,121,121,122,123,123,123,123,124,124,124,124,124,124,124,125,
- 126,126,126,126,127,127,127,127,128,128,128,128, 2, 2, 3, 2,
- 2,129,130, 0,131,131,131,131,132, 17, 17, 18, 20, 20, 20,133,
- 7, 7, 7,134, 20, 20, 20, 23, 0,135,109,109,109,109,109,136,
- 137,137,137,137, 0, 0, 0,138,139,139,139,139,140,140,140,140,
- 84, 0, 0, 0,141,141,141,141,142,142,142,142,143,143,143,143,
- 144,144,144,144,145,145,145,145,146,146,146,146,147,147,147,147,
- 148,148,148,148,149,149,149,149,150,150,150,150,151,151,151,151,
- 152,152,152,152,153,153,153,153,154,154,154,154,155,155,155,155,
- 156,156,156,156,157,157,157,157,158,158,158,158,159,159,159,159,
- 160,160,160,160,161,161,161,161,162,162,162,162,163,163,163,163,
- 164,164,164,164,165,165,165,165,166,166,166,166,167,167,167,167,
- 168,168,168,168,169,169,169,169,170,170,170,170,171,171,171,171,
- 172,172,172,172,173,173,173,173,174,174,174,174,175,175,175,175,
- 176,176,176,176,177,177,177,177,178,178,178,178,179,179,179,179,
- 180,180,180,180,181,181,181,181,182,182,182,182,183,183,183,183,
- 184,184,184,184,185,185,185,185,186, 45, 45, 45,187,187,187,187,
- 188,188,188,188,189,189,189,189,190,190,190,190,190,190,191,190,
- 192,192,192,192,193,193,193,193,194,194,194,194,195,195,195,195,
- 196,196,196,196,197,197,197,197,198,198,198,198,199,199,199,199,
- 200,200,200,200,201,201,201,201,202,202,202,202,203,203,203,203,
- 204,204,204,204,205,205,205,205,206,206,206,206,207,207,207,207,
- 208,208,208,208,209,209,209,209,210,210,210,210,211,211,211,211,
- 212,212,212,212,213,213,213,213,214,214,214,214,215,215,215,215,
- 216,216,216,216,217,217,217,217,218,218,218,218,219,219,219,219,
- 220,221,221,221,222,222,222,222,221,221,221,221,223,106,106,106,
- 106,109,109,109,224,224,224,224,225,225,225,225, 0,226, 86, 0,
- 0, 0,226, 7, 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,
- 229,229,229,229,230,230,230,230,231,231,231,231,232,232,232,232,
- 233,233,233,233,234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0,
- 0, 0, 26, 26, 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9,
- 9, 9, 0, 9, 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55,
- 6, 6, 6, 6, 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4,
- 4, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3,
- 0, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3,
- 1, 3, 3, 3, 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64,
- 90, 90, 90, 90, 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7,
- 7, 1, 1, 1, 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5,
- 11, 11, 11, 11, 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22,
- 23, 23, 23, 23, 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36,
- 24, 24, 24, 24, 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25,
- 25, 0, 0, 0, 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8,
- 8, 8, 8, 0, 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29,
- 28, 28, 28, 28, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0,
- 0, 0, 35, 35, 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0,
- 43, 43, 43, 43, 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0,
- 32, 0, 32, 32, 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52,
- 58, 58, 58, 58, 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62,
- 76, 76, 76, 76, 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73,
- 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
- 1, 1, 0, 0, 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9,
- 9, 9, 19, 19, 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9,
- 0, 0, 0, 19, 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27,
- 56, 56, 56, 56, 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13,
- 0, 13, 13, 13, 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15,
- 15, 15, 15, 15, 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 0, 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0,
- 39, 39, 39, 39, 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79,
- 60, 60, 60, 60, 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69,
- 69, 69, 0, 69, 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0,
- 68, 68, 68, 68, 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19,
- 19, 19, 0, 0, 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0,
- 1, 1, 6, 6, 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49,
- 0, 1, 1, 1, 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42,
- 41, 41, 41, 41,118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59,
- 40, 40, 40, 40, 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,
- 106,106,106,106,104,104,104,104,161,161,161,161,110,110,110,110,
- 47, 47, 47, 47, 81, 81, 81, 81,120,120,120,120,116,116,116,116,
- 128,128,128,128, 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98,
- 97, 97, 97, 97, 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,
- 112,112,112,112, 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,
- 122,122,122,122, 89, 89, 89, 89,130,130,130,130,144,144,144,144,
- 156,156,156,156,147,147,147,147,148,148,148,148,158,158,158,158,
- 153,153,153,153,149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,
- 101,101,101,101, 96, 96, 96, 96,111,111,111,111,100,100,100,100,
- 100, 36, 36, 36,108,108,108,108,129,129,129,129,109,109,109,109,
- 107,107,107,107,107,107,107, 1,137,137,137,137,124,124,124,124,
- 123,123,123,123,114,114,114,114,102,102,102,102,126,126,126,126,
- 142,142,142,142,125,125,125,125,154,154,154,154,150,150,150,150,
- 141,141,141,141,140,140,140,140,121,121,121,121,133,133,133,133,
- 134,134,134,134,138,138,138,138,143,143,143,143,145,145,145,145,
- 63, 63, 63, 63,157,157,157,157, 80, 80, 80, 80,127,127,127,127,
- 115,115,115,115,159,159,159,159,103,103,103,103,119,119,119,119,
- 146,146,146,146, 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,
- 136,136,136,136, 17, 15, 15, 15,139,139,139,139,105,105,105,105,
- 0, 0, 0, 1, 0, 0, 1, 1,131,131,131,131,151,151,151,151,
- 160,160,160,160,152,152,152,152,113,113,113,113,132,132,132,132,
- 15, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9,
- 9, 10, 9, 11, 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9,
+ 192,192,192,192,193,193,193,193,194,194,194,194,194,194, 66, 66,
+ 195,195,195,195,196,196,196,196,197,197,197,197,198,198,198,198,
+ 199,199,199,199,200,200,200,200,201,201,201,201,201,202,202,202,
+ 202,202,202, 55,203,203,203,203,204,204,204,204,204,204,204,205,
+ 205,205,205,205,206,206,206,206,206,206,207,207,207,207,207,207,
+ 208,208,208,208,110,110,110,110,209,209,209,209,210,210,210,210,
+ 211,211,211,211,212,212,212,212,213,213,213,214,214,214,214,214,
+ 214,215,215,215,216,216,216,216,217,217,217,217,218,218,218,218,
+ 218,218,219, 94,220,220,220,220,221,221,221,221,222, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99,102,102,102, 99,223,224,224,224,224,224,
+ 225,225,225,225,225,225, 0, 0, 8, 0, 0, 0, 0, 0,226,227,
+ 228, 0,229, 0,230,230,230,230,231,231,231,231,232,232,232,232,
+ 233,233,233,233,234,234,234,234,235,235,235,235,236, 0, 0, 0,
+ 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 0, 0, 0, 4, 0,
+ 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 5, 0, 2, 5, 6, 0,
+ 7, 7, 7, 7, 8, 9, 8, 10, 8, 11, 8, 8, 8, 8, 8, 8,
+ 12, 13, 13, 13, 14, 14, 14, 14, 14, 15, 14, 14, 16, 17, 17, 17,
+ 17, 17, 17, 17, 18, 19, 19, 19, 19, 19, 19, 19, 20, 21, 20, 22,
+ 20, 20, 23, 23, 20, 20, 20, 20, 22, 20, 24, 7, 7, 25, 20, 20,
+ 26, 20, 20, 20, 20, 20, 20, 21, 27, 27, 27, 27, 28, 28, 28, 28,
+ 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31, 32, 20, 20, 20,
+ 33, 33, 33, 33, 34, 35, 33, 33, 33, 36, 33, 33, 37, 37, 37, 37,
+ 38, 38, 38, 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41,
+ 42, 42, 42, 42, 43, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45,
+ 46, 46, 46, 46, 46, 46, 46, 47, 48, 48, 48, 48, 49, 49, 49, 49,
+ 49, 50, 51, 49, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 54, 53,
+ 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58,
+ 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 61, 62, 63, 63, 63, 63,
+ 64, 64, 64, 64, 64, 65, 0, 0, 66, 66, 66, 66, 67, 67, 67, 67,
+ 68, 68, 68, 68, 69, 70, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72,
+ 73, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 75, 76, 76, 76, 76,
+ 77, 77, 77, 77, 78, 78, 78, 78, 79, 79, 79, 79, 80, 80, 80, 80,
+ 81, 81, 81, 81, 82, 7, 7, 7, 83, 7, 84, 85, 0, 84, 86, 0,
+ 2, 87, 88, 2, 2, 2, 2, 89, 90, 87, 91, 2, 2, 2, 92, 2,
+ 2, 2, 2, 93, 0, 0, 0, 86, 1, 0, 0, 94, 0, 95, 96, 0,
+ 4, 0, 0, 0, 0, 0, 0, 4, 97, 97, 97, 97, 98, 98, 98, 98,
+ 13, 13, 13, 13, 99, 99, 99, 99,100,100,100,100, 0,101, 0, 0,
+ 102,100,103,104, 0, 0,100, 0,105,106,106,106,106,106,106,106,
+ 106,106,107,105,108,109,109,109,109,109,109,109,109,109,110,108,
+ 111,111,111,111,112, 55, 55, 55, 55, 55, 55,113,109,109,109,110,
+ 109,109, 0, 0,114,114,114,114,115,115,115,115,116,116,116,116,
+ 117,117,117,117, 96, 2, 2, 2, 2, 2, 94, 2,118,118,118,118,
+ 119,119,119,119,120,120,120,120,121,121,121,121,121,121,121,122,
+ 123,123,123,123,124,124,124,124,124,124,124,125,126,126,126,126,
+ 127,127,127,127,128,128,128,128, 2, 2, 3, 2, 2,129,130, 0,
+ 131,131,131,131,132, 17, 17, 18, 20, 20, 20,133, 7, 7, 7,134,
+ 20, 20, 20, 23, 0,135,109,109,109,109,109,136,137,137,137,137,
+ 0, 0, 0,138,139,139,139,139,140,140,140,140, 84, 0, 0, 0,
+ 141,141,141,141,142,142,142,142,143,143,143,143,144,144,144,144,
+ 145,145,145,145,146,146,146,146,147,147,147,147,148,148,148,148,
+ 149,149,149,149,150,150,150,150,151,151,151,151,152,152,152,152,
+ 153,153,153,153,154,154,154,154,155,155,155,155,156,156,156,156,
+ 157,157,157,157,158,158,158,158,159,159,159,159,160,160,160,160,
+ 161,161,161,161,162,162,162,162,163,163,163,163,164,164,164,164,
+ 165,165,165,165,166,166,166,166,167,167,167,167,168,168,168,168,
+ 169,169,169,169,170,170,170,170,171,171,171,171,172,172,172,172,
+ 173,173,173,173,174,174,174,174,175,175,175,175,176,176,176,176,
+ 177,177,177,177,178,178,178,178,179,179,179,179,180,180,180,180,
+ 181,181,181,181,182,182,182,182,183,183,183,183,184,184,184,184,
+ 185,185,185,185,186, 45, 45, 45,187,187,187,187,188,188,188,188,
+ 189,189,189,189,190,190,190,190,190,190,191,190,192,192,192,192,
+ 193,193,193,193,194,194,194,194,195,195,195,195,196,196,196,196,
+ 197,197,197,197,198,198,198,198,199,199,199,199,200,200,200,200,
+ 201,201,201,201,202,202,202,202,203,203,203,203,204,204,204,204,
+ 205,205,205,205,206,206,206,206,207,207,207,207,208,208,208,208,
+ 209,209,209,209,210,210,210,210,211,211,211,211,212,212,212,212,
+ 213,213,213,213,214,214,214,214,215,215,215,215,216,216,216,216,
+ 217,217,217,217,218,218,218,218,219,219,219,219,220,221,221,221,
+ 222,222,222,222,221,221,221,221,223,106,106,106,106,109,109,109,
+ 224,224,224,224,225,225,225,225, 0,226, 86, 0, 0, 0,226, 7,
+ 82,138, 7, 0, 0, 0,227, 86,228,228,228,228,229,229,229,229,
+ 230,230,230,230,231,231,231,231,232,232,232,232,233,233,233,233,
+ 234, 0, 0, 0, 0, 0, 0, 0, 0, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 19, 0, 0, 0, 19, 0, 19, 0, 0, 0, 0, 0, 26, 26,
+ 1, 1, 1, 1, 9, 9, 9, 9, 0, 9, 9, 9, 9, 9, 0, 9,
+ 9, 0, 9, 0, 9, 9, 55, 55, 55, 55, 55, 55, 6, 6, 6, 6,
+ 6, 1, 1, 6, 6, 4, 4, 4, 4, 4, 4, 4, 4, 14, 14, 14,
+ 14, 14, 14, 14, 3, 3, 3, 3, 3, 0, 3, 3, 0, 3, 3, 3,
+ 3, 3, 3, 0, 3, 3, 3, 1, 1, 1, 3, 3, 1, 3, 3, 3,
+ 37, 37, 37, 37, 38, 38, 38, 38, 64, 64, 64, 64, 90, 90, 90, 90,
+ 95, 95, 95, 95, 3, 3, 0, 3, 7, 7, 7, 7, 7, 1, 1, 1,
+ 1, 7, 7, 7, 0, 0, 7, 7, 5, 5, 5, 5, 11, 11, 11, 11,
+ 10, 10, 10, 10, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,
+ 16, 16, 16, 16, 20, 20, 20, 20, 36, 36, 36, 36, 24, 24, 24, 24,
+ 24, 24, 24, 0, 18, 18, 18, 18, 25, 25, 25, 25, 25, 0, 0, 0,
+ 0, 25, 25, 25, 33, 33, 33, 33, 8, 8, 8, 8, 8, 8, 8, 0,
+ 12, 12, 12, 12, 30, 30, 30, 30, 29, 29, 29, 29, 28, 28, 28, 28,
+ 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 35, 35,
+ 45, 45, 45, 45, 44, 44, 44, 44, 44, 0, 0, 0, 43, 43, 43, 43,
+ 46, 46, 46, 46, 31, 31, 31, 31, 32, 32, 0, 0, 32, 0, 32, 32,
+ 32, 32, 32, 32, 48, 48, 48, 48, 52, 52, 52, 52, 58, 58, 58, 58,
+ 54, 54, 54, 54, 91, 91, 91, 91, 62, 62, 62, 62, 76, 76, 76, 76,
+ 93, 93, 93, 93, 70, 70, 70, 70, 73, 73, 73, 73, 1, 1, 1, 0,
+ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0,
+ 19, 19, 9, 9, 9, 9, 9, 6, 19, 9, 9, 9, 9, 9, 19, 19,
+ 9, 9, 9, 19, 6, 19, 19, 19, 19, 19, 19, 9, 0, 0, 0, 19,
+ 0, 0, 9, 0, 0, 0, 19, 19, 27, 27, 27, 27, 56, 56, 56, 56,
+ 61, 61, 61, 61, 13, 13, 13, 13, 0, 13, 0, 13, 0, 13, 13, 13,
+ 13, 13, 1, 1, 1, 1, 12, 12, 0, 15, 15, 15, 15, 15, 15, 15,
+ 15, 1, 1, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0,
+ 26, 26, 26, 26, 26, 12, 12, 12, 12, 12, 12, 0, 39, 39, 39, 39,
+ 86, 86, 86, 86, 77, 77, 77, 77, 79, 79, 79, 79, 60, 60, 60, 60,
+ 65, 65, 65, 65, 75, 75, 75, 75, 69, 69, 69, 69, 69, 69, 0, 69,
+ 74, 74, 74, 74, 84, 84, 84, 84, 84, 84, 84, 0, 68, 68, 68, 68,
+ 92, 92, 92, 92, 87, 87, 87, 87, 19, 9, 19, 19, 19, 19, 0, 0,
+ 2, 2, 2, 2, 19, 19, 19, 4, 3, 3, 0, 0, 1, 1, 6, 6,
+ 0, 0, 17, 17, 17, 17, 0, 0, 49, 49, 49, 49, 0, 1, 1, 1,
+ 71, 71, 71, 71, 67, 67, 67, 67, 42, 42, 42, 42, 41, 41, 41, 41,
+ 118,118,118,118, 53, 53, 53, 53, 59, 59, 59, 59, 40, 40, 40, 40,
+ 51, 51, 51, 51, 50, 50, 50, 50,135,135,135,135,106,106,106,106,
+ 104,104,104,104,161,161,161,161,110,110,110,110, 47, 47, 47, 47,
+ 81, 81, 81, 81,120,120,120,120,116,116,116,116,128,128,128,128,
+ 66, 66, 66, 66, 72, 72, 72, 72, 98, 98, 98, 98, 97, 97, 97, 97,
+ 57, 57, 57, 57, 88, 88, 88, 88,117,117,117,117,112,112,112,112,
+ 78, 78, 78, 78, 83, 83, 83, 83, 82, 82, 82, 82,122,122,122,122,
+ 89, 89, 89, 89,130,130,130,130,144,144,144,144,156,156,156,156,
+ 147,147,147,147,148,148,148,148,158,158,158,158,153,153,153,153,
+ 149,149,149,149, 94, 94, 94, 94, 85, 85, 85, 85,101,101,101,101,
+ 96, 96, 96, 96,111,111,111,111,100,100,100,100,100, 36, 36, 36,
+ 108,108,108,108,129,129,129,129,109,109,109,109,107,107,107,107,
+ 107,107,107, 1,137,137,137,137,124,124,124,124,123,123,123,123,
+ 114,114,114,114,102,102,102,102,126,126,126,126,142,142,142,142,
+ 125,125,125,125,154,154,154,154,150,150,150,150,141,141,141,141,
+ 140,140,140,140,121,121,121,121,133,133,133,133,134,134,134,134,
+ 138,138,138,138,143,143,143,143,145,145,145,145, 63, 63, 63, 63,
+ 157,157,157,157, 80, 80, 80, 80,127,127,127,127,115,115,115,115,
+ 159,159,159,159,103,103,103,103,119,119,119,119,146,146,146,146,
+ 99, 99, 99, 99,136,139, 13, 13,155,155,155,155,136,136,136,136,
+ 17, 15, 15, 15,139,139,139,139,105,105,105,105, 0, 0, 0, 1,
+ 0, 0, 1, 1,131,131,131,131,151,151,151,151,160,160,160,160,
+ 152,152,152,152,113,113,113,113,132,132,132,132, 15, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 10, 9, 11,
+ 12, 13, 9, 9, 9, 14, 9, 9, 15, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 16, 17, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9, 21, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 16, 17, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 18, 19, 20, 9,
- 21, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 22, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
@@ -6478,58 +5336,57 @@ _hb_ucd_u8[13602] =
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30,
- 0, 0, 31, 32, 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37,
- 38, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 23, 24, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 23, 0, 0, 24, 25, 26, 27, 28, 29, 30, 0, 0, 31, 32,
+ 0, 33, 0, 34, 0, 35, 0, 0, 0, 0, 36, 37, 38, 39, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47, 0, 0, 0, 0,
+ 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0,
+ 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 43, 44, 0, 45, 0, 0, 0, 0, 0, 0, 46, 47,
- 0, 0, 0, 0, 0, 48, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 50, 51, 0, 0, 0, 52, 0, 0, 53, 0,
- 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 55, 0,
- 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 57,
+ 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, 0, 0,
+ 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 58, 59, 60, 61, 62, 63, 64, 65, 0, 0,
- 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 67, 68,
+ 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 97, 98, 99,100,101,102,103, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0, 0, 0,108, 0,
+ 109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,115, 0, 0, 0,
+ 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 67, 68, 0, 69, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 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, 97, 98, 99,100,
- 101,102,103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0,105,106, 0,107, 0,
- 0, 0,108, 0,109, 0,110, 0,111,112,113, 0,114, 0, 0, 0,
- 115, 0, 0, 0,116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,117,
+ 0, 0,118,119,120,121, 0,122,123,124,125,126, 0,127, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,118,119,120,121, 0,122,123,124,125,126,
- 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,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, 0, 0, 0,158,
+ 159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0, 0, 0, 0, 0,
+ 164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0,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,
- 0, 0, 0,158,159,160,161, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,162,163, 0, 0, 0,
- 0, 0, 0, 0,164, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,165, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,166, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,167, 0, 0,
+ 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,168, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0, 0, 0,173,174,
+ 175,176,177,178,179,180,181,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,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0,169,170, 0, 0, 0, 0,171,172, 0,
- 0, 0,173,174,175,176,177,178,179,180,181,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2,
- 3, 4,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
};
static const uint16_t
_hb_ucd_u16[4888] =
@@ -6842,21 +5699,14 @@ _hb_ucd_u16[4888] =
817, 818, 819, 820, 821, 935, 0, 0,
};
static const int16_t
-_hb_ucd_i16[196] =
+_hb_ucd_i16[92] =
{
- 0, 0, 0, 0, 1, -1, 0, 0, 2, 0, -2, 0, 0, 0, 0, 2,
- 0, -2, 0, 0, 0, 0, 0, 16, 0, 0, 0, -16, 0, 0, 1, -1,
- 0, 0, 0, 1, -1, 0, 0, 0, 0, 1, -1, 0, 3, 3, 3, -3,
- -3, -3, 0, 0, 0, 2016, 0, 0, 0, 0, 0, 2527, 1923, 1914, 1918, 0,
- 2250, 0, 0, 0, 0, 0, 0, 138, 0, 7, 0, 0, -7, 0, 0, 0,
- 1, -1, 1, -1, -1, 1, -1, 0, 1824, 0, 0, 0, 0, 0, 2104, 0,
- 2108, 2106, 0, 2106, 1316, 0, 0, 0, 0, 1, -1, 1, -1, -138, 0, 0,
- 1, -1, 8, 8, 8, 0, 7, 7, 0, 0, -8, -8, -8, -7, -7, 0,
- 1, -1, 0, 2,-1316, 1, -1, 0, -1, 1, -1, 1, -1, 3, 1, -1,
- -3, 1, -1, 1, -1, 0, 0,-1914,-1918, 0, 0,-1923,-1824, 0, 0, 0,
- 0,-2016, 0, 0, 1, -1, 0, 1, 0, 0,-2104, 0, 0, 0, 0,-2106,
- -2108,-2106, 0, 0, 1, -1,-2250, 0, 0, 0,-2527, 0, 0, -2, 0, 1,
- -1, 0, 1, -1,
+ 0, 0, 1, -1, 2, 0, -2, 0, 0, 2, 0, -2, 0, 16, 0, -16,
+ 0, 1, -1, 0, 3, 3, 3, -3, -3, -3, 0, 2016, 0, 2527, 1923, 1914,
+ 1918, 0, 2250, 0, 0, 138, 0, 7, -7, 0, -1, 1, 1824, 0, 2104, 0,
+ 2108, 2106, 0, 2106, 1316, 0, -1, -138, 8, 8, 8, 0, 7, 7, -8, -8,
+ -8, -7,-1316, 1, -1, 3, -3, 1, 0,-1914,-1918, 0, 0,-1923,-1824, 0,
+ 0,-2016,-2104, 0, 0,-2106,-2108,-2106,-2250, 0,-2527, 0,
};
static inline uint_fast8_t
@@ -6877,17 +5727,17 @@ _hb_ucd_b4 (const uint8_t* a, unsigned i)
static inline int_fast16_t
_hb_ucd_bmg (unsigned u)
{
- return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7714+(((_hb_ucd_u8[7594+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>2>>3>>3))<<3)+((u>>2>>3)&7u))])<<3)+((u>>2)&7u))])<<2)+((u)&3u)]:0;
+ return u<65380u?_hb_ucd_i16[((_hb_ucd_u8[7858+(((_hb_ucd_u8[7626+(((_hb_ucd_u8[7530+(((_hb_ucd_b4(7466+_hb_ucd_u8,u>>1>>2>>3>>3))<<3)+((u>>1>>2>>3)&7u))])<<3)+((u>>1>>2)&7u))])<<2)+((u>>1)&3u))])<<1)+((u)&1u)]:0;
}
static inline uint_fast8_t
_hb_ucd_sc (unsigned u)
{
- return u<918016u?_hb_ucd_u8[11480+(((_hb_ucd_u8[10532+(((_hb_ucd_u8[9124+(((_hb_ucd_u8[8500+(((_hb_ucd_u8[8050+(u>>2>>2>>3>>4)])<<4)+((u>>2>>2>>3)&15u))])<<3)+((u>>2>>2)&7u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
+ return u<918016u?_hb_ucd_u8[11124+(((_hb_ucd_u8[10176+(((_hb_ucd_u8[9204+(((_hb_ucd_u8[8524+(((_hb_ucd_u8[8220+(((_hb_ucd_u8[8106+(u>>2>>2>>2>>3>>4)])<<4)+((u>>2>>2>>2>>3)&15u))])<<3)+((u>>2>>2>>2)&7u))])<<2)+((u>>2>>2)&3u))])<<2)+((u>>2)&3u))])<<2)+((u)&3u))]:2;
}
static inline uint_fast16_t
_hb_ucd_dm (unsigned u)
{
- return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12802+(((_hb_ucd_u8[12420+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
+ return u<195102u?_hb_ucd_u16[1576+(((_hb_ucd_u8[12446+(((_hb_ucd_u8[12064+(u>>4>>5)])<<5)+((u>>4)&31u))])<<4)+((u)&15u))]:0;
}
#endif
diff --git a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
index c216379201..036c71a424 100644
--- a/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
+++ b/thirdparty/harfbuzz/src/hb-unicode-emoji-table.hh
@@ -24,42 +24,37 @@
#include "hb-unicode.hh"
static const uint8_t
-_hb_emoji_u8[544] =
+_hb_emoji_u8[464] =
{
16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,118,152,
- 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 3, 0, 0, 4, 0, 5, 0, 0, 0, 0, 0, 6, 0, 7, 8,
- 0, 0, 0, 9, 0, 0, 10, 11, 12, 13, 14, 13, 15, 16, 17, 0,
- 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 19, 20, 0, 0,
- 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0,
- 13, 13, 13, 13, 23, 24, 25, 26, 27, 28, 13, 13, 13, 13, 13, 29,
- 13, 13, 13, 13, 30, 31, 13, 13, 13, 32, 13, 13, 0, 33, 0, 34,
- 35, 36, 37, 13, 38, 39, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0,
- 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 30,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 16, 0, 2, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 4, 0, 0, 2, 0, 0,240, 3, 0, 6, 0, 0,
- 0, 0, 0, 12, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
- 0,128, 0, 0, 0,254, 15, 7, 4, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0, 0, 0, 0,120,
- 191,255,247,255,255,255,255,255,255,255,255,255,255,255,255,255,
- 63, 0,255,255,255,255,255,255, 63,255, 87, 32, 2, 1, 24, 0,
- 144, 80,184, 0,248, 0, 0, 0, 0, 0,224, 0, 2, 0, 1,128,
- 0, 0, 0, 0, 0, 0, 48, 0,224, 0, 0, 24, 0, 0, 0, 0,
- 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32,
- 0, 0,128, 2, 0, 0, 0, 0, 0,224, 0, 0, 0,128, 0, 0,
- 0, 0, 0, 0, 0,240, 3,192, 0, 64,254, 7, 0,224,255,255,
- 255,255,255,255, 63, 0, 0, 0,254,255, 0, 4, 0,128,252,247,
- 0,254,255,255,255,255,255,255,255,255,255,255,255,255,255, 7,
- 255,255,255,255,255,255,255, 63,192,255,255,255,255,255,255,255,
- 255,255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,240,255,
- 0, 0,224,255,255,255,255,255, 0,240, 0, 0, 0, 0, 0, 0,
- 0,255, 0,252, 0, 0, 0, 0, 0,255, 0, 0, 0,192,255,255,
- 0,240,255,255,255,255,255,247,191,255,255,255,255,255,255,255,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 3, 4, 0, 0, 5, 6, 0, 7, 0, 8, 9, 10, 11, 12,
+ 0, 0, 13, 0, 0, 0, 14, 0, 15, 0, 0, 0, 0, 16, 0, 0,
+ 17, 17, 18, 19, 20, 17, 17, 21, 17, 17, 22, 17, 23, 17, 24, 25,
+ 26, 27, 28, 17, 17, 17, 0, 0, 17, 17, 17, 17, 17, 17, 17, 29,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 3, 0, 0, 4, 0, 0,
+ 5, 6, 0, 0, 7, 8, 0, 0, 8, 0, 9, 10, 0, 0, 11, 0,
+ 0, 12, 13, 14, 15, 16, 16, 16, 17, 16, 16, 16, 18, 19, 20, 21,
+ 22, 23, 0, 0, 0, 24, 0, 0, 25, 0, 26, 0, 0, 27, 0, 0,
+ 28, 0, 0, 0, 16, 16, 16, 16, 29, 9, 0, 30, 31, 32, 16, 33,
+ 34, 35, 36, 16, 16, 16, 16, 37, 16, 38, 39, 16, 16, 16, 40, 0,
+ 0, 0, 0, 41, 0, 0, 42, 16, 43, 0, 44, 0, 45, 46, 16, 16,
+ 47, 48, 49, 16, 16, 16, 16, 38, 0, 0, 0, 0, 0, 66, 0, 0,
+ 0, 0, 0, 16, 0, 2, 0, 0, 4, 0, 0, 2, 0, 0,240, 3,
+ 0, 6, 0, 0, 0, 0, 0, 12, 0, 1, 0, 0, 0,128, 0, 0,
+ 0,254, 15, 7, 4, 0, 0, 0, 0, 12, 64, 0, 1, 0, 0, 0,
+ 0, 0, 0,120,191,255,247,255,255,255,255,255, 63, 0,255,255,
+ 63,255, 87, 32, 2, 1, 24, 0,144, 80,184, 0,248, 0, 0, 0,
+ 0, 0,224, 0, 2, 0, 1,128, 0, 0, 48, 0,224, 0, 0, 24,
+ 0, 0, 33, 0, 0, 0, 1, 32, 0, 0,128, 2, 0,224, 0, 0,
+ 0,240, 3,192, 0, 64,254, 7, 0,224,255,255, 63, 0, 0, 0,
+ 254,255, 0, 4, 0,128,252,247, 0,254,255,255,255,255,255, 7,
+ 255,255,255, 63,192,255,255,255,255,255, 0, 0, 0, 0,240,255,
+ 0, 0,224,255, 0,240, 0, 0, 0,255, 0,252, 0,255, 0, 0,
+ 0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255,
};
static inline unsigned
@@ -75,7 +70,7 @@ _hb_emoji_b1 (const uint8_t* a, unsigned i)
static inline uint_fast8_t
_hb_emoji_is_Extended_Pictographic (unsigned u)
{
- return u<131070u?_hb_emoji_b1(224+_hb_emoji_u8,((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>6>>4))<<4)+((u>>6)&15u))])<<6)+((u)&63u)):0;
+ return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0;
}
diff --git a/thirdparty/harfbuzz/src/hb-unicode.cc b/thirdparty/harfbuzz/src/hb-unicode.cc
index 83ead6398b..c1795dc7f2 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.cc
+++ b/thirdparty/harfbuzz/src/hb-unicode.cc
@@ -169,7 +169,7 @@ hb_unicode_funcs_get_default ()
#endif
/**
- * hb_unicode_funcs_create: (Xconstructor)
+ * hb_unicode_funcs_create:
* @parent: (nullable): Parent Unicode-functions structure
*
* Creates a new #hb_unicode_funcs_t structure of Unicode functions.
@@ -281,7 +281,7 @@ hb_unicode_funcs_destroy (hb_unicode_funcs_t *ufuncs)
*
* Attaches a user-data key/data pair to the specified Unicode-functions structure.
*
- * Return value: %true if success, %false otherwise
+ * Return value: `true` if success, `false` otherwise
*
* Since: 0.9.2
**/
@@ -308,8 +308,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
* Since: 0.9.2
**/
void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key)
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key)
{
return hb_object_get_user_data (ufuncs, key);
}
@@ -340,7 +340,7 @@ hb_unicode_funcs_make_immutable (hb_unicode_funcs_t *ufuncs)
* Tests whether the specified Unicode-functions structure
* is immutable.
*
- * Return value: %true if @ufuncs is immutable, %false otherwise
+ * Return value: `true` if @ufuncs is immutable, `false` otherwise
*
* Since: 0.9.2
**/
@@ -421,7 +421,7 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
* Calls the composition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @a and @b composed, %false otherwise
+ * Return value: `true` if @a and @b composed, `false` otherwise
*
* Since: 0.9.2
**/
@@ -446,7 +446,7 @@ hb_unicode_compose (hb_unicode_funcs_t *ufuncs,
* Calls the decomposition function of the specified
* Unicode-functions structure @ufuncs.
*
- * Return value: %true if @ab was decomposed, %false otherwise
+ * Return value: `true` if @ab was decomposed, `false` otherwise
*
* Since: 0.9.2
**/
diff --git a/thirdparty/harfbuzz/src/hb-unicode.h b/thirdparty/harfbuzz/src/hb-unicode.h
index c04ee15a09..faa8d67924 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.h
+++ b/thirdparty/harfbuzz/src/hb-unicode.h
@@ -317,8 +317,8 @@ hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
HB_EXTERN void *
-hb_unicode_funcs_get_user_data (hb_unicode_funcs_t *ufuncs,
- hb_user_data_key_t *key);
+hb_unicode_funcs_get_user_data (const hb_unicode_funcs_t *ufuncs,
+ hb_user_data_key_t *key);
HB_EXTERN void
@@ -429,7 +429,7 @@ typedef hb_script_t (*hb_unicode_script_func_t) (hb_unicode_funcs_t *ufuncs,
* The method must return an #hb_bool_t indicating the success
* of the composition.
*
- * Return value: %true is @a,@b composed, %false otherwise
+ * Return value: `true` is @a,@b composed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
@@ -453,7 +453,7 @@ typedef hb_bool_t (*hb_unicode_compose_func_t) (hb_unicode_funcs_t *ufuncs,
* output parameters (if successful). The method must return an
* #hb_bool_t indicating the success of the composition.
*
- * Return value: %true if @ab decomposed, %false otherwise
+ * Return value: `true` if @ab decomposed, `false` otherwise
*
**/
typedef hb_bool_t (*hb_unicode_decompose_func_t) (hb_unicode_funcs_t *ufuncs,
diff --git a/thirdparty/harfbuzz/src/hb-unicode.hh b/thirdparty/harfbuzz/src/hb-unicode.hh
index 4c28bb0cdf..39aaee5baa 100644
--- a/thirdparty/harfbuzz/src/hb-unicode.hh
+++ b/thirdparty/harfbuzz/src/hb-unicode.hh
@@ -105,12 +105,9 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
unsigned int
modified_combining_class (hb_codepoint_t u)
{
- /* XXX This hack belongs to the USE shaper (for Tai Tham):
- * Reorder SAKOT to ensure it comes after any tone marks. */
+ /* Reorder SAKOT to ensure it comes after any tone marks. */
if (unlikely (u == 0x1A60u)) return 254;
-
- /* XXX This hack belongs to the Tibetan shaper:
- * Reorder PADMA to ensure it comes after any vowel marks. */
+ /* Reorder PADMA to ensure it comes after any vowel marks. */
if (unlikely (u == 0x0FC6u)) return 254;
/* Reorder TSA -PHRU to reorder before U+0F74 */
if (unlikely (u == 0x0F39u)) return 127;
diff --git a/thirdparty/harfbuzz/src/hb-vector.hh b/thirdparty/harfbuzz/src/hb-vector.hh
index 6c7d32e49d..a6d9f6b3fb 100644
--- a/thirdparty/harfbuzz/src/hb-vector.hh
+++ b/thirdparty/harfbuzz/src/hb-vector.hh
@@ -29,6 +29,7 @@
#include "hb.hh"
#include "hb-array.hh"
+#include "hb-meta.hh"
#include "hb-null.hh"
@@ -59,7 +60,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
hb_vector_t (const hb_vector_t &o) : hb_vector_t ()
{
alloc (o.length);
- hb_copy (o, *this);
+ if (unlikely (in_error ())) return;
+ copy_vector (o);
}
hb_vector_t (hb_vector_t &&o)
{
@@ -70,9 +72,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
~hb_vector_t () { fini (); }
- private:
- int allocated = 0; /* == -1 means allocation failed. */
public:
+ int allocated = 0; /* == -1 means allocation failed. */
unsigned int length = 0;
public:
Type *arrayZ = nullptr;
@@ -108,7 +109,10 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
reset ();
alloc (o.length);
- hb_copy (o, *this);
+ if (unlikely (in_error ())) return *this;
+
+ copy_vector (o);
+
return *this;
}
hb_vector_t& operator = (hb_vector_t &&o)
@@ -184,12 +188,14 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
if (unlikely (!resize (length + 1)))
return &Crap (Type);
- return &arrayZ[length - 1];
+ return std::addressof (arrayZ[length - 1]);
}
- template <typename T>
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (!std::is_copy_constructible<T2>::value &&
+ std::is_copy_assignable<T>::value)>
Type *push (T&& v)
{
- /* TODO Emplace? */
Type *p = push ();
if (p == &Crap (Type))
// If push failed to allocate then don't copy v, since this may cause
@@ -199,18 +205,34 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
*p = std::forward<T> (v);
return p;
}
+ template <typename T,
+ typename T2 = Type,
+ hb_enable_if (std::is_copy_constructible<T2>::value)>
+ Type *push (T&& v)
+ {
+ if (unlikely (!alloc (length + 1)))
+ // If push failed to allocate then don't copy v, since this may cause
+ // the created copy to leak memory since we won't have stored a
+ // reference to it.
+ return &Crap (Type);
+
+ /* Emplace. */
+ length++;
+ Type *p = std::addressof (arrayZ[length - 1]);
+ return new (p) Type (std::forward<T> (v));
+ }
bool in_error () const { return allocated < 0; }
template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (hb_is_trivially_copy_assignable(T))>
Type *
realloc_vector (unsigned new_allocated)
{
return (Type *) hb_realloc (arrayZ, new_allocated * sizeof (Type));
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (!hb_is_trivially_copy_assignable(T))>
Type *
realloc_vector (unsigned new_allocated)
{
@@ -230,8 +252,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_constructible<T>::value ||
- !std::is_default_constructible<T>::value)>
+ hb_enable_if (hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -239,8 +260,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
length = size;
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_constructible<T>::value &&
- std::is_default_constructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_constructible(T))>
void
grow_vector (unsigned size)
{
@@ -252,14 +272,52 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_destructible<T>::value)>
+ hb_enable_if (hb_is_trivially_copyable (T))>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = other.length;
+ hb_memcpy ((void *) arrayZ, (const void *) other.arrayZ, length * item_size);
+ }
+ template <typename T = Type,
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ std::is_copy_constructible<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type (other.arrayZ[length - 1]);
+ }
+ }
+ template <typename T = Type,
+ hb_enable_if (!hb_is_trivially_copyable (T) &&
+ !std::is_copy_constructible<T>::value &&
+ std::is_default_constructible<T>::value &&
+ std::is_copy_assignable<T>::value)>
+ void
+ copy_vector (const hb_vector_t &other)
+ {
+ length = 0;
+ while (length < other.length)
+ {
+ length++;
+ new (std::addressof (arrayZ[length - 1])) Type ();
+ arrayZ[length - 1] = other.arrayZ[length - 1];
+ }
+ }
+
+ template <typename T = Type,
+ hb_enable_if (hb_is_trivially_destructible(T))>
void
shrink_vector (unsigned size)
{
length = size;
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_destructible<T>::value)>
+ hb_enable_if (!hb_is_trivially_destructible(T))>
void
shrink_vector (unsigned size)
{
@@ -271,7 +329,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
}
template <typename T = Type,
- hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (hb_is_trivially_copy_assignable(T))>
void
shift_down_vector (unsigned i)
{
@@ -280,7 +338,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
(length - i) * sizeof (Type));
}
template <typename T = Type,
- hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
+ hb_enable_if (!hb_is_trivially_copy_assignable(T))>
void
shift_down_vector (unsigned i)
{
@@ -341,7 +399,7 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
Type pop ()
{
if (!length) return Null (Type);
- Type v = std::move (arrayZ[length - 1]);
+ Type v = arrayZ[length - 1];
arrayZ[length - 1].~Type ();
length--;
return v;
@@ -351,8 +409,8 @@ struct hb_vector_t : std::conditional<sorted, hb_vector_t<Type, false>, hb_empty
{
if (unlikely (i >= length))
return;
- arrayZ[i].~Type ();
shift_down_vector (i + 1);
+ arrayZ[length - 1].~Type ();
length--;
}
diff --git a/thirdparty/harfbuzz/src/hb-version.h b/thirdparty/harfbuzz/src/hb-version.h
index 493a09f8cf..a1586a58b6 100644
--- a/thirdparty/harfbuzz/src/hb-version.h
+++ b/thirdparty/harfbuzz/src/hb-version.h
@@ -41,26 +41,26 @@ HB_BEGIN_DECLS
*
* The major component of the library version available at compile-time.
*/
-#define HB_VERSION_MAJOR 3
+#define HB_VERSION_MAJOR 5
/**
* HB_VERSION_MINOR:
*
* The minor component of the library version available at compile-time.
*/
-#define HB_VERSION_MINOR 3
+#define HB_VERSION_MINOR 1
/**
* HB_VERSION_MICRO:
*
* The micro component of the library version available at compile-time.
*/
-#define HB_VERSION_MICRO 2
+#define HB_VERSION_MICRO 0
/**
* HB_VERSION_STRING:
*
* A string literal containing the library version available at compile-time.
*/
-#define HB_VERSION_STRING "3.3.2"
+#define HB_VERSION_STRING "5.1.0"
/**
* HB_VERSION_ATLEAST:
diff --git a/thirdparty/harfbuzz/src/hb.hh b/thirdparty/harfbuzz/src/hb.hh
index b9f5f71415..8ec638a2b4 100644
--- a/thirdparty/harfbuzz/src/hb.hh
+++ b/thirdparty/harfbuzz/src/hb.hh
@@ -29,7 +29,6 @@
#ifndef HB_HH
#define HB_HH
-
#ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC
#ifdef _MSC_VER
#pragma warning( disable: 4068 ) /* Unknown pragma */
@@ -65,6 +64,7 @@
#pragma GCC diagnostic error "-Wbitwise-instead-of-logical"
#pragma GCC diagnostic error "-Wcast-align"
#pragma GCC diagnostic error "-Wcast-function-type"
+#pragma GCC diagnostic error "-Wcomma"
#pragma GCC diagnostic error "-Wdelete-non-virtual-dtor"
#pragma GCC diagnostic error "-Wembedded-directive"
#pragma GCC diagnostic error "-Wextra-semi-stmt"
@@ -183,7 +183,7 @@
#include <cassert>
#include <cfloat>
#include <climits>
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
# define _USE_MATH_DEFINES
#endif
#include <cmath>
@@ -470,6 +470,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
/* Headers we include for everyone. Keep topologically sorted by dependency.
* They express dependency amongst themselves, but no other file should include
* them directly.*/
+#include "hb-cplusplus.hh"
#include "hb-meta.hh"
#include "hb-mutex.hh"
#include "hb-number.hh"
diff --git a/thirdparty/icu4c/LICENSE b/thirdparty/icu4c/LICENSE
index 970ae074cb..80b587723a 100644
--- a/thirdparty/icu4c/LICENSE
+++ b/thirdparty/icu4c/LICENSE
@@ -1,6 +1,19 @@
-COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
-Copyright © 1991-2020 Unicode, Inc. All rights reserved.
+See Terms of Use <https://www.unicode.org/copyright.html>
+for definitions of Unicode Inc.’s Data Files and Software.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2022 Unicode, Inc. All rights reserved.
Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
Permission is hereby granted, free of charge, to any person obtaining
@@ -32,7 +45,7 @@ shall not be used in advertising or otherwise to promote the sale,
use or other dealings in these Data Files or Software without prior
written authorization of the copyright holder.
----------------------
+----------------------------------------------------------------------
Third-Party Software Licenses
@@ -40,7 +53,9 @@ This section contains third-party software notices and/or additional
terms for licensed third-party software components included within ICU
libraries.
-1. ICU License - ICU 1.8.1 to ICU 57.1
+----------------------------------------------------------------------
+
+ICU License - ICU 1.8.1 to ICU 57.1
COPYRIGHT AND PERMISSION NOTICE
@@ -75,7 +90,9 @@ of the copyright holder.
All trademarks and registered trademarks mentioned herein are the
property of their respective owners.
-2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
+----------------------------------------------------------------------
+
+Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
# The Google Chrome software developed by Google is licensed under
# the BSD license. Other software included in this distribution is
@@ -279,7 +296,9 @@ property of their respective owners.
#
# ---------------COPYING.ipadic-----END----------------------------------
-3. Lao Word Break Dictionary Data (laodict.txt)
+----------------------------------------------------------------------
+
+Lao Word Break Dictionary Data (laodict.txt)
# Copyright (C) 2016 and later: Unicode, Inc. and others.
# License & terms of use: http://www.unicode.org/copyright.html
@@ -319,7 +338,9 @@ property of their respective owners.
# OF THE POSSIBILITY OF SUCH DAMAGE.
# --------------------------------------------------------------------------
-4. Burmese Word Break Dictionary Data (burmesedict.txt)
+----------------------------------------------------------------------
+
+Burmese Word Break Dictionary Data (burmesedict.txt)
# Copyright (c) 2014 International Business Machines Corporation
# and others. All Rights Reserved.
@@ -359,7 +380,9 @@ property of their respective owners.
# SUCH DAMAGE.
# --------------------------------------------------------------------------
-5. Time Zone Database
+----------------------------------------------------------------------
+
+Time Zone Database
ICU uses the public domain data and code derived from Time Zone
Database for its time zone support. The ownership of the TZ database
@@ -382,7 +405,9 @@ Database section 7.
# making a contribution to the database or code waives all rights to
# future claims in that contribution or in the TZ Database.
-6. Google double-conversion
+----------------------------------------------------------------------
+
+Google double-conversion
Copyright 2006-2011, the V8 project authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -410,3 +435,85 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+
+File: aclocal.m4 (only for ICU4C)
+Section: pkg.m4 - Macros to locate and utilise pkg-config.
+
+
+Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.
+
+As a special exception to the GNU General Public License, if you
+distribute this file as part of a program that contains a
+configuration script generated by Autoconf, you may include it under
+the same distribution terms that you use for the rest of that
+program.
+
+
+(The condition for the exception is fulfilled because
+ICU4C includes a configuration script generated by Autoconf,
+namely the `configure` script.)
+
+----------------------------------------------------------------------
+
+File: config.guess (only for ICU4C)
+
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, see <https://www.gnu.org/licenses/>.
+
+As a special exception to the GNU General Public License, if you
+distribute this file as part of a program that contains a
+configuration script generated by Autoconf, you may include it under
+the same distribution terms that you use for the rest of that
+program. This Exception is an additional permission under section 7
+of the GNU General Public License, version 3 ("GPLv3").
+
+
+(The condition for the exception is fulfilled because
+ICU4C includes a configuration script generated by Autoconf,
+namely the `configure` script.)
+
+----------------------------------------------------------------------
+
+File: install-sh (only for ICU4C)
+
+
+Copyright 1991 by the Massachusetts Institute of Technology
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
diff --git a/thirdparty/icu4c/common/brkeng.cpp b/thirdparty/icu4c/common/brkeng.cpp
index 52e9c53621..dc9fb99bf1 100644
--- a/thirdparty/icu4c/common/brkeng.cpp
+++ b/thirdparty/icu4c/common/brkeng.cpp
@@ -79,6 +79,7 @@ UnhandledEngine::findBreaks( UText *text,
int32_t /* startPos */,
int32_t endPos,
UVector32 &/*foundBreaks*/,
+ UBool /* isPhraseBreaking */,
UErrorCode &status) const {
if (U_FAILURE(status)) return 0;
UChar32 c = utext_current32(text);
diff --git a/thirdparty/icu4c/common/brkeng.h b/thirdparty/icu4c/common/brkeng.h
index 6843f1cc95..127ba59e18 100644
--- a/thirdparty/icu4c/common/brkeng.h
+++ b/thirdparty/icu4c/common/brkeng.h
@@ -75,6 +75,7 @@ class LanguageBreakEngine : public UMemory {
int32_t startPos,
int32_t endPos,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode &status) const = 0;
};
@@ -194,6 +195,7 @@ class UnhandledEngine : public LanguageBreakEngine {
int32_t startPos,
int32_t endPos,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode &status) const override;
/**
diff --git a/thirdparty/icu4c/common/brkiter.cpp b/thirdparty/icu4c/common/brkiter.cpp
index 8b228acf2c..8a1915880e 100644
--- a/thirdparty/icu4c/common/brkiter.cpp
+++ b/thirdparty/icu4c/common/brkiter.cpp
@@ -30,6 +30,7 @@
#include "unicode/ures.h"
#include "unicode/ustring.h"
#include "unicode/filteredbrk.h"
+#include "bytesinkutil.h"
#include "ucln_cmn.h"
#include "cstring.h"
#include "umutex.h"
@@ -115,7 +116,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st
}
// Create a RuleBasedBreakIterator
- result = new RuleBasedBreakIterator(file, status);
+ result = new RuleBasedBreakIterator(file, uprv_strstr(type, "phrase") != NULL, status);
// If there is a result, set the valid locale and actual locale, and the kind
if (U_SUCCESS(status) && result != NULL) {
@@ -408,7 +409,6 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status)
if (U_FAILURE(status)) {
return NULL;
}
- char lbType[kKeyValueLenMax];
BreakIterator *result = NULL;
switch (kind) {
@@ -428,18 +428,29 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status)
break;
case UBRK_LINE:
{
+ char lb_lw[kKeyValueLenMax];
UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE);
- uprv_strcpy(lbType, "line");
- char lbKeyValue[kKeyValueLenMax] = {0};
+ uprv_strcpy(lb_lw, "line");
UErrorCode kvStatus = U_ZERO_ERROR;
- int32_t kLen = loc.getKeywordValue("lb", lbKeyValue, kKeyValueLenMax, kvStatus);
- if (U_SUCCESS(kvStatus) && kLen > 0 && (uprv_strcmp(lbKeyValue,"strict")==0 || uprv_strcmp(lbKeyValue,"normal")==0 || uprv_strcmp(lbKeyValue,"loose")==0)) {
- uprv_strcat(lbType, "_");
- uprv_strcat(lbType, lbKeyValue);
+ CharString value;
+ CharStringByteSink valueSink(&value);
+ loc.getKeywordValue("lb", valueSink, kvStatus);
+ if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) {
+ uprv_strcat(lb_lw, "_");
+ uprv_strcat(lb_lw, value.data());
}
- result = BreakIterator::buildInstance(loc, lbType, status);
+ // lw=phrase is only supported in Japanese.
+ if (uprv_strcmp(loc.getLanguage(), "ja") == 0) {
+ value.clear();
+ loc.getKeywordValue("lw", valueSink, kvStatus);
+ if (U_SUCCESS(kvStatus) && value == "phrase") {
+ uprv_strcat(lb_lw, "_");
+ uprv_strcat(lb_lw, value.data());
+ }
+ }
+ result = BreakIterator::buildInstance(loc, lb_lw, status);
- UTRACE_DATA1(UTRACE_INFO, "lb=%s", lbKeyValue);
+ UTRACE_DATA1(UTRACE_INFO, "lb_lw=%s", lb_lw);
UTRACE_EXIT_STATUS(status);
}
break;
diff --git a/thirdparty/icu4c/common/dictbe.cpp b/thirdparty/icu4c/common/dictbe.cpp
index 4d158e3226..4fdbdf2760 100644
--- a/thirdparty/icu4c/common/dictbe.cpp
+++ b/thirdparty/icu4c/common/dictbe.cpp
@@ -17,7 +17,10 @@
#include "dictbe.h"
#include "unicode/uniset.h"
#include "unicode/chariter.h"
+#include "unicode/resbund.h"
#include "unicode/ubrk.h"
+#include "unicode/usetiter.h"
+#include "ubrkimpl.h"
#include "utracimp.h"
#include "uvectr32.h"
#include "uvector.h"
@@ -48,6 +51,7 @@ DictionaryBreakEngine::findBreaks( UText *text,
int32_t startPos,
int32_t endPos,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const {
if (U_FAILURE(status)) return 0;
(void)startPos; // TODO: remove this param?
@@ -68,7 +72,7 @@ DictionaryBreakEngine::findBreaks( UText *text,
}
rangeStart = start;
rangeEnd = current;
- result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, status);
+ result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, isPhraseBreaking, status);
utext_setNativeIndex(text, current);
return result;
@@ -199,13 +203,13 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode
{
UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE);
UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Thai");
- fThaiWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]]"), status);
+ UnicodeSet thaiWordSet(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]]"), status);
if (U_SUCCESS(status)) {
- setCharacters(fThaiWordSet);
+ setCharacters(thaiWordSet);
}
- fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status);
+ fMarkSet.applyPattern(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status);
fMarkSet.add(0x0020);
- fEndWordSet = fThaiWordSet;
+ fEndWordSet = thaiWordSet;
fEndWordSet.remove(0x0E31); // MAI HAN-AKAT
fEndWordSet.remove(0x0E40, 0x0E44); // SARA E through SARA AI MAIMALAI
fBeginWordSet.add(0x0E01, 0x0E2E); // KO KAI through HO NOKHUK
@@ -230,6 +234,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text,
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool /* isPhraseBreaking */,
UErrorCode& status) const {
if (U_FAILURE(status)) return 0;
utext_setNativeIndex(text, rangeStart);
@@ -441,13 +446,13 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s
{
UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE);
UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Laoo");
- fLaoWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]]"), status);
+ UnicodeSet laoWordSet(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]]"), status);
if (U_SUCCESS(status)) {
- setCharacters(fLaoWordSet);
+ setCharacters(laoWordSet);
}
- fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status);
+ fMarkSet.applyPattern(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status);
fMarkSet.add(0x0020);
- fEndWordSet = fLaoWordSet;
+ fEndWordSet = laoWordSet;
fEndWordSet.remove(0x0EC0, 0x0EC4); // prefix vowels
fBeginWordSet.add(0x0E81, 0x0EAE); // basic consonants (including holes for corresponding Thai characters)
fBeginWordSet.add(0x0EDC, 0x0EDD); // digraph consonants (no Thai equivalent)
@@ -469,6 +474,7 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text,
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool /* isPhraseBreaking */,
UErrorCode& status) const {
if (U_FAILURE(status)) return 0;
if ((rangeEnd - rangeStart) < LAO_MIN_WORD_SPAN) {
@@ -637,14 +643,13 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro
{
UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE);
UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Mymr");
- fBurmeseWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]]"), status);
+ fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels
+ fEndWordSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]]"), status);
+ fMarkSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status);
+ fMarkSet.add(0x0020);
if (U_SUCCESS(status)) {
- setCharacters(fBurmeseWordSet);
+ setCharacters(fEndWordSet);
}
- fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status);
- fMarkSet.add(0x0020);
- fEndWordSet = fBurmeseWordSet;
- fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels
// Compact for caching.
fMarkSet.compact();
@@ -662,6 +667,7 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text,
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool /* isPhraseBreaking */,
UErrorCode& status ) const {
if (U_FAILURE(status)) return 0;
if ((rangeEnd - rangeStart) < BURMESE_MIN_WORD_SPAN) {
@@ -830,13 +836,13 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod
{
UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE);
UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Khmr");
- fKhmerWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]]"), status);
+ UnicodeSet khmerWordSet(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]]"), status);
if (U_SUCCESS(status)) {
- setCharacters(fKhmerWordSet);
+ setCharacters(khmerWordSet);
}
- fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status);
+ fMarkSet.applyPattern(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status);
fMarkSet.add(0x0020);
- fEndWordSet = fKhmerWordSet;
+ fEndWordSet = khmerWordSet;
fBeginWordSet.add(0x1780, 0x17B3);
//fBeginWordSet.add(0x17A3, 0x17A4); // deprecated vowels
//fEndWordSet.remove(0x17A5, 0x17A9); // Khmer independent vowels that can't end a word
@@ -867,6 +873,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text,
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool /* isPhraseBreaking */,
UErrorCode& status ) const {
if (U_FAILURE(status)) return 0;
if ((rangeEnd - rangeStart) < KHMER_MIN_WORD_SPAN) {
@@ -1050,25 +1057,27 @@ CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType
: DictionaryBreakEngine(), fDictionary(adoptDictionary) {
UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE);
UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Hani");
- // Korean dictionary only includes Hangul syllables
- fHangulWordSet.applyPattern(UNICODE_STRING_SIMPLE("[\\uac00-\\ud7a3]"), status);
- fHanWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Han:]"), status);
- fKatakanaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Katakana:]\\uff9e\\uff9f]"), status);
- fHiraganaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Hiragana:]"), status);
nfkcNorm2 = Normalizer2::getNFKCInstance(status);
-
- if (U_SUCCESS(status)) {
- // handle Korean and Japanese/Chinese using different dictionaries
- if (type == kKorean) {
+ // Korean dictionary only includes Hangul syllables
+ fHangulWordSet.applyPattern(UnicodeString(u"[\\uac00-\\ud7a3]"), status);
+ fHangulWordSet.compact();
+ // Digits, open puncutation and Alphabetic characters.
+ fDigitOrOpenPunctuationOrAlphabetSet.applyPattern(
+ UnicodeString(u"[[:Nd:][:Pi:][:Ps:][:Alphabetic:]]"), status);
+ fDigitOrOpenPunctuationOrAlphabetSet.compact();
+ fClosePunctuationSet.applyPattern(UnicodeString(u"[[:Pc:][:Pd:][:Pe:][:Pf:][:Po:]]"), status);
+ fClosePunctuationSet.compact();
+
+ // handle Korean and Japanese/Chinese using different dictionaries
+ if (type == kKorean) {
+ if (U_SUCCESS(status)) {
setCharacters(fHangulWordSet);
- } else { //Chinese and Japanese
- UnicodeSet cjSet;
- cjSet.addAll(fHanWordSet);
- cjSet.addAll(fKatakanaWordSet);
- cjSet.addAll(fHiraganaWordSet);
- cjSet.add(0xFF70); // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
- cjSet.add(0x30FC); // KATAKANA-HIRAGANA PROLONGED SOUND MARK
+ }
+ } else { //Chinese and Japanese
+ UnicodeSet cjSet(UnicodeString(u"[[:Han:][:Hiragana:][:Katakana:]\\u30fc\\uff70\\uff9e\\uff9f]"), status);
+ if (U_SUCCESS(status)) {
setCharacters(cjSet);
+ initJapanesePhraseParameter(status);
}
}
UTRACE_EXIT_STATUS(status);
@@ -1096,14 +1105,12 @@ static inline bool isKatakana(UChar32 value) {
(value >= 0xFF66 && value <= 0xFF9f);
}
-
// Function for accessing internal utext flags.
// Replicates an internal UText function.
static inline int32_t utext_i32_flag(int32_t bitIndex) {
return (int32_t)1 << bitIndex;
}
-
/*
* @param text A UText representing the text
@@ -1117,6 +1124,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText,
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const {
if (U_FAILURE(status)) return 0;
if (rangeStart >= rangeEnd) {
@@ -1347,6 +1355,31 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText,
if ((uint32_t)bestSnlp.elementAti(numCodePts) == kuint32max) {
t_boundary.addElement(numCodePts, status);
numBreaks++;
+ } else if (isPhraseBreaking) {
+ t_boundary.addElement(numCodePts, status);
+ if(U_SUCCESS(status)) {
+ numBreaks++;
+ int32_t prevIdx = numCodePts;
+
+ int32_t codeUnitIdx = -1;
+ int32_t prevCodeUnitIdx = -1;
+ int32_t length = -1;
+ for (int32_t i = prev.elementAti(numCodePts); i > 0; i = prev.elementAti(i)) {
+ codeUnitIdx = inString.moveIndex32(0, i);
+ prevCodeUnitIdx = inString.moveIndex32(0, prevIdx);
+ // Calculate the length by using the code unit.
+ length = prevCodeUnitIdx - codeUnitIdx;
+ prevIdx = i;
+ // Keep the breakpoint if the pattern is not in the fSkipSet and continuous Katakana
+ // characters don't occur.
+ if (!fSkipSet.containsKey(inString.tempSubString(codeUnitIdx, length))
+ && (!isKatakana(inString.char32At(inString.moveIndex32(codeUnitIdx, -1)))
+ || !isKatakana(inString.char32At(codeUnitIdx)))) {
+ t_boundary.addElement(i, status);
+ numBreaks++;
+ }
+ }
+ }
} else {
for (int32_t i = numCodePts; i > 0; i = prev.elementAti(i)) {
t_boundary.addElement(i, status);
@@ -1367,7 +1400,8 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText,
// while reversing t_boundary and pushing values to foundBreaks.
int32_t prevCPPos = -1;
int32_t prevUTextPos = -1;
- for (int32_t i = numBreaks-1; i >= 0; i--) {
+ int32_t correctedNumBreaks = 0;
+ for (int32_t i = numBreaks - 1; i >= 0; i--) {
int32_t cpPos = t_boundary.elementAti(i);
U_ASSERT(cpPos > prevCPPos);
int32_t utextPos = inputMap.isValid() ? inputMap->elementAti(cpPos) : cpPos + rangeStart;
@@ -1375,7 +1409,15 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText,
if (utextPos > prevUTextPos) {
// Boundaries are added to foundBreaks output in ascending order.
U_ASSERT(foundBreaks.size() == 0 || foundBreaks.peeki() < utextPos);
- foundBreaks.push(utextPos, status);
+ // In phrase breaking, there has to be a breakpoint between Cj character and close
+ // punctuation.
+ // E.g.ï¼»æºå¸¯é›»è©±ï¼½æ­£ã—ã„é¸æŠž -> ï¼»æºå¸¯â–電話]â–æ­£ã—ã„â–é¸æŠž -> breakpoint between ï¼½ and æ­£
+ if (utextPos != rangeStart
+ || (isPhraseBreaking && utextPos > 0
+ && fClosePunctuationSet.contains(utext_char32At(inText, utextPos - 1)))) {
+ foundBreaks.push(utextPos, status);
+ correctedNumBreaks++;
+ }
} else {
// Normalization expanded the input text, the dictionary found a boundary
// within the expansion, giving two boundaries with the same index in the
@@ -1387,9 +1429,52 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText,
}
(void)prevCPPos; // suppress compiler warnings about unused variable
+ UChar32 nextChar = utext_char32At(inText, rangeEnd);
+ if (!foundBreaks.isEmpty() && foundBreaks.peeki() == rangeEnd) {
+ // In phrase breaking, there has to be a breakpoint between Cj character and
+ // the number/open punctuation.
+ // E.g. る文字「ãã†ã ã€äº¬éƒ½ã€->ã‚‹â–文字â–「ãã†ã ã€â–京都ã€-> breakpoint between å­— and「
+ // E.g. 乗車率9ï¼ï¼…程度ã ã‚ã†ã‹ -> 乗車â–率â–ï¼™ï¼ï¼…â–程度ã ã‚ã†ã‹ -> breakpoint between 率 and ï¼™
+ // E.g. ã—ã‹ã‚‚ロゴãŒï¼µï½Žï½‰ï½ƒï½ï½„ï½…ï¼ -> ã—ã‹ã‚‚â–ロゴãŒâ–Unicï½ï½„ï½…ï¼-> breakpoint between ㌠and ï¼µ
+ if (isPhraseBreaking) {
+ if (!fDigitOrOpenPunctuationOrAlphabetSet.contains(nextChar)) {
+ foundBreaks.popi();
+ correctedNumBreaks--;
+ }
+ } else {
+ foundBreaks.popi();
+ correctedNumBreaks--;
+ }
+ }
+
// inString goes out of scope
// inputMap goes out of scope
- return numBreaks;
+ return correctedNumBreaks;
+}
+
+void CjkBreakEngine::initJapanesePhraseParameter(UErrorCode& error) {
+ loadJapaneseExtensions(error);
+ loadHiragana(error);
+}
+
+void CjkBreakEngine::loadJapaneseExtensions(UErrorCode& error) {
+ const char* tag = "extensions";
+ ResourceBundle ja(U_ICUDATA_BRKITR, "ja", error);
+ if (U_SUCCESS(error)) {
+ ResourceBundle bundle = ja.get(tag, error);
+ while (U_SUCCESS(error) && bundle.hasNext()) {
+ fSkipSet.puti(bundle.getNextString(error), 1, error);
+ }
+ }
+}
+
+void CjkBreakEngine::loadHiragana(UErrorCode& error) {
+ UnicodeSet hiraganaWordSet(UnicodeString(u"[:Hiragana:]"), error);
+ hiraganaWordSet.compact();
+ UnicodeSetIterator iterator(hiraganaWordSet);
+ while (iterator.next()) {
+ fSkipSet.puti(UnicodeString(iterator.getCodepoint()), 1, error);
+ }
}
#endif
diff --git a/thirdparty/icu4c/common/dictbe.h b/thirdparty/icu4c/common/dictbe.h
index 4e70ed3817..ca1a3c28b7 100644
--- a/thirdparty/icu4c/common/dictbe.h
+++ b/thirdparty/icu4c/common/dictbe.h
@@ -15,6 +15,7 @@
#include "unicode/utext.h"
#include "brkeng.h"
+#include "hash.h"
#include "uvectr32.h"
U_NAMESPACE_BEGIN
@@ -80,6 +81,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine {
int32_t startPos,
int32_t endPos,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status ) const override;
protected:
@@ -105,6 +107,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const = 0;
};
@@ -127,7 +130,6 @@ class ThaiBreakEngine : public DictionaryBreakEngine {
* @internal
*/
- UnicodeSet fThaiWordSet;
UnicodeSet fEndWordSet;
UnicodeSet fBeginWordSet;
UnicodeSet fSuffixSet;
@@ -164,6 +166,7 @@ class ThaiBreakEngine : public DictionaryBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
};
@@ -186,7 +189,6 @@ class LaoBreakEngine : public DictionaryBreakEngine {
* @internal
*/
- UnicodeSet fLaoWordSet;
UnicodeSet fEndWordSet;
UnicodeSet fBeginWordSet;
UnicodeSet fMarkSet;
@@ -222,6 +224,7 @@ class LaoBreakEngine : public DictionaryBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
};
@@ -244,7 +247,6 @@ class BurmeseBreakEngine : public DictionaryBreakEngine {
* @internal
*/
- UnicodeSet fBurmeseWordSet;
UnicodeSet fEndWordSet;
UnicodeSet fBeginWordSet;
UnicodeSet fMarkSet;
@@ -280,6 +282,7 @@ class BurmeseBreakEngine : public DictionaryBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
};
@@ -302,7 +305,6 @@ class KhmerBreakEngine : public DictionaryBreakEngine {
* @internal
*/
- UnicodeSet fKhmerWordSet;
UnicodeSet fEndWordSet;
UnicodeSet fBeginWordSet;
UnicodeSet fMarkSet;
@@ -338,6 +340,7 @@ class KhmerBreakEngine : public DictionaryBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
};
@@ -366,13 +369,22 @@ class CjkBreakEngine : public DictionaryBreakEngine {
* @internal
*/
UnicodeSet fHangulWordSet;
- UnicodeSet fHanWordSet;
- UnicodeSet fKatakanaWordSet;
- UnicodeSet fHiraganaWordSet;
+ UnicodeSet fDigitOrOpenPunctuationOrAlphabetSet;
+ UnicodeSet fClosePunctuationSet;
DictionaryMatcher *fDictionary;
const Normalizer2 *nfkcNorm2;
+ private:
+ // Load Japanese extensions.
+ void loadJapaneseExtensions(UErrorCode& error);
+ // Load Japanese Hiragana.
+ void loadHiragana(UErrorCode& error);
+ // Initialize fSkipSet by loading Japanese Hiragana and extensions.
+ void initJapanesePhraseParameter(UErrorCode& error);
+
+ Hashtable fSkipSet;
+
public:
/**
@@ -404,6 +416,7 @@ class CjkBreakEngine : public DictionaryBreakEngine {
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
};
diff --git a/thirdparty/icu4c/common/localematcher.cpp b/thirdparty/icu4c/common/localematcher.cpp
index 3d178dfbaf..2cad708d99 100644
--- a/thirdparty/icu4c/common/localematcher.cpp
+++ b/thirdparty/icu4c/common/localematcher.cpp
@@ -168,12 +168,9 @@ void LocaleMatcher::Builder::clearSupportedLocales() {
bool LocaleMatcher::Builder::ensureSupportedLocaleVector() {
if (U_FAILURE(errorCode_)) { return false; }
if (supportedLocales_ != nullptr) { return true; }
- supportedLocales_ = new UVector(uprv_deleteUObject, nullptr, errorCode_);
+ LocalPointer<UVector> lpSupportedLocales(new UVector(uprv_deleteUObject, nullptr, errorCode_), errorCode_);
if (U_FAILURE(errorCode_)) { return false; }
- if (supportedLocales_ == nullptr) {
- errorCode_ = U_MEMORY_ALLOCATION_ERROR;
- return false;
- }
+ supportedLocales_ = lpSupportedLocales.orphan();
return true;
}
@@ -187,9 +184,8 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin
for (int32_t i = 0; i < length; ++i) {
Locale *locale = list.orphanLocaleAt(i);
if (locale == nullptr) { continue; }
- supportedLocales_->addElementX(locale, errorCode_);
+ supportedLocales_->adoptElement(locale, errorCode_);
if (U_FAILURE(errorCode_)) {
- delete locale;
break;
}
}
@@ -197,35 +193,21 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin
}
LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator &locales) {
- if (U_FAILURE(errorCode_)) { return *this; }
- clearSupportedLocales();
- if (!ensureSupportedLocaleVector()) { return *this; }
- while (locales.hasNext()) {
- const Locale &locale = locales.next();
- Locale *clone = locale.clone();
- if (clone == nullptr) {
- errorCode_ = U_MEMORY_ALLOCATION_ERROR;
- break;
- }
- supportedLocales_->addElementX(clone, errorCode_);
- if (U_FAILURE(errorCode_)) {
- delete clone;
- break;
+ if (ensureSupportedLocaleVector()) {
+ clearSupportedLocales();
+ while (locales.hasNext() && U_SUCCESS(errorCode_)) {
+ const Locale &locale = locales.next();
+ LocalPointer<Locale> clone (locale.clone(), errorCode_);
+ supportedLocales_->adoptElement(clone.orphan(), errorCode_);
}
}
return *this;
}
LocaleMatcher::Builder &LocaleMatcher::Builder::addSupportedLocale(const Locale &locale) {
- if (!ensureSupportedLocaleVector()) { return *this; }
- Locale *clone = locale.clone();
- if (clone == nullptr) {
- errorCode_ = U_MEMORY_ALLOCATION_ERROR;
- return *this;
- }
- supportedLocales_->addElementX(clone, errorCode_);
- if (U_FAILURE(errorCode_)) {
- delete clone;
+ if (ensureSupportedLocaleVector()) {
+ LocalPointer<Locale> clone(locale.clone(), errorCode_);
+ supportedLocales_->adoptElement(clone.orphan(), errorCode_);
}
return *this;
}
diff --git a/thirdparty/icu4c/common/locid.cpp b/thirdparty/icu4c/common/locid.cpp
index e8859c7048..73bb8d8aec 100644
--- a/thirdparty/icu4c/common/locid.cpp
+++ b/thirdparty/icu4c/common/locid.cpp
@@ -1204,14 +1204,11 @@ AliasReplacer::parseLanguageReplacement(
// We have multiple field so we have to allocate and parse
CharString* str = new CharString(
replacement, (int32_t)uprv_strlen(replacement), status);
+ LocalPointer<CharString> lpStr(str, status);
+ toBeFreed.adoptElement(lpStr.orphan(), status);
if (U_FAILURE(status)) {
return;
}
- if (str == nullptr) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- toBeFreed.addElementX(str, status);
char* data = str->data();
replacedLanguage = (const char*) data;
char* endOfField = uprv_strchr(data, '_');
@@ -1420,12 +1417,9 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status)
(int32_t)(firstSpace - replacement), status), status);
}
if (U_FAILURE(status)) { return false; }
- if (item.isNull()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return false;
- }
replacedRegion = item->data();
- toBeFreed.addElementX(item.orphan(), status);
+ toBeFreed.adoptElement(item.orphan(), status);
+ if (U_FAILURE(status)) { return false; }
}
U_ASSERT(!same(region, replacedRegion));
region = replacedRegion;
@@ -1659,10 +1653,10 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status
while ((end = uprv_strchr(start, SEP_CHAR)) != nullptr &&
U_SUCCESS(status)) {
*end = NULL_CHAR; // null terminate inside variantsBuff
- variants.addElementX(start, status);
+ variants.addElement(start, status);
start = end + 1;
}
- variants.addElementX(start, status);
+ variants.addElement(start, status);
}
if (U_FAILURE(status)) { return false; }
diff --git a/thirdparty/icu4c/common/lstmbe.cpp b/thirdparty/icu4c/common/lstmbe.cpp
index 3793abceb3..f6114cdfe2 100644
--- a/thirdparty/icu4c/common/lstmbe.cpp
+++ b/thirdparty/icu4c/common/lstmbe.cpp
@@ -1,8 +1,8 @@
// © 2021 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
+#include <complex>
#include <utility>
-#include <ctgmath>
#include "unicode/utypes.h"
@@ -639,6 +639,7 @@ LSTMBreakEngine::divideUpDictionaryRange( UText *text,
int32_t startPos,
int32_t endPos,
UVector32 &foundBreaks,
+ UBool /* isPhraseBreaking */,
UErrorCode& status) const {
if (U_FAILURE(status)) return 0;
int32_t beginFoundBreakSize = foundBreaks.size();
diff --git a/thirdparty/icu4c/common/lstmbe.h b/thirdparty/icu4c/common/lstmbe.h
index c3f7ecf815..ffdf805eca 100644
--- a/thirdparty/icu4c/common/lstmbe.h
+++ b/thirdparty/icu4c/common/lstmbe.h
@@ -62,6 +62,7 @@ protected:
int32_t rangeStart,
int32_t rangeEnd,
UVector32 &foundBreaks,
+ UBool isPhraseBreaking,
UErrorCode& status) const override;
private:
const LSTMData* fData;
diff --git a/thirdparty/icu4c/common/normalizer2impl.cpp b/thirdparty/icu4c/common/normalizer2impl.cpp
index 5bfd49e8cb..e6bd75e717 100644
--- a/thirdparty/icu4c/common/normalizer2impl.cpp
+++ b/thirdparty/icu4c/common/normalizer2impl.cpp
@@ -2496,15 +2496,18 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode
// origin is not the first character, or it is U+0000.
UnicodeSet *set;
if((canonValue&CANON_HAS_SET)==0) {
- set=new UnicodeSet;
- if(set==NULL) {
- errorCode=U_MEMORY_ALLOCATION_ERROR;
+ LocalPointer<UnicodeSet> lpSet(new UnicodeSet, errorCode);
+ set=lpSet.getAlias();
+ if(U_FAILURE(errorCode)) {
return;
}
UChar32 firstOrigin=(UChar32)(canonValue&CANON_VALUE_MASK);
canonValue=(canonValue&~CANON_VALUE_MASK)|CANON_HAS_SET|(uint32_t)canonStartSets.size();
umutablecptrie_set(mutableTrie, decompLead, canonValue, &errorCode);
- canonStartSets.addElementX(set, errorCode);
+ canonStartSets.adoptElement(lpSet.orphan(), errorCode);
+ if (U_FAILURE(errorCode)) {
+ return;
+ }
if(firstOrigin!=0) {
set->add(firstOrigin);
}
diff --git a/thirdparty/icu4c/common/rbbi.cpp b/thirdparty/icu4c/common/rbbi.cpp
index f65177f232..cae8d154b3 100644
--- a/thirdparty/icu4c/common/rbbi.cpp
+++ b/thirdparty/icu4c/common/rbbi.cpp
@@ -82,6 +82,19 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode
}
}
+//-------------------------------------------------------------------------------
+//
+// Constructor from a UDataMemory handle to precompiled break rules
+// stored in an ICU data file. This construcotr is private API,
+// only for internal use.
+//
+//-------------------------------------------------------------------------------
+RuleBasedBreakIterator::RuleBasedBreakIterator(UDataMemory* udm, UBool isPhraseBreaking,
+ UErrorCode &status) : RuleBasedBreakIterator(udm, status)
+{
+ fIsPhraseBreaking = isPhraseBreaking;
+}
+
//
// Construct from precompiled binary rules (tables). This constructor is public API,
// taking the rules as a (const uint8_t *) to match the type produced by getBinaryRules().
@@ -322,6 +335,7 @@ void RuleBasedBreakIterator::init(UErrorCode &status) {
fBreakCache = nullptr;
fDictionaryCache = nullptr;
fLookAheadMatches = nullptr;
+ fIsPhraseBreaking = false;
// Note: IBM xlC is unable to assign or initialize member fText from UTEXT_INITIALIZER.
// fText = UTEXT_INITIALIZER;
diff --git a/thirdparty/icu4c/common/rbbi_cache.cpp b/thirdparty/icu4c/common/rbbi_cache.cpp
index 6bfe3feca4..26d82df781 100644
--- a/thirdparty/icu4c/common/rbbi_cache.cpp
+++ b/thirdparty/icu4c/common/rbbi_cache.cpp
@@ -163,7 +163,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo
// Ask the language object if there are any breaks. It will add them to the cache and
// leave the text pointer on the other side of its range, ready to search for the next one.
if (lbe != NULL) {
- foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, status);
+ foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, fBI->fIsPhraseBreaking, status);
}
// Reload the loop variables for the next go-round
diff --git a/thirdparty/icu4c/common/serv.cpp b/thirdparty/icu4c/common/serv.cpp
index 0c54a4dce9..c26dbca1a9 100644
--- a/thirdparty/icu4c/common/serv.cpp
+++ b/thirdparty/icu4c/common/serv.cpp
@@ -625,10 +625,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC
}
}
- LocalPointer<UnicodeString> idClone(new UnicodeString(*id), status);
- if (U_SUCCESS(status) && idClone->isBogus()) {
- status = U_MEMORY_ALLOCATION_ERROR;
- }
+ LocalPointer<UnicodeString> idClone(id->clone(), status);
result.adoptElement(idClone.orphan(), status);
}
delete fallbackKey;
diff --git a/thirdparty/icu4c/common/servls.cpp b/thirdparty/icu4c/common/servls.cpp
index 7108afd4a5..98f0a8a12b 100644
--- a/thirdparty/icu4c/common/servls.cpp
+++ b/thirdparty/icu4c/common/servls.cpp
@@ -179,7 +179,8 @@ private:
length = other._ids.size();
for(i = 0; i < length; ++i) {
- _ids.addElementX(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
+ LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status);
+ _ids.adoptElement(clonedId.orphan(), status);
}
if(U_SUCCESS(status)) {
diff --git a/thirdparty/icu4c/common/servnotf.cpp b/thirdparty/icu4c/common/servnotf.cpp
index 342e0d9f24..d9fb388752 100644
--- a/thirdparty/icu4c/common/servnotf.cpp
+++ b/thirdparty/icu4c/common/servnotf.cpp
@@ -49,7 +49,11 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status)
if (acceptsListener(*l)) {
Mutex lmx(&notifyLock);
if (listeners == NULL) {
- listeners = new UVector(5, status);
+ LocalPointer<UVector> lpListeners(new UVector(5, status), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ listeners = lpListeners.orphan();
} else {
for (int i = 0, e = listeners->size(); i < e; ++i) {
const EventListener* el = (const EventListener*)(listeners->elementAt(i));
@@ -59,7 +63,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status)
}
}
- listeners->addElementX((void*)l, status); // cast away const
+ listeners->addElement((void*)l, status); // cast away const
}
#ifdef NOTIFIER_DEBUG
else {
@@ -102,13 +106,11 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status)
void
ICUNotifier::notifyChanged(void)
{
+ Mutex lmx(&notifyLock);
if (listeners != NULL) {
- Mutex lmx(&notifyLock);
- if (listeners != NULL) {
- for (int i = 0, e = listeners->size(); i < e; ++i) {
- EventListener* el = (EventListener*)listeners->elementAt(i);
- notifyListener(*el);
- }
+ for (int i = 0, e = listeners->size(); i < e; ++i) {
+ EventListener* el = (EventListener*)listeners->elementAt(i);
+ notifyListener(*el);
}
}
}
diff --git a/thirdparty/icu4c/common/ubrk.cpp b/thirdparty/icu4c/common/ubrk.cpp
index bb5bdd1b50..f4e064961f 100644
--- a/thirdparty/icu4c/common/ubrk.cpp
+++ b/thirdparty/icu4c/common/ubrk.cpp
@@ -168,7 +168,7 @@ ubrk_safeClone(
BreakIterator *newBI = ((BreakIterator *)bi)->clone();
if (newBI == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
- } else {
+ } else if (pBufferSize != NULL) {
*status = U_SAFECLONE_ALLOCATED_WARNING;
}
return (UBreakIterator *)newBI;
@@ -176,15 +176,7 @@ ubrk_safeClone(
U_CAPI UBreakIterator * U_EXPORT2
ubrk_clone(const UBreakIterator *bi, UErrorCode *status) {
- if (U_FAILURE(*status)) {
- return nullptr;
- }
- BreakIterator *newBI = ((BreakIterator *)bi)->clone();
- if (newBI == nullptr) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return nullptr;
- }
- return (UBreakIterator *)newBI;
+ return ubrk_safeClone(bi, nullptr, nullptr, status);
}
diff --git a/thirdparty/icu4c/common/ucase.cpp b/thirdparty/icu4c/common/ucase.cpp
index 4aa856507a..388c86b1bb 100644
--- a/thirdparty/icu4c/common/ucase.cpp
+++ b/thirdparty/icu4c/common/ucase.cpp
@@ -22,27 +22,14 @@
#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "unicode/uset.h"
-#include "unicode/udata.h" /* UDataInfo */
#include "unicode/utf16.h"
-#include "ucmndata.h" /* DataHeader */
-#include "udatamem.h"
-#include "umutex.h"
-#include "uassert.h"
#include "cmemory.h"
-#include "utrie2.h"
+#include "uassert.h"
#include "ucase.h"
+#include "umutex.h"
+#include "utrie2.h"
-struct UCaseProps {
- UDataMemory *mem;
- const int32_t *indexes;
- const uint16_t *exceptions;
- const uint16_t *unfold;
-
- UTrie2 trie;
- uint8_t formatVersion[4];
-};
-
-/* ucase_props_data.h is machine-generated by gencase --csource */
+/* ucase_props_data.h is machine-generated by genprops/casepropsbuilder.cpp */
#define INCLUDED_FROM_UCASE_CPP
#include "ucase_props_data.h"
@@ -77,6 +64,13 @@ ucase_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) {
/* data access primitives --------------------------------------------------- */
+U_CAPI const struct UCaseProps * U_EXPORT2
+ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength) {
+ *pExceptionsLength = UPRV_LENGTHOF(ucase_props_exceptions);
+ *pUnfoldLength = UPRV_LENGTHOF(ucase_props_unfold);
+ return &ucase_props_singleton;
+}
+
U_CFUNC const UTrie2 * U_EXPORT2
ucase_getTrie() {
return &ucase_props_singleton.trie;
@@ -690,7 +684,7 @@ ucase_isCaseSensitive(UChar32 c) {
* - The general category of C is
* Nonspacing Mark (Mn), or Enclosing Mark (Me), or Format Control (Cf), or
* Letter Modifier (Lm), or Symbol Modifier (Sk)
- * - C is one of the following characters
+ * - C is one of the following characters
* U+0027 APOSTROPHE
* U+00AD SOFT HYPHEN (SHY)
* U+2019 RIGHT SINGLE QUOTATION MARK
@@ -1064,6 +1058,8 @@ ucase_toFullLower(UChar32 c,
// The sign of the result has meaning, input must be non-negative so that it can be returned as is.
U_ASSERT(c >= 0);
UChar32 result=c;
+ // Reset the output pointer in case it was uninitialized.
+ *pString=nullptr;
uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c);
if(!UCASE_HAS_EXCEPTION(props)) {
if(UCASE_IS_UPPER_OR_TITLE(props)) {
@@ -1148,7 +1144,6 @@ ucase_toFullLower(UChar32 c,
0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE
0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE
*/
- *pString=nullptr;
return 0; /* remove the dot (continue without output) */
} else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) {
/*
@@ -1215,6 +1210,8 @@ toUpperOrTitle(UChar32 c,
// The sign of the result has meaning, input must be non-negative so that it can be returned as is.
U_ASSERT(c >= 0);
UChar32 result=c;
+ // Reset the output pointer in case it was uninitialized.
+ *pString=nullptr;
uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c);
if(!UCASE_HAS_EXCEPTION(props)) {
if(UCASE_GET_TYPE(props)==UCASE_LOWER) {
@@ -1252,7 +1249,6 @@ toUpperOrTitle(UChar32 c,
0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE
*/
- *pString=nullptr;
return 0; /* remove the dot (continue without output) */
} else if(c==0x0587) {
// See ICU-13416:
@@ -1449,6 +1445,8 @@ ucase_toFullFolding(UChar32 c,
// The sign of the result has meaning, input must be non-negative so that it can be returned as is.
U_ASSERT(c >= 0);
UChar32 result=c;
+ // Reset the output pointer in case it was uninitialized.
+ *pString=nullptr;
uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c);
if(!UCASE_HAS_EXCEPTION(props)) {
if(UCASE_IS_UPPER_OR_TITLE(props)) {
@@ -1542,7 +1540,7 @@ U_CAPI UChar32 U_EXPORT2
u_tolower(UChar32 c) {
return ucase_tolower(c);
}
-
+
/* Transforms the Unicode character to its upper case equivalent.*/
U_CAPI UChar32 U_EXPORT2
u_toupper(UChar32 c) {
diff --git a/thirdparty/icu4c/common/ucase.h b/thirdparty/icu4c/common/ucase.h
index a018f82b81..7bf57fd370 100644
--- a/thirdparty/icu4c/common/ucase.h
+++ b/thirdparty/icu4c/common/ucase.h
@@ -312,6 +312,21 @@ UCaseMapFull(UChar32 c,
U_CDECL_END
+/* for icuexportdata -------------------------------------------------------- */
+
+struct UCaseProps {
+ void *mem; // TODO: was unused, and type UDataMemory -- remove
+ const int32_t *indexes;
+ const uint16_t *exceptions;
+ const uint16_t *unfold;
+
+ UTrie2 trie;
+ uint8_t formatVersion[4];
+};
+
+U_CAPI const struct UCaseProps * U_EXPORT2
+ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength);
+
/* file definitions --------------------------------------------------------- */
#define UCASE_DATA_NAME "ucase"
diff --git a/thirdparty/icu4c/common/ucasemap.cpp b/thirdparty/icu4c/common/ucasemap.cpp
index ed72bda828..95b55d56a0 100644
--- a/thirdparty/icu4c/common/ucasemap.cpp
+++ b/thirdparty/icu4c/common/ucasemap.cpp
@@ -112,8 +112,7 @@ ucasemap_setLocale(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) {
if(length==sizeof(csm->locale)) {
*pErrorCode=U_BUFFER_OVERFLOW_ERROR;
}
- if(U_SUCCESS(*pErrorCode)) {
- csm->caseLocale=UCASE_LOC_UNKNOWN;
+ if(U_SUCCESS(*pErrorCode)) {
csm->caseLocale = ucase_getCaseLocale(csm->locale);
} else {
csm->locale[0]=0;
@@ -420,6 +419,97 @@ void toUpper(int32_t caseLocale, uint32_t options,
#if !UCONFIG_NO_BREAK_ITERATION
+namespace {
+
+constexpr uint8_t ACUTE_BYTE0 = u8"\u0301"[0];
+
+constexpr uint8_t ACUTE_BYTE1 = u8"\u0301"[1];
+
+/**
+ * Input: c is a letter I with or without acute accent.
+ * start is the index in src after c, and is less than segmentLimit.
+ * If a plain i/I is followed by a plain j/J,
+ * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute,
+ * then we output accordingly.
+ *
+ * @return the src index after the titlecased sequence, or the start index if no Dutch IJ
+ */
+int32_t maybeTitleDutchIJ(const uint8_t *src, UChar32 c, int32_t start, int32_t segmentLimit,
+ ByteSink &sink, uint32_t options, icu::Edits *edits, UErrorCode &errorCode) {
+ U_ASSERT(start < segmentLimit);
+
+ int32_t index = start;
+ bool withAcute = false;
+
+ // If the conditions are met, then the following variables tell us what to output.
+ int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3)
+ bool doTitleJ = false; // true if the j needs to be titlecased
+ int32_t unchanged2 = 0; // after the j (0 or 1)
+
+ // next character after the first letter
+ UChar32 c2;
+ c2 = src[index++];
+
+ // Is the first letter an i/I with accent?
+ if (c == u'I') {
+ if (c2 == ACUTE_BYTE0 && index < segmentLimit && src[index++] == ACUTE_BYTE1) {
+ withAcute = true;
+ unchanged1 = 2; // ACUTE is 2 code units in UTF-8
+ if (index == segmentLimit) { return start; }
+ c2 = src[index++];
+ }
+ } else { // Ã
+ withAcute = true;
+ }
+
+ // Is the next character a j/J?
+ if (c2 == u'j') {
+ doTitleJ = true;
+ } else if (c2 == u'J') {
+ ++unchanged1;
+ } else {
+ return start;
+ }
+
+ // A plain i/I must be followed by a plain j/J.
+ // An i/I with acute must be followed by a j/J with acute.
+ if (withAcute) {
+ if ((index + 1) >= segmentLimit || src[index++] != ACUTE_BYTE0 || src[index++] != ACUTE_BYTE1) {
+ return start;
+ }
+ if (doTitleJ) {
+ unchanged2 = 2; // ACUTE is 2 code units in UTF-8
+ } else {
+ unchanged1 = unchanged1 + 2; // ACUTE is 2 code units in UTF-8
+ }
+ }
+
+ // There must not be another combining mark.
+ if (index < segmentLimit) {
+ int32_t cp;
+ int32_t i = index;
+ U8_NEXT(src, i, segmentLimit, cp);
+ uint32_t typeMask = U_GET_GC_MASK(cp);
+ if ((typeMask & U_GC_M_MASK) != 0) {
+ return start;
+ }
+ }
+
+ // Output the rest of the Dutch IJ.
+ ByteSinkUtil::appendUnchanged(src + start, unchanged1, sink, options, edits, errorCode);
+ start += unchanged1;
+ if (doTitleJ) {
+ ByteSinkUtil::appendCodePoint(1, u'J', sink, edits);
+ ++start;
+ }
+ ByteSinkUtil::appendUnchanged(src + start, unchanged2, sink, options, edits, errorCode);
+
+ U_ASSERT(start + unchanged2 == index);
+ return index;
+}
+
+} // namespace
+
U_CFUNC void U_CALLCONV
ucasemap_internalUTF8ToTitle(
int32_t caseLocale, uint32_t options, BreakIterator *iter,
@@ -504,19 +594,14 @@ ucasemap_internalUTF8ToTitle(
}
/* Special case Dutch IJ titlecasing */
- if (titleStart+1 < index &&
- caseLocale == UCASE_LOC_DUTCH &&
- (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) {
- if (src[titleStart+1] == 0x006A) {
- ByteSinkUtil::appendCodePoint(1, 0x004A, sink, edits);
- titleLimit++;
- } else if (src[titleStart+1] == 0x004A) {
- // Keep the capital J from getting lowercased.
- if (!ByteSinkUtil::appendUnchanged(src+titleStart+1, 1,
- sink, options, edits, errorCode)) {
- return;
- }
- titleLimit++;
+ if (titleLimit < index &&
+ caseLocale == UCASE_LOC_DUTCH) {
+ if (c < 0) {
+ c = ~c;
+ }
+
+ if (c == u'I' || c == u'Ã') {
+ titleLimit = maybeTitleDutchIJ(src, c, titleLimit, index, sink, options, edits, errorCode);
}
}
diff --git a/thirdparty/icu4c/common/ucnv.cpp b/thirdparty/icu4c/common/ucnv.cpp
index 5dcf35e043..019bcb6a79 100644
--- a/thirdparty/icu4c/common/ucnv.cpp
+++ b/thirdparty/icu4c/common/ucnv.cpp
@@ -252,7 +252,10 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U
UTRACE_EXIT_STATUS(*status);
return NULL;
}
- *status = U_SAFECLONE_ALLOCATED_WARNING;
+ // If pBufferSize was NULL as the input, pBufferSize is set to &stackBufferSize in this function.
+ if (pBufferSize != &stackBufferSize) {
+ *status = U_SAFECLONE_ALLOCATED_WARNING;
+ }
/* record the fact that memory was allocated */
*pBufferSize = bufferSizeNeeded;
@@ -317,7 +320,11 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U
return localConverter;
}
-
+U_CAPI UConverter* U_EXPORT2
+ucnv_clone(const UConverter* cnv, UErrorCode *status)
+{
+ return ucnv_safeClone(cnv, nullptr, nullptr, status);
+}
/*Decreases the reference counter in the shared immutable section of the object
*and frees the mutable part*/
diff --git a/thirdparty/icu4c/common/ucurr.cpp b/thirdparty/icu4c/common/ucurr.cpp
index 67aab4e8ff..6e489e0563 100644
--- a/thirdparty/icu4c/common/ucurr.cpp
+++ b/thirdparty/icu4c/common/ucurr.cpp
@@ -254,7 +254,7 @@ currSymbolsEquiv_cleanup(void)
}
/**
- * Deleter for OlsonToMetaMappingEntry
+ * Deleter for IsoCodeEntry
*/
static void U_CALLCONV
deleteIsoCodeEntry(void *obj) {
diff --git a/thirdparty/icu4c/common/uloc.cpp b/thirdparty/icu4c/common/uloc.cpp
index c8a3f1ff73..99c6a0af39 100644
--- a/thirdparty/icu4c/common/uloc.cpp
+++ b/thirdparty/icu4c/common/uloc.cpp
@@ -186,10 +186,10 @@ NULL
};
static const char* const DEPRECATED_LANGUAGES[]={
- "in", "iw", "ji", "jw", NULL, NULL
+ "in", "iw", "ji", "jw", "mo", NULL, NULL
};
static const char* const REPLACEMENT_LANGUAGES[]={
- "id", "he", "yi", "jv", NULL, NULL
+ "id", "he", "yi", "jv", "ro", NULL, NULL
};
/**
@@ -444,7 +444,7 @@ static const char * const COUNTRIES_3[] = {
/* "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */
"VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF",
/* "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW", */
- "WSM", "XXK", "YEM", "MYT", "ZAF", "ZMB", "ZWE",
+ "WSM", "XKK", "YEM", "MYT", "ZAF", "ZMB", "ZWE",
NULL,
/* "AN", "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR" */
"ANT", "BUR", "SCG", "FXX", "ROM", "SUN", "TMP", "YMD", "YUG", "ZAR",
diff --git a/thirdparty/icu4c/common/unicode/localematcher.h b/thirdparty/icu4c/common/unicode/localematcher.h
index 252bb7fdc2..0f7e04a3af 100644
--- a/thirdparty/icu4c/common/unicode/localematcher.h
+++ b/thirdparty/icu4c/common/unicode/localematcher.h
@@ -461,13 +461,13 @@ public:
* Option for whether to include or ignore one-way (fallback) match data.
* By default, they are included.
*
- * @param direction the match direction to set.
+ * @param matchDirection the match direction to set.
* @return this Builder object
* @stable ICU 67
*/
- Builder &setDirection(ULocMatchDirection direction) {
+ Builder &setDirection(ULocMatchDirection matchDirection) {
if (U_SUCCESS(errorCode_)) {
- direction_ = direction;
+ direction_ = matchDirection;
}
return *this;
}
diff --git a/thirdparty/icu4c/common/unicode/rbbi.h b/thirdparty/icu4c/common/unicode/rbbi.h
index 0ce93819f5..0bad0d3897 100644
--- a/thirdparty/icu4c/common/unicode/rbbi.h
+++ b/thirdparty/icu4c/common/unicode/rbbi.h
@@ -147,6 +147,11 @@ private:
*/
int32_t *fLookAheadMatches;
+ /**
+ * A flag to indicate if phrase based breaking is enabled.
+ */
+ UBool fIsPhraseBreaking;
+
//=======================================================================
// constructors
//=======================================================================
@@ -163,6 +168,21 @@ private:
*/
RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status);
+ /**
+ * This constructor uses the udata interface to create a BreakIterator
+ * whose internal tables live in a memory-mapped file. "image" is an
+ * ICU UDataMemory handle for the pre-compiled break iterator tables.
+ * @param image handle to the memory image for the break iterator data.
+ * Ownership of the UDataMemory handle passes to the Break Iterator,
+ * which will be responsible for closing it when it is no longer needed.
+ * @param status Information on any errors encountered.
+ * @param isPhraseBreaking true if phrase based breaking is required, otherwise false.
+ * @see udata_open
+ * @see #getBinaryRules
+ * @internal (private)
+ */
+ RuleBasedBreakIterator(UDataMemory* image, UBool isPhraseBreaking, UErrorCode &status);
+
/** @internal */
friend class RBBIRuleBuilder;
/** @internal */
diff --git a/thirdparty/icu4c/common/unicode/ubrk.h b/thirdparty/icu4c/common/unicode/ubrk.h
index c603f7c13f..2b3dc7aa57 100644
--- a/thirdparty/icu4c/common/unicode/ubrk.h
+++ b/thirdparty/icu4c/common/unicode/ubrk.h
@@ -312,11 +312,12 @@ ubrk_openBinaryRules(const uint8_t *binaryRules, int32_t rulesLength,
* If *pBufferSize is not enough for a stack-based safe clone,
* new memory will be allocated.
* @param status to indicate whether the operation went on smoothly or there were errors
- * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary.
+ * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used
+ * if pBufferSize != NULL and any allocations were necessary
* @return pointer to the new clone
* @deprecated ICU 69 Use ubrk_clone() instead.
*/
-U_CAPI UBreakIterator * U_EXPORT2
+U_DEPRECATED UBreakIterator * U_EXPORT2
ubrk_safeClone(
const UBreakIterator *bi,
void *stackBuffer,
@@ -325,21 +326,17 @@ ubrk_safeClone(
#endif /* U_HIDE_DEPRECATED_API */
-#ifndef U_HIDE_DRAFT_API
-
/**
* Thread safe cloning operation.
* @param bi iterator to be cloned
* @param status to indicate whether the operation went on smoothly or there were errors
* @return pointer to the new clone
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI UBreakIterator * U_EXPORT2
ubrk_clone(const UBreakIterator *bi,
UErrorCode *status);
-#endif // U_HIDE_DRAFT_API
-
#ifndef U_HIDE_DEPRECATED_API
/**
diff --git a/thirdparty/icu4c/common/unicode/ucnv.h b/thirdparty/icu4c/common/unicode/ucnv.h
index 2687c984d4..20c173b662 100644
--- a/thirdparty/icu4c/common/unicode/ucnv.h
+++ b/thirdparty/icu4c/common/unicode/ucnv.h
@@ -477,7 +477,7 @@ ucnv_openCCSID(int32_t codepage,
*
* <p>The name will NOT be looked up in the alias mechanism, nor will the converter be
* stored in the converter cache or the alias table. The only way to open further converters
- * is call this function multiple times, or use the ucnv_safeClone() function to clone a
+ * is call this function multiple times, or use the ucnv_clone() function to clone a
* 'primary' converter.</p>
*
* <p>A future version of ICU may add alias table lookups and/or caching
@@ -493,7 +493,7 @@ ucnv_openCCSID(int32_t codepage,
* @return the created Unicode converter object, or <TT>NULL</TT> if an error occurred
* @see udata_open
* @see ucnv_open
- * @see ucnv_safeClone
+ * @see ucnv_clone
* @see ucnv_close
* @stable ICU 2.2
*/
@@ -502,6 +502,20 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode
/**
* Thread safe converter cloning operation.
+ *
+ * You must ucnv_close() the clone.
+ *
+ * @param cnv converter to be cloned
+ * @param status to indicate whether the operation went on smoothly or there were errors
+ * @return pointer to the new clone
+ * @stable ICU 71
+ */
+U_CAPI UConverter* U_EXPORT2 ucnv_clone(const UConverter *cnv, UErrorCode *status);
+
+#ifndef U_HIDE_DEPRECATED_API
+
+/**
+ * Thread safe converter cloning operation.
* For most efficient operation, pass in a stackBuffer (and a *pBufferSize)
* with at least U_CNV_SAFECLONE_BUFFERSIZE bytes of space.
* If the buffer size is sufficient, then the clone will use the stack buffer;
@@ -532,21 +546,19 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode
* pointer to size of allocated space.
* @param status to indicate whether the operation went on smoothly or there were errors
* An informational status value, U_SAFECLONE_ALLOCATED_WARNING,
- * is used if any allocations were necessary.
+ * is used if pBufferSize != NULL and any allocations were necessary
* However, it is better to check if *pBufferSize grew for checking for
* allocations because warning codes can be overridden by subsequent
* function calls.
* @return pointer to the new clone
- * @stable ICU 2.0
+ * @deprecated ICU 71 Use ucnv_clone() instead.
*/
-U_CAPI UConverter * U_EXPORT2
+U_DEPRECATED UConverter * U_EXPORT2
ucnv_safeClone(const UConverter *cnv,
void *stackBuffer,
int32_t *pBufferSize,
UErrorCode *status);
-#ifndef U_HIDE_DEPRECATED_API
-
/**
* \def U_CNV_SAFECLONE_BUFFERSIZE
* Definition of a buffer size that is designed to be large enough for
diff --git a/thirdparty/icu4c/common/unicode/uniset.h b/thirdparty/icu4c/common/unicode/uniset.h
index 730337a353..310c7c8d20 100644
--- a/thirdparty/icu4c/common/unicode/uniset.h
+++ b/thirdparty/icu4c/common/unicode/uniset.h
@@ -1229,7 +1229,6 @@ public:
*/
UnicodeSet& retain(UChar32 c);
-#ifndef U_HIDE_DRAFT_API
/**
* Retains only the specified string from this set if it is present.
* Upon return this set will be empty if it did not contain s, or
@@ -1238,10 +1237,9 @@ public:
*
* @param s the source string
* @return this object, for chaining
- * @draft ICU 69
+ * @stable ICU 69
*/
UnicodeSet& retain(const UnicodeString &s);
-#endif // U_HIDE_DRAFT_API
/**
* Removes the specified range from this set if it is present.
diff --git a/thirdparty/icu4c/common/unicode/urename.h b/thirdparty/icu4c/common/unicode/urename.h
index 4605f632ea..d9f9b8f336 100644
--- a/thirdparty/icu4c/common/unicode/urename.h
+++ b/thirdparty/icu4c/common/unicode/urename.h
@@ -567,6 +567,7 @@
#define ucase_addStringCaseClosure U_ICU_ENTRY_POINT_RENAME(ucase_addStringCaseClosure)
#define ucase_fold U_ICU_ENTRY_POINT_RENAME(ucase_fold)
#define ucase_getCaseLocale U_ICU_ENTRY_POINT_RENAME(ucase_getCaseLocale)
+#define ucase_getSingleton U_ICU_ENTRY_POINT_RENAME(ucase_getSingleton)
#define ucase_getTrie U_ICU_ENTRY_POINT_RENAME(ucase_getTrie)
#define ucase_getType U_ICU_ENTRY_POINT_RENAME(ucase_getType)
#define ucase_getTypeOrIgnorable U_ICU_ENTRY_POINT_RENAME(ucase_getTypeOrIgnorable)
@@ -630,6 +631,7 @@
#define ucnv_cbFromUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbFromUWriteUChars)
#define ucnv_cbToUWriteSub U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteSub)
#define ucnv_cbToUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteUChars)
+#define ucnv_clone U_ICU_ENTRY_POINT_RENAME(ucnv_clone)
#define ucnv_close U_ICU_ENTRY_POINT_RENAME(ucnv_close)
#define ucnv_compareNames U_ICU_ENTRY_POINT_RENAME(ucnv_compareNames)
#define ucnv_convert U_ICU_ENTRY_POINT_RENAME(ucnv_convert)
@@ -725,6 +727,7 @@
#define ucnvsel_selectForString U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForString)
#define ucnvsel_selectForUTF8 U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForUTF8)
#define ucnvsel_serialize U_ICU_ENTRY_POINT_RENAME(ucnvsel_serialize)
+#define ucol_clone U_ICU_ENTRY_POINT_RENAME(ucol_clone)
#define ucol_cloneBinary U_ICU_ENTRY_POINT_RENAME(ucol_cloneBinary)
#define ucol_close U_ICU_ENTRY_POINT_RENAME(ucol_close)
#define ucol_closeElements U_ICU_ENTRY_POINT_RENAME(ucol_closeElements)
@@ -904,6 +907,7 @@
#define udatpg_getBestPattern U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPattern)
#define udatpg_getBestPatternWithOptions U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPatternWithOptions)
#define udatpg_getDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormat)
+#define udatpg_getDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormatForStyle)
#define udatpg_getDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_getDecimal)
#define udatpg_getDefaultHourCycle U_ICU_ENTRY_POINT_RENAME(udatpg_getDefaultHourCycle)
#define udatpg_getFieldDisplayName U_ICU_ENTRY_POINT_RENAME(udatpg_getFieldDisplayName)
@@ -918,6 +922,7 @@
#define udatpg_setAppendItemFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemFormat)
#define udatpg_setAppendItemName U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemName)
#define udatpg_setDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormat)
+#define udatpg_setDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormatForStyle)
#define udatpg_setDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_setDecimal)
#define udict_swap U_ICU_ENTRY_POINT_RENAME(udict_swap)
#define udtitvfmt_close U_ICU_ENTRY_POINT_RENAME(udtitvfmt_close)
diff --git a/thirdparty/icu4c/common/unicode/uset.h b/thirdparty/icu4c/common/unicode/uset.h
index 2ef352ef56..33332f2d36 100644
--- a/thirdparty/icu4c/common/unicode/uset.h
+++ b/thirdparty/icu4c/common/unicode/uset.h
@@ -628,7 +628,6 @@ uset_removeRange(USet* set, UChar32 start, UChar32 end);
U_CAPI void U_EXPORT2
uset_removeString(USet* set, const UChar* str, int32_t strLen);
-#ifndef U_HIDE_DRAFT_API
/**
* Removes EACH of the characters in this string. Note: "ch" == {"c", "h"}
* A frozen set will not be modified.
@@ -636,11 +635,10 @@ uset_removeString(USet* set, const UChar* str, int32_t strLen);
* @param set the object to be modified
* @param str the string
* @param length the length of the string, or -1 if NUL-terminated
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_removeAllCodePoints(USet *set, const UChar *str, int32_t length);
-#endif // U_HIDE_DRAFT_API
/**
* Removes from this set all of its elements that are contained in the
@@ -671,7 +669,6 @@ uset_removeAll(USet* set, const USet* removeSet);
U_CAPI void U_EXPORT2
uset_retain(USet* set, UChar32 start, UChar32 end);
-#ifndef U_HIDE_DRAFT_API
/**
* Retains only the specified string from this set if it is present.
* Upon return this set will be empty if it did not contain s, or
@@ -681,7 +678,7 @@ uset_retain(USet* set, UChar32 start, UChar32 end);
* @param set the object to be modified
* @param str the string
* @param length the length of the string, or -1 if NUL-terminated
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_retainString(USet *set, const UChar *str, int32_t length);
@@ -693,11 +690,10 @@ uset_retainString(USet *set, const UChar *str, int32_t length);
* @param set the object to be modified
* @param str the string
* @param length the length of the string, or -1 if NUL-terminated
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_retainAllCodePoints(USet *set, const UChar *str, int32_t length);
-#endif // U_HIDE_DRAFT_API
/**
* Retains only the elements in this set that are contained in the
@@ -741,7 +737,6 @@ uset_compact(USet* set);
U_CAPI void U_EXPORT2
uset_complement(USet* set);
-#ifndef U_HIDE_DRAFT_API
/**
* Complements the specified range in this set. Any character in
* the range will be removed if it is in this set, or will be
@@ -753,7 +748,7 @@ uset_complement(USet* set);
* @param set the object to be modified
* @param start first character, inclusive, of range
* @param end last character, inclusive, of range
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_complementRange(USet *set, UChar32 start, UChar32 end);
@@ -766,7 +761,7 @@ uset_complementRange(USet *set, UChar32 start, UChar32 end);
* @param set the object to be modified
* @param str the string
* @param length the length of the string, or -1 if NUL-terminated
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_complementString(USet *set, const UChar *str, int32_t length);
@@ -778,11 +773,10 @@ uset_complementString(USet *set, const UChar *str, int32_t length);
* @param set the object to be modified
* @param str the string
* @param length the length of the string, or -1 if NUL-terminated
- * @draft ICU 69
+ * @stable ICU 69
*/
U_CAPI void U_EXPORT2
uset_complementAllCodePoints(USet *set, const UChar *str, int32_t length);
-#endif // U_HIDE_DRAFT_API
/**
* Complements in this set all elements contained in the specified
diff --git a/thirdparty/icu4c/common/unicode/uvernum.h b/thirdparty/icu4c/common/unicode/uvernum.h
index 42e8865d7e..2706e0b060 100644
--- a/thirdparty/icu4c/common/unicode/uvernum.h
+++ b/thirdparty/icu4c/common/unicode/uvernum.h
@@ -60,7 +60,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.4
*/
-#define U_ICU_VERSION_MAJOR_NUM 70
+#define U_ICU_VERSION_MAJOR_NUM 71
/** The current ICU minor version as an integer.
* This value will change in the subsequent releases of ICU
@@ -86,7 +86,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.6
*/
-#define U_ICU_VERSION_SUFFIX _70
+#define U_ICU_VERSION_SUFFIX _71
/**
* \def U_DEF2_ICU_ENTRY_POINT_RENAME
@@ -139,7 +139,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.4
*/
-#define U_ICU_VERSION "70.1"
+#define U_ICU_VERSION "71.1"
/**
* The current ICU library major version number as a string, for library name suffixes.
@@ -152,13 +152,13 @@
*
* @stable ICU 2.6
*/
-#define U_ICU_VERSION_SHORT "70"
+#define U_ICU_VERSION_SHORT "71"
#ifndef U_HIDE_INTERNAL_API
/** Data version in ICU4C.
* @internal ICU 4.4 Internal Use Only
**/
-#define U_ICU_DATA_VERSION "70.1"
+#define U_ICU_DATA_VERSION "71.1"
#endif /* U_HIDE_INTERNAL_API */
/*===========================================================================
diff --git a/thirdparty/icu4c/common/unistr.cpp b/thirdparty/icu4c/common/unistr.cpp
index 077b4d6ef2..c18665928d 100644
--- a/thirdparty/icu4c/common/unistr.cpp
+++ b/thirdparty/icu4c/common/unistr.cpp
@@ -334,7 +334,8 @@ Replaceable::clone() const {
// UnicodeString overrides clone() with a real implementation
UnicodeString *
UnicodeString::clone() const {
- return new UnicodeString(*this);
+ LocalPointer<UnicodeString> clonedString(new UnicodeString(*this));
+ return clonedString.isValid() && !clonedString->isBogus() ? clonedString.orphan() : nullptr;
}
//========================================
@@ -1976,7 +1977,12 @@ The vector deleting destructor is already a part of UObject,
but defining it here makes sure that it is included with this object file.
This makes sure that static library dependencies are kept to a minimum.
*/
+#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 1100
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
static void uprv_UnicodeStringDummy(void) {
delete [] (new UnicodeString[2]);
}
+#pragma GCC diagnostic pop
+#endif
#endif
diff --git a/thirdparty/icu4c/common/ustrcase.cpp b/thirdparty/icu4c/common/ustrcase.cpp
index 36b19e75f2..43910ea520 100644
--- a/thirdparty/icu4c/common/ustrcase.cpp
+++ b/thirdparty/icu4c/common/ustrcase.cpp
@@ -36,6 +36,12 @@
#include "ustr_imp.h"
#include "uassert.h"
+/**
+ * Code point for COMBINING ACUTE ACCENT
+ * @internal
+ */
+#define ACUTE u'\u0301'
+
U_NAMESPACE_BEGIN
namespace {
@@ -396,6 +402,94 @@ U_NAMESPACE_USE
#if !UCONFIG_NO_BREAK_ITERATION
+namespace {
+
+/**
+ * Input: c is a letter I with or without acute accent.
+ * start is the index in src after c, and is less than segmentLimit.
+ * If a plain i/I is followed by a plain j/J,
+ * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute,
+ * then we output accordingly.
+ *
+ * @return the src index after the titlecased sequence, or the start index if no Dutch IJ
+ */
+int32_t maybeTitleDutchIJ(const UChar *src, UChar32 c, int32_t start, int32_t segmentLimit,
+ UChar *dest, int32_t &destIndex, int32_t destCapacity, uint32_t options,
+ icu::Edits *edits) {
+ U_ASSERT(start < segmentLimit);
+
+ int32_t index = start;
+ bool withAcute = false;
+
+ // If the conditions are met, then the following variables tell us what to output.
+ int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3)
+ bool doTitleJ = false; // true if the j needs to be titlecased
+ int32_t unchanged2 = 0; // after the j (0 or 1)
+
+ // next character after the first letter
+ UChar c2 = src[index++];
+
+ // Is the first letter an i/I with accent?
+ if (c == u'I') {
+ if (c2 == ACUTE) {
+ withAcute = true;
+ unchanged1 = 1;
+ if (index == segmentLimit) { return start; }
+ c2 = src[index++];
+ }
+ } else { // Ã
+ withAcute = true;
+ }
+
+ // Is the next character a j/J?
+ if (c2 == u'j') {
+ doTitleJ = true;
+ } else if (c2 == u'J') {
+ ++unchanged1;
+ } else {
+ return start;
+ }
+
+ // A plain i/I must be followed by a plain j/J.
+ // An i/I with acute must be followed by a j/J with acute.
+ if (withAcute) {
+ if (index == segmentLimit || src[index++] != ACUTE) { return start; }
+ if (doTitleJ) {
+ unchanged2 = 1;
+ } else {
+ ++unchanged1;
+ }
+ }
+
+ // There must not be another combining mark.
+ if (index < segmentLimit) {
+ int32_t cp;
+ int32_t i = index;
+ U16_NEXT(src, i, segmentLimit, cp);
+ uint32_t typeMask = U_GET_GC_MASK(cp);
+ if ((typeMask & U_GC_M_MASK) != 0) {
+ return start;
+ }
+ }
+
+ // Output the rest of the Dutch IJ.
+ destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged1, options, edits);
+ start += unchanged1;
+ if (doTitleJ) {
+ destIndex = appendUChar(dest, destIndex, destCapacity, u'J');
+ if (edits != nullptr) {
+ edits->addReplace(1, 1);
+ }
+ ++start;
+ }
+ destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged2, options, edits);
+
+ U_ASSERT(start + unchanged2 == index);
+ return index;
+}
+
+} // namespace
+
U_CFUNC int32_t U_CALLCONV
ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *iter,
UChar *dest, int32_t destCapacity,
@@ -412,14 +506,14 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it
csc.limit=srcLength;
int32_t destIndex=0;
int32_t prev=0;
- UBool isFirstIndex=TRUE;
+ bool isFirstIndex=true;
/* titlecasing loop */
while(prev<srcLength) {
/* find next index where to titlecase */
int32_t index;
if(isFirstIndex) {
- isFirstIndex=FALSE;
+ isFirstIndex=false;
index=iter->first();
} else {
index=iter->next();
@@ -446,7 +540,7 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it
// Stop with titleStart<titleLimit<=index
// if there is a character to be titlecased,
// or else stop with titleStart==titleLimit==index.
- UBool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0;
+ bool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0;
while (toCased ? UCASE_NONE==ucase_getType(c) : !ustrcase_isLNS(c)) {
titleStart=titleLimit;
if(titleLimit==index) {
@@ -479,27 +573,15 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it
/* Special case Dutch IJ titlecasing */
if (titleStart+1 < index &&
- caseLocale == UCASE_LOC_DUTCH &&
- (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) {
- if (src[titleStart+1] == 0x006A) {
- destIndex=appendUChar(dest, destIndex, destCapacity, 0x004A);
- if(destIndex<0) {
- errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- }
- if(edits!=NULL) {
- edits->addReplace(1, 1);
- }
- titleLimit++;
- } else if (src[titleStart+1] == 0x004A) {
- // Keep the capital J from getting lowercased.
- destIndex=appendUnchanged(dest, destIndex, destCapacity,
- src+titleStart+1, 1, options, edits);
- if(destIndex<0) {
- errorCode=U_INDEX_OUTOFBOUNDS_ERROR;
- return 0;
- }
- titleLimit++;
+ caseLocale == UCASE_LOC_DUTCH) {
+ if (c < 0) {
+ c = ~c;
+ }
+
+ if (c == u'I' || c == u'Ã') {
+ titleLimit = maybeTitleDutchIJ(src, c, titleStart + 1, index,
+ dest, destIndex, destCapacity, options,
+ edits);
}
}
diff --git a/thirdparty/icu4c/common/uvector.cpp b/thirdparty/icu4c/common/uvector.cpp
index 4da8b864e1..844463921e 100644
--- a/thirdparty/icu4c/common/uvector.cpp
+++ b/thirdparty/icu4c/common/uvector.cpp
@@ -99,14 +99,6 @@ bool UVector::operator==(const UVector& other) const {
return true;
}
-// TODO: delete this function once all call sites have been migrated to the
-// new addElement().
-void UVector::addElementX(void* obj, UErrorCode &status) {
- if (ensureCapacityX(count + 1, status)) {
- elements[count++].pointer = obj;
- }
-}
-
void UVector::addElement(void* obj, UErrorCode &status) {
U_ASSERT(deleter == nullptr);
if (ensureCapacity(count + 1, status)) {
@@ -331,38 +323,6 @@ int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const {
return -1;
}
-UBool UVector::ensureCapacityX(int32_t minimumCapacity, UErrorCode &status) {
- if (minimumCapacity < 0) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return FALSE;
- }
- if (capacity < minimumCapacity) {
- if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return FALSE;
- }
- int32_t newCap = capacity * 2;
- if (newCap < minimumCapacity) {
- newCap = minimumCapacity;
- }
- if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check
- // We keep the original memory contents on bad minimumCapacity.
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return FALSE;
- }
- UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap);
- if (newElems == nullptr) {
- // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
- status = U_MEMORY_ALLOCATION_ERROR;
- return FALSE;
- }
- elements = newElems;
- capacity = newCap;
- }
- return TRUE;
-}
-
-
UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
if (U_FAILURE(status)) {
return false;
@@ -370,7 +330,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
if (minimumCapacity < 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return false;
- }
+ }
if (capacity < minimumCapacity) {
if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check
status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -396,6 +356,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
}
return true;
}
+
/**
* Change the size of this vector as follows: If newSize is smaller,
* then truncate the array, possibly deleting held elements for i >=
diff --git a/thirdparty/icu4c/common/uvector.h b/thirdparty/icu4c/common/uvector.h
index f61fcc2be6..1eb7d136e7 100644
--- a/thirdparty/icu4c/common/uvector.h
+++ b/thirdparty/icu4c/common/uvector.h
@@ -123,12 +123,6 @@ public:
// java.util.Vector API
//------------------------------------------------------------
- /*
- * Old version of addElement, with non-standard error handling.
- * Will be removed once all uses have been switched to the new addElement().
- */
- void addElementX(void* obj, UErrorCode &status);
-
/**
* Add an element at the end of the vector.
* For use only with vectors that do not adopt their elements, which is to say,
@@ -197,12 +191,6 @@ public:
inline UBool isEmpty(void) const {return count == 0;}
- /*
- * Old version of ensureCapacity, with non-standard error handling.
- * Will be removed once all uses have been switched to the new ensureCapacity().
- */
- UBool ensureCapacityX(int32_t minimumCapacity, UErrorCode &status);
-
UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status);
/**
diff --git a/thirdparty/icu4c/common/uvectr32.cpp b/thirdparty/icu4c/common/uvectr32.cpp
index a77ecb689f..2b4d0b8a75 100644
--- a/thirdparty/icu4c/common/uvectr32.cpp
+++ b/thirdparty/icu4c/common/uvectr32.cpp
@@ -83,7 +83,7 @@ void UVector32::assign(const UVector32& other, UErrorCode &ec) {
}
-bool UVector32::operator==(const UVector32& other) {
+bool UVector32::operator==(const UVector32& other) const {
int32_t i;
if (count != other.count) return false;
for (i=0; i<count; ++i) {
diff --git a/thirdparty/icu4c/common/uvectr32.h b/thirdparty/icu4c/common/uvectr32.h
index f08c2ade76..ecefb7af3e 100644
--- a/thirdparty/icu4c/common/uvectr32.h
+++ b/thirdparty/icu4c/common/uvectr32.h
@@ -86,12 +86,12 @@ public:
* equal if they are of the same size and all elements are equal,
* as compared using this object's comparer.
*/
- bool operator==(const UVector32& other);
+ bool operator==(const UVector32& other) const;
/**
* Equivalent to !operator==()
*/
- inline bool operator!=(const UVector32& other);
+ inline bool operator!=(const UVector32& other) const;
//------------------------------------------------------------
// java.util.Vector API
@@ -268,7 +268,7 @@ inline int32_t UVector32::lastElementi(void) const {
return elementAti(count-1);
}
-inline bool UVector32::operator!=(const UVector32& other) {
+inline bool UVector32::operator!=(const UVector32& other) const {
return !operator==(other);
}
diff --git a/thirdparty/icu4c/godot_data.json b/thirdparty/icu4c/godot_data.json
index 3a9c28af4c..e36e2b078b 100644
--- a/thirdparty/icu4c/godot_data.json
+++ b/thirdparty/icu4c/godot_data.json
@@ -6,5 +6,6 @@
brkitr_tree: include
misc: include
normalization: include
+ confusables: include
}
-} \ No newline at end of file
+}
diff --git a/thirdparty/icu4c/i18n/scriptset.cpp b/thirdparty/icu4c/i18n/scriptset.cpp
new file mode 100644
index 0000000000..6a1db8c01c
--- /dev/null
+++ b/thirdparty/icu4c/i18n/scriptset.cpp
@@ -0,0 +1,313 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2014, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*
+* scriptset.cpp
+*
+* created on: 2013 Jan 7
+* created by: Andy Heninger
+*/
+
+#include "unicode/utypes.h"
+
+#include "unicode/uchar.h"
+#include "unicode/unistr.h"
+
+#include "scriptset.h"
+#include "uassert.h"
+#include "cmemory.h"
+
+U_NAMESPACE_BEGIN
+
+//----------------------------------------------------------------------------
+//
+// ScriptSet implementation
+//
+//----------------------------------------------------------------------------
+ScriptSet::ScriptSet() {
+ uprv_memset(bits, 0, sizeof(bits));
+}
+
+ScriptSet::~ScriptSet() {
+}
+
+ScriptSet::ScriptSet(const ScriptSet &other) {
+ *this = other;
+}
+
+ScriptSet & ScriptSet::operator =(const ScriptSet &other) {
+ uprv_memcpy(bits, other.bits, sizeof(bits));
+ return *this;
+}
+
+bool ScriptSet::operator == (const ScriptSet &other) const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if (bits[i] != other.bits[i]) {
+ return false;
+ }
+ }
+ return true;
+}
+
+UBool ScriptSet::test(UScriptCode script, UErrorCode &status) const {
+ if (U_FAILURE(status)) {
+ return FALSE;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return FALSE;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ return ((bits[index] & bit) != 0);
+}
+
+
+ScriptSet &ScriptSet::set(UScriptCode script, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return *this;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ bits[index] |= bit;
+ return *this;
+}
+
+ScriptSet &ScriptSet::reset(UScriptCode script, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ if (script < 0 || (int32_t)script >= SCRIPT_LIMIT) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return *this;
+ }
+ uint32_t index = script / 32;
+ uint32_t bit = 1 << (script & 31);
+ bits[index] &= ~bit;
+ return *this;
+}
+
+
+
+ScriptSet &ScriptSet::Union(const ScriptSet &other) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] |= other.bits[i];
+ }
+ return *this;
+}
+
+ScriptSet &ScriptSet::intersect(const ScriptSet &other) {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] &= other.bits[i];
+ }
+ return *this;
+}
+
+ScriptSet &ScriptSet::intersect(UScriptCode script, UErrorCode &status) {
+ ScriptSet t;
+ t.set(script, status);
+ if (U_SUCCESS(status)) {
+ this->intersect(t);
+ }
+ return *this;
+}
+
+UBool ScriptSet::intersects(const ScriptSet &other) const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if ((bits[i] & other.bits[i]) != 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+UBool ScriptSet::contains(const ScriptSet &other) const {
+ ScriptSet t(*this);
+ t.intersect(other);
+ return (t == other);
+}
+
+
+ScriptSet &ScriptSet::setAll() {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ bits[i] = 0xffffffffu;
+ }
+ return *this;
+}
+
+
+ScriptSet &ScriptSet::resetAll() {
+ uprv_memset(bits, 0, sizeof(bits));
+ return *this;
+}
+
+int32_t ScriptSet::countMembers() const {
+ // This bit counter is good for sparse numbers of '1's, which is
+ // very much the case that we will usually have.
+ int32_t count = 0;
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ uint32_t x = bits[i];
+ while (x > 0) {
+ count++;
+ x &= (x - 1); // and off the least significant one bit.
+ }
+ }
+ return count;
+}
+
+int32_t ScriptSet::hashCode() const {
+ int32_t hash = 0;
+ for (int32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ hash ^= bits[i];
+ }
+ return hash;
+}
+
+int32_t ScriptSet::nextSetBit(int32_t fromIndex) const {
+ // TODO: Wants a better implementation.
+ if (fromIndex < 0) {
+ return -1;
+ }
+ UErrorCode status = U_ZERO_ERROR;
+ for (int32_t scriptIndex = fromIndex; scriptIndex < SCRIPT_LIMIT; scriptIndex++) {
+ if (test((UScriptCode)scriptIndex, status)) {
+ return scriptIndex;
+ }
+ }
+ return -1;
+}
+
+UBool ScriptSet::isEmpty() const {
+ for (uint32_t i=0; i<UPRV_LENGTHOF(bits); i++) {
+ if (bits[i] != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+UnicodeString &ScriptSet::displayScripts(UnicodeString &dest) const {
+ UBool firstTime = TRUE;
+ for (int32_t i = nextSetBit(0); i >= 0; i = nextSetBit(i + 1)) {
+ if (!firstTime) {
+ dest.append((UChar)0x20);
+ }
+ firstTime = FALSE;
+ const char *scriptName = uscript_getShortName((UScriptCode(i)));
+ dest.append(UnicodeString(scriptName, -1, US_INV));
+ }
+ return dest;
+}
+
+ScriptSet &ScriptSet::parseScripts(const UnicodeString &scriptString, UErrorCode &status) {
+ resetAll();
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ UnicodeString oneScriptName;
+ for (int32_t i=0; i<scriptString.length();) {
+ UChar32 c = scriptString.char32At(i);
+ i = scriptString.moveIndex32(i, 1);
+ if (!u_isUWhiteSpace(c)) {
+ oneScriptName.append(c);
+ if (i < scriptString.length()) {
+ continue;
+ }
+ }
+ if (oneScriptName.length() > 0) {
+ char buf[40];
+ oneScriptName.extract(0, oneScriptName.length(), buf, sizeof(buf)-1, US_INV);
+ buf[sizeof(buf)-1] = 0;
+ int32_t sc = u_getPropertyValueEnum(UCHAR_SCRIPT, buf);
+ if (sc == UCHAR_INVALID_CODE) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ } else {
+ this->set((UScriptCode)sc, status);
+ }
+ if (U_FAILURE(status)) {
+ return *this;
+ }
+ oneScriptName.remove();
+ }
+ }
+ return *this;
+}
+
+void ScriptSet::setScriptExtensions(UChar32 codePoint, UErrorCode& status) {
+ if (U_FAILURE(status)) { return; }
+ static const int32_t FIRST_GUESS_SCRIPT_CAPACITY = 20;
+ MaybeStackArray<UScriptCode,FIRST_GUESS_SCRIPT_CAPACITY> scripts;
+ UErrorCode internalStatus = U_ZERO_ERROR;
+ int32_t script_count = -1;
+
+ while (TRUE) {
+ script_count = uscript_getScriptExtensions(
+ codePoint, scripts.getAlias(), scripts.getCapacity(), &internalStatus);
+ if (internalStatus == U_BUFFER_OVERFLOW_ERROR) {
+ // Need to allocate more space
+ if (scripts.resize(script_count) == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ internalStatus = U_ZERO_ERROR;
+ } else {
+ break;
+ }
+ }
+
+ // Check if we failed for some reason other than buffer overflow
+ if (U_FAILURE(internalStatus)) {
+ status = internalStatus;
+ return;
+ }
+
+ // Load the scripts into the ScriptSet and return
+ for (int32_t i = 0; i < script_count; i++) {
+ this->set(scripts[i], status);
+ if (U_FAILURE(status)) { return; }
+ }
+}
+
+U_NAMESPACE_END
+
+U_CAPI UBool U_EXPORT2
+uhash_equalsScriptSet(const UElement key1, const UElement key2) {
+ icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
+ icu::ScriptSet *s2 = static_cast<icu::ScriptSet *>(key2.pointer);
+ return (*s1 == *s2);
+}
+
+U_CAPI int8_t U_EXPORT2
+uhash_compareScriptSet(UElement key0, UElement key1) {
+ icu::ScriptSet *s0 = static_cast<icu::ScriptSet *>(key0.pointer);
+ icu::ScriptSet *s1 = static_cast<icu::ScriptSet *>(key1.pointer);
+ int32_t diff = s0->countMembers() - s1->countMembers();
+ if (diff != 0) return static_cast<UBool>(diff);
+ int32_t i0 = s0->nextSetBit(0);
+ int32_t i1 = s1->nextSetBit(0);
+ while ((diff = i0-i1) == 0 && i0 > 0) {
+ i0 = s0->nextSetBit(i0+1);
+ i1 = s1->nextSetBit(i1+1);
+ }
+ return (int8_t)diff;
+}
+
+U_CAPI int32_t U_EXPORT2
+uhash_hashScriptSet(const UElement key) {
+ icu::ScriptSet *s = static_cast<icu::ScriptSet *>(key.pointer);
+ return s->hashCode();
+}
+
+U_CAPI void U_EXPORT2
+uhash_deleteScriptSet(void *obj) {
+ icu::ScriptSet *s = static_cast<icu::ScriptSet *>(obj);
+ delete s;
+}
diff --git a/thirdparty/icu4c/i18n/scriptset.h b/thirdparty/icu4c/i18n/scriptset.h
new file mode 100644
index 0000000000..51980ab7b3
--- /dev/null
+++ b/thirdparty/icu4c/i18n/scriptset.h
@@ -0,0 +1,86 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2013, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*
+* scriptset.h
+*
+* created on: 2013 Jan 7
+* created by: Andy Heninger
+*/
+
+#ifndef __SCRIPTSET_H__
+#define __SCRIPTSET_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uobject.h"
+#include "unicode/uscript.h"
+
+#include "uelement.h"
+
+U_NAMESPACE_BEGIN
+
+//-------------------------------------------------------------------------------
+//
+// ScriptSet - A bit set representing a set of scripts.
+//
+// This class was originally used exclusively with script sets appearing
+// as part of the spoof check whole script confusable binary data. Its
+// use has since become more general, but the continued use to wrap
+// prebuilt binary data does constrain the design.
+//
+//-------------------------------------------------------------------------------
+class U_I18N_API ScriptSet: public UMemory {
+ public:
+ static constexpr int32_t SCRIPT_LIMIT = 224; // multiple of 32!
+
+ ScriptSet();
+ ScriptSet(const ScriptSet &other);
+ ~ScriptSet();
+
+ bool operator == (const ScriptSet &other) const;
+ bool operator != (const ScriptSet &other) const {return !(*this == other);}
+ ScriptSet & operator = (const ScriptSet &other);
+
+ UBool test(UScriptCode script, UErrorCode &status) const;
+ ScriptSet &Union(const ScriptSet &other);
+ ScriptSet &set(UScriptCode script, UErrorCode &status);
+ ScriptSet &reset(UScriptCode script, UErrorCode &status);
+ ScriptSet &intersect(const ScriptSet &other);
+ ScriptSet &intersect(UScriptCode script, UErrorCode &status);
+ UBool intersects(const ScriptSet &other) const; // Sets contain at least one script in common.
+ UBool contains(const ScriptSet &other) const; // All set bits in other are also set in this.
+
+ ScriptSet &setAll();
+ ScriptSet &resetAll();
+ int32_t countMembers() const;
+ int32_t hashCode() const;
+ int32_t nextSetBit(int32_t script) const;
+
+ UBool isEmpty() const;
+
+ UnicodeString &displayScripts(UnicodeString &dest) const; // append script names to dest string.
+ ScriptSet & parseScripts(const UnicodeString &scriptsString, UErrorCode &status); // Replaces ScriptSet contents.
+
+ // Wraps around UScript::getScriptExtensions() and adds the corresponding scripts to this instance.
+ void setScriptExtensions(UChar32 codePoint, UErrorCode& status);
+
+ private:
+ uint32_t bits[SCRIPT_LIMIT / 32];
+};
+
+U_NAMESPACE_END
+
+U_CAPI UBool U_EXPORT2
+uhash_compareScriptSet(const UElement key1, const UElement key2);
+
+U_CAPI int32_t U_EXPORT2
+uhash_hashScriptSet(const UElement key);
+
+U_CAPI void U_EXPORT2
+uhash_deleteScriptSet(void *obj);
+
+#endif // __SCRIPTSET_H__
diff --git a/thirdparty/icu4c/i18n/ucln_in.cpp b/thirdparty/icu4c/i18n/ucln_in.cpp
new file mode 100644
index 0000000000..f29cbe41dd
--- /dev/null
+++ b/thirdparty/icu4c/i18n/ucln_in.cpp
@@ -0,0 +1,65 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+* *
+* Copyright (C) 2001-2014, International Business Machines *
+* Corporation and others. All Rights Reserved. *
+* *
+******************************************************************************
+* file name: ucln_in.cpp
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2001July05
+* created by: George Rhoten
+*/
+
+#include "ucln.h"
+#include "ucln_in.h"
+#include "mutex.h"
+#include "uassert.h"
+
+/** Auto-client for UCLN_I18N **/
+#define UCLN_TYPE UCLN_I18N
+#include "ucln_imp.h"
+
+/* Leave this copyright notice here! It needs to go somewhere in this library. */
+static const char copyright[] = U_COPYRIGHT_STRING;
+
+static cleanupFunc *gCleanupFunctions[UCLN_I18N_COUNT];
+
+static UBool U_CALLCONV i18n_cleanup(void)
+{
+ int32_t libType = UCLN_I18N_START;
+ (void)copyright; /* Suppress unused variable warning with clang. */
+
+ while (++libType<UCLN_I18N_COUNT) {
+ if (gCleanupFunctions[libType])
+ {
+ gCleanupFunctions[libType]();
+ gCleanupFunctions[libType] = NULL;
+ }
+ }
+#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
+ ucln_unRegisterAutomaticCleanup();
+#endif
+ return TRUE;
+}
+
+void ucln_i18n_registerCleanup(ECleanupI18NType type,
+ cleanupFunc *func) {
+ U_ASSERT(UCLN_I18N_START < type && type < UCLN_I18N_COUNT);
+ {
+ icu::Mutex m; // See ticket 10295 for discussion.
+ ucln_registerCleanup(UCLN_I18N, i18n_cleanup);
+ if (UCLN_I18N_START < type && type < UCLN_I18N_COUNT) {
+ gCleanupFunctions[type] = func;
+ }
+ }
+#if !UCLN_NO_AUTO_CLEANUP && (defined(UCLN_AUTO_ATEXIT) || defined(UCLN_AUTO_LOCAL))
+ ucln_registerAutomaticCleanup();
+#endif
+}
+
diff --git a/thirdparty/icu4c/i18n/ucln_in.h b/thirdparty/icu4c/i18n/ucln_in.h
new file mode 100644
index 0000000000..765cdd559f
--- /dev/null
+++ b/thirdparty/icu4c/i18n/ucln_in.h
@@ -0,0 +1,74 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
+* Copyright (C) 2001-2016, International Business Machines
+* Corporation and others. All Rights Reserved.
+******************************************************************************
+* file name: ucln_in.h
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2001July05
+* created by: George Rhoten
+*/
+
+#ifndef __UCLN_IN_H__
+#define __UCLN_IN_H__
+
+#include "unicode/utypes.h"
+#include "ucln.h"
+
+/*
+Please keep the order of enums declared in same order
+as the functions are suppose to be called.
+It's usually best to have child dependencies called first. */
+typedef enum ECleanupI18NType {
+ UCLN_I18N_START = -1,
+ UCLN_I18N_UNIT_EXTRAS,
+ UCLN_I18N_NUMBER_SKELETONS,
+ UCLN_I18N_CURRENCY_SPACING,
+ UCLN_I18N_SPOOF,
+ UCLN_I18N_SPOOFDATA,
+ UCLN_I18N_TRANSLITERATOR,
+ UCLN_I18N_REGEX,
+ UCLN_I18N_JAPANESE_CALENDAR,
+ UCLN_I18N_ISLAMIC_CALENDAR,
+ UCLN_I18N_CHINESE_CALENDAR,
+ UCLN_I18N_HEBREW_CALENDAR,
+ UCLN_I18N_ASTRO_CALENDAR,
+ UCLN_I18N_DANGI_CALENDAR,
+ UCLN_I18N_CALENDAR,
+ UCLN_I18N_TIMEZONEFORMAT,
+ UCLN_I18N_TZDBTIMEZONENAMES,
+ UCLN_I18N_TIMEZONEGENERICNAMES,
+ UCLN_I18N_TIMEZONENAMES,
+ UCLN_I18N_ZONEMETA,
+ UCLN_I18N_TIMEZONE,
+ UCLN_I18N_DIGITLIST,
+ UCLN_I18N_DECFMT,
+ UCLN_I18N_NUMFMT,
+ UCLN_I18N_ALLOWED_HOUR_FORMATS,
+ UCLN_I18N_DAYPERIODRULES,
+ UCLN_I18N_SMPDTFMT,
+ UCLN_I18N_USEARCH,
+ UCLN_I18N_COLLATOR,
+ UCLN_I18N_UCOL_RES,
+ UCLN_I18N_CSDET,
+ UCLN_I18N_COLLATION_ROOT,
+ UCLN_I18N_GENDERINFO,
+ UCLN_I18N_CDFINFO,
+ UCLN_I18N_REGION,
+ UCLN_I18N_LIST_FORMATTER,
+ UCLN_I18N_NUMSYS,
+ UCLN_I18N_COUNT /* This must be last */
+} ECleanupI18NType;
+
+/* Main library cleanup registration function. */
+/* See common/ucln.h for details on adding a cleanup function. */
+/* Note: the global mutex must not be held when calling this function. */
+U_CFUNC void U_EXPORT2 ucln_i18n_registerCleanup(ECleanupI18NType type,
+ cleanupFunc *func);
+
+#endif
diff --git a/thirdparty/icu4c/i18n/unicode/uspoof.h b/thirdparty/icu4c/i18n/unicode/uspoof.h
new file mode 100644
index 0000000000..b674c91b2c
--- /dev/null
+++ b/thirdparty/icu4c/i18n/unicode/uspoof.h
@@ -0,0 +1,1577 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2016, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+* file name: uspoof.h
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2008Feb13
+* created by: Andy Heninger
+*
+* Unicode Spoof Detection
+*/
+
+#ifndef USPOOF_H
+#define USPOOF_H
+
+#include "unicode/utypes.h"
+#include "unicode/uset.h"
+#include "unicode/parseerr.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+
+#if U_SHOW_CPLUSPLUS_API
+#include "unicode/localpointer.h"
+#include "unicode/unistr.h"
+#include "unicode/uniset.h"
+#endif
+
+
+/**
+ * \file
+ * \brief Unicode Security and Spoofing Detection, C API.
+ *
+ * <p>
+ * This class, based on <a href="http://unicode.org/reports/tr36">Unicode Technical Report #36</a> and
+ * <a href="http://unicode.org/reports/tr39">Unicode Technical Standard #39</a>, has two main functions:
+ *
+ * <ol>
+ * <li>Checking whether two strings are visually <em>confusable</em> with each other, such as "Harvest" and
+ * &quot;&Eta;arvest&quot;, where the second string starts with the Greek capital letter Eta.</li>
+ * <li>Checking whether an individual string is likely to be an attempt at confusing the reader (<em>spoof
+ * detection</em>), such as "paypal" with some Latin characters substituted with Cyrillic look-alikes.</li>
+ * </ol>
+ *
+ * <p>
+ * Although originally designed as a method for flagging suspicious identifier strings such as URLs,
+ * <code>USpoofChecker</code> has a number of other practical use cases, such as preventing attempts to evade bad-word
+ * content filters.
+ *
+ * <p>
+ * The functions of this class are exposed as C API, with a handful of syntactical conveniences for C++.
+ *
+ * <h2>Confusables</h2>
+ *
+ * <p>
+ * The following example shows how to use <code>USpoofChecker</code> to check for confusability between two strings:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str1 = (UChar*) u"Harvest";
+ * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ *
+ * int32_t bitmask = uspoof_areConfusable(sc, str1, -1, str2, -1, &status);
+ * UBool result = bitmask != 0;
+ * // areConfusable: 1 (status: U_ZERO_ERROR)
+ * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * <p>
+ * The call to {@link uspoof_open} creates a <code>USpoofChecker</code> object; the call to {@link uspoof_setChecks}
+ * enables confusable checking and disables all other checks; the call to {@link uspoof_areConfusable} performs the
+ * confusability test; and the following line extracts the result out of the return value. For best performance,
+ * the instance should be created once (e.g., upon application startup), and the efficient
+ * {@link uspoof_areConfusable} method can be used at runtime.
+ *
+ * <p>
+ * The type {@link LocalUSpoofCheckerPointer} is exposed for C++ programmers. It will automatically call
+ * {@link uspoof_close} when the object goes out of scope:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setChecks(sc.getAlias(), USPOOF_CONFUSABLE, &status);
+ * // ...
+ * \endcode
+ *
+ * UTS 39 defines two strings to be <em>confusable</em> if they map to the same <em>skeleton string</em>. A skeleton can
+ * be thought of as a "hash code". {@link uspoof_getSkeleton} computes the skeleton for a particular string, so
+ * the following snippet is equivalent to the example above:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str1 = (UChar*) u"Harvest";
+ * UChar* str2 = (UChar*) u"\u0397arvest"; // with U+0397 GREEK CAPITAL LETTER ETA
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ *
+ * // Get skeleton 1
+ * int32_t skel1Len = uspoof_getSkeleton(sc, 0, str1, -1, NULL, 0, &status);
+ * UChar* skel1 = (UChar*) malloc(++skel1Len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str1, -1, skel1, skel1Len, &status);
+ *
+ * // Get skeleton 2
+ * int32_t skel2Len = uspoof_getSkeleton(sc, 0, str2, -1, NULL, 0, &status);
+ * UChar* skel2 = (UChar*) malloc(++skel2Len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str2, -1, skel2, skel2Len, &status);
+ *
+ * // Are the skeletons the same?
+ * UBool result = u_strcmp(skel1, skel2) == 0;
+ * // areConfusable: 1 (status: U_ZERO_ERROR)
+ * printf("areConfusable: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * free(skel1);
+ * free(skel2);
+ * \endcode
+ *
+ * If you need to check if a string is confusable with any string in a dictionary of many strings, rather than calling
+ * {@link uspoof_areConfusable} many times in a loop, {@link uspoof_getSkeleton} can be used instead, as shown below:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * #define DICTIONARY_LENGTH 2
+ * UChar* dictionary[DICTIONARY_LENGTH] = { (UChar*) u"lorem", (UChar*) u"ipsum" };
+ * UChar* skeletons[DICTIONARY_LENGTH];
+ * UChar* str = (UChar*) u"1orern";
+ *
+ * // Setup:
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * UChar* word = dictionary[i];
+ * int32_t len = uspoof_getSkeleton(sc, 0, word, -1, NULL, 0, &status);
+ * skeletons[i] = (UChar*) malloc(++len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, word, -1, skeletons[i], len, &status);
+ * }
+ *
+ * // Live Check:
+ * {
+ * int32_t len = uspoof_getSkeleton(sc, 0, str, -1, NULL, 0, &status);
+ * UChar* skel = (UChar*) malloc(++len * sizeof(UChar));
+ * status = U_ZERO_ERROR;
+ * uspoof_getSkeleton(sc, 0, str, -1, skel, len, &status);
+ * UBool result = false;
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * result = u_strcmp(skel, skeletons[i]) == 0;
+ * if (result == true) { break; }
+ * }
+ * // Has confusable in dictionary: 1 (status: U_ZERO_ERROR)
+ * printf("Has confusable in dictionary: %d (status: %s)\n", result, u_errorName(status));
+ * free(skel);
+ * }
+ *
+ * for (size_t i=0; i<DICTIONARY_LENGTH; i++) {
+ * free(skeletons[i]);
+ * }
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * <b>Note:</b> Since the Unicode confusables mapping table is frequently updated, confusable skeletons are <em>not</em>
+ * guaranteed to be the same between ICU releases. We therefore recommend that you always compute confusable skeletons
+ * at runtime and do not rely on creating a permanent, or difficult to update, database of skeletons.
+ *
+ * <h2>Spoof Detection</h2>
+ *
+ * The following snippet shows a minimal example of using <code>USpoofChecker</code> to perform spoof detection on a
+ * string:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * USet* allowed = uset_openEmpty();
+ * uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ * uset_addAll(allowed, uspoof_getInclusionSet(&status));
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setAllowedChars(sc, allowed, &status);
+ * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * int32_t bitmask = uspoof_check(sc, str, -1, NULL, &status);
+ * UBool result = bitmask != 0;
+ * // fails checks: 1 (status: U_ZERO_ERROR)
+ * printf("fails checks: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * uset_close(allowed);
+ * \endcode
+ *
+ * As in the case for confusability checking, it is good practice to create one <code>USpoofChecker</code> instance at
+ * startup, and call the cheaper {@link uspoof_check} online. We specify the set of
+ * allowed characters to be those with type RECOMMENDED or INCLUSION, according to the recommendation in UTS 39.
+ *
+ * In addition to {@link uspoof_check}, the function {@link uspoof_checkUTF8} is exposed for UTF8-encoded char* strings,
+ * and {@link uspoof_checkUnicodeString} is exposed for C++ programmers.
+ *
+ * If the {@link USPOOF_AUX_INFO} check is enabled, a limited amount of information on why a string failed the checks
+ * is available in the returned bitmask. For complete information, use the {@link uspoof_check2} class of functions
+ * with a {@link USpoofCheckResult} parameter:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"p\u0430ypal"; // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * USet* allowed = uset_openEmpty();
+ * uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ * uset_addAll(allowed, uspoof_getInclusionSet(&status));
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setAllowedChars(sc, allowed, &status);
+ * uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * USpoofCheckResult* checkResult = uspoof_openCheckResult(&status);
+ * int32_t bitmask = uspoof_check2(sc, str, -1, checkResult, &status);
+ *
+ * int32_t failures1 = bitmask;
+ * int32_t failures2 = uspoof_getCheckResultChecks(checkResult, &status);
+ * assert(failures1 == failures2);
+ * // checks that failed: 0x00000010 (status: U_ZERO_ERROR)
+ * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status));
+ *
+ * // Cleanup:
+ * uspoof_close(sc);
+ * uset_close(allowed);
+ * uspoof_closeCheckResult(checkResult);
+ * \endcode
+ *
+ * C++ users can take advantage of a few syntactical conveniences. The following snippet is functionally
+ * equivalent to the one above:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * UnicodeSet allowed;
+ * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status));
+ * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status));
+ *
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status);
+ * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE);
+ *
+ * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status));
+ * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status);
+ *
+ * int32_t failures1 = bitmask;
+ * int32_t failures2 = uspoof_getCheckResultChecks(checkResult.getAlias(), &status);
+ * assert(failures1 == failures2);
+ * // checks that failed: 0x00000010 (status: U_ZERO_ERROR)
+ * printf("checks that failed: %#010x (status: %s)\n", failures1, u_errorName(status));
+ *
+ * // Explicit cleanup not necessary.
+ * \endcode
+ *
+ * The return value is a bitmask of the checks that failed. In this case, there was one check that failed:
+ * {@link USPOOF_RESTRICTION_LEVEL}, corresponding to the fifth bit (16). The possible checks are:
+ *
+ * <ul>
+ * <li><code>RESTRICTION_LEVEL</code>: flags strings that violate the
+ * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">Restriction Level</a> test as specified in UTS
+ * 39; in most cases, this means flagging strings that contain characters from multiple different scripts.</li>
+ * <li><code>INVISIBLE</code>: flags strings that contain invisible characters, such as zero-width spaces, or character
+ * sequences that are likely not to display, such as multiple occurrences of the same non-spacing mark.</li>
+ * <li><code>CHAR_LIMIT</code>: flags strings that contain characters outside of a specified set of acceptable
+ * characters. See {@link uspoof_setAllowedChars} and {@link uspoof_setAllowedLocales}.</li>
+ * <li><code>MIXED_NUMBERS</code>: flags strings that contain digits from multiple different numbering systems.</li>
+ * </ul>
+ *
+ * <p>
+ * These checks can be enabled independently of each other. For example, if you were interested in checking for only the
+ * INVISIBLE and MIXED_NUMBERS conditions, you could do:
+ *
+ * \code{.c}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UChar* str = (UChar*) u"8\u09EA"; // 8 mixed with U+09EA BENGALI DIGIT FOUR
+ *
+ * USpoofChecker* sc = uspoof_open(&status);
+ * uspoof_setChecks(sc, USPOOF_INVISIBLE | USPOOF_MIXED_NUMBERS, &status);
+ *
+ * int32_t bitmask = uspoof_check2(sc, str, -1, NULL, &status);
+ * UBool result = bitmask != 0;
+ * // fails checks: 1 (status: U_ZERO_ERROR)
+ * printf("fails checks: %d (status: %s)\n", result, u_errorName(status));
+ * uspoof_close(sc);
+ * \endcode
+ *
+ * Here is an example in C++ showing how to compute the restriction level of a string:
+ *
+ * \code{.cpp}
+ * UErrorCode status = U_ZERO_ERROR;
+ * UnicodeString str((UChar*) u"p\u0430ypal"); // with U+0430 CYRILLIC SMALL LETTER A
+ *
+ * // Get the default set of allowable characters:
+ * UnicodeSet allowed;
+ * allowed.addAll(*uspoof_getRecommendedUnicodeSet(&status));
+ * allowed.addAll(*uspoof_getInclusionUnicodeSet(&status));
+ *
+ * LocalUSpoofCheckerPointer sc(uspoof_open(&status));
+ * uspoof_setAllowedChars(sc.getAlias(), allowed.toUSet(), &status);
+ * uspoof_setRestrictionLevel(sc.getAlias(), USPOOF_MODERATELY_RESTRICTIVE);
+ * uspoof_setChecks(sc.getAlias(), USPOOF_RESTRICTION_LEVEL | USPOOF_AUX_INFO, &status);
+ *
+ * LocalUSpoofCheckResultPointer checkResult(uspoof_openCheckResult(&status));
+ * int32_t bitmask = uspoof_check2UnicodeString(sc.getAlias(), str, checkResult.getAlias(), &status);
+ *
+ * URestrictionLevel restrictionLevel = uspoof_getCheckResultRestrictionLevel(checkResult.getAlias(), &status);
+ * // Since USPOOF_AUX_INFO was enabled, the restriction level is also available in the upper bits of the bitmask:
+ * assert((restrictionLevel & bitmask) == restrictionLevel);
+ * // Restriction level: 0x50000000 (status: U_ZERO_ERROR)
+ * printf("Restriction level: %#010x (status: %s)\n", restrictionLevel, u_errorName(status));
+ * \endcode
+ *
+ * The code '0x50000000' corresponds to the restriction level USPOOF_MINIMALLY_RESTRICTIVE. Since
+ * USPOOF_MINIMALLY_RESTRICTIVE is weaker than USPOOF_MODERATELY_RESTRICTIVE, the string fails the check.
+ *
+ * <b>Note:</b> The Restriction Level is the most powerful of the checks. The full logic is documented in
+ * <a href="http://unicode.org/reports/tr39/#Restriction_Level_Detection">UTS 39</a>, but the basic idea is that strings
+ * are restricted to contain characters from only a single script, <em>except</em> that most scripts are allowed to have
+ * Latin characters interspersed. Although the default restriction level is <code>HIGHLY_RESTRICTIVE</code>, it is
+ * recommended that users set their restriction level to <code>MODERATELY_RESTRICTIVE</code>, which allows Latin mixed
+ * with all other scripts except Cyrillic, Greek, and Cherokee, with which it is often confusable. For more details on
+ * the levels, see UTS 39 or {@link URestrictionLevel}. The Restriction Level test is aware of the set of
+ * allowed characters set in {@link uspoof_setAllowedChars}. Note that characters which have script code
+ * COMMON or INHERITED, such as numbers and punctuation, are ignored when computing whether a string has multiple
+ * scripts.
+ *
+ * <h2>Additional Information</h2>
+ *
+ * A <code>USpoofChecker</code> instance may be used repeatedly to perform checks on any number of identifiers.
+ *
+ * <b>Thread Safety:</b> The test functions for checking a single identifier, or for testing whether
+ * two identifiers are possible confusable, are thread safe. They may called concurrently, from multiple threads,
+ * using the same USpoofChecker instance.
+ *
+ * More generally, the standard ICU thread safety rules apply: functions that take a const USpoofChecker parameter are
+ * thread safe. Those that take a non-const USpoofChecker are not thread safe..
+ *
+ * @stable ICU 4.6
+ */
+
+U_CDECL_BEGIN
+
+struct USpoofChecker;
+/**
+ * @stable ICU 4.2
+ */
+typedef struct USpoofChecker USpoofChecker; /**< typedef for C of USpoofChecker */
+
+struct USpoofCheckResult;
+/**
+ * @see uspoof_openCheckResult
+ * @stable ICU 58
+ */
+typedef struct USpoofCheckResult USpoofCheckResult;
+
+/**
+ * Enum for the kinds of checks that USpoofChecker can perform.
+ * These enum values are used both to select the set of checks that
+ * will be performed, and to report results from the check function.
+ *
+ * @stable ICU 4.2
+ */
+typedef enum USpoofChecks {
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are from the same script, according to UTS 39 section
+ * 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_SINGLE_SCRIPT_CONFUSABLE = 1,
+
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are <b>not</b> from the same script, according to UTS
+ * 39 section 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_MIXED_SCRIPT_CONFUSABLE = 2,
+
+ /**
+ * When performing the two-string {@link uspoof_areConfusable} test, this flag in the return value indicates
+ * that the two strings are visually confusable and that they are not from the same script but both of them are
+ * single-script strings, according to UTS 39 section 4.
+ *
+ * @see uspoof_areConfusable
+ * @stable ICU 4.2
+ */
+ USPOOF_WHOLE_SCRIPT_CONFUSABLE = 4,
+
+ /**
+ * Enable this flag in {@link uspoof_setChecks} to turn on all types of confusables. You may set
+ * the checks to some subset of SINGLE_SCRIPT_CONFUSABLE, MIXED_SCRIPT_CONFUSABLE, or WHOLE_SCRIPT_CONFUSABLE to
+ * make {@link uspoof_areConfusable} return only those types of confusables.
+ *
+ * @see uspoof_areConfusable
+ * @see uspoof_getSkeleton
+ * @stable ICU 58
+ */
+ USPOOF_CONFUSABLE = USPOOF_SINGLE_SCRIPT_CONFUSABLE | USPOOF_MIXED_SCRIPT_CONFUSABLE | USPOOF_WHOLE_SCRIPT_CONFUSABLE,
+
+#ifndef U_HIDE_DEPRECATED_API
+ /**
+ * This flag is deprecated and no longer affects the behavior of SpoofChecker.
+ *
+ * @deprecated ICU 58 Any case confusable mappings were removed from UTS 39; the corresponding ICU API was deprecated.
+ */
+ USPOOF_ANY_CASE = 8,
+#endif /* U_HIDE_DEPRECATED_API */
+
+ /**
+ * Check that an identifier is no looser than the specified RestrictionLevel.
+ * The default if {@link uspoof_setRestrictionLevel} is not called is HIGHLY_RESTRICTIVE.
+ *
+ * If USPOOF_AUX_INFO is enabled the actual restriction level of the
+ * identifier being tested will also be returned by uspoof_check().
+ *
+ * @see URestrictionLevel
+ * @see uspoof_setRestrictionLevel
+ * @see USPOOF_AUX_INFO
+ *
+ * @stable ICU 51
+ */
+ USPOOF_RESTRICTION_LEVEL = 16,
+
+#ifndef U_HIDE_DEPRECATED_API
+ /** Check that an identifier contains only characters from a
+ * single script (plus chars from the common and inherited scripts.)
+ * Applies to checks of a single identifier check only.
+ * @deprecated ICU 51 Use RESTRICTION_LEVEL instead.
+ */
+ USPOOF_SINGLE_SCRIPT = USPOOF_RESTRICTION_LEVEL,
+#endif /* U_HIDE_DEPRECATED_API */
+
+ /** Check an identifier for the presence of invisible characters,
+ * such as zero-width spaces, or character sequences that are
+ * likely not to display, such as multiple occurrences of the same
+ * non-spacing mark. This check does not test the input string as a whole
+ * for conformance to any particular syntax for identifiers.
+ */
+ USPOOF_INVISIBLE = 32,
+
+ /** Check that an identifier contains only characters from a specified set
+ * of acceptable characters. See {@link uspoof_setAllowedChars} and
+ * {@link uspoof_setAllowedLocales}. Note that a string that fails this check
+ * will also fail the {@link USPOOF_RESTRICTION_LEVEL} check.
+ */
+ USPOOF_CHAR_LIMIT = 64,
+
+ /**
+ * Check that an identifier does not mix numbers from different numbering systems.
+ * For more information, see UTS 39 section 5.3.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MIXED_NUMBERS = 128,
+
+ /**
+ * Check that an identifier does not have a combining character following a character in which that
+ * combining character would be hidden; for example 'i' followed by a U+0307 combining dot.
+ *
+ * More specifically, the following characters are forbidden from preceding a U+0307:
+ * <ul>
+ * <li>Those with the Soft_Dotted Unicode property (which includes 'i' and 'j')</li>
+ * <li>Latin lowercase letter 'l'</li>
+ * <li>Dotless 'i' and 'j' ('ı' and 'ȷ', U+0131 and U+0237)</li>
+ * <li>Any character whose confusable prototype ends with such a character
+ * (Soft_Dotted, 'l', 'ı', or 'ȷ')</li>
+ * </ul>
+ * In addition, combining characters are allowed between the above characters and U+0307 except those
+ * with combining class 0 or combining class "Above" (230, same class as U+0307).
+ *
+ * This list and the number of combing characters considered by this check may grow over time.
+ *
+ * @stable ICU 62
+ */
+ USPOOF_HIDDEN_OVERLAY = 256,
+
+ /**
+ * Enable all spoof checks.
+ *
+ * @stable ICU 4.6
+ */
+ USPOOF_ALL_CHECKS = 0xFFFF,
+
+ /**
+ * Enable the return of auxiliary (non-error) information in the
+ * upper bits of the check results value.
+ *
+ * If this "check" is not enabled, the results of {@link uspoof_check} will be
+ * zero when an identifier passes all of the enabled checks.
+ *
+ * If this "check" is enabled, (uspoof_check() & {@link USPOOF_ALL_CHECKS}) will
+ * be zero when an identifier passes all checks.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_AUX_INFO = 0x40000000
+
+ } USpoofChecks;
+
+
+ /**
+ * Constants from UAX #39 for use in {@link uspoof_setRestrictionLevel}, and
+ * for returned identifier restriction levels in check results.
+ *
+ * @stable ICU 51
+ *
+ * @see uspoof_setRestrictionLevel
+ * @see uspoof_check
+ */
+ typedef enum URestrictionLevel {
+ /**
+ * All characters in the string are in the identifier profile and all characters in the string are in the
+ * ASCII range.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_ASCII = 0x10000000,
+ /**
+ * The string classifies as ASCII-Only, or all characters in the string are in the identifier profile and
+ * the string is single-script, according to the definition in UTS 39 section 5.1.
+ *
+ * @stable ICU 53
+ */
+ USPOOF_SINGLE_SCRIPT_RESTRICTIVE = 0x20000000,
+ /**
+ * The string classifies as Single Script, or all characters in the string are in the identifier profile and
+ * the string is covered by any of the following sets of scripts, according to the definition in UTS 39
+ * section 5.1:
+ * <ul>
+ * <li>Latin + Han + Bopomofo (or equivalently: Latn + Hanb)</li>
+ * <li>Latin + Han + Hiragana + Katakana (or equivalently: Latn + Jpan)</li>
+ * <li>Latin + Han + Hangul (or equivalently: Latn +Kore)</li>
+ * </ul>
+ * This is the default restriction in ICU.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_HIGHLY_RESTRICTIVE = 0x30000000,
+ /**
+ * The string classifies as Highly Restrictive, or all characters in the string are in the identifier profile
+ * and the string is covered by Latin and any one other Recommended or Aspirational script, except Cyrillic,
+ * Greek, and Cherokee.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MODERATELY_RESTRICTIVE = 0x40000000,
+ /**
+ * All characters in the string are in the identifier profile. Allow arbitrary mixtures of scripts.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_MINIMALLY_RESTRICTIVE = 0x50000000,
+ /**
+ * Any valid identifiers, including characters outside of the Identifier Profile.
+ *
+ * @stable ICU 51
+ */
+ USPOOF_UNRESTRICTIVE = 0x60000000,
+ /**
+ * Mask for selecting the Restriction Level bits from the return value of {@link uspoof_check}.
+ *
+ * @stable ICU 53
+ */
+ USPOOF_RESTRICTION_LEVEL_MASK = 0x7F000000,
+#ifndef U_HIDE_INTERNAL_API
+ /**
+ * An undefined restriction level.
+ * @internal
+ */
+ USPOOF_UNDEFINED_RESTRICTIVE = -1
+#endif /* U_HIDE_INTERNAL_API */
+ } URestrictionLevel;
+
+/**
+ * Create a Unicode Spoof Checker, configured to perform all
+ * checks except for USPOOF_LOCALE_LIMIT and USPOOF_CHAR_LIMIT.
+ * Note that additional checks may be added in the future,
+ * resulting in the changes to the default checking behavior.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @return the newly created Spoof Checker
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_open(UErrorCode *status);
+
+
+/**
+ * Open a Spoof checker from its serialized form, stored in 32-bit-aligned memory.
+ * Inverse of uspoof_serialize().
+ * The memory containing the serialized data must remain valid and unchanged
+ * as long as the spoof checker, or any cloned copies of the spoof checker,
+ * are in use. Ownership of the memory remains with the caller.
+ * The spoof checker (and any clones) must be closed prior to deleting the
+ * serialized data.
+ *
+ * @param data a pointer to 32-bit-aligned memory containing the serialized form of spoof data
+ * @param length the number of bytes available at data;
+ * can be more than necessary
+ * @param pActualLength receives the actual number of bytes at data taken up by the data;
+ * can be NULL
+ * @param pErrorCode ICU error code
+ * @return the spoof checker.
+ *
+ * @see uspoof_open
+ * @see uspoof_serialize
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength,
+ UErrorCode *pErrorCode);
+
+/**
+ * Open a Spoof Checker from the source form of the spoof data.
+ * The input corresponds to the Unicode data file confusables.txt
+ * as described in Unicode UAX #39. The syntax of the source data
+ * is as described in UAX #39 for this file, and the content of
+ * this file is acceptable input.
+ *
+ * The character encoding of the (char *) input text is UTF-8.
+ *
+ * @param confusables a pointer to the confusable characters definitions,
+ * as found in file confusables.txt from unicode.org.
+ * @param confusablesLen The length of the confusables text, or -1 if the
+ * input string is zero terminated.
+ * @param confusablesWholeScript
+ * Deprecated in ICU 58. No longer used.
+ * @param confusablesWholeScriptLen
+ * Deprecated in ICU 58. No longer used.
+ * @param errType In the event of an error in the input, indicates
+ * which of the input files contains the error.
+ * The value is one of USPOOF_SINGLE_SCRIPT_CONFUSABLE or
+ * USPOOF_WHOLE_SCRIPT_CONFUSABLE, or
+ * zero if no errors are found.
+ * @param pe In the event of an error in the input, receives the position
+ * in the input text (line, offset) of the error.
+ * @param status an in/out ICU UErrorCode. Among the possible errors is
+ * U_PARSE_ERROR, which is used to report syntax errors
+ * in the input.
+ * @return A spoof checker that uses the rules from the input files.
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSource(const char *confusables, int32_t confusablesLen,
+ const char *confusablesWholeScript, int32_t confusablesWholeScriptLen,
+ int32_t *errType, UParseError *pe, UErrorCode *status);
+
+
+/**
+ * Close a Spoof Checker, freeing any memory that was being held by
+ * its implementation.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_close(USpoofChecker *sc);
+
+/**
+ * Clone a Spoof Checker. The clone will be set to perform the same checks
+ * as the original source.
+ *
+ * @param sc The source USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return
+ * @stable ICU 4.2
+ */
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_clone(const USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Specify the bitmask of checks that will be performed by {@link uspoof_check}. Calling this method
+ * overwrites any checks that may have already been enabled. By default, all checks are enabled.
+ *
+ * To enable specific checks and disable all others,
+ * OR together only the bit constants for the desired checks.
+ * For example, to fail strings containing characters outside of
+ * the set specified by {@link uspoof_setAllowedChars} and
+ * also strings that contain digits from mixed numbering systems:
+ *
+ * <pre>
+ * {@code
+ * uspoof_setChecks(USPOOF_CHAR_LIMIT | USPOOF_MIXED_NUMBERS);
+ * }
+ * </pre>
+ *
+ * To disable specific checks and enable all others,
+ * start with ALL_CHECKS and "AND away" the not-desired checks.
+ * For example, if you are not planning to use the {@link uspoof_areConfusable} functionality,
+ * it is good practice to disable the CONFUSABLE check:
+ *
+ * <pre>
+ * {@code
+ * uspoof_setChecks(USPOOF_ALL_CHECKS & ~USPOOF_CONFUSABLE);
+ * }
+ * </pre>
+ *
+ * Note that methods such as {@link uspoof_setAllowedChars}, {@link uspoof_setAllowedLocales}, and
+ * {@link uspoof_setRestrictionLevel} will enable certain checks when called. Those methods will OR the check they
+ * enable onto the existing bitmask specified by this method. For more details, see the documentation of those
+ * methods.
+ *
+ * @param sc The USpoofChecker
+ * @param checks The set of checks that this spoof checker will perform.
+ * The value is a bit set, obtained by OR-ing together
+ * values from enum USpoofChecks.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ *
+ */
+U_CAPI void U_EXPORT2
+uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status);
+
+/**
+ * Get the set of checks that this Spoof Checker has been configured to perform.
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return The set of checks that this spoof checker will perform.
+ * The value is a bit set, obtained by OR-ing together
+ * values from enum USpoofChecks.
+ * @stable ICU 4.2
+ *
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status);
+
+/**
+ * Set the loosest restriction level allowed for strings. The default if this is not called is
+ * {@link USPOOF_HIGHLY_RESTRICTIVE}. Calling this method enables the {@link USPOOF_RESTRICTION_LEVEL} and
+ * {@link USPOOF_MIXED_NUMBERS} checks, corresponding to Sections 5.1 and 5.2 of UTS 39. To customize which checks are
+ * to be performed by {@link uspoof_check}, see {@link uspoof_setChecks}.
+ *
+ * @param sc The USpoofChecker
+ * @param restrictionLevel The loosest restriction level allowed.
+ * @see URestrictionLevel
+ * @stable ICU 51
+ */
+U_CAPI void U_EXPORT2
+uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel);
+
+
+/**
+ * Get the Restriction Level that will be tested if the checks include {@link USPOOF_RESTRICTION_LEVEL}.
+ *
+ * @return The restriction level
+ * @see URestrictionLevel
+ * @stable ICU 51
+ */
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getRestrictionLevel(const USpoofChecker *sc);
+
+/**
+ * Limit characters that are acceptable in identifiers being checked to those
+ * normally used with the languages associated with the specified locales.
+ * Any previously specified list of locales is replaced by the new settings.
+ *
+ * A set of languages is determined from the locale(s), and
+ * from those a set of acceptable Unicode scripts is determined.
+ * Characters from this set of scripts, along with characters from
+ * the "common" and "inherited" Unicode Script categories
+ * will be permitted.
+ *
+ * Supplying an empty string removes all restrictions;
+ * characters from any script will be allowed.
+ *
+ * The {@link USPOOF_CHAR_LIMIT} test is automatically enabled for this
+ * USpoofChecker when calling this function with a non-empty list
+ * of locales.
+ *
+ * The Unicode Set of characters that will be allowed is accessible
+ * via the uspoof_getAllowedChars() function. uspoof_setAllowedLocales()
+ * will <i>replace</i> any previously applied set of allowed characters.
+ *
+ * Adjustments, such as additions or deletions of certain classes of characters,
+ * can be made to the result of uspoof_setAllowedLocales() by
+ * fetching the resulting set with uspoof_getAllowedChars(),
+ * manipulating it with the Unicode Set API, then resetting the
+ * spoof detectors limits with uspoof_setAllowedChars().
+ *
+ * @param sc The USpoofChecker
+ * @param localesList A list list of locales, from which the language
+ * and associated script are extracted. The locales
+ * are comma-separated if there is more than one.
+ * White space may not appear within an individual locale,
+ * but is ignored otherwise.
+ * The locales are syntactically like those from the
+ * HTTP Accept-Language header.
+ * If the localesList is empty, no restrictions will be placed on
+ * the allowed characters.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status);
+
+/**
+ * Get a list of locales for the scripts that are acceptable in strings
+ * to be checked. If no limitations on scripts have been specified,
+ * an empty string will be returned.
+ *
+ * uspoof_setAllowedChars() will reset the list of allowed to be empty.
+ *
+ * The format of the returned list is the same as that supplied to
+ * uspoof_setAllowedLocales(), but returned list may not be identical
+ * to the originally specified string; the string may be reformatted,
+ * and information other than languages from
+ * the originally specified locales may be omitted.
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A string containing a list of locales corresponding
+ * to the acceptable scripts, formatted like an
+ * HTTP Accept Language value.
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI const char * U_EXPORT2
+uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Limit the acceptable characters to those specified by a Unicode Set.
+ * Any previously specified character limit is
+ * is replaced by the new settings. This includes limits on
+ * characters that were set with the uspoof_setAllowedLocales() function.
+ *
+ * The USPOOF_CHAR_LIMIT test is automatically enabled for this
+ * USpoofChecker by this function.
+ *
+ * @param sc The USpoofChecker
+ * @param chars A Unicode Set containing the list of
+ * characters that are permitted. Ownership of the set
+ * remains with the caller. The incoming set is cloned by
+ * this function, so there are no restrictions on modifying
+ * or deleting the USet after calling this function.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status);
+
+
+/**
+ * Get a USet for the characters permitted in an identifier.
+ * This corresponds to the limits imposed by the Set Allowed Characters
+ * functions. Limitations imposed by other checks will not be
+ * reflected in the set returned by this function.
+ *
+ * The returned set will be frozen, meaning that it cannot be modified
+ * by the caller.
+ *
+ * Ownership of the returned set remains with the Spoof Detector. The
+ * returned set will become invalid if the spoof detector is closed,
+ * or if a new set of allowed characters is specified.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A USet containing the characters that are permitted by
+ * the USPOOF_CHAR_LIMIT test.
+ * @stable ICU 4.2
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id The identifier to be checked for possible security issues,
+ * in UTF-16 format.
+ * @param length the length of the string to be checked, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * zero terminated.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check(const USpoofChecker *sc,
+ const UChar *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2UTF8}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues, in UTF8 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * If the input contains invalid UTF-8 sequences,
+ * a status of U_INVALID_CHAR_FOUND will be returned.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2UTF8
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status);
+
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * @param sc The USpoofChecker
+ * @param id The identifier to be checked for possible security issues,
+ * in UTF-16 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2UTF8
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2(const USpoofChecker *sc,
+ const UChar* id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * This version of {@link uspoof_check} accepts a USpoofCheckResult, which
+ * returns additional information about the identifier. For more
+ * information, see {@link uspoof_openCheckResult}.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues, in UTF8 format.
+ * @param length the length of the string to be checked, or -1 if the string is
+ * zero terminated.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * Create a USpoofCheckResult, used by the {@link uspoof_check2} class of functions to return
+ * information about the identifier. Information includes:
+ * <ul>
+ * <li>A bitmask of the checks that failed</li>
+ * <li>The identifier's restriction level (UTS 39 section 5.2)</li>
+ * <li>The set of numerics in the string (UTS 39 section 5.3)</li>
+ * </ul>
+ * The data held in a USpoofCheckResult is cleared whenever it is passed into a new call
+ * of {@link uspoof_check2}.
+ *
+ * @param status The error code, set if this function encounters a problem.
+ * @return the newly created USpoofCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UTF8
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 58
+ */
+U_CAPI USpoofCheckResult* U_EXPORT2
+uspoof_openCheckResult(UErrorCode *status);
+
+/**
+ * Close a USpoofCheckResult, freeing any memory that was being held by
+ * its implementation.
+ *
+ * @param checkResult The instance of USpoofCheckResult to close
+ * @stable ICU 58
+ */
+U_CAPI void U_EXPORT2
+uspoof_closeCheckResult(USpoofCheckResult *checkResult);
+
+/**
+ * Indicates which of the spoof check(s) have failed. The value is a bitwise OR of the constants for the tests
+ * in question: USPOOF_RESTRICTION_LEVEL, USPOOF_CHAR_LIMIT, and so on.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @param status The error code, set if an error occurred.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_setChecks
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+/**
+ * Gets the restriction level that the text meets, if the USPOOF_RESTRICTION_LEVEL check
+ * was enabled; otherwise, undefined.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @param status The error code, set if an error occurred.
+ * @return The restriction level contained in the USpoofCheckResult
+ * @see uspoof_setRestrictionLevel
+ * @stable ICU 58
+ */
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+/**
+ * Gets the set of numerics found in the string, if the USPOOF_MIXED_NUMBERS check was enabled;
+ * otherwise, undefined. The set will contain the zero digit from each decimal number system found
+ * in the input string. Ownership of the returned USet remains with the USpoofCheckResult.
+ * The USet will be free'd when {@link uspoof_closeCheckResult} is called.
+ *
+ * @param checkResult The instance of USpoofCheckResult created by {@link uspoof_openCheckResult}
+ * @return The set of numerics contained in the USpoofCheckResult
+ * @param status The error code, set if an error occurred.
+ * @stable ICU 58
+ */
+U_CAPI const USet* U_EXPORT2
+uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status);
+
+
+/**
+ * Check the whether two specified strings are visually confusable.
+ *
+ * If the strings are confusable, the return value will be nonzero, as long as
+ * {@link USPOOF_CONFUSABLE} was enabled in uspoof_setChecks().
+ *
+ * The bits in the return value correspond to flags for each of the classes of
+ * confusables applicable to the two input strings. According to UTS 39
+ * section 4, the possible flags are:
+ *
+ * <ul>
+ * <li>{@link USPOOF_SINGLE_SCRIPT_CONFUSABLE}</li>
+ * <li>{@link USPOOF_MIXED_SCRIPT_CONFUSABLE}</li>
+ * <li>{@link USPOOF_WHOLE_SCRIPT_CONFUSABLE}</li>
+ * </ul>
+ *
+ * If one or more of the above flags were not listed in uspoof_setChecks(), this
+ * function will never report that class of confusable. The check
+ * {@link USPOOF_CONFUSABLE} enables all three flags.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param id1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-16 format.
+ * @param length1 the length of the first identifier, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * nul terminated.
+ * @param id2 The second of the two identifiers to be compared for
+ * confusability. The identifiers are in UTF-16 format.
+ * @param length2 The length of the second identifiers, expressed in
+ * 16 bit UTF-16 code units, or -1 if the string is
+ * nul terminated.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the identifiers is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the identifiers
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusable(const USpoofChecker *sc,
+ const UChar *id1, int32_t length1,
+ const UChar *id2, int32_t length2,
+ UErrorCode *status);
+
+
+
+/**
+ * A version of {@link uspoof_areConfusable} accepting strings in UTF-8 format.
+ *
+ * @param sc The USpoofChecker
+ * @param id1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param length1 the length of the first identifiers, in bytes, or -1
+ * if the string is nul terminated.
+ * @param id2 The second of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param length2 The length of the second string in bytes, or -1
+ * if the string is nul terminated.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the strings is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the strings
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ *
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUTF8(const USpoofChecker *sc,
+ const char *id1, int32_t length1,
+ const char *id2, int32_t length2,
+ UErrorCode *status);
+
+
+
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The input identifier whose skeleton will be computed.
+ * @param length The length of the input identifier, expressed in 16 bit
+ * UTF-16 code units, or -1 if the string is zero terminated.
+ * @param dest The output buffer, to receive the skeleton string.
+ * @param destCapacity The length of the output buffer, in 16 bit units.
+ * The destCapacity may be zero, in which case the function will
+ * return the actual length of the skeleton.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * @return The length of the skeleton string. The returned length
+ * is always that of the complete skeleton, even when the
+ * supplied buffer is too small (or of zero length)
+ *
+ * @stable ICU 4.2
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeleton(const USpoofChecker *sc,
+ uint32_t type,
+ const UChar *id, int32_t length,
+ UChar *dest, int32_t destCapacity,
+ UErrorCode *status);
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The UTF-8 format identifier whose skeleton will be computed.
+ * @param length The length of the input string, in bytes,
+ * or -1 if the string is zero terminated.
+ * @param dest The output buffer, to receive the skeleton string.
+ * @param destCapacity The length of the output buffer, in bytes.
+ * The destCapacity may be zero, in which case the function will
+ * return the actual length of the skeleton.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check. Possible Errors include U_INVALID_CHAR_FOUND
+ * for invalid UTF-8 sequences, and
+ * U_BUFFER_OVERFLOW_ERROR if the destination buffer is too small
+ * to hold the complete skeleton.
+ * @return The length of the skeleton string, in bytes. The returned length
+ * is always that of the complete skeleton, even when the
+ * supplied buffer is too small (or of zero length)
+ *
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeletonUTF8(const USpoofChecker *sc,
+ uint32_t type,
+ const char *id, int32_t length,
+ char *dest, int32_t destCapacity,
+ UErrorCode *status);
+
+/**
+ * Get the set of Candidate Characters for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getInclusionSet(UErrorCode *status);
+
+/**
+ * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const USet * U_EXPORT2
+uspoof_getRecommendedSet(UErrorCode *status);
+
+/**
+ * Serialize the data for a spoof detector into a chunk of memory.
+ * The flattened spoof detection tables can later be used to efficiently
+ * instantiate a new Spoof Detector.
+ *
+ * The serialized spoof checker includes only the data compiled from the
+ * Unicode data tables by uspoof_openFromSource(); it does not include
+ * include any other state or configuration that may have been set.
+ *
+ * @param sc the Spoof Detector whose data is to be serialized.
+ * @param data a pointer to 32-bit-aligned memory to be filled with the data,
+ * can be NULL if capacity==0
+ * @param capacity the number of bytes available at data,
+ * or 0 for preflighting
+ * @param status an in/out ICU UErrorCode; possible errors include:
+ * - U_BUFFER_OVERFLOW_ERROR if the data storage block is too small for serialization
+ * - U_ILLEGAL_ARGUMENT_ERROR the data or capacity parameters are bad
+ * @return the number of bytes written or needed for the spoof data
+ *
+ * @see utrie2_openFromSerialized()
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_serialize(USpoofChecker *sc,
+ void *data, int32_t capacity,
+ UErrorCode *status);
+
+U_CDECL_END
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUSpoofCheckerPointer
+ * "Smart pointer" class, closes a USpoofChecker via uspoof_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+/**
+ * \cond
+ * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER.
+ * For now, suppress with a Doxygen cond
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckerPointer, USpoofChecker, uspoof_close);
+/** \endcond */
+
+/**
+ * \class LocalUSpoofCheckResultPointer
+ * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`.
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 58
+ */
+
+/**
+ * \cond
+ * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER.
+ * For now, suppress with a Doxygen cond
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult);
+/** \endcond */
+
+U_NAMESPACE_END
+
+/**
+ * Limit the acceptable characters to those specified by a Unicode Set.
+ * Any previously specified character limit is
+ * is replaced by the new settings. This includes limits on
+ * characters that were set with the uspoof_setAllowedLocales() function.
+ *
+ * The USPOOF_CHAR_LIMIT test is automatically enabled for this
+ * USoofChecker by this function.
+ *
+ * @param sc The USpoofChecker
+ * @param chars A Unicode Set containing the list of
+ * characters that are permitted. Ownership of the set
+ * remains with the caller. The incoming set is cloned by
+ * this function, so there are no restrictions on modifying
+ * or deleting the UnicodeSet after calling this function.
+ * @param status The error code, set if this function encounters a problem.
+ * @stable ICU 4.2
+ */
+U_CAPI void U_EXPORT2
+uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const icu::UnicodeSet *chars, UErrorCode *status);
+
+
+/**
+ * Get a UnicodeSet for the characters permitted in an identifier.
+ * This corresponds to the limits imposed by the Set Allowed Characters /
+ * UnicodeSet functions. Limitations imposed by other checks will not be
+ * reflected in the set returned by this function.
+ *
+ * The returned set will be frozen, meaning that it cannot be modified
+ * by the caller.
+ *
+ * Ownership of the returned set remains with the Spoof Detector. The
+ * returned set will become invalid if the spoof detector is closed,
+ * or if a new set of allowed characters is specified.
+ *
+ *
+ * @param sc The USpoofChecker
+ * @param status The error code, set if this function encounters a problem.
+ * @return A UnicodeSet containing the characters that are permitted by
+ * the USPOOF_CHAR_LIMIT test.
+ * @stable ICU 4.2
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * \note
+ * Consider using the newer API, {@link uspoof_check2UnicodeString}, instead.
+ * The newer API exposes additional information from the check procedure
+ * and is otherwise identical to this method.
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues.
+ * @param position Deprecated in ICU 51. Always returns zero.
+ * Originally, an out parameter for the index of the first
+ * string position that failed a check.
+ * This parameter may be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks.
+ * @see uspoof_check2UnicodeString
+ * @stable ICU 4.2
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ int32_t *position,
+ UErrorCode *status);
+
+/**
+ * Check the specified string for possible security issues.
+ * The text to be checked will typically be an identifier of some sort.
+ * The set of checks to be performed is specified with uspoof_setChecks().
+ *
+ * @param sc The USpoofChecker
+ * @param id A identifier to be checked for possible security issues.
+ * @param checkResult An instance of USpoofCheckResult to be filled with
+ * details about the identifier. Can be NULL.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Spoofing or security issues detected with the input string are
+ * not reported here, but through the function's return value.
+ * @return An integer value with bits set for any potential security
+ * or spoofing issues detected. The bits are defined by
+ * enum USpoofChecks. (returned_value & USPOOF_ALL_CHECKS)
+ * will be zero if the input string passes all of the
+ * enabled checks. Any information in this bitmask will be
+ * consistent with the information saved in the optional
+ * checkResult parameter.
+ * @see uspoof_openCheckResult
+ * @see uspoof_check2
+ * @see uspoof_check2UTF8
+ * @stable ICU 58
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status);
+
+/**
+ * A version of {@link uspoof_areConfusable} accepting UnicodeStrings.
+ *
+ * @param sc The USpoofChecker
+ * @param s1 The first of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param s2 The second of the two identifiers to be compared for
+ * confusability. The strings are in UTF-8 format.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * Confusability of the identifiers is not reported here,
+ * but through this function's return value.
+ * @return An integer value with bit(s) set corresponding to
+ * the type of confusability found, as defined by
+ * enum USpoofChecks. Zero is returned if the identifiers
+ * are not confusable.
+ *
+ * @stable ICU 4.2
+ *
+ * @see uspoof_areConfusable
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &s1,
+ const icu::UnicodeString &s2,
+ UErrorCode *status);
+
+/**
+ * Get the "skeleton" for an identifier.
+ * Skeletons are a transformation of the input identifier;
+ * Two identifiers are confusable if their skeletons are identical.
+ * See Unicode UAX #39 for additional information.
+ *
+ * Using skeletons directly makes it possible to quickly check
+ * whether an identifier is confusable with any of some large
+ * set of existing identifiers, by creating an efficiently
+ * searchable collection of the skeletons.
+ *
+ * @param sc The USpoofChecker.
+ * @param type Deprecated in ICU 58. You may pass any number.
+ * Originally, controlled which of the Unicode confusable data
+ * tables to use.
+ * @param id The input identifier whose skeleton will be computed.
+ * @param dest The output identifier, to receive the skeleton string.
+ * @param status The error code, set if an error occurred while attempting to
+ * perform the check.
+ * @return A reference to the destination (skeleton) string.
+ *
+ * @stable ICU 4.2
+ */
+U_I18N_API icu::UnicodeString & U_EXPORT2
+uspoof_getSkeletonUnicodeString(const USpoofChecker *sc,
+ uint32_t type,
+ const icu::UnicodeString &id,
+ icu::UnicodeString &dest,
+ UErrorCode *status);
+
+/**
+ * Get the set of Candidate Characters for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getInclusionUnicodeSet(UErrorCode *status);
+
+/**
+ * Get the set of characters from Recommended Scripts for Inclusion in Identifiers, as defined
+ * in http://unicode.org/Public/security/latest/xidmodifications.txt
+ * and documented in http://www.unicode.org/reports/tr39/, Unicode Security Mechanisms.
+ *
+ * The returned set is frozen. Ownership of the set remains with the ICU library; it must not
+ * be deleted by the caller.
+ *
+ * @param status The error code, set if a problem occurs while creating the set.
+ *
+ * @stable ICU 51
+ */
+U_CAPI const icu::UnicodeSet * U_EXPORT2
+uspoof_getRecommendedUnicodeSet(UErrorCode *status);
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
+#endif /* UCONFIG_NO_NORMALIZATION */
+
+#endif /* USPOOF_H */
diff --git a/thirdparty/icu4c/i18n/uspoof.cpp b/thirdparty/icu4c/i18n/uspoof.cpp
new file mode 100644
index 0000000000..dd4618baa7
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof.cpp
@@ -0,0 +1,839 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2015, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+* file name: uspoof.cpp
+* encoding: UTF-8
+* tab size: 8 (not used)
+* indentation:4
+*
+* created on: 2008Feb13
+* created by: Andy Heninger
+*
+* Unicode Spoof Detection
+*/
+#include "unicode/utypes.h"
+#include "unicode/normalizer2.h"
+#include "unicode/uspoof.h"
+#include "unicode/ustring.h"
+#include "unicode/utf16.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "mutex.h"
+#include "scriptset.h"
+#include "uassert.h"
+#include "ucln_in.h"
+#include "uspoof_impl.h"
+#include "umutex.h"
+
+
+#if !UCONFIG_NO_NORMALIZATION
+
+U_NAMESPACE_USE
+
+
+//
+// Static Objects used by the spoof impl, their thread safe initialization and their cleanup.
+//
+static UnicodeSet *gInclusionSet = NULL;
+static UnicodeSet *gRecommendedSet = NULL;
+static const Normalizer2 *gNfdNormalizer = NULL;
+static UInitOnce gSpoofInitStaticsOnce = U_INITONCE_INITIALIZER;
+
+namespace {
+
+UBool U_CALLCONV
+uspoof_cleanup(void) {
+ delete gInclusionSet;
+ gInclusionSet = NULL;
+ delete gRecommendedSet;
+ gRecommendedSet = NULL;
+ gNfdNormalizer = NULL;
+ gSpoofInitStaticsOnce.reset();
+ return TRUE;
+}
+
+void U_CALLCONV initializeStatics(UErrorCode &status) {
+ static const char16_t *inclusionPat =
+ u"['\\-.\\:\\u00B7\\u0375\\u058A\\u05F3\\u05F4\\u06FD\\u06FE\\u0F0B\\u200C"
+ u"\\u200D\\u2010\\u2019\\u2027\\u30A0\\u30FB]";
+ gInclusionSet = new UnicodeSet(UnicodeString(inclusionPat), status);
+ if (gInclusionSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ gInclusionSet->freeze();
+
+ // Note: data from IdentifierStatus.txt & IdentifierType.txt
+ // There is tooling to generate this constant in the unicodetools project:
+ // org.unicode.text.tools.RecommendedSetGenerator
+ // It will print the Java and C++ code to the console for easy copy-paste into this file.
+ static const char16_t *recommendedPat =
+ u"[0-9A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u0131\\u0134-\\u013E"
+ u"\\u0141-\\u0148\\u014A-\\u017E\\u018F\\u01A0\\u01A1\\u01AF\\u01B0\\u01CD-"
+ u"\\u01DC\\u01DE-\\u01E3\\u01E6-\\u01F0\\u01F4\\u01F5\\u01F8-\\u021B\\u021E"
+ u"\\u021F\\u0226-\\u0233\\u0259\\u02BB\\u02BC\\u02EC\\u0300-\\u0304\\u0306-"
+ u"\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u0328\\u032D\\u032E"
+ u"\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386"
+ u"\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-"
+ u"\\u04FF\\u0510-\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0586"
+ u"\\u05B4\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-"
+ u"\\u0669\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06A0\\u06A2-\\u06D3"
+ u"\\u06D5\\u06E5\\u06E6\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u0870-\\u0887"
+ u"\\u0889-\\u088E\\u08A0-\\u08AC\\u08B2\\u08B5-\\u08C9\\u0901-\\u094D\\u094F"
+ u"\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096F\\u0971-\\u0977\\u0979-"
+ u"\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-"
+ u"\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE"
+ u"\\u09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u09FE\\u0A01-\\u0A03\\u0A05-\\u0A0A"
+ u"\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A35\\u0A38\\u0A39"
+ u"\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A5C\\u0A66-\\u0A74"
+ u"\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0"
+ u"\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD"
+ u"\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0AFA-\\u0AFF\\u0B01-\\u0B03\\u0B05-"
+ u"\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-"
+ u"\\u0B39\\u0B3C-\\u0B43\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B55-\\u0B57\\u0B5F-"
+ u"\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90"
+ u"\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-"
+ u"\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0"
+ u"\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-"
+ u"\\u0C33\\u0C35-\\u0C39\\u0C3C-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55"
+ u"\\u0C56\\u0C5D\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80\\u0C82\\u0C83\\u0C85-"
+ u"\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-"
+ u"\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDD\\u0CE0-\\u0CE3"
+ u"\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02\\u0D03\\u0D05-\\u0D0C\\u0D0E-"
+ u"\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-"
+ u"\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-"
+ u"\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD"
+ u"\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-"
+ u"\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84"
+ u"\\u0E86-\\u0E8A\\u0E8C-\\u0EA3\\u0EA5\\u0EA7-\\u0EB2\\u0EB4-\\u0EBD\\u0EC0-"
+ u"\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00\\u0F20-"
+ u"\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C\\u0F4E-"
+ u"\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C\\u0F71"
+ u"\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84\\u0F86-\\u0F92\\u0F94-\\u0F97"
+ u"\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8"
+ u"\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10C7\\u10CD\\u10D0-"
+ u"\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D\\u1250-"
+ u"\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0"
+ u"\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-"
+ u"\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u1780-"
+ u"\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-\\u17CD\\u17D0\\u17D2\\u17D7"
+ u"\\u17DC\\u17E0-\\u17E9\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1E00-\\u1E99\\u1E9E"
+ u"\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D"
+ u"\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72\\u1F74\\u1F76"
+ u"\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC\\u1FC2-\\u1FC4"
+ u"\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-\\u1FDA\\u1FE0-\\u1FE2"
+ u"\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8\\u1FFA\\u1FFC\\u2D27"
+ u"\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-"
+ u"\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u3005-"
+ u"\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-\\u30FA\\u30FC-"
+ u"\\u30FE\\u3105-\\u312D\\u312F\\u31A0-\\u31BF\\u3400-\\u4DBF\\u4E00-\\u9FFF"
+ u"\\uA67F\\uA717-\\uA71F\\uA788\\uA78D\\uA792\\uA793\\uA7AA\\uA7AE\\uA7B8"
+ u"\\uA7B9\\uA7C0-\\uA7CA\\uA7D0\\uA7D1\\uA7D3\\uA7D5-\\uA7D9\\uA9E7-\\uA9FE"
+ u"\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16"
+ u"\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB66\\uAB67\\uAC00-\\uD7A3\\uFA0E\\uFA0F"
+ u"\\uFA11\\uFA13\\uFA14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29\\U00011301"
+ u"\\U00011303\\U0001133B\\U0001133C\\U00016FF0\\U00016FF1\\U0001B11F-"
+ u"\\U0001B122\\U0001B150-\\U0001B152\\U0001B164-\\U0001B167\\U0001DF00-"
+ u"\\U0001DF1E\\U0001E7E0-\\U0001E7E6\\U0001E7E8-\\U0001E7EB\\U0001E7ED"
+ u"\\U0001E7EE\\U0001E7F0-\\U0001E7FE\\U00020000-\\U0002A6DF\\U0002A700-"
+ u"\\U0002B738\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-"
+ u"\\U0002EBE0\\U00030000-\\U0003134A]";
+
+ gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status);
+ if (gRecommendedSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ delete gInclusionSet;
+ return;
+ }
+ gRecommendedSet->freeze();
+ gNfdNormalizer = Normalizer2::getNFDInstance(status);
+ ucln_i18n_registerCleanup(UCLN_I18N_SPOOF, uspoof_cleanup);
+}
+
+} // namespace
+
+U_CFUNC void uspoof_internalInitStatics(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+}
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_open(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ if (U_FAILURE(*status)) {
+ return NULL;
+ }
+ SpoofImpl *si = new SpoofImpl(*status);
+ if (si == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(*status)) {
+ delete si;
+ return NULL;
+ }
+ return si->asUSpoofChecker();
+}
+
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLength,
+ UErrorCode *status) {
+ if (U_FAILURE(*status)) {
+ return NULL;
+ }
+
+ if (data == NULL) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return NULL;
+ }
+
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ if (U_FAILURE(*status))
+ {
+ return NULL;
+ }
+
+ SpoofData *sd = new SpoofData(data, length, *status);
+ if (sd == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+
+ if (U_FAILURE(*status)) {
+ delete sd;
+ return NULL;
+ }
+
+ SpoofImpl *si = new SpoofImpl(sd, *status);
+ if (si == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ delete sd; // explicit delete as the destructor for si won't be called.
+ return NULL;
+ }
+
+ if (U_FAILURE(*status)) {
+ delete si; // no delete for sd, as the si destructor will delete it.
+ return NULL;
+ }
+
+ if (pActualLength != NULL) {
+ *pActualLength = sd->size();
+ }
+ return si->asUSpoofChecker();
+}
+
+
+U_CAPI USpoofChecker * U_EXPORT2
+uspoof_clone(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *src = SpoofImpl::validateThis(sc, *status);
+ if (src == NULL) {
+ return NULL;
+ }
+ SpoofImpl *result = new SpoofImpl(*src, *status); // copy constructor
+ if (result == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(*status)) {
+ delete result;
+ result = NULL;
+ }
+ return result->asUSpoofChecker();
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_close(USpoofChecker *sc) {
+ UErrorCode status = U_ZERO_ERROR;
+ SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ delete This;
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setChecks(USpoofChecker *sc, int32_t checks, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+
+ // Verify that the requested checks are all ones (bits) that
+ // are acceptable, known values.
+ if (checks & ~(USPOOF_ALL_CHECKS | USPOOF_AUX_INFO)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ This->fChecks = checks;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getChecks(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return 0;
+ }
+ return This->fChecks;
+}
+
+U_CAPI void U_EXPORT2
+uspoof_setRestrictionLevel(USpoofChecker *sc, URestrictionLevel restrictionLevel) {
+ UErrorCode status = U_ZERO_ERROR;
+ SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ if (This != NULL) {
+ This->fRestrictionLevel = restrictionLevel;
+ This->fChecks |= USPOOF_RESTRICTION_LEVEL;
+ }
+}
+
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getRestrictionLevel(const USpoofChecker *sc) {
+ UErrorCode status = U_ZERO_ERROR;
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, status);
+ if (This == NULL) {
+ return USPOOF_UNRESTRICTIVE;
+ }
+ return This->fRestrictionLevel;
+}
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedLocales(USpoofChecker *sc, const char *localesList, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+ This->setAllowedLocales(localesList, *status);
+}
+
+U_CAPI const char * U_EXPORT2
+uspoof_getAllowedLocales(USpoofChecker *sc, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return NULL;
+ }
+ return This->getAllowedLocales(*status);
+}
+
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getAllowedChars(const USpoofChecker *sc, UErrorCode *status) {
+ const UnicodeSet *result = uspoof_getAllowedUnicodeSet(sc, status);
+ return result->toUSet();
+}
+
+U_CAPI const UnicodeSet * U_EXPORT2
+uspoof_getAllowedUnicodeSet(const USpoofChecker *sc, UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return NULL;
+ }
+ return This->fAllowedCharsSet;
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedChars(USpoofChecker *sc, const USet *chars, UErrorCode *status) {
+ const UnicodeSet *set = UnicodeSet::fromUSet(chars);
+ uspoof_setAllowedUnicodeSet(sc, set, status);
+}
+
+
+U_CAPI void U_EXPORT2
+uspoof_setAllowedUnicodeSet(USpoofChecker *sc, const UnicodeSet *chars, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return;
+ }
+ if (chars->isBogus()) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ UnicodeSet *clonedSet = chars->clone();
+ if (clonedSet == NULL || clonedSet->isBogus()) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ clonedSet->freeze();
+ delete This->fAllowedCharsSet;
+ This->fAllowedCharsSet = clonedSet;
+ This->fChecks |= USPOOF_CHAR_LIMIT;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check(const USpoofChecker *sc,
+ const UChar *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2(sc, id, length, NULL, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2(const USpoofChecker *sc,
+ const UChar* id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return 0;
+ }
+ if (length < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ UnicodeString idStr((length == -1), id, length); // Aliasing constructor.
+ int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status);
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2UTF8(sc, id, length, NULL, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UTF8(const USpoofChecker *sc,
+ const char *id, int32_t length,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ UnicodeString idStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id))));
+ int32_t result = uspoof_check2UnicodeString(sc, idStr, checkResult, status);
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusable(const USpoofChecker *sc,
+ const UChar *id1, int32_t length1,
+ const UChar *id2, int32_t length2,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length1 < -1 || length2 < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString id1Str((length1==-1), id1, length1); // Aliasing constructor
+ UnicodeString id2Str((length2==-1), id2, length2); // Aliasing constructor
+ return uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status);
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUTF8(const USpoofChecker *sc,
+ const char *id1, int32_t length1,
+ const char *id2, int32_t length2,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length1 < -1 || length2 < -1) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+ UnicodeString id1Str = UnicodeString::fromUTF8(StringPiece(id1, length1>=0? length1 : static_cast<int32_t>(uprv_strlen(id1))));
+ UnicodeString id2Str = UnicodeString::fromUTF8(StringPiece(id2, length2>=0? length2 : static_cast<int32_t>(uprv_strlen(id2))));
+ int32_t results = uspoof_areConfusableUnicodeString(sc, id1Str, id2Str, status);
+ return results;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_areConfusableUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id1,
+ const icu::UnicodeString &id2,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ //
+ // See section 4 of UAX 39 for the algorithm for checking whether two strings are confusable,
+ // and for definitions of the types (single, whole, mixed-script) of confusables.
+
+ // We only care about a few of the check flags. Ignore the others.
+ // If no tests relevant to this function have been specified, return an error.
+ // TODO: is this really the right thing to do? It's probably an error on the caller's part,
+ // but logically we would just return 0 (no error).
+ if ((This->fChecks & USPOOF_CONFUSABLE) == 0) {
+ *status = U_INVALID_STATE_ERROR;
+ return 0;
+ }
+
+ // Compute the skeletons and check for confusability.
+ UnicodeString id1Skeleton;
+ uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id1, id1Skeleton, status);
+ UnicodeString id2Skeleton;
+ uspoof_getSkeletonUnicodeString(sc, 0 /* deprecated */, id2, id2Skeleton, status);
+ if (U_FAILURE(*status)) { return 0; }
+ if (id1Skeleton != id2Skeleton) {
+ return 0;
+ }
+
+ // If we get here, the strings are confusable. Now we just need to set the flags for the appropriate classes
+ // of confusables according to UTS 39 section 4.
+ // Start by computing the resolved script sets of id1 and id2.
+ ScriptSet id1RSS;
+ This->getResolvedScriptSet(id1, id1RSS, *status);
+ ScriptSet id2RSS;
+ This->getResolvedScriptSet(id2, id2RSS, *status);
+
+ // Turn on all applicable flags
+ int32_t result = 0;
+ if (id1RSS.intersects(id2RSS)) {
+ result |= USPOOF_SINGLE_SCRIPT_CONFUSABLE;
+ } else {
+ result |= USPOOF_MIXED_SCRIPT_CONFUSABLE;
+ if (!id1RSS.isEmpty() && !id2RSS.isEmpty()) {
+ result |= USPOOF_WHOLE_SCRIPT_CONFUSABLE;
+ }
+ }
+
+ // Turn off flags that the user doesn't want
+ if ((This->fChecks & USPOOF_SINGLE_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_SINGLE_SCRIPT_CONFUSABLE;
+ }
+ if ((This->fChecks & USPOOF_MIXED_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_MIXED_SCRIPT_CONFUSABLE;
+ }
+ if ((This->fChecks & USPOOF_WHOLE_SCRIPT_CONFUSABLE) == 0) {
+ result &= ~USPOOF_WHOLE_SCRIPT_CONFUSABLE;
+ }
+
+ return result;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_checkUnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ int32_t *position,
+ UErrorCode *status) {
+
+ // Backwards compatibility:
+ if (position != NULL) {
+ *position = 0;
+ }
+
+ // Delegate to uspoof_check2
+ return uspoof_check2UnicodeString(sc, id, NULL, status);
+}
+
+namespace {
+
+int32_t checkImpl(const SpoofImpl* This, const UnicodeString& id, CheckResult* checkResult, UErrorCode* status) {
+ U_ASSERT(This != NULL);
+ U_ASSERT(checkResult != NULL);
+ checkResult->clear();
+ int32_t result = 0;
+
+ if (0 != (This->fChecks & USPOOF_RESTRICTION_LEVEL)) {
+ URestrictionLevel idRestrictionLevel = This->getRestrictionLevel(id, *status);
+ if (idRestrictionLevel > This->fRestrictionLevel) {
+ result |= USPOOF_RESTRICTION_LEVEL;
+ }
+ checkResult->fRestrictionLevel = idRestrictionLevel;
+ }
+
+ if (0 != (This->fChecks & USPOOF_MIXED_NUMBERS)) {
+ UnicodeSet numerics;
+ This->getNumerics(id, numerics, *status);
+ if (numerics.size() > 1) {
+ result |= USPOOF_MIXED_NUMBERS;
+ }
+ checkResult->fNumerics = numerics; // UnicodeSet::operator=
+ }
+
+ if (0 != (This->fChecks & USPOOF_HIDDEN_OVERLAY)) {
+ int32_t index = This->findHiddenOverlay(id, *status);
+ if (index != -1) {
+ result |= USPOOF_HIDDEN_OVERLAY;
+ }
+ }
+
+
+ if (0 != (This->fChecks & USPOOF_CHAR_LIMIT)) {
+ int32_t i;
+ UChar32 c;
+ int32_t length = id.length();
+ for (i=0; i<length ;) {
+ c = id.char32At(i);
+ i += U16_LENGTH(c);
+ if (!This->fAllowedCharsSet->contains(c)) {
+ result |= USPOOF_CHAR_LIMIT;
+ break;
+ }
+ }
+ }
+
+ if (0 != (This->fChecks & USPOOF_INVISIBLE)) {
+ // This check needs to be done on NFD input
+ UnicodeString nfdText;
+ gNfdNormalizer->normalize(id, nfdText, *status);
+ int32_t nfdLength = nfdText.length();
+
+ // scan for more than one occurrence of the same non-spacing mark
+ // in a sequence of non-spacing marks.
+ int32_t i;
+ UChar32 c;
+ UChar32 firstNonspacingMark = 0;
+ UBool haveMultipleMarks = FALSE;
+ UnicodeSet marksSeenSoFar; // Set of combining marks in a single combining sequence.
+
+ for (i=0; i<nfdLength ;) {
+ c = nfdText.char32At(i);
+ i += U16_LENGTH(c);
+ if (u_charType(c) != U_NON_SPACING_MARK) {
+ firstNonspacingMark = 0;
+ if (haveMultipleMarks) {
+ marksSeenSoFar.clear();
+ haveMultipleMarks = FALSE;
+ }
+ continue;
+ }
+ if (firstNonspacingMark == 0) {
+ firstNonspacingMark = c;
+ continue;
+ }
+ if (!haveMultipleMarks) {
+ marksSeenSoFar.add(firstNonspacingMark);
+ haveMultipleMarks = TRUE;
+ }
+ if (marksSeenSoFar.contains(c)) {
+ // report the error, and stop scanning.
+ // No need to find more than the first failure.
+ result |= USPOOF_INVISIBLE;
+ break;
+ }
+ marksSeenSoFar.add(c);
+ }
+ }
+
+ checkResult->fChecks = result;
+ return checkResult->toCombinedBitmask(This->fChecks);
+}
+
+} // namespace
+
+U_CAPI int32_t U_EXPORT2
+uspoof_check2UnicodeString(const USpoofChecker *sc,
+ const icu::UnicodeString &id,
+ USpoofCheckResult* checkResult,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ return FALSE;
+ }
+
+ if (checkResult != NULL) {
+ CheckResult* ThisCheckResult = CheckResult::validateThis(checkResult, *status);
+ if (ThisCheckResult == NULL) {
+ return FALSE;
+ }
+ return checkImpl(This, id, ThisCheckResult, status);
+ } else {
+ // Stack-allocate the checkResult since this method doesn't return it
+ CheckResult stackCheckResult;
+ return checkImpl(This, id, &stackCheckResult, status);
+ }
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeleton(const USpoofChecker *sc,
+ uint32_t type,
+ const UChar *id, int32_t length,
+ UChar *dest, int32_t destCapacity,
+ UErrorCode *status) {
+
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString idStr((length==-1), id, length); // Aliasing constructor
+ UnicodeString destStr;
+ uspoof_getSkeletonUnicodeString(sc, type, idStr, destStr, status);
+ destStr.extract(dest, destCapacity, *status);
+ return destStr.length();
+}
+
+
+
+U_I18N_API UnicodeString & U_EXPORT2
+uspoof_getSkeletonUnicodeString(const USpoofChecker *sc,
+ uint32_t /*type*/,
+ const UnicodeString &id,
+ UnicodeString &dest,
+ UErrorCode *status) {
+ const SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return dest;
+ }
+
+ UnicodeString nfdId;
+ gNfdNormalizer->normalize(id, nfdId, *status);
+
+ // Apply the skeleton mapping to the NFD normalized input string
+ // Accumulate the skeleton, possibly unnormalized, in a UnicodeString.
+ int32_t inputIndex = 0;
+ UnicodeString skelStr;
+ int32_t normalizedLen = nfdId.length();
+ for (inputIndex=0; inputIndex < normalizedLen; ) {
+ UChar32 c = nfdId.char32At(inputIndex);
+ inputIndex += U16_LENGTH(c);
+ This->fSpoofData->confusableLookup(c, skelStr);
+ }
+
+ gNfdNormalizer->normalize(skelStr, dest, *status);
+ return dest;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getSkeletonUTF8(const USpoofChecker *sc,
+ uint32_t type,
+ const char *id, int32_t length,
+ char *dest, int32_t destCapacity,
+ UErrorCode *status) {
+ SpoofImpl::validateThis(sc, *status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (length<-1 || destCapacity<0 || (destCapacity==0 && dest!=NULL)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ UnicodeString srcStr = UnicodeString::fromUTF8(StringPiece(id, length>=0 ? length : static_cast<int32_t>(uprv_strlen(id))));
+ UnicodeString destStr;
+ uspoof_getSkeletonUnicodeString(sc, type, srcStr, destStr, status);
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+
+ int32_t lengthInUTF8 = 0;
+ u_strToUTF8(dest, destCapacity, &lengthInUTF8,
+ destStr.getBuffer(), destStr.length(), status);
+ return lengthInUTF8;
+}
+
+
+U_CAPI int32_t U_EXPORT2
+uspoof_serialize(USpoofChecker *sc,void *buf, int32_t capacity, UErrorCode *status) {
+ SpoofImpl *This = SpoofImpl::validateThis(sc, *status);
+ if (This == NULL) {
+ U_ASSERT(U_FAILURE(*status));
+ return 0;
+ }
+
+ return This->fSpoofData->serialize(buf, capacity, *status);
+}
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getInclusionSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gInclusionSet->toUSet();
+}
+
+U_CAPI const USet * U_EXPORT2
+uspoof_getRecommendedSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gRecommendedSet->toUSet();
+}
+
+U_I18N_API const UnicodeSet * U_EXPORT2
+uspoof_getInclusionUnicodeSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gInclusionSet;
+}
+
+U_I18N_API const UnicodeSet * U_EXPORT2
+uspoof_getRecommendedUnicodeSet(UErrorCode *status) {
+ umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status);
+ return gRecommendedSet;
+}
+
+//------------------
+// CheckResult APIs
+//------------------
+
+U_CAPI USpoofCheckResult* U_EXPORT2
+uspoof_openCheckResult(UErrorCode *status) {
+ CheckResult* checkResult = new CheckResult();
+ if (checkResult == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ return checkResult->asUSpoofCheckResult();
+}
+
+U_CAPI void U_EXPORT2
+uspoof_closeCheckResult(USpoofCheckResult* checkResult) {
+ UErrorCode status = U_ZERO_ERROR;
+ CheckResult* This = CheckResult::validateThis(checkResult, status);
+ delete This;
+}
+
+U_CAPI int32_t U_EXPORT2
+uspoof_getCheckResultChecks(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return 0; }
+ return This->fChecks;
+}
+
+U_CAPI URestrictionLevel U_EXPORT2
+uspoof_getCheckResultRestrictionLevel(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return USPOOF_UNRESTRICTIVE; }
+ return This->fRestrictionLevel;
+}
+
+U_CAPI const USet* U_EXPORT2
+uspoof_getCheckResultNumerics(const USpoofCheckResult *checkResult, UErrorCode *status) {
+ const CheckResult* This = CheckResult::validateThis(checkResult, *status);
+ if (U_FAILURE(*status)) { return NULL; }
+ return This->fNumerics.toUSet();
+}
+
+
+
+#endif // !UCONFIG_NO_NORMALIZATION
diff --git a/thirdparty/icu4c/i18n/uspoof_impl.cpp b/thirdparty/icu4c/i18n/uspoof_impl.cpp
new file mode 100644
index 0000000000..b283d81321
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof_impl.cpp
@@ -0,0 +1,959 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+**********************************************************************
+* Copyright (C) 2008-2016, International Business Machines
+* Corporation and others. All Rights Reserved.
+**********************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "unicode/uspoof.h"
+#include "unicode/uchar.h"
+#include "unicode/uniset.h"
+#include "unicode/utf16.h"
+#include "utrie2.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "scriptset.h"
+#include "umutex.h"
+#include "udataswp.h"
+#include "uassert.h"
+#include "ucln_in.h"
+#include "uspoof_impl.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+
+U_NAMESPACE_BEGIN
+
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SpoofImpl)
+
+SpoofImpl::SpoofImpl(SpoofData *data, UErrorCode& status) {
+ construct(status);
+ fSpoofData = data;
+}
+
+SpoofImpl::SpoofImpl(UErrorCode& status) {
+ construct(status);
+
+ // TODO: Call this method where it is actually needed, instead of in the
+ // constructor, to allow for lazy data loading. See #12696.
+ fSpoofData = SpoofData::getDefault(status);
+}
+
+SpoofImpl::SpoofImpl() {
+ UErrorCode status = U_ZERO_ERROR;
+ construct(status);
+
+ // TODO: Call this method where it is actually needed, instead of in the
+ // constructor, to allow for lazy data loading. See #12696.
+ fSpoofData = SpoofData::getDefault(status);
+}
+
+void SpoofImpl::construct(UErrorCode& status) {
+ fChecks = USPOOF_ALL_CHECKS;
+ fSpoofData = NULL;
+ fAllowedCharsSet = NULL;
+ fAllowedLocales = NULL;
+ fRestrictionLevel = USPOOF_HIGHLY_RESTRICTIVE;
+
+ if (U_FAILURE(status)) { return; }
+
+ UnicodeSet *allowedCharsSet = new UnicodeSet(0, 0x10ffff);
+ fAllowedCharsSet = allowedCharsSet;
+ fAllowedLocales = uprv_strdup("");
+ if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ allowedCharsSet->freeze();
+}
+
+
+// Copy Constructor, used by the user level clone() function.
+SpoofImpl::SpoofImpl(const SpoofImpl &src, UErrorCode &status) :
+ fChecks(USPOOF_ALL_CHECKS), fSpoofData(NULL), fAllowedCharsSet(NULL) ,
+ fAllowedLocales(NULL) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fChecks = src.fChecks;
+ if (src.fSpoofData != NULL) {
+ fSpoofData = src.fSpoofData->addReference();
+ }
+ fAllowedCharsSet = src.fAllowedCharsSet->clone();
+ fAllowedLocales = uprv_strdup(src.fAllowedLocales);
+ if (fAllowedCharsSet == NULL || fAllowedLocales == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ fRestrictionLevel = src.fRestrictionLevel;
+}
+
+SpoofImpl::~SpoofImpl() {
+ if (fSpoofData != NULL) {
+ fSpoofData->removeReference(); // Will delete if refCount goes to zero.
+ }
+ delete fAllowedCharsSet;
+ uprv_free((void *)fAllowedLocales);
+}
+
+// Cast this instance as a USpoofChecker for the C API.
+USpoofChecker *SpoofImpl::asUSpoofChecker() {
+ return exportForC();
+}
+
+//
+// Incoming parameter check on Status and the SpoofChecker object
+// received from the C API.
+//
+const SpoofImpl *SpoofImpl::validateThis(const USpoofChecker *sc, UErrorCode &status) {
+ auto* This = validate(sc, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (This->fSpoofData != NULL && !This->fSpoofData->validateDataVersion(status)) {
+ return NULL;
+ }
+ return This;
+}
+
+SpoofImpl *SpoofImpl::validateThis(USpoofChecker *sc, UErrorCode &status) {
+ return const_cast<SpoofImpl *>
+ (SpoofImpl::validateThis(const_cast<const USpoofChecker *>(sc), status));
+}
+
+
+void SpoofImpl::setAllowedLocales(const char *localesList, UErrorCode &status) {
+ UnicodeSet allowedChars;
+ UnicodeSet *tmpSet = NULL;
+ const char *locStart = localesList;
+ const char *locEnd = NULL;
+ const char *localesListEnd = localesList + uprv_strlen(localesList);
+ int32_t localeListCount = 0; // Number of locales provided by caller.
+
+ // Loop runs once per locale from the localesList, a comma separated list of locales.
+ do {
+ locEnd = uprv_strchr(locStart, ',');
+ if (locEnd == NULL) {
+ locEnd = localesListEnd;
+ }
+ while (*locStart == ' ') {
+ locStart++;
+ }
+ const char *trimmedEnd = locEnd-1;
+ while (trimmedEnd > locStart && *trimmedEnd == ' ') {
+ trimmedEnd--;
+ }
+ if (trimmedEnd <= locStart) {
+ break;
+ }
+ const char *locale = uprv_strndup(locStart, (int32_t)(trimmedEnd + 1 - locStart));
+ localeListCount++;
+
+ // We have one locale from the locales list.
+ // Add the script chars for this locale to the accumulating set of allowed chars.
+ // If the locale is no good, we will be notified back via status.
+ addScriptChars(locale, &allowedChars, status);
+ uprv_free((void *)locale);
+ if (U_FAILURE(status)) {
+ break;
+ }
+ locStart = locEnd + 1;
+ } while (locStart < localesListEnd);
+
+ // If our caller provided an empty list of locales, we disable the allowed characters checking
+ if (localeListCount == 0) {
+ uprv_free((void *)fAllowedLocales);
+ fAllowedLocales = uprv_strdup("");
+ tmpSet = new UnicodeSet(0, 0x10ffff);
+ if (fAllowedLocales == NULL || tmpSet == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ tmpSet->freeze();
+ delete fAllowedCharsSet;
+ fAllowedCharsSet = tmpSet;
+ fChecks &= ~USPOOF_CHAR_LIMIT;
+ return;
+ }
+
+
+ // Add all common and inherited characters to the set of allowed chars.
+ UnicodeSet tempSet;
+ tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_COMMON, status);
+ allowedChars.addAll(tempSet);
+ tempSet.applyIntPropertyValue(UCHAR_SCRIPT, USCRIPT_INHERITED, status);
+ allowedChars.addAll(tempSet);
+
+ // If anything went wrong, we bail out without changing
+ // the state of the spoof checker.
+ if (U_FAILURE(status)) {
+ return;
+ }
+
+ // Store the updated spoof checker state.
+ tmpSet = allowedChars.clone();
+ const char *tmpLocalesList = uprv_strdup(localesList);
+ if (tmpSet == NULL || tmpLocalesList == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ uprv_free((void *)fAllowedLocales);
+ fAllowedLocales = tmpLocalesList;
+ tmpSet->freeze();
+ delete fAllowedCharsSet;
+ fAllowedCharsSet = tmpSet;
+ fChecks |= USPOOF_CHAR_LIMIT;
+}
+
+
+const char * SpoofImpl::getAllowedLocales(UErrorCode &/*status*/) {
+ return fAllowedLocales;
+}
+
+
+// Given a locale (a language), add all the characters from all of the scripts used with that language
+// to the allowedChars UnicodeSet
+
+void SpoofImpl::addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status) {
+ UScriptCode scripts[30];
+
+ int32_t numScripts = uscript_getCode(locale, scripts, UPRV_LENGTHOF(scripts), &status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (status == U_USING_DEFAULT_WARNING) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ UnicodeSet tmpSet;
+ int32_t i;
+ for (i=0; i<numScripts; i++) {
+ tmpSet.applyIntPropertyValue(UCHAR_SCRIPT, scripts[i], status);
+ allowedChars->addAll(tmpSet);
+ }
+}
+
+// Computes the augmented script set for a code point, according to UTS 39 section 5.1.
+void SpoofImpl::getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status) {
+ result.resetAll();
+ result.setScriptExtensions(codePoint, status);
+ if (U_FAILURE(status)) { return; }
+
+ // Section 5.1 step 1
+ if (result.test(USCRIPT_HAN, status)) {
+ result.set(USCRIPT_HAN_WITH_BOPOMOFO, status);
+ result.set(USCRIPT_JAPANESE, status);
+ result.set(USCRIPT_KOREAN, status);
+ }
+ if (result.test(USCRIPT_HIRAGANA, status)) {
+ result.set(USCRIPT_JAPANESE, status);
+ }
+ if (result.test(USCRIPT_KATAKANA, status)) {
+ result.set(USCRIPT_JAPANESE, status);
+ }
+ if (result.test(USCRIPT_HANGUL, status)) {
+ result.set(USCRIPT_KOREAN, status);
+ }
+ if (result.test(USCRIPT_BOPOMOFO, status)) {
+ result.set(USCRIPT_HAN_WITH_BOPOMOFO, status);
+ }
+
+ // Section 5.1 step 2
+ if (result.test(USCRIPT_COMMON, status) || result.test(USCRIPT_INHERITED, status)) {
+ result.setAll();
+ }
+}
+
+// Computes the resolved script set for a string, according to UTS 39 section 5.1.
+void SpoofImpl::getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const {
+ getResolvedScriptSetWithout(input, USCRIPT_CODE_LIMIT, result, status);
+}
+
+// Computes the resolved script set for a string, omitting characters having the specified script.
+// If USCRIPT_CODE_LIMIT is passed as the second argument, all characters are included.
+void SpoofImpl::getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const {
+ result.setAll();
+
+ ScriptSet temp;
+ UChar32 codePoint;
+ for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) {
+ codePoint = input.char32At(i);
+
+ // Compute the augmented script set for the character
+ getAugmentedScriptSet(codePoint, temp, status);
+ if (U_FAILURE(status)) { return; }
+
+ // Intersect the augmented script set with the resolved script set, but only if the character doesn't
+ // have the script specified in the function call
+ if (script == USCRIPT_CODE_LIMIT || !temp.test(script, status)) {
+ result.intersect(temp);
+ }
+ }
+}
+
+// Computes the set of numerics for a string, according to UTS 39 section 5.3.
+void SpoofImpl::getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& /*status*/) const {
+ result.clear();
+
+ UChar32 codePoint;
+ for (int32_t i = 0; i < input.length(); i += U16_LENGTH(codePoint)) {
+ codePoint = input.char32At(i);
+
+ // Store a representative character for each kind of decimal digit
+ if (u_charType(codePoint) == U_DECIMAL_DIGIT_NUMBER) {
+ // Store the zero character as a representative for comparison.
+ // Unicode guarantees it is codePoint - value
+ result.add(codePoint - (UChar32)u_getNumericValue(codePoint));
+ }
+ }
+}
+
+// Computes the restriction level of a string, according to UTS 39 section 5.2.
+URestrictionLevel SpoofImpl::getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const {
+ // Section 5.2 step 1:
+ if (!fAllowedCharsSet->containsAll(input)) {
+ return USPOOF_UNRESTRICTIVE;
+ }
+
+ // Section 5.2 step 2
+ // Java use a static UnicodeSet for this test. In C++, avoid the static variable
+ // and just do a simple for loop.
+ UBool allASCII = TRUE;
+ for (int32_t i=0, length=input.length(); i<length; i++) {
+ if (input.charAt(i) > 0x7f) {
+ allASCII = FALSE;
+ break;
+ }
+ }
+ if (allASCII) {
+ return USPOOF_ASCII;
+ }
+
+ // Section 5.2 steps 3:
+ ScriptSet resolvedScriptSet;
+ getResolvedScriptSet(input, resolvedScriptSet, status);
+ if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; }
+
+ // Section 5.2 step 4:
+ if (!resolvedScriptSet.isEmpty()) {
+ return USPOOF_SINGLE_SCRIPT_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 5:
+ ScriptSet resolvedNoLatn;
+ getResolvedScriptSetWithout(input, USCRIPT_LATIN, resolvedNoLatn, status);
+ if (U_FAILURE(status)) { return USPOOF_UNRESTRICTIVE; }
+
+ // Section 5.2 step 6:
+ if (resolvedNoLatn.test(USCRIPT_HAN_WITH_BOPOMOFO, status)
+ || resolvedNoLatn.test(USCRIPT_JAPANESE, status)
+ || resolvedNoLatn.test(USCRIPT_KOREAN, status)) {
+ return USPOOF_HIGHLY_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 7:
+ if (!resolvedNoLatn.isEmpty()
+ && !resolvedNoLatn.test(USCRIPT_CYRILLIC, status)
+ && !resolvedNoLatn.test(USCRIPT_GREEK, status)
+ && !resolvedNoLatn.test(USCRIPT_CHEROKEE, status)) {
+ return USPOOF_MODERATELY_RESTRICTIVE;
+ }
+
+ // Section 5.2 step 8:
+ return USPOOF_MINIMALLY_RESTRICTIVE;
+}
+
+int32_t SpoofImpl::findHiddenOverlay(const UnicodeString& input, UErrorCode&) const {
+ bool sawLeadCharacter = false;
+ for (int32_t i=0; i<input.length();) {
+ UChar32 cp = input.char32At(i);
+ if (sawLeadCharacter && cp == 0x0307) {
+ return i;
+ }
+ uint8_t combiningClass = u_getCombiningClass(cp);
+ // Skip over characters except for those with combining class 0 (non-combining characters) or with
+ // combining class 230 (same class as U+0307)
+ U_ASSERT(u_getCombiningClass(0x0307) == 230);
+ if (combiningClass == 0 || combiningClass == 230) {
+ sawLeadCharacter = isIllegalCombiningDotLeadCharacter(cp);
+ }
+ i += U16_LENGTH(cp);
+ }
+ return -1;
+}
+
+static inline bool isIllegalCombiningDotLeadCharacterNoLookup(UChar32 cp) {
+ return cp == u'i' || cp == u'j' || cp == u'ı' || cp == u'ȷ' || cp == u'l' ||
+ u_hasBinaryProperty(cp, UCHAR_SOFT_DOTTED);
+}
+
+bool SpoofImpl::isIllegalCombiningDotLeadCharacter(UChar32 cp) const {
+ if (isIllegalCombiningDotLeadCharacterNoLookup(cp)) {
+ return true;
+ }
+ UnicodeString skelStr;
+ fSpoofData->confusableLookup(cp, skelStr);
+ UChar32 finalCp = skelStr.char32At(skelStr.moveIndex32(skelStr.length(), -1));
+ if (finalCp != cp && isIllegalCombiningDotLeadCharacterNoLookup(finalCp)) {
+ return true;
+ }
+ return false;
+}
+
+
+
+// Convert a text format hex number. Utility function used by builder code. Static.
+// Input: UChar *string text. Output: a UChar32
+// Input has been pre-checked, and will have no non-hex chars.
+// The number must fall in the code point range of 0..0x10ffff
+// Static Function.
+UChar32 SpoofImpl::ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ U_ASSERT(limit-start > 0);
+ uint32_t val = 0;
+ int i;
+ for (i=start; i<limit; i++) {
+ int digitVal = s[i] - 0x30;
+ if (digitVal>9) {
+ digitVal = 0xa + (s[i] - 0x41); // Upper Case 'A'
+ }
+ if (digitVal>15) {
+ digitVal = 0xa + (s[i] - 0x61); // Lower Case 'a'
+ }
+ U_ASSERT(digitVal <= 0xf);
+ val <<= 4;
+ val += digitVal;
+ }
+ if (val > 0x10ffff) {
+ status = U_PARSE_ERROR;
+ val = 0;
+ }
+ return (UChar32)val;
+}
+
+
+//-----------------------------------------
+//
+// class CheckResult Implementation
+//
+//-----------------------------------------
+
+CheckResult::CheckResult() {
+ clear();
+}
+
+USpoofCheckResult* CheckResult::asUSpoofCheckResult() {
+ return exportForC();
+}
+
+//
+// Incoming parameter check on Status and the CheckResult object
+// received from the C API.
+//
+const CheckResult* CheckResult::validateThis(const USpoofCheckResult *ptr, UErrorCode &status) {
+ return validate(ptr, status);
+}
+
+CheckResult* CheckResult::validateThis(USpoofCheckResult *ptr, UErrorCode &status) {
+ return validate(ptr, status);
+}
+
+void CheckResult::clear() {
+ fChecks = 0;
+ fNumerics.clear();
+ fRestrictionLevel = USPOOF_UNDEFINED_RESTRICTIVE;
+}
+
+int32_t CheckResult::toCombinedBitmask(int32_t enabledChecks) {
+ if ((enabledChecks & USPOOF_AUX_INFO) != 0 && fRestrictionLevel != USPOOF_UNDEFINED_RESTRICTIVE) {
+ return fChecks | fRestrictionLevel;
+ } else {
+ return fChecks;
+ }
+}
+
+CheckResult::~CheckResult() {
+}
+
+//----------------------------------------------------------------------------------------------
+//
+// class SpoofData Implementation
+//
+//----------------------------------------------------------------------------------------------
+
+
+UBool SpoofData::validateDataVersion(UErrorCode &status) const {
+ if (U_FAILURE(status) ||
+ fRawData == NULL ||
+ fRawData->fMagic != USPOOF_MAGIC ||
+ fRawData->fFormatVersion[0] != USPOOF_CONFUSABLE_DATA_FORMAT_VERSION ||
+ fRawData->fFormatVersion[1] != 0 ||
+ fRawData->fFormatVersion[2] != 0 ||
+ fRawData->fFormatVersion[3] != 0) {
+ status = U_INVALID_FORMAT_ERROR;
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static UBool U_CALLCONV
+spoofDataIsAcceptable(void *context,
+ const char * /* type */, const char * /*name*/,
+ const UDataInfo *pInfo) {
+ if(
+ pInfo->size >= 20 &&
+ pInfo->isBigEndian == U_IS_BIG_ENDIAN &&
+ pInfo->charsetFamily == U_CHARSET_FAMILY &&
+ pInfo->dataFormat[0] == 0x43 && // dataFormat="Cfu "
+ pInfo->dataFormat[1] == 0x66 &&
+ pInfo->dataFormat[2] == 0x75 &&
+ pInfo->dataFormat[3] == 0x20 &&
+ pInfo->formatVersion[0] == USPOOF_CONFUSABLE_DATA_FORMAT_VERSION
+ ) {
+ UVersionInfo *version = static_cast<UVersionInfo *>(context);
+ if(version != NULL) {
+ uprv_memcpy(version, pInfo->dataVersion, 4);
+ }
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+// Methods for the loading of the default confusables data file. The confusable
+// data is loaded only when it is needed.
+//
+// SpoofData::getDefault() - Return the default confusables data, and call the
+// initOnce() if it is not available. Adds a reference
+// to the SpoofData that the caller is responsible for
+// decrementing when they are done with the data.
+//
+// uspoof_loadDefaultData - Called once, from initOnce(). The resulting SpoofData
+// is shared by all spoof checkers using the default data.
+//
+// uspoof_cleanupDefaultData - Called during cleanup.
+//
+
+static UInitOnce gSpoofInitDefaultOnce = U_INITONCE_INITIALIZER;
+static SpoofData* gDefaultSpoofData;
+
+static UBool U_CALLCONV
+uspoof_cleanupDefaultData(void) {
+ if (gDefaultSpoofData) {
+ // Will delete, assuming all user-level spoof checkers were closed.
+ gDefaultSpoofData->removeReference();
+ gDefaultSpoofData = nullptr;
+ gSpoofInitDefaultOnce.reset();
+ }
+ return TRUE;
+}
+
+static void U_CALLCONV uspoof_loadDefaultData(UErrorCode& status) {
+ UDataMemory *udm = udata_openChoice(nullptr, "cfu", "confusables",
+ spoofDataIsAcceptable,
+ nullptr, // context, would receive dataVersion if supplied.
+ &status);
+ if (U_FAILURE(status)) { return; }
+ gDefaultSpoofData = new SpoofData(udm, status);
+ if (U_FAILURE(status)) {
+ delete gDefaultSpoofData;
+ gDefaultSpoofData = nullptr;
+ return;
+ }
+ if (gDefaultSpoofData == nullptr) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ ucln_i18n_registerCleanup(UCLN_I18N_SPOOFDATA, uspoof_cleanupDefaultData);
+}
+
+SpoofData* SpoofData::getDefault(UErrorCode& status) {
+ umtx_initOnce(gSpoofInitDefaultOnce, &uspoof_loadDefaultData, status);
+ if (U_FAILURE(status)) { return NULL; }
+ gDefaultSpoofData->addReference();
+ return gDefaultSpoofData;
+}
+
+
+
+SpoofData::SpoofData(UDataMemory *udm, UErrorCode &status)
+{
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fUDM = udm;
+ // fRawData is non-const because it may be constructed by the data builder.
+ fRawData = reinterpret_cast<SpoofDataHeader *>(
+ const_cast<void *>(udata_getMemory(udm)));
+ validateDataVersion(status);
+ initPtrs(status);
+}
+
+
+SpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status)
+{
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if ((size_t)length < sizeof(SpoofDataHeader)) {
+ status = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ if (data == NULL) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ void *ncData = const_cast<void *>(data);
+ fRawData = static_cast<SpoofDataHeader *>(ncData);
+ if (length < fRawData->fLength) {
+ status = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ validateDataVersion(status);
+ initPtrs(status);
+}
+
+
+// Spoof Data constructor for use from data builder.
+// Initializes a new, empty data area that will be populated later.
+SpoofData::SpoofData(UErrorCode &status) {
+ reset();
+ if (U_FAILURE(status)) {
+ return;
+ }
+ fDataOwned = true;
+
+ // The spoof header should already be sized to be a multiple of 16 bytes.
+ // Just in case it's not, round it up.
+ uint32_t initialSize = (sizeof(SpoofDataHeader) + 15) & ~15;
+ U_ASSERT(initialSize == sizeof(SpoofDataHeader));
+
+ fRawData = static_cast<SpoofDataHeader *>(uprv_malloc(initialSize));
+ fMemLimit = initialSize;
+ if (fRawData == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ uprv_memset(fRawData, 0, initialSize);
+
+ fRawData->fMagic = USPOOF_MAGIC;
+ fRawData->fFormatVersion[0] = USPOOF_CONFUSABLE_DATA_FORMAT_VERSION;
+ fRawData->fFormatVersion[1] = 0;
+ fRawData->fFormatVersion[2] = 0;
+ fRawData->fFormatVersion[3] = 0;
+ initPtrs(status);
+}
+
+// reset() - initialize all fields.
+// Should be updated if any new fields are added.
+// Called by constructors to put things in a known initial state.
+void SpoofData::reset() {
+ fRawData = NULL;
+ fDataOwned = FALSE;
+ fUDM = NULL;
+ fMemLimit = 0;
+ fRefCount = 1;
+ fCFUKeys = NULL;
+ fCFUValues = NULL;
+ fCFUStrings = NULL;
+}
+
+
+// SpoofData::initPtrs()
+// Initialize the pointers to the various sections of the raw data.
+//
+// This function is used both during the Trie building process (multiple
+// times, as the individual data sections are added), and
+// during the opening of a Spoof Checker from prebuilt data.
+//
+// The pointers for non-existent data sections (identified by an offset of 0)
+// are set to NULL.
+//
+// Note: During building the data, adding each new data section
+// reallocs the raw data area, which likely relocates it, which
+// in turn requires reinitializing all of the pointers into it, hence
+// multiple calls to this function during building.
+//
+void SpoofData::initPtrs(UErrorCode &status) {
+ fCFUKeys = NULL;
+ fCFUValues = NULL;
+ fCFUStrings = NULL;
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (fRawData->fCFUKeys != 0) {
+ fCFUKeys = (int32_t *)((char *)fRawData + fRawData->fCFUKeys);
+ }
+ if (fRawData->fCFUStringIndex != 0) {
+ fCFUValues = (uint16_t *)((char *)fRawData + fRawData->fCFUStringIndex);
+ }
+ if (fRawData->fCFUStringTable != 0) {
+ fCFUStrings = (UChar *)((char *)fRawData + fRawData->fCFUStringTable);
+ }
+}
+
+
+SpoofData::~SpoofData() {
+ if (fDataOwned) {
+ uprv_free(fRawData);
+ }
+ fRawData = NULL;
+ if (fUDM != NULL) {
+ udata_close(fUDM);
+ }
+ fUDM = NULL;
+}
+
+
+void SpoofData::removeReference() {
+ if (umtx_atomic_dec(&fRefCount) == 0) {
+ delete this;
+ }
+}
+
+
+SpoofData *SpoofData::addReference() {
+ umtx_atomic_inc(&fRefCount);
+ return this;
+}
+
+
+void *SpoofData::reserveSpace(int32_t numBytes, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ if (!fDataOwned) {
+ UPRV_UNREACHABLE_EXIT;
+ }
+
+ numBytes = (numBytes + 15) & ~15; // Round up to a multiple of 16
+ uint32_t returnOffset = fMemLimit;
+ fMemLimit += numBytes;
+ fRawData = static_cast<SpoofDataHeader *>(uprv_realloc(fRawData, fMemLimit));
+ fRawData->fLength = fMemLimit;
+ uprv_memset((char *)fRawData + returnOffset, 0, numBytes);
+ initPtrs(status);
+ return (char *)fRawData + returnOffset;
+}
+
+int32_t SpoofData::serialize(void *buf, int32_t capacity, UErrorCode &status) const {
+ int32_t dataSize = fRawData->fLength;
+ if (capacity < dataSize) {
+ status = U_BUFFER_OVERFLOW_ERROR;
+ return dataSize;
+ }
+ uprv_memcpy(buf, fRawData, dataSize);
+ return dataSize;
+}
+
+int32_t SpoofData::size() const {
+ return fRawData->fLength;
+}
+
+//-------------------------------
+//
+// Front-end APIs for SpoofData
+//
+//-------------------------------
+
+int32_t SpoofData::confusableLookup(UChar32 inChar, UnicodeString &dest) const {
+ // Perform a binary search.
+ // [lo, hi), i.e lo is inclusive, hi is exclusive.
+ // The result after the loop will be in lo.
+ int32_t lo = 0;
+ int32_t hi = length();
+ do {
+ int32_t mid = (lo + hi) / 2;
+ if (codePointAt(mid) > inChar) {
+ hi = mid;
+ } else if (codePointAt(mid) < inChar) {
+ lo = mid;
+ } else {
+ // Found result. Break early.
+ lo = mid;
+ break;
+ }
+ } while (hi - lo > 1);
+
+ // Did we find an entry? If not, the char maps to itself.
+ if (codePointAt(lo) != inChar) {
+ dest.append(inChar);
+ return 1;
+ }
+
+ // Add the element to the string builder and return.
+ return appendValueTo(lo, dest);
+}
+
+int32_t SpoofData::length() const {
+ return fRawData->fCFUKeysSize;
+}
+
+UChar32 SpoofData::codePointAt(int32_t index) const {
+ return ConfusableDataUtils::keyToCodePoint(fCFUKeys[index]);
+}
+
+int32_t SpoofData::appendValueTo(int32_t index, UnicodeString& dest) const {
+ int32_t stringLength = ConfusableDataUtils::keyToLength(fCFUKeys[index]);
+
+ // Value is either a char (for strings of length 1) or
+ // an index into the string table (for longer strings)
+ uint16_t value = fCFUValues[index];
+ if (stringLength == 1) {
+ dest.append((UChar)value);
+ } else {
+ dest.append(fCFUStrings + value, stringLength);
+ }
+
+ return stringLength;
+}
+
+
+U_NAMESPACE_END
+
+U_NAMESPACE_USE
+
+//-----------------------------------------------------------------------------
+//
+// uspoof_swap - byte swap and char encoding swap of spoof data
+//
+//-----------------------------------------------------------------------------
+U_CAPI int32_t U_EXPORT2
+uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData,
+ UErrorCode *status) {
+
+ if (status == NULL || U_FAILURE(*status)) {
+ return 0;
+ }
+ if(ds==NULL || inData==NULL || length<-1 || (length>0 && outData==NULL)) {
+ *status=U_ILLEGAL_ARGUMENT_ERROR;
+ return 0;
+ }
+
+ //
+ // Check that the data header is for spoof data.
+ // (Header contents are defined in gencfu.cpp)
+ //
+ const UDataInfo *pInfo = (const UDataInfo *)((const char *)inData+4);
+ if(!( pInfo->dataFormat[0]==0x43 && /* dataFormat="Cfu " */
+ pInfo->dataFormat[1]==0x66 &&
+ pInfo->dataFormat[2]==0x75 &&
+ pInfo->dataFormat[3]==0x20 &&
+ pInfo->formatVersion[0]==USPOOF_CONFUSABLE_DATA_FORMAT_VERSION &&
+ pInfo->formatVersion[1]==0 &&
+ pInfo->formatVersion[2]==0 &&
+ pInfo->formatVersion[3]==0 )) {
+ udata_printError(ds, "uspoof_swap(): data format %02x.%02x.%02x.%02x "
+ "(format version %02x %02x %02x %02x) is not recognized\n",
+ pInfo->dataFormat[0], pInfo->dataFormat[1],
+ pInfo->dataFormat[2], pInfo->dataFormat[3],
+ pInfo->formatVersion[0], pInfo->formatVersion[1],
+ pInfo->formatVersion[2], pInfo->formatVersion[3]);
+ *status=U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ //
+ // Swap the data header. (This is the generic ICU Data Header, not the uspoof Specific
+ // header). This swap also conveniently gets us
+ // the size of the ICU d.h., which lets us locate the start
+ // of the uspoof specific data.
+ //
+ int32_t headerSize=udata_swapDataHeader(ds, inData, length, outData, status);
+
+
+ //
+ // Get the Spoof Data Header, and check that it appears to be OK.
+ //
+ //
+ const uint8_t *inBytes =(const uint8_t *)inData+headerSize;
+ SpoofDataHeader *spoofDH = (SpoofDataHeader *)inBytes;
+ if (ds->readUInt32(spoofDH->fMagic) != USPOOF_MAGIC ||
+ ds->readUInt32(spoofDH->fLength) < sizeof(SpoofDataHeader))
+ {
+ udata_printError(ds, "uspoof_swap(): Spoof Data header is invalid.\n");
+ *status=U_UNSUPPORTED_ERROR;
+ return 0;
+ }
+
+ //
+ // Prefight operation? Just return the size
+ //
+ int32_t spoofDataLength = ds->readUInt32(spoofDH->fLength);
+ int32_t totalSize = headerSize + spoofDataLength;
+ if (length < 0) {
+ return totalSize;
+ }
+
+ //
+ // Check that length passed in is consistent with length from Spoof data header.
+ //
+ if (length < totalSize) {
+ udata_printError(ds, "uspoof_swap(): too few bytes (%d after ICU Data header) for spoof data.\n",
+ spoofDataLength);
+ *status=U_INDEX_OUTOFBOUNDS_ERROR;
+ return 0;
+ }
+
+
+ //
+ // Swap the Data. Do the data itself first, then the Spoof Data Header, because
+ // we need to reference the header to locate the data, and an
+ // inplace swap of the header leaves it unusable.
+ //
+ uint8_t *outBytes = (uint8_t *)outData + headerSize;
+ SpoofDataHeader *outputDH = (SpoofDataHeader *)outBytes;
+
+ int32_t sectionStart;
+ int32_t sectionLength;
+
+ //
+ // If not swapping in place, zero out the output buffer before starting.
+ // Gaps may exist between the individual sections, and these must be zeroed in
+ // the output buffer. The simplest way to do that is to just zero the whole thing.
+ //
+ if (inBytes != outBytes) {
+ uprv_memset(outBytes, 0, spoofDataLength);
+ }
+
+ // Confusables Keys Section (fCFUKeys)
+ sectionStart = ds->readUInt32(spoofDH->fCFUKeys);
+ sectionLength = ds->readUInt32(spoofDH->fCFUKeysSize) * 4;
+ ds->swapArray32(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // String Index Section
+ sectionStart = ds->readUInt32(spoofDH->fCFUStringIndex);
+ sectionLength = ds->readUInt32(spoofDH->fCFUStringIndexSize) * 2;
+ ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // String Table Section
+ sectionStart = ds->readUInt32(spoofDH->fCFUStringTable);
+ sectionLength = ds->readUInt32(spoofDH->fCFUStringTableLen) * 2;
+ ds->swapArray16(ds, inBytes+sectionStart, sectionLength, outBytes+sectionStart, status);
+
+ // And, last, swap the header itself.
+ // int32_t fMagic // swap this
+ // uint8_t fFormatVersion[4] // Do not swap this, just copy
+ // int32_t fLength and all the rest // Swap the rest, all is 32 bit stuff.
+ //
+ uint32_t magic = ds->readUInt32(spoofDH->fMagic);
+ ds->writeUInt32((uint32_t *)&outputDH->fMagic, magic);
+
+ if (outputDH->fFormatVersion != spoofDH->fFormatVersion) {
+ uprv_memcpy(outputDH->fFormatVersion, spoofDH->fFormatVersion, sizeof(spoofDH->fFormatVersion));
+ }
+ // swap starting at fLength
+ ds->swapArray32(ds, &spoofDH->fLength, sizeof(SpoofDataHeader)-8 /* minus magic and fFormatVersion[4] */, &outputDH->fLength, status);
+
+ return totalSize;
+}
+
+#endif
+
+
diff --git a/thirdparty/icu4c/i18n/uspoof_impl.h b/thirdparty/icu4c/i18n/uspoof_impl.h
new file mode 100644
index 0000000000..e75ae262bd
--- /dev/null
+++ b/thirdparty/icu4c/i18n/uspoof_impl.h
@@ -0,0 +1,343 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+***************************************************************************
+* Copyright (C) 2008-2013, International Business Machines Corporation
+* and others. All Rights Reserved.
+***************************************************************************
+*
+* uspoof_impl.h
+*
+* Implementation header for spoof detection
+*
+*/
+
+#ifndef USPOOFIM_H
+#define USPOOFIM_H
+
+#include "uassert.h"
+#include "unicode/utypes.h"
+#include "unicode/uspoof.h"
+#include "unicode/uscript.h"
+#include "unicode/udata.h"
+#include "udataswp.h"
+#include "utrie2.h"
+
+#if !UCONFIG_NO_NORMALIZATION
+
+#ifdef __cplusplus
+
+#include "capi_helper.h"
+
+U_NAMESPACE_BEGIN
+
+// The maximum length (in UTF-16 UChars) of the skeleton replacement string resulting from
+// a single input code point. This is function of the unicode.org data.
+#define USPOOF_MAX_SKELETON_EXPANSION 20
+
+// The default stack buffer size for copies or conversions or normalizations
+// of input strings being checked. (Used in multiple places.)
+#define USPOOF_STACK_BUFFER_SIZE 100
+
+// Magic number for sanity checking spoof data.
+#define USPOOF_MAGIC 0x3845fdef
+
+// Magic number for sanity checking spoof checkers.
+#define USPOOF_CHECK_MAGIC 0x2734ecde
+
+class ScriptSet;
+class SpoofData;
+struct SpoofDataHeader;
+class ConfusableDataUtils;
+
+/**
+ * Class SpoofImpl corresponds directly to the plain C API opaque type
+ * USpoofChecker. One can be cast to the other.
+ */
+class SpoofImpl : public UObject,
+ public IcuCApiHelper<USpoofChecker, SpoofImpl, USPOOF_MAGIC> {
+public:
+ SpoofImpl(SpoofData *data, UErrorCode& status);
+ SpoofImpl(UErrorCode& status);
+ SpoofImpl();
+ void construct(UErrorCode& status);
+ virtual ~SpoofImpl();
+
+ /** Copy constructor, used by the user level uspoof_clone() function.
+ */
+ SpoofImpl(const SpoofImpl &src, UErrorCode &status);
+
+ USpoofChecker *asUSpoofChecker();
+ static SpoofImpl *validateThis(USpoofChecker *sc, UErrorCode &status);
+ static const SpoofImpl *validateThis(const USpoofChecker *sc, UErrorCode &status);
+
+ /** Set and Get AllowedLocales, implementations of the corresponding API */
+ void setAllowedLocales(const char *localesList, UErrorCode &status);
+ const char * getAllowedLocales(UErrorCode &status);
+
+ // Add (union) to the UnicodeSet all of the characters for the scripts used for
+ // the specified locale. Part of the implementation of setAllowedLocales.
+ void addScriptChars(const char *locale, UnicodeSet *allowedChars, UErrorCode &status);
+
+ // Functions implementing the features of UTS 39 section 5.
+ static void getAugmentedScriptSet(UChar32 codePoint, ScriptSet& result, UErrorCode& status);
+ void getResolvedScriptSet(const UnicodeString& input, ScriptSet& result, UErrorCode& status) const;
+ void getResolvedScriptSetWithout(const UnicodeString& input, UScriptCode script, ScriptSet& result, UErrorCode& status) const;
+ void getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& status) const;
+ URestrictionLevel getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const;
+
+ int32_t findHiddenOverlay(const UnicodeString& input, UErrorCode& status) const;
+ bool isIllegalCombiningDotLeadCharacter(UChar32 cp) const;
+
+ /** parse a hex number. Untility used by the builders. */
+ static UChar32 ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status);
+
+ static UClassID U_EXPORT2 getStaticClassID(void);
+ virtual UClassID getDynamicClassID(void) const override;
+
+ //
+ // Data Members
+ //
+
+ int32_t fChecks; // Bit vector of checks to perform.
+
+ SpoofData *fSpoofData;
+
+ const UnicodeSet *fAllowedCharsSet; // The UnicodeSet of allowed characters.
+ // for this Spoof Checker. Defaults to all chars.
+
+ const char *fAllowedLocales; // The list of allowed locales.
+ URestrictionLevel fRestrictionLevel; // The maximum restriction level for an acceptable identifier.
+};
+
+/**
+ * Class CheckResult corresponds directly to the plain C API opaque type
+ * USpoofCheckResult. One can be cast to the other.
+ */
+class CheckResult : public UObject,
+ public IcuCApiHelper<USpoofCheckResult, CheckResult, USPOOF_CHECK_MAGIC> {
+public:
+ CheckResult();
+ virtual ~CheckResult();
+
+ USpoofCheckResult *asUSpoofCheckResult();
+ static CheckResult *validateThis(USpoofCheckResult *ptr, UErrorCode &status);
+ static const CheckResult *validateThis(const USpoofCheckResult *ptr, UErrorCode &status);
+
+ void clear();
+
+ // Used to convert this CheckResult to the older int32_t return value API
+ int32_t toCombinedBitmask(int32_t expectedChecks);
+
+ // Data Members
+ int32_t fChecks; // Bit vector of checks that were failed.
+ UnicodeSet fNumerics; // Set of numerics found in the string.
+ URestrictionLevel fRestrictionLevel; // The restriction level of the string.
+};
+
+
+//
+// Confusable Mappings Data Structures, version 2.0
+//
+// For the confusable data, we are essentially implementing a map,
+// key: a code point
+// value: a string. Most commonly one char in length, but can be more.
+//
+// The keys are stored as a sorted array of 32 bit ints.
+// bits 0-23 a code point value
+// bits 24-31 length of value string, in UChars (between 1 and 256 UChars).
+// The key table is sorted in ascending code point order. (not on the
+// 32 bit int value, the flag bits do not participate in the sorting.)
+//
+// Lookup is done by means of a binary search in the key table.
+//
+// The corresponding values are kept in a parallel array of 16 bit ints.
+// If the value string is of length 1, it is literally in the value array.
+// For longer strings, the value array contains an index into the strings table.
+//
+// String Table:
+// The strings table contains all of the value strings (those of length two or greater)
+// concatenated together into one long UChar (UTF-16) array.
+//
+// There is no nul character or other mark between adjacent strings.
+//
+//----------------------------------------------------------------------------
+//
+// Changes from format version 1 to format version 2:
+// 1) Removal of the whole-script confusable data tables.
+// 2) Removal of the SL/SA/ML/MA and multi-table flags in the key bitmask.
+// 3) Expansion of string length value in the key bitmask from 2 bits to 8 bits.
+// 4) Removal of the string lengths table since 8 bits is sufficient for the
+// lengths of all entries in confusables.txt.
+
+
+
+// Internal functions for manipulating confusable data table keys
+#define USPOOF_CONFUSABLE_DATA_FORMAT_VERSION 2 // version for ICU 58
+class ConfusableDataUtils {
+public:
+ inline static UChar32 keyToCodePoint(int32_t key) {
+ return key & 0x00ffffff;
+ }
+ inline static int32_t keyToLength(int32_t key) {
+ return ((key & 0xff000000) >> 24) + 1;
+ }
+ inline static int32_t codePointAndLengthToKey(UChar32 codePoint, int32_t length) {
+ U_ASSERT((codePoint & 0x00ffffff) == codePoint);
+ U_ASSERT(length <= 256);
+ return codePoint | ((length - 1) << 24);
+ }
+};
+
+
+//-------------------------------------------------------------------------------------
+//
+// SpoofData
+//
+// A small class that wraps the raw (usually memory mapped) spoof data.
+// Serves two primary functions:
+// 1. Convenience. Contains real pointers to the data, to avoid dealing with
+// the offsets in the raw data.
+// 2. Reference counting. When a spoof checker is cloned, the raw data is shared
+// and must be retained until all checkers using the data are closed.
+// Nothing in this struct includes state that is specific to any particular
+// USpoofDetector object.
+//
+//---------------------------------------------------------------------------------------
+class SpoofData: public UMemory {
+ public:
+ static SpoofData* getDefault(UErrorCode &status); // Get standard ICU spoof data.
+ static void releaseDefault(); // Cleanup reference to default spoof data.
+
+ SpoofData(UErrorCode &status); // Create new spoof data wrapper.
+ // Only used when building new data from rules.
+
+ // Constructor for use when creating from prebuilt default data.
+ // A UDataMemory is what the ICU internal data loading functions provide.
+ // The udm is adopted by the SpoofData.
+ SpoofData(UDataMemory *udm, UErrorCode &status);
+
+ // Constructor for use when creating from serialized data.
+ //
+ SpoofData(const void *serializedData, int32_t length, UErrorCode &status);
+
+ // Check raw Spoof Data Version compatibility.
+ // Return true it looks good.
+ UBool validateDataVersion(UErrorCode &status) const;
+
+ ~SpoofData(); // Destructor not normally used.
+ // Use removeReference() instead.
+ // Reference Counting functions.
+ // Clone of a user-level spoof detector increments the ref count on the data.
+ // Close of a user-level spoof detector decrements the ref count.
+ // If the data is owned by us, it will be deleted when count goes to zero.
+ SpoofData *addReference();
+ void removeReference();
+
+ // Reset all fields to an initial state.
+ // Called from the top of all constructors.
+ void reset();
+
+ // Copy this instance's raw data buffer to the specified address.
+ int32_t serialize(void *buf, int32_t capacity, UErrorCode &status) const;
+
+ // Get the total number of bytes of data backed by this SpoofData.
+ // Not to be confused with length, which returns the number of confusable entries.
+ int32_t size() const;
+
+ // Get the confusable skeleton transform for a single code point.
+ // The result is a string with a length between 1 and 18 as of Unicode 9.
+ // This is the main public endpoint for this class.
+ // @return The length in UTF-16 code units of the substitution string.
+ int32_t confusableLookup(UChar32 inChar, UnicodeString &dest) const;
+
+ // Get the number of confusable entries in this SpoofData.
+ int32_t length() const;
+
+ // Get the code point (key) at the specified index.
+ UChar32 codePointAt(int32_t index) const;
+
+ // Get the confusable skeleton (value) at the specified index.
+ // Append it to the specified UnicodeString&.
+ // @return The length in UTF-16 code units of the skeleton string.
+ int32_t appendValueTo(int32_t index, UnicodeString& dest) const;
+
+ private:
+ // Reserve space in the raw data. For use by builder when putting together a
+ // new set of data. Init the new storage to zero, to prevent inconsistent
+ // results if it is not all otherwise set by the requester.
+ // Return:
+ // pointer to the new space that was added by this function.
+ void *reserveSpace(int32_t numBytes, UErrorCode &status);
+
+ // initialize the pointers from this object to the raw data.
+ void initPtrs(UErrorCode &status);
+
+ SpoofDataHeader *fRawData; // Ptr to the raw memory-mapped data
+ UBool fDataOwned; // True if the raw data is owned, and needs
+ // to be deleted when refcount goes to zero.
+ UDataMemory *fUDM; // If not NULL, our data came from a
+ // UDataMemory, which we must close when
+ // we are done.
+
+ uint32_t fMemLimit; // Limit of available raw data space
+ u_atomic_int32_t fRefCount;
+
+ // Confusable data
+ int32_t *fCFUKeys;
+ uint16_t *fCFUValues;
+ UChar *fCFUStrings;
+
+ friend class ConfusabledataBuilder;
+};
+
+//---------------------------------------------------------------------------------------
+//
+// Raw Binary Data Formats, as loaded from the ICU data file,
+// or as built by the builder.
+//
+//---------------------------------------------------------------------------------------
+struct SpoofDataHeader {
+ int32_t fMagic; // (0x3845fdef)
+ uint8_t fFormatVersion[4]; // Data Format. Same as the value in struct UDataInfo
+ // if there is one associated with this data.
+ int32_t fLength; // Total length in bytes of this spoof data,
+ // including all sections, not just the header.
+
+ // The following four sections refer to data representing the confusable data
+ // from the Unicode.org data from "confusables.txt"
+
+ int32_t fCFUKeys; // byte offset to Keys table (from SpoofDataHeader *)
+ int32_t fCFUKeysSize; // number of entries in keys table (32 bits each)
+
+ // TODO: change name to fCFUValues, for consistency.
+ int32_t fCFUStringIndex; // byte offset to String Indexes table
+ int32_t fCFUStringIndexSize; // number of entries in String Indexes table (16 bits each)
+ // (number of entries must be same as in Keys table
+
+ int32_t fCFUStringTable; // byte offset of String table
+ int32_t fCFUStringTableLen; // length of string table (in 16 bit UChars)
+
+ // The following sections are for data from xidmodifications.txt
+
+ int32_t unused[15]; // Padding, Room for Expansion
+};
+
+
+
+U_NAMESPACE_END
+#endif /* __cplusplus */
+
+/**
+ * Endianness swap function for binary spoof data.
+ * @internal
+ */
+U_CAPI int32_t U_EXPORT2
+uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outData,
+ UErrorCode *status);
+
+
+#endif
+
+#endif /* USPOOFIM_H */
+
diff --git a/thirdparty/icu4c/icudt70l.dat b/thirdparty/icu4c/icudt70l.dat
deleted file mode 100644
index 7932bc2ccd..0000000000
--- a/thirdparty/icu4c/icudt70l.dat
+++ /dev/null
Binary files differ
diff --git a/thirdparty/icu4c/icudt71l.dat b/thirdparty/icu4c/icudt71l.dat
new file mode 100644
index 0000000000..3fa3af9c23
--- /dev/null
+++ b/thirdparty/icu4c/icudt71l.dat
Binary files differ
diff --git a/thirdparty/jpeg-compressor/jpge.cpp b/thirdparty/jpeg-compressor/jpge.cpp
new file mode 100644
index 0000000000..5a36c19653
--- /dev/null
+++ b/thirdparty/jpeg-compressor/jpge.cpp
@@ -0,0 +1,1076 @@
+// jpge.cpp - C++ class for JPEG compression. Richard Geldreich <richgel99@gmail.com>
+// Supports grayscale, H1V1, H2V1, and H2V2 chroma subsampling factors, one or two pass Huffman table optimization, libjpeg-style quality 1-100 quality factors.
+// Also supports using luma quantization tables for chroma.
+//
+// Released under two licenses. You are free to choose which license you want:
+// License 1:
+// Public Domain
+//
+// License 2:
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// v1.01, Dec. 18, 2010 - Initial release
+// v1.02, Apr. 6, 2011 - Removed 2x2 ordered dither in H2V1 chroma subsampling method load_block_16_8_8(). (The rounding factor was 2, when it should have been 1. Either way, it wasn't helping.)
+// v1.03, Apr. 16, 2011 - Added support for optimized Huffman code tables, optimized dynamic memory allocation down to only 1 alloc.
+// Also from Alex Evans: Added RGBA support, linear memory allocator (no longer needed in v1.03).
+// v1.04, May. 19, 2012: Forgot to set m_pFile ptr to NULL in cfile_stream::close(). Thanks to Owen Kaluza for reporting this bug.
+// Code tweaks to fix VS2008 static code analysis warnings (all looked harmless).
+// Code review revealed method load_block_16_8_8() (used for the non-default H2V1 sampling mode to downsample chroma) somehow didn't get the rounding factor fix from v1.02.
+// v1.05, March 25, 2020: Added Apache 2.0 alternate license
+
+#include "jpge.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define JPGE_MAX(a,b) (((a)>(b))?(a):(b))
+#define JPGE_MIN(a,b) (((a)<(b))?(a):(b))
+
+namespace jpge {
+
+ static inline void* jpge_malloc(size_t nSize) { return malloc(nSize); }
+ static inline void jpge_free(void* p) { free(p); }
+
+ // Various JPEG enums and tables.
+ enum { M_SOF0 = 0xC0, M_DHT = 0xC4, M_SOI = 0xD8, M_EOI = 0xD9, M_SOS = 0xDA, M_DQT = 0xDB, M_APP0 = 0xE0 };
+ enum { DC_LUM_CODES = 12, AC_LUM_CODES = 256, DC_CHROMA_CODES = 12, AC_CHROMA_CODES = 256, MAX_HUFF_SYMBOLS = 257, MAX_HUFF_CODESIZE = 32 };
+
+ static uint8 s_zag[64] = { 0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63 };
+ static int16 s_std_lum_quant[64] = { 16,11,12,14,12,10,16,14,13,14,18,17,16,19,24,40,26,24,22,22,24,49,35,37,29,40,58,51,61,60,57,51,56,55,64,72,92,78,64,68,87,69,55,56,80,109,81,87,95,98,103,104,103,62,77,113,121,112,100,120,92,101,103,99 };
+ static int16 s_std_croma_quant[64] = { 17,18,18,24,21,24,47,26,26,47,99,66,56,66,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99 };
+
+ // Table from http://www.imagemagick.org/discourse-server/viewtopic.php?f=22&t=20333&p=98008#p98008
+ // This is mozjpeg's default table, in zag order.
+ static int16 s_alt_quant[64] = { 16,16,16,16,17,16,18,20,20,18,25,27,24,27,25,37,34,31,31,34,37,56,40,43,40,43,40,56,85,53,62,53,53,62,53,85,75,91,74,69,74,91,75,135,106,94,94,106,135,156,131,124,131,156,189,169,169,189,238,226,238,311,311,418 };
+
+ static uint8 s_dc_lum_bits[17] = { 0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0 };
+ static uint8 s_dc_lum_val[DC_LUM_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
+ static uint8 s_ac_lum_bits[17] = { 0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d };
+ static uint8 s_ac_lum_val[AC_LUM_CODES] =
+ {
+ 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,
+ 0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,
+ 0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
+ 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,
+ 0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
+ 0xf9,0xfa
+ };
+ static uint8 s_dc_chroma_bits[17] = { 0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };
+ static uint8 s_dc_chroma_val[DC_CHROMA_CODES] = { 0,1,2,3,4,5,6,7,8,9,10,11 };
+ static uint8 s_ac_chroma_bits[17] = { 0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77 };
+ static uint8 s_ac_chroma_val[AC_CHROMA_CODES] =
+ {
+ 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,
+ 0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,
+ 0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,
+ 0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,
+ 0xf9,0xfa
+ };
+
+ // Low-level helper functions.
+ template <class T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }
+
+ const int YR = 19595, YG = 38470, YB = 7471, CB_R = -11059, CB_G = -21709, CB_B = 32768, CR_R = 32768, CR_G = -27439, CR_B = -5329;
+ static inline uint8 clamp(int i) { if (static_cast<uint>(i) > 255U) { if (i < 0) i = 0; else if (i > 255) i = 255; } return static_cast<uint8>(i); }
+
+ static inline int left_shifti(int val, uint32 bits)
+ {
+ return static_cast<int>(static_cast<uint32>(val) << bits);
+ }
+
+ static void RGB_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels)
+ {
+ for (; num_pixels; pDst += 3, pSrc += 3, num_pixels--)
+ {
+ const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
+ pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
+ pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
+ pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
+ }
+ }
+
+ static void RGB_to_Y(uint8* pDst, const uint8* pSrc, int num_pixels)
+ {
+ for (; num_pixels; pDst++, pSrc += 3, num_pixels--)
+ pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
+ }
+
+ static void RGBA_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels)
+ {
+ for (; num_pixels; pDst += 3, pSrc += 4, num_pixels--)
+ {
+ const int r = pSrc[0], g = pSrc[1], b = pSrc[2];
+ pDst[0] = static_cast<uint8>((r * YR + g * YG + b * YB + 32768) >> 16);
+ pDst[1] = clamp(128 + ((r * CB_R + g * CB_G + b * CB_B + 32768) >> 16));
+ pDst[2] = clamp(128 + ((r * CR_R + g * CR_G + b * CR_B + 32768) >> 16));
+ }
+ }
+
+ static void RGBA_to_Y(uint8* pDst, const uint8* pSrc, int num_pixels)
+ {
+ for (; num_pixels; pDst++, pSrc += 4, num_pixels--)
+ pDst[0] = static_cast<uint8>((pSrc[0] * YR + pSrc[1] * YG + pSrc[2] * YB + 32768) >> 16);
+ }
+
+ static void Y_to_YCC(uint8* pDst, const uint8* pSrc, int num_pixels)
+ {
+ for (; num_pixels; pDst += 3, pSrc++, num_pixels--) { pDst[0] = pSrc[0]; pDst[1] = 128; pDst[2] = 128; }
+ }
+
+ // Forward DCT - DCT derived from jfdctint.
+ enum { CONST_BITS = 13, ROW_BITS = 2 };
+#define DCT_DESCALE(x, n) (((x) + (((int32)1) << ((n) - 1))) >> (n))
+#define DCT_MUL(var, c) (static_cast<int16>(var) * static_cast<int32>(c))
+#define DCT1D(s0, s1, s2, s3, s4, s5, s6, s7) \
+ int32 t0 = s0 + s7, t7 = s0 - s7, t1 = s1 + s6, t6 = s1 - s6, t2 = s2 + s5, t5 = s2 - s5, t3 = s3 + s4, t4 = s3 - s4; \
+ int32 t10 = t0 + t3, t13 = t0 - t3, t11 = t1 + t2, t12 = t1 - t2; \
+ int32 u1 = DCT_MUL(t12 + t13, 4433); \
+ s2 = u1 + DCT_MUL(t13, 6270); \
+ s6 = u1 + DCT_MUL(t12, -15137); \
+ u1 = t4 + t7; \
+ int32 u2 = t5 + t6, u3 = t4 + t6, u4 = t5 + t7; \
+ int32 z5 = DCT_MUL(u3 + u4, 9633); \
+ t4 = DCT_MUL(t4, 2446); t5 = DCT_MUL(t5, 16819); \
+ t6 = DCT_MUL(t6, 25172); t7 = DCT_MUL(t7, 12299); \
+ u1 = DCT_MUL(u1, -7373); u2 = DCT_MUL(u2, -20995); \
+ u3 = DCT_MUL(u3, -16069); u4 = DCT_MUL(u4, -3196); \
+ u3 += z5; u4 += z5; \
+ s0 = t10 + t11; s1 = t7 + u1 + u4; s3 = t6 + u2 + u3; s4 = t10 - t11; s5 = t5 + u2 + u4; s7 = t4 + u1 + u3;
+
+ static void DCT2D(int32* p)
+ {
+ int32 c, * q = p;
+ for (c = 7; c >= 0; c--, q += 8)
+ {
+ int32 s0 = q[0], s1 = q[1], s2 = q[2], s3 = q[3], s4 = q[4], s5 = q[5], s6 = q[6], s7 = q[7];
+ DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
+ q[0] = left_shifti(s0, ROW_BITS); q[1] = DCT_DESCALE(s1, CONST_BITS - ROW_BITS); q[2] = DCT_DESCALE(s2, CONST_BITS - ROW_BITS); q[3] = DCT_DESCALE(s3, CONST_BITS - ROW_BITS);
+ q[4] = left_shifti(s4, ROW_BITS); q[5] = DCT_DESCALE(s5, CONST_BITS - ROW_BITS); q[6] = DCT_DESCALE(s6, CONST_BITS - ROW_BITS); q[7] = DCT_DESCALE(s7, CONST_BITS - ROW_BITS);
+ }
+ for (q = p, c = 7; c >= 0; c--, q++)
+ {
+ int32 s0 = q[0 * 8], s1 = q[1 * 8], s2 = q[2 * 8], s3 = q[3 * 8], s4 = q[4 * 8], s5 = q[5 * 8], s6 = q[6 * 8], s7 = q[7 * 8];
+ DCT1D(s0, s1, s2, s3, s4, s5, s6, s7);
+ q[0 * 8] = DCT_DESCALE(s0, ROW_BITS + 3); q[1 * 8] = DCT_DESCALE(s1, CONST_BITS + ROW_BITS + 3); q[2 * 8] = DCT_DESCALE(s2, CONST_BITS + ROW_BITS + 3); q[3 * 8] = DCT_DESCALE(s3, CONST_BITS + ROW_BITS + 3);
+ q[4 * 8] = DCT_DESCALE(s4, ROW_BITS + 3); q[5 * 8] = DCT_DESCALE(s5, CONST_BITS + ROW_BITS + 3); q[6 * 8] = DCT_DESCALE(s6, CONST_BITS + ROW_BITS + 3); q[7 * 8] = DCT_DESCALE(s7, CONST_BITS + ROW_BITS + 3);
+ }
+ }
+
+ struct sym_freq { uint m_key, m_sym_index; };
+
+ // Radix sorts sym_freq[] array by 32-bit key m_key. Returns ptr to sorted values.
+ static inline sym_freq* radix_sort_syms(uint num_syms, sym_freq* pSyms0, sym_freq* pSyms1)
+ {
+ const uint cMaxPasses = 4;
+ uint32 hist[256 * cMaxPasses]; clear_obj(hist);
+ for (uint i = 0; i < num_syms; i++) { uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; hist[256 * 2 + ((freq >> 16) & 0xFF)]++; hist[256 * 3 + ((freq >> 24) & 0xFF)]++; }
+ sym_freq* pCur_syms = pSyms0, * pNew_syms = pSyms1;
+ uint total_passes = cMaxPasses; while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--;
+ for (uint pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
+ {
+ const uint32* pHist = &hist[pass << 8];
+ uint offsets[256], cur_ofs = 0;
+ for (uint i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; }
+ for (uint i = 0; i < num_syms; i++)
+ pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
+ sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t;
+ }
+ return pCur_syms;
+ }
+
+ // calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996.
+ static void calculate_minimum_redundancy(sym_freq* A, int n)
+ {
+ int root, leaf, next, avbl, used, dpth;
+ if (n == 0) return; else if (n == 1) { A[0].m_key = 1; return; }
+ A[0].m_key += A[1].m_key; root = 0; leaf = 2;
+ for (next = 1; next < n - 1; next++)
+ {
+ if (leaf >= n || A[root].m_key < A[leaf].m_key) { A[next].m_key = A[root].m_key; A[root++].m_key = next; }
+ else A[next].m_key = A[leaf++].m_key;
+ if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key)) { A[next].m_key += A[root].m_key; A[root++].m_key = next; }
+ else A[next].m_key += A[leaf++].m_key;
+ }
+ A[n - 2].m_key = 0;
+ for (next = n - 3; next >= 0; next--) A[next].m_key = A[A[next].m_key].m_key + 1;
+ avbl = 1; used = dpth = 0; root = n - 2; next = n - 1;
+ while (avbl > 0)
+ {
+ while (root >= 0 && (int)A[root].m_key == dpth) { used++; root--; }
+ while (avbl > used) { A[next--].m_key = dpth; avbl--; }
+ avbl = 2 * used; dpth++; used = 0;
+ }
+ }
+
+ // Limits canonical Huffman code table's max code size to max_code_size.
+ static void huffman_enforce_max_code_size(int* pNum_codes, int code_list_len, int max_code_size)
+ {
+ if (code_list_len <= 1) return;
+
+ for (int i = max_code_size + 1; i <= MAX_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i];
+
+ uint32 total = 0;
+ for (int i = max_code_size; i > 0; i--)
+ total += (((uint32)pNum_codes[i]) << (max_code_size - i));
+
+ while (total != (1UL << max_code_size))
+ {
+ pNum_codes[max_code_size]--;
+ for (int i = max_code_size - 1; i > 0; i--)
+ {
+ if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; }
+ }
+ total--;
+ }
+ }
+
+ // Generates an optimized offman table.
+ void jpeg_encoder::optimize_huffman_table(int table_num, int table_len)
+ {
+ sym_freq syms0[MAX_HUFF_SYMBOLS], syms1[MAX_HUFF_SYMBOLS];
+ syms0[0].m_key = 1; syms0[0].m_sym_index = 0; // dummy symbol, assures that no valid code contains all 1's
+ int num_used_syms = 1;
+ const uint32* pSym_count = &m_huff_count[table_num][0];
+ for (int i = 0; i < table_len; i++)
+ if (pSym_count[i]) { syms0[num_used_syms].m_key = pSym_count[i]; syms0[num_used_syms++].m_sym_index = i + 1; }
+ sym_freq* pSyms = radix_sort_syms(num_used_syms, syms0, syms1);
+ calculate_minimum_redundancy(pSyms, num_used_syms);
+
+ // Count the # of symbols of each code size.
+ int num_codes[1 + MAX_HUFF_CODESIZE]; clear_obj(num_codes);
+ for (int i = 0; i < num_used_syms; i++)
+ num_codes[pSyms[i].m_key]++;
+
+ const uint JPGE_CODE_SIZE_LIMIT = 16; // the maximum possible size of a JPEG Huffman code (valid range is [9,16] - 9 vs. 8 because of the dummy symbol)
+ huffman_enforce_max_code_size(num_codes, num_used_syms, JPGE_CODE_SIZE_LIMIT);
+
+ // Compute m_huff_bits array, which contains the # of symbols per code size.
+ clear_obj(m_huff_bits[table_num]);
+ for (int i = 1; i <= (int)JPGE_CODE_SIZE_LIMIT; i++)
+ m_huff_bits[table_num][i] = static_cast<uint8>(num_codes[i]);
+
+ // Remove the dummy symbol added above, which must be in largest bucket.
+ for (int i = JPGE_CODE_SIZE_LIMIT; i >= 1; i--)
+ {
+ if (m_huff_bits[table_num][i]) { m_huff_bits[table_num][i]--; break; }
+ }
+
+ // Compute the m_huff_val array, which contains the symbol indices sorted by code size (smallest to largest).
+ for (int i = num_used_syms - 1; i >= 1; i--)
+ m_huff_val[table_num][num_used_syms - 1 - i] = static_cast<uint8>(pSyms[i].m_sym_index - 1);
+ }
+
+ // JPEG marker generation.
+ void jpeg_encoder::emit_byte(uint8 i)
+ {
+ m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_obj(i);
+ }
+
+ void jpeg_encoder::emit_word(uint i)
+ {
+ emit_byte(uint8(i >> 8)); emit_byte(uint8(i & 0xFF));
+ }
+
+ void jpeg_encoder::emit_marker(int marker)
+ {
+ emit_byte(uint8(0xFF)); emit_byte(uint8(marker));
+ }
+
+ // Emit JFIF marker
+ void jpeg_encoder::emit_jfif_app0()
+ {
+ emit_marker(M_APP0);
+ emit_word(2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1);
+ emit_byte(0x4A); emit_byte(0x46); emit_byte(0x49); emit_byte(0x46); /* Identifier: ASCII "JFIF" */
+ emit_byte(0);
+ emit_byte(1); /* Major version */
+ emit_byte(1); /* Minor version */
+ emit_byte(0); /* Density unit */
+ emit_word(1);
+ emit_word(1);
+ emit_byte(0); /* No thumbnail image */
+ emit_byte(0);
+ }
+
+ // Emit quantization tables
+ void jpeg_encoder::emit_dqt()
+ {
+ for (int i = 0; i < ((m_num_components == 3) ? 2 : 1); i++)
+ {
+ emit_marker(M_DQT);
+ emit_word(64 + 1 + 2);
+ emit_byte(static_cast<uint8>(i));
+ for (int j = 0; j < 64; j++)
+ emit_byte(static_cast<uint8>(m_quantization_tables[i][j]));
+ }
+ }
+
+ // Emit start of frame marker
+ void jpeg_encoder::emit_sof()
+ {
+ emit_marker(M_SOF0); /* baseline */
+ emit_word(3 * m_num_components + 2 + 5 + 1);
+ emit_byte(8); /* precision */
+ emit_word(m_image_y);
+ emit_word(m_image_x);
+ emit_byte(m_num_components);
+ for (int i = 0; i < m_num_components; i++)
+ {
+ emit_byte(static_cast<uint8>(i + 1)); /* component ID */
+ emit_byte((m_comp_h_samp[i] << 4) + m_comp_v_samp[i]); /* h and v sampling */
+ emit_byte(i > 0); /* quant. table num */
+ }
+ }
+
+ // Emit Huffman table.
+ void jpeg_encoder::emit_dht(uint8* bits, uint8* val, int index, bool ac_flag)
+ {
+ emit_marker(M_DHT);
+
+ int length = 0;
+ for (int i = 1; i <= 16; i++)
+ length += bits[i];
+
+ emit_word(length + 2 + 1 + 16);
+ emit_byte(static_cast<uint8>(index + (ac_flag << 4)));
+
+ for (int i = 1; i <= 16; i++)
+ emit_byte(bits[i]);
+
+ for (int i = 0; i < length; i++)
+ emit_byte(val[i]);
+ }
+
+ // Emit all Huffman tables.
+ void jpeg_encoder::emit_dhts()
+ {
+ emit_dht(m_huff_bits[0 + 0], m_huff_val[0 + 0], 0, false);
+ emit_dht(m_huff_bits[2 + 0], m_huff_val[2 + 0], 0, true);
+ if (m_num_components == 3)
+ {
+ emit_dht(m_huff_bits[0 + 1], m_huff_val[0 + 1], 1, false);
+ emit_dht(m_huff_bits[2 + 1], m_huff_val[2 + 1], 1, true);
+ }
+ }
+
+ // emit start of scan
+ void jpeg_encoder::emit_sos()
+ {
+ emit_marker(M_SOS);
+ emit_word(2 * m_num_components + 2 + 1 + 3);
+ emit_byte(m_num_components);
+ for (int i = 0; i < m_num_components; i++)
+ {
+ emit_byte(static_cast<uint8>(i + 1));
+ if (i == 0)
+ emit_byte((0 << 4) + 0);
+ else
+ emit_byte((1 << 4) + 1);
+ }
+ emit_byte(0); /* spectral selection */
+ emit_byte(63);
+ emit_byte(0);
+ }
+
+ // Emit all markers at beginning of image file.
+ void jpeg_encoder::emit_markers()
+ {
+ emit_marker(M_SOI);
+ emit_jfif_app0();
+ emit_dqt();
+ emit_sof();
+ emit_dhts();
+ emit_sos();
+ }
+
+ // Compute the actual canonical Huffman codes/code sizes given the JPEG huff bits and val arrays.
+ void jpeg_encoder::compute_huffman_table(uint* codes, uint8* code_sizes, uint8* bits, uint8* val)
+ {
+ int i, l, last_p, si;
+ uint8 huff_size[257];
+ uint huff_code[257];
+ uint code;
+
+ int p = 0;
+ for (l = 1; l <= 16; l++)
+ for (i = 1; i <= bits[l]; i++)
+ huff_size[p++] = (char)l;
+
+ huff_size[p] = 0; last_p = p; // write sentinel
+
+ code = 0; si = huff_size[0]; p = 0;
+
+ while (huff_size[p])
+ {
+ while (huff_size[p] == si)
+ huff_code[p++] = code++;
+ code <<= 1;
+ si++;
+ }
+
+ memset(codes, 0, sizeof(codes[0]) * 256);
+ memset(code_sizes, 0, sizeof(code_sizes[0]) * 256);
+ for (p = 0; p < last_p; p++)
+ {
+ codes[val[p]] = huff_code[p];
+ code_sizes[val[p]] = huff_size[p];
+ }
+ }
+
+ // Quantization table generation.
+ void jpeg_encoder::compute_quant_table(int32* pDst, int16* pSrc)
+ {
+ int32 q;
+ if (m_params.m_quality < 50)
+ q = 5000 / m_params.m_quality;
+ else
+ q = 200 - m_params.m_quality * 2;
+ for (int i = 0; i < 64; i++)
+ {
+ int32 j = *pSrc++; j = (j * q + 50L) / 100L;
+ *pDst++ = JPGE_MIN(JPGE_MAX(j, 1), 255);
+ }
+ }
+
+ // Higher-level methods.
+ void jpeg_encoder::first_pass_init()
+ {
+ m_bit_buffer = 0; m_bits_in = 0;
+ memset(m_last_dc_val, 0, 3 * sizeof(m_last_dc_val[0]));
+ m_mcu_y_ofs = 0;
+ m_pass_num = 1;
+ }
+
+ bool jpeg_encoder::second_pass_init()
+ {
+ compute_huffman_table(&m_huff_codes[0 + 0][0], &m_huff_code_sizes[0 + 0][0], m_huff_bits[0 + 0], m_huff_val[0 + 0]);
+ compute_huffman_table(&m_huff_codes[2 + 0][0], &m_huff_code_sizes[2 + 0][0], m_huff_bits[2 + 0], m_huff_val[2 + 0]);
+ if (m_num_components > 1)
+ {
+ compute_huffman_table(&m_huff_codes[0 + 1][0], &m_huff_code_sizes[0 + 1][0], m_huff_bits[0 + 1], m_huff_val[0 + 1]);
+ compute_huffman_table(&m_huff_codes[2 + 1][0], &m_huff_code_sizes[2 + 1][0], m_huff_bits[2 + 1], m_huff_val[2 + 1]);
+ }
+ first_pass_init();
+ emit_markers();
+ m_pass_num = 2;
+ return true;
+ }
+
+ bool jpeg_encoder::jpg_open(int p_x_res, int p_y_res, int src_channels)
+ {
+ m_num_components = 3;
+ switch (m_params.m_subsampling)
+ {
+ case Y_ONLY:
+ {
+ m_num_components = 1;
+ m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
+ m_mcu_x = 8; m_mcu_y = 8;
+ break;
+ }
+ case H1V1:
+ {
+ m_comp_h_samp[0] = 1; m_comp_v_samp[0] = 1;
+ m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
+ m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
+ m_mcu_x = 8; m_mcu_y = 8;
+ break;
+ }
+ case H2V1:
+ {
+ m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 1;
+ m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
+ m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
+ m_mcu_x = 16; m_mcu_y = 8;
+ break;
+ }
+ case H2V2:
+ {
+ m_comp_h_samp[0] = 2; m_comp_v_samp[0] = 2;
+ m_comp_h_samp[1] = 1; m_comp_v_samp[1] = 1;
+ m_comp_h_samp[2] = 1; m_comp_v_samp[2] = 1;
+ m_mcu_x = 16; m_mcu_y = 16;
+ }
+ }
+
+ m_image_x = p_x_res; m_image_y = p_y_res;
+ m_image_bpp = src_channels;
+ m_image_bpl = m_image_x * src_channels;
+ m_image_x_mcu = (m_image_x + m_mcu_x - 1) & (~(m_mcu_x - 1));
+ m_image_y_mcu = (m_image_y + m_mcu_y - 1) & (~(m_mcu_y - 1));
+ m_image_bpl_xlt = m_image_x * m_num_components;
+ m_image_bpl_mcu = m_image_x_mcu * m_num_components;
+ m_mcus_per_row = m_image_x_mcu / m_mcu_x;
+
+ if ((m_mcu_lines[0] = static_cast<uint8*>(jpge_malloc(m_image_bpl_mcu * m_mcu_y))) == NULL) return false;
+ for (int i = 1; i < m_mcu_y; i++)
+ m_mcu_lines[i] = m_mcu_lines[i - 1] + m_image_bpl_mcu;
+
+ if (m_params.m_use_std_tables)
+ {
+ compute_quant_table(m_quantization_tables[0], s_std_lum_quant);
+ compute_quant_table(m_quantization_tables[1], m_params.m_no_chroma_discrim_flag ? s_std_lum_quant : s_std_croma_quant);
+ }
+ else
+ {
+ compute_quant_table(m_quantization_tables[0], s_alt_quant);
+ memcpy(m_quantization_tables[1], m_quantization_tables[0], sizeof(m_quantization_tables[1]));
+ }
+
+ m_out_buf_left = JPGE_OUT_BUF_SIZE;
+ m_pOut_buf = m_out_buf;
+
+ if (m_params.m_two_pass_flag)
+ {
+ clear_obj(m_huff_count);
+ first_pass_init();
+ }
+ else
+ {
+ memcpy(m_huff_bits[0 + 0], s_dc_lum_bits, 17); memcpy(m_huff_val[0 + 0], s_dc_lum_val, DC_LUM_CODES);
+ memcpy(m_huff_bits[2 + 0], s_ac_lum_bits, 17); memcpy(m_huff_val[2 + 0], s_ac_lum_val, AC_LUM_CODES);
+ memcpy(m_huff_bits[0 + 1], s_dc_chroma_bits, 17); memcpy(m_huff_val[0 + 1], s_dc_chroma_val, DC_CHROMA_CODES);
+ memcpy(m_huff_bits[2 + 1], s_ac_chroma_bits, 17); memcpy(m_huff_val[2 + 1], s_ac_chroma_val, AC_CHROMA_CODES);
+ if (!second_pass_init()) return false; // in effect, skip over the first pass
+ }
+ return m_all_stream_writes_succeeded;
+ }
+
+ void jpeg_encoder::load_block_8_8_grey(int x)
+ {
+ uint8* pSrc;
+ sample_array_t* pDst = m_sample_array;
+ x <<= 3;
+ for (int i = 0; i < 8; i++, pDst += 8)
+ {
+ pSrc = m_mcu_lines[i] + x;
+ pDst[0] = pSrc[0] - 128; pDst[1] = pSrc[1] - 128; pDst[2] = pSrc[2] - 128; pDst[3] = pSrc[3] - 128;
+ pDst[4] = pSrc[4] - 128; pDst[5] = pSrc[5] - 128; pDst[6] = pSrc[6] - 128; pDst[7] = pSrc[7] - 128;
+ }
+ }
+
+ void jpeg_encoder::load_block_8_8(int x, int y, int c)
+ {
+ uint8* pSrc;
+ sample_array_t* pDst = m_sample_array;
+ x = (x * (8 * 3)) + c;
+ y <<= 3;
+ for (int i = 0; i < 8; i++, pDst += 8)
+ {
+ pSrc = m_mcu_lines[y + i] + x;
+ pDst[0] = pSrc[0 * 3] - 128; pDst[1] = pSrc[1 * 3] - 128; pDst[2] = pSrc[2 * 3] - 128; pDst[3] = pSrc[3 * 3] - 128;
+ pDst[4] = pSrc[4 * 3] - 128; pDst[5] = pSrc[5 * 3] - 128; pDst[6] = pSrc[6 * 3] - 128; pDst[7] = pSrc[7 * 3] - 128;
+ }
+ }
+
+ void jpeg_encoder::load_block_16_8(int x, int c)
+ {
+ uint8* pSrc1, * pSrc2;
+ sample_array_t* pDst = m_sample_array;
+ x = (x * (16 * 3)) + c;
+ for (int i = 0; i < 16; i += 2, pDst += 8)
+ {
+ pSrc1 = m_mcu_lines[i + 0] + x;
+ pSrc2 = m_mcu_lines[i + 1] + x;
+ pDst[0] = ((pSrc1[0 * 3] + pSrc1[1 * 3] + pSrc2[0 * 3] + pSrc2[1 * 3] + 2) >> 2) - 128; pDst[1] = ((pSrc1[2 * 3] + pSrc1[3 * 3] + pSrc2[2 * 3] + pSrc2[3 * 3] + 2) >> 2) - 128;
+ pDst[2] = ((pSrc1[4 * 3] + pSrc1[5 * 3] + pSrc2[4 * 3] + pSrc2[5 * 3] + 2) >> 2) - 128; pDst[3] = ((pSrc1[6 * 3] + pSrc1[7 * 3] + pSrc2[6 * 3] + pSrc2[7 * 3] + 2) >> 2) - 128;
+ pDst[4] = ((pSrc1[8 * 3] + pSrc1[9 * 3] + pSrc2[8 * 3] + pSrc2[9 * 3] + 2) >> 2) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + pSrc2[10 * 3] + pSrc2[11 * 3] + 2) >> 2) - 128;
+ pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + pSrc2[12 * 3] + pSrc2[13 * 3] + 2) >> 2) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + pSrc2[14 * 3] + pSrc2[15 * 3] + 2) >> 2) - 128;
+ }
+ }
+
+ void jpeg_encoder::load_block_16_8_8(int x, int c)
+ {
+ uint8* pSrc1;
+ sample_array_t* pDst = m_sample_array;
+ x = (x * (16 * 3)) + c;
+ for (int i = 0; i < 8; i++, pDst += 8)
+ {
+ pSrc1 = m_mcu_lines[i + 0] + x;
+ pDst[0] = ((pSrc1[0 * 3] + pSrc1[1 * 3] + 1) >> 1) - 128; pDst[1] = ((pSrc1[2 * 3] + pSrc1[3 * 3] + 1) >> 1) - 128;
+ pDst[2] = ((pSrc1[4 * 3] + pSrc1[5 * 3] + 1) >> 1) - 128; pDst[3] = ((pSrc1[6 * 3] + pSrc1[7 * 3] + 1) >> 1) - 128;
+ pDst[4] = ((pSrc1[8 * 3] + pSrc1[9 * 3] + 1) >> 1) - 128; pDst[5] = ((pSrc1[10 * 3] + pSrc1[11 * 3] + 1) >> 1) - 128;
+ pDst[6] = ((pSrc1[12 * 3] + pSrc1[13 * 3] + 1) >> 1) - 128; pDst[7] = ((pSrc1[14 * 3] + pSrc1[15 * 3] + 1) >> 1) - 128;
+ }
+ }
+
+ void jpeg_encoder::load_quantized_coefficients(int component_num)
+ {
+ int32* q = m_quantization_tables[component_num > 0];
+ int16* pDst = m_coefficient_array;
+ for (int i = 0; i < 64; i++)
+ {
+ sample_array_t j = m_sample_array[s_zag[i]];
+ if (j < 0)
+ {
+ if ((j = -j + (*q >> 1)) < *q)
+ *pDst++ = 0;
+ else
+ *pDst++ = static_cast<int16>(-(j / *q));
+ }
+ else
+ {
+ if ((j = j + (*q >> 1)) < *q)
+ *pDst++ = 0;
+ else
+ *pDst++ = static_cast<int16>((j / *q));
+ }
+ q++;
+ }
+ }
+
+ void jpeg_encoder::flush_output_buffer()
+ {
+ if (m_out_buf_left != JPGE_OUT_BUF_SIZE)
+ m_all_stream_writes_succeeded = m_all_stream_writes_succeeded && m_pStream->put_buf(m_out_buf, JPGE_OUT_BUF_SIZE - m_out_buf_left);
+ m_pOut_buf = m_out_buf;
+ m_out_buf_left = JPGE_OUT_BUF_SIZE;
+ }
+
+ void jpeg_encoder::put_bits(uint bits, uint len)
+ {
+ m_bit_buffer |= ((uint32)bits << (24 - (m_bits_in += len)));
+ while (m_bits_in >= 8)
+ {
+ uint8 c;
+#define JPGE_PUT_BYTE(c) { *m_pOut_buf++ = (c); if (--m_out_buf_left == 0) flush_output_buffer(); }
+ JPGE_PUT_BYTE(c = (uint8)((m_bit_buffer >> 16) & 0xFF));
+ if (c == 0xFF) JPGE_PUT_BYTE(0);
+ m_bit_buffer <<= 8;
+ m_bits_in -= 8;
+ }
+ }
+
+ void jpeg_encoder::code_coefficients_pass_one(int component_num)
+ {
+ if (component_num >= 3) return; // just to shut up static analysis
+ int i, run_len, nbits, temp1;
+ int16* src = m_coefficient_array;
+ uint32* dc_count = component_num ? m_huff_count[0 + 1] : m_huff_count[0 + 0], * ac_count = component_num ? m_huff_count[2 + 1] : m_huff_count[2 + 0];
+
+ temp1 = src[0] - m_last_dc_val[component_num];
+ m_last_dc_val[component_num] = src[0];
+ if (temp1 < 0) temp1 = -temp1;
+
+ nbits = 0;
+ while (temp1)
+ {
+ nbits++; temp1 >>= 1;
+ }
+
+ dc_count[nbits]++;
+ for (run_len = 0, i = 1; i < 64; i++)
+ {
+ if ((temp1 = m_coefficient_array[i]) == 0)
+ run_len++;
+ else
+ {
+ while (run_len >= 16)
+ {
+ ac_count[0xF0]++;
+ run_len -= 16;
+ }
+ if (temp1 < 0) temp1 = -temp1;
+ nbits = 1;
+ while (temp1 >>= 1) nbits++;
+ ac_count[(run_len << 4) + nbits]++;
+ run_len = 0;
+ }
+ }
+ if (run_len) ac_count[0]++;
+ }
+
+ void jpeg_encoder::code_coefficients_pass_two(int component_num)
+ {
+ int i, j, run_len, nbits, temp1, temp2;
+ int16* pSrc = m_coefficient_array;
+ uint* codes[2];
+ uint8* code_sizes[2];
+
+ if (component_num == 0)
+ {
+ codes[0] = m_huff_codes[0 + 0]; codes[1] = m_huff_codes[2 + 0];
+ code_sizes[0] = m_huff_code_sizes[0 + 0]; code_sizes[1] = m_huff_code_sizes[2 + 0];
+ }
+ else
+ {
+ codes[0] = m_huff_codes[0 + 1]; codes[1] = m_huff_codes[2 + 1];
+ code_sizes[0] = m_huff_code_sizes[0 + 1]; code_sizes[1] = m_huff_code_sizes[2 + 1];
+ }
+
+ temp1 = temp2 = pSrc[0] - m_last_dc_val[component_num];
+ m_last_dc_val[component_num] = pSrc[0];
+
+ if (temp1 < 0)
+ {
+ temp1 = -temp1; temp2--;
+ }
+
+ nbits = 0;
+ while (temp1)
+ {
+ nbits++; temp1 >>= 1;
+ }
+
+ put_bits(codes[0][nbits], code_sizes[0][nbits]);
+ if (nbits) put_bits(temp2 & ((1 << nbits) - 1), nbits);
+
+ for (run_len = 0, i = 1; i < 64; i++)
+ {
+ if ((temp1 = m_coefficient_array[i]) == 0)
+ run_len++;
+ else
+ {
+ while (run_len >= 16)
+ {
+ put_bits(codes[1][0xF0], code_sizes[1][0xF0]);
+ run_len -= 16;
+ }
+ if ((temp2 = temp1) < 0)
+ {
+ temp1 = -temp1;
+ temp2--;
+ }
+ nbits = 1;
+ while (temp1 >>= 1)
+ nbits++;
+ j = (run_len << 4) + nbits;
+ put_bits(codes[1][j], code_sizes[1][j]);
+ put_bits(temp2 & ((1 << nbits) - 1), nbits);
+ run_len = 0;
+ }
+ }
+ if (run_len)
+ put_bits(codes[1][0], code_sizes[1][0]);
+ }
+
+ void jpeg_encoder::code_block(int component_num)
+ {
+ DCT2D(m_sample_array);
+ load_quantized_coefficients(component_num);
+ if (m_pass_num == 1)
+ code_coefficients_pass_one(component_num);
+ else
+ code_coefficients_pass_two(component_num);
+ }
+
+ void jpeg_encoder::process_mcu_row()
+ {
+ if (m_num_components == 1)
+ {
+ for (int i = 0; i < m_mcus_per_row; i++)
+ {
+ load_block_8_8_grey(i); code_block(0);
+ }
+ }
+ else if ((m_comp_h_samp[0] == 1) && (m_comp_v_samp[0] == 1))
+ {
+ for (int i = 0; i < m_mcus_per_row; i++)
+ {
+ load_block_8_8(i, 0, 0); code_block(0); load_block_8_8(i, 0, 1); code_block(1); load_block_8_8(i, 0, 2); code_block(2);
+ }
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 1))
+ {
+ for (int i = 0; i < m_mcus_per_row; i++)
+ {
+ load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
+ load_block_16_8_8(i, 1); code_block(1); load_block_16_8_8(i, 2); code_block(2);
+ }
+ }
+ else if ((m_comp_h_samp[0] == 2) && (m_comp_v_samp[0] == 2))
+ {
+ for (int i = 0; i < m_mcus_per_row; i++)
+ {
+ load_block_8_8(i * 2 + 0, 0, 0); code_block(0); load_block_8_8(i * 2 + 1, 0, 0); code_block(0);
+ load_block_8_8(i * 2 + 0, 1, 0); code_block(0); load_block_8_8(i * 2 + 1, 1, 0); code_block(0);
+ load_block_16_8(i, 1); code_block(1); load_block_16_8(i, 2); code_block(2);
+ }
+ }
+ }
+
+ bool jpeg_encoder::terminate_pass_one()
+ {
+ optimize_huffman_table(0 + 0, DC_LUM_CODES); optimize_huffman_table(2 + 0, AC_LUM_CODES);
+ if (m_num_components > 1)
+ {
+ optimize_huffman_table(0 + 1, DC_CHROMA_CODES); optimize_huffman_table(2 + 1, AC_CHROMA_CODES);
+ }
+ return second_pass_init();
+ }
+
+ bool jpeg_encoder::terminate_pass_two()
+ {
+ put_bits(0x7F, 7);
+ flush_output_buffer();
+ emit_marker(M_EOI);
+ m_pass_num++; // purposely bump up m_pass_num, for debugging
+ return true;
+ }
+
+ bool jpeg_encoder::process_end_of_image()
+ {
+ if (m_mcu_y_ofs)
+ {
+ if (m_mcu_y_ofs < 16) // check here just to shut up static analysis
+ {
+ for (int i = m_mcu_y_ofs; i < m_mcu_y; i++)
+ memcpy(m_mcu_lines[i], m_mcu_lines[m_mcu_y_ofs - 1], m_image_bpl_mcu);
+ }
+
+ process_mcu_row();
+ }
+
+ if (m_pass_num == 1)
+ return terminate_pass_one();
+ else
+ return terminate_pass_two();
+ }
+
+ void jpeg_encoder::load_mcu(const void* pSrc)
+ {
+ const uint8* Psrc = reinterpret_cast<const uint8*>(pSrc);
+
+ uint8* pDst = m_mcu_lines[m_mcu_y_ofs]; // OK to write up to m_image_bpl_xlt bytes to pDst
+
+ if (m_num_components == 1)
+ {
+ if (m_image_bpp == 4)
+ RGBA_to_Y(pDst, Psrc, m_image_x);
+ else if (m_image_bpp == 3)
+ RGB_to_Y(pDst, Psrc, m_image_x);
+ else
+ memcpy(pDst, Psrc, m_image_x);
+ }
+ else
+ {
+ if (m_image_bpp == 4)
+ RGBA_to_YCC(pDst, Psrc, m_image_x);
+ else if (m_image_bpp == 3)
+ RGB_to_YCC(pDst, Psrc, m_image_x);
+ else
+ Y_to_YCC(pDst, Psrc, m_image_x);
+ }
+
+ // Possibly duplicate pixels at end of scanline if not a multiple of 8 or 16
+ if (m_num_components == 1)
+ memset(m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt, pDst[m_image_bpl_xlt - 1], m_image_x_mcu - m_image_x);
+ else
+ {
+ const uint8 y = pDst[m_image_bpl_xlt - 3 + 0], cb = pDst[m_image_bpl_xlt - 3 + 1], cr = pDst[m_image_bpl_xlt - 3 + 2];
+ uint8* q = m_mcu_lines[m_mcu_y_ofs] + m_image_bpl_xlt;
+ for (int i = m_image_x; i < m_image_x_mcu; i++)
+ {
+ *q++ = y; *q++ = cb; *q++ = cr;
+ }
+ }
+
+ if (++m_mcu_y_ofs == m_mcu_y)
+ {
+ process_mcu_row();
+ m_mcu_y_ofs = 0;
+ }
+ }
+
+ void jpeg_encoder::clear()
+ {
+ m_mcu_lines[0] = NULL;
+ m_pass_num = 0;
+ m_all_stream_writes_succeeded = true;
+ }
+
+ jpeg_encoder::jpeg_encoder()
+ {
+ clear();
+ }
+
+ jpeg_encoder::~jpeg_encoder()
+ {
+ deinit();
+ }
+
+ bool jpeg_encoder::init(output_stream* pStream, int width, int height, int src_channels, const params& comp_params)
+ {
+ deinit();
+ if (((!pStream) || (width < 1) || (height < 1)) || ((src_channels != 1) && (src_channels != 3) && (src_channels != 4)) || (!comp_params.check())) return false;
+ m_pStream = pStream;
+ m_params = comp_params;
+ return jpg_open(width, height, src_channels);
+ }
+
+ void jpeg_encoder::deinit()
+ {
+ jpge_free(m_mcu_lines[0]);
+ clear();
+ }
+
+ bool jpeg_encoder::process_scanline(const void* pScanline)
+ {
+ if ((m_pass_num < 1) || (m_pass_num > 2)) return false;
+ if (m_all_stream_writes_succeeded)
+ {
+ if (!pScanline)
+ {
+ if (!process_end_of_image()) return false;
+ }
+ else
+ {
+ load_mcu(pScanline);
+ }
+ }
+ return m_all_stream_writes_succeeded;
+ }
+
+ // Higher level wrappers/examples (optional).
+#include <stdio.h>
+
+ class cfile_stream : public output_stream
+ {
+ cfile_stream(const cfile_stream&);
+ cfile_stream& operator= (const cfile_stream&);
+
+ FILE* m_pFile;
+ bool m_bStatus;
+
+ public:
+ cfile_stream() : m_pFile(NULL), m_bStatus(false) { }
+
+ virtual ~cfile_stream()
+ {
+ close();
+ }
+
+ bool open(const char* pFilename)
+ {
+ close();
+ m_pFile = fopen(pFilename, "wb");
+ m_bStatus = (m_pFile != NULL);
+ return m_bStatus;
+ }
+
+ bool close()
+ {
+ if (m_pFile)
+ {
+ if (fclose(m_pFile) == EOF)
+ {
+ m_bStatus = false;
+ }
+ m_pFile = NULL;
+ }
+ return m_bStatus;
+ }
+
+ virtual bool put_buf(const void* pBuf, int len)
+ {
+ m_bStatus = m_bStatus && (fwrite(pBuf, len, 1, m_pFile) == 1);
+ return m_bStatus;
+ }
+
+ uint get_size() const
+ {
+ return m_pFile ? ftell(m_pFile) : 0;
+ }
+ };
+
+ // Writes JPEG image to file.
+ bool compress_image_to_jpeg_file(const char* pFilename, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params)
+ {
+ cfile_stream dst_stream;
+ if (!dst_stream.open(pFilename))
+ return false;
+
+ jpge::jpeg_encoder dst_image;
+ if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
+ return false;
+
+ for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
+ {
+ for (int i = 0; i < height; i++)
+ {
+ const uint8* pBuf = pImage_data + i * width * num_channels;
+ if (!dst_image.process_scanline(pBuf))
+ return false;
+ }
+ if (!dst_image.process_scanline(NULL))
+ return false;
+ }
+
+ dst_image.deinit();
+
+ return dst_stream.close();
+ }
+
+ class memory_stream : public output_stream
+ {
+ memory_stream(const memory_stream&);
+ memory_stream& operator= (const memory_stream&);
+
+ uint8* m_pBuf;
+ uint m_buf_size, m_buf_ofs;
+
+ public:
+ memory_stream(void* pBuf, uint buf_size) : m_pBuf(static_cast<uint8*>(pBuf)), m_buf_size(buf_size), m_buf_ofs(0) { }
+
+ virtual ~memory_stream() { }
+
+ virtual bool put_buf(const void* pBuf, int len)
+ {
+ uint buf_remaining = m_buf_size - m_buf_ofs;
+ if ((uint)len > buf_remaining)
+ return false;
+ memcpy(m_pBuf + m_buf_ofs, pBuf, len);
+ m_buf_ofs += len;
+ return true;
+ }
+
+ uint get_size() const
+ {
+ return m_buf_ofs;
+ }
+ };
+
+ bool compress_image_to_jpeg_file_in_memory(void* pDstBuf, int& buf_size, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params)
+ {
+ if ((!pDstBuf) || (!buf_size))
+ return false;
+
+ memory_stream dst_stream(pDstBuf, buf_size);
+
+ buf_size = 0;
+
+ jpge::jpeg_encoder dst_image;
+ if (!dst_image.init(&dst_stream, width, height, num_channels, comp_params))
+ return false;
+
+ for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
+ {
+ for (int i = 0; i < height; i++)
+ {
+ const uint8* pScanline = pImage_data + i * width * num_channels;
+ if (!dst_image.process_scanline(pScanline))
+ return false;
+ }
+ if (!dst_image.process_scanline(NULL))
+ return false;
+ }
+
+ dst_image.deinit();
+
+ buf_size = dst_stream.get_size();
+ return true;
+ }
+
+} // namespace jpge
+
diff --git a/thirdparty/jpeg-compressor/jpge.h b/thirdparty/jpeg-compressor/jpge.h
new file mode 100644
index 0000000000..d10510e553
--- /dev/null
+++ b/thirdparty/jpeg-compressor/jpge.h
@@ -0,0 +1,174 @@
+// jpge.h - C++ class for JPEG compression.
+// Public Domain or Apache 2.0, Richard Geldreich <richgel99@gmail.com>
+// Alex Evans: Added RGBA support, linear memory allocator.
+#ifndef JPEG_ENCODER_H
+#define JPEG_ENCODER_H
+
+namespace jpge
+{
+ typedef unsigned char uint8;
+ typedef signed short int16;
+ typedef signed int int32;
+ typedef unsigned short uint16;
+ typedef unsigned int uint32;
+ typedef unsigned int uint;
+
+ // JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color images) are the most common.
+ enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 };
+
+ // JPEG compression parameters structure.
+ struct params
+ {
+ inline params() : m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false), m_two_pass_flag(false), m_use_std_tables(false) { }
+
+ inline bool check() const
+ {
+ if ((m_quality < 1) || (m_quality > 100)) return false;
+ if ((uint)m_subsampling > (uint)H2V2) return false;
+ return true;
+ }
+
+ // Quality: 1-100, higher is better. Typical values are around 50-95.
+ int m_quality;
+
+ // m_subsampling:
+ // 0 = Y (grayscale) only
+ // 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU)
+ // 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU)
+ // 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common)
+ subsampling_t m_subsampling;
+
+ // Disables CbCr discrimination - only intended for testing.
+ // If true, the Y quantization table is also used for the CbCr channels.
+ bool m_no_chroma_discrim_flag;
+
+ bool m_two_pass_flag;
+
+ // By default we use the same quantization tables as mozjpeg's default.
+ // Set to true to use the traditional tables from JPEG Annex K.
+ bool m_use_std_tables;
+ };
+
+ // Writes JPEG image to a file.
+ // num_channels must be 1 (Y) or 3 (RGB), image pitch must be width*num_channels.
+ bool compress_image_to_jpeg_file(const char* pFilename, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params = params());
+
+ // Writes JPEG image to memory buffer.
+ // On entry, buf_size is the size of the output buffer pointed at by pBuf, which should be at least ~1024 bytes.
+ // If return value is true, buf_size will be set to the size of the compressed data.
+ bool compress_image_to_jpeg_file_in_memory(void* pBuf, int& buf_size, int width, int height, int num_channels, const uint8* pImage_data, const params& comp_params = params());
+
+ // Output stream abstract class - used by the jpeg_encoder class to write to the output stream.
+ // put_buf() is generally called with len==JPGE_OUT_BUF_SIZE bytes, but for headers it'll be called with smaller amounts.
+ class output_stream
+ {
+ public:
+ virtual ~output_stream() { };
+ virtual bool put_buf(const void* Pbuf, int len) = 0;
+ template<class T> inline bool put_obj(const T& obj) { return put_buf(&obj, sizeof(T)); }
+ };
+
+ // Lower level jpeg_encoder class - useful if more control is needed than the above helper functions.
+ class jpeg_encoder
+ {
+ public:
+ jpeg_encoder();
+ ~jpeg_encoder();
+
+ // Initializes the compressor.
+ // pStream: The stream object to use for writing compressed data.
+ // params - Compression parameters structure, defined above.
+ // width, height - Image dimensions.
+ // channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source data.
+ // Returns false on out of memory or if a stream write fails.
+ bool init(output_stream* pStream, int width, int height, int src_channels, const params& comp_params = params());
+
+ const params& get_params() const { return m_params; }
+
+ // Deinitializes the compressor, freeing any allocated memory. May be called at any time.
+ void deinit();
+
+ uint get_total_passes() const { return m_params.m_two_pass_flag ? 2 : 1; }
+ inline uint get_cur_pass() { return m_pass_num; }
+
+ // Call this method with each source scanline.
+ // width * src_channels bytes per scanline is expected (RGB or Y format).
+ // You must call with NULL after all scanlines are processed to finish compression.
+ // Returns false on out of memory or if a stream write fails.
+ bool process_scanline(const void* pScanline);
+
+ private:
+ jpeg_encoder(const jpeg_encoder&);
+ jpeg_encoder& operator =(const jpeg_encoder&);
+
+ typedef int32 sample_array_t;
+
+ output_stream* m_pStream;
+ params m_params;
+ uint8 m_num_components;
+ uint8 m_comp_h_samp[3], m_comp_v_samp[3];
+ int m_image_x, m_image_y, m_image_bpp, m_image_bpl;
+ int m_image_x_mcu, m_image_y_mcu;
+ int m_image_bpl_xlt, m_image_bpl_mcu;
+ int m_mcus_per_row;
+ int m_mcu_x, m_mcu_y;
+ uint8* m_mcu_lines[16];
+ uint8 m_mcu_y_ofs;
+ sample_array_t m_sample_array[64];
+ int16 m_coefficient_array[64];
+ int32 m_quantization_tables[2][64];
+ uint m_huff_codes[4][256];
+ uint8 m_huff_code_sizes[4][256];
+ uint8 m_huff_bits[4][17];
+ uint8 m_huff_val[4][256];
+ uint32 m_huff_count[4][256];
+ int m_last_dc_val[3];
+ enum { JPGE_OUT_BUF_SIZE = 2048 };
+ uint8 m_out_buf[JPGE_OUT_BUF_SIZE];
+ uint8* m_pOut_buf;
+ uint m_out_buf_left;
+ uint32 m_bit_buffer;
+ uint m_bits_in;
+ uint8 m_pass_num;
+ bool m_all_stream_writes_succeeded;
+
+ void optimize_huffman_table(int table_num, int table_len);
+ void emit_byte(uint8 i);
+ void emit_word(uint i);
+ void emit_marker(int marker);
+ void emit_jfif_app0();
+ void emit_dqt();
+ void emit_sof();
+ void emit_dht(uint8* bits, uint8* val, int index, bool ac_flag);
+ void emit_dhts();
+ void emit_sos();
+ void emit_markers();
+ void compute_huffman_table(uint* codes, uint8* code_sizes, uint8* bits, uint8* val);
+ void compute_quant_table(int32* dst, int16* src);
+ void adjust_quant_table(int32* dst, int32* src);
+ void first_pass_init();
+ bool second_pass_init();
+ bool jpg_open(int p_x_res, int p_y_res, int src_channels);
+ void load_block_8_8_grey(int x);
+ void load_block_8_8(int x, int y, int c);
+ void load_block_16_8(int x, int c);
+ void load_block_16_8_8(int x, int c);
+ void load_quantized_coefficients(int component_num);
+ void flush_output_buffer();
+ void put_bits(uint bits, uint len);
+ void code_coefficients_pass_one(int component_num);
+ void code_coefficients_pass_two(int component_num);
+ void code_block(int component_num);
+ void process_mcu_row();
+ bool terminate_pass_one();
+ bool terminate_pass_two();
+ bool process_end_of_image();
+ void load_mcu(const void* src);
+ void clear();
+ void init();
+ };
+
+} // namespace jpge
+
+#endif // JPEG_ENCODER
+
diff --git a/thirdparty/mbedtls/LICENSE b/thirdparty/mbedtls/LICENSE
index e15ea821d2..d645695673 100644
--- a/thirdparty/mbedtls/LICENSE
+++ b/thirdparty/mbedtls/LICENSE
@@ -1,5 +1,202 @@
-Unless specifically indicated otherwise in a file, Mbed TLS files are provided
-under the Apache License 2.0, or the GNU General Public License v2.0 or later
-(SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later).
-A copy of these licenses can be found in apache-2.0.txt and gpl-2.0.txt
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/thirdparty/mbedtls/include/godot_core_mbedtls_config.h b/thirdparty/mbedtls/include/godot_core_mbedtls_config.h
index 0e90a98886..9e7b2742a7 100644
--- a/thirdparty/mbedtls/include/godot_core_mbedtls_config.h
+++ b/thirdparty/mbedtls/include/godot_core_mbedtls_config.h
@@ -7,7 +7,12 @@
#define MBEDTLS_AES_C
#define MBEDTLS_BASE64_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ENTROPY_C
#define MBEDTLS_MD5_C
#define MBEDTLS_SHA1_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_PLATFORM_ZEROIZE_ALT
+#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+#include <limits.h>
diff --git a/thirdparty/mbedtls/include/mbedtls/aes.h b/thirdparty/mbedtls/include/mbedtls/aes.h
index e280dbb1c6..401ac39de8 100644
--- a/thirdparty/mbedtls/include/mbedtls/aes.h
+++ b/thirdparty/mbedtls/include/mbedtls/aes.h
@@ -564,7 +564,7 @@ int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
* for example, with 96-bit random nonces, you should not encrypt
* more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that an AES block is 16 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/aria.h b/thirdparty/mbedtls/include/mbedtls/aria.h
index 226e2dbf3c..d294c47f2d 100644
--- a/thirdparty/mbedtls/include/mbedtls/aria.h
+++ b/thirdparty/mbedtls/include/mbedtls/aria.h
@@ -44,7 +44,7 @@
#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */
-#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */
+#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maximum number of rounds in ARIA. */
#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -321,7 +321,7 @@ int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx,
* for example, with 96-bit random nonces, you should not encrypt
* more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that an ARIA block is 16 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/asn1.h b/thirdparty/mbedtls/include/mbedtls/asn1.h
index 10f7905b7e..5117fc7a41 100644
--- a/thirdparty/mbedtls/include/mbedtls/asn1.h
+++ b/thirdparty/mbedtls/include/mbedtls/asn1.h
@@ -61,7 +61,7 @@
/** Buffer too small when writing ASN.1 data structure. */
#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C
-/* \} name */
+/** \} name ASN1 Error codes */
/**
* \name DER constants
@@ -121,8 +121,7 @@
#define MBEDTLS_ASN1_TAG_PC_MASK 0x20
#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F
-/* \} name */
-/* \} addtogroup asn1_module */
+/** \} name DER constants */
/** Returns the size of the binary string, without the trailing \\0 */
#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1)
@@ -210,7 +209,7 @@ mbedtls_asn1_named_data;
* \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* would end beyond \p end.
- * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.
*/
int mbedtls_asn1_get_len( unsigned char **p,
const unsigned char *end,
@@ -235,7 +234,7 @@ int mbedtls_asn1_get_len( unsigned char **p,
* with the requested tag.
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* would end beyond \p end.
- * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
+ * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparsable.
*/
int mbedtls_asn1_get_tag( unsigned char **p,
const unsigned char *end,
@@ -607,6 +606,9 @@ void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
*/
void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
+/** \} name Functions to parse ASN.1 data structures */
+/** \} addtogroup asn1_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/bignum.h b/thirdparty/mbedtls/include/mbedtls/bignum.h
index 9d2cff3275..dd594c512d 100644
--- a/thirdparty/mbedtls/include/mbedtls/bignum.h
+++ b/thirdparty/mbedtls/include/mbedtls/bignum.h
@@ -989,7 +989,7 @@ MBEDTLS_DEPRECATED int mbedtls_mpi_is_prime( const mbedtls_mpi *X,
* generate yourself and that are supposed to be prime, then
* \p rounds should be at least the half of the security
* strength of the cryptographic algorithm. On the other hand,
- * if \p X is chosen uniformly or non-adversially (as is the
+ * if \p X is chosen uniformly or non-adversarially (as is the
* case when mbedtls_mpi_gen_prime calls this function), then
* \p rounds can be much lower.
*
diff --git a/thirdparty/mbedtls/include/mbedtls/blowfish.h b/thirdparty/mbedtls/include/mbedtls/blowfish.h
index 77dca70d31..d5f809921f 100644
--- a/thirdparty/mbedtls/include/mbedtls/blowfish.h
+++ b/thirdparty/mbedtls/include/mbedtls/blowfish.h
@@ -185,7 +185,7 @@ int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
* #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
* #MBEDTLS_BLOWFISH_DECRYPT for decryption.
* \param length The length of the input data in Bytes.
- * \param iv_off The offset in the initialiation vector.
+ * \param iv_off The offset in the initialization vector.
* The value pointed to must be smaller than \c 8 Bytes.
* It is updated by this function to support the aforementioned
* streaming usage.
@@ -246,7 +246,7 @@ int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
* The recommended way to ensure uniqueness is to use a message
* counter.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that a Blowfish block is 8 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/camellia.h b/thirdparty/mbedtls/include/mbedtls/camellia.h
index 925a623e47..d39d932fa2 100644
--- a/thirdparty/mbedtls/include/mbedtls/camellia.h
+++ b/thirdparty/mbedtls/include/mbedtls/camellia.h
@@ -273,7 +273,7 @@ int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
* encrypted: for example, with 96-bit random nonces, you should
* not encrypt more than 2**32 messages with the same key.
*
- * Note that for both stategies, sizes are measured in blocks and
+ * Note that for both strategies, sizes are measured in blocks and
* that a CAMELLIA block is \c 16 Bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
diff --git a/thirdparty/mbedtls/include/mbedtls/chachapoly.h b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
index c4ec7b5f2a..ed568bc98b 100644
--- a/thirdparty/mbedtls/include/mbedtls/chachapoly.h
+++ b/thirdparty/mbedtls/include/mbedtls/chachapoly.h
@@ -161,7 +161,7 @@ int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
* \param ctx The ChaCha20-Poly1305 context. This must be initialized
* and bound to a key.
* \param nonce The nonce/IV to use for the message.
- * This must be a redable buffer of length \c 12 Bytes.
+ * This must be a readable buffer of length \c 12 Bytes.
* \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
* #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
*
diff --git a/thirdparty/mbedtls/include/mbedtls/check_config.h b/thirdparty/mbedtls/include/mbedtls/check_config.h
index 396fe7dfc2..be5c548e56 100644
--- a/thirdparty/mbedtls/include/mbedtls/check_config.h
+++ b/thirdparty/mbedtls/include/mbedtls/check_config.h
@@ -173,7 +173,11 @@
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
-#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
+#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PKCS5_C) && !defined(MBEDTLS_MD_C)
+#error "MBEDTLS_PKCS5_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
@@ -214,11 +218,32 @@
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too"
#endif
+#if defined(MBEDTLS_CCM_C) && ( \
+ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+#error "MBEDTLS_CCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C)
+#error "MBEDTLS_CCM_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_GCM_C) && ( \
- !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+ !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
+#error "MBEDTLS_GCM_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C)
#error "MBEDTLS_GCM_C defined, but not all prerequisites"
#endif
+#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_CHACHA20_C)
+#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C) && !defined(MBEDTLS_POLY1305_C)
+#error "MBEDTLS_CHACHAPOLY_C defined, but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites"
#endif
@@ -338,11 +363,11 @@
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites"
+#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites"
+#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
@@ -619,6 +644,18 @@
#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO."
#endif
+#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO) && \
+ !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_ECDSA_C)
+#error "MBEDTLS_PK_C in configuration with MBEDTLS_USE_PSA_CRYPTO and \
+ MBEDTLS_ECDSA_C requires MBEDTLS_PK_WRITE_C to be defined."
+#endif
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V15) && \
+ !defined(MBEDTLS_PK_WRITE_C) && defined(MBEDTLS_PSA_CRYPTO_C)
+#error "MBEDTLS_PSA_CRYPTO_C, MBEDTLS_RSA_C and MBEDTLS_PKCS1_V15 defined, \
+ but not all prerequisites"
+#endif
+
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites"
@@ -761,14 +798,14 @@
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites"
+#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
!defined(MBEDTLS_SSL_PROTO_TLS1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites"
+#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/config.h b/thirdparty/mbedtls/include/mbedtls/config.h
index 87b4e9192e..1cd6eb6634 100644
--- a/thirdparty/mbedtls/include/mbedtls/config.h
+++ b/thirdparty/mbedtls/include/mbedtls/config.h
@@ -128,7 +128,12 @@
* MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and
* MBEDTLS_PLATFORM_STD_TIME.
*
- * Comment if your system does not support time functions
+ * Comment if your system does not support time functions.
+ *
+ * \note If MBEDTLS_TIMING_C is set - to enable the semi-portable timing
+ * interface - timing.c will include time.h on suitable platforms
+ * regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ * MBEDTLS_TIMING_ALT is used. See timing.c for more information.
*/
#define MBEDTLS_HAVE_TIME
@@ -321,7 +326,7 @@
*/
//#define MBEDTLS_CHECK_PARAMS_ASSERT
-/* \} name SECTION: System support */
+/** \} name SECTION: System support */
/**
* \name SECTION: mbed TLS feature support
@@ -395,7 +400,7 @@
//#define MBEDTLS_XTEA_ALT
/*
- * When replacing the elliptic curve module, pleace consider, that it is
+ * When replacing the elliptic curve module, please consider, that it is
* implemented with two .c files:
* - ecp.c
* - ecp_curves.c
@@ -1493,7 +1498,7 @@
* Enable an implementation of SHA-256 that has lower ROM footprint but also
* lower performance.
*
- * The default implementation is meant to be a reasonnable compromise between
+ * The default implementation is meant to be a reasonable compromise between
* performance and size. This version optimizes more aggressively for size at
* the expense of performance. Eg on Cortex-M4 it reduces the size of
* mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about
@@ -1658,7 +1663,7 @@
* Enable support for RFC 7627: Session Hash and Extended Master Secret
* Extension.
*
- * This was introduced as "the proper fix" to the Triple Handshake familiy of
+ * This was introduced as "the proper fix" to the Triple Handshake family of
* attacks, but it is recommended to always use it (even if you disable
* renegotiation), since it actually fixes a more fundamental issue in the
* original SSL/TLS design, and has implications beyond Triple Handshake.
@@ -1704,7 +1709,7 @@
* \note This option has no influence on the protection against the
* triple handshake attack. Even if it is disabled, Mbed TLS will
* still ensure that certificates do not change during renegotiation,
- * for exaple by keeping a hash of the peer's certificate.
+ * for example by keeping a hash of the peer's certificate.
*
* Comment this macro to disable storing the peer's certificate
* after the handshake.
@@ -1909,7 +1914,7 @@
* unless you know for sure amplification cannot be a problem in the
* environment in which your server operates.
*
- * \warning Disabling this can ba a security risk! (see above)
+ * \warning Disabling this can be a security risk! (see above)
*
* Requires: MBEDTLS_SSL_PROTO_DTLS
*
@@ -2162,8 +2167,19 @@
* This setting allows support for cryptographic mechanisms through the PSA
* API to be configured separately from support through the mbedtls API.
*
- * Uncomment this to enable use of PSA Crypto configuration settings which
- * can be found in include/psa/crypto_config.h.
+ * When this option is disabled, the PSA API exposes the cryptographic
+ * mechanisms that can be implemented on top of the `mbedtls_xxx` API
+ * configured with `MBEDTLS_XXX` symbols.
+ *
+ * When this option is enabled, the PSA API exposes the cryptographic
+ * mechanisms requested by the `PSA_WANT_XXX` symbols defined in
+ * include/psa/crypto_config.h. The corresponding `MBEDTLS_XXX` settings are
+ * automatically enabled if required (i.e. if no PSA driver provides the
+ * mechanism). You may still freely enable additional `MBEDTLS_XXX` symbols
+ * in config.h.
+ *
+ * If the symbol #MBEDTLS_PSA_CRYPTO_CONFIG_FILE is defined, it specifies
+ * an alternative header to include instead of include/psa/crypto_config.h.
*
* If you enable this option and write your own configuration file, you must
* include mbedtls/config_psa.h in your configuration file. The default
@@ -2289,7 +2305,7 @@
* Uncomment to enable use of ZLIB
*/
//#define MBEDTLS_ZLIB_SUPPORT
-/* \} name SECTION: mbed TLS feature support */
+/** \} name SECTION: mbed TLS feature support */
/**
* \name SECTION: mbed TLS modules
@@ -2902,7 +2918,7 @@
*
* Requires: MBEDTLS_MD_C
*
- * Uncomment to enable the HMAC_DRBG random number geerator.
+ * Uncomment to enable the HMAC_DRBG random number generator.
*/
#define MBEDTLS_HMAC_DRBG_C
@@ -3096,7 +3112,7 @@
/**
* \def MBEDTLS_PK_C
*
- * Enable the generic public (asymetric) key layer.
+ * Enable the generic public (asymmetric) key layer.
*
* Module: library/pk.c
* Caller: library/ssl_tls.c
@@ -3112,7 +3128,7 @@
/**
* \def MBEDTLS_PK_PARSE_C
*
- * Enable the generic public (asymetric) key parser.
+ * Enable the generic public (asymmetric) key parser.
*
* Module: library/pkparse.c
* Caller: library/x509_crt.c
@@ -3127,7 +3143,7 @@
/**
* \def MBEDTLS_PK_WRITE_C
*
- * Enable the generic public (asymetric) key writer.
+ * Enable the generic public (asymmetric) key writer.
*
* Module: library/pkwrite.c
* Caller: library/x509write.c
@@ -3466,6 +3482,10 @@
* your own implementation of the whole module by setting
* \c MBEDTLS_TIMING_ALT in the current file.
*
+ * \note The timing module will include time.h on suitable platforms
+ * regardless of the setting of MBEDTLS_HAVE_TIME, unless
+ * MBEDTLS_TIMING_ALT is used. See timing.c for more information.
+ *
* \note See also our Knowledge Base article about porting to a new
* environment:
* https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS
@@ -3598,7 +3618,88 @@
*/
#define MBEDTLS_XTEA_C
-/* \} name SECTION: mbed TLS modules */
+/** \} name SECTION: mbed TLS modules */
+
+/**
+ * \name SECTION: General configuration options
+ *
+ * This section contains Mbed TLS build settings that are not associated
+ * with a particular module.
+ *
+ * \{
+ */
+
+/**
+ * \def MBEDTLS_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"mbedtls/config.h"`.
+ * This header file specifies the compile-time configuration of Mbed TLS.
+ * Unlike other configuration options, this one must be defined on the
+ * compiler command line: a definition in `config.h` would have no effect.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_CONFIG_FILE "mbedtls/config.h"
+
+/**
+ * \def MBEDTLS_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"mbedtls/config.h"` or #MBEDTLS_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_USER_CONFIG_FILE "/dev/null"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included instead of
+ * `"psa/crypto_config.h"`.
+ * This header file specifies which cryptographic mechanisms are available
+ * through the PSA API when #MBEDTLS_PSA_CRYPTO_CONFIG is enabled, and
+ * is not used when #MBEDTLS_PSA_CRYPTO_CONFIG is disabled.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "psa/crypto_config.h"
+
+/**
+ * \def MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
+ *
+ * If defined, this is a header which will be included after
+ * `"psa/crypto_config.h"` or #MBEDTLS_PSA_CRYPTO_CONFIG_FILE.
+ * This allows you to modify the default configuration, including the ability
+ * to undefine options that are enabled by default.
+ *
+ * This macro is expanded after an <tt>\#include</tt> directive. This is a popular but
+ * non-standard feature of the C language, so this feature is only available
+ * with compilers that perform macro expansion on an <tt>\#include</tt> line.
+ *
+ * The value of this symbol is typically a path in double quotes, either
+ * absolute or relative to a directory on the include search path.
+ */
+//#define MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE "/dev/null"
+
+/** \} name SECTION: General configuration options */
/**
* \name SECTION: Module configuration options
@@ -3609,11 +3710,15 @@
*
* Our advice is to enable options and change their values here
* only if you have a good reason and know the consequences.
- *
- * Please check the respective header file for documentation on these
- * parameters (to prevent duplicate documentation).
* \{
*/
+/* The Doxygen documentation here is used when a user comments out a
+ * setting and runs doxygen themselves. On the other hand, when we typeset
+ * the full documentation including disabled settings, the documentation
+ * in specific modules' header files is used if present. When editing this
+ * file, make sure that each option is documented in exactly one place,
+ * plus optionally a same-line Doxygen comment here if there is a Doxygen
+ * comment in the specific module. */
/* MPI / BIGNUM options */
//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */
@@ -4002,7 +4107,7 @@
*/
//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
-/* \} name SECTION: Customisation configuration options */
+/** \} name SECTION: Module configuration options */
/* Target and application specific configurations
*
diff --git a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
index dc4adc896d..e68237a439 100644
--- a/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/ctr_drbg.h
@@ -138,7 +138,7 @@
/**< The maximum size of seed or reseed buffer in bytes. */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_CTR_DRBG_PR_OFF 0
/**< Prediction resistance is disabled. */
diff --git a/thirdparty/mbedtls/include/mbedtls/debug.h b/thirdparty/mbedtls/include/mbedtls/debug.h
index 3c08244f3d..4fc4662d9a 100644
--- a/thirdparty/mbedtls/include/mbedtls/debug.h
+++ b/thirdparty/mbedtls/include/mbedtls/debug.h
@@ -139,7 +139,7 @@ extern "C" {
* discarded.
* (Default value: 0 = No debug )
*
- * \param threshold theshold level of messages to filter on. Messages at a
+ * \param threshold threshold level of messages to filter on. Messages at a
* higher level will be discarded.
* - Debug levels
* - 0 No debug
diff --git a/thirdparty/mbedtls/include/mbedtls/ecjpake.h b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
index 891705d8c4..3564ff8dd3 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecjpake.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecjpake.h
@@ -68,7 +68,7 @@ typedef enum {
* (KeyExchange) as defined by the Thread spec.
*
* In order to benefit from this symmetry, we choose a different naming
- * convetion from the Thread v1.0 spec. Correspondance is indicated in the
+ * convention from the Thread v1.0 spec. Correspondence is indicated in the
* description as a pair C: client name, S: server name
*/
typedef struct mbedtls_ecjpake_context
diff --git a/thirdparty/mbedtls/include/mbedtls/ecp.h b/thirdparty/mbedtls/include/mbedtls/ecp.h
index 0924341e00..64a0bccda0 100644
--- a/thirdparty/mbedtls/include/mbedtls/ecp.h
+++ b/thirdparty/mbedtls/include/mbedtls/ecp.h
@@ -315,7 +315,7 @@ mbedtls_ecp_group;
#if !defined(MBEDTLS_ECP_WINDOW_SIZE)
/*
* Maximum "window" size used for point multiplication.
- * Default: a point where higher memory usage yields disminishing performance
+ * Default: a point where higher memory usage yields diminishing performance
* returns.
* Minimum value: 2. Maximum value: 7.
*
@@ -351,7 +351,7 @@ mbedtls_ecp_group;
#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */
#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#else /* MBEDTLS_ECP_ALT */
#include "ecp_alt.h"
diff --git a/thirdparty/mbedtls/include/mbedtls/entropy.h b/thirdparty/mbedtls/include/mbedtls/entropy.h
index deb3c50300..40259ebc8a 100644
--- a/thirdparty/mbedtls/include/mbedtls/entropy.h
+++ b/thirdparty/mbedtls/include/mbedtls/entropy.h
@@ -75,7 +75,7 @@
#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */
diff --git a/thirdparty/mbedtls/include/mbedtls/hkdf.h b/thirdparty/mbedtls/include/mbedtls/hkdf.h
index 223004b8ed..111d960e56 100644
--- a/thirdparty/mbedtls/include/mbedtls/hkdf.h
+++ b/thirdparty/mbedtls/include/mbedtls/hkdf.h
@@ -39,7 +39,7 @@
*/
/** Bad input parameters to function. */
#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80
-/* \} name */
+/** \} name */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
index 79132d4d91..6d372b9788 100644
--- a/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/thirdparty/mbedtls/include/mbedtls/hmac_drbg.h
@@ -74,7 +74,7 @@
#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
@@ -207,7 +207,7 @@ int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
size_t len );
/**
- * \brief Initilisation of simpified HMAC_DRBG (never reseeds).
+ * \brief Initialisation of simplified HMAC_DRBG (never reseeds).
*
* This function is meant for use in algorithms that need a pseudorandom
* input such as deterministic ECDSA.
diff --git a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
index 233977252a..3954b36ab5 100644
--- a/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
+++ b/thirdparty/mbedtls/include/mbedtls/memory_buffer_alloc.h
@@ -42,7 +42,7 @@
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#define MBEDTLS_MEMORY_VERIFY_NONE 0
#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0)
diff --git a/thirdparty/mbedtls/include/mbedtls/oid.h b/thirdparty/mbedtls/include/mbedtls/oid.h
index 1c39186a49..0186217804 100644
--- a/thirdparty/mbedtls/include/mbedtls/oid.h
+++ b/thirdparty/mbedtls/include/mbedtls/oid.h
@@ -143,7 +143,7 @@
#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */
#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */
#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */
-#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */
+#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributeType:= {id-at 45} */
#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */
#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */
diff --git a/thirdparty/mbedtls/include/mbedtls/pem.h b/thirdparty/mbedtls/include/mbedtls/pem.h
index dfb4ff218e..daa71c886b 100644
--- a/thirdparty/mbedtls/include/mbedtls/pem.h
+++ b/thirdparty/mbedtls/include/mbedtls/pem.h
@@ -54,7 +54,7 @@
#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400
/** Bad input parameters to function. */
#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480
-/* \} name */
+/** \} name PEM Error codes */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/pk.h b/thirdparty/mbedtls/include/mbedtls/pk.h
index 8f2abf2a60..c9a13f484e 100644
--- a/thirdparty/mbedtls/include/mbedtls/pk.h
+++ b/thirdparty/mbedtls/include/mbedtls/pk.h
@@ -217,32 +217,6 @@ typedef struct
typedef void mbedtls_pk_restart_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
-#if defined(MBEDTLS_RSA_C)
-/**
- * Quick access to an RSA context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an RSA context
- * before using this function!
- */
-static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
-{
- return( (mbedtls_rsa_context *) (pk).pk_ctx );
-}
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-/**
- * Quick access to an EC context inside a PK context.
- *
- * \warning You must make sure the PK context actually holds an EC context
- * before using this function!
- */
-static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
-{
- return( (mbedtls_ecp_keypair *) (pk).pk_ctx );
-}
-#endif /* MBEDTLS_ECP_C */
-
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/**
* \brief Types for RSA-alt abstraction
@@ -656,6 +630,55 @@ const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx );
*/
mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
+#if defined(MBEDTLS_RSA_C)
+/**
+ * Quick access to an RSA context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_RSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal RSA context held by the PK context, or NULL.
+ */
+static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
+{
+ switch( mbedtls_pk_get_type( &pk ) )
+ {
+ case MBEDTLS_PK_RSA:
+ return( (mbedtls_rsa_context *) (pk).pk_ctx );
+ default:
+ return( NULL );
+ }
+}
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+/**
+ * Quick access to an EC context inside a PK context.
+ *
+ * \warning This function can only be used when the type of the context, as
+ * returned by mbedtls_pk_get_type(), is #MBEDTLS_PK_ECKEY,
+ * #MBEDTLS_PK_ECKEY_DH, or #MBEDTLS_PK_ECDSA.
+ * Ensuring that is the caller's responsibility.
+ * Alternatively, you can check whether this function returns NULL.
+ *
+ * \return The internal EC context held by the PK context, or NULL.
+ */
+static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
+{
+ switch( mbedtls_pk_get_type( &pk ) )
+ {
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ return( (mbedtls_ecp_keypair *) (pk).pk_ctx );
+ default:
+ return( NULL );
+ }
+}
+#endif /* MBEDTLS_ECP_C */
+
#if defined(MBEDTLS_PK_PARSE_C)
/** \ingroup pk_module */
/**
diff --git a/thirdparty/mbedtls/include/mbedtls/platform.h b/thirdparty/mbedtls/include/mbedtls/platform.h
index bdef07498d..06dd192eab 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform.h
@@ -70,7 +70,9 @@ extern "C" {
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
#include <stdio.h>
#include <stdlib.h>
+#if defined(MBEDTLS_HAVE_TIME)
#include <time.h>
+#endif
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */
@@ -127,7 +129,7 @@ extern "C" {
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
/*
* The function pointers for calloc and free.
diff --git a/thirdparty/mbedtls/include/mbedtls/platform_time.h b/thirdparty/mbedtls/include/mbedtls/platform_time.h
index 7e7daab692..94055711b2 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform_time.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform_time.h
@@ -32,14 +32,6 @@
extern "C" {
#endif
-/**
- * \name SECTION: Module settings
- *
- * The configuration options you can set for this module are in this section.
- * Either change them in config.h or define them on the compiler command line.
- * \{
- */
-
/*
* The time_t datatype
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/platform_util.h b/thirdparty/mbedtls/include/mbedtls/platform_util.h
index f982db8c01..cd112ab58e 100644
--- a/thirdparty/mbedtls/include/mbedtls/platform_util.h
+++ b/thirdparty/mbedtls/include/mbedtls/platform_util.h
@@ -67,7 +67,7 @@ extern "C" {
* \brief User supplied callback function for parameter validation failure.
* See #MBEDTLS_CHECK_PARAMS for context.
*
- * This function will be called unless an alternative treatement
+ * This function will be called unless an alternative treatment
* is defined through the #MBEDTLS_PARAM_FAILED macro.
*
* This function can return, and the operation will be aborted, or
@@ -198,7 +198,7 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;
*
* This macro has an empty expansion. It exists for documentation purposes:
* a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function
- * has been analyzed for return-check usefuless, whereas the lack of
+ * has been analyzed for return-check usefulness, whereas the lack of
* an annotation indicates that the function has not been analyzed and its
* return-check usefulness is unknown.
*/
diff --git a/thirdparty/mbedtls/include/mbedtls/rsa.h b/thirdparty/mbedtls/include/mbedtls/rsa.h
index 3c481e12a1..062df73aa0 100644
--- a/thirdparty/mbedtls/include/mbedtls/rsa.h
+++ b/thirdparty/mbedtls/include/mbedtls/rsa.h
@@ -88,7 +88,7 @@
/*
* The above constants may be used even if the RSA module is compile out,
- * eg for alternative (PKCS#11) RSA implemenations in the PK layers.
+ * eg for alternative (PKCS#11) RSA implementations in the PK layers.
*/
#ifdef __cplusplus
@@ -552,7 +552,7 @@ int mbedtls_rsa_public( mbedtls_rsa_context *ctx,
*
* \note Blinding is used if and only if a PRNG is provided.
*
- * \note If blinding is used, both the base of exponentation
+ * \note If blinding is used, both the base of exponentiation
* and the exponent are blinded, providing protection
* against some side-channel attacks.
*
@@ -687,7 +687,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx,
* mode being set to #MBEDTLS_RSA_PRIVATE and might instead
* return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED.
*
- * \param ctx The initnialized RSA context to use.
+ * \param ctx The initialized RSA context to use.
* \param f_rng The RNG function to use. This is needed for padding
* generation and must be provided.
* \param p_rng The RNG context to be passed to \p f_rng. This may
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl.h b/thirdparty/mbedtls/include/mbedtls/ssl.h
index 209dbf6053..5064ec5689 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl.h
@@ -349,7 +349,7 @@
#define MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY 1
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
/*
* Length of the verify data for secure renegotiation
@@ -1152,7 +1152,7 @@ struct mbedtls_ssl_config
#endif
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
- /** Callback to create & write a cookie for ClientHello veirifcation */
+ /** Callback to create & write a cookie for ClientHello verification */
int (*f_cookie_write)( void *, unsigned char **, unsigned char *,
const unsigned char *, size_t );
/** Callback to verify validity of a ClientHello cookie */
@@ -1405,7 +1405,7 @@ struct mbedtls_ssl_context
unsigned char *compress_buf; /*!< zlib data buffer */
#endif /* MBEDTLS_ZLIB_SUPPORT */
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
- signed char split_done; /*!< current record already splitted? */
+ signed char split_done; /*!< current record already split? */
#endif /* MBEDTLS_SSL_CBC_RECORD_SPLITTING */
/*
@@ -1688,7 +1688,7 @@ void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf,
*
* \note The two most common use cases are:
* - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL
- * - blocking I/O, f_recv == NULL, f_recv_timout != NULL
+ * - blocking I/O, f_recv == NULL, f_recv_timeout != NULL
*
* \note For DTLS, you need to provide either a non-NULL
* f_recv_timeout callback, or a f_recv that doesn't block.
@@ -1846,7 +1846,7 @@ int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
/**
- * \brief Set the Maximum Tranport Unit (MTU).
+ * \brief Set the Maximum Transport Unit (MTU).
* Special value: 0 means unset (no limit).
* This represents the maximum size of a datagram payload
* handled by the transport layer (usually UDP) as determined
@@ -2387,7 +2387,7 @@ void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode );
* ones going through the authentication-decryption phase.
*
* \note This is a security trade-off related to the fact that it's
- * often relatively easy for an active attacker ot inject UDP
+ * often relatively easy for an active attacker to inject UDP
* datagrams. On one hand, setting a low limit here makes it
* easier for such an attacker to forcibly terminated a
* connection. On the other hand, a high limit or no limit
@@ -2498,7 +2498,7 @@ void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min,
* successfully cached, return 1 otherwise.
*
* \param conf SSL configuration
- * \param p_cache parmater (context) for both callbacks
+ * \param p_cache parameter (context) for both callbacks
* \param f_get_cache session get callback
* \param f_set_cache session set callback
*/
@@ -2529,7 +2529,7 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session
/**
* \brief Load serialized session data into a session structure.
* On client, this can be used for loading saved sessions
- * before resuming them with mbedstls_ssl_set_session().
+ * before resuming them with mbedtls_ssl_set_session().
* On server, this can be used for alternative implementations
* of session cache or session tickets.
*
@@ -2793,7 +2793,7 @@ void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
*
* \note On client, only the first call has any effect. That is,
* only one client certificate can be provisioned. The
- * server's preferences in its CertficateRequest message will
+ * server's preferences in its CertificateRequest message will
* be ignored and our only cert will be sent regardless of
* whether it matches those preferences - the server can then
* decide what it wants to do with it.
@@ -3241,7 +3241,7 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl,
* \param protos Pointer to a NULL-terminated list of supported protocols,
* in decreasing preference order. The pointer to the list is
* recorded by the library for later reference as required, so
- * the lifetime of the table must be atleast as long as the
+ * the lifetime of the table must be at least as long as the
* lifetime of the SSL configuration structure.
*
* \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA.
@@ -3255,7 +3255,7 @@ int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **prot
*
* \param ssl SSL context
*
- * \return Protcol name, or NULL if no protocol was negotiated.
+ * \return Protocol name, or NULL if no protocol was negotiated.
*/
const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_ALPN */
@@ -3338,7 +3338,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
unsigned char *mki_value,
uint16_t mki_len );
/**
- * \brief Get the negotiated DTLS-SRTP informations:
+ * \brief Get the negotiated DTLS-SRTP information:
* Protection profile and MKI value.
*
* \warning This function must be called after the handshake is
@@ -3346,7 +3346,7 @@ int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl,
* not be trusted or acted upon before the handshake completes.
*
* \param ssl The SSL context to query.
- * \param dtls_srtp_info The negotiated DTLS-SRTP informations:
+ * \param dtls_srtp_info The negotiated DTLS-SRTP information:
* - Protection profile in use.
* A direct mapping of the iana defined value for protection
* profile on an uint16_t.
@@ -3508,7 +3508,7 @@ void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf,
* \c mbedtls_ssl_get_record_expansion().
*
* \note For DTLS, it is also possible to set a limit for the total
- * size of daragrams passed to the transport layer, including
+ * size of datagrams passed to the transport layer, including
* record overhead, see \c mbedtls_ssl_set_mtu().
*
* \param conf SSL configuration
@@ -3568,7 +3568,7 @@ void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets
* initiated by peer
* (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED)
*
- * \warning It is recommended to always disable renegotation unless you
+ * \warning It is recommended to always disable renegotiation unless you
* know you need it and you know what you're doing. In the
* past, there have been several issues associated with
* renegotiation or a poor understanding of its properties.
@@ -3631,7 +3631,7 @@ void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_
* scenario.
*
* \note With DTLS and server-initiated renegotiation, the
- * HelloRequest is retransmited every time mbedtls_ssl_read() times
+ * HelloRequest is retransmitted every time mbedtls_ssl_read() times
* out or receives Application Data, until:
* - max_records records have beens seen, if it is >= 0, or
* - the number of retransmits that would happen during an
@@ -4263,7 +4263,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl );
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
* \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed
- * while reseting the context.
+ * while resetting the context.
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in
* progress, or there is pending data for reading or sending,
* or the connection does not use DTLS 1.2 with an AEAD
@@ -4357,7 +4357,7 @@ int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl,
void mbedtls_ssl_config_init( mbedtls_ssl_config *conf );
/**
- * \brief Load reasonnable default SSL configuration values.
+ * \brief Load reasonable default SSL configuration values.
* (You need to call mbedtls_ssl_config_init() first.)
*
* \param conf SSL configuration context
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
index c6ef2960f4..02eab96d45 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_cache.h
@@ -50,7 +50,7 @@
#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
index 0a238708e5..2aa373177b 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_cookie.h
@@ -45,7 +45,7 @@
#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */
#endif
-/* \} name SECTION: Module settings */
+/** \} name SECTION: Module settings */
#ifdef __cplusplus
extern "C" {
@@ -84,7 +84,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
* \brief Set expiration delay for cookies
* (Default MBEDTLS_SSL_COOKIE_TIMEOUT)
*
- * \param ctx Cookie contex
+ * \param ctx Cookie context
* \param delay Delay, in seconds if HAVE_TIME, or in number of cookies
* issued in the meantime.
* 0 to disable expiration (NOT recommended)
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
index 6913dc0f66..46ade67b9c 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_internal.h
@@ -934,16 +934,22 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform );
*/
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl );
void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
@@ -1023,27 +1029,39 @@ void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl );
* following the above definition.
*
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
unsigned update_hs_digest );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl );
void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *ciphersuite_info );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex );
/**
@@ -1108,13 +1126,18 @@ mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig );
mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash );
unsigned char mbedtls_ssl_hash_from_md_alg( int md );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md );
#if defined(MBEDTLS_ECP_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id );
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id );
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl,
mbedtls_md_type_t md );
#endif
@@ -1170,6 +1193,7 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl )
*
* Return 0 if everything is OK, -1 if not.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert,
const mbedtls_ssl_ciphersuite_t *ciphersuite,
int cert_endpoint,
@@ -1218,21 +1242,26 @@ static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_PROTO_DTLS)
void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl );
void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_resend( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl );
#endif
/* Visible for testing purposes only */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl );
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
#endif
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
const mbedtls_ssl_session *src );
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len );
@@ -1242,6 +1271,7 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
@@ -1254,11 +1284,13 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
#endif
void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec );
@@ -1276,10 +1308,12 @@ static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl );
void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl );
@@ -1287,6 +1321,7 @@ void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl,
mbedtls_ssl_transform *transform );
void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial );
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
@@ -1296,6 +1331,7 @@ void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl );
void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_RENEGOTIATION */
@@ -1305,4 +1341,12 @@ void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl );
void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_TEST_HOOKS)
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+ mbedtls_ssl_context *ssl,
+ const unsigned char *cli_id, size_t cli_id_len,
+ const unsigned char *in, size_t in_len,
+ unsigned char *obuf, size_t buf_len, size_t *olen );
+#endif
+
#endif /* ssl_internal.h */
diff --git a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
index a882eed23b..8221051b24 100644
--- a/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/thirdparty/mbedtls/include/mbedtls/ssl_ticket.h
@@ -101,7 +101,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx );
* supported. Usually that means a 256-bit key.
*
* \note The lifetime of the keys is twice the lifetime of tickets.
- * It is recommended to pick a reasonnable lifetime so as not
+ * It is recommended to pick a reasonable lifetime so as not
* to negate the benefits of forward secrecy.
*
* \return 0 if successful,
diff --git a/thirdparty/mbedtls/include/mbedtls/version.h b/thirdparty/mbedtls/include/mbedtls/version.h
index b1a92b2bcf..44adcbfe03 100644
--- a/thirdparty/mbedtls/include/mbedtls/version.h
+++ b/thirdparty/mbedtls/include/mbedtls/version.h
@@ -38,16 +38,16 @@
*/
#define MBEDTLS_VERSION_MAJOR 2
#define MBEDTLS_VERSION_MINOR 28
-#define MBEDTLS_VERSION_PATCH 0
+#define MBEDTLS_VERSION_PATCH 1
/**
* The single version number has the following structure:
* MMNNPP00
* Major version | Minor version | Patch version
*/
-#define MBEDTLS_VERSION_NUMBER 0x021C0000
-#define MBEDTLS_VERSION_STRING "2.28.0"
-#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.0"
+#define MBEDTLS_VERSION_NUMBER 0x021C0100
+#define MBEDTLS_VERSION_STRING "2.28.1"
+#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.28.1"
#if defined(MBEDTLS_VERSION_C)
diff --git a/thirdparty/mbedtls/include/mbedtls/x509.h b/thirdparty/mbedtls/include/mbedtls/x509.h
index c177501430..31b78df32f 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509.h
@@ -96,7 +96,7 @@
#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980
/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */
#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000
-/* \} name */
+/** \} name X509 Error codes */
/**
* \name X509 Verify codes
@@ -124,8 +124,8 @@
#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */
#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name X509 Verify codes */
+/** \} addtogroup x509_module */
/*
* X.509 v3 Subject Alternative Name types.
@@ -255,7 +255,6 @@ typedef struct mbedtls_x509_time
mbedtls_x509_time;
/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
-/** \} addtogroup x509_module */
/**
* \brief Store the certificate DN in printable form into buf;
@@ -311,6 +310,8 @@ int mbedtls_x509_time_is_past( const mbedtls_x509_time *to );
*/
int mbedtls_x509_time_is_future( const mbedtls_x509_time *from );
+/** \} addtogroup x509_module */
+
#if defined(MBEDTLS_SELF_TEST)
/**
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crl.h b/thirdparty/mbedtls/include/mbedtls/x509_crl.h
index 7e9e8885f4..9222009019 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crl.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crl.h
@@ -162,8 +162,8 @@ void mbedtls_x509_crl_init( mbedtls_x509_crl *crl );
*/
void mbedtls_x509_crl_free( mbedtls_x509_crl *crl );
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for parsing CRLs */
+/** \} addtogroup x509_module */
#ifdef __cplusplus
}
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_crt.h b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
index 64ccb433ba..0f2885a7ee 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_crt.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_crt.h
@@ -107,7 +107,7 @@ mbedtls_x509_crt;
typedef struct mbedtls_x509_san_other_name
{
/**
- * The type_id is an OID as deifned in RFC 5280.
+ * The type_id is an OID as defined in RFC 5280.
* To check the value of the type id, you should use
* \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
*/
@@ -159,7 +159,9 @@ mbedtls_x509_subject_alternative_name;
typedef struct mbedtls_x509_crt_profile
{
uint32_t allowed_mds; /**< MDs for signatures */
- uint32_t allowed_pks; /**< PK algs for signatures */
+ uint32_t allowed_pks; /**< PK algs for public keys;
+ * this applies to all certificates
+ * in the provided chain. */
uint32_t allowed_curves; /**< Elliptic curves for ECDSA */
uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */
}
@@ -850,8 +852,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for parsing and writing X.509 certificates */
#if defined(MBEDTLS_X509_CRT_WRITE_C)
/**
@@ -862,7 +863,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx );
void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx );
/**
- * \brief Set the verion for a Certificate
+ * \brief Set the version for a Certificate
* Default: MBEDTLS_X509_CRT_VERSION_3
*
* \param ctx CRT context to use
@@ -978,7 +979,7 @@ int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx,
* \param is_ca is this a CA certificate
* \param max_pathlen maximum length of certificate chains below this
* certificate (only for CA certificates, -1 is
- * inlimited)
+ * unlimited)
*
* \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED
*/
@@ -1087,6 +1088,8 @@ int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf,
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_X509_CRT_WRITE_C */
+/** \} addtogroup x509_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/include/mbedtls/x509_csr.h b/thirdparty/mbedtls/include/mbedtls/x509_csr.h
index b1dfc21f1f..2a1c046131 100644
--- a/thirdparty/mbedtls/include/mbedtls/x509_csr.h
+++ b/thirdparty/mbedtls/include/mbedtls/x509_csr.h
@@ -151,8 +151,7 @@ void mbedtls_x509_csr_init( mbedtls_x509_csr *csr );
void mbedtls_x509_csr_free( mbedtls_x509_csr *csr );
#endif /* MBEDTLS_X509_CSR_PARSE_C */
-/* \} name */
-/* \} addtogroup x509_module */
+/** \} name Structures and functions for X.509 Certificate Signing Requests (CSR) */
#if defined(MBEDTLS_X509_CSR_WRITE_C)
/**
@@ -182,7 +181,7 @@ int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,
* private key used to sign the CSR when writing it)
*
* \param ctx CSR context to use
- * \param key Asymetric key to include
+ * \param key Asymmetric key to include
*/
void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key );
@@ -298,6 +297,8 @@ int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, s
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_X509_CSR_WRITE_C */
+/** \} addtogroup x509_module */
+
#ifdef __cplusplus
}
#endif
diff --git a/thirdparty/mbedtls/library/aes.c b/thirdparty/mbedtls/library/aes.c
index 31824e75cf..03d8b7ea61 100644
--- a/thirdparty/mbedtls/library/aes.c
+++ b/thirdparty/mbedtls/library/aes.c
@@ -1106,7 +1106,7 @@ typedef unsigned char mbedtls_be128[16];
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
- * for machine endianess and hence works correctly on both big and little
+ * for machine endianness and hence works correctly on both big and little
* endian machines.
*/
static void mbedtls_gf128mul_x_ble( unsigned char r[16],
@@ -1206,7 +1206,7 @@ int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
- * byte of cyphertext we won't steal. At the same time, copy the
+ * byte of ciphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for( i = 0; i < leftover; i++ )
diff --git a/thirdparty/mbedtls/library/asn1write.c b/thirdparty/mbedtls/library/asn1write.c
index 3811ef27a3..afa26a6be9 100644
--- a/thirdparty/mbedtls/library/asn1write.c
+++ b/thirdparty/mbedtls/library/asn1write.c
@@ -133,6 +133,11 @@ int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedt
//
len = mbedtls_mpi_size( X );
+ /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
+ * as 0 digits. We need to end up with 020100, not with 0200. */
+ if( len == 0 )
+ len = 1;
+
if( *p < start || (size_t)( *p - start ) < len )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
@@ -472,7 +477,7 @@ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
cur->val.len = val_len;
}
- if( val != NULL )
+ if( val != NULL && val_len != 0 )
memcpy( cur->val.p, val, val_len );
return( cur );
diff --git a/thirdparty/mbedtls/library/bignum.c b/thirdparty/mbedtls/library/bignum.c
index 62e7f76727..32578e2c68 100644
--- a/thirdparty/mbedtls/library/bignum.c
+++ b/thirdparty/mbedtls/library/bignum.c
@@ -1829,7 +1829,7 @@ int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_
/*
* handle trivial cases
*/
- if( b == 1 )
+ if( b == 1 || A->n == 0 )
{
*r = 0;
return( 0 );
@@ -2317,7 +2317,7 @@ int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B
* TA-TB is even so the division by 2 has an integer result.
* Invariant (I) is preserved since any odd divisor of both TA and TB
* also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2
- * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also
+ * also divides TB, and any odd divisor of both TB and |TA-TB|/2 also
* divides TA.
*/
if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 )
diff --git a/thirdparty/mbedtls/library/cipher.c b/thirdparty/mbedtls/library/cipher.c
index 4ec40d2cac..f3b4bd29ce 100644
--- a/thirdparty/mbedtls/library/cipher.c
+++ b/thirdparty/mbedtls/library/cipher.c
@@ -386,6 +386,12 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
#if defined(MBEDTLS_CHACHA20_C)
if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 )
{
+ /* Even though the actual_iv_size is overwritten with a correct value
+ * of 12 from the cipher info, return an error to indicate that
+ * the input iv_len is wrong. */
+ if( iv_len != 12 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+
if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx,
iv,
0U ) ) /* Initial counter value */
@@ -393,6 +399,11 @@ int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
}
}
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
+ iv_len != 12 )
+ return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA );
+#endif
#endif
if ( actual_iv_size != 0 )
diff --git a/thirdparty/mbedtls/library/constant_time.c b/thirdparty/mbedtls/library/constant_time.c
index 18f1b20daa..e276d23ca0 100644
--- a/thirdparty/mbedtls/library/constant_time.c
+++ b/thirdparty/mbedtls/library/constant_time.c
@@ -489,6 +489,12 @@ int mbedtls_ct_hmac( mbedtls_md_context_t *ctx,
MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) );
MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) );
+ /* Fill the hash buffer in advance with something that is
+ * not a valid hash (barring an attack on the hash and
+ * deliberately-crafted input), in case the caller doesn't
+ * check the return status properly. */
+ memset( output, '!', hash_size );
+
/* For each possible length, compute the hash up to that point */
for( offset = min_data_len; offset <= max_data_len; offset++ )
{
@@ -533,6 +539,13 @@ cleanup:
* about whether the assignment was made or not.
* (Leaking information about the respective sizes of X and Y is ok however.)
*/
+#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
+/*
+ * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
+ * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
+ */
+__declspec(noinline)
+#endif
int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X,
const mbedtls_mpi *Y,
unsigned char assign )
@@ -562,7 +575,7 @@ cleanup:
/*
* Conditionally swap X and Y, without leaking information
* about whether the swap was made or not.
- * Here it is not ok to simply swap the pointers, which whould lead to
+ * Here it is not ok to simply swap the pointers, which would lead to
* different memory access patterns when X and Y are used afterwards.
*/
int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X,
diff --git a/thirdparty/mbedtls/library/constant_time_internal.h b/thirdparty/mbedtls/library/constant_time_internal.h
index bbb3a90670..a550b38fa5 100644
--- a/thirdparty/mbedtls/library/constant_time_internal.h
+++ b/thirdparty/mbedtls/library/constant_time_internal.h
@@ -221,6 +221,13 @@ void mbedtls_ct_memcpy_if_eq( unsigned char *dest,
* offset_secret, but only on \p offset_min, \p offset_max and \p len.
* Functionally equivalent to `memcpy(dst, src + offset_secret, len)`.
*
+ * \note This function reads from \p dest, but the value that
+ * is read does not influence the result and this
+ * function's behavior is well-defined regardless of the
+ * contents of the buffers. This may result in false
+ * positives from static or dynamic analyzers, especially
+ * if \p dest is not initialized.
+ *
* \param dest The destination buffer. This must point to a writable
* buffer of at least \p len bytes.
* \param src The base of the source buffer. This must point to a
diff --git a/thirdparty/mbedtls/library/ctr_drbg.c b/thirdparty/mbedtls/library/ctr_drbg.c
index a604ec0761..a00d66ce87 100644
--- a/thirdparty/mbedtls/library/ctr_drbg.c
+++ b/thirdparty/mbedtls/library/ctr_drbg.c
@@ -828,7 +828,7 @@ static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf,
return( 1 ); \
}
-#define SELF_TEST_OUPUT_DISCARD_LENGTH 64
+#define SELF_TEST_OUTPUT_DISCARD_LENGTH 64
/*
* Checkup routine
@@ -854,7 +854,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
(void *) entropy_source_pr,
pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) );
CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) );
@@ -879,7 +879,7 @@ int mbedtls_ctr_drbg_self_test( int verbose )
(void *) entropy_source_nopr,
pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) );
CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) );
- CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) );
+ CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUTPUT_DISCARD_LENGTH ) );
CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) );
CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) );
diff --git a/thirdparty/mbedtls/library/ecdh.c b/thirdparty/mbedtls/library/ecdh.c
index 9dfa868063..60c6e429de 100644
--- a/thirdparty/mbedtls/library/ecdh.c
+++ b/thirdparty/mbedtls/library/ecdh.c
@@ -399,7 +399,7 @@ static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
}
/*
- * Read the ServerKeyExhange parameters (RFC 4492)
+ * Read the ServerKeyExchange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
diff --git a/thirdparty/mbedtls/library/ecjpake.c b/thirdparty/mbedtls/library/ecjpake.c
index 368b6c7124..0b9bffb93e 100644
--- a/thirdparty/mbedtls/library/ecjpake.c
+++ b/thirdparty/mbedtls/library/ecjpake.c
@@ -435,7 +435,7 @@ cleanup:
/*
* Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs
- * Ouputs: verified peer public keys Xa, Xb
+ * Outputs: verified peer public keys Xa, Xb
*/
static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info,
const mbedtls_ecp_group *grp,
diff --git a/thirdparty/mbedtls/library/ecp.c b/thirdparty/mbedtls/library/ecp.c
index 7f9e1045d4..890f364a08 100644
--- a/thirdparty/mbedtls/library/ecp.c
+++ b/thirdparty/mbedtls/library/ecp.c
@@ -1307,7 +1307,7 @@ cleanup:
* For curves in short Weierstrass form, we do all the internal operations in
* Jacobian coordinates.
*
- * For multiplication, we'll use a comb method with coutermeasueres against
+ * For multiplication, we'll use a comb method with countermeasures against
* SPA, hence timing attacks.
*/
@@ -2251,7 +2251,7 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp,
* This function is mainly responsible for administrative work:
* - managing the restart context if enabled
* - managing the table of precomputed points (passed between the below two
- * functions): allocation, computation, ownership tranfer, freeing.
+ * functions): allocation, computation, ownership transfer, freeing.
*
* It delegates the actual arithmetic work to:
* ecp_precompute_comb() and ecp_mul_comb_with_precomp()
@@ -2422,7 +2422,7 @@ cleanup:
/*
* For Montgomery curves, we do all the internal arithmetic in projective
* coordinates. Import/export of points uses only the x coordinates, which is
- * internaly represented as X / Z.
+ * internally represented as X / Z.
*
* For scalar multiplication, we'll use a Montgomery ladder.
*/
@@ -2592,7 +2592,7 @@ static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) );
mbedtls_mpi_free( &R->Y );
- /* RP.X might be sligtly larger than P, so reduce it */
+ /* RP.X might be slightly larger than P, so reduce it */
MOD_ADD( RP.X );
/* Randomize coordinates of the starting point */
diff --git a/thirdparty/mbedtls/library/ecp_curves.c b/thirdparty/mbedtls/library/ecp_curves.c
index ff26a18e8f..2199be6461 100644
--- a/thirdparty/mbedtls/library/ecp_curves.c
+++ b/thirdparty/mbedtls/library/ecp_curves.c
@@ -755,6 +755,8 @@ int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id )
ECP_VALIDATE_RET( grp != NULL );
mbedtls_ecp_group_free( grp );
+ mbedtls_ecp_group_init( grp );
+
grp->id = id;
switch( id )
diff --git a/thirdparty/mbedtls/library/memory_buffer_alloc.c b/thirdparty/mbedtls/library/memory_buffer_alloc.c
index 0d5d27d3de..cc62324bdc 100644
--- a/thirdparty/mbedtls/library/memory_buffer_alloc.c
+++ b/thirdparty/mbedtls/library/memory_buffer_alloc.c
@@ -555,8 +555,8 @@ static void *buffer_alloc_calloc_mutexed( size_t n, size_t size )
static void buffer_alloc_free_mutexed( void *ptr )
{
- /* We have to good option here, but corrupting the heap seems
- * worse than loosing memory. */
+ /* We have no good option here, but corrupting the heap seems
+ * worse than losing memory. */
if( mbedtls_mutex_lock( &heap.mutex ) )
return;
buffer_alloc_free( ptr );
diff --git a/thirdparty/mbedtls/library/mps_common.h b/thirdparty/mbedtls/library/mps_common.h
index d20776f159..668876ccfc 100644
--- a/thirdparty/mbedtls/library/mps_common.h
+++ b/thirdparty/mbedtls/library/mps_common.h
@@ -51,7 +51,7 @@
* the function's behavior is entirely undefined.
* In addition to state integrity, all MPS structures have a more refined
* notion of abstract state that the API operates on. For example, all layers
- * have a notion of 'abtract read state' which indicates if incoming data has
+ * have a notion of 'abstract read state' which indicates if incoming data has
* been passed to the user, e.g. through mps_l2_read_start() for Layer 2
* or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to
* call these reading functions again until the incoming data has been
diff --git a/thirdparty/mbedtls/library/net_sockets.c b/thirdparty/mbedtls/library/net_sockets.c
index 5fbe1f764a..8c765e1c8c 100644
--- a/thirdparty/mbedtls/library/net_sockets.c
+++ b/thirdparty/mbedtls/library/net_sockets.c
@@ -107,7 +107,9 @@ static int wsa_init_done = 0;
#include <stdio.h>
+#if defined(MBEDTLS_HAVE_TIME)
#include <time.h>
+#endif
#include <stdint.h>
diff --git a/thirdparty/mbedtls/library/pkparse.c b/thirdparty/mbedtls/library/pkparse.c
index 535ed70eb1..ea5c6b69cb 100644
--- a/thirdparty/mbedtls/library/pkparse.c
+++ b/thirdparty/mbedtls/library/pkparse.c
@@ -474,7 +474,7 @@ static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *g
}
/*
- * grp may already be initilialized; if so, make sure IDs match
+ * grp may already be initialized; if so, make sure IDs match
*/
if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id )
return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
@@ -807,7 +807,7 @@ static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa,
goto cleanup;
#else
- /* Verify existance of the CRT params */
+ /* Verify existence of the CRT params */
if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ||
( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 )
@@ -1463,10 +1463,16 @@ int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
{
p = pem.buf;
if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL )
+ {
+ mbedtls_pem_free( &pem );
return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
+ }
if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
+ {
+ mbedtls_pem_free( &pem );
return( ret );
+ }
if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 )
mbedtls_pk_free( ctx );
diff --git a/thirdparty/mbedtls/library/rsa.c b/thirdparty/mbedtls/library/rsa.c
index 8a5d40ff1e..d1f6ddb177 100644
--- a/thirdparty/mbedtls/library/rsa.c
+++ b/thirdparty/mbedtls/library/rsa.c
@@ -832,10 +832,10 @@ cleanup:
* the more bits of the key can be recovered. See [3].
*
* Collecting n collisions with m bit long blinding value requires 2^(m-m/n)
- * observations on avarage.
+ * observations on average.
*
* For example with 28 byte blinding to achieve 2 collisions the adversary has
- * to make 2^112 observations on avarage.
+ * to make 2^112 observations on average.
*
* (With the currently (as of 2017 April) known best algorithms breaking 2048
* bit RSA requires approximately as much time as trying out 2^112 random keys.
diff --git a/thirdparty/mbedtls/library/ssl_ciphersuites.c b/thirdparty/mbedtls/library/ssl_ciphersuites.c
index 3826ad27fa..ceec77efb0 100644
--- a/thirdparty/mbedtls/library/ssl_ciphersuites.c
+++ b/thirdparty/mbedtls/library/ssl_ciphersuites.c
@@ -2181,6 +2181,7 @@ const int *mbedtls_ssl_list_ciphersuites( void )
static int supported_ciphersuites[MAX_CIPHERSUITES];
static int supported_init = 0;
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info )
{
(void)cs_info;
diff --git a/thirdparty/mbedtls/library/ssl_cli.c b/thirdparty/mbedtls/library/ssl_cli.c
index b87879ce6a..72351c9757 100644
--- a/thirdparty/mbedtls/library/ssl_cli.c
+++ b/thirdparty/mbedtls/library/ssl_cli.c
@@ -53,6 +53,7 @@
#endif
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
@@ -73,6 +74,7 @@ static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
{
if( conf->psk_identity == NULL ||
@@ -91,6 +93,7 @@ static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf )
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -161,6 +164,7 @@ static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -204,6 +208,7 @@ static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl,
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -302,6 +307,7 @@ static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -373,6 +379,7 @@ static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl,
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -404,6 +411,7 @@ static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -477,6 +485,7 @@ static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -523,6 +532,7 @@ static int ssl_write_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -555,6 +565,7 @@ static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -585,6 +596,7 @@ static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -616,6 +628,7 @@ static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -647,6 +660,7 @@ static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -689,6 +703,7 @@ static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -748,6 +763,7 @@ static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
const unsigned char *end,
@@ -868,6 +884,7 @@ static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
/*
* Generate random bytes for ClientHello
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_generate_random( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -917,6 +934,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl )
*
* \return 0 if valid, else 1
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_validate_ciphersuite(
const mbedtls_ssl_ciphersuite_t * suite_info,
const mbedtls_ssl_context * ssl,
@@ -960,6 +978,7 @@ static int ssl_validate_ciphersuite(
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1450,6 +1469,7 @@ static int ssl_write_client_hello( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1494,6 +1514,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1520,6 +1541,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1545,6 +1567,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1601,6 +1624,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1627,6 +1651,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1653,6 +1678,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1679,6 +1705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1724,6 +1751,7 @@ static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1758,6 +1786,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -1828,6 +1857,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -1948,6 +1978,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
* Parse HelloVerifyRequest. Only called after verifying the HS type.
*/
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
{
const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl );
@@ -2031,6 +2062,7 @@ static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
{
int ret, i;
@@ -2276,16 +2308,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
else
{
ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC;
-
- if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
- mbedtls_ssl_send_alert_message(
- ssl,
- MBEDTLS_SSL_ALERT_LEVEL_FATAL,
- MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
- return( ret );
- }
}
MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed",
@@ -2538,6 +2560,24 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
}
/*
+ * mbedtls_ssl_derive_keys() has to be called after the parsing of the
+ * extensions. It sets the transform data for the resumed session which in
+ * case of DTLS includes the server CID extracted from the CID extension.
+ */
+ if( ssl->handshake->resume )
+ {
+ if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret );
+ mbedtls_ssl_send_alert_message(
+ ssl,
+ MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+ MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
+ return( ret );
+ }
+ }
+
+ /*
* Renegotiation security checks
*/
if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION &&
@@ -2591,6 +2631,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2637,6 +2678,7 @@ static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl,
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
{
const mbedtls_ecp_curve_info *curve_info;
@@ -2678,6 +2720,7 @@ static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) )
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2703,6 +2746,10 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
tls_id <<= 8;
tls_id |= *(*p)++;
+ /* Check it's a curve we offered */
+ if( mbedtls_ssl_check_curve_tls_id( ssl, tls_id ) != 0 )
+ return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
+
/* Convert EC group to PSA key type. */
if( ( handshake->ecdh_psa_type =
mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 )
@@ -2740,6 +2787,7 @@ static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2779,6 +2827,7 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end )
@@ -2825,6 +2874,7 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
/*
* Generate a pre-master secret and encrypt it with the server's RSA key
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t offset, size_t *olen,
size_t pms_offset )
@@ -2912,6 +2962,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
unsigned char **p,
unsigned char *end,
@@ -2978,6 +3029,7 @@ static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2996,6 +3048,8 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
peer_pk = &ssl->session_negotiate->peer_cert->pk;
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /* This is a public key, so it can't be opaque, so can_do() is a good
+ * enough check to ensure pk_ec() is safe to use below. */
if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
@@ -3029,6 +3083,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3147,7 +3202,7 @@ start_processing:
MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER );
return( MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE );
}
- } /* FALLTROUGH */
+ } /* FALLTHROUGH */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
@@ -3435,6 +3490,7 @@ exit:
}
#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3453,6 +3509,7 @@ static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3624,6 +3681,7 @@ exit:
}
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3663,6 +3721,7 @@ static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3718,7 +3777,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA )
{
- psa_status_t status;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t key_attributes;
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
@@ -3761,13 +3821,19 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
own_pubkey, sizeof( own_pubkey ),
&own_pubkey_len );
if( status != PSA_SUCCESS )
+ {
+ psa_destroy_key( handshake->ecdh_psa_privkey );
+ handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ }
if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey,
own_pubkey_len,
&own_pubkey_ecpoint,
&own_pubkey_ecpoint_len ) != 0 )
{
+ psa_destroy_key( handshake->ecdh_psa_privkey );
+ handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
@@ -3787,13 +3853,12 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
ssl->handshake->premaster,
sizeof( ssl->handshake->premaster ),
&ssl->handshake->pmslen );
- if( status != PSA_SUCCESS )
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
- status = psa_destroy_key( handshake->ecdh_psa_privkey );
- if( status != PSA_SUCCESS )
- return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
+ destruction_status = psa_destroy_key( handshake->ecdh_psa_privkey );
handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+
+ if( status != PSA_SUCCESS || destruction_status != PSA_SUCCESS )
+ return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED );
}
else
#endif /* MBEDTLS_USE_PSA_CRYPTO &&
@@ -3918,7 +3983,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
if( ( ret = ssl_write_encrypted_pms( ssl, header_len,
@@ -3933,7 +4001,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
@@ -3970,7 +4041,10 @@ ecdh_calc_secret:
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only suites. */
if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
@@ -4080,6 +4154,7 @@ ecdh_calc_secret:
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -4105,6 +4180,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -4277,6 +4353,7 @@ sign:
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/thirdparty/mbedtls/library/ssl_cookie.c b/thirdparty/mbedtls/library/ssl_cookie.c
index abf29ae717..3781796b72 100644
--- a/thirdparty/mbedtls/library/ssl_cookie.c
+++ b/thirdparty/mbedtls/library/ssl_cookie.c
@@ -63,7 +63,7 @@
/*
* Cookies are formed of a 4-bytes timestamp (or serial number) and
- * an HMAC of timestemp and client ID.
+ * an HMAC of timestamp and client ID.
*/
#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN )
@@ -122,6 +122,7 @@ int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx,
/*
* Generate the HMAC part of a cookie
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx,
const unsigned char time[4],
unsigned char **p, unsigned char *end,
diff --git a/thirdparty/mbedtls/library/ssl_msg.c b/thirdparty/mbedtls/library/ssl_msg.c
index 0b696dd561..e47c538888 100644
--- a/thirdparty/mbedtls/library/ssl_msg.c
+++ b/thirdparty/mbedtls/library/ssl_msg.c
@@ -91,6 +91,7 @@ int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
unsigned char *buf,
size_t len,
@@ -165,11 +166,16 @@ exit:
static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl,
uint8_t slot );
static void ssl_free_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
mbedtls_record const *rec );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
@@ -187,6 +193,7 @@ static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl )
return( out_buf_len );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
{
size_t const bytes_written = ssl->out_left;
@@ -203,6 +210,7 @@ static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl )
return( (int) ( mtu - bytes_written ) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -254,6 +262,7 @@ static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl
* Double the retransmit timeout value, within the allowed range,
* returning -1 if the maximum value has already been reached.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl )
{
uint32_t new_timeout;
@@ -353,6 +362,7 @@ static size_t ssl_compute_padding_length( size_t len,
* - A negative error code if `max_len` didn't offer enough space
* for the expansion.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_build_inner_plaintext( unsigned char *content,
size_t *content_size,
size_t remaining,
@@ -380,6 +390,7 @@ static int ssl_build_inner_plaintext( unsigned char *content,
/* This function parses a (D)TLSInnerPlaintext structure.
* See ssl_build_inner_plaintext() for details. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_inner_plaintext( unsigned char const *content,
size_t *content_size,
uint8_t *rec_type )
@@ -474,6 +485,7 @@ static void ssl_extract_add_data_from_record( unsigned char* add_data,
/*
* SSLv3.0 MAC functions
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_mac( mbedtls_md_context_t *md_ctx,
const unsigned char *secret,
const unsigned char *buf, size_t len,
@@ -541,6 +553,7 @@ static int ssl_mac( mbedtls_md_context_t *md_ctx,
#if defined(MBEDTLS_GCM_C) || \
defined(MBEDTLS_CCM_C) || \
defined(MBEDTLS_CHACHAPOLY_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_transform_aead_dynamic_iv_is_explicit(
mbedtls_ssl_transform const *transform )
{
@@ -1245,7 +1258,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
add_data, add_data_len );
/* Because of the check above, we know that there are
- * explicit_iv_len Bytes preceeding data, and taglen
+ * explicit_iv_len Bytes preceding data, and taglen
* bytes following data + data_len. This justifies
* the debug message and the invocation of
* mbedtls_cipher_auth_decrypt() below. */
@@ -1590,8 +1603,8 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
if( auth_done == 0 )
{
- unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD];
- unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD];
+ unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
+ unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
/* If the initial value of padlen was such that
* data_len < maclen + padlen + 1, then padlen
@@ -1738,6 +1751,7 @@ int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
/*
* Compression/decompression functions
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_compress_buf( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1790,6 +1804,7 @@ static int ssl_compress_buf( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_decompress_buf( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2149,6 +2164,7 @@ int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl )
/*
* Append current handshake message to current outgoing flight
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_flight_append( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_flight_item *msg;
@@ -2215,6 +2231,7 @@ void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight )
/*
* Swap transform_out and out_ctr with the alternative ones
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_swap_epochs( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_transform *tmp_transform;
@@ -2857,6 +2874,7 @@ int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush )
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen < ssl->in_hslen ||
@@ -2882,6 +2900,7 @@ static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl )
ssl->in_msg[8] );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_hs_header( mbedtls_ssl_context const *ssl )
{
uint32_t msg_len, frag_off, frag_len;
@@ -2948,6 +2967,7 @@ static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len )
/*
* Check that bitmask is full
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_bitmask_check( unsigned char *mask, size_t len )
{
size_t i;
@@ -3147,6 +3167,7 @@ static inline uint64_t ssl_load_six_bytes( unsigned char *buf )
( (uint64_t) buf[5] ) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3229,8 +3250,8 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
/*
- * Without any SSL context, check if a datagram looks like a ClientHello with
- * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message.
+ * Check if a datagram looks like a ClientHello with a valid cookie,
+ * and if it doesn't, generate a HelloVerifyRequest message.
* Both input and output include full DTLS headers.
*
* - if cookie is valid, return 0
@@ -3239,10 +3260,10 @@ void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl )
* return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED
* - otherwise return a specific error code
*/
-static int ssl_check_dtls_clihlo_cookie(
- mbedtls_ssl_cookie_write_t *f_cookie_write,
- mbedtls_ssl_cookie_check_t *f_cookie_check,
- void *p_cookie,
+MBEDTLS_CHECK_RETURN_CRITICAL
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ssl_check_dtls_clihlo_cookie(
+ mbedtls_ssl_context *ssl,
const unsigned char *cli_id, size_t cli_id_len,
const unsigned char *in, size_t in_len,
unsigned char *obuf, size_t buf_len, size_t *olen )
@@ -3276,26 +3297,53 @@ static int ssl_check_dtls_clihlo_cookie(
*
* Minimum length is 61 bytes.
*/
- if( in_len < 61 ||
- in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: in_len=%u",
+ (unsigned) in_len ) );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "cli_id", cli_id, cli_id_len );
+ if( in_len < 61 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: record too short" ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ if( in[0] != MBEDTLS_SSL_MSG_HANDSHAKE ||
in[3] != 0 || in[4] != 0 ||
in[19] != 0 || in[20] != 0 || in[21] != 0 )
{
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: not a good ClientHello" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( " type=%u epoch=%u fragment_offset=%u",
+ in[0],
+ (unsigned) in[3] << 8 | in[4],
+ (unsigned) in[19] << 16 | in[20] << 8 | in[21] ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
sid_len = in[59];
- if( sid_len > in_len - 61 )
+ if( 59 + 1 + sid_len + 1 > in_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: sid_len=%u > %u",
+ (unsigned) sid_len,
+ (unsigned) in_len - 61 ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
+ MBEDTLS_SSL_DEBUG_BUF( 4, "sid received from network",
+ in + 60, sid_len );
cookie_len = in[60 + sid_len];
- if( cookie_len > in_len - 60 )
+ if( 59 + 1 + sid_len + 1 + cookie_len > in_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: cookie_len=%u > %u",
+ (unsigned) cookie_len,
+ (unsigned) ( in_len - sid_len - 61 ) ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
- if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len,
- cli_id, cli_id_len ) == 0 )
+ MBEDTLS_SSL_DEBUG_BUF( 4, "cookie received from network",
+ in + sid_len + 61, cookie_len );
+ if( ssl->conf->f_cookie_check( ssl->conf->p_cookie,
+ in + sid_len + 61, cookie_len,
+ cli_id, cli_id_len ) == 0 )
{
- /* Valid cookie */
+ MBEDTLS_SSL_DEBUG_MSG( 4, ( "check cookie: valid" ) );
return( 0 );
}
@@ -3330,8 +3378,9 @@ static int ssl_check_dtls_clihlo_cookie(
/* Generate and write actual cookie */
p = obuf + 28;
- if( f_cookie_write( p_cookie,
- &p, obuf + buf_len, cli_id, cli_id_len ) != 0 )
+ if( ssl->conf->f_cookie_write( ssl->conf->p_cookie,
+ &p, obuf + buf_len,
+ cli_id, cli_id_len ) != 0 )
{
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
@@ -3370,6 +3419,7 @@ static int ssl_check_dtls_clihlo_cookie(
* includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected
* errors, and is the right thing to do in both cases).
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3385,15 +3435,13 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
return( 0 );
}
- ret = ssl_check_dtls_clihlo_cookie(
- ssl->conf->f_cookie_write,
- ssl->conf->f_cookie_check,
- ssl->conf->p_cookie,
+ ret = mbedtls_ssl_check_dtls_clihlo_cookie(
+ ssl,
ssl->cli_id, ssl->cli_id_len,
ssl->in_buf, ssl->in_left,
ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len );
- MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret );
+ MBEDTLS_SSL_DEBUG_RET( 2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret );
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{
@@ -3427,6 +3475,7 @@ static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl )
}
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_record_type( uint8_t record_type )
{
if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE &&
@@ -3459,6 +3508,7 @@ static int ssl_check_record_type( uint8_t record_type )
* Point 2 is needed when the peer is resending, and we have already received
* the first record from a datagram but are still waiting for the others.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
unsigned char *buf,
size_t len,
@@ -3571,7 +3621,6 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
/*
* Parse and validate record version
*/
-
rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
mbedtls_ssl_read_version( &major_ver, &minor_ver,
@@ -3580,16 +3629,19 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
if( major_ver != ssl->major_ver )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch: got %u, expected %u",
+ (unsigned) major_ver,
+ (unsigned) ssl->major_ver ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
if( minor_ver > ssl->conf->max_minor_ver )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch: got %u, expected max %u",
+ (unsigned) minor_ver,
+ (unsigned) ssl->conf->max_minor_ver ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
-
/*
* Parse/Copy record sequence number.
*/
@@ -3692,6 +3744,7 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
{
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
@@ -3721,6 +3774,7 @@ static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
/*
* If applicable, decrypt record content
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
mbedtls_record *rec )
{
@@ -3854,7 +3908,7 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
/* Check actual (decrypted) record content length against
* configured maximum. */
- if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+ if( rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
@@ -3872,8 +3926,11 @@ static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
*/
/* Helper functions for mbedtls_ssl_read_record(). */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record( mbedtls_ssl_context *ssl );
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl );
int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
@@ -3961,6 +4018,7 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_PROTO_DTLS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
{
if( ssl->in_left > ssl->next_record_offset )
@@ -3969,6 +4027,7 @@ static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -4066,6 +4125,7 @@ exit:
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
size_t desired )
{
@@ -4108,6 +4168,7 @@ static int ssl_buffer_make_space( mbedtls_ssl_context *ssl,
return( -1 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_message( mbedtls_ssl_context *ssl )
{
int ret = 0;
@@ -4312,6 +4373,7 @@ exit:
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
{
/*
@@ -4399,6 +4461,7 @@ static int ssl_consume_current_message( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl )
{
if( ssl->in_msglen > 0 )
@@ -4425,6 +4488,7 @@ static void ssl_free_buffered_record( mbedtls_ssl_context *ssl )
}
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
@@ -4482,6 +4546,7 @@ exit:
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
mbedtls_record const *rec )
{
@@ -4540,6 +4605,7 @@ static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_next_record( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -4918,6 +4984,9 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
if( ssl == NULL || ssl->conf == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
+ if( ssl->out_left != 0 )
+ return( mbedtls_ssl_flush_output( ssl ) );
+
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message ));
@@ -5287,6 +5356,7 @@ int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl )
/*
* Check record counters and renegotiate if they're above the limit.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl )
{
size_t ep_len = mbedtls_ssl_ep_len( ssl );
@@ -5637,6 +5707,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
* Therefore, it is possible that the input message length is 0 and the
* corresponding return code is 0 on success.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_real( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -5708,6 +5779,7 @@ static int ssl_write_real( mbedtls_ssl_context *ssl,
* remember whether we already did the split or not.
*/
#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_split( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -5790,9 +5862,6 @@ int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) );
- if( ssl->out_left != 0 )
- return( mbedtls_ssl_flush_output( ssl ) );
-
if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
{
if( ( ret = mbedtls_ssl_send_alert_message( ssl,
diff --git a/thirdparty/mbedtls/library/ssl_srv.c b/thirdparty/mbedtls/library/ssl_srv.c
index 1a63173204..2efb13cc33 100644
--- a/thirdparty/mbedtls/library/ssl_srv.c
+++ b/thirdparty/mbedtls/library/ssl_srv.c
@@ -78,6 +78,7 @@ void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf,
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -147,6 +148,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
{
if( conf->f_psk != NULL )
@@ -167,6 +169,7 @@ static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
@@ -188,6 +191,7 @@ static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -239,6 +243,7 @@ static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl,
* This needs to be done at a later stage.
*
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -317,6 +322,7 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -383,6 +389,7 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -425,6 +432,7 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -454,6 +462,7 @@ static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -473,6 +482,7 @@ static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -545,6 +555,7 @@ static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
#if defined(MBEDTLS_SSL_TRUNCATED_HMAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -567,6 +578,7 @@ static int ssl_parse_truncated_hmac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */
#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -592,6 +604,7 @@ static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -617,6 +630,7 @@ static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
unsigned char *buf,
size_t len )
@@ -691,6 +705,7 @@ static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
#if defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf, size_t len )
{
@@ -779,6 +794,7 @@ static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_DTLS_SRTP)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -907,6 +923,7 @@ static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl,
* Return 0 if the given key uses one of the acceptable curves, -1 otherwise
*/
#if defined(MBEDTLS_ECDSA_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_key_curve( mbedtls_pk_context *pk,
const mbedtls_ecp_curve_info **curves )
{
@@ -928,6 +945,7 @@ static int ssl_check_key_curve( mbedtls_pk_context *pk,
* Try picking a certificate for this ciphersuite,
* return 0 on success and -1 on failure.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_pick_cert( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t * ciphersuite_info )
{
@@ -1032,6 +1050,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
* Check if a given ciphersuite is suitable for use with our config/keys/etc
* Sets ciphersuite_info only if the suite matches.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
const mbedtls_ssl_ciphersuite_t **ciphersuite_info )
{
@@ -1147,6 +1166,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id,
}
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_hello_v2( mbedtls_ssl_context *ssl )
{
int ret, got_common_suite;
@@ -1410,6 +1430,7 @@ have_ciphersuite_v2:
/* This function doesn't alert on errors that happen early during
ClientHello parsing because they might indicate that the client is
not talking SSL/TLS at all and would not understand our alert. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_hello( mbedtls_ssl_context *ssl )
{
int ret, got_common_suite;
@@ -1583,7 +1604,7 @@ read_record_header:
* Handshake layer:
* 0 . 0 handshake type
* 1 . 3 handshake length
- * 4 . 5 DTLS only: message seqence number
+ * 4 . 5 DTLS only: message sequence number
* 6 . 8 DTLS only: fragment offset
* 9 . 11 DTLS only: fragment length
*/
@@ -1604,11 +1625,19 @@ read_record_header:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d",
( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) );
+ if( buf[1] != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != 0",
+ (unsigned) buf[1] ) );
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
+ }
/* We don't support fragmentation of ClientHello (yet?) */
- if( buf[1] != 0 ||
- msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
+ if( msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message: %u != %u + %u",
+ (unsigned) msg_len,
+ (unsigned) mbedtls_ssl_hs_hdr_len( ssl ),
+ (unsigned) ( buf[2] << 8 ) | buf[3] ) );
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
@@ -1649,6 +1678,11 @@ read_record_header:
* For now we don't support fragmentation, so make sure
* fragment_offset == 0 and fragment_length == length
*/
+ MBEDTLS_SSL_DEBUG_MSG(
+ 4, ( "fragment_offset=%u fragment_length=%u length=%u",
+ (unsigned) ( ssl->in_msg[6] << 16 | ssl->in_msg[7] << 8 | ssl->in_msg[8] ),
+ (unsigned) ( ssl->in_msg[9] << 16 | ssl->in_msg[10] << 8 | ssl->in_msg[11] ),
+ (unsigned) ( ssl->in_msg[1] << 16 | ssl->in_msg[2] << 8 | ssl->in_msg[3] ) ) );
if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 ||
memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 )
{
@@ -2354,12 +2388,8 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
const mbedtls_ssl_ciphersuite_t *suite = NULL;
const mbedtls_cipher_info_t *cipher = NULL;
- if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ||
- ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
- {
- *olen = 0;
- return;
- }
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
+ ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
/*
* RFC 7366: "If a server receives an encrypt-then-MAC request extension
@@ -2372,6 +2402,11 @@ static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl,
( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL ||
cipher->mode != MBEDTLS_MODE_CBC )
{
+ ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_DISABLED;
+ }
+
+ if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED )
+ {
*olen = 0;
return;
}
@@ -2685,6 +2720,7 @@ static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl,
#endif /* MBEDTLS_SSL_DTLS_SRTP */
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -2805,6 +2841,7 @@ exit:
mbedtls_ssl_session_free( &session_tmp );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
{
#if defined(MBEDTLS_HAVE_TIME)
@@ -3035,6 +3072,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -3053,6 +3091,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -3222,18 +3261,23 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_pk_context *own_key = mbedtls_ssl_own_key( ssl );
- if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) )
+ /* Check if the key is a transparent ECDH key.
+ * This also ensures that it is safe to call mbedtls_pk_ec(). */
+ if( mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY &&
+ mbedtls_pk_get_type( own_key ) != MBEDTLS_PK_ECKEY_DH )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
}
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx,
- mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ),
+ mbedtls_pk_ec( *own_key ),
MBEDTLS_ECDH_OURS ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret );
@@ -3247,6 +3291,7 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
@@ -3274,6 +3319,7 @@ static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
/* Prepare the ServerKeyExchange message, up to and including
* calculating the signature if any, but excluding formatting the
* signature and sending the message. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
@@ -3643,6 +3689,7 @@ curve_matching_done:
* that do not include a ServerKeyExchange message, do nothing. Either
* way, if successful, move on to the next step in the SSL state
* machine. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3664,7 +3711,12 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
- ssl_get_ecdh_params_from_cert( ssl );
+ ret = ssl_get_ecdh_params_from_cert( ssl );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret );
+ return( ret );
+ }
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
@@ -3740,6 +3792,7 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( 0 );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -3779,6 +3832,7 @@ static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p,
const unsigned char *end )
{
@@ -3822,6 +3876,7 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
unsigned char *peer_pms,
size_t *peer_pmslen,
@@ -3839,6 +3894,7 @@ static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
@@ -3931,6 +3987,7 @@ static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
@@ -4020,6 +4077,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p,
const unsigned char *end )
{
@@ -4080,6 +4138,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -4207,7 +4266,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
- /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically
+ /* For opaque PSKs, we perform the PSK-to-MS derivation automatically
* and skip the intermediate PMS. */
if( ssl_use_opaque_psk( ssl ) == 1 )
MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) );
@@ -4247,7 +4306,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with RSA-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 )
@@ -4282,7 +4344,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with DHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
if( p != end )
@@ -4319,7 +4384,10 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/* Opaque PSKs are currently only supported for PSK-only. */
if( ssl_use_opaque_psk( ssl ) == 1 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "opaque PSK not supported with ECDHE-PSK" ) );
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ }
#endif
MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx,
@@ -4386,6 +4454,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
}
#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
{
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
@@ -4404,6 +4473,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -4597,6 +4667,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
diff --git a/thirdparty/mbedtls/library/ssl_ticket.c b/thirdparty/mbedtls/library/ssl_ticket.c
index 046ed1b2ff..e0126cc9d1 100644
--- a/thirdparty/mbedtls/library/ssl_ticket.c
+++ b/thirdparty/mbedtls/library/ssl_ticket.c
@@ -37,7 +37,7 @@
#include <string.h>
/*
- * Initialze context
+ * Initialize context
*/
void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
{
@@ -66,6 +66,7 @@ void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx )
/*
* Generate/update a key
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
unsigned char index )
{
@@ -96,6 +97,7 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx,
/*
* Rotate/generate keys if necessary
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx )
{
#if !defined(MBEDTLS_HAVE_TIME)
diff --git a/thirdparty/mbedtls/library/ssl_tls.c b/thirdparty/mbedtls/library/ssl_tls.c
index 2e6469de83..7badec51ae 100644
--- a/thirdparty/mbedtls/library/ssl_tls.c
+++ b/thirdparty/mbedtls/library/ssl_tls.c
@@ -245,6 +245,7 @@ int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
}
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old )
{
unsigned char* resized_buffer = mbedtls_calloc( 1, len_new );
@@ -337,6 +338,7 @@ static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing,
* Key material generation
*/
#if defined(MBEDTLS_SSL_PROTO_SSL3)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl3_prf( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -398,6 +400,7 @@ exit:
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls1_prf( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -605,6 +608,7 @@ static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* de
return( PSA_SUCCESS );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
const char *label,
@@ -679,6 +683,7 @@ static int tls_prf_generic( mbedtls_md_type_t md_type,
#else /* MBEDTLS_USE_PSA_CRYPTO */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_generic( mbedtls_md_type_t md_type,
const unsigned char *secret, size_t slen,
const char *label,
@@ -770,6 +775,7 @@ exit:
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_SHA256_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_sha256( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -781,6 +787,7 @@ static int tls_prf_sha256( const unsigned char *secret, size_t slen,
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_SHA512_NO_SHA384)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int tls_prf_sha384( const unsigned char *secret, size_t slen,
const char *label,
const unsigned char *random, size_t rlen,
@@ -825,6 +832,7 @@ static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *
#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl )
{
if( ssl->conf->f_psk != NULL )
@@ -949,6 +957,7 @@ typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *,
* - MBEDTLS_SSL_EXPORT_KEYS: ssl->conf->{f,p}_export_keys
* - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_populate_transform( mbedtls_ssl_transform *transform,
int ciphersuite,
const unsigned char master[48],
@@ -990,6 +999,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
#if !defined(MBEDTLS_SSL_HW_RECORD_ACCEL) && \
!defined(MBEDTLS_SSL_EXPORT_KEYS) && \
+ !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
!defined(MBEDTLS_DEBUG_C)
ssl = NULL; /* make sure we don't use it except for those cases */
(void) ssl;
@@ -1361,7 +1371,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc,
cipher_info, transform->taglen );
@@ -1404,7 +1414,7 @@ static int ssl_populate_transform( mbedtls_ssl_transform *transform,
* the structure field for the IV, which the PSA-based
* implementation currently doesn't. */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
+ if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec,
cipher_info, transform->taglen );
@@ -1511,6 +1521,7 @@ end:
* Outputs:
* - the tls_prf, calc_verify and calc_finished members of handshake structure
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
int minor_ver,
mbedtls_md_type_t hash )
@@ -1580,6 +1591,7 @@ static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake,
* EMS: passed to calc_verify (debug + (SSL3) session_negotiate)
* PSA-PSA: minor_ver, conf
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake,
unsigned char *master,
const mbedtls_ssl_context *ssl )
@@ -2108,6 +2120,7 @@ int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exch
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_request( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_PROTO_DTLS)
@@ -2323,6 +2336,7 @@ write_msg:
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
unsigned char *crt_buf,
size_t crt_buf_len )
@@ -2338,6 +2352,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) );
}
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
unsigned char *crt_buf,
size_t crt_buf_len )
@@ -2372,6 +2387,7 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
* Once the certificate message is read, parse it into a cert chain and
* perform basic checks, but leave actual verification to the caller
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *chain )
{
@@ -2521,6 +2537,7 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
}
#if defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
{
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
@@ -2570,6 +2587,7 @@ static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
*/
#define SSL_CERTIFICATE_EXPECTED 0
#define SSL_CERTIFICATE_SKIP 1
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
int authmode )
{
@@ -2599,6 +2617,7 @@ static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
return( SSL_CERTIFICATE_EXPECTED );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
int authmode,
mbedtls_x509_crt *chain,
@@ -2696,7 +2715,9 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
{
const mbedtls_pk_context *pk = &chain->pk;
- /* If certificate uses an EC key, make sure the curve is OK */
+ /* If certificate uses an EC key, make sure the curve is OK.
+ * This is a public key, so it can't be opaque, so can_do() is a good
+ * enough check to ensure pk_ec() is safe to use here. */
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 )
{
@@ -2787,6 +2808,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
@@ -2818,6 +2840,7 @@ static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
return( ret );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
unsigned char *start, size_t len )
{
@@ -3428,7 +3451,7 @@ void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
ssl->handshake = NULL;
/*
- * Free the previous transform and swith in the current one
+ * Free the previous transform and switch in the current one
*/
if( ssl->transform )
{
@@ -3796,6 +3819,7 @@ void mbedtls_ssl_session_init( mbedtls_ssl_session *session )
memset( session, 0, sizeof(mbedtls_ssl_session) );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_handshake_init( mbedtls_ssl_context *ssl )
{
/* Clear old handshake information if present */
@@ -3873,6 +3897,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
/* Dummy cookie callbacks for defaults */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_write_dummy( void *ctx,
unsigned char **p, unsigned char *end,
const unsigned char *cli_id, size_t cli_id_len )
@@ -3886,6 +3911,7 @@ static int ssl_cookie_write_dummy( void *ctx,
return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
}
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_cookie_check_dummy( void *ctx,
const unsigned char *cookie, size_t cookie_len,
const unsigned char *cli_id, size_t cli_id_len )
@@ -4303,6 +4329,7 @@ void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf,
}
/* Append a new keycert entry to a (possibly empty) list */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_append_key_cert( mbedtls_ssl_key_cert **head,
mbedtls_x509_crt *cert,
mbedtls_pk_context *key )
@@ -4471,6 +4498,7 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf )
* It checks that the provided identity is well-formed and attempts
* to make a copy of it in the SSL config.
* On failure, the PSK identity in the config remains unset. */
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf,
unsigned char const *psk_identity,
size_t psk_identity_len )
@@ -4632,6 +4660,9 @@ int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf,
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_mpi_free( &conf->dhm_P );
+ mbedtls_mpi_free( &conf->dhm_G );
+
if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 ||
( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 )
{
@@ -4647,6 +4678,9 @@ int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ mbedtls_mpi_free( &conf->dhm_P );
+ mbedtls_mpi_free( &conf->dhm_G );
+
if( ( ret = mbedtls_mpi_copy( &conf->dhm_P, &dhm_ctx->P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &conf->dhm_G, &dhm_ctx->G ) ) != 0 )
{
@@ -5384,6 +5418,7 @@ static unsigned char ssl_serialized_session_header[] = {
* verify_result is put before peer_cert so that all mandatory fields come
* together in one block.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_session_save( const mbedtls_ssl_session *session,
unsigned char omit_header,
unsigned char *buf,
@@ -5583,6 +5618,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
* This internal version is wrapped by a public function that cleans up in
* case of error, and has an extra option omit_header.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_session_load( mbedtls_ssl_session *session,
unsigned char omit_header,
const unsigned char *buf,
@@ -5886,6 +5922,7 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl )
/*
* Write HelloRequest to request renegotiation on server
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_write_hello_request( mbedtls_ssl_context *ssl )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -6497,6 +6534,7 @@ static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id )
* This internal version is wrapped by a public function that cleans up in
* case of error.
*/
+MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_context_load( mbedtls_ssl_context *ssl,
const unsigned char *buf,
size_t len )
@@ -7320,6 +7358,18 @@ int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_i
return( -1 );
}
+
+/*
+ * Same as mbedtls_ssl_check_curve() but takes a TLS ID for the curve.
+ */
+int mbedtls_ssl_check_curve_tls_id( const mbedtls_ssl_context *ssl, uint16_t tls_id )
+{
+ const mbedtls_ecp_curve_info *curve_info =
+ mbedtls_ecp_curve_info_from_tls_id( tls_id );
+ if( curve_info == NULL )
+ return( -1 );
+ return( mbedtls_ssl_check_curve( ssl, curve_info->grp_id ) );
+}
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
diff --git a/thirdparty/mbedtls/library/threading.c b/thirdparty/mbedtls/library/threading.c
index 2de117f52a..5e0aaa4f21 100644
--- a/thirdparty/mbedtls/library/threading.c
+++ b/thirdparty/mbedtls/library/threading.c
@@ -113,7 +113,7 @@ int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_
int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread;
/*
- * With phtreads we can statically initialize mutexes
+ * With pthreads we can statically initialize mutexes
*/
#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 }
diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c
index eb41461320..57bc9bcc12 100644
--- a/thirdparty/mbedtls/library/timing.c
+++ b/thirdparty/mbedtls/library/timing.c
@@ -56,15 +56,15 @@ struct _hr_time
#include <unistd.h>
#include <sys/types.h>
-#include <sys/time.h>
#include <signal.h>
+/* time.h should be included independently of MBEDTLS_HAVE_TIME. If the
+ * platform matches the ifdefs above, it will be used. */
#include <time.h>
-
+#include <sys/time.h>
struct _hr_time
{
struct timeval start;
};
-
#endif /* _WIN32 && !EFIX64 && !EFI32 */
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
@@ -364,7 +364,6 @@ int mbedtls_timing_get_delay( void *data )
return( 0 );
}
-#endif /* !MBEDTLS_TIMING_ALT */
#if defined(MBEDTLS_SELF_TEST)
@@ -526,5 +525,5 @@ hard_test_done:
}
#endif /* MBEDTLS_SELF_TEST */
-
+#endif /* !MBEDTLS_TIMING_ALT */
#endif /* MBEDTLS_TIMING_C */
diff --git a/thirdparty/mbedtls/library/x509.c b/thirdparty/mbedtls/library/x509.c
index f21e9e6944..3997ebd1f3 100644
--- a/thirdparty/mbedtls/library/x509.c
+++ b/thirdparty/mbedtls/library/x509.c
@@ -741,7 +741,7 @@ int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end,
int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t i, n;
+ size_t i, j, n;
unsigned char c, merge = 0;
const mbedtls_x509_name *name;
const char *short_name = NULL;
@@ -775,17 +775,24 @@ int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn )
ret = mbedtls_snprintf( p, n, "\?\?=" );
MBEDTLS_X509_SAFE_SNPRINTF;
- for( i = 0; i < name->val.len; i++ )
+ for( i = 0, j = 0; i < name->val.len; i++, j++ )
{
- if( i >= sizeof( s ) - 1 )
- break;
+ if( j >= sizeof( s ) - 1 )
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
c = name->val.p[i];
+ // Special characters requiring escaping, RFC 1779
+ if( c && strchr( ",=+<>#;\"\\", c ) )
+ {
+ if( j + 1 >= sizeof( s ) - 1 )
+ return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL );
+ s[j++] = '\\';
+ }
if( c < 32 || c >= 127 )
- s[i] = '?';
- else s[i] = c;
+ s[j] = '?';
+ else s[j] = c;
}
- s[i] = '\0';
+ s[j] = '\0';
ret = mbedtls_snprintf( p, n, "%s", s );
MBEDTLS_X509_SAFE_SNPRINTF;
diff --git a/thirdparty/mbedtls/library/x509_crl.c b/thirdparty/mbedtls/library/x509_crl.c
index ac4fc75de3..d2d8042029 100644
--- a/thirdparty/mbedtls/library/x509_crl.c
+++ b/thirdparty/mbedtls/library/x509_crl.c
@@ -52,11 +52,13 @@
#define mbedtls_snprintf snprintf
#endif
+#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#else
#include <time.h>
#endif
+#endif
#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
#include <stdio.h>
diff --git a/thirdparty/mbedtls/library/x509_crt.c b/thirdparty/mbedtls/library/x509_crt.c
index 60312bf2f5..96477e4c9d 100644
--- a/thirdparty/mbedtls/library/x509_crt.c
+++ b/thirdparty/mbedtls/library/x509_crt.c
@@ -63,6 +63,7 @@
#include "mbedtls/threading.h"
#endif
+#if defined(MBEDTLS_HAVE_TIME)
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#if defined(_MSC_VER) && _MSC_VER <= 1600
@@ -81,6 +82,7 @@
#else
#include <time.h>
#endif
+#endif
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
diff --git a/thirdparty/mbedtls/library/x509write_crt.c b/thirdparty/mbedtls/library/x509write_crt.c
index 184c90cd33..0c5e991834 100644
--- a/thirdparty/mbedtls/library/x509write_crt.c
+++ b/thirdparty/mbedtls/library/x509write_crt.c
@@ -299,7 +299,7 @@ static int x509_write_time( unsigned char **p, unsigned char *start,
/*
* write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter)
*/
- if( t[0] == '2' && t[1] == '0' && t[2] < '5' )
+ if( t[0] < '2' || ( t[0] == '2' && t[1] == '0' && t[2] < '5' ) )
{
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) t + 2,
diff --git a/thirdparty/meshoptimizer/allocator.cpp b/thirdparty/meshoptimizer/allocator.cpp
index da7cc540b2..072e8e51ac 100644
--- a/thirdparty/meshoptimizer/allocator.cpp
+++ b/thirdparty/meshoptimizer/allocator.cpp
@@ -1,7 +1,7 @@
// This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
#include "meshoptimizer.h"
-void meshopt_setAllocator(void* (*allocate)(size_t), void (*deallocate)(void*))
+void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*))
{
meshopt_Allocator::Storage::allocate = allocate;
meshopt_Allocator::Storage::deallocate = deallocate;
diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
index a420eb1098..463fad29da 100644
--- a/thirdparty/meshoptimizer/meshoptimizer.h
+++ b/thirdparty/meshoptimizer/meshoptimizer.h
@@ -1,5 +1,5 @@
/**
- * meshoptimizer - version 0.16
+ * meshoptimizer - version 0.17
*
* Copyright (C) 2016-2021, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at https://github.com/zeux/meshoptimizer
@@ -12,13 +12,22 @@
#include <stddef.h>
/* Version macro; major * 1000 + minor * 10 + patch */
-#define MESHOPTIMIZER_VERSION 160 /* 0.16 */
+#define MESHOPTIMIZER_VERSION 170 /* 0.17 */
/* If no API is defined, assume default */
#ifndef MESHOPTIMIZER_API
#define MESHOPTIMIZER_API
#endif
+/* Set the calling-convention for alloc/dealloc function pointers */
+#ifndef MESHOPTIMIZER_ALLOC_CALLCONV
+#ifdef _MSC_VER
+#define MESHOPTIMIZER_ALLOC_CALLCONV __cdecl
+#else
+#define MESHOPTIMIZER_ALLOC_CALLCONV
+#endif
+#endif
+
/* Experimental APIs have unstable interface and might have implementation that's not fully tested or optimized */
#define MESHOPTIMIZER_EXPERIMENTAL MESHOPTIMIZER_API
@@ -108,7 +117,7 @@ MESHOPTIMIZER_API void meshopt_generateShadowIndexBufferMulti(unsigned int* dest
* destination must contain enough space for the resulting index buffer (index_count*2 elements)
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
*/
-MESHOPTIMIZER_EXPERIMENTAL void meshopt_generateAdjacencyIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+MESHOPTIMIZER_API void meshopt_generateAdjacencyIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
/**
* Generate index buffer that can be used for PN-AEN tessellation with crack-free displacement
@@ -124,7 +133,7 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_generateAdjacencyIndexBuffer(unsigned in
* destination must contain enough space for the resulting index buffer (index_count*4 elements)
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
*/
-MESHOPTIMIZER_EXPERIMENTAL void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+MESHOPTIMIZER_API void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
/**
* Vertex transform cache optimizer
@@ -201,10 +210,10 @@ MESHOPTIMIZER_API size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t
MESHOPTIMIZER_API size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count);
/**
- * Experimental: Set index encoder format version
+ * Set index encoder format version
* version must specify the data format version to encode; valid values are 0 (decodable by all library versions) and 1 (decodable by 0.14+)
*/
-MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeIndexVersion(int version);
+MESHOPTIMIZER_API void meshopt_encodeIndexVersion(int version);
/**
* Index buffer decoder
@@ -217,15 +226,15 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeIndexVersion(int version);
MESHOPTIMIZER_API int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size);
/**
- * Experimental: Index sequence encoder
+ * Index sequence encoder
* Encodes index sequence into an array of bytes that is generally smaller and compresses better compared to original.
* Input index sequence can represent arbitrary topology; for triangle lists meshopt_encodeIndexBuffer is likely to be better.
* Returns encoded data size on success, 0 on error; the only error condition is if buffer doesn't have enough space
*
* buffer must contain enough space for the encoded index sequence (use meshopt_encodeIndexSequenceBound to compute worst case size)
*/
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count);
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_encodeIndexSequenceBound(size_t index_count, size_t vertex_count);
+MESHOPTIMIZER_API size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count);
+MESHOPTIMIZER_API size_t meshopt_encodeIndexSequenceBound(size_t index_count, size_t vertex_count);
/**
* Index sequence decoder
@@ -235,7 +244,7 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_encodeIndexSequenceBound(size_t index_
*
* destination must contain enough space for the resulting index sequence (index_count elements)
*/
-MESHOPTIMIZER_EXPERIMENTAL int meshopt_decodeIndexSequence(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size);
+MESHOPTIMIZER_API int meshopt_decodeIndexSequence(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size);
/**
* Vertex buffer encoder
@@ -250,10 +259,10 @@ MESHOPTIMIZER_API size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_
MESHOPTIMIZER_API size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size);
/**
- * Experimental: Set vertex encoder format version
+ * Set vertex encoder format version
* version must specify the data format version to encode; valid values are 0 (decodable by all library versions)
*/
-MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeVertexVersion(int version);
+MESHOPTIMIZER_API void meshopt_encodeVertexVersion(int version);
/**
* Vertex buffer decoder
@@ -285,15 +294,15 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t cou
/**
* Vertex buffer filter encoders
* These functions can be used to encode data in a format that meshopt_decodeFilter can decode
- *
+ *
* meshopt_encodeFilterOct encodes unit vectors with K-bit (K <= 16) signed X/Y as an output.
* Each component is stored as an 8-bit or 16-bit normalized integer; stride must be equal to 4 or 8. W is preserved as is.
* Input data must contain 4 floats for every vector (count*4 total).
- *
+ *
* meshopt_encodeFilterQuat encodes unit quaternions with K-bit (4 <= K <= 16) component encoding.
* Each component is stored as an 16-bit integer; stride must be equal to 8.
* Input data must contain 4 floats for every quaternion (count*4 total).
- *
+ *
* meshopt_encodeFilterExp encodes arbitrary (finite) floating-point data with 8-bit exponent and K-bit integer mantissa (1 <= K <= 24).
* Mantissa is shared between all components of a given vector as defined by stride; stride must be divisible by 4.
* Input data must contain stride/4 floats for every vector (count*stride/4 total).
@@ -353,7 +362,7 @@ MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplifyPoints(unsigned int* destinati
/**
* Experimental: Returns the error scaling factor used by the simplifier to convert between absolute and relative extents
- *
+ *
* Absolute error must be *divided* by the scaling factor before passing it to meshopt_simplify as target_error
* Relative error returned by meshopt_simplify via result_error must be *multiplied* by the scaling factor to get absolute error.
*/
@@ -438,7 +447,7 @@ struct meshopt_Meshlet
};
/**
- * Experimental: Meshlet builder
+ * Meshlet builder
* Splits the mesh into a set of meshlets where each meshlet has a micro index buffer indexing into meshlet vertices that refer to the original vertex buffer
* The resulting data can be used to render meshes using NVidia programmable mesh shading pipeline, or in other cluster-based renderers.
* When using buildMeshlets, vertex positions need to be provided to minimize the size of the resulting clusters.
@@ -451,9 +460,9 @@ struct meshopt_Meshlet
* max_vertices and max_triangles must not exceed implementation limits (max_vertices <= 255 - not 256!, max_triangles <= 512)
* cone_weight should be set to 0 when cone culling is not used, and a value between 0 and 1 otherwise to balance between cluster size and cone culling efficiency
*/
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshlets(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t max_triangles, float cone_weight);
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshletsScan(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles);
-MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_t max_triangles);
+MESHOPTIMIZER_API size_t meshopt_buildMeshlets(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t max_vertices, size_t max_triangles, float cone_weight);
+MESHOPTIMIZER_API size_t meshopt_buildMeshletsScan(struct meshopt_Meshlet* meshlets, unsigned int* meshlet_vertices, unsigned char* meshlet_triangles, const unsigned int* indices, size_t index_count, size_t vertex_count, size_t max_vertices, size_t max_triangles);
+MESHOPTIMIZER_API size_t meshopt_buildMeshletsBound(size_t index_count, size_t max_vertices, size_t max_triangles);
struct meshopt_Bounds
{
@@ -472,7 +481,7 @@ struct meshopt_Bounds
};
/**
- * Experimental: Cluster bounds generator
+ * Cluster bounds generator
* Creates bounding volumes that can be used for frustum, backface and occlusion culling.
*
* For backface culling with orthographic projection, use the following formula to reject backfacing clusters:
@@ -492,8 +501,8 @@ struct meshopt_Bounds
* vertex_positions should have float3 position in the first 12 bytes of each vertex - similar to glVertexPointer
* index_count/3 should be less than or equal to 512 (the function assumes clusters of limited size)
*/
-MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
-MESHOPTIMIZER_EXPERIMENTAL struct meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices, const unsigned char* meshlet_triangles, size_t triangle_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeClusterBounds(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
+MESHOPTIMIZER_API struct meshopt_Bounds meshopt_computeMeshletBounds(const unsigned int* meshlet_vertices, const unsigned char* meshlet_triangles, size_t triangle_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride);
/**
* Experimental: Spatial sorter
@@ -519,7 +528,7 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_spatialSortTriangles(unsigned int* desti
* Note that all algorithms only allocate memory for temporary use.
* allocate/deallocate are always called in a stack-like order - last pointer to be allocated is deallocated first.
*/
-MESHOPTIMIZER_API void meshopt_setAllocator(void* (*allocate)(size_t), void (*deallocate)(void*));
+MESHOPTIMIZER_API void meshopt_setAllocator(void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t), void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*));
#ifdef __cplusplus
} /* extern "C" */
@@ -701,8 +710,8 @@ public:
template <typename T>
struct StorageT
{
- static void* (*allocate)(size_t);
- static void (*deallocate)(void*);
+ static void* (MESHOPTIMIZER_ALLOC_CALLCONV *allocate)(size_t);
+ static void (MESHOPTIMIZER_ALLOC_CALLCONV *deallocate)(void*);
};
typedef StorageT<void> Storage;
@@ -733,8 +742,8 @@ private:
};
// This makes sure that allocate/deallocate are lazily generated in translation units that need them and are deduplicated by the linker
-template <typename T> void* (*meshopt_Allocator::StorageT<T>::allocate)(size_t) = operator new;
-template <typename T> void (*meshopt_Allocator::StorageT<T>::deallocate)(void*) = operator delete;
+template <typename T> void* (MESHOPTIMIZER_ALLOC_CALLCONV *meshopt_Allocator::StorageT<T>::allocate)(size_t) = operator new;
+template <typename T> void (MESHOPTIMIZER_ALLOC_CALLCONV *meshopt_Allocator::StorageT<T>::deallocate)(void*) = operator delete;
#endif
/* Inline implementation for C++ templated wrappers */
diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch
index 54132a6c86..21daac6eec 100644
--- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch
+++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify-distance-only-metric.patch
@@ -1,5 +1,5 @@
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
-index 0f10ebef4b..cf5db4e119 100644
+index 5e92e2dc73..e40c141e76 100644
--- a/thirdparty/meshoptimizer/simplifier.cpp
+++ b/thirdparty/meshoptimizer/simplifier.cpp
@@ -20,7 +20,7 @@
@@ -11,7 +11,7 @@ index 0f10ebef4b..cf5db4e119 100644
// This work is based on:
// Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
-@@ -445,6 +445,7 @@ struct Collapse
+@@ -453,6 +453,7 @@ struct Collapse
float error;
unsigned int errorui;
};
@@ -19,7 +19,7 @@ index 0f10ebef4b..cf5db4e119 100644
};
static float normalize(Vector3& v)
-@@ -525,6 +526,34 @@ static float quadricError(const Quadric& Q, const Vector3& v)
+@@ -533,6 +534,34 @@ static float quadricError(const Quadric& Q, const Vector3& v)
return fabsf(r) * s;
}
@@ -54,7 +54,7 @@ index 0f10ebef4b..cf5db4e119 100644
static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, float w)
{
float aw = a * w;
-@@ -680,7 +709,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3
+@@ -688,7 +717,7 @@ static void quadricUpdateAttributes(Quadric& Q, const Vector3& p0, const Vector3
}
#endif
@@ -63,7 +63,7 @@ index 0f10ebef4b..cf5db4e119 100644
{
for (size_t i = 0; i < index_count; i += 3)
{
-@@ -690,6 +719,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+@@ -698,6 +727,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
Quadric Q;
quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
@@ -73,7 +73,7 @@ index 0f10ebef4b..cf5db4e119 100644
#if ATTRIBUTES
quadricUpdateAttributes(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], Q.w);
-@@ -700,7 +732,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+@@ -708,7 +740,7 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
}
}
@@ -82,7 +82,7 @@ index 0f10ebef4b..cf5db4e119 100644
{
for (size_t i = 0; i < index_count; i += 3)
{
-@@ -744,6 +776,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+@@ -752,6 +784,9 @@ static void fillEdgeQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
quadricAdd(vertex_quadrics[remap[i0]], Q);
quadricAdd(vertex_quadrics[remap[i1]], Q);
@@ -92,7 +92,7 @@ index 0f10ebef4b..cf5db4e119 100644
}
}
}
-@@ -848,7 +883,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices
+@@ -856,7 +891,7 @@ static size_t pickEdgeCollapses(Collapse* collapses, const unsigned int* indices
return collapse_count;
}
@@ -101,7 +101,7 @@ index 0f10ebef4b..cf5db4e119 100644
{
for (size_t i = 0; i < collapse_count; ++i)
{
-@@ -868,10 +903,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const
+@@ -876,10 +911,14 @@ static void rankEdgeCollapses(Collapse* collapses, size_t collapse_count, const
float ei = quadricError(qi, vertex_positions[i1]);
float ej = quadricError(qj, vertex_positions[j1]);
@@ -116,7 +116,7 @@ index 0f10ebef4b..cf5db4e119 100644
}
}
-@@ -968,7 +1007,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
+@@ -976,7 +1015,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
}
}
@@ -125,7 +125,7 @@ index 0f10ebef4b..cf5db4e119 100644
{
size_t edge_collapses = 0;
size_t triangle_collapses = 0;
-@@ -1030,6 +1069,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
+@@ -1038,6 +1077,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
assert(collapse_remap[r1] == r1);
quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]);
@@ -133,7 +133,7 @@ index 0f10ebef4b..cf5db4e119 100644
if (vertex_kind[i0] == Kind_Complex)
{
-@@ -1067,7 +1107,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
+@@ -1075,7 +1115,7 @@ static size_t performEdgeCollapses(unsigned int* collapse_remap, unsigned char*
triangle_collapses += (vertex_kind[i0] == Kind_Border) ? 1 : 2;
edge_collapses++;
@@ -142,7 +142,7 @@ index 0f10ebef4b..cf5db4e119 100644
}
#if TRACE
-@@ -1455,9 +1495,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
+@@ -1463,9 +1503,11 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
@@ -156,7 +156,7 @@ index 0f10ebef4b..cf5db4e119 100644
if (result != indices)
memcpy(result, indices, index_count * sizeof(unsigned int));
-@@ -1488,7 +1530,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
+@@ -1496,7 +1538,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
if (edge_collapse_count == 0)
break;
@@ -165,7 +165,7 @@ index 0f10ebef4b..cf5db4e119 100644
#if TRACE > 1
dumpEdgeCollapses(edge_collapses, edge_collapse_count, vertex_kind);
-@@ -1507,7 +1549,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
+@@ -1515,7 +1557,7 @@ size_t meshopt_simplifyWithAttributes(unsigned int* destination, const unsigned
printf("pass %d: ", int(pass_count++));
#endif
diff --git a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
index cf648b0da3..33a17fe9fa 100644
--- a/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
+++ b/thirdparty/meshoptimizer/patches/attribute-aware-simplify.patch
@@ -1,8 +1,8 @@
diff --git a/thirdparty/meshoptimizer/meshoptimizer.h b/thirdparty/meshoptimizer/meshoptimizer.h
-index fe8d349731..e44b99ce52 100644
+index be4b765d97..463fad29da 100644
--- a/thirdparty/meshoptimizer/meshoptimizer.h
+++ b/thirdparty/meshoptimizer/meshoptimizer.h
-@@ -298,6 +298,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_decodeFilterExp(void* buffer, size_t ver
+@@ -328,6 +328,11 @@ MESHOPTIMIZER_EXPERIMENTAL void meshopt_encodeFilterExp(void* destination, size_
*/
MESHOPTIMIZER_EXPERIMENTAL size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* result_error);
@@ -13,9 +13,9 @@ index fe8d349731..e44b99ce52 100644
+
/**
* Experimental: Mesh simplifier (sloppy)
- * Reduces the number of triangles in the mesh, sacrificing mesh apperance for simplification performance
+ * Reduces the number of triangles in the mesh, sacrificing mesh appearance for simplification performance
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
-index b2cb589462..059cabb055 100644
+index a74b08a97d..5e92e2dc73 100644
--- a/thirdparty/meshoptimizer/simplifier.cpp
+++ b/thirdparty/meshoptimizer/simplifier.cpp
@@ -20,6 +20,8 @@
@@ -27,7 +27,7 @@ index b2cb589462..059cabb055 100644
// This work is based on:
// Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
// Michael Garland. Quadric-based polygonal surface simplification. 1999
-@@ -358,6 +360,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
+@@ -371,6 +373,10 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
struct Vector3
{
float x, y, z;
@@ -38,7 +38,7 @@ index b2cb589462..059cabb055 100644
};
static float rescalePositions(Vector3* result, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride)
-@@ -414,6 +420,13 @@ struct Quadric
+@@ -427,6 +433,13 @@ struct Quadric
float a10, a20, a21;
float b0, b1, b2, c;
float w;
@@ -52,7 +52,7 @@ index b2cb589462..059cabb055 100644
};
struct Collapse
-@@ -456,6 +469,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
+@@ -469,6 +482,16 @@ static void quadricAdd(Quadric& Q, const Quadric& R)
Q.b2 += R.b2;
Q.c += R.c;
Q.w += R.w;
@@ -69,7 +69,7 @@ index b2cb589462..059cabb055 100644
}
static float quadricError(const Quadric& Q, const Vector3& v)
-@@ -481,6 +504,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
+@@ -494,6 +517,17 @@ static float quadricError(const Quadric& Q, const Vector3& v)
r += ry * v.y;
r += rz * v.z;
@@ -87,7 +87,7 @@ index b2cb589462..059cabb055 100644
float s = Q.w == 0.f ? 0.f : 1.f / Q.w;
return fabsf(r) * s;
-@@ -504,6 +538,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
+@@ -517,6 +551,13 @@ static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d, flo
Q.b2 = c * dw;
Q.c = d * dw;
Q.w = w;
@@ -101,7 +101,7 @@ index b2cb589462..059cabb055 100644
}
static void quadricFromPoint(Quadric& Q, float x, float y, float z, float w)
-@@ -556,6 +597,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
+@@ -569,6 +610,84 @@ static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3
quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance, length * weight);
}
@@ -186,7 +186,7 @@ index b2cb589462..059cabb055 100644
static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indices, size_t index_count, const Vector3* vertex_positions, const unsigned int* remap)
{
for (size_t i = 0; i < index_count; i += 3)
-@@ -567,6 +686,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
+@@ -580,6 +699,9 @@ static void fillFaceQuadrics(Quadric* vertex_quadrics, const unsigned int* indic
Quadric Q;
quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], 1.f);
@@ -196,7 +196,7 @@ index b2cb589462..059cabb055 100644
quadricAdd(vertex_quadrics[remap[i0]], Q);
quadricAdd(vertex_quadrics[remap[i1]], Q);
quadricAdd(vertex_quadrics[remap[i2]], Q);
-@@ -1259,13 +1381,19 @@ unsigned int* meshopt_simplifyDebugLoopBack = 0;
+@@ -1273,13 +1395,19 @@ MESHOPTIMIZER_API unsigned int* meshopt_simplifyDebugLoopBack = 0;
#endif
size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count, float target_error, float* out_result_error)
@@ -218,7 +218,7 @@ index b2cb589462..059cabb055 100644
meshopt_Allocator allocator;
-@@ -1279,7 +1407,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+@@ -1293,7 +1421,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// build position remap that maps each vertex to the one with identical position
unsigned int* remap = allocator.allocate<unsigned int>(vertex_count);
unsigned int* wedge = allocator.allocate<unsigned int>(vertex_count);
@@ -227,7 +227,7 @@ index b2cb589462..059cabb055 100644
// classify vertices; vertex kind determines collapse rules, see kCanCollapse
unsigned char* vertex_kind = allocator.allocate<unsigned char>(vertex_count);
-@@ -1303,7 +1431,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+@@ -1317,7 +1445,21 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
#endif
Vector3* vertex_positions = allocator.allocate<Vector3>(vertex_count);
@@ -250,7 +250,7 @@ index b2cb589462..059cabb055 100644
Quadric* vertex_quadrics = allocator.allocate<Quadric>(vertex_count);
memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
-@@ -1395,7 +1537,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
+@@ -1409,7 +1551,9 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
// result_error is quadratic; we need to remap it back to linear
if (out_result_error)
diff --git a/thirdparty/meshoptimizer/simplifier.cpp b/thirdparty/meshoptimizer/simplifier.cpp
index ccc99edb1a..e40c141e76 100644
--- a/thirdparty/meshoptimizer/simplifier.cpp
+++ b/thirdparty/meshoptimizer/simplifier.cpp
@@ -276,7 +276,15 @@ static void classifyVertices(unsigned char* result, unsigned int* loop, unsigned
{
unsigned int target = edges[j].next;
- if (!hasEdge(adjacency, target, vertex))
+ if (target == vertex)
+ {
+ // degenerate triangles have two distinct edges instead of three, and the self edge
+ // is bi-directional by definition; this can break border/seam classification by "closing"
+ // the open edge from another triangle and falsely marking the vertex as manifold
+ // instead we mark the vertex as having >1 open edges which turns it into locked/complex
+ openinc[vertex] = openout[vertex] = vertex;
+ }
+ else if (!hasEdge(adjacency, target, vertex))
{
openinc[target] = (openinc[target] == ~0u) ? vertex : target;
openout[vertex] = (openout[vertex] == ~0u) ? target : vertex;
diff --git a/thirdparty/minizip/crypt.h b/thirdparty/minizip/crypt.h
index 1e9e8200b2..9da15373d8 100644
--- a/thirdparty/minizip/crypt.h
+++ b/thirdparty/minizip/crypt.h
@@ -38,6 +38,7 @@ static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab)
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
+ (void)pcrc_32_tab;
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
@@ -77,24 +78,24 @@ static void init_keys(const char* passwd,unsigned long* pkeys,const z_crc_t* pcr
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
- (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
+ (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2
-# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
+# define ZCR_SEED2 3141592654L /* use PI as default pattern */
# endif
-static int crypthead(const char* passwd, /* password string */
- unsigned char* buf, /* where to write header */
- int bufSize,
- unsigned long* pkeys,
- const z_crc_t* pcrc_32_tab,
- unsigned long crcForCrypting)
+static unsigned crypthead(const char* passwd, /* password string */
+ unsigned char* buf, /* where to write header */
+ int bufSize,
+ unsigned long* pkeys,
+ const z_crc_t* pcrc_32_tab,
+ unsigned long crcForCrypting)
{
- int n; /* index in random header */
+ unsigned n; /* index in random header */
int t; /* temporary */
int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */
diff --git a/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch b/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch
deleted file mode 100644
index 2162bafbbc..0000000000
--- a/thirdparty/minizip/godot-zlib-1.2.4-minizip-seek.patch
+++ /dev/null
@@ -1,295 +0,0 @@
-diff --git a/thirdparty/minizip/ioapi.c b/thirdparty/minizip/ioapi.c
-index 49958f61f..0afbdc06a 100644
---- a/thirdparty/minizip/ioapi.c
-+++ b/thirdparty/minizip/ioapi.c
-@@ -68,8 +68,15 @@ void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filef
- p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
- p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
- p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
-+ /* GODOT start */
-+ p_filefunc64_32->zfile_func64.alloc_mem = p_filefunc32->alloc_mem;
-+ p_filefunc64_32->zfile_func64.free_mem = p_filefunc32->free_mem;
-+ /* GODOT end */
- }
-
-+/* GODOT start */
-+/*
-+// GODOT end
-
-
- static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
-@@ -233,3 +240,6 @@ void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
- pzlib_filefunc_def->zerror_file = ferror_file_func;
- pzlib_filefunc_def->opaque = NULL;
- }
-+// GODOT start
-+*/
-+/* GODOT end */
-diff --git a/thirdparty/minizip/ioapi.h b/thirdparty/minizip/ioapi.h
-index 8309c4cf8..f25ab6464 100644
---- a/thirdparty/minizip/ioapi.h
-+++ b/thirdparty/minizip/ioapi.h
-@@ -145,6 +145,10 @@ typedef struct zlib_filefunc_def_s
- close_file_func zclose_file;
- testerror_file_func zerror_file;
- voidpf opaque;
-+ /* GODOT start */
-+ alloc_func alloc_mem;
-+ free_func free_mem;
-+ /* GODOT end */
- } zlib_filefunc_def;
-
- typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
-@@ -161,6 +165,10 @@ typedef struct zlib_filefunc64_def_s
- close_file_func zclose_file;
- testerror_file_func zerror_file;
- voidpf opaque;
-+ /* GODOT start */
-+ alloc_func alloc_mem;
-+ free_func free_mem;
-+ /* GODOT end */
- } zlib_filefunc64_def;
-
- void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
-diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
-index 7617f41f1..32e27bd65 100644
---- a/thirdparty/minizip/unzip.c
-+++ b/thirdparty/minizip/unzip.c
-@@ -157,6 +157,9 @@ typedef struct
- uLong compression_method; /* compression method (0==store) */
- ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
- int raw;
-+ /* GODOT start */
-+ int extra_size;
-+ /* GODOT end */
- } file_in_zip64_read_info_s;
-
-
-@@ -606,9 +609,10 @@ local unzFile unzOpenInternal (const void *path,
- us.z_filefunc.zseek32_file = NULL;
- us.z_filefunc.ztell32_file = NULL;
- if (pzlib_filefunc64_32_def==NULL)
-- fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
-- else
-- us.z_filefunc = *pzlib_filefunc64_32_def;
-+ /* GODOT start */
-+ return NULL; // standard i/o not supported
-+ us.z_filefunc = *pzlib_filefunc64_32_def;
-+ /* GODOT end */
- us.is64bitOpenFunction = is64bitOpenFunction;
-
-
-@@ -800,6 +804,18 @@ extern unzFile ZEXPORT unzOpen64 (const void *path)
- return unzOpenInternal(path, NULL, 1);
- }
-
-+/* GODOT start */
-+extern void* unzGetOpaque(unzFile file) {
-+
-+ unz64_s* s;
-+ if (file==NULL)
-+ return NULL;
-+ s=(unz64_s*)file;
-+
-+ return s->z_filefunc.zfile_func64.opaque;
-+};
-+/* GODOT end */
-+
- /*
- Close a ZipFile opened with unzOpen.
- If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-@@ -1018,10 +1034,20 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
-
- if (lSeek!=0)
- {
-- if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
-- lSeek=0;
-- else
-- err=UNZ_ERRNO;
-+ /* GODOT start */
-+ if (lSeek<0) {
-+ // WORKAROUND for backwards seeking
-+ z_off_t pos = ZTELL64(s->z_filefunc, s->filestream);
-+ if (ZSEEK64(s->z_filefunc, s->filestream,pos+lSeek,ZLIB_FILEFUNC_SEEK_SET)==0)
-+ lSeek=0;
-+ else
-+ err=UNZ_ERRNO;
-+ } else {
-+ if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
-+ lSeek=0;
-+ else
-+ err=UNZ_ERRNO;
-+ }
- }
-
- while(acc < file_info.size_file_extra)
-@@ -1575,8 +1601,10 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
- }
- else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
- {
-- pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
-- pfile_in_zip_read_info->stream.zfree = (free_func)0;
-+ /* GODOT start */
-+ pfile_in_zip_read_info->stream.zalloc = s->z_filefunc.zfile_func64.alloc_mem;
-+ pfile_in_zip_read_info->stream.zfree = s->z_filefunc.zfile_func64.free_mem;
-+ /* GODOT end */
- pfile_in_zip_read_info->stream.opaque = (voidpf)0;
- pfile_in_zip_read_info->stream.next_in = 0;
- pfile_in_zip_read_info->stream.avail_in = 0;
-@@ -1608,6 +1636,9 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
- iSizeVar;
-
- pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-+ /* GODOT start */
-+ pfile_in_zip_read_info->extra_size = iSizeVar;
-+ /* GODOT end */
-
- s->pfile_in_zip_read = pfile_in_zip_read_info;
- s->encrypted = 0;
-@@ -1638,6 +1669,85 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
- return UNZ_OK;
- }
-
-+/* GODOT start */
-+extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos) {
-+
-+ unz64_s* s;
-+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
-+ if (file==NULL)
-+ return UNZ_PARAMERROR;
-+ s=(unz64_s*)file;
-+ pfile_in_zip_read_info=s->pfile_in_zip_read;
-+
-+ if (pfile_in_zip_read_info==NULL)
-+ return UNZ_PARAMERROR;
-+
-+ if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) { // don't know how to support bzip
-+ return UNZ_INTERNALERROR;
-+ };
-+
-+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) {
-+
-+ pfile_in_zip_read_info->rest_read_compressed =
-+ s->cur_file_info.compressed_size - pos;
-+ pfile_in_zip_read_info->rest_read_uncompressed =
-+ s->cur_file_info.uncompressed_size - pos;
-+
-+ pfile_in_zip_read_info->pos_in_zipfile =
-+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
-+ pfile_in_zip_read_info->extra_size + pos;
-+
-+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-+ pfile_in_zip_read_info->stream.total_out = pos;
-+
-+ return ZSEEK64(pfile_in_zip_read_info->z_filefunc,
-+ pfile_in_zip_read_info->filestream,
-+ pfile_in_zip_read_info->byte_before_the_zipfile + pfile_in_zip_read_info->pos_in_zipfile,
-+ ZLIB_FILEFUNC_SEEK_SET);
-+
-+ } else { // gzip
-+
-+ if (pos < pfile_in_zip_read_info->stream.total_out) { // negative seek, rewind
-+
-+ pfile_in_zip_read_info->rest_read_compressed =
-+ s->cur_file_info.compressed_size ;
-+ pfile_in_zip_read_info->rest_read_uncompressed =
-+ s->cur_file_info.uncompressed_size ;
-+
-+ pfile_in_zip_read_info->pos_in_zipfile =
-+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
-+ pfile_in_zip_read_info->extra_size;
-+
-+ (void)inflateReset(&pfile_in_zip_read_info->stream);
-+
-+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-+ pfile_in_zip_read_info->stream.total_out = 0;
-+ pfile_in_zip_read_info->stream.next_in = 0;
-+ };
-+
-+ // not sure where to read, so read on the stack
-+ {
-+ char buf[512];
-+ int to_read = pos - pfile_in_zip_read_info->stream.total_out;
-+ while (to_read) {
-+
-+ int len = to_read > sizeof(buf)?sizeof(buf):to_read;
-+ int read = unzReadCurrentFile(file, buf, len);
-+ if (read < 0) {
-+ return read;
-+ };
-+ to_read -= read;
-+ if (read == UNZ_EOF) {
-+ return pos;
-+ };
-+ };
-+ };
-+ };
-+
-+ return pos;
-+};
-+/* GODOT end */
-+
- extern int ZEXPORT unzOpenCurrentFile (unzFile file)
- {
- return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
-diff --git a/thirdparty/minizip/unzip.h b/thirdparty/minizip/unzip.h
-index 3183968b7..54e65ad8a 100644
---- a/thirdparty/minizip/unzip.h
-+++ b/thirdparty/minizip/unzip.h
-@@ -202,6 +202,10 @@ extern int ZEXPORT unzClose OF((unzFile file));
- these files MUST be closed with unzCloseCurrentFile before call unzClose.
- return UNZ_OK if there is no problem. */
-
-+/* GODOT start */
-+extern void* unzGetOpaque(unzFile file);
-+/* GODOT end */
-+
- extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
- unz_global_info *pglobal_info));
-
-@@ -390,6 +394,13 @@ extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
- (UNZ_ERRNO for IO error, or zLib error for uncompress error)
- */
-
-+/* GODOT start */
-+extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos);
-+/*
-+ Seek to position in uncompressed data
-+*/
-+/* GODOT end */
-+
- extern z_off_t ZEXPORT unztell OF((unzFile file));
-
- extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
-diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c
-index 3c34fc8bd..d7093e745 100644
---- a/thirdparty/minizip/zip.c
-+++ b/thirdparty/minizip/zip.c
-@@ -854,9 +854,11 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl
-
- ziinit.z_filefunc.zseek32_file = NULL;
- ziinit.z_filefunc.ztell32_file = NULL;
-- if (pzlib_filefunc64_32_def==NULL)
-- fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
-- else
-+ /* GODOT start */
-+ if (pzlib_filefunc64_32_def==NULL) {
-+ //fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
-+ } else
-+ /* GODOT end */
- ziinit.z_filefunc = *pzlib_filefunc64_32_def;
-
- ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
-@@ -1210,8 +1212,10 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
- {
- if(zi->ci.method == Z_DEFLATED)
- {
-- zi->ci.stream.zalloc = (alloc_func)0;
-- zi->ci.stream.zfree = (free_func)0;
-+ /* GODOT start */
-+ zi->ci.stream.zalloc = zi->z_filefunc.zfile_func64.alloc_mem;
-+ zi->ci.stream.zfree = zi->z_filefunc.zfile_func64.free_mem;
-+ /* GODOT end */
- zi->ci.stream.opaque = (voidpf)0;
-
- if (windowBits>0)
diff --git a/thirdparty/minizip/ioapi.c b/thirdparty/minizip/ioapi.c
index 9cb27c16db..db4c33b4b9 100644
--- a/thirdparty/minizip/ioapi.c
+++ b/thirdparty/minizip/ioapi.c
@@ -58,7 +58,7 @@ ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream
return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
else
{
- uLong tell_uLong = (*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+ uLong tell_uLong = (uLong)(*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
if ((tell_uLong) == MAXU32)
return (ZPOS64_T)-1;
else
@@ -101,6 +101,7 @@ static int ZCALLBACK ferror_file_func OF((voidpf opaque, voidpf stream));
static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, int mode)
{
+ (void)opaque;
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
@@ -119,6 +120,7 @@ static voidpf ZCALLBACK fopen_file_func (voidpf opaque, const char* filename, in
static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename, int mode)
{
+ (void)opaque;
FILE* file = NULL;
const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
@@ -138,6 +140,7 @@ static voidpf ZCALLBACK fopen64_file_func (voidpf opaque, const void* filename,
static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf, uLong size)
{
+ (void)opaque;
uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret;
@@ -145,6 +148,7 @@ static uLong ZCALLBACK fread_file_func (voidpf opaque, voidpf stream, void* buf,
static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const void* buf, uLong size)
{
+ (void)opaque;
uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret;
@@ -152,6 +156,7 @@ static uLong ZCALLBACK fwrite_file_func (voidpf opaque, voidpf stream, const voi
static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
{
+ (void)opaque;
long ret;
ret = ftell((FILE *)stream);
return ret;
@@ -160,13 +165,15 @@ static long ZCALLBACK ftell_file_func (voidpf opaque, voidpf stream)
static ZPOS64_T ZCALLBACK ftell64_file_func (voidpf opaque, voidpf stream)
{
+ (void)opaque;
ZPOS64_T ret;
- ret = FTELLO_FUNC((FILE *)stream);
+ ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream);
return ret;
}
static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offset, int origin)
{
+ (void)opaque;
int fseek_origin=0;
long ret;
switch (origin)
@@ -183,13 +190,14 @@ static long ZCALLBACK fseek_file_func (voidpf opaque, voidpf stream, uLong offs
default: return -1;
}
ret = 0;
- if (fseek((FILE *)stream, offset, fseek_origin) != 0)
+ if (fseek((FILE *)stream, (long)offset, fseek_origin) != 0)
ret = -1;
return ret;
}
static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin)
{
+ (void)opaque;
int fseek_origin=0;
long ret;
switch (origin)
@@ -207,7 +215,7 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
}
ret = 0;
- if(FSEEKO_FUNC((FILE *)stream, offset, fseek_origin) != 0)
+ if(FSEEKO_FUNC((FILE *)stream, (long)offset, fseek_origin) != 0)
ret = -1;
return ret;
@@ -216,6 +224,7 @@ static long ZCALLBACK fseek64_file_func (voidpf opaque, voidpf stream, ZPOS64_T
static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
{
+ (void)opaque;
int ret;
ret = fclose((FILE *)stream);
return ret;
@@ -223,6 +232,7 @@ static int ZCALLBACK fclose_file_func (voidpf opaque, voidpf stream)
static int ZCALLBACK ferror_file_func (voidpf opaque, voidpf stream)
{
+ (void)opaque;
int ret;
ret = ferror((FILE *)stream);
return ret;
diff --git a/thirdparty/minizip/ioapi.h b/thirdparty/minizip/ioapi.h
index 4011e9cabb..e9e5899852 100644
--- a/thirdparty/minizip/ioapi.h
+++ b/thirdparty/minizip/ioapi.h
@@ -107,8 +107,7 @@ typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
typedef uint64_t ZPOS64_T;
#else
-/* Maximum unsigned 32-bit value used as placeholder for zip64 */
-#define MAXU32 0xffffffff
+
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 ZPOS64_T;
@@ -118,7 +117,10 @@ typedef unsigned long long int ZPOS64_T;
#endif
#endif
-
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#ifndef MAXU32
+#define MAXU32 (0xffffffff)
+#endif
#ifdef __cplusplus
extern "C" {
diff --git a/thirdparty/minizip/patches/godot-seek.patch b/thirdparty/minizip/patches/godot-seek.patch
new file mode 100644
index 0000000000..24838c252a
--- /dev/null
+++ b/thirdparty/minizip/patches/godot-seek.patch
@@ -0,0 +1,294 @@
+diff --git a/thirdparty/minizip/ioapi.c b/thirdparty/minizip/ioapi.c
+index d666e5a228..db4c33b4b9 100644
+--- a/thirdparty/minizip/ioapi.c
++++ b/thirdparty/minizip/ioapi.c
+@@ -80,8 +80,15 @@ void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filef
+ p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+ p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
++ /* GODOT start */
++ p_filefunc64_32->zfile_func64.alloc_mem = p_filefunc32->alloc_mem;
++ p_filefunc64_32->zfile_func64.free_mem = p_filefunc32->free_mem;
++ /* GODOT end */
+ }
+
++/* GODOT start */
++/*
++// GODOT end
+
+
+ static voidpf ZCALLBACK fopen_file_func OF((voidpf opaque, const char* filename, int mode));
+@@ -255,3 +262,6 @@ void fill_fopen64_filefunc (zlib_filefunc64_def* pzlib_filefunc_def)
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+ }
++// GODOT start
++*/
++/* GODOT end */
+diff --git a/thirdparty/minizip/ioapi.h b/thirdparty/minizip/ioapi.h
+index 114bfab762..2f24a5b6a0 100644
+--- a/thirdparty/minizip/ioapi.h
++++ b/thirdparty/minizip/ioapi.h
+@@ -155,6 +155,10 @@ typedef struct zlib_filefunc_def_s
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
++ /* GODOT start */
++ alloc_func alloc_mem;
++ free_func free_mem;
++ /* GODOT end */
+ } zlib_filefunc_def;
+
+ typedef ZPOS64_T (ZCALLBACK *tell64_file_func) OF((voidpf opaque, voidpf stream));
+@@ -171,6 +175,10 @@ typedef struct zlib_filefunc64_def_s
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
++ /* GODOT start */
++ alloc_func alloc_mem;
++ free_func free_mem;
++ /* GODOT end */
+ } zlib_filefunc64_def;
+
+ void fill_fopen64_filefunc OF((zlib_filefunc64_def* pzlib_filefunc_def));
+diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
+index 5e12e47474..3b191e827c 100644
+--- a/thirdparty/minizip/unzip.c
++++ b/thirdparty/minizip/unzip.c
+@@ -157,6 +157,9 @@ typedef struct
+ uLong compression_method; /* compression method (0==store) */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
++ /* GODOT start */
++ int extra_size;
++ /* GODOT end */
+ } file_in_zip64_read_info_s;
+
+
+@@ -606,9 +609,10 @@ local unzFile unzOpenInternal (const void *path,
+ us.z_filefunc.zseek32_file = NULL;
+ us.z_filefunc.ztell32_file = NULL;
+ if (pzlib_filefunc64_32_def==NULL)
+- fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+- else
+- us.z_filefunc = *pzlib_filefunc64_32_def;
++ /* GODOT start */
++ return NULL; // standard i/o not supported
++ us.z_filefunc = *pzlib_filefunc64_32_def;
++ /* GODOT end */
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+@@ -800,6 +804,18 @@ extern unzFile ZEXPORT unzOpen64 (const void *path)
+ return unzOpenInternal(path, NULL, 1);
+ }
+
++/* GODOT start */
++extern void* unzGetOpaque(unzFile file) {
++
++ unz64_s* s;
++ if (file==NULL)
++ return NULL;
++ s=(unz64_s*)file;
++
++ return s->z_filefunc.zfile_func64.opaque;
++};
++/* GODOT end */
++
+ /*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+@@ -1018,10 +1034,23 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
+
+ if (lSeek!=0)
+ {
++ /* GODOT start */
++ if (lSeek<0) {
++ // WORKAROUND for backwards seeking
++ ZPOS64_T pos = ZTELL64(s->z_filefunc, s->filestream);
++ if (ZSEEK64(s->z_filefunc, s->filestream,pos+(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_SET)==0)
++ lSeek=0;
++ else
++ err=UNZ_ERRNO;
++ } else {
++ /* GODOT end */
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
++ /* GODOT start */
++ }
++ /* GODOT end */
+ }
+
+ while(acc < file_info.size_file_extra)
+@@ -1575,8 +1604,10 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+ }
+ else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+ {
+- pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+- pfile_in_zip_read_info->stream.zfree = (free_func)0;
++ /* GODOT start */
++ pfile_in_zip_read_info->stream.zalloc = s->z_filefunc.zfile_func64.alloc_mem;
++ pfile_in_zip_read_info->stream.zfree = s->z_filefunc.zfile_func64.free_mem;
++ /* GODOT end */
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = 0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+@@ -1608,6 +1639,9 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
++ /* GODOT start */
++ pfile_in_zip_read_info->extra_size = iSizeVar;
++ /* GODOT end */
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ s->encrypted = 0;
+@@ -1638,6 +1672,85 @@ extern int ZEXPORT unzOpenCurrentFile3 (unzFile file, int* method,
+ return UNZ_OK;
+ }
+
++/* GODOT start */
++extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos) {
++
++ unz64_s* s;
++ file_in_zip64_read_info_s* pfile_in_zip_read_info;
++ if (file==NULL)
++ return UNZ_PARAMERROR;
++ s=(unz64_s*)file;
++ pfile_in_zip_read_info=s->pfile_in_zip_read;
++
++ if (pfile_in_zip_read_info==NULL)
++ return UNZ_PARAMERROR;
++
++ if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) { // don't know how to support bzip
++ return UNZ_INTERNALERROR;
++ }
++
++ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) {
++
++ pfile_in_zip_read_info->rest_read_compressed =
++ s->cur_file_info.compressed_size - pos;
++ pfile_in_zip_read_info->rest_read_uncompressed =
++ s->cur_file_info.uncompressed_size - pos;
++
++ pfile_in_zip_read_info->pos_in_zipfile =
++ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
++ pfile_in_zip_read_info->extra_size + pos;
++
++ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
++ pfile_in_zip_read_info->stream.total_out = pos;
++
++ return ZSEEK64(pfile_in_zip_read_info->z_filefunc,
++ pfile_in_zip_read_info->filestream,
++ pfile_in_zip_read_info->byte_before_the_zipfile + pfile_in_zip_read_info->pos_in_zipfile,
++ ZLIB_FILEFUNC_SEEK_SET);
++
++ } else { // gzip
++
++ if (pos < pfile_in_zip_read_info->stream.total_out) { // negative seek, rewind
++
++ pfile_in_zip_read_info->rest_read_compressed =
++ s->cur_file_info.compressed_size ;
++ pfile_in_zip_read_info->rest_read_uncompressed =
++ s->cur_file_info.uncompressed_size ;
++
++ pfile_in_zip_read_info->pos_in_zipfile =
++ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
++ pfile_in_zip_read_info->extra_size;
++
++ (void)inflateReset(&pfile_in_zip_read_info->stream);
++
++ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
++ pfile_in_zip_read_info->stream.total_out = 0;
++ pfile_in_zip_read_info->stream.next_in = 0;
++ }
++
++ // not sure where to read, so read on the stack
++ {
++ char buf[512];
++ int to_read = pos - pfile_in_zip_read_info->stream.total_out;
++ while (to_read) {
++
++ int len = to_read > sizeof(buf)?sizeof(buf):to_read;
++ int read = unzReadCurrentFile(file, buf, len);
++ if (read < 0) {
++ return read;
++ }
++ to_read -= read;
++ if (read == UNZ_EOF) {
++ return pos;
++ }
++ }
++ }
++ }
++
++ return pos;
++}
++/* GODOT end */
++
+ extern int ZEXPORT unzOpenCurrentFile (unzFile file)
+ {
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+diff --git a/thirdparty/minizip/unzip.h b/thirdparty/minizip/unzip.h
+index 6f95e94d75..71a7d89692 100644
+--- a/thirdparty/minizip/unzip.h
++++ b/thirdparty/minizip/unzip.h
+@@ -202,6 +202,10 @@ extern int ZEXPORT unzClose OF((unzFile file));
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+
++/* GODOT start */
++extern void* unzGetOpaque(unzFile file);
++/* GODOT end */
++
+ extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+
+@@ -390,6 +394,13 @@ extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+ */
+
++/* GODOT start */
++extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos);
++/*
++ Seek to position in uncompressed data
++*/
++/* GODOT end */
++
+ extern z_off_t ZEXPORT unztell OF((unzFile file));
+
+ extern ZPOS64_T ZEXPORT unztell64 OF((unzFile file));
+diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c
+index 4e611e1163..6d1c26d9f8 100644
+--- a/thirdparty/minizip/zip.c
++++ b/thirdparty/minizip/zip.c
+@@ -854,9 +854,11 @@ extern zipFile ZEXPORT zipOpen3 (const void *pathname, int append, zipcharpc* gl
+
+ ziinit.z_filefunc.zseek32_file = NULL;
+ ziinit.z_filefunc.ztell32_file = NULL;
+- if (pzlib_filefunc64_32_def==NULL)
+- fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
+- else
++ /* GODOT start */
++ if (pzlib_filefunc64_32_def==NULL) {
++ //fill_fopen64_filefunc(&ziinit.z_filefunc.zfile_func64);
++ } else
++ /* GODOT end */
+ ziinit.z_filefunc = *pzlib_filefunc64_32_def;
+
+ ziinit.filestream = ZOPEN64(ziinit.z_filefunc,
+@@ -1211,8 +1213,10 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
+ {
+ if(zi->ci.method == Z_DEFLATED)
+ {
+- zi->ci.stream.zalloc = (alloc_func)0;
+- zi->ci.stream.zfree = (free_func)0;
++ /* GODOT start */
++ zi->ci.stream.zalloc = zi->z_filefunc.zfile_func64.alloc_mem;
++ zi->ci.stream.zfree = zi->z_filefunc.zfile_func64.free_mem;
++ /* GODOT end */
+ zi->ci.stream.opaque = (voidpf)0;
+
+ if (windowBits>0)
diff --git a/thirdparty/minizip/godot-zlib-1.2.4-minizip-unbreak-gentoo.patch b/thirdparty/minizip/patches/unbreak-gentoo.patch
index 9292e32ac6..9292e32ac6 100644
--- a/thirdparty/minizip/godot-zlib-1.2.4-minizip-unbreak-gentoo.patch
+++ b/thirdparty/minizip/patches/unbreak-gentoo.patch
diff --git a/thirdparty/minizip/unzip.c b/thirdparty/minizip/unzip.c
index 31f8a5ff47..3b191e827c 100644
--- a/thirdparty/minizip/unzip.c
+++ b/thirdparty/minizip/unzip.c
@@ -458,7 +458,7 @@ local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
{
- uPosFound = uReadPos+i;
+ uPosFound = uReadPos+(unsigned)i;
break;
}
@@ -526,7 +526,7 @@ local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
{
- uPosFound = uReadPos+i;
+ uPosFound = uReadPos+(unsigned)i;
break;
}
@@ -869,13 +869,13 @@ local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
{
ZPOS64_T uDate;
uDate = (ZPOS64_T)(ulDosDate>>16);
- ptm->tm_mday = (uInt)(uDate&0x1f) ;
- ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
- ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+ ptm->tm_mday = (int)(uDate&0x1f) ;
+ ptm->tm_mon = (int)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;
- ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
- ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
- ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+ ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (int) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (int) (2*(ulDosDate&0x1f)) ;
}
/*
@@ -1009,7 +1009,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
if (lSeek!=0)
{
- if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
lSeek=0;
else
err=UNZ_ERRNO;
@@ -1037,17 +1037,20 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
/* GODOT start */
if (lSeek<0) {
// WORKAROUND for backwards seeking
- z_off_t pos = ZTELL64(s->z_filefunc, s->filestream);
- if (ZSEEK64(s->z_filefunc, s->filestream,pos+lSeek,ZLIB_FILEFUNC_SEEK_SET)==0)
+ ZPOS64_T pos = ZTELL64(s->z_filefunc, s->filestream);
+ if (ZSEEK64(s->z_filefunc, s->filestream,pos+(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_SET)==0)
lSeek=0;
else
err=UNZ_ERRNO;
} else {
- if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
- lSeek=0;
- else
- err=UNZ_ERRNO;
+ /* GODOT end */
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ /* GODOT start */
}
+ /* GODOT end */
}
while(acc < file_info.size_file_extra)
@@ -1116,7 +1119,7 @@ local int unz64local_GetCurrentFileInfoInternal (unzFile file,
if (lSeek!=0)
{
- if (ZSEEK64(s->z_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
lSeek=0;
else
err=UNZ_ERRNO;
@@ -1684,7 +1687,7 @@ extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos) {
if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED) { // don't know how to support bzip
return UNZ_INTERNALERROR;
- };
+ }
if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw)) {
@@ -1723,7 +1726,7 @@ extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos) {
pfile_in_zip_read_info->stream.avail_in = (uInt)0;
pfile_in_zip_read_info->stream.total_out = 0;
pfile_in_zip_read_info->stream.next_in = 0;
- };
+ }
// not sure where to read, so read on the stack
{
@@ -1735,17 +1738,17 @@ extern int ZEXPORT unzSeekCurrentFile(unzFile file, int pos) {
int read = unzReadCurrentFile(file, buf, len);
if (read < 0) {
return read;
- };
+ }
to_read -= read;
if (read == UNZ_EOF) {
return pos;
- };
- };
- };
- };
+ }
+ }
+ }
+ }
return pos;
-};
+}
/* GODOT end */
extern int ZEXPORT unzOpenCurrentFile (unzFile file)
@@ -1877,7 +1880,7 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
(pfile_in_zip_read_info->rest_read_compressed == 0))
- return (iRead==0) ? UNZ_EOF : iRead;
+ return (iRead==0) ? UNZ_EOF : (int)iRead;
if (pfile_in_zip_read_info->stream.avail_out <
pfile_in_zip_read_info->stream.avail_in)
@@ -1967,6 +1970,9 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
err = Z_DATA_ERROR;
uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
+ if (uTotalOutAfter<uTotalOutBefore)
+ uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
uOutThis = uTotalOutAfter-uTotalOutBefore;
pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
@@ -1981,14 +1987,14 @@ extern int ZEXPORT unzReadCurrentFile (unzFile file, voidp buf, unsigned len)
iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
if (err==Z_STREAM_END)
- return (iRead==0) ? UNZ_EOF : iRead;
+ return (iRead==0) ? UNZ_EOF : (int)iRead;
if (err!=Z_OK)
break;
}
}
if (err==Z_OK)
- return iRead;
+ return (int)iRead;
return err;
}
diff --git a/thirdparty/minizip/unzip.h b/thirdparty/minizip/unzip.h
index bab1cb939f..71a7d89692 100644
--- a/thirdparty/minizip/unzip.h
+++ b/thirdparty/minizip/unzip.h
@@ -83,12 +83,12 @@ typedef voidp unzFile;
/* tm_unz contain date/time info */
typedef struct tm_unz_s
{
- uInt tm_sec; /* seconds after the minute - [0,59] */
- uInt tm_min; /* minutes after the hour - [0,59] */
- uInt tm_hour; /* hours since midnight - [0,23] */
- uInt tm_mday; /* day of the month - [1,31] */
- uInt tm_mon; /* months since January - [0,11] */
- uInt tm_year; /* years - [1980..2044] */
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years - [1980..2044] */
} tm_unz;
/* unz_global_info structure contain global data about the ZIPfile
diff --git a/thirdparty/minizip/zip.c b/thirdparty/minizip/zip.c
index 2936e2b5d9..6d1c26d9f8 100644
--- a/thirdparty/minizip/zip.c
+++ b/thirdparty/minizip/zip.c
@@ -158,7 +158,7 @@ typedef struct
#ifndef NOCRYPT
unsigned long keys[3]; /* keys defining the pseudo-random sequence */
const z_crc_t* pcrc_32_tab;
- int crypt_header_size;
+ unsigned crypt_header_size;
#endif
} curfile64_info;
@@ -301,7 +301,7 @@ local int zip64local_putValue (const zlib_filefunc64_32_def* pzlib_filefunc_def,
}
}
- if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,nbByte)!=(uLong)nbByte)
+ if (ZWRITE64(*pzlib_filefunc_def,filestream,buf,(uLong)nbByte)!=(uLong)nbByte)
return ZIP_ERRNO;
else
return ZIP_OK;
@@ -337,8 +337,8 @@ local uLong zip64local_TmzDateToDosDate(const tm_zip* ptm)
else if (year>=80)
year-=80;
return
- (uLong) (((ptm->tm_mday) + (32 * (ptm->tm_mon+1)) + (512 * year)) << 16) |
- ((ptm->tm_sec/2) + (32* ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
+ (uLong) (((uLong)(ptm->tm_mday) + (32 * (uLong)(ptm->tm_mon+1)) + (512 * year)) << 16) |
+ (((uLong)ptm->tm_sec/2) + (32 * (uLong)ptm->tm_min) + (2048 * (uLong)ptm->tm_hour));
}
@@ -522,12 +522,12 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
{
- uPosFound = uReadPos+i;
+ uPosFound = uReadPos+(unsigned)i;
break;
}
- if (uPosFound!=0)
- break;
+ if (uPosFound!=0)
+ break;
}
TRYFREE(buf);
return uPosFound;
@@ -586,7 +586,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
// Signature "0x07064b50" Zip64 end of central directory locater
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
{
- uPosFound = uReadPos+i;
+ uPosFound = uReadPos+(unsigned)i;
break;
}
}
@@ -637,7 +637,7 @@ local ZPOS64_T zip64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib
return relativeOffset;
}
-int LoadCentralDirectoryRecord(zip64_internal* pziinit)
+local int LoadCentralDirectoryRecord(zip64_internal* pziinit)
{
int err=ZIP_OK;
ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
@@ -957,7 +957,7 @@ extern zipFile ZEXPORT zipOpen64 (const void* pathname, int append)
return zipOpen3(pathname,append,NULL,NULL);
}
-int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
+local int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_extrafield_local, const void* extrafield_local)
{
/* write the local header */
int err;
@@ -1036,8 +1036,8 @@ int Write_LocalFileHeader(zip64_internal* zi, const char* filename, uInt size_ex
// Remember position of Zip64 extended info for the local file header. (needed when we update size after done with file)
zi->ci.pos_zip64extrainfo = ZTELL64(zi->z_filefunc,zi->filestream);
- err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)HeaderID,2);
- err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (short)DataSize,2);
+ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)HeaderID,2);
+ err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)DataSize,2);
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)UncompressedSize,8);
err = zip64local_putValue(&zi->z_filefunc, zi->filestream, (ZPOS64_T)CompressedSize,8);
@@ -1520,7 +1520,7 @@ extern int ZEXPORT zipCloseFileInZipRaw64 (zipFile file, ZPOS64_T uncompressed_s
zip64_internal* zi;
ZPOS64_T compressed_size;
uLong invalidValue = 0xffffffff;
- short datasize = 0;
+ unsigned datasize = 0;
int err=ZIP_OK;
if (file == NULL)
@@ -1756,7 +1756,7 @@ extern int ZEXPORT zipCloseFileInZip (zipFile file)
return zipCloseFileInZipRaw (file,0,0);
}
-int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
+local int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eocd_pos_inzip)
{
int err = ZIP_OK;
ZPOS64_T pos = zip64eocd_pos_inzip - zi->add_position_when_writing_offset;
@@ -1778,7 +1778,7 @@ int Write_Zip64EndOfCentralDirectoryLocator(zip64_internal* zi, ZPOS64_T zip64eo
return err;
}
-int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
+local int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
{
int err = ZIP_OK;
@@ -1817,7 +1817,7 @@ int Write_Zip64EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centra
}
return err;
}
-int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
+local int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir, ZPOS64_T centraldir_pos_inzip)
{
int err = ZIP_OK;
@@ -1865,7 +1865,7 @@ int Write_EndOfCentralDirectoryRecord(zip64_internal* zi, uLong size_centraldir,
return err;
}
-int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
+local int Write_GlobalComment(zip64_internal* zi, const char* global_comment)
{
int err = ZIP_OK;
uInt size_global_comment = 0;
@@ -1966,7 +1966,7 @@ extern int ZEXPORT zipRemoveExtraInfoBlock (char* pData, int* dataLen, short sHe
if(pData == NULL || *dataLen < 4)
return ZIP_PARAMERROR;
- pNewHeader = (char*)ALLOC(*dataLen);
+ pNewHeader = (char*)ALLOC((unsigned)*dataLen);
pTmp = pNewHeader;
while(p < (pData + *dataLen))
diff --git a/thirdparty/minizip/zip.h b/thirdparty/minizip/zip.h
index 8aaebb6234..7e4509d77b 100644
--- a/thirdparty/minizip/zip.h
+++ b/thirdparty/minizip/zip.h
@@ -88,12 +88,12 @@ typedef voidp zipFile;
/* tm_zip contain date/time info */
typedef struct tm_zip_s
{
- uInt tm_sec; /* seconds after the minute - [0,59] */
- uInt tm_min; /* minutes after the hour - [0,59] */
- uInt tm_hour; /* hours since midnight - [0,23] */
- uInt tm_mday; /* day of the month - [1,31] */
- uInt tm_mon; /* months since January - [0,11] */
- uInt tm_year; /* years - [1980..2044] */
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
@@ -144,6 +144,11 @@ extern zipFile ZEXPORT zipOpen2_64 OF((const void *pathname,
zipcharpc* globalcomment,
zlib_filefunc64_def* pzlib_filefunc_def));
+extern zipFile ZEXPORT zipOpen3 OF((const void *pathname,
+ int append,
+ zipcharpc* globalcomment,
+ zlib_filefunc64_32_def* pzlib_filefunc64_32_def));
+
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename,
const zip_fileinfo* zipfi,
diff --git a/thirdparty/misc/ok_color.h b/thirdparty/misc/ok_color.h
new file mode 100644
index 0000000000..dbc7dafc36
--- /dev/null
+++ b/thirdparty/misc/ok_color.h
@@ -0,0 +1,688 @@
+// Copyright(c) 2021 Björn Ottosson
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and /or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions :
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef OK_COLOR_H
+#define OK_COLOR_H
+
+#include <cmath>
+#include <cfloat>
+
+class ok_color
+{
+public:
+
+struct Lab { float L; float a; float b; };
+struct RGB { float r; float g; float b; };
+struct HSV { float h; float s; float v; };
+struct HSL { float h; float s; float l; };
+struct LC { float L; float C; };
+
+// Alternative representation of (L_cusp, C_cusp)
+// Encoded so S = C_cusp/L_cusp and T = C_cusp/(1-L_cusp)
+// The maximum value for C in the triangle is then found as fmin(S*L, T*(1-L)), for a given L
+struct ST { float S; float T; };
+
+static constexpr float pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062f;
+
+float clamp(float x, float min, float max)
+{
+ if (x < min)
+ return min;
+ if (x > max)
+ return max;
+
+ return x;
+}
+
+float sgn(float x)
+{
+ return (float)(0.f < x) - (float)(x < 0.f);
+}
+
+float srgb_transfer_function(float a)
+{
+ return .0031308f >= a ? 12.92f * a : 1.055f * powf(a, .4166666666666667f) - .055f;
+}
+
+float srgb_transfer_function_inv(float a)
+{
+ return .04045f < a ? powf((a + .055f) / 1.055f, 2.4f) : a / 12.92f;
+}
+
+Lab linear_srgb_to_oklab(RGB c)
+{
+ float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
+ float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
+ float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;
+
+ float l_ = cbrtf(l);
+ float m_ = cbrtf(m);
+ float s_ = cbrtf(s);
+
+ return {
+ 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_,
+ 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_,
+ 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_,
+ };
+}
+
+RGB oklab_to_linear_srgb(Lab c)
+{
+ float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b;
+ float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b;
+ float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ return {
+ +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
+ -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
+ -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
+ };
+}
+
+// Finds the maximum saturation possible for a given hue that fits in sRGB
+// Saturation here is defined as S = C/L
+// a and b must be normalized so a^2 + b^2 == 1
+float compute_max_saturation(float a, float b)
+{
+ // Max saturation will be when one of r, g or b goes below zero.
+
+ // Select different coefficients depending on which component goes below zero first
+ float k0, k1, k2, k3, k4, wl, wm, ws;
+
+ if (-1.88170328f * a - 0.80936493f * b > 1)
+ {
+ // Red component
+ k0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f;
+ wl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f;
+ }
+ else if (1.81444104f * a - 1.19445276f * b > 1)
+ {
+ // Green component
+ k0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f;
+ wl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f;
+ }
+ else
+ {
+ // Blue component
+ k0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f;
+ wl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f;
+ }
+
+ // Approximate max saturation using a polynomial:
+ float S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
+
+ // Do one step Halley's method to get closer
+ // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite
+ // this should be sufficient for most applications, otherwise do two/three steps
+
+ float k_l = +0.3963377774f * a + 0.2158037573f * b;
+ float k_m = -0.1055613458f * a - 0.0638541728f * b;
+ float k_s = -0.0894841775f * a - 1.2914855480f * b;
+
+ {
+ float l_ = 1.f + S * k_l;
+ float m_ = 1.f + S * k_m;
+ float s_ = 1.f + S * k_s;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ float l_dS = 3.f * k_l * l_ * l_;
+ float m_dS = 3.f * k_m * m_ * m_;
+ float s_dS = 3.f * k_s * s_ * s_;
+
+ float l_dS2 = 6.f * k_l * k_l * l_;
+ float m_dS2 = 6.f * k_m * k_m * m_;
+ float s_dS2 = 6.f * k_s * k_s * s_;
+
+ float f = wl * l + wm * m + ws * s;
+ float f1 = wl * l_dS + wm * m_dS + ws * s_dS;
+ float f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;
+
+ S = S - f * f1 / (f1 * f1 - 0.5f * f * f2);
+ }
+
+ return S;
+}
+
+// finds L_cusp and C_cusp for a given hue
+// a and b must be normalized so a^2 + b^2 == 1
+LC find_cusp(float a, float b)
+{
+ // First, find the maximum saturation (saturation S = C/L)
+ float S_cusp = compute_max_saturation(a, b);
+
+ // Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:
+ RGB rgb_at_max = oklab_to_linear_srgb({ 1, S_cusp * a, S_cusp * b });
+ float L_cusp = cbrtf(1.f / fmax(fmax(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b));
+ float C_cusp = L_cusp * S_cusp;
+
+ return { L_cusp , C_cusp };
+}
+
+// Finds intersection of the line defined by
+// L = L0 * (1 - t) + t * L1;
+// C = t * C1;
+// a and b must be normalized so a^2 + b^2 == 1
+float find_gamut_intersection(float a, float b, float L1, float C1, float L0, LC cusp)
+{
+ // Find the intersection for upper and lower half seprately
+ float t;
+ if (((L1 - L0) * cusp.C - (cusp.L - L0) * C1) <= 0.f)
+ {
+ // Lower half
+
+ t = cusp.C * L0 / (C1 * cusp.L + cusp.C * (L0 - L1));
+ }
+ else
+ {
+ // Upper half
+
+ // First intersect with triangle
+ t = cusp.C * (L0 - 1.f) / (C1 * (cusp.L - 1.f) + cusp.C * (L0 - L1));
+
+ // Then one step Halley's method
+ {
+ float dL = L1 - L0;
+ float dC = C1;
+
+ float k_l = +0.3963377774f * a + 0.2158037573f * b;
+ float k_m = -0.1055613458f * a - 0.0638541728f * b;
+ float k_s = -0.0894841775f * a - 1.2914855480f * b;
+
+ float l_dt = dL + dC * k_l;
+ float m_dt = dL + dC * k_m;
+ float s_dt = dL + dC * k_s;
+
+
+ // If higher accuracy is required, 2 or 3 iterations of the following block can be used:
+ {
+ float L = L0 * (1.f - t) + t * L1;
+ float C = t * C1;
+
+ float l_ = L + C * k_l;
+ float m_ = L + C * k_m;
+ float s_ = L + C * k_s;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ float ldt = 3 * l_dt * l_ * l_;
+ float mdt = 3 * m_dt * m_ * m_;
+ float sdt = 3 * s_dt * s_ * s_;
+
+ float ldt2 = 6 * l_dt * l_dt * l_;
+ float mdt2 = 6 * m_dt * m_dt * m_;
+ float sdt2 = 6 * s_dt * s_dt * s_;
+
+ float r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1;
+ float r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt;
+ float r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2;
+
+ float u_r = r1 / (r1 * r1 - 0.5f * r * r2);
+ float t_r = -r * u_r;
+
+ float g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1;
+ float g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt;
+ float g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2;
+
+ float u_g = g1 / (g1 * g1 - 0.5f * g * g2);
+ float t_g = -g * u_g;
+
+ b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1;
+ float b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt;
+ float b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2;
+
+ float u_b = b1 / (b1 * b1 - 0.5f * b * b2);
+ float t_b = -b * u_b;
+
+ t_r = u_r >= 0.f ? t_r : FLT_MAX;
+ t_g = u_g >= 0.f ? t_g : FLT_MAX;
+ t_b = u_b >= 0.f ? t_b : FLT_MAX;
+
+ t += fmin(t_r, fmin(t_g, t_b));
+ }
+ }
+ }
+
+ return t;
+}
+
+float find_gamut_intersection(float a, float b, float L1, float C1, float L0)
+{
+ // Find the cusp of the gamut triangle
+ LC cusp = find_cusp(a, b);
+
+ return find_gamut_intersection(a, b, L1, C1, L0, cusp);
+}
+
+RGB gamut_clip_preserve_chroma(RGB rgb)
+{
+ if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0)
+ return rgb;
+
+ Lab lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.L;
+ float eps = 0.00001f;
+ float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b));
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ float L0 = clamp(L, 0, 1);
+
+ float t = find_gamut_intersection(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1 - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ });
+}
+
+RGB gamut_clip_project_to_0_5(RGB rgb)
+{
+ if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0)
+ return rgb;
+
+ Lab lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.L;
+ float eps = 0.00001f;
+ float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b));
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ float L0 = 0.5;
+
+ float t = find_gamut_intersection(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1 - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ });
+}
+
+RGB gamut_clip_project_to_L_cusp(RGB rgb)
+{
+ if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0)
+ return rgb;
+
+ Lab lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.L;
+ float eps = 0.00001f;
+ float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b));
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.
+ LC cusp = find_cusp(a_, b_);
+
+ float L0 = cusp.L;
+
+ float t = find_gamut_intersection(a_, b_, L, C, L0);
+
+ float L_clipped = L0 * (1 - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ });
+}
+
+RGB gamut_clip_adaptive_L0_0_5(RGB rgb, float alpha = 0.05f)
+{
+ if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0)
+ return rgb;
+
+ Lab lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.L;
+ float eps = 0.00001f;
+ float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b));
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ float Ld = L - 0.5f;
+ float e1 = 0.5f + fabs(Ld) + alpha * C;
+ float L0 = 0.5f * (1.f + sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * fabs(Ld))));
+
+ float t = find_gamut_intersection(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ });
+}
+
+RGB gamut_clip_adaptive_L0_L_cusp(RGB rgb, float alpha = 0.05f)
+{
+ if (rgb.r < 1 && rgb.g < 1 && rgb.b < 1 && rgb.r > 0 && rgb.g > 0 && rgb.b > 0)
+ return rgb;
+
+ Lab lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.L;
+ float eps = 0.00001f;
+ float C = fmax(eps, sqrtf(lab.a * lab.a + lab.b * lab.b));
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.
+ LC cusp = find_cusp(a_, b_);
+
+ float Ld = L - cusp.L;
+ float k = 2.f * (Ld > 0 ? 1.f - cusp.L : cusp.L);
+
+ float e1 = 0.5f * k + fabs(Ld) + alpha * C / k;
+ float L0 = cusp.L + 0.5f * (sgn(Ld) * (e1 - sqrtf(e1 * e1 - 2.f * k * fabs(Ld))));
+
+ float t = find_gamut_intersection(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb({ L_clipped, C_clipped * a_, C_clipped * b_ });
+}
+
+float toe(float x)
+{
+ constexpr float k_1 = 0.206f;
+ constexpr float k_2 = 0.03f;
+ constexpr float k_3 = (1.f + k_1) / (1.f + k_2);
+ return 0.5f * (k_3 * x - k_1 + sqrtf((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x));
+}
+
+float toe_inv(float x)
+{
+ constexpr float k_1 = 0.206f;
+ constexpr float k_2 = 0.03f;
+ constexpr float k_3 = (1.f + k_1) / (1.f + k_2);
+ return (x * x + k_1 * x) / (k_3 * (x + k_2));
+}
+
+ST to_ST(LC cusp)
+{
+ float L = cusp.L;
+ float C = cusp.C;
+ return { C / L, C / (1 - L) };
+}
+
+// Returns a smooth approximation of the location of the cusp
+// This polynomial was created by an optimization process
+// It has been designed so that S_mid < S_max and T_mid < T_max
+ST get_ST_mid(float a_, float b_)
+{
+ float S = 0.11516993f + 1.f / (
+ +7.44778970f + 4.15901240f * b_
+ + a_ * (-2.19557347f + 1.75198401f * b_
+ + a_ * (-2.13704948f - 10.02301043f * b_
+ + a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_
+ )))
+ );
+
+ float T = 0.11239642f + 1.f / (
+ +1.61320320f - 0.68124379f * b_
+ + a_ * (+0.40370612f + 0.90148123f * b_
+ + a_ * (-0.27087943f + 0.61223990f * b_
+ + a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_
+ )))
+ );
+
+ return { S, T };
+}
+
+struct Cs { float C_0; float C_mid; float C_max; };
+Cs get_Cs(float L, float a_, float b_)
+{
+ LC cusp = find_cusp(a_, b_);
+
+ float C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp);
+ ST ST_max = to_ST(cusp);
+
+ // Scale factor to compensate for the curved part of gamut shape:
+ float k = C_max / fmin((L * ST_max.S), (1 - L) * ST_max.T);
+
+ float C_mid;
+ {
+ ST ST_mid = get_ST_mid(a_, b_);
+
+ // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
+ float C_a = L * ST_mid.S;
+ float C_b = (1.f - L) * ST_mid.T;
+ C_mid = 0.9f * k * sqrtf(sqrtf(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b))));
+ }
+
+ float C_0;
+ {
+ // for C_0, the shape is independent of hue, so ST are constant. Values picked to roughly be the average values of ST.
+ float C_a = L * 0.4f;
+ float C_b = (1.f - L) * 0.8f;
+
+ // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
+ C_0 = sqrtf(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b)));
+ }
+
+ return { C_0, C_mid, C_max };
+}
+
+RGB okhsl_to_srgb(HSL hsl)
+{
+ float h = hsl.h;
+ float s = hsl.s;
+ float l = hsl.l;
+
+ if (l == 1.0f)
+ {
+ return { 1.f, 1.f, 1.f };
+ }
+
+ else if (l == 0.f)
+ {
+ return { 0.f, 0.f, 0.f };
+ }
+
+ float a_ = cosf(2.f * pi * h);
+ float b_ = sinf(2.f * pi * h);
+ float L = toe_inv(l);
+
+ Cs cs = get_Cs(L, a_, b_);
+ float C_0 = cs.C_0;
+ float C_mid = cs.C_mid;
+ float C_max = cs.C_max;
+
+ float mid = 0.8f;
+ float mid_inv = 1.25f;
+
+ float C, t, k_0, k_1, k_2;
+
+ if (s < mid)
+ {
+ t = mid_inv * s;
+
+ k_1 = mid * C_0;
+ k_2 = (1.f - k_1 / C_mid);
+
+ C = t * k_1 / (1.f - k_2 * t);
+ }
+ else
+ {
+ t = (s - mid)/ (1 - mid);
+
+ k_0 = C_mid;
+ k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
+ k_2 = (1.f - (k_1) / (C_max - C_mid));
+
+ C = k_0 + t * k_1 / (1.f - k_2 * t);
+ }
+
+ RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ });
+ return {
+ srgb_transfer_function(rgb.r),
+ srgb_transfer_function(rgb.g),
+ srgb_transfer_function(rgb.b),
+ };
+}
+
+HSL srgb_to_okhsl(RGB rgb)
+{
+ Lab lab = linear_srgb_to_oklab({
+ srgb_transfer_function_inv(rgb.r),
+ srgb_transfer_function_inv(rgb.g),
+ srgb_transfer_function_inv(rgb.b)
+ });
+
+ float C = sqrtf(lab.a * lab.a + lab.b * lab.b);
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ float L = lab.L;
+ float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi;
+
+ Cs cs = get_Cs(L, a_, b_);
+ float C_0 = cs.C_0;
+ float C_mid = cs.C_mid;
+ float C_max = cs.C_max;
+
+ // Inverse of the interpolation in okhsl_to_srgb:
+
+ float mid = 0.8f;
+ float mid_inv = 1.25f;
+
+ float s;
+ if (C < C_mid)
+ {
+ float k_1 = mid * C_0;
+ float k_2 = (1.f - k_1 / C_mid);
+
+ float t = C / (k_1 + k_2 * C);
+ s = t * mid;
+ }
+ else
+ {
+ float k_0 = C_mid;
+ float k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
+ float k_2 = (1.f - (k_1) / (C_max - C_mid));
+
+ float t = (C - k_0) / (k_1 + k_2 * (C - k_0));
+ s = mid + (1.f - mid) * t;
+ }
+
+ float l = toe(L);
+ return { h, s, l };
+}
+
+
+RGB okhsv_to_srgb(HSV hsv)
+{
+ float h = hsv.h;
+ float s = hsv.s;
+ float v = hsv.v;
+
+ float a_ = cosf(2.f * pi * h);
+ float b_ = sinf(2.f * pi * h);
+
+ LC cusp = find_cusp(a_, b_);
+ ST ST_max = to_ST(cusp);
+ float S_max = ST_max.S;
+ float T_max = ST_max.T;
+ float S_0 = 0.5f;
+ float k = 1 - S_0 / S_max;
+
+ // first we compute L and V as if the gamut is a perfect triangle:
+
+ // L, C when v==1:
+ float L_v = 1 - s * S_0 / (S_0 + T_max - T_max * k * s);
+ float C_v = s * T_max * S_0 / (S_0 + T_max - T_max * k * s);
+
+ float L = v * L_v;
+ float C = v * C_v;
+
+ // then we compensate for both toe and the curved top part of the triangle:
+ float L_vt = toe_inv(L_v);
+ float C_vt = C_v * L_vt / L_v;
+
+ float L_new = toe_inv(L);
+ C = C * L_new / L;
+ L = L_new;
+
+ RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt });
+ float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f)));
+
+ L = L * scale_L;
+ C = C * scale_L;
+
+ RGB rgb = oklab_to_linear_srgb({ L, C * a_, C * b_ });
+ return {
+ srgb_transfer_function(rgb.r),
+ srgb_transfer_function(rgb.g),
+ srgb_transfer_function(rgb.b),
+ };
+}
+
+HSV srgb_to_okhsv(RGB rgb)
+{
+ Lab lab = linear_srgb_to_oklab({
+ srgb_transfer_function_inv(rgb.r),
+ srgb_transfer_function_inv(rgb.g),
+ srgb_transfer_function_inv(rgb.b)
+ });
+
+ float C = sqrtf(lab.a * lab.a + lab.b * lab.b);
+ float a_ = lab.a / C;
+ float b_ = lab.b / C;
+
+ float L = lab.L;
+ float h = 0.5f + 0.5f * atan2f(-lab.b, -lab.a) / pi;
+
+ LC cusp = find_cusp(a_, b_);
+ ST ST_max = to_ST(cusp);
+ float S_max = ST_max.S;
+ float T_max = ST_max.T;
+ float S_0 = 0.5f;
+ float k = 1 - S_0 / S_max;
+
+ // first we find L_v, C_v, L_vt and C_vt
+
+ float t = T_max / (C + L * T_max);
+ float L_v = t * L;
+ float C_v = t * C;
+
+ float L_vt = toe_inv(L_v);
+ float C_vt = C_v * L_vt / L_v;
+
+ // we can then use these to invert the step that compensates for the toe and the curved top part of the triangle:
+ RGB rgb_scale = oklab_to_linear_srgb({ L_vt, a_ * C_vt, b_ * C_vt });
+ float scale_L = cbrtf(1.f / fmax(fmax(rgb_scale.r, rgb_scale.g), fmax(rgb_scale.b, 0.f)));
+
+ L = L / scale_L;
+ C = C / scale_L;
+
+ C = C * toe(L) / L;
+ L = toe(L);
+
+ // we can now compute v and s:
+
+ float v = L / L_v;
+ float s = (S_0 + T_max) * C_v / ((T_max * S_0) + T_max * k * C_v);
+
+ return { h, s, v };
+}
+
+};
+#endif // OK_COLOR_H
diff --git a/thirdparty/misc/ok_color_shader.h b/thirdparty/misc/ok_color_shader.h
new file mode 100644
index 0000000000..40d83366ee
--- /dev/null
+++ b/thirdparty/misc/ok_color_shader.h
@@ -0,0 +1,663 @@
+// Copyright(c) 2021 Björn Ottosson
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files(the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and /or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions :
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef OK_COLOR_SHADER_H
+#define OK_COLOR_SHADER_H
+
+#include "core/string/ustring.h"
+
+static String OK_COLOR_SHADER = R"(shader_type canvas_item;
+
+const float M_PI = 3.1415926535897932384626433832795;
+
+float cbrt( float x )
+{
+ return sign(x)*pow(abs(x),1.0f/3.0f);
+}
+
+float srgb_transfer_function(float a)
+{
+ return .0031308f >= a ? 12.92f * a : 1.055f * pow(a, .4166666666666667f) - .055f;
+}
+
+float srgb_transfer_function_inv(float a)
+{
+ return .04045f < a ? pow((a + .055f) / 1.055f, 2.4f) : a / 12.92f;
+}
+
+vec3 linear_srgb_to_oklab(vec3 c)
+{
+ float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
+ float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
+ float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;
+
+ float l_ = cbrt(l);
+ float m_ = cbrt(m);
+ float s_ = cbrt(s);
+
+ return vec3(
+ 0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_,
+ 1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_,
+ 0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_
+ );
+}
+
+vec3 oklab_to_linear_srgb(vec3 c)
+{
+ float l_ = c.x + 0.3963377774f * c.y + 0.2158037573f * c.z;
+ float m_ = c.x - 0.1055613458f * c.y - 0.0638541728f * c.z;
+ float s_ = c.x - 0.0894841775f * c.y - 1.2914855480f * c.z;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ return vec3(
+ +4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
+ -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
+ -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s
+ );
+}
+
+// Finds the maximum saturation possible for a given hue that fits in sRGB
+// Saturation here is defined as S = C/L
+// a and b must be normalized so a^2 + b^2 == 1
+float compute_max_saturation(float a, float b)
+{
+ // Max saturation will be when one of r, g or b goes below zero.
+
+ // Select different coefficients depending on which component goes below zero first
+ float k0, k1, k2, k3, k4, wl, wm, ws;
+
+ if (-1.88170328f * a - 0.80936493f * b > 1.f)
+ {
+ // Red component
+ k0 = +1.19086277f; k1 = +1.76576728f; k2 = +0.59662641f; k3 = +0.75515197f; k4 = +0.56771245f;
+ wl = +4.0767416621f; wm = -3.3077115913f; ws = +0.2309699292f;
+ }
+ else if (1.81444104f * a - 1.19445276f * b > 1.f)
+ {
+ // Green component
+ k0 = +0.73956515f; k1 = -0.45954404f; k2 = +0.08285427f; k3 = +0.12541070f; k4 = +0.14503204f;
+ wl = -1.2684380046f; wm = +2.6097574011f; ws = -0.3413193965f;
+ }
+ else
+ {
+ // Blue component
+ k0 = +1.35733652f; k1 = -0.00915799f; k2 = -1.15130210f; k3 = -0.50559606f; k4 = +0.00692167f;
+ wl = -0.0041960863f; wm = -0.7034186147f; ws = +1.7076147010f;
+ }
+
+ // Approximate max saturation using a polynomial:
+ float S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;
+
+ // Do one step Halley's method to get closer
+ // this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite
+ // this should be sufficient for most applications, otherwise do two/three steps
+
+ float k_l = +0.3963377774f * a + 0.2158037573f * b;
+ float k_m = -0.1055613458f * a - 0.0638541728f * b;
+ float k_s = -0.0894841775f * a - 1.2914855480f * b;
+
+ {
+ float l_ = 1.f + S * k_l;
+ float m_ = 1.f + S * k_m;
+ float s_ = 1.f + S * k_s;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ float l_dS = 3.f * k_l * l_ * l_;
+ float m_dS = 3.f * k_m * m_ * m_;
+ float s_dS = 3.f * k_s * s_ * s_;
+
+ float l_dS2 = 6.f * k_l * k_l * l_;
+ float m_dS2 = 6.f * k_m * k_m * m_;
+ float s_dS2 = 6.f * k_s * k_s * s_;
+
+ float f = wl * l + wm * m + ws * s;
+ float f1 = wl * l_dS + wm * m_dS + ws * s_dS;
+ float f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;
+
+ S = S - f * f1 / (f1 * f1 - 0.5f * f * f2);
+ }
+
+ return S;
+}
+
+// finds L_cusp and C_cusp for a given hue
+// a and b must be normalized so a^2 + b^2 == 1
+vec2 find_cusp(float a, float b)
+{
+ // First, find the maximum saturation (saturation S = C/L)
+ float S_cusp = compute_max_saturation(a, b);
+
+ // Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:
+ vec3 rgb_at_max = oklab_to_linear_srgb(vec3( 1, S_cusp * a, S_cusp * b ));
+ float L_cusp = cbrt(1.f / max(max(rgb_at_max.r, rgb_at_max.g), rgb_at_max.b));
+ float C_cusp = L_cusp * S_cusp;
+
+ return vec2( L_cusp , C_cusp );
+} )"
+R"(// Finds intersection of the line defined by
+// L = L0 * (1 - t) + t * L1;
+// C = t * C1;
+// a and b must be normalized so a^2 + b^2 == 1
+float find_gamut_intersection(float a, float b, float L1, float C1, float L0, vec2 cusp)
+{
+ // Find the intersection for upper and lower half seprately
+ float t;
+ if (((L1 - L0) * cusp.y - (cusp.x - L0) * C1) <= 0.f)
+ {
+ // Lower half
+
+ t = cusp.y * L0 / (C1 * cusp.x + cusp.y * (L0 - L1));
+ }
+ else
+ {
+ // Upper half
+
+ // First intersect with triangle
+ t = cusp.y * (L0 - 1.f) / (C1 * (cusp.x - 1.f) + cusp.y * (L0 - L1));
+
+ // Then one step Halley's method
+ {
+ float dL = L1 - L0;
+ float dC = C1;
+
+ float k_l = +0.3963377774f * a + 0.2158037573f * b;
+ float k_m = -0.1055613458f * a - 0.0638541728f * b;
+ float k_s = -0.0894841775f * a - 1.2914855480f * b;
+
+ float l_dt = dL + dC * k_l;
+ float m_dt = dL + dC * k_m;
+ float s_dt = dL + dC * k_s;
+
+
+ // If higher accuracy is required, 2 or 3 iterations of the following block can be used:
+ {
+ float L = L0 * (1.f - t) + t * L1;
+ float C = t * C1;
+
+ float l_ = L + C * k_l;
+ float m_ = L + C * k_m;
+ float s_ = L + C * k_s;
+
+ float l = l_ * l_ * l_;
+ float m = m_ * m_ * m_;
+ float s = s_ * s_ * s_;
+
+ float ldt = 3.f * l_dt * l_ * l_;
+ float mdt = 3.f * m_dt * m_ * m_;
+ float sdt = 3.f * s_dt * s_ * s_;
+
+ float ldt2 = 6.f * l_dt * l_dt * l_;
+ float mdt2 = 6.f * m_dt * m_dt * m_;
+ float sdt2 = 6.f * s_dt * s_dt * s_;
+
+ float r = 4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s - 1.f;
+ float r1 = 4.0767416621f * ldt - 3.3077115913f * mdt + 0.2309699292f * sdt;
+ float r2 = 4.0767416621f * ldt2 - 3.3077115913f * mdt2 + 0.2309699292f * sdt2;
+
+ float u_r = r1 / (r1 * r1 - 0.5f * r * r2);
+ float t_r = -r * u_r;
+
+ float g = -1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s - 1.f;
+ float g1 = -1.2684380046f * ldt + 2.6097574011f * mdt - 0.3413193965f * sdt;
+ float g2 = -1.2684380046f * ldt2 + 2.6097574011f * mdt2 - 0.3413193965f * sdt2;
+
+ float u_g = g1 / (g1 * g1 - 0.5f * g * g2);
+ float t_g = -g * u_g;
+
+ float b = -0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s - 1.f;
+ float b1 = -0.0041960863f * ldt - 0.7034186147f * mdt + 1.7076147010f * sdt;
+ float b2 = -0.0041960863f * ldt2 - 0.7034186147f * mdt2 + 1.7076147010f * sdt2;
+
+ float u_b = b1 / (b1 * b1 - 0.5f * b * b2);
+ float t_b = -b * u_b;
+
+ t_r = u_r >= 0.f ? t_r : 10000.f;
+ t_g = u_g >= 0.f ? t_g : 10000.f;
+ t_b = u_b >= 0.f ? t_b : 10000.f;
+
+ t += min(t_r, min(t_g, t_b));
+ }
+ }
+ }
+
+ return t;
+}
+
+float find_gamut_intersection_5(float a, float b, float L1, float C1, float L0)
+{
+ // Find the cusp of the gamut triangle
+ vec2 cusp = find_cusp(a, b);
+
+ return find_gamut_intersection(a, b, L1, C1, L0, cusp);
+})"
+R"(
+
+vec3 gamut_clip_preserve_chroma(vec3 rgb)
+{
+ if (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)
+ return rgb;
+
+ vec3 lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.x;
+ float eps = 0.00001f;
+ float C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ float L0 = clamp(L, 0.f, 1.f);
+
+ float t = find_gamut_intersection_5(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));
+}
+
+vec3 gamut_clip_project_to_0_5(vec3 rgb)
+{
+ if (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)
+ return rgb;
+
+ vec3 lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.x;
+ float eps = 0.00001f;
+ float C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ float L0 = 0.5;
+
+ float t = find_gamut_intersection_5(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));
+}
+
+vec3 gamut_clip_project_to_L_cusp(vec3 rgb)
+{
+ if (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)
+ return rgb;
+
+ vec3 lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.x;
+ float eps = 0.00001f;
+ float C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.
+ vec2 cusp = find_cusp(a_, b_);
+
+ float L0 = cusp.x;
+
+ float t = find_gamut_intersection_5(a_, b_, L, C, L0);
+
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));
+}
+
+vec3 gamut_clip_adaptive_L0_0_5(vec3 rgb, float alpha)
+{
+ if (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)
+ return rgb;
+
+ vec3 lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.x;
+ float eps = 0.00001f;
+ float C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ float Ld = L - 0.5f;
+ float e1 = 0.5f + abs(Ld) + alpha * C;
+ float L0 = 0.5f * (1.f + sign(Ld) * (e1 - sqrt(e1 * e1 - 2.f * abs(Ld))));
+
+ float t = find_gamut_intersection_5(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));
+}
+
+vec3 gamut_clip_adaptive_L0_L_cusp(vec3 rgb, float alpha)
+{
+ if (rgb.r < 1.f && rgb.g < 1.f && rgb.b < 1.f && rgb.r > 0.f && rgb.g > 0.f && rgb.b > 0.f)
+ return rgb;
+
+ vec3 lab = linear_srgb_to_oklab(rgb);
+
+ float L = lab.x;
+ float eps = 0.00001f;
+ float C = max(eps, sqrt(lab.y * lab.y + lab.z * lab.z));
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ // The cusp is computed here and in find_gamut_intersection, an optimized solution would only compute it once.
+ vec2 cusp = find_cusp(a_, b_);
+
+ float Ld = L - cusp.x;
+ float k = 2.f * (Ld > 0.f ? 1.f - cusp.x : cusp.x);
+
+ float e1 = 0.5f * k + abs(Ld) + alpha * C / k;
+ float L0 = cusp.x + 0.5f * (sign(Ld) * (e1 - sqrt(e1 * e1 - 2.f * k * abs(Ld))));
+
+ float t = find_gamut_intersection_5(a_, b_, L, C, L0);
+ float L_clipped = L0 * (1.f - t) + t * L;
+ float C_clipped = t * C;
+
+ return oklab_to_linear_srgb(vec3( L_clipped, C_clipped * a_, C_clipped * b_ ));
+}
+
+float toe(float x)
+{
+ float k_1 = 0.206f;
+ float k_2 = 0.03f;
+ float k_3 = (1.f + k_1) / (1.f + k_2);
+ return 0.5f * (k_3 * x - k_1 + sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4.f * k_2 * k_3 * x));
+}
+
+float toe_inv(float x)
+{
+ float k_1 = 0.206f;
+ float k_2 = 0.03f;
+ float k_3 = (1.f + k_1) / (1.f + k_2);
+ return (x * x + k_1 * x) / (k_3 * (x + k_2));
+}
+)"
+R"(vec2 to_ST(vec2 cusp)
+{
+ float L = cusp.x;
+ float C = cusp.y;
+ return vec2( C / L, C / (1.f - L) );
+}
+
+// Returns a smooth approximation of the location of the cusp
+// This polynomial was created by an optimization process
+// It has been designed so that S_mid < S_max and T_mid < T_max
+vec2 get_ST_mid(float a_, float b_)
+{
+ float S = 0.11516993f + 1.f / (
+ +7.44778970f + 4.15901240f * b_
+ + a_ * (-2.19557347f + 1.75198401f * b_
+ + a_ * (-2.13704948f - 10.02301043f * b_
+ + a_ * (-4.24894561f + 5.38770819f * b_ + 4.69891013f * a_
+ )))
+ );
+
+ float T = 0.11239642f + 1.f / (
+ +1.61320320f - 0.68124379f * b_
+ + a_ * (+0.40370612f + 0.90148123f * b_
+ + a_ * (-0.27087943f + 0.61223990f * b_
+ + a_ * (+0.00299215f - 0.45399568f * b_ - 0.14661872f * a_
+ )))
+ );
+
+ return vec2( S, T );
+}
+
+vec3 get_Cs(float L, float a_, float b_)
+{
+ vec2 cusp = find_cusp(a_, b_);
+
+ float C_max = find_gamut_intersection(a_, b_, L, 1.f, L, cusp);
+ vec2 ST_max = to_ST(cusp);
+
+ // Scale factor to compensate for the curved part of gamut shape:
+ float k = C_max / min((L * ST_max.x), (1.f - L) * ST_max.y);
+
+ float C_mid;
+ {
+ vec2 ST_mid = get_ST_mid(a_, b_);
+
+ // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
+ float C_a = L * ST_mid.x;
+ float C_b = (1.f - L) * ST_mid.y;
+ C_mid = 0.9f * k * sqrt(sqrt(1.f / (1.f / (C_a * C_a * C_a * C_a) + 1.f / (C_b * C_b * C_b * C_b))));
+ }
+
+ float C_0;
+ {
+ // for C_0, the shape is independent of hue, so vec2 are constant. Values picked to roughly be the average values of vec2.
+ float C_a = L * 0.4f;
+ float C_b = (1.f - L) * 0.8f;
+
+ // Use a soft minimum function, instead of a sharp triangle shape to get a smooth value for chroma.
+ C_0 = sqrt(1.f / (1.f / (C_a * C_a) + 1.f / (C_b * C_b)));
+ }
+
+ return vec3( C_0, C_mid, C_max );
+}
+
+vec3 okhsl_to_srgb(vec3 hsl)
+{
+ float h = hsl.x;
+ float s = hsl.y;
+ float l = hsl.z;
+
+ if (l == 1.0f)
+ {
+ return vec3( 1.f, 1.f, 1.f );
+ }
+
+ else if (l == 0.f)
+ {
+ return vec3( 0.f, 0.f, 0.f );
+ }
+
+ float a_ = cos(2.f * M_PI * h);
+ float b_ = sin(2.f * M_PI * h);
+ float L = toe_inv(l);
+
+ vec3 cs = get_Cs(L, a_, b_);
+ float C_0 = cs.x;
+ float C_mid = cs.y;
+ float C_max = cs.z;
+
+ float mid = 0.8f;
+ float mid_inv = 1.25f;
+
+ float C, t, k_0, k_1, k_2;
+
+ if (s < mid)
+ {
+ t = mid_inv * s;
+
+ k_1 = mid * C_0;
+ k_2 = (1.f - k_1 / C_mid);
+
+ C = t * k_1 / (1.f - k_2 * t);
+ }
+ else
+ {
+ t = (s - mid)/ (1.f - mid);
+
+ k_0 = C_mid;
+ k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
+ k_2 = (1.f - (k_1) / (C_max - C_mid));
+
+ C = k_0 + t * k_1 / (1.f - k_2 * t);
+ }
+
+ vec3 rgb = oklab_to_linear_srgb(vec3( L, C * a_, C * b_ ));
+ return vec3(
+ srgb_transfer_function(rgb.r),
+ srgb_transfer_function(rgb.g),
+ srgb_transfer_function(rgb.b)
+ );
+}
+
+vec3 srgb_to_okhsl(vec3 rgb)
+{
+ vec3 lab = linear_srgb_to_oklab(vec3(
+ srgb_transfer_function_inv(rgb.r),
+ srgb_transfer_function_inv(rgb.g),
+ srgb_transfer_function_inv(rgb.b)
+ ));
+
+ float C = sqrt(lab.y * lab.y + lab.z * lab.z);
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ float L = lab.x;
+ float h = 0.5f + 0.5f * atan(-lab.z, -lab.y) / M_PI;
+
+ vec3 cs = get_Cs(L, a_, b_);
+ float C_0 = cs.x;
+ float C_mid = cs.y;
+ float C_max = cs.z;
+
+ // Inverse of the interpolation in okhsl_to_srgb:
+
+ float mid = 0.8f;
+ float mid_inv = 1.25f;
+
+ float s;
+ if (C < C_mid)
+ {
+ float k_1 = mid * C_0;
+ float k_2 = (1.f - k_1 / C_mid);
+
+ float t = C / (k_1 + k_2 * C);
+ s = t * mid;
+ }
+ else
+ {
+ float k_0 = C_mid;
+ float k_1 = (1.f - mid) * C_mid * C_mid * mid_inv * mid_inv / C_0;
+ float k_2 = (1.f - (k_1) / (C_max - C_mid));
+
+ float t = (C - k_0) / (k_1 + k_2 * (C - k_0));
+ s = mid + (1.f - mid) * t;
+ }
+
+ float l = toe(L);
+ return vec3( h, s, l );
+}
+
+
+vec3 okhsv_to_srgb(vec3 hsv)
+{
+ float h = hsv.x;
+ float s = hsv.y;
+ float v = hsv.z;
+
+ float a_ = cos(2.f * M_PI * h);
+ float b_ = sin(2.f * M_PI * h);
+
+ vec2 cusp = find_cusp(a_, b_);
+ vec2 ST_max = to_ST(cusp);
+ float S_max = ST_max.x;
+ float T_max = ST_max.y;
+ float S_0 = 0.5f;
+ float k = 1.f- S_0 / S_max;
+
+ // first we compute L and V as if the gamut is a perfect triangle:
+
+ // L, C when v==1:
+ float L_v = 1.f - s * S_0 / (S_0 + T_max - T_max * k * s);
+ float C_v = s * T_max * S_0 / (S_0 + T_max - T_max * k * s);
+
+ float L = v * L_v;
+ float C = v * C_v;
+
+ // then we compensate for both toe and the curved top part of the triangle:
+ float L_vt = toe_inv(L_v);
+ float C_vt = C_v * L_vt / L_v;
+
+ float L_new = toe_inv(L);
+ C = C * L_new / L;
+ L = L_new;
+
+ vec3 rgb_scale = oklab_to_linear_srgb(vec3( L_vt, a_ * C_vt, b_ * C_vt ));
+ float scale_L = cbrt(1.f / max(max(rgb_scale.r, rgb_scale.g), max(rgb_scale.b, 0.f)));
+
+ L = L * scale_L;
+ C = C * scale_L;
+
+ vec3 rgb = oklab_to_linear_srgb(vec3( L, C * a_, C * b_ ));
+ return vec3(
+ srgb_transfer_function(rgb.r),
+ srgb_transfer_function(rgb.g),
+ srgb_transfer_function(rgb.b)
+ );
+}
+)"
+R"(
+vec3 srgb_to_okhsv(vec3 rgb)
+{
+ vec3 lab = linear_srgb_to_oklab(vec3(
+ srgb_transfer_function_inv(rgb.r),
+ srgb_transfer_function_inv(rgb.g),
+ srgb_transfer_function_inv(rgb.b)
+ ));
+
+ float C = sqrt(lab.y * lab.y + lab.z * lab.z);
+ float a_ = lab.y / C;
+ float b_ = lab.z / C;
+
+ float L = lab.x;
+ float h = 0.5f + 0.5f * atan(-lab.z, -lab.y) / M_PI;
+
+ vec2 cusp = find_cusp(a_, b_);
+ vec2 ST_max = to_ST(cusp);
+ float S_max = ST_max.x;
+ float T_max = ST_max.y;
+ float S_0 = 0.5f;
+ float k = 1.f - S_0 / S_max;
+
+ // first we find L_v, C_v, L_vt and C_vt
+
+ float t = T_max / (C + L * T_max);
+ float L_v = t * L;
+ float C_v = t * C;
+
+ float L_vt = toe_inv(L_v);
+ float C_vt = C_v * L_vt / L_v;
+
+ // we can then use these to invert the step that compensates for the toe and the curved top part of the triangle:
+ vec3 rgb_scale = oklab_to_linear_srgb(vec3( L_vt, a_ * C_vt, b_ * C_vt ));
+ float scale_L = cbrt(1.f / max(max(rgb_scale.r, rgb_scale.g), max(rgb_scale.b, 0.f)));
+
+ L = L / scale_L;
+ C = C / scale_L;
+
+ C = C * toe(L) / L;
+ L = toe(L);
+
+ // we can now compute v and s:
+
+ float v = L / L_v;
+ float s = (S_0 + T_max) * C_v / ((T_max * S_0) + T_max * k * C_v);
+
+ return vec3 (h, s, v );
+})";
+
+#endif
diff --git a/thirdparty/misc/open-simplex-noise-LICENSE b/thirdparty/misc/open-simplex-noise-LICENSE
deleted file mode 100644
index a84c395662..0000000000
--- a/thirdparty/misc/open-simplex-noise-LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-This is free and unencumbered software released into the public domain.
-
-Anyone is free to copy, modify, publish, use, compile, sell, or
-distribute this software, either in source code form or as a compiled
-binary, for any purpose, commercial or non-commercial, and by any
-means.
-
-In jurisdictions that recognize copyright laws, the author or authors
-of this software dedicate any and all copyright interest in the
-software to the public domain. We make this dedication for the benefit
-of the public at large and to the detriment of our heirs and
-successors. We intend this dedication to be an overt act of
-relinquishment in perpetuity of all present and future rights to this
-software under copyright law.
-
-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 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.
-
-For more information, please refer to <http://unlicense.org>
-
diff --git a/thirdparty/misc/open-simplex-noise-no-allocate.patch b/thirdparty/misc/open-simplex-noise-no-allocate.patch
deleted file mode 100644
index fc3abe7d00..0000000000
--- a/thirdparty/misc/open-simplex-noise-no-allocate.patch
+++ /dev/null
@@ -1,133 +0,0 @@
-diff -u orig/open-simplex-noise.c misc/open-simplex-noise.c
---- orig/open-simplex-noise.c 2018-09-14 11:11:40.049810000 +0200
-+++ misc/open-simplex-noise.c 2018-09-14 11:09:39.726457000 +0200
-@@ -13,6 +13,11 @@
- * of any particular randomization library, so results
- * will be the same when ported to other languages.
- */
-+
-+// -- GODOT start --
-+// Modified to work without allocating memory, also removed some unused function.
-+// -- GODOT end --
-+
- #include <math.h>
- #include <stdlib.h>
- #include <stdint.h>
-@@ -34,11 +39,12 @@
-
- #define DEFAULT_SEED (0LL)
-
--struct osn_context {
-+// -- GODOT start --
-+/*struct osn_context {
- int16_t *perm;
- int16_t *permGradIndex3D;
--};
--
-+};*/
-+// -- GODOT end --
- #define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
-
- /*
-@@ -126,7 +132,9 @@
- int xi = (int) x;
- return x < xi ? xi - 1 : xi;
- }
--
-+
-+// -- GODOT start --
-+/*
- static int allocate_perm(struct osn_context *ctx, int nperm, int ngrad)
- {
- if (ctx->perm)
-@@ -154,18 +162,21 @@
- memcpy(ctx->perm, p, sizeof(*ctx->perm) * nelements);
-
- for (i = 0; i < 256; i++) {
-- /* Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array. */
-+ // Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array.
- ctx->permGradIndex3D[i] = (int16_t)((ctx->perm[i] % (ARRAYSIZE(gradients3D) / 3)) * 3);
- }
- return 0;
- }
-+*/
-+// -- GODOT end --
-
- /*
- * Initializes using a permutation array generated from a 64-bit seed.
- * Generates a proper permutation (i.e. doesn't merely perform N successive pair
- * swaps on a base array). Uses a simple 64-bit LCG.
- */
--int open_simplex_noise(int64_t seed, struct osn_context **ctx)
-+// -- GODOT start --
-+int open_simplex_noise(int64_t seed, struct osn_context *ctx)
- {
- int rc;
- int16_t source[256];
-@@ -174,20 +185,9 @@
- int16_t *permGradIndex3D;
- int r;
-
-- *ctx = (struct osn_context *) malloc(sizeof(**ctx));
-- if (!(*ctx))
-- return -ENOMEM;
-- (*ctx)->perm = NULL;
-- (*ctx)->permGradIndex3D = NULL;
--
-- rc = allocate_perm(*ctx, 256, 256);
-- if (rc) {
-- free(*ctx);
-- return rc;
-- }
--
-- perm = (*ctx)->perm;
-- permGradIndex3D = (*ctx)->permGradIndex3D;
-+ perm = ctx->perm;
-+ permGradIndex3D = ctx->permGradIndex3D;
-+// -- GODOT end --
-
- for (i = 0; i < 256; i++)
- source[i] = (int16_t) i;
-@@ -206,6 +206,8 @@
- return 0;
- }
-
-+// -- GODOT start --
-+/*
- void open_simplex_noise_free(struct osn_context *ctx)
- {
- if (!ctx)
-@@ -220,6 +222,8 @@
- }
- free(ctx);
- }
-+*/
-+// -- GODOT end --
-
- /* 2D OpenSimplex (Simplectic) Noise. */
- double open_simplex_noise2(struct osn_context *ctx, double x, double y)
-diff -u orig/open-simplex-noise.h misc/open-simplex-noise.h
---- orig/open-simplex-noise.h 2018-09-14 11:11:19.659807000 +0200
-+++ misc/open-simplex-noise.h 2018-09-14 11:10:05.006460000 +0200
-@@ -35,11 +35,18 @@
- extern "C" {
- #endif
-
--struct osn_context;
-+// -- GODOT start --
-+// Modified to work without allocating memory, also removed some unused function.
-
--int open_simplex_noise(int64_t seed, struct osn_context **ctx);
-+struct osn_context {
-+ int16_t perm[256];
-+ int16_t permGradIndex3D[256];
-+};
-+
-+int open_simplex_noise(int64_t seed, struct osn_context *ctx);
-+//int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
-+// -- GODOT end --
- void open_simplex_noise_free(struct osn_context *ctx);
--int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
- double open_simplex_noise2(struct osn_context *ctx, double x, double y);
- double open_simplex_noise3(struct osn_context *ctx, double x, double y, double z);
- double open_simplex_noise4(struct osn_context *ctx, double x, double y, double z, double w);
diff --git a/thirdparty/misc/open-simplex-noise.c b/thirdparty/misc/open-simplex-noise.c
deleted file mode 100644
index 44a072cad1..0000000000
--- a/thirdparty/misc/open-simplex-noise.c
+++ /dev/null
@@ -1,2255 +0,0 @@
-/*
- * OpenSimplex (Simplectic) Noise in C.
- * Ported by Stephen M. Cameron from Kurt Spencer's java implementation
- *
- * v1.1 (October 5, 2014)
- * - Added 2D and 4D implementations.
- * - Proper gradient sets for all dimensions, from a
- * dimensionally-generalizable scheme with an actual
- * rhyme and reason behind it.
- * - Removed default permutation array in favor of
- * default seed.
- * - Changed seed-based constructor to be independent
- * of any particular randomization library, so results
- * will be the same when ported to other languages.
- */
-
-// -- GODOT start --
-// Modified to work without allocating memory, also removed some unused function.
-// -- GODOT end --
-
-#include <math.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-
-#include "open-simplex-noise.h"
-
-#define STRETCH_CONSTANT_2D (-0.211324865405187) /* (1 / sqrt(2 + 1) - 1 ) / 2; */
-#define SQUISH_CONSTANT_2D (0.366025403784439) /* (sqrt(2 + 1) -1) / 2; */
-#define STRETCH_CONSTANT_3D (-1.0 / 6.0) /* (1 / sqrt(3 + 1) - 1) / 3; */
-#define SQUISH_CONSTANT_3D (1.0 / 3.0) /* (sqrt(3+1)-1)/3; */
-#define STRETCH_CONSTANT_4D (-0.138196601125011) /* (1 / sqrt(4 + 1) - 1) / 4; */
-#define SQUISH_CONSTANT_4D (0.309016994374947) /* (sqrt(4 + 1) - 1) / 4; */
-
-#define NORM_CONSTANT_2D (47.0)
-#define NORM_CONSTANT_3D (103.0)
-#define NORM_CONSTANT_4D (30.0)
-
-#define DEFAULT_SEED (0LL)
-
-// -- GODOT start --
-/*struct osn_context {
- int16_t *perm;
- int16_t *permGradIndex3D;
-};*/
-// -- GODOT end --
-#define ARRAYSIZE(x) (sizeof((x)) / sizeof((x)[0]))
-
-/*
- * Gradients for 2D. They approximate the directions to the
- * vertices of an octagon from the center.
- */
-static const int8_t gradients2D[] = {
- 5, 2, 2, 5,
- -5, 2, -2, 5,
- 5, -2, 2, -5,
- -5, -2, -2, -5,
-};
-
-/*
- * Gradients for 3D. They approximate the directions to the
- * vertices of a rhombicuboctahedron from the center, skewed so
- * that the triangular and square facets can be inscribed inside
- * circles of the same radius.
- */
-static const signed char gradients3D[] = {
- -11, 4, 4, -4, 11, 4, -4, 4, 11,
- 11, 4, 4, 4, 11, 4, 4, 4, 11,
- -11, -4, 4, -4, -11, 4, -4, -4, 11,
- 11, -4, 4, 4, -11, 4, 4, -4, 11,
- -11, 4, -4, -4, 11, -4, -4, 4, -11,
- 11, 4, -4, 4, 11, -4, 4, 4, -11,
- -11, -4, -4, -4, -11, -4, -4, -4, -11,
- 11, -4, -4, 4, -11, -4, 4, -4, -11,
-};
-
-/*
- * Gradients for 4D. They approximate the directions to the
- * vertices of a disprismatotesseractihexadecachoron from the center,
- * skewed so that the tetrahedral and cubic facets can be inscribed inside
- * spheres of the same radius.
- */
-static const signed char gradients4D[] = {
- 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 3,
- -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3,
- 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3, 1, 1, -1, 1, 3,
- -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3,
- 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3, 1, 1, 1, -1, 3,
- -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3,
- 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3, 1, 1, -1, -1, 3,
- -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3,
- 3, 1, 1, -1, 1, 3, 1, -1, 1, 1, 3, -1, 1, 1, 1, -3,
- -3, 1, 1, -1, -1, 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3,
- 3, -1, 1, -1, 1, -3, 1, -1, 1, -1, 3, -1, 1, -1, 1, -3,
- -3, -1, 1, -1, -1, -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3,
- 3, 1, -1, -1, 1, 3, -1, -1, 1, 1, -3, -1, 1, 1, -1, -3,
- -3, 1, -1, -1, -1, 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3,
- 3, -1, -1, -1, 1, -3, -1, -1, 1, -1, -3, -1, 1, -1, -1, -3,
- -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3, -1, -1, -1, -1, -3,
-};
-
-static double extrapolate2(const struct osn_context *ctx, int xsb, int ysb, double dx, double dy)
-{
- const int16_t *perm = ctx->perm;
- int index = perm[(perm[xsb & 0xFF] + ysb) & 0xFF] & 0x0E;
- return gradients2D[index] * dx
- + gradients2D[index + 1] * dy;
-}
-
-static double extrapolate3(const struct osn_context *ctx, int xsb, int ysb, int zsb, double dx, double dy, double dz)
-{
- const int16_t *perm = ctx->perm;
- const int16_t *permGradIndex3D = ctx->permGradIndex3D;
- int index = permGradIndex3D[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF];
- return gradients3D[index] * dx
- + gradients3D[index + 1] * dy
- + gradients3D[index + 2] * dz;
-}
-
-static double extrapolate4(const struct osn_context *ctx, int xsb, int ysb, int zsb, int wsb, double dx, double dy, double dz, double dw)
-{
- const int16_t *perm = ctx->perm;
- int index = perm[(perm[(perm[(perm[xsb & 0xFF] + ysb) & 0xFF] + zsb) & 0xFF] + wsb) & 0xFF] & 0xFC;
- return gradients4D[index] * dx
- + gradients4D[index + 1] * dy
- + gradients4D[index + 2] * dz
- + gradients4D[index + 3] * dw;
-}
-
-static INLINE int fastFloor(double x) {
- int xi = (int) x;
- return x < xi ? xi - 1 : xi;
-}
-
-// -- GODOT start --
-/*
-static int allocate_perm(struct osn_context *ctx, int nperm, int ngrad)
-{
- if (ctx->perm)
- free(ctx->perm);
- if (ctx->permGradIndex3D)
- free(ctx->permGradIndex3D);
- ctx->perm = (int16_t *) malloc(sizeof(*ctx->perm) * nperm);
- if (!ctx->perm)
- return -ENOMEM;
- ctx->permGradIndex3D = (int16_t *) malloc(sizeof(*ctx->permGradIndex3D) * ngrad);
- if (!ctx->permGradIndex3D) {
- free(ctx->perm);
- return -ENOMEM;
- }
- return 0;
-}
-
-int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements)
-{
- int i, rc;
-
- rc = allocate_perm(ctx, nelements, 256);
- if (rc)
- return rc;
- memcpy(ctx->perm, p, sizeof(*ctx->perm) * nelements);
-
- for (i = 0; i < 256; i++) {
- // Since 3D has 24 gradients, simple bitmask won't work, so precompute modulo array.
- ctx->permGradIndex3D[i] = (int16_t)((ctx->perm[i] % (ARRAYSIZE(gradients3D) / 3)) * 3);
- }
- return 0;
-}
-*/
-// -- GODOT end --
-
-/*
- * Initializes using a permutation array generated from a 64-bit seed.
- * Generates a proper permutation (i.e. doesn't merely perform N successive pair
- * swaps on a base array). Uses a simple 64-bit LCG.
- */
-// -- GODOT start --
-int open_simplex_noise(int64_t seed, struct osn_context *ctx)
-{
- int rc;
- int16_t source[256];
- int i;
- int16_t *perm;
- int16_t *permGradIndex3D;
- int r;
-
- perm = ctx->perm;
- permGradIndex3D = ctx->permGradIndex3D;
-// -- GODOT end --
-
- uint64_t seedU = seed;
- for (i = 0; i < 256; i++)
- source[i] = (int16_t) i;
- seedU = seedU * 6364136223846793005ULL + 1442695040888963407ULL;
- seedU = seedU * 6364136223846793005ULL + 1442695040888963407ULL;
- seedU = seedU * 6364136223846793005ULL + 1442695040888963407ULL;
- for (i = 255; i >= 0; i--) {
- seedU = seedU * 6364136223846793005ULL + 1442695040888963407ULL;
- r = (int)((seedU + 31) % (i + 1));
- if (r < 0)
- r += (i + 1);
- perm[i] = source[r];
- permGradIndex3D[i] = (short)((perm[i] % (ARRAYSIZE(gradients3D) / 3)) * 3);
- source[r] = source[i];
- }
- return 0;
-}
-
-// -- GODOT start --
-/*
-void open_simplex_noise_free(struct osn_context *ctx)
-{
- if (!ctx)
- return;
- if (ctx->perm) {
- free(ctx->perm);
- ctx->perm = NULL;
- }
- if (ctx->permGradIndex3D) {
- free(ctx->permGradIndex3D);
- ctx->permGradIndex3D = NULL;
- }
- free(ctx);
-}
-*/
-// -- GODOT end --
-
-/* 2D OpenSimplex (Simplectic) Noise. */
-double open_simplex_noise2(const struct osn_context *ctx, double x, double y)
-{
-
- /* Place input coordinates onto grid. */
- double stretchOffset = (x + y) * STRETCH_CONSTANT_2D;
- double xs = x + stretchOffset;
- double ys = y + stretchOffset;
-
- /* Floor to get grid coordinates of rhombus (stretched square) super-cell origin. */
- int xsb = fastFloor(xs);
- int ysb = fastFloor(ys);
-
- /* Skew out to get actual coordinates of rhombus origin. We'll need these later. */
- double squishOffset = (xsb + ysb) * SQUISH_CONSTANT_2D;
- double xb = xsb + squishOffset;
- double yb = ysb + squishOffset;
-
- /* Compute grid coordinates relative to rhombus origin. */
- double xins = xs - xsb;
- double yins = ys - ysb;
-
- /* Sum those together to get a value that determines which region we're in. */
- double inSum = xins + yins;
-
- /* Positions relative to origin point. */
- double dx0 = x - xb;
- double dy0 = y - yb;
-
- /* We'll be defining these inside the next block and using them afterwards. */
- double dx_ext, dy_ext;
- int xsv_ext, ysv_ext;
-
- double dx1;
- double dy1;
- double attn1;
- double dx2;
- double dy2;
- double attn2;
- double zins;
- double attn0;
- double attn_ext;
-
- double value = 0;
-
- /* Contribution (1,0) */
- dx1 = dx0 - 1 - SQUISH_CONSTANT_2D;
- dy1 = dy0 - 0 - SQUISH_CONSTANT_2D;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate2(ctx, xsb + 1, ysb + 0, dx1, dy1);
- }
-
- /* Contribution (0,1) */
- dx2 = dx0 - 0 - SQUISH_CONSTANT_2D;
- dy2 = dy0 - 1 - SQUISH_CONSTANT_2D;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate2(ctx, xsb + 0, ysb + 1, dx2, dy2);
- }
-
- if (inSum <= 1) { /* We're inside the triangle (2-Simplex) at (0,0) */
- zins = 1 - inSum;
- if (zins > xins || zins > yins) { /* (0,0) is one of the closest two triangular vertices */
- if (xins > yins) {
- xsv_ext = xsb + 1;
- ysv_ext = ysb - 1;
- dx_ext = dx0 - 1;
- dy_ext = dy0 + 1;
- } else {
- xsv_ext = xsb - 1;
- ysv_ext = ysb + 1;
- dx_ext = dx0 + 1;
- dy_ext = dy0 - 1;
- }
- } else { /* (1,0) and (0,1) are the closest two vertices. */
- xsv_ext = xsb + 1;
- ysv_ext = ysb + 1;
- dx_ext = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
- dy_ext = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
- }
- } else { /* We're inside the triangle (2-Simplex) at (1,1) */
- zins = 2 - inSum;
- if (zins < xins || zins < yins) { /* (0,0) is one of the closest two triangular vertices */
- if (xins > yins) {
- xsv_ext = xsb + 2;
- ysv_ext = ysb + 0;
- dx_ext = dx0 - 2 - 2 * SQUISH_CONSTANT_2D;
- dy_ext = dy0 + 0 - 2 * SQUISH_CONSTANT_2D;
- } else {
- xsv_ext = xsb + 0;
- ysv_ext = ysb + 2;
- dx_ext = dx0 + 0 - 2 * SQUISH_CONSTANT_2D;
- dy_ext = dy0 - 2 - 2 * SQUISH_CONSTANT_2D;
- }
- } else { /* (1,0) and (0,1) are the closest two vertices. */
- dx_ext = dx0;
- dy_ext = dy0;
- xsv_ext = xsb;
- ysv_ext = ysb;
- }
- xsb += 1;
- ysb += 1;
- dx0 = dx0 - 1 - 2 * SQUISH_CONSTANT_2D;
- dy0 = dy0 - 1 - 2 * SQUISH_CONSTANT_2D;
- }
-
- /* Contribution (0,0) or (1,1) */
- attn0 = 2 - dx0 * dx0 - dy0 * dy0;
- if (attn0 > 0) {
- attn0 *= attn0;
- value += attn0 * attn0 * extrapolate2(ctx, xsb, ysb, dx0, dy0);
- }
-
- /* Extra Vertex */
- attn_ext = 2 - dx_ext * dx_ext - dy_ext * dy_ext;
- if (attn_ext > 0) {
- attn_ext *= attn_ext;
- value += attn_ext * attn_ext * extrapolate2(ctx, xsv_ext, ysv_ext, dx_ext, dy_ext);
- }
-
- return value / NORM_CONSTANT_2D;
-}
-
-/*
- * 3D OpenSimplex (Simplectic) Noise
- */
-double open_simplex_noise3(const struct osn_context *ctx, double x, double y, double z)
-{
-
- /* Place input coordinates on simplectic honeycomb. */
- double stretchOffset = (x + y + z) * STRETCH_CONSTANT_3D;
- double xs = x + stretchOffset;
- double ys = y + stretchOffset;
- double zs = z + stretchOffset;
-
- /* Floor to get simplectic honeycomb coordinates of rhombohedron (stretched cube) super-cell origin. */
- int xsb = fastFloor(xs);
- int ysb = fastFloor(ys);
- int zsb = fastFloor(zs);
-
- /* Skew out to get actual coordinates of rhombohedron origin. We'll need these later. */
- double squishOffset = (xsb + ysb + zsb) * SQUISH_CONSTANT_3D;
- double xb = xsb + squishOffset;
- double yb = ysb + squishOffset;
- double zb = zsb + squishOffset;
-
- /* Compute simplectic honeycomb coordinates relative to rhombohedral origin. */
- double xins = xs - xsb;
- double yins = ys - ysb;
- double zins = zs - zsb;
-
- /* Sum those together to get a value that determines which region we're in. */
- double inSum = xins + yins + zins;
-
- /* Positions relative to origin point. */
- double dx0 = x - xb;
- double dy0 = y - yb;
- double dz0 = z - zb;
-
- /* We'll be defining these inside the next block and using them afterwards. */
- double dx_ext0, dy_ext0, dz_ext0;
- double dx_ext1, dy_ext1, dz_ext1;
- int xsv_ext0, ysv_ext0, zsv_ext0;
- int xsv_ext1, ysv_ext1, zsv_ext1;
-
- double wins;
- int8_t c, c1, c2;
- int8_t aPoint, bPoint;
- double aScore, bScore;
- int aIsFurtherSide;
- int bIsFurtherSide;
- double p1, p2, p3;
- double score;
- double attn0, attn1, attn2, attn3, attn4, attn5, attn6;
- double dx1, dy1, dz1;
- double dx2, dy2, dz2;
- double dx3, dy3, dz3;
- double dx4, dy4, dz4;
- double dx5, dy5, dz5;
- double dx6, dy6, dz6;
- double attn_ext0, attn_ext1;
-
- double value = 0;
- if (inSum <= 1) { /* We're inside the tetrahedron (3-Simplex) at (0,0,0) */
-
- /* Determine which two of (0,0,1), (0,1,0), (1,0,0) are closest. */
- aPoint = 0x01;
- aScore = xins;
- bPoint = 0x02;
- bScore = yins;
- if (aScore >= bScore && zins > bScore) {
- bScore = zins;
- bPoint = 0x04;
- } else if (aScore < bScore && zins > aScore) {
- aScore = zins;
- aPoint = 0x04;
- }
-
- /* Now we determine the two lattice points not part of the tetrahedron that may contribute.
- This depends on the closest two tetrahedral vertices, including (0,0,0) */
- wins = 1 - inSum;
- if (wins > aScore || wins > bScore) { /* (0,0,0) is one of the closest two tetrahedral vertices. */
- c = (bScore > aScore ? bPoint : aPoint); /* Our other closest vertex is the closest out of a and b. */
-
- if ((c & 0x01) == 0) {
- xsv_ext0 = xsb - 1;
- xsv_ext1 = xsb;
- dx_ext0 = dx0 + 1;
- dx_ext1 = dx0;
- } else {
- xsv_ext0 = xsv_ext1 = xsb + 1;
- dx_ext0 = dx_ext1 = dx0 - 1;
- }
-
- if ((c & 0x02) == 0) {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0;
- if ((c & 0x01) == 0) {
- ysv_ext1 -= 1;
- dy_ext1 += 1;
- } else {
- ysv_ext0 -= 1;
- dy_ext0 += 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1;
- }
-
- if ((c & 0x04) == 0) {
- zsv_ext0 = zsb;
- zsv_ext1 = zsb - 1;
- dz_ext0 = dz0;
- dz_ext1 = dz0 + 1;
- } else {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz_ext1 = dz0 - 1;
- }
- } else { /* (0,0,0) is not one of the closest two tetrahedral vertices. */
- c = (int8_t)(aPoint | bPoint); /* Our two extra vertices are determined by the closest two. */
-
- if ((c & 0x01) == 0) {
- xsv_ext0 = xsb;
- xsv_ext1 = xsb - 1;
- dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_3D;
- dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb + 1;
- dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x02) == 0) {
- ysv_ext0 = ysb;
- ysv_ext1 = ysb - 1;
- dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D;
- } else {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x04) == 0) {
- zsv_ext0 = zsb;
- zsv_ext1 = zsb - 1;
- dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D;
- } else {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
- }
- }
-
- /* Contribution (0,0,0) */
- attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0;
- if (attn0 > 0) {
- attn0 *= attn0;
- value += attn0 * attn0 * extrapolate3(ctx, xsb + 0, ysb + 0, zsb + 0, dx0, dy0, dz0);
- }
-
- /* Contribution (1,0,0) */
- dx1 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy1 = dy0 - 0 - SQUISH_CONSTANT_3D;
- dz1 = dz0 - 0 - SQUISH_CONSTANT_3D;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate3(ctx, xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1);
- }
-
- /* Contribution (0,1,0) */
- dx2 = dx0 - 0 - SQUISH_CONSTANT_3D;
- dy2 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz2 = dz1;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate3(ctx, xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2);
- }
-
- /* Contribution (0,0,1) */
- dx3 = dx2;
- dy3 = dy1;
- dz3 = dz0 - 1 - SQUISH_CONSTANT_3D;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate3(ctx, xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3);
- }
- } else if (inSum >= 2) { /* We're inside the tetrahedron (3-Simplex) at (1,1,1) */
-
- /* Determine which two tetrahedral vertices are the closest, out of (1,1,0), (1,0,1), (0,1,1) but not (1,1,1). */
- aPoint = 0x06;
- aScore = xins;
- bPoint = 0x05;
- bScore = yins;
- if (aScore <= bScore && zins < bScore) {
- bScore = zins;
- bPoint = 0x03;
- } else if (aScore > bScore && zins < aScore) {
- aScore = zins;
- aPoint = 0x03;
- }
-
- /* Now we determine the two lattice points not part of the tetrahedron that may contribute.
- This depends on the closest two tetrahedral vertices, including (1,1,1) */
- wins = 3 - inSum;
- if (wins < aScore || wins < bScore) { /* (1,1,1) is one of the closest two tetrahedral vertices. */
- c = (bScore < aScore ? bPoint : aPoint); /* Our other closest vertex is the closest out of a and b. */
-
- if ((c & 0x01) != 0) {
- xsv_ext0 = xsb + 2;
- xsv_ext1 = xsb + 1;
- dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_3D;
- dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb;
- dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x02) != 0) {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
- if ((c & 0x01) != 0) {
- ysv_ext1 += 1;
- dy_ext1 -= 1;
- } else {
- ysv_ext0 += 1;
- dy_ext0 -= 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x04) != 0) {
- zsv_ext0 = zsb + 1;
- zsv_ext1 = zsb + 2;
- dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 - 3 * SQUISH_CONSTANT_3D;
- } else {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_3D;
- }
- } else { /* (1,1,1) is not one of the closest two tetrahedral vertices. */
- c = (int8_t)(aPoint & bPoint); /* Our two extra vertices are determined by the closest two. */
-
- if ((c & 0x01) != 0) {
- xsv_ext0 = xsb + 1;
- xsv_ext1 = xsb + 2;
- dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb;
- dx_ext0 = dx0 - SQUISH_CONSTANT_3D;
- dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x02) != 0) {
- ysv_ext0 = ysb + 1;
- ysv_ext1 = ysb + 2;
- dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D;
- } else {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy0 - SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
- }
-
- if ((c & 0x04) != 0) {
- zsv_ext0 = zsb + 1;
- zsv_ext1 = zsb + 2;
- dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D;
- } else {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz0 - SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
- }
- }
-
- /* Contribution (1,1,0) */
- dx3 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dy3 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dz3 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate3(ctx, xsb + 1, ysb + 1, zsb + 0, dx3, dy3, dz3);
- }
-
- /* Contribution (1,0,1) */
- dx2 = dx3;
- dy2 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D;
- dz2 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate3(ctx, xsb + 1, ysb + 0, zsb + 1, dx2, dy2, dz2);
- }
-
- /* Contribution (0,1,1) */
- dx1 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D;
- dy1 = dy3;
- dz1 = dz2;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate3(ctx, xsb + 0, ysb + 1, zsb + 1, dx1, dy1, dz1);
- }
-
- /* Contribution (1,1,1) */
- dx0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
- dy0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
- dz0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
- attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0;
- if (attn0 > 0) {
- attn0 *= attn0;
- value += attn0 * attn0 * extrapolate3(ctx, xsb + 1, ysb + 1, zsb + 1, dx0, dy0, dz0);
- }
- } else { /* We're inside the octahedron (Rectified 3-Simplex) in between.
- Decide between point (0,0,1) and (1,1,0) as closest */
- p1 = xins + yins;
- if (p1 > 1) {
- aScore = p1 - 1;
- aPoint = 0x03;
- aIsFurtherSide = 1;
- } else {
- aScore = 1 - p1;
- aPoint = 0x04;
- aIsFurtherSide = 0;
- }
-
- /* Decide between point (0,1,0) and (1,0,1) as closest */
- p2 = xins + zins;
- if (p2 > 1) {
- bScore = p2 - 1;
- bPoint = 0x05;
- bIsFurtherSide = 1;
- } else {
- bScore = 1 - p2;
- bPoint = 0x02;
- bIsFurtherSide = 0;
- }
-
- /* The closest out of the two (1,0,0) and (0,1,1) will replace the furthest out of the two decided above, if closer. */
- p3 = yins + zins;
- if (p3 > 1) {
- score = p3 - 1;
- if (aScore <= bScore && aScore < score) {
- aScore = score;
- aPoint = 0x06;
- aIsFurtherSide = 1;
- } else if (aScore > bScore && bScore < score) {
- bScore = score;
- bPoint = 0x06;
- bIsFurtherSide = 1;
- }
- } else {
- score = 1 - p3;
- if (aScore <= bScore && aScore < score) {
- aScore = score;
- aPoint = 0x01;
- aIsFurtherSide = 0;
- } else if (aScore > bScore && bScore < score) {
- bScore = score;
- bPoint = 0x01;
- bIsFurtherSide = 0;
- }
- }
-
- /* Where each of the two closest points are determines how the extra two vertices are calculated. */
- if (aIsFurtherSide == bIsFurtherSide) {
- if (aIsFurtherSide) { /* Both closest points on (1,1,1) side */
-
- /* One of the two extra points is (1,1,1) */
- dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_3D;
- dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_3D;
- dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_3D;
- xsv_ext0 = xsb + 1;
- ysv_ext0 = ysb + 1;
- zsv_ext0 = zsb + 1;
-
- /* Other extra point is based on the shared axis. */
- c = (int8_t)(aPoint & bPoint);
- if ((c & 0x01) != 0) {
- dx_ext1 = dx0 - 2 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb + 2;
- ysv_ext1 = ysb;
- zsv_ext1 = zsb;
- } else if ((c & 0x02) != 0) {
- dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb;
- ysv_ext1 = ysb + 2;
- zsv_ext1 = zsb;
- } else {
- dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 - 2 * SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb;
- ysv_ext1 = ysb;
- zsv_ext1 = zsb + 2;
- }
- } else { /* Both closest points on (0,0,0) side */
-
- /* One of the two extra points is (0,0,0) */
- dx_ext0 = dx0;
- dy_ext0 = dy0;
- dz_ext0 = dz0;
- xsv_ext0 = xsb;
- ysv_ext0 = ysb;
- zsv_ext0 = zsb;
-
- /* Other extra point is based on the omitted axis. */
- c = (int8_t)(aPoint | bPoint);
- if ((c & 0x01) == 0) {
- dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb - 1;
- ysv_ext1 = ysb + 1;
- zsv_ext1 = zsb + 1;
- } else if ((c & 0x02) == 0) {
- dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 + 1 - SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb + 1;
- ysv_ext1 = ysb - 1;
- zsv_ext1 = zsb + 1;
- } else {
- dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 + 1 - SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb + 1;
- ysv_ext1 = ysb + 1;
- zsv_ext1 = zsb - 1;
- }
- }
- } else { /* One point on (0,0,0) side, one point on (1,1,1) side */
- if (aIsFurtherSide) {
- c1 = aPoint;
- c2 = bPoint;
- } else {
- c1 = bPoint;
- c2 = aPoint;
- }
-
- /* One contribution is a permutation of (1,1,-1) */
- if ((c1 & 0x01) == 0) {
- dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_3D;
- dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
- xsv_ext0 = xsb - 1;
- ysv_ext0 = ysb + 1;
- zsv_ext0 = zsb + 1;
- } else if ((c1 & 0x02) == 0) {
- dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy_ext0 = dy0 + 1 - SQUISH_CONSTANT_3D;
- dz_ext0 = dz0 - 1 - SQUISH_CONSTANT_3D;
- xsv_ext0 = xsb + 1;
- ysv_ext0 = ysb - 1;
- zsv_ext0 = zsb + 1;
- } else {
- dx_ext0 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy_ext0 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz_ext0 = dz0 + 1 - SQUISH_CONSTANT_3D;
- xsv_ext0 = xsb + 1;
- ysv_ext0 = ysb + 1;
- zsv_ext0 = zsb - 1;
- }
-
- /* One contribution is a permutation of (0,0,2) */
- dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_3D;
- dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_3D;
- dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_3D;
- xsv_ext1 = xsb;
- ysv_ext1 = ysb;
- zsv_ext1 = zsb;
- if ((c2 & 0x01) != 0) {
- dx_ext1 -= 2;
- xsv_ext1 += 2;
- } else if ((c2 & 0x02) != 0) {
- dy_ext1 -= 2;
- ysv_ext1 += 2;
- } else {
- dz_ext1 -= 2;
- zsv_ext1 += 2;
- }
- }
-
- /* Contribution (1,0,0) */
- dx1 = dx0 - 1 - SQUISH_CONSTANT_3D;
- dy1 = dy0 - 0 - SQUISH_CONSTANT_3D;
- dz1 = dz0 - 0 - SQUISH_CONSTANT_3D;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate3(ctx, xsb + 1, ysb + 0, zsb + 0, dx1, dy1, dz1);
- }
-
- /* Contribution (0,1,0) */
- dx2 = dx0 - 0 - SQUISH_CONSTANT_3D;
- dy2 = dy0 - 1 - SQUISH_CONSTANT_3D;
- dz2 = dz1;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate3(ctx, xsb + 0, ysb + 1, zsb + 0, dx2, dy2, dz2);
- }
-
- /* Contribution (0,0,1) */
- dx3 = dx2;
- dy3 = dy1;
- dz3 = dz0 - 1 - SQUISH_CONSTANT_3D;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate3(ctx, xsb + 0, ysb + 0, zsb + 1, dx3, dy3, dz3);
- }
-
- /* Contribution (1,1,0) */
- dx4 = dx0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dy4 = dy0 - 1 - 2 * SQUISH_CONSTANT_3D;
- dz4 = dz0 - 0 - 2 * SQUISH_CONSTANT_3D;
- attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4;
- if (attn4 > 0) {
- attn4 *= attn4;
- value += attn4 * attn4 * extrapolate3(ctx, xsb + 1, ysb + 1, zsb + 0, dx4, dy4, dz4);
- }
-
- /* Contribution (1,0,1) */
- dx5 = dx4;
- dy5 = dy0 - 0 - 2 * SQUISH_CONSTANT_3D;
- dz5 = dz0 - 1 - 2 * SQUISH_CONSTANT_3D;
- attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5;
- if (attn5 > 0) {
- attn5 *= attn5;
- value += attn5 * attn5 * extrapolate3(ctx, xsb + 1, ysb + 0, zsb + 1, dx5, dy5, dz5);
- }
-
- /* Contribution (0,1,1) */
- dx6 = dx0 - 0 - 2 * SQUISH_CONSTANT_3D;
- dy6 = dy4;
- dz6 = dz5;
- attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6;
- if (attn6 > 0) {
- attn6 *= attn6;
- value += attn6 * attn6 * extrapolate3(ctx, xsb + 0, ysb + 1, zsb + 1, dx6, dy6, dz6);
- }
- }
-
- /* First extra vertex */
- attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0;
- if (attn_ext0 > 0)
- {
- attn_ext0 *= attn_ext0;
- value += attn_ext0 * attn_ext0 * extrapolate3(ctx, xsv_ext0, ysv_ext0, zsv_ext0, dx_ext0, dy_ext0, dz_ext0);
- }
-
- /* Second extra vertex */
- attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1;
- if (attn_ext1 > 0)
- {
- attn_ext1 *= attn_ext1;
- value += attn_ext1 * attn_ext1 * extrapolate3(ctx, xsv_ext1, ysv_ext1, zsv_ext1, dx_ext1, dy_ext1, dz_ext1);
- }
-
- return value / NORM_CONSTANT_3D;
-}
-
-/*
- * 4D OpenSimplex (Simplectic) Noise.
- */
-double open_simplex_noise4(const struct osn_context *ctx, double x, double y, double z, double w)
-{
- double uins;
- double dx1, dy1, dz1, dw1;
- double dx2, dy2, dz2, dw2;
- double dx3, dy3, dz3, dw3;
- double dx4, dy4, dz4, dw4;
- double dx5, dy5, dz5, dw5;
- double dx6, dy6, dz6, dw6;
- double dx7, dy7, dz7, dw7;
- double dx8, dy8, dz8, dw8;
- double dx9, dy9, dz9, dw9;
- double dx10, dy10, dz10, dw10;
- double attn0, attn1, attn2, attn3, attn4;
- double attn5, attn6, attn7, attn8, attn9, attn10;
- double attn_ext0, attn_ext1, attn_ext2;
- int8_t c, c1, c2;
- int8_t aPoint, bPoint;
- double aScore, bScore;
- int aIsBiggerSide;
- int bIsBiggerSide;
- double p1, p2, p3, p4;
- double score;
-
- /* Place input coordinates on simplectic honeycomb. */
- double stretchOffset = (x + y + z + w) * STRETCH_CONSTANT_4D;
- double xs = x + stretchOffset;
- double ys = y + stretchOffset;
- double zs = z + stretchOffset;
- double ws = w + stretchOffset;
-
- /* Floor to get simplectic honeycomb coordinates of rhombo-hypercube super-cell origin. */
- int xsb = fastFloor(xs);
- int ysb = fastFloor(ys);
- int zsb = fastFloor(zs);
- int wsb = fastFloor(ws);
-
- /* Skew out to get actual coordinates of stretched rhombo-hypercube origin. We'll need these later. */
- double squishOffset = (xsb + ysb + zsb + wsb) * SQUISH_CONSTANT_4D;
- double xb = xsb + squishOffset;
- double yb = ysb + squishOffset;
- double zb = zsb + squishOffset;
- double wb = wsb + squishOffset;
-
- /* Compute simplectic honeycomb coordinates relative to rhombo-hypercube origin. */
- double xins = xs - xsb;
- double yins = ys - ysb;
- double zins = zs - zsb;
- double wins = ws - wsb;
-
- /* Sum those together to get a value that determines which region we're in. */
- double inSum = xins + yins + zins + wins;
-
- /* Positions relative to origin point. */
- double dx0 = x - xb;
- double dy0 = y - yb;
- double dz0 = z - zb;
- double dw0 = w - wb;
-
- /* We'll be defining these inside the next block and using them afterwards. */
- double dx_ext0, dy_ext0, dz_ext0, dw_ext0;
- double dx_ext1, dy_ext1, dz_ext1, dw_ext1;
- double dx_ext2, dy_ext2, dz_ext2, dw_ext2;
- int xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0;
- int xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1;
- int xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2;
-
- double value = 0;
- if (inSum <= 1) { /* We're inside the pentachoron (4-Simplex) at (0,0,0,0) */
-
- /* Determine which two of (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0) are closest. */
- aPoint = 0x01;
- aScore = xins;
- bPoint = 0x02;
- bScore = yins;
- if (aScore >= bScore && zins > bScore) {
- bScore = zins;
- bPoint = 0x04;
- } else if (aScore < bScore && zins > aScore) {
- aScore = zins;
- aPoint = 0x04;
- }
- if (aScore >= bScore && wins > bScore) {
- bScore = wins;
- bPoint = 0x08;
- } else if (aScore < bScore && wins > aScore) {
- aScore = wins;
- aPoint = 0x08;
- }
-
- /* Now we determine the three lattice points not part of the pentachoron that may contribute.
- This depends on the closest two pentachoron vertices, including (0,0,0,0) */
- uins = 1 - inSum;
- if (uins > aScore || uins > bScore) { /* (0,0,0,0) is one of the closest two pentachoron vertices. */
- c = (bScore > aScore ? bPoint : aPoint); /* Our other closest vertex is the closest out of a and b. */
- if ((c & 0x01) == 0) {
- xsv_ext0 = xsb - 1;
- xsv_ext1 = xsv_ext2 = xsb;
- dx_ext0 = dx0 + 1;
- dx_ext1 = dx_ext2 = dx0;
- } else {
- xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1;
- dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 1;
- }
-
- if ((c & 0x02) == 0) {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
- dy_ext0 = dy_ext1 = dy_ext2 = dy0;
- if ((c & 0x01) == 0x01) {
- ysv_ext0 -= 1;
- dy_ext0 += 1;
- } else {
- ysv_ext1 -= 1;
- dy_ext1 += 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
- dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1;
- }
-
- if ((c & 0x04) == 0) {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
- dz_ext0 = dz_ext1 = dz_ext2 = dz0;
- if ((c & 0x03) != 0) {
- if ((c & 0x03) == 0x03) {
- zsv_ext0 -= 1;
- dz_ext0 += 1;
- } else {
- zsv_ext1 -= 1;
- dz_ext1 += 1;
- }
- } else {
- zsv_ext2 -= 1;
- dz_ext2 += 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
- dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1;
- }
-
- if ((c & 0x08) == 0) {
- wsv_ext0 = wsv_ext1 = wsb;
- wsv_ext2 = wsb - 1;
- dw_ext0 = dw_ext1 = dw0;
- dw_ext2 = dw0 + 1;
- } else {
- wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1;
- dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 1;
- }
- } else { /* (0,0,0,0) is not one of the closest two pentachoron vertices. */
- c = (int8_t)(aPoint | bPoint); /* Our three extra vertices are determined by the closest two. */
-
- if ((c & 0x01) == 0) {
- xsv_ext0 = xsv_ext2 = xsb;
- xsv_ext1 = xsb - 1;
- dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 + 1 - SQUISH_CONSTANT_4D;
- dx_ext2 = dx0 - SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb + 1;
- dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx_ext2 = dx0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x02) == 0) {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
- dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy_ext2 = dy0 - SQUISH_CONSTANT_4D;
- if ((c & 0x01) == 0x01) {
- ysv_ext1 -= 1;
- dy_ext1 += 1;
- } else {
- ysv_ext2 -= 1;
- dy_ext2 += 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
- dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy_ext2 = dy0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x04) == 0) {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
- dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz_ext2 = dz0 - SQUISH_CONSTANT_4D;
- if ((c & 0x03) == 0x03) {
- zsv_ext1 -= 1;
- dz_ext1 += 1;
- } else {
- zsv_ext2 -= 1;
- dz_ext2 += 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
- dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz_ext2 = dz0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x08) == 0) {
- wsv_ext0 = wsv_ext1 = wsb;
- wsv_ext2 = wsb - 1;
- dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 + 1 - SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb + 1;
- dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw_ext2 = dw0 - 1 - SQUISH_CONSTANT_4D;
- }
- }
-
- /* Contribution (0,0,0,0) */
- attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0;
- if (attn0 > 0) {
- attn0 *= attn0;
- value += attn0 * attn0 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 0, wsb + 0, dx0, dy0, dz0, dw0);
- }
-
- /* Contribution (1,0,0,0) */
- dx1 = dx0 - 1 - SQUISH_CONSTANT_4D;
- dy1 = dy0 - 0 - SQUISH_CONSTANT_4D;
- dz1 = dz0 - 0 - SQUISH_CONSTANT_4D;
- dw1 = dw0 - 0 - SQUISH_CONSTANT_4D;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1);
- }
-
- /* Contribution (0,1,0,0) */
- dx2 = dx0 - 0 - SQUISH_CONSTANT_4D;
- dy2 = dy0 - 1 - SQUISH_CONSTANT_4D;
- dz2 = dz1;
- dw2 = dw1;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2);
- }
-
- /* Contribution (0,0,1,0) */
- dx3 = dx2;
- dy3 = dy1;
- dz3 = dz0 - 1 - SQUISH_CONSTANT_4D;
- dw3 = dw1;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3);
- }
-
- /* Contribution (0,0,0,1) */
- dx4 = dx2;
- dy4 = dy1;
- dz4 = dz1;
- dw4 = dw0 - 1 - SQUISH_CONSTANT_4D;
- attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
- if (attn4 > 0) {
- attn4 *= attn4;
- value += attn4 * attn4 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4);
- }
- } else if (inSum >= 3) { /* We're inside the pentachoron (4-Simplex) at (1,1,1,1)
- Determine which two of (1,1,1,0), (1,1,0,1), (1,0,1,1), (0,1,1,1) are closest. */
- aPoint = 0x0E;
- aScore = xins;
- bPoint = 0x0D;
- bScore = yins;
- if (aScore <= bScore && zins < bScore) {
- bScore = zins;
- bPoint = 0x0B;
- } else if (aScore > bScore && zins < aScore) {
- aScore = zins;
- aPoint = 0x0B;
- }
- if (aScore <= bScore && wins < bScore) {
- bScore = wins;
- bPoint = 0x07;
- } else if (aScore > bScore && wins < aScore) {
- aScore = wins;
- aPoint = 0x07;
- }
-
- /* Now we determine the three lattice points not part of the pentachoron that may contribute.
- This depends on the closest two pentachoron vertices, including (0,0,0,0) */
- uins = 4 - inSum;
- if (uins < aScore || uins < bScore) { /* (1,1,1,1) is one of the closest two pentachoron vertices. */
- c = (bScore < aScore ? bPoint : aPoint); /* Our other closest vertex is the closest out of a and b. */
-
- if ((c & 0x01) != 0) {
- xsv_ext0 = xsb + 2;
- xsv_ext1 = xsv_ext2 = xsb + 1;
- dx_ext0 = dx0 - 2 - 4 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb;
- dx_ext0 = dx_ext1 = dx_ext2 = dx0 - 4 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x02) != 0) {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
- dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
- if ((c & 0x01) != 0) {
- ysv_ext1 += 1;
- dy_ext1 -= 1;
- } else {
- ysv_ext0 += 1;
- dy_ext0 -= 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
- dy_ext0 = dy_ext1 = dy_ext2 = dy0 - 4 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x04) != 0) {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
- dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
- if ((c & 0x03) != 0x03) {
- if ((c & 0x03) == 0) {
- zsv_ext0 += 1;
- dz_ext0 -= 1;
- } else {
- zsv_ext1 += 1;
- dz_ext1 -= 1;
- }
- } else {
- zsv_ext2 += 1;
- dz_ext2 -= 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
- dz_ext0 = dz_ext1 = dz_ext2 = dz0 - 4 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x08) != 0) {
- wsv_ext0 = wsv_ext1 = wsb + 1;
- wsv_ext2 = wsb + 2;
- dw_ext0 = dw_ext1 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 2 - 4 * SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb;
- dw_ext0 = dw_ext1 = dw_ext2 = dw0 - 4 * SQUISH_CONSTANT_4D;
- }
- } else { /* (1,1,1,1) is not one of the closest two pentachoron vertices. */
- c = (int8_t)(aPoint & bPoint); /* Our three extra vertices are determined by the closest two. */
-
- if ((c & 0x01) != 0) {
- xsv_ext0 = xsv_ext2 = xsb + 1;
- xsv_ext1 = xsb + 2;
- dx_ext0 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
- dx_ext2 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsv_ext2 = xsb;
- dx_ext0 = dx0 - 2 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx_ext2 = dx0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x02) != 0) {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb + 1;
- dy_ext0 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy_ext2 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c & 0x01) != 0) {
- ysv_ext2 += 1;
- dy_ext2 -= 1;
- } else {
- ysv_ext1 += 1;
- dy_ext1 -= 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysv_ext2 = ysb;
- dy_ext0 = dy0 - 2 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy_ext2 = dy0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x04) != 0) {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb + 1;
- dz_ext0 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz_ext2 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c & 0x03) != 0) {
- zsv_ext2 += 1;
- dz_ext2 -= 1;
- } else {
- zsv_ext1 += 1;
- dz_ext1 -= 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsv_ext2 = zsb;
- dz_ext0 = dz0 - 2 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz_ext2 = dz0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x08) != 0) {
- wsv_ext0 = wsv_ext1 = wsb + 1;
- wsv_ext2 = wsb + 2;
- dw_ext0 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsv_ext2 = wsb;
- dw_ext0 = dw0 - 2 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw_ext2 = dw0 - 3 * SQUISH_CONSTANT_4D;
- }
- }
-
- /* Contribution (1,1,1,0) */
- dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw4 = dw0 - 3 * SQUISH_CONSTANT_4D;
- attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
- if (attn4 > 0) {
- attn4 *= attn4;
- value += attn4 * attn4 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4);
- }
-
- /* Contribution (1,1,0,1) */
- dx3 = dx4;
- dy3 = dy4;
- dz3 = dz0 - 3 * SQUISH_CONSTANT_4D;
- dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3);
- }
-
- /* Contribution (1,0,1,1) */
- dx2 = dx4;
- dy2 = dy0 - 3 * SQUISH_CONSTANT_4D;
- dz2 = dz4;
- dw2 = dw3;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2);
- }
-
- /* Contribution (0,1,1,1) */
- dx1 = dx0 - 3 * SQUISH_CONSTANT_4D;
- dz1 = dz4;
- dy1 = dy4;
- dw1 = dw3;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1);
- }
-
- /* Contribution (1,1,1,1) */
- dx0 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dy0 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dz0 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dw0 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
- attn0 = 2 - dx0 * dx0 - dy0 * dy0 - dz0 * dz0 - dw0 * dw0;
- if (attn0 > 0) {
- attn0 *= attn0;
- value += attn0 * attn0 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 1, wsb + 1, dx0, dy0, dz0, dw0);
- }
- } else if (inSum <= 2) { /* We're inside the first dispentachoron (Rectified 4-Simplex) */
- aIsBiggerSide = 1;
- bIsBiggerSide = 1;
-
- /* Decide between (1,1,0,0) and (0,0,1,1) */
- if (xins + yins > zins + wins) {
- aScore = xins + yins;
- aPoint = 0x03;
- } else {
- aScore = zins + wins;
- aPoint = 0x0C;
- }
-
- /* Decide between (1,0,1,0) and (0,1,0,1) */
- if (xins + zins > yins + wins) {
- bScore = xins + zins;
- bPoint = 0x05;
- } else {
- bScore = yins + wins;
- bPoint = 0x0A;
- }
-
- /* Closer between (1,0,0,1) and (0,1,1,0) will replace the further of a and b, if closer. */
- if (xins + wins > yins + zins) {
- score = xins + wins;
- if (aScore >= bScore && score > bScore) {
- bScore = score;
- bPoint = 0x09;
- } else if (aScore < bScore && score > aScore) {
- aScore = score;
- aPoint = 0x09;
- }
- } else {
- score = yins + zins;
- if (aScore >= bScore && score > bScore) {
- bScore = score;
- bPoint = 0x06;
- } else if (aScore < bScore && score > aScore) {
- aScore = score;
- aPoint = 0x06;
- }
- }
-
- /* Decide if (1,0,0,0) is closer. */
- p1 = 2 - inSum + xins;
- if (aScore >= bScore && p1 > bScore) {
- bScore = p1;
- bPoint = 0x01;
- bIsBiggerSide = 0;
- } else if (aScore < bScore && p1 > aScore) {
- aScore = p1;
- aPoint = 0x01;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (0,1,0,0) is closer. */
- p2 = 2 - inSum + yins;
- if (aScore >= bScore && p2 > bScore) {
- bScore = p2;
- bPoint = 0x02;
- bIsBiggerSide = 0;
- } else if (aScore < bScore && p2 > aScore) {
- aScore = p2;
- aPoint = 0x02;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (0,0,1,0) is closer. */
- p3 = 2 - inSum + zins;
- if (aScore >= bScore && p3 > bScore) {
- bScore = p3;
- bPoint = 0x04;
- bIsBiggerSide = 0;
- } else if (aScore < bScore && p3 > aScore) {
- aScore = p3;
- aPoint = 0x04;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (0,0,0,1) is closer. */
- p4 = 2 - inSum + wins;
- if (aScore >= bScore && p4 > bScore) {
- bScore = p4;
- bPoint = 0x08;
- bIsBiggerSide = 0;
- } else if (aScore < bScore && p4 > aScore) {
- aScore = p4;
- aPoint = 0x08;
- aIsBiggerSide = 0;
- }
-
- /* Where each of the two closest points are determines how the extra three vertices are calculated. */
- if (aIsBiggerSide == bIsBiggerSide) {
- if (aIsBiggerSide) { /* Both closest points on the bigger side */
- c1 = (int8_t)(aPoint | bPoint);
- c2 = (int8_t)(aPoint & bPoint);
- if ((c1 & 0x01) == 0) {
- xsv_ext0 = xsb;
- xsv_ext1 = xsb - 1;
- dx_ext0 = dx0 - 3 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 + 1 - 2 * SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb + 1;
- dx_ext0 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x02) == 0) {
- ysv_ext0 = ysb;
- ysv_ext1 = ysb - 1;
- dy_ext0 = dy0 - 3 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy0 + 1 - 2 * SQUISH_CONSTANT_4D;
- } else {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x04) == 0) {
- zsv_ext0 = zsb;
- zsv_ext1 = zsb - 1;
- dz_ext0 = dz0 - 3 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz0 + 1 - 2 * SQUISH_CONSTANT_4D;
- } else {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x08) == 0) {
- wsv_ext0 = wsb;
- wsv_ext1 = wsb - 1;
- dw_ext0 = dw0 - 3 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 + 1 - 2 * SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsb + 1;
- dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- }
-
- /* One combination is a permutation of (0,0,0,2) based on c2 */
- xsv_ext2 = xsb;
- ysv_ext2 = ysb;
- zsv_ext2 = zsb;
- wsv_ext2 = wsb;
- dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D;
- dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D;
- dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D;
- if ((c2 & 0x01) != 0) {
- xsv_ext2 += 2;
- dx_ext2 -= 2;
- } else if ((c2 & 0x02) != 0) {
- ysv_ext2 += 2;
- dy_ext2 -= 2;
- } else if ((c2 & 0x04) != 0) {
- zsv_ext2 += 2;
- dz_ext2 -= 2;
- } else {
- wsv_ext2 += 2;
- dw_ext2 -= 2;
- }
-
- } else { /* Both closest points on the smaller side */
- /* One of the two extra points is (0,0,0,0) */
- xsv_ext2 = xsb;
- ysv_ext2 = ysb;
- zsv_ext2 = zsb;
- wsv_ext2 = wsb;
- dx_ext2 = dx0;
- dy_ext2 = dy0;
- dz_ext2 = dz0;
- dw_ext2 = dw0;
-
- /* Other two points are based on the omitted axes. */
- c = (int8_t)(aPoint | bPoint);
-
- if ((c & 0x01) == 0) {
- xsv_ext0 = xsb - 1;
- xsv_ext1 = xsb;
- dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb + 1;
- dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x02) == 0) {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D;
- if ((c & 0x01) == 0x01)
- {
- ysv_ext0 -= 1;
- dy_ext0 += 1;
- } else {
- ysv_ext1 -= 1;
- dy_ext1 += 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x04) == 0) {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D;
- if ((c & 0x03) == 0x03)
- {
- zsv_ext0 -= 1;
- dz_ext0 += 1;
- } else {
- zsv_ext1 -= 1;
- dz_ext1 += 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x08) == 0)
- {
- wsv_ext0 = wsb;
- wsv_ext1 = wsb - 1;
- dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsb + 1;
- dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- }
- } else { /* One point on each "side" */
- if (aIsBiggerSide) {
- c1 = aPoint;
- c2 = bPoint;
- } else {
- c1 = bPoint;
- c2 = aPoint;
- }
-
- /* Two contributions are the bigger-sided point with each 0 replaced with -1. */
- if ((c1 & 0x01) == 0) {
- xsv_ext0 = xsb - 1;
- xsv_ext1 = xsb;
- dx_ext0 = dx0 + 1 - SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb + 1;
- dx_ext0 = dx_ext1 = dx0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x02) == 0) {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0 - SQUISH_CONSTANT_4D;
- if ((c1 & 0x01) == 0x01) {
- ysv_ext0 -= 1;
- dy_ext0 += 1;
- } else {
- ysv_ext1 -= 1;
- dy_ext1 += 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x04) == 0) {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz_ext1 = dz0 - SQUISH_CONSTANT_4D;
- if ((c1 & 0x03) == 0x03) {
- zsv_ext0 -= 1;
- dz_ext0 += 1;
- } else {
- zsv_ext1 -= 1;
- dz_ext1 += 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz_ext1 = dz0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x08) == 0) {
- wsv_ext0 = wsb;
- wsv_ext1 = wsb - 1;
- dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 + 1 - SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsb + 1;
- dw_ext0 = dw_ext1 = dw0 - 1 - SQUISH_CONSTANT_4D;
- }
-
- /* One contribution is a permutation of (0,0,0,2) based on the smaller-sided point */
- xsv_ext2 = xsb;
- ysv_ext2 = ysb;
- zsv_ext2 = zsb;
- wsv_ext2 = wsb;
- dx_ext2 = dx0 - 2 * SQUISH_CONSTANT_4D;
- dy_ext2 = dy0 - 2 * SQUISH_CONSTANT_4D;
- dz_ext2 = dz0 - 2 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 2 * SQUISH_CONSTANT_4D;
- if ((c2 & 0x01) != 0) {
- xsv_ext2 += 2;
- dx_ext2 -= 2;
- } else if ((c2 & 0x02) != 0) {
- ysv_ext2 += 2;
- dy_ext2 -= 2;
- } else if ((c2 & 0x04) != 0) {
- zsv_ext2 += 2;
- dz_ext2 -= 2;
- } else {
- wsv_ext2 += 2;
- dw_ext2 -= 2;
- }
- }
-
- /* Contribution (1,0,0,0) */
- dx1 = dx0 - 1 - SQUISH_CONSTANT_4D;
- dy1 = dy0 - 0 - SQUISH_CONSTANT_4D;
- dz1 = dz0 - 0 - SQUISH_CONSTANT_4D;
- dw1 = dw0 - 0 - SQUISH_CONSTANT_4D;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 0, wsb + 0, dx1, dy1, dz1, dw1);
- }
-
- /* Contribution (0,1,0,0) */
- dx2 = dx0 - 0 - SQUISH_CONSTANT_4D;
- dy2 = dy0 - 1 - SQUISH_CONSTANT_4D;
- dz2 = dz1;
- dw2 = dw1;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 0, wsb + 0, dx2, dy2, dz2, dw2);
- }
-
- /* Contribution (0,0,1,0) */
- dx3 = dx2;
- dy3 = dy1;
- dz3 = dz0 - 1 - SQUISH_CONSTANT_4D;
- dw3 = dw1;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 1, wsb + 0, dx3, dy3, dz3, dw3);
- }
-
- /* Contribution (0,0,0,1) */
- dx4 = dx2;
- dy4 = dy1;
- dz4 = dz1;
- dw4 = dw0 - 1 - SQUISH_CONSTANT_4D;
- attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
- if (attn4 > 0) {
- attn4 *= attn4;
- value += attn4 * attn4 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 0, wsb + 1, dx4, dy4, dz4, dw4);
- }
-
- /* Contribution (1,1,0,0) */
- dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5;
- if (attn5 > 0) {
- attn5 *= attn5;
- value += attn5 * attn5 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5);
- }
-
- /* Contribution (1,0,1,0) */
- dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6;
- if (attn6 > 0) {
- attn6 *= attn6;
- value += attn6 * attn6 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6);
- }
-
- /* Contribution (1,0,0,1) */
- dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7;
- if (attn7 > 0) {
- attn7 *= attn7;
- value += attn7 * attn7 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7);
- }
-
- /* Contribution (0,1,1,0) */
- dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8;
- if (attn8 > 0) {
- attn8 *= attn8;
- value += attn8 * attn8 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8);
- }
-
- /* Contribution (0,1,0,1) */
- dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9;
- if (attn9 > 0) {
- attn9 *= attn9;
- value += attn9 * attn9 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9);
- }
-
- /* Contribution (0,0,1,1) */
- dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10;
- if (attn10 > 0) {
- attn10 *= attn10;
- value += attn10 * attn10 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10);
- }
- } else { /* We're inside the second dispentachoron (Rectified 4-Simplex) */
- aIsBiggerSide = 1;
- bIsBiggerSide = 1;
-
- /* Decide between (0,0,1,1) and (1,1,0,0) */
- if (xins + yins < zins + wins) {
- aScore = xins + yins;
- aPoint = 0x0C;
- } else {
- aScore = zins + wins;
- aPoint = 0x03;
- }
-
- /* Decide between (0,1,0,1) and (1,0,1,0) */
- if (xins + zins < yins + wins) {
- bScore = xins + zins;
- bPoint = 0x0A;
- } else {
- bScore = yins + wins;
- bPoint = 0x05;
- }
-
- /* Closer between (0,1,1,0) and (1,0,0,1) will replace the further of a and b, if closer. */
- if (xins + wins < yins + zins) {
- score = xins + wins;
- if (aScore <= bScore && score < bScore) {
- bScore = score;
- bPoint = 0x06;
- } else if (aScore > bScore && score < aScore) {
- aScore = score;
- aPoint = 0x06;
- }
- } else {
- score = yins + zins;
- if (aScore <= bScore && score < bScore) {
- bScore = score;
- bPoint = 0x09;
- } else if (aScore > bScore && score < aScore) {
- aScore = score;
- aPoint = 0x09;
- }
- }
-
- /* Decide if (0,1,1,1) is closer. */
- p1 = 3 - inSum + xins;
- if (aScore <= bScore && p1 < bScore) {
- bScore = p1;
- bPoint = 0x0E;
- bIsBiggerSide = 0;
- } else if (aScore > bScore && p1 < aScore) {
- aScore = p1;
- aPoint = 0x0E;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (1,0,1,1) is closer. */
- p2 = 3 - inSum + yins;
- if (aScore <= bScore && p2 < bScore) {
- bScore = p2;
- bPoint = 0x0D;
- bIsBiggerSide = 0;
- } else if (aScore > bScore && p2 < aScore) {
- aScore = p2;
- aPoint = 0x0D;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (1,1,0,1) is closer. */
- p3 = 3 - inSum + zins;
- if (aScore <= bScore && p3 < bScore) {
- bScore = p3;
- bPoint = 0x0B;
- bIsBiggerSide = 0;
- } else if (aScore > bScore && p3 < aScore) {
- aScore = p3;
- aPoint = 0x0B;
- aIsBiggerSide = 0;
- }
-
- /* Decide if (1,1,1,0) is closer. */
- p4 = 3 - inSum + wins;
- if (aScore <= bScore && p4 < bScore) {
- bScore = p4;
- bPoint = 0x07;
- bIsBiggerSide = 0;
- } else if (aScore > bScore && p4 < aScore) {
- aScore = p4;
- aPoint = 0x07;
- aIsBiggerSide = 0;
- }
-
- /* Where each of the two closest points are determines how the extra three vertices are calculated. */
- if (aIsBiggerSide == bIsBiggerSide) {
- if (aIsBiggerSide) { /* Both closest points on the bigger side */
- c1 = (int8_t)(aPoint & bPoint);
- c2 = (int8_t)(aPoint | bPoint);
-
- /* Two contributions are permutations of (0,0,0,1) and (0,0,0,2) based on c1 */
- xsv_ext0 = xsv_ext1 = xsb;
- ysv_ext0 = ysv_ext1 = ysb;
- zsv_ext0 = zsv_ext1 = zsb;
- wsv_ext0 = wsv_ext1 = wsb;
- dx_ext0 = dx0 - SQUISH_CONSTANT_4D;
- dy_ext0 = dy0 - SQUISH_CONSTANT_4D;
- dz_ext0 = dz0 - SQUISH_CONSTANT_4D;
- dw_ext0 = dw0 - SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - 2 * SQUISH_CONSTANT_4D;
- dy_ext1 = dy0 - 2 * SQUISH_CONSTANT_4D;
- dz_ext1 = dz0 - 2 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - 2 * SQUISH_CONSTANT_4D;
- if ((c1 & 0x01) != 0) {
- xsv_ext0 += 1;
- dx_ext0 -= 1;
- xsv_ext1 += 2;
- dx_ext1 -= 2;
- } else if ((c1 & 0x02) != 0) {
- ysv_ext0 += 1;
- dy_ext0 -= 1;
- ysv_ext1 += 2;
- dy_ext1 -= 2;
- } else if ((c1 & 0x04) != 0) {
- zsv_ext0 += 1;
- dz_ext0 -= 1;
- zsv_ext1 += 2;
- dz_ext1 -= 2;
- } else {
- wsv_ext0 += 1;
- dw_ext0 -= 1;
- wsv_ext1 += 2;
- dw_ext1 -= 2;
- }
-
- /* One contribution is a permutation of (1,1,1,-1) based on c2 */
- xsv_ext2 = xsb + 1;
- ysv_ext2 = ysb + 1;
- zsv_ext2 = zsb + 1;
- wsv_ext2 = wsb + 1;
- dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- if ((c2 & 0x01) == 0) {
- xsv_ext2 -= 2;
- dx_ext2 += 2;
- } else if ((c2 & 0x02) == 0) {
- ysv_ext2 -= 2;
- dy_ext2 += 2;
- } else if ((c2 & 0x04) == 0) {
- zsv_ext2 -= 2;
- dz_ext2 += 2;
- } else {
- wsv_ext2 -= 2;
- dw_ext2 += 2;
- }
- } else { /* Both closest points on the smaller side */
- /* One of the two extra points is (1,1,1,1) */
- xsv_ext2 = xsb + 1;
- ysv_ext2 = ysb + 1;
- zsv_ext2 = zsb + 1;
- wsv_ext2 = wsb + 1;
- dx_ext2 = dx0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dy_ext2 = dy0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dz_ext2 = dz0 - 1 - 4 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 1 - 4 * SQUISH_CONSTANT_4D;
-
- /* Other two points are based on the shared axes. */
- c = (int8_t)(aPoint & bPoint);
-
- if ((c & 0x01) != 0) {
- xsv_ext0 = xsb + 2;
- xsv_ext1 = xsb + 1;
- dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb;
- dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x02) != 0) {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c & 0x01) == 0)
- {
- ysv_ext0 += 1;
- dy_ext0 -= 1;
- } else {
- ysv_ext1 += 1;
- dy_ext1 -= 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x04) != 0) {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c & 0x03) == 0)
- {
- zsv_ext0 += 1;
- dz_ext0 -= 1;
- } else {
- zsv_ext1 += 1;
- dz_ext1 -= 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c & 0x08) != 0)
- {
- wsv_ext0 = wsb + 1;
- wsv_ext1 = wsb + 2;
- dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsb;
- dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D;
- }
- }
- } else { /* One point on each "side" */
- if (aIsBiggerSide) {
- c1 = aPoint;
- c2 = bPoint;
- } else {
- c1 = bPoint;
- c2 = aPoint;
- }
-
- /* Two contributions are the bigger-sided point with each 1 replaced with 2. */
- if ((c1 & 0x01) != 0) {
- xsv_ext0 = xsb + 2;
- xsv_ext1 = xsb + 1;
- dx_ext0 = dx0 - 2 - 3 * SQUISH_CONSTANT_4D;
- dx_ext1 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- } else {
- xsv_ext0 = xsv_ext1 = xsb;
- dx_ext0 = dx_ext1 = dx0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x02) != 0) {
- ysv_ext0 = ysv_ext1 = ysb + 1;
- dy_ext0 = dy_ext1 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c1 & 0x01) == 0) {
- ysv_ext0 += 1;
- dy_ext0 -= 1;
- } else {
- ysv_ext1 += 1;
- dy_ext1 -= 1;
- }
- } else {
- ysv_ext0 = ysv_ext1 = ysb;
- dy_ext0 = dy_ext1 = dy0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x04) != 0) {
- zsv_ext0 = zsv_ext1 = zsb + 1;
- dz_ext0 = dz_ext1 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- if ((c1 & 0x03) == 0) {
- zsv_ext0 += 1;
- dz_ext0 -= 1;
- } else {
- zsv_ext1 += 1;
- dz_ext1 -= 1;
- }
- } else {
- zsv_ext0 = zsv_ext1 = zsb;
- dz_ext0 = dz_ext1 = dz0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- if ((c1 & 0x08) != 0) {
- wsv_ext0 = wsb + 1;
- wsv_ext1 = wsb + 2;
- dw_ext0 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw_ext1 = dw0 - 2 - 3 * SQUISH_CONSTANT_4D;
- } else {
- wsv_ext0 = wsv_ext1 = wsb;
- dw_ext0 = dw_ext1 = dw0 - 3 * SQUISH_CONSTANT_4D;
- }
-
- /* One contribution is a permutation of (1,1,1,-1) based on the smaller-sided point */
- xsv_ext2 = xsb + 1;
- ysv_ext2 = ysb + 1;
- zsv_ext2 = zsb + 1;
- wsv_ext2 = wsb + 1;
- dx_ext2 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy_ext2 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz_ext2 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw_ext2 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- if ((c2 & 0x01) == 0) {
- xsv_ext2 -= 2;
- dx_ext2 += 2;
- } else if ((c2 & 0x02) == 0) {
- ysv_ext2 -= 2;
- dy_ext2 += 2;
- } else if ((c2 & 0x04) == 0) {
- zsv_ext2 -= 2;
- dz_ext2 += 2;
- } else {
- wsv_ext2 -= 2;
- dw_ext2 += 2;
- }
- }
-
- /* Contribution (1,1,1,0) */
- dx4 = dx0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dy4 = dy0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dz4 = dz0 - 1 - 3 * SQUISH_CONSTANT_4D;
- dw4 = dw0 - 3 * SQUISH_CONSTANT_4D;
- attn4 = 2 - dx4 * dx4 - dy4 * dy4 - dz4 * dz4 - dw4 * dw4;
- if (attn4 > 0) {
- attn4 *= attn4;
- value += attn4 * attn4 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 1, wsb + 0, dx4, dy4, dz4, dw4);
- }
-
- /* Contribution (1,1,0,1) */
- dx3 = dx4;
- dy3 = dy4;
- dz3 = dz0 - 3 * SQUISH_CONSTANT_4D;
- dw3 = dw0 - 1 - 3 * SQUISH_CONSTANT_4D;
- attn3 = 2 - dx3 * dx3 - dy3 * dy3 - dz3 * dz3 - dw3 * dw3;
- if (attn3 > 0) {
- attn3 *= attn3;
- value += attn3 * attn3 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 0, wsb + 1, dx3, dy3, dz3, dw3);
- }
-
- /* Contribution (1,0,1,1) */
- dx2 = dx4;
- dy2 = dy0 - 3 * SQUISH_CONSTANT_4D;
- dz2 = dz4;
- dw2 = dw3;
- attn2 = 2 - dx2 * dx2 - dy2 * dy2 - dz2 * dz2 - dw2 * dw2;
- if (attn2 > 0) {
- attn2 *= attn2;
- value += attn2 * attn2 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 1, wsb + 1, dx2, dy2, dz2, dw2);
- }
-
- /* Contribution (0,1,1,1) */
- dx1 = dx0 - 3 * SQUISH_CONSTANT_4D;
- dz1 = dz4;
- dy1 = dy4;
- dw1 = dw3;
- attn1 = 2 - dx1 * dx1 - dy1 * dy1 - dz1 * dz1 - dw1 * dw1;
- if (attn1 > 0) {
- attn1 *= attn1;
- value += attn1 * attn1 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 1, wsb + 1, dx1, dy1, dz1, dw1);
- }
-
- /* Contribution (1,1,0,0) */
- dx5 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy5 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz5 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw5 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn5 = 2 - dx5 * dx5 - dy5 * dy5 - dz5 * dz5 - dw5 * dw5;
- if (attn5 > 0) {
- attn5 *= attn5;
- value += attn5 * attn5 * extrapolate4(ctx, xsb + 1, ysb + 1, zsb + 0, wsb + 0, dx5, dy5, dz5, dw5);
- }
-
- /* Contribution (1,0,1,0) */
- dx6 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy6 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz6 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw6 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn6 = 2 - dx6 * dx6 - dy6 * dy6 - dz6 * dz6 - dw6 * dw6;
- if (attn6 > 0) {
- attn6 *= attn6;
- value += attn6 * attn6 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 1, wsb + 0, dx6, dy6, dz6, dw6);
- }
-
- /* Contribution (1,0,0,1) */
- dx7 = dx0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dy7 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz7 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw7 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn7 = 2 - dx7 * dx7 - dy7 * dy7 - dz7 * dz7 - dw7 * dw7;
- if (attn7 > 0) {
- attn7 *= attn7;
- value += attn7 * attn7 * extrapolate4(ctx, xsb + 1, ysb + 0, zsb + 0, wsb + 1, dx7, dy7, dz7, dw7);
- }
-
- /* Contribution (0,1,1,0) */
- dx8 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy8 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz8 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw8 = dw0 - 0 - 2 * SQUISH_CONSTANT_4D;
- attn8 = 2 - dx8 * dx8 - dy8 * dy8 - dz8 * dz8 - dw8 * dw8;
- if (attn8 > 0) {
- attn8 *= attn8;
- value += attn8 * attn8 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 1, wsb + 0, dx8, dy8, dz8, dw8);
- }
-
- /* Contribution (0,1,0,1) */
- dx9 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy9 = dy0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dz9 = dz0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dw9 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn9 = 2 - dx9 * dx9 - dy9 * dy9 - dz9 * dz9 - dw9 * dw9;
- if (attn9 > 0) {
- attn9 *= attn9;
- value += attn9 * attn9 * extrapolate4(ctx, xsb + 0, ysb + 1, zsb + 0, wsb + 1, dx9, dy9, dz9, dw9);
- }
-
- /* Contribution (0,0,1,1) */
- dx10 = dx0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dy10 = dy0 - 0 - 2 * SQUISH_CONSTANT_4D;
- dz10 = dz0 - 1 - 2 * SQUISH_CONSTANT_4D;
- dw10 = dw0 - 1 - 2 * SQUISH_CONSTANT_4D;
- attn10 = 2 - dx10 * dx10 - dy10 * dy10 - dz10 * dz10 - dw10 * dw10;
- if (attn10 > 0) {
- attn10 *= attn10;
- value += attn10 * attn10 * extrapolate4(ctx, xsb + 0, ysb + 0, zsb + 1, wsb + 1, dx10, dy10, dz10, dw10);
- }
- }
-
- /* First extra vertex */
- attn_ext0 = 2 - dx_ext0 * dx_ext0 - dy_ext0 * dy_ext0 - dz_ext0 * dz_ext0 - dw_ext0 * dw_ext0;
- if (attn_ext0 > 0)
- {
- attn_ext0 *= attn_ext0;
- value += attn_ext0 * attn_ext0 * extrapolate4(ctx, xsv_ext0, ysv_ext0, zsv_ext0, wsv_ext0, dx_ext0, dy_ext0, dz_ext0, dw_ext0);
- }
-
- /* Second extra vertex */
- attn_ext1 = 2 - dx_ext1 * dx_ext1 - dy_ext1 * dy_ext1 - dz_ext1 * dz_ext1 - dw_ext1 * dw_ext1;
- if (attn_ext1 > 0)
- {
- attn_ext1 *= attn_ext1;
- value += attn_ext1 * attn_ext1 * extrapolate4(ctx, xsv_ext1, ysv_ext1, zsv_ext1, wsv_ext1, dx_ext1, dy_ext1, dz_ext1, dw_ext1);
- }
-
- /* Third extra vertex */
- attn_ext2 = 2 - dx_ext2 * dx_ext2 - dy_ext2 * dy_ext2 - dz_ext2 * dz_ext2 - dw_ext2 * dw_ext2;
- if (attn_ext2 > 0)
- {
- attn_ext2 *= attn_ext2;
- value += attn_ext2 * attn_ext2 * extrapolate4(ctx, xsv_ext2, ysv_ext2, zsv_ext2, wsv_ext2, dx_ext2, dy_ext2, dz_ext2, dw_ext2);
- }
-
- return value / NORM_CONSTANT_4D;
-}
-
diff --git a/thirdparty/misc/open-simplex-noise.h b/thirdparty/misc/open-simplex-noise.h
deleted file mode 100644
index fd9248c3a1..0000000000
--- a/thirdparty/misc/open-simplex-noise.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef OPEN_SIMPLEX_NOISE_H__
-#define OPEN_SIMPLEX_NOISE_H__
-
-/*
- * OpenSimplex (Simplectic) Noise in C.
- * Ported to C from Kurt Spencer's java implementation by Stephen M. Cameron
- *
- * v1.1 (October 6, 2014)
- * - Ported to C
- *
- * v1.1 (October 5, 2014)
- * - Added 2D and 4D implementations.
- * - Proper gradient sets for all dimensions, from a
- * dimensionally-generalizable scheme with an actual
- * rhyme and reason behind it.
- * - Removed default permutation array in favor of
- * default seed.
- * - Changed seed-based constructor to be independent
- * of any particular randomization library, so results
- * will be the same when ported to other languages.
- */
-
-#if ((__GNUC_STDC_INLINE__) || (__STDC_VERSION__ >= 199901L))
- #include <stdint.h>
- #define INLINE inline
-#elif (defined (_MSC_VER) || defined (__GNUC_GNU_INLINE__))
- #include <stdint.h>
- #define INLINE __inline
-#else
- /* ANSI C doesn't have inline or stdint.h. */
- #define INLINE
-#endif
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-// -- GODOT start --
-// Modified to work without allocating memory, also removed some unused function.
-
-struct osn_context {
- int16_t perm[256];
- int16_t permGradIndex3D[256];
-};
-
-int open_simplex_noise(int64_t seed, struct osn_context *ctx);
-//int open_simplex_noise_init_perm(struct osn_context *ctx, int16_t p[], int nelements);
-// -- GODOT end --
-void open_simplex_noise_free(struct osn_context *ctx);
-double open_simplex_noise2(const struct osn_context *ctx, double x, double y);
-double open_simplex_noise3(const struct osn_context *ctx, double x, double y, double z);
-double open_simplex_noise4(const struct osn_context *ctx, double x, double y, double z, double w);
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
diff --git a/thirdparty/misc/patches/polypartition-godot-types.patch b/thirdparty/misc/patches/polypartition-godot-types.patch
index 61737f9fd2..5d8aba3437 100644
--- a/thirdparty/misc/patches/polypartition-godot-types.patch
+++ b/thirdparty/misc/patches/polypartition-godot-types.patch
@@ -101,7 +101,7 @@ index 3a8a6efa83..8c5409bf24 100644
pointvisible = true;
- for (iter2 = polys.begin(); iter2 != polys.end(); iter2++) {
- if (iter2->IsHole()) {
-+ for (iter2 = polys.front(); iter2; iter2->next()) {
++ for (iter2 = polys.front(); iter2; iter2 = iter2->next()) {
+ if (iter2->get().IsHole()) {
continue;
}
diff --git a/thirdparty/misc/polypartition.cpp b/thirdparty/misc/polypartition.cpp
index 8c5409bf24..a725125ed0 100644
--- a/thirdparty/misc/polypartition.cpp
+++ b/thirdparty/misc/polypartition.cpp
@@ -262,7 +262,7 @@ int TPPLPartition::RemoveHoles(TPPLPolyList *inpolys, TPPLPolyList *outpolys) {
}
}
pointvisible = true;
- for (iter2 = polys.front(); iter2; iter2->next()) {
+ for (iter2 = polys.front(); iter2; iter2 = iter2->next()) {
if (iter2->get().IsHole()) {
continue;
}
@@ -1357,12 +1357,12 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
// Note that while set doesn't actually have to be implemented as
// a tree, complexity requirements for operations are the same as
// for the balanced binary search tree.
- Set<ScanLineEdge> edgeTree;
+ RBSet<ScanLineEdge> edgeTree;
// Store iterators to the edge tree elements.
// This makes deleting existing edges much faster.
- Set<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter;
- edgeTreeIterators = new Set<ScanLineEdge>::Element *[maxnumvertices];
- //Pair<Set<ScanLineEdge>::iterator, bool> edgeTreeRet;
+ RBSet<ScanLineEdge>::Element **edgeTreeIterators, *edgeIter;
+ edgeTreeIterators = new RBSet<ScanLineEdge>::Element *[maxnumvertices];
+ //Pair<RBSet<ScanLineEdge>::iterator, bool> edgeTreeRet;
for (i = 0; i < numvertices; i++) {
edgeTreeIterators[i] = nullptr;
}
@@ -1569,8 +1569,8 @@ int TPPLPartition::MonotonePartition(TPPLPolyList *inpolys, TPPLPolyList *monoto
// Adds a diagonal to the doubly-connected list of vertices.
void TPPLPartition::AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
- TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
- Set<ScanLineEdge> *edgeTree, long *helpers) {
+ TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators,
+ RBSet<ScanLineEdge> *edgeTree, long *helpers) {
long newindex1, newindex2;
newindex1 = *numvertices;
diff --git a/thirdparty/misc/polypartition.h b/thirdparty/misc/polypartition.h
index b2d905a3ef..fae7909079 100644
--- a/thirdparty/misc/polypartition.h
+++ b/thirdparty/misc/polypartition.h
@@ -26,7 +26,7 @@
#include "core/math/vector2.h"
#include "core/templates/list.h"
-#include "core/templates/set.h"
+#include "core/templates/rb_set.h"
typedef double tppl_float;
@@ -224,8 +224,8 @@ public:
// Helper functions for MonotonePartition.
bool Below(TPPLPoint &p1, TPPLPoint &p2);
void AddDiagonal(MonotoneVertex *vertices, long *numvertices, long index1, long index2,
- TPPLVertexType *vertextypes, Set<ScanLineEdge>::Element **edgeTreeIterators,
- Set<ScanLineEdge> *edgeTree, long *helpers);
+ TPPLVertexType *vertextypes, RBSet<ScanLineEdge>::Element **edgeTreeIterators,
+ RBSet<ScanLineEdge> *edgeTree, long *helpers);
// Triangulates a monotone polygon, used in Triangulate_MONO.
int TriangulateMonotone(TPPLPoly *inPoly, TPPLPolyList *triangles);
diff --git a/thirdparty/misc/stb_rect_pack.h b/thirdparty/misc/stb_rect_pack.h
index 5c848de0e7..6a633ce666 100644
--- a/thirdparty/misc/stb_rect_pack.h
+++ b/thirdparty/misc/stb_rect_pack.h
@@ -1,9 +1,15 @@
-// stb_rect_pack.h - v1.00 - public domain - rectangle packing
+// stb_rect_pack.h - v1.01 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
// Does not do rotation.
//
+// Before #including,
+//
+// #define STB_RECT_PACK_IMPLEMENTATION
+//
+// in the file that you want to have the implementation.
+//
// Not necessarily the awesomest packing method, but better than
// the totally naive one in stb_truetype (which is primarily what
// this is meant to replace).
@@ -35,6 +41,7 @@
//
// Version history:
//
+// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
// 0.99 (2019-02-07) warning fixes
// 0.11 (2017-03-03) return packing success/fail result
@@ -75,11 +82,10 @@ typedef struct stbrp_context stbrp_context;
typedef struct stbrp_node stbrp_node;
typedef struct stbrp_rect stbrp_rect;
-#ifdef STBRP_LARGE_RECTS
typedef int stbrp_coord;
-#else
-typedef unsigned short stbrp_coord;
-#endif
+
+#define STBRP__MAXVAL 0x7fffffff
+// Mostly for internal use, but this is the maximum supported coordinate value.
STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects);
// Assign packed locations to rectangles. The rectangles are of type
@@ -209,8 +215,10 @@ struct stbrp_context
#ifdef _MSC_VER
#define STBRP__NOTUSED(v) (void)(v)
+#define STBRP__CDECL __cdecl
#else
#define STBRP__NOTUSED(v) (void)sizeof(v)
+#define STBRP__CDECL
#endif
enum
@@ -253,9 +261,6 @@ STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_ou
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
{
int i;
-#ifndef STBRP_LARGE_RECTS
- STBRP_ASSERT(width <= 0xffff && height <= 0xffff);
-#endif
for (i=0; i < num_nodes-1; ++i)
nodes[i].next = &nodes[i+1];
@@ -274,11 +279,7 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
context->extra[0].y = 0;
context->extra[0].next = &context->extra[1];
context->extra[1].x = (stbrp_coord) width;
-#ifdef STBRP_LARGE_RECTS
context->extra[1].y = (1<<30);
-#else
- context->extra[1].y = 65535;
-#endif
context->extra[1].next = NULL;
}
@@ -520,7 +521,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
return res;
}
-static int rect_height_compare(const void *a, const void *b)
+static int STBRP__CDECL rect_height_compare(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
@@ -531,19 +532,13 @@ static int rect_height_compare(const void *a, const void *b)
return (p->w > q->w) ? -1 : (p->w < q->w);
}
-static int rect_original_order(const void *a, const void *b)
+static int STBRP__CDECL rect_original_order(const void *a, const void *b)
{
const stbrp_rect *p = (const stbrp_rect *) a;
const stbrp_rect *q = (const stbrp_rect *) b;
return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
}
-#ifdef STBRP_LARGE_RECTS
-#define STBRP__MAXVAL 0xffffffff
-#else
-#define STBRP__MAXVAL 0xffff
-#endif
-
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
{
int i, all_rects_packed = 1;
diff --git a/thirdparty/noise/FastNoise-LICENSE b/thirdparty/noise/FastNoise-LICENSE
new file mode 100644
index 0000000000..dd6df2c160
--- /dev/null
+++ b/thirdparty/noise/FastNoise-LICENSE
@@ -0,0 +1,22 @@
+MIT License
+
+Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
+Copyright(c) 2020 Contributors
+
+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. \ No newline at end of file
diff --git a/thirdparty/noise/FastNoiseLite.h b/thirdparty/noise/FastNoiseLite.h
new file mode 100644
index 0000000000..a213f0888e
--- /dev/null
+++ b/thirdparty/noise/FastNoiseLite.h
@@ -0,0 +1,2598 @@
+// MIT License
+//
+// Copyright(c) 2020 Jordan Peck (jordan.me2@gmail.com)
+// Copyright(c) 2020 Contributors
+//
+// 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.
+//
+// .'',;:cldxkO00KKXXNNWWWNNXKOkxdollcc::::::;:::ccllloooolllllllllooollc:,'... ...........',;cldxkO000Okxdlc::;;;,,;;;::cclllllll
+// ..',;:ldxO0KXXNNNNNNNNXXK0kxdolcc::::::;;;,,,,,,;;;;;;;;;;:::cclllllc:;'.... ...........',;:ldxO0KXXXK0Okxdolc::;;;;::cllodddddo
+// ...',:loxO0KXNNNNNXXKK0Okxdolc::;::::::::;;;,,'''''.....''',;:clllllc:;,'............''''''''',;:loxO0KXNNNNNXK0Okxdollccccllodxxxxxxd
+// ....';:ldkO0KXXXKK00Okxdolcc:;;;;;::cclllcc:;;,''..... ....',;clooddolcc:;;;;,,;;;;;::::;;;;;;:cloxk0KXNWWWWWWNXKK0Okxddoooddxxkkkkkxx
+// .....';:ldxkOOOOOkxxdolcc:;;;,,,;;:cllooooolcc:;'... ..,:codxkkkxddooollloooooooollcc:::::clodkO0KXNWWWWWWNNXK00Okxxxxxxxxkkkkxxx
+// . ....';:cloddddo___________,,,,;;:clooddddoolc:,... ..,:ldx__00OOOkkk___kkkkkkxxdollc::::cclodkO0KXXNNNNNNXXK0OOkxxxxxxxxxxxxddd
+// .......',;:cccc:| |,,,;;:cclooddddoll:;'.. ..';cox| \KKK000| |KK00OOkxdocc___;::clldxxkO0KKKKK00Okkxdddddddddddddddoo
+// .......'',,,,,''| ________|',,;;::cclloooooolc:;'......___:ldk| \KK000| |XKKK0Okxolc| |;;::cclodxxkkkkxxdoolllcclllooodddooooo
+// ''......''''....| | ....'',,,,;;;::cclloooollc:;,''.'| |oxk| \OOO0| |KKK00Oxdoll|___|;;;;;::ccllllllcc::;;,,;;;:cclloooooooo
+// ;;,''.......... | |_____',,;;;____:___cllo________.___| |___| \xkk| |KK_______ool___:::;________;;;_______...'',;;:ccclllloo
+// c:;,''......... | |:::/ ' |lo/ | | \dx| |0/ \d| |cc/ |'/ \......',,;;:ccllo
+// ol:;,'..........| _____|ll/ __ |o/ ______|____ ___| | \o| |/ ___ \| |o/ ______|/ ___ \ .......'',;:clo
+// dlc;,...........| |::clooo| / | |x\___ \KXKKK0| |dol| |\ \| | | | | |d\___ \..| | / / ....',:cl
+// xoc;'... .....'| |llodddd| \__| |_____\ \KKK0O| |lc:| |'\ | |___| | |_____\ \.| |_/___/... ...',;:c
+// dlc;'... ....',;| |oddddddo\ | |Okkx| |::;| |..\ |\ /| | | \ |... ....',;:c
+// ol:,'.......',:c|___|xxxddollc\_____,___|_________/ddoll|___|,,,|___|...\_____|:\ ______/l|___|_________/...\________|'........',;::cc
+// c:;'.......';:codxxkkkkxxolc::;::clodxkOO0OOkkxdollc::;;,,''''',,,,''''''''''',,'''''',;:loxkkOOkxol:;,'''',,;:ccllcc:;,'''''',;::ccll
+// ;,'.......',:codxkOO0OOkxdlc:;,,;;:cldxxkkxxdolc:;;,,''.....'',;;:::;;,,,'''''........,;cldkO0KK0Okdoc::;;::cloodddoolc:;;;;;::ccllooo
+// .........',;:lodxOO0000Okdoc:,,',,;:clloddoolc:;,''.......'',;:clooollc:;;,,''.......',:ldkOKXNNXX0Oxdolllloddxxxxxxdolccccccllooodddd
+// . .....';:cldxkO0000Okxol:;,''',,;::cccc:;,,'.......'',;:cldxxkkxxdolc:;;,'.......';coxOKXNWWWNXKOkxddddxxkkkkkkxdoollllooddxxxxkkk
+// ....',;:codxkO000OOxdoc:;,''',,,;;;;,''.......',,;:clodkO00000Okxolc::;,,''..',;:ldxOKXNWWWNNK0OkkkkkkkkkkkxxddooooodxxkOOOOO000
+// ....',;;clodxkkOOOkkdolc:;,,,,,,,,'..........,;:clodxkO0KKXKK0Okxdolcc::;;,,,;;:codkO0XXNNNNXKK0OOOOOkkkkxxdoollloodxkO0KKKXXXXX
+//
+// VERSION: 1.0.1
+// https://github.com/Auburn/FastNoise
+
+#ifndef FASTNOISELITE_H
+#define FASTNOISELITE_H
+
+#include <cmath>
+
+namespace fastnoiselite{
+
+class FastNoiseLite
+{
+public:
+ enum NoiseType
+ {
+ NoiseType_OpenSimplex2,
+ NoiseType_OpenSimplex2S,
+ NoiseType_Cellular,
+ NoiseType_Perlin,
+ NoiseType_ValueCubic,
+ NoiseType_Value
+ };
+
+ enum RotationType3D
+ {
+ RotationType3D_None,
+ RotationType3D_ImproveXYPlanes,
+ RotationType3D_ImproveXZPlanes
+ };
+
+ enum FractalType
+ {
+ FractalType_None,
+ FractalType_FBm,
+ FractalType_Ridged,
+ FractalType_PingPong,
+ FractalType_DomainWarpProgressive,
+ FractalType_DomainWarpIndependent
+ };
+
+ enum CellularDistanceFunction
+ {
+ CellularDistanceFunction_Euclidean,
+ CellularDistanceFunction_EuclideanSq,
+ CellularDistanceFunction_Manhattan,
+ CellularDistanceFunction_Hybrid
+ };
+
+ enum CellularReturnType
+ {
+ CellularReturnType_CellValue,
+ CellularReturnType_Distance,
+ CellularReturnType_Distance2,
+ CellularReturnType_Distance2Add,
+ CellularReturnType_Distance2Sub,
+ CellularReturnType_Distance2Mul,
+ CellularReturnType_Distance2Div
+ };
+
+ enum DomainWarpType
+ {
+ DomainWarpType_OpenSimplex2,
+ DomainWarpType_OpenSimplex2Reduced,
+ DomainWarpType_BasicGrid
+ };
+
+ /// <summary>
+ /// Create new FastNoise object with optional seed
+ /// </summary>
+ FastNoiseLite(int seed = 1337)
+ {
+ mSeed = seed;
+ mFrequency = 0.01f;
+ mNoiseType = NoiseType_OpenSimplex2;
+ mRotationType3D = RotationType3D_None;
+ mTransformType3D = TransformType3D_DefaultOpenSimplex2;
+
+ mFractalType = FractalType_None;
+ mOctaves = 3;
+ mLacunarity = 2.0f;
+ mGain = 0.5f;
+ mWeightedStrength = 0.0f;
+ mPingPongStrength = 2.0f;
+
+ mFractalBounding = 1 / 1.75f;
+
+ mCellularDistanceFunction = CellularDistanceFunction_EuclideanSq;
+ mCellularReturnType = CellularReturnType_Distance;
+ mCellularJitterModifier = 1.0f;
+
+ mDomainWarpType = DomainWarpType_OpenSimplex2;
+ mWarpTransformType3D = TransformType3D_DefaultOpenSimplex2;
+ mDomainWarpAmp = 1.0f;
+ }
+
+ /// <summary>
+ /// Sets seed used for all noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: 1337
+ /// </remarks>
+ void SetSeed(int seed) { mSeed = seed; }
+
+ /// <summary>
+ /// Sets frequency for all noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: 0.01
+ /// </remarks>
+ void SetFrequency(float frequency) { mFrequency = frequency; }
+
+ /// <summary>
+ /// Sets noise algorithm used for GetNoise(...)
+ /// </summary>
+ /// <remarks>
+ /// Default: OpenSimplex2
+ /// </remarks>
+ void SetNoiseType(NoiseType noiseType)
+ {
+ mNoiseType = noiseType;
+ UpdateTransformType3D();
+ }
+
+ /// <summary>
+ /// Sets domain rotation type for 3D Noise and 3D DomainWarp.
+ /// Can aid in reducing directional artifacts when sampling a 2D plane in 3D
+ /// </summary>
+ /// <remarks>
+ /// Default: None
+ /// </remarks>
+ void SetRotationType3D(RotationType3D rotationType3D)
+ {
+ mRotationType3D = rotationType3D;
+ UpdateTransformType3D();
+ UpdateWarpTransformType3D();
+ }
+
+ /// <summary>
+ /// Sets method for combining octaves in all fractal noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: None
+ /// Note: FractalType_DomainWarp... only affects DomainWarp(...)
+ /// </remarks>
+ void SetFractalType(FractalType fractalType) { mFractalType = fractalType; }
+
+ /// <summary>
+ /// Sets octave count for all fractal noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: 3
+ /// </remarks>
+ void SetFractalOctaves(int octaves)
+ {
+ mOctaves = octaves;
+ CalculateFractalBounding();
+ }
+
+ /// <summary>
+ /// Sets octave lacunarity for all fractal noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: 2.0
+ /// </remarks>
+ void SetFractalLacunarity(float lacunarity) { mLacunarity = lacunarity; }
+
+ /// <summary>
+ /// Sets octave gain for all fractal noise types
+ /// </summary>
+ /// <remarks>
+ /// Default: 0.5
+ /// </remarks>
+ void SetFractalGain(float gain)
+ {
+ mGain = gain;
+ CalculateFractalBounding();
+ }
+
+ /// <summary>
+ /// Sets octave weighting for all none DomainWarp fratal types
+ /// </summary>
+ /// <remarks>
+ /// Default: 0.0
+ /// Note: Keep between 0...1 to maintain -1...1 output bounding
+ /// </remarks>
+ void SetFractalWeightedStrength(float weightedStrength) { mWeightedStrength = weightedStrength; }
+
+ /// <summary>
+ /// Sets strength of the fractal ping pong effect
+ /// </summary>
+ /// <remarks>
+ /// Default: 2.0
+ /// </remarks>
+ void SetFractalPingPongStrength(float pingPongStrength) { mPingPongStrength = pingPongStrength; }
+
+
+ /// <summary>
+ /// Sets distance function used in cellular noise calculations
+ /// </summary>
+ /// <remarks>
+ /// Default: Distance
+ /// </remarks>
+ void SetCellularDistanceFunction(CellularDistanceFunction cellularDistanceFunction) { mCellularDistanceFunction = cellularDistanceFunction; }
+
+ /// <summary>
+ /// Sets return type from cellular noise calculations
+ /// </summary>
+ /// <remarks>
+ /// Default: EuclideanSq
+ /// </remarks>
+ void SetCellularReturnType(CellularReturnType cellularReturnType) { mCellularReturnType = cellularReturnType; }
+
+ /// <summary>
+ /// Sets the maximum distance a cellular point can move from it's grid position
+ /// </summary>
+ /// <remarks>
+ /// Default: 1.0
+ /// Note: Setting this higher than 1 will cause artifacts
+ /// </remarks>
+ void SetCellularJitter(float cellularJitter) { mCellularJitterModifier = cellularJitter; }
+
+
+ /// <summary>
+ /// Sets the warp algorithm when using DomainWarp(...)
+ /// </summary>
+ /// <remarks>
+ /// Default: OpenSimplex2
+ /// </remarks>
+ void SetDomainWarpType(DomainWarpType domainWarpType)
+ {
+ mDomainWarpType = domainWarpType;
+ UpdateWarpTransformType3D();
+ }
+
+
+ /// <summary>
+ /// Sets the maximum warp distance from original position when using DomainWarp(...)
+ /// </summary>
+ /// <remarks>
+ /// Default: 1.0
+ /// </remarks>
+ void SetDomainWarpAmp(float domainWarpAmp) { mDomainWarpAmp = domainWarpAmp; }
+
+
+ /// <summary>
+ /// 2D noise at given position using current settings
+ /// </summary>
+ /// <returns>
+ /// Noise output bounded between -1...1
+ /// </returns>
+ template <typename FNfloat>
+ float GetNoise(FNfloat x, FNfloat y) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+ TransformNoiseCoordinate(x, y);
+
+ switch (mFractalType)
+ {
+ default:
+ return GenNoiseSingle(mSeed, x, y);
+ case FractalType_FBm:
+ return GenFractalFBm(x, y);
+ case FractalType_Ridged:
+ return GenFractalRidged(x, y);
+ case FractalType_PingPong:
+ return GenFractalPingPong(x, y);
+ }
+ }
+
+ /// <summary>
+ /// 3D noise at given position using current settings
+ /// </summary>
+ /// <returns>
+ /// Noise output bounded between -1...1
+ /// </returns>
+ template <typename FNfloat>
+ float GetNoise(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+ TransformNoiseCoordinate(x, y, z);
+
+ switch (mFractalType)
+ {
+ default:
+ return GenNoiseSingle(mSeed, x, y, z);
+ case FractalType_FBm:
+ return GenFractalFBm(x, y, z);
+ case FractalType_Ridged:
+ return GenFractalRidged(x, y, z);
+ case FractalType_PingPong:
+ return GenFractalPingPong(x, y, z);
+ }
+ }
+
+
+ /// <summary>
+ /// 2D warps the input position using current domain warp settings
+ /// </summary>
+ /// <example>
+ /// Example usage with GetNoise
+ /// <code>DomainWarp(x, y)
+ /// noise = GetNoise(x, y)</code>
+ /// </example>
+ template <typename FNfloat>
+ void DomainWarp(FNfloat& x, FNfloat& y) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+ switch (mFractalType)
+ {
+ default:
+ DomainWarpSingle(x, y);
+ break;
+ case FractalType_DomainWarpProgressive:
+ DomainWarpFractalProgressive(x, y);
+ break;
+ case FractalType_DomainWarpIndependent:
+ DomainWarpFractalIndependent(x, y);
+ break;
+ }
+ }
+
+ /// <summary>
+ /// 3D warps the input position using current domain warp settings
+ /// </summary>
+ /// <example>
+ /// Example usage with GetNoise
+ /// <code>DomainWarp(x, y, z)
+ /// noise = GetNoise(x, y, z)</code>
+ /// </example>
+ template <typename FNfloat>
+ void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+ switch (mFractalType)
+ {
+ default:
+ DomainWarpSingle(x, y, z);
+ break;
+ case FractalType_DomainWarpProgressive:
+ DomainWarpFractalProgressive(x, y, z);
+ break;
+ case FractalType_DomainWarpIndependent:
+ DomainWarpFractalIndependent(x, y, z);
+ break;
+ }
+ }
+
+private:
+ template <typename T>
+ struct Arguments_must_be_floating_point_values;
+
+ enum TransformType3D
+ {
+ TransformType3D_None,
+ TransformType3D_ImproveXYPlanes,
+ TransformType3D_ImproveXZPlanes,
+ TransformType3D_DefaultOpenSimplex2
+ };
+
+ int mSeed;
+ float mFrequency;
+ NoiseType mNoiseType;
+ RotationType3D mRotationType3D;
+ TransformType3D mTransformType3D;
+
+ FractalType mFractalType;
+ int mOctaves;
+ float mLacunarity;
+ float mGain;
+ float mWeightedStrength;
+ float mPingPongStrength;
+
+ float mFractalBounding;
+
+ CellularDistanceFunction mCellularDistanceFunction;
+ CellularReturnType mCellularReturnType;
+ float mCellularJitterModifier;
+
+ DomainWarpType mDomainWarpType;
+ TransformType3D mWarpTransformType3D;
+ float mDomainWarpAmp;
+
+
+ template <typename T>
+ struct Lookup
+ {
+ static const T Gradients2D[];
+ static const T Gradients3D[];
+ static const T RandVecs2D[];
+ static const T RandVecs3D[];
+ };
+
+ static float FastMin(float a, float b) { return a < b ? a : b; }
+
+ static float FastMax(float a, float b) { return a > b ? a : b; }
+
+ static float FastAbs(float f) { return f < 0 ? -f : f; }
+
+ static float FastSqrt(float f) { return sqrtf(f); }
+
+ template <typename FNfloat>
+ static int FastFloor(FNfloat f) { return f >= 0 ? (int)f : (int)f - 1; }
+
+ template <typename FNfloat>
+ static int FastRound(FNfloat f) { return f >= 0 ? (int)(f + 0.5f) : (int)(f - 0.5f); }
+
+ static float Lerp(float a, float b, float t) { return a + t * (b - a); }
+
+ static float InterpHermite(float t) { return t * t * (3 - 2 * t); }
+
+ static float InterpQuintic(float t) { return t * t * t * (t * (t * 6 - 15) + 10); }
+
+ static float CubicLerp(float a, float b, float c, float d, float t)
+ {
+ float p = (d - c) - (a - b);
+ return t * t * t * p + t * t * ((a - b) - p) + t * (c - a) + b;
+ }
+
+ static float PingPong(float t)
+ {
+ t -= (int)(t * 0.5f) * 2;
+ return t < 1 ? t : 2 - t;
+ }
+
+ void CalculateFractalBounding()
+ {
+ float gain = FastAbs(mGain);
+ float amp = gain;
+ float ampFractal = 1.0f;
+ for (int i = 1; i < mOctaves; i++)
+ {
+ ampFractal += amp;
+ amp *= gain;
+ }
+ mFractalBounding = 1 / ampFractal;
+ }
+
+ // Hashing
+ static const int PrimeX = 501125321;
+ static const int PrimeY = 1136930381;
+ static const int PrimeZ = 1720413743;
+
+ static int Hash(int seed, int xPrimed, int yPrimed)
+ {
+ int hash = seed ^ xPrimed ^ yPrimed;
+
+ hash *= 0x27d4eb2d;
+ return hash;
+ }
+
+
+ static int Hash(int seed, int xPrimed, int yPrimed, int zPrimed)
+ {
+ int hash = seed ^ xPrimed ^ yPrimed ^ zPrimed;
+
+ hash *= 0x27d4eb2d;
+ return hash;
+ }
+
+
+ static float ValCoord(int seed, int xPrimed, int yPrimed)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+
+ hash *= hash;
+ hash ^= hash << 19;
+ return hash * (1 / 2147483648.0f);
+ }
+
+
+ static float ValCoord(int seed, int xPrimed, int yPrimed, int zPrimed)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+
+ hash *= hash;
+ hash ^= hash << 19;
+ return hash * (1 / 2147483648.0f);
+ }
+
+
+ float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ hash ^= hash >> 15;
+ hash &= 127 << 1;
+
+ float xg = Lookup<float>::Gradients2D[hash];
+ float yg = Lookup<float>::Gradients2D[hash | 1];
+
+ return xd * xg + yd * yg;
+ }
+
+
+ float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ hash ^= hash >> 15;
+ hash &= 63 << 2;
+
+ float xg = Lookup<float>::Gradients3D[hash];
+ float yg = Lookup<float>::Gradients3D[hash | 1];
+ float zg = Lookup<float>::Gradients3D[hash | 2];
+
+ return xd * xg + yd * yg + zd * zg;
+ }
+
+
+ void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1);
+
+ xo = Lookup<float>::RandVecs2D[hash];
+ yo = Lookup<float>::RandVecs2D[hash | 1];
+ }
+
+
+ void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2);
+
+ xo = Lookup<float>::RandVecs3D[hash];
+ yo = Lookup<float>::RandVecs3D[hash | 1];
+ zo = Lookup<float>::RandVecs3D[hash | 2];
+ }
+
+
+ void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ int index1 = hash & (127 << 1);
+ int index2 = (hash >> 7) & (255 << 1);
+
+ float xg = Lookup<float>::Gradients2D[index1];
+ float yg = Lookup<float>::Gradients2D[index1 | 1];
+ float value = xd * xg + yd * yg;
+
+ float xgo = Lookup<float>::RandVecs2D[index2];
+ float ygo = Lookup<float>::RandVecs2D[index2 | 1];
+
+ xo = value * xgo;
+ yo = value * ygo;
+ }
+
+
+ void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ int index1 = hash & (63 << 2);
+ int index2 = (hash >> 6) & (255 << 2);
+
+ float xg = Lookup<float>::Gradients3D[index1];
+ float yg = Lookup<float>::Gradients3D[index1 | 1];
+ float zg = Lookup<float>::Gradients3D[index1 | 2];
+ float value = xd * xg + yd * yg + zd * zg;
+
+ float xgo = Lookup<float>::RandVecs3D[index2];
+ float ygo = Lookup<float>::RandVecs3D[index2 | 1];
+ float zgo = Lookup<float>::RandVecs3D[index2 | 2];
+
+ xo = value * xgo;
+ yo = value * ygo;
+ zo = value * zgo;
+ }
+
+
+ // Generic noise gen
+
+ template <typename FNfloat>
+ float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const
+ {
+ switch (mNoiseType)
+ {
+ case NoiseType_OpenSimplex2:
+ return SingleSimplex(seed, x, y);
+ case NoiseType_OpenSimplex2S:
+ return SingleOpenSimplex2S(seed, x, y);
+ case NoiseType_Cellular:
+ return SingleCellular(seed, x, y);
+ case NoiseType_Perlin:
+ return SinglePerlin(seed, x, y);
+ case NoiseType_ValueCubic:
+ return SingleValueCubic(seed, x, y);
+ case NoiseType_Value:
+ return SingleValue(seed, x, y);
+ default:
+ return 0;
+ }
+ }
+
+ template <typename FNfloat>
+ float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ switch (mNoiseType)
+ {
+ case NoiseType_OpenSimplex2:
+ return SingleOpenSimplex2(seed, x, y, z);
+ case NoiseType_OpenSimplex2S:
+ return SingleOpenSimplex2S(seed, x, y, z);
+ case NoiseType_Cellular:
+ return SingleCellular(seed, x, y, z);
+ case NoiseType_Perlin:
+ return SinglePerlin(seed, x, y, z);
+ case NoiseType_ValueCubic:
+ return SingleValueCubic(seed, x, y, z);
+ case NoiseType_Value:
+ return SingleValue(seed, x, y, z);
+ default:
+ return 0;
+ }
+ }
+
+
+ // Noise Coordinate Transforms (frequency, and possible skew or rotation)
+
+ template <typename FNfloat>
+ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const
+ {
+ x *= mFrequency;
+ y *= mFrequency;
+
+ switch (mNoiseType)
+ {
+ case NoiseType_OpenSimplex2:
+ case NoiseType_OpenSimplex2S:
+ {
+ const FNfloat SQRT3 = (FNfloat)1.7320508075688772935274463415059;
+ const FNfloat F2 = 0.5f * (SQRT3 - 1);
+ FNfloat t = (x + y) * F2;
+ x += t;
+ y += t;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ template <typename FNfloat>
+ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ x *= mFrequency;
+ y *= mFrequency;
+ z *= mFrequency;
+
+ switch (mTransformType3D)
+ {
+ case TransformType3D_ImproveXYPlanes:
+ {
+ FNfloat xy = x + y;
+ FNfloat s2 = xy * -(FNfloat)0.211324865405187;
+ z *= (FNfloat)0.577350269189626;
+ x += s2 - z;
+ y = y + s2 - z;
+ z += xy * (FNfloat)0.577350269189626;
+ }
+ break;
+ case TransformType3D_ImproveXZPlanes:
+ {
+ FNfloat xz = x + z;
+ FNfloat s2 = xz * -(FNfloat)0.211324865405187;
+ y *= (FNfloat)0.577350269189626;
+ x += s2 - y;
+ z += s2 - y;
+ y += xz * (FNfloat)0.577350269189626;
+ }
+ break;
+ case TransformType3D_DefaultOpenSimplex2:
+ {
+ const FNfloat R3 = (FNfloat)(2.0 / 3.0);
+ FNfloat r = (x + y + z) * R3; // Rotation, not skew
+ x = r - x;
+ y = r - y;
+ z = r - z;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateTransformType3D()
+ {
+ switch (mRotationType3D)
+ {
+ case RotationType3D_ImproveXYPlanes:
+ mTransformType3D = TransformType3D_ImproveXYPlanes;
+ break;
+ case RotationType3D_ImproveXZPlanes:
+ mTransformType3D = TransformType3D_ImproveXZPlanes;
+ break;
+ default:
+ switch (mNoiseType)
+ {
+ case NoiseType_OpenSimplex2:
+ case NoiseType_OpenSimplex2S:
+ mTransformType3D = TransformType3D_DefaultOpenSimplex2;
+ break;
+ default:
+ mTransformType3D = TransformType3D_None;
+ break;
+ }
+ break;
+ }
+ }
+
+
+ // Domain Warp Coordinate Transforms
+
+ template <typename FNfloat>
+ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const
+ {
+ switch (mDomainWarpType)
+ {
+ case DomainWarpType_OpenSimplex2:
+ case DomainWarpType_OpenSimplex2Reduced:
+ {
+ const FNfloat SQRT3 = (FNfloat)1.7320508075688772935274463415059;
+ const FNfloat F2 = 0.5f * (SQRT3 - 1);
+ FNfloat t = (x + y) * F2;
+ x += t;
+ y += t;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ template <typename FNfloat>
+ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ switch (mWarpTransformType3D)
+ {
+ case TransformType3D_ImproveXYPlanes:
+ {
+ FNfloat xy = x + y;
+ FNfloat s2 = xy * -(FNfloat)0.211324865405187;
+ z *= (FNfloat)0.577350269189626;
+ x += s2 - z;
+ y = y + s2 - z;
+ z += xy * (FNfloat)0.577350269189626;
+ }
+ break;
+ case TransformType3D_ImproveXZPlanes:
+ {
+ FNfloat xz = x + z;
+ FNfloat s2 = xz * -(FNfloat)0.211324865405187;
+ y *= (FNfloat)0.577350269189626;
+ x += s2 - y;
+ z += s2 - y;
+ y += xz * (FNfloat)0.577350269189626;
+ }
+ break;
+ case TransformType3D_DefaultOpenSimplex2:
+ {
+ const FNfloat R3 = (FNfloat)(2.0 / 3.0);
+ FNfloat r = (x + y + z) * R3; // Rotation, not skew
+ x = r - x;
+ y = r - y;
+ z = r - z;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ void UpdateWarpTransformType3D()
+ {
+ switch (mRotationType3D)
+ {
+ case RotationType3D_ImproveXYPlanes:
+ mWarpTransformType3D = TransformType3D_ImproveXYPlanes;
+ break;
+ case RotationType3D_ImproveXZPlanes:
+ mWarpTransformType3D = TransformType3D_ImproveXZPlanes;
+ break;
+ default:
+ switch (mDomainWarpType)
+ {
+ case DomainWarpType_OpenSimplex2:
+ case DomainWarpType_OpenSimplex2Reduced:
+ mWarpTransformType3D = TransformType3D_DefaultOpenSimplex2;
+ break;
+ default:
+ mWarpTransformType3D = TransformType3D_None;
+ break;
+ }
+ break;
+ }
+ }
+
+
+ // Fractal FBm
+
+ template <typename FNfloat>
+ float GenFractalFBm(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = GenNoiseSingle(seed++, x, y);
+ sum += noise * amp;
+ amp *= Lerp(1.0f, FastMin(noise + 1, 2) * 0.5f, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+ template <typename FNfloat>
+ float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = GenNoiseSingle(seed++, x, y, z);
+ sum += noise * amp;
+ amp *= Lerp(1.0f, (noise + 1) * 0.5f, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ z *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+
+ // Fractal Ridged
+
+ template <typename FNfloat>
+ float GenFractalRidged(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = FastAbs(GenNoiseSingle(seed++, x, y));
+ sum += (noise * -2 + 1) * amp;
+ amp *= Lerp(1.0f, 1 - noise, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+ template <typename FNfloat>
+ float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = FastAbs(GenNoiseSingle(seed++, x, y, z));
+ sum += (noise * -2 + 1) * amp;
+ amp *= Lerp(1.0f, 1 - noise, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ z *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+
+ // Fractal PingPong
+
+ template <typename FNfloat>
+ float GenFractalPingPong(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = PingPong((GenNoiseSingle(seed++, x, y) + 1) * mPingPongStrength);
+ sum += (noise - 0.5f) * 2 * amp;
+ amp *= Lerp(1.0f, noise, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+ template <typename FNfloat>
+ float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+ float amp = mFractalBounding;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ float noise = PingPong((GenNoiseSingle(seed++, x, y, z) + 1) * mPingPongStrength);
+ sum += (noise - 0.5f) * 2 * amp;
+ amp *= Lerp(1.0f, noise, mWeightedStrength);
+
+ x *= mLacunarity;
+ y *= mLacunarity;
+ z *= mLacunarity;
+ amp *= mGain;
+ }
+
+ return sum;
+ }
+
+
+ // Simplex/OpenSimplex2 Noise
+
+ template <typename FNfloat>
+ float SingleSimplex(int seed, FNfloat x, FNfloat y) const
+ {
+ // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex.
+
+ const float SQRT3 = 1.7320508075688772935274463415059f;
+ const float G2 = (3 - SQRT3) / 6;
+
+ /*
+ * --- Skew moved to TransformNoiseCoordinate method ---
+ * const FNfloat F2 = 0.5f * (SQRT3 - 1);
+ * FNfloat s = (x + y) * F2;
+ * x += s; y += s;
+ */
+
+ int i = FastFloor(x);
+ int j = FastFloor(y);
+ float xi = (float)(x - i);
+ float yi = (float)(y - j);
+
+ float t = (xi + yi) * G2;
+ float x0 = (float)(xi - t);
+ float y0 = (float)(yi - t);
+
+ i *= PrimeX;
+ j *= PrimeY;
+
+ float n0, n1, n2;
+
+ float a = 0.5f - x0 * x0 - y0 * y0;
+ if (a <= 0) n0 = 0;
+ else
+ {
+ n0 = (a * a) * (a * a) * GradCoord(seed, i, j, x0, y0);
+ }
+
+ float c = (float)(2 * (1 - 2 * G2) * (1 / G2 - 2)) * t + ((float)(-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a);
+ if (c <= 0) n2 = 0;
+ else
+ {
+ float x2 = x0 + (2 * (float)G2 - 1);
+ float y2 = y0 + (2 * (float)G2 - 1);
+ n2 = (c * c) * (c * c) * GradCoord(seed, i + PrimeX, j + PrimeY, x2, y2);
+ }
+
+ if (y0 > x0)
+ {
+ float x1 = x0 + (float)G2;
+ float y1 = y0 + ((float)G2 - 1);
+ float b = 0.5f - x1 * x1 - y1 * y1;
+ if (b <= 0) n1 = 0;
+ else
+ {
+ n1 = (b * b) * (b * b) * GradCoord(seed, i, j + PrimeY, x1, y1);
+ }
+ }
+ else
+ {
+ float x1 = x0 + ((float)G2 - 1);
+ float y1 = y0 + (float)G2;
+ float b = 0.5f - x1 * x1 - y1 * y1;
+ if (b <= 0) n1 = 0;
+ else
+ {
+ n1 = (b * b) * (b * b) * GradCoord(seed, i + PrimeX, j, x1, y1);
+ }
+ }
+
+ return (n0 + n1 + n2) * 99.83685446303647f;
+ }
+
+ template <typename FNfloat>
+ float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ // 3D OpenSimplex2 case uses two offset rotated cube grids.
+
+ /*
+ * --- Rotation moved to TransformNoiseCoordinate method ---
+ * const FNfloat R3 = (FNfloat)(2.0 / 3.0);
+ * FNfloat r = (x + y + z) * R3; // Rotation, not skew
+ * x = r - x; y = r - y; z = r - z;
+ */
+
+ int i = FastRound(x);
+ int j = FastRound(y);
+ int k = FastRound(z);
+ float x0 = (float)(x - i);
+ float y0 = (float)(y - j);
+ float z0 = (float)(z - k);
+
+ int xNSign = (int)(-1.0f - x0) | 1;
+ int yNSign = (int)(-1.0f - y0) | 1;
+ int zNSign = (int)(-1.0f - z0) | 1;
+
+ float ax0 = xNSign * -x0;
+ float ay0 = yNSign * -y0;
+ float az0 = zNSign * -z0;
+
+ i *= PrimeX;
+ j *= PrimeY;
+ k *= PrimeZ;
+
+ float value = 0;
+ float a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0);
+
+ for (int l = 0; ; l++)
+ {
+ if (a > 0)
+ {
+ value += (a * a) * (a * a) * GradCoord(seed, i, j, k, x0, y0, z0);
+ }
+
+ float b = a + 1;
+ int i1 = i;
+ int j1 = j;
+ int k1 = k;
+ float x1 = x0;
+ float y1 = y0;
+ float z1 = z0;
+
+ if (ax0 >= ay0 && ax0 >= az0)
+ {
+ x1 += xNSign;
+ b -= xNSign * 2 * x1;
+ i1 -= xNSign * PrimeX;
+ }
+ else if (ay0 > ax0 && ay0 >= az0)
+ {
+ y1 += yNSign;
+ b -= yNSign * 2 * y1;
+ j1 -= yNSign * PrimeY;
+ }
+ else
+ {
+ z1 += zNSign;
+ b -= zNSign * 2 * z1;
+ k1 -= zNSign * PrimeZ;
+ }
+
+ if (b > 0)
+ {
+ value += (b * b) * (b * b) * GradCoord(seed, i1, j1, k1, x1, y1, z1);
+ }
+
+ if (l == 1) break;
+
+ ax0 = 0.5f - ax0;
+ ay0 = 0.5f - ay0;
+ az0 = 0.5f - az0;
+
+ x0 = xNSign * ax0;
+ y0 = yNSign * ay0;
+ z0 = zNSign * az0;
+
+ a += (0.75f - ax0) - (ay0 + az0);
+
+ i += (xNSign >> 1) & PrimeX;
+ j += (yNSign >> 1) & PrimeY;
+ k += (zNSign >> 1) & PrimeZ;
+
+ xNSign = -xNSign;
+ yNSign = -yNSign;
+ zNSign = -zNSign;
+
+ seed = ~seed;
+ }
+
+ return value * 32.69428253173828125f;
+ }
+
+
+ // OpenSimplex2S Noise
+
+ template <typename FNfloat>
+ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const
+ {
+ // 2D OpenSimplex2S case is a modified 2D simplex noise.
+
+ const FNfloat SQRT3 = (FNfloat)1.7320508075688772935274463415059;
+ const FNfloat G2 = (3 - SQRT3) / 6;
+
+ /*
+ * --- Skew moved to TransformNoiseCoordinate method ---
+ * const FNfloat F2 = 0.5f * (SQRT3 - 1);
+ * FNfloat s = (x + y) * F2;
+ * x += s; y += s;
+ */
+
+ int i = FastFloor(x);
+ int j = FastFloor(y);
+ float xi = (float)(x - i);
+ float yi = (float)(y - j);
+
+ i *= PrimeX;
+ j *= PrimeY;
+ int i1 = i + PrimeX;
+ int j1 = j + PrimeY;
+
+ float t = (xi + yi) * (float)G2;
+ float x0 = xi - t;
+ float y0 = yi - t;
+
+ float a0 = (2.0f / 3.0f) - x0 * x0 - y0 * y0;
+ float value = (a0 * a0) * (a0 * a0) * GradCoord(seed, i, j, x0, y0);
+
+ float a1 = (float)(2 * (1 - 2 * G2) * (1 / G2 - 2)) * t + ((float)(-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0);
+ float x1 = x0 - (float)(1 - 2 * G2);
+ float y1 = y0 - (float)(1 - 2 * G2);
+ value += (a1 * a1) * (a1 * a1) * GradCoord(seed, i1, j1, x1, y1);
+
+ // Nested conditionals were faster than compact bit logic/arithmetic.
+ float xmyi = xi - yi;
+ if (t > G2)
+ {
+ if (xi + xmyi > 1)
+ {
+ float x2 = x0 + (float)(3 * G2 - 2);
+ float y2 = y0 + (float)(3 * G2 - 1);
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i + (PrimeX << 1), j + PrimeY, x2, y2);
+ }
+ }
+ else
+ {
+ float x2 = x0 + (float)G2;
+ float y2 = y0 + (float)(G2 - 1);
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i, j + PrimeY, x2, y2);
+ }
+ }
+
+ if (yi - xmyi > 1)
+ {
+ float x3 = x0 + (float)(3 * G2 - 1);
+ float y3 = y0 + (float)(3 * G2 - 2);
+ float a3 = (2.0f / 3.0f) - x3 * x3 - y3 * y3;
+ if (a3 > 0)
+ {
+ value += (a3 * a3) * (a3 * a3) * GradCoord(seed, i + PrimeX, j + (PrimeY << 1), x3, y3);
+ }
+ }
+ else
+ {
+ float x3 = x0 + (float)(G2 - 1);
+ float y3 = y0 + (float)G2;
+ float a3 = (2.0f / 3.0f) - x3 * x3 - y3 * y3;
+ if (a3 > 0)
+ {
+ value += (a3 * a3) * (a3 * a3) * GradCoord(seed, i + PrimeX, j, x3, y3);
+ }
+ }
+ }
+ else
+ {
+ if (xi + xmyi < 0)
+ {
+ float x2 = x0 + (float)(1 - G2);
+ float y2 = y0 - (float)G2;
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i - PrimeX, j, x2, y2);
+ }
+ }
+ else
+ {
+ float x2 = x0 + (float)(G2 - 1);
+ float y2 = y0 + (float)G2;
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i + PrimeX, j, x2, y2);
+ }
+ }
+
+ if (yi < xmyi)
+ {
+ float x2 = x0 - (float)G2;
+ float y2 = y0 - (float)(G2 - 1);
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i, j - PrimeY, x2, y2);
+ }
+ }
+ else
+ {
+ float x2 = x0 + (float)G2;
+ float y2 = y0 + (float)(G2 - 1);
+ float a2 = (2.0f / 3.0f) - x2 * x2 - y2 * y2;
+ if (a2 > 0)
+ {
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed, i, j + PrimeY, x2, y2);
+ }
+ }
+ }
+
+ return value * 18.24196194486065f;
+ }
+
+ template <typename FNfloat>
+ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ // 3D OpenSimplex2S case uses two offset rotated cube grids.
+
+ /*
+ * --- Rotation moved to TransformNoiseCoordinate method ---
+ * const FNfloat R3 = (FNfloat)(2.0 / 3.0);
+ * FNfloat r = (x + y + z) * R3; // Rotation, not skew
+ * x = r - x; y = r - y; z = r - z;
+ */
+
+ int i = FastFloor(x);
+ int j = FastFloor(y);
+ int k = FastFloor(z);
+ float xi = (float)(x - i);
+ float yi = (float)(y - j);
+ float zi = (float)(z - k);
+
+ i *= PrimeX;
+ j *= PrimeY;
+ k *= PrimeZ;
+ int seed2 = seed + 1293373;
+
+ int xNMask = (int)(-0.5f - xi);
+ int yNMask = (int)(-0.5f - yi);
+ int zNMask = (int)(-0.5f - zi);
+
+ float x0 = xi + xNMask;
+ float y0 = yi + yNMask;
+ float z0 = zi + zNMask;
+ float a0 = 0.75f - x0 * x0 - y0 * y0 - z0 * z0;
+ float value = (a0 * a0) * (a0 * a0) * GradCoord(seed,
+ i + (xNMask & PrimeX), j + (yNMask & PrimeY), k + (zNMask & PrimeZ), x0, y0, z0);
+
+ float x1 = xi - 0.5f;
+ float y1 = yi - 0.5f;
+ float z1 = zi - 0.5f;
+ float a1 = 0.75f - x1 * x1 - y1 * y1 - z1 * z1;
+ value += (a1 * a1) * (a1 * a1) * GradCoord(seed2,
+ i + PrimeX, j + PrimeY, k + PrimeZ, x1, y1, z1);
+
+ float xAFlipMask0 = ((xNMask | 1) << 1) * x1;
+ float yAFlipMask0 = ((yNMask | 1) << 1) * y1;
+ float zAFlipMask0 = ((zNMask | 1) << 1) * z1;
+ float xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0f;
+ float yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0f;
+ float zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0f;
+
+ bool skip5 = false;
+ float a2 = xAFlipMask0 + a0;
+ if (a2 > 0)
+ {
+ float x2 = x0 - (xNMask | 1);
+ float y2 = y0;
+ float z2 = z0;
+ value += (a2 * a2) * (a2 * a2) * GradCoord(seed,
+ i + (~xNMask & PrimeX), j + (yNMask & PrimeY), k + (zNMask & PrimeZ), x2, y2, z2);
+ }
+ else
+ {
+ float a3 = yAFlipMask0 + zAFlipMask0 + a0;
+ if (a3 > 0)
+ {
+ float x3 = x0;
+ float y3 = y0 - (yNMask | 1);
+ float z3 = z0 - (zNMask | 1);
+ value += (a3 * a3) * (a3 * a3) * GradCoord(seed,
+ i + (xNMask & PrimeX), j + (~yNMask & PrimeY), k + (~zNMask & PrimeZ), x3, y3, z3);
+ }
+
+ float a4 = xAFlipMask1 + a1;
+ if (a4 > 0)
+ {
+ float x4 = (xNMask | 1) + x1;
+ float y4 = y1;
+ float z4 = z1;
+ value += (a4 * a4) * (a4 * a4) * GradCoord(seed2,
+ i + (xNMask & (PrimeX * 2)), j + PrimeY, k + PrimeZ, x4, y4, z4);
+ skip5 = true;
+ }
+ }
+
+ bool skip9 = false;
+ float a6 = yAFlipMask0 + a0;
+ if (a6 > 0)
+ {
+ float x6 = x0;
+ float y6 = y0 - (yNMask | 1);
+ float z6 = z0;
+ value += (a6 * a6) * (a6 * a6) * GradCoord(seed,
+ i + (xNMask & PrimeX), j + (~yNMask & PrimeY), k + (zNMask & PrimeZ), x6, y6, z6);
+ }
+ else
+ {
+ float a7 = xAFlipMask0 + zAFlipMask0 + a0;
+ if (a7 > 0)
+ {
+ float x7 = x0 - (xNMask | 1);
+ float y7 = y0;
+ float z7 = z0 - (zNMask | 1);
+ value += (a7 * a7) * (a7 * a7) * GradCoord(seed,
+ i + (~xNMask & PrimeX), j + (yNMask & PrimeY), k + (~zNMask & PrimeZ), x7, y7, z7);
+ }
+
+ float a8 = yAFlipMask1 + a1;
+ if (a8 > 0)
+ {
+ float x8 = x1;
+ float y8 = (yNMask | 1) + y1;
+ float z8 = z1;
+ value += (a8 * a8) * (a8 * a8) * GradCoord(seed2,
+ i + PrimeX, j + (yNMask & (PrimeY << 1)), k + PrimeZ, x8, y8, z8);
+ skip9 = true;
+ }
+ }
+
+ bool skipD = false;
+ float aA = zAFlipMask0 + a0;
+ if (aA > 0)
+ {
+ float xA = x0;
+ float yA = y0;
+ float zA = z0 - (zNMask | 1);
+ value += (aA * aA) * (aA * aA) * GradCoord(seed,
+ i + (xNMask & PrimeX), j + (yNMask & PrimeY), k + (~zNMask & PrimeZ), xA, yA, zA);
+ }
+ else
+ {
+ float aB = xAFlipMask0 + yAFlipMask0 + a0;
+ if (aB > 0)
+ {
+ float xB = x0 - (xNMask | 1);
+ float yB = y0 - (yNMask | 1);
+ float zB = z0;
+ value += (aB * aB) * (aB * aB) * GradCoord(seed,
+ i + (~xNMask & PrimeX), j + (~yNMask & PrimeY), k + (zNMask & PrimeZ), xB, yB, zB);
+ }
+
+ float aC = zAFlipMask1 + a1;
+ if (aC > 0)
+ {
+ float xC = x1;
+ float yC = y1;
+ float zC = (zNMask | 1) + z1;
+ value += (aC * aC) * (aC * aC) * GradCoord(seed2,
+ i + PrimeX, j + PrimeY, k + (zNMask & (PrimeZ << 1)), xC, yC, zC);
+ skipD = true;
+ }
+ }
+
+ if (!skip5)
+ {
+ float a5 = yAFlipMask1 + zAFlipMask1 + a1;
+ if (a5 > 0)
+ {
+ float x5 = x1;
+ float y5 = (yNMask | 1) + y1;
+ float z5 = (zNMask | 1) + z1;
+ value += (a5 * a5) * (a5 * a5) * GradCoord(seed2,
+ i + PrimeX, j + (yNMask & (PrimeY << 1)), k + (zNMask & (PrimeZ << 1)), x5, y5, z5);
+ }
+ }
+
+ if (!skip9)
+ {
+ float a9 = xAFlipMask1 + zAFlipMask1 + a1;
+ if (a9 > 0)
+ {
+ float x9 = (xNMask | 1) + x1;
+ float y9 = y1;
+ float z9 = (zNMask | 1) + z1;
+ value += (a9 * a9) * (a9 * a9) * GradCoord(seed2,
+ i + (xNMask & (PrimeX * 2)), j + PrimeY, k + (zNMask & (PrimeZ << 1)), x9, y9, z9);
+ }
+ }
+
+ if (!skipD)
+ {
+ float aD = xAFlipMask1 + yAFlipMask1 + a1;
+ if (aD > 0)
+ {
+ float xD = (xNMask | 1) + x1;
+ float yD = (yNMask | 1) + y1;
+ float zD = z1;
+ value += (aD * aD) * (aD * aD) * GradCoord(seed2,
+ i + (xNMask & (PrimeX << 1)), j + (yNMask & (PrimeY << 1)), k + PrimeZ, xD, yD, zD);
+ }
+ }
+
+ return value * 9.046026385208288f;
+ }
+
+
+ // Cellular Noise
+
+ template <typename FNfloat>
+ float SingleCellular(int seed, FNfloat x, FNfloat y) const
+ {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+
+ float distance0 = 1e10f;
+ float distance1 = 1e10f;
+ int closestHash = 0;
+
+ float cellularJitter = 0.43701595f * mCellularJitterModifier;
+
+ int xPrimed = (xr - 1) * PrimeX;
+ int yPrimedBase = (yr - 1) * PrimeY;
+
+ switch (mCellularDistanceFunction)
+ {
+ default:
+ case CellularDistanceFunction_Euclidean:
+ case CellularDistanceFunction_EuclideanSq:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ int idx = hash & (255 << 1);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs2D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs2D[idx | 1] * cellularJitter;
+
+ float newDistance = vecX * vecX + vecY * vecY;
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ case CellularDistanceFunction_Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ int idx = hash & (255 << 1);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs2D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs2D[idx | 1] * cellularJitter;
+
+ float newDistance = FastAbs(vecX) + FastAbs(vecY);
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ case CellularDistanceFunction_Hybrid:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ int idx = hash & (255 << 1);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs2D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs2D[idx | 1] * cellularJitter;
+
+ float newDistance = (FastAbs(vecX) + FastAbs(vecY)) + (vecX * vecX + vecY * vecY);
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ }
+
+ if (mCellularDistanceFunction == CellularDistanceFunction_Euclidean && mCellularReturnType >= CellularReturnType_Distance)
+ {
+ distance0 = FastSqrt(distance0);
+
+ if (mCellularReturnType >= CellularReturnType_Distance2)
+ {
+ distance1 = FastSqrt(distance1);
+ }
+ }
+
+ switch (mCellularReturnType)
+ {
+ case CellularReturnType_CellValue:
+ return closestHash * (1 / 2147483648.0f);
+ case CellularReturnType_Distance:
+ return distance0 - 1;
+ case CellularReturnType_Distance2:
+ return distance1 - 1;
+ case CellularReturnType_Distance2Add:
+ return (distance1 + distance0) * 0.5f - 1;
+ case CellularReturnType_Distance2Sub:
+ return distance1 - distance0 - 1;
+ case CellularReturnType_Distance2Mul:
+ return distance1 * distance0 * 0.5f - 1;
+ case CellularReturnType_Distance2Div:
+ return distance0 / distance1 - 1;
+ default:
+ return 0;
+ }
+ }
+
+// GCC raises warnings when integer overflows occur, which are needed for hashing here.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
+#endif
+
+ template <typename FNfloat>
+ float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+ int zr = FastRound(z);
+
+ float distance0 = 1e10f;
+ float distance1 = 1e10f;
+ int closestHash = 0;
+
+ float cellularJitter = 0.39614353f * mCellularJitterModifier;
+
+ int xPrimed = (xr - 1) * PrimeX;
+ int yPrimedBase = (yr - 1) * PrimeY;
+ int zPrimedBase = (zr - 1) * PrimeZ;
+
+ switch (mCellularDistanceFunction)
+ {
+ case CellularDistanceFunction_Euclidean:
+ case CellularDistanceFunction_EuclideanSq:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int zPrimed = zPrimedBase;
+
+ for (int zi = zr - 1; zi <= zr + 1; zi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ int idx = hash & (255 << 2);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs3D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs3D[idx | 1] * cellularJitter;
+ float vecZ = (float)(zi - z) + Lookup<float>::RandVecs3D[idx | 2] * cellularJitter;
+
+ float newDistance = vecX * vecX + vecY * vecY + vecZ * vecZ;
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ zPrimed += PrimeZ;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ case CellularDistanceFunction_Manhattan:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int zPrimed = zPrimedBase;
+
+ for (int zi = zr - 1; zi <= zr + 1; zi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ int idx = hash & (255 << 2);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs3D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs3D[idx | 1] * cellularJitter;
+ float vecZ = (float)(zi - z) + Lookup<float>::RandVecs3D[idx | 2] * cellularJitter;
+
+ float newDistance = FastAbs(vecX) + FastAbs(vecY) + FastAbs(vecZ);
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ zPrimed += PrimeZ;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ case CellularDistanceFunction_Hybrid:
+ for (int xi = xr - 1; xi <= xr + 1; xi++)
+ {
+ int yPrimed = yPrimedBase;
+
+ for (int yi = yr - 1; yi <= yr + 1; yi++)
+ {
+ int zPrimed = zPrimedBase;
+
+ for (int zi = zr - 1; zi <= zr + 1; zi++)
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ int idx = hash & (255 << 2);
+
+ float vecX = (float)(xi - x) + Lookup<float>::RandVecs3D[idx] * cellularJitter;
+ float vecY = (float)(yi - y) + Lookup<float>::RandVecs3D[idx | 1] * cellularJitter;
+ float vecZ = (float)(zi - z) + Lookup<float>::RandVecs3D[idx | 2] * cellularJitter;
+
+ float newDistance = (FastAbs(vecX) + FastAbs(vecY) + FastAbs(vecZ)) + (vecX * vecX + vecY * vecY + vecZ * vecZ);
+
+ distance1 = FastMax(FastMin(distance1, newDistance), distance0);
+ if (newDistance < distance0)
+ {
+ distance0 = newDistance;
+ closestHash = hash;
+ }
+ zPrimed += PrimeZ;
+ }
+ yPrimed += PrimeY;
+ }
+ xPrimed += PrimeX;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (mCellularDistanceFunction == CellularDistanceFunction_Euclidean && mCellularReturnType >= CellularReturnType_Distance)
+ {
+ distance0 = FastSqrt(distance0);
+
+ if (mCellularReturnType >= CellularReturnType_Distance2)
+ {
+ distance1 = FastSqrt(distance1);
+ }
+ }
+
+ switch (mCellularReturnType)
+ {
+ case CellularReturnType_CellValue:
+ return closestHash * (1 / 2147483648.0f);
+ case CellularReturnType_Distance:
+ return distance0 - 1;
+ case CellularReturnType_Distance2:
+ return distance1 - 1;
+ case CellularReturnType_Distance2Add:
+ return (distance1 + distance0) * 0.5f - 1;
+ case CellularReturnType_Distance2Sub:
+ return distance1 - distance0 - 1;
+ case CellularReturnType_Distance2Mul:
+ return distance1 * distance0 * 0.5f - 1;
+ case CellularReturnType_Distance2Div:
+ return distance0 / distance1 - 1;
+ default:
+ return 0;
+ }
+ }
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+ // Perlin Noise
+
+ template <typename FNfloat>
+ float SinglePerlin(int seed, FNfloat x, FNfloat y) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+
+ float xd0 = (float)(x - x0);
+ float yd0 = (float)(y - y0);
+ float xd1 = xd0 - 1;
+ float yd1 = yd0 - 1;
+
+ float xs = InterpQuintic(xd0);
+ float ys = InterpQuintic(yd0);
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+
+ float xf0 = Lerp(GradCoord(seed, x0, y0, xd0, yd0), GradCoord(seed, x1, y0, xd1, yd0), xs);
+ float xf1 = Lerp(GradCoord(seed, x0, y1, xd0, yd1), GradCoord(seed, x1, y1, xd1, yd1), xs);
+
+ return Lerp(xf0, xf1, ys) * 1.4247691104677813f;
+ }
+
+ template <typename FNfloat>
+ float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int z0 = FastFloor(z);
+
+ float xd0 = (float)(x - x0);
+ float yd0 = (float)(y - y0);
+ float zd0 = (float)(z - z0);
+ float xd1 = xd0 - 1;
+ float yd1 = yd0 - 1;
+ float zd1 = zd0 - 1;
+
+ float xs = InterpQuintic(xd0);
+ float ys = InterpQuintic(yd0);
+ float zs = InterpQuintic(zd0);
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ z0 *= PrimeZ;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+ int z1 = z0 + PrimeZ;
+
+ float xf00 = Lerp(GradCoord(seed, x0, y0, z0, xd0, yd0, zd0), GradCoord(seed, x1, y0, z0, xd1, yd0, zd0), xs);
+ float xf10 = Lerp(GradCoord(seed, x0, y1, z0, xd0, yd1, zd0), GradCoord(seed, x1, y1, z0, xd1, yd1, zd0), xs);
+ float xf01 = Lerp(GradCoord(seed, x0, y0, z1, xd0, yd0, zd1), GradCoord(seed, x1, y0, z1, xd1, yd0, zd1), xs);
+ float xf11 = Lerp(GradCoord(seed, x0, y1, z1, xd0, yd1, zd1), GradCoord(seed, x1, y1, z1, xd1, yd1, zd1), xs);
+
+ float yf0 = Lerp(xf00, xf10, ys);
+ float yf1 = Lerp(xf01, xf11, ys);
+
+ return Lerp(yf0, yf1, zs) * 0.964921414852142333984375f;
+ }
+
+
+ // Value Cubic Noise
+
+ template <typename FNfloat>
+ float SingleValueCubic(int seed, FNfloat x, FNfloat y) const
+ {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+
+ float xs = (float)(x - x1);
+ float ys = (float)(y - y1);
+
+ x1 *= PrimeX;
+ y1 *= PrimeY;
+ int x0 = x1 - PrimeX;
+ int y0 = y1 - PrimeY;
+ int x2 = x1 + PrimeX;
+ int y2 = y1 + PrimeY;
+ int x3 = x1 + (int)((long)PrimeX << 1);
+ int y3 = y1 + (int)((long)PrimeY << 1);
+
+ return CubicLerp(
+ CubicLerp(ValCoord(seed, x0, y0), ValCoord(seed, x1, y0), ValCoord(seed, x2, y0), ValCoord(seed, x3, y0),
+ xs),
+ CubicLerp(ValCoord(seed, x0, y1), ValCoord(seed, x1, y1), ValCoord(seed, x2, y1), ValCoord(seed, x3, y1),
+ xs),
+ CubicLerp(ValCoord(seed, x0, y2), ValCoord(seed, x1, y2), ValCoord(seed, x2, y2), ValCoord(seed, x3, y2),
+ xs),
+ CubicLerp(ValCoord(seed, x0, y3), ValCoord(seed, x1, y3), ValCoord(seed, x2, y3), ValCoord(seed, x3, y3),
+ xs),
+ ys) * (1 / (1.5f * 1.5f));
+ }
+
+ template <typename FNfloat>
+ float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+ int z1 = FastFloor(z);
+
+ float xs = (float)(x - x1);
+ float ys = (float)(y - y1);
+ float zs = (float)(z - z1);
+
+ x1 *= PrimeX;
+ y1 *= PrimeY;
+ z1 *= PrimeZ;
+
+ int x0 = x1 - PrimeX;
+ int y0 = y1 - PrimeY;
+ int z0 = z1 - PrimeZ;
+ int x2 = x1 + PrimeX;
+ int y2 = y1 + PrimeY;
+ int z2 = z1 + PrimeZ;
+ int x3 = x1 + (int)((long)PrimeX << 1);
+ int y3 = y1 + (int)((long)PrimeY << 1);
+ int z3 = z1 + (int)((long)PrimeZ << 1);
+
+
+ return CubicLerp(
+ CubicLerp(
+ CubicLerp(ValCoord(seed, x0, y0, z0), ValCoord(seed, x1, y0, z0), ValCoord(seed, x2, y0, z0), ValCoord(seed, x3, y0, z0), xs),
+ CubicLerp(ValCoord(seed, x0, y1, z0), ValCoord(seed, x1, y1, z0), ValCoord(seed, x2, y1, z0), ValCoord(seed, x3, y1, z0), xs),
+ CubicLerp(ValCoord(seed, x0, y2, z0), ValCoord(seed, x1, y2, z0), ValCoord(seed, x2, y2, z0), ValCoord(seed, x3, y2, z0), xs),
+ CubicLerp(ValCoord(seed, x0, y3, z0), ValCoord(seed, x1, y3, z0), ValCoord(seed, x2, y3, z0), ValCoord(seed, x3, y3, z0), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord(seed, x0, y0, z1), ValCoord(seed, x1, y0, z1), ValCoord(seed, x2, y0, z1), ValCoord(seed, x3, y0, z1), xs),
+ CubicLerp(ValCoord(seed, x0, y1, z1), ValCoord(seed, x1, y1, z1), ValCoord(seed, x2, y1, z1), ValCoord(seed, x3, y1, z1), xs),
+ CubicLerp(ValCoord(seed, x0, y2, z1), ValCoord(seed, x1, y2, z1), ValCoord(seed, x2, y2, z1), ValCoord(seed, x3, y2, z1), xs),
+ CubicLerp(ValCoord(seed, x0, y3, z1), ValCoord(seed, x1, y3, z1), ValCoord(seed, x2, y3, z1), ValCoord(seed, x3, y3, z1), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord(seed, x0, y0, z2), ValCoord(seed, x1, y0, z2), ValCoord(seed, x2, y0, z2), ValCoord(seed, x3, y0, z2), xs),
+ CubicLerp(ValCoord(seed, x0, y1, z2), ValCoord(seed, x1, y1, z2), ValCoord(seed, x2, y1, z2), ValCoord(seed, x3, y1, z2), xs),
+ CubicLerp(ValCoord(seed, x0, y2, z2), ValCoord(seed, x1, y2, z2), ValCoord(seed, x2, y2, z2), ValCoord(seed, x3, y2, z2), xs),
+ CubicLerp(ValCoord(seed, x0, y3, z2), ValCoord(seed, x1, y3, z2), ValCoord(seed, x2, y3, z2), ValCoord(seed, x3, y3, z2), xs),
+ ys),
+ CubicLerp(
+ CubicLerp(ValCoord(seed, x0, y0, z3), ValCoord(seed, x1, y0, z3), ValCoord(seed, x2, y0, z3), ValCoord(seed, x3, y0, z3), xs),
+ CubicLerp(ValCoord(seed, x0, y1, z3), ValCoord(seed, x1, y1, z3), ValCoord(seed, x2, y1, z3), ValCoord(seed, x3, y1, z3), xs),
+ CubicLerp(ValCoord(seed, x0, y2, z3), ValCoord(seed, x1, y2, z3), ValCoord(seed, x2, y2, z3), ValCoord(seed, x3, y2, z3), xs),
+ CubicLerp(ValCoord(seed, x0, y3, z3), ValCoord(seed, x1, y3, z3), ValCoord(seed, x2, y3, z3), ValCoord(seed, x3, y3, z3), xs),
+ ys),
+ zs) * (1 / (1.5f * 1.5f * 1.5f));
+ }
+
+
+ // Value Noise
+
+ template <typename FNfloat>
+ float SingleValue(int seed, FNfloat x, FNfloat y) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+
+ float xs = InterpHermite((float)(x - x0));
+ float ys = InterpHermite((float)(y - y0));
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+
+ float xf0 = Lerp(ValCoord(seed, x0, y0), ValCoord(seed, x1, y0), xs);
+ float xf1 = Lerp(ValCoord(seed, x0, y1), ValCoord(seed, x1, y1), xs);
+
+ return Lerp(xf0, xf1, ys);
+ }
+
+ template <typename FNfloat>
+ float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+ int z0 = FastFloor(z);
+
+ float xs = InterpHermite((float)(x - x0));
+ float ys = InterpHermite((float)(y - y0));
+ float zs = InterpHermite((float)(z - z0));
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ z0 *= PrimeZ;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+ int z1 = z0 + PrimeZ;
+
+ float xf00 = Lerp(ValCoord(seed, x0, y0, z0), ValCoord(seed, x1, y0, z0), xs);
+ float xf10 = Lerp(ValCoord(seed, x0, y1, z0), ValCoord(seed, x1, y1, z0), xs);
+ float xf01 = Lerp(ValCoord(seed, x0, y0, z1), ValCoord(seed, x1, y0, z1), xs);
+ float xf11 = Lerp(ValCoord(seed, x0, y1, z1), ValCoord(seed, x1, y1, z1), xs);
+
+ float yf0 = Lerp(xf00, xf10, ys);
+ float yf1 = Lerp(xf01, xf11, ys);
+
+ return Lerp(yf0, yf1, zs);
+ }
+
+
+ // Domain Warp
+
+ template <typename FNfloat>
+ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const
+ {
+ switch (mDomainWarpType)
+ {
+ case DomainWarpType_OpenSimplex2:
+ SingleDomainWarpSimplexGradient(seed, amp * 38.283687591552734375f, freq, x, y, xr, yr, false);
+ break;
+ case DomainWarpType_OpenSimplex2Reduced:
+ SingleDomainWarpSimplexGradient(seed, amp * 16.0f, freq, x, y, xr, yr, true);
+ break;
+ case DomainWarpType_BasicGrid:
+ SingleDomainWarpBasicGrid(seed, amp, freq, x, y, xr, yr);
+ break;
+ }
+ }
+
+ template <typename FNfloat>
+ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const
+ {
+ switch (mDomainWarpType)
+ {
+ case DomainWarpType_OpenSimplex2:
+ SingleDomainWarpOpenSimplex2Gradient(seed, amp * 32.69428253173828125f, freq, x, y, z, xr, yr, zr, false);
+ break;
+ case DomainWarpType_OpenSimplex2Reduced:
+ SingleDomainWarpOpenSimplex2Gradient(seed, amp * 7.71604938271605f, freq, x, y, z, xr, yr, zr, true);
+ break;
+ case DomainWarpType_BasicGrid:
+ SingleDomainWarpBasicGrid(seed, amp, freq, x, y, z, xr, yr, zr);
+ break;
+ }
+ }
+
+
+ // Domain Warp Single Wrapper
+
+ template <typename FNfloat>
+ void DomainWarpSingle(FNfloat& x, FNfloat& y) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ FNfloat xs = x;
+ FNfloat ys = y;
+ TransformDomainWarpCoordinate(xs, ys);
+
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, x, y);
+ }
+
+ template <typename FNfloat>
+ void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ FNfloat xs = x;
+ FNfloat ys = y;
+ FNfloat zs = z;
+ TransformDomainWarpCoordinate(xs, ys, zs);
+
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, zs, x, y, z);
+ }
+
+
+ // Domain Warp Fractal Progressive
+
+ template <typename FNfloat>
+ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+ TransformDomainWarpCoordinate(xs, ys);
+
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, x, y);
+
+ seed++;
+ amp *= mGain;
+ freq *= mLacunarity;
+ }
+ }
+
+ template <typename FNfloat>
+ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+ FNfloat zs = z;
+ TransformDomainWarpCoordinate(xs, ys, zs);
+
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, zs, x, y, z);
+
+ seed++;
+ amp *= mGain;
+ freq *= mLacunarity;
+ }
+ }
+
+
+ // Domain Warp Fractal Independant
+
+ template <typename FNfloat>
+ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+ TransformDomainWarpCoordinate(xs, ys);
+
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, x, y);
+
+ seed++;
+ amp *= mGain;
+ freq *= mLacunarity;
+ }
+ }
+
+ template <typename FNfloat>
+ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+ FNfloat zs = z;
+ TransformDomainWarpCoordinate(xs, ys, zs);
+
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+ float freq = mFrequency;
+
+ for (int i = 0; i < mOctaves; i++)
+ {
+ DoSingleDomainWarp(seed, amp, freq, xs, ys, zs, x, y, z);
+
+ seed++;
+ amp *= mGain;
+ freq *= mLacunarity;
+ }
+ }
+
+
+ // Domain Warp Basic Grid
+
+ template <typename FNfloat>
+ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const
+ {
+ FNfloat xf = x * frequency;
+ FNfloat yf = y * frequency;
+
+ int x0 = FastFloor(xf);
+ int y0 = FastFloor(yf);
+
+ float xs = InterpHermite((float)(xf - x0));
+ float ys = InterpHermite((float)(yf - y0));
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+
+ int hash0 = Hash(seed, x0, y0) & (255 << 1);
+ int hash1 = Hash(seed, x1, y0) & (255 << 1);
+
+ float lx0x = Lerp(Lookup<float>::RandVecs2D[hash0], Lookup<float>::RandVecs2D[hash1], xs);
+ float ly0x = Lerp(Lookup<float>::RandVecs2D[hash0 | 1], Lookup<float>::RandVecs2D[hash1 | 1], xs);
+
+ hash0 = Hash(seed, x0, y1) & (255 << 1);
+ hash1 = Hash(seed, x1, y1) & (255 << 1);
+
+ float lx1x = Lerp(Lookup<float>::RandVecs2D[hash0], Lookup<float>::RandVecs2D[hash1], xs);
+ float ly1x = Lerp(Lookup<float>::RandVecs2D[hash0 | 1], Lookup<float>::RandVecs2D[hash1 | 1], xs);
+
+ xr += Lerp(lx0x, lx1x, ys) * warpAmp;
+ yr += Lerp(ly0x, ly1x, ys) * warpAmp;
+ }
+
+ template <typename FNfloat>
+ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const
+ {
+ FNfloat xf = x * frequency;
+ FNfloat yf = y * frequency;
+ FNfloat zf = z * frequency;
+
+ int x0 = FastFloor(xf);
+ int y0 = FastFloor(yf);
+ int z0 = FastFloor(zf);
+
+ float xs = InterpHermite((float)(xf - x0));
+ float ys = InterpHermite((float)(yf - y0));
+ float zs = InterpHermite((float)(zf - z0));
+
+ x0 *= PrimeX;
+ y0 *= PrimeY;
+ z0 *= PrimeZ;
+ int x1 = x0 + PrimeX;
+ int y1 = y0 + PrimeY;
+ int z1 = z0 + PrimeZ;
+
+ int hash0 = Hash(seed, x0, y0, z0) & (255 << 2);
+ int hash1 = Hash(seed, x1, y0, z0) & (255 << 2);
+
+ float lx0x = Lerp(Lookup<float>::RandVecs3D[hash0], Lookup<float>::RandVecs3D[hash1], xs);
+ float ly0x = Lerp(Lookup<float>::RandVecs3D[hash0 | 1], Lookup<float>::RandVecs3D[hash1 | 1], xs);
+ float lz0x = Lerp(Lookup<float>::RandVecs3D[hash0 | 2], Lookup<float>::RandVecs3D[hash1 | 2], xs);
+
+ hash0 = Hash(seed, x0, y1, z0) & (255 << 2);
+ hash1 = Hash(seed, x1, y1, z0) & (255 << 2);
+
+ float lx1x = Lerp(Lookup<float>::RandVecs3D[hash0], Lookup<float>::RandVecs3D[hash1], xs);
+ float ly1x = Lerp(Lookup<float>::RandVecs3D[hash0 | 1], Lookup<float>::RandVecs3D[hash1 | 1], xs);
+ float lz1x = Lerp(Lookup<float>::RandVecs3D[hash0 | 2], Lookup<float>::RandVecs3D[hash1 | 2], xs);
+
+ float lx0y = Lerp(lx0x, lx1x, ys);
+ float ly0y = Lerp(ly0x, ly1x, ys);
+ float lz0y = Lerp(lz0x, lz1x, ys);
+
+ hash0 = Hash(seed, x0, y0, z1) & (255 << 2);
+ hash1 = Hash(seed, x1, y0, z1) & (255 << 2);
+
+ lx0x = Lerp(Lookup<float>::RandVecs3D[hash0], Lookup<float>::RandVecs3D[hash1], xs);
+ ly0x = Lerp(Lookup<float>::RandVecs3D[hash0 | 1], Lookup<float>::RandVecs3D[hash1 | 1], xs);
+ lz0x = Lerp(Lookup<float>::RandVecs3D[hash0 | 2], Lookup<float>::RandVecs3D[hash1 | 2], xs);
+
+ hash0 = Hash(seed, x0, y1, z1) & (255 << 2);
+ hash1 = Hash(seed, x1, y1, z1) & (255 << 2);
+
+ lx1x = Lerp(Lookup<float>::RandVecs3D[hash0], Lookup<float>::RandVecs3D[hash1], xs);
+ ly1x = Lerp(Lookup<float>::RandVecs3D[hash0 | 1], Lookup<float>::RandVecs3D[hash1 | 1], xs);
+ lz1x = Lerp(Lookup<float>::RandVecs3D[hash0 | 2], Lookup<float>::RandVecs3D[hash1 | 2], xs);
+
+ xr += Lerp(lx0y, Lerp(lx0x, lx1x, ys), zs) * warpAmp;
+ yr += Lerp(ly0y, Lerp(ly0x, ly1x, ys), zs) * warpAmp;
+ zr += Lerp(lz0y, Lerp(lz0x, lz1x, ys), zs) * warpAmp;
+ }
+
+
+ // Domain Warp Simplex/OpenSimplex2
+
+ template <typename FNfloat>
+ void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const
+ {
+ const float SQRT3 = 1.7320508075688772935274463415059f;
+ const float G2 = (3 - SQRT3) / 6;
+
+ x *= frequency;
+ y *= frequency;
+
+ /*
+ * --- Skew moved to TransformNoiseCoordinate method ---
+ * const FNfloat F2 = 0.5f * (SQRT3 - 1);
+ * FNfloat s = (x + y) * F2;
+ * x += s; y += s;
+ */
+
+ int i = FastFloor(x);
+ int j = FastFloor(y);
+ float xi = (float)(x - i);
+ float yi = (float)(y - j);
+
+ float t = (xi + yi) * G2;
+ float x0 = (float)(xi - t);
+ float y0 = (float)(yi - t);
+
+ i *= PrimeX;
+ j *= PrimeY;
+
+ float vx, vy;
+ vx = vy = 0;
+
+ float a = 0.5f - x0 * x0 - y0 * y0;
+ if (a > 0)
+ {
+ float aaaa = (a * a) * (a * a);
+ float xo, yo;
+ if (outGradOnly)
+ GradCoordOut(seed, i, j, xo, yo);
+ else
+ GradCoordDual(seed, i, j, x0, y0, xo, yo);
+ vx += aaaa * xo;
+ vy += aaaa * yo;
+ }
+
+ float c = (float)(2 * (1 - 2 * G2) * (1 / G2 - 2)) * t + ((float)(-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a);
+ if (c > 0)
+ {
+ float x2 = x0 + (2 * (float)G2 - 1);
+ float y2 = y0 + (2 * (float)G2 - 1);
+ float cccc = (c * c) * (c * c);
+ float xo, yo;
+ if (outGradOnly)
+ GradCoordOut(seed, i + PrimeX, j + PrimeY, xo, yo);
+ else
+ GradCoordDual(seed, i + PrimeX, j + PrimeY, x2, y2, xo, yo);
+ vx += cccc * xo;
+ vy += cccc * yo;
+ }
+
+ if (y0 > x0)
+ {
+ float x1 = x0 + (float)G2;
+ float y1 = y0 + ((float)G2 - 1);
+ float b = 0.5f - x1 * x1 - y1 * y1;
+ if (b > 0)
+ {
+ float bbbb = (b * b) * (b * b);
+ float xo, yo;
+ if (outGradOnly)
+ GradCoordOut(seed, i, j + PrimeY, xo, yo);
+ else
+ GradCoordDual(seed, i, j + PrimeY, x1, y1, xo, yo);
+ vx += bbbb * xo;
+ vy += bbbb * yo;
+ }
+ }
+ else
+ {
+ float x1 = x0 + ((float)G2 - 1);
+ float y1 = y0 + (float)G2;
+ float b = 0.5f - x1 * x1 - y1 * y1;
+ if (b > 0)
+ {
+ float bbbb = (b * b) * (b * b);
+ float xo, yo;
+ if (outGradOnly)
+ GradCoordOut(seed, i + PrimeX, j, xo, yo);
+ else
+ GradCoordDual(seed, i + PrimeX, j, x1, y1, xo, yo);
+ vx += bbbb * xo;
+ vy += bbbb * yo;
+ }
+ }
+
+ xr += vx * warpAmp;
+ yr += vy * warpAmp;
+ }
+
+ template <typename FNfloat>
+ void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const
+ {
+ x *= frequency;
+ y *= frequency;
+ z *= frequency;
+
+ /*
+ * --- Rotation moved to TransformDomainWarpCoordinate method ---
+ * const FNfloat R3 = (FNfloat)(2.0 / 3.0);
+ * FNfloat r = (x + y + z) * R3; // Rotation, not skew
+ * x = r - x; y = r - y; z = r - z;
+ */
+
+ int i = FastRound(x);
+ int j = FastRound(y);
+ int k = FastRound(z);
+ float x0 = (float)x - i;
+ float y0 = (float)y - j;
+ float z0 = (float)z - k;
+
+ int xNSign = (int)(-x0 - 1.0f) | 1;
+ int yNSign = (int)(-y0 - 1.0f) | 1;
+ int zNSign = (int)(-z0 - 1.0f) | 1;
+
+ float ax0 = xNSign * -x0;
+ float ay0 = yNSign * -y0;
+ float az0 = zNSign * -z0;
+
+ i *= PrimeX;
+ j *= PrimeY;
+ k *= PrimeZ;
+
+ float vx, vy, vz;
+ vx = vy = vz = 0;
+
+ float a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0);
+ for (int l = 0; l < 2; l++)
+ {
+ if (a > 0)
+ {
+ float aaaa = (a * a) * (a * a);
+ float xo, yo, zo;
+ if (outGradOnly)
+ GradCoordOut(seed, i, j, k, xo, yo, zo);
+ else
+ GradCoordDual(seed, i, j, k, x0, y0, z0, xo, yo, zo);
+ vx += aaaa * xo;
+ vy += aaaa * yo;
+ vz += aaaa * zo;
+ }
+
+ float b = a + 1;
+ int i1 = i;
+ int j1 = j;
+ int k1 = k;
+ float x1 = x0;
+ float y1 = y0;
+ float z1 = z0;
+
+ if (ax0 >= ay0 && ax0 >= az0)
+ {
+ x1 += xNSign;
+ b -= xNSign * 2 * x1;
+ i1 -= xNSign * PrimeX;
+ }
+ else if (ay0 > ax0 && ay0 >= az0)
+ {
+ y1 += yNSign;
+ b -= yNSign * 2 * y1;
+ j1 -= yNSign * PrimeY;
+ }
+ else
+ {
+ z1 += zNSign;
+ b -= zNSign * 2 * z1;
+ k1 -= zNSign * PrimeZ;
+ }
+
+ if (b > 0)
+ {
+ float bbbb = (b * b) * (b * b);
+ float xo, yo, zo;
+ if (outGradOnly)
+ GradCoordOut(seed, i1, j1, k1, xo, yo, zo);
+ else
+ GradCoordDual(seed, i1, j1, k1, x1, y1, z1, xo, yo, zo);
+ vx += bbbb * xo;
+ vy += bbbb * yo;
+ vz += bbbb * zo;
+ }
+
+ if (l == 1) break;
+
+ ax0 = 0.5f - ax0;
+ ay0 = 0.5f - ay0;
+ az0 = 0.5f - az0;
+
+ x0 = xNSign * ax0;
+ y0 = yNSign * ay0;
+ z0 = zNSign * az0;
+
+ a += (0.75f - ax0) - (ay0 + az0);
+
+ i += (xNSign >> 1) & PrimeX;
+ j += (yNSign >> 1) & PrimeY;
+ k += (zNSign >> 1) & PrimeZ;
+
+ xNSign = -xNSign;
+ yNSign = -yNSign;
+ zNSign = -zNSign;
+
+ seed += 1293373;
+ }
+
+ xr += vx * warpAmp;
+ yr += vy * warpAmp;
+ zr += vz * warpAmp;
+ }
+};
+
+template <>
+struct FastNoiseLite::Arguments_must_be_floating_point_values<float> {};
+template <>
+struct FastNoiseLite::Arguments_must_be_floating_point_values<double> {};
+template <>
+struct FastNoiseLite::Arguments_must_be_floating_point_values<long double> {};
+
+template <typename T>
+const T FastNoiseLite::Lookup<T>::Gradients2D[] =
+{
+ 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, 0.793353340291235f, 0.608761429008721f,
+ 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f,
+ 0.793353340291235f, -0.60876142900872f, 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f,
+ -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, -0.793353340291235f, -0.608761429008721f,
+ -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f,
+ -0.793353340291235f, 0.608761429008721f, -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f,
+ 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, 0.793353340291235f, 0.608761429008721f,
+ 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f,
+ 0.793353340291235f, -0.60876142900872f, 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f,
+ -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, -0.793353340291235f, -0.608761429008721f,
+ -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f,
+ -0.793353340291235f, 0.608761429008721f, -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f,
+ 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, 0.793353340291235f, 0.608761429008721f,
+ 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f,
+ 0.793353340291235f, -0.60876142900872f, 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f,
+ -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, -0.793353340291235f, -0.608761429008721f,
+ -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f,
+ -0.793353340291235f, 0.608761429008721f, -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f,
+ 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, 0.793353340291235f, 0.608761429008721f,
+ 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f,
+ 0.793353340291235f, -0.60876142900872f, 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f,
+ -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, -0.793353340291235f, -0.608761429008721f,
+ -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f,
+ -0.793353340291235f, 0.608761429008721f, -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f,
+ 0.130526192220052f, 0.99144486137381f, 0.38268343236509f, 0.923879532511287f, 0.608761429008721f, 0.793353340291235f, 0.793353340291235f, 0.608761429008721f,
+ 0.923879532511287f, 0.38268343236509f, 0.99144486137381f, 0.130526192220051f, 0.99144486137381f, -0.130526192220051f, 0.923879532511287f, -0.38268343236509f,
+ 0.793353340291235f, -0.60876142900872f, 0.608761429008721f, -0.793353340291235f, 0.38268343236509f, -0.923879532511287f, 0.130526192220052f, -0.99144486137381f,
+ -0.130526192220052f, -0.99144486137381f, -0.38268343236509f, -0.923879532511287f, -0.608761429008721f, -0.793353340291235f, -0.793353340291235f, -0.608761429008721f,
+ -0.923879532511287f, -0.38268343236509f, -0.99144486137381f, -0.130526192220052f, -0.99144486137381f, 0.130526192220051f, -0.923879532511287f, 0.38268343236509f,
+ -0.793353340291235f, 0.608761429008721f, -0.608761429008721f, 0.793353340291235f, -0.38268343236509f, 0.923879532511287f, -0.130526192220052f, 0.99144486137381f,
+ 0.38268343236509f, 0.923879532511287f, 0.923879532511287f, 0.38268343236509f, 0.923879532511287f, -0.38268343236509f, 0.38268343236509f, -0.923879532511287f,
+ -0.38268343236509f, -0.923879532511287f, -0.923879532511287f, -0.38268343236509f, -0.923879532511287f, 0.38268343236509f, -0.38268343236509f, 0.923879532511287f,
+};
+
+template <typename T>
+const T FastNoiseLite::Lookup<T>::RandVecs2D[] =
+{
+ -0.2700222198f, -0.9628540911f, 0.3863092627f, -0.9223693152f, 0.04444859006f, -0.999011673f, -0.5992523158f, -0.8005602176f, -0.7819280288f, 0.6233687174f, 0.9464672271f, 0.3227999196f, -0.6514146797f, -0.7587218957f, 0.9378472289f, 0.347048376f,
+ -0.8497875957f, -0.5271252623f, -0.879042592f, 0.4767432447f, -0.892300288f, -0.4514423508f, -0.379844434f, -0.9250503802f, -0.9951650832f, 0.0982163789f, 0.7724397808f, -0.6350880136f, 0.7573283322f, -0.6530343002f, -0.9928004525f, -0.119780055f,
+ -0.0532665713f, 0.9985803285f, 0.9754253726f, -0.2203300762f, -0.7665018163f, 0.6422421394f, 0.991636706f, 0.1290606184f, -0.994696838f, 0.1028503788f, -0.5379205513f, -0.84299554f, 0.5022815471f, -0.8647041387f, 0.4559821461f, -0.8899889226f,
+ -0.8659131224f, -0.5001944266f, 0.0879458407f, -0.9961252577f, -0.5051684983f, 0.8630207346f, 0.7753185226f, -0.6315704146f, -0.6921944612f, 0.7217110418f, -0.5191659449f, -0.8546734591f, 0.8978622882f, -0.4402764035f, -0.1706774107f, 0.9853269617f,
+ -0.9353430106f, -0.3537420705f, -0.9992404798f, 0.03896746794f, -0.2882064021f, -0.9575683108f, -0.9663811329f, 0.2571137995f, -0.8759714238f, -0.4823630009f, -0.8303123018f, -0.5572983775f, 0.05110133755f, -0.9986934731f, -0.8558373281f, -0.5172450752f,
+ 0.09887025282f, 0.9951003332f, 0.9189016087f, 0.3944867976f, -0.2439375892f, -0.9697909324f, -0.8121409387f, -0.5834613061f, -0.9910431363f, 0.1335421355f, 0.8492423985f, -0.5280031709f, -0.9717838994f, -0.2358729591f, 0.9949457207f, 0.1004142068f,
+ 0.6241065508f, -0.7813392434f, 0.662910307f, 0.7486988212f, -0.7197418176f, 0.6942418282f, -0.8143370775f, -0.5803922158f, 0.104521054f, -0.9945226741f, -0.1065926113f, -0.9943027784f, 0.445799684f, -0.8951327509f, 0.105547406f, 0.9944142724f,
+ -0.992790267f, 0.1198644477f, -0.8334366408f, 0.552615025f, 0.9115561563f, -0.4111755999f, 0.8285544909f, -0.5599084351f, 0.7217097654f, -0.6921957921f, 0.4940492677f, -0.8694339084f, -0.3652321272f, -0.9309164803f, -0.9696606758f, 0.2444548501f,
+ 0.08925509731f, -0.996008799f, 0.5354071276f, -0.8445941083f, -0.1053576186f, 0.9944343981f, -0.9890284586f, 0.1477251101f, 0.004856104961f, 0.9999882091f, 0.9885598478f, 0.1508291331f, 0.9286129562f, -0.3710498316f, -0.5832393863f, -0.8123003252f,
+ 0.3015207509f, 0.9534596146f, -0.9575110528f, 0.2883965738f, 0.9715802154f, -0.2367105511f, 0.229981792f, 0.9731949318f, 0.955763816f, -0.2941352207f, 0.740956116f, 0.6715534485f, -0.9971513787f, -0.07542630764f, 0.6905710663f, -0.7232645452f,
+ -0.290713703f, -0.9568100872f, 0.5912777791f, -0.8064679708f, -0.9454592212f, -0.325740481f, 0.6664455681f, 0.74555369f, 0.6236134912f, 0.7817328275f, 0.9126993851f, -0.4086316587f, -0.8191762011f, 0.5735419353f, -0.8812745759f, -0.4726046147f,
+ 0.9953313627f, 0.09651672651f, 0.9855650846f, -0.1692969699f, -0.8495980887f, 0.5274306472f, 0.6174853946f, -0.7865823463f, 0.8508156371f, 0.52546432f, 0.9985032451f, -0.05469249926f, 0.1971371563f, -0.9803759185f, 0.6607855748f, -0.7505747292f,
+ -0.03097494063f, 0.9995201614f, -0.6731660801f, 0.739491331f, -0.7195018362f, -0.6944905383f, 0.9727511689f, 0.2318515979f, 0.9997059088f, -0.0242506907f, 0.4421787429f, -0.8969269532f, 0.9981350961f, -0.061043673f, -0.9173660799f, -0.3980445648f,
+ -0.8150056635f, -0.5794529907f, -0.8789331304f, 0.4769450202f, 0.0158605829f, 0.999874213f, -0.8095464474f, 0.5870558317f, -0.9165898907f, -0.3998286786f, -0.8023542565f, 0.5968480938f, -0.5176737917f, 0.8555780767f, -0.8154407307f, -0.5788405779f,
+ 0.4022010347f, -0.9155513791f, -0.9052556868f, -0.4248672045f, 0.7317445619f, 0.6815789728f, -0.5647632201f, -0.8252529947f, -0.8403276335f, -0.5420788397f, -0.9314281527f, 0.363925262f, 0.5238198472f, 0.8518290719f, 0.7432803869f, -0.6689800195f,
+ -0.985371561f, -0.1704197369f, 0.4601468731f, 0.88784281f, 0.825855404f, 0.5638819483f, 0.6182366099f, 0.7859920446f, 0.8331502863f, -0.553046653f, 0.1500307506f, 0.9886813308f, -0.662330369f, -0.7492119075f, -0.668598664f, 0.743623444f,
+ 0.7025606278f, 0.7116238924f, -0.5419389763f, -0.8404178401f, -0.3388616456f, 0.9408362159f, 0.8331530315f, 0.5530425174f, -0.2989720662f, -0.9542618632f, 0.2638522993f, 0.9645630949f, 0.124108739f, -0.9922686234f, -0.7282649308f, -0.6852956957f,
+ 0.6962500149f, 0.7177993569f, -0.9183535368f, 0.3957610156f, -0.6326102274f, -0.7744703352f, -0.9331891859f, -0.359385508f, -0.1153779357f, -0.9933216659f, 0.9514974788f, -0.3076565421f, -0.08987977445f, -0.9959526224f, 0.6678496916f, 0.7442961705f,
+ 0.7952400393f, -0.6062947138f, -0.6462007402f, -0.7631674805f, -0.2733598753f, 0.9619118351f, 0.9669590226f, -0.254931851f, -0.9792894595f, 0.2024651934f, -0.5369502995f, -0.8436138784f, -0.270036471f, -0.9628500944f, -0.6400277131f, 0.7683518247f,
+ -0.7854537493f, -0.6189203566f, 0.06005905383f, -0.9981948257f, -0.02455770378f, 0.9996984141f, -0.65983623f, 0.751409442f, -0.6253894466f, -0.7803127835f, -0.6210408851f, -0.7837781695f, 0.8348888491f, 0.5504185768f, -0.1592275245f, 0.9872419133f,
+ 0.8367622488f, 0.5475663786f, -0.8675753916f, -0.4973056806f, -0.2022662628f, -0.9793305667f, 0.9399189937f, 0.3413975472f, 0.9877404807f, -0.1561049093f, -0.9034455656f, 0.4287028224f, 0.1269804218f, -0.9919052235f, -0.3819600854f, 0.924178821f,
+ 0.9754625894f, 0.2201652486f, -0.3204015856f, -0.9472818081f, -0.9874760884f, 0.1577687387f, 0.02535348474f, -0.9996785487f, 0.4835130794f, -0.8753371362f, -0.2850799925f, -0.9585037287f, -0.06805516006f, -0.99768156f, -0.7885244045f, -0.6150034663f,
+ 0.3185392127f, -0.9479096845f, 0.8880043089f, 0.4598351306f, 0.6476921488f, -0.7619021462f, 0.9820241299f, 0.1887554194f, 0.9357275128f, -0.3527237187f, -0.8894895414f, 0.4569555293f, 0.7922791302f, 0.6101588153f, 0.7483818261f, 0.6632681526f,
+ -0.7288929755f, -0.6846276581f, 0.8729032783f, -0.4878932944f, 0.8288345784f, 0.5594937369f, 0.08074567077f, 0.9967347374f, 0.9799148216f, -0.1994165048f, -0.580730673f, -0.8140957471f, -0.4700049791f, -0.8826637636f, 0.2409492979f, 0.9705377045f,
+ 0.9437816757f, -0.3305694308f, -0.8927998638f, -0.4504535528f, -0.8069622304f, 0.5906030467f, 0.06258973166f, 0.9980393407f, -0.9312597469f, 0.3643559849f, 0.5777449785f, 0.8162173362f, -0.3360095855f, -0.941858566f, 0.697932075f, -0.7161639607f,
+ -0.002008157227f, -0.9999979837f, -0.1827294312f, -0.9831632392f, -0.6523911722f, 0.7578824173f, -0.4302626911f, -0.9027037258f, -0.9985126289f, -0.05452091251f, -0.01028102172f, -0.9999471489f, -0.4946071129f, 0.8691166802f, -0.2999350194f, 0.9539596344f,
+ 0.8165471961f, 0.5772786819f, 0.2697460475f, 0.962931498f, -0.7306287391f, -0.6827749597f, -0.7590952064f, -0.6509796216f, -0.907053853f, 0.4210146171f, -0.5104861064f, -0.8598860013f, 0.8613350597f, 0.5080373165f, 0.5007881595f, -0.8655698812f,
+ -0.654158152f, 0.7563577938f, -0.8382755311f, -0.545246856f, 0.6940070834f, 0.7199681717f, 0.06950936031f, 0.9975812994f, 0.1702942185f, -0.9853932612f, 0.2695973274f, 0.9629731466f, 0.5519612192f, -0.8338697815f, 0.225657487f, -0.9742067022f,
+ 0.4215262855f, -0.9068161835f, 0.4881873305f, -0.8727388672f, -0.3683854996f, -0.9296731273f, -0.9825390578f, 0.1860564427f, 0.81256471f, 0.5828709909f, 0.3196460933f, -0.9475370046f, 0.9570913859f, 0.2897862643f, -0.6876655497f, -0.7260276109f,
+ -0.9988770922f, -0.047376731f, -0.1250179027f, 0.992154486f, -0.8280133617f, 0.560708367f, 0.9324863769f, -0.3612051451f, 0.6394653183f, 0.7688199442f, -0.01623847064f, -0.9998681473f, -0.9955014666f, -0.09474613458f, -0.81453315f, 0.580117012f,
+ 0.4037327978f, -0.9148769469f, 0.9944263371f, 0.1054336766f, -0.1624711654f, 0.9867132919f, -0.9949487814f, -0.100383875f, -0.6995302564f, 0.7146029809f, 0.5263414922f, -0.85027327f, -0.5395221479f, 0.841971408f, 0.6579370318f, 0.7530729462f,
+ 0.01426758847f, -0.9998982128f, -0.6734383991f, 0.7392433447f, 0.639412098f, -0.7688642071f, 0.9211571421f, 0.3891908523f, -0.146637214f, -0.9891903394f, -0.782318098f, 0.6228791163f, -0.5039610839f, -0.8637263605f, -0.7743120191f, -0.6328039957f,
+};
+
+template <typename T>
+const T FastNoiseLite::Lookup<T>::Gradients3D[] =
+{
+ 0, 1, 1, 0, 0,-1, 1, 0, 0, 1,-1, 0, 0,-1,-1, 0,
+ 1, 0, 1, 0, -1, 0, 1, 0, 1, 0,-1, 0, -1, 0,-1, 0,
+ 1, 1, 0, 0, -1, 1, 0, 0, 1,-1, 0, 0, -1,-1, 0, 0,
+ 0, 1, 1, 0, 0,-1, 1, 0, 0, 1,-1, 0, 0,-1,-1, 0,
+ 1, 0, 1, 0, -1, 0, 1, 0, 1, 0,-1, 0, -1, 0,-1, 0,
+ 1, 1, 0, 0, -1, 1, 0, 0, 1,-1, 0, 0, -1,-1, 0, 0,
+ 0, 1, 1, 0, 0,-1, 1, 0, 0, 1,-1, 0, 0,-1,-1, 0,
+ 1, 0, 1, 0, -1, 0, 1, 0, 1, 0,-1, 0, -1, 0,-1, 0,
+ 1, 1, 0, 0, -1, 1, 0, 0, 1,-1, 0, 0, -1,-1, 0, 0,
+ 0, 1, 1, 0, 0,-1, 1, 0, 0, 1,-1, 0, 0,-1,-1, 0,
+ 1, 0, 1, 0, -1, 0, 1, 0, 1, 0,-1, 0, -1, 0,-1, 0,
+ 1, 1, 0, 0, -1, 1, 0, 0, 1,-1, 0, 0, -1,-1, 0, 0,
+ 0, 1, 1, 0, 0,-1, 1, 0, 0, 1,-1, 0, 0,-1,-1, 0,
+ 1, 0, 1, 0, -1, 0, 1, 0, 1, 0,-1, 0, -1, 0,-1, 0,
+ 1, 1, 0, 0, -1, 1, 0, 0, 1,-1, 0, 0, -1,-1, 0, 0,
+ 1, 1, 0, 0, 0,-1, 1, 0, -1, 1, 0, 0, 0,-1,-1, 0
+};
+
+template <typename T>
+const T FastNoiseLite::Lookup<T>::RandVecs3D[] =
+{
+ -0.7292736885f, -0.6618439697f, 0.1735581948f, 0, 0.790292081f, -0.5480887466f, -0.2739291014f, 0, 0.7217578935f, 0.6226212466f, -0.3023380997f, 0, 0.565683137f, -0.8208298145f, -0.0790000257f, 0, 0.760049034f, -0.5555979497f, -0.3370999617f, 0, 0.3713945616f, 0.5011264475f, 0.7816254623f, 0, -0.1277062463f, -0.4254438999f, -0.8959289049f, 0, -0.2881560924f, -0.5815838982f, 0.7607405838f, 0,
+ 0.5849561111f, -0.662820239f, -0.4674352136f, 0, 0.3307171178f, 0.0391653737f, 0.94291689f, 0, 0.8712121778f, -0.4113374369f, -0.2679381538f, 0, 0.580981015f, 0.7021915846f, 0.4115677815f, 0, 0.503756873f, 0.6330056931f, -0.5878203852f, 0, 0.4493712205f, 0.601390195f, 0.6606022552f, 0, -0.6878403724f, 0.09018890807f, -0.7202371714f, 0, -0.5958956522f, -0.6469350577f, 0.475797649f, 0,
+ -0.5127052122f, 0.1946921978f, -0.8361987284f, 0, -0.9911507142f, -0.05410276466f, -0.1212153153f, 0, -0.2149721042f, 0.9720882117f, -0.09397607749f, 0, -0.7518650936f, -0.5428057603f, 0.3742469607f, 0, 0.5237068895f, 0.8516377189f, -0.02107817834f, 0, 0.6333504779f, 0.1926167129f, -0.7495104896f, 0, -0.06788241606f, 0.3998305789f, 0.9140719259f, 0, -0.5538628599f, -0.4729896695f, -0.6852128902f, 0,
+ -0.7261455366f, -0.5911990757f, 0.3509933228f, 0, -0.9229274737f, -0.1782808786f, 0.3412049336f, 0, -0.6968815002f, 0.6511274338f, 0.3006480328f, 0, 0.9608044783f, -0.2098363234f, -0.1811724921f, 0, 0.06817146062f, -0.9743405129f, 0.2145069156f, 0, -0.3577285196f, -0.6697087264f, -0.6507845481f, 0, -0.1868621131f, 0.7648617052f, -0.6164974636f, 0, -0.6541697588f, 0.3967914832f, 0.6439087246f, 0,
+ 0.6993340405f, -0.6164538506f, 0.3618239211f, 0, -0.1546665739f, 0.6291283928f, 0.7617583057f, 0, -0.6841612949f, -0.2580482182f, -0.6821542638f, 0, 0.5383980957f, 0.4258654885f, 0.7271630328f, 0, -0.5026987823f, -0.7939832935f, -0.3418836993f, 0, 0.3202971715f, 0.2834415347f, 0.9039195862f, 0, 0.8683227101f, -0.0003762656404f, -0.4959995258f, 0, 0.791120031f, -0.08511045745f, 0.6057105799f, 0,
+ -0.04011016052f, -0.4397248749f, 0.8972364289f, 0, 0.9145119872f, 0.3579346169f, -0.1885487608f, 0, -0.9612039066f, -0.2756484276f, 0.01024666929f, 0, 0.6510361721f, -0.2877799159f, -0.7023778346f, 0, -0.2041786351f, 0.7365237271f, 0.644859585f, 0, -0.7718263711f, 0.3790626912f, 0.5104855816f, 0, -0.3060082741f, -0.7692987727f, 0.5608371729f, 0, 0.454007341f, -0.5024843065f, 0.7357899537f, 0,
+ 0.4816795475f, 0.6021208291f, -0.6367380315f, 0, 0.6961980369f, -0.3222197429f, 0.641469197f, 0, -0.6532160499f, -0.6781148932f, 0.3368515753f, 0, 0.5089301236f, -0.6154662304f, -0.6018234363f, 0, -0.1635919754f, -0.9133604627f, -0.372840892f, 0, 0.52408019f, -0.8437664109f, 0.1157505864f, 0, 0.5902587356f, 0.4983817807f, -0.6349883666f, 0, 0.5863227872f, 0.494764745f, 0.6414307729f, 0,
+ 0.6779335087f, 0.2341345225f, 0.6968408593f, 0, 0.7177054546f, -0.6858979348f, 0.120178631f, 0, -0.5328819713f, -0.5205125012f, 0.6671608058f, 0, -0.8654874251f, -0.0700727088f, -0.4960053754f, 0, -0.2861810166f, 0.7952089234f, 0.5345495242f, 0, -0.04849529634f, 0.9810836427f, -0.1874115585f, 0, -0.6358521667f, 0.6058348682f, 0.4781800233f, 0, 0.6254794696f, -0.2861619734f, 0.7258696564f, 0,
+ -0.2585259868f, 0.5061949264f, -0.8227581726f, 0, 0.02136306781f, 0.5064016808f, -0.8620330371f, 0, 0.200111773f, 0.8599263484f, 0.4695550591f, 0, 0.4743561372f, 0.6014985084f, -0.6427953014f, 0, 0.6622993731f, -0.5202474575f, -0.5391679918f, 0, 0.08084972818f, -0.6532720452f, 0.7527940996f, 0, -0.6893687501f, 0.0592860349f, 0.7219805347f, 0, -0.1121887082f, -0.9673185067f, 0.2273952515f, 0,
+ 0.7344116094f, 0.5979668656f, -0.3210532909f, 0, 0.5789393465f, -0.2488849713f, 0.7764570201f, 0, 0.6988182827f, 0.3557169806f, -0.6205791146f, 0, -0.8636845529f, -0.2748771249f, -0.4224826141f, 0, -0.4247027957f, -0.4640880967f, 0.777335046f, 0, 0.5257722489f, -0.8427017621f, 0.1158329937f, 0, 0.9343830603f, 0.316302472f, -0.1639543925f, 0, -0.1016836419f, -0.8057303073f, -0.5834887393f, 0,
+ -0.6529238969f, 0.50602126f, -0.5635892736f, 0, -0.2465286165f, -0.9668205684f, -0.06694497494f, 0, -0.9776897119f, -0.2099250524f, -0.007368825344f, 0, 0.7736893337f, 0.5734244712f, 0.2694238123f, 0, -0.6095087895f, 0.4995678998f, 0.6155736747f, 0, 0.5794535482f, 0.7434546771f, 0.3339292269f, 0, -0.8226211154f, 0.08142581855f, 0.5627293636f, 0, -0.510385483f, 0.4703667658f, 0.7199039967f, 0,
+ -0.5764971849f, -0.07231656274f, -0.8138926898f, 0, 0.7250628871f, 0.3949971505f, -0.5641463116f, 0, -0.1525424005f, 0.4860840828f, -0.8604958341f, 0, -0.5550976208f, -0.4957820792f, 0.667882296f, 0, -0.1883614327f, 0.9145869398f, 0.357841725f, 0, 0.7625556724f, -0.5414408243f, -0.3540489801f, 0, -0.5870231946f, -0.3226498013f, -0.7424963803f, 0, 0.3051124198f, 0.2262544068f, -0.9250488391f, 0,
+ 0.6379576059f, 0.577242424f, -0.5097070502f, 0, -0.5966775796f, 0.1454852398f, -0.7891830656f, 0, -0.658330573f, 0.6555487542f, -0.3699414651f, 0, 0.7434892426f, 0.2351084581f, 0.6260573129f, 0, 0.5562114096f, 0.8264360377f, -0.0873632843f, 0, -0.3028940016f, -0.8251527185f, 0.4768419182f, 0, 0.1129343818f, -0.985888439f, -0.1235710781f, 0, 0.5937652891f, -0.5896813806f, 0.5474656618f, 0,
+ 0.6757964092f, -0.5835758614f, -0.4502648413f, 0, 0.7242302609f, -0.1152719764f, 0.6798550586f, 0, -0.9511914166f, 0.0753623979f, -0.2992580792f, 0, 0.2539470961f, -0.1886339355f, 0.9486454084f, 0, 0.571433621f, -0.1679450851f, -0.8032795685f, 0, -0.06778234979f, 0.3978269256f, 0.9149531629f, 0, 0.6074972649f, 0.733060024f, -0.3058922593f, 0, -0.5435478392f, 0.1675822484f, 0.8224791405f, 0,
+ -0.5876678086f, -0.3380045064f, -0.7351186982f, 0, -0.7967562402f, 0.04097822706f, -0.6029098428f, 0, -0.1996350917f, 0.8706294745f, 0.4496111079f, 0, -0.02787660336f, -0.9106232682f, -0.4122962022f, 0, -0.7797625996f, -0.6257634692f, 0.01975775581f, 0, -0.5211232846f, 0.7401644346f, -0.4249554471f, 0, 0.8575424857f, 0.4053272873f, -0.3167501783f, 0, 0.1045223322f, 0.8390195772f, -0.5339674439f, 0,
+ 0.3501822831f, 0.9242524096f, -0.1520850155f, 0, 0.1987849858f, 0.07647613266f, 0.9770547224f, 0, 0.7845996363f, 0.6066256811f, -0.1280964233f, 0, 0.09006737436f, -0.9750989929f, -0.2026569073f, 0, -0.8274343547f, -0.542299559f, 0.1458203587f, 0, -0.3485797732f, -0.415802277f, 0.840000362f, 0, -0.2471778936f, -0.7304819962f, -0.6366310879f, 0, -0.3700154943f, 0.8577948156f, 0.3567584454f, 0,
+ 0.5913394901f, -0.548311967f, -0.5913303597f, 0, 0.1204873514f, -0.7626472379f, -0.6354935001f, 0, 0.616959265f, 0.03079647928f, 0.7863922953f, 0, 0.1258156836f, -0.6640829889f, -0.7369967419f, 0, -0.6477565124f, -0.1740147258f, -0.7417077429f, 0, 0.6217889313f, -0.7804430448f, -0.06547655076f, 0, 0.6589943422f, -0.6096987708f, 0.4404473475f, 0, -0.2689837504f, -0.6732403169f, -0.6887635427f, 0,
+ -0.3849775103f, 0.5676542638f, 0.7277093879f, 0, 0.5754444408f, 0.8110471154f, -0.1051963504f, 0, 0.9141593684f, 0.3832947817f, 0.131900567f, 0, -0.107925319f, 0.9245493968f, 0.3654593525f, 0, 0.377977089f, 0.3043148782f, 0.8743716458f, 0, -0.2142885215f, -0.8259286236f, 0.5214617324f, 0, 0.5802544474f, 0.4148098596f, -0.7008834116f, 0, -0.1982660881f, 0.8567161266f, -0.4761596756f, 0,
+ -0.03381553704f, 0.3773180787f, -0.9254661404f, 0, -0.6867922841f, -0.6656597827f, 0.2919133642f, 0, 0.7731742607f, -0.2875793547f, -0.5652430251f, 0, -0.09655941928f, 0.9193708367f, -0.3813575004f, 0, 0.2715702457f, -0.9577909544f, -0.09426605581f, 0, 0.2451015704f, -0.6917998565f, -0.6792188003f, 0, 0.977700782f, -0.1753855374f, 0.1155036542f, 0, -0.5224739938f, 0.8521606816f, 0.02903615945f, 0,
+ -0.7734880599f, -0.5261292347f, 0.3534179531f, 0, -0.7134492443f, -0.269547243f, 0.6467878011f, 0, 0.1644037271f, 0.5105846203f, -0.8439637196f, 0, 0.6494635788f, 0.05585611296f, 0.7583384168f, 0, -0.4711970882f, 0.5017280509f, -0.7254255765f, 0, -0.6335764307f, -0.2381686273f, -0.7361091029f, 0, -0.9021533097f, -0.270947803f, -0.3357181763f, 0, -0.3793711033f, 0.872258117f, 0.3086152025f, 0,
+ -0.6855598966f, -0.3250143309f, 0.6514394162f, 0, 0.2900942212f, -0.7799057743f, -0.5546100667f, 0, -0.2098319339f, 0.85037073f, 0.4825351604f, 0, -0.4592603758f, 0.6598504336f, -0.5947077538f, 0, 0.8715945488f, 0.09616365406f, -0.4807031248f, 0, -0.6776666319f, 0.7118504878f, -0.1844907016f, 0, 0.7044377633f, 0.312427597f, 0.637304036f, 0, -0.7052318886f, -0.2401093292f, -0.6670798253f, 0,
+ 0.081921007f, -0.7207336136f, -0.6883545647f, 0, -0.6993680906f, -0.5875763221f, -0.4069869034f, 0, -0.1281454481f, 0.6419895885f, 0.7559286424f, 0, -0.6337388239f, -0.6785471501f, -0.3714146849f, 0, 0.5565051903f, -0.2168887573f, -0.8020356851f, 0, -0.5791554484f, 0.7244372011f, -0.3738578718f, 0, 0.1175779076f, -0.7096451073f, 0.6946792478f, 0, -0.6134619607f, 0.1323631078f, 0.7785527795f, 0,
+ 0.6984635305f, -0.02980516237f, -0.715024719f, 0, 0.8318082963f, -0.3930171956f, 0.3919597455f, 0, 0.1469576422f, 0.05541651717f, -0.9875892167f, 0, 0.708868575f, -0.2690503865f, 0.6520101478f, 0, 0.2726053183f, 0.67369766f, -0.68688995f, 0, -0.6591295371f, 0.3035458599f, -0.6880466294f, 0, 0.4815131379f, -0.7528270071f, 0.4487723203f, 0, 0.9430009463f, 0.1675647412f, -0.2875261255f, 0,
+ 0.434802957f, 0.7695304522f, -0.4677277752f, 0, 0.3931996188f, 0.594473625f, 0.7014236729f, 0, 0.7254336655f, -0.603925654f, 0.3301814672f, 0, 0.7590235227f, -0.6506083235f, 0.02433313207f, 0, -0.8552768592f, -0.3430042733f, 0.3883935666f, 0, -0.6139746835f, 0.6981725247f, 0.3682257648f, 0, -0.7465905486f, -0.5752009504f, 0.3342849376f, 0, 0.5730065677f, 0.810555537f, -0.1210916791f, 0,
+ -0.9225877367f, -0.3475211012f, -0.167514036f, 0, -0.7105816789f, -0.4719692027f, -0.5218416899f, 0, -0.08564609717f, 0.3583001386f, 0.929669703f, 0, -0.8279697606f, -0.2043157126f, 0.5222271202f, 0, 0.427944023f, 0.278165994f, 0.8599346446f, 0, 0.5399079671f, -0.7857120652f, -0.3019204161f, 0, 0.5678404253f, -0.5495413974f, -0.6128307303f, 0, -0.9896071041f, 0.1365639107f, -0.04503418428f, 0,
+ -0.6154342638f, -0.6440875597f, 0.4543037336f, 0, 0.1074204368f, -0.7946340692f, 0.5975094525f, 0, -0.3595449969f, -0.8885529948f, 0.28495784f, 0, -0.2180405296f, 0.1529888965f, 0.9638738118f, 0, -0.7277432317f, -0.6164050508f, -0.3007234646f, 0, 0.7249729114f, -0.00669719484f, 0.6887448187f, 0, -0.5553659455f, -0.5336586252f, 0.6377908264f, 0, 0.5137558015f, 0.7976208196f, -0.3160000073f, 0,
+ -0.3794024848f, 0.9245608561f, -0.03522751494f, 0, 0.8229248658f, 0.2745365933f, -0.4974176556f, 0, -0.5404114394f, 0.6091141441f, 0.5804613989f, 0, 0.8036581901f, -0.2703029469f, 0.5301601931f, 0, 0.6044318879f, 0.6832968393f, 0.4095943388f, 0, 0.06389988817f, 0.9658208605f, -0.2512108074f, 0, 0.1087113286f, 0.7402471173f, -0.6634877936f, 0, -0.713427712f, -0.6926784018f, 0.1059128479f, 0,
+ 0.6458897819f, -0.5724548511f, -0.5050958653f, 0, -0.6553931414f, 0.7381471625f, 0.159995615f, 0, 0.3910961323f, 0.9188871375f, -0.05186755998f, 0, -0.4879022471f, -0.5904376907f, 0.6429111375f, 0, 0.6014790094f, 0.7707441366f, -0.2101820095f, 0, -0.5677173047f, 0.7511360995f, 0.3368851762f, 0, 0.7858573506f, 0.226674665f, 0.5753666838f, 0, -0.4520345543f, -0.604222686f, -0.6561857263f, 0,
+ 0.002272116345f, 0.4132844051f, -0.9105991643f, 0, -0.5815751419f, -0.5162925989f, 0.6286591339f, 0, -0.03703704785f, 0.8273785755f, 0.5604221175f, 0, -0.5119692504f, 0.7953543429f, -0.3244980058f, 0, -0.2682417366f, -0.9572290247f, -0.1084387619f, 0, -0.2322482736f, -0.9679131102f, -0.09594243324f, 0, 0.3554328906f, -0.8881505545f, 0.2913006227f, 0, 0.7346520519f, -0.4371373164f, 0.5188422971f, 0,
+ 0.9985120116f, 0.04659011161f, -0.02833944577f, 0, -0.3727687496f, -0.9082481361f, 0.1900757285f, 0, 0.91737377f, -0.3483642108f, 0.1925298489f, 0, 0.2714911074f, 0.4147529736f, -0.8684886582f, 0, 0.5131763485f, -0.7116334161f, 0.4798207128f, 0, -0.8737353606f, 0.18886992f, -0.4482350644f, 0, 0.8460043821f, -0.3725217914f, 0.3814499973f, 0, 0.8978727456f, -0.1780209141f, -0.4026575304f, 0,
+ 0.2178065647f, -0.9698322841f, -0.1094789531f, 0, -0.1518031304f, -0.7788918132f, -0.6085091231f, 0, -0.2600384876f, -0.4755398075f, -0.8403819825f, 0, 0.572313509f, -0.7474340931f, -0.3373418503f, 0, -0.7174141009f, 0.1699017182f, -0.6756111411f, 0, -0.684180784f, 0.02145707593f, -0.7289967412f, 0, -0.2007447902f, 0.06555605789f, -0.9774476623f, 0, -0.1148803697f, -0.8044887315f, 0.5827524187f, 0,
+ -0.7870349638f, 0.03447489231f, 0.6159443543f, 0, -0.2015596421f, 0.6859872284f, 0.6991389226f, 0, -0.08581082512f, -0.10920836f, -0.9903080513f, 0, 0.5532693395f, 0.7325250401f, -0.396610771f, 0, -0.1842489331f, -0.9777375055f, -0.1004076743f, 0, 0.0775473789f, -0.9111505856f, 0.4047110257f, 0, 0.1399838409f, 0.7601631212f, -0.6344734459f, 0, 0.4484419361f, -0.845289248f, 0.2904925424f, 0
+};
+
+}
+#endif // namespace fastnoiselite
diff --git a/thirdparty/noise/patches/FastNoiseLite.patch b/thirdparty/noise/patches/FastNoiseLite.patch
new file mode 100644
index 0000000000..3c835c7b06
--- /dev/null
+++ b/thirdparty/noise/patches/FastNoiseLite.patch
@@ -0,0 +1,455 @@
+--- orig/FastNoiseLite.h 1900-01-00 00:00:00 +0000
++++ noise/FastNoiseLite.h 1900-01-00 00:00:00 +0000
+@@ -52,6 +52,8 @@
+
+ #include <cmath>
+
++namespace fastnoiselite{
++
+ class FastNoiseLite
+ {
+ public:
+@@ -2583,4 +2585,5 @@
+ -0.7870349638f, 0.03447489231f, 0.6159443543f, 0, -0.2015596421f, 0.6859872284f, 0.6991389226f, 0, -0.08581082512f, -0.10920836f, -0.9903080513f, 0, 0.5532693395f, 0.7325250401f, -0.396610771f, 0, -0.1842489331f, -0.9777375055f, -0.1004076743f, 0, 0.0775473789f, -0.9111505856f, 0.4047110257f, 0, 0.1399838409f, 0.7601631212f, -0.6344734459f, 0, 0.4484419361f, -0.845289248f, 0.2904925424f, 0
+ };
+
+-#endif
++}
++#endif // namespace fastnoiselite
+@@ -295,7 +295,7 @@ public:
+ /// Noise output bounded between -1...1
+ /// </returns>
+ template <typename FNfloat>
+- float GetNoise(FNfloat x, FNfloat y)
++ float GetNoise(FNfloat x, FNfloat y) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+@@ -321,7 +321,7 @@ public:
+ /// Noise output bounded between -1...1
+ /// </returns>
+ template <typename FNfloat>
+- float GetNoise(FNfloat x, FNfloat y, FNfloat z)
++ float GetNoise(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+@@ -350,7 +350,7 @@ public:
+ /// noise = GetNoise(x, y)</code>
+ /// </example>
+ template <typename FNfloat>
+- void DomainWarp(FNfloat& x, FNfloat& y)
++ void DomainWarp(FNfloat& x, FNfloat& y) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+@@ -377,7 +377,7 @@ public:
+ /// noise = GetNoise(x, y, z)</code>
+ /// </example>
+ template <typename FNfloat>
+- void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z)
++ void DomainWarp(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ Arguments_must_be_floating_point_values<FNfloat>();
+
+@@ -528,7 +528,7 @@ private:
+ }
+
+
+- float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd)
++ float GradCoord(int seed, int xPrimed, int yPrimed, float xd, float yd) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ hash ^= hash >> 15;
+@@ -541,7 +541,7 @@ private:
+ }
+
+
+- float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd)
++ float GradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ hash ^= hash >> 15;
+@@ -555,7 +555,7 @@ private:
+ }
+
+
+- void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo)
++ void GradCoordOut(int seed, int xPrimed, int yPrimed, float& xo, float& yo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed) & (255 << 1);
+
+@@ -564,7 +564,7 @@ private:
+ }
+
+
+- void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo)
++ void GradCoordOut(int seed, int xPrimed, int yPrimed, int zPrimed, float& xo, float& yo, float& zo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed) & (255 << 2);
+
+@@ -574,7 +574,7 @@ private:
+ }
+
+
+- void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo)
++ void GradCoordDual(int seed, int xPrimed, int yPrimed, float xd, float yd, float& xo, float& yo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed);
+ int index1 = hash & (127 << 1);
+@@ -592,7 +592,7 @@ private:
+ }
+
+
+- void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo)
++ void GradCoordDual(int seed, int xPrimed, int yPrimed, int zPrimed, float xd, float yd, float zd, float& xo, float& yo, float& zo) const
+ {
+ int hash = Hash(seed, xPrimed, yPrimed, zPrimed);
+ int index1 = hash & (63 << 2);
+@@ -616,7 +616,7 @@ private:
+ // Generic noise gen
+
+ template <typename FNfloat>
+- float GenNoiseSingle(int seed, FNfloat x, FNfloat y)
++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y) const
+ {
+ switch (mNoiseType)
+ {
+@@ -638,7 +638,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float GenNoiseSingle(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ switch (mNoiseType)
+ {
+@@ -663,7 +663,7 @@ private:
+ // Noise Coordinate Transforms (frequency, and possible skew or rotation)
+
+ template <typename FNfloat>
+- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y)
++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y) const
+ {
+ x *= mFrequency;
+ y *= mFrequency;
+@@ -686,7 +686,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z)
++ void TransformNoiseCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ x *= mFrequency;
+ y *= mFrequency;
+@@ -757,7 +757,7 @@ private:
+ // Domain Warp Coordinate Transforms
+
+ template <typename FNfloat>
+- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y)
++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y) const
+ {
+ switch (mDomainWarpType)
+ {
+@@ -777,7 +777,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z)
++ void TransformDomainWarpCoordinate(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ switch (mWarpTransformType3D)
+ {
+@@ -844,7 +844,7 @@ private:
+ // Fractal FBm
+
+ template <typename FNfloat>
+- float GenFractalFBm(FNfloat x, FNfloat y)
++ float GenFractalFBm(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -865,7 +865,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z)
++ float GenFractalFBm(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -890,7 +890,7 @@ private:
+ // Fractal Ridged
+
+ template <typename FNfloat>
+- float GenFractalRidged(FNfloat x, FNfloat y)
++ float GenFractalRidged(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -911,7 +911,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z)
++ float GenFractalRidged(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -936,7 +936,7 @@ private:
+ // Fractal PingPong
+
+ template <typename FNfloat>
+- float GenFractalPingPong(FNfloat x, FNfloat y)
++ float GenFractalPingPong(FNfloat x, FNfloat y) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -957,7 +957,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z)
++ float GenFractalPingPong(FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int seed = mSeed;
+ float sum = 0;
+@@ -982,7 +982,7 @@ private:
+ // Simplex/OpenSimplex2 Noise
+
+ template <typename FNfloat>
+- float SingleSimplex(int seed, FNfloat x, FNfloat y)
++ float SingleSimplex(int seed, FNfloat x, FNfloat y) const
+ {
+ // 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex.
+
+@@ -1053,7 +1053,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SingleOpenSimplex2(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ // 3D OpenSimplex2 case uses two offset rotated cube grids.
+
+@@ -1155,7 +1155,7 @@ private:
+ // OpenSimplex2S Noise
+
+ template <typename FNfloat>
+- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y)
++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y) const
+ {
+ // 2D OpenSimplex2S case is a modified 2D simplex noise.
+
+@@ -1286,7 +1286,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SingleOpenSimplex2S(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ // 3D OpenSimplex2S case uses two offset rotated cube grids.
+
+@@ -1482,7 +1482,7 @@ private:
+ // Cellular Noise
+
+ template <typename FNfloat>
+- float SingleCellular(int seed, FNfloat x, FNfloat y)
++ float SingleCellular(int seed, FNfloat x, FNfloat y) const
+ {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+@@ -1612,7 +1612,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int xr = FastRound(x);
+ int yr = FastRound(y);
+@@ -1769,7 +1769,7 @@ private:
+ // Perlin Noise
+
+ template <typename FNfloat>
+- float SinglePerlin(int seed, FNfloat x, FNfloat y)
++ float SinglePerlin(int seed, FNfloat x, FNfloat y) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+@@ -1794,7 +1794,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SinglePerlin(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+@@ -1833,7 +1833,7 @@ private:
+ // Value Cubic Noise
+
+ template <typename FNfloat>
+- float SingleValueCubic(int seed, FNfloat x, FNfloat y)
++ float SingleValueCubic(int seed, FNfloat x, FNfloat y) const
+ {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+@@ -1863,7 +1863,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SingleValueCubic(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x1 = FastFloor(x);
+ int y1 = FastFloor(y);
+@@ -1920,7 +1920,7 @@ private:
+ // Value Noise
+
+ template <typename FNfloat>
+- float SingleValue(int seed, FNfloat x, FNfloat y)
++ float SingleValue(int seed, FNfloat x, FNfloat y) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+@@ -1940,7 +1940,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z)
++ float SingleValue(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+ int x0 = FastFloor(x);
+ int y0 = FastFloor(y);
+@@ -1972,7 +1972,7 @@ private:
+ // Domain Warp
+
+ template <typename FNfloat>
+- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr)
++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const
+ {
+ switch (mDomainWarpType)
+ {
+@@ -1989,7 +1989,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr)
++ void DoSingleDomainWarp(int seed, float amp, float freq, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const
+ {
+ switch (mDomainWarpType)
+ {
+@@ -2009,7 +2009,7 @@ private:
+ // Domain Warp Single Wrapper
+
+ template <typename FNfloat>
+- void DomainWarpSingle(FNfloat& x, FNfloat& y)
++ void DomainWarpSingle(FNfloat& x, FNfloat& y) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+@@ -2023,7 +2023,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z)
++ void DomainWarpSingle(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+@@ -2041,7 +2041,7 @@ private:
+ // Domain Warp Fractal Progressive
+
+ template <typename FNfloat>
+- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y)
++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+@@ -2062,7 +2062,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z)
++ void DomainWarpFractalProgressive(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ int seed = mSeed;
+ float amp = mDomainWarpAmp * mFractalBounding;
+@@ -2087,7 +2087,7 @@ private:
+ // Domain Warp Fractal Independant
+
+ template <typename FNfloat>
+- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y)
++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y) const
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+@@ -2108,7 +2108,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z)
++ void DomainWarpFractalIndependent(FNfloat& x, FNfloat& y, FNfloat& z) const
+ {
+ FNfloat xs = x;
+ FNfloat ys = y;
+@@ -2133,7 +2133,7 @@ private:
+ // Domain Warp Basic Grid
+
+ template <typename FNfloat>
+- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr)
++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr) const
+ {
+ FNfloat xf = x * frequency;
+ FNfloat yf = y * frequency;
+@@ -2166,7 +2166,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr)
++ void SingleDomainWarpBasicGrid(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr) const
+ {
+ FNfloat xf = x * frequency;
+ FNfloat yf = y * frequency;
+@@ -2228,7 +2228,7 @@ private:
+ // Domain Warp Simplex/OpenSimplex2
+
+ template <typename FNfloat>
+- void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly)
++ void SingleDomainWarpSimplexGradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat& xr, FNfloat& yr, bool outGradOnly) const
+ {
+ const float SQRT3 = 1.7320508075688772935274463415059f;
+ const float G2 = (3 - SQRT3) / 6;
+@@ -2326,7 +2326,7 @@ private:
+ }
+
+ template <typename FNfloat>
+- void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly)
++ void SingleDomainWarpOpenSimplex2Gradient(int seed, float warpAmp, float frequency, FNfloat x, FNfloat y, FNfloat z, FNfloat& xr, FNfloat& yr, FNfloat& zr, bool outGradOnly) const
+ {
+ x *= frequency;
+ y *= frequency;
+@@ -1611,6 +1611,12 @@ private:
+ }
+ }
+
++// GCC raises warnings when integer overflows occur, which are needed for hashing here.
++#if defined(__GNUC__) && !defined(__clang__)
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Waggressive-loop-optimizations"
++#endif
++
+ template <typename FNfloat>
+ float SingleCellular(int seed, FNfloat x, FNfloat y, FNfloat z) const
+ {
+@@ -1765,6 +1771,9 @@ private:
+ }
+ }
+
++#if defined(__GNUC__) && !defined(__clang__)
++#pragma GCC diagnostic pop
++#endif
+
+ // Perlin Noise
+ \ No newline at end of file
diff --git a/thirdparty/openxr/COPYING.adoc b/thirdparty/openxr/COPYING.adoc
new file mode 100644
index 0000000000..3a31362acb
--- /dev/null
+++ b/thirdparty/openxr/COPYING.adoc
@@ -0,0 +1,123 @@
+= COPYING.adoc for the Khronos Group OpenXR projects
+
+// Copyright (c) 2020-2022, The Khronos Group Inc.
+//
+// SPDX-License-Identifier: CC-BY-4.0
+
+This document is shared across a number of OpenXR GitHub projects, as the
+set of files in those projects is partially overlapping.
+(There is a single "source of truth" internal Khronos GitLab repo these
+GitHub repositories interact with.)
+
+== Licenses
+
+The OpenXR GitHub projects use several licenses.
+In general, we work to maintain compliance with the
+https://reuse.software/spec/[REUSE 3.0 specification] with clear copyright
+holders and license identifier listed for each file, preferably in each
+file.
+Where this is not possible, or e.g. when we are using files unmodified from
+other open-source projects, license data is listed:
+
+* in an adjacent file of the same name, with the additional extension
+ "`.license`"
+* in the repository-wide "`.reuse/dep5`" copyright description
+ https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/["DEP5"
+ machine-readable copyright data] file.
+
+The https://github.com/fsfe/reuse-tool["`reuse`" command line tool] can be
+used to create a software bill of materials in SPDX format from this data.
+Note that this tool will typically exclude the generated files, so if the
+BOM is important to you, you may consider using the
+https://github.com/KhronosGroup/OpenXR-SDK[OpenXR-SDK] repository that
+contains the API headers and the loader source with all generated files
+pre-generated.
+
+The data in/adjacent to each file is the authoritative license and copyright
+data.
+However, for ease of understanding, the following general practices can be
+observed.
+(If in doubt, or if the following summary conflicts with the per-file data,
+the per-file data remains authoritative.)
+
+* The source files (in asciidoctor and other formats) for the OpenXR
+ Specification, reference pages, and supporting documentation are licensed
+ under the Creative Commons Attribution 4.0 International License (SPDX
+ license identifier "`CC-BY-4.0`").
+* Header files, scripts, programs, XML files, and other tooling used or
+ generated as part of the build process is licensed under the Apache
+ License, Version 2.0.
+* For compatibility with external developers working in GPLed projects who
+ have requested it, the main OpenXR headers, XML registry, and loader
+ source are licensed under a dual license with the SPDX license identifier
+ "`Apache-2.0 OR MIT`" .
+ Relevant files include:
+** "`specification/registry/xr.xml`"
+** "`include/openxr/openxr_platform_defines.h`"
+** The generated OpenXR headers "`openxr.h`", "`openxr_platform.h`", and
+ "`openxr_reflection.h`".
+** Source files in "`src/loader/`", and a few files in "`src/common/`".
+** Generated source files used by the loader (including pre-generated in
+ OpenXR-SDK): "`common_config.h`", "`xr_generated_loader.cpp`", and
+ "`xr_generated_loader.hpp`".
+* There are a few files adopted from other open source projects.
+ Such files continue under their original licenses, and appropriately
+ annotated in accordance with REUSE.
+* Some generated, transient files produced during the course of building the
+ specification, headers, or other targets may not have copyrights.
+ These are typically very short asciidoc fragments describing parts of the
+ OpenXR API, and are incorporated by reference into specification or
+ reference page builds.
+
+Users outside Khronos who create and post OpenXR Specifications, whether
+modified or not, should use the CC-BY-4.0 license on the output documents
+(HTML, PDF, etc.) they generate.
+
+
+== Frequently Asked Questions
+
+Q: Why are the HTML and PDF Specifications posted on Khronos' website under
+a license which is neither CC-BY-4.0 nor Apache 2.0?
+
+A: The Specifications posted by Khronos in the OpenXR Registry are licensed
+under the proprietary Khronos Specification License.
+Only these Specifications are Ratified by the Khronos Board of Promoters,
+and therefore they are the only Specifications covered by the Khronos
+Intellectual Property Rights Policy.
+
+
+Q: Does Khronos allow the creation and distribution of modified versions of
+the OpenXR Specification, such as translations to other languages?
+
+A: Yes.
+Such modified Specifications, since they are not created by Khronos, should
+be placed under the CC-BY-4.0 license.
+If you believe your modifications are of general interest, consider
+contributing them back by making a pull request (PR) on the OpenXR-Docs
+project.
+
+
+Q: Can I contribute changes to the OpenXR Specification?
+
+A: Yes, by opening an Issue or Pull Request (PR) on the
+link:https://github.com/KhronosGroup/OpenXR-Docs/[OpenXR-Docs] GitHub
+project.
+You must execute a click-through Contributor License Agreement, which brings
+your changes under the umbrella of the Khronos IP policy.
+
+
+Q: Can you change the license on your files so they're compatible with my
+license?
+
+A: We are using a dual license license on `xr.xml`, the main API headers,
+and the loader source files, to make them compatible with GPL-2.0- and
+LGPL-2.0/2.1-licensed projects.
+This replaces earlier approaches of an MIT-like license on the XML and
+Apache 2.0 on all headers, and allows use of the SPDX license identifier
+"`Apache-2.0 OR MIT`" to denote the license.
+
+If you *require* this same compatibility for use of other Apache-2.0
+licensed files in our repository, please raise an issue identifying the
+files and we will consider changing those specific files to the dual license
+as well.
+
diff --git a/thirdparty/mbedtls/apache-2.0.txt b/thirdparty/openxr/LICENSE
index d645695673..d645695673 100644
--- a/thirdparty/mbedtls/apache-2.0.txt
+++ b/thirdparty/openxr/LICENSE
diff --git a/thirdparty/openxr/include/openxr/openxr.h b/thirdparty/openxr/include/openxr/openxr.h
new file mode 100644
index 0000000000..6c6a52d27e
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr.h
@@ -0,0 +1,4466 @@
+#ifndef OPENXR_H_
+#define OPENXR_H_ 1
+
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#define XR_VERSION_1_0 1
+#include "openxr_platform_defines.h"
+#define XR_MAKE_VERSION(major, minor, patch) \
+ ((((major) & 0xffffULL) << 48) | (((minor) & 0xffffULL) << 32) | ((patch) & 0xffffffffULL))
+
+// OpenXR current version number.
+#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 0, 23)
+
+#define XR_VERSION_MAJOR(version) (uint16_t)(((uint64_t)(version) >> 48)& 0xffffULL)
+#define XR_VERSION_MINOR(version) (uint16_t)(((uint64_t)(version) >> 32) & 0xffffULL)
+#define XR_VERSION_PATCH(version) (uint32_t)((uint64_t)(version) & 0xffffffffULL)
+
+#define XR_MIN_COMPOSITION_LAYERS_SUPPORTED 16
+
+
+#if !defined(XR_NULL_HANDLE)
+#if (XR_PTR_SIZE == 8) && XR_CPP_NULLPTR_SUPPORTED
+ #define XR_NULL_HANDLE nullptr
+#else
+ #define XR_NULL_HANDLE 0
+#endif
+#endif
+
+
+
+#define XR_NULL_SYSTEM_ID 0
+
+
+#define XR_NULL_PATH 0
+
+
+#define XR_SUCCEEDED(result) ((result) >= 0)
+
+
+#define XR_FAILED(result) ((result) < 0)
+
+
+#define XR_UNQUALIFIED_SUCCESS(result) ((result) == 0)
+
+
+#define XR_NO_DURATION 0
+
+
+#define XR_INFINITE_DURATION 0x7fffffffffffffffLL
+
+
+#define XR_MIN_HAPTIC_DURATION -1
+
+
+#define XR_FREQUENCY_UNSPECIFIED 0
+
+
+#define XR_MAX_EVENT_DATA_SIZE sizeof(XrEventDataBuffer)
+
+
+#if !defined(XR_MAY_ALIAS)
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 4))
+#define XR_MAY_ALIAS __attribute__((__may_alias__))
+#else
+#define XR_MAY_ALIAS
+#endif
+#endif
+
+
+#if !defined(XR_DEFINE_HANDLE)
+#if (XR_PTR_SIZE == 8)
+ #define XR_DEFINE_HANDLE(object) typedef struct object##_T* object;
+#else
+ #define XR_DEFINE_HANDLE(object) typedef uint64_t object;
+#endif
+#endif
+
+
+
+#if !defined(XR_DEFINE_ATOM)
+ #define XR_DEFINE_ATOM(object) typedef uint64_t object;
+#endif
+
+
+typedef uint64_t XrVersion;
+typedef uint64_t XrFlags64;
+XR_DEFINE_ATOM(XrSystemId)
+typedef uint32_t XrBool32;
+XR_DEFINE_ATOM(XrPath)
+typedef int64_t XrTime;
+typedef int64_t XrDuration;
+XR_DEFINE_HANDLE(XrInstance)
+XR_DEFINE_HANDLE(XrSession)
+XR_DEFINE_HANDLE(XrSpace)
+XR_DEFINE_HANDLE(XrAction)
+XR_DEFINE_HANDLE(XrSwapchain)
+XR_DEFINE_HANDLE(XrActionSet)
+#define XR_TRUE 1
+#define XR_FALSE 0
+#define XR_MAX_EXTENSION_NAME_SIZE 128
+#define XR_MAX_API_LAYER_NAME_SIZE 256
+#define XR_MAX_API_LAYER_DESCRIPTION_SIZE 256
+#define XR_MAX_SYSTEM_NAME_SIZE 256
+#define XR_MAX_APPLICATION_NAME_SIZE 128
+#define XR_MAX_ENGINE_NAME_SIZE 128
+#define XR_MAX_RUNTIME_NAME_SIZE 128
+#define XR_MAX_PATH_LENGTH 256
+#define XR_MAX_STRUCTURE_NAME_SIZE 64
+#define XR_MAX_RESULT_STRING_SIZE 64
+#define XR_MAX_ACTION_SET_NAME_SIZE 64
+#define XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE 128
+#define XR_MAX_ACTION_NAME_SIZE 64
+#define XR_MAX_LOCALIZED_ACTION_NAME_SIZE 128
+
+typedef enum XrResult {
+ XR_SUCCESS = 0,
+ XR_TIMEOUT_EXPIRED = 1,
+ XR_SESSION_LOSS_PENDING = 3,
+ XR_EVENT_UNAVAILABLE = 4,
+ XR_SPACE_BOUNDS_UNAVAILABLE = 7,
+ XR_SESSION_NOT_FOCUSED = 8,
+ XR_FRAME_DISCARDED = 9,
+ XR_ERROR_VALIDATION_FAILURE = -1,
+ XR_ERROR_RUNTIME_FAILURE = -2,
+ XR_ERROR_OUT_OF_MEMORY = -3,
+ XR_ERROR_API_VERSION_UNSUPPORTED = -4,
+ XR_ERROR_INITIALIZATION_FAILED = -6,
+ XR_ERROR_FUNCTION_UNSUPPORTED = -7,
+ XR_ERROR_FEATURE_UNSUPPORTED = -8,
+ XR_ERROR_EXTENSION_NOT_PRESENT = -9,
+ XR_ERROR_LIMIT_REACHED = -10,
+ XR_ERROR_SIZE_INSUFFICIENT = -11,
+ XR_ERROR_HANDLE_INVALID = -12,
+ XR_ERROR_INSTANCE_LOST = -13,
+ XR_ERROR_SESSION_RUNNING = -14,
+ XR_ERROR_SESSION_NOT_RUNNING = -16,
+ XR_ERROR_SESSION_LOST = -17,
+ XR_ERROR_SYSTEM_INVALID = -18,
+ XR_ERROR_PATH_INVALID = -19,
+ XR_ERROR_PATH_COUNT_EXCEEDED = -20,
+ XR_ERROR_PATH_FORMAT_INVALID = -21,
+ XR_ERROR_PATH_UNSUPPORTED = -22,
+ XR_ERROR_LAYER_INVALID = -23,
+ XR_ERROR_LAYER_LIMIT_EXCEEDED = -24,
+ XR_ERROR_SWAPCHAIN_RECT_INVALID = -25,
+ XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED = -26,
+ XR_ERROR_ACTION_TYPE_MISMATCH = -27,
+ XR_ERROR_SESSION_NOT_READY = -28,
+ XR_ERROR_SESSION_NOT_STOPPING = -29,
+ XR_ERROR_TIME_INVALID = -30,
+ XR_ERROR_REFERENCE_SPACE_UNSUPPORTED = -31,
+ XR_ERROR_FILE_ACCESS_ERROR = -32,
+ XR_ERROR_FILE_CONTENTS_INVALID = -33,
+ XR_ERROR_FORM_FACTOR_UNSUPPORTED = -34,
+ XR_ERROR_FORM_FACTOR_UNAVAILABLE = -35,
+ XR_ERROR_API_LAYER_NOT_PRESENT = -36,
+ XR_ERROR_CALL_ORDER_INVALID = -37,
+ XR_ERROR_GRAPHICS_DEVICE_INVALID = -38,
+ XR_ERROR_POSE_INVALID = -39,
+ XR_ERROR_INDEX_OUT_OF_RANGE = -40,
+ XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED = -41,
+ XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED = -42,
+ XR_ERROR_NAME_DUPLICATED = -44,
+ XR_ERROR_NAME_INVALID = -45,
+ XR_ERROR_ACTIONSET_NOT_ATTACHED = -46,
+ XR_ERROR_ACTIONSETS_ALREADY_ATTACHED = -47,
+ XR_ERROR_LOCALIZED_NAME_DUPLICATED = -48,
+ XR_ERROR_LOCALIZED_NAME_INVALID = -49,
+ XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING = -50,
+ XR_ERROR_RUNTIME_UNAVAILABLE = -51,
+ XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR = -1000003000,
+ XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR = -1000003001,
+ XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT = -1000039001,
+ XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT = -1000053000,
+ XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT = -1000055000,
+ XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT = -1000066000,
+ XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT = -1000097000,
+ XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT = -1000097001,
+ XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT = -1000097002,
+ XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT = -1000097003,
+ XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT = -1000097004,
+ XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT = -1000097005,
+ XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB = -1000101000,
+ XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB = -1000108000,
+ XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB = -1000113000,
+ XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB = -1000113001,
+ XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB = -1000113002,
+ XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB = -1000113003,
+ XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB = -1000118000,
+ XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB = -1000118001,
+ XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB = -1000118002,
+ XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB = -1000118003,
+ XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB = -1000118004,
+ XR_ERROR_UNKNOWN_PASSTHROUGH_FB = -1000118050,
+ XR_ERROR_RENDER_MODEL_KEY_INVALID_FB = -1000119000,
+ XR_RENDER_MODEL_UNAVAILABLE_FB = 1000119020,
+ XR_ERROR_MARKER_NOT_TRACKED_VARJO = -1000124000,
+ XR_ERROR_MARKER_ID_INVALID_VARJO = -1000124001,
+ XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT = -1000142001,
+ XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT = -1000142002,
+ XR_RESULT_MAX_ENUM = 0x7FFFFFFF
+} XrResult;
+
+typedef enum XrStructureType {
+ XR_TYPE_UNKNOWN = 0,
+ XR_TYPE_API_LAYER_PROPERTIES = 1,
+ XR_TYPE_EXTENSION_PROPERTIES = 2,
+ XR_TYPE_INSTANCE_CREATE_INFO = 3,
+ XR_TYPE_SYSTEM_GET_INFO = 4,
+ XR_TYPE_SYSTEM_PROPERTIES = 5,
+ XR_TYPE_VIEW_LOCATE_INFO = 6,
+ XR_TYPE_VIEW = 7,
+ XR_TYPE_SESSION_CREATE_INFO = 8,
+ XR_TYPE_SWAPCHAIN_CREATE_INFO = 9,
+ XR_TYPE_SESSION_BEGIN_INFO = 10,
+ XR_TYPE_VIEW_STATE = 11,
+ XR_TYPE_FRAME_END_INFO = 12,
+ XR_TYPE_HAPTIC_VIBRATION = 13,
+ XR_TYPE_EVENT_DATA_BUFFER = 16,
+ XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING = 17,
+ XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED = 18,
+ XR_TYPE_ACTION_STATE_BOOLEAN = 23,
+ XR_TYPE_ACTION_STATE_FLOAT = 24,
+ XR_TYPE_ACTION_STATE_VECTOR2F = 25,
+ XR_TYPE_ACTION_STATE_POSE = 27,
+ XR_TYPE_ACTION_SET_CREATE_INFO = 28,
+ XR_TYPE_ACTION_CREATE_INFO = 29,
+ XR_TYPE_INSTANCE_PROPERTIES = 32,
+ XR_TYPE_FRAME_WAIT_INFO = 33,
+ XR_TYPE_COMPOSITION_LAYER_PROJECTION = 35,
+ XR_TYPE_COMPOSITION_LAYER_QUAD = 36,
+ XR_TYPE_REFERENCE_SPACE_CREATE_INFO = 37,
+ XR_TYPE_ACTION_SPACE_CREATE_INFO = 38,
+ XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING = 40,
+ XR_TYPE_VIEW_CONFIGURATION_VIEW = 41,
+ XR_TYPE_SPACE_LOCATION = 42,
+ XR_TYPE_SPACE_VELOCITY = 43,
+ XR_TYPE_FRAME_STATE = 44,
+ XR_TYPE_VIEW_CONFIGURATION_PROPERTIES = 45,
+ XR_TYPE_FRAME_BEGIN_INFO = 46,
+ XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW = 48,
+ XR_TYPE_EVENT_DATA_EVENTS_LOST = 49,
+ XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING = 51,
+ XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED = 52,
+ XR_TYPE_INTERACTION_PROFILE_STATE = 53,
+ XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO = 55,
+ XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO = 56,
+ XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO = 57,
+ XR_TYPE_ACTION_STATE_GET_INFO = 58,
+ XR_TYPE_HAPTIC_ACTION_INFO = 59,
+ XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO = 60,
+ XR_TYPE_ACTIONS_SYNC_INFO = 61,
+ XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO = 62,
+ XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO = 63,
+ XR_TYPE_COMPOSITION_LAYER_CUBE_KHR = 1000006000,
+ XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR = 1000008000,
+ XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR = 1000010000,
+ XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR = 1000014000,
+ XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT = 1000015000,
+ XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR = 1000017000,
+ XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR = 1000018000,
+ XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT = 1000019000,
+ XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT = 1000019001,
+ XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT = 1000019002,
+ XR_TYPE_DEBUG_UTILS_LABEL_EXT = 1000019003,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR = 1000023000,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR = 1000023001,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR = 1000023002,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR = 1000023003,
+ XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR = 1000023004,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR = 1000023005,
+ XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR = 1000024001,
+ XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR = 1000024002,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR = 1000024003,
+ XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR = 1000025000,
+ XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR = 1000025001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR = 1000025002,
+ XR_TYPE_GRAPHICS_BINDING_D3D11_KHR = 1000027000,
+ XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR = 1000027001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR = 1000027002,
+ XR_TYPE_GRAPHICS_BINDING_D3D12_KHR = 1000028000,
+ XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR = 1000028001,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR = 1000028002,
+ XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT = 1000030000,
+ XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT = 1000030001,
+ XR_TYPE_VISIBILITY_MASK_KHR = 1000031000,
+ XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR = 1000031001,
+ XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX = 1000033000,
+ XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX = 1000033003,
+ XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR = 1000034000,
+ XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT = 1000039000,
+ XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT = 1000039001,
+ XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB = 1000040000,
+ XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB = 1000041001,
+ XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT = 1000046000,
+ XR_TYPE_GRAPHICS_BINDING_EGL_MNDX = 1000048004,
+ XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT = 1000049000,
+ XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT = 1000049001,
+ XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT = 1000049002,
+ XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT = 1000049003,
+ XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT = 1000051000,
+ XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT = 1000051001,
+ XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT = 1000051002,
+ XR_TYPE_HAND_JOINT_LOCATIONS_EXT = 1000051003,
+ XR_TYPE_HAND_JOINT_VELOCITIES_EXT = 1000051004,
+ XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT = 1000052000,
+ XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT = 1000052001,
+ XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT = 1000052002,
+ XR_TYPE_HAND_MESH_MSFT = 1000052003,
+ XR_TYPE_HAND_POSE_TYPE_INFO_MSFT = 1000052004,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT = 1000053000,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT = 1000053001,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT = 1000053002,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT = 1000053003,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT = 1000053004,
+ XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT = 1000053005,
+ XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT = 1000055000,
+ XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT = 1000055001,
+ XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT = 1000055002,
+ XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT = 1000055003,
+ XR_TYPE_CONTROLLER_MODEL_STATE_MSFT = 1000055004,
+ XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC = 1000059000,
+ XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT = 1000063000,
+ XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT = 1000066000,
+ XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT = 1000066001,
+ XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB = 1000070000,
+ XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB = 1000072000,
+ XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT = 1000078000,
+ XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE = 1000079000,
+ XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT = 1000080000,
+ XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR = 1000089000,
+ XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR = 1000090000,
+ XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR = 1000090001,
+ XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR = 1000090003,
+ XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR = 1000091000,
+ XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT = 1000097000,
+ XR_TYPE_SCENE_CREATE_INFO_MSFT = 1000097001,
+ XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT = 1000097002,
+ XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT = 1000097003,
+ XR_TYPE_SCENE_COMPONENTS_MSFT = 1000097004,
+ XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT = 1000097005,
+ XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT = 1000097006,
+ XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT = 1000097007,
+ XR_TYPE_SCENE_OBJECTS_MSFT = 1000097008,
+ XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT = 1000097009,
+ XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT = 1000097010,
+ XR_TYPE_SCENE_PLANES_MSFT = 1000097011,
+ XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT = 1000097012,
+ XR_TYPE_SCENE_MESHES_MSFT = 1000097013,
+ XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT = 1000097014,
+ XR_TYPE_SCENE_MESH_BUFFERS_MSFT = 1000097015,
+ XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT = 1000097016,
+ XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT = 1000097017,
+ XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT = 1000097018,
+ XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT = 1000098000,
+ XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT = 1000098001,
+ XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB = 1000101000,
+ XR_TYPE_VIVE_TRACKER_PATHS_HTCX = 1000103000,
+ XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX = 1000103001,
+ XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC = 1000104000,
+ XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC = 1000104001,
+ XR_TYPE_FACIAL_EXPRESSIONS_HTC = 1000104002,
+ XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB = 1000108000,
+ XR_TYPE_HAND_TRACKING_MESH_FB = 1000110001,
+ XR_TYPE_HAND_TRACKING_SCALE_FB = 1000110003,
+ XR_TYPE_HAND_TRACKING_AIM_STATE_FB = 1000111001,
+ XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB = 1000112000,
+ XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB = 1000113004,
+ XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB = 1000113003,
+ XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB = 1000113007,
+ XR_TYPE_SPACE_COMPONENT_STATUS_FB = 1000113001,
+ XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB = 1000113005,
+ XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB = 1000113006,
+ XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB = 1000114000,
+ XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB = 1000114001,
+ XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB = 1000114002,
+ XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB = 1000115000,
+ XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB = 1000116009,
+ XR_TYPE_KEYBOARD_TRACKING_QUERY_FB = 1000116004,
+ XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB = 1000116002,
+ XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB = 1000117001,
+ XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB = 1000118000,
+ XR_TYPE_PASSTHROUGH_CREATE_INFO_FB = 1000118001,
+ XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB = 1000118002,
+ XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB = 1000118003,
+ XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB = 1000118004,
+ XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB = 1000118005,
+ XR_TYPE_PASSTHROUGH_STYLE_FB = 1000118020,
+ XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB = 1000118021,
+ XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB = 1000118022,
+ XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB = 1000118023,
+ XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB = 1000118030,
+ XR_TYPE_RENDER_MODEL_PATH_INFO_FB = 1000119000,
+ XR_TYPE_RENDER_MODEL_PROPERTIES_FB = 1000119001,
+ XR_TYPE_RENDER_MODEL_BUFFER_FB = 1000119002,
+ XR_TYPE_RENDER_MODEL_LOAD_INFO_FB = 1000119003,
+ XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB = 1000119004,
+ XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB = 1000119005,
+ XR_TYPE_BINDING_MODIFICATIONS_KHR = 1000120000,
+ XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO = 1000121000,
+ XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO = 1000121001,
+ XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO = 1000121002,
+ XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO = 1000122000,
+ XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO = 1000124000,
+ XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO = 1000124001,
+ XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO = 1000124002,
+ XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT = 1000142000,
+ XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT = 1000142001,
+ XR_TYPE_SPACE_QUERY_INFO_FB = 1000156001,
+ XR_TYPE_SPACE_QUERY_RESULTS_FB = 1000156002,
+ XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB = 1000156003,
+ XR_TYPE_SPACE_UUID_FILTER_INFO_FB = 1000156054,
+ XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB = 1000156052,
+ XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB = 1000156103,
+ XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB = 1000156104,
+ XR_TYPE_SPACE_SAVE_INFO_FB = 1000158000,
+ XR_TYPE_SPACE_ERASE_INFO_FB = 1000158001,
+ XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB = 1000158106,
+ XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB = 1000158107,
+ XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB = 1000160000,
+ XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB = 1000161000,
+ XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB = 1000162000,
+ XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB = 1000163000,
+ XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB = 1000171000,
+ XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB = 1000171001,
+ XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE = 1000196000,
+ XR_TYPE_SPACE_CONTAINER_FB = 1000199000,
+ XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB = 1000203002,
+ XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB = 1000204000,
+ XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META = 1000227000,
+ XR_TYPE_PERFORMANCE_METRICS_STATE_META = 1000232001,
+ XR_TYPE_PERFORMANCE_METRICS_COUNTER_META = 1000232002,
+ XR_TYPE_GRAPHICS_BINDING_VULKAN2_KHR = XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR,
+ XR_TYPE_SWAPCHAIN_IMAGE_VULKAN2_KHR = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR,
+ XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR = XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR,
+ XR_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrStructureType;
+
+typedef enum XrFormFactor {
+ XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1,
+ XR_FORM_FACTOR_HANDHELD_DISPLAY = 2,
+ XR_FORM_FACTOR_MAX_ENUM = 0x7FFFFFFF
+} XrFormFactor;
+
+typedef enum XrViewConfigurationType {
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO = 1,
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO = 2,
+ XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO = 1000037000,
+ XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT = 1000054000,
+ XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrViewConfigurationType;
+
+typedef enum XrEnvironmentBlendMode {
+ XR_ENVIRONMENT_BLEND_MODE_OPAQUE = 1,
+ XR_ENVIRONMENT_BLEND_MODE_ADDITIVE = 2,
+ XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND = 3,
+ XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM = 0x7FFFFFFF
+} XrEnvironmentBlendMode;
+
+typedef enum XrReferenceSpaceType {
+ XR_REFERENCE_SPACE_TYPE_VIEW = 1,
+ XR_REFERENCE_SPACE_TYPE_LOCAL = 2,
+ XR_REFERENCE_SPACE_TYPE_STAGE = 3,
+ XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT = 1000038000,
+ XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO = 1000121000,
+ XR_REFERENCE_SPACE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrReferenceSpaceType;
+
+typedef enum XrActionType {
+ XR_ACTION_TYPE_BOOLEAN_INPUT = 1,
+ XR_ACTION_TYPE_FLOAT_INPUT = 2,
+ XR_ACTION_TYPE_VECTOR2F_INPUT = 3,
+ XR_ACTION_TYPE_POSE_INPUT = 4,
+ XR_ACTION_TYPE_VIBRATION_OUTPUT = 100,
+ XR_ACTION_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrActionType;
+
+typedef enum XrEyeVisibility {
+ XR_EYE_VISIBILITY_BOTH = 0,
+ XR_EYE_VISIBILITY_LEFT = 1,
+ XR_EYE_VISIBILITY_RIGHT = 2,
+ XR_EYE_VISIBILITY_MAX_ENUM = 0x7FFFFFFF
+} XrEyeVisibility;
+
+typedef enum XrSessionState {
+ XR_SESSION_STATE_UNKNOWN = 0,
+ XR_SESSION_STATE_IDLE = 1,
+ XR_SESSION_STATE_READY = 2,
+ XR_SESSION_STATE_SYNCHRONIZED = 3,
+ XR_SESSION_STATE_VISIBLE = 4,
+ XR_SESSION_STATE_FOCUSED = 5,
+ XR_SESSION_STATE_STOPPING = 6,
+ XR_SESSION_STATE_LOSS_PENDING = 7,
+ XR_SESSION_STATE_EXITING = 8,
+ XR_SESSION_STATE_MAX_ENUM = 0x7FFFFFFF
+} XrSessionState;
+
+typedef enum XrObjectType {
+ XR_OBJECT_TYPE_UNKNOWN = 0,
+ XR_OBJECT_TYPE_INSTANCE = 1,
+ XR_OBJECT_TYPE_SESSION = 2,
+ XR_OBJECT_TYPE_SWAPCHAIN = 3,
+ XR_OBJECT_TYPE_SPACE = 4,
+ XR_OBJECT_TYPE_ACTION_SET = 5,
+ XR_OBJECT_TYPE_ACTION = 6,
+ XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT = 1000019000,
+ XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT = 1000039000,
+ XR_OBJECT_TYPE_SPATIAL_GRAPH_NODE_BINDING_MSFT = 1000049000,
+ XR_OBJECT_TYPE_HAND_TRACKER_EXT = 1000051000,
+ XR_OBJECT_TYPE_SCENE_OBSERVER_MSFT = 1000097000,
+ XR_OBJECT_TYPE_SCENE_MSFT = 1000097001,
+ XR_OBJECT_TYPE_FACIAL_TRACKER_HTC = 1000104000,
+ XR_OBJECT_TYPE_FOVEATION_PROFILE_FB = 1000114000,
+ XR_OBJECT_TYPE_TRIANGLE_MESH_FB = 1000117000,
+ XR_OBJECT_TYPE_PASSTHROUGH_FB = 1000118000,
+ XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB = 1000118002,
+ XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB = 1000118004,
+ XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT = 1000142000,
+ XR_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} XrObjectType;
+typedef XrFlags64 XrInstanceCreateFlags;
+
+// Flag bits for XrInstanceCreateFlags
+
+typedef XrFlags64 XrSessionCreateFlags;
+
+// Flag bits for XrSessionCreateFlags
+
+typedef XrFlags64 XrSpaceVelocityFlags;
+
+// Flag bits for XrSpaceVelocityFlags
+static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_LINEAR_VALID_BIT = 0x00000001;
+static const XrSpaceVelocityFlags XR_SPACE_VELOCITY_ANGULAR_VALID_BIT = 0x00000002;
+
+typedef XrFlags64 XrSpaceLocationFlags;
+
+// Flag bits for XrSpaceLocationFlags
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_VALID_BIT = 0x00000001;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_VALID_BIT = 0x00000002;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT = 0x00000004;
+static const XrSpaceLocationFlags XR_SPACE_LOCATION_POSITION_TRACKED_BIT = 0x00000008;
+
+typedef XrFlags64 XrSwapchainCreateFlags;
+
+// Flag bits for XrSwapchainCreateFlags
+static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT = 0x00000001;
+static const XrSwapchainCreateFlags XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT = 0x00000002;
+
+typedef XrFlags64 XrSwapchainUsageFlags;
+
+// Flag bits for XrSwapchainUsageFlags
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT = 0x00000001;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000002;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT = 0x00000004;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT = 0x00000008;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT = 0x00000010;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_SAMPLED_BIT = 0x00000020;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT = 0x00000040;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND = 0x00000080;
+static const XrSwapchainUsageFlags XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR = 0x00000080; // alias of XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND
+
+typedef XrFlags64 XrCompositionLayerFlags;
+
+// Flag bits for XrCompositionLayerFlags
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT = 0x00000001;
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT = 0x00000002;
+static const XrCompositionLayerFlags XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT = 0x00000004;
+
+typedef XrFlags64 XrViewStateFlags;
+
+// Flag bits for XrViewStateFlags
+static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_VALID_BIT = 0x00000001;
+static const XrViewStateFlags XR_VIEW_STATE_POSITION_VALID_BIT = 0x00000002;
+static const XrViewStateFlags XR_VIEW_STATE_ORIENTATION_TRACKED_BIT = 0x00000004;
+static const XrViewStateFlags XR_VIEW_STATE_POSITION_TRACKED_BIT = 0x00000008;
+
+typedef XrFlags64 XrInputSourceLocalizedNameFlags;
+
+// Flag bits for XrInputSourceLocalizedNameFlags
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT = 0x00000001;
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT = 0x00000002;
+static const XrInputSourceLocalizedNameFlags XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT = 0x00000004;
+
+typedef void (XRAPI_PTR *PFN_xrVoidFunction)(void);
+typedef struct XrApiLayerProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE];
+ XrVersion specVersion;
+ uint32_t layerVersion;
+ char description[XR_MAX_API_LAYER_DESCRIPTION_SIZE];
+} XrApiLayerProperties;
+
+typedef struct XrExtensionProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ char extensionName[XR_MAX_EXTENSION_NAME_SIZE];
+ uint32_t extensionVersion;
+} XrExtensionProperties;
+
+typedef struct XrApplicationInfo {
+ char applicationName[XR_MAX_APPLICATION_NAME_SIZE];
+ uint32_t applicationVersion;
+ char engineName[XR_MAX_ENGINE_NAME_SIZE];
+ uint32_t engineVersion;
+ XrVersion apiVersion;
+} XrApplicationInfo;
+
+typedef struct XrInstanceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrInstanceCreateFlags createFlags;
+ XrApplicationInfo applicationInfo;
+ uint32_t enabledApiLayerCount;
+ const char* const* enabledApiLayerNames;
+ uint32_t enabledExtensionCount;
+ const char* const* enabledExtensionNames;
+} XrInstanceCreateInfo;
+
+typedef struct XrInstanceProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion runtimeVersion;
+ char runtimeName[XR_MAX_RUNTIME_NAME_SIZE];
+} XrInstanceProperties;
+
+typedef struct XrEventDataBuffer {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint8_t varying[4000];
+} XrEventDataBuffer;
+
+typedef struct XrSystemGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFormFactor formFactor;
+} XrSystemGetInfo;
+
+typedef struct XrSystemGraphicsProperties {
+ uint32_t maxSwapchainImageHeight;
+ uint32_t maxSwapchainImageWidth;
+ uint32_t maxLayerCount;
+} XrSystemGraphicsProperties;
+
+typedef struct XrSystemTrackingProperties {
+ XrBool32 orientationTracking;
+ XrBool32 positionTracking;
+} XrSystemTrackingProperties;
+
+typedef struct XrSystemProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSystemId systemId;
+ uint32_t vendorId;
+ char systemName[XR_MAX_SYSTEM_NAME_SIZE];
+ XrSystemGraphicsProperties graphicsProperties;
+ XrSystemTrackingProperties trackingProperties;
+} XrSystemProperties;
+
+typedef struct XrSessionCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSessionCreateFlags createFlags;
+ XrSystemId systemId;
+} XrSessionCreateInfo;
+
+typedef struct XrVector3f {
+ float x;
+ float y;
+ float z;
+} XrVector3f;
+
+// XrSpaceVelocity extends XrSpaceLocation
+typedef struct XrSpaceVelocity {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSpaceVelocityFlags velocityFlags;
+ XrVector3f linearVelocity;
+ XrVector3f angularVelocity;
+} XrSpaceVelocity;
+
+typedef struct XrQuaternionf {
+ float x;
+ float y;
+ float z;
+ float w;
+} XrQuaternionf;
+
+typedef struct XrPosef {
+ XrQuaternionf orientation;
+ XrVector3f position;
+} XrPosef;
+
+typedef struct XrReferenceSpaceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrReferenceSpaceType referenceSpaceType;
+ XrPosef poseInReferenceSpace;
+} XrReferenceSpaceCreateInfo;
+
+typedef struct XrExtent2Df {
+ float width;
+ float height;
+} XrExtent2Df;
+
+typedef struct XrActionSpaceCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+ XrPosef poseInActionSpace;
+} XrActionSpaceCreateInfo;
+
+typedef struct XrSpaceLocation {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSpaceLocationFlags locationFlags;
+ XrPosef pose;
+} XrSpaceLocation;
+
+typedef struct XrViewConfigurationProperties {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrBool32 fovMutable;
+} XrViewConfigurationProperties;
+
+typedef struct XrViewConfigurationView {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t recommendedImageRectWidth;
+ uint32_t maxImageRectWidth;
+ uint32_t recommendedImageRectHeight;
+ uint32_t maxImageRectHeight;
+ uint32_t recommendedSwapchainSampleCount;
+ uint32_t maxSwapchainSampleCount;
+} XrViewConfigurationView;
+
+typedef struct XrSwapchainCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSwapchainCreateFlags createFlags;
+ XrSwapchainUsageFlags usageFlags;
+ int64_t format;
+ uint32_t sampleCount;
+ uint32_t width;
+ uint32_t height;
+ uint32_t faceCount;
+ uint32_t arraySize;
+ uint32_t mipCount;
+} XrSwapchainCreateInfo;
+
+typedef struct XR_MAY_ALIAS XrSwapchainImageBaseHeader {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+} XrSwapchainImageBaseHeader;
+
+typedef struct XrSwapchainImageAcquireInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSwapchainImageAcquireInfo;
+
+typedef struct XrSwapchainImageWaitInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDuration timeout;
+} XrSwapchainImageWaitInfo;
+
+typedef struct XrSwapchainImageReleaseInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSwapchainImageReleaseInfo;
+
+typedef struct XrSessionBeginInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType primaryViewConfigurationType;
+} XrSessionBeginInfo;
+
+typedef struct XrFrameWaitInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrFrameWaitInfo;
+
+typedef struct XrFrameState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrTime predictedDisplayTime;
+ XrDuration predictedDisplayPeriod;
+ XrBool32 shouldRender;
+} XrFrameState;
+
+typedef struct XrFrameBeginInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrFrameBeginInfo;
+
+typedef struct XR_MAY_ALIAS XrCompositionLayerBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+} XrCompositionLayerBaseHeader;
+
+typedef struct XrFrameEndInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTime displayTime;
+ XrEnvironmentBlendMode environmentBlendMode;
+ uint32_t layerCount;
+ const XrCompositionLayerBaseHeader* const* layers;
+} XrFrameEndInfo;
+
+typedef struct XrViewLocateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrTime displayTime;
+ XrSpace space;
+} XrViewLocateInfo;
+
+typedef struct XrViewState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrViewStateFlags viewStateFlags;
+} XrViewState;
+
+typedef struct XrFovf {
+ float angleLeft;
+ float angleRight;
+ float angleUp;
+ float angleDown;
+} XrFovf;
+
+typedef struct XrView {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPosef pose;
+ XrFovf fov;
+} XrView;
+
+typedef struct XrActionSetCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ char actionSetName[XR_MAX_ACTION_SET_NAME_SIZE];
+ char localizedActionSetName[XR_MAX_LOCALIZED_ACTION_SET_NAME_SIZE];
+ uint32_t priority;
+} XrActionSetCreateInfo;
+
+typedef struct XrActionCreateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ char actionName[XR_MAX_ACTION_NAME_SIZE];
+ XrActionType actionType;
+ uint32_t countSubactionPaths;
+ const XrPath* subactionPaths;
+ char localizedActionName[XR_MAX_LOCALIZED_ACTION_NAME_SIZE];
+} XrActionCreateInfo;
+
+typedef struct XrActionSuggestedBinding {
+ XrAction action;
+ XrPath binding;
+} XrActionSuggestedBinding;
+
+typedef struct XrInteractionProfileSuggestedBinding {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPath interactionProfile;
+ uint32_t countSuggestedBindings;
+ const XrActionSuggestedBinding* suggestedBindings;
+} XrInteractionProfileSuggestedBinding;
+
+typedef struct XrSessionActionSetsAttachInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t countActionSets;
+ const XrActionSet* actionSets;
+} XrSessionActionSetsAttachInfo;
+
+typedef struct XrInteractionProfileState {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPath interactionProfile;
+} XrInteractionProfileState;
+
+typedef struct XrActionStateGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+} XrActionStateGetInfo;
+
+typedef struct XrActionStateBoolean {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateBoolean;
+
+typedef struct XrActionStateFloat {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ float currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateFloat;
+
+typedef struct XrVector2f {
+ float x;
+ float y;
+} XrVector2f;
+
+typedef struct XrActionStateVector2f {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVector2f currentState;
+ XrBool32 changedSinceLastSync;
+ XrTime lastChangeTime;
+ XrBool32 isActive;
+} XrActionStateVector2f;
+
+typedef struct XrActionStatePose {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 isActive;
+} XrActionStatePose;
+
+typedef struct XrActiveActionSet {
+ XrActionSet actionSet;
+ XrPath subactionPath;
+} XrActiveActionSet;
+
+typedef struct XrActionsSyncInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t countActiveActionSets;
+ const XrActiveActionSet* activeActionSets;
+} XrActionsSyncInfo;
+
+typedef struct XrBoundSourcesForActionEnumerateInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+} XrBoundSourcesForActionEnumerateInfo;
+
+typedef struct XrInputSourceLocalizedNameGetInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPath sourcePath;
+ XrInputSourceLocalizedNameFlags whichComponents;
+} XrInputSourceLocalizedNameGetInfo;
+
+typedef struct XrHapticActionInfo {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath subactionPath;
+} XrHapticActionInfo;
+
+typedef struct XR_MAY_ALIAS XrHapticBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrHapticBaseHeader;
+
+typedef struct XR_MAY_ALIAS XrBaseInStructure {
+ XrStructureType type;
+ const struct XrBaseInStructure* next;
+} XrBaseInStructure;
+
+typedef struct XR_MAY_ALIAS XrBaseOutStructure {
+ XrStructureType type;
+ struct XrBaseOutStructure* next;
+} XrBaseOutStructure;
+
+typedef struct XrOffset2Di {
+ int32_t x;
+ int32_t y;
+} XrOffset2Di;
+
+typedef struct XrExtent2Di {
+ int32_t width;
+ int32_t height;
+} XrExtent2Di;
+
+typedef struct XrRect2Di {
+ XrOffset2Di offset;
+ XrExtent2Di extent;
+} XrRect2Di;
+
+typedef struct XrSwapchainSubImage {
+ XrSwapchain swapchain;
+ XrRect2Di imageRect;
+ uint32_t imageArrayIndex;
+} XrSwapchainSubImage;
+
+typedef struct XrCompositionLayerProjectionView {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPosef pose;
+ XrFovf fov;
+ XrSwapchainSubImage subImage;
+} XrCompositionLayerProjectionView;
+
+typedef struct XrCompositionLayerProjection {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ uint32_t viewCount;
+ const XrCompositionLayerProjectionView* views;
+} XrCompositionLayerProjection;
+
+typedef struct XrCompositionLayerQuad {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ XrExtent2Df size;
+} XrCompositionLayerQuad;
+
+typedef struct XR_MAY_ALIAS XrEventDataBaseHeader {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrEventDataBaseHeader;
+
+typedef struct XrEventDataEventsLost {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t lostEventCount;
+} XrEventDataEventsLost;
+
+typedef struct XrEventDataInstanceLossPending {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTime lossTime;
+} XrEventDataInstanceLossPending;
+
+typedef struct XrEventDataSessionStateChanged {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrSessionState state;
+ XrTime time;
+} XrEventDataSessionStateChanged;
+
+typedef struct XrEventDataReferenceSpaceChangePending {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrReferenceSpaceType referenceSpaceType;
+ XrTime changeTime;
+ XrBool32 poseValid;
+ XrPosef poseInPreviousSpace;
+} XrEventDataReferenceSpaceChangePending;
+
+typedef struct XrEventDataInteractionProfileChanged {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+} XrEventDataInteractionProfileChanged;
+
+typedef struct XrHapticVibration {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDuration duration;
+ float frequency;
+ float amplitude;
+} XrHapticVibration;
+
+typedef struct XrOffset2Df {
+ float x;
+ float y;
+} XrOffset2Df;
+
+typedef struct XrRect2Df {
+ XrOffset2Df offset;
+ XrExtent2Df extent;
+} XrRect2Df;
+
+typedef struct XrVector4f {
+ float x;
+ float y;
+ float z;
+ float w;
+} XrVector4f;
+
+typedef struct XrColor4f {
+ float r;
+ float g;
+ float b;
+ float a;
+} XrColor4f;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProcAddr)(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateApiLayerProperties)(uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrApiLayerProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateInstanceExtensionProperties)(const char* layerName, uint32_t propertyCapacityInput, uint32_t* propertyCountOutput, XrExtensionProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateInstance)(const XrInstanceCreateInfo* createInfo, XrInstance* instance);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyInstance)(XrInstance instance);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInstanceProperties)(XrInstance instance, XrInstanceProperties* instanceProperties);
+typedef XrResult (XRAPI_PTR *PFN_xrPollEvent)(XrInstance instance, XrEventDataBuffer* eventData);
+typedef XrResult (XRAPI_PTR *PFN_xrResultToString)(XrInstance instance, XrResult value, char buffer[XR_MAX_RESULT_STRING_SIZE]);
+typedef XrResult (XRAPI_PTR *PFN_xrStructureTypeToString)(XrInstance instance, XrStructureType value, char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystem)(XrInstance instance, const XrSystemGetInfo* getInfo, XrSystemId* systemId);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSystemProperties)(XrInstance instance, XrSystemId systemId, XrSystemProperties* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateEnvironmentBlendModes)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t environmentBlendModeCapacityInput, uint32_t* environmentBlendModeCountOutput, XrEnvironmentBlendMode* environmentBlendModes);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSession)(XrInstance instance, const XrSessionCreateInfo* createInfo, XrSession* session);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReferenceSpaces)(XrSession session, uint32_t spaceCapacityInput, uint32_t* spaceCountOutput, XrReferenceSpaceType* spaces);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateReferenceSpace)(XrSession session, const XrReferenceSpaceCreateInfo* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrGetReferenceSpaceBoundsRect)(XrSession session, XrReferenceSpaceType referenceSpaceType, XrExtent2Df* bounds);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSpace)(XrSession session, const XrActionSpaceCreateInfo* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateSpace)(XrSpace space, XrSpace baseSpace, XrTime time, XrSpaceLocation* location);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpace)(XrSpace space);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurations)(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput, uint32_t* viewConfigurationTypeCountOutput, XrViewConfigurationType* viewConfigurationTypes);
+typedef XrResult (XRAPI_PTR *PFN_xrGetViewConfigurationProperties)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, XrViewConfigurationProperties* configurationProperties);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViewConfigurationViews)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrViewConfigurationView* views);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainFormats)(XrSession session, uint32_t formatCapacityInput, uint32_t* formatCountOutput, int64_t* formats);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchain)(XrSession session, const XrSwapchainCreateInfo* createInfo, XrSwapchain* swapchain);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySwapchain)(XrSwapchain swapchain);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSwapchainImages)(XrSwapchain swapchain, uint32_t imageCapacityInput, uint32_t* imageCountOutput, XrSwapchainImageBaseHeader* images);
+typedef XrResult (XRAPI_PTR *PFN_xrAcquireSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageAcquireInfo* acquireInfo, uint32_t* index);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageWaitInfo* waitInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrReleaseSwapchainImage)(XrSwapchain swapchain, const XrSwapchainImageReleaseInfo* releaseInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginSession)(XrSession session, const XrSessionBeginInfo* beginInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEndSession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrRequestExitSession)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrWaitFrame)(XrSession session, const XrFrameWaitInfo* frameWaitInfo, XrFrameState* frameState);
+typedef XrResult (XRAPI_PTR *PFN_xrBeginFrame)(XrSession session, const XrFrameBeginInfo* frameBeginInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEndFrame)(XrSession session, const XrFrameEndInfo* frameEndInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateViews)(XrSession session, const XrViewLocateInfo* viewLocateInfo, XrViewState* viewState, uint32_t viewCapacityInput, uint32_t* viewCountOutput, XrView* views);
+typedef XrResult (XRAPI_PTR *PFN_xrStringToPath)(XrInstance instance, const char* pathString, XrPath* path);
+typedef XrResult (XRAPI_PTR *PFN_xrPathToString)(XrInstance instance, XrPath path, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateActionSet)(XrInstance instance, const XrActionSetCreateInfo* createInfo, XrActionSet* actionSet);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyActionSet)(XrActionSet actionSet);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateAction)(XrActionSet actionSet, const XrActionCreateInfo* createInfo, XrAction* action);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyAction)(XrAction action);
+typedef XrResult (XRAPI_PTR *PFN_xrSuggestInteractionProfileBindings)(XrInstance instance, const XrInteractionProfileSuggestedBinding* suggestedBindings);
+typedef XrResult (XRAPI_PTR *PFN_xrAttachSessionActionSets)(XrSession session, const XrSessionActionSetsAttachInfo* attachInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrGetCurrentInteractionProfile)(XrSession session, XrPath topLevelUserPath, XrInteractionProfileState* interactionProfile);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateBoolean)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateBoolean* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateFloat)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateFloat* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStateVector2f)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStateVector2f* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetActionStatePose)(XrSession session, const XrActionStateGetInfo* getInfo, XrActionStatePose* state);
+typedef XrResult (XRAPI_PTR *PFN_xrSyncActions)(XrSession session, const XrActionsSyncInfo* syncInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateBoundSourcesForAction)(XrSession session, const XrBoundSourcesForActionEnumerateInfo* enumerateInfo, uint32_t sourceCapacityInput, uint32_t* sourceCountOutput, XrPath* sources);
+typedef XrResult (XRAPI_PTR *PFN_xrGetInputSourceLocalizedName)(XrSession session, const XrInputSourceLocalizedNameGetInfo* getInfo, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrApplyHapticFeedback)(XrSession session, const XrHapticActionInfo* hapticActionInfo, const XrHapticBaseHeader* hapticFeedback);
+typedef XrResult (XRAPI_PTR *PFN_xrStopHapticFeedback)(XrSession session, const XrHapticActionInfo* hapticActionInfo);
+
+#ifndef XR_NO_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(
+ XrInstance instance,
+ const char* name,
+ PFN_xrVoidFunction* function);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrApiLayerProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(
+ const char* layerName,
+ uint32_t propertyCapacityInput,
+ uint32_t* propertyCountOutput,
+ XrExtensionProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(
+ const XrInstanceCreateInfo* createInfo,
+ XrInstance* instance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(
+ XrInstance instance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
+ XrSpace space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
+ XrSwapchain swapchain);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
+ XrActionSet actionSet);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
+ XrAction action);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo);
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_KHR_composition_layer_cube 1
+#define XR_KHR_composition_layer_cube_SPEC_VERSION 8
+#define XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME "XR_KHR_composition_layer_cube"
+typedef struct XrCompositionLayerCubeKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchain swapchain;
+ uint32_t imageArrayIndex;
+ XrQuaternionf orientation;
+} XrCompositionLayerCubeKHR;
+
+
+
+#define XR_KHR_composition_layer_depth 1
+#define XR_KHR_composition_layer_depth_SPEC_VERSION 6
+#define XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME "XR_KHR_composition_layer_depth"
+// XrCompositionLayerDepthInfoKHR extends XrCompositionLayerProjectionView
+typedef struct XrCompositionLayerDepthInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSwapchainSubImage subImage;
+ float minDepth;
+ float maxDepth;
+ float nearZ;
+ float farZ;
+} XrCompositionLayerDepthInfoKHR;
+
+
+
+#define XR_KHR_composition_layer_cylinder 1
+#define XR_KHR_composition_layer_cylinder_SPEC_VERSION 4
+#define XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME "XR_KHR_composition_layer_cylinder"
+typedef struct XrCompositionLayerCylinderKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ float centralAngle;
+ float aspectRatio;
+} XrCompositionLayerCylinderKHR;
+
+
+
+#define XR_KHR_composition_layer_equirect 1
+#define XR_KHR_composition_layer_equirect_SPEC_VERSION 3
+#define XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME "XR_KHR_composition_layer_equirect"
+typedef struct XrCompositionLayerEquirectKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ XrVector2f scale;
+ XrVector2f bias;
+} XrCompositionLayerEquirectKHR;
+
+
+
+#define XR_KHR_visibility_mask 1
+#define XR_KHR_visibility_mask_SPEC_VERSION 2
+#define XR_KHR_VISIBILITY_MASK_EXTENSION_NAME "XR_KHR_visibility_mask"
+
+typedef enum XrVisibilityMaskTypeKHR {
+ XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR = 1,
+ XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR = 2,
+ XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR = 3,
+ XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} XrVisibilityMaskTypeKHR;
+typedef struct XrVisibilityMaskKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrVector2f* vertices;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t* indices;
+} XrVisibilityMaskKHR;
+
+typedef struct XrEventDataVisibilityMaskChangedKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSession session;
+ XrViewConfigurationType viewConfigurationType;
+ uint32_t viewIndex;
+} XrEventDataVisibilityMaskChangedKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetVisibilityMaskKHR)(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR* visibilityMask);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVisibilityMaskKHR(
+ XrSession session,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewIndex,
+ XrVisibilityMaskTypeKHR visibilityMaskType,
+ XrVisibilityMaskKHR* visibilityMask);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_KHR_composition_layer_color_scale_bias 1
+#define XR_KHR_composition_layer_color_scale_bias_SPEC_VERSION 5
+#define XR_KHR_COMPOSITION_LAYER_COLOR_SCALE_BIAS_EXTENSION_NAME "XR_KHR_composition_layer_color_scale_bias"
+// XrCompositionLayerColorScaleBiasKHR extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerColorScaleBiasKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrColor4f colorScale;
+ XrColor4f colorBias;
+} XrCompositionLayerColorScaleBiasKHR;
+
+
+
+#define XR_KHR_loader_init 1
+#define XR_KHR_loader_init_SPEC_VERSION 1
+#define XR_KHR_LOADER_INIT_EXTENSION_NAME "XR_KHR_loader_init"
+typedef struct XR_MAY_ALIAS XrLoaderInitInfoBaseHeaderKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrLoaderInitInfoBaseHeaderKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrInitializeLoaderKHR)(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrInitializeLoaderKHR(
+ const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_KHR_composition_layer_equirect2 1
+#define XR_KHR_composition_layer_equirect2_SPEC_VERSION 1
+#define XR_KHR_COMPOSITION_LAYER_EQUIRECT2_EXTENSION_NAME "XR_KHR_composition_layer_equirect2"
+typedef struct XrCompositionLayerEquirect2KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags layerFlags;
+ XrSpace space;
+ XrEyeVisibility eyeVisibility;
+ XrSwapchainSubImage subImage;
+ XrPosef pose;
+ float radius;
+ float centralHorizontalAngle;
+ float upperVerticalAngle;
+ float lowerVerticalAngle;
+} XrCompositionLayerEquirect2KHR;
+
+
+
+#define XR_KHR_binding_modification 1
+#define XR_KHR_binding_modification_SPEC_VERSION 1
+#define XR_KHR_BINDING_MODIFICATION_EXTENSION_NAME "XR_KHR_binding_modification"
+typedef struct XR_MAY_ALIAS XrBindingModificationBaseHeaderKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrBindingModificationBaseHeaderKHR;
+
+// XrBindingModificationsKHR extends XrInteractionProfileSuggestedBinding
+typedef struct XrBindingModificationsKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t bindingModificationCount;
+ const XrBindingModificationBaseHeaderKHR* const* bindingModifications;
+} XrBindingModificationsKHR;
+
+
+
+#define XR_KHR_swapchain_usage_input_attachment_bit 1
+#define XR_KHR_swapchain_usage_input_attachment_bit_SPEC_VERSION 3
+#define XR_KHR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME "XR_KHR_swapchain_usage_input_attachment_bit"
+
+
+#define XR_EXT_performance_settings 1
+#define XR_EXT_performance_settings_SPEC_VERSION 3
+#define XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME "XR_EXT_performance_settings"
+
+typedef enum XrPerfSettingsDomainEXT {
+ XR_PERF_SETTINGS_DOMAIN_CPU_EXT = 1,
+ XR_PERF_SETTINGS_DOMAIN_GPU_EXT = 2,
+ XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsDomainEXT;
+
+typedef enum XrPerfSettingsSubDomainEXT {
+ XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT = 1,
+ XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT = 2,
+ XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT = 3,
+ XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsSubDomainEXT;
+
+typedef enum XrPerfSettingsLevelEXT {
+ XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT = 0,
+ XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT = 25,
+ XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT = 50,
+ XR_PERF_SETTINGS_LEVEL_BOOST_EXT = 75,
+ XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsLevelEXT;
+
+typedef enum XrPerfSettingsNotificationLevelEXT {
+ XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT = 0,
+ XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT = 25,
+ XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT = 75,
+ XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrPerfSettingsNotificationLevelEXT;
+typedef struct XrEventDataPerfSettingsEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPerfSettingsDomainEXT domain;
+ XrPerfSettingsSubDomainEXT subDomain;
+ XrPerfSettingsNotificationLevelEXT fromLevel;
+ XrPerfSettingsNotificationLevelEXT toLevel;
+} XrEventDataPerfSettingsEXT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrPerfSettingsSetPerformanceLevelEXT)(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsLevelEXT level);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrPerfSettingsSetPerformanceLevelEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsLevelEXT level);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_thermal_query 1
+#define XR_EXT_thermal_query_SPEC_VERSION 2
+#define XR_EXT_THERMAL_QUERY_EXTENSION_NAME "XR_EXT_thermal_query"
+typedef XrResult (XRAPI_PTR *PFN_xrThermalGetTemperatureTrendEXT)(XrSession session, XrPerfSettingsDomainEXT domain, XrPerfSettingsNotificationLevelEXT* notificationLevel, float* tempHeadroom, float* tempSlope);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrThermalGetTemperatureTrendEXT(
+ XrSession session,
+ XrPerfSettingsDomainEXT domain,
+ XrPerfSettingsNotificationLevelEXT* notificationLevel,
+ float* tempHeadroom,
+ float* tempSlope);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_debug_utils 1
+XR_DEFINE_HANDLE(XrDebugUtilsMessengerEXT)
+#define XR_EXT_debug_utils_SPEC_VERSION 4
+#define XR_EXT_DEBUG_UTILS_EXTENSION_NAME "XR_EXT_debug_utils"
+typedef XrFlags64 XrDebugUtilsMessageSeverityFlagsEXT;
+
+// Flag bits for XrDebugUtilsMessageSeverityFlagsEXT
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100;
+static const XrDebugUtilsMessageSeverityFlagsEXT XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000;
+
+typedef XrFlags64 XrDebugUtilsMessageTypeFlagsEXT;
+
+// Flag bits for XrDebugUtilsMessageTypeFlagsEXT
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT = 0x00000001;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT = 0x00000002;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT = 0x00000004;
+static const XrDebugUtilsMessageTypeFlagsEXT XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT = 0x00000008;
+
+typedef struct XrDebugUtilsObjectNameInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrObjectType objectType;
+ uint64_t objectHandle;
+ const char* objectName;
+} XrDebugUtilsObjectNameInfoEXT;
+
+typedef struct XrDebugUtilsLabelEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ const char* labelName;
+} XrDebugUtilsLabelEXT;
+
+typedef struct XrDebugUtilsMessengerCallbackDataEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ const char* messageId;
+ const char* functionName;
+ const char* message;
+ uint32_t objectCount;
+ XrDebugUtilsObjectNameInfoEXT* objects;
+ uint32_t sessionLabelCount;
+ XrDebugUtilsLabelEXT* sessionLabels;
+} XrDebugUtilsMessengerCallbackDataEXT;
+
+typedef XrBool32 (XRAPI_PTR *PFN_xrDebugUtilsMessengerCallbackEXT)(
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData,
+ void* userData);
+
+
+// XrDebugUtilsMessengerCreateInfoEXT extends XrInstanceCreateInfo
+typedef struct XrDebugUtilsMessengerCreateInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverities;
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes;
+ PFN_xrDebugUtilsMessengerCallbackEXT userCallback;
+ void* XR_MAY_ALIAS userData;
+} XrDebugUtilsMessengerCreateInfoEXT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrSetDebugUtilsObjectNameEXT)(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateDebugUtilsMessengerEXT)(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT* createInfo, XrDebugUtilsMessengerEXT* messenger);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyDebugUtilsMessengerEXT)(XrDebugUtilsMessengerEXT messenger);
+typedef XrResult (XRAPI_PTR *PFN_xrSubmitDebugUtilsMessageEXT)(XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes, const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionBeginDebugUtilsLabelRegionEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionEndDebugUtilsLabelRegionEXT)(XrSession session);
+typedef XrResult (XRAPI_PTR *PFN_xrSessionInsertDebugUtilsLabelEXT)(XrSession session, const XrDebugUtilsLabelEXT* labelInfo);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetDebugUtilsObjectNameEXT(
+ XrInstance instance,
+ const XrDebugUtilsObjectNameInfoEXT* nameInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateDebugUtilsMessengerEXT(
+ XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT* createInfo,
+ XrDebugUtilsMessengerEXT* messenger);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyDebugUtilsMessengerEXT(
+ XrDebugUtilsMessengerEXT messenger);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSubmitDebugUtilsMessageEXT(
+ XrInstance instance,
+ XrDebugUtilsMessageSeverityFlagsEXT messageSeverity,
+ XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT* callbackData);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionBeginDebugUtilsLabelRegionEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionEndDebugUtilsLabelRegionEXT(
+ XrSession session);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSessionInsertDebugUtilsLabelEXT(
+ XrSession session,
+ const XrDebugUtilsLabelEXT* labelInfo);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_eye_gaze_interaction 1
+#define XR_EXT_eye_gaze_interaction_SPEC_VERSION 2
+#define XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME "XR_EXT_eye_gaze_interaction"
+// XrSystemEyeGazeInteractionPropertiesEXT extends XrSystemProperties
+typedef struct XrSystemEyeGazeInteractionPropertiesEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsEyeGazeInteraction;
+} XrSystemEyeGazeInteractionPropertiesEXT;
+
+// XrEyeGazeSampleTimeEXT extends XrSpaceLocation
+typedef struct XrEyeGazeSampleTimeEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrTime time;
+} XrEyeGazeSampleTimeEXT;
+
+
+
+#define XR_EXTX_overlay 1
+#define XR_EXTX_overlay_SPEC_VERSION 5
+#define XR_EXTX_OVERLAY_EXTENSION_NAME "XR_EXTX_overlay"
+typedef XrFlags64 XrOverlaySessionCreateFlagsEXTX;
+
+// Flag bits for XrOverlaySessionCreateFlagsEXTX
+
+typedef XrFlags64 XrOverlayMainSessionFlagsEXTX;
+
+// Flag bits for XrOverlayMainSessionFlagsEXTX
+static const XrOverlayMainSessionFlagsEXTX XR_OVERLAY_MAIN_SESSION_ENABLED_COMPOSITION_LAYER_INFO_DEPTH_BIT_EXTX = 0x00000001;
+
+// XrSessionCreateInfoOverlayEXTX extends XrSessionCreateInfo
+typedef struct XrSessionCreateInfoOverlayEXTX {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrOverlaySessionCreateFlagsEXTX createFlags;
+ uint32_t sessionLayersPlacement;
+} XrSessionCreateInfoOverlayEXTX;
+
+typedef struct XrEventDataMainSessionVisibilityChangedEXTX {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 visible;
+ XrOverlayMainSessionFlagsEXTX flags;
+} XrEventDataMainSessionVisibilityChangedEXTX;
+
+
+
+#define XR_VARJO_quad_views 1
+#define XR_VARJO_quad_views_SPEC_VERSION 1
+#define XR_VARJO_QUAD_VIEWS_EXTENSION_NAME "XR_VARJO_quad_views"
+
+
+#define XR_MSFT_unbounded_reference_space 1
+#define XR_MSFT_unbounded_reference_space_SPEC_VERSION 1
+#define XR_MSFT_UNBOUNDED_REFERENCE_SPACE_EXTENSION_NAME "XR_MSFT_unbounded_reference_space"
+
+
+#define XR_MSFT_spatial_anchor 1
+XR_DEFINE_HANDLE(XrSpatialAnchorMSFT)
+#define XR_MSFT_spatial_anchor_SPEC_VERSION 2
+#define XR_MSFT_SPATIAL_ANCHOR_EXTENSION_NAME "XR_MSFT_spatial_anchor"
+typedef struct XrSpatialAnchorCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace space;
+ XrPosef pose;
+ XrTime time;
+} XrSpatialAnchorCreateInfoMSFT;
+
+typedef struct XrSpatialAnchorSpaceCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpatialAnchorMSFT anchor;
+ XrPosef poseInAnchorSpace;
+} XrSpatialAnchorSpaceCreateInfoMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorMSFT)(XrSession session, const XrSpatialAnchorCreateInfoMSFT* createInfo, XrSpatialAnchorMSFT* anchor);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorSpaceMSFT)(XrSession session, const XrSpatialAnchorSpaceCreateInfoMSFT* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorMSFT)(XrSpatialAnchorMSFT anchor);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorMSFT(
+ XrSession session,
+ const XrSpatialAnchorCreateInfoMSFT* createInfo,
+ XrSpatialAnchorMSFT* anchor);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorSpaceMSFT(
+ XrSession session,
+ const XrSpatialAnchorSpaceCreateInfoMSFT* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorMSFT(
+ XrSpatialAnchorMSFT anchor);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_composition_layer_image_layout 1
+#define XR_FB_composition_layer_image_layout_SPEC_VERSION 1
+#define XR_FB_COMPOSITION_LAYER_IMAGE_LAYOUT_EXTENSION_NAME "XR_FB_composition_layer_image_layout"
+typedef XrFlags64 XrCompositionLayerImageLayoutFlagsFB;
+
+// Flag bits for XrCompositionLayerImageLayoutFlagsFB
+static const XrCompositionLayerImageLayoutFlagsFB XR_COMPOSITION_LAYER_IMAGE_LAYOUT_VERTICAL_FLIP_BIT_FB = 0x00000001;
+
+// XrCompositionLayerImageLayoutFB extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerImageLayoutFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrCompositionLayerImageLayoutFlagsFB flags;
+} XrCompositionLayerImageLayoutFB;
+
+
+
+#define XR_FB_composition_layer_alpha_blend 1
+#define XR_FB_composition_layer_alpha_blend_SPEC_VERSION 2
+#define XR_FB_COMPOSITION_LAYER_ALPHA_BLEND_EXTENSION_NAME "XR_FB_composition_layer_alpha_blend"
+
+typedef enum XrBlendFactorFB {
+ XR_BLEND_FACTOR_ZERO_FB = 0,
+ XR_BLEND_FACTOR_ONE_FB = 1,
+ XR_BLEND_FACTOR_SRC_ALPHA_FB = 2,
+ XR_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA_FB = 3,
+ XR_BLEND_FACTOR_DST_ALPHA_FB = 4,
+ XR_BLEND_FACTOR_ONE_MINUS_DST_ALPHA_FB = 5,
+ XR_BLEND_FACTOR_MAX_ENUM_FB = 0x7FFFFFFF
+} XrBlendFactorFB;
+// XrCompositionLayerAlphaBlendFB extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerAlphaBlendFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBlendFactorFB srcFactorColor;
+ XrBlendFactorFB dstFactorColor;
+ XrBlendFactorFB srcFactorAlpha;
+ XrBlendFactorFB dstFactorAlpha;
+} XrCompositionLayerAlphaBlendFB;
+
+
+
+#define XR_MND_headless 1
+#define XR_MND_headless_SPEC_VERSION 2
+#define XR_MND_HEADLESS_EXTENSION_NAME "XR_MND_headless"
+
+
+#define XR_OCULUS_android_session_state_enable 1
+#define XR_OCULUS_android_session_state_enable_SPEC_VERSION 1
+#define XR_OCULUS_ANDROID_SESSION_STATE_ENABLE_EXTENSION_NAME "XR_OCULUS_android_session_state_enable"
+
+
+#define XR_EXT_view_configuration_depth_range 1
+#define XR_EXT_view_configuration_depth_range_SPEC_VERSION 1
+#define XR_EXT_VIEW_CONFIGURATION_DEPTH_RANGE_EXTENSION_NAME "XR_EXT_view_configuration_depth_range"
+// XrViewConfigurationDepthRangeEXT extends XrViewConfigurationView
+typedef struct XrViewConfigurationDepthRangeEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ float recommendedNearZ;
+ float minNearZ;
+ float recommendedFarZ;
+ float maxFarZ;
+} XrViewConfigurationDepthRangeEXT;
+
+
+
+#define XR_EXT_conformance_automation 1
+#define XR_EXT_conformance_automation_SPEC_VERSION 3
+#define XR_EXT_CONFORMANCE_AUTOMATION_EXTENSION_NAME "XR_EXT_conformance_automation"
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceActiveEXT)(XrSession session, XrPath interactionProfile, XrPath topLevelPath, XrBool32 isActive);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateBoolEXT)(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrBool32 state);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateFloatEXT)(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, float state);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceStateVector2fEXT)(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrVector2f state);
+typedef XrResult (XRAPI_PTR *PFN_xrSetInputDeviceLocationEXT)(XrSession session, XrPath topLevelPath, XrPath inputSourcePath, XrSpace space, XrPosef pose);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceActiveEXT(
+ XrSession session,
+ XrPath interactionProfile,
+ XrPath topLevelPath,
+ XrBool32 isActive);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateBoolEXT(
+ XrSession session,
+ XrPath topLevelPath,
+ XrPath inputSourcePath,
+ XrBool32 state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateFloatEXT(
+ XrSession session,
+ XrPath topLevelPath,
+ XrPath inputSourcePath,
+ float state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceStateVector2fEXT(
+ XrSession session,
+ XrPath topLevelPath,
+ XrPath inputSourcePath,
+ XrVector2f state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetInputDeviceLocationEXT(
+ XrSession session,
+ XrPath topLevelPath,
+ XrPath inputSourcePath,
+ XrSpace space,
+ XrPosef pose);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_spatial_graph_bridge 1
+XR_DEFINE_HANDLE(XrSpatialGraphNodeBindingMSFT)
+#define XR_MSFT_spatial_graph_bridge_SPEC_VERSION 2
+#define XR_MSFT_SPATIAL_GRAPH_BRIDGE_EXTENSION_NAME "XR_MSFT_spatial_graph_bridge"
+#define XR_GUID_SIZE_MSFT 16
+
+typedef enum XrSpatialGraphNodeTypeMSFT {
+ XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT = 1,
+ XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT = 2,
+ XR_SPATIAL_GRAPH_NODE_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSpatialGraphNodeTypeMSFT;
+typedef struct XrSpatialGraphNodeSpaceCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpatialGraphNodeTypeMSFT nodeType;
+ uint8_t nodeId[XR_GUID_SIZE_MSFT];
+ XrPosef pose;
+} XrSpatialGraphNodeSpaceCreateInfoMSFT;
+
+typedef struct XrSpatialGraphStaticNodeBindingCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace space;
+ XrPosef poseInSpace;
+ XrTime time;
+} XrSpatialGraphStaticNodeBindingCreateInfoMSFT;
+
+typedef struct XrSpatialGraphNodeBindingPropertiesGetInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSpatialGraphNodeBindingPropertiesGetInfoMSFT;
+
+typedef struct XrSpatialGraphNodeBindingPropertiesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint8_t nodeId[XR_GUID_SIZE_MSFT];
+ XrPosef poseInNodeSpace;
+} XrSpatialGraphNodeBindingPropertiesMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialGraphNodeSpaceMSFT)(XrSession session, const XrSpatialGraphNodeSpaceCreateInfoMSFT* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrTryCreateSpatialGraphStaticNodeBindingMSFT)(XrSession session, const XrSpatialGraphStaticNodeBindingCreateInfoMSFT* createInfo, XrSpatialGraphNodeBindingMSFT* nodeBinding);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialGraphNodeBindingMSFT)(XrSpatialGraphNodeBindingMSFT nodeBinding);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSpatialGraphNodeBindingPropertiesMSFT)(XrSpatialGraphNodeBindingMSFT nodeBinding, const XrSpatialGraphNodeBindingPropertiesGetInfoMSFT* getInfo, XrSpatialGraphNodeBindingPropertiesMSFT* properties);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialGraphNodeSpaceMSFT(
+ XrSession session,
+ const XrSpatialGraphNodeSpaceCreateInfoMSFT* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTryCreateSpatialGraphStaticNodeBindingMSFT(
+ XrSession session,
+ const XrSpatialGraphStaticNodeBindingCreateInfoMSFT* createInfo,
+ XrSpatialGraphNodeBindingMSFT* nodeBinding);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialGraphNodeBindingMSFT(
+ XrSpatialGraphNodeBindingMSFT nodeBinding);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSpatialGraphNodeBindingPropertiesMSFT(
+ XrSpatialGraphNodeBindingMSFT nodeBinding,
+ const XrSpatialGraphNodeBindingPropertiesGetInfoMSFT* getInfo,
+ XrSpatialGraphNodeBindingPropertiesMSFT* properties);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_hand_interaction 1
+#define XR_MSFT_hand_interaction_SPEC_VERSION 1
+#define XR_MSFT_HAND_INTERACTION_EXTENSION_NAME "XR_MSFT_hand_interaction"
+
+
+#define XR_EXT_hand_tracking 1
+
+#define XR_HAND_JOINT_COUNT_EXT 26
+
+XR_DEFINE_HANDLE(XrHandTrackerEXT)
+#define XR_EXT_hand_tracking_SPEC_VERSION 4
+#define XR_EXT_HAND_TRACKING_EXTENSION_NAME "XR_EXT_hand_tracking"
+
+typedef enum XrHandEXT {
+ XR_HAND_LEFT_EXT = 1,
+ XR_HAND_RIGHT_EXT = 2,
+ XR_HAND_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrHandEXT;
+
+typedef enum XrHandJointEXT {
+ XR_HAND_JOINT_PALM_EXT = 0,
+ XR_HAND_JOINT_WRIST_EXT = 1,
+ XR_HAND_JOINT_THUMB_METACARPAL_EXT = 2,
+ XR_HAND_JOINT_THUMB_PROXIMAL_EXT = 3,
+ XR_HAND_JOINT_THUMB_DISTAL_EXT = 4,
+ XR_HAND_JOINT_THUMB_TIP_EXT = 5,
+ XR_HAND_JOINT_INDEX_METACARPAL_EXT = 6,
+ XR_HAND_JOINT_INDEX_PROXIMAL_EXT = 7,
+ XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT = 8,
+ XR_HAND_JOINT_INDEX_DISTAL_EXT = 9,
+ XR_HAND_JOINT_INDEX_TIP_EXT = 10,
+ XR_HAND_JOINT_MIDDLE_METACARPAL_EXT = 11,
+ XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT = 12,
+ XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT = 13,
+ XR_HAND_JOINT_MIDDLE_DISTAL_EXT = 14,
+ XR_HAND_JOINT_MIDDLE_TIP_EXT = 15,
+ XR_HAND_JOINT_RING_METACARPAL_EXT = 16,
+ XR_HAND_JOINT_RING_PROXIMAL_EXT = 17,
+ XR_HAND_JOINT_RING_INTERMEDIATE_EXT = 18,
+ XR_HAND_JOINT_RING_DISTAL_EXT = 19,
+ XR_HAND_JOINT_RING_TIP_EXT = 20,
+ XR_HAND_JOINT_LITTLE_METACARPAL_EXT = 21,
+ XR_HAND_JOINT_LITTLE_PROXIMAL_EXT = 22,
+ XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT = 23,
+ XR_HAND_JOINT_LITTLE_DISTAL_EXT = 24,
+ XR_HAND_JOINT_LITTLE_TIP_EXT = 25,
+ XR_HAND_JOINT_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrHandJointEXT;
+
+typedef enum XrHandJointSetEXT {
+ XR_HAND_JOINT_SET_DEFAULT_EXT = 0,
+ XR_HAND_JOINT_SET_HAND_WITH_FOREARM_ULTRALEAP = 1000149000,
+ XR_HAND_JOINT_SET_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrHandJointSetEXT;
+// XrSystemHandTrackingPropertiesEXT extends XrSystemProperties
+typedef struct XrSystemHandTrackingPropertiesEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsHandTracking;
+} XrSystemHandTrackingPropertiesEXT;
+
+typedef struct XrHandTrackerCreateInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrHandEXT hand;
+ XrHandJointSetEXT handJointSet;
+} XrHandTrackerCreateInfoEXT;
+
+typedef struct XrHandJointsLocateInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace baseSpace;
+ XrTime time;
+} XrHandJointsLocateInfoEXT;
+
+typedef struct XrHandJointLocationEXT {
+ XrSpaceLocationFlags locationFlags;
+ XrPosef pose;
+ float radius;
+} XrHandJointLocationEXT;
+
+typedef struct XrHandJointVelocityEXT {
+ XrSpaceVelocityFlags velocityFlags;
+ XrVector3f linearVelocity;
+ XrVector3f angularVelocity;
+} XrHandJointVelocityEXT;
+
+typedef struct XrHandJointLocationsEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 isActive;
+ uint32_t jointCount;
+ XrHandJointLocationEXT* jointLocations;
+} XrHandJointLocationsEXT;
+
+// XrHandJointVelocitiesEXT extends XrHandJointLocationsEXT
+typedef struct XrHandJointVelocitiesEXT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t jointCount;
+ XrHandJointVelocityEXT* jointVelocities;
+} XrHandJointVelocitiesEXT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateHandTrackerEXT)(XrSession session, const XrHandTrackerCreateInfoEXT* createInfo, XrHandTrackerEXT* handTracker);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyHandTrackerEXT)(XrHandTrackerEXT handTracker);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateHandJointsEXT)(XrHandTrackerEXT handTracker, const XrHandJointsLocateInfoEXT* locateInfo, XrHandJointLocationsEXT* locations);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateHandTrackerEXT(
+ XrSession session,
+ const XrHandTrackerCreateInfoEXT* createInfo,
+ XrHandTrackerEXT* handTracker);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyHandTrackerEXT(
+ XrHandTrackerEXT handTracker);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateHandJointsEXT(
+ XrHandTrackerEXT handTracker,
+ const XrHandJointsLocateInfoEXT* locateInfo,
+ XrHandJointLocationsEXT* locations);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_hand_tracking_mesh 1
+#define XR_MSFT_hand_tracking_mesh_SPEC_VERSION 4
+#define XR_MSFT_HAND_TRACKING_MESH_EXTENSION_NAME "XR_MSFT_hand_tracking_mesh"
+
+typedef enum XrHandPoseTypeMSFT {
+ XR_HAND_POSE_TYPE_TRACKED_MSFT = 0,
+ XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT = 1,
+ XR_HAND_POSE_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrHandPoseTypeMSFT;
+// XrSystemHandTrackingMeshPropertiesMSFT extends XrSystemProperties
+typedef struct XrSystemHandTrackingMeshPropertiesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsHandTrackingMesh;
+ uint32_t maxHandMeshIndexCount;
+ uint32_t maxHandMeshVertexCount;
+} XrSystemHandTrackingMeshPropertiesMSFT;
+
+typedef struct XrHandMeshSpaceCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrHandPoseTypeMSFT handPoseType;
+ XrPosef poseInHandMeshSpace;
+} XrHandMeshSpaceCreateInfoMSFT;
+
+typedef struct XrHandMeshUpdateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTime time;
+ XrHandPoseTypeMSFT handPoseType;
+} XrHandMeshUpdateInfoMSFT;
+
+typedef struct XrHandMeshIndexBufferMSFT {
+ uint32_t indexBufferKey;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t* indices;
+} XrHandMeshIndexBufferMSFT;
+
+typedef struct XrHandMeshVertexMSFT {
+ XrVector3f position;
+ XrVector3f normal;
+} XrHandMeshVertexMSFT;
+
+typedef struct XrHandMeshVertexBufferMSFT {
+ XrTime vertexUpdateTime;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrHandMeshVertexMSFT* vertices;
+} XrHandMeshVertexBufferMSFT;
+
+typedef struct XrHandMeshMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 isActive;
+ XrBool32 indexBufferChanged;
+ XrBool32 vertexBufferChanged;
+ XrHandMeshIndexBufferMSFT indexBuffer;
+ XrHandMeshVertexBufferMSFT vertexBuffer;
+} XrHandMeshMSFT;
+
+// XrHandPoseTypeInfoMSFT extends XrHandTrackerCreateInfoEXT
+typedef struct XrHandPoseTypeInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrHandPoseTypeMSFT handPoseType;
+} XrHandPoseTypeInfoMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateHandMeshSpaceMSFT)(XrHandTrackerEXT handTracker, const XrHandMeshSpaceCreateInfoMSFT* createInfo, XrSpace* space);
+typedef XrResult (XRAPI_PTR *PFN_xrUpdateHandMeshMSFT)(XrHandTrackerEXT handTracker, const XrHandMeshUpdateInfoMSFT* updateInfo, XrHandMeshMSFT* handMesh);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateHandMeshSpaceMSFT(
+ XrHandTrackerEXT handTracker,
+ const XrHandMeshSpaceCreateInfoMSFT* createInfo,
+ XrSpace* space);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrUpdateHandMeshMSFT(
+ XrHandTrackerEXT handTracker,
+ const XrHandMeshUpdateInfoMSFT* updateInfo,
+ XrHandMeshMSFT* handMesh);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_secondary_view_configuration 1
+#define XR_MSFT_secondary_view_configuration_SPEC_VERSION 1
+#define XR_MSFT_SECONDARY_VIEW_CONFIGURATION_EXTENSION_NAME "XR_MSFT_secondary_view_configuration"
+// XrSecondaryViewConfigurationSessionBeginInfoMSFT extends XrSessionBeginInfo
+typedef struct XrSecondaryViewConfigurationSessionBeginInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t viewConfigurationCount;
+ const XrViewConfigurationType* enabledViewConfigurationTypes;
+} XrSecondaryViewConfigurationSessionBeginInfoMSFT;
+
+typedef struct XrSecondaryViewConfigurationStateMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrBool32 active;
+} XrSecondaryViewConfigurationStateMSFT;
+
+// XrSecondaryViewConfigurationFrameStateMSFT extends XrFrameState
+typedef struct XrSecondaryViewConfigurationFrameStateMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t viewConfigurationCount;
+ XrSecondaryViewConfigurationStateMSFT* viewConfigurationStates;
+} XrSecondaryViewConfigurationFrameStateMSFT;
+
+typedef struct XrSecondaryViewConfigurationLayerInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+ XrEnvironmentBlendMode environmentBlendMode;
+ uint32_t layerCount;
+ const XrCompositionLayerBaseHeader* const* layers;
+} XrSecondaryViewConfigurationLayerInfoMSFT;
+
+// XrSecondaryViewConfigurationFrameEndInfoMSFT extends XrFrameEndInfo
+typedef struct XrSecondaryViewConfigurationFrameEndInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t viewConfigurationCount;
+ const XrSecondaryViewConfigurationLayerInfoMSFT* viewConfigurationLayersInfo;
+} XrSecondaryViewConfigurationFrameEndInfoMSFT;
+
+// XrSecondaryViewConfigurationSwapchainCreateInfoMSFT extends XrSwapchainCreateInfo
+typedef struct XrSecondaryViewConfigurationSwapchainCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViewConfigurationType viewConfigurationType;
+} XrSecondaryViewConfigurationSwapchainCreateInfoMSFT;
+
+
+
+#define XR_MSFT_first_person_observer 1
+#define XR_MSFT_first_person_observer_SPEC_VERSION 1
+#define XR_MSFT_FIRST_PERSON_OBSERVER_EXTENSION_NAME "XR_MSFT_first_person_observer"
+
+
+#define XR_MSFT_controller_model 1
+
+#define XR_NULL_CONTROLLER_MODEL_KEY_MSFT 0
+
+XR_DEFINE_ATOM(XrControllerModelKeyMSFT)
+#define XR_MSFT_controller_model_SPEC_VERSION 2
+#define XR_MSFT_CONTROLLER_MODEL_EXTENSION_NAME "XR_MSFT_controller_model"
+#define XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT 64
+typedef struct XrControllerModelKeyStateMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrControllerModelKeyMSFT modelKey;
+} XrControllerModelKeyStateMSFT;
+
+typedef struct XrControllerModelNodePropertiesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ char parentNodeName[XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT];
+ char nodeName[XR_MAX_CONTROLLER_MODEL_NODE_NAME_SIZE_MSFT];
+} XrControllerModelNodePropertiesMSFT;
+
+typedef struct XrControllerModelPropertiesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t nodeCapacityInput;
+ uint32_t nodeCountOutput;
+ XrControllerModelNodePropertiesMSFT* nodeProperties;
+} XrControllerModelPropertiesMSFT;
+
+typedef struct XrControllerModelNodeStateMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPosef nodePose;
+} XrControllerModelNodeStateMSFT;
+
+typedef struct XrControllerModelStateMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t nodeCapacityInput;
+ uint32_t nodeCountOutput;
+ XrControllerModelNodeStateMSFT* nodeStates;
+} XrControllerModelStateMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelKeyMSFT)(XrSession session, XrPath topLevelUserPath, XrControllerModelKeyStateMSFT* controllerModelKeyState);
+typedef XrResult (XRAPI_PTR *PFN_xrLoadControllerModelMSFT)(XrSession session, XrControllerModelKeyMSFT modelKey, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, uint8_t* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelPropertiesMSFT)(XrSession session, XrControllerModelKeyMSFT modelKey, XrControllerModelPropertiesMSFT* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrGetControllerModelStateMSFT)(XrSession session, XrControllerModelKeyMSFT modelKey, XrControllerModelStateMSFT* state);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelKeyMSFT(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrControllerModelKeyStateMSFT* controllerModelKeyState);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLoadControllerModelMSFT(
+ XrSession session,
+ XrControllerModelKeyMSFT modelKey,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ uint8_t* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelPropertiesMSFT(
+ XrSession session,
+ XrControllerModelKeyMSFT modelKey,
+ XrControllerModelPropertiesMSFT* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetControllerModelStateMSFT(
+ XrSession session,
+ XrControllerModelKeyMSFT modelKey,
+ XrControllerModelStateMSFT* state);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_win32_appcontainer_compatible 1
+#define XR_EXT_win32_appcontainer_compatible_SPEC_VERSION 1
+#define XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME "XR_EXT_win32_appcontainer_compatible"
+
+
+#define XR_EPIC_view_configuration_fov 1
+#define XR_EPIC_view_configuration_fov_SPEC_VERSION 2
+#define XR_EPIC_VIEW_CONFIGURATION_FOV_EXTENSION_NAME "XR_EPIC_view_configuration_fov"
+// XrViewConfigurationViewFovEPIC extends XrViewConfigurationView
+typedef struct XrViewConfigurationViewFovEPIC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFovf recommendedFov;
+ XrFovf maxMutableFov;
+} XrViewConfigurationViewFovEPIC;
+
+
+
+#define XR_MSFT_composition_layer_reprojection 1
+#define XR_MSFT_composition_layer_reprojection_SPEC_VERSION 1
+#define XR_MSFT_COMPOSITION_LAYER_REPROJECTION_EXTENSION_NAME "XR_MSFT_composition_layer_reprojection"
+
+typedef enum XrReprojectionModeMSFT {
+ XR_REPROJECTION_MODE_DEPTH_MSFT = 1,
+ XR_REPROJECTION_MODE_PLANAR_FROM_DEPTH_MSFT = 2,
+ XR_REPROJECTION_MODE_PLANAR_MANUAL_MSFT = 3,
+ XR_REPROJECTION_MODE_ORIENTATION_ONLY_MSFT = 4,
+ XR_REPROJECTION_MODE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrReprojectionModeMSFT;
+// XrCompositionLayerReprojectionInfoMSFT extends XrCompositionLayerProjection
+typedef struct XrCompositionLayerReprojectionInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrReprojectionModeMSFT reprojectionMode;
+} XrCompositionLayerReprojectionInfoMSFT;
+
+// XrCompositionLayerReprojectionPlaneOverrideMSFT extends XrCompositionLayerProjection
+typedef struct XrCompositionLayerReprojectionPlaneOverrideMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrVector3f position;
+ XrVector3f normal;
+ XrVector3f velocity;
+} XrCompositionLayerReprojectionPlaneOverrideMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateReprojectionModesMSFT)(XrInstance instance, XrSystemId systemId, XrViewConfigurationType viewConfigurationType, uint32_t modeCapacityInput, uint32_t* modeCountOutput, XrReprojectionModeMSFT* modes);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReprojectionModesMSFT(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t modeCapacityInput,
+ uint32_t* modeCountOutput,
+ XrReprojectionModeMSFT* modes);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_HUAWEI_controller_interaction 1
+#define XR_HUAWEI_controller_interaction_SPEC_VERSION 1
+#define XR_HUAWEI_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_HUAWEI_controller_interaction"
+
+
+#define XR_FB_swapchain_update_state 1
+#define XR_FB_swapchain_update_state_SPEC_VERSION 3
+#define XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME "XR_FB_swapchain_update_state"
+typedef struct XR_MAY_ALIAS XrSwapchainStateBaseHeaderFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+} XrSwapchainStateBaseHeaderFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrUpdateSwapchainFB)(XrSwapchain swapchain, const XrSwapchainStateBaseHeaderFB* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSwapchainStateFB)(XrSwapchain swapchain, XrSwapchainStateBaseHeaderFB* state);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrUpdateSwapchainFB(
+ XrSwapchain swapchain,
+ const XrSwapchainStateBaseHeaderFB* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSwapchainStateFB(
+ XrSwapchain swapchain,
+ XrSwapchainStateBaseHeaderFB* state);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_composition_layer_secure_content 1
+#define XR_FB_composition_layer_secure_content_SPEC_VERSION 1
+#define XR_FB_COMPOSITION_LAYER_SECURE_CONTENT_EXTENSION_NAME "XR_FB_composition_layer_secure_content"
+typedef XrFlags64 XrCompositionLayerSecureContentFlagsFB;
+
+// Flag bits for XrCompositionLayerSecureContentFlagsFB
+static const XrCompositionLayerSecureContentFlagsFB XR_COMPOSITION_LAYER_SECURE_CONTENT_EXCLUDE_LAYER_BIT_FB = 0x00000001;
+static const XrCompositionLayerSecureContentFlagsFB XR_COMPOSITION_LAYER_SECURE_CONTENT_REPLACE_LAYER_BIT_FB = 0x00000002;
+
+// XrCompositionLayerSecureContentFB extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerSecureContentFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerSecureContentFlagsFB flags;
+} XrCompositionLayerSecureContentFB;
+
+
+
+#define XR_EXT_dpad_binding 1
+#define XR_EXT_dpad_binding_SPEC_VERSION 1
+#define XR_EXT_DPAD_BINDING_EXTENSION_NAME "XR_EXT_dpad_binding"
+typedef struct XrInteractionProfileDpadBindingEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPath binding;
+ XrActionSet actionSet;
+ float forceThreshold;
+ float forceThresholdReleased;
+ float centerRegion;
+ float wedgeAngle;
+ XrBool32 isSticky;
+ const XrHapticBaseHeader* onHaptic;
+ const XrHapticBaseHeader* offHaptic;
+} XrInteractionProfileDpadBindingEXT;
+
+
+
+#define XR_VALVE_analog_threshold 1
+#define XR_VALVE_analog_threshold_SPEC_VERSION 2
+#define XR_VALVE_ANALOG_THRESHOLD_EXTENSION_NAME "XR_VALVE_analog_threshold"
+typedef struct XrInteractionProfileAnalogThresholdVALVE {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAction action;
+ XrPath binding;
+ float onThreshold;
+ float offThreshold;
+ const XrHapticBaseHeader* onHaptic;
+ const XrHapticBaseHeader* offHaptic;
+} XrInteractionProfileAnalogThresholdVALVE;
+
+
+
+#define XR_EXT_hand_joints_motion_range 1
+#define XR_EXT_hand_joints_motion_range_SPEC_VERSION 1
+#define XR_EXT_HAND_JOINTS_MOTION_RANGE_EXTENSION_NAME "XR_EXT_hand_joints_motion_range"
+
+typedef enum XrHandJointsMotionRangeEXT {
+ XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT = 1,
+ XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT = 2,
+ XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT = 0x7FFFFFFF
+} XrHandJointsMotionRangeEXT;
+// XrHandJointsMotionRangeInfoEXT extends XrHandJointsLocateInfoEXT
+typedef struct XrHandJointsMotionRangeInfoEXT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrHandJointsMotionRangeEXT handJointsMotionRange;
+} XrHandJointsMotionRangeInfoEXT;
+
+
+
+#define XR_EXT_samsung_odyssey_controller 1
+#define XR_EXT_samsung_odyssey_controller_SPEC_VERSION 1
+#define XR_EXT_SAMSUNG_ODYSSEY_CONTROLLER_EXTENSION_NAME "XR_EXT_samsung_odyssey_controller"
+
+
+#define XR_EXT_hp_mixed_reality_controller 1
+#define XR_EXT_hp_mixed_reality_controller_SPEC_VERSION 1
+#define XR_EXT_HP_MIXED_REALITY_CONTROLLER_EXTENSION_NAME "XR_EXT_hp_mixed_reality_controller"
+
+
+#define XR_MND_swapchain_usage_input_attachment_bit 1
+#define XR_MND_swapchain_usage_input_attachment_bit_SPEC_VERSION 2
+#define XR_MND_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_EXTENSION_NAME "XR_MND_swapchain_usage_input_attachment_bit"
+
+
+#define XR_MSFT_scene_understanding 1
+
+ XR_DEFINE_HANDLE(XrSceneObserverMSFT)
+
+
+ XR_DEFINE_HANDLE(XrSceneMSFT)
+
+#define XR_MSFT_scene_understanding_SPEC_VERSION 1
+#define XR_MSFT_SCENE_UNDERSTANDING_EXTENSION_NAME "XR_MSFT_scene_understanding"
+
+typedef enum XrSceneComputeFeatureMSFT {
+ XR_SCENE_COMPUTE_FEATURE_PLANE_MSFT = 1,
+ XR_SCENE_COMPUTE_FEATURE_PLANE_MESH_MSFT = 2,
+ XR_SCENE_COMPUTE_FEATURE_VISUAL_MESH_MSFT = 3,
+ XR_SCENE_COMPUTE_FEATURE_COLLIDER_MESH_MSFT = 4,
+ XR_SCENE_COMPUTE_FEATURE_SERIALIZE_SCENE_MSFT = 1000098000,
+ XR_SCENE_COMPUTE_FEATURE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSceneComputeFeatureMSFT;
+
+typedef enum XrSceneComputeConsistencyMSFT {
+ XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_COMPLETE_MSFT = 1,
+ XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_INCOMPLETE_FAST_MSFT = 2,
+ XR_SCENE_COMPUTE_CONSISTENCY_OCCLUSION_OPTIMIZED_MSFT = 3,
+ XR_SCENE_COMPUTE_CONSISTENCY_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSceneComputeConsistencyMSFT;
+
+typedef enum XrMeshComputeLodMSFT {
+ XR_MESH_COMPUTE_LOD_COARSE_MSFT = 1,
+ XR_MESH_COMPUTE_LOD_MEDIUM_MSFT = 2,
+ XR_MESH_COMPUTE_LOD_FINE_MSFT = 3,
+ XR_MESH_COMPUTE_LOD_UNLIMITED_MSFT = 4,
+ XR_MESH_COMPUTE_LOD_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrMeshComputeLodMSFT;
+
+typedef enum XrSceneComponentTypeMSFT {
+ XR_SCENE_COMPONENT_TYPE_INVALID_MSFT = -1,
+ XR_SCENE_COMPONENT_TYPE_OBJECT_MSFT = 1,
+ XR_SCENE_COMPONENT_TYPE_PLANE_MSFT = 2,
+ XR_SCENE_COMPONENT_TYPE_VISUAL_MESH_MSFT = 3,
+ XR_SCENE_COMPONENT_TYPE_COLLIDER_MESH_MSFT = 4,
+ XR_SCENE_COMPONENT_TYPE_SERIALIZED_SCENE_FRAGMENT_MSFT = 1000098000,
+ XR_SCENE_COMPONENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSceneComponentTypeMSFT;
+
+typedef enum XrSceneObjectTypeMSFT {
+ XR_SCENE_OBJECT_TYPE_UNCATEGORIZED_MSFT = -1,
+ XR_SCENE_OBJECT_TYPE_BACKGROUND_MSFT = 1,
+ XR_SCENE_OBJECT_TYPE_WALL_MSFT = 2,
+ XR_SCENE_OBJECT_TYPE_FLOOR_MSFT = 3,
+ XR_SCENE_OBJECT_TYPE_CEILING_MSFT = 4,
+ XR_SCENE_OBJECT_TYPE_PLATFORM_MSFT = 5,
+ XR_SCENE_OBJECT_TYPE_INFERRED_MSFT = 6,
+ XR_SCENE_OBJECT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSceneObjectTypeMSFT;
+
+typedef enum XrScenePlaneAlignmentTypeMSFT {
+ XR_SCENE_PLANE_ALIGNMENT_TYPE_NON_ORTHOGONAL_MSFT = 0,
+ XR_SCENE_PLANE_ALIGNMENT_TYPE_HORIZONTAL_MSFT = 1,
+ XR_SCENE_PLANE_ALIGNMENT_TYPE_VERTICAL_MSFT = 2,
+ XR_SCENE_PLANE_ALIGNMENT_TYPE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrScenePlaneAlignmentTypeMSFT;
+
+typedef enum XrSceneComputeStateMSFT {
+ XR_SCENE_COMPUTE_STATE_NONE_MSFT = 0,
+ XR_SCENE_COMPUTE_STATE_UPDATING_MSFT = 1,
+ XR_SCENE_COMPUTE_STATE_COMPLETED_MSFT = 2,
+ XR_SCENE_COMPUTE_STATE_COMPLETED_WITH_ERROR_MSFT = 3,
+ XR_SCENE_COMPUTE_STATE_MAX_ENUM_MSFT = 0x7FFFFFFF
+} XrSceneComputeStateMSFT;
+typedef struct XrUuidMSFT {
+ uint8_t bytes[16];
+} XrUuidMSFT;
+
+typedef struct XrSceneObserverCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSceneObserverCreateInfoMSFT;
+
+typedef struct XrSceneCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSceneCreateInfoMSFT;
+
+typedef struct XrSceneSphereBoundMSFT {
+ XrVector3f center;
+ float radius;
+} XrSceneSphereBoundMSFT;
+
+typedef struct XrSceneOrientedBoxBoundMSFT {
+ XrPosef pose;
+ XrVector3f extents;
+} XrSceneOrientedBoxBoundMSFT;
+
+typedef struct XrSceneFrustumBoundMSFT {
+ XrPosef pose;
+ XrFovf fov;
+ float farDistance;
+} XrSceneFrustumBoundMSFT;
+
+typedef struct XrSceneBoundsMSFT {
+ XrSpace space;
+ XrTime time;
+ uint32_t sphereCount;
+ const XrSceneSphereBoundMSFT* spheres;
+ uint32_t boxCount;
+ const XrSceneOrientedBoxBoundMSFT* boxes;
+ uint32_t frustumCount;
+ const XrSceneFrustumBoundMSFT* frustums;
+} XrSceneBoundsMSFT;
+
+typedef struct XrNewSceneComputeInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t requestedFeatureCount;
+ const XrSceneComputeFeatureMSFT* requestedFeatures;
+ XrSceneComputeConsistencyMSFT consistency;
+ XrSceneBoundsMSFT bounds;
+} XrNewSceneComputeInfoMSFT;
+
+// XrVisualMeshComputeLodInfoMSFT extends XrNewSceneComputeInfoMSFT
+typedef struct XrVisualMeshComputeLodInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrMeshComputeLodMSFT lod;
+} XrVisualMeshComputeLodInfoMSFT;
+
+typedef struct XrSceneComponentMSFT {
+ XrSceneComponentTypeMSFT componentType;
+ XrUuidMSFT id;
+ XrUuidMSFT parentId;
+ XrTime updateTime;
+} XrSceneComponentMSFT;
+
+typedef struct XrSceneComponentsMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t componentCapacityInput;
+ uint32_t componentCountOutput;
+ XrSceneComponentMSFT* components;
+} XrSceneComponentsMSFT;
+
+typedef struct XrSceneComponentsGetInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSceneComponentTypeMSFT componentType;
+} XrSceneComponentsGetInfoMSFT;
+
+typedef struct XrSceneComponentLocationMSFT {
+ XrSpaceLocationFlags flags;
+ XrPosef pose;
+} XrSceneComponentLocationMSFT;
+
+typedef struct XrSceneComponentLocationsMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t locationCount;
+ XrSceneComponentLocationMSFT* locations;
+} XrSceneComponentLocationsMSFT;
+
+typedef struct XrSceneComponentsLocateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace baseSpace;
+ XrTime time;
+ uint32_t componentIdCount;
+ const XrUuidMSFT* componentIds;
+} XrSceneComponentsLocateInfoMSFT;
+
+typedef struct XrSceneObjectMSFT {
+ XrSceneObjectTypeMSFT objectType;
+} XrSceneObjectMSFT;
+
+// XrSceneObjectsMSFT extends XrSceneComponentsMSFT
+typedef struct XrSceneObjectsMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t sceneObjectCount;
+ XrSceneObjectMSFT* sceneObjects;
+} XrSceneObjectsMSFT;
+
+// XrSceneComponentParentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
+typedef struct XrSceneComponentParentFilterInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrUuidMSFT parentId;
+} XrSceneComponentParentFilterInfoMSFT;
+
+// XrSceneObjectTypesFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
+typedef struct XrSceneObjectTypesFilterInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t objectTypeCount;
+ const XrSceneObjectTypeMSFT* objectTypes;
+} XrSceneObjectTypesFilterInfoMSFT;
+
+typedef struct XrScenePlaneMSFT {
+ XrScenePlaneAlignmentTypeMSFT alignment;
+ XrExtent2Df size;
+ uint64_t meshBufferId;
+ XrBool32 supportsIndicesUint16;
+} XrScenePlaneMSFT;
+
+// XrScenePlanesMSFT extends XrSceneComponentsMSFT
+typedef struct XrScenePlanesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t scenePlaneCount;
+ XrScenePlaneMSFT* scenePlanes;
+} XrScenePlanesMSFT;
+
+// XrScenePlaneAlignmentFilterInfoMSFT extends XrSceneComponentsGetInfoMSFT
+typedef struct XrScenePlaneAlignmentFilterInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t alignmentCount;
+ const XrScenePlaneAlignmentTypeMSFT* alignments;
+} XrScenePlaneAlignmentFilterInfoMSFT;
+
+typedef struct XrSceneMeshMSFT {
+ uint64_t meshBufferId;
+ XrBool32 supportsIndicesUint16;
+} XrSceneMeshMSFT;
+
+// XrSceneMeshesMSFT extends XrSceneComponentsMSFT
+typedef struct XrSceneMeshesMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t sceneMeshCount;
+ XrSceneMeshMSFT* sceneMeshes;
+} XrSceneMeshesMSFT;
+
+typedef struct XrSceneMeshBuffersGetInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint64_t meshBufferId;
+} XrSceneMeshBuffersGetInfoMSFT;
+
+typedef struct XrSceneMeshBuffersMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+} XrSceneMeshBuffersMSFT;
+
+typedef struct XrSceneMeshVertexBufferMSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrVector3f* vertices;
+} XrSceneMeshVertexBufferMSFT;
+
+typedef struct XrSceneMeshIndicesUint32MSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint32_t* indices;
+} XrSceneMeshIndicesUint32MSFT;
+
+typedef struct XrSceneMeshIndicesUint16MSFT {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ uint16_t* indices;
+} XrSceneMeshIndicesUint16MSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSceneComputeFeaturesMSFT)(XrInstance instance, XrSystemId systemId, uint32_t featureCapacityInput, uint32_t* featureCountOutput, XrSceneComputeFeatureMSFT* features);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSceneObserverMSFT)(XrSession session, const XrSceneObserverCreateInfoMSFT* createInfo, XrSceneObserverMSFT* sceneObserver);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySceneObserverMSFT)(XrSceneObserverMSFT sceneObserver);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSceneMSFT)(XrSceneObserverMSFT sceneObserver, const XrSceneCreateInfoMSFT* createInfo, XrSceneMSFT* scene);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySceneMSFT)(XrSceneMSFT scene);
+typedef XrResult (XRAPI_PTR *PFN_xrComputeNewSceneMSFT)(XrSceneObserverMSFT sceneObserver, const XrNewSceneComputeInfoMSFT* computeInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSceneComputeStateMSFT)(XrSceneObserverMSFT sceneObserver, XrSceneComputeStateMSFT* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSceneComponentsMSFT)(XrSceneMSFT scene, const XrSceneComponentsGetInfoMSFT* getInfo, XrSceneComponentsMSFT* components);
+typedef XrResult (XRAPI_PTR *PFN_xrLocateSceneComponentsMSFT)(XrSceneMSFT scene, const XrSceneComponentsLocateInfoMSFT* locateInfo, XrSceneComponentLocationsMSFT* locations);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSceneMeshBuffersMSFT)(XrSceneMSFT scene, const XrSceneMeshBuffersGetInfoMSFT* getInfo, XrSceneMeshBuffersMSFT* buffers);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSceneComputeFeaturesMSFT(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t featureCapacityInput,
+ uint32_t* featureCountOutput,
+ XrSceneComputeFeatureMSFT* features);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSceneObserverMSFT(
+ XrSession session,
+ const XrSceneObserverCreateInfoMSFT* createInfo,
+ XrSceneObserverMSFT* sceneObserver);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySceneObserverMSFT(
+ XrSceneObserverMSFT sceneObserver);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSceneMSFT(
+ XrSceneObserverMSFT sceneObserver,
+ const XrSceneCreateInfoMSFT* createInfo,
+ XrSceneMSFT* scene);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySceneMSFT(
+ XrSceneMSFT scene);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrComputeNewSceneMSFT(
+ XrSceneObserverMSFT sceneObserver,
+ const XrNewSceneComputeInfoMSFT* computeInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSceneComputeStateMSFT(
+ XrSceneObserverMSFT sceneObserver,
+ XrSceneComputeStateMSFT* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSceneComponentsMSFT(
+ XrSceneMSFT scene,
+ const XrSceneComponentsGetInfoMSFT* getInfo,
+ XrSceneComponentsMSFT* components);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLocateSceneComponentsMSFT(
+ XrSceneMSFT scene,
+ const XrSceneComponentsLocateInfoMSFT* locateInfo,
+ XrSceneComponentLocationsMSFT* locations);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSceneMeshBuffersMSFT(
+ XrSceneMSFT scene,
+ const XrSceneMeshBuffersGetInfoMSFT* getInfo,
+ XrSceneMeshBuffersMSFT* buffers);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_scene_understanding_serialization 1
+#define XR_MSFT_scene_understanding_serialization_SPEC_VERSION 1
+#define XR_MSFT_SCENE_UNDERSTANDING_SERIALIZATION_EXTENSION_NAME "XR_MSFT_scene_understanding_serialization"
+typedef struct XrSerializedSceneFragmentDataGetInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrUuidMSFT sceneFragmentId;
+} XrSerializedSceneFragmentDataGetInfoMSFT;
+
+typedef struct XrDeserializeSceneFragmentMSFT {
+ uint32_t bufferSize;
+ const uint8_t* buffer;
+} XrDeserializeSceneFragmentMSFT;
+
+typedef struct XrSceneDeserializeInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t fragmentCount;
+ const XrDeserializeSceneFragmentMSFT* fragments;
+} XrSceneDeserializeInfoMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrDeserializeSceneMSFT)(XrSceneObserverMSFT sceneObserver, const XrSceneDeserializeInfoMSFT* deserializeInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSerializedSceneFragmentDataMSFT)(XrSceneMSFT scene, const XrSerializedSceneFragmentDataGetInfoMSFT* getInfo, uint32_t countInput, uint32_t* readOutput, uint8_t* buffer);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrDeserializeSceneMSFT(
+ XrSceneObserverMSFT sceneObserver,
+ const XrSceneDeserializeInfoMSFT* deserializeInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSerializedSceneFragmentDataMSFT(
+ XrSceneMSFT scene,
+ const XrSerializedSceneFragmentDataGetInfoMSFT* getInfo,
+ uint32_t countInput,
+ uint32_t* readOutput,
+ uint8_t* buffer);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_display_refresh_rate 1
+#define XR_FB_display_refresh_rate_SPEC_VERSION 1
+#define XR_FB_DISPLAY_REFRESH_RATE_EXTENSION_NAME "XR_FB_display_refresh_rate"
+typedef struct XrEventDataDisplayRefreshRateChangedFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float fromDisplayRefreshRate;
+ float toDisplayRefreshRate;
+} XrEventDataDisplayRefreshRateChangedFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateDisplayRefreshRatesFB)(XrSession session, uint32_t displayRefreshRateCapacityInput, uint32_t* displayRefreshRateCountOutput, float* displayRefreshRates);
+typedef XrResult (XRAPI_PTR *PFN_xrGetDisplayRefreshRateFB)(XrSession session, float* displayRefreshRate);
+typedef XrResult (XRAPI_PTR *PFN_xrRequestDisplayRefreshRateFB)(XrSession session, float displayRefreshRate);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateDisplayRefreshRatesFB(
+ XrSession session,
+ uint32_t displayRefreshRateCapacityInput,
+ uint32_t* displayRefreshRateCountOutput,
+ float* displayRefreshRates);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetDisplayRefreshRateFB(
+ XrSession session,
+ float* displayRefreshRate);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrRequestDisplayRefreshRateFB(
+ XrSession session,
+ float displayRefreshRate);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_HTC_vive_cosmos_controller_interaction 1
+#define XR_HTC_vive_cosmos_controller_interaction_SPEC_VERSION 1
+#define XR_HTC_VIVE_COSMOS_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_HTC_vive_cosmos_controller_interaction"
+
+
+#define XR_HTCX_vive_tracker_interaction 1
+#define XR_HTCX_vive_tracker_interaction_SPEC_VERSION 1
+#define XR_HTCX_VIVE_TRACKER_INTERACTION_EXTENSION_NAME "XR_HTCX_vive_tracker_interaction"
+typedef struct XrViveTrackerPathsHTCX {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPath persistentPath;
+ XrPath rolePath;
+} XrViveTrackerPathsHTCX;
+
+typedef struct XrEventDataViveTrackerConnectedHTCX {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrViveTrackerPathsHTCX* paths;
+} XrEventDataViveTrackerConnectedHTCX;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateViveTrackerPathsHTCX)(XrInstance instance, uint32_t pathCapacityInput, uint32_t* pathCountOutput, XrViveTrackerPathsHTCX* paths);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViveTrackerPathsHTCX(
+ XrInstance instance,
+ uint32_t pathCapacityInput,
+ uint32_t* pathCountOutput,
+ XrViveTrackerPathsHTCX* paths);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_HTC_facial_tracking 1
+
+#define XR_FACIAL_EXPRESSION_EYE_COUNT_HTC 14
+
+
+#define XR_FACIAL_EXPRESSION_LIP_COUNT_HTC 37
+
+XR_DEFINE_HANDLE(XrFacialTrackerHTC)
+#define XR_HTC_facial_tracking_SPEC_VERSION 1
+#define XR_HTC_FACIAL_TRACKING_EXTENSION_NAME "XR_HTC_facial_tracking"
+
+typedef enum XrEyeExpressionHTC {
+ XR_EYE_EXPRESSION_LEFT_BLINK_HTC = 0,
+ XR_EYE_EXPRESSION_LEFT_WIDE_HTC = 1,
+ XR_EYE_EXPRESSION_RIGHT_BLINK_HTC = 2,
+ XR_EYE_EXPRESSION_RIGHT_WIDE_HTC = 3,
+ XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC = 4,
+ XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC = 5,
+ XR_EYE_EXPRESSION_LEFT_DOWN_HTC = 6,
+ XR_EYE_EXPRESSION_RIGHT_DOWN_HTC = 7,
+ XR_EYE_EXPRESSION_LEFT_OUT_HTC = 8,
+ XR_EYE_EXPRESSION_RIGHT_IN_HTC = 9,
+ XR_EYE_EXPRESSION_LEFT_IN_HTC = 10,
+ XR_EYE_EXPRESSION_RIGHT_OUT_HTC = 11,
+ XR_EYE_EXPRESSION_LEFT_UP_HTC = 12,
+ XR_EYE_EXPRESSION_RIGHT_UP_HTC = 13,
+ XR_EYE_EXPRESSION_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrEyeExpressionHTC;
+
+typedef enum XrLipExpressionHTC {
+ XR_LIP_EXPRESSION_JAW_RIGHT_HTC = 0,
+ XR_LIP_EXPRESSION_JAW_LEFT_HTC = 1,
+ XR_LIP_EXPRESSION_JAW_FORWARD_HTC = 2,
+ XR_LIP_EXPRESSION_JAW_OPEN_HTC = 3,
+ XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC = 4,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC = 5,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC = 6,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC = 7,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC = 8,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC = 9,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC = 10,
+ XR_LIP_EXPRESSION_MOUTH_POUT_HTC = 11,
+ XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC = 12,
+ XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC = 13,
+ XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC = 14,
+ XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC = 15,
+ XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC = 16,
+ XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC = 17,
+ XR_LIP_EXPRESSION_CHEEK_SUCK_HTC = 18,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC = 19,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC = 20,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC = 21,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC = 22,
+ XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC = 23,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC = 24,
+ XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC = 25,
+ XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC = 26,
+ XR_LIP_EXPRESSION_TONGUE_LEFT_HTC = 27,
+ XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC = 28,
+ XR_LIP_EXPRESSION_TONGUE_UP_HTC = 29,
+ XR_LIP_EXPRESSION_TONGUE_DOWN_HTC = 30,
+ XR_LIP_EXPRESSION_TONGUE_ROLL_HTC = 31,
+ XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC = 32,
+ XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC = 33,
+ XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC = 34,
+ XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC = 35,
+ XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC = 36,
+ XR_LIP_EXPRESSION_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrLipExpressionHTC;
+
+typedef enum XrFacialTrackingTypeHTC {
+ XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC = 1,
+ XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC = 2,
+ XR_FACIAL_TRACKING_TYPE_MAX_ENUM_HTC = 0x7FFFFFFF
+} XrFacialTrackingTypeHTC;
+// XrSystemFacialTrackingPropertiesHTC extends XrSystemProperties
+typedef struct XrSystemFacialTrackingPropertiesHTC {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportEyeFacialTracking;
+ XrBool32 supportLipFacialTracking;
+} XrSystemFacialTrackingPropertiesHTC;
+
+typedef struct XrFacialExpressionsHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 isActive;
+ XrTime sampleTime;
+ uint32_t expressionCount;
+ float* expressionWeightings;
+} XrFacialExpressionsHTC;
+
+typedef struct XrFacialTrackerCreateInfoHTC {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrFacialTrackingTypeHTC facialTrackingType;
+} XrFacialTrackerCreateInfoHTC;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateFacialTrackerHTC)(XrSession session, const XrFacialTrackerCreateInfoHTC* createInfo, XrFacialTrackerHTC* facialTracker);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyFacialTrackerHTC)(XrFacialTrackerHTC facialTracker);
+typedef XrResult (XRAPI_PTR *PFN_xrGetFacialExpressionsHTC)(XrFacialTrackerHTC facialTracker, XrFacialExpressionsHTC* facialExpressions);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateFacialTrackerHTC(
+ XrSession session,
+ const XrFacialTrackerCreateInfoHTC* createInfo,
+ XrFacialTrackerHTC* facialTracker);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyFacialTrackerHTC(
+ XrFacialTrackerHTC facialTracker);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetFacialExpressionsHTC(
+ XrFacialTrackerHTC facialTracker,
+ XrFacialExpressionsHTC* facialExpressions);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_HTC_vive_focus3_controller_interaction 1
+#define XR_HTC_vive_focus3_controller_interaction_SPEC_VERSION 2
+#define XR_HTC_VIVE_FOCUS3_CONTROLLER_INTERACTION_EXTENSION_NAME "XR_HTC_vive_focus3_controller_interaction"
+
+
+#define XR_HTC_hand_interaction 1
+#define XR_HTC_hand_interaction_SPEC_VERSION 1
+#define XR_HTC_HAND_INTERACTION_EXTENSION_NAME "XR_HTC_hand_interaction"
+
+
+#define XR_HTC_vive_wrist_tracker_interaction 1
+#define XR_HTC_vive_wrist_tracker_interaction_SPEC_VERSION 1
+#define XR_HTC_VIVE_WRIST_TRACKER_INTERACTION_EXTENSION_NAME "XR_HTC_vive_wrist_tracker_interaction"
+
+
+#define XR_FB_color_space 1
+#define XR_FB_color_space_SPEC_VERSION 2
+#define XR_FB_COLOR_SPACE_EXTENSION_NAME "XR_FB_color_space"
+
+typedef enum XrColorSpaceFB {
+ XR_COLOR_SPACE_UNMANAGED_FB = 0,
+ XR_COLOR_SPACE_REC2020_FB = 1,
+ XR_COLOR_SPACE_REC709_FB = 2,
+ XR_COLOR_SPACE_RIFT_CV1_FB = 3,
+ XR_COLOR_SPACE_RIFT_S_FB = 4,
+ XR_COLOR_SPACE_QUEST_FB = 5,
+ XR_COLOR_SPACE_P3_FB = 6,
+ XR_COLOR_SPACE_ADOBE_RGB_FB = 7,
+ XR_COLOR_SPACE_MAX_ENUM_FB = 0x7FFFFFFF
+} XrColorSpaceFB;
+// XrSystemColorSpacePropertiesFB extends XrSystemProperties
+typedef struct XrSystemColorSpacePropertiesFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrColorSpaceFB colorSpace;
+} XrSystemColorSpacePropertiesFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateColorSpacesFB)(XrSession session, uint32_t colorSpaceCapacityInput, uint32_t* colorSpaceCountOutput, XrColorSpaceFB* colorSpaces);
+typedef XrResult (XRAPI_PTR *PFN_xrSetColorSpaceFB)(XrSession session, const XrColorSpaceFB colorspace);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateColorSpacesFB(
+ XrSession session,
+ uint32_t colorSpaceCapacityInput,
+ uint32_t* colorSpaceCountOutput,
+ XrColorSpaceFB* colorSpaces);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetColorSpaceFB(
+ XrSession session,
+ const XrColorSpaceFB colorspace);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_hand_tracking_mesh 1
+#define XR_FB_hand_tracking_mesh_SPEC_VERSION 2
+#define XR_FB_HAND_TRACKING_MESH_EXTENSION_NAME "XR_FB_hand_tracking_mesh"
+typedef struct XrVector4sFB {
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ int16_t w;
+} XrVector4sFB;
+
+typedef struct XrHandTrackingMeshFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t jointCapacityInput;
+ uint32_t jointCountOutput;
+ XrPosef* jointBindPoses;
+ float* jointRadii;
+ XrHandJointEXT* jointParents;
+ uint32_t vertexCapacityInput;
+ uint32_t vertexCountOutput;
+ XrVector3f* vertexPositions;
+ XrVector3f* vertexNormals;
+ XrVector2f* vertexUVs;
+ XrVector4sFB* vertexBlendIndices;
+ XrVector4f* vertexBlendWeights;
+ uint32_t indexCapacityInput;
+ uint32_t indexCountOutput;
+ int16_t* indices;
+} XrHandTrackingMeshFB;
+
+// XrHandTrackingScaleFB extends XrHandJointLocationsEXT
+typedef struct XrHandTrackingScaleFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ float sensorOutput;
+ float currentOutput;
+ XrBool32 overrideHandScale;
+ float overrideValueInput;
+} XrHandTrackingScaleFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetHandMeshFB)(XrHandTrackerEXT handTracker, XrHandTrackingMeshFB* mesh);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetHandMeshFB(
+ XrHandTrackerEXT handTracker,
+ XrHandTrackingMeshFB* mesh);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_hand_tracking_aim 1
+#define XR_FB_hand_tracking_aim_SPEC_VERSION 2
+#define XR_FB_HAND_TRACKING_AIM_EXTENSION_NAME "XR_FB_hand_tracking_aim"
+typedef XrFlags64 XrHandTrackingAimFlagsFB;
+
+// Flag bits for XrHandTrackingAimFlagsFB
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_COMPUTED_BIT_FB = 0x00000001;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_VALID_BIT_FB = 0x00000002;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_INDEX_PINCHING_BIT_FB = 0x00000004;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_MIDDLE_PINCHING_BIT_FB = 0x00000008;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_RING_PINCHING_BIT_FB = 0x00000010;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_LITTLE_PINCHING_BIT_FB = 0x00000020;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_SYSTEM_GESTURE_BIT_FB = 0x00000040;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_DOMINANT_HAND_BIT_FB = 0x00000080;
+static const XrHandTrackingAimFlagsFB XR_HAND_TRACKING_AIM_MENU_PRESSED_BIT_FB = 0x00000100;
+
+// XrHandTrackingAimStateFB extends XrHandJointLocationsEXT
+typedef struct XrHandTrackingAimStateFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrHandTrackingAimFlagsFB status;
+ XrPosef aimPose;
+ float pinchStrengthIndex;
+ float pinchStrengthMiddle;
+ float pinchStrengthRing;
+ float pinchStrengthLittle;
+} XrHandTrackingAimStateFB;
+
+
+
+#define XR_FB_hand_tracking_capsules 1
+#define XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB 2
+#define XR_HAND_TRACKING_CAPSULE_COUNT_FB 19
+#define XR_FB_hand_tracking_capsules_SPEC_VERSION 3
+#define XR_FB_HAND_TRACKING_CAPSULES_EXTENSION_NAME "XR_FB_hand_tracking_capsules"
+#define XR_FB_HAND_TRACKING_CAPSULE_POINT_COUNT XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB
+#define XR_FB_HAND_TRACKING_CAPSULE_COUNT XR_HAND_TRACKING_CAPSULE_COUNT_FB
+typedef struct XrHandCapsuleFB {
+ XrVector3f points[XR_HAND_TRACKING_CAPSULE_POINT_COUNT_FB];
+ float radius;
+ XrHandJointEXT joint;
+} XrHandCapsuleFB;
+
+// XrHandTrackingCapsulesStateFB extends XrHandJointLocationsEXT
+typedef struct XrHandTrackingCapsulesStateFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrHandCapsuleFB capsules[XR_HAND_TRACKING_CAPSULE_COUNT_FB];
+} XrHandTrackingCapsulesStateFB;
+
+
+
+#define XR_FB_spatial_entity 1
+XR_DEFINE_ATOM(XrAsyncRequestIdFB)
+#define XR_UUID_SIZE_EXT 16
+#define XR_FB_spatial_entity_SPEC_VERSION 1
+#define XR_FB_SPATIAL_ENTITY_EXTENSION_NAME "XR_FB_spatial_entity"
+
+typedef enum XrSpaceComponentTypeFB {
+ XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB = 0,
+ XR_SPACE_COMPONENT_TYPE_STORABLE_FB = 1,
+ XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB = 7,
+ XR_SPACE_COMPONENT_TYPE_MAX_ENUM_FB = 0x7FFFFFFF
+} XrSpaceComponentTypeFB;
+// XrSystemSpatialEntityPropertiesFB extends XrSystemProperties
+typedef struct XrSystemSpatialEntityPropertiesFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 supportsSpatialEntity;
+} XrSystemSpatialEntityPropertiesFB;
+
+typedef struct XrSpatialAnchorCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace space;
+ XrPosef poseInSpace;
+ XrTime time;
+} XrSpatialAnchorCreateInfoFB;
+
+typedef struct XrSpaceComponentStatusSetInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpaceComponentTypeFB componentType;
+ XrBool32 enabled;
+ XrDuration timeout;
+} XrSpaceComponentStatusSetInfoFB;
+
+typedef struct XrSpaceComponentStatusFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 enabled;
+ XrBool32 changePending;
+} XrSpaceComponentStatusFB;
+
+typedef struct XrUuidEXT {
+ uint8_t data[XR_UUID_SIZE_EXT];
+} XrUuidEXT;
+
+typedef struct XrEventDataSpatialAnchorCreateCompleteFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+ XrResult result;
+ XrSpace space;
+ XrUuidEXT uuid;
+} XrEventDataSpatialAnchorCreateCompleteFB;
+
+typedef struct XrEventDataSpaceSetStatusCompleteFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+ XrResult result;
+ XrSpace space;
+ XrUuidEXT uuid;
+ XrSpaceComponentTypeFB componentType;
+ XrBool32 enabled;
+} XrEventDataSpaceSetStatusCompleteFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFB)(XrSession session, const XrSpatialAnchorCreateInfoFB* info, XrAsyncRequestIdFB* requestId);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSpaceUuidFB)(XrSpace space, XrUuidEXT* uuid);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateSpaceSupportedComponentsFB)(XrSpace space, uint32_t componentTypeCapacityInput, uint32_t* componentTypeCountOutput, XrSpaceComponentTypeFB* componentTypes);
+typedef XrResult (XRAPI_PTR *PFN_xrSetSpaceComponentStatusFB)(XrSpace space, const XrSpaceComponentStatusSetInfoFB* info, XrAsyncRequestIdFB* requestId);
+typedef XrResult (XRAPI_PTR *PFN_xrGetSpaceComponentStatusFB)(XrSpace space, XrSpaceComponentTypeFB componentType, XrSpaceComponentStatusFB* status);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFB(
+ XrSession session,
+ const XrSpatialAnchorCreateInfoFB* info,
+ XrAsyncRequestIdFB* requestId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceUuidFB(
+ XrSpace space,
+ XrUuidEXT* uuid);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSpaceSupportedComponentsFB(
+ XrSpace space,
+ uint32_t componentTypeCapacityInput,
+ uint32_t* componentTypeCountOutput,
+ XrSpaceComponentTypeFB* componentTypes);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetSpaceComponentStatusFB(
+ XrSpace space,
+ const XrSpaceComponentStatusSetInfoFB* info,
+ XrAsyncRequestIdFB* requestId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceComponentStatusFB(
+ XrSpace space,
+ XrSpaceComponentTypeFB componentType,
+ XrSpaceComponentStatusFB* status);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_foveation 1
+XR_DEFINE_HANDLE(XrFoveationProfileFB)
+#define XR_FB_foveation_SPEC_VERSION 1
+#define XR_FB_FOVEATION_EXTENSION_NAME "XR_FB_foveation"
+typedef XrFlags64 XrSwapchainCreateFoveationFlagsFB;
+
+// Flag bits for XrSwapchainCreateFoveationFlagsFB
+static const XrSwapchainCreateFoveationFlagsFB XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB = 0x00000001;
+static const XrSwapchainCreateFoveationFlagsFB XR_SWAPCHAIN_CREATE_FOVEATION_FRAGMENT_DENSITY_MAP_BIT_FB = 0x00000002;
+
+typedef XrFlags64 XrSwapchainStateFoveationFlagsFB;
+
+// Flag bits for XrSwapchainStateFoveationFlagsFB
+
+typedef struct XrFoveationProfileCreateInfoFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+} XrFoveationProfileCreateInfoFB;
+
+// XrSwapchainCreateInfoFoveationFB extends XrSwapchainCreateInfo
+typedef struct XrSwapchainCreateInfoFoveationFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSwapchainCreateFoveationFlagsFB flags;
+} XrSwapchainCreateInfoFoveationFB;
+
+typedef struct XrSwapchainStateFoveationFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrSwapchainStateFoveationFlagsFB flags;
+ XrFoveationProfileFB profile;
+} XrSwapchainStateFoveationFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateFoveationProfileFB)(XrSession session, const XrFoveationProfileCreateInfoFB* createInfo, XrFoveationProfileFB* profile);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyFoveationProfileFB)(XrFoveationProfileFB profile);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateFoveationProfileFB(
+ XrSession session,
+ const XrFoveationProfileCreateInfoFB* createInfo,
+ XrFoveationProfileFB* profile);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyFoveationProfileFB(
+ XrFoveationProfileFB profile);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_foveation_configuration 1
+#define XR_FB_foveation_configuration_SPEC_VERSION 1
+#define XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME "XR_FB_foveation_configuration"
+
+typedef enum XrFoveationLevelFB {
+ XR_FOVEATION_LEVEL_NONE_FB = 0,
+ XR_FOVEATION_LEVEL_LOW_FB = 1,
+ XR_FOVEATION_LEVEL_MEDIUM_FB = 2,
+ XR_FOVEATION_LEVEL_HIGH_FB = 3,
+ XR_FOVEATION_LEVEL_MAX_ENUM_FB = 0x7FFFFFFF
+} XrFoveationLevelFB;
+
+typedef enum XrFoveationDynamicFB {
+ XR_FOVEATION_DYNAMIC_DISABLED_FB = 0,
+ XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB = 1,
+ XR_FOVEATION_DYNAMIC_MAX_ENUM_FB = 0x7FFFFFFF
+} XrFoveationDynamicFB;
+// XrFoveationLevelProfileCreateInfoFB extends XrFoveationProfileCreateInfoFB
+typedef struct XrFoveationLevelProfileCreateInfoFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrFoveationLevelFB level;
+ float verticalOffset;
+ XrFoveationDynamicFB dynamic;
+} XrFoveationLevelProfileCreateInfoFB;
+
+
+
+#define XR_FB_keyboard_tracking 1
+#define XR_FB_keyboard_tracking_SPEC_VERSION 1
+#define XR_FB_KEYBOARD_TRACKING_EXTENSION_NAME "XR_FB_keyboard_tracking"
+#define XR_MAX_KEYBOARD_TRACKING_NAME_SIZE_FB 128
+typedef XrFlags64 XrKeyboardTrackingFlagsFB;
+
+// Flag bits for XrKeyboardTrackingFlagsFB
+static const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_EXISTS_BIT_FB = 0x00000001;
+static const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_LOCAL_BIT_FB = 0x00000002;
+static const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_REMOTE_BIT_FB = 0x00000004;
+static const XrKeyboardTrackingFlagsFB XR_KEYBOARD_TRACKING_CONNECTED_BIT_FB = 0x00000008;
+
+typedef XrFlags64 XrKeyboardTrackingQueryFlagsFB;
+
+// Flag bits for XrKeyboardTrackingQueryFlagsFB
+static const XrKeyboardTrackingQueryFlagsFB XR_KEYBOARD_TRACKING_QUERY_LOCAL_BIT_FB = 0x00000002;
+static const XrKeyboardTrackingQueryFlagsFB XR_KEYBOARD_TRACKING_QUERY_REMOTE_BIT_FB = 0x00000004;
+
+// XrSystemKeyboardTrackingPropertiesFB extends XrSystemProperties
+typedef struct XrSystemKeyboardTrackingPropertiesFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsKeyboardTracking;
+} XrSystemKeyboardTrackingPropertiesFB;
+
+typedef struct XrKeyboardTrackingDescriptionFB {
+ uint64_t trackedKeyboardId;
+ XrVector3f size;
+ XrKeyboardTrackingFlagsFB flags;
+ char name[XR_MAX_KEYBOARD_TRACKING_NAME_SIZE_FB];
+} XrKeyboardTrackingDescriptionFB;
+
+typedef struct XrKeyboardSpaceCreateInfoFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint64_t trackedKeyboardId;
+} XrKeyboardSpaceCreateInfoFB;
+
+typedef struct XrKeyboardTrackingQueryFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrKeyboardTrackingQueryFlagsFB flags;
+} XrKeyboardTrackingQueryFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrQuerySystemTrackedKeyboardFB)(XrSession session, const XrKeyboardTrackingQueryFB* queryInfo, XrKeyboardTrackingDescriptionFB* keyboard);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateKeyboardSpaceFB)(XrSession session, const XrKeyboardSpaceCreateInfoFB* createInfo, XrSpace* keyboardSpace);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrQuerySystemTrackedKeyboardFB(
+ XrSession session,
+ const XrKeyboardTrackingQueryFB* queryInfo,
+ XrKeyboardTrackingDescriptionFB* keyboard);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateKeyboardSpaceFB(
+ XrSession session,
+ const XrKeyboardSpaceCreateInfoFB* createInfo,
+ XrSpace* keyboardSpace);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_triangle_mesh 1
+XR_DEFINE_HANDLE(XrTriangleMeshFB)
+#define XR_FB_triangle_mesh_SPEC_VERSION 2
+#define XR_FB_TRIANGLE_MESH_EXTENSION_NAME "XR_FB_triangle_mesh"
+
+typedef enum XrWindingOrderFB {
+ XR_WINDING_ORDER_UNKNOWN_FB = 0,
+ XR_WINDING_ORDER_CW_FB = 1,
+ XR_WINDING_ORDER_CCW_FB = 2,
+ XR_WINDING_ORDER_MAX_ENUM_FB = 0x7FFFFFFF
+} XrWindingOrderFB;
+typedef XrFlags64 XrTriangleMeshFlagsFB;
+
+// Flag bits for XrTriangleMeshFlagsFB
+static const XrTriangleMeshFlagsFB XR_TRIANGLE_MESH_MUTABLE_BIT_FB = 0x00000001;
+
+typedef struct XrTriangleMeshCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrTriangleMeshFlagsFB flags;
+ XrWindingOrderFB windingOrder;
+ uint32_t vertexCount;
+ const XrVector3f* vertexBuffer;
+ uint32_t triangleCount;
+ const uint32_t* indexBuffer;
+} XrTriangleMeshCreateInfoFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateTriangleMeshFB)(XrSession session, const XrTriangleMeshCreateInfoFB* createInfo, XrTriangleMeshFB* outTriangleMesh);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyTriangleMeshFB)(XrTriangleMeshFB mesh);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshGetVertexBufferFB)(XrTriangleMeshFB mesh, XrVector3f** outVertexBuffer);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshGetIndexBufferFB)(XrTriangleMeshFB mesh, uint32_t** outIndexBuffer);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshBeginUpdateFB)(XrTriangleMeshFB mesh);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshEndUpdateFB)(XrTriangleMeshFB mesh, uint32_t vertexCount, uint32_t triangleCount);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshBeginVertexBufferUpdateFB)(XrTriangleMeshFB mesh, uint32_t* outVertexCount);
+typedef XrResult (XRAPI_PTR *PFN_xrTriangleMeshEndVertexBufferUpdateFB)(XrTriangleMeshFB mesh);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateTriangleMeshFB(
+ XrSession session,
+ const XrTriangleMeshCreateInfoFB* createInfo,
+ XrTriangleMeshFB* outTriangleMesh);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyTriangleMeshFB(
+ XrTriangleMeshFB mesh);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshGetVertexBufferFB(
+ XrTriangleMeshFB mesh,
+ XrVector3f** outVertexBuffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshGetIndexBufferFB(
+ XrTriangleMeshFB mesh,
+ uint32_t** outIndexBuffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshBeginUpdateFB(
+ XrTriangleMeshFB mesh);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshEndUpdateFB(
+ XrTriangleMeshFB mesh,
+ uint32_t vertexCount,
+ uint32_t triangleCount);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshBeginVertexBufferUpdateFB(
+ XrTriangleMeshFB mesh,
+ uint32_t* outVertexCount);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTriangleMeshEndVertexBufferUpdateFB(
+ XrTriangleMeshFB mesh);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_passthrough 1
+XR_DEFINE_HANDLE(XrPassthroughFB)
+XR_DEFINE_HANDLE(XrPassthroughLayerFB)
+XR_DEFINE_HANDLE(XrGeometryInstanceFB)
+#define XR_FB_passthrough_SPEC_VERSION 2
+#define XR_FB_PASSTHROUGH_EXTENSION_NAME "XR_FB_passthrough"
+#define XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB 256
+
+typedef enum XrPassthroughLayerPurposeFB {
+ XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB = 0,
+ XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB = 1,
+ XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB = 1000203001,
+ XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB = 1000203002,
+ XR_PASSTHROUGH_LAYER_PURPOSE_MAX_ENUM_FB = 0x7FFFFFFF
+} XrPassthroughLayerPurposeFB;
+typedef XrFlags64 XrPassthroughFlagsFB;
+
+// Flag bits for XrPassthroughFlagsFB
+static const XrPassthroughFlagsFB XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB = 0x00000001;
+
+typedef XrFlags64 XrPassthroughStateChangedFlagsFB;
+
+// Flag bits for XrPassthroughStateChangedFlagsFB
+static const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB = 0x00000001;
+static const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB = 0x00000002;
+static const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB = 0x00000004;
+static const XrPassthroughStateChangedFlagsFB XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB = 0x00000008;
+
+// XrSystemPassthroughPropertiesFB extends XrSystemProperties
+typedef struct XrSystemPassthroughPropertiesFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 supportsPassthrough;
+} XrSystemPassthroughPropertiesFB;
+
+typedef struct XrPassthroughCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPassthroughFlagsFB flags;
+} XrPassthroughCreateInfoFB;
+
+typedef struct XrPassthroughLayerCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPassthroughFB passthrough;
+ XrPassthroughFlagsFB flags;
+ XrPassthroughLayerPurposeFB purpose;
+} XrPassthroughLayerCreateInfoFB;
+
+// XrCompositionLayerPassthroughFB extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerPassthroughFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerFlags flags;
+ XrSpace space;
+ XrPassthroughLayerFB layerHandle;
+} XrCompositionLayerPassthroughFB;
+
+typedef struct XrGeometryInstanceCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPassthroughLayerFB layer;
+ XrTriangleMeshFB mesh;
+ XrSpace baseSpace;
+ XrPosef pose;
+ XrVector3f scale;
+} XrGeometryInstanceCreateInfoFB;
+
+typedef struct XrGeometryInstanceTransformFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace baseSpace;
+ XrTime time;
+ XrPosef pose;
+ XrVector3f scale;
+} XrGeometryInstanceTransformFB;
+
+typedef struct XrPassthroughStyleFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float textureOpacityFactor;
+ XrColor4f edgeColor;
+} XrPassthroughStyleFB;
+
+// XrPassthroughColorMapMonoToRgbaFB extends XrPassthroughStyleFB
+typedef struct XrPassthroughColorMapMonoToRgbaFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrColor4f textureColorMap[XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
+} XrPassthroughColorMapMonoToRgbaFB;
+
+// XrPassthroughColorMapMonoToMonoFB extends XrPassthroughStyleFB
+typedef struct XrPassthroughColorMapMonoToMonoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint8_t textureColorMap[XR_PASSTHROUGH_COLOR_MAP_MONO_SIZE_FB];
+} XrPassthroughColorMapMonoToMonoFB;
+
+// XrPassthroughBrightnessContrastSaturationFB extends XrPassthroughStyleFB
+typedef struct XrPassthroughBrightnessContrastSaturationFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float brightness;
+ float contrast;
+ float saturation;
+} XrPassthroughBrightnessContrastSaturationFB;
+
+typedef struct XrEventDataPassthroughStateChangedFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPassthroughStateChangedFlagsFB flags;
+} XrEventDataPassthroughStateChangedFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughFB)(XrSession session, const XrPassthroughCreateInfoFB* createInfo, XrPassthroughFB* outPassthrough);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughFB)(XrPassthroughFB passthrough);
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughStartFB)(XrPassthroughFB passthrough);
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughPauseFB)(XrPassthroughFB passthrough);
+typedef XrResult (XRAPI_PTR *PFN_xrCreatePassthroughLayerFB)(XrSession session, const XrPassthroughLayerCreateInfoFB* createInfo, XrPassthroughLayerFB* outLayer);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyPassthroughLayerFB)(XrPassthroughLayerFB layer);
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerPauseFB)(XrPassthroughLayerFB layer);
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerResumeFB)(XrPassthroughLayerFB layer);
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerSetStyleFB)(XrPassthroughLayerFB layer, const XrPassthroughStyleFB* style);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateGeometryInstanceFB)(XrSession session, const XrGeometryInstanceCreateInfoFB* createInfo, XrGeometryInstanceFB* outGeometryInstance);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroyGeometryInstanceFB)(XrGeometryInstanceFB instance);
+typedef XrResult (XRAPI_PTR *PFN_xrGeometryInstanceSetTransformFB)(XrGeometryInstanceFB instance, const XrGeometryInstanceTransformFB* transformation);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughFB(
+ XrSession session,
+ const XrPassthroughCreateInfoFB* createInfo,
+ XrPassthroughFB* outPassthrough);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughFB(
+ XrPassthroughFB passthrough);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughStartFB(
+ XrPassthroughFB passthrough);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughPauseFB(
+ XrPassthroughFB passthrough);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreatePassthroughLayerFB(
+ XrSession session,
+ const XrPassthroughLayerCreateInfoFB* createInfo,
+ XrPassthroughLayerFB* outLayer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyPassthroughLayerFB(
+ XrPassthroughLayerFB layer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerPauseFB(
+ XrPassthroughLayerFB layer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerResumeFB(
+ XrPassthroughLayerFB layer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerSetStyleFB(
+ XrPassthroughLayerFB layer,
+ const XrPassthroughStyleFB* style);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateGeometryInstanceFB(
+ XrSession session,
+ const XrGeometryInstanceCreateInfoFB* createInfo,
+ XrGeometryInstanceFB* outGeometryInstance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroyGeometryInstanceFB(
+ XrGeometryInstanceFB instance);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGeometryInstanceSetTransformFB(
+ XrGeometryInstanceFB instance,
+ const XrGeometryInstanceTransformFB* transformation);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_render_model 1
+
+#define XR_NULL_RENDER_MODEL_KEY_FB 0
+
+XR_DEFINE_ATOM(XrRenderModelKeyFB)
+#define XR_FB_render_model_SPEC_VERSION 2
+#define XR_FB_RENDER_MODEL_EXTENSION_NAME "XR_FB_render_model"
+#define XR_MAX_RENDER_MODEL_NAME_SIZE_FB 64
+typedef XrFlags64 XrRenderModelFlagsFB;
+
+// Flag bits for XrRenderModelFlagsFB
+static const XrRenderModelFlagsFB XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_1_BIT_FB = 0x00000001;
+static const XrRenderModelFlagsFB XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_2_BIT_FB = 0x00000002;
+
+typedef struct XrRenderModelPathInfoFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrPath path;
+} XrRenderModelPathInfoFB;
+
+typedef struct XrRenderModelPropertiesFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t vendorId;
+ char modelName[XR_MAX_RENDER_MODEL_NAME_SIZE_FB];
+ XrRenderModelKeyFB modelKey;
+ uint32_t modelVersion;
+ XrRenderModelFlagsFB flags;
+} XrRenderModelPropertiesFB;
+
+typedef struct XrRenderModelBufferFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t bufferCapacityInput;
+ uint32_t bufferCountOutput;
+ uint8_t* buffer;
+} XrRenderModelBufferFB;
+
+typedef struct XrRenderModelLoadInfoFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrRenderModelKeyFB modelKey;
+} XrRenderModelLoadInfoFB;
+
+// XrSystemRenderModelPropertiesFB extends XrSystemProperties
+typedef struct XrSystemRenderModelPropertiesFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsRenderModelLoading;
+} XrSystemRenderModelPropertiesFB;
+
+// XrRenderModelCapabilitiesRequestFB extends XrSystemProperties
+typedef struct XrRenderModelCapabilitiesRequestFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrRenderModelFlagsFB flags;
+} XrRenderModelCapabilitiesRequestFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumerateRenderModelPathsFB)(XrSession session, uint32_t pathCapacityInput, uint32_t* pathCountOutput, XrRenderModelPathInfoFB* paths);
+typedef XrResult (XRAPI_PTR *PFN_xrGetRenderModelPropertiesFB)(XrSession session, XrPath path, XrRenderModelPropertiesFB* properties);
+typedef XrResult (XRAPI_PTR *PFN_xrLoadRenderModelFB)(XrSession session, const XrRenderModelLoadInfoFB* info, XrRenderModelBufferFB* buffer);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateRenderModelPathsFB(
+ XrSession session,
+ uint32_t pathCapacityInput,
+ uint32_t* pathCountOutput,
+ XrRenderModelPathInfoFB* paths);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetRenderModelPropertiesFB(
+ XrSession session,
+ XrPath path,
+ XrRenderModelPropertiesFB* properties);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrLoadRenderModelFB(
+ XrSession session,
+ const XrRenderModelLoadInfoFB* info,
+ XrRenderModelBufferFB* buffer);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_VARJO_foveated_rendering 1
+#define XR_VARJO_foveated_rendering_SPEC_VERSION 2
+#define XR_VARJO_FOVEATED_RENDERING_EXTENSION_NAME "XR_VARJO_foveated_rendering"
+// XrViewLocateFoveatedRenderingVARJO extends XrViewLocateInfo
+typedef struct XrViewLocateFoveatedRenderingVARJO {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 foveatedRenderingActive;
+} XrViewLocateFoveatedRenderingVARJO;
+
+// XrFoveatedViewConfigurationViewVARJO extends XrViewConfigurationView
+typedef struct XrFoveatedViewConfigurationViewVARJO {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 foveatedRenderingActive;
+} XrFoveatedViewConfigurationViewVARJO;
+
+// XrSystemFoveatedRenderingPropertiesVARJO extends XrSystemProperties
+typedef struct XrSystemFoveatedRenderingPropertiesVARJO {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsFoveatedRendering;
+} XrSystemFoveatedRenderingPropertiesVARJO;
+
+
+
+#define XR_VARJO_composition_layer_depth_test 1
+#define XR_VARJO_composition_layer_depth_test_SPEC_VERSION 2
+#define XR_VARJO_COMPOSITION_LAYER_DEPTH_TEST_EXTENSION_NAME "XR_VARJO_composition_layer_depth_test"
+// XrCompositionLayerDepthTestVARJO extends XrCompositionLayerProjection
+typedef struct XrCompositionLayerDepthTestVARJO {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float depthTestRangeNearZ;
+ float depthTestRangeFarZ;
+} XrCompositionLayerDepthTestVARJO;
+
+
+
+#define XR_VARJO_environment_depth_estimation 1
+#define XR_VARJO_environment_depth_estimation_SPEC_VERSION 1
+#define XR_VARJO_ENVIRONMENT_DEPTH_ESTIMATION_EXTENSION_NAME "XR_VARJO_environment_depth_estimation"
+typedef XrResult (XRAPI_PTR *PFN_xrSetEnvironmentDepthEstimationVARJO)(XrSession session, XrBool32 enabled);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetEnvironmentDepthEstimationVARJO(
+ XrSession session,
+ XrBool32 enabled);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_VARJO_marker_tracking 1
+#define XR_VARJO_marker_tracking_SPEC_VERSION 1
+#define XR_VARJO_MARKER_TRACKING_EXTENSION_NAME "XR_VARJO_marker_tracking"
+// XrSystemMarkerTrackingPropertiesVARJO extends XrSystemProperties
+typedef struct XrSystemMarkerTrackingPropertiesVARJO {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrBool32 supportsMarkerTracking;
+} XrSystemMarkerTrackingPropertiesVARJO;
+
+typedef struct XrEventDataMarkerTrackingUpdateVARJO {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint64_t markerId;
+ XrBool32 isActive;
+ XrBool32 isPredicted;
+ XrTime time;
+} XrEventDataMarkerTrackingUpdateVARJO;
+
+typedef struct XrMarkerSpaceCreateInfoVARJO {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint64_t markerId;
+ XrPosef poseInMarkerSpace;
+} XrMarkerSpaceCreateInfoVARJO;
+
+typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingVARJO)(XrSession session, XrBool32 enabled);
+typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingTimeoutVARJO)(XrSession session, uint64_t markerId, XrDuration timeout);
+typedef XrResult (XRAPI_PTR *PFN_xrSetMarkerTrackingPredictionVARJO)(XrSession session, uint64_t markerId, XrBool32 enabled);
+typedef XrResult (XRAPI_PTR *PFN_xrGetMarkerSizeVARJO)(XrSession session, uint64_t markerId, XrExtent2Df* size);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateMarkerSpaceVARJO)(XrSession session, const XrMarkerSpaceCreateInfoVARJO* createInfo, XrSpace* space);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingVARJO(
+ XrSession session,
+ XrBool32 enabled);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingTimeoutVARJO(
+ XrSession session,
+ uint64_t markerId,
+ XrDuration timeout);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetMarkerTrackingPredictionVARJO(
+ XrSession session,
+ uint64_t markerId,
+ XrBool32 enabled);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetMarkerSizeVARJO(
+ XrSession session,
+ uint64_t markerId,
+ XrExtent2Df* size);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateMarkerSpaceVARJO(
+ XrSession session,
+ const XrMarkerSpaceCreateInfoVARJO* createInfo,
+ XrSpace* space);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_VARJO_view_offset 1
+#define XR_VARJO_view_offset_SPEC_VERSION 1
+#define XR_VARJO_VIEW_OFFSET_EXTENSION_NAME "XR_VARJO_view_offset"
+typedef XrResult (XRAPI_PTR *PFN_xrSetViewOffsetVARJO)(XrSession session, float offset);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetViewOffsetVARJO(
+ XrSession session,
+ float offset);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_MSFT_spatial_anchor_persistence 1
+XR_DEFINE_HANDLE(XrSpatialAnchorStoreConnectionMSFT)
+#define XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_MSFT 256
+#define XR_MSFT_spatial_anchor_persistence_SPEC_VERSION 2
+#define XR_MSFT_SPATIAL_ANCHOR_PERSISTENCE_EXTENSION_NAME "XR_MSFT_spatial_anchor_persistence"
+typedef struct XrSpatialAnchorPersistenceNameMSFT {
+ char name[XR_MAX_SPATIAL_ANCHOR_NAME_SIZE_MSFT];
+} XrSpatialAnchorPersistenceNameMSFT;
+
+typedef struct XrSpatialAnchorPersistenceInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpatialAnchorPersistenceNameMSFT spatialAnchorPersistenceName;
+ XrSpatialAnchorMSFT spatialAnchor;
+} XrSpatialAnchorPersistenceInfoMSFT;
+
+typedef struct XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore;
+ XrSpatialAnchorPersistenceNameMSFT spatialAnchorPersistenceName;
+} XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorStoreConnectionMSFT)(XrSession session, XrSpatialAnchorStoreConnectionMSFT* spatialAnchorStore);
+typedef XrResult (XRAPI_PTR *PFN_xrDestroySpatialAnchorStoreConnectionMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);
+typedef XrResult (XRAPI_PTR *PFN_xrPersistSpatialAnchorMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, const XrSpatialAnchorPersistenceInfoMSFT* spatialAnchorPersistenceInfo);
+typedef XrResult (XRAPI_PTR *PFN_xrEnumeratePersistedSpatialAnchorNamesMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, uint32_t spatialAnchorNamesCapacityInput, uint32_t* spatialAnchorNamesCountOutput, XrSpatialAnchorPersistenceNameMSFT* persistedAnchorNames);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPersistedNameMSFT)(XrSession session, const XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT* spatialAnchorCreateInfo, XrSpatialAnchorMSFT* spatialAnchor);
+typedef XrResult (XRAPI_PTR *PFN_xrUnpersistSpatialAnchorMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore, const XrSpatialAnchorPersistenceNameMSFT* spatialAnchorPersistenceName);
+typedef XrResult (XRAPI_PTR *PFN_xrClearSpatialAnchorStoreMSFT)(XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorStoreConnectionMSFT(
+ XrSession session,
+ XrSpatialAnchorStoreConnectionMSFT* spatialAnchorStore);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpatialAnchorStoreConnectionMSFT(
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrPersistSpatialAnchorMSFT(
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,
+ const XrSpatialAnchorPersistenceInfoMSFT* spatialAnchorPersistenceInfo);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumeratePersistedSpatialAnchorNamesMSFT(
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,
+ uint32_t spatialAnchorNamesCapacityInput,
+ uint32_t* spatialAnchorNamesCountOutput,
+ XrSpatialAnchorPersistenceNameMSFT* persistedAnchorNames);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPersistedNameMSFT(
+ XrSession session,
+ const XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT* spatialAnchorCreateInfo,
+ XrSpatialAnchorMSFT* spatialAnchor);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrUnpersistSpatialAnchorMSFT(
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore,
+ const XrSpatialAnchorPersistenceNameMSFT* spatialAnchorPersistenceName);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrClearSpatialAnchorStoreMSFT(
+ XrSpatialAnchorStoreConnectionMSFT spatialAnchorStore);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_ULTRALEAP_hand_tracking_forearm 1
+
+#define XR_HAND_FOREARM_JOINT_COUNT_ULTRALEAP 27
+
+#define XR_ULTRALEAP_hand_tracking_forearm_SPEC_VERSION 1
+#define XR_ULTRALEAP_HAND_TRACKING_FOREARM_EXTENSION_NAME "XR_ULTRALEAP_hand_tracking_forearm"
+
+typedef enum XrHandForearmJointULTRALEAP {
+ XR_HAND_FOREARM_JOINT_PALM_ULTRALEAP = 0,
+ XR_HAND_FOREARM_JOINT_WRIST_ULTRALEAP = 1,
+ XR_HAND_FOREARM_JOINT_THUMB_METACARPAL_ULTRALEAP = 2,
+ XR_HAND_FOREARM_JOINT_THUMB_PROXIMAL_ULTRALEAP = 3,
+ XR_HAND_FOREARM_JOINT_THUMB_DISTAL_ULTRALEAP = 4,
+ XR_HAND_FOREARM_JOINT_THUMB_TIP_ULTRALEAP = 5,
+ XR_HAND_FOREARM_JOINT_INDEX_METACARPAL_ULTRALEAP = 6,
+ XR_HAND_FOREARM_JOINT_INDEX_PROXIMAL_ULTRALEAP = 7,
+ XR_HAND_FOREARM_JOINT_INDEX_INTERMEDIATE_ULTRALEAP = 8,
+ XR_HAND_FOREARM_JOINT_INDEX_DISTAL_ULTRALEAP = 9,
+ XR_HAND_FOREARM_JOINT_INDEX_TIP_ULTRALEAP = 10,
+ XR_HAND_FOREARM_JOINT_MIDDLE_METACARPAL_ULTRALEAP = 11,
+ XR_HAND_FOREARM_JOINT_MIDDLE_PROXIMAL_ULTRALEAP = 12,
+ XR_HAND_FOREARM_JOINT_MIDDLE_INTERMEDIATE_ULTRALEAP = 13,
+ XR_HAND_FOREARM_JOINT_MIDDLE_DISTAL_ULTRALEAP = 14,
+ XR_HAND_FOREARM_JOINT_MIDDLE_TIP_ULTRALEAP = 15,
+ XR_HAND_FOREARM_JOINT_RING_METACARPAL_ULTRALEAP = 16,
+ XR_HAND_FOREARM_JOINT_RING_PROXIMAL_ULTRALEAP = 17,
+ XR_HAND_FOREARM_JOINT_RING_INTERMEDIATE_ULTRALEAP = 18,
+ XR_HAND_FOREARM_JOINT_RING_DISTAL_ULTRALEAP = 19,
+ XR_HAND_FOREARM_JOINT_RING_TIP_ULTRALEAP = 20,
+ XR_HAND_FOREARM_JOINT_LITTLE_METACARPAL_ULTRALEAP = 21,
+ XR_HAND_FOREARM_JOINT_LITTLE_PROXIMAL_ULTRALEAP = 22,
+ XR_HAND_FOREARM_JOINT_LITTLE_INTERMEDIATE_ULTRALEAP = 23,
+ XR_HAND_FOREARM_JOINT_LITTLE_DISTAL_ULTRALEAP = 24,
+ XR_HAND_FOREARM_JOINT_LITTLE_TIP_ULTRALEAP = 25,
+ XR_HAND_FOREARM_JOINT_ELBOW_ULTRALEAP = 26,
+ XR_HAND_FOREARM_JOINT_MAX_ENUM_ULTRALEAP = 0x7FFFFFFF
+} XrHandForearmJointULTRALEAP;
+
+
+#define XR_FB_spatial_entity_query 1
+#define XR_FB_spatial_entity_query_SPEC_VERSION 1
+#define XR_FB_SPATIAL_ENTITY_QUERY_EXTENSION_NAME "XR_FB_spatial_entity_query"
+
+typedef enum XrSpaceQueryActionFB {
+ XR_SPACE_QUERY_ACTION_LOAD_FB = 0,
+ XR_SPACE_QUERY_ACTION_MAX_ENUM_FB = 0x7FFFFFFF
+} XrSpaceQueryActionFB;
+
+typedef enum XrSpaceStorageLocationFB {
+ XR_SPACE_STORAGE_LOCATION_INVALID_FB = 0,
+ XR_SPACE_STORAGE_LOCATION_LOCAL_FB = 1,
+ XR_SPACE_STORAGE_LOCATION_MAX_ENUM_FB = 0x7FFFFFFF
+} XrSpaceStorageLocationFB;
+typedef struct XR_MAY_ALIAS XrSpaceQueryInfoBaseHeaderFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSpaceQueryInfoBaseHeaderFB;
+
+typedef struct XR_MAY_ALIAS XrSpaceFilterInfoBaseHeaderFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+} XrSpaceFilterInfoBaseHeaderFB;
+
+typedef struct XrSpaceQueryInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpaceQueryActionFB queryAction;
+ uint32_t maxResultCount;
+ XrDuration timeout;
+ const XrSpaceFilterInfoBaseHeaderFB* filter;
+ const XrSpaceFilterInfoBaseHeaderFB* excludeFilter;
+} XrSpaceQueryInfoFB;
+
+// XrSpaceStorageLocationFilterInfoFB extends XrSpaceFilterInfoBaseHeaderFB
+typedef struct XrSpaceStorageLocationFilterInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpaceStorageLocationFB location;
+} XrSpaceStorageLocationFilterInfoFB;
+
+typedef struct XrSpaceUuidFilterInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t uuidCount;
+ XrUuidEXT* uuids;
+} XrSpaceUuidFilterInfoFB;
+
+typedef struct XrSpaceComponentFilterInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpaceComponentTypeFB componentType;
+} XrSpaceComponentFilterInfoFB;
+
+typedef struct XrSpaceQueryResultFB {
+ XrSpace space;
+ XrUuidEXT uuid;
+} XrSpaceQueryResultFB;
+
+typedef struct XrSpaceQueryResultsFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t resultCapacityInput;
+ uint32_t resultCountOutput;
+ XrSpaceQueryResultFB* results;
+} XrSpaceQueryResultsFB;
+
+typedef struct XrEventDataSpaceQueryResultsAvailableFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+} XrEventDataSpaceQueryResultsAvailableFB;
+
+typedef struct XrEventDataSpaceQueryCompleteFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+ XrResult result;
+} XrEventDataSpaceQueryCompleteFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrQuerySpacesFB)(XrSession session, const XrSpaceQueryInfoBaseHeaderFB* info, XrAsyncRequestIdFB* requestId);
+typedef XrResult (XRAPI_PTR *PFN_xrRetrieveSpaceQueryResultsFB)(XrSession session, XrAsyncRequestIdFB requestId, XrSpaceQueryResultsFB* results);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrQuerySpacesFB(
+ XrSession session,
+ const XrSpaceQueryInfoBaseHeaderFB* info,
+ XrAsyncRequestIdFB* requestId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrRetrieveSpaceQueryResultsFB(
+ XrSession session,
+ XrAsyncRequestIdFB requestId,
+ XrSpaceQueryResultsFB* results);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_spatial_entity_storage 1
+#define XR_FB_spatial_entity_storage_SPEC_VERSION 1
+#define XR_FB_SPATIAL_ENTITY_STORAGE_EXTENSION_NAME "XR_FB_spatial_entity_storage"
+
+typedef enum XrSpacePersistenceModeFB {
+ XR_SPACE_PERSISTENCE_MODE_INVALID_FB = 0,
+ XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB = 1,
+ XR_SPACE_PERSISTENCE_MODE_MAX_ENUM_FB = 0x7FFFFFFF
+} XrSpacePersistenceModeFB;
+typedef struct XrSpaceSaveInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace space;
+ XrSpaceStorageLocationFB location;
+ XrSpacePersistenceModeFB persistenceMode;
+} XrSpaceSaveInfoFB;
+
+typedef struct XrSpaceEraseInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSpace space;
+ XrSpaceStorageLocationFB location;
+} XrSpaceEraseInfoFB;
+
+typedef struct XrEventDataSpaceSaveCompleteFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+ XrResult result;
+ XrSpace space;
+ XrUuidEXT uuid;
+ XrSpaceStorageLocationFB location;
+} XrEventDataSpaceSaveCompleteFB;
+
+typedef struct XrEventDataSpaceEraseCompleteFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAsyncRequestIdFB requestId;
+ XrResult result;
+ XrSpace space;
+ XrUuidEXT uuid;
+ XrSpaceStorageLocationFB location;
+} XrEventDataSpaceEraseCompleteFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrSaveSpaceFB)(XrSession session, const XrSpaceSaveInfoFB* info, XrAsyncRequestIdFB* requestId);
+typedef XrResult (XRAPI_PTR *PFN_xrEraseSpaceFB)(XrSession session, const XrSpaceEraseInfoFB* info, XrAsyncRequestIdFB* requestId);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSaveSpaceFB(
+ XrSession session,
+ const XrSpaceSaveInfoFB* info,
+ XrAsyncRequestIdFB* requestId);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrEraseSpaceFB(
+ XrSession session,
+ const XrSpaceEraseInfoFB* info,
+ XrAsyncRequestIdFB* requestId);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_space_warp 1
+#define XR_FB_space_warp_SPEC_VERSION 2
+#define XR_FB_SPACE_WARP_EXTENSION_NAME "XR_FB_space_warp"
+typedef XrFlags64 XrCompositionLayerSpaceWarpInfoFlagsFB;
+
+// Flag bits for XrCompositionLayerSpaceWarpInfoFlagsFB
+static const XrCompositionLayerSpaceWarpInfoFlagsFB XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB = 0x00000001;
+
+// XrCompositionLayerSpaceWarpInfoFB extends XrCompositionLayerProjectionView
+typedef struct XrCompositionLayerSpaceWarpInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerSpaceWarpInfoFlagsFB layerFlags;
+ XrSwapchainSubImage motionVectorSubImage;
+ XrPosef appSpaceDeltaPose;
+ XrSwapchainSubImage depthSubImage;
+ float minDepth;
+ float maxDepth;
+ float nearZ;
+ float farZ;
+} XrCompositionLayerSpaceWarpInfoFB;
+
+// XrSystemSpaceWarpPropertiesFB extends XrSystemProperties
+typedef struct XrSystemSpaceWarpPropertiesFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t recommendedMotionVectorImageRectWidth;
+ uint32_t recommendedMotionVectorImageRectHeight;
+} XrSystemSpaceWarpPropertiesFB;
+
+
+
+#define XR_ALMALENCE_digital_lens_control 1
+#define XR_ALMALENCE_digital_lens_control_SPEC_VERSION 1
+#define XR_ALMALENCE_DIGITAL_LENS_CONTROL_EXTENSION_NAME "XR_ALMALENCE_digital_lens_control"
+typedef XrFlags64 XrDigitalLensControlFlagsALMALENCE;
+
+// Flag bits for XrDigitalLensControlFlagsALMALENCE
+static const XrDigitalLensControlFlagsALMALENCE XR_DIGITAL_LENS_CONTROL_PROCESSING_DISABLE_BIT_ALMALENCE = 0x00000001;
+
+typedef struct XrDigitalLensControlALMALENCE {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrDigitalLensControlFlagsALMALENCE flags;
+} XrDigitalLensControlALMALENCE;
+
+typedef XrResult (XRAPI_PTR *PFN_xrSetDigitalLensControlALMALENCE)(XrSession session, const XrDigitalLensControlALMALENCE* digitalLensControl);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetDigitalLensControlALMALENCE(
+ XrSession session,
+ const XrDigitalLensControlALMALENCE* digitalLensControl);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_spatial_entity_container 1
+#define XR_FB_spatial_entity_container_SPEC_VERSION 1
+#define XR_FB_SPATIAL_ENTITY_CONTAINER_EXTENSION_NAME "XR_FB_spatial_entity_container"
+typedef struct XrSpaceContainerFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t uuidCapacityInput;
+ uint32_t* uuidCountOutput;
+ XrUuidEXT* uuids;
+} XrSpaceContainerFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetSpaceContainerFB)(XrSession session, XrSpace space, XrSpaceContainerFB* spaceContainerOutput);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetSpaceContainerFB(
+ XrSession session,
+ XrSpace space,
+ XrSpaceContainerFB* spaceContainerOutput);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_passthrough_keyboard_hands 1
+#define XR_FB_passthrough_keyboard_hands_SPEC_VERSION 2
+#define XR_FB_PASSTHROUGH_KEYBOARD_HANDS_EXTENSION_NAME "XR_FB_passthrough_keyboard_hands"
+typedef struct XrPassthroughKeyboardHandsIntensityFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ float leftHandIntensity;
+ float rightHandIntensity;
+} XrPassthroughKeyboardHandsIntensityFB;
+
+typedef XrResult (XRAPI_PTR *PFN_xrPassthroughLayerSetKeyboardHandsIntensityFB)(XrPassthroughLayerFB layer, const XrPassthroughKeyboardHandsIntensityFB* intensity);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrPassthroughLayerSetKeyboardHandsIntensityFB(
+ XrPassthroughLayerFB layer,
+ const XrPassthroughKeyboardHandsIntensityFB* intensity);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_FB_composition_layer_settings 1
+#define XR_FB_composition_layer_settings_SPEC_VERSION 1
+#define XR_FB_COMPOSITION_LAYER_SETTINGS_EXTENSION_NAME "XR_FB_composition_layer_settings"
+typedef XrFlags64 XrCompositionLayerSettingsFlagsFB;
+
+// Flag bits for XrCompositionLayerSettingsFlagsFB
+static const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SUPER_SAMPLING_BIT_FB = 0x00000001;
+static const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SUPER_SAMPLING_BIT_FB = 0x00000002;
+static const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SHARPENING_BIT_FB = 0x00000004;
+static const XrCompositionLayerSettingsFlagsFB XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SHARPENING_BIT_FB = 0x00000008;
+
+// XrCompositionLayerSettingsFB extends XrCompositionLayerBaseHeader
+typedef struct XrCompositionLayerSettingsFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrCompositionLayerSettingsFlagsFB layerFlags;
+} XrCompositionLayerSettingsFB;
+
+
+
+#define XR_META_performance_metrics 1
+#define XR_META_performance_metrics_SPEC_VERSION 1
+#define XR_META_PERFORMANCE_METRICS_EXTENSION_NAME "XR_META_performance_metrics"
+
+typedef enum XrPerformanceMetricsCounterUnitMETA {
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META = 0,
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_PERCENTAGE_META = 1,
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_MILLISECONDS_META = 2,
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_BYTES_META = 3,
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_HERTZ_META = 4,
+ XR_PERFORMANCE_METRICS_COUNTER_UNIT_MAX_ENUM_META = 0x7FFFFFFF
+} XrPerformanceMetricsCounterUnitMETA;
+typedef XrFlags64 XrPerformanceMetricsCounterFlagsMETA;
+
+// Flag bits for XrPerformanceMetricsCounterFlagsMETA
+static const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META = 0x00000001;
+static const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_UINT_VALUE_VALID_BIT_META = 0x00000002;
+static const XrPerformanceMetricsCounterFlagsMETA XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META = 0x00000004;
+
+typedef struct XrPerformanceMetricsStateMETA {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrBool32 enabled;
+} XrPerformanceMetricsStateMETA;
+
+typedef struct XrPerformanceMetricsCounterMETA {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrPerformanceMetricsCounterFlagsMETA counterFlags;
+ XrPerformanceMetricsCounterUnitMETA counterUnit;
+ uint32_t uintValue;
+ float floatValue;
+} XrPerformanceMetricsCounterMETA;
+
+typedef XrResult (XRAPI_PTR *PFN_xrEnumeratePerformanceMetricsCounterPathsMETA)(XrInstance instance, uint32_t counterPathCapacityInput, uint32_t* counterPathCountOutput, XrPath* counterPaths);
+typedef XrResult (XRAPI_PTR *PFN_xrSetPerformanceMetricsStateMETA)(XrSession session, const XrPerformanceMetricsStateMETA* state);
+typedef XrResult (XRAPI_PTR *PFN_xrGetPerformanceMetricsStateMETA)(XrSession session, XrPerformanceMetricsStateMETA* state);
+typedef XrResult (XRAPI_PTR *PFN_xrQueryPerformanceMetricsCounterMETA)(XrSession session, XrPath counterPath, XrPerformanceMetricsCounterMETA* counter);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrEnumeratePerformanceMetricsCounterPathsMETA(
+ XrInstance instance,
+ uint32_t counterPathCapacityInput,
+ uint32_t* counterPathCountOutput,
+ XrPath* counterPaths);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrSetPerformanceMetricsStateMETA(
+ XrSession session,
+ const XrPerformanceMetricsStateMETA* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetPerformanceMetricsStateMETA(
+ XrSession session,
+ XrPerformanceMetricsStateMETA* state);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrQueryPerformanceMetricsCounterMETA(
+ XrSession session,
+ XrPath counterPath,
+ XrPerformanceMetricsCounterMETA* counter);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+
+
+#define XR_EXT_uuid 1
+#define XR_EXT_uuid_SPEC_VERSION 1
+#define XR_EXT_UUID_EXTENSION_NAME "XR_EXT_uuid"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/openxr/include/openxr/openxr_platform.h b/thirdparty/openxr/include/openxr/openxr_platform.h
new file mode 100644
index 0000000000..f0fbf6955a
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr_platform.h
@@ -0,0 +1,690 @@
+#ifndef OPENXR_PLATFORM_H_
+#define OPENXR_PLATFORM_H_ 1
+
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_thread_settings 1
+#define XR_KHR_android_thread_settings_SPEC_VERSION 5
+#define XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME "XR_KHR_android_thread_settings"
+
+typedef enum XrAndroidThreadTypeKHR {
+ XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR = 1,
+ XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR = 2,
+ XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR = 3,
+ XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR = 4,
+ XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR = 0x7FFFFFFF
+} XrAndroidThreadTypeKHR;
+typedef XrResult (XRAPI_PTR *PFN_xrSetAndroidApplicationThreadKHR)(XrSession session, XrAndroidThreadTypeKHR threadType, uint32_t threadId);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrSetAndroidApplicationThreadKHR(
+ XrSession session,
+ XrAndroidThreadTypeKHR threadType,
+ uint32_t threadId);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_surface_swapchain 1
+#define XR_KHR_android_surface_swapchain_SPEC_VERSION 4
+#define XR_KHR_ANDROID_SURFACE_SWAPCHAIN_EXTENSION_NAME "XR_KHR_android_surface_swapchain"
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSwapchainAndroidSurfaceKHR)(XrSession session, const XrSwapchainCreateInfo* info, XrSwapchain* swapchain, jobject* surface);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchainAndroidSurfaceKHR(
+ XrSession session,
+ const XrSwapchainCreateInfo* info,
+ XrSwapchain* swapchain,
+ jobject* surface);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_android_create_instance 1
+#define XR_KHR_android_create_instance_SPEC_VERSION 3
+#define XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME "XR_KHR_android_create_instance"
+// XrInstanceCreateInfoAndroidKHR extends XrInstanceCreateInfo
+typedef struct XrInstanceCreateInfoAndroidKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ void* XR_MAY_ALIAS applicationVM;
+ void* XR_MAY_ALIAS applicationActivity;
+} XrInstanceCreateInfoAndroidKHR;
+
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_KHR_vulkan_swapchain_format_list 1
+#define XR_KHR_vulkan_swapchain_format_list_SPEC_VERSION 4
+#define XR_KHR_VULKAN_SWAPCHAIN_FORMAT_LIST_EXTENSION_NAME "XR_KHR_vulkan_swapchain_format_list"
+typedef struct XrVulkanSwapchainFormatListCreateInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ uint32_t viewFormatCount;
+ const VkFormat* viewFormats;
+} XrVulkanSwapchainFormatListCreateInfoKHR;
+
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL
+
+#define XR_KHR_opengl_enable 1
+#define XR_KHR_opengl_enable_SPEC_VERSION 10
+#define XR_KHR_OPENGL_ENABLE_EXTENSION_NAME "XR_KHR_opengl_enable"
+#ifdef XR_USE_PLATFORM_WIN32
+// XrGraphicsBindingOpenGLWin32KHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingOpenGLWin32KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ HDC hDC;
+ HGLRC hGLRC;
+} XrGraphicsBindingOpenGLWin32KHR;
+#endif // XR_USE_PLATFORM_WIN32
+
+#ifdef XR_USE_PLATFORM_XLIB
+// XrGraphicsBindingOpenGLXlibKHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingOpenGLXlibKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ Display* xDisplay;
+ uint32_t visualid;
+ GLXFBConfig glxFBConfig;
+ GLXDrawable glxDrawable;
+ GLXContext glxContext;
+} XrGraphicsBindingOpenGLXlibKHR;
+#endif // XR_USE_PLATFORM_XLIB
+
+#ifdef XR_USE_PLATFORM_XCB
+// XrGraphicsBindingOpenGLXcbKHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingOpenGLXcbKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ xcb_connection_t* connection;
+ uint32_t screenNumber;
+ xcb_glx_fbconfig_t fbconfigid;
+ xcb_visualid_t visualid;
+ xcb_glx_drawable_t glxDrawable;
+ xcb_glx_context_t glxContext;
+} XrGraphicsBindingOpenGLXcbKHR;
+#endif // XR_USE_PLATFORM_XCB
+
+#ifdef XR_USE_PLATFORM_WAYLAND
+// XrGraphicsBindingOpenGLWaylandKHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingOpenGLWaylandKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ struct wl_display* display;
+} XrGraphicsBindingOpenGLWaylandKHR;
+#endif // XR_USE_PLATFORM_WAYLAND
+
+typedef struct XrSwapchainImageOpenGLKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t image;
+} XrSwapchainImageOpenGLKHR;
+
+typedef struct XrGraphicsRequirementsOpenGLKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsOpenGLKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLKHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_OPENGL */
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+
+#define XR_KHR_opengl_es_enable 1
+#define XR_KHR_opengl_es_enable_SPEC_VERSION 8
+#define XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME "XR_KHR_opengl_es_enable"
+#ifdef XR_USE_PLATFORM_ANDROID
+// XrGraphicsBindingOpenGLESAndroidKHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingOpenGLESAndroidKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ EGLDisplay display;
+ EGLConfig config;
+ EGLContext context;
+} XrGraphicsBindingOpenGLESAndroidKHR;
+#endif // XR_USE_PLATFORM_ANDROID
+
+typedef struct XrSwapchainImageOpenGLESKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t image;
+} XrSwapchainImageOpenGLESKHR;
+
+typedef struct XrGraphicsRequirementsOpenGLESKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsOpenGLESKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetOpenGLESGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetOpenGLESGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsOpenGLESKHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_KHR_vulkan_enable 1
+#define XR_KHR_vulkan_enable_SPEC_VERSION 8
+#define XR_KHR_VULKAN_ENABLE_EXTENSION_NAME "XR_KHR_vulkan_enable"
+// XrGraphicsBindingVulkanKHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingVulkanKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ VkInstance instance;
+ VkPhysicalDevice physicalDevice;
+ VkDevice device;
+ uint32_t queueFamilyIndex;
+ uint32_t queueIndex;
+} XrGraphicsBindingVulkanKHR;
+
+typedef struct XrSwapchainImageVulkanKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ VkImage image;
+} XrSwapchainImageVulkanKHR;
+
+typedef struct XrGraphicsRequirementsVulkanKHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ XrVersion minApiVersionSupported;
+ XrVersion maxApiVersionSupported;
+} XrGraphicsRequirementsVulkanKHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanInstanceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanDeviceExtensionsKHR)(XrInstance instance, XrSystemId systemId, uint32_t bufferCapacityInput, uint32_t* bufferCountOutput, char* buffer);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDeviceKHR)(XrInstance instance, XrSystemId systemId, VkInstance vkInstance, VkPhysicalDevice* vkPhysicalDevice);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanInstanceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanDeviceExtensionsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDeviceKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ VkInstance vkInstance,
+ VkPhysicalDevice* vkPhysicalDevice);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_GRAPHICS_API_D3D11
+
+#define XR_KHR_D3D11_enable 1
+#define XR_KHR_D3D11_enable_SPEC_VERSION 9
+#define XR_KHR_D3D11_ENABLE_EXTENSION_NAME "XR_KHR_D3D11_enable"
+// XrGraphicsBindingD3D11KHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingD3D11KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ ID3D11Device* device;
+} XrGraphicsBindingD3D11KHR;
+
+typedef struct XrSwapchainImageD3D11KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ ID3D11Texture2D* texture;
+} XrSwapchainImageD3D11KHR;
+
+typedef struct XrGraphicsRequirementsD3D11KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+} XrGraphicsRequirementsD3D11KHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D11GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D11GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D11KHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_D3D11 */
+
+#ifdef XR_USE_GRAPHICS_API_D3D12
+
+#define XR_KHR_D3D12_enable 1
+#define XR_KHR_D3D12_enable_SPEC_VERSION 9
+#define XR_KHR_D3D12_ENABLE_EXTENSION_NAME "XR_KHR_D3D12_enable"
+// XrGraphicsBindingD3D12KHR extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingD3D12KHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ ID3D12Device* device;
+ ID3D12CommandQueue* queue;
+} XrGraphicsBindingD3D12KHR;
+
+typedef struct XrSwapchainImageD3D12KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ ID3D12Resource* texture;
+} XrSwapchainImageD3D12KHR;
+
+typedef struct XrGraphicsRequirementsD3D12KHR {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ LUID adapterLuid;
+ D3D_FEATURE_LEVEL minFeatureLevel;
+} XrGraphicsRequirementsD3D12KHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrGetD3D12GraphicsRequirementsKHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetD3D12GraphicsRequirementsKHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsD3D12KHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_D3D12 */
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#define XR_KHR_win32_convert_performance_counter_time 1
+#define XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION 1
+#define XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME "XR_KHR_win32_convert_performance_counter_time"
+typedef XrResult (XRAPI_PTR *PFN_xrConvertWin32PerformanceCounterToTimeKHR)(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToWin32PerformanceCounterKHR)(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertWin32PerformanceCounterToTimeKHR(
+ XrInstance instance,
+ const LARGE_INTEGER* performanceCounter,
+ XrTime* time);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToWin32PerformanceCounterKHR(
+ XrInstance instance,
+ XrTime time,
+ LARGE_INTEGER* performanceCounter);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_PLATFORM_WIN32 */
+
+#ifdef XR_USE_TIMESPEC
+
+#define XR_KHR_convert_timespec_time 1
+#define XR_KHR_convert_timespec_time_SPEC_VERSION 1
+#define XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME "XR_KHR_convert_timespec_time"
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimespecTimeToTimeKHR)(XrInstance instance, const struct timespec* timespecTime, XrTime* time);
+typedef XrResult (XRAPI_PTR *PFN_xrConvertTimeToTimespecTimeKHR)(XrInstance instance, XrTime time, struct timespec* timespecTime);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(
+ XrInstance instance,
+ const struct timespec* timespecTime,
+ XrTime* time);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(
+ XrInstance instance,
+ XrTime time,
+ struct timespec* timespecTime);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_TIMESPEC */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_KHR_loader_init_android 1
+#define XR_KHR_loader_init_android_SPEC_VERSION 1
+#define XR_KHR_LOADER_INIT_ANDROID_EXTENSION_NAME "XR_KHR_loader_init_android"
+typedef struct XrLoaderInitInfoAndroidKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ void* XR_MAY_ALIAS applicationVM;
+ void* XR_MAY_ALIAS applicationContext;
+} XrLoaderInitInfoAndroidKHR;
+
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_KHR_vulkan_enable2 1
+#define XR_KHR_vulkan_enable2_SPEC_VERSION 2
+#define XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME "XR_KHR_vulkan_enable2"
+typedef XrFlags64 XrVulkanInstanceCreateFlagsKHR;
+
+// Flag bits for XrVulkanInstanceCreateFlagsKHR
+
+typedef XrFlags64 XrVulkanDeviceCreateFlagsKHR;
+
+// Flag bits for XrVulkanDeviceCreateFlagsKHR
+
+typedef struct XrVulkanInstanceCreateInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSystemId systemId;
+ XrVulkanInstanceCreateFlagsKHR createFlags;
+ PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
+ const VkInstanceCreateInfo* vulkanCreateInfo;
+ const VkAllocationCallbacks* vulkanAllocator;
+} XrVulkanInstanceCreateInfoKHR;
+
+typedef struct XrVulkanDeviceCreateInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSystemId systemId;
+ XrVulkanDeviceCreateFlagsKHR createFlags;
+ PFN_vkGetInstanceProcAddr pfnGetInstanceProcAddr;
+ VkPhysicalDevice vulkanPhysicalDevice;
+ const VkDeviceCreateInfo* vulkanCreateInfo;
+ const VkAllocationCallbacks* vulkanAllocator;
+} XrVulkanDeviceCreateInfoKHR;
+
+typedef XrGraphicsBindingVulkanKHR XrGraphicsBindingVulkan2KHR;
+
+typedef struct XrVulkanGraphicsDeviceGetInfoKHR {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrSystemId systemId;
+ VkInstance vulkanInstance;
+} XrVulkanGraphicsDeviceGetInfoKHR;
+
+typedef XrSwapchainImageVulkanKHR XrSwapchainImageVulkan2KHR;
+
+typedef XrGraphicsRequirementsVulkanKHR XrGraphicsRequirementsVulkan2KHR;
+
+typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanInstanceKHR)(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult);
+typedef XrResult (XRAPI_PTR *PFN_xrCreateVulkanDeviceKHR)(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsDevice2KHR)(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice);
+typedef XrResult (XRAPI_PTR *PFN_xrGetVulkanGraphicsRequirements2KHR)(XrInstance instance, XrSystemId systemId, XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(
+ XrInstance instance,
+ const XrVulkanInstanceCreateInfoKHR* createInfo,
+ VkInstance* vulkanInstance,
+ VkResult* vulkanResult);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateVulkanDeviceKHR(
+ XrInstance instance,
+ const XrVulkanDeviceCreateInfoKHR* createInfo,
+ VkDevice* vulkanDevice,
+ VkResult* vulkanResult);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsDevice2KHR(
+ XrInstance instance,
+ const XrVulkanGraphicsDeviceGetInfoKHR* getInfo,
+ VkPhysicalDevice* vulkanPhysicalDevice);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetVulkanGraphicsRequirements2KHR(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrGraphicsRequirementsVulkanKHR* graphicsRequirements);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_PLATFORM_EGL
+
+#define XR_MNDX_egl_enable 1
+#define XR_MNDX_egl_enable_SPEC_VERSION 1
+#define XR_MNDX_EGL_ENABLE_EXTENSION_NAME "XR_MNDX_egl_enable"
+// XrGraphicsBindingEGLMNDX extends XrSessionCreateInfo
+typedef struct XrGraphicsBindingEGLMNDX {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ PFNEGLGETPROCADDRESSPROC getProcAddress;
+ EGLDisplay display;
+ EGLConfig config;
+ EGLContext context;
+} XrGraphicsBindingEGLMNDX;
+
+#endif /* XR_USE_PLATFORM_EGL */
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#define XR_MSFT_perception_anchor_interop 1
+#define XR_MSFT_perception_anchor_interop_SPEC_VERSION 1
+#define XR_MSFT_PERCEPTION_ANCHOR_INTEROP_EXTENSION_NAME "XR_MSFT_perception_anchor_interop"
+typedef XrResult (XRAPI_PTR *PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT)(XrSession session, IUnknown* perceptionAnchor, XrSpatialAnchorMSFT* anchor);
+typedef XrResult (XRAPI_PTR *PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT)(XrSession session, XrSpatialAnchorMSFT anchor, IUnknown** perceptionAnchor);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrCreateSpatialAnchorFromPerceptionAnchorMSFT(
+ XrSession session,
+ IUnknown* perceptionAnchor,
+ XrSpatialAnchorMSFT* anchor);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrTryGetPerceptionAnchorFromSpatialAnchorMSFT(
+ XrSession session,
+ XrSpatialAnchorMSFT anchor,
+ IUnknown** perceptionAnchor);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_PLATFORM_WIN32 */
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#define XR_MSFT_holographic_window_attachment 1
+#define XR_MSFT_holographic_window_attachment_SPEC_VERSION 1
+#define XR_MSFT_HOLOGRAPHIC_WINDOW_ATTACHMENT_EXTENSION_NAME "XR_MSFT_holographic_window_attachment"
+#ifdef XR_USE_PLATFORM_WIN32
+// XrHolographicWindowAttachmentMSFT extends XrSessionCreateInfo
+typedef struct XrHolographicWindowAttachmentMSFT {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ IUnknown* holographicSpace;
+ IUnknown* coreWindow;
+} XrHolographicWindowAttachmentMSFT;
+#endif // XR_USE_PLATFORM_WIN32
+
+#endif /* XR_USE_PLATFORM_WIN32 */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_FB_android_surface_swapchain_create 1
+#define XR_FB_android_surface_swapchain_create_SPEC_VERSION 1
+#define XR_FB_ANDROID_SURFACE_SWAPCHAIN_CREATE_EXTENSION_NAME "XR_FB_android_surface_swapchain_create"
+typedef XrFlags64 XrAndroidSurfaceSwapchainFlagsFB;
+
+// Flag bits for XrAndroidSurfaceSwapchainFlagsFB
+static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB = 0x00000001;
+static const XrAndroidSurfaceSwapchainFlagsFB XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB = 0x00000002;
+
+#ifdef XR_USE_PLATFORM_ANDROID
+// XrAndroidSurfaceSwapchainCreateInfoFB extends XrSwapchainCreateInfo
+typedef struct XrAndroidSurfaceSwapchainCreateInfoFB {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ XrAndroidSurfaceSwapchainFlagsFB createFlags;
+} XrAndroidSurfaceSwapchainCreateInfoFB;
+#endif // XR_USE_PLATFORM_ANDROID
+
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#define XR_OCULUS_audio_device_guid 1
+#define XR_OCULUS_audio_device_guid_SPEC_VERSION 1
+#define XR_OCULUS_AUDIO_DEVICE_GUID_EXTENSION_NAME "XR_OCULUS_audio_device_guid"
+#define XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS 128
+typedef XrResult (XRAPI_PTR *PFN_xrGetAudioOutputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
+typedef XrResult (XRAPI_PTR *PFN_xrGetAudioInputDeviceGuidOculus)(XrInstance instance, wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
+
+#ifndef XR_NO_PROTOTYPES
+#ifdef XR_EXTENSION_PROTOTYPES
+XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioOutputDeviceGuidOculus(
+ XrInstance instance,
+ wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
+
+XRAPI_ATTR XrResult XRAPI_CALL xrGetAudioInputDeviceGuidOculus(
+ XrInstance instance,
+ wchar_t buffer[XR_MAX_AUDIO_DEVICE_STR_SIZE_OCULUS]);
+#endif /* XR_EXTENSION_PROTOTYPES */
+#endif /* !XR_NO_PROTOTYPES */
+#endif /* XR_USE_PLATFORM_WIN32 */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_FB_foveation_vulkan 1
+#define XR_FB_foveation_vulkan_SPEC_VERSION 1
+#define XR_FB_FOVEATION_VULKAN_EXTENSION_NAME "XR_FB_foveation_vulkan"
+// XrSwapchainImageFoveationVulkanFB extends XrSwapchainImageVulkanKHR
+typedef struct XrSwapchainImageFoveationVulkanFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ VkImage image;
+ uint32_t width;
+ uint32_t height;
+} XrSwapchainImageFoveationVulkanFB;
+
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_PLATFORM_ANDROID
+
+#define XR_FB_swapchain_update_state_android_surface 1
+#define XR_FB_swapchain_update_state_android_surface_SPEC_VERSION 1
+#define XR_FB_SWAPCHAIN_UPDATE_STATE_ANDROID_SURFACE_EXTENSION_NAME "XR_FB_swapchain_update_state_android_surface"
+#ifdef XR_USE_PLATFORM_ANDROID
+typedef struct XrSwapchainStateAndroidSurfaceDimensionsFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ uint32_t width;
+ uint32_t height;
+} XrSwapchainStateAndroidSurfaceDimensionsFB;
+#endif // XR_USE_PLATFORM_ANDROID
+
+#endif /* XR_USE_PLATFORM_ANDROID */
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+
+#define XR_FB_swapchain_update_state_opengl_es 1
+#define XR_FB_swapchain_update_state_opengl_es_SPEC_VERSION 1
+#define XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME "XR_FB_swapchain_update_state_opengl_es"
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+typedef struct XrSwapchainStateSamplerOpenGLESFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ EGLenum minFilter;
+ EGLenum magFilter;
+ EGLenum wrapModeS;
+ EGLenum wrapModeT;
+ EGLenum swizzleRed;
+ EGLenum swizzleGreen;
+ EGLenum swizzleBlue;
+ EGLenum swizzleAlpha;
+ float maxAnisotropy;
+ XrColor4f borderColor;
+} XrSwapchainStateSamplerOpenGLESFB;
+#endif // XR_USE_GRAPHICS_API_OPENGL_ES
+
+#endif /* XR_USE_GRAPHICS_API_OPENGL_ES */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_FB_swapchain_update_state_vulkan 1
+#define XR_FB_swapchain_update_state_vulkan_SPEC_VERSION 1
+#define XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME "XR_FB_swapchain_update_state_vulkan"
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+typedef struct XrSwapchainStateSamplerVulkanFB {
+ XrStructureType type;
+ void* XR_MAY_ALIAS next;
+ VkFilter minFilter;
+ VkFilter magFilter;
+ VkSamplerMipmapMode mipmapMode;
+ VkSamplerAddressMode wrapModeS;
+ VkSamplerAddressMode wrapModeT;
+ VkComponentSwizzle swizzleRed;
+ VkComponentSwizzle swizzleGreen;
+ VkComponentSwizzle swizzleBlue;
+ VkComponentSwizzle swizzleAlpha;
+ float maxAnisotropy;
+ XrColor4f borderColor;
+} XrSwapchainStateSamplerVulkanFB;
+#endif // XR_USE_GRAPHICS_API_VULKAN
+
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+
+#define XR_META_vulkan_swapchain_create_info 1
+#define XR_META_vulkan_swapchain_create_info_SPEC_VERSION 1
+#define XR_META_VULKAN_SWAPCHAIN_CREATE_INFO_EXTENSION_NAME "XR_META_vulkan_swapchain_create_info"
+// XrVulkanSwapchainCreateInfoMETA extends XrSwapchainCreateInfo
+typedef struct XrVulkanSwapchainCreateInfoMETA {
+ XrStructureType type;
+ const void* XR_MAY_ALIAS next;
+ VkImageCreateFlags additionalCreateFlags;
+ VkImageUsageFlags additionalUsageFlags;
+} XrVulkanSwapchainCreateInfoMETA;
+
+#endif /* XR_USE_GRAPHICS_API_VULKAN */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/openxr/include/openxr/openxr_platform_defines.h b/thirdparty/openxr/include/openxr/openxr_platform_defines.h
new file mode 100644
index 0000000000..31fa05a0c8
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr_platform_defines.h
@@ -0,0 +1,110 @@
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+#ifndef OPENXR_PLATFORM_DEFINES_H_
+#define OPENXR_PLATFORM_DEFINES_H_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Platform-specific calling convention macros.
+ *
+ * Platforms should define these so that OpenXR clients call OpenXR functions
+ * with the same calling conventions that the OpenXR implementation expects.
+ *
+ * XRAPI_ATTR - Placed before the return type in function declarations.
+ * Useful for C++11 and GCC/Clang-style function attribute syntax.
+ * XRAPI_CALL - Placed after the return type in function declarations.
+ * Useful for MSVC-style calling convention syntax.
+ * XRAPI_PTR - Placed between the '(' and '*' in function pointer types.
+ *
+ * Function declaration: XRAPI_ATTR void XRAPI_CALL xrFunction(void);
+ * Function pointer type: typedef void (XRAPI_PTR *PFN_xrFunction)(void);
+ */
+#if defined(_WIN32)
+#define XRAPI_ATTR
+// On Windows, functions use the stdcall convention
+#define XRAPI_CALL __stdcall
+#define XRAPI_PTR XRAPI_CALL
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
+#error "API not supported for the 'armeabi' NDK ABI"
+#elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
+// On Android 32-bit ARM targets, functions use the "hardfloat"
+// calling convention, i.e. float parameters are passed in registers. This
+// is true even if the rest of the application passes floats on the stack,
+// as it does by default when compiling for the armeabi-v7a NDK ABI.
+#define XRAPI_ATTR __attribute__((pcs("aapcs-vfp")))
+#define XRAPI_CALL
+#define XRAPI_PTR XRAPI_ATTR
+#else
+// On other platforms, use the default calling convention
+#define XRAPI_ATTR
+#define XRAPI_CALL
+#define XRAPI_PTR
+#endif
+
+#include <stddef.h>
+
+#if !defined(XR_NO_STDINT_H)
+#if defined(_MSC_VER) && (_MSC_VER < 1600)
+typedef signed __int8 int8_t;
+typedef unsigned __int8 uint8_t;
+typedef signed __int16 int16_t;
+typedef unsigned __int16 uint16_t;
+typedef signed __int32 int32_t;
+typedef unsigned __int32 uint32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <stdint.h>
+#endif
+#endif // !defined( XR_NO_STDINT_H )
+
+// XR_PTR_SIZE (in bytes)
+#if (defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__))
+#define XR_PTR_SIZE 8
+#else
+#define XR_PTR_SIZE 4
+#endif
+
+// Needed so we can use clang __has_feature portably.
+#if !defined(XR_COMPILER_HAS_FEATURE)
+#if defined(__clang__)
+#define XR_COMPILER_HAS_FEATURE(x) __has_feature(x)
+#else
+#define XR_COMPILER_HAS_FEATURE(x) 0
+#endif
+#endif
+
+// Identifies if the current compiler has C++11 support enabled.
+// Does not by itself identify if any given C++11 feature is present.
+#if !defined(XR_CPP11_ENABLED) && defined(__cplusplus)
+#if defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
+#define XR_CPP11_ENABLED 1
+#elif defined(_MSC_VER) && (_MSC_VER >= 1600)
+#define XR_CPP11_ENABLED 1
+#elif (__cplusplus >= 201103L) // 201103 is the first C++11 version.
+#define XR_CPP11_ENABLED 1
+#endif
+#endif
+
+// Identifies if the current compiler supports C++11 nullptr.
+#if !defined(XR_CPP_NULLPTR_SUPPORTED)
+#if defined(XR_CPP11_ENABLED) && \
+ ((defined(__clang__) && XR_COMPILER_HAS_FEATURE(cxx_nullptr)) || \
+ (defined(__GNUC__) && (((__GNUC__ * 1000) + __GNUC_MINOR__) >= 4006)) || \
+ (defined(_MSC_VER) && (_MSC_VER >= 1600)) || \
+ (defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403)))
+#define XR_CPP_NULLPTR_SUPPORTED 1
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/thirdparty/openxr/include/openxr/openxr_reflection.h b/thirdparty/openxr/include/openxr/openxr_reflection.h
new file mode 100644
index 0000000000..163b54e4e4
--- /dev/null
+++ b/thirdparty/openxr/include/openxr/openxr_reflection.h
@@ -0,0 +1,3095 @@
+#ifndef OPENXR_REFLECTION_H_
+#define OPENXR_REFLECTION_H_ 1
+
+/*
+** Copyright (c) 2017-2022, The Khronos Group Inc.
+**
+** SPDX-License-Identifier: Apache-2.0 OR MIT
+*/
+
+/*
+** This header is generated from the Khronos OpenXR XML API Registry.
+**
+*/
+
+#include "openxr.h"
+
+/*
+This file contains expansion macros (X Macros) for OpenXR enumerations and structures.
+Example of how to use expansion macros to make an enum-to-string function:
+
+#define XR_ENUM_CASE_STR(name, val) case name: return #name;
+#define XR_ENUM_STR(enumType) \
+ constexpr const char* XrEnumStr(enumType e) { \
+ switch (e) { \
+ XR_LIST_ENUM_##enumType(XR_ENUM_CASE_STR) \
+ default: return "Unknown"; \
+ } \
+ } \
+
+XR_ENUM_STR(XrResult);
+*/
+
+#define XR_LIST_ENUM_XrResult(_) \
+ _(XR_SUCCESS, 0) \
+ _(XR_TIMEOUT_EXPIRED, 1) \
+ _(XR_SESSION_LOSS_PENDING, 3) \
+ _(XR_EVENT_UNAVAILABLE, 4) \
+ _(XR_SPACE_BOUNDS_UNAVAILABLE, 7) \
+ _(XR_SESSION_NOT_FOCUSED, 8) \
+ _(XR_FRAME_DISCARDED, 9) \
+ _(XR_ERROR_VALIDATION_FAILURE, -1) \
+ _(XR_ERROR_RUNTIME_FAILURE, -2) \
+ _(XR_ERROR_OUT_OF_MEMORY, -3) \
+ _(XR_ERROR_API_VERSION_UNSUPPORTED, -4) \
+ _(XR_ERROR_INITIALIZATION_FAILED, -6) \
+ _(XR_ERROR_FUNCTION_UNSUPPORTED, -7) \
+ _(XR_ERROR_FEATURE_UNSUPPORTED, -8) \
+ _(XR_ERROR_EXTENSION_NOT_PRESENT, -9) \
+ _(XR_ERROR_LIMIT_REACHED, -10) \
+ _(XR_ERROR_SIZE_INSUFFICIENT, -11) \
+ _(XR_ERROR_HANDLE_INVALID, -12) \
+ _(XR_ERROR_INSTANCE_LOST, -13) \
+ _(XR_ERROR_SESSION_RUNNING, -14) \
+ _(XR_ERROR_SESSION_NOT_RUNNING, -16) \
+ _(XR_ERROR_SESSION_LOST, -17) \
+ _(XR_ERROR_SYSTEM_INVALID, -18) \
+ _(XR_ERROR_PATH_INVALID, -19) \
+ _(XR_ERROR_PATH_COUNT_EXCEEDED, -20) \
+ _(XR_ERROR_PATH_FORMAT_INVALID, -21) \
+ _(XR_ERROR_PATH_UNSUPPORTED, -22) \
+ _(XR_ERROR_LAYER_INVALID, -23) \
+ _(XR_ERROR_LAYER_LIMIT_EXCEEDED, -24) \
+ _(XR_ERROR_SWAPCHAIN_RECT_INVALID, -25) \
+ _(XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED, -26) \
+ _(XR_ERROR_ACTION_TYPE_MISMATCH, -27) \
+ _(XR_ERROR_SESSION_NOT_READY, -28) \
+ _(XR_ERROR_SESSION_NOT_STOPPING, -29) \
+ _(XR_ERROR_TIME_INVALID, -30) \
+ _(XR_ERROR_REFERENCE_SPACE_UNSUPPORTED, -31) \
+ _(XR_ERROR_FILE_ACCESS_ERROR, -32) \
+ _(XR_ERROR_FILE_CONTENTS_INVALID, -33) \
+ _(XR_ERROR_FORM_FACTOR_UNSUPPORTED, -34) \
+ _(XR_ERROR_FORM_FACTOR_UNAVAILABLE, -35) \
+ _(XR_ERROR_API_LAYER_NOT_PRESENT, -36) \
+ _(XR_ERROR_CALL_ORDER_INVALID, -37) \
+ _(XR_ERROR_GRAPHICS_DEVICE_INVALID, -38) \
+ _(XR_ERROR_POSE_INVALID, -39) \
+ _(XR_ERROR_INDEX_OUT_OF_RANGE, -40) \
+ _(XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, -41) \
+ _(XR_ERROR_ENVIRONMENT_BLEND_MODE_UNSUPPORTED, -42) \
+ _(XR_ERROR_NAME_DUPLICATED, -44) \
+ _(XR_ERROR_NAME_INVALID, -45) \
+ _(XR_ERROR_ACTIONSET_NOT_ATTACHED, -46) \
+ _(XR_ERROR_ACTIONSETS_ALREADY_ATTACHED, -47) \
+ _(XR_ERROR_LOCALIZED_NAME_DUPLICATED, -48) \
+ _(XR_ERROR_LOCALIZED_NAME_INVALID, -49) \
+ _(XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING, -50) \
+ _(XR_ERROR_RUNTIME_UNAVAILABLE, -51) \
+ _(XR_ERROR_ANDROID_THREAD_SETTINGS_ID_INVALID_KHR, -1000003000) \
+ _(XR_ERROR_ANDROID_THREAD_SETTINGS_FAILURE_KHR, -1000003001) \
+ _(XR_ERROR_CREATE_SPATIAL_ANCHOR_FAILED_MSFT, -1000039001) \
+ _(XR_ERROR_SECONDARY_VIEW_CONFIGURATION_TYPE_NOT_ENABLED_MSFT, -1000053000) \
+ _(XR_ERROR_CONTROLLER_MODEL_KEY_INVALID_MSFT, -1000055000) \
+ _(XR_ERROR_REPROJECTION_MODE_UNSUPPORTED_MSFT, -1000066000) \
+ _(XR_ERROR_COMPUTE_NEW_SCENE_NOT_COMPLETED_MSFT, -1000097000) \
+ _(XR_ERROR_SCENE_COMPONENT_ID_INVALID_MSFT, -1000097001) \
+ _(XR_ERROR_SCENE_COMPONENT_TYPE_MISMATCH_MSFT, -1000097002) \
+ _(XR_ERROR_SCENE_MESH_BUFFER_ID_INVALID_MSFT, -1000097003) \
+ _(XR_ERROR_SCENE_COMPUTE_FEATURE_INCOMPATIBLE_MSFT, -1000097004) \
+ _(XR_ERROR_SCENE_COMPUTE_CONSISTENCY_MISMATCH_MSFT, -1000097005) \
+ _(XR_ERROR_DISPLAY_REFRESH_RATE_UNSUPPORTED_FB, -1000101000) \
+ _(XR_ERROR_COLOR_SPACE_UNSUPPORTED_FB, -1000108000) \
+ _(XR_ERROR_SPACE_COMPONENT_NOT_SUPPORTED_FB, -1000113000) \
+ _(XR_ERROR_SPACE_COMPONENT_NOT_ENABLED_FB, -1000113001) \
+ _(XR_ERROR_SPACE_COMPONENT_STATUS_PENDING_FB, -1000113002) \
+ _(XR_ERROR_SPACE_COMPONENT_STATUS_ALREADY_SET_FB, -1000113003) \
+ _(XR_ERROR_UNEXPECTED_STATE_PASSTHROUGH_FB, -1000118000) \
+ _(XR_ERROR_FEATURE_ALREADY_CREATED_PASSTHROUGH_FB, -1000118001) \
+ _(XR_ERROR_FEATURE_REQUIRED_PASSTHROUGH_FB, -1000118002) \
+ _(XR_ERROR_NOT_PERMITTED_PASSTHROUGH_FB, -1000118003) \
+ _(XR_ERROR_INSUFFICIENT_RESOURCES_PASSTHROUGH_FB, -1000118004) \
+ _(XR_ERROR_UNKNOWN_PASSTHROUGH_FB, -1000118050) \
+ _(XR_ERROR_RENDER_MODEL_KEY_INVALID_FB, -1000119000) \
+ _(XR_RENDER_MODEL_UNAVAILABLE_FB, 1000119020) \
+ _(XR_ERROR_MARKER_NOT_TRACKED_VARJO, -1000124000) \
+ _(XR_ERROR_MARKER_ID_INVALID_VARJO, -1000124001) \
+ _(XR_ERROR_SPATIAL_ANCHOR_NAME_NOT_FOUND_MSFT, -1000142001) \
+ _(XR_ERROR_SPATIAL_ANCHOR_NAME_INVALID_MSFT, -1000142002) \
+ _(XR_RESULT_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrStructureType(_) \
+ _(XR_TYPE_UNKNOWN, 0) \
+ _(XR_TYPE_API_LAYER_PROPERTIES, 1) \
+ _(XR_TYPE_EXTENSION_PROPERTIES, 2) \
+ _(XR_TYPE_INSTANCE_CREATE_INFO, 3) \
+ _(XR_TYPE_SYSTEM_GET_INFO, 4) \
+ _(XR_TYPE_SYSTEM_PROPERTIES, 5) \
+ _(XR_TYPE_VIEW_LOCATE_INFO, 6) \
+ _(XR_TYPE_VIEW, 7) \
+ _(XR_TYPE_SESSION_CREATE_INFO, 8) \
+ _(XR_TYPE_SWAPCHAIN_CREATE_INFO, 9) \
+ _(XR_TYPE_SESSION_BEGIN_INFO, 10) \
+ _(XR_TYPE_VIEW_STATE, 11) \
+ _(XR_TYPE_FRAME_END_INFO, 12) \
+ _(XR_TYPE_HAPTIC_VIBRATION, 13) \
+ _(XR_TYPE_EVENT_DATA_BUFFER, 16) \
+ _(XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING, 17) \
+ _(XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED, 18) \
+ _(XR_TYPE_ACTION_STATE_BOOLEAN, 23) \
+ _(XR_TYPE_ACTION_STATE_FLOAT, 24) \
+ _(XR_TYPE_ACTION_STATE_VECTOR2F, 25) \
+ _(XR_TYPE_ACTION_STATE_POSE, 27) \
+ _(XR_TYPE_ACTION_SET_CREATE_INFO, 28) \
+ _(XR_TYPE_ACTION_CREATE_INFO, 29) \
+ _(XR_TYPE_INSTANCE_PROPERTIES, 32) \
+ _(XR_TYPE_FRAME_WAIT_INFO, 33) \
+ _(XR_TYPE_COMPOSITION_LAYER_PROJECTION, 35) \
+ _(XR_TYPE_COMPOSITION_LAYER_QUAD, 36) \
+ _(XR_TYPE_REFERENCE_SPACE_CREATE_INFO, 37) \
+ _(XR_TYPE_ACTION_SPACE_CREATE_INFO, 38) \
+ _(XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING, 40) \
+ _(XR_TYPE_VIEW_CONFIGURATION_VIEW, 41) \
+ _(XR_TYPE_SPACE_LOCATION, 42) \
+ _(XR_TYPE_SPACE_VELOCITY, 43) \
+ _(XR_TYPE_FRAME_STATE, 44) \
+ _(XR_TYPE_VIEW_CONFIGURATION_PROPERTIES, 45) \
+ _(XR_TYPE_FRAME_BEGIN_INFO, 46) \
+ _(XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW, 48) \
+ _(XR_TYPE_EVENT_DATA_EVENTS_LOST, 49) \
+ _(XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING, 51) \
+ _(XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED, 52) \
+ _(XR_TYPE_INTERACTION_PROFILE_STATE, 53) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO, 55) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO, 56) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, 57) \
+ _(XR_TYPE_ACTION_STATE_GET_INFO, 58) \
+ _(XR_TYPE_HAPTIC_ACTION_INFO, 59) \
+ _(XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO, 60) \
+ _(XR_TYPE_ACTIONS_SYNC_INFO, 61) \
+ _(XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO, 62) \
+ _(XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO, 63) \
+ _(XR_TYPE_COMPOSITION_LAYER_CUBE_KHR, 1000006000) \
+ _(XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR, 1000008000) \
+ _(XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR, 1000010000) \
+ _(XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR, 1000014000) \
+ _(XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT, 1000015000) \
+ _(XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR, 1000017000) \
+ _(XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR, 1000018000) \
+ _(XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, 1000019000) \
+ _(XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT, 1000019001) \
+ _(XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, 1000019002) \
+ _(XR_TYPE_DEBUG_UTILS_LABEL_EXT, 1000019003) \
+ _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR, 1000023000) \
+ _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR, 1000023001) \
+ _(XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR, 1000023002) \
+ _(XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR, 1000023003) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR, 1000023004) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR, 1000023005) \
+ _(XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR, 1000024001) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR, 1000024002) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR, 1000024003) \
+ _(XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR, 1000025000) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR, 1000025001) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR, 1000025002) \
+ _(XR_TYPE_GRAPHICS_BINDING_D3D11_KHR, 1000027000) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR, 1000027001) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR, 1000027002) \
+ _(XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, 1000028000) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR, 1000028001) \
+ _(XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR, 1000028002) \
+ _(XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT, 1000030000) \
+ _(XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT, 1000030001) \
+ _(XR_TYPE_VISIBILITY_MASK_KHR, 1000031000) \
+ _(XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR, 1000031001) \
+ _(XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX, 1000033000) \
+ _(XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX, 1000033003) \
+ _(XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR, 1000034000) \
+ _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT, 1000039000) \
+ _(XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT, 1000039001) \
+ _(XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB, 1000040000) \
+ _(XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB, 1000041001) \
+ _(XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT, 1000046000) \
+ _(XR_TYPE_GRAPHICS_BINDING_EGL_MNDX, 1000048004) \
+ _(XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT, 1000049000) \
+ _(XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT, 1000049001) \
+ _(XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT, 1000049002) \
+ _(XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT, 1000049003) \
+ _(XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT, 1000051000) \
+ _(XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT, 1000051001) \
+ _(XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT, 1000051002) \
+ _(XR_TYPE_HAND_JOINT_LOCATIONS_EXT, 1000051003) \
+ _(XR_TYPE_HAND_JOINT_VELOCITIES_EXT, 1000051004) \
+ _(XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT, 1000052000) \
+ _(XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT, 1000052001) \
+ _(XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT, 1000052002) \
+ _(XR_TYPE_HAND_MESH_MSFT, 1000052003) \
+ _(XR_TYPE_HAND_POSE_TYPE_INFO_MSFT, 1000052004) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT, 1000053000) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT, 1000053001) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT, 1000053002) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT, 1000053003) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT, 1000053004) \
+ _(XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT, 1000053005) \
+ _(XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT, 1000055000) \
+ _(XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT, 1000055001) \
+ _(XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT, 1000055002) \
+ _(XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT, 1000055003) \
+ _(XR_TYPE_CONTROLLER_MODEL_STATE_MSFT, 1000055004) \
+ _(XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC, 1000059000) \
+ _(XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT, 1000063000) \
+ _(XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT, 1000066000) \
+ _(XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT, 1000066001) \
+ _(XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB, 1000070000) \
+ _(XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB, 1000072000) \
+ _(XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT, 1000078000) \
+ _(XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE, 1000079000) \
+ _(XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT, 1000080000) \
+ _(XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR, 1000089000) \
+ _(XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR, 1000090000) \
+ _(XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR, 1000090001) \
+ _(XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR, 1000090003) \
+ _(XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR, 1000091000) \
+ _(XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT, 1000097000) \
+ _(XR_TYPE_SCENE_CREATE_INFO_MSFT, 1000097001) \
+ _(XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT, 1000097002) \
+ _(XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT, 1000097003) \
+ _(XR_TYPE_SCENE_COMPONENTS_MSFT, 1000097004) \
+ _(XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT, 1000097005) \
+ _(XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT, 1000097006) \
+ _(XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT, 1000097007) \
+ _(XR_TYPE_SCENE_OBJECTS_MSFT, 1000097008) \
+ _(XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT, 1000097009) \
+ _(XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT, 1000097010) \
+ _(XR_TYPE_SCENE_PLANES_MSFT, 1000097011) \
+ _(XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT, 1000097012) \
+ _(XR_TYPE_SCENE_MESHES_MSFT, 1000097013) \
+ _(XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT, 1000097014) \
+ _(XR_TYPE_SCENE_MESH_BUFFERS_MSFT, 1000097015) \
+ _(XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT, 1000097016) \
+ _(XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT, 1000097017) \
+ _(XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT, 1000097018) \
+ _(XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT, 1000098000) \
+ _(XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT, 1000098001) \
+ _(XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB, 1000101000) \
+ _(XR_TYPE_VIVE_TRACKER_PATHS_HTCX, 1000103000) \
+ _(XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX, 1000103001) \
+ _(XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC, 1000104000) \
+ _(XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC, 1000104001) \
+ _(XR_TYPE_FACIAL_EXPRESSIONS_HTC, 1000104002) \
+ _(XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB, 1000108000) \
+ _(XR_TYPE_HAND_TRACKING_MESH_FB, 1000110001) \
+ _(XR_TYPE_HAND_TRACKING_SCALE_FB, 1000110003) \
+ _(XR_TYPE_HAND_TRACKING_AIM_STATE_FB, 1000111001) \
+ _(XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB, 1000112000) \
+ _(XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB, 1000113004) \
+ _(XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB, 1000113003) \
+ _(XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB, 1000113007) \
+ _(XR_TYPE_SPACE_COMPONENT_STATUS_FB, 1000113001) \
+ _(XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB, 1000113005) \
+ _(XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB, 1000113006) \
+ _(XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB, 1000114000) \
+ _(XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB, 1000114001) \
+ _(XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB, 1000114002) \
+ _(XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB, 1000115000) \
+ _(XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB, 1000116009) \
+ _(XR_TYPE_KEYBOARD_TRACKING_QUERY_FB, 1000116004) \
+ _(XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB, 1000116002) \
+ _(XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB, 1000117001) \
+ _(XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB, 1000118000) \
+ _(XR_TYPE_PASSTHROUGH_CREATE_INFO_FB, 1000118001) \
+ _(XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB, 1000118002) \
+ _(XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB, 1000118003) \
+ _(XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB, 1000118004) \
+ _(XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB, 1000118005) \
+ _(XR_TYPE_PASSTHROUGH_STYLE_FB, 1000118020) \
+ _(XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB, 1000118021) \
+ _(XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB, 1000118022) \
+ _(XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB, 1000118023) \
+ _(XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB, 1000118030) \
+ _(XR_TYPE_RENDER_MODEL_PATH_INFO_FB, 1000119000) \
+ _(XR_TYPE_RENDER_MODEL_PROPERTIES_FB, 1000119001) \
+ _(XR_TYPE_RENDER_MODEL_BUFFER_FB, 1000119002) \
+ _(XR_TYPE_RENDER_MODEL_LOAD_INFO_FB, 1000119003) \
+ _(XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB, 1000119004) \
+ _(XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB, 1000119005) \
+ _(XR_TYPE_BINDING_MODIFICATIONS_KHR, 1000120000) \
+ _(XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO, 1000121000) \
+ _(XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO, 1000121001) \
+ _(XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO, 1000121002) \
+ _(XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO, 1000122000) \
+ _(XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO, 1000124000) \
+ _(XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO, 1000124001) \
+ _(XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO, 1000124002) \
+ _(XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT, 1000142000) \
+ _(XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT, 1000142001) \
+ _(XR_TYPE_SPACE_QUERY_INFO_FB, 1000156001) \
+ _(XR_TYPE_SPACE_QUERY_RESULTS_FB, 1000156002) \
+ _(XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB, 1000156003) \
+ _(XR_TYPE_SPACE_UUID_FILTER_INFO_FB, 1000156054) \
+ _(XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB, 1000156052) \
+ _(XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB, 1000156103) \
+ _(XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB, 1000156104) \
+ _(XR_TYPE_SPACE_SAVE_INFO_FB, 1000158000) \
+ _(XR_TYPE_SPACE_ERASE_INFO_FB, 1000158001) \
+ _(XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB, 1000158106) \
+ _(XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB, 1000158107) \
+ _(XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB, 1000160000) \
+ _(XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB, 1000161000) \
+ _(XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB, 1000162000) \
+ _(XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB, 1000163000) \
+ _(XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB, 1000171000) \
+ _(XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB, 1000171001) \
+ _(XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE, 1000196000) \
+ _(XR_TYPE_SPACE_CONTAINER_FB, 1000199000) \
+ _(XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB, 1000203002) \
+ _(XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB, 1000204000) \
+ _(XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META, 1000227000) \
+ _(XR_TYPE_PERFORMANCE_METRICS_STATE_META, 1000232001) \
+ _(XR_TYPE_PERFORMANCE_METRICS_COUNTER_META, 1000232002) \
+ _(XR_STRUCTURE_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFormFactor(_) \
+ _(XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY, 1) \
+ _(XR_FORM_FACTOR_HANDHELD_DISPLAY, 2) \
+ _(XR_FORM_FACTOR_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrViewConfigurationType(_) \
+ _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO, 1) \
+ _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO, 2) \
+ _(XR_VIEW_CONFIGURATION_TYPE_PRIMARY_QUAD_VARJO, 1000037000) \
+ _(XR_VIEW_CONFIGURATION_TYPE_SECONDARY_MONO_FIRST_PERSON_OBSERVER_MSFT, 1000054000) \
+ _(XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrEnvironmentBlendMode(_) \
+ _(XR_ENVIRONMENT_BLEND_MODE_OPAQUE, 1) \
+ _(XR_ENVIRONMENT_BLEND_MODE_ADDITIVE, 2) \
+ _(XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND, 3) \
+ _(XR_ENVIRONMENT_BLEND_MODE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrReferenceSpaceType(_) \
+ _(XR_REFERENCE_SPACE_TYPE_VIEW, 1) \
+ _(XR_REFERENCE_SPACE_TYPE_LOCAL, 2) \
+ _(XR_REFERENCE_SPACE_TYPE_STAGE, 3) \
+ _(XR_REFERENCE_SPACE_TYPE_UNBOUNDED_MSFT, 1000038000) \
+ _(XR_REFERENCE_SPACE_TYPE_COMBINED_EYE_VARJO, 1000121000) \
+ _(XR_REFERENCE_SPACE_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrActionType(_) \
+ _(XR_ACTION_TYPE_BOOLEAN_INPUT, 1) \
+ _(XR_ACTION_TYPE_FLOAT_INPUT, 2) \
+ _(XR_ACTION_TYPE_VECTOR2F_INPUT, 3) \
+ _(XR_ACTION_TYPE_POSE_INPUT, 4) \
+ _(XR_ACTION_TYPE_VIBRATION_OUTPUT, 100) \
+ _(XR_ACTION_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrEyeVisibility(_) \
+ _(XR_EYE_VISIBILITY_BOTH, 0) \
+ _(XR_EYE_VISIBILITY_LEFT, 1) \
+ _(XR_EYE_VISIBILITY_RIGHT, 2) \
+ _(XR_EYE_VISIBILITY_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSessionState(_) \
+ _(XR_SESSION_STATE_UNKNOWN, 0) \
+ _(XR_SESSION_STATE_IDLE, 1) \
+ _(XR_SESSION_STATE_READY, 2) \
+ _(XR_SESSION_STATE_SYNCHRONIZED, 3) \
+ _(XR_SESSION_STATE_VISIBLE, 4) \
+ _(XR_SESSION_STATE_FOCUSED, 5) \
+ _(XR_SESSION_STATE_STOPPING, 6) \
+ _(XR_SESSION_STATE_LOSS_PENDING, 7) \
+ _(XR_SESSION_STATE_EXITING, 8) \
+ _(XR_SESSION_STATE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrObjectType(_) \
+ _(XR_OBJECT_TYPE_UNKNOWN, 0) \
+ _(XR_OBJECT_TYPE_INSTANCE, 1) \
+ _(XR_OBJECT_TYPE_SESSION, 2) \
+ _(XR_OBJECT_TYPE_SWAPCHAIN, 3) \
+ _(XR_OBJECT_TYPE_SPACE, 4) \
+ _(XR_OBJECT_TYPE_ACTION_SET, 5) \
+ _(XR_OBJECT_TYPE_ACTION, 6) \
+ _(XR_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT, 1000019000) \
+ _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_MSFT, 1000039000) \
+ _(XR_OBJECT_TYPE_SPATIAL_GRAPH_NODE_BINDING_MSFT, 1000049000) \
+ _(XR_OBJECT_TYPE_HAND_TRACKER_EXT, 1000051000) \
+ _(XR_OBJECT_TYPE_SCENE_OBSERVER_MSFT, 1000097000) \
+ _(XR_OBJECT_TYPE_SCENE_MSFT, 1000097001) \
+ _(XR_OBJECT_TYPE_FACIAL_TRACKER_HTC, 1000104000) \
+ _(XR_OBJECT_TYPE_FOVEATION_PROFILE_FB, 1000114000) \
+ _(XR_OBJECT_TYPE_TRIANGLE_MESH_FB, 1000117000) \
+ _(XR_OBJECT_TYPE_PASSTHROUGH_FB, 1000118000) \
+ _(XR_OBJECT_TYPE_PASSTHROUGH_LAYER_FB, 1000118002) \
+ _(XR_OBJECT_TYPE_GEOMETRY_INSTANCE_FB, 1000118004) \
+ _(XR_OBJECT_TYPE_SPATIAL_ANCHOR_STORE_CONNECTION_MSFT, 1000142000) \
+ _(XR_OBJECT_TYPE_MAX_ENUM, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrAndroidThreadTypeKHR(_) \
+ _(XR_ANDROID_THREAD_TYPE_APPLICATION_MAIN_KHR, 1) \
+ _(XR_ANDROID_THREAD_TYPE_APPLICATION_WORKER_KHR, 2) \
+ _(XR_ANDROID_THREAD_TYPE_RENDERER_MAIN_KHR, 3) \
+ _(XR_ANDROID_THREAD_TYPE_RENDERER_WORKER_KHR, 4) \
+ _(XR_ANDROID_THREAD_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrVisibilityMaskTypeKHR(_) \
+ _(XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR, 1) \
+ _(XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR, 2) \
+ _(XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR, 3) \
+ _(XR_VISIBILITY_MASK_TYPE_MAX_ENUM_KHR, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerfSettingsDomainEXT(_) \
+ _(XR_PERF_SETTINGS_DOMAIN_CPU_EXT, 1) \
+ _(XR_PERF_SETTINGS_DOMAIN_GPU_EXT, 2) \
+ _(XR_PERF_SETTINGS_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerfSettingsSubDomainEXT(_) \
+ _(XR_PERF_SETTINGS_SUB_DOMAIN_COMPOSITING_EXT, 1) \
+ _(XR_PERF_SETTINGS_SUB_DOMAIN_RENDERING_EXT, 2) \
+ _(XR_PERF_SETTINGS_SUB_DOMAIN_THERMAL_EXT, 3) \
+ _(XR_PERF_SETTINGS_SUB_DOMAIN_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerfSettingsLevelEXT(_) \
+ _(XR_PERF_SETTINGS_LEVEL_POWER_SAVINGS_EXT, 0) \
+ _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_LOW_EXT, 25) \
+ _(XR_PERF_SETTINGS_LEVEL_SUSTAINED_HIGH_EXT, 50) \
+ _(XR_PERF_SETTINGS_LEVEL_BOOST_EXT, 75) \
+ _(XR_PERF_SETTINGS_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerfSettingsNotificationLevelEXT(_) \
+ _(XR_PERF_SETTINGS_NOTIF_LEVEL_NORMAL_EXT, 0) \
+ _(XR_PERF_SETTINGS_NOTIF_LEVEL_WARNING_EXT, 25) \
+ _(XR_PERF_SETTINGS_NOTIF_LEVEL_IMPAIRED_EXT, 75) \
+ _(XR_PERF_SETTINGS_NOTIFICATION_LEVEL_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrBlendFactorFB(_) \
+ _(XR_BLEND_FACTOR_ZERO_FB, 0) \
+ _(XR_BLEND_FACTOR_ONE_FB, 1) \
+ _(XR_BLEND_FACTOR_SRC_ALPHA_FB, 2) \
+ _(XR_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA_FB, 3) \
+ _(XR_BLEND_FACTOR_DST_ALPHA_FB, 4) \
+ _(XR_BLEND_FACTOR_ONE_MINUS_DST_ALPHA_FB, 5) \
+ _(XR_BLEND_FACTOR_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSpatialGraphNodeTypeMSFT(_) \
+ _(XR_SPATIAL_GRAPH_NODE_TYPE_STATIC_MSFT, 1) \
+ _(XR_SPATIAL_GRAPH_NODE_TYPE_DYNAMIC_MSFT, 2) \
+ _(XR_SPATIAL_GRAPH_NODE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandEXT(_) \
+ _(XR_HAND_LEFT_EXT, 1) \
+ _(XR_HAND_RIGHT_EXT, 2) \
+ _(XR_HAND_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandJointEXT(_) \
+ _(XR_HAND_JOINT_PALM_EXT, 0) \
+ _(XR_HAND_JOINT_WRIST_EXT, 1) \
+ _(XR_HAND_JOINT_THUMB_METACARPAL_EXT, 2) \
+ _(XR_HAND_JOINT_THUMB_PROXIMAL_EXT, 3) \
+ _(XR_HAND_JOINT_THUMB_DISTAL_EXT, 4) \
+ _(XR_HAND_JOINT_THUMB_TIP_EXT, 5) \
+ _(XR_HAND_JOINT_INDEX_METACARPAL_EXT, 6) \
+ _(XR_HAND_JOINT_INDEX_PROXIMAL_EXT, 7) \
+ _(XR_HAND_JOINT_INDEX_INTERMEDIATE_EXT, 8) \
+ _(XR_HAND_JOINT_INDEX_DISTAL_EXT, 9) \
+ _(XR_HAND_JOINT_INDEX_TIP_EXT, 10) \
+ _(XR_HAND_JOINT_MIDDLE_METACARPAL_EXT, 11) \
+ _(XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT, 12) \
+ _(XR_HAND_JOINT_MIDDLE_INTERMEDIATE_EXT, 13) \
+ _(XR_HAND_JOINT_MIDDLE_DISTAL_EXT, 14) \
+ _(XR_HAND_JOINT_MIDDLE_TIP_EXT, 15) \
+ _(XR_HAND_JOINT_RING_METACARPAL_EXT, 16) \
+ _(XR_HAND_JOINT_RING_PROXIMAL_EXT, 17) \
+ _(XR_HAND_JOINT_RING_INTERMEDIATE_EXT, 18) \
+ _(XR_HAND_JOINT_RING_DISTAL_EXT, 19) \
+ _(XR_HAND_JOINT_RING_TIP_EXT, 20) \
+ _(XR_HAND_JOINT_LITTLE_METACARPAL_EXT, 21) \
+ _(XR_HAND_JOINT_LITTLE_PROXIMAL_EXT, 22) \
+ _(XR_HAND_JOINT_LITTLE_INTERMEDIATE_EXT, 23) \
+ _(XR_HAND_JOINT_LITTLE_DISTAL_EXT, 24) \
+ _(XR_HAND_JOINT_LITTLE_TIP_EXT, 25) \
+ _(XR_HAND_JOINT_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandJointSetEXT(_) \
+ _(XR_HAND_JOINT_SET_DEFAULT_EXT, 0) \
+ _(XR_HAND_JOINT_SET_HAND_WITH_FOREARM_ULTRALEAP, 1000149000) \
+ _(XR_HAND_JOINT_SET_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandPoseTypeMSFT(_) \
+ _(XR_HAND_POSE_TYPE_TRACKED_MSFT, 0) \
+ _(XR_HAND_POSE_TYPE_REFERENCE_OPEN_PALM_MSFT, 1) \
+ _(XR_HAND_POSE_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrReprojectionModeMSFT(_) \
+ _(XR_REPROJECTION_MODE_DEPTH_MSFT, 1) \
+ _(XR_REPROJECTION_MODE_PLANAR_FROM_DEPTH_MSFT, 2) \
+ _(XR_REPROJECTION_MODE_PLANAR_MANUAL_MSFT, 3) \
+ _(XR_REPROJECTION_MODE_ORIENTATION_ONLY_MSFT, 4) \
+ _(XR_REPROJECTION_MODE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandJointsMotionRangeEXT(_) \
+ _(XR_HAND_JOINTS_MOTION_RANGE_UNOBSTRUCTED_EXT, 1) \
+ _(XR_HAND_JOINTS_MOTION_RANGE_CONFORMING_TO_CONTROLLER_EXT, 2) \
+ _(XR_HAND_JOINTS_MOTION_RANGE_MAX_ENUM_EXT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSceneComputeFeatureMSFT(_) \
+ _(XR_SCENE_COMPUTE_FEATURE_PLANE_MSFT, 1) \
+ _(XR_SCENE_COMPUTE_FEATURE_PLANE_MESH_MSFT, 2) \
+ _(XR_SCENE_COMPUTE_FEATURE_VISUAL_MESH_MSFT, 3) \
+ _(XR_SCENE_COMPUTE_FEATURE_COLLIDER_MESH_MSFT, 4) \
+ _(XR_SCENE_COMPUTE_FEATURE_SERIALIZE_SCENE_MSFT, 1000098000) \
+ _(XR_SCENE_COMPUTE_FEATURE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSceneComputeConsistencyMSFT(_) \
+ _(XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_COMPLETE_MSFT, 1) \
+ _(XR_SCENE_COMPUTE_CONSISTENCY_SNAPSHOT_INCOMPLETE_FAST_MSFT, 2) \
+ _(XR_SCENE_COMPUTE_CONSISTENCY_OCCLUSION_OPTIMIZED_MSFT, 3) \
+ _(XR_SCENE_COMPUTE_CONSISTENCY_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrMeshComputeLodMSFT(_) \
+ _(XR_MESH_COMPUTE_LOD_COARSE_MSFT, 1) \
+ _(XR_MESH_COMPUTE_LOD_MEDIUM_MSFT, 2) \
+ _(XR_MESH_COMPUTE_LOD_FINE_MSFT, 3) \
+ _(XR_MESH_COMPUTE_LOD_UNLIMITED_MSFT, 4) \
+ _(XR_MESH_COMPUTE_LOD_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSceneComponentTypeMSFT(_) \
+ _(XR_SCENE_COMPONENT_TYPE_INVALID_MSFT, -1) \
+ _(XR_SCENE_COMPONENT_TYPE_OBJECT_MSFT, 1) \
+ _(XR_SCENE_COMPONENT_TYPE_PLANE_MSFT, 2) \
+ _(XR_SCENE_COMPONENT_TYPE_VISUAL_MESH_MSFT, 3) \
+ _(XR_SCENE_COMPONENT_TYPE_COLLIDER_MESH_MSFT, 4) \
+ _(XR_SCENE_COMPONENT_TYPE_SERIALIZED_SCENE_FRAGMENT_MSFT, 1000098000) \
+ _(XR_SCENE_COMPONENT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSceneObjectTypeMSFT(_) \
+ _(XR_SCENE_OBJECT_TYPE_UNCATEGORIZED_MSFT, -1) \
+ _(XR_SCENE_OBJECT_TYPE_BACKGROUND_MSFT, 1) \
+ _(XR_SCENE_OBJECT_TYPE_WALL_MSFT, 2) \
+ _(XR_SCENE_OBJECT_TYPE_FLOOR_MSFT, 3) \
+ _(XR_SCENE_OBJECT_TYPE_CEILING_MSFT, 4) \
+ _(XR_SCENE_OBJECT_TYPE_PLATFORM_MSFT, 5) \
+ _(XR_SCENE_OBJECT_TYPE_INFERRED_MSFT, 6) \
+ _(XR_SCENE_OBJECT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrScenePlaneAlignmentTypeMSFT(_) \
+ _(XR_SCENE_PLANE_ALIGNMENT_TYPE_NON_ORTHOGONAL_MSFT, 0) \
+ _(XR_SCENE_PLANE_ALIGNMENT_TYPE_HORIZONTAL_MSFT, 1) \
+ _(XR_SCENE_PLANE_ALIGNMENT_TYPE_VERTICAL_MSFT, 2) \
+ _(XR_SCENE_PLANE_ALIGNMENT_TYPE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSceneComputeStateMSFT(_) \
+ _(XR_SCENE_COMPUTE_STATE_NONE_MSFT, 0) \
+ _(XR_SCENE_COMPUTE_STATE_UPDATING_MSFT, 1) \
+ _(XR_SCENE_COMPUTE_STATE_COMPLETED_MSFT, 2) \
+ _(XR_SCENE_COMPUTE_STATE_COMPLETED_WITH_ERROR_MSFT, 3) \
+ _(XR_SCENE_COMPUTE_STATE_MAX_ENUM_MSFT, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrEyeExpressionHTC(_) \
+ _(XR_EYE_EXPRESSION_LEFT_BLINK_HTC, 0) \
+ _(XR_EYE_EXPRESSION_LEFT_WIDE_HTC, 1) \
+ _(XR_EYE_EXPRESSION_RIGHT_BLINK_HTC, 2) \
+ _(XR_EYE_EXPRESSION_RIGHT_WIDE_HTC, 3) \
+ _(XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC, 4) \
+ _(XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC, 5) \
+ _(XR_EYE_EXPRESSION_LEFT_DOWN_HTC, 6) \
+ _(XR_EYE_EXPRESSION_RIGHT_DOWN_HTC, 7) \
+ _(XR_EYE_EXPRESSION_LEFT_OUT_HTC, 8) \
+ _(XR_EYE_EXPRESSION_RIGHT_IN_HTC, 9) \
+ _(XR_EYE_EXPRESSION_LEFT_IN_HTC, 10) \
+ _(XR_EYE_EXPRESSION_RIGHT_OUT_HTC, 11) \
+ _(XR_EYE_EXPRESSION_LEFT_UP_HTC, 12) \
+ _(XR_EYE_EXPRESSION_RIGHT_UP_HTC, 13) \
+ _(XR_EYE_EXPRESSION_MAX_ENUM_HTC, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrLipExpressionHTC(_) \
+ _(XR_LIP_EXPRESSION_JAW_RIGHT_HTC, 0) \
+ _(XR_LIP_EXPRESSION_JAW_LEFT_HTC, 1) \
+ _(XR_LIP_EXPRESSION_JAW_FORWARD_HTC, 2) \
+ _(XR_LIP_EXPRESSION_JAW_OPEN_HTC, 3) \
+ _(XR_LIP_EXPRESSION_MOUTH_APE_SHAPE_HTC, 4) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_RIGHT_HTC, 5) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_LEFT_HTC, 6) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_RIGHT_HTC, 7) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_LEFT_HTC, 8) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_OVERTURN_HTC, 9) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_OVERTURN_HTC, 10) \
+ _(XR_LIP_EXPRESSION_MOUTH_POUT_HTC, 11) \
+ _(XR_LIP_EXPRESSION_MOUTH_SMILE_RIGHT_HTC, 12) \
+ _(XR_LIP_EXPRESSION_MOUTH_SMILE_LEFT_HTC, 13) \
+ _(XR_LIP_EXPRESSION_MOUTH_SAD_RIGHT_HTC, 14) \
+ _(XR_LIP_EXPRESSION_MOUTH_SAD_LEFT_HTC, 15) \
+ _(XR_LIP_EXPRESSION_CHEEK_PUFF_RIGHT_HTC, 16) \
+ _(XR_LIP_EXPRESSION_CHEEK_PUFF_LEFT_HTC, 17) \
+ _(XR_LIP_EXPRESSION_CHEEK_SUCK_HTC, 18) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_UPRIGHT_HTC, 19) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_UPLEFT_HTC, 20) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNRIGHT_HTC, 21) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_DOWNLEFT_HTC, 22) \
+ _(XR_LIP_EXPRESSION_MOUTH_UPPER_INSIDE_HTC, 23) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_INSIDE_HTC, 24) \
+ _(XR_LIP_EXPRESSION_MOUTH_LOWER_OVERLAY_HTC, 25) \
+ _(XR_LIP_EXPRESSION_TONGUE_LONGSTEP1_HTC, 26) \
+ _(XR_LIP_EXPRESSION_TONGUE_LEFT_HTC, 27) \
+ _(XR_LIP_EXPRESSION_TONGUE_RIGHT_HTC, 28) \
+ _(XR_LIP_EXPRESSION_TONGUE_UP_HTC, 29) \
+ _(XR_LIP_EXPRESSION_TONGUE_DOWN_HTC, 30) \
+ _(XR_LIP_EXPRESSION_TONGUE_ROLL_HTC, 31) \
+ _(XR_LIP_EXPRESSION_TONGUE_LONGSTEP2_HTC, 32) \
+ _(XR_LIP_EXPRESSION_TONGUE_UPRIGHT_MORPH_HTC, 33) \
+ _(XR_LIP_EXPRESSION_TONGUE_UPLEFT_MORPH_HTC, 34) \
+ _(XR_LIP_EXPRESSION_TONGUE_DOWNRIGHT_MORPH_HTC, 35) \
+ _(XR_LIP_EXPRESSION_TONGUE_DOWNLEFT_MORPH_HTC, 36) \
+ _(XR_LIP_EXPRESSION_MAX_ENUM_HTC, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFacialTrackingTypeHTC(_) \
+ _(XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC, 1) \
+ _(XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC, 2) \
+ _(XR_FACIAL_TRACKING_TYPE_MAX_ENUM_HTC, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrColorSpaceFB(_) \
+ _(XR_COLOR_SPACE_UNMANAGED_FB, 0) \
+ _(XR_COLOR_SPACE_REC2020_FB, 1) \
+ _(XR_COLOR_SPACE_REC709_FB, 2) \
+ _(XR_COLOR_SPACE_RIFT_CV1_FB, 3) \
+ _(XR_COLOR_SPACE_RIFT_S_FB, 4) \
+ _(XR_COLOR_SPACE_QUEST_FB, 5) \
+ _(XR_COLOR_SPACE_P3_FB, 6) \
+ _(XR_COLOR_SPACE_ADOBE_RGB_FB, 7) \
+ _(XR_COLOR_SPACE_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSpaceComponentTypeFB(_) \
+ _(XR_SPACE_COMPONENT_TYPE_LOCATABLE_FB, 0) \
+ _(XR_SPACE_COMPONENT_TYPE_STORABLE_FB, 1) \
+ _(XR_SPACE_COMPONENT_TYPE_SPACE_CONTAINER_FB, 7) \
+ _(XR_SPACE_COMPONENT_TYPE_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFoveationLevelFB(_) \
+ _(XR_FOVEATION_LEVEL_NONE_FB, 0) \
+ _(XR_FOVEATION_LEVEL_LOW_FB, 1) \
+ _(XR_FOVEATION_LEVEL_MEDIUM_FB, 2) \
+ _(XR_FOVEATION_LEVEL_HIGH_FB, 3) \
+ _(XR_FOVEATION_LEVEL_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrFoveationDynamicFB(_) \
+ _(XR_FOVEATION_DYNAMIC_DISABLED_FB, 0) \
+ _(XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB, 1) \
+ _(XR_FOVEATION_DYNAMIC_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrWindingOrderFB(_) \
+ _(XR_WINDING_ORDER_UNKNOWN_FB, 0) \
+ _(XR_WINDING_ORDER_CW_FB, 1) \
+ _(XR_WINDING_ORDER_CCW_FB, 2) \
+ _(XR_WINDING_ORDER_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPassthroughLayerPurposeFB(_) \
+ _(XR_PASSTHROUGH_LAYER_PURPOSE_RECONSTRUCTION_FB, 0) \
+ _(XR_PASSTHROUGH_LAYER_PURPOSE_PROJECTED_FB, 1) \
+ _(XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_HANDS_FB, 1000203001) \
+ _(XR_PASSTHROUGH_LAYER_PURPOSE_TRACKED_KEYBOARD_MASKED_HANDS_FB, 1000203002) \
+ _(XR_PASSTHROUGH_LAYER_PURPOSE_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrHandForearmJointULTRALEAP(_) \
+ _(XR_HAND_FOREARM_JOINT_PALM_ULTRALEAP, 0) \
+ _(XR_HAND_FOREARM_JOINT_WRIST_ULTRALEAP, 1) \
+ _(XR_HAND_FOREARM_JOINT_THUMB_METACARPAL_ULTRALEAP, 2) \
+ _(XR_HAND_FOREARM_JOINT_THUMB_PROXIMAL_ULTRALEAP, 3) \
+ _(XR_HAND_FOREARM_JOINT_THUMB_DISTAL_ULTRALEAP, 4) \
+ _(XR_HAND_FOREARM_JOINT_THUMB_TIP_ULTRALEAP, 5) \
+ _(XR_HAND_FOREARM_JOINT_INDEX_METACARPAL_ULTRALEAP, 6) \
+ _(XR_HAND_FOREARM_JOINT_INDEX_PROXIMAL_ULTRALEAP, 7) \
+ _(XR_HAND_FOREARM_JOINT_INDEX_INTERMEDIATE_ULTRALEAP, 8) \
+ _(XR_HAND_FOREARM_JOINT_INDEX_DISTAL_ULTRALEAP, 9) \
+ _(XR_HAND_FOREARM_JOINT_INDEX_TIP_ULTRALEAP, 10) \
+ _(XR_HAND_FOREARM_JOINT_MIDDLE_METACARPAL_ULTRALEAP, 11) \
+ _(XR_HAND_FOREARM_JOINT_MIDDLE_PROXIMAL_ULTRALEAP, 12) \
+ _(XR_HAND_FOREARM_JOINT_MIDDLE_INTERMEDIATE_ULTRALEAP, 13) \
+ _(XR_HAND_FOREARM_JOINT_MIDDLE_DISTAL_ULTRALEAP, 14) \
+ _(XR_HAND_FOREARM_JOINT_MIDDLE_TIP_ULTRALEAP, 15) \
+ _(XR_HAND_FOREARM_JOINT_RING_METACARPAL_ULTRALEAP, 16) \
+ _(XR_HAND_FOREARM_JOINT_RING_PROXIMAL_ULTRALEAP, 17) \
+ _(XR_HAND_FOREARM_JOINT_RING_INTERMEDIATE_ULTRALEAP, 18) \
+ _(XR_HAND_FOREARM_JOINT_RING_DISTAL_ULTRALEAP, 19) \
+ _(XR_HAND_FOREARM_JOINT_RING_TIP_ULTRALEAP, 20) \
+ _(XR_HAND_FOREARM_JOINT_LITTLE_METACARPAL_ULTRALEAP, 21) \
+ _(XR_HAND_FOREARM_JOINT_LITTLE_PROXIMAL_ULTRALEAP, 22) \
+ _(XR_HAND_FOREARM_JOINT_LITTLE_INTERMEDIATE_ULTRALEAP, 23) \
+ _(XR_HAND_FOREARM_JOINT_LITTLE_DISTAL_ULTRALEAP, 24) \
+ _(XR_HAND_FOREARM_JOINT_LITTLE_TIP_ULTRALEAP, 25) \
+ _(XR_HAND_FOREARM_JOINT_ELBOW_ULTRALEAP, 26) \
+ _(XR_HAND_FOREARM_JOINT_MAX_ENUM_ULTRALEAP, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSpaceQueryActionFB(_) \
+ _(XR_SPACE_QUERY_ACTION_LOAD_FB, 0) \
+ _(XR_SPACE_QUERY_ACTION_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSpaceStorageLocationFB(_) \
+ _(XR_SPACE_STORAGE_LOCATION_INVALID_FB, 0) \
+ _(XR_SPACE_STORAGE_LOCATION_LOCAL_FB, 1) \
+ _(XR_SPACE_STORAGE_LOCATION_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrSpacePersistenceModeFB(_) \
+ _(XR_SPACE_PERSISTENCE_MODE_INVALID_FB, 0) \
+ _(XR_SPACE_PERSISTENCE_MODE_INDEFINITE_FB, 1) \
+ _(XR_SPACE_PERSISTENCE_MODE_MAX_ENUM_FB, 0x7FFFFFFF)
+
+#define XR_LIST_ENUM_XrPerformanceMetricsCounterUnitMETA(_) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_GENERIC_META, 0) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_PERCENTAGE_META, 1) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_MILLISECONDS_META, 2) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_BYTES_META, 3) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_HERTZ_META, 4) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UNIT_MAX_ENUM_META, 0x7FFFFFFF)
+
+#define XR_LIST_BITS_XrInstanceCreateFlags(_)
+
+#define XR_LIST_BITS_XrSessionCreateFlags(_)
+
+#define XR_LIST_BITS_XrSpaceVelocityFlags(_) \
+ _(XR_SPACE_VELOCITY_LINEAR_VALID_BIT, 0x00000001) \
+ _(XR_SPACE_VELOCITY_ANGULAR_VALID_BIT, 0x00000002) \
+
+#define XR_LIST_BITS_XrSpaceLocationFlags(_) \
+ _(XR_SPACE_LOCATION_ORIENTATION_VALID_BIT, 0x00000001) \
+ _(XR_SPACE_LOCATION_POSITION_VALID_BIT, 0x00000002) \
+ _(XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT, 0x00000004) \
+ _(XR_SPACE_LOCATION_POSITION_TRACKED_BIT, 0x00000008) \
+
+#define XR_LIST_BITS_XrSwapchainCreateFlags(_) \
+ _(XR_SWAPCHAIN_CREATE_PROTECTED_CONTENT_BIT, 0x00000001) \
+ _(XR_SWAPCHAIN_CREATE_STATIC_IMAGE_BIT, 0x00000002) \
+
+#define XR_LIST_BITS_XrSwapchainUsageFlags(_) \
+ _(XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT, 0x00000001) \
+ _(XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0x00000002) \
+ _(XR_SWAPCHAIN_USAGE_UNORDERED_ACCESS_BIT, 0x00000004) \
+ _(XR_SWAPCHAIN_USAGE_TRANSFER_SRC_BIT, 0x00000008) \
+ _(XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT, 0x00000010) \
+ _(XR_SWAPCHAIN_USAGE_SAMPLED_BIT, 0x00000020) \
+ _(XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT, 0x00000040) \
+ _(XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND, 0x00000080) \
+ _(XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_KHR, XR_SWAPCHAIN_USAGE_INPUT_ATTACHMENT_BIT_MND) \
+
+#define XR_LIST_BITS_XrCompositionLayerFlags(_) \
+ _(XR_COMPOSITION_LAYER_CORRECT_CHROMATIC_ABERRATION_BIT, 0x00000001) \
+ _(XR_COMPOSITION_LAYER_BLEND_TEXTURE_SOURCE_ALPHA_BIT, 0x00000002) \
+ _(XR_COMPOSITION_LAYER_UNPREMULTIPLIED_ALPHA_BIT, 0x00000004) \
+
+#define XR_LIST_BITS_XrViewStateFlags(_) \
+ _(XR_VIEW_STATE_ORIENTATION_VALID_BIT, 0x00000001) \
+ _(XR_VIEW_STATE_POSITION_VALID_BIT, 0x00000002) \
+ _(XR_VIEW_STATE_ORIENTATION_TRACKED_BIT, 0x00000004) \
+ _(XR_VIEW_STATE_POSITION_TRACKED_BIT, 0x00000008) \
+
+#define XR_LIST_BITS_XrInputSourceLocalizedNameFlags(_) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT, 0x00000001) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT, 0x00000002) \
+ _(XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT, 0x00000004) \
+
+#define XR_LIST_BITS_XrVulkanInstanceCreateFlagsKHR(_)
+
+#define XR_LIST_BITS_XrVulkanDeviceCreateFlagsKHR(_)
+
+#define XR_LIST_BITS_XrDebugUtilsMessageSeverityFlagsEXT(_) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT, 0x00000001) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT, 0x00000010) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT, 0x00000100) \
+ _(XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, 0x00001000) \
+
+#define XR_LIST_BITS_XrDebugUtilsMessageTypeFlagsEXT(_) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, 0x00000001) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT, 0x00000002) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, 0x00000004) \
+ _(XR_DEBUG_UTILS_MESSAGE_TYPE_CONFORMANCE_BIT_EXT, 0x00000008) \
+
+#define XR_LIST_BITS_XrOverlaySessionCreateFlagsEXTX(_)
+
+#define XR_LIST_BITS_XrOverlayMainSessionFlagsEXTX(_) \
+ _(XR_OVERLAY_MAIN_SESSION_ENABLED_COMPOSITION_LAYER_INFO_DEPTH_BIT_EXTX, 0x00000001) \
+
+#define XR_LIST_BITS_XrCompositionLayerImageLayoutFlagsFB(_) \
+ _(XR_COMPOSITION_LAYER_IMAGE_LAYOUT_VERTICAL_FLIP_BIT_FB, 0x00000001) \
+
+#define XR_LIST_BITS_XrAndroidSurfaceSwapchainFlagsFB(_) \
+ _(XR_ANDROID_SURFACE_SWAPCHAIN_SYNCHRONOUS_BIT_FB, 0x00000001) \
+ _(XR_ANDROID_SURFACE_SWAPCHAIN_USE_TIMESTAMPS_BIT_FB, 0x00000002) \
+
+#define XR_LIST_BITS_XrCompositionLayerSecureContentFlagsFB(_) \
+ _(XR_COMPOSITION_LAYER_SECURE_CONTENT_EXCLUDE_LAYER_BIT_FB, 0x00000001) \
+ _(XR_COMPOSITION_LAYER_SECURE_CONTENT_REPLACE_LAYER_BIT_FB, 0x00000002) \
+
+#define XR_LIST_BITS_XrHandTrackingAimFlagsFB(_) \
+ _(XR_HAND_TRACKING_AIM_COMPUTED_BIT_FB, 0x00000001) \
+ _(XR_HAND_TRACKING_AIM_VALID_BIT_FB, 0x00000002) \
+ _(XR_HAND_TRACKING_AIM_INDEX_PINCHING_BIT_FB, 0x00000004) \
+ _(XR_HAND_TRACKING_AIM_MIDDLE_PINCHING_BIT_FB, 0x00000008) \
+ _(XR_HAND_TRACKING_AIM_RING_PINCHING_BIT_FB, 0x00000010) \
+ _(XR_HAND_TRACKING_AIM_LITTLE_PINCHING_BIT_FB, 0x00000020) \
+ _(XR_HAND_TRACKING_AIM_SYSTEM_GESTURE_BIT_FB, 0x00000040) \
+ _(XR_HAND_TRACKING_AIM_DOMINANT_HAND_BIT_FB, 0x00000080) \
+ _(XR_HAND_TRACKING_AIM_MENU_PRESSED_BIT_FB, 0x00000100) \
+
+#define XR_LIST_BITS_XrSwapchainCreateFoveationFlagsFB(_) \
+ _(XR_SWAPCHAIN_CREATE_FOVEATION_SCALED_BIN_BIT_FB, 0x00000001) \
+ _(XR_SWAPCHAIN_CREATE_FOVEATION_FRAGMENT_DENSITY_MAP_BIT_FB, 0x00000002) \
+
+#define XR_LIST_BITS_XrSwapchainStateFoveationFlagsFB(_)
+
+#define XR_LIST_BITS_XrKeyboardTrackingFlagsFB(_) \
+ _(XR_KEYBOARD_TRACKING_EXISTS_BIT_FB, 0x00000001) \
+ _(XR_KEYBOARD_TRACKING_LOCAL_BIT_FB, 0x00000002) \
+ _(XR_KEYBOARD_TRACKING_REMOTE_BIT_FB, 0x00000004) \
+ _(XR_KEYBOARD_TRACKING_CONNECTED_BIT_FB, 0x00000008) \
+
+#define XR_LIST_BITS_XrKeyboardTrackingQueryFlagsFB(_) \
+ _(XR_KEYBOARD_TRACKING_QUERY_LOCAL_BIT_FB, 0x00000002) \
+ _(XR_KEYBOARD_TRACKING_QUERY_REMOTE_BIT_FB, 0x00000004) \
+
+#define XR_LIST_BITS_XrTriangleMeshFlagsFB(_) \
+ _(XR_TRIANGLE_MESH_MUTABLE_BIT_FB, 0x00000001) \
+
+#define XR_LIST_BITS_XrPassthroughFlagsFB(_) \
+ _(XR_PASSTHROUGH_IS_RUNNING_AT_CREATION_BIT_FB, 0x00000001) \
+
+#define XR_LIST_BITS_XrPassthroughStateChangedFlagsFB(_) \
+ _(XR_PASSTHROUGH_STATE_CHANGED_REINIT_REQUIRED_BIT_FB, 0x00000001) \
+ _(XR_PASSTHROUGH_STATE_CHANGED_NON_RECOVERABLE_ERROR_BIT_FB, 0x00000002) \
+ _(XR_PASSTHROUGH_STATE_CHANGED_RECOVERABLE_ERROR_BIT_FB, 0x00000004) \
+ _(XR_PASSTHROUGH_STATE_CHANGED_RESTORED_ERROR_BIT_FB, 0x00000008) \
+
+#define XR_LIST_BITS_XrRenderModelFlagsFB(_) \
+ _(XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_1_BIT_FB, 0x00000001) \
+ _(XR_RENDER_MODEL_SUPPORTS_GLTF_2_0_SUBSET_2_BIT_FB, 0x00000002) \
+
+#define XR_LIST_BITS_XrCompositionLayerSpaceWarpInfoFlagsFB(_) \
+ _(XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0x00000001) \
+
+#define XR_LIST_BITS_XrDigitalLensControlFlagsALMALENCE(_) \
+ _(XR_DIGITAL_LENS_CONTROL_PROCESSING_DISABLE_BIT_ALMALENCE, 0x00000001) \
+
+#define XR_LIST_BITS_XrCompositionLayerSettingsFlagsFB(_) \
+ _(XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SUPER_SAMPLING_BIT_FB, 0x00000001) \
+ _(XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SUPER_SAMPLING_BIT_FB, 0x00000002) \
+ _(XR_COMPOSITION_LAYER_SETTINGS_NORMAL_SHARPENING_BIT_FB, 0x00000004) \
+ _(XR_COMPOSITION_LAYER_SETTINGS_QUALITY_SHARPENING_BIT_FB, 0x00000008) \
+
+#define XR_LIST_BITS_XrPerformanceMetricsCounterFlagsMETA(_) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_ANY_VALUE_VALID_BIT_META, 0x00000001) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_UINT_VALUE_VALID_BIT_META, 0x00000002) \
+ _(XR_PERFORMANCE_METRICS_COUNTER_FLOAT_VALUE_VALID_BIT_META, 0x00000004) \
+
+#define XR_LIST_STRUCT_XrApiLayerProperties(_) \
+ _(type) \
+ _(next) \
+ _(layerName) \
+ _(specVersion) \
+ _(layerVersion) \
+ _(description) \
+
+#define XR_LIST_STRUCT_XrExtensionProperties(_) \
+ _(type) \
+ _(next) \
+ _(extensionName) \
+ _(extensionVersion) \
+
+#define XR_LIST_STRUCT_XrApplicationInfo(_) \
+ _(applicationName) \
+ _(applicationVersion) \
+ _(engineName) \
+ _(engineVersion) \
+ _(apiVersion) \
+
+#define XR_LIST_STRUCT_XrInstanceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(applicationInfo) \
+ _(enabledApiLayerCount) \
+ _(enabledApiLayerNames) \
+ _(enabledExtensionCount) \
+ _(enabledExtensionNames) \
+
+#define XR_LIST_STRUCT_XrInstanceProperties(_) \
+ _(type) \
+ _(next) \
+ _(runtimeVersion) \
+ _(runtimeName) \
+
+#define XR_LIST_STRUCT_XrEventDataBuffer(_) \
+ _(type) \
+ _(next) \
+ _(varying) \
+
+#define XR_LIST_STRUCT_XrSystemGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(formFactor) \
+
+#define XR_LIST_STRUCT_XrSystemGraphicsProperties(_) \
+ _(maxSwapchainImageHeight) \
+ _(maxSwapchainImageWidth) \
+ _(maxLayerCount) \
+
+#define XR_LIST_STRUCT_XrSystemTrackingProperties(_) \
+ _(orientationTracking) \
+ _(positionTracking) \
+
+#define XR_LIST_STRUCT_XrSystemProperties(_) \
+ _(type) \
+ _(next) \
+ _(systemId) \
+ _(vendorId) \
+ _(systemName) \
+ _(graphicsProperties) \
+ _(trackingProperties) \
+
+#define XR_LIST_STRUCT_XrSessionCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(systemId) \
+
+#define XR_LIST_STRUCT_XrVector3f(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+
+#define XR_LIST_STRUCT_XrSpaceVelocity(_) \
+ _(type) \
+ _(next) \
+ _(velocityFlags) \
+ _(linearVelocity) \
+ _(angularVelocity) \
+
+#define XR_LIST_STRUCT_XrQuaternionf(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+ _(w) \
+
+#define XR_LIST_STRUCT_XrPosef(_) \
+ _(orientation) \
+ _(position) \
+
+#define XR_LIST_STRUCT_XrReferenceSpaceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(referenceSpaceType) \
+ _(poseInReferenceSpace) \
+
+#define XR_LIST_STRUCT_XrExtent2Df(_) \
+ _(width) \
+ _(height) \
+
+#define XR_LIST_STRUCT_XrActionSpaceCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath) \
+ _(poseInActionSpace) \
+
+#define XR_LIST_STRUCT_XrSpaceLocation(_) \
+ _(type) \
+ _(next) \
+ _(locationFlags) \
+ _(pose) \
+
+#define XR_LIST_STRUCT_XrViewConfigurationProperties(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(fovMutable) \
+
+#define XR_LIST_STRUCT_XrViewConfigurationView(_) \
+ _(type) \
+ _(next) \
+ _(recommendedImageRectWidth) \
+ _(maxImageRectWidth) \
+ _(recommendedImageRectHeight) \
+ _(maxImageRectHeight) \
+ _(recommendedSwapchainSampleCount) \
+ _(maxSwapchainSampleCount) \
+
+#define XR_LIST_STRUCT_XrSwapchainCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(usageFlags) \
+ _(format) \
+ _(sampleCount) \
+ _(width) \
+ _(height) \
+ _(faceCount) \
+ _(arraySize) \
+ _(mipCount) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageBaseHeader(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageAcquireInfo(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageWaitInfo(_) \
+ _(type) \
+ _(next) \
+ _(timeout) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageReleaseInfo(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSessionBeginInfo(_) \
+ _(type) \
+ _(next) \
+ _(primaryViewConfigurationType) \
+
+#define XR_LIST_STRUCT_XrFrameWaitInfo(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrFrameState(_) \
+ _(type) \
+ _(next) \
+ _(predictedDisplayTime) \
+ _(predictedDisplayPeriod) \
+ _(shouldRender) \
+
+#define XR_LIST_STRUCT_XrFrameBeginInfo(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerBaseHeader(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+
+#define XR_LIST_STRUCT_XrFrameEndInfo(_) \
+ _(type) \
+ _(next) \
+ _(displayTime) \
+ _(environmentBlendMode) \
+ _(layerCount) \
+ _(layers) \
+
+#define XR_LIST_STRUCT_XrViewLocateInfo(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(displayTime) \
+ _(space) \
+
+#define XR_LIST_STRUCT_XrViewState(_) \
+ _(type) \
+ _(next) \
+ _(viewStateFlags) \
+
+#define XR_LIST_STRUCT_XrFovf(_) \
+ _(angleLeft) \
+ _(angleRight) \
+ _(angleUp) \
+ _(angleDown) \
+
+#define XR_LIST_STRUCT_XrView(_) \
+ _(type) \
+ _(next) \
+ _(pose) \
+ _(fov) \
+
+#define XR_LIST_STRUCT_XrActionSetCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(actionSetName) \
+ _(localizedActionSetName) \
+ _(priority) \
+
+#define XR_LIST_STRUCT_XrActionCreateInfo(_) \
+ _(type) \
+ _(next) \
+ _(actionName) \
+ _(actionType) \
+ _(countSubactionPaths) \
+ _(subactionPaths) \
+ _(localizedActionName) \
+
+#define XR_LIST_STRUCT_XrActionSuggestedBinding(_) \
+ _(action) \
+ _(binding) \
+
+#define XR_LIST_STRUCT_XrInteractionProfileSuggestedBinding(_) \
+ _(type) \
+ _(next) \
+ _(interactionProfile) \
+ _(countSuggestedBindings) \
+ _(suggestedBindings) \
+
+#define XR_LIST_STRUCT_XrSessionActionSetsAttachInfo(_) \
+ _(type) \
+ _(next) \
+ _(countActionSets) \
+ _(actionSets) \
+
+#define XR_LIST_STRUCT_XrInteractionProfileState(_) \
+ _(type) \
+ _(next) \
+ _(interactionProfile) \
+
+#define XR_LIST_STRUCT_XrActionStateGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath) \
+
+#define XR_LIST_STRUCT_XrActionStateBoolean(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive) \
+
+#define XR_LIST_STRUCT_XrActionStateFloat(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive) \
+
+#define XR_LIST_STRUCT_XrVector2f(_) \
+ _(x) \
+ _(y) \
+
+#define XR_LIST_STRUCT_XrActionStateVector2f(_) \
+ _(type) \
+ _(next) \
+ _(currentState) \
+ _(changedSinceLastSync) \
+ _(lastChangeTime) \
+ _(isActive) \
+
+#define XR_LIST_STRUCT_XrActionStatePose(_) \
+ _(type) \
+ _(next) \
+ _(isActive) \
+
+#define XR_LIST_STRUCT_XrActiveActionSet(_) \
+ _(actionSet) \
+ _(subactionPath) \
+
+#define XR_LIST_STRUCT_XrActionsSyncInfo(_) \
+ _(type) \
+ _(next) \
+ _(countActiveActionSets) \
+ _(activeActionSets) \
+
+#define XR_LIST_STRUCT_XrBoundSourcesForActionEnumerateInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+
+#define XR_LIST_STRUCT_XrInputSourceLocalizedNameGetInfo(_) \
+ _(type) \
+ _(next) \
+ _(sourcePath) \
+ _(whichComponents) \
+
+#define XR_LIST_STRUCT_XrHapticActionInfo(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(subactionPath) \
+
+#define XR_LIST_STRUCT_XrHapticBaseHeader(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrBaseInStructure(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrBaseOutStructure(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrOffset2Di(_) \
+ _(x) \
+ _(y) \
+
+#define XR_LIST_STRUCT_XrExtent2Di(_) \
+ _(width) \
+ _(height) \
+
+#define XR_LIST_STRUCT_XrRect2Di(_) \
+ _(offset) \
+ _(extent) \
+
+#define XR_LIST_STRUCT_XrSwapchainSubImage(_) \
+ _(swapchain) \
+ _(imageRect) \
+ _(imageArrayIndex) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerProjectionView(_) \
+ _(type) \
+ _(next) \
+ _(pose) \
+ _(fov) \
+ _(subImage) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerProjection(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(viewCount) \
+ _(views) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerQuad(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(size) \
+
+#define XR_LIST_STRUCT_XrEventDataBaseHeader(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrEventDataEventsLost(_) \
+ _(type) \
+ _(next) \
+ _(lostEventCount) \
+
+#define XR_LIST_STRUCT_XrEventDataInstanceLossPending(_) \
+ _(type) \
+ _(next) \
+ _(lossTime) \
+
+#define XR_LIST_STRUCT_XrEventDataSessionStateChanged(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(state) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrEventDataReferenceSpaceChangePending(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(referenceSpaceType) \
+ _(changeTime) \
+ _(poseValid) \
+ _(poseInPreviousSpace) \
+
+#define XR_LIST_STRUCT_XrEventDataInteractionProfileChanged(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+
+#define XR_LIST_STRUCT_XrHapticVibration(_) \
+ _(type) \
+ _(next) \
+ _(duration) \
+ _(frequency) \
+ _(amplitude) \
+
+#define XR_LIST_STRUCT_XrOffset2Df(_) \
+ _(x) \
+ _(y) \
+
+#define XR_LIST_STRUCT_XrRect2Df(_) \
+ _(offset) \
+ _(extent) \
+
+#define XR_LIST_STRUCT_XrVector4f(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+ _(w) \
+
+#define XR_LIST_STRUCT_XrColor4f(_) \
+ _(r) \
+ _(g) \
+ _(b) \
+ _(a) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerCubeKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(swapchain) \
+ _(imageArrayIndex) \
+ _(orientation) \
+
+#define XR_LIST_STRUCT_XrInstanceCreateInfoAndroidKHR(_) \
+ _(type) \
+ _(next) \
+ _(applicationVM) \
+ _(applicationActivity) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerDepthInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(subImage) \
+ _(minDepth) \
+ _(maxDepth) \
+ _(nearZ) \
+ _(farZ) \
+
+#define XR_LIST_STRUCT_XrVulkanSwapchainFormatListCreateInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(viewFormatCount) \
+ _(viewFormats) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerCylinderKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(radius) \
+ _(centralAngle) \
+ _(aspectRatio) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerEquirectKHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(radius) \
+ _(scale) \
+ _(bias) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWin32KHR(_) \
+ _(type) \
+ _(next) \
+ _(hDC) \
+ _(hGLRC) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXlibKHR(_) \
+ _(type) \
+ _(next) \
+ _(xDisplay) \
+ _(visualid) \
+ _(glxFBConfig) \
+ _(glxDrawable) \
+ _(glxContext) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLXcbKHR(_) \
+ _(type) \
+ _(next) \
+ _(connection) \
+ _(screenNumber) \
+ _(fbconfigid) \
+ _(visualid) \
+ _(glxDrawable) \
+ _(glxContext) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLWaylandKHR(_) \
+ _(type) \
+ _(next) \
+ _(display) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageOpenGLKHR(_) \
+ _(type) \
+ _(next) \
+ _(image) \
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingOpenGLESAndroidKHR(_) \
+ _(type) \
+ _(next) \
+ _(display) \
+ _(config) \
+ _(context) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageOpenGLESKHR(_) \
+ _(type) \
+ _(next) \
+ _(image) \
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsOpenGLESKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(instance) \
+ _(physicalDevice) \
+ _(device) \
+ _(queueFamilyIndex) \
+ _(queueIndex) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(image) \
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsVulkanKHR(_) \
+ _(type) \
+ _(next) \
+ _(minApiVersionSupported) \
+ _(maxApiVersionSupported) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(device) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(texture) \
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D11KHR(_) \
+ _(type) \
+ _(next) \
+ _(adapterLuid) \
+ _(minFeatureLevel) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(device) \
+ _(queue) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(texture) \
+
+#define XR_LIST_STRUCT_XrGraphicsRequirementsD3D12KHR(_) \
+ _(type) \
+ _(next) \
+ _(adapterLuid) \
+ _(minFeatureLevel) \
+
+#define XR_LIST_STRUCT_XrVisibilityMaskKHR(_) \
+ _(type) \
+ _(next) \
+ _(vertexCapacityInput) \
+ _(vertexCountOutput) \
+ _(vertices) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices) \
+
+#define XR_LIST_STRUCT_XrEventDataVisibilityMaskChangedKHR(_) \
+ _(type) \
+ _(next) \
+ _(session) \
+ _(viewConfigurationType) \
+ _(viewIndex) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerColorScaleBiasKHR(_) \
+ _(type) \
+ _(next) \
+ _(colorScale) \
+ _(colorBias) \
+
+#define XR_LIST_STRUCT_XrLoaderInitInfoBaseHeaderKHR(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrLoaderInitInfoAndroidKHR(_) \
+ _(type) \
+ _(next) \
+ _(applicationVM) \
+ _(applicationContext) \
+
+#define XR_LIST_STRUCT_XrVulkanInstanceCreateInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(systemId) \
+ _(createFlags) \
+ _(pfnGetInstanceProcAddr) \
+ _(vulkanCreateInfo) \
+ _(vulkanAllocator) \
+
+#define XR_LIST_STRUCT_XrVulkanDeviceCreateInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(systemId) \
+ _(createFlags) \
+ _(pfnGetInstanceProcAddr) \
+ _(vulkanPhysicalDevice) \
+ _(vulkanCreateInfo) \
+ _(vulkanAllocator) \
+
+#define XR_LIST_STRUCT_XrVulkanGraphicsDeviceGetInfoKHR(_) \
+ _(type) \
+ _(next) \
+ _(systemId) \
+ _(vulkanInstance) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerEquirect2KHR(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(space) \
+ _(eyeVisibility) \
+ _(subImage) \
+ _(pose) \
+ _(radius) \
+ _(centralHorizontalAngle) \
+ _(upperVerticalAngle) \
+ _(lowerVerticalAngle) \
+
+#define XR_LIST_STRUCT_XrBindingModificationBaseHeaderKHR(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrBindingModificationsKHR(_) \
+ _(type) \
+ _(next) \
+ _(bindingModificationCount) \
+ _(bindingModifications) \
+
+#define XR_LIST_STRUCT_XrEventDataPerfSettingsEXT(_) \
+ _(type) \
+ _(next) \
+ _(domain) \
+ _(subDomain) \
+ _(fromLevel) \
+ _(toLevel) \
+
+#define XR_LIST_STRUCT_XrDebugUtilsObjectNameInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(objectType) \
+ _(objectHandle) \
+ _(objectName) \
+
+#define XR_LIST_STRUCT_XrDebugUtilsLabelEXT(_) \
+ _(type) \
+ _(next) \
+ _(labelName) \
+
+#define XR_LIST_STRUCT_XrDebugUtilsMessengerCallbackDataEXT(_) \
+ _(type) \
+ _(next) \
+ _(messageId) \
+ _(functionName) \
+ _(message) \
+ _(objectCount) \
+ _(objects) \
+ _(sessionLabelCount) \
+ _(sessionLabels) \
+
+#define XR_LIST_STRUCT_XrDebugUtilsMessengerCreateInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(messageSeverities) \
+ _(messageTypes) \
+ _(userCallback) \
+ _(userData) \
+
+#define XR_LIST_STRUCT_XrSystemEyeGazeInteractionPropertiesEXT(_) \
+ _(type) \
+ _(next) \
+ _(supportsEyeGazeInteraction) \
+
+#define XR_LIST_STRUCT_XrEyeGazeSampleTimeEXT(_) \
+ _(type) \
+ _(next) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrSessionCreateInfoOverlayEXTX(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+ _(sessionLayersPlacement) \
+
+#define XR_LIST_STRUCT_XrEventDataMainSessionVisibilityChangedEXTX(_) \
+ _(type) \
+ _(next) \
+ _(visible) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(space) \
+ _(pose) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorSpaceCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(anchor) \
+ _(poseInAnchorSpace) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerImageLayoutFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerAlphaBlendFB(_) \
+ _(type) \
+ _(next) \
+ _(srcFactorColor) \
+ _(dstFactorColor) \
+ _(srcFactorAlpha) \
+ _(dstFactorAlpha) \
+
+#define XR_LIST_STRUCT_XrViewConfigurationDepthRangeEXT(_) \
+ _(type) \
+ _(next) \
+ _(recommendedNearZ) \
+ _(minNearZ) \
+ _(recommendedFarZ) \
+ _(maxFarZ) \
+
+#define XR_LIST_STRUCT_XrGraphicsBindingEGLMNDX(_) \
+ _(type) \
+ _(next) \
+ _(getProcAddress) \
+ _(display) \
+ _(config) \
+ _(context) \
+
+#define XR_LIST_STRUCT_XrSpatialGraphNodeSpaceCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(nodeType) \
+ _(nodeId) \
+ _(pose) \
+
+#define XR_LIST_STRUCT_XrSpatialGraphStaticNodeBindingCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(space) \
+ _(poseInSpace) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesGetInfoMSFT(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSpatialGraphNodeBindingPropertiesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(nodeId) \
+ _(poseInNodeSpace) \
+
+#define XR_LIST_STRUCT_XrSystemHandTrackingPropertiesEXT(_) \
+ _(type) \
+ _(next) \
+ _(supportsHandTracking) \
+
+#define XR_LIST_STRUCT_XrHandTrackerCreateInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(hand) \
+ _(handJointSet) \
+
+#define XR_LIST_STRUCT_XrHandJointsLocateInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(baseSpace) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrHandJointLocationEXT(_) \
+ _(locationFlags) \
+ _(pose) \
+ _(radius) \
+
+#define XR_LIST_STRUCT_XrHandJointVelocityEXT(_) \
+ _(velocityFlags) \
+ _(linearVelocity) \
+ _(angularVelocity) \
+
+#define XR_LIST_STRUCT_XrHandJointLocationsEXT(_) \
+ _(type) \
+ _(next) \
+ _(isActive) \
+ _(jointCount) \
+ _(jointLocations) \
+
+#define XR_LIST_STRUCT_XrHandJointVelocitiesEXT(_) \
+ _(type) \
+ _(next) \
+ _(jointCount) \
+ _(jointVelocities) \
+
+#define XR_LIST_STRUCT_XrSystemHandTrackingMeshPropertiesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(supportsHandTrackingMesh) \
+ _(maxHandMeshIndexCount) \
+ _(maxHandMeshVertexCount) \
+
+#define XR_LIST_STRUCT_XrHandMeshSpaceCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(handPoseType) \
+ _(poseInHandMeshSpace) \
+
+#define XR_LIST_STRUCT_XrHandMeshUpdateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(time) \
+ _(handPoseType) \
+
+#define XR_LIST_STRUCT_XrHandMeshIndexBufferMSFT(_) \
+ _(indexBufferKey) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices) \
+
+#define XR_LIST_STRUCT_XrHandMeshVertexMSFT(_) \
+ _(position) \
+ _(normal) \
+
+#define XR_LIST_STRUCT_XrHandMeshVertexBufferMSFT(_) \
+ _(vertexUpdateTime) \
+ _(vertexCapacityInput) \
+ _(vertexCountOutput) \
+ _(vertices) \
+
+#define XR_LIST_STRUCT_XrHandMeshMSFT(_) \
+ _(type) \
+ _(next) \
+ _(isActive) \
+ _(indexBufferChanged) \
+ _(vertexBufferChanged) \
+ _(indexBuffer) \
+ _(vertexBuffer) \
+
+#define XR_LIST_STRUCT_XrHandPoseTypeInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(handPoseType) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSessionBeginInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationCount) \
+ _(enabledViewConfigurationTypes) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationStateMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(active) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameStateMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationCount) \
+ _(viewConfigurationStates) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationLayerInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+ _(environmentBlendMode) \
+ _(layerCount) \
+ _(layers) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationFrameEndInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationCount) \
+ _(viewConfigurationLayersInfo) \
+
+#define XR_LIST_STRUCT_XrSecondaryViewConfigurationSwapchainCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(viewConfigurationType) \
+
+#define XR_LIST_STRUCT_XrControllerModelKeyStateMSFT(_) \
+ _(type) \
+ _(next) \
+ _(modelKey) \
+
+#define XR_LIST_STRUCT_XrControllerModelNodePropertiesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(parentNodeName) \
+ _(nodeName) \
+
+#define XR_LIST_STRUCT_XrControllerModelPropertiesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(nodeCapacityInput) \
+ _(nodeCountOutput) \
+ _(nodeProperties) \
+
+#define XR_LIST_STRUCT_XrControllerModelNodeStateMSFT(_) \
+ _(type) \
+ _(next) \
+ _(nodePose) \
+
+#define XR_LIST_STRUCT_XrControllerModelStateMSFT(_) \
+ _(type) \
+ _(next) \
+ _(nodeCapacityInput) \
+ _(nodeCountOutput) \
+ _(nodeStates) \
+
+#define XR_LIST_STRUCT_XrViewConfigurationViewFovEPIC(_) \
+ _(type) \
+ _(next) \
+ _(recommendedFov) \
+ _(maxMutableFov) \
+
+#define XR_LIST_STRUCT_XrHolographicWindowAttachmentMSFT(_) \
+ _(type) \
+ _(next) \
+ _(holographicSpace) \
+ _(coreWindow) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerReprojectionInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(reprojectionMode) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerReprojectionPlaneOverrideMSFT(_) \
+ _(type) \
+ _(next) \
+ _(position) \
+ _(normal) \
+ _(velocity) \
+
+#define XR_LIST_STRUCT_XrAndroidSurfaceSwapchainCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(createFlags) \
+
+#define XR_LIST_STRUCT_XrSwapchainStateBaseHeaderFB(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerSecureContentFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrInteractionProfileDpadBindingEXT(_) \
+ _(type) \
+ _(next) \
+ _(binding) \
+ _(actionSet) \
+ _(forceThreshold) \
+ _(forceThresholdReleased) \
+ _(centerRegion) \
+ _(wedgeAngle) \
+ _(isSticky) \
+ _(onHaptic) \
+ _(offHaptic) \
+
+#define XR_LIST_STRUCT_XrInteractionProfileAnalogThresholdVALVE(_) \
+ _(type) \
+ _(next) \
+ _(action) \
+ _(binding) \
+ _(onThreshold) \
+ _(offThreshold) \
+ _(onHaptic) \
+ _(offHaptic) \
+
+#define XR_LIST_STRUCT_XrHandJointsMotionRangeInfoEXT(_) \
+ _(type) \
+ _(next) \
+ _(handJointsMotionRange) \
+
+#define XR_LIST_STRUCT_XrUuidMSFT(_) \
+ _(bytes) \
+
+#define XR_LIST_STRUCT_XrSceneObserverCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSceneCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSceneSphereBoundMSFT(_) \
+ _(center) \
+ _(radius) \
+
+#define XR_LIST_STRUCT_XrSceneOrientedBoxBoundMSFT(_) \
+ _(pose) \
+ _(extents) \
+
+#define XR_LIST_STRUCT_XrSceneFrustumBoundMSFT(_) \
+ _(pose) \
+ _(fov) \
+ _(farDistance) \
+
+#define XR_LIST_STRUCT_XrSceneBoundsMSFT(_) \
+ _(space) \
+ _(time) \
+ _(sphereCount) \
+ _(spheres) \
+ _(boxCount) \
+ _(boxes) \
+ _(frustumCount) \
+ _(frustums) \
+
+#define XR_LIST_STRUCT_XrNewSceneComputeInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(requestedFeatureCount) \
+ _(requestedFeatures) \
+ _(consistency) \
+ _(bounds) \
+
+#define XR_LIST_STRUCT_XrVisualMeshComputeLodInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(lod) \
+
+#define XR_LIST_STRUCT_XrSceneComponentMSFT(_) \
+ _(componentType) \
+ _(id) \
+ _(parentId) \
+ _(updateTime) \
+
+#define XR_LIST_STRUCT_XrSceneComponentsMSFT(_) \
+ _(type) \
+ _(next) \
+ _(componentCapacityInput) \
+ _(componentCountOutput) \
+ _(components) \
+
+#define XR_LIST_STRUCT_XrSceneComponentsGetInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(componentType) \
+
+#define XR_LIST_STRUCT_XrSceneComponentLocationMSFT(_) \
+ _(flags) \
+ _(pose) \
+
+#define XR_LIST_STRUCT_XrSceneComponentLocationsMSFT(_) \
+ _(type) \
+ _(next) \
+ _(locationCount) \
+ _(locations) \
+
+#define XR_LIST_STRUCT_XrSceneComponentsLocateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(baseSpace) \
+ _(time) \
+ _(componentIdCount) \
+ _(componentIds) \
+
+#define XR_LIST_STRUCT_XrSceneObjectMSFT(_) \
+ _(objectType) \
+
+#define XR_LIST_STRUCT_XrSceneObjectsMSFT(_) \
+ _(type) \
+ _(next) \
+ _(sceneObjectCount) \
+ _(sceneObjects) \
+
+#define XR_LIST_STRUCT_XrSceneComponentParentFilterInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(parentId) \
+
+#define XR_LIST_STRUCT_XrSceneObjectTypesFilterInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(objectTypeCount) \
+ _(objectTypes) \
+
+#define XR_LIST_STRUCT_XrScenePlaneMSFT(_) \
+ _(alignment) \
+ _(size) \
+ _(meshBufferId) \
+ _(supportsIndicesUint16) \
+
+#define XR_LIST_STRUCT_XrScenePlanesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(scenePlaneCount) \
+ _(scenePlanes) \
+
+#define XR_LIST_STRUCT_XrScenePlaneAlignmentFilterInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(alignmentCount) \
+ _(alignments) \
+
+#define XR_LIST_STRUCT_XrSceneMeshMSFT(_) \
+ _(meshBufferId) \
+ _(supportsIndicesUint16) \
+
+#define XR_LIST_STRUCT_XrSceneMeshesMSFT(_) \
+ _(type) \
+ _(next) \
+ _(sceneMeshCount) \
+ _(sceneMeshes) \
+
+#define XR_LIST_STRUCT_XrSceneMeshBuffersGetInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(meshBufferId) \
+
+#define XR_LIST_STRUCT_XrSceneMeshBuffersMSFT(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSceneMeshVertexBufferMSFT(_) \
+ _(type) \
+ _(next) \
+ _(vertexCapacityInput) \
+ _(vertexCountOutput) \
+ _(vertices) \
+
+#define XR_LIST_STRUCT_XrSceneMeshIndicesUint32MSFT(_) \
+ _(type) \
+ _(next) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices) \
+
+#define XR_LIST_STRUCT_XrSceneMeshIndicesUint16MSFT(_) \
+ _(type) \
+ _(next) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices) \
+
+#define XR_LIST_STRUCT_XrSerializedSceneFragmentDataGetInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(sceneFragmentId) \
+
+#define XR_LIST_STRUCT_XrDeserializeSceneFragmentMSFT(_) \
+ _(bufferSize) \
+ _(buffer) \
+
+#define XR_LIST_STRUCT_XrSceneDeserializeInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(fragmentCount) \
+ _(fragments) \
+
+#define XR_LIST_STRUCT_XrEventDataDisplayRefreshRateChangedFB(_) \
+ _(type) \
+ _(next) \
+ _(fromDisplayRefreshRate) \
+ _(toDisplayRefreshRate) \
+
+#define XR_LIST_STRUCT_XrViveTrackerPathsHTCX(_) \
+ _(type) \
+ _(next) \
+ _(persistentPath) \
+ _(rolePath) \
+
+#define XR_LIST_STRUCT_XrEventDataViveTrackerConnectedHTCX(_) \
+ _(type) \
+ _(next) \
+ _(paths) \
+
+#define XR_LIST_STRUCT_XrSystemFacialTrackingPropertiesHTC(_) \
+ _(type) \
+ _(next) \
+ _(supportEyeFacialTracking) \
+ _(supportLipFacialTracking) \
+
+#define XR_LIST_STRUCT_XrFacialExpressionsHTC(_) \
+ _(type) \
+ _(next) \
+ _(isActive) \
+ _(sampleTime) \
+ _(expressionCount) \
+ _(expressionWeightings) \
+
+#define XR_LIST_STRUCT_XrFacialTrackerCreateInfoHTC(_) \
+ _(type) \
+ _(next) \
+ _(facialTrackingType) \
+
+#define XR_LIST_STRUCT_XrSystemColorSpacePropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(colorSpace) \
+
+#define XR_LIST_STRUCT_XrVector4sFB(_) \
+ _(x) \
+ _(y) \
+ _(z) \
+ _(w) \
+
+#define XR_LIST_STRUCT_XrHandTrackingMeshFB(_) \
+ _(type) \
+ _(next) \
+ _(jointCapacityInput) \
+ _(jointCountOutput) \
+ _(jointBindPoses) \
+ _(jointRadii) \
+ _(jointParents) \
+ _(vertexCapacityInput) \
+ _(vertexCountOutput) \
+ _(vertexPositions) \
+ _(vertexNormals) \
+ _(vertexUVs) \
+ _(vertexBlendIndices) \
+ _(vertexBlendWeights) \
+ _(indexCapacityInput) \
+ _(indexCountOutput) \
+ _(indices) \
+
+#define XR_LIST_STRUCT_XrHandTrackingScaleFB(_) \
+ _(type) \
+ _(next) \
+ _(sensorOutput) \
+ _(currentOutput) \
+ _(overrideHandScale) \
+ _(overrideValueInput) \
+
+#define XR_LIST_STRUCT_XrHandTrackingAimStateFB(_) \
+ _(type) \
+ _(next) \
+ _(status) \
+ _(aimPose) \
+ _(pinchStrengthIndex) \
+ _(pinchStrengthMiddle) \
+ _(pinchStrengthRing) \
+ _(pinchStrengthLittle) \
+
+#define XR_LIST_STRUCT_XrHandCapsuleFB(_) \
+ _(points) \
+ _(radius) \
+ _(joint) \
+
+#define XR_LIST_STRUCT_XrHandTrackingCapsulesStateFB(_) \
+ _(type) \
+ _(next) \
+ _(capsules) \
+
+#define XR_LIST_STRUCT_XrSystemSpatialEntityPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(supportsSpatialEntity) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(space) \
+ _(poseInSpace) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrSpaceComponentStatusSetInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(componentType) \
+ _(enabled) \
+ _(timeout) \
+
+#define XR_LIST_STRUCT_XrSpaceComponentStatusFB(_) \
+ _(type) \
+ _(next) \
+ _(enabled) \
+ _(changePending) \
+
+#define XR_LIST_STRUCT_XrUuidEXT(_) \
+ _(data) \
+
+#define XR_LIST_STRUCT_XrEventDataSpatialAnchorCreateCompleteFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+ _(result) \
+ _(space) \
+ _(uuid) \
+
+#define XR_LIST_STRUCT_XrEventDataSpaceSetStatusCompleteFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+ _(result) \
+ _(space) \
+ _(uuid) \
+ _(componentType) \
+ _(enabled) \
+
+#define XR_LIST_STRUCT_XrFoveationProfileCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSwapchainCreateInfoFoveationFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrSwapchainStateFoveationFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+ _(profile) \
+
+#define XR_LIST_STRUCT_XrFoveationLevelProfileCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(level) \
+ _(verticalOffset) \
+ _(dynamic) \
+
+#define XR_LIST_STRUCT_XrSystemKeyboardTrackingPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(supportsKeyboardTracking) \
+
+#define XR_LIST_STRUCT_XrKeyboardTrackingDescriptionFB(_) \
+ _(trackedKeyboardId) \
+ _(size) \
+ _(flags) \
+ _(name) \
+
+#define XR_LIST_STRUCT_XrKeyboardSpaceCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(trackedKeyboardId) \
+
+#define XR_LIST_STRUCT_XrKeyboardTrackingQueryFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrTriangleMeshCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+ _(windingOrder) \
+ _(vertexCount) \
+ _(vertexBuffer) \
+ _(triangleCount) \
+ _(indexBuffer) \
+
+#define XR_LIST_STRUCT_XrSystemPassthroughPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(supportsPassthrough) \
+
+#define XR_LIST_STRUCT_XrPassthroughCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrPassthroughLayerCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(passthrough) \
+ _(flags) \
+ _(purpose) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerPassthroughFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+ _(space) \
+ _(layerHandle) \
+
+#define XR_LIST_STRUCT_XrGeometryInstanceCreateInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(layer) \
+ _(mesh) \
+ _(baseSpace) \
+ _(pose) \
+ _(scale) \
+
+#define XR_LIST_STRUCT_XrGeometryInstanceTransformFB(_) \
+ _(type) \
+ _(next) \
+ _(baseSpace) \
+ _(time) \
+ _(pose) \
+ _(scale) \
+
+#define XR_LIST_STRUCT_XrPassthroughStyleFB(_) \
+ _(type) \
+ _(next) \
+ _(textureOpacityFactor) \
+ _(edgeColor) \
+
+#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToRgbaFB(_) \
+ _(type) \
+ _(next) \
+ _(textureColorMap) \
+
+#define XR_LIST_STRUCT_XrPassthroughColorMapMonoToMonoFB(_) \
+ _(type) \
+ _(next) \
+ _(textureColorMap) \
+
+#define XR_LIST_STRUCT_XrPassthroughBrightnessContrastSaturationFB(_) \
+ _(type) \
+ _(next) \
+ _(brightness) \
+ _(contrast) \
+ _(saturation) \
+
+#define XR_LIST_STRUCT_XrEventDataPassthroughStateChangedFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrRenderModelPathInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(path) \
+
+#define XR_LIST_STRUCT_XrRenderModelPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(vendorId) \
+ _(modelName) \
+ _(modelKey) \
+ _(modelVersion) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrRenderModelBufferFB(_) \
+ _(type) \
+ _(next) \
+ _(bufferCapacityInput) \
+ _(bufferCountOutput) \
+ _(buffer) \
+
+#define XR_LIST_STRUCT_XrRenderModelLoadInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(modelKey) \
+
+#define XR_LIST_STRUCT_XrSystemRenderModelPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(supportsRenderModelLoading) \
+
+#define XR_LIST_STRUCT_XrRenderModelCapabilitiesRequestFB(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrViewLocateFoveatedRenderingVARJO(_) \
+ _(type) \
+ _(next) \
+ _(foveatedRenderingActive) \
+
+#define XR_LIST_STRUCT_XrFoveatedViewConfigurationViewVARJO(_) \
+ _(type) \
+ _(next) \
+ _(foveatedRenderingActive) \
+
+#define XR_LIST_STRUCT_XrSystemFoveatedRenderingPropertiesVARJO(_) \
+ _(type) \
+ _(next) \
+ _(supportsFoveatedRendering) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerDepthTestVARJO(_) \
+ _(type) \
+ _(next) \
+ _(depthTestRangeNearZ) \
+ _(depthTestRangeFarZ) \
+
+#define XR_LIST_STRUCT_XrSystemMarkerTrackingPropertiesVARJO(_) \
+ _(type) \
+ _(next) \
+ _(supportsMarkerTracking) \
+
+#define XR_LIST_STRUCT_XrEventDataMarkerTrackingUpdateVARJO(_) \
+ _(type) \
+ _(next) \
+ _(markerId) \
+ _(isActive) \
+ _(isPredicted) \
+ _(time) \
+
+#define XR_LIST_STRUCT_XrMarkerSpaceCreateInfoVARJO(_) \
+ _(type) \
+ _(next) \
+ _(markerId) \
+ _(poseInMarkerSpace) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceNameMSFT(_) \
+ _(name) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorPersistenceInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(spatialAnchorPersistenceName) \
+ _(spatialAnchor) \
+
+#define XR_LIST_STRUCT_XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT(_) \
+ _(type) \
+ _(next) \
+ _(spatialAnchorStore) \
+ _(spatialAnchorPersistenceName) \
+
+#define XR_LIST_STRUCT_XrSpaceQueryInfoBaseHeaderFB(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSpaceFilterInfoBaseHeaderFB(_) \
+ _(type) \
+ _(next) \
+
+#define XR_LIST_STRUCT_XrSpaceQueryInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(queryAction) \
+ _(maxResultCount) \
+ _(timeout) \
+ _(filter) \
+ _(excludeFilter) \
+
+#define XR_LIST_STRUCT_XrSpaceStorageLocationFilterInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(location) \
+
+#define XR_LIST_STRUCT_XrSpaceUuidFilterInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(uuidCount) \
+ _(uuids) \
+
+#define XR_LIST_STRUCT_XrSpaceComponentFilterInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(componentType) \
+
+#define XR_LIST_STRUCT_XrSpaceQueryResultFB(_) \
+ _(space) \
+ _(uuid) \
+
+#define XR_LIST_STRUCT_XrSpaceQueryResultsFB(_) \
+ _(type) \
+ _(next) \
+ _(resultCapacityInput) \
+ _(resultCountOutput) \
+ _(results) \
+
+#define XR_LIST_STRUCT_XrEventDataSpaceQueryResultsAvailableFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+
+#define XR_LIST_STRUCT_XrEventDataSpaceQueryCompleteFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+ _(result) \
+
+#define XR_LIST_STRUCT_XrSpaceSaveInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(space) \
+ _(location) \
+ _(persistenceMode) \
+
+#define XR_LIST_STRUCT_XrSpaceEraseInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(space) \
+ _(location) \
+
+#define XR_LIST_STRUCT_XrEventDataSpaceSaveCompleteFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+ _(result) \
+ _(space) \
+ _(uuid) \
+ _(location) \
+
+#define XR_LIST_STRUCT_XrEventDataSpaceEraseCompleteFB(_) \
+ _(type) \
+ _(next) \
+ _(requestId) \
+ _(result) \
+ _(space) \
+ _(uuid) \
+ _(location) \
+
+#define XR_LIST_STRUCT_XrSwapchainImageFoveationVulkanFB(_) \
+ _(type) \
+ _(next) \
+ _(image) \
+ _(width) \
+ _(height) \
+
+#define XR_LIST_STRUCT_XrSwapchainStateAndroidSurfaceDimensionsFB(_) \
+ _(type) \
+ _(next) \
+ _(width) \
+ _(height) \
+
+#define XR_LIST_STRUCT_XrSwapchainStateSamplerOpenGLESFB(_) \
+ _(type) \
+ _(next) \
+ _(minFilter) \
+ _(magFilter) \
+ _(wrapModeS) \
+ _(wrapModeT) \
+ _(swizzleRed) \
+ _(swizzleGreen) \
+ _(swizzleBlue) \
+ _(swizzleAlpha) \
+ _(maxAnisotropy) \
+ _(borderColor) \
+
+#define XR_LIST_STRUCT_XrSwapchainStateSamplerVulkanFB(_) \
+ _(type) \
+ _(next) \
+ _(minFilter) \
+ _(magFilter) \
+ _(mipmapMode) \
+ _(wrapModeS) \
+ _(wrapModeT) \
+ _(swizzleRed) \
+ _(swizzleGreen) \
+ _(swizzleBlue) \
+ _(swizzleAlpha) \
+ _(maxAnisotropy) \
+ _(borderColor) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerSpaceWarpInfoFB(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+ _(motionVectorSubImage) \
+ _(appSpaceDeltaPose) \
+ _(depthSubImage) \
+ _(minDepth) \
+ _(maxDepth) \
+ _(nearZ) \
+ _(farZ) \
+
+#define XR_LIST_STRUCT_XrSystemSpaceWarpPropertiesFB(_) \
+ _(type) \
+ _(next) \
+ _(recommendedMotionVectorImageRectWidth) \
+ _(recommendedMotionVectorImageRectHeight) \
+
+#define XR_LIST_STRUCT_XrDigitalLensControlALMALENCE(_) \
+ _(type) \
+ _(next) \
+ _(flags) \
+
+#define XR_LIST_STRUCT_XrSpaceContainerFB(_) \
+ _(type) \
+ _(next) \
+ _(uuidCapacityInput) \
+ _(uuidCountOutput) \
+ _(uuids) \
+
+#define XR_LIST_STRUCT_XrPassthroughKeyboardHandsIntensityFB(_) \
+ _(type) \
+ _(next) \
+ _(leftHandIntensity) \
+ _(rightHandIntensity) \
+
+#define XR_LIST_STRUCT_XrCompositionLayerSettingsFB(_) \
+ _(type) \
+ _(next) \
+ _(layerFlags) \
+
+#define XR_LIST_STRUCT_XrVulkanSwapchainCreateInfoMETA(_) \
+ _(type) \
+ _(next) \
+ _(additionalCreateFlags) \
+ _(additionalUsageFlags) \
+
+#define XR_LIST_STRUCT_XrPerformanceMetricsStateMETA(_) \
+ _(type) \
+ _(next) \
+ _(enabled) \
+
+#define XR_LIST_STRUCT_XrPerformanceMetricsCounterMETA(_) \
+ _(type) \
+ _(next) \
+ _(counterFlags) \
+ _(counterUnit) \
+ _(uintValue) \
+ _(floatValue) \
+
+
+
+#define XR_LIST_STRUCTURE_TYPES_CORE(_) \
+ _(XrApiLayerProperties, XR_TYPE_API_LAYER_PROPERTIES) \
+ _(XrExtensionProperties, XR_TYPE_EXTENSION_PROPERTIES) \
+ _(XrInstanceCreateInfo, XR_TYPE_INSTANCE_CREATE_INFO) \
+ _(XrInstanceProperties, XR_TYPE_INSTANCE_PROPERTIES) \
+ _(XrEventDataBuffer, XR_TYPE_EVENT_DATA_BUFFER) \
+ _(XrSystemGetInfo, XR_TYPE_SYSTEM_GET_INFO) \
+ _(XrSystemProperties, XR_TYPE_SYSTEM_PROPERTIES) \
+ _(XrSessionCreateInfo, XR_TYPE_SESSION_CREATE_INFO) \
+ _(XrSpaceVelocity, XR_TYPE_SPACE_VELOCITY) \
+ _(XrReferenceSpaceCreateInfo, XR_TYPE_REFERENCE_SPACE_CREATE_INFO) \
+ _(XrActionSpaceCreateInfo, XR_TYPE_ACTION_SPACE_CREATE_INFO) \
+ _(XrSpaceLocation, XR_TYPE_SPACE_LOCATION) \
+ _(XrViewConfigurationProperties, XR_TYPE_VIEW_CONFIGURATION_PROPERTIES) \
+ _(XrViewConfigurationView, XR_TYPE_VIEW_CONFIGURATION_VIEW) \
+ _(XrSwapchainCreateInfo, XR_TYPE_SWAPCHAIN_CREATE_INFO) \
+ _(XrSwapchainImageAcquireInfo, XR_TYPE_SWAPCHAIN_IMAGE_ACQUIRE_INFO) \
+ _(XrSwapchainImageWaitInfo, XR_TYPE_SWAPCHAIN_IMAGE_WAIT_INFO) \
+ _(XrSwapchainImageReleaseInfo, XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO) \
+ _(XrSessionBeginInfo, XR_TYPE_SESSION_BEGIN_INFO) \
+ _(XrFrameWaitInfo, XR_TYPE_FRAME_WAIT_INFO) \
+ _(XrFrameState, XR_TYPE_FRAME_STATE) \
+ _(XrFrameBeginInfo, XR_TYPE_FRAME_BEGIN_INFO) \
+ _(XrFrameEndInfo, XR_TYPE_FRAME_END_INFO) \
+ _(XrViewLocateInfo, XR_TYPE_VIEW_LOCATE_INFO) \
+ _(XrViewState, XR_TYPE_VIEW_STATE) \
+ _(XrView, XR_TYPE_VIEW) \
+ _(XrActionSetCreateInfo, XR_TYPE_ACTION_SET_CREATE_INFO) \
+ _(XrActionCreateInfo, XR_TYPE_ACTION_CREATE_INFO) \
+ _(XrInteractionProfileSuggestedBinding, XR_TYPE_INTERACTION_PROFILE_SUGGESTED_BINDING) \
+ _(XrSessionActionSetsAttachInfo, XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO) \
+ _(XrInteractionProfileState, XR_TYPE_INTERACTION_PROFILE_STATE) \
+ _(XrActionStateGetInfo, XR_TYPE_ACTION_STATE_GET_INFO) \
+ _(XrActionStateBoolean, XR_TYPE_ACTION_STATE_BOOLEAN) \
+ _(XrActionStateFloat, XR_TYPE_ACTION_STATE_FLOAT) \
+ _(XrActionStateVector2f, XR_TYPE_ACTION_STATE_VECTOR2F) \
+ _(XrActionStatePose, XR_TYPE_ACTION_STATE_POSE) \
+ _(XrActionsSyncInfo, XR_TYPE_ACTIONS_SYNC_INFO) \
+ _(XrBoundSourcesForActionEnumerateInfo, XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO) \
+ _(XrInputSourceLocalizedNameGetInfo, XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO) \
+ _(XrHapticActionInfo, XR_TYPE_HAPTIC_ACTION_INFO) \
+ _(XrCompositionLayerProjectionView, XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW) \
+ _(XrCompositionLayerProjection, XR_TYPE_COMPOSITION_LAYER_PROJECTION) \
+ _(XrCompositionLayerQuad, XR_TYPE_COMPOSITION_LAYER_QUAD) \
+ _(XrEventDataEventsLost, XR_TYPE_EVENT_DATA_EVENTS_LOST) \
+ _(XrEventDataInstanceLossPending, XR_TYPE_EVENT_DATA_INSTANCE_LOSS_PENDING) \
+ _(XrEventDataSessionStateChanged, XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) \
+ _(XrEventDataReferenceSpaceChangePending, XR_TYPE_EVENT_DATA_REFERENCE_SPACE_CHANGE_PENDING) \
+ _(XrEventDataInteractionProfileChanged, XR_TYPE_EVENT_DATA_INTERACTION_PROFILE_CHANGED) \
+ _(XrHapticVibration, XR_TYPE_HAPTIC_VIBRATION) \
+ _(XrCompositionLayerCubeKHR, XR_TYPE_COMPOSITION_LAYER_CUBE_KHR) \
+ _(XrCompositionLayerDepthInfoKHR, XR_TYPE_COMPOSITION_LAYER_DEPTH_INFO_KHR) \
+ _(XrCompositionLayerCylinderKHR, XR_TYPE_COMPOSITION_LAYER_CYLINDER_KHR) \
+ _(XrCompositionLayerEquirectKHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT_KHR) \
+ _(XrVisibilityMaskKHR, XR_TYPE_VISIBILITY_MASK_KHR) \
+ _(XrEventDataVisibilityMaskChangedKHR, XR_TYPE_EVENT_DATA_VISIBILITY_MASK_CHANGED_KHR) \
+ _(XrCompositionLayerColorScaleBiasKHR, XR_TYPE_COMPOSITION_LAYER_COLOR_SCALE_BIAS_KHR) \
+ _(XrCompositionLayerEquirect2KHR, XR_TYPE_COMPOSITION_LAYER_EQUIRECT2_KHR) \
+ _(XrBindingModificationsKHR, XR_TYPE_BINDING_MODIFICATIONS_KHR) \
+ _(XrEventDataPerfSettingsEXT, XR_TYPE_EVENT_DATA_PERF_SETTINGS_EXT) \
+ _(XrDebugUtilsObjectNameInfoEXT, XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT) \
+ _(XrDebugUtilsLabelEXT, XR_TYPE_DEBUG_UTILS_LABEL_EXT) \
+ _(XrDebugUtilsMessengerCallbackDataEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT) \
+ _(XrDebugUtilsMessengerCreateInfoEXT, XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) \
+ _(XrSystemEyeGazeInteractionPropertiesEXT, XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT) \
+ _(XrEyeGazeSampleTimeEXT, XR_TYPE_EYE_GAZE_SAMPLE_TIME_EXT) \
+ _(XrSessionCreateInfoOverlayEXTX, XR_TYPE_SESSION_CREATE_INFO_OVERLAY_EXTX) \
+ _(XrEventDataMainSessionVisibilityChangedEXTX, XR_TYPE_EVENT_DATA_MAIN_SESSION_VISIBILITY_CHANGED_EXTX) \
+ _(XrSpatialAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_MSFT) \
+ _(XrSpatialAnchorSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_SPACE_CREATE_INFO_MSFT) \
+ _(XrCompositionLayerImageLayoutFB, XR_TYPE_COMPOSITION_LAYER_IMAGE_LAYOUT_FB) \
+ _(XrCompositionLayerAlphaBlendFB, XR_TYPE_COMPOSITION_LAYER_ALPHA_BLEND_FB) \
+ _(XrViewConfigurationDepthRangeEXT, XR_TYPE_VIEW_CONFIGURATION_DEPTH_RANGE_EXT) \
+ _(XrSpatialGraphNodeSpaceCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_SPACE_CREATE_INFO_MSFT) \
+ _(XrSpatialGraphStaticNodeBindingCreateInfoMSFT, XR_TYPE_SPATIAL_GRAPH_STATIC_NODE_BINDING_CREATE_INFO_MSFT) \
+ _(XrSpatialGraphNodeBindingPropertiesGetInfoMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_GET_INFO_MSFT) \
+ _(XrSpatialGraphNodeBindingPropertiesMSFT, XR_TYPE_SPATIAL_GRAPH_NODE_BINDING_PROPERTIES_MSFT) \
+ _(XrSystemHandTrackingPropertiesEXT, XR_TYPE_SYSTEM_HAND_TRACKING_PROPERTIES_EXT) \
+ _(XrHandTrackerCreateInfoEXT, XR_TYPE_HAND_TRACKER_CREATE_INFO_EXT) \
+ _(XrHandJointsLocateInfoEXT, XR_TYPE_HAND_JOINTS_LOCATE_INFO_EXT) \
+ _(XrHandJointLocationsEXT, XR_TYPE_HAND_JOINT_LOCATIONS_EXT) \
+ _(XrHandJointVelocitiesEXT, XR_TYPE_HAND_JOINT_VELOCITIES_EXT) \
+ _(XrSystemHandTrackingMeshPropertiesMSFT, XR_TYPE_SYSTEM_HAND_TRACKING_MESH_PROPERTIES_MSFT) \
+ _(XrHandMeshSpaceCreateInfoMSFT, XR_TYPE_HAND_MESH_SPACE_CREATE_INFO_MSFT) \
+ _(XrHandMeshUpdateInfoMSFT, XR_TYPE_HAND_MESH_UPDATE_INFO_MSFT) \
+ _(XrHandMeshMSFT, XR_TYPE_HAND_MESH_MSFT) \
+ _(XrHandPoseTypeInfoMSFT, XR_TYPE_HAND_POSE_TYPE_INFO_MSFT) \
+ _(XrSecondaryViewConfigurationSessionBeginInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SESSION_BEGIN_INFO_MSFT) \
+ _(XrSecondaryViewConfigurationStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_STATE_MSFT) \
+ _(XrSecondaryViewConfigurationFrameStateMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_STATE_MSFT) \
+ _(XrSecondaryViewConfigurationLayerInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_LAYER_INFO_MSFT) \
+ _(XrSecondaryViewConfigurationFrameEndInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_FRAME_END_INFO_MSFT) \
+ _(XrSecondaryViewConfigurationSwapchainCreateInfoMSFT, XR_TYPE_SECONDARY_VIEW_CONFIGURATION_SWAPCHAIN_CREATE_INFO_MSFT) \
+ _(XrControllerModelKeyStateMSFT, XR_TYPE_CONTROLLER_MODEL_KEY_STATE_MSFT) \
+ _(XrControllerModelNodePropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_PROPERTIES_MSFT) \
+ _(XrControllerModelPropertiesMSFT, XR_TYPE_CONTROLLER_MODEL_PROPERTIES_MSFT) \
+ _(XrControllerModelNodeStateMSFT, XR_TYPE_CONTROLLER_MODEL_NODE_STATE_MSFT) \
+ _(XrControllerModelStateMSFT, XR_TYPE_CONTROLLER_MODEL_STATE_MSFT) \
+ _(XrViewConfigurationViewFovEPIC, XR_TYPE_VIEW_CONFIGURATION_VIEW_FOV_EPIC) \
+ _(XrCompositionLayerReprojectionInfoMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_INFO_MSFT) \
+ _(XrCompositionLayerReprojectionPlaneOverrideMSFT, XR_TYPE_COMPOSITION_LAYER_REPROJECTION_PLANE_OVERRIDE_MSFT) \
+ _(XrCompositionLayerSecureContentFB, XR_TYPE_COMPOSITION_LAYER_SECURE_CONTENT_FB) \
+ _(XrInteractionProfileDpadBindingEXT, XR_TYPE_INTERACTION_PROFILE_DPAD_BINDING_EXT) \
+ _(XrInteractionProfileAnalogThresholdVALVE, XR_TYPE_INTERACTION_PROFILE_ANALOG_THRESHOLD_VALVE) \
+ _(XrHandJointsMotionRangeInfoEXT, XR_TYPE_HAND_JOINTS_MOTION_RANGE_INFO_EXT) \
+ _(XrSceneObserverCreateInfoMSFT, XR_TYPE_SCENE_OBSERVER_CREATE_INFO_MSFT) \
+ _(XrSceneCreateInfoMSFT, XR_TYPE_SCENE_CREATE_INFO_MSFT) \
+ _(XrNewSceneComputeInfoMSFT, XR_TYPE_NEW_SCENE_COMPUTE_INFO_MSFT) \
+ _(XrVisualMeshComputeLodInfoMSFT, XR_TYPE_VISUAL_MESH_COMPUTE_LOD_INFO_MSFT) \
+ _(XrSceneComponentsMSFT, XR_TYPE_SCENE_COMPONENTS_MSFT) \
+ _(XrSceneComponentsGetInfoMSFT, XR_TYPE_SCENE_COMPONENTS_GET_INFO_MSFT) \
+ _(XrSceneComponentLocationsMSFT, XR_TYPE_SCENE_COMPONENT_LOCATIONS_MSFT) \
+ _(XrSceneComponentsLocateInfoMSFT, XR_TYPE_SCENE_COMPONENTS_LOCATE_INFO_MSFT) \
+ _(XrSceneObjectsMSFT, XR_TYPE_SCENE_OBJECTS_MSFT) \
+ _(XrSceneComponentParentFilterInfoMSFT, XR_TYPE_SCENE_COMPONENT_PARENT_FILTER_INFO_MSFT) \
+ _(XrSceneObjectTypesFilterInfoMSFT, XR_TYPE_SCENE_OBJECT_TYPES_FILTER_INFO_MSFT) \
+ _(XrScenePlanesMSFT, XR_TYPE_SCENE_PLANES_MSFT) \
+ _(XrScenePlaneAlignmentFilterInfoMSFT, XR_TYPE_SCENE_PLANE_ALIGNMENT_FILTER_INFO_MSFT) \
+ _(XrSceneMeshesMSFT, XR_TYPE_SCENE_MESHES_MSFT) \
+ _(XrSceneMeshBuffersGetInfoMSFT, XR_TYPE_SCENE_MESH_BUFFERS_GET_INFO_MSFT) \
+ _(XrSceneMeshBuffersMSFT, XR_TYPE_SCENE_MESH_BUFFERS_MSFT) \
+ _(XrSceneMeshVertexBufferMSFT, XR_TYPE_SCENE_MESH_VERTEX_BUFFER_MSFT) \
+ _(XrSceneMeshIndicesUint32MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT32_MSFT) \
+ _(XrSceneMeshIndicesUint16MSFT, XR_TYPE_SCENE_MESH_INDICES_UINT16_MSFT) \
+ _(XrSerializedSceneFragmentDataGetInfoMSFT, XR_TYPE_SERIALIZED_SCENE_FRAGMENT_DATA_GET_INFO_MSFT) \
+ _(XrSceneDeserializeInfoMSFT, XR_TYPE_SCENE_DESERIALIZE_INFO_MSFT) \
+ _(XrEventDataDisplayRefreshRateChangedFB, XR_TYPE_EVENT_DATA_DISPLAY_REFRESH_RATE_CHANGED_FB) \
+ _(XrViveTrackerPathsHTCX, XR_TYPE_VIVE_TRACKER_PATHS_HTCX) \
+ _(XrEventDataViveTrackerConnectedHTCX, XR_TYPE_EVENT_DATA_VIVE_TRACKER_CONNECTED_HTCX) \
+ _(XrSystemFacialTrackingPropertiesHTC, XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC) \
+ _(XrFacialExpressionsHTC, XR_TYPE_FACIAL_EXPRESSIONS_HTC) \
+ _(XrFacialTrackerCreateInfoHTC, XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC) \
+ _(XrSystemColorSpacePropertiesFB, XR_TYPE_SYSTEM_COLOR_SPACE_PROPERTIES_FB) \
+ _(XrHandTrackingMeshFB, XR_TYPE_HAND_TRACKING_MESH_FB) \
+ _(XrHandTrackingScaleFB, XR_TYPE_HAND_TRACKING_SCALE_FB) \
+ _(XrHandTrackingAimStateFB, XR_TYPE_HAND_TRACKING_AIM_STATE_FB) \
+ _(XrHandTrackingCapsulesStateFB, XR_TYPE_HAND_TRACKING_CAPSULES_STATE_FB) \
+ _(XrSystemSpatialEntityPropertiesFB, XR_TYPE_SYSTEM_SPATIAL_ENTITY_PROPERTIES_FB) \
+ _(XrSpatialAnchorCreateInfoFB, XR_TYPE_SPATIAL_ANCHOR_CREATE_INFO_FB) \
+ _(XrSpaceComponentStatusSetInfoFB, XR_TYPE_SPACE_COMPONENT_STATUS_SET_INFO_FB) \
+ _(XrSpaceComponentStatusFB, XR_TYPE_SPACE_COMPONENT_STATUS_FB) \
+ _(XrEventDataSpatialAnchorCreateCompleteFB, XR_TYPE_EVENT_DATA_SPATIAL_ANCHOR_CREATE_COMPLETE_FB) \
+ _(XrEventDataSpaceSetStatusCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SET_STATUS_COMPLETE_FB) \
+ _(XrFoveationProfileCreateInfoFB, XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB) \
+ _(XrSwapchainCreateInfoFoveationFB, XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB) \
+ _(XrSwapchainStateFoveationFB, XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB) \
+ _(XrFoveationLevelProfileCreateInfoFB, XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB) \
+ _(XrSystemKeyboardTrackingPropertiesFB, XR_TYPE_SYSTEM_KEYBOARD_TRACKING_PROPERTIES_FB) \
+ _(XrKeyboardSpaceCreateInfoFB, XR_TYPE_KEYBOARD_SPACE_CREATE_INFO_FB) \
+ _(XrKeyboardTrackingQueryFB, XR_TYPE_KEYBOARD_TRACKING_QUERY_FB) \
+ _(XrTriangleMeshCreateInfoFB, XR_TYPE_TRIANGLE_MESH_CREATE_INFO_FB) \
+ _(XrSystemPassthroughPropertiesFB, XR_TYPE_SYSTEM_PASSTHROUGH_PROPERTIES_FB) \
+ _(XrPassthroughCreateInfoFB, XR_TYPE_PASSTHROUGH_CREATE_INFO_FB) \
+ _(XrPassthroughLayerCreateInfoFB, XR_TYPE_PASSTHROUGH_LAYER_CREATE_INFO_FB) \
+ _(XrCompositionLayerPassthroughFB, XR_TYPE_COMPOSITION_LAYER_PASSTHROUGH_FB) \
+ _(XrGeometryInstanceCreateInfoFB, XR_TYPE_GEOMETRY_INSTANCE_CREATE_INFO_FB) \
+ _(XrGeometryInstanceTransformFB, XR_TYPE_GEOMETRY_INSTANCE_TRANSFORM_FB) \
+ _(XrPassthroughStyleFB, XR_TYPE_PASSTHROUGH_STYLE_FB) \
+ _(XrPassthroughColorMapMonoToRgbaFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_RGBA_FB) \
+ _(XrPassthroughColorMapMonoToMonoFB, XR_TYPE_PASSTHROUGH_COLOR_MAP_MONO_TO_MONO_FB) \
+ _(XrPassthroughBrightnessContrastSaturationFB, XR_TYPE_PASSTHROUGH_BRIGHTNESS_CONTRAST_SATURATION_FB) \
+ _(XrEventDataPassthroughStateChangedFB, XR_TYPE_EVENT_DATA_PASSTHROUGH_STATE_CHANGED_FB) \
+ _(XrRenderModelPathInfoFB, XR_TYPE_RENDER_MODEL_PATH_INFO_FB) \
+ _(XrRenderModelPropertiesFB, XR_TYPE_RENDER_MODEL_PROPERTIES_FB) \
+ _(XrRenderModelBufferFB, XR_TYPE_RENDER_MODEL_BUFFER_FB) \
+ _(XrRenderModelLoadInfoFB, XR_TYPE_RENDER_MODEL_LOAD_INFO_FB) \
+ _(XrSystemRenderModelPropertiesFB, XR_TYPE_SYSTEM_RENDER_MODEL_PROPERTIES_FB) \
+ _(XrRenderModelCapabilitiesRequestFB, XR_TYPE_RENDER_MODEL_CAPABILITIES_REQUEST_FB) \
+ _(XrViewLocateFoveatedRenderingVARJO, XR_TYPE_VIEW_LOCATE_FOVEATED_RENDERING_VARJO) \
+ _(XrFoveatedViewConfigurationViewVARJO, XR_TYPE_FOVEATED_VIEW_CONFIGURATION_VIEW_VARJO) \
+ _(XrSystemFoveatedRenderingPropertiesVARJO, XR_TYPE_SYSTEM_FOVEATED_RENDERING_PROPERTIES_VARJO) \
+ _(XrCompositionLayerDepthTestVARJO, XR_TYPE_COMPOSITION_LAYER_DEPTH_TEST_VARJO) \
+ _(XrSystemMarkerTrackingPropertiesVARJO, XR_TYPE_SYSTEM_MARKER_TRACKING_PROPERTIES_VARJO) \
+ _(XrEventDataMarkerTrackingUpdateVARJO, XR_TYPE_EVENT_DATA_MARKER_TRACKING_UPDATE_VARJO) \
+ _(XrMarkerSpaceCreateInfoVARJO, XR_TYPE_MARKER_SPACE_CREATE_INFO_VARJO) \
+ _(XrSpatialAnchorPersistenceInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_PERSISTENCE_INFO_MSFT) \
+ _(XrSpatialAnchorFromPersistedAnchorCreateInfoMSFT, XR_TYPE_SPATIAL_ANCHOR_FROM_PERSISTED_ANCHOR_CREATE_INFO_MSFT) \
+ _(XrSpaceQueryInfoFB, XR_TYPE_SPACE_QUERY_INFO_FB) \
+ _(XrSpaceStorageLocationFilterInfoFB, XR_TYPE_SPACE_STORAGE_LOCATION_FILTER_INFO_FB) \
+ _(XrSpaceUuidFilterInfoFB, XR_TYPE_SPACE_UUID_FILTER_INFO_FB) \
+ _(XrSpaceComponentFilterInfoFB, XR_TYPE_SPACE_COMPONENT_FILTER_INFO_FB) \
+ _(XrSpaceQueryResultsFB, XR_TYPE_SPACE_QUERY_RESULTS_FB) \
+ _(XrEventDataSpaceQueryResultsAvailableFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_RESULTS_AVAILABLE_FB) \
+ _(XrEventDataSpaceQueryCompleteFB, XR_TYPE_EVENT_DATA_SPACE_QUERY_COMPLETE_FB) \
+ _(XrSpaceSaveInfoFB, XR_TYPE_SPACE_SAVE_INFO_FB) \
+ _(XrSpaceEraseInfoFB, XR_TYPE_SPACE_ERASE_INFO_FB) \
+ _(XrEventDataSpaceSaveCompleteFB, XR_TYPE_EVENT_DATA_SPACE_SAVE_COMPLETE_FB) \
+ _(XrEventDataSpaceEraseCompleteFB, XR_TYPE_EVENT_DATA_SPACE_ERASE_COMPLETE_FB) \
+ _(XrCompositionLayerSpaceWarpInfoFB, XR_TYPE_COMPOSITION_LAYER_SPACE_WARP_INFO_FB) \
+ _(XrSystemSpaceWarpPropertiesFB, XR_TYPE_SYSTEM_SPACE_WARP_PROPERTIES_FB) \
+ _(XrDigitalLensControlALMALENCE, XR_TYPE_DIGITAL_LENS_CONTROL_ALMALENCE) \
+ _(XrSpaceContainerFB, XR_TYPE_SPACE_CONTAINER_FB) \
+ _(XrPassthroughKeyboardHandsIntensityFB, XR_TYPE_PASSTHROUGH_KEYBOARD_HANDS_INTENSITY_FB) \
+ _(XrCompositionLayerSettingsFB, XR_TYPE_COMPOSITION_LAYER_SETTINGS_FB) \
+ _(XrPerformanceMetricsStateMETA, XR_TYPE_PERFORMANCE_METRICS_STATE_META) \
+ _(XrPerformanceMetricsCounterMETA, XR_TYPE_PERFORMANCE_METRICS_COUNTER_META) \
+
+
+
+
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \
+ _(XrGraphicsBindingD3D11KHR, XR_TYPE_GRAPHICS_BINDING_D3D11_KHR) \
+ _(XrSwapchainImageD3D11KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR) \
+ _(XrGraphicsRequirementsD3D11KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \
+ _(XrGraphicsBindingD3D12KHR, XR_TYPE_GRAPHICS_BINDING_D3D12_KHR) \
+ _(XrSwapchainImageD3D12KHR, XR_TYPE_SWAPCHAIN_IMAGE_D3D12_KHR) \
+ _(XrGraphicsRequirementsD3D12KHR, XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \
+ _(XrSwapchainImageOpenGLKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR) \
+ _(XrGraphicsRequirementsOpenGLKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WAYLAND)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \
+ _(XrGraphicsBindingOpenGLWaylandKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WAYLAND_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_WIN32)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \
+ _(XrGraphicsBindingOpenGLWin32KHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_WIN32_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XCB)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \
+ _(XrGraphicsBindingOpenGLXcbKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XCB_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL) && defined(XR_USE_PLATFORM_XLIB)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \
+ _(XrGraphicsBindingOpenGLXlibKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_XLIB_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \
+ _(XrSwapchainImageOpenGLESKHR, XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR) \
+ _(XrGraphicsRequirementsOpenGLESKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR) \
+ _(XrSwapchainStateSamplerOpenGLESFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_OPENGL_ES_FB) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES) && defined(XR_USE_PLATFORM_ANDROID)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \
+ _(XrGraphicsBindingOpenGLESAndroidKHR, XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_)
+#endif
+
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \
+ _(XrVulkanSwapchainFormatListCreateInfoKHR, XR_TYPE_VULKAN_SWAPCHAIN_FORMAT_LIST_CREATE_INFO_KHR) \
+ _(XrGraphicsBindingVulkanKHR, XR_TYPE_GRAPHICS_BINDING_VULKAN_KHR) \
+ _(XrSwapchainImageVulkanKHR, XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR) \
+ _(XrGraphicsRequirementsVulkanKHR, XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR) \
+ _(XrVulkanInstanceCreateInfoKHR, XR_TYPE_VULKAN_INSTANCE_CREATE_INFO_KHR) \
+ _(XrVulkanDeviceCreateInfoKHR, XR_TYPE_VULKAN_DEVICE_CREATE_INFO_KHR) \
+ _(XrVulkanGraphicsDeviceGetInfoKHR, XR_TYPE_VULKAN_GRAPHICS_DEVICE_GET_INFO_KHR) \
+ _(XrSwapchainImageFoveationVulkanFB, XR_TYPE_SWAPCHAIN_IMAGE_FOVEATION_VULKAN_FB) \
+ _(XrSwapchainStateSamplerVulkanFB, XR_TYPE_SWAPCHAIN_STATE_SAMPLER_VULKAN_FB) \
+ _(XrVulkanSwapchainCreateInfoMETA, XR_TYPE_VULKAN_SWAPCHAIN_CREATE_INFO_META) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_)
+#endif
+
+#if defined(XR_USE_PLATFORM_ANDROID)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \
+ _(XrInstanceCreateInfoAndroidKHR, XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR) \
+ _(XrLoaderInitInfoAndroidKHR, XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) \
+ _(XrAndroidSurfaceSwapchainCreateInfoFB, XR_TYPE_ANDROID_SURFACE_SWAPCHAIN_CREATE_INFO_FB) \
+ _(XrSwapchainStateAndroidSurfaceDimensionsFB, XR_TYPE_SWAPCHAIN_STATE_ANDROID_SURFACE_DIMENSIONS_FB) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_)
+#endif
+
+#if defined(XR_USE_PLATFORM_EGL)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \
+ _(XrGraphicsBindingEGLMNDX, XR_TYPE_GRAPHICS_BINDING_EGL_MNDX) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_)
+#endif
+
+#if defined(XR_USE_PLATFORM_WIN32)
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \
+ _(XrHolographicWindowAttachmentMSFT, XR_TYPE_HOLOGRAPHIC_WINDOW_ATTACHMENT_MSFT) \
+
+
+#else
+#define XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_)
+#endif
+
+#define XR_LIST_STRUCTURE_TYPES(_) \
+ XR_LIST_STRUCTURE_TYPES_CORE(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D11(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_D3D12(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WAYLAND(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_WIN32(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XCB(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_XR_USE_PLATFORM_XLIB(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_OPENGL_ES_XR_USE_PLATFORM_ANDROID(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_GRAPHICS_API_VULKAN(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_ANDROID(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_EGL(_) \
+ XR_LIST_STRUCTURE_TYPES_XR_USE_PLATFORM_WIN32(_) \
+
+
+#define XR_LIST_EXTENSIONS(_) \
+ _(XR_KHR_android_thread_settings, 4) \
+ _(XR_KHR_android_surface_swapchain, 5) \
+ _(XR_KHR_composition_layer_cube, 7) \
+ _(XR_KHR_android_create_instance, 9) \
+ _(XR_KHR_composition_layer_depth, 11) \
+ _(XR_KHR_vulkan_swapchain_format_list, 15) \
+ _(XR_EXT_performance_settings, 16) \
+ _(XR_EXT_thermal_query, 17) \
+ _(XR_KHR_composition_layer_cylinder, 18) \
+ _(XR_KHR_composition_layer_equirect, 19) \
+ _(XR_EXT_debug_utils, 20) \
+ _(XR_KHR_opengl_enable, 24) \
+ _(XR_KHR_opengl_es_enable, 25) \
+ _(XR_KHR_vulkan_enable, 26) \
+ _(XR_KHR_D3D11_enable, 28) \
+ _(XR_KHR_D3D12_enable, 29) \
+ _(XR_EXT_eye_gaze_interaction, 31) \
+ _(XR_KHR_visibility_mask, 32) \
+ _(XR_EXTX_overlay, 34) \
+ _(XR_KHR_composition_layer_color_scale_bias, 35) \
+ _(XR_KHR_win32_convert_performance_counter_time, 36) \
+ _(XR_KHR_convert_timespec_time, 37) \
+ _(XR_VARJO_quad_views, 38) \
+ _(XR_MSFT_unbounded_reference_space, 39) \
+ _(XR_MSFT_spatial_anchor, 40) \
+ _(XR_FB_composition_layer_image_layout, 41) \
+ _(XR_FB_composition_layer_alpha_blend, 42) \
+ _(XR_MND_headless, 43) \
+ _(XR_OCULUS_android_session_state_enable, 45) \
+ _(XR_EXT_view_configuration_depth_range, 47) \
+ _(XR_EXT_conformance_automation, 48) \
+ _(XR_MNDX_egl_enable, 49) \
+ _(XR_MSFT_spatial_graph_bridge, 50) \
+ _(XR_MSFT_hand_interaction, 51) \
+ _(XR_EXT_hand_tracking, 52) \
+ _(XR_MSFT_hand_tracking_mesh, 53) \
+ _(XR_MSFT_secondary_view_configuration, 54) \
+ _(XR_MSFT_first_person_observer, 55) \
+ _(XR_MSFT_controller_model, 56) \
+ _(XR_MSFT_perception_anchor_interop, 57) \
+ _(XR_EXT_win32_appcontainer_compatible, 58) \
+ _(XR_EPIC_view_configuration_fov, 60) \
+ _(XR_MSFT_holographic_window_attachment, 64) \
+ _(XR_MSFT_composition_layer_reprojection, 67) \
+ _(XR_HUAWEI_controller_interaction, 70) \
+ _(XR_FB_android_surface_swapchain_create, 71) \
+ _(XR_FB_swapchain_update_state, 72) \
+ _(XR_FB_composition_layer_secure_content, 73) \
+ _(XR_EXT_dpad_binding, 79) \
+ _(XR_VALVE_analog_threshold, 80) \
+ _(XR_EXT_hand_joints_motion_range, 81) \
+ _(XR_KHR_loader_init, 89) \
+ _(XR_KHR_loader_init_android, 90) \
+ _(XR_KHR_vulkan_enable2, 91) \
+ _(XR_KHR_composition_layer_equirect2, 92) \
+ _(XR_EXT_samsung_odyssey_controller, 95) \
+ _(XR_EXT_hp_mixed_reality_controller, 96) \
+ _(XR_MND_swapchain_usage_input_attachment_bit, 97) \
+ _(XR_MSFT_scene_understanding, 98) \
+ _(XR_MSFT_scene_understanding_serialization, 99) \
+ _(XR_FB_display_refresh_rate, 102) \
+ _(XR_HTC_vive_cosmos_controller_interaction, 103) \
+ _(XR_HTCX_vive_tracker_interaction, 104) \
+ _(XR_HTC_facial_tracking, 105) \
+ _(XR_HTC_vive_focus3_controller_interaction, 106) \
+ _(XR_HTC_hand_interaction, 107) \
+ _(XR_HTC_vive_wrist_tracker_interaction, 108) \
+ _(XR_FB_color_space, 109) \
+ _(XR_FB_hand_tracking_mesh, 111) \
+ _(XR_FB_hand_tracking_aim, 112) \
+ _(XR_FB_hand_tracking_capsules, 113) \
+ _(XR_FB_spatial_entity, 114) \
+ _(XR_FB_foveation, 115) \
+ _(XR_FB_foveation_configuration, 116) \
+ _(XR_FB_keyboard_tracking, 117) \
+ _(XR_FB_triangle_mesh, 118) \
+ _(XR_FB_passthrough, 119) \
+ _(XR_FB_render_model, 120) \
+ _(XR_KHR_binding_modification, 121) \
+ _(XR_VARJO_foveated_rendering, 122) \
+ _(XR_VARJO_composition_layer_depth_test, 123) \
+ _(XR_VARJO_environment_depth_estimation, 124) \
+ _(XR_VARJO_marker_tracking, 125) \
+ _(XR_VARJO_view_offset, 126) \
+ _(XR_MSFT_spatial_anchor_persistence, 143) \
+ _(XR_ULTRALEAP_hand_tracking_forearm, 150) \
+ _(XR_FB_spatial_entity_query, 157) \
+ _(XR_FB_spatial_entity_storage, 159) \
+ _(XR_OCULUS_audio_device_guid, 160) \
+ _(XR_FB_foveation_vulkan, 161) \
+ _(XR_FB_swapchain_update_state_android_surface, 162) \
+ _(XR_FB_swapchain_update_state_opengl_es, 163) \
+ _(XR_FB_swapchain_update_state_vulkan, 164) \
+ _(XR_KHR_swapchain_usage_input_attachment_bit, 166) \
+ _(XR_FB_space_warp, 172) \
+ _(XR_ALMALENCE_digital_lens_control, 197) \
+ _(XR_FB_spatial_entity_container, 200) \
+ _(XR_FB_passthrough_keyboard_hands, 204) \
+ _(XR_FB_composition_layer_settings, 205) \
+ _(XR_META_vulkan_swapchain_create_info, 228) \
+ _(XR_META_performance_metrics, 233) \
+ _(XR_EXT_uuid, 300) \
+
+
+#endif
+
diff --git a/thirdparty/openxr/src/.clang-format b/thirdparty/openxr/src/.clang-format
new file mode 100644
index 0000000000..36546cab92
--- /dev/null
+++ b/thirdparty/openxr/src/.clang-format
@@ -0,0 +1,10 @@
+---
+# Copyright (c) 2017-2022, The Khronos Group Inc.
+#
+# SPDX-License-Identifier: Apache-2.0
+# Use defaults from the Google style with the following exceptions:
+BasedOnStyle: Google
+IndentWidth: 4
+ColumnLimit: 132
+SortIncludes: false
+...
diff --git a/thirdparty/openxr/src/common/extra_algorithms.h b/thirdparty/openxr/src/common/extra_algorithms.h
new file mode 100644
index 0000000000..64af4d08ff
--- /dev/null
+++ b/thirdparty/openxr/src/common/extra_algorithms.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+/*!
+ * @file
+ *
+ * Additional functions along the lines of the standard library algorithms.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <vector>
+
+/// Like std::remove_if, except it works on associative containers and it actually removes this.
+///
+/// The iterator stuff in here is subtle - .erase() invalidates only that iterator, but it returns a non-invalidated iterator to the
+/// next valid element which we can use instead of incrementing.
+template <typename T, typename Pred>
+static inline void map_erase_if(T &container, Pred &&predicate) {
+ for (auto it = container.begin(); it != container.end();) {
+ if (predicate(*it)) {
+ it = container.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+/*!
+ * Moves all elements matching the predicate to the end of the vector then erases them.
+ *
+ * Combines the two parts of the erase-remove idiom to simplify things and avoid accidentally using the wrong erase overload.
+ */
+template <typename T, typename Alloc, typename Pred>
+static inline void vector_remove_if_and_erase(std::vector<T, Alloc> &vec, Pred &&predicate) {
+ auto b = vec.begin();
+ auto e = vec.end();
+ vec.erase(std::remove_if(b, e, std::forward<Pred>(predicate)), e);
+}
diff --git a/thirdparty/openxr/src/common/filesystem_utils.cpp b/thirdparty/openxr/src/common/filesystem_utils.cpp
new file mode 100644
index 0000000000..d3d4182fb9
--- /dev/null
+++ b/thirdparty/openxr/src/common/filesystem_utils.cpp
@@ -0,0 +1,322 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>
+// Nat Brown <natb@valvesoftware.com>
+//
+
+#include "filesystem_utils.hpp"
+
+#include "platform_utils.hpp"
+
+#include <cstring>
+#include <string>
+
+#if defined DISABLE_STD_FILESYSTEM
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 0
+
+#else
+#include "stdfs_conditions.h"
+#endif
+
+#if USE_FINAL_FS == 1
+#include <filesystem>
+#define FS_PREFIX std::filesystem
+#elif USE_EXPERIMENTAL_FS == 1
+#include <experimental/filesystem>
+#define FS_PREFIX std::experimental::filesystem
+#elif defined(XR_USE_PLATFORM_WIN32)
+// Windows fallback includes
+#include <stdint.h>
+#include <direct.h>
+#else
+// Linux/Apple fallback includes
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+#endif
+
+#if defined(XR_USE_PLATFORM_WIN32)
+#define PATH_SEPARATOR ';'
+#define DIRECTORY_SYMBOL '\\'
+#define ALTERNATE_DIRECTORY_SYMBOL '/'
+#else
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+#endif
+
+#if (USE_FINAL_FS == 1) || (USE_EXPERIMENTAL_FS == 1)
+// We can use one of the C++ filesystem packages
+
+bool FileSysUtilsIsRegularFile(const std::string& path) { return FS_PREFIX::is_regular_file(path); }
+
+bool FileSysUtilsIsDirectory(const std::string& path) { return FS_PREFIX::is_directory(path); }
+
+bool FileSysUtilsPathExists(const std::string& path) { return FS_PREFIX::exists(path); }
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) {
+ FS_PREFIX::path file_path(path);
+ return file_path.is_absolute();
+}
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ FS_PREFIX::path cur_path = FS_PREFIX::current_path();
+ path = cur_path.string();
+ return true;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ FS_PREFIX::path path_var(file_path);
+ parent_path = path_var.parent_path().string();
+ return true;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ absolute = FS_PREFIX::absolute(path).string();
+ return true;
+}
+
+bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
+#if defined(XR_USE_PLATFORM_WIN32)
+ // std::filesystem::canonical fails on UWP and must be avoided. Further, PathCchCanonicalize is not available on Windows 7 and
+ // PathCanonicalizeW is not available on UWP. However, symbolic links are not important on Windows since the loader uses the
+ // registry for indirection instead, and so this function can be a no-op on Windows.
+ canonical = path;
+#else
+ canonical = FS_PREFIX::canonical(path).string();
+#endif
+ return true;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ FS_PREFIX::path parent_path(parent);
+ FS_PREFIX::path child_path(child);
+ FS_PREFIX::path full_path = parent_path / child_path;
+ combined = full_path.string();
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ for (auto& dir_iter : FS_PREFIX::directory_iterator(path)) {
+ files.push_back(dir_iter.path().filename().string());
+ }
+ return true;
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+// For pre C++17 compiler that doesn't support experimental filesystem
+
+bool FileSysUtilsIsRegularFile(const std::string& path) {
+ const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+bool FileSysUtilsIsDirectory(const std::string& path) {
+ const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
+ return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+bool FileSysUtilsPathExists(const std::string& path) {
+ return (GetFileAttributesW(utf8_to_wide(path).c_str()) != INVALID_FILE_ATTRIBUTES);
+}
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) {
+ bool pathStartsWithDir = (path.size() >= 1) && ((path[0] == DIRECTORY_SYMBOL) || (path[0] == ALTERNATE_DIRECTORY_SYMBOL));
+
+ bool pathStartsWithDrive =
+ (path.size() >= 3) && (path[1] == ':' && (path[2] == DIRECTORY_SYMBOL || path[2] == ALTERNATE_DIRECTORY_SYMBOL));
+
+ return pathStartsWithDir || pathStartsWithDrive;
+}
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ wchar_t tmp_path[MAX_PATH];
+ if (nullptr != _wgetcwd(tmp_path, MAX_PATH - 1)) {
+ path = wide_to_utf8(tmp_path);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ std::string full_path;
+ if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
+ std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
+ parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ wchar_t tmp_path[MAX_PATH];
+ if (0 != GetFullPathNameW(utf8_to_wide(path).c_str(), MAX_PATH, tmp_path, NULL)) {
+ absolute = wide_to_utf8(tmp_path);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& absolute) {
+ // PathCchCanonicalize is not available on Windows 7 and PathCanonicalizeW is not available on UWP. However, symbolic links are
+ // not important on Windows since the loader uses the registry for indirection instead, and so this function can be a no-op on
+ // Windows.
+ absolute = path;
+ return true;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ std::string::size_type parent_len = parent.length();
+ if (0 == parent_len || "." == parent || ".\\" == parent || "./" == parent) {
+ combined = child;
+ return true;
+ }
+ char last_char = parent[parent_len - 1];
+ if ((last_char == DIRECTORY_SYMBOL) || (last_char == ALTERNATE_DIRECTORY_SYMBOL)) {
+ parent_len--;
+ }
+ combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ std::string searchPath;
+ FileSysUtilsCombinePaths(path, "*", searchPath);
+
+ WIN32_FIND_DATAW file_data;
+ HANDLE file_handle = FindFirstFileW(utf8_to_wide(searchPath).c_str(), &file_data);
+ if (file_handle != INVALID_HANDLE_VALUE) {
+ do {
+ if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ files.push_back(wide_to_utf8(file_data.cFileName));
+ }
+ } while (FindNextFileW(file_handle, &file_data));
+ return true;
+ }
+ return false;
+}
+
+#else // XR_OS_LINUX/XR_OS_APPLE fallback
+
+// simple POSIX-compatible implementation of the <filesystem> pieces used by OpenXR
+
+bool FileSysUtilsIsRegularFile(const std::string& path) {
+ struct stat path_stat;
+ stat(path.c_str(), &path_stat);
+ return S_ISREG(path_stat.st_mode);
+}
+
+bool FileSysUtilsIsDirectory(const std::string& path) {
+ struct stat path_stat;
+ stat(path.c_str(), &path_stat);
+ return S_ISDIR(path_stat.st_mode);
+}
+
+bool FileSysUtilsPathExists(const std::string& path) { return (access(path.c_str(), F_OK) != -1); }
+
+bool FileSysUtilsIsAbsolutePath(const std::string& path) { return (path[0] == DIRECTORY_SYMBOL); }
+
+bool FileSysUtilsGetCurrentPath(std::string& path) {
+ char tmp_path[PATH_MAX];
+ if (nullptr != getcwd(tmp_path, PATH_MAX - 1)) {
+ path = tmp_path;
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
+ std::string full_path;
+ if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
+ std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
+ parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
+ // canonical path is absolute
+ return FileSysUtilsGetCanonicalPath(path, absolute);
+}
+
+bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
+ char buf[PATH_MAX];
+ if (nullptr != realpath(path.c_str(), buf)) {
+ canonical = buf;
+ return true;
+ }
+ return false;
+}
+
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
+ std::string::size_type parent_len = parent.length();
+ if (0 == parent_len || "." == parent || "./" == parent) {
+ combined = child;
+ return true;
+ }
+ char last_char = parent[parent_len - 1];
+ if (last_char == DIRECTORY_SYMBOL) {
+ parent_len--;
+ }
+ combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
+ return true;
+}
+
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
+ std::string::size_type start = 0;
+ std::string::size_type location = path_list.find(PATH_SEPARATOR);
+ while (location != std::string::npos) {
+ paths.push_back(path_list.substr(start, location));
+ start = location + 1;
+ location = path_list.find(PATH_SEPARATOR, start);
+ }
+ paths.push_back(path_list.substr(start, location));
+ return true;
+}
+
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
+ DIR* dir = opendir(path.c_str());
+ if (dir == nullptr) {
+ return false;
+ }
+ struct dirent* entry;
+ while ((entry = readdir(dir)) != nullptr) {
+ files.emplace_back(entry->d_name);
+ }
+ closedir(dir);
+ return true;
+}
+
+#endif
diff --git a/thirdparty/openxr/src/common/filesystem_utils.hpp b/thirdparty/openxr/src/common/filesystem_utils.hpp
new file mode 100644
index 0000000000..4a5c987e7b
--- /dev/null
+++ b/thirdparty/openxr/src/common/filesystem_utils.hpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+// Determine if the path indicates a regular file (not a directory or symbolic link)
+bool FileSysUtilsIsRegularFile(const std::string& path);
+
+// Determine if the path indicates a directory
+bool FileSysUtilsIsDirectory(const std::string& path);
+
+// Determine if the provided path exists on the filesystem
+bool FileSysUtilsPathExists(const std::string& path);
+
+// Get the current directory
+bool FileSysUtilsGetCurrentPath(std::string& path);
+
+// Get the parent path of a file
+bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path);
+
+// Determine if the provided path is an absolute path
+bool FileSysUtilsIsAbsolutePath(const std::string& path);
+
+// Get the absolute path for a provided file
+bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute);
+
+// Get the absolute path for a provided file
+bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical);
+
+// Combine a parent and child directory
+bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined);
+
+// Parse out individual paths in a path list
+bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths);
+
+// Record all the filenames for files found in the provided path.
+bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files);
diff --git a/thirdparty/openxr/src/common/hex_and_handles.h b/thirdparty/openxr/src/common/hex_and_handles.h
new file mode 100644
index 0000000000..341013d32b
--- /dev/null
+++ b/thirdparty/openxr/src/common/hex_and_handles.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+/*!
+ * @file
+ *
+ * Some utilities, primarily for working with OpenXR handles in a generic way.
+ */
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+#include <string>
+#include <stdint.h>
+
+inline std::string to_hex(const uint8_t* const data, size_t bytes) {
+ std::string out(2 + bytes * 2, '?');
+ out[0] = '0';
+ out[1] = 'x';
+ static const char* hex = "0123456789abcdef";
+ auto ch = out.end();
+ for (size_t i = 0; i < bytes; ++i) {
+ auto b = data[i];
+ *--ch = hex[(b >> 0) & 0xf];
+ *--ch = hex[(b >> 4) & 0xf];
+ }
+ return out;
+}
+
+template <typename T>
+inline std::string to_hex(const T& data) {
+ return to_hex(reinterpret_cast<const uint8_t* const>(&data), sizeof(data));
+}
+
+#if XR_PTR_SIZE == 8
+/// Convert a handle into a same-sized integer.
+template <typename T>
+static inline uint64_t MakeHandleGeneric(T handle) {
+ return reinterpret_cast<uint64_t>(handle);
+}
+
+/// Treat an integer as a handle
+template <typename T>
+static inline T& TreatIntegerAsHandle(uint64_t& handle) {
+ return reinterpret_cast<T&>(handle);
+}
+
+/// @overload
+template <typename T>
+static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
+ return reinterpret_cast<T const&>(handle);
+}
+
+/// Does a correctly-sized integer represent a null handle?
+static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == reinterpret_cast<void*>(handle); }
+
+#else
+
+/// Convert a handle into a same-sized integer: no-op on 32-bit systems
+static inline uint64_t MakeHandleGeneric(uint64_t handle) { return handle; }
+
+/// Treat an integer as a handle: no-op on 32-bit systems
+template <typename T>
+static inline T& TreatIntegerAsHandle(uint64_t& handle) {
+ return handle;
+}
+
+/// @overload
+template <typename T>
+static inline T const& TreatIntegerAsHandle(uint64_t const& handle) {
+ return handle;
+}
+
+/// Does a correctly-sized integer represent a null handle?
+static inline bool IsIntegerNullHandle(uint64_t handle) { return XR_NULL_HANDLE == handle; }
+
+#endif
+
+/// Turns a uint64_t into a string formatted as hex.
+///
+/// The core of the HandleToHexString implementation is in here.
+inline std::string Uint64ToHexString(uint64_t val) { return to_hex(val); }
+
+/// Turns a uint32_t into a string formatted as hex.
+inline std::string Uint32ToHexString(uint32_t val) { return to_hex(val); }
+
+/// Turns an OpenXR handle into a string formatted as hex.
+template <typename T>
+inline std::string HandleToHexString(T handle) {
+ return to_hex(handle);
+}
+
+/// Turns a pointer-sized integer into a string formatted as hex.
+inline std::string UintptrToHexString(uintptr_t val) { return to_hex(val); }
+
+/// Convert a pointer to a string formatted as hex.
+template <typename T>
+inline std::string PointerToHexString(T const* ptr) {
+ return to_hex(ptr);
+}
diff --git a/thirdparty/openxr/src/common/loader_interfaces.h b/thirdparty/openxr/src/common/loader_interfaces.h
new file mode 100644
index 0000000000..9c74ed16f3
--- /dev/null
+++ b/thirdparty/openxr/src/common/loader_interfaces.h
@@ -0,0 +1,114 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Forward declare.
+typedef struct XrApiLayerCreateInfo XrApiLayerCreateInfo;
+
+// Function pointer prototype for the xrCreateApiLayerInstance function used in place of xrCreateInstance.
+// This function allows us to pass special API layer information to each layer during the process of creating an Instance.
+typedef XrResult(XRAPI_PTR *PFN_xrCreateApiLayerInstance)(const XrInstanceCreateInfo *info,
+ const XrApiLayerCreateInfo *apiLayerInfo, XrInstance *instance);
+
+// Loader/API Layer Interface versions
+// 1 - First version, introduces negotiation structure and functions
+#define XR_CURRENT_LOADER_API_LAYER_VERSION 1
+
+// Loader/Runtime Interface versions
+// 1 - First version, introduces negotiation structure and functions
+#define XR_CURRENT_LOADER_RUNTIME_VERSION 1
+
+// Version negotiation values
+typedef enum XrLoaderInterfaceStructs {
+ XR_LOADER_INTERFACE_STRUCT_UNINTIALIZED = 0,
+ XR_LOADER_INTERFACE_STRUCT_LOADER_INFO,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST,
+ XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO,
+ XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO,
+} XrLoaderInterfaceStructs;
+
+#define XR_LOADER_INFO_STRUCT_VERSION 1
+typedef struct XrNegotiateLoaderInfo {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_LOADER_INFO
+ uint32_t structVersion; // XR_LOADER_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateLoaderInfo)
+ uint32_t minInterfaceVersion;
+ uint32_t maxInterfaceVersion;
+ XrVersion minApiVersion;
+ XrVersion maxApiVersion;
+} XrNegotiateLoaderInfo;
+
+#define XR_API_LAYER_INFO_STRUCT_VERSION 1
+typedef struct XrNegotiateApiLayerRequest {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST
+ uint32_t structVersion; // XR_API_LAYER_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateApiLayerRequest)
+ uint32_t layerInterfaceVersion; // CURRENT_LOADER_API_LAYER_VERSION
+ XrVersion layerApiVersion;
+ PFN_xrGetInstanceProcAddr getInstanceProcAddr;
+ PFN_xrCreateApiLayerInstance createApiLayerInstance;
+} XrNegotiateApiLayerRequest;
+
+#define XR_RUNTIME_INFO_STRUCT_VERSION 1
+typedef struct XrNegotiateRuntimeRequest {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST
+ uint32_t structVersion; // XR_RUNTIME_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrNegotiateRuntimeRequest)
+ uint32_t runtimeInterfaceVersion; // CURRENT_LOADER_RUNTIME_VERSION
+ XrVersion runtimeApiVersion;
+ PFN_xrGetInstanceProcAddr getInstanceProcAddr;
+} XrNegotiateRuntimeRequest;
+
+// Function used to negotiate an interface betewen the loader and an API layer. Each library exposing one or
+// more API layers needs to expose at least this function.
+typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderApiLayerInterface)(const XrNegotiateLoaderInfo *loaderInfo,
+ const char *apiLayerName,
+ XrNegotiateApiLayerRequest *apiLayerRequest);
+
+// Function used to negotiate an interface betewen the loader and a runtime. Each runtime should expose
+// at least this function.
+typedef XrResult(XRAPI_PTR *PFN_xrNegotiateLoaderRuntimeInterface)(const XrNegotiateLoaderInfo *loaderInfo,
+ XrNegotiateRuntimeRequest *runtimeRequest);
+
+// Forward declare.
+typedef struct XrApiLayerNextInfo XrApiLayerNextInfo;
+
+#define XR_API_LAYER_NEXT_INFO_STRUCT_VERSION 1
+struct XrApiLayerNextInfo {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO
+ uint32_t structVersion; // XR_API_LAYER_NEXT_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrApiLayerNextInfo)
+ char layerName[XR_MAX_API_LAYER_NAME_SIZE]; // Name of API layer which should receive this info
+ PFN_xrGetInstanceProcAddr nextGetInstanceProcAddr; // Pointer to next API layer's xrGetInstanceProcAddr
+ PFN_xrCreateApiLayerInstance nextCreateApiLayerInstance; // Pointer to next API layer's xrCreateApiLayerInstance
+ XrApiLayerNextInfo *next; // Pointer to the next API layer info in the sequence
+};
+
+#define XR_API_LAYER_MAX_SETTINGS_PATH_SIZE 512
+#define XR_API_LAYER_CREATE_INFO_STRUCT_VERSION 1
+typedef struct XrApiLayerCreateInfo {
+ XrLoaderInterfaceStructs structType; // XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO
+ uint32_t structVersion; // XR_API_LAYER_CREATE_INFO_STRUCT_VERSION
+ size_t structSize; // sizeof(XrApiLayerCreateInfo)
+ void *loaderInstance; // Pointer to the LoaderInstance class
+ char settings_file_location[XR_API_LAYER_MAX_SETTINGS_PATH_SIZE]; // Location to the found settings file (or empty '\0')
+ XrApiLayerNextInfo *nextInfo; // Pointer to the next API layer's Info
+} XrApiLayerCreateInfo;
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/thirdparty/openxr/src/common/object_info.cpp b/thirdparty/openxr/src/common/object_info.cpp
new file mode 100644
index 0000000000..95b5aaf404
--- /dev/null
+++ b/thirdparty/openxr/src/common/object_info.cpp
@@ -0,0 +1,276 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>
+// Ryan Pavlik <ryan.pavlik@collabora.com>
+// Dave Houlton <daveh@lunarg.com>
+//
+
+#include "object_info.h"
+
+#include "extra_algorithms.h"
+#include "hex_and_handles.h"
+
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "memory.h"
+
+std::string XrSdkLogObjectInfo::ToString() const {
+ std::ostringstream oss;
+ oss << Uint64ToHexString(handle);
+ if (!name.empty()) {
+ oss << " (" << name << ")";
+ }
+ return oss.str();
+}
+
+void ObjectInfoCollection::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
+ // If name is empty, we should erase it
+ if (object_name.empty()) {
+ RemoveObject(object_handle, object_type);
+ return;
+ }
+
+ // Otherwise, add it or update the name
+ XrSdkLogObjectInfo new_obj = {object_handle, object_type};
+
+ // If it already exists, update the name
+ auto lookup_info = LookUpStoredObjectInfo(new_obj);
+ if (lookup_info != nullptr) {
+ lookup_info->name = object_name;
+ return;
+ }
+
+ // It doesn't exist, so add a new info block
+ new_obj.name = object_name;
+ object_info_.push_back(new_obj);
+}
+
+void ObjectInfoCollection::RemoveObject(uint64_t object_handle, XrObjectType object_type) {
+ vector_remove_if_and_erase(
+ object_info_, [=](XrSdkLogObjectInfo const& info) { return info.handle == object_handle && info.type == object_type; });
+}
+
+XrSdkLogObjectInfo const* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const {
+ auto e = object_info_.end();
+ auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });
+ if (it != e) {
+ return &(*it);
+ }
+ return nullptr;
+}
+
+XrSdkLogObjectInfo* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) {
+ auto e = object_info_.end();
+ auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });
+ if (it != e) {
+ return &(*it);
+ }
+ return nullptr;
+}
+
+bool ObjectInfoCollection::LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const {
+ auto info_lookup = LookUpStoredObjectInfo(info.objectHandle, info.objectType);
+ if (info_lookup != nullptr) {
+ info.objectName = info_lookup->name.c_str();
+ return true;
+ }
+ return false;
+}
+
+bool ObjectInfoCollection::LookUpObjectName(XrSdkLogObjectInfo& info) const {
+ auto info_lookup = LookUpStoredObjectInfo(info);
+ if (info_lookup != nullptr) {
+ info.name = info_lookup->name;
+ return true;
+ }
+ return false;
+}
+
+static std::vector<XrDebugUtilsObjectNameInfoEXT> PopulateObjectNameInfo(std::vector<XrSdkLogObjectInfo> const& obj) {
+ std::vector<XrDebugUtilsObjectNameInfoEXT> ret;
+ ret.reserve(obj.size());
+ std::transform(obj.begin(), obj.end(), std::back_inserter(ret), [](XrSdkLogObjectInfo const& info) {
+ return XrDebugUtilsObjectNameInfoEXT{XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, nullptr, info.type, info.handle,
+ info.name.c_str()};
+ });
+ return ret;
+}
+
+NamesAndLabels::NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab)
+ : sdk_objects(std::move(obj)), objects(PopulateObjectNameInfo(sdk_objects)), labels(std::move(lab)) {}
+
+void NamesAndLabels::PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& callback_data) const {
+ callback_data.objects = objects.empty() ? nullptr : const_cast<XrDebugUtilsObjectNameInfoEXT*>(objects.data());
+ callback_data.objectCount = static_cast<uint32_t>(objects.size());
+ callback_data.sessionLabels = labels.empty() ? nullptr : const_cast<XrDebugUtilsLabelEXT*>(labels.data());
+ callback_data.sessionLabelCount = static_cast<uint32_t>(labels.size());
+}
+
+void DebugUtilsData::LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const {
+ auto session_label_iterator = session_labels_.find(session);
+ if (session_label_iterator != session_labels_.end()) {
+ auto& XrSdkSessionLabels = *session_label_iterator->second;
+ // Copy the debug utils labels in reverse order in the the labels vector.
+ std::transform(XrSdkSessionLabels.rbegin(), XrSdkSessionLabels.rend(), std::back_inserter(labels),
+ [](XrSdkSessionLabelPtr const& label) { return label->debug_utils_label; });
+ }
+}
+
+XrSdkSessionLabel::XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual)
+ : label_name(label_info.labelName), debug_utils_label(label_info), is_individual_label(individual) {
+ // Update the c string pointer to the one we hold.
+ debug_utils_label.labelName = label_name.c_str();
+}
+
+XrSdkSessionLabelPtr XrSdkSessionLabel::make(const XrDebugUtilsLabelEXT& label_info, bool individual) {
+ XrSdkSessionLabelPtr ret(new XrSdkSessionLabel(label_info, individual));
+ return ret;
+}
+void DebugUtilsData::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
+ object_info_.AddObjectName(object_handle, object_type, object_name);
+}
+
+// We always want to remove the old individual label before we do anything else.
+// So, do that in it's own method
+void DebugUtilsData::RemoveIndividualLabel(XrSdkSessionLabelList& label_vec) {
+ if (!label_vec.empty() && label_vec.back()->is_individual_label) {
+ label_vec.pop_back();
+ }
+}
+
+XrSdkSessionLabelList* DebugUtilsData::GetSessionLabelList(XrSession session) {
+ auto session_label_iterator = session_labels_.find(session);
+ if (session_label_iterator == session_labels_.end()) {
+ return nullptr;
+ }
+ return session_label_iterator->second.get();
+}
+
+XrSdkSessionLabelList& DebugUtilsData::GetOrCreateSessionLabelList(XrSession session) {
+ XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr == nullptr) {
+ std::unique_ptr<XrSdkSessionLabelList> vec(new XrSdkSessionLabelList);
+ vec_ptr = vec.get();
+ session_labels_[session] = std::move(vec);
+ }
+ return *vec_ptr;
+}
+
+void DebugUtilsData::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info) {
+ auto& vec = GetOrCreateSessionLabelList(session);
+
+ // Individual labels do not stay around in the transition into a new label region
+ RemoveIndividualLabel(vec);
+
+ // Start the new label region
+ vec.emplace_back(XrSdkSessionLabel::make(label_info, false));
+}
+
+void DebugUtilsData::EndLabelRegion(XrSession session) {
+ XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr == nullptr) {
+ return;
+ }
+
+ // Individual labels do not stay around in the transition out of label region
+ RemoveIndividualLabel(*vec_ptr);
+
+ // Remove the last label region
+ if (!vec_ptr->empty()) {
+ vec_ptr->pop_back();
+ }
+}
+
+void DebugUtilsData::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info) {
+ auto& vec = GetOrCreateSessionLabelList(session);
+
+ // Remove any individual layer that might already be there
+ RemoveIndividualLabel(vec);
+
+ // Insert a new individual label
+ vec.emplace_back(XrSdkSessionLabel::make(label_info, true));
+}
+
+void DebugUtilsData::DeleteObject(uint64_t object_handle, XrObjectType object_type) {
+ object_info_.RemoveObject(object_handle, object_type);
+
+ if (object_type == XR_OBJECT_TYPE_SESSION) {
+ auto session = TreatIntegerAsHandle<XrSession>(object_handle);
+ XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);
+ if (vec_ptr != nullptr) {
+ session_labels_.erase(session);
+ }
+ }
+}
+
+void DebugUtilsData::DeleteSessionLabels(XrSession session) { session_labels_.erase(session); }
+
+NamesAndLabels DebugUtilsData::PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const {
+ std::vector<XrDebugUtilsLabelEXT> labels;
+ for (auto& obj : objects) {
+ // Check for any names that have been associated with the objects and set them up here
+ object_info_.LookUpObjectName(obj);
+ // If this is a session, see if there are any labels associated with it for us to add
+ // to the callback content.
+ if (XR_OBJECT_TYPE_SESSION == obj.type) {
+ LookUpSessionLabels(obj.GetTypedHandle<XrSession>(), labels);
+ }
+ }
+
+ return {objects, labels};
+}
+
+void DebugUtilsData::WrapCallbackData(AugmentedCallbackData* aug_data,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) const {
+ // If there's nothing to add, just return the original data as the augmented copy
+ aug_data->exported_data = callback_data;
+ if (object_info_.Empty() || callback_data->objectCount == 0) {
+ return;
+ }
+
+ // Inspect each of the callback objects
+ bool name_found = false;
+ for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {
+ auto& current_obj = callback_data->objects[obj];
+ name_found |= (nullptr != object_info_.LookUpStoredObjectInfo(current_obj.objectHandle, current_obj.objectType));
+
+ // If this is a session, record any labels associated with it
+ if (XR_OBJECT_TYPE_SESSION == current_obj.objectType) {
+ XrSession session = TreatIntegerAsHandle<XrSession>(current_obj.objectHandle);
+ LookUpSessionLabels(session, aug_data->labels);
+ }
+ }
+
+ // If we found nothing to add, return the original data
+ if (!name_found && aug_data->labels.empty()) {
+ return;
+ }
+
+ // Found additional data - modify an internal copy and return that as the exported data
+ memcpy(&aug_data->modified_data, callback_data, sizeof(XrDebugUtilsMessengerCallbackDataEXT));
+ aug_data->new_objects.assign(callback_data->objects, callback_data->objects + callback_data->objectCount);
+
+ // Record (overwrite) the names of all incoming objects provided in our internal list
+ for (auto& obj : aug_data->new_objects) {
+ object_info_.LookUpObjectName(obj);
+ }
+
+ // Update local copy & point export to it
+ aug_data->modified_data.objects = aug_data->new_objects.data();
+ aug_data->modified_data.sessionLabelCount = static_cast<uint32_t>(aug_data->labels.size());
+ aug_data->modified_data.sessionLabels = aug_data->labels.empty() ? nullptr : aug_data->labels.data();
+ aug_data->exported_data = &aug_data->modified_data;
+ return;
+}
diff --git a/thirdparty/openxr/src/common/object_info.h b/thirdparty/openxr/src/common/object_info.h
new file mode 100644
index 0000000000..8e9742b605
--- /dev/null
+++ b/thirdparty/openxr/src/common/object_info.h
@@ -0,0 +1,229 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// Copyright (c) 2019 Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>, Ryan Pavlik <ryan.pavlik@collabora.com
+//
+/*!
+ * @file
+ *
+ * The core of an XR_EXT_debug_utils implementation, used/shared by the loader and several SDK layers.
+ */
+
+#pragma once
+
+#include "hex_and_handles.h"
+
+#include <openxr/openxr.h>
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+struct XrSdkGenericObject {
+ //! Type-erased handle value
+ uint64_t handle;
+
+ //! Kind of object this handle refers to
+ XrObjectType type;
+ /// Un-erase the type of the handle and get it properly typed again.
+ ///
+ /// Note: Does not check the type before doing it!
+ template <typename HandleType>
+ HandleType& GetTypedHandle() {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ //! @overload
+ template <typename HandleType>
+ HandleType const& GetTypedHandle() const {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ //! Create from a typed handle and object type
+ template <typename T>
+ XrSdkGenericObject(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
+
+ //! Create from an untyped handle value (integer) and object type
+ XrSdkGenericObject(uint64_t h, XrObjectType t) : handle(h), type(t) {}
+};
+
+struct XrSdkLogObjectInfo {
+ //! Type-erased handle value
+ uint64_t handle;
+
+ //! Kind of object this handle refers to
+ XrObjectType type;
+
+ //! To be assigned by the application - not part of this object's identity
+ std::string name;
+
+ /// Un-erase the type of the handle and get it properly typed again.
+ ///
+ /// Note: Does not check the type before doing it!
+ template <typename HandleType>
+ HandleType& GetTypedHandle() {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ //! @overload
+ template <typename HandleType>
+ HandleType const& GetTypedHandle() const {
+ return TreatIntegerAsHandle<HandleType&>(handle);
+ }
+
+ XrSdkLogObjectInfo() = default;
+
+ //! Create from a typed handle and object type
+ template <typename T>
+ XrSdkLogObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
+
+ //! Create from an untyped handle value (integer) and object type
+ XrSdkLogObjectInfo(uint64_t h, XrObjectType t) : handle(h), type(t) {}
+ //! Create from an untyped handle value (integer), object type, and name
+ XrSdkLogObjectInfo(uint64_t h, XrObjectType t, const char* n) : handle(h), type(t), name(n == nullptr ? "" : n) {}
+
+ std::string ToString() const;
+};
+
+//! True if the two object infos have the same handle value and handle type
+static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrSdkLogObjectInfo const& b) {
+ return a.handle == b.handle && a.type == b.type;
+}
+
+//! @overload
+static inline bool Equivalent(XrDebugUtilsObjectNameInfoEXT const& a, XrSdkLogObjectInfo const& b) {
+ return a.objectHandle == b.handle && a.objectType == b.type;
+}
+
+//! @overload
+static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrDebugUtilsObjectNameInfoEXT const& b) { return Equivalent(b, a); }
+
+/// Object info registered with calls to xrSetDebugUtilsObjectNameEXT
+class ObjectInfoCollection {
+ public:
+ void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
+
+ void RemoveObject(uint64_t object_handle, XrObjectType object_type);
+
+ //! Find the stored object info, if any, matching handle and type.
+ //! Return nullptr if not found.
+ XrSdkLogObjectInfo const* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const;
+
+ //! Find the stored object info, if any, matching handle and type.
+ //! Return nullptr if not found.
+ XrSdkLogObjectInfo* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info);
+
+ //! Find the stored object info, if any.
+ //! Return nullptr if not found.
+ XrSdkLogObjectInfo const* LookUpStoredObjectInfo(uint64_t handle, XrObjectType type) const {
+ return LookUpStoredObjectInfo({handle, type});
+ }
+
+ //! Find the object name, if any, and update debug utils info accordingly.
+ //! Return true if found and updated.
+ bool LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const;
+
+ //! Find the object name, if any, and update logging info accordingly.
+ //! Return true if found and updated.
+ bool LookUpObjectName(XrSdkLogObjectInfo& info) const;
+
+ //! Is the collection empty?
+ bool Empty() const { return object_info_.empty(); }
+
+ private:
+ // Object names that have been set for given objects
+ std::vector<XrSdkLogObjectInfo> object_info_;
+};
+
+struct XrSdkSessionLabel;
+using XrSdkSessionLabelPtr = std::unique_ptr<XrSdkSessionLabel>;
+using XrSdkSessionLabelList = std::vector<XrSdkSessionLabelPtr>;
+
+struct XrSdkSessionLabel {
+ static XrSdkSessionLabelPtr make(const XrDebugUtilsLabelEXT& label_info, bool individual);
+
+ std::string label_name;
+ XrDebugUtilsLabelEXT debug_utils_label;
+ bool is_individual_label;
+
+ private:
+ XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual);
+};
+
+/// The metadata for a collection of objects. Must persist unmodified during the entire debug messenger call!
+struct NamesAndLabels {
+ NamesAndLabels() = default;
+ NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab);
+ /// C++ structure owning the data (strings) backing the objects vector.
+ std::vector<XrSdkLogObjectInfo> sdk_objects;
+
+ std::vector<XrDebugUtilsObjectNameInfoEXT> objects;
+ std::vector<XrDebugUtilsLabelEXT> labels;
+
+ /// Populate the debug utils callback data structure.
+ void PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& data) const;
+ // XrDebugUtilsMessengerCallbackDataEXT MakeCallbackData() const;
+};
+
+struct AugmentedCallbackData {
+ std::vector<XrDebugUtilsLabelEXT> labels;
+ std::vector<XrDebugUtilsObjectNameInfoEXT> new_objects;
+ XrDebugUtilsMessengerCallbackDataEXT modified_data;
+ const XrDebugUtilsMessengerCallbackDataEXT* exported_data;
+};
+
+/// Tracks all the data (handle names and session labels) required to fully augment XR_EXT_debug_utils-related calls.
+class DebugUtilsData {
+ public:
+ DebugUtilsData() = default;
+
+ DebugUtilsData(const DebugUtilsData&) = delete;
+ DebugUtilsData& operator=(const DebugUtilsData&) = delete;
+
+ bool Empty() const { return object_info_.Empty() && session_labels_.empty(); }
+
+ //! Core of implementation for xrSetDebugUtilsObjectNameEXT
+ void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
+
+ /// Core of implementation for xrSessionBeginDebugUtilsLabelRegionEXT
+ void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info);
+
+ /// Core of implementation for xrSessionEndDebugUtilsLabelRegionEXT
+ void EndLabelRegion(XrSession session);
+
+ /// Core of implementation for xrSessionInsertDebugUtilsLabelEXT
+ void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info);
+
+ /// Removes all labels associated with a session - call in xrDestroySession and xrDestroyInstance (for all child sessions)
+ void DeleteSessionLabels(XrSession session);
+
+ /// Retrieve labels for the given session, if any, and push them in reverse order on the vector.
+ void LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const;
+
+ /// Removes all data related to this object - including session labels if it's a session.
+ ///
+ /// Does not take care of handling child objects - you must do this yourself.
+ void DeleteObject(uint64_t object_handle, XrObjectType object_type);
+
+ /// Given the collection of objects, populate their names and list of labels
+ NamesAndLabels PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const;
+
+ void WrapCallbackData(AugmentedCallbackData* aug_data,
+ const XrDebugUtilsMessengerCallbackDataEXT* provided_callback_data) const;
+
+ private:
+ void RemoveIndividualLabel(XrSdkSessionLabelList& label_vec);
+ XrSdkSessionLabelList* GetSessionLabelList(XrSession session);
+ XrSdkSessionLabelList& GetOrCreateSessionLabelList(XrSession session);
+
+ // Session labels: one vector of them per session.
+ std::unordered_map<XrSession, std::unique_ptr<XrSdkSessionLabelList>> session_labels_;
+
+ // Names for objects.
+ ObjectInfoCollection object_info_;
+};
diff --git a/thirdparty/openxr/src/common/platform_utils.hpp b/thirdparty/openxr/src/common/platform_utils.hpp
new file mode 100644
index 0000000000..85d5cdab10
--- /dev/null
+++ b/thirdparty/openxr/src/common/platform_utils.hpp
@@ -0,0 +1,345 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
+//
+
+#pragma once
+
+#include "xr_dependencies.h"
+#include <string>
+#include <stdlib.h>
+
+// OpenXR paths and registry key locations
+#define OPENXR_RELATIVE_PATH "openxr/"
+#define OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/implicit.d"
+#define OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH "/api_layers/explicit.d"
+#ifdef XR_OS_WINDOWS
+#define OPENXR_REGISTRY_LOCATION "SOFTWARE\\Khronos\\OpenXR\\"
+#define OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Implicit"
+#define OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION "\\ApiLayers\\Explicit"
+#endif
+
+// OpenXR Loader environment variables of interest
+#define OPENXR_RUNTIME_JSON_ENV_VAR "XR_RUNTIME_JSON"
+#define OPENXR_API_LAYER_PATH_ENV_VAR "XR_API_LAYER_PATH"
+
+// This is a CMake generated file with #defines for any functions/includes
+// that it found present and build-time configuration.
+// If you don't have this file, on non-Windows you'll need to define
+// one of HAVE_SECURE_GETENV or HAVE___SECURE_GETENV depending on which
+// of secure_getenv or __secure_getenv are present
+#ifdef OPENXR_HAVE_COMMON_CONFIG
+#include "common_config.h"
+#endif // OPENXR_HAVE_COMMON_CONFIG
+
+// Environment variables
+#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <iostream>
+
+namespace detail {
+
+static inline char* ImplGetEnv(const char* name) { return getenv(name); }
+
+static inline int ImplSetEnv(const char* name, const char* value, int overwrite) { return setenv(name, value, overwrite); }
+
+static inline char* ImplGetSecureEnv(const char* name) {
+#ifdef HAVE_SECURE_GETENV
+ return secure_getenv(name);
+#elif defined(HAVE___SECURE_GETENV)
+ return __secure_getenv(name);
+#else
+#pragma message( \
+ "Warning: Falling back to non-secure getenv for environmental" \
+ "lookups! Consider updating to a different libc.")
+
+ return ImplGetEnv(name);
+#endif
+}
+} // namespace detail
+
+#endif // defined(XR_OS_LINUX) || defined(XR_OS_APPLE)
+#if defined(XR_OS_LINUX)
+
+static inline std::string PlatformUtilsGetEnv(const char* name) {
+ auto str = detail::ImplGetEnv(name);
+ if (str == nullptr) {
+ return {};
+ }
+ return str;
+}
+
+static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
+ auto str = detail::ImplGetSecureEnv(name);
+ if (str == nullptr) {
+ return {};
+ }
+ return str;
+}
+
+static inline bool PlatformUtilsGetEnvSet(const char* name) { return detail::ImplGetEnv(name) != nullptr; }
+
+static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
+ const int shouldOverwrite = 1;
+ int result = detail::ImplSetEnv(name, value, shouldOverwrite);
+ return (result == 0);
+}
+
+#elif defined(XR_OS_APPLE)
+
+static inline std::string PlatformUtilsGetEnv(const char* name) {
+ auto str = detail::ImplGetEnv(name);
+ if (str == nullptr) {
+ return {};
+ }
+ return str;
+}
+
+static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
+ auto str = detail::ImplGetSecureEnv(name);
+ if (str == nullptr) {
+ return {};
+ }
+ return str;
+}
+
+static inline bool PlatformUtilsGetEnvSet(const char* name) { return detail::ImplGetEnv(name) != nullptr; }
+
+static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
+ const int shouldOverwrite = 1;
+ int result = detail::ImplSetEnv(name, value, shouldOverwrite);
+ return (result == 0);
+}
+
+// Prefix for the Apple global runtime JSON file name
+static const std::string rt_dir_prefix = "/usr/local/share/openxr/";
+static const std::string rt_filename = "/active_runtime.json";
+
+static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
+ file_name = rt_dir_prefix;
+ file_name += std::to_string(major_version);
+ file_name += rt_filename;
+ return true;
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+#if !defined(NDEBUG)
+inline void LogError(const std::string& error) { OutputDebugStringA(error.c_str()); }
+#else
+#define LogError(x)
+#endif
+
+inline std::wstring utf8_to_wide(const std::string& utf8Text) {
+ if (utf8Text.empty()) {
+ return {};
+ }
+
+ std::wstring wideText;
+ const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
+ if (wideLength == 0) {
+ LogError("utf8_to_wide get size error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ // MultiByteToWideChar returns number of chars of the input buffer, regardless of null terminitor
+ wideText.resize(wideLength, 0);
+ wchar_t* wideString = const_cast<wchar_t*>(wideText.data()); // mutable data() only exists in c++17
+ const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideString, wideLength);
+ if (length != wideLength) {
+ LogError("utf8_to_wide convert string error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ return wideText;
+}
+
+inline std::string wide_to_utf8(const std::wstring& wideText) {
+ if (wideText.empty()) {
+ return {};
+ }
+
+ std::string narrowText;
+ int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
+ if (narrowLength == 0) {
+ LogError("wide_to_utf8 get size error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ // WideCharToMultiByte returns number of chars of the input buffer, regardless of null terminitor
+ narrowText.resize(narrowLength, 0);
+ char* narrowString = const_cast<char*>(narrowText.data()); // mutable data() only exists in c++17
+ const int length =
+ ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowString, narrowLength, nullptr, nullptr);
+ if (length != narrowLength) {
+ LogError("wide_to_utf8 convert string error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ return narrowText;
+}
+
+// Returns true if the current process has an integrity level > SECURITY_MANDATORY_MEDIUM_RID.
+static inline bool IsHighIntegrityLevel() {
+ // Execute this check once and save the value as a static bool.
+ static bool isHighIntegrityLevel = ([] {
+ HANDLE processToken;
+ if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &processToken)) {
+ // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
+ uint8_t mandatoryLabelBuffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)]{};
+ DWORD bufferSize;
+ if (GetTokenInformation(processToken, TokenIntegrityLevel, mandatoryLabelBuffer, sizeof(mandatoryLabelBuffer),
+ &bufferSize) != 0) {
+ const auto mandatoryLabel = reinterpret_cast<const TOKEN_MANDATORY_LABEL*>(mandatoryLabelBuffer);
+ if (mandatoryLabel->Label.Sid != 0) {
+ const DWORD subAuthorityCount = *GetSidSubAuthorityCount(mandatoryLabel->Label.Sid);
+ const DWORD integrityLevel = *GetSidSubAuthority(mandatoryLabel->Label.Sid, subAuthorityCount - 1);
+ CloseHandle(processToken);
+ return integrityLevel > SECURITY_MANDATORY_MEDIUM_RID;
+ }
+ }
+
+ CloseHandle(processToken);
+ }
+
+ return false;
+ })();
+
+ return isHighIntegrityLevel;
+}
+
+// Returns true if the given environment variable exists.
+// The name is a case-sensitive UTF8 string.
+static inline bool PlatformUtilsGetEnvSet(const char* name) {
+ const std::wstring wname = utf8_to_wide(name);
+ const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
+ // GetEnvironmentVariable returns 0 when environment variable does not exist or there is an error.
+ return 0 != valSize;
+}
+
+// Returns the environment variable value for the given name.
+// Returns an empty string if the environment variable doesn't exist or if it exists but is empty.
+// Use PlatformUtilsGetEnvSet to tell if it exists.
+// The name is a case-sensitive UTF8 string.
+static inline std::string PlatformUtilsGetEnv(const char* name) {
+ const std::wstring wname = utf8_to_wide(name);
+ const DWORD valSize = ::GetEnvironmentVariableW(wname.c_str(), nullptr, 0);
+ // GetEnvironmentVariable returns 0 when environment variable does not exist or there is an error.
+ // The size includes the null-terminator, so a size of 1 is means the variable was explicitly set to empty.
+ if (valSize == 0 || valSize == 1) {
+ return {};
+ }
+
+ // GetEnvironmentVariable returns size including null terminator for "query size" call.
+ std::wstring wValue(valSize, 0);
+ wchar_t* wValueData = &wValue[0];
+
+ // GetEnvironmentVariable returns string length, excluding null terminator for "get value"
+ // call if there was enough capacity. Else it returns the required capacity (including null terminator).
+ const DWORD length = ::GetEnvironmentVariableW(wname.c_str(), wValueData, (DWORD)wValue.size());
+ if ((length == 0) || (length >= wValue.size())) { // If error or the variable increased length between calls...
+ LogError("GetEnvironmentVariable get value error: " + std::to_string(::GetLastError()));
+ return {};
+ }
+
+ wValue.resize(length); // Strip the null terminator.
+
+ return wide_to_utf8(wValue);
+}
+
+// Acts the same as PlatformUtilsGetEnv except returns an empty string if IsHighIntegrityLevel.
+static inline std::string PlatformUtilsGetSecureEnv(const char* name) {
+ // Do not allow high integrity processes to act on data that can be controlled by medium integrity processes.
+ if (IsHighIntegrityLevel()) {
+ return {};
+ }
+
+ // No secure version for Windows so the above integrity check is needed.
+ return PlatformUtilsGetEnv(name);
+}
+
+// Sets an environment variable via UTF8 strings.
+// The name is case-sensitive.
+// Overwrites the variable if it already exists.
+// Returns true if it could be set.
+static inline bool PlatformUtilsSetEnv(const char* name, const char* value) {
+ const std::wstring wname = utf8_to_wide(name);
+ const std::wstring wvalue = utf8_to_wide(value);
+ BOOL result = ::SetEnvironmentVariableW(wname.c_str(), wvalue.c_str());
+ return (result != 0);
+}
+
+#elif defined(XR_OS_ANDROID)
+
+static inline bool PlatformUtilsGetEnvSet(const char* /* name */) {
+ // Stub func
+ return false;
+}
+
+static inline std::string PlatformUtilsGetEnv(const char* /* name */) {
+ // Stub func
+ return {};
+}
+
+static inline std::string PlatformUtilsGetSecureEnv(const char* /* name */) {
+ // Stub func
+ return {};
+}
+
+static inline bool PlatformUtilsSetEnv(const char* /* name */, const char* /* value */) {
+ // Stub func
+ return false;
+}
+
+#include <sys/stat.h>
+
+// Intended to be only used as a fallback on Android, with a more open, "native" technique used in most cases
+static inline bool PlatformGetGlobalRuntimeFileName(uint16_t major_version, std::string& file_name) {
+ // Prefix for the runtime JSON file name
+ static const char* rt_dir_prefixes[] = {"/oem", "/vendor", "/system"};
+ static const std::string rt_filename = "/active_runtime.json";
+ static const std::string subdir = "/etc/openxr/";
+ for (const auto prefix : rt_dir_prefixes) {
+ auto path = prefix + subdir + std::to_string(major_version) + rt_filename;
+ struct stat buf;
+ if (0 == stat(path.c_str(), &buf)) {
+ file_name = path;
+ return true;
+ }
+ }
+ return false;
+}
+#else // Not Linux, Apple, nor Windows
+
+static inline bool PlatformUtilsGetEnvSet(const char* /* name */) {
+ // Stub func
+ return false;
+}
+
+static inline std::string PlatformUtilsGetEnv(const char* /* name */) {
+ // Stub func
+ return {};
+}
+
+static inline std::string PlatformUtilsGetSecureEnv(const char* /* name */) {
+ // Stub func
+ return {};
+}
+
+static inline bool PlatformUtilsSetEnv(const char* /* name */, const char* /* value */) {
+ // Stub func
+ return false;
+}
+
+static inline bool PlatformGetGlobalRuntimeFileName(uint16_t /* major_version */, std::string const& /* file_name */) {
+ // Stub func
+ return false;
+}
+
+#endif
diff --git a/thirdparty/openxr/src/common/stdfs_conditions.h b/thirdparty/openxr/src/common/stdfs_conditions.h
new file mode 100644
index 0000000000..6dc18cc620
--- /dev/null
+++ b/thirdparty/openxr/src/common/stdfs_conditions.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+#ifndef _STDFS_CONDITIONS_H
+#define _STDFS_CONDITIONS_H
+
+// If the C++ macro is set to the version containing C++17, it must support
+// the final C++17 package
+#if __cplusplus >= 201703L
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+
+#elif defined(_MSC_VER) && _MSC_VER >= 1900
+
+#if defined(_HAS_CXX17) && _HAS_CXX17
+// When MSC supports c++17 use <filesystem> package.
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+#endif // !_HAS_CXX17
+
+// GCC supports the experimental filesystem items starting in GCC 6
+#elif (__GNUC__ >= 6)
+#define USE_EXPERIMENTAL_FS 1
+#define USE_FINAL_FS 0
+
+// If Clang, check for feature support
+#elif defined(__clang__) && (__cpp_lib_filesystem || __cpp_lib_experimental_filesystem)
+#if __cpp_lib_filesystem
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 1
+#else
+#define USE_EXPERIMENTAL_FS 1
+#define USE_FINAL_FS 0
+#endif
+
+// If all above fails, fall back to standard C++ and OS-specific items
+#else
+#define USE_EXPERIMENTAL_FS 0
+#define USE_FINAL_FS 0
+#endif
+
+#endif // !_STDFS_CONDITIONS_H
diff --git a/thirdparty/openxr/src/common/xr_dependencies.h b/thirdparty/openxr/src/common/xr_dependencies.h
new file mode 100644
index 0000000000..e34527abc3
--- /dev/null
+++ b/thirdparty/openxr/src/common/xr_dependencies.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2018-2022, The Khronos Group Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// This file includes headers with types which openxr.h depends on in order
+// to compile when platforms, graphics apis, and the like are enabled.
+
+#pragma once
+
+#ifdef XR_USE_PLATFORM_ANDROID
+#include <android/native_window.h>
+#include <android/window.h>
+#include <android/native_window_jni.h>
+#endif // XR_USE_PLATFORM_ANDROID
+
+#ifdef XR_USE_PLATFORM_WIN32
+
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM))
+// Enable desktop partition APIs, such as RegOpenKeyEx, LoadLibraryEx, PathFileExists etc.
+#undef WINAPI_PARTITION_DESKTOP
+#define WINAPI_PARTITION_DESKTOP 1
+#endif
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif // !NOMINMAX
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif // !WIN32_LEAN_AND_MEAN
+
+#include <windows.h>
+#include <unknwn.h>
+
+#endif // XR_USE_PLATFORM_WIN32
+
+#ifdef XR_USE_GRAPHICS_API_D3D11
+#include <d3d11.h>
+#endif // XR_USE_GRAPHICS_API_D3D11
+
+#ifdef XR_USE_GRAPHICS_API_D3D12
+#include <d3d12.h>
+#endif // XR_USE_GRAPHICS_API_D3D12
+
+#ifdef XR_USE_PLATFORM_XLIB
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#ifdef Success
+#undef Success
+#endif // Success
+
+#ifdef Always
+#undef Always
+#endif // Always
+
+#ifdef None
+#undef None
+#endif // None
+#endif // XR_USE_PLATFORM_XLIB
+
+#ifdef XR_USE_PLATFORM_XCB
+#include <xcb/xcb.h>
+#endif // XR_USE_PLATFORM_XCB
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL
+#if defined(XR_USE_PLATFORM_XLIB) || defined(XR_USE_PLATFORM_XCB)
+#include <GL/glx.h>
+#endif // (XR_USE_PLATFORM_XLIB || XR_USE_PLATFORM_XCB)
+#ifdef XR_USE_PLATFORM_XCB
+#include <xcb/glx.h>
+#endif // XR_USE_PLATFORM_XCB
+#ifdef XR_USE_PLATFORM_MACOS
+#include <CL/cl_gl_ext.h>
+#endif // XR_USE_PLATFORM_MACOS
+#endif // XR_USE_GRAPHICS_API_OPENGL
+
+#ifdef XR_USE_GRAPHICS_API_OPENGL_ES
+#include <EGL/egl.h>
+#endif // XR_USE_GRAPHICS_API_OPENGL_ES
+
+#ifdef XR_USE_GRAPHICS_API_VULKAN
+#include <vulkan/vulkan.h>
+#endif // XR_USE_GRAPHICS_API_VULKAN
+
+#ifdef XR_USE_PLATFORM_WAYLAND
+#include "wayland-client.h"
+#endif // XR_USE_PLATFORM_WAYLAND
diff --git a/thirdparty/openxr/src/common/xr_linear.h b/thirdparty/openxr/src/common/xr_linear.h
new file mode 100644
index 0000000000..1f0e803b7a
--- /dev/null
+++ b/thirdparty/openxr/src/common/xr_linear.h
@@ -0,0 +1,787 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2016 Oculus VR, LLC.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: J.M.P. van Waveren
+//
+
+#ifndef XR_LINEAR_H_
+#define XR_LINEAR_H_
+
+#if defined(OS_LINUX_XCB) || defined(OS_LINUX_XCB_GLX) || defined(OS_LINUX_WAYLAND)
+#pragma GCC diagnostic ignored "-Wunused-function"
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
+#include <openxr/openxr.h>
+
+/*
+================================================================================================
+
+Description : Vector, matrix and quaternion math.
+Author : J.M.P. van Waveren
+Date : 12/10/2016
+Language : C99
+Format : Indent 4 spaces - no tabs.
+Copyright : Copyright (c) 2016 Oculus VR, LLC. All Rights reserved.
+
+
+DESCRIPTION
+===========
+
+All matrices are column-major.
+
+INTERFACE
+=========
+
+XrVector2f
+XrVector3f
+XrVector4f
+XrQuaternionf
+XrMatrix4x4f
+
+inline static void XrVector3f_Set(XrVector3f* v, const float value);
+inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b);
+inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value);
+inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction);
+inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor);
+inline static void XrVector3f_Normalize(XrVector3f* v);
+inline static float XrVector3f_Length(const XrVector3f* v);
+
+inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction);
+inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b;
+
+inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result);
+inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z);
+inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
+ const float degreesZ);
+inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z);
+inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
+ const XrQuaternionf* rotation, const XrVector3f* scale);
+inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, const float tanAngleLeft, const float tanAngleRight,
+ const float tanAngleUp, float const tanAngleDown, const float nearZ,
+ const float farZ);
+inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, const float fovDegreesLeft, const float fovDegreesRight,
+ const float fovDegreeUp, const float fovDegreesDown, const float nearZ,
+ const float farZ);
+inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* src);
+inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
+ const XrVector3f* maxs);
+
+inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon);
+inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon);
+
+inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src);
+
+inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b);
+inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src);
+
+inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v);
+inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v);
+
+inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
+ const XrVector3f* mins, const XrVector3f* maxs);
+inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs);
+
+================================================================================================
+*/
+
+#include <assert.h>
+#include <math.h>
+#include <stdbool.h>
+
+#define MATH_PI 3.14159265358979323846f
+
+#define DEFAULT_NEAR_Z 0.015625f // exact floating point representation
+#define INFINITE_FAR_Z 0.0f
+
+static const XrColor4f XrColorRed = {1.0f, 0.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorGreen = {0.0f, 1.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorBlue = {0.0f, 0.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorYellow = {1.0f, 1.0f, 0.0f, 1.0f};
+static const XrColor4f XrColorPurple = {1.0f, 0.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorCyan = {0.0f, 1.0f, 1.0f, 1.0f};
+static const XrColor4f XrColorLightGrey = {0.7f, 0.7f, 0.7f, 1.0f};
+static const XrColor4f XrColorDarkGrey = {0.3f, 0.3f, 0.3f, 1.0f};
+
+typedef enum GraphicsAPI { GRAPHICS_VULKAN, GRAPHICS_OPENGL, GRAPHICS_OPENGL_ES, GRAPHICS_D3D } GraphicsAPI;
+
+// Column-major, pre-multiplied. This type does not exist in the OpenXR API and is provided for convenience.
+typedef struct XrMatrix4x4f {
+ float m[16];
+} XrMatrix4x4f;
+
+inline static float XrRcpSqrt(const float x) {
+ const float SMALLEST_NON_DENORMAL = 1.1754943508222875e-038f; // ( 1U << 23 )
+ const float rcp = (x >= SMALLEST_NON_DENORMAL) ? 1.0f / sqrtf(x) : 1.0f;
+ return rcp;
+}
+
+inline static void XrVector3f_Set(XrVector3f* v, const float value) {
+ v->x = value;
+ v->y = value;
+ v->z = value;
+}
+
+inline static void XrVector3f_Add(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->x + b->x;
+ result->y = a->y + b->y;
+ result->z = a->z + b->z;
+}
+
+inline static void XrVector3f_Sub(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->x - b->x;
+ result->y = a->y - b->y;
+ result->z = a->z - b->z;
+}
+
+inline static void XrVector3f_Min(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = (a->x < b->x) ? a->x : b->x;
+ result->y = (a->y < b->y) ? a->y : b->y;
+ result->z = (a->z < b->z) ? a->z : b->z;
+}
+
+inline static void XrVector3f_Max(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = (a->x > b->x) ? a->x : b->x;
+ result->y = (a->y > b->y) ? a->y : b->y;
+ result->z = (a->z > b->z) ? a->z : b->z;
+}
+
+inline static void XrVector3f_Decay(XrVector3f* result, const XrVector3f* a, const float value) {
+ result->x = (fabsf(a->x) > value) ? ((a->x > 0.0f) ? (a->x - value) : (a->x + value)) : 0.0f;
+ result->y = (fabsf(a->y) > value) ? ((a->y > 0.0f) ? (a->y - value) : (a->y + value)) : 0.0f;
+ result->z = (fabsf(a->z) > value) ? ((a->z > 0.0f) ? (a->z - value) : (a->z + value)) : 0.0f;
+}
+
+inline static void XrVector3f_Lerp(XrVector3f* result, const XrVector3f* a, const XrVector3f* b, const float fraction) {
+ result->x = a->x + fraction * (b->x - a->x);
+ result->y = a->y + fraction * (b->y - a->y);
+ result->z = a->z + fraction * (b->z - a->z);
+}
+
+inline static void XrVector3f_Scale(XrVector3f* result, const XrVector3f* a, const float scaleFactor) {
+ result->x = a->x * scaleFactor;
+ result->y = a->y * scaleFactor;
+ result->z = a->z * scaleFactor;
+}
+
+inline static float XrVector3f_Dot(const XrVector3f* a, const XrVector3f* b) { return a->x * b->x + a->y * b->y + a->z * b->z; }
+
+// Compute cross product, which generates a normal vector.
+// Direction vector can be determined by right-hand rule: Pointing index finder in
+// direction a and middle finger in direction b, thumb will point in Cross(a, b).
+inline static void XrVector3f_Cross(XrVector3f* result, const XrVector3f* a, const XrVector3f* b) {
+ result->x = a->y * b->z - a->z * b->y;
+ result->y = a->z * b->x - a->x * b->z;
+ result->z = a->x * b->y - a->y * b->x;
+}
+
+inline static void XrVector3f_Normalize(XrVector3f* v) {
+ const float lengthRcp = XrRcpSqrt(v->x * v->x + v->y * v->y + v->z * v->z);
+ v->x *= lengthRcp;
+ v->y *= lengthRcp;
+ v->z *= lengthRcp;
+}
+
+inline static float XrVector3f_Length(const XrVector3f* v) { return sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); }
+
+inline static void XrQuaternionf_CreateFromAxisAngle(XrQuaternionf* result, const XrVector3f* axis, const float angleInRadians) {
+ float s = sinf(angleInRadians / 2.0f);
+ float lengthRcp = XrRcpSqrt(axis->x * axis->x + axis->y * axis->y + axis->z * axis->z);
+ result->x = s * axis->x * lengthRcp;
+ result->y = s * axis->y * lengthRcp;
+ result->z = s * axis->z * lengthRcp;
+ result->w = cosf(angleInRadians / 2.0f);
+}
+
+inline static void XrQuaternionf_Lerp(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b, const float fraction) {
+ const float s = a->x * b->x + a->y * b->y + a->z * b->z + a->w * b->w;
+ const float fa = 1.0f - fraction;
+ const float fb = (s < 0.0f) ? -fraction : fraction;
+ const float x = a->x * fa + b->x * fb;
+ const float y = a->y * fa + b->y * fb;
+ const float z = a->z * fa + b->z * fb;
+ const float w = a->w * fa + b->w * fb;
+ const float lengthRcp = XrRcpSqrt(x * x + y * y + z * z + w * w);
+ result->x = x * lengthRcp;
+ result->y = y * lengthRcp;
+ result->z = z * lengthRcp;
+ result->w = w * lengthRcp;
+}
+
+inline static void XrQuaternionf_Multiply(XrQuaternionf* result, const XrQuaternionf* a, const XrQuaternionf* b) {
+ result->x = (b->w * a->x) + (b->x * a->w) + (b->y * a->z) - (b->z * a->y);
+ result->y = (b->w * a->y) - (b->x * a->z) + (b->y * a->w) + (b->z * a->x);
+ result->z = (b->w * a->z) + (b->x * a->y) - (b->y * a->x) + (b->z * a->w);
+ result->w = (b->w * a->w) - (b->x * a->x) - (b->y * a->y) - (b->z * a->z);
+}
+
+// Use left-multiplication to accumulate transformations.
+inline static void XrMatrix4x4f_Multiply(XrMatrix4x4f* result, const XrMatrix4x4f* a, const XrMatrix4x4f* b) {
+ result->m[0] = a->m[0] * b->m[0] + a->m[4] * b->m[1] + a->m[8] * b->m[2] + a->m[12] * b->m[3];
+ result->m[1] = a->m[1] * b->m[0] + a->m[5] * b->m[1] + a->m[9] * b->m[2] + a->m[13] * b->m[3];
+ result->m[2] = a->m[2] * b->m[0] + a->m[6] * b->m[1] + a->m[10] * b->m[2] + a->m[14] * b->m[3];
+ result->m[3] = a->m[3] * b->m[0] + a->m[7] * b->m[1] + a->m[11] * b->m[2] + a->m[15] * b->m[3];
+
+ result->m[4] = a->m[0] * b->m[4] + a->m[4] * b->m[5] + a->m[8] * b->m[6] + a->m[12] * b->m[7];
+ result->m[5] = a->m[1] * b->m[4] + a->m[5] * b->m[5] + a->m[9] * b->m[6] + a->m[13] * b->m[7];
+ result->m[6] = a->m[2] * b->m[4] + a->m[6] * b->m[5] + a->m[10] * b->m[6] + a->m[14] * b->m[7];
+ result->m[7] = a->m[3] * b->m[4] + a->m[7] * b->m[5] + a->m[11] * b->m[6] + a->m[15] * b->m[7];
+
+ result->m[8] = a->m[0] * b->m[8] + a->m[4] * b->m[9] + a->m[8] * b->m[10] + a->m[12] * b->m[11];
+ result->m[9] = a->m[1] * b->m[8] + a->m[5] * b->m[9] + a->m[9] * b->m[10] + a->m[13] * b->m[11];
+ result->m[10] = a->m[2] * b->m[8] + a->m[6] * b->m[9] + a->m[10] * b->m[10] + a->m[14] * b->m[11];
+ result->m[11] = a->m[3] * b->m[8] + a->m[7] * b->m[9] + a->m[11] * b->m[10] + a->m[15] * b->m[11];
+
+ result->m[12] = a->m[0] * b->m[12] + a->m[4] * b->m[13] + a->m[8] * b->m[14] + a->m[12] * b->m[15];
+ result->m[13] = a->m[1] * b->m[12] + a->m[5] * b->m[13] + a->m[9] * b->m[14] + a->m[13] * b->m[15];
+ result->m[14] = a->m[2] * b->m[12] + a->m[6] * b->m[13] + a->m[10] * b->m[14] + a->m[14] * b->m[15];
+ result->m[15] = a->m[3] * b->m[12] + a->m[7] * b->m[13] + a->m[11] * b->m[14] + a->m[15] * b->m[15];
+}
+
+// Creates the transpose of the given matrix.
+inline static void XrMatrix4x4f_Transpose(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ result->m[0] = src->m[0];
+ result->m[1] = src->m[4];
+ result->m[2] = src->m[8];
+ result->m[3] = src->m[12];
+
+ result->m[4] = src->m[1];
+ result->m[5] = src->m[5];
+ result->m[6] = src->m[9];
+ result->m[7] = src->m[13];
+
+ result->m[8] = src->m[2];
+ result->m[9] = src->m[6];
+ result->m[10] = src->m[10];
+ result->m[11] = src->m[14];
+
+ result->m[12] = src->m[3];
+ result->m[13] = src->m[7];
+ result->m[14] = src->m[11];
+ result->m[15] = src->m[15];
+}
+
+// Returns a 3x3 minor of a 4x4 matrix.
+inline static float XrMatrix4x4f_Minor(const XrMatrix4x4f* matrix, int r0, int r1, int r2, int c0, int c1, int c2) {
+ return matrix->m[4 * r0 + c0] *
+ (matrix->m[4 * r1 + c1] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c1] * matrix->m[4 * r1 + c2]) -
+ matrix->m[4 * r0 + c1] *
+ (matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c2] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c2]) +
+ matrix->m[4 * r0 + c2] *
+ (matrix->m[4 * r1 + c0] * matrix->m[4 * r2 + c1] - matrix->m[4 * r2 + c0] * matrix->m[4 * r1 + c1]);
+}
+
+// Calculates the inverse of a 4x4 matrix.
+inline static void XrMatrix4x4f_Invert(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ const float rcpDet =
+ 1.0f / (src->m[0] * XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) - src->m[1] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) +
+ src->m[2] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) - src->m[3] * XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2));
+
+ result->m[0] = XrMatrix4x4f_Minor(src, 1, 2, 3, 1, 2, 3) * rcpDet;
+ result->m[1] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 1, 2, 3) * rcpDet;
+ result->m[2] = XrMatrix4x4f_Minor(src, 0, 1, 3, 1, 2, 3) * rcpDet;
+ result->m[3] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 1, 2, 3) * rcpDet;
+ result->m[4] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 2, 3) * rcpDet;
+ result->m[5] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 2, 3) * rcpDet;
+ result->m[6] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 2, 3) * rcpDet;
+ result->m[7] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 2, 3) * rcpDet;
+ result->m[8] = XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 3) * rcpDet;
+ result->m[9] = -XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 3) * rcpDet;
+ result->m[10] = XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 3) * rcpDet;
+ result->m[11] = -XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 3) * rcpDet;
+ result->m[12] = -XrMatrix4x4f_Minor(src, 1, 2, 3, 0, 1, 2) * rcpDet;
+ result->m[13] = XrMatrix4x4f_Minor(src, 0, 2, 3, 0, 1, 2) * rcpDet;
+ result->m[14] = -XrMatrix4x4f_Minor(src, 0, 1, 3, 0, 1, 2) * rcpDet;
+ result->m[15] = XrMatrix4x4f_Minor(src, 0, 1, 2, 0, 1, 2) * rcpDet;
+}
+
+// Calculates the inverse of a rigid body transform.
+inline static void XrMatrix4x4f_InvertRigidBody(XrMatrix4x4f* result, const XrMatrix4x4f* src) {
+ result->m[0] = src->m[0];
+ result->m[1] = src->m[4];
+ result->m[2] = src->m[8];
+ result->m[3] = 0.0f;
+ result->m[4] = src->m[1];
+ result->m[5] = src->m[5];
+ result->m[6] = src->m[9];
+ result->m[7] = 0.0f;
+ result->m[8] = src->m[2];
+ result->m[9] = src->m[6];
+ result->m[10] = src->m[10];
+ result->m[11] = 0.0f;
+ result->m[12] = -(src->m[0] * src->m[12] + src->m[1] * src->m[13] + src->m[2] * src->m[14]);
+ result->m[13] = -(src->m[4] * src->m[12] + src->m[5] * src->m[13] + src->m[6] * src->m[14]);
+ result->m[14] = -(src->m[8] * src->m[12] + src->m[9] * src->m[13] + src->m[10] * src->m[14]);
+ result->m[15] = 1.0f;
+}
+
+// Creates an identity matrix.
+inline static void XrMatrix4x4f_CreateIdentity(XrMatrix4x4f* result) {
+ result->m[0] = 1.0f;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = 1.0f;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = 1.0f;
+ result->m[11] = 0.0f;
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a translation matrix.
+inline static void XrMatrix4x4f_CreateTranslation(XrMatrix4x4f* result, const float x, const float y, const float z) {
+ result->m[0] = 1.0f;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = 1.0f;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = 1.0f;
+ result->m[11] = 0.0f;
+ result->m[12] = x;
+ result->m[13] = y;
+ result->m[14] = z;
+ result->m[15] = 1.0f;
+}
+
+// Creates a rotation matrix.
+// If -Z=forward, +Y=up, +X=right, then degreesX=pitch, degreesY=yaw, degreesZ=roll.
+inline static void XrMatrix4x4f_CreateRotation(XrMatrix4x4f* result, const float degreesX, const float degreesY,
+ const float degreesZ) {
+ const float sinX = sinf(degreesX * (MATH_PI / 180.0f));
+ const float cosX = cosf(degreesX * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationX = {{1, 0, 0, 0, 0, cosX, sinX, 0, 0, -sinX, cosX, 0, 0, 0, 0, 1}};
+ const float sinY = sinf(degreesY * (MATH_PI / 180.0f));
+ const float cosY = cosf(degreesY * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationY = {{cosY, 0, -sinY, 0, 0, 1, 0, 0, sinY, 0, cosY, 0, 0, 0, 0, 1}};
+ const float sinZ = sinf(degreesZ * (MATH_PI / 180.0f));
+ const float cosZ = cosf(degreesZ * (MATH_PI / 180.0f));
+ const XrMatrix4x4f rotationZ = {{cosZ, sinZ, 0, 0, -sinZ, cosZ, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}};
+ XrMatrix4x4f rotationXY;
+ XrMatrix4x4f_Multiply(&rotationXY, &rotationY, &rotationX);
+ XrMatrix4x4f_Multiply(result, &rotationZ, &rotationXY);
+}
+
+// Creates a scale matrix.
+inline static void XrMatrix4x4f_CreateScale(XrMatrix4x4f* result, const float x, const float y, const float z) {
+ result->m[0] = x;
+ result->m[1] = 0.0f;
+ result->m[2] = 0.0f;
+ result->m[3] = 0.0f;
+ result->m[4] = 0.0f;
+ result->m[5] = y;
+ result->m[6] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[8] = 0.0f;
+ result->m[9] = 0.0f;
+ result->m[10] = z;
+ result->m[11] = 0.0f;
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a matrix from a quaternion.
+inline static void XrMatrix4x4f_CreateFromQuaternion(XrMatrix4x4f* result, const XrQuaternionf* quat) {
+ const float x2 = quat->x + quat->x;
+ const float y2 = quat->y + quat->y;
+ const float z2 = quat->z + quat->z;
+
+ const float xx2 = quat->x * x2;
+ const float yy2 = quat->y * y2;
+ const float zz2 = quat->z * z2;
+
+ const float yz2 = quat->y * z2;
+ const float wx2 = quat->w * x2;
+ const float xy2 = quat->x * y2;
+ const float wz2 = quat->w * z2;
+ const float xz2 = quat->x * z2;
+ const float wy2 = quat->w * y2;
+
+ result->m[0] = 1.0f - yy2 - zz2;
+ result->m[1] = xy2 + wz2;
+ result->m[2] = xz2 - wy2;
+ result->m[3] = 0.0f;
+
+ result->m[4] = xy2 - wz2;
+ result->m[5] = 1.0f - xx2 - zz2;
+ result->m[6] = yz2 + wx2;
+ result->m[7] = 0.0f;
+
+ result->m[8] = xz2 + wy2;
+ result->m[9] = yz2 - wx2;
+ result->m[10] = 1.0f - xx2 - yy2;
+ result->m[11] = 0.0f;
+
+ result->m[12] = 0.0f;
+ result->m[13] = 0.0f;
+ result->m[14] = 0.0f;
+ result->m[15] = 1.0f;
+}
+
+// Creates a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_CreateTranslationRotationScale(XrMatrix4x4f* result, const XrVector3f* translation,
+ const XrQuaternionf* rotation, const XrVector3f* scale) {
+ XrMatrix4x4f scaleMatrix;
+ XrMatrix4x4f_CreateScale(&scaleMatrix, scale->x, scale->y, scale->z);
+
+ XrMatrix4x4f rotationMatrix;
+ XrMatrix4x4f_CreateFromQuaternion(&rotationMatrix, rotation);
+
+ XrMatrix4x4f translationMatrix;
+ XrMatrix4x4f_CreateTranslation(&translationMatrix, translation->x, translation->y, translation->z);
+
+ XrMatrix4x4f combinedMatrix;
+ XrMatrix4x4f_Multiply(&combinedMatrix, &rotationMatrix, &scaleMatrix);
+ XrMatrix4x4f_Multiply(result, &translationMatrix, &combinedMatrix);
+}
+
+// Creates a projection matrix based on the specified dimensions.
+// The projection matrix transforms -Z=forward, +Y=up, +X=right to the appropriate clip space for the graphics API.
+// The far plane is placed at infinity if farZ <= nearZ.
+// An infinite projection matrix is preferred for rasterization because, except for
+// things *right* up against the near plane, it always provides better precision:
+// "Tightening the Precision of Perspective Rendering"
+// Paul Upchurch, Mathieu Desbrun
+// Journal of Graphics Tools, Volume 16, Issue 1, 2012
+inline static void XrMatrix4x4f_CreateProjection(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const float tanAngleLeft,
+ const float tanAngleRight, const float tanAngleUp, float const tanAngleDown,
+ const float nearZ, const float farZ) {
+ const float tanAngleWidth = tanAngleRight - tanAngleLeft;
+
+ // Set to tanAngleDown - tanAngleUp for a clip space with positive Y down (Vulkan).
+ // Set to tanAngleUp - tanAngleDown for a clip space with positive Y up (OpenGL / D3D / Metal).
+ const float tanAngleHeight = graphicsApi == GRAPHICS_VULKAN ? (tanAngleDown - tanAngleUp) : (tanAngleUp - tanAngleDown);
+
+ // Set to nearZ for a [-1,1] Z clip space (OpenGL / OpenGL ES).
+ // Set to zero for a [0,1] Z clip space (Vulkan / D3D / Metal).
+ const float offsetZ = (graphicsApi == GRAPHICS_OPENGL || graphicsApi == GRAPHICS_OPENGL_ES) ? nearZ : 0;
+
+ if (farZ <= nearZ) {
+ // place the far plane at infinity
+ result->m[0] = 2.0f / tanAngleWidth;
+ result->m[4] = 0.0f;
+ result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
+ result->m[12] = 0.0f;
+
+ result->m[1] = 0.0f;
+ result->m[5] = 2.0f / tanAngleHeight;
+ result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
+ result->m[13] = 0.0f;
+
+ result->m[2] = 0.0f;
+ result->m[6] = 0.0f;
+ result->m[10] = -1.0f;
+ result->m[14] = -(nearZ + offsetZ);
+
+ result->m[3] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[11] = -1.0f;
+ result->m[15] = 0.0f;
+ } else {
+ // normal projection
+ result->m[0] = 2.0f / tanAngleWidth;
+ result->m[4] = 0.0f;
+ result->m[8] = (tanAngleRight + tanAngleLeft) / tanAngleWidth;
+ result->m[12] = 0.0f;
+
+ result->m[1] = 0.0f;
+ result->m[5] = 2.0f / tanAngleHeight;
+ result->m[9] = (tanAngleUp + tanAngleDown) / tanAngleHeight;
+ result->m[13] = 0.0f;
+
+ result->m[2] = 0.0f;
+ result->m[6] = 0.0f;
+ result->m[10] = -(farZ + offsetZ) / (farZ - nearZ);
+ result->m[14] = -(farZ * (nearZ + offsetZ)) / (farZ - nearZ);
+
+ result->m[3] = 0.0f;
+ result->m[7] = 0.0f;
+ result->m[11] = -1.0f;
+ result->m[15] = 0.0f;
+ }
+}
+
+// Creates a projection matrix based on the specified FOV.
+inline static void XrMatrix4x4f_CreateProjectionFov(XrMatrix4x4f* result, GraphicsAPI graphicsApi, const XrFovf fov,
+ const float nearZ, const float farZ) {
+ const float tanLeft = tanf(fov.angleLeft);
+ const float tanRight = tanf(fov.angleRight);
+
+ const float tanDown = tanf(fov.angleDown);
+ const float tanUp = tanf(fov.angleUp);
+
+ XrMatrix4x4f_CreateProjection(result, graphicsApi, tanLeft, tanRight, tanUp, tanDown, nearZ, farZ);
+}
+
+// Creates a matrix that transforms the -1 to 1 cube to cover the given 'mins' and 'maxs' transformed with the given 'matrix'.
+inline static void XrMatrix4x4f_CreateOffsetScaleForBounds(XrMatrix4x4f* result, const XrMatrix4x4f* matrix, const XrVector3f* mins,
+ const XrVector3f* maxs) {
+ const XrVector3f offset = {(maxs->x + mins->x) * 0.5f, (maxs->y + mins->y) * 0.5f, (maxs->z + mins->z) * 0.5f};
+ const XrVector3f scale = {(maxs->x - mins->x) * 0.5f, (maxs->y - mins->y) * 0.5f, (maxs->z - mins->z) * 0.5f};
+
+ result->m[0] = matrix->m[0] * scale.x;
+ result->m[1] = matrix->m[1] * scale.x;
+ result->m[2] = matrix->m[2] * scale.x;
+ result->m[3] = matrix->m[3] * scale.x;
+
+ result->m[4] = matrix->m[4] * scale.y;
+ result->m[5] = matrix->m[5] * scale.y;
+ result->m[6] = matrix->m[6] * scale.y;
+ result->m[7] = matrix->m[7] * scale.y;
+
+ result->m[8] = matrix->m[8] * scale.z;
+ result->m[9] = matrix->m[9] * scale.z;
+ result->m[10] = matrix->m[10] * scale.z;
+ result->m[11] = matrix->m[11] * scale.z;
+
+ result->m[12] = matrix->m[12] + matrix->m[0] * offset.x + matrix->m[4] * offset.y + matrix->m[8] * offset.z;
+ result->m[13] = matrix->m[13] + matrix->m[1] * offset.x + matrix->m[5] * offset.y + matrix->m[9] * offset.z;
+ result->m[14] = matrix->m[14] + matrix->m[2] * offset.x + matrix->m[6] * offset.y + matrix->m[10] * offset.z;
+ result->m[15] = matrix->m[15] + matrix->m[3] * offset.x + matrix->m[7] * offset.y + matrix->m[11] * offset.z;
+}
+
+// Returns true if the given matrix is affine.
+inline static bool XrMatrix4x4f_IsAffine(const XrMatrix4x4f* matrix, const float epsilon) {
+ return fabsf(matrix->m[3]) <= epsilon && fabsf(matrix->m[7]) <= epsilon && fabsf(matrix->m[11]) <= epsilon &&
+ fabsf(matrix->m[15] - 1.0f) <= epsilon;
+}
+
+// Returns true if the given matrix is orthogonal.
+inline static bool XrMatrix4x4f_IsOrthogonal(const XrMatrix4x4f* matrix, const float epsilon) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ if (i != j) {
+ if (fabsf(matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
+ matrix->m[4 * i + 2] * matrix->m[4 * j + 2]) > epsilon) {
+ return false;
+ }
+ if (fabsf(matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
+ matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j]) > epsilon) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+// Returns true if the given matrix is orthonormal.
+inline static bool XrMatrix4x4f_IsOrthonormal(const XrMatrix4x4f* matrix, const float epsilon) {
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ const float kd = (i == j) ? 1.0f : 0.0f; // Kronecker delta
+ if (fabsf(kd - (matrix->m[4 * i + 0] * matrix->m[4 * j + 0] + matrix->m[4 * i + 1] * matrix->m[4 * j + 1] +
+ matrix->m[4 * i + 2] * matrix->m[4 * j + 2])) > epsilon) {
+ return false;
+ }
+ if (fabsf(kd - (matrix->m[4 * 0 + i] * matrix->m[4 * 0 + j] + matrix->m[4 * 1 + i] * matrix->m[4 * 1 + j] +
+ matrix->m[4 * 2 + i] * matrix->m[4 * 2 + j])) > epsilon) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// Returns true if the given matrix is a rigid body transform.
+inline static bool XrMatrix4x4f_IsRigidBody(const XrMatrix4x4f* matrix, const float epsilon) {
+ return XrMatrix4x4f_IsAffine(matrix, epsilon) && XrMatrix4x4f_IsOrthonormal(matrix, epsilon);
+}
+
+// Get the translation from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetTranslation(XrVector3f* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ result->x = src->m[12];
+ result->y = src->m[13];
+ result->z = src->m[14];
+}
+
+// Get the rotation from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetRotation(XrQuaternionf* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ const float rcpScaleX = XrRcpSqrt(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
+ const float rcpScaleY = XrRcpSqrt(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
+ const float rcpScaleZ = XrRcpSqrt(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
+ const float m[9] = {src->m[0] * rcpScaleX, src->m[1] * rcpScaleX, src->m[2] * rcpScaleX,
+ src->m[4] * rcpScaleY, src->m[5] * rcpScaleY, src->m[6] * rcpScaleY,
+ src->m[8] * rcpScaleZ, src->m[9] * rcpScaleZ, src->m[10] * rcpScaleZ};
+ if (m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] > 0.0f) {
+ float t = +m[0 * 3 + 0] + m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->w = s * t;
+ result->z = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
+ result->y = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
+ result->x = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
+ } else if (m[0 * 3 + 0] > m[1 * 3 + 1] && m[0 * 3 + 0] > m[2 * 3 + 2]) {
+ float t = +m[0 * 3 + 0] - m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->x = s * t;
+ result->y = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
+ result->z = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
+ result->w = (m[1 * 3 + 2] - m[2 * 3 + 1]) * s;
+ } else if (m[1 * 3 + 1] > m[2 * 3 + 2]) {
+ float t = -m[0 * 3 + 0] + m[1 * 3 + 1] - m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->y = s * t;
+ result->x = (m[0 * 3 + 1] + m[1 * 3 + 0]) * s;
+ result->w = (m[2 * 3 + 0] - m[0 * 3 + 2]) * s;
+ result->z = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
+ } else {
+ float t = -m[0 * 3 + 0] - m[1 * 3 + 1] + m[2 * 3 + 2] + 1.0f;
+ float s = XrRcpSqrt(t) * 0.5f;
+ result->z = s * t;
+ result->w = (m[0 * 3 + 1] - m[1 * 3 + 0]) * s;
+ result->x = (m[2 * 3 + 0] + m[0 * 3 + 2]) * s;
+ result->y = (m[1 * 3 + 2] + m[2 * 3 + 1]) * s;
+ }
+}
+
+// Get the scale from a combined translation(rotation(scale(object))) matrix.
+inline static void XrMatrix4x4f_GetScale(XrVector3f* result, const XrMatrix4x4f* src) {
+ assert(XrMatrix4x4f_IsAffine(src, 1e-4f));
+ assert(XrMatrix4x4f_IsOrthogonal(src, 1e-4f));
+
+ result->x = sqrtf(src->m[0] * src->m[0] + src->m[1] * src->m[1] + src->m[2] * src->m[2]);
+ result->y = sqrtf(src->m[4] * src->m[4] + src->m[5] * src->m[5] + src->m[6] * src->m[6]);
+ result->z = sqrtf(src->m[8] * src->m[8] + src->m[9] * src->m[9] + src->m[10] * src->m[10]);
+}
+
+// Transforms a 3D vector.
+inline static void XrMatrix4x4f_TransformVector3f(XrVector3f* result, const XrMatrix4x4f* m, const XrVector3f* v) {
+ const float w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15];
+ const float rcpW = 1.0f / w;
+ result->x = (m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12]) * rcpW;
+ result->y = (m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13]) * rcpW;
+ result->z = (m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14]) * rcpW;
+}
+
+// Transforms a 4D vector.
+inline static void XrMatrix4x4f_TransformVector4f(XrVector4f* result, const XrMatrix4x4f* m, const XrVector4f* v) {
+ result->x = m->m[0] * v->x + m->m[4] * v->y + m->m[8] * v->z + m->m[12] * v->w;
+ result->y = m->m[1] * v->x + m->m[5] * v->y + m->m[9] * v->z + m->m[13] * v->w;
+ result->z = m->m[2] * v->x + m->m[6] * v->y + m->m[10] * v->z + m->m[14] * v->w;
+ result->w = m->m[3] * v->x + m->m[7] * v->y + m->m[11] * v->z + m->m[15] * v->w;
+}
+
+// Transforms the 'mins' and 'maxs' bounds with the given 'matrix'.
+inline static void XrMatrix4x4f_TransformBounds(XrVector3f* resultMins, XrVector3f* resultMaxs, const XrMatrix4x4f* matrix,
+ const XrVector3f* mins, const XrVector3f* maxs) {
+ assert(XrMatrix4x4f_IsAffine(matrix, 1e-4f));
+
+ const XrVector3f center = {(mins->x + maxs->x) * 0.5f, (mins->y + maxs->y) * 0.5f, (mins->z + maxs->z) * 0.5f};
+ const XrVector3f extents = {maxs->x - center.x, maxs->y - center.y, maxs->z - center.z};
+ const XrVector3f newCenter = {matrix->m[0] * center.x + matrix->m[4] * center.y + matrix->m[8] * center.z + matrix->m[12],
+ matrix->m[1] * center.x + matrix->m[5] * center.y + matrix->m[9] * center.z + matrix->m[13],
+ matrix->m[2] * center.x + matrix->m[6] * center.y + matrix->m[10] * center.z + matrix->m[14]};
+ const XrVector3f newExtents = {
+ fabsf(extents.x * matrix->m[0]) + fabsf(extents.y * matrix->m[4]) + fabsf(extents.z * matrix->m[8]),
+ fabsf(extents.x * matrix->m[1]) + fabsf(extents.y * matrix->m[5]) + fabsf(extents.z * matrix->m[9]),
+ fabsf(extents.x * matrix->m[2]) + fabsf(extents.y * matrix->m[6]) + fabsf(extents.z * matrix->m[10])};
+ XrVector3f_Sub(resultMins, &newCenter, &newExtents);
+ XrVector3f_Add(resultMaxs, &newCenter, &newExtents);
+}
+
+// Returns true if the 'mins' and 'maxs' bounds is completely off to one side of the projection matrix.
+inline static bool XrMatrix4x4f_CullBounds(const XrMatrix4x4f* mvp, const XrVector3f* mins, const XrVector3f* maxs) {
+ if (maxs->x <= mins->x && maxs->y <= mins->y && maxs->z <= mins->z) {
+ return false;
+ }
+
+ XrVector4f c[8];
+ for (int i = 0; i < 8; i++) {
+ const XrVector4f corner = {(i & 1) != 0 ? maxs->x : mins->x, (i & 2) != 0 ? maxs->y : mins->y,
+ (i & 4) != 0 ? maxs->z : mins->z, 1.0f};
+ XrMatrix4x4f_TransformVector4f(&c[i], mvp, &corner);
+ }
+
+ int i;
+ for (i = 0; i < 8; i++) {
+ if (c[i].x > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].x < c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (c[i].y > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].y < c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].z > -c[i].w) {
+ break;
+ }
+ }
+ if (i == 8) {
+ return true;
+ }
+ for (i = 0; i < 8; i++) {
+ if (c[i].z < c[i].w) {
+ break;
+ }
+ }
+ return i == 8;
+}
+
+#endif // XR_LINEAR_H_
diff --git a/thirdparty/openxr/src/external/jsoncpp/AUTHORS b/thirdparty/openxr/src/external/jsoncpp/AUTHORS
new file mode 100644
index 0000000000..e1fa0fc3ad
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/AUTHORS
@@ -0,0 +1,115 @@
+Baptiste Lepilleur <blep@users.sourceforge.net>
+
+Aaron Jacobs <aaronjjacobs@gmail.com>
+Aaron Jacobs <jacobsa@google.com>
+Adam Boseley <ABoseley@agjunction.com>
+Adam Boseley <adam.boseley@gmail.com>
+Aleksandr Derbenev <13alexac@gmail.com>
+Alexander Gazarov <DrMetallius@users.noreply.github.com>
+Alexander V. Brezgin <abrezgin@appliedtech.ru>
+Alexandr Brezgin <albrezgin@mail.ru>
+Alexey Kruchinin <alexey@mopals.com>
+Anton Indrawan <anton.indrawan@gmail.com>
+Baptiste Jonglez <git@bitsofnetworks.org>
+Baptiste Lepilleur <baptiste.lepilleur@gmail.com>
+Baruch Siach <baruch@tkos.co.il>
+Ben Boeckel <mathstuf@gmail.com>
+Benjamin Knecht <bknecht@logitech.com>
+Bernd Kuhls <bernd.kuhls@t-online.de>
+Billy Donahue <billydonahue@google.com>
+Braden McDorman <bmcdorman@gmail.com>
+Brandon Myers <bmyers1788@gmail.com>
+Brendan Drew <brendan.drew@daqri.com>
+chason <cxchao802@gmail.com>
+chenguoping <chenguopingdota@163.com>
+Chris Gilling <cgilling@iparadigms.com>
+Christopher Dawes <christopher.dawes.1981@googlemail.com>
+Christopher Dunn <cdunn2001@gmail.com>
+Chuck Atkins <chuck.atkins@kitware.com>
+Cody P Schafer <dev@codyps.com>
+Connor Manning <connor@hobu.co>
+Cory Quammen <cory.quammen@kitware.com>
+CristoÌvão B da Cruz e Silva <CrisXed@gmail.com>
+Daniel Krügler <daniel.kruegler@gmail.com>
+Dani-Hub <daniel.kruegler@googlemail.com>
+Dan Liu <gzliudan>
+datadiode <datadiode@users.noreply.github.com>
+datadiode <jochen.neubeck@vodafone.de>
+David Seifert <soap@gentoo.org>
+David West <david-west@idexx.com>
+dawesc <chris.dawes@eftlab.co.uk>
+Devin Jeanpierre <jeanpierreda@google.com>
+Dmitry Marakasov <amdmi3@amdmi3.ru>
+dominicpezzuto <dom@dompezzuto.com>
+Don Milham <dmilham@gmail.com>
+drgler <daniel.kruegler@gmail.com>
+ds283 <D.Seery@sussex.ac.uk>
+Egor Tensin <Egor.Tensin@gmail.com>
+eightnoteight <mr.eightnoteight@gmail.com>
+Evince <baneyue@gmail.com>
+filipjs <filipjs@users.noreply.github.com>
+findblar <ft@finbarr.ca>
+Florian Meier <florian.meier@koalo.de>
+Gaëtan Lehmann <gaetan.lehmann@gmail.com>
+Gaurav <g.gupta@samsung.com>
+Gergely Nagy <ngg@ngg.hu>
+Gida Pataki <gida.pataki@prezi.com>
+I3ck <buckmartin@buckmartin.de>
+Iñaki Baz Castillo <ibc@aliax.net>
+Jacco <jacco@geul.net>
+Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
+Jonas Platte <mail@jonasplatte.de>
+Jordan Bayles <bayles.jordan@gmail.com>
+Jörg Krause <joerg.krause@embedded.rocks>
+Keith Lea <keith@whamcitylights.com>
+Kevin Grant <kbradleygrant@gmail.com>
+Kirill V. Lyadvinsky <jia3ep@gmail.com>
+Kirill V. Lyadvinsky <mail@codeatcpp.com>
+Kobi Gurkan <kobigurk@gmail.com>
+Magnus Bjerke Vik <mbvett@gmail.com>
+Malay Shah <malays@users.sourceforge.net>
+Mara Kim <hacker.root@gmail.com>
+Marek Kotewicz <marek.kotewicz@gmail.com>
+Mark Lakata <mark@lakata.org>
+Mark Zeren <mzeren@vmware.com>
+Martin Buck <buckmartin@buckmartin.de>
+Martyn Gigg <martyn.gigg@gmail.com>
+Mattes D <github@xoft.cz>
+Matthias Loy <matthias.loy@hbm.com>
+Merlyn Morgan-Graham <kavika@gmail.com>
+Michael Shields <mshields@google.com>
+Michał Górny <mgorny@gentoo.org>
+Mike Naberezny <mike@naberezny.com>
+mloy <matthias.loy@googlemail.com>
+Motti <lanzkron@gmail.com>
+nnkur <nnkur@mail.ru>
+Omkar Wagh <owagh@owaghlinux.ny.tower-research.com>
+paulo <paulobrizolara@users.noreply.github.com>
+pavel.pimenov <pavel.pimenov@gmail.com>
+Paweł Bylica <chfast@gmail.com>
+Péricles Lopes Machado <pericles.raskolnikoff@gmail.com>
+Peter Spiess-Knafl <psk@autistici.org>
+pffang <pffang@vip.qq.com>
+Rémi Verschelde <remi@verschelde.fr>
+renu555 <renu.tyagi@samsung.com>
+Robert Dailey <rcdailey@gmail.com>
+Sam Clegg <sbc@chromium.org>
+selaselah <selah@outlook.com>
+Sergiy80 <sil2004@gmail.com>
+sergzub <sergzub@gmail.com>
+Stefan Schweter <stefan@schweter.it>
+Stefano Fiorentino <stefano.fiore84@gmail.com>
+Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
+Steven Hahn <hahnse@ornl.gov>
+Stuart Eichert <stuart@fivemicro.com>
+SuperManitu <supermanitu@gmail.com>
+Techwolf <dring@g33kworld.net>
+Tengiz Sharafiev <btolfa+github@gmail.com>
+Tomasz Maciejewski <tmaciejewsk@gmail.com>
+Vicente Olivert Riera <Vincent.Riera@imgtec.com>
+xiaoyur347 <xiaoyur347@gmail.com>
+ycqiu <429148848@qq.com>
+yiqiju <fred_ju@selinc.com>
+Yu Xiaolei <dreifachstein@gmail.com>
+
+Google Inc.
diff --git a/thirdparty/openxr/src/external/jsoncpp/LICENSE b/thirdparty/openxr/src/external/jsoncpp/LICENSE
new file mode 100644
index 0000000000..c41a1d1c77
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/LICENSE
@@ -0,0 +1,55 @@
+The JsonCpp library's source code, including accompanying documentation,
+tests and demonstration applications, are licensed under the following
+conditions...
+
+Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
+jurisdictions which recognize such a disclaimer. In such jurisdictions,
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
+The JsonCpp Authors, and is released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this
+software may choose to accept it either as 1) Public Domain, 2) under the
+conditions of the MIT License (see below), or 3) under the terms of dual
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+ http://en.wikipedia.org/wiki/MIT_License
+
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h b/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h
new file mode 100644
index 0000000000..95ef8a5ec4
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/allocator.h
@@ -0,0 +1,88 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ALLOCATOR_H_INCLUDED
+#define JSON_ALLOCATOR_H_INCLUDED
+
+#include <cstring>
+#include <memory>
+
+#pragma pack(push, 8)
+
+namespace Json {
+template <typename T> class SecureAllocator {
+public:
+ // Type definitions
+ using value_type = T;
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ /**
+ * Allocate memory for N items using the standard allocator.
+ */
+ pointer allocate(size_type n) {
+ // allocate using "global operator new"
+ return static_cast<pointer>(::operator new(n * sizeof(T)));
+ }
+
+ /**
+ * Release memory which was allocated for N items at pointer P.
+ *
+ * The memory block is filled with zeroes before being released.
+ */
+ void deallocate(pointer p, size_type n) {
+ // memset_s is used because memset may be optimized away by the compiler
+ memset_s(p, n * sizeof(T), 0, n * sizeof(T));
+ // free using "global operator delete"
+ ::operator delete(p);
+ }
+
+ /**
+ * Construct an item in-place at pointer P.
+ */
+ template <typename... Args> void construct(pointer p, Args&&... args) {
+ // construct using "placement new" and "perfect forwarding"
+ ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
+ }
+
+ size_type max_size() const { return size_t(-1) / sizeof(T); }
+
+ pointer address(reference x) const { return std::addressof(x); }
+
+ const_pointer address(const_reference x) const { return std::addressof(x); }
+
+ /**
+ * Destroy an item in-place at pointer P.
+ */
+ void destroy(pointer p) {
+ // destroy using "explicit destructor"
+ p->~T();
+ }
+
+ // Boilerplate
+ SecureAllocator() {}
+ template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
+ template <typename U> struct rebind { using other = SecureAllocator<U>; };
+};
+
+template <typename T, typename U>
+bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+ return true;
+}
+
+template <typename T, typename U>
+bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
+ return false;
+}
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_ALLOCATOR_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h b/thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h
new file mode 100644
index 0000000000..666fa7f542
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/assertions.h
@@ -0,0 +1,61 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_ASSERTIONS_H_INCLUDED
+#define JSON_ASSERTIONS_H_INCLUDED
+
+#include <cstdlib>
+#include <sstream>
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+/** It should not be possible for a maliciously designed file to
+ * cause an abort() or seg-fault, so these macros are used only
+ * for pre-condition violations and internal logic errors.
+ */
+#if JSON_USE_EXCEPTION
+
+// @todo <= add detail about condition in exception
+#define JSON_ASSERT(condition) \
+ do { \
+ if (!(condition)) { \
+ Json::throwLogicError("assert json failed"); \
+ } \
+ } while (0)
+
+#define JSON_FAIL_MESSAGE(message) \
+ do { \
+ OStringStream oss; \
+ oss << message; \
+ Json::throwLogicError(oss.str()); \
+ abort(); \
+ } while (0)
+
+#else // JSON_USE_EXCEPTION
+
+#define JSON_ASSERT(condition) assert(condition)
+
+// The call to assert() will show the failure message in debug builds. In
+// release builds we abort, for a core-dump or debugger.
+#define JSON_FAIL_MESSAGE(message) \
+ { \
+ OStringStream oss; \
+ oss << message; \
+ assert(false && oss.str().c_str()); \
+ abort(); \
+ }
+
+#endif
+
+#define JSON_ASSERT_MESSAGE(condition, message) \
+ do { \
+ if (!(condition)) { \
+ JSON_FAIL_MESSAGE(message); \
+ } \
+ } while (0)
+
+#endif // JSON_ASSERTIONS_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/config.h b/thirdparty/openxr/src/external/jsoncpp/include/json/config.h
new file mode 100644
index 0000000000..6359273a22
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/config.h
@@ -0,0 +1,150 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+#include <cstddef>
+#include <cstdint>
+#include <istream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+// Temporary, tracked for removal with issue #982.
+#ifndef JSON_USE_NULLREF
+#define JSON_USE_NULLREF 1
+#endif
+
+/// If defined, indicates that the source file is amalgamated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgamated header.
+// #define JSON_IS_AMALGAMATION
+
+// Export macros for DLL visibility
+#if defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#elif defined(__GNUC__) || defined(__clang__)
+#define JSON_API __attribute__((visibility("default")))
+#endif // if defined(_MSC_VER)
+
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER) || defined(__MINGW32__)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_DLL_BUILD
+
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1800
+#error \
+ "ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER < 1900
+// As recommended at
+// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
+extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+ const char* format, ...);
+#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
+#else
+#define jsoncpp_snprintf std::snprintf
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
+// C++11 should be used directly in JSONCPP.
+#define JSONCPP_OVERRIDE override
+
+#ifdef __clang__
+#if __has_extension(attribute_deprecated_with_message)
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
+#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
+#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
+#endif // GNUC version
+#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
+ // MSVC)
+#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#endif // __clang__ || __GNUC__ || _MSC_VER
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
+#define JSON_USE_INT64_DOUBLE_CONVERSION 1
+#endif
+
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "allocator.h"
+#include "version.h"
+
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+using Int = int;
+using UInt = unsigned int;
+#if defined(JSON_NO_INT64)
+using LargestInt = int;
+using LargestUInt = unsigned int;
+#undef JSON_HAS_INT64
+#else // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+using Int64 = __int64;
+using UInt64 = unsigned __int64;
+#else // if defined(_MSC_VER) // Other platforms, use long long
+using Int64 = int64_t;
+using UInt64 = uint64_t;
+#endif // if defined(_MSC_VER)
+using LargestInt = Int64;
+using LargestUInt = UInt64;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+
+template <typename T>
+using Allocator =
+ typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
+ std::allocator<T>>::type;
+using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
+using IStringStream =
+ std::basic_istringstream<String::value_type, String::traits_type,
+ String::allocator_type>;
+using OStringStream =
+ std::basic_ostringstream<String::value_type, String::traits_type,
+ String::allocator_type>;
+using IStream = std::istream;
+using OStream = std::ostream;
+} // namespace Json
+
+// Legacy names (formerly macros).
+using JSONCPP_STRING = Json::String;
+using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
+using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
+using JSONCPP_ISTREAM = Json::IStream;
+using JSONCPP_OSTREAM = Json::OStream;
+
+#endif // JSON_CONFIG_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h b/thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h
new file mode 100644
index 0000000000..affe33a7f9
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/forwards.h
@@ -0,0 +1,43 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class StreamWriter;
+class StreamWriterBuilder;
+class Writer;
+class FastWriter;
+class StyledWriter;
+class StyledStreamWriter;
+
+// reader.h
+class Reader;
+class CharReader;
+class CharReaderBuilder;
+
+// json_features.h
+class Features;
+
+// value.h
+using ArrayIndex = unsigned int;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/json.h b/thirdparty/openxr/src/external/jsoncpp/include/json/json.h
new file mode 100644
index 0000000000..5c776a1609
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/json.h
@@ -0,0 +1,15 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_JSON_H_INCLUDED
+#define JSON_JSON_H_INCLUDED
+
+#include "config.h"
+#include "json_features.h"
+#include "reader.h"
+#include "value.h"
+#include "writer.h"
+
+#endif // JSON_JSON_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h b/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h
new file mode 100644
index 0000000000..7c7e9f5de1
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/json_features.h
@@ -0,0 +1,61 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FEATURES_H_INCLUDED
+#define JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+/** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+class JSON_API Features {
+public:
+ /** \brief A configuration that allows all features and assumes all strings
+ * are UTF-8.
+ * - C & C++ comments are allowed
+ * - Root object can be any JSON value
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features all();
+
+ /** \brief A configuration that is strictly compatible with the JSON
+ * specification.
+ * - Comments are forbidden.
+ * - Root object must be either an array or an object value.
+ * - Assumes Value strings are encoded in UTF-8
+ */
+ static Features strictMode();
+
+ /** \brief Initialize the configuration like JsonConfig::allFeatures;
+ */
+ Features();
+
+ /// \c true if comments are allowed. Default: \c true.
+ bool allowComments_{true};
+
+ /// \c true if root must be either an array or an object value. Default: \c
+ /// false.
+ bool strictRoot_{false};
+
+ /// \c true if dropped null placeholders are allowed. Default: \c false.
+ bool allowDroppedNullPlaceholders_{false};
+
+ /// \c true if numeric object key are allowed. Default: \c false.
+ bool allowNumericKeys_{false};
+};
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#endif // JSON_FEATURES_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h b/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h
new file mode 100644
index 0000000000..be0d7676ab
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/reader.h
@@ -0,0 +1,405 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_READER_H_INCLUDED
+#define JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "json_features.h"
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <deque>
+#include <iosfwd>
+#include <istream>
+#include <stack>
+#include <string>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
+ * Value.
+ *
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+
+class JSON_API Reader {
+public:
+ using Char = char;
+ using Location = const Char*;
+
+ /** \brief An error tagged with where in the JSON text it was encountered.
+ *
+ * The offsets give the [start, limit) range of bytes within the text. Note
+ * that this is bytes, not codepoints.
+ */
+ struct StructuredError {
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ String message;
+ };
+
+ /** \brief Constructs a Reader allowing all features for parsing.
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+ Reader();
+
+ /** \brief Constructs a Reader allowing the specified feature set for parsing.
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+ Reader(const Features& features);
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ * document.
+ *
+ * \param document UTF-8 encoded string containing the document
+ * to read.
+ * \param[out] root Contains the root value of the document if it
+ * was successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing
+ * them back during serialization, \c false to
+ * discard comments. This parameter is ignored
+ * if Features::allowComments_ is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ * error occurred.
+ */
+ bool parse(const std::string& document, Value& root,
+ bool collectComments = true);
+
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ * document.
+ *
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded
+ * string of the document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string
+ * of the document to read. Must be >= beginDoc.
+ * \param[out] root Contains the root value of the document if it
+ * was successfully parsed.
+ * \param collectComments \c true to collect comment and allow writing
+ * them back during serialization, \c false to
+ * discard comments. This parameter is ignored
+ * if Features::allowComments_ is \c false.
+ * \return \c true if the document was successfully parsed, \c false if an
+ * error occurred.
+ */
+ bool parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments = true);
+
+ /// \brief Parse from input stream.
+ /// \see Json::operator>>(std::istream&, Json::Value&).
+ bool parse(IStream& is, Value& root, bool collectComments = true);
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ *
+ * \return Formatted error message with the list of errors with their
+ * location in the parsed document. An empty string is returned if no error
+ * occurred during parsing.
+ * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+ */
+ JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+ String getFormatedErrorMessages() const;
+
+ /** \brief Returns a user friendly string that list errors in the parsed
+ * document.
+ *
+ * \return Formatted error message with the list of errors with their
+ * location in the parsed document. An empty string is returned if no error
+ * occurred during parsing.
+ */
+ String getFormattedErrorMessages() const;
+
+ /** \brief Returns a vector of structured errors encountered while parsing.
+ *
+ * \return A (possibly empty) vector of StructuredError objects. Currently
+ * only one error can be returned, but the caller should tolerate multiple
+ * errors. This can occur if the parser recovers from a non-fatal parse
+ * error and then encounters additional errors.
+ */
+ std::vector<StructuredError> getStructuredErrors() const;
+
+ /** \brief Add a semantic error message.
+ *
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \return \c true if the error was successfully added, \c false if the Value
+ * offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const String& message);
+
+ /** \brief Add a semantic error message with extra context.
+ *
+ * \param value JSON Value location associated with the error
+ * \param message The error message.
+ * \param extra Additional JSON Value location to contextualize the error
+ * \return \c true if the error was successfully added, \c false if either
+ * Value offset exceeds the document size.
+ */
+ bool pushError(const Value& value, const String& message, const Value& extra);
+
+ /** \brief Return whether there are any errors.
+ *
+ * \return \c true if there are no errors to report \c false if errors have
+ * occurred.
+ */
+ bool good() const;
+
+private:
+ enum TokenType {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo {
+ public:
+ Token token_;
+ String message_;
+ Location extra_;
+ };
+
+ using Errors = std::deque<ErrorInfo>;
+
+ bool readToken(Token& token);
+ void skipSpaces();
+ bool match(const Char* pattern, int patternLength);
+ bool readComment();
+ bool readCStyleComment();
+ bool readCppStyleComment();
+ bool readString();
+ void readNumber();
+ bool readValue();
+ bool readObject(Token& token);
+ bool readArray(Token& token);
+ bool decodeNumber(Token& token);
+ bool decodeNumber(Token& token, Value& decoded);
+ bool decodeString(Token& token);
+ bool decodeString(Token& token, String& decoded);
+ bool decodeDouble(Token& token);
+ bool decodeDouble(Token& token, Value& decoded);
+ bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
+ unsigned int& unicode);
+ bool decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end, unsigned int& unicode);
+ bool addError(const String& message, Token& token, Location extra = nullptr);
+ bool recoverFromError(TokenType skipUntilToken);
+ bool addErrorAndRecover(const String& message, Token& token,
+ TokenType skipUntilToken);
+ void skipUntilSpace();
+ Value& currentValue();
+ Char getNextChar();
+ void getLocationLineAndColumn(Location location, int& line,
+ int& column) const;
+ String getLocationLineAndColumn(Location location) const;
+ void addComment(Location begin, Location end, CommentPlacement placement);
+ void skipCommentTokens(Token& token);
+
+ static bool containsNewLine(Location begin, Location end);
+ static String normalizeEOL(Location begin, Location end);
+
+ using Nodes = std::stack<Value*>;
+ Nodes nodes_;
+ Errors errors_;
+ String document_;
+ Location begin_{};
+ Location end_{};
+ Location current_{};
+ Location lastValueEnd_{};
+ Value* lastValue_{};
+ String commentsBefore_;
+ Features features_;
+ bool collectComments_{};
+}; // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+ virtual ~CharReader() = default;
+ /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+ * document. The document must be a UTF-8 encoded string containing the
+ * document to read.
+ *
+ * \param beginDoc Pointer on the beginning of the UTF-8 encoded string
+ * of the document to read.
+ * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+ * document to read. Must be >= beginDoc.
+ * \param[out] root Contains the root value of the document if it was
+ * successfully parsed.
+ * \param[out] errs Formatted error messages (if not NULL) a user
+ * friendly string that lists errors in the parsed
+ * document.
+ * \return \c true if the document was successfully parsed, \c false if an
+ * error occurred.
+ */
+ virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
+ String* errs) = 0;
+
+ class JSON_API Factory {
+ public:
+ virtual ~Factory() = default;
+ /** \brief Allocate a CharReader via operator new().
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ virtual CharReader* newCharReader() const = 0;
+ }; // Factory
+}; // CharReader
+
+/** \brief Build a CharReader implementation.
+ *
+ * Usage:
+ * \code
+ * using namespace Json;
+ * CharReaderBuilder builder;
+ * builder["collectComments"] = false;
+ * Value value;
+ * String errs;
+ * bool ok = parseFromStream(builder, std::cin, &value, &errs);
+ * \endcode
+ */
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+ // Note: We use a Json::Value so that we can add data-members to this class
+ // without a major version bump.
+ /** Configuration of this builder.
+ * These are case-sensitive.
+ * Available settings (case-sensitive):
+ * - `"collectComments": false or true`
+ * - true to collect comment and allow writing them back during
+ * serialization, false to discard comments. This parameter is ignored
+ * if allowComments is false.
+ * - `"allowComments": false or true`
+ * - true if comments are allowed.
+ * - `"allowTrailingCommas": false or true`
+ * - true if trailing commas in objects and arrays are allowed.
+ * - `"strictRoot": false or true`
+ * - true if root must be either an array or an object value
+ * - `"allowDroppedNullPlaceholders": false or true`
+ * - true if dropped null placeholders are allowed. (See
+ * StreamWriterBuilder.)
+ * - `"allowNumericKeys": false or true`
+ * - true if numeric object keys are allowed.
+ * - `"allowSingleQuotes": false or true`
+ * - true if '' are allowed for strings (both keys and values)
+ * - `"stackLimit": integer`
+ * - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
+ * exception.
+ * - This is a security issue (seg-faults caused by deeply nested JSON), so
+ * the default is low.
+ * - `"failIfExtra": false or true`
+ * - If true, `parse()` returns false when extra non-whitespace trails the
+ * JSON value in the input string.
+ * - `"rejectDupKeys": false or true`
+ * - If true, `parse()` returns false when a key is duplicated within an
+ * object.
+ * - `"allowSpecialFloats": false or true`
+ * - If true, special float values (NaNs and infinities) are allowed and
+ * their values are lossfree restorable.
+ * - `"skipBom": false or true`
+ * - If true, if the input starts with the Unicode byte order mark (BOM),
+ * it is skipped.
+ *
+ * You can examine 'settings_` yourself to see the defaults. You can also
+ * write and read them just like any JSON Value.
+ * \sa setDefaults()
+ */
+ Json::Value settings_;
+
+ CharReaderBuilder();
+ ~CharReaderBuilder() override;
+
+ CharReader* newCharReader() const override;
+
+ /** \return true if 'settings' are legal and consistent;
+ * otherwise, indicate bad settings via 'invalid'.
+ */
+ bool validate(Json::Value* invalid) const;
+
+ /** A simple way to update a specific setting.
+ */
+ Value& operator[](const String& key);
+
+ /** Called by ctor, but you can use this to reset settings_.
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+ */
+ static void setDefaults(Json::Value* settings);
+ /** Same as old Features::strictMode().
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+ */
+ static void strictMode(Json::Value* settings);
+};
+
+/** Consume entire stream and use its begin/end.
+ * Someday we might have a real StreamReader, but for now this
+ * is convenient.
+ */
+bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
+ String* errs);
+
+/** \brief Read from 'sin' into 'root'.
+ *
+ * Always keep comments from the input JSON.
+ *
+ * This can be used to read a file into a particular sub-object.
+ * For example:
+ * \code
+ * Json::Value root;
+ * cin >> root["dir"]["file"];
+ * cout << root;
+ * \endcode
+ * Result:
+ * \verbatim
+ * {
+ * "dir": {
+ * "file": {
+ * // The input stream JSON would be nested here.
+ * }
+ * }
+ * }
+ * \endverbatim
+ * \throw std::exception on parse error.
+ * \see Json::operator<<()
+ */
+JSON_API IStream& operator>>(IStream&, Value&);
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_READER_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/value.h b/thirdparty/openxr/src/external/jsoncpp/include/json/value.h
new file mode 100644
index 0000000000..0edeb050ca
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/value.h
@@ -0,0 +1,935 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_H_INCLUDED
+#define JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+// Conditional NORETURN attribute on the throw functions would:
+// a) suppress false positives from static code analysis
+// b) possibly improve optimization opportunities.
+#if !defined(JSONCPP_NORETURN)
+#if defined(_MSC_VER) && _MSC_VER == 1800
+#define JSONCPP_NORETURN __declspec(noreturn)
+#else
+#define JSONCPP_NORETURN [[noreturn]]
+#endif
+#endif
+
+// Support for '= delete' with template declarations was a late addition
+// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
+// even though these declare themselves to be c++11 compilers.
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#if defined(__clang__) && defined(__apple_build_version__)
+#if __apple_build_version__ <= 8000042
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#elif defined(__clang__)
+#if __clang_major__ == 3 && __clang_minor__ <= 8
+#define JSONCPP_TEMPLATE_DELETE
+#endif
+#endif
+#if !defined(JSONCPP_TEMPLATE_DELETE)
+#define JSONCPP_TEMPLATE_DELETE = delete
+#endif
+#endif
+
+#include <array>
+#include <exception>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251 4275)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+#if JSON_USE_EXCEPTION
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+ Exception(String msg);
+ ~Exception() noexcept override;
+ char const* what() const noexcept override;
+
+protected:
+ String msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+ RuntimeError(String const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ *
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+ LogicError(String const& msg);
+};
+#endif
+
+/// used internally
+JSONCPP_NORETURN void throwRuntimeError(String const& msg);
+/// used internally
+JSONCPP_NORETURN void throwLogicError(String const& msg);
+
+/** \brief Type of the value held by a Value object.
+ */
+enum ValueType {
+ nullValue = 0, ///< 'null' value
+ intValue, ///< signed integer value
+ uintValue, ///< unsigned integer value
+ realValue, ///< double value
+ stringValue, ///< UTF-8 string value
+ booleanValue, ///< bool value
+ arrayValue, ///< array value (ordered list)
+ objectValue ///< object value (collection of name/value pairs).
+};
+
+enum CommentPlacement {
+ commentBefore = 0, ///< a comment placed on the line before a value
+ commentAfterOnSameLine, ///< a comment just after a value on the same line
+ commentAfter, ///< a comment on the line after a value (only make sense for
+ /// root value)
+ numberOfCommentPlacement
+};
+
+/** \brief Type of precision for formatting of real values.
+ */
+enum PrecisionType {
+ significantDigits = 0, ///< we set max number of significant digits in string
+ decimalPlaces ///< we set max number of digits after "." in string
+};
+
+/** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignment takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+class JSON_API StaticString {
+public:
+ explicit StaticString(const char* czstring) : c_str_(czstring) {}
+
+ operator const char*() const { return c_str_; }
+
+ const char* c_str() const { return c_str_; }
+
+private:
+ const char* c_str_;
+};
+
+/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resized and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
+ *
+ * It is possible to iterate over the list of member keys of an object using
+ * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
+ */
+class JSON_API Value {
+ friend class ValueIteratorBase;
+
+public:
+ using Members = std::vector<String>;
+ using iterator = ValueIterator;
+ using const_iterator = ValueConstIterator;
+ using UInt = Json::UInt;
+ using Int = Json::Int;
+#if defined(JSON_HAS_INT64)
+ using UInt64 = Json::UInt64;
+ using Int64 = Json::Int64;
+#endif // defined(JSON_HAS_INT64)
+ using LargestInt = Json::LargestInt;
+ using LargestUInt = Json::LargestUInt;
+ using ArrayIndex = Json::ArrayIndex;
+
+ // Required for boost integration, e. g. BOOST_TEST
+ using value_type = std::string;
+
+#if JSON_USE_NULLREF
+ // Binary compatibility kludges, do not use.
+ static const Value& null;
+ static const Value& nullRef;
+#endif
+
+ // null and nullRef are deprecated, use this instead.
+ static Value const& nullSingleton();
+
+ /// Minimum signed integer value that can be stored in a Json::Value.
+ static constexpr LargestInt minLargestInt =
+ LargestInt(~(LargestUInt(-1) / 2));
+ /// Maximum signed integer value that can be stored in a Json::Value.
+ static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
+ /// Maximum unsigned integer value that can be stored in a Json::Value.
+ static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
+
+ /// Minimum signed int value that can be stored in a Json::Value.
+ static constexpr Int minInt = Int(~(UInt(-1) / 2));
+ /// Maximum signed int value that can be stored in a Json::Value.
+ static constexpr Int maxInt = Int(UInt(-1) / 2);
+ /// Maximum unsigned int value that can be stored in a Json::Value.
+ static constexpr UInt maxUInt = UInt(-1);
+
+#if defined(JSON_HAS_INT64)
+ /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+ static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
+ /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+ static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
+ /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+ static constexpr UInt64 maxUInt64 = UInt64(-1);
+#endif // defined(JSON_HAS_INT64)
+ /// Default precision for real value for string representation.
+ static constexpr UInt defaultRealPrecision = 17;
+ // The constant is hard-coded because some compiler have trouble
+ // converting Value::maxUInt64 to a double correctly (AIX/xlC).
+ // Assumes that UInt64 is a 64 bits integer.
+ static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
+// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
+// when using gcc and clang backend compilers. CZString
+// cannot be defined as private. See issue #486
+#ifdef __NVCC__
+public:
+#else
+private:
+#endif
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+ class CZString {
+ public:
+ enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy };
+ CZString(ArrayIndex index);
+ CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+ CZString(CZString const& other);
+ CZString(CZString&& other) noexcept;
+ ~CZString();
+ CZString& operator=(const CZString& other);
+ CZString& operator=(CZString&& other) noexcept;
+
+ bool operator<(CZString const& other) const;
+ bool operator==(CZString const& other) const;
+ ArrayIndex index() const;
+ // const char* c_str() const; ///< \deprecated
+ char const* data() const;
+ unsigned length() const;
+ bool isStaticString() const;
+
+ private:
+ void swap(CZString& other);
+
+ struct StringStorage {
+ unsigned policy_ : 2;
+ unsigned length_ : 30; // 1GB max
+ };
+
+ char const* cstr_; // actually, a prefixed string, unless policy is noDup
+ union {
+ ArrayIndex index_;
+ StringStorage storage_;
+ };
+ };
+
+public:
+ typedef std::map<CZString, Value> ObjectValues;
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+public:
+ /**
+ * \brief Create a default Value of the given type.
+ *
+ * This is a very useful constructor.
+ * To create an empty array, pass arrayValue.
+ * To create an empty object, pass objectValue.
+ * Another Value can then be set to this one by assignment.
+ * This is useful since clear() and resize() will not alter types.
+ *
+ * Examples:
+ * \code
+ * Json::Value null_value; // null
+ * Json::Value arr_value(Json::arrayValue); // []
+ * Json::Value obj_value(Json::objectValue); // {}
+ * \endcode
+ */
+ Value(ValueType type = nullValue);
+ Value(Int value);
+ Value(UInt value);
+#if defined(JSON_HAS_INT64)
+ Value(Int64 value);
+ Value(UInt64 value);
+#endif // if defined(JSON_HAS_INT64)
+ Value(double value);
+ Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+ Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
+ /**
+ * \brief Constructs a value from a static string.
+ *
+ * Like other value string constructor but do not duplicate the string for
+ * internal storage. The given string must remain alive after the call to
+ * this constructor.
+ *
+ * \note This works only for null-terminated strings. (We cannot change the
+ * size of this class, so we have nowhere to store the length, which might be
+ * computed later for various operations.)
+ *
+ * Example of usage:
+ * \code
+ * static StaticString foo("some text");
+ * Json::Value aValue(foo);
+ * \endcode
+ */
+ Value(const StaticString& value);
+ Value(const String& value);
+ Value(bool value);
+ Value(std::nullptr_t ptr) = delete;
+ Value(const Value& other);
+ Value(Value&& other) noexcept;
+ ~Value();
+
+ /// \note Overwrite existing comments. To preserve comments, use
+ /// #swapPayload().
+ Value& operator=(const Value& other);
+ Value& operator=(Value&& other) noexcept;
+
+ /// Swap everything.
+ void swap(Value& other);
+ /// Swap values but leave comments and source offsets in place.
+ void swapPayload(Value& other);
+
+ /// copy everything.
+ void copy(const Value& other);
+ /// copy values but leave comments and source offsets in place.
+ void copyPayload(const Value& other);
+
+ ValueType type() const;
+
+ /// Compare payload only, not comments etc.
+ bool operator<(const Value& other) const;
+ bool operator<=(const Value& other) const;
+ bool operator>=(const Value& other) const;
+ bool operator>(const Value& other) const;
+ bool operator==(const Value& other) const;
+ bool operator!=(const Value& other) const;
+ int compare(const Value& other) const;
+
+ const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+#if JSONCPP_USING_SECURE_MEMORY
+ unsigned getCStringLength() const; // Allows you to understand the length of
+ // the CString
+#endif
+ String asString() const; ///< Embedded zeroes are possible.
+ /** Get raw char* of string-value.
+ * \return false if !string. (Seg-fault if str or end are NULL.)
+ */
+ bool getString(char const** begin, char const** end) const;
+ Int asInt() const;
+ UInt asUInt() const;
+#if defined(JSON_HAS_INT64)
+ Int64 asInt64() const;
+ UInt64 asUInt64() const;
+#endif // if defined(JSON_HAS_INT64)
+ LargestInt asLargestInt() const;
+ LargestUInt asLargestUInt() const;
+ float asFloat() const;
+ double asDouble() const;
+ bool asBool() const;
+
+ bool isNull() const;
+ bool isBool() const;
+ bool isInt() const;
+ bool isInt64() const;
+ bool isUInt() const;
+ bool isUInt64() const;
+ bool isIntegral() const;
+ bool isDouble() const;
+ bool isNumeric() const;
+ bool isString() const;
+ bool isArray() const;
+ bool isObject() const;
+
+ /// The `as<T>` and `is<T>` member function templates and specializations.
+ template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
+ template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
+
+ bool isConvertibleTo(ValueType other) const;
+
+ /// Number of values in array or object
+ ArrayIndex size() const;
+
+ /// \brief Return true if empty array, empty object, or null;
+ /// otherwise, false.
+ bool empty() const;
+
+ /// Return !isNull()
+ explicit operator bool() const;
+
+ /// Remove all object members and array elements.
+ /// \pre type() is arrayValue, objectValue, or nullValue
+ /// \post type() is unchanged
+ void clear();
+
+ /// Resize the array to newSize elements.
+ /// New elements are initialized to null.
+ /// May only be called on nullValue or arrayValue.
+ /// \pre type() is arrayValue or nullValue
+ /// \post type() is arrayValue
+ void resize(ArrayIndex newSize);
+
+ //@{
+ /// Access an array element (zero based index). If the array contains less
+ /// than index element, then null value are inserted in the array so that
+ /// its size is index+1.
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ Value& operator[](ArrayIndex index);
+ Value& operator[](int index);
+ //@}
+
+ //@{
+ /// Access an array element (zero based index).
+ /// (You may need to say 'value[0u]' to get your compiler to distinguish
+ /// this from the operator[] which takes a string.)
+ const Value& operator[](ArrayIndex index) const;
+ const Value& operator[](int index) const;
+ //@}
+
+ /// If the array contains at least index+1 elements, returns the element
+ /// value, otherwise returns defaultValue.
+ Value get(ArrayIndex index, const Value& defaultValue) const;
+ /// Return true if index < size().
+ bool isValidIndex(ArrayIndex index) const;
+ /// \brief Append value to array at the end.
+ ///
+ /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+ Value& append(const Value& value);
+ Value& append(Value&& value);
+
+ /// \brief Insert value in array at specific index
+ bool insert(ArrayIndex index, const Value& newValue);
+ bool insert(ArrayIndex index, Value&& newValue);
+
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+ /// Exceeding that will cause an exception.
+ Value& operator[](const char* key);
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ const Value& operator[](const char* key) const;
+ /// Access an object value by name, create a null member if it does not exist.
+ /// \param key may contain embedded nulls.
+ Value& operator[](const String& key);
+ /// Access an object value by name, returns null if there is no member with
+ /// that name.
+ /// \param key may contain embedded nulls.
+ const Value& operator[](const String& key) const;
+ /** \brief Access an object value by name, create a null member if it does not
+ * exist.
+ *
+ * If the object has no entry for that name, then the member name used to
+ * store the new entry is not duplicated.
+ * Example of use:
+ * \code
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+ Value& operator[](const StaticString& key);
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ Value get(const char* key, const Value& defaultValue) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ /// \note key may contain embedded nulls.
+ Value get(const char* begin, const char* end,
+ const Value& defaultValue) const;
+ /// Return the member named key if it exist, defaultValue otherwise.
+ /// \note deep copy
+ /// \param key may contain embedded nulls.
+ Value get(const String& key, const Value& defaultValue) const;
+ /// Most general and efficient version of isMember()const, get()const,
+ /// and operator[]const
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+ Value const* find(char const* begin, char const* end) const;
+ /// Most general and efficient version of object-mutators.
+ /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+ /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+ Value* demand(char const* begin, char const* end);
+ /// \brief Remove and return the named member.
+ ///
+ /// Do nothing if it did not exist.
+ /// \pre type() is objectValue or nullValue
+ /// \post type() is unchanged
+ void removeMember(const char* key);
+ /// Same as removeMember(const char*)
+ /// \param key may contain embedded nulls.
+ void removeMember(const String& key);
+ /// Same as removeMember(const char* begin, const char* end, Value* removed),
+ /// but 'key' is null-terminated.
+ bool removeMember(const char* key, Value* removed);
+ /** \brief Remove the named map member.
+ *
+ * Update 'removed' iff removed.
+ * \param key may contain embedded nulls.
+ * \return true iff removed (no exceptions)
+ */
+ bool removeMember(String const& key, Value* removed);
+ /// Same as removeMember(String const& key, Value* removed)
+ bool removeMember(const char* begin, const char* end, Value* removed);
+ /** \brief Remove the indexed array element.
+ *
+ * O(n) expensive operations.
+ * Update 'removed' iff removed.
+ * \return true if removed (no exceptions)
+ */
+ bool removeIndex(ArrayIndex index, Value* removed);
+
+ /// Return true if the object has a member named key.
+ /// \note 'key' must be null-terminated.
+ bool isMember(const char* key) const;
+ /// Return true if the object has a member named key.
+ /// \param key may contain embedded nulls.
+ bool isMember(const String& key) const;
+ /// Same as isMember(String const& key)const
+ bool isMember(const char* begin, const char* end) const;
+
+ /// \brief Return a list of the member names.
+ ///
+ /// If null, return an empty list.
+ /// \pre type() is objectValue or nullValue
+ /// \post if type() was nullValue, it remains nullValue
+ Members getMemberNames() const;
+
+ /// \deprecated Always pass len.
+ JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
+ void setComment(const char* comment, CommentPlacement placement) {
+ setComment(String(comment, strlen(comment)), placement);
+ }
+ /// Comments must be //... or /* ... */
+ void setComment(const char* comment, size_t len, CommentPlacement placement) {
+ setComment(String(comment, len), placement);
+ }
+ /// Comments must be //... or /* ... */
+ void setComment(String comment, CommentPlacement placement);
+ bool hasComment(CommentPlacement placement) const;
+ /// Include delimiters and embedded newlines.
+ String getComment(CommentPlacement placement) const;
+
+ String toStyledString() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ iterator begin();
+ iterator end();
+
+ // Accessors for the [start, limit) range of bytes within the JSON text from
+ // which this value was parsed, if any.
+ void setOffsetStart(ptrdiff_t start);
+ void setOffsetLimit(ptrdiff_t limit);
+ ptrdiff_t getOffsetStart() const;
+ ptrdiff_t getOffsetLimit() const;
+
+private:
+ void setType(ValueType v) {
+ bits_.value_type_ = static_cast<unsigned char>(v);
+ }
+ bool isAllocated() const { return bits_.allocated_; }
+ void setIsAllocated(bool v) { bits_.allocated_ = v; }
+
+ void initBasic(ValueType type, bool allocated = false);
+ void dupPayload(const Value& other);
+ void releasePayload();
+ void dupMeta(const Value& other);
+
+ Value& resolveReference(const char* key);
+ Value& resolveReference(const char* key, const char* end);
+
+ // struct MemberNamesTransform
+ //{
+ // typedef const char *result_type;
+ // const char *operator()( const CZString &name ) const
+ // {
+ // return name.c_str();
+ // }
+ //};
+
+ union ValueHolder {
+ LargestInt int_;
+ LargestUInt uint_;
+ double real_;
+ bool bool_;
+ char* string_; // if allocated_, ptr to { unsigned, char[] }.
+ ObjectValues* map_;
+ } value_;
+
+ struct {
+ // Really a ValueType, but types should agree for bitfield packing.
+ unsigned int value_type_ : 8;
+ // Unless allocated_, string_ must be null-terminated.
+ unsigned int allocated_ : 1;
+ } bits_;
+
+ class Comments {
+ public:
+ Comments() = default;
+ Comments(const Comments& that);
+ Comments(Comments&& that) noexcept;
+ Comments& operator=(const Comments& that);
+ Comments& operator=(Comments&& that) noexcept;
+ bool has(CommentPlacement slot) const;
+ String get(CommentPlacement slot) const;
+ void set(CommentPlacement slot, String comment);
+
+ private:
+ using Array = std::array<String, numberOfCommentPlacement>;
+ std::unique_ptr<Array> ptr_;
+ };
+ Comments comments_;
+
+ // [start, limit) byte offsets in the source JSON text from which this Value
+ // was extracted.
+ ptrdiff_t start_;
+ ptrdiff_t limit_;
+};
+
+template <> inline bool Value::as<bool>() const { return asBool(); }
+template <> inline bool Value::is<bool>() const { return isBool(); }
+
+template <> inline Int Value::as<Int>() const { return asInt(); }
+template <> inline bool Value::is<Int>() const { return isInt(); }
+
+template <> inline UInt Value::as<UInt>() const { return asUInt(); }
+template <> inline bool Value::is<UInt>() const { return isUInt(); }
+
+#if defined(JSON_HAS_INT64)
+template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
+template <> inline bool Value::is<Int64>() const { return isInt64(); }
+
+template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
+template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
+#endif
+
+template <> inline double Value::as<double>() const { return asDouble(); }
+template <> inline bool Value::is<double>() const { return isDouble(); }
+
+template <> inline String Value::as<String>() const { return asString(); }
+template <> inline bool Value::is<String>() const { return isString(); }
+
+/// These `as` specializations are type conversions, and do not have a
+/// corresponding `is`.
+template <> inline float Value::as<float>() const { return asFloat(); }
+template <> inline const char* Value::as<const char*>() const {
+ return asCString();
+}
+
+/** \brief Experimental and untested: represents an element of the "path" to
+ * access a node.
+ */
+class JSON_API PathArgument {
+public:
+ friend class Path;
+
+ PathArgument();
+ PathArgument(ArrayIndex index);
+ PathArgument(const char* key);
+ PathArgument(String key);
+
+private:
+ enum Kind { kindNone = 0, kindIndex, kindKey };
+ String key_;
+ ArrayIndex index_{};
+ Kind kind_{kindNone};
+};
+
+/** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provided as parameter
+ */
+class JSON_API Path {
+public:
+ Path(const String& path, const PathArgument& a1 = PathArgument(),
+ const PathArgument& a2 = PathArgument(),
+ const PathArgument& a3 = PathArgument(),
+ const PathArgument& a4 = PathArgument(),
+ const PathArgument& a5 = PathArgument());
+
+ const Value& resolve(const Value& root) const;
+ Value resolve(const Value& root, const Value& defaultValue) const;
+ /// Creates the "path" to access the specified node and returns a reference on
+ /// the node.
+ Value& make(Value& root) const;
+
+private:
+ using InArgs = std::vector<const PathArgument*>;
+ using Args = std::vector<PathArgument>;
+
+ void makePath(const String& path, const InArgs& in);
+ void addPathInArg(const String& path, const InArgs& in,
+ InArgs::const_iterator& itInArg, PathArgument::Kind kind);
+ static void invalidPath(const String& path, int location);
+
+ Args args_;
+};
+
+/** \brief base class for Value iterators.
+ *
+ */
+class JSON_API ValueIteratorBase {
+public:
+ using iterator_category = std::bidirectional_iterator_tag;
+ using size_t = unsigned int;
+ using difference_type = int;
+ using SelfType = ValueIteratorBase;
+
+ bool operator==(const SelfType& other) const { return isEqual(other); }
+
+ bool operator!=(const SelfType& other) const { return !isEqual(other); }
+
+ difference_type operator-(const SelfType& other) const {
+ return other.computeDistance(*this);
+ }
+
+ /// Return either the index or the member name of the referenced value as a
+ /// Value.
+ Value key() const;
+
+ /// Return the index of the referenced Value, or -1 if it is not an
+ /// arrayValue.
+ UInt index() const;
+
+ /// Return the member name of the referenced Value, or "" if it is not an
+ /// objectValue.
+ /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+ String name() const;
+
+ /// Return the member name of the referenced Value. "" if it is not an
+ /// objectValue.
+ /// \deprecated This cannot be used for UTF-8 strings, since there can be
+ /// embedded nulls.
+ JSONCPP_DEPRECATED("Use `key = name();` instead.")
+ char const* memberName() const;
+ /// Return the member name of the referenced Value, or NULL if it is not an
+ /// objectValue.
+ /// \note Better version than memberName(). Allows embedded nulls.
+ char const* memberName(char const** end) const;
+
+protected:
+ /*! Internal utility functions to assist with implementing
+ * other iterator functions. The const and non-const versions
+ * of the "deref" protected methods expose the protected
+ * current_ member variable in a way that can often be
+ * optimized away by the compiler.
+ */
+ const Value& deref() const;
+ Value& deref();
+
+ void increment();
+
+ void decrement();
+
+ difference_type computeDistance(const SelfType& other) const;
+
+ bool isEqual(const SelfType& other) const;
+
+ void copy(const SelfType& other);
+
+private:
+ Value::ObjectValues::iterator current_;
+ // Indicates that iterator is for a null value.
+ bool isNull_{true};
+
+public:
+ // For some reason, BORLAND needs these at the end, rather
+ // than earlier. No idea why.
+ ValueIteratorBase();
+ explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
+};
+
+/** \brief const iterator for object and array value.
+ *
+ */
+class JSON_API ValueConstIterator : public ValueIteratorBase {
+ friend class Value;
+
+public:
+ using value_type = const Value;
+ // typedef unsigned int size_t;
+ // typedef int difference_type;
+ using reference = const Value&;
+ using pointer = const Value*;
+ using SelfType = ValueConstIterator;
+
+ ValueConstIterator();
+ ValueConstIterator(ValueIterator const& other);
+
+private:
+ /*! \internal Use by Value to create an iterator.
+ */
+ explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+
+public:
+ SelfType& operator=(const ValueIteratorBase& other);
+
+ SelfType operator++(int) {
+ SelfType temp(*this);
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--(int) {
+ SelfType temp(*this);
+ --*this;
+ return temp;
+ }
+
+ SelfType& operator--() {
+ decrement();
+ return *this;
+ }
+
+ SelfType& operator++() {
+ increment();
+ return *this;
+ }
+
+ reference operator*() const { return deref(); }
+
+ pointer operator->() const { return &deref(); }
+};
+
+/** \brief Iterator for object and array value.
+ */
+class JSON_API ValueIterator : public ValueIteratorBase {
+ friend class Value;
+
+public:
+ using value_type = Value;
+ using size_t = unsigned int;
+ using difference_type = int;
+ using reference = Value&;
+ using pointer = Value*;
+ using SelfType = ValueIterator;
+
+ ValueIterator();
+ explicit ValueIterator(const ValueConstIterator& other);
+ ValueIterator(const ValueIterator& other);
+
+private:
+ /*! \internal Use by Value to create an iterator.
+ */
+ explicit ValueIterator(const Value::ObjectValues::iterator& current);
+
+public:
+ SelfType& operator=(const SelfType& other);
+
+ SelfType operator++(int) {
+ SelfType temp(*this);
+ ++*this;
+ return temp;
+ }
+
+ SelfType operator--(int) {
+ SelfType temp(*this);
+ --*this;
+ return temp;
+ }
+
+ SelfType& operator--() {
+ decrement();
+ return *this;
+ }
+
+ SelfType& operator++() {
+ increment();
+ return *this;
+ }
+
+ /*! The return value of non-const iterators can be
+ * changed, so the these functions are not const
+ * because the returned references/pointers can be used
+ * to change state of the base class.
+ */
+ reference operator*() const { return const_cast<reference>(deref()); }
+ pointer operator->() const { return const_cast<pointer>(&deref()); }
+};
+
+inline void swap(Value& a, Value& b) { a.swap(b); }
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/version.h b/thirdparty/openxr/src/external/jsoncpp/include/json/version.h
new file mode 100644
index 0000000000..e931d0383e
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/version.h
@@ -0,0 +1,28 @@
+#ifndef JSON_VERSION_H_INCLUDED
+#define JSON_VERSION_H_INCLUDED
+
+// Note: version must be updated in three places when doing a release. This
+// annoying process ensures that amalgamate, CMake, and meson all report the
+// correct version.
+// 1. /meson.build
+// 2. /include/json/version.h
+// 3. /CMakeLists.txt
+// IMPORTANT: also update the SOVERSION!!
+
+#define JSONCPP_VERSION_STRING "1.9.5"
+#define JSONCPP_VERSION_MAJOR 1
+#define JSONCPP_VERSION_MINOR 9
+#define JSONCPP_VERSION_PATCH 5
+#define JSONCPP_VERSION_QUALIFIER
+#define JSONCPP_VERSION_HEXA \
+ ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
+ (JSONCPP_VERSION_PATCH << 8))
+
+#ifdef JSONCPP_USING_SECURE_MEMORY
+#undef JSONCPP_USING_SECURE_MEMORY
+#endif
+#define JSONCPP_USING_SECURE_MEMORY 0
+// If non-zero, the library zeroes any memory that it has allocated before
+// it frees its memory.
+
+#endif // JSON_VERSION_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h b/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h
new file mode 100644
index 0000000000..88a3b12e9d
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/include/json/writer.h
@@ -0,0 +1,369 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+#define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <ostream>
+#include <string>
+#include <vector>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#pragma pack(push, 8)
+
+namespace Json {
+
+class Value;
+
+/**
+ *
+ * Usage:
+ * \code
+ * using namespace Json;
+ * void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
+ * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
+ * writer->write(value, &std::cout);
+ * std::cout << std::endl; // add lf and flush
+ * }
+ * \endcode
+ */
+class JSON_API StreamWriter {
+protected:
+ OStream* sout_; // not owned; will not delete
+public:
+ StreamWriter();
+ virtual ~StreamWriter();
+ /** Write Value into document as configured in sub-class.
+ * Do not take ownership of sout, but maintain a reference during function.
+ * \pre sout != NULL
+ * \return zero on success (For now, we always return zero, so check the
+ * stream instead.) \throw std::exception possibly, depending on
+ * configuration
+ */
+ virtual int write(Value const& root, OStream* sout) = 0;
+
+ /** \brief A simple abstract factory.
+ */
+ class JSON_API Factory {
+ public:
+ virtual ~Factory();
+ /** \brief Allocate a CharReader via operator new().
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ virtual StreamWriter* newStreamWriter() const = 0;
+ }; // Factory
+}; // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+String JSON_API writeString(StreamWriter::Factory const& factory,
+ Value const& root);
+
+/** \brief Build a StreamWriter implementation.
+
+* Usage:
+* \code
+* using namespace Json;
+* Value value = ...;
+* StreamWriterBuilder builder;
+* builder["commentStyle"] = "None";
+* builder["indentation"] = " "; // or whatever you like
+* std::unique_ptr<Json::StreamWriter> writer(
+* builder.newStreamWriter());
+* writer->write(value, &std::cout);
+* std::cout << std::endl; // add lf and flush
+* \endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+ // Note: We use a Json::Value so that we can add data-members to this class
+ // without a major version bump.
+ /** Configuration of this builder.
+ * Available settings (case-sensitive):
+ * - "commentStyle": "None" or "All"
+ * - "indentation": "<anything>".
+ * - Setting this to an empty string also omits newline characters.
+ * - "enableYAMLCompatibility": false or true
+ * - slightly change the whitespace around colons
+ * - "dropNullPlaceholders": false or true
+ * - Drop the "null" string from the writer's output for nullValues.
+ * Strictly speaking, this is not valid JSON. But when the output is being
+ * fed to a browser's JavaScript, it makes for smaller output and the
+ * browser can handle the output just fine.
+ * - "useSpecialFloats": false or true
+ * - If true, outputs non-finite floating point values in the following way:
+ * NaN values as "NaN", positive infinity as "Infinity", and negative
+ * infinity as "-Infinity".
+ * - "precision": int
+ * - Number of precision digits for formatting of real values.
+ * - "precisionType": "significant"(default) or "decimal"
+ * - Type of precision for formatting of real values.
+ * - "emitUTF8": false or true
+ * - If true, outputs raw UTF8 strings instead of escaping them.
+
+ * You can examine 'settings_` yourself
+ * to see the defaults. You can also write and read them just like any
+ * JSON Value.
+ * \sa setDefaults()
+ */
+ Json::Value settings_;
+
+ StreamWriterBuilder();
+ ~StreamWriterBuilder() override;
+
+ /**
+ * \throw std::exception if something goes wrong (e.g. invalid settings)
+ */
+ StreamWriter* newStreamWriter() const override;
+
+ /** \return true if 'settings' are legal and consistent;
+ * otherwise, indicate bad settings via 'invalid'.
+ */
+ bool validate(Json::Value* invalid) const;
+ /** A simple way to update a specific setting.
+ */
+ Value& operator[](const String& key);
+
+ /** Called by ctor, but you can use this to reset settings_.
+ * \pre 'settings' != NULL (but Json::null is fine)
+ * \remark Defaults:
+ * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+ */
+ static void setDefaults(Json::Value* settings);
+};
+
+/** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ */
+class JSON_API Writer {
+public:
+ virtual ~Writer();
+
+ virtual String write(const Value& root) = 0;
+};
+
+/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
+ *without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human'
+ *consumption,
+ * but may be useful to support feature such as RPC where bandwidth is limited.
+ * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
+ */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSON_API FastWriter
+ : public Writer {
+public:
+ FastWriter();
+ ~FastWriter() override = default;
+
+ void enableYAMLCompatibility();
+
+ /** \brief Drop the "null" string from the writer's output for nullValues.
+ * Strictly speaking, this is not valid JSON. But when the output is being
+ * fed to a browser's JavaScript, it makes for smaller output and the
+ * browser can handle the output just fine.
+ */
+ void dropNullPlaceholders();
+
+ void omitEndingLineFeed();
+
+public: // overridden from Writer
+ String write(const Value& root) override;
+
+private:
+ void writeValue(const Value& value);
+
+ String document_;
+ bool yamlCompatibilityEnabled_{false};
+ bool dropNullPlaceholders_{false};
+ bool omitEndingLineFeed_{false};
+};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ *human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per
+ *line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value
+ *types,
+ * and all the values fit on one lines, then print the array on a single
+ *line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ *#CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSON_API
+ StyledWriter : public Writer {
+public:
+ StyledWriter();
+ ~StyledWriter() override = default;
+
+public: // overridden from Writer
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param root Value to serialize.
+ * \return String containing the JSON document that represents the root value.
+ */
+ String write(const Value& root) override;
+
+private:
+ void writeValue(const Value& value);
+ void writeArrayValue(const Value& value);
+ bool isMultilineArray(const Value& value);
+ void pushValue(const String& value);
+ void writeIndent();
+ void writeWithIndent(const String& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(const Value& root);
+ void writeCommentAfterValueOnSameLine(const Value& root);
+ static bool hasCommentForValue(const Value& value);
+ static String normalizeEOL(const String& text);
+
+ using ChildValues = std::vector<String>;
+
+ ChildValues childValues_;
+ String document_;
+ String indentString_;
+ unsigned int rightMargin_{74};
+ unsigned int indentSize_{3};
+ bool addChildValues_{false};
+};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ human friendly way,
+ to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ * - if empty then print {} without indent and line break
+ * - if not empty the print '{', line break & indent, print one value per
+ line
+ * and then unindent and line break and print '}'.
+ * - Array value:
+ * - if empty then print [] without indent and line break
+ * - if the array contains no object value, empty array or some other value
+ types,
+ * and all the values fit on one lines, then print the array on a single
+ line.
+ * - otherwise, it the values do not fit on one line, or the array contains
+ * object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ #CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4996) // Deriving from deprecated class
+#endif
+class JSON_API
+ StyledStreamWriter {
+public:
+ /**
+ * \param indentation Each level will be indented by this amount extra.
+ */
+ StyledStreamWriter(String indentation = "\t");
+ ~StyledStreamWriter() = default;
+
+public:
+ /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+ * \param out Stream to write to. (Can be ostringstream, e.g.)
+ * \param root Value to serialize.
+ * \note There is no point in deriving from Writer, since write() should not
+ * return a value.
+ */
+ void write(OStream& out, const Value& root);
+
+private:
+ void writeValue(const Value& value);
+ void writeArrayValue(const Value& value);
+ bool isMultilineArray(const Value& value);
+ void pushValue(const String& value);
+ void writeIndent();
+ void writeWithIndent(const String& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(const Value& root);
+ void writeCommentAfterValueOnSameLine(const Value& root);
+ static bool hasCommentForValue(const Value& value);
+ static String normalizeEOL(const String& text);
+
+ using ChildValues = std::vector<String>;
+
+ ChildValues childValues_;
+ OStream* document_;
+ String indentString_;
+ unsigned int rightMargin_{74};
+ String indentation_;
+ bool addChildValues_ : 1;
+ bool indented_ : 1;
+};
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#if defined(JSON_HAS_INT64)
+String JSON_API valueToString(Int value);
+String JSON_API valueToString(UInt value);
+#endif // if defined(JSON_HAS_INT64)
+String JSON_API valueToString(LargestInt value);
+String JSON_API valueToString(LargestUInt value);
+String JSON_API valueToString(
+ double value, unsigned int precision = Value::defaultRealPrecision,
+ PrecisionType precisionType = PrecisionType::significantDigits);
+String JSON_API valueToString(bool value);
+String JSON_API valueToQuotedString(const char* value);
+
+/// \brief Output using the StyledStreamWriter.
+/// \see Json::operator>>()
+JSON_API OStream& operator<<(OStream&, const Value& root);
+
+} // namespace Json
+
+#pragma pack(pop)
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_WRITER_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp
new file mode 100644
index 0000000000..a6a3f4e30d
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_reader.cpp
@@ -0,0 +1,1992 @@
+// Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
+// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "json_tool.h"
+#include <json/assertions.h>
+#include <json/reader.h>
+#include <json/value.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cstring>
+#include <iostream>
+#include <istream>
+#include <limits>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <utility>
+
+#include <cstdio>
+#if __cplusplus >= 201103L
+
+#if !defined(sscanf)
+#define sscanf std::sscanf
+#endif
+
+#endif //__cplusplus
+
+#if defined(_MSC_VER)
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+#endif //_MSC_VER
+
+#if defined(_MSC_VER)
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile
+// time to change the stack limit
+#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
+#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
+#endif
+
+static size_t const stackLimit_g =
+ JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+using CharReaderPtr = std::unique_ptr<CharReader>;
+#else
+using CharReaderPtr = std::auto_ptr<CharReader>;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features() = default;
+
+Features Features::all() { return {}; }
+
+Features Features::strictMode() {
+ Features features;
+ features.allowComments_ = false;
+ features.strictRoot_ = true;
+ features.allowDroppedNullPlaceholders_ = false;
+ features.allowNumericKeys_ = false;
+ return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
+ return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
+}
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader() : features_(Features::all()) {}
+
+Reader::Reader(const Features& features) : features_(features) {}
+
+bool Reader::parse(const std::string& document, Value& root,
+ bool collectComments) {
+ document_.assign(document.begin(), document.end());
+ const char* begin = document_.c_str();
+ const char* end = begin + document_.length();
+ return parse(begin, end, root, collectComments);
+}
+
+bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
+ // std::istream_iterator<char> begin(is);
+ // std::istream_iterator<char> end;
+ // Those would allow streamed input from a file, if parse() were a
+ // template function.
+
+ // Since String is reference-counted, this at least does not
+ // create an extra copy.
+ String doc(std::istreambuf_iterator<char>(is), {});
+ return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
+}
+
+bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = nullptr;
+ lastValue_ = nullptr;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ bool successful = readValue();
+ Token token;
+ skipCommentTokens(token);
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
+ if (!root.isArray() && !root.isObject()) {
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
+ return false;
+ }
+ }
+ return successful;
+}
+
+bool Reader::readValue() {
+ // readValue() may call itself only if it calls readObject() or ReadArray().
+ // These methods execute nodes_.push() just before and nodes_.pop)() just
+ // after calling readValue(). parse() executes one nodes_.push(), so > instead
+ // of >=.
+ if (nodes_.size() > stackLimit_g)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
+
+ Token token;
+ skipCommentTokens(token);
+ bool successful = true;
+
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
+ }
+
+ switch (token.type_) {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue: {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenFalse: {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenNull: {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // Else, fall through...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
+ }
+
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+void Reader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
+ do {
+ readToken(token);
+ } while (token.type_ == tokenComment);
+ } else {
+ readToken(token);
+ }
+}
+
+bool Reader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch (c) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '-':
+ token.type_ = tokenNumber;
+ readNumber();
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return ok;
+}
+
+void Reader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ ++current_;
+ else
+ break;
+ }
+}
+
+bool Reader::match(const Char* pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
+ return false;
+ int index = patternLength;
+ while (index--)
+ if (current_[index] != pattern[index])
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+bool Reader::readComment() {
+ Location commentBegin = current_ - 1;
+ Char c = getNextChar();
+ bool successful = false;
+ if (c == '*')
+ successful = readCStyleComment();
+ else if (c == '/')
+ successful = readCppStyleComment();
+ if (!successful)
+ return false;
+
+ if (collectComments_) {
+ CommentPlacement placement = commentBefore;
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (c != '*' || !containsNewLine(commentBegin, current_))
+ placement = commentAfterOnSameLine;
+ }
+
+ addComment(commentBegin, current_, placement);
+ }
+ return true;
+}
+
+String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
+ String normalized;
+ normalized.reserve(static_cast<size_t>(end - begin));
+ Reader::Location current = begin;
+ while (current != end) {
+ char c = *current++;
+ if (c == '\r') {
+ if (current != end && *current == '\n')
+ // convert dos EOL
+ ++current;
+ // convert Mac EOL
+ normalized += '\n';
+ } else {
+ normalized += c;
+ }
+ }
+ return normalized;
+}
+
+void Reader::addComment(Location begin, Location end,
+ CommentPlacement placement) {
+ assert(collectComments_);
+ const String& normalized = normalizeEOL(begin, end);
+ if (placement == commentAfterOnSameLine) {
+ assert(lastValue_ != nullptr);
+ lastValue_->setComment(normalized, placement);
+ } else {
+ commentsBefore_ += normalized;
+ }
+}
+
+bool Reader::readCStyleComment() {
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
+ break;
+ }
+ return getNextChar() == '/';
+}
+
+bool Reader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ // Consume DOS EOL. It will be normalized in addComment.
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
+ // Break on Moc OS 9 EOL.
+ break;
+ }
+ }
+ return true;
+}
+
+void Reader::readNumber() {
+ Location p = current_;
+ char c = '0'; // stopgap for already consumed character
+ // integral part
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ // fractional part
+ if (c == '.') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ // exponential part
+ if (c == 'e' || c == 'E') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ if (c == '+' || c == '-')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+}
+
+bool Reader::readString() {
+ Char c = '\0';
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '"')
+ break;
+ }
+ return c == '"';
+}
+
+bool Reader::readObject(Token& token) {
+ Token tokenName;
+ String name;
+ Value init(objectValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ while (readToken(tokenName)) {
+ bool initialTokenOk = true;
+ while (tokenName.type_ == tokenComment && initialTokenOk)
+ initialTokenOk = readToken(tokenName);
+ if (!initialTokenOk)
+ break;
+ if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+ return true;
+ name.clear();
+ if (tokenName.type_ == tokenString) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ Value numberName;
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
+ name = numberName.asString();
+ } else {
+ break;
+ }
+
+ Token colon;
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover("Missing ':' after object member name", colon,
+ tokenObjectEnd);
+ }
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenObjectEnd);
+
+ Token comma;
+ if (!readToken(comma) ||
+ (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment)) {
+ return addErrorAndRecover("Missing ',' or '}' in object declaration",
+ comma, tokenObjectEnd);
+ }
+ bool finalizeTokenOk = true;
+ while (comma.type_ == tokenComment && finalizeTokenOk)
+ finalizeTokenOk = readToken(comma);
+ if (comma.type_ == tokenObjectEnd)
+ return true;
+ }
+ return addErrorAndRecover("Missing '}' or object member name", tokenName,
+ tokenObjectEnd);
+}
+
+bool Reader::readArray(Token& token) {
+ Value init(arrayValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']') // empty array
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
+ int index = 0;
+ for (;;) {
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenArrayEnd);
+
+ Token currentToken;
+ // Accept Comment after last item in the array.
+ ok = readToken(currentToken);
+ while (currentToken.type_ == tokenComment && ok) {
+ ok = readToken(currentToken);
+ }
+ bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
+ currentToken.type_ != tokenArrayEnd);
+ if (!ok || badTokenType) {
+ return addErrorAndRecover("Missing ',' or ']' in array declaration",
+ currentToken, tokenArrayEnd);
+ }
+ if (currentToken.type_ == tokenArrayEnd)
+ break;
+ }
+ return true;
+}
+
+bool Reader::decodeNumber(Token& token) {
+ Value decoded;
+ if (!decodeNumber(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeNumber(Token& token, Value& decoded) {
+ // Attempts to parse the number as an integer. If the number is
+ // larger than the maximum supported value of an integer then
+ // we decode the number as a double.
+ Location current = token.start_;
+ bool isNegative = *current == '-';
+ if (isNegative)
+ ++current;
+ // TODO: Help the compiler do the div and mod at compile time or get rid of
+ // them.
+ Value::LargestUInt maxIntegerValue =
+ isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
+ : Value::maxLargestUInt;
+ Value::LargestUInt threshold = maxIntegerValue / 10;
+ Value::LargestUInt value = 0;
+ while (current < token.end_) {
+ Char c = *current++;
+ if (c < '0' || c > '9')
+ return decodeDouble(token, decoded);
+ auto digit(static_cast<Value::UInt>(c - '0'));
+ if (value >= threshold) {
+ // We've hit or exceeded the max value divided by 10 (rounded down). If
+ // a) we've only just touched the limit, b) this is the last digit, and
+ // c) it's small enough to fit in that rounding delta, we're okay.
+ // Otherwise treat this number as a double to avoid overflow.
+ if (value > threshold || current != token.end_ ||
+ digit > maxIntegerValue % 10) {
+ return decodeDouble(token, decoded);
+ }
+ }
+ value = value * 10 + digit;
+ }
+ if (isNegative && value == maxIntegerValue)
+ decoded = Value::minLargestInt;
+ else if (isNegative)
+ decoded = -Value::LargestInt(value);
+ else if (value <= Value::LargestUInt(Value::maxInt))
+ decoded = Value::LargestInt(value);
+ else
+ decoded = value;
+ return true;
+}
+
+bool Reader::decodeDouble(Token& token) {
+ Value decoded;
+ if (!decodeDouble(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeDouble(Token& token, Value& decoded) {
+ double value = 0;
+ String buffer(token.start_, token.end_);
+ IStringStream is(buffer);
+ if (!(is >> value))
+ return addError(
+ "'" + String(token.start_, token.end_) + "' is not a number.", token);
+ decoded = value;
+ return true;
+}
+
+bool Reader::decodeString(Token& token) {
+ String decoded_string;
+ if (!decodeString(token, decoded_string))
+ return false;
+ Value decoded(decoded_string);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool Reader::decodeString(Token& token, String& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while (current != end) {
+ Char c = *current++;
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (current == end)
+ return addError("Empty escape sequence in string", token, current);
+ Char escape = *current++;
+ switch (escape) {
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
+ }
+ } else {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode) {
+
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
+ if (*(current++) == '\\' && *(current++) == 'u') {
+ unsigned int surrogatePair;
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ } else
+ return false;
+ } else
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token, current);
+ }
+ return true;
+}
+
+bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
+ if (end - current < 4)
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.", token,
+ current);
+ int unicode = 0;
+ for (int index = 0; index < 4; ++index) {
+ Char c = *current++;
+ unicode *= 16;
+ if (c >= '0' && c <= '9')
+ unicode += c - '0';
+ else if (c >= 'a' && c <= 'f')
+ unicode += c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ unicode += c - 'A' + 10;
+ else
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token, current);
+ }
+ ret_unicode = static_cast<unsigned int>(unicode);
+ return true;
+}
+
+bool Reader::addError(const String& message, Token& token, Location extra) {
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back(info);
+ return false;
+}
+
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+ size_t const errorCount = errors_.size();
+ Token skip;
+ for (;;) {
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
+ if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+ break;
+ }
+ errors_.resize(errorCount);
+ return false;
+}
+
+bool Reader::addErrorAndRecover(const String& message, Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
+}
+
+Value& Reader::currentValue() { return *(nodes_.top()); }
+
+Reader::Char Reader::getNextChar() {
+ if (current_ == end_)
+ return 0;
+ return *current_++;
+}
+
+void Reader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const {
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while (current < location && current != end_) {
+ Char c = *current++;
+ if (c == '\r') {
+ if (*current == '\n')
+ ++current;
+ lastLineStart = current;
+ ++line;
+ } else if (c == '\n') {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+String Reader::getLocationLineAndColumn(Location location) const {
+ int line, column;
+ getLocationLineAndColumn(location, line, column);
+ char buffer[18 + 16 + 16 + 1];
+ jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ return buffer;
+}
+
+// Deprecated. Preserved for backward compatibility
+String Reader::getFormatedErrorMessages() const {
+ return getFormattedErrorMessages();
+}
+
+String Reader::getFormattedErrorMessages() const {
+ String formattedMessage;
+ for (const auto& error : errors_) {
+ formattedMessage +=
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if (error.extra_)
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+ std::vector<Reader::StructuredError> allErrors;
+ for (const auto& error : errors_) {
+ Reader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+bool Reader::pushError(const Value& value, const String& message) {
+ ptrdiff_t const length = end_ - begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = nullptr;
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::pushError(const Value& value, const String& message,
+ const Value& extra) {
+ ptrdiff_t const length = end_ - begin_;
+ if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
+ extra.getOffsetLimit() > length)
+ return false;
+ Token token;
+ token.type_ = tokenError;
+ token.start_ = begin_ + value.getOffsetStart();
+ token.end_ = begin_ + value.getOffsetLimit();
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = begin_ + extra.getOffsetStart();
+ errors_.push_back(info);
+ return true;
+}
+
+bool Reader::good() const { return errors_.empty(); }
+
+// Originally copied from the Features class (now deprecated), used internally
+// for features implementation.
+class OurFeatures {
+public:
+ static OurFeatures all();
+ bool allowComments_;
+ bool allowTrailingCommas_;
+ bool strictRoot_;
+ bool allowDroppedNullPlaceholders_;
+ bool allowNumericKeys_;
+ bool allowSingleQuotes_;
+ bool failIfExtra_;
+ bool rejectDupKeys_;
+ bool allowSpecialFloats_;
+ bool skipBom_;
+ size_t stackLimit_;
+}; // OurFeatures
+
+OurFeatures OurFeatures::all() { return {}; }
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+// Originally copied from the Reader class (now deprecated), used internally
+// for implementing JSON reading.
+class OurReader {
+public:
+ using Char = char;
+ using Location = const Char*;
+ struct StructuredError {
+ ptrdiff_t offset_start;
+ ptrdiff_t offset_limit;
+ String message;
+ };
+
+ explicit OurReader(OurFeatures const& features);
+ bool parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments = true);
+ String getFormattedErrorMessages() const;
+ std::vector<StructuredError> getStructuredErrors() const;
+
+private:
+ OurReader(OurReader const&); // no impl
+ void operator=(OurReader const&); // no impl
+
+ enum TokenType {
+ tokenEndOfStream = 0,
+ tokenObjectBegin,
+ tokenObjectEnd,
+ tokenArrayBegin,
+ tokenArrayEnd,
+ tokenString,
+ tokenNumber,
+ tokenTrue,
+ tokenFalse,
+ tokenNull,
+ tokenNaN,
+ tokenPosInf,
+ tokenNegInf,
+ tokenArraySeparator,
+ tokenMemberSeparator,
+ tokenComment,
+ tokenError
+ };
+
+ class Token {
+ public:
+ TokenType type_;
+ Location start_;
+ Location end_;
+ };
+
+ class ErrorInfo {
+ public:
+ Token token_;
+ String message_;
+ Location extra_;
+ };
+
+ using Errors = std::deque<ErrorInfo>;
+
+ bool readToken(Token& token);
+ void skipSpaces();
+ void skipBom(bool skipBom);
+ bool match(const Char* pattern, int patternLength);
+ bool readComment();
+ bool readCStyleComment(bool* containsNewLineResult);
+ bool readCppStyleComment();
+ bool readString();
+ bool readStringSingleQuote();
+ bool readNumber(bool checkInf);
+ bool readValue();
+ bool readObject(Token& token);
+ bool readArray(Token& token);
+ bool decodeNumber(Token& token);
+ bool decodeNumber(Token& token, Value& decoded);
+ bool decodeString(Token& token);
+ bool decodeString(Token& token, String& decoded);
+ bool decodeDouble(Token& token);
+ bool decodeDouble(Token& token, Value& decoded);
+ bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
+ unsigned int& unicode);
+ bool decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end, unsigned int& unicode);
+ bool addError(const String& message, Token& token, Location extra = nullptr);
+ bool recoverFromError(TokenType skipUntilToken);
+ bool addErrorAndRecover(const String& message, Token& token,
+ TokenType skipUntilToken);
+ void skipUntilSpace();
+ Value& currentValue();
+ Char getNextChar();
+ void getLocationLineAndColumn(Location location, int& line,
+ int& column) const;
+ String getLocationLineAndColumn(Location location) const;
+ void addComment(Location begin, Location end, CommentPlacement placement);
+ void skipCommentTokens(Token& token);
+
+ static String normalizeEOL(Location begin, Location end);
+ static bool containsNewLine(Location begin, Location end);
+
+ using Nodes = std::stack<Value*>;
+
+ Nodes nodes_{};
+ Errors errors_{};
+ String document_{};
+ Location begin_ = nullptr;
+ Location end_ = nullptr;
+ Location current_ = nullptr;
+ Location lastValueEnd_ = nullptr;
+ Value* lastValue_ = nullptr;
+ bool lastValueHasAComment_ = false;
+ String commentsBefore_{};
+
+ OurFeatures const features_;
+ bool collectComments_ = false;
+}; // OurReader
+
+// complete copy of Read impl, for OurReader
+
+bool OurReader::containsNewLine(OurReader::Location begin,
+ OurReader::Location end) {
+ return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
+}
+
+OurReader::OurReader(OurFeatures const& features) : features_(features) {}
+
+bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
+ bool collectComments) {
+ if (!features_.allowComments_) {
+ collectComments = false;
+ }
+
+ begin_ = beginDoc;
+ end_ = endDoc;
+ collectComments_ = collectComments;
+ current_ = begin_;
+ lastValueEnd_ = nullptr;
+ lastValue_ = nullptr;
+ commentsBefore_.clear();
+ errors_.clear();
+ while (!nodes_.empty())
+ nodes_.pop();
+ nodes_.push(&root);
+
+ // skip byte order mark if it exists at the beginning of the UTF-8 text.
+ skipBom(features_.skipBom_);
+ bool successful = readValue();
+ nodes_.pop();
+ Token token;
+ skipCommentTokens(token);
+ if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
+ addError("Extra non-whitespace after JSON value.", token);
+ return false;
+ }
+ if (collectComments_ && !commentsBefore_.empty())
+ root.setComment(commentsBefore_, commentAfter);
+ if (features_.strictRoot_) {
+ if (!root.isArray() && !root.isObject()) {
+ // Set error location to start of doc, ideally should be first token found
+ // in doc
+ token.type_ = tokenError;
+ token.start_ = beginDoc;
+ token.end_ = endDoc;
+ addError(
+ "A valid JSON document must be either an array or an object value.",
+ token);
+ return false;
+ }
+ }
+ return successful;
+}
+
+bool OurReader::readValue() {
+ // To preserve the old behaviour we cast size_t to int.
+ if (nodes_.size() > features_.stackLimit_)
+ throwRuntimeError("Exceeded stackLimit in readValue().");
+ Token token;
+ skipCommentTokens(token);
+ bool successful = true;
+
+ if (collectComments_ && !commentsBefore_.empty()) {
+ currentValue().setComment(commentsBefore_, commentBefore);
+ commentsBefore_.clear();
+ }
+
+ switch (token.type_) {
+ case tokenObjectBegin:
+ successful = readObject(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenArrayBegin:
+ successful = readArray(token);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ case tokenNumber:
+ successful = decodeNumber(token);
+ break;
+ case tokenString:
+ successful = decodeString(token);
+ break;
+ case tokenTrue: {
+ Value v(true);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenFalse: {
+ Value v(false);
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenNull: {
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenNaN: {
+ Value v(std::numeric_limits<double>::quiet_NaN());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenPosInf: {
+ Value v(std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenNegInf: {
+ Value v(-std::numeric_limits<double>::infinity());
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ } break;
+ case tokenArraySeparator:
+ case tokenObjectEnd:
+ case tokenArrayEnd:
+ if (features_.allowDroppedNullPlaceholders_) {
+ // "Un-read" the current token and mark the current value as a null
+ // token.
+ current_--;
+ Value v;
+ currentValue().swapPayload(v);
+ currentValue().setOffsetStart(current_ - begin_ - 1);
+ currentValue().setOffsetLimit(current_ - begin_);
+ break;
+ } // else, fall through ...
+ default:
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return addError("Syntax error: value, object or array expected.", token);
+ }
+
+ if (collectComments_) {
+ lastValueEnd_ = current_;
+ lastValueHasAComment_ = false;
+ lastValue_ = &currentValue();
+ }
+
+ return successful;
+}
+
+void OurReader::skipCommentTokens(Token& token) {
+ if (features_.allowComments_) {
+ do {
+ readToken(token);
+ } while (token.type_ == tokenComment);
+ } else {
+ readToken(token);
+ }
+}
+
+bool OurReader::readToken(Token& token) {
+ skipSpaces();
+ token.start_ = current_;
+ Char c = getNextChar();
+ bool ok = true;
+ switch (c) {
+ case '{':
+ token.type_ = tokenObjectBegin;
+ break;
+ case '}':
+ token.type_ = tokenObjectEnd;
+ break;
+ case '[':
+ token.type_ = tokenArrayBegin;
+ break;
+ case ']':
+ token.type_ = tokenArrayEnd;
+ break;
+ case '"':
+ token.type_ = tokenString;
+ ok = readString();
+ break;
+ case '\'':
+ if (features_.allowSingleQuotes_) {
+ token.type_ = tokenString;
+ ok = readStringSingleQuote();
+ } else {
+ // If we don't allow single quotes, this is a failure case.
+ ok = false;
+ }
+ break;
+ case '/':
+ token.type_ = tokenComment;
+ ok = readComment();
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ token.type_ = tokenNumber;
+ readNumber(false);
+ break;
+ case '-':
+ if (readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenNegInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
+ break;
+ case '+':
+ if (readNumber(true)) {
+ token.type_ = tokenNumber;
+ } else {
+ token.type_ = tokenPosInf;
+ ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+ }
+ break;
+ case 't':
+ token.type_ = tokenTrue;
+ ok = match("rue", 3);
+ break;
+ case 'f':
+ token.type_ = tokenFalse;
+ ok = match("alse", 4);
+ break;
+ case 'n':
+ token.type_ = tokenNull;
+ ok = match("ull", 3);
+ break;
+ case 'N':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenNaN;
+ ok = match("aN", 2);
+ } else {
+ ok = false;
+ }
+ break;
+ case 'I':
+ if (features_.allowSpecialFloats_) {
+ token.type_ = tokenPosInf;
+ ok = match("nfinity", 7);
+ } else {
+ ok = false;
+ }
+ break;
+ case ',':
+ token.type_ = tokenArraySeparator;
+ break;
+ case ':':
+ token.type_ = tokenMemberSeparator;
+ break;
+ case 0:
+ token.type_ = tokenEndOfStream;
+ break;
+ default:
+ ok = false;
+ break;
+ }
+ if (!ok)
+ token.type_ = tokenError;
+ token.end_ = current_;
+ return ok;
+}
+
+void OurReader::skipSpaces() {
+ while (current_ != end_) {
+ Char c = *current_;
+ if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ ++current_;
+ else
+ break;
+ }
+}
+
+void OurReader::skipBom(bool skipBom) {
+ // The default behavior is to skip BOM.
+ if (skipBom) {
+ if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
+ begin_ += 3;
+ current_ = begin_;
+ }
+ }
+}
+
+bool OurReader::match(const Char* pattern, int patternLength) {
+ if (end_ - current_ < patternLength)
+ return false;
+ int index = patternLength;
+ while (index--)
+ if (current_[index] != pattern[index])
+ return false;
+ current_ += patternLength;
+ return true;
+}
+
+bool OurReader::readComment() {
+ const Location commentBegin = current_ - 1;
+ const Char c = getNextChar();
+ bool successful = false;
+ bool cStyleWithEmbeddedNewline = false;
+
+ const bool isCStyleComment = (c == '*');
+ const bool isCppStyleComment = (c == '/');
+ if (isCStyleComment) {
+ successful = readCStyleComment(&cStyleWithEmbeddedNewline);
+ } else if (isCppStyleComment) {
+ successful = readCppStyleComment();
+ }
+
+ if (!successful)
+ return false;
+
+ if (collectComments_) {
+ CommentPlacement placement = commentBefore;
+
+ if (!lastValueHasAComment_) {
+ if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+ if (isCppStyleComment || !cStyleWithEmbeddedNewline) {
+ placement = commentAfterOnSameLine;
+ lastValueHasAComment_ = true;
+ }
+ }
+ }
+
+ addComment(commentBegin, current_, placement);
+ }
+ return true;
+}
+
+String OurReader::normalizeEOL(OurReader::Location begin,
+ OurReader::Location end) {
+ String normalized;
+ normalized.reserve(static_cast<size_t>(end - begin));
+ OurReader::Location current = begin;
+ while (current != end) {
+ char c = *current++;
+ if (c == '\r') {
+ if (current != end && *current == '\n')
+ // convert dos EOL
+ ++current;
+ // convert Mac EOL
+ normalized += '\n';
+ } else {
+ normalized += c;
+ }
+ }
+ return normalized;
+}
+
+void OurReader::addComment(Location begin, Location end,
+ CommentPlacement placement) {
+ assert(collectComments_);
+ const String& normalized = normalizeEOL(begin, end);
+ if (placement == commentAfterOnSameLine) {
+ assert(lastValue_ != nullptr);
+ lastValue_->setComment(normalized, placement);
+ } else {
+ commentsBefore_ += normalized;
+ }
+}
+
+bool OurReader::readCStyleComment(bool* containsNewLineResult) {
+ *containsNewLineResult = false;
+
+ while ((current_ + 1) < end_) {
+ Char c = getNextChar();
+ if (c == '*' && *current_ == '/')
+ break;
+ if (c == '\n')
+ *containsNewLineResult = true;
+ }
+
+ return getNextChar() == '/';
+}
+
+bool OurReader::readCppStyleComment() {
+ while (current_ != end_) {
+ Char c = getNextChar();
+ if (c == '\n')
+ break;
+ if (c == '\r') {
+ // Consume DOS EOL. It will be normalized in addComment.
+ if (current_ != end_ && *current_ == '\n')
+ getNextChar();
+ // Break on Moc OS 9 EOL.
+ break;
+ }
+ }
+ return true;
+}
+
+bool OurReader::readNumber(bool checkInf) {
+ Location p = current_;
+ if (checkInf && p != end_ && *p == 'I') {
+ current_ = ++p;
+ return false;
+ }
+ char c = '0'; // stopgap for already consumed character
+ // integral part
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ // fractional part
+ if (c == '.') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ // exponential part
+ if (c == 'e' || c == 'E') {
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ if (c == '+' || c == '-')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ while (c >= '0' && c <= '9')
+ c = (current_ = p) < end_ ? *p++ : '\0';
+ }
+ return true;
+}
+bool OurReader::readString() {
+ Char c = 0;
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '"')
+ break;
+ }
+ return c == '"';
+}
+
+bool OurReader::readStringSingleQuote() {
+ Char c = 0;
+ while (current_ != end_) {
+ c = getNextChar();
+ if (c == '\\')
+ getNextChar();
+ else if (c == '\'')
+ break;
+ }
+ return c == '\'';
+}
+
+bool OurReader::readObject(Token& token) {
+ Token tokenName;
+ String name;
+ Value init(objectValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ while (readToken(tokenName)) {
+ bool initialTokenOk = true;
+ while (tokenName.type_ == tokenComment && initialTokenOk)
+ initialTokenOk = readToken(tokenName);
+ if (!initialTokenOk)
+ break;
+ if (tokenName.type_ == tokenObjectEnd &&
+ (name.empty() ||
+ features_.allowTrailingCommas_)) // empty object or trailing comma
+ return true;
+ name.clear();
+ if (tokenName.type_ == tokenString) {
+ if (!decodeString(tokenName, name))
+ return recoverFromError(tokenObjectEnd);
+ } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+ Value numberName;
+ if (!decodeNumber(tokenName, numberName))
+ return recoverFromError(tokenObjectEnd);
+ name = numberName.asString();
+ } else {
+ break;
+ }
+ if (name.length() >= (1U << 30))
+ throwRuntimeError("keylength >= 2^30");
+ if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+ String msg = "Duplicate key: '" + name + "'";
+ return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
+ }
+
+ Token colon;
+ if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+ return addErrorAndRecover("Missing ':' after object member name", colon,
+ tokenObjectEnd);
+ }
+ Value& value = currentValue()[name];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenObjectEnd);
+
+ Token comma;
+ if (!readToken(comma) ||
+ (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+ comma.type_ != tokenComment)) {
+ return addErrorAndRecover("Missing ',' or '}' in object declaration",
+ comma, tokenObjectEnd);
+ }
+ bool finalizeTokenOk = true;
+ while (comma.type_ == tokenComment && finalizeTokenOk)
+ finalizeTokenOk = readToken(comma);
+ if (comma.type_ == tokenObjectEnd)
+ return true;
+ }
+ return addErrorAndRecover("Missing '}' or object member name", tokenName,
+ tokenObjectEnd);
+}
+
+bool OurReader::readArray(Token& token) {
+ Value init(arrayValue);
+ currentValue().swapPayload(init);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ int index = 0;
+ for (;;) {
+ skipSpaces();
+ if (current_ != end_ && *current_ == ']' &&
+ (index == 0 ||
+ (features_.allowTrailingCommas_ &&
+ !features_.allowDroppedNullPlaceholders_))) // empty array or trailing
+ // comma
+ {
+ Token endArray;
+ readToken(endArray);
+ return true;
+ }
+ Value& value = currentValue()[index++];
+ nodes_.push(&value);
+ bool ok = readValue();
+ nodes_.pop();
+ if (!ok) // error already set
+ return recoverFromError(tokenArrayEnd);
+
+ Token currentToken;
+ // Accept Comment after last item in the array.
+ ok = readToken(currentToken);
+ while (currentToken.type_ == tokenComment && ok) {
+ ok = readToken(currentToken);
+ }
+ bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
+ currentToken.type_ != tokenArrayEnd);
+ if (!ok || badTokenType) {
+ return addErrorAndRecover("Missing ',' or ']' in array declaration",
+ currentToken, tokenArrayEnd);
+ }
+ if (currentToken.type_ == tokenArrayEnd)
+ break;
+ }
+ return true;
+}
+
+bool OurReader::decodeNumber(Token& token) {
+ Value decoded;
+ if (!decodeNumber(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
+ // Attempts to parse the number as an integer. If the number is
+ // larger than the maximum supported value of an integer then
+ // we decode the number as a double.
+ Location current = token.start_;
+ const bool isNegative = *current == '-';
+ if (isNegative) {
+ ++current;
+ }
+
+ // We assume we can represent the largest and smallest integer types as
+ // unsigned integers with separate sign. This is only true if they can fit
+ // into an unsigned integer.
+ static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
+ "Int must be smaller than UInt");
+
+ // We need to convert minLargestInt into a positive number. The easiest way
+ // to do this conversion is to assume our "threshold" value of minLargestInt
+ // divided by 10 can fit in maxLargestInt when absolute valued. This should
+ // be a safe assumption.
+ static_assert(Value::minLargestInt <= -Value::maxLargestInt,
+ "The absolute value of minLargestInt must be greater than or "
+ "equal to maxLargestInt");
+ static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
+ "The absolute value of minLargestInt must be only 1 magnitude "
+ "larger than maxLargest Int");
+
+ static constexpr Value::LargestUInt positive_threshold =
+ Value::maxLargestUInt / 10;
+ static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
+
+ // For the negative values, we have to be more careful. Since typically
+ // -Value::minLargestInt will cause an overflow, we first divide by 10 and
+ // then take the inverse. This assumes that minLargestInt is only a single
+ // power of 10 different in magnitude, which we check above. For the last
+ // digit, we take the modulus before negating for the same reason.
+ static constexpr auto negative_threshold =
+ Value::LargestUInt(-(Value::minLargestInt / 10));
+ static constexpr auto negative_last_digit =
+ Value::UInt(-(Value::minLargestInt % 10));
+
+ const Value::LargestUInt threshold =
+ isNegative ? negative_threshold : positive_threshold;
+ const Value::UInt max_last_digit =
+ isNegative ? negative_last_digit : positive_last_digit;
+
+ Value::LargestUInt value = 0;
+ while (current < token.end_) {
+ Char c = *current++;
+ if (c < '0' || c > '9')
+ return decodeDouble(token, decoded);
+
+ const auto digit(static_cast<Value::UInt>(c - '0'));
+ if (value >= threshold) {
+ // We've hit or exceeded the max value divided by 10 (rounded down). If
+ // a) we've only just touched the limit, meaing value == threshold,
+ // b) this is the last digit, or
+ // c) it's small enough to fit in that rounding delta, we're okay.
+ // Otherwise treat this number as a double to avoid overflow.
+ if (value > threshold || current != token.end_ ||
+ digit > max_last_digit) {
+ return decodeDouble(token, decoded);
+ }
+ }
+ value = value * 10 + digit;
+ }
+
+ if (isNegative) {
+ // We use the same magnitude assumption here, just in case.
+ const auto last_digit = static_cast<Value::UInt>(value % 10);
+ decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
+ } else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
+ decoded = Value::LargestInt(value);
+ } else {
+ decoded = value;
+ }
+
+ return true;
+}
+
+bool OurReader::decodeDouble(Token& token) {
+ Value decoded;
+ if (!decodeDouble(token, decoded))
+ return false;
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
+ double value = 0;
+ const String buffer(token.start_, token.end_);
+ IStringStream is(buffer);
+ if (!(is >> value)) {
+ return addError(
+ "'" + String(token.start_, token.end_) + "' is not a number.", token);
+ }
+ decoded = value;
+ return true;
+}
+
+bool OurReader::decodeString(Token& token) {
+ String decoded_string;
+ if (!decodeString(token, decoded_string))
+ return false;
+ Value decoded(decoded_string);
+ currentValue().swapPayload(decoded);
+ currentValue().setOffsetStart(token.start_ - begin_);
+ currentValue().setOffsetLimit(token.end_ - begin_);
+ return true;
+}
+
+bool OurReader::decodeString(Token& token, String& decoded) {
+ decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
+ Location current = token.start_ + 1; // skip '"'
+ Location end = token.end_ - 1; // do not include '"'
+ while (current != end) {
+ Char c = *current++;
+ if (c == '"')
+ break;
+ if (c == '\\') {
+ if (current == end)
+ return addError("Empty escape sequence in string", token, current);
+ Char escape = *current++;
+ switch (escape) {
+ case '"':
+ decoded += '"';
+ break;
+ case '/':
+ decoded += '/';
+ break;
+ case '\\':
+ decoded += '\\';
+ break;
+ case 'b':
+ decoded += '\b';
+ break;
+ case 'f':
+ decoded += '\f';
+ break;
+ case 'n':
+ decoded += '\n';
+ break;
+ case 'r':
+ decoded += '\r';
+ break;
+ case 't':
+ decoded += '\t';
+ break;
+ case 'u': {
+ unsigned int unicode;
+ if (!decodeUnicodeCodePoint(token, current, end, unicode))
+ return false;
+ decoded += codePointToUTF8(unicode);
+ } break;
+ default:
+ return addError("Bad escape sequence in string", token, current);
+ }
+ } else {
+ decoded += c;
+ }
+ }
+ return true;
+}
+
+bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
+ Location end, unsigned int& unicode) {
+
+ if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+ return false;
+ if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+ // surrogate pairs
+ if (end - current < 6)
+ return addError(
+ "additional six characters expected to parse unicode surrogate pair.",
+ token, current);
+ if (*(current++) == '\\' && *(current++) == 'u') {
+ unsigned int surrogatePair;
+ if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+ unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+ } else
+ return false;
+ } else
+ return addError("expecting another \\u token to begin the second half of "
+ "a unicode surrogate pair",
+ token, current);
+ }
+ return true;
+}
+
+bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
+ Location end,
+ unsigned int& ret_unicode) {
+ if (end - current < 4)
+ return addError(
+ "Bad unicode escape sequence in string: four digits expected.", token,
+ current);
+ int unicode = 0;
+ for (int index = 0; index < 4; ++index) {
+ Char c = *current++;
+ unicode *= 16;
+ if (c >= '0' && c <= '9')
+ unicode += c - '0';
+ else if (c >= 'a' && c <= 'f')
+ unicode += c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ unicode += c - 'A' + 10;
+ else
+ return addError(
+ "Bad unicode escape sequence in string: hexadecimal digit expected.",
+ token, current);
+ }
+ ret_unicode = static_cast<unsigned int>(unicode);
+ return true;
+}
+
+bool OurReader::addError(const String& message, Token& token, Location extra) {
+ ErrorInfo info;
+ info.token_ = token;
+ info.message_ = message;
+ info.extra_ = extra;
+ errors_.push_back(info);
+ return false;
+}
+
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+ size_t errorCount = errors_.size();
+ Token skip;
+ for (;;) {
+ if (!readToken(skip))
+ errors_.resize(errorCount); // discard errors caused by recovery
+ if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+ break;
+ }
+ errors_.resize(errorCount);
+ return false;
+}
+
+bool OurReader::addErrorAndRecover(const String& message, Token& token,
+ TokenType skipUntilToken) {
+ addError(message, token);
+ return recoverFromError(skipUntilToken);
+}
+
+Value& OurReader::currentValue() { return *(nodes_.top()); }
+
+OurReader::Char OurReader::getNextChar() {
+ if (current_ == end_)
+ return 0;
+ return *current_++;
+}
+
+void OurReader::getLocationLineAndColumn(Location location, int& line,
+ int& column) const {
+ Location current = begin_;
+ Location lastLineStart = current;
+ line = 0;
+ while (current < location && current != end_) {
+ Char c = *current++;
+ if (c == '\r') {
+ if (*current == '\n')
+ ++current;
+ lastLineStart = current;
+ ++line;
+ } else if (c == '\n') {
+ lastLineStart = current;
+ ++line;
+ }
+ }
+ // column & line start at 1
+ column = int(location - lastLineStart) + 1;
+ ++line;
+}
+
+String OurReader::getLocationLineAndColumn(Location location) const {
+ int line, column;
+ getLocationLineAndColumn(location, line, column);
+ char buffer[18 + 16 + 16 + 1];
+ jsoncpp_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+ return buffer;
+}
+
+String OurReader::getFormattedErrorMessages() const {
+ String formattedMessage;
+ for (const auto& error : errors_) {
+ formattedMessage +=
+ "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+ formattedMessage += " " + error.message_ + "\n";
+ if (error.extra_)
+ formattedMessage +=
+ "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+ }
+ return formattedMessage;
+}
+
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+ std::vector<OurReader::StructuredError> allErrors;
+ for (const auto& error : errors_) {
+ OurReader::StructuredError structured;
+ structured.offset_start = error.token_.start_ - begin_;
+ structured.offset_limit = error.token_.end_ - begin_;
+ structured.message = error.message_;
+ allErrors.push_back(structured);
+ }
+ return allErrors;
+}
+
+class OurCharReader : public CharReader {
+ bool const collectComments_;
+ OurReader reader_;
+
+public:
+ OurCharReader(bool collectComments, OurFeatures const& features)
+ : collectComments_(collectComments), reader_(features) {}
+ bool parse(char const* beginDoc, char const* endDoc, Value* root,
+ String* errs) override {
+ bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+ if (errs) {
+ *errs = reader_.getFormattedErrorMessages();
+ }
+ return ok;
+ }
+};
+
+CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
+CharReaderBuilder::~CharReaderBuilder() = default;
+CharReader* CharReaderBuilder::newCharReader() const {
+ bool collectComments = settings_["collectComments"].asBool();
+ OurFeatures features = OurFeatures::all();
+ features.allowComments_ = settings_["allowComments"].asBool();
+ features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
+ features.strictRoot_ = settings_["strictRoot"].asBool();
+ features.allowDroppedNullPlaceholders_ =
+ settings_["allowDroppedNullPlaceholders"].asBool();
+ features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+ features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+
+ // Stack limit is always a size_t, so we get this as an unsigned int
+ // regardless of it we have 64-bit integer support enabled.
+ features.stackLimit_ = static_cast<size_t>(settings_["stackLimit"].asUInt());
+ features.failIfExtra_ = settings_["failIfExtra"].asBool();
+ features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+ features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+ features.skipBom_ = settings_["skipBom"].asBool();
+ return new OurCharReader(collectComments, features);
+}
+
+bool CharReaderBuilder::validate(Json::Value* invalid) const {
+ static const auto& valid_keys = *new std::set<String>{
+ "collectComments",
+ "allowComments",
+ "allowTrailingCommas",
+ "strictRoot",
+ "allowDroppedNullPlaceholders",
+ "allowNumericKeys",
+ "allowSingleQuotes",
+ "stackLimit",
+ "failIfExtra",
+ "rejectDupKeys",
+ "allowSpecialFloats",
+ "skipBom",
+ };
+ for (auto si = settings_.begin(); si != settings_.end(); ++si) {
+ auto key = si.name();
+ if (valid_keys.count(key))
+ continue;
+ if (invalid)
+ (*invalid)[key] = *si;
+ else
+ return false;
+ }
+ return invalid ? invalid->empty() : true;
+}
+
+Value& CharReaderBuilder::operator[](const String& key) {
+ return settings_[key];
+}
+// static
+void CharReaderBuilder::strictMode(Json::Value* settings) {
+ //! [CharReaderBuilderStrictMode]
+ (*settings)["allowComments"] = false;
+ (*settings)["allowTrailingCommas"] = false;
+ (*settings)["strictRoot"] = true;
+ (*settings)["allowDroppedNullPlaceholders"] = false;
+ (*settings)["allowNumericKeys"] = false;
+ (*settings)["allowSingleQuotes"] = false;
+ (*settings)["stackLimit"] = 1000;
+ (*settings)["failIfExtra"] = true;
+ (*settings)["rejectDupKeys"] = true;
+ (*settings)["allowSpecialFloats"] = false;
+ (*settings)["skipBom"] = true;
+ //! [CharReaderBuilderStrictMode]
+}
+// static
+void CharReaderBuilder::setDefaults(Json::Value* settings) {
+ //! [CharReaderBuilderDefaults]
+ (*settings)["collectComments"] = true;
+ (*settings)["allowComments"] = true;
+ (*settings)["allowTrailingCommas"] = true;
+ (*settings)["strictRoot"] = false;
+ (*settings)["allowDroppedNullPlaceholders"] = false;
+ (*settings)["allowNumericKeys"] = false;
+ (*settings)["allowSingleQuotes"] = false;
+ (*settings)["stackLimit"] = 1000;
+ (*settings)["failIfExtra"] = false;
+ (*settings)["rejectDupKeys"] = false;
+ (*settings)["allowSpecialFloats"] = false;
+ (*settings)["skipBom"] = true;
+ //! [CharReaderBuilderDefaults]
+}
+
+//////////////////////////////////
+// global functions
+
+bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
+ String* errs) {
+ OStringStream ssin;
+ ssin << sin.rdbuf();
+ String doc = ssin.str();
+ char const* begin = doc.data();
+ char const* end = begin + doc.size();
+ // Note that we do not actually need a null-terminator.
+ CharReaderPtr const reader(fact.newCharReader());
+ return reader->parse(begin, end, root, errs);
+}
+
+IStream& operator>>(IStream& sin, Value& root) {
+ CharReaderBuilder b;
+ String errs;
+ bool ok = parseFromStream(b, sin, &root, &errs);
+ if (!ok) {
+ throwRuntimeError(errs);
+ }
+ return sin;
+}
+
+} // namespace Json
diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h
new file mode 100644
index 0000000000..b952c19167
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_tool.h
@@ -0,0 +1,138 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/config.h>
+#endif
+
+// Also support old flag NO_LOCALE_SUPPORT
+#ifdef NO_LOCALE_SUPPORT
+#define JSONCPP_NO_LOCALE_SUPPORT
+#endif
+
+#ifndef JSONCPP_NO_LOCALE_SUPPORT
+#include <clocale>
+#endif
+
+/* This header provides common string manipulation support, such as UTF-8,
+ * portable conversion from/to string...
+ *
+ * It is an internal header that must not be exposed.
+ */
+
+namespace Json {
+static inline char getDecimalPoint() {
+#ifdef JSONCPP_NO_LOCALE_SUPPORT
+ return '\0';
+#else
+ struct lconv* lc = localeconv();
+ return lc ? *(lc->decimal_point) : '\0';
+#endif
+}
+
+/// Converts a unicode code-point to UTF-8.
+static inline String codePointToUTF8(unsigned int cp) {
+ String result;
+
+ // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+ if (cp <= 0x7f) {
+ result.resize(1);
+ result[0] = static_cast<char>(cp);
+ } else if (cp <= 0x7FF) {
+ result.resize(2);
+ result[1] = static_cast<char>(0x80 | (0x3f & cp));
+ result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+ } else if (cp <= 0xFFFF) {
+ result.resize(3);
+ result[2] = static_cast<char>(0x80 | (0x3f & cp));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
+ } else if (cp <= 0x10FFFF) {
+ result.resize(4);
+ result[3] = static_cast<char>(0x80 | (0x3f & cp));
+ result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+ result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+ result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+ }
+
+ return result;
+}
+
+enum {
+ /// Constant that specify the size of the buffer that must be passed to
+ /// uintToString.
+ uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
+};
+
+// Defines a char buffer for use with uintToString().
+using UIntToStringBuffer = char[uintToStringBufferSize];
+
+/** Converts an unsigned integer to string.
+ * @param value Unsigned integer to convert to string
+ * @param current Input/Output string buffer.
+ * Must have at least uintToStringBufferSize chars free.
+ */
+static inline void uintToString(LargestUInt value, char*& current) {
+ *--current = 0;
+ do {
+ *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
+ value /= 10;
+ } while (value != 0);
+}
+
+/** Change ',' to '.' everywhere in buffer.
+ *
+ * We had a sophisticated way, but it did not work in WinCE.
+ * @see https://github.com/open-source-parsers/jsoncpp/pull/9
+ */
+template <typename Iter> Iter fixNumericLocale(Iter begin, Iter end) {
+ for (; begin != end; ++begin) {
+ if (*begin == ',') {
+ *begin = '.';
+ }
+ }
+ return begin;
+}
+
+template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
+ char decimalPoint = getDecimalPoint();
+ if (decimalPoint == '\0' || decimalPoint == '.') {
+ return;
+ }
+ for (; begin != end; ++begin) {
+ if (*begin == '.') {
+ *begin = decimalPoint;
+ }
+ }
+}
+
+/**
+ * Return iterator that would be the new end of the range [begin,end), if we
+ * were to delete zeros in the end of string, but not the last zero before '.'.
+ */
+template <typename Iter>
+Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
+ for (; begin != end; --end) {
+ if (*(end - 1) != '0') {
+ return end;
+ }
+ // Don't delete the last zero before the decimal point.
+ if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
+ if (precision) {
+ return end;
+ }
+ return end - 2;
+ }
+ }
+ return end;
+}
+
+} // namespace Json
+
+#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp
new file mode 100644
index 0000000000..aa2b744ca8
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_value.cpp
@@ -0,0 +1,1634 @@
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/value.h>
+#include <json/writer.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <utility>
+
+// Provide implementation equivalent of std::snprintf for older _MSC compilers
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#include <stdarg.h>
+static int msvc_pre1900_c99_vsnprintf(char* outBuf, size_t size,
+ const char* format, va_list ap) {
+ int count = -1;
+ if (size != 0)
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ if (count == -1)
+ count = _vscprintf(format, ap);
+ return count;
+}
+
+int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
+ const char* format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ const int count = msvc_pre1900_c99_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+ return count;
+}
+#endif
+
+// Disable warning C4702 : unreachable code
+#if defined(_MSC_VER)
+#pragma warning(disable : 4702)
+#endif
+
+#define JSON_ASSERT_UNREACHABLE assert(false)
+
+namespace Json {
+template <typename T>
+static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
+ std::unique_ptr<T> r;
+ if (p) {
+ r = std::unique_ptr<T>(new T(*p));
+ }
+ return r;
+}
+
+// This is a walkaround to avoid the static initialization of Value::null.
+// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
+// 8 (instead of 4) as a bit of future-proofing.
+#if defined(__ARMEL__)
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#else
+#define ALIGNAS(byte_alignment)
+#endif
+
+// static
+Value const& Value::nullSingleton() {
+ static Value const nullStatic;
+ return nullStatic;
+}
+
+#if JSON_USE_NULLREF
+// for backwards compatibility, we'll leave these global references around, but
+// DO NOT use them in JSONCPP library code any more!
+// static
+Value const& Value::null = Value::nullSingleton();
+
+// static
+Value const& Value::nullRef = Value::nullSingleton();
+#endif
+
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+ // The casts can lose precision, but we are looking only for
+ // an approximate range. Might fail on edge cases though. ~cdunn
+ return d >= static_cast<double>(min) && d <= static_cast<double>(max);
+}
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+static inline double integerToDouble(Json::UInt64 value) {
+ return static_cast<double>(Int64(value / 2)) * 2.0 +
+ static_cast<double>(Int64(value & 1));
+}
+
+template <typename T> static inline double integerToDouble(T value) {
+ return static_cast<double>(value);
+}
+
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+ return d >= integerToDouble(min) && d <= integerToDouble(max);
+}
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+
+/** Duplicates the specified string value.
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
+ * length is "unknown".
+ * @param length Length of the value. if equals to unknown, then it will be
+ * computed using strlen(value).
+ * @return Pointer on the duplicate instance of string.
+ */
+static inline char* duplicateStringValue(const char* value, size_t length) {
+ // Avoid an integer overflow in the call to malloc below by limiting length
+ // to a sane value.
+ if (length >= static_cast<size_t>(Value::maxInt))
+ length = Value::maxInt - 1;
+
+ auto newString = static_cast<char*>(malloc(length + 1));
+ if (newString == nullptr) {
+ throwRuntimeError("in Json::Value::duplicateStringValue(): "
+ "Failed to allocate string value buffer");
+ }
+ memcpy(newString, value, length);
+ newString[length] = 0;
+ return newString;
+}
+
+/* Record the length as a prefix.
+ */
+static inline char* duplicateAndPrefixStringValue(const char* value,
+ unsigned int length) {
+ // Avoid an integer overflow in the call to malloc below by limiting length
+ // to a sane value.
+ JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) -
+ sizeof(unsigned) - 1U,
+ "in Json::Value::duplicateAndPrefixStringValue(): "
+ "length too big for prefixing");
+ size_t actualLength = sizeof(length) + length + 1;
+ auto newString = static_cast<char*>(malloc(actualLength));
+ if (newString == nullptr) {
+ throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
+ "Failed to allocate string value buffer");
+ }
+ *reinterpret_cast<unsigned*>(newString) = length;
+ memcpy(newString + sizeof(unsigned), value, length);
+ newString[actualLength - 1U] =
+ 0; // to avoid buffer over-run accidents by users later
+ return newString;
+}
+inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
+ unsigned* length, char const** value) {
+ if (!isPrefixed) {
+ *length = static_cast<unsigned>(strlen(prefixed));
+ *value = prefixed;
+ } else {
+ *length = *reinterpret_cast<unsigned const*>(prefixed);
+ *value = prefixed + sizeof(unsigned);
+ }
+}
+/** Free the string duplicated by
+ * duplicateStringValue()/duplicateAndPrefixStringValue().
+ */
+#if JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) {
+ unsigned length = 0;
+ char const* valueDecoded;
+ decodePrefixedString(true, value, &length, &valueDecoded);
+ size_t const size = sizeof(unsigned) + length + 1U;
+ memset(value, 0, size);
+ free(value);
+}
+static inline void releaseStringValue(char* value, unsigned length) {
+ // length==0 => we allocated the strings memory
+ size_t size = (length == 0) ? strlen(value) : length;
+ memset(value, 0, size);
+ free(value);
+}
+#else // !JSONCPP_USING_SECURE_MEMORY
+static inline void releasePrefixedStringValue(char* value) { free(value); }
+static inline void releaseStringValue(char* value, unsigned) { free(value); }
+#endif // JSONCPP_USING_SECURE_MEMORY
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "json_valueiterator.inl"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+#if JSON_USE_EXCEPTION
+Exception::Exception(String msg) : msg_(std::move(msg)) {}
+Exception::~Exception() noexcept = default;
+char const* Exception::what() const noexcept { return msg_.c_str(); }
+RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
+LogicError::LogicError(String const& msg) : Exception(msg) {}
+JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
+ throw RuntimeError(msg);
+}
+JSONCPP_NORETURN void throwLogicError(String const& msg) {
+ throw LogicError(msg);
+}
+#else // !JSON_USE_EXCEPTION
+JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
+ std::cerr << msg << std::endl;
+ abort();
+}
+JSONCPP_NORETURN void throwLogicError(String const& msg) {
+ std::cerr << msg << std::endl;
+ abort();
+}
+#endif
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+// Notes: policy_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
+
+Value::CZString::CZString(char const* str, unsigned length,
+ DuplicationPolicy allocate)
+ : cstr_(str) {
+ // allocate != duplicate
+ storage_.policy_ = allocate & 0x3;
+ storage_.length_ = length & 0x3FFFFFFF;
+}
+
+Value::CZString::CZString(const CZString& other) {
+ cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
+ ? duplicateStringValue(other.cstr_, other.storage_.length_)
+ : other.cstr_);
+ storage_.policy_ =
+ static_cast<unsigned>(
+ other.cstr_
+ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) ==
+ noDuplication
+ ? noDuplication
+ : duplicate)
+ : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
+ 3U;
+ storage_.length_ = other.storage_.length_;
+}
+
+Value::CZString::CZString(CZString&& other) noexcept
+ : cstr_(other.cstr_), index_(other.index_) {
+ other.cstr_ = nullptr;
+}
+
+Value::CZString::~CZString() {
+ if (cstr_ && storage_.policy_ == duplicate) {
+ releaseStringValue(const_cast<char*>(cstr_),
+ storage_.length_ + 1U); // +1 for null terminating
+ // character for sake of
+ // completeness but not actually
+ // necessary
+ }
+}
+
+void Value::CZString::swap(CZString& other) {
+ std::swap(cstr_, other.cstr_);
+ std::swap(index_, other.index_);
+}
+
+Value::CZString& Value::CZString::operator=(const CZString& other) {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
+ return *this;
+}
+
+Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
+ cstr_ = other.cstr_;
+ index_ = other.index_;
+ other.cstr_ = nullptr;
+ return *this;
+}
+
+bool Value::CZString::operator<(const CZString& other) const {
+ if (!cstr_)
+ return index_ < other.index_;
+ // return strcmp(cstr_, other.cstr_) < 0;
+ // Assume both are strings.
+ unsigned this_len = this->storage_.length_;
+ unsigned other_len = other.storage_.length_;
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this->cstr_ && other.cstr_);
+ int comp = memcmp(this->cstr_, other.cstr_, min_len);
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
+ return (this_len < other_len);
+}
+
+bool Value::CZString::operator==(const CZString& other) const {
+ if (!cstr_)
+ return index_ == other.index_;
+ // return strcmp(cstr_, other.cstr_) == 0;
+ // Assume both are strings.
+ unsigned this_len = this->storage_.length_;
+ unsigned other_len = other.storage_.length_;
+ if (this_len != other_len)
+ return false;
+ JSON_ASSERT(this->cstr_ && other.cstr_);
+ int comp = memcmp(this->cstr_, other.cstr_, this_len);
+ return comp == 0;
+}
+
+ArrayIndex Value::CZString::index() const { return index_; }
+
+// const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const {
+ return storage_.policy_ == noDuplication;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value(ValueType type) {
+ static char const emptyString[] = "";
+ initBasic(type);
+ switch (type) {
+ case nullValue:
+ break;
+ case intValue:
+ case uintValue:
+ value_.int_ = 0;
+ break;
+ case realValue:
+ value_.real_ = 0.0;
+ break;
+ case stringValue:
+ // allocated_ == false, so this is safe.
+ value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues();
+ break;
+ case booleanValue:
+ value_.bool_ = false;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+Value::Value(Int value) {
+ initBasic(intValue);
+ value_.int_ = value;
+}
+
+Value::Value(UInt value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
+}
+#if defined(JSON_HAS_INT64)
+Value::Value(Int64 value) {
+ initBasic(intValue);
+ value_.int_ = value;
+}
+Value::Value(UInt64 value) {
+ initBasic(uintValue);
+ value_.uint_ = value;
+}
+#endif // defined(JSON_HAS_INT64)
+
+Value::Value(double value) {
+ initBasic(realValue);
+ value_.real_ = value;
+}
+
+Value::Value(const char* value) {
+ initBasic(stringValue, true);
+ JSON_ASSERT_MESSAGE(value != nullptr,
+ "Null Value Passed to Value Constructor");
+ value_.string_ = duplicateAndPrefixStringValue(
+ value, static_cast<unsigned>(strlen(value)));
+}
+
+Value::Value(const char* begin, const char* end) {
+ initBasic(stringValue, true);
+ value_.string_ =
+ duplicateAndPrefixStringValue(begin, static_cast<unsigned>(end - begin));
+}
+
+Value::Value(const String& value) {
+ initBasic(stringValue, true);
+ value_.string_ = duplicateAndPrefixStringValue(
+ value.data(), static_cast<unsigned>(value.length()));
+}
+
+Value::Value(const StaticString& value) {
+ initBasic(stringValue);
+ value_.string_ = const_cast<char*>(value.c_str());
+}
+
+Value::Value(bool value) {
+ initBasic(booleanValue);
+ value_.bool_ = value;
+}
+
+Value::Value(const Value& other) {
+ dupPayload(other);
+ dupMeta(other);
+}
+
+Value::Value(Value&& other) noexcept {
+ initBasic(nullValue);
+ swap(other);
+}
+
+Value::~Value() {
+ releasePayload();
+ value_.uint_ = 0;
+}
+
+Value& Value::operator=(const Value& other) {
+ Value(other).swap(*this);
+ return *this;
+}
+
+Value& Value::operator=(Value&& other) noexcept {
+ other.swap(*this);
+ return *this;
+}
+
+void Value::swapPayload(Value& other) {
+ std::swap(bits_, other.bits_);
+ std::swap(value_, other.value_);
+}
+
+void Value::copyPayload(const Value& other) {
+ releasePayload();
+ dupPayload(other);
+}
+
+void Value::swap(Value& other) {
+ swapPayload(other);
+ std::swap(comments_, other.comments_);
+ std::swap(start_, other.start_);
+ std::swap(limit_, other.limit_);
+}
+
+void Value::copy(const Value& other) {
+ copyPayload(other);
+ dupMeta(other);
+}
+
+ValueType Value::type() const {
+ return static_cast<ValueType>(bits_.value_type_);
+}
+
+int Value::compare(const Value& other) const {
+ if (*this < other)
+ return -1;
+ if (*this > other)
+ return 1;
+ return 0;
+}
+
+bool Value::operator<(const Value& other) const {
+ int typeDelta = type() - other.type();
+ if (typeDelta)
+ return typeDelta < 0;
+ switch (type()) {
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ < other.value_.int_;
+ case uintValue:
+ return value_.uint_ < other.value_.uint_;
+ case realValue:
+ return value_.real_ < other.value_.real_;
+ case booleanValue:
+ return value_.bool_ < other.value_.bool_;
+ case stringValue: {
+ if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
+ return other.value_.string_ != nullptr;
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
+ &other_str);
+ unsigned min_len = std::min<unsigned>(this_len, other_len);
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, min_len);
+ if (comp < 0)
+ return true;
+ if (comp > 0)
+ return false;
+ return (this_len < other_len);
+ }
+ case arrayValue:
+ case objectValue: {
+ auto thisSize = value_.map_->size();
+ auto otherSize = other.value_.map_->size();
+ if (thisSize != otherSize)
+ return thisSize < otherSize;
+ return (*value_.map_) < (*other.value_.map_);
+ }
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable
+}
+
+bool Value::operator<=(const Value& other) const { return !(other < *this); }
+
+bool Value::operator>=(const Value& other) const { return !(*this < other); }
+
+bool Value::operator>(const Value& other) const { return other < *this; }
+
+bool Value::operator==(const Value& other) const {
+ if (type() != other.type())
+ return false;
+ switch (type()) {
+ case nullValue:
+ return true;
+ case intValue:
+ return value_.int_ == other.value_.int_;
+ case uintValue:
+ return value_.uint_ == other.value_.uint_;
+ case realValue:
+ return value_.real_ == other.value_.real_;
+ case booleanValue:
+ return value_.bool_ == other.value_.bool_;
+ case stringValue: {
+ if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
+ return (value_.string_ == other.value_.string_);
+ }
+ unsigned this_len;
+ unsigned other_len;
+ char const* this_str;
+ char const* other_str;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &other_len,
+ &other_str);
+ if (this_len != other_len)
+ return false;
+ JSON_ASSERT(this_str && other_str);
+ int comp = memcmp(this_str, other_str, this_len);
+ return comp == 0;
+ }
+ case arrayValue:
+ case objectValue:
+ return value_.map_->size() == other.value_.map_->size() &&
+ (*value_.map_) == (*other.value_.map_);
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+ return false; // unreachable
+}
+
+bool Value::operator!=(const Value& other) const { return !(*this == other); }
+
+const char* Value::asCString() const {
+ JSON_ASSERT_MESSAGE(type() == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == nullptr)
+ return nullptr;
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ return this_str;
+}
+
+#if JSONCPP_USING_SECURE_MEMORY
+unsigned Value::getCStringLength() const {
+ JSON_ASSERT_MESSAGE(type() == stringValue,
+ "in Json::Value::asCString(): requires stringValue");
+ if (value_.string_ == 0)
+ return 0;
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ return this_len;
+}
+#endif
+
+bool Value::getString(char const** begin, char const** end) const {
+ if (type() != stringValue)
+ return false;
+ if (value_.string_ == nullptr)
+ return false;
+ unsigned length;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
+ begin);
+ *end = *begin + length;
+ return true;
+}
+
+String Value::asString() const {
+ switch (type()) {
+ case nullValue:
+ return "";
+ case stringValue: {
+ if (value_.string_ == nullptr)
+ return "";
+ unsigned this_len;
+ char const* this_str;
+ decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
+ &this_str);
+ return String(this_str, this_len);
+ }
+ case booleanValue:
+ return value_.bool_ ? "true" : "false";
+ case intValue:
+ return valueToString(value_.int_);
+ case uintValue:
+ return valueToString(value_.uint_);
+ case realValue:
+ return valueToString(value_.real_);
+ default:
+ JSON_FAIL_MESSAGE("Type is not convertible to string");
+ }
+}
+
+Value::Int Value::asInt() const {
+ switch (type()) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+ return Int(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+ return Int(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+ "double out of Int range");
+ return Int(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to Int.");
+}
+
+Value::UInt Value::asUInt() const {
+ switch (type()) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+ return UInt(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+ return UInt(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+ "double out of UInt range");
+ return UInt(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
+}
+
+#if defined(JSON_HAS_INT64)
+
+Value::Int64 Value::asInt64() const {
+ switch (type()) {
+ case intValue:
+ return Int64(value_.int_);
+ case uintValue:
+ JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+ return Int64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+ "double out of Int64 range");
+ return Int64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
+}
+
+Value::UInt64 Value::asUInt64() const {
+ switch (type()) {
+ case intValue:
+ JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+ return UInt64(value_.int_);
+ case uintValue:
+ return UInt64(value_.uint_);
+ case realValue:
+ JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+ "double out of UInt64 range");
+ return UInt64(value_.real_);
+ case nullValue:
+ return 0;
+ case booleanValue:
+ return value_.bool_ ? 1 : 0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
+}
+#endif // if defined(JSON_HAS_INT64)
+
+LargestInt Value::asLargestInt() const {
+#if defined(JSON_NO_INT64)
+ return asInt();
+#else
+ return asInt64();
+#endif
+}
+
+LargestUInt Value::asLargestUInt() const {
+#if defined(JSON_NO_INT64)
+ return asUInt();
+#else
+ return asUInt64();
+#endif
+}
+
+double Value::asDouble() const {
+ switch (type()) {
+ case intValue:
+ return static_cast<double>(value_.int_);
+ case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<double>(value_.uint_);
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ case realValue:
+ return value_.real_;
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0 : 0.0;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to double.");
+}
+
+float Value::asFloat() const {
+ switch (type()) {
+ case intValue:
+ return static_cast<float>(value_.int_);
+ case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ return static_cast<float>(value_.uint_);
+#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ // This can fail (silently?) if the value is bigger than MAX_FLOAT.
+ return static_cast<float>(integerToDouble(value_.uint_));
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+ case realValue:
+ return static_cast<float>(value_.real_);
+ case nullValue:
+ return 0.0;
+ case booleanValue:
+ return value_.bool_ ? 1.0F : 0.0F;
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to float.");
+}
+
+bool Value::asBool() const {
+ switch (type()) {
+ case booleanValue:
+ return value_.bool_;
+ case nullValue:
+ return false;
+ case intValue:
+ return value_.int_ != 0;
+ case uintValue:
+ return value_.uint_ != 0;
+ case realValue: {
+ // According to JavaScript language zero or NaN is regarded as false
+ const auto value_classification = std::fpclassify(value_.real_);
+ return value_classification != FP_ZERO && value_classification != FP_NAN;
+ }
+ default:
+ break;
+ }
+ JSON_FAIL_MESSAGE("Value is not convertible to bool.");
+}
+
+bool Value::isConvertibleTo(ValueType other) const {
+ switch (other) {
+ case nullValue:
+ return (isNumeric() && asDouble() == 0.0) ||
+ (type() == booleanValue && !value_.bool_) ||
+ (type() == stringValue && asString().empty()) ||
+ (type() == arrayValue && value_.map_->empty()) ||
+ (type() == objectValue && value_.map_->empty()) ||
+ type() == nullValue;
+ case intValue:
+ return isInt() ||
+ (type() == realValue && InRange(value_.real_, minInt, maxInt)) ||
+ type() == booleanValue || type() == nullValue;
+ case uintValue:
+ return isUInt() ||
+ (type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
+ type() == booleanValue || type() == nullValue;
+ case realValue:
+ return isNumeric() || type() == booleanValue || type() == nullValue;
+ case booleanValue:
+ return isNumeric() || type() == booleanValue || type() == nullValue;
+ case stringValue:
+ return isNumeric() || type() == booleanValue || type() == stringValue ||
+ type() == nullValue;
+ case arrayValue:
+ return type() == arrayValue || type() == nullValue;
+ case objectValue:
+ return type() == objectValue || type() == nullValue;
+ }
+ JSON_ASSERT_UNREACHABLE;
+ return false;
+}
+
+/// Number of values in array or object
+ArrayIndex Value::size() const {
+ switch (type()) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ case stringValue:
+ return 0;
+ case arrayValue: // size of the array is highest index + 1
+ if (!value_.map_->empty()) {
+ ObjectValues::const_iterator itLast = value_.map_->end();
+ --itLast;
+ return (*itLast).first.index() + 1;
+ }
+ return 0;
+ case objectValue:
+ return ArrayIndex(value_.map_->size());
+ }
+ JSON_ASSERT_UNREACHABLE;
+ return 0; // unreachable;
+}
+
+bool Value::empty() const {
+ if (isNull() || isArray() || isObject())
+ return size() == 0U;
+ return false;
+}
+
+Value::operator bool() const { return !isNull(); }
+
+void Value::clear() {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue ||
+ type() == objectValue,
+ "in Json::Value::clear(): requires complex value");
+ start_ = 0;
+ limit_ = 0;
+ switch (type()) {
+ case arrayValue:
+ case objectValue:
+ value_.map_->clear();
+ break;
+ default:
+ break;
+ }
+}
+
+void Value::resize(ArrayIndex newSize) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+ "in Json::Value::resize(): requires arrayValue");
+ if (type() == nullValue)
+ *this = Value(arrayValue);
+ ArrayIndex oldSize = size();
+ if (newSize == 0)
+ clear();
+ else if (newSize > oldSize)
+ for (ArrayIndex i = oldSize; i < newSize; ++i)
+ (*this)[i];
+ else {
+ for (ArrayIndex index = newSize; index < oldSize; ++index) {
+ value_.map_->erase(index);
+ }
+ JSON_ASSERT(size() == newSize);
+ }
+}
+
+Value& Value::operator[](ArrayIndex index) {
+ JSON_ASSERT_MESSAGE(
+ type() == nullValue || type() == arrayValue,
+ "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+ if (type() == nullValue)
+ *this = Value(arrayValue);
+ CZString key(index);
+ auto it = value_.map_->lower_bound(key);
+ if (it != value_.map_->end() && (*it).first == key)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(key, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ return (*it).second;
+}
+
+Value& Value::operator[](int index) {
+ JSON_ASSERT_MESSAGE(
+ index >= 0,
+ "in Json::Value::operator[](int index): index cannot be negative");
+ return (*this)[ArrayIndex(index)];
+}
+
+const Value& Value::operator[](ArrayIndex index) const {
+ JSON_ASSERT_MESSAGE(
+ type() == nullValue || type() == arrayValue,
+ "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+ if (type() == nullValue)
+ return nullSingleton();
+ CZString key(index);
+ ObjectValues::const_iterator it = value_.map_->find(key);
+ if (it == value_.map_->end())
+ return nullSingleton();
+ return (*it).second;
+}
+
+const Value& Value::operator[](int index) const {
+ JSON_ASSERT_MESSAGE(
+ index >= 0,
+ "in Json::Value::operator[](int index) const: index cannot be negative");
+ return (*this)[ArrayIndex(index)];
+}
+
+void Value::initBasic(ValueType type, bool allocated) {
+ setType(type);
+ setIsAllocated(allocated);
+ comments_ = Comments{};
+ start_ = 0;
+ limit_ = 0;
+}
+
+void Value::dupPayload(const Value& other) {
+ setType(other.type());
+ setIsAllocated(false);
+ switch (type()) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ value_ = other.value_;
+ break;
+ case stringValue:
+ if (other.value_.string_ && other.isAllocated()) {
+ unsigned len;
+ char const* str;
+ decodePrefixedString(other.isAllocated(), other.value_.string_, &len,
+ &str);
+ value_.string_ = duplicateAndPrefixStringValue(str, len);
+ setIsAllocated(true);
+ } else {
+ value_.string_ = other.value_.string_;
+ }
+ break;
+ case arrayValue:
+ case objectValue:
+ value_.map_ = new ObjectValues(*other.value_.map_);
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+void Value::releasePayload() {
+ switch (type()) {
+ case nullValue:
+ case intValue:
+ case uintValue:
+ case realValue:
+ case booleanValue:
+ break;
+ case stringValue:
+ if (isAllocated())
+ releasePrefixedStringValue(value_.string_);
+ break;
+ case arrayValue:
+ case objectValue:
+ delete value_.map_;
+ break;
+ default:
+ JSON_ASSERT_UNREACHABLE;
+ }
+}
+
+void Value::dupMeta(const Value& other) {
+ comments_ = other.comments_;
+ start_ = other.start_;
+ limit_ = other.limit_;
+}
+
+// Access an object value by name, create a null member if it does not exist.
+// @pre Type of '*this' is object or null.
+// @param key is null-terminated.
+Value& Value::resolveReference(const char* key) {
+ JSON_ASSERT_MESSAGE(
+ type() == nullValue || type() == objectValue,
+ "in Json::Value::resolveReference(): requires objectValue");
+ if (type() == nullValue)
+ *this = Value(objectValue);
+ CZString actualKey(key, static_cast<unsigned>(strlen(key)),
+ CZString::noDuplication); // NOTE!
+ auto it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ Value& value = (*it).second;
+ return value;
+}
+
+// @param key is not null-terminated.
+Value& Value::resolveReference(char const* key, char const* end) {
+ JSON_ASSERT_MESSAGE(
+ type() == nullValue || type() == objectValue,
+ "in Json::Value::resolveReference(key, end): requires objectValue");
+ if (type() == nullValue)
+ *this = Value(objectValue);
+ CZString actualKey(key, static_cast<unsigned>(end - key),
+ CZString::duplicateOnCopy);
+ auto it = value_.map_->lower_bound(actualKey);
+ if (it != value_.map_->end() && (*it).first == actualKey)
+ return (*it).second;
+
+ ObjectValues::value_type defaultValue(actualKey, nullSingleton());
+ it = value_.map_->insert(it, defaultValue);
+ Value& value = (*it).second;
+ return value;
+}
+
+Value Value::get(ArrayIndex index, const Value& defaultValue) const {
+ const Value* value = &((*this)[index]);
+ return value == &nullSingleton() ? defaultValue : *value;
+}
+
+bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
+
+Value const* Value::find(char const* begin, char const* end) const {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::find(begin, end): requires "
+ "objectValue or nullValue");
+ if (type() == nullValue)
+ return nullptr;
+ CZString actualKey(begin, static_cast<unsigned>(end - begin),
+ CZString::noDuplication);
+ ObjectValues::const_iterator it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
+ return nullptr;
+ return &(*it).second;
+}
+Value* Value::demand(char const* begin, char const* end) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::demand(begin, end): requires "
+ "objectValue or nullValue");
+ return &resolveReference(begin, end);
+}
+const Value& Value::operator[](const char* key) const {
+ Value const* found = find(key, key + strlen(key));
+ if (!found)
+ return nullSingleton();
+ return *found;
+}
+Value const& Value::operator[](const String& key) const {
+ Value const* found = find(key.data(), key.data() + key.length());
+ if (!found)
+ return nullSingleton();
+ return *found;
+}
+
+Value& Value::operator[](const char* key) {
+ return resolveReference(key, key + strlen(key));
+}
+
+Value& Value::operator[](const String& key) {
+ return resolveReference(key.data(), key.data() + key.length());
+}
+
+Value& Value::operator[](const StaticString& key) {
+ return resolveReference(key.c_str());
+}
+
+Value& Value::append(const Value& value) { return append(Value(value)); }
+
+Value& Value::append(Value&& value) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+ "in Json::Value::append: requires arrayValue");
+ if (type() == nullValue) {
+ *this = Value(arrayValue);
+ }
+ return this->value_.map_->emplace(size(), std::move(value)).first->second;
+}
+
+bool Value::insert(ArrayIndex index, const Value& newValue) {
+ return insert(index, Value(newValue));
+}
+
+bool Value::insert(ArrayIndex index, Value&& newValue) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
+ "in Json::Value::insert: requires arrayValue");
+ ArrayIndex length = size();
+ if (index > length) {
+ return false;
+ }
+ for (ArrayIndex i = length; i > index; i--) {
+ (*this)[i] = std::move((*this)[i - 1]);
+ }
+ (*this)[index] = std::move(newValue);
+ return true;
+}
+
+Value Value::get(char const* begin, char const* end,
+ Value const& defaultValue) const {
+ Value const* found = find(begin, end);
+ return !found ? defaultValue : *found;
+}
+Value Value::get(char const* key, Value const& defaultValue) const {
+ return get(key, key + strlen(key), defaultValue);
+}
+Value Value::get(String const& key, Value const& defaultValue) const {
+ return get(key.data(), key.data() + key.length(), defaultValue);
+}
+
+bool Value::removeMember(const char* begin, const char* end, Value* removed) {
+ if (type() != objectValue) {
+ return false;
+ }
+ CZString actualKey(begin, static_cast<unsigned>(end - begin),
+ CZString::noDuplication);
+ auto it = value_.map_->find(actualKey);
+ if (it == value_.map_->end())
+ return false;
+ if (removed)
+ *removed = std::move(it->second);
+ value_.map_->erase(it);
+ return true;
+}
+bool Value::removeMember(const char* key, Value* removed) {
+ return removeMember(key, key + strlen(key), removed);
+}
+bool Value::removeMember(String const& key, Value* removed) {
+ return removeMember(key.data(), key.data() + key.length(), removed);
+}
+void Value::removeMember(const char* key) {
+ JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
+ "in Json::Value::removeMember(): requires objectValue");
+ if (type() == nullValue)
+ return;
+
+ CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
+ value_.map_->erase(actualKey);
+}
+void Value::removeMember(const String& key) { removeMember(key.c_str()); }
+
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+ if (type() != arrayValue) {
+ return false;
+ }
+ CZString key(index);
+ auto it = value_.map_->find(key);
+ if (it == value_.map_->end()) {
+ return false;
+ }
+ if (removed)
+ *removed = it->second;
+ ArrayIndex oldSize = size();
+ // shift left all items left, into the place of the "removed"
+ for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
+ CZString keey(i);
+ (*value_.map_)[keey] = (*this)[i + 1];
+ }
+ // erase the last one ("leftover")
+ CZString keyLast(oldSize - 1);
+ auto itLast = value_.map_->find(keyLast);
+ value_.map_->erase(itLast);
+ return true;
+}
+
+bool Value::isMember(char const* begin, char const* end) const {
+ Value const* value = find(begin, end);
+ return nullptr != value;
+}
+bool Value::isMember(char const* key) const {
+ return isMember(key, key + strlen(key));
+}
+bool Value::isMember(String const& key) const {
+ return isMember(key.data(), key.data() + key.length());
+}
+
+Value::Members Value::getMemberNames() const {
+ JSON_ASSERT_MESSAGE(
+ type() == nullValue || type() == objectValue,
+ "in Json::Value::getMemberNames(), value must be objectValue");
+ if (type() == nullValue)
+ return Value::Members();
+ Members members;
+ members.reserve(value_.map_->size());
+ ObjectValues::const_iterator it = value_.map_->begin();
+ ObjectValues::const_iterator itEnd = value_.map_->end();
+ for (; it != itEnd; ++it) {
+ members.push_back(String((*it).first.data(), (*it).first.length()));
+ }
+ return members;
+}
+
+static bool IsIntegral(double d) {
+ double integral_part;
+ return modf(d, &integral_part) == 0.0;
+}
+
+bool Value::isNull() const { return type() == nullValue; }
+
+bool Value::isBool() const { return type() == booleanValue; }
+
+bool Value::isInt() const {
+ switch (type()) {
+ case intValue:
+#if defined(JSON_HAS_INT64)
+ return value_.int_ >= minInt && value_.int_ <= maxInt;
+#else
+ return true;
+#endif
+ case uintValue:
+ return value_.uint_ <= UInt(maxInt);
+ case realValue:
+ return value_.real_ >= minInt && value_.real_ <= maxInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isUInt() const {
+ switch (type()) {
+ case intValue:
+#if defined(JSON_HAS_INT64)
+ return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+#else
+ return value_.int_ >= 0;
+#endif
+ case uintValue:
+#if defined(JSON_HAS_INT64)
+ return value_.uint_ <= maxUInt;
+#else
+ return true;
+#endif
+ case realValue:
+ return value_.real_ >= 0 && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isInt64() const {
+#if defined(JSON_HAS_INT64)
+ switch (type()) {
+ case intValue:
+ return true;
+ case uintValue:
+ return value_.uint_ <= UInt64(maxInt64);
+ case realValue:
+ // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+ // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) &&
+ value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
+ default:
+ break;
+ }
+#endif // JSON_HAS_INT64
+ return false;
+}
+
+bool Value::isUInt64() const {
+#if defined(JSON_HAS_INT64)
+ switch (type()) {
+ case intValue:
+ return value_.int_ >= 0;
+ case uintValue:
+ return true;
+ case realValue:
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
+ IsIntegral(value_.real_);
+ default:
+ break;
+ }
+#endif // JSON_HAS_INT64
+ return false;
+}
+
+bool Value::isIntegral() const {
+ switch (type()) {
+ case intValue:
+ case uintValue:
+ return true;
+ case realValue:
+#if defined(JSON_HAS_INT64)
+ // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+ // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+ // require the value to be strictly less than the limit.
+ return value_.real_ >= double(minInt64) &&
+ value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
+#else
+ return value_.real_ >= minInt && value_.real_ <= maxUInt &&
+ IsIntegral(value_.real_);
+#endif // JSON_HAS_INT64
+ default:
+ break;
+ }
+ return false;
+}
+
+bool Value::isDouble() const {
+ return type() == intValue || type() == uintValue || type() == realValue;
+}
+
+bool Value::isNumeric() const { return isDouble(); }
+
+bool Value::isString() const { return type() == stringValue; }
+
+bool Value::isArray() const { return type() == arrayValue; }
+
+bool Value::isObject() const { return type() == objectValue; }
+
+Value::Comments::Comments(const Comments& that)
+ : ptr_{cloneUnique(that.ptr_)} {}
+
+Value::Comments::Comments(Comments&& that) noexcept
+ : ptr_{std::move(that.ptr_)} {}
+
+Value::Comments& Value::Comments::operator=(const Comments& that) {
+ ptr_ = cloneUnique(that.ptr_);
+ return *this;
+}
+
+Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
+ ptr_ = std::move(that.ptr_);
+ return *this;
+}
+
+bool Value::Comments::has(CommentPlacement slot) const {
+ return ptr_ && !(*ptr_)[slot].empty();
+}
+
+String Value::Comments::get(CommentPlacement slot) const {
+ if (!ptr_)
+ return {};
+ return (*ptr_)[slot];
+}
+
+void Value::Comments::set(CommentPlacement slot, String comment) {
+ if (slot >= CommentPlacement::numberOfCommentPlacement)
+ return;
+ if (!ptr_)
+ ptr_ = std::unique_ptr<Array>(new Array());
+ (*ptr_)[slot] = std::move(comment);
+}
+
+void Value::setComment(String comment, CommentPlacement placement) {
+ if (!comment.empty() && (comment.back() == '\n')) {
+ // Always discard trailing newline, to aid indentation.
+ comment.pop_back();
+ }
+ JSON_ASSERT(!comment.empty());
+ JSON_ASSERT_MESSAGE(
+ comment[0] == '\0' || comment[0] == '/',
+ "in Json::Value::setComment(): Comments must start with /");
+ comments_.set(placement, std::move(comment));
+}
+
+bool Value::hasComment(CommentPlacement placement) const {
+ return comments_.has(placement);
+}
+
+String Value::getComment(CommentPlacement placement) const {
+ return comments_.get(placement);
+}
+
+void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
+
+void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
+
+ptrdiff_t Value::getOffsetStart() const { return start_; }
+
+ptrdiff_t Value::getOffsetLimit() const { return limit_; }
+
+String Value::toStyledString() const {
+ StreamWriterBuilder builder;
+
+ String out = this->hasComment(commentBefore) ? "\n" : "";
+ out += Json::writeString(builder, *this);
+ out += '\n';
+
+ return out;
+}
+
+Value::const_iterator Value::begin() const {
+ switch (type()) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->begin());
+ break;
+ default:
+ break;
+ }
+ return {};
+}
+
+Value::const_iterator Value::end() const {
+ switch (type()) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return const_iterator(value_.map_->end());
+ break;
+ default:
+ break;
+ }
+ return {};
+}
+
+Value::iterator Value::begin() {
+ switch (type()) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->begin());
+ break;
+ default:
+ break;
+ }
+ return iterator();
+}
+
+Value::iterator Value::end() {
+ switch (type()) {
+ case arrayValue:
+ case objectValue:
+ if (value_.map_)
+ return iterator(value_.map_->end());
+ break;
+ default:
+ break;
+ }
+ return iterator();
+}
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument() = default;
+
+PathArgument::PathArgument(ArrayIndex index)
+ : index_(index), kind_(kindIndex) {}
+
+PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
+
+PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
+ const PathArgument& a3, const PathArgument& a4,
+ const PathArgument& a5) {
+ InArgs in;
+ in.reserve(5);
+ in.push_back(&a1);
+ in.push_back(&a2);
+ in.push_back(&a3);
+ in.push_back(&a4);
+ in.push_back(&a5);
+ makePath(path, in);
+}
+
+void Path::makePath(const String& path, const InArgs& in) {
+ const char* current = path.c_str();
+ const char* end = current + path.length();
+ auto itInArg = in.begin();
+ while (current != end) {
+ if (*current == '[') {
+ ++current;
+ if (*current == '%')
+ addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+ else {
+ ArrayIndex index = 0;
+ for (; current != end && *current >= '0' && *current <= '9'; ++current)
+ index = index * 10 + ArrayIndex(*current - '0');
+ args_.push_back(index);
+ }
+ if (current == end || *++current != ']')
+ invalidPath(path, int(current - path.c_str()));
+ } else if (*current == '%') {
+ addPathInArg(path, in, itInArg, PathArgument::kindKey);
+ ++current;
+ } else if (*current == '.' || *current == ']') {
+ ++current;
+ } else {
+ const char* beginName = current;
+ while (current != end && !strchr("[.", *current))
+ ++current;
+ args_.push_back(String(beginName, current));
+ }
+ }
+}
+
+void Path::addPathInArg(const String& /*path*/, const InArgs& in,
+ InArgs::const_iterator& itInArg,
+ PathArgument::Kind kind) {
+ if (itInArg == in.end()) {
+ // Error: missing argument %d
+ } else if ((*itInArg)->kind_ != kind) {
+ // Error: bad argument type
+ } else {
+ args_.push_back(**itInArg++);
+ }
+}
+
+void Path::invalidPath(const String& /*path*/, int /*location*/) {
+ // Error: invalid path.
+}
+
+const Value& Path::resolve(const Value& root) const {
+ const Value* node = &root;
+ for (const auto& arg : args_) {
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || !node->isValidIndex(arg.index_)) {
+ // Error: unable to resolve path (array value expected at position... )
+ return Value::nullSingleton();
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: unable to resolve path (object value expected at position...)
+ return Value::nullSingleton();
+ }
+ node = &((*node)[arg.key_]);
+ if (node == &Value::nullSingleton()) {
+ // Error: unable to resolve path (object has no member named '' at
+ // position...)
+ return Value::nullSingleton();
+ }
+ }
+ }
+ return *node;
+}
+
+Value Path::resolve(const Value& root, const Value& defaultValue) const {
+ const Value* node = &root;
+ for (const auto& arg : args_) {
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray() || !node->isValidIndex(arg.index_))
+ return defaultValue;
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject())
+ return defaultValue;
+ node = &((*node)[arg.key_]);
+ if (node == &Value::nullSingleton())
+ return defaultValue;
+ }
+ }
+ return *node;
+}
+
+Value& Path::make(Value& root) const {
+ Value* node = &root;
+ for (const auto& arg : args_) {
+ if (arg.kind_ == PathArgument::kindIndex) {
+ if (!node->isArray()) {
+ // Error: node is not an array at position ...
+ }
+ node = &((*node)[arg.index_]);
+ } else if (arg.kind_ == PathArgument::kindKey) {
+ if (!node->isObject()) {
+ // Error: node is not an object at position...
+ }
+ node = &((*node)[arg.key_]);
+ }
+ }
+ return *node;
+}
+
+} // namespace Json
diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl
new file mode 100644
index 0000000000..d6128b8edf
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_valueiterator.inl
@@ -0,0 +1,156 @@
+// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+// included by json_value.cpp
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase() : current_() {}
+
+ValueIteratorBase::ValueIteratorBase(
+ const Value::ObjectValues::iterator& current)
+ : current_(current), isNull_(false) {}
+
+Value& ValueIteratorBase::deref() { return current_->second; }
+const Value& ValueIteratorBase::deref() const { return current_->second; }
+
+void ValueIteratorBase::increment() { ++current_; }
+
+void ValueIteratorBase::decrement() { --current_; }
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance(const SelfType& other) const {
+ // Iterator for null value are initialized using the default
+ // constructor, which initialize current_ to the default
+ // std::map::iterator. As begin() and end() are two instance
+ // of the default std::map::iterator, they can not be compared.
+ // To allow this, we handle this comparison specifically.
+ if (isNull_ && other.isNull_) {
+ return 0;
+ }
+
+ // Usage of std::distance is not portable (does not compile with Sun Studio 12
+ // RogueWave STL,
+ // which is the one used by default).
+ // Using a portable hand-made version for non random iterator instead:
+ // return difference_type( std::distance( current_, other.current_ ) );
+ difference_type myDistance = 0;
+ for (Value::ObjectValues::iterator it = current_; it != other.current_;
+ ++it) {
+ ++myDistance;
+ }
+ return myDistance;
+}
+
+bool ValueIteratorBase::isEqual(const SelfType& other) const {
+ if (isNull_) {
+ return other.isNull_;
+ }
+ return current_ == other.current_;
+}
+
+void ValueIteratorBase::copy(const SelfType& other) {
+ current_ = other.current_;
+ isNull_ = other.isNull_;
+}
+
+Value ValueIteratorBase::key() const {
+ const Value::CZString czstring = (*current_).first;
+ if (czstring.data()) {
+ if (czstring.isStaticString())
+ return Value(StaticString(czstring.data()));
+ return Value(czstring.data(), czstring.data() + czstring.length());
+ }
+ return Value(czstring.index());
+}
+
+UInt ValueIteratorBase::index() const {
+ const Value::CZString czstring = (*current_).first;
+ if (!czstring.data())
+ return czstring.index();
+ return Value::UInt(-1);
+}
+
+String ValueIteratorBase::name() const {
+ char const* keey;
+ char const* end;
+ keey = memberName(&end);
+ if (!keey)
+ return String();
+ return String(keey, end);
+}
+
+char const* ValueIteratorBase::memberName() const {
+ const char* cname = (*current_).first.data();
+ return cname ? cname : "";
+}
+
+char const* ValueIteratorBase::memberName(char const** end) const {
+ const char* cname = (*current_).first.data();
+ if (!cname) {
+ *end = nullptr;
+ return nullptr;
+ }
+ *end = cname + (*current_).first.length();
+ return cname;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator() = default;
+
+ValueConstIterator::ValueConstIterator(
+ const Value::ObjectValues::iterator& current)
+ : ValueIteratorBase(current) {}
+
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+ : ValueIteratorBase(other) {}
+
+ValueConstIterator& ValueConstIterator::
+operator=(const ValueIteratorBase& other) {
+ copy(other);
+ return *this;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator() = default;
+
+ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
+ : ValueIteratorBase(current) {}
+
+ValueIterator::ValueIterator(const ValueConstIterator& other)
+ : ValueIteratorBase(other) {
+ throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
+
+ValueIterator::ValueIterator(const ValueIterator& other) = default;
+
+ValueIterator& ValueIterator::operator=(const SelfType& other) {
+ copy(other);
+ return *this;
+}
+
+} // namespace Json
diff --git a/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp
new file mode 100644
index 0000000000..0dd160e452
--- /dev/null
+++ b/thirdparty/openxr/src/external/jsoncpp/src/lib_json/json_writer.cpp
@@ -0,0 +1,1259 @@
+// Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "json_tool.h"
+#include <json/writer.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstring>
+#include <iomanip>
+#include <memory>
+#include <set>
+#include <sstream>
+#include <utility>
+
+#if __cplusplus >= 201103L
+#include <cmath>
+#include <cstdio>
+
+#if !defined(isnan)
+#define isnan std::isnan
+#endif
+
+#if !defined(isfinite)
+#define isfinite std::isfinite
+#endif
+
+#else
+#include <cmath>
+#include <cstdio>
+
+#if defined(_MSC_VER)
+#if !defined(isnan)
+#include <float.h>
+#define isnan _isnan
+#endif
+
+#if !defined(isfinite)
+#include <float.h>
+#define isfinite _finite
+#endif
+
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+
+#endif //_MSC_VER
+
+#if defined(__sun) && defined(__SVR4) // Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
+#endif
+
+#if defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) \
+ ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
+#endif
+#endif
+#endif
+
+#if !defined(isnan)
+// IEEE standard states that NaN values will not compare to themselves
+#define isnan(x) ((x) != (x))
+#endif
+
+#if !defined(__APPLE__)
+#if !defined(isfinite)
+#define isfinite finite
+#endif
+#endif
+#endif
+
+#if defined(_MSC_VER)
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+using StreamWriterPtr = std::unique_ptr<StreamWriter>;
+#else
+using StreamWriterPtr = std::auto_ptr<StreamWriter>;
+#endif
+
+String valueToString(LargestInt value) {
+ UIntToStringBuffer buffer;
+ char* current = buffer + sizeof(buffer);
+ if (value == Value::minLargestInt) {
+ uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
+ *--current = '-';
+ } else if (value < 0) {
+ uintToString(LargestUInt(-value), current);
+ *--current = '-';
+ } else {
+ uintToString(LargestUInt(value), current);
+ }
+ assert(current >= buffer);
+ return current;
+}
+
+String valueToString(LargestUInt value) {
+ UIntToStringBuffer buffer;
+ char* current = buffer + sizeof(buffer);
+ uintToString(value, current);
+ assert(current >= buffer);
+ return current;
+}
+
+#if defined(JSON_HAS_INT64)
+
+String valueToString(Int value) { return valueToString(LargestInt(value)); }
+
+String valueToString(UInt value) { return valueToString(LargestUInt(value)); }
+
+#endif // # if defined(JSON_HAS_INT64)
+
+namespace {
+String valueToString(double value, bool useSpecialFloats,
+ unsigned int precision, PrecisionType precisionType) {
+ // Print into the buffer. We need not request the alternative representation
+ // that always has a decimal point because JSON doesn't distinguish the
+ // concepts of reals and integers.
+ if (!isfinite(value)) {
+ static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
+ {"null", "-1e+9999", "1e+9999"}};
+ return reps[useSpecialFloats ? 0 : 1]
+ [isnan(value) ? 0 : (value < 0) ? 1 : 2];
+ }
+
+ String buffer(size_t(36), '\0');
+ while (true) {
+ int len = jsoncpp_snprintf(
+ &*buffer.begin(), buffer.size(),
+ (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
+ precision, value);
+ assert(len >= 0);
+ auto wouldPrint = static_cast<size_t>(len);
+ if (wouldPrint >= buffer.size()) {
+ buffer.resize(wouldPrint + 1);
+ continue;
+ }
+ buffer.resize(wouldPrint);
+ break;
+ }
+
+ buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
+
+ // try to ensure we preserve the fact that this was given to us as a double on
+ // input
+ if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
+ buffer += ".0";
+ }
+
+ // strip the zero padding from the right
+ if (precisionType == PrecisionType::decimalPlaces) {
+ buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision),
+ buffer.end());
+ }
+
+ return buffer;
+}
+} // namespace
+
+String valueToString(double value, unsigned int precision,
+ PrecisionType precisionType) {
+ return valueToString(value, false, precision, precisionType);
+}
+
+String valueToString(bool value) { return value ? "true" : "false"; }
+
+static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
+ assert(s || !n);
+
+ return std::any_of(s, s + n, [](unsigned char c) {
+ return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
+ });
+}
+
+static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
+ const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
+
+ unsigned int firstByte = static_cast<unsigned char>(*s);
+
+ if (firstByte < 0x80)
+ return firstByte;
+
+ if (firstByte < 0xE0) {
+ if (e - s < 2)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated =
+ ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
+ s += 1;
+ // oversized encoded characters are invalid
+ return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ if (firstByte < 0xF0) {
+ if (e - s < 3)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x0F) << 12) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[2]) & 0x3F);
+ s += 2;
+ // surrogates aren't valid codepoints itself
+ // shouldn't be UTF-8 encoded
+ if (calculated >= 0xD800 && calculated <= 0xDFFF)
+ return REPLACEMENT_CHARACTER;
+ // oversized encoded characters are invalid
+ return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ if (firstByte < 0xF8) {
+ if (e - s < 4)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x07) << 18) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
+ ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[3]) & 0x3F);
+ s += 3;
+ // oversized encoded characters are invalid
+ return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ return REPLACEMENT_CHARACTER;
+}
+
+static const char hex2[] = "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+static String toHex16Bit(unsigned int x) {
+ const unsigned int hi = (x >> 8) & 0xff;
+ const unsigned int lo = x & 0xff;
+ String result(4, ' ');
+ result[0] = hex2[2 * hi];
+ result[1] = hex2[2 * hi + 1];
+ result[2] = hex2[2 * lo];
+ result[3] = hex2[2 * lo + 1];
+ return result;
+}
+
+static void appendRaw(String& result, unsigned ch) {
+ result += static_cast<char>(ch);
+}
+
+static void appendHex(String& result, unsigned ch) {
+ result.append("\\u").append(toHex16Bit(ch));
+}
+
+static String valueToQuotedStringN(const char* value, size_t length,
+ bool emitUTF8 = false) {
+ if (value == nullptr)
+ return "";
+
+ if (!doesAnyCharRequireEscaping(value, length))
+ return String("\"") + value + "\"";
+ // We have to walk value and escape any special characters.
+ // Appending to String is not efficient, but this should be rare.
+ // (Note: forward slashes are *not* rare, but I am not escaping them.)
+ String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
+ String result;
+ result.reserve(maxsize); // to avoid lots of mallocs
+ result += "\"";
+ char const* end = value + length;
+ for (const char* c = value; c != end; ++c) {
+ switch (*c) {
+ case '\"':
+ result += "\\\"";
+ break;
+ case '\\':
+ result += "\\\\";
+ break;
+ case '\b':
+ result += "\\b";
+ break;
+ case '\f':
+ result += "\\f";
+ break;
+ case '\n':
+ result += "\\n";
+ break;
+ case '\r':
+ result += "\\r";
+ break;
+ case '\t':
+ result += "\\t";
+ break;
+ // case '/':
+ // Even though \/ is considered a legal escape in JSON, a bare
+ // slash is also legal, so I see no reason to escape it.
+ // (I hope I am not misunderstanding something.)
+ // blep notes: actually escaping \/ may be useful in javascript to avoid </
+ // sequence.
+ // Should add a flag to allow this compatibility mode and prevent this
+ // sequence from occurring.
+ default: {
+ if (emitUTF8) {
+ unsigned codepoint = static_cast<unsigned char>(*c);
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else {
+ appendRaw(result, codepoint);
+ }
+ } else {
+ unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else if (codepoint < 0x80) {
+ appendRaw(result, codepoint);
+ } else if (codepoint < 0x10000) {
+ // Basic Multilingual Plane
+ appendHex(result, codepoint);
+ } else {
+ // Extended Unicode. Encode 20 bits as a surrogate pair.
+ codepoint -= 0x10000;
+ appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
+ appendHex(result, 0xdc00 + (codepoint & 0x3ff));
+ }
+ }
+ } break;
+ }
+ }
+ result += "\"";
+ return result;
+}
+
+String valueToQuotedString(const char* value) {
+ return valueToQuotedStringN(value, strlen(value));
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer() = default;
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+
+ = default;
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
+
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+
+String FastWriter::write(const Value& root) {
+ document_.clear();
+ writeValue(root);
+ if (!omitEndingLineFeed_)
+ document_ += '\n';
+ return document_;
+}
+
+void FastWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ if (!dropNullPlaceholders_)
+ document_ += "null";
+ break;
+ case intValue:
+ document_ += valueToString(value.asLargestInt());
+ break;
+ case uintValue:
+ document_ += valueToString(value.asLargestUInt());
+ break;
+ case realValue:
+ document_ += valueToString(value.asDouble());
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
+ break;
+ }
+ case booleanValue:
+ document_ += valueToString(value.asBool());
+ break;
+ case arrayValue: {
+ document_ += '[';
+ ArrayIndex size = value.size();
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ',';
+ writeValue(value[index]);
+ }
+ document_ += ']';
+ } break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ document_ += '{';
+ for (auto it = members.begin(); it != members.end(); ++it) {
+ const String& name = *it;
+ if (it != members.begin())
+ document_ += ',';
+ document_ += valueToQuotedStringN(name.data(), name.length());
+ document_ += yamlCompatibilityEnabled_ ? ": " : ":";
+ writeValue(value[name]);
+ }
+ document_ += '}';
+ } break;
+ }
+}
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter() = default;
+
+String StyledWriter::write(const Value& root) {
+ document_.clear();
+ addChildValues_ = false;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ document_ += '\n';
+ return document_;
+}
+
+void StyledWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
+ else
+ pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ auto it = members.begin();
+ for (;;) {
+ const String& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ document_ += " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void StyledWriter::writeArrayValue(const Value& value) {
+ size_t size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultilineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ ArrayIndex index = 0;
+ for (;;) {
+ const Value& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ writeIndent();
+ writeValue(childValue);
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ document_ += ',';
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ document_ += "[ ";
+ for (size_t index = 0; index < size; ++index) {
+ if (index > 0)
+ document_ += ", ";
+ document_ += childValues_[index];
+ }
+ document_ += " ]";
+ }
+ }
+}
+
+bool StyledWriter::isMultilineArray(const Value& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ const Value& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ !childValue.empty());
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledWriter::pushValue(const String& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ document_ += value;
+}
+
+void StyledWriter::writeIndent() {
+ if (!document_.empty()) {
+ char last = document_[document_.length() - 1];
+ if (last == ' ') // already indented
+ return;
+ if (last != '\n') // Comments may add new-line
+ document_ += '\n';
+ }
+ document_ += indentString_;
+}
+
+void StyledWriter::writeWithIndent(const String& value) {
+ writeIndent();
+ document_ += value;
+}
+
+void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); }
+
+void StyledWriter::unindent() {
+ assert(indentString_.size() >= indentSize_);
+ indentString_.resize(indentString_.size() - indentSize_);
+}
+
+void StyledWriter::writeCommentBeforeValue(const Value& root) {
+ if (!root.hasComment(commentBefore))
+ return;
+
+ document_ += '\n';
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ document_ += *iter;
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
+ writeIndent();
+ ++iter;
+ }
+
+ // Comments are stripped of trailing newlines, so add one here
+ document_ += '\n';
+}
+
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ document_ += " " + root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ document_ += '\n';
+ document_ += root.getComment(commentAfter);
+ document_ += '\n';
+ }
+}
+
+bool StyledWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter(String indentation)
+ : document_(nullptr), indentation_(std::move(indentation)),
+ addChildValues_(), indented_(false) {}
+
+void StyledStreamWriter::write(OStream& out, const Value& root) {
+ document_ = &out;
+ addChildValues_ = false;
+ indentString_.clear();
+ indented_ = true;
+ writeCommentBeforeValue(root);
+ if (!indented_)
+ writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *document_ << "\n";
+ document_ = nullptr; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue("null");
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble()));
+ break;
+ case stringValue: {
+ // Is NULL possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
+ else
+ pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ auto it = members.begin();
+ for (;;) {
+ const String& name = *it;
+ const Value& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(valueToQuotedString(name.c_str()));
+ *document_ << " : ";
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void StyledStreamWriter::writeArrayValue(const Value& value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isArrayMultiLine = isMultilineArray(value);
+ if (isArrayMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ for (;;) {
+ const Value& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ if (!indented_)
+ writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *document_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ *document_ << "[ ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ *document_ << ", ";
+ *document_ << childValues_[index];
+ }
+ *document_ << " ]";
+ }
+ }
+}
+
+bool StyledStreamWriter::isMultilineArray(const Value& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ const Value& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ !childValue.empty());
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void StyledStreamWriter::pushValue(const String& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ *document_ << value;
+}
+
+void StyledStreamWriter::writeIndent() {
+ // blep intended this to look at the so-far-written string
+ // to determine whether we are already indented, but
+ // with a stream we cannot do that. So we rely on some saved state.
+ // The caller checks indented_.
+ *document_ << '\n' << indentString_;
+}
+
+void StyledStreamWriter::writeWithIndent(const String& value) {
+ if (!indented_)
+ writeIndent();
+ *document_ << value;
+ indented_ = false;
+}
+
+void StyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void StyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+ if (!root.hasComment(commentBefore))
+ return;
+
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ *document_ << *iter;
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
+ // writeIndent(); // would include newline
+ *document_ << indentString_;
+ ++iter;
+ }
+ indented_ = false;
+}
+
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+ if (root.hasComment(commentAfterOnSameLine))
+ *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ writeIndent();
+ *document_ << root.getComment(commentAfter);
+ }
+ indented_ = false;
+}
+
+bool StyledStreamWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+//////////////////////////
+// BuiltStyledStreamWriter
+
+/// Scoped enums are not available until C++11.
+struct CommentStyle {
+ /// Decide whether to write comments.
+ enum Enum {
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
+ };
+};
+
+struct BuiltStyledStreamWriter : public StreamWriter {
+ BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs,
+ String colonSymbol, String nullSymbol,
+ String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision,
+ PrecisionType precisionType);
+ int write(Value const& root, OStream* sout) override;
+
+private:
+ void writeValue(Value const& value);
+ void writeArrayValue(Value const& value);
+ bool isMultilineArray(Value const& value);
+ void pushValue(String const& value);
+ void writeIndent();
+ void writeWithIndent(String const& value);
+ void indent();
+ void unindent();
+ void writeCommentBeforeValue(Value const& root);
+ void writeCommentAfterValueOnSameLine(Value const& root);
+ static bool hasCommentForValue(const Value& value);
+
+ using ChildValues = std::vector<String>;
+
+ ChildValues childValues_;
+ String indentString_;
+ unsigned int rightMargin_;
+ String indentation_;
+ CommentStyle::Enum cs_;
+ String colonSymbol_;
+ String nullSymbol_;
+ String endingLineFeedSymbol_;
+ bool addChildValues_ : 1;
+ bool indented_ : 1;
+ bool useSpecialFloats_ : 1;
+ bool emitUTF8_ : 1;
+ unsigned int precision_;
+ PrecisionType precisionType_;
+};
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(
+ String indentation, CommentStyle::Enum cs, String colonSymbol,
+ String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision, PrecisionType precisionType)
+ : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
+ colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
+ endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
+ addChildValues_(false), indented_(false),
+ useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
+ precision_(precision), precisionType_(precisionType) {}
+int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
+ sout_ = sout;
+ addChildValues_ = false;
+ indented_ = true;
+ indentString_.clear();
+ writeCommentBeforeValue(root);
+ if (!indented_)
+ writeIndent();
+ indented_ = true;
+ writeValue(root);
+ writeCommentAfterValueOnSameLine(root);
+ *sout_ << endingLineFeedSymbol_;
+ sout_ = nullptr;
+ return 0;
+}
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
+ switch (value.type()) {
+ case nullValue:
+ pushValue(nullSymbol_);
+ break;
+ case intValue:
+ pushValue(valueToString(value.asLargestInt()));
+ break;
+ case uintValue:
+ pushValue(valueToString(value.asLargestUInt()));
+ break;
+ case realValue:
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_,
+ precisionType_));
+ break;
+ case stringValue: {
+ // Is NULL is possible for value.string_? No.
+ char const* str;
+ char const* end;
+ bool ok = value.getString(&str, &end);
+ if (ok)
+ pushValue(
+ valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
+ else
+ pushValue("");
+ break;
+ }
+ case booleanValue:
+ pushValue(valueToString(value.asBool()));
+ break;
+ case arrayValue:
+ writeArrayValue(value);
+ break;
+ case objectValue: {
+ Value::Members members(value.getMemberNames());
+ if (members.empty())
+ pushValue("{}");
+ else {
+ writeWithIndent("{");
+ indent();
+ auto it = members.begin();
+ for (;;) {
+ String const& name = *it;
+ Value const& childValue = value[name];
+ writeCommentBeforeValue(childValue);
+ writeWithIndent(
+ valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
+ *sout_ << colonSymbol_;
+ writeValue(childValue);
+ if (++it == members.end()) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("}");
+ }
+ } break;
+ }
+}
+
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+ unsigned size = value.size();
+ if (size == 0)
+ pushValue("[]");
+ else {
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
+ if (isMultiLine) {
+ writeWithIndent("[");
+ indent();
+ bool hasChildValue = !childValues_.empty();
+ unsigned index = 0;
+ for (;;) {
+ Value const& childValue = value[index];
+ writeCommentBeforeValue(childValue);
+ if (hasChildValue)
+ writeWithIndent(childValues_[index]);
+ else {
+ if (!indented_)
+ writeIndent();
+ indented_ = true;
+ writeValue(childValue);
+ indented_ = false;
+ }
+ if (++index == size) {
+ writeCommentAfterValueOnSameLine(childValue);
+ break;
+ }
+ *sout_ << ",";
+ writeCommentAfterValueOnSameLine(childValue);
+ }
+ unindent();
+ writeWithIndent("]");
+ } else // output on a single line
+ {
+ assert(childValues_.size() == size);
+ *sout_ << "[";
+ if (!indentation_.empty())
+ *sout_ << " ";
+ for (unsigned index = 0; index < size; ++index) {
+ if (index > 0)
+ *sout_ << ((!indentation_.empty()) ? ", " : ",");
+ *sout_ << childValues_[index];
+ }
+ if (!indentation_.empty())
+ *sout_ << " ";
+ *sout_ << "]";
+ }
+ }
+}
+
+bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
+ ArrayIndex const size = value.size();
+ bool isMultiLine = size * 3 >= rightMargin_;
+ childValues_.clear();
+ for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
+ Value const& childValue = value[index];
+ isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+ !childValue.empty());
+ }
+ if (!isMultiLine) // check if line length > max line length
+ {
+ childValues_.reserve(size);
+ addChildValues_ = true;
+ ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+ for (ArrayIndex index = 0; index < size; ++index) {
+ if (hasCommentForValue(value[index])) {
+ isMultiLine = true;
+ }
+ writeValue(value[index]);
+ lineLength += static_cast<ArrayIndex>(childValues_[index].length());
+ }
+ addChildValues_ = false;
+ isMultiLine = isMultiLine || lineLength >= rightMargin_;
+ }
+ return isMultiLine;
+}
+
+void BuiltStyledStreamWriter::pushValue(String const& value) {
+ if (addChildValues_)
+ childValues_.push_back(value);
+ else
+ *sout_ << value;
+}
+
+void BuiltStyledStreamWriter::writeIndent() {
+ // blep intended this to look at the so-far-written string
+ // to determine whether we are already indented, but
+ // with a stream we cannot do that. So we rely on some saved state.
+ // The caller checks indented_.
+
+ if (!indentation_.empty()) {
+ // In this case, drop newlines too.
+ *sout_ << '\n' << indentString_;
+ }
+}
+
+void BuiltStyledStreamWriter::writeWithIndent(String const& value) {
+ if (!indented_)
+ writeIndent();
+ *sout_ << value;
+ indented_ = false;
+}
+
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void BuiltStyledStreamWriter::unindent() {
+ assert(indentString_.size() >= indentation_.size());
+ indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+ if (cs_ == CommentStyle::None)
+ return;
+ if (!root.hasComment(commentBefore))
+ return;
+
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
+ while (iter != comment.end()) {
+ *sout_ << *iter;
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
+ // writeIndent(); // would write extra newline
+ *sout_ << indentString_;
+ ++iter;
+ }
+ indented_ = false;
+}
+
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
+ Value const& root) {
+ if (cs_ == CommentStyle::None)
+ return;
+ if (root.hasComment(commentAfterOnSameLine))
+ *sout_ << " " + root.getComment(commentAfterOnSameLine);
+
+ if (root.hasComment(commentAfter)) {
+ writeIndent();
+ *sout_ << root.getComment(commentAfter);
+ }
+}
+
+// static
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+ return value.hasComment(commentBefore) ||
+ value.hasComment(commentAfterOnSameLine) ||
+ value.hasComment(commentAfter);
+}
+
+///////////////
+// StreamWriter
+
+StreamWriter::StreamWriter() : sout_(nullptr) {}
+StreamWriter::~StreamWriter() = default;
+StreamWriter::Factory::~Factory() = default;
+StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
+StreamWriterBuilder::~StreamWriterBuilder() = default;
+StreamWriter* StreamWriterBuilder::newStreamWriter() const {
+ const String indentation = settings_["indentation"].asString();
+ const String cs_str = settings_["commentStyle"].asString();
+ const String pt_str = settings_["precisionType"].asString();
+ const bool eyc = settings_["enableYAMLCompatibility"].asBool();
+ const bool dnp = settings_["dropNullPlaceholders"].asBool();
+ const bool usf = settings_["useSpecialFloats"].asBool();
+ const bool emitUTF8 = settings_["emitUTF8"].asBool();
+ unsigned int pre = settings_["precision"].asUInt();
+ CommentStyle::Enum cs = CommentStyle::All;
+ if (cs_str == "All") {
+ cs = CommentStyle::All;
+ } else if (cs_str == "None") {
+ cs = CommentStyle::None;
+ } else {
+ throwRuntimeError("commentStyle must be 'All' or 'None'");
+ }
+ PrecisionType precisionType(significantDigits);
+ if (pt_str == "significant") {
+ precisionType = PrecisionType::significantDigits;
+ } else if (pt_str == "decimal") {
+ precisionType = PrecisionType::decimalPlaces;
+ } else {
+ throwRuntimeError("precisionType must be 'significant' or 'decimal'");
+ }
+ String colonSymbol = " : ";
+ if (eyc) {
+ colonSymbol = ": ";
+ } else if (indentation.empty()) {
+ colonSymbol = ":";
+ }
+ String nullSymbol = "null";
+ if (dnp) {
+ nullSymbol.clear();
+ }
+ if (pre > 17)
+ pre = 17;
+ String endingLineFeedSymbol;
+ return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
+ endingLineFeedSymbol, usf, emitUTF8, pre,
+ precisionType);
+}
+
+bool StreamWriterBuilder::validate(Json::Value* invalid) const {
+ static const auto& valid_keys = *new std::set<String>{
+ "indentation",
+ "commentStyle",
+ "enableYAMLCompatibility",
+ "dropNullPlaceholders",
+ "useSpecialFloats",
+ "emitUTF8",
+ "precision",
+ "precisionType",
+ };
+ for (auto si = settings_.begin(); si != settings_.end(); ++si) {
+ auto key = si.name();
+ if (valid_keys.count(key))
+ continue;
+ if (invalid)
+ (*invalid)[key] = *si;
+ else
+ return false;
+ }
+ return invalid ? invalid->empty() : true;
+}
+
+Value& StreamWriterBuilder::operator[](const String& key) {
+ return settings_[key];
+}
+// static
+void StreamWriterBuilder::setDefaults(Json::Value* settings) {
+ //! [StreamWriterBuilderDefaults]
+ (*settings)["commentStyle"] = "All";
+ (*settings)["indentation"] = "\t";
+ (*settings)["enableYAMLCompatibility"] = false;
+ (*settings)["dropNullPlaceholders"] = false;
+ (*settings)["useSpecialFloats"] = false;
+ (*settings)["emitUTF8"] = false;
+ (*settings)["precision"] = 17;
+ (*settings)["precisionType"] = "significant";
+ //! [StreamWriterBuilderDefaults]
+}
+
+String writeString(StreamWriter::Factory const& factory, Value const& root) {
+ OStringStream sout;
+ StreamWriterPtr const writer(factory.newStreamWriter());
+ writer->write(root, &sout);
+ return sout.str();
+}
+
+OStream& operator<<(OStream& sout, Value const& root) {
+ StreamWriterBuilder builder;
+ StreamWriterPtr const writer(builder.newStreamWriter());
+ writer->write(root, &sout);
+ return sout;
+}
+
+} // namespace Json
diff --git a/thirdparty/openxr/src/loader/.gitignore b/thirdparty/openxr/src/loader/.gitignore
new file mode 100644
index 0000000000..5e8e0ba3a4
--- /dev/null
+++ b/thirdparty/openxr/src/loader/.gitignore
@@ -0,0 +1,5 @@
+# Copyright (c) 2020 The Khronos Group Inc.
+#
+# SPDX-License-Identifier: Apache-2.0
+
+!openxr_loader_for_android.pom
diff --git a/thirdparty/openxr/src/loader/android_utilities.cpp b/thirdparty/openxr/src/loader/android_utilities.cpp
new file mode 100644
index 0000000000..807a775820
--- /dev/null
+++ b/thirdparty/openxr/src/loader/android_utilities.cpp
@@ -0,0 +1,319 @@
+// Copyright (c) 2020-2022, The Khronos Group Inc.
+// Copyright (c) 2020-2021, Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+
+#include "android_utilities.h"
+
+#ifdef __ANDROID__
+#include <wrap/android.net.h>
+#include <wrap/android.content.h>
+#include <wrap/android.database.h>
+#include <json/value.h>
+
+#include <openxr/openxr.h>
+
+#include <sstream>
+#include <vector>
+#include <android/log.h>
+
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, "openxr_loader", __VA_ARGS__)
+#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, "openxr_loader", __VA_ARGS__)
+#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "openxr_loader", __VA_ARGS__)
+#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, "openxr_loader", __VA_ARGS__)
+
+namespace openxr_android {
+using wrap::android::content::ContentUris;
+using wrap::android::content::Context;
+using wrap::android::database::Cursor;
+using wrap::android::net::Uri;
+using wrap::android::net::Uri_Builder;
+
+// Code in here corresponds roughly to the Java "BrokerContract" class and subclasses.
+namespace {
+constexpr auto AUTHORITY = "org.khronos.openxr.runtime_broker";
+constexpr auto SYSTEM_AUTHORITY = "org.khronos.openxr.system_runtime_broker";
+constexpr auto BASE_PATH = "openxr";
+constexpr auto ABI_PATH = "abi";
+constexpr auto RUNTIMES_PATH = "runtimes";
+
+constexpr const char *getBrokerAuthority(bool systemBroker) { return systemBroker ? SYSTEM_AUTHORITY : AUTHORITY; }
+
+struct BaseColumns {
+ /**
+ * The unique ID for a row.
+ */
+ [[maybe_unused]] static constexpr auto ID = "_id";
+};
+
+/**
+ * Contains details for the /openxr/[major_ver]/abi/[abi]/runtimes/active URI.
+ * <p>
+ * This URI represents a "table" containing at most one item, the currently active runtime. The
+ * policy of which runtime is chosen to be active (if more than one is installed) is left to the
+ * content provider.
+ * <p>
+ * No sort order is required to be honored by the content provider.
+ */
+namespace active_runtime {
+/**
+ * Final path component to this URI.
+ */
+static constexpr auto TABLE_PATH = "active";
+
+/**
+ * Create a content URI for querying the data on the active runtime for a
+ * given major version of OpenXR.
+ *
+ * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
+ * @param majorVer The major version of OpenXR.
+ * @param abi The Android ABI name in use.
+ * @return A content URI for a single item: the active runtime.
+ */
+static Uri makeContentUri(bool systemBroker, int majorVersion, const char *abi) {
+ auto builder = Uri_Builder::construct();
+ builder.scheme("content")
+ .authority(getBrokerAuthority(systemBroker))
+ .appendPath(BASE_PATH)
+ .appendPath(std::to_string(majorVersion))
+ .appendPath(ABI_PATH)
+ .appendPath(abi)
+ .appendPath(RUNTIMES_PATH)
+ .appendPath(TABLE_PATH);
+ ContentUris::appendId(builder, 0);
+ return builder.build();
+}
+
+struct Columns : BaseColumns {
+ /**
+ * Constant for the PACKAGE_NAME column name
+ */
+ static constexpr auto PACKAGE_NAME = "package_name";
+
+ /**
+ * Constant for the NATIVE_LIB_DIR column name
+ */
+ static constexpr auto NATIVE_LIB_DIR = "native_lib_dir";
+
+ /**
+ * Constant for the SO_FILENAME column name
+ */
+ static constexpr auto SO_FILENAME = "so_filename";
+
+ /**
+ * Constant for the HAS_FUNCTIONS column name.
+ * <p>
+ * If this column contains true, you should check the /functions/ URI for that runtime.
+ */
+ static constexpr auto HAS_FUNCTIONS = "has_functions";
+};
+} // namespace active_runtime
+
+/**
+ * Contains details for the /openxr/[major_ver]/abi/[abi]/runtimes/[package]/functions URI.
+ * <p>
+ * This URI is for package-specific function name remapping. Since this is an optional field in
+ * the corresponding JSON manifests for OpenXR, it is optional here as well. If the active
+ * runtime contains "true" in its "has_functions" column, then this table must exist and be
+ * queryable.
+ * <p>
+ * No sort order is required to be honored by the content provider.
+ */
+namespace functions {
+/**
+ * Final path component to this URI.
+ */
+static constexpr auto TABLE_PATH = "functions";
+
+/**
+ * Create a content URI for querying all rows of the function remapping data for a given
+ * runtime package and major version of OpenXR.
+ *
+ * @param systemBroker If the system runtime broker (instead of the installable one) should be queried.
+ * @param majorVer The major version of OpenXR.
+ * @param packageName The package name of the runtime.
+ * @param abi The Android ABI name in use.
+ * @return A content URI for the entire table: the function remapping for that runtime.
+ */
+static Uri makeContentUri(bool systemBroker, int majorVersion, std::string const &packageName, const char *abi) {
+ auto builder = Uri_Builder::construct();
+ builder.scheme("content")
+ .authority(getBrokerAuthority(systemBroker))
+ .appendPath(BASE_PATH)
+ .appendPath(std::to_string(majorVersion))
+ .appendPath(ABI_PATH)
+ .appendPath(abi)
+ .appendPath(RUNTIMES_PATH)
+ .appendPath(packageName)
+ .appendPath(TABLE_PATH);
+ return builder.build();
+}
+
+struct Columns : BaseColumns {
+ /**
+ * Constant for the FUNCTION_NAME column name
+ */
+ static constexpr auto FUNCTION_NAME = "function_name";
+
+ /**
+ * Constant for the SYMBOL_NAME column name
+ */
+ static constexpr auto SYMBOL_NAME = "symbol_name";
+};
+} // namespace functions
+
+} // namespace
+
+static inline jni::Array<std::string> makeArray(std::initializer_list<const char *> &&list) {
+ auto ret = jni::Array<std::string>{(long)list.size()};
+ long i = 0;
+ for (auto &&elt : list) {
+ ret.setElement(i, elt);
+ ++i;
+ }
+ return ret;
+}
+static constexpr auto TAG = "OpenXR-Loader";
+
+#if defined(__arm__)
+static constexpr auto ABI = "armeabi-v7l";
+#elif defined(__aarch64__)
+static constexpr auto ABI = "arm64-v8a";
+#elif defined(__i386__)
+static constexpr auto ABI = "x86";
+#elif defined(__x86_64__)
+static constexpr auto ABI = "x86_64";
+#else
+#error "Unknown ABI!"
+#endif
+
+/// Helper class to generate the jsoncpp object corresponding to a synthetic runtime manifest.
+class JsonManifestBuilder {
+ public:
+ JsonManifestBuilder(const std::string &libraryPathParent, const std::string &libraryPath);
+ JsonManifestBuilder &function(const std::string &functionName, const std::string &symbolName);
+
+ Json::Value build() const { return root_node; }
+
+ private:
+ Json::Value root_node;
+};
+
+inline JsonManifestBuilder::JsonManifestBuilder(const std::string &libraryPathParent, const std::string &libraryPath)
+ : root_node(Json::objectValue) {
+ root_node["file_format_version"] = "1.0.0";
+ root_node["instance_extensions"] = Json::Value(Json::arrayValue);
+ root_node["functions"] = Json::Value(Json::objectValue);
+ root_node[libraryPathParent] = Json::objectValue;
+ root_node[libraryPathParent]["library_path"] = libraryPath;
+}
+
+inline JsonManifestBuilder &JsonManifestBuilder::function(const std::string &functionName, const std::string &symbolName) {
+ root_node["functions"][functionName] = symbolName;
+ return *this;
+}
+
+static constexpr const char *getBrokerTypeName(bool systemBroker) { return systemBroker ? "system" : "installable"; }
+
+static int populateFunctions(wrap::android::content::Context const &context, bool systemBroker, const std::string &packageName,
+ JsonManifestBuilder &builder) {
+ jni::Array<std::string> projection = makeArray({functions::Columns::FUNCTION_NAME, functions::Columns::SYMBOL_NAME});
+
+ auto uri = functions::makeContentUri(systemBroker, XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), packageName, ABI);
+ ALOGI("populateFunctions: Querying URI: %s", uri.toString().c_str());
+
+ Cursor cursor = context.getContentResolver().query(uri, projection);
+
+ if (cursor.isNull()) {
+ ALOGE("Null cursor when querying content resolver for functions.");
+ return -1;
+ }
+ if (cursor.getCount() < 1) {
+ ALOGE("Non-null but empty cursor when querying content resolver for functions.");
+ cursor.close();
+ return -1;
+ }
+ auto functionIndex = cursor.getColumnIndex(functions::Columns::FUNCTION_NAME);
+ auto symbolIndex = cursor.getColumnIndex(functions::Columns::SYMBOL_NAME);
+ while (cursor.moveToNext()) {
+ builder.function(cursor.getString(functionIndex), cursor.getString(symbolIndex));
+ }
+
+ cursor.close();
+ return 0;
+}
+
+/// Get cursor for active runtime, parameterized by whether or not we use the system broker
+static bool getActiveRuntimeCursor(wrap::android::content::Context const &context, jni::Array<std::string> const &projection,
+ bool systemBroker, Cursor &cursor) {
+ auto uri = active_runtime::makeContentUri(systemBroker, XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), ABI);
+ ALOGI("getActiveRuntimeCursor: Querying URI: %s", uri.toString().c_str());
+ try {
+ cursor = context.getContentResolver().query(uri, projection);
+ } catch (const std::exception &e) {
+ ALOGW("Exception when querying %s content resolver: %s", getBrokerTypeName(systemBroker), e.what());
+ cursor = {};
+ return false;
+ }
+
+ if (cursor.isNull()) {
+ ALOGW("Null cursor when querying %s content resolver.", getBrokerTypeName(systemBroker));
+ cursor = {};
+ return false;
+ }
+ if (cursor.getCount() < 1) {
+ ALOGW("Non-null but empty cursor when querying %s content resolver.", getBrokerTypeName(systemBroker));
+ cursor.close();
+ cursor = {};
+ return false;
+ }
+ return true;
+}
+
+int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &context, Json::Value &virtualManifest) {
+ jni::Array<std::string> projection = makeArray({active_runtime::Columns::PACKAGE_NAME, active_runtime::Columns::NATIVE_LIB_DIR,
+ active_runtime::Columns::SO_FILENAME, active_runtime::Columns::HAS_FUNCTIONS});
+
+ // First, try getting the installable broker's provider
+ bool systemBroker = false;
+ Cursor cursor;
+ if (!getActiveRuntimeCursor(context, projection, systemBroker, cursor)) {
+ // OK, try the system broker as a fallback.
+ systemBroker = true;
+ getActiveRuntimeCursor(context, projection, systemBroker, cursor);
+ }
+
+ if (cursor.isNull()) {
+ // Couldn't find either broker
+ ALOGE("Could access neither the installable nor system runtime broker.");
+ return -1;
+ }
+
+ cursor.moveToFirst();
+
+ auto filename = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::SO_FILENAME));
+ auto libDir = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::NATIVE_LIB_DIR));
+ auto packageName = cursor.getString(cursor.getColumnIndex(active_runtime::Columns::PACKAGE_NAME));
+
+ auto hasFunctions = cursor.getInt(cursor.getColumnIndex(active_runtime::Columns::HAS_FUNCTIONS)) == 1;
+ __android_log_print(ANDROID_LOG_INFO, TAG, "Got runtime: package: %s, so filename: %s, native lib dir: %s, has functions: %s",
+ packageName.c_str(), libDir.c_str(), filename.c_str(), (hasFunctions ? "yes" : "no"));
+
+ auto lib_path = libDir + "/" + filename;
+ cursor.close();
+
+ JsonManifestBuilder builder{"runtime", lib_path};
+ if (hasFunctions) {
+ int result = populateFunctions(context, systemBroker, packageName, builder);
+ if (result != 0) {
+ return result;
+ }
+ }
+ virtualManifest = builder.build();
+ return 0;
+}
+} // namespace openxr_android
+
+#endif // __ANDROID__
diff --git a/thirdparty/openxr/src/loader/android_utilities.h b/thirdparty/openxr/src/loader/android_utilities.h
new file mode 100644
index 0000000000..adb8abaf1f
--- /dev/null
+++ b/thirdparty/openxr/src/loader/android_utilities.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2020-2022, The Khronos Group Inc.
+// Copyright (c) 2020-2021, Collabora, Ltd.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+
+#pragma once
+#ifdef __ANDROID__
+
+#include "wrap/android.content.h"
+
+#include <string>
+namespace Json {
+class Value;
+} // namespace Json
+
+namespace openxr_android {
+using wrap::android::content::Context;
+
+/*!
+ * Find the single active OpenXR runtime on the system, and return a constructed JSON object representing it.
+ *
+ * @param context An Android context, preferably an Activity Context.
+ * @param[out] virtualManifest The Json::Value to fill with the virtual manifest.
+ *
+ * @return 0 on success, something else on failure.
+ */
+int getActiveRuntimeVirtualManifest(wrap::android::content::Context const &context, Json::Value &virtualManifest);
+} // namespace openxr_android
+
+#endif // __ANDROID__
diff --git a/thirdparty/openxr/src/loader/api_layer_interface.cpp b/thirdparty/openxr/src/loader/api_layer_interface.cpp
new file mode 100644
index 0000000000..c3fd5bb7f1
--- /dev/null
+++ b/thirdparty/openxr/src/loader/api_layer_interface.cpp
@@ -0,0 +1,399 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#include "api_layer_interface.hpp"
+
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "manifest_file.hpp"
+#include "platform_utils.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#define OPENXR_ENABLE_LAYERS_ENV_VAR "XR_ENABLE_API_LAYERS"
+
+// Add any layers defined in the loader layer environment variable.
+static void AddEnvironmentApiLayers(std::vector<std::string>& enabled_layers) {
+ std::string layers = PlatformUtilsGetEnv(OPENXR_ENABLE_LAYERS_ENV_VAR);
+
+ std::size_t last_found = 0;
+ std::size_t found = layers.find_first_of(PATH_SEPARATOR);
+ std::string cur_search;
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ cur_search = layers.substr(last_found, found - last_found);
+ enabled_layers.push_back(cur_search);
+ last_found = found + 1;
+ found = layers.find_first_of(PATH_SEPARATOR, last_found);
+ }
+
+ // If there's something remaining in the string, copy it over
+ if (last_found < layers.size()) {
+ cur_search = layers.substr(last_found);
+ enabled_layers.push_back(cur_search);
+ }
+}
+
+XrResult ApiLayerInterface::GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count,
+ uint32_t* outgoing_count, XrApiLayerProperties* api_layer_properties) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
+ uint32_t manifest_count = 0;
+
+ // Validate props struct before proceeding
+ if (0 < incoming_count && nullptr != api_layer_properties) {
+ for (uint32_t i = 0; i < incoming_count; i++) {
+ if (XR_TYPE_API_LAYER_PROPERTIES != api_layer_properties[i].type) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "VUID-XrApiLayerProperties-type-type: unknown type in api_layer_properties");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ }
+ }
+
+ // "Independent of elementCapacityInput or elements parameters, elementCountOutput must be a valid pointer,
+ // and the function sets elementCountOutput." - 2.11
+ if (nullptr == outgoing_count) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ // Find any implicit layers which we may need to report information for.
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCEEDED(result)) {
+ // Find any explicit layers which we may need to report information for.
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
+ }
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "ApiLayerInterface::GetApiLayerProperties - failed searching for API layer manifest files");
+ return result;
+ }
+
+ manifest_count = static_cast<uint32_t>(manifest_files.size());
+ if (nullptr == outgoing_count) {
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
+ "VUID-xrEnumerateApiLayerProperties-propertyCountOutput-parameter: null propertyCountOutput");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ *outgoing_count = manifest_count;
+ if (0 == incoming_count) {
+ // capacity check only
+ return XR_SUCCESS;
+ }
+ if (nullptr == api_layer_properties) {
+ // incoming_count is not 0 BUT the api_layer_properties is NULL
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
+ "VUID-xrEnumerateApiLayerProperties-properties-parameter: non-zero capacity but null array");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (incoming_count < manifest_count) {
+ LoaderLogger::LogErrorMessage(
+ "xrEnumerateInstanceExtensionProperties",
+ "VUID-xrEnumerateApiLayerProperties-propertyCapacityInput-parameter: insufficient space in array");
+ return XR_ERROR_SIZE_INSUFFICIENT;
+ }
+
+ for (uint32_t prop = 0; prop < incoming_count && prop < manifest_count; ++prop) {
+ manifest_files[prop]->PopulateApiLayerProperties(api_layer_properties[prop]);
+ }
+ return XR_SUCCESS;
+}
+
+XrResult ApiLayerInterface::GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
+ std::vector<XrExtensionProperties>& extension_properties) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> manifest_files;
+
+ // If a layer name is supplied, only use the information out of that one layer
+ if (nullptr != layer_name && 0 != strlen(layer_name)) {
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCEEDED(result)) {
+ // Find any explicit layers which we may need to report information for.
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, manifest_files);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage(
+ openxr_command,
+ "ApiLayerInterface::GetInstanceExtensionProperties - failed searching for API layer manifest files");
+ return result;
+ }
+
+ bool found = false;
+ auto num_files = static_cast<uint32_t>(manifest_files.size());
+ for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
+ // If a layer with the provided name exists, get it's instance extension information.
+ if (manifest_files[man_file]->LayerName() == layer_name) {
+ manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
+ found = true;
+ break;
+ }
+ }
+
+ // If nothing found, report 0
+ if (!found) {
+ return XR_ERROR_API_LAYER_NOT_PRESENT;
+ }
+ }
+ // Otherwise, we want to add only implicit API layers and explicit API layers enabled using the environment variables
+ } else {
+ XrResult result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, manifest_files);
+ if (XR_SUCCEEDED(result)) {
+ // Find any environmentally enabled explicit layers. If they're present, treat them like implicit layers
+ // since we know that they're going to be enabled.
+ std::vector<std::string> env_enabled_layers;
+ AddEnvironmentApiLayers(env_enabled_layers);
+ if (!env_enabled_layers.empty()) {
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> exp_layer_man_files = {};
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, exp_layer_man_files);
+ if (XR_SUCCEEDED(result)) {
+ for (auto& exp_layer_man_file : exp_layer_man_files) {
+ for (std::string& enabled_layer : env_enabled_layers) {
+ // If this is an enabled layer, transfer it over to the manifest list.
+ if (enabled_layer == exp_layer_man_file->LayerName()) {
+ manifest_files.push_back(std::move(exp_layer_man_file));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Grab the layer instance extensions information
+ auto num_files = static_cast<uint32_t>(manifest_files.size());
+ for (uint32_t man_file = 0; man_file < num_files; ++man_file) {
+ manifest_files[man_file]->GetInstanceExtensionProperties(extension_properties);
+ }
+ }
+ return XR_SUCCESS;
+}
+
+XrResult ApiLayerInterface::LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
+ const char* const* enabled_api_layer_names,
+ std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces) {
+ XrResult last_error = XR_SUCCESS;
+ std::unordered_set<std::string> layers_already_found;
+
+ bool any_loaded = false;
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> enabled_layer_manifest_files_in_init_order = {};
+
+ // Find any implicit layers.
+ XrResult result =
+ ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_IMPLICIT_API_LAYER, enabled_layer_manifest_files_in_init_order);
+
+ for (const auto& enabled_layer_manifest_file : enabled_layer_manifest_files_in_init_order) {
+ layers_already_found.insert(enabled_layer_manifest_file->LayerName());
+ }
+
+ // Find any explicit layers.
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> explicit_layer_manifest_files = {};
+
+ if (XR_SUCCEEDED(result)) {
+ result = ApiLayerManifestFile::FindManifestFiles(MANIFEST_TYPE_EXPLICIT_API_LAYER, explicit_layer_manifest_files);
+ }
+
+ bool found_all_layers = true;
+
+ if (XR_SUCCEEDED(result)) {
+ // Put all explicit and then xrCreateInstance enabled layers into a string vector
+
+ std::vector<std::string> enabled_explicit_api_layer_names = {};
+
+ AddEnvironmentApiLayers(enabled_explicit_api_layer_names);
+
+ if (enabled_api_layer_count > 0) {
+ if (nullptr == enabled_api_layer_names) {
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance",
+ "VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter: enabledApiLayerCount is non-0 but array is NULL");
+ LoaderLogger::LogErrorMessage(
+ "xrCreateInstance", "VUID-xrCreateInstance-info-parameter: something wrong with XrInstanceCreateInfo contents");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ std::copy(enabled_api_layer_names, enabled_api_layer_names + enabled_api_layer_count,
+ std::back_inserter(enabled_explicit_api_layer_names));
+ }
+
+ // add explicit layers to list of layers to enable
+ for (const auto& layer_name : enabled_explicit_api_layer_names) {
+ bool found_this_layer = false;
+
+ for (auto it = explicit_layer_manifest_files.begin(); it != explicit_layer_manifest_files.end();) {
+ bool erased_layer_manifest_file = false;
+
+ if (layers_already_found.count(layer_name) > 0) {
+ found_this_layer = true;
+ } else if (layer_name == (*it)->LayerName()) {
+ found_this_layer = true;
+ layers_already_found.insert(layer_name);
+ enabled_layer_manifest_files_in_init_order.push_back(std::move(*it));
+ it = explicit_layer_manifest_files.erase(it);
+ erased_layer_manifest_file = true;
+ }
+
+ if (!erased_layer_manifest_file) {
+ it++;
+ }
+ }
+
+ // If even one of the layers wasn't found, we want to return an error
+ if (!found_this_layer) {
+ found_all_layers = false;
+ std::string error_message = "ApiLayerInterface::LoadApiLayers - failed to find layer ";
+ error_message += layer_name;
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ }
+ }
+ }
+
+ for (std::unique_ptr<ApiLayerManifestFile>& manifest_file : enabled_layer_manifest_files_in_init_order) {
+ LoaderPlatformLibraryHandle layer_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
+ if (nullptr == layer_library) {
+ if (!any_loaded) {
+ last_error = XR_ERROR_FILE_ACCESS_ERROR;
+ }
+ std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
+ std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
+ warning_message += manifest_file->LayerName();
+ warning_message += ", failed to load with message \"";
+ warning_message += library_message;
+ warning_message += "\"";
+ LoaderLogger::LogWarningMessage(openxr_command, warning_message);
+ continue;
+ }
+
+ // Get and settle on an layer interface version (using any provided name if required).
+ std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderApiLayerInterface");
+ auto negotiate = reinterpret_cast<PFN_xrNegotiateLoaderApiLayerInterface>(
+ LoaderPlatformLibraryGetProcAddr(layer_library, function_name));
+
+ if (nullptr == negotiate) {
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
+ << " because negotiation function " << function_name << " was not found";
+ LoaderLogger::LogErrorMessage(openxr_command, oss.str());
+ LoaderPlatformLibraryClose(layer_library);
+ last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
+ continue;
+ }
+
+ // Loader info for negotiation
+ XrNegotiateLoaderInfo loader_info = {};
+ loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
+ loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
+ loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
+ loader_info.minInterfaceVersion = 1;
+ loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_API_LAYER_VERSION;
+ loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
+ loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
+
+ // Set up the layer return structure
+ XrNegotiateApiLayerRequest api_layer_info = {};
+ api_layer_info.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_REQUEST;
+ api_layer_info.structVersion = XR_API_LAYER_INFO_STRUCT_VERSION;
+ api_layer_info.structSize = sizeof(XrNegotiateApiLayerRequest);
+
+ XrResult res = negotiate(&loader_info, manifest_file->LayerName().c_str(), &api_layer_info);
+ // If we supposedly succeeded, but got a nullptr for getInstanceProcAddr
+ // then something still went wrong, so return with an error.
+ if (XR_SUCCEEDED(res) && nullptr == api_layer_info.getInstanceProcAddr) {
+ std::string warning_message = "ApiLayerInterface::LoadApiLayers skipping layer ";
+ warning_message += manifest_file->LayerName();
+ warning_message += ", negotiation did not return a valid getInstanceProcAddr";
+ LoaderLogger::LogWarningMessage(openxr_command, warning_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ }
+ if (XR_FAILED(res)) {
+ if (!any_loaded) {
+ last_error = res;
+ }
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers skipping layer " << manifest_file->LayerName()
+ << " due to failed negotiation with error " << res;
+ LoaderLogger::LogWarningMessage(openxr_command, oss.str());
+ LoaderPlatformLibraryClose(layer_library);
+ continue;
+ }
+
+ {
+ std::ostringstream oss;
+ oss << "ApiLayerInterface::LoadApiLayers succeeded loading layer " << manifest_file->LayerName()
+ << " using interface version " << api_layer_info.layerInterfaceVersion << " and OpenXR API version "
+ << XR_VERSION_MAJOR(api_layer_info.layerApiVersion) << "." << XR_VERSION_MINOR(api_layer_info.layerApiVersion);
+ LoaderLogger::LogInfoMessage(openxr_command, oss.str());
+ }
+
+ // Grab the list of extensions this layer supports for easy filtering after the
+ // xrCreateInstance call
+ std::vector<std::string> supported_extensions;
+ std::vector<XrExtensionProperties> extension_properties;
+ manifest_file->GetInstanceExtensionProperties(extension_properties);
+ supported_extensions.reserve(extension_properties.size());
+ for (XrExtensionProperties& ext_prop : extension_properties) {
+ supported_extensions.emplace_back(ext_prop.extensionName);
+ }
+
+ // Add this API layer to the vector
+ api_layer_interfaces.emplace_back(new ApiLayerInterface(manifest_file->LayerName(), layer_library, supported_extensions,
+ api_layer_info.getInstanceProcAddr,
+ api_layer_info.createApiLayerInstance));
+
+ // If we load one, clear all errors.
+ any_loaded = true;
+ last_error = XR_SUCCESS;
+ }
+
+ // Set error here to preserve prior error behavior
+ if (!found_all_layers) {
+ last_error = XR_ERROR_API_LAYER_NOT_PRESENT;
+ }
+
+ // If we failed catastrophically for some reason, clean up everything.
+ if (XR_FAILED(last_error)) {
+ api_layer_interfaces.clear();
+ }
+
+ return last_error;
+}
+
+ApiLayerInterface::ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
+ std::vector<std::string>& supported_extensions,
+ PFN_xrGetInstanceProcAddr get_instance_proc_addr,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance)
+ : _layer_name(layer_name),
+ _layer_library(layer_library),
+ _get_instance_proc_addr(get_instance_proc_addr),
+ _create_api_layer_instance(create_api_layer_instance),
+ _supported_extensions(supported_extensions) {}
+
+ApiLayerInterface::~ApiLayerInterface() {
+ std::string info_message = "ApiLayerInterface being destroyed for layer ";
+ info_message += _layer_name;
+ LoaderLogger::LogInfoMessage("", info_message);
+ LoaderPlatformLibraryClose(_layer_library);
+}
+
+bool ApiLayerInterface::SupportsExtension(const std::string& extension_name) const {
+ bool found_prop = false;
+ for (const std::string& supported_extension : _supported_extensions) {
+ if (supported_extension == extension_name) {
+ found_prop = true;
+ break;
+ }
+ }
+ return found_prop;
+}
diff --git a/thirdparty/openxr/src/loader/api_layer_interface.hpp b/thirdparty/openxr/src/loader/api_layer_interface.hpp
new file mode 100644
index 0000000000..b93e44584e
--- /dev/null
+++ b/thirdparty/openxr/src/loader/api_layer_interface.hpp
@@ -0,0 +1,54 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <openxr/openxr.h>
+
+#include "loader_platform.hpp"
+#include "loader_interfaces.h"
+
+struct XrGeneratedDispatchTable;
+
+class ApiLayerInterface {
+ public:
+ // Factory method
+ static XrResult LoadApiLayers(const std::string& openxr_command, uint32_t enabled_api_layer_count,
+ const char* const* enabled_api_layer_names,
+ std::vector<std::unique_ptr<ApiLayerInterface>>& api_layer_interfaces);
+ // Static queries
+ static XrResult GetApiLayerProperties(const std::string& openxr_command, uint32_t incoming_count, uint32_t* outgoing_count,
+ XrApiLayerProperties* api_layer_properties);
+ static XrResult GetInstanceExtensionProperties(const std::string& openxr_command, const char* layer_name,
+ std::vector<XrExtensionProperties>& extension_properties);
+
+ ApiLayerInterface(const std::string& layer_name, LoaderPlatformLibraryHandle layer_library,
+ std::vector<std::string>& supported_extensions, PFN_xrGetInstanceProcAddr get_instance_proc_addr,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance);
+ virtual ~ApiLayerInterface();
+
+ PFN_xrGetInstanceProcAddr GetInstanceProcAddrFuncPointer() { return _get_instance_proc_addr; }
+ PFN_xrCreateApiLayerInstance GetCreateApiLayerInstanceFuncPointer() { return _create_api_layer_instance; }
+
+ std::string LayerName() { return _layer_name; }
+
+ // Generated methods
+ bool SupportsExtension(const std::string& extension_name) const;
+
+ private:
+ std::string _layer_name;
+ LoaderPlatformLibraryHandle _layer_library;
+ PFN_xrGetInstanceProcAddr _get_instance_proc_addr;
+ PFN_xrCreateApiLayerInstance _create_api_layer_instance;
+ std::vector<std::string> _supported_extensions;
+};
diff --git a/thirdparty/openxr/src/loader/exception_handling.hpp b/thirdparty/openxr/src/loader/exception_handling.hpp
new file mode 100644
index 0000000000..428dd00279
--- /dev/null
+++ b/thirdparty/openxr/src/loader/exception_handling.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2019-2022, The Khronos Group Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+// Provides protection for C ABI functions if standard library functions may throw.
+
+#pragma once
+
+#ifdef OPENXR_HAVE_COMMON_CONFIG
+#include "common_config.h"
+#endif // OPENXR_HAVE_COMMON_CONFIG
+
+#ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING
+
+#define XRLOADER_ABI_TRY
+#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM
+#define XRLOADER_ABI_CATCH_FALLBACK
+
+#else
+
+#include <stdexcept>
+#define XRLOADER_ABI_TRY try
+#define XRLOADER_ABI_CATCH_BAD_ALLOC_OOM \
+ catch (const std::bad_alloc&) { \
+ LoaderLogger::LogErrorMessage("", "failed allocating memory"); \
+ return XR_ERROR_OUT_OF_MEMORY; \
+ }
+#define XRLOADER_ABI_CATCH_FALLBACK \
+ catch (const std::exception& e) { \
+ LoaderLogger::LogErrorMessage("", "Unknown failure: " + std::string(e.what())); \
+ return XR_ERROR_RUNTIME_FAILURE; \
+ } \
+ catch (...) { \
+ LoaderLogger::LogErrorMessage("", "Unknown failure"); \
+ return XR_ERROR_RUNTIME_FAILURE; \
+ }
+
+#endif
diff --git a/thirdparty/openxr/src/loader/loader_core.cpp b/thirdparty/openxr/src/loader/loader_core.cpp
new file mode 100644
index 0000000000..375f1c93ba
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_core.cpp
@@ -0,0 +1,847 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
+//
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+
+#include "api_layer_interface.hpp"
+#include "exception_handling.hpp"
+#include "hex_and_handles.h"
+#include "loader_instance.hpp"
+#include "loader_logger_recorders.hpp"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+#include "xr_generated_loader.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+// Global loader lock to:
+// 1. Ensure ActiveLoaderInstance get and set operations are done atomically.
+// 2. Ensure RuntimeInterface isn't used to unload the runtime while the runtime is in use.
+std::mutex &GetGlobalLoaderMutex() {
+ static std::mutex loader_mutex;
+ return loader_mutex;
+}
+
+// Prototypes for the debug utils calls used internally.
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineCreateDebugUtilsMessengerEXT(
+ XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo, XrDebugUtilsMessengerEXT *messenger);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger);
+
+// Terminal functions needed by xrCreateInstance.
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance, const char *, PFN_xrVoidFunction *);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *, XrInstance *);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *,
+ const struct XrApiLayerCreateInfo *, XrInstance *);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance, const XrDebugUtilsObjectNameInfoEXT *);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance,
+ const XrDebugUtilsMessengerCreateInfoEXT *,
+ XrDebugUtilsMessengerEXT *);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT);
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
+ XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData);
+
+// Utility template function meant to validate if a fixed size string contains
+// a null-terminator.
+template <size_t max_length>
+inline bool IsMissingNullTerminator(const char (&str)[max_length]) {
+ for (size_t index = 0; index < max_length; ++index) {
+ if (str[index] == '\0') {
+ return false;
+ }
+ }
+ return true;
+}
+
+// ---- Core 1.0 manual loader trampoline functions
+#ifdef XR_KHR_LOADER_INIT_SUPPORT // platforms that support XR_KHR_loader_init.
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrInitializeLoaderKHR", "Entering loader trampoline");
+ return InitializeLoader(loaderInitInfo);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+#endif
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
+ uint32_t *propertyCountOutput,
+ XrApiLayerProperties *properties) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrEnumerateApiLayerProperties", "Entering loader trampoline");
+
+ // Make sure only one thread is attempting to read the JSON files at a time.
+ std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
+
+ XrResult result = ApiLayerInterface::GetApiLayerProperties("xrEnumerateApiLayerProperties", propertyCapacityInput,
+ propertyCountOutput, properties);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage("xrEnumerateApiLayerProperties", "Failed ApiLayerInterface::GetApiLayerProperties");
+ }
+
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL
+LoaderXrEnumerateInstanceExtensionProperties(const char *layerName, uint32_t propertyCapacityInput, uint32_t *propertyCountOutput,
+ XrExtensionProperties *properties) XRLOADER_ABI_TRY {
+ bool just_layer_properties = false;
+ LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Entering loader trampoline");
+
+ // "Independent of elementCapacityInput or elements parameters, elementCountOutput must be a valid pointer,
+ // and the function sets elementCountOutput." - 2.11
+ if (nullptr == propertyCountOutput) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ if (nullptr != layerName && 0 != strlen(layerName)) {
+ // Application is only interested in layer's properties, not all of them.
+ just_layer_properties = true;
+ }
+
+ std::vector<XrExtensionProperties> extension_properties = {};
+ XrResult result;
+
+ {
+ // Make sure the runtime isn't unloaded while this call is in progress.
+ std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
+
+ // Get the layer extension properties
+ result = ApiLayerInterface::GetInstanceExtensionProperties("xrEnumerateInstanceExtensionProperties", layerName,
+ extension_properties);
+ if (XR_SUCCEEDED(result) && !just_layer_properties) {
+ // If not specific to a layer, get the runtime extension properties
+ result = RuntimeInterface::LoadRuntime("xrEnumerateInstanceExtensionProperties");
+ if (XR_SUCCEEDED(result)) {
+ RuntimeInterface::GetRuntime().GetInstanceExtensionProperties(extension_properties);
+ } else {
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties",
+ "Failed to find default runtime with RuntimeInterface::LoadRuntime()");
+ }
+ }
+ }
+
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage("xrEnumerateInstanceExtensionProperties", "Failed querying extension properties");
+ return result;
+ }
+
+ // If this is not in reference to a specific layer, then add the loader-specific extension properties as well.
+ // These are extensions that the loader directly supports.
+ if (!just_layer_properties) {
+ for (const XrExtensionProperties &loader_prop : LoaderInstance::LoaderSpecificExtensions()) {
+ bool found_prop = false;
+ for (XrExtensionProperties &existing_prop : extension_properties) {
+ if (0 == strcmp(existing_prop.extensionName, loader_prop.extensionName)) {
+ found_prop = true;
+ // Use the loader version if it is newer
+ if (existing_prop.extensionVersion < loader_prop.extensionVersion) {
+ existing_prop.extensionVersion = loader_prop.extensionVersion;
+ }
+ break;
+ }
+ }
+ // Only add extensions not supported by the loader
+ if (!found_prop) {
+ extension_properties.push_back(loader_prop);
+ }
+ }
+ }
+
+ auto num_extension_properties = static_cast<uint32_t>(extension_properties.size());
+ if (propertyCapacityInput == 0) {
+ *propertyCountOutput = num_extension_properties;
+ } else if (nullptr != properties) {
+ if (propertyCapacityInput < num_extension_properties) {
+ *propertyCountOutput = num_extension_properties;
+ LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-propertyCountOutput-parameter",
+ "xrEnumerateInstanceExtensionProperties", "insufficient space in array");
+ return XR_ERROR_SIZE_INSUFFICIENT;
+ }
+
+ uint32_t num_to_copy = num_extension_properties;
+ // Determine how many extension properties we can copy over
+ if (propertyCapacityInput < num_to_copy) {
+ num_to_copy = propertyCapacityInput;
+ }
+ bool properties_valid = true;
+ for (uint32_t prop = 0; prop < propertyCapacityInput && prop < extension_properties.size(); ++prop) {
+ if (XR_TYPE_EXTENSION_PROPERTIES != properties[prop].type) {
+ properties_valid = false;
+ LoaderLogger::LogValidationErrorMessage("VUID-XrExtensionProperties-type-type",
+ "xrEnumerateInstanceExtensionProperties", "unknown type in properties");
+ }
+ if (properties_valid) {
+ properties[prop] = extension_properties[prop];
+ }
+ }
+ if (!properties_valid) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrEnumerateInstanceExtensionProperties-properties-parameter",
+ "xrEnumerateInstanceExtensionProperties", "invalid properties");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (nullptr != propertyCountOutput) {
+ *propertyCountOutput = num_to_copy;
+ }
+ } else {
+ // incoming_count is not 0 BUT the properties is NULL
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ LoaderLogger::LogVerboseMessage("xrEnumerateInstanceExtensionProperties", "Completed loader trampoline");
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrCreateInstance(const XrInstanceCreateInfo *info,
+ XrInstance *instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader trampoline");
+ if (nullptr == info) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance", "must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // If application requested OpenXR API version is higher than the loader version, then we need to throw
+ // an error.
+ uint16_t app_major = XR_VERSION_MAJOR(info->applicationInfo.apiVersion); // NOLINT
+ uint16_t app_minor = XR_VERSION_MINOR(info->applicationInfo.apiVersion); // NOLINT
+ uint16_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION); // NOLINT
+ uint16_t loader_minor = XR_VERSION_MINOR(XR_CURRENT_API_VERSION); // NOLINT
+ if (app_major > loader_major || (app_major == loader_major && app_minor > loader_minor)) {
+ std::ostringstream oss;
+ oss << "xrCreateInstance called with invalid API version " << app_major << "." << app_minor
+ << ". Max supported version is " << loader_major << "." << loader_minor;
+ LoaderLogger::LogErrorMessage("xrCreateInstance", oss.str());
+ return XR_ERROR_API_VERSION_UNSUPPORTED;
+ }
+
+ if (nullptr == instance) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-instance-parameter", "xrCreateInstance", "must be non-NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ // Make sure the ActiveLoaderInstance::IsAvailable check is done atomically with RuntimeInterface::LoadRuntime.
+ std::unique_lock<std::mutex> instance_lock(GetGlobalLoaderMutex());
+
+ // Check if there is already an XrInstance that is alive. If so, another instance cannot be created.
+ // The loader does not support multiple simultaneous instances because the loader is intended to be
+ // usable by apps using future OpenXR APIs (through xrGetInstanceProcAddr). Because the loader would
+ // not be aware of new handle types, it would not be able to look up the appropriate dispatch table
+ // in some cases.
+ if (ActiveLoaderInstance::IsAvailable()) { // If there is an XrInstance already alive.
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "Loader does not support simultaneous XrInstances");
+ return XR_ERROR_LIMIT_REACHED;
+ }
+
+ std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces;
+ XrResult result;
+
+ // Make sure only one thread is attempting to read the JSON files and use the instance.
+ {
+ // Load the available runtime
+ result = RuntimeInterface::LoadRuntime("xrCreateInstance");
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading runtime information");
+ } else {
+ // Load the appropriate layers
+ result = ApiLayerInterface::LoadApiLayers("xrCreateInstance", info->enabledApiLayerCount, info->enabledApiLayerNames,
+ api_layer_interfaces);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "Failed loading layer information");
+ }
+ }
+ }
+
+ // Create the loader instance (only send down first runtime interface)
+ LoaderInstance *loader_instance = nullptr;
+ if (XR_SUCCEEDED(result)) {
+ std::unique_ptr<LoaderInstance> owned_loader_instance;
+ result = LoaderInstance::CreateInstance(LoaderXrTermGetInstanceProcAddr, LoaderXrTermCreateInstance,
+ LoaderXrTermCreateApiLayerInstance, std::move(api_layer_interfaces), info,
+ &owned_loader_instance);
+ if (XR_SUCCEEDED(result)) {
+ loader_instance = owned_loader_instance.get();
+ result = ActiveLoaderInstance::Set(std::move(owned_loader_instance), "xrCreateInstance");
+ }
+ }
+
+ if (XR_SUCCEEDED(result)) {
+ // Create a debug utils messenger if the create structure is in the "next" chain
+ const auto *next_header = reinterpret_cast<const XrBaseInStructure *>(info->next);
+ const XrDebugUtilsMessengerCreateInfoEXT *dbg_utils_create_info = nullptr;
+ while (next_header != nullptr) {
+ if (next_header->type == XR_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
+ LoaderLogger::LogInfoMessage("xrCreateInstance", "Found XrDebugUtilsMessengerCreateInfoEXT in \'next\' chain.");
+ dbg_utils_create_info = reinterpret_cast<const XrDebugUtilsMessengerCreateInfoEXT *>(next_header);
+ XrDebugUtilsMessengerEXT messenger;
+ result = LoaderTrampolineCreateDebugUtilsMessengerEXT(loader_instance->GetInstanceHandle(), dbg_utils_create_info,
+ &messenger);
+ if (XR_FAILED(result)) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ loader_instance->SetDefaultDebugUtilsMessenger(messenger);
+ break;
+ }
+ next_header = reinterpret_cast<const XrBaseInStructure *>(next_header->next);
+ }
+ }
+
+ if (XR_FAILED(result)) {
+ // Ensure the global loader instance and runtime are destroyed if something went wrong.
+ ActiveLoaderInstance::Remove();
+ RuntimeInterface::UnloadRuntime("xrCreateInstance");
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "xrCreateInstance failed");
+ } else {
+ *instance = loader_instance->GetInstanceHandle();
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader trampoline");
+ }
+
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader trampoline");
+ // Runtimes may detect XR_NULL_HANDLE provided as a required handle parameter and return XR_ERROR_HANDLE_INVALID. - 2.9
+ if (XR_NULL_HANDLE == instance) {
+ LoaderLogger::LogErrorMessage("xrDestroyInstance", "Instance handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ // Make sure the runtime isn't unloaded while it is being used by xrEnumerateInstanceExtensionProperties.
+ std::unique_lock<std::mutex> loader_lock(GetGlobalLoaderMutex());
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyInstance");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+
+ // If we allocated a default debug utils messenger, free it
+ XrDebugUtilsMessengerEXT messenger = loader_instance->DefaultDebugUtilsMessenger();
+ if (messenger != XR_NULL_HANDLE) {
+ LoaderTrampolineDestroyDebugUtilsMessengerEXT(messenger);
+ }
+
+ // Now destroy the instance
+ if (XR_FAILED(dispatch_table->DestroyInstance(instance))) {
+ LoaderLogger::LogErrorMessage("xrDestroyInstance", "Unknown error occurred calling down chain");
+ }
+
+ // Get rid of the loader instance. This will make it possible to create another instance in the future.
+ ActiveLoaderInstance::Remove();
+
+ // Lock the instance create/destroy mutex
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader trampoline");
+
+ // Finally, unload the runtime if necessary
+ RuntimeInterface::UnloadRuntime("xrDestroyInstance");
+
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Core 1.0 manual loader terminator functions
+
+// Validate that the applicationInfo structure in the XrInstanceCreateInfo is valid.
+static XrResult ValidateApplicationInfo(const XrApplicationInfo &info) {
+ if (IsMissingNullTerminator<XR_MAX_APPLICATION_NAME_SIZE>(info.applicationName)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-applicationName-parameter", "xrCreateInstance",
+ "application name missing NULL terminator.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ if (IsMissingNullTerminator<XR_MAX_ENGINE_NAME_SIZE>(info.engineName)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrApplicationInfo-engineName-parameter", "xrCreateInstance",
+ "engine name missing NULL terminator.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ if (strlen(info.applicationName) == 0) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance",
+ "VUID-XrApplicationInfo-engineName-parameter: application name can not be empty.");
+ return XR_ERROR_NAME_INVALID;
+ }
+ return XR_SUCCESS;
+}
+
+// Validate that the XrInstanceCreateInfo is valid
+static XrResult ValidateInstanceCreateInfo(const XrInstanceCreateInfo *info) {
+ // Should have a valid 'type'
+ if (XR_TYPE_INSTANCE_CREATE_INFO != info->type) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-type-type", "xrCreateInstance",
+ "expected XR_TYPE_INSTANCE_CREATE_INFO.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // Flags must be 0
+ if (0 != info->createFlags) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-createFlags-zerobitmask", "xrCreateInstance",
+ "flags must be 0.");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ // ApplicationInfo struct must be valid
+ XrResult result = ValidateApplicationInfo(info->applicationInfo);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-applicationInfo-parameter", "xrCreateInstance",
+ "info->applicationInfo is not valid.");
+ return result;
+ }
+ // VUID-XrInstanceCreateInfo-enabledApiLayerNames-parameter already tested in LoadApiLayers()
+ if ((info->enabledExtensionCount != 0u) && nullptr == info->enabledExtensionNames) {
+ LoaderLogger::LogValidationErrorMessage("VUID-XrInstanceCreateInfo-enabledExtensionNames-parameter", "xrCreateInstance",
+ "enabledExtensionCount is non-0 but array is NULL");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ return XR_SUCCESS;
+}
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateInstance(const XrInstanceCreateInfo *createInfo,
+ XrInstance *instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering loader terminator");
+ XrResult result = ValidateInstanceCreateInfo(createInfo);
+ if (XR_FAILED(result)) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateInstance-info-parameter", "xrCreateInstance",
+ "something wrong with XrInstanceCreateInfo contents");
+ return result;
+ }
+ result = RuntimeInterface::GetRuntime().CreateInstance(createInfo, instance);
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateApiLayerInstance(const XrInstanceCreateInfo *info,
+ const struct XrApiLayerCreateInfo * /*apiLayerInfo*/,
+ XrInstance *instance) {
+ return LoaderXrTermCreateInstance(info, instance);
+}
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyInstance(XrInstance instance) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Entering loader terminator");
+ LoaderLogger::GetInstance().RemoveLogRecordersForXrInstance(instance);
+ XrResult result = RuntimeInterface::GetRuntime().DestroyInstance(instance);
+ LoaderLogger::LogVerboseMessage("xrDestroyInstance", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermGetInstanceProcAddr(XrInstance instance, const char *name,
+ PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
+ // A few instance commands need to go through a loader terminator.
+ // Otherwise, go directly to the runtime version of the command if it exists.
+ // But first set the function pointer to NULL so that the fall-through below actually works.
+ *function = nullptr;
+
+ // NOTE: ActiveLoaderInstance cannot be used in this function because it is called before an instance is made active.
+
+ if (0 == strcmp(name, "xrGetInstanceProcAddr")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermGetInstanceProcAddr);
+ } else if (0 == strcmp(name, "xrCreateInstance")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateInstance);
+ } else if (0 == strcmp(name, "xrDestroyInstance")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyInstance);
+ } else if (0 == strcmp(name, "xrSetDebugUtilsObjectNameEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSetDebugUtilsObjectNameEXT);
+ } else if (0 == strcmp(name, "xrCreateDebugUtilsMessengerEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateDebugUtilsMessengerEXT);
+ } else if (0 == strcmp(name, "xrDestroyDebugUtilsMessengerEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermDestroyDebugUtilsMessengerEXT);
+ } else if (0 == strcmp(name, "xrSubmitDebugUtilsMessageEXT")) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermSubmitDebugUtilsMessageEXT);
+ } else if (0 == strcmp(name, "xrCreateApiLayerInstance")) {
+ // Special layer version of xrCreateInstance terminator. If we get called this by a layer,
+ // we simply re-direct the information back into the standard xrCreateInstance terminator.
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrTermCreateApiLayerInstance);
+ }
+
+ if (nullptr != *function) {
+ return XR_SUCCESS;
+ }
+
+ return RuntimeInterface::GetInstanceProcAddr(instance, name, function);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Extension manual loader trampoline functions
+
+static XRAPI_ATTR XrResult XRAPI_CALL
+LoaderTrampolineCreateDebugUtilsMessengerEXT(XrInstance instance, const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
+ XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader trampoline");
+
+ if (instance == XR_NULL_HANDLE) {
+ LoaderLogger::LogErrorMessage("xrCreateDebugUtilsMessengerEXT", "Instance handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateDebugUtilsMessengerEXT");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+
+ result = loader_instance->DispatchTable()->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader trampoline");
+ return result;
+}
+XRLOADER_ABI_CATCH_BAD_ALLOC_OOM XRLOADER_ABI_CATCH_FALLBACK
+
+ static XRAPI_ATTR XrResult XRAPI_CALL
+ LoaderTrampolineDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
+ // TODO: get instance from messenger in loader
+ // Also, is the loader really doing all this every call?
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader trampoline");
+
+ if (messenger == XR_NULL_HANDLE) {
+ LoaderLogger::LogErrorMessage("xrDestroyDebugUtilsMessengerEXT", "Messenger handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyDebugUtilsMessengerEXT");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+
+ result = loader_instance->DispatchTable()->DestroyDebugUtilsMessengerEXT(messenger);
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader trampoline");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL
+LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
+ if (session == XR_NULL_HANDLE) {
+ LoaderLogger::LogErrorMessage("xrSessionBeginDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ if (nullptr == labelInfo) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionBeginDebugUtilsLabelRegionEXT-labelInfo-parameter",
+ "xrSessionBeginDebugUtilsLabelRegionEXT", "labelInfo must be non-NULL",
+ {XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionBeginDebugUtilsLabelRegionEXT");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+ LoaderLogger::GetInstance().BeginLabelRegion(session, labelInfo);
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionBeginDebugUtilsLabelRegionEXT) {
+ return dispatch_table->SessionBeginDebugUtilsLabelRegionEXT(session, labelInfo);
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT(XrSession session) XRLOADER_ABI_TRY {
+ if (session == XR_NULL_HANDLE) {
+ LoaderLogger::LogErrorMessage("xrSessionEndDebugUtilsLabelRegionEXT", "Session handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionEndDebugUtilsLabelRegionEXT");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+
+ LoaderLogger::GetInstance().EndLabelRegion(session);
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionEndDebugUtilsLabelRegionEXT) {
+ return dispatch_table->SessionEndDebugUtilsLabelRegionEXT(session);
+ }
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+static XRAPI_ATTR XrResult XRAPI_CALL
+LoaderTrampolineSessionInsertDebugUtilsLabelEXT(XrSession session, const XrDebugUtilsLabelEXT *labelInfo) XRLOADER_ABI_TRY {
+ if (session == XR_NULL_HANDLE) {
+ LoaderLogger::LogErrorMessage("xrSessionInsertDebugUtilsLabelEXT", "Session handle is XR_NULL_HANDLE.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSessionInsertDebugUtilsLabelEXT");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+
+ if (nullptr == labelInfo) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrSessionInsertDebugUtilsLabelEXT-labelInfo-parameter",
+ "xrSessionInsertDebugUtilsLabelEXT", "labelInfo must be non-NULL",
+ {XrSdkLogObjectInfo{session, XR_OBJECT_TYPE_SESSION}});
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ LoaderLogger::GetInstance().InsertLabel(session, labelInfo);
+
+ const std::unique_ptr<XrGeneratedDispatchTable> &dispatch_table = loader_instance->DispatchTable();
+ if (nullptr != dispatch_table->SessionInsertDebugUtilsLabelEXT) {
+ return dispatch_table->SessionInsertDebugUtilsLabelEXT(session, labelInfo);
+ }
+
+ return XR_SUCCESS;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
+static XRAPI_ATTR XrResult XRAPI_CALL
+LoaderTrampolineSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSetDebugUtilsObjectNameEXT");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->SetDebugUtilsObjectNameEXT(instance, nameInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// No-op trampoline needed for xrGetInstanceProcAddr. Work done in terminator.
+static XRAPI_ATTR XrResult XRAPI_CALL LoaderTrampolineSubmitDebugUtilsMessageEXT(
+ XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
+ LoaderInstance *loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSubmitDebugUtilsMessageEXT");
+ if (XR_SUCCEEDED(result)) {
+ result =
+ loader_instance->DispatchTable()->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// ---- Extension manual loader terminator functions
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermCreateDebugUtilsMessengerEXT(XrInstance instance,
+ const XrDebugUtilsMessengerCreateInfoEXT *createInfo,
+ XrDebugUtilsMessengerEXT *messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Entering loader terminator");
+ if (nullptr == messenger) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrCreateDebugUtilsMessengerEXT-messenger-parameter",
+ "xrCreateDebugUtilsMessengerEXT", "invalid messenger pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ // This extension is supported entirely by the loader which means the runtime may or may not support it.
+ if (nullptr != dispatch_table->CreateDebugUtilsMessengerEXT) {
+ result = dispatch_table->CreateDebugUtilsMessengerEXT(instance, createInfo, messenger);
+ } else {
+ // Just allocate a character so we have a unique value
+ char *temp_mess_ptr = new char;
+ *messenger = reinterpret_cast<XrDebugUtilsMessengerEXT>(temp_mess_ptr);
+ }
+ if (XR_SUCCEEDED(result)) {
+ LoaderLogger::GetInstance().AddLogRecorderForXrInstance(instance, MakeDebugUtilsLoaderLogRecorder(createInfo, *messenger));
+ RuntimeInterface::GetRuntime().TrackDebugMessenger(instance, *messenger);
+ }
+ LoaderLogger::LogVerboseMessage("xrCreateDebugUtilsMessengerEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermDestroyDebugUtilsMessengerEXT(XrDebugUtilsMessengerEXT messenger) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDebugUtilsMessengerDispatchTable(messenger);
+ XrResult result = XR_SUCCESS;
+ LoaderLogger::GetInstance().RemoveLogRecorder(MakeHandleGeneric(messenger));
+ RuntimeInterface::GetRuntime().ForgetDebugMessenger(messenger);
+ // This extension is supported entirely by the loader which means the runtime may or may not support it.
+ if (nullptr != dispatch_table->DestroyDebugUtilsMessengerEXT) {
+ result = dispatch_table->DestroyDebugUtilsMessengerEXT(messenger);
+ } else {
+ // Delete the character we would've created
+ delete (reinterpret_cast<char *>(MakeHandleGeneric(messenger)));
+ }
+ LoaderLogger::LogVerboseMessage("xrDestroyDebugUtilsMessengerEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrTermSubmitDebugUtilsMessageEXT(
+ XrInstance instance, XrDebugUtilsMessageSeverityFlagsEXT messageSeverity, XrDebugUtilsMessageTypeFlagsEXT messageTypes,
+ const XrDebugUtilsMessengerCallbackDataEXT *callbackData) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ if (nullptr != dispatch_table->SubmitDebugUtilsMessageEXT) {
+ result = dispatch_table->SubmitDebugUtilsMessageEXT(instance, messageSeverity, messageTypes, callbackData);
+ } else {
+ // Only log the message from the loader if the runtime doesn't support this extension. If we did,
+ // then the user would receive multiple instances of the same message.
+ LoaderLogger::GetInstance().LogDebugUtilsMessage(messageSeverity, messageTypes, callbackData);
+ }
+ LoaderLogger::LogVerboseMessage("xrSubmitDebugUtilsMessageEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL
+LoaderXrTermSetDebugUtilsObjectNameEXT(XrInstance instance, const XrDebugUtilsObjectNameInfoEXT *nameInfo) XRLOADER_ABI_TRY {
+ LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Entering loader terminator");
+ const XrGeneratedDispatchTable *dispatch_table = RuntimeInterface::GetDispatchTable(instance);
+ XrResult result = XR_SUCCESS;
+ if (nullptr != dispatch_table->SetDebugUtilsObjectNameEXT) {
+ result = dispatch_table->SetDebugUtilsObjectNameEXT(instance, nameInfo);
+ }
+ LoaderLogger::GetInstance().AddObjectName(nameInfo->objectHandle, nameInfo->objectType, nameInfo->objectName);
+ LoaderLogger::LogVerboseMessage("xrSetDebugUtilsObjectNameEXT", "Completed loader terminator");
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+XRAPI_ATTR XrResult XRAPI_CALL LoaderXrGetInstanceProcAddr(XrInstance instance, const char *name,
+ PFN_xrVoidFunction *function) XRLOADER_ABI_TRY {
+ // Initialize the function to nullptr in case it does not get caught in a known case
+ *function = nullptr;
+
+ if (nullptr == function) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
+ "Invalid Function pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ if (nullptr == name) {
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-function-parameter", "xrGetInstanceProcAddr",
+ "Invalid Name pointer");
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+
+ LoaderInstance *loader_instance = nullptr;
+ if (instance == XR_NULL_HANDLE) {
+ // Null instance is allowed for a few specific API entry points, otherwise return error
+ if (strcmp(name, "xrCreateInstance") != 0 && strcmp(name, "xrEnumerateApiLayerProperties") != 0 &&
+ strcmp(name, "xrEnumerateInstanceExtensionProperties") != 0 && strcmp(name, "xrInitializeLoaderKHR") != 0) {
+ // TODO why is xrGetInstanceProcAddr not listed in here?
+ std::string error_str = "XR_NULL_HANDLE for instance but query for ";
+ error_str += name;
+ error_str += " requires a valid instance";
+ LoaderLogger::LogValidationErrorMessage("VUID-xrGetInstanceProcAddr-instance-parameter", "xrGetInstanceProcAddr",
+ error_str);
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ } else {
+ // non null instance passed in, it should be our current instance
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInstanceProcAddr");
+ if (XR_FAILED(result)) {
+ return result;
+ }
+ if (loader_instance->GetInstanceHandle() != instance) {
+ return XR_ERROR_HANDLE_INVALID;
+ }
+ }
+
+ // These functions must always go through the loader's implementation (trampoline).
+ if (strcmp(name, "xrGetInstanceProcAddr") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrGetInstanceProcAddr);
+ return XR_SUCCESS;
+ } else if (strcmp(name, "xrInitializeLoaderKHR") == 0) {
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrInitializeLoaderKHR);
+ return XR_SUCCESS;
+#else
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+#endif
+ } else if (strcmp(name, "xrEnumerateApiLayerProperties") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateApiLayerProperties);
+ return XR_SUCCESS;
+ } else if (strcmp(name, "xrEnumerateInstanceExtensionProperties") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrEnumerateInstanceExtensionProperties);
+ return XR_SUCCESS;
+ } else if (strcmp(name, "xrCreateInstance") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrCreateInstance);
+ return XR_SUCCESS;
+ } else if (strcmp(name, "xrDestroyInstance") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderXrDestroyInstance);
+ return XR_SUCCESS;
+ }
+
+ // XR_EXT_debug_utils is built into the loader and handled partly through the xrGetInstanceProcAddress terminator,
+ // but the check to see if the extension is enabled must be done here where ActiveLoaderInstance is safe to use.
+ if (*function == nullptr) {
+ if (strcmp(name, "xrCreateDebugUtilsMessengerEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineCreateDebugUtilsMessengerEXT);
+ } else if (strcmp(name, "xrDestroyDebugUtilsMessengerEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineDestroyDebugUtilsMessengerEXT);
+ } else if (strcmp(name, "xrSessionBeginDebugUtilsLabelRegionEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionBeginDebugUtilsLabelRegionEXT);
+ } else if (strcmp(name, "xrSessionEndDebugUtilsLabelRegionEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionEndDebugUtilsLabelRegionEXT);
+ } else if (strcmp(name, "xrSessionInsertDebugUtilsLabelEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSessionInsertDebugUtilsLabelEXT);
+ } else if (strcmp(name, "xrSetDebugUtilsObjectNameEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSetDebugUtilsObjectNameEXT);
+ } else if (strcmp(name, "xrSubmitDebugUtilsMessageEXT") == 0) {
+ *function = reinterpret_cast<PFN_xrVoidFunction>(LoaderTrampolineSubmitDebugUtilsMessageEXT);
+ }
+
+ if (*function != nullptr && !loader_instance->ExtensionIsEnabled("XR_EXT_debug_utils")) {
+ // The function matches one of the XR_EXT_debug_utils functions but the extension is not enabled.
+ *function = nullptr;
+ return XR_ERROR_FUNCTION_UNSUPPORTED;
+ }
+ }
+
+ if (*function != nullptr) {
+ // The loader has a trampoline or implementation of this function.
+ return XR_SUCCESS;
+ }
+
+ // If the function is not supported by the loader, call down to the next layer.
+ return loader_instance->GetInstanceProcAddr(name, function);
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+// Exported loader functions
+//
+// The application might override these by exporting the same symbols and so we can't use these
+// symbols anywhere in the loader code, and instead the internal non exported functions that these
+// stubs call should be used internally.
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateApiLayerProperties(uint32_t propertyCapacityInput,
+ uint32_t *propertyCountOutput,
+ XrApiLayerProperties *properties) {
+ return LoaderXrEnumerateApiLayerProperties(propertyCapacityInput, propertyCountOutput, properties);
+}
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateInstanceExtensionProperties(const char *layerName,
+ uint32_t propertyCapacityInput,
+ uint32_t *propertyCountOutput,
+ XrExtensionProperties *properties) {
+ return LoaderXrEnumerateInstanceExtensionProperties(layerName, propertyCapacityInput, propertyCountOutput, properties);
+}
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateInstance(const XrInstanceCreateInfo *info, XrInstance *instance) {
+ return LoaderXrCreateInstance(info, instance);
+}
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyInstance(XrInstance instance) { return LoaderXrDestroyInstance(instance); }
+
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProcAddr(XrInstance instance, const char *name,
+ PFN_xrVoidFunction *function) {
+ return LoaderXrGetInstanceProcAddr(instance, name, function);
+}
+
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrInitializeLoaderKHR(const XrLoaderInitInfoBaseHeaderKHR *loaderInitInfo) {
+ return LoaderXrInitializeLoaderKHR(loaderInitInfo);
+}
+#endif
diff --git a/thirdparty/openxr/src/loader/loader_instance.cpp b/thirdparty/openxr/src/loader/loader_instance.cpp
new file mode 100644
index 0000000000..b24c8de53b
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_instance.cpp
@@ -0,0 +1,303 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+
+#include "loader_instance.hpp"
+
+#include "api_layer_interface.hpp"
+#include "hex_and_handles.h"
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+#include "xr_generated_loader.hpp"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace {
+std::unique_ptr<LoaderInstance>& GetSetCurrentLoaderInstance() {
+ static std::unique_ptr<LoaderInstance> current_loader_instance;
+ return current_loader_instance;
+}
+} // namespace
+
+namespace ActiveLoaderInstance {
+XrResult Set(std::unique_ptr<LoaderInstance> loader_instance, const char* log_function_name) {
+ if (GetSetCurrentLoaderInstance() != nullptr) {
+ LoaderLogger::LogErrorMessage(log_function_name, "Active XrInstance handle already exists");
+ return XR_ERROR_LIMIT_REACHED;
+ }
+
+ GetSetCurrentLoaderInstance() = std::move(loader_instance);
+ return XR_SUCCESS;
+}
+
+XrResult Get(LoaderInstance** loader_instance, const char* log_function_name) {
+ *loader_instance = GetSetCurrentLoaderInstance().get();
+ if (*loader_instance == nullptr) {
+ LoaderLogger::LogErrorMessage(log_function_name, "No active XrInstance handle.");
+ return XR_ERROR_HANDLE_INVALID;
+ }
+
+ return XR_SUCCESS;
+}
+
+bool IsAvailable() { return GetSetCurrentLoaderInstance() != nullptr; }
+
+void Remove() { GetSetCurrentLoaderInstance().release(); }
+} // namespace ActiveLoaderInstance
+
+// Extensions that are supported by the loader, but may not be supported
+// the the runtime.
+const std::array<XrExtensionProperties, 1>& LoaderInstance::LoaderSpecificExtensions() {
+ static const std::array<XrExtensionProperties, 1> extensions = {XrExtensionProperties{
+ XR_TYPE_EXTENSION_PROPERTIES, nullptr, XR_EXT_DEBUG_UTILS_EXTENSION_NAME, XR_EXT_debug_utils_SPEC_VERSION}};
+ return extensions;
+}
+
+namespace {
+class InstanceCreateInfoManager {
+ public:
+ explicit InstanceCreateInfoManager(const XrInstanceCreateInfo* info) : original_create_info(info), modified_create_info(*info) {
+ Reset();
+ }
+
+ // Reset the "modified" state to match the original state.
+ void Reset() {
+ enabled_extensions_cstr.clear();
+ enabled_extensions_cstr.reserve(original_create_info->enabledExtensionCount);
+
+ for (uint32_t i = 0; i < original_create_info->enabledExtensionCount; ++i) {
+ enabled_extensions_cstr.push_back(original_create_info->enabledExtensionNames[i]);
+ }
+ Update();
+ }
+
+ // Remove extensions named in the parameter and return a pointer to the current state.
+ const XrInstanceCreateInfo* FilterOutExtensions(const std::vector<const char*>& extensions_to_skip) {
+ if (enabled_extensions_cstr.empty()) {
+ return Get();
+ }
+ if (extensions_to_skip.empty()) {
+ return Get();
+ }
+ for (auto& ext : extensions_to_skip) {
+ FilterOutExtension(ext);
+ }
+ return Update();
+ }
+ // Remove the extension named in the parameter and return a pointer to the current state.
+ const XrInstanceCreateInfo* FilterOutExtension(const char* extension_to_skip) {
+ if (enabled_extensions_cstr.empty()) {
+ return &modified_create_info;
+ }
+ auto b = enabled_extensions_cstr.begin();
+ auto e = enabled_extensions_cstr.end();
+ auto it = std::find_if(b, e, [&](const char* extension) { return strcmp(extension_to_skip, extension) == 0; });
+ if (it != e) {
+ // Just that one element goes away
+ enabled_extensions_cstr.erase(it);
+ }
+ return Update();
+ }
+
+ // Get the current modified XrInstanceCreateInfo
+ const XrInstanceCreateInfo* Get() const { return &modified_create_info; }
+
+ private:
+ const XrInstanceCreateInfo* Update() {
+ modified_create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions_cstr.size());
+ modified_create_info.enabledExtensionNames = enabled_extensions_cstr.empty() ? nullptr : enabled_extensions_cstr.data();
+ return &modified_create_info;
+ }
+ const XrInstanceCreateInfo* original_create_info;
+
+ XrInstanceCreateInfo modified_create_info;
+ std::vector<const char*> enabled_extensions_cstr;
+};
+} // namespace
+
+// Factory method
+XrResult LoaderInstance::CreateInstance(PFN_xrGetInstanceProcAddr get_instance_proc_addr_term,
+ PFN_xrCreateInstance create_instance_term,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance_term,
+ std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces,
+ const XrInstanceCreateInfo* info, std::unique_ptr<LoaderInstance>* loader_instance) {
+ LoaderLogger::LogVerboseMessage("xrCreateInstance", "Entering LoaderInstance::CreateInstance");
+
+ // Check the list of enabled extensions to make sure something supports them, and, if we do,
+ // add it to the list of enabled extensions
+ XrResult last_error = XR_SUCCESS;
+ for (uint32_t ext = 0; ext < info->enabledExtensionCount; ++ext) {
+ bool found = false;
+ // First check the runtime
+ if (RuntimeInterface::GetRuntime().SupportsExtension(info->enabledExtensionNames[ext])) {
+ found = true;
+ }
+ // Next check the loader
+ if (!found) {
+ for (auto& loader_extension : LoaderInstance::LoaderSpecificExtensions()) {
+ if (strcmp(loader_extension.extensionName, info->enabledExtensionNames[ext]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ }
+ // Finally, check the enabled layers
+ if (!found) {
+ for (auto& layer_interface : api_layer_interfaces) {
+ if (layer_interface->SupportsExtension(info->enabledExtensionNames[ext])) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ std::string msg = "LoaderInstance::CreateInstance, no support found for requested extension: ";
+ msg += info->enabledExtensionNames[ext];
+ LoaderLogger::LogErrorMessage("xrCreateInstance", msg);
+ last_error = XR_ERROR_EXTENSION_NOT_PRESENT;
+ break;
+ }
+ }
+
+ // Topmost means "closest to the application"
+ PFN_xrGetInstanceProcAddr topmost_gipa = get_instance_proc_addr_term;
+ XrInstance instance{XR_NULL_HANDLE};
+
+ if (XR_SUCCEEDED(last_error)) {
+ // Remove the loader-supported-extensions (debug utils), if it's in the list of enabled extensions but not supported by
+ // the runtime.
+ InstanceCreateInfoManager create_info_manager{info};
+ const XrInstanceCreateInfo* modified_create_info = info;
+ if (info->enabledExtensionCount > 0) {
+ std::vector<const char*> extensions_to_skip;
+ for (const auto& ext : LoaderInstance::LoaderSpecificExtensions()) {
+ if (!RuntimeInterface::GetRuntime().SupportsExtension(ext.extensionName)) {
+ extensions_to_skip.emplace_back(ext.extensionName);
+ }
+ }
+ modified_create_info = create_info_manager.FilterOutExtensions(extensions_to_skip);
+ }
+
+ // Only start the xrCreateApiLayerInstance stack if we have layers.
+ if (!api_layer_interfaces.empty()) {
+ // Initialize an array of ApiLayerNextInfo structs
+ std::unique_ptr<XrApiLayerNextInfo[]> next_info_list(new XrApiLayerNextInfo[api_layer_interfaces.size()]);
+ auto ni_index = static_cast<uint32_t>(api_layer_interfaces.size() - 1);
+ for (uint32_t i = 0; i <= ni_index; i++) {
+ next_info_list[i].structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_NEXT_INFO;
+ next_info_list[i].structVersion = XR_API_LAYER_NEXT_INFO_STRUCT_VERSION;
+ next_info_list[i].structSize = sizeof(XrApiLayerNextInfo);
+ }
+
+ // Go through all layers, and override the instance pointers with the layer version. However,
+ // go backwards through the layer list so we replace in reverse order so the layers can call their next function
+ // appropriately.
+ PFN_xrCreateApiLayerInstance topmost_cali_fp = create_api_layer_instance_term;
+ XrApiLayerNextInfo* topmost_nextinfo = nullptr;
+ for (auto layer_interface = api_layer_interfaces.rbegin(); layer_interface != api_layer_interfaces.rend();
+ ++layer_interface) {
+ // Collect current layer's function pointers
+ PFN_xrGetInstanceProcAddr cur_gipa_fp = (*layer_interface)->GetInstanceProcAddrFuncPointer();
+ PFN_xrCreateApiLayerInstance cur_cali_fp = (*layer_interface)->GetCreateApiLayerInstanceFuncPointer();
+
+ // Fill in layer info and link previous (lower) layer fxn pointers
+ strncpy(next_info_list[ni_index].layerName, (*layer_interface)->LayerName().c_str(),
+ XR_MAX_API_LAYER_NAME_SIZE - 1);
+ next_info_list[ni_index].layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
+ next_info_list[ni_index].next = topmost_nextinfo;
+ next_info_list[ni_index].nextGetInstanceProcAddr = topmost_gipa;
+ next_info_list[ni_index].nextCreateApiLayerInstance = topmost_cali_fp;
+
+ // Update saved pointers for next iteration
+ topmost_nextinfo = &next_info_list[ni_index];
+ topmost_gipa = cur_gipa_fp;
+ topmost_cali_fp = cur_cali_fp;
+ ni_index--;
+ }
+
+ // Populate the ApiLayerCreateInfo struct and pass to topmost CreateApiLayerInstance()
+ XrApiLayerCreateInfo api_layer_ci = {};
+ api_layer_ci.structType = XR_LOADER_INTERFACE_STRUCT_API_LAYER_CREATE_INFO;
+ api_layer_ci.structVersion = XR_API_LAYER_CREATE_INFO_STRUCT_VERSION;
+ api_layer_ci.structSize = sizeof(XrApiLayerCreateInfo);
+ api_layer_ci.loaderInstance = nullptr; // Not used.
+ api_layer_ci.settings_file_location[0] = '\0';
+ api_layer_ci.nextInfo = next_info_list.get();
+ //! @todo do we filter our create info extension list here?
+ //! Think that actually each layer might need to filter...
+ last_error = topmost_cali_fp(modified_create_info, &api_layer_ci, &instance);
+
+ } else {
+ // The loader's terminator is the topmost CreateInstance if there are no layers.
+ last_error = create_instance_term(modified_create_info, &instance);
+ }
+
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage("xrCreateInstance", "LoaderInstance::CreateInstance chained CreateInstance call failed");
+ }
+ }
+
+ if (XR_SUCCEEDED(last_error)) {
+ loader_instance->reset(new LoaderInstance(instance, info, topmost_gipa, std::move(api_layer_interfaces)));
+
+ std::ostringstream oss;
+ oss << "LoaderInstance::CreateInstance succeeded with ";
+ oss << (*loader_instance)->LayerInterfaces().size();
+ oss << " layers enabled and runtime interface - created instance = ";
+ oss << HandleToHexString((*loader_instance)->GetInstanceHandle());
+ LoaderLogger::LogInfoMessage("xrCreateInstance", oss.str());
+ }
+
+ return last_error;
+}
+
+XrResult LoaderInstance::GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function) {
+ return _topmost_gipa(_runtime_instance, name, function);
+}
+
+LoaderInstance::LoaderInstance(XrInstance instance, const XrInstanceCreateInfo* create_info, PFN_xrGetInstanceProcAddr topmost_gipa,
+ std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces)
+ : _runtime_instance(instance),
+ _topmost_gipa(topmost_gipa),
+ _api_layer_interfaces(std::move(api_layer_interfaces)),
+ _dispatch_table(new XrGeneratedDispatchTable{}) {
+ for (uint32_t ext = 0; ext < create_info->enabledExtensionCount; ++ext) {
+ _enabled_extensions.push_back(create_info->enabledExtensionNames[ext]);
+ }
+
+ GeneratedXrPopulateDispatchTable(_dispatch_table.get(), instance, topmost_gipa);
+}
+
+LoaderInstance::~LoaderInstance() {
+ std::ostringstream oss;
+ oss << "Destroying LoaderInstance = ";
+ oss << PointerToHexString(this);
+ LoaderLogger::LogInfoMessage("xrDestroyInstance", oss.str());
+}
+
+bool LoaderInstance::ExtensionIsEnabled(const std::string& extension) {
+ for (std::string& cur_enabled : _enabled_extensions) {
+ if (cur_enabled == extension) {
+ return true;
+ }
+ }
+ return false;
+}
diff --git a/thirdparty/openxr/src/loader/loader_instance.hpp b/thirdparty/openxr/src/loader/loader_instance.hpp
new file mode 100644
index 0000000000..1d43ed758d
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_instance.hpp
@@ -0,0 +1,77 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include "extra_algorithms.h"
+#include "loader_interfaces.h"
+
+#include <openxr/openxr.h>
+
+#include <array>
+#include <cmath>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+class ApiLayerInterface;
+struct XrGeneratedDispatchTable;
+class LoaderInstance;
+
+// Manage the single loader instance that is available.
+namespace ActiveLoaderInstance {
+// Set the active loader instance. This will fail if there is already an active loader instance.
+XrResult Set(std::unique_ptr<LoaderInstance> loader_instance, const char* log_function_name);
+
+// Returns true if there is an active loader instance.
+bool IsAvailable();
+
+// Get the active LoaderInstance.
+XrResult Get(LoaderInstance** loader_instance, const char* log_function_name);
+
+// Destroy the currently active LoaderInstance if there is one. This will make the loader able to create a new XrInstance if needed.
+void Remove();
+}; // namespace ActiveLoaderInstance
+
+// Manages information needed by the loader for an XrInstance, such as what extensions are available and the dispatch table.
+class LoaderInstance {
+ public:
+ // Factory method
+ static XrResult CreateInstance(PFN_xrGetInstanceProcAddr get_instance_proc_addr_term, PFN_xrCreateInstance create_instance_term,
+ PFN_xrCreateApiLayerInstance create_api_layer_instance_term,
+ std::vector<std::unique_ptr<ApiLayerInterface>> layer_interfaces,
+ const XrInstanceCreateInfo* createInfo, std::unique_ptr<LoaderInstance>* loader_instance);
+ static const std::array<XrExtensionProperties, 1>& LoaderSpecificExtensions();
+
+ virtual ~LoaderInstance();
+
+ XrInstance GetInstanceHandle() { return _runtime_instance; }
+ const std::unique_ptr<XrGeneratedDispatchTable>& DispatchTable() { return _dispatch_table; }
+ std::vector<std::unique_ptr<ApiLayerInterface>>& LayerInterfaces() { return _api_layer_interfaces; }
+ bool ExtensionIsEnabled(const std::string& extension);
+ XrDebugUtilsMessengerEXT DefaultDebugUtilsMessenger() { return _messenger; }
+ void SetDefaultDebugUtilsMessenger(XrDebugUtilsMessengerEXT messenger) { _messenger = messenger; }
+ XrResult GetInstanceProcAddr(const char* name, PFN_xrVoidFunction* function);
+
+ private:
+ LoaderInstance(XrInstance instance, const XrInstanceCreateInfo* createInfo, PFN_xrGetInstanceProcAddr topmost_gipa,
+ std::vector<std::unique_ptr<ApiLayerInterface>> api_layer_interfaces);
+
+ private:
+ XrInstance _runtime_instance{XR_NULL_HANDLE};
+ PFN_xrGetInstanceProcAddr _topmost_gipa{nullptr};
+ std::vector<std::string> _enabled_extensions;
+ std::vector<std::unique_ptr<ApiLayerInterface>> _api_layer_interfaces;
+
+ std::unique_ptr<XrGeneratedDispatchTable> _dispatch_table;
+ // Internal debug messenger created during xrCreateInstance
+ XrDebugUtilsMessengerEXT _messenger{XR_NULL_HANDLE};
+};
diff --git a/thirdparty/openxr/src/loader/loader_logger.cpp b/thirdparty/openxr/src/loader/loader_logger.cpp
new file mode 100644
index 0000000000..dba46aa92d
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_logger.cpp
@@ -0,0 +1,239 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#include "loader_logger.hpp"
+
+#include "extra_algorithms.h"
+#include "hex_and_handles.h"
+#include "loader_logger_recorders.hpp"
+#include "platform_utils.hpp"
+
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <iterator>
+#include <memory>
+#include <mutex>
+#include <sstream>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+bool LoaderLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT /*message_severity*/,
+ XrDebugUtilsMessageTypeFlagsEXT /*message_type*/,
+ const XrDebugUtilsMessengerCallbackDataEXT* /*callback_data*/) {
+ return false;
+}
+
+// Utility functions for converting to/from XR_EXT_debug_utils values
+
+XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities) {
+ XrLoaderLogMessageSeverityFlags log_severities = 0UL;
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
+ }
+ if ((utils_severities & XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0u) {
+ log_severities |= XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
+ }
+ return log_severities;
+}
+
+XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
+ XrLoaderLogMessageSeverityFlags log_severities) {
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities = 0UL;
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+ }
+ if ((log_severities & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT) != 0u) {
+ utils_severities |= XR_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
+ }
+ return utils_severities;
+}
+
+XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types) {
+ XrLoaderLogMessageTypeFlagBits log_types = 0UL;
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT;
+ }
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT;
+ }
+ if ((utils_types & XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) != 0u) {
+ log_types |= XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT;
+ }
+ return log_types;
+}
+
+XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types) {
+ XrDebugUtilsMessageTypeFlagsEXT utils_types = 0UL;
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+ }
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
+ }
+ if ((log_types & XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT) != 0u) {
+ utils_types |= XR_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ }
+ return utils_types;
+}
+
+LoaderLogger::LoaderLogger() {
+ std::string debug_string = PlatformUtilsGetEnv("XR_LOADER_DEBUG");
+
+ // Add an error logger by default so that we at least get errors out to std::cerr.
+ // Normally we enable stderr output. But if the XR_LOADER_DEBUG environment variable is
+ // present as "none" then we don't.
+ if (debug_string != "none") {
+ AddLogRecorder(MakeStdErrLoaderLogRecorder(nullptr));
+#ifdef __ANDROID__
+ // Add a logcat logger by default.
+ AddLogRecorder(MakeLogcatLoaderLogRecorder());
+#endif // __ANDROID__
+ }
+
+#ifdef _WIN32
+ // Add an debugger logger by default so that we at least get errors out to the debugger.
+ AddLogRecorder(MakeDebuggerLoaderLogRecorder(nullptr));
+#endif
+
+ // If the environment variable to enable loader debugging is set, then enable the
+ // appropriate logging out to std::cout.
+ if (!debug_string.empty()) {
+ XrLoaderLogMessageSeverityFlags debug_flags = {};
+ if (debug_string == "error") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT;
+ } else if (debug_string == "warn") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT;
+ } else if (debug_string == "info") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
+ XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT;
+ } else if (debug_string == "all" || debug_string == "verbose") {
+ debug_flags = XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT |
+ XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT;
+ }
+ AddLogRecorder(MakeStdOutLoaderLogRecorder(nullptr, debug_flags));
+ }
+}
+
+void LoaderLogger::AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder) {
+ std::unique_lock<std::shared_timed_mutex> lock(_mutex);
+ _recorders.push_back(std::move(recorder));
+}
+
+void LoaderLogger::AddLogRecorderForXrInstance(XrInstance instance, std::unique_ptr<LoaderLogRecorder>&& recorder) {
+ std::unique_lock<std::shared_timed_mutex> lock(_mutex);
+ _recordersByInstance[instance].insert(recorder->UniqueId());
+ _recorders.emplace_back(std::move(recorder));
+}
+
+void LoaderLogger::RemoveLogRecorder(uint64_t unique_id) {
+ std::unique_lock<std::shared_timed_mutex> lock(_mutex);
+ vector_remove_if_and_erase(
+ _recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) { return recorder->UniqueId() == unique_id; });
+ for (auto& recorders : _recordersByInstance) {
+ auto& messengersForInstance = recorders.second;
+ if (messengersForInstance.count(unique_id) > 0) {
+ messengersForInstance.erase(unique_id);
+ }
+ }
+}
+
+void LoaderLogger::RemoveLogRecordersForXrInstance(XrInstance instance) {
+ std::unique_lock<std::shared_timed_mutex> lock(_mutex);
+ if (_recordersByInstance.find(instance) != _recordersByInstance.end()) {
+ auto recorders = _recordersByInstance[instance];
+ vector_remove_if_and_erase(_recorders, [=](std::unique_ptr<LoaderLogRecorder> const& recorder) {
+ return recorders.find(recorder->UniqueId()) != recorders.end();
+ });
+ _recordersByInstance.erase(instance);
+ }
+}
+
+bool LoaderLogger::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const std::string& message_id, const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects) {
+ XrLoaderLogMessengerCallbackData callback_data = {};
+ callback_data.message_id = message_id.c_str();
+ callback_data.command_name = command_name.c_str();
+ callback_data.message = message.c_str();
+
+ auto names_and_labels = data_.PopulateNamesAndLabels(objects);
+ callback_data.objects = names_and_labels.sdk_objects.empty() ? nullptr : names_and_labels.sdk_objects.data();
+ callback_data.object_count = static_cast<uint8_t>(names_and_labels.objects.size());
+
+ callback_data.session_labels = names_and_labels.labels.empty() ? nullptr : names_and_labels.labels.data();
+ callback_data.session_labels_count = static_cast<uint8_t>(names_and_labels.labels.size());
+
+ std::shared_lock<std::shared_timed_mutex> lock(_mutex);
+ bool exit_app = false;
+ for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
+ if ((recorder->MessageSeverities() & message_severity) == message_severity &&
+ (recorder->MessageTypes() & message_type) == message_type) {
+ exit_app |= recorder->LogMessage(message_severity, message_type, &callback_data);
+ }
+ }
+ return exit_app;
+}
+
+// Extension-specific logging functions
+bool LoaderLogger::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
+ bool exit_app = false;
+ XrLoaderLogMessageSeverityFlags log_message_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
+ XrLoaderLogMessageTypeFlags log_message_type = DebugUtilsMessageTypesToLoaderLogMessageTypes(message_type);
+
+ AugmentedCallbackData augmented_data;
+ data_.WrapCallbackData(&augmented_data, callback_data);
+
+ // Loop through the recorders
+ std::shared_lock<std::shared_timed_mutex> lock(_mutex);
+ for (std::unique_ptr<LoaderLogRecorder>& recorder : _recorders) {
+ // Only send the message if it's a debug utils recorder and of the type the recorder cares about.
+ if (recorder->Type() != XR_LOADER_LOG_DEBUG_UTILS ||
+ (recorder->MessageSeverities() & log_message_severity) != log_message_severity ||
+ (recorder->MessageTypes() & log_message_type) != log_message_type) {
+ continue;
+ }
+
+ exit_app |= recorder->LogDebugUtilsMessage(message_severity, message_type, augmented_data.exported_data);
+ }
+ return exit_app;
+}
+
+void LoaderLogger::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {
+ data_.AddObjectName(object_handle, object_type, object_name);
+}
+
+void LoaderLogger::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
+ data_.BeginLabelRegion(session, *label_info);
+}
+
+void LoaderLogger::EndLabelRegion(XrSession session) { data_.EndLabelRegion(session); }
+
+void LoaderLogger::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info) {
+ data_.InsertLabel(session, *label_info);
+}
+
+void LoaderLogger::DeleteSessionLabels(XrSession session) { data_.DeleteSessionLabels(session); }
diff --git a/thirdparty/openxr/src/loader/loader_logger.hpp b/thirdparty/openxr/src/loader/loader_logger.hpp
new file mode 100644
index 0000000000..260ebe354a
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_logger.hpp
@@ -0,0 +1,194 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+#include <set>
+#include <map>
+#include <shared_mutex>
+
+#include <openxr/openxr.h>
+
+#include "hex_and_handles.h"
+#include "object_info.h"
+
+// Use internal versions of flags similar to XR_EXT_debug_utils so that
+// we're not tightly coupled to that extension. This way, if the extension
+// changes or gets replaced, we can be flexible in the loader.
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT 0x00000001
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT 0x00000010
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT 0x00000100
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT 0x00001000
+#define XR_LOADER_LOG_MESSAGE_SEVERITY_DEFAULT_BITS 0x00000000
+typedef XrFlags64 XrLoaderLogMessageSeverityFlagBits;
+typedef XrFlags64 XrLoaderLogMessageSeverityFlags;
+
+#define XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT 0x00000001
+#define XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT 0x00000002
+#define XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT 0x00000004
+#define XR_LOADER_LOG_MESSAGE_TYPE_DEFAULT_BITS 0xffffffff
+typedef XrFlags64 XrLoaderLogMessageTypeFlagBits;
+typedef XrFlags64 XrLoaderLogMessageTypeFlags;
+
+struct XrLoaderLogMessengerCallbackData {
+ const char* message_id;
+ const char* command_name;
+ const char* message;
+ uint8_t object_count;
+ XrSdkLogObjectInfo* objects;
+ uint8_t session_labels_count;
+ XrDebugUtilsLabelEXT* session_labels;
+};
+
+enum XrLoaderLogType {
+ XR_LOADER_LOG_UNKNOWN = 0,
+ XR_LOADER_LOG_STDERR,
+ XR_LOADER_LOG_STDOUT,
+ XR_LOADER_LOG_DEBUG_UTILS,
+ XR_LOADER_LOG_DEBUGGER,
+ XR_LOADER_LOG_LOGCAT,
+};
+
+class LoaderLogRecorder {
+ public:
+ LoaderLogRecorder(XrLoaderLogType type, void* user_data, XrLoaderLogMessageSeverityFlags message_severities,
+ XrLoaderLogMessageTypeFlags message_types) {
+ _active = false;
+ _user_data = user_data;
+ _type = type;
+ _unique_id = 0;
+ _message_severities = message_severities;
+ _message_types = message_types;
+ }
+ virtual ~LoaderLogRecorder() = default;
+
+ XrLoaderLogType Type() { return _type; }
+
+ uint64_t UniqueId() { return _unique_id; }
+
+ XrLoaderLogMessageSeverityFlags MessageSeverities() { return _message_severities; }
+
+ XrLoaderLogMessageTypeFlags MessageTypes() { return _message_types; }
+
+ virtual void Start() { _active = true; }
+
+ bool IsPaused() { return _active; }
+
+ virtual void Pause() { _active = false; }
+
+ virtual void Resume() { _active = true; }
+
+ virtual void Stop() { _active = false; }
+
+ virtual bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) = 0;
+
+ // Extension-specific logging functions - defaults to do nothing.
+ virtual bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
+
+ protected:
+ bool _active;
+ XrLoaderLogType _type;
+ uint64_t _unique_id;
+ void* _user_data;
+ XrLoaderLogMessageSeverityFlags _message_severities;
+ XrLoaderLogMessageTypeFlags _message_types;
+};
+
+class LoaderLogger {
+ public:
+ static LoaderLogger& GetInstance() {
+ static LoaderLogger instance;
+ return instance;
+ }
+
+ void AddLogRecorder(std::unique_ptr<LoaderLogRecorder>&& recorder);
+ void RemoveLogRecorder(uint64_t unique_id);
+
+ void AddLogRecorderForXrInstance(XrInstance instance, std::unique_ptr<LoaderLogRecorder>&& recorder);
+ void RemoveLogRecordersForXrInstance(XrInstance instance);
+
+ //! Called from LoaderXrTermSetDebugUtilsObjectNameEXT - an empty name means remove
+ void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
+ void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT* label_info);
+ void EndLabelRegion(XrSession session);
+ void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT* label_info);
+ void DeleteSessionLabels(XrSession session);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const std::string& message_id, const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {});
+ static bool LogErrorMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogWarningMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogInfoMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogVerboseMessage(const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT, XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT,
+ "OpenXR-Loader", command_name, message, objects);
+ }
+ static bool LogValidationErrorMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
+ vuid, command_name, message, objects);
+ }
+ static bool LogValidationWarningMessage(const std::string& vuid, const std::string& command_name, const std::string& message,
+ const std::vector<XrSdkLogObjectInfo>& objects = {}) {
+ return GetInstance().LogMessage(XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT, XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT,
+ vuid, command_name, message, objects);
+ }
+
+ // Extension-specific logging functions
+ bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data);
+
+ // Non-copyable
+ LoaderLogger(const LoaderLogger&) = delete;
+ LoaderLogger& operator=(const LoaderLogger&) = delete;
+
+ private:
+ LoaderLogger();
+
+ std::shared_timed_mutex _mutex;
+
+ // List of *all* available recorder objects (including created specifically for an Instance)
+ std::vector<std::unique_ptr<LoaderLogRecorder>> _recorders;
+
+ // List of recorder objects only created specifically for an XrInstance
+ std::unordered_map<XrInstance, std::unordered_set<uint64_t>> _recordersByInstance;
+
+ DebugUtilsData data_;
+};
+
+// Utility functions for converting to/from XR_EXT_debug_utils values
+XrLoaderLogMessageSeverityFlags DebugUtilsSeveritiesToLoaderLogMessageSeverities(
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severities);
+XrDebugUtilsMessageSeverityFlagsEXT LoaderLogMessageSeveritiesToDebugUtilsMessageSeverities(
+ XrLoaderLogMessageSeverityFlags log_severities);
+XrLoaderLogMessageTypeFlagBits DebugUtilsMessageTypesToLoaderLogMessageTypes(XrDebugUtilsMessageTypeFlagsEXT utils_types);
+XrDebugUtilsMessageTypeFlagsEXT LoaderLogMessageTypesToDebugUtilsMessageTypes(XrLoaderLogMessageTypeFlagBits log_types);
diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.cpp b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp
new file mode 100644
index 0000000000..7673678c60
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_logger_recorders.cpp
@@ -0,0 +1,291 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#include "loader_logger_recorders.hpp"
+
+#include "hex_and_handles.h"
+#include "loader_logger.hpp"
+
+#include <openxr/openxr.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <sstream>
+
+#ifdef __ANDROID__
+#include "android/log.h"
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+// Anonymous namespace to keep these types private
+namespace {
+void OutputMessageToStream(std::ostream& os, XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type, const XrLoaderLogMessengerCallbackData* callback_data) {
+ if (XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT > message_severity) {
+ os << "Verbose [";
+ } else if (XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT > message_severity) {
+ os << "Info [";
+ } else if (XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT > message_severity) {
+ os << "Warning [";
+ } else {
+ os << "Error [";
+ }
+ switch (message_type) {
+ case XR_LOADER_LOG_MESSAGE_TYPE_GENERAL_BIT:
+ os << "GENERAL";
+ break;
+ case XR_LOADER_LOG_MESSAGE_TYPE_SPECIFICATION_BIT:
+ os << "SPEC";
+ break;
+ case XR_LOADER_LOG_MESSAGE_TYPE_PERFORMANCE_BIT:
+ os << "PERF";
+ break;
+ default:
+ os << "UNKNOWN";
+ break;
+ }
+ os << " | " << callback_data->command_name << " | " << callback_data->message_id << "] : " << callback_data->message
+ << std::endl;
+
+ for (uint32_t obj = 0; obj < callback_data->object_count; ++obj) {
+ os << " Object[" << obj << "] = " << callback_data->objects[obj].ToString();
+ os << std::endl;
+ }
+ for (uint32_t label = 0; label < callback_data->session_labels_count; ++label) {
+ os << " SessionLabel[" << std::to_string(label) << "] = " << callback_data->session_labels[label].labelName;
+ os << std::endl;
+ }
+}
+
+// With std::cerr: Standard Error logger, always on for now
+// With std::cout: Standard Output logger used with XR_LOADER_DEBUG
+class OstreamLoaderLogRecorder : public LoaderLogRecorder {
+ public:
+ OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+
+ private:
+ std::ostream& os_;
+};
+
+// Debug Utils logger used with XR_EXT_debug_utils
+class DebugUtilsLogRecorder : public LoaderLogRecorder {
+ public:
+ DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info, XrDebugUtilsMessengerEXT debug_messenger);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+
+ // Extension-specific logging functions
+ bool LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity, XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) override;
+
+ private:
+ PFN_xrDebugUtilsMessengerCallbackEXT _user_callback;
+};
+#ifdef __ANDROID__
+
+class LogcatLoaderLogRecorder : public LoaderLogRecorder {
+ public:
+ LogcatLoaderLogRecorder();
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+};
+#endif
+
+#ifdef _WIN32
+// Output to debugger
+class DebuggerLoaderLogRecorder : public LoaderLogRecorder {
+ public:
+ DebuggerLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
+
+ bool LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity, XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) override;
+};
+#endif
+
+// Unified stdout/stderr logger
+OstreamLoaderLogRecorder::OstreamLoaderLogRecorder(std::ostream& os, void* user_data, XrLoaderLogMessageSeverityFlags flags)
+ : LoaderLogRecorder(XR_LOADER_LOG_STDOUT, user_data, flags, 0xFFFFFFFFUL), os_(os) {
+ // Automatically start
+ Start();
+}
+
+bool OstreamLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ OutputMessageToStream(os_, message_severity, message_type, callback_data);
+ }
+
+ // Return of "true" means that we should exit the application after the logged message. We
+ // don't want to do that for our internal logging. Only let a user return true.
+ return false;
+}
+
+// A logger associated with the XR_EXT_debug_utils extension
+
+DebugUtilsLogRecorder::DebugUtilsLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger)
+ : LoaderLogRecorder(XR_LOADER_LOG_DEBUG_UTILS, static_cast<void*>(create_info->userData),
+ DebugUtilsSeveritiesToLoaderLogMessageSeverities(create_info->messageSeverities),
+ DebugUtilsMessageTypesToLoaderLogMessageTypes(create_info->messageTypes)),
+ _user_callback(create_info->userCallback) {
+ // Use the debug messenger value to uniquely identify this logger with that messenger
+ _unique_id = MakeHandleGeneric(debug_messenger);
+ Start();
+}
+
+// Extension-specific logging functions
+bool DebugUtilsLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ bool should_exit = false;
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ XrDebugUtilsMessageSeverityFlagsEXT utils_severity = DebugUtilsSeveritiesToLoaderLogMessageSeverities(message_severity);
+ XrDebugUtilsMessageTypeFlagsEXT utils_type = LoaderLogMessageTypesToDebugUtilsMessageTypes(message_type);
+
+ // Convert the loader log message into the debug utils log message information
+ XrDebugUtilsMessengerCallbackDataEXT utils_callback_data = {};
+ utils_callback_data.type = XR_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ utils_callback_data.messageId = callback_data->message_id;
+ utils_callback_data.functionName = callback_data->command_name;
+ utils_callback_data.message = callback_data->message;
+ std::vector<XrDebugUtilsObjectNameInfoEXT> utils_objects;
+ utils_objects.resize(callback_data->object_count);
+ for (uint8_t object = 0; object < callback_data->object_count; ++object) {
+ utils_objects[object].type = XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
+ utils_objects[object].next = nullptr;
+ utils_objects[object].objectHandle = callback_data->objects[object].handle;
+ utils_objects[object].objectType = callback_data->objects[object].type;
+ utils_objects[object].objectName = callback_data->objects[object].name.c_str();
+ }
+ utils_callback_data.objectCount = callback_data->object_count;
+ utils_callback_data.objects = utils_objects.data();
+ utils_callback_data.sessionLabelCount = callback_data->session_labels_count;
+ utils_callback_data.sessionLabels = callback_data->session_labels;
+
+ // Call the user callback with the appropriate info
+ // Return of "true" means that we should exit the application after the logged message.
+ should_exit = (_user_callback(utils_severity, utils_type, &utils_callback_data, _user_data) == XR_TRUE);
+ }
+
+ return should_exit;
+}
+
+bool DebugUtilsLogRecorder::LogDebugUtilsMessage(XrDebugUtilsMessageSeverityFlagsEXT message_severity,
+ XrDebugUtilsMessageTypeFlagsEXT message_type,
+ const XrDebugUtilsMessengerCallbackDataEXT* callback_data) {
+ // Call the user callback with the appropriate info
+ // Return of "true" means that we should exit the application after the logged message.
+ return (_user_callback(message_severity, message_type, callback_data, _user_data) == XR_TRUE);
+}
+
+#ifdef __ANDROID__
+
+static inline android_LogPriority LoaderToAndroidLogPriority(XrLoaderLogMessageSeverityFlags message_severity) {
+ if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT)) {
+ return ANDROID_LOG_ERROR;
+ }
+ if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT)) {
+ return ANDROID_LOG_WARN;
+ }
+ if (0 != (message_severity & XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT)) {
+ return ANDROID_LOG_INFO;
+ }
+ return ANDROID_LOG_VERBOSE;
+}
+
+LogcatLoaderLogRecorder::LogcatLoaderLogRecorder()
+ : LoaderLogRecorder(XR_LOADER_LOG_LOGCAT, nullptr,
+ XR_LOADER_LOG_MESSAGE_SEVERITY_VERBOSE_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_INFO_BIT |
+ XR_LOADER_LOG_MESSAGE_SEVERITY_WARNING_BIT | XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT,
+ 0xFFFFFFFFUL) {
+ // Automatically start
+ Start();
+}
+
+bool LogcatLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ std::stringstream ss;
+ OutputMessageToStream(ss, message_severity, message_type, callback_data);
+ __android_log_write(LoaderToAndroidLogPriority(message_severity), "OpenXR-Loader", ss.str().c_str());
+ }
+
+ // Return of "true" means that we should exit the application after the logged message. We
+ // don't want to do that for our internal logging. Only let a user return true.
+ return false;
+}
+#endif // __ANDROID__
+
+#ifdef _WIN32
+// Unified stdout/stderr logger
+DebuggerLoaderLogRecorder::DebuggerLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags)
+ : LoaderLogRecorder(XR_LOADER_LOG_DEBUGGER, user_data, flags, 0xFFFFFFFFUL) {
+ // Automatically start
+ Start();
+}
+
+bool DebuggerLoaderLogRecorder::LogMessage(XrLoaderLogMessageSeverityFlagBits message_severity,
+ XrLoaderLogMessageTypeFlags message_type,
+ const XrLoaderLogMessengerCallbackData* callback_data) {
+ if (_active && 0 != (_message_severities & message_severity) && 0 != (_message_types & message_type)) {
+ std::stringstream ss;
+ OutputMessageToStream(ss, message_severity, message_type, callback_data);
+
+ OutputDebugStringA(ss.str().c_str());
+ }
+
+ // Return of "true" means that we should exit the application after the logged message. We
+ // don't want to do that for our internal logging. Only let a user return true.
+ return false;
+}
+#endif
+} // namespace
+
+std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags) {
+ std::unique_ptr<LoaderLogRecorder> recorder(new OstreamLoaderLogRecorder(std::cout, user_data, flags));
+ return recorder;
+}
+
+std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data) {
+ std::unique_ptr<LoaderLogRecorder> recorder(
+ new OstreamLoaderLogRecorder(std::cerr, user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
+ return recorder;
+}
+
+std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger) {
+ std::unique_ptr<LoaderLogRecorder> recorder(new DebugUtilsLogRecorder(create_info, debug_messenger));
+ return recorder;
+}
+
+#ifdef __ANDROID__
+std::unique_ptr<LoaderLogRecorder> MakeLogcatLoaderLogRecorder() {
+ std::unique_ptr<LoaderLogRecorder> recorder(new LogcatLoaderLogRecorder());
+ return recorder;
+}
+#endif
+
+#ifdef _WIN32
+std::unique_ptr<LoaderLogRecorder> MakeDebuggerLoaderLogRecorder(void* user_data) {
+ std::unique_ptr<LoaderLogRecorder> recorder(new DebuggerLoaderLogRecorder(user_data, XR_LOADER_LOG_MESSAGE_SEVERITY_ERROR_BIT));
+ return recorder;
+}
+#endif
diff --git a/thirdparty/openxr/src/loader/loader_logger_recorders.hpp b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp
new file mode 100644
index 0000000000..31e5243c45
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_logger_recorders.hpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Ryan Pavlik <ryan.pavlik@collabora.com>
+//
+
+#pragma once
+
+#include "loader_logger.hpp"
+
+#include <openxr/openxr.h>
+
+#include <memory>
+
+//! Standard Error logger, on by default. Disabled with environment variable XR_LOADER_DEBUG = "none".
+std::unique_ptr<LoaderLogRecorder> MakeStdErrLoaderLogRecorder(void* user_data);
+
+//! Standard Output logger used with XR_LOADER_DEBUG environment variable.
+std::unique_ptr<LoaderLogRecorder> MakeStdOutLoaderLogRecorder(void* user_data, XrLoaderLogMessageSeverityFlags flags);
+
+#ifdef __ANDROID__
+//! Android liblog ("logcat") logger
+std::unique_ptr<LoaderLogRecorder> MakeLogcatLoaderLogRecorder();
+#endif
+
+// Debug Utils logger used with XR_EXT_debug_utils
+std::unique_ptr<LoaderLogRecorder> MakeDebugUtilsLoaderLogRecorder(const XrDebugUtilsMessengerCreateInfoEXT* create_info,
+ XrDebugUtilsMessengerEXT debug_messenger);
+
+#ifdef _WIN32
+//! Win32 debugger output
+std::unique_ptr<LoaderLogRecorder> MakeDebuggerLoaderLogRecorder(void* user_data);
+#endif
+
+// TODO: Add other Derived classes:
+// - FileLoaderLogRecorder - During/after xrCreateInstance
+// - PipeLoaderLogRecorder? - During/after xrCreateInstance
diff --git a/thirdparty/openxr/src/loader/loader_platform.hpp b/thirdparty/openxr/src/loader/loader_platform.hpp
new file mode 100644
index 0000000000..e2757fffb9
--- /dev/null
+++ b/thirdparty/openxr/src/loader/loader_platform.hpp
@@ -0,0 +1,204 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
+//
+
+#pragma once
+
+#include <cassert>
+#include <sstream>
+#include <string>
+
+#include "xr_dependencies.h"
+#include "platform_utils.hpp"
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
+#define LOADER_EXPORT __attribute__((visibility("default")))
+#else
+#define LOADER_EXPORT
+#endif
+
+// Environment variables
+#if defined(XR_OS_LINUX) || defined(XR_OS_APPLE) || defined(XR_OS_ANDROID)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+
+#ifndef PATH_MAX
+#define PATH_MAX 1024
+#endif
+
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+
+// Dynamic Loading of libraries:
+typedef void *LoaderPlatformLibraryHandle;
+static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+ // When loading the library, we use RTLD_LAZY so that not all symbols have to be
+ // resolved at this time (which improves performance). Note that if not all symbols
+ // can be resolved, this could cause crashes later.
+ // For experimenting/debugging: Define the LD_BIND_NOW environment variable to force all
+ // symbols to be resolved here.
+ return dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
+}
+
+static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
+ (void)path;
+ return dlerror();
+}
+
+static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { dlclose(library); }
+
+static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ assert(library);
+ assert(!name.empty());
+ return dlsym(library, name.c_str());
+}
+
+static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
+ (void)name;
+ return dlerror();
+}
+
+#elif defined(XR_OS_WINDOWS)
+
+#define PATH_SEPARATOR ';'
+#define DIRECTORY_SYMBOL '\\'
+
+// Workaround for MS VS 2010/2013 missing snprintf and vsnprintf
+#if defined(_MSC_VER) && _MSC_VER < 1900
+#include <stdint.h>
+
+static inline int32_t xr_vsnprintf(char *result_buffer, size_t buffer_size, const char *print_format, va_list varying_list) {
+ int32_t copy_count = -1;
+ if (buffer_size != 0) {
+ copy_count = _vsnprintf_s(result_buffer, buffer_size, _TRUNCATE, print_format, varying_list);
+ }
+ if (copy_count == -1) {
+ copy_count = _vscprintf(print_format, varying_list);
+ }
+ return copy_count;
+}
+
+static inline int32_t xr_snprintf(char *result_buffer, size_t buffer_size, const char *print_format, ...) {
+ va_list varying_list;
+ va_start(varying_list, print_format);
+ int32_t copy_count = xr_vsnprintf(result_buffer, buffer_size, print_format, varying_list);
+ va_end(varying_list);
+ return copy_count;
+}
+
+#define snprintf xr_snprintf
+#define vsnprintf xr_vsnprintf
+
+#endif
+
+static inline std::string DescribeError(uint32_t code, bool prefixErrorCode = true) {
+ std::string str;
+
+ if (prefixErrorCode) {
+ char prefixBuffer[64];
+ snprintf(prefixBuffer, sizeof(prefixBuffer), "0x%llx (%lld): ", (uint64_t)code, (int64_t)code);
+ str = prefixBuffer;
+ }
+
+ // Could use FORMAT_MESSAGE_FROM_HMODULE to specify an error source.
+ WCHAR errorBufferW[1024]{};
+ const DWORD errorBufferWCapacity = sizeof(errorBufferW) / sizeof(errorBufferW[0]);
+ const DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, (DWORD)code,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), errorBufferW, errorBufferWCapacity, nullptr);
+
+ if (length) { // If errorBufferW contains what we are looking for...
+ str += wide_to_utf8(errorBufferW);
+ } else {
+ str = "(unknown)";
+ }
+
+ return str;
+}
+
+// Dynamic Loading:
+typedef HMODULE LoaderPlatformLibraryHandle;
+static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+ const std::wstring pathW = utf8_to_wide(path);
+
+ // Try loading the library the original way first.
+ LoaderPlatformLibraryHandle handle = LoadLibraryW(pathW.c_str());
+
+ if (handle == NULL && GetLastError() == ERROR_MOD_NOT_FOUND) {
+ const DWORD dwAttrib = GetFileAttributesW(pathW.c_str());
+ const bool fileExists = (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
+ if (fileExists) {
+ // If that failed, then try loading it with broader search folders.
+ handle = LoadLibraryExW(pathW.c_str(), NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
+ }
+ }
+
+ return handle;
+}
+
+static inline std::string LoaderPlatformLibraryOpenError(const std::string &path) {
+ std::stringstream ss;
+ const DWORD dwLastError = GetLastError();
+ const std::string strError = DescribeError(dwLastError);
+ ss << "Failed to open dynamic library " << path << " with error " << dwLastError << ": " << strError;
+ return ss.str();
+}
+
+static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) { FreeLibrary(library); }
+
+static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ assert(library);
+ assert(name.size() > 0);
+ return reinterpret_cast<void *>(GetProcAddress(library, name.c_str()));
+}
+
+static inline std::string LoaderPlatformLibraryGetProcAddrAddrError(const std::string &name) {
+ std::stringstream ss;
+ ss << "Failed to find function " << name << " in dynamic library";
+ return ss.str();
+}
+
+#else // Not Linux or Windows
+
+#define PATH_SEPARATOR ':'
+#define DIRECTORY_SYMBOL '/'
+
+static inline LoaderPlatformLibraryHandle LoaderPlatformLibraryOpen(const std::string &path) {
+// Stub func
+#error("Unknown platform, undefined dynamic library routines resulting");
+ (void)path;
+}
+
+static inline const char *LoaderPlatformLibraryOpenError(const std::string &path) {
+ // Stub func
+ (void)path;
+}
+
+static inline void LoaderPlatformLibraryClose(LoaderPlatformLibraryHandle library) {
+ // Stub func
+ (void)library;
+}
+
+static inline void *LoaderPlatformLibraryGetProcAddr(LoaderPlatformLibraryHandle library, const std::string &name) {
+ // Stub func
+ void(library);
+ void(name);
+}
+
+static inline const char *LoaderPlatformLibraryGetProcAddrError(const std::string &name) {
+ // Stub func
+ (void)name;
+}
+
+#endif
diff --git a/thirdparty/openxr/src/loader/manifest_file.cpp b/thirdparty/openxr/src/loader/manifest_file.cpp
new file mode 100644
index 0000000000..e4eab3949e
--- /dev/null
+++ b/thirdparty/openxr/src/loader/manifest_file.cpp
@@ -0,0 +1,845 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Authors: Mark Young <marky@lunarg.com>, Dave Houlton <daveh@lunarg.com>
+//
+
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+#define _CRT_SECURE_NO_WARNINGS
+#endif // defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
+
+#include "manifest_file.hpp"
+
+#ifdef OPENXR_HAVE_COMMON_CONFIG
+#include "common_config.h"
+#endif // OPENXR_HAVE_COMMON_CONFIG
+
+#include "filesystem_utils.hpp"
+#include "loader_platform.hpp"
+#include "platform_utils.hpp"
+#include "loader_logger.hpp"
+
+#include <json/json.h>
+#include <openxr/openxr.h>
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#ifndef FALLBACK_CONFIG_DIRS
+#define FALLBACK_CONFIG_DIRS "/etc/xdg"
+#endif // !FALLBACK_CONFIG_DIRS
+
+#ifndef FALLBACK_DATA_DIRS
+#define FALLBACK_DATA_DIRS "/usr/local/share:/usr/share"
+#endif // !FALLBACK_DATA_DIRS
+
+#ifndef SYSCONFDIR
+#define SYSCONFDIR "/etc"
+#endif // !SYSCONFDIR
+
+#ifdef XRLOADER_DISABLE_EXCEPTION_HANDLING
+#if JSON_USE_EXCEPTIONS
+#error \
+ "Loader is configured to not catch exceptions, but jsoncpp was built with exception-throwing enabled, which could violate the C ABI. One of those two things needs to change."
+#endif // JSON_USE_EXCEPTIONS
+#endif // !XRLOADER_DISABLE_EXCEPTION_HANDLING
+
+#include "runtime_interface.hpp"
+
+// Utility functions for finding files in the appropriate paths
+
+static inline bool StringEndsWith(const std::string &value, const std::string &ending) {
+ if (ending.size() > value.size()) {
+ return false;
+ }
+ return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+}
+
+// If the file found is a manifest file name, add it to the out_files manifest list.
+static void AddIfJson(const std::string &full_file, std::vector<std::string> &manifest_files) {
+ if (full_file.empty() || !StringEndsWith(full_file, ".json")) {
+ return;
+ }
+ manifest_files.push_back(full_file);
+}
+
+// Check the current path for any manifest files. If the provided search_path is a directory, look for
+// all included JSON files in that directory. Otherwise, just check the provided search_path which should
+// be a single filename.
+static void CheckAllFilesInThePath(const std::string &search_path, bool is_directory_list,
+ std::vector<std::string> &manifest_files) {
+ if (FileSysUtilsPathExists(search_path)) {
+ std::string absolute_path;
+ if (!is_directory_list) {
+ // If the file exists, try to add it
+ if (FileSysUtilsIsRegularFile(search_path)) {
+ FileSysUtilsGetAbsolutePath(search_path, absolute_path);
+ AddIfJson(absolute_path, manifest_files);
+ }
+ } else {
+ std::vector<std::string> files;
+ if (FileSysUtilsFindFilesInPath(search_path, files)) {
+ for (std::string &cur_file : files) {
+ std::string relative_path;
+ FileSysUtilsCombinePaths(search_path, cur_file, relative_path);
+ if (!FileSysUtilsGetAbsolutePath(relative_path, absolute_path)) {
+ continue;
+ }
+ AddIfJson(absolute_path, manifest_files);
+ }
+ }
+ }
+ }
+}
+
+// Add all manifest files in the provided paths to the manifest_files list. If search_path
+// is made up of directory listings (versus direct manifest file names) search each path for
+// any manifest files.
+static void AddFilesInPath(const std::string &search_path, bool is_directory_list, std::vector<std::string> &manifest_files) {
+ std::size_t last_found = 0;
+ std::size_t found = search_path.find_first_of(PATH_SEPARATOR);
+ std::string cur_search;
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ // substr takes a start index and length.
+ std::size_t length = found - last_found;
+ cur_search = search_path.substr(last_found, length);
+
+ CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
+
+ // This works around issue if multiple path separator follow each other directly.
+ last_found = found;
+ while (found == last_found) {
+ last_found = found + 1;
+ found = search_path.find_first_of(PATH_SEPARATOR, last_found);
+ }
+ }
+
+ // If there's something remaining in the string, copy it over
+ if (last_found < search_path.size()) {
+ cur_search = search_path.substr(last_found);
+ CheckAllFilesInThePath(cur_search, is_directory_list, manifest_files);
+ }
+}
+
+// Copy all paths listed in the cur_path string into output_path and append the appropriate relative_path onto the end of each.
+static void CopyIncludedPaths(bool is_directory_list, const std::string &cur_path, const std::string &relative_path,
+ std::string &output_path) {
+ if (!cur_path.empty()) {
+ std::size_t last_found = 0;
+ std::size_t found = cur_path.find_first_of(PATH_SEPARATOR);
+
+ // Handle any path listings in the string (separated by the appropriate path separator)
+ while (found != std::string::npos) {
+ std::size_t length = found - last_found;
+ output_path += cur_path.substr(last_found, length);
+ if (is_directory_list && (cur_path[found - 1] != '\\' && cur_path[found - 1] != '/')) {
+ output_path += DIRECTORY_SYMBOL;
+ }
+ output_path += relative_path;
+ output_path += PATH_SEPARATOR;
+
+ last_found = found;
+ found = cur_path.find_first_of(PATH_SEPARATOR, found + 1);
+ }
+
+ // If there's something remaining in the string, copy it over
+ size_t last_char = cur_path.size() - 1;
+ if (last_found != last_char) {
+ output_path += cur_path.substr(last_found);
+ if (is_directory_list && (cur_path[last_char] != '\\' && cur_path[last_char] != '/')) {
+ output_path += DIRECTORY_SYMBOL;
+ }
+ output_path += relative_path;
+ output_path += PATH_SEPARATOR;
+ }
+ }
+}
+
+// Look for data files in the provided paths, but first check the environment override to determine if we should use that instead.
+static void ReadDataFilesInSearchPaths(const std::string &override_env_var, const std::string &relative_path, bool &override_active,
+ std::vector<std::string> &manifest_files) {
+ std::string override_path;
+ std::string search_path;
+
+ if (!override_env_var.empty()) {
+ bool permit_override = true;
+#ifndef XR_OS_WINDOWS
+ if (geteuid() != getuid() || getegid() != getgid()) {
+ // Don't allow setuid apps to use the env var
+ permit_override = false;
+ }
+#endif
+ if (permit_override) {
+ override_path = PlatformUtilsGetSecureEnv(override_env_var.c_str());
+ }
+ }
+
+ if (!override_path.empty()) {
+ CopyIncludedPaths(true, override_path, "", search_path);
+ override_active = true;
+ } else {
+ override_active = false;
+#if !defined(XR_OS_WINDOWS) && !defined(XR_OS_ANDROID)
+ const char home_additional[] = ".local/share/";
+
+ // Determine how much space is needed to generate the full search path
+ // for the current manifest files.
+ std::string xdg_conf_dirs = PlatformUtilsGetSecureEnv("XDG_CONFIG_DIRS");
+ std::string xdg_data_dirs = PlatformUtilsGetSecureEnv("XDG_DATA_DIRS");
+ std::string xdg_data_home = PlatformUtilsGetSecureEnv("XDG_DATA_HOME");
+ std::string home = PlatformUtilsGetSecureEnv("HOME");
+
+ if (xdg_conf_dirs.empty()) {
+ CopyIncludedPaths(true, FALLBACK_CONFIG_DIRS, relative_path, search_path);
+ } else {
+ CopyIncludedPaths(true, xdg_conf_dirs, relative_path, search_path);
+ }
+
+ CopyIncludedPaths(true, SYSCONFDIR, relative_path, search_path);
+#if defined(EXTRASYSCONFDIR)
+ CopyIncludedPaths(true, EXTRASYSCONFDIR, relative_path, search_path);
+#endif
+
+ if (xdg_data_dirs.empty()) {
+ CopyIncludedPaths(true, FALLBACK_DATA_DIRS, relative_path, search_path);
+ } else {
+ CopyIncludedPaths(true, xdg_data_dirs, relative_path, search_path);
+ }
+
+ if (!xdg_data_home.empty()) {
+ CopyIncludedPaths(true, xdg_data_home, relative_path, search_path);
+ } else if (!home.empty()) {
+ std::string relative_home_path = home_additional;
+ relative_home_path += relative_path;
+ CopyIncludedPaths(true, home, relative_home_path, search_path);
+ }
+#else
+ (void)relative_path;
+#endif
+ }
+
+ // Now, parse the paths and add any manifest files found in them.
+ AddFilesInPath(search_path, true, manifest_files);
+}
+
+#ifdef XR_OS_LINUX
+
+// Get an XDG environment variable with a $HOME-relative default
+static std::string GetXDGEnvHome(const char *name, const char *fallback_path) {
+ std::string result = PlatformUtilsGetSecureEnv(name);
+ if (!result.empty()) {
+ return result;
+ }
+ result = PlatformUtilsGetSecureEnv("HOME");
+ if (result.empty()) {
+ return result;
+ }
+ result += "/";
+ result += fallback_path;
+ return result;
+}
+
+// Get an XDG environment variable with absolute defaults
+static std::string GetXDGEnvAbsolute(const char *name, const char *fallback_paths) {
+ std::string result = PlatformUtilsGetSecureEnv(name);
+ if (!result.empty()) {
+ return result;
+ }
+ return fallback_paths;
+}
+
+// Return the first instance of relative_path occurring in an XDG config dir according to standard
+// precedence order.
+static bool FindXDGConfigFile(const std::string &relative_path, std::string &out) {
+ out = GetXDGEnvHome("XDG_CONFIG_HOME", ".config");
+ if (!out.empty()) {
+ out += "/";
+ out += relative_path;
+
+ LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in XDG_CONFIG_HOME: " + out);
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+ }
+
+ std::istringstream iss(GetXDGEnvAbsolute("XDG_CONFIG_DIRS", FALLBACK_CONFIG_DIRS));
+ std::string path;
+ while (std::getline(iss, path, PATH_SEPARATOR)) {
+ if (path.empty()) {
+ continue;
+ }
+ out = path;
+ out += "/";
+ out += relative_path;
+ LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in an entry of XDG_CONFIG_DIRS: " + out);
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+ }
+
+ out = SYSCONFDIR;
+ out += "/";
+ out += relative_path;
+ LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in compiled-in SYSCONFDIR: " + out);
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+
+#if defined(EXTRASYSCONFDIR)
+ out = EXTRASYSCONFDIR;
+ out += "/";
+ out += relative_path;
+ LoaderLogger::LogInfoMessage("", "Looking for " + relative_path + " in compiled-in EXTRASYSCONFDIR: " + out);
+ if (FileSysUtilsPathExists(out)) {
+ return true;
+ }
+#endif
+
+ out.clear();
+ return false;
+}
+
+#endif
+
+#ifdef XR_OS_WINDOWS
+
+// Look for runtime data files in the provided paths, but first check the environment override to determine
+// if we should use that instead.
+static void ReadRuntimeDataFilesInRegistry(const std::string &runtime_registry_location,
+ const std::string &default_runtime_value_name,
+ std::vector<std::string> &manifest_files) {
+ HKEY hkey;
+ DWORD access_flags;
+ wchar_t value_w[1024];
+ DWORD value_size_w = sizeof(value_w); // byte size of the buffer.
+
+ // Generate the full registry location for the registry information
+ std::string full_registry_location = OPENXR_REGISTRY_LOCATION;
+ full_registry_location += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
+ full_registry_location += runtime_registry_location;
+
+ const std::wstring full_registry_location_w = utf8_to_wide(full_registry_location);
+ const std::wstring default_runtime_value_name_w = utf8_to_wide(default_runtime_value_name);
+
+ // Use 64 bit regkey for 64bit application, and use 32 bit regkey in WOW for 32bit application.
+ access_flags = KEY_QUERY_VALUE;
+ LONG open_value = RegOpenKeyExW(HKEY_LOCAL_MACHINE, full_registry_location_w.c_str(), 0, access_flags, &hkey);
+
+ if (ERROR_SUCCESS != open_value) {
+ LoaderLogger::LogWarningMessage("",
+ "ReadRuntimeDataFilesInRegistry - failed to open registry key " + full_registry_location);
+ } else if (ERROR_SUCCESS != RegGetValueW(hkey, nullptr, default_runtime_value_name_w.c_str(),
+ RRF_RT_REG_SZ | REG_EXPAND_SZ | RRF_ZEROONFAILURE, NULL,
+ reinterpret_cast<LPBYTE>(&value_w), &value_size_w)) {
+ LoaderLogger::LogWarningMessage(
+ "", "ReadRuntimeDataFilesInRegistry - failed to read registry value " + default_runtime_value_name);
+ } else {
+ AddFilesInPath(wide_to_utf8(value_w), false, manifest_files);
+ }
+}
+
+// Look for layer data files in the provided paths, but first check the environment override to determine
+// if we should use that instead.
+static void ReadLayerDataFilesInRegistry(const std::string &registry_location, std::vector<std::string> &manifest_files) {
+ const std::wstring full_registry_location_w =
+ utf8_to_wide(OPENXR_REGISTRY_LOCATION + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + registry_location);
+
+ auto ReadLayerDataFilesInHive = [&](HKEY hive) {
+ HKEY hkey;
+ LONG open_value = RegOpenKeyExW(hive, full_registry_location_w.c_str(), 0, KEY_QUERY_VALUE, &hkey);
+ if (ERROR_SUCCESS != open_value) {
+ return false;
+ }
+
+ wchar_t name_w[1024]{};
+ LONG rtn_value;
+ DWORD name_size = 1023;
+ DWORD value;
+ DWORD value_size = sizeof(value);
+ DWORD key_index = 0;
+ while (ERROR_SUCCESS ==
+ (rtn_value = RegEnumValueW(hkey, key_index++, name_w, &name_size, NULL, NULL, (LPBYTE)&value, &value_size))) {
+ if (value_size == sizeof(value) && value == 0) {
+ const std::string filename = wide_to_utf8(name_w);
+ AddFilesInPath(filename, false, manifest_files);
+ }
+ // Reset some items for the next loop
+ name_size = 1023;
+ }
+
+ RegCloseKey(hkey);
+
+ return true;
+ };
+
+ // Do not allow high integrity processes to act on data that can be controlled by medium integrity processes.
+ const bool readFromCurrentUser = !IsHighIntegrityLevel();
+
+ bool found = ReadLayerDataFilesInHive(HKEY_LOCAL_MACHINE);
+ if (readFromCurrentUser) {
+ found |= ReadLayerDataFilesInHive(HKEY_CURRENT_USER);
+ }
+
+ if (!found) {
+ std::string warning_message = "ReadLayerDataFilesInRegistry - failed to read registry location ";
+ warning_message += registry_location;
+ warning_message += (readFromCurrentUser ? " in either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER" : " in HKEY_LOCAL_MACHINE");
+ LoaderLogger::LogWarningMessage("", warning_message);
+ }
+}
+
+#endif // XR_OS_WINDOWS
+
+ManifestFile::ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path)
+ : _filename(filename), _type(type), _library_path(library_path) {}
+
+bool ManifestFile::IsValidJson(const Json::Value &root_node, JsonVersion &version) {
+ if (root_node["file_format_version"].isNull() || !root_node["file_format_version"].isString()) {
+ LoaderLogger::LogErrorMessage("", "ManifestFile::IsValidJson - JSON file missing \"file_format_version\"");
+ return false;
+ }
+ std::string file_format = root_node["file_format_version"].asString();
+ const int num_fields = sscanf(file_format.c_str(), "%u.%u.%u", &version.major, &version.minor, &version.patch);
+
+ // Only version 1.0.0 is defined currently. Eventually we may have more version, but
+ // some of the versions may only be valid for layers or runtimes specifically.
+ if (num_fields != 3 || version.major != 1 || version.minor != 0 || version.patch != 0) {
+ std::ostringstream error_ss;
+ error_ss << "ManifestFile::IsValidJson - JSON \"file_format_version\" " << version.major << "." << version.minor << "."
+ << version.patch << " is not supported";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return false;
+ }
+
+ return true;
+}
+
+static void GetExtensionProperties(const std::vector<ExtensionListing> &extensions, std::vector<XrExtensionProperties> &props) {
+ for (const auto &ext : extensions) {
+ auto it =
+ std::find_if(props.begin(), props.end(), [&](XrExtensionProperties &prop) { return prop.extensionName == ext.name; });
+ if (it != props.end()) {
+ it->extensionVersion = std::max(it->extensionVersion, ext.extension_version);
+ } else {
+ XrExtensionProperties prop = {};
+ prop.type = XR_TYPE_EXTENSION_PROPERTIES;
+ prop.next = nullptr;
+ strncpy(prop.extensionName, ext.name.c_str(), XR_MAX_EXTENSION_NAME_SIZE - 1);
+ prop.extensionName[XR_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
+ prop.extensionVersion = ext.extension_version;
+ props.push_back(prop);
+ }
+ }
+}
+
+// Return any instance extensions found in the manifest files in the proper form for
+// OpenXR (XrExtensionProperties).
+void ManifestFile::GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props) {
+ GetExtensionProperties(_instance_extensions, props);
+}
+
+const std::string &ManifestFile::GetFunctionName(const std::string &func_name) const {
+ if (!_functions_renamed.empty()) {
+ auto found = _functions_renamed.find(func_name);
+ if (found != _functions_renamed.end()) {
+ return found->second;
+ }
+ }
+ return func_name;
+}
+
+RuntimeManifestFile::RuntimeManifestFile(const std::string &filename, const std::string &library_path)
+ : ManifestFile(MANIFEST_TYPE_RUNTIME, filename, library_path) {}
+
+static void ParseExtension(Json::Value const &ext, std::vector<ExtensionListing> &extensions) {
+ Json::Value ext_name = ext["name"];
+ Json::Value ext_version = ext["extension_version"];
+
+ // Allow "extension_version" as a String or a UInt to maintain backwards compatibility, even though it should be a String.
+ // Internal Issue 1411: https://gitlab.khronos.org/openxr/openxr/-/issues/1411
+ // Internal MR !1867: https://gitlab.khronos.org/openxr/openxr/-/merge_requests/1867
+ if (ext_name.isString() && (ext_version.isString() || ext_version.isUInt())) {
+ ExtensionListing ext_listing = {};
+ ext_listing.name = ext_name.asString();
+ if (ext_version.isUInt()) {
+ ext_listing.extension_version = ext_version.asUInt();
+ } else {
+ ext_listing.extension_version = atoi(ext_version.asString().c_str());
+ }
+ extensions.push_back(ext_listing);
+ }
+}
+
+void ManifestFile::ParseCommon(Json::Value const &root_node) {
+ const Json::Value &inst_exts = root_node["instance_extensions"];
+ if (!inst_exts.isNull() && inst_exts.isArray()) {
+ for (const auto &ext : inst_exts) {
+ ParseExtension(ext, _instance_extensions);
+ }
+ }
+ const Json::Value &funcs_renamed = root_node["functions"];
+ if (!funcs_renamed.isNull() && !funcs_renamed.empty()) {
+ for (Json::ValueConstIterator func_it = funcs_renamed.begin(); func_it != funcs_renamed.end(); ++func_it) {
+ if (!(*func_it).isString()) {
+ LoaderLogger::LogWarningMessage(
+ "", "ManifestFile::ParseCommon " + _filename + " \"functions\" section contains non-string values.");
+ continue;
+ }
+ std::string original_name = func_it.key().asString();
+ std::string new_name = (*func_it).asString();
+ _functions_renamed.emplace(original_name, new_name);
+ }
+ }
+}
+
+void RuntimeManifestFile::CreateIfValid(std::string const &filename,
+ std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
+ std::ifstream json_stream(filename, std::ifstream::in);
+
+ LoaderLogger::LogInfoMessage("", "RuntimeManifestFile::CreateIfValid - attempting to load " + filename);
+ std::ostringstream error_ss("RuntimeManifestFile::CreateIfValid ");
+ if (!json_stream.is_open()) {
+ error_ss << "failed to open " << filename << ". Does it exist?";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ Json::CharReaderBuilder builder;
+ std::string errors;
+ Json::Value root_node = Json::nullValue;
+ if (!Json::parseFromStream(builder, json_stream, &root_node, &errors) || !root_node.isObject()) {
+ error_ss << "failed to parse " << filename << ".";
+ if (!errors.empty()) {
+ error_ss << " (Error message: " << errors << ")";
+ }
+ error_ss << " Is it a valid runtime manifest file?";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+
+ CreateIfValid(root_node, filename, manifest_files);
+}
+
+void RuntimeManifestFile::CreateIfValid(const Json::Value &root_node, const std::string &filename,
+ std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
+ std::ostringstream error_ss("RuntimeManifestFile::CreateIfValid ");
+ JsonVersion file_version = {};
+ if (!ManifestFile::IsValidJson(root_node, file_version)) {
+ error_ss << "isValidJson indicates " << filename << " is not a valid manifest file.";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ const Json::Value &runtime_root_node = root_node["runtime"];
+ // The Runtime manifest file needs the "runtime" root as well as a sub-node for "library_path". If any of those aren't there,
+ // fail.
+ if (runtime_root_node.isNull() || runtime_root_node["library_path"].isNull() || !runtime_root_node["library_path"].isString()) {
+ error_ss << filename << " is missing required fields. Verify all proper fields exist.";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+
+ std::string lib_path = runtime_root_node["library_path"].asString();
+
+ // If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
+ // global library path.
+ if (lib_path.find('\\') != std::string::npos || lib_path.find('/') != std::string::npos) {
+ // If the library_path is an absolute path, just use that if it exists
+ if (FileSysUtilsIsAbsolutePath(lib_path)) {
+ if (!FileSysUtilsPathExists(lib_path)) {
+ error_ss << filename << " library " << lib_path << " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ } else {
+ // Otherwise, treat the library path as a relative path based on the JSON file.
+ std::string canonical_path;
+ std::string combined_path;
+ std::string file_parent;
+ // Search relative to the real manifest file, not relative to the symlink
+ if (!FileSysUtilsGetCanonicalPath(filename, canonical_path)) {
+ // Give relative to the non-canonical path a chance
+ canonical_path = filename;
+ }
+ if (!FileSysUtilsGetParentPath(canonical_path, file_parent) ||
+ !FileSysUtilsCombinePaths(file_parent, lib_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
+ error_ss << filename << " library " << combined_path << " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ lib_path = combined_path;
+ }
+ }
+
+ // Add this runtime manifest file
+ manifest_files.emplace_back(new RuntimeManifestFile(filename, lib_path));
+
+ // Add any extensions to it after the fact.
+ // Handle any renamed functions
+ manifest_files.back()->ParseCommon(runtime_root_node);
+}
+
+// Find all manifest files in the appropriate search paths/registries for the given type.
+XrResult RuntimeManifestFile::FindManifestFiles(std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files) {
+ XrResult result = XR_SUCCESS;
+ std::string filename = PlatformUtilsGetSecureEnv(OPENXR_RUNTIME_JSON_ENV_VAR);
+ if (!filename.empty()) {
+ LoaderLogger::LogInfoMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - using environment variable override runtime file " + filename);
+ } else {
+#ifdef XR_OS_WINDOWS
+ std::vector<std::string> filenames;
+ ReadRuntimeDataFilesInRegistry("", "ActiveRuntime", filenames);
+ if (filenames.size() == 0) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to find active runtime file in registry");
+ return XR_ERROR_RUNTIME_UNAVAILABLE;
+ }
+ if (filenames.size() > 1) {
+ LoaderLogger::LogWarningMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - found too many default runtime files in registry");
+ }
+ filename = filenames[0];
+ LoaderLogger::LogInfoMessage("",
+ "RuntimeManifestFile::FindManifestFiles - using registry-specified runtime file " + filename);
+#elif defined(XR_OS_LINUX)
+ const std::string relative_path =
+ "openxr/" + std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) + "/active_runtime.json";
+ if (!FindXDGConfigFile(relative_path, filename)) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
+ return XR_ERROR_RUNTIME_UNAVAILABLE;
+ }
+#else
+
+#if defined(XR_KHR_LOADER_INIT_SUPPORT)
+ Json::Value virtualManifest;
+ result = GetPlatformRuntimeVirtualManifest(virtualManifest);
+ if (XR_SUCCESS == result) {
+ RuntimeManifestFile::CreateIfValid(virtualManifest, "", manifest_files);
+ return result;
+ }
+#endif // defined(XR_KHR_LOADER_INIT_SUPPORT)
+ if (!PlatformGetGlobalRuntimeFileName(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION), filename)) {
+ LoaderLogger::LogErrorMessage(
+ "", "RuntimeManifestFile::FindManifestFiles - failed to determine active runtime file path for this environment");
+ return XR_ERROR_RUNTIME_UNAVAILABLE;
+ }
+ result = XR_SUCCESS;
+ LoaderLogger::LogInfoMessage("", "RuntimeManifestFile::FindManifestFiles - using global runtime file " + filename);
+#endif
+ }
+ RuntimeManifestFile::CreateIfValid(filename, manifest_files);
+
+ return result;
+}
+
+ApiLayerManifestFile::ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
+ const std::string &description, const JsonVersion &api_version,
+ const uint32_t &implementation_version, const std::string &library_path)
+ : ManifestFile(type, filename, library_path),
+ _api_version(api_version),
+ _layer_name(layer_name),
+ _description(description),
+ _implementation_version(implementation_version) {}
+
+void ApiLayerManifestFile::CreateIfValid(ManifestFileType type, const std::string &filename,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
+ std::ifstream json_stream(filename, std::ifstream::in);
+
+ std::ostringstream error_ss("ApiLayerManifestFile::CreateIfValid ");
+ if (!json_stream.is_open()) {
+ error_ss << "failed to open " << filename << ". Does it exist?";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+
+ Json::CharReaderBuilder builder;
+ std::string errors;
+ Json::Value root_node = Json::nullValue;
+ if (!Json::parseFromStream(builder, json_stream, &root_node, &errors) || !root_node.isObject()) {
+ error_ss << "failed to parse " << filename << ".";
+ if (!errors.empty()) {
+ error_ss << " (Error message: " << errors << ")";
+ }
+ error_ss << " Is it a valid layer manifest file?";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ JsonVersion file_version = {};
+ if (!ManifestFile::IsValidJson(root_node, file_version)) {
+ error_ss << "isValidJson indicates " << filename << " is not a valid manifest file.";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+
+ Json::Value layer_root_node = root_node["api_layer"];
+
+ // The API Layer manifest file needs the "api_layer" root as well as other sub-nodes.
+ // If any of those aren't there, fail.
+ if (layer_root_node.isNull() || layer_root_node["name"].isNull() || !layer_root_node["name"].isString() ||
+ layer_root_node["api_version"].isNull() || !layer_root_node["api_version"].isString() ||
+ layer_root_node["library_path"].isNull() || !layer_root_node["library_path"].isString() ||
+ layer_root_node["implementation_version"].isNull() || !layer_root_node["implementation_version"].isString()) {
+ error_ss << filename << " is missing required fields. Verify all proper fields exist.";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ if (MANIFEST_TYPE_IMPLICIT_API_LAYER == type) {
+ bool enabled = true;
+ // Implicit layers require the disable environment variable.
+ if (layer_root_node["disable_environment"].isNull() || !layer_root_node["disable_environment"].isString()) {
+ error_ss << "Implicit layer " << filename << " is missing \"disable_environment\"";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ // Check if there's an enable environment variable provided
+ if (!layer_root_node["enable_environment"].isNull() && layer_root_node["enable_environment"].isString()) {
+ std::string env_var = layer_root_node["enable_environment"].asString();
+ // If it's not set in the environment, disable the layer
+ if (!PlatformUtilsGetEnvSet(env_var.c_str())) {
+ enabled = false;
+ }
+ }
+ // Check for the disable environment variable, which must be provided in the JSON
+ std::string env_var = layer_root_node["disable_environment"].asString();
+ // If the env var is set, disable the layer. Disable env var overrides enable above
+ if (PlatformUtilsGetEnvSet(env_var.c_str())) {
+ enabled = false;
+ }
+
+ // Not enabled, so pretend like it isn't even there.
+ if (!enabled) {
+ error_ss << "Implicit layer " << filename << " is disabled";
+ LoaderLogger::LogInfoMessage("", error_ss.str());
+ return;
+ }
+ }
+ std::string layer_name = layer_root_node["name"].asString();
+ std::string api_version_string = layer_root_node["api_version"].asString();
+ JsonVersion api_version = {};
+ const int num_fields = sscanf(api_version_string.c_str(), "%u.%u", &api_version.major, &api_version.minor);
+ api_version.patch = 0;
+
+ if ((num_fields != 2) || (api_version.major == 0 && api_version.minor == 0) ||
+ api_version.major > XR_VERSION_MAJOR(XR_CURRENT_API_VERSION)) {
+ error_ss << "layer " << filename << " has invalid API Version. Skipping layer.";
+ LoaderLogger::LogWarningMessage("", error_ss.str());
+ return;
+ }
+
+ uint32_t implementation_version = atoi(layer_root_node["implementation_version"].asString().c_str());
+ std::string library_path = layer_root_node["library_path"].asString();
+
+ // If the library_path variable has no directory symbol, it's just a file name and should be accessible on the
+ // global library path.
+ if (library_path.find('\\') != std::string::npos || library_path.find('/') != std::string::npos) {
+ // If the library_path is an absolute path, just use that if it exists
+ if (FileSysUtilsIsAbsolutePath(library_path)) {
+ if (!FileSysUtilsPathExists(library_path)) {
+ error_ss << filename << " library " << library_path << " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ } else {
+ // Otherwise, treat the library path as a relative path based on the JSON file.
+ std::string combined_path;
+ std::string file_parent;
+ if (!FileSysUtilsGetParentPath(filename, file_parent) ||
+ !FileSysUtilsCombinePaths(file_parent, library_path, combined_path) || !FileSysUtilsPathExists(combined_path)) {
+ error_ss << filename << " library " << combined_path << " does not appear to exist";
+ LoaderLogger::LogErrorMessage("", error_ss.str());
+ return;
+ }
+ library_path = combined_path;
+ }
+ }
+
+ std::string description;
+ if (!layer_root_node["description"].isNull() && layer_root_node["description"].isString()) {
+ description = layer_root_node["description"].asString();
+ }
+
+ // Add this layer manifest file
+ manifest_files.emplace_back(
+ new ApiLayerManifestFile(type, filename, layer_name, description, api_version, implementation_version, library_path));
+
+ // Add any extensions to it after the fact.
+ manifest_files.back()->ParseCommon(layer_root_node);
+}
+
+void ApiLayerManifestFile::PopulateApiLayerProperties(XrApiLayerProperties &props) const {
+ props.layerVersion = _implementation_version;
+ props.specVersion = XR_MAKE_VERSION(_api_version.major, _api_version.minor, _api_version.patch);
+ strncpy(props.layerName, _layer_name.c_str(), XR_MAX_API_LAYER_NAME_SIZE - 1);
+ if (_layer_name.size() >= XR_MAX_API_LAYER_NAME_SIZE - 1) {
+ props.layerName[XR_MAX_API_LAYER_NAME_SIZE - 1] = '\0';
+ }
+ strncpy(props.description, _description.c_str(), XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1);
+ if (_description.size() >= XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1) {
+ props.description[XR_MAX_API_LAYER_DESCRIPTION_SIZE - 1] = '\0';
+ }
+}
+
+// Find all layer manifest files in the appropriate search paths/registries for the given type.
+XrResult ApiLayerManifestFile::FindManifestFiles(ManifestFileType type,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files) {
+ std::string relative_path;
+ std::string override_env_var;
+ std::string registry_location;
+
+ // Add the appropriate top-level folders for the relative path. These should be
+ // the string "openxr/" followed by the API major version as a string.
+ relative_path = OPENXR_RELATIVE_PATH;
+ relative_path += std::to_string(XR_VERSION_MAJOR(XR_CURRENT_API_VERSION));
+
+ switch (type) {
+ case MANIFEST_TYPE_IMPLICIT_API_LAYER:
+ relative_path += OPENXR_IMPLICIT_API_LAYER_RELATIVE_PATH;
+ override_env_var = "";
+#ifdef XR_OS_WINDOWS
+ registry_location = OPENXR_IMPLICIT_API_LAYER_REGISTRY_LOCATION;
+#endif
+ break;
+ case MANIFEST_TYPE_EXPLICIT_API_LAYER:
+ relative_path += OPENXR_EXPLICIT_API_LAYER_RELATIVE_PATH;
+ override_env_var = OPENXR_API_LAYER_PATH_ENV_VAR;
+#ifdef XR_OS_WINDOWS
+ registry_location = OPENXR_EXPLICIT_API_LAYER_REGISTRY_LOCATION;
+#endif
+ break;
+ default:
+ LoaderLogger::LogErrorMessage("", "ApiLayerManifestFile::FindManifestFiles - unknown manifest file requested");
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+
+ bool override_active = false;
+ std::vector<std::string> filenames;
+ ReadDataFilesInSearchPaths(override_env_var, relative_path, override_active, filenames);
+
+#ifdef XR_OS_WINDOWS
+ // Read the registry if the override wasn't active.
+ if (!override_active) {
+ ReadLayerDataFilesInRegistry(registry_location, filenames);
+ }
+#endif
+
+ for (std::string &cur_file : filenames) {
+ ApiLayerManifestFile::CreateIfValid(type, cur_file, manifest_files);
+ }
+
+ return XR_SUCCESS;
+}
diff --git a/thirdparty/openxr/src/loader/manifest_file.hpp b/thirdparty/openxr/src/loader/manifest_file.hpp
new file mode 100644
index 0000000000..0d04886d84
--- /dev/null
+++ b/thirdparty/openxr/src/loader/manifest_file.hpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2017 The Khronos Group Inc.
+// Copyright (c) 2017 Valve Corporation
+// Copyright (c) 2017 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include <openxr/openxr.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+namespace Json {
+class Value;
+}
+
+enum ManifestFileType {
+ MANIFEST_TYPE_UNDEFINED = 0,
+ MANIFEST_TYPE_RUNTIME,
+ MANIFEST_TYPE_IMPLICIT_API_LAYER,
+ MANIFEST_TYPE_EXPLICIT_API_LAYER,
+};
+
+struct JsonVersion {
+ uint32_t major;
+ uint32_t minor;
+ uint32_t patch;
+};
+
+struct ExtensionListing {
+ std::string name;
+ uint32_t extension_version;
+};
+
+// ManifestFile class -
+// Base class responsible for finding and parsing manifest files.
+class ManifestFile {
+ public:
+ // Non-copyable
+ ManifestFile(const ManifestFile &) = delete;
+ ManifestFile &operator=(const ManifestFile &) = delete;
+
+ ManifestFileType Type() const { return _type; }
+ const std::string &Filename() const { return _filename; }
+ const std::string &LibraryPath() const { return _library_path; }
+ void GetInstanceExtensionProperties(std::vector<XrExtensionProperties> &props);
+ const std::string &GetFunctionName(const std::string &func_name) const;
+
+ protected:
+ ManifestFile(ManifestFileType type, const std::string &filename, const std::string &library_path);
+ void ParseCommon(Json::Value const &root_node);
+ static bool IsValidJson(const Json::Value &root, JsonVersion &version);
+
+ private:
+ std::string _filename;
+ ManifestFileType _type;
+ std::string _library_path;
+ std::vector<ExtensionListing> _instance_extensions;
+ std::unordered_map<std::string, std::string> _functions_renamed;
+};
+
+// RuntimeManifestFile class -
+// Responsible for finding and parsing Runtime-specific manifest files.
+class RuntimeManifestFile : public ManifestFile {
+ public:
+ // Factory method
+ static XrResult FindManifestFiles(std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
+
+ private:
+ RuntimeManifestFile(const std::string &filename, const std::string &library_path);
+ static void CreateIfValid(const std::string &filename, std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
+ static void CreateIfValid(const Json::Value &root_node, const std::string &filename,
+ std::vector<std::unique_ptr<RuntimeManifestFile>> &manifest_files);
+};
+
+// ApiLayerManifestFile class -
+// Responsible for finding and parsing API Layer-specific manifest files.
+class ApiLayerManifestFile : public ManifestFile {
+ public:
+ // Factory method
+ static XrResult FindManifestFiles(ManifestFileType type, std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
+
+ const std::string &LayerName() const { return _layer_name; }
+ void PopulateApiLayerProperties(XrApiLayerProperties &props) const;
+
+ private:
+ ApiLayerManifestFile(ManifestFileType type, const std::string &filename, const std::string &layer_name,
+ const std::string &description, const JsonVersion &api_version, const uint32_t &implementation_version,
+ const std::string &library_path);
+ static void CreateIfValid(ManifestFileType type, const std::string &filename,
+ std::vector<std::unique_ptr<ApiLayerManifestFile>> &manifest_files);
+
+ JsonVersion _api_version;
+ std::string _layer_name;
+ std::string _description;
+ uint32_t _implementation_version;
+};
diff --git a/thirdparty/openxr/src/loader/runtime_interface.cpp b/thirdparty/openxr/src/loader/runtime_interface.cpp
new file mode 100644
index 0000000000..1a35ba013a
--- /dev/null
+++ b/thirdparty/openxr/src/loader/runtime_interface.cpp
@@ -0,0 +1,493 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#include "runtime_interface.hpp"
+
+#include "manifest_file.hpp"
+#include "loader_interfaces.h"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "xr_generated_dispatch_table.h"
+
+#include <openxr/openxr.h>
+
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#ifdef XR_USE_PLATFORM_ANDROID
+#include "android_utilities.h"
+#include <json/value.h>
+#endif // XR_USE_PLATFORM_ANDROID
+
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+namespace {
+/*!
+ * Stores a copy of the data passed to the xrInitializeLoaderKHR function in a singleton.
+ */
+class LoaderInitData {
+ public:
+ /*!
+ * Singleton accessor.
+ */
+ static LoaderInitData& instance() {
+ static LoaderInitData obj;
+ return obj;
+ }
+
+#ifdef XR_USE_PLATFORM_ANDROID
+ /*!
+ * Type alias for the platform-specific structure type.
+ */
+ using StructType = XrLoaderInitInfoAndroidKHR;
+#endif
+
+ /*!
+ * Get our copy of the data, casted to pass to the runtime's matching method.
+ */
+ const XrLoaderInitInfoBaseHeaderKHR* getParam() const { return reinterpret_cast<const XrLoaderInitInfoBaseHeaderKHR*>(&_data); }
+
+ /*!
+ * Get the data via its real structure type.
+ */
+ const StructType& getData() const { return _data; }
+
+ /*!
+ * Has this been correctly initialized?
+ */
+ bool initialized() const noexcept { return _initialized; }
+
+ /*!
+ * Initialize loader data - called by InitializeLoader() and thus ultimately by the loader's xrInitializeLoaderKHR
+ * implementation. Each platform that needs this extension will provide an implementation of this.
+ */
+ XrResult initialize(const XrLoaderInitInfoBaseHeaderKHR* info);
+
+ private:
+ //! Private constructor, forces use of singleton accessor.
+ LoaderInitData() = default;
+ //! Platform-specific init data
+ StructType _data = {};
+ //! Flag for indicating whether _data is valid.
+ bool _initialized = false;
+};
+
+#ifdef XR_USE_PLATFORM_ANDROID
+// Check and copy the Android-specific init data.
+XrResult LoaderInitData::initialize(const XrLoaderInitInfoBaseHeaderKHR* info) {
+ if (info->type != XR_TYPE_LOADER_INIT_INFO_ANDROID_KHR) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ auto cast_info = reinterpret_cast<XrLoaderInitInfoAndroidKHR const*>(info);
+
+ if (cast_info->applicationVM == nullptr) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ if (cast_info->applicationContext == nullptr) {
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ _data = *cast_info;
+ jni::init((jni::JavaVM*)_data.applicationVM);
+ _data.next = nullptr;
+ _initialized = true;
+ return XR_SUCCESS;
+}
+#endif // XR_USE_PLATFORM_ANDROID
+} // namespace
+
+XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo) {
+ return LoaderInitData::instance().initialize(loaderInitInfo);
+}
+
+#endif // XR_KHR_LOADER_INIT_SUPPORT
+
+#ifdef XR_USE_PLATFORM_ANDROID
+XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest) {
+ using wrap::android::content::Context;
+ auto& initData = LoaderInitData::instance();
+ if (!initData.initialized()) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+ auto context = Context(reinterpret_cast<jobject>(initData.getData().applicationContext));
+ if (context.isNull()) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+ Json::Value virtualManifest;
+ if (0 != openxr_android::getActiveRuntimeVirtualManifest(context, virtualManifest)) {
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+ out_manifest = virtualManifest;
+ return XR_SUCCESS;
+}
+#endif // XR_USE_PLATFORM_ANDROID
+
+XrResult RuntimeInterface::TryLoadingSingleRuntime(const std::string& openxr_command,
+ std::unique_ptr<RuntimeManifestFile>& manifest_file) {
+ LoaderPlatformLibraryHandle runtime_library = LoaderPlatformLibraryOpen(manifest_file->LibraryPath());
+ if (nullptr == runtime_library) {
+ std::string library_message = LoaderPlatformLibraryOpenError(manifest_file->LibraryPath());
+ std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ warning_message += manifest_file->Filename();
+ warning_message += ", failed to load with message \"";
+ warning_message += library_message;
+ warning_message += "\"";
+ LoaderLogger::LogErrorMessage(openxr_command, warning_message);
+ return XR_ERROR_FILE_ACCESS_ERROR;
+ }
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+ if (!LoaderInitData::instance().initialized()) {
+ LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntime skipping manifest file " +
+ manifest_file->Filename() +
+ " because xrInitializeLoaderKHR was not yet called.");
+
+ LoaderPlatformLibraryClose(runtime_library);
+ return XR_ERROR_VALIDATION_FAILURE;
+ }
+ bool forwardedInitLoader = false;
+ {
+ // If we have xrInitializeLoaderKHR exposed as an export, forward call to it.
+ const auto function_name = manifest_file->GetFunctionName("xrInitializeLoaderKHR");
+ auto initLoader =
+ reinterpret_cast<PFN_xrInitializeLoaderKHR>(LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
+ if (initLoader != nullptr) {
+ // we found the entry point one way or another.
+ LoaderLogger::LogInfoMessage(openxr_command,
+ "RuntimeInterface::LoadRuntime forwarding xrInitializeLoaderKHR call to runtime before "
+ "calling xrNegotiateLoaderRuntimeInterface.");
+ XrResult res = initLoader(LoaderInitData::instance().getParam());
+ if (!XR_SUCCEEDED(res)) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "RuntimeInterface::LoadRuntime forwarded call to xrInitializeLoaderKHR failed.");
+
+ LoaderPlatformLibraryClose(runtime_library);
+ return res;
+ }
+ forwardedInitLoader = true;
+ }
+ }
+#endif
+
+ // Get and settle on an runtime interface version (using any provided name if required).
+ std::string function_name = manifest_file->GetFunctionName("xrNegotiateLoaderRuntimeInterface");
+ auto negotiate =
+ reinterpret_cast<PFN_xrNegotiateLoaderRuntimeInterface>(LoaderPlatformLibraryGetProcAddr(runtime_library, function_name));
+
+ // Loader info for negotiation
+ XrNegotiateLoaderInfo loader_info = {};
+ loader_info.structType = XR_LOADER_INTERFACE_STRUCT_LOADER_INFO;
+ loader_info.structVersion = XR_LOADER_INFO_STRUCT_VERSION;
+ loader_info.structSize = sizeof(XrNegotiateLoaderInfo);
+ loader_info.minInterfaceVersion = 1;
+ loader_info.maxInterfaceVersion = XR_CURRENT_LOADER_RUNTIME_VERSION;
+ loader_info.minApiVersion = XR_MAKE_VERSION(1, 0, 0);
+ loader_info.maxApiVersion = XR_MAKE_VERSION(1, 0x3ff, 0xfff); // Maximum allowed version for this major version.
+
+ // Set up the runtime return structure
+ XrNegotiateRuntimeRequest runtime_info = {};
+ runtime_info.structType = XR_LOADER_INTERFACE_STRUCT_RUNTIME_REQUEST;
+ runtime_info.structVersion = XR_RUNTIME_INFO_STRUCT_VERSION;
+ runtime_info.structSize = sizeof(XrNegotiateRuntimeRequest);
+
+ // Skip calling the negotiate function and fail if the function pointer
+ // could not get loaded
+ XrResult res = XR_ERROR_RUNTIME_FAILURE;
+ if (nullptr != negotiate) {
+ res = negotiate(&loader_info, &runtime_info);
+ }
+ // If we supposedly succeeded, but got a nullptr for GetInstanceProcAddr
+ // then something still went wrong, so return with an error.
+ if (XR_SUCCEEDED(res)) {
+ uint32_t runtime_major = XR_VERSION_MAJOR(runtime_info.runtimeApiVersion);
+ uint32_t runtime_minor = XR_VERSION_MINOR(runtime_info.runtimeApiVersion);
+ uint32_t loader_major = XR_VERSION_MAJOR(XR_CURRENT_API_VERSION);
+ if (nullptr == runtime_info.getInstanceProcAddr) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", negotiation succeeded but returned NULL getInstanceProcAddr";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ } else if (0 >= runtime_info.runtimeInterfaceVersion ||
+ XR_CURRENT_LOADER_RUNTIME_VERSION < runtime_info.runtimeInterfaceVersion) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", negotiation succeeded but returned invalid interface version";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ } else if (runtime_major != loader_major || (runtime_major == 0 && runtime_minor == 0)) {
+ std::string error_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ error_message += manifest_file->Filename();
+ error_message += ", OpenXR version returned not compatible with this loader";
+ LoaderLogger::LogErrorMessage(openxr_command, error_message);
+ res = XR_ERROR_FILE_CONTENTS_INVALID;
+ }
+ }
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+ if (XR_SUCCEEDED(res) && !forwardedInitLoader) {
+ // Forward initialize loader call, where possible and if we did not do so before.
+ PFN_xrVoidFunction initializeVoid = nullptr;
+ PFN_xrInitializeLoaderKHR initialize = nullptr;
+
+ // Now we may try asking xrGetInstanceProcAddr
+ if (XR_SUCCEEDED(runtime_info.getInstanceProcAddr(XR_NULL_HANDLE, "xrInitializeLoaderKHR", &initializeVoid))) {
+ if (initializeVoid == nullptr) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "RuntimeInterface::LoadRuntime got success from xrGetInstanceProcAddr "
+ "for xrInitializeLoaderKHR, but output a null pointer.");
+ res = XR_ERROR_RUNTIME_FAILURE;
+ } else {
+ initialize = reinterpret_cast<PFN_xrInitializeLoaderKHR>(initializeVoid);
+ }
+ }
+ if (initialize != nullptr) {
+ // we found the entry point one way or another.
+ LoaderLogger::LogInfoMessage(openxr_command,
+ "RuntimeInterface::LoadRuntime forwarding xrInitializeLoaderKHR call to runtime after "
+ "calling xrNegotiateLoaderRuntimeInterface.");
+ res = initialize(LoaderInitData::instance().getParam());
+ if (!XR_SUCCEEDED(res)) {
+ LoaderLogger::LogErrorMessage(openxr_command,
+ "RuntimeInterface::LoadRuntime forwarded call to xrInitializeLoaderKHR failed.");
+ }
+ }
+ }
+#endif
+ if (XR_FAILED(res)) {
+ std::string warning_message = "RuntimeInterface::LoadRuntime skipping manifest file ";
+ warning_message += manifest_file->Filename();
+ warning_message += ", negotiation failed with error ";
+ warning_message += std::to_string(res);
+ LoaderLogger::LogErrorMessage(openxr_command, warning_message);
+ LoaderPlatformLibraryClose(runtime_library);
+ return res;
+ }
+
+ std::string info_message = "RuntimeInterface::LoadRuntime succeeded loading runtime defined in manifest file ";
+ info_message += manifest_file->Filename();
+ info_message += " using interface version ";
+ info_message += std::to_string(runtime_info.runtimeInterfaceVersion);
+ info_message += " and OpenXR API version ";
+ info_message += std::to_string(XR_VERSION_MAJOR(runtime_info.runtimeApiVersion));
+ info_message += ".";
+ info_message += std::to_string(XR_VERSION_MINOR(runtime_info.runtimeApiVersion));
+ LoaderLogger::LogInfoMessage(openxr_command, info_message);
+
+ // Use this runtime
+ GetInstance().reset(new RuntimeInterface(runtime_library, runtime_info.getInstanceProcAddr));
+
+ // Grab the list of extensions this runtime supports for easy filtering after the
+ // xrCreateInstance call
+ std::vector<std::string> supported_extensions;
+ std::vector<XrExtensionProperties> extension_properties;
+ GetInstance()->GetInstanceExtensionProperties(extension_properties);
+ supported_extensions.reserve(extension_properties.size());
+ for (XrExtensionProperties ext_prop : extension_properties) {
+ supported_extensions.emplace_back(ext_prop.extensionName);
+ }
+ GetInstance()->SetSupportedExtensions(supported_extensions);
+
+ return XR_SUCCESS;
+}
+
+XrResult RuntimeInterface::LoadRuntime(const std::string& openxr_command) {
+ // If something's already loaded, we're done here.
+ if (GetInstance() != nullptr) {
+ return XR_SUCCESS;
+ }
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+
+ if (!LoaderInitData::instance().initialized()) {
+ LoaderLogger::LogErrorMessage(
+ openxr_command, "RuntimeInterface::LoadRuntime cannot run because xrInitializeLoaderKHR was not successfully called.");
+ return XR_ERROR_INITIALIZATION_FAILED;
+ }
+#endif // XR_KHR_LOADER_INIT_SUPPORT
+
+ std::vector<std::unique_ptr<RuntimeManifestFile>> runtime_manifest_files = {};
+
+ // Find the available runtimes which we may need to report information for.
+ XrResult last_error = RuntimeManifestFile::FindManifestFiles(runtime_manifest_files);
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - unknown error");
+ } else {
+ last_error = XR_ERROR_RUNTIME_UNAVAILABLE;
+ for (std::unique_ptr<RuntimeManifestFile>& manifest_file : runtime_manifest_files) {
+ last_error = RuntimeInterface::TryLoadingSingleRuntime(openxr_command, manifest_file);
+ if (XR_SUCCEEDED(last_error)) {
+ break;
+ }
+ }
+ }
+
+ // Unsuccessful in loading any runtime, throw the runtime unavailable message.
+ if (XR_FAILED(last_error)) {
+ LoaderLogger::LogErrorMessage(openxr_command, "RuntimeInterface::LoadRuntimes - failed to load a runtime");
+ last_error = XR_ERROR_RUNTIME_UNAVAILABLE;
+ }
+
+ return last_error;
+}
+
+void RuntimeInterface::UnloadRuntime(const std::string& openxr_command) {
+ if (GetInstance()) {
+ LoaderLogger::LogInfoMessage(openxr_command, "RuntimeInterface::UnloadRuntime - Unloading RuntimeInterface");
+ GetInstance().reset();
+ }
+}
+
+XrResult RuntimeInterface::GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function) {
+ return GetInstance()->_get_instance_proc_addr(instance, name, function);
+}
+
+const XrGeneratedDispatchTable* RuntimeInterface::GetDispatchTable(XrInstance instance) {
+ XrGeneratedDispatchTable* table = nullptr;
+ std::lock_guard<std::mutex> mlock(GetInstance()->_dispatch_table_mutex);
+ auto it = GetInstance()->_dispatch_table_map.find(instance);
+ if (it != GetInstance()->_dispatch_table_map.end()) {
+ table = it->second.get();
+ }
+ return table;
+}
+
+const XrGeneratedDispatchTable* RuntimeInterface::GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger) {
+ XrInstance runtime_instance = XR_NULL_HANDLE;
+ {
+ std::lock_guard<std::mutex> mlock(GetInstance()->_messenger_to_instance_mutex);
+ auto it = GetInstance()->_messenger_to_instance_map.find(messenger);
+ if (it != GetInstance()->_messenger_to_instance_map.end()) {
+ runtime_instance = it->second;
+ }
+ }
+ return GetDispatchTable(runtime_instance);
+}
+
+RuntimeInterface::RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instance_proc_addr)
+ : _runtime_library(runtime_library), _get_instance_proc_addr(get_instance_proc_addr) {}
+
+RuntimeInterface::~RuntimeInterface() {
+ std::string info_message = "RuntimeInterface being destroyed.";
+ LoaderLogger::LogInfoMessage("", info_message);
+ {
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ _dispatch_table_map.clear();
+ }
+ LoaderPlatformLibraryClose(_runtime_library);
+}
+
+void RuntimeInterface::GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties) {
+ std::vector<XrExtensionProperties> runtime_extension_properties;
+ PFN_xrEnumerateInstanceExtensionProperties rt_xrEnumerateInstanceExtensionProperties;
+ _get_instance_proc_addr(XR_NULL_HANDLE, "xrEnumerateInstanceExtensionProperties",
+ reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrEnumerateInstanceExtensionProperties));
+ uint32_t count = 0;
+ uint32_t count_output = 0;
+ // Get the count from the runtime
+ rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, nullptr);
+ if (count_output > 0) {
+ runtime_extension_properties.resize(count_output);
+ count = count_output;
+ for (XrExtensionProperties& ext_prop : runtime_extension_properties) {
+ ext_prop.type = XR_TYPE_EXTENSION_PROPERTIES;
+ ext_prop.next = nullptr;
+ }
+ rt_xrEnumerateInstanceExtensionProperties(nullptr, count, &count_output, runtime_extension_properties.data());
+ }
+ size_t ext_count = runtime_extension_properties.size();
+ size_t props_count = extension_properties.size();
+ for (size_t ext = 0; ext < ext_count; ++ext) {
+ bool found = false;
+ for (size_t prop = 0; prop < props_count; ++prop) {
+ // If we find it, then make sure the spec version matches that of the runtime instead of the
+ // layer.
+ if (strcmp(extension_properties[prop].extensionName, runtime_extension_properties[ext].extensionName) == 0) {
+ // Make sure the spec version used is the runtime's
+ extension_properties[prop].extensionVersion = runtime_extension_properties[ext].extensionVersion;
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ extension_properties.push_back(runtime_extension_properties[ext]);
+ }
+ }
+}
+
+XrResult RuntimeInterface::CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance) {
+ XrResult res = XR_SUCCESS;
+ bool create_succeeded = false;
+ PFN_xrCreateInstance rt_xrCreateInstance;
+ _get_instance_proc_addr(XR_NULL_HANDLE, "xrCreateInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrCreateInstance));
+ res = rt_xrCreateInstance(info, instance);
+ if (XR_SUCCEEDED(res)) {
+ create_succeeded = true;
+ std::unique_ptr<XrGeneratedDispatchTable> dispatch_table(new XrGeneratedDispatchTable());
+ GeneratedXrPopulateDispatchTable(dispatch_table.get(), *instance, _get_instance_proc_addr);
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ _dispatch_table_map[*instance] = std::move(dispatch_table);
+ }
+
+ // If the failure occurred during the populate, clean up the instance we had picked up from the runtime
+ if (XR_FAILED(res) && create_succeeded) {
+ PFN_xrDestroyInstance rt_xrDestroyInstance;
+ _get_instance_proc_addr(*instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
+ rt_xrDestroyInstance(*instance);
+ *instance = XR_NULL_HANDLE;
+ }
+
+ return res;
+}
+
+XrResult RuntimeInterface::DestroyInstance(XrInstance instance) {
+ if (XR_NULL_HANDLE != instance) {
+ // Destroy the dispatch table for this instance first
+ {
+ std::lock_guard<std::mutex> mlock(_dispatch_table_mutex);
+ auto map_iter = _dispatch_table_map.find(instance);
+ if (map_iter != _dispatch_table_map.end()) {
+ _dispatch_table_map.erase(map_iter);
+ }
+ }
+ // Now delete the instance
+ PFN_xrDestroyInstance rt_xrDestroyInstance;
+ _get_instance_proc_addr(instance, "xrDestroyInstance", reinterpret_cast<PFN_xrVoidFunction*>(&rt_xrDestroyInstance));
+ rt_xrDestroyInstance(instance);
+ }
+ return XR_SUCCESS;
+}
+
+bool RuntimeInterface::TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger) {
+ std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
+ _messenger_to_instance_map[messenger] = instance;
+ return true;
+}
+
+void RuntimeInterface::ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger) {
+ if (XR_NULL_HANDLE != messenger) {
+ std::lock_guard<std::mutex> mlock(_messenger_to_instance_mutex);
+ _messenger_to_instance_map.erase(messenger);
+ }
+}
+
+void RuntimeInterface::SetSupportedExtensions(std::vector<std::string>& supported_extensions) {
+ _supported_extensions = supported_extensions;
+}
+
+bool RuntimeInterface::SupportsExtension(const std::string& extension_name) {
+ bool found_prop = false;
+ for (const std::string& supported_extension : _supported_extensions) {
+ if (supported_extension == extension_name) {
+ found_prop = true;
+ break;
+ }
+ }
+ return found_prop;
+}
diff --git a/thirdparty/openxr/src/loader/runtime_interface.hpp b/thirdparty/openxr/src/loader/runtime_interface.hpp
new file mode 100644
index 0000000000..5f49b28abe
--- /dev/null
+++ b/thirdparty/openxr/src/loader/runtime_interface.hpp
@@ -0,0 +1,84 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+//
+// Initial Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+
+#include "loader_platform.hpp"
+
+#include <openxr/openxr.h>
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <mutex>
+#include <memory>
+
+#ifdef XR_USE_PLATFORM_ANDROID
+#define XR_KHR_LOADER_INIT_SUPPORT
+#endif
+
+namespace Json {
+class Value;
+}
+
+#ifdef XR_KHR_LOADER_INIT_SUPPORT
+//! Initialize loader, where required.
+XrResult InitializeLoader(const XrLoaderInitInfoBaseHeaderKHR* loaderInitInfo);
+XrResult GetPlatformRuntimeVirtualManifest(Json::Value& out_manifest);
+#endif
+
+class RuntimeManifestFile;
+struct XrGeneratedDispatchTable;
+
+class RuntimeInterface {
+ public:
+ virtual ~RuntimeInterface();
+
+ // Helper functions for loading and unloading the runtime (but only when necessary)
+ static XrResult LoadRuntime(const std::string& openxr_command);
+ static void UnloadRuntime(const std::string& openxr_command);
+ static RuntimeInterface& GetRuntime() { return *(GetInstance().get()); }
+ static XrResult GetInstanceProcAddr(XrInstance instance, const char* name, PFN_xrVoidFunction* function);
+
+ // Get the direct dispatch table to this runtime, without API layers or loader terminators.
+ static const XrGeneratedDispatchTable* GetDispatchTable(XrInstance instance);
+ static const XrGeneratedDispatchTable* GetDebugUtilsMessengerDispatchTable(XrDebugUtilsMessengerEXT messenger);
+
+ void GetInstanceExtensionProperties(std::vector<XrExtensionProperties>& extension_properties);
+ bool SupportsExtension(const std::string& extension_name);
+ XrResult CreateInstance(const XrInstanceCreateInfo* info, XrInstance* instance);
+ XrResult DestroyInstance(XrInstance instance);
+ bool TrackDebugMessenger(XrInstance instance, XrDebugUtilsMessengerEXT messenger);
+ void ForgetDebugMessenger(XrDebugUtilsMessengerEXT messenger);
+
+ // No default construction
+ RuntimeInterface() = delete;
+
+ // Non-copyable
+ RuntimeInterface(const RuntimeInterface&) = delete;
+ RuntimeInterface& operator=(const RuntimeInterface&) = delete;
+
+ private:
+ RuntimeInterface(LoaderPlatformLibraryHandle runtime_library, PFN_xrGetInstanceProcAddr get_instance_proc_addr);
+ void SetSupportedExtensions(std::vector<std::string>& supported_extensions);
+ static XrResult TryLoadingSingleRuntime(const std::string& openxr_command, std::unique_ptr<RuntimeManifestFile>& manifest_file);
+
+ static std::unique_ptr<RuntimeInterface>& GetInstance() {
+ static std::unique_ptr<RuntimeInterface> instance;
+ return instance;
+ }
+
+ LoaderPlatformLibraryHandle _runtime_library;
+ PFN_xrGetInstanceProcAddr _get_instance_proc_addr;
+ std::unordered_map<XrInstance, std::unique_ptr<XrGeneratedDispatchTable>> _dispatch_table_map;
+ std::mutex _dispatch_table_mutex;
+ std::unordered_map<XrDebugUtilsMessengerEXT, XrInstance> _messenger_to_instance_map;
+ std::mutex _messenger_to_instance_mutex;
+ std::vector<std::string> _supported_extensions;
+};
diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.cpp b/thirdparty/openxr/src/loader/xr_generated_loader.cpp
new file mode 100644
index 0000000000..2ce323e51f
--- /dev/null
+++ b/thirdparty/openxr/src/loader/xr_generated_loader.cpp
@@ -0,0 +1,700 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See loader_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "xr_generated_loader.hpp"
+
+#include "api_layer_interface.hpp"
+#include "exception_handling.hpp"
+#include "hex_and_handles.h"
+#include "loader_instance.hpp"
+#include "loader_logger.hpp"
+#include "loader_platform.hpp"
+#include "runtime_interface.hpp"
+#include "xr_generated_dispatch_table.h"
+
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+#include <cstring>
+#include <memory>
+#include <new>
+#include <string>
+#include <unordered_map>
+
+
+// Automatically generated instance trampolines and terminators
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInstanceProperties");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetInstanceProperties(instance, instanceProperties);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrPollEvent");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->PollEvent(instance, eventData);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrResultToString");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->ResultToString(instance, value, buffer);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStructureTypeToString");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->StructureTypeToString(instance, value, buffer);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetSystem");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetSystem(instance, getInfo, systemId);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetSystemProperties");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetSystemProperties(instance, systemId, properties);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateEnvironmentBlendModes");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateEnvironmentBlendModes(instance, systemId, viewConfigurationType, environmentBlendModeCapacityInput, environmentBlendModeCountOutput, environmentBlendModes);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateSession");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateSession(instance, createInfo, session);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySession");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->DestroySession(session);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateReferenceSpaces");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateReferenceSpaces(session, spaceCapacityInput, spaceCountOutput, spaces);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateReferenceSpace");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateReferenceSpace(session, createInfo, space);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetReferenceSpaceBoundsRect");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetReferenceSpaceBoundsRect(session, referenceSpaceType, bounds);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateActionSpace");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateActionSpace(session, createInfo, space);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrLocateSpace");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->LocateSpace(space, baseSpace, time, location);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
+ XrSpace space) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySpace");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->DestroySpace(space);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateViewConfigurations");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateViewConfigurations(instance, systemId, viewConfigurationTypeCapacityInput, viewConfigurationTypeCountOutput, viewConfigurationTypes);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetViewConfigurationProperties");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetViewConfigurationProperties(instance, systemId, viewConfigurationType, configurationProperties);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateViewConfigurationViews");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateViewConfigurationViews(instance, systemId, viewConfigurationType, viewCapacityInput, viewCountOutput, views);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateSwapchainFormats");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateSwapchainFormats(session, formatCapacityInput, formatCountOutput, formats);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateSwapchain");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateSwapchain(session, createInfo, swapchain);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
+ XrSwapchain swapchain) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroySwapchain");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->DestroySwapchain(swapchain);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateSwapchainImages");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateSwapchainImages(swapchain, imageCapacityInput, imageCountOutput, images);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrAcquireSwapchainImage");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->AcquireSwapchainImage(swapchain, acquireInfo, index);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrWaitSwapchainImage");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->WaitSwapchainImage(swapchain, waitInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrReleaseSwapchainImage");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->ReleaseSwapchainImage(swapchain, releaseInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrBeginSession");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->BeginSession(session, beginInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEndSession");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EndSession(session);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
+ XrSession session) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrRequestExitSession");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->RequestExitSession(session);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrWaitFrame");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->WaitFrame(session, frameWaitInfo, frameState);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrBeginFrame");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->BeginFrame(session, frameBeginInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEndFrame");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EndFrame(session, frameEndInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrLocateViews");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->LocateViews(session, viewLocateInfo, viewState, viewCapacityInput, viewCountOutput, views);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStringToPath");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->StringToPath(instance, pathString, path);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrPathToString");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->PathToString(instance, path, bufferCapacityInput, bufferCountOutput, buffer);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateActionSet");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateActionSet(instance, createInfo, actionSet);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
+ XrActionSet actionSet) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyActionSet");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->DestroyActionSet(actionSet);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrCreateAction");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->CreateAction(actionSet, createInfo, action);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
+ XrAction action) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrDestroyAction");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->DestroyAction(action);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSuggestInteractionProfileBindings");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->SuggestInteractionProfileBindings(instance, suggestedBindings);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrAttachSessionActionSets");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->AttachSessionActionSets(session, attachInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetCurrentInteractionProfile");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetCurrentInteractionProfile(session, topLevelUserPath, interactionProfile);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateBoolean");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetActionStateBoolean(session, getInfo, state);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateFloat");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetActionStateFloat(session, getInfo, state);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStateVector2f");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetActionStateVector2f(session, getInfo, state);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetActionStatePose");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetActionStatePose(session, getInfo, state);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrSyncActions");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->SyncActions(session, syncInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrEnumerateBoundSourcesForAction");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->EnumerateBoundSourcesForAction(session, enumerateInfo, sourceCapacityInput, sourceCountOutput, sources);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrGetInputSourceLocalizedName");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->GetInputSourceLocalizedName(session, getInfo, bufferCapacityInput, bufferCountOutput, buffer);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrApplyHapticFeedback");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->ApplyHapticFeedback(session, hapticActionInfo, hapticFeedback);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo) XRLOADER_ABI_TRY {
+ LoaderInstance* loader_instance;
+ XrResult result = ActiveLoaderInstance::Get(&loader_instance, "xrStopHapticFeedback");
+ if (XR_SUCCEEDED(result)) {
+ result = loader_instance->DispatchTable()->StopHapticFeedback(session, hapticActionInfo);
+ }
+ return result;
+}
+XRLOADER_ABI_CATCH_FALLBACK
+
+
diff --git a/thirdparty/openxr/src/loader/xr_generated_loader.hpp b/thirdparty/openxr/src/loader/xr_generated_loader.hpp
new file mode 100644
index 0000000000..482cf1e83e
--- /dev/null
+++ b/thirdparty/openxr/src/loader/xr_generated_loader.hpp
@@ -0,0 +1,252 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See loader_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+#include <unordered_map>
+#include <thread>
+#include <mutex>
+
+#include "xr_dependencies.h"
+#include "openxr/openxr.h"
+#include "openxr/openxr_platform.h"
+
+#include "loader_interfaces.h"
+
+#include "loader_instance.hpp"
+
+#include "loader_platform.hpp"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Loader manually generated function prototypes
+
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInstanceProperties(
+ XrInstance instance,
+ XrInstanceProperties* instanceProperties);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPollEvent(
+ XrInstance instance,
+ XrEventDataBuffer* eventData);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrResultToString(
+ XrInstance instance,
+ XrResult value,
+ char buffer[XR_MAX_RESULT_STRING_SIZE]);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStructureTypeToString(
+ XrInstance instance,
+ XrStructureType value,
+ char buffer[XR_MAX_STRUCTURE_NAME_SIZE]);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystem(
+ XrInstance instance,
+ const XrSystemGetInfo* getInfo,
+ XrSystemId* systemId);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetSystemProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrSystemProperties* properties);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateEnvironmentBlendModes(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t environmentBlendModeCapacityInput,
+ uint32_t* environmentBlendModeCountOutput,
+ XrEnvironmentBlendMode* environmentBlendModes);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSession(
+ XrInstance instance,
+ const XrSessionCreateInfo* createInfo,
+ XrSession* session);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySession(
+ XrSession session);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateReferenceSpaces(
+ XrSession session,
+ uint32_t spaceCapacityInput,
+ uint32_t* spaceCountOutput,
+ XrReferenceSpaceType* spaces);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateReferenceSpace(
+ XrSession session,
+ const XrReferenceSpaceCreateInfo* createInfo,
+ XrSpace* space);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetReferenceSpaceBoundsRect(
+ XrSession session,
+ XrReferenceSpaceType referenceSpaceType,
+ XrExtent2Df* bounds);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSpace(
+ XrSession session,
+ const XrActionSpaceCreateInfo* createInfo,
+ XrSpace* space);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateSpace(
+ XrSpace space,
+ XrSpace baseSpace,
+ XrTime time,
+ XrSpaceLocation* location);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySpace(
+ XrSpace space);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurations(
+ XrInstance instance,
+ XrSystemId systemId,
+ uint32_t viewConfigurationTypeCapacityInput,
+ uint32_t* viewConfigurationTypeCountOutput,
+ XrViewConfigurationType* viewConfigurationTypes);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetViewConfigurationProperties(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ XrViewConfigurationProperties* configurationProperties);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateViewConfigurationViews(
+ XrInstance instance,
+ XrSystemId systemId,
+ XrViewConfigurationType viewConfigurationType,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrViewConfigurationView* views);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainFormats(
+ XrSession session,
+ uint32_t formatCapacityInput,
+ uint32_t* formatCountOutput,
+ int64_t* formats);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateSwapchain(
+ XrSession session,
+ const XrSwapchainCreateInfo* createInfo,
+ XrSwapchain* swapchain);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroySwapchain(
+ XrSwapchain swapchain);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateSwapchainImages(
+ XrSwapchain swapchain,
+ uint32_t imageCapacityInput,
+ uint32_t* imageCountOutput,
+ XrSwapchainImageBaseHeader* images);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAcquireSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageAcquireInfo* acquireInfo,
+ uint32_t* index);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageWaitInfo* waitInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrReleaseSwapchainImage(
+ XrSwapchain swapchain,
+ const XrSwapchainImageReleaseInfo* releaseInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginSession(
+ XrSession session,
+ const XrSessionBeginInfo* beginInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndSession(
+ XrSession session);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrRequestExitSession(
+ XrSession session);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrWaitFrame(
+ XrSession session,
+ const XrFrameWaitInfo* frameWaitInfo,
+ XrFrameState* frameState);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrBeginFrame(
+ XrSession session,
+ const XrFrameBeginInfo* frameBeginInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEndFrame(
+ XrSession session,
+ const XrFrameEndInfo* frameEndInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrLocateViews(
+ XrSession session,
+ const XrViewLocateInfo* viewLocateInfo,
+ XrViewState* viewState,
+ uint32_t viewCapacityInput,
+ uint32_t* viewCountOutput,
+ XrView* views);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStringToPath(
+ XrInstance instance,
+ const char* pathString,
+ XrPath* path);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrPathToString(
+ XrInstance instance,
+ XrPath path,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateActionSet(
+ XrInstance instance,
+ const XrActionSetCreateInfo* createInfo,
+ XrActionSet* actionSet);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyActionSet(
+ XrActionSet actionSet);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrCreateAction(
+ XrActionSet actionSet,
+ const XrActionCreateInfo* createInfo,
+ XrAction* action);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrDestroyAction(
+ XrAction action);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSuggestInteractionProfileBindings(
+ XrInstance instance,
+ const XrInteractionProfileSuggestedBinding* suggestedBindings);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrAttachSessionActionSets(
+ XrSession session,
+ const XrSessionActionSetsAttachInfo* attachInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetCurrentInteractionProfile(
+ XrSession session,
+ XrPath topLevelUserPath,
+ XrInteractionProfileState* interactionProfile);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateBoolean(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateBoolean* state);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateFloat(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateFloat* state);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStateVector2f(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStateVector2f* state);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetActionStatePose(
+ XrSession session,
+ const XrActionStateGetInfo* getInfo,
+ XrActionStatePose* state);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrSyncActions(
+ XrSession session,
+ const XrActionsSyncInfo* syncInfo);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrEnumerateBoundSourcesForAction(
+ XrSession session,
+ const XrBoundSourcesForActionEnumerateInfo* enumerateInfo,
+ uint32_t sourceCapacityInput,
+ uint32_t* sourceCountOutput,
+ XrPath* sources);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrGetInputSourceLocalizedName(
+ XrSession session,
+ const XrInputSourceLocalizedNameGetInfo* getInfo,
+ uint32_t bufferCapacityInput,
+ uint32_t* bufferCountOutput,
+ char* buffer);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrApplyHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo,
+ const XrHapticBaseHeader* hapticFeedback);
+extern "C" LOADER_EXPORT XRAPI_ATTR XrResult XRAPI_CALL xrStopHapticFeedback(
+ XrSession session,
+ const XrHapticActionInfo* hapticActionInfo);
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table.c b/thirdparty/openxr/src/xr_generated_dispatch_table.c
new file mode 100644
index 0000000000..91fa0c3ca0
--- /dev/null
+++ b/thirdparty/openxr/src/xr_generated_dispatch_table.c
@@ -0,0 +1,377 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#include "xr_generated_dispatch_table.h"
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Helper function to populate an instance dispatch table
+void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
+ XrInstance instance,
+ PFN_xrGetInstanceProcAddr get_inst_proc_addr) {
+
+ // ---- Core 1.0 commands
+ table->GetInstanceProcAddr = get_inst_proc_addr;
+ (get_inst_proc_addr(instance, "xrCreateInstance", (PFN_xrVoidFunction*)&table->CreateInstance));
+ (get_inst_proc_addr(instance, "xrDestroyInstance", (PFN_xrVoidFunction*)&table->DestroyInstance));
+ (get_inst_proc_addr(instance, "xrGetInstanceProperties", (PFN_xrVoidFunction*)&table->GetInstanceProperties));
+ (get_inst_proc_addr(instance, "xrPollEvent", (PFN_xrVoidFunction*)&table->PollEvent));
+ (get_inst_proc_addr(instance, "xrResultToString", (PFN_xrVoidFunction*)&table->ResultToString));
+ (get_inst_proc_addr(instance, "xrStructureTypeToString", (PFN_xrVoidFunction*)&table->StructureTypeToString));
+ (get_inst_proc_addr(instance, "xrGetSystem", (PFN_xrVoidFunction*)&table->GetSystem));
+ (get_inst_proc_addr(instance, "xrGetSystemProperties", (PFN_xrVoidFunction*)&table->GetSystemProperties));
+ (get_inst_proc_addr(instance, "xrEnumerateEnvironmentBlendModes", (PFN_xrVoidFunction*)&table->EnumerateEnvironmentBlendModes));
+ (get_inst_proc_addr(instance, "xrCreateSession", (PFN_xrVoidFunction*)&table->CreateSession));
+ (get_inst_proc_addr(instance, "xrDestroySession", (PFN_xrVoidFunction*)&table->DestroySession));
+ (get_inst_proc_addr(instance, "xrEnumerateReferenceSpaces", (PFN_xrVoidFunction*)&table->EnumerateReferenceSpaces));
+ (get_inst_proc_addr(instance, "xrCreateReferenceSpace", (PFN_xrVoidFunction*)&table->CreateReferenceSpace));
+ (get_inst_proc_addr(instance, "xrGetReferenceSpaceBoundsRect", (PFN_xrVoidFunction*)&table->GetReferenceSpaceBoundsRect));
+ (get_inst_proc_addr(instance, "xrCreateActionSpace", (PFN_xrVoidFunction*)&table->CreateActionSpace));
+ (get_inst_proc_addr(instance, "xrLocateSpace", (PFN_xrVoidFunction*)&table->LocateSpace));
+ (get_inst_proc_addr(instance, "xrDestroySpace", (PFN_xrVoidFunction*)&table->DestroySpace));
+ (get_inst_proc_addr(instance, "xrEnumerateViewConfigurations", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurations));
+ (get_inst_proc_addr(instance, "xrGetViewConfigurationProperties", (PFN_xrVoidFunction*)&table->GetViewConfigurationProperties));
+ (get_inst_proc_addr(instance, "xrEnumerateViewConfigurationViews", (PFN_xrVoidFunction*)&table->EnumerateViewConfigurationViews));
+ (get_inst_proc_addr(instance, "xrEnumerateSwapchainFormats", (PFN_xrVoidFunction*)&table->EnumerateSwapchainFormats));
+ (get_inst_proc_addr(instance, "xrCreateSwapchain", (PFN_xrVoidFunction*)&table->CreateSwapchain));
+ (get_inst_proc_addr(instance, "xrDestroySwapchain", (PFN_xrVoidFunction*)&table->DestroySwapchain));
+ (get_inst_proc_addr(instance, "xrEnumerateSwapchainImages", (PFN_xrVoidFunction*)&table->EnumerateSwapchainImages));
+ (get_inst_proc_addr(instance, "xrAcquireSwapchainImage", (PFN_xrVoidFunction*)&table->AcquireSwapchainImage));
+ (get_inst_proc_addr(instance, "xrWaitSwapchainImage", (PFN_xrVoidFunction*)&table->WaitSwapchainImage));
+ (get_inst_proc_addr(instance, "xrReleaseSwapchainImage", (PFN_xrVoidFunction*)&table->ReleaseSwapchainImage));
+ (get_inst_proc_addr(instance, "xrBeginSession", (PFN_xrVoidFunction*)&table->BeginSession));
+ (get_inst_proc_addr(instance, "xrEndSession", (PFN_xrVoidFunction*)&table->EndSession));
+ (get_inst_proc_addr(instance, "xrRequestExitSession", (PFN_xrVoidFunction*)&table->RequestExitSession));
+ (get_inst_proc_addr(instance, "xrWaitFrame", (PFN_xrVoidFunction*)&table->WaitFrame));
+ (get_inst_proc_addr(instance, "xrBeginFrame", (PFN_xrVoidFunction*)&table->BeginFrame));
+ (get_inst_proc_addr(instance, "xrEndFrame", (PFN_xrVoidFunction*)&table->EndFrame));
+ (get_inst_proc_addr(instance, "xrLocateViews", (PFN_xrVoidFunction*)&table->LocateViews));
+ (get_inst_proc_addr(instance, "xrStringToPath", (PFN_xrVoidFunction*)&table->StringToPath));
+ (get_inst_proc_addr(instance, "xrPathToString", (PFN_xrVoidFunction*)&table->PathToString));
+ (get_inst_proc_addr(instance, "xrCreateActionSet", (PFN_xrVoidFunction*)&table->CreateActionSet));
+ (get_inst_proc_addr(instance, "xrDestroyActionSet", (PFN_xrVoidFunction*)&table->DestroyActionSet));
+ (get_inst_proc_addr(instance, "xrCreateAction", (PFN_xrVoidFunction*)&table->CreateAction));
+ (get_inst_proc_addr(instance, "xrDestroyAction", (PFN_xrVoidFunction*)&table->DestroyAction));
+ (get_inst_proc_addr(instance, "xrSuggestInteractionProfileBindings", (PFN_xrVoidFunction*)&table->SuggestInteractionProfileBindings));
+ (get_inst_proc_addr(instance, "xrAttachSessionActionSets", (PFN_xrVoidFunction*)&table->AttachSessionActionSets));
+ (get_inst_proc_addr(instance, "xrGetCurrentInteractionProfile", (PFN_xrVoidFunction*)&table->GetCurrentInteractionProfile));
+ (get_inst_proc_addr(instance, "xrGetActionStateBoolean", (PFN_xrVoidFunction*)&table->GetActionStateBoolean));
+ (get_inst_proc_addr(instance, "xrGetActionStateFloat", (PFN_xrVoidFunction*)&table->GetActionStateFloat));
+ (get_inst_proc_addr(instance, "xrGetActionStateVector2f", (PFN_xrVoidFunction*)&table->GetActionStateVector2f));
+ (get_inst_proc_addr(instance, "xrGetActionStatePose", (PFN_xrVoidFunction*)&table->GetActionStatePose));
+ (get_inst_proc_addr(instance, "xrSyncActions", (PFN_xrVoidFunction*)&table->SyncActions));
+ (get_inst_proc_addr(instance, "xrEnumerateBoundSourcesForAction", (PFN_xrVoidFunction*)&table->EnumerateBoundSourcesForAction));
+ (get_inst_proc_addr(instance, "xrGetInputSourceLocalizedName", (PFN_xrVoidFunction*)&table->GetInputSourceLocalizedName));
+ (get_inst_proc_addr(instance, "xrApplyHapticFeedback", (PFN_xrVoidFunction*)&table->ApplyHapticFeedback));
+ (get_inst_proc_addr(instance, "xrStopHapticFeedback", (PFN_xrVoidFunction*)&table->StopHapticFeedback));
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ (get_inst_proc_addr(instance, "xrSetAndroidApplicationThreadKHR", (PFN_xrVoidFunction*)&table->SetAndroidApplicationThreadKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ (get_inst_proc_addr(instance, "xrCreateSwapchainAndroidSurfaceKHR", (PFN_xrVoidFunction*)&table->CreateSwapchainAndroidSurfaceKHR));
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ (get_inst_proc_addr(instance, "xrGetOpenGLGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ (get_inst_proc_addr(instance, "xrGetOpenGLESGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetOpenGLESGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanInstanceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanInstanceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanDeviceExtensionsKHR", (PFN_xrVoidFunction*)&table->GetVulkanDeviceExtensionsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsDeviceKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDeviceKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ (get_inst_proc_addr(instance, "xrGetD3D11GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D11GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ (get_inst_proc_addr(instance, "xrGetD3D12GraphicsRequirementsKHR", (PFN_xrVoidFunction*)&table->GetD3D12GraphicsRequirementsKHR));
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ (get_inst_proc_addr(instance, "xrGetVisibilityMaskKHR", (PFN_xrVoidFunction*)&table->GetVisibilityMaskKHR));
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrConvertWin32PerformanceCounterToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertWin32PerformanceCounterToTimeKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrConvertTimeToWin32PerformanceCounterKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToWin32PerformanceCounterKHR));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ (get_inst_proc_addr(instance, "xrConvertTimespecTimeToTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimespecTimeToTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ (get_inst_proc_addr(instance, "xrConvertTimeToTimespecTimeKHR", (PFN_xrVoidFunction*)&table->ConvertTimeToTimespecTimeKHR));
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_KHR_vulkan_enable2 extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrCreateVulkanInstanceKHR", (PFN_xrVoidFunction*)&table->CreateVulkanInstanceKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrCreateVulkanDeviceKHR", (PFN_xrVoidFunction*)&table->CreateVulkanDeviceKHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsDevice2KHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsDevice2KHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ (get_inst_proc_addr(instance, "xrGetVulkanGraphicsRequirements2KHR", (PFN_xrVoidFunction*)&table->GetVulkanGraphicsRequirements2KHR));
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_EXT_performance_settings extension commands
+ (get_inst_proc_addr(instance, "xrPerfSettingsSetPerformanceLevelEXT", (PFN_xrVoidFunction*)&table->PerfSettingsSetPerformanceLevelEXT));
+
+ // ---- XR_EXT_thermal_query extension commands
+ (get_inst_proc_addr(instance, "xrThermalGetTemperatureTrendEXT", (PFN_xrVoidFunction*)&table->ThermalGetTemperatureTrendEXT));
+
+ // ---- XR_EXT_debug_utils extension commands
+ (get_inst_proc_addr(instance, "xrSetDebugUtilsObjectNameEXT", (PFN_xrVoidFunction*)&table->SetDebugUtilsObjectNameEXT));
+ (get_inst_proc_addr(instance, "xrCreateDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->CreateDebugUtilsMessengerEXT));
+ (get_inst_proc_addr(instance, "xrDestroyDebugUtilsMessengerEXT", (PFN_xrVoidFunction*)&table->DestroyDebugUtilsMessengerEXT));
+ (get_inst_proc_addr(instance, "xrSubmitDebugUtilsMessageEXT", (PFN_xrVoidFunction*)&table->SubmitDebugUtilsMessageEXT));
+ (get_inst_proc_addr(instance, "xrSessionBeginDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionBeginDebugUtilsLabelRegionEXT));
+ (get_inst_proc_addr(instance, "xrSessionEndDebugUtilsLabelRegionEXT", (PFN_xrVoidFunction*)&table->SessionEndDebugUtilsLabelRegionEXT));
+ (get_inst_proc_addr(instance, "xrSessionInsertDebugUtilsLabelEXT", (PFN_xrVoidFunction*)&table->SessionInsertDebugUtilsLabelEXT));
+
+ // ---- XR_MSFT_spatial_anchor extension commands
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorMSFT));
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorSpaceMSFT));
+ (get_inst_proc_addr(instance, "xrDestroySpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->DestroySpatialAnchorMSFT));
+
+ // ---- XR_EXT_conformance_automation extension commands
+ (get_inst_proc_addr(instance, "xrSetInputDeviceActiveEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceActiveEXT));
+ (get_inst_proc_addr(instance, "xrSetInputDeviceStateBoolEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateBoolEXT));
+ (get_inst_proc_addr(instance, "xrSetInputDeviceStateFloatEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateFloatEXT));
+ (get_inst_proc_addr(instance, "xrSetInputDeviceStateVector2fEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceStateVector2fEXT));
+ (get_inst_proc_addr(instance, "xrSetInputDeviceLocationEXT", (PFN_xrVoidFunction*)&table->SetInputDeviceLocationEXT));
+
+ // ---- XR_MSFT_spatial_graph_bridge extension commands
+ (get_inst_proc_addr(instance, "xrCreateSpatialGraphNodeSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialGraphNodeSpaceMSFT));
+ (get_inst_proc_addr(instance, "xrTryCreateSpatialGraphStaticNodeBindingMSFT", (PFN_xrVoidFunction*)&table->TryCreateSpatialGraphStaticNodeBindingMSFT));
+ (get_inst_proc_addr(instance, "xrDestroySpatialGraphNodeBindingMSFT", (PFN_xrVoidFunction*)&table->DestroySpatialGraphNodeBindingMSFT));
+ (get_inst_proc_addr(instance, "xrGetSpatialGraphNodeBindingPropertiesMSFT", (PFN_xrVoidFunction*)&table->GetSpatialGraphNodeBindingPropertiesMSFT));
+
+ // ---- XR_EXT_hand_tracking extension commands
+ (get_inst_proc_addr(instance, "xrCreateHandTrackerEXT", (PFN_xrVoidFunction*)&table->CreateHandTrackerEXT));
+ (get_inst_proc_addr(instance, "xrDestroyHandTrackerEXT", (PFN_xrVoidFunction*)&table->DestroyHandTrackerEXT));
+ (get_inst_proc_addr(instance, "xrLocateHandJointsEXT", (PFN_xrVoidFunction*)&table->LocateHandJointsEXT));
+
+ // ---- XR_MSFT_hand_tracking_mesh extension commands
+ (get_inst_proc_addr(instance, "xrCreateHandMeshSpaceMSFT", (PFN_xrVoidFunction*)&table->CreateHandMeshSpaceMSFT));
+ (get_inst_proc_addr(instance, "xrUpdateHandMeshMSFT", (PFN_xrVoidFunction*)&table->UpdateHandMeshMSFT));
+
+ // ---- XR_MSFT_controller_model extension commands
+ (get_inst_proc_addr(instance, "xrGetControllerModelKeyMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelKeyMSFT));
+ (get_inst_proc_addr(instance, "xrLoadControllerModelMSFT", (PFN_xrVoidFunction*)&table->LoadControllerModelMSFT));
+ (get_inst_proc_addr(instance, "xrGetControllerModelPropertiesMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelPropertiesMSFT));
+ (get_inst_proc_addr(instance, "xrGetControllerModelStateMSFT", (PFN_xrVoidFunction*)&table->GetControllerModelStateMSFT));
+
+ // ---- XR_MSFT_perception_anchor_interop extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorFromPerceptionAnchorMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorFromPerceptionAnchorMSFT));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrTryGetPerceptionAnchorFromSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->TryGetPerceptionAnchorFromSpatialAnchorMSFT));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_MSFT_composition_layer_reprojection extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateReprojectionModesMSFT", (PFN_xrVoidFunction*)&table->EnumerateReprojectionModesMSFT));
+
+ // ---- XR_FB_swapchain_update_state extension commands
+ (get_inst_proc_addr(instance, "xrUpdateSwapchainFB", (PFN_xrVoidFunction*)&table->UpdateSwapchainFB));
+ (get_inst_proc_addr(instance, "xrGetSwapchainStateFB", (PFN_xrVoidFunction*)&table->GetSwapchainStateFB));
+
+ // ---- XR_MSFT_scene_understanding extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateSceneComputeFeaturesMSFT", (PFN_xrVoidFunction*)&table->EnumerateSceneComputeFeaturesMSFT));
+ (get_inst_proc_addr(instance, "xrCreateSceneObserverMSFT", (PFN_xrVoidFunction*)&table->CreateSceneObserverMSFT));
+ (get_inst_proc_addr(instance, "xrDestroySceneObserverMSFT", (PFN_xrVoidFunction*)&table->DestroySceneObserverMSFT));
+ (get_inst_proc_addr(instance, "xrCreateSceneMSFT", (PFN_xrVoidFunction*)&table->CreateSceneMSFT));
+ (get_inst_proc_addr(instance, "xrDestroySceneMSFT", (PFN_xrVoidFunction*)&table->DestroySceneMSFT));
+ (get_inst_proc_addr(instance, "xrComputeNewSceneMSFT", (PFN_xrVoidFunction*)&table->ComputeNewSceneMSFT));
+ (get_inst_proc_addr(instance, "xrGetSceneComputeStateMSFT", (PFN_xrVoidFunction*)&table->GetSceneComputeStateMSFT));
+ (get_inst_proc_addr(instance, "xrGetSceneComponentsMSFT", (PFN_xrVoidFunction*)&table->GetSceneComponentsMSFT));
+ (get_inst_proc_addr(instance, "xrLocateSceneComponentsMSFT", (PFN_xrVoidFunction*)&table->LocateSceneComponentsMSFT));
+ (get_inst_proc_addr(instance, "xrGetSceneMeshBuffersMSFT", (PFN_xrVoidFunction*)&table->GetSceneMeshBuffersMSFT));
+
+ // ---- XR_MSFT_scene_understanding_serialization extension commands
+ (get_inst_proc_addr(instance, "xrDeserializeSceneMSFT", (PFN_xrVoidFunction*)&table->DeserializeSceneMSFT));
+ (get_inst_proc_addr(instance, "xrGetSerializedSceneFragmentDataMSFT", (PFN_xrVoidFunction*)&table->GetSerializedSceneFragmentDataMSFT));
+
+ // ---- XR_FB_display_refresh_rate extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateDisplayRefreshRatesFB", (PFN_xrVoidFunction*)&table->EnumerateDisplayRefreshRatesFB));
+ (get_inst_proc_addr(instance, "xrGetDisplayRefreshRateFB", (PFN_xrVoidFunction*)&table->GetDisplayRefreshRateFB));
+ (get_inst_proc_addr(instance, "xrRequestDisplayRefreshRateFB", (PFN_xrVoidFunction*)&table->RequestDisplayRefreshRateFB));
+
+ // ---- XR_HTCX_vive_tracker_interaction extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateViveTrackerPathsHTCX", (PFN_xrVoidFunction*)&table->EnumerateViveTrackerPathsHTCX));
+
+ // ---- XR_HTC_facial_tracking extension commands
+ (get_inst_proc_addr(instance, "xrCreateFacialTrackerHTC", (PFN_xrVoidFunction*)&table->CreateFacialTrackerHTC));
+ (get_inst_proc_addr(instance, "xrDestroyFacialTrackerHTC", (PFN_xrVoidFunction*)&table->DestroyFacialTrackerHTC));
+ (get_inst_proc_addr(instance, "xrGetFacialExpressionsHTC", (PFN_xrVoidFunction*)&table->GetFacialExpressionsHTC));
+
+ // ---- XR_FB_color_space extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateColorSpacesFB", (PFN_xrVoidFunction*)&table->EnumerateColorSpacesFB));
+ (get_inst_proc_addr(instance, "xrSetColorSpaceFB", (PFN_xrVoidFunction*)&table->SetColorSpaceFB));
+
+ // ---- XR_FB_hand_tracking_mesh extension commands
+ (get_inst_proc_addr(instance, "xrGetHandMeshFB", (PFN_xrVoidFunction*)&table->GetHandMeshFB));
+
+ // ---- XR_FB_spatial_entity extension commands
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorFB", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceUuidFB", (PFN_xrVoidFunction*)&table->GetSpaceUuidFB));
+ (get_inst_proc_addr(instance, "xrEnumerateSpaceSupportedComponentsFB", (PFN_xrVoidFunction*)&table->EnumerateSpaceSupportedComponentsFB));
+ (get_inst_proc_addr(instance, "xrSetSpaceComponentStatusFB", (PFN_xrVoidFunction*)&table->SetSpaceComponentStatusFB));
+ (get_inst_proc_addr(instance, "xrGetSpaceComponentStatusFB", (PFN_xrVoidFunction*)&table->GetSpaceComponentStatusFB));
+
+ // ---- XR_FB_foveation extension commands
+ (get_inst_proc_addr(instance, "xrCreateFoveationProfileFB", (PFN_xrVoidFunction*)&table->CreateFoveationProfileFB));
+ (get_inst_proc_addr(instance, "xrDestroyFoveationProfileFB", (PFN_xrVoidFunction*)&table->DestroyFoveationProfileFB));
+
+ // ---- XR_FB_keyboard_tracking extension commands
+ (get_inst_proc_addr(instance, "xrQuerySystemTrackedKeyboardFB", (PFN_xrVoidFunction*)&table->QuerySystemTrackedKeyboardFB));
+ (get_inst_proc_addr(instance, "xrCreateKeyboardSpaceFB", (PFN_xrVoidFunction*)&table->CreateKeyboardSpaceFB));
+
+ // ---- XR_FB_triangle_mesh extension commands
+ (get_inst_proc_addr(instance, "xrCreateTriangleMeshFB", (PFN_xrVoidFunction*)&table->CreateTriangleMeshFB));
+ (get_inst_proc_addr(instance, "xrDestroyTriangleMeshFB", (PFN_xrVoidFunction*)&table->DestroyTriangleMeshFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshGetVertexBufferFB", (PFN_xrVoidFunction*)&table->TriangleMeshGetVertexBufferFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshGetIndexBufferFB", (PFN_xrVoidFunction*)&table->TriangleMeshGetIndexBufferFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshBeginUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshBeginUpdateFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshEndUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshEndUpdateFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshBeginVertexBufferUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshBeginVertexBufferUpdateFB));
+ (get_inst_proc_addr(instance, "xrTriangleMeshEndVertexBufferUpdateFB", (PFN_xrVoidFunction*)&table->TriangleMeshEndVertexBufferUpdateFB));
+
+ // ---- XR_FB_passthrough extension commands
+ (get_inst_proc_addr(instance, "xrCreatePassthroughFB", (PFN_xrVoidFunction*)&table->CreatePassthroughFB));
+ (get_inst_proc_addr(instance, "xrDestroyPassthroughFB", (PFN_xrVoidFunction*)&table->DestroyPassthroughFB));
+ (get_inst_proc_addr(instance, "xrPassthroughStartFB", (PFN_xrVoidFunction*)&table->PassthroughStartFB));
+ (get_inst_proc_addr(instance, "xrPassthroughPauseFB", (PFN_xrVoidFunction*)&table->PassthroughPauseFB));
+ (get_inst_proc_addr(instance, "xrCreatePassthroughLayerFB", (PFN_xrVoidFunction*)&table->CreatePassthroughLayerFB));
+ (get_inst_proc_addr(instance, "xrDestroyPassthroughLayerFB", (PFN_xrVoidFunction*)&table->DestroyPassthroughLayerFB));
+ (get_inst_proc_addr(instance, "xrPassthroughLayerPauseFB", (PFN_xrVoidFunction*)&table->PassthroughLayerPauseFB));
+ (get_inst_proc_addr(instance, "xrPassthroughLayerResumeFB", (PFN_xrVoidFunction*)&table->PassthroughLayerResumeFB));
+ (get_inst_proc_addr(instance, "xrPassthroughLayerSetStyleFB", (PFN_xrVoidFunction*)&table->PassthroughLayerSetStyleFB));
+ (get_inst_proc_addr(instance, "xrCreateGeometryInstanceFB", (PFN_xrVoidFunction*)&table->CreateGeometryInstanceFB));
+ (get_inst_proc_addr(instance, "xrDestroyGeometryInstanceFB", (PFN_xrVoidFunction*)&table->DestroyGeometryInstanceFB));
+ (get_inst_proc_addr(instance, "xrGeometryInstanceSetTransformFB", (PFN_xrVoidFunction*)&table->GeometryInstanceSetTransformFB));
+
+ // ---- XR_FB_render_model extension commands
+ (get_inst_proc_addr(instance, "xrEnumerateRenderModelPathsFB", (PFN_xrVoidFunction*)&table->EnumerateRenderModelPathsFB));
+ (get_inst_proc_addr(instance, "xrGetRenderModelPropertiesFB", (PFN_xrVoidFunction*)&table->GetRenderModelPropertiesFB));
+ (get_inst_proc_addr(instance, "xrLoadRenderModelFB", (PFN_xrVoidFunction*)&table->LoadRenderModelFB));
+
+ // ---- XR_VARJO_environment_depth_estimation extension commands
+ (get_inst_proc_addr(instance, "xrSetEnvironmentDepthEstimationVARJO", (PFN_xrVoidFunction*)&table->SetEnvironmentDepthEstimationVARJO));
+
+ // ---- XR_VARJO_marker_tracking extension commands
+ (get_inst_proc_addr(instance, "xrSetMarkerTrackingVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingVARJO));
+ (get_inst_proc_addr(instance, "xrSetMarkerTrackingTimeoutVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingTimeoutVARJO));
+ (get_inst_proc_addr(instance, "xrSetMarkerTrackingPredictionVARJO", (PFN_xrVoidFunction*)&table->SetMarkerTrackingPredictionVARJO));
+ (get_inst_proc_addr(instance, "xrGetMarkerSizeVARJO", (PFN_xrVoidFunction*)&table->GetMarkerSizeVARJO));
+ (get_inst_proc_addr(instance, "xrCreateMarkerSpaceVARJO", (PFN_xrVoidFunction*)&table->CreateMarkerSpaceVARJO));
+
+ // ---- XR_VARJO_view_offset extension commands
+ (get_inst_proc_addr(instance, "xrSetViewOffsetVARJO", (PFN_xrVoidFunction*)&table->SetViewOffsetVARJO));
+
+ // ---- XR_MSFT_spatial_anchor_persistence extension commands
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorStoreConnectionMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorStoreConnectionMSFT));
+ (get_inst_proc_addr(instance, "xrDestroySpatialAnchorStoreConnectionMSFT", (PFN_xrVoidFunction*)&table->DestroySpatialAnchorStoreConnectionMSFT));
+ (get_inst_proc_addr(instance, "xrPersistSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->PersistSpatialAnchorMSFT));
+ (get_inst_proc_addr(instance, "xrEnumeratePersistedSpatialAnchorNamesMSFT", (PFN_xrVoidFunction*)&table->EnumeratePersistedSpatialAnchorNamesMSFT));
+ (get_inst_proc_addr(instance, "xrCreateSpatialAnchorFromPersistedNameMSFT", (PFN_xrVoidFunction*)&table->CreateSpatialAnchorFromPersistedNameMSFT));
+ (get_inst_proc_addr(instance, "xrUnpersistSpatialAnchorMSFT", (PFN_xrVoidFunction*)&table->UnpersistSpatialAnchorMSFT));
+ (get_inst_proc_addr(instance, "xrClearSpatialAnchorStoreMSFT", (PFN_xrVoidFunction*)&table->ClearSpatialAnchorStoreMSFT));
+
+ // ---- XR_FB_spatial_entity_query extension commands
+ (get_inst_proc_addr(instance, "xrQuerySpacesFB", (PFN_xrVoidFunction*)&table->QuerySpacesFB));
+ (get_inst_proc_addr(instance, "xrRetrieveSpaceQueryResultsFB", (PFN_xrVoidFunction*)&table->RetrieveSpaceQueryResultsFB));
+
+ // ---- XR_FB_spatial_entity_storage extension commands
+ (get_inst_proc_addr(instance, "xrSaveSpaceFB", (PFN_xrVoidFunction*)&table->SaveSpaceFB));
+ (get_inst_proc_addr(instance, "xrEraseSpaceFB", (PFN_xrVoidFunction*)&table->EraseSpaceFB));
+
+ // ---- XR_OCULUS_audio_device_guid extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrGetAudioOutputDeviceGuidOculus", (PFN_xrVoidFunction*)&table->GetAudioOutputDeviceGuidOculus));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ (get_inst_proc_addr(instance, "xrGetAudioInputDeviceGuidOculus", (PFN_xrVoidFunction*)&table->GetAudioInputDeviceGuidOculus));
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_ALMALENCE_digital_lens_control extension commands
+ (get_inst_proc_addr(instance, "xrSetDigitalLensControlALMALENCE", (PFN_xrVoidFunction*)&table->SetDigitalLensControlALMALENCE));
+
+ // ---- XR_FB_spatial_entity_container extension commands
+ (get_inst_proc_addr(instance, "xrGetSpaceContainerFB", (PFN_xrVoidFunction*)&table->GetSpaceContainerFB));
+
+ // ---- XR_FB_passthrough_keyboard_hands extension commands
+ (get_inst_proc_addr(instance, "xrPassthroughLayerSetKeyboardHandsIntensityFB", (PFN_xrVoidFunction*)&table->PassthroughLayerSetKeyboardHandsIntensityFB));
+
+ // ---- XR_META_performance_metrics extension commands
+ (get_inst_proc_addr(instance, "xrEnumeratePerformanceMetricsCounterPathsMETA", (PFN_xrVoidFunction*)&table->EnumeratePerformanceMetricsCounterPathsMETA));
+ (get_inst_proc_addr(instance, "xrSetPerformanceMetricsStateMETA", (PFN_xrVoidFunction*)&table->SetPerformanceMetricsStateMETA));
+ (get_inst_proc_addr(instance, "xrGetPerformanceMetricsStateMETA", (PFN_xrVoidFunction*)&table->GetPerformanceMetricsStateMETA));
+ (get_inst_proc_addr(instance, "xrQueryPerformanceMetricsCounterMETA", (PFN_xrVoidFunction*)&table->QueryPerformanceMetricsCounterMETA));
+}
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/thirdparty/openxr/src/xr_generated_dispatch_table.h b/thirdparty/openxr/src/xr_generated_dispatch_table.h
new file mode 100644
index 0000000000..51d48bef43
--- /dev/null
+++ b/thirdparty/openxr/src/xr_generated_dispatch_table.h
@@ -0,0 +1,385 @@
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+// *********** THIS FILE IS GENERATED - DO NOT EDIT ***********
+// See utility_source_generator.py for modifications
+// ************************************************************
+
+// Copyright (c) 2017-2022, The Khronos Group Inc.
+// Copyright (c) 2017-2019 Valve Corporation
+// Copyright (c) 2017-2019 LunarG, Inc.
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Author: Mark Young <marky@lunarg.com>
+//
+
+#pragma once
+#include "xr_dependencies.h"
+#include <openxr/openxr.h>
+#include <openxr/openxr_platform.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// Generated dispatch table
+struct XrGeneratedDispatchTable {
+
+ // ---- Core 1.0 commands
+ PFN_xrGetInstanceProcAddr GetInstanceProcAddr;
+ PFN_xrEnumerateApiLayerProperties EnumerateApiLayerProperties;
+ PFN_xrEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_xrCreateInstance CreateInstance;
+ PFN_xrDestroyInstance DestroyInstance;
+ PFN_xrGetInstanceProperties GetInstanceProperties;
+ PFN_xrPollEvent PollEvent;
+ PFN_xrResultToString ResultToString;
+ PFN_xrStructureTypeToString StructureTypeToString;
+ PFN_xrGetSystem GetSystem;
+ PFN_xrGetSystemProperties GetSystemProperties;
+ PFN_xrEnumerateEnvironmentBlendModes EnumerateEnvironmentBlendModes;
+ PFN_xrCreateSession CreateSession;
+ PFN_xrDestroySession DestroySession;
+ PFN_xrEnumerateReferenceSpaces EnumerateReferenceSpaces;
+ PFN_xrCreateReferenceSpace CreateReferenceSpace;
+ PFN_xrGetReferenceSpaceBoundsRect GetReferenceSpaceBoundsRect;
+ PFN_xrCreateActionSpace CreateActionSpace;
+ PFN_xrLocateSpace LocateSpace;
+ PFN_xrDestroySpace DestroySpace;
+ PFN_xrEnumerateViewConfigurations EnumerateViewConfigurations;
+ PFN_xrGetViewConfigurationProperties GetViewConfigurationProperties;
+ PFN_xrEnumerateViewConfigurationViews EnumerateViewConfigurationViews;
+ PFN_xrEnumerateSwapchainFormats EnumerateSwapchainFormats;
+ PFN_xrCreateSwapchain CreateSwapchain;
+ PFN_xrDestroySwapchain DestroySwapchain;
+ PFN_xrEnumerateSwapchainImages EnumerateSwapchainImages;
+ PFN_xrAcquireSwapchainImage AcquireSwapchainImage;
+ PFN_xrWaitSwapchainImage WaitSwapchainImage;
+ PFN_xrReleaseSwapchainImage ReleaseSwapchainImage;
+ PFN_xrBeginSession BeginSession;
+ PFN_xrEndSession EndSession;
+ PFN_xrRequestExitSession RequestExitSession;
+ PFN_xrWaitFrame WaitFrame;
+ PFN_xrBeginFrame BeginFrame;
+ PFN_xrEndFrame EndFrame;
+ PFN_xrLocateViews LocateViews;
+ PFN_xrStringToPath StringToPath;
+ PFN_xrPathToString PathToString;
+ PFN_xrCreateActionSet CreateActionSet;
+ PFN_xrDestroyActionSet DestroyActionSet;
+ PFN_xrCreateAction CreateAction;
+ PFN_xrDestroyAction DestroyAction;
+ PFN_xrSuggestInteractionProfileBindings SuggestInteractionProfileBindings;
+ PFN_xrAttachSessionActionSets AttachSessionActionSets;
+ PFN_xrGetCurrentInteractionProfile GetCurrentInteractionProfile;
+ PFN_xrGetActionStateBoolean GetActionStateBoolean;
+ PFN_xrGetActionStateFloat GetActionStateFloat;
+ PFN_xrGetActionStateVector2f GetActionStateVector2f;
+ PFN_xrGetActionStatePose GetActionStatePose;
+ PFN_xrSyncActions SyncActions;
+ PFN_xrEnumerateBoundSourcesForAction EnumerateBoundSourcesForAction;
+ PFN_xrGetInputSourceLocalizedName GetInputSourceLocalizedName;
+ PFN_xrApplyHapticFeedback ApplyHapticFeedback;
+ PFN_xrStopHapticFeedback StopHapticFeedback;
+
+ // ---- XR_KHR_android_thread_settings extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ PFN_xrSetAndroidApplicationThreadKHR SetAndroidApplicationThreadKHR;
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_android_surface_swapchain extension commands
+#if defined(XR_USE_PLATFORM_ANDROID)
+ PFN_xrCreateSwapchainAndroidSurfaceKHR CreateSwapchainAndroidSurfaceKHR;
+#endif // defined(XR_USE_PLATFORM_ANDROID)
+
+ // ---- XR_KHR_opengl_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL)
+ PFN_xrGetOpenGLGraphicsRequirementsKHR GetOpenGLGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL)
+
+ // ---- XR_KHR_opengl_es_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+ PFN_xrGetOpenGLESGraphicsRequirementsKHR GetOpenGLESGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_OPENGL_ES)
+
+ // ---- XR_KHR_vulkan_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanInstanceExtensionsKHR GetVulkanInstanceExtensionsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanDeviceExtensionsKHR GetVulkanDeviceExtensionsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsDeviceKHR GetVulkanGraphicsDeviceKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsRequirementsKHR GetVulkanGraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_KHR_D3D11_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D11)
+ PFN_xrGetD3D11GraphicsRequirementsKHR GetD3D11GraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_D3D11)
+
+ // ---- XR_KHR_D3D12_enable extension commands
+#if defined(XR_USE_GRAPHICS_API_D3D12)
+ PFN_xrGetD3D12GraphicsRequirementsKHR GetD3D12GraphicsRequirementsKHR;
+#endif // defined(XR_USE_GRAPHICS_API_D3D12)
+
+ // ---- XR_KHR_visibility_mask extension commands
+ PFN_xrGetVisibilityMaskKHR GetVisibilityMaskKHR;
+
+ // ---- XR_KHR_win32_convert_performance_counter_time extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrConvertWin32PerformanceCounterToTimeKHR ConvertWin32PerformanceCounterToTimeKHR;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrConvertTimeToWin32PerformanceCounterKHR ConvertTimeToWin32PerformanceCounterKHR;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_KHR_convert_timespec_time extension commands
+#if defined(XR_USE_TIMESPEC)
+ PFN_xrConvertTimespecTimeToTimeKHR ConvertTimespecTimeToTimeKHR;
+#endif // defined(XR_USE_TIMESPEC)
+#if defined(XR_USE_TIMESPEC)
+ PFN_xrConvertTimeToTimespecTimeKHR ConvertTimeToTimespecTimeKHR;
+#endif // defined(XR_USE_TIMESPEC)
+
+ // ---- XR_KHR_loader_init extension commands
+ PFN_xrInitializeLoaderKHR InitializeLoaderKHR;
+
+ // ---- XR_KHR_vulkan_enable2 extension commands
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrCreateVulkanInstanceKHR CreateVulkanInstanceKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrCreateVulkanDeviceKHR CreateVulkanDeviceKHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsDevice2KHR GetVulkanGraphicsDevice2KHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+#if defined(XR_USE_GRAPHICS_API_VULKAN)
+ PFN_xrGetVulkanGraphicsRequirements2KHR GetVulkanGraphicsRequirements2KHR;
+#endif // defined(XR_USE_GRAPHICS_API_VULKAN)
+
+ // ---- XR_EXT_performance_settings extension commands
+ PFN_xrPerfSettingsSetPerformanceLevelEXT PerfSettingsSetPerformanceLevelEXT;
+
+ // ---- XR_EXT_thermal_query extension commands
+ PFN_xrThermalGetTemperatureTrendEXT ThermalGetTemperatureTrendEXT;
+
+ // ---- XR_EXT_debug_utils extension commands
+ PFN_xrSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
+ PFN_xrCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
+ PFN_xrDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
+ PFN_xrSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
+ PFN_xrSessionBeginDebugUtilsLabelRegionEXT SessionBeginDebugUtilsLabelRegionEXT;
+ PFN_xrSessionEndDebugUtilsLabelRegionEXT SessionEndDebugUtilsLabelRegionEXT;
+ PFN_xrSessionInsertDebugUtilsLabelEXT SessionInsertDebugUtilsLabelEXT;
+
+ // ---- XR_MSFT_spatial_anchor extension commands
+ PFN_xrCreateSpatialAnchorMSFT CreateSpatialAnchorMSFT;
+ PFN_xrCreateSpatialAnchorSpaceMSFT CreateSpatialAnchorSpaceMSFT;
+ PFN_xrDestroySpatialAnchorMSFT DestroySpatialAnchorMSFT;
+
+ // ---- XR_EXT_conformance_automation extension commands
+ PFN_xrSetInputDeviceActiveEXT SetInputDeviceActiveEXT;
+ PFN_xrSetInputDeviceStateBoolEXT SetInputDeviceStateBoolEXT;
+ PFN_xrSetInputDeviceStateFloatEXT SetInputDeviceStateFloatEXT;
+ PFN_xrSetInputDeviceStateVector2fEXT SetInputDeviceStateVector2fEXT;
+ PFN_xrSetInputDeviceLocationEXT SetInputDeviceLocationEXT;
+
+ // ---- XR_MSFT_spatial_graph_bridge extension commands
+ PFN_xrCreateSpatialGraphNodeSpaceMSFT CreateSpatialGraphNodeSpaceMSFT;
+ PFN_xrTryCreateSpatialGraphStaticNodeBindingMSFT TryCreateSpatialGraphStaticNodeBindingMSFT;
+ PFN_xrDestroySpatialGraphNodeBindingMSFT DestroySpatialGraphNodeBindingMSFT;
+ PFN_xrGetSpatialGraphNodeBindingPropertiesMSFT GetSpatialGraphNodeBindingPropertiesMSFT;
+
+ // ---- XR_EXT_hand_tracking extension commands
+ PFN_xrCreateHandTrackerEXT CreateHandTrackerEXT;
+ PFN_xrDestroyHandTrackerEXT DestroyHandTrackerEXT;
+ PFN_xrLocateHandJointsEXT LocateHandJointsEXT;
+
+ // ---- XR_MSFT_hand_tracking_mesh extension commands
+ PFN_xrCreateHandMeshSpaceMSFT CreateHandMeshSpaceMSFT;
+ PFN_xrUpdateHandMeshMSFT UpdateHandMeshMSFT;
+
+ // ---- XR_MSFT_controller_model extension commands
+ PFN_xrGetControllerModelKeyMSFT GetControllerModelKeyMSFT;
+ PFN_xrLoadControllerModelMSFT LoadControllerModelMSFT;
+ PFN_xrGetControllerModelPropertiesMSFT GetControllerModelPropertiesMSFT;
+ PFN_xrGetControllerModelStateMSFT GetControllerModelStateMSFT;
+
+ // ---- XR_MSFT_perception_anchor_interop extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrCreateSpatialAnchorFromPerceptionAnchorMSFT CreateSpatialAnchorFromPerceptionAnchorMSFT;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrTryGetPerceptionAnchorFromSpatialAnchorMSFT TryGetPerceptionAnchorFromSpatialAnchorMSFT;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_MSFT_composition_layer_reprojection extension commands
+ PFN_xrEnumerateReprojectionModesMSFT EnumerateReprojectionModesMSFT;
+
+ // ---- XR_FB_swapchain_update_state extension commands
+ PFN_xrUpdateSwapchainFB UpdateSwapchainFB;
+ PFN_xrGetSwapchainStateFB GetSwapchainStateFB;
+
+ // ---- XR_MSFT_scene_understanding extension commands
+ PFN_xrEnumerateSceneComputeFeaturesMSFT EnumerateSceneComputeFeaturesMSFT;
+ PFN_xrCreateSceneObserverMSFT CreateSceneObserverMSFT;
+ PFN_xrDestroySceneObserverMSFT DestroySceneObserverMSFT;
+ PFN_xrCreateSceneMSFT CreateSceneMSFT;
+ PFN_xrDestroySceneMSFT DestroySceneMSFT;
+ PFN_xrComputeNewSceneMSFT ComputeNewSceneMSFT;
+ PFN_xrGetSceneComputeStateMSFT GetSceneComputeStateMSFT;
+ PFN_xrGetSceneComponentsMSFT GetSceneComponentsMSFT;
+ PFN_xrLocateSceneComponentsMSFT LocateSceneComponentsMSFT;
+ PFN_xrGetSceneMeshBuffersMSFT GetSceneMeshBuffersMSFT;
+
+ // ---- XR_MSFT_scene_understanding_serialization extension commands
+ PFN_xrDeserializeSceneMSFT DeserializeSceneMSFT;
+ PFN_xrGetSerializedSceneFragmentDataMSFT GetSerializedSceneFragmentDataMSFT;
+
+ // ---- XR_FB_display_refresh_rate extension commands
+ PFN_xrEnumerateDisplayRefreshRatesFB EnumerateDisplayRefreshRatesFB;
+ PFN_xrGetDisplayRefreshRateFB GetDisplayRefreshRateFB;
+ PFN_xrRequestDisplayRefreshRateFB RequestDisplayRefreshRateFB;
+
+ // ---- XR_HTCX_vive_tracker_interaction extension commands
+ PFN_xrEnumerateViveTrackerPathsHTCX EnumerateViveTrackerPathsHTCX;
+
+ // ---- XR_HTC_facial_tracking extension commands
+ PFN_xrCreateFacialTrackerHTC CreateFacialTrackerHTC;
+ PFN_xrDestroyFacialTrackerHTC DestroyFacialTrackerHTC;
+ PFN_xrGetFacialExpressionsHTC GetFacialExpressionsHTC;
+
+ // ---- XR_FB_color_space extension commands
+ PFN_xrEnumerateColorSpacesFB EnumerateColorSpacesFB;
+ PFN_xrSetColorSpaceFB SetColorSpaceFB;
+
+ // ---- XR_FB_hand_tracking_mesh extension commands
+ PFN_xrGetHandMeshFB GetHandMeshFB;
+
+ // ---- XR_FB_spatial_entity extension commands
+ PFN_xrCreateSpatialAnchorFB CreateSpatialAnchorFB;
+ PFN_xrGetSpaceUuidFB GetSpaceUuidFB;
+ PFN_xrEnumerateSpaceSupportedComponentsFB EnumerateSpaceSupportedComponentsFB;
+ PFN_xrSetSpaceComponentStatusFB SetSpaceComponentStatusFB;
+ PFN_xrGetSpaceComponentStatusFB GetSpaceComponentStatusFB;
+
+ // ---- XR_FB_foveation extension commands
+ PFN_xrCreateFoveationProfileFB CreateFoveationProfileFB;
+ PFN_xrDestroyFoveationProfileFB DestroyFoveationProfileFB;
+
+ // ---- XR_FB_keyboard_tracking extension commands
+ PFN_xrQuerySystemTrackedKeyboardFB QuerySystemTrackedKeyboardFB;
+ PFN_xrCreateKeyboardSpaceFB CreateKeyboardSpaceFB;
+
+ // ---- XR_FB_triangle_mesh extension commands
+ PFN_xrCreateTriangleMeshFB CreateTriangleMeshFB;
+ PFN_xrDestroyTriangleMeshFB DestroyTriangleMeshFB;
+ PFN_xrTriangleMeshGetVertexBufferFB TriangleMeshGetVertexBufferFB;
+ PFN_xrTriangleMeshGetIndexBufferFB TriangleMeshGetIndexBufferFB;
+ PFN_xrTriangleMeshBeginUpdateFB TriangleMeshBeginUpdateFB;
+ PFN_xrTriangleMeshEndUpdateFB TriangleMeshEndUpdateFB;
+ PFN_xrTriangleMeshBeginVertexBufferUpdateFB TriangleMeshBeginVertexBufferUpdateFB;
+ PFN_xrTriangleMeshEndVertexBufferUpdateFB TriangleMeshEndVertexBufferUpdateFB;
+
+ // ---- XR_FB_passthrough extension commands
+ PFN_xrCreatePassthroughFB CreatePassthroughFB;
+ PFN_xrDestroyPassthroughFB DestroyPassthroughFB;
+ PFN_xrPassthroughStartFB PassthroughStartFB;
+ PFN_xrPassthroughPauseFB PassthroughPauseFB;
+ PFN_xrCreatePassthroughLayerFB CreatePassthroughLayerFB;
+ PFN_xrDestroyPassthroughLayerFB DestroyPassthroughLayerFB;
+ PFN_xrPassthroughLayerPauseFB PassthroughLayerPauseFB;
+ PFN_xrPassthroughLayerResumeFB PassthroughLayerResumeFB;
+ PFN_xrPassthroughLayerSetStyleFB PassthroughLayerSetStyleFB;
+ PFN_xrCreateGeometryInstanceFB CreateGeometryInstanceFB;
+ PFN_xrDestroyGeometryInstanceFB DestroyGeometryInstanceFB;
+ PFN_xrGeometryInstanceSetTransformFB GeometryInstanceSetTransformFB;
+
+ // ---- XR_FB_render_model extension commands
+ PFN_xrEnumerateRenderModelPathsFB EnumerateRenderModelPathsFB;
+ PFN_xrGetRenderModelPropertiesFB GetRenderModelPropertiesFB;
+ PFN_xrLoadRenderModelFB LoadRenderModelFB;
+
+ // ---- XR_VARJO_environment_depth_estimation extension commands
+ PFN_xrSetEnvironmentDepthEstimationVARJO SetEnvironmentDepthEstimationVARJO;
+
+ // ---- XR_VARJO_marker_tracking extension commands
+ PFN_xrSetMarkerTrackingVARJO SetMarkerTrackingVARJO;
+ PFN_xrSetMarkerTrackingTimeoutVARJO SetMarkerTrackingTimeoutVARJO;
+ PFN_xrSetMarkerTrackingPredictionVARJO SetMarkerTrackingPredictionVARJO;
+ PFN_xrGetMarkerSizeVARJO GetMarkerSizeVARJO;
+ PFN_xrCreateMarkerSpaceVARJO CreateMarkerSpaceVARJO;
+
+ // ---- XR_VARJO_view_offset extension commands
+ PFN_xrSetViewOffsetVARJO SetViewOffsetVARJO;
+
+ // ---- XR_MSFT_spatial_anchor_persistence extension commands
+ PFN_xrCreateSpatialAnchorStoreConnectionMSFT CreateSpatialAnchorStoreConnectionMSFT;
+ PFN_xrDestroySpatialAnchorStoreConnectionMSFT DestroySpatialAnchorStoreConnectionMSFT;
+ PFN_xrPersistSpatialAnchorMSFT PersistSpatialAnchorMSFT;
+ PFN_xrEnumeratePersistedSpatialAnchorNamesMSFT EnumeratePersistedSpatialAnchorNamesMSFT;
+ PFN_xrCreateSpatialAnchorFromPersistedNameMSFT CreateSpatialAnchorFromPersistedNameMSFT;
+ PFN_xrUnpersistSpatialAnchorMSFT UnpersistSpatialAnchorMSFT;
+ PFN_xrClearSpatialAnchorStoreMSFT ClearSpatialAnchorStoreMSFT;
+
+ // ---- XR_FB_spatial_entity_query extension commands
+ PFN_xrQuerySpacesFB QuerySpacesFB;
+ PFN_xrRetrieveSpaceQueryResultsFB RetrieveSpaceQueryResultsFB;
+
+ // ---- XR_FB_spatial_entity_storage extension commands
+ PFN_xrSaveSpaceFB SaveSpaceFB;
+ PFN_xrEraseSpaceFB EraseSpaceFB;
+
+ // ---- XR_OCULUS_audio_device_guid extension commands
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrGetAudioOutputDeviceGuidOculus GetAudioOutputDeviceGuidOculus;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+#if defined(XR_USE_PLATFORM_WIN32)
+ PFN_xrGetAudioInputDeviceGuidOculus GetAudioInputDeviceGuidOculus;
+#endif // defined(XR_USE_PLATFORM_WIN32)
+
+ // ---- XR_ALMALENCE_digital_lens_control extension commands
+ PFN_xrSetDigitalLensControlALMALENCE SetDigitalLensControlALMALENCE;
+
+ // ---- XR_FB_spatial_entity_container extension commands
+ PFN_xrGetSpaceContainerFB GetSpaceContainerFB;
+
+ // ---- XR_FB_passthrough_keyboard_hands extension commands
+ PFN_xrPassthroughLayerSetKeyboardHandsIntensityFB PassthroughLayerSetKeyboardHandsIntensityFB;
+
+ // ---- XR_META_performance_metrics extension commands
+ PFN_xrEnumeratePerformanceMetricsCounterPathsMETA EnumeratePerformanceMetricsCounterPathsMETA;
+ PFN_xrSetPerformanceMetricsStateMETA SetPerformanceMetricsStateMETA;
+ PFN_xrGetPerformanceMetricsStateMETA GetPerformanceMetricsStateMETA;
+ PFN_xrQueryPerformanceMetricsCounterMETA QueryPerformanceMetricsCounterMETA;
+};
+
+
+// Prototype for dispatch table helper function
+void GeneratedXrPopulateDispatchTable(struct XrGeneratedDispatchTable *table,
+ XrInstance instance,
+ PFN_xrGetInstanceProcAddr get_inst_proc_addr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
diff --git a/thirdparty/pcre2/AUTHORS b/thirdparty/pcre2/AUTHORS
index bec8a1e5ad..11ef898b25 100644
--- a/thirdparty/pcre2/AUTHORS
+++ b/thirdparty/pcre2/AUTHORS
@@ -8,7 +8,7 @@ Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2021 University of Cambridge
+Copyright (c) 1997-2022 University of Cambridge
All rights reserved
@@ -19,7 +19,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2010-2021 Zoltan Herczeg
+Copyright(c) 2010-2022 Zoltan Herczeg
All rights reserved.
@@ -30,7 +30,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Emain domain: freemail.hu
-Copyright(c) 2009-2021 Zoltan Herczeg
+Copyright(c) 2009-2022 Zoltan Herczeg
All rights reserved.
####
diff --git a/thirdparty/pcre2/LICENCE b/thirdparty/pcre2/LICENCE
index b1ec61be44..2f3cd5cac5 100644
--- a/thirdparty/pcre2/LICENCE
+++ b/thirdparty/pcre2/LICENCE
@@ -26,7 +26,7 @@ Email domain: gmail.com
Retired from University of Cambridge Computing Service,
Cambridge, England.
-Copyright (c) 1997-2021 University of Cambridge
+Copyright (c) 1997-2022 University of Cambridge
All rights reserved.
@@ -37,7 +37,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
-Copyright(c) 2010-2021 Zoltan Herczeg
+Copyright(c) 2010-2022 Zoltan Herczeg
All rights reserved.
@@ -48,7 +48,7 @@ Written by: Zoltan Herczeg
Email local part: hzmester
Email domain: freemail.hu
-Copyright(c) 2009-2021 Zoltan Herczeg
+Copyright(c) 2009-2022 Zoltan Herczeg
All rights reserved.
diff --git a/thirdparty/pcre2/patches/sljit-macos11-conditional.patch b/thirdparty/pcre2/patches/sljit-macos11-conditional.patch
new file mode 100644
index 0000000000..def1207a3d
--- /dev/null
+++ b/thirdparty/pcre2/patches/sljit-macos11-conditional.patch
@@ -0,0 +1,31 @@
+From de8fc816bc6698ab97316ed954e133e7e5098262 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Carlo=20Marcelo=20Arenas=20Bel=C3=B3n?= <carenas@gmail.com>
+Date: Thu, 21 Apr 2022 21:01:12 -0700
+Subject: [PATCH] macos: somehow allow building with a target below 11.0
+
+While building for macOS older than 11 in Apple Silicon makes no
+sense, some build systems lack the flexibility to set a target per
+architecture while aiming to support multi architecture binaries.
+
+Allow an option in those cases by using the slower runtime checks
+if the toolchain allows it.
+
+Fixes: PCRE2Project/pcre2#109
+---
+ sljit_src/sljitExecAllocator.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sljit_src/sljitExecAllocator.c b/sljit_src/sljitExecAllocator.c
+index 92d940dd..6359848c 100644
+--- a/sljit_src/sljitExecAllocator.c
++++ b/sljit_src/sljitExecAllocator.c
+@@ -152,6 +152,9 @@ static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
+ {
+ #if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
+ pthread_jit_write_protect_np(enable_exec);
++#elif defined(__clang__)
++ if (__builtin_available(macOS 11.0, *))
++ pthread_jit_write_protect_np(enable_exec);
+ #else
+ #error "Must target Big Sur or newer"
+ #endif /* BigSur */
diff --git a/thirdparty/pcre2/src/config.h b/thirdparty/pcre2/src/config.h
index a13593715e..76dc5868b1 100644
--- a/thirdparty/pcre2/src/config.h
+++ b/thirdparty/pcre2/src/config.h
@@ -97,6 +97,9 @@ sure both macros are undefined; an emulation function will then be used. */
/* Have PTHREAD_PRIO_INHERIT. */
/* #undef HAVE_PTHREAD_PRIO_INHERIT */
+/* Define to 1 if you have the <readline.h> header file. */
+/* #undef HAVE_READLINE_H */
+
/* Define to 1 if you have the <readline/history.h> header file. */
/* #undef HAVE_READLINE_HISTORY_H */
@@ -233,7 +236,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE2"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE2 10.39"
+#define PACKAGE_STRING "PCRE2 10.40"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre2"
@@ -242,7 +245,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "10.39"
+#define PACKAGE_VERSION "10.40"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -435,7 +438,7 @@ sure both macros are undefined; an emulation function will then be used. */
#endif
/* Version number of package */
-#define VERSION "10.39"
+#define VERSION "10.40"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
diff --git a/thirdparty/pcre2/src/pcre2.h b/thirdparty/pcre2/src/pcre2.h
index 90a97d9cb7..8adcede57c 100644
--- a/thirdparty/pcre2/src/pcre2.h
+++ b/thirdparty/pcre2/src/pcre2.h
@@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE.
/* The current PCRE version information. */
#define PCRE2_MAJOR 10
-#define PCRE2_MINOR 39
+#define PCRE2_MINOR 40
#define PCRE2_PRERELEASE
-#define PCRE2_DATE 2021-10-29
+#define PCRE2_DATE 2022-04-14
/* When an application links to a PCRE DLL in Windows, the symbols that are
imported have to be identified as such. When building PCRE2, the appropriate
diff --git a/thirdparty/pcre2/src/pcre2_auto_possess.c b/thirdparty/pcre2/src/pcre2_auto_possess.c
index e5e0895682..419fd49001 100644
--- a/thirdparty/pcre2/src/pcre2_auto_possess.c
+++ b/thirdparty/pcre2/src/pcre2_auto_possess.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2021 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -123,18 +123,21 @@ opcode is used to select the column. The values are as follows:
*/
static const uint8_t propposstab[PT_TABSIZE][PT_TABSIZE] = {
-/* ANY LAMP GC PC SC ALNUM SPACE PXSPACE WORD CLIST UCNC */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
- { 0, 3, 0, 0, 0, 3, 1, 1, 0, 0, 0 }, /* PT_LAMP */
- { 0, 0, 2, 4, 0, 9, 10, 10, 11, 0, 0 }, /* PT_GC */
- { 0, 0, 5, 2, 0, 15, 16, 16, 17, 0, 0 }, /* PT_PC */
- { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
- { 0, 3, 6, 12, 0, 3, 1, 1, 0, 0, 0 }, /* PT_ALNUM */
- { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_SPACE */
- { 0, 1, 7, 13, 0, 1, 3, 3, 1, 0, 0 }, /* PT_PXSPACE */
- { 0, 0, 8, 14, 0, 0, 1, 1, 3, 0, 0 }, /* PT_WORD */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3 } /* PT_UCNC */
+/* ANY LAMP GC PC SC SCX ALNUM SPACE PXSPACE WORD CLIST UCNC BIDICL BOOL */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_ANY */
+ { 0, 3, 0, 0, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_LAMP */
+ { 0, 0, 2, 4, 0, 0, 9, 10, 10, 11, 0, 0, 0, 0 }, /* PT_GC */
+ { 0, 0, 5, 2, 0, 0, 15, 16, 16, 17, 0, 0, 0, 0 }, /* PT_PC */
+ { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SC */
+ { 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_SCX */
+ { 0, 3, 6, 12, 0, 0, 3, 1, 1, 0, 0, 0, 0, 0 }, /* PT_ALNUM */
+ { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_SPACE */
+ { 0, 1, 7, 13, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0 }, /* PT_PXSPACE */
+ { 0, 0, 8, 14, 0, 0, 0, 1, 1, 3, 0, 0, 0, 0 }, /* PT_WORD */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_CLIST */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, /* PT_UCNC */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* PT_BIDICL */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* PT_BOOL */
};
/* This table is used to check whether auto-possessification is possible
@@ -196,6 +199,7 @@ static BOOL
check_char_prop(uint32_t c, unsigned int ptype, unsigned int pdata,
BOOL negated)
{
+BOOL ok;
const uint32_t *p;
const ucd_record *prop = GET_UCD(c);
@@ -215,6 +219,11 @@ switch(ptype)
case PT_SC:
return (pdata == prop->script) == negated;
+ case PT_SCX:
+ ok = (pdata == prop->script
+ || MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), pdata) != 0);
+ return ok == negated;
+
/* These are specials */
case PT_ALNUM:
@@ -251,6 +260,14 @@ switch(ptype)
if (c == *p++) return negated;
}
break; /* Control never reaches here */
+
+ /* Haven't yet thought these through. */
+
+ case PT_BIDICL:
+ return FALSE;
+
+ case PT_BOOL:
+ return FALSE;
}
return FALSE;
diff --git a/thirdparty/pcre2/src/pcre2_compile.c b/thirdparty/pcre2/src/pcre2_compile.c
index 383159be76..de259c9c40 100644
--- a/thirdparty/pcre2/src/pcre2_compile.c
+++ b/thirdparty/pcre2/src/pcre2_compile.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2021 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -124,7 +124,7 @@ static unsigned int
static int
compile_regex(uint32_t, PCRE2_UCHAR **, uint32_t **, int *, uint32_t,
- uint32_t *, int32_t *, uint32_t *, int32_t *, branch_chain *,
+ uint32_t *, uint32_t *, uint32_t *, uint32_t *, branch_chain *,
compile_block *, PCRE2_SIZE *);
static int
@@ -385,13 +385,15 @@ compiler is clever with identical subexpressions. */
#define SETBIT(a,b) a[(b)/8] = (uint8_t)(a[(b)/8] | (1u << ((b)&7)))
-/* Private flags added to firstcu and reqcu. */
+/* Values and flags for the unsigned xxcuflags variables that accompany xxcu
+variables, which are concerned with first and required code units. A value
+greater than or equal to REQ_NONE means "no code unit set"; otherwise the
+matching xxcu variable is set, and the low valued bits are relevant. */
-#define REQ_CASELESS (1u << 0) /* Indicates caselessness */
-#define REQ_VARY (1u << 1) /* reqcu followed non-literal item */
-/* Negative values for the firstcu and reqcu flags */
-#define REQ_UNSET (-2) /* Not yet found anything */
-#define REQ_NONE (-1) /* Found not fixed char */
+#define REQ_UNSET 0xffffffffu /* Not yet found anything */
+#define REQ_NONE 0xfffffffeu /* Found not fixed character */
+#define REQ_CASELESS 0x00000001u /* Code unit in xxcu is caseless */
+#define REQ_VARY 0x00000002u /* Code unit is followed by non-literal */
/* These flags are used in the groupinfo vector. */
@@ -2088,7 +2090,9 @@ get_ucp(PCRE2_SPTR *ptrptr, BOOL *negptr, uint16_t *ptypeptr,
PCRE2_UCHAR c;
PCRE2_SIZE i, bot, top;
PCRE2_SPTR ptr = *ptrptr;
-PCRE2_UCHAR name[32];
+PCRE2_UCHAR name[50];
+PCRE2_UCHAR *vptr = NULL;
+uint16_t ptscript = PT_NOTSCRIPT;
if (ptr >= cb->end_pattern) goto ERROR_RETURN;
c = *ptr++;
@@ -2100,36 +2104,95 @@ negation. */
if (c == CHAR_LEFT_CURLY_BRACKET)
{
if (ptr >= cb->end_pattern) goto ERROR_RETURN;
+
if (*ptr == CHAR_CIRCUMFLEX_ACCENT)
{
*negptr = TRUE;
ptr++;
}
+
for (i = 0; i < (int)(sizeof(name) / sizeof(PCRE2_UCHAR)) - 1; i++)
{
if (ptr >= cb->end_pattern) goto ERROR_RETURN;
c = *ptr++;
+ while (c == '_' || c == '-' || isspace(c))
+ {
+ if (ptr >= cb->end_pattern) goto ERROR_RETURN;
+ c = *ptr++;
+ }
if (c == CHAR_NUL) goto ERROR_RETURN;
if (c == CHAR_RIGHT_CURLY_BRACKET) break;
- name[i] = c;
+ name[i] = tolower(c);
+ if ((c == ':' || c == '=') && vptr == NULL) vptr = name + i;
}
+
if (c != CHAR_RIGHT_CURLY_BRACKET) goto ERROR_RETURN;
name[i] = 0;
}
-/* Otherwise there is just one following character, which must be an ASCII
-letter. */
+/* If { doesn't follow \p or \P there is just one following character, which
+must be an ASCII letter. */
else if (MAX_255(c) && (cb->ctypes[c] & ctype_letter) != 0)
{
- name[0] = c;
+ name[0] = tolower(c);
name[1] = 0;
}
else goto ERROR_RETURN;
*ptrptr = ptr;
-/* Search for a recognized property name using binary chop. */
+/* If the property contains ':' or '=' we have class name and value separately
+specified. The following are supported:
+
+ . Bidi_Class (synonym bc), for which the property names are "bidi<name>".
+ . Script (synonym sc) for which the property name is the script name
+ . Script_Extensions (synonym scx), ditto
+
+As this is a small number, we currently just check the names directly. If this
+grows, a sorted table and a switch will be neater.
+
+For both the script properties, set a PT_xxx value so that (1) they can be
+distinguished and (2) invalid script names that happen to be the name of
+another property can be diagnosed. */
+
+if (vptr != NULL)
+ {
+ int offset = 0;
+ PCRE2_UCHAR sname[8];
+
+ *vptr = 0; /* Terminate property name */
+ if (PRIV(strcmp_c8)(name, STRING_bidiclass) == 0 ||
+ PRIV(strcmp_c8)(name, STRING_bc) == 0)
+ {
+ offset = 4;
+ sname[0] = CHAR_b;
+ sname[1] = CHAR_i; /* There is no strcpy_c8 function */
+ sname[2] = CHAR_d;
+ sname[3] = CHAR_i;
+ }
+
+ else if (PRIV(strcmp_c8)(name, STRING_script) == 0 ||
+ PRIV(strcmp_c8)(name, STRING_sc) == 0)
+ ptscript = PT_SC;
+
+ else if (PRIV(strcmp_c8)(name, STRING_scriptextensions) == 0 ||
+ PRIV(strcmp_c8)(name, STRING_scx) == 0)
+ ptscript = PT_SCX;
+
+ else
+ {
+ *errorcodeptr = ERR47;
+ return FALSE;
+ }
+
+ /* Adjust the string in name[] as needed */
+
+ memmove(name + offset, vptr + 1, (name + i - vptr)*sizeof(PCRE2_UCHAR));
+ if (offset != 0) memmove(name, sname, offset*sizeof(PCRE2_UCHAR));
+ }
+
+/* Search for a recognized property using binary chop. */
bot = 0;
top = PRIV(utt_size);
@@ -2139,15 +2202,37 @@ while (bot < top)
int r;
i = (bot + top) >> 1;
r = PRIV(strcmp_c8)(name, PRIV(utt_names) + PRIV(utt)[i].name_offset);
+
+ /* When a matching property is found, some extra checking is needed when the
+ \p{xx:yy} syntax is used and xx is either sc or scx. */
+
if (r == 0)
{
- *ptypeptr = PRIV(utt)[i].type;
*pdataptr = PRIV(utt)[i].value;
- return TRUE;
+ if (vptr == NULL || ptscript == PT_NOTSCRIPT)
+ {
+ *ptypeptr = PRIV(utt)[i].type;
+ return TRUE;
+ }
+
+ switch (PRIV(utt)[i].type)
+ {
+ case PT_SC:
+ *ptypeptr = PT_SC;
+ return TRUE;
+
+ case PT_SCX:
+ *ptypeptr = ptscript;
+ return TRUE;
+ }
+
+ break; /* Non-script found */
}
+
if (r > 0) bot = i + 1; else top = i;
}
-*errorcodeptr = ERR47; /* Unrecognized name */
+
+*errorcodeptr = ERR47; /* Unrecognized property */
return FALSE;
ERROR_RETURN: /* Malformed \P or \p */
@@ -5285,9 +5370,9 @@ Arguments:
pptrptr points to the current parsed pattern pointer
errorcodeptr points to error code variable
firstcuptr place to put the first required code unit
- firstcuflagsptr place to put the first code unit flags, or a negative number
+ firstcuflagsptr place to put the first code unit flags
reqcuptr place to put the last required code unit
- reqcuflagsptr place to put the last required code unit flags, or a negative number
+ reqcuflagsptr place to put the last required code unit flags
bcptr points to current branch chain
cb contains pointers to tables etc.
lengthptr NULL during the real compile phase
@@ -5300,8 +5385,8 @@ Returns: 0 There's been an error, *errorcodeptr is non-zero
static int
compile_branch(uint32_t *optionsptr, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,
- int *errorcodeptr, uint32_t *firstcuptr, int32_t *firstcuflagsptr,
- uint32_t *reqcuptr, int32_t *reqcuflagsptr, branch_chain *bcptr,
+ int *errorcodeptr, uint32_t *firstcuptr, uint32_t *firstcuflagsptr,
+ uint32_t *reqcuptr, uint32_t *reqcuflagsptr, branch_chain *bcptr,
compile_block *cb, PCRE2_SIZE *lengthptr)
{
int bravalue = 0;
@@ -5316,9 +5401,9 @@ uint32_t zeroreqcu, zerofirstcu;
uint32_t escape;
uint32_t *pptr = *pptrptr;
uint32_t meta, meta_arg;
-int32_t firstcuflags, reqcuflags;
-int32_t zeroreqcuflags, zerofirstcuflags;
-int32_t req_caseopt, reqvary, tempreqvary;
+uint32_t firstcuflags, reqcuflags;
+uint32_t zeroreqcuflags, zerofirstcuflags;
+uint32_t req_caseopt, reqvary, tempreqvary;
PCRE2_SIZE offset = 0;
PCRE2_SIZE length_prevgroup = 0;
PCRE2_UCHAR *code = *codeptr;
@@ -5374,13 +5459,13 @@ item types that can be repeated set these backoff variables appropriately. */
firstcu = reqcu = zerofirstcu = zeroreqcu = 0;
firstcuflags = reqcuflags = zerofirstcuflags = zeroreqcuflags = REQ_UNSET;
-/* The variable req_caseopt contains either the REQ_CASELESS value or zero,
+/* The variable req_caseopt contains either the REQ_CASELESS bit or zero,
according to the current setting of the caseless flag. The REQ_CASELESS value
leaves the lower 28 bit empty. It is added into the firstcu or reqcu variables
to record the case status of the value. This is used only for ASCII characters.
*/
-req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS:0;
+req_caseopt = ((options & PCRE2_CASELESS) != 0)? REQ_CASELESS : 0;
/* Switch on next META item until the end of the branch */
@@ -5395,13 +5480,12 @@ for (;; pptr++)
BOOL possessive_quantifier;
BOOL note_group_empty;
int class_has_8bitchar;
- int i;
uint32_t mclength;
uint32_t skipunits;
uint32_t subreqcu, subfirstcu;
uint32_t groupnumber;
uint32_t verbarglen, verbculen;
- int32_t subreqcuflags, subfirstcuflags; /* Must be signed */
+ uint32_t subreqcuflags, subfirstcuflags;
open_capitem *oc;
PCRE2_UCHAR mcbuffer[8];
@@ -5770,9 +5854,9 @@ for (;; pptr++)
if (taboffset >= 0)
{
if (tabopt >= 0)
- for (i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];
+ for (int i = 0; i < 32; i++) pbits[i] |= cbits[(int)i + taboffset];
else
- for (i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];
+ for (int i = 0; i < 32; i++) pbits[i] &= ~cbits[(int)i + taboffset];
}
/* Now see if we need to remove any special characters. An option
@@ -5786,9 +5870,9 @@ for (;; pptr++)
being built and we are done. */
if (local_negate)
- for (i = 0; i < 32; i++) classbits[i] |= ~pbits[i];
+ for (int i = 0; i < 32; i++) classbits[i] |= (uint8_t)(~pbits[i]);
else
- for (i = 0; i < 32; i++) classbits[i] |= pbits[i];
+ for (int i = 0; i < 32; i++) classbits[i] |= pbits[i];
/* Every class contains at least one < 256 character. */
@@ -5827,21 +5911,23 @@ for (;; pptr++)
switch(escape)
{
case ESC_d:
- for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];
+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_digit];
break;
case ESC_D:
should_flip_negation = TRUE;
- for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_digit];
+ for (int i = 0; i < 32; i++)
+ classbits[i] |= (uint8_t)(~cbits[i+cbit_digit]);
break;
case ESC_w:
- for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];
+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_word];
break;
case ESC_W:
should_flip_negation = TRUE;
- for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_word];
+ for (int i = 0; i < 32; i++)
+ classbits[i] |= (uint8_t)(~cbits[i+cbit_word]);
break;
/* Perl 5.004 onwards omitted VT from \s, but restored it at Perl
@@ -5852,12 +5938,13 @@ for (;; pptr++)
longer treat \s and \S specially. */
case ESC_s:
- for (i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];
+ for (int i = 0; i < 32; i++) classbits[i] |= cbits[i+cbit_space];
break;
case ESC_S:
should_flip_negation = TRUE;
- for (i = 0; i < 32; i++) classbits[i] |= ~cbits[i+cbit_space];
+ for (int i = 0; i < 32; i++)
+ classbits[i] |= (uint8_t)(~cbits[i+cbit_space]);
break;
/* When adding the horizontal or vertical space lists to a class, or
@@ -6098,7 +6185,7 @@ for (;; pptr++)
if (negate_class && !xclass_has_prop)
{
/* Using 255 ^ instead of ~ avoids clang sanitize warning. */
- for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
+ for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
}
memcpy(code, classbits, 32);
code = class_uchardata + (32 / sizeof(PCRE2_UCHAR));
@@ -6124,7 +6211,7 @@ for (;; pptr++)
if (negate_class)
{
/* Using 255 ^ instead of ~ avoids clang sanitize warning. */
- for (i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
+ for (int i = 0; i < 32; i++) classbits[i] = 255 ^ classbits[i];
}
memcpy(code, classbits, 32);
}
@@ -6198,7 +6285,7 @@ for (;; pptr++)
verbarglen = *(++pptr);
verbculen = 0;
tempcode = code++;
- for (i = 0; i < (int)verbarglen; i++)
+ for (int i = 0; i < (int)verbarglen; i++)
{
meta = *(++pptr);
#ifdef SUPPORT_UNICODE
@@ -6247,6 +6334,7 @@ for (;; pptr++)
bravalue = OP_COND;
{
int count, index;
+ unsigned int i;
PCRE2_SPTR name;
named_group *ng = cb->named_groups;
uint32_t length = *(++pptr);
@@ -6286,7 +6374,7 @@ for (;; pptr++)
groupnumber = 0;
if (meta == META_COND_RNUMBER)
{
- for (i = 1; i < (int)length; i++)
+ for (i = 1; i < length; i++)
{
groupnumber = groupnumber * 10 + name[i] - CHAR_0;
if (groupnumber > MAX_GROUP_NUMBER)
@@ -6608,7 +6696,7 @@ for (;; pptr++)
if (firstcuflags == REQ_UNSET && subfirstcuflags != REQ_UNSET)
{
- if (subfirstcuflags >= 0)
+ if (subfirstcuflags < REQ_NONE)
{
firstcu = subfirstcu;
firstcuflags = subfirstcuflags;
@@ -6622,7 +6710,7 @@ for (;; pptr++)
into reqcu if there wasn't one, using the vary flag that was in
existence beforehand. */
- else if (subfirstcuflags >= 0 && subreqcuflags < 0)
+ else if (subfirstcuflags < REQ_NONE && subreqcuflags >= REQ_NONE)
{
subreqcu = subfirstcu;
subreqcuflags = subfirstcuflags | tempreqvary;
@@ -6631,7 +6719,7 @@ for (;; pptr++)
/* If the subpattern set a required code unit (or set a first code unit
that isn't really the first code unit - see above), set it. */
- if (subreqcuflags >= 0)
+ if (subreqcuflags < REQ_NONE)
{
reqcu = subreqcu;
reqcuflags = subreqcuflags;
@@ -6650,7 +6738,7 @@ for (;; pptr++)
in that example, 'X' ends up set for both. */
else if ((bravalue == OP_ASSERT || bravalue == OP_ASSERT_NA) &&
- subreqcuflags >= 0 && subfirstcuflags >= 0)
+ subreqcuflags < REQ_NONE && subfirstcuflags < REQ_NONE)
{
reqcu = subreqcu;
reqcuflags = subreqcuflags;
@@ -6680,7 +6768,7 @@ for (;; pptr++)
this name is duplicated. */
groupnumber = 0;
- for (i = 0; i < cb->names_found; i++, ng++)
+ for (unsigned int i = 0; i < cb->names_found; i++, ng++)
{
if (length == ng->length &&
PRIV(strncmp)(name, ng->name, length) == 0)
@@ -6935,14 +7023,19 @@ for (;; pptr++)
#endif /* MAYBE_UTF_MULTI */
/* Handle the case of a single code unit - either with no UTF support, or
- with UTF disabled, or for a single-code-unit UTF character. */
+ with UTF disabled, or for a single-code-unit UTF character. In the latter
+ case, for a repeated positive match, get the caseless flag for the
+ required code unit from the previous character, because a class like [Aa]
+ sets a caseless A but by now the req_caseopt flag has been reset. */
+
{
mcbuffer[0] = code[-1];
mclength = 1;
if (op_previous <= OP_CHARI && repeat_min > 1)
{
reqcu = mcbuffer[0];
- reqcuflags = req_caseopt | cb->req_varyopt;
+ reqcuflags = cb->req_varyopt;
+ if (op_previous == OP_CHARI) reqcuflags |= REQ_CASELESS;
}
}
goto OUTPUT_SINGLE_REPEAT; /* Code shared with single character types */
@@ -7034,7 +7127,7 @@ for (;; pptr++)
*lengthptr += delta;
}
- else for (i = 0; i < replicate; i++)
+ else for (int i = 0; i < replicate; i++)
{
memcpy(code, previous, CU2BYTES(1 + LINK_SIZE));
previous = code;
@@ -7210,12 +7303,12 @@ for (;; pptr++)
else
{
- if (groupsetfirstcu && reqcuflags < 0)
+ if (groupsetfirstcu && reqcuflags >= REQ_NONE)
{
reqcu = firstcu;
reqcuflags = firstcuflags;
}
- for (i = 1; (uint32_t)i < repeat_min; i++)
+ for (uint32_t i = 1; i < repeat_min; i++)
{
memcpy(code, previous, CU2BYTES(len));
code += len;
@@ -7259,14 +7352,14 @@ for (;; pptr++)
/* This is compiling for real */
- else for (i = repeat_max - 1; i >= 0; i--)
+ else for (uint32_t i = repeat_max; i >= 1; i--)
{
*code++ = OP_BRAZERO + repeat_type;
/* All but the final copy start a new nesting, maintaining the
chain of brackets outstanding. */
- if (i != 0)
+ if (i != 1)
{
int linkoffset;
*code++ = OP_BRA;
@@ -7985,9 +8078,9 @@ Arguments:
errorcodeptr -> pointer to error code variable
skipunits skip this many code units at start (for brackets and OP_COND)
firstcuptr place to put the first required code unit
- firstcuflagsptr place to put the first code unit flags, or a negative number
+ firstcuflagsptr place to put the first code unit flags
reqcuptr place to put the last required code unit
- reqcuflagsptr place to put the last required code unit flags, or a negative number
+ reqcuflagsptr place to put the last required code unit flags
bcptr pointer to the chain of currently open branches
cb points to the data block with tables pointers etc.
lengthptr NULL during the real compile phase
@@ -8001,7 +8094,7 @@ Returns: 0 There has been an error
static int
compile_regex(uint32_t options, PCRE2_UCHAR **codeptr, uint32_t **pptrptr,
int *errorcodeptr, uint32_t skipunits, uint32_t *firstcuptr,
- int32_t *firstcuflagsptr, uint32_t *reqcuptr,int32_t *reqcuflagsptr,
+ uint32_t *firstcuflagsptr, uint32_t *reqcuptr, uint32_t *reqcuflagsptr,
branch_chain *bcptr, compile_block *cb, PCRE2_SIZE *lengthptr)
{
PCRE2_UCHAR *code = *codeptr;
@@ -8014,9 +8107,9 @@ int okreturn = 1;
uint32_t *pptr = *pptrptr;
uint32_t firstcu, reqcu;
uint32_t lookbehindlength;
-int32_t firstcuflags, reqcuflags;
+uint32_t firstcuflags, reqcuflags;
uint32_t branchfirstcu, branchreqcu;
-int32_t branchfirstcuflags, branchreqcuflags;
+uint32_t branchfirstcuflags, branchreqcuflags;
PCRE2_SIZE length;
branch_chain bc;
@@ -8135,9 +8228,9 @@ for (;;)
if (firstcuflags != branchfirstcuflags || firstcu != branchfirstcu)
{
- if (firstcuflags >= 0)
+ if (firstcuflags < REQ_NONE)
{
- if (reqcuflags < 0)
+ if (reqcuflags >= REQ_NONE)
{
reqcu = firstcu;
reqcuflags = firstcuflags;
@@ -8149,8 +8242,8 @@ for (;;)
/* If we (now or from before) have no firstcu, a firstcu from the
branch becomes a reqcu if there isn't a branch reqcu. */
- if (firstcuflags < 0 && branchfirstcuflags >= 0 &&
- branchreqcuflags < 0)
+ if (firstcuflags >= REQ_NONE && branchfirstcuflags < REQ_NONE &&
+ branchreqcuflags >= REQ_NONE)
{
branchreqcu = branchfirstcu;
branchreqcuflags = branchfirstcuflags;
@@ -8298,7 +8391,7 @@ Returns: TRUE or FALSE
*/
static BOOL
-is_anchored(PCRE2_SPTR code, unsigned int bracket_map, compile_block *cb,
+is_anchored(PCRE2_SPTR code, uint32_t bracket_map, compile_block *cb,
int atomcount, BOOL inassert)
{
do {
@@ -8321,7 +8414,7 @@ do {
op == OP_SCBRA || op == OP_SCBRAPOS)
{
int n = GET2(scode, 1+LINK_SIZE);
- int new_map = bracket_map | ((n < 32)? (1u << n) : 1);
+ uint32_t new_map = bracket_map | ((n < 32)? (1u << n) : 1);
if (!is_anchored(scode, new_map, cb, atomcount, inassert)) return FALSE;
}
@@ -8681,15 +8774,15 @@ Returns: the fixed first code unit, or 0 with REQ_NONE in flags
*/
static uint32_t
-find_firstassertedcu(PCRE2_SPTR code, int32_t *flags, uint32_t inassert)
+find_firstassertedcu(PCRE2_SPTR code, uint32_t *flags, uint32_t inassert)
{
uint32_t c = 0;
-int cflags = REQ_NONE;
+uint32_t cflags = REQ_NONE;
*flags = REQ_NONE;
do {
uint32_t d;
- int dflags;
+ uint32_t dflags;
int xl = (*code == OP_CBRA || *code == OP_SCBRA ||
*code == OP_CBRAPOS || *code == OP_SCBRAPOS)? IMM2_SIZE:0;
PCRE2_SPTR scode = first_significant_code(code + 1+LINK_SIZE + xl, TRUE);
@@ -8712,9 +8805,8 @@ do {
case OP_SCRIPT_RUN:
d = find_firstassertedcu(scode, &dflags, inassert +
((op == OP_ASSERT || op == OP_ASSERT_NA)?1:0));
- if (dflags < 0)
- return 0;
- if (cflags < 0) { c = d; cflags = dflags; }
+ if (dflags >= REQ_NONE) return 0;
+ if (cflags >= REQ_NONE) { c = d; cflags = dflags; }
else if (c != d || cflags != dflags) return 0;
break;
@@ -8727,7 +8819,7 @@ do {
case OP_MINPLUS:
case OP_POSPLUS:
if (inassert == 0) return 0;
- if (cflags < 0) { c = scode[1]; cflags = 0; }
+ if (cflags >= REQ_NONE) { c = scode[1]; cflags = 0; }
else if (c != scode[1]) return 0;
break;
@@ -8753,7 +8845,7 @@ do {
#endif
#endif
- if (cflags < 0) { c = scode[1]; cflags = REQ_CASELESS; }
+ if (cflags >= REQ_NONE) { c = scode[1]; cflags = REQ_CASELESS; }
else if (c != scode[1]) return 0;
break;
}
@@ -9689,7 +9781,7 @@ PCRE2_SIZE re_blocksize; /* Size of memory block */
PCRE2_SIZE big32count = 0; /* 32-bit literals >= 0x80000000 */
PCRE2_SIZE parsed_size_needed; /* Needed for parsed pattern */
-int32_t firstcuflags, reqcuflags; /* Type of first/req code unit */
+uint32_t firstcuflags, reqcuflags; /* Type of first/req code unit */
uint32_t firstcu, reqcu; /* Value of first/req code unit */
uint32_t setflags = 0; /* NL and BSR set flags */
@@ -10369,13 +10461,13 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
(these are not saved during the compile because they can cause conflicts with
actual literals that follow). */
- if (firstcuflags < 0)
+ if (firstcuflags >= REQ_NONE)
firstcu = find_firstassertedcu(codestart, &firstcuflags, 0);
/* Save the data for a first code unit. The existence of one means the
minimum length must be at least 1. */
- if (firstcuflags >= 0)
+ if (firstcuflags < REQ_NONE)
{
re->first_codeunit = firstcu;
re->flags |= PCRE2_FIRSTSET;
@@ -10422,16 +10514,16 @@ if ((re->overall_options & PCRE2_NO_START_OPTIMIZE) == 0)
different character and not a non-starting code unit of the first character,
because the minimum length count is in characters, not code units. */
- if (reqcuflags >= 0)
+ if (reqcuflags < REQ_NONE)
{
#if PCRE2_CODE_UNIT_WIDTH == 16
if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
- firstcuflags < 0 || /* First not set */
+ firstcuflags >= REQ_NONE || /* First not set */
(firstcu & 0xf800) != 0xd800 || /* First not surrogate */
(reqcu & 0xfc00) != 0xdc00) /* Req not low surrogate */
#elif PCRE2_CODE_UNIT_WIDTH == 8
if ((re->overall_options & PCRE2_UTF) == 0 || /* Not UTF */
- firstcuflags < 0 || /* First not set */
+ firstcuflags >= REQ_NONE || /* First not set */
(firstcu & 0x80) == 0 || /* First is ASCII */
(reqcu & 0x80) == 0) /* Req is ASCII */
#endif
diff --git a/thirdparty/pcre2/src/pcre2_dfa_match.c b/thirdparty/pcre2/src/pcre2_dfa_match.c
index 060dc7669a..d29130f2d0 100644
--- a/thirdparty/pcre2/src/pcre2_dfa_match.c
+++ b/thirdparty/pcre2/src/pcre2_dfa_match.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2021 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -1193,6 +1193,11 @@ for (;;)
OK = prop->script == code[2];
break;
+ case PT_SCX:
+ OK = (prop->script == code[2] ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), code[2]) != 0);
+ break;
+
/* These are specials for combination cases. */
case PT_ALNUM:
@@ -1240,6 +1245,15 @@ for (;;)
c >= 0xe000;
break;
+ case PT_BIDICL:
+ OK = UCD_BIDICLASS(c) == code[2];
+ break;
+
+ case PT_BOOL:
+ OK = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), code[2]) != 0;
+ break;
+
/* Should never occur, but keep compilers from grumbling. */
default:
@@ -1451,6 +1465,11 @@ for (;;)
OK = prop->script == code[3];
break;
+ case PT_SCX:
+ OK = (prop->script == code[3] ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), code[3]) != 0);
+ break;
+
/* These are specials for combination cases. */
case PT_ALNUM:
@@ -1498,6 +1517,15 @@ for (;;)
c >= 0xe000;
break;
+ case PT_BIDICL:
+ OK = UCD_BIDICLASS(c) == code[3];
+ break;
+
+ case PT_BOOL:
+ OK = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), code[3]) != 0;
+ break;
+
/* Should never occur, but keep compilers from grumbling. */
default:
@@ -1692,6 +1720,11 @@ for (;;)
OK = prop->script == code[3];
break;
+ case PT_SCX:
+ OK = (prop->script == code[3] ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), code[3]) != 0);
+ break;
+
/* These are specials for combination cases. */
case PT_ALNUM:
@@ -1739,6 +1772,15 @@ for (;;)
c >= 0xe000;
break;
+ case PT_BIDICL:
+ OK = UCD_BIDICLASS(c) == code[3];
+ break;
+
+ case PT_BOOL:
+ OK = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), code[3]) != 0;
+ break;
+
/* Should never occur, but keep compilers from grumbling. */
default:
@@ -1958,6 +2000,12 @@ for (;;)
OK = prop->script == code[1 + IMM2_SIZE + 2];
break;
+ case PT_SCX:
+ OK = (prop->script == code[1 + IMM2_SIZE + 2] ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop),
+ code[1 + IMM2_SIZE + 2]) != 0);
+ break;
+
/* These are specials for combination cases. */
case PT_ALNUM:
@@ -2005,6 +2053,15 @@ for (;;)
c >= 0xe000;
break;
+ case PT_BIDICL:
+ OK = UCD_BIDICLASS(c) == code[1 + IMM2_SIZE + 2];
+ break;
+
+ case PT_BOOL:
+ OK = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), code[1 + IMM2_SIZE + 2]) != 0;
+ break;
+
/* Should never occur, but keep compilers from grumbling. */
default:
@@ -3285,20 +3342,22 @@ rws->next = NULL;
rws->size = RWS_BASE_SIZE;
rws->free = RWS_BASE_SIZE - RWS_ANCHOR_SIZE;
-/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
-subject string. */
+/* Recognize NULL, length 0 as an empty string. */
-if (length == PCRE2_ZERO_TERMINATED)
- {
- length = PRIV(strlen)(subject);
- was_zero_terminated = 1;
- }
+if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";
/* Plausibility checks */
if ((options & ~PUBLIC_DFA_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
if (re == NULL || subject == NULL || workspace == NULL || match_data == NULL)
return PCRE2_ERROR_NULL;
+
+if (length == PCRE2_ZERO_TERMINATED)
+ {
+ length = PRIV(strlen)(subject);
+ was_zero_terminated = 1;
+ }
+
if (wscount < 20) return PCRE2_ERROR_DFA_WSSIZE;
if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
diff --git a/thirdparty/pcre2/src/pcre2_error.c b/thirdparty/pcre2/src/pcre2_error.c
index 3dee63d0db..09904c03e3 100644
--- a/thirdparty/pcre2/src/pcre2_error.c
+++ b/thirdparty/pcre2/src/pcre2_error.c
@@ -119,7 +119,7 @@ static const unsigned char compile_error_texts[] =
/* 45 */
"this version of PCRE2 does not have support for \\P, \\p, or \\X\0"
"malformed \\P or \\p sequence\0"
- "unknown property name after \\P or \\p\0"
+ "unknown property after \\P or \\p\0"
"subpattern name is too long (maximum " XSTRING(MAX_NAME_SIZE) " code units)\0"
"too many named subpatterns (maximum " XSTRING(MAX_NAME_COUNT) ")\0"
/* 50 */
@@ -253,7 +253,7 @@ static const unsigned char match_error_texts[] =
"unknown substring\0"
/* 50 */
"non-unique substring name\0"
- "NULL argument passed\0"
+ "NULL argument passed with non-zero length\0"
"nested recursion at the same subject position\0"
"matching depth limit exceeded\0"
"requested value is not available\0"
diff --git a/thirdparty/pcre2/src/pcre2_extuni.c b/thirdparty/pcre2/src/pcre2_extuni.c
index 5a719e9cb4..b23946b0d1 100644
--- a/thirdparty/pcre2/src/pcre2_extuni.c
+++ b/thirdparty/pcre2/src/pcre2_extuni.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2019 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -105,7 +105,7 @@ while (eptr < end_subject)
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
- if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
+ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)
{
int ricount = 0;
PCRE2_SPTR bptr = eptr - 1;
@@ -123,7 +123,7 @@ while (eptr < end_subject)
}
else
c = *bptr;
- if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break;
ricount++;
}
if ((ricount & 1) != 0) break; /* Grapheme break required */
diff --git a/thirdparty/pcre2/src/pcre2_internal.h b/thirdparty/pcre2/src/pcre2_internal.h
index d8fad1e93b..fe7a0e005a 100644
--- a/thirdparty/pcre2/src/pcre2_internal.h
+++ b/thirdparty/pcre2/src/pcre2_internal.h
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2020 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -954,6 +954,13 @@ a positive value. */
#define STRING_LIMIT_RECURSION_EQ "LIMIT_RECURSION="
#define STRING_MARK "MARK"
+#define STRING_bc "bc"
+#define STRING_bidiclass "bidiclass"
+#define STRING_sc "sc"
+#define STRING_script "script"
+#define STRING_scriptextensions "scriptextensions"
+#define STRING_scx "scx"
+
#else /* SUPPORT_UNICODE */
/* UTF-8 support is enabled; always use UTF-8 (=ASCII) character codes. This
@@ -1248,26 +1255,39 @@ only. */
#define STRING_LIMIT_RECURSION_EQ STR_L STR_I STR_M STR_I STR_T STR_UNDERSCORE STR_R STR_E STR_C STR_U STR_R STR_S STR_I STR_O STR_N STR_EQUALS_SIGN
#define STRING_MARK STR_M STR_A STR_R STR_K
+#define STRING_bc STR_b STR_c
+#define STRING_bidiclass STR_b STR_i STR_d STR_i STR_c STR_l STR_a STR_s STR_s
+#define STRING_sc STR_s STR_c
+#define STRING_script STR_s STR_c STR_r STR_i STR_p STR_t
+#define STRING_scriptextensions STR_s STR_c STR_r STR_i STR_p STR_t STR_e STR_x STR_t STR_e STR_n STR_s STR_i STR_o STR_n STR_s
+#define STRING_scx STR_s STR_c STR_x
+
+
#endif /* SUPPORT_UNICODE */
/* -------------------- End of character and string names -------------------*/
/* -------------------- Definitions for compiled patterns -------------------*/
-/* Codes for different types of Unicode property */
+/* Codes for different types of Unicode property. If these definitions are
+changed, the autopossessifying table in pcre2_auto_possess.c must be updated to
+match. */
#define PT_ANY 0 /* Any property - matches all chars */
#define PT_LAMP 1 /* L& - the union of Lu, Ll, Lt */
#define PT_GC 2 /* Specified general characteristic (e.g. L) */
#define PT_PC 3 /* Specified particular characteristic (e.g. Lu) */
-#define PT_SC 4 /* Script (e.g. Han) */
-#define PT_ALNUM 5 /* Alphanumeric - the union of L and N */
-#define PT_SPACE 6 /* Perl space - Z plus 9,10,12,13 */
-#define PT_PXSPACE 7 /* POSIX space - Z plus 9,10,11,12,13 */
-#define PT_WORD 8 /* Word - L plus N plus underscore */
-#define PT_CLIST 9 /* Pseudo-property: match character list */
-#define PT_UCNC 10 /* Universal Character nameable character */
-#define PT_TABSIZE 11 /* Size of square table for autopossessify tests */
+#define PT_SC 4 /* Script only (e.g. Han) */
+#define PT_SCX 5 /* Script extensions (includes SC) */
+#define PT_ALNUM 6 /* Alphanumeric - the union of L and N */
+#define PT_SPACE 7 /* Perl space - general category Z plus 9,10,12,13 */
+#define PT_PXSPACE 8 /* POSIX space - Z plus 9,10,11,12,13 */
+#define PT_WORD 9 /* Word - L plus N plus underscore */
+#define PT_CLIST 10 /* Pseudo-property: match character list */
+#define PT_UCNC 11 /* Universal Character nameable character */
+#define PT_BIDICL 12 /* Specified bidi class */
+#define PT_BOOL 13 /* Boolean property */
+#define PT_TABSIZE 14 /* Size of square table for autopossessify tests */
/* The following special properties are used only in XCLASS items, when POSIX
classes are specified and PCRE2_UCP is set - in other words, for Unicode
@@ -1275,22 +1295,27 @@ handling of these classes. They are not available via the \p or \P escapes like
those in the above list, and so they do not take part in the autopossessifying
table. */
-#define PT_PXGRAPH 11 /* [:graph:] - characters that mark the paper */
-#define PT_PXPRINT 12 /* [:print:] - [:graph:] plus non-control spaces */
-#define PT_PXPUNCT 13 /* [:punct:] - punctuation characters */
+#define PT_PXGRAPH 14 /* [:graph:] - characters that mark the paper */
+#define PT_PXPRINT 15 /* [:print:] - [:graph:] plus non-control spaces */
+#define PT_PXPUNCT 16 /* [:punct:] - punctuation characters */
+
+/* This value is used when parsing \p and \P escapes to indicate that neither
+\p{script:...} nor \p{scx:...} has been encountered. */
+
+#define PT_NOTSCRIPT 255
/* Flag bits and data types for the extended class (OP_XCLASS) for classes that
contain characters with values greater than 255. */
-#define XCL_NOT 0x01 /* Flag: this is a negative class */
-#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
-#define XCL_HASPROP 0x04 /* Flag: property checks are present. */
+#define XCL_NOT 0x01 /* Flag: this is a negative class */
+#define XCL_MAP 0x02 /* Flag: a 32-byte map is present */
+#define XCL_HASPROP 0x04 /* Flag: property checks are present. */
-#define XCL_END 0 /* Marks end of individual items */
-#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
-#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
-#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
-#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
+#define XCL_END 0 /* Marks end of individual items */
+#define XCL_SINGLE 1 /* Single item (one multibyte char) follows */
+#define XCL_RANGE 2 /* A range (two multibyte chars) follows */
+#define XCL_PROP 3 /* Unicode property (2-byte property code follows) */
+#define XCL_NOTPROP 4 /* Unicode inverted property (ditto) */
/* These are escaped items that aren't just an encoding of a particular data
value such as \n. They must have non-zero values, as check_escape() returns 0
@@ -1797,8 +1822,8 @@ typedef struct {
uint8_t gbprop; /* ucp_gbControl, etc. (grapheme break property) */
uint8_t caseset; /* offset to multichar other cases or zero */
int32_t other_case; /* offset to other case, or zero if none */
- int16_t scriptx; /* script extension value */
- int16_t dummy; /* spare - to round to multiple of 4 bytes */
+ uint16_t scriptx_bidiclass; /* script extension (11 bit) and bidi class (5 bit) values */
+ uint16_t bprops; /* binary properties offset */
} ucd_record;
/* UCD access macros */
@@ -1815,13 +1840,30 @@ typedef struct {
#define GET_UCD(ch) REAL_GET_UCD(ch)
#endif
+#define UCD_SCRIPTX_MASK 0x3ff
+#define UCD_BIDICLASS_SHIFT 11
+#define UCD_BPROPS_MASK 0xfff
+
+#define UCD_SCRIPTX_PROP(prop) ((prop)->scriptx_bidiclass & UCD_SCRIPTX_MASK)
+#define UCD_BIDICLASS_PROP(prop) ((prop)->scriptx_bidiclass >> UCD_BIDICLASS_SHIFT)
+#define UCD_BPROPS_PROP(prop) ((prop)->bprops & UCD_BPROPS_MASK)
+
#define UCD_CHARTYPE(ch) GET_UCD(ch)->chartype
#define UCD_SCRIPT(ch) GET_UCD(ch)->script
#define UCD_CATEGORY(ch) PRIV(ucp_gentype)[UCD_CHARTYPE(ch)]
#define UCD_GRAPHBREAK(ch) GET_UCD(ch)->gbprop
#define UCD_CASESET(ch) GET_UCD(ch)->caseset
#define UCD_OTHERCASE(ch) ((uint32_t)((int)ch + (int)(GET_UCD(ch)->other_case)))
-#define UCD_SCRIPTX(ch) GET_UCD(ch)->scriptx
+#define UCD_SCRIPTX(ch) UCD_SCRIPTX_PROP(GET_UCD(ch))
+#define UCD_BPROPS(ch) UCD_BPROPS_PROP(GET_UCD(ch))
+#define UCD_BIDICLASS(ch) UCD_BIDICLASS_PROP(GET_UCD(ch))
+
+/* The "scriptx" and bprops fields contain offsets into vectors of 32-bit words
+that form a bitmap representing a list of scripts or boolean properties. These
+macros test or set a bit in the map by number. */
+
+#define MAPBIT(map,n) ((map)[(n)/32]&(1u<<((n)%32)))
+#define MAPSET(map,n) ((map)[(n)/32]|=(1u<<((n)%32)))
/* Header for serialized pcre2 codes. */
@@ -1878,6 +1920,7 @@ extern const uint8_t PRIV(utf8_table4)[];
#endif
#define _pcre2_hspace_list PCRE2_SUFFIX(_pcre2_hspace_list_)
#define _pcre2_vspace_list PCRE2_SUFFIX(_pcre2_vspace_list_)
+#define _pcre2_ucd_boolprop_sets PCRE2_SUFFIX(_pcre2_ucd_boolprop_sets_)
#define _pcre2_ucd_caseless_sets PCRE2_SUFFIX(_pcre2_ucd_caseless_sets_)
#define _pcre2_ucd_digit_sets PCRE2_SUFFIX(_pcre2_ucd_digit_sets_)
#define _pcre2_ucd_script_sets PCRE2_SUFFIX(_pcre2_ucd_script_sets_)
@@ -1901,9 +1944,10 @@ extern const pcre2_match_context PRIV(default_match_context);
extern const uint8_t PRIV(default_tables)[];
extern const uint32_t PRIV(hspace_list)[];
extern const uint32_t PRIV(vspace_list)[];
+extern const uint32_t PRIV(ucd_boolprop_sets)[];
extern const uint32_t PRIV(ucd_caseless_sets)[];
extern const uint32_t PRIV(ucd_digit_sets)[];
-extern const uint8_t PRIV(ucd_script_sets)[];
+extern const uint32_t PRIV(ucd_script_sets)[];
extern const ucd_record PRIV(ucd_records)[];
#if PCRE2_CODE_UNIT_WIDTH == 32
extern const ucd_record PRIV(dummy_ucd_record)[];
diff --git a/thirdparty/pcre2/src/pcre2_intmodedep.h b/thirdparty/pcre2/src/pcre2_intmodedep.h
index ea3b3ec698..f8a3d25de6 100644
--- a/thirdparty/pcre2/src/pcre2_intmodedep.h
+++ b/thirdparty/pcre2/src/pcre2_intmodedep.h
@@ -519,7 +519,7 @@ it is. This is called only in UTF-32 mode - we don't put a test within the
macro because almost all calls are already within a block of UTF-32 only
code.
-These are all no-ops since all UTF-32 characters fit into one pcre_uchar. */
+These are all no-ops since all UTF-32 characters fit into one PCRE2_UCHAR. */
#define BACKCHAR(eptr) do { } while (0)
@@ -747,8 +747,8 @@ typedef struct compile_block {
uint32_t class_range_start; /* Overall class range start */
uint32_t class_range_end; /* Overall class range end */
PCRE2_UCHAR nl[4]; /* Newline string when fixed length */
+ uint32_t req_varyopt; /* "After variable item" flag for reqbyte */
int max_lookbehind; /* Maximum lookbehind (characters) */
- int req_varyopt; /* "After variable item" flag for reqbyte */
BOOL had_accept; /* (*ACCEPT) encountered */
BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */
BOOL had_recurse; /* Had a recursion or subroutine call */
@@ -764,7 +764,7 @@ typedef struct pcre2_real_jit_stack {
} pcre2_real_jit_stack;
/* Structure for items in a linked list that represents an explicit recursive
-call within the pattern when running pcre_dfa_match(). */
+call within the pattern when running pcre2_dfa_match(). */
typedef struct dfa_recursion_info {
struct dfa_recursion_info *prevrec;
@@ -838,6 +838,17 @@ multiple of PCRE2_SIZE. See various comments above. */
typedef char check_heapframe_size[
((sizeof(heapframe) % sizeof(PCRE2_SIZE)) == 0)? (+1):(-1)];
+/* Structure for computing the alignment of heapframe. */
+
+typedef struct heapframe_align {
+ char unalign; /* Completely unalign the current offset */
+ heapframe frame; /* Offset is its alignment */
+} heapframe_align;
+
+/* This define is the minimum alignment required for a heapframe, in bytes. */
+
+#define HEAPFRAME_ALIGNMENT offsetof(heapframe_align, frame)
+
/* Structure for passing "static" information around between the functions
doing traditional NFA matching (pcre2_match() and friends). */
diff --git a/thirdparty/pcre2/src/pcre2_jit_compile.c b/thirdparty/pcre2/src/pcre2_jit_compile.c
index db2ce65598..d726c3ca04 100644
--- a/thirdparty/pcre2/src/pcre2_jit_compile.c
+++ b/thirdparty/pcre2/src/pcre2_jit_compile.c
@@ -8,7 +8,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
This module by Zoltan Herczeg
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2019 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -413,6 +413,9 @@ typedef struct compiler_common {
/* Locals used by fast fail optimization. */
sljit_s32 early_fail_start_ptr;
sljit_s32 early_fail_end_ptr;
+ /* Variables used by recursive call generator. */
+ sljit_s32 recurse_bitset_size;
+ uint8_t *recurse_bitset;
/* Flipped and lower case tables. */
const sljit_u8 *fcc;
@@ -613,6 +616,8 @@ the start pointers when the end of the capturing group has not yet reached. */
sljit_emit_op1(compiler, (op), (dst), (dstw), (src), (srcw))
#define OP2(op, dst, dstw, src1, src1w, src2, src2w) \
sljit_emit_op2(compiler, (op), (dst), (dstw), (src1), (src1w), (src2), (src2w))
+#define OP2U(op, src1, src1w, src2, src2w) \
+ sljit_emit_op2u(compiler, (op), (src1), (src1w), (src2), (src2w))
#define OP_SRC(op, src, srcw) \
sljit_emit_op_src(compiler, (op), (src), (srcw))
#define LABEL() \
@@ -1621,7 +1626,7 @@ if (end[-(1 + LINK_SIZE)] != OP_KET || PRIVATE_DATA(begin) != 0)
/* /(?:AB){4,6}/ is currently converted to /(?:AB){3}(?AB){1,3}/
* Skip the check of the second part. */
-if (PRIVATE_DATA(end - LINK_SIZE) == 0)
+if (PRIVATE_DATA(end - LINK_SIZE) != 0)
return TRUE;
next = end;
@@ -2315,22 +2320,47 @@ for (i = 0; i < RECURSE_TMP_REG_COUNT; i++)
#undef RECURSE_TMP_REG_COUNT
-static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,
- BOOL *needs_control_head, BOOL *has_quit, BOOL *has_accept)
+static BOOL recurse_check_bit(compiler_common *common, sljit_sw bit_index)
+{
+uint8_t *byte;
+uint8_t mask;
+
+SLJIT_ASSERT((bit_index & (sizeof(sljit_sw) - 1)) == 0);
+
+bit_index >>= SLJIT_WORD_SHIFT;
+
+SLJIT_ASSERT((bit_index >> 3) < common->recurse_bitset_size);
+
+mask = 1 << (bit_index & 0x7);
+byte = common->recurse_bitset + (bit_index >> 3);
+
+if (*byte & mask)
+ return FALSE;
+
+*byte |= mask;
+return TRUE;
+}
+
+enum get_recurse_flags {
+ recurse_flag_quit_found = (1 << 0),
+ recurse_flag_accept_found = (1 << 1),
+ recurse_flag_setsom_found = (1 << 2),
+ recurse_flag_setmark_found = (1 << 3),
+ recurse_flag_control_head_found = (1 << 4),
+};
+
+static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend, uint32_t *result_flags)
{
int length = 1;
-int size;
+int size, offset;
PCRE2_SPTR alternative;
-BOOL quit_found = FALSE;
-BOOL accept_found = FALSE;
-BOOL setsom_found = FALSE;
-BOOL setmark_found = FALSE;
-BOOL capture_last_found = FALSE;
-BOOL control_head_found = FALSE;
+uint32_t recurse_flags = 0;
+
+memset(common->recurse_bitset, 0, common->recurse_bitset_size);
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
SLJIT_ASSERT(common->control_head_ptr != 0);
-control_head_found = TRUE;
+recurse_flags |= recurse_flag_control_head_found;
#endif
/* Calculate the sum of the private machine words. */
@@ -2341,24 +2371,26 @@ while (cc < ccend)
{
case OP_SET_SOM:
SLJIT_ASSERT(common->has_set_som);
- setsom_found = TRUE;
+ recurse_flags |= recurse_flag_setsom_found;
cc += 1;
break;
case OP_RECURSE:
if (common->has_set_som)
- setsom_found = TRUE;
+ recurse_flags |= recurse_flag_setsom_found;
if (common->mark_ptr != 0)
- setmark_found = TRUE;
- if (common->capture_last_ptr != 0)
- capture_last_found = TRUE;
+ recurse_flags |= recurse_flag_setmark_found;
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
+ length++;
cc += 1 + LINK_SIZE;
break;
case OP_KET:
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0)
{
- length++;
+ if (recurse_check_bit(common, offset))
+ length++;
SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
cc += PRIVATE_DATA(cc + 1);
}
@@ -2377,39 +2409,55 @@ while (cc < ccend)
case OP_SBRA:
case OP_SBRAPOS:
case OP_SCOND:
- length++;
SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);
+ if (recurse_check_bit(common, PRIVATE_DATA(cc)))
+ length++;
cc += 1 + LINK_SIZE;
break;
case OP_CBRA:
case OP_SCBRA:
- length += 2;
- if (common->capture_last_ptr != 0)
- capture_last_found = TRUE;
- if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+ offset = GET2(cc, 1 + LINK_SIZE);
+ if (recurse_check_bit(common, OVECTOR(offset << 1)))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
+ length += 2;
+ }
+ if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, OVECTOR_PRIV(offset)))
+ length++;
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
length++;
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
case OP_CBRAPOS:
case OP_SCBRAPOS:
- length += 2 + 2;
- if (common->capture_last_ptr != 0)
- capture_last_found = TRUE;
+ offset = GET2(cc, 1 + LINK_SIZE);
+ if (recurse_check_bit(common, OVECTOR(offset << 1)))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
+ length += 2;
+ }
+ if (recurse_check_bit(common, OVECTOR_PRIV(offset)))
+ length++;
+ if (recurse_check_bit(common, PRIVATE_DATA(cc)))
+ length++;
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
+ length++;
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
case OP_COND:
/* Might be a hidden SCOND. */
alternative = cc + GET(cc, 1);
- if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+ if ((*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) && recurse_check_bit(common, PRIVATE_DATA(cc)))
length++;
cc += 1 + LINK_SIZE;
break;
CASE_ITERATOR_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
length++;
cc += 2;
#ifdef SUPPORT_UNICODE
@@ -2418,8 +2466,12 @@ while (cc < ccend)
break;
CASE_ITERATOR_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
length += 2;
+ }
cc += 2;
#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2427,8 +2479,12 @@ while (cc < ccend)
break;
CASE_ITERATOR_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
length += 2;
+ }
cc += 2 + IMM2_SIZE;
#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2436,20 +2492,29 @@ while (cc < ccend)
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
length++;
cc += 1;
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
length += 2;
+ }
cc += 1;
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc) != 0)
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
+ {
+ SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
length += 2;
+ }
cc += 1 + IMM2_SIZE;
break;
@@ -2461,7 +2526,9 @@ while (cc < ccend)
#else
size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#endif
- if (PRIVATE_DATA(cc) != 0)
+
+ offset = PRIVATE_DATA(cc);
+ if (offset != 0 && recurse_check_bit(common, offset))
length += get_class_iterator_size(cc + size);
cc += size;
break;
@@ -2471,12 +2538,11 @@ while (cc < ccend)
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
- if (!setmark_found)
- setmark_found = TRUE;
+ recurse_flags |= recurse_flag_setmark_found;
if (common->control_head_ptr != 0)
- control_head_found = TRUE;
+ recurse_flags |= recurse_flag_control_head_found;
if (*cc != OP_MARK)
- quit_found = TRUE;
+ recurse_flags |= recurse_flag_quit_found;
cc += 1 + 2 + cc[1];
break;
@@ -2484,26 +2550,24 @@ while (cc < ccend)
case OP_PRUNE:
case OP_SKIP:
case OP_COMMIT:
- quit_found = TRUE;
+ recurse_flags |= recurse_flag_quit_found;
cc++;
break;
case OP_SKIP_ARG:
- quit_found = TRUE;
+ recurse_flags |= recurse_flag_quit_found;
cc += 1 + 2 + cc[1];
break;
case OP_THEN:
SLJIT_ASSERT(common->control_head_ptr != 0);
- quit_found = TRUE;
- if (!control_head_found)
- control_head_found = TRUE;
+ recurse_flags |= recurse_flag_quit_found | recurse_flag_control_head_found;
cc++;
break;
case OP_ACCEPT:
case OP_ASSERT_ACCEPT:
- accept_found = TRUE;
+ recurse_flags |= recurse_flag_accept_found;
cc++;
break;
@@ -2515,21 +2579,17 @@ while (cc < ccend)
}
SLJIT_ASSERT(cc == ccend);
-if (control_head_found)
+if (recurse_flags & recurse_flag_control_head_found)
length++;
-if (capture_last_found)
- length++;
-if (quit_found)
+if (recurse_flags & recurse_flag_quit_found)
{
- if (setsom_found)
+ if (recurse_flags & recurse_flag_setsom_found)
length++;
- if (setmark_found)
+ if (recurse_flags & recurse_flag_setmark_found)
length++;
}
-*needs_control_head = control_head_found;
-*has_quit = quit_found;
-*has_accept = accept_found;
+*result_flags = recurse_flags;
return length;
}
@@ -2542,7 +2602,7 @@ enum copy_recurse_data_types {
};
static void copy_recurse_data(compiler_common *common, PCRE2_SPTR cc, PCRE2_SPTR ccend,
- int type, int stackptr, int stacktop, BOOL has_quit)
+ int type, int stackptr, int stacktop, uint32_t recurse_flags)
{
delayed_mem_copy_status status;
PCRE2_SPTR alternative;
@@ -2551,14 +2611,12 @@ sljit_sw shared_srcw[3];
sljit_sw kept_shared_srcw[2];
int private_count, shared_count, kept_shared_count;
int from_sp, base_reg, offset, i;
-BOOL setsom_found = FALSE;
-BOOL setmark_found = FALSE;
-BOOL capture_last_found = FALSE;
-BOOL control_head_found = FALSE;
+
+memset(common->recurse_bitset, 0, common->recurse_bitset_size);
#if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
SLJIT_ASSERT(common->control_head_ptr != 0);
-control_head_found = TRUE;
+recurse_check_bit(common, common->control_head_ptr);
#endif
switch (type)
@@ -2646,45 +2704,42 @@ while (cc < ccend)
{
case OP_SET_SOM:
SLJIT_ASSERT(common->has_set_som);
- if (has_quit && !setsom_found)
+ if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, OVECTOR(0)))
{
kept_shared_srcw[0] = OVECTOR(0);
kept_shared_count = 1;
- setsom_found = TRUE;
}
cc += 1;
break;
case OP_RECURSE:
- if (has_quit)
+ if (recurse_flags & recurse_flag_quit_found)
{
- if (common->has_set_som && !setsom_found)
+ if (common->has_set_som && recurse_check_bit(common, OVECTOR(0)))
{
kept_shared_srcw[0] = OVECTOR(0);
kept_shared_count = 1;
- setsom_found = TRUE;
}
- if (common->mark_ptr != 0 && !setmark_found)
+ if (common->mark_ptr != 0 && recurse_check_bit(common, common->mark_ptr))
{
kept_shared_srcw[kept_shared_count] = common->mark_ptr;
kept_shared_count++;
- setmark_found = TRUE;
}
}
- if (common->capture_last_ptr != 0 && !capture_last_found)
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
{
shared_srcw[0] = common->capture_last_ptr;
shared_count = 1;
- capture_last_found = TRUE;
}
cc += 1 + LINK_SIZE;
break;
case OP_KET:
- if (PRIVATE_DATA(cc) != 0)
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0)
{
- private_count = 1;
- private_srcw[0] = PRIVATE_DATA(cc);
+ if (recurse_check_bit(common, private_srcw[0]))
+ private_count = 1;
SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
cc += PRIVATE_DATA(cc + 1);
}
@@ -2703,50 +2758,66 @@ while (cc < ccend)
case OP_SBRA:
case OP_SBRAPOS:
case OP_SCOND:
- private_count = 1;
private_srcw[0] = PRIVATE_DATA(cc);
+ if (recurse_check_bit(common, private_srcw[0]))
+ private_count = 1;
cc += 1 + LINK_SIZE;
break;
case OP_CBRA:
case OP_SCBRA:
- offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
- shared_srcw[0] = OVECTOR(offset);
- shared_srcw[1] = OVECTOR(offset + 1);
- shared_count = 2;
+ offset = GET2(cc, 1 + LINK_SIZE);
+ shared_srcw[0] = OVECTOR(offset << 1);
+ if (recurse_check_bit(common, shared_srcw[0]))
+ {
+ shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));
+ shared_count = 2;
+ }
- if (common->capture_last_ptr != 0 && !capture_last_found)
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
{
- shared_srcw[2] = common->capture_last_ptr;
- shared_count = 3;
- capture_last_found = TRUE;
+ shared_srcw[shared_count] = common->capture_last_ptr;
+ shared_count++;
}
- if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+ if (common->optimized_cbracket[offset] == 0)
{
- private_count = 1;
- private_srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+ private_srcw[0] = OVECTOR_PRIV(offset);
+ if (recurse_check_bit(common, private_srcw[0]))
+ private_count = 1;
}
+
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
case OP_CBRAPOS:
case OP_SCBRAPOS:
- offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
- shared_srcw[0] = OVECTOR(offset);
- shared_srcw[1] = OVECTOR(offset + 1);
- shared_count = 2;
+ offset = GET2(cc, 1 + LINK_SIZE);
+ shared_srcw[0] = OVECTOR(offset << 1);
+ if (recurse_check_bit(common, shared_srcw[0]))
+ {
+ shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));
+ shared_count = 2;
+ }
- if (common->capture_last_ptr != 0 && !capture_last_found)
+ if (common->capture_last_ptr != 0 && recurse_check_bit(common, common->capture_last_ptr))
{
- shared_srcw[2] = common->capture_last_ptr;
- shared_count = 3;
- capture_last_found = TRUE;
+ shared_srcw[shared_count] = common->capture_last_ptr;
+ shared_count++;
}
- private_count = 2;
private_srcw[0] = PRIVATE_DATA(cc);
- private_srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+ if (recurse_check_bit(common, private_srcw[0]))
+ private_count = 1;
+
+ offset = OVECTOR_PRIV(offset);
+ if (recurse_check_bit(common, offset))
+ {
+ private_srcw[private_count] = offset;
+ private_count++;
+ }
cc += 1 + LINK_SIZE + IMM2_SIZE;
break;
@@ -2755,18 +2826,17 @@ while (cc < ccend)
alternative = cc + GET(cc, 1);
if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
{
- private_count = 1;
private_srcw[0] = PRIVATE_DATA(cc);
+ if (recurse_check_bit(common, private_srcw[0]))
+ private_count = 1;
}
cc += 1 + LINK_SIZE;
break;
CASE_ITERATOR_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc))
- {
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
private_count = 1;
- private_srcw[0] = PRIVATE_DATA(cc);
- }
cc += 2;
#ifdef SUPPORT_UNICODE
if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2774,11 +2844,12 @@ while (cc < ccend)
break;
CASE_ITERATOR_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc))
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
{
private_count = 2;
- private_srcw[0] = PRIVATE_DATA(cc);
- private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
}
cc += 2;
#ifdef SUPPORT_UNICODE
@@ -2787,11 +2858,12 @@ while (cc < ccend)
break;
CASE_ITERATOR_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc))
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
{
private_count = 2;
- private_srcw[0] = PRIVATE_DATA(cc);
- private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
}
cc += 2 + IMM2_SIZE;
#ifdef SUPPORT_UNICODE
@@ -2800,30 +2872,30 @@ while (cc < ccend)
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_1
- if (PRIVATE_DATA(cc))
- {
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
private_count = 1;
- private_srcw[0] = PRIVATE_DATA(cc);
- }
cc += 1;
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
- if (PRIVATE_DATA(cc))
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
{
private_count = 2;
- private_srcw[0] = PRIVATE_DATA(cc);
private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
}
cc += 1;
break;
CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
- if (PRIVATE_DATA(cc))
+ private_srcw[0] = PRIVATE_DATA(cc);
+ if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
{
private_count = 2;
- private_srcw[0] = PRIVATE_DATA(cc);
private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
}
cc += 1 + IMM2_SIZE;
break;
@@ -2837,23 +2909,28 @@ while (cc < ccend)
i = 1 + 32 / (int)sizeof(PCRE2_UCHAR);
#endif
if (PRIVATE_DATA(cc) != 0)
+ {
+ private_count = 1;
+ private_srcw[0] = PRIVATE_DATA(cc);
switch(get_class_iterator_size(cc + i))
{
case 1:
- private_count = 1;
- private_srcw[0] = PRIVATE_DATA(cc);
break;
case 2:
- private_count = 2;
- private_srcw[0] = PRIVATE_DATA(cc);
- private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ if (recurse_check_bit(common, private_srcw[0]))
+ {
+ private_count = 2;
+ private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+ SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
+ }
break;
default:
SLJIT_UNREACHABLE();
break;
}
+ }
cc += i;
break;
@@ -2862,28 +2939,25 @@ while (cc < ccend)
case OP_PRUNE_ARG:
case OP_THEN_ARG:
SLJIT_ASSERT(common->mark_ptr != 0);
- if (has_quit && !setmark_found)
+ if ((recurse_flags & recurse_flag_quit_found) && recurse_check_bit(common, common->mark_ptr))
{
kept_shared_srcw[0] = common->mark_ptr;
kept_shared_count = 1;
- setmark_found = TRUE;
}
- if (common->control_head_ptr != 0 && !control_head_found)
+ if (common->control_head_ptr != 0 && recurse_check_bit(common, common->control_head_ptr))
{
private_srcw[0] = common->control_head_ptr;
private_count = 1;
- control_head_found = TRUE;
}
cc += 1 + 2 + cc[1];
break;
case OP_THEN:
SLJIT_ASSERT(common->control_head_ptr != 0);
- if (!control_head_found)
+ if (recurse_check_bit(common, common->control_head_ptr))
{
private_srcw[0] = common->control_head_ptr;
private_count = 1;
- control_head_found = TRUE;
}
cc++;
break;
@@ -2891,7 +2965,7 @@ while (cc < ccend)
default:
cc = next_opcode(common, cc);
SLJIT_ASSERT(cc != NULL);
- break;
+ continue;
}
if (type != recurse_copy_shared_to_global && type != recurse_copy_kept_shared_to_global)
@@ -3743,9 +3817,9 @@ if (common->invalid_utf)
else
{
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
}
}
@@ -3982,7 +4056,7 @@ if (common->utf)
{
if (options & READ_CHAR_UPDATE_STR_PTR)
OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);
if (options & READ_CHAR_UPDATE_STR_PTR)
CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);
if (max >= 0xd800)
@@ -4010,9 +4084,9 @@ if (common->invalid_utf)
else
{
OP2(SLJIT_SUB, TMP2, 0, TMP1, 0, SLJIT_IMM, 0xd800);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x110000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0xe000 - 0xd800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
}
}
@@ -4167,7 +4241,7 @@ if (common->utf && negated)
if (sljit_has_cpu_feature(SLJIT_HAS_CMOV) && !HAS_VIRTUAL_REGISTERS)
{
OP2(SLJIT_ADD, RETURN_ADDR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);
CMOV(SLJIT_LESS, STR_PTR, RETURN_ADDR, 0);
}
else
@@ -4250,7 +4324,7 @@ if (common->utf)
/* Skip low surrogate if necessary. */
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xdc00);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xdc00);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -4267,7 +4341,7 @@ if (common->invalid_utf && !must_be_valid)
return;
}
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x110000);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x110000);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -4332,7 +4406,7 @@ OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
/* Searching for the first zero. */
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x3000);
@@ -4345,7 +4419,7 @@ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 6);
OP2(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x3f);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);
jump = JUMP(SLJIT_NOT_ZERO);
/* Three byte sequence. */
OP2(SLJIT_XOR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xe0000);
@@ -4373,7 +4447,7 @@ struct sljit_jump *compare;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x20);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, 0x20);
jump = JUMP(SLJIT_NOT_ZERO);
/* Two byte sequence. */
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
@@ -4432,7 +4506,7 @@ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
@@ -4447,14 +4521,14 @@ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0x20000);
exit_invalid[2] = NULL;
}
else
exit_invalid[2] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x10000);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x10000);
jump = JUMP(SLJIT_NOT_ZERO);
three_byte_entry = LABEL();
@@ -4462,7 +4536,7 @@ three_byte_entry = LABEL();
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2d800);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0xd800);
exit_invalid[3] = NULL;
}
@@ -4473,7 +4547,7 @@ OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
exit_invalid[4] = NULL;
}
@@ -4490,7 +4564,7 @@ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, 0);
exit_invalid[5] = NULL;
}
@@ -4500,7 +4574,7 @@ else
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xc10000);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);
exit_invalid[6] = NULL;
}
@@ -4522,7 +4596,7 @@ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
exit_invalid[8] = CMP(SLJIT_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x800);
jump = JUMP(SLJIT_NOT_ZERO);
OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);
@@ -4537,7 +4611,7 @@ OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0x80);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x40);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP2, 0, SLJIT_IMM, 0x40);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
exit_invalid[10] = NULL;
}
@@ -4830,7 +4904,7 @@ OP2(SLJIT_OR, TMP1, 0, TMP1, 0, TMP2, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, -0xd800);
exit_invalid[2] = NULL;
}
@@ -4840,7 +4914,7 @@ else
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xd800);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x800);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x800);
CMOV(SLJIT_LESS, TMP1, SLJIT_IMM, INVALID_UTF_CHAR);
exit_invalid[3] = NULL;
}
@@ -4865,7 +4939,7 @@ OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
if (has_cmov)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x100000);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0x100000);
CMOV(SLJIT_GREATER_EQUAL, TMP1, SLJIT_IMM, INVALID_UTF_CHAR - 0x10000);
exit_invalid[5] = NULL;
}
@@ -4968,7 +5042,7 @@ OP1(MOV_UCHAR, TMP2, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
exit_invalid[1] = CMP(SLJIT_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xdc00);
OP2(SLJIT_SUB, TMP2, 0, TMP2, 0, SLJIT_IMM, 0xdc00);
-OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, 0x400);
+OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, SLJIT_IMM, 0x400);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 0x10000);
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
@@ -5239,7 +5313,7 @@ if (newlinecheck)
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
end = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, common->newline & 0xff);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
@@ -5304,12 +5378,12 @@ else if (common->utf)
if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))
{
OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);
CMOV(SLJIT_LESS, STR_PTR, TMP2, 0);
}
else
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x400);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, SLJIT_IMM, 0x400);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_LESS);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -5860,7 +5934,7 @@ if (has_match_end)
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offset + 1));
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
@@ -6063,7 +6137,7 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
OP2(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, STR_END, 0, SLJIT_IMM, IN_UCHARS(max));
add_jump(compiler, &common->failed_match, JUMP(SLJIT_LESS));
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
else
@@ -6200,7 +6274,7 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_SUB, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, STR_PTR, 0, TMP1, 0);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_NOT_EQUAL);
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
@@ -6228,7 +6302,7 @@ if (common->nltype == NLTYPE_FIXED && common->newline > 255)
firstchar = CMP(SLJIT_LESS_EQUAL, STR_PTR, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(2));
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, STR_PTR, 0, TMP1, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, STR_PTR, 0, TMP1, 0);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER_EQUAL);
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, UCHAR_SHIFT);
@@ -6293,7 +6367,7 @@ if (JIT_HAS_FAST_FORWARD_CHAR_SIMD && (common->nltype == NLTYPE_FIXED || common-
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(1));
if (common->mode != PCRE2_JIT_COMPLETE)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
}
@@ -6319,7 +6393,7 @@ if (common->nltype == NLTYPE_ANY || common->nltype == NLTYPE_ANYCRLF)
notfoundnl = CMP(SLJIT_GREATER_EQUAL, STR_PTR, 0, STR_END, 0);
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), 0);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, CHAR_NL);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, CHAR_NL);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
#if PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, UCHAR_SHIFT);
@@ -6355,7 +6429,7 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
OP1(SLJIT_MOV, RETURN_ADDR, 0, STR_END, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(1));
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_END, 0, TMP1, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_END, 0, TMP1, 0);
CMOV(SLJIT_GREATER, STR_END, TMP1, 0);
}
@@ -6385,12 +6459,12 @@ if (!optimize_class(common, start_bits, (start_bits[31] & 0x80) != 0, FALSE, &ma
if (!HAS_VIRTUAL_REGISTERS)
{
OP2(SLJIT_SHL, TMP3, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP3, 0);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP3, 0);
}
else
{
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);
}
JUMPTO(SLJIT_ZERO, start);
}
@@ -6525,7 +6599,7 @@ jump = CMP(SLJIT_NOT_ZERO /* SIG_LESS */, TMP2, 0, SLJIT_IMM, 0);
OP_SRC(SLJIT_FAST_RETURN, RETURN_ADDR, 0);
JUMPHERE(jump);
-OP1(SLJIT_NEG, TMP2, 0, TMP2, 0);
+OP2(SLJIT_SUB, TMP2, 0, SLJIT_IMM, 0, TMP2, 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
if (HAS_VIRTUAL_REGISTERS)
{
@@ -6600,10 +6674,10 @@ if (common->ucp)
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
JUMPHERE(jump);
OP1(SLJIT_MOV, TMP3, 0, TMP2, 0);
@@ -6646,10 +6720,10 @@ if (common->ucp)
jump = CMP(SLJIT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_UNDERSCORE);
add_jump(compiler, &common->getucdtype, JUMP(SLJIT_FAST_CALL));
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, ucp_Nd - ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, ucp_No - ucp_Nd);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
JUMPHERE(jump);
}
@@ -6916,7 +6990,7 @@ j = 0;
if (char_list[0] == 0)
{
i++;
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_ZERO);
}
else
@@ -6928,7 +7002,7 @@ while (i < len)
j++;
else
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i]);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i]);
CMOV(SLJIT_ZERO, TMP2, TMP1, 0);
}
i++;
@@ -6942,7 +7016,7 @@ if (j != 0)
if ((char_list[i] & 0x100) != 0)
{
j--;
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, char_list[i] & 0xff);
CMOV(SLJIT_ZERO, TMP2, TMP1, 0);
}
}
@@ -6971,9 +7045,9 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
@@ -6981,7 +7055,7 @@ if (common->utf)
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
@@ -6997,29 +7071,29 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
-OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x09);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x09);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x20);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x20);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xa0);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xa0);
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
{
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x1680);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x1680);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x2000);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x200A - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x202f - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x205f - 0x2000);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x3000 - 0x2000);
#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
@@ -7037,9 +7111,9 @@ DEFINE_COMPILER;
sljit_emit_fast_enter(compiler, RETURN_ADDR, 0);
OP2(SLJIT_SUB, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x0a);
-OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x0d - 0x0a);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
-OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
+OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x0a);
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH == 16 || PCRE2_CODE_UNIT_WIDTH == 32
#if PCRE2_CODE_UNIT_WIDTH == 8
if (common->utf)
@@ -7047,7 +7121,7 @@ if (common->utf)
#endif
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, 0x1);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x2029 - 0x0a);
#if PCRE2_CODE_UNIT_WIDTH == 8
}
#endif
@@ -7412,6 +7486,21 @@ return cc;
static PCRE2_SPTR compile_char1_matchingpath(compiler_common *common, PCRE2_UCHAR type, PCRE2_SPTR cc, jump_list **backtracks, BOOL check_str_ptr);
+#ifdef SUPPORT_UNICODE
+#define XCLASS_SAVE_CHAR 0x001
+#define XCLASS_CHAR_SAVED 0x002
+#define XCLASS_HAS_TYPE 0x004
+#define XCLASS_HAS_SCRIPT 0x008
+#define XCLASS_HAS_SCRIPT_EXTENSION 0x010
+#define XCLASS_HAS_BOOL 0x020
+#define XCLASS_HAS_BIDICL 0x040
+#define XCLASS_NEEDS_UCD (XCLASS_HAS_TYPE | XCLASS_HAS_SCRIPT | XCLASS_HAS_SCRIPT_EXTENSION | XCLASS_HAS_BOOL | XCLASS_HAS_BIDICL)
+#define XCLASS_SCRIPT_EXTENSION_NOTPROP 0x080
+#define XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR 0x100
+#define XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0 0x200
+
+#endif /* SUPPORT_UNICODE */
+
static void compile_xclass_matchingpath(compiler_common *common, PCRE2_SPTR cc, jump_list **backtracks)
{
DEFINE_COMPILER;
@@ -7426,8 +7515,7 @@ BOOL utf = common->utf;
#endif /* SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == [8|16] */
#ifdef SUPPORT_UNICODE
-BOOL needstype = FALSE, needsscript = FALSE, needschar = FALSE;
-BOOL charsaved = FALSE;
+sljit_u32 unicode_status = 0;
int typereg = TMP1;
const sljit_u32 *other_cases;
sljit_uw typeoffset;
@@ -7454,7 +7542,7 @@ while (*cc != XCL_END)
if (c > max) max = c;
if (c < min) min = c;
#ifdef SUPPORT_UNICODE
- needschar = TRUE;
+ unicode_status |= XCLASS_SAVE_CHAR;
#endif /* SUPPORT_UNICODE */
}
else if (*cc == XCL_RANGE)
@@ -7465,7 +7553,7 @@ while (*cc != XCL_END)
GETCHARINCTEST(c, cc);
if (c > max) max = c;
#ifdef SUPPORT_UNICODE
- needschar = TRUE;
+ unicode_status |= XCLASS_SAVE_CHAR;
#endif /* SUPPORT_UNICODE */
}
#ifdef SUPPORT_UNICODE
@@ -7473,7 +7561,7 @@ while (*cc != XCL_END)
{
SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
cc++;
- if (*cc == PT_CLIST)
+ if (*cc == PT_CLIST && cc[-1] == XCL_PROP)
{
other_cases = PRIV(ucd_caseless_sets) + cc[1];
while (*other_cases != NOTACHAR)
@@ -7506,11 +7594,21 @@ while (*cc != XCL_END)
case PT_GC:
case PT_PC:
case PT_ALNUM:
- needstype = TRUE;
+ unicode_status |= XCLASS_HAS_TYPE;
break;
+ case PT_SCX:
+ unicode_status |= XCLASS_HAS_SCRIPT_EXTENSION;
+ if (cc[-1] == XCL_NOTPROP)
+ {
+ unicode_status |= XCLASS_SCRIPT_EXTENSION_NOTPROP;
+ break;
+ }
+ compares++;
+ /* Fall through */
+
case PT_SC:
- needsscript = TRUE;
+ unicode_status |= XCLASS_HAS_SCRIPT;
break;
case PT_SPACE:
@@ -7519,13 +7617,20 @@ while (*cc != XCL_END)
case PT_PXGRAPH:
case PT_PXPRINT:
case PT_PXPUNCT:
- needstype = TRUE;
- needschar = TRUE;
+ unicode_status |= XCLASS_SAVE_CHAR | XCLASS_HAS_TYPE;
break;
case PT_CLIST:
case PT_UCNC:
- needschar = TRUE;
+ unicode_status |= XCLASS_SAVE_CHAR;
+ break;
+
+ case PT_BOOL:
+ unicode_status |= XCLASS_HAS_BOOL;
+ break;
+
+ case PT_BIDICL:
+ unicode_status |= XCLASS_HAS_BIDICL;
break;
default:
@@ -7545,7 +7650,7 @@ if ((cc[-1] & XCL_NOT) != 0)
else
{
#ifdef SUPPORT_UNICODE
- read_char(common, min, max, (needstype || needsscript) ? backtracks : NULL, 0);
+ read_char(common, min, max, (unicode_status & XCLASS_NEEDS_UCD) ? backtracks : NULL, 0);
#else /* !SUPPORT_UNICODE */
read_char(common, min, max, NULL, 0);
#endif /* SUPPORT_UNICODE */
@@ -7562,7 +7667,7 @@ if ((cc[-1] & XCL_HASPROP) == 0)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);
add_jump(compiler, &found, JUMP(SLJIT_NOT_ZERO));
}
@@ -7581,7 +7686,7 @@ else if ((cc[-1] & XCL_MAP) != 0)
{
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
#ifdef SUPPORT_UNICODE
- charsaved = TRUE;
+ unicode_status |= XCLASS_CHAR_SAVED;
#endif /* SUPPORT_UNICODE */
if (!optimize_class(common, (const sljit_u8 *)cc, FALSE, TRUE, list))
{
@@ -7595,7 +7700,7 @@ else if ((cc[-1] & XCL_MAP) != 0)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);
add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO));
#if PCRE2_CODE_UNIT_WIDTH == 8
@@ -7609,9 +7714,9 @@ else if ((cc[-1] & XCL_MAP) != 0)
}
#ifdef SUPPORT_UNICODE
-if (needstype || needsscript)
+if (unicode_status & XCLASS_NEEDS_UCD)
{
- if (needschar && !charsaved)
+ if ((unicode_status & (XCLASS_SAVE_CHAR | XCLASS_CHAR_SAVED)) == XCLASS_SAVE_CHAR)
OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP1, 0);
#if PCRE2_CODE_UNIT_WIDTH == 32
@@ -7631,17 +7736,16 @@ if (needstype || needsscript)
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_IMM, (sljit_sw)PRIV(ucd_stage2));
OP1(SLJIT_MOV_U16, TMP2, 0, SLJIT_MEM2(TMP2, TMP1), 1);
+ OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);
+ OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+ OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
- /* Before anything else, we deal with scripts. */
- if (needsscript)
- {
- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
-
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+ ccbegin = cc;
- ccbegin = cc;
+ if (unicode_status & XCLASS_HAS_BIDICL)
+ {
+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));
+ OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BIDICLASS_SHIFT);
while (*cc != XCL_END)
{
@@ -7660,7 +7764,7 @@ if (needstype || needsscript)
{
SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
cc++;
- if (*cc == PT_SC)
+ if (*cc == PT_BIDICL)
{
compares--;
invertcmp = (compares == 0 && list != backtracks);
@@ -7674,52 +7778,176 @@ if (needstype || needsscript)
}
cc = ccbegin;
+ }
+
+ if (unicode_status & XCLASS_HAS_BOOL)
+ {
+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, bprops));
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_BPROPS_MASK);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
- if (needstype)
+ while (*cc != XCL_END)
{
- /* TMP2 has already been shifted by 2 */
- if (!needschar)
+ if (*cc == XCL_SINGLE)
{
- OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0);
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
-
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ }
+ else if (*cc == XCL_RANGE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ GETCHARINCTEST(c, cc);
}
else
{
- OP2(SLJIT_ADD, TMP1, 0, TMP2, 0, TMP2, 0);
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+ if (*cc == PT_BOOL)
+ {
+ compares--;
+ invertcmp = (compares == 0 && list != backtracks);
+ if (cc[-1] == XCL_NOTPROP)
+ invertcmp ^= 0x1;
- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
- OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
- typereg = RETURN_ADDR;
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_boolprop_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)1 << (cc[1] & 0x1f));
+ add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));
+ }
+ cc += 2;
}
}
- else if (needschar)
- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
+
+ cc = ccbegin;
}
- else if (needstype)
+
+ if (unicode_status & XCLASS_HAS_SCRIPT)
{
- OP2(SLJIT_SHL, TMP1, 0, TMP2, 0, SLJIT_IMM, 3);
- OP2(SLJIT_SHL, TMP2, 0, TMP2, 0, SLJIT_IMM, 2);
+ OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
- if (!needschar)
+ while (*cc != XCL_END)
{
- OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, TMP2, 0);
+ if (*cc == XCL_SINGLE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ }
+ else if (*cc == XCL_RANGE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ GETCHARINCTEST(c, cc);
+ }
+ else
+ {
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+ switch (*cc)
+ {
+ case PT_SCX:
+ if (cc[-1] == XCL_NOTPROP)
+ break;
+ /* Fall through */
+
+ case PT_SC:
+ compares--;
+ invertcmp = (compares == 0 && list != backtracks);
+ if (cc[-1] == XCL_NOTPROP)
+ invertcmp ^= 0x1;
- OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+ add_jump(compiler, compares > 0 ? list : backtracks, CMP(SLJIT_EQUAL ^ invertcmp, TMP1, 0, SLJIT_IMM, (int)cc[1]));
+ }
+ cc += 2;
+ }
}
- else
+
+ cc = ccbegin;
+ }
+
+ if (unicode_status & XCLASS_HAS_SCRIPT_EXTENSION)
+ {
+ OP1(SLJIT_MOV_U16, TMP1, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, scriptx_bidiclass));
+ OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, UCD_SCRIPTX_MASK);
+ OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 2);
+
+ if (unicode_status & XCLASS_SCRIPT_EXTENSION_NOTPROP)
{
- OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, TMP1, 0);
+ if (unicode_status & XCLASS_HAS_TYPE)
+ {
+ if (unicode_status & XCLASS_SAVE_CHAR)
+ {
+ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, TMP2, 0);
+ unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0;
+ }
+ else
+ {
+ OP1(SLJIT_MOV, RETURN_ADDR, 0, TMP2, 0);
+ unicode_status |= XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR;
+ }
+ }
+ OP1(SLJIT_MOV_U8, TMP2, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, script));
+ }
- OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
- OP1(SLJIT_MOV_U8, RETURN_ADDR, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
- typereg = RETURN_ADDR;
+ while (*cc != XCL_END)
+ {
+ if (*cc == XCL_SINGLE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ }
+ else if (*cc == XCL_RANGE)
+ {
+ cc ++;
+ GETCHARINCTEST(c, cc);
+ GETCHARINCTEST(c, cc);
+ }
+ else
+ {
+ SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
+ cc++;
+ if (*cc == PT_SCX)
+ {
+ compares--;
+ invertcmp = (compares == 0 && list != backtracks);
+
+ jump = NULL;
+ if (cc[-1] == XCL_NOTPROP)
+ {
+ jump = CMP(SLJIT_EQUAL, TMP2, 0, SLJIT_IMM, (int)cc[1]);
+ if (invertcmp)
+ {
+ add_jump(compiler, backtracks, jump);
+ jump = NULL;
+ }
+ invertcmp ^= 0x1;
+ }
+
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), (sljit_sw)(PRIV(ucd_script_sets) + (cc[1] >> 5)), SLJIT_IMM, (sljit_sw)1 << (cc[1] & 0x1f));
+ add_jump(compiler, compares > 0 ? list : backtracks, JUMP(SLJIT_NOT_ZERO ^ invertcmp));
+
+ if (jump != NULL)
+ JUMPHERE(jump);
+ }
+ cc += 2;
+ }
}
+
+ if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_LOCALS0)
+ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
+ else if (unicode_status & XCLASS_SCRIPT_EXTENSION_RESTORE_RETURN_ADDR)
+ OP1(SLJIT_MOV, TMP2, 0, RETURN_ADDR, 0);
+ cc = ccbegin;
}
- else if (needschar)
+
+ if (unicode_status & XCLASS_SAVE_CHAR)
OP1(SLJIT_MOV, TMP1, 0, RETURN_ADDR, 0);
+
+ if (unicode_status & XCLASS_HAS_TYPE)
+ {
+ if (unicode_status & XCLASS_SAVE_CHAR)
+ typereg = RETURN_ADDR;
+
+ OP1(SLJIT_MOV_U8, typereg, 0, SLJIT_MEM1(TMP2), (sljit_sw)PRIV(ucd_records) + SLJIT_OFFSETOF(ucd_record, chartype));
+ }
}
#endif /* SUPPORT_UNICODE */
@@ -7743,13 +7971,13 @@ while (*cc != XCL_END)
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
@@ -7769,13 +7997,13 @@ while (*cc != XCL_END)
if (numberofcmps < 3 && (*cc == XCL_SINGLE || *cc == XCL_RANGE))
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(numberofcmps == 0 ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
numberofcmps++;
}
else if (numberofcmps > 0)
{
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(c - charoffset));
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
numberofcmps = 0;
@@ -7801,11 +8029,11 @@ while (*cc != XCL_END)
break;
case PT_LAMP:
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Lu - typeoffset);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Ll - typeoffset);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Lt - typeoffset);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -7821,6 +8049,9 @@ while (*cc != XCL_END)
break;
case PT_SC:
+ case PT_SCX:
+ case PT_BOOL:
+ case PT_BIDICL:
compares++;
/* Do nothing. */
break;
@@ -7828,32 +8059,32 @@ while (*cc != XCL_END)
case PT_SPACE:
case PT_PXSPACE:
SET_CHAR_OFFSET(9);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0xd - 0x9);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x85 - 0x9);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x9);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
SET_TYPE_OFFSET(ucp_Zl);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Zl);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
case PT_WORD:
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_UNDERSCORE - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
/* Fall through. */
case PT_ALNUM:
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_Lu - ucp_Ll);
OP_FLAGS((*cc == PT_ALNUM) ? SLJIT_MOV : SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
SET_TYPE_OFFSET(ucp_Nd);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_No - ucp_Nd);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -7876,7 +8107,7 @@ while (*cc != XCL_END)
OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
}
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[1]);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[1]);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
other_cases += 2;
}
@@ -7889,41 +8120,41 @@ while (*cc != XCL_END)
OP2(SLJIT_ADD, TMP2, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)charoffset);
OP2(SLJIT_OR, TMP2, 0, TMP2, 0, SLJIT_IMM, other_cases[1] ^ other_cases[0]);
}
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, other_cases[2]);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, other_cases[2]);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(other_cases[0] - charoffset));
OP_FLAGS(SLJIT_OR | ((other_cases[3] == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
other_cases += 3;
}
else
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
}
while (*other_cases != NOTACHAR)
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(*other_cases++ - charoffset));
OP_FLAGS(SLJIT_OR | ((*other_cases == NOTACHAR) ? SLJIT_SET_Z : 0), TMP2, 0, SLJIT_EQUAL);
}
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
case PT_UCNC:
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_DOLLAR_SIGN - charoffset));
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_COMMERCIAL_AT - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (sljit_sw)(CHAR_GRAVE_ACCENT - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
SET_CHAR_OFFSET(0xa0);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, (sljit_sw)(0xd7ff - charoffset));
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_LESS_EQUAL);
SET_CHAR_OFFSET(0);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER_EQUAL, TMP1, 0, SLJIT_IMM, 0xe000 - 0);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_GREATER_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -7931,20 +8162,20 @@ while (*cc != XCL_END)
case PT_PXGRAPH:
/* C and Z groups are the farthest two groups. */
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
/* In case of ucp_Cf, we overwrite the result. */
SET_CHAR_OFFSET(0x2066);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x180e - 0x2066);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
JUMPHERE(jump);
@@ -7954,20 +8185,20 @@ while (*cc != XCL_END)
case PT_PXPRINT:
/* C and Z groups are the farthest two groups. */
SET_TYPE_OFFSET(ucp_Ll);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, typereg, 0, SLJIT_IMM, ucp_So - ucp_Ll);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_GREATER);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, typereg, 0, SLJIT_IMM, ucp_Zs - ucp_Ll);
OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_NOT_EQUAL);
jump = CMP(SLJIT_NOT_EQUAL, typereg, 0, SLJIT_IMM, ucp_Cf - ucp_Ll);
/* In case of ucp_Cf, we overwrite the result. */
SET_CHAR_OFFSET(0x2066);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x2069 - 0x2066);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0x061c - 0x2066);
OP_FLAGS(SLJIT_OR, TMP2, 0, SLJIT_EQUAL);
JUMPHERE(jump);
@@ -7976,15 +8207,15 @@ while (*cc != XCL_END)
case PT_PXPUNCT:
SET_TYPE_OFFSET(ucp_Sc);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_So - ucp_Sc);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS_EQUAL);
SET_CHAR_OFFSET(0);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, TMP1, 0, SLJIT_IMM, 0x7f);
OP_FLAGS(SLJIT_AND, TMP2, 0, SLJIT_LESS_EQUAL);
SET_TYPE_OFFSET(ucp_Pc);
- OP2(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, SLJIT_UNUSED, 0, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS_EQUAL, typereg, 0, SLJIT_IMM, ucp_Ps - ucp_Pc);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_LESS_EQUAL);
jump = JUMP(SLJIT_NOT_ZERO ^ invertcmp);
break;
@@ -8069,9 +8300,9 @@ switch(type)
else
{
jump[1] = CMP(SLJIT_EQUAL, TMP2, 0, STR_END, 0);
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP2, 0, STR_END, 0);
OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_LESS);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, (common->newline >> 8) & 0xff);
OP_FLAGS(SLJIT_OR | SLJIT_SET_Z, TMP2, 0, SLJIT_NOT_EQUAL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL));
check_partial(common, TRUE);
@@ -8094,7 +8325,7 @@ switch(type)
OP1(MOV_UCHAR, TMP1, 0, SLJIT_MEM1(STR_PTR), IN_UCHARS(0));
jump[1] = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, CHAR_CR);
OP2(SLJIT_ADD, TMP2, 0, STR_PTR, 0, SLJIT_IMM, IN_UCHARS(2));
- OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, TMP2, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_GREATER, TMP2, 0, STR_END, 0);
jump[2] = JUMP(SLJIT_GREATER);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_EQUAL) /* LESS */);
/* Equal. */
@@ -8137,10 +8368,10 @@ switch(type)
if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
}
else
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
if (!common->endonly)
@@ -8157,10 +8388,10 @@ switch(type)
if (HAS_VIRTUAL_REGISTERS)
{
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
}
else
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTEOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
check_partial(common, FALSE);
jump[0] = JUMP(SLJIT_JUMP);
@@ -8200,14 +8431,14 @@ switch(type)
OP1(SLJIT_MOV, TMP2, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, begin));
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
}
else
{
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
add_jump(compiler, backtracks, CMP(SLJIT_GREATER, STR_PTR, 0, TMP1, 0));
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
}
return cc;
@@ -8219,13 +8450,13 @@ switch(type)
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, begin));
jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
}
else
{
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, begin));
jump[1] = CMP(SLJIT_GREATER, STR_PTR, 0, TMP2, 0);
- OP2(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_UNUSED, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
+ OP2U(SLJIT_AND32 | SLJIT_SET_Z, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options), SLJIT_IMM, PCRE2_NOTBOL);
}
add_jump(compiler, backtracks, JUMP(SLJIT_NOT_ZERO));
jump[0] = JUMP(SLJIT_JUMP);
@@ -8319,7 +8550,7 @@ do
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
- if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
+ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)
{
ricount = 0;
bptr = prevcc;
@@ -8331,7 +8562,7 @@ do
BACKCHAR(bptr);
GETCHAR(c, bptr);
- if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)
break;
ricount++;
@@ -8387,7 +8618,7 @@ do
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
- if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
+ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)
{
ricount = 0;
bptr = prevcc;
@@ -8397,7 +8628,7 @@ do
{
GETCHARBACK_INVALID(c, bptr, start_subject, break);
- if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator)
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator)
break;
ricount++;
@@ -8455,7 +8686,7 @@ while (cc < end_subject)
/* Not breaking between Regional Indicators is allowed only if there
are an even number of preceding RIs. */
- if (lgb == ucp_gbRegionalIndicator && rgb == ucp_gbRegionalIndicator)
+ if (lgb == ucp_gbRegional_Indicator && rgb == ucp_gbRegional_Indicator)
{
ricount = 0;
bptr = cc - 1;
@@ -8470,7 +8701,7 @@ while (cc < end_subject)
break;
#endif /* PCRE2_CODE_UNIT_WIDTH == 32 */
- if (UCD_GRAPHBREAK(c) != ucp_gbRegionalIndicator) break;
+ if (UCD_GRAPHBREAK(c) != ucp_gbRegional_Indicator) break;
ricount++;
}
@@ -8520,7 +8751,7 @@ switch(type)
#endif
read_char8_type(common, backtracks, type == OP_NOT_DIGIT);
/* Flip the starting bit in the negative case. */
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_digit);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_digit);
add_jump(compiler, backtracks, JUMP(type == OP_DIGIT ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -8534,7 +8765,7 @@ switch(type)
else
#endif
read_char8_type(common, backtracks, type == OP_NOT_WHITESPACE);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_space);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_space);
add_jump(compiler, backtracks, JUMP(type == OP_WHITESPACE ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -8548,7 +8779,7 @@ switch(type)
else
#endif
read_char8_type(common, backtracks, type == OP_NOT_WORDCHAR);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, ctype_word);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, ctype_word);
add_jump(compiler, backtracks, JUMP(type == OP_WORDCHAR ? SLJIT_ZERO : SLJIT_NOT_ZERO));
return cc;
@@ -8596,7 +8827,7 @@ switch(type)
#elif PCRE2_CODE_UNIT_WIDTH == 16
jump[0] = CMP(SLJIT_LESS, TMP1, 0, SLJIT_IMM, 0xd800);
OP2(SLJIT_AND, TMP1, 0, TMP1, 0, SLJIT_IMM, 0xfc00);
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xd800);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, 0xd800);
OP_FLAGS(SLJIT_MOV, TMP1, 0, SLJIT_EQUAL);
OP2(SLJIT_SHL, TMP1, 0, TMP1, 0, SLJIT_IMM, 1);
OP2(SLJIT_ADD, STR_PTR, 0, STR_PTR, 0, TMP1, 0);
@@ -8690,13 +8921,13 @@ switch(type)
OP1(SLJIT_MOV, SLJIT_R0, 0, ARGUMENTS, 0);
#if PCRE2_CODE_UNIT_WIDTH != 32
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
- common->utf ? (common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_utf)) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,
+ common->utf ? (common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_utf)) : SLJIT_FUNC_ADDR(do_extuni_no_utf));
if (common->invalid_utf)
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
- common->invalid_utf ? SLJIT_FUNC_OFFSET(do_extuni_utf_invalid) : SLJIT_FUNC_OFFSET(do_extuni_no_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,
+ common->invalid_utf ? SLJIT_FUNC_ADDR(do_extuni_utf_invalid) : SLJIT_FUNC_ADDR(do_extuni_no_utf));
if (!common->utf || common->invalid_utf)
add_jump(compiler, backtracks, CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0));
#endif
@@ -8758,7 +8989,7 @@ switch(type)
if (sljit_has_cpu_feature(SLJIT_HAS_CMOV))
{
- OP2(SLJIT_SUB | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, oc);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z, TMP1, 0, SLJIT_IMM, oc);
CMOV(SLJIT_EQUAL, TMP1, SLJIT_IMM, c);
add_jump(compiler, backtracks, CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, c));
}
@@ -8878,7 +9109,7 @@ switch(type)
OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3);
OP1(SLJIT_MOV_U8, TMP1, 0, SLJIT_MEM1(TMP1), (sljit_sw)cc);
OP2(SLJIT_SHL, TMP2, 0, SLJIT_IMM, 1, TMP2, 0);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP1, 0, TMP2, 0);
add_jump(compiler, backtracks, JUMP(SLJIT_ZERO));
#if defined SUPPORT_UNICODE || PCRE2_CODE_UNIT_WIDTH != 8
@@ -9116,7 +9347,7 @@ if (common->utf && *cc == OP_REFI)
caseless_loop = LABEL();
OP1(SLJIT_MOV_U32, TMP1, 0, SLJIT_MEM1(TMP2), 0);
OP2(SLJIT_ADD, TMP2, 0, TMP2, 0, SLJIT_IMM, sizeof(uint32_t));
- OP2(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, char1_reg, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_Z | SLJIT_SET_LESS, TMP1, 0, char1_reg, 0);
JUMPTO(SLJIT_EQUAL, loop);
JUMPTO(SLJIT_LESS, caseless_loop);
@@ -9575,12 +9806,12 @@ OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LOCALS0, STR_PTR, 0);
/* SLJIT_R0 = arguments */
OP1(SLJIT_MOV, SLJIT_R1, 0, STACK_TOP, 0);
GET_LOCAL_BASE(SLJIT_R2, 0, OVECTOR_START);
-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(S32) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_callout));
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS3(32, W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_callout));
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(SLJIT_SP), LOCALS0);
free_stack(common, callout_arg_size);
/* Check return value. */
-OP2(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_UNUSED, 0, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
+OP2U(SLJIT_SUB32 | SLJIT_SET_Z | SLJIT_SET_SIG_GREATER, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_SIG_GREATER));
if (common->abort_label == NULL)
add_jump(compiler, &common->abort, JUMP(SLJIT_NOT_EQUAL) /* SIG_LESS */);
@@ -10148,10 +10379,10 @@ SLJIT_ASSERT(TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
#ifdef SUPPORT_UNICODE
-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM,
- common->utf ? SLJIT_FUNC_OFFSET(do_script_run_utf) : SLJIT_FUNC_OFFSET(do_script_run));
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM,
+ common->utf ? SLJIT_FUNC_ADDR(do_script_run_utf) : SLJIT_FUNC_ADDR(do_script_run));
#else
-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_script_run));
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_script_run));
#endif
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_RETURN_REG, 0);
@@ -11374,7 +11605,7 @@ switch(opcode)
if (common->mode == PCRE2_JIT_COMPLETE)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
else
@@ -11667,7 +11898,7 @@ switch(opcode)
if (common->mode == PCRE2_JIT_COMPLETE)
{
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
else
@@ -11751,9 +11982,9 @@ if (HAS_VIRTUAL_REGISTERS)
else
OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(ARGUMENTS), SLJIT_OFFSETOF(jit_arguments, options));
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
add_jump(compiler, &backtrack->topbacktracks, JUMP(SLJIT_NOT_ZERO));
-OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
+OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
if (common->accept_label == NULL)
add_jump(compiler, &common->accept, JUMP(SLJIT_ZERO));
else
@@ -13004,7 +13235,7 @@ if (opcode == OP_SKIP_ARG)
SLJIT_ASSERT(common->control_head_ptr != 0 && TMP1 == SLJIT_R0 && STR_PTR == SLJIT_R1);
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
OP1(SLJIT_MOV, SLJIT_R1, 0, SLJIT_IMM, (sljit_sw)(current->cc + 2));
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(do_search_mark));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(do_search_mark));
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_R0, 0);
add_jump(compiler, &common->reset_match, CMP(SLJIT_NOT_EQUAL, SLJIT_R0, 0, SLJIT_IMM, 0));
@@ -13248,10 +13479,8 @@ DEFINE_COMPILER;
PCRE2_SPTR cc = common->start + common->currententry->start;
PCRE2_SPTR ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE);
PCRE2_SPTR ccend = bracketend(cc) - (1 + LINK_SIZE);
-BOOL needs_control_head;
-BOOL has_quit;
-BOOL has_accept;
-int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &needs_control_head, &has_quit, &has_accept);
+uint32_t recurse_flags = 0;
+int private_data_size = get_recurse_data_length(common, ccbegin, ccend, &recurse_flags);
int alt_count, alt_max, local_size;
backtrack_common altbacktrack;
jump_list *match = NULL;
@@ -13285,12 +13514,12 @@ allocate_stack(common, private_data_size + local_size);
/* Save return address. */
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP2, 0);
-copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, has_quit);
+copy_recurse_data(common, ccbegin, ccend, recurse_copy_from_global, local_size, private_data_size + local_size, recurse_flags);
/* This variable is saved and restored all time when we enter or exit from a recursive context. */
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr, STACK_TOP, 0);
-if (needs_control_head)
+if (recurse_flags & recurse_flag_control_head_found)
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
if (alt_max > 1)
@@ -13315,10 +13544,10 @@ while (1)
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
return;
- allocate_stack(common, (alt_max > 1 || has_accept) ? 2 : 1);
+ allocate_stack(common, (alt_max > 1 || (recurse_flags & recurse_flag_accept_found)) ? 2 : 1);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
- if (alt_max > 1 || has_accept)
+ if (alt_max > 1 || (recurse_flags & recurse_flag_accept_found))
{
if (alt_max > 3)
put_label = sljit_emit_put_label(compiler, SLJIT_MEM1(STACK_TOP), STACK(1));
@@ -13337,14 +13566,14 @@ while (1)
sljit_emit_fast_enter(compiler, TMP1, 0);
- if (has_accept)
+ if (recurse_flags & recurse_flag_accept_found)
accept_exit = CMP(SLJIT_EQUAL, SLJIT_MEM1(STACK_TOP), STACK(1), SLJIT_IMM, -1);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
/* Save return address. */
OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), STACK(local_size - 1), TMP1, 0);
- copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit);
+ copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);
if (alt_max > 1)
{
@@ -13361,7 +13590,7 @@ while (1)
next_alt = CMP(SLJIT_NOT_EQUAL, TMP1, 0, SLJIT_IMM, 0);
}
else
- free_stack(common, has_accept ? 2 : 1);
+ free_stack(common, (recurse_flags & recurse_flag_accept_found) ? 2 : 1);
}
else if (alt_max > 3)
{
@@ -13396,7 +13625,7 @@ while (1)
quit = LABEL();
-copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, has_quit);
+copy_recurse_data(common, ccbegin, ccend, recurse_copy_private_to_global, local_size, private_data_size + local_size, recurse_flags);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));
free_stack(common, private_data_size + local_size);
@@ -13405,15 +13634,15 @@ OP_SRC(SLJIT_FAST_RETURN, TMP2, 0);
if (common->quit != NULL)
{
- SLJIT_ASSERT(has_quit);
+ SLJIT_ASSERT(recurse_flags & recurse_flag_quit_found);
set_jumps(common->quit, LABEL());
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), common->recursive_head_ptr);
- copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, has_quit);
+ copy_recurse_data(common, ccbegin, ccend, recurse_copy_shared_to_global, local_size, private_data_size + local_size, recurse_flags);
JUMPTO(SLJIT_JUMP, quit);
}
-if (has_accept)
+if (recurse_flags & recurse_flag_accept_found)
{
JUMPHERE(accept_exit);
free_stack(common, 2);
@@ -13421,7 +13650,7 @@ if (has_accept)
/* Save return address. */
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1), TMP1, 0);
- copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, has_quit);
+ copy_recurse_data(common, ccbegin, ccend, recurse_copy_kept_shared_to_global, local_size, private_data_size + local_size, recurse_flags);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(STACK_TOP), STACK(local_size - 1));
free_stack(common, private_data_size + local_size);
@@ -13431,7 +13660,7 @@ if (has_accept)
if (common->accept != NULL)
{
- SLJIT_ASSERT(has_accept);
+ SLJIT_ASSERT(recurse_flags & recurse_flag_accept_found);
set_jumps(common->accept, LABEL());
@@ -13446,7 +13675,7 @@ set_jumps(match, LABEL());
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), TMP2, 0);
-copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, has_quit);
+copy_recurse_data(common, ccbegin, ccend, recurse_swap_global, local_size, private_data_size + local_size, recurse_flags);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP2), STACK(local_size - 1));
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 1);
@@ -13652,7 +13881,7 @@ SLJIT_ASSERT(!(common->req_char_ptr != 0 && common->start_used_ptr != 0));
common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * sizeof(sljit_sw);
total_length = ccend - common->start;
-common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);
+common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length * (sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);
if (!common->private_data_ptrs)
{
SLJIT_FREE(common->optimized_cbracket, allocator_data);
@@ -13692,8 +13921,9 @@ if (!compiler)
}
common->compiler = compiler;
-/* Main pcre_jit_exec entry. */
-sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);
+/* Main pcre2_jit_exec entry. */
+SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0);
+sljit_emit_enter(compiler, 0, SLJIT_ARGS1(W, W), 5, 5, 0, 0, private_data_size);
/* Register init. */
reset_ovector(common, (re->top_bracket + 1) * 2);
@@ -13900,9 +14130,9 @@ if (common->might_be_empty)
JUMPHERE(empty_match);
OP1(SLJIT_MOV, TMP1, 0, ARGUMENTS, 0);
OP1(SLJIT_MOV_U32, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, options));
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY);
JUMPTO(SLJIT_NOT_ZERO, empty_match_backtrack_label);
- OP2(SLJIT_AND | SLJIT_SET_Z, SLJIT_UNUSED, 0, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
+ OP2U(SLJIT_AND | SLJIT_SET_Z, TMP2, 0, SLJIT_IMM, PCRE2_NOTEMPTY_ATSTART);
JUMPTO(SLJIT_ZERO, empty_match_found_label);
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, str));
CMPTO(SLJIT_NOT_EQUAL, TMP2, 0, STR_PTR, 0, empty_match_found_label);
@@ -13915,20 +14145,40 @@ common->early_fail_end_ptr = 0;
common->currententry = common->entries;
common->local_quit_available = TRUE;
quit_label = common->quit_label;
-while (common->currententry != NULL)
+if (common->currententry != NULL)
{
- /* Might add new entries. */
- compile_recurse(common);
- if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ /* A free bit for each private data. */
+ common->recurse_bitset_size = ((private_data_size / (int)sizeof(sljit_sw)) + 7) >> 3;
+ SLJIT_ASSERT(common->recurse_bitset_size > 0);
+ common->recurse_bitset = (sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);;
+
+ if (common->recurse_bitset != NULL)
+ {
+ do
+ {
+ /* Might add new entries. */
+ compile_recurse(common);
+ if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+ break;
+ flush_stubs(common);
+ common->currententry = common->currententry->next;
+ }
+ while (common->currententry != NULL);
+
+ SLJIT_FREE(common->recurse_bitset, allocator_data);
+ }
+
+ if (common->currententry != NULL)
{
+ /* The common->recurse_bitset has been freed. */
+ SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset == NULL);
+
sljit_free_compiler(compiler);
SLJIT_FREE(common->optimized_cbracket, allocator_data);
SLJIT_FREE(common->private_data_ptrs, allocator_data);
PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
return PCRE2_ERROR_NOMEMORY;
}
- flush_stubs(common);
- common->currententry = common->currententry->next;
}
common->local_quit_available = FALSE;
common->quit_label = quit_label;
@@ -13947,7 +14197,7 @@ OP2(SLJIT_SUB, SLJIT_R1, 0, STACK_LIMIT, 0, SLJIT_IMM, STACK_GROWTH_RATE);
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), SLJIT_OFFSETOF(jit_arguments, stack));
OP1(SLJIT_MOV, STACK_LIMIT, 0, TMP2, 0);
-sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW), SLJIT_IMM, SLJIT_FUNC_OFFSET(sljit_stack_resize));
+sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS2(W, W, W), SLJIT_IMM, SLJIT_FUNC_ADDR(sljit_stack_resize));
jump = CMP(SLJIT_EQUAL, SLJIT_RETURN_REG, 0, SLJIT_IMM, 0);
OP1(SLJIT_MOV, TMP2, 0, STACK_LIMIT, 0);
diff --git a/thirdparty/pcre2/src/pcre2_jit_match.c b/thirdparty/pcre2/src/pcre2_jit_match.c
index 7e13b8cfee..1ab3af073e 100644
--- a/thirdparty/pcre2/src/pcre2_jit_match.c
+++ b/thirdparty/pcre2/src/pcre2_jit_match.c
@@ -120,7 +120,7 @@ else if ((options & PCRE2_PARTIAL_SOFT) != 0)
if (functions == NULL || functions->executable_funcs[index] == NULL)
return PCRE2_ERROR_JIT_BADOPTION;
-/* Sanity checks should be handled by pcre_exec. */
+/* Sanity checks should be handled by pcre2_match. */
arguments.str = subject + start_offset;
arguments.begin = subject;
arguments.end = subject + length;
diff --git a/thirdparty/pcre2/src/pcre2_jit_misc.c b/thirdparty/pcre2/src/pcre2_jit_misc.c
index ec924e0f9b..e57afad065 100644
--- a/thirdparty/pcre2/src/pcre2_jit_misc.c
+++ b/thirdparty/pcre2/src/pcre2_jit_misc.c
@@ -135,7 +135,7 @@ return NULL;
pcre2_jit_stack *jit_stack;
-if (startsize < 1 || maxsize < 1)
+if (startsize == 0 || maxsize == 0 || maxsize > SIZE_MAX - STACK_GROWTH_RATE)
return NULL;
if (startsize > maxsize)
startsize = maxsize;
diff --git a/thirdparty/pcre2/src/pcre2_jit_simd_inc.h b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h
index aa029cce38..d99cfc5ce4 100644
--- a/thirdparty/pcre2/src/pcre2_jit_simd_inc.h
+++ b/thirdparty/pcre2/src/pcre2_jit_simd_inc.h
@@ -339,7 +339,7 @@ if (common->mode != PCRE2_JIT_COMPLETE)
{
JUMPHERE(partial_quit[0]);
JUMPHERE(partial_quit[1]);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
else
@@ -537,7 +537,7 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);
CMOV(SLJIT_LESS, STR_END, TMP1, 0);
}
@@ -883,14 +883,14 @@ if (char1 == char2)
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_utf));
else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs));
#endif
}
else
@@ -904,14 +904,14 @@ else
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask_utf));
else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_mask));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_mask));
#endif
}
else
@@ -922,14 +922,14 @@ else
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf && offset > 0)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2_utf));
else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));
#else
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(UW) | SLJIT_ARG3(UW) | SLJIT_ARG4(UW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcs_2));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcs_2));
#endif
}
}
@@ -1067,7 +1067,7 @@ else
OP1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_SP), common->match_end_ptr);
OP2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, STR_END, 0, SLJIT_R0, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, STR_END, 0, SLJIT_R0, 0);
CMOV(SLJIT_LESS, SLJIT_R0, STR_END, 0);
}
@@ -1084,31 +1084,31 @@ if (diff == 1) {
if (char1a == char1b && char2a == char2b) {
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0_utf));
else
#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_0));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_0));
} else {
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1_utf));
else
#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_1));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_1));
}
} else {
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH != 32
if (common->utf)
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default_utf));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default_utf));
else
#endif
- sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_RET(SW) | SLJIT_ARG1(SW) | SLJIT_ARG2(SW) | SLJIT_ARG3(SW) | SLJIT_ARG4(SW),
- SLJIT_IMM, SLJIT_FUNC_OFFSET(ffcps_default));
+ sljit_emit_icall(compiler, SLJIT_CALL, SLJIT_ARGS4(W, W, W, W, W),
+ SLJIT_IMM, SLJIT_FUNC_ADDR(ffcps_default));
}
/* Restore STR_PTR register. */
@@ -1418,7 +1418,7 @@ if (common->mode != PCRE2_JIT_COMPLETE)
{
JUMPHERE(partial_quit[0]);
JUMPHERE(partial_quit[1]);
- OP2(SLJIT_SUB | SLJIT_SET_GREATER, SLJIT_UNUSED, 0, STR_PTR, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_GREATER, STR_PTR, 0, STR_END, 0);
CMOV(SLJIT_GREATER, STR_PTR, STR_END, 0);
}
else
@@ -1673,7 +1673,7 @@ if (common->match_end_ptr != 0)
OP1(SLJIT_MOV, TMP3, 0, STR_END, 0);
OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, IN_UCHARS(offs1 + 1));
- OP2(SLJIT_SUB | SLJIT_SET_LESS, SLJIT_UNUSED, 0, TMP1, 0, STR_END, 0);
+ OP2U(SLJIT_SUB | SLJIT_SET_LESS, TMP1, 0, STR_END, 0);
CMOV(SLJIT_LESS, STR_END, TMP1, 0);
}
diff --git a/thirdparty/pcre2/src/pcre2_match.c b/thirdparty/pcre2/src/pcre2_match.c
index f28cdbb47a..6354e1bb9e 100644
--- a/thirdparty/pcre2/src/pcre2_match.c
+++ b/thirdparty/pcre2/src/pcre2_match.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2015-2021 University of Cambridge
+ New API code Copyright (c) 2015-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -49,7 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
/* #define DEBUG_SHOW_OPS */
/* #define DEBUG_SHOW_RMATCH */
-#ifdef DEBUG_FRAME_DISPLAY
+#ifdef DEBUG_FRAMES_DISPLAY
#include <stdarg.h>
#endif
@@ -159,7 +159,8 @@ enum { RM100=100, RM101 };
#ifdef SUPPORT_UNICODE
enum { RM200=200, RM201, RM202, RM203, RM204, RM205, RM206, RM207,
RM208, RM209, RM210, RM211, RM212, RM213, RM214, RM215,
- RM216, RM217, RM218, RM219, RM220, RM221, RM222 };
+ RM216, RM217, RM218, RM219, RM220, RM221, RM222, RM223,
+ RM224, RM225 };
#endif
/* Define short names for general fields in the current backtrack frame, which
@@ -2421,40 +2422,49 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
const uint32_t *cp;
const ucd_record *prop = GET_UCD(fc);
+ BOOL notmatch = Fop == OP_NOTPROP;
switch(Fecode[1])
{
case PT_ANY:
- if (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ if (notmatch) RRETURN(MATCH_NOMATCH);
break;
case PT_LAMP:
if ((prop->chartype == ucp_Lu ||
prop->chartype == ucp_Ll ||
- prop->chartype == ucp_Lt) == (Fop == OP_NOTPROP))
+ prop->chartype == ucp_Lt) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
case PT_GC:
- if ((Fecode[2] != PRIV(ucp_gentype)[prop->chartype]) == (Fop == OP_PROP))
+ if ((Fecode[2] == PRIV(ucp_gentype)[prop->chartype]) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
case PT_PC:
- if ((Fecode[2] != prop->chartype) == (Fop == OP_PROP))
+ if ((Fecode[2] == prop->chartype) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
case PT_SC:
- if ((Fecode[2] != prop->script) == (Fop == OP_PROP))
+ if ((Fecode[2] == prop->script) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
+ case PT_SCX:
+ {
+ BOOL ok = (Fecode[2] == prop->script ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Fecode[2]) != 0);
+ if (ok == notmatch) RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
/* These are specials */
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
- PRIV(ucp_gentype)[prop->chartype] == ucp_N) == (Fop == OP_NOTPROP))
+ PRIV(ucp_gentype)[prop->chartype] == ucp_N) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
@@ -2468,12 +2478,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
HSPACE_CASES:
VSPACE_CASES:
- if (Fop == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ if (notmatch) RRETURN(MATCH_NOMATCH);
break;
default:
- if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) ==
- (Fop == OP_NOTPROP)) RRETURN(MATCH_NOMATCH);
+ if ((PRIV(ucp_gentype)[prop->chartype] == ucp_Z) == notmatch)
+ RRETURN(MATCH_NOMATCH);
break;
}
break;
@@ -2481,7 +2491,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
case PT_WORD:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N ||
- fc == CHAR_UNDERSCORE) == (Fop == OP_NOTPROP))
+ fc == CHAR_UNDERSCORE) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
@@ -2490,19 +2500,32 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
for (;;)
{
if (fc < *cp)
- { if (Fop == OP_PROP) { RRETURN(MATCH_NOMATCH); } else break; }
+ { if (notmatch) break; else { RRETURN(MATCH_NOMATCH); } }
if (fc == *cp++)
- { if (Fop == OP_PROP) break; else { RRETURN(MATCH_NOMATCH); } }
+ { if (notmatch) { RRETURN(MATCH_NOMATCH); } else break; }
}
break;
case PT_UCNC:
if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
- fc >= 0xe000) == (Fop == OP_NOTPROP))
+ fc >= 0xe000) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
+ case PT_BIDICL:
+ if ((UCD_BIDICLASS_PROP(prop) == Fecode[2]) == notmatch)
+ RRETURN(MATCH_NOMATCH);
+ break;
+
+ case PT_BOOL:
+ {
+ BOOL ok = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), Fecode[2]) != 0;
+ if (ok == notmatch) RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
/* This should never occur */
default:
@@ -2616,18 +2639,20 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
/* First, ensure the minimum number of matches are present. Use inline
code for maximizing the speed, and do the type test once at the start
- (i.e. keep it out of the loop). The code for UTF mode is separated out for
- tidiness, except for Unicode property tests. */
+ (i.e. keep it out of the loops). As there are no calls to RMATCH in the
+ loops, we can use an ordinary variable for "notmatch". The code for UTF
+ mode is separated out for tidiness, except for Unicode property tests. */
if (Lmin > 0)
{
#ifdef SUPPORT_UNICODE
if (proptype >= 0) /* Property tests in all modes */
{
+ BOOL notmatch = Lctype == OP_NOTPROP;
switch(proptype)
{
case PT_ANY:
- if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ if (notmatch) RRETURN(MATCH_NOMATCH);
for (i = 1; i <= Lmin; i++)
{
if (Feptr >= mb->end_subject)
@@ -2652,7 +2677,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
chartype = UCD_CHARTYPE(fc);
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
- chartype == ucp_Lt) == (Lctype == OP_NOTPROP))
+ chartype == ucp_Lt) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2666,7 +2691,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
- if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
+ if ((UCD_CATEGORY(fc) == Lpropvalue) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2680,7 +2705,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
- if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
+ if ((UCD_CHARTYPE(fc) == Lpropvalue) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2694,7 +2719,26 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
RRETURN(MATCH_NOMATCH);
}
GETCHARINCTEST(fc, Feptr);
- if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
+ if ((UCD_SCRIPT(fc) == Lpropvalue) == notmatch)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_SCX:
+ for (i = 1; i <= Lmin; i++)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ prop = GET_UCD(fc);
+ ok = (prop->script == Lpropvalue ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
+ if (ok == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2710,7 +2754,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
GETCHARINCTEST(fc, Feptr);
category = UCD_CATEGORY(fc);
- if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP))
+ if ((category == ucp_L || category == ucp_N) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2733,11 +2777,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
HSPACE_CASES:
VSPACE_CASES:
- if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ if (notmatch) RRETURN(MATCH_NOMATCH);
break;
default:
- if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP))
+ if ((UCD_CATEGORY(fc) == ucp_Z) == notmatch)
RRETURN(MATCH_NOMATCH);
break;
}
@@ -2756,7 +2800,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHARINCTEST(fc, Feptr);
category = UCD_CATEGORY(fc);
if ((category == ucp_L || category == ucp_N ||
- fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP))
+ fc == CHAR_UNDERSCORE) == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -2776,12 +2820,12 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
if (fc < *cp)
{
- if (Lctype == OP_NOTPROP) break;
+ if (notmatch) break;
RRETURN(MATCH_NOMATCH);
}
if (fc == *cp++)
{
- if (Lctype == OP_NOTPROP) RRETURN(MATCH_NOMATCH);
+ if (notmatch) RRETURN(MATCH_NOMATCH);
break;
}
}
@@ -2799,7 +2843,40 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHARINCTEST(fc, Feptr);
if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
- fc >= 0xe000) == (Lctype == OP_NOTPROP))
+ fc >= 0xe000) == notmatch)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_BIDICL:
+ for (i = 1; i <= Lmin; i++)
+ {
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ if ((UCD_BIDICLASS(fc) == Lpropvalue) == notmatch)
+ RRETURN(MATCH_NOMATCH);
+ }
+ break;
+
+ case PT_BOOL:
+ for (i = 1; i <= Lmin; i++)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ prop = GET_UCD(fc);
+ ok = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
+ if (ok == notmatch)
RRETURN(MATCH_NOMATCH);
}
break;
@@ -3343,7 +3420,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
if (Lmin == Lmax) continue;
/* If minimizing, we have to test the rest of the pattern before each
- subsequent match. */
+ subsequent match. This means we cannot use a local "notmatch" variable as
+ in the other cases. As all 4 temporary 32-bit values in the frame are
+ already in use, just test the type each time. */
if (reptype == REPTYPE_MIN)
{
@@ -3440,6 +3519,28 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
/* Control never gets here */
+ case PT_SCX:
+ for (;;)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ RMATCH(Fecode, RM225);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ prop = GET_UCD(fc);
+ ok = (prop->script == Lpropvalue
+ || MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
+ if (ok == (Lctype == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
case PT_ALNUM:
for (;;)
{
@@ -3454,8 +3555,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
GETCHARINCTEST(fc, Feptr);
category = UCD_CATEGORY(fc);
- if ((category == ucp_L || category == ucp_N) ==
- (Lctype == OP_NOTPROP))
+ if ((category == ucp_L || category == ucp_N) == (Lctype == OP_NOTPROP))
RRETURN(MATCH_NOMATCH);
}
/* Control never gets here */
@@ -3562,6 +3662,45 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
/* Control never gets here */
+ case PT_BIDICL:
+ for (;;)
+ {
+ RMATCH(Fecode, RM224);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ if ((UCD_BIDICLASS(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
+ case PT_BOOL:
+ for (;;)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ RMATCH(Fecode, RM223);
+ if (rrc != MATCH_NOMATCH) RRETURN(rrc);
+ if (Lmin++ >= Lmax) RRETURN(MATCH_NOMATCH);
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ RRETURN(MATCH_NOMATCH);
+ }
+ GETCHARINCTEST(fc, Feptr);
+ prop = GET_UCD(fc);
+ ok = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
+ if (ok == (Lctype == OP_NOTPROP))
+ RRETURN(MATCH_NOMATCH);
+ }
+ /* Control never gets here */
+
/* This should never occur */
default:
return PCRE2_ERROR_INTERNAL;
@@ -3870,7 +4009,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
/* If maximizing, it is worth using inline code for speed, doing the type
- test once at the start (i.e. keep it out of the loop). */
+ test once at the start (i.e. keep it out of the loops). Once again,
+ "notmatch" can be an ordinary local variable because the loops do not call
+ RMATCH. */
else
{
@@ -3879,6 +4020,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
#ifdef SUPPORT_UNICODE
if (proptype >= 0)
{
+ BOOL notmatch = Lctype == OP_NOTPROP;
switch(proptype)
{
case PT_ANY:
@@ -3891,7 +4033,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
- if (Lctype == OP_NOTPROP) break;
+ if (notmatch) break;
Feptr+= len;
}
break;
@@ -3910,7 +4052,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
chartype = UCD_CHARTYPE(fc);
if ((chartype == ucp_Lu ||
chartype == ucp_Ll ||
- chartype == ucp_Lt) == (Lctype == OP_NOTPROP))
+ chartype == ucp_Lt) == notmatch)
break;
Feptr+= len;
}
@@ -3926,8 +4068,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
- if ((UCD_CATEGORY(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
- break;
+ if ((UCD_CATEGORY(fc) == Lpropvalue) == notmatch) break;
Feptr+= len;
}
break;
@@ -3942,8 +4083,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
- if ((UCD_CHARTYPE(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
- break;
+ if ((UCD_CHARTYPE(fc) == Lpropvalue) == notmatch) break;
Feptr+= len;
}
break;
@@ -3958,8 +4098,27 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
break;
}
GETCHARLENTEST(fc, Feptr, len);
- if ((UCD_SCRIPT(fc) == Lpropvalue) == (Lctype == OP_NOTPROP))
+ if ((UCD_SCRIPT(fc) == Lpropvalue) == notmatch) break;
+ Feptr+= len;
+ }
+ break;
+
+ case PT_SCX:
+ for (i = Lmin; i < Lmax; i++)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ int len = 1;
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
break;
+ }
+ GETCHARLENTEST(fc, Feptr, len);
+ prop = GET_UCD(fc);
+ ok = (prop->script == Lpropvalue ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), Lpropvalue) != 0);
+ if (ok == notmatch) break;
Feptr+= len;
}
break;
@@ -3976,8 +4135,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
}
GETCHARLENTEST(fc, Feptr, len);
category = UCD_CATEGORY(fc);
- if ((category == ucp_L || category == ucp_N) ==
- (Lctype == OP_NOTPROP))
+ if ((category == ucp_L || category == ucp_N) == notmatch)
break;
Feptr+= len;
}
@@ -4002,11 +4160,11 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
{
HSPACE_CASES:
VSPACE_CASES:
- if (Lctype == OP_NOTPROP) goto ENDLOOP99; /* Break the loop */
+ if (notmatch) goto ENDLOOP99; /* Break the loop */
break;
default:
- if ((UCD_CATEGORY(fc) == ucp_Z) == (Lctype == OP_NOTPROP))
+ if ((UCD_CATEGORY(fc) == ucp_Z) == notmatch)
goto ENDLOOP99; /* Break the loop */
break;
}
@@ -4028,7 +4186,7 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHARLENTEST(fc, Feptr, len);
category = UCD_CATEGORY(fc);
if ((category == ucp_L || category == ucp_N ||
- fc == CHAR_UNDERSCORE) == (Lctype == OP_NOTPROP))
+ fc == CHAR_UNDERSCORE) == notmatch)
break;
Feptr+= len;
}
@@ -4049,9 +4207,9 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
for (;;)
{
if (fc < *cp)
- { if (Lctype == OP_NOTPROP) break; else goto GOT_MAX; }
+ { if (notmatch) break; else goto GOT_MAX; }
if (fc == *cp++)
- { if (Lctype == OP_NOTPROP) goto GOT_MAX; else break; }
+ { if (notmatch) goto GOT_MAX; else break; }
}
Feptr += len;
}
@@ -4070,12 +4228,47 @@ fprintf(stderr, "++ op=%d\n", *Fecode);
GETCHARLENTEST(fc, Feptr, len);
if ((fc == CHAR_DOLLAR_SIGN || fc == CHAR_COMMERCIAL_AT ||
fc == CHAR_GRAVE_ACCENT || (fc >= 0xa0 && fc <= 0xd7ff) ||
- fc >= 0xe000) == (Lctype == OP_NOTPROP))
+ fc >= 0xe000) == notmatch)
break;
Feptr += len;
}
break;
+ case PT_BIDICL:
+ for (i = Lmin; i < Lmax; i++)
+ {
+ int len = 1;
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(fc, Feptr, len);
+ if ((UCD_BIDICLASS(fc) == Lpropvalue) == notmatch) break;
+ Feptr+= len;
+ }
+ break;
+
+ case PT_BOOL:
+ for (i = Lmin; i < Lmax; i++)
+ {
+ BOOL ok;
+ const ucd_record *prop;
+ int len = 1;
+ if (Feptr >= mb->end_subject)
+ {
+ SCHECK_PARTIAL();
+ break;
+ }
+ GETCHARLENTEST(fc, Feptr, len);
+ prop = GET_UCD(fc);
+ ok = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), Lpropvalue) != 0;
+ if (ok == notmatch) break;
+ Feptr+= len;
+ }
+ break;
+
default:
return PCRE2_ERROR_INTERNAL;
}
@@ -6066,7 +6259,7 @@ switch (Freturn_id)
LBL(200) LBL(201) LBL(202) LBL(203) LBL(204) LBL(205) LBL(206)
LBL(207) LBL(208) LBL(209) LBL(210) LBL(211) LBL(212) LBL(213)
LBL(214) LBL(215) LBL(216) LBL(217) LBL(218) LBL(219) LBL(220)
- LBL(221) LBL(222)
+ LBL(221) LBL(222) LBL(223) LBL(224) LBL(225)
#endif
default:
@@ -6129,8 +6322,8 @@ PCRE2_UCHAR req_cu2 = 0;
PCRE2_SPTR bumpalong_limit;
PCRE2_SPTR end_subject;
PCRE2_SPTR true_end_subject;
-PCRE2_SPTR start_match = subject + start_offset;
-PCRE2_SPTR req_cu_ptr = start_match - 1;
+PCRE2_SPTR start_match;
+PCRE2_SPTR req_cu_ptr;
PCRE2_SPTR start_partial;
PCRE2_SPTR match_partial;
@@ -6170,9 +6363,18 @@ PCRE2_SPTR stack_frames_vector[START_FRAMES_SIZE/sizeof(PCRE2_SPTR)]
PCRE2_KEEP_UNINITIALIZED;
mb->stack_frames = (heapframe *)stack_frames_vector;
-/* A length equal to PCRE2_ZERO_TERMINATED implies a zero-terminated
-subject string. */
+/* Recognize NULL, length 0 as an empty string. */
+
+if (subject == NULL && length == 0) subject = (PCRE2_SPTR)"";
+
+/* Plausibility checks */
+
+if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
+if (code == NULL || subject == NULL || match_data == NULL)
+ return PCRE2_ERROR_NULL;
+start_match = subject + start_offset;
+req_cu_ptr = start_match - 1;
if (length == PCRE2_ZERO_TERMINATED)
{
length = PRIV(strlen)(subject);
@@ -6180,11 +6382,6 @@ if (length == PCRE2_ZERO_TERMINATED)
}
true_end_subject = end_subject = subject + length;
-/* Plausibility checks */
-
-if ((options & ~PUBLIC_MATCH_OPTIONS) != 0) return PCRE2_ERROR_BADOPTION;
-if (code == NULL || subject == NULL || match_data == NULL)
- return PCRE2_ERROR_NULL;
if (start_offset > length) return PCRE2_ERROR_BADOFFSET;
/* Check that the first field in the block is the magic number. */
@@ -6482,7 +6679,7 @@ if (utf &&
/* If the end precedes start_match, it means there is invalid UTF in the
extra code units we reversed over because of a lookbehind. Advance past the
first bad code unit, and then skip invalid character starting code units in
- 8-bit and 16-bit modes, and try again. */
+ 8-bit and 16-bit modes, and try again with the original end point. */
if (end_subject < start_match)
{
@@ -6491,6 +6688,7 @@ if (utf &&
while (mb->check_subject < start_match && NOT_FIRSTCU(*mb->check_subject))
mb->check_subject++;
#endif
+ end_subject = true_end_subject;
}
/* Otherwise, set the not end of line option, and do the match. */
@@ -6601,10 +6799,16 @@ the pattern. It is not used at all if there are no capturing parentheses.
The last of these is changed within the match() function if the frame vector
has to be expanded. We therefore put it into the match block so that it is
-correct when calling match() more than once for non-anchored patterns. */
+correct when calling match() more than once for non-anchored patterns.
+
+We must also pad frame_size for alignment to ensure subsequent frames are as
+aligned as heapframe. Whilst ovector is word-aligned due to being a PCRE2_SIZE
+array, that does not guarantee it is suitably aligned for pointers, as some
+architectures have pointers that are larger than a size_t. */
-frame_size = offsetof(heapframe, ovector) +
- re->top_bracket * 2 * sizeof(PCRE2_SIZE);
+frame_size = (offsetof(heapframe, ovector) +
+ re->top_bracket * 2 * sizeof(PCRE2_SIZE) + HEAPFRAME_ALIGNMENT - 1) &
+ ~(HEAPFRAME_ALIGNMENT - 1);
/* Limits set in the pattern override the match context only if they are
smaller. */
@@ -6648,7 +6852,7 @@ mb->match_frames_top =
to avoid uninitialized memory read errors when it is copied to a new frame. */
memset((char *)(mb->match_frames) + offsetof(heapframe, ovector), 0xff,
- re->top_bracket * 2 * sizeof(PCRE2_SIZE));
+ frame_size - offsetof(heapframe, ovector));
/* Pointers to the individual character tables */
diff --git a/thirdparty/pcre2/src/pcre2_script_run.c b/thirdparty/pcre2/src/pcre2_script_run.c
index 91a4833028..4926fa63bb 100644
--- a/thirdparty/pcre2/src/pcre2_script_run.c
+++ b/thirdparty/pcre2/src/pcre2_script_run.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -68,26 +68,26 @@ Arguments:
Returns: TRUE if this is a valid script run
*/
-/* These dummy values must be less than the negation of the largest offset in
-the PRIV(ucd_script_sets) vector, which is held in a 16-bit field in UCD
-records (and is only likely to be a few hundred). */
+/* These are states in the checking process. */
-#define SCRIPT_UNSET (-99999)
-#define SCRIPT_HANPENDING (-99998)
-#define SCRIPT_HANHIRAKATA (-99997)
-#define SCRIPT_HANBOPOMOFO (-99996)
-#define SCRIPT_HANHANGUL (-99995)
-#define SCRIPT_LIST (-99994)
+enum { SCRIPT_UNSET, /* Requirement as yet unknown */
+ SCRIPT_MAP, /* Bitmap contains acceptable scripts */
+ SCRIPT_HANPENDING, /* Have had only Han characters */
+ SCRIPT_HANHIRAKATA, /* Expect Han or Hirikata */
+ SCRIPT_HANBOPOMOFO, /* Expect Han or Bopomofo */
+ SCRIPT_HANHANGUL /* Expect Han or Hangul */
+ };
-#define INTERSECTION_LIST_SIZE 50
+#define UCD_MAPSIZE (ucp_Unknown/32 + 1)
+#define FULL_MAPSIZE (ucp_Script_Count/32 + 1)
BOOL
PRIV(script_run)(PCRE2_SPTR ptr, PCRE2_SPTR endptr, BOOL utf)
{
#ifdef SUPPORT_UNICODE
-int require_script = SCRIPT_UNSET;
-uint8_t intersection_list[INTERSECTION_LIST_SIZE];
-const uint8_t *require_list = NULL;
+uint32_t require_state = SCRIPT_UNSET;
+uint32_t require_map[FULL_MAPSIZE];
+uint32_t map[FULL_MAPSIZE];
uint32_t require_digitset = 0;
uint32_t c;
@@ -101,11 +101,17 @@ if (ptr >= endptr) return TRUE;
GETCHARINCTEST(c, ptr);
if (ptr >= endptr) return TRUE;
+/* Initialize the require map. This is a full-size bitmap that has a bit for
+every script, as opposed to the maps in ucd_script_sets, which only have bits
+for scripts less than ucp_Unknown - those that appear in script extension
+lists. */
+
+for (int i = 0; i < FULL_MAPSIZE; i++) require_map[i] = 0;
+
/* Scan strings of two or more characters, checking the Unicode characteristics
-of each code point. We make use of the Script Extensions property. There is
-special code for scripts that can be combined with characters from the Han
-Chinese script. This may be used in conjunction with four other scripts in
-these combinations:
+of each code point. There is special code for scripts that can be combined with
+characters from the Han Chinese script. This may be used in conjunction with
+four other scripts in these combinations:
. Han with Hiragana and Katakana is allowed (for Japanese).
. Han with Bopomofo is allowed (for Taiwanese Mandarin).
@@ -119,310 +125,207 @@ Hence the SCRIPT_HANPENDING state. */
for (;;)
{
const ucd_record *ucd = GET_UCD(c);
- int32_t scriptx = ucd->scriptx;
+ uint32_t script = ucd->script;
- /* If the script extension is Unknown, the string is not a valid script run.
- Such characters can only form script runs of length one. */
+ /* If the script is Unknown, the string is not a valid script run. Such
+ characters can only form script runs of length one (see test above). */
- if (scriptx == ucp_Unknown) return FALSE;
+ if (script == ucp_Unknown) return FALSE;
- /* A character whose script extension is Inherited is always accepted with
- any script, and plays no further part in this testing. A character whose
- script is Common is always accepted, but must still be tested for a digit
- below. The scriptx value at this point is non-zero, because zero is
- ucp_Unknown, tested for above. */
+ /* A character without any script extensions whose script is Inherited or
+ Common is always accepted with any script. If there are extensions, the
+ following processing happens for all scripts. */
- if (scriptx != ucp_Inherited)
+ if (UCD_SCRIPTX_PROP(ucd) != 0 || (script != ucp_Inherited && script != ucp_Common))
{
- if (scriptx != ucp_Common)
+ BOOL OK;
+
+ /* Set up a full-sized map for this character that can include bits for all
+ scripts. Copy the scriptx map for this character (which covers those
+ scripts that appear in script extension lists), set the remaining values to
+ zero, and then, except for Common or Inherited, add this script's bit to
+ the map. */
+
+ memcpy(map, PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(ucd), UCD_MAPSIZE * sizeof(uint32_t));
+ memset(map + UCD_MAPSIZE, 0, (FULL_MAPSIZE - UCD_MAPSIZE) * sizeof(uint32_t));
+ if (script != ucp_Common && script != ucp_Inherited) MAPSET(map, script);
+
+ /* Handle the different checking states */
+
+ switch(require_state)
{
- /* If the script extension value is positive, the character is not a mark
- that can be used with many scripts. In the simple case we either set or
- compare with the required script. However, handling the scripts that can
- combine with Han are more complicated, as is the case when the previous
- characters have been man-script marks. */
+ /* First significant character - it might follow Common or Inherited
+ characters that do not have any script extensions. */
- if (scriptx > 0)
+ case SCRIPT_UNSET:
+ switch(script)
{
- switch(require_script)
- {
- /* Either the first significant character (require_script unset) or
- after only Han characters. */
-
- case SCRIPT_UNSET:
- case SCRIPT_HANPENDING:
- switch(scriptx)
- {
- case ucp_Han:
- require_script = SCRIPT_HANPENDING;
- break;
-
- case ucp_Hiragana:
- case ucp_Katakana:
- require_script = SCRIPT_HANHIRAKATA;
- break;
-
- case ucp_Bopomofo:
- require_script = SCRIPT_HANBOPOMOFO;
- break;
-
- case ucp_Hangul:
- require_script = SCRIPT_HANHANGUL;
- break;
-
- /* Not a Han-related script. If expecting one, fail. Otherise set
- the requirement to this script. */
-
- default:
- if (require_script == SCRIPT_HANPENDING) return FALSE;
- require_script = scriptx;
- break;
- }
- break;
+ case ucp_Han:
+ require_state = SCRIPT_HANPENDING;
+ break;
+
+ case ucp_Hiragana:
+ case ucp_Katakana:
+ require_state = SCRIPT_HANHIRAKATA;
+ break;
+
+ case ucp_Bopomofo:
+ require_state = SCRIPT_HANBOPOMOFO;
+ break;
+
+ case ucp_Hangul:
+ require_state = SCRIPT_HANHANGUL;
+ break;
+
+ default:
+ memcpy(require_map, map, FULL_MAPSIZE * sizeof(uint32_t));
+ require_state = SCRIPT_MAP;
+ break;
+ }
+ break;
- /* Previously encountered one of the "with Han" scripts. Check that
- this character is appropriate. */
+ /* The first significant character was Han. An inspection of the Unicode
+ 11.0.0 files shows that there are the following types of Script Extension
+ list that involve the Han, Bopomofo, Hiragana, Katakana, and Hangul
+ scripts:
- case SCRIPT_HANHIRAKATA:
- if (scriptx != ucp_Han && scriptx != ucp_Hiragana &&
- scriptx != ucp_Katakana)
- return FALSE;
- break;
+ . Bopomofo + Han
+ . Han + Hiragana + Katakana
+ . Hiragana + Katakana
+ . Bopopmofo + Hangul + Han + Hiragana + Katakana
- case SCRIPT_HANBOPOMOFO:
- if (scriptx != ucp_Han && scriptx != ucp_Bopomofo) return FALSE;
- break;
+ The following code tries to make sense of this. */
- case SCRIPT_HANHANGUL:
- if (scriptx != ucp_Han && scriptx != ucp_Hangul) return FALSE;
- break;
+#define FOUND_BOPOMOFO 1
+#define FOUND_HIRAGANA 2
+#define FOUND_KATAKANA 4
+#define FOUND_HANGUL 8
- /* We have a list of scripts to check that is derived from one or
- more previous characters. This is either one of the lists in
- ucd_script_sets[] (for one previous character) or the intersection of
- several lists for multiple characters. */
-
- case SCRIPT_LIST:
- {
- const uint8_t *list;
- for (list = require_list; *list != 0; list++)
- {
- if (*list == scriptx) break;
- }
- if (*list == 0) return FALSE;
- }
-
- /* The rest of the string must be in this script, but we have to
- allow for the Han complications. */
-
- switch(scriptx)
- {
- case ucp_Han:
- require_script = SCRIPT_HANPENDING;
- break;
-
- case ucp_Hiragana:
- case ucp_Katakana:
- require_script = SCRIPT_HANHIRAKATA;
- break;
-
- case ucp_Bopomofo:
- require_script = SCRIPT_HANBOPOMOFO;
- break;
-
- case ucp_Hangul:
- require_script = SCRIPT_HANHANGUL;
- break;
-
- default:
- require_script = scriptx;
- break;
- }
- break;
+ case SCRIPT_HANPENDING:
+ if (script != ucp_Han) /* Another Han does nothing */
+ {
+ uint32_t chspecial = 0;
- /* This is the easy case when a single script is required. */
+ if (MAPBIT(map, ucp_Bopomofo) != 0) chspecial |= FOUND_BOPOMOFO;
+ if (MAPBIT(map, ucp_Hiragana) != 0) chspecial |= FOUND_HIRAGANA;
+ if (MAPBIT(map, ucp_Katakana) != 0) chspecial |= FOUND_KATAKANA;
+ if (MAPBIT(map, ucp_Hangul) != 0) chspecial |= FOUND_HANGUL;
- default:
- if (scriptx != require_script) return FALSE;
- break;
- }
- } /* End of handing positive scriptx */
+ if (chspecial == 0) return FALSE; /* Not allowed with Han */
- /* If scriptx is negative, this character is a mark-type character that
- has a list of permitted scripts. */
+ if (chspecial == FOUND_BOPOMOFO)
+ require_state = SCRIPT_HANBOPOMOFO;
+ else if (chspecial == (FOUND_HIRAGANA|FOUND_KATAKANA))
+ require_state = SCRIPT_HANHIRAKATA;
- else
- {
- uint32_t chspecial;
- const uint8_t *clist, *rlist;
- const uint8_t *list = PRIV(ucd_script_sets) - scriptx;
-
- switch(require_script)
- {
- case SCRIPT_UNSET:
- require_list = PRIV(ucd_script_sets) - scriptx;
- require_script = SCRIPT_LIST;
- break;
+ /* Otherwise this character must be allowed with all of them, so remain
+ in the pending state. */
+ }
+ break;
- /* An inspection of the Unicode 11.0.0 files shows that there are the
- following types of Script Extension list that involve the Han,
- Bopomofo, Hiragana, Katakana, and Hangul scripts:
+ /* Previously encountered one of the "with Han" scripts. Check that
+ this character is appropriate. */
- . Bopomofo + Han
- . Han + Hiragana + Katakana
- . Hiragana + Katakana
- . Bopopmofo + Hangul + Han + Hiragana + Katakana
+ case SCRIPT_HANHIRAKATA:
+ if (MAPBIT(map, ucp_Han) + MAPBIT(map, ucp_Hiragana) +
+ MAPBIT(map, ucp_Katakana) == 0) return FALSE;
+ break;
- The following code tries to make sense of this. */
+ case SCRIPT_HANBOPOMOFO:
+ if (MAPBIT(map, ucp_Han) + MAPBIT(map, ucp_Bopomofo) == 0) return FALSE;
+ break;
-#define FOUND_BOPOMOFO 1
-#define FOUND_HIRAGANA 2
-#define FOUND_KATAKANA 4
-#define FOUND_HANGUL 8
+ case SCRIPT_HANHANGUL:
+ if (MAPBIT(map, ucp_Han) + MAPBIT(map, ucp_Hangul) == 0) return FALSE;
+ break;
- case SCRIPT_HANPENDING:
- chspecial = 0;
- for (; *list != 0; list++)
- {
- switch (*list)
- {
- case ucp_Bopomofo: chspecial |= FOUND_BOPOMOFO; break;
- case ucp_Hiragana: chspecial |= FOUND_HIRAGANA; break;
- case ucp_Katakana: chspecial |= FOUND_KATAKANA; break;
- case ucp_Hangul: chspecial |= FOUND_HANGUL; break;
- default: break;
- }
- }
-
- if (chspecial == 0) return FALSE;
-
- if (chspecial == FOUND_BOPOMOFO)
- {
- require_script = SCRIPT_HANBOPOMOFO;
- }
- else if (chspecial == (FOUND_HIRAGANA|FOUND_KATAKANA))
- {
- require_script = SCRIPT_HANHIRAKATA;
- }
-
- /* Otherwise it must be allowed with all of them, so remain in
- the pending state. */
+ /* Previously encountered one or more characters that are allowed with a
+ list of scripts. */
- break;
+ case SCRIPT_MAP:
+ OK = FALSE;
- case SCRIPT_HANHIRAKATA:
- for (; *list != 0; list++)
- {
- if (*list == ucp_Hiragana || *list == ucp_Katakana) break;
- }
- if (*list == 0) return FALSE;
+ for (int i = 0; i < FULL_MAPSIZE; i++)
+ {
+ if ((require_map[i] & map[i]) != 0)
+ {
+ OK = TRUE;
break;
+ }
+ }
- case SCRIPT_HANBOPOMOFO:
- for (; *list != 0; list++)
- {
- if (*list == ucp_Bopomofo) break;
- }
- if (*list == 0) return FALSE;
- break;
+ if (!OK) return FALSE;
- case SCRIPT_HANHANGUL:
- for (; *list != 0; list++)
- {
- if (*list == ucp_Hangul) break;
- }
- if (*list == 0) return FALSE;
- break;
+ /* The rest of the string must be in this script, but we have to
+ allow for the Han complications. */
- /* Previously encountered one or more characters that are allowed
- with a list of scripts. Build the intersection of the required list
- with this character's list in intersection_list[]. This code is
- written so that it still works OK if the required list is already in
- that vector. */
-
- case SCRIPT_LIST:
- {
- int i = 0;
- for (rlist = require_list; *rlist != 0; rlist++)
- {
- for (clist = list; *clist != 0; clist++)
- {
- if (*rlist == *clist)
- {
- intersection_list[i++] = *rlist;
- break;
- }
- }
- }
- if (i == 0) return FALSE; /* No scripts in common */
-
- /* If there's just one script in common, we can set it as the
- unique required script. Otherwise, terminate the intersection list
- and make it the required list. */
-
- if (i == 1)
- {
- require_script = intersection_list[0];
- }
- else
- {
- intersection_list[i] = 0;
- require_list = intersection_list;
- }
- }
- break;
+ switch(script)
+ {
+ case ucp_Han:
+ require_state = SCRIPT_HANPENDING;
+ break;
- /* The previously set required script is a single script, not
- Han-related. Check that it is in this character's list. */
+ case ucp_Hiragana:
+ case ucp_Katakana:
+ require_state = SCRIPT_HANHIRAKATA;
+ break;
- default:
- for (; *list != 0; list++)
- {
- if (*list == require_script) break;
- }
- if (*list == 0) return FALSE;
- break;
- }
- } /* End of handling negative scriptx */
- } /* End of checking non-Common character */
-
- /* The character is in an acceptable script. We must now ensure that all
- decimal digits in the string come from the same set. Some scripts (e.g.
- Common, Arabic) have more than one set of decimal digits. This code does
- not allow mixing sets, even within the same script. The vector called
- PRIV(ucd_digit_sets)[] contains, in its first element, the number of
- following elements, and then, in ascending order, the code points of the
- '9' characters in every set of 10 digits. Each set is identified by the
- offset in the vector of its '9' character. An initial check of the first
- value picks up ASCII digits quickly. Otherwise, a binary chop is used. */
-
- if (ucd->chartype == ucp_Nd)
- {
- uint32_t digitset;
+ case ucp_Bopomofo:
+ require_state = SCRIPT_HANBOPOMOFO;
+ break;
+
+ case ucp_Hangul:
+ require_state = SCRIPT_HANHANGUL;
+ break;
+
+ /* Compute the intersection of the required list of scripts and the
+ allowed scripts for this character. */
- if (c <= PRIV(ucd_digit_sets)[1]) digitset = 1; else
+ default:
+ for (int i = 0; i < FULL_MAPSIZE; i++) require_map[i] &= map[i];
+ break;
+ }
+
+ break;
+ }
+ } /* End checking character's script and extensions. */
+
+ /* The character is in an acceptable script. We must now ensure that all
+ decimal digits in the string come from the same set. Some scripts (e.g.
+ Common, Arabic) have more than one set of decimal digits. This code does
+ not allow mixing sets, even within the same script. The vector called
+ PRIV(ucd_digit_sets)[] contains, in its first element, the number of
+ following elements, and then, in ascending order, the code points of the
+ '9' characters in every set of 10 digits. Each set is identified by the
+ offset in the vector of its '9' character. An initial check of the first
+ value picks up ASCII digits quickly. Otherwise, a binary chop is used. */
+
+ if (ucd->chartype == ucp_Nd)
+ {
+ uint32_t digitset;
+
+ if (c <= PRIV(ucd_digit_sets)[1]) digitset = 1; else
+ {
+ int mid;
+ int bot = 1;
+ int top = PRIV(ucd_digit_sets)[0];
+ for (;;)
{
- int mid;
- int bot = 1;
- int top = PRIV(ucd_digit_sets)[0];
- for (;;)
+ if (top <= bot + 1) /* <= rather than == is paranoia */
{
- if (top <= bot + 1) /* <= rather than == is paranoia */
- {
- digitset = top;
- break;
- }
- mid = (top + bot) / 2;
- if (c <= PRIV(ucd_digit_sets)[mid]) top = mid; else bot = mid;
+ digitset = top;
+ break;
}
+ mid = (top + bot) / 2;
+ if (c <= PRIV(ucd_digit_sets)[mid]) top = mid; else bot = mid;
}
+ }
- /* A required value of 0 means "unset". */
+ /* A required value of 0 means "unset". */
- if (require_digitset == 0) require_digitset = digitset;
- else if (digitset != require_digitset) return FALSE;
- } /* End digit handling */
- } /* End checking non-Inherited character */
+ if (require_digitset == 0) require_digitset = digitset;
+ else if (digitset != require_digitset) return FALSE;
+ } /* End digit handling */
/* If we haven't yet got to the end, pick up the next character. */
diff --git a/thirdparty/pcre2/src/pcre2_string_utils.c b/thirdparty/pcre2/src/pcre2_string_utils.c
index d6be01acf5..ebfa9434e3 100644
--- a/thirdparty/pcre2/src/pcre2_string_utils.c
+++ b/thirdparty/pcre2/src/pcre2_string_utils.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2018 University of Cambridge
+ New API code Copyright (c) 2018-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/pcre2/src/pcre2_study.c b/thirdparty/pcre2/src/pcre2_study.c
index 9bbb37570f..4db3ad1184 100644
--- a/thirdparty/pcre2/src/pcre2_study.c
+++ b/thirdparty/pcre2/src/pcre2_study.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2020 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -908,7 +908,7 @@ set_nottype_bits(pcre2_real_code *re, int cbit_type, unsigned int table_limit)
{
uint32_t c;
for (c = 0; c < table_limit; c++)
- re->start_bitmap[c] |= ~(re->tables[c+cbits_offset+cbit_type]);
+ re->start_bitmap[c] |= (uint8_t)(~(re->tables[c+cbits_offset+cbit_type]));
#if defined SUPPORT_UNICODE && PCRE2_CODE_UNIT_WIDTH == 8
if (table_limit != 32) for (c = 24; c < 32; c++) re->start_bitmap[c] = 0xff;
#endif
diff --git a/thirdparty/pcre2/src/pcre2_substitute.c b/thirdparty/pcre2/src/pcre2_substitute.c
index 981a106a9f..8b2c369ccc 100644
--- a/thirdparty/pcre2/src/pcre2_substitute.c
+++ b/thirdparty/pcre2/src/pcre2_substitute.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2020 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -259,6 +259,18 @@ PCRE2_UNSET, so as not to imply an offset in the replacement. */
if ((options & (PCRE2_PARTIAL_HARD|PCRE2_PARTIAL_SOFT)) != 0)
return PCRE2_ERROR_BADOPTION;
+
+/* Validate length and find the end of the replacement. A NULL replacement of
+zero length is interpreted as an empty string. */
+
+if (replacement == NULL)
+ {
+ if (rlength != 0) return PCRE2_ERROR_NULL;
+ replacement = (PCRE2_SPTR)"";
+ }
+
+if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);
+repend = replacement + rlength;
/* Check for using a match that has already happened. Note that the subject
pointer in the match data may be NULL after a no-match. */
@@ -312,11 +324,18 @@ scb.input = subject;
scb.output = (PCRE2_SPTR)buffer;
scb.ovector = ovector;
-/* Find lengths of zero-terminated strings and the end of the replacement. */
+/* A NULL subject of zero length is treated as an empty string. */
-if (length == PCRE2_ZERO_TERMINATED) length = PRIV(strlen)(subject);
-if (rlength == PCRE2_ZERO_TERMINATED) rlength = PRIV(strlen)(replacement);
-repend = replacement + rlength;
+if (subject == NULL)
+ {
+ if (length != 0) return PCRE2_ERROR_NULL;
+ subject = (PCRE2_SPTR)"";
+ }
+
+/* Find length of zero-terminated subject */
+
+if (length == PCRE2_ZERO_TERMINATED)
+ length = subject? PRIV(strlen)(subject) : 0;
/* Check UTF replacement string if necessary. */
diff --git a/thirdparty/pcre2/src/pcre2_tables.c b/thirdparty/pcre2/src/pcre2_tables.c
index c164e976e0..e00252f1eb 100644
--- a/thirdparty/pcre2/src/pcre2_tables.c
+++ b/thirdparty/pcre2/src/pcre2_tables.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2019 University of Cambridge
+ New API code Copyright (c) 2016-2021 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -51,10 +51,10 @@ defined. */
#include "pcre2_internal.h"
#endif /* PCRE2_PCRE2TEST */
-
/* Table of sizes for the fixed-length opcodes. It's defined in a macro so that
the definition is next to the definition of the opcodes in pcre2_internal.h.
-This is mode-dependent, so is skipped when this file is included by pcre2test. */
+This is mode-dependent, so it is skipped when this file is included by
+pcre2test. */
#ifndef PCRE2_PCRE2TEST
const uint8_t PRIV(OP_lengths)[] = { OP_LENGTHS };
@@ -119,6 +119,9 @@ const uint8_t PRIV(utf8_table4)[] = {
#endif /* UTF-8 support needed */
+/* Tables concerned with Unicode properties are relevant only when Unicode
+support is enabled. See also the pcre2_ucptables.c file, which is generated by
+a Python script from Unicode data files. */
#ifdef SUPPORT_UNICODE
@@ -190,7 +193,7 @@ const uint32_t PRIV(ucp_gbtable)[] = {
ESZ|(1u<<ucp_gbPrepend)| /* 4 Prepend */
(1u<<ucp_gbL)|(1u<<ucp_gbV)|(1u<<ucp_gbT)|
(1u<<ucp_gbLV)|(1u<<ucp_gbLVT)|(1u<<ucp_gbOther)|
- (1u<<ucp_gbRegionalIndicator),
+ (1u<<ucp_gbRegional_Indicator),
ESZ, /* 5 SpacingMark */
ESZ|(1u<<ucp_gbL)|(1u<<ucp_gbV)|(1u<<ucp_gbLV)| /* 6 L */
(1u<<ucp_gbLVT),
@@ -198,7 +201,7 @@ const uint32_t PRIV(ucp_gbtable)[] = {
ESZ|(1u<<ucp_gbT), /* 8 T */
ESZ|(1u<<ucp_gbV)|(1u<<ucp_gbT), /* 9 LV */
ESZ|(1u<<ucp_gbT), /* 10 LVT */
- (1u<<ucp_gbRegionalIndicator), /* 11 RegionalIndicator */
+ (1u<<ucp_gbRegional_Indicator), /* 11 Regional Indicator */
ESZ, /* 12 Other */
ESZ, /* 13 ZWJ */
ESZ|(1u<<ucp_gbExtended_Pictographic) /* 14 Extended Pictographic */
@@ -221,648 +224,10 @@ const int PRIV(ucp_typerange)[] = {
};
#endif /* SUPPORT_JIT */
-/* The PRIV(utt)[] table below translates Unicode property names into type and
-code values. It is searched by binary chop, so must be in collating sequence of
-name. Originally, the table contained pointers to the name strings in the first
-field of each entry. However, that leads to a large number of relocations when
-a shared library is dynamically loaded. A significant reduction is made by
-putting all the names into a single, large string and then using offsets in the
-table itself. Maintenance is more error-prone, but frequent changes to this
-data are unlikely.
-
-July 2008: There is now a script called maint/GenerateUtt.py that can be used
-to generate this data automatically instead of maintaining it by hand.
-
-The script was updated in March 2009 to generate a new EBCDIC-compliant
-version. Like all other character and string literals that are compared against
-the regular expression pattern, we must use STR_ macros instead of literal
-strings to make sure that UTF-8 support works on EBCDIC platforms. */
-
-#define STRING_Adlam0 STR_A STR_d STR_l STR_a STR_m "\0"
-#define STRING_Ahom0 STR_A STR_h STR_o STR_m "\0"
-#define STRING_Anatolian_Hieroglyphs0 STR_A STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
-#define STRING_Any0 STR_A STR_n STR_y "\0"
-#define STRING_Arabic0 STR_A STR_r STR_a STR_b STR_i STR_c "\0"
-#define STRING_Armenian0 STR_A STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"
-#define STRING_Avestan0 STR_A STR_v STR_e STR_s STR_t STR_a STR_n "\0"
-#define STRING_Balinese0 STR_B STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"
-#define STRING_Bamum0 STR_B STR_a STR_m STR_u STR_m "\0"
-#define STRING_Bassa_Vah0 STR_B STR_a STR_s STR_s STR_a STR_UNDERSCORE STR_V STR_a STR_h "\0"
-#define STRING_Batak0 STR_B STR_a STR_t STR_a STR_k "\0"
-#define STRING_Bengali0 STR_B STR_e STR_n STR_g STR_a STR_l STR_i "\0"
-#define STRING_Bhaiksuki0 STR_B STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0"
-#define STRING_Bopomofo0 STR_B STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"
-#define STRING_Brahmi0 STR_B STR_r STR_a STR_h STR_m STR_i "\0"
-#define STRING_Braille0 STR_B STR_r STR_a STR_i STR_l STR_l STR_e "\0"
-#define STRING_Buginese0 STR_B STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"
-#define STRING_Buhid0 STR_B STR_u STR_h STR_i STR_d "\0"
-#define STRING_C0 STR_C "\0"
-#define STRING_Canadian_Aboriginal0 STR_C STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"
-#define STRING_Carian0 STR_C STR_a STR_r STR_i STR_a STR_n "\0"
-#define STRING_Caucasian_Albanian0 STR_C STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_UNDERSCORE STR_A STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"
-#define STRING_Cc0 STR_C STR_c "\0"
-#define STRING_Cf0 STR_C STR_f "\0"
-#define STRING_Chakma0 STR_C STR_h STR_a STR_k STR_m STR_a "\0"
-#define STRING_Cham0 STR_C STR_h STR_a STR_m "\0"
-#define STRING_Cherokee0 STR_C STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
-#define STRING_Chorasmian0 STR_C STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"
-#define STRING_Cn0 STR_C STR_n "\0"
-#define STRING_Co0 STR_C STR_o "\0"
-#define STRING_Common0 STR_C STR_o STR_m STR_m STR_o STR_n "\0"
-#define STRING_Coptic0 STR_C STR_o STR_p STR_t STR_i STR_c "\0"
-#define STRING_Cs0 STR_C STR_s "\0"
-#define STRING_Cuneiform0 STR_C STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"
-#define STRING_Cypriot0 STR_C STR_y STR_p STR_r STR_i STR_o STR_t "\0"
-#define STRING_Cypro_Minoan0 STR_C STR_y STR_p STR_r STR_o STR_UNDERSCORE STR_M STR_i STR_n STR_o STR_a STR_n "\0"
-#define STRING_Cyrillic0 STR_C STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
-#define STRING_Deseret0 STR_D STR_e STR_s STR_e STR_r STR_e STR_t "\0"
-#define STRING_Devanagari0 STR_D STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
-#define STRING_Dives_Akuru0 STR_D STR_i STR_v STR_e STR_s STR_UNDERSCORE STR_A STR_k STR_u STR_r STR_u "\0"
-#define STRING_Dogra0 STR_D STR_o STR_g STR_r STR_a "\0"
-#define STRING_Duployan0 STR_D STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
-#define STRING_Egyptian_Hieroglyphs0 STR_E STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
-#define STRING_Elbasan0 STR_E STR_l STR_b STR_a STR_s STR_a STR_n "\0"
-#define STRING_Elymaic0 STR_E STR_l STR_y STR_m STR_a STR_i STR_c "\0"
-#define STRING_Ethiopic0 STR_E STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
-#define STRING_Georgian0 STR_G STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
-#define STRING_Glagolitic0 STR_G STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
-#define STRING_Gothic0 STR_G STR_o STR_t STR_h STR_i STR_c "\0"
-#define STRING_Grantha0 STR_G STR_r STR_a STR_n STR_t STR_h STR_a "\0"
-#define STRING_Greek0 STR_G STR_r STR_e STR_e STR_k "\0"
-#define STRING_Gujarati0 STR_G STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
-#define STRING_Gunjala_Gondi0 STR_G STR_u STR_n STR_j STR_a STR_l STR_a STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"
-#define STRING_Gurmukhi0 STR_G STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
-#define STRING_Han0 STR_H STR_a STR_n "\0"
-#define STRING_Hangul0 STR_H STR_a STR_n STR_g STR_u STR_l "\0"
-#define STRING_Hanifi_Rohingya0 STR_H STR_a STR_n STR_i STR_f STR_i STR_UNDERSCORE STR_R STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"
-#define STRING_Hanunoo0 STR_H STR_a STR_n STR_u STR_n STR_o STR_o "\0"
-#define STRING_Hatran0 STR_H STR_a STR_t STR_r STR_a STR_n "\0"
-#define STRING_Hebrew0 STR_H STR_e STR_b STR_r STR_e STR_w "\0"
-#define STRING_Hiragana0 STR_H STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"
-#define STRING_Imperial_Aramaic0 STR_I STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_UNDERSCORE STR_A STR_r STR_a STR_m STR_a STR_i STR_c "\0"
-#define STRING_Inherited0 STR_I STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"
-#define STRING_Inscriptional_Pahlavi0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"
-#define STRING_Inscriptional_Parthian0 STR_I STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_UNDERSCORE STR_P STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"
-#define STRING_Javanese0 STR_J STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"
-#define STRING_Kaithi0 STR_K STR_a STR_i STR_t STR_h STR_i "\0"
-#define STRING_Kannada0 STR_K STR_a STR_n STR_n STR_a STR_d STR_a "\0"
-#define STRING_Katakana0 STR_K STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
-#define STRING_Kayah_Li0 STR_K STR_a STR_y STR_a STR_h STR_UNDERSCORE STR_L STR_i "\0"
-#define STRING_Kharoshthi0 STR_K STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
-#define STRING_Khitan_Small_Script0 STR_K STR_h STR_i STR_t STR_a STR_n STR_UNDERSCORE STR_S STR_m STR_a STR_l STR_l STR_UNDERSCORE STR_S STR_c STR_r STR_i STR_p STR_t "\0"
-#define STRING_Khmer0 STR_K STR_h STR_m STR_e STR_r "\0"
-#define STRING_Khojki0 STR_K STR_h STR_o STR_j STR_k STR_i "\0"
-#define STRING_Khudawadi0 STR_K STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"
-#define STRING_L0 STR_L "\0"
-#define STRING_L_AMPERSAND0 STR_L STR_AMPERSAND "\0"
-#define STRING_Lao0 STR_L STR_a STR_o "\0"
-#define STRING_Latin0 STR_L STR_a STR_t STR_i STR_n "\0"
-#define STRING_Lepcha0 STR_L STR_e STR_p STR_c STR_h STR_a "\0"
-#define STRING_Limbu0 STR_L STR_i STR_m STR_b STR_u "\0"
-#define STRING_Linear_A0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_A "\0"
-#define STRING_Linear_B0 STR_L STR_i STR_n STR_e STR_a STR_r STR_UNDERSCORE STR_B "\0"
-#define STRING_Lisu0 STR_L STR_i STR_s STR_u "\0"
-#define STRING_Ll0 STR_L STR_l "\0"
-#define STRING_Lm0 STR_L STR_m "\0"
-#define STRING_Lo0 STR_L STR_o "\0"
-#define STRING_Lt0 STR_L STR_t "\0"
-#define STRING_Lu0 STR_L STR_u "\0"
-#define STRING_Lycian0 STR_L STR_y STR_c STR_i STR_a STR_n "\0"
-#define STRING_Lydian0 STR_L STR_y STR_d STR_i STR_a STR_n "\0"
-#define STRING_M0 STR_M "\0"
-#define STRING_Mahajani0 STR_M STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"
-#define STRING_Makasar0 STR_M STR_a STR_k STR_a STR_s STR_a STR_r "\0"
-#define STRING_Malayalam0 STR_M STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
-#define STRING_Mandaic0 STR_M STR_a STR_n STR_d STR_a STR_i STR_c "\0"
-#define STRING_Manichaean0 STR_M STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"
-#define STRING_Marchen0 STR_M STR_a STR_r STR_c STR_h STR_e STR_n "\0"
-#define STRING_Masaram_Gondi0 STR_M STR_a STR_s STR_a STR_r STR_a STR_m STR_UNDERSCORE STR_G STR_o STR_n STR_d STR_i "\0"
-#define STRING_Mc0 STR_M STR_c "\0"
-#define STRING_Me0 STR_M STR_e "\0"
-#define STRING_Medefaidrin0 STR_M STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"
-#define STRING_Meetei_Mayek0 STR_M STR_e STR_e STR_t STR_e STR_i STR_UNDERSCORE STR_M STR_a STR_y STR_e STR_k "\0"
-#define STRING_Mende_Kikakui0 STR_M STR_e STR_n STR_d STR_e STR_UNDERSCORE STR_K STR_i STR_k STR_a STR_k STR_u STR_i "\0"
-#define STRING_Meroitic_Cursive0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_C STR_u STR_r STR_s STR_i STR_v STR_e "\0"
-#define STRING_Meroitic_Hieroglyphs0 STR_M STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_UNDERSCORE STR_H STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
-#define STRING_Miao0 STR_M STR_i STR_a STR_o "\0"
-#define STRING_Mn0 STR_M STR_n "\0"
-#define STRING_Modi0 STR_M STR_o STR_d STR_i "\0"
-#define STRING_Mongolian0 STR_M STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
-#define STRING_Mro0 STR_M STR_r STR_o "\0"
-#define STRING_Multani0 STR_M STR_u STR_l STR_t STR_a STR_n STR_i "\0"
-#define STRING_Myanmar0 STR_M STR_y STR_a STR_n STR_m STR_a STR_r "\0"
-#define STRING_N0 STR_N "\0"
-#define STRING_Nabataean0 STR_N STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
-#define STRING_Nandinagari0 STR_N STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0"
-#define STRING_Nd0 STR_N STR_d "\0"
-#define STRING_New_Tai_Lue0 STR_N STR_e STR_w STR_UNDERSCORE STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_u STR_e "\0"
-#define STRING_Newa0 STR_N STR_e STR_w STR_a "\0"
-#define STRING_Nko0 STR_N STR_k STR_o "\0"
-#define STRING_Nl0 STR_N STR_l "\0"
-#define STRING_No0 STR_N STR_o "\0"
-#define STRING_Nushu0 STR_N STR_u STR_s STR_h STR_u "\0"
-#define STRING_Nyiakeng_Puachue_Hmong0 STR_N STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_UNDERSCORE STR_P STR_u STR_a STR_c STR_h STR_u STR_e STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"
-#define STRING_Ogham0 STR_O STR_g STR_h STR_a STR_m "\0"
-#define STRING_Ol_Chiki0 STR_O STR_l STR_UNDERSCORE STR_C STR_h STR_i STR_k STR_i "\0"
-#define STRING_Old_Hungarian0 STR_O STR_l STR_d STR_UNDERSCORE STR_H STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"
-#define STRING_Old_Italic0 STR_O STR_l STR_d STR_UNDERSCORE STR_I STR_t STR_a STR_l STR_i STR_c "\0"
-#define STRING_Old_North_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_N STR_o STR_r STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
-#define STRING_Old_Permic0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_m STR_i STR_c "\0"
-#define STRING_Old_Persian0 STR_O STR_l STR_d STR_UNDERSCORE STR_P STR_e STR_r STR_s STR_i STR_a STR_n "\0"
-#define STRING_Old_Sogdian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"
-#define STRING_Old_South_Arabian0 STR_O STR_l STR_d STR_UNDERSCORE STR_S STR_o STR_u STR_t STR_h STR_UNDERSCORE STR_A STR_r STR_a STR_b STR_i STR_a STR_n "\0"
-#define STRING_Old_Turkic0 STR_O STR_l STR_d STR_UNDERSCORE STR_T STR_u STR_r STR_k STR_i STR_c "\0"
-#define STRING_Old_Uyghur0 STR_O STR_l STR_d STR_UNDERSCORE STR_U STR_y STR_g STR_h STR_u STR_r "\0"
-#define STRING_Oriya0 STR_O STR_r STR_i STR_y STR_a "\0"
-#define STRING_Osage0 STR_O STR_s STR_a STR_g STR_e "\0"
-#define STRING_Osmanya0 STR_O STR_s STR_m STR_a STR_n STR_y STR_a "\0"
-#define STRING_P0 STR_P "\0"
-#define STRING_Pahawh_Hmong0 STR_P STR_a STR_h STR_a STR_w STR_h STR_UNDERSCORE STR_H STR_m STR_o STR_n STR_g "\0"
-#define STRING_Palmyrene0 STR_P STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"
-#define STRING_Pau_Cin_Hau0 STR_P STR_a STR_u STR_UNDERSCORE STR_C STR_i STR_n STR_UNDERSCORE STR_H STR_a STR_u "\0"
-#define STRING_Pc0 STR_P STR_c "\0"
-#define STRING_Pd0 STR_P STR_d "\0"
-#define STRING_Pe0 STR_P STR_e "\0"
-#define STRING_Pf0 STR_P STR_f "\0"
-#define STRING_Phags_Pa0 STR_P STR_h STR_a STR_g STR_s STR_UNDERSCORE STR_P STR_a "\0"
-#define STRING_Phoenician0 STR_P STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"
-#define STRING_Pi0 STR_P STR_i "\0"
-#define STRING_Po0 STR_P STR_o "\0"
-#define STRING_Ps0 STR_P STR_s "\0"
-#define STRING_Psalter_Pahlavi0 STR_P STR_s STR_a STR_l STR_t STR_e STR_r STR_UNDERSCORE STR_P STR_a STR_h STR_l STR_a STR_v STR_i "\0"
-#define STRING_Rejang0 STR_R STR_e STR_j STR_a STR_n STR_g "\0"
-#define STRING_Runic0 STR_R STR_u STR_n STR_i STR_c "\0"
-#define STRING_S0 STR_S "\0"
-#define STRING_Samaritan0 STR_S STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"
-#define STRING_Saurashtra0 STR_S STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"
-#define STRING_Sc0 STR_S STR_c "\0"
-#define STRING_Sharada0 STR_S STR_h STR_a STR_r STR_a STR_d STR_a "\0"
-#define STRING_Shavian0 STR_S STR_h STR_a STR_v STR_i STR_a STR_n "\0"
-#define STRING_Siddham0 STR_S STR_i STR_d STR_d STR_h STR_a STR_m "\0"
-#define STRING_SignWriting0 STR_S STR_i STR_g STR_n STR_W STR_r STR_i STR_t STR_i STR_n STR_g "\0"
-#define STRING_Sinhala0 STR_S STR_i STR_n STR_h STR_a STR_l STR_a "\0"
-#define STRING_Sk0 STR_S STR_k "\0"
-#define STRING_Sm0 STR_S STR_m "\0"
-#define STRING_So0 STR_S STR_o "\0"
-#define STRING_Sogdian0 STR_S STR_o STR_g STR_d STR_i STR_a STR_n "\0"
-#define STRING_Sora_Sompeng0 STR_S STR_o STR_r STR_a STR_UNDERSCORE STR_S STR_o STR_m STR_p STR_e STR_n STR_g "\0"
-#define STRING_Soyombo0 STR_S STR_o STR_y STR_o STR_m STR_b STR_o "\0"
-#define STRING_Sundanese0 STR_S STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
-#define STRING_Syloti_Nagri0 STR_S STR_y STR_l STR_o STR_t STR_i STR_UNDERSCORE STR_N STR_a STR_g STR_r STR_i "\0"
-#define STRING_Syriac0 STR_S STR_y STR_r STR_i STR_a STR_c "\0"
-#define STRING_Tagalog0 STR_T STR_a STR_g STR_a STR_l STR_o STR_g "\0"
-#define STRING_Tagbanwa0 STR_T STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"
-#define STRING_Tai_Le0 STR_T STR_a STR_i STR_UNDERSCORE STR_L STR_e "\0"
-#define STRING_Tai_Tham0 STR_T STR_a STR_i STR_UNDERSCORE STR_T STR_h STR_a STR_m "\0"
-#define STRING_Tai_Viet0 STR_T STR_a STR_i STR_UNDERSCORE STR_V STR_i STR_e STR_t "\0"
-#define STRING_Takri0 STR_T STR_a STR_k STR_r STR_i "\0"
-#define STRING_Tamil0 STR_T STR_a STR_m STR_i STR_l "\0"
-#define STRING_Tangsa0 STR_T STR_a STR_n STR_g STR_s STR_a "\0"
-#define STRING_Tangut0 STR_T STR_a STR_n STR_g STR_u STR_t "\0"
-#define STRING_Telugu0 STR_T STR_e STR_l STR_u STR_g STR_u "\0"
-#define STRING_Thaana0 STR_T STR_h STR_a STR_a STR_n STR_a "\0"
-#define STRING_Thai0 STR_T STR_h STR_a STR_i "\0"
-#define STRING_Tibetan0 STR_T STR_i STR_b STR_e STR_t STR_a STR_n "\0"
-#define STRING_Tifinagh0 STR_T STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
-#define STRING_Tirhuta0 STR_T STR_i STR_r STR_h STR_u STR_t STR_a "\0"
-#define STRING_Toto0 STR_T STR_o STR_t STR_o "\0"
-#define STRING_Ugaritic0 STR_U STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
-#define STRING_Unknown0 STR_U STR_n STR_k STR_n STR_o STR_w STR_n "\0"
-#define STRING_Vai0 STR_V STR_a STR_i "\0"
-#define STRING_Vithkuqi0 STR_V STR_i STR_t STR_h STR_k STR_u STR_q STR_i "\0"
-#define STRING_Wancho0 STR_W STR_a STR_n STR_c STR_h STR_o "\0"
-#define STRING_Warang_Citi0 STR_W STR_a STR_r STR_a STR_n STR_g STR_UNDERSCORE STR_C STR_i STR_t STR_i "\0"
-#define STRING_Xan0 STR_X STR_a STR_n "\0"
-#define STRING_Xps0 STR_X STR_p STR_s "\0"
-#define STRING_Xsp0 STR_X STR_s STR_p "\0"
-#define STRING_Xuc0 STR_X STR_u STR_c "\0"
-#define STRING_Xwd0 STR_X STR_w STR_d "\0"
-#define STRING_Yezidi0 STR_Y STR_e STR_z STR_i STR_d STR_i "\0"
-#define STRING_Yi0 STR_Y STR_i "\0"
-#define STRING_Z0 STR_Z "\0"
-#define STRING_Zanabazar_Square0 STR_Z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_UNDERSCORE STR_S STR_q STR_u STR_a STR_r STR_e "\0"
-#define STRING_Zl0 STR_Z STR_l "\0"
-#define STRING_Zp0 STR_Z STR_p "\0"
-#define STRING_Zs0 STR_Z STR_s "\0"
-
-const char PRIV(utt_names)[] =
- STRING_Adlam0
- STRING_Ahom0
- STRING_Anatolian_Hieroglyphs0
- STRING_Any0
- STRING_Arabic0
- STRING_Armenian0
- STRING_Avestan0
- STRING_Balinese0
- STRING_Bamum0
- STRING_Bassa_Vah0
- STRING_Batak0
- STRING_Bengali0
- STRING_Bhaiksuki0
- STRING_Bopomofo0
- STRING_Brahmi0
- STRING_Braille0
- STRING_Buginese0
- STRING_Buhid0
- STRING_C0
- STRING_Canadian_Aboriginal0
- STRING_Carian0
- STRING_Caucasian_Albanian0
- STRING_Cc0
- STRING_Cf0
- STRING_Chakma0
- STRING_Cham0
- STRING_Cherokee0
- STRING_Chorasmian0
- STRING_Cn0
- STRING_Co0
- STRING_Common0
- STRING_Coptic0
- STRING_Cs0
- STRING_Cuneiform0
- STRING_Cypriot0
- STRING_Cypro_Minoan0
- STRING_Cyrillic0
- STRING_Deseret0
- STRING_Devanagari0
- STRING_Dives_Akuru0
- STRING_Dogra0
- STRING_Duployan0
- STRING_Egyptian_Hieroglyphs0
- STRING_Elbasan0
- STRING_Elymaic0
- STRING_Ethiopic0
- STRING_Georgian0
- STRING_Glagolitic0
- STRING_Gothic0
- STRING_Grantha0
- STRING_Greek0
- STRING_Gujarati0
- STRING_Gunjala_Gondi0
- STRING_Gurmukhi0
- STRING_Han0
- STRING_Hangul0
- STRING_Hanifi_Rohingya0
- STRING_Hanunoo0
- STRING_Hatran0
- STRING_Hebrew0
- STRING_Hiragana0
- STRING_Imperial_Aramaic0
- STRING_Inherited0
- STRING_Inscriptional_Pahlavi0
- STRING_Inscriptional_Parthian0
- STRING_Javanese0
- STRING_Kaithi0
- STRING_Kannada0
- STRING_Katakana0
- STRING_Kayah_Li0
- STRING_Kharoshthi0
- STRING_Khitan_Small_Script0
- STRING_Khmer0
- STRING_Khojki0
- STRING_Khudawadi0
- STRING_L0
- STRING_L_AMPERSAND0
- STRING_Lao0
- STRING_Latin0
- STRING_Lepcha0
- STRING_Limbu0
- STRING_Linear_A0
- STRING_Linear_B0
- STRING_Lisu0
- STRING_Ll0
- STRING_Lm0
- STRING_Lo0
- STRING_Lt0
- STRING_Lu0
- STRING_Lycian0
- STRING_Lydian0
- STRING_M0
- STRING_Mahajani0
- STRING_Makasar0
- STRING_Malayalam0
- STRING_Mandaic0
- STRING_Manichaean0
- STRING_Marchen0
- STRING_Masaram_Gondi0
- STRING_Mc0
- STRING_Me0
- STRING_Medefaidrin0
- STRING_Meetei_Mayek0
- STRING_Mende_Kikakui0
- STRING_Meroitic_Cursive0
- STRING_Meroitic_Hieroglyphs0
- STRING_Miao0
- STRING_Mn0
- STRING_Modi0
- STRING_Mongolian0
- STRING_Mro0
- STRING_Multani0
- STRING_Myanmar0
- STRING_N0
- STRING_Nabataean0
- STRING_Nandinagari0
- STRING_Nd0
- STRING_New_Tai_Lue0
- STRING_Newa0
- STRING_Nko0
- STRING_Nl0
- STRING_No0
- STRING_Nushu0
- STRING_Nyiakeng_Puachue_Hmong0
- STRING_Ogham0
- STRING_Ol_Chiki0
- STRING_Old_Hungarian0
- STRING_Old_Italic0
- STRING_Old_North_Arabian0
- STRING_Old_Permic0
- STRING_Old_Persian0
- STRING_Old_Sogdian0
- STRING_Old_South_Arabian0
- STRING_Old_Turkic0
- STRING_Old_Uyghur0
- STRING_Oriya0
- STRING_Osage0
- STRING_Osmanya0
- STRING_P0
- STRING_Pahawh_Hmong0
- STRING_Palmyrene0
- STRING_Pau_Cin_Hau0
- STRING_Pc0
- STRING_Pd0
- STRING_Pe0
- STRING_Pf0
- STRING_Phags_Pa0
- STRING_Phoenician0
- STRING_Pi0
- STRING_Po0
- STRING_Ps0
- STRING_Psalter_Pahlavi0
- STRING_Rejang0
- STRING_Runic0
- STRING_S0
- STRING_Samaritan0
- STRING_Saurashtra0
- STRING_Sc0
- STRING_Sharada0
- STRING_Shavian0
- STRING_Siddham0
- STRING_SignWriting0
- STRING_Sinhala0
- STRING_Sk0
- STRING_Sm0
- STRING_So0
- STRING_Sogdian0
- STRING_Sora_Sompeng0
- STRING_Soyombo0
- STRING_Sundanese0
- STRING_Syloti_Nagri0
- STRING_Syriac0
- STRING_Tagalog0
- STRING_Tagbanwa0
- STRING_Tai_Le0
- STRING_Tai_Tham0
- STRING_Tai_Viet0
- STRING_Takri0
- STRING_Tamil0
- STRING_Tangsa0
- STRING_Tangut0
- STRING_Telugu0
- STRING_Thaana0
- STRING_Thai0
- STRING_Tibetan0
- STRING_Tifinagh0
- STRING_Tirhuta0
- STRING_Toto0
- STRING_Ugaritic0
- STRING_Unknown0
- STRING_Vai0
- STRING_Vithkuqi0
- STRING_Wancho0
- STRING_Warang_Citi0
- STRING_Xan0
- STRING_Xps0
- STRING_Xsp0
- STRING_Xuc0
- STRING_Xwd0
- STRING_Yezidi0
- STRING_Yi0
- STRING_Z0
- STRING_Zanabazar_Square0
- STRING_Zl0
- STRING_Zp0
- STRING_Zs0;
-
-const ucp_type_table PRIV(utt)[] = {
- { 0, PT_SC, ucp_Adlam },
- { 6, PT_SC, ucp_Ahom },
- { 11, PT_SC, ucp_Anatolian_Hieroglyphs },
- { 33, PT_ANY, 0 },
- { 37, PT_SC, ucp_Arabic },
- { 44, PT_SC, ucp_Armenian },
- { 53, PT_SC, ucp_Avestan },
- { 61, PT_SC, ucp_Balinese },
- { 70, PT_SC, ucp_Bamum },
- { 76, PT_SC, ucp_Bassa_Vah },
- { 86, PT_SC, ucp_Batak },
- { 92, PT_SC, ucp_Bengali },
- { 100, PT_SC, ucp_Bhaiksuki },
- { 110, PT_SC, ucp_Bopomofo },
- { 119, PT_SC, ucp_Brahmi },
- { 126, PT_SC, ucp_Braille },
- { 134, PT_SC, ucp_Buginese },
- { 143, PT_SC, ucp_Buhid },
- { 149, PT_GC, ucp_C },
- { 151, PT_SC, ucp_Canadian_Aboriginal },
- { 171, PT_SC, ucp_Carian },
- { 178, PT_SC, ucp_Caucasian_Albanian },
- { 197, PT_PC, ucp_Cc },
- { 200, PT_PC, ucp_Cf },
- { 203, PT_SC, ucp_Chakma },
- { 210, PT_SC, ucp_Cham },
- { 215, PT_SC, ucp_Cherokee },
- { 224, PT_SC, ucp_Chorasmian },
- { 235, PT_PC, ucp_Cn },
- { 238, PT_PC, ucp_Co },
- { 241, PT_SC, ucp_Common },
- { 248, PT_SC, ucp_Coptic },
- { 255, PT_PC, ucp_Cs },
- { 258, PT_SC, ucp_Cuneiform },
- { 268, PT_SC, ucp_Cypriot },
- { 276, PT_SC, ucp_Cypro_Minoan },
- { 289, PT_SC, ucp_Cyrillic },
- { 298, PT_SC, ucp_Deseret },
- { 306, PT_SC, ucp_Devanagari },
- { 317, PT_SC, ucp_Dives_Akuru },
- { 329, PT_SC, ucp_Dogra },
- { 335, PT_SC, ucp_Duployan },
- { 344, PT_SC, ucp_Egyptian_Hieroglyphs },
- { 365, PT_SC, ucp_Elbasan },
- { 373, PT_SC, ucp_Elymaic },
- { 381, PT_SC, ucp_Ethiopic },
- { 390, PT_SC, ucp_Georgian },
- { 399, PT_SC, ucp_Glagolitic },
- { 410, PT_SC, ucp_Gothic },
- { 417, PT_SC, ucp_Grantha },
- { 425, PT_SC, ucp_Greek },
- { 431, PT_SC, ucp_Gujarati },
- { 440, PT_SC, ucp_Gunjala_Gondi },
- { 454, PT_SC, ucp_Gurmukhi },
- { 463, PT_SC, ucp_Han },
- { 467, PT_SC, ucp_Hangul },
- { 474, PT_SC, ucp_Hanifi_Rohingya },
- { 490, PT_SC, ucp_Hanunoo },
- { 498, PT_SC, ucp_Hatran },
- { 505, PT_SC, ucp_Hebrew },
- { 512, PT_SC, ucp_Hiragana },
- { 521, PT_SC, ucp_Imperial_Aramaic },
- { 538, PT_SC, ucp_Inherited },
- { 548, PT_SC, ucp_Inscriptional_Pahlavi },
- { 570, PT_SC, ucp_Inscriptional_Parthian },
- { 593, PT_SC, ucp_Javanese },
- { 602, PT_SC, ucp_Kaithi },
- { 609, PT_SC, ucp_Kannada },
- { 617, PT_SC, ucp_Katakana },
- { 626, PT_SC, ucp_Kayah_Li },
- { 635, PT_SC, ucp_Kharoshthi },
- { 646, PT_SC, ucp_Khitan_Small_Script },
- { 666, PT_SC, ucp_Khmer },
- { 672, PT_SC, ucp_Khojki },
- { 679, PT_SC, ucp_Khudawadi },
- { 689, PT_GC, ucp_L },
- { 691, PT_LAMP, 0 },
- { 694, PT_SC, ucp_Lao },
- { 698, PT_SC, ucp_Latin },
- { 704, PT_SC, ucp_Lepcha },
- { 711, PT_SC, ucp_Limbu },
- { 717, PT_SC, ucp_Linear_A },
- { 726, PT_SC, ucp_Linear_B },
- { 735, PT_SC, ucp_Lisu },
- { 740, PT_PC, ucp_Ll },
- { 743, PT_PC, ucp_Lm },
- { 746, PT_PC, ucp_Lo },
- { 749, PT_PC, ucp_Lt },
- { 752, PT_PC, ucp_Lu },
- { 755, PT_SC, ucp_Lycian },
- { 762, PT_SC, ucp_Lydian },
- { 769, PT_GC, ucp_M },
- { 771, PT_SC, ucp_Mahajani },
- { 780, PT_SC, ucp_Makasar },
- { 788, PT_SC, ucp_Malayalam },
- { 798, PT_SC, ucp_Mandaic },
- { 806, PT_SC, ucp_Manichaean },
- { 817, PT_SC, ucp_Marchen },
- { 825, PT_SC, ucp_Masaram_Gondi },
- { 839, PT_PC, ucp_Mc },
- { 842, PT_PC, ucp_Me },
- { 845, PT_SC, ucp_Medefaidrin },
- { 857, PT_SC, ucp_Meetei_Mayek },
- { 870, PT_SC, ucp_Mende_Kikakui },
- { 884, PT_SC, ucp_Meroitic_Cursive },
- { 901, PT_SC, ucp_Meroitic_Hieroglyphs },
- { 922, PT_SC, ucp_Miao },
- { 927, PT_PC, ucp_Mn },
- { 930, PT_SC, ucp_Modi },
- { 935, PT_SC, ucp_Mongolian },
- { 945, PT_SC, ucp_Mro },
- { 949, PT_SC, ucp_Multani },
- { 957, PT_SC, ucp_Myanmar },
- { 965, PT_GC, ucp_N },
- { 967, PT_SC, ucp_Nabataean },
- { 977, PT_SC, ucp_Nandinagari },
- { 989, PT_PC, ucp_Nd },
- { 992, PT_SC, ucp_New_Tai_Lue },
- { 1004, PT_SC, ucp_Newa },
- { 1009, PT_SC, ucp_Nko },
- { 1013, PT_PC, ucp_Nl },
- { 1016, PT_PC, ucp_No },
- { 1019, PT_SC, ucp_Nushu },
- { 1025, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
- { 1048, PT_SC, ucp_Ogham },
- { 1054, PT_SC, ucp_Ol_Chiki },
- { 1063, PT_SC, ucp_Old_Hungarian },
- { 1077, PT_SC, ucp_Old_Italic },
- { 1088, PT_SC, ucp_Old_North_Arabian },
- { 1106, PT_SC, ucp_Old_Permic },
- { 1117, PT_SC, ucp_Old_Persian },
- { 1129, PT_SC, ucp_Old_Sogdian },
- { 1141, PT_SC, ucp_Old_South_Arabian },
- { 1159, PT_SC, ucp_Old_Turkic },
- { 1170, PT_SC, ucp_Old_Uyghur },
- { 1181, PT_SC, ucp_Oriya },
- { 1187, PT_SC, ucp_Osage },
- { 1193, PT_SC, ucp_Osmanya },
- { 1201, PT_GC, ucp_P },
- { 1203, PT_SC, ucp_Pahawh_Hmong },
- { 1216, PT_SC, ucp_Palmyrene },
- { 1226, PT_SC, ucp_Pau_Cin_Hau },
- { 1238, PT_PC, ucp_Pc },
- { 1241, PT_PC, ucp_Pd },
- { 1244, PT_PC, ucp_Pe },
- { 1247, PT_PC, ucp_Pf },
- { 1250, PT_SC, ucp_Phags_Pa },
- { 1259, PT_SC, ucp_Phoenician },
- { 1270, PT_PC, ucp_Pi },
- { 1273, PT_PC, ucp_Po },
- { 1276, PT_PC, ucp_Ps },
- { 1279, PT_SC, ucp_Psalter_Pahlavi },
- { 1295, PT_SC, ucp_Rejang },
- { 1302, PT_SC, ucp_Runic },
- { 1308, PT_GC, ucp_S },
- { 1310, PT_SC, ucp_Samaritan },
- { 1320, PT_SC, ucp_Saurashtra },
- { 1331, PT_PC, ucp_Sc },
- { 1334, PT_SC, ucp_Sharada },
- { 1342, PT_SC, ucp_Shavian },
- { 1350, PT_SC, ucp_Siddham },
- { 1358, PT_SC, ucp_SignWriting },
- { 1370, PT_SC, ucp_Sinhala },
- { 1378, PT_PC, ucp_Sk },
- { 1381, PT_PC, ucp_Sm },
- { 1384, PT_PC, ucp_So },
- { 1387, PT_SC, ucp_Sogdian },
- { 1395, PT_SC, ucp_Sora_Sompeng },
- { 1408, PT_SC, ucp_Soyombo },
- { 1416, PT_SC, ucp_Sundanese },
- { 1426, PT_SC, ucp_Syloti_Nagri },
- { 1439, PT_SC, ucp_Syriac },
- { 1446, PT_SC, ucp_Tagalog },
- { 1454, PT_SC, ucp_Tagbanwa },
- { 1463, PT_SC, ucp_Tai_Le },
- { 1470, PT_SC, ucp_Tai_Tham },
- { 1479, PT_SC, ucp_Tai_Viet },
- { 1488, PT_SC, ucp_Takri },
- { 1494, PT_SC, ucp_Tamil },
- { 1500, PT_SC, ucp_Tangsa },
- { 1507, PT_SC, ucp_Tangut },
- { 1514, PT_SC, ucp_Telugu },
- { 1521, PT_SC, ucp_Thaana },
- { 1528, PT_SC, ucp_Thai },
- { 1533, PT_SC, ucp_Tibetan },
- { 1541, PT_SC, ucp_Tifinagh },
- { 1550, PT_SC, ucp_Tirhuta },
- { 1558, PT_SC, ucp_Toto },
- { 1563, PT_SC, ucp_Ugaritic },
- { 1572, PT_SC, ucp_Unknown },
- { 1580, PT_SC, ucp_Vai },
- { 1584, PT_SC, ucp_Vithkuqi },
- { 1593, PT_SC, ucp_Wancho },
- { 1600, PT_SC, ucp_Warang_Citi },
- { 1612, PT_ALNUM, 0 },
- { 1616, PT_PXSPACE, 0 },
- { 1620, PT_SPACE, 0 },
- { 1624, PT_UCNC, 0 },
- { 1628, PT_WORD, 0 },
- { 1632, PT_SC, ucp_Yezidi },
- { 1639, PT_SC, ucp_Yi },
- { 1642, PT_GC, ucp_Z },
- { 1644, PT_SC, ucp_Zanabazar_Square },
- { 1661, PT_PC, ucp_Zl },
- { 1664, PT_PC, ucp_Zp },
- { 1667, PT_PC, ucp_Zs }
-};
+/* Finally, include the tables that are auto-generated from the Unicode data
+files. */
-const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
+#include "pcre2_ucptables.c"
#endif /* SUPPORT_UNICODE */
diff --git a/thirdparty/pcre2/src/pcre2_ucd.c b/thirdparty/pcre2/src/pcre2_ucd.c
index 0b8ac75bd4..5e0fc37c35 100644
--- a/thirdparty/pcre2/src/pcre2_ucd.c
+++ b/thirdparty/pcre2/src/pcre2_ucd.c
@@ -1,36 +1,71 @@
-/* This module is generated by the maint/MultiStage2.py script.
-Do not modify it by hand. Instead modify the script and run it
-to regenerate this code.
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
+
+This module is auto-generated from Unicode data files. DO NOT EDIT MANUALLY!
+Instead, modify the maint/GenerateUcd.py script and run it to generate
+a new version of this code.
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
-As well as being part of the PCRE2 library, this module is #included
-by the pcre2test program, which redefines the PRIV macro to change
-table names from _pcre2_xxx to xxxx, thereby avoiding name clashes
-with the library. At present, just one of these tables is actually
-needed. */
+/* This file contains tables of Unicode properties that are extracted from
+Unicode data files. See the comments at the start of maint/GenerateUcd.py for
+details.
-#ifndef PCRE2_PCRE2TEST
+As well as being part of the PCRE2 library, this file is #included by the
+pcre2test program, which redefines the PRIV macro to change table names from
+_pcre2_xxx to xxxx, thereby avoiding name clashes with the library. At present,
+just one of these tables is actually needed. When compiling the library, some
+headers are needed. */
+#ifndef PCRE2_PCRE2TEST
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-
#include "pcre2_internal.h"
-
#endif /* PCRE2_PCRE2TEST */
-/* Unicode character database. */
-/* This file was autogenerated by the MultiStage2.py script. */
-/* Total size: 102844 bytes, block size: 128. */
-
-/* The tables herein are needed only when UCP support is built,
-and in PCRE2 that happens automatically with UTF support.
-This module should not be referenced otherwise, so
-it should not matter whether it is compiled or not. However
-a comment was received about space saving - maybe the guy linked
-all the modules rather than using a library - so we include a
-condition to cut out the tables when not needed. But don't leave
-a totally empty module because some compilers barf at that.
-Instead, just supply some small dummy tables. */
+/* The tables herein are needed only when UCP support is built, and in PCRE2
+that happens automatically with UTF support. This module should not be
+referenced otherwise, so it should not matter whether it is compiled or not.
+However a comment was received about space saving - maybe the guy linked all
+the modules rather than using a library - so we include a condition to cut out
+the tables when not needed. But don't leave a totally empty module because some
+compilers barf at that. Instead, just supply some small dummy tables. */
#ifndef SUPPORT_UNICODE
const ucd_record PRIV(ucd_records)[] = {{0,0,0,0,0,0,0 }};
@@ -39,11 +74,27 @@ const uint16_t PRIV(ucd_stage2)[] = {0};
const uint32_t PRIV(ucd_caseless_sets)[] = {0};
#else
+/* Total size: 111116 bytes, block size: 128. */
+
const char *PRIV(unicode_version) = "14.0.0";
-/* If the 32-bit library is run in non-32-bit mode, character values
-greater than 0x10ffff may be encountered. For these we set up a
-special record. */
+/* When recompiling tables with a new Unicode version, please check the types
+in this structure definition with those in pcre2_internal.h (the actual field
+names will be different).
+
+typedef struct {
+uint8_t property_0;
+uint8_t property_1;
+uint8_t property_2;
+uint8_t property_3;
+int32_t property_4;
+uint16_t property_5;
+uint16_t property_6;
+} ucd_record;
+*/
+
+/* If the 32-bit library is run in non-32-bit mode, character values greater
+than 0x10ffff may be encountered. For these we set up a special record. */
#if PCRE2_CODE_UNIT_WIDTH == 32
const ucd_record PRIV(dummy_ucd_record)[] = {{
@@ -52,68 +103,53 @@ const ucd_record PRIV(dummy_ucd_record)[] = {{
ucp_gbOther, /* grapheme break property */
0, /* case set */
0, /* other case */
- ucp_Unknown, /* script extension */
- 0, /* dummy filler */
+ 0 | (ucp_bidiL << UCD_BIDICLASS_SHIFT), /* script extension and bidi class */
+ 0, /* bool properties offset */
}};
#endif
-/* When recompiling tables with a new Unicode version, please check the
-types in this structure definition from pcre2_internal.h (the actual
-field names will be different):
-
-typedef struct {
-uint8_t property_0;
-uint8_t property_1;
-uint8_t property_2;
-uint8_t property_3;
-pcre_int32 property_4;
-pcre_int16 property_5;
-uint16_t property_6;
-} ucd_record;
-*/
-
/* This table contains lists of characters that are caseless sets of
more than one character. Each list is terminated by NOTACHAR. */
const uint32_t PRIV(ucd_caseless_sets)[] = {
NOTACHAR,
- 0x0053, 0x0073, 0x017f, NOTACHAR,
- 0x01c4, 0x01c5, 0x01c6, NOTACHAR,
- 0x01c7, 0x01c8, 0x01c9, NOTACHAR,
- 0x01ca, 0x01cb, 0x01cc, NOTACHAR,
- 0x01f1, 0x01f2, 0x01f3, NOTACHAR,
- 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,
- 0x00b5, 0x039c, 0x03bc, NOTACHAR,
- 0x03a3, 0x03c2, 0x03c3, NOTACHAR,
- 0x0392, 0x03b2, 0x03d0, NOTACHAR,
- 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,
- 0x03a6, 0x03c6, 0x03d5, NOTACHAR,
- 0x03a0, 0x03c0, 0x03d6, NOTACHAR,
- 0x039a, 0x03ba, 0x03f0, NOTACHAR,
- 0x03a1, 0x03c1, 0x03f1, NOTACHAR,
- 0x0395, 0x03b5, 0x03f5, NOTACHAR,
- 0x0412, 0x0432, 0x1c80, NOTACHAR,
- 0x0414, 0x0434, 0x1c81, NOTACHAR,
- 0x041e, 0x043e, 0x1c82, NOTACHAR,
- 0x0421, 0x0441, 0x1c83, NOTACHAR,
- 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR,
- 0x042a, 0x044a, 0x1c86, NOTACHAR,
- 0x0462, 0x0463, 0x1c87, NOTACHAR,
- 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,
- 0x03a9, 0x03c9, 0x2126, NOTACHAR,
- 0x004b, 0x006b, 0x212a, NOTACHAR,
- 0x00c5, 0x00e5, 0x212b, NOTACHAR,
- 0x1c88, 0xa64a, 0xa64b, NOTACHAR,
+ 0x0053, 0x0073, 0x017f, NOTACHAR,
+ 0x01c4, 0x01c5, 0x01c6, NOTACHAR,
+ 0x01c7, 0x01c8, 0x01c9, NOTACHAR,
+ 0x01ca, 0x01cb, 0x01cc, NOTACHAR,
+ 0x01f1, 0x01f2, 0x01f3, NOTACHAR,
+ 0x0345, 0x0399, 0x03b9, 0x1fbe, NOTACHAR,
+ 0x00b5, 0x039c, 0x03bc, NOTACHAR,
+ 0x03a3, 0x03c2, 0x03c3, NOTACHAR,
+ 0x0392, 0x03b2, 0x03d0, NOTACHAR,
+ 0x0398, 0x03b8, 0x03d1, 0x03f4, NOTACHAR,
+ 0x03a6, 0x03c6, 0x03d5, NOTACHAR,
+ 0x03a0, 0x03c0, 0x03d6, NOTACHAR,
+ 0x039a, 0x03ba, 0x03f0, NOTACHAR,
+ 0x03a1, 0x03c1, 0x03f1, NOTACHAR,
+ 0x0395, 0x03b5, 0x03f5, NOTACHAR,
+ 0x0412, 0x0432, 0x1c80, NOTACHAR,
+ 0x0414, 0x0434, 0x1c81, NOTACHAR,
+ 0x041e, 0x043e, 0x1c82, NOTACHAR,
+ 0x0421, 0x0441, 0x1c83, NOTACHAR,
+ 0x0422, 0x0442, 0x1c84, 0x1c85, NOTACHAR,
+ 0x042a, 0x044a, 0x1c86, NOTACHAR,
+ 0x0462, 0x0463, 0x1c87, NOTACHAR,
+ 0x1e60, 0x1e61, 0x1e9b, NOTACHAR,
+ 0x03a9, 0x03c9, 0x2126, NOTACHAR,
+ 0x004b, 0x006b, 0x212a, NOTACHAR,
+ 0x00c5, 0x00e5, 0x212b, NOTACHAR,
+ 0x1c88, 0xa64a, 0xa64b, NOTACHAR,
};
-/* When #included in pcre2test, we don't need the table of digit
-sets, nor the the large main UCD tables. */
+/* When #included in pcre2test, we don't need the table of digit sets, nor the
+the large main UCD tables. */
#ifndef PCRE2_PCRE2TEST
-/* This table lists the code points for the '9' characters in each
-set of decimal digits. It is used to ensure that all the digits in
-a script run come from the same set. */
+/* This table lists the code points for the '9' characters in each set of
+decimal digits. It is used to ensure that all the digits in a script run come
+from the same set. */
const uint32_t PRIV(ucd_digit_sets)[] = {
66, /* Number of subsequent values */
@@ -128,1072 +164,1676 @@ const uint32_t PRIV(ucd_digit_sets)[] = {
0x1e959, 0x1fbf9,
};
-/* This vector is a list of lists of scripts for the Script Extension
-property. Each sublist is zero-terminated. */
-
-const uint8_t PRIV(ucd_script_sets)[] = {
- /* 0 */ 0,
- /* 1 */ 1, 11, 0,
- /* 4 */ 1, 144, 0,
- /* 7 */ 1, 64, 0,
- /* 10 */ 1, 50, 0,
- /* 13 */ 1, 56, 0,
- /* 16 */ 3, 15, 0,
- /* 19 */ 4, 23, 0,
- /* 22 */ 6, 84, 0,
- /* 25 */ 12, 36, 0,
- /* 28 */ 13, 18, 0,
- /* 31 */ 13, 34, 0,
- /* 34 */ 13, 118, 0,
- /* 37 */ 13, 50, 0,
- /* 40 */ 15, 107, 0,
- /* 43 */ 15, 150, 0,
- /* 46 */ 15, 100, 0,
- /* 49 */ 15, 54, 0,
- /* 52 */ 17, 34, 0,
- /* 55 */ 107, 54, 0,
- /* 58 */ 21, 108, 0,
- /* 61 */ 22, 129, 0,
- /* 64 */ 23, 34, 0,
- /* 67 */ 27, 30, 0,
- /* 70 */ 29, 150, 0,
- /* 73 */ 34, 38, 0,
- /* 76 */ 112, 158, 0,
- /* 79 */ 38, 65, 0,
- /* 82 */ 1, 50, 56, 0,
- /* 86 */ 1, 56, 156, 0,
- /* 90 */ 3, 96, 49, 0,
- /* 94 */ 96, 39, 53, 0,
- /* 98 */ 157, 12, 36, 0,
- /* 102 */ 12, 110, 36, 0,
- /* 106 */ 15, 107, 29, 0,
- /* 110 */ 15, 107, 34, 0,
- /* 114 */ 23, 27, 30, 0,
- /* 118 */ 69, 34, 39, 0,
- /* 122 */ 3, 15, 107, 29, 0,
- /* 127 */ 7, 25, 52, 51, 0,
- /* 132 */ 15, 142, 85, 111, 0,
- /* 137 */ 4, 24, 23, 27, 30, 0,
- /* 143 */ 1, 64, 144, 50, 56, 156, 0,
- /* 150 */ 4, 24, 23, 27, 30, 61, 0,
- /* 157 */ 15, 29, 37, 44, 54, 55, 0,
- /* 164 */ 132, 1, 64, 144, 50, 56, 156, 0,
- /* 172 */ 3, 15, 107, 29, 150, 44, 55, 124, 0,
- /* 181 */ 132, 1, 95, 112, 158, 121, 144, 148, 50, 0,
- /* 191 */ 15, 142, 21, 22, 108, 85, 111, 114, 109, 102, 124, 0,
- /* 203 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 54, 55, 124, 0,
- /* 216 */ 3, 15, 107, 21, 22, 29, 34, 37, 44, 100, 54, 55, 124, 0,
- /* 230 */ 15, 142, 21, 22, 108, 29, 85, 111, 114, 150, 109, 102, 124, 0,
- /* 244 */ 15, 142, 21, 22, 108, 29, 85, 111, 37, 114, 150, 109, 102, 124, 0,
- /* 259 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,
- /* 280 */ 3, 15, 142, 143, 138, 107, 21, 22, 29, 35, 111, 37, 150, 44, 109, 48, 49, 102, 54, 55, 124, 0,
- /* 302 */
+/* This vector is a list of script bitsets for the Script Extension property.
+The number of 32-bit words in each bitset is #defined in pcre2_ucp.h as
+ucd_script_sets_item_size. */
+
+const uint32_t PRIV(ucd_script_sets)[] = {
+ 0x00000000u, 0x00000000u, 0x00000000u,
+ 0x00000080u, 0x00000000u, 0x00000000u,
+ 0x00000040u, 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00004000u, 0x00000000u,
+ 0x00000002u, 0x00000000u, 0x00000000u,
+ 0x00800000u, 0x00000000u, 0x00000000u,
+ 0x00000001u, 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000000u, 0x00000001u,
+ 0x00000010u, 0x00000000u, 0x00000000u,
+ 0x00000008u, 0x00000004u, 0x00000000u,
+ 0x00000008u, 0x40000000u, 0x00000000u,
+ 0x00000008u, 0x00000040u, 0x00000000u,
+ 0x00000018u, 0x00000000u, 0x00000000u,
+ 0x00000028u, 0x00000000u, 0x00000000u,
+ 0x000000c0u, 0x00000000u, 0x00000000u,
+ 0x00c00000u, 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00000102u, 0x00000000u,
+ 0x80000000u, 0x00000001u, 0x00000000u,
+ 0x00000004u, 0x00000008u, 0x00000000u,
+ 0x00000005u, 0x00000000u, 0x00000000u,
+ 0x00000004u, 0x00200000u, 0x00000000u,
+ 0x00000014u, 0x00000000u, 0x00000000u,
+ 0x00000040u, 0x00008000u, 0x00000000u,
+ 0x00000040u, 0x00000000u, 0x00000001u,
+ 0x00000040u, 0x00001000u, 0x00000000u,
+ 0x00000840u, 0x00000000u, 0x00000000u,
+ 0x00020001u, 0x00000000u, 0x00000000u,
+ 0x00000800u, 0x00008000u, 0x00000000u,
+ 0x00000200u, 0x00010000u, 0x00000000u,
+ 0x00000100u, 0x02000000u, 0x00000000u,
+ 0x00800001u, 0x00000000u, 0x00000000u,
+ 0x00300000u, 0x00000000u, 0x00000000u,
+ 0x00002000u, 0x00000000u, 0x00000001u,
+ 0x00080001u, 0x00000000u, 0x00000000u,
+ 0x00000000u, 0x00080000u, 0x00000008u,
+ 0x00080000u, 0x00000020u, 0x00000000u,
+ 0x00000038u, 0x00000000u, 0x00000000u,
+ 0x00000028u, 0x00000000u, 0x00000002u,
+ 0x00000080u, 0x00000810u, 0x00000000u,
+ 0x40010000u, 0x00000800u, 0x00000000u,
+ 0x80000000u, 0x00000001u, 0x00000004u,
+ 0x80000000u, 0x00020001u, 0x00000000u,
+ 0x00002040u, 0x00008000u, 0x00000000u,
+ 0x00000041u, 0x00008000u, 0x00000000u,
+ 0x00b00000u, 0x00000000u, 0x00000000u,
+ 0x00010001u, 0x00000080u, 0x00000000u,
+ 0x000020c0u, 0x00008000u, 0x00000000u,
+ 0x1e000000u, 0x00000000u, 0x00000000u,
+ 0x00000040u, 0x10040200u, 0x00000000u,
+ 0x00f40000u, 0x00000000u, 0x00000000u,
+ 0x00000038u, 0x40000040u, 0x00000002u,
+ 0x01f40000u, 0x00000000u, 0x00000000u,
+ 0x00007c40u, 0x00000000u, 0x00000000u,
+ 0x00000038u, 0x44000040u, 0x00000002u,
+ 0x000034c0u, 0x01008000u, 0x00000001u,
+ 0x00000018u, 0xc4480400u, 0x00000008u,
+ 0x00000340u, 0x11952200u, 0x00000000u,
+ 0x00007fc1u, 0x01008000u, 0x00000000u,
+ 0x00007fc1u, 0x01009000u, 0x00000000u,
+ 0x00002340u, 0x11952200u, 0x00000001u,
+ 0x00006340u, 0x11952200u, 0x00000001u,
+ 0x0000ffc0u, 0x3984a010u, 0x00000001u,
+ 0x2000ffc0u, 0x3984a010u, 0x00000001u,
+};
+
+/* This vector is a list of bitsets for Boolean properties. The number of
+32_bit words in each bitset is #defined as ucd_boolprop_sets_item_size in
+pcre2_ucp.h. */
+
+const uint32_t PRIV(ucd_boolprop_sets)[] = {
+ 0x00000000u, 0x00000000u,
+ 0x00000001u, 0x00000000u,
+ 0x00000001u, 0x00020040u,
+ 0x00800001u, 0x00020040u,
+ 0x00800001u, 0x00002820u,
+ 0x00800001u, 0x00000120u,
+ 0x00830001u, 0x00000020u,
+ 0x00800001u, 0x00000020u,
+ 0x00800021u, 0x00000120u,
+ 0x00800011u, 0x00000020u,
+ 0x00800001u, 0x00000028u,
+ 0x00800001u, 0x00002020u,
+ 0x00801001u, 0x00000020u,
+ 0x00800021u, 0x00002820u,
+ 0x24830003u, 0x00040000u,
+ 0x00800021u, 0x00002020u,
+ 0x00800011u, 0x00000028u,
+ 0x648003c7u, 0x000c8000u,
+ 0x608003c5u, 0x000c8000u,
+ 0x00808021u, 0x00000028u,
+ 0x20800001u, 0x00040000u,
+ 0x00808021u, 0x00000020u,
+ 0x64800d47u, 0x000c0004u,
+ 0x60800d45u, 0x000c0004u,
+ 0x60800d45u, 0x000c1004u,
+ 0x00000000u, 0x00020040u,
+ 0x00800000u, 0x00020000u,
+ 0x00800000u, 0x00000020u,
+ 0x00808020u, 0x00000000u,
+ 0x00a10000u, 0x00000020u,
+ 0x60800044u, 0x000c0004u,
+ 0x00800010u, 0x00000120u,
+ 0x00800000u, 0x00000028u,
+ 0x00002020u, 0x00000000u,
+ 0x00800000u, 0x00000000u,
+ 0x60800dc4u, 0x000c0004u,
+ 0x20c08020u, 0x00040000u,
+ 0x608003c4u, 0x000c8000u,
+ 0x60800d44u, 0x000c0004u,
+ 0x60800d44u, 0x000c1004u,
+ 0x60804dc4u, 0x000c0004u,
+ 0x60800004u, 0x000c0000u,
+ 0x608007c4u, 0x000c8000u,
+ 0x60800bc4u, 0x000c0000u,
+ 0x60808064u, 0x000c0004u,
+ 0x60808064u, 0x000c1004u,
+ 0x60808024u, 0x000c0000u,
+ 0x60c08024u, 0x000c0000u,
+ 0x21008020u, 0x00040000u,
+ 0x21008de4u, 0x00040004u,
+ 0x21002020u, 0x00040000u,
+ 0x21000020u, 0x00040000u,
+ 0x60808064u, 0x00000004u,
+ 0x00800000u, 0x00002000u,
+ 0x20800020u, 0x00042000u,
+ 0x60800dc4u, 0x000c000cu,
+ 0x60800044u, 0x000c8008u,
+ 0x60800044u, 0x000c8000u,
+ 0x608003c4u, 0x000c8008u,
+ 0x00800000u, 0x00000008u,
+ 0x01000020u, 0x00000000u,
+ 0x00800020u, 0x00000000u,
+ 0x00800000u, 0x00002800u,
+ 0x00801000u, 0x00000000u,
+ 0x21008024u, 0x00040000u,
+ 0x21000024u, 0x00040000u,
+ 0x00000020u, 0x00000080u,
+ 0x00002028u, 0x00000000u,
+ 0x60c00024u, 0x000c0000u,
+ 0x20800000u, 0x00040000u,
+ 0x60804004u, 0x000c0000u,
+ 0x60800024u, 0x000c0000u,
+ 0x20800004u, 0x00040000u,
+ 0x23008020u, 0x00040000u,
+ 0x21000004u, 0x00040000u,
+ 0x21408020u, 0x00040000u,
+ 0x60800004u, 0x00040000u,
+ 0x23000024u, 0x00040000u,
+ 0x60800004u, 0x000c0002u,
+ 0x00800010u, 0x00000000u,
+ 0x20808000u, 0x00040000u,
+ 0x21004024u, 0x00040000u,
+ 0x20808004u, 0x00040000u,
+ 0x60800944u, 0x000c0004u,
+ 0x60802004u, 0x000c0000u,
+ 0x60800344u, 0x000c8000u,
+ 0x22808000u, 0x00040000u,
+ 0x22800000u, 0x00040000u,
+ 0x00c00000u, 0x00000000u,
+ 0x21002020u, 0x00050000u,
+ 0x61000024u, 0x000c0000u,
+ 0x23000020u, 0x00040000u,
+ 0x01008020u, 0x00000000u,
+ 0x21408024u, 0x00040000u,
+ 0x00808000u, 0x00000000u,
+ 0x60800064u, 0x000c0004u,
+ 0x60800044u, 0x000c1004u,
+ 0x60800064u, 0x000c1004u,
+ 0x01002020u, 0x00000001u,
+ 0x00022020u, 0x00000001u,
+ 0x00002028u, 0x00000040u,
+ 0x00801000u, 0x00000020u,
+ 0x00800020u, 0x00000120u,
+ 0x00800000u, 0x00000120u,
+ 0x00800020u, 0x00000020u,
+ 0x00a10000u, 0x00002820u,
+ 0x00800000u, 0x00002820u,
+ 0x20800000u, 0x00040008u,
+ 0x00800010u, 0x00000020u,
+ 0x00002020u, 0x00000008u,
+ 0x00002000u, 0x00000000u,
+ 0x00006020u, 0x00000000u,
+ 0x00801000u, 0x00000008u,
+ 0x00800010u, 0x00000008u,
+ 0x21000020u, 0x00040008u,
+ 0x01020020u, 0x00000000u,
+ 0x60800044u, 0x000c000cu,
+ 0x60800000u, 0x000c0008u,
+ 0x00a10000u, 0x00000000u,
+ 0x60800000u, 0x000c0000u,
+ 0x60800004u, 0x000c0008u,
+ 0x60a10044u, 0x000c0004u,
+ 0x60800044u, 0x000c100cu,
+ 0x00a10000u, 0x00000028u,
+ 0x00800010u, 0x00000028u,
+ 0x00801000u, 0x00000028u,
+ 0x00b10000u, 0x00000020u,
+ 0x00804010u, 0x00000020u,
+ 0x00a00000u, 0x00000020u,
+ 0x00000000u, 0x00000020u,
+ 0x008003c4u, 0x00008000u,
+ 0x00a103c4u, 0x00008000u,
+ 0x00800d44u, 0x00000004u,
+ 0x00b10000u, 0x00000028u,
+ 0x00a00000u, 0x00000028u,
+ 0x00a90000u, 0x00000020u,
+ 0x00b90000u, 0x00000020u,
+ 0x00808024u, 0x00000020u,
+ 0x00800000u, 0x00002020u,
+ 0x00800000u, 0x00000200u,
+ 0x08800000u, 0x00000000u,
+ 0x10800000u, 0x00000000u,
+ 0xe0800004u, 0x000c0000u,
+ 0x21008000u, 0x00040000u,
+ 0x00a11000u, 0x00000020u,
+ 0x60808020u, 0x00000000u,
+ 0xe0800004u, 0x000c4000u,
+ 0x60808004u, 0x000c0000u,
+ 0x60800004u, 0x00000000u,
+ 0x00000000u, 0x00000010u,
+ 0x21022020u, 0x00050000u,
+ 0x00800000u, 0x00000100u,
+ 0x00800020u, 0x00002800u,
+ 0x00800020u, 0x00002000u,
+ 0x00800020u, 0x00000100u,
+ 0x24800000u, 0x00040000u,
+ 0x648003c4u, 0x000c8000u,
+ 0x00808020u, 0x00000008u,
+ 0x64800d44u, 0x000c0004u,
+ 0x00800010u, 0x00000100u,
+ 0x61008024u, 0x00040000u,
+ 0x00000020u, 0x00000000u,
+ 0x60c00004u, 0x000c0000u,
+ 0x21400020u, 0x00040000u,
+ 0xa1000020u, 0x00040000u,
+ 0x21000000u, 0x00040000u,
+ 0x00a00000u, 0x00000000u,
+ 0x00b10000u, 0x00000000u,
+ 0x00200000u, 0x00000000u,
+ 0x00800044u, 0x00008000u,
+ 0x00a10044u, 0x00008000u,
+ 0x00930000u, 0x00000400u,
+ 0x00b90000u, 0x00000000u,
+ 0x00a90000u, 0x00000000u,
+ 0x00970020u, 0x00000000u,
+ 0x00b30000u, 0x00000000u,
+ 0x01022020u, 0x00000000u,
};
/* These are the main two-stage UCD tables. The fields in each record are:
script (8 bits), character type (8 bits), grapheme break property (8 bits),
-offset to multichar other cases or zero (8 bits), offset to other case
-or zero (32 bits, signed), script extension (16 bits, signed), and a dummy
-16-bit field to make the whole thing a multiple of 4 bytes. */
-
-const ucd_record PRIV(ucd_records)[] = { /* 11964 bytes, record size 12 */
- { 10, 0, 2, 0, 0, 10, 256, }, /* 0 */
- { 10, 0, 2, 0, 0, 10, 0, }, /* 1 */
- { 10, 0, 1, 0, 0, 10, 0, }, /* 2 */
- { 10, 0, 0, 0, 0, 10, 0, }, /* 3 */
- { 10, 29, 12, 0, 0, 10, 0, }, /* 4 */
- { 10, 21, 12, 0, 0, 10, 0, }, /* 5 */
- { 10, 23, 12, 0, 0, 10, 0, }, /* 6 */
- { 10, 22, 12, 0, 0, 10, 0, }, /* 7 */
- { 10, 18, 12, 0, 0, 10, 0, }, /* 8 */
- { 10, 25, 12, 0, 0, 10, 0, }, /* 9 */
- { 10, 17, 12, 0, 0, 10, 0, }, /* 10 */
- { 10, 13, 12, 0, 0, 10, 0, }, /* 11 */
- { 34, 9, 12, 0, 32, 34, 0, }, /* 12 */
- { 34, 9, 12, 100, 32, 34, 0, }, /* 13 */
- { 34, 9, 12, 1, 32, 34, 0, }, /* 14 */
- { 10, 24, 12, 0, 0, 10, 0, }, /* 15 */
- { 10, 16, 12, 0, 0, 10, 0, }, /* 16 */
- { 34, 5, 12, 0, -32, 34, 0, }, /* 17 */
- { 34, 5, 12, 100, -32, 34, 0, }, /* 18 */
- { 34, 5, 12, 1, -32, 34, 0, }, /* 19 */
- { 10, 26, 12, 0, 0, 10, 0, }, /* 20 */
- { 10, 26, 14, 0, 0, 10, 0, }, /* 21 */
- { 34, 7, 12, 0, 0, 34, 0, }, /* 22 */
- { 10, 20, 12, 0, 0, 10, 0, }, /* 23 */
- { 10, 1, 2, 0, 0, 10, 0, }, /* 24 */
- { 10, 15, 12, 0, 0, 10, 0, }, /* 25 */
- { 10, 5, 12, 26, 775, 10, 0, }, /* 26 */
- { 10, 19, 12, 0, 0, 10, 0, }, /* 27 */
- { 34, 9, 12, 104, 32, 34, 0, }, /* 28 */
- { 34, 5, 12, 0, 7615, 34, 0, }, /* 29 */
- { 34, 5, 12, 104, -32, 34, 0, }, /* 30 */
- { 34, 5, 12, 0, 121, 34, 0, }, /* 31 */
- { 34, 9, 12, 0, 1, 34, 0, }, /* 32 */
- { 34, 5, 12, 0, -1, 34, 0, }, /* 33 */
- { 34, 9, 12, 0, 0, 34, 0, }, /* 34 */
- { 34, 5, 12, 0, 0, 34, 0, }, /* 35 */
- { 34, 9, 12, 0, -121, 34, 0, }, /* 36 */
- { 34, 5, 12, 1, -268, 34, 0, }, /* 37 */
- { 34, 5, 12, 0, 195, 34, 0, }, /* 38 */
- { 34, 9, 12, 0, 210, 34, 0, }, /* 39 */
- { 34, 9, 12, 0, 206, 34, 0, }, /* 40 */
- { 34, 9, 12, 0, 205, 34, 0, }, /* 41 */
- { 34, 9, 12, 0, 79, 34, 0, }, /* 42 */
- { 34, 9, 12, 0, 202, 34, 0, }, /* 43 */
- { 34, 9, 12, 0, 203, 34, 0, }, /* 44 */
- { 34, 9, 12, 0, 207, 34, 0, }, /* 45 */
- { 34, 5, 12, 0, 97, 34, 0, }, /* 46 */
- { 34, 9, 12, 0, 211, 34, 0, }, /* 47 */
- { 34, 9, 12, 0, 209, 34, 0, }, /* 48 */
- { 34, 5, 12, 0, 163, 34, 0, }, /* 49 */
- { 34, 9, 12, 0, 213, 34, 0, }, /* 50 */
- { 34, 5, 12, 0, 130, 34, 0, }, /* 51 */
- { 34, 9, 12, 0, 214, 34, 0, }, /* 52 */
- { 34, 9, 12, 0, 218, 34, 0, }, /* 53 */
- { 34, 9, 12, 0, 217, 34, 0, }, /* 54 */
- { 34, 9, 12, 0, 219, 34, 0, }, /* 55 */
- { 34, 5, 12, 0, 56, 34, 0, }, /* 56 */
- { 34, 9, 12, 5, 2, 34, 0, }, /* 57 */
- { 34, 8, 12, 5, 1, 34, 0, }, /* 58 */
- { 34, 5, 12, 5, -2, 34, 0, }, /* 59 */
- { 34, 9, 12, 9, 2, 34, 0, }, /* 60 */
- { 34, 8, 12, 9, 1, 34, 0, }, /* 61 */
- { 34, 5, 12, 9, -2, 34, 0, }, /* 62 */
- { 34, 9, 12, 13, 2, 34, 0, }, /* 63 */
- { 34, 8, 12, 13, 1, 34, 0, }, /* 64 */
- { 34, 5, 12, 13, -2, 34, 0, }, /* 65 */
- { 34, 5, 12, 0, -79, 34, 0, }, /* 66 */
- { 34, 9, 12, 17, 2, 34, 0, }, /* 67 */
- { 34, 8, 12, 17, 1, 34, 0, }, /* 68 */
- { 34, 5, 12, 17, -2, 34, 0, }, /* 69 */
- { 34, 9, 12, 0, -97, 34, 0, }, /* 70 */
- { 34, 9, 12, 0, -56, 34, 0, }, /* 71 */
- { 34, 9, 12, 0, -130, 34, 0, }, /* 72 */
- { 34, 9, 12, 0, 10795, 34, 0, }, /* 73 */
- { 34, 9, 12, 0, -163, 34, 0, }, /* 74 */
- { 34, 9, 12, 0, 10792, 34, 0, }, /* 75 */
- { 34, 5, 12, 0, 10815, 34, 0, }, /* 76 */
- { 34, 9, 12, 0, -195, 34, 0, }, /* 77 */
- { 34, 9, 12, 0, 69, 34, 0, }, /* 78 */
- { 34, 9, 12, 0, 71, 34, 0, }, /* 79 */
- { 34, 5, 12, 0, 10783, 34, 0, }, /* 80 */
- { 34, 5, 12, 0, 10780, 34, 0, }, /* 81 */
- { 34, 5, 12, 0, 10782, 34, 0, }, /* 82 */
- { 34, 5, 12, 0, -210, 34, 0, }, /* 83 */
- { 34, 5, 12, 0, -206, 34, 0, }, /* 84 */
- { 34, 5, 12, 0, -205, 34, 0, }, /* 85 */
- { 34, 5, 12, 0, -202, 34, 0, }, /* 86 */
- { 34, 5, 12, 0, -203, 34, 0, }, /* 87 */
- { 34, 5, 12, 0, 42319, 34, 0, }, /* 88 */
- { 34, 5, 12, 0, 42315, 34, 0, }, /* 89 */
- { 34, 5, 12, 0, -207, 34, 0, }, /* 90 */
- { 34, 5, 12, 0, 42280, 34, 0, }, /* 91 */
- { 34, 5, 12, 0, 42308, 34, 0, }, /* 92 */
- { 34, 5, 12, 0, -209, 34, 0, }, /* 93 */
- { 34, 5, 12, 0, -211, 34, 0, }, /* 94 */
- { 34, 5, 12, 0, 10743, 34, 0, }, /* 95 */
- { 34, 5, 12, 0, 42305, 34, 0, }, /* 96 */
- { 34, 5, 12, 0, 10749, 34, 0, }, /* 97 */
- { 34, 5, 12, 0, -213, 34, 0, }, /* 98 */
- { 34, 5, 12, 0, -214, 34, 0, }, /* 99 */
- { 34, 5, 12, 0, 10727, 34, 0, }, /* 100 */
- { 34, 5, 12, 0, -218, 34, 0, }, /* 101 */
- { 34, 5, 12, 0, 42307, 34, 0, }, /* 102 */
- { 34, 5, 12, 0, 42282, 34, 0, }, /* 103 */
- { 34, 5, 12, 0, -69, 34, 0, }, /* 104 */
- { 34, 5, 12, 0, -217, 34, 0, }, /* 105 */
- { 34, 5, 12, 0, -71, 34, 0, }, /* 106 */
- { 34, 5, 12, 0, -219, 34, 0, }, /* 107 */
- { 34, 5, 12, 0, 42261, 34, 0, }, /* 108 */
- { 34, 5, 12, 0, 42258, 34, 0, }, /* 109 */
- { 34, 6, 12, 0, 0, 34, 0, }, /* 110 */
- { 10, 6, 12, 0, 0, 10, 0, }, /* 111 */
- { 4, 24, 12, 0, 0, 4, 0, }, /* 112 */
- { 28, 12, 3, 0, 0, 28, 0, }, /* 113 */
- { 28, 12, 3, 0, 0, 20, 0, }, /* 114 */
- { 28, 12, 3, 21, 116, 20, 0, }, /* 115 */
- { 28, 12, 3, 0, 0, 34, 0, }, /* 116 */
- { 20, 9, 12, 0, 1, 20, 0, }, /* 117 */
- { 20, 5, 12, 0, -1, 20, 0, }, /* 118 */
- { 20, 24, 12, 0, 0, 20, 0, }, /* 119 */
- { 0, 2, 12, 0, 0, 0, 0, }, /* 120 */
- { 20, 6, 12, 0, 0, 20, 0, }, /* 121 */
- { 20, 5, 12, 0, 130, 20, 0, }, /* 122 */
- { 20, 9, 12, 0, 116, 20, 0, }, /* 123 */
- { 20, 9, 12, 0, 38, 20, 0, }, /* 124 */
- { 20, 9, 12, 0, 37, 20, 0, }, /* 125 */
- { 20, 9, 12, 0, 64, 20, 0, }, /* 126 */
- { 20, 9, 12, 0, 63, 20, 0, }, /* 127 */
- { 20, 5, 12, 0, 0, 20, 0, }, /* 128 */
- { 20, 9, 12, 0, 32, 20, 0, }, /* 129 */
- { 20, 9, 12, 34, 32, 20, 0, }, /* 130 */
- { 20, 9, 12, 59, 32, 20, 0, }, /* 131 */
- { 20, 9, 12, 38, 32, 20, 0, }, /* 132 */
- { 20, 9, 12, 21, 32, 20, 0, }, /* 133 */
- { 20, 9, 12, 51, 32, 20, 0, }, /* 134 */
- { 20, 9, 12, 26, 32, 20, 0, }, /* 135 */
- { 20, 9, 12, 47, 32, 20, 0, }, /* 136 */
- { 20, 9, 12, 55, 32, 20, 0, }, /* 137 */
- { 20, 9, 12, 30, 32, 20, 0, }, /* 138 */
- { 20, 9, 12, 43, 32, 20, 0, }, /* 139 */
- { 20, 9, 12, 96, 32, 20, 0, }, /* 140 */
- { 20, 5, 12, 0, -38, 20, 0, }, /* 141 */
- { 20, 5, 12, 0, -37, 20, 0, }, /* 142 */
- { 20, 5, 12, 0, -32, 20, 0, }, /* 143 */
- { 20, 5, 12, 34, -32, 20, 0, }, /* 144 */
- { 20, 5, 12, 59, -32, 20, 0, }, /* 145 */
- { 20, 5, 12, 38, -32, 20, 0, }, /* 146 */
- { 20, 5, 12, 21, -116, 20, 0, }, /* 147 */
- { 20, 5, 12, 51, -32, 20, 0, }, /* 148 */
- { 20, 5, 12, 26, -775, 20, 0, }, /* 149 */
- { 20, 5, 12, 47, -32, 20, 0, }, /* 150 */
- { 20, 5, 12, 55, -32, 20, 0, }, /* 151 */
- { 20, 5, 12, 30, 1, 20, 0, }, /* 152 */
- { 20, 5, 12, 30, -32, 20, 0, }, /* 153 */
- { 20, 5, 12, 43, -32, 20, 0, }, /* 154 */
- { 20, 5, 12, 96, -32, 20, 0, }, /* 155 */
- { 20, 5, 12, 0, -64, 20, 0, }, /* 156 */
- { 20, 5, 12, 0, -63, 20, 0, }, /* 157 */
- { 20, 9, 12, 0, 8, 20, 0, }, /* 158 */
- { 20, 5, 12, 34, -30, 20, 0, }, /* 159 */
- { 20, 5, 12, 38, -25, 20, 0, }, /* 160 */
- { 20, 9, 12, 0, 0, 20, 0, }, /* 161 */
- { 20, 5, 12, 43, -15, 20, 0, }, /* 162 */
- { 20, 5, 12, 47, -22, 20, 0, }, /* 163 */
- { 20, 5, 12, 0, -8, 20, 0, }, /* 164 */
- { 11, 9, 12, 0, 1, 11, 0, }, /* 165 */
- { 11, 5, 12, 0, -1, 11, 0, }, /* 166 */
- { 20, 5, 12, 51, -54, 20, 0, }, /* 167 */
- { 20, 5, 12, 55, -48, 20, 0, }, /* 168 */
- { 20, 5, 12, 0, 7, 20, 0, }, /* 169 */
- { 20, 5, 12, 0, -116, 20, 0, }, /* 170 */
- { 20, 9, 12, 38, -60, 20, 0, }, /* 171 */
- { 20, 5, 12, 59, -64, 20, 0, }, /* 172 */
- { 20, 25, 12, 0, 0, 20, 0, }, /* 173 */
- { 20, 9, 12, 0, -7, 20, 0, }, /* 174 */
- { 20, 9, 12, 0, -130, 20, 0, }, /* 175 */
- { 13, 9, 12, 0, 80, 13, 0, }, /* 176 */
- { 13, 9, 12, 0, 32, 13, 0, }, /* 177 */
- { 13, 9, 12, 63, 32, 13, 0, }, /* 178 */
- { 13, 9, 12, 67, 32, 13, 0, }, /* 179 */
- { 13, 9, 12, 71, 32, 13, 0, }, /* 180 */
- { 13, 9, 12, 75, 32, 13, 0, }, /* 181 */
- { 13, 9, 12, 79, 32, 13, 0, }, /* 182 */
- { 13, 9, 12, 84, 32, 13, 0, }, /* 183 */
- { 13, 5, 12, 0, -32, 13, 0, }, /* 184 */
- { 13, 5, 12, 63, -32, 13, 0, }, /* 185 */
- { 13, 5, 12, 67, -32, 13, 0, }, /* 186 */
- { 13, 5, 12, 71, -32, 13, 0, }, /* 187 */
- { 13, 5, 12, 75, -32, 13, 0, }, /* 188 */
- { 13, 5, 12, 79, -32, 13, 0, }, /* 189 */
- { 13, 5, 12, 84, -32, 13, 0, }, /* 190 */
- { 13, 5, 12, 0, -80, 13, 0, }, /* 191 */
- { 13, 9, 12, 0, 1, 13, 0, }, /* 192 */
- { 13, 5, 12, 0, -1, 13, 0, }, /* 193 */
- { 13, 9, 12, 88, 1, 13, 0, }, /* 194 */
- { 13, 5, 12, 88, -1, 13, 0, }, /* 195 */
- { 13, 26, 12, 0, 0, 13, 0, }, /* 196 */
- { 13, 12, 3, 0, 0, -34, 0, }, /* 197 */
- { 13, 12, 3, 0, 0, -28, 0, }, /* 198 */
- { 28, 12, 3, 0, 0, -31, 0, }, /* 199 */
- { 13, 11, 3, 0, 0, 13, 0, }, /* 200 */
- { 13, 9, 12, 0, 15, 13, 0, }, /* 201 */
- { 13, 5, 12, 0, -15, 13, 0, }, /* 202 */
- { 2, 9, 12, 0, 48, 2, 0, }, /* 203 */
- { 2, 6, 12, 0, 0, 2, 0, }, /* 204 */
- { 2, 21, 12, 0, 0, 2, 0, }, /* 205 */
- { 2, 5, 12, 0, 0, 2, 0, }, /* 206 */
- { 2, 5, 12, 0, -48, 2, 0, }, /* 207 */
- { 2, 17, 12, 0, 0, 2, 0, }, /* 208 */
- { 2, 26, 12, 0, 0, 2, 0, }, /* 209 */
- { 2, 23, 12, 0, 0, 2, 0, }, /* 210 */
- { 26, 12, 3, 0, 0, 26, 0, }, /* 211 */
- { 26, 17, 12, 0, 0, 26, 0, }, /* 212 */
- { 26, 21, 12, 0, 0, 26, 0, }, /* 213 */
- { 26, 7, 12, 0, 0, 26, 0, }, /* 214 */
- { 1, 1, 4, 0, 0, 1, 0, }, /* 215 */
- { 10, 1, 4, 0, 0, 10, 0, }, /* 216 */
- { 1, 25, 12, 0, 0, 1, 0, }, /* 217 */
- { 1, 21, 12, 0, 0, 1, 0, }, /* 218 */
- { 1, 23, 12, 0, 0, 1, 0, }, /* 219 */
- { 10, 21, 12, 0, 0, -143, 0, }, /* 220 */
- { 1, 26, 12, 0, 0, 1, 0, }, /* 221 */
- { 1, 12, 3, 0, 0, 1, 0, }, /* 222 */
- { 1, 1, 2, 0, 0, -82, 0, }, /* 223 */
- { 10, 21, 12, 0, 0, -164, 0, }, /* 224 */
- { 1, 7, 12, 0, 0, 1, 0, }, /* 225 */
- { 10, 6, 12, 0, 0, -181, 0, }, /* 226 */
- { 28, 12, 3, 0, 0, -10, 0, }, /* 227 */
- { 1, 13, 12, 0, 0, -86, 0, }, /* 228 */
- { 1, 21, 12, 0, 0, -4, 0, }, /* 229 */
- { 1, 6, 12, 0, 0, 1, 0, }, /* 230 */
- { 1, 13, 12, 0, 0, 1, 0, }, /* 231 */
- { 50, 21, 12, 0, 0, 50, 0, }, /* 232 */
- { 50, 1, 4, 0, 0, 50, 0, }, /* 233 */
- { 50, 7, 12, 0, 0, 50, 0, }, /* 234 */
- { 50, 12, 3, 0, 0, 50, 0, }, /* 235 */
- { 56, 7, 12, 0, 0, 56, 0, }, /* 236 */
- { 56, 12, 3, 0, 0, 56, 0, }, /* 237 */
- { 64, 13, 12, 0, 0, 64, 0, }, /* 238 */
- { 64, 7, 12, 0, 0, 64, 0, }, /* 239 */
- { 64, 12, 3, 0, 0, 64, 0, }, /* 240 */
- { 64, 6, 12, 0, 0, 64, 0, }, /* 241 */
- { 64, 26, 12, 0, 0, 64, 0, }, /* 242 */
- { 64, 21, 12, 0, 0, 64, 0, }, /* 243 */
- { 64, 23, 12, 0, 0, 64, 0, }, /* 244 */
- { 90, 7, 12, 0, 0, 90, 0, }, /* 245 */
- { 90, 12, 3, 0, 0, 90, 0, }, /* 246 */
- { 90, 6, 12, 0, 0, 90, 0, }, /* 247 */
- { 90, 21, 12, 0, 0, 90, 0, }, /* 248 */
- { 95, 7, 12, 0, 0, 95, 0, }, /* 249 */
- { 95, 12, 3, 0, 0, 95, 0, }, /* 250 */
- { 95, 21, 12, 0, 0, 95, 0, }, /* 251 */
- { 1, 24, 12, 0, 0, 1, 0, }, /* 252 */
- { 15, 12, 3, 0, 0, 15, 0, }, /* 253 */
- { 15, 10, 5, 0, 0, 15, 0, }, /* 254 */
- { 15, 7, 12, 0, 0, 15, 0, }, /* 255 */
- { 28, 12, 3, 0, 0, -216, 0, }, /* 256 */
- { 28, 12, 3, 0, 0, -203, 0, }, /* 257 */
- { 10, 21, 12, 0, 0, -259, 0, }, /* 258 */
- { 10, 21, 12, 0, 0, -280, 0, }, /* 259 */
- { 15, 13, 12, 0, 0, -132, 0, }, /* 260 */
- { 15, 21, 12, 0, 0, 15, 0, }, /* 261 */
- { 15, 6, 12, 0, 0, 15, 0, }, /* 262 */
- { 3, 7, 12, 0, 0, 3, 0, }, /* 263 */
- { 3, 12, 3, 0, 0, 3, 0, }, /* 264 */
- { 3, 10, 5, 0, 0, 3, 0, }, /* 265 */
- { 3, 10, 3, 0, 0, 3, 0, }, /* 266 */
- { 3, 13, 12, 0, 0, -90, 0, }, /* 267 */
- { 3, 23, 12, 0, 0, 3, 0, }, /* 268 */
- { 3, 15, 12, 0, 0, 3, 0, }, /* 269 */
- { 3, 26, 12, 0, 0, 3, 0, }, /* 270 */
- { 3, 21, 12, 0, 0, 3, 0, }, /* 271 */
- { 22, 12, 3, 0, 0, 22, 0, }, /* 272 */
- { 22, 10, 5, 0, 0, 22, 0, }, /* 273 */
- { 22, 7, 12, 0, 0, 22, 0, }, /* 274 */
- { 22, 13, 12, 0, 0, -61, 0, }, /* 275 */
- { 22, 21, 12, 0, 0, 22, 0, }, /* 276 */
- { 21, 12, 3, 0, 0, 21, 0, }, /* 277 */
- { 21, 10, 5, 0, 0, 21, 0, }, /* 278 */
- { 21, 7, 12, 0, 0, 21, 0, }, /* 279 */
- { 21, 13, 12, 0, 0, -58, 0, }, /* 280 */
- { 21, 21, 12, 0, 0, 21, 0, }, /* 281 */
- { 21, 23, 12, 0, 0, 21, 0, }, /* 282 */
- { 44, 12, 3, 0, 0, 44, 0, }, /* 283 */
- { 44, 10, 5, 0, 0, 44, 0, }, /* 284 */
- { 44, 7, 12, 0, 0, 44, 0, }, /* 285 */
- { 44, 10, 3, 0, 0, 44, 0, }, /* 286 */
- { 44, 13, 12, 0, 0, 44, 0, }, /* 287 */
- { 44, 26, 12, 0, 0, 44, 0, }, /* 288 */
- { 44, 15, 12, 0, 0, 44, 0, }, /* 289 */
- { 54, 12, 3, 0, 0, 54, 0, }, /* 290 */
- { 54, 7, 12, 0, 0, 54, 0, }, /* 291 */
- { 54, 10, 3, 0, 0, 54, 0, }, /* 292 */
- { 54, 10, 5, 0, 0, 54, 0, }, /* 293 */
- { 54, 13, 12, 0, 0, -55, 0, }, /* 294 */
- { 54, 15, 12, 0, 0, -55, 0, }, /* 295 */
- { 54, 26, 12, 0, 0, -55, 0, }, /* 296 */
- { 54, 26, 12, 0, 0, 54, 0, }, /* 297 */
- { 54, 23, 12, 0, 0, 54, 0, }, /* 298 */
- { 55, 12, 3, 0, 0, 55, 0, }, /* 299 */
- { 55, 10, 5, 0, 0, 55, 0, }, /* 300 */
- { 55, 7, 12, 0, 0, 55, 0, }, /* 301 */
- { 55, 13, 12, 0, 0, 55, 0, }, /* 302 */
- { 55, 21, 12, 0, 0, 55, 0, }, /* 303 */
- { 55, 15, 12, 0, 0, 55, 0, }, /* 304 */
- { 55, 26, 12, 0, 0, 55, 0, }, /* 305 */
- { 29, 7, 12, 0, 0, 29, 0, }, /* 306 */
- { 29, 12, 3, 0, 0, 29, 0, }, /* 307 */
- { 29, 10, 5, 0, 0, 29, 0, }, /* 308 */
- { 29, 21, 12, 0, 0, 29, 0, }, /* 309 */
- { 29, 10, 3, 0, 0, 29, 0, }, /* 310 */
- { 29, 13, 12, 0, 0, -70, 0, }, /* 311 */
- { 37, 12, 3, 0, 0, 37, 0, }, /* 312 */
- { 37, 10, 5, 0, 0, 37, 0, }, /* 313 */
- { 37, 7, 12, 0, 0, 37, 0, }, /* 314 */
- { 37, 10, 3, 0, 0, 37, 0, }, /* 315 */
- { 37, 7, 4, 0, 0, 37, 0, }, /* 316 */
- { 37, 26, 12, 0, 0, 37, 0, }, /* 317 */
- { 37, 15, 12, 0, 0, 37, 0, }, /* 318 */
- { 37, 13, 12, 0, 0, 37, 0, }, /* 319 */
- { 48, 12, 3, 0, 0, 48, 0, }, /* 320 */
- { 48, 10, 5, 0, 0, 48, 0, }, /* 321 */
- { 48, 7, 12, 0, 0, 48, 0, }, /* 322 */
- { 48, 10, 3, 0, 0, 48, 0, }, /* 323 */
- { 48, 13, 12, 0, 0, 48, 0, }, /* 324 */
- { 48, 21, 12, 0, 0, 48, 0, }, /* 325 */
- { 57, 7, 12, 0, 0, 57, 0, }, /* 326 */
- { 57, 12, 3, 0, 0, 57, 0, }, /* 327 */
- { 57, 7, 5, 0, 0, 57, 0, }, /* 328 */
- { 57, 6, 12, 0, 0, 57, 0, }, /* 329 */
- { 57, 21, 12, 0, 0, 57, 0, }, /* 330 */
- { 57, 13, 12, 0, 0, 57, 0, }, /* 331 */
- { 33, 7, 12, 0, 0, 33, 0, }, /* 332 */
- { 33, 12, 3, 0, 0, 33, 0, }, /* 333 */
- { 33, 7, 5, 0, 0, 33, 0, }, /* 334 */
- { 33, 6, 12, 0, 0, 33, 0, }, /* 335 */
- { 33, 13, 12, 0, 0, 33, 0, }, /* 336 */
- { 58, 7, 12, 0, 0, 58, 0, }, /* 337 */
- { 58, 26, 12, 0, 0, 58, 0, }, /* 338 */
- { 58, 21, 12, 0, 0, 58, 0, }, /* 339 */
- { 58, 12, 3, 0, 0, 58, 0, }, /* 340 */
- { 58, 13, 12, 0, 0, 58, 0, }, /* 341 */
- { 58, 15, 12, 0, 0, 58, 0, }, /* 342 */
- { 58, 22, 12, 0, 0, 58, 0, }, /* 343 */
- { 58, 18, 12, 0, 0, 58, 0, }, /* 344 */
- { 58, 10, 5, 0, 0, 58, 0, }, /* 345 */
- { 39, 7, 12, 0, 0, 39, 0, }, /* 346 */
- { 39, 10, 12, 0, 0, 39, 0, }, /* 347 */
- { 39, 12, 3, 0, 0, 39, 0, }, /* 348 */
- { 39, 10, 5, 0, 0, 39, 0, }, /* 349 */
- { 39, 13, 12, 0, 0, -94, 0, }, /* 350 */
- { 39, 21, 12, 0, 0, 39, 0, }, /* 351 */
- { 39, 13, 12, 0, 0, 39, 0, }, /* 352 */
- { 39, 26, 12, 0, 0, 39, 0, }, /* 353 */
- { 17, 9, 12, 0, 7264, 17, 0, }, /* 354 */
- { 17, 5, 12, 0, 3008, 17, 0, }, /* 355 */
- { 10, 21, 12, 0, 0, -52, 0, }, /* 356 */
- { 17, 6, 12, 0, 0, 17, 0, }, /* 357 */
- { 24, 7, 6, 0, 0, 24, 0, }, /* 358 */
- { 24, 7, 7, 0, 0, 24, 0, }, /* 359 */
- { 24, 7, 8, 0, 0, 24, 0, }, /* 360 */
- { 16, 7, 12, 0, 0, 16, 0, }, /* 361 */
- { 16, 12, 3, 0, 0, 16, 0, }, /* 362 */
- { 16, 21, 12, 0, 0, 16, 0, }, /* 363 */
- { 16, 15, 12, 0, 0, 16, 0, }, /* 364 */
- { 16, 26, 12, 0, 0, 16, 0, }, /* 365 */
- { 9, 9, 12, 0, 38864, 9, 0, }, /* 366 */
- { 9, 9, 12, 0, 8, 9, 0, }, /* 367 */
- { 9, 5, 12, 0, -8, 9, 0, }, /* 368 */
- { 8, 17, 12, 0, 0, 8, 0, }, /* 369 */
- { 8, 7, 12, 0, 0, 8, 0, }, /* 370 */
- { 8, 26, 12, 0, 0, 8, 0, }, /* 371 */
- { 8, 21, 12, 0, 0, 8, 0, }, /* 372 */
- { 41, 29, 12, 0, 0, 41, 0, }, /* 373 */
- { 41, 7, 12, 0, 0, 41, 0, }, /* 374 */
- { 41, 22, 12, 0, 0, 41, 0, }, /* 375 */
- { 41, 18, 12, 0, 0, 41, 0, }, /* 376 */
- { 46, 7, 12, 0, 0, 46, 0, }, /* 377 */
- { 46, 14, 12, 0, 0, 46, 0, }, /* 378 */
- { 51, 7, 12, 0, 0, 51, 0, }, /* 379 */
- { 51, 12, 3, 0, 0, 51, 0, }, /* 380 */
- { 51, 10, 5, 0, 0, 51, 0, }, /* 381 */
- { 25, 7, 12, 0, 0, 25, 0, }, /* 382 */
- { 25, 12, 3, 0, 0, 25, 0, }, /* 383 */
- { 25, 10, 5, 0, 0, 25, 0, }, /* 384 */
- { 10, 21, 12, 0, 0, -127, 0, }, /* 385 */
- { 7, 7, 12, 0, 0, 7, 0, }, /* 386 */
- { 7, 12, 3, 0, 0, 7, 0, }, /* 387 */
- { 52, 7, 12, 0, 0, 52, 0, }, /* 388 */
- { 52, 12, 3, 0, 0, 52, 0, }, /* 389 */
- { 32, 7, 12, 0, 0, 32, 0, }, /* 390 */
- { 32, 12, 3, 0, 0, 32, 0, }, /* 391 */
- { 32, 10, 5, 0, 0, 32, 0, }, /* 392 */
- { 32, 21, 12, 0, 0, 32, 0, }, /* 393 */
- { 32, 6, 12, 0, 0, 32, 0, }, /* 394 */
- { 32, 23, 12, 0, 0, 32, 0, }, /* 395 */
- { 32, 13, 12, 0, 0, 32, 0, }, /* 396 */
- { 32, 15, 12, 0, 0, 32, 0, }, /* 397 */
- { 38, 21, 12, 0, 0, 38, 0, }, /* 398 */
- { 10, 21, 12, 0, 0, -79, 0, }, /* 399 */
- { 38, 17, 12, 0, 0, 38, 0, }, /* 400 */
- { 38, 12, 3, 0, 0, 38, 0, }, /* 401 */
- { 38, 1, 2, 0, 0, 38, 0, }, /* 402 */
- { 38, 13, 12, 0, 0, 38, 0, }, /* 403 */
- { 38, 7, 12, 0, 0, 38, 0, }, /* 404 */
- { 38, 6, 12, 0, 0, 38, 0, }, /* 405 */
- { 35, 7, 12, 0, 0, 35, 0, }, /* 406 */
- { 35, 12, 3, 0, 0, 35, 0, }, /* 407 */
- { 35, 10, 5, 0, 0, 35, 0, }, /* 408 */
- { 35, 26, 12, 0, 0, 35, 0, }, /* 409 */
- { 35, 21, 12, 0, 0, 35, 0, }, /* 410 */
- { 35, 13, 12, 0, 0, 35, 0, }, /* 411 */
- { 53, 7, 12, 0, 0, 53, 0, }, /* 412 */
- { 40, 7, 12, 0, 0, 40, 0, }, /* 413 */
- { 40, 13, 12, 0, 0, 40, 0, }, /* 414 */
- { 40, 15, 12, 0, 0, 40, 0, }, /* 415 */
- { 40, 26, 12, 0, 0, 40, 0, }, /* 416 */
- { 32, 26, 12, 0, 0, 32, 0, }, /* 417 */
- { 6, 7, 12, 0, 0, 6, 0, }, /* 418 */
- { 6, 12, 3, 0, 0, 6, 0, }, /* 419 */
- { 6, 10, 5, 0, 0, 6, 0, }, /* 420 */
- { 6, 21, 12, 0, 0, 6, 0, }, /* 421 */
- { 91, 7, 12, 0, 0, 91, 0, }, /* 422 */
- { 91, 10, 5, 0, 0, 91, 0, }, /* 423 */
- { 91, 12, 3, 0, 0, 91, 0, }, /* 424 */
- { 91, 10, 12, 0, 0, 91, 0, }, /* 425 */
- { 91, 13, 12, 0, 0, 91, 0, }, /* 426 */
- { 91, 21, 12, 0, 0, 91, 0, }, /* 427 */
- { 91, 6, 12, 0, 0, 91, 0, }, /* 428 */
- { 28, 11, 3, 0, 0, 28, 0, }, /* 429 */
- { 62, 12, 3, 0, 0, 62, 0, }, /* 430 */
- { 62, 10, 5, 0, 0, 62, 0, }, /* 431 */
- { 62, 7, 12, 0, 0, 62, 0, }, /* 432 */
- { 62, 10, 3, 0, 0, 62, 0, }, /* 433 */
- { 62, 13, 12, 0, 0, 62, 0, }, /* 434 */
- { 62, 21, 12, 0, 0, 62, 0, }, /* 435 */
- { 62, 26, 12, 0, 0, 62, 0, }, /* 436 */
- { 76, 12, 3, 0, 0, 76, 0, }, /* 437 */
- { 76, 10, 5, 0, 0, 76, 0, }, /* 438 */
- { 76, 7, 12, 0, 0, 76, 0, }, /* 439 */
- { 76, 13, 12, 0, 0, 76, 0, }, /* 440 */
- { 93, 7, 12, 0, 0, 93, 0, }, /* 441 */
- { 93, 12, 3, 0, 0, 93, 0, }, /* 442 */
- { 93, 10, 5, 0, 0, 93, 0, }, /* 443 */
- { 93, 21, 12, 0, 0, 93, 0, }, /* 444 */
- { 70, 7, 12, 0, 0, 70, 0, }, /* 445 */
- { 70, 10, 5, 0, 0, 70, 0, }, /* 446 */
- { 70, 12, 3, 0, 0, 70, 0, }, /* 447 */
- { 70, 21, 12, 0, 0, 70, 0, }, /* 448 */
- { 70, 13, 12, 0, 0, 70, 0, }, /* 449 */
- { 73, 13, 12, 0, 0, 73, 0, }, /* 450 */
- { 73, 7, 12, 0, 0, 73, 0, }, /* 451 */
- { 73, 6, 12, 0, 0, 73, 0, }, /* 452 */
- { 73, 21, 12, 0, 0, 73, 0, }, /* 453 */
- { 13, 5, 12, 63, -6222, 13, 0, }, /* 454 */
- { 13, 5, 12, 67, -6221, 13, 0, }, /* 455 */
- { 13, 5, 12, 71, -6212, 13, 0, }, /* 456 */
- { 13, 5, 12, 75, -6210, 13, 0, }, /* 457 */
- { 13, 5, 12, 79, -6210, 13, 0, }, /* 458 */
- { 13, 5, 12, 79, -6211, 13, 0, }, /* 459 */
- { 13, 5, 12, 84, -6204, 13, 0, }, /* 460 */
- { 13, 5, 12, 88, -6180, 13, 0, }, /* 461 */
- { 13, 5, 12, 108, 35267, 13, 0, }, /* 462 */
- { 17, 9, 12, 0, -3008, 17, 0, }, /* 463 */
- { 76, 21, 12, 0, 0, 76, 0, }, /* 464 */
- { 28, 12, 3, 0, 0, -122, 0, }, /* 465 */
- { 28, 12, 3, 0, 0, 15, 0, }, /* 466 */
- { 10, 21, 12, 0, 0, -40, 0, }, /* 467 */
- { 28, 12, 3, 0, 0, -16, 0, }, /* 468 */
- { 28, 12, 3, 0, 0, -46, 0, }, /* 469 */
- { 28, 12, 3, 0, 0, -157, 0, }, /* 470 */
- { 10, 10, 5, 0, 0, -16, 0, }, /* 471 */
- { 10, 7, 12, 0, 0, -43, 0, }, /* 472 */
- { 10, 7, 12, 0, 0, -16, 0, }, /* 473 */
- { 10, 7, 12, 0, 0, 15, 0, }, /* 474 */
- { 10, 7, 12, 0, 0, -172, 0, }, /* 475 */
- { 10, 7, 12, 0, 0, -40, 0, }, /* 476 */
- { 28, 12, 3, 0, 0, -106, 0, }, /* 477 */
- { 10, 10, 5, 0, 0, 3, 0, }, /* 478 */
- { 28, 12, 3, 0, 0, -40, 0, }, /* 479 */
- { 10, 7, 12, 0, 0, 150, 0, }, /* 480 */
- { 13, 5, 12, 0, 0, 13, 0, }, /* 481 */
- { 13, 6, 12, 0, 0, 13, 0, }, /* 482 */
- { 34, 5, 12, 0, 35332, 34, 0, }, /* 483 */
- { 34, 5, 12, 0, 3814, 34, 0, }, /* 484 */
- { 34, 5, 12, 0, 35384, 34, 0, }, /* 485 */
- { 28, 12, 3, 0, 0, -37, 0, }, /* 486 */
- { 28, 12, 3, 0, 0, 50, 0, }, /* 487 */
- { 34, 9, 12, 92, 1, 34, 0, }, /* 488 */
- { 34, 5, 12, 92, -1, 34, 0, }, /* 489 */
- { 34, 5, 12, 92, -58, 34, 0, }, /* 490 */
- { 34, 9, 12, 0, -7615, 34, 0, }, /* 491 */
- { 20, 5, 12, 0, 8, 20, 0, }, /* 492 */
- { 20, 9, 12, 0, -8, 20, 0, }, /* 493 */
- { 20, 5, 12, 0, 74, 20, 0, }, /* 494 */
- { 20, 5, 12, 0, 86, 20, 0, }, /* 495 */
- { 20, 5, 12, 0, 100, 20, 0, }, /* 496 */
- { 20, 5, 12, 0, 128, 20, 0, }, /* 497 */
- { 20, 5, 12, 0, 112, 20, 0, }, /* 498 */
- { 20, 5, 12, 0, 126, 20, 0, }, /* 499 */
- { 20, 8, 12, 0, -8, 20, 0, }, /* 500 */
- { 20, 5, 12, 0, 9, 20, 0, }, /* 501 */
- { 20, 9, 12, 0, -74, 20, 0, }, /* 502 */
- { 20, 8, 12, 0, -9, 20, 0, }, /* 503 */
- { 20, 5, 12, 21, -7173, 20, 0, }, /* 504 */
- { 20, 9, 12, 0, -86, 20, 0, }, /* 505 */
- { 20, 9, 12, 0, -100, 20, 0, }, /* 506 */
- { 20, 9, 12, 0, -112, 20, 0, }, /* 507 */
- { 20, 9, 12, 0, -128, 20, 0, }, /* 508 */
- { 20, 9, 12, 0, -126, 20, 0, }, /* 509 */
- { 28, 1, 3, 0, 0, 28, 0, }, /* 510 */
- { 28, 1, 13, 0, 0, 28, 0, }, /* 511 */
- { 10, 27, 2, 0, 0, 10, 0, }, /* 512 */
- { 10, 28, 2, 0, 0, 10, 0, }, /* 513 */
- { 10, 29, 12, 0, 0, -73, 0, }, /* 514 */
- { 10, 21, 14, 0, 0, 10, 0, }, /* 515 */
- { 0, 2, 2, 0, 0, 0, 0, }, /* 516 */
- { 28, 12, 3, 0, 0, -110, 0, }, /* 517 */
- { 10, 9, 12, 0, 0, 10, 0, }, /* 518 */
- { 10, 5, 12, 0, 0, 10, 0, }, /* 519 */
- { 20, 9, 12, 96, -7517, 20, 0, }, /* 520 */
- { 34, 9, 12, 100, -8383, 34, 0, }, /* 521 */
- { 34, 9, 12, 104, -8262, 34, 0, }, /* 522 */
- { 34, 9, 12, 0, 28, 34, 0, }, /* 523 */
- { 10, 7, 12, 0, 0, 10, 0, }, /* 524 */
- { 10, 5, 14, 0, 0, 10, 0, }, /* 525 */
- { 34, 5, 12, 0, -28, 34, 0, }, /* 526 */
- { 34, 14, 12, 0, 16, 34, 0, }, /* 527 */
- { 34, 14, 12, 0, -16, 34, 0, }, /* 528 */
- { 34, 14, 12, 0, 0, 34, 0, }, /* 529 */
- { 10, 25, 14, 0, 0, 10, 0, }, /* 530 */
- { 10, 26, 12, 0, 26, 10, 0, }, /* 531 */
- { 10, 26, 14, 0, 26, 10, 0, }, /* 532 */
- { 10, 26, 12, 0, -26, 10, 0, }, /* 533 */
- { 5, 26, 12, 0, 0, 5, 0, }, /* 534 */
- { 18, 9, 12, 0, 48, 18, 0, }, /* 535 */
- { 18, 5, 12, 0, -48, 18, 0, }, /* 536 */
- { 34, 9, 12, 0, -10743, 34, 0, }, /* 537 */
- { 34, 9, 12, 0, -3814, 34, 0, }, /* 538 */
- { 34, 9, 12, 0, -10727, 34, 0, }, /* 539 */
- { 34, 5, 12, 0, -10795, 34, 0, }, /* 540 */
- { 34, 5, 12, 0, -10792, 34, 0, }, /* 541 */
- { 34, 9, 12, 0, -10780, 34, 0, }, /* 542 */
- { 34, 9, 12, 0, -10749, 34, 0, }, /* 543 */
- { 34, 9, 12, 0, -10783, 34, 0, }, /* 544 */
- { 34, 9, 12, 0, -10782, 34, 0, }, /* 545 */
- { 34, 9, 12, 0, -10815, 34, 0, }, /* 546 */
- { 11, 5, 12, 0, 0, 11, 0, }, /* 547 */
- { 11, 26, 12, 0, 0, 11, 0, }, /* 548 */
- { 11, 12, 3, 0, 0, 11, 0, }, /* 549 */
- { 11, 21, 12, 0, 0, 11, 0, }, /* 550 */
- { 11, 15, 12, 0, 0, 11, 0, }, /* 551 */
- { 17, 5, 12, 0, -7264, 17, 0, }, /* 552 */
- { 59, 7, 12, 0, 0, 59, 0, }, /* 553 */
- { 59, 6, 12, 0, 0, 59, 0, }, /* 554 */
- { 59, 21, 12, 0, 0, 59, 0, }, /* 555 */
- { 59, 12, 3, 0, 0, 59, 0, }, /* 556 */
- { 13, 12, 3, 0, 0, 13, 0, }, /* 557 */
- { 10, 21, 12, 0, 0, -28, 0, }, /* 558 */
- { 23, 26, 12, 0, 0, 23, 0, }, /* 559 */
- { 10, 21, 12, 0, 0, -150, 0, }, /* 560 */
- { 10, 21, 12, 0, 0, -137, 0, }, /* 561 */
- { 23, 6, 12, 0, 0, 23, 0, }, /* 562 */
- { 10, 7, 12, 0, 0, 23, 0, }, /* 563 */
- { 23, 14, 12, 0, 0, 23, 0, }, /* 564 */
- { 10, 22, 12, 0, 0, -150, 0, }, /* 565 */
- { 10, 18, 12, 0, 0, -150, 0, }, /* 566 */
- { 10, 26, 12, 0, 0, -137, 0, }, /* 567 */
- { 10, 17, 12, 0, 0, -137, 0, }, /* 568 */
- { 10, 22, 12, 0, 0, -137, 0, }, /* 569 */
- { 10, 18, 12, 0, 0, -137, 0, }, /* 570 */
- { 28, 12, 3, 0, 0, -19, 0, }, /* 571 */
- { 24, 10, 3, 0, 0, 24, 0, }, /* 572 */
- { 10, 17, 14, 0, 0, -137, 0, }, /* 573 */
- { 10, 6, 12, 0, 0, -67, 0, }, /* 574 */
- { 10, 7, 12, 0, 0, -114, 0, }, /* 575 */
- { 10, 21, 14, 0, 0, -114, 0, }, /* 576 */
- { 10, 26, 12, 0, 0, 23, 0, }, /* 577 */
- { 27, 7, 12, 0, 0, 27, 0, }, /* 578 */
- { 28, 12, 3, 0, 0, -67, 0, }, /* 579 */
- { 10, 24, 12, 0, 0, -67, 0, }, /* 580 */
- { 27, 6, 12, 0, 0, 27, 0, }, /* 581 */
- { 10, 17, 12, 0, 0, -67, 0, }, /* 582 */
- { 30, 7, 12, 0, 0, 30, 0, }, /* 583 */
- { 30, 6, 12, 0, 0, 30, 0, }, /* 584 */
- { 4, 7, 12, 0, 0, 4, 0, }, /* 585 */
- { 24, 7, 12, 0, 0, 24, 0, }, /* 586 */
- { 10, 15, 12, 0, 0, 23, 0, }, /* 587 */
- { 24, 26, 12, 0, 0, 24, 0, }, /* 588 */
- { 10, 26, 14, 0, 0, 23, 0, }, /* 589 */
- { 30, 26, 12, 0, 0, 30, 0, }, /* 590 */
- { 23, 7, 12, 0, 0, 23, 0, }, /* 591 */
- { 61, 7, 12, 0, 0, 61, 0, }, /* 592 */
- { 61, 6, 12, 0, 0, 61, 0, }, /* 593 */
- { 61, 26, 12, 0, 0, 61, 0, }, /* 594 */
- { 86, 7, 12, 0, 0, 86, 0, }, /* 595 */
- { 86, 6, 12, 0, 0, 86, 0, }, /* 596 */
- { 86, 21, 12, 0, 0, 86, 0, }, /* 597 */
- { 77, 7, 12, 0, 0, 77, 0, }, /* 598 */
- { 77, 6, 12, 0, 0, 77, 0, }, /* 599 */
- { 77, 21, 12, 0, 0, 77, 0, }, /* 600 */
- { 77, 13, 12, 0, 0, 77, 0, }, /* 601 */
- { 13, 9, 12, 108, 1, 13, 0, }, /* 602 */
- { 13, 5, 12, 108, -35267, 13, 0, }, /* 603 */
- { 13, 7, 12, 0, 0, 13, 0, }, /* 604 */
- { 13, 21, 12, 0, 0, 13, 0, }, /* 605 */
- { 79, 7, 12, 0, 0, 79, 0, }, /* 606 */
- { 79, 14, 12, 0, 0, 79, 0, }, /* 607 */
- { 79, 12, 3, 0, 0, 79, 0, }, /* 608 */
- { 79, 21, 12, 0, 0, 79, 0, }, /* 609 */
- { 10, 24, 12, 0, 0, -64, 0, }, /* 610 */
- { 34, 9, 12, 0, -35332, 34, 0, }, /* 611 */
- { 34, 9, 12, 0, -42280, 34, 0, }, /* 612 */
- { 34, 5, 12, 0, 48, 34, 0, }, /* 613 */
- { 34, 9, 12, 0, -42308, 34, 0, }, /* 614 */
- { 34, 9, 12, 0, -42319, 34, 0, }, /* 615 */
- { 34, 9, 12, 0, -42315, 34, 0, }, /* 616 */
- { 34, 9, 12, 0, -42305, 34, 0, }, /* 617 */
- { 34, 9, 12, 0, -42258, 34, 0, }, /* 618 */
- { 34, 9, 12, 0, -42282, 34, 0, }, /* 619 */
- { 34, 9, 12, 0, -42261, 34, 0, }, /* 620 */
- { 34, 9, 12, 0, 928, 34, 0, }, /* 621 */
- { 34, 9, 12, 0, -48, 34, 0, }, /* 622 */
- { 34, 9, 12, 0, -42307, 34, 0, }, /* 623 */
- { 34, 9, 12, 0, -35384, 34, 0, }, /* 624 */
- { 49, 7, 12, 0, 0, 49, 0, }, /* 625 */
- { 49, 12, 3, 0, 0, 49, 0, }, /* 626 */
- { 49, 10, 5, 0, 0, 49, 0, }, /* 627 */
- { 49, 26, 12, 0, 0, 49, 0, }, /* 628 */
- { 10, 15, 12, 0, 0, -244, 0, }, /* 629 */
- { 10, 15, 12, 0, 0, -230, 0, }, /* 630 */
- { 10, 26, 12, 0, 0, -191, 0, }, /* 631 */
- { 10, 23, 12, 0, 0, -191, 0, }, /* 632 */
- { 65, 7, 12, 0, 0, 65, 0, }, /* 633 */
- { 65, 21, 12, 0, 0, 65, 0, }, /* 634 */
- { 75, 10, 5, 0, 0, 75, 0, }, /* 635 */
- { 75, 7, 12, 0, 0, 75, 0, }, /* 636 */
- { 75, 12, 3, 0, 0, 75, 0, }, /* 637 */
- { 75, 21, 12, 0, 0, 75, 0, }, /* 638 */
- { 75, 13, 12, 0, 0, 75, 0, }, /* 639 */
- { 15, 12, 3, 0, 0, -16, 0, }, /* 640 */
- { 15, 7, 12, 0, 0, -49, 0, }, /* 641 */
- { 69, 13, 12, 0, 0, 69, 0, }, /* 642 */
- { 69, 7, 12, 0, 0, 69, 0, }, /* 643 */
- { 69, 12, 3, 0, 0, 69, 0, }, /* 644 */
- { 10, 21, 12, 0, 0, -118, 0, }, /* 645 */
- { 69, 21, 12, 0, 0, 69, 0, }, /* 646 */
- { 74, 7, 12, 0, 0, 74, 0, }, /* 647 */
- { 74, 12, 3, 0, 0, 74, 0, }, /* 648 */
- { 74, 10, 5, 0, 0, 74, 0, }, /* 649 */
- { 74, 21, 12, 0, 0, 74, 0, }, /* 650 */
- { 84, 12, 3, 0, 0, 84, 0, }, /* 651 */
- { 84, 10, 5, 0, 0, 84, 0, }, /* 652 */
- { 84, 7, 12, 0, 0, 84, 0, }, /* 653 */
- { 84, 21, 12, 0, 0, 84, 0, }, /* 654 */
- { 10, 6, 12, 0, 0, -22, 0, }, /* 655 */
- { 84, 13, 12, 0, 0, 84, 0, }, /* 656 */
- { 39, 6, 12, 0, 0, 39, 0, }, /* 657 */
- { 68, 7, 12, 0, 0, 68, 0, }, /* 658 */
- { 68, 12, 3, 0, 0, 68, 0, }, /* 659 */
- { 68, 10, 5, 0, 0, 68, 0, }, /* 660 */
- { 68, 13, 12, 0, 0, 68, 0, }, /* 661 */
- { 68, 21, 12, 0, 0, 68, 0, }, /* 662 */
- { 92, 7, 12, 0, 0, 92, 0, }, /* 663 */
- { 92, 12, 3, 0, 0, 92, 0, }, /* 664 */
- { 92, 6, 12, 0, 0, 92, 0, }, /* 665 */
- { 92, 21, 12, 0, 0, 92, 0, }, /* 666 */
- { 87, 7, 12, 0, 0, 87, 0, }, /* 667 */
- { 87, 10, 5, 0, 0, 87, 0, }, /* 668 */
- { 87, 12, 3, 0, 0, 87, 0, }, /* 669 */
- { 87, 21, 12, 0, 0, 87, 0, }, /* 670 */
- { 87, 6, 12, 0, 0, 87, 0, }, /* 671 */
- { 34, 5, 12, 0, -928, 34, 0, }, /* 672 */
- { 9, 5, 12, 0, -38864, 9, 0, }, /* 673 */
- { 87, 13, 12, 0, 0, 87, 0, }, /* 674 */
- { 24, 7, 9, 0, 0, 24, 0, }, /* 675 */
- { 24, 7, 10, 0, 0, 24, 0, }, /* 676 */
- { 0, 4, 12, 0, 0, 0, 0, }, /* 677 */
- { 0, 3, 12, 0, 0, 0, 0, }, /* 678 */
- { 26, 25, 12, 0, 0, 26, 0, }, /* 679 */
- { 10, 18, 12, 0, 0, -7, 0, }, /* 680 */
- { 10, 22, 12, 0, 0, -7, 0, }, /* 681 */
- { 1, 7, 12, 0, 0, -13, 0, }, /* 682 */
- { 1, 26, 12, 0, 0, -13, 0, }, /* 683 */
- { 10, 6, 3, 0, 0, -67, 0, }, /* 684 */
- { 36, 7, 12, 0, 0, 36, 0, }, /* 685 */
- { 10, 21, 12, 0, 0, -98, 0, }, /* 686 */
- { 10, 21, 12, 0, 0, -25, 0, }, /* 687 */
- { 10, 15, 12, 0, 0, -102, 0, }, /* 688 */
- { 10, 26, 12, 0, 0, -25, 0, }, /* 689 */
- { 20, 14, 12, 0, 0, 20, 0, }, /* 690 */
- { 20, 15, 12, 0, 0, 20, 0, }, /* 691 */
- { 20, 26, 12, 0, 0, 20, 0, }, /* 692 */
- { 71, 7, 12, 0, 0, 71, 0, }, /* 693 */
- { 67, 7, 12, 0, 0, 67, 0, }, /* 694 */
- { 28, 12, 3, 0, 0, -1, 0, }, /* 695 */
- { 10, 15, 12, 0, 0, -1, 0, }, /* 696 */
- { 42, 7, 12, 0, 0, 42, 0, }, /* 697 */
- { 42, 15, 12, 0, 0, 42, 0, }, /* 698 */
- { 19, 7, 12, 0, 0, 19, 0, }, /* 699 */
- { 19, 14, 12, 0, 0, 19, 0, }, /* 700 */
- { 118, 7, 12, 0, 0, 118, 0, }, /* 701 */
- { 118, 12, 3, 0, 0, 118, 0, }, /* 702 */
- { 60, 7, 12, 0, 0, 60, 0, }, /* 703 */
- { 60, 21, 12, 0, 0, 60, 0, }, /* 704 */
- { 43, 7, 12, 0, 0, 43, 0, }, /* 705 */
- { 43, 21, 12, 0, 0, 43, 0, }, /* 706 */
- { 43, 14, 12, 0, 0, 43, 0, }, /* 707 */
- { 14, 9, 12, 0, 40, 14, 0, }, /* 708 */
- { 14, 5, 12, 0, -40, 14, 0, }, /* 709 */
- { 47, 7, 12, 0, 0, 47, 0, }, /* 710 */
- { 45, 7, 12, 0, 0, 45, 0, }, /* 711 */
- { 45, 13, 12, 0, 0, 45, 0, }, /* 712 */
- { 136, 9, 12, 0, 40, 136, 0, }, /* 713 */
- { 136, 5, 12, 0, -40, 136, 0, }, /* 714 */
- { 106, 7, 12, 0, 0, 106, 0, }, /* 715 */
- { 104, 7, 12, 0, 0, 104, 0, }, /* 716 */
- { 104, 21, 12, 0, 0, 104, 0, }, /* 717 */
- { 161, 9, 12, 0, 39, 161, 0, }, /* 718 */
- { 161, 5, 12, 0, -39, 161, 0, }, /* 719 */
- { 110, 7, 12, 0, 0, 110, 0, }, /* 720 */
- { 12, 7, 12, 0, 0, 12, 0, }, /* 721 */
- { 81, 7, 12, 0, 0, 81, 0, }, /* 722 */
- { 81, 21, 12, 0, 0, 81, 0, }, /* 723 */
- { 81, 15, 12, 0, 0, 81, 0, }, /* 724 */
- { 120, 7, 12, 0, 0, 120, 0, }, /* 725 */
- { 120, 26, 12, 0, 0, 120, 0, }, /* 726 */
- { 120, 15, 12, 0, 0, 120, 0, }, /* 727 */
- { 116, 7, 12, 0, 0, 116, 0, }, /* 728 */
- { 116, 15, 12, 0, 0, 116, 0, }, /* 729 */
- { 128, 7, 12, 0, 0, 128, 0, }, /* 730 */
- { 128, 15, 12, 0, 0, 128, 0, }, /* 731 */
- { 66, 7, 12, 0, 0, 66, 0, }, /* 732 */
- { 66, 15, 12, 0, 0, 66, 0, }, /* 733 */
- { 66, 21, 12, 0, 0, 66, 0, }, /* 734 */
- { 72, 7, 12, 0, 0, 72, 0, }, /* 735 */
- { 72, 21, 12, 0, 0, 72, 0, }, /* 736 */
- { 98, 7, 12, 0, 0, 98, 0, }, /* 737 */
- { 97, 7, 12, 0, 0, 97, 0, }, /* 738 */
- { 97, 15, 12, 0, 0, 97, 0, }, /* 739 */
- { 31, 7, 12, 0, 0, 31, 0, }, /* 740 */
- { 31, 12, 3, 0, 0, 31, 0, }, /* 741 */
- { 31, 15, 12, 0, 0, 31, 0, }, /* 742 */
- { 31, 21, 12, 0, 0, 31, 0, }, /* 743 */
- { 88, 7, 12, 0, 0, 88, 0, }, /* 744 */
- { 88, 15, 12, 0, 0, 88, 0, }, /* 745 */
- { 88, 21, 12, 0, 0, 88, 0, }, /* 746 */
- { 117, 7, 12, 0, 0, 117, 0, }, /* 747 */
- { 117, 15, 12, 0, 0, 117, 0, }, /* 748 */
- { 112, 7, 12, 0, 0, 112, 0, }, /* 749 */
- { 112, 26, 12, 0, 0, 112, 0, }, /* 750 */
- { 112, 12, 3, 0, 0, 112, 0, }, /* 751 */
- { 112, 15, 12, 0, 0, 112, 0, }, /* 752 */
- { 112, 21, 12, 0, 0, 112, 0, }, /* 753 */
- { 112, 21, 12, 0, 0, -76, 0, }, /* 754 */
- { 78, 7, 12, 0, 0, 78, 0, }, /* 755 */
- { 78, 21, 12, 0, 0, 78, 0, }, /* 756 */
- { 83, 7, 12, 0, 0, 83, 0, }, /* 757 */
- { 83, 15, 12, 0, 0, 83, 0, }, /* 758 */
- { 82, 7, 12, 0, 0, 82, 0, }, /* 759 */
- { 82, 15, 12, 0, 0, 82, 0, }, /* 760 */
- { 121, 7, 12, 0, 0, 121, 0, }, /* 761 */
- { 121, 21, 12, 0, 0, 121, 0, }, /* 762 */
- { 121, 15, 12, 0, 0, 121, 0, }, /* 763 */
- { 89, 7, 12, 0, 0, 89, 0, }, /* 764 */
- { 130, 9, 12, 0, 64, 130, 0, }, /* 765 */
- { 130, 5, 12, 0, -64, 130, 0, }, /* 766 */
- { 130, 15, 12, 0, 0, 130, 0, }, /* 767 */
- { 144, 7, 12, 0, 0, 144, 0, }, /* 768 */
- { 144, 12, 3, 0, 0, 144, 0, }, /* 769 */
- { 144, 13, 12, 0, 0, 144, 0, }, /* 770 */
- { 1, 15, 12, 0, 0, 1, 0, }, /* 771 */
- { 156, 7, 12, 0, 0, 156, 0, }, /* 772 */
- { 156, 12, 3, 0, 0, 156, 0, }, /* 773 */
- { 156, 17, 12, 0, 0, 156, 0, }, /* 774 */
- { 147, 7, 12, 0, 0, 147, 0, }, /* 775 */
- { 147, 15, 12, 0, 0, 147, 0, }, /* 776 */
- { 148, 7, 12, 0, 0, 148, 0, }, /* 777 */
- { 148, 12, 3, 0, 0, 148, 0, }, /* 778 */
- { 148, 15, 12, 0, 0, 148, 0, }, /* 779 */
- { 148, 21, 12, 0, 0, 148, 0, }, /* 780 */
- { 158, 7, 12, 0, 0, 158, 0, }, /* 781 */
- { 158, 12, 3, 0, 0, 158, 0, }, /* 782 */
- { 158, 21, 12, 0, 0, 158, 0, }, /* 783 */
- { 153, 7, 12, 0, 0, 153, 0, }, /* 784 */
- { 153, 15, 12, 0, 0, 153, 0, }, /* 785 */
- { 149, 7, 12, 0, 0, 149, 0, }, /* 786 */
- { 94, 10, 5, 0, 0, 94, 0, }, /* 787 */
- { 94, 12, 3, 0, 0, 94, 0, }, /* 788 */
- { 94, 7, 12, 0, 0, 94, 0, }, /* 789 */
- { 94, 21, 12, 0, 0, 94, 0, }, /* 790 */
- { 94, 15, 12, 0, 0, 94, 0, }, /* 791 */
- { 94, 13, 12, 0, 0, 94, 0, }, /* 792 */
- { 85, 12, 3, 0, 0, 85, 0, }, /* 793 */
- { 85, 10, 5, 0, 0, 85, 0, }, /* 794 */
- { 85, 7, 12, 0, 0, 85, 0, }, /* 795 */
- { 85, 21, 12, 0, 0, 85, 0, }, /* 796 */
- { 85, 1, 4, 0, 0, 85, 0, }, /* 797 */
- { 101, 7, 12, 0, 0, 101, 0, }, /* 798 */
- { 101, 13, 12, 0, 0, 101, 0, }, /* 799 */
- { 96, 12, 3, 0, 0, 96, 0, }, /* 800 */
- { 96, 7, 12, 0, 0, 96, 0, }, /* 801 */
- { 96, 10, 5, 0, 0, 96, 0, }, /* 802 */
- { 96, 13, 12, 0, 0, 96, 0, }, /* 803 */
- { 96, 21, 12, 0, 0, 96, 0, }, /* 804 */
- { 111, 7, 12, 0, 0, 111, 0, }, /* 805 */
- { 111, 12, 3, 0, 0, 111, 0, }, /* 806 */
- { 111, 21, 12, 0, 0, 111, 0, }, /* 807 */
- { 100, 12, 3, 0, 0, 100, 0, }, /* 808 */
- { 100, 10, 5, 0, 0, 100, 0, }, /* 809 */
- { 100, 7, 12, 0, 0, 100, 0, }, /* 810 */
- { 100, 7, 4, 0, 0, 100, 0, }, /* 811 */
- { 100, 21, 12, 0, 0, 100, 0, }, /* 812 */
- { 100, 13, 12, 0, 0, 100, 0, }, /* 813 */
- { 48, 15, 12, 0, 0, 48, 0, }, /* 814 */
- { 108, 7, 12, 0, 0, 108, 0, }, /* 815 */
- { 108, 10, 5, 0, 0, 108, 0, }, /* 816 */
- { 108, 12, 3, 0, 0, 108, 0, }, /* 817 */
- { 108, 21, 12, 0, 0, 108, 0, }, /* 818 */
- { 129, 7, 12, 0, 0, 129, 0, }, /* 819 */
- { 129, 21, 12, 0, 0, 129, 0, }, /* 820 */
- { 109, 7, 12, 0, 0, 109, 0, }, /* 821 */
- { 109, 12, 3, 0, 0, 109, 0, }, /* 822 */
- { 109, 10, 5, 0, 0, 109, 0, }, /* 823 */
- { 109, 13, 12, 0, 0, 109, 0, }, /* 824 */
- { 107, 12, 3, 0, 0, 107, 0, }, /* 825 */
- { 107, 12, 3, 0, 0, -55, 0, }, /* 826 */
- { 107, 10, 5, 0, 0, 107, 0, }, /* 827 */
- { 107, 10, 5, 0, 0, -55, 0, }, /* 828 */
- { 107, 7, 12, 0, 0, 107, 0, }, /* 829 */
- { 28, 12, 3, 0, 0, -55, 0, }, /* 830 */
- { 107, 10, 3, 0, 0, 107, 0, }, /* 831 */
- { 135, 7, 12, 0, 0, 135, 0, }, /* 832 */
- { 135, 10, 5, 0, 0, 135, 0, }, /* 833 */
- { 135, 12, 3, 0, 0, 135, 0, }, /* 834 */
- { 135, 21, 12, 0, 0, 135, 0, }, /* 835 */
- { 135, 13, 12, 0, 0, 135, 0, }, /* 836 */
- { 124, 7, 12, 0, 0, 124, 0, }, /* 837 */
- { 124, 10, 3, 0, 0, 124, 0, }, /* 838 */
- { 124, 10, 5, 0, 0, 124, 0, }, /* 839 */
- { 124, 12, 3, 0, 0, 124, 0, }, /* 840 */
- { 124, 21, 12, 0, 0, 124, 0, }, /* 841 */
- { 124, 13, 12, 0, 0, 124, 0, }, /* 842 */
- { 123, 7, 12, 0, 0, 123, 0, }, /* 843 */
- { 123, 10, 3, 0, 0, 123, 0, }, /* 844 */
- { 123, 10, 5, 0, 0, 123, 0, }, /* 845 */
- { 123, 12, 3, 0, 0, 123, 0, }, /* 846 */
- { 123, 21, 12, 0, 0, 123, 0, }, /* 847 */
- { 114, 7, 12, 0, 0, 114, 0, }, /* 848 */
- { 114, 10, 5, 0, 0, 114, 0, }, /* 849 */
- { 114, 12, 3, 0, 0, 114, 0, }, /* 850 */
- { 114, 21, 12, 0, 0, 114, 0, }, /* 851 */
- { 114, 13, 12, 0, 0, 114, 0, }, /* 852 */
- { 102, 7, 12, 0, 0, 102, 0, }, /* 853 */
- { 102, 12, 3, 0, 0, 102, 0, }, /* 854 */
- { 102, 10, 5, 0, 0, 102, 0, }, /* 855 */
- { 102, 21, 12, 0, 0, 102, 0, }, /* 856 */
- { 102, 13, 12, 0, 0, 102, 0, }, /* 857 */
- { 126, 7, 12, 0, 0, 126, 0, }, /* 858 */
- { 126, 12, 3, 0, 0, 126, 0, }, /* 859 */
- { 126, 10, 12, 0, 0, 126, 0, }, /* 860 */
- { 126, 10, 5, 0, 0, 126, 0, }, /* 861 */
- { 126, 13, 12, 0, 0, 126, 0, }, /* 862 */
- { 126, 15, 12, 0, 0, 126, 0, }, /* 863 */
- { 126, 21, 12, 0, 0, 126, 0, }, /* 864 */
- { 126, 26, 12, 0, 0, 126, 0, }, /* 865 */
- { 142, 7, 12, 0, 0, 142, 0, }, /* 866 */
- { 142, 10, 5, 0, 0, 142, 0, }, /* 867 */
- { 142, 12, 3, 0, 0, 142, 0, }, /* 868 */
- { 142, 21, 12, 0, 0, 142, 0, }, /* 869 */
- { 125, 9, 12, 0, 32, 125, 0, }, /* 870 */
- { 125, 5, 12, 0, -32, 125, 0, }, /* 871 */
- { 125, 13, 12, 0, 0, 125, 0, }, /* 872 */
- { 125, 15, 12, 0, 0, 125, 0, }, /* 873 */
- { 125, 7, 12, 0, 0, 125, 0, }, /* 874 */
- { 154, 7, 12, 0, 0, 154, 0, }, /* 875 */
- { 154, 10, 3, 0, 0, 154, 0, }, /* 876 */
- { 154, 10, 5, 0, 0, 154, 0, }, /* 877 */
- { 154, 12, 3, 0, 0, 154, 0, }, /* 878 */
- { 154, 7, 4, 0, 0, 154, 0, }, /* 879 */
- { 154, 21, 12, 0, 0, 154, 0, }, /* 880 */
- { 154, 13, 12, 0, 0, 154, 0, }, /* 881 */
- { 150, 7, 12, 0, 0, 150, 0, }, /* 882 */
- { 150, 10, 5, 0, 0, 150, 0, }, /* 883 */
- { 150, 12, 3, 0, 0, 150, 0, }, /* 884 */
- { 150, 21, 12, 0, 0, 150, 0, }, /* 885 */
- { 141, 7, 12, 0, 0, 141, 0, }, /* 886 */
- { 141, 12, 3, 0, 0, 141, 0, }, /* 887 */
- { 141, 10, 5, 0, 0, 141, 0, }, /* 888 */
- { 141, 7, 4, 0, 0, 141, 0, }, /* 889 */
- { 141, 21, 12, 0, 0, 141, 0, }, /* 890 */
- { 140, 7, 12, 0, 0, 140, 0, }, /* 891 */
- { 140, 12, 3, 0, 0, 140, 0, }, /* 892 */
- { 140, 10, 5, 0, 0, 140, 0, }, /* 893 */
- { 140, 7, 4, 0, 0, 140, 0, }, /* 894 */
- { 140, 21, 12, 0, 0, 140, 0, }, /* 895 */
- { 122, 7, 12, 0, 0, 122, 0, }, /* 896 */
- { 133, 7, 12, 0, 0, 133, 0, }, /* 897 */
- { 133, 10, 5, 0, 0, 133, 0, }, /* 898 */
- { 133, 12, 3, 0, 0, 133, 0, }, /* 899 */
- { 133, 21, 12, 0, 0, 133, 0, }, /* 900 */
- { 133, 13, 12, 0, 0, 133, 0, }, /* 901 */
- { 133, 15, 12, 0, 0, 133, 0, }, /* 902 */
- { 134, 21, 12, 0, 0, 134, 0, }, /* 903 */
- { 134, 7, 12, 0, 0, 134, 0, }, /* 904 */
- { 134, 12, 3, 0, 0, 134, 0, }, /* 905 */
- { 134, 10, 5, 0, 0, 134, 0, }, /* 906 */
- { 138, 7, 12, 0, 0, 138, 0, }, /* 907 */
- { 138, 12, 3, 0, 0, 138, 0, }, /* 908 */
- { 138, 7, 4, 0, 0, 138, 0, }, /* 909 */
- { 138, 13, 12, 0, 0, 138, 0, }, /* 910 */
- { 143, 7, 12, 0, 0, 143, 0, }, /* 911 */
- { 143, 10, 5, 0, 0, 143, 0, }, /* 912 */
- { 143, 12, 3, 0, 0, 143, 0, }, /* 913 */
- { 143, 13, 12, 0, 0, 143, 0, }, /* 914 */
- { 145, 7, 12, 0, 0, 145, 0, }, /* 915 */
- { 145, 12, 3, 0, 0, 145, 0, }, /* 916 */
- { 145, 10, 5, 0, 0, 145, 0, }, /* 917 */
- { 145, 21, 12, 0, 0, 145, 0, }, /* 918 */
- { 54, 15, 12, 0, 0, 54, 0, }, /* 919 */
- { 54, 21, 12, 0, 0, 54, 0, }, /* 920 */
- { 63, 7, 12, 0, 0, 63, 0, }, /* 921 */
- { 63, 14, 12, 0, 0, 63, 0, }, /* 922 */
- { 63, 21, 12, 0, 0, 63, 0, }, /* 923 */
- { 157, 7, 12, 0, 0, 157, 0, }, /* 924 */
- { 157, 21, 12, 0, 0, 157, 0, }, /* 925 */
- { 80, 7, 12, 0, 0, 80, 0, }, /* 926 */
- { 80, 1, 2, 0, 0, 80, 0, }, /* 927 */
- { 127, 7, 12, 0, 0, 127, 0, }, /* 928 */
- { 115, 7, 12, 0, 0, 115, 0, }, /* 929 */
- { 115, 13, 12, 0, 0, 115, 0, }, /* 930 */
- { 115, 21, 12, 0, 0, 115, 0, }, /* 931 */
- { 159, 7, 12, 0, 0, 159, 0, }, /* 932 */
- { 159, 13, 12, 0, 0, 159, 0, }, /* 933 */
- { 103, 7, 12, 0, 0, 103, 0, }, /* 934 */
- { 103, 12, 3, 0, 0, 103, 0, }, /* 935 */
- { 103, 21, 12, 0, 0, 103, 0, }, /* 936 */
- { 119, 7, 12, 0, 0, 119, 0, }, /* 937 */
- { 119, 12, 3, 0, 0, 119, 0, }, /* 938 */
- { 119, 21, 12, 0, 0, 119, 0, }, /* 939 */
- { 119, 26, 12, 0, 0, 119, 0, }, /* 940 */
- { 119, 6, 12, 0, 0, 119, 0, }, /* 941 */
- { 119, 13, 12, 0, 0, 119, 0, }, /* 942 */
- { 119, 15, 12, 0, 0, 119, 0, }, /* 943 */
- { 146, 9, 12, 0, 32, 146, 0, }, /* 944 */
- { 146, 5, 12, 0, -32, 146, 0, }, /* 945 */
- { 146, 15, 12, 0, 0, 146, 0, }, /* 946 */
- { 146, 21, 12, 0, 0, 146, 0, }, /* 947 */
- { 99, 7, 12, 0, 0, 99, 0, }, /* 948 */
- { 99, 12, 3, 0, 0, 99, 0, }, /* 949 */
- { 99, 10, 5, 0, 0, 99, 0, }, /* 950 */
- { 99, 6, 12, 0, 0, 99, 0, }, /* 951 */
- { 137, 6, 12, 0, 0, 137, 0, }, /* 952 */
- { 139, 6, 12, 0, 0, 139, 0, }, /* 953 */
- { 23, 21, 12, 0, 0, 23, 0, }, /* 954 */
- { 155, 12, 3, 0, 0, 155, 0, }, /* 955 */
- { 23, 10, 5, 0, 0, 23, 0, }, /* 956 */
- { 137, 7, 12, 0, 0, 137, 0, }, /* 957 */
- { 155, 7, 12, 0, 0, 155, 0, }, /* 958 */
- { 139, 7, 12, 0, 0, 139, 0, }, /* 959 */
- { 105, 7, 12, 0, 0, 105, 0, }, /* 960 */
- { 105, 26, 12, 0, 0, 105, 0, }, /* 961 */
- { 105, 12, 3, 0, 0, 105, 0, }, /* 962 */
- { 105, 21, 12, 0, 0, 105, 0, }, /* 963 */
- { 10, 1, 2, 0, 0, 105, 0, }, /* 964 */
- { 10, 10, 3, 0, 0, 10, 0, }, /* 965 */
- { 10, 10, 5, 0, 0, 10, 0, }, /* 966 */
- { 20, 12, 3, 0, 0, 20, 0, }, /* 967 */
- { 131, 26, 12, 0, 0, 131, 0, }, /* 968 */
- { 131, 12, 3, 0, 0, 131, 0, }, /* 969 */
- { 131, 21, 12, 0, 0, 131, 0, }, /* 970 */
- { 18, 12, 3, 0, 0, 18, 0, }, /* 971 */
- { 151, 7, 12, 0, 0, 151, 0, }, /* 972 */
- { 151, 12, 3, 0, 0, 151, 0, }, /* 973 */
- { 151, 6, 12, 0, 0, 151, 0, }, /* 974 */
- { 151, 13, 12, 0, 0, 151, 0, }, /* 975 */
- { 151, 26, 12, 0, 0, 151, 0, }, /* 976 */
- { 160, 7, 12, 0, 0, 160, 0, }, /* 977 */
- { 160, 12, 3, 0, 0, 160, 0, }, /* 978 */
- { 152, 7, 12, 0, 0, 152, 0, }, /* 979 */
- { 152, 12, 3, 0, 0, 152, 0, }, /* 980 */
- { 152, 13, 12, 0, 0, 152, 0, }, /* 981 */
- { 152, 23, 12, 0, 0, 152, 0, }, /* 982 */
- { 113, 7, 12, 0, 0, 113, 0, }, /* 983 */
- { 113, 15, 12, 0, 0, 113, 0, }, /* 984 */
- { 113, 12, 3, 0, 0, 113, 0, }, /* 985 */
- { 132, 9, 12, 0, 34, 132, 0, }, /* 986 */
- { 132, 5, 12, 0, -34, 132, 0, }, /* 987 */
- { 132, 12, 3, 0, 0, 132, 0, }, /* 988 */
- { 132, 6, 12, 0, 0, 132, 0, }, /* 989 */
- { 132, 13, 12, 0, 0, 132, 0, }, /* 990 */
- { 132, 21, 12, 0, 0, 132, 0, }, /* 991 */
- { 0, 2, 14, 0, 0, 0, 0, }, /* 992 */
- { 10, 26, 11, 0, 0, 10, 0, }, /* 993 */
- { 27, 26, 12, 0, 0, 27, 0, }, /* 994 */
- { 10, 24, 3, 0, 0, 10, 0, }, /* 995 */
- { 10, 1, 3, 0, 0, 10, 0, }, /* 996 */
+offset to multichar other cases or zero (8 bits), offset to other case or zero
+(32 bits, signed), bidi class (5 bits) and script extension (11 bits) packed
+into a 16-bit field, and offset in binary properties table (16 bits). */
+
+const ucd_record PRIV(ucd_records)[] = { /* 16908 bytes, record size 12 */
+ { 69, 0, 2, 0, 0, 6144, 2, }, /* 0 */
+ { 69, 0, 2, 0, 0, 43008, 4, }, /* 1 */
+ { 69, 0, 1, 0, 0, 4096, 4, }, /* 2 */
+ { 69, 0, 2, 0, 0, 45056, 4, }, /* 3 */
+ { 69, 0, 0, 0, 0, 4096, 4, }, /* 4 */
+ { 69, 0, 2, 0, 0, 4096, 2, }, /* 5 */
+ { 69, 0, 2, 0, 0, 43008, 2, }, /* 6 */
+ { 69, 29, 12, 0, 0, 45056, 6, }, /* 7 */
+ { 69, 21, 12, 0, 0, 28672, 8, }, /* 8 */
+ { 69, 21, 12, 0, 0, 28672, 10, }, /* 9 */
+ { 69, 21, 12, 0, 0, 14336, 12, }, /* 10 */
+ { 69, 23, 12, 0, 0, 14336, 14, }, /* 11 */
+ { 69, 21, 12, 0, 0, 14336, 14, }, /* 12 */
+ { 69, 21, 12, 0, 0, 28672, 14, }, /* 13 */
+ { 69, 21, 12, 0, 0, 28672, 16, }, /* 14 */
+ { 69, 22, 12, 0, 0, 28672, 18, }, /* 15 */
+ { 69, 18, 12, 0, 0, 28672, 18, }, /* 16 */
+ { 69, 21, 12, 0, 0, 28672, 12, }, /* 17 */
+ { 69, 25, 12, 0, 0, 12288, 20, }, /* 18 */
+ { 69, 21, 12, 0, 0, 8192, 22, }, /* 19 */
+ { 69, 17, 12, 0, 0, 12288, 24, }, /* 20 */
+ { 69, 21, 12, 0, 0, 8192, 26, }, /* 21 */
+ { 69, 21, 12, 0, 0, 8192, 14, }, /* 22 */
+ { 69, 13, 12, 0, 0, 10240, 28, }, /* 23 */
+ { 69, 21, 12, 0, 0, 8192, 30, }, /* 24 */
+ { 69, 21, 12, 0, 0, 28672, 22, }, /* 25 */
+ { 69, 25, 12, 0, 0, 28672, 32, }, /* 26 */
+ { 69, 25, 12, 0, 0, 28672, 20, }, /* 27 */
+ { 0, 9, 12, 0, 32, 18432, 34, }, /* 28 */
+ { 0, 9, 12, 0, 32, 18432, 36, }, /* 29 */
+ { 0, 9, 12, 100, 32, 18432, 36, }, /* 30 */
+ { 0, 9, 12, 1, 32, 18432, 36, }, /* 31 */
+ { 69, 24, 12, 0, 0, 28672, 38, }, /* 32 */
+ { 69, 16, 12, 0, 0, 28672, 40, }, /* 33 */
+ { 69, 24, 12, 0, 0, 28672, 42, }, /* 34 */
+ { 0, 5, 12, 0, -32, 18432, 44, }, /* 35 */
+ { 0, 5, 12, 0, -32, 18432, 46, }, /* 36 */
+ { 0, 5, 12, 0, -32, 18432, 48, }, /* 37 */
+ { 0, 5, 12, 100, -32, 18432, 46, }, /* 38 */
+ { 0, 5, 12, 1, -32, 18432, 46, }, /* 39 */
+ { 69, 0, 2, 0, 0, 6144, 0, }, /* 40 */
+ { 69, 0, 2, 0, 0, 4096, 50, }, /* 41 */
+ { 69, 29, 12, 0, 0, 8192, 52, }, /* 42 */
+ { 69, 21, 12, 0, 0, 28672, 54, }, /* 43 */
+ { 69, 23, 12, 0, 0, 14336, 54, }, /* 44 */
+ { 69, 26, 12, 0, 0, 28672, 54, }, /* 45 */
+ { 69, 24, 12, 0, 0, 28672, 56, }, /* 46 */
+ { 69, 26, 14, 0, 0, 28672, 58, }, /* 47 */
+ { 0, 7, 12, 0, 0, 18432, 60, }, /* 48 */
+ { 69, 20, 12, 0, 0, 28672, 62, }, /* 49 */
+ { 69, 25, 12, 0, 0, 28672, 64, }, /* 50 */
+ { 69, 1, 2, 0, 0, 6144, 66, }, /* 51 */
+ { 69, 26, 12, 0, 0, 14336, 54, }, /* 52 */
+ { 69, 25, 12, 0, 0, 14336, 64, }, /* 53 */
+ { 69, 15, 12, 0, 0, 10240, 68, }, /* 54 */
+ { 69, 5, 12, 26, 775, 18432, 70, }, /* 55 */
+ { 69, 21, 12, 0, 0, 28672, 72, }, /* 56 */
+ { 69, 19, 12, 0, 0, 28672, 62, }, /* 57 */
+ { 69, 15, 12, 0, 0, 28672, 68, }, /* 58 */
+ { 0, 9, 12, 0, 32, 18432, 74, }, /* 59 */
+ { 0, 9, 12, 104, 32, 18432, 74, }, /* 60 */
+ { 0, 5, 12, 0, 7615, 18432, 70, }, /* 61 */
+ { 0, 5, 12, 0, -32, 18432, 76, }, /* 62 */
+ { 0, 5, 12, 104, -32, 18432, 76, }, /* 63 */
+ { 0, 5, 12, 0, 121, 18432, 76, }, /* 64 */
+ { 0, 9, 12, 0, 1, 18432, 74, }, /* 65 */
+ { 0, 5, 12, 0, -1, 18432, 76, }, /* 66 */
+ { 0, 5, 12, 0, -1, 18432, 78, }, /* 67 */
+ { 0, 9, 12, 0, 0, 18432, 74, }, /* 68 */
+ { 0, 5, 12, 0, 0, 18432, 76, }, /* 69 */
+ { 0, 5, 12, 0, 0, 18432, 60, }, /* 70 */
+ { 0, 5, 12, 0, 0, 18432, 80, }, /* 71 */
+ { 0, 9, 12, 0, -121, 18432, 74, }, /* 72 */
+ { 0, 5, 12, 1, -268, 18432, 70, }, /* 73 */
+ { 0, 5, 12, 0, 195, 18432, 76, }, /* 74 */
+ { 0, 9, 12, 0, 210, 18432, 74, }, /* 75 */
+ { 0, 9, 12, 0, 206, 18432, 74, }, /* 76 */
+ { 0, 9, 12, 0, 205, 18432, 74, }, /* 77 */
+ { 0, 9, 12, 0, 79, 18432, 74, }, /* 78 */
+ { 0, 9, 12, 0, 202, 18432, 74, }, /* 79 */
+ { 0, 9, 12, 0, 203, 18432, 74, }, /* 80 */
+ { 0, 9, 12, 0, 207, 18432, 74, }, /* 81 */
+ { 0, 5, 12, 0, 97, 18432, 76, }, /* 82 */
+ { 0, 9, 12, 0, 211, 18432, 74, }, /* 83 */
+ { 0, 9, 12, 0, 209, 18432, 74, }, /* 84 */
+ { 0, 5, 12, 0, 163, 18432, 76, }, /* 85 */
+ { 0, 9, 12, 0, 213, 18432, 74, }, /* 86 */
+ { 0, 5, 12, 0, 130, 18432, 76, }, /* 87 */
+ { 0, 9, 12, 0, 214, 18432, 74, }, /* 88 */
+ { 0, 9, 12, 0, 218, 18432, 74, }, /* 89 */
+ { 0, 9, 12, 0, 217, 18432, 74, }, /* 90 */
+ { 0, 9, 12, 0, 219, 18432, 74, }, /* 91 */
+ { 0, 7, 12, 0, 0, 18432, 82, }, /* 92 */
+ { 0, 5, 12, 0, 56, 18432, 76, }, /* 93 */
+ { 0, 9, 12, 5, 2, 18432, 84, }, /* 94 */
+ { 0, 8, 12, 5, 1, 18432, 86, }, /* 95 */
+ { 0, 5, 12, 5, -2, 18432, 76, }, /* 96 */
+ { 0, 9, 12, 9, 2, 18432, 84, }, /* 97 */
+ { 0, 8, 12, 9, 1, 18432, 86, }, /* 98 */
+ { 0, 5, 12, 9, -2, 18432, 76, }, /* 99 */
+ { 0, 9, 12, 13, 2, 18432, 84, }, /* 100 */
+ { 0, 8, 12, 13, 1, 18432, 86, }, /* 101 */
+ { 0, 5, 12, 13, -2, 18432, 76, }, /* 102 */
+ { 0, 5, 12, 0, -79, 18432, 76, }, /* 103 */
+ { 0, 9, 12, 17, 2, 18432, 84, }, /* 104 */
+ { 0, 8, 12, 17, 1, 18432, 86, }, /* 105 */
+ { 0, 5, 12, 17, -2, 18432, 76, }, /* 106 */
+ { 0, 9, 12, 0, -97, 18432, 74, }, /* 107 */
+ { 0, 9, 12, 0, -56, 18432, 74, }, /* 108 */
+ { 0, 9, 12, 0, -130, 18432, 74, }, /* 109 */
+ { 0, 9, 12, 0, 10795, 18432, 74, }, /* 110 */
+ { 0, 9, 12, 0, -163, 18432, 74, }, /* 111 */
+ { 0, 9, 12, 0, 10792, 18432, 74, }, /* 112 */
+ { 0, 5, 12, 0, 10815, 18432, 76, }, /* 113 */
+ { 0, 9, 12, 0, -195, 18432, 74, }, /* 114 */
+ { 0, 9, 12, 0, 69, 18432, 74, }, /* 115 */
+ { 0, 9, 12, 0, 71, 18432, 74, }, /* 116 */
+ { 0, 5, 12, 0, 10783, 18432, 76, }, /* 117 */
+ { 0, 5, 12, 0, 10780, 18432, 76, }, /* 118 */
+ { 0, 5, 12, 0, 10782, 18432, 76, }, /* 119 */
+ { 0, 5, 12, 0, -210, 18432, 76, }, /* 120 */
+ { 0, 5, 12, 0, -206, 18432, 76, }, /* 121 */
+ { 0, 5, 12, 0, -205, 18432, 76, }, /* 122 */
+ { 0, 5, 12, 0, -202, 18432, 76, }, /* 123 */
+ { 0, 5, 12, 0, -203, 18432, 76, }, /* 124 */
+ { 0, 5, 12, 0, 42319, 18432, 76, }, /* 125 */
+ { 0, 5, 12, 0, 42315, 18432, 76, }, /* 126 */
+ { 0, 5, 12, 0, -207, 18432, 76, }, /* 127 */
+ { 0, 5, 12, 0, 42280, 18432, 76, }, /* 128 */
+ { 0, 5, 12, 0, 42308, 18432, 76, }, /* 129 */
+ { 0, 5, 12, 0, -209, 18432, 78, }, /* 130 */
+ { 0, 5, 12, 0, -211, 18432, 76, }, /* 131 */
+ { 0, 5, 12, 0, 10743, 18432, 76, }, /* 132 */
+ { 0, 5, 12, 0, 42305, 18432, 76, }, /* 133 */
+ { 0, 5, 12, 0, 10749, 18432, 76, }, /* 134 */
+ { 0, 5, 12, 0, -213, 18432, 76, }, /* 135 */
+ { 0, 5, 12, 0, -214, 18432, 76, }, /* 136 */
+ { 0, 5, 12, 0, 10727, 18432, 76, }, /* 137 */
+ { 0, 5, 12, 0, -218, 18432, 76, }, /* 138 */
+ { 0, 5, 12, 0, 42307, 18432, 76, }, /* 139 */
+ { 0, 5, 12, 0, 42282, 18432, 76, }, /* 140 */
+ { 0, 5, 12, 0, -69, 18432, 76, }, /* 141 */
+ { 0, 5, 12, 0, -217, 18432, 76, }, /* 142 */
+ { 0, 5, 12, 0, -71, 18432, 76, }, /* 143 */
+ { 0, 5, 12, 0, -219, 18432, 76, }, /* 144 */
+ { 0, 5, 12, 0, 42261, 18432, 78, }, /* 145 */
+ { 0, 5, 12, 0, 42258, 18432, 76, }, /* 146 */
+ { 0, 6, 12, 0, 0, 18432, 88, }, /* 147 */
+ { 0, 6, 12, 0, 0, 18432, 90, }, /* 148 */
+ { 69, 6, 12, 0, 0, 28672, 92, }, /* 149 */
+ { 69, 6, 12, 0, 0, 18432, 92, }, /* 150 */
+ { 69, 6, 12, 0, 0, 18432, 88, }, /* 151 */
+ { 69, 6, 12, 0, 0, 18432, 94, }, /* 152 */
+ { 22, 24, 12, 0, 0, 28672, 56, }, /* 153 */
+ { 84, 12, 3, 0, 0, 26624, 96, }, /* 154 */
+ { 84, 12, 3, 0, 0, 26636, 96, }, /* 155 */
+ { 84, 12, 3, 21, 116, 26636, 98, }, /* 156 */
+ { 84, 12, 3, 0, 0, 26624, 100, }, /* 157 */
+ { 84, 12, 3, 0, 0, 26624, 102, }, /* 158 */
+ { 84, 12, 3, 0, 0, 26642, 102, }, /* 159 */
+ { 1, 9, 12, 0, 1, 18432, 74, }, /* 160 */
+ { 1, 5, 12, 0, -1, 18432, 76, }, /* 161 */
+ { 1, 24, 12, 0, 0, 28672, 56, }, /* 162 */
+ { 68, 2, 12, 0, 0, 18432, 0, }, /* 163 */
+ { 1, 6, 12, 0, 0, 18432, 104, }, /* 164 */
+ { 1, 5, 12, 0, 130, 18432, 76, }, /* 165 */
+ { 69, 21, 12, 0, 0, 28672, 106, }, /* 166 */
+ { 1, 9, 12, 0, 116, 18432, 74, }, /* 167 */
+ { 1, 9, 12, 0, 38, 18432, 74, }, /* 168 */
+ { 69, 21, 12, 0, 0, 28672, 108, }, /* 169 */
+ { 1, 9, 12, 0, 37, 18432, 74, }, /* 170 */
+ { 1, 9, 12, 0, 64, 18432, 74, }, /* 171 */
+ { 1, 9, 12, 0, 63, 18432, 74, }, /* 172 */
+ { 1, 5, 12, 0, 0, 18432, 76, }, /* 173 */
+ { 1, 9, 12, 0, 32, 18432, 74, }, /* 174 */
+ { 1, 9, 12, 34, 32, 18432, 74, }, /* 175 */
+ { 1, 9, 12, 59, 32, 18432, 74, }, /* 176 */
+ { 1, 9, 12, 38, 32, 18432, 74, }, /* 177 */
+ { 1, 9, 12, 21, 32, 18432, 74, }, /* 178 */
+ { 1, 9, 12, 51, 32, 18432, 74, }, /* 179 */
+ { 1, 9, 12, 26, 32, 18432, 74, }, /* 180 */
+ { 1, 9, 12, 47, 32, 18432, 74, }, /* 181 */
+ { 1, 9, 12, 55, 32, 18432, 74, }, /* 182 */
+ { 1, 9, 12, 30, 32, 18432, 74, }, /* 183 */
+ { 1, 9, 12, 43, 32, 18432, 74, }, /* 184 */
+ { 1, 9, 12, 96, 32, 18432, 74, }, /* 185 */
+ { 1, 5, 12, 0, -38, 18432, 76, }, /* 186 */
+ { 1, 5, 12, 0, -37, 18432, 76, }, /* 187 */
+ { 1, 5, 12, 0, -32, 18432, 76, }, /* 188 */
+ { 1, 5, 12, 34, -32, 18432, 76, }, /* 189 */
+ { 1, 5, 12, 59, -32, 18432, 76, }, /* 190 */
+ { 1, 5, 12, 38, -32, 18432, 76, }, /* 191 */
+ { 1, 5, 12, 21, -116, 18432, 76, }, /* 192 */
+ { 1, 5, 12, 51, -32, 18432, 76, }, /* 193 */
+ { 1, 5, 12, 26, -775, 18432, 76, }, /* 194 */
+ { 1, 5, 12, 47, -32, 18432, 76, }, /* 195 */
+ { 1, 5, 12, 55, -32, 18432, 76, }, /* 196 */
+ { 1, 5, 12, 30, 1, 18432, 70, }, /* 197 */
+ { 1, 5, 12, 30, -32, 18432, 76, }, /* 198 */
+ { 1, 5, 12, 43, -32, 18432, 76, }, /* 199 */
+ { 1, 5, 12, 96, -32, 18432, 76, }, /* 200 */
+ { 1, 5, 12, 0, -64, 18432, 76, }, /* 201 */
+ { 1, 5, 12, 0, -63, 18432, 76, }, /* 202 */
+ { 1, 9, 12, 0, 8, 18432, 74, }, /* 203 */
+ { 1, 5, 12, 34, -30, 18432, 110, }, /* 204 */
+ { 1, 5, 12, 38, -25, 18432, 110, }, /* 205 */
+ { 1, 9, 12, 0, 0, 18432, 112, }, /* 206 */
+ { 1, 9, 12, 0, 0, 18432, 114, }, /* 207 */
+ { 1, 5, 12, 43, -15, 18432, 110, }, /* 208 */
+ { 1, 5, 12, 47, -22, 18432, 70, }, /* 209 */
+ { 1, 5, 12, 0, -8, 18432, 76, }, /* 210 */
+ { 34, 9, 12, 0, 1, 18432, 74, }, /* 211 */
+ { 34, 5, 12, 0, -1, 18432, 76, }, /* 212 */
+ { 1, 5, 12, 51, -54, 18432, 110, }, /* 213 */
+ { 1, 5, 12, 55, -48, 18432, 110, }, /* 214 */
+ { 1, 5, 12, 0, 7, 18432, 76, }, /* 215 */
+ { 1, 5, 12, 0, -116, 18432, 78, }, /* 216 */
+ { 1, 9, 12, 38, -60, 18432, 116, }, /* 217 */
+ { 1, 5, 12, 59, -64, 18432, 110, }, /* 218 */
+ { 1, 25, 12, 0, 0, 28672, 118, }, /* 219 */
+ { 1, 9, 12, 0, -7, 18432, 74, }, /* 220 */
+ { 1, 5, 12, 0, 0, 18432, 60, }, /* 221 */
+ { 1, 9, 12, 0, -130, 18432, 74, }, /* 222 */
+ { 2, 9, 12, 0, 80, 18432, 74, }, /* 223 */
+ { 2, 9, 12, 0, 32, 18432, 74, }, /* 224 */
+ { 2, 9, 12, 63, 32, 18432, 74, }, /* 225 */
+ { 2, 9, 12, 67, 32, 18432, 74, }, /* 226 */
+ { 2, 9, 12, 71, 32, 18432, 74, }, /* 227 */
+ { 2, 9, 12, 75, 32, 18432, 74, }, /* 228 */
+ { 2, 9, 12, 79, 32, 18432, 74, }, /* 229 */
+ { 2, 9, 12, 84, 32, 18432, 74, }, /* 230 */
+ { 2, 5, 12, 0, -32, 18432, 76, }, /* 231 */
+ { 2, 5, 12, 63, -32, 18432, 76, }, /* 232 */
+ { 2, 5, 12, 67, -32, 18432, 76, }, /* 233 */
+ { 2, 5, 12, 71, -32, 18432, 76, }, /* 234 */
+ { 2, 5, 12, 75, -32, 18432, 76, }, /* 235 */
+ { 2, 5, 12, 79, -32, 18432, 76, }, /* 236 */
+ { 2, 5, 12, 84, -32, 18432, 76, }, /* 237 */
+ { 2, 5, 12, 0, -80, 18432, 76, }, /* 238 */
+ { 2, 5, 12, 0, -80, 18432, 78, }, /* 239 */
+ { 2, 9, 12, 0, 1, 18432, 74, }, /* 240 */
+ { 2, 5, 12, 0, -1, 18432, 76, }, /* 241 */
+ { 2, 9, 12, 88, 1, 18432, 74, }, /* 242 */
+ { 2, 5, 12, 88, -1, 18432, 76, }, /* 243 */
+ { 2, 26, 12, 0, 0, 18432, 68, }, /* 244 */
+ { 2, 12, 3, 0, 0, 26684, 96, }, /* 245 */
+ { 2, 12, 3, 0, 0, 26678, 96, }, /* 246 */
+ { 84, 12, 3, 0, 0, 26681, 96, }, /* 247 */
+ { 2, 11, 3, 0, 0, 26624, 120, }, /* 248 */
+ { 2, 9, 12, 0, 15, 18432, 74, }, /* 249 */
+ { 2, 5, 12, 0, -15, 18432, 76, }, /* 250 */
+ { 70, 9, 12, 0, 48, 18432, 74, }, /* 251 */
+ { 70, 6, 12, 0, 0, 18432, 92, }, /* 252 */
+ { 70, 21, 12, 0, 0, 18432, 68, }, /* 253 */
+ { 70, 21, 12, 0, 0, 18432, 122, }, /* 254 */
+ { 70, 5, 12, 0, 0, 18432, 60, }, /* 255 */
+ { 70, 5, 12, 0, -48, 18432, 76, }, /* 256 */
+ { 70, 5, 12, 0, 0, 18432, 70, }, /* 257 */
+ { 70, 21, 12, 0, 0, 18432, 124, }, /* 258 */
+ { 70, 17, 12, 0, 0, 28672, 126, }, /* 259 */
+ { 70, 26, 12, 0, 0, 28672, 68, }, /* 260 */
+ { 70, 23, 12, 0, 0, 14336, 68, }, /* 261 */
+ { 68, 2, 12, 0, 0, 34816, 0, }, /* 262 */
+ { 71, 12, 3, 0, 0, 26624, 96, }, /* 263 */
+ { 71, 12, 3, 0, 0, 26624, 102, }, /* 264 */
+ { 71, 12, 3, 0, 0, 26624, 128, }, /* 265 */
+ { 71, 17, 12, 0, 0, 34816, 126, }, /* 266 */
+ { 71, 21, 12, 0, 0, 34816, 68, }, /* 267 */
+ { 71, 21, 12, 0, 0, 34816, 106, }, /* 268 */
+ { 71, 12, 3, 0, 0, 26624, 130, }, /* 269 */
+ { 71, 7, 12, 0, 0, 34816, 82, }, /* 270 */
+ { 71, 21, 12, 0, 0, 34816, 122, }, /* 271 */
+ { 3, 1, 4, 0, 0, 2048, 132, }, /* 272 */
+ { 69, 1, 4, 0, 0, 2048, 132, }, /* 273 */
+ { 3, 25, 12, 0, 0, 28672, 118, }, /* 274 */
+ { 3, 25, 12, 0, 0, 0, 118, }, /* 275 */
+ { 3, 21, 12, 0, 0, 14336, 68, }, /* 276 */
+ { 3, 23, 12, 0, 0, 0, 68, }, /* 277 */
+ { 69, 21, 12, 0, 0, 8342, 106, }, /* 278 */
+ { 3, 21, 12, 0, 0, 0, 68, }, /* 279 */
+ { 3, 26, 12, 0, 0, 28672, 68, }, /* 280 */
+ { 3, 12, 3, 0, 0, 26624, 130, }, /* 281 */
+ { 69, 21, 12, 0, 0, 150, 106, }, /* 282 */
+ { 3, 1, 2, 0, 0, 108, 134, }, /* 283 */
+ { 3, 21, 12, 0, 0, 0, 124, }, /* 284 */
+ { 69, 21, 12, 0, 0, 159, 124, }, /* 285 */
+ { 3, 7, 12, 0, 0, 0, 82, }, /* 286 */
+ { 69, 6, 12, 0, 0, 165, 136, }, /* 287 */
+ { 84, 12, 3, 0, 0, 26660, 128, }, /* 288 */
+ { 84, 12, 3, 0, 0, 26660, 130, }, /* 289 */
+ { 3, 12, 3, 0, 0, 26624, 128, }, /* 290 */
+ { 3, 12, 3, 0, 0, 26624, 96, }, /* 291 */
+ { 3, 13, 12, 0, 0, 2159, 138, }, /* 292 */
+ { 3, 21, 12, 0, 0, 2048, 68, }, /* 293 */
+ { 3, 7, 12, 0, 0, 0, 140, }, /* 294 */
+ { 3, 21, 12, 0, 0, 30, 124, }, /* 295 */
+ { 3, 6, 12, 0, 0, 0, 92, }, /* 296 */
+ { 3, 13, 12, 0, 0, 10240, 138, }, /* 297 */
+ { 3, 26, 12, 0, 0, 0, 68, }, /* 298 */
+ { 4, 21, 12, 0, 0, 0, 124, }, /* 299 */
+ { 4, 21, 12, 0, 0, 0, 106, }, /* 300 */
+ { 4, 21, 12, 0, 0, 0, 68, }, /* 301 */
+ { 68, 2, 12, 0, 0, 0, 0, }, /* 302 */
+ { 4, 1, 4, 0, 0, 0, 132, }, /* 303 */
+ { 4, 7, 12, 0, 0, 0, 82, }, /* 304 */
+ { 4, 12, 3, 0, 0, 26624, 130, }, /* 305 */
+ { 4, 12, 3, 0, 0, 26624, 128, }, /* 306 */
+ { 4, 12, 3, 0, 0, 26624, 96, }, /* 307 */
+ { 5, 7, 12, 0, 0, 0, 82, }, /* 308 */
+ { 5, 12, 3, 0, 0, 26624, 128, }, /* 309 */
+ { 38, 13, 12, 0, 0, 34816, 138, }, /* 310 */
+ { 38, 7, 12, 0, 0, 34816, 82, }, /* 311 */
+ { 38, 12, 3, 0, 0, 26624, 96, }, /* 312 */
+ { 38, 6, 12, 0, 0, 34816, 92, }, /* 313 */
+ { 38, 26, 12, 0, 0, 28672, 68, }, /* 314 */
+ { 38, 21, 12, 0, 0, 28672, 68, }, /* 315 */
+ { 38, 21, 12, 0, 0, 28672, 106, }, /* 316 */
+ { 38, 21, 12, 0, 0, 28672, 124, }, /* 317 */
+ { 38, 6, 12, 0, 0, 34816, 136, }, /* 318 */
+ { 38, 12, 3, 0, 0, 26624, 102, }, /* 319 */
+ { 38, 23, 12, 0, 0, 34816, 68, }, /* 320 */
+ { 110, 7, 12, 0, 0, 34816, 82, }, /* 321 */
+ { 110, 12, 3, 0, 0, 26624, 130, }, /* 322 */
+ { 110, 12, 3, 0, 0, 26624, 96, }, /* 323 */
+ { 110, 6, 12, 0, 0, 34816, 142, }, /* 324 */
+ { 110, 12, 3, 0, 0, 26624, 102, }, /* 325 */
+ { 110, 21, 12, 0, 0, 34816, 106, }, /* 326 */
+ { 110, 21, 12, 0, 0, 34816, 124, }, /* 327 */
+ { 42, 7, 12, 0, 0, 34816, 82, }, /* 328 */
+ { 42, 12, 3, 0, 0, 26624, 102, }, /* 329 */
+ { 42, 21, 12, 0, 0, 34816, 106, }, /* 330 */
+ { 3, 24, 12, 0, 0, 0, 122, }, /* 331 */
+ { 3, 12, 3, 0, 0, 26624, 102, }, /* 332 */
+ { 6, 12, 3, 0, 0, 26624, 130, }, /* 333 */
+ { 6, 10, 5, 0, 0, 18432, 144, }, /* 334 */
+ { 6, 7, 12, 0, 0, 18432, 82, }, /* 335 */
+ { 6, 12, 3, 0, 0, 26624, 96, }, /* 336 */
+ { 6, 12, 3, 0, 0, 26624, 146, }, /* 337 */
+ { 84, 12, 3, 0, 0, 26798, 96, }, /* 338 */
+ { 84, 12, 3, 0, 0, 26795, 96, }, /* 339 */
+ { 69, 21, 12, 0, 0, 18615, 124, }, /* 340 */
+ { 69, 21, 12, 0, 0, 18618, 124, }, /* 341 */
+ { 6, 13, 12, 0, 0, 18576, 138, }, /* 342 */
+ { 6, 21, 12, 0, 0, 18432, 68, }, /* 343 */
+ { 6, 6, 12, 0, 0, 18432, 92, }, /* 344 */
+ { 7, 7, 12, 0, 0, 18432, 82, }, /* 345 */
+ { 7, 12, 3, 0, 0, 26624, 130, }, /* 346 */
+ { 7, 10, 5, 0, 0, 18432, 144, }, /* 347 */
+ { 7, 12, 3, 0, 0, 26624, 96, }, /* 348 */
+ { 7, 10, 3, 0, 0, 18432, 148, }, /* 349 */
+ { 7, 12, 3, 0, 0, 26624, 146, }, /* 350 */
+ { 7, 13, 12, 0, 0, 18546, 138, }, /* 351 */
+ { 7, 23, 12, 0, 0, 14336, 68, }, /* 352 */
+ { 7, 15, 12, 0, 0, 18432, 68, }, /* 353 */
+ { 7, 26, 12, 0, 0, 18432, 68, }, /* 354 */
+ { 7, 21, 12, 0, 0, 18432, 68, }, /* 355 */
+ { 7, 12, 3, 0, 0, 26624, 102, }, /* 356 */
+ { 8, 12, 3, 0, 0, 26624, 130, }, /* 357 */
+ { 8, 10, 5, 0, 0, 18432, 144, }, /* 358 */
+ { 8, 7, 12, 0, 0, 18432, 82, }, /* 359 */
+ { 8, 12, 3, 0, 0, 26624, 96, }, /* 360 */
+ { 8, 12, 3, 0, 0, 26624, 146, }, /* 361 */
+ { 8, 13, 12, 0, 0, 18519, 138, }, /* 362 */
+ { 8, 21, 12, 0, 0, 18432, 68, }, /* 363 */
+ { 9, 12, 3, 0, 0, 26624, 130, }, /* 364 */
+ { 9, 10, 5, 0, 0, 18432, 144, }, /* 365 */
+ { 9, 7, 12, 0, 0, 18432, 82, }, /* 366 */
+ { 9, 12, 3, 0, 0, 26624, 96, }, /* 367 */
+ { 9, 12, 3, 0, 0, 26624, 146, }, /* 368 */
+ { 9, 13, 12, 0, 0, 18516, 138, }, /* 369 */
+ { 9, 21, 12, 0, 0, 18432, 68, }, /* 370 */
+ { 9, 23, 12, 0, 0, 14336, 68, }, /* 371 */
+ { 10, 12, 3, 0, 0, 26624, 130, }, /* 372 */
+ { 10, 10, 5, 0, 0, 18432, 144, }, /* 373 */
+ { 10, 7, 12, 0, 0, 18432, 82, }, /* 374 */
+ { 10, 12, 3, 0, 0, 26624, 96, }, /* 375 */
+ { 10, 10, 3, 0, 0, 18432, 148, }, /* 376 */
+ { 10, 12, 3, 0, 0, 26624, 146, }, /* 377 */
+ { 10, 12, 3, 0, 0, 26624, 150, }, /* 378 */
+ { 10, 13, 12, 0, 0, 18432, 138, }, /* 379 */
+ { 10, 26, 12, 0, 0, 18432, 68, }, /* 380 */
+ { 10, 15, 12, 0, 0, 18432, 68, }, /* 381 */
+ { 11, 12, 3, 0, 0, 26624, 130, }, /* 382 */
+ { 11, 7, 12, 0, 0, 18432, 82, }, /* 383 */
+ { 11, 10, 3, 0, 0, 18432, 148, }, /* 384 */
+ { 11, 10, 5, 0, 0, 18432, 144, }, /* 385 */
+ { 11, 12, 3, 0, 0, 26624, 146, }, /* 386 */
+ { 11, 13, 12, 0, 0, 18513, 138, }, /* 387 */
+ { 11, 15, 12, 0, 0, 18513, 68, }, /* 388 */
+ { 11, 26, 12, 0, 0, 28753, 68, }, /* 389 */
+ { 11, 26, 12, 0, 0, 28672, 68, }, /* 390 */
+ { 11, 23, 12, 0, 0, 14336, 68, }, /* 391 */
+ { 12, 12, 3, 0, 0, 26624, 130, }, /* 392 */
+ { 12, 10, 5, 0, 0, 18432, 144, }, /* 393 */
+ { 12, 12, 3, 0, 0, 26624, 102, }, /* 394 */
+ { 12, 7, 12, 0, 0, 18432, 82, }, /* 395 */
+ { 12, 12, 3, 0, 0, 26624, 96, }, /* 396 */
+ { 12, 12, 3, 0, 0, 26624, 146, }, /* 397 */
+ { 12, 13, 12, 0, 0, 18432, 138, }, /* 398 */
+ { 12, 21, 12, 0, 0, 18432, 68, }, /* 399 */
+ { 12, 15, 12, 0, 0, 28672, 68, }, /* 400 */
+ { 12, 26, 12, 0, 0, 18432, 68, }, /* 401 */
+ { 13, 7, 12, 0, 0, 18432, 82, }, /* 402 */
+ { 13, 12, 3, 0, 0, 26624, 130, }, /* 403 */
+ { 13, 10, 5, 0, 0, 18432, 144, }, /* 404 */
+ { 13, 21, 12, 0, 0, 18432, 68, }, /* 405 */
+ { 13, 12, 3, 0, 0, 26624, 96, }, /* 406 */
+ { 13, 12, 3, 0, 0, 18432, 130, }, /* 407 */
+ { 13, 10, 3, 0, 0, 18432, 148, }, /* 408 */
+ { 13, 12, 3, 0, 0, 26624, 146, }, /* 409 */
+ { 13, 13, 12, 0, 0, 18528, 138, }, /* 410 */
+ { 14, 12, 3, 0, 0, 26624, 130, }, /* 411 */
+ { 14, 10, 5, 0, 0, 18432, 144, }, /* 412 */
+ { 14, 7, 12, 0, 0, 18432, 82, }, /* 413 */
+ { 14, 12, 3, 0, 0, 26624, 146, }, /* 414 */
+ { 14, 10, 3, 0, 0, 18432, 148, }, /* 415 */
+ { 14, 7, 4, 0, 0, 18432, 82, }, /* 416 */
+ { 14, 26, 12, 0, 0, 18432, 68, }, /* 417 */
+ { 14, 15, 12, 0, 0, 18432, 68, }, /* 418 */
+ { 14, 13, 12, 0, 0, 18432, 138, }, /* 419 */
+ { 15, 12, 3, 0, 0, 26624, 130, }, /* 420 */
+ { 15, 10, 5, 0, 0, 18432, 144, }, /* 421 */
+ { 15, 7, 12, 0, 0, 18432, 82, }, /* 422 */
+ { 15, 12, 3, 0, 0, 26624, 146, }, /* 423 */
+ { 15, 10, 3, 0, 0, 18432, 148, }, /* 424 */
+ { 15, 13, 12, 0, 0, 18432, 138, }, /* 425 */
+ { 15, 21, 12, 0, 0, 18432, 68, }, /* 426 */
+ { 72, 7, 12, 0, 0, 18432, 82, }, /* 427 */
+ { 72, 12, 3, 0, 0, 26624, 130, }, /* 428 */
+ { 72, 7, 5, 0, 0, 18432, 152, }, /* 429 */
+ { 72, 12, 3, 0, 0, 26624, 154, }, /* 430 */
+ { 69, 23, 12, 0, 0, 14336, 68, }, /* 431 */
+ { 72, 7, 12, 0, 0, 18432, 156, }, /* 432 */
+ { 72, 6, 12, 0, 0, 18432, 136, }, /* 433 */
+ { 72, 12, 3, 0, 0, 26624, 96, }, /* 434 */
+ { 72, 21, 12, 0, 0, 18432, 68, }, /* 435 */
+ { 72, 13, 12, 0, 0, 18432, 138, }, /* 436 */
+ { 72, 21, 12, 0, 0, 18432, 106, }, /* 437 */
+ { 73, 7, 12, 0, 0, 18432, 82, }, /* 438 */
+ { 73, 12, 3, 0, 0, 26624, 130, }, /* 439 */
+ { 73, 7, 5, 0, 0, 18432, 152, }, /* 440 */
+ { 73, 12, 3, 0, 0, 26624, 146, }, /* 441 */
+ { 73, 7, 12, 0, 0, 18432, 156, }, /* 442 */
+ { 73, 6, 12, 0, 0, 18432, 136, }, /* 443 */
+ { 73, 12, 3, 0, 0, 26624, 96, }, /* 444 */
+ { 73, 13, 12, 0, 0, 18432, 138, }, /* 445 */
+ { 74, 7, 12, 0, 0, 18432, 82, }, /* 446 */
+ { 74, 26, 12, 0, 0, 18432, 68, }, /* 447 */
+ { 74, 21, 12, 0, 0, 18432, 68, }, /* 448 */
+ { 74, 21, 12, 0, 0, 18432, 106, }, /* 449 */
+ { 74, 12, 3, 0, 0, 26624, 96, }, /* 450 */
+ { 74, 13, 12, 0, 0, 18432, 138, }, /* 451 */
+ { 74, 15, 12, 0, 0, 18432, 68, }, /* 452 */
+ { 74, 22, 12, 0, 0, 28672, 158, }, /* 453 */
+ { 74, 18, 12, 0, 0, 28672, 158, }, /* 454 */
+ { 74, 10, 5, 0, 0, 18432, 160, }, /* 455 */
+ { 74, 12, 3, 0, 0, 26624, 130, }, /* 456 */
+ { 74, 12, 3, 0, 0, 26624, 162, }, /* 457 */
+ { 74, 10, 5, 0, 0, 18432, 144, }, /* 458 */
+ { 74, 12, 3, 0, 0, 26624, 146, }, /* 459 */
+ { 69, 26, 12, 0, 0, 18432, 68, }, /* 460 */
+ { 16, 7, 12, 0, 0, 18432, 82, }, /* 461 */
+ { 16, 10, 12, 0, 0, 18432, 144, }, /* 462 */
+ { 16, 12, 3, 0, 0, 26624, 130, }, /* 463 */
+ { 16, 10, 5, 0, 0, 18432, 144, }, /* 464 */
+ { 16, 12, 3, 0, 0, 26624, 96, }, /* 465 */
+ { 16, 12, 3, 0, 0, 26624, 146, }, /* 466 */
+ { 16, 13, 12, 0, 0, 18549, 138, }, /* 467 */
+ { 16, 21, 12, 0, 0, 18432, 124, }, /* 468 */
+ { 16, 21, 12, 0, 0, 18432, 68, }, /* 469 */
+ { 16, 10, 12, 0, 0, 18432, 164, }, /* 470 */
+ { 16, 12, 3, 0, 0, 26624, 128, }, /* 471 */
+ { 16, 13, 12, 0, 0, 18432, 138, }, /* 472 */
+ { 16, 26, 12, 0, 0, 18432, 68, }, /* 473 */
+ { 17, 9, 12, 0, 7264, 18432, 74, }, /* 474 */
+ { 17, 5, 12, 0, 3008, 18432, 166, }, /* 475 */
+ { 69, 21, 12, 0, 0, 18510, 68, }, /* 476 */
+ { 17, 6, 12, 0, 0, 18432, 142, }, /* 477 */
+ { 18, 7, 6, 0, 0, 18432, 82, }, /* 478 */
+ { 18, 7, 6, 0, 0, 18432, 168, }, /* 479 */
+ { 18, 7, 7, 0, 0, 18432, 168, }, /* 480 */
+ { 18, 7, 7, 0, 0, 18432, 82, }, /* 481 */
+ { 18, 7, 8, 0, 0, 18432, 82, }, /* 482 */
+ { 75, 7, 12, 0, 0, 18432, 82, }, /* 483 */
+ { 75, 12, 3, 0, 0, 26624, 96, }, /* 484 */
+ { 75, 21, 12, 0, 0, 18432, 68, }, /* 485 */
+ { 75, 21, 12, 0, 0, 18432, 106, }, /* 486 */
+ { 75, 21, 12, 0, 0, 18432, 124, }, /* 487 */
+ { 75, 15, 12, 0, 0, 18432, 138, }, /* 488 */
+ { 75, 15, 12, 0, 0, 18432, 68, }, /* 489 */
+ { 75, 26, 12, 0, 0, 28672, 68, }, /* 490 */
+ { 76, 9, 12, 0, 38864, 18432, 170, }, /* 491 */
+ { 76, 9, 12, 0, 8, 18432, 170, }, /* 492 */
+ { 76, 5, 12, 0, -8, 18432, 70, }, /* 493 */
+ { 77, 17, 12, 0, 0, 28672, 126, }, /* 494 */
+ { 77, 7, 12, 0, 0, 18432, 82, }, /* 495 */
+ { 77, 26, 12, 0, 0, 18432, 68, }, /* 496 */
+ { 77, 21, 12, 0, 0, 18432, 124, }, /* 497 */
+ { 78, 29, 12, 0, 0, 45056, 52, }, /* 498 */
+ { 78, 7, 12, 0, 0, 18432, 82, }, /* 499 */
+ { 78, 22, 12, 0, 0, 28672, 158, }, /* 500 */
+ { 78, 18, 12, 0, 0, 28672, 158, }, /* 501 */
+ { 79, 7, 12, 0, 0, 18432, 82, }, /* 502 */
+ { 69, 21, 12, 0, 0, 18432, 106, }, /* 503 */
+ { 79, 14, 12, 0, 0, 18432, 82, }, /* 504 */
+ { 25, 7, 12, 0, 0, 18432, 82, }, /* 505 */
+ { 25, 12, 3, 0, 0, 26624, 130, }, /* 506 */
+ { 25, 12, 3, 0, 0, 26624, 146, }, /* 507 */
+ { 25, 10, 5, 0, 0, 18432, 172, }, /* 508 */
+ { 26, 7, 12, 0, 0, 18432, 82, }, /* 509 */
+ { 26, 12, 3, 0, 0, 26624, 130, }, /* 510 */
+ { 26, 10, 5, 0, 0, 18432, 174, }, /* 511 */
+ { 69, 21, 12, 0, 0, 18573, 124, }, /* 512 */
+ { 27, 7, 12, 0, 0, 18432, 82, }, /* 513 */
+ { 27, 12, 3, 0, 0, 26624, 130, }, /* 514 */
+ { 28, 7, 12, 0, 0, 18432, 82, }, /* 515 */
+ { 28, 12, 3, 0, 0, 26624, 130, }, /* 516 */
+ { 80, 7, 12, 0, 0, 18432, 82, }, /* 517 */
+ { 80, 7, 12, 0, 0, 18432, 140, }, /* 518 */
+ { 80, 12, 3, 0, 0, 26624, 100, }, /* 519 */
+ { 80, 10, 5, 0, 0, 18432, 144, }, /* 520 */
+ { 80, 12, 3, 0, 0, 26624, 130, }, /* 521 */
+ { 80, 12, 3, 0, 0, 26624, 96, }, /* 522 */
+ { 80, 12, 3, 0, 0, 26624, 146, }, /* 523 */
+ { 80, 21, 12, 0, 0, 18432, 106, }, /* 524 */
+ { 80, 6, 12, 0, 0, 18432, 142, }, /* 525 */
+ { 80, 21, 12, 0, 0, 18432, 68, }, /* 526 */
+ { 80, 23, 12, 0, 0, 14336, 68, }, /* 527 */
+ { 80, 13, 12, 0, 0, 18432, 138, }, /* 528 */
+ { 80, 15, 12, 0, 0, 28672, 68, }, /* 529 */
+ { 19, 21, 12, 0, 0, 28672, 68, }, /* 530 */
+ { 69, 21, 12, 0, 0, 28777, 106, }, /* 531 */
+ { 69, 21, 12, 0, 0, 28777, 124, }, /* 532 */
+ { 19, 21, 12, 0, 0, 28672, 106, }, /* 533 */
+ { 19, 17, 12, 0, 0, 28672, 126, }, /* 534 */
+ { 19, 21, 12, 0, 0, 28672, 124, }, /* 535 */
+ { 19, 21, 12, 0, 0, 28672, 176, }, /* 536 */
+ { 19, 12, 3, 0, 0, 26624, 178, }, /* 537 */
+ { 19, 1, 2, 0, 0, 6144, 66, }, /* 538 */
+ { 19, 13, 12, 0, 0, 18432, 138, }, /* 539 */
+ { 19, 7, 12, 0, 0, 18432, 82, }, /* 540 */
+ { 19, 6, 12, 0, 0, 18432, 136, }, /* 541 */
+ { 19, 12, 3, 0, 0, 26624, 180, }, /* 542 */
+ { 19, 12, 3, 0, 0, 26624, 130, }, /* 543 */
+ { 29, 7, 12, 0, 0, 18432, 82, }, /* 544 */
+ { 29, 12, 3, 0, 0, 26624, 130, }, /* 545 */
+ { 29, 10, 5, 0, 0, 18432, 144, }, /* 546 */
+ { 29, 12, 3, 0, 0, 26624, 96, }, /* 547 */
+ { 29, 26, 12, 0, 0, 28672, 68, }, /* 548 */
+ { 29, 21, 12, 0, 0, 28672, 124, }, /* 549 */
+ { 29, 13, 12, 0, 0, 18432, 138, }, /* 550 */
+ { 30, 7, 12, 0, 0, 18432, 82, }, /* 551 */
+ { 89, 7, 12, 0, 0, 18432, 82, }, /* 552 */
+ { 89, 7, 12, 0, 0, 18432, 156, }, /* 553 */
+ { 89, 13, 12, 0, 0, 18432, 138, }, /* 554 */
+ { 89, 15, 12, 0, 0, 18432, 138, }, /* 555 */
+ { 89, 26, 12, 0, 0, 28672, 68, }, /* 556 */
+ { 80, 26, 12, 0, 0, 28672, 68, }, /* 557 */
+ { 33, 7, 12, 0, 0, 18432, 82, }, /* 558 */
+ { 33, 12, 3, 0, 0, 26624, 130, }, /* 559 */
+ { 33, 10, 5, 0, 0, 18432, 144, }, /* 560 */
+ { 33, 21, 12, 0, 0, 18432, 68, }, /* 561 */
+ { 106, 7, 12, 0, 0, 18432, 82, }, /* 562 */
+ { 106, 10, 5, 0, 0, 18432, 144, }, /* 563 */
+ { 106, 12, 3, 0, 0, 26624, 130, }, /* 564 */
+ { 106, 12, 3, 0, 0, 26624, 182, }, /* 565 */
+ { 106, 10, 12, 0, 0, 18432, 144, }, /* 566 */
+ { 106, 12, 3, 0, 0, 26624, 96, }, /* 567 */
+ { 106, 13, 12, 0, 0, 18432, 138, }, /* 568 */
+ { 106, 21, 12, 0, 0, 18432, 68, }, /* 569 */
+ { 106, 6, 12, 0, 0, 18432, 136, }, /* 570 */
+ { 106, 21, 12, 0, 0, 18432, 124, }, /* 571 */
+ { 84, 11, 3, 0, 0, 26624, 184, }, /* 572 */
+ { 84, 12, 3, 0, 0, 26624, 130, }, /* 573 */
+ { 93, 12, 3, 0, 0, 26624, 130, }, /* 574 */
+ { 93, 10, 5, 0, 0, 18432, 144, }, /* 575 */
+ { 93, 7, 12, 0, 0, 18432, 82, }, /* 576 */
+ { 93, 12, 3, 0, 0, 26624, 96, }, /* 577 */
+ { 93, 10, 3, 0, 0, 18432, 148, }, /* 578 */
+ { 93, 10, 5, 0, 0, 18432, 172, }, /* 579 */
+ { 93, 13, 12, 0, 0, 18432, 138, }, /* 580 */
+ { 93, 21, 12, 0, 0, 18432, 124, }, /* 581 */
+ { 93, 21, 12, 0, 0, 18432, 68, }, /* 582 */
+ { 93, 21, 12, 0, 0, 18432, 106, }, /* 583 */
+ { 93, 26, 12, 0, 0, 18432, 68, }, /* 584 */
+ { 96, 12, 3, 0, 0, 26624, 130, }, /* 585 */
+ { 96, 10, 5, 0, 0, 18432, 144, }, /* 586 */
+ { 96, 7, 12, 0, 0, 18432, 82, }, /* 587 */
+ { 96, 10, 5, 0, 0, 18432, 172, }, /* 588 */
+ { 96, 12, 3, 0, 0, 26624, 146, }, /* 589 */
+ { 96, 13, 12, 0, 0, 18432, 138, }, /* 590 */
+ { 119, 7, 12, 0, 0, 18432, 82, }, /* 591 */
+ { 119, 12, 3, 0, 0, 26624, 102, }, /* 592 */
+ { 119, 10, 5, 0, 0, 18432, 144, }, /* 593 */
+ { 119, 12, 3, 0, 0, 26624, 130, }, /* 594 */
+ { 119, 10, 5, 0, 0, 18432, 174, }, /* 595 */
+ { 119, 21, 12, 0, 0, 18432, 68, }, /* 596 */
+ { 97, 7, 12, 0, 0, 18432, 82, }, /* 597 */
+ { 97, 10, 5, 0, 0, 18432, 144, }, /* 598 */
+ { 97, 12, 3, 0, 0, 26624, 130, }, /* 599 */
+ { 97, 12, 3, 0, 0, 26624, 186, }, /* 600 */
+ { 97, 12, 3, 0, 0, 26624, 96, }, /* 601 */
+ { 97, 21, 12, 0, 0, 18432, 124, }, /* 602 */
+ { 97, 21, 12, 0, 0, 18432, 106, }, /* 603 */
+ { 97, 13, 12, 0, 0, 18432, 138, }, /* 604 */
+ { 98, 13, 12, 0, 0, 18432, 138, }, /* 605 */
+ { 98, 7, 12, 0, 0, 18432, 82, }, /* 606 */
+ { 98, 6, 12, 0, 0, 18432, 92, }, /* 607 */
+ { 98, 6, 12, 0, 0, 18432, 94, }, /* 608 */
+ { 98, 21, 12, 0, 0, 18432, 124, }, /* 609 */
+ { 2, 5, 12, 63, -6222, 18432, 70, }, /* 610 */
+ { 2, 5, 12, 67, -6221, 18432, 70, }, /* 611 */
+ { 2, 5, 12, 71, -6212, 18432, 70, }, /* 612 */
+ { 2, 5, 12, 75, -6210, 18432, 70, }, /* 613 */
+ { 2, 5, 12, 79, -6210, 18432, 70, }, /* 614 */
+ { 2, 5, 12, 79, -6211, 18432, 70, }, /* 615 */
+ { 2, 5, 12, 84, -6204, 18432, 70, }, /* 616 */
+ { 2, 5, 12, 88, -6180, 18432, 70, }, /* 617 */
+ { 2, 5, 12, 108, 35267, 18432, 70, }, /* 618 */
+ { 17, 9, 12, 0, -3008, 18432, 74, }, /* 619 */
+ { 96, 21, 12, 0, 0, 18432, 68, }, /* 620 */
+ { 84, 12, 3, 0, 0, 26762, 96, }, /* 621 */
+ { 84, 12, 3, 0, 0, 26630, 96, }, /* 622 */
+ { 69, 21, 12, 0, 0, 18498, 188, }, /* 623 */
+ { 84, 12, 3, 0, 0, 26666, 96, }, /* 624 */
+ { 84, 12, 3, 0, 0, 26696, 96, }, /* 625 */
+ { 84, 12, 3, 0, 0, 26780, 96, }, /* 626 */
+ { 69, 10, 5, 0, 0, 18474, 160, }, /* 627 */
+ { 69, 7, 12, 0, 0, 18501, 82, }, /* 628 */
+ { 69, 7, 12, 0, 0, 18474, 82, }, /* 629 */
+ { 69, 7, 12, 0, 0, 18438, 82, }, /* 630 */
+ { 69, 7, 12, 0, 0, 18594, 82, }, /* 631 */
+ { 69, 7, 12, 0, 0, 18498, 82, }, /* 632 */
+ { 84, 12, 3, 0, 0, 26750, 96, }, /* 633 */
+ { 69, 10, 5, 0, 0, 18435, 160, }, /* 634 */
+ { 84, 12, 3, 0, 0, 26690, 96, }, /* 635 */
+ { 69, 7, 12, 0, 0, 18453, 82, }, /* 636 */
+ { 2, 5, 12, 0, 0, 18432, 60, }, /* 637 */
+ { 1, 6, 12, 0, 0, 18432, 88, }, /* 638 */
+ { 2, 6, 12, 0, 0, 18432, 190, }, /* 639 */
+ { 0, 5, 12, 0, 35332, 18432, 76, }, /* 640 */
+ { 0, 5, 12, 0, 3814, 18432, 76, }, /* 641 */
+ { 0, 5, 12, 0, 35384, 18432, 76, }, /* 642 */
+ { 0, 5, 12, 0, 0, 18432, 192, }, /* 643 */
+ { 0, 6, 12, 0, 0, 18432, 190, }, /* 644 */
+ { 0, 6, 12, 0, 0, 18432, 194, }, /* 645 */
+ { 1, 6, 12, 0, 0, 18432, 190, }, /* 646 */
+ { 84, 12, 3, 0, 0, 26636, 102, }, /* 647 */
+ { 84, 12, 3, 0, 0, 26687, 96, }, /* 648 */
+ { 84, 12, 3, 0, 0, 26648, 96, }, /* 649 */
+ { 0, 9, 12, 92, 1, 18432, 74, }, /* 650 */
+ { 0, 5, 12, 92, -1, 18432, 76, }, /* 651 */
+ { 0, 5, 12, 0, 0, 18432, 70, }, /* 652 */
+ { 0, 5, 12, 92, -58, 18432, 70, }, /* 653 */
+ { 0, 9, 12, 0, -7615, 18432, 74, }, /* 654 */
+ { 1, 5, 12, 0, 8, 18432, 76, }, /* 655 */
+ { 1, 9, 12, 0, -8, 18432, 74, }, /* 656 */
+ { 1, 5, 12, 0, 74, 18432, 76, }, /* 657 */
+ { 1, 5, 12, 0, 86, 18432, 76, }, /* 658 */
+ { 1, 5, 12, 0, 100, 18432, 76, }, /* 659 */
+ { 1, 5, 12, 0, 128, 18432, 76, }, /* 660 */
+ { 1, 5, 12, 0, 112, 18432, 76, }, /* 661 */
+ { 1, 5, 12, 0, 126, 18432, 76, }, /* 662 */
+ { 1, 5, 12, 0, 8, 18432, 70, }, /* 663 */
+ { 1, 8, 12, 0, -8, 18432, 86, }, /* 664 */
+ { 1, 5, 12, 0, 0, 18432, 70, }, /* 665 */
+ { 1, 5, 12, 0, 9, 18432, 70, }, /* 666 */
+ { 1, 9, 12, 0, -74, 18432, 74, }, /* 667 */
+ { 1, 8, 12, 0, -9, 18432, 86, }, /* 668 */
+ { 1, 5, 12, 21, -7173, 18432, 76, }, /* 669 */
+ { 1, 9, 12, 0, -86, 18432, 74, }, /* 670 */
+ { 1, 9, 12, 0, -100, 18432, 74, }, /* 671 */
+ { 1, 9, 12, 0, -112, 18432, 74, }, /* 672 */
+ { 1, 9, 12, 0, -128, 18432, 74, }, /* 673 */
+ { 1, 9, 12, 0, -126, 18432, 74, }, /* 674 */
+ { 69, 29, 12, 0, 0, 45056, 52, }, /* 675 */
+ { 84, 1, 3, 0, 0, 6144, 196, }, /* 676 */
+ { 84, 1, 13, 0, 0, 6144, 198, }, /* 677 */
+ { 69, 1, 2, 0, 0, 18432, 200, }, /* 678 */
+ { 69, 1, 2, 0, 0, 34816, 200, }, /* 679 */
+ { 69, 17, 12, 0, 0, 28672, 202, }, /* 680 */
+ { 69, 21, 12, 0, 0, 28672, 64, }, /* 681 */
+ { 69, 20, 12, 0, 0, 28672, 204, }, /* 682 */
+ { 69, 19, 12, 0, 0, 28672, 204, }, /* 683 */
+ { 69, 22, 12, 0, 0, 28672, 206, }, /* 684 */
+ { 69, 20, 12, 0, 0, 28672, 206, }, /* 685 */
+ { 69, 19, 12, 0, 0, 28672, 206, }, /* 686 */
+ { 69, 21, 12, 0, 0, 28672, 208, }, /* 687 */
+ { 69, 27, 2, 0, 0, 45056, 50, }, /* 688 */
+ { 69, 28, 2, 0, 0, 4096, 50, }, /* 689 */
+ { 69, 1, 2, 0, 0, 20480, 134, }, /* 690 */
+ { 69, 1, 2, 0, 0, 36864, 134, }, /* 691 */
+ { 69, 1, 2, 0, 0, 30720, 134, }, /* 692 */
+ { 69, 1, 2, 0, 0, 24576, 134, }, /* 693 */
+ { 69, 1, 2, 0, 0, 40960, 134, }, /* 694 */
+ { 69, 29, 12, 0, 0, 8291, 52, }, /* 695 */
+ { 69, 21, 12, 0, 0, 14336, 54, }, /* 696 */
+ { 69, 21, 12, 0, 0, 14336, 64, }, /* 697 */
+ { 69, 21, 14, 0, 0, 28672, 210, }, /* 698 */
+ { 69, 21, 12, 0, 0, 28672, 212, }, /* 699 */
+ { 69, 16, 12, 0, 0, 28672, 138, }, /* 700 */
+ { 69, 16, 12, 0, 0, 28672, 214, }, /* 701 */
+ { 69, 25, 12, 0, 0, 8192, 64, }, /* 702 */
+ { 69, 22, 12, 0, 0, 28672, 216, }, /* 703 */
+ { 69, 18, 12, 0, 0, 28672, 216, }, /* 704 */
+ { 69, 21, 12, 0, 0, 28672, 202, }, /* 705 */
+ { 69, 1, 2, 0, 0, 6144, 218, }, /* 706 */
+ { 68, 2, 2, 0, 0, 6144, 220, }, /* 707 */
+ { 69, 1, 2, 0, 0, 22528, 134, }, /* 708 */
+ { 69, 1, 2, 0, 0, 38912, 134, }, /* 709 */
+ { 69, 1, 2, 0, 0, 16384, 134, }, /* 710 */
+ { 69, 1, 2, 0, 0, 32768, 134, }, /* 711 */
+ { 69, 1, 2, 0, 0, 6144, 222, }, /* 712 */
+ { 69, 25, 12, 0, 0, 12288, 118, }, /* 713 */
+ { 69, 25, 12, 0, 0, 12288, 224, }, /* 714 */
+ { 69, 25, 12, 0, 0, 28672, 118, }, /* 715 */
+ { 69, 22, 12, 0, 0, 28672, 226, }, /* 716 */
+ { 69, 18, 12, 0, 0, 28672, 226, }, /* 717 */
+ { 68, 2, 12, 0, 0, 14336, 0, }, /* 718 */
+ { 84, 12, 3, 0, 0, 26624, 228, }, /* 719 */
+ { 84, 11, 3, 0, 0, 26624, 120, }, /* 720 */
+ { 84, 11, 3, 0, 0, 26624, 230, }, /* 721 */
+ { 84, 12, 3, 0, 0, 26753, 102, }, /* 722 */
+ { 69, 26, 12, 0, 0, 28672, 68, }, /* 723 */
+ { 69, 9, 12, 0, 0, 18432, 112, }, /* 724 */
+ { 69, 5, 12, 0, 0, 18432, 232, }, /* 725 */
+ { 69, 25, 12, 0, 0, 28672, 234, }, /* 726 */
+ { 69, 26, 14, 0, 0, 28672, 236, }, /* 727 */
+ { 1, 9, 12, 96, -7517, 18432, 74, }, /* 728 */
+ { 69, 26, 12, 0, 0, 28672, 118, }, /* 729 */
+ { 0, 9, 12, 100, -8383, 18432, 74, }, /* 730 */
+ { 0, 9, 12, 104, -8262, 18432, 74, }, /* 731 */
+ { 69, 26, 12, 0, 0, 14336, 238, }, /* 732 */
+ { 0, 9, 12, 0, 28, 18432, 74, }, /* 733 */
+ { 69, 7, 12, 0, 0, 18432, 240, }, /* 734 */
+ { 69, 5, 14, 0, 0, 18432, 242, }, /* 735 */
+ { 69, 5, 12, 0, 0, 18432, 244, }, /* 736 */
+ { 0, 5, 12, 0, -28, 18432, 76, }, /* 737 */
+ { 0, 14, 12, 0, 16, 18432, 74, }, /* 738 */
+ { 0, 14, 12, 0, -16, 18432, 76, }, /* 739 */
+ { 0, 14, 12, 0, 0, 18432, 82, }, /* 740 */
+ { 69, 25, 14, 0, 0, 28672, 246, }, /* 741 */
+ { 69, 26, 14, 0, 0, 28672, 246, }, /* 742 */
+ { 69, 26, 12, 0, 0, 28672, 64, }, /* 743 */
+ { 69, 25, 12, 0, 0, 28672, 248, }, /* 744 */
+ { 69, 25, 12, 0, 0, 12288, 250, }, /* 745 */
+ { 69, 22, 12, 0, 0, 28672, 248, }, /* 746 */
+ { 69, 18, 12, 0, 0, 28672, 248, }, /* 747 */
+ { 69, 26, 14, 0, 0, 28672, 252, }, /* 748 */
+ { 69, 22, 12, 0, 0, 28672, 254, }, /* 749 */
+ { 69, 18, 12, 0, 0, 28672, 254, }, /* 750 */
+ { 69, 26, 12, 0, 0, 18432, 54, }, /* 751 */
+ { 69, 26, 14, 0, 0, 28672, 256, }, /* 752 */
+ { 68, 2, 12, 0, 0, 18432, 258, }, /* 753 */
+ { 69, 26, 12, 0, 26, 18432, 260, }, /* 754 */
+ { 69, 26, 14, 0, 26, 18432, 262, }, /* 755 */
+ { 69, 26, 12, 0, -26, 18432, 264, }, /* 756 */
+ { 69, 25, 14, 0, 0, 28672, 266, }, /* 757 */
+ { 69, 26, 14, 0, 0, 28672, 268, }, /* 758 */
+ { 69, 26, 14, 0, 0, 28672, 270, }, /* 759 */
+ { 69, 25, 14, 0, 0, 28672, 268, }, /* 760 */
+ { 69, 26, 14, 0, 0, 18432, 256, }, /* 761 */
+ { 69, 26, 14, 0, 0, 28672, 272, }, /* 762 */
+ { 88, 26, 12, 0, 0, 18432, 54, }, /* 763 */
+ { 69, 26, 12, 0, 0, 28672, 216, }, /* 764 */
+ { 35, 9, 12, 0, 48, 18432, 74, }, /* 765 */
+ { 35, 5, 12, 0, -48, 18432, 76, }, /* 766 */
+ { 0, 9, 12, 0, -10743, 18432, 74, }, /* 767 */
+ { 0, 9, 12, 0, -3814, 18432, 74, }, /* 768 */
+ { 0, 9, 12, 0, -10727, 18432, 74, }, /* 769 */
+ { 0, 5, 12, 0, -10795, 18432, 76, }, /* 770 */
+ { 0, 5, 12, 0, -10792, 18432, 76, }, /* 771 */
+ { 0, 9, 12, 0, -10780, 18432, 74, }, /* 772 */
+ { 0, 9, 12, 0, -10749, 18432, 74, }, /* 773 */
+ { 0, 9, 12, 0, -10783, 18432, 74, }, /* 774 */
+ { 0, 9, 12, 0, -10782, 18432, 74, }, /* 775 */
+ { 0, 9, 12, 0, -10815, 18432, 74, }, /* 776 */
+ { 34, 5, 12, 0, 0, 18432, 60, }, /* 777 */
+ { 34, 26, 12, 0, 0, 28672, 68, }, /* 778 */
+ { 34, 12, 3, 0, 0, 26624, 96, }, /* 779 */
+ { 34, 21, 12, 0, 0, 28672, 68, }, /* 780 */
+ { 34, 15, 12, 0, 0, 28672, 68, }, /* 781 */
+ { 17, 5, 12, 0, -7264, 18432, 76, }, /* 782 */
+ { 90, 7, 12, 0, 0, 18432, 82, }, /* 783 */
+ { 90, 6, 12, 0, 0, 18432, 142, }, /* 784 */
+ { 90, 21, 12, 0, 0, 18432, 68, }, /* 785 */
+ { 90, 12, 3, 0, 0, 26624, 182, }, /* 786 */
+ { 2, 12, 3, 0, 0, 26624, 130, }, /* 787 */
+ { 69, 20, 12, 0, 0, 28672, 216, }, /* 788 */
+ { 69, 19, 12, 0, 0, 28672, 216, }, /* 789 */
+ { 69, 6, 12, 0, 0, 28672, 274, }, /* 790 */
+ { 69, 21, 12, 0, 0, 28672, 276, }, /* 791 */
+ { 69, 21, 12, 0, 0, 28726, 54, }, /* 792 */
+ { 23, 26, 12, 0, 0, 28672, 278, }, /* 793 */
+ { 69, 26, 12, 0, 0, 28672, 280, }, /* 794 */
+ { 69, 26, 12, 0, 0, 28672, 282, }, /* 795 */
+ { 69, 21, 12, 0, 0, 28825, 276, }, /* 796 */
+ { 69, 21, 12, 0, 0, 28825, 212, }, /* 797 */
+ { 69, 21, 12, 0, 0, 28819, 54, }, /* 798 */
+ { 23, 6, 12, 0, 0, 18432, 136, }, /* 799 */
+ { 69, 7, 12, 0, 0, 18447, 284, }, /* 800 */
+ { 23, 14, 12, 0, 0, 18432, 284, }, /* 801 */
+ { 69, 22, 12, 0, 0, 28825, 216, }, /* 802 */
+ { 69, 18, 12, 0, 0, 28825, 216, }, /* 803 */
+ { 69, 22, 12, 0, 0, 28825, 62, }, /* 804 */
+ { 69, 18, 12, 0, 0, 28825, 62, }, /* 805 */
+ { 69, 26, 12, 0, 0, 28819, 54, }, /* 806 */
+ { 69, 17, 12, 0, 0, 28819, 202, }, /* 807 */
+ { 69, 22, 12, 0, 0, 28819, 206, }, /* 808 */
+ { 69, 18, 12, 0, 0, 28819, 206, }, /* 809 */
+ { 84, 12, 3, 0, 0, 26669, 96, }, /* 810 */
+ { 18, 10, 3, 0, 0, 18432, 286, }, /* 811 */
+ { 69, 17, 14, 0, 0, 28819, 288, }, /* 812 */
+ { 69, 6, 12, 0, 0, 18525, 136, }, /* 813 */
+ { 69, 26, 12, 0, 0, 28819, 68, }, /* 814 */
+ { 23, 6, 12, 0, 0, 18432, 142, }, /* 815 */
+ { 69, 7, 12, 0, 0, 18564, 82, }, /* 816 */
+ { 69, 21, 14, 0, 0, 28804, 236, }, /* 817 */
+ { 69, 26, 12, 0, 0, 28687, 68, }, /* 818 */
+ { 20, 7, 12, 0, 0, 18432, 82, }, /* 819 */
+ { 84, 12, 3, 0, 0, 26717, 96, }, /* 820 */
+ { 69, 24, 12, 0, 0, 28765, 290, }, /* 821 */
+ { 20, 6, 12, 0, 0, 18432, 136, }, /* 822 */
+ { 69, 17, 12, 0, 0, 28765, 126, }, /* 823 */
+ { 21, 7, 12, 0, 0, 18432, 82, }, /* 824 */
+ { 69, 21, 12, 0, 0, 28825, 68, }, /* 825 */
+ { 69, 6, 12, 0, 0, 18525, 94, }, /* 826 */
+ { 21, 6, 12, 0, 0, 18432, 136, }, /* 827 */
+ { 22, 7, 12, 0, 0, 18432, 82, }, /* 828 */
+ { 18, 7, 12, 0, 0, 18432, 82, }, /* 829 */
+ { 18, 7, 12, 0, 0, 18432, 168, }, /* 830 */
+ { 69, 26, 12, 0, 0, 18447, 68, }, /* 831 */
+ { 69, 15, 12, 0, 0, 18447, 68, }, /* 832 */
+ { 18, 26, 12, 0, 0, 18432, 68, }, /* 833 */
+ { 18, 26, 12, 0, 0, 28672, 68, }, /* 834 */
+ { 69, 15, 12, 0, 0, 18432, 68, }, /* 835 */
+ { 69, 26, 14, 0, 0, 18447, 236, }, /* 836 */
+ { 21, 26, 12, 0, 0, 18432, 68, }, /* 837 */
+ { 23, 7, 12, 0, 0, 18432, 292, }, /* 838 */
+ { 24, 7, 12, 0, 0, 18432, 82, }, /* 839 */
+ { 24, 6, 12, 0, 0, 18432, 136, }, /* 840 */
+ { 24, 26, 12, 0, 0, 28672, 68, }, /* 841 */
+ { 111, 7, 12, 0, 0, 18432, 82, }, /* 842 */
+ { 111, 6, 12, 0, 0, 18432, 142, }, /* 843 */
+ { 111, 21, 12, 0, 0, 18432, 106, }, /* 844 */
+ { 111, 21, 12, 0, 0, 18432, 124, }, /* 845 */
+ { 99, 7, 12, 0, 0, 18432, 82, }, /* 846 */
+ { 99, 6, 12, 0, 0, 18432, 136, }, /* 847 */
+ { 99, 21, 12, 0, 0, 28672, 106, }, /* 848 */
+ { 99, 21, 12, 0, 0, 28672, 124, }, /* 849 */
+ { 99, 13, 12, 0, 0, 18432, 138, }, /* 850 */
+ { 2, 9, 12, 108, 1, 18432, 74, }, /* 851 */
+ { 2, 5, 12, 108, -35267, 18432, 76, }, /* 852 */
+ { 2, 7, 12, 0, 0, 18432, 82, }, /* 853 */
+ { 2, 21, 12, 0, 0, 28672, 68, }, /* 854 */
+ { 2, 12, 3, 0, 0, 26624, 96, }, /* 855 */
+ { 2, 6, 12, 0, 0, 28672, 92, }, /* 856 */
+ { 2, 6, 12, 0, 0, 18432, 88, }, /* 857 */
+ { 112, 7, 12, 0, 0, 18432, 82, }, /* 858 */
+ { 112, 14, 12, 0, 0, 18432, 82, }, /* 859 */
+ { 112, 12, 3, 0, 0, 26624, 96, }, /* 860 */
+ { 112, 21, 12, 0, 0, 18432, 68, }, /* 861 */
+ { 112, 21, 12, 0, 0, 18432, 124, }, /* 862 */
+ { 112, 21, 12, 0, 0, 18432, 106, }, /* 863 */
+ { 69, 24, 12, 0, 0, 28762, 56, }, /* 864 */
+ { 0, 9, 12, 0, -35332, 18432, 74, }, /* 865 */
+ { 69, 24, 12, 0, 0, 18432, 56, }, /* 866 */
+ { 0, 9, 12, 0, -42280, 18432, 74, }, /* 867 */
+ { 0, 5, 12, 0, 48, 18432, 76, }, /* 868 */
+ { 0, 9, 12, 0, -42308, 18432, 74, }, /* 869 */
+ { 0, 9, 12, 0, -42319, 18432, 74, }, /* 870 */
+ { 0, 9, 12, 0, -42315, 18432, 74, }, /* 871 */
+ { 0, 9, 12, 0, -42305, 18432, 74, }, /* 872 */
+ { 0, 9, 12, 0, -42258, 18432, 74, }, /* 873 */
+ { 0, 9, 12, 0, -42282, 18432, 74, }, /* 874 */
+ { 0, 9, 12, 0, -42261, 18432, 74, }, /* 875 */
+ { 0, 9, 12, 0, 928, 18432, 74, }, /* 876 */
+ { 0, 9, 12, 0, -48, 18432, 74, }, /* 877 */
+ { 0, 9, 12, 0, -42307, 18432, 74, }, /* 878 */
+ { 0, 9, 12, 0, -35384, 18432, 74, }, /* 879 */
+ { 0, 6, 12, 0, 0, 18432, 142, }, /* 880 */
+ { 36, 7, 12, 0, 0, 18432, 82, }, /* 881 */
+ { 36, 12, 3, 0, 0, 26624, 130, }, /* 882 */
+ { 36, 12, 3, 0, 0, 26624, 182, }, /* 883 */
+ { 36, 10, 5, 0, 0, 18432, 144, }, /* 884 */
+ { 36, 26, 12, 0, 0, 28672, 68, }, /* 885 */
+ { 69, 15, 12, 0, 0, 18612, 68, }, /* 886 */
+ { 69, 15, 12, 0, 0, 18609, 68, }, /* 887 */
+ { 69, 26, 12, 0, 0, 18600, 68, }, /* 888 */
+ { 69, 23, 12, 0, 0, 14504, 68, }, /* 889 */
+ { 69, 26, 12, 0, 0, 14504, 68, }, /* 890 */
+ { 37, 7, 12, 0, 0, 18432, 82, }, /* 891 */
+ { 37, 21, 12, 0, 0, 28672, 68, }, /* 892 */
+ { 37, 21, 12, 0, 0, 28672, 124, }, /* 893 */
+ { 100, 10, 5, 0, 0, 18432, 144, }, /* 894 */
+ { 100, 7, 12, 0, 0, 18432, 82, }, /* 895 */
+ { 100, 12, 3, 0, 0, 26624, 146, }, /* 896 */
+ { 100, 12, 3, 0, 0, 26624, 130, }, /* 897 */
+ { 100, 21, 12, 0, 0, 18432, 124, }, /* 898 */
+ { 100, 13, 12, 0, 0, 18432, 138, }, /* 899 */
+ { 6, 12, 3, 0, 0, 26666, 96, }, /* 900 */
+ { 6, 7, 12, 0, 0, 18507, 82, }, /* 901 */
+ { 39, 13, 12, 0, 0, 18432, 138, }, /* 902 */
+ { 39, 7, 12, 0, 0, 18432, 82, }, /* 903 */
+ { 39, 12, 3, 0, 0, 26624, 130, }, /* 904 */
+ { 39, 12, 3, 0, 0, 26624, 96, }, /* 905 */
+ { 69, 21, 12, 0, 0, 18567, 188, }, /* 906 */
+ { 39, 21, 12, 0, 0, 18432, 124, }, /* 907 */
+ { 101, 7, 12, 0, 0, 18432, 82, }, /* 908 */
+ { 101, 12, 3, 0, 0, 26624, 130, }, /* 909 */
+ { 101, 10, 5, 0, 0, 18432, 144, }, /* 910 */
+ { 101, 10, 5, 0, 0, 18432, 172, }, /* 911 */
+ { 101, 21, 12, 0, 0, 18432, 68, }, /* 912 */
+ { 40, 12, 3, 0, 0, 26624, 130, }, /* 913 */
+ { 40, 10, 5, 0, 0, 18432, 144, }, /* 914 */
+ { 40, 7, 12, 0, 0, 18432, 82, }, /* 915 */
+ { 40, 12, 3, 0, 0, 26624, 96, }, /* 916 */
+ { 40, 10, 5, 0, 0, 18432, 172, }, /* 917 */
+ { 40, 21, 12, 0, 0, 18432, 68, }, /* 918 */
+ { 40, 21, 12, 0, 0, 18432, 106, }, /* 919 */
+ { 40, 21, 12, 0, 0, 18432, 124, }, /* 920 */
+ { 69, 6, 12, 0, 0, 18480, 136, }, /* 921 */
+ { 40, 13, 12, 0, 0, 18432, 138, }, /* 922 */
+ { 16, 6, 12, 0, 0, 18432, 136, }, /* 923 */
+ { 105, 7, 12, 0, 0, 18432, 82, }, /* 924 */
+ { 105, 12, 3, 0, 0, 26624, 130, }, /* 925 */
+ { 105, 10, 5, 0, 0, 18432, 144, }, /* 926 */
+ { 105, 13, 12, 0, 0, 18432, 138, }, /* 927 */
+ { 105, 21, 12, 0, 0, 18432, 68, }, /* 928 */
+ { 105, 21, 12, 0, 0, 18432, 124, }, /* 929 */
+ { 107, 7, 12, 0, 0, 18432, 82, }, /* 930 */
+ { 107, 12, 3, 0, 0, 26624, 130, }, /* 931 */
+ { 107, 7, 12, 0, 0, 18432, 156, }, /* 932 */
+ { 107, 12, 3, 0, 0, 26624, 96, }, /* 933 */
+ { 107, 7, 12, 0, 0, 18432, 294, }, /* 934 */
+ { 107, 6, 12, 0, 0, 18432, 136, }, /* 935 */
+ { 107, 21, 12, 0, 0, 18432, 68, }, /* 936 */
+ { 107, 21, 12, 0, 0, 18432, 106, }, /* 937 */
+ { 113, 7, 12, 0, 0, 18432, 82, }, /* 938 */
+ { 113, 10, 5, 0, 0, 18432, 144, }, /* 939 */
+ { 113, 12, 3, 0, 0, 26624, 130, }, /* 940 */
+ { 113, 21, 12, 0, 0, 18432, 124, }, /* 941 */
+ { 113, 6, 12, 0, 0, 18432, 136, }, /* 942 */
+ { 113, 12, 3, 0, 0, 26624, 146, }, /* 943 */
+ { 0, 5, 12, 0, -928, 18432, 76, }, /* 944 */
+ { 0, 6, 12, 0, 0, 18432, 92, }, /* 945 */
+ { 76, 5, 12, 0, -38864, 18432, 70, }, /* 946 */
+ { 113, 10, 5, 0, 0, 18432, 160, }, /* 947 */
+ { 113, 13, 12, 0, 0, 18432, 138, }, /* 948 */
+ { 18, 7, 9, 0, 0, 18432, 82, }, /* 949 */
+ { 18, 7, 10, 0, 0, 18432, 82, }, /* 950 */
+ { 68, 4, 12, 0, 0, 18432, 0, }, /* 951 */
+ { 68, 3, 12, 0, 0, 18432, 0, }, /* 952 */
+ { 23, 7, 12, 0, 0, 18432, 284, }, /* 953 */
+ { 71, 25, 12, 0, 0, 12288, 118, }, /* 954 */
+ { 3, 7, 12, 0, 0, 0, 296, }, /* 955 */
+ { 69, 18, 12, 0, 0, 28705, 54, }, /* 956 */
+ { 69, 22, 12, 0, 0, 28705, 54, }, /* 957 */
+ { 68, 2, 12, 0, 0, 6144, 298, }, /* 958 */
+ { 3, 7, 12, 0, 0, 39, 82, }, /* 959 */
+ { 3, 26, 12, 0, 0, 28711, 68, }, /* 960 */
+ { 84, 12, 3, 0, 0, 26624, 178, }, /* 961 */
+ { 84, 12, 3, 0, 0, 26624, 300, }, /* 962 */
+ { 69, 21, 12, 0, 0, 28672, 68, }, /* 963 */
+ { 69, 21, 12, 0, 0, 28672, 122, }, /* 964 */
+ { 69, 22, 12, 0, 0, 28672, 68, }, /* 965 */
+ { 69, 18, 12, 0, 0, 28672, 68, }, /* 966 */
+ { 69, 17, 12, 0, 0, 28672, 126, }, /* 967 */
+ { 69, 22, 12, 0, 0, 28672, 302, }, /* 968 */
+ { 69, 18, 12, 0, 0, 28672, 302, }, /* 969 */
+ { 69, 21, 12, 0, 0, 8192, 106, }, /* 970 */
+ { 69, 21, 12, 0, 0, 8192, 304, }, /* 971 */
+ { 69, 21, 12, 0, 0, 8192, 306, }, /* 972 */
+ { 69, 21, 12, 0, 0, 28672, 124, }, /* 973 */
+ { 69, 22, 12, 0, 0, 28672, 158, }, /* 974 */
+ { 69, 18, 12, 0, 0, 28672, 158, }, /* 975 */
+ { 69, 21, 12, 0, 0, 14336, 68, }, /* 976 */
+ { 69, 21, 12, 0, 0, 28672, 118, }, /* 977 */
+ { 69, 17, 12, 0, 0, 12288, 224, }, /* 978 */
+ { 69, 25, 12, 0, 0, 28672, 226, }, /* 979 */
+ { 69, 21, 12, 0, 0, 28672, 302, }, /* 980 */
+ { 69, 21, 12, 0, 0, 28672, 308, }, /* 981 */
+ { 69, 17, 12, 0, 0, 12288, 126, }, /* 982 */
+ { 69, 21, 12, 0, 0, 8192, 68, }, /* 983 */
+ { 69, 13, 12, 0, 0, 10240, 310, }, /* 984 */
+ { 0, 9, 12, 0, 32, 18432, 312, }, /* 985 */
+ { 69, 24, 12, 0, 0, 28672, 314, }, /* 986 */
+ { 0, 5, 12, 0, -32, 18432, 316, }, /* 987 */
+ { 69, 21, 12, 0, 0, 28825, 124, }, /* 988 */
+ { 69, 22, 12, 0, 0, 28825, 318, }, /* 989 */
+ { 69, 18, 12, 0, 0, 28825, 318, }, /* 990 */
+ { 69, 21, 12, 0, 0, 28825, 106, }, /* 991 */
+ { 69, 6, 3, 0, 0, 18525, 320, }, /* 992 */
+ { 69, 1, 2, 0, 0, 28672, 322, }, /* 993 */
+ { 31, 7, 12, 0, 0, 18432, 82, }, /* 994 */
+ { 69, 21, 12, 0, 0, 18552, 68, }, /* 995 */
+ { 69, 21, 12, 0, 0, 28792, 68, }, /* 996 */
+ { 69, 21, 12, 0, 0, 18483, 68, }, /* 997 */
+ { 69, 15, 12, 0, 0, 18555, 68, }, /* 998 */
+ { 69, 26, 12, 0, 0, 18483, 68, }, /* 999 */
+ { 1, 14, 12, 0, 0, 28672, 82, }, /* 1000 */
+ { 1, 15, 12, 0, 0, 28672, 68, }, /* 1001 */
+ { 1, 26, 12, 0, 0, 28672, 68, }, /* 1002 */
+ { 1, 26, 12, 0, 0, 18432, 68, }, /* 1003 */
+ { 102, 7, 12, 0, 0, 18432, 82, }, /* 1004 */
+ { 103, 7, 12, 0, 0, 18432, 82, }, /* 1005 */
+ { 84, 12, 3, 0, 0, 26651, 96, }, /* 1006 */
+ { 69, 15, 12, 0, 0, 10267, 68, }, /* 1007 */
+ { 81, 7, 12, 0, 0, 18432, 82, }, /* 1008 */
+ { 81, 15, 12, 0, 0, 18432, 68, }, /* 1009 */
+ { 82, 7, 12, 0, 0, 18432, 82, }, /* 1010 */
+ { 82, 14, 12, 0, 0, 18432, 82, }, /* 1011 */
+ { 53, 7, 12, 0, 0, 18432, 82, }, /* 1012 */
+ { 53, 12, 3, 0, 0, 26624, 130, }, /* 1013 */
+ { 85, 7, 12, 0, 0, 18432, 82, }, /* 1014 */
+ { 85, 21, 12, 0, 0, 18432, 106, }, /* 1015 */
+ { 91, 7, 12, 0, 0, 18432, 82, }, /* 1016 */
+ { 91, 21, 12, 0, 0, 18432, 106, }, /* 1017 */
+ { 91, 14, 12, 0, 0, 18432, 82, }, /* 1018 */
+ { 83, 9, 12, 0, 40, 18432, 74, }, /* 1019 */
+ { 83, 5, 12, 0, -40, 18432, 76, }, /* 1020 */
+ { 86, 7, 12, 0, 0, 18432, 82, }, /* 1021 */
+ { 87, 7, 12, 0, 0, 18432, 82, }, /* 1022 */
+ { 87, 13, 12, 0, 0, 18432, 138, }, /* 1023 */
+ { 145, 9, 12, 0, 40, 18432, 74, }, /* 1024 */
+ { 145, 5, 12, 0, -40, 18432, 76, }, /* 1025 */
+ { 127, 7, 12, 0, 0, 18432, 82, }, /* 1026 */
+ { 125, 7, 12, 0, 0, 18432, 82, }, /* 1027 */
+ { 125, 21, 12, 0, 0, 18432, 68, }, /* 1028 */
+ { 161, 9, 12, 0, 39, 18432, 74, }, /* 1029 */
+ { 161, 5, 12, 0, -39, 18432, 76, }, /* 1030 */
+ { 49, 7, 12, 0, 0, 18432, 82, }, /* 1031 */
+ { 0, 6, 12, 0, 0, 18432, 94, }, /* 1032 */
+ { 32, 7, 12, 0, 0, 34816, 82, }, /* 1033 */
+ { 114, 7, 12, 0, 0, 34816, 82, }, /* 1034 */
+ { 114, 21, 12, 0, 0, 34816, 106, }, /* 1035 */
+ { 114, 15, 12, 0, 0, 34816, 68, }, /* 1036 */
+ { 133, 7, 12, 0, 0, 34816, 82, }, /* 1037 */
+ { 133, 26, 12, 0, 0, 34816, 68, }, /* 1038 */
+ { 133, 15, 12, 0, 0, 34816, 68, }, /* 1039 */
+ { 132, 7, 12, 0, 0, 34816, 82, }, /* 1040 */
+ { 132, 15, 12, 0, 0, 34816, 68, }, /* 1041 */
+ { 139, 7, 12, 0, 0, 34816, 82, }, /* 1042 */
+ { 139, 15, 12, 0, 0, 34816, 68, }, /* 1043 */
+ { 95, 7, 12, 0, 0, 34816, 82, }, /* 1044 */
+ { 95, 15, 12, 0, 0, 34816, 68, }, /* 1045 */
+ { 95, 21, 12, 0, 0, 28672, 106, }, /* 1046 */
+ { 104, 7, 12, 0, 0, 34816, 82, }, /* 1047 */
+ { 104, 21, 12, 0, 0, 34816, 68, }, /* 1048 */
+ { 122, 7, 12, 0, 0, 34816, 82, }, /* 1049 */
+ { 121, 7, 12, 0, 0, 34816, 82, }, /* 1050 */
+ { 121, 15, 12, 0, 0, 34816, 68, }, /* 1051 */
+ { 92, 7, 12, 0, 0, 34816, 82, }, /* 1052 */
+ { 92, 12, 3, 0, 0, 26624, 130, }, /* 1053 */
+ { 92, 12, 3, 0, 0, 26624, 102, }, /* 1054 */
+ { 92, 12, 3, 0, 0, 26624, 182, }, /* 1055 */
+ { 92, 15, 12, 0, 0, 34816, 68, }, /* 1056 */
+ { 92, 21, 12, 0, 0, 34816, 68, }, /* 1057 */
+ { 92, 21, 12, 0, 0, 34816, 124, }, /* 1058 */
+ { 115, 7, 12, 0, 0, 34816, 82, }, /* 1059 */
+ { 115, 15, 12, 0, 0, 34816, 68, }, /* 1060 */
+ { 115, 21, 12, 0, 0, 34816, 68, }, /* 1061 */
+ { 131, 7, 12, 0, 0, 34816, 82, }, /* 1062 */
+ { 131, 15, 12, 0, 0, 34816, 68, }, /* 1063 */
+ { 51, 7, 12, 0, 0, 34816, 82, }, /* 1064 */
+ { 51, 26, 12, 0, 0, 34816, 68, }, /* 1065 */
+ { 51, 12, 3, 0, 0, 26624, 96, }, /* 1066 */
+ { 51, 15, 12, 0, 0, 34816, 68, }, /* 1067 */
+ { 51, 21, 12, 0, 0, 34816, 106, }, /* 1068 */
+ { 51, 21, 12, 0, 0, 34918, 106, }, /* 1069 */
+ { 51, 21, 12, 0, 0, 34816, 68, }, /* 1070 */
+ { 108, 7, 12, 0, 0, 34816, 82, }, /* 1071 */
+ { 108, 21, 12, 0, 0, 28672, 68, }, /* 1072 */
+ { 108, 21, 12, 0, 0, 28672, 106, }, /* 1073 */
+ { 116, 7, 12, 0, 0, 34816, 82, }, /* 1074 */
+ { 116, 15, 12, 0, 0, 34816, 68, }, /* 1075 */
+ { 117, 7, 12, 0, 0, 34816, 82, }, /* 1076 */
+ { 117, 15, 12, 0, 0, 34816, 68, }, /* 1077 */
+ { 54, 7, 12, 0, 0, 34816, 82, }, /* 1078 */
+ { 54, 21, 12, 0, 0, 34816, 106, }, /* 1079 */
+ { 54, 15, 12, 0, 0, 34816, 68, }, /* 1080 */
+ { 118, 7, 12, 0, 0, 34816, 82, }, /* 1081 */
+ { 140, 9, 12, 0, 64, 34816, 74, }, /* 1082 */
+ { 140, 5, 12, 0, -64, 34816, 76, }, /* 1083 */
+ { 140, 15, 12, 0, 0, 34816, 68, }, /* 1084 */
+ { 62, 7, 12, 0, 0, 0, 82, }, /* 1085 */
+ { 62, 7, 12, 0, 0, 0, 294, }, /* 1086 */
+ { 62, 12, 3, 0, 0, 26624, 128, }, /* 1087 */
+ { 62, 13, 12, 0, 0, 2048, 138, }, /* 1088 */
+ { 3, 15, 12, 0, 0, 2048, 68, }, /* 1089 */
+ { 65, 7, 12, 0, 0, 34816, 82, }, /* 1090 */
+ { 65, 12, 3, 0, 0, 26624, 130, }, /* 1091 */
+ { 65, 17, 12, 0, 0, 34816, 126, }, /* 1092 */
+ { 152, 7, 12, 0, 0, 34816, 82, }, /* 1093 */
+ { 152, 15, 12, 0, 0, 34816, 68, }, /* 1094 */
+ { 63, 7, 12, 0, 0, 0, 82, }, /* 1095 */
+ { 63, 12, 3, 0, 0, 26624, 96, }, /* 1096 */
+ { 63, 15, 12, 0, 0, 0, 68, }, /* 1097 */
+ { 63, 21, 12, 0, 0, 0, 124, }, /* 1098 */
+ { 67, 7, 12, 0, 0, 34816, 82, }, /* 1099 */
+ { 67, 12, 3, 0, 0, 26624, 96, }, /* 1100 */
+ { 67, 21, 12, 0, 0, 34816, 124, }, /* 1101 */
+ { 156, 7, 12, 0, 0, 34816, 82, }, /* 1102 */
+ { 156, 15, 12, 0, 0, 34816, 68, }, /* 1103 */
+ { 153, 7, 12, 0, 0, 34816, 82, }, /* 1104 */
+ { 120, 10, 5, 0, 0, 18432, 144, }, /* 1105 */
+ { 120, 12, 3, 0, 0, 26624, 130, }, /* 1106 */
+ { 120, 7, 12, 0, 0, 18432, 82, }, /* 1107 */
+ { 120, 12, 3, 0, 0, 26624, 146, }, /* 1108 */
+ { 120, 21, 12, 0, 0, 18432, 124, }, /* 1109 */
+ { 120, 21, 12, 0, 0, 18432, 106, }, /* 1110 */
+ { 120, 15, 12, 0, 0, 28672, 68, }, /* 1111 */
+ { 120, 13, 12, 0, 0, 18432, 138, }, /* 1112 */
+ { 120, 12, 3, 0, 0, 26624, 182, }, /* 1113 */
+ { 41, 12, 3, 0, 0, 26624, 102, }, /* 1114 */
+ { 41, 10, 5, 0, 0, 18432, 144, }, /* 1115 */
+ { 41, 7, 12, 0, 0, 18432, 82, }, /* 1116 */
+ { 41, 12, 3, 0, 0, 26624, 130, }, /* 1117 */
+ { 41, 12, 3, 0, 0, 26624, 146, }, /* 1118 */
+ { 41, 12, 3, 0, 0, 26624, 96, }, /* 1119 */
+ { 41, 21, 12, 0, 0, 18432, 68, }, /* 1120 */
+ { 41, 1, 4, 0, 0, 18432, 132, }, /* 1121 */
+ { 41, 21, 12, 0, 0, 18432, 124, }, /* 1122 */
+ { 124, 7, 12, 0, 0, 18432, 82, }, /* 1123 */
+ { 124, 13, 12, 0, 0, 18432, 138, }, /* 1124 */
+ { 43, 12, 3, 0, 0, 26624, 130, }, /* 1125 */
+ { 43, 7, 12, 0, 0, 18432, 82, }, /* 1126 */
+ { 43, 10, 5, 0, 0, 18432, 144, }, /* 1127 */
+ { 43, 12, 3, 0, 0, 26624, 146, }, /* 1128 */
+ { 43, 13, 12, 0, 0, 18432, 138, }, /* 1129 */
+ { 43, 21, 12, 0, 0, 18432, 68, }, /* 1130 */
+ { 43, 21, 12, 0, 0, 18432, 124, }, /* 1131 */
+ { 50, 7, 12, 0, 0, 18432, 82, }, /* 1132 */
+ { 50, 12, 3, 0, 0, 26624, 96, }, /* 1133 */
+ { 50, 21, 12, 0, 0, 18432, 68, }, /* 1134 */
+ { 44, 12, 3, 0, 0, 26624, 130, }, /* 1135 */
+ { 44, 10, 5, 0, 0, 18432, 144, }, /* 1136 */
+ { 44, 7, 12, 0, 0, 18432, 82, }, /* 1137 */
+ { 44, 10, 5, 0, 0, 18432, 172, }, /* 1138 */
+ { 44, 7, 4, 0, 0, 18432, 82, }, /* 1139 */
+ { 44, 21, 12, 0, 0, 18432, 124, }, /* 1140 */
+ { 44, 21, 12, 0, 0, 18432, 68, }, /* 1141 */
+ { 44, 12, 3, 0, 0, 26624, 102, }, /* 1142 */
+ { 44, 12, 3, 0, 0, 26624, 96, }, /* 1143 */
+ { 44, 13, 12, 0, 0, 18432, 138, }, /* 1144 */
+ { 15, 15, 12, 0, 0, 18432, 68, }, /* 1145 */
+ { 48, 7, 12, 0, 0, 18432, 82, }, /* 1146 */
+ { 48, 10, 5, 0, 0, 18432, 144, }, /* 1147 */
+ { 48, 12, 3, 0, 0, 26624, 130, }, /* 1148 */
+ { 48, 10, 5, 0, 0, 18432, 172, }, /* 1149 */
+ { 48, 12, 3, 0, 0, 26624, 96, }, /* 1150 */
+ { 48, 21, 12, 0, 0, 18432, 124, }, /* 1151 */
+ { 48, 21, 12, 0, 0, 18432, 106, }, /* 1152 */
+ { 48, 21, 12, 0, 0, 18432, 68, }, /* 1153 */
+ { 57, 7, 12, 0, 0, 18432, 82, }, /* 1154 */
+ { 57, 21, 12, 0, 0, 18432, 124, }, /* 1155 */
+ { 55, 7, 12, 0, 0, 18432, 82, }, /* 1156 */
+ { 55, 12, 3, 0, 0, 26624, 130, }, /* 1157 */
+ { 55, 10, 5, 0, 0, 18432, 144, }, /* 1158 */
+ { 55, 12, 3, 0, 0, 26624, 96, }, /* 1159 */
+ { 55, 12, 3, 0, 0, 26624, 146, }, /* 1160 */
+ { 55, 13, 12, 0, 0, 18432, 138, }, /* 1161 */
+ { 47, 12, 3, 0, 0, 26624, 130, }, /* 1162 */
+ { 47, 12, 3, 0, 0, 26705, 130, }, /* 1163 */
+ { 47, 10, 5, 0, 0, 18432, 144, }, /* 1164 */
+ { 47, 10, 5, 0, 0, 18513, 144, }, /* 1165 */
+ { 47, 7, 12, 0, 0, 18432, 82, }, /* 1166 */
+ { 84, 12, 3, 0, 0, 26705, 102, }, /* 1167 */
+ { 47, 12, 3, 0, 0, 26705, 96, }, /* 1168 */
+ { 47, 10, 3, 0, 0, 18432, 148, }, /* 1169 */
+ { 47, 10, 5, 0, 0, 18432, 172, }, /* 1170 */
+ { 47, 7, 12, 0, 0, 18432, 324, }, /* 1171 */
+ { 47, 12, 3, 0, 0, 26624, 96, }, /* 1172 */
+ { 144, 7, 12, 0, 0, 18432, 82, }, /* 1173 */
+ { 144, 10, 5, 0, 0, 18432, 144, }, /* 1174 */
+ { 144, 12, 3, 0, 0, 26624, 130, }, /* 1175 */
+ { 144, 12, 3, 0, 0, 26624, 146, }, /* 1176 */
+ { 144, 12, 3, 0, 0, 26624, 96, }, /* 1177 */
+ { 144, 21, 12, 0, 0, 18432, 124, }, /* 1178 */
+ { 144, 21, 12, 0, 0, 18432, 106, }, /* 1179 */
+ { 144, 21, 12, 0, 0, 18432, 68, }, /* 1180 */
+ { 144, 13, 12, 0, 0, 18432, 138, }, /* 1181 */
+ { 144, 12, 3, 0, 0, 26624, 102, }, /* 1182 */
+ { 56, 7, 12, 0, 0, 18432, 82, }, /* 1183 */
+ { 56, 10, 3, 0, 0, 18432, 148, }, /* 1184 */
+ { 56, 10, 5, 0, 0, 18432, 144, }, /* 1185 */
+ { 56, 12, 3, 0, 0, 26624, 130, }, /* 1186 */
+ { 56, 12, 3, 0, 0, 26624, 146, }, /* 1187 */
+ { 56, 12, 3, 0, 0, 26624, 96, }, /* 1188 */
+ { 56, 21, 12, 0, 0, 18432, 68, }, /* 1189 */
+ { 56, 13, 12, 0, 0, 18432, 138, }, /* 1190 */
+ { 135, 7, 12, 0, 0, 18432, 82, }, /* 1191 */
+ { 135, 10, 3, 0, 0, 18432, 148, }, /* 1192 */
+ { 135, 10, 5, 0, 0, 18432, 144, }, /* 1193 */
+ { 135, 12, 3, 0, 0, 26624, 130, }, /* 1194 */
+ { 135, 12, 3, 0, 0, 26624, 146, }, /* 1195 */
+ { 135, 12, 3, 0, 0, 26624, 96, }, /* 1196 */
+ { 135, 21, 12, 0, 0, 18432, 68, }, /* 1197 */
+ { 135, 21, 12, 0, 0, 18432, 124, }, /* 1198 */
+ { 135, 21, 12, 0, 0, 18432, 106, }, /* 1199 */
+ { 135, 21, 12, 0, 0, 18432, 176, }, /* 1200 */
+ { 52, 7, 12, 0, 0, 18432, 82, }, /* 1201 */
+ { 52, 10, 5, 0, 0, 18432, 144, }, /* 1202 */
+ { 52, 12, 3, 0, 0, 26624, 130, }, /* 1203 */
+ { 52, 12, 3, 0, 0, 26624, 146, }, /* 1204 */
+ { 52, 21, 12, 0, 0, 18432, 124, }, /* 1205 */
+ { 52, 21, 12, 0, 0, 18432, 68, }, /* 1206 */
+ { 52, 13, 12, 0, 0, 18432, 138, }, /* 1207 */
+ { 45, 7, 12, 0, 0, 18432, 82, }, /* 1208 */
+ { 45, 12, 3, 0, 0, 26624, 130, }, /* 1209 */
+ { 45, 10, 5, 0, 0, 18432, 144, }, /* 1210 */
+ { 45, 10, 5, 0, 0, 18432, 172, }, /* 1211 */
+ { 45, 12, 3, 0, 0, 26624, 96, }, /* 1212 */
+ { 45, 21, 12, 0, 0, 18432, 68, }, /* 1213 */
+ { 45, 13, 12, 0, 0, 18432, 138, }, /* 1214 */
+ { 137, 7, 12, 0, 0, 18432, 82, }, /* 1215 */
+ { 137, 12, 3, 0, 0, 26624, 130, }, /* 1216 */
+ { 137, 10, 12, 0, 0, 18432, 144, }, /* 1217 */
+ { 137, 10, 5, 0, 0, 18432, 144, }, /* 1218 */
+ { 137, 12, 3, 0, 0, 26624, 146, }, /* 1219 */
+ { 137, 13, 12, 0, 0, 18432, 138, }, /* 1220 */
+ { 137, 15, 12, 0, 0, 18432, 68, }, /* 1221 */
+ { 137, 21, 12, 0, 0, 18432, 124, }, /* 1222 */
+ { 137, 26, 12, 0, 0, 18432, 68, }, /* 1223 */
+ { 60, 7, 12, 0, 0, 18432, 82, }, /* 1224 */
+ { 60, 10, 5, 0, 0, 18432, 144, }, /* 1225 */
+ { 60, 12, 3, 0, 0, 26624, 130, }, /* 1226 */
+ { 60, 12, 3, 0, 0, 26624, 146, }, /* 1227 */
+ { 60, 12, 3, 0, 0, 26624, 96, }, /* 1228 */
+ { 60, 21, 12, 0, 0, 18432, 68, }, /* 1229 */
+ { 136, 9, 12, 0, 32, 18432, 74, }, /* 1230 */
+ { 136, 5, 12, 0, -32, 18432, 76, }, /* 1231 */
+ { 136, 13, 12, 0, 0, 18432, 138, }, /* 1232 */
+ { 136, 15, 12, 0, 0, 18432, 68, }, /* 1233 */
+ { 136, 7, 12, 0, 0, 18432, 82, }, /* 1234 */
+ { 157, 7, 12, 0, 0, 18432, 82, }, /* 1235 */
+ { 157, 10, 3, 0, 0, 18432, 148, }, /* 1236 */
+ { 157, 10, 5, 0, 0, 18432, 144, }, /* 1237 */
+ { 157, 12, 3, 0, 0, 26624, 130, }, /* 1238 */
+ { 157, 10, 5, 0, 0, 18432, 172, }, /* 1239 */
+ { 157, 12, 3, 0, 0, 26624, 146, }, /* 1240 */
+ { 157, 7, 4, 0, 0, 18432, 82, }, /* 1241 */
+ { 157, 12, 3, 0, 0, 26624, 96, }, /* 1242 */
+ { 157, 21, 12, 0, 0, 18432, 124, }, /* 1243 */
+ { 157, 21, 12, 0, 0, 18432, 68, }, /* 1244 */
+ { 157, 13, 12, 0, 0, 18432, 138, }, /* 1245 */
+ { 64, 7, 12, 0, 0, 18432, 82, }, /* 1246 */
+ { 64, 10, 5, 0, 0, 18432, 144, }, /* 1247 */
+ { 64, 12, 3, 0, 0, 26624, 130, }, /* 1248 */
+ { 64, 12, 3, 0, 0, 26624, 146, }, /* 1249 */
+ { 64, 21, 12, 0, 0, 18432, 68, }, /* 1250 */
+ { 149, 7, 12, 0, 0, 18432, 82, }, /* 1251 */
+ { 149, 12, 3, 0, 0, 26624, 130, }, /* 1252 */
+ { 149, 12, 3, 0, 0, 18432, 130, }, /* 1253 */
+ { 149, 12, 3, 0, 0, 26624, 102, }, /* 1254 */
+ { 149, 12, 3, 0, 0, 26624, 146, }, /* 1255 */
+ { 149, 10, 5, 0, 0, 18432, 144, }, /* 1256 */
+ { 149, 7, 4, 0, 0, 18432, 82, }, /* 1257 */
+ { 149, 21, 12, 0, 0, 18432, 68, }, /* 1258 */
+ { 149, 21, 12, 0, 0, 18432, 124, }, /* 1259 */
+ { 148, 7, 12, 0, 0, 18432, 82, }, /* 1260 */
+ { 148, 12, 3, 0, 0, 26624, 130, }, /* 1261 */
+ { 148, 10, 5, 0, 0, 18432, 144, }, /* 1262 */
+ { 148, 7, 4, 0, 0, 18432, 82, }, /* 1263 */
+ { 148, 12, 3, 0, 0, 26624, 326, }, /* 1264 */
+ { 148, 12, 3, 0, 0, 26624, 146, }, /* 1265 */
+ { 148, 21, 12, 0, 0, 18432, 68, }, /* 1266 */
+ { 148, 21, 12, 0, 0, 18432, 124, }, /* 1267 */
+ { 148, 21, 12, 0, 0, 18432, 106, }, /* 1268 */
+ { 134, 7, 12, 0, 0, 18432, 82, }, /* 1269 */
+ { 142, 7, 12, 0, 0, 18432, 82, }, /* 1270 */
+ { 142, 10, 5, 0, 0, 18432, 144, }, /* 1271 */
+ { 142, 12, 3, 0, 0, 26624, 130, }, /* 1272 */
+ { 142, 12, 3, 0, 0, 18432, 146, }, /* 1273 */
+ { 142, 21, 12, 0, 0, 18432, 124, }, /* 1274 */
+ { 142, 21, 12, 0, 0, 18432, 106, }, /* 1275 */
+ { 142, 21, 12, 0, 0, 18432, 68, }, /* 1276 */
+ { 142, 13, 12, 0, 0, 18432, 138, }, /* 1277 */
+ { 142, 15, 12, 0, 0, 18432, 68, }, /* 1278 */
+ { 143, 21, 12, 0, 0, 18432, 68, }, /* 1279 */
+ { 143, 21, 12, 0, 0, 18432, 106, }, /* 1280 */
+ { 143, 7, 12, 0, 0, 18432, 82, }, /* 1281 */
+ { 143, 12, 3, 0, 0, 26624, 130, }, /* 1282 */
+ { 143, 10, 5, 0, 0, 18432, 144, }, /* 1283 */
+ { 59, 7, 12, 0, 0, 18432, 82, }, /* 1284 */
+ { 59, 12, 3, 0, 0, 26624, 130, }, /* 1285 */
+ { 59, 12, 3, 0, 0, 26624, 96, }, /* 1286 */
+ { 59, 12, 3, 0, 0, 26624, 146, }, /* 1287 */
+ { 59, 7, 4, 0, 0, 18432, 82, }, /* 1288 */
+ { 59, 13, 12, 0, 0, 18432, 138, }, /* 1289 */
+ { 61, 7, 12, 0, 0, 18432, 82, }, /* 1290 */
+ { 61, 10, 5, 0, 0, 18432, 144, }, /* 1291 */
+ { 61, 12, 3, 0, 0, 26624, 130, }, /* 1292 */
+ { 61, 12, 3, 0, 0, 26624, 146, }, /* 1293 */
+ { 61, 13, 12, 0, 0, 18432, 138, }, /* 1294 */
+ { 150, 7, 12, 0, 0, 18432, 82, }, /* 1295 */
+ { 150, 12, 3, 0, 0, 26624, 130, }, /* 1296 */
+ { 150, 10, 5, 0, 0, 18432, 144, }, /* 1297 */
+ { 150, 21, 12, 0, 0, 18432, 124, }, /* 1298 */
+ { 11, 15, 12, 0, 0, 18432, 68, }, /* 1299 */
+ { 11, 21, 12, 0, 0, 18432, 68, }, /* 1300 */
+ { 94, 7, 12, 0, 0, 18432, 82, }, /* 1301 */
+ { 94, 14, 12, 0, 0, 18432, 82, }, /* 1302 */
+ { 94, 21, 12, 0, 0, 18432, 106, }, /* 1303 */
+ { 66, 7, 12, 0, 0, 18432, 82, }, /* 1304 */
+ { 66, 21, 12, 0, 0, 18432, 68, }, /* 1305 */
+ { 109, 7, 12, 0, 0, 18432, 82, }, /* 1306 */
+ { 109, 1, 2, 0, 0, 18432, 322, }, /* 1307 */
+ { 138, 7, 12, 0, 0, 18432, 82, }, /* 1308 */
+ { 130, 7, 12, 0, 0, 18432, 82, }, /* 1309 */
+ { 130, 13, 12, 0, 0, 18432, 138, }, /* 1310 */
+ { 130, 21, 12, 0, 0, 18432, 124, }, /* 1311 */
+ { 159, 7, 12, 0, 0, 18432, 82, }, /* 1312 */
+ { 159, 13, 12, 0, 0, 18432, 138, }, /* 1313 */
+ { 126, 7, 12, 0, 0, 18432, 82, }, /* 1314 */
+ { 126, 12, 3, 0, 0, 26624, 96, }, /* 1315 */
+ { 126, 21, 12, 0, 0, 18432, 124, }, /* 1316 */
+ { 128, 7, 12, 0, 0, 18432, 82, }, /* 1317 */
+ { 128, 12, 3, 0, 0, 26624, 96, }, /* 1318 */
+ { 128, 21, 12, 0, 0, 18432, 124, }, /* 1319 */
+ { 128, 21, 12, 0, 0, 18432, 106, }, /* 1320 */
+ { 128, 21, 12, 0, 0, 18432, 68, }, /* 1321 */
+ { 128, 26, 12, 0, 0, 18432, 68, }, /* 1322 */
+ { 128, 6, 12, 0, 0, 18432, 142, }, /* 1323 */
+ { 128, 6, 12, 0, 0, 18432, 136, }, /* 1324 */
+ { 128, 13, 12, 0, 0, 18432, 138, }, /* 1325 */
+ { 128, 15, 12, 0, 0, 18432, 68, }, /* 1326 */
+ { 151, 9, 12, 0, 32, 18432, 74, }, /* 1327 */
+ { 151, 5, 12, 0, -32, 18432, 76, }, /* 1328 */
+ { 151, 15, 12, 0, 0, 18432, 68, }, /* 1329 */
+ { 151, 21, 12, 0, 0, 18432, 106, }, /* 1330 */
+ { 151, 21, 12, 0, 0, 18432, 124, }, /* 1331 */
+ { 151, 21, 12, 0, 0, 18432, 68, }, /* 1332 */
+ { 123, 7, 12, 0, 0, 18432, 82, }, /* 1333 */
+ { 123, 12, 3, 0, 0, 26624, 130, }, /* 1334 */
+ { 123, 10, 5, 0, 0, 18432, 144, }, /* 1335 */
+ { 123, 12, 3, 0, 0, 26624, 128, }, /* 1336 */
+ { 123, 6, 12, 0, 0, 18432, 92, }, /* 1337 */
+ { 146, 6, 12, 0, 0, 18432, 136, }, /* 1338 */
+ { 147, 6, 12, 0, 0, 18432, 136, }, /* 1339 */
+ { 23, 21, 12, 0, 0, 28672, 68, }, /* 1340 */
+ { 158, 12, 3, 0, 0, 26624, 328, }, /* 1341 */
+ { 23, 10, 5, 0, 0, 18432, 164, }, /* 1342 */
+ { 146, 7, 12, 0, 0, 18432, 284, }, /* 1343 */
+ { 158, 7, 12, 0, 0, 18432, 284, }, /* 1344 */
+ { 21, 6, 12, 0, 0, 18432, 92, }, /* 1345 */
+ { 147, 7, 12, 0, 0, 18432, 284, }, /* 1346 */
+ { 46, 7, 12, 0, 0, 18432, 82, }, /* 1347 */
+ { 46, 26, 12, 0, 0, 18432, 68, }, /* 1348 */
+ { 46, 12, 3, 0, 0, 26624, 102, }, /* 1349 */
+ { 46, 12, 3, 0, 0, 26624, 130, }, /* 1350 */
+ { 46, 21, 12, 0, 0, 18432, 124, }, /* 1351 */
+ { 69, 1, 2, 0, 0, 6153, 66, }, /* 1352 */
+ { 69, 10, 3, 0, 0, 18432, 330, }, /* 1353 */
+ { 69, 10, 5, 0, 0, 18432, 138, }, /* 1354 */
+ { 69, 10, 5, 0, 0, 18432, 160, }, /* 1355 */
+ { 69, 10, 3, 0, 0, 18432, 286, }, /* 1356 */
+ { 1, 12, 3, 0, 0, 26624, 102, }, /* 1357 */
+ { 69, 25, 12, 0, 0, 18432, 118, }, /* 1358 */
+ { 69, 13, 12, 0, 0, 10240, 214, }, /* 1359 */
+ { 141, 26, 12, 0, 0, 18432, 68, }, /* 1360 */
+ { 141, 12, 3, 0, 0, 26624, 102, }, /* 1361 */
+ { 141, 21, 12, 0, 0, 18432, 106, }, /* 1362 */
+ { 141, 21, 12, 0, 0, 18432, 124, }, /* 1363 */
+ { 141, 21, 12, 0, 0, 18432, 68, }, /* 1364 */
+ { 35, 12, 3, 0, 0, 26624, 130, }, /* 1365 */
+ { 154, 7, 12, 0, 0, 18432, 82, }, /* 1366 */
+ { 154, 12, 3, 0, 0, 26624, 96, }, /* 1367 */
+ { 154, 6, 12, 0, 0, 18432, 142, }, /* 1368 */
+ { 154, 6, 12, 0, 0, 18432, 136, }, /* 1369 */
+ { 154, 13, 12, 0, 0, 18432, 138, }, /* 1370 */
+ { 154, 26, 12, 0, 0, 18432, 68, }, /* 1371 */
+ { 160, 7, 12, 0, 0, 18432, 82, }, /* 1372 */
+ { 160, 12, 3, 0, 0, 26624, 96, }, /* 1373 */
+ { 155, 7, 12, 0, 0, 18432, 82, }, /* 1374 */
+ { 155, 12, 3, 0, 0, 26624, 96, }, /* 1375 */
+ { 155, 13, 12, 0, 0, 18432, 138, }, /* 1376 */
+ { 155, 23, 12, 0, 0, 14336, 68, }, /* 1377 */
+ { 129, 7, 12, 0, 0, 34816, 82, }, /* 1378 */
+ { 129, 15, 12, 0, 0, 34816, 68, }, /* 1379 */
+ { 129, 12, 3, 0, 0, 26624, 96, }, /* 1380 */
+ { 58, 9, 12, 0, 34, 34816, 74, }, /* 1381 */
+ { 58, 5, 12, 0, -34, 34816, 76, }, /* 1382 */
+ { 58, 12, 3, 0, 0, 26624, 150, }, /* 1383 */
+ { 58, 12, 3, 0, 0, 26624, 130, }, /* 1384 */
+ { 58, 12, 3, 0, 0, 26624, 96, }, /* 1385 */
+ { 58, 6, 12, 0, 0, 34816, 142, }, /* 1386 */
+ { 58, 13, 12, 0, 0, 34816, 138, }, /* 1387 */
+ { 58, 21, 12, 0, 0, 34816, 68, }, /* 1388 */
+ { 69, 15, 12, 0, 0, 0, 68, }, /* 1389 */
+ { 69, 26, 12, 0, 0, 0, 68, }, /* 1390 */
+ { 69, 23, 12, 0, 0, 0, 68, }, /* 1391 */
+ { 3, 7, 12, 0, 0, 0, 240, }, /* 1392 */
+ { 69, 26, 14, 0, 0, 28672, 332, }, /* 1393 */
+ { 69, 26, 14, 0, 0, 28672, 334, }, /* 1394 */
+ { 68, 2, 14, 0, 0, 18432, 336, }, /* 1395 */
+ { 69, 26, 12, 0, 0, 18432, 338, }, /* 1396 */
+ { 69, 26, 14, 0, 0, 18432, 340, }, /* 1397 */
+ { 69, 26, 14, 0, 0, 18432, 334, }, /* 1398 */
+ { 69, 26, 11, 0, 0, 18432, 342, }, /* 1399 */
+ { 20, 26, 12, 0, 0, 18432, 68, }, /* 1400 */
+ { 69, 26, 14, 0, 0, 18432, 236, }, /* 1401 */
+ { 69, 26, 14, 0, 0, 18447, 334, }, /* 1402 */
+ { 69, 26, 14, 0, 0, 28672, 344, }, /* 1403 */
+ { 69, 26, 14, 0, 0, 28672, 346, }, /* 1404 */
+ { 69, 24, 3, 0, 0, 28672, 348, }, /* 1405 */
+ { 69, 26, 14, 0, 0, 28672, 350, }, /* 1406 */
+ { 69, 13, 12, 0, 0, 10240, 138, }, /* 1407 */
+ { 69, 1, 3, 0, 0, 6144, 352, }, /* 1408 */
};
const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
@@ -1201,3419 +1841,3549 @@ const uint16_t PRIV(ucd_stage1)[] = { /* 17408 bytes */
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* U+0800 */
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 41, 42, 43, 44, 45, /* U+1000 */
46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, /* U+1800 */
- 62, 63, 64, 65, 66, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, /* U+2000 */
- 77, 77, 78, 79, 66, 66, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, /* U+2800 */
- 90, 91, 92, 93, 94, 95, 96, 97, 98, 98, 98, 98, 98, 98, 98, 98, /* U+3000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+3800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+4000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 98, 98, 98, 98, /* U+4800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+5000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+5800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+6000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+6800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+7000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+7800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+8000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+8800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+9000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+9800 */
-100,101,101,101,101,101,101,101,101,102,103,103,104,105,106,107, /* U+A000 */
-108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,116, /* U+A800 */
-117,118,119,120,121,122,116,117,118,119,120,121,122,116,117,118, /* U+B000 */
-119,120,121,122,116,117,118,119,120,121,122,116,117,118,119,120, /* U+B800 */
-121,122,116,117,118,119,120,121,122,116,117,118,119,120,121,122, /* U+C000 */
-116,117,118,119,120,121,122,116,117,118,119,120,121,122,116,117, /* U+C800 */
-118,119,120,121,122,116,117,118,119,120,121,122,116,117,118,123, /* U+D000 */
-124,124,124,124,124,124,124,124,124,124,124,124,124,124,124,124, /* U+D800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+E000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+E800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F000 */
-125,125, 98, 98,126,127,128,129,130,130,131,132,133,134,135,136, /* U+F800 */
-137,138,139,140,141,142,143,144,145,146,147,148,149,149,150,151, /* U+10000 */
-152,153,154,155,156,157,158,159,160,161,162,141,163,164,165,166, /* U+10800 */
-167,168,169,170,171,172,173,141,174,175,141,176,177,178,179,141, /* U+11000 */
-180,181,182,183,184,185,141,141,186,187,188,189,141,190,141,191, /* U+11800 */
-192,192,192,192,192,192,192,193,194,192,195,141,141,141,141,141, /* U+12000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,196, /* U+12800 */
-197,197,197,197,197,197,197,197,198,141,141,141,141,141,141,141, /* U+13000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+13800 */
-141,141,141,141,141,141,141,141,199,199,199,199,200,141,141,141, /* U+14000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+14800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+15000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+15800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+16000 */
-201,201,201,201,202,203,204,205,141,141,141,141,206,207,208,209, /* U+16800 */
-210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, /* U+17000 */
-210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210, /* U+17800 */
-210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,211, /* U+18000 */
-210,210,210,210,210,210,212,212,212,213,214,141,141,141,141,141, /* U+18800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+19000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+19800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,215, /* U+1A800 */
-216,217,218,219,219,220,141,141,141,141,141,141,141,141,141,141, /* U+1B000 */
-141,141,141,141,141,141,141,141,221,222,141,141,141,141,141,141, /* U+1B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+1C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,223,224, /* U+1C800 */
- 71,225,226,227,228,229,230,141,231,232,233,234,235,236,237,238, /* U+1D000 */
-239,239,239,239,240,241,141,141,141,141,141,141,141,141,242,141, /* U+1D800 */
-243,141,244,141,141,245,141,141,141,141,141,141,141,141,141,246, /* U+1E000 */
-247,248,249,141,141,141,141,141,250,251,252,141,253,254,141,141, /* U+1E800 */
-255,256,257,258,259,260,261,262,261,261,263,261,264,265,266,267, /* U+1F000 */
-268,269,270,261,271,272, 71,273,260,260,260,260,260,260,260,274, /* U+1F800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+20800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+21800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+22000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+22800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+23000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+23800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+24000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+24800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+25000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+25800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+26000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+26800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+27000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+27800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+28800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+29800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,275, 98, 98, /* U+2A000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2A800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,276, 98, /* U+2B000 */
-277, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2B800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2C000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,278, 98, 98, /* U+2C800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2D800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+2E000 */
- 98, 98, 98, 98, 98, 98, 98,279,141,141,141,141,141,141,141,141, /* U+2E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+2F000 */
- 98, 98, 98, 98,280,141,141,141,141,141,141,141,141,141,141,141, /* U+2F800 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30000 */
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, /* U+30800 */
- 98, 98, 98, 98, 98, 98,281,141,141,141,141,141,141,141,141,141, /* U+31000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+31800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+32000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+32800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+33000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+33800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+34000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+34800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+35000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+35800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+36000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+36800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+37000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+37800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+38000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+38800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+39000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+39800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+3F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+40000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+40800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+41000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+41800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+42000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+42800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+43000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+43800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+44000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+44800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+45000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+45800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+46000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+46800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+47000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+47800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+48000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+48800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+49000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+49800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+4F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+50000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+50800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+51000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+51800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+52000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+52800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+53000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+53800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+54000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+54800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+55000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+55800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+56000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+56800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+57000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+57800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+58000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+58800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+59000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+59800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+5F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+60000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+60800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+61000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+61800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+62000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+62800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+63000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+63800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+64000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+64800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+65000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+65800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+66000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+66800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+67000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+67800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+68000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+68800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+69000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+69800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+6F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+70000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+70800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+71000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+71800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+72000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+72800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+73000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+73800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+74000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+74800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+75000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+75800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+76000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+76800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+77000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+77800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+78000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+78800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+79000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+79800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+7F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+80000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+80800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+81000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+81800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+82000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+82800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+83000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+83800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+84000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+84800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+85000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+85800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+86000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+86800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+87000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+87800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+88000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+88800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+89000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+89800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+8F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+90000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+90800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+91000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+91800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+92000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+92800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+93000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+93800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+94000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+94800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+95000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+95800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+96000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+96800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+97000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+97800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+98000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+98800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+99000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+99800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9A000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9A800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9B000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9B800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9C000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9C800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9D000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9D800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9E000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9E800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9F000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+9F800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A0000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A0800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A1000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A1800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A2000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A2800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A3000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A3800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A4000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A4800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A5000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A5800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A6000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A6800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A7000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A7800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A8000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A8800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A9000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+A9800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AA000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AA800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AB000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AB800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AC000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AC800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AD000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AD800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AE000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AE800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AF000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+AF800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B0000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B0800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B1000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B1800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B2000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B2800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B3000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B3800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B4000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B4800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B5000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B5800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B6000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B6800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B7000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B7800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B8000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B8800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B9000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+B9800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BA000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BA800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BB000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BB800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BC000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BC800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BD000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BD800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BE000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BE800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BF000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+BF800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C0000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C0800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C1000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C1800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C2000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C2800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C3000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C3800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C4000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C4800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C5000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C5800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C6000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C6800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C7000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C7800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C8000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C8800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C9000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+C9800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CA000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CA800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CB000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CB800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CC000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CC800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CD000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CD800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CE000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CE800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CF000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+CF800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D0000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D0800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D1000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D1800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D2000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D2800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D3000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D3800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D4000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D4800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D5000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D5800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D6000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D6800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D7000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D7800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D8000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D8800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D9000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+D9800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DA000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DA800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DB000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DB800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DC000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DC800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DD000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DD800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DE000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DE800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DF000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+DF800 */
-282,283,284,285,283,283,283,283,283,283,283,283,283,283,283,283, /* U+E0000 */
-283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, /* U+E0800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E1000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E1800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E2000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E2800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E3000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E3800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E4000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E4800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E5000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E5800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E6000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E6800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E7000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E7800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E8000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E8800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E9000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+E9800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EA000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EA800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EB000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EB800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EC000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EC800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+ED000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+ED800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EE000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EE800 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EF000 */
-141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141, /* U+EF800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F0000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F0800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F1000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F1800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F2000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F2800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F3000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F3800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F4000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F4800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F5000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F5800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F6000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F6800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F7000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F7800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F8000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F8800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F9000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+F9800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FA000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FA800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FB000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FB800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FC000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FC800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FD000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FD800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FE000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FE800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+FF000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,286, /* U+FF800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+100000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+100800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+101000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+101800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+102000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+102800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+103000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+103800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+104000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+104800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+105000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+105800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+106000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+106800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+107000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+107800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+108000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+108800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+109000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+109800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10A000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10A800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10B000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10B800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10C000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10C800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10D000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10D800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10E000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10E800 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,125, /* U+10F000 */
-125,125,125,125,125,125,125,125,125,125,125,125,125,125,125,286, /* U+10F800 */
+ 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, /* U+2000 */
+ 78, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, /* U+2800 */
+ 93, 94, 95, 96, 97, 98, 99,100,101,101,101,101,101,101,101,101, /* U+3000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+3800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+4000 */
+101,101,101,101,101,101,101,101,101,101,101,102,101,101,101,101, /* U+4800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+5800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+6800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+7800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+8800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+9800 */
+103,104,104,104,104,104,104,104,104,105,106,106,107,108,109,110, /* U+A000 */
+111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,119, /* U+A800 */
+120,121,122,123,124,125,119,120,121,122,123,124,125,119,120,121, /* U+B000 */
+122,123,124,125,119,120,121,122,123,124,125,119,120,121,122,123, /* U+B800 */
+124,125,119,120,121,122,123,124,125,119,120,121,122,123,124,125, /* U+C000 */
+119,120,121,122,123,124,125,119,120,121,122,123,124,125,119,120, /* U+C800 */
+121,122,123,124,125,119,120,121,122,123,124,125,119,120,121,126, /* U+D000 */
+127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127, /* U+D800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+E800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F000 */
+128,128,129,129,130,131,132,133,134,135,136,137,138,139,140,141, /* U+F800 */
+142,143,144,145,146,147,148,149,150,151,152,153,154,154,155,156, /* U+10000 */
+157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172, /* U+10800 */
+173,174,175,176,177,178,179,146,180,181,146,182,183,184,185,146, /* U+11000 */
+186,187,188,189,190,191,146,146,192,193,194,195,146,196,146,197, /* U+11800 */
+198,198,198,198,198,198,198,199,200,198,201,146,146,146,146,146, /* U+12000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,202, /* U+12800 */
+203,203,203,203,203,203,203,203,204,146,146,146,146,146,146,146, /* U+13000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+13800 */
+146,146,146,146,146,146,146,146,205,205,205,205,206,146,146,146, /* U+14000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+14800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+15800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+16000 */
+207,207,207,207,208,209,210,211,146,146,146,146,212,213,214,215, /* U+16800 */
+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* U+17000 */
+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,216, /* U+17800 */
+216,216,216,216,216,216,216,216,216,216,216,216,216,216,216,217, /* U+18000 */
+216,216,216,216,216,216,218,218,218,219,220,146,146,146,146,146, /* U+18800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+19800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,221, /* U+1A800 */
+222,223,224,225,225,226,146,146,146,146,146,146,146,146,146,146, /* U+1B000 */
+146,146,146,146,146,146,146,146,227,228,146,146,146,146,146,146, /* U+1B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+1C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,229,230, /* U+1C800 */
+231,232,233,234,235,236,237,146,238,239,240,241,242,243,244,245, /* U+1D000 */
+246,246,246,246,247,248,146,146,146,146,146,146,146,146,249,146, /* U+1D800 */
+250,146,251,146,146,252,146,146,146,146,146,146,146,146,146,253, /* U+1E000 */
+254,255,256,168,168,168,168,168,257,258,259,168,260,261,168,168, /* U+1E800 */
+262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277, /* U+1F000 */
+278,279,280,281,282,283,284,285,267,267,267,267,267,267,267,286, /* U+1F800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+20800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+21800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+22800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+23800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+24800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+25800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+26800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+27800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+28800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+29800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,287,101,101, /* U+2A000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2A800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,288,101, /* U+2B000 */
+289,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2B800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2C000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,290,101,101, /* U+2C800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2D800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+2E000 */
+101,101,101,101,101,101,101,291,146,146,146,146,146,146,146,146, /* U+2E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+2F000 */
+129,129,129,129,292,146,146,146,146,146,146,146,146,146,146,293, /* U+2F800 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30000 */
+101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101, /* U+30800 */
+101,101,101,101,101,101,294,146,146,146,146,146,146,146,146,146, /* U+31000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+31800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+32800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+33800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+34800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+35800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+36800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+37800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+38800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+39800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+3F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+3F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+40800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+41800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+42800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+43800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+44800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+45800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+46800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+47800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+48800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+49800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+4F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+4F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+50800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+51800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+52800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+53800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+54800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+55800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+56800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+57800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+58800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+59800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+5F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+5F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+60800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+61800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+62800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+63800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+64800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+65800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+66800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+67800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+68800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+69800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+6F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+6F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+70800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+71800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+72800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+73800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+74800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+75800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+76800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+77800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+78800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+79800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+7F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+7F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+80800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+81800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+82800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+83800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+84800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+85800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+86800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+87800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+88800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+89800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+8F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+8F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+90800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+91800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+92800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+93800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+94800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+95800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+96800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+97800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+98800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+99800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9A800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9B800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9C800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9D800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9E800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+9F000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+9F800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A0800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A1800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A2800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A3800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A4800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A5800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A6800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A7800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A8800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+A9800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AA800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AB800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AC800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AD800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AE800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+AF000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+AF800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B0800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B1800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B2800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B3800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B4800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B5800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B6800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B7800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B8800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+B9800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BA800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BB800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BC800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BD800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BE800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+BF000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+BF800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C0800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C1800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C2800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C3800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C4800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C5800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C6800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C7800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C8800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+C9800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CA800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CB800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CC800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CD800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CE800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+CF000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+CF800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D0800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D1800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D2800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D3800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D4800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D5800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D6800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D7800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D8800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+D9800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DA800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DB800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DC800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DD800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DE800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+DF000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+DF800 */
+295,296,297,298,296,296,296,296,296,296,296,296,296,296,296,296, /* U+E0000 */
+296,296,296,296,296,296,296,296,296,296,296,296,296,296,296,296, /* U+E0800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E1800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E2800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E3800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E4800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E5800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E6800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E7800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E8800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+E9800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EA800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EB800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EC800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+ED800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EE800 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,146, /* U+EF000 */
+146,146,146,146,146,146,146,146,146,146,146,146,146,146,146,293, /* U+EF800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F0800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F1800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F2800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F3800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F4800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F5800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F6800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F7800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F8800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+F9800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FA800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FB800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FC800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FD800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FE800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+FF000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,299, /* U+FF800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+100800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+101800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+102800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+103800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+104800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+105800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+106800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+107800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+108800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+109800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10A800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10B800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10C800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10D800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10E800 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128, /* U+10F000 */
+128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,299, /* U+10F800 */
};
-const uint16_t PRIV(ucd_stage2)[] = { /* 73472 bytes, block = 128 */
+const uint16_t PRIV(ucd_stage2)[] = { /* 76800 bytes, block = 128 */
+
/* block 0 */
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 4, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 9, 9, 9, 5,
- 5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 12, 12, 12, 12,
- 12, 12, 12, 14, 12, 12, 12, 12, 12, 12, 12, 7, 5, 8, 15, 16,
- 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 17, 17, 17, 17,
- 17, 17, 17, 19, 17, 17, 17, 17, 17, 17, 17, 7, 9, 8, 9, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 3, 4, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 25, 26, 27, 26, 8,
+ 13, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 30, 29, 29, 29, 29,
+ 29, 29, 29, 31, 29, 29, 29, 29, 29, 29, 29, 15, 13, 16, 32, 33,
+ 34, 35, 35, 35, 35, 35, 35, 36, 36, 37, 37, 38, 36, 36, 36, 36,
+ 36, 36, 36, 39, 36, 36, 36, 36, 36, 36, 36, 15, 27, 16, 27, 0,
/* block 1 */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 4, 5, 6, 6, 6, 6, 20, 5, 15, 21, 22, 23, 9, 24, 21, 15,
- 20, 9, 25, 25, 15, 26, 5, 5, 15, 25, 22, 27, 25, 25, 25, 5,
- 12, 12, 12, 12, 12, 28, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 29,
- 17, 17, 17, 17, 17, 30, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 9, 17, 17, 17, 17, 17, 17, 17, 31,
+ 40, 40, 40, 40, 40, 41, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,
+ 42, 43, 44, 44, 44, 44, 45, 43, 46, 47, 48, 49, 50, 51, 47, 46,
+ 52, 53, 54, 54, 46, 55, 43, 56, 46, 54, 48, 57, 58, 58, 58, 43,
+ 59, 59, 59, 59, 59, 60, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 50, 59, 59, 59, 59, 59, 59, 59, 61,
+ 62, 62, 62, 62, 62, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 50, 62, 62, 62, 62, 62, 62, 62, 64,
/* block 2 */
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 34, 35, 32, 33, 32, 33, 32, 33, 35, 32, 33, 32, 33, 32, 33, 32,
- 33, 32, 33, 32, 33, 32, 33, 32, 33, 35, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 36, 32, 33, 32, 33, 32, 33, 37,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67,
+ 68, 69, 65, 66, 65, 66, 65, 66, 70, 65, 66, 65, 66, 65, 66, 65,
+ 66, 65, 66, 65, 66, 65, 66, 65, 66, 71, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 72, 65, 66, 65, 66, 65, 66, 73,
/* block 3 */
- 38, 39, 32, 33, 32, 33, 40, 32, 33, 41, 41, 32, 33, 35, 42, 43,
- 44, 32, 33, 41, 45, 46, 47, 48, 32, 33, 49, 35, 47, 50, 51, 52,
- 32, 33, 32, 33, 32, 33, 53, 32, 33, 53, 35, 35, 32, 33, 53, 32,
- 33, 54, 54, 32, 33, 32, 33, 55, 32, 33, 35, 22, 32, 33, 35, 56,
- 22, 22, 22, 22, 57, 58, 59, 60, 61, 62, 63, 64, 65, 32, 33, 32,
- 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 66, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 35, 67, 68, 69, 32, 33, 70, 71, 32, 33, 32, 33, 32, 33, 32, 33,
+ 74, 75, 65, 66, 65, 66, 76, 65, 66, 77, 77, 65, 66, 70, 78, 79,
+ 80, 65, 66, 77, 81, 82, 83, 84, 65, 66, 85, 70, 83, 86, 87, 88,
+ 65, 66, 65, 66, 65, 66, 89, 65, 66, 89, 70, 70, 65, 66, 89, 65,
+ 66, 90, 90, 65, 66, 65, 66, 91, 65, 66, 70, 92, 65, 66, 70, 93,
+ 92, 92, 92, 92, 94, 95, 96, 97, 98, 99,100,101,102, 65, 66, 65,
+ 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,103, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 69,104,105,106, 65, 66,107,108, 65, 66, 65, 66, 65, 66, 65, 66,
/* block 4 */
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 72, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 35, 35, 35, 35, 35, 35, 73, 32, 33, 74, 75, 76,
- 76, 32, 33, 77, 78, 79, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 80, 81, 82, 83, 84, 35, 85, 85, 35, 86, 35, 87, 88, 35, 35, 35,
- 85, 89, 35, 90, 35, 91, 92, 35, 93, 94, 92, 95, 96, 35, 35, 94,
- 35, 97, 98, 35, 35, 99, 35, 35, 35, 35, 35, 35, 35,100, 35, 35,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+109, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 70, 70, 70, 70, 70, 70,110, 65, 66,111,112,113,
+113, 65, 66,114,115,116, 65, 66, 65, 67, 65, 66, 65, 66, 65, 66,
+117,118,119,120,121, 70,122,122, 70,123, 70,124,125, 70, 70, 70,
+122,126, 70,127, 70,128,129, 70,130,131,129,132,133, 70, 70,131,
+ 70,134,135, 70, 70,136, 70, 70, 70, 70, 70, 70, 70,137, 70, 70,
/* block 5 */
-101, 35,102,101, 35, 35, 35,103,101,104,105,105,106, 35, 35, 35,
- 35, 35,107, 35, 22, 35, 35, 35, 35, 35, 35, 35, 35,108,109, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
-110,110,110,110,110,110,110,110,110,111,111,111,111,111,111,111,
-111,111, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,111,
-111,111, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-110,110,110,110,110, 15, 15, 15, 15, 15,112,112,111, 15,111, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+138, 70,139,138, 70, 70, 70,140,138,141,142,142,143, 70, 70, 70,
+ 70, 70,144, 70, 92, 70, 70, 70, 70, 70, 70, 70, 70,145,146, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+147,147,148,147,147,147,147,147,147,149,149,150,150,150,150,150,
+151,151, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,149,
+152,152, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+147,147,147,147,147, 46, 46, 46, 46, 46,153,153,149, 46,150, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
/* block 6 */
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,114,113,113,115,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,116,116,116,116,116,116,116,116,116,116,116,116,116,
-117,118,117,118,111,119,117,118,120,120,121,122,122,122, 5,123,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,155,154,154,156,154,154,154,154,154,154,154,154,154,157,
+154,154,154,154,154,154,154,154,158,158,158,158,158,154,154,154,
+154,154,154,159,159,159,159,159,159,159,159,159,159,159,159,159,
+160,161,160,161,149,162,160,161,163,163,164,165,165,165,166,167,
/* block 7 */
-120,120,120,120,119, 15,124, 5,125,125,125,120,126,120,127,127,
-128,129,130,129,129,131,129,129,132,133,134,129,135,129,129,129,
-136,137,120,138,129,129,139,129,129,140,129,129,141,142,142,142,
-128,143,144,143,143,145,143,143,146,147,148,143,149,143,143,143,
-150,151,152,153,143,143,154,143,143,155,143,143,156,157,157,158,
-159,160,161,161,161,162,163,164,117,118,117,118,117,118,117,118,
-117,118,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-167,168,169,170,171,172,173,117,118,174,117,118,128,175,175,175,
+163,163,163,163,162, 46,168,169,170,170,170,163,171,163,172,172,
+173,174,175,174,174,176,174,174,177,178,179,174,180,174,174,174,
+181,182,163,183,174,174,184,174,174,185,174,174,186,187,187,187,
+173,188,189,188,188,190,188,188,191,192,193,188,194,188,188,188,
+195,196,197,198,188,188,199,188,188,200,188,188,201,202,202,203,
+204,205,206,207,207,208,209,210,160,161,160,161,160,161,160,161,
+160,161,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+213,214,215,216,217,218,219,160,161,220,160,161,221,222,222,222,
/* block 8 */
-176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,176,
-177,177,178,177,179,177,177,177,177,177,177,177,177,177,180,177,
-177,181,182,177,177,177,177,177,177,177,183,177,177,177,177,177,
-184,184,185,184,186,184,184,184,184,184,184,184,184,184,187,184,
-184,188,189,184,184,184,184,184,184,184,190,184,184,184,184,184,
-191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,191,
-192,193,194,195,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,223,
+224,224,225,224,226,224,224,224,224,224,224,224,224,224,227,224,
+224,228,229,224,224,224,224,224,224,224,230,224,224,224,224,224,
+231,231,232,231,233,231,231,231,231,231,231,231,231,231,234,231,
+231,235,236,231,231,231,231,231,231,231,237,231,231,231,231,231,
+238,238,238,238,238,238,239,238,239,238,238,238,238,238,238,238,
+240,241,242,243,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
/* block 9 */
-192,193,196,197,198,199,199,198,200,200,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-201,192,193,192,193,192,193,192,193,192,193,192,193,192,193,202,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
+240,241,244,245,246,247,247,246,248,248,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+249,240,241,240,241,240,241,240,241,240,241,240,241,240,241,250,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
/* block 10 */
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-120,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,
-203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,
-203,203,203,203,203,203,203,120,120,204,205,205,205,205,205,205,
-206,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
-207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,207,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+163,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
+251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,251,
+251,251,251,251,251,251,251,163,163,252,253,253,253,253,253,254,
+255,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
+256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,
/* block 11 */
-207,207,207,207,207,207,207,206,206,205,208,120,120,209,209,210,
-120,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,
-211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,211,
-211,211,211,211,211,211,211,211,211,211,211,211,211,211,212,211,
-213,211,211,213,211,211,213,211,120,120,120,120,120,120,120,120,
-214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,214,
-214,214,214,214,214,214,214,214,214,214,214,120,120,120,120,214,
-214,214,214,213,213,120,120,120,120,120,120,120,120,120,120,120,
+256,256,256,256,256,256,256,257,255,258,259,163,163,260,260,261,
+262,263,263,263,263,263,263,263,263,263,263,263,263,263,263,263,
+263,263,264,263,263,263,263,263,263,263,263,263,263,263,263,263,
+265,265,265,265,265,265,265,265,265,265,265,265,265,265,266,265,
+267,265,265,268,265,269,267,269,262,262,262,262,262,262,262,262,
+270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,270,
+270,270,270,270,270,270,270,270,270,270,270,262,262,262,262,270,
+270,270,270,267,271,262,262,262,262,262,262,262,262,262,262,262,
/* block 12 */
-215,215,215,215,215,216,217,217,217,218,218,219,220,218,221,221,
-222,222,222,222,222,222,222,222,222,222,222,220,223,218,218,224,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-226,225,225,225,225,225,225,225,225,225,225,227,227,227,227,227,
-227,227,227,227,227,227,222,222,222,222,222,222,222,222,222,222,
-228,228,228,228,228,228,228,228,228,228,218,218,218,218,225,225,
-227,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+272,272,272,272,272,273,274,274,275,276,276,277,278,279,280,280,
+281,281,281,281,281,281,281,281,281,281,281,282,283,284,284,285,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+287,286,286,286,286,286,286,286,286,286,286,288,288,288,288,288,
+288,288,288,289,289,289,281,290,291,281,281,281,281,281,281,281,
+292,292,292,292,292,292,292,292,292,292,276,293,293,279,286,286,
+289,286,286,294,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 13 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,229,225,222,222,222,222,222,222,222,216,221,222,
-222,222,222,222,222,230,230,222,222,221,222,222,222,222,225,225,
-231,231,231,231,231,231,231,231,231,231,225,225,225,221,221,225,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,295,286,281,281,281,281,281,281,281,273,280,291,
+291,281,281,281,281,296,296,281,281,280,291,291,291,281,286,286,
+297,297,297,297,297,297,297,297,297,297,286,286,286,298,298,286,
/* block 14 */
-232,232,232,232,232,232,232,232,232,232,232,232,232,232,120,233,
-234,235,234,234,234,234,234,234,234,234,234,234,234,234,234,234,
-234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,234,
-235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,235,
-235,235,235,235,235,235,235,235,235,235,235,120,120,234,234,234,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+299,299,299,300,300,300,300,300,300,300,300,301,300,301,302,303,
+304,305,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
+304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,304,
+306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
+307,307,307,307,307,307,307,307,307,307,307,302,302,304,304,304,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 15 */
-236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,236,
-236,236,236,236,236,236,237,237,237,237,237,237,237,237,237,237,
-237,236,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-238,238,238,238,238,238,238,238,238,238,239,239,239,239,239,239,
-239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,239,
-239,239,239,239,239,239,239,239,239,239,239,240,240,240,240,240,
-240,240,240,240,241,241,242,243,243,243,241,120,120,240,244,244,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,308,
+308,308,308,308,308,308,309,309,309,309,309,309,309,309,309,309,
+309,308,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+310,310,310,310,310,310,310,310,310,310,311,311,311,311,311,311,
+311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,311,
+311,311,311,311,311,311,311,311,311,311,311,312,312,312,312,312,
+312,312,312,312,313,313,314,315,316,317,318,262,262,319,320,320,
/* block 16 */
-245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,245,
-245,245,245,245,245,245,246,246,246,246,247,246,246,246,246,246,
-246,246,246,246,247,246,246,246,247,246,246,246,246,246,120,120,
-248,248,248,248,248,248,248,248,248,248,248,248,248,248,248,120,
-249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,249,
-249,249,249,249,249,249,249,249,249,250,250,250,120,120,251,120,
-234,234,234,234,234,234,234,234,234,234,234,120,120,120,120,120,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,321,
+321,321,321,321,321,321,322,322,323,323,324,322,322,322,322,322,
+322,322,322,322,324,322,322,322,324,322,322,322,322,325,262,262,
+326,326,326,326,326,326,326,327,326,327,326,326,326,327,327,262,
+328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,328,
+328,328,328,328,328,328,328,328,328,329,329,329,262,262,330,262,
+304,304,304,304,304,304,304,304,304,304,304,302,302,302,302,302,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 17 */
-225,225,225,225,225,225,225,225,252,225,225,225,225,225,225,120,
-215,215,120,120,120,120,120,120,222,222,222,222,222,222,222,222,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,230,222,222,222,222,222,222,
-222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
-222,222,216,222,222,222,222,222,222,222,222,222,222,222,222,222,
-222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,222,
+286,286,286,286,286,286,286,286,331,286,286,286,286,286,286,302,
+272,272,302,302,302,302,302,302,291,291,291,291,291,291,291,291,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,296,291,291,291,291,291,291,
+291,291,291,332,281,281,281,281,281,281,281,281,281,281,281,281,
+332,332,273,290,290,290,290,290,290,290,291,291,291,291,291,291,
+290,290,290,290,290,290,290,290,290,290,290,290,290,290,290,281,
/* block 18 */
-253,253,253,254,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
-255,255,255,255,255,255,255,255,255,255,253,254,253,255,254,254,
-254,253,253,253,253,253,253,253,253,254,254,254,254,253,254,254,
-255,256,257,113,113,253,253,253,255,255,255,255,255,255,255,255,
-255,255,253,253,258,259,260,260,260,260,260,260,260,260,260,260,
-261,262,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
+333,333,333,334,335,335,335,335,335,335,335,335,335,335,335,335,
+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
+335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
+335,335,335,335,335,335,335,335,335,335,333,334,336,335,334,334,
+334,333,333,333,333,333,333,333,333,334,334,334,334,337,334,334,
+335,338,339,154,154,333,333,333,335,335,335,335,335,335,335,335,
+335,335,333,333,340,341,342,342,342,342,342,342,342,342,342,342,
+343,344,335,335,335,335,335,335,335,335,335,335,335,335,335,335,
/* block 19 */
-263,264,265,265,120,263,263,263,263,263,263,263,263,120,120,263,
-263,120,120,263,263,263,263,263,263,263,263,263,263,263,263,263,
-263,263,263,263,263,263,263,263,263,120,263,263,263,263,263,263,
-263,120,263,120,120,120,263,263,263,263,120,120,264,263,266,265,
-265,264,264,264,264,120,120,265,265,120,120,265,265,264,263,120,
-120,120,120,120,120,120,120,266,120,120,120,120,263,263,120,263,
-263,263,264,264,120,120,267,267,267,267,267,267,267,267,267,267,
-263,263,268,268,269,269,269,269,269,269,270,268,263,271,264,120,
+345,346,347,347,163,345,345,345,345,345,345,345,345,163,163,345,
+345,163,163,345,345,345,345,345,345,345,345,345,345,345,345,345,
+345,345,345,345,345,345,345,345,345,163,345,345,345,345,345,345,
+345,163,345,163,163,163,345,345,345,345,163,163,348,345,349,347,
+347,346,346,346,346,163,163,347,347,163,163,347,347,350,345,163,
+163,163,163,163,163,163,163,349,163,163,163,163,345,345,163,345,
+345,345,346,346,163,163,351,351,351,351,351,351,351,351,351,351,
+345,345,352,352,353,353,353,353,353,353,354,352,345,355,356,163,
/* block 20 */
-120,272,272,273,120,274,274,274,274,274,274,120,120,120,120,274,
-274,120,120,274,274,274,274,274,274,274,274,274,274,274,274,274,
-274,274,274,274,274,274,274,274,274,120,274,274,274,274,274,274,
-274,120,274,274,120,274,274,120,274,274,120,120,272,120,273,273,
-273,272,272,120,120,120,120,272,272,120,120,272,272,272,120,120,
-120,272,120,120,120,120,120,120,120,274,274,274,274,120,274,120,
-120,120,120,120,120,120,275,275,275,275,275,275,275,275,275,275,
-272,272,274,274,274,272,276,120,120,120,120,120,120,120,120,120,
+163,357,357,358,163,359,359,359,359,359,359,163,163,163,163,359,
+359,163,163,359,359,359,359,359,359,359,359,359,359,359,359,359,
+359,359,359,359,359,359,359,359,359,163,359,359,359,359,359,359,
+359,163,359,359,163,359,359,163,359,359,163,163,360,163,358,358,
+358,357,357,163,163,163,163,357,357,163,163,357,357,361,163,163,
+163,357,163,163,163,163,163,163,163,359,359,359,359,163,359,163,
+163,163,163,163,163,163,362,362,362,362,362,362,362,362,362,362,
+357,357,359,359,359,357,363,163,163,163,163,163,163,163,163,163,
/* block 21 */
-120,277,277,278,120,279,279,279,279,279,279,279,279,279,120,279,
-279,279,120,279,279,279,279,279,279,279,279,279,279,279,279,279,
-279,279,279,279,279,279,279,279,279,120,279,279,279,279,279,279,
-279,120,279,279,120,279,279,279,279,279,120,120,277,279,278,278,
-278,277,277,277,277,277,120,277,277,278,120,278,278,277,120,120,
-279,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-279,279,277,277,120,120,280,280,280,280,280,280,280,280,280,280,
-281,282,120,120,120,120,120,120,120,279,277,277,277,277,277,277,
+163,364,364,365,163,366,366,366,366,366,366,366,366,366,163,366,
+366,366,163,366,366,366,366,366,366,366,366,366,366,366,366,366,
+366,366,366,366,366,366,366,366,366,163,366,366,366,366,366,366,
+366,163,366,366,163,366,366,366,366,366,163,163,367,366,365,365,
+365,364,364,364,364,364,163,364,364,365,163,365,365,368,163,163,
+366,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+366,366,364,364,163,163,369,369,369,369,369,369,369,369,369,369,
+370,371,163,163,163,163,163,163,163,366,364,364,364,367,367,367,
/* block 22 */
-120,283,284,284,120,285,285,285,285,285,285,285,285,120,120,285,
-285,120,120,285,285,285,285,285,285,285,285,285,285,285,285,285,
-285,285,285,285,285,285,285,285,285,120,285,285,285,285,285,285,
-285,120,285,285,120,285,285,285,285,285,120,120,283,285,286,283,
-284,283,283,283,283,120,120,284,284,120,120,284,284,283,120,120,
-120,120,120,120,120,283,283,286,120,120,120,120,285,285,120,285,
-285,285,283,283,120,120,287,287,287,287,287,287,287,287,287,287,
-288,285,289,289,289,289,289,289,120,120,120,120,120,120,120,120,
+163,372,373,373,163,374,374,374,374,374,374,374,374,163,163,374,
+374,163,163,374,374,374,374,374,374,374,374,374,374,374,374,374,
+374,374,374,374,374,374,374,374,374,163,374,374,374,374,374,374,
+374,163,374,374,163,374,374,374,374,374,163,163,375,374,376,372,
+373,372,372,372,372,163,163,373,373,163,163,373,373,377,163,163,
+163,163,163,163,163,378,372,376,163,163,163,163,374,374,163,374,
+374,374,372,372,163,163,379,379,379,379,379,379,379,379,379,379,
+380,374,381,381,381,381,381,381,163,163,163,163,163,163,163,163,
/* block 23 */
-120,120,290,291,120,291,291,291,291,291,291,120,120,120,291,291,
-291,120,291,291,291,291,120,120,120,291,291,120,291,120,291,291,
-120,120,120,291,291,120,120,120,291,291,291,120,120,120,291,291,
-291,291,291,291,291,291,291,291,291,291,120,120,120,120,292,293,
-290,293,293,120,120,120,293,293,293,120,293,293,293,290,120,120,
-291,120,120,120,120,120,120,292,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,294,294,294,294,294,294,294,294,294,294,
-295,295,295,296,297,297,297,297,297,298,297,120,120,120,120,120,
+163,163,382,383,163,383,383,383,383,383,383,163,163,163,383,383,
+383,163,383,383,383,383,163,163,163,383,383,163,383,163,383,383,
+163,163,163,383,383,163,163,163,383,383,383,163,163,163,383,383,
+383,383,383,383,383,383,383,383,383,383,163,163,163,163,384,385,
+382,385,385,163,163,163,385,385,385,163,385,385,385,386,163,163,
+383,163,163,163,163,163,163,384,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,387,387,387,387,387,387,387,387,387,387,
+388,388,388,389,390,390,390,390,390,391,390,163,163,163,163,163,
/* block 24 */
-299,300,300,300,299,301,301,301,301,301,301,301,301,120,301,301,
-301,120,301,301,301,301,301,301,301,301,301,301,301,301,301,301,
-301,301,301,301,301,301,301,301,301,120,301,301,301,301,301,301,
-301,301,301,301,301,301,301,301,301,301,120,120,299,301,299,299,
-299,300,300,300,300,120,299,299,299,120,299,299,299,299,120,120,
-120,120,120,120,120,299,299,120,301,301,301,120,120,301,120,120,
-301,301,299,299,120,120,302,302,302,302,302,302,302,302,302,302,
-120,120,120,120,120,120,120,303,304,304,304,304,304,304,304,305,
+392,393,393,393,394,395,395,395,395,395,395,395,395,163,395,395,
+395,163,395,395,395,395,395,395,395,395,395,395,395,395,395,395,
+395,395,395,395,395,395,395,395,395,163,395,395,395,395,395,395,
+395,395,395,395,395,395,395,395,395,395,163,163,396,395,392,392,
+392,393,393,393,393,163,392,392,392,163,392,392,392,397,163,163,
+163,163,163,163,163,392,392,163,395,395,395,163,163,395,163,163,
+395,395,392,392,163,163,398,398,398,398,398,398,398,398,398,398,
+163,163,163,163,163,163,163,399,400,400,400,400,400,400,400,401,
/* block 25 */
-306,307,308,308,309,306,306,306,306,306,306,306,306,120,306,306,
-306,120,306,306,306,306,306,306,306,306,306,306,306,306,306,306,
-306,306,306,306,306,306,306,306,306,120,306,306,306,306,306,306,
-306,306,306,306,120,306,306,306,306,306,120,120,307,306,308,307,
-308,308,310,308,308,120,307,308,308,120,308,308,307,307,120,120,
-120,120,120,120,120,310,310,120,120,120,120,120,120,306,306,120,
-306,306,307,307,120,120,311,311,311,311,311,311,311,311,311,311,
-120,306,306,120,120,120,120,120,120,120,120,120,120,120,120,120,
+402,403,404,404,405,402,402,402,402,402,402,402,402,163,402,402,
+402,163,402,402,402,402,402,402,402,402,402,402,402,402,402,402,
+402,402,402,402,402,402,402,402,402,163,402,402,402,402,402,402,
+402,402,402,402,163,402,402,402,402,402,163,163,406,402,404,407,
+404,404,408,404,404,163,407,404,404,163,404,404,403,409,163,163,
+163,163,163,163,163,408,408,163,163,163,163,163,163,402,402,163,
+402,402,403,403,163,163,410,410,410,410,410,410,410,410,410,410,
+163,402,402,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 26 */
-312,312,313,313,314,314,314,314,314,314,314,314,314,120,314,314,
-314,120,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,314,
-314,314,314,314,314,314,314,314,314,314,314,312,312,314,315,313,
-313,312,312,312,312,120,313,313,313,120,313,313,313,312,316,317,
-120,120,120,120,314,314,314,315,318,318,318,318,318,318,318,314,
-314,314,312,312,120,120,319,319,319,319,319,319,319,319,319,319,
-318,318,318,318,318,318,318,318,318,317,314,314,314,314,314,314,
+411,411,412,412,413,413,413,413,413,413,413,413,413,163,413,413,
+413,163,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
+413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
+413,413,413,413,413,413,413,413,413,413,413,414,414,413,415,412,
+412,411,411,411,411,163,412,412,412,163,412,412,412,414,416,417,
+163,163,163,163,413,413,413,415,418,418,418,418,418,418,418,413,
+413,413,411,411,163,163,419,419,419,419,419,419,419,419,419,419,
+418,418,418,418,418,418,418,418,418,417,413,413,413,413,413,413,
/* block 27 */
-120,320,321,321,120,322,322,322,322,322,322,322,322,322,322,322,
-322,322,322,322,322,322,322,120,120,120,322,322,322,322,322,322,
-322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,
-322,322,120,322,322,322,322,322,322,322,322,322,120,322,120,120,
-322,322,322,322,322,322,322,120,120,120,320,120,120,120,120,323,
-321,321,320,320,320,120,320,120,321,321,321,321,321,321,321,323,
-120,120,120,120,120,120,324,324,324,324,324,324,324,324,324,324,
-120,120,321,321,325,120,120,120,120,120,120,120,120,120,120,120,
+163,420,421,421,163,422,422,422,422,422,422,422,422,422,422,422,
+422,422,422,422,422,422,422,163,163,163,422,422,422,422,422,422,
+422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
+422,422,163,422,422,422,422,422,422,422,422,422,163,422,163,163,
+422,422,422,422,422,422,422,163,163,163,423,163,163,163,163,424,
+421,421,420,420,420,163,420,163,421,421,421,421,421,421,421,424,
+163,163,163,163,163,163,425,425,425,425,425,425,425,425,425,425,
+163,163,421,421,426,163,163,163,163,163,163,163,163,163,163,163,
/* block 28 */
-120,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
-326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
-326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,326,
-326,327,326,328,327,327,327,327,327,327,327,120,120,120,120, 6,
-326,326,326,326,326,326,329,327,327,327,327,327,327,327,327,330,
-331,331,331,331,331,331,331,331,331,331,330,330,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,
+427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,
+427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,427,
+427,428,427,429,428,428,428,428,428,428,430,163,163,163,163,431,
+432,432,432,432,432,427,433,434,434,434,434,434,434,428,434,435,
+436,436,436,436,436,436,436,436,436,436,437,437,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 29 */
-120,332,332,120,332,120,332,332,332,332,332,120,332,332,332,332,
-332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,332,
-332,332,332,332,120,332,120,332,332,332,332,332,332,332,332,332,
-332,333,332,334,333,333,333,333,333,333,333,333,333,332,120,120,
-332,332,332,332,332,120,335,120,333,333,333,333,333,333,120,120,
-336,336,336,336,336,336,336,336,336,336,120,120,332,332,332,332,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,438,438,163,438,163,438,438,438,438,438,163,438,438,438,438,
+438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,438,
+438,438,438,438,163,438,163,438,438,438,438,438,438,438,438,438,
+438,439,438,440,439,439,439,439,439,439,441,439,439,438,163,163,
+442,442,442,442,442,163,443,163,444,444,444,444,444,439,163,163,
+445,445,445,445,445,445,445,445,445,445,163,163,438,438,438,438,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 30 */
-337,338,338,338,339,339,339,339,339,339,339,339,339,339,339,339,
-339,339,339,338,339,338,338,338,340,340,338,338,338,338,338,338,
-341,341,341,341,341,341,341,341,341,341,342,342,342,342,342,342,
-342,342,342,342,338,340,338,340,338,340,343,344,343,344,345,345,
-337,337,337,337,337,337,337,337,120,337,337,337,337,337,337,337,
-337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,337,
-337,337,337,337,337,337,337,337,337,337,337,337,337,120,120,120,
-120,340,340,340,340,340,340,340,340,340,340,340,340,340,340,345,
+446,447,447,447,448,448,448,448,449,448,448,448,448,449,449,449,
+449,449,449,447,448,447,447,447,450,450,447,447,447,447,447,447,
+451,451,451,451,451,451,451,451,451,451,452,452,452,452,452,452,
+452,452,452,452,447,450,447,450,447,450,453,454,453,454,455,455,
+446,446,446,446,446,446,446,446,163,446,446,446,446,446,446,446,
+446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,446,
+446,446,446,446,446,446,446,446,446,446,446,446,446,163,163,163,
+163,456,456,456,456,456,456,457,456,457,456,456,456,456,456,458,
/* block 31 */
-340,340,340,340,340,339,340,340,337,337,337,337,337,340,340,340,
-340,340,340,340,340,340,340,340,120,340,340,340,340,340,340,340,
-340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,340,
-340,340,340,340,340,340,340,340,340,340,340,340,340,120,338,338,
-338,338,338,338,338,338,340,338,338,338,338,338,338,120,338,338,
-339,339,339,339,339, 20, 20, 20, 20,339,339,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+456,456,450,450,459,448,450,450,446,446,446,446,446,456,456,456,
+456,456,456,456,456,456,456,456,163,456,456,456,456,456,456,456,
+456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,456,
+456,456,456,456,456,456,456,456,456,456,456,456,456,163,447,447,
+447,447,447,447,447,447,450,447,447,447,447,447,447,163,447,447,
+448,448,448,448,448,460,460,460,460,448,448,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 32 */
-346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,
-346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,
-346,346,346,346,346,346,346,346,346,346,346,347,347,348,348,348,
-348,349,348,348,348,348,348,348,347,348,348,349,349,348,348,346,
-350,350,350,350,350,350,350,350,350,350,351,351,351,351,351,351,
-346,346,346,346,346,346,349,349,348,348,346,346,346,346,348,348,
-348,346,347,347,347,346,346,347,347,347,347,347,347,347,346,346,
-346,348,348,348,348,346,346,346,346,346,346,346,346,346,346,346,
+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,
+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,
+461,461,461,461,461,461,461,461,461,461,461,462,462,463,463,463,
+463,464,463,463,463,463,463,465,462,466,466,464,464,463,463,461,
+467,467,467,467,467,467,467,467,467,467,468,468,469,469,469,469,
+461,461,461,461,461,461,464,464,463,463,461,461,461,461,463,463,
+463,461,462,470,470,461,461,462,462,470,470,470,470,470,461,461,
+461,463,463,463,463,461,461,461,461,461,461,461,461,461,461,461,
/* block 33 */
-346,346,348,347,349,348,348,347,347,347,347,347,347,348,346,347,
-352,352,352,352,352,352,352,352,352,352,347,347,347,348,353,353,
-354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,
-354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,
-354,354,354,354,354,354,120,354,120,120,120,120,120,354,120,120,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,355,
-355,355,355,355,355,355,355,355,355,355,355,356,357,355,355,355,
+461,461,463,462,464,463,463,470,470,470,470,470,470,471,461,470,
+472,472,472,472,472,472,472,472,472,472,470,470,462,463,473,473,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,474,
+474,474,474,474,474,474,163,474,163,163,163,163,163,474,163,163,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,475,
+475,475,475,475,475,475,475,475,475,475,475,476,477,475,475,475,
/* block 34 */
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
-359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,479,
+480,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
/* block 35 */
-359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
-359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
-359,359,359,359,359,359,359,359,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,481,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
/* block 36 */
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,120,361,361,361,361,120,120,
-361,361,361,361,361,361,361,120,361,120,361,361,361,361,120,120,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,163,483,483,483,483,163,163,
+483,483,483,483,483,483,483,163,483,163,483,483,483,483,163,163,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
/* block 37 */
-361,361,361,361,361,361,361,361,361,120,361,361,361,361,120,120,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,120,361,361,361,361,120,120,361,361,361,361,361,361,361,120,
-361,120,361,361,361,361,120,120,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
+483,483,483,483,483,483,483,483,483,163,483,483,483,483,163,163,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,163,
+483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
/* block 38 */
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,120,361,361,361,361,120,120,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,361,361,361,361,120,120,362,362,362,
-363,363,363,363,363,363,363,363,363,364,364,364,364,364,364,364,
-364,364,364,364,364,364,364,364,364,364,364,364,364,120,120,120,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,163,483,483,483,483,163,163,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,483,483,483,483,163,163,484,484,484,
+485,486,487,486,486,486,486,487,487,488,488,488,488,488,488,488,
+488,488,489,489,489,489,489,489,489,489,489,489,489,163,163,163,
/* block 39 */
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-365,365,365,365,365,365,365,365,365,365,120,120,120,120,120,120,
-366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,
-366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,
-366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,
-366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,
-366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,366,
-367,367,367,367,367,367,120,120,368,368,368,368,368,368,120,120,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+490,490,490,490,490,490,490,490,490,490,163,163,163,163,163,163,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,491,
+492,492,492,492,492,492,163,163,493,493,493,493,493,493,163,163,
/* block 40 */
-369,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+494,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
/* block 41 */
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
/* block 42 */
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,371,372,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,496,497,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
/* block 43 */
-373,374,374,374,374,374,374,374,374,374,374,374,374,374,374,374,
-374,374,374,374,374,374,374,374,374,374,374,375,376,120,120,120,
-377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
-377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
-377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
-377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,377,
-377,377,377,377,377,377,377,377,377,377,377, 5, 5, 5,378,378,
-378,377,377,377,377,377,377,377,377,120,120,120,120,120,120,120,
+498,499,499,499,499,499,499,499,499,499,499,499,499,499,499,499,
+499,499,499,499,499,499,499,499,499,499,499,500,501,163,163,163,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,502,
+502,502,502,502,502,502,502,502,502,502,502,503,503,503,504,504,
+504,502,502,502,502,502,502,502,502,163,163,163,163,163,163,163,
/* block 44 */
-379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,379,
-379,379,380,380,380,381,120,120,120,120,120,120,120,120,120,379,
-382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,382,
-382,382,383,383,384,385,385,120,120,120,120,120,120,120,120,120,
-386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,386,
-386,386,387,387,120,120,120,120,120,120,120,120,120,120,120,120,
-388,388,388,388,388,388,388,388,388,388,388,388,388,120,388,388,
-388,120,389,389,120,120,120,120,120,120,120,120,120,120,120,120,
+505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,505,
+505,505,506,506,507,508,163,163,163,163,163,163,163,163,163,505,
+509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,509,
+509,509,510,510,511,512,512,163,163,163,163,163,163,163,163,163,
+513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,513,
+513,513,514,514,163,163,163,163,163,163,163,163,163,163,163,163,
+515,515,515,515,515,515,515,515,515,515,515,515,515,163,515,515,
+515,163,516,516,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 45 */
-390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,
-390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,
-390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,
-390,390,390,390,391,391,392,391,391,391,391,391,391,391,392,392,
-392,392,392,392,392,392,391,392,392,391,391,391,391,391,391,391,
-391,391,391,391,393,393,393,394,393,393,393,395,390,391,120,120,
-396,396,396,396,396,396,396,396,396,396,120,120,120,120,120,120,
-397,397,397,397,397,397,397,397,397,397,120,120,120,120,120,120,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,518,518,517,517,517,517,517,517,517,517,517,517,517,
+517,517,517,517,519,519,520,521,521,521,521,521,521,521,520,520,
+520,520,520,520,520,520,521,520,520,522,522,522,522,522,522,522,
+522,522,523,522,524,524,524,525,526,526,524,527,517,522,163,163,
+528,528,528,528,528,528,528,528,528,528,163,163,163,163,163,163,
+529,529,529,529,529,529,529,529,529,529,163,163,163,163,163,163,
/* block 46 */
-398,398,399,399,398,399,400,398,398,398,398,401,401,401,402,401,
-403,403,403,403,403,403,403,403,403,403,120,120,120,120,120,120,
-404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,405,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,120,120,120,120,120,120,120,
+530,530,531,532,533,531,534,530,533,535,536,537,537,537,538,537,
+539,539,539,539,539,539,539,539,539,539,163,163,163,163,163,163,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,541,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,163,163,163,163,163,163,163,
/* block 47 */
-404,404,404,404,404,401,401,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,404,
-404,404,404,404,404,404,404,404,404,401,404,120,120,120,120,120,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-370,370,370,370,370,370,120,120,120,120,120,120,120,120,120,120,
+540,540,540,540,540,542,542,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,540,
+540,540,540,540,540,540,540,540,540,543,540,163,163,163,163,163,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+495,495,495,495,495,495,163,163,163,163,163,163,163,163,163,163,
/* block 48 */
-406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,
-406,406,406,406,406,406,406,406,406,406,406,406,406,406,406,120,
-407,407,407,408,408,408,408,407,407,408,408,408,120,120,120,120,
-408,408,407,408,408,408,408,408,408,407,407,407,120,120,120,120,
-409,120,120,120,410,410,411,411,411,411,411,411,411,411,411,411,
-412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,412,
-412,412,412,412,412,412,412,412,412,412,412,412,412,412,120,120,
-412,412,412,412,412,120,120,120,120,120,120,120,120,120,120,120,
+544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,
+544,544,544,544,544,544,544,544,544,544,544,544,544,544,544,163,
+545,545,545,546,546,546,546,545,545,546,546,546,163,163,163,163,
+546,546,545,546,546,546,546,546,546,547,547,547,163,163,163,163,
+548,163,163,163,549,549,550,550,550,550,550,550,550,550,550,550,
+551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,551,
+551,551,551,551,551,551,551,551,551,551,551,551,551,551,163,163,
+551,551,551,551,551,163,163,163,163,163,163,163,163,163,163,163,
/* block 49 */
-413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
-413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
-413,413,413,413,413,413,413,413,413,413,413,413,120,120,120,120,
-413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,413,
-413,413,413,413,413,413,413,413,413,413,120,120,120,120,120,120,
-414,414,414,414,414,414,414,414,414,414,415,120,120,120,416,416,
-417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,
-417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,417,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,552,552,163,163,163,163,
+552,552,552,552,552,553,553,553,552,552,553,552,552,552,552,552,
+552,552,552,552,552,552,552,552,552,552,163,163,163,163,163,163,
+554,554,554,554,554,554,554,554,554,554,555,163,163,163,556,556,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
/* block 50 */
-418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,418,
-418,418,418,418,418,418,418,419,419,420,420,419,120,120,421,421,
-422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
-422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
-422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,422,
-422,422,422,422,422,423,424,423,424,424,424,424,424,424,424,120,
-424,425,424,425,425,424,424,424,424,424,424,424,424,423,423,423,
-423,423,423,424,424,424,424,424,424,424,424,424,424,120,120,424,
+558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,558,
+558,558,558,558,558,558,558,559,559,560,560,559,163,163,561,561,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,562,
+562,562,562,562,562,563,564,563,564,564,564,564,564,564,564,163,
+565,566,564,566,566,564,564,564,564,564,564,564,564,563,563,563,
+563,563,563,564,564,567,567,567,567,567,567,567,567,163,163,567,
/* block 51 */
-426,426,426,426,426,426,426,426,426,426,120,120,120,120,120,120,
-426,426,426,426,426,426,426,426,426,426,120,120,120,120,120,120,
-427,427,427,427,427,427,427,428,427,427,427,427,427,427,120,120,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,429,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+568,568,568,568,568,568,568,568,568,568,163,163,163,163,163,163,
+568,568,568,568,568,568,568,568,568,568,163,163,163,163,163,163,
+569,569,569,569,569,569,569,570,571,571,571,571,569,569,163,163,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,572,573,
+573,154,154,154,154,154,154,154,154,154,154,154,573,573,573,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 52 */
-430,430,430,430,431,432,432,432,432,432,432,432,432,432,432,432,
-432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
-432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,432,
-432,432,432,432,430,433,430,430,430,430,430,431,430,431,431,431,
-431,431,430,431,431,432,432,432,432,432,432,432,432,120,120,120,
-434,434,434,434,434,434,434,434,434,434,435,435,435,435,435,435,
-435,436,436,436,436,436,436,436,436,436,436,430,430,430,430,430,
-430,430,430,430,436,436,436,436,436,436,436,436,436,435,435,120,
+574,574,574,574,575,576,576,576,576,576,576,576,576,576,576,576,
+576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
+576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,
+576,576,576,576,577,578,574,574,574,574,574,575,574,575,575,575,
+575,575,574,575,579,576,576,576,576,576,576,576,576,163,163,163,
+580,580,580,580,580,580,580,580,580,580,581,581,582,583,581,581,
+582,584,584,584,584,584,584,584,584,584,584,577,577,577,577,577,
+577,577,577,577,584,584,584,584,584,584,584,584,584,581,581,163,
/* block 53 */
-437,437,438,439,439,439,439,439,439,439,439,439,439,439,439,439,
-439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,439,
-439,438,437,437,437,437,438,438,437,437,438,437,437,437,439,439,
-440,440,440,440,440,440,440,440,440,440,439,439,439,439,439,439,
-441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,
-441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,441,
-441,441,441,441,441,441,442,443,442,442,443,443,443,442,443,442,
-442,442,443,443,120,120,120,120,120,120,120,120,444,444,444,444,
+585,585,586,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
+587,586,585,585,585,585,586,586,585,585,588,589,585,585,587,587,
+590,590,590,590,590,590,590,590,590,590,587,587,587,587,587,587,
+591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+591,591,591,591,591,591,592,593,594,594,593,593,593,594,593,594,
+594,594,595,595,163,163,163,163,163,163,163,163,596,596,596,596,
/* block 54 */
-445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,
-445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,445,
-445,445,445,445,446,446,446,446,446,446,446,446,447,447,447,447,
-447,447,447,447,446,446,447,447,120,120,120,448,448,448,448,448,
-449,449,449,449,449,449,449,449,449,449,120,120,120,445,445,445,
-450,450,450,450,450,450,450,450,450,450,451,451,451,451,451,451,
-451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,451,
-451,451,451,451,451,451,451,451,452,452,452,452,452,452,453,453,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,597,
+597,597,597,597,598,598,598,598,598,598,598,598,599,599,599,599,
+599,599,599,599,598,598,600,601,163,163,163,602,602,603,603,603,
+604,604,604,604,604,604,604,604,604,604,163,163,163,597,597,597,
+605,605,605,605,605,605,605,605,605,605,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+606,606,606,606,606,606,606,606,607,607,607,608,607,607,609,609,
/* block 55 */
-454,455,456,457,458,459,460,461,462,120,120,120,120,120,120,120,
-463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
-463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,463,
-463,463,463,463,463,463,463,463,463,463,463,120,120,463,463,463,
-464,464,464,464,464,464,464,464,120,120,120,120,120,120,120,120,
-465,466,465,467,466,468,468,469,468,469,470,466,469,469,466,466,
-469,471,466,466,466,466,466,466,466,472,473,474,474,468,474,474,
-474,474,475,476,477,473,473,478,479,479,480,120,120,120,120,120,
+610,611,612,613,614,615,616,617,618,163,163,163,163,163,163,163,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,619,
+619,619,619,619,619,619,619,619,619,619,619,163,163,619,619,619,
+620,620,620,620,620,620,620,620,163,163,163,163,163,163,163,163,
+621,622,621,623,622,624,624,625,624,625,626,622,625,625,622,622,
+625,627,622,622,622,622,622,622,622,628,629,630,630,624,630,630,
+630,630,631,632,633,629,629,634,635,635,636,163,163,163,163,163,
/* block 56 */
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35,128,128,128,128,128,481,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,121,121,121,
-121,121,110,110,110,110,121,121,121,121,121, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35,482,483, 35, 35, 35,484, 35, 35,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70,221,221,221,221,221,637,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,638,638,638,
+638,638,148,147,147,147,638,638,638,638,638, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70,639,640, 70, 70, 70,641, 70, 70,
/* block 57 */
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,485, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,121,
-114,114,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,486,113,487,113,113,113,113,113,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,642, 70,
+ 70, 70, 70, 70, 70, 70,643, 70, 70, 70, 70,644,644,644,644,644,
+644,644,644,644,645,644,644,644,645,644,644,644,644,644,644,644,
+644,644,644,644,644,644,644,644,644,644,644,644,644,644,644,646,
+647,647,158,158,154,154,154,154,154,154,154,154,154,154,154,154,
+158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,158,
+158,158,158,158,158,158,158,573,573,573,573,573,573,573,573,573,
+573,573,573,573,573,154,154,154,648,154,649,154,154,154,154,154,
/* block 58 */
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
-488,489, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+650,651, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
/* block 59 */
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 35, 35, 35, 35, 35,490, 35, 35,491, 35,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 69, 69, 69, 69,652,653, 70, 70,654, 70,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 67, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
/* block 60 */
-492,492,492,492,492,492,492,492,493,493,493,493,493,493,493,493,
-492,492,492,492,492,492,120,120,493,493,493,493,493,493,120,120,
-492,492,492,492,492,492,492,492,493,493,493,493,493,493,493,493,
-492,492,492,492,492,492,492,492,493,493,493,493,493,493,493,493,
-492,492,492,492,492,492,120,120,493,493,493,493,493,493,120,120,
-128,492,128,492,128,492,128,492,120,493,120,493,120,493,120,493,
-492,492,492,492,492,492,492,492,493,493,493,493,493,493,493,493,
-494,494,495,495,495,495,496,496,497,497,498,498,499,499,120,120,
+655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,
+655,655,655,655,655,655,163,163,656,656,656,656,656,656,163,163,
+655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,
+655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,
+655,655,655,655,655,655,163,163,656,656,656,656,656,656,163,163,
+173,655,173,655,173,655,173,655,163,656,163,656,163,656,163,656,
+655,655,655,655,655,655,655,655,656,656,656,656,656,656,656,656,
+657,657,658,658,658,658,659,659,660,660,661,661,662,662,163,163,
/* block 61 */
-492,492,492,492,492,492,492,492,500,500,500,500,500,500,500,500,
-492,492,492,492,492,492,492,492,500,500,500,500,500,500,500,500,
-492,492,492,492,492,492,492,492,500,500,500,500,500,500,500,500,
-492,492,128,501,128,120,128,128,493,493,502,502,503,119,504,119,
-119,119,128,501,128,120,128,128,505,505,505,505,503,119,119,119,
-492,492,128,128,120,120,128,128,493,493,506,506,120,119,119,119,
-492,492,128,128,128,169,128,128,493,493,507,507,174,119,119,119,
-120,120,128,501,128,120,128,128,508,508,509,509,503,119,119,120,
+663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,
+663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,
+663,663,663,663,663,663,663,663,664,664,664,664,664,664,664,664,
+655,655,665,666,665,163,173,665,656,656,667,667,668,162,669,162,
+162,162,665,666,665,163,173,665,670,670,670,670,668,162,162,162,
+655,655,173,173,163,163,173,173,656,656,671,671,163,162,162,162,
+655,655,173,173,173,215,173,173,656,656,672,672,220,162,162,162,
+163,163,665,666,665,163,173,665,673,673,674,674,668,162,162,163,
/* block 62 */
- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 24,510,511, 24, 24,
- 10, 10, 10, 10, 10, 10, 5, 5, 23, 27, 7, 23, 23, 27, 7, 23,
- 5, 5, 5, 5, 5, 5, 5, 5,512,513, 24, 24, 24, 24, 24,514,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 23, 27, 5,515, 5, 5, 16,
- 16, 5, 5, 5, 9, 7, 8, 5, 5,515, 5, 5, 5, 5, 5, 5,
- 5, 5, 9, 5, 16, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4,
- 24, 24, 24, 24, 24,516, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
- 25,110,120,120, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,110,
+675,675,675,675,675,675,675,675,675,675,675, 51,676,677,678,679,
+680,680,680,680,680,680,681, 43,682,683,684,685,685,686,684,685,
+ 43, 43, 43, 43,687, 43, 43,687,688,689,690,691,692,693,694,695,
+696,696,697,697,697, 43, 43, 43, 43, 49, 57, 43,698,699, 43,700,
+701, 43, 43, 43,702,703,704,699,699,698, 43, 43, 43, 43, 43, 43,
+ 43, 43, 50,705,700, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,675,
+ 51,706,706,706,706,707,708,709,710,711,712,712,712,712,712,712,
+ 54,645,163,163, 54, 54, 54, 54, 54, 54,713,714,715,716,717,644,
/* block 63 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 9, 9, 9, 7, 8,120,
-110,110,110,110,110,110,110,110,110,110,110,110,110,120,120,120,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-113,113,113,113,113,113,113,113,113,113,113,113,113,429,429,429,
-429,113,429,429,429,113,113,113,113,113,113,113,113,113,113,113,
-517,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,713,714,715,716,717,163,
+644,644,644,644,644,644,644,644,644,644,644,644,644,163,163,163,
+431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,
+431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,431,
+431,718,718,718,718,718,718,718,718,718,718,718,718,718,718,718,
+719,719,719,719,719,719,719,719,719,719,719,719,719,720,720,720,
+720,719,720,721,720,719,719,158,158,158,158,719,719,719,719,719,
+722,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 64 */
- 20, 20,518, 20, 20, 20, 20,518, 20, 20,519,518,518,518,519,519,
-518,518,518,519, 20,518, 20, 20, 9,518,518,518,518,518, 20, 20,
- 20, 20, 21, 20,518, 20,520, 20,518, 20,521,522,518,518, 20,519,
-518,518,523,518,519,524,524,524,524,525, 20, 20,519,519,518,518,
- 9, 9, 9, 9, 9,518,519,519,519,519, 20, 9, 20, 20,526, 20,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,527,
-528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,528,
+723,723,724,723,723,723,723,724,723,723,725,724,724,724,725,725,
+724,724,724,725,723,724,723,723,726,724,724,724,724,724,723,723,
+723,723,727,723,724,723,728,723,724,729,730,731,724,724,732,725,
+724,724,733,724,725,734,734,734,734,735,723,723,725,725,724,724,
+715,715,715,715,715,724,725,725,736,736,723,715,723,723,737,460,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,
+739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
/* block 65 */
-529,529,529, 32, 33,529,529,529,529, 25, 20, 20,120,120,120,120,
- 9, 9, 9, 9,530, 21, 21, 21, 21, 21, 9, 9, 20, 20, 20, 20,
- 9, 20, 20, 9, 20, 20, 9, 20, 20, 21, 21, 20, 20, 20, 9, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9,
- 20, 20, 9, 20, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+740,740,740, 65, 66,740,740,740,740, 58,723,723,163,163,163,163,
+ 50, 50, 50, 50,741,742,742,742,742,742, 50, 50,743,743,743,743,
+ 50,743,743, 50,743,743, 50,743, 45,742,742,743,743,743, 50, 45,
+743,743, 45, 45, 45, 45,743,743, 45, 45, 45, 45,743,743,743,743,
+743,743,743,743,743,743,743,743,743,743,743,743,743,743, 50, 50,
+743,743, 50,743, 50,743,743,743,743,743,743,743, 45,743, 45, 45,
+ 45, 45, 45, 45,743,743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
/* block 66 */
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744,744, 50, 50,
+ 50, 50,745, 53, 50,744, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,
+744,744,744, 50,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744, 50, 50,
+ 50, 50, 50,744, 50,744, 50, 50, 50, 50, 50, 50,744, 50, 50, 50,
+ 50, 50,744,744,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50,744,744,744,744,744,744,744,744, 50, 50,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
/* block 67 */
- 20, 20, 20, 20, 20, 20, 20, 20, 7, 8, 7, 8, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20,
- 9, 9, 20, 20, 20, 20, 20, 20, 21, 7, 8, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 20, 20, 20,
+744,744,744,744,744,744,744,744,744,744,744,744, 50, 50, 50,744,
+744,744,744, 50, 50, 50, 50, 50,744, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50,744,744, 50, 50,744, 50,744,744, 50,744, 50, 50, 50, 50,
+744,744,744,744,744,744,744,744,744, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744, 50, 50,
+744,744, 50, 50, 50, 50,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744, 50, 50,
+744,744,744,744,744, 50,744,744, 50, 50,744,744,744,744,744, 50,
/* block 68 */
- 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9, 9,
- 9, 9, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 20, 20, 20, 20, 21, 21, 21, 20, 20, 20, 20, 20,
+ 45, 45, 45, 45, 45, 45, 45, 45,746,747,746,747, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,748, 45, 45, 45, 45,
+ 50, 50, 45, 45, 45, 45, 45, 45, 47,749,750, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,751,
+751,751,751,751,751,751,751,751,751,751,751, 45, 50, 45, 45, 45,
/* block 69 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 45, 45, 45, 45, 45, 45, 45, 45,752, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45,751, 45, 45, 45, 45, 45, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50,743,743, 45,743, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 47,
+743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50, 50,
+ 50, 50,743, 45, 45, 45, 45, 45, 45,748,748,748,748, 47, 47, 47,
+748, 47, 47,748, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45,
/* block 70 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,531,531,531,531,531,531,531,531,531,531,
-531,531,532,531,531,531,531,531,531,531,531,531,531,531,531,531,
-533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,533,
-533,533,533,533,533,533,533,533,533,533, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
/* block 71 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 58, 58, 58, 58, 58, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,754,754,754,754,754,754,754,754,754,754,
+754,754,755,754,754,754,754,754,754,754,754,754,754,754,754,754,
+756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,756,
+756,756,756,756,756,756,756,756,756,756, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
/* block 72 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 21, 9, 20, 20, 20, 20, 20, 20, 20, 20,
- 21, 9, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 9, 9, 9,530,530,530,530, 9,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
/* block 73 */
- 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,530,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+743,743, 45, 45, 45, 45, 45, 45, 45, 45, 47, 47, 45, 45,743,743,
+743,743,743,743,743,743,742, 50, 45, 45, 45, 45,743,743,743,743,
+742, 50, 45, 45, 45, 45,743,743, 45, 45,743,743, 45, 45, 45,743,
+743,743,743,743, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45,743, 45,743, 45, 45,743,743,743,743,743,743, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 50, 50, 50,741,741,757,757, 50,
/* block 74 */
- 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 47, 47, 47, 47, 47,758,743,752,752,752,752,752,752,752, 47,752,
+752, 47,752, 45,748,748,752,752, 47,752,752,752,752,759,752,752,
+ 47,752, 47, 47,752,752, 47,752,752,752, 47,752,752,752, 47, 47,
+752,752,752,752,752,752,752,752, 47, 47, 47,752,752,752,752,752,
+742,752,742,752,752,752,752,752,748,748,748,748,748,748,748,748,
+748,748,748,748,752,752,752,752,752,752,752,752,752,752,752, 47,
+742,758,758,742,752, 47, 47,752, 47,752,752,752,752,758,758,760,
+752,752,752,752,752,752,752,752,752,752,752, 47,752,752, 47,748,
/* block 75 */
- 21, 21, 21, 21, 21, 21, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 20, 21, 20, 21, 20, 20, 20, 20, 20, 20, 21, 20, 20,
- 20, 21, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 21, 20, 20, 21, 20, 20, 20, 20, 21, 20, 21, 20,
- 20, 20, 20, 21, 21, 21, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 21, 21, 21, 21, 21, 7, 8, 7, 8, 7, 8, 7, 8,
- 7, 8, 7, 8, 7, 8, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+752,752,752,752,752,752, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+752,752, 47,748, 47, 47, 47, 47,752, 47,752, 47, 47,752,752,752,
+ 47,748,752,752,752,752,752, 47,752,752,748,748,761,752,752,752,
+ 47, 47,752,752,752,752,752,752,752,752,752,752,752,748,748,752,
+752,752,752,752,748,748,752,752, 47,752,752,752,752,752,748, 47,
+752, 47,752, 47,748,752,752,752,752,752,752,752,752,752,752,752,
+752,752,752,752,752,752,752,752,752, 47,748,752,752,752,752,752,
+ 47, 47,748,748, 47,748,752, 47, 47,759,748,752,752,748,752,752,
/* block 76 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 20, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
- 9, 9, 9, 9, 9, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+752,752, 47,752,752,748, 45, 45, 47, 47,762,762,759,759,752, 47,
+752,752, 47, 45, 47, 45, 47, 45, 45, 45, 45, 45, 45, 47, 45, 45,
+ 45, 47, 45, 45, 45, 45, 45, 45,748, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 47, 45, 45, 47, 45, 45, 45, 45,748, 45,748, 45,
+ 45, 45, 45,748,748,748, 45,748, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 47, 47,752,752,752,703,704,703,704,703,704,703,704,
+703,704,703,704,703,704, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
/* block 77 */
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
-534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,534,
+ 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+ 58, 58, 58, 58, 45,748,748,748, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 47, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+748, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,
+ 50, 50, 50,744,744,746,747, 50,744,744, 50,744, 50,744, 50, 50,
+ 50, 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50,744,744,744, 50,
+ 50, 50,744,744,744,744,746,747,746,747,746,747,746,747,746,747,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
/* block 78 */
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9,530,530, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
+763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,763,
/* block 79 */
- 9, 9, 9, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
- 8, 7, 8, 7, 8, 7, 8, 7, 8, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, 7, 8, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 8, 9, 9,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50,741,741, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
/* block 80 */
- 20, 20, 20, 20, 20, 21, 21, 21, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 20, 20, 9, 9, 9, 9, 9, 9, 20, 20, 20,
- 21, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 50, 50, 50,746,747,746,747,746,747,746,747,746,747,746,747,746,
+747,746,747,746,747,746,747,746,747, 50, 50,744, 50, 50, 50, 50,
+744, 50, 50,744,744,744, 50, 50,744,744,744,744,744,744,744,744,
+ 50, 50, 50, 50, 50, 50, 50, 50,744, 50, 50, 50, 50, 50, 50, 50,
+744,744, 50, 50,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,
+744,744,744, 50,744,744, 50, 50,746,747,746,747, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50,744, 50, 50,744,744, 50, 50,746,747, 50, 50,
/* block 81 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744, 50,
+ 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50,744,744, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50,744,744, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50,744,744,744,744,744,744,744,
/* block 82 */
-535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
-535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
-535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,535,
-536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
-536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
-536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,536,
- 32, 33,537,538,539,540,541, 32, 33, 32, 33, 32, 33,542,543,544,
-545, 35, 32, 33, 35, 32, 33, 35, 35, 35, 35, 35,110,110,546,546,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744, 50, 50, 50,744,744,744,744,744,744,744,744, 50,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
+744,744,744,744,744,744,744, 50, 50, 50, 50, 50, 50, 50,744, 50,
+ 50, 50, 50,744,744,744, 50, 50, 50, 50, 50, 50,744,744,744, 50,
+ 50, 50, 50, 50, 50, 50, 50,744,744,744,744, 50, 50, 50, 50, 50,
/* block 83 */
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,165,166,165,166,165,166,165,166,165,166,165,166,
-165,166,165,166,547,548,548,548,548,548,548,165,166,165,166,549,
-549,549,165,166,120,120,120,120,120,550,550,550,550,551,550,550,
+ 45, 45, 45, 45, 45, 47, 47, 47, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,748,748, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 50, 50, 50, 50, 45, 45, 50, 50, 50, 50, 50, 50, 45, 45, 45,
+748, 45, 45, 45, 45,748, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45,753,753, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
/* block 84 */
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,552,
-552,552,552,552,552,552,120,552,120,120,120,120,120,552,120,120,
-553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
-553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
-553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,553,
-553,553,553,553,553,553,553,553,120,120,120,120,120,120,120,554,
-555,120,120,120,120,120,120,120,120,120,120,120,120,120,120,556,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45,753, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,764, 45,
/* block 85 */
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,
-361,361,361,361,361,361,361,120,120,120,120,120,120,120,120,120,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,120,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,120,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,120,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,120,
-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
-557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,557,
+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
+765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
+766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
+ 65, 66,767,768,769,770,771, 65, 66, 65, 66, 65, 66,772,773,774,
+775, 70, 65, 66, 70, 65, 66, 70, 70, 70, 70, 70,645,644,776,776,
/* block 86 */
- 5, 5, 23, 27, 23, 27, 5, 5, 5, 23, 27, 5, 23, 27, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 10, 5, 5, 10, 5, 23, 27, 5, 5,
- 23, 27, 7, 8, 7, 8, 7, 8, 7, 8, 5, 5, 5, 5, 5,111,
- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 5, 5, 5, 5,
- 10, 5, 7,558, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 20, 20, 5, 5, 5, 7, 8, 7, 8, 7, 8, 7, 8, 10,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,211,212,211,212,211,212,211,212,211,212,211,212,
+211,212,211,212,777,778,778,778,778,778,778,211,212,211,212,779,
+779,779,211,212,163,163,163,163,163,780,780,780,780,781,780,780,
/* block 87 */
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,120,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,120,120,120,120,120,120,120,120,120,120,120,120,
+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,
+782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,782,
+782,782,782,782,782,782,163,782,163,163,163,163,163,782,163,163,
+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
+783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,783,
+783,783,783,783,783,783,783,783,163,163,163,163,163,163,163,784,
+785,163,163,163,163,163,163,163,163,163,163,163,163,163,163,786,
/* block 88 */
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,
+483,483,483,483,483,483,483,163,163,163,163,163,163,163,163,163,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,
+787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,
+787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,787,
/* block 89 */
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,559,
-559,559,559,559,559,559,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,
+ 43, 43,788,789,788,789, 43, 43, 43,788,789, 43,788,789, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43,680, 43, 43,680, 43,788,789, 43, 43,
+788,789,703,704,703,704,703,704,703,704, 43, 43, 43, 43,699,790,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 43,680,680,699, 43, 43, 43,
+680,791,684,792, 43, 43, 43, 43, 43, 43, 43, 43,791, 43,791,791,
+ 45, 45, 43,699,699,703,704,703,704,703,704,703,704,680,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
+753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,753,
/* block 90 */
- 4,560,560,561, 20,562,563,564,565,566,565,566,565,566,565,566,
-565,566, 20,567,565,566,565,566,565,566,565,566,568,569,570,570,
- 20,564,564,564,564,564,564,564,564,564,571,571,571,571,572,572,
-573,574,574,574,574,574, 20,567,564,564,564,562,575,576,577,577,
-120,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,163,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 91 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,120,120,579,579,580,580,581,581,578,
-582,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,560,574,584,584,583,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
/* block 92 */
-120,120,120,120,120,585,585,585,585,585,585,585,585,585,585,585,
-585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
-585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
-120,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,793,
+793,793,793,793,793,793,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+794,794,795,795,794,794,794,794,794,794,794,794,163,163,163,163,
/* block 93 */
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,
-577,577,587,587,587,587,577,577,577,577,577,577,577,577,577,577,
-585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
-585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,585,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,120,120,120,120,120,120,120,120,120,120,120,120,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+675,796,797,798,723,799,800,801,802,803,802,803,804,805,804,805,
+802,803, 45,806,802,803,802,803,802,803,802,803,807,808,809,809,
+ 45,801,801,801,801,801,801,801,801,801,810,810,810,810,811,811,
+812,813,813,813,813,813,723,814,801,801,801,815,816,817,818,818,
+163,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
/* block 94 */
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,120,
-587,587,587,587,587,587,587,587,587,587,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577, 25, 25, 25, 25, 25, 25, 25, 25,
- 20, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,588,
-588,588,588,588,588,588,588,588,588,588,588,588,588,588,588, 20,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,163,163,820,820,821,821,822,822,819,
+823,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,825,826,827,827,824,
/* block 95 */
-587,587,587,587,587,587,587,587,587,587,577,577,577,577,577,577,
-577,577,577,577,577,577,577,589,577,589,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-577,577,577,577,577,577,577,577,577,577,577,577, 20, 20, 20, 20,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,577,
+163,163,163,163,163,828,828,828,828,828,828,828,828,828,828,828,
+828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+163,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,830,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
/* block 96 */
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,590,
-590,590,590,590,590,590,590,590,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,577,577,577,577,577,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,163,
+831,831,832,832,832,832,831,831,831,831,831,831,831,831,831,831,
+828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,828,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,818,
+818,818,818,818,163,163,163,163,163,163,163,163,163,163,163,163,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
/* block 97 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,577,
-577,577,577,577,577,577,577,577,577,577,577,577,577,577,577, 20,
+833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,
+833,833,833,833,833,833,833,833,833,833,833,833,833,834,834,163,
+832,832,832,832,832,832,832,832,832,832,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,835,835,835,835,835,835,835,835,
+723, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,833,
+833,833,833,833,833,833,833,833,833,833,833,833,834,834,834,460,
/* block 98 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+832,832,832,832,832,832,832,832,832,832,831,831,831,831,831,831,
+831,831,831,831,831,831,831,836,831,836,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
+831,831,831,831,831,831,831,831,831,831,831,831,723,723,723,723,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,831,
/* block 99 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
+837,837,837,837,837,837,837,837,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,460,460,460,460,460,460,723,723,723,723,831,831,831,831,831,
/* block 100 */
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,593,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,723,723,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,
+831,831,831,831,831,831,831,831,831,831,831,831,831,831,831,723,
/* block 101 */
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
-592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,592,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
/* block 102 */
-592,592,592,592,592,592,592,592,592,592,592,592,592,120,120,120,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,594,
-594,594,594,594,594,594,594,120,120,120,120,120,120,120,120,120,
-595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
-595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,595,
-595,595,595,595,595,595,595,595,596,596,596,596,596,596,597,597,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
/* block 103 */
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,840,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
/* block 104 */
-598,598,598,598,598,598,598,598,598,598,598,598,599,600,600,600,
-598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,598,
-601,601,601,601,601,601,601,601,601,601,598,598,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-192,193,192,193,192,193,192,193,192,193,602,603,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,604,198,
-200,200,200,605,557,557,557,557,557,557,557,557,557,557,605,482,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
+839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,839,
/* block 105 */
-192,193,192,193,192,193,192,193,192,193,192,193,192,193,192,193,
-192,193,192,193,192,193,192,193,192,193,192,193,482,482,557,557,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,607,607,607,607,607,607,607,607,607,607,
-608,608,609,609,609,609,609,609,120,120,120,120,120,120,120,120,
+839,839,839,839,839,839,839,839,839,839,839,839,839,163,163,163,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,841,
+841,841,841,841,841,841,841,163,163,163,163,163,163,163,163,163,
+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,
+842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,842,
+842,842,842,842,842,842,842,842,843,843,843,843,843,843,844,845,
/* block 106 */
-610,610,610,610,610,610,610,610, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15,111,111,111,111,111,111,111,111,111,
- 15, 15, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 35, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
-110, 35, 35, 35, 35, 35, 35, 35, 35, 32, 33, 32, 33,611, 32, 33,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
/* block 107 */
- 32, 33, 32, 33, 32, 33, 32, 33,111, 15, 15, 32, 33,612, 35, 22,
- 32, 33, 32, 33,613, 35, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,614,615,616,617,614, 35,
-618,619,620,621, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33, 32, 33,
- 32, 33, 32, 33,622,623,624, 32, 33, 32, 33,120,120,120,120,120,
- 32, 33,120, 35,120, 35, 32, 33, 32, 33,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,110,110,110, 32, 33, 22,110,110, 35, 22, 22, 22, 22, 22,
+846,846,846,846,846,846,846,846,846,846,846,846,847,848,849,849,
+846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,846,
+850,850,850,850,850,850,850,850,850,850,846,846,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+240,241,240,241,240,241,240,241,240,241,851,852,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,853,246,
+248,248,248,854,787,787,787,787,787,787,787,787,855,855,854,856,
/* block 108 */
-625,625,626,625,625,625,626,625,625,625,625,626,625,625,625,625,
-625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,625,
-625,625,625,627,627,626,626,627,628,628,628,628,626,120,120,120,
-629,629,629,630,630,630,631,631,632,631,120,120,120,120,120,120,
-633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
-633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
-633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,633,
-633,633,633,633,634,634,634,634,120,120,120,120,120,120,120,120,
+240,241,240,241,240,241,240,241,240,241,240,241,240,241,240,241,
+240,241,240,241,240,241,240,241,240,241,240,241,857,857,787,787,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,859,859,859,859,859,859,859,859,859,859,
+860,860,861,862,863,863,863,862,163,163,163,163,163,163,163,163,
/* block 109 */
-635,635,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
-636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
-636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,636,
-636,636,636,636,635,635,635,635,635,635,635,635,635,635,635,635,
-635,635,635,635,637,637,120,120,120,120,120,120,120,120,638,638,
-639,639,639,639,639,639,639,639,639,639,120,120,120,120,120,120,
-253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,253,
-253,640,255,641,255,255,255,255,261,261,261,255,261,255,255,253,
+864,864,864,864,864,864,864,864, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46,149,149,149,149,149,149,149,149,149,
+ 46, 46, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 70, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+644, 70, 70, 70, 70, 70, 70, 70, 70, 65, 66, 65, 66,865, 65, 66,
/* block 110 */
-642,642,642,642,642,642,642,642,642,642,643,643,643,643,643,643,
-643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,643,
-643,643,643,643,643,643,644,644,644,644,644,644,644,644,645,646,
-647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,647,
-647,647,647,647,647,647,647,648,648,648,648,648,648,648,648,648,
-648,648,649,649,120,120,120,120,120,120,120,120,120,120,120,650,
-358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,358,
-358,358,358,358,358,358,358,358,358,358,358,358,358,120,120,120,
+ 65, 66, 65, 66, 65, 66, 65, 66,149,866,866, 65, 66,867, 70, 92,
+ 65, 66, 65, 66,868, 70, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,869,870,871,872,869, 70,
+873,874,875,876, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66, 65, 66,
+ 65, 66, 65, 66,877,878,879, 65, 66, 65, 66,163,163,163,163,163,
+ 65, 66,163, 70,163, 70, 65, 66, 65, 66,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,880,880,880, 65, 66, 92,147,147, 70, 92, 92, 92, 92, 92,
/* block 111 */
-651,651,651,652,653,653,653,653,653,653,653,653,653,653,653,653,
-653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,
-653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,653,
-653,653,653,651,652,652,651,651,651,651,652,652,651,651,652,652,
-652,654,654,654,654,654,654,654,654,654,654,654,654,654,120,655,
-656,656,656,656,656,656,656,656,656,656,120,120,120,120,654,654,
-346,346,346,346,346,348,657,346,346,346,346,346,346,346,346,346,
-352,352,352,352,352,352,352,352,352,352,346,346,346,346,346,120,
+881,881,882,881,881,881,883,881,881,881,881,882,881,881,881,881,
+881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,881,
+881,881,881,884,884,882,882,884,885,885,885,885,883,163,163,163,
+886,886,886,887,887,887,888,888,889,890,163,163,163,163,163,163,
+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
+891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
+891,891,891,891,892,892,893,893,163,163,163,163,163,163,163,163,
/* block 112 */
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,658,
-658,658,658,658,658,658,658,658,658,659,659,659,659,659,659,660,
-660,659,659,660,660,659,659,120,120,120,120,120,120,120,120,120,
-658,658,658,659,658,658,658,658,658,658,658,658,659,660,120,120,
-661,661,661,661,661,661,661,661,661,661,120,120,662,662,662,662,
-346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,346,
-657,346,346,346,346,346,346,353,353,353,346,347,348,347,346,346,
+894,894,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
+895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
+895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,895,
+895,895,895,895,894,894,894,894,894,894,894,894,894,894,894,894,
+894,894,894,894,896,897,163,163,163,163,163,163,163,163,898,898,
+899,899,899,899,899,899,899,899,899,899,163,163,163,163,163,163,
+336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,336,
+336,900,335,901,335,335,335,335,343,343,343,335,343,335,335,333,
/* block 113 */
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,663,
-664,663,664,664,664,663,663,664,664,663,663,663,663,663,664,664,
-663,664,663,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,663,663,665,666,666,
-667,667,667,667,667,667,667,667,667,667,667,668,669,669,668,668,
-670,670,667,671,671,668,669,120,120,120,120,120,120,120,120,120,
+902,902,902,902,902,902,902,902,902,902,903,903,903,903,903,903,
+903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,903,
+903,903,903,903,903,903,904,904,904,904,904,905,905,905,906,907,
+908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,908,
+908,908,908,908,908,908,908,909,909,909,909,909,909,909,909,909,
+909,909,910,911,163,163,163,163,163,163,163,163,163,163,163,912,
+478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,478,
+478,478,478,478,478,478,478,478,478,478,478,478,478,163,163,163,
/* block 114 */
-120,361,361,361,361,361,361,120,120,361,361,361,361,361,361,120,
-120,361,361,361,361,361,361,120,120,120,120,120,120,120,120,120,
-361,361,361,361,361,361,361,120,361,361,361,361,361,361,361,120,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
- 35, 35, 35,672, 35, 35, 35, 35, 35, 35, 35, 15,110,110,110,110,
- 35, 35, 35, 35, 35,128, 35, 35, 35,110, 15, 15,120,120,120,120,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
+913,913,913,914,915,915,915,915,915,915,915,915,915,915,915,915,
+915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
+915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
+915,915,915,916,914,914,913,913,913,913,914,914,913,913,914,914,
+917,918,918,918,918,918,918,919,920,920,918,918,918,918,163,921,
+922,922,922,922,922,922,922,922,922,922,163,163,163,163,918,918,
+461,461,461,461,461,471,923,461,461,461,461,461,461,461,461,461,
+472,472,472,472,472,472,472,472,472,472,461,461,461,461,461,163,
/* block 115 */
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,673,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
-667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,667,
-667,667,667,668,668,669,668,668,669,668,668,670,668,669,120,120,
-674,674,674,674,674,674,674,674,674,674,120,120,120,120,120,120,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
+924,924,924,924,924,924,924,924,924,925,925,925,925,925,925,926,
+926,925,925,926,926,925,925,163,163,163,163,163,163,163,163,163,
+924,924,924,925,924,924,924,924,924,924,924,924,925,926,163,163,
+927,927,927,927,927,927,927,927,927,927,163,163,928,929,929,929,
+461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,461,
+923,461,461,461,461,461,461,473,473,473,461,470,471,470,461,461,
/* block 116 */
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,
+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,
+930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,930,
+931,930,931,931,931,932,932,931,931,932,930,932,932,930,931,933,
+934,933,934,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,930,930,935,936,937,
+938,938,938,938,938,938,938,938,938,938,938,939,940,940,939,939,
+941,941,938,942,942,939,943,163,163,163,163,163,163,163,163,163,
/* block 117 */
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
+163,483,483,483,483,483,483,163,163,483,483,483,483,483,483,163,
+163,483,483,483,483,483,483,163,163,163,163,163,163,163,163,163,
+483,483,483,483,483,483,483,163,483,483,483,483,483,483,483,163,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,
+ 70, 70, 70,944, 70, 70, 70, 70, 70, 70, 70,866,147,147,147,147,
+ 70, 70, 70, 70, 70,221, 70, 70, 70,945, 46, 46,163,163,163,163,
+946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
/* block 118 */
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
+946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
+946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
+946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
+946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,
+938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,938,
+938,938,938,939,939,940,939,939,940,939,939,941,947,943,163,163,
+948,948,948,948,948,948,948,948,948,948,163,163,163,163,163,163,
/* block 119 */
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
/* block 120 */
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
/* block 121 */
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
/* block 122 */
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-675,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,675,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,675,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
/* block 123 */
-676,676,676,676,676,676,676,676,675,676,676,676,676,676,676,676,
-676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,676,
-676,676,676,676,120,120,120,120,120,120,120,120,120,120,120,120,
-359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,359,
-359,359,359,359,359,359,359,120,120,120,120,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,360,
-360,360,360,360,360,360,360,360,360,360,360,360,120,120,120,120,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
/* block 124 */
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
-677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,677,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
/* block 125 */
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+949,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,949,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,949,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
/* block 126 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,120,120,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+950,950,950,950,950,950,950,950,949,950,950,950,950,950,950,950,
+950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+950,950,950,950,163,163,163,163,163,163,163,163,163,163,163,163,
+481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,481,
+481,481,481,481,481,481,481,163,163,163,163,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,482,
+482,482,482,482,482,482,482,482,482,482,482,482,163,163,163,163,
/* block 127 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
+951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,951,
/* block 128 */
- 35, 35, 35, 35, 35, 35, 35,120,120,120,120,120,120,120,120,120,
-120,120,120,206,206,206,206,206,120,120,120,120,120,214,211,214,
-214,214,214,214,214,214,214,214,214,679,214,214,214,214,214,214,
-214,214,214,214,214,214,214,120,214,214,214,214,214,120,214,120,
-214,214,120,214,214,120,214,214,214,214,214,214,214,214,214,214,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
/* block 129 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,252,252,252,252,252,252,252,252,252,252,252,252,252,252,
-252,252,252,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
/* block 130 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,838,838,
+953,838,953,838,838,953,953,953,953,953,953,953,953,953,953,838,
+953,838,953,838,838,953,953,838,838,838,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,163,163,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
/* block 131 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,680,681,
-221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,221,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 132 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-120,120,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,120,120,120,120,120,120,120,221,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-225,225,682,225,225,225,225,225,225,225,225,225,219,683,221,221,
+652,652,652,652,652,652,652,163,163,163,163,163,163,163,163,163,
+163,163,163,257,257,257,257,257,163,163,163,163,163,270,265,270,
+270,270,270,270,270,270,270,270,270,954,270,270,270,270,270,270,
+270,270,270,270,270,270,270,262,270,270,270,270,270,262,270,262,
+270,270,262,270,270,262,270,270,270,270,270,270,270,270,270,270,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 133 */
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
- 5, 5, 5, 5, 5, 5, 5, 7, 8, 5,120,120,120,120,120,120,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,557,557,
- 5, 10, 10, 16, 16, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7,
- 8, 7, 8, 7, 8,561,561, 7, 8, 5, 5, 5, 5, 16, 16, 16,
- 5, 5, 5,120, 5, 5, 5, 5, 10, 7, 8, 7, 8, 7, 8, 5,
- 5, 5, 9, 10, 9, 9, 9,120, 5, 6, 5, 5,120,120,120,120,
-225,225,225,225,225,120,225,225,225,225,225,225,225,225,225,225,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,331,331,331,331,331,331,331,331,331,331,331,331,331,331,
+331,331,331,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 134 */
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,120,120, 24,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,955,955,
+955,955,955,955,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 135 */
-120, 5, 5, 5, 6, 5, 5, 5, 7, 8, 5, 9, 5, 10, 5, 5,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, 5, 9, 9, 9, 5,
- 5, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
- 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 7, 5, 8, 15, 16,
- 15, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 7, 9, 8, 9, 7,
- 8,560,565,566,560,560,583,583,583,583,583,583,583,583,583,583,
-574,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 136 */
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,583,
-583,583,583,583,583,583,583,583,583,583,583,583,583,583,684,684,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,
-586,586,586,586,586,586,586,586,586,586,586,586,586,586,586,120,
-120,120,586,586,586,586,586,586,120,120,586,586,586,586,586,586,
-120,120,586,586,586,586,586,586,120,120,586,586,586,120,120,120,
- 6, 6, 9, 15, 20, 6, 6,120, 20, 9, 9, 9, 9, 20, 20,120,
-516,516,516,516,516,516,516,516,516, 24, 24, 24, 20, 20,120,120,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,956,957,
+280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
/* block 137 */
-685,685,685,685,685,685,685,685,685,685,685,685,120,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,120,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,120,685,685,120,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,120,120,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+302,302,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,302,302,302,302,302,302,302,280,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+286,286,959,286,286,286,286,286,286,286,955,955,277,960,280,280,
/* block 138 */
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,685,
-685,685,685,685,685,685,685,685,685,685,685,120,120,120,120,120,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,962,
+963,963,963,964,963,963,963,965,966,963,163,163,163,163,163,163,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,855,855,
+963,967,967,700,700,965,966,965,966,965,966,965,966,965,966,965,
+966,968,969,968,969,798,798,965,966,963,963,963,963,700,700,700,
+970,166,971,163,166,972,973,973,967,974,975,974,975,974,975,976,
+963,977,713,978,979,979,715,163,977,431,976,963,163,163,163,163,
+955,286,955,286,955,302,955,286,955,286,955,286,955,286,955,286,
/* block 139 */
-686,686,687,120,120,120,120,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,688,
-688,688,688,688,120,120,120,689,689,689,689,689,689,689,689,689,
-690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
-690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
-690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,
-690,690,690,690,690,691,691,691,691,692,692,692,692,692,692,692,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,286,
+286,286,286,286,286,286,286,286,286,286,286,286,286,302,302, 51,
/* block 140 */
-692,692,692,692,692,692,692,692,692,692,691,691,692,692,692,120,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,
-692,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,120,120,
+163,973,980,976,431,976,963,981,974,975,963,713,970,982,971,983,
+984,984,984,984,984,984,984,984,984,984,972,166,979,715,979,973,
+963,985,985,985,985,985,985, 59, 59, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,974,977,975,986,700,
+ 46,987,987,987,987,987,987, 62, 62, 62, 62, 62, 62, 62, 62, 62,
+ 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,974,715,975,715,974,
+975,988,989,990,991,825,824,824,824,824,824,824,824,824,824,824,
+826,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
/* block 141 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,824,
+824,824,824,824,824,824,824,824,824,824,824,824,824,824,992,992,
+830,829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,
+829,829,829,829,829,829,829,829,829,829,829,829,829,829,829,163,
+163,163,829,829,829,829,829,829,163,163,829,829,829,829,829,829,
+163,163,829,829,829,829,829,829,163,163,829,829,829,163,163,163,
+431,431,715, 46,723,431,431,163,723,715,715,715,715,723,723,163,
+707,707,707,707,707,707,707,707,707,993,993,993,723,723,958,958,
/* block 142 */
-693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,693,
-693,693,693,693,693,693,693,693,693,693,693,693,693,120,120,120,
-694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
-694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
-694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,694,
-694,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-695,696,696,696,696,696,696,696,696,696,696,696,696,696,696,696,
-696,696,696,696,696,696,696,696,696,696,696,696,120,120,120,120,
+994,994,994,994,994,994,994,994,994,994,994,994,163,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,163,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,163,994,994,163,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,163,163,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 143 */
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,697,
-698,698,698,698,120,120,120,120,120,120,120,120,120,697,697,697,
-699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,699,
-699,700,699,699,699,699,699,699,699,699,700,120,120,120,120,120,
-701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,
-701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,701,
-701,701,701,701,701,701,702,702,702,702,702,120,120,120,120,120,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,994,
+994,994,994,994,994,994,994,994,994,994,994,163,163,163,163,163,
/* block 144 */
-703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,703,
-703,703,703,703,703,703,703,703,703,703,703,703,703,703,120,704,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,705,
-705,705,705,705,120,120,120,120,705,705,705,705,705,705,705,705,
-706,707,707,707,707,707,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+995,996,997,163,163,163,163,998,998,998,998,998,998,998,998,998,
+998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,
+998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,998,
+998,998,998,998,163,163,163,999,999,999,999,999,999,999,999,999,
+1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
+1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
+1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,
+1000,1000,1000,1000,1000,1001,1001,1001,1001,1002,1002,1002,1002,1002,1002,1002,
/* block 145 */
-708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
-708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,708,
-708,708,708,708,708,708,708,708,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,709,
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
-710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,710,
+1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1001,1001,1002,1003,1003,163,
+723,723,723,723,723,723,723,723,723,723,723,723,723,163,163,163,
+1002,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,158,163,163,
/* block 146 */
-711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,711,
-711,711,711,711,711,711,711,711,711,711,711,711,711,711,120,120,
-712,712,712,712,712,712,712,712,712,712,120,120,120,120,120,120,
-713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,
-713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,713,
-713,713,713,713,120,120,120,120,714,714,714,714,714,714,714,714,
-714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,714,
-714,714,714,714,714,714,714,714,714,714,714,714,120,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 147 */
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,715,
-715,715,715,715,715,715,715,715,120,120,120,120,120,120,120,120,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,716,
-716,716,716,716,120,120,120,120,120,120,120,120,120,120,120,717,
-718,718,718,718,718,718,718,718,718,718,718,120,718,718,718,718,
+1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,
+1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,1004,163,163,163,
+1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,
+1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,
+1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,1005,
+1005,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1006,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,
+1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,1007,163,163,163,163,
/* block 148 */
-718,718,718,718,718,718,718,718,718,718,718,120,718,718,718,718,
-718,718,718,120,718,718,120,719,719,719,719,719,719,719,719,719,
-719,719,120,719,719,719,719,719,719,719,719,719,719,719,719,719,
-719,719,120,719,719,719,719,719,719,719,120,719,719,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,
+1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,1008,
+1009,1009,1009,1009,163,163,163,163,163,163,163,163,163,1008,1008,1008,
+1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,1010,
+1010,1011,1010,1010,1010,1010,1010,1010,1010,1010,1011,163,163,163,163,163,
+1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,
+1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,1012,
+1012,1012,1012,1012,1012,1012,1013,1013,1013,1013,1013,163,163,163,163,163,
/* block 149 */
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
+1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,
+1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,1014,163,1015,
+1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,
+1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,1016,
+1016,1016,1016,1016,163,163,163,163,1016,1016,1016,1016,1016,1016,1016,1016,
+1017,1018,1018,1018,1018,1018,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 150 */
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,720,120,120,120,120,120,120,120,120,120,
-720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,
-720,720,720,720,720,720,120,120,120,120,120,120,120,120,120,120,
-720,720,720,720,720,720,720,720,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,
+1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,1019,
+1019,1019,1019,1019,1019,1019,1019,1019,1020,1020,1020,1020,1020,1020,1020,1020,
+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,
+1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,1020,
+1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,
+1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,
+1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,1021,
/* block 151 */
-110,110,110,110,110,110,120,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,
-110,120,110,110,110,110,110,110,110,110,110,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,
+1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,1022,163,163,
+1023,1023,1023,1023,1023,1023,1023,1023,1023,1023,163,163,163,163,163,163,
+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,
+1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,
+1024,1024,1024,1024,163,163,163,163,1025,1025,1025,1025,1025,1025,1025,1025,
+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,
+1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,163,163,163,163,
/* block 152 */
-721,721,721,721,721,721,120,120,721,120,721,721,721,721,721,721,
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
-721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,721,
-721,721,721,721,721,721,120,721,721,120,120,120,721,120,120,721,
-722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,722,
-722,722,722,722,722,722,120,723,724,724,724,724,724,724,724,724,
-725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
-725,725,725,725,725,725,725,726,726,727,727,727,727,727,727,727,
+1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,
+1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,1026,
+1026,1026,1026,1026,1026,1026,1026,1026,163,163,163,163,163,163,163,163,
+1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,
+1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,
+1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,1027,
+1027,1027,1027,1027,163,163,163,163,163,163,163,163,163,163,163,1028,
+1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,1029,1029,
/* block 153 */
-728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,
-728,728,728,728,728,728,728,728,728,728,728,728,728,728,728,120,
-120,120,120,120,120,120,120,729,729,729,729,729,729,729,729,729,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,730,
-730,730,730,120,730,730,120,120,120,120,120,731,731,731,731,731,
+1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,1029,163,1029,1029,1029,1029,
+1029,1029,1029,163,1029,1029,163,1030,1030,1030,1030,1030,1030,1030,1030,1030,
+1030,1030,163,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,1030,
+1030,1030,163,1030,1030,1030,1030,1030,1030,1030,163,1030,1030,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 154 */
-732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,732,
-732,732,732,732,732,732,733,733,733,733,733,733,120,120,120,734,
-735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,735,
-735,735,735,735,735,735,735,735,735,735,120,120,120,120,120,736,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
/* block 155 */
-737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
-737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,737,
-738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,738,
-738,738,738,738,738,738,738,738,120,120,120,120,739,739,738,738,
-739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
-120,120,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
-739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
-739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,739,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,163,
+1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,1031,
+1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,163,163,
+1031,1031,1031,1031,1031,1031,1031,1031,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 156 */
-740,741,741,741,120,741,741,120,120,120,120,120,741,741,741,741,
-740,740,740,740,120,740,740,740,120,740,740,740,740,740,740,740,
-740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,740,
-740,740,740,740,740,740,120,120,741,741,741,120,120,120,120,741,
-742,742,742,742,742,742,742,742,742,120,120,120,120,120,120,120,
-743,743,743,743,743,743,743,743,743,120,120,120,120,120,120,120,
-744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,744,
-744,744,744,744,744,744,744,744,744,744,744,744,744,745,745,746,
+147,1032,1032,147,147,147,163,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
+147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,147,
+147,163,147,147,147,147,147,147,147,147,147,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 157 */
-747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,747,
-747,747,747,747,747,747,747,747,747,747,747,747,747,748,748,748,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-749,749,749,749,749,749,749,749,750,749,749,749,749,749,749,749,
-749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,749,
-749,749,749,749,749,751,751,120,120,120,120,752,752,752,752,752,
-753,753,754,753,753,753,753,120,120,120,120,120,120,120,120,120,
+1033,1033,1033,1033,1033,1033,262,262,1033,262,1033,1033,1033,1033,1033,1033,
+1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,
+1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,1033,
+1033,1033,1033,1033,1033,1033,262,1033,1033,262,262,262,1033,262,262,1033,
+1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,1034,
+1034,1034,1034,1034,1034,1034,262,1035,1036,1036,1036,1036,1036,1036,1036,1036,
+1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,1037,
+1037,1037,1037,1037,1037,1037,1037,1038,1038,1039,1039,1039,1039,1039,1039,1039,
/* block 158 */
-755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
-755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
-755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,755,
-755,755,755,755,755,755,120,120,120,756,756,756,756,756,756,756,
-757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,757,
-757,757,757,757,757,757,120,120,758,758,758,758,758,758,758,758,
-759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,759,
-759,759,759,120,120,120,120,120,760,760,760,760,760,760,760,760,
+1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,
+1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,1040,262,
+262,262,262,262,262,262,262,1041,1041,1041,1041,1041,1041,1041,1041,1041,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,1042,
+1042,1042,1042,262,1042,1042,262,262,262,262,262,1043,1043,1043,1043,1043,
/* block 159 */
-761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,761,
-761,761,120,120,120,120,120,120,120,762,762,762,762,120,120,120,
-120,120,120,120,120,120,120,120,120,763,763,763,763,763,763,763,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,1044,
+1044,1044,1044,1044,1044,1044,1045,1045,1045,1045,1045,1045,262,262,262,1046,
+1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,
+1047,1047,1047,1047,1047,1047,1047,1047,1047,1047,262,262,262,262,262,1048,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 160 */
-764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
-764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
-764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
-764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,764,
-764,764,764,764,764,764,764,764,764,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,
+1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,1049,
+1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,1050,
+1050,1050,1050,1050,1050,1050,1050,1050,262,262,262,262,1051,1051,1050,1050,
+1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,
+262,262,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,
+1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,
+1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,1051,
/* block 161 */
-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
-765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,765,
-765,765,765,120,120,120,120,120,120,120,120,120,120,120,120,120,
-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
-766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,766,
-766,766,766,120,120,120,120,120,120,120,767,767,767,767,767,767,
+1052,1053,1053,1053,262,1053,1053,262,262,262,262,262,1053,1053,1053,1053,
+1052,1052,1052,1052,262,1052,1052,1052,262,1052,1052,1052,1052,1052,1052,1052,
+1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,1052,
+1052,1052,1052,1052,1052,1052,262,262,1054,1054,1054,262,262,262,262,1055,
+1056,1056,1056,1056,1056,1056,1056,1056,1056,262,262,262,262,262,262,262,
+1057,1057,1057,1057,1057,1057,1058,1058,1057,262,262,262,262,262,262,262,
+1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,
+1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1059,1060,1060,1061,
/* block 162 */
-768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
-768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,768,
-768,768,768,768,769,769,769,769,120,120,120,120,120,120,120,120,
-770,770,770,770,770,770,770,770,770,770,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,
+1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1062,1063,1063,1063,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1064,1064,1064,1064,1064,1064,1064,1064,1065,1064,1064,1064,1064,1064,1064,1064,
+1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,1064,
+1064,1064,1064,1064,1064,1066,1066,262,262,262,262,1067,1067,1067,1067,1067,
+1068,1068,1069,1068,1068,1068,1070,262,262,262,262,262,262,262,262,262,
/* block 163 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,
-771,771,771,771,771,771,771,771,771,771,771,771,771,771,771,120,
+1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,
+1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,
+1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,1071,
+1071,1071,1071,1071,1071,1071,262,262,262,1072,1073,1073,1073,1073,1073,1073,
+1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,1074,
+1074,1074,1074,1074,1074,1074,262,262,1075,1075,1075,1075,1075,1075,1075,1075,
+1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,1076,
+1076,1076,1076,262,262,262,262,262,1077,1077,1077,1077,1077,1077,1077,1077,
/* block 164 */
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,772,
-772,772,772,772,772,772,772,772,772,772,120,773,773,774,120,120,
-772,772,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,1078,
+1078,1078,262,262,262,262,262,262,262,1079,1079,1079,1079,262,262,262,
+262,262,262,262,262,262,262,262,262,1080,1080,1080,1080,1080,1080,1080,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 165 */
-775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,775,
-775,775,775,775,775,775,775,775,775,775,775,775,775,776,776,776,
-776,776,776,776,776,776,776,775,120,120,120,120,120,120,120,120,
-777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,777,
-777,777,777,777,777,777,778,778,778,778,778,778,778,778,778,778,
-778,779,779,779,779,780,780,780,780,780,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,781,
+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,
+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,
+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,
+1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,1081,
+1081,1081,1081,1081,1081,1081,1081,1081,1081,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 166 */
-781,781,782,782,782,782,783,783,783,783,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,784,
-784,784,784,784,784,785,785,785,785,785,785,785,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,786,
-786,786,786,786,786,786,786,120,120,120,120,120,120,120,120,120,
+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,
+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,
+1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,1082,
+1082,1082,1082,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,
+1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,
+1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,1083,
+1083,1083,1083,262,262,262,262,262,262,262,1084,1084,1084,1084,1084,1084,
/* block 167 */
-787,788,787,789,789,789,789,789,789,789,789,789,789,789,789,789,
-789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,
-789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,789,
-789,789,789,789,789,789,789,789,788,788,788,788,788,788,788,788,
-788,788,788,788,788,788,788,790,790,790,790,790,790,790,120,120,
-120,120,791,791,791,791,791,791,791,791,791,791,791,791,791,791,
-791,791,791,791,791,791,792,792,792,792,792,792,792,792,792,792,
-788,789,789,788,788,789,120,120,120,120,120,120,120,120,120,788,
+1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,
+1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,1085,
+1085,1085,1086,1086,1087,1087,1087,1087,302,302,302,302,302,302,302,302,
+1088,1088,1088,1088,1088,1088,1088,1088,1088,1088,302,302,302,302,302,302,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 168 */
-793,793,794,795,795,795,795,795,795,795,795,795,795,795,795,795,
-795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,
-795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,795,
-794,794,794,793,793,793,793,794,794,793,793,796,796,797,796,796,
-796,796,793,120,120,120,120,120,120,120,120,120,120,797,120,120,
-798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,798,
-798,798,798,798,798,798,798,798,798,120,120,120,120,120,120,120,
-799,799,799,799,799,799,799,799,799,799,120,120,120,120,120,120,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 169 */
-800,800,800,801,801,801,801,801,801,801,801,801,801,801,801,801,
-801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,801,
-801,801,801,801,801,801,801,800,800,800,800,800,802,800,800,800,
-800,800,800,800,800,120,803,803,803,803,803,803,803,803,803,803,
-804,804,804,804,801,802,802,801,120,120,120,120,120,120,120,120,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,805,
-805,805,805,806,807,807,805,120,120,120,120,120,120,120,120,120,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,
+1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,1089,262,
/* block 170 */
-808,808,809,810,810,810,810,810,810,810,810,810,810,810,810,810,
-810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,
-810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,810,
-810,810,810,809,809,809,808,808,808,808,808,808,808,808,808,809,
-809,810,811,811,810,812,812,812,812,808,808,808,808,812,809,808,
-813,813,813,813,813,813,813,813,813,813,810,812,810,812,812,812,
-120,814,814,814,814,814,814,814,814,814,814,814,814,814,814,814,
-814,814,814,814,814,120,120,120,120,120,120,120,120,120,120,120,
+1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,
+1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,
+1090,1090,1090,1090,1090,1090,1090,1090,1090,1090,262,1091,1091,1092,262,262,
+1090,1090,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 171 */
-815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,815,
-815,815,120,815,815,815,815,815,815,815,815,815,815,815,815,815,
-815,815,815,815,815,815,815,815,815,815,815,815,816,816,816,817,
-817,817,816,816,817,816,817,817,818,818,818,818,818,818,817,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,
+1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1093,1094,1094,1094,
+1094,1094,1094,1094,1094,1094,1094,1093,262,262,262,262,262,262,262,262,
+1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,1095,
+1095,1095,1095,1095,1095,1095,1096,1096,1096,1096,1096,1096,1096,1096,1096,1096,
+1096,1097,1097,1097,1097,1098,1098,1098,1098,1098,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,1099,
/* block 172 */
-819,819,819,819,819,819,819,120,819,120,819,819,819,819,120,819,
-819,819,819,819,819,819,819,819,819,819,819,819,819,819,120,819,
-819,819,819,819,819,819,819,819,819,820,120,120,120,120,120,120,
-821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,
-821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,
-821,821,821,821,821,821,821,821,821,821,821,821,821,821,821,822,
-823,823,823,822,822,822,822,822,822,822,822,120,120,120,120,120,
-824,824,824,824,824,824,824,824,824,824,120,120,120,120,120,120,
+1099,1099,1100,1100,1100,1100,1101,1101,1101,1101,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,1102,
+1102,1102,1102,1102,1102,1103,1103,1103,1103,1103,1103,1103,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,1104,
+1104,1104,1104,1104,1104,1104,1104,262,262,262,262,262,262,262,262,262,
/* block 173 */
-825,826,827,828,120,829,829,829,829,829,829,829,829,120,120,829,
-829,120,120,829,829,829,829,829,829,829,829,829,829,829,829,829,
-829,829,829,829,829,829,829,829,829,120,829,829,829,829,829,829,
-829,120,829,829,120,829,829,829,829,829,120,830,826,829,831,827,
-825,827,827,827,827,120,120,827,827,120,120,827,827,827,120,120,
-829,120,120,120,120,120,120,831,120,120,120,120,120,829,829,829,
-829,829,827,827,120,120,825,825,825,825,825,825,825,120,120,120,
-825,825,825,825,825,120,120,120,120,120,120,120,120,120,120,120,
+1105,1106,1105,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,
+1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,
+1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,1107,
+1107,1107,1107,1107,1107,1107,1107,1107,1106,1106,1106,1106,1106,1106,1106,1106,
+1106,1106,1106,1106,1106,1106,1108,1109,1109,1110,1110,1110,1110,1110,163,163,
+163,163,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,1111,
+1111,1111,1111,1111,1111,1111,1112,1112,1112,1112,1112,1112,1112,1112,1112,1112,
+1108,1107,1107,1106,1106,1107,163,163,163,163,163,163,163,163,163,1113,
/* block 174 */
-832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
-832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
-832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
-832,832,832,832,832,833,833,833,834,834,834,834,834,834,834,834,
-833,833,834,834,834,833,834,832,832,832,832,835,835,835,835,835,
-836,836,836,836,836,836,836,836,836,836,835,835,120,835,834,832,
-832,832,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1114,1114,1115,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,
+1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,
+1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,1116,
+1115,1115,1115,1117,1117,1117,1117,1115,1115,1118,1119,1120,1120,1121,1122,1122,
+1122,1122,1117,163,163,163,163,163,163,163,163,163,163,1121,163,163,
+1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,1123,
+1123,1123,1123,1123,1123,1123,1123,1123,1123,163,163,163,163,163,163,163,
+1124,1124,1124,1124,1124,1124,1124,1124,1124,1124,163,163,163,163,163,163,
/* block 175 */
-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
-837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,837,
-838,839,839,840,840,840,840,840,840,839,840,839,839,838,839,840,
-840,839,840,840,837,837,841,837,120,120,120,120,120,120,120,120,
-842,842,842,842,842,842,842,842,842,842,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1125,1125,1125,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,
+1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,1126,
+1126,1126,1126,1126,1126,1126,1126,1125,1125,1125,1125,1125,1127,1125,1125,1125,
+1125,1125,1125,1128,1128,163,1129,1129,1129,1129,1129,1129,1129,1129,1129,1129,
+1130,1131,1131,1131,1126,1127,1127,1126,163,163,163,163,163,163,163,163,
+1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,
+1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,1132,
+1132,1132,1132,1133,1134,1134,1132,163,163,163,163,163,163,163,163,163,
/* block 176 */
-843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,
-843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,
-843,843,843,843,843,843,843,843,843,843,843,843,843,843,843,844,
-845,845,846,846,846,846,120,120,845,845,845,845,846,846,845,846,
-846,847,847,847,847,847,847,847,847,847,847,847,847,847,847,847,
-847,847,847,847,847,847,847,847,843,843,843,843,846,846,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1135,1135,1136,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,
+1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,
+1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,1137,
+1137,1137,1137,1136,1136,1136,1135,1135,1135,1135,1135,1135,1135,1135,1135,1136,
+1138,1137,1139,1139,1137,1140,1140,1141,1141,1142,1143,1143,1143,1140,1136,1135,
+1144,1144,1144,1144,1144,1144,1144,1144,1144,1144,1137,1141,1137,1141,1140,1140,
+163,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,1145,
+1145,1145,1145,1145,1145,163,163,163,163,163,163,163,163,163,163,163,
/* block 177 */
-848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,
-848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,
-848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,848,
-849,849,849,850,850,850,850,850,850,850,850,849,849,850,849,850,
-850,851,851,851,848,120,120,120,120,120,120,120,120,120,120,120,
-852,852,852,852,852,852,852,852,852,852,120,120,120,120,120,120,
-398,398,398,398,398,398,398,398,398,398,398,398,398,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,
+1146,1146,163,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,
+1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1146,1147,1147,1147,1148,
+1148,1148,1147,1147,1148,1149,1150,1148,1151,1151,1152,1151,1151,1153,1148,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 178 */
-853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
-853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,853,
-853,853,853,853,853,853,853,853,853,853,853,854,855,854,855,855,
-854,854,854,854,854,854,855,854,853,856,120,120,120,120,120,120,
-857,857,857,857,857,857,857,857,857,857,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1154,1154,1154,1154,1154,1154,1154,163,1154,163,1154,1154,1154,1154,163,1154,
+1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,1154,163,1154,
+1154,1154,1154,1154,1154,1154,1154,1154,1154,1155,163,163,163,163,163,163,
+1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,
+1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,
+1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1156,1157,
+1158,1158,1158,1157,1157,1157,1157,1157,1157,1159,1160,163,163,163,163,163,
+1161,1161,1161,1161,1161,1161,1161,1161,1161,1161,163,163,163,163,163,163,
/* block 179 */
-858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
-858,858,858,858,858,858,858,858,858,858,858,120,120,859,859,859,
-860,860,859,859,859,859,861,859,859,859,859,859,120,120,120,120,
-862,862,862,862,862,862,862,862,862,862,863,863,864,864,864,865,
-858,858,858,858,858,858,858,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1162,1163,1164,1165,163,1166,1166,1166,1166,1166,1166,1166,1166,163,163,1166,
+1166,163,163,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,1166,
+1166,1166,1166,1166,1166,1166,1166,1166,1166,163,1166,1166,1166,1166,1166,1166,
+1166,163,1166,1166,163,1166,1166,1166,1166,1166,163,1167,1168,1166,1169,1164,
+1162,1164,1164,1164,1164,163,163,1164,1164,163,163,1164,1164,1170,163,163,
+1166,163,163,163,163,163,163,1169,163,163,163,163,163,1171,1166,1166,
+1166,1166,1164,1164,163,163,1172,1172,1172,1172,1172,1172,1172,163,163,163,
+1172,1172,1172,1172,1172,163,163,163,163,163,163,163,163,163,163,163,
/* block 180 */
-866,866,866,866,866,866,866,866,866,866,866,866,866,866,866,866,
-866,866,866,866,866,866,866,866,866,866,866,866,866,866,866,866,
-866,866,866,866,866,866,866,866,866,866,866,866,867,867,867,868,
-868,868,868,868,868,868,868,868,867,868,868,869,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,
+1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,
+1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,1173,
+1173,1173,1173,1173,1173,1174,1174,1174,1175,1175,1175,1175,1175,1175,1175,1175,
+1174,1174,1176,1175,1175,1174,1177,1173,1173,1173,1173,1178,1178,1179,1180,1180,
+1181,1181,1181,1181,1181,1181,1181,1181,1181,1181,1179,1179,163,1180,1182,1173,
+1173,1173,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 181 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-870,870,870,870,870,870,870,870,870,870,870,870,870,870,870,870,
-870,870,870,870,870,870,870,870,870,870,870,870,870,870,870,870,
-871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,
-871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,871,
-872,872,872,872,872,872,872,872,872,872,873,873,873,873,873,873,
-873,873,873,120,120,120,120,120,120,120,120,120,120,120,120,874,
+1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,
+1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,
+1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,1183,
+1184,1185,1185,1186,1186,1186,1186,1186,1186,1185,1186,1185,1185,1184,1185,1186,
+1186,1185,1187,1188,1183,1183,1189,1183,163,163,163,163,163,163,163,163,
+1190,1190,1190,1190,1190,1190,1190,1190,1190,1190,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 182 */
-875,875,875,875,875,875,875,120,120,875,120,120,875,875,875,875,
-875,875,875,875,120,875,875,120,875,875,875,875,875,875,875,875,
-875,875,875,875,875,875,875,875,875,875,875,875,875,875,875,875,
-876,877,877,877,877,877,120,877,877,120,120,878,878,877,878,879,
-877,879,877,878,880,880,880,120,120,120,120,120,120,120,120,120,
-881,881,881,881,881,881,881,881,881,881,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,
+1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,
+1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1191,1192,
+1193,1193,1194,1194,1194,1194,163,163,1193,1193,1193,1193,1194,1194,1193,1195,
+1196,1197,1198,1198,1199,1199,1200,1200,1200,1198,1198,1198,1198,1198,1198,1198,
+1198,1198,1198,1198,1198,1198,1198,1198,1191,1191,1191,1191,1194,1194,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 183 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-882,882,882,882,882,882,882,882,120,120,882,882,882,882,882,882,
-882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,
-882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,882,
-882,883,883,883,884,884,884,884,120,120,884,884,883,883,883,883,
-884,882,885,882,883,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,
+1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,
+1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,1201,
+1202,1202,1202,1203,1203,1203,1203,1203,1203,1203,1203,1202,1202,1203,1202,1204,
+1203,1205,1205,1206,1201,163,163,163,163,163,163,163,163,163,163,163,
+1207,1207,1207,1207,1207,1207,1207,1207,1207,1207,163,163,163,163,163,163,
+530,530,530,530,530,530,530,530,530,530,530,530,530,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 184 */
-886,887,887,887,887,887,887,887,887,887,887,886,886,886,886,886,
-886,886,886,886,886,886,886,886,886,886,886,886,886,886,886,886,
-886,886,886,886,886,886,886,886,886,886,886,886,886,886,886,886,
-886,886,886,887,887,887,887,887,887,888,889,887,887,887,887,890,
-890,890,890,890,890,890,890,887,120,120,120,120,120,120,120,120,
-891,892,892,892,892,892,892,893,893,892,892,892,891,891,891,891,
-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
-891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,891,
+1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,
+1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,
+1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1208,1209,1210,1209,1210,1210,
+1209,1209,1209,1209,1209,1209,1211,1212,1208,1213,163,163,163,163,163,163,
+1214,1214,1214,1214,1214,1214,1214,1214,1214,1214,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 185 */
-891,891,891,891,894,894,894,894,894,894,892,892,892,892,892,892,
-892,892,892,892,892,892,892,893,892,892,895,895,895,891,895,895,
-895,895,895,120,120,120,120,120,120,120,120,120,120,120,120,120,
-370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,370,
-896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
-896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
-896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,896,
-896,896,896,896,896,896,896,896,896,120,120,120,120,120,120,120,
+1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,
+1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,1215,163,163,1216,1216,1216,
+1217,1217,1216,1216,1216,1216,1218,1216,1216,1216,1216,1219,163,163,163,163,
+1220,1220,1220,1220,1220,1220,1220,1220,1220,1220,1221,1221,1222,1222,1222,1223,
+1215,1215,1215,1215,1215,1215,1215,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 186 */
-897,897,897,897,897,897,897,897,897,120,897,897,897,897,897,897,
-897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,
-897,897,897,897,897,897,897,897,897,897,897,897,897,897,897,898,
-899,899,899,899,899,899,899,120,899,899,899,899,899,899,898,899,
-897,900,900,900,900,900,120,120,120,120,120,120,120,120,120,120,
-901,901,901,901,901,901,901,901,901,901,902,902,902,902,902,902,
-902,902,902,902,902,902,902,902,902,902,902,902,902,120,120,120,
-903,903,904,904,904,904,904,904,904,904,904,904,904,904,904,904,
+1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,
+1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,
+1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1224,1225,1225,1225,1226,
+1226,1226,1226,1226,1226,1226,1226,1226,1225,1227,1228,1229,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 187 */
-904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,904,
-120,120,905,905,905,905,905,905,905,905,905,905,905,905,905,905,
-905,905,905,905,905,905,905,905,120,906,905,905,905,905,905,905,
-905,906,905,905,906,905,905,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,
+1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,1230,
+1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,
+1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,1231,
+1232,1232,1232,1232,1232,1232,1232,1232,1232,1232,1233,1233,1233,1233,1233,1233,
+1233,1233,1233,163,163,163,163,163,163,163,163,163,163,163,163,1234,
/* block 188 */
-907,907,907,907,907,907,907,120,907,907,120,907,907,907,907,907,
-907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,
-907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,907,
-907,908,908,908,908,908,908,120,120,120,908,120,908,908,120,908,
-908,908,908,908,908,908,909,908,120,120,120,120,120,120,120,120,
-910,910,910,910,910,910,910,910,910,910,120,120,120,120,120,120,
-911,911,911,911,911,911,120,911,911,120,911,911,911,911,911,911,
-911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,911,
+1235,1235,1235,1235,1235,1235,1235,163,163,1235,163,163,1235,1235,1235,1235,
+1235,1235,1235,1235,163,1235,1235,163,1235,1235,1235,1235,1235,1235,1235,1235,
+1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,1235,
+1236,1237,1237,1237,1237,1237,163,1237,1237,163,163,1238,1238,1239,1240,1241,
+1237,1241,1237,1242,1243,1244,1243,163,163,163,163,163,163,163,163,163,
+1245,1245,1245,1245,1245,1245,1245,1245,1245,1245,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 189 */
-911,911,911,911,911,911,911,911,911,911,912,912,912,912,912,120,
-913,913,120,912,912,913,912,913,911,120,120,120,120,120,120,120,
-914,914,914,914,914,914,914,914,914,914,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1246,1246,1246,1246,1246,1246,1246,1246,163,163,1246,1246,1246,1246,1246,1246,
+1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,
+1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,1246,
+1246,1247,1247,1247,1248,1248,1248,1248,163,163,1248,1248,1247,1247,1247,1247,
+1249,1246,1250,1246,1247,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 190 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,915,
-915,915,915,916,916,917,917,918,918,120,120,120,120,120,120,120,
+1251,1252,1252,1252,1252,1252,1252,1253,1253,1252,1252,1251,1251,1251,1251,1251,
+1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,
+1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,1251,
+1251,1251,1251,1254,1255,1252,1252,1252,1252,1256,1257,1252,1252,1252,1252,1258,
+1258,1258,1259,1259,1258,1258,1258,1255,163,163,163,163,163,163,163,163,
+1260,1261,1261,1261,1261,1261,1261,1262,1262,1261,1261,1261,1260,1260,1260,1260,
+1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,
+1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,1260,
/* block 191 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-595,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-919,919,919,919,919,919,919,919,919,919,919,919,919,919,919,919,
-295,295,919,295,919,297,297,297,297,297,297,297,297,298,298,298,
-298,297,297,297,297,297,297,297,297,297,297,297,297,297,297,297,
-297,297,120,120,120,120,120,120,120,120,120,120,120,120,120,920,
+1260,1260,1260,1260,1263,1263,1263,1263,1263,1263,1261,1261,1261,1261,1261,1261,
+1261,1261,1261,1261,1261,1261,1261,1262,1264,1265,1266,1267,1267,1260,1266,1266,
+1266,1268,1268,163,163,163,163,163,163,163,163,163,163,163,163,163,
+495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,495,
+1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,
+1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,
+1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,1269,
+1269,1269,1269,1269,1269,1269,1269,1269,1269,163,163,163,163,163,163,163,
/* block 192 */
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
+1270,1270,1270,1270,1270,1270,1270,1270,1270,163,1270,1270,1270,1270,1270,1270,
+1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,
+1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1270,1271,
+1272,1272,1272,1272,1272,1272,1272,163,1272,1272,1272,1272,1272,1272,1271,1273,
+1270,1274,1274,1275,1276,1276,163,163,163,163,163,163,163,163,163,163,
+1277,1277,1277,1277,1277,1277,1277,1277,1277,1277,1278,1278,1278,1278,1278,1278,
+1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,1278,163,163,163,
+1279,1280,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,
/* block 193 */
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,1281,
+163,163,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,1282,
+1282,1282,1282,1282,1282,1282,1282,1282,163,1283,1282,1282,1282,1282,1282,1282,
+1282,1283,1282,1282,1283,1282,1282,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 194 */
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,
-922,922,922,922,922,922,922,922,922,922,922,922,922,922,922,120,
-923,923,923,923,923,120,120,120,120,120,120,120,120,120,120,120,
+1284,1284,1284,1284,1284,1284,1284,163,1284,1284,163,1284,1284,1284,1284,1284,
+1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,
+1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,1284,
+1284,1285,1285,1285,1285,1285,1285,163,163,163,1285,163,1285,1285,163,1285,
+1285,1285,1286,1285,1287,1287,1288,1285,163,163,163,163,163,163,163,163,
+1289,1289,1289,1289,1289,1289,1289,1289,1289,1289,163,163,163,163,163,163,
+1290,1290,1290,1290,1290,1290,163,1290,1290,163,1290,1290,1290,1290,1290,1290,
+1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,
/* block 195 */
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,921,
-921,921,921,921,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1290,1290,1290,1290,1290,1290,1290,1290,1290,1290,1291,1291,1291,1291,1291,163,
+1292,1292,163,1291,1291,1292,1291,1293,1290,163,163,163,163,163,163,163,
+1294,1294,1294,1294,1294,1294,1294,1294,1294,1294,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 196 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,924,
-924,925,925,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,1295,
+1295,1295,1295,1296,1296,1297,1297,1298,1298,163,163,163,163,163,163,163,
/* block 197 */
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+842,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,1299,
+388,388,1299,388,1299,390,390,390,390,390,390,390,390,391,391,391,
+391,390,390,390,390,390,390,390,390,390,390,390,390,390,390,390,
+390,390,163,163,163,163,163,163,163,163,163,163,163,163,163,1300,
/* block 198 */
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,
-926,926,926,926,926,926,926,926,926,926,926,926,926,926,926,120,
-927,927,927,927,927,927,927,927,927,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
/* block 199 */
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 200 */
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,928,
-928,928,928,928,928,928,928,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,
+1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,1302,163,
+1303,1303,1303,1303,1303,163,163,163,163,163,163,163,163,163,163,163,
/* block 201 */
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,1301,
+1301,1301,1301,1301,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 202 */
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,606,
-606,606,606,606,606,606,606,606,606,120,120,120,120,120,120,120,
-929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,
-929,929,929,929,929,929,929,929,929,929,929,929,929,929,929,120,
-930,930,930,930,930,930,930,930,930,930,120,120,120,120,931,931,
-932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,1304,
+1304,1305,1305,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 203 */
-932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
-932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
-932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,
-932,932,932,932,932,932,932,932,932,932,932,932,932,932,932,120,
-933,933,933,933,933,933,933,933,933,933,120,120,120,120,120,120,
-934,934,934,934,934,934,934,934,934,934,934,934,934,934,934,934,
-934,934,934,934,934,934,934,934,934,934,934,934,934,934,120,120,
-935,935,935,935,935,936,120,120,120,120,120,120,120,120,120,120,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
/* block 204 */
-937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,
-937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,
-937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,
-938,938,938,938,938,938,938,939,939,939,939,939,940,940,940,940,
-941,941,941,941,939,940,120,120,120,120,120,120,120,120,120,120,
-942,942,942,942,942,942,942,942,942,942,120,943,943,943,943,943,
-943,943,120,937,937,937,937,937,937,937,937,937,937,937,937,937,
-937,937,937,937,937,937,937,937,120,120,120,120,120,937,937,937,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,
+1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,1306,163,
+1307,1307,1307,1307,1307,1307,1307,1307,1307,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 205 */
-937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,937,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
/* block 206 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-944,944,944,944,944,944,944,944,944,944,944,944,944,944,944,944,
-944,944,944,944,944,944,944,944,944,944,944,944,944,944,944,944,
-945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
-945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,945,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,1308,
+1308,1308,1308,1308,1308,1308,1308,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 207 */
-946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,946,
-946,946,946,946,946,946,946,947,947,947,947,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
/* block 208 */
-948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
-948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
-948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
-948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,948,
-948,948,948,948,948,948,948,948,948,948,948,120,120,120,120,949,
-948,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
-950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,858,
+858,858,858,858,858,858,858,858,858,163,163,163,163,163,163,163,
+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,
+1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,1309,163,
+1310,1310,1310,1310,1310,1310,1310,1310,1310,1310,163,163,163,163,1311,1311,
+1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,
/* block 209 */
-950,950,950,950,950,950,950,950,120,120,120,120,120,120,120,949,
-949,949,949,951,951,951,951,951,951,951,951,951,951,951,951,951,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-952,953,954,562,955,120,120,120,120,120,120,120,120,120,120,120,
-956,956,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,
+1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,
+1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,
+1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,1312,163,
+1313,1313,1313,1313,1313,1313,1313,1313,1313,1313,163,163,163,163,163,163,
+1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,
+1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,1314,163,163,
+1315,1315,1315,1315,1315,1316,163,163,163,163,163,163,163,163,163,163,
/* block 210 */
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,
+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,
+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,
+1318,1318,1318,1318,1318,1318,1318,1319,1319,1320,1321,1321,1322,1322,1322,1322,
+1323,1323,1324,1324,1319,1322,163,163,163,163,163,163,163,163,163,163,
+1325,1325,1325,1325,1325,1325,1325,1325,1325,1325,163,1326,1326,1326,1326,1326,
+1326,1326,163,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,
+1317,1317,1317,1317,1317,1317,1317,1317,163,163,163,163,163,1317,1317,1317,
/* block 211 */
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,957,
-957,957,957,957,957,957,957,957,120,120,120,120,120,120,120,120,
+1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,1317,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 212 */
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,
+1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,1327,
+1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,
+1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,1328,
/* block 213 */
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,958,
-958,958,958,958,958,958,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,1329,
+1329,1329,1329,1329,1329,1329,1329,1330,1331,1332,1332,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 214 */
-957,957,957,957,957,957,957,957,957,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,
+1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,
+1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,
+1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,
+1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,1333,163,163,163,163,1334,
+1333,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,
+1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,
+1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,1335,
/* block 215 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-584,584,584,584,120,584,584,584,584,584,584,584,120,584,584,120,
+1335,1335,1335,1335,1335,1335,1335,1335,163,163,163,163,163,163,163,1336,
+1336,1336,1336,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,1337,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1338,1339,1340,799,1341,163,163,163,163,163,163,163,163,163,163,163,
+1342,1342,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 216 */
-583,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
/* block 217 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,1343,
+1343,1343,1343,1343,1343,1343,1343,1343,163,163,163,163,163,163,163,163,
/* block 218 */
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,578,
-583,583,583,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-578,578,578,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,583,583,583,583,120,120,120,120,120,120,120,120,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
/* block 219 */
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,1344,
+1344,1344,1344,1344,1344,1344,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 220 */
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,959,
-959,959,959,959,959,959,959,959,959,959,959,959,120,120,120,120,
+1343,1343,1343,1343,1343,1343,1343,1343,1343,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 221 */
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,960,
-960,960,960,960,960,960,960,960,960,960,960,120,120,120,120,120,
-960,960,960,960,960,960,960,960,960,960,960,960,960,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1345,1345,1345,1345,163,1345,1345,1345,1345,1345,1345,1345,163,1345,1345,163,
/* block 222 */
-960,960,960,960,960,960,960,960,960,120,120,120,120,120,120,120,
-960,960,960,960,960,960,960,960,960,960,120,120,961,962,962,963,
-964,964,964,964,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+824,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
/* block 223 */
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,120,120,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,120,120,120,120,120,120,120,120,120,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
/* block 224 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,819,
+824,824,824,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+819,819,819,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,824,824,824,824,163,163,163,163,163,163,163,163,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
/* block 225 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,120,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
/* block 226 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,120,120, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20,965,966,113,113,113, 20, 20, 20,966,965,965,
-965,965,965, 24, 24, 24, 24, 24, 24, 24, 24,113,113,113,113,113,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,
+1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,1346,163,163,163,163,
/* block 227 */
-113,113,113, 20, 20,113,113,113,113,113,113,113, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,113,113,113,113, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,163,163,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,
/* block 228 */
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,692,
-692,692,967,967,967,692,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,163,163,163,163,163,
+1347,1347,1347,1347,1347,1347,1347,1347,1347,1347,163,163,1348,1349,1350,1351,
+1352,1352,1352,1352,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 229 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,120,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,163,163,
+154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,154,
+154,154,154,154,154,154,154,163,163,163,163,163,163,163,163,163,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
/* block 230 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,120,120,120,120,
-587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,587,
-587,587, 25, 25, 25, 25, 25, 25, 25,120,120,120,120,120,120,120,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 231 */
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,519,519,
-519,519,519,519,519,120,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
/* block 232 */
-518,518,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,518,120,518,518,
-120,120,518,120,120,518,518,120,120,518,518,518,518,120,518,518,
-518,518,518,518,518,518,519,519,519,519,120,519,120,519,519,519,
-519,519,519,519,120,519,519,519,519,519,519,519,519,519,519,519,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,163,163,163,163,163,163,163,163,163,163,
/* block 233 */
-519,519,519,519,518,518,120,518,518,518,518,120,120,518,518,518,
-518,518,518,518,518,120,518,518,518,518,518,518,518,120,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,518,518,120,518,518,518,518,120,
-518,518,518,518,518,120,518,120,120,120,518,518,518,518,518,518,
-518,120,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,163,163,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,1353,1354,154,154,154,460,460,460,1355,1356,1356,
+1356,1356,1356, 51, 51, 51, 51, 51, 51, 51, 51,154,154,154,154,154,
/* block 234 */
-518,518,518,518,518,518,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+154,154,154,460,460,154,154,154,154,154,154,154,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,154,154,154,154,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,723,723,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 235 */
-519,519,519,519,519,519,519,519,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
+1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,
+1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,
+1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,
+1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,1002,
+1002,1002,1357,1357,1357,1002,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 236 */
-518,518,518,518,518,518,518,518,518,518,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,120,120,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518, 9,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519, 9,519,519,519,519,
-519,519,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518, 9,519,519,519,519,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,835,
+835,835,835,835,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 237 */
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519, 9,519,519,519,519,519,519,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518, 9,519,519,519,519,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519, 9,
-519,519,519,519,519,519,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518, 9,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,163,163,163,163,163,163,163,163,163,
+832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,832,
+832,832,835,835,835,835,835,835,835,163,163,163,163,163,163,163,
/* block 238 */
-519,519,519,519,519,519,519,519,519, 9,519,519,519,519,519,519,
-518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,518,
-518,518,518,518,518,518,518,518,518, 9,519,519,519,519,519,519,
-519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,519,
-519,519,519, 9,519,519,519,519,519,519,518,519,120,120, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,
+725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,
+725,725,725,725,725,163,736,736,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
/* block 239 */
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
-968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,968,
+724,724,725,725,725,725,725,725,725,725,736,736,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,724,163,724,724,
+163,163,724,163,163,724,724,163,163,724,724,724,724,163,724,724,
+724,724,724,724,724,724,725,725,725,725,163,725,163,725,736,736,
+725,725,725,725,163,725,725,725,725,725,725,725,725,725,725,725,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,
+725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,
/* block 240 */
-969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-969,969,969,969,969,969,969,968,968,968,968,969,969,969,969,969,
-969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-969,969,969,969,969,969,969,969,969,969,969,969,969,968,968,968,
-968,968,968,968,968,969,968,968,968,968,968,968,968,968,968,968,
+725,725,725,725,724,724,163,724,724,724,724,163,163,724,724,724,
+724,724,724,724,724,163,724,724,724,724,724,724,724,163,725,725,
+725,725,725,725,725,725,736,736,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,724,724,163,724,724,724,724,163,
+724,724,724,724,724,163,724,163,163,163,724,724,724,724,724,724,
+724,163,725,725,725,725,725,725,725,725,736,736,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
/* block 241 */
-968,968,968,968,969,968,968,970,970,970,970,970,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,969,969,969,969,969,
-120,969,969,969,969,969,969,969,969,969,969,969,969,969,969,969,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+724,724,724,724,724,724,725,725,725,725,725,725,725,725,736,736,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,
+725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,725,725,
+725,725,725,725,725,725,736,736,725,725,725,725,725,725,725,725,
/* block 242 */
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 22, 35, 35, 35, 35, 35,
- 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+725,725,725,725,725,725,725,725,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,725,725,725,725,725,725,725,725,736,736,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,725,725,725,725,725,725,725,725,736,736,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
/* block 243 */
-971,971,971,971,971,971,971,120,971,971,971,971,971,971,971,971,
-971,971,971,971,971,971,971,971,971,120,120,971,971,971,971,971,
-971,971,120,971,971,120,971,971,971,971,971,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+724,724,724,724,724,724,724,724,724,724,725,725,725,725,725,725,
+725,725,736,736,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,163,163,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,1358,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,715,725,725,725,725,
+725,725,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,1358,725,725,725,725,
/* block 244 */
-972,972,972,972,972,972,972,972,972,972,972,972,972,972,972,972,
-972,972,972,972,972,972,972,972,972,972,972,972,972,972,972,972,
-972,972,972,972,972,972,972,972,972,972,972,972,972,120,120,120,
-973,973,973,973,973,973,973,974,974,974,974,974,974,974,120,120,
-975,975,975,975,975,975,975,975,975,975,120,120,120,120,972,976,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,715,725,725,725,725,725,725,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,1358,725,725,725,725,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,715,
+725,725,725,725,725,725,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,1358,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
/* block 245 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-977,977,977,977,977,977,977,977,977,977,977,977,977,977,977,977,
-977,977,977,977,977,977,977,977,977,977,977,977,977,977,978,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-979,979,979,979,979,979,979,979,979,979,979,979,979,979,979,979,
-979,979,979,979,979,979,979,979,979,979,979,979,979,979,979,979,
-979,979,979,979,979,979,979,979,979,979,979,979,980,980,980,980,
-981,981,981,981,981,981,981,981,981,981,120,120,120,120,120,982,
+725,725,725,725,725,725,725,725,725,715,725,725,725,725,725,725,
+724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,724,
+724,724,724,724,724,724,724,724,724,1358,725,725,725,725,725,725,
+725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,725,
+725,725,725,715,725,725,725,725,725,725,724,725,163,163,1359,1359,
+1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,
+1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,
+1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,1359,
/* block 246 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-361,361,361,361,361,361,361,120,361,361,361,361,120,361,361,120,
-361,361,361,361,361,361,361,361,361,361,361,361,361,361,361,120,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
+1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
/* block 247 */
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1360,1360,1360,1360,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1360,1360,1360,
+1360,1360,1360,1360,1360,1361,1360,1360,1360,1360,1360,1360,1360,1360,1360,1360,
/* block 248 */
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,983,
-983,983,983,983,983,120,120,984,984,984,984,984,984,984,984,984,
-985,985,985,985,985,985,985,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1360,1360,1360,1360,1361,1360,1360,1362,1363,1362,1362,1364,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,1361,1361,1361,1361,1361,
+163,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,1361,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 249 */
-986,986,986,986,986,986,986,986,986,986,986,986,986,986,986,986,
-986,986,986,986,986,986,986,986,986,986,986,986,986,986,986,986,
-986,986,987,987,987,987,987,987,987,987,987,987,987,987,987,987,
-987,987,987,987,987,987,987,987,987,987,987,987,987,987,987,987,
-987,987,987,987,988,988,988,988,988,988,988,989,120,120,120,120,
-990,990,990,990,990,990,990,990,990,990,120,120,120,120,991,991,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 92, 70, 70, 70, 70, 70,
+ 70, 70, 70, 70, 70, 70, 70, 70, 70, 70,643, 70, 70, 70, 70,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 250 */
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+1365,1365,1365,1365,1365,1365,1365,163,1365,1365,1365,1365,1365,1365,1365,1365,
+1365,1365,1365,1365,1365,1365,1365,1365,1365,163,163,1365,1365,1365,1365,1365,
+1365,1365,163,1365,1365,163,1365,1365,1365,1365,1365,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 251 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25, 25, 25,
- 6, 25, 25, 25, 25,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,
+1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,
+1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,1366,163,163,163,
+1367,1367,1367,1367,1367,1367,1367,1368,1368,1368,1368,1368,1369,1369,163,163,
+1370,1370,1370,1370,1370,1370,1370,1370,1370,1370,163,163,163,163,1366,1371,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
/* block 252 */
-120, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,
+1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1372,1373,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,
+1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,
+1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1374,1375,1375,1375,1375,
+1376,1376,1376,1376,1376,1376,1376,1376,1376,1376,163,163,163,163,163,1377,
/* block 253 */
-225,225,225,225,120,225,225,225,225,225,225,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,225,
-120,225,225,120,225,120,120,225,120,225,225,225,225,225,225,225,
-225,225,225,120,225,225,225,225,120,225,120,225,120,120,120,120,
-120,120,225,120,120,120,120,225,120,225,120,225,120,225,225,225,
-120,225,225,120,225,120,120,225,120,225,120,225,120,225,120,225,
-120,225,225,120,225,120,120,225,225,225,225,120,225,225,225,225,
-225,225,225,120,225,225,225,225,120,225,225,225,225,120,225,120,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+483,483,483,483,483,483,483,163,483,483,483,483,163,483,483,163,
+483,483,483,483,483,483,483,483,483,483,483,483,483,483,483,163,
/* block 254 */
-225,225,225,225,225,225,225,225,225,225,120,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120,
-120,225,225,225,120,225,225,225,225,225,120,225,225,225,225,225,
-225,225,225,225,225,225,225,225,225,225,225,225,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-217,217,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
/* block 255 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,1378,
+1378,1378,1378,1378,1378,262,262,1379,1379,1379,1379,1379,1379,1379,1379,1379,
+1380,1380,1380,1380,1380,1380,1380,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 256 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,
-992, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-992, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
-992, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,992,
+1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,
+1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,1381,
+1381,1381,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,
+1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,1382,
+1382,1382,1382,1382,1383,1383,1383,1384,1385,1385,1385,1386,262,262,262,262,
+1387,1387,1387,1387,1387,1387,1387,1387,1387,1387,262,262,262,262,1388,1388,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 257 */
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 21, 21, 21,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21,
- 21, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+302,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,
/* block 258 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20,
- 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,993,993,993,993,993,993,993,993,993,993,
-993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,993,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1390,1389,1389,1389,
+1391,1389,1389,1389,1389,302,302,302,302,302,302,302,302,302,302,302,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 259 */
-994, 21, 21,992,992,992,992,992,992,992,992,992,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
- 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20,992,992,992,992,992,992,992,
-589,589,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
+302,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1390,1389,
+1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,1389,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
+262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,262,
/* block 260 */
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
+1392,1392,1392,1392,302,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,
+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,
+302,1392,1392,302,1392,302,302,1392,302,1392,1392,1392,1392,1392,1392,1392,
+1392,1392,1392,302,1392,1392,1392,1392,302,1392,302,1392,302,302,302,302,
+302,302,1392,302,302,302,302,1392,302,1392,302,1392,302,1392,1392,1392,
+302,1392,1392,302,1392,302,302,1392,302,1392,302,1392,302,1392,302,1392,
+302,1392,1392,302,1392,302,302,1392,1392,1392,1392,302,1392,1392,1392,1392,
+1392,1392,1392,302,1392,1392,1392,1392,302,1392,1392,1392,1392,302,1392,302,
/* block 261 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,1392,1392,1392,1392,1392,
+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,302,302,302,
+302,1392,1392,1392,302,1392,1392,1392,1392,1392,302,1392,1392,1392,1392,1392,
+1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,1392,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
+274,274,302,302,302,302,302,302,302,302,302,302,302,302,302,302,
/* block 262 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,995,995,995,995,995,
+1393,1393,1393,1393,1394,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
/* block 263 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 20,
- 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,
+1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1394,
+1395,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 264 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 58, 58,1393,1393,1393,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,1393,
+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,
+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,460,460,460,460,460,460,
+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,
+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,723,723,1393,1393,1393,1393,
+1397,1397,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,1397,1397,
/* block 265 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,
+1396,1396,1396,1396,1396,1396,1396,1396,1396,1396,460,460,460,460,1398,460,
+460,1398,1398,1398,1398,1398,1398,1398,1398,1398,1398,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,1393,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,
+1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,1399,
/* block 266 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20,992,992,992,992,992,992,992,992,992,992,992,992,
+1400,1398,1401,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+460,460,460,460,460,460,460,460,460,460,1398,460,460,460,460,460,
+460,460,460,460,460,460,460,460,460,460,460,460,460,460,460,1398,
+460,460,1398,1398,1398,1398,1398,1401,1398,1398,1398,460,1395,1395,1395,1395,
+460,460,460,460,460,460,460,460,460,1395,1395,1395,1395,1395,1395,1395,
+1402,1402,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1393,1393,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 267 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 21, 21, 21, 21,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,
- 21,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 268 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20,992,992,992,992,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,992,992,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,727,1393,1393,727,727,727,727,727,727,727,727,727,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,727,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,1394,1394,
/* block 269 */
- 20, 20, 20, 20, 20, 20, 20, 20,992,992,992,992,992,992,992,992,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,992,992,
- 21, 21,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
+1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1393,1393,727,727,1393,727,727,727,1393,1393,727,727,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1403,1403,1403,1394,1394,1403,1394,1394,1403,1404,1404,727,727,1394,
+1394,1394,1394,1394,727,727,727,727,727,727,727,727,727,727,727,727,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1393,1393,727,1394,727,1393,727,1394,1394,1394,1405,1405,1405,1405,1405,
/* block 270 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,
+1394,727,1403,1403,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,
+1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,
+1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,1394,1394,1403,1394,1394,1394,
/* block 271 */
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,
- 21, 21, 21, 21, 21,992,992,992, 21, 21, 21, 21, 21,992,992,992,
+1394,1403,1403,1403,1394,1403,1403,1403,1394,1394,1394,1394,1394,1394,1394,1403,
+1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,727,1393,1394,
/* block 272 */
- 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,
- 21, 21, 21, 21, 21, 21, 21,992,992,992,992,992,992,992,992,992,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,723,723,
+723,723,723,723,723,723,1393,1393,1393,727,727,1394,1394,1394,1394,1393,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1393,1393,1393,1393,1393,1393,1393,727,
+727,1393,1393,727,1404,1404,727,727,727,727,1403,1393,1393,1393,1393,1393,
/* block 273 */
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20,120, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
- 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,120,120,120,120,120,120,
+1393,1393,1393,1393,1393,1393,1393,727,1393,1393,727,727,727,727,1393,1393,
+1404,1393,1393,1393,1393,1403,1403,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1394,727,1393,1393,727,1393,1393,1393,1393,1393,1393,1393,
+1393,727,727,1393,1393,1393,1393,1393,1393,1393,1393,1393,727,1393,1393,1393,
+1393,1393,727,727,727,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,727,727,727,1393,1393,1393,1393,1393,1393,1393,1393,727,727,727,1393,
+1393,727,1393,727,1393,1393,1393,1393,727,1393,1393,1393,1393,1393,1393,727,
+1393,1393,1393,727,1393,1393,1393,1393,1393,1393,727,1394,1394,1394,1394,1394,
/* block 274 */
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,992,
-992,992,992,992,992,992,992,992,992,992,992,992,992,992,120,120,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1403,1403,1403,1394,1394,1394,1403,1403,1403,1403,1403,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
/* block 275 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1403,1403,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1403,1394,1394,1394,1394,1394,1393,1393,1393,1393,1393,727,1403,727,727,727,
+1394,1394,1394,1393,1393,1394,1394,1394,1395,1395,1395,1395,1395,1394,1394,1394,
+727,727,727,727,727,727,1393,1393,1393,727,1393,1394,1394,1395,1395,1395,
+727,1393,1393,727,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,
/* block 276 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,120,120,120,120,120,120,120,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 277 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,120,120,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,
+1394,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 278 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
+723,723,723,723,723,723,723,723,723,723,723,723,1395,1395,1395,1395,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,
+723,723,723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
/* block 279 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+723,723,723,723,723,723,723,723,1395,1395,1395,1395,1395,1395,1395,1395,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,1395,1395,
+1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 280 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+723,723,723,723,723,723,723,723,723,723,723,723,1403,1394,1394,1403,
+1394,1394,1394,1394,1394,1394,1394,1394,1403,1403,1403,1403,1403,1403,1403,1403,
+1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,723,1403,1403,1403,1394,
+1394,1394,1394,1394,1394,1394,723,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1403,1394,1394,1394,1394,1394,1394,1394,1394,
/* block 281 */
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,591,
-591,591,591,591,591,591,591,591,591,591,591,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
-120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,120,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1406,1406,1406,1406,1394,1403,1403,1394,1403,1403,1394,1403,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1403,1403,1403,
+1394,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1403,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
/* block 282 */
-516, 24,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
-996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,996,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,
+1393,1393,1393,1393,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1393,1395,1395,
+1394,1394,1394,1394,1394,1395,1395,1395,1394,1394,1394,1394,1394,1395,1395,1395,
/* block 283 */
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,
+1394,1394,1394,1403,1403,1403,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1394,1394,1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,
+1394,1394,1394,1394,1394,1394,1394,1394,1395,1395,1395,1395,1395,1395,1395,1395,
+1403,1403,1403,1403,1403,1403,1403,1395,1395,1395,1395,1395,1395,1395,1395,1395,
/* block 284 */
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
/* block 285 */
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,113,
-516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,516,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,163,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,723,
+723,723,723,723,723,723,723,723,723,723,723,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+1407,1407,1407,1407,1407,1407,1407,1407,1407,1407,163,163,163,163,163,163,
/* block 286 */
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
-678,678,678,678,678,678,678,678,678,678,678,678,678,678,120,120,
-
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,
+1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,1395,958,958,
+
+/* block 287 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+
+/* block 288 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,163,163,163,163,163,163,163,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+
+/* block 289 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,163,163,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+
+/* block 290 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+
+/* block 291 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+
+/* block 292 */
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,953,
+953,953,953,953,953,953,953,953,953,953,953,953,953,953,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+
+/* block 293 */
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,958,958,
+
+/* block 294 */
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,838,
+838,838,838,838,838,838,838,838,838,838,838,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,163,
+
+/* block 295 */
+707,712,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,1408,
+
+/* block 296 */
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+
+/* block 297 */
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+
+/* block 298 */
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,961,
+707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,707,
+
+/* block 299 */
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,952,
+952,952,952,952,952,952,952,952,952,952,952,952,952,952,958,958,
};
#if UCD_BLOCK_SIZE != 128
@@ -4622,3 +5392,5 @@ const uint16_t PRIV(ucd_stage2)[] = { /* 73472 bytes, block = 128 */
#endif /* SUPPORT_UNICODE */
#endif /* PCRE2_PCRE2TEST */
+
+/* End of pcre2_ucd.c */
diff --git a/thirdparty/pcre2/src/pcre2_ucp.h b/thirdparty/pcre2/src/pcre2_ucp.h
index d84f269e87..282238982d 100644
--- a/thirdparty/pcre2/src/pcre2_ucp.h
+++ b/thirdparty/pcre2/src/pcre2_ucp.h
@@ -7,7 +7,11 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2018 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
+
+This module is auto-generated from Unicode data files. DO NOT EDIT MANUALLY!
+Instead, modify the maint/GenerateUcpHeader.py script and run it to generate
+a new version of this code.
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -38,31 +42,27 @@ POSSIBILITY OF SUCH DAMAGE.
-----------------------------------------------------------------------------
*/
-
#ifndef PCRE2_UCP_H_IDEMPOTENT_GUARD
#define PCRE2_UCP_H_IDEMPOTENT_GUARD
-/* This file contains definitions of the property values that are returned by
-the UCD access macros. New values that are added for new releases of Unicode
-should always be at the end of each enum, for backwards compatibility.
+/* This file contains definitions of the Unicode property values that are
+returned by the UCD access macros and used throughout PCRE2.
-IMPORTANT: Note also that the specific numeric values of the enums have to be
-the same as the values that are generated by the maint/MultiStage2.py script,
-where the equivalent property descriptive names are listed in vectors.
-
-ALSO: The specific values of the first two enums are assumed for the table
-called catposstab in pcre2_compile.c. */
+IMPORTANT: The specific values of the first two enums (general and particular
+character categories) are assumed by the table called catposstab in the file
+pcre2_auto_possess.c. They are unlikely to change, but should be checked after
+an update. */
/* These are the general character categories. */
enum {
- ucp_C, /* Other */
- ucp_L, /* Letter */
- ucp_M, /* Mark */
- ucp_N, /* Number */
- ucp_P, /* Punctuation */
- ucp_S, /* Symbol */
- ucp_Z /* Separator */
+ ucp_C,
+ ucp_L,
+ ucp_M,
+ ucp_N,
+ ucp_P,
+ ucp_S,
+ ucp_Z,
};
/* These are the particular character categories. */
@@ -97,7 +97,98 @@ enum {
ucp_So, /* Other symbol */
ucp_Zl, /* Line separator */
ucp_Zp, /* Paragraph separator */
- ucp_Zs /* Space separator */
+ ucp_Zs, /* Space separator */
+};
+
+/* These are Boolean properties. */
+
+enum {
+ ucp_ASCII,
+ ucp_ASCII_Hex_Digit,
+ ucp_Alphabetic,
+ ucp_Bidi_Control,
+ ucp_Bidi_Mirrored,
+ ucp_Case_Ignorable,
+ ucp_Cased,
+ ucp_Changes_When_Casefolded,
+ ucp_Changes_When_Casemapped,
+ ucp_Changes_When_Lowercased,
+ ucp_Changes_When_Titlecased,
+ ucp_Changes_When_Uppercased,
+ ucp_Dash,
+ ucp_Default_Ignorable_Code_Point,
+ ucp_Deprecated,
+ ucp_Diacritic,
+ ucp_Emoji,
+ ucp_Emoji_Component,
+ ucp_Emoji_Modifier,
+ ucp_Emoji_Modifier_Base,
+ ucp_Emoji_Presentation,
+ ucp_Extended_Pictographic,
+ ucp_Extender,
+ ucp_Grapheme_Base,
+ ucp_Grapheme_Extend,
+ ucp_Grapheme_Link,
+ ucp_Hex_Digit,
+ ucp_IDS_Binary_Operator,
+ ucp_IDS_Trinary_Operator,
+ ucp_ID_Continue,
+ ucp_ID_Start,
+ ucp_Ideographic,
+ ucp_Join_Control,
+ ucp_Logical_Order_Exception,
+ ucp_Lowercase,
+ ucp_Math,
+ ucp_Noncharacter_Code_Point,
+ ucp_Pattern_Syntax,
+ ucp_Pattern_White_Space,
+ ucp_Prepended_Concatenation_Mark,
+ ucp_Quotation_Mark,
+ ucp_Radical,
+ ucp_Regional_Indicator,
+ ucp_Sentence_Terminal,
+ ucp_Soft_Dotted,
+ ucp_Terminal_Punctuation,
+ ucp_Unified_Ideograph,
+ ucp_Uppercase,
+ ucp_Variation_Selector,
+ ucp_White_Space,
+ ucp_XID_Continue,
+ ucp_XID_Start,
+ /* This must be last */
+ ucp_Bprop_Count
+};
+
+/* Size of entries in ucd_boolprop_sets[] */
+
+#define ucd_boolprop_sets_item_size 2
+
+/* These are the bidi class values. */
+
+enum {
+ ucp_bidiAL, /* Arabic letter */
+ ucp_bidiAN, /* Arabic number */
+ ucp_bidiB, /* Paragraph separator */
+ ucp_bidiBN, /* Boundary neutral */
+ ucp_bidiCS, /* Common separator */
+ ucp_bidiEN, /* European number */
+ ucp_bidiES, /* European separator */
+ ucp_bidiET, /* European terminator */
+ ucp_bidiFSI, /* First strong isolate */
+ ucp_bidiL, /* Left to right */
+ ucp_bidiLRE, /* Left to right embedding */
+ ucp_bidiLRI, /* Left to right isolate */
+ ucp_bidiLRO, /* Left to right override */
+ ucp_bidiNSM, /* Non-spacing mark */
+ ucp_bidiON, /* Other neutral */
+ ucp_bidiPDF, /* Pop directional format */
+ ucp_bidiPDI, /* Pop directional isolate */
+ ucp_bidiR, /* Right to left */
+ ucp_bidiRLE, /* Right to left embedding */
+ ucp_bidiRLI, /* Right to left isolate */
+ ucp_bidiRLO, /* Right to left override */
+ ucp_bidiS, /* Segment separator */
+ ucp_bidiWS, /* White space */
};
/* These are grapheme break properties. The Extended Pictographic property
@@ -115,191 +206,189 @@ enum {
ucp_gbT, /* 8 Hangul syllable type T */
ucp_gbLV, /* 9 Hangul syllable type LV */
ucp_gbLVT, /* 10 Hangul syllable type LVT */
- ucp_gbRegionalIndicator, /* 11 */
+ ucp_gbRegional_Indicator, /* 11 */
ucp_gbOther, /* 12 */
ucp_gbZWJ, /* 13 */
- ucp_gbExtended_Pictographic /* 14 */
+ ucp_gbExtended_Pictographic, /* 14 */
};
/* These are the script identifications. */
enum {
- ucp_Unknown,
- ucp_Arabic,
- ucp_Armenian,
- ucp_Bengali,
- ucp_Bopomofo,
- ucp_Braille,
- ucp_Buginese,
- ucp_Buhid,
- ucp_Canadian_Aboriginal,
- ucp_Cherokee,
- ucp_Common,
- ucp_Coptic,
- ucp_Cypriot,
+ /* Scripts which has characters in other scripts. */
+ ucp_Latin,
+ ucp_Greek,
ucp_Cyrillic,
- ucp_Deseret,
+ ucp_Arabic,
+ ucp_Syriac,
+ ucp_Thaana,
ucp_Devanagari,
- ucp_Ethiopic,
- ucp_Georgian,
- ucp_Glagolitic,
- ucp_Gothic,
- ucp_Greek,
- ucp_Gujarati,
+ ucp_Bengali,
ucp_Gurmukhi,
- ucp_Han,
- ucp_Hangul,
- ucp_Hanunoo,
- ucp_Hebrew,
- ucp_Hiragana,
- ucp_Inherited,
+ ucp_Gujarati,
+ ucp_Oriya,
+ ucp_Tamil,
+ ucp_Telugu,
ucp_Kannada,
- ucp_Katakana,
- ucp_Kharoshthi,
- ucp_Khmer,
- ucp_Lao,
- ucp_Latin,
- ucp_Limbu,
- ucp_Linear_B,
ucp_Malayalam,
- ucp_Mongolian,
- ucp_Myanmar,
- ucp_New_Tai_Lue,
- ucp_Ogham,
- ucp_Old_Italic,
- ucp_Old_Persian,
- ucp_Oriya,
- ucp_Osmanya,
- ucp_Runic,
- ucp_Shavian,
ucp_Sinhala,
- ucp_Syloti_Nagri,
- ucp_Syriac,
+ ucp_Myanmar,
+ ucp_Georgian,
+ ucp_Hangul,
+ ucp_Mongolian,
+ ucp_Hiragana,
+ ucp_Katakana,
+ ucp_Bopomofo,
+ ucp_Han,
+ ucp_Yi,
ucp_Tagalog,
+ ucp_Hanunoo,
+ ucp_Buhid,
ucp_Tagbanwa,
+ ucp_Limbu,
ucp_Tai_Le,
- ucp_Tamil,
- ucp_Telugu,
- ucp_Thaana,
+ ucp_Linear_B,
+ ucp_Cypriot,
+ ucp_Buginese,
+ ucp_Coptic,
+ ucp_Glagolitic,
+ ucp_Syloti_Nagri,
+ ucp_Phags_Pa,
+ ucp_Nko,
+ ucp_Kayah_Li,
+ ucp_Javanese,
+ ucp_Kaithi,
+ ucp_Mandaic,
+ ucp_Chakma,
+ ucp_Sharada,
+ ucp_Takri,
+ ucp_Duployan,
+ ucp_Grantha,
+ ucp_Khojki,
+ ucp_Linear_A,
+ ucp_Mahajani,
+ ucp_Manichaean,
+ ucp_Modi,
+ ucp_Old_Permic,
+ ucp_Psalter_Pahlavi,
+ ucp_Khudawadi,
+ ucp_Tirhuta,
+ ucp_Multani,
+ ucp_Adlam,
+ ucp_Masaram_Gondi,
+ ucp_Dogra,
+ ucp_Gunjala_Gondi,
+ ucp_Hanifi_Rohingya,
+ ucp_Sogdian,
+ ucp_Nandinagari,
+ ucp_Yezidi,
+ ucp_Cypro_Minoan,
+ ucp_Old_Uyghur,
+
+ /* Scripts which has no characters in other scripts. */
+ ucp_Unknown,
+ ucp_Common,
+ ucp_Armenian,
+ ucp_Hebrew,
ucp_Thai,
+ ucp_Lao,
ucp_Tibetan,
- ucp_Tifinagh,
+ ucp_Ethiopic,
+ ucp_Cherokee,
+ ucp_Canadian_Aboriginal,
+ ucp_Ogham,
+ ucp_Runic,
+ ucp_Khmer,
+ ucp_Old_Italic,
+ ucp_Gothic,
+ ucp_Deseret,
+ ucp_Inherited,
ucp_Ugaritic,
- ucp_Yi,
- /* New for Unicode 5.0 */
+ ucp_Shavian,
+ ucp_Osmanya,
+ ucp_Braille,
+ ucp_New_Tai_Lue,
+ ucp_Tifinagh,
+ ucp_Old_Persian,
+ ucp_Kharoshthi,
ucp_Balinese,
ucp_Cuneiform,
- ucp_Nko,
- ucp_Phags_Pa,
ucp_Phoenician,
- /* New for Unicode 5.1 */
- ucp_Carian,
- ucp_Cham,
- ucp_Kayah_Li,
+ ucp_Sundanese,
ucp_Lepcha,
- ucp_Lycian,
- ucp_Lydian,
ucp_Ol_Chiki,
- ucp_Rejang,
- ucp_Saurashtra,
- ucp_Sundanese,
ucp_Vai,
- /* New for Unicode 5.2 */
+ ucp_Saurashtra,
+ ucp_Rejang,
+ ucp_Lycian,
+ ucp_Carian,
+ ucp_Lydian,
+ ucp_Cham,
+ ucp_Tai_Tham,
+ ucp_Tai_Viet,
ucp_Avestan,
- ucp_Bamum,
ucp_Egyptian_Hieroglyphs,
- ucp_Imperial_Aramaic,
- ucp_Inscriptional_Pahlavi,
- ucp_Inscriptional_Parthian,
- ucp_Javanese,
- ucp_Kaithi,
+ ucp_Samaritan,
ucp_Lisu,
+ ucp_Bamum,
ucp_Meetei_Mayek,
+ ucp_Imperial_Aramaic,
ucp_Old_South_Arabian,
+ ucp_Inscriptional_Parthian,
+ ucp_Inscriptional_Pahlavi,
ucp_Old_Turkic,
- ucp_Samaritan,
- ucp_Tai_Tham,
- ucp_Tai_Viet,
- /* New for Unicode 6.0.0 */
ucp_Batak,
ucp_Brahmi,
- ucp_Mandaic,
- /* New for Unicode 6.1.0 */
- ucp_Chakma,
ucp_Meroitic_Cursive,
ucp_Meroitic_Hieroglyphs,
ucp_Miao,
- ucp_Sharada,
ucp_Sora_Sompeng,
- ucp_Takri,
- /* New for Unicode 7.0.0 */
- ucp_Bassa_Vah,
ucp_Caucasian_Albanian,
- ucp_Duployan,
+ ucp_Bassa_Vah,
ucp_Elbasan,
- ucp_Grantha,
- ucp_Khojki,
- ucp_Khudawadi,
- ucp_Linear_A,
- ucp_Mahajani,
- ucp_Manichaean,
+ ucp_Pahawh_Hmong,
ucp_Mende_Kikakui,
- ucp_Modi,
ucp_Mro,
- ucp_Nabataean,
ucp_Old_North_Arabian,
- ucp_Old_Permic,
- ucp_Pahawh_Hmong,
+ ucp_Nabataean,
ucp_Palmyrene,
- ucp_Psalter_Pahlavi,
ucp_Pau_Cin_Hau,
ucp_Siddham,
- ucp_Tirhuta,
ucp_Warang_Citi,
- /* New for Unicode 8.0.0 */
ucp_Ahom,
ucp_Anatolian_Hieroglyphs,
ucp_Hatran,
- ucp_Multani,
ucp_Old_Hungarian,
ucp_SignWriting,
- /* New for Unicode 10.0.0 (no update since 8.0.0) */
- ucp_Adlam,
ucp_Bhaiksuki,
ucp_Marchen,
ucp_Newa,
ucp_Osage,
ucp_Tangut,
- ucp_Masaram_Gondi,
ucp_Nushu,
ucp_Soyombo,
ucp_Zanabazar_Square,
- /* New for Unicode 11.0.0 */
- ucp_Dogra,
- ucp_Gunjala_Gondi,
- ucp_Hanifi_Rohingya,
ucp_Makasar,
ucp_Medefaidrin,
ucp_Old_Sogdian,
- ucp_Sogdian,
- /* New for Unicode 12.0.0 */
ucp_Elymaic,
- ucp_Nandinagari,
ucp_Nyiakeng_Puachue_Hmong,
ucp_Wancho,
- /* New for Unicode 13.0.0 */
ucp_Chorasmian,
ucp_Dives_Akuru,
ucp_Khitan_Small_Script,
- ucp_Yezidi,
- /* New for Unicode 14.0.0 */
- ucp_Cypro_Minoan,
- ucp_Old_Uyghur,
ucp_Tangsa,
ucp_Toto,
- ucp_Vithkuqi
+ ucp_Vithkuqi,
+
+ /* This must be last */
+ ucp_Script_Count
};
+/* Size of entries in ucd_script_sets[] */
+
+#define ucd_script_sets_item_size 3
+
#endif /* PCRE2_UCP_H_IDEMPOTENT_GUARD */
/* End of pcre2_ucp.h */
diff --git a/thirdparty/pcre2/src/pcre2_ucptables.c b/thirdparty/pcre2/src/pcre2_ucptables.c
new file mode 100644
index 0000000000..bd1b67a9f1
--- /dev/null
+++ b/thirdparty/pcre2/src/pcre2_ucptables.c
@@ -0,0 +1,1524 @@
+/*************************************************
+* Perl-Compatible Regular Expressions *
+*************************************************/
+
+/* PCRE is a library of functions to support regular expressions whose syntax
+and semantics are as close as possible to those of the Perl 5 language.
+
+ Written by Philip Hazel
+ Original API code Copyright (c) 1997-2012 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
+
+This module is auto-generated from Unicode data files. DO NOT EDIT MANUALLY!
+Instead, modify the maint/GenerateUcpTables.py script and run it to generate
+a new version of this code.
+
+-----------------------------------------------------------------------------
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the University of Cambridge nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------------
+*/
+
+#ifdef SUPPORT_UNICODE
+
+/* The PRIV(utt)[] table below translates Unicode property names into type and
+code values. It is searched by binary chop, so must be in collating sequence of
+name. Originally, the table contained pointers to the name strings in the first
+field of each entry. However, that leads to a large number of relocations when
+a shared library is dynamically loaded. A significant reduction is made by
+putting all the names into a single, large string and using offsets instead.
+All letters are lower cased, and underscores are removed, in accordance with
+the "loose matching" rules that Unicode advises and Perl uses. */
+
+#define STRING_adlam0 STR_a STR_d STR_l STR_a STR_m "\0"
+#define STRING_adlm0 STR_a STR_d STR_l STR_m "\0"
+#define STRING_aghb0 STR_a STR_g STR_h STR_b "\0"
+#define STRING_ahex0 STR_a STR_h STR_e STR_x "\0"
+#define STRING_ahom0 STR_a STR_h STR_o STR_m "\0"
+#define STRING_alpha0 STR_a STR_l STR_p STR_h STR_a "\0"
+#define STRING_alphabetic0 STR_a STR_l STR_p STR_h STR_a STR_b STR_e STR_t STR_i STR_c "\0"
+#define STRING_anatolianhieroglyphs0 STR_a STR_n STR_a STR_t STR_o STR_l STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
+#define STRING_any0 STR_a STR_n STR_y "\0"
+#define STRING_arab0 STR_a STR_r STR_a STR_b "\0"
+#define STRING_arabic0 STR_a STR_r STR_a STR_b STR_i STR_c "\0"
+#define STRING_armenian0 STR_a STR_r STR_m STR_e STR_n STR_i STR_a STR_n "\0"
+#define STRING_armi0 STR_a STR_r STR_m STR_i "\0"
+#define STRING_armn0 STR_a STR_r STR_m STR_n "\0"
+#define STRING_ascii0 STR_a STR_s STR_c STR_i STR_i "\0"
+#define STRING_asciihexdigit0 STR_a STR_s STR_c STR_i STR_i STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"
+#define STRING_avestan0 STR_a STR_v STR_e STR_s STR_t STR_a STR_n "\0"
+#define STRING_avst0 STR_a STR_v STR_s STR_t "\0"
+#define STRING_bali0 STR_b STR_a STR_l STR_i "\0"
+#define STRING_balinese0 STR_b STR_a STR_l STR_i STR_n STR_e STR_s STR_e "\0"
+#define STRING_bamu0 STR_b STR_a STR_m STR_u "\0"
+#define STRING_bamum0 STR_b STR_a STR_m STR_u STR_m "\0"
+#define STRING_bass0 STR_b STR_a STR_s STR_s "\0"
+#define STRING_bassavah0 STR_b STR_a STR_s STR_s STR_a STR_v STR_a STR_h "\0"
+#define STRING_batak0 STR_b STR_a STR_t STR_a STR_k "\0"
+#define STRING_batk0 STR_b STR_a STR_t STR_k "\0"
+#define STRING_beng0 STR_b STR_e STR_n STR_g "\0"
+#define STRING_bengali0 STR_b STR_e STR_n STR_g STR_a STR_l STR_i "\0"
+#define STRING_bhaiksuki0 STR_b STR_h STR_a STR_i STR_k STR_s STR_u STR_k STR_i "\0"
+#define STRING_bhks0 STR_b STR_h STR_k STR_s "\0"
+#define STRING_bidial0 STR_b STR_i STR_d STR_i STR_a STR_l "\0"
+#define STRING_bidian0 STR_b STR_i STR_d STR_i STR_a STR_n "\0"
+#define STRING_bidib0 STR_b STR_i STR_d STR_i STR_b "\0"
+#define STRING_bidibn0 STR_b STR_i STR_d STR_i STR_b STR_n "\0"
+#define STRING_bidic0 STR_b STR_i STR_d STR_i STR_c "\0"
+#define STRING_bidicontrol0 STR_b STR_i STR_d STR_i STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"
+#define STRING_bidics0 STR_b STR_i STR_d STR_i STR_c STR_s "\0"
+#define STRING_bidien0 STR_b STR_i STR_d STR_i STR_e STR_n "\0"
+#define STRING_bidies0 STR_b STR_i STR_d STR_i STR_e STR_s "\0"
+#define STRING_bidiet0 STR_b STR_i STR_d STR_i STR_e STR_t "\0"
+#define STRING_bidifsi0 STR_b STR_i STR_d STR_i STR_f STR_s STR_i "\0"
+#define STRING_bidil0 STR_b STR_i STR_d STR_i STR_l "\0"
+#define STRING_bidilre0 STR_b STR_i STR_d STR_i STR_l STR_r STR_e "\0"
+#define STRING_bidilri0 STR_b STR_i STR_d STR_i STR_l STR_r STR_i "\0"
+#define STRING_bidilro0 STR_b STR_i STR_d STR_i STR_l STR_r STR_o "\0"
+#define STRING_bidim0 STR_b STR_i STR_d STR_i STR_m "\0"
+#define STRING_bidimirrored0 STR_b STR_i STR_d STR_i STR_m STR_i STR_r STR_r STR_o STR_r STR_e STR_d "\0"
+#define STRING_bidinsm0 STR_b STR_i STR_d STR_i STR_n STR_s STR_m "\0"
+#define STRING_bidion0 STR_b STR_i STR_d STR_i STR_o STR_n "\0"
+#define STRING_bidipdf0 STR_b STR_i STR_d STR_i STR_p STR_d STR_f "\0"
+#define STRING_bidipdi0 STR_b STR_i STR_d STR_i STR_p STR_d STR_i "\0"
+#define STRING_bidir0 STR_b STR_i STR_d STR_i STR_r "\0"
+#define STRING_bidirle0 STR_b STR_i STR_d STR_i STR_r STR_l STR_e "\0"
+#define STRING_bidirli0 STR_b STR_i STR_d STR_i STR_r STR_l STR_i "\0"
+#define STRING_bidirlo0 STR_b STR_i STR_d STR_i STR_r STR_l STR_o "\0"
+#define STRING_bidis0 STR_b STR_i STR_d STR_i STR_s "\0"
+#define STRING_bidiws0 STR_b STR_i STR_d STR_i STR_w STR_s "\0"
+#define STRING_bopo0 STR_b STR_o STR_p STR_o "\0"
+#define STRING_bopomofo0 STR_b STR_o STR_p STR_o STR_m STR_o STR_f STR_o "\0"
+#define STRING_brah0 STR_b STR_r STR_a STR_h "\0"
+#define STRING_brahmi0 STR_b STR_r STR_a STR_h STR_m STR_i "\0"
+#define STRING_brai0 STR_b STR_r STR_a STR_i "\0"
+#define STRING_braille0 STR_b STR_r STR_a STR_i STR_l STR_l STR_e "\0"
+#define STRING_bugi0 STR_b STR_u STR_g STR_i "\0"
+#define STRING_buginese0 STR_b STR_u STR_g STR_i STR_n STR_e STR_s STR_e "\0"
+#define STRING_buhd0 STR_b STR_u STR_h STR_d "\0"
+#define STRING_buhid0 STR_b STR_u STR_h STR_i STR_d "\0"
+#define STRING_c0 STR_c "\0"
+#define STRING_cakm0 STR_c STR_a STR_k STR_m "\0"
+#define STRING_canadianaboriginal0 STR_c STR_a STR_n STR_a STR_d STR_i STR_a STR_n STR_a STR_b STR_o STR_r STR_i STR_g STR_i STR_n STR_a STR_l "\0"
+#define STRING_cans0 STR_c STR_a STR_n STR_s "\0"
+#define STRING_cari0 STR_c STR_a STR_r STR_i "\0"
+#define STRING_carian0 STR_c STR_a STR_r STR_i STR_a STR_n "\0"
+#define STRING_cased0 STR_c STR_a STR_s STR_e STR_d "\0"
+#define STRING_caseignorable0 STR_c STR_a STR_s STR_e STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e "\0"
+#define STRING_caucasianalbanian0 STR_c STR_a STR_u STR_c STR_a STR_s STR_i STR_a STR_n STR_a STR_l STR_b STR_a STR_n STR_i STR_a STR_n "\0"
+#define STRING_cc0 STR_c STR_c "\0"
+#define STRING_cf0 STR_c STR_f "\0"
+#define STRING_chakma0 STR_c STR_h STR_a STR_k STR_m STR_a "\0"
+#define STRING_cham0 STR_c STR_h STR_a STR_m "\0"
+#define STRING_changeswhencasefolded0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_f STR_o STR_l STR_d STR_e STR_d "\0"
+#define STRING_changeswhencasemapped0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_c STR_a STR_s STR_e STR_m STR_a STR_p STR_p STR_e STR_d "\0"
+#define STRING_changeswhenlowercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"
+#define STRING_changeswhentitlecased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_t STR_i STR_t STR_l STR_e STR_c STR_a STR_s STR_e STR_d "\0"
+#define STRING_changeswhenuppercased0 STR_c STR_h STR_a STR_n STR_g STR_e STR_s STR_w STR_h STR_e STR_n STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e STR_d "\0"
+#define STRING_cher0 STR_c STR_h STR_e STR_r "\0"
+#define STRING_cherokee0 STR_c STR_h STR_e STR_r STR_o STR_k STR_e STR_e "\0"
+#define STRING_chorasmian0 STR_c STR_h STR_o STR_r STR_a STR_s STR_m STR_i STR_a STR_n "\0"
+#define STRING_chrs0 STR_c STR_h STR_r STR_s "\0"
+#define STRING_ci0 STR_c STR_i "\0"
+#define STRING_cn0 STR_c STR_n "\0"
+#define STRING_co0 STR_c STR_o "\0"
+#define STRING_common0 STR_c STR_o STR_m STR_m STR_o STR_n "\0"
+#define STRING_copt0 STR_c STR_o STR_p STR_t "\0"
+#define STRING_coptic0 STR_c STR_o STR_p STR_t STR_i STR_c "\0"
+#define STRING_cpmn0 STR_c STR_p STR_m STR_n "\0"
+#define STRING_cprt0 STR_c STR_p STR_r STR_t "\0"
+#define STRING_cs0 STR_c STR_s "\0"
+#define STRING_cuneiform0 STR_c STR_u STR_n STR_e STR_i STR_f STR_o STR_r STR_m "\0"
+#define STRING_cwcf0 STR_c STR_w STR_c STR_f "\0"
+#define STRING_cwcm0 STR_c STR_w STR_c STR_m "\0"
+#define STRING_cwl0 STR_c STR_w STR_l "\0"
+#define STRING_cwt0 STR_c STR_w STR_t "\0"
+#define STRING_cwu0 STR_c STR_w STR_u "\0"
+#define STRING_cypriot0 STR_c STR_y STR_p STR_r STR_i STR_o STR_t "\0"
+#define STRING_cyprominoan0 STR_c STR_y STR_p STR_r STR_o STR_m STR_i STR_n STR_o STR_a STR_n "\0"
+#define STRING_cyrillic0 STR_c STR_y STR_r STR_i STR_l STR_l STR_i STR_c "\0"
+#define STRING_cyrl0 STR_c STR_y STR_r STR_l "\0"
+#define STRING_dash0 STR_d STR_a STR_s STR_h "\0"
+#define STRING_defaultignorablecodepoint0 STR_d STR_e STR_f STR_a STR_u STR_l STR_t STR_i STR_g STR_n STR_o STR_r STR_a STR_b STR_l STR_e STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"
+#define STRING_dep0 STR_d STR_e STR_p "\0"
+#define STRING_deprecated0 STR_d STR_e STR_p STR_r STR_e STR_c STR_a STR_t STR_e STR_d "\0"
+#define STRING_deseret0 STR_d STR_e STR_s STR_e STR_r STR_e STR_t "\0"
+#define STRING_deva0 STR_d STR_e STR_v STR_a "\0"
+#define STRING_devanagari0 STR_d STR_e STR_v STR_a STR_n STR_a STR_g STR_a STR_r STR_i "\0"
+#define STRING_di0 STR_d STR_i "\0"
+#define STRING_dia0 STR_d STR_i STR_a "\0"
+#define STRING_diacritic0 STR_d STR_i STR_a STR_c STR_r STR_i STR_t STR_i STR_c "\0"
+#define STRING_diak0 STR_d STR_i STR_a STR_k "\0"
+#define STRING_divesakuru0 STR_d STR_i STR_v STR_e STR_s STR_a STR_k STR_u STR_r STR_u "\0"
+#define STRING_dogr0 STR_d STR_o STR_g STR_r "\0"
+#define STRING_dogra0 STR_d STR_o STR_g STR_r STR_a "\0"
+#define STRING_dsrt0 STR_d STR_s STR_r STR_t "\0"
+#define STRING_dupl0 STR_d STR_u STR_p STR_l "\0"
+#define STRING_duployan0 STR_d STR_u STR_p STR_l STR_o STR_y STR_a STR_n "\0"
+#define STRING_ebase0 STR_e STR_b STR_a STR_s STR_e "\0"
+#define STRING_ecomp0 STR_e STR_c STR_o STR_m STR_p "\0"
+#define STRING_egyp0 STR_e STR_g STR_y STR_p "\0"
+#define STRING_egyptianhieroglyphs0 STR_e STR_g STR_y STR_p STR_t STR_i STR_a STR_n STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
+#define STRING_elba0 STR_e STR_l STR_b STR_a "\0"
+#define STRING_elbasan0 STR_e STR_l STR_b STR_a STR_s STR_a STR_n "\0"
+#define STRING_elym0 STR_e STR_l STR_y STR_m "\0"
+#define STRING_elymaic0 STR_e STR_l STR_y STR_m STR_a STR_i STR_c "\0"
+#define STRING_emod0 STR_e STR_m STR_o STR_d "\0"
+#define STRING_emoji0 STR_e STR_m STR_o STR_j STR_i "\0"
+#define STRING_emojicomponent0 STR_e STR_m STR_o STR_j STR_i STR_c STR_o STR_m STR_p STR_o STR_n STR_e STR_n STR_t "\0"
+#define STRING_emojimodifier0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r "\0"
+#define STRING_emojimodifierbase0 STR_e STR_m STR_o STR_j STR_i STR_m STR_o STR_d STR_i STR_f STR_i STR_e STR_r STR_b STR_a STR_s STR_e "\0"
+#define STRING_emojipresentation0 STR_e STR_m STR_o STR_j STR_i STR_p STR_r STR_e STR_s STR_e STR_n STR_t STR_a STR_t STR_i STR_o STR_n "\0"
+#define STRING_epres0 STR_e STR_p STR_r STR_e STR_s "\0"
+#define STRING_ethi0 STR_e STR_t STR_h STR_i "\0"
+#define STRING_ethiopic0 STR_e STR_t STR_h STR_i STR_o STR_p STR_i STR_c "\0"
+#define STRING_ext0 STR_e STR_x STR_t "\0"
+#define STRING_extendedpictographic0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_d STR_p STR_i STR_c STR_t STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"
+#define STRING_extender0 STR_e STR_x STR_t STR_e STR_n STR_d STR_e STR_r "\0"
+#define STRING_extpict0 STR_e STR_x STR_t STR_p STR_i STR_c STR_t "\0"
+#define STRING_geor0 STR_g STR_e STR_o STR_r "\0"
+#define STRING_georgian0 STR_g STR_e STR_o STR_r STR_g STR_i STR_a STR_n "\0"
+#define STRING_glag0 STR_g STR_l STR_a STR_g "\0"
+#define STRING_glagolitic0 STR_g STR_l STR_a STR_g STR_o STR_l STR_i STR_t STR_i STR_c "\0"
+#define STRING_gong0 STR_g STR_o STR_n STR_g "\0"
+#define STRING_gonm0 STR_g STR_o STR_n STR_m "\0"
+#define STRING_goth0 STR_g STR_o STR_t STR_h "\0"
+#define STRING_gothic0 STR_g STR_o STR_t STR_h STR_i STR_c "\0"
+#define STRING_gran0 STR_g STR_r STR_a STR_n "\0"
+#define STRING_grantha0 STR_g STR_r STR_a STR_n STR_t STR_h STR_a "\0"
+#define STRING_graphemebase0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_b STR_a STR_s STR_e "\0"
+#define STRING_graphemeextend0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_e STR_x STR_t STR_e STR_n STR_d "\0"
+#define STRING_graphemelink0 STR_g STR_r STR_a STR_p STR_h STR_e STR_m STR_e STR_l STR_i STR_n STR_k "\0"
+#define STRING_grbase0 STR_g STR_r STR_b STR_a STR_s STR_e "\0"
+#define STRING_greek0 STR_g STR_r STR_e STR_e STR_k "\0"
+#define STRING_grek0 STR_g STR_r STR_e STR_k "\0"
+#define STRING_grext0 STR_g STR_r STR_e STR_x STR_t "\0"
+#define STRING_grlink0 STR_g STR_r STR_l STR_i STR_n STR_k "\0"
+#define STRING_gujarati0 STR_g STR_u STR_j STR_a STR_r STR_a STR_t STR_i "\0"
+#define STRING_gujr0 STR_g STR_u STR_j STR_r "\0"
+#define STRING_gunjalagondi0 STR_g STR_u STR_n STR_j STR_a STR_l STR_a STR_g STR_o STR_n STR_d STR_i "\0"
+#define STRING_gurmukhi0 STR_g STR_u STR_r STR_m STR_u STR_k STR_h STR_i "\0"
+#define STRING_guru0 STR_g STR_u STR_r STR_u "\0"
+#define STRING_han0 STR_h STR_a STR_n "\0"
+#define STRING_hang0 STR_h STR_a STR_n STR_g "\0"
+#define STRING_hangul0 STR_h STR_a STR_n STR_g STR_u STR_l "\0"
+#define STRING_hani0 STR_h STR_a STR_n STR_i "\0"
+#define STRING_hanifirohingya0 STR_h STR_a STR_n STR_i STR_f STR_i STR_r STR_o STR_h STR_i STR_n STR_g STR_y STR_a "\0"
+#define STRING_hano0 STR_h STR_a STR_n STR_o "\0"
+#define STRING_hanunoo0 STR_h STR_a STR_n STR_u STR_n STR_o STR_o "\0"
+#define STRING_hatr0 STR_h STR_a STR_t STR_r "\0"
+#define STRING_hatran0 STR_h STR_a STR_t STR_r STR_a STR_n "\0"
+#define STRING_hebr0 STR_h STR_e STR_b STR_r "\0"
+#define STRING_hebrew0 STR_h STR_e STR_b STR_r STR_e STR_w "\0"
+#define STRING_hex0 STR_h STR_e STR_x "\0"
+#define STRING_hexdigit0 STR_h STR_e STR_x STR_d STR_i STR_g STR_i STR_t "\0"
+#define STRING_hira0 STR_h STR_i STR_r STR_a "\0"
+#define STRING_hiragana0 STR_h STR_i STR_r STR_a STR_g STR_a STR_n STR_a "\0"
+#define STRING_hluw0 STR_h STR_l STR_u STR_w "\0"
+#define STRING_hmng0 STR_h STR_m STR_n STR_g "\0"
+#define STRING_hmnp0 STR_h STR_m STR_n STR_p "\0"
+#define STRING_hung0 STR_h STR_u STR_n STR_g "\0"
+#define STRING_idc0 STR_i STR_d STR_c "\0"
+#define STRING_idcontinue0 STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"
+#define STRING_ideo0 STR_i STR_d STR_e STR_o "\0"
+#define STRING_ideographic0 STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h STR_i STR_c "\0"
+#define STRING_ids0 STR_i STR_d STR_s "\0"
+#define STRING_idsb0 STR_i STR_d STR_s STR_b "\0"
+#define STRING_idsbinaryoperator0 STR_i STR_d STR_s STR_b STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"
+#define STRING_idst0 STR_i STR_d STR_s STR_t "\0"
+#define STRING_idstart0 STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"
+#define STRING_idstrinaryoperator0 STR_i STR_d STR_s STR_t STR_r STR_i STR_n STR_a STR_r STR_y STR_o STR_p STR_e STR_r STR_a STR_t STR_o STR_r "\0"
+#define STRING_imperialaramaic0 STR_i STR_m STR_p STR_e STR_r STR_i STR_a STR_l STR_a STR_r STR_a STR_m STR_a STR_i STR_c "\0"
+#define STRING_inherited0 STR_i STR_n STR_h STR_e STR_r STR_i STR_t STR_e STR_d "\0"
+#define STRING_inscriptionalpahlavi0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"
+#define STRING_inscriptionalparthian0 STR_i STR_n STR_s STR_c STR_r STR_i STR_p STR_t STR_i STR_o STR_n STR_a STR_l STR_p STR_a STR_r STR_t STR_h STR_i STR_a STR_n "\0"
+#define STRING_ital0 STR_i STR_t STR_a STR_l "\0"
+#define STRING_java0 STR_j STR_a STR_v STR_a "\0"
+#define STRING_javanese0 STR_j STR_a STR_v STR_a STR_n STR_e STR_s STR_e "\0"
+#define STRING_joinc0 STR_j STR_o STR_i STR_n STR_c "\0"
+#define STRING_joincontrol0 STR_j STR_o STR_i STR_n STR_c STR_o STR_n STR_t STR_r STR_o STR_l "\0"
+#define STRING_kaithi0 STR_k STR_a STR_i STR_t STR_h STR_i "\0"
+#define STRING_kali0 STR_k STR_a STR_l STR_i "\0"
+#define STRING_kana0 STR_k STR_a STR_n STR_a "\0"
+#define STRING_kannada0 STR_k STR_a STR_n STR_n STR_a STR_d STR_a "\0"
+#define STRING_katakana0 STR_k STR_a STR_t STR_a STR_k STR_a STR_n STR_a "\0"
+#define STRING_kayahli0 STR_k STR_a STR_y STR_a STR_h STR_l STR_i "\0"
+#define STRING_khar0 STR_k STR_h STR_a STR_r "\0"
+#define STRING_kharoshthi0 STR_k STR_h STR_a STR_r STR_o STR_s STR_h STR_t STR_h STR_i "\0"
+#define STRING_khitansmallscript0 STR_k STR_h STR_i STR_t STR_a STR_n STR_s STR_m STR_a STR_l STR_l STR_s STR_c STR_r STR_i STR_p STR_t "\0"
+#define STRING_khmer0 STR_k STR_h STR_m STR_e STR_r "\0"
+#define STRING_khmr0 STR_k STR_h STR_m STR_r "\0"
+#define STRING_khoj0 STR_k STR_h STR_o STR_j "\0"
+#define STRING_khojki0 STR_k STR_h STR_o STR_j STR_k STR_i "\0"
+#define STRING_khudawadi0 STR_k STR_h STR_u STR_d STR_a STR_w STR_a STR_d STR_i "\0"
+#define STRING_kits0 STR_k STR_i STR_t STR_s "\0"
+#define STRING_knda0 STR_k STR_n STR_d STR_a "\0"
+#define STRING_kthi0 STR_k STR_t STR_h STR_i "\0"
+#define STRING_l0 STR_l "\0"
+#define STRING_l_AMPERSAND0 STR_l STR_AMPERSAND "\0"
+#define STRING_lana0 STR_l STR_a STR_n STR_a "\0"
+#define STRING_lao0 STR_l STR_a STR_o "\0"
+#define STRING_laoo0 STR_l STR_a STR_o STR_o "\0"
+#define STRING_latin0 STR_l STR_a STR_t STR_i STR_n "\0"
+#define STRING_latn0 STR_l STR_a STR_t STR_n "\0"
+#define STRING_lc0 STR_l STR_c "\0"
+#define STRING_lepc0 STR_l STR_e STR_p STR_c "\0"
+#define STRING_lepcha0 STR_l STR_e STR_p STR_c STR_h STR_a "\0"
+#define STRING_limb0 STR_l STR_i STR_m STR_b "\0"
+#define STRING_limbu0 STR_l STR_i STR_m STR_b STR_u "\0"
+#define STRING_lina0 STR_l STR_i STR_n STR_a "\0"
+#define STRING_linb0 STR_l STR_i STR_n STR_b "\0"
+#define STRING_lineara0 STR_l STR_i STR_n STR_e STR_a STR_r STR_a "\0"
+#define STRING_linearb0 STR_l STR_i STR_n STR_e STR_a STR_r STR_b "\0"
+#define STRING_lisu0 STR_l STR_i STR_s STR_u "\0"
+#define STRING_ll0 STR_l STR_l "\0"
+#define STRING_lm0 STR_l STR_m "\0"
+#define STRING_lo0 STR_l STR_o "\0"
+#define STRING_loe0 STR_l STR_o STR_e "\0"
+#define STRING_logicalorderexception0 STR_l STR_o STR_g STR_i STR_c STR_a STR_l STR_o STR_r STR_d STR_e STR_r STR_e STR_x STR_c STR_e STR_p STR_t STR_i STR_o STR_n "\0"
+#define STRING_lower0 STR_l STR_o STR_w STR_e STR_r "\0"
+#define STRING_lowercase0 STR_l STR_o STR_w STR_e STR_r STR_c STR_a STR_s STR_e "\0"
+#define STRING_lt0 STR_l STR_t "\0"
+#define STRING_lu0 STR_l STR_u "\0"
+#define STRING_lyci0 STR_l STR_y STR_c STR_i "\0"
+#define STRING_lycian0 STR_l STR_y STR_c STR_i STR_a STR_n "\0"
+#define STRING_lydi0 STR_l STR_y STR_d STR_i "\0"
+#define STRING_lydian0 STR_l STR_y STR_d STR_i STR_a STR_n "\0"
+#define STRING_m0 STR_m "\0"
+#define STRING_mahajani0 STR_m STR_a STR_h STR_a STR_j STR_a STR_n STR_i "\0"
+#define STRING_mahj0 STR_m STR_a STR_h STR_j "\0"
+#define STRING_maka0 STR_m STR_a STR_k STR_a "\0"
+#define STRING_makasar0 STR_m STR_a STR_k STR_a STR_s STR_a STR_r "\0"
+#define STRING_malayalam0 STR_m STR_a STR_l STR_a STR_y STR_a STR_l STR_a STR_m "\0"
+#define STRING_mand0 STR_m STR_a STR_n STR_d "\0"
+#define STRING_mandaic0 STR_m STR_a STR_n STR_d STR_a STR_i STR_c "\0"
+#define STRING_mani0 STR_m STR_a STR_n STR_i "\0"
+#define STRING_manichaean0 STR_m STR_a STR_n STR_i STR_c STR_h STR_a STR_e STR_a STR_n "\0"
+#define STRING_marc0 STR_m STR_a STR_r STR_c "\0"
+#define STRING_marchen0 STR_m STR_a STR_r STR_c STR_h STR_e STR_n "\0"
+#define STRING_masaramgondi0 STR_m STR_a STR_s STR_a STR_r STR_a STR_m STR_g STR_o STR_n STR_d STR_i "\0"
+#define STRING_math0 STR_m STR_a STR_t STR_h "\0"
+#define STRING_mc0 STR_m STR_c "\0"
+#define STRING_me0 STR_m STR_e "\0"
+#define STRING_medefaidrin0 STR_m STR_e STR_d STR_e STR_f STR_a STR_i STR_d STR_r STR_i STR_n "\0"
+#define STRING_medf0 STR_m STR_e STR_d STR_f "\0"
+#define STRING_meeteimayek0 STR_m STR_e STR_e STR_t STR_e STR_i STR_m STR_a STR_y STR_e STR_k "\0"
+#define STRING_mend0 STR_m STR_e STR_n STR_d "\0"
+#define STRING_mendekikakui0 STR_m STR_e STR_n STR_d STR_e STR_k STR_i STR_k STR_a STR_k STR_u STR_i "\0"
+#define STRING_merc0 STR_m STR_e STR_r STR_c "\0"
+#define STRING_mero0 STR_m STR_e STR_r STR_o "\0"
+#define STRING_meroiticcursive0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_c STR_u STR_r STR_s STR_i STR_v STR_e "\0"
+#define STRING_meroitichieroglyphs0 STR_m STR_e STR_r STR_o STR_i STR_t STR_i STR_c STR_h STR_i STR_e STR_r STR_o STR_g STR_l STR_y STR_p STR_h STR_s "\0"
+#define STRING_miao0 STR_m STR_i STR_a STR_o "\0"
+#define STRING_mlym0 STR_m STR_l STR_y STR_m "\0"
+#define STRING_mn0 STR_m STR_n "\0"
+#define STRING_modi0 STR_m STR_o STR_d STR_i "\0"
+#define STRING_mong0 STR_m STR_o STR_n STR_g "\0"
+#define STRING_mongolian0 STR_m STR_o STR_n STR_g STR_o STR_l STR_i STR_a STR_n "\0"
+#define STRING_mro0 STR_m STR_r STR_o "\0"
+#define STRING_mroo0 STR_m STR_r STR_o STR_o "\0"
+#define STRING_mtei0 STR_m STR_t STR_e STR_i "\0"
+#define STRING_mult0 STR_m STR_u STR_l STR_t "\0"
+#define STRING_multani0 STR_m STR_u STR_l STR_t STR_a STR_n STR_i "\0"
+#define STRING_myanmar0 STR_m STR_y STR_a STR_n STR_m STR_a STR_r "\0"
+#define STRING_mymr0 STR_m STR_y STR_m STR_r "\0"
+#define STRING_n0 STR_n "\0"
+#define STRING_nabataean0 STR_n STR_a STR_b STR_a STR_t STR_a STR_e STR_a STR_n "\0"
+#define STRING_nand0 STR_n STR_a STR_n STR_d "\0"
+#define STRING_nandinagari0 STR_n STR_a STR_n STR_d STR_i STR_n STR_a STR_g STR_a STR_r STR_i "\0"
+#define STRING_narb0 STR_n STR_a STR_r STR_b "\0"
+#define STRING_nbat0 STR_n STR_b STR_a STR_t "\0"
+#define STRING_nchar0 STR_n STR_c STR_h STR_a STR_r "\0"
+#define STRING_nd0 STR_n STR_d "\0"
+#define STRING_newa0 STR_n STR_e STR_w STR_a "\0"
+#define STRING_newtailue0 STR_n STR_e STR_w STR_t STR_a STR_i STR_l STR_u STR_e "\0"
+#define STRING_nko0 STR_n STR_k STR_o "\0"
+#define STRING_nkoo0 STR_n STR_k STR_o STR_o "\0"
+#define STRING_nl0 STR_n STR_l "\0"
+#define STRING_no0 STR_n STR_o "\0"
+#define STRING_noncharactercodepoint0 STR_n STR_o STR_n STR_c STR_h STR_a STR_r STR_a STR_c STR_t STR_e STR_r STR_c STR_o STR_d STR_e STR_p STR_o STR_i STR_n STR_t "\0"
+#define STRING_nshu0 STR_n STR_s STR_h STR_u "\0"
+#define STRING_nushu0 STR_n STR_u STR_s STR_h STR_u "\0"
+#define STRING_nyiakengpuachuehmong0 STR_n STR_y STR_i STR_a STR_k STR_e STR_n STR_g STR_p STR_u STR_a STR_c STR_h STR_u STR_e STR_h STR_m STR_o STR_n STR_g "\0"
+#define STRING_ogam0 STR_o STR_g STR_a STR_m "\0"
+#define STRING_ogham0 STR_o STR_g STR_h STR_a STR_m "\0"
+#define STRING_olchiki0 STR_o STR_l STR_c STR_h STR_i STR_k STR_i "\0"
+#define STRING_olck0 STR_o STR_l STR_c STR_k "\0"
+#define STRING_oldhungarian0 STR_o STR_l STR_d STR_h STR_u STR_n STR_g STR_a STR_r STR_i STR_a STR_n "\0"
+#define STRING_olditalic0 STR_o STR_l STR_d STR_i STR_t STR_a STR_l STR_i STR_c "\0"
+#define STRING_oldnortharabian0 STR_o STR_l STR_d STR_n STR_o STR_r STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"
+#define STRING_oldpermic0 STR_o STR_l STR_d STR_p STR_e STR_r STR_m STR_i STR_c "\0"
+#define STRING_oldpersian0 STR_o STR_l STR_d STR_p STR_e STR_r STR_s STR_i STR_a STR_n "\0"
+#define STRING_oldsogdian0 STR_o STR_l STR_d STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"
+#define STRING_oldsoutharabian0 STR_o STR_l STR_d STR_s STR_o STR_u STR_t STR_h STR_a STR_r STR_a STR_b STR_i STR_a STR_n "\0"
+#define STRING_oldturkic0 STR_o STR_l STR_d STR_t STR_u STR_r STR_k STR_i STR_c "\0"
+#define STRING_olduyghur0 STR_o STR_l STR_d STR_u STR_y STR_g STR_h STR_u STR_r "\0"
+#define STRING_oriya0 STR_o STR_r STR_i STR_y STR_a "\0"
+#define STRING_orkh0 STR_o STR_r STR_k STR_h "\0"
+#define STRING_orya0 STR_o STR_r STR_y STR_a "\0"
+#define STRING_osage0 STR_o STR_s STR_a STR_g STR_e "\0"
+#define STRING_osge0 STR_o STR_s STR_g STR_e "\0"
+#define STRING_osma0 STR_o STR_s STR_m STR_a "\0"
+#define STRING_osmanya0 STR_o STR_s STR_m STR_a STR_n STR_y STR_a "\0"
+#define STRING_ougr0 STR_o STR_u STR_g STR_r "\0"
+#define STRING_p0 STR_p "\0"
+#define STRING_pahawhhmong0 STR_p STR_a STR_h STR_a STR_w STR_h STR_h STR_m STR_o STR_n STR_g "\0"
+#define STRING_palm0 STR_p STR_a STR_l STR_m "\0"
+#define STRING_palmyrene0 STR_p STR_a STR_l STR_m STR_y STR_r STR_e STR_n STR_e "\0"
+#define STRING_patsyn0 STR_p STR_a STR_t STR_s STR_y STR_n "\0"
+#define STRING_patternsyntax0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_s STR_y STR_n STR_t STR_a STR_x "\0"
+#define STRING_patternwhitespace0 STR_p STR_a STR_t STR_t STR_e STR_r STR_n STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"
+#define STRING_patws0 STR_p STR_a STR_t STR_w STR_s "\0"
+#define STRING_pauc0 STR_p STR_a STR_u STR_c "\0"
+#define STRING_paucinhau0 STR_p STR_a STR_u STR_c STR_i STR_n STR_h STR_a STR_u "\0"
+#define STRING_pc0 STR_p STR_c "\0"
+#define STRING_pcm0 STR_p STR_c STR_m "\0"
+#define STRING_pd0 STR_p STR_d "\0"
+#define STRING_pe0 STR_p STR_e "\0"
+#define STRING_perm0 STR_p STR_e STR_r STR_m "\0"
+#define STRING_pf0 STR_p STR_f "\0"
+#define STRING_phag0 STR_p STR_h STR_a STR_g "\0"
+#define STRING_phagspa0 STR_p STR_h STR_a STR_g STR_s STR_p STR_a "\0"
+#define STRING_phli0 STR_p STR_h STR_l STR_i "\0"
+#define STRING_phlp0 STR_p STR_h STR_l STR_p "\0"
+#define STRING_phnx0 STR_p STR_h STR_n STR_x "\0"
+#define STRING_phoenician0 STR_p STR_h STR_o STR_e STR_n STR_i STR_c STR_i STR_a STR_n "\0"
+#define STRING_pi0 STR_p STR_i "\0"
+#define STRING_plrd0 STR_p STR_l STR_r STR_d "\0"
+#define STRING_po0 STR_p STR_o "\0"
+#define STRING_prependedconcatenationmark0 STR_p STR_r STR_e STR_p STR_e STR_n STR_d STR_e STR_d STR_c STR_o STR_n STR_c STR_a STR_t STR_e STR_n STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"
+#define STRING_prti0 STR_p STR_r STR_t STR_i "\0"
+#define STRING_ps0 STR_p STR_s "\0"
+#define STRING_psalterpahlavi0 STR_p STR_s STR_a STR_l STR_t STR_e STR_r STR_p STR_a STR_h STR_l STR_a STR_v STR_i "\0"
+#define STRING_qaac0 STR_q STR_a STR_a STR_c "\0"
+#define STRING_qaai0 STR_q STR_a STR_a STR_i "\0"
+#define STRING_qmark0 STR_q STR_m STR_a STR_r STR_k "\0"
+#define STRING_quotationmark0 STR_q STR_u STR_o STR_t STR_a STR_t STR_i STR_o STR_n STR_m STR_a STR_r STR_k "\0"
+#define STRING_radical0 STR_r STR_a STR_d STR_i STR_c STR_a STR_l "\0"
+#define STRING_regionalindicator0 STR_r STR_e STR_g STR_i STR_o STR_n STR_a STR_l STR_i STR_n STR_d STR_i STR_c STR_a STR_t STR_o STR_r "\0"
+#define STRING_rejang0 STR_r STR_e STR_j STR_a STR_n STR_g "\0"
+#define STRING_ri0 STR_r STR_i "\0"
+#define STRING_rjng0 STR_r STR_j STR_n STR_g "\0"
+#define STRING_rohg0 STR_r STR_o STR_h STR_g "\0"
+#define STRING_runic0 STR_r STR_u STR_n STR_i STR_c "\0"
+#define STRING_runr0 STR_r STR_u STR_n STR_r "\0"
+#define STRING_s0 STR_s "\0"
+#define STRING_samaritan0 STR_s STR_a STR_m STR_a STR_r STR_i STR_t STR_a STR_n "\0"
+#define STRING_samr0 STR_s STR_a STR_m STR_r "\0"
+#define STRING_sarb0 STR_s STR_a STR_r STR_b "\0"
+#define STRING_saur0 STR_s STR_a STR_u STR_r "\0"
+#define STRING_saurashtra0 STR_s STR_a STR_u STR_r STR_a STR_s STR_h STR_t STR_r STR_a "\0"
+#define STRING_sc0 STR_s STR_c "\0"
+#define STRING_sd0 STR_s STR_d "\0"
+#define STRING_sentenceterminal0 STR_s STR_e STR_n STR_t STR_e STR_n STR_c STR_e STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l "\0"
+#define STRING_sgnw0 STR_s STR_g STR_n STR_w "\0"
+#define STRING_sharada0 STR_s STR_h STR_a STR_r STR_a STR_d STR_a "\0"
+#define STRING_shavian0 STR_s STR_h STR_a STR_v STR_i STR_a STR_n "\0"
+#define STRING_shaw0 STR_s STR_h STR_a STR_w "\0"
+#define STRING_shrd0 STR_s STR_h STR_r STR_d "\0"
+#define STRING_sidd0 STR_s STR_i STR_d STR_d "\0"
+#define STRING_siddham0 STR_s STR_i STR_d STR_d STR_h STR_a STR_m "\0"
+#define STRING_signwriting0 STR_s STR_i STR_g STR_n STR_w STR_r STR_i STR_t STR_i STR_n STR_g "\0"
+#define STRING_sind0 STR_s STR_i STR_n STR_d "\0"
+#define STRING_sinh0 STR_s STR_i STR_n STR_h "\0"
+#define STRING_sinhala0 STR_s STR_i STR_n STR_h STR_a STR_l STR_a "\0"
+#define STRING_sk0 STR_s STR_k "\0"
+#define STRING_sm0 STR_s STR_m "\0"
+#define STRING_so0 STR_s STR_o "\0"
+#define STRING_softdotted0 STR_s STR_o STR_f STR_t STR_d STR_o STR_t STR_t STR_e STR_d "\0"
+#define STRING_sogd0 STR_s STR_o STR_g STR_d "\0"
+#define STRING_sogdian0 STR_s STR_o STR_g STR_d STR_i STR_a STR_n "\0"
+#define STRING_sogo0 STR_s STR_o STR_g STR_o "\0"
+#define STRING_sora0 STR_s STR_o STR_r STR_a "\0"
+#define STRING_sorasompeng0 STR_s STR_o STR_r STR_a STR_s STR_o STR_m STR_p STR_e STR_n STR_g "\0"
+#define STRING_soyo0 STR_s STR_o STR_y STR_o "\0"
+#define STRING_soyombo0 STR_s STR_o STR_y STR_o STR_m STR_b STR_o "\0"
+#define STRING_space0 STR_s STR_p STR_a STR_c STR_e "\0"
+#define STRING_sterm0 STR_s STR_t STR_e STR_r STR_m "\0"
+#define STRING_sund0 STR_s STR_u STR_n STR_d "\0"
+#define STRING_sundanese0 STR_s STR_u STR_n STR_d STR_a STR_n STR_e STR_s STR_e "\0"
+#define STRING_sylo0 STR_s STR_y STR_l STR_o "\0"
+#define STRING_sylotinagri0 STR_s STR_y STR_l STR_o STR_t STR_i STR_n STR_a STR_g STR_r STR_i "\0"
+#define STRING_syrc0 STR_s STR_y STR_r STR_c "\0"
+#define STRING_syriac0 STR_s STR_y STR_r STR_i STR_a STR_c "\0"
+#define STRING_tagalog0 STR_t STR_a STR_g STR_a STR_l STR_o STR_g "\0"
+#define STRING_tagb0 STR_t STR_a STR_g STR_b "\0"
+#define STRING_tagbanwa0 STR_t STR_a STR_g STR_b STR_a STR_n STR_w STR_a "\0"
+#define STRING_taile0 STR_t STR_a STR_i STR_l STR_e "\0"
+#define STRING_taitham0 STR_t STR_a STR_i STR_t STR_h STR_a STR_m "\0"
+#define STRING_taiviet0 STR_t STR_a STR_i STR_v STR_i STR_e STR_t "\0"
+#define STRING_takr0 STR_t STR_a STR_k STR_r "\0"
+#define STRING_takri0 STR_t STR_a STR_k STR_r STR_i "\0"
+#define STRING_tale0 STR_t STR_a STR_l STR_e "\0"
+#define STRING_talu0 STR_t STR_a STR_l STR_u "\0"
+#define STRING_tamil0 STR_t STR_a STR_m STR_i STR_l "\0"
+#define STRING_taml0 STR_t STR_a STR_m STR_l "\0"
+#define STRING_tang0 STR_t STR_a STR_n STR_g "\0"
+#define STRING_tangsa0 STR_t STR_a STR_n STR_g STR_s STR_a "\0"
+#define STRING_tangut0 STR_t STR_a STR_n STR_g STR_u STR_t "\0"
+#define STRING_tavt0 STR_t STR_a STR_v STR_t "\0"
+#define STRING_telu0 STR_t STR_e STR_l STR_u "\0"
+#define STRING_telugu0 STR_t STR_e STR_l STR_u STR_g STR_u "\0"
+#define STRING_term0 STR_t STR_e STR_r STR_m "\0"
+#define STRING_terminalpunctuation0 STR_t STR_e STR_r STR_m STR_i STR_n STR_a STR_l STR_p STR_u STR_n STR_c STR_t STR_u STR_a STR_t STR_i STR_o STR_n "\0"
+#define STRING_tfng0 STR_t STR_f STR_n STR_g "\0"
+#define STRING_tglg0 STR_t STR_g STR_l STR_g "\0"
+#define STRING_thaa0 STR_t STR_h STR_a STR_a "\0"
+#define STRING_thaana0 STR_t STR_h STR_a STR_a STR_n STR_a "\0"
+#define STRING_thai0 STR_t STR_h STR_a STR_i "\0"
+#define STRING_tibetan0 STR_t STR_i STR_b STR_e STR_t STR_a STR_n "\0"
+#define STRING_tibt0 STR_t STR_i STR_b STR_t "\0"
+#define STRING_tifinagh0 STR_t STR_i STR_f STR_i STR_n STR_a STR_g STR_h "\0"
+#define STRING_tirh0 STR_t STR_i STR_r STR_h "\0"
+#define STRING_tirhuta0 STR_t STR_i STR_r STR_h STR_u STR_t STR_a "\0"
+#define STRING_tnsa0 STR_t STR_n STR_s STR_a "\0"
+#define STRING_toto0 STR_t STR_o STR_t STR_o "\0"
+#define STRING_ugar0 STR_u STR_g STR_a STR_r "\0"
+#define STRING_ugaritic0 STR_u STR_g STR_a STR_r STR_i STR_t STR_i STR_c "\0"
+#define STRING_uideo0 STR_u STR_i STR_d STR_e STR_o "\0"
+#define STRING_unifiedideograph0 STR_u STR_n STR_i STR_f STR_i STR_e STR_d STR_i STR_d STR_e STR_o STR_g STR_r STR_a STR_p STR_h "\0"
+#define STRING_unknown0 STR_u STR_n STR_k STR_n STR_o STR_w STR_n "\0"
+#define STRING_upper0 STR_u STR_p STR_p STR_e STR_r "\0"
+#define STRING_uppercase0 STR_u STR_p STR_p STR_e STR_r STR_c STR_a STR_s STR_e "\0"
+#define STRING_vai0 STR_v STR_a STR_i "\0"
+#define STRING_vaii0 STR_v STR_a STR_i STR_i "\0"
+#define STRING_variationselector0 STR_v STR_a STR_r STR_i STR_a STR_t STR_i STR_o STR_n STR_s STR_e STR_l STR_e STR_c STR_t STR_o STR_r "\0"
+#define STRING_vith0 STR_v STR_i STR_t STR_h "\0"
+#define STRING_vithkuqi0 STR_v STR_i STR_t STR_h STR_k STR_u STR_q STR_i "\0"
+#define STRING_vs0 STR_v STR_s "\0"
+#define STRING_wancho0 STR_w STR_a STR_n STR_c STR_h STR_o "\0"
+#define STRING_wara0 STR_w STR_a STR_r STR_a "\0"
+#define STRING_warangciti0 STR_w STR_a STR_r STR_a STR_n STR_g STR_c STR_i STR_t STR_i "\0"
+#define STRING_wcho0 STR_w STR_c STR_h STR_o "\0"
+#define STRING_whitespace0 STR_w STR_h STR_i STR_t STR_e STR_s STR_p STR_a STR_c STR_e "\0"
+#define STRING_wspace0 STR_w STR_s STR_p STR_a STR_c STR_e "\0"
+#define STRING_xan0 STR_x STR_a STR_n "\0"
+#define STRING_xidc0 STR_x STR_i STR_d STR_c "\0"
+#define STRING_xidcontinue0 STR_x STR_i STR_d STR_c STR_o STR_n STR_t STR_i STR_n STR_u STR_e "\0"
+#define STRING_xids0 STR_x STR_i STR_d STR_s "\0"
+#define STRING_xidstart0 STR_x STR_i STR_d STR_s STR_t STR_a STR_r STR_t "\0"
+#define STRING_xpeo0 STR_x STR_p STR_e STR_o "\0"
+#define STRING_xps0 STR_x STR_p STR_s "\0"
+#define STRING_xsp0 STR_x STR_s STR_p "\0"
+#define STRING_xsux0 STR_x STR_s STR_u STR_x "\0"
+#define STRING_xuc0 STR_x STR_u STR_c "\0"
+#define STRING_xwd0 STR_x STR_w STR_d "\0"
+#define STRING_yezi0 STR_y STR_e STR_z STR_i "\0"
+#define STRING_yezidi0 STR_y STR_e STR_z STR_i STR_d STR_i "\0"
+#define STRING_yi0 STR_y STR_i "\0"
+#define STRING_yiii0 STR_y STR_i STR_i STR_i "\0"
+#define STRING_z0 STR_z "\0"
+#define STRING_zanabazarsquare0 STR_z STR_a STR_n STR_a STR_b STR_a STR_z STR_a STR_r STR_s STR_q STR_u STR_a STR_r STR_e "\0"
+#define STRING_zanb0 STR_z STR_a STR_n STR_b "\0"
+#define STRING_zinh0 STR_z STR_i STR_n STR_h "\0"
+#define STRING_zl0 STR_z STR_l "\0"
+#define STRING_zp0 STR_z STR_p "\0"
+#define STRING_zs0 STR_z STR_s "\0"
+#define STRING_zyyy0 STR_z STR_y STR_y STR_y "\0"
+#define STRING_zzzz0 STR_z STR_z STR_z STR_z "\0"
+
+const char PRIV(utt_names)[] =
+ STRING_adlam0
+ STRING_adlm0
+ STRING_aghb0
+ STRING_ahex0
+ STRING_ahom0
+ STRING_alpha0
+ STRING_alphabetic0
+ STRING_anatolianhieroglyphs0
+ STRING_any0
+ STRING_arab0
+ STRING_arabic0
+ STRING_armenian0
+ STRING_armi0
+ STRING_armn0
+ STRING_ascii0
+ STRING_asciihexdigit0
+ STRING_avestan0
+ STRING_avst0
+ STRING_bali0
+ STRING_balinese0
+ STRING_bamu0
+ STRING_bamum0
+ STRING_bass0
+ STRING_bassavah0
+ STRING_batak0
+ STRING_batk0
+ STRING_beng0
+ STRING_bengali0
+ STRING_bhaiksuki0
+ STRING_bhks0
+ STRING_bidial0
+ STRING_bidian0
+ STRING_bidib0
+ STRING_bidibn0
+ STRING_bidic0
+ STRING_bidicontrol0
+ STRING_bidics0
+ STRING_bidien0
+ STRING_bidies0
+ STRING_bidiet0
+ STRING_bidifsi0
+ STRING_bidil0
+ STRING_bidilre0
+ STRING_bidilri0
+ STRING_bidilro0
+ STRING_bidim0
+ STRING_bidimirrored0
+ STRING_bidinsm0
+ STRING_bidion0
+ STRING_bidipdf0
+ STRING_bidipdi0
+ STRING_bidir0
+ STRING_bidirle0
+ STRING_bidirli0
+ STRING_bidirlo0
+ STRING_bidis0
+ STRING_bidiws0
+ STRING_bopo0
+ STRING_bopomofo0
+ STRING_brah0
+ STRING_brahmi0
+ STRING_brai0
+ STRING_braille0
+ STRING_bugi0
+ STRING_buginese0
+ STRING_buhd0
+ STRING_buhid0
+ STRING_c0
+ STRING_cakm0
+ STRING_canadianaboriginal0
+ STRING_cans0
+ STRING_cari0
+ STRING_carian0
+ STRING_cased0
+ STRING_caseignorable0
+ STRING_caucasianalbanian0
+ STRING_cc0
+ STRING_cf0
+ STRING_chakma0
+ STRING_cham0
+ STRING_changeswhencasefolded0
+ STRING_changeswhencasemapped0
+ STRING_changeswhenlowercased0
+ STRING_changeswhentitlecased0
+ STRING_changeswhenuppercased0
+ STRING_cher0
+ STRING_cherokee0
+ STRING_chorasmian0
+ STRING_chrs0
+ STRING_ci0
+ STRING_cn0
+ STRING_co0
+ STRING_common0
+ STRING_copt0
+ STRING_coptic0
+ STRING_cpmn0
+ STRING_cprt0
+ STRING_cs0
+ STRING_cuneiform0
+ STRING_cwcf0
+ STRING_cwcm0
+ STRING_cwl0
+ STRING_cwt0
+ STRING_cwu0
+ STRING_cypriot0
+ STRING_cyprominoan0
+ STRING_cyrillic0
+ STRING_cyrl0
+ STRING_dash0
+ STRING_defaultignorablecodepoint0
+ STRING_dep0
+ STRING_deprecated0
+ STRING_deseret0
+ STRING_deva0
+ STRING_devanagari0
+ STRING_di0
+ STRING_dia0
+ STRING_diacritic0
+ STRING_diak0
+ STRING_divesakuru0
+ STRING_dogr0
+ STRING_dogra0
+ STRING_dsrt0
+ STRING_dupl0
+ STRING_duployan0
+ STRING_ebase0
+ STRING_ecomp0
+ STRING_egyp0
+ STRING_egyptianhieroglyphs0
+ STRING_elba0
+ STRING_elbasan0
+ STRING_elym0
+ STRING_elymaic0
+ STRING_emod0
+ STRING_emoji0
+ STRING_emojicomponent0
+ STRING_emojimodifier0
+ STRING_emojimodifierbase0
+ STRING_emojipresentation0
+ STRING_epres0
+ STRING_ethi0
+ STRING_ethiopic0
+ STRING_ext0
+ STRING_extendedpictographic0
+ STRING_extender0
+ STRING_extpict0
+ STRING_geor0
+ STRING_georgian0
+ STRING_glag0
+ STRING_glagolitic0
+ STRING_gong0
+ STRING_gonm0
+ STRING_goth0
+ STRING_gothic0
+ STRING_gran0
+ STRING_grantha0
+ STRING_graphemebase0
+ STRING_graphemeextend0
+ STRING_graphemelink0
+ STRING_grbase0
+ STRING_greek0
+ STRING_grek0
+ STRING_grext0
+ STRING_grlink0
+ STRING_gujarati0
+ STRING_gujr0
+ STRING_gunjalagondi0
+ STRING_gurmukhi0
+ STRING_guru0
+ STRING_han0
+ STRING_hang0
+ STRING_hangul0
+ STRING_hani0
+ STRING_hanifirohingya0
+ STRING_hano0
+ STRING_hanunoo0
+ STRING_hatr0
+ STRING_hatran0
+ STRING_hebr0
+ STRING_hebrew0
+ STRING_hex0
+ STRING_hexdigit0
+ STRING_hira0
+ STRING_hiragana0
+ STRING_hluw0
+ STRING_hmng0
+ STRING_hmnp0
+ STRING_hung0
+ STRING_idc0
+ STRING_idcontinue0
+ STRING_ideo0
+ STRING_ideographic0
+ STRING_ids0
+ STRING_idsb0
+ STRING_idsbinaryoperator0
+ STRING_idst0
+ STRING_idstart0
+ STRING_idstrinaryoperator0
+ STRING_imperialaramaic0
+ STRING_inherited0
+ STRING_inscriptionalpahlavi0
+ STRING_inscriptionalparthian0
+ STRING_ital0
+ STRING_java0
+ STRING_javanese0
+ STRING_joinc0
+ STRING_joincontrol0
+ STRING_kaithi0
+ STRING_kali0
+ STRING_kana0
+ STRING_kannada0
+ STRING_katakana0
+ STRING_kayahli0
+ STRING_khar0
+ STRING_kharoshthi0
+ STRING_khitansmallscript0
+ STRING_khmer0
+ STRING_khmr0
+ STRING_khoj0
+ STRING_khojki0
+ STRING_khudawadi0
+ STRING_kits0
+ STRING_knda0
+ STRING_kthi0
+ STRING_l0
+ STRING_l_AMPERSAND0
+ STRING_lana0
+ STRING_lao0
+ STRING_laoo0
+ STRING_latin0
+ STRING_latn0
+ STRING_lc0
+ STRING_lepc0
+ STRING_lepcha0
+ STRING_limb0
+ STRING_limbu0
+ STRING_lina0
+ STRING_linb0
+ STRING_lineara0
+ STRING_linearb0
+ STRING_lisu0
+ STRING_ll0
+ STRING_lm0
+ STRING_lo0
+ STRING_loe0
+ STRING_logicalorderexception0
+ STRING_lower0
+ STRING_lowercase0
+ STRING_lt0
+ STRING_lu0
+ STRING_lyci0
+ STRING_lycian0
+ STRING_lydi0
+ STRING_lydian0
+ STRING_m0
+ STRING_mahajani0
+ STRING_mahj0
+ STRING_maka0
+ STRING_makasar0
+ STRING_malayalam0
+ STRING_mand0
+ STRING_mandaic0
+ STRING_mani0
+ STRING_manichaean0
+ STRING_marc0
+ STRING_marchen0
+ STRING_masaramgondi0
+ STRING_math0
+ STRING_mc0
+ STRING_me0
+ STRING_medefaidrin0
+ STRING_medf0
+ STRING_meeteimayek0
+ STRING_mend0
+ STRING_mendekikakui0
+ STRING_merc0
+ STRING_mero0
+ STRING_meroiticcursive0
+ STRING_meroitichieroglyphs0
+ STRING_miao0
+ STRING_mlym0
+ STRING_mn0
+ STRING_modi0
+ STRING_mong0
+ STRING_mongolian0
+ STRING_mro0
+ STRING_mroo0
+ STRING_mtei0
+ STRING_mult0
+ STRING_multani0
+ STRING_myanmar0
+ STRING_mymr0
+ STRING_n0
+ STRING_nabataean0
+ STRING_nand0
+ STRING_nandinagari0
+ STRING_narb0
+ STRING_nbat0
+ STRING_nchar0
+ STRING_nd0
+ STRING_newa0
+ STRING_newtailue0
+ STRING_nko0
+ STRING_nkoo0
+ STRING_nl0
+ STRING_no0
+ STRING_noncharactercodepoint0
+ STRING_nshu0
+ STRING_nushu0
+ STRING_nyiakengpuachuehmong0
+ STRING_ogam0
+ STRING_ogham0
+ STRING_olchiki0
+ STRING_olck0
+ STRING_oldhungarian0
+ STRING_olditalic0
+ STRING_oldnortharabian0
+ STRING_oldpermic0
+ STRING_oldpersian0
+ STRING_oldsogdian0
+ STRING_oldsoutharabian0
+ STRING_oldturkic0
+ STRING_olduyghur0
+ STRING_oriya0
+ STRING_orkh0
+ STRING_orya0
+ STRING_osage0
+ STRING_osge0
+ STRING_osma0
+ STRING_osmanya0
+ STRING_ougr0
+ STRING_p0
+ STRING_pahawhhmong0
+ STRING_palm0
+ STRING_palmyrene0
+ STRING_patsyn0
+ STRING_patternsyntax0
+ STRING_patternwhitespace0
+ STRING_patws0
+ STRING_pauc0
+ STRING_paucinhau0
+ STRING_pc0
+ STRING_pcm0
+ STRING_pd0
+ STRING_pe0
+ STRING_perm0
+ STRING_pf0
+ STRING_phag0
+ STRING_phagspa0
+ STRING_phli0
+ STRING_phlp0
+ STRING_phnx0
+ STRING_phoenician0
+ STRING_pi0
+ STRING_plrd0
+ STRING_po0
+ STRING_prependedconcatenationmark0
+ STRING_prti0
+ STRING_ps0
+ STRING_psalterpahlavi0
+ STRING_qaac0
+ STRING_qaai0
+ STRING_qmark0
+ STRING_quotationmark0
+ STRING_radical0
+ STRING_regionalindicator0
+ STRING_rejang0
+ STRING_ri0
+ STRING_rjng0
+ STRING_rohg0
+ STRING_runic0
+ STRING_runr0
+ STRING_s0
+ STRING_samaritan0
+ STRING_samr0
+ STRING_sarb0
+ STRING_saur0
+ STRING_saurashtra0
+ STRING_sc0
+ STRING_sd0
+ STRING_sentenceterminal0
+ STRING_sgnw0
+ STRING_sharada0
+ STRING_shavian0
+ STRING_shaw0
+ STRING_shrd0
+ STRING_sidd0
+ STRING_siddham0
+ STRING_signwriting0
+ STRING_sind0
+ STRING_sinh0
+ STRING_sinhala0
+ STRING_sk0
+ STRING_sm0
+ STRING_so0
+ STRING_softdotted0
+ STRING_sogd0
+ STRING_sogdian0
+ STRING_sogo0
+ STRING_sora0
+ STRING_sorasompeng0
+ STRING_soyo0
+ STRING_soyombo0
+ STRING_space0
+ STRING_sterm0
+ STRING_sund0
+ STRING_sundanese0
+ STRING_sylo0
+ STRING_sylotinagri0
+ STRING_syrc0
+ STRING_syriac0
+ STRING_tagalog0
+ STRING_tagb0
+ STRING_tagbanwa0
+ STRING_taile0
+ STRING_taitham0
+ STRING_taiviet0
+ STRING_takr0
+ STRING_takri0
+ STRING_tale0
+ STRING_talu0
+ STRING_tamil0
+ STRING_taml0
+ STRING_tang0
+ STRING_tangsa0
+ STRING_tangut0
+ STRING_tavt0
+ STRING_telu0
+ STRING_telugu0
+ STRING_term0
+ STRING_terminalpunctuation0
+ STRING_tfng0
+ STRING_tglg0
+ STRING_thaa0
+ STRING_thaana0
+ STRING_thai0
+ STRING_tibetan0
+ STRING_tibt0
+ STRING_tifinagh0
+ STRING_tirh0
+ STRING_tirhuta0
+ STRING_tnsa0
+ STRING_toto0
+ STRING_ugar0
+ STRING_ugaritic0
+ STRING_uideo0
+ STRING_unifiedideograph0
+ STRING_unknown0
+ STRING_upper0
+ STRING_uppercase0
+ STRING_vai0
+ STRING_vaii0
+ STRING_variationselector0
+ STRING_vith0
+ STRING_vithkuqi0
+ STRING_vs0
+ STRING_wancho0
+ STRING_wara0
+ STRING_warangciti0
+ STRING_wcho0
+ STRING_whitespace0
+ STRING_wspace0
+ STRING_xan0
+ STRING_xidc0
+ STRING_xidcontinue0
+ STRING_xids0
+ STRING_xidstart0
+ STRING_xpeo0
+ STRING_xps0
+ STRING_xsp0
+ STRING_xsux0
+ STRING_xuc0
+ STRING_xwd0
+ STRING_yezi0
+ STRING_yezidi0
+ STRING_yi0
+ STRING_yiii0
+ STRING_z0
+ STRING_zanabazarsquare0
+ STRING_zanb0
+ STRING_zinh0
+ STRING_zl0
+ STRING_zp0
+ STRING_zs0
+ STRING_zyyy0
+ STRING_zzzz0;
+
+const ucp_type_table PRIV(utt)[] = {
+ { 0, PT_SCX, ucp_Adlam },
+ { 6, PT_SCX, ucp_Adlam },
+ { 11, PT_SC, ucp_Caucasian_Albanian },
+ { 16, PT_BOOL, ucp_ASCII_Hex_Digit },
+ { 21, PT_SC, ucp_Ahom },
+ { 26, PT_BOOL, ucp_Alphabetic },
+ { 32, PT_BOOL, ucp_Alphabetic },
+ { 43, PT_SC, ucp_Anatolian_Hieroglyphs },
+ { 64, PT_ANY, 0 },
+ { 68, PT_SCX, ucp_Arabic },
+ { 73, PT_SCX, ucp_Arabic },
+ { 80, PT_SC, ucp_Armenian },
+ { 89, PT_SC, ucp_Imperial_Aramaic },
+ { 94, PT_SC, ucp_Armenian },
+ { 99, PT_BOOL, ucp_ASCII },
+ { 105, PT_BOOL, ucp_ASCII_Hex_Digit },
+ { 119, PT_SC, ucp_Avestan },
+ { 127, PT_SC, ucp_Avestan },
+ { 132, PT_SC, ucp_Balinese },
+ { 137, PT_SC, ucp_Balinese },
+ { 146, PT_SC, ucp_Bamum },
+ { 151, PT_SC, ucp_Bamum },
+ { 157, PT_SC, ucp_Bassa_Vah },
+ { 162, PT_SC, ucp_Bassa_Vah },
+ { 171, PT_SC, ucp_Batak },
+ { 177, PT_SC, ucp_Batak },
+ { 182, PT_SCX, ucp_Bengali },
+ { 187, PT_SCX, ucp_Bengali },
+ { 195, PT_SC, ucp_Bhaiksuki },
+ { 205, PT_SC, ucp_Bhaiksuki },
+ { 210, PT_BIDICL, ucp_bidiAL },
+ { 217, PT_BIDICL, ucp_bidiAN },
+ { 224, PT_BIDICL, ucp_bidiB },
+ { 230, PT_BIDICL, ucp_bidiBN },
+ { 237, PT_BOOL, ucp_Bidi_Control },
+ { 243, PT_BOOL, ucp_Bidi_Control },
+ { 255, PT_BIDICL, ucp_bidiCS },
+ { 262, PT_BIDICL, ucp_bidiEN },
+ { 269, PT_BIDICL, ucp_bidiES },
+ { 276, PT_BIDICL, ucp_bidiET },
+ { 283, PT_BIDICL, ucp_bidiFSI },
+ { 291, PT_BIDICL, ucp_bidiL },
+ { 297, PT_BIDICL, ucp_bidiLRE },
+ { 305, PT_BIDICL, ucp_bidiLRI },
+ { 313, PT_BIDICL, ucp_bidiLRO },
+ { 321, PT_BOOL, ucp_Bidi_Mirrored },
+ { 327, PT_BOOL, ucp_Bidi_Mirrored },
+ { 340, PT_BIDICL, ucp_bidiNSM },
+ { 348, PT_BIDICL, ucp_bidiON },
+ { 355, PT_BIDICL, ucp_bidiPDF },
+ { 363, PT_BIDICL, ucp_bidiPDI },
+ { 371, PT_BIDICL, ucp_bidiR },
+ { 377, PT_BIDICL, ucp_bidiRLE },
+ { 385, PT_BIDICL, ucp_bidiRLI },
+ { 393, PT_BIDICL, ucp_bidiRLO },
+ { 401, PT_BIDICL, ucp_bidiS },
+ { 407, PT_BIDICL, ucp_bidiWS },
+ { 414, PT_SCX, ucp_Bopomofo },
+ { 419, PT_SCX, ucp_Bopomofo },
+ { 428, PT_SC, ucp_Brahmi },
+ { 433, PT_SC, ucp_Brahmi },
+ { 440, PT_SC, ucp_Braille },
+ { 445, PT_SC, ucp_Braille },
+ { 453, PT_SCX, ucp_Buginese },
+ { 458, PT_SCX, ucp_Buginese },
+ { 467, PT_SCX, ucp_Buhid },
+ { 472, PT_SCX, ucp_Buhid },
+ { 478, PT_GC, ucp_C },
+ { 480, PT_SCX, ucp_Chakma },
+ { 485, PT_SC, ucp_Canadian_Aboriginal },
+ { 504, PT_SC, ucp_Canadian_Aboriginal },
+ { 509, PT_SC, ucp_Carian },
+ { 514, PT_SC, ucp_Carian },
+ { 521, PT_BOOL, ucp_Cased },
+ { 527, PT_BOOL, ucp_Case_Ignorable },
+ { 541, PT_SC, ucp_Caucasian_Albanian },
+ { 559, PT_PC, ucp_Cc },
+ { 562, PT_PC, ucp_Cf },
+ { 565, PT_SCX, ucp_Chakma },
+ { 572, PT_SC, ucp_Cham },
+ { 577, PT_BOOL, ucp_Changes_When_Casefolded },
+ { 599, PT_BOOL, ucp_Changes_When_Casemapped },
+ { 621, PT_BOOL, ucp_Changes_When_Lowercased },
+ { 643, PT_BOOL, ucp_Changes_When_Titlecased },
+ { 665, PT_BOOL, ucp_Changes_When_Uppercased },
+ { 687, PT_SC, ucp_Cherokee },
+ { 692, PT_SC, ucp_Cherokee },
+ { 701, PT_SC, ucp_Chorasmian },
+ { 712, PT_SC, ucp_Chorasmian },
+ { 717, PT_BOOL, ucp_Case_Ignorable },
+ { 720, PT_PC, ucp_Cn },
+ { 723, PT_PC, ucp_Co },
+ { 726, PT_SC, ucp_Common },
+ { 733, PT_SCX, ucp_Coptic },
+ { 738, PT_SCX, ucp_Coptic },
+ { 745, PT_SCX, ucp_Cypro_Minoan },
+ { 750, PT_SCX, ucp_Cypriot },
+ { 755, PT_PC, ucp_Cs },
+ { 758, PT_SC, ucp_Cuneiform },
+ { 768, PT_BOOL, ucp_Changes_When_Casefolded },
+ { 773, PT_BOOL, ucp_Changes_When_Casemapped },
+ { 778, PT_BOOL, ucp_Changes_When_Lowercased },
+ { 782, PT_BOOL, ucp_Changes_When_Titlecased },
+ { 786, PT_BOOL, ucp_Changes_When_Uppercased },
+ { 790, PT_SCX, ucp_Cypriot },
+ { 798, PT_SCX, ucp_Cypro_Minoan },
+ { 810, PT_SCX, ucp_Cyrillic },
+ { 819, PT_SCX, ucp_Cyrillic },
+ { 824, PT_BOOL, ucp_Dash },
+ { 829, PT_BOOL, ucp_Default_Ignorable_Code_Point },
+ { 855, PT_BOOL, ucp_Deprecated },
+ { 859, PT_BOOL, ucp_Deprecated },
+ { 870, PT_SC, ucp_Deseret },
+ { 878, PT_SCX, ucp_Devanagari },
+ { 883, PT_SCX, ucp_Devanagari },
+ { 894, PT_BOOL, ucp_Default_Ignorable_Code_Point },
+ { 897, PT_BOOL, ucp_Diacritic },
+ { 901, PT_BOOL, ucp_Diacritic },
+ { 911, PT_SC, ucp_Dives_Akuru },
+ { 916, PT_SC, ucp_Dives_Akuru },
+ { 927, PT_SCX, ucp_Dogra },
+ { 932, PT_SCX, ucp_Dogra },
+ { 938, PT_SC, ucp_Deseret },
+ { 943, PT_SCX, ucp_Duployan },
+ { 948, PT_SCX, ucp_Duployan },
+ { 957, PT_BOOL, ucp_Emoji_Modifier_Base },
+ { 963, PT_BOOL, ucp_Emoji_Component },
+ { 969, PT_SC, ucp_Egyptian_Hieroglyphs },
+ { 974, PT_SC, ucp_Egyptian_Hieroglyphs },
+ { 994, PT_SC, ucp_Elbasan },
+ { 999, PT_SC, ucp_Elbasan },
+ { 1007, PT_SC, ucp_Elymaic },
+ { 1012, PT_SC, ucp_Elymaic },
+ { 1020, PT_BOOL, ucp_Emoji_Modifier },
+ { 1025, PT_BOOL, ucp_Emoji },
+ { 1031, PT_BOOL, ucp_Emoji_Component },
+ { 1046, PT_BOOL, ucp_Emoji_Modifier },
+ { 1060, PT_BOOL, ucp_Emoji_Modifier_Base },
+ { 1078, PT_BOOL, ucp_Emoji_Presentation },
+ { 1096, PT_BOOL, ucp_Emoji_Presentation },
+ { 1102, PT_SC, ucp_Ethiopic },
+ { 1107, PT_SC, ucp_Ethiopic },
+ { 1116, PT_BOOL, ucp_Extender },
+ { 1120, PT_BOOL, ucp_Extended_Pictographic },
+ { 1141, PT_BOOL, ucp_Extender },
+ { 1150, PT_BOOL, ucp_Extended_Pictographic },
+ { 1158, PT_SCX, ucp_Georgian },
+ { 1163, PT_SCX, ucp_Georgian },
+ { 1172, PT_SCX, ucp_Glagolitic },
+ { 1177, PT_SCX, ucp_Glagolitic },
+ { 1188, PT_SCX, ucp_Gunjala_Gondi },
+ { 1193, PT_SCX, ucp_Masaram_Gondi },
+ { 1198, PT_SC, ucp_Gothic },
+ { 1203, PT_SC, ucp_Gothic },
+ { 1210, PT_SCX, ucp_Grantha },
+ { 1215, PT_SCX, ucp_Grantha },
+ { 1223, PT_BOOL, ucp_Grapheme_Base },
+ { 1236, PT_BOOL, ucp_Grapheme_Extend },
+ { 1251, PT_BOOL, ucp_Grapheme_Link },
+ { 1264, PT_BOOL, ucp_Grapheme_Base },
+ { 1271, PT_SCX, ucp_Greek },
+ { 1277, PT_SCX, ucp_Greek },
+ { 1282, PT_BOOL, ucp_Grapheme_Extend },
+ { 1288, PT_BOOL, ucp_Grapheme_Link },
+ { 1295, PT_SCX, ucp_Gujarati },
+ { 1304, PT_SCX, ucp_Gujarati },
+ { 1309, PT_SCX, ucp_Gunjala_Gondi },
+ { 1322, PT_SCX, ucp_Gurmukhi },
+ { 1331, PT_SCX, ucp_Gurmukhi },
+ { 1336, PT_SCX, ucp_Han },
+ { 1340, PT_SCX, ucp_Hangul },
+ { 1345, PT_SCX, ucp_Hangul },
+ { 1352, PT_SCX, ucp_Han },
+ { 1357, PT_SCX, ucp_Hanifi_Rohingya },
+ { 1372, PT_SCX, ucp_Hanunoo },
+ { 1377, PT_SCX, ucp_Hanunoo },
+ { 1385, PT_SC, ucp_Hatran },
+ { 1390, PT_SC, ucp_Hatran },
+ { 1397, PT_SC, ucp_Hebrew },
+ { 1402, PT_SC, ucp_Hebrew },
+ { 1409, PT_BOOL, ucp_Hex_Digit },
+ { 1413, PT_BOOL, ucp_Hex_Digit },
+ { 1422, PT_SCX, ucp_Hiragana },
+ { 1427, PT_SCX, ucp_Hiragana },
+ { 1436, PT_SC, ucp_Anatolian_Hieroglyphs },
+ { 1441, PT_SC, ucp_Pahawh_Hmong },
+ { 1446, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
+ { 1451, PT_SC, ucp_Old_Hungarian },
+ { 1456, PT_BOOL, ucp_ID_Continue },
+ { 1460, PT_BOOL, ucp_ID_Continue },
+ { 1471, PT_BOOL, ucp_Ideographic },
+ { 1476, PT_BOOL, ucp_Ideographic },
+ { 1488, PT_BOOL, ucp_ID_Start },
+ { 1492, PT_BOOL, ucp_IDS_Binary_Operator },
+ { 1497, PT_BOOL, ucp_IDS_Binary_Operator },
+ { 1515, PT_BOOL, ucp_IDS_Trinary_Operator },
+ { 1520, PT_BOOL, ucp_ID_Start },
+ { 1528, PT_BOOL, ucp_IDS_Trinary_Operator },
+ { 1547, PT_SC, ucp_Imperial_Aramaic },
+ { 1563, PT_SC, ucp_Inherited },
+ { 1573, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 1594, PT_SC, ucp_Inscriptional_Parthian },
+ { 1616, PT_SC, ucp_Old_Italic },
+ { 1621, PT_SCX, ucp_Javanese },
+ { 1626, PT_SCX, ucp_Javanese },
+ { 1635, PT_BOOL, ucp_Join_Control },
+ { 1641, PT_BOOL, ucp_Join_Control },
+ { 1653, PT_SCX, ucp_Kaithi },
+ { 1660, PT_SCX, ucp_Kayah_Li },
+ { 1665, PT_SCX, ucp_Katakana },
+ { 1670, PT_SCX, ucp_Kannada },
+ { 1678, PT_SCX, ucp_Katakana },
+ { 1687, PT_SCX, ucp_Kayah_Li },
+ { 1695, PT_SC, ucp_Kharoshthi },
+ { 1700, PT_SC, ucp_Kharoshthi },
+ { 1711, PT_SC, ucp_Khitan_Small_Script },
+ { 1729, PT_SC, ucp_Khmer },
+ { 1735, PT_SC, ucp_Khmer },
+ { 1740, PT_SCX, ucp_Khojki },
+ { 1745, PT_SCX, ucp_Khojki },
+ { 1752, PT_SCX, ucp_Khudawadi },
+ { 1762, PT_SC, ucp_Khitan_Small_Script },
+ { 1767, PT_SCX, ucp_Kannada },
+ { 1772, PT_SCX, ucp_Kaithi },
+ { 1777, PT_GC, ucp_L },
+ { 1779, PT_LAMP, 0 },
+ { 1782, PT_SC, ucp_Tai_Tham },
+ { 1787, PT_SC, ucp_Lao },
+ { 1791, PT_SC, ucp_Lao },
+ { 1796, PT_SCX, ucp_Latin },
+ { 1802, PT_SCX, ucp_Latin },
+ { 1807, PT_LAMP, 0 },
+ { 1810, PT_SC, ucp_Lepcha },
+ { 1815, PT_SC, ucp_Lepcha },
+ { 1822, PT_SCX, ucp_Limbu },
+ { 1827, PT_SCX, ucp_Limbu },
+ { 1833, PT_SCX, ucp_Linear_A },
+ { 1838, PT_SCX, ucp_Linear_B },
+ { 1843, PT_SCX, ucp_Linear_A },
+ { 1851, PT_SCX, ucp_Linear_B },
+ { 1859, PT_SC, ucp_Lisu },
+ { 1864, PT_PC, ucp_Ll },
+ { 1867, PT_PC, ucp_Lm },
+ { 1870, PT_PC, ucp_Lo },
+ { 1873, PT_BOOL, ucp_Logical_Order_Exception },
+ { 1877, PT_BOOL, ucp_Logical_Order_Exception },
+ { 1899, PT_BOOL, ucp_Lowercase },
+ { 1905, PT_BOOL, ucp_Lowercase },
+ { 1915, PT_PC, ucp_Lt },
+ { 1918, PT_PC, ucp_Lu },
+ { 1921, PT_SC, ucp_Lycian },
+ { 1926, PT_SC, ucp_Lycian },
+ { 1933, PT_SC, ucp_Lydian },
+ { 1938, PT_SC, ucp_Lydian },
+ { 1945, PT_GC, ucp_M },
+ { 1947, PT_SCX, ucp_Mahajani },
+ { 1956, PT_SCX, ucp_Mahajani },
+ { 1961, PT_SC, ucp_Makasar },
+ { 1966, PT_SC, ucp_Makasar },
+ { 1974, PT_SCX, ucp_Malayalam },
+ { 1984, PT_SCX, ucp_Mandaic },
+ { 1989, PT_SCX, ucp_Mandaic },
+ { 1997, PT_SCX, ucp_Manichaean },
+ { 2002, PT_SCX, ucp_Manichaean },
+ { 2013, PT_SC, ucp_Marchen },
+ { 2018, PT_SC, ucp_Marchen },
+ { 2026, PT_SCX, ucp_Masaram_Gondi },
+ { 2039, PT_BOOL, ucp_Math },
+ { 2044, PT_PC, ucp_Mc },
+ { 2047, PT_PC, ucp_Me },
+ { 2050, PT_SC, ucp_Medefaidrin },
+ { 2062, PT_SC, ucp_Medefaidrin },
+ { 2067, PT_SC, ucp_Meetei_Mayek },
+ { 2079, PT_SC, ucp_Mende_Kikakui },
+ { 2084, PT_SC, ucp_Mende_Kikakui },
+ { 2097, PT_SC, ucp_Meroitic_Cursive },
+ { 2102, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 2107, PT_SC, ucp_Meroitic_Cursive },
+ { 2123, PT_SC, ucp_Meroitic_Hieroglyphs },
+ { 2143, PT_SC, ucp_Miao },
+ { 2148, PT_SCX, ucp_Malayalam },
+ { 2153, PT_PC, ucp_Mn },
+ { 2156, PT_SCX, ucp_Modi },
+ { 2161, PT_SCX, ucp_Mongolian },
+ { 2166, PT_SCX, ucp_Mongolian },
+ { 2176, PT_SC, ucp_Mro },
+ { 2180, PT_SC, ucp_Mro },
+ { 2185, PT_SC, ucp_Meetei_Mayek },
+ { 2190, PT_SCX, ucp_Multani },
+ { 2195, PT_SCX, ucp_Multani },
+ { 2203, PT_SCX, ucp_Myanmar },
+ { 2211, PT_SCX, ucp_Myanmar },
+ { 2216, PT_GC, ucp_N },
+ { 2218, PT_SC, ucp_Nabataean },
+ { 2228, PT_SCX, ucp_Nandinagari },
+ { 2233, PT_SCX, ucp_Nandinagari },
+ { 2245, PT_SC, ucp_Old_North_Arabian },
+ { 2250, PT_SC, ucp_Nabataean },
+ { 2255, PT_BOOL, ucp_Noncharacter_Code_Point },
+ { 2261, PT_PC, ucp_Nd },
+ { 2264, PT_SC, ucp_Newa },
+ { 2269, PT_SC, ucp_New_Tai_Lue },
+ { 2279, PT_SCX, ucp_Nko },
+ { 2283, PT_SCX, ucp_Nko },
+ { 2288, PT_PC, ucp_Nl },
+ { 2291, PT_PC, ucp_No },
+ { 2294, PT_BOOL, ucp_Noncharacter_Code_Point },
+ { 2316, PT_SC, ucp_Nushu },
+ { 2321, PT_SC, ucp_Nushu },
+ { 2327, PT_SC, ucp_Nyiakeng_Puachue_Hmong },
+ { 2348, PT_SC, ucp_Ogham },
+ { 2353, PT_SC, ucp_Ogham },
+ { 2359, PT_SC, ucp_Ol_Chiki },
+ { 2367, PT_SC, ucp_Ol_Chiki },
+ { 2372, PT_SC, ucp_Old_Hungarian },
+ { 2385, PT_SC, ucp_Old_Italic },
+ { 2395, PT_SC, ucp_Old_North_Arabian },
+ { 2411, PT_SCX, ucp_Old_Permic },
+ { 2421, PT_SC, ucp_Old_Persian },
+ { 2432, PT_SC, ucp_Old_Sogdian },
+ { 2443, PT_SC, ucp_Old_South_Arabian },
+ { 2459, PT_SC, ucp_Old_Turkic },
+ { 2469, PT_SCX, ucp_Old_Uyghur },
+ { 2479, PT_SCX, ucp_Oriya },
+ { 2485, PT_SC, ucp_Old_Turkic },
+ { 2490, PT_SCX, ucp_Oriya },
+ { 2495, PT_SC, ucp_Osage },
+ { 2501, PT_SC, ucp_Osage },
+ { 2506, PT_SC, ucp_Osmanya },
+ { 2511, PT_SC, ucp_Osmanya },
+ { 2519, PT_SCX, ucp_Old_Uyghur },
+ { 2524, PT_GC, ucp_P },
+ { 2526, PT_SC, ucp_Pahawh_Hmong },
+ { 2538, PT_SC, ucp_Palmyrene },
+ { 2543, PT_SC, ucp_Palmyrene },
+ { 2553, PT_BOOL, ucp_Pattern_Syntax },
+ { 2560, PT_BOOL, ucp_Pattern_Syntax },
+ { 2574, PT_BOOL, ucp_Pattern_White_Space },
+ { 2592, PT_BOOL, ucp_Pattern_White_Space },
+ { 2598, PT_SC, ucp_Pau_Cin_Hau },
+ { 2603, PT_SC, ucp_Pau_Cin_Hau },
+ { 2613, PT_PC, ucp_Pc },
+ { 2616, PT_BOOL, ucp_Prepended_Concatenation_Mark },
+ { 2620, PT_PC, ucp_Pd },
+ { 2623, PT_PC, ucp_Pe },
+ { 2626, PT_SCX, ucp_Old_Permic },
+ { 2631, PT_PC, ucp_Pf },
+ { 2634, PT_SCX, ucp_Phags_Pa },
+ { 2639, PT_SCX, ucp_Phags_Pa },
+ { 2647, PT_SC, ucp_Inscriptional_Pahlavi },
+ { 2652, PT_SCX, ucp_Psalter_Pahlavi },
+ { 2657, PT_SC, ucp_Phoenician },
+ { 2662, PT_SC, ucp_Phoenician },
+ { 2673, PT_PC, ucp_Pi },
+ { 2676, PT_SC, ucp_Miao },
+ { 2681, PT_PC, ucp_Po },
+ { 2684, PT_BOOL, ucp_Prepended_Concatenation_Mark },
+ { 2711, PT_SC, ucp_Inscriptional_Parthian },
+ { 2716, PT_PC, ucp_Ps },
+ { 2719, PT_SCX, ucp_Psalter_Pahlavi },
+ { 2734, PT_SCX, ucp_Coptic },
+ { 2739, PT_SC, ucp_Inherited },
+ { 2744, PT_BOOL, ucp_Quotation_Mark },
+ { 2750, PT_BOOL, ucp_Quotation_Mark },
+ { 2764, PT_BOOL, ucp_Radical },
+ { 2772, PT_BOOL, ucp_Regional_Indicator },
+ { 2790, PT_SC, ucp_Rejang },
+ { 2797, PT_BOOL, ucp_Regional_Indicator },
+ { 2800, PT_SC, ucp_Rejang },
+ { 2805, PT_SCX, ucp_Hanifi_Rohingya },
+ { 2810, PT_SC, ucp_Runic },
+ { 2816, PT_SC, ucp_Runic },
+ { 2821, PT_GC, ucp_S },
+ { 2823, PT_SC, ucp_Samaritan },
+ { 2833, PT_SC, ucp_Samaritan },
+ { 2838, PT_SC, ucp_Old_South_Arabian },
+ { 2843, PT_SC, ucp_Saurashtra },
+ { 2848, PT_SC, ucp_Saurashtra },
+ { 2859, PT_PC, ucp_Sc },
+ { 2862, PT_BOOL, ucp_Soft_Dotted },
+ { 2865, PT_BOOL, ucp_Sentence_Terminal },
+ { 2882, PT_SC, ucp_SignWriting },
+ { 2887, PT_SCX, ucp_Sharada },
+ { 2895, PT_SC, ucp_Shavian },
+ { 2903, PT_SC, ucp_Shavian },
+ { 2908, PT_SCX, ucp_Sharada },
+ { 2913, PT_SC, ucp_Siddham },
+ { 2918, PT_SC, ucp_Siddham },
+ { 2926, PT_SC, ucp_SignWriting },
+ { 2938, PT_SCX, ucp_Khudawadi },
+ { 2943, PT_SCX, ucp_Sinhala },
+ { 2948, PT_SCX, ucp_Sinhala },
+ { 2956, PT_PC, ucp_Sk },
+ { 2959, PT_PC, ucp_Sm },
+ { 2962, PT_PC, ucp_So },
+ { 2965, PT_BOOL, ucp_Soft_Dotted },
+ { 2976, PT_SCX, ucp_Sogdian },
+ { 2981, PT_SCX, ucp_Sogdian },
+ { 2989, PT_SC, ucp_Old_Sogdian },
+ { 2994, PT_SC, ucp_Sora_Sompeng },
+ { 2999, PT_SC, ucp_Sora_Sompeng },
+ { 3011, PT_SC, ucp_Soyombo },
+ { 3016, PT_SC, ucp_Soyombo },
+ { 3024, PT_BOOL, ucp_White_Space },
+ { 3030, PT_BOOL, ucp_Sentence_Terminal },
+ { 3036, PT_SC, ucp_Sundanese },
+ { 3041, PT_SC, ucp_Sundanese },
+ { 3051, PT_SCX, ucp_Syloti_Nagri },
+ { 3056, PT_SCX, ucp_Syloti_Nagri },
+ { 3068, PT_SCX, ucp_Syriac },
+ { 3073, PT_SCX, ucp_Syriac },
+ { 3080, PT_SCX, ucp_Tagalog },
+ { 3088, PT_SCX, ucp_Tagbanwa },
+ { 3093, PT_SCX, ucp_Tagbanwa },
+ { 3102, PT_SCX, ucp_Tai_Le },
+ { 3108, PT_SC, ucp_Tai_Tham },
+ { 3116, PT_SC, ucp_Tai_Viet },
+ { 3124, PT_SCX, ucp_Takri },
+ { 3129, PT_SCX, ucp_Takri },
+ { 3135, PT_SCX, ucp_Tai_Le },
+ { 3140, PT_SC, ucp_New_Tai_Lue },
+ { 3145, PT_SCX, ucp_Tamil },
+ { 3151, PT_SCX, ucp_Tamil },
+ { 3156, PT_SC, ucp_Tangut },
+ { 3161, PT_SC, ucp_Tangsa },
+ { 3168, PT_SC, ucp_Tangut },
+ { 3175, PT_SC, ucp_Tai_Viet },
+ { 3180, PT_SCX, ucp_Telugu },
+ { 3185, PT_SCX, ucp_Telugu },
+ { 3192, PT_BOOL, ucp_Terminal_Punctuation },
+ { 3197, PT_BOOL, ucp_Terminal_Punctuation },
+ { 3217, PT_SC, ucp_Tifinagh },
+ { 3222, PT_SCX, ucp_Tagalog },
+ { 3227, PT_SCX, ucp_Thaana },
+ { 3232, PT_SCX, ucp_Thaana },
+ { 3239, PT_SC, ucp_Thai },
+ { 3244, PT_SC, ucp_Tibetan },
+ { 3252, PT_SC, ucp_Tibetan },
+ { 3257, PT_SC, ucp_Tifinagh },
+ { 3266, PT_SCX, ucp_Tirhuta },
+ { 3271, PT_SCX, ucp_Tirhuta },
+ { 3279, PT_SC, ucp_Tangsa },
+ { 3284, PT_SC, ucp_Toto },
+ { 3289, PT_SC, ucp_Ugaritic },
+ { 3294, PT_SC, ucp_Ugaritic },
+ { 3303, PT_BOOL, ucp_Unified_Ideograph },
+ { 3309, PT_BOOL, ucp_Unified_Ideograph },
+ { 3326, PT_SC, ucp_Unknown },
+ { 3334, PT_BOOL, ucp_Uppercase },
+ { 3340, PT_BOOL, ucp_Uppercase },
+ { 3350, PT_SC, ucp_Vai },
+ { 3354, PT_SC, ucp_Vai },
+ { 3359, PT_BOOL, ucp_Variation_Selector },
+ { 3377, PT_SC, ucp_Vithkuqi },
+ { 3382, PT_SC, ucp_Vithkuqi },
+ { 3391, PT_BOOL, ucp_Variation_Selector },
+ { 3394, PT_SC, ucp_Wancho },
+ { 3401, PT_SC, ucp_Warang_Citi },
+ { 3406, PT_SC, ucp_Warang_Citi },
+ { 3417, PT_SC, ucp_Wancho },
+ { 3422, PT_BOOL, ucp_White_Space },
+ { 3433, PT_BOOL, ucp_White_Space },
+ { 3440, PT_ALNUM, 0 },
+ { 3444, PT_BOOL, ucp_XID_Continue },
+ { 3449, PT_BOOL, ucp_XID_Continue },
+ { 3461, PT_BOOL, ucp_XID_Start },
+ { 3466, PT_BOOL, ucp_XID_Start },
+ { 3475, PT_SC, ucp_Old_Persian },
+ { 3480, PT_PXSPACE, 0 },
+ { 3484, PT_SPACE, 0 },
+ { 3488, PT_SC, ucp_Cuneiform },
+ { 3493, PT_UCNC, 0 },
+ { 3497, PT_WORD, 0 },
+ { 3501, PT_SCX, ucp_Yezidi },
+ { 3506, PT_SCX, ucp_Yezidi },
+ { 3513, PT_SCX, ucp_Yi },
+ { 3516, PT_SCX, ucp_Yi },
+ { 3521, PT_GC, ucp_Z },
+ { 3523, PT_SC, ucp_Zanabazar_Square },
+ { 3539, PT_SC, ucp_Zanabazar_Square },
+ { 3544, PT_SC, ucp_Inherited },
+ { 3549, PT_PC, ucp_Zl },
+ { 3552, PT_PC, ucp_Zp },
+ { 3555, PT_PC, ucp_Zs },
+ { 3558, PT_SC, ucp_Common },
+ { 3563, PT_SC, ucp_Unknown }
+};
+
+const size_t PRIV(utt_size) = sizeof(PRIV(utt)) / sizeof(ucp_type_table);
+
+#endif /* SUPPORT_UNICODE */
+
+/* End of pcre2_ucptables.c */
diff --git a/thirdparty/pcre2/src/pcre2_xclass.c b/thirdparty/pcre2/src/pcre2_xclass.c
index 8b052be66a..bb57196449 100644
--- a/thirdparty/pcre2/src/pcre2_xclass.c
+++ b/thirdparty/pcre2/src/pcre2_xclass.c
@@ -7,7 +7,7 @@ and semantics are as close as possible to those of the Perl 5 language.
Written by Philip Hazel
Original API code Copyright (c) 1997-2012 University of Cambridge
- New API code Copyright (c) 2016-2019 University of Cambridge
+ New API code Copyright (c) 2016-2022 University of Cambridge
-----------------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,7 @@ while ((t = *data++) != XCL_END)
{
const ucd_record *prop = GET_UCD(c);
BOOL isprop = t == XCL_PROP;
+ BOOL ok;
switch(*data)
{
@@ -160,6 +161,12 @@ while ((t = *data++) != XCL_END)
if ((data[1] == prop->script) == isprop) return !negated;
break;
+ case PT_SCX:
+ ok = (data[1] == prop->script ||
+ MAPBIT(PRIV(ucd_script_sets) + UCD_SCRIPTX_PROP(prop), data[1]) != 0);
+ if (ok == isprop) return !negated;
+ break;
+
case PT_ALNUM:
if ((PRIV(ucp_gentype)[prop->chartype] == ucp_L ||
PRIV(ucp_gentype)[prop->chartype] == ucp_N) == isprop)
@@ -207,6 +214,17 @@ while ((t = *data++) != XCL_END)
}
break;
+ case PT_BIDICL:
+ if ((UCD_BIDICLASS_PROP(prop) == data[1]) == isprop)
+ return !negated;
+ break;
+
+ case PT_BOOL:
+ ok = MAPBIT(PRIV(ucd_boolprop_sets) +
+ UCD_BPROPS_PROP(prop), data[1]) != 0;
+ if (ok == isprop) return !negated;
+ break;
+
/* The following three properties can occur only in an XCLASS, as there
is no \p or \P coding for them. */
diff --git a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
index 7bb9990a59..55e4e39f13 100644
--- a/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
+++ b/thirdparty/pcre2/src/sljit/sljitConfigInternal.h
@@ -60,7 +60,7 @@ extern "C" {
SLJIT_LITTLE_ENDIAN : little endian architecture
SLJIT_BIG_ENDIAN : big endian architecture
SLJIT_UNALIGNED : allows unaligned memory accesses for non-fpu operations (only!)
- SLJIT_INDIRECT_CALL : see SLJIT_FUNC_OFFSET() for more information
+ SLJIT_INDIRECT_CALL : see SLJIT_FUNC_ADDR() for more information
Constants:
SLJIT_NUMBER_OF_REGISTERS : number of available registers
@@ -148,7 +148,7 @@ extern "C" {
#endif
#elif defined (__aarch64__)
#define SLJIT_CONFIG_ARM_64 1
-#elif defined(__ppc64__) || defined(__powerpc64__) || defined(_ARCH_PPC64) || (defined(_POWER) && defined(__64BIT__))
+#elif defined(__ppc64__) || defined(__powerpc64__) || (defined(_ARCH_PPC64) && defined(__64BIT__)) || (defined(_POWER) && defined(__64BIT__))
#define SLJIT_CONFIG_PPC_64 1
#elif defined(__ppc__) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(_ARCH_PWR) || defined(_ARCH_PWR2) || defined(_POWER)
#define SLJIT_CONFIG_PPC_32 1
@@ -156,7 +156,7 @@ extern "C" {
#define SLJIT_CONFIG_MIPS_32 1
#elif defined(__mips64)
#define SLJIT_CONFIG_MIPS_64 1
-#elif defined(__sparc__) || defined(__sparc)
+#elif (defined(__sparc__) || defined(__sparc)) && !defined(_LP64)
#define SLJIT_CONFIG_SPARC_32 1
#elif defined(__s390x__)
#define SLJIT_CONFIG_S390X 1
@@ -274,9 +274,13 @@ extern "C" {
#ifndef SLJIT_INLINE
/* Inline functions. Some old compilers do not support them. */
-#if defined(__SUNPRO_C) && __SUNPRO_C <= 0x510
+#ifdef __SUNPRO_C
+#if __SUNPRO_C < 0x560
#define SLJIT_INLINE
#else
+#define SLJIT_INLINE inline
+#endif /* __SUNPRO_C */
+#else
#define SLJIT_INLINE __inline
#endif
#endif /* !SLJIT_INLINE */
@@ -319,18 +323,36 @@ extern "C" {
/* Instruction cache flush. */
/****************************/
+/*
+ * TODO:
+ *
+ * clang >= 15 could be safe to enable below
+ * older versions are known to abort in some targets
+ * https://github.com/PhilipHazel/pcre2/issues/92
+ *
+ * beware APPLE is known to have removed the code in iOS so
+ * it will need to be excempted or result in broken builds
+ */
#if (!defined SLJIT_CACHE_FLUSH && defined __has_builtin)
-#if __has_builtin(__builtin___clear_cache)
+#if __has_builtin(__builtin___clear_cache) && !defined(__clang__)
+/*
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=91248
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=93811
+ * gcc's clear_cache builtin for power and sparc are broken
+ */
+#if !defined(SLJIT_CONFIG_PPC) && !defined(SLJIT_CONFIG_SPARC_32)
#define SLJIT_CACHE_FLUSH(from, to) \
__builtin___clear_cache((char*)(from), (char*)(to))
+#endif
-#endif /* __has_builtin(__builtin___clear_cache) */
+#endif /* gcc >= 10 */
#endif /* (!defined SLJIT_CACHE_FLUSH && defined __has_builtin) */
#ifndef SLJIT_CACHE_FLUSH
-#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86)
+#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
+ || (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
/* Not required to implement on archs with unified caches. */
#define SLJIT_CACHE_FLUSH(from, to)
@@ -340,9 +362,9 @@ extern "C" {
/* Supported by all macs since Mac OS 10.5.
However, it does not work on non-jailbroken iOS devices,
although the compilation is successful. */
-
+#include <libkern/OSCacheControl.h>
#define SLJIT_CACHE_FLUSH(from, to) \
- sys_icache_invalidate((char*)(from), (char*)(to) - (char*)(from))
+ sys_icache_invalidate((void*)(from), (size_t)((char*)(to) - (char*)(from)))
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
@@ -351,33 +373,33 @@ extern "C" {
ppc_cache_flush((from), (to))
#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
-#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
+#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
#define SLJIT_CACHE_FLUSH(from, to) \
- __builtin___clear_cache((char*)(from), (char*)(to))
-
-#elif defined __ANDROID__
+ sparc_cache_flush((from), (to))
+#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
-/* Android lacks __clear_cache; instead, cacheflush should be used. */
+#elif (defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || defined(__clang__)
#define SLJIT_CACHE_FLUSH(from, to) \
- cacheflush((long)(from), (long)(to), 0)
+ __builtin___clear_cache((char*)(from), (char*)(to))
-#elif (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
+#elif defined __ANDROID__
-/* The __clear_cache() implementation of GCC is a dummy function on Sparc. */
+/* Android ARMv7 with gcc lacks __clear_cache; use cacheflush instead. */
+#include <sys/cachectl.h>
#define SLJIT_CACHE_FLUSH(from, to) \
- sparc_cache_flush((from), (to))
-#define SLJIT_CACHE_FLUSH_OWN_IMPL 1
+ cacheflush((long)(from), (long)(to), 0)
#elif defined _WIN32
#define SLJIT_CACHE_FLUSH(from, to) \
- FlushInstructionCache(GetCurrentProcess(), (char*)(from), (char*)(to) - (char*)(from))
+ FlushInstructionCache(GetCurrentProcess(), (void*)(from), (char*)(to) - (char*)(from))
#else
-/* Calls __ARM_NR_cacheflush on ARM-Linux. */
+/* Call __ARM_NR_cacheflush on ARM-Linux or the corresponding MIPS syscall. */
#define SLJIT_CACHE_FLUSH(from, to) \
__clear_cache((char*)(from), (char*)(to))
@@ -645,18 +667,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 9
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 7
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
#define SLJIT_PREF_SHIFT_REG SLJIT_R2
#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#define SLJIT_NUMBER_OF_REGISTERS 13
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
#ifndef _WIN64
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 6
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE 0
#else /* _WIN64 */
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
-#define SLJIT_LOCALS_OFFSET_BASE (compiler->locals_offset)
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 10
+#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
#endif /* !_WIN64 */
#define SLJIT_PREF_SHIFT_REG SLJIT_R3
@@ -664,31 +691,39 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE 0
#elif (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
#define SLJIT_NUMBER_OF_REGISTERS 26
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 10
-#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
+#define SLJIT_LOCALS_OFFSET_BASE (2 * (sljit_s32)sizeof(sljit_sw))
#elif (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
#define SLJIT_NUMBER_OF_REGISTERS 23
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 17
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 30
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 18
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) || (defined _AIX)
-#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE ((6 + 8) * (sljit_s32)sizeof(sljit_sw))
#elif (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
/* Add +1 for double alignment. */
-#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE ((3 + 1) * (sljit_s32)sizeof(sljit_sw))
#else
-#define SLJIT_LOCALS_OFFSET_BASE (3 * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (3 * (sljit_s32)sizeof(sljit_sw))
#endif /* SLJIT_CONFIG_PPC_64 || _AIX */
#elif (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
@@ -696,19 +731,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_REGISTERS 21
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-#define SLJIT_LOCALS_OFFSET_BASE (4 * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE (4 * (sljit_s32)sizeof(sljit_sw))
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 13
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 6
#else
#define SLJIT_LOCALS_OFFSET_BASE 0
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 29
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#endif
#elif (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
#define SLJIT_NUMBER_OF_REGISTERS 18
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 14
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 14
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
/* saved registers (16), return struct pointer (1), space for 6 argument words (1),
4th double arg (2), double alignment (1). */
-#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * sizeof(sljit_sw))
+#define SLJIT_LOCALS_OFFSET_BASE ((16 + 1 + 6 + 2 + 1) * (sljit_s32)sizeof(sljit_sw))
#endif
#elif (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
@@ -736,12 +777,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_REGISTERS 12
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 8
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 15
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 8
#define SLJIT_LOCALS_OFFSET_BASE SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE
#elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
#define SLJIT_NUMBER_OF_REGISTERS 0
#define SLJIT_NUMBER_OF_SAVED_REGISTERS 0
+#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 0
+#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
#define SLJIT_LOCALS_OFFSET_BASE 0
#endif
@@ -751,13 +796,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
#define SLJIT_NUMBER_OF_SCRATCH_REGISTERS \
(SLJIT_NUMBER_OF_REGISTERS - SLJIT_NUMBER_OF_SAVED_REGISTERS)
-#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && (defined _WIN64)
-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1
-#else
-#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 0
-#endif
-
#define SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS \
(SLJIT_NUMBER_OF_FLOAT_REGISTERS - SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS)
@@ -765,8 +803,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_sw sljit_exec_offset(void* ptr);
/* CPU status flags management. */
/********************************/
-#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) \
- || (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64) \
+#if (defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM) \
+ || (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS) \
|| (defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC) \
|| (defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
diff --git a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
index 6e5bf78e45..6359848cd5 100644
--- a/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
+++ b/thirdparty/pcre2/src/sljit/sljitExecAllocator.c
@@ -66,7 +66,7 @@
/* --------------------------------------------------------------------- */
/* 64 KByte. */
-#define CHUNK_SIZE 0x10000
+#define CHUNK_SIZE (sljit_uw)0x10000u
/*
alloc_chunk / free_chunk :
@@ -112,7 +112,7 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
static SLJIT_INLINE int get_map_jit_flag()
{
- sljit_sw page_size;
+ size_t page_size;
void *ptr;
struct utsname name;
static int map_jit_flag = -1;
@@ -139,8 +139,9 @@ static SLJIT_INLINE int get_map_jit_flag()
#endif /* MAP_ANON */
#else /* !SLJIT_CONFIG_X86 */
#if !(defined SLJIT_CONFIG_ARM && SLJIT_CONFIG_ARM)
-#error Unsupported architecture
+#error "Unsupported architecture"
#endif /* SLJIT_CONFIG_ARM */
+#include <AvailabilityMacros.h>
#include <pthread.h>
#define SLJIT_MAP_JIT (MAP_JIT)
@@ -149,7 +150,14 @@ static SLJIT_INLINE int get_map_jit_flag()
static SLJIT_INLINE void apple_update_wx_flags(sljit_s32 enable_exec)
{
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
pthread_jit_write_protect_np(enable_exec);
+#elif defined(__clang__)
+ if (__builtin_available(macOS 11.0, *))
+ pthread_jit_write_protect_np(enable_exec);
+#else
+#error "Must target Big Sur or newer"
+#endif /* BigSur */
}
#endif /* SLJIT_CONFIG_X86 */
#else /* !TARGET_OS_OSX */
@@ -187,10 +195,13 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
if (retval == MAP_FAILED)
return NULL;
+#ifdef __FreeBSD__
+ /* HardenedBSD's mmap lies, so check permissions again */
if (mprotect(retval, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
munmap(retval, size);
return NULL;
}
+#endif /* FreeBSD */
SLJIT_UPDATE_WX_FLAGS(retval, (uint8_t *)retval + size, 0);
@@ -227,7 +238,7 @@ struct free_block {
#define AS_FREE_BLOCK(base, offset) \
((struct free_block*)(((sljit_u8*)base) + offset))
#define MEM_START(base) ((void*)(((sljit_u8*)base) + sizeof(struct block_header)))
-#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
static struct free_block* free_blocks;
static sljit_uw allocated_size;
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.c b/thirdparty/pcre2/src/sljit/sljitLir.c
index a24a99ab87..313a061dd3 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.c
+++ b/thirdparty/pcre2/src/sljit/sljitLir.c
@@ -90,26 +90,28 @@
#if !(defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED)
+#define SSIZE_OF(type) ((sljit_s32)sizeof(sljit_ ## type))
+
#define VARIABLE_FLAG_SHIFT (10)
#define VARIABLE_FLAG_MASK (0x3f << VARIABLE_FLAG_SHIFT)
#define GET_FLAG_TYPE(op) ((op) >> VARIABLE_FLAG_SHIFT)
#define GET_OPCODE(op) \
- ((op) & ~(SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
+ ((op) & ~(SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
#define HAS_FLAGS(op) \
((op) & (SLJIT_SET_Z | VARIABLE_FLAG_MASK))
#define GET_ALL_FLAGS(op) \
- ((op) & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
+ ((op) & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK))
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
#define TYPE_CAST_NEEDED(op) \
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S32)
-#else
+#else /* !SLJIT_64BIT_ARCHITECTURE */
#define TYPE_CAST_NEEDED(op) \
((op) >= SLJIT_MOV_U8 && (op) <= SLJIT_MOV_S16)
-#endif
+#endif /* SLJIT_64BIT_ARCHITECTURE */
#define BUF_SIZE 4096
@@ -126,11 +128,10 @@
#define TO_OFFS_REG(reg) ((reg) << 8)
/* When reg cannot be unused. */
#define FAST_IS_REG(reg) ((reg) <= REG_MASK)
-/* When reg can be unused. */
-#define SLOW_IS_REG(reg) ((reg) > 0 && (reg) <= REG_MASK)
/* Mask for argument types. */
-#define SLJIT_DEF_MASK ((1 << SLJIT_DEF_SHIFT) - 1)
+#define SLJIT_ARG_MASK 0x7
+#define SLJIT_ARG_FULL_MASK (SLJIT_ARG_MASK | SLJIT_ARG_TYPE_SCRATCH_REG)
/* Jump flags. */
#define JUMP_LABEL 0x1
@@ -247,8 +248,11 @@
#define GET_SAVED_REGISTERS_SIZE(scratches, saveds, extra) \
(((scratches < SLJIT_NUMBER_OF_SCRATCH_REGISTERS ? 0 : (scratches - SLJIT_NUMBER_OF_SCRATCH_REGISTERS)) + \
- (saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? saveds : SLJIT_NUMBER_OF_SAVED_REGISTERS) + \
- extra) * sizeof(sljit_sw))
+ (saveds) + (sljit_s32)(extra)) * (sljit_s32)sizeof(sljit_sw))
+
+#define GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, size) \
+ (((fscratches < SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS ? 0 : (fscratches - SLJIT_NUMBER_OF_SCRATCH_FLOAT_REGISTERS)) + \
+ (fsaveds)) * (sljit_s32)(size))
#define ADJUST_LOCAL_OFFSET(p, i) \
if ((p) == (SLJIT_MEM1(SLJIT_SP))) \
@@ -379,9 +383,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
&& (sizeof(sljit_sw) == 4 || sizeof(sljit_sw) == 8)
&& (sizeof(sljit_uw) == 4 || sizeof(sljit_uw) == 8),
invalid_integer_types);
- SLJIT_COMPILE_ASSERT(SLJIT_I32_OP == SLJIT_F32_OP,
- int_op_and_single_op_must_be_the_same);
- SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_F32_OP,
+ SLJIT_COMPILE_ASSERT(SLJIT_REWRITABLE_JUMP != SLJIT_32,
rewritable_jump_and_single_op_must_not_be_the_same);
SLJIT_COMPILE_ASSERT(!(SLJIT_EQUAL & 0x1) && !(SLJIT_LESS & 0x1) && !(SLJIT_EQUAL_F64 & 0x1) && !(SLJIT_JUMP & 0x1),
conditional_flags_must_be_even_numbers);
@@ -415,7 +417,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
compiler->local_size = -1;
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- compiler->args = -1;
+ compiler->args_size = -1;
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -439,6 +441,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_compiler* sljit_create_compiler(void *allo
compiler->delay_slot = UNMOVABLE_INS;
#endif
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_DEBUG && SLJIT_DEBUG)
+ compiler->last_flags = 0;
+ compiler->last_return = -1;
+ compiler->logical_local_size = 0;
+#endif
+
#if (defined SLJIT_NEEDS_COMPILER_INIT && SLJIT_NEEDS_COMPILER_INIT)
if (!compiler_initialized) {
init_compiler();
@@ -488,7 +497,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_d
SLJIT_UNUSED_ARG(exec_allocator_data);
/* Remove thumb mode flag. */
- SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~0x1), exec_allocator_data);
+ SLJIT_FREE_EXEC((void*)((sljit_uw)code & ~(sljit_uw)0x1), exec_allocator_data);
}
#elif (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_data)
@@ -511,7 +520,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code, void *exec_allocator_d
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sljit_label* label)
{
if (SLJIT_LIKELY(!!jump) && SLJIT_LIKELY(!!label)) {
- jump->flags &= ~JUMP_ADDR;
+ jump->flags &= (sljit_uw)~JUMP_ADDR;
jump->flags |= JUMP_LABEL;
jump->u.label = label;
}
@@ -520,7 +529,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_label(struct sljit_jump *jump, struct sl
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_target(struct sljit_jump *jump, sljit_uw target)
{
if (SLJIT_LIKELY(!!jump)) {
- jump->flags &= ~JUMP_LABEL;
+ jump->flags &= (sljit_uw)~JUMP_LABEL;
jump->flags |= JUMP_ADDR;
jump->u.target = target;
}
@@ -533,7 +542,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_put_label(struct sljit_put_label *put_la
}
#define SLJIT_CURRENT_FLAGS_ALL \
- (SLJIT_CURRENT_FLAGS_I32_OP | SLJIT_CURRENT_FLAGS_ADD_SUB | SLJIT_CURRENT_FLAGS_COMPARE)
+ (SLJIT_CURRENT_FLAGS_32 | SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB | SLJIT_CURRENT_FLAGS_COMPARE)
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *compiler, sljit_s32 current_flags)
{
@@ -547,7 +556,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_current_flags(struct sljit_compiler *com
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->last_flags = 0;
if ((current_flags & ~(VARIABLE_FLAG_MASK | SLJIT_SET_Z | SLJIT_CURRENT_FLAGS_ALL)) == 0) {
- compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_I32_OP | SLJIT_SET_Z));
+ compiler->last_flags = GET_FLAG_TYPE(current_flags) | (current_flags & (SLJIT_32 | SLJIT_SET_Z));
}
#endif
}
@@ -607,7 +616,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_alloc_memory(struct sljit_compiler *compile
return NULL;
size = (size + 3) & ~3;
#endif
- return ensure_abuf(compiler, size);
+ return ensure_abuf(compiler, (sljit_uw)size);
}
static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
@@ -626,20 +635,6 @@ static SLJIT_INLINE void reverse_buf(struct sljit_compiler *compiler)
compiler->buf = prev;
}
-static SLJIT_INLINE sljit_s32 get_arg_count(sljit_s32 arg_types)
-{
- sljit_s32 arg_count = 0;
-
- arg_types >>= SLJIT_DEF_SHIFT;
- while (arg_types) {
- arg_count++;
- arg_types >>= SLJIT_DEF_SHIFT;
- }
-
- return arg_count;
-}
-
-
/* Only used in RISC architectures where the instruction size is constant */
#if !(defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
&& !(defined SLJIT_CONFIG_S390X && SLJIT_CONFIG_S390X)
@@ -679,6 +674,7 @@ static SLJIT_INLINE void set_emit_enter(struct sljit_compiler *compiler,
compiler->fscratches = fscratches;
compiler->fsaveds = fsaveds;
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_return = args & SLJIT_ARG_MASK;
compiler->logical_local_size = local_size;
#endif
}
@@ -696,6 +692,7 @@ static SLJIT_INLINE void set_set_context(struct sljit_compiler *compiler,
compiler->fscratches = fscratches;
compiler->fsaveds = fsaveds;
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->last_return = args & SLJIT_ARG_MASK;
compiler->logical_local_size = local_size;
#endif
}
@@ -711,7 +708,7 @@ static SLJIT_INLINE void set_label(struct sljit_label *label, struct sljit_compi
compiler->last_label = label;
}
-static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_s32 flags)
+static SLJIT_INLINE void set_jump(struct sljit_jump *jump, struct sljit_compiler *compiler, sljit_u32 flags)
{
jump->next = NULL;
jump->flags = flags;
@@ -751,6 +748,58 @@ static SLJIT_INLINE void set_put_label(struct sljit_put_label *put_label, struct
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+static sljit_s32 function_check_arguments(sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds, sljit_s32 fscratches)
+{
+ sljit_s32 word_arg_count, scratch_arg_end, saved_arg_count, float_arg_count, curr_type;
+
+ curr_type = (arg_types & SLJIT_ARG_FULL_MASK);
+
+ if (curr_type >= SLJIT_ARG_TYPE_F64) {
+ if (curr_type > SLJIT_ARG_TYPE_F32 || fscratches == 0)
+ return 0;
+ } else if (curr_type >= SLJIT_ARG_TYPE_W) {
+ if (scratches == 0)
+ return 0;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ word_arg_count = 0;
+ scratch_arg_end = 0;
+ saved_arg_count = 0;
+ float_arg_count = 0;
+ while (arg_types != 0) {
+ if (word_arg_count + float_arg_count >= 4)
+ return 0;
+
+ curr_type = (arg_types & SLJIT_ARG_MASK);
+
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ if (saveds == -1 || curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_P)
+ return 0;
+
+ word_arg_count++;
+ scratch_arg_end = word_arg_count;
+ } else {
+ if (curr_type < SLJIT_ARG_TYPE_W || curr_type > SLJIT_ARG_TYPE_F32)
+ return 0;
+
+ if (curr_type < SLJIT_ARG_TYPE_F64) {
+ word_arg_count++;
+ saved_arg_count++;
+ } else
+ float_arg_count++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (saveds == -1)
+ return (word_arg_count <= scratches && float_arg_count <= fscratches);
+
+ return (saved_arg_count <= saveds && scratch_arg_end <= scratches && float_arg_count <= fscratches);
+}
+
#define FUNCTION_CHECK_IS_REG(r) \
(((r) >= SLJIT_R0 && (r) < (SLJIT_R0 + compiler->scratches)) \
|| ((r) > (SLJIT_S0 - compiler->saveds) && (r) <= SLJIT_S0))
@@ -773,14 +822,14 @@ static sljit_s32 function_check_src_mem(struct sljit_compiler *compiler, sljit_s
if (!(p & SLJIT_MEM))
return 0;
- if (!((p & REG_MASK) == SLJIT_UNUSED || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
+ if (!(!(p & REG_MASK) || FUNCTION_CHECK_IS_REG(p & REG_MASK)))
return 0;
if (CHECK_IF_VIRTUAL_REGISTER(p & REG_MASK))
return 0;
if (p & OFFS_REG_MASK) {
- if ((p & REG_MASK) == SLJIT_UNUSED)
+ if (!(p & REG_MASK))
return 0;
if (!(FUNCTION_CHECK_IS_REG(OFFS_REG(p))))
@@ -819,12 +868,12 @@ static sljit_s32 function_check_src(struct sljit_compiler *compiler, sljit_s32 p
#define FUNCTION_CHECK_SRC(p, i) \
CHECK_ARGUMENT(function_check_src(compiler, p, i));
-static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i, sljit_s32 unused)
+static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
if (compiler->scratches == -1 || compiler->saveds == -1)
return 0;
- if (FUNCTION_CHECK_IS_REG(p) || ((unused) && (p) == SLJIT_UNUSED))
+ if (FUNCTION_CHECK_IS_REG(p))
return (i == 0);
if (p == SLJIT_MEM1(SLJIT_SP))
@@ -833,8 +882,8 @@ static sljit_s32 function_check_dst(struct sljit_compiler *compiler, sljit_s32 p
return function_check_src_mem(compiler, p, i);
}
-#define FUNCTION_CHECK_DST(p, i, unused) \
- CHECK_ARGUMENT(function_check_dst(compiler, p, i, unused));
+#define FUNCTION_CHECK_DST(p, i) \
+ CHECK_ARGUMENT(function_check_dst(compiler, p, i));
static sljit_s32 function_fcheck(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
{
@@ -910,10 +959,8 @@ static void sljit_verbose_param(struct sljit_compiler *compiler, sljit_s32 p, sl
}
else
fprintf(compiler->verbose, "[#%" SLJIT_PRINT_D "d]", (i));
- } else if (p)
+ } else
sljit_verbose_reg(compiler, p);
- else
- fprintf(compiler->verbose, "unused");
}
static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, sljit_sw i)
@@ -940,63 +987,61 @@ static void sljit_verbose_fparam(struct sljit_compiler *compiler, sljit_s32 p, s
}
static const char* op0_names[] = {
- (char*)"breakpoint", (char*)"nop", (char*)"lmul.uw", (char*)"lmul.sw",
- (char*)"divmod.u", (char*)"divmod.s", (char*)"div.u", (char*)"div.s",
- (char*)"endbr", (char*)"skip_frames_before_return"
+ "breakpoint", "nop", "lmul.uw", "lmul.sw",
+ "divmod.u", "divmod.s", "div.u", "div.s",
+ "endbr", "skip_frames_before_return"
};
static const char* op1_names[] = {
- (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",
- (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",
- (char*)"", (char*)".u8", (char*)".s8", (char*)".u16",
- (char*)".s16", (char*)".u32", (char*)".s32", (char*)".p",
- (char*)"not", (char*)"neg", (char*)"clz",
+ "", ".u8", ".s8", ".u16",
+ ".s16", ".u32", ".s32", "32",
+ ".p", "not", "clz",
};
static const char* op2_names[] = {
- (char*)"add", (char*)"addc", (char*)"sub", (char*)"subc",
- (char*)"mul", (char*)"and", (char*)"or", (char*)"xor",
- (char*)"shl", (char*)"lshr", (char*)"ashr",
+ "add", "addc", "sub", "subc",
+ "mul", "and", "or", "xor",
+ "shl", "lshr", "ashr",
};
static const char* op_src_names[] = {
- (char*)"fast_return", (char*)"skip_frames_before_fast_return",
- (char*)"prefetch_l1", (char*)"prefetch_l2",
- (char*)"prefetch_l3", (char*)"prefetch_once",
+ "fast_return", "skip_frames_before_fast_return",
+ "prefetch_l1", "prefetch_l2",
+ "prefetch_l3", "prefetch_once",
};
static const char* fop1_names[] = {
- (char*)"mov", (char*)"conv", (char*)"conv", (char*)"conv",
- (char*)"conv", (char*)"conv", (char*)"cmp", (char*)"neg",
- (char*)"abs",
+ "mov", "conv", "conv", "conv",
+ "conv", "conv", "cmp", "neg",
+ "abs",
};
static const char* fop2_names[] = {
- (char*)"add", (char*)"sub", (char*)"mul", (char*)"div"
+ "add", "sub", "mul", "div"
};
#define JUMP_POSTFIX(type) \
- ((type & 0xff) <= SLJIT_NOT_OVERFLOW ? ((type & SLJIT_I32_OP) ? "32" : "") \
- : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_F32_OP) ? ".f32" : ".f64") : ""))
-
-static char* jump_names[] = {
- (char*)"equal", (char*)"not_equal",
- (char*)"less", (char*)"greater_equal",
- (char*)"greater", (char*)"less_equal",
- (char*)"sig_less", (char*)"sig_greater_equal",
- (char*)"sig_greater", (char*)"sig_less_equal",
- (char*)"overflow", (char*)"not_overflow",
- (char*)"carry", (char*)"",
- (char*)"equal", (char*)"not_equal",
- (char*)"less", (char*)"greater_equal",
- (char*)"greater", (char*)"less_equal",
- (char*)"unordered", (char*)"ordered",
- (char*)"jump", (char*)"fast_call",
- (char*)"call", (char*)"call.cdecl"
+ ((type & 0xff) <= SLJIT_NOT_OVERFLOW ? ((type & SLJIT_32) ? "32" : "") \
+ : ((type & 0xff) <= SLJIT_ORDERED_F64 ? ((type & SLJIT_32) ? ".f32" : ".f64") : ""))
+
+static const char* jump_names[] = {
+ "equal", "not_equal",
+ "less", "greater_equal",
+ "greater", "less_equal",
+ "sig_less", "sig_greater_equal",
+ "sig_greater", "sig_less_equal",
+ "overflow", "not_overflow",
+ "carry", "",
+ "equal", "not_equal",
+ "less", "greater_equal",
+ "greater", "less_equal",
+ "unordered", "ordered",
+ "jump", "fast_call",
+ "call", "call.cdecl"
};
-static char* call_arg_names[] = {
- (char*)"void", (char*)"sw", (char*)"uw", (char*)"s32", (char*)"u32", (char*)"f32", (char*)"f64"
+static const char* call_arg_names[] = {
+ "void", "w", "32", "p", "f64", "f32"
};
#endif /* SLJIT_VERBOSE */
@@ -1032,48 +1077,40 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_enter(struct sljit_compil
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- sljit_s32 types, arg_count, curr_type;
-#endif
-
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
+ CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL));
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
- CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
- CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
- CHECK_ARGUMENT((arg_types & SLJIT_DEF_MASK) == 0);
-
- types = (arg_types >> SLJIT_DEF_SHIFT);
- arg_count = 0;
- while (types != 0 && arg_count < 3) {
- curr_type = (types & SLJIT_DEF_MASK);
- CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);
- arg_count++;
- types >>= SLJIT_DEF_SHIFT;
- }
- CHECK_ARGUMENT(arg_count <= saveds && types == 0);
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches));
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " enter options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");
-
- arg_types >>= SLJIT_DEF_SHIFT;
- while (arg_types) {
- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
- if (arg_types)
- fprintf(compiler->verbose, ",");
+ fprintf(compiler->verbose, " enter ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
}
- fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
+ fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
+ (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "",
scratches, saveds, fscratches, fsaveds, local_size);
}
#endif
@@ -1084,74 +1121,94 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_set_context(struct sljit_compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
-#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- sljit_s32 types, arg_count, curr_type;
-#endif
-
SLJIT_UNUSED_ARG(compiler);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(options & ~SLJIT_F64_ALIGNMENT));
+ CHECK_ARGUMENT(!(options & ~SLJIT_ENTER_CDECL));
CHECK_ARGUMENT(scratches >= 0 && scratches <= SLJIT_NUMBER_OF_REGISTERS);
- CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_REGISTERS);
+ CHECK_ARGUMENT(saveds >= 0 && saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS);
CHECK_ARGUMENT(scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS);
CHECK_ARGUMENT(fscratches >= 0 && fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
- CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
+ CHECK_ARGUMENT(fsaveds >= 0 && fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS);
CHECK_ARGUMENT(fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS);
CHECK_ARGUMENT(local_size >= 0 && local_size <= SLJIT_MAX_LOCAL_SIZE);
-
- types = (arg_types >> SLJIT_DEF_SHIFT);
- arg_count = 0;
- while (types != 0 && arg_count < 3) {
- curr_type = (types & SLJIT_DEF_MASK);
- CHECK_ARGUMENT(curr_type == SLJIT_ARG_TYPE_SW || curr_type == SLJIT_ARG_TYPE_UW);
- arg_count++;
- types >>= SLJIT_DEF_SHIFT;
- }
- CHECK_ARGUMENT(arg_count <= saveds && types == 0);
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_FULL_MASK) < SLJIT_ARG_TYPE_F64);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, scratches, saveds, fscratches));
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " set_context options:%s args[", (options & SLJIT_F64_ALIGNMENT) ? "f64_align" : "");
-
- arg_types >>= SLJIT_DEF_SHIFT;
- while (arg_types) {
- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
- if (arg_types)
- fprintf(compiler->verbose, ",");
+ fprintf(compiler->verbose, " set_context ret[%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types) {
+ fprintf(compiler->verbose, "], args[");
+ do {
+ fprintf(compiler->verbose, "%s%s", call_arg_names[arg_types & SLJIT_ARG_MASK],
+ (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? "_r" : "");
+ arg_types >>= SLJIT_ARG_SHIFT;
+ if (arg_types)
+ fprintf(compiler->verbose, ",");
+ } while (arg_types);
}
- fprintf(compiler->verbose, "] scratches:%d saveds:%d fscratches:%d fsaveds:%d local_size:%d\n",
+ fprintf(compiler->verbose, "],%s scratches:%d, saveds:%d, fscratches:%d, fsaveds:%d, local_size:%d\n",
+ (options & SLJIT_ENTER_CDECL) ? " enter:cdecl," : "",
scratches, saveds, fscratches, fsaveds, local_size);
}
#endif
CHECK_RETURN_OK;
}
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ if (SLJIT_UNLIKELY(compiler->skip_checks)) {
+ compiler->skip_checks = 0;
+ CHECK_RETURN_OK;
+ }
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ CHECK_ARGUMENT(compiler->last_return == SLJIT_ARG_TYPE_VOID);
+#endif
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ if (SLJIT_UNLIKELY(!!compiler->verbose)) {
+ fprintf(compiler->verbose, " return_void\n");
+ }
+#endif
+ CHECK_RETURN_OK;
+}
+
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(compiler->scratches >= 0);
- if (op != SLJIT_UNUSED) {
- CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_P);
- FUNCTION_CHECK_SRC(src, srcw);
+
+ switch (compiler->last_return) {
+ case SLJIT_ARG_TYPE_W:
+ CHECK_ARGUMENT(op >= SLJIT_MOV && op <= SLJIT_MOV_S32);
+ break;
+ case SLJIT_ARG_TYPE_32:
+ CHECK_ARGUMENT(op == SLJIT_MOV32 || (op >= SLJIT_MOV32_U8 && op <= SLJIT_MOV32_S16));
+ break;
+ case SLJIT_ARG_TYPE_P:
+ CHECK_ARGUMENT(op == SLJIT_MOV_P);
+ break;
+ default:
+ /* Context not initialized, void, etc. */
+ CHECK_ARGUMENT(0);
+ break;
}
- else
- CHECK_ARGUMENT(src == 0 && srcw == 0);
+ FUNCTION_CHECK_SRC(src, srcw);
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- if (op == SLJIT_UNUSED)
- fprintf(compiler->verbose, " return\n");
- else {
- fprintf(compiler->verbose, " return%s ", op1_names[op - SLJIT_OP1_BASE]);
- sljit_verbose_param(compiler, src, srcw);
- fprintf(compiler->verbose, "\n");
- }
+ fprintf(compiler->verbose, " return%s%s ", !(op & SLJIT_32) ? "" : "32",
+ op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]);
+ sljit_verbose_param(compiler, src, srcw);
+ fprintf(compiler->verbose, "\n");
}
#endif
CHECK_RETURN_OK;
@@ -1160,7 +1217,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_return(struct sljit_compi
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
compiler->last_flags = 0;
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
@@ -1177,7 +1234,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LMUL_SW)
- || ((op & ~SLJIT_I32_OP) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_I32_OP) <= SLJIT_DIV_SW)
+ || ((op & ~SLJIT_32) >= SLJIT_DIVMOD_UW && (op & ~SLJIT_32) <= SLJIT_DIV_SW)
|| (op >= SLJIT_ENDBR && op <= SLJIT_SKIP_FRAMES_BEFORE_RETURN));
CHECK_ARGUMENT(GET_OPCODE(op) < SLJIT_LMUL_UW || GET_OPCODE(op) >= SLJIT_ENDBR || compiler->scratches >= 2);
if ((GET_OPCODE(op) >= SLJIT_LMUL_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) || op == SLJIT_SKIP_FRAMES_BEFORE_RETURN)
@@ -1188,7 +1245,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler
{
fprintf(compiler->verbose, " %s", op0_names[GET_OPCODE(op) - SLJIT_OP0_BASE]);
if (GET_OPCODE(op) >= SLJIT_DIVMOD_UW && GET_OPCODE(op) <= SLJIT_DIV_SW) {
- fprintf(compiler->verbose, (op & SLJIT_I32_OP) ? "32" : "w");
+ fprintf(compiler->verbose, (op & SLJIT_32) ? "32" : "w");
}
fprintf(compiler->verbose, "\n");
}
@@ -1210,43 +1267,39 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
switch (GET_OPCODE(op)) {
case SLJIT_NOT:
- /* Only SLJIT_I32_OP and SLJIT_SET_Z are allowed. */
+ /* Only SLJIT_32 and SLJIT_SET_Z are allowed. */
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
break;
- case SLJIT_NEG:
- CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
- || GET_FLAG_TYPE(op) == SLJIT_OVERFLOW);
- break;
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_P:
/* Nothing allowed */
- CHECK_ARGUMENT(!(op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
+ CHECK_ARGUMENT(!(op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
break;
default:
- /* Only SLJIT_I32_OP is allowed. */
+ /* Only SLJIT_32 is allowed. */
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
break;
}
- FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));
+ FUNCTION_CHECK_DST(dst, dstw);
FUNCTION_CHECK_SRC(src, srcw);
if (GET_OPCODE(op) >= SLJIT_NOT) {
CHECK_ARGUMENT(src != SLJIT_IMM);
- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
}
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (GET_OPCODE(op) <= SLJIT_MOV_P)
{
- fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_I32_OP) ? "" : "32",
- (op != SLJIT_MOV32) ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : "");
+ fprintf(compiler->verbose, " mov%s%s ", !(op & SLJIT_32) ? "" : "32",
+ op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE]);
}
else
{
- fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+ fprintf(compiler->verbose, " %s%s%s%s%s ", op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE], !(op & SLJIT_32) ? "" : "32",
!(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
!(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
}
@@ -1260,7 +1313,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op1(struct sljit_compiler
CHECK_RETURN_OK;
}
-static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
+static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 unset,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
@@ -1302,24 +1355,31 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op2(struct sljit_compiler
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK)
|| GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
CHECK_ARGUMENT((compiler->last_flags & 0xff) == GET_FLAG_TYPE(SLJIT_SET_CARRY));
- CHECK_ARGUMENT((op & SLJIT_I32_OP) == (compiler->last_flags & SLJIT_I32_OP));
+ CHECK_ARGUMENT((op & SLJIT_32) == (compiler->last_flags & SLJIT_32));
break;
default:
SLJIT_UNREACHABLE();
break;
}
- FUNCTION_CHECK_DST(dst, dstw, HAS_FLAGS(op));
+ if (unset) {
+ CHECK_ARGUMENT(HAS_FLAGS(op));
+ } else {
+ FUNCTION_CHECK_DST(dst, dstw);
+ }
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_I32_OP) ? "" : "32",
+ fprintf(compiler->verbose, " %s%s%s%s%s ", op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE], !(op & SLJIT_32) ? "" : "32",
!(op & SLJIT_SET_Z) ? "" : ".z", !(op & VARIABLE_FLAG_MASK) ? "" : ".",
!(op & VARIABLE_FLAG_MASK) ? "" : jump_names[GET_FLAG_TYPE(op)]);
- sljit_verbose_param(compiler, dst, dstw);
+ if (unset)
+ fprintf(compiler->verbose, "unset");
+ else
+ sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
@@ -1376,10 +1436,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_float_register_index(sljit
}
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
- int i;
+ sljit_u32 i;
#endif
SLJIT_UNUSED_ARG(compiler);
@@ -1431,10 +1491,10 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1(struct sljit_compile
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
fprintf(compiler->verbose, " %s%s ", fop1_names[SLJIT_CONV_F64_FROM_F32 - SLJIT_FOP1_BASE],
- (op & SLJIT_F32_OP) ? ".f32.from.f64" : ".f64.from.f32");
+ (op & SLJIT_32) ? ".f32.from.f64" : ".f64.from.f32");
else
fprintf(compiler->verbose, " %s%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
- (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+ (op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
@@ -1450,7 +1510,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
#endif
if (SLJIT_UNLIKELY(compiler->skip_checks)) {
@@ -1469,7 +1529,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_cmp(struct sljit_com
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+ fprintf(compiler->verbose, " %s%s", fop1_names[SLJIT_CMP_F64 - SLJIT_FOP1_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
if (op & VARIABLE_FLAG_MASK) {
fprintf(compiler->verbose, ".%s_f", jump_names[GET_FLAG_TYPE(op)]);
}
@@ -1497,13 +1557,13 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_sw_from_f64(str
CHECK_ARGUMENT(GET_OPCODE(op) >= SLJIT_CONV_SW_FROM_F64 && GET_OPCODE(op) <= SLJIT_CONV_S32_FROM_F64);
CHECK_ARGUMENT(!(op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)));
FUNCTION_FCHECK(src, srcw);
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
(GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64) ? ".s32" : ".sw",
- (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+ (op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src, srcw);
@@ -1532,7 +1592,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop1_conv_f64_from_sw(str
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " %s%s.from%s ", fop1_names[GET_OPCODE(op) - SLJIT_FOP1_BASE],
- (op & SLJIT_F32_OP) ? ".f32" : ".f64",
+ (op & SLJIT_32) ? ".f32" : ".f64",
(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32) ? ".s32" : ".sw");
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
@@ -1558,7 +1618,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fop2(struct sljit_compile
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_F32_OP) ? ".f32" : ".f64");
+ fprintf(compiler->verbose, " %s%s ", fop2_names[GET_OPCODE(op) - SLJIT_FOP2_BASE], (op & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_fparam(compiler, dst, dstw);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src1, src1w);
@@ -1598,15 +1658,17 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_jump(struct sljit_compile
}
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
- CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_FAST_CALL);
- CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_I32_OP));
+ CHECK_ARGUMENT((type & 0xff) < SLJIT_JUMP || !(type & SLJIT_32));
if ((type & 0xff) < SLJIT_JUMP) {
if ((type & 0xff) <= SLJIT_NOT_ZERO)
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
- else
+ else if ((compiler->last_flags & 0xff) == SLJIT_CARRY) {
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CARRY || (type & 0xff) == SLJIT_NOT_CARRY);
+ compiler->last_flags = 0;
+ } else
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));
}
@@ -1623,49 +1685,27 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_call(struct sljit_compile
sljit_s32 arg_types)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- sljit_s32 i, types, curr_type, scratches, fscratches;
-
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP)));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_CALL_RETURN)));
CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
- types = arg_types;
- scratches = 0;
- fscratches = 0;
- for (i = 0; i < 5; i++) {
- curr_type = (types & SLJIT_DEF_MASK);
- CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);
- if (i > 0) {
- if (curr_type == 0) {
- break;
- }
- if (curr_type >= SLJIT_ARG_TYPE_F32)
- fscratches++;
- else
- scratches++;
- } else {
- if (curr_type >= SLJIT_ARG_TYPE_F32) {
- CHECK_ARGUMENT(compiler->fscratches > 0);
- } else if (curr_type >= SLJIT_ARG_TYPE_SW) {
- CHECK_ARGUMENT(compiler->scratches > 0);
- }
- }
- types >>= SLJIT_DEF_SHIFT;
+ if (type & SLJIT_CALL_RETURN) {
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
}
- CHECK_ARGUMENT(compiler->scratches >= scratches);
- CHECK_ARGUMENT(compiler->fscratches >= fscratches);
- CHECK_ARGUMENT(types == 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
- fprintf(compiler->verbose, " %s%s ret[%s", jump_names[type & 0xff],
- !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);
+ fprintf(compiler->verbose, " %s%s%s ret[%s", jump_names[type & 0xff],
+ !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",
+ call_arg_names[arg_types & SLJIT_ARG_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+ arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
@@ -1681,7 +1721,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler
sljit_s32 src2, sljit_sw src2w)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_SIG_LESS_EQUAL);
FUNCTION_CHECK_SRC(src1, src1w);
FUNCTION_CHECK_SRC(src2, src2w);
@@ -1690,7 +1730,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmp(struct sljit_compiler
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " cmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
- jump_names[type & 0xff], (type & SLJIT_I32_OP) ? "32" : "");
+ jump_names[type & 0xff], (type & SLJIT_32) ? "32" : "");
sljit_verbose_param(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src2, src2w);
@@ -1706,7 +1746,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT(sljit_has_cpu_feature(SLJIT_HAS_FPU));
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_F32_OP)));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_REWRITABLE_JUMP | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL_F64 && (type & 0xff) <= SLJIT_ORDERED_F64);
FUNCTION_FCHECK(src1, src1w);
FUNCTION_FCHECK(src2, src2w);
@@ -1715,7 +1755,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fcmp(struct sljit_compile
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " fcmp%s %s%s, ", !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r",
- jump_names[type & 0xff], (type & SLJIT_F32_OP) ? ".f32" : ".f64");
+ jump_names[type & 0xff], (type & SLJIT_32) ? ".f32" : ".f64");
sljit_verbose_fparam(compiler, src1, src1w);
fprintf(compiler->verbose, ", ");
sljit_verbose_fparam(compiler, src2, src2w);
@@ -1752,49 +1792,27 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_icall(struct sljit_compil
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- sljit_s32 i, types, curr_type, scratches, fscratches;
-
- CHECK_ARGUMENT(type == SLJIT_CALL || type == SLJIT_CALL_CDECL);
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_CALL_RETURN)));
+ CHECK_ARGUMENT((type & 0xff) == SLJIT_CALL || (type & 0xff) == SLJIT_CALL_CDECL);
+ CHECK_ARGUMENT(function_check_arguments(arg_types, compiler->scratches, -1, compiler->fscratches));
FUNCTION_CHECK_SRC(src, srcw);
- types = arg_types;
- scratches = 0;
- fscratches = 0;
- for (i = 0; i < 5; i++) {
- curr_type = (types & SLJIT_DEF_MASK);
- CHECK_ARGUMENT(curr_type <= SLJIT_ARG_TYPE_F64);
- if (i > 0) {
- if (curr_type == 0) {
- break;
- }
- if (curr_type >= SLJIT_ARG_TYPE_F32)
- fscratches++;
- else
- scratches++;
- } else {
- if (curr_type >= SLJIT_ARG_TYPE_F32) {
- CHECK_ARGUMENT(compiler->fscratches > 0);
- } else if (curr_type >= SLJIT_ARG_TYPE_SW) {
- CHECK_ARGUMENT(compiler->scratches > 0);
- }
- }
- types >>= SLJIT_DEF_SHIFT;
+ if (type & SLJIT_CALL_RETURN) {
+ CHECK_ARGUMENT((arg_types & SLJIT_ARG_MASK) == compiler->last_return);
}
- CHECK_ARGUMENT(compiler->scratches >= scratches);
- CHECK_ARGUMENT(compiler->fscratches >= fscratches);
- CHECK_ARGUMENT(types == 0);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " i%s%s ret[%s", jump_names[type & 0xff],
- !(type & SLJIT_REWRITABLE_JUMP) ? "" : ".r", call_arg_names[arg_types & SLJIT_DEF_MASK]);
+ !(type & SLJIT_CALL_RETURN) ? "" : ".ret",
+ call_arg_names[arg_types & SLJIT_ARG_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types) {
fprintf(compiler->verbose, "], args[");
do {
- fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_DEF_MASK]);
- arg_types >>= SLJIT_DEF_SHIFT;
+ fprintf(compiler->verbose, "%s", call_arg_names[arg_types & SLJIT_ARG_MASK]);
+ arg_types >>= SLJIT_ARG_SHIFT;
if (arg_types)
fprintf(compiler->verbose, ",");
} while (arg_types);
@@ -1812,9 +1830,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
sljit_s32 type)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
- CHECK_ARGUMENT((type & 0xff) != GET_FLAG_TYPE(SLJIT_SET_CARRY) && (type & 0xff) != (GET_FLAG_TYPE(SLJIT_SET_CARRY) + 1));
CHECK_ARGUMENT(op == SLJIT_MOV || op == SLJIT_MOV32
|| (GET_OPCODE(op) >= SLJIT_AND && GET_OPCODE(op) <= SLJIT_XOR));
CHECK_ARGUMENT(!(op & VARIABLE_FLAG_MASK));
@@ -1823,19 +1840,20 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com
CHECK_ARGUMENT(compiler->last_flags & SLJIT_SET_Z);
else
CHECK_ARGUMENT((type & 0xff) == (compiler->last_flags & 0xff)
+ || ((type & 0xff) == SLJIT_NOT_CARRY && (compiler->last_flags & 0xff) == SLJIT_CARRY)
|| ((type & 0xff) == SLJIT_NOT_OVERFLOW && (compiler->last_flags & 0xff) == SLJIT_OVERFLOW));
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
if (GET_OPCODE(op) >= SLJIT_ADD)
- compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_I32_OP | SLJIT_SET_Z));
+ compiler->last_flags = GET_FLAG_TYPE(op) | (op & (SLJIT_32 | SLJIT_SET_Z));
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " flags%s %s%s, ",
!(op & SLJIT_SET_Z) ? "" : ".z",
GET_OPCODE(op) < SLJIT_OP2_BASE ? "mov" : op2_names[GET_OPCODE(op) - SLJIT_OP2_BASE],
- GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_I32_OP) ? "32" : ""));
+ GET_OPCODE(op) < SLJIT_OP2_BASE ? op1_names[GET_OPCODE(op) - SLJIT_OP1_BASE] : ((op & SLJIT_32) ? "32" : ""));
sljit_verbose_param(compiler, dst, dstw);
fprintf(compiler->verbose, ", %s%s\n", jump_names[type & 0xff], JUMP_POSTFIX(type));
}
@@ -1848,11 +1866,11 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_I32_OP)));
+ CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_32)));
CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_ORDERED_F64);
CHECK_ARGUMENT(compiler->scratches != -1 && compiler->saveds != -1);
- CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_I32_OP));
+ CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_32));
if (src != SLJIT_IMM) {
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(src));
CHECK_ARGUMENT(srcw == 0);
@@ -1867,9 +1885,9 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_cmov(struct sljit_compile
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
fprintf(compiler->verbose, " cmov%s %s%s, ",
- !(dst_reg & SLJIT_I32_OP) ? "" : "32",
+ !(dst_reg & SLJIT_32) ? "" : "32",
jump_names[type & 0xff], JUMP_POSTFIX(type));
- sljit_verbose_reg(compiler, dst_reg & ~SLJIT_I32_OP);
+ sljit_verbose_reg(compiler, dst_reg & ~SLJIT_32);
fprintf(compiler->verbose, ", ");
sljit_verbose_param(compiler, src, srcw);
fprintf(compiler->verbose, "\n");
@@ -1884,15 +1902,15 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
CHECK_ARGUMENT((type & 0xff) >= SLJIT_MOV && (type & 0xff) <= SLJIT_MOV_P);
- CHECK_ARGUMENT(!(type & SLJIT_I32_OP) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
+ CHECK_ARGUMENT(!(type & SLJIT_32) || ((type & 0xff) != SLJIT_MOV && (type & 0xff) != SLJIT_MOV_U32 && (type & 0xff) != SLJIT_MOV_P));
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
- CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
FUNCTION_CHECK_SRC_MEM(mem, memw);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(reg));
- CHECK_ARGUMENT((mem & REG_MASK) != SLJIT_UNUSED && (mem & REG_MASK) != reg);
+ CHECK_ARGUMENT((mem & REG_MASK) != 0 && (mem & REG_MASK) != reg);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (!(type & SLJIT_MEM_SUPP) && SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1900,7 +1918,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_mem(struct sljit_compiler
fprintf(compiler->verbose, " //");
fprintf(compiler->verbose, " mem%s.%s%s%s ",
- !(type & SLJIT_I32_OP) ? "" : "32",
+ !(type & SLJIT_32) ? "" : "32",
(type & SLJIT_MEM_STORE) ? "st" : "ld",
op1_names[(type & 0xff) - SLJIT_OP1_BASE],
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
@@ -1921,7 +1939,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile
CHECK_ARGUMENT((type & 0xff) == SLJIT_MOV_F64);
CHECK_ARGUMENT((type & SLJIT_MEM_PRE) || (type & SLJIT_MEM_POST));
CHECK_ARGUMENT((type & (SLJIT_MEM_PRE | SLJIT_MEM_POST)) != (SLJIT_MEM_PRE | SLJIT_MEM_POST));
- CHECK_ARGUMENT((type & ~(0xff | SLJIT_I32_OP | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
+ CHECK_ARGUMENT((type & ~(0xff | SLJIT_32 | SLJIT_MEM_STORE | SLJIT_MEM_SUPP | SLJIT_MEM_PRE | SLJIT_MEM_POST)) == 0);
FUNCTION_CHECK_SRC_MEM(mem, memw);
CHECK_ARGUMENT(FUNCTION_CHECK_IS_FREG(freg));
@@ -1933,7 +1951,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_fmem(struct sljit_compile
fprintf(compiler->verbose, " fmem.%s%s%s ",
(type & SLJIT_MEM_STORE) ? "st" : "ld",
- !(type & SLJIT_I32_OP) ? ".f64" : ".f32",
+ !(type & SLJIT_32) ? ".f64" : ".f32",
(type & SLJIT_MEM_PRE) ? ".pre" : ".post");
sljit_verbose_freg(compiler, freg);
fprintf(compiler->verbose, ", ");
@@ -1950,7 +1968,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co
SLJIT_UNUSED_ARG(offset);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1967,7 +1985,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
SLJIT_UNUSED_ARG(init_value);
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -1982,7 +2000,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compil
static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- FUNCTION_CHECK_DST(dst, dstw, 0);
+ FUNCTION_CHECK_DST(dst, dstw);
#endif
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
if (SLJIT_UNLIKELY(!!compiler->verbose)) {
@@ -2023,10 +2041,6 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_put_label(struct sljit_co
static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
- /* Return if don't need to do anything. */
- if (op == SLJIT_UNUSED)
- return SLJIT_SUCCESS;
-
#if (defined SLJIT_64BIT_ARCHITECTURE && SLJIT_64BIT_ARCHITECTURE)
/* At the moment the pointer size is always equal to sljit_sw. May be changed in the future. */
if (src == SLJIT_RETURN_REG && (op == SLJIT_MOV || op == SLJIT_MOV_P))
@@ -2043,6 +2057,24 @@ static SLJIT_INLINE sljit_s32 emit_mov_before_return(struct sljit_compiler *comp
return sljit_emit_op1(compiler, op, SLJIT_RETURN_REG, 0, src, srcw);
}
+#if !(defined SLJIT_CONFIG_SPARC && SLJIT_CONFIG_SPARC)
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+
+ FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+
+#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) \
+ || (defined SLJIT_VERBOSE && SLJIT_VERBOSE)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_return_void(compiler);
+}
+
+#endif
+
#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) \
|| (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC) \
|| (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) \
@@ -2054,7 +2086,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
{
struct sljit_label *label;
struct sljit_jump *jump;
- sljit_s32 op = (dst_reg & SLJIT_I32_OP) ? SLJIT_MOV32 : SLJIT_MOV;
+ sljit_s32 op = (dst_reg & SLJIT_32) ? SLJIT_MOV32 : SLJIT_MOV;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2067,7 +2099,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_cmov_generic(struct sljit_compiler *com
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_I32_OP, 0, src, srcw));
+ FAIL_IF(sljit_emit_op1(compiler, op, dst_reg & ~SLJIT_32, 0, src, srcw));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2183,7 +2215,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
break;
}
- type = condition | (type & (SLJIT_I32_OP | SLJIT_REWRITABLE_JUMP));
+ type = condition | (type & (SLJIT_32 | SLJIT_REWRITABLE_JUMP));
tmp_src = src1;
src1 = src2;
src2 = tmp_src;
@@ -2201,13 +2233,13 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- PTR_FAIL_IF(sljit_emit_op2(compiler, SLJIT_SUB | flags | (type & SLJIT_I32_OP),
- SLJIT_UNUSED, 0, src1, src1w, src2, src2w));
+ PTR_FAIL_IF(sljit_emit_op2u(compiler,
+ SLJIT_SUB | flags | (type & SLJIT_32), src1, src1w, src2, src2w));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_I32_OP)));
+ return sljit_emit_jump(compiler, condition | (type & (SLJIT_REWRITABLE_JUMP | SLJIT_32)));
}
#endif
@@ -2223,7 +2255,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_fcmp(struct sljit_compile
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
- sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_I32_OP), src1, src1w, src2, src2w);
+ sljit_emit_fop1(compiler, SLJIT_CMP_F64 | ((type & 0xff) << VARIABLE_FLAG_SHIFT) | (type & SLJIT_32), src1, src1w, src2, src2w);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2404,6 +2436,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
return SLJIT_ERR_UNSUPPORTED;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNREACHABLE();
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw)
{
SLJIT_UNUSED_ARG(compiler);
@@ -2452,6 +2491,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_ERR_UNSUPPORTED;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ SLJIT_UNUSED_ARG(compiler);
+ SLJIT_UNUSED_ARG(op);
+ SLJIT_UNUSED_ARG(src1);
+ SLJIT_UNUSED_ARG(src1w);
+ SLJIT_UNUSED_ARG(src2);
+ SLJIT_UNUSED_ARG(src2w);
+ SLJIT_UNREACHABLE();
+ return SLJIT_ERR_UNSUPPORTED;
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2470,7 +2523,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(instruction);
diff --git a/thirdparty/pcre2/src/sljit/sljitLir.h b/thirdparty/pcre2/src/sljit/sljitLir.h
index 0eb62fc21b..1162658156 100644
--- a/thirdparty/pcre2/src/sljit/sljitLir.h
+++ b/thirdparty/pcre2/src/sljit/sljitLir.h
@@ -163,13 +163,6 @@ extern "C" {
is not available at all.
*/
-/* When SLJIT_UNUSED is specified as the destination of sljit_emit_op1
- or sljit_emit_op2 operations the result is discarded. Some status
- flags must be set when the destination is SLJIT_UNUSED, because the
- operation would have no effect otherwise. Other SLJIT operations do
- not support SLJIT_UNUSED as a destination operand. */
-#define SLJIT_UNUSED 0
-
/* Scratch registers. */
#define SLJIT_R0 1
#define SLJIT_R1 2
@@ -231,9 +224,6 @@ extern "C" {
value. The FR and FS register sets are overlap in the same way as R
and S register sets. See above. */
-/* Note: SLJIT_UNUSED as destination is not valid for floating point
- operations, since they cannot be used for setting flags. */
-
/* Floating point scratch registers. */
#define SLJIT_FR0 1
#define SLJIT_FR1 2
@@ -263,39 +253,38 @@ extern "C" {
/* Argument type definitions */
/* --------------------------------------------------------------------- */
-/* Argument type definitions.
- Used by SLJIT_[DEF_]ARGx and SLJIT_[DEF]_RET macros. */
-
-#define SLJIT_ARG_TYPE_VOID 0
-#define SLJIT_ARG_TYPE_SW 1
-#define SLJIT_ARG_TYPE_UW 2
-#define SLJIT_ARG_TYPE_S32 3
-#define SLJIT_ARG_TYPE_U32 4
-#define SLJIT_ARG_TYPE_F32 5
-#define SLJIT_ARG_TYPE_F64 6
-
/* The following argument type definitions are used by sljit_emit_enter,
sljit_set_context, sljit_emit_call, and sljit_emit_icall functions.
- The following return type definitions are used by sljit_emit_call
- and sljit_emit_icall functions.
- When a function is called, the first integer argument must be placed
- in SLJIT_R0, the second in SLJIT_R1, and so on. Similarly the first
- floating point argument must be placed in SLJIT_FR0, the second in
- SLJIT_FR1, and so on.
+ As for sljit_emit_call and sljit_emit_icall, the first integer argument
+ must be placed into SLJIT_R0, the second one into SLJIT_R1, and so on.
+ Similarly the first floating point argument must be placed into SLJIT_FR0,
+ the second one into SLJIT_FR1, and so on.
+
+ As for sljit_emit_enter, the integer arguments can be stored in scratch
+ or saved registers. The first integer argument without _R postfix is
+ stored in SLJIT_S0, the next one in SLJIT_S1, and so on. The integer
+ arguments with _R postfix are placed into scratch registers. The index
+ of the scratch register is the count of the previous integer arguments
+ starting from SLJIT_R0. The floating point arguments are always placed
+ into SLJIT_FR0, SLJIT_FR1, and so on.
+
+ Note: if a function is called by sljit_emit_call/sljit_emit_icall and
+ an argument is stored in a scratch register by sljit_emit_enter,
+ that argument uses the same scratch register index for both
+ integer and floating point arguments.
Example function definition:
- sljit_f32 SLJIT_FUNC example_c_callback(sljit_sw arg_a,
+ sljit_f32 SLJIT_FUNC example_c_callback(void *arg_a,
sljit_f64 arg_b, sljit_u32 arg_c, sljit_f32 arg_d);
Argument type definition:
- SLJIT_DEF_RET(SLJIT_ARG_TYPE_F32)
- | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F64)
- | SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_U32) | SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_F32)
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_F32)
+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_P, 1) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F64, 2)
+ | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_32, 3) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 4)
Short form of argument type definition:
- SLJIT_RET(F32) | SLJIT_ARG1(SW) | SLJIT_ARG2(F64)
- | SLJIT_ARG3(S32) | SLJIT_ARG4(F32)
+ SLJIT_ARGS4(32, P, F64, 32, F32)
Argument passing:
arg_a must be placed in SLJIT_R0
@@ -303,34 +292,73 @@ extern "C" {
arg_b must be placed in SLJIT_FR0
arg_d must be placed in SLJIT_FR1
-Note:
- The SLJIT_ARG_TYPE_VOID type is only supported by
- SLJIT_DEF_RET, and SLJIT_ARG_TYPE_VOID is also the
- default value when SLJIT_DEF_RET is not specified. */
-#define SLJIT_DEF_SHIFT 4
-#define SLJIT_DEF_RET(type) (type)
-#define SLJIT_DEF_ARG1(type) ((type) << SLJIT_DEF_SHIFT)
-#define SLJIT_DEF_ARG2(type) ((type) << (2 * SLJIT_DEF_SHIFT))
-#define SLJIT_DEF_ARG3(type) ((type) << (3 * SLJIT_DEF_SHIFT))
-#define SLJIT_DEF_ARG4(type) ((type) << (4 * SLJIT_DEF_SHIFT))
+ Examples for argument processing by sljit_emit_enter:
+ SLJIT_ARGS4(VOID, P, 32_R, F32, W)
+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_FR0, SLJIT_S1
+
+ SLJIT_ARGS4(VOID, W, W_R, W, W_R)
+ Arguments are placed into: SLJIT_S0, SLJIT_R1, SLJIT_S1, SLJIT_R3
-/* Short form of the macros above.
+ SLJIT_ARGS4(VOID, F64, W, F32, W_R)
+ Arguments are placed into: SLJIT_FR0, SLJIT_S0, SLJIT_FR1, SLJIT_R1
- For example the following definition:
- SLJIT_DEF_RET(SLJIT_ARG_TYPE_SW) | SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_F32)
+ Note: it is recommended to pass the scratch arguments first
+ followed by the saved arguments:
+
+ SLJIT_ARGS4(VOID, W_R, W_R, W, W)
+ Arguments are placed into: SLJIT_R0, SLJIT_R1, SLJIT_S0, SLJIT_S1
+*/
+
+/* The following flag is only allowed for the integer arguments of
+ sljit_emit_enter. When the flag is set, the integer argument is
+ stored in a scratch register instead of a saved register. */
+#define SLJIT_ARG_TYPE_SCRATCH_REG 0x8
+
+/* Void result, can only be used by SLJIT_ARG_RETURN. */
+#define SLJIT_ARG_TYPE_VOID 0
+/* Machine word sized integer argument or result. */
+#define SLJIT_ARG_TYPE_W 1
+#define SLJIT_ARG_TYPE_W_R (SLJIT_ARG_TYPE_W | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* 32 bit integer argument or result. */
+#define SLJIT_ARG_TYPE_32 2
+#define SLJIT_ARG_TYPE_32_R (SLJIT_ARG_TYPE_32 | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* Pointer sized integer argument or result. */
+#define SLJIT_ARG_TYPE_P 3
+#define SLJIT_ARG_TYPE_P_R (SLJIT_ARG_TYPE_P | SLJIT_ARG_TYPE_SCRATCH_REG)
+/* 64 bit floating point argument or result. */
+#define SLJIT_ARG_TYPE_F64 4
+/* 32 bit floating point argument or result. */
+#define SLJIT_ARG_TYPE_F32 5
+
+#define SLJIT_ARG_SHIFT 4
+#define SLJIT_ARG_RETURN(type) (type)
+#define SLJIT_ARG_VALUE(type, idx) ((type) << ((idx) * SLJIT_ARG_SHIFT))
+
+/* Simplified argument list definitions.
+
+ The following definition:
+ SLJIT_ARG_RETURN(SLJIT_ARG_TYPE_W) | SLJIT_ARG_VALUE(SLJIT_ARG_TYPE_F32, 1)
can be shortened to:
- SLJIT_RET(SW) | SLJIT_ARG1(F32)
-
-Note:
- The VOID type is only supported by SLJIT_RET, and
- VOID is also the default value when SLJIT_RET is
- not specified. */
-#define SLJIT_RET(type) SLJIT_DEF_RET(SLJIT_ARG_TYPE_ ## type)
-#define SLJIT_ARG1(type) SLJIT_DEF_ARG1(SLJIT_ARG_TYPE_ ## type)
-#define SLJIT_ARG2(type) SLJIT_DEF_ARG2(SLJIT_ARG_TYPE_ ## type)
-#define SLJIT_ARG3(type) SLJIT_DEF_ARG3(SLJIT_ARG_TYPE_ ## type)
-#define SLJIT_ARG4(type) SLJIT_DEF_ARG4(SLJIT_ARG_TYPE_ ## type)
+ SLJIT_ARGS1(W, F32)
+*/
+
+#define SLJIT_ARG_TO_TYPE(type) SLJIT_ARG_TYPE_ ## type
+
+#define SLJIT_ARGS0(ret) \
+ SLJIT_ARG_RETURN(SLJIT_ARG_TO_TYPE(ret))
+
+#define SLJIT_ARGS1(ret, arg1) \
+ (SLJIT_ARGS0(ret) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg1), 1))
+
+#define SLJIT_ARGS2(ret, arg1, arg2) \
+ (SLJIT_ARGS1(ret, arg1) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg2), 2))
+
+#define SLJIT_ARGS3(ret, arg1, arg2, arg3) \
+ (SLJIT_ARGS2(ret, arg1, arg2) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg3), 3))
+
+#define SLJIT_ARGS4(ret, arg1, arg2, arg3, arg4) \
+ (SLJIT_ARGS3(ret, arg1, arg2, arg3) | SLJIT_ARG_VALUE(SLJIT_ARG_TO_TYPE(arg4), 4))
/* --------------------------------------------------------------------- */
/* Main structures and functions */
@@ -408,7 +436,7 @@ struct sljit_compiler {
/* Code size. */
sljit_uw size;
/* Relative offset of the executable mapping from the writable mapping. */
- sljit_uw executable_offset;
+ sljit_sw executable_offset;
/* Executable size for statistical purposes. */
sljit_uw executable_size;
@@ -417,17 +445,13 @@ struct sljit_compiler {
#endif
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- sljit_s32 args;
+ sljit_s32 args_size;
sljit_s32 locals_offset;
- sljit_s32 saveds_offset;
- sljit_s32 stack_tmp_size;
+ sljit_s32 scratches_offset;
#endif
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
sljit_s32 mode32;
-#ifdef _WIN64
- sljit_s32 locals_offset;
-#endif
#endif
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
@@ -444,10 +468,14 @@ struct sljit_compiler {
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5) || (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
/* Temporary fields. */
sljit_uw shift_imm;
+#endif /* SLJIT_CONFIG_ARM_V5 || SLJIT_CONFIG_ARM_V7 */
+
+#if (defined SLJIT_CONFIG_ARM_32 && SLJIT_CONFIG_ARM_32) && (defined __SOFTFP__)
+ sljit_uw args_size;
#endif
#if (defined SLJIT_CONFIG_PPC && SLJIT_CONFIG_PPC)
- sljit_sw imm;
+ sljit_u32 imm;
#endif
#if (defined SLJIT_CONFIG_MIPS && SLJIT_CONFIG_MIPS)
@@ -456,6 +484,10 @@ struct sljit_compiler {
sljit_sw cache_argw;
#endif
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ sljit_uw args_size;
+#endif
+
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
sljit_s32 delay_slot;
sljit_s32 cache_arg;
@@ -476,7 +508,9 @@ struct sljit_compiler {
/* Flags specified by the last arithmetic instruction.
It contains the type of the variable flag. */
sljit_s32 last_flags;
- /* Local size passed to the functions. */
+ /* Return value type set by entry functions. */
+ sljit_s32 last_return;
+ /* Local size passed to entry functions. */
sljit_s32 logical_local_size;
#endif
@@ -615,38 +649,43 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
available options are listed before sljit_emit_enter.
The function argument list is the combination of SLJIT_ARGx
- (SLJIT_DEF_ARG1) macros. Currently maximum 3 SW / UW
- (SLJIT_ARG_TYPE_SW / LJIT_ARG_TYPE_UW) arguments are supported.
- The first argument goes to SLJIT_S0, the second goes to SLJIT_S1
- and so on. The register set used by the function must be declared
- as well. The number of scratch and saved registers used by the
- function must be passed to sljit_emit_enter. Only R registers
- between R0 and "scratches" argument can be used later. E.g. if
- "scratches" is set to 2, the scratch register set will be limited
- to SLJIT_R0 and SLJIT_R1. The S registers and the floating point
- registers ("fscratches" and "fsaveds") are specified in a similar
- manner. The sljit_emit_enter is also capable of allocating a stack
- space for local variables. The "local_size" argument contains the
- size in bytes of this local area and its staring address is stored
+ (SLJIT_DEF_ARG1) macros. Currently maximum 4 arguments are
+ supported. The first integer argument is loaded into SLJIT_S0,
+ the second one is loaded into SLJIT_S1, and so on. Similarly,
+ the first floating point argument is loaded into SLJIT_FR0,
+ the second one is loaded into SLJIT_FR1, and so on. Furthermore
+ the register set used by the function must be declared as well.
+ The number of scratch and saved registers used by the function
+ must be passed to sljit_emit_enter. Only R registers between R0
+ and "scratches" argument can be used later. E.g. if "scratches"
+ is set to 2, the scratch register set will be limited to SLJIT_R0
+ and SLJIT_R1. The S registers and the floating point registers
+ ("fscratches" and "fsaveds") are specified in a similar manner.
+ The sljit_emit_enter is also capable of allocating a stack space
+ for local variables. The "local_size" argument contains the size
+ in bytes of this local area and its staring address is stored
in SLJIT_SP. The memory area between SLJIT_SP (inclusive) and
SLJIT_SP + local_size (exclusive) can be modified freely until
the function returns. The stack space is not initialized.
Note: the following conditions must met:
0 <= scratches <= SLJIT_NUMBER_OF_REGISTERS
- 0 <= saveds <= SLJIT_NUMBER_OF_REGISTERS
+ 0 <= saveds <= SLJIT_NUMBER_OF_SAVED_REGISTERS
scratches + saveds <= SLJIT_NUMBER_OF_REGISTERS
0 <= fscratches <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
- 0 <= fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ 0 <= fsaveds <= SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS
fscratches + fsaveds <= SLJIT_NUMBER_OF_FLOAT_REGISTERS
+ Note: the compiler can use saved registers as scratch registers,
+ but the opposite is not supported
+
Note: every call of sljit_emit_enter and sljit_set_context
overwrites the previous context.
*/
-/* The absolute address returned by sljit_get_local_base with
-offset 0 is aligned to sljit_f64. Otherwise it is aligned to sljit_sw. */
-#define SLJIT_F64_ALIGNMENT 0x00000001
+/* The compiled function uses cdecl calling
+ * convention instead of SLJIT_FUNC. */
+#define SLJIT_ENTER_CDECL 0x00000001
/* The local_size must be >= 0 and <= SLJIT_MAX_LOCAL_SIZE. */
#define SLJIT_MAX_LOCAL_SIZE 65536
@@ -657,7 +696,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
/* The machine code has a context (which contains the local stack space size,
number of used registers, etc.) which initialized by sljit_emit_enter. Several
- functions (like sljit_emit_return) requres this context to be able to generate
+ functions (such as sljit_emit_return) requres this context to be able to generate
the appropriate code. However, some code fragments (like inline cache) may have
no normal entry point so their context is unknown for the compiler. Their context
can be provided to the compiler by the sljit_set_context function.
@@ -669,11 +708,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size);
-/* Return from machine code. The op argument can be SLJIT_UNUSED which means the
- function does not return with anything or any opcode between SLJIT_MOV and
- SLJIT_MOV_P (see sljit_emit_op1). As for src and srcw they must be 0 if op
- is SLJIT_UNUSED, otherwise see below the description about source and
- destination arguments. */
+/* Return from machine code. The sljit_emit_return_void function does not return with
+ any value. The sljit_emit_return function returns with a single value which stores
+ the result of a data move instruction. The instruction is specified by the op
+ argument, and must be between SLJIT_MOV and SLJIT_MOV_P (see sljit_emit_op1). */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler);
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw);
@@ -766,7 +806,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
#define SLJIT_MEM2(r1, r2) (SLJIT_MEM | (r1) | ((r2) << 8))
#define SLJIT_IMM 0x40
-/* Set 32 bit operation mode (I) on 64 bit CPUs. This option is ignored on
+/* Sets 32 bit operation mode on 64 bit CPUs. This option is ignored on
32 bit CPUs. When this option is set for an arithmetic operation, only
the lower 32 bit of the input registers are used, and the CPU status
flags are set according to the 32 bit result. Although the higher 32 bit
@@ -774,12 +814,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
be defined by the CPU architecture (e.g. MIPS). To satisfy these CPU
requirements all source registers must be the result of those operations
where this option was also set. Memory loads read 32 bit values rather
- than 64 bit ones. In other words 32 bit and 64 bit operations cannot
- be mixed. The only exception is SLJIT_MOV32 and SLJIT_MOVU32 whose source
- register can hold any 32 or 64 bit value, and it is converted to a 32 bit
- compatible format first. This conversion is free (no instructions are
- emitted) on most CPUs. A 32 bit value can also be converted to a 64 bit
- value by SLJIT_MOV_S32 (sign extension) or SLJIT_MOV_U32 (zero extension).
+ than 64 bit ones. In other words 32 bit and 64 bit operations cannot be
+ mixed. The only exception is SLJIT_MOV32 whose source register can hold
+ any 32 or 64 bit value, and it is converted to a 32 bit compatible format
+ first. This conversion is free (no instructions are emitted) on most CPUs.
+ A 32 bit value can also be converted to a 64 bit value by SLJIT_MOV_S32
+ (sign extension) or SLJIT_MOV_U32 (zero extension).
+
+ As for floating-point operations, this option sets 32 bit single
+ precision mode. Similar to the integer operations, all register arguments
+ must be the result of those operations where this option was also set.
Note: memory addressing always uses 64 bit values on 64 bit systems so
the result of a 32 bit operation must not be used with SLJIT_MEMx
@@ -788,22 +832,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
This option is part of the instruction name, so there is no need to
manually set it. E.g:
- SLJIT_ADD32 == (SLJIT_ADD | SLJIT_I32_OP) */
-#define SLJIT_I32_OP 0x100
-
-/* Set F32 (single) precision mode for floating-point computation. This
- option is similar to SLJIT_I32_OP, it just applies to floating point
- registers. When this option is passed, the CPU performs 32 bit floating
- point operations, rather than 64 bit one. Similar to SLJIT_I32_OP, all
- register arguments must be the result of those operations where this
- option was also set.
-
- This option is part of the instruction name, so there is no need to
- manually set it. E.g:
-
- SLJIT_MOV_F32 = (SLJIT_MOV_F64 | SLJIT_F32_OP)
- */
-#define SLJIT_F32_OP SLJIT_I32_OP
+ SLJIT_ADD32 == (SLJIT_ADD | SLJIT_32) */
+#define SLJIT_32 0x100
/* Many CPUs (x86, ARM, PPC) have status flags which can be set according
to the result of an operation. Other CPUs (MIPS) do not have status
@@ -887,7 +917,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
Note: if SLJIT_R1 is 0, the behaviour is undefined. */
#define SLJIT_DIVMOD_UW (SLJIT_OP0_BASE + 4)
-#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_I32_OP)
+#define SLJIT_DIVMOD_U32 (SLJIT_DIVMOD_UW | SLJIT_32)
/* Flags: - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0 and the remainder into SLJIT_R1.
@@ -895,13 +925,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
the behaviour is undefined. */
#define SLJIT_DIVMOD_SW (SLJIT_OP0_BASE + 5)
-#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_I32_OP)
+#define SLJIT_DIVMOD_S32 (SLJIT_DIVMOD_SW | SLJIT_32)
/* Flags: - (may destroy flags)
Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
Note: if SLJIT_R1 is 0, the behaviour is undefined. */
#define SLJIT_DIV_UW (SLJIT_OP0_BASE + 6)
-#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_I32_OP)
+#define SLJIT_DIV_U32 (SLJIT_DIV_UW | SLJIT_32)
/* Flags: - (may destroy flags)
Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1.
The result is placed into SLJIT_R0. SLJIT_R1 preserves its value.
@@ -909,7 +939,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00),
the behaviour is undefined. */
#define SLJIT_DIV_SW (SLJIT_OP0_BASE + 7)
-#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_I32_OP)
+#define SLJIT_DIV_S32 (SLJIT_DIV_SW | SLJIT_32)
/* Flags: - (does not modify flags)
ENDBR32 instruction for x86-32 and ENDBR64 instruction for x86-64
when Intel Control-flow Enforcement Technology (CET) is enabled.
@@ -941,16 +971,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#define SLJIT_MOV (SLJIT_OP1_BASE + 0)
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_U8 (SLJIT_OP1_BASE + 1)
-#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_I32_OP)
+#define SLJIT_MOV32_U8 (SLJIT_MOV_U8 | SLJIT_32)
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_S8 (SLJIT_OP1_BASE + 2)
-#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_I32_OP)
+#define SLJIT_MOV32_S8 (SLJIT_MOV_S8 | SLJIT_32)
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_U16 (SLJIT_OP1_BASE + 3)
-#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_I32_OP)
+#define SLJIT_MOV32_U16 (SLJIT_MOV_U16 | SLJIT_32)
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_S16 (SLJIT_OP1_BASE + 4)
-#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_I32_OP)
+#define SLJIT_MOV32_S16 (SLJIT_MOV_S16 | SLJIT_32)
/* Flags: - (does not modify flags)
Note: no SLJIT_MOV32_U32 form, since it is the same as SLJIT_MOV32 */
#define SLJIT_MOV_U32 (SLJIT_OP1_BASE + 5)
@@ -958,25 +988,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
Note: no SLJIT_MOV32_S32 form, since it is the same as SLJIT_MOV32 */
#define SLJIT_MOV_S32 (SLJIT_OP1_BASE + 6)
/* Flags: - (does not modify flags) */
-#define SLJIT_MOV32 (SLJIT_MOV_S32 | SLJIT_I32_OP)
+#define SLJIT_MOV32 (SLJIT_OP1_BASE + 7)
/* Flags: - (does not modify flags)
Note: load a pointer sized data, useful on x32 (a 32 bit mode on x86-64
where all x64 features are available, e.g. 16 register) or similar
compiling modes */
-#define SLJIT_MOV_P (SLJIT_OP1_BASE + 7)
+#define SLJIT_MOV_P (SLJIT_OP1_BASE + 8)
/* Flags: Z
Note: immediate source argument is not supported */
-#define SLJIT_NOT (SLJIT_OP1_BASE + 8)
-#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_I32_OP)
-/* Flags: Z | OVERFLOW
- Note: immediate source argument is not supported */
-#define SLJIT_NEG (SLJIT_OP1_BASE + 9)
-#define SLJIT_NEG32 (SLJIT_NEG | SLJIT_I32_OP)
+#define SLJIT_NOT (SLJIT_OP1_BASE + 9)
+#define SLJIT_NOT32 (SLJIT_NOT | SLJIT_32)
/* Count leading zeroes
Flags: - (may destroy flags)
Note: immediate source argument is not supported */
#define SLJIT_CLZ (SLJIT_OP1_BASE + 10)
-#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_I32_OP)
+#define SLJIT_CLZ32 (SLJIT_CLZ | SLJIT_32)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
@@ -987,58 +1013,64 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
/* Flags: Z | OVERFLOW | CARRY */
#define SLJIT_ADD (SLJIT_OP2_BASE + 0)
-#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_I32_OP)
+#define SLJIT_ADD32 (SLJIT_ADD | SLJIT_32)
/* Flags: CARRY */
#define SLJIT_ADDC (SLJIT_OP2_BASE + 1)
-#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_I32_OP)
+#define SLJIT_ADDC32 (SLJIT_ADDC | SLJIT_32)
/* Flags: Z | LESS | GREATER_EQUAL | GREATER | LESS_EQUAL
SIG_LESS | SIG_GREATER_EQUAL | SIG_GREATER
SIG_LESS_EQUAL | CARRY */
#define SLJIT_SUB (SLJIT_OP2_BASE + 2)
-#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_I32_OP)
+#define SLJIT_SUB32 (SLJIT_SUB | SLJIT_32)
/* Flags: CARRY */
#define SLJIT_SUBC (SLJIT_OP2_BASE + 3)
-#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_I32_OP)
+#define SLJIT_SUBC32 (SLJIT_SUBC | SLJIT_32)
/* Note: integer mul
Flags: OVERFLOW */
#define SLJIT_MUL (SLJIT_OP2_BASE + 4)
-#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_I32_OP)
+#define SLJIT_MUL32 (SLJIT_MUL | SLJIT_32)
/* Flags: Z */
#define SLJIT_AND (SLJIT_OP2_BASE + 5)
-#define SLJIT_AND32 (SLJIT_AND | SLJIT_I32_OP)
+#define SLJIT_AND32 (SLJIT_AND | SLJIT_32)
/* Flags: Z */
#define SLJIT_OR (SLJIT_OP2_BASE + 6)
-#define SLJIT_OR32 (SLJIT_OR | SLJIT_I32_OP)
+#define SLJIT_OR32 (SLJIT_OR | SLJIT_32)
/* Flags: Z */
#define SLJIT_XOR (SLJIT_OP2_BASE + 7)
-#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_I32_OP)
+#define SLJIT_XOR32 (SLJIT_XOR | SLJIT_32)
/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the result is undefined. */
#define SLJIT_SHL (SLJIT_OP2_BASE + 8)
-#define SLJIT_SHL32 (SLJIT_SHL | SLJIT_I32_OP)
+#define SLJIT_SHL32 (SLJIT_SHL | SLJIT_32)
/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the result is undefined. */
#define SLJIT_LSHR (SLJIT_OP2_BASE + 9)
-#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_I32_OP)
+#define SLJIT_LSHR32 (SLJIT_LSHR | SLJIT_32)
/* Flags: Z
Let bit_length be the length of the shift operation: 32 or 64.
If src2 is immediate, src2w is masked by (bit_length - 1).
Otherwise, if the content of src2 is outside the range from 0
to bit_length - 1, the result is undefined. */
#define SLJIT_ASHR (SLJIT_OP2_BASE + 10)
-#define SLJIT_ASHR32 (SLJIT_ASHR | SLJIT_I32_OP)
+#define SLJIT_ASHR32 (SLJIT_ASHR | SLJIT_32)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w);
+/* The sljit_emit_op2u function is the same as sljit_emit_op2 except the result is discarded. */
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w);
+
/* Starting index of opcodes for sljit_emit_op2. */
#define SLJIT_OP_SRC_BASE 128
@@ -1082,35 +1114,35 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
/* Flags: - (does not modify flags) */
#define SLJIT_MOV_F64 (SLJIT_FOP1_BASE + 0)
-#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_F32_OP)
+#define SLJIT_MOV_F32 (SLJIT_MOV_F64 | SLJIT_32)
/* Convert opcodes: CONV[DST_TYPE].FROM[SRC_TYPE]
SRC/DST TYPE can be: D - double, S - single, W - signed word, I - signed int
Rounding mode when the destination is W or I: round towards zero. */
-/* Flags: - (does not modify flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_CONV_F64_FROM_F32 (SLJIT_FOP1_BASE + 1)
-#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_F32_FROM_F64 (SLJIT_CONV_F64_FROM_F32 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_CONV_SW_FROM_F64 (SLJIT_FOP1_BASE + 2)
-#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_SW_FROM_F32 (SLJIT_CONV_SW_FROM_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_CONV_S32_FROM_F64 (SLJIT_FOP1_BASE + 3)
-#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_S32_FROM_F32 (SLJIT_CONV_S32_FROM_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_CONV_F64_FROM_SW (SLJIT_FOP1_BASE + 4)
-#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_CONV_F32_FROM_SW (SLJIT_CONV_F64_FROM_SW | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_CONV_F64_FROM_S32 (SLJIT_FOP1_BASE + 5)
-#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_F32_OP)
+#define SLJIT_CONV_F32_FROM_S32 (SLJIT_CONV_F64_FROM_S32 | SLJIT_32)
/* Note: dst is the left and src is the right operand for SLJIT_CMPD.
Flags: EQUAL_F | LESS_F | GREATER_EQUAL_F | GREATER_F | LESS_EQUAL_F */
#define SLJIT_CMP_F64 (SLJIT_FOP1_BASE + 6)
-#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_CMP_F32 (SLJIT_CMP_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_NEG_F64 (SLJIT_FOP1_BASE + 7)
-#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_NEG_F32 (SLJIT_NEG_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_ABS_F64 (SLJIT_FOP1_BASE + 8)
-#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_F32_OP)
+#define SLJIT_ABS_F32 (SLJIT_ABS_F64 | SLJIT_32)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
@@ -1119,18 +1151,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
/* Starting index of opcodes for sljit_emit_fop2. */
#define SLJIT_FOP2_BASE 192
-/* Flags: - (does not modify flags) */
+/* Flags: - (may destroy flags) */
#define SLJIT_ADD_F64 (SLJIT_FOP2_BASE + 0)
-#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_ADD_F32 (SLJIT_ADD_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_SUB_F64 (SLJIT_FOP2_BASE + 1)
-#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_SUB_F32 (SLJIT_SUB_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_MUL_F64 (SLJIT_FOP2_BASE + 2)
-#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_F32_OP)
-/* Flags: - (does not modify flags) */
+#define SLJIT_MUL_F32 (SLJIT_MUL_F64 | SLJIT_32)
+/* Flags: - (may destroy flags) */
#define SLJIT_DIV_F64 (SLJIT_FOP2_BASE + 3)
-#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_F32_OP)
+#define SLJIT_DIV_F32 (SLJIT_DIV_F64 | SLJIT_32)
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
@@ -1170,33 +1202,35 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
#define SLJIT_SET_OVERFLOW SLJIT_SET(SLJIT_OVERFLOW)
#define SLJIT_NOT_OVERFLOW 11
-/* There is no SLJIT_CARRY or SLJIT_NOT_CARRY. */
-#define SLJIT_SET_CARRY SLJIT_SET(12)
+/* Unlike other flags, sljit_emit_jump may destroy this flag. */
+#define SLJIT_CARRY 12
+#define SLJIT_SET_CARRY SLJIT_SET(SLJIT_CARRY)
+#define SLJIT_NOT_CARRY 13
/* Floating point comparison types. */
#define SLJIT_EQUAL_F64 14
-#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_EQUAL_F32 (SLJIT_EQUAL_F64 | SLJIT_32)
#define SLJIT_SET_EQUAL_F SLJIT_SET(SLJIT_EQUAL_F64)
#define SLJIT_NOT_EQUAL_F64 15
-#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_NOT_EQUAL_F32 (SLJIT_NOT_EQUAL_F64 | SLJIT_32)
#define SLJIT_SET_NOT_EQUAL_F SLJIT_SET(SLJIT_NOT_EQUAL_F64)
#define SLJIT_LESS_F64 16
-#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_F32_OP)
+#define SLJIT_LESS_F32 (SLJIT_LESS_F64 | SLJIT_32)
#define SLJIT_SET_LESS_F SLJIT_SET(SLJIT_LESS_F64)
#define SLJIT_GREATER_EQUAL_F64 17
-#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_GREATER_EQUAL_F32 (SLJIT_GREATER_EQUAL_F64 | SLJIT_32)
#define SLJIT_SET_GREATER_EQUAL_F SLJIT_SET(SLJIT_GREATER_EQUAL_F64)
#define SLJIT_GREATER_F64 18
-#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_F32_OP)
+#define SLJIT_GREATER_F32 (SLJIT_GREATER_F64 | SLJIT_32)
#define SLJIT_SET_GREATER_F SLJIT_SET(SLJIT_GREATER_F64)
#define SLJIT_LESS_EQUAL_F64 19
-#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_F32_OP)
+#define SLJIT_LESS_EQUAL_F32 (SLJIT_LESS_EQUAL_F64 | SLJIT_32)
#define SLJIT_SET_LESS_EQUAL_F SLJIT_SET(SLJIT_LESS_EQUAL_F64)
#define SLJIT_UNORDERED_F64 20
-#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_F32_OP)
+#define SLJIT_UNORDERED_F32 (SLJIT_UNORDERED_F64 | SLJIT_32)
#define SLJIT_SET_UNORDERED_F SLJIT_SET(SLJIT_UNORDERED_F64)
#define SLJIT_ORDERED_F64 21
-#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_F32_OP)
+#define SLJIT_ORDERED_F32 (SLJIT_ORDERED_F64 | SLJIT_32)
#define SLJIT_SET_ORDERED_F SLJIT_SET(SLJIT_ORDERED_F64)
/* Unconditional jump types. */
@@ -1211,6 +1245,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
/* The target can be changed during runtime (see: sljit_set_jump_addr). */
#define SLJIT_REWRITABLE_JUMP 0x1000
+/* When this flag is passed, the execution of the current function ends and
+ the called function returns to the caller of the current function. The
+ stack usage is reduced before the call, but it is not necessarily reduced
+ to zero. In the latter case the compiler needs to allocate space for some
+ arguments and the return register must be kept as well.
+
+ This feature is highly experimental and not supported on SPARC platform
+ at the moment. */
+#define SLJIT_CALL_RETURN 0x2000
/* Emit a jump instruction. The destination is not set, only the type of the jump.
type must be between SLJIT_EQUAL and SLJIT_FAST_CALL
@@ -1221,15 +1264,14 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
/* Emit a C compiler (ABI) compatible function call.
type must be SLJIT_CALL or SLJIT_CALL_CDECL
- type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP
+ type can be combined (or'ed) with SLJIT_REWRITABLE_JUMP and SLJIT_CALL_RETURN
arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros
Flags: destroy all flags. */
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type, sljit_s32 arg_types);
/* Basic arithmetic comparison. In most architectures it is implemented as
- an SLJIT_SUB operation (with SLJIT_UNUSED destination and setting
- appropriate flags) followed by a sljit_emit_jump. However some
+ an compare operation followed by a sljit_emit_jump. However some
architectures (i.e: ARM64 or MIPS) may employ special optimizations here.
It is suggested to use this comparison form when appropriate.
type must be between SLJIT_EQUAL and SLJIT_I_SIG_LESS_EQUAL
@@ -1271,6 +1313,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
Direct form: set src to SLJIT_IMM() and srcw to the address
Indirect form: any other valid addressing mode
type must be SLJIT_CALL or SLJIT_CALL_CDECL
+ type can be combined (or'ed) with SLJIT_CALL_RETURN
arg_types is the combination of SLJIT_RET / SLJIT_ARGx (SLJIT_DEF_RET / SLJIT_DEF_ARGx) macros
Flags: destroy all flags. */
@@ -1298,7 +1341,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
type must be between SLJIT_EQUAL and SLJIT_ORDERED_F64
dst_reg must be a valid register and it can be combined
- with SLJIT_I32_OP to perform a 32 bit arithmetic operation
+ with SLJIT_32 to perform a 32 bit arithmetic operation
src must be register or immediate (SLJIT_IMM)
Flags: - (does not modify flags) */
@@ -1454,26 +1497,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st
#if !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
-/* Get the entry address of a given function. */
-#define SLJIT_FUNC_OFFSET(func_name) ((sljit_sw)func_name)
+/* Get the entry address of a given function (signed, unsigned result). */
+#define SLJIT_FUNC_ADDR(func_name) ((sljit_sw)func_name)
+#define SLJIT_FUNC_UADDR(func_name) ((sljit_uw)func_name)
#else /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
/* All JIT related code should be placed in the same context (library, binary, etc.). */
-#define SLJIT_FUNC_OFFSET(func_name) (*(sljit_sw*)(void*)func_name)
+/* Get the entry address of a given function (signed, unsigned result). */
+#define SLJIT_FUNC_ADDR(func_name) (*(sljit_sw*)(void*)func_name)
+#define SLJIT_FUNC_UADDR(func_name) (*(sljit_uw*)(void*)func_name)
/* For powerpc64, the function pointers point to a context descriptor. */
struct sljit_function_context {
- sljit_sw addr;
- sljit_sw r2;
- sljit_sw r11;
+ sljit_uw addr;
+ sljit_uw r2;
+ sljit_uw r11;
};
/* Fill the context arguments using the addr and the function.
If func_ptr is NULL, it will not be set to the address of context
If addr is NULL, the function address also comes from the func pointer. */
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func);
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func);
#endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */
@@ -1516,17 +1562,19 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size);
+ void *instruction, sljit_u32 size);
/* Flags were set by a 32 bit operation. */
-#define SLJIT_CURRENT_FLAGS_I32_OP SLJIT_I32_OP
+#define SLJIT_CURRENT_FLAGS_32 SLJIT_32
-/* Flags were set by an ADD, ADDC, SUB, SUBC, or NEG operation. */
-#define SLJIT_CURRENT_FLAGS_ADD_SUB 0x01
+/* Flags were set by an ADD or ADDC operations. */
+#define SLJIT_CURRENT_FLAGS_ADD 0x01
+/* Flags were set by a SUB, SUBC, or NEG operation. */
+#define SLJIT_CURRENT_FLAGS_SUB 0x02
-/* Flags were set by a SUB with unused destination.
- Must be combined with SLJIT_CURRENT_FLAGS_ADD_SUB. */
-#define SLJIT_CURRENT_FLAGS_COMPARE 0x02
+/* Flags were set by sljit_emit_op2u with SLJIT_SUB opcode.
+ Must be combined with SLJIT_CURRENT_FLAGS_SUB. */
+#define SLJIT_CURRENT_FLAGS_COMPARE 0x04
/* Define the currently available CPU status flags. It is usually used after
an sljit_emit_label or sljit_emit_op_custom operations to define which CPU
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
index 74cf55fcd2..7b87f5907a 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_32.c
@@ -65,12 +65,17 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 1, 2, 3, 4, 5, 6, 7
+ 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7
};
-#define RM(rm) (reg_map[rm])
-#define RD(rd) (reg_map[rd] << 12)
-#define RN(rn) (reg_map[rn] << 16)
+#define RM(rm) ((sljit_uw)reg_map[rm])
+#define RM8(rm) ((sljit_uw)reg_map[rm] << 8)
+#define RD(rd) ((sljit_uw)reg_map[rd] << 12)
+#define RN(rn) ((sljit_uw)reg_map[rn] << 16)
+
+#define VM(rm) ((sljit_uw)freg_map[rm])
+#define VD(rd) ((sljit_uw)freg_map[rd] << 12)
+#define VN(rn) ((sljit_uw)freg_map[rn] << 16)
/* --------------------------------------------------------------------- */
/* Instrucion forms */
@@ -107,6 +112,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SBC 0xe0c00000
#define SMULL 0xe0c00090
#define SUB 0xe0400000
+#define TST 0xe1000000
#define UMULL 0xe0800090
#define VABS_F32 0xeeb00ac0
#define VADD_F32 0xee300a00
@@ -115,12 +121,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define VCVT_F64_F32 0xeeb70ac0
#define VCVT_S32_F32 0xeebd0ac0
#define VDIV_F32 0xee800a00
+#define VLDR_F32 0xed100a00
#define VMOV_F32 0xeeb00a40
#define VMOV 0xee000a10
#define VMOV2 0xec400a10
#define VMRS 0xeef1fa10
#define VMUL_F32 0xee200a00
#define VNEG_F32 0xeeb10a40
+#define VPOP 0xecbd0b00
+#define VPUSH 0xed2d0b00
#define VSTR_F32 0xed000a00
#define VSUB_F32 0xee300a40
@@ -204,7 +213,7 @@ static sljit_s32 push_inst_with_literal(struct sljit_compiler *compiler, sljit_u
cpool_unique_ptr = compiler->cpool_unique;
do {
if ((*cpool_ptr == literal) && !(*cpool_unique_ptr)) {
- cpool_index = cpool_ptr - compiler->cpool;
+ cpool_index = (sljit_uw)(cpool_ptr - compiler->cpool);
break;
}
cpool_ptr++;
@@ -293,7 +302,7 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
while (last_pc_patch < code_ptr) {
/* Data transfer instruction with Rn == r15. */
if ((*last_pc_patch & 0x0c0f0000) == 0x040f0000) {
- diff = const_pool - last_pc_patch;
+ diff = (sljit_uw)(const_pool - last_pc_patch);
ind = (*last_pc_patch) & 0xfff;
/* Must be a load instruction with immediate offset. */
@@ -308,12 +317,12 @@ static sljit_uw patch_pc_relative_loads(sljit_uw *last_pc_patch, sljit_uw *code_
SLJIT_ASSERT(diff >= 1);
if (diff >= 2 || ind > 0) {
- diff = (diff + ind - 2) << 2;
+ diff = (diff + (sljit_uw)ind - 2) << 2;
SLJIT_ASSERT(diff <= 0xfff);
- *last_pc_patch = (*last_pc_patch & ~0xfff) | diff;
+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)0xfff) | diff;
}
else
- *last_pc_patch = (*last_pc_patch & ~(0xfff | (1 << 23))) | 0x004;
+ *last_pc_patch = (*last_pc_patch & ~(sljit_uw)(0xfff | (1 << 23))) | 0x004;
}
last_pc_patch++;
}
@@ -329,24 +338,24 @@ struct future_patch {
static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struct future_patch **first_patch, sljit_uw cpool_current_index, sljit_uw *cpool_start_address, sljit_uw *buf_ptr)
{
- sljit_s32 value;
+ sljit_u32 value;
struct future_patch *curr_patch, *prev_patch;
SLJIT_UNUSED_ARG(compiler);
/* Using the values generated by patch_pc_relative_loads. */
if (!*first_patch)
- value = (sljit_s32)cpool_start_address[cpool_current_index];
+ value = cpool_start_address[cpool_current_index];
else {
curr_patch = *first_patch;
prev_patch = NULL;
while (1) {
if (!curr_patch) {
- value = (sljit_s32)cpool_start_address[cpool_current_index];
+ value = cpool_start_address[cpool_current_index];
break;
}
if ((sljit_uw)curr_patch->index == cpool_current_index) {
- value = curr_patch->value;
+ value = (sljit_uw)curr_patch->value;
if (prev_patch)
prev_patch->next = curr_patch->next;
else
@@ -359,8 +368,8 @@ static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struc
}
}
- if (value >= 0) {
- if ((sljit_uw)value > cpool_current_index) {
+ if ((sljit_sw)value >= 0) {
+ if (value > cpool_current_index) {
curr_patch = (struct future_patch*)SLJIT_MALLOC(sizeof(struct future_patch), compiler->allocator_data);
if (!curr_patch) {
while (*first_patch) {
@@ -371,8 +380,8 @@ static sljit_s32 resolve_const_pool_index(struct sljit_compiler *compiler, struc
return SLJIT_ERR_ALLOC_FAILED;
}
curr_patch->next = *first_patch;
- curr_patch->index = value;
- curr_patch->value = cpool_start_address[value];
+ curr_patch->index = (sljit_sw)value;
+ curr_patch->value = (sljit_sw)cpool_start_address[value];
*first_patch = curr_patch;
}
cpool_start_address[value] = *buf_ptr;
@@ -395,8 +404,8 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_uw inst)
static SLJIT_INLINE sljit_s32 emit_imm(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
{
- FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff)));
- return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | ((imm >> 16) & 0xfff));
+ FAIL_IF(push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | ((sljit_u32)imm & 0xfff)));
+ return push_inst(compiler, MOVT | RD(reg) | ((imm >> 12) & 0xf0000) | (((sljit_u32)imm >> 16) & 0xfff));
}
#endif
@@ -554,8 +563,9 @@ static SLJIT_INLINE void inline_set_jump_addr(sljit_uw jump_ptr, sljit_sw execut
}
static sljit_uw get_imm(sljit_uw imm);
+static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg, sljit_uw imm);
-static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_sw new_constant, sljit_s32 flush_cache)
+static SLJIT_INLINE void inline_set_const(sljit_uw addr, sljit_sw executable_offset, sljit_uw new_constant, sljit_s32 flush_cache)
{
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw *ptr = (sljit_uw*)addr;
@@ -658,7 +668,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw word_count;
sljit_uw next_addr;
sljit_sw executable_offset;
- sljit_sw addr;
+ sljit_uw addr;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
sljit_uw cpool_size;
sljit_uw cpool_skip_alignment;
@@ -737,7 +747,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
/* Points after the current instruction. */
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
next_addr = compute_next_addr(label, jump, const_, put_label);
@@ -770,7 +780,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
/* code_ptr can be affected above. */
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr + 1, executable_offset);
- label->size = (code_ptr + 1) - code;
+ label->size = (sljit_uw)((code_ptr + 1) - code);
label = label->next;
}
if (const_ && const_->addr == word_count) {
@@ -799,8 +809,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, cpool_size);
if (cpool_current_index > 0) {
/* Unconditional branch. */
- *code_ptr = B | (((cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
- code_ptr = cpool_start_address + cpool_current_index;
+ *code_ptr = B | (((sljit_uw)(cpool_start_address - code_ptr) + cpool_current_index - 2) & ~PUSH_POOL);
+ code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);
}
cpool_skip_alignment = CONST_POOL_ALIGNMENT - 1;
cpool_current_index = 0;
@@ -822,7 +832,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
cpool_start_address = ALIGN_INSTRUCTION(code_ptr);
cpool_current_index = patch_pc_relative_loads(last_pc_patch, code_ptr, cpool_start_address, compiler->cpool_fill);
if (cpool_current_index > 0)
- code_ptr = cpool_start_address + cpool_current_index;
+ code_ptr = (sljit_uw*)(cpool_start_address + cpool_current_index);
buf_ptr = compiler->cpool;
buf_end = buf_ptr + compiler->cpool_fill;
@@ -845,15 +855,15 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr = (sljit_uw *)jump->addr;
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
+ addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr + 2, executable_offset);
if (!(jump->flags & JUMP_ADDR)) {
SLJIT_ASSERT(jump->flags & JUMP_LABEL);
- SLJIT_ASSERT(((sljit_sw)jump->u.label->addr - addr) <= 0x01ffffff && ((sljit_sw)jump->u.label->addr - addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.label->addr - addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - addr) <= 0x01ffffff && (sljit_sw)(jump->u.label->addr - addr) >= -0x02000000);
+ *buf_ptr |= ((jump->u.label->addr - addr) >> 2) & 0x00ffffff;
}
else {
- SLJIT_ASSERT(((sljit_sw)jump->u.target - addr) <= 0x01ffffff && ((sljit_sw)jump->u.target - addr) >= -0x02000000);
- *buf_ptr |= (((sljit_sw)jump->u.target - addr) >> 2) & 0x00ffffff;
+ SLJIT_ASSERT((sljit_sw)(jump->u.target - addr) <= 0x01ffffff && (sljit_sw)(jump->u.target - addr) >= -0x02000000);
+ *buf_ptr |= ((jump->u.target - addr) >> 2) & 0x00ffffff;
}
}
else if (jump->flags & SLJIT_REWRITABLE_JUMP) {
@@ -923,7 +933,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_uw);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_uw);
code = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
code_ptr = (sljit_uw *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -972,6 +982,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#define ALLOW_IMM 0x10
#define ALLOW_INV_IMM 0x20
#define ALLOW_ANY_IMM (ALLOW_IMM | ALLOW_INV_IMM)
+#define ALLOW_NEG_IMM 0x40
/* s/l - store/load (1 bit)
u/s - signed/unsigned (1 bit)
@@ -999,7 +1010,7 @@ static const sljit_uw data_transfer_insts[16] = {
};
#define EMIT_DATA_TRANSFER(type, add, target_reg, base_reg, arg) \
- (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (arg))
+ (data_transfer_insts[(type) & 0xf] | ((add) << 23) | RD(target_reg) | RN(base_reg) | (sljit_uw)(arg))
/* Normal ldr/str instruction.
Type2: ldrsb, ldrh, ldrsh */
@@ -1008,6 +1019,26 @@ static const sljit_uw data_transfer_insts[16] = {
#define TYPE2_TRANSFER_IMM(imm) \
(((imm) & 0xf) | (((imm) & 0xf0) << 4) | (1 << 22))
+#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
+ ((sljit_uw)(opcode) | (sljit_uw)(mode) | VD(dst) | VM(src1) | VN(src2))
+
+/* Flags for emit_op: */
+ /* Arguments are swapped. */
+#define ARGS_SWAPPED 0x01
+ /* Inverted immediate. */
+#define INV_IMM 0x02
+ /* Source and destination is register. */
+#define MOVE_REG_CONV 0x04
+ /* Unused return value. */
+#define UNUSED_RETURN 0x08
+/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
+#define SET_FLAGS (1 << 20)
+/* dst: reg
+ src1: reg
+ src2: reg or imm (if allowed)
+ SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
+#define SRC2_IMM (1 << 25)
+
static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 inp_flags,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
@@ -1017,41 +1048,161 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args, size, i, tmp;
- sljit_uw push;
+ sljit_uw imm, offset;
+ sljit_s32 i, tmp, size, word_arg_count, saved_arg_count;
+#ifdef __SOFTFP__
+ sljit_u32 float_arg_count;
+#else
+ sljit_u32 old_offset, f32_offset;
+ sljit_u32 remap[3];
+ sljit_u32 *remap_ptr = remap;
+#endif
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- /* Push saved registers, temporary registers
- stmdb sp!, {..., lr} */
- push = PUSH | (1 << 14);
+ imm = 0;
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--)
- push |= 1 << reg_map[i];
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
- push |= 1 << reg_map[i];
+ imm |= (sljit_uw)1 << reg_map[i];
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- FAIL_IF(push_inst(compiler, push));
+ /* Push saved and temporary registers
+ multiple registers: stmdb sp!, {..., lr}
+ single register: str reg, [sp, #-4]! */
+ if (imm != 0)
+ FAIL_IF(push_inst(compiler, PUSH | (1 << 14) | imm));
+ else
+ FAIL_IF(push_inst(compiler, 0xe52d0004 | RD(TMP_REG2)));
/* Stack must be aligned to 8 bytes: */
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- local_size = ((size + local_size + 7) & ~7) - size;
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((size & SSIZE_OF(sw)) != 0) {
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | sizeof(sljit_sw)));
+ size += SSIZE_OF(sw);
+ }
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fsaveds > 0)
+ FAIL_IF(push_inst(compiler, VPUSH | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst(compiler, VPUSH | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ }
+ }
+
+ local_size = ((size + local_size + 0x7) & ~0x7) - size;
compiler->local_size = local_size;
- if (local_size > 0)
- FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
- args = get_arg_count(arg_types);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+#ifdef __SOFTFP__
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+
+ offset = 0;
+ float_arg_count = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ else
+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800100 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
+ else
+ FAIL_IF(push_inst(compiler, VLDR_F32 | 0x800000 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
+ tmp = word_arg_count;
+ else
+ break;
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst(compiler, MOV | RD(tmp) | (offset >> 2)));
+ else
+ FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
+ | RN(SLJIT_SP) | RD(tmp) | (offset + (sljit_uw)size - 4 * sizeof(sljit_sw))));
+ break;
+ }
+
+ offset += sizeof(sljit_sw);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = offset;
+#else
+ offset = SLJIT_FR0;
+ old_offset = SLJIT_FR0;
+ f32_offset = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != old_offset)
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, SLJIT_32, offset, old_offset, 0);
+ old_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0x20, offset, f32_offset, 0);
+ f32_offset = 0;
+ } else {
+ if (offset != old_offset)
+ *remap_ptr++ = EMIT_FPU_OPERATION(VMOV_F32, 0, offset, old_offset, 0);
+ f32_offset = old_offset;
+ old_offset++;
+ }
+ offset++;
+ break;
+ default:
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0 - saved_arg_count) | RM(SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
+
+ word_arg_count++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
- if (args >= 1)
- FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S0) | RM(SLJIT_R0)));
- if (args >= 2)
- FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S1) | RM(SLJIT_R1)));
- if (args >= 3)
- FAIL_IF(push_inst(compiler, MOV | RD(SLJIT_S2) | RM(SLJIT_R2)));
+ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
+
+ while (remap_ptr > remap)
+ FAIL_IF(push_inst(compiler, *(--remap_ptr)));
+#endif
+
+ if (local_size > 0)
+ FAIL_IF(emit_op(compiler, SLJIT_SUB, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
return SLJIT_SUCCESS;
}
@@ -1067,58 +1218,129 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- compiler->local_size = ((size + local_size + 7) & ~7) - size;
+
+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
+ size += SSIZE_OF(sw);
+
+ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
{
- sljit_s32 i, tmp;
- sljit_uw pop;
+ sljit_uw imm2 = get_imm(imm);
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+ if (imm2 == 0) {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, imm));
+ imm2 = RM(TMP_REG2);
+ }
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | imm2);
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
+{
+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;
+ sljit_s32 lr_dst = TMP_PC;
+ sljit_uw reg_list;
- if (compiler->local_size > 0)
- FAIL_IF(emit_op(compiler, SLJIT_ADD, ALLOW_IMM, SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14);
- /* Push saved registers, temporary registers
- ldmia sp!, {..., pc} */
- pop = POP | (1 << 15);
+ local_size = compiler->local_size;
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--)
- pop |= 1 << reg_map[i];
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst(compiler, VPOP | VD(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ if (fsaveds > 0)
+ FAIL_IF(push_inst(compiler, VPOP | VD(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ }
+
+ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
+ }
+
+ if (frame_size < 0) {
+ lr_dst = TMP_REG2;
+ frame_size = 0;
+ } else if (frame_size > 0)
+ lr_dst = 0;
+
+ reg_list = 0;
+ if (lr_dst != 0)
+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0; i > tmp; i--)
+ reg_list |= (sljit_uw)1 << reg_map[i];
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
- pop |= 1 << reg_map[i];
+ reg_list |= (sljit_uw)1 << reg_map[i];
+
+ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
+ /* The local_size does not include the saved registers. */
+ local_size += SSIZE_OF(sw);
+
+ if (reg_list != 0)
+ local_size += SSIZE_OF(sw);
+
+ if (frame_size > local_size)
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | (sljit_uw)(frame_size - local_size)));
+ else if (frame_size < local_size)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
+
+ if (reg_list == 0)
+ return SLJIT_SUCCESS;
+
+ if (compiler->saveds > 0) {
+ SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0]));
+ lr_dst = SLJIT_S0;
+ } else {
+ SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG]));
+ lr_dst = SLJIT_FIRST_SAVED_REG;
+ }
+
+ return push_inst(compiler, data_transfer_insts[WORD_SIZE | LOAD_DATA] | 0x800000
+ | RN(SLJIT_SP) | RD(lr_dst) | (sljit_uw)(frame_size - 2 * SSIZE_OF(sw)));
+ }
- return push_inst(compiler, pop);
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ /* Pop saved and temporary registers
+ multiple registers: ldmia sp!, {...}
+ single register: ldr reg, [sp], #4 */
+ if ((reg_list & (reg_list - 1)) == 0) {
+ SLJIT_ASSERT(lr_dst != 0);
+ SLJIT_ASSERT(reg_list == (sljit_uw)1 << reg_map[lr_dst]);
+
+ return push_inst(compiler, 0xe49d0004 | RD(lr_dst));
+ }
+
+ FAIL_IF(push_inst(compiler, POP | reg_list));
+ if (frame_size > 0)
+ return push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 25) | ((sljit_uw)frame_size - sizeof(sljit_sw)));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ return emit_stack_frame_release(compiler, 0);
}
/* --------------------------------------------------------------------- */
/* Operators */
/* --------------------------------------------------------------------- */
-/* flags: */
- /* Arguments are swapped. */
-#define ARGS_SWAPPED 0x01
- /* Inverted immediate. */
-#define INV_IMM 0x02
- /* Source and destination is register. */
-#define MOVE_REG_CONV 0x04
- /* Unused return value. */
-#define UNUSED_RETURN 0x08
-/* SET_FLAGS must be (1 << 20) as it is also the value of S bit (can be used for optimization). */
-#define SET_FLAGS (1 << 20)
-/* dst: reg
- src1: reg
- src2: reg or imm (if allowed)
- SRC2_IMM must be (1 << 25) as it is also the value of I bit (can be used for optimization). */
-#define SRC2_IMM (1 << 25)
-
#define EMIT_SHIFT_INS_AND_RETURN(opcode) \
SLJIT_ASSERT(!(flags & INV_IMM) && !(src2 & SRC2_IMM)); \
if (compiler->shift_imm != 0x20) { \
@@ -1130,11 +1352,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
RD(dst) | (compiler->shift_imm << 7) | (opcode << 5) | RM(src2)); \
return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | RM(src2)); \
} \
- return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) | \
- (reg_map[(flags & ARGS_SWAPPED) ? src1 : src2] << 8) | (opcode << 5) | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1));
+ return push_inst(compiler, MOV | (flags & SET_FLAGS) | RD(dst) \
+ | RM8((flags & ARGS_SWAPPED) ? src1 : src2) | (sljit_uw)(opcode << 5) \
+ | 0x10 | RM((flags & ARGS_SWAPPED) ? src2 : src1));
static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
- sljit_s32 dst, sljit_s32 src1, sljit_s32 src2)
+ sljit_uw dst, sljit_uw src1, sljit_uw src2)
{
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
@@ -1184,9 +1407,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return SLJIT_SUCCESS;
case SLJIT_NOT:
- if (src2 & SRC2_IMM) {
+ if (src2 & SRC2_IMM)
return push_inst(compiler, ((flags & INV_IMM) ? MOV : MVN) | (flags & SET_FLAGS) | RD(dst) | src2);
- }
+
return push_inst(compiler, MVN | (flags & SET_FLAGS) | RD(dst) | RM(src2));
case SLJIT_CLZ:
@@ -1197,9 +1420,8 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_ADD:
SLJIT_ASSERT(!(flags & INV_IMM));
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
return push_inst(compiler, CMN | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
return push_inst(compiler, ADD | (flags & SET_FLAGS) | RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
@@ -1209,10 +1431,10 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
case SLJIT_SUB:
SLJIT_ASSERT(!(flags & INV_IMM));
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- if ((flags & (UNUSED_RETURN | SET_FLAGS)) == (UNUSED_RETURN | SET_FLAGS) && !(flags & ARGS_SWAPPED))
+ if ((flags & (UNUSED_RETURN | ARGS_SWAPPED)) == UNUSED_RETURN)
return push_inst(compiler, CMP | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
+
return push_inst(compiler, (!(flags & ARGS_SWAPPED) ? SUB : RSB) | (flags & SET_FLAGS)
| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
@@ -1227,14 +1449,16 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
compiler->status_flags_state = 0;
if (!HAS_FLAGS(op))
- return push_inst(compiler, MUL | (reg_map[dst] << 16) | (reg_map[src2] << 8) | reg_map[src1]);
+ return push_inst(compiler, MUL | RN(dst) | RM8(src2) | RM(src1));
- FAIL_IF(push_inst(compiler, SMULL | (reg_map[TMP_REG1] << 16) | (reg_map[dst] << 12) | (reg_map[src2] << 8) | reg_map[src1]));
+ FAIL_IF(push_inst(compiler, SMULL | RN(TMP_REG1) | RD(dst) | RM8(src2) | RM(src1)));
/* cmp TMP_REG1, dst asr #31. */
return push_inst(compiler, CMP | SET_FLAGS | RN(TMP_REG1) | RM(dst) | 0xfc0);
case SLJIT_AND:
+ if ((flags & (UNUSED_RETURN | INV_IMM)) == UNUSED_RETURN)
+ return push_inst(compiler, TST | SET_FLAGS | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
return push_inst(compiler, (!(flags & INV_IMM) ? AND : BIC) | (flags & SET_FLAGS)
| RD(dst) | RN(src1) | ((src2 & SRC2_IMM) ? src2 : RM(src2)));
@@ -1266,7 +1490,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
Returns with 0 if not possible. */
static sljit_uw get_imm(sljit_uw imm)
{
- sljit_s32 rol;
+ sljit_u32 rol;
if (imm <= 0xff)
return SRC2_IMM | imm;
@@ -1307,7 +1531,7 @@ static sljit_s32 generate_int(struct sljit_compiler *compiler, sljit_s32 reg, sl
sljit_uw mask;
sljit_uw imm1;
sljit_uw imm2;
- sljit_s32 rol;
+ sljit_uw rol;
/* Step1: Search a zero byte (8 continous zero bit). */
mask = 0xff000000;
@@ -1418,7 +1642,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
sljit_uw tmp;
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
- if (!(imm & ~0xffff))
+ if (!(imm & ~(sljit_uw)0xffff))
return push_inst(compiler, MOVW | RD(reg) | ((imm << 4) & 0xf0000) | (imm & 0xfff));
#endif
@@ -1455,13 +1679,13 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
SLJIT_ASSERT (arg & SLJIT_MEM);
SLJIT_ASSERT((arg & REG_MASK) != tmp_reg);
- if ((arg & REG_MASK) == SLJIT_UNUSED) {
+ if (!(arg & REG_MASK)) {
if (is_type1_transfer) {
- FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xfff));
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xfff));
argw &= 0xfff;
}
else {
- FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~0xff));
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw & ~(sljit_uw)0xff));
argw &= 0xff;
}
@@ -1475,20 +1699,20 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
argw &= 0x3;
if (argw != 0 && !is_type1_transfer) {
- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | (argw << 7)));
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | RM(offset_reg) | ((sljit_uw)argw << 7)));
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, tmp_reg, TYPE2_TRANSFER_IMM(0)));
}
/* Bit 25: RM is offset. */
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
- RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | (argw << 7)));
+ RM(offset_reg) | (is_type1_transfer ? (1 << 25) : 0) | ((sljit_uw)argw << 7)));
}
arg &= REG_MASK;
if (is_type1_transfer) {
if (argw > 0xfff) {
- imm = get_imm(argw & ~0xfff);
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
argw = argw & 0xfff;
@@ -1496,7 +1720,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
else if (argw < -0xfff) {
- imm = get_imm(-argw & ~0xfff);
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xfff);
if (imm) {
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
argw = -(-argw & 0xfff);
@@ -1512,7 +1736,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
else {
if (argw > 0xff) {
- imm = get_imm(argw & ~0xff);
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0xff);
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg) | imm));
argw = argw & 0xff;
@@ -1520,7 +1744,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
else if (argw < -0xff) {
- imm = get_imm(-argw & ~0xff);
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
if (imm) {
FAIL_IF(push_inst(compiler, SUB | RD(tmp_reg) | RN(arg) | imm));
argw = -(-argw & 0xff);
@@ -1537,7 +1761,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
- FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
return push_inst(compiler, EMIT_DATA_TRANSFER(flags, 1, reg, arg,
RM(tmp_reg) | (is_type1_transfer ? (1 << 25) : 0)));
}
@@ -1554,50 +1778,62 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
/* We prefers register and simple consts. */
sljit_s32 dst_reg;
sljit_s32 src1_reg;
- sljit_s32 src2_reg;
+ sljit_s32 src2_reg = 0;
sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_s32 neg_op = 0;
- /* Destination check. */
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
+ if (dst == TMP_REG2)
flags |= UNUSED_RETURN;
SLJIT_ASSERT(!(inp_flags & ALLOW_INV_IMM) || (inp_flags & ALLOW_IMM));
- src2_reg = 0;
+ if (inp_flags & ALLOW_NEG_IMM) {
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ neg_op = SLJIT_SUB;
+ break;
+ case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ neg_op = SLJIT_SUBC;
+ break;
+ case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ neg_op = SLJIT_ADD;
+ break;
+ case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ neg_op = SLJIT_ADDC;
+ break;
+ }
+ }
do {
if (!(inp_flags & ALLOW_IMM))
break;
if (src2 & SLJIT_IMM) {
- src2_reg = get_imm(src2w);
+ src2_reg = (sljit_s32)get_imm((sljit_uw)src2w);
if (src2_reg)
break;
if (inp_flags & ALLOW_INV_IMM) {
- src2_reg = get_imm(~src2w);
+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src2w);
if (src2_reg) {
flags |= INV_IMM;
break;
}
}
- if (GET_OPCODE(op) == SLJIT_ADD) {
- src2_reg = get_imm(-src2w);
+ if (neg_op != 0) {
+ src2_reg = (sljit_s32)get_imm((sljit_uw)-src2w);
if (src2_reg) {
- op = SLJIT_SUB | GET_ALL_FLAGS(op);
- break;
- }
- }
- if (GET_OPCODE(op) == SLJIT_SUB) {
- src2_reg = get_imm(-src2w);
- if (src2_reg) {
- op = SLJIT_ADD | GET_ALL_FLAGS(op);
+ op = neg_op | GET_ALL_FLAGS(op);
break;
}
}
}
if (src1 & SLJIT_IMM) {
- src2_reg = get_imm(src1w);
+ src2_reg = (sljit_s32)get_imm((sljit_uw)src1w);
if (src2_reg) {
flags |= ARGS_SWAPPED;
src1 = src2;
@@ -1605,7 +1841,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
break;
}
if (inp_flags & ALLOW_INV_IMM) {
- src2_reg = get_imm(~src1w);
+ src2_reg = (sljit_s32)get_imm(~(sljit_uw)src1w);
if (src2_reg) {
flags |= ARGS_SWAPPED | INV_IMM;
src1 = src2;
@@ -1613,13 +1849,13 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
break;
}
}
- if (GET_OPCODE(op) == SLJIT_ADD) {
- src2_reg = get_imm(-src1w);
+ if (neg_op >= SLJIT_SUB) {
+ /* Note: additive operation (commutative). */
+ src2_reg = (sljit_s32)get_imm((sljit_uw)-src1w);
if (src2_reg) {
- /* Note: add is commutative operation. */
src1 = src2;
src1w = src2w;
- op = SLJIT_SUB | GET_ALL_FLAGS(op);
+ op = neg_op | GET_ALL_FLAGS(op);
break;
}
}
@@ -1634,12 +1870,12 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
src1_reg = TMP_REG1;
}
else {
- FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)src1w));
src1_reg = TMP_REG1;
}
/* Destination. */
- dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG2;
if (op <= SLJIT_MOV_P) {
if (dst & SLJIT_MEM) {
@@ -1663,10 +1899,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
else if (src2 & SLJIT_MEM)
FAIL_IF(emit_op_mem(compiler, inp_flags | LOAD_DATA, src2_reg, src2, src2w, TMP_REG2));
else
- FAIL_IF(load_immediate(compiler, src2_reg, src2w));
+ FAIL_IF(load_immediate(compiler, src2_reg, (sljit_uw)src2w));
}
- FAIL_IF(emit_single_op(compiler, op, flags, dst_reg, src1_reg, src2_reg));
+ FAIL_IF(emit_single_op(compiler, op, flags, (sljit_uw)dst_reg, (sljit_uw)src1_reg, (sljit_uw)src2_reg));
if (!(dst & SLJIT_MEM))
return SLJIT_SUCCESS;
@@ -1691,7 +1927,7 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
- sljit_sw saved_reg_list[3];
+ sljit_uw saved_reg_list[3];
sljit_sw saved_reg_count;
CHECK_ERROR();
@@ -1708,10 +1944,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_LMUL_UW:
case SLJIT_LMUL_SW:
return push_inst(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
- | (reg_map[SLJIT_R1] << 16)
- | (reg_map[SLJIT_R0] << 12)
- | (reg_map[SLJIT_R0] << 8)
- | reg_map[SLJIT_R1]);
+ | RN(SLJIT_R1) | RD(SLJIT_R0) | RM8(SLJIT_R0) | RM(SLJIT_R1));
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
case SLJIT_DIV_UW:
@@ -1742,7 +1975,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
#if defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
@@ -1756,7 +1989,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
SLJIT_ASSERT(saved_reg_list[1] < 8);
FAIL_IF(push_inst(compiler, 0xe59d0004 | (saved_reg_list[1] << 12) /* ldr rX, [sp, #4] */));
}
- return push_inst(compiler, 0xe49d0000 | (saved_reg_count >= 3 ? 16 : 8)
+ return push_inst(compiler, 0xe49d0000 | (sljit_uw)(saved_reg_count >= 3 ? 16 : 8)
| (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */);
}
return SLJIT_SUCCESS;
@@ -1781,6 +2014,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
case SLJIT_MOV_P:
return emit_op(compiler, SLJIT_MOV, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
@@ -1799,13 +2033,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_NOT:
return emit_op(compiler, op, ALLOW_ANY_IMM, dst, dstw, TMP_REG1, 0, src, srcw);
- case SLJIT_NEG:
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- compiler->skip_checks = 1;
-#endif
- return sljit_emit_op2(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), dst, dstw, SLJIT_IMM, 0, src, srcw);
-
case SLJIT_CLZ:
return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw);
}
@@ -1819,19 +2046,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src2, sljit_sw src2w)
{
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
case SLJIT_ADDC:
case SLJIT_SUB:
case SLJIT_SUBC:
+ return emit_op(compiler, op, ALLOW_IMM | ALLOW_NEG_IMM, dst, dstw, src1, src1w, src2, src2w);
+
case SLJIT_OR:
case SLJIT_XOR:
return emit_op(compiler, op, ALLOW_IMM, dst, dstw, src1, src1w, src2, src2w);
@@ -1858,6 +2084,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -1905,8 +2145,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
+ SLJIT_UNUSED_ARG(size);
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1917,23 +2158,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-
#define FPU_LOAD (1 << 20)
#define EMIT_FPU_DATA_TRANSFER(inst, add, base, freg, offs) \
- ((inst) | ((add) << 23) | (reg_map[base] << 16) | (freg_map[freg] << 12) | (offs))
-#define EMIT_FPU_OPERATION(opcode, mode, dst, src1, src2) \
- ((opcode) | (mode) | (freg_map[dst] << 12) | freg_map[src1] | (freg_map[src2] << 16))
+ ((inst) | (sljit_uw)((add) << 23) | RN(base) | VD(freg) | (sljit_uw)(offs))
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
sljit_uw imm;
- sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
+ sljit_uw inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
SLJIT_ASSERT(arg & SLJIT_MEM);
arg &= ~SLJIT_MEM;
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((argw & 0x3) << 7)));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 7)));
arg = TMP_REG2;
argw = 0;
}
@@ -1945,12 +2183,12 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
if (!(-argw & ~0x3fc))
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 0, arg & REG_MASK, reg, (-argw) >> 2));
- imm = get_imm(argw & ~0x3fc);
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
if (imm) {
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, (argw & 0x3fc) >> 2));
}
- imm = get_imm(-argw & ~0x3fc);
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
if (imm) {
argw = -argw;
FAIL_IF(push_inst(compiler, SUB | RD(TMP_REG2) | RN(arg & REG_MASK) | imm));
@@ -1959,11 +2197,11 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
}
if (arg) {
- FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));
FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG2) | RN(arg & REG_MASK) | RM(TMP_REG2)));
}
else
- FAIL_IF(load_immediate(compiler, TMP_REG2, argw));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, (sljit_uw)argw));
return push_inst(compiler, EMIT_FPU_DATA_TRANSFER(inst, 1, TMP_REG2, reg, 0));
}
@@ -1972,17 +2210,17 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
src = TMP_FREG1;
}
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_F32_OP, TMP_FREG1, src, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_S32_F32, op & SLJIT_32, TMP_FREG1, src, 0)));
if (FAST_IS_REG(dst))
- return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | (freg_map[TMP_FREG1] << 16));
+ return push_inst(compiler, VMOV | (1 << 20) | RD(dst) | VN(TMP_FREG1));
/* Store the integer value from a VFP register. */
return emit_fop_mem(compiler, 0, TMP_FREG1, dst, dstw);
@@ -1994,23 +2232,23 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (FAST_IS_REG(src))
- FAIL_IF(push_inst(compiler, VMOV | RD(src) | (freg_map[TMP_FREG1] << 16)));
+ FAIL_IF(push_inst(compiler, VMOV | RD(src) | VN(TMP_FREG1)));
else if (src & SLJIT_MEM) {
/* Load the integer value into a VFP register. */
FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
}
else {
- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
- FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | (freg_map[TMP_FREG1] << 16)));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
+ FAIL_IF(push_inst(compiler, VMOV | RD(TMP_REG1) | VN(TMP_FREG1)));
}
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_F32_OP, dst_r, TMP_FREG1, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F32_S32, op & SLJIT_32, dst_r, TMP_FREG1, 0)));
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -2018,19 +2256,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src1 & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
src1 = TMP_FREG1;
}
if (src2 & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
src2 = TMP_FREG2;
}
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_F32_OP, src1, src2, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCMP_F32, op & SLJIT_32, src1, src2, 0)));
return push_inst(compiler, VMRS);
}
@@ -2042,16 +2280,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
CHECK_ERROR();
- SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw));
src = dst_r;
}
@@ -2059,25 +2297,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
case SLJIT_MOV_F64:
if (src != dst_r) {
if (dst_r != TMP_FREG1)
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, op & SLJIT_32, dst_r, src, 0)));
else
dst_r = src;
}
break;
case SLJIT_NEG_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VNEG_F32, op & SLJIT_32, dst_r, src, 0)));
break;
case SLJIT_ABS_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VABS_F32, op & SLJIT_32, dst_r, src, 0)));
break;
case SLJIT_CONV_F64_FROM_F32:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_F32_OP, dst_r, src, 0)));
- op ^= SLJIT_F32_OP;
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VCVT_F64_F32, op & SLJIT_32, dst_r, src, 0)));
+ op ^= SLJIT_32;
break;
}
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -2094,40 +2332,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src2 & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w));
src2 = TMP_FREG2;
}
if (src1 & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w));
src1 = TMP_FREG1;
}
switch (GET_OPCODE(op)) {
case SLJIT_ADD_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VADD_F32, op & SLJIT_32, dst_r, src2, src1)));
break;
case SLJIT_SUB_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VSUB_F32, op & SLJIT_32, dst_r, src2, src1)));
break;
case SLJIT_MUL_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMUL_F32, op & SLJIT_32, dst_r, src2, src1)));
break;
case SLJIT_DIV_F64:
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_F32_OP, dst_r, src2, src1)));
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VDIV_F32, op & SLJIT_32, dst_r, src2, src1)));
break;
}
if (dst_r == TMP_FREG1)
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw));
return SLJIT_SUCCESS;
}
@@ -2169,10 +2407,20 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_EQUAL_F64:
return 0x10000000;
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x20000000;
+ /* fallthrough */
+
case SLJIT_LESS:
case SLJIT_LESS_F64:
return 0x30000000;
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x30000000;
+ /* fallthrough */
+
case SLJIT_GREATER_EQUAL:
case SLJIT_GREATER_EQUAL_F64:
return 0x20000000;
@@ -2198,15 +2446,17 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
return 0xd0000000;
case SLJIT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x10000000;
+ /* fallthrough */
case SLJIT_UNORDERED_F64:
return 0x60000000;
case SLJIT_NOT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x00000000;
+ /* fallthrough */
case SLJIT_ORDERED_F64:
return 0x70000000;
@@ -2277,111 +2527,124 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
#ifdef __SOFTFP__
-static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
+static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
{
- sljit_s32 stack_offset = 0;
- sljit_s32 arg_count = 0;
- sljit_s32 word_arg_offset = 0;
- sljit_s32 float_arg_count = 0;
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
+ sljit_u32 word_arg_offset = 0;
+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);
+ sljit_u32 float_arg_count = 0;
sljit_s32 types = 0;
- sljit_s32 src_offset = 4 * sizeof(sljit_sw);
sljit_u8 offsets[4];
+ sljit_u8 *offset_ptr = offsets;
if (src && FAST_IS_REG(*src))
- src_offset = reg_map[*src] * sizeof(sljit_sw);
+ src_offset = (sljit_uw)reg_map[*src] * sizeof(sljit_sw);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_f32);
- arg_count++;
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f64);
float_arg_count++;
break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_offset & 0x7)
- stack_offset += sizeof(sljit_sw);
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_f64);
- arg_count++;
+ case SLJIT_ARG_TYPE_F32:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f32);
float_arg_count++;
break;
default:
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_sw);
- arg_count++;
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_sw);
word_arg_offset += sizeof(sljit_sw);
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
- if (stack_offset > 16)
- FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_offset - 16) + 0x7) & ~0x7)));
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ /* Keep lr register on the stack. */
+ if (is_tail_call)
+ offset += sizeof(sljit_sw);
+
+ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;
+
+ *extra_space = offset;
+
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
+ else
+ FAIL_IF(push_inst(compiler, SUB | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | offset));
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ *extra_space = 0;
+ }
/* Process arguments in reversed direction. */
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- arg_count--;
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
float_arg_count--;
- stack_offset = offsets[arg_count];
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT((offset & 0x7) == 0);
- if (stack_offset < 16) {
- if (src_offset == stack_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
*src = TMP_REG1;
}
- FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10)));
+ FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
} else
- FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
break;
- case SLJIT_ARG_TYPE_F64:
- arg_count--;
+ case SLJIT_ARG_TYPE_F32:
float_arg_count--;
- stack_offset = offsets[arg_count];
-
- SLJIT_ASSERT((stack_offset & 0x7) == 0);
+ offset = *(--offset_ptr);
- if (stack_offset < 16) {
- if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
*src = TMP_REG1;
}
- FAIL_IF(push_inst(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ FAIL_IF(push_inst(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
} else
- FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800100 | RN(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
+ FAIL_IF(push_inst(compiler, VSTR_F32 | 0x800000 | RN(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
break;
default:
- arg_count--;
word_arg_offset -= sizeof(sljit_sw);
- stack_offset = offsets[arg_count];
+ offset = *(--offset_ptr);
- SLJIT_ASSERT(stack_offset >= word_arg_offset);
+ SLJIT_ASSERT(offset >= word_arg_offset);
- if (stack_offset != word_arg_offset) {
- if (stack_offset < 16) {
- if (src_offset == stack_offset) {
+ if (offset != word_arg_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | (src_offset >> 2)));
*src = TMP_REG1;
}
else if (src_offset == word_arg_offset) {
- *src = 1 + (stack_offset >> 2);
- src_offset = stack_offset;
+ *src = (sljit_s32)(SLJIT_R0 + (offset >> 2));
+ src_offset = offset;
}
- FAIL_IF(push_inst(compiler, MOV | (stack_offset << 10) | (word_arg_offset >> 2)));
+ FAIL_IF(push_inst(compiler, MOV | (offset << 10) | (word_arg_offset >> 2)));
} else
- FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (stack_offset - 16)));
+ FAIL_IF(push_inst(compiler, data_transfer_insts[WORD_SIZE] | 0x800000 | RN(SLJIT_SP) | (word_arg_offset << 10) | (offset - 4 * sizeof(sljit_sw))));
}
break;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -2389,83 +2652,51 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit
static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
{
- sljit_s32 stack_size = 0;
-
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32)
- FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64)
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
FAIL_IF(push_inst(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
+ FAIL_IF(push_inst(compiler, VMOV | (0 << 16) | (0 << 12)));
- arg_types >>= SLJIT_DEF_SHIFT;
-
- while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- stack_size += sizeof(sljit_f32);
- break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_size & 0x7)
- stack_size += sizeof(sljit_sw);
- stack_size += sizeof(sljit_f64);
- break;
- default:
- stack_size += sizeof(sljit_sw);
- break;
- }
-
- arg_types >>= SLJIT_DEF_SHIFT;
- }
-
- if (stack_size <= 16)
- return SLJIT_SUCCESS;
-
- return push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | (((stack_size - 16) + 0x7) & ~0x7));
+ return SLJIT_SUCCESS;
}
#else /* !__SOFTFP__ */
static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
{
- sljit_u32 remap = 0;
- sljit_u32 offset = 0;
- sljit_u32 new_offset, mask;
+ sljit_u32 offset = SLJIT_FR0;
+ sljit_u32 new_offset = SLJIT_FR0;
+ sljit_u32 f32_offset = 0;
/* Remove return value. */
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) {
- new_offset = 0;
- mask = 1;
-
- while (remap & mask) {
- new_offset++;
- mask <<= 1;
- }
- remap |= mask;
-
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
if (offset != new_offset)
FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
- 0, (new_offset >> 1) + 1, (offset >> 1) + 1, 0) | ((new_offset & 0x1) ? 0x400000 : 0)));
+ SLJIT_32, new_offset, offset, 0)));
- offset += 2;
- }
- else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) {
- new_offset = 0;
- mask = 3;
-
- while (remap & mask) {
- new_offset += 2;
- mask <<= 2;
+ new_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
+ 0x400000, f32_offset, offset, 0)));
+ f32_offset = 0;
+ } else {
+ if (offset != new_offset)
+ FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32,
+ 0, new_offset, offset, 0)));
+ f32_offset = new_offset;
+ new_offset++;
}
- remap |= mask;
-
- if (offset != new_offset)
- FAIL_IF(push_inst(compiler, EMIT_FPU_OPERATION(VMOV_F32, SLJIT_F32_OP, (new_offset >> 1) + 1, (offset >> 1) + 1, 0)));
-
- offset += 2;
+ offset++;
+ break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -2480,13 +2711,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
{
#ifdef __SOFTFP__
struct sljit_jump *jump;
+ sljit_u32 extra_space = (sljit_u32)type;
#endif
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
#ifdef __SOFTFP__
- PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL));
+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2496,9 +2732,28 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
+
+ PTR_FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(push_inst(compiler, BX | RM(TMP_REG2)));
+ return jump;
+ }
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
#else /* !__SOFTFP__ */
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -2535,7 +2790,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
if (type >= SLJIT_FAST_CALL)
@@ -2555,16 +2810,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
+#ifdef __SOFTFP__
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
-#ifdef __SOFTFP__
if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, WORD_SIZE | LOAD_DATA, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
- FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src));
+ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) {
+ FAIL_IF(push_inst(compiler, MOV | RD(TMP_REG1) | RM(src)));
+ src = TMP_REG1;
+ }
+
+#ifdef __SOFTFP__
+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2573,8 +2841,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1,
+ TMP_REG2, SLJIT_SP, extra_space - sizeof(sljit_sw))));
+
+ FAIL_IF(push_inst(compiler, ADD | RD(SLJIT_SP) | RN(SLJIT_SP) | SRC2_IMM | extra_space));
+
+ if (type & SLJIT_CALL_RETURN)
+ return push_inst(compiler, BX | RM(TMP_REG2));
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
#else /* !__SOFTFP__ */
+ if (type & SLJIT_CALL_RETURN) {
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP;
+ }
+
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -2636,27 +2921,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
- dst_reg &= ~SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_32;
cc = get_cc(compiler, type & 0xff);
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
- tmp = get_imm(srcw);
+ tmp = get_imm((sljit_uw)srcw);
if (tmp)
return push_inst(compiler, ((MOV | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
- tmp = get_imm(~srcw);
+ tmp = get_imm(~(sljit_uw)srcw);
if (tmp)
return push_inst(compiler, ((MVN | RD(dst_reg) | tmp) & ~COND_MASK) | cc);
#if (defined SLJIT_CONFIG_ARM_V7 && SLJIT_CONFIG_ARM_V7)
- tmp = (sljit_uw) srcw;
+ tmp = (sljit_uw)srcw;
FAIL_IF(push_inst(compiler, (MOVW & ~COND_MASK) | cc | RD(dst_reg) | ((tmp << 4) & 0xf0000) | (tmp & 0xfff)));
if (tmp <= 0xffff)
return SLJIT_SUCCESS;
return push_inst(compiler, (MOVT & ~COND_MASK) | cc | RD(dst_reg) | ((tmp >> 12) & 0xf0000) | ((tmp >> 16) & 0xfff));
#else
- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
src = TMP_REG1;
#endif
}
@@ -2680,6 +2965,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
case SLJIT_MOV_P:
flags = WORD_SIZE;
break;
@@ -2731,7 +3017,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
if (SLJIT_UNLIKELY(mem & OFFS_REG_MASK)) {
memw &= 0x3;
- inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | (memw << 7));
+ inst = EMIT_DATA_TRANSFER(flags, 1, reg, mem & REG_MASK, RM(OFFS_REG(mem)) | ((sljit_uw)memw << 7));
if (is_type1_transfer)
inst |= (1 << 25);
@@ -2757,7 +3043,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
else
memw = -memw;
- return push_inst(compiler, inst | memw);
+ return push_inst(compiler, inst | (sljit_uw)memw);
}
if (memw >= 0)
@@ -2765,7 +3051,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
else
memw = -memw;
- return push_inst(compiler, inst | TYPE2_TRANSFER_IMM(memw));
+ return push_inst(compiler, inst | TYPE2_TRANSFER_IMM((sljit_uw)memw));
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2777,10 +3063,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value));
ADJUST_LOCAL_OFFSET(dst, dstw);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
- PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), init_value));
+ PTR_FAIL_IF(push_inst_with_unique_literal(compiler,
+ EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), (sljit_uw)init_value));
compiler->patches++;
#else
PTR_FAIL_IF(emit_imm(compiler, dst_r, init_value));
@@ -2804,7 +3091,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj
CHECK_PTR(check_sljit_emit_put_label(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG2;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG2;
#if (defined SLJIT_CONFIG_ARM_V5 && SLJIT_CONFIG_ARM_V5)
PTR_FAIL_IF(push_inst_with_unique_literal(compiler, EMIT_DATA_TRANSFER(WORD_SIZE | LOAD_DATA, 1, dst_r, TMP_PC, 0), 0));
@@ -2829,5 +3116,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- inline_set_const(addr, executable_offset, new_constant, 1);
+ inline_set_const(addr, executable_offset, (sljit_uw)new_constant, 1);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
index 3f0f5fcc30..96453b4abe 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_64.c
@@ -48,19 +48,20 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 1, 2, 3, 4, 5, 6, 7
+ 0, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 15, 14, 13, 12, 11, 10, 9, 8, 30, 31
};
-#define W_OP (1u << 31)
-#define RD(rd) (reg_map[rd])
-#define RT(rt) (reg_map[rt])
-#define RN(rn) (reg_map[rn] << 5)
-#define RT2(rt2) (reg_map[rt2] << 10)
-#define RM(rm) (reg_map[rm] << 16)
-#define VD(vd) (freg_map[vd])
-#define VT(vt) (freg_map[vt])
-#define VN(vn) (freg_map[vn] << 5)
-#define VM(vm) (freg_map[vm] << 16)
+#define W_OP ((sljit_ins)1 << 31)
+#define RD(rd) ((sljit_ins)reg_map[rd])
+#define RT(rt) ((sljit_ins)reg_map[rt])
+#define RN(rn) ((sljit_ins)reg_map[rn] << 5)
+#define RT2(rt2) ((sljit_ins)reg_map[rt2] << 10)
+#define RM(rm) ((sljit_ins)reg_map[rm] << 16)
+#define VD(vd) ((sljit_ins)freg_map[vd])
+#define VT(vt) ((sljit_ins)freg_map[vt])
+#define VT2(vt) ((sljit_ins)freg_map[vt] << 10)
+#define VN(vn) ((sljit_ins)freg_map[vn] << 5)
+#define VM(vm) ((sljit_ins)freg_map[vm] << 16)
/* --------------------------------------------------------------------- */
/* Instrucion forms */
@@ -96,8 +97,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define FNEG 0x1e614000
#define FSUB 0x1e603800
#define LDRI 0xf9400000
+#define LDRI_F64 0xfd400000
#define LDP 0xa9400000
-#define LDP_PRE 0xa9c00000
+#define LDP_F64 0x6d400000
+#define LDP_POST 0xa8c00000
#define LDR_PRE 0xf8400c00
#define LSLV 0x9ac02000
#define LSRV 0x9ac02400
@@ -117,10 +120,12 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SMADDL 0x9b200000
#define SMULH 0x9b403c00
#define STP 0xa9000000
+#define STP_F64 0x6d000000
#define STP_PRE 0xa9800000
#define STRB 0x38206800
#define STRBI 0x39000000
#define STRI 0xf9000000
+#define STRI_F64 0xfd000000
#define STR_FI 0x3d000000
#define STR_FR 0x3c206800
#define STUR_FI 0x3c000000
@@ -145,10 +150,10 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins)
static SLJIT_INLINE sljit_s32 emit_imm64_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_uw imm)
{
- FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));
- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 16) & 0xffff) << 5) | (1 << 21)));
- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((imm >> 32) & 0xffff) << 5) | (2 << 21)));
- return push_inst(compiler, MOVK | RD(dst) | ((imm >> 48) << 5) | (3 << 21));
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm & 0xffff) << 5)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 16) & 0xffff) << 5) | (1 << 21)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)(imm >> 32) & 0xffff) << 5) | (2 << 21)));
+ return push_inst(compiler, MOVK | RD(dst) | ((sljit_ins)(imm >> 48) << 5) | (3 << 21));
}
static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins *code_ptr, sljit_ins *code, sljit_sw executable_offset)
@@ -171,14 +176,14 @@ static SLJIT_INLINE sljit_sw detect_jump_type(struct sljit_jump *jump, sljit_ins
diff = (sljit_sw)target_addr - (sljit_sw)(code_ptr + 4) - executable_offset;
if (jump->flags & IS_COND) {
- diff += sizeof(sljit_ins);
+ diff += SSIZE_OF(ins);
if (diff <= 0xfffff && diff >= -0x100000) {
code_ptr[-5] ^= (jump->flags & IS_CBZ) ? (0x1 << 24) : 0x1;
jump->addr -= sizeof(sljit_ins);
jump->flags |= PATCH_COND;
return 5;
}
- diff -= sizeof(sljit_ins);
+ diff -= SSIZE_OF(ins);
}
if (diff <= 0x7ffffff && diff >= -0x8000000) {
@@ -231,8 +236,8 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw word_count;
sljit_uw next_addr;
sljit_sw executable_offset;
- sljit_uw addr;
- sljit_s32 dst;
+ sljit_sw addr;
+ sljit_u32 dst;
struct sljit_label *label;
struct sljit_jump *jump;
@@ -271,7 +276,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (label && label->size == word_count) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
if (jump && jump->addr == word_count) {
@@ -300,7 +305,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
@@ -313,58 +318,58 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
do {
- addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ addr = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
buf_ptr = (sljit_ins *)jump->addr;
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
- SLJIT_ASSERT((sljit_sw)addr <= 0x1ffffff && (sljit_sw)addr >= -0x2000000);
- buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (addr & 0x3ffffff);
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= 0x1ffffff && addr >= -0x2000000);
+ buf_ptr[0] = ((jump->flags & IS_BL) ? BL : B) | (sljit_ins)(addr & 0x3ffffff);
if (jump->flags & IS_COND)
buf_ptr[-1] -= (4 << 5);
break;
}
if (jump->flags & PATCH_COND) {
- addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
- SLJIT_ASSERT((sljit_sw)addr <= 0x3ffff && (sljit_sw)addr >= -0x40000);
- buf_ptr[0] = (buf_ptr[0] & ~0xffffe0) | ((addr & 0x7ffff) << 5);
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= 0x3ffff && addr >= -0x40000);
+ buf_ptr[0] = (buf_ptr[0] & ~(sljit_ins)0xffffe0) | (sljit_ins)((addr & 0x7ffff) << 5);
break;
}
- SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || addr <= 0xffffffffl);
- SLJIT_ASSERT((jump->flags & PATCH_ABS64) || addr <= 0xffffffffffffl);
+ SLJIT_ASSERT((jump->flags & (PATCH_ABS48 | PATCH_ABS64)) || (sljit_uw)addr <= (sljit_uw)0xffffffff);
+ SLJIT_ASSERT((jump->flags & PATCH_ABS64) || (sljit_uw)addr <= (sljit_uw)0xffffffffffff);
dst = buf_ptr[0] & 0x1f;
- buf_ptr[0] = MOVZ | dst | ((addr & 0xffff) << 5);
- buf_ptr[1] = MOVK | dst | (((addr >> 16) & 0xffff) << 5) | (1 << 21);
+ buf_ptr[0] = MOVZ | dst | (((sljit_ins)addr & 0xffff) << 5);
+ buf_ptr[1] = MOVK | dst | (((sljit_ins)(addr >> 16) & 0xffff) << 5) | (1 << 21);
if (jump->flags & (PATCH_ABS48 | PATCH_ABS64))
- buf_ptr[2] = MOVK | dst | (((addr >> 32) & 0xffff) << 5) | (2 << 21);
+ buf_ptr[2] = MOVK | dst | (((sljit_ins)(addr >> 32) & 0xffff) << 5) | (2 << 21);
if (jump->flags & PATCH_ABS64)
- buf_ptr[3] = MOVK | dst | (((addr >> 48) & 0xffff) << 5) | (3 << 21);
+ buf_ptr[3] = MOVK | dst | ((sljit_ins)(addr >> 48) << 5) | (3 << 21);
} while (0);
jump = jump->next;
}
put_label = compiler->put_labels;
while (put_label) {
- addr = put_label->label->addr;
- buf_ptr = (sljit_ins *)put_label->addr;
+ addr = (sljit_sw)put_label->label->addr;
+ buf_ptr = (sljit_ins*)put_label->addr;
- buf_ptr[0] |= (addr & 0xffff) << 5;
- buf_ptr[1] |= ((addr >> 16) & 0xffff) << 5;
+ buf_ptr[0] |= ((sljit_ins)addr & 0xffff) << 5;
+ buf_ptr[1] |= ((sljit_ins)(addr >> 16) & 0xffff) << 5;
if (put_label->flags >= 1)
- buf_ptr[2] |= ((addr >> 32) & 0xffff) << 5;
+ buf_ptr[2] |= ((sljit_ins)(addr >> 32) & 0xffff) << 5;
if (put_label->flags >= 2)
- buf_ptr[3] |= ((addr >> 48) & 0xffff) << 5;
+ buf_ptr[3] |= (sljit_ins)(addr >> 48) << 5;
put_label = put_label->next;
}
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -426,11 +431,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
value >>= 1; \
}
-#define LOGICAL_IMM_CHECK 0x100
+#define LOGICAL_IMM_CHECK (sljit_ins)0x100
-static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len)
+static sljit_ins logical_imm(sljit_sw imm, sljit_u32 len)
{
- sljit_s32 negated, ones, right;
+ sljit_s32 negated;
+ sljit_u32 ones, right;
sljit_uw mask, uimm;
sljit_ins ins;
@@ -497,30 +503,30 @@ static sljit_ins logical_imm(sljit_sw imm, sljit_s32 len)
static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw simm)
{
sljit_uw imm = (sljit_uw)simm;
- sljit_s32 i, zeros, ones, first;
+ sljit_u32 i, zeros, ones, first;
sljit_ins bitmask;
/* Handling simple immediates first. */
if (imm <= 0xffff)
- return push_inst(compiler, MOVZ | RD(dst) | (imm << 5));
+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)imm << 5));
if (simm < 0 && simm >= -0x10000)
- return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5));
+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));
if (imm <= 0xffffffffl) {
if ((imm & 0xffff) == 0)
- return push_inst(compiler, MOVZ | RD(dst) | ((imm >> 16) << 5) | (1 << 21));
+ return push_inst(compiler, MOVZ | RD(dst) | ((sljit_ins)(imm >> 16) << 5) | (1 << 21));
if ((imm & 0xffff0000l) == 0xffff0000)
- return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff) << 5));
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5));
if ((imm & 0xffff) == 0xffff)
- return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ return push_inst(compiler, (MOVN ^ W_OP) | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
bitmask = logical_imm(simm, 16);
if (bitmask != 0)
return push_inst(compiler, (ORRI ^ W_OP) | RD(dst) | RN(TMP_ZERO) | bitmask);
- FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((imm & 0xffff) << 5)));
- return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
}
bitmask = logical_imm(simm, 32);
@@ -529,10 +535,10 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
if (simm < 0 && simm >= -0x100000000l) {
if ((imm & 0xffff) == 0xffff)
- return push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ return push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
- FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((~imm & 0xffff) << 5)));
- return push_inst(compiler, MOVK | RD(dst) | ((imm & 0xffff0000l) >> (16 - 5)) | (1 << 21));
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)~imm & 0xffff) << 5)));
+ return push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)imm & 0xffff0000u) >> (16 - 5)) | (1 << 21));
}
/* A large amount of number can be constructed from ORR and MOVx, but computing them is costly. */
@@ -558,10 +564,10 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
}
if (first) {
first = 0;
- FAIL_IF(push_inst(compiler, MOVN | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ FAIL_IF(push_inst(compiler, MOVN | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
}
else
- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((~simm & 0xffff) << 5) | (i << 21)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)~simm & 0xffff) << 5) | (i << 21)));
simm >>= 16;
}
return SLJIT_SUCCESS;
@@ -574,10 +580,10 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
}
if (first) {
first = 0;
- FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ FAIL_IF(push_inst(compiler, MOVZ | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
}
else
- FAIL_IF(push_inst(compiler, MOVK | RD(dst) | ((simm & 0xffff) << 5) | (i << 21)));
+ FAIL_IF(push_inst(compiler, MOVK | RD(dst) | (((sljit_ins)simm & 0xffff) << 5) | (i << 21)));
simm >>= 16;
}
return SLJIT_SUCCESS;
@@ -619,12 +625,11 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
}
if (flags & (ARG1_IMM | ARG2_IMM)) {
- reg = (flags & ARG2_IMM) ? arg1 : arg2;
+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);
imm = (flags & ARG2_IMM) ? arg2 : arg1;
switch (op) {
case SLJIT_MUL:
- case SLJIT_NEG:
case SLJIT_CLZ:
case SLJIT_ADDC:
case SLJIT_SUBC:
@@ -639,40 +644,43 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
FAIL_IF(load_immediate(compiler, dst, (flags & INT_OP) ? (~imm & 0xffffffff) : ~imm));
goto set_flags;
case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
if (flags & ARG1_IMM)
break;
imm = -imm;
/* Fall through. */
case SLJIT_ADD:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ if (op != SLJIT_SUB)
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+
if (imm == 0) {
CHECK_FLAGS(1 << 29);
return push_inst(compiler, ((op == SLJIT_ADD ? ADDI : SUBI) ^ inv_bits) | RD(dst) | RN(reg));
}
if (imm > 0 && imm <= 0xfff) {
CHECK_FLAGS(1 << 29);
- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (imm << 10));
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)imm << 10));
}
nimm = -imm;
if (nimm > 0 && nimm <= 0xfff) {
CHECK_FLAGS(1 << 29);
- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (nimm << 10));
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((sljit_ins)nimm << 10));
}
if (imm > 0 && imm <= 0xffffff && !(imm & 0xfff)) {
CHECK_FLAGS(1 << 29);
- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22));
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22));
}
if (nimm > 0 && nimm <= 0xffffff && !(nimm & 0xfff)) {
CHECK_FLAGS(1 << 29);
- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22));
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22));
}
if (imm > 0 && imm <= 0xffffff && !(flags & SET_FLAGS)) {
- FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | ((imm >> 12) << 10) | (1 << 22)));
- return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | ((imm & 0xfff) << 10));
+ FAIL_IF(push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)imm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (ADDI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)imm & 0xfff) << 10));
}
if (nimm > 0 && nimm <= 0xffffff && !(flags & SET_FLAGS)) {
- FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | ((nimm >> 12) << 10) | (1 << 22)));
- return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | ((nimm & 0xfff) << 10));
+ FAIL_IF(push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(reg) | (((sljit_ins)nimm >> 12) << 10) | (1 << 22)));
+ return push_inst(compiler, (SUBI ^ inv_bits) | RD(dst) | RN(dst) | (((sljit_ins)nimm & 0xfff) << 10));
}
break;
case SLJIT_AND:
@@ -697,11 +705,13 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
break;
if (flags & INT_OP) {
imm &= 0x1f;
- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | ((-imm & 0x1f) << 16) | ((31 - imm) << 10)));
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)
+ | (((sljit_ins)-imm & 0x1f) << 16) | ((31 - (sljit_ins)imm) << 10)));
}
else {
imm &= 0x3f;
- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | ((-imm & 0x3f) << 16) | ((63 - imm) << 10)));
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22)
+ | (((sljit_ins)-imm & 0x3f) << 16) | ((63 - (sljit_ins)imm) << 10)));
}
goto set_flags;
case SLJIT_LSHR:
@@ -712,11 +722,13 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
inv_bits |= 1 << 30;
if (flags & INT_OP) {
imm &= 0x1f;
- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (imm << 16) | (31 << 10)));
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)
+ | ((sljit_ins)imm << 16) | (31 << 10)));
}
else {
imm &= 0x3f;
- FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1) | (1 << 22) | (imm << 16) | (63 << 10)));
+ FAIL_IF(push_inst(compiler, (UBFM ^ inv_bits) | RD(dst) | RN(arg1)
+ | (1 << 22) | ((sljit_ins)imm << 16) | (63 << 10)));
}
goto set_flags;
default:
@@ -766,41 +778,38 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (!(flags & INT_OP))
inv_bits |= 1 << 22;
return push_inst(compiler, (SBFM ^ inv_bits) | RD(dst) | RN(arg2) | (15 << 10));
- case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
- if ((flags & INT_OP) && dst == arg2)
+ if (dst == arg2)
return SLJIT_SUCCESS;
+ /* fallthrough */
+ case SLJIT_MOV_U32:
+ SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
return push_inst(compiler, (ORR ^ W_OP) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
case SLJIT_MOV_S32:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG1);
- if ((flags & INT_OP) && dst == arg2)
- return SLJIT_SUCCESS;
return push_inst(compiler, SBFM | (1 << 22) | RD(dst) | RN(arg2) | (31 << 10));
case SLJIT_NOT:
SLJIT_ASSERT(arg1 == TMP_REG1);
FAIL_IF(push_inst(compiler, (ORN ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2)));
break; /* Set flags. */
- case SLJIT_NEG:
- SLJIT_ASSERT(arg1 == TMP_REG1);
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- if (flags & SET_FLAGS)
- inv_bits |= 1 << 29;
- return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(TMP_ZERO) | RM(arg2));
case SLJIT_CLZ:
SLJIT_ASSERT(arg1 == TMP_REG1);
return push_inst(compiler, (CLZ ^ inv_bits) | RD(dst) | RN(arg2));
case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
CHECK_FLAGS(1 << 29);
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
return push_inst(compiler, (ADD ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
CHECK_FLAGS(1 << 29);
return push_inst(compiler, (ADC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
CHECK_FLAGS(1 << 29);
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
return push_inst(compiler, (SUB ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
CHECK_FLAGS(1 << 29);
return push_inst(compiler, (SBC ^ inv_bits) | RD(dst) | RN(arg1) | RM(arg2));
case SLJIT_MUL:
@@ -852,7 +861,7 @@ set_flags:
#define INT_SIZE 0x2
#define WORD_SIZE 0x3
-#define MEM_SIZE_SHIFT(flags) ((flags) & 0x3)
+#define MEM_SIZE_SHIFT(flags) ((sljit_ins)(flags) & 0x3)
static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg,
sljit_s32 arg, sljit_sw argw, sljit_s32 tmp_reg)
@@ -872,35 +881,34 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst(compiler, STRB | type | RT(reg)
| RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));
- FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10)));
+ FAIL_IF(push_inst(compiler, ADD | RD(tmp_reg) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));
return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg));
}
arg &= REG_MASK;
- if (arg == SLJIT_UNUSED) {
+ if (!arg) {
FAIL_IF(load_immediate(compiler, tmp_reg, argw & ~(0xfff << shift)));
argw = (argw >> shift) & 0xfff;
- return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10));
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));
}
if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {
- if ((argw >> shift) <= 0xfff) {
- return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | (argw << (10 - shift)));
- }
+ if ((argw >> shift) <= 0xfff)
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));
if (argw <= 0xffffff) {
- FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | ((argw >> 12) << 10)));
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(tmp_reg) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
argw = ((argw & 0xfff) >> shift);
- return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | (argw << 10));
+ return push_inst(compiler, STRBI | type | RT(reg) | RN(tmp_reg) | ((sljit_ins)argw << 10));
}
}
if (argw <= 255 && argw >= -256)
- return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | ((argw & 0x1ff) << 12));
+ return push_inst(compiler, STURBI | type | RT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));
FAIL_IF(load_immediate(compiler, tmp_reg, argw));
@@ -915,39 +923,44 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args, i, tmp, offs, prev, saved_regs_size;
+ sljit_s32 prev, fprev, saved_regs_size, i, tmp;
+ sljit_s32 word_arg_count = 0;
+ sljit_ins offs;
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
- if (saved_regs_size & 0x8)
- saved_regs_size += sizeof(sljit_sw);
+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64));
- local_size = (local_size + 15) & ~0xf;
- compiler->local_size = local_size + saved_regs_size;
+ local_size = (local_size + saved_regs_size + 0xf) & ~0xf;
+ compiler->local_size = local_size;
- FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
- | RN(SLJIT_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15)));
+ if (local_size <= 512) {
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
+ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);
+ local_size = 0;
+ } else {
+ saved_regs_size = ((saved_regs_size - 2 * SSIZE_OF(sw)) + 0xf) & ~0xf;
-#ifdef _WIN32
- if (local_size >= 4096)
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
- else if (local_size > 256)
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(SLJIT_SP) | (local_size << 10)));
-#endif
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)saved_regs_size << 10)));
+ offs = (sljit_ins)(saved_regs_size - 2 * SSIZE_OF(sw)) << (15 - 3);
+ local_size -= saved_regs_size;
+ SLJIT_ASSERT(local_size > 0);
+ }
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
prev = -1;
- offs = 2 << 15;
- for (i = SLJIT_S0; i >= tmp; i--) {
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
if (prev == -1) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
- offs += 2 << 15;
+ offs -= (sljit_ins)2 << 15;
prev = -1;
}
@@ -957,84 +970,124 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
continue;
}
FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
- offs += 2 << 15;
+ offs -= (sljit_ins)2 << 15;
prev = -1;
}
- if (prev != -1)
- FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));
+ fprev = -1;
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
- FAIL_IF(push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10)));
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, STP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
- args = get_arg_count(arg_types);
+ if (fprev != -1)
+ FAIL_IF(push_inst(compiler, STRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));
- if (args >= 1)
- FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0)));
- if (args >= 2)
- FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1)));
- if (args >= 3)
- FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2)));
+ if (prev != -1)
+ FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+#ifdef _WIN32
+ if (local_size > 4096)
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+#endif /* _WIN32 */
+
+ tmp = 0;
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0 - tmp) | RN(TMP_ZERO) | RM(SLJIT_R0 + word_arg_count)));
+ tmp++;
+ }
+ word_arg_count++;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
#ifdef _WIN32
- if (local_size >= 4096) {
+ if (local_size > 4096) {
if (local_size < 4 * 4096) {
/* No need for a loop. */
- if (local_size >= 2 * 4096) {
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
- local_size -= 4096;
- }
if (local_size >= 2 * 4096) {
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
- local_size -= 4096;
- }
+ if (local_size >= 3 * 4096) {
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ }
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- local_size -= 4096;
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ }
}
else {
- FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG2) | (((local_size >> 12) - 1) << 5)));
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10) | (1 << 22)));
- FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG2) | RN(TMP_REG2) | (1 << 10)));
+ FAIL_IF(push_inst(compiler, MOVZ | RD(TMP_REG1) | ((((sljit_ins)local_size >> 12) - 1) << 5)));
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (1 << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, SUBI | (1 << 29) | RD(TMP_REG1) | RN(TMP_REG1) | (1 << 10)));
FAIL_IF(push_inst(compiler, B_CC | ((((sljit_ins) -3) & 0x7ffff) << 5) | 0x1 /* not-equal */));
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
-
- local_size &= 0xfff;
}
- if (local_size > 256) {
- FAIL_IF(push_inst(compiler, SUBI | RD(TMP_REG1) | RN(TMP_REG1) | (local_size << 10)));
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- }
- else if (local_size > 0)
- FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(TMP_REG1) | ((-local_size & 0x1ff) << 12)));
+ local_size &= 0xfff;
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));
+ if (local_size > 0)
+ FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(SLJIT_SP)));
+ else
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
}
- else if (local_size > 256) {
- FAIL_IF(push_inst(compiler, LDRI | RT(TMP_ZERO) | RN(TMP_REG1)));
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_REG1) | (0 << 10)));
+
+ if (local_size > 0) {
+ if (local_size <= 512)
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
+ else {
+ if (local_size >= 4096)
+ local_size = (1 << (22 - 10));
+
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ }
}
- else if (local_size > 0)
- FAIL_IF(push_inst(compiler, LDR_PRE | RT(TMP_ZERO) | RN(SLJIT_SP) | ((-local_size & 0x1ff) << 12)));
#else /* !_WIN32 */
/* The local_size does not include saved registers size. */
- if (local_size > 0xfff) {
- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));
- local_size &= 0xfff;
+ if (local_size != 0) {
+ if (local_size > 0xfff) {
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));
+ local_size &= 0xfff;
+ }
+
+ if (local_size > 512 || local_size == 0) {
+ if (local_size != 0)
+ FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+
+ FAIL_IF(push_inst(compiler, STP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ } else
+ FAIL_IF(push_inst(compiler, STP_PRE | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | (sljit_ins)((-(local_size >> 3) & 0x7f) << 15)));
}
- if (local_size != 0)
- FAIL_IF(push_inst(compiler, SUBI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));
#endif /* _WIN32 */
- return SLJIT_SUCCESS;
+ return push_inst(compiler, ADDI | RD(TMP_FP) | RN(SLJIT_SP) | (0 << 10));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
@@ -1048,57 +1101,49 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 2);
- if (saved_regs_size & 0x8)
- saved_regs_size += sizeof(sljit_sw);
+ saved_regs_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, SSIZE_OF(f64));
- compiler->local_size = saved_regs_size + ((local_size + 15) & ~0xf);
+ compiler->local_size = (local_size + saved_regs_size + 0xf) & ~0xf;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
{
- sljit_s32 local_size;
- sljit_s32 i, tmp, offs, prev, saved_regs_size;
-
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
-
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
-
- saved_regs_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 2);
- if (saved_regs_size & 0x8)
- saved_regs_size += sizeof(sljit_sw);
+ sljit_s32 local_size, prev, fprev, i, tmp;
+ sljit_ins offs;
- local_size = compiler->local_size - saved_regs_size;
+ local_size = compiler->local_size;
- /* Load LR as early as possible. */
- if (local_size == 0)
+ if (local_size > 512 && local_size <= 512 + 496) {
+ FAIL_IF(push_inst(compiler, LDP_POST | RT(TMP_FP) | RT2(TMP_LR)
+ | RN(SLJIT_SP) | ((sljit_ins)(local_size - 512) << (15 - 3))));
+ local_size = 512;
+ } else
FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
- else if (local_size < 63 * sizeof(sljit_sw)) {
- FAIL_IF(push_inst(compiler, LDP_PRE | RT(TMP_FP) | RT2(TMP_LR)
- | RN(SLJIT_SP) | (local_size << (15 - 3))));
- }
- else {
+
+ if (local_size > 512) {
+ local_size -= 512;
if (local_size > 0xfff) {
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((local_size >> 12) << 10) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP)
+ | (((sljit_ins)local_size >> 12) << 10) | (1 << 22)));
local_size &= 0xfff;
}
- if (local_size)
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (local_size << 10)));
- FAIL_IF(push_inst(compiler, LDP | RT(TMP_FP) | RT2(TMP_LR) | RN(SLJIT_SP)));
+ FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | ((sljit_ins)local_size << 10)));
+ local_size = 512;
}
- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
+ offs = (sljit_ins)(local_size - 2 * SSIZE_OF(sw)) << (15 - 3);
prev = -1;
- offs = 2 << 15;
- for (i = SLJIT_S0; i >= tmp; i--) {
+
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
if (prev == -1) {
prev = i;
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
- offs += 2 << 15;
+ offs -= (sljit_ins)2 << 15;
prev = -1;
}
@@ -1108,15 +1153,50 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
continue;
}
FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(SLJIT_SP) | offs));
- offs += 2 << 15;
+ offs -= (sljit_ins)2 << 15;
prev = -1;
}
+ fprev = -1;
+
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ if (fprev == -1) {
+ fprev = i;
+ continue;
+ }
+ FAIL_IF(push_inst(compiler, LDP_F64 | VT(fprev) | VT2(i) | RN(SLJIT_SP) | offs));
+ offs -= (sljit_ins)2 << 15;
+ fprev = -1;
+ }
+
+ if (fprev != -1)
+ FAIL_IF(push_inst(compiler, LDRI_F64 | VT(fprev) | RN(SLJIT_SP) | (offs >> 5) | (1 << 10)));
+
if (prev != -1)
- FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5)));
+ FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(SLJIT_SP) | (offs >> 5) | ((fprev == -1) ? (1 << 10) : 0)));
+
+ /* This and the next call/jump instruction can be executed parallelly. */
+ return push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (sljit_ins)(local_size << 10));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler));
- /* These two can be executed in parallel. */
- FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(SLJIT_SP) | (saved_regs_size << 10)));
return push_inst(compiler, RET | RN(TMP_LR));
}
@@ -1126,7 +1206,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
- sljit_ins inv_bits = (op & SLJIT_I32_OP) ? W_OP : 0;
+ sljit_ins inv_bits = (op & SLJIT_32) ? W_OP : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
@@ -1171,13 +1251,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
/* Both operands are registers. */
if (dst_r != TMP_REG1 && FAST_IS_REG(src))
- return emit_op_imm(compiler, op | ((op_flags & SLJIT_I32_OP) ? INT_OP : 0), dst_r, TMP_REG1, src);
+ return emit_op_imm(compiler, op | ((op_flags & SLJIT_32) ? INT_OP : 0), dst_r, TMP_REG1, src);
switch (op) {
case SLJIT_MOV:
@@ -1210,6 +1290,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
srcw = (sljit_u32)srcw;
break;
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
mem_flags = INT_SIZE | SIGNED;
if (src & SLJIT_IMM)
srcw = (sljit_s32)srcw;
@@ -1235,14 +1316,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
- if (op_flags & SLJIT_I32_OP) {
+ if (op_flags & SLJIT_32) {
flags |= INT_OP;
mem_flags = INT_SIZE;
}
- if (dst == SLJIT_UNUSED)
- flags |= UNUSED_RETURN;
-
if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, mem_flags, TMP_REG2, src, srcw, TMP_REG2));
src = TMP_REG2;
@@ -1263,24 +1341,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 dst_r, flags, mem_flags;
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
- if (op & SLJIT_I32_OP) {
+ if (op & SLJIT_32) {
flags |= INT_OP;
mem_flags = INT_SIZE;
}
- if (dst == SLJIT_UNUSED)
+ if (dst == TMP_REG1)
flags |= UNUSED_RETURN;
if (src1 & SLJIT_MEM) {
@@ -1310,6 +1385,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -1363,8 +1452,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
+ SLJIT_UNUSED_ARG(size);
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1391,34 +1481,34 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
return push_inst(compiler, STR_FR | type | VT(reg)
| RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw ? (1 << 12) : 0));
- FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | (argw << 10)));
+ FAIL_IF(push_inst(compiler, ADD | RD(TMP_REG1) | RN(arg & REG_MASK) | RM(OFFS_REG(arg)) | ((sljit_ins)argw << 10)));
return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1));
}
arg &= REG_MASK;
- if (arg == SLJIT_UNUSED) {
+ if (!arg) {
FAIL_IF(load_immediate(compiler, TMP_REG1, argw & ~(0xfff << shift)));
argw = (argw >> shift) & 0xfff;
- return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10));
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | ((sljit_ins)argw << 10));
}
if (argw >= 0 && (argw & ((1 << shift) - 1)) == 0) {
if ((argw >> shift) <= 0xfff)
- return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | (argw << (10 - shift)));
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(arg) | ((sljit_ins)argw << (10 - shift)));
if (argw <= 0xffffff) {
- FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | ((argw >> 12) << 10)));
+ FAIL_IF(push_inst(compiler, ADDI | (1 << 22) | RD(TMP_REG1) | RN(arg) | (((sljit_ins)argw >> 12) << 10)));
argw = ((argw & 0xfff) >> shift);
- return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | (argw << 10));
+ return push_inst(compiler, STR_FI | type | VT(reg) | RN(TMP_REG1) | ((sljit_ins)argw << 10));
}
}
if (argw <= 255 && argw >= -256)
- return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | ((argw & 0x1ff) << 12));
+ return push_inst(compiler, STUR_FI | type | VT(reg) | RN(arg) | (((sljit_ins)argw & 0x1ff) << 12));
FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
return push_inst(compiler, STR_FR | type | VT(reg) | RN(arg) | RM(TMP_REG1));
@@ -1429,13 +1519,13 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
if (GET_OPCODE(op) == SLJIT_CONV_S32_FROM_F64)
inv_bits |= W_OP;
if (src & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
+ emit_fop_mem(compiler, (op & SLJIT_32) ? INT_SIZE : WORD_SIZE, TMP_FREG1, src, srcw);
src = TMP_FREG1;
}
@@ -1451,7 +1541,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
sljit_s32 src, sljit_sw srcw)
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_S32)
inv_bits |= W_OP;
@@ -1471,7 +1561,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
FAIL_IF(push_inst(compiler, (SCVTF ^ inv_bits) | VD(dst_r) | RN(src)));
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, ((op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, ((op & SLJIT_32) ? INT_SIZE : WORD_SIZE) | STORE, TMP_FREG1, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -1479,8 +1569,8 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
- sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
+ sljit_s32 mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
if (src1 & SLJIT_MEM) {
emit_fop_mem(compiler, mem_flags, TMP_FREG1, src1, src1w);
@@ -1499,7 +1589,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
+ sljit_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
sljit_ins inv_bits;
CHECK_ERROR();
@@ -1507,7 +1597,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
SLJIT_COMPILE_ASSERT((INT_SIZE ^ 0x1) == WORD_SIZE, must_be_one_bit_difference);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
- inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
+ inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src & SLJIT_MEM) {
@@ -1531,7 +1621,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
FAIL_IF(push_inst(compiler, (FABS ^ inv_bits) | VD(dst_r) | VN(src)));
break;
case SLJIT_CONV_F64_FROM_F32:
- FAIL_IF(push_inst(compiler, FCVT | ((op & SLJIT_F32_OP) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
+ FAIL_IF(push_inst(compiler, FCVT | (sljit_ins)((op & SLJIT_32) ? (1 << 22) : (1 << 15)) | VD(dst_r) | VN(src)));
break;
}
@@ -1545,8 +1635,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 dst_r, mem_flags = (op & SLJIT_F32_OP) ? INT_SIZE : WORD_SIZE;
- sljit_ins inv_bits = (op & SLJIT_F32_OP) ? (1 << 22) : 0;
+ sljit_s32 dst_r, mem_flags = (op & SLJIT_32) ? INT_SIZE : WORD_SIZE;
+ sljit_ins inv_bits = (op & SLJIT_32) ? (1 << 22) : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
@@ -1605,7 +1695,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
/* Conditional instructions */
/* --------------------------------------------------------------------- */
-static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
+static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
{
switch (type) {
case SLJIT_EQUAL:
@@ -1616,10 +1706,20 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_EQUAL_F64:
return 0x0;
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x3;
+ /* fallthrough */
+
case SLJIT_LESS:
case SLJIT_LESS_F64:
return 0x2;
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x2;
+ /* fallthrough */
+
case SLJIT_GREATER_EQUAL:
case SLJIT_GREATER_EQUAL_F64:
return 0x3;
@@ -1645,15 +1745,17 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
return 0xc;
case SLJIT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x0;
+ /* fallthrough */
case SLJIT_UNORDERED_F64:
return 0x7;
case SLJIT_NOT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x1;
+ /* fallthrough */
case SLJIT_ORDERED_F64:
return 0x6;
@@ -1709,9 +1811,15 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
+ SLJIT_UNUSED_ARG(arg_types);
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
@@ -1724,7 +1832,7 @@ static SLJIT_INLINE struct sljit_jump* emit_cmp_to0(struct sljit_compiler *compi
sljit_s32 src, sljit_sw srcw)
{
struct sljit_jump *jump;
- sljit_ins inv_bits = (type & SLJIT_I32_OP) ? W_OP : 0;
+ sljit_ins inv_bits = (type & SLJIT_32) ? W_OP : 0;
SLJIT_ASSERT((type & 0xff) == SLJIT_EQUAL || (type & 0xff) == SLJIT_NOT_EQUAL);
ADJUST_LOCAL_OFFSET(src, srcw);
@@ -1775,7 +1883,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
FAIL_IF(emit_imm64_const(compiler, TMP_REG1, 0));
jump->addr = compiler->size;
@@ -1786,8 +1894,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
+ SLJIT_UNUSED_ARG(arg_types);
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+ ADJUST_LOCAL_OFFSET(src, srcw);
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
+ src = TMP_REG1;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
+ FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(src)));
+ src = TMP_REG1;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP;
+ }
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -1825,7 +1950,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
mem_flags = WORD_SIZE;
- if (op & SLJIT_I32_OP) {
+ if (op & SLJIT_32) {
flags |= INT_OP;
mem_flags = INT_SIZE;
}
@@ -1849,14 +1974,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
sljit_s32 dst_reg,
sljit_s32 src, sljit_sw srcw)
{
- sljit_ins inv_bits = (dst_reg & SLJIT_I32_OP) ? W_OP : 0;
+ sljit_ins inv_bits = (dst_reg & SLJIT_32) ? W_OP : 0;
sljit_ins cc;
CHECK_ERROR();
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
- if (dst_reg & SLJIT_I32_OP)
+ if (dst_reg & SLJIT_32)
srcw = (sljit_s32)srcw;
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
src = TMP_REG1;
@@ -1864,7 +1989,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
}
cc = get_cc(compiler, type & 0xff);
- dst_reg &= ~SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_32;
return push_inst(compiler, (CSEL ^ inv_bits) | (cc << 12) | RD(dst_reg) | RN(dst_reg) | RM(src));
}
@@ -1891,17 +2016,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
break;
case SLJIT_MOV_S8:
sign = 1;
+ /* fallthrough */
case SLJIT_MOV_U8:
inst = STURBI | (MEM_SIZE_SHIFT(BYTE_SIZE) << 30) | 0x400;
break;
case SLJIT_MOV_S16:
sign = 1;
+ /* fallthrough */
case SLJIT_MOV_U16:
inst = STURBI | (MEM_SIZE_SHIFT(HALF_SIZE) << 30) | 0x400;
break;
case SLJIT_MOV_S32:
sign = 1;
+ /* fallthrough */
case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
inst = STURBI | (MEM_SIZE_SHIFT(INT_SIZE) << 30) | 0x400;
break;
default:
@@ -1916,7 +2045,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
if (type & SLJIT_MEM_PRE)
inst |= 0x800;
- return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12));
+ return push_inst(compiler, inst | RT(reg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compiler, sljit_s32 type,
@@ -1936,7 +2065,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
inst = STUR_FI | 0x80000400;
- if (!(type & SLJIT_F32_OP))
+ if (!(type & SLJIT_32))
inst |= 0x40000000;
if (!(type & SLJIT_MEM_STORE))
@@ -1945,7 +2074,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fmem(struct sljit_compiler *compil
if (type & SLJIT_MEM_PRE)
inst |= 0x800;
- return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | ((memw & 0x1ff) << 12));
+ return push_inst(compiler, inst | VT(freg) | RN(mem & REG_MASK) | (sljit_ins)((memw & 0x1ff) << 12));
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw offset)
@@ -1955,11 +2084,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
CHECK_ERROR();
CHECK(check_sljit_get_local_base(compiler, dst, dstw, offset));
-
- SLJIT_ASSERT (SLJIT_LOCALS_OFFSET_BASE == 0);
+ ADJUST_LOCAL_OFFSET(SLJIT_MEM1(SLJIT_SP), offset);
dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
+ /* Not all instruction forms support accessing SP register. */
if (offset <= 0xffffff && offset >= -0xffffff) {
ins = ADDI;
if (offset < 0) {
@@ -1968,13 +2097,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_local_base(struct sljit_compiler *c
}
if (offset <= 0xfff)
- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (offset << 10)));
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)(offset << 10)));
else {
- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | ((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(SLJIT_SP) | (sljit_ins)((offset & 0xfff000) >> (12 - 10)) | (1 << 22)));
offset &= 0xfff;
if (offset != 0)
- FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (offset << 10)));
+ FAIL_IF(push_inst(compiler, ins | RD(dst_reg) | RN(dst_reg) | (sljit_ins)(offset << 10)));
}
}
else {
@@ -2002,7 +2131,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, init_value));
+ PTR_FAIL_IF(emit_imm64_const(compiler, dst_r, (sljit_uw)init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
@@ -2034,17 +2163,17 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_target, sljit_sw executable_offset)
{
sljit_ins* inst = (sljit_ins*)addr;
- sljit_s32 dst;
+ sljit_u32 dst;
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 0);
dst = inst[0] & 0x1f;
SLJIT_ASSERT((inst[0] & 0xffe00000) == MOVZ && (inst[1] & 0xffe00000) == (MOVK | (1 << 21)));
- inst[0] = MOVZ | dst | ((new_target & 0xffff) << 5);
- inst[1] = MOVK | dst | (((new_target >> 16) & 0xffff) << 5) | (1 << 21);
- inst[2] = MOVK | dst | (((new_target >> 32) & 0xffff) << 5) | (2 << 21);
- inst[3] = MOVK | dst | ((new_target >> 48) << 5) | (3 << 21);
+ inst[0] = MOVZ | dst | (((sljit_u32)new_target & 0xffff) << 5);
+ inst[1] = MOVK | dst | (((sljit_u32)(new_target >> 16) & 0xffff) << 5) | (1 << 21);
+ inst[2] = MOVK | dst | (((sljit_u32)(new_target >> 32) & 0xffff) << 5) | (2 << 21);
+ inst[3] = MOVK | dst | ((sljit_u32)(new_target >> 48) << 5) | (3 << 21);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 4, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
@@ -2053,5 +2182,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
index e35dbe99b3..ed21ea7daa 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeARM_T2_32.c
@@ -50,40 +50,42 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 1, 2, 3, 4, 5, 6, 7
+ 0, 0, 1, 2, 3, 4, 5, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7
};
#define COPY_BITS(src, from, to, bits) \
- ((from >= to ? (src >> (from - to)) : (src << (to - from))) & (((1 << bits) - 1) << to))
+ ((from >= to ? ((sljit_ins)(src) >> (from - to)) : ((sljit_ins)(src) << (to - from))) & (((1 << bits) - 1) << to))
+
+#define NEGATE(uimm) ((sljit_uw)-(sljit_sw)(uimm))
/* Thumb16 encodings. */
-#define RD3(rd) (reg_map[rd])
-#define RN3(rn) (reg_map[rn] << 3)
-#define RM3(rm) (reg_map[rm] << 6)
-#define RDN3(rdn) (reg_map[rdn] << 8)
-#define IMM3(imm) (imm << 6)
-#define IMM8(imm) (imm)
+#define RD3(rd) ((sljit_ins)reg_map[rd])
+#define RN3(rn) ((sljit_ins)reg_map[rn] << 3)
+#define RM3(rm) ((sljit_ins)reg_map[rm] << 6)
+#define RDN3(rdn) ((sljit_ins)reg_map[rdn] << 8)
+#define IMM3(imm) ((sljit_ins)imm << 6)
+#define IMM8(imm) ((sljit_ins)imm)
/* Thumb16 helpers. */
#define SET_REGS44(rd, rn) \
- ((reg_map[rn] << 3) | (reg_map[rd] & 0x7) | ((reg_map[rd] & 0x8) << 4))
+ (((sljit_ins)reg_map[rn] << 3) | ((sljit_ins)reg_map[rd] & 0x7) | (((sljit_ins)reg_map[rd] & 0x8) << 4))
#define IS_2_LO_REGS(reg1, reg2) \
(reg_map[reg1] <= 7 && reg_map[reg2] <= 7)
#define IS_3_LO_REGS(reg1, reg2, reg3) \
(reg_map[reg1] <= 7 && reg_map[reg2] <= 7 && reg_map[reg3] <= 7)
/* Thumb32 encodings. */
-#define RD4(rd) (reg_map[rd] << 8)
-#define RN4(rn) (reg_map[rn] << 16)
-#define RM4(rm) (reg_map[rm])
-#define RT4(rt) (reg_map[rt] << 12)
-#define DD4(dd) (freg_map[dd] << 12)
-#define DN4(dn) (freg_map[dn] << 16)
-#define DM4(dm) (freg_map[dm])
+#define RD4(rd) ((sljit_ins)reg_map[rd] << 8)
+#define RN4(rn) ((sljit_ins)reg_map[rn] << 16)
+#define RM4(rm) ((sljit_ins)reg_map[rm])
+#define RT4(rt) ((sljit_ins)reg_map[rt] << 12)
+#define DD4(dd) ((sljit_ins)freg_map[dd] << 12)
+#define DN4(dn) ((sljit_ins)freg_map[dn] << 16)
+#define DM4(dm) ((sljit_ins)freg_map[dm])
#define IMM5(imm) \
- (COPY_BITS(imm, 2, 12, 3) | ((imm & 0x3) << 6))
+ (COPY_BITS(imm, 2, 12, 3) | (((sljit_ins)imm & 0x3) << 6))
#define IMM12(imm) \
- (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | (imm & 0xff))
+ (COPY_BITS(imm, 11, 26, 1) | COPY_BITS(imm, 8, 12, 3) | ((sljit_ins)imm & 0xff))
/* --------------------------------------------------------------------- */
/* Instrucion forms */
@@ -100,7 +102,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define ADDSI8 0x3000
#define ADD_W 0xeb000000
#define ADDWI 0xf2000000
-#define ADD_SP 0xb000
+#define ADD_SP 0x4485
+#define ADD_SP_I 0xb000
#define ADD_W 0xeb000000
#define ADD_WI 0xf1000000
#define ANDI 0xf0000000
@@ -126,6 +129,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define EORS 0x4040
#define EOR_W 0xea800000
#define IT 0xbf00
+#define LDR_SP 0x9800
+#define LDR 0xf8d00000
#define LDRI 0xf8500800
#define LSLS 0x4080
#define LSLSI 0x0000
@@ -168,13 +173,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SUBSI8 0x3800
#define SUB_W 0xeba00000
#define SUBWI 0xf2a00000
-#define SUB_SP 0xb080
+#define SUB_SP_I 0xb080
#define SUB_WI 0xf1a00000
#define SXTB 0xb240
#define SXTB_W 0xfa4ff080
#define SXTH 0xb200
#define SXTH_W 0xfa0ff080
#define TST 0x4200
+#define TSTI 0xf0000f00
+#define TST_W 0xea000f00
#define UDIV 0xfbb0f0f0
#define UMULL 0xfba00000
#define UXTB 0xb2c0
@@ -188,12 +195,15 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define VCVT_F64_F32 0xeeb70ac0
#define VCVT_S32_F32 0xeebd0ac0
#define VDIV_F32 0xee800a00
+#define VLDR_F32 0xed100a00
#define VMOV_F32 0xeeb00a40
#define VMOV 0xee000a10
#define VMOV2 0xec400a10
#define VMRS 0xeef1fa10
#define VMUL_F32 0xee200a00
#define VNEG_F32 0xeeb10a40
+#define VPOP 0xecbd0b00
+#define VPUSH 0xed2d0b00
#define VSTR_F32 0xed000a00
#define VSUB_F32 0xee300a40
@@ -204,7 +214,7 @@ static sljit_s32 push_inst16(struct sljit_compiler *compiler, sljit_ins inst)
ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_u16));
FAIL_IF(!ptr);
- *ptr = inst;
+ *ptr = (sljit_u16)(inst);
compiler->size++;
return SLJIT_SUCCESS;
}
@@ -213,8 +223,8 @@ static sljit_s32 push_inst32(struct sljit_compiler *compiler, sljit_ins inst)
{
sljit_u16 *ptr = (sljit_u16*)ensure_buf(compiler, sizeof(sljit_ins));
FAIL_IF(!ptr);
- *ptr++ = inst >> 16;
- *ptr = inst;
+ *ptr++ = (sljit_u16)(inst >> 16);
+ *ptr = (sljit_u16)(inst);
compiler->size += 2;
return SLJIT_SUCCESS;
}
@@ -229,12 +239,12 @@ static SLJIT_INLINE sljit_s32 emit_imm32_const(struct sljit_compiler *compiler,
static SLJIT_INLINE void modify_imm32_const(sljit_u16 *inst, sljit_uw new_imm)
{
- sljit_s32 dst = inst[1] & 0x0f00;
+ sljit_ins dst = inst[1] & 0x0f00;
SLJIT_ASSERT(((inst[0] & 0xfbf0) == (MOVW >> 16)) && ((inst[2] & 0xfbf0) == (MOVT >> 16)) && dst == (inst[3] & 0x0f00));
- inst[0] = (MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1);
- inst[1] = dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff);
- inst[2] = (MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1);
- inst[3] = dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16);
+ inst[0] = (sljit_u16)((MOVW >> 16) | COPY_BITS(new_imm, 12, 0, 4) | COPY_BITS(new_imm, 11, 10, 1));
+ inst[1] = (sljit_u16)(dst | COPY_BITS(new_imm, 8, 12, 3) | (new_imm & 0xff));
+ inst[2] = (sljit_u16)((MOVT >> 16) | COPY_BITS(new_imm, 12 + 16, 0, 4) | COPY_BITS(new_imm, 11 + 16, 10, 1));
+ inst[3] = (sljit_u16)(dst | COPY_BITS(new_imm, 8 + 16, 12, 3) | ((new_imm & 0xff0000) >> 16));
}
static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_u16 *code_ptr, sljit_u16 *code, sljit_sw executable_offset)
@@ -318,24 +328,24 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw
case 1:
/* Encoding T1 of 'B' instruction */
SLJIT_ASSERT(diff <= 127 && diff >= -128 && (jump->flags & IS_COND));
- jump_inst[0] = 0xd000 | (jump->flags & 0xf00) | (diff & 0xff);
+ jump_inst[0] = (sljit_u16)(0xd000 | (jump->flags & 0xf00) | ((sljit_ins)diff & 0xff));
return;
case 2:
/* Encoding T3 of 'B' instruction */
SLJIT_ASSERT(diff <= 524287 && diff >= -524288 && (jump->flags & IS_COND));
- jump_inst[0] = 0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1);
- jump_inst[1] = 0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | (diff & 0x7ff);
+ jump_inst[0] = (sljit_u16)(0xf000 | COPY_BITS(jump->flags, 8, 6, 4) | COPY_BITS(diff, 11, 0, 6) | COPY_BITS(diff, 19, 10, 1));
+ jump_inst[1] = (sljit_u16)(0x8000 | COPY_BITS(diff, 17, 13, 1) | COPY_BITS(diff, 18, 11, 1) | ((sljit_ins)diff & 0x7ff));
return;
case 3:
SLJIT_ASSERT(jump->flags & IS_COND);
- *jump_inst++ = IT | ((jump->flags >> 4) & 0xf0) | 0x8;
+ *jump_inst++ = (sljit_u16)(IT | ((jump->flags >> 4) & 0xf0) | 0x8);
diff--;
type = 5;
break;
case 4:
/* Encoding T2 of 'B' instruction */
SLJIT_ASSERT(diff <= 1023 && diff >= -1024 && !(jump->flags & IS_COND));
- jump_inst[0] = 0xe000 | (diff & 0x7ff);
+ jump_inst[0] = (sljit_u16)(0xe000 | (diff & 0x7ff));
return;
}
@@ -345,8 +355,8 @@ static SLJIT_INLINE void set_jump_instruction(struct sljit_jump *jump, sljit_sw
s = (diff >> 23) & 0x1;
j1 = (~(diff >> 22) ^ s) & 0x1;
j2 = (~(diff >> 21) ^ s) & 0x1;
- jump_inst[0] = 0xf000 | (s << 10) | COPY_BITS(diff, 11, 0, 10);
- jump_inst[1] = (j1 << 13) | (j2 << 11) | (diff & 0x7ff);
+ jump_inst[0] = (sljit_u16)(0xf000 | ((sljit_ins)s << 10) | COPY_BITS(diff, 11, 0, 10));
+ jump_inst[1] = (sljit_u16)((j1 << 13) | (j2 << 11) | (diff & 0x7ff));
/* The others have a common form. */
if (type == 5) /* Encoding T4 of 'B' instruction */
@@ -405,7 +415,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (label && label->size == half_count) {
label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
if (jump && jump->addr == half_count) {
@@ -433,7 +443,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == half_count) {
label->addr = ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset)) | 0x1;
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
@@ -457,7 +467,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_u16);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_u16);
code = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
code_ptr = (sljit_u16 *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -592,7 +602,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
}
if (flags & (ARG1_IMM | ARG2_IMM)) {
- reg = (flags & ARG2_IMM) ? arg1 : arg2;
+ reg = (sljit_s32)((flags & ARG2_IMM) ? arg1 : arg2);
imm = (flags & ARG2_IMM) ? arg2 : arg1;
switch (flags & 0xffff) {
@@ -610,8 +620,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
Although some clever things could be done here, "NOT IMM" does not worth the efforts. */
break;
case SLJIT_ADD:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- nimm = -(sljit_sw)imm;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ nimm = NEGATE(imm);
if (IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, ADDSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
@@ -633,18 +643,18 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
nimm = get_imm(imm);
if (nimm != INVALID_IMM)
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
- nimm = get_imm(-(sljit_sw)imm);
+ nimm = get_imm(NEGATE(imm));
if (nimm != INVALID_IMM)
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
break;
case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
imm = get_imm(imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, ADCI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
case SLJIT_SUB:
- /* SUB operation can be replaced by ADD because of the negative carry flag. */
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
if (flags & ARG1_IMM) {
if (imm == 0 && IS_2_LO_REGS(reg, dst))
return push_inst16(compiler, RSBSI | RD3(dst) | RN3(reg));
@@ -659,11 +669,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
nimm = get_imm(imm);
if (nimm != INVALID_IMM)
return push_inst32(compiler, CMPI_W | RN4(reg) | nimm);
- nimm = get_imm(-(sljit_sw)imm);
+ nimm = get_imm(NEGATE(imm));
if (nimm != INVALID_IMM)
return push_inst32(compiler, CMNI_W | RN4(reg) | nimm);
+ break;
}
- nimm = -(sljit_sw)imm;
+ nimm = NEGATE(imm);
if (IS_2_LO_REGS(reg, dst)) {
if (imm <= 0x7)
return push_inst16(compiler, SUBSI3 | IMM3(imm) | RD3(dst) | RN3(reg));
@@ -685,11 +696,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
nimm = get_imm(imm);
if (nimm != INVALID_IMM)
return push_inst32(compiler, SUB_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
- nimm = get_imm(-(sljit_sw)imm);
+ nimm = get_imm(NEGATE(imm));
if (nimm != INVALID_IMM)
return push_inst32(compiler, ADD_WI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
break;
case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
if (flags & ARG1_IMM)
break;
imm = get_imm(imm);
@@ -699,8 +711,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
case SLJIT_AND:
nimm = get_imm(imm);
if (nimm != INVALID_IMM)
- return push_inst32(compiler, ANDI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
- imm = get_imm(imm);
+ return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TSTI : ANDI) | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
+ imm = get_imm(~imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, BICI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
@@ -708,7 +720,7 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
nimm = get_imm(imm);
if (nimm != INVALID_IMM)
return push_inst32(compiler, ORRI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | nimm);
- imm = get_imm(imm);
+ imm = get_imm(~imm);
if (imm != INVALID_IMM)
return push_inst32(compiler, ORNI | (flags & SET_FLAGS) | RD4(dst) | RN4(reg) | imm);
break;
@@ -752,12 +764,12 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
if (flags & ARG2_IMM) {
imm = arg2;
arg2 = (arg1 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
- FAIL_IF(load_immediate(compiler, arg2, imm));
+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg2, imm));
}
else {
imm = arg1;
arg1 = (arg2 == TMP_REG1) ? TMP_REG2 : TMP_REG1;
- FAIL_IF(load_immediate(compiler, arg1, imm));
+ FAIL_IF(load_immediate(compiler, (sljit_s32)arg1, imm));
}
SLJIT_ASSERT(arg1 != arg2);
@@ -768,9 +780,10 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
case SLJIT_MOV_P:
SLJIT_ASSERT(!(flags & SET_FLAGS) && arg1 == TMP_REG2);
- if (dst == arg2)
+ if (dst == (sljit_s32)arg2)
return SLJIT_SUCCESS;
return push_inst16(compiler, MOV | SET_REGS44(dst, arg2));
case SLJIT_MOV_U8:
@@ -803,18 +816,19 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
FAIL_IF(push_inst32(compiler, CLZ | RN4(arg2) | RD4(dst) | RM4(arg2)));
return SLJIT_SUCCESS;
case SLJIT_ADD:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
if (IS_3_LO_REGS(dst, arg1, arg2))
return push_inst16(compiler, ADDS | RD3(dst) | RN3(arg1) | RM3(arg2));
- if (dst == arg1 && !(flags & SET_FLAGS))
+ if (dst == (sljit_s32)arg1 && !(flags & SET_FLAGS))
return push_inst16(compiler, ADD | SET_REGS44(dst, arg2));
return push_inst32(compiler, ADD_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_ADDC:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ADCS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ADC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SUB:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
if (flags & UNUSED_RETURN) {
if (IS_2_LO_REGS(arg1, arg2))
return push_inst16(compiler, CMP | RD3(arg1) | RN3(arg2));
@@ -824,7 +838,8 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
return push_inst16(compiler, SUBS | RD3(dst) | RN3(arg1) | RM3(arg2));
return push_inst32(compiler, SUB_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SUBC:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, SBCS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, SBC_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_MUL:
@@ -836,29 +851,29 @@ static sljit_s32 emit_op_imm(struct sljit_compiler *compiler, sljit_s32 flags, s
/* cmp TMP_REG2, dst asr #31. */
return push_inst32(compiler, CMP_W | RN4(TMP_REG2) | 0x70e0 | RM4(dst));
case SLJIT_AND:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ANDS | RD3(dst) | RN3(arg2));
if ((flags & UNUSED_RETURN) && IS_2_LO_REGS(arg1, arg2))
return push_inst16(compiler, TST | RD3(arg1) | RN3(arg2));
- return push_inst32(compiler, AND_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
+ return push_inst32(compiler, ((flags & UNUSED_RETURN) ? TST_W : AND_W) | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_OR:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ORRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ORR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_XOR:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, EORS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, EOR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_SHL:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSLS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, LSL_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_LSHR:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, LSRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, LSR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
case SLJIT_ASHR:
- if (dst == arg1 && IS_2_LO_REGS(dst, arg2))
+ if (dst == (sljit_s32)arg1 && IS_2_LO_REGS(dst, arg2))
return push_inst16(compiler, ASRS | RD3(dst) | RN3(arg2));
return push_inst32(compiler, ASR_W | (flags & SET_FLAGS) | RD4(dst) | RN4(arg1) | RM4(arg2));
}
@@ -951,20 +966,22 @@ static const sljit_ins sljit_mem32[13] = {
/* Helper function. Dst should be reg + value, using at most 1 instruction, flags does not set. */
static sljit_s32 emit_set_delta(struct sljit_compiler *compiler, sljit_s32 dst, sljit_s32 reg, sljit_sw value)
{
+ sljit_uw imm;
+
if (value >= 0) {
if (value <= 0xfff)
return push_inst32(compiler, ADDWI | RD4(dst) | RN4(reg) | IMM12(value));
- value = get_imm(value);
- if (value != INVALID_IMM)
- return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | value);
+ imm = get_imm((sljit_uw)value);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | RD4(dst) | RN4(reg) | imm);
}
else {
value = -value;
if (value <= 0xfff)
return push_inst32(compiler, SUBWI | RD4(dst) | RN4(reg) | IMM12(value));
- value = get_imm(value);
- if (value != INVALID_IMM)
- return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | value);
+ imm = get_imm((sljit_uw)value);
+ if (imm != INVALID_IMM)
+ return push_inst32(compiler, SUB_WI | RD4(dst) | RN4(reg) | imm);
}
return SLJIT_ERR_UNSUPPORTED;
}
@@ -980,13 +997,13 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
arg &= ~SLJIT_MEM;
if (SLJIT_UNLIKELY(!(arg & REG_MASK))) {
- tmp = get_imm(argw & ~0xfff);
+ tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
if (tmp != INVALID_IMM) {
FAIL_IF(push_inst32(compiler, MOV_WI | RD4(tmp_reg) | tmp));
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg) | (argw & 0xfff));
}
- FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
if (IS_2_LO_REGS(reg, tmp_reg) && sljit_mem16_imm5[flags])
return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(tmp_reg));
return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(tmp_reg));
@@ -999,11 +1016,11 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
if (!argw && IS_3_LO_REGS(reg, arg, other_r))
return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(other_r));
- return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | (argw << 4));
+ return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(other_r) | ((sljit_ins)argw << 4));
}
if (argw > 0xfff) {
- tmp = get_imm(argw & ~0xfff);
+ tmp = get_imm((sljit_uw)argw & ~(sljit_uw)0xfff);
if (tmp != INVALID_IMM) {
push_inst32(compiler, ADD_WI | RD4(tmp_reg) | RN4(arg) | tmp);
arg = tmp_reg;
@@ -1011,7 +1028,7 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
}
else if (argw < -0xff) {
- tmp = get_imm(-argw & ~0xff);
+ tmp = get_imm((sljit_uw)-argw & ~(sljit_uw)0xff);
if (tmp != INVALID_IMM) {
push_inst32(compiler, SUB_WI | RD4(tmp_reg) | RN4(arg) | tmp);
arg = tmp_reg;
@@ -1037,21 +1054,21 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
}
if (tmp < 3)
- return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | (argw << (6 - tmp)));
+ return push_inst16(compiler, sljit_mem16_imm5[flags] | RD3(reg) | RN3(arg) | ((sljit_ins)argw << (6 - tmp)));
}
else if (SLJIT_UNLIKELY(arg == SLJIT_SP) && IS_WORD_SIZE(flags) && OFFSET_CHECK(0xff, 2) && reg_map[reg] <= 7) {
/* SP based immediate. */
- return push_inst16(compiler, STR_SP | ((flags & STORE) ? 0 : 0x800) | RDN3(reg) | (argw >> 2));
+ return push_inst16(compiler, STR_SP | (sljit_ins)((flags & STORE) ? 0 : 0x800) | RDN3(reg) | ((sljit_ins)argw >> 2));
}
if (argw >= 0 && argw <= 0xfff)
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | argw);
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM12 | RT4(reg) | RN4(arg) | (sljit_ins)argw);
else if (argw < 0 && argw >= -0xff)
- return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | -argw);
+ return push_inst32(compiler, sljit_mem32[flags] | MEM_IMM8 | RT4(reg) | RN4(arg) | (sljit_ins)-argw);
SLJIT_ASSERT(arg != tmp_reg);
- FAIL_IF(load_immediate(compiler, tmp_reg, argw));
+ FAIL_IF(load_immediate(compiler, tmp_reg, (sljit_uw)argw));
if (IS_3_LO_REGS(reg, arg, tmp_reg))
return push_inst16(compiler, sljit_mem16[flags] | RD3(reg) | RN3(arg) | RM3(tmp_reg));
return push_inst32(compiler, sljit_mem32[flags] | RT4(reg) | RN4(arg) | RM4(tmp_reg));
@@ -1065,114 +1082,203 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args, size, i, tmp;
- sljit_ins push = 0;
-#ifdef _WIN32
- sljit_uw imm;
+ sljit_s32 size, i, tmp, word_arg_count, saved_arg_count;
+ sljit_uw offset;
+ sljit_uw imm = 0;
+#ifdef __SOFTFP__
+ sljit_u32 float_arg_count;
+#else
+ sljit_u32 old_offset, f32_offset;
+ sljit_u32 remap[3];
+ sljit_u32 *remap_ptr = remap;
#endif
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--)
- push |= 1 << reg_map[i];
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--)
+ imm |= (sljit_uw)1 << reg_map[i];
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
- push |= 1 << reg_map[i];
+ imm |= (sljit_uw)1 << reg_map[i];
- FAIL_IF((push & 0xff00)
- ? push_inst32(compiler, PUSH_W | (1 << 14) | push)
- : push_inst16(compiler, PUSH | (1 << 8) | push));
+ /* At least two registers must be set for PUSH_W and one for PUSH instruction. */
+ FAIL_IF((imm & 0xff00)
+ ? push_inst32(compiler, PUSH_W | (1 << 14) | imm)
+ : push_inst16(compiler, PUSH | (1 << 8) | imm));
/* Stack must be aligned to 8 bytes: (LR, R4) */
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- local_size = ((size + local_size + 7) & ~7) - size;
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((size & SSIZE_OF(sw)) != 0) {
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (sizeof(sljit_sw) >> 2)));
+ size += SSIZE_OF(sw);
+ }
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fsaveds > 0)
+ FAIL_IF(push_inst32(compiler, VPUSH | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst32(compiler, VPUSH | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ }
+ }
+
+ local_size = ((size + local_size + 0x7) & ~0x7) - size;
compiler->local_size = local_size;
-#ifdef _WIN32
- if (local_size >= 256) {
- if (local_size > 4096)
- imm = get_imm(4096);
- else
- imm = get_imm(local_size & ~0xff);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+#ifdef __SOFTFP__
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
- SLJIT_ASSERT(imm != INVALID_IMM);
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(SLJIT_SP) | imm));
+ offset = 0;
+ float_arg_count = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst32(compiler, VMOV2 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ else
+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800100 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ offset += sizeof(sljit_f64) - sizeof(sljit_sw);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst32(compiler, VMOV | (float_arg_count << 16) | (offset << 10)));
+ else
+ FAIL_IF(push_inst32(compiler, VLDR_F32 | 0x800000 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count - 1 != (sljit_s32)(offset >> 2))
+ tmp = word_arg_count;
+ else
+ break;
+
+ SLJIT_ASSERT(reg_map[tmp] <= 7);
+
+ if (offset < 4 * sizeof(sljit_sw))
+ FAIL_IF(push_inst16(compiler, MOV | RD3(tmp) | (offset << 1)));
+ else
+ FAIL_IF(push_inst16(compiler, LDR_SP | RDN3(tmp)
+ | ((offset + (sljit_uw)size - 4 * sizeof(sljit_sw)) >> 2)));
+ break;
+ }
+
+ offset += sizeof(sljit_sw);
+ arg_types >>= SLJIT_ARG_SHIFT;
}
+
+ compiler->args_size = offset;
#else
- if (local_size > 0) {
- if (local_size <= (127 << 2))
- FAIL_IF(push_inst16(compiler, SUB_SP | (local_size >> 2)));
- else
- FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, local_size));
+ offset = SLJIT_FR0;
+ old_offset = SLJIT_FR0;
+ f32_offset = 0;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset != old_offset)
+ *remap_ptr++ = VMOV_F32 | SLJIT_32 | DD4(offset) | DM4(old_offset);
+ old_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ *remap_ptr++ = VMOV_F32 | 0x20 | DD4(offset) | DM4(f32_offset);
+ f32_offset = 0;
+ } else {
+ if (offset != old_offset)
+ *remap_ptr++ = VMOV_F32 | DD4(offset) | DM4(old_offset);
+ f32_offset = old_offset;
+ old_offset++;
+ }
+ offset++;
+ break;
+ default:
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0 - saved_arg_count, SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
+
+ word_arg_count++;
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
}
-#endif
- args = get_arg_count(arg_types);
+ SLJIT_ASSERT((sljit_uw)(remap_ptr - remap) <= sizeof(remap));
- if (args >= 1)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S0, SLJIT_R0)));
- if (args >= 2)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S1, SLJIT_R1)));
- if (args >= 3)
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_S2, SLJIT_R2)));
+ while (remap_ptr > remap)
+ FAIL_IF(push_inst32(compiler, *(--remap_ptr)));
+#endif
#ifdef _WIN32
- if (local_size >= 256) {
- if (local_size > 4096) {
- imm = get_imm(4096);
- SLJIT_ASSERT(imm != INVALID_IMM);
-
- if (local_size < 4 * 4096) {
- if (local_size > 2 * 4096) {
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
- local_size -= 4096;
- }
+ if (local_size >= 4096) {
+ imm = get_imm(4096);
+ SLJIT_ASSERT(imm != INVALID_IMM);
- if (local_size > 2 * 4096) {
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
- local_size -= 4096;
- }
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
- local_size -= 4096;
+ if (local_size < 4 * 4096) {
+ if (local_size > 2 * 4096) {
+ if (local_size > 3 * 4096) {
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+ }
- SLJIT_ASSERT(local_size > 0);
- }
- else {
- FAIL_IF(load_immediate(compiler, SLJIT_R3, (local_size >> 12) - 1));
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
- SLJIT_ASSERT(reg_map[SLJIT_R3] < 7);
- FAIL_IF(push_inst16(compiler, SUBSI8 | RDN3(SLJIT_R3) | 1));
- FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-7 & 0xff)));
-
- local_size &= 0xfff;
-
- if (local_size != 0)
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG2) | RN4(TMP_REG1)));
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
}
+ } else {
+ FAIL_IF(load_immediate(compiler, TMP_REG2, ((sljit_uw)local_size >> 12) - 1));
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ FAIL_IF(push_inst32(compiler, SUB_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm));
+ FAIL_IF(push_inst32(compiler, SUB_WI | SET_FLAGS | RD4(TMP_REG2) | RN4(TMP_REG2) | 1));
+ FAIL_IF(push_inst16(compiler, BCC | (0x1 << 8) /* not-equal */ | (-8 & 0xff)));
+ }
- if (local_size >= 256) {
- imm = get_imm(local_size & ~0xff);
- SLJIT_ASSERT(imm != INVALID_IMM);
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ local_size &= 0xfff;
+ }
- FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(TMP_REG1) | imm));
- }
- }
+ if (local_size >= 256) {
+ SLJIT_ASSERT(local_size < 4096);
- local_size &= 0xff;
- FAIL_IF(push_inst32(compiler, LDRI | 0x400 | (local_size > 0 ? 0x100 : 0) | RT4(TMP_REG2) | RN4(TMP_REG1) | local_size));
+ if (local_size <= (127 << 2))
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));
+ else
+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));
- FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_SP, TMP_REG1)));
+ FAIL_IF(push_inst32(compiler, LDRI | 0x400 | RT4(TMP_REG1) | RN4(SLJIT_SP)));
+ } else if (local_size > 0)
+ FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | (sljit_uw)local_size));
+#else /* !_WIN32 */
+ if (local_size > 0) {
+ if (local_size <= (127 << 2))
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)local_size >> 2)));
+ else
+ FAIL_IF(emit_op_imm(compiler, SLJIT_SUB | ARG2_IMM, SLJIT_SP, SLJIT_SP, (sljit_uw)local_size));
}
- else if (local_size > 0)
- FAIL_IF(push_inst32(compiler, LDRI | 0x500 | RT4(TMP_REG1) | RN4(SLJIT_SP) | local_size));
-#endif
+#endif /* _WIN32 */
return SLJIT_SUCCESS;
}
@@ -1188,37 +1294,143 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- compiler->local_size = ((size + local_size + 7) & ~7) - size;
+
+ if ((size & SSIZE_OF(sw)) != 0 && (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG))
+ size += SSIZE_OF(sw);
+
+ compiler->local_size = ((size + local_size + 0x7) & ~0x7) - size;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_add_sp(struct sljit_compiler *compiler, sljit_uw imm)
{
- sljit_s32 i, tmp;
- sljit_ins pop = 0;
+ sljit_uw imm2;
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+ /* The TMP_REG1 register must keep its value. */
+ if (imm <= (127u << 2))
+ return push_inst16(compiler, ADD_SP_I | (imm >> 2));
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ if (imm <= 0xfff)
+ return push_inst32(compiler, ADDWI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | IMM12(imm));
- if (compiler->local_size > 0) {
- if (compiler->local_size <= (127 << 2))
- FAIL_IF(push_inst16(compiler, ADD_SP | (compiler->local_size >> 2)));
- else
- FAIL_IF(emit_op_imm(compiler, SLJIT_ADD | ARG2_IMM, SLJIT_SP, SLJIT_SP, compiler->local_size));
+ imm2 = get_imm(imm);
+
+ if (imm2 != INVALID_IMM)
+ return push_inst32(compiler, ADD_WI | RD4(SLJIT_SP) | RN4(SLJIT_SP) | imm2);
+
+ FAIL_IF(load_immediate(compiler, TMP_REG2, imm));
+ return push_inst16(compiler, ADD_SP | RN3(TMP_REG2));
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size)
+{
+ sljit_s32 local_size, fscratches, fsaveds, i, tmp;
+ sljit_s32 lr_dst = TMP_PC;
+ sljit_uw reg_list;
+
+ SLJIT_ASSERT(reg_map[TMP_REG2] == 14 && frame_size <= 128);
+
+ local_size = compiler->local_size;
+ fscratches = compiler->fscratches;
+ fsaveds = compiler->fsaveds;
+
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (fsaveds + fscratches >= SLJIT_NUMBER_OF_FLOAT_REGISTERS) {
+ FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS << 1)));
+ } else {
+ if (fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG)
+ FAIL_IF(push_inst32(compiler, VPOP | DD4(fscratches) | ((sljit_uw)(fscratches - (SLJIT_FIRST_SAVED_FLOAT_REG - 1)) << 1)));
+ if (fsaveds > 0)
+ FAIL_IF(push_inst32(compiler, VPOP | DD4(SLJIT_FS0) | ((sljit_uw)fsaveds << 1)));
+ }
+
+ local_size = GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1) & 0x7;
}
- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--)
- pop |= 1 << reg_map[i];
+ if (frame_size < 0) {
+ lr_dst = TMP_REG2;
+ frame_size = 0;
+ } else if (frame_size > 0)
+ lr_dst = 0;
+
+ reg_list = 0;
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0; i > tmp; i--)
+ reg_list |= (sljit_uw)1 << reg_map[i];
for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--)
- pop |= 1 << reg_map[i];
+ reg_list |= (sljit_uw)1 << reg_map[i];
+
+ if (lr_dst == 0 && (reg_list & (reg_list - 1)) == 0) {
+ /* The local_size does not include the saved registers. */
+ local_size += SSIZE_OF(sw);
+
+ if (reg_list != 0)
+ local_size += SSIZE_OF(sw);
+
+ if (frame_size > local_size)
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | ((sljit_uw)(frame_size - local_size) >> 2)));
+ else if (frame_size < local_size)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)(local_size - frame_size)));
+
+ if (reg_list == 0)
+ return SLJIT_SUCCESS;
+
+ if (compiler->saveds > 0) {
+ SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_S0]));
+ lr_dst = SLJIT_S0;
+ } else {
+ SLJIT_ASSERT(reg_list == ((sljit_uw)1 << reg_map[SLJIT_FIRST_SAVED_REG]));
+ lr_dst = SLJIT_FIRST_SAVED_REG;
+ }
+
+ frame_size -= 2 * SSIZE_OF(sw);
+
+ if (reg_map[lr_dst] <= 7)
+ return push_inst16(compiler, STR_SP | 0x800 | RDN3(lr_dst) | (sljit_uw)(frame_size >> 2));
+
+ return push_inst32(compiler, LDR | RT4(lr_dst) | RN4(SLJIT_SP) | (sljit_uw)frame_size);
+ }
+
+ if (local_size > 0)
+ FAIL_IF(emit_add_sp(compiler, (sljit_uw)local_size));
+
+ if (!(reg_list & 0xff00) && lr_dst != TMP_REG2) {
+ if (lr_dst == TMP_PC)
+ reg_list |= 1u << 8;
+
+ /* At least one register must be set for POP instruction. */
+ SLJIT_ASSERT(reg_list != 0);
- return (pop & 0xff00)
- ? push_inst32(compiler, POP_W | (1 << 15) | pop)
- : push_inst16(compiler, POP | (1 << 8) | pop);
+ FAIL_IF(push_inst16(compiler, POP | reg_list));
+ } else {
+ if (lr_dst != 0) {
+ if (reg_list == 0)
+ return push_inst32(compiler, 0xf85d0b04 | RT4(lr_dst));
+
+ reg_list |= (sljit_uw)1 << reg_map[lr_dst];
+ }
+
+ /* At least two registers must be set for POP_W instruction. */
+ SLJIT_ASSERT((reg_list & (reg_list - 1)) != 0);
+
+ FAIL_IF(push_inst32(compiler, POP_W | reg_list));
+ }
+
+ if (frame_size > 0)
+ return push_inst16(compiler, SUB_SP_I | (((sljit_uw)frame_size - sizeof(sljit_sw)) >> 2));
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ return emit_stack_frame_release(compiler, 0);
}
/* --------------------------------------------------------------------- */
@@ -1250,8 +1462,8 @@ extern int __aeabi_idivmod(int numerator, int denominator);
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
#if !(defined __ARM_FEATURE_IDIV) && !(defined __ARM_ARCH_EXT_IDIV__)
- sljit_sw saved_reg_list[3];
- sljit_sw saved_reg_count;
+ sljit_uw saved_reg_list[3];
+ sljit_uw saved_reg_count;
#endif
CHECK_ERROR();
@@ -1266,10 +1478,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
case SLJIT_LMUL_UW:
case SLJIT_LMUL_SW:
return push_inst32(compiler, (op == SLJIT_LMUL_UW ? UMULL : SMULL)
- | (reg_map[SLJIT_R1] << 8)
- | (reg_map[SLJIT_R0] << 12)
- | (reg_map[SLJIT_R0] << 16)
- | reg_map[SLJIT_R1]);
+ | RD4(SLJIT_R1) | RT4(SLJIT_R0) | RN4(SLJIT_R0) | RM4(SLJIT_R1));
#if (defined __ARM_FEATURE_IDIV) || (defined __ARM_ARCH_EXT_IDIV__)
case SLJIT_DIVMOD_UW:
case SLJIT_DIVMOD_SW:
@@ -1314,10 +1523,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R0, SLJIT_R1)));
FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(SLJIT_R1, TMP_REG1)));
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__rt_udiv) : SLJIT_FUNC_OFFSET(__rt_sdiv))));
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__rt_udiv) : SLJIT_FUNC_ADDR(__rt_sdiv))));
#elif defined(__GNUC__)
FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM,
- ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod))));
+ ((op | 0x2) == SLJIT_DIV_UW ? SLJIT_FUNC_ADDR(__aeabi_uidivmod) : SLJIT_FUNC_ADDR(__aeabi_idivmod))));
#else
#error "Software divmod functions are needed"
#endif
@@ -1356,7 +1565,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
op = GET_OPCODE(op);
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P) {
@@ -1364,6 +1573,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
case SLJIT_MOV_P:
flags = WORD_SIZE;
break;
@@ -1394,12 +1604,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
}
if (src & SLJIT_IMM)
- FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, srcw));
+ FAIL_IF(emit_op_imm(compiler, SLJIT_MOV | ARG2_IMM, dst_r, TMP_REG2, (sljit_uw)srcw));
else if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, flags, dst_r, src, srcw, TMP_REG1));
} else {
if (dst_r != TMP_REG1)
- return emit_op_imm(compiler, op, dst_r, TMP_REG2, src);
+ return emit_op_imm(compiler, op, dst_r, TMP_REG2, (sljit_uw)src);
dst_r = src;
}
@@ -1409,14 +1619,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
}
- if (op == SLJIT_NEG) {
-#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
- || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
- compiler->skip_checks = 1;
-#endif
- return sljit_emit_op2(compiler, SLJIT_SUB | op_flags, dst, dstw, SLJIT_IMM, 0, src, srcw);
- }
-
flags = HAS_FLAGS(op_flags) ? SET_FLAGS : 0;
if (src & SLJIT_MEM) {
@@ -1424,7 +1626,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
src = TMP_REG1;
}
- emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, src);
+ emit_op_imm(compiler, flags | op, dst_r, TMP_REG2, (sljit_uw)src);
if (SLJIT_UNLIKELY(dst & SLJIT_MEM))
return emit_op_mem(compiler, flags | STORE, dst_r, dst, dstw, TMP_REG2);
@@ -1439,17 +1641,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 dst_reg, flags, src2_reg;
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
- dst_reg = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ dst_reg = FAST_IS_REG(dst) ? dst : TMP_REG1;
flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ if (dst == TMP_REG1)
+ flags |= UNUSED_RETURN;
+
if (src1 & SLJIT_IMM)
flags |= ARG1_IMM;
else if (src1 & SLJIT_MEM) {
@@ -1469,16 +1671,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
else
src2w = src2;
- if (dst == SLJIT_UNUSED)
- flags |= UNUSED_RETURN;
-
- emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, src1w, src2w);
+ emit_op_imm(compiler, flags | GET_OPCODE(op), dst_reg, (sljit_uw)src1w, (sljit_uw)src2w);
if (!(dst & SLJIT_MEM))
return SLJIT_SUCCESS;
return emit_op_mem(compiler, WORD_SIZE | STORE, dst_reg, dst, dstw, TMP_REG2);
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -1521,7 +1734,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1540,22 +1753,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
sljit_uw imm;
- sljit_sw inst = VSTR_F32 | (flags & (SLJIT_F32_OP | FPU_LOAD));
+ sljit_ins inst = VSTR_F32 | (flags & (SLJIT_32 | FPU_LOAD));
SLJIT_ASSERT(arg & SLJIT_MEM);
/* Fast loads and stores. */
if (SLJIT_UNLIKELY(arg & OFFS_REG_MASK)) {
- FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | ((argw & 0x3) << 6)));
+ FAIL_IF(push_inst32(compiler, ADD_W | RD4(TMP_REG1) | RN4(arg & REG_MASK) | RM4(OFFS_REG(arg)) | (((sljit_uw)argw & 0x3) << 6)));
arg = SLJIT_MEM | TMP_REG1;
argw = 0;
}
if ((arg & REG_MASK) && (argw & 0x3) == 0) {
if (!(argw & ~0x3fc))
- return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | (argw >> 2));
+ return push_inst32(compiler, inst | 0x800000 | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)argw >> 2));
if (!(-argw & ~0x3fc))
- return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | (-argw >> 2));
+ return push_inst32(compiler, inst | RN4(arg & REG_MASK) | DD4(reg) | ((sljit_uw)-argw >> 2));
}
if (arg & REG_MASK) {
@@ -1563,20 +1776,22 @@ static sljit_s32 emit_fop_mem(struct sljit_compiler *compiler, sljit_s32 flags,
FAIL_IF(compiler->error);
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
}
- imm = get_imm(argw & ~0x3fc);
+
+ imm = get_imm((sljit_uw)argw & ~(sljit_uw)0x3fc);
if (imm != INVALID_IMM) {
FAIL_IF(push_inst32(compiler, ADD_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
- return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
+ return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));
}
- imm = get_imm(-argw & ~0x3fc);
+
+ imm = get_imm((sljit_uw)-argw & ~(sljit_uw)0x3fc);
if (imm != INVALID_IMM) {
argw = -argw;
FAIL_IF(push_inst32(compiler, SUB_WI | RD4(TMP_REG1) | RN4(arg & REG_MASK) | imm));
- return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | ((argw & 0x3fc) >> 2));
+ return push_inst32(compiler, inst | RN4(TMP_REG1) | DD4(reg) | (((sljit_uw)argw & 0x3fc) >> 2));
}
}
- FAIL_IF(load_immediate(compiler, TMP_REG1, argw));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)argw));
if (arg & REG_MASK)
FAIL_IF(push_inst16(compiler, ADD | SET_REGS44(TMP_REG1, (arg & REG_MASK))));
return push_inst32(compiler, inst | 0x800000 | RN4(TMP_REG1) | DD4(reg));
@@ -1586,14 +1801,14 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src & SLJIT_MEM) {
- FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src, srcw));
+ FAIL_IF(emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src, srcw));
src = TMP_FREG1;
}
- FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_F32_OP) | DD4(TMP_FREG1) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VCVT_S32_F32 | (op & SLJIT_32) | DD4(TMP_FREG1) | DM4(src)));
if (FAST_IS_REG(dst))
return push_inst32(compiler, VMOV | (1 << 20) | RT4(dst) | DN4(TMP_FREG1));
@@ -1608,7 +1823,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
{
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (FAST_IS_REG(src))
FAIL_IF(push_inst32(compiler, VMOV | RT4(src) | DN4(TMP_FREG1)));
@@ -1617,14 +1832,14 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
FAIL_IF(emit_fop_mem(compiler, FPU_LOAD, TMP_FREG1, src, srcw));
}
else {
- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, (sljit_uw)srcw));
FAIL_IF(push_inst32(compiler, VMOV | RT4(TMP_REG1) | DN4(TMP_FREG1)));
}
- FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(TMP_FREG1)));
+ FAIL_IF(push_inst32(compiler, VCVT_F32_S32 | (op & SLJIT_32) | DD4(dst_r) | DM4(TMP_FREG1)));
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -1632,19 +1847,19 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src1 & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
+ emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
}
if (src2 & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
+ emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w);
src2 = TMP_FREG2;
}
- FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_F32_OP) | DD4(src1) | DM4(src2)));
+ FAIL_IF(push_inst32(compiler, VCMP_F32 | (op & SLJIT_32) | DD4(src1) | DM4(src2)));
return push_inst32(compiler, VMRS);
}
@@ -1656,16 +1871,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
CHECK_ERROR();
- SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100), float_transfer_bit_error);
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (GET_OPCODE(op) != SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
if (src & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, dst_r, src, srcw);
+ emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, dst_r, src, srcw);
src = dst_r;
}
@@ -1673,25 +1888,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
case SLJIT_MOV_F64:
if (src != dst_r) {
if (dst_r != TMP_FREG1)
- FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));
else
dst_r = src;
}
break;
case SLJIT_NEG_F64:
- FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VNEG_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));
break;
case SLJIT_ABS_F64:
- FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
+ FAIL_IF(push_inst32(compiler, VABS_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));
break;
case SLJIT_CONV_F64_FROM_F32:
- FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DM4(src)));
- op ^= SLJIT_F32_OP;
+ FAIL_IF(push_inst32(compiler, VCVT_F64_F32 | (op & SLJIT_32) | DD4(dst_r) | DM4(src)));
+ op ^= SLJIT_32;
break;
}
if (dst & SLJIT_MEM)
- return emit_fop_mem(compiler, (op & SLJIT_F32_OP), dst_r, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_32), dst_r, dst, dstw);
return SLJIT_SUCCESS;
}
@@ -1708,36 +1923,36 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
if (src1 & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG1, src1, src1w);
+ emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG1, src1, src1w);
src1 = TMP_FREG1;
}
if (src2 & SLJIT_MEM) {
- emit_fop_mem(compiler, (op & SLJIT_F32_OP) | FPU_LOAD, TMP_FREG2, src2, src2w);
+ emit_fop_mem(compiler, (op & SLJIT_32) | FPU_LOAD, TMP_FREG2, src2, src2w);
src2 = TMP_FREG2;
}
switch (GET_OPCODE(op)) {
case SLJIT_ADD_F64:
- FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ FAIL_IF(push_inst32(compiler, VADD_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
case SLJIT_SUB_F64:
- FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ FAIL_IF(push_inst32(compiler, VSUB_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
case SLJIT_MUL_F64:
- FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ FAIL_IF(push_inst32(compiler, VMUL_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
case SLJIT_DIV_F64:
- FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_F32_OP) | DD4(dst_r) | DN4(src1) | DM4(src2)));
+ FAIL_IF(push_inst32(compiler, VDIV_F32 | (op & SLJIT_32) | DD4(dst_r) | DN4(src1) | DM4(src2)));
break;
}
if (!(dst & SLJIT_MEM))
return SLJIT_SUCCESS;
- return emit_fop_mem(compiler, (op & SLJIT_F32_OP), TMP_FREG1, dst, dstw);
+ return emit_fop_mem(compiler, (op & SLJIT_32), TMP_FREG1, dst, dstw);
}
#undef FPU_LOAD
@@ -1776,10 +1991,20 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_NOT_EQUAL_F64:
return 0x1;
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x2;
+ /* fallthrough */
+
case SLJIT_LESS:
case SLJIT_LESS_F64:
return 0x3;
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD)
+ return 0x3;
+ /* fallthrough */
+
case SLJIT_GREATER_EQUAL:
case SLJIT_GREATER_EQUAL_F64:
return 0x2;
@@ -1805,15 +2030,17 @@ static sljit_uw get_cc(struct sljit_compiler *compiler, sljit_s32 type)
return 0xd;
case SLJIT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x1;
+ /* fallthrough */
case SLJIT_UNORDERED_F64:
return 0x6;
case SLJIT_NOT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return 0x0;
+ /* fallthrough */
case SLJIT_ORDERED_F64:
return 0x7;
@@ -1874,113 +2101,126 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
#ifdef __SOFTFP__
-static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src)
+static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src, sljit_u32 *extra_space)
{
- sljit_s32 stack_offset = 0;
- sljit_s32 arg_count = 0;
- sljit_s32 word_arg_offset = 0;
- sljit_s32 float_arg_count = 0;
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
+ sljit_u32 word_arg_offset = 0;
+ sljit_u32 float_arg_count = 0;
sljit_s32 types = 0;
- sljit_s32 src_offset = 4 * sizeof(sljit_sw);
+ sljit_u32 src_offset = 4 * sizeof(sljit_sw);
sljit_u8 offsets[4];
+ sljit_u8 *offset_ptr = offsets;
if (src && FAST_IS_REG(*src))
- src_offset = reg_map[*src] * sizeof(sljit_sw);
+ src_offset = (sljit_u32)reg_map[*src] * sizeof(sljit_sw);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_f32);
- arg_count++;
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7)
+ offset += sizeof(sljit_sw);
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f64);
float_arg_count++;
break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_offset & 0x7)
- stack_offset += sizeof(sljit_sw);
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_f64);
- arg_count++;
+ case SLJIT_ARG_TYPE_F32:
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_f32);
float_arg_count++;
break;
default:
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_sw);
- arg_count++;
+ *offset_ptr++ = (sljit_u8)offset;
+ offset += sizeof(sljit_sw);
word_arg_offset += sizeof(sljit_sw);
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
- if (stack_offset > 16)
- FAIL_IF(push_inst16(compiler, SUB_SP | (((stack_offset - 16) + 0x7) & ~0x7) >> 2));
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ /* Keep lr register on the stack. */
+ if (is_tail_call)
+ offset += sizeof(sljit_sw);
+
+ offset = ((offset - 4 * sizeof(sljit_sw)) + 0x7) & ~(sljit_uw)0x7;
+
+ *extra_space = offset;
+
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset));
+ else
+ FAIL_IF(push_inst16(compiler, SUB_SP_I | (offset >> 2)));
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ *extra_space = 0;
+ }
SLJIT_ASSERT(reg_map[TMP_REG1] == 12);
/* Process arguments in reversed direction. */
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- arg_count--;
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
float_arg_count--;
- stack_offset = offsets[arg_count];
+ offset = *(--offset_ptr);
+
+ SLJIT_ASSERT((offset & 0x7) == 0);
- if (stack_offset < 16) {
- if (src_offset == stack_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset || src_offset == offset + sizeof(sljit_sw)) {
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
*src = TMP_REG1;
}
- FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (stack_offset << 10)));
+ FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (offset << 10) | ((offset + sizeof(sljit_sw)) << 14) | float_arg_count));
} else
- FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
break;
- case SLJIT_ARG_TYPE_F64:
- arg_count--;
+ case SLJIT_ARG_TYPE_F32:
float_arg_count--;
- stack_offset = offsets[arg_count];
-
- SLJIT_ASSERT((stack_offset & 0x7) == 0);
+ offset = *(--offset_ptr);
- if (stack_offset < 16) {
- if (src_offset == stack_offset || src_offset == stack_offset + sizeof(sljit_sw)) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
*src = TMP_REG1;
}
- FAIL_IF(push_inst32(compiler, VMOV2 | 0x100000 | (stack_offset << 10) | ((stack_offset + sizeof(sljit_sw)) << 14) | float_arg_count));
+ FAIL_IF(push_inst32(compiler, VMOV | 0x100000 | (float_arg_count << 16) | (offset << 10)));
} else
- FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800100 | RN4(SLJIT_SP) | (float_arg_count << 12) | ((stack_offset - 16) >> 2)));
+ FAIL_IF(push_inst32(compiler, VSTR_F32 | 0x800000 | RN4(SLJIT_SP)
+ | (float_arg_count << 12) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
break;
default:
- arg_count--;
word_arg_offset -= sizeof(sljit_sw);
- stack_offset = offsets[arg_count];
+ offset = *(--offset_ptr);
- SLJIT_ASSERT(stack_offset >= word_arg_offset);
+ SLJIT_ASSERT(offset >= word_arg_offset);
- if (stack_offset != word_arg_offset) {
- if (stack_offset < 16) {
- if (src_offset == stack_offset) {
+ if (offset != word_arg_offset) {
+ if (offset < 4 * sizeof(sljit_sw)) {
+ if (src_offset == offset) {
FAIL_IF(push_inst16(compiler, MOV | (src_offset << 1) | 4 | (1 << 7)));
*src = TMP_REG1;
}
else if (src_offset == word_arg_offset) {
- *src = 1 + (stack_offset >> 2);
- src_offset = stack_offset;
+ *src = (sljit_s32)(1 + (offset >> 2));
+ src_offset = offset;
}
- FAIL_IF(push_inst16(compiler, MOV | (stack_offset >> 2) | (word_arg_offset << 1)));
+ FAIL_IF(push_inst16(compiler, MOV | (offset >> 2) | (word_arg_offset << 1)));
} else
- FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((stack_offset - 16) >> 2)));
+ FAIL_IF(push_inst16(compiler, STR_SP | (word_arg_offset << 6) | ((offset - 4 * sizeof(sljit_sw)) >> 2)));
}
break;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -1988,83 +2228,48 @@ static sljit_s32 softfloat_call_with_args(struct sljit_compiler *compiler, sljit
static sljit_s32 softfloat_post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
{
- sljit_s32 stack_size = 0;
-
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32)
- FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64)
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
FAIL_IF(push_inst32(compiler, VMOV2 | (1 << 16) | (0 << 12) | 0));
+ if ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32)
+ FAIL_IF(push_inst32(compiler, VMOV | (0 << 16) | (0 << 12)));
- arg_types >>= SLJIT_DEF_SHIFT;
-
- while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- stack_size += sizeof(sljit_f32);
- break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_size & 0x7)
- stack_size += sizeof(sljit_sw);
- stack_size += sizeof(sljit_f64);
- break;
- default:
- stack_size += sizeof(sljit_sw);
- break;
- }
-
- arg_types >>= SLJIT_DEF_SHIFT;
- }
-
- if (stack_size <= 16)
- return SLJIT_SUCCESS;
-
- return push_inst16(compiler, ADD_SP | ((((stack_size - 16) + 0x7) & ~0x7) >> 2));
+ return SLJIT_SUCCESS;
}
#else
static sljit_s32 hardfloat_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
{
- sljit_u32 remap = 0;
- sljit_u32 offset = 0;
- sljit_u32 new_offset, mask;
+ sljit_u32 offset = SLJIT_FR0;
+ sljit_u32 new_offset = SLJIT_FR0;
+ sljit_u32 f32_offset = 0;
/* Remove return value. */
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32) {
- new_offset = 0;
- mask = 1;
-
- while (remap & mask) {
- new_offset++;
- mask <<= 1;
- }
- remap |= mask;
-
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
if (offset != new_offset)
- FAIL_IF(push_inst32(compiler, VMOV_F32 | DD4((new_offset >> 1) + 1)
- | ((new_offset & 0x1) ? 0x400000 : 0) | DM4((offset >> 1) + 1)));
-
- offset += 2;
- }
- else if ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F64) {
- new_offset = 0;
- mask = 3;
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_32 | DD4(new_offset) | DM4(offset)));
- while (remap & mask) {
- new_offset += 2;
- mask <<= 2;
+ new_offset++;
+ offset++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (f32_offset != 0) {
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(f32_offset) | DM4(offset)));
+ f32_offset = 0;
+ } else {
+ if (offset != new_offset)
+ FAIL_IF(push_inst32(compiler, VMOV_F32 | 0x400000 | DD4(new_offset) | DM4(offset)));
+ f32_offset = new_offset;
+ new_offset++;
}
- remap |= mask;
-
- if (offset != new_offset)
- FAIL_IF(push_inst32(compiler, VMOV_F32 | SLJIT_F32_OP | DD4((new_offset >> 1) + 1) | DM4((offset >> 1) + 1)));
-
- offset += 2;
+ offset++;
+ break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -2077,13 +2282,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
{
#ifdef __SOFTFP__
struct sljit_jump *jump;
+ sljit_u32 extra_space = (sljit_u32)type;
#endif
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
#ifdef __SOFTFP__
- PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL));
+ PTR_FAIL_IF(softfloat_call_with_args(compiler, arg_types, NULL, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2093,9 +2303,29 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
jump = sljit_emit_jump(compiler, type);
PTR_FAIL_IF(jump == NULL);
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
+
+ PTR_FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(push_inst16(compiler, BX | RN3(TMP_REG2)));
+ return jump;
+ }
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
PTR_FAIL_IF(softfloat_post_call_with_args(compiler, arg_types));
return jump;
#else
+ if (type & SLJIT_CALL_RETURN) {
+ /* ldmia sp!, {..., lr} */
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
PTR_FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -2132,7 +2362,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_BL : 0));
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
FAIL_IF(emit_imm32_const(compiler, TMP_REG1, 0));
jump->addr = compiler->size;
@@ -2143,16 +2373,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
+#ifdef __SOFTFP__
+ sljit_u32 extra_space = (sljit_u32)type;
+#endif
+
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
-#ifdef __SOFTFP__
if (src & SLJIT_MEM) {
FAIL_IF(emit_op_mem(compiler, WORD_SIZE, TMP_REG1, src, srcw, TMP_REG1));
src = TMP_REG1;
}
- FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src));
+ if ((type & SLJIT_CALL_RETURN) && (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0)) {
+ FAIL_IF(push_inst16(compiler, MOV | SET_REGS44(TMP_REG1, src)));
+ src = TMP_REG1;
+ }
+
+#ifdef __SOFTFP__
+ FAIL_IF(softfloat_call_with_args(compiler, arg_types, &src, &extra_space));
+ SLJIT_ASSERT((extra_space & 0x7) == 0);
+
+ if ((type & SLJIT_CALL_RETURN) && extra_space == 0)
+ type = SLJIT_JUMP;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -2161,8 +2404,26 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+ if (extra_space > 0) {
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst32(compiler, LDR | RT4(TMP_REG2)
+ | RN4(SLJIT_SP) | (extra_space - sizeof(sljit_sw))));
+
+ FAIL_IF(push_inst16(compiler, ADD_SP_I | (extra_space >> 2)));
+
+ if (type & SLJIT_CALL_RETURN)
+ return push_inst16(compiler, BX | RN3(TMP_REG2));
+ }
+
+ SLJIT_ASSERT(!(type & SLJIT_CALL_RETURN));
return softfloat_post_call_with_args(compiler, arg_types);
#else /* !__SOFTFP__ */
+ if (type & SLJIT_CALL_RETURN) {
+ /* ldmia sp!, {..., lr} */
+ FAIL_IF(emit_stack_frame_release(compiler, -1));
+ type = SLJIT_JUMP;
+ }
+
FAIL_IF(hardfloat_call_with_args(compiler, arg_types));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -2236,7 +2497,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
CHECK_ERROR();
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
- dst_reg &= ~SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_32;
cc = get_cc(compiler, type & 0xff);
@@ -2254,13 +2515,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
| COPY_BITS(tmp, 12, 16, 4) | COPY_BITS(tmp, 11, 26, 1) | COPY_BITS(tmp, 8, 12, 3) | (tmp & 0xff));
}
- tmp = get_imm(srcw);
+ tmp = get_imm((sljit_uw)srcw);
if (tmp != INVALID_IMM) {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
return push_inst32(compiler, MOV_WI | RD4(dst_reg) | tmp);
}
- tmp = get_imm(~srcw);
+ tmp = get_imm(~(sljit_uw)srcw);
if (tmp != INVALID_IMM) {
FAIL_IF(push_inst16(compiler, IT | (cc << 4) | 0x8));
return push_inst32(compiler, MVN_WI | RD4(dst_reg) | tmp);
@@ -2295,6 +2556,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
case SLJIT_MOV:
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
case SLJIT_MOV_P:
flags = WORD_SIZE;
break;
@@ -2329,7 +2591,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
else
memw = -memw;
- return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | memw);
+ return push_inst32(compiler, inst | RT4(reg) | RN4(mem & REG_MASK) | (sljit_ins)memw);
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compiler *compiler, sljit_s32 dst, sljit_sw dstw, sljit_sw init_value)
@@ -2346,7 +2608,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const* sljit_emit_const(struct sljit_compi
set_const(const_, compiler);
dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
- PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, init_value));
+ PTR_FAIL_IF(emit_imm32_const(compiler, dst_r, (sljit_uw)init_value));
if (dst & SLJIT_MEM)
PTR_FAIL_IF(emit_op_mem(compiler, WORD_SIZE | STORE, dst_r, dst, dstw, TMP_REG2));
@@ -2388,5 +2650,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
index a90345f1f8..1a06b17d12 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_32.c
@@ -73,50 +73,49 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
- case SLJIT_MOV_U32:
- case SLJIT_MOV_S32:
- case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (dst != src2)
return push_inst(compiler, ADDU | S(src2) | TA(0) | D(dst), DR(dst));
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
- if (op == SLJIT_MOV_S8) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
- return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
- FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
- return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(24), DR(dst));
#endif /* SLJIT_MIPS_REV >= 1 */
- }
- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
- }
- else {
- SLJIT_ASSERT(dst == src2);
}
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
- if (op == SLJIT_MOV_S16) {
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
- return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
#else /* SLJIT_MIPS_REV < 1 */
- FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
- return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
+ FAIL_IF(push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, SRA | T(dst) | D(dst) | SH_IMM(16), DR(dst));
#endif /* SLJIT_MIPS_REV >= 1 */
- }
- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
- }
- else {
- SLJIT_ASSERT(dst == src2);
}
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_NOT:
@@ -438,131 +437,120 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
-static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr, sljit_u32 *extra_space)
{
- sljit_s32 stack_offset = 0;
- sljit_s32 arg_count = 0;
+ sljit_u32 is_tail_call = *extra_space & SLJIT_CALL_RETURN;
+ sljit_u32 offset = 0;
sljit_s32 float_arg_count = 0;
sljit_s32 word_arg_count = 0;
sljit_s32 types = 0;
- sljit_s32 arg_count_save, types_save;
sljit_ins prev_ins = NOP;
sljit_ins ins = NOP;
sljit_u8 offsets[4];
+ sljit_u8 *offsets_ptr = offsets;
SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ /* See ABI description in sljit_emit_enter. */
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+ *offsets_ptr = (sljit_u8)offset;
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- offsets[arg_count] = (sljit_u8)stack_offset;
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (offset & 0x7) {
+ offset += sizeof(sljit_sw);
+ *offsets_ptr = (sljit_u8)offset;
+ }
- if (word_arg_count == 0 && arg_count <= 1)
- offsets[arg_count] = 254 + arg_count;
+ if (word_arg_count == 0 && float_arg_count <= 1)
+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);
- stack_offset += sizeof(sljit_f32);
- arg_count++;
+ offset += sizeof(sljit_f64);
float_arg_count++;
break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_offset & 0x7)
- stack_offset += sizeof(sljit_sw);
- offsets[arg_count] = (sljit_u8)stack_offset;
-
- if (word_arg_count == 0 && arg_count <= 1)
- offsets[arg_count] = 254 + arg_count;
+ case SLJIT_ARG_TYPE_F32:
+ if (word_arg_count == 0 && float_arg_count <= 1)
+ *offsets_ptr = (sljit_u8)(254 + float_arg_count);
- stack_offset += sizeof(sljit_f64);
- arg_count++;
+ offset += sizeof(sljit_f32);
float_arg_count++;
break;
default:
- offsets[arg_count] = (sljit_u8)stack_offset;
- stack_offset += sizeof(sljit_sw);
- arg_count++;
+ offset += sizeof(sljit_sw);
word_arg_count++;
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ offsets_ptr++;
}
- /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
- if (stack_offset > 16)
- FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
+ /* Stack is aligned to 16 bytes. */
+ SLJIT_ASSERT(offset <= 8 * sizeof(sljit_sw));
- types_save = types;
- arg_count_save = arg_count;
+ if (offset > 4 * sizeof(sljit_sw) && (!is_tail_call || offset > compiler->args_size)) {
+ if (is_tail_call) {
+ offset = (offset + sizeof(sljit_sw) + 15) & ~(sljit_uw)0xf;
+ FAIL_IF(emit_stack_frame_release(compiler, (sljit_s32)offset, &prev_ins));
+ *extra_space = offset;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-16), DR(SLJIT_SP)));
+ *extra_space = 16;
+ }
+ } else {
+ if (is_tail_call)
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &prev_ins));
+ *extra_space = 0;
+ }
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- arg_count--;
- if (offsets[arg_count] < 254)
- ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
- float_arg_count--;
- break;
- case SLJIT_ARG_TYPE_F64:
- arg_count--;
- if (offsets[arg_count] < 254)
- ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(offsets[arg_count]);
- float_arg_count--;
- break;
- default:
- if (offsets[arg_count - 1] >= 16)
- ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(offsets[arg_count - 1]);
- else if (arg_count != word_arg_count)
- ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (offsets[arg_count - 1] >> 2));
- else if (arg_count == 1)
- ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
+ --offsets_ptr;
- arg_count--;
- word_arg_count--;
- break;
- }
-
- if (ins != NOP) {
- if (prev_ins != NOP)
- FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
- prev_ins = ins;
- ins = NOP;
- }
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (*offsets_ptr < 4 * sizeof (sljit_sw)) {
+ if (prev_ins != NOP)
+ FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
- types >>= SLJIT_DEF_SHIFT;
- }
+ /* Must be preceded by at least one other argument,
+ * and its starting offset must be 8 because of alignment. */
+ SLJIT_ASSERT((*offsets_ptr >> 2) == 2);
- types = types_save;
- arg_count = arg_count_save;
+ prev_ins = MFC1 | TA(6) | FS(float_arg_count) | (1 << 11);
+ ins = MFC1 | TA(7) | FS(float_arg_count);
+ } else if (*offsets_ptr < 254)
+ ins = SDC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
+ else if (*offsets_ptr == 254)
+ ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
- while (types) {
- switch (types & SLJIT_DEF_MASK) {
+ float_arg_count--;
+ break;
case SLJIT_ARG_TYPE_F32:
- arg_count--;
- if (offsets[arg_count] == 254)
+ if (*offsets_ptr < 4 * sizeof (sljit_sw))
+ ins = MFC1 | TA(4 + (*offsets_ptr >> 2)) | FS(float_arg_count);
+ else if (*offsets_ptr < 254)
+ ins = SWC1 | S(SLJIT_SP) | FT(float_arg_count) | IMM(*offsets_ptr);
+ else if (*offsets_ptr == 254)
ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
- else if (offsets[arg_count] < 16)
- ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
- break;
- case SLJIT_ARG_TYPE_F64:
- arg_count--;
- if (offsets[arg_count] == 254)
- ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
- else if (offsets[arg_count] < 16) {
- if (prev_ins != NOP)
- FAIL_IF(push_inst(compiler, prev_ins, MOVABLE_INS));
- prev_ins = LW | S(SLJIT_SP) | TA(4 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count]);
- ins = LW | S(SLJIT_SP) | TA(5 + (offsets[arg_count] >> 2)) | IMM(offsets[arg_count] + sizeof(sljit_sw));
- }
+
+ float_arg_count--;
break;
default:
- arg_count--;
+ if (*offsets_ptr >= 4 * sizeof (sljit_sw))
+ ins = SW | S(SLJIT_SP) | T(word_arg_count) | IMM(*offsets_ptr);
+ else if ((*offsets_ptr >> 2) != word_arg_count - 1)
+ ins = ADDU | S(word_arg_count) | TA(0) | DA(4 + (*offsets_ptr >> 2));
+ else if (*offsets_ptr == 0)
+ ins = ADDU | S(SLJIT_R0) | TA(0) | DA(4);
+
+ word_arg_count--;
break;
}
@@ -573,7 +561,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
ins = NOP;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
*ins_ptr = prev_ins;
@@ -581,41 +569,11 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
return SLJIT_SUCCESS;
}
-static sljit_s32 post_call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types)
-{
- sljit_s32 stack_offset = 0;
-
- arg_types >>= SLJIT_DEF_SHIFT;
-
- while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- stack_offset += sizeof(sljit_f32);
- break;
- case SLJIT_ARG_TYPE_F64:
- if (stack_offset & 0x7)
- stack_offset += sizeof(sljit_sw);
- stack_offset += sizeof(sljit_f64);
- break;
- default:
- stack_offset += sizeof(sljit_sw);
- break;
- }
-
- arg_types >>= SLJIT_DEF_SHIFT;
- }
-
- /* Stack is aligned to 16 bytes, max two doubles can be placed on the stack. */
- if (stack_offset > 16)
- return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(16), DR(SLJIT_SP));
-
- return SLJIT_SUCCESS;
-}
-
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
struct sljit_jump *jump;
+ sljit_u32 extra_space = (sljit_u32)type;
sljit_ins ins;
CHECK_ERROR_PTR();
@@ -624,21 +582,34 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
- type &= 0xff;
- PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
SLJIT_ASSERT(DR(PIC_ADDR_REG) == 25 && PIC_ADDR_REG == TMP_REG2);
PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
- jump->flags |= IS_JAL | IS_CALL;
- PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0) {
+ jump->flags |= IS_JAL | IS_CALL;
+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ } else
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
- PTR_FAIL_IF(post_call_with_args(compiler, arg_types));
+ if (extra_space == 0)
+ return jump;
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP)));
return jump;
}
@@ -646,6 +617,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
+ sljit_u32 extra_space = (sljit_u32)type;
sljit_ins ins;
CHECK_ERROR();
@@ -662,10 +634,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
}
- FAIL_IF(call_with_args(compiler, arg_types, &ins));
+ FAIL_IF(call_with_args(compiler, arg_types, &ins, &extra_space));
/* Register input. */
- FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ if (!(type & SLJIT_CALL_RETURN) || extra_space > 0)
+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
- return post_call_with_args(compiler, arg_types);
+
+ if (extra_space == 0)
+ return SLJIT_SUCCESS;
+
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, RETURN_ADDR_REG,
+ SLJIT_MEM1(SLJIT_SP), (sljit_sw)(extra_space - sizeof(sljit_sw))));
+
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+
+ return push_inst(compiler, ADDIU | S(SLJIT_SP) | T(SLJIT_SP) | IMM(extra_space),
+ (type & SLJIT_CALL_RETURN) ? UNMOVABLE_INS : DR(SLJIT_SP));
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
index 1f22e49ed9..c2b3d839c2 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_64.c
@@ -46,9 +46,9 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
}
/* Zero extended number. */
- uimm = imm;
+ uimm = (sljit_uw)imm;
if (imm < 0) {
- uimm = ~imm;
+ uimm = ~(sljit_uw)imm;
inv = 1;
}
@@ -119,7 +119,7 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
}
#define SELECT_OP(a, b) \
- (!(op & SLJIT_I32_OP) ? a : b)
+ (!(op & SLJIT_32) ? a : b)
#define EMIT_LOGICAL(op_imm, op_norm) \
if (flags & SRC2_IMM) { \
@@ -138,19 +138,19 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst_a
#define EMIT_SHIFT(op_dimm, op_dimm32, op_imm, op_dv, op_v) \
if (flags & SRC2_IMM) { \
if (src2 >= 32) { \
- SLJIT_ASSERT(!(op & SLJIT_I32_OP)); \
+ SLJIT_ASSERT(!(op & SLJIT_32)); \
ins = op_dimm32; \
src2 -= 32; \
} \
else \
- ins = (op & SLJIT_I32_OP) ? op_imm : op_dimm; \
+ ins = (op & SLJIT_32) ? op_imm : op_dimm; \
if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, ins | T(src1) | DA(EQUAL_FLAG) | SH_IMM(src2), EQUAL_FLAG)); \
if (!(flags & UNUSED_DEST)) \
FAIL_IF(push_inst(compiler, ins | T(src1) | D(dst) | SH_IMM(src2), DR(dst))); \
} \
else { \
- ins = (op & SLJIT_I32_OP) ? op_v : op_dv; \
+ ins = (op & SLJIT_32) ? op_v : op_dv; \
if (op & SLJIT_SET_Z) \
FAIL_IF(push_inst(compiler, ins | S(src2) | T(src1) | DA(EQUAL_FLAG), EQUAL_FLAG)); \
if (!(flags & UNUSED_DEST)) \
@@ -165,50 +165,71 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
- case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (dst != src2)
return push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(dst), DR(dst));
return SLJIT_SUCCESS;
case SLJIT_MOV_U8:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
case SLJIT_MOV_S8:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
- if (op == SLJIT_MOV_S8) {
- FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
- return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
- }
- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xff), DR(dst));
- }
- else {
- SLJIT_ASSERT(dst == src2);
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ if (op & SLJIT_32)
+ return push_inst(compiler, SEB | T(src2) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 1 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(24), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(24), DR(dst));
}
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE))
+ return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
+
case SLJIT_MOV_S16:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
- if (op == SLJIT_MOV_S16) {
- FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
- return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
- }
- return push_inst(compiler, ANDI | S(src2) | T(dst) | IMM(0xffff), DR(dst));
- }
- else {
- SLJIT_ASSERT(dst == src2);
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
+ if (op & SLJIT_32)
+ return push_inst(compiler, SEH | T(src2) | D(dst), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 1 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(16), DR(dst)));
+ return push_inst(compiler, DSRA32 | T(dst) | D(dst) | SH_IMM(16), DR(dst));
}
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_MOV_U32:
- SLJIT_ASSERT(!(op & SLJIT_I32_OP));
- FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
- return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 2)
+ if (dst == src2)
+ return push_inst(compiler, DINSU | T(src2) | SA(0) | (31 << 11) | (0 << 11), DR(dst));
+#endif /* SLJIT_MIPS_REV >= 2 */
+ FAIL_IF(push_inst(compiler, DSLL32 | T(src2) | D(dst) | SH_IMM(0), DR(dst)));
+ return push_inst(compiler, DSRL32 | T(dst) | D(dst) | SH_IMM(0), DR(dst));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
case SLJIT_MOV_S32:
- SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
- return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
+ SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM) && !(op & SLJIT_32));
+ if ((flags & (REG_DEST | REG2_SOURCE)) == (REG_DEST | REG2_SOURCE)) {
+ return push_inst(compiler, SLL | T(src2) | D(dst) | SH_IMM(0), DR(dst));
+ }
+ SLJIT_ASSERT(dst == src2);
+ return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
@@ -234,7 +255,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SELECT_OP(DADDU, ADDU) | S(src2) | TA(0) | D(TMP_REG1), DR(TMP_REG1)));
/* Check zero. */
FAIL_IF(push_inst(compiler, BEQ | S(TMP_REG1) | TA(0) | IMM(5), UNMOVABLE_INS));
- FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_I32_OP) ? 32 : 64), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, ORI | SA(0) | T(dst) | IMM((op & SLJIT_32) ? 32 : 64), UNMOVABLE_INS));
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | SA(0) | T(dst) | IMM(-1), DR(dst)));
/* Loop for searching the highest bit. */
FAIL_IF(push_inst(compiler, SELECT_OP(DADDIU, ADDIU) | S(dst) | T(dst) | IMM(1), DR(dst)));
@@ -462,7 +483,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
return push_inst(compiler, SELECT_OP(DMUL, MUL) | S(src1) | T(src2) | D(dst), DR(dst));
#elif (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 1)
- if (op & SLJIT_I32_OP)
+ if (op & SLJIT_32)
return push_inst(compiler, MUL | S(src1) | T(src2) | D(dst), DR(dst));
FAIL_IF(push_inst(compiler, DMULT | S(src1) | T(src2), MOVABLE_INS));
return push_inst(compiler, MFLO | D(dst), DR(dst));
@@ -528,10 +549,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 0);
- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
- inst[5] = (inst[5] & 0xffff0000) | (new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000) | ((sljit_ins)(new_target >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000) | ((sljit_ins)(new_target >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000) | ((sljit_ins)(new_target >> 16) & 0xffff);
+ inst[5] = (inst[5] & 0xffff0000) | ((sljit_ins)new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 6, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 6);
@@ -539,7 +560,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_ins *ins_ptr)
@@ -548,19 +569,19 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
sljit_s32 word_arg_count = 0;
sljit_s32 float_arg_count = 0;
sljit_s32 types = 0;
- sljit_ins prev_ins = NOP;
+ sljit_ins prev_ins = *ins_ptr;
sljit_ins ins = NOP;
SLJIT_ASSERT(reg_map[TMP_REG1] == 4 && freg_map[TMP_FREG1] == 12);
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
arg_count++;
float_arg_count++;
break;
@@ -570,24 +591,24 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
if (arg_count != float_arg_count)
- ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
+ ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
- ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
+ ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
arg_count--;
float_arg_count--;
break;
- case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
if (arg_count != float_arg_count)
- ins = MOV_S | FMT_D | FS(float_arg_count) | FD(arg_count);
+ ins = MOV_S | FMT_S | FS(float_arg_count) | FD(arg_count);
else if (arg_count == 1)
- ins = MOV_S | FMT_D | FS(SLJIT_FR0) | FD(TMP_FREG1);
+ ins = MOV_S | FMT_S | FS(SLJIT_FR0) | FD(TMP_FREG1);
arg_count--;
float_arg_count--;
break;
@@ -608,7 +629,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
ins = NOP;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
*ins_ptr = prev_ins;
@@ -620,7 +641,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
sljit_s32 arg_types)
{
struct sljit_jump *jump;
- sljit_ins ins;
+ sljit_ins ins = NOP;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
@@ -628,7 +649,9 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
- type &= 0xff;
+
+ if (type & SLJIT_CALL_RETURN)
+ PTR_FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
PTR_FAIL_IF(call_with_args(compiler, arg_types, &ins));
@@ -636,8 +659,12 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
PTR_FAIL_IF(emit_const(compiler, PIC_ADDR_REG, 0));
- jump->flags |= IS_JAL | IS_CALL;
- PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ if (!(type & SLJIT_CALL_RETURN)) {
+ jump->flags |= IS_JAL | IS_CALL;
+ PTR_FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ } else
+ PTR_FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
+
jump->addr = compiler->size;
PTR_FAIL_IF(push_inst(compiler, ins, UNMOVABLE_INS));
@@ -648,7 +675,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
- sljit_ins ins;
+ sljit_ins ins = NOP;
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
@@ -664,9 +691,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
FAIL_IF(emit_op_mem(compiler, WORD_DATA | LOAD_DATA, DR(PIC_ADDR_REG), src, srcw));
}
+ if (type & SLJIT_CALL_RETURN)
+ FAIL_IF(emit_stack_frame_release(compiler, 0, &ins));
+
FAIL_IF(call_with_args(compiler, arg_types, &ins));
/* Register input. */
- FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ if (!(type & SLJIT_CALL_RETURN))
+ FAIL_IF(push_inst(compiler, JALR | S(PIC_ADDR_REG) | DA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, JR | S(PIC_ADDR_REG), UNMOVABLE_INS));
return push_inst(compiler, ins, UNMOVABLE_INS);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
index fd747695a7..be5cb22a23 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeMIPS_common.c
@@ -86,13 +86,13 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 5] = {
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
- 0, 0, 14, 2, 4, 6, 8, 12, 10, 16
+ 0, 0, 14, 2, 4, 6, 8, 18, 30, 28, 26, 24, 22, 20, 12, 10, 16
};
#else
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
- 0, 0, 13, 14, 15, 16, 17, 12, 18, 10
+ 0, 0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 31, 30, 29, 28, 27, 26, 25, 24, 12, 11, 10
};
#endif
@@ -101,23 +101,23 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
/* Instrucion forms */
/* --------------------------------------------------------------------- */
-#define S(s) (reg_map[s] << 21)
-#define T(t) (reg_map[t] << 16)
-#define D(d) (reg_map[d] << 11)
-#define FT(t) (freg_map[t] << 16)
-#define FS(s) (freg_map[s] << 11)
-#define FD(d) (freg_map[d] << 6)
+#define S(s) ((sljit_ins)reg_map[s] << 21)
+#define T(t) ((sljit_ins)reg_map[t] << 16)
+#define D(d) ((sljit_ins)reg_map[d] << 11)
+#define FT(t) ((sljit_ins)freg_map[t] << 16)
+#define FS(s) ((sljit_ins)freg_map[s] << 11)
+#define FD(d) ((sljit_ins)freg_map[d] << 6)
/* Absolute registers. */
-#define SA(s) ((s) << 21)
-#define TA(t) ((t) << 16)
-#define DA(d) ((d) << 11)
-#define IMM(imm) ((imm) & 0xffff)
-#define SH_IMM(imm) ((imm) << 6)
+#define SA(s) ((sljit_ins)(s) << 21)
+#define TA(t) ((sljit_ins)(t) << 16)
+#define DA(d) ((sljit_ins)(d) << 11)
+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
+#define SH_IMM(imm) ((sljit_ins)(imm) << 6)
#define DR(dr) (reg_map[dr])
#define FR(dr) (freg_map[dr])
-#define HI(opcode) ((opcode) << 26)
-#define LO(opcode) (opcode)
+#define HI(opcode) ((sljit_ins)(opcode) << 26)
+#define LO(opcode) ((sljit_ins)(opcode))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
/* CMP.cond.fmt */
/* S = (20 << 21) D = (21 << 21) */
@@ -186,6 +186,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define DMULTU (HI(0) | LO(29))
#endif /* SLJIT_MIPS_REV >= 6 */
#define DIV_S (HI(17) | FMT_S | LO(3))
+#define DINSU (HI(31) | LO(6))
#define DSLL (HI(0) | LO(56))
#define DSLL32 (HI(0) | LO(60))
#define DSLLV (HI(0) | LO(20))
@@ -205,8 +206,10 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define JR (HI(0) | LO(8))
#endif /* SLJIT_MIPS_REV >= 6 */
#define LD (HI(55))
+#define LDC1 (HI(53))
#define LUI (HI(15))
#define LW (HI(35))
+#define LWC1 (HI(49))
#define MFC1 (HI(17))
#if (defined SLJIT_MIPS_REV && SLJIT_MIPS_REV >= 6)
#define MOD (HI(0) | (3 << 6) | LO(26))
@@ -292,7 +295,8 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit
{
sljit_ins *ptr = (sljit_ins*)ensure_buf(compiler, sizeof(sljit_ins));
SLJIT_ASSERT(delay_slot == MOVABLE_INS || delay_slot >= UNMOVABLE_INS
- || delay_slot == ((ins >> 11) & 0x1f) || delay_slot == ((ins >> 16) & 0x1f));
+ || (sljit_ins)delay_slot == ((ins >> 11) & 0x1f)
+ || (sljit_ins)delay_slot == ((ins >> 16) & 0x1f));
FAIL_IF(!ptr);
*ptr = ins;
compiler->size++;
@@ -300,7 +304,7 @@ static sljit_s32 push_inst(struct sljit_compiler *compiler, sljit_ins ins, sljit
return SLJIT_SUCCESS;
}
-static SLJIT_INLINE sljit_ins invert_branch(sljit_s32 flags)
+static SLJIT_INLINE sljit_ins invert_branch(sljit_uw flags)
{
if (flags & IS_BIT26_COND)
return (1 << 26);
@@ -371,7 +375,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
inst[1] = NOP;
return inst + 1;
}
- inst[0] = inst[0] ^ invert_branch(jump->flags);
+ inst[0] ^= invert_branch(jump->flags);
inst[1] = NOP;
jump->addr -= sizeof(sljit_ins);
return inst + 1;
@@ -379,7 +383,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
}
if (jump->flags & IS_COND) {
- if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~0xfffffff)) {
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 2 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
jump->flags |= PATCH_J;
saved_inst = inst[0];
inst[0] = inst[-1];
@@ -388,7 +392,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
inst[2] = NOP;
return inst + 2;
}
- else if ((target_addr & ~0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~0xfffffff)) {
+ else if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + 3 * sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = (inst[0] & 0xffff0000) | 3;
inst[1] = NOP;
@@ -400,7 +404,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
}
else {
/* J instuctions. */
- if ((jump->flags & IS_MOVABLE) && (target_addr & ~0xfffffff) == (jump->addr & ~0xfffffff)) {
+ if ((jump->flags & IS_MOVABLE) && (target_addr & ~(sljit_uw)0xfffffff) == (jump->addr & ~(sljit_uw)0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = inst[-1];
inst[-1] = (jump->flags & IS_JAL) ? JAL : J;
@@ -408,7 +412,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
return inst;
}
- if ((target_addr & ~0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~0xfffffff)) {
+ if ((target_addr & ~(sljit_uw)0xfffffff) == ((jump->addr + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff)) {
jump->flags |= PATCH_J;
inst[0] = (jump->flags & IS_JAL) ? JAL : J;
inst[1] = NOP;
@@ -472,7 +476,7 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
{
sljit_uw addr = put_label->label->addr;
sljit_ins *inst = (sljit_ins *)put_label->addr;
- sljit_s32 reg = *inst;
+ sljit_u32 reg = *inst;
if (put_label->flags == 0) {
SLJIT_ASSERT(addr < 0x80000000l);
@@ -548,7 +552,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* These structures are ordered by their address. */
if (label && label->size == word_count) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
if (jump && jump->addr == word_count) {
@@ -584,7 +588,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
label->addr = (sljit_uw)code_ptr;
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
@@ -601,39 +605,46 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
buf_ptr = (sljit_ins *)jump->addr;
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - ((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins))) >> 2;
+ addr = (sljit_uw)((sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) - sizeof(sljit_ins)) >> 2);
SLJIT_ASSERT((sljit_sw)addr <= SIMM_MAX && (sljit_sw)addr >= SIMM_MIN);
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | (addr & 0xffff);
+ buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((sljit_ins)addr & 0xffff);
break;
}
if (jump->flags & PATCH_J) {
- SLJIT_ASSERT((addr & ~0xfffffff) == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~0xfffffff));
- buf_ptr[0] |= (addr >> 2) & 0x03ffffff;
+ SLJIT_ASSERT((addr & ~(sljit_uw)0xfffffff)
+ == (((sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset) + sizeof(sljit_ins)) & ~(sljit_uw)0xfffffff));
+ buf_ptr[0] |= (sljit_ins)(addr >> 2) & 0x03ffffff;
break;
}
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)addr & 0xffff;
#else
if (jump->flags & PATCH_ABS32) {
SLJIT_ASSERT(addr <= 0x7fffffff);
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)addr & 0xffff;
+ break;
}
- else if (jump->flags & PATCH_ABS48) {
+
+ if (jump->flags & PATCH_ABS48) {
SLJIT_ASSERT(addr <= 0x7fffffffffffl);
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
- }
- else {
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
- buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[5] = (buf_ptr[5] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[3] |= (sljit_ins)addr & 0xffff;
+ break;
}
+
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[5]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;
+ buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[5] |= (sljit_ins)addr & 0xffff;
#endif
} while (0);
jump = jump->next;
@@ -656,7 +667,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -673,7 +684,9 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
{
+#if defined(__GNUC__) && !defined(SLJIT_IS_FPU_AVAILABLE)
sljit_sw fir = 0;
+#endif /* __GNUC__ && !SLJIT_IS_FPU_AVAILABLE */
switch (feature_type) {
case SLJIT_HAS_FPU:
@@ -696,7 +709,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#endif /* SLJIT_MIPS_REV >= 1 */
default:
- return fir;
+ return 0;
}
}
@@ -723,15 +736,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#define CUMULATIVE_OP 0x00080
#define LOGICAL_OP 0x00100
#define IMM_OP 0x00200
-#define SRC2_IMM 0x00400
+#define MOVE_OP 0x00400
+#define SRC2_IMM 0x00800
-#define UNUSED_DEST 0x00800
-#define REG_DEST 0x01000
-#define REG1_SOURCE 0x02000
-#define REG2_SOURCE 0x04000
-#define SLOW_SRC1 0x08000
-#define SLOW_SRC2 0x10000
-#define SLOW_DEST 0x20000
+#define UNUSED_DEST 0x01000
+#define REG_DEST 0x02000
+#define REG1_SOURCE 0x04000
+#define REG2_SOURCE 0x08000
+#define SLOW_SRC1 0x10000
+#define SLOW_SRC2 0x20000
+#define SLOW_DEST 0x40000
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#define STACK_STORE SW
@@ -741,7 +755,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#define STACK_LOAD LD
#endif
-static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw);
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr);
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
#include "sljitNativeMIPS_32.c"
@@ -754,56 +769,195 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
sljit_ins base;
- sljit_s32 args, i, tmp, offs;
+ sljit_s32 i, tmp, offset;
+ sljit_s32 arg_count, word_arg_count, saved_arg_count, float_arg_count;
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- local_size = (local_size + 15) & ~0xf;
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ }
+
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
#else
- local_size = (local_size + 31) & ~0x1f;
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
#endif
compiler->local_size = local_size;
- if (local_size <= SIMM_MAX) {
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ tmp = arg_types >> SLJIT_ARG_SHIFT;
+ arg_count = 0;
+ offset = 0;
+
+ while (tmp) {
+ offset = arg_count;
+ if ((tmp & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64) {
+ if ((arg_count & 0x1) != 0)
+ arg_count++;
+ arg_count++;
+ }
+
+ arg_count++;
+ tmp >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = (sljit_uw)arg_count << 2;
+ offset = (offset >= 4) ? (offset << 2) : 0;
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ offset = 0;
+#endif /* SLJIT_CONFIG_MIPS_32 */
+
+ if (local_size + offset <= -SIMM_MIN) {
/* Frequent case. */
FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(-local_size), DR(SLJIT_SP)));
base = S(SLJIT_SP);
- offs = local_size - (sljit_sw)sizeof(sljit_sw);
- }
- else {
+ offset = local_size - SSIZE_OF(sw);
+ } else {
FAIL_IF(load_immediate(compiler, DR(OTHER_FLAG), local_size));
FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | TA(0) | D(TMP_REG2), DR(TMP_REG2)));
FAIL_IF(push_inst(compiler, SUBU_W | S(SLJIT_SP) | T(OTHER_FLAG) | D(SLJIT_SP), DR(SLJIT_SP)));
base = S(TMP_REG2);
+ offset = -SSIZE_OF(sw);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
local_size = 0;
- offs = -(sljit_sw)sizeof(sljit_sw);
+#endif
}
- FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offs), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | TA(RETURN_ADDR_REG) | IMM(offset), MOVABLE_INS));
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--) {
- offs -= (sljit_s32)(sizeof(sljit_sw));
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
}
for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
- offs -= (sljit_s32)(sizeof(sljit_sw));
- FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offs), MOVABLE_INS));
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | base | T(i) | IMM(offset), MOVABLE_INS));
+ }
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, SDC1 | base | FT(i) | IMM(offset), MOVABLE_INS));
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ arg_count = 0;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+ float_arg_count = 0;
+
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* The first maximum two floating point arguments are passed in floating point
+ registers if no integer argument precedes them. The first 16 byte data is
+ passed in four integer registers, the rest is placed onto the stack.
+ The floating point registers are also part of the first 16 byte data, so
+ their corresponding integer registers are not used when they are present. */
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ if ((arg_count & 0x1) != 0)
+ arg_count++;
+
+ if (word_arg_count == 0 && float_arg_count <= 2) {
+ if (float_arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ } else if (arg_count < 4) {
+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, MTC1 | TA(5 + arg_count) | FS(float_arg_count) | (1 << 11), MOVABLE_INS));
+ } else
+ FAIL_IF(push_inst(compiler, LDC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
+ arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+
+ if (word_arg_count == 0 && float_arg_count <= 2) {
+ if (float_arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ } else if (arg_count < 4)
+ FAIL_IF(push_inst(compiler, MTC1 | TA(4 + arg_count) | FS(float_arg_count), MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, LWC1 | base | FT(float_arg_count) | IMM(local_size + (arg_count << 2)), MOVABLE_INS));
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count != arg_count + 1 || arg_count == 0)
+ tmp = word_arg_count;
+ else
+ break;
+
+ if (arg_count < 4)
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(4 + arg_count) | TA(0) | D(tmp), DR(tmp)));
+ else
+ FAIL_IF(push_inst(compiler, LW | base | T(tmp) | IMM(local_size + (arg_count << 2)), DR(tmp)));
+ break;
+ }
+ arg_count++;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
- args = get_arg_count(arg_types);
+ SLJIT_ASSERT(compiler->args_size == (sljit_uw)arg_count << 2);
+#else /* !SLJIT_CONFIG_MIPS_32 */
+ while (arg_types) {
+ arg_count++;
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ if (arg_count != float_arg_count)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
+ else if (arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_D | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ if (arg_count != float_arg_count)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(arg_count) | FD(float_arg_count), MOVABLE_INS));
+ else if (arg_count == 1)
+ FAIL_IF(push_inst(compiler, MOV_S | FMT_S | FS(TMP_FREG1) | FD(SLJIT_FR0), MOVABLE_INS));
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (word_arg_count != arg_count || word_arg_count <= 1)
+ tmp = word_arg_count;
+ else
+ break;
- if (args >= 1)
- FAIL_IF(push_inst(compiler, ADDU_W | SA(4) | TA(0) | D(SLJIT_S0), DR(SLJIT_S0)));
- if (args >= 2)
- FAIL_IF(push_inst(compiler, ADDU_W | SA(5) | TA(0) | D(SLJIT_S1), DR(SLJIT_S1)));
- if (args >= 3)
- FAIL_IF(push_inst(compiler, ADDU_W | SA(6) | TA(0) | D(SLJIT_S2), DR(SLJIT_S2)));
+ FAIL_IF(push_inst(compiler, ADDU_W | SA(3 + arg_count) | TA(0) | D(tmp), DR(tmp)));
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+#endif /* SLJIT_CONFIG_MIPS_32 */
return SLJIT_SUCCESS;
}
@@ -816,57 +970,110 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- compiler->local_size = (local_size + 15) & ~0xf;
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((local_size & SSIZE_OF(sw)) != 0)
+ local_size += SSIZE_OF(sw);
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ }
+
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
#else
- compiler->local_size = (local_size + 31) & ~0x1f;
+ local_size += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 31) & ~0x1f;
#endif
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler, sljit_s32 frame_size, sljit_ins *ins_ptr)
{
- sljit_s32 local_size, i, tmp, offs;
- sljit_ins base;
+ sljit_s32 local_size, i, tmp, offset;
+ sljit_s32 scratches = compiler->scratches;
+ sljit_s32 saveds = compiler->saveds;
+ sljit_s32 fsaveds = compiler->fsaveds;
+ sljit_s32 fscratches = compiler->fscratches;
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+ local_size = compiler->local_size;
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ tmp = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ if (fsaveds > 0 || fscratches >= SLJIT_FIRST_SAVED_FLOAT_REG) {
+ if ((tmp & SSIZE_OF(sw)) != 0)
+ tmp += SSIZE_OF(sw);
+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ }
+#else
+ tmp += GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+#endif
- local_size = compiler->local_size;
- if (local_size <= SIMM_MAX)
- base = S(SLJIT_SP);
- else {
- FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size));
- FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(TMP_REG1), DR(TMP_REG1)));
- base = S(TMP_REG1);
- local_size = 0;
+ if (local_size <= SIMM_MAX) {
+ if (local_size < frame_size) {
+ FAIL_IF(push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size), DR(SLJIT_SP)));
+ local_size = frame_size;
+ }
+ } else {
+ if (tmp < frame_size)
+ tmp = frame_size;
+
+ FAIL_IF(load_immediate(compiler, DR(TMP_REG1), local_size - tmp));
+ FAIL_IF(push_inst(compiler, ADDU_W | S(SLJIT_SP) | T(TMP_REG1) | D(SLJIT_SP), DR(SLJIT_SP)));
+ local_size = tmp;
}
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | TA(RETURN_ADDR_REG) | IMM(local_size - (sljit_s32)sizeof(sljit_sw)), RETURN_ADDR_REG));
- offs = local_size - (sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
+ SLJIT_ASSERT(local_size >= frame_size);
+
+ offset = local_size - SSIZE_OF(sw);
+ if (frame_size == 0)
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | TA(RETURN_ADDR_REG) | IMM(offset), RETURN_ADDR_REG));
+
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
+ }
- tmp = compiler->scratches;
- for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
- offs += (sljit_s32)(sizeof(sljit_sw));
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(SLJIT_SP) | T(i) | IMM(offset), MOVABLE_INS));
}
- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = tmp; i <= SLJIT_S0; i++) {
- FAIL_IF(push_inst(compiler, STACK_LOAD | base | T(i) | IMM(offs), DR(i)));
- offs += (sljit_s32)(sizeof(sljit_sw));
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ /* This alignment is valid because offset is not used after storing FPU regs. */
+ if ((offset & SSIZE_OF(sw)) != 0)
+ offset -= SSIZE_OF(sw);
+#endif
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
}
- SLJIT_ASSERT(offs == local_size - (sljit_sw)(sizeof(sljit_sw)));
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LDC1 | S(SLJIT_SP) | FT(i) | IMM(offset), MOVABLE_INS));
+ }
- FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
- if (compiler->local_size <= SIMM_MAX)
- return push_inst(compiler, ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(compiler->local_size), UNMOVABLE_INS);
+ if (local_size > frame_size)
+ *ins_ptr = ADDIU_W | S(SLJIT_SP) | T(SLJIT_SP) | IMM(local_size - frame_size);
else
- return push_inst(compiler, ADDU_W | S(TMP_REG1) | TA(0) | D(SLJIT_SP), UNMOVABLE_INS);
+ *ins_ptr = NOP;
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ sljit_ins ins;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ emit_stack_frame_release(compiler, 0, &ins);
+
+ FAIL_IF(push_inst(compiler, JR | SA(RETURN_ADDR_REG), UNMOVABLE_INS));
+ return push_inst(compiler, ins, UNMOVABLE_INS);
}
#undef STACK_STORE
@@ -1041,7 +1248,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | SA(tmp_ar) | TA(reg_ar), delay_slot);
}
-static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
+static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg_ar, sljit_s32 arg, sljit_sw argw)
{
sljit_s32 tmp_ar, base, delay_slot;
@@ -1104,14 +1311,14 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
compiler->cache_argw = 0;
}
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED)) {
+ if (dst == TMP_REG2) {
SLJIT_ASSERT(HAS_FLAGS(op));
flags |= UNUSED_DEST;
}
else if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
+ if (flags & MOVE_OP)
sugg_src2_r = dst_r;
}
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, DR(TMP_REG1), dst, dstw))
@@ -1165,8 +1372,8 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
- if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
- dst_r = src2_r;
+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
+ dst_r = (sljit_s32)src2_r;
}
else if (src2 & SLJIT_IMM) {
if (!(flags & SRC2_IMM)) {
@@ -1176,8 +1383,12 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
}
else {
src2_r = 0;
- if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
- dst_r = 0;
+ if (flags & MOVE_OP) {
+ if (dst & SLJIT_MEM)
+ dst_r = 0;
+ else
+ op = SLJIT_MOV;
+ }
}
}
}
@@ -1221,7 +1432,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- sljit_s32 int_op = op & SLJIT_I32_OP;
+ sljit_s32 int_op = op & SLJIT_32;
#endif
CHECK_ERROR();
@@ -1326,11 +1537,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define flags 0
-#else
sljit_s32 flags = 0;
-#endif
CHECK_ERROR();
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
@@ -1338,58 +1545,50 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src, srcw);
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if ((op & SLJIT_I32_OP) && GET_OPCODE(op) >= SLJIT_NOT)
- flags |= INT_DATA | SIGNED_DATA;
+ if (op & SLJIT_32)
+ flags = INT_DATA | SIGNED_DATA;
#endif
switch (GET_OPCODE(op)) {
case SLJIT_MOV:
+#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
+ case SLJIT_MOV_U32:
+ case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
+#endif
case SLJIT_MOV_P:
- return emit_op(compiler, SLJIT_MOV, WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_MOV, WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
+#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
case SLJIT_MOV_U32:
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
-#else
- return emit_op(compiler, SLJIT_MOV_U32, INT_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
-#endif
+ return emit_op(compiler, SLJIT_MOV_U32, INT_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u32)srcw : srcw);
case SLJIT_MOV_S32:
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
- return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
-#else
- return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
+ case SLJIT_MOV32:
+ return emit_op(compiler, SLJIT_MOV_S32, INT_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s32)srcw : srcw);
#endif
case SLJIT_MOV_U8:
- return emit_op(compiler, SLJIT_MOV_U8, BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+ return emit_op(compiler, op, BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
case SLJIT_MOV_S8:
- return emit_op(compiler, SLJIT_MOV_S8, BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+ return emit_op(compiler, op, BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
case SLJIT_MOV_U16:
- return emit_op(compiler, SLJIT_MOV_U16, HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+ return emit_op(compiler, op, HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
case SLJIT_MOV_S16:
- return emit_op(compiler, SLJIT_MOV_S16, HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+ return emit_op(compiler, op, HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
case SLJIT_NOT:
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
- case SLJIT_NEG:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
-
case SLJIT_CLZ:
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
}
SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
-
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# undef flags
-#endif
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1397,23 +1596,16 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define flags 0
-#else
sljit_s32 flags = 0;
-#endif
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (op & SLJIT_I32_OP) {
+ if (op & SLJIT_32) {
flags |= INT_DATA | SIGNED_DATA;
if (src1 & SLJIT_IMM)
src1w = (sljit_s32)src1w;
@@ -1425,12 +1617,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
case SLJIT_ADDC:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
return emit_op(compiler, op, flags | CUMULATIVE_OP | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
case SLJIT_SUBC:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
return emit_op(compiler, op, flags | IMM_OP, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
@@ -1450,7 +1642,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
src2w &= 0x1f;
#else
if (src2 & SLJIT_IMM) {
- if (op & SLJIT_I32_OP)
+ if (op & SLJIT_32)
src2w &= 0x1f;
else
src2w &= 0x3f;
@@ -1461,10 +1653,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
SLJIT_UNREACHABLE();
return SLJIT_SUCCESS;
+}
-#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# undef flags
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
#endif
+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1512,7 +1714,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1524,17 +1726,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
-#define FMT(op) (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) << (21 - 8))
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 7))
+#define FMT(op) ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) << (21 - 8))
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define flags 0
+# define flags (sljit_u32)0
#else
- sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64) << 21;
+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)) << 21;
#endif
if (src & SLJIT_MEM) {
@@ -1560,9 +1762,9 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
-# define flags 0
+# define flags (sljit_u32)0
#else
- sljit_s32 flags = (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW) << 21;
+ sljit_u32 flags = ((sljit_u32)(GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)) << 21;
#endif
sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -1582,7 +1784,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
FAIL_IF(push_inst(compiler, MTC1 | flags | T(TMP_REG1) | FS(TMP_FREG1), MOVABLE_INS));
}
- FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | (((op & SLJIT_F32_OP) ^ SLJIT_F32_OP) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, CVT_S_S | flags | (4 << 21) | ((((sljit_ins)op & SLJIT_32) ^ SLJIT_32) >> 8) | FS(TMP_FREG1) | FD(dst_r), MOVABLE_INS));
if (dst & SLJIT_MEM)
return emit_op_mem2(compiler, FLOAT_DATA(op), FR(TMP_FREG1), dst, dstw, 0, 0);
@@ -1640,11 +1842,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -1669,8 +1871,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
FAIL_IF(push_inst(compiler, ABS_S | FMT(op) | FS(src) | FD(dst_r), MOVABLE_INS));
break;
case SLJIT_CONV_F64_FROM_F32:
- FAIL_IF(push_inst(compiler, CVT_S_S | ((op & SLJIT_F32_OP) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
- op ^= SLJIT_F32_OP;
+ FAIL_IF(push_inst(compiler, CVT_S_S | (sljit_ins)((op & SLJIT_32) ? 1 : (1 << 21)) | FS(src) | FD(dst_r), MOVABLE_INS));
+ op ^= SLJIT_32;
break;
}
@@ -1841,7 +2043,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
{
struct sljit_jump *jump;
sljit_ins inst;
- sljit_s32 flags = 0;
+ sljit_u32 flags = 0;
sljit_s32 delay_check = UNMOVABLE_INS;
CHECK_ERROR_PTR();
@@ -1864,6 +2066,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
case SLJIT_SIG_LESS:
case SLJIT_SIG_GREATER:
case SLJIT_OVERFLOW:
+ case SLJIT_CARRY:
BR_Z(OTHER_FLAG);
break;
case SLJIT_GREATER_EQUAL:
@@ -1871,6 +2074,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
case SLJIT_SIG_GREATER_EQUAL:
case SLJIT_SIG_LESS_EQUAL:
case SLJIT_NOT_OVERFLOW:
+ case SLJIT_NOT_CARRY:
BR_NZ(OTHER_FLAG);
break;
case SLJIT_NOT_EQUAL_F64:
@@ -1947,7 +2151,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_cmp(struct sljit_compiler
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- flags = ((type & SLJIT_I32_OP) ? INT_DATA : WORD_DATA) | LOAD_DATA;
+ flags = ((type & SLJIT_32) ? INT_DATA : WORD_DATA) | LOAD_DATA;
if (src1 & SLJIT_MEM) {
PTR_FAIL_IF(emit_op_mem2(compiler, flags, DR(TMP_REG1), src1, src1w, src2, src2w));
src1 = TMP_REG1;
@@ -2074,7 +2278,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR | ((type >= SLJIT_FAST_CALL) ? IS_JAL : 0));
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
if (compiler->delay_slot != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
@@ -2103,7 +2307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
sljit_s32 mem_type = WORD_DATA;
#else
- sljit_s32 mem_type = (op & SLJIT_I32_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
+ sljit_s32 mem_type = ((op & SLJIT_32) || op == SLJIT_MOV32) ? (INT_DATA | SIGNED_DATA) : WORD_DATA;
#endif
CHECK_ERROR();
@@ -2111,10 +2315,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
ADJUST_LOCAL_OFFSET(dst, dstw);
op = GET_OPCODE(op);
-#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (op == SLJIT_MOV_S32)
- mem_type = INT_DATA | SIGNED_DATA;
-#endif
dst_ar = DR((op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2);
compiler->cache_arg = 0;
@@ -2131,7 +2331,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
break;
case SLJIT_OVERFLOW:
case SLJIT_NOT_OVERFLOW:
- if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB) {
+ if (compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) {
src_ar = OTHER_FLAG;
break;
}
@@ -2142,6 +2342,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
case SLJIT_GREATER_F64:
case SLJIT_LESS_EQUAL_F64:
type ^= 0x1; /* Flip type bit for the XORI below. */
+ /* fallthrough */
case SLJIT_EQUAL_F64:
case SLJIT_NOT_EQUAL_F64:
case SLJIT_LESS_F64:
@@ -2203,7 +2404,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
#if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64)
- if (dst_reg & SLJIT_I32_OP)
+ if (dst_reg & SLJIT_32)
srcw = (sljit_s32)srcw;
#endif
FAIL_IF(load_immediate(compiler, DR(TMP_REG1), srcw));
@@ -2211,7 +2412,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
srcw = 0;
}
- dst_reg &= ~SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_32;
switch (type & 0xff) {
case SLJIT_EQUAL:
@@ -2298,7 +2499,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32)
PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
#else
- PTR_FAIL_IF(push_inst(compiler, dst_r, UNMOVABLE_INS));
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r, UNMOVABLE_INS));
compiler->size += 5;
#endif
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
index 6ddb5508ec..95fe6bbe0e 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_32.c
@@ -86,11 +86,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
- case SLJIT_NEG:
- SLJIT_ASSERT(src1 == TMP_REG1);
- /* Setting XER SO is not enough, CR SO is also needed. */
- return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
-
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
return push_inst(compiler, CNTLZW | S(src2) | A(dst));
@@ -158,7 +153,9 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & ALT_FORM3) {
/* Setting XER SO is not enough, CR SO is also needed. */
- return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
}
if (flags & ALT_FORM4) {
@@ -167,11 +164,17 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
- if (!(flags & ALT_SET_FLAGS))
+ if (!(flags & ALT_SET_FLAGS)) {
+ SLJIT_ASSERT(src1 != TMP_ZERO);
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
if (flags & ALT_FORM5)
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
- return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
+
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
case SLJIT_SUBC:
return push_inst(compiler, SUBFE | D(dst) | A(src2) | B(src1));
@@ -277,5 +280,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
index cbdf2dd8a2..d104f6d75f 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_64.c
@@ -57,20 +57,20 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
}
/* Count leading zeroes. */
- tmp = (imm >= 0) ? imm : ~imm;
+ tmp = (sljit_uw)((imm >= 0) ? imm : ~imm);
ASM_SLJIT_CLZ(tmp, shift);
SLJIT_ASSERT(shift > 0);
shift--;
- tmp = (imm << shift);
+ tmp = ((sljit_uw)imm << shift);
if ((tmp & ~0xffff000000000000ul) == 0) {
- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
shift += 15;
return PUSH_RLDICR(reg, shift);
}
if ((tmp & ~0xffffffff00000000ul) == 0) {
- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(tmp >> 48)));
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp >> 32)));
shift += 31;
return PUSH_RLDICR(reg, shift);
@@ -78,18 +78,18 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
/* Cut out the 16 bit from immediate. */
shift += 15;
- tmp2 = imm & ((1ul << (63 - shift)) - 1);
+ tmp2 = (sljit_uw)imm & (((sljit_uw)1 << (63 - shift)) - 1);
if (tmp2 <= 0xffff) {
- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
FAIL_IF(PUSH_RLDICR(reg, shift));
- return push_inst(compiler, ORI | S(reg) | A(reg) | tmp2);
+ return push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)tmp2);
}
if (tmp2 <= 0xffffffff) {
FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
FAIL_IF(PUSH_RLDICR(reg, shift));
- FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (tmp2 >> 16)));
+ FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 16)));
return (imm & 0xffff) ? push_inst(compiler, ORI | S(reg) | A(reg) | IMM(tmp2)) : SLJIT_SUCCESS;
}
@@ -97,16 +97,16 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 reg,
tmp2 <<= shift2;
if ((tmp2 & ~0xffff000000000000ul) == 0) {
- FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | IMM(tmp >> 48)));
+ FAIL_IF(push_inst(compiler, ADDI | D(reg) | A(0) | (sljit_ins)(tmp >> 48)));
shift2 += 15;
shift += (63 - shift2);
FAIL_IF(PUSH_RLDICR(reg, shift));
- FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (tmp2 >> 48)));
+ FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | (sljit_ins)(tmp2 >> 48)));
return PUSH_RLDICR(reg, shift2);
}
/* The general version. */
- FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | IMM(imm >> 48)));
+ FAIL_IF(push_inst(compiler, ADDIS | D(reg) | A(0) | (sljit_ins)((sljit_uw)imm >> 48)));
FAIL_IF(push_inst(compiler, ORI | S(reg) | A(reg) | IMM(imm >> 32)));
FAIL_IF(PUSH_RLDICR(reg, 31));
FAIL_IF(push_inst(compiler, ORIS | S(reg) | A(reg) | IMM(imm >> 16)));
@@ -199,19 +199,6 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
UN_EXTS();
return push_inst(compiler, NOR | RC(flags) | S(src2) | A(dst) | B(src2));
- case SLJIT_NEG:
- SLJIT_ASSERT(src1 == TMP_REG1);
-
- if ((flags & (ALT_FORM1 | ALT_SIGN_EXT)) == (ALT_FORM1 | ALT_SIGN_EXT)) {
- FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
- FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(TMP_REG2)));
- return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
- }
-
- UN_EXTS();
- /* Setting XER SO is not enough, CR SO is also needed. */
- return push_inst(compiler, NEG | OE((flags & ALT_FORM1) ? ALT_SET_FLAGS : 0) | RC(flags) | D(dst) | A(src2));
-
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1);
if (flags & ALT_FORM1)
@@ -299,13 +286,22 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
if (flags & ALT_FORM3) {
if (flags & ALT_SIGN_EXT) {
- FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
- src1 = TMP_REG1;
- FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
- src2 = TMP_REG2;
+ if (src1 != TMP_ZERO) {
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, src1, 32, 31, 1)));
+ src1 = TMP_REG1;
+ }
+ if (src2 != TMP_ZERO) {
+ FAIL_IF(push_inst(compiler, RLDI(TMP_REG2, src2, 32, 31, 1)));
+ src2 = TMP_REG2;
+ }
}
+
/* Setting XER SO is not enough, CR SO is also needed. */
- FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
+ if (src1 != TMP_ZERO)
+ FAIL_IF(push_inst(compiler, SUBF | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1)));
+ else
+ FAIL_IF(push_inst(compiler, NEG | OE(ALT_SET_FLAGS) | RC(ALT_SET_FLAGS) | D(dst) | A(src2)));
+
if (flags & ALT_SIGN_EXT)
return push_inst(compiler, RLDI(dst, dst, 32, 32, 0));
return SLJIT_SUCCESS;
@@ -317,12 +313,18 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SUBFIC | D(dst) | A(src1) | compiler->imm);
}
- if (!(flags & ALT_SET_FLAGS))
+ if (!(flags & ALT_SET_FLAGS)) {
+ SLJIT_ASSERT(src1 != TMP_ZERO);
return push_inst(compiler, SUBF | D(dst) | A(src2) | B(src1));
+ }
+
BIN_EXTS();
if (flags & ALT_FORM5)
return push_inst(compiler, SUBFC | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
- return push_inst(compiler, SUBF | RC(flags) | D(dst) | A(src2) | B(src1));
+
+ if (src1 != TMP_ZERO)
+ return push_inst(compiler, SUBF | RC(ALT_SET_FLAGS) | D(dst) | A(src2) | B(src1));
+ return push_inst(compiler, NEG | RC(ALT_SET_FLAGS) | D(dst) | A(src2));
case SLJIT_SUBC:
BIN_EXTS();
@@ -432,14 +434,14 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
if (src)
reg = *src & REG_MASK;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
arg_count++;
break;
default:
@@ -453,13 +455,13 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
arg_count--;
break;
default:
@@ -471,7 +473,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -492,10 +494,10 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UNUSED_ARG(executable_offset);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 0);
- inst[0] = (inst[0] & 0xffff0000) | ((new_target >> 48) & 0xffff);
- inst[1] = (inst[1] & 0xffff0000) | ((new_target >> 32) & 0xffff);
- inst[3] = (inst[3] & 0xffff0000) | ((new_target >> 16) & 0xffff);
- inst[4] = (inst[4] & 0xffff0000) | (new_target & 0xffff);
+ inst[0] = (inst[0] & 0xffff0000u) | ((sljit_ins)(new_target >> 48) & 0xffff);
+ inst[1] = (inst[1] & 0xffff0000u) | ((sljit_ins)(new_target >> 32) & 0xffff);
+ inst[3] = (inst[3] & 0xffff0000u) | ((sljit_ins)(new_target >> 16) & 0xffff);
+ inst[4] = (inst[4] & 0xffff0000u) | ((sljit_ins)new_target & 0xffff);
SLJIT_UPDATE_WX_FLAGS(inst, inst + 5, 1);
inst = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(inst, executable_offset);
SLJIT_CACHE_FLUSH(inst, inst + 5);
@@ -503,5 +505,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
index 2174dbb07b..8bfdc69522 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativePPC_common.c
@@ -109,32 +109,32 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 7] = {
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 1, 2, 3, 4, 5, 6, 0, 7
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 0, 13
};
/* --------------------------------------------------------------------- */
/* Instrucion forms */
/* --------------------------------------------------------------------- */
-#define D(d) (reg_map[d] << 21)
-#define S(s) (reg_map[s] << 21)
-#define A(a) (reg_map[a] << 16)
-#define B(b) (reg_map[b] << 11)
-#define C(c) (reg_map[c] << 6)
-#define FD(fd) (freg_map[fd] << 21)
-#define FS(fs) (freg_map[fs] << 21)
-#define FA(fa) (freg_map[fa] << 16)
-#define FB(fb) (freg_map[fb] << 11)
-#define FC(fc) (freg_map[fc] << 6)
-#define IMM(imm) ((imm) & 0xffff)
-#define CRD(d) ((d) << 21)
+#define D(d) ((sljit_ins)reg_map[d] << 21)
+#define S(s) ((sljit_ins)reg_map[s] << 21)
+#define A(a) ((sljit_ins)reg_map[a] << 16)
+#define B(b) ((sljit_ins)reg_map[b] << 11)
+#define C(c) ((sljit_ins)reg_map[c] << 6)
+#define FD(fd) ((sljit_ins)freg_map[fd] << 21)
+#define FS(fs) ((sljit_ins)freg_map[fs] << 21)
+#define FA(fa) ((sljit_ins)freg_map[fa] << 16)
+#define FB(fb) ((sljit_ins)freg_map[fb] << 11)
+#define FC(fc) ((sljit_ins)freg_map[fc] << 6)
+#define IMM(imm) ((sljit_ins)(imm) & 0xffff)
+#define CRD(d) ((sljit_ins)(d) << 21)
/* Instruction bit sections.
OE and Rc flag (see ALT_SET_FLAGS). */
#define OE(flags) ((flags) & ALT_SET_FLAGS)
/* Rc flag (see ALT_SET_FLAGS). */
#define RC(flags) (((flags) & ALT_SET_FLAGS) >> 10)
-#define HI(opcode) ((opcode) << 26)
-#define LO(opcode) ((opcode) << 1)
+#define HI(opcode) ((sljit_ins)(opcode) << 26)
+#define LO(opcode) ((sljit_ins)(opcode) << 1)
#define ADD (HI(31) | LO(266))
#define ADDC (HI(31) | LO(10))
@@ -182,6 +182,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define FSUB (HI(63) | LO(20))
#define FSUBS (HI(59) | LO(20))
#define LD (HI(58) | 0)
+#define LFD (HI(50))
#define LWZ (HI(32))
#define MFCR (HI(31) | LO(19))
#define MFLR (HI(31) | LO(339) | 0x80000)
@@ -215,6 +216,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define STD (HI(62) | 0)
#define STDU (HI(62) | 1)
#define STDUX (HI(31) | LO(181))
+#define STFD (HI(54))
#define STFIWX (HI(31) | LO(983))
#define STW (HI(36))
#define STWU (HI(37))
@@ -232,15 +234,18 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define UIMM_MAX (0xffff)
#define RLDI(dst, src, sh, mb, type) \
- (HI(30) | S(src) | A(dst) | ((type) << 2) | (((sh) & 0x1f) << 11) | (((sh) & 0x20) >> 4) | (((mb) & 0x1f) << 6) | ((mb) & 0x20))
+ (HI(30) | S(src) | A(dst) | ((sljit_ins)(type) << 2) | (((sljit_ins)(sh) & 0x1f) << 11) \
+ | (((sljit_ins)(sh) & 0x20) >> 4) | (((sljit_ins)(mb) & 0x1f) << 6) | ((sljit_ins)(mb) & 0x20))
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
-SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_sw addr, void* func)
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct sljit_function_context* context, sljit_uw addr, void* func)
{
- sljit_sw* ptrs;
+ sljit_uw* ptrs;
+
if (func_ptr)
*func_ptr = (void*)context;
- ptrs = (sljit_sw*)func;
+
+ ptrs = (sljit_uw*)func;
context->addr = addr ? addr : ptrs[0];
context->r2 = ptrs[1];
context->r11 = ptrs[2];
@@ -260,7 +265,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
{
sljit_sw diff;
sljit_uw target_addr;
- sljit_sw extra_jump_flags;
+ sljit_uw extra_jump_flags;
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL) && (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
if (jump->flags & (SLJIT_REWRITABLE_JUMP | IS_CALL))
@@ -296,7 +301,7 @@ static SLJIT_INLINE sljit_s32 detect_jump_type(struct sljit_jump *jump, sljit_in
}
extra_jump_flags = REMOVE_COND;
- diff -= sizeof(sljit_ins);
+ diff -= SSIZE_OF(ins);
}
if (diff <= 0x01ffffff && diff >= -0x02000000) {
@@ -349,7 +354,7 @@ static SLJIT_INLINE void put_label_set(struct sljit_put_label *put_label)
{
sljit_uw addr = put_label->label->addr;
sljit_ins *inst = (sljit_ins *)put_label->addr;
- sljit_s32 reg = *inst;
+ sljit_u32 reg = *inst;
if (put_label->flags == 0) {
SLJIT_ASSERT(addr < 0x100000000l);
@@ -433,7 +438,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
/* Just recording the address. */
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
if (jump && jump->addr == word_count) {
@@ -501,7 +506,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
@@ -511,7 +516,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
SLJIT_ASSERT(!put_label);
#if (defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL)
- SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins)));
+ SLJIT_ASSERT(code_ptr - code <= (sljit_sw)(compiler->size - (sizeof(struct sljit_function_context) / sizeof(sljit_ins))));
#else
SLJIT_ASSERT(code_ptr - code <= (sljit_sw)compiler->size);
#endif
@@ -527,22 +532,22 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (!(jump->flags & PATCH_ABS_B)) {
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
SLJIT_ASSERT((sljit_sw)addr <= 0x7fff && (sljit_sw)addr >= -0x8000);
- *buf_ptr = BCx | (addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
+ *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | ((*buf_ptr) & 0x03ff0001);
}
else {
SLJIT_ASSERT(addr <= 0xffff);
- *buf_ptr = BCx | (addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
+ *buf_ptr = BCx | ((sljit_ins)addr & 0xfffc) | 0x2 | ((*buf_ptr) & 0x03ff0001);
}
}
else {
if (!(jump->flags & PATCH_ABS_B)) {
addr -= (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset);
SLJIT_ASSERT((sljit_sw)addr <= 0x01ffffff && (sljit_sw)addr >= -0x02000000);
- *buf_ptr = Bx | (addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
+ *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | ((*buf_ptr) & 0x1);
}
else {
SLJIT_ASSERT(addr <= 0x03ffffff);
- *buf_ptr = Bx | (addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
+ *buf_ptr = Bx | ((sljit_ins)addr & 0x03fffffc) | 0x2 | ((*buf_ptr) & 0x1);
}
}
break;
@@ -550,26 +555,32 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)addr & 0xffff;
#else
if (jump->flags & PATCH_ABS32) {
SLJIT_ASSERT(addr <= 0x7fffffff);
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)addr & 0xffff;
break;
}
+
if (jump->flags & PATCH_ABS48) {
SLJIT_ASSERT(addr <= 0x7fffffffffff);
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 32) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | (addr & 0xffff);
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 32) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[3] |= (sljit_ins)addr & 0xffff;
break;
}
- buf_ptr[0] = (buf_ptr[0] & 0xffff0000) | ((addr >> 48) & 0xffff);
- buf_ptr[1] = (buf_ptr[1] & 0xffff0000) | ((addr >> 32) & 0xffff);
- buf_ptr[3] = (buf_ptr[3] & 0xffff0000) | ((addr >> 16) & 0xffff);
- buf_ptr[4] = (buf_ptr[4] & 0xffff0000) | (addr & 0xffff);
+
+ SLJIT_ASSERT(((buf_ptr[0] | buf_ptr[1] | buf_ptr[3] | buf_ptr[4]) & 0xffff) == 0);
+ buf_ptr[0] |= (sljit_ins)(addr >> 48) & 0xffff;
+ buf_ptr[1] |= (sljit_ins)(addr >> 32) & 0xffff;
+ buf_ptr[3] |= (sljit_ins)(addr >> 16) & 0xffff;
+ buf_ptr[4] |= (sljit_ins)addr & 0xffff;
#endif
} while (0);
jump = jump->next;
@@ -592,7 +603,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
@@ -601,7 +612,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (((sljit_sw)code_ptr) & 0x4)
code_ptr++;
#endif
- sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_sw)code, (void*)sljit_generate_code);
+ sljit_set_function_context(NULL, (struct sljit_function_context*)code_ptr, (sljit_uw)code, (void*)sljit_generate_code);
#endif
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -696,69 +707,116 @@ ALT_FORM5 0x010000 */
#define STACK_LOAD LD
#endif
+#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
+#define LR_SAVE_OFFSET 2 * SSIZE_OF(sw)
+#else
+#define LR_SAVE_OFFSET SSIZE_OF(sw)
+#endif
+
+#define STACK_MAX_DISTANCE (0x8000 - SSIZE_OF(sw) - LR_SAVE_OFFSET)
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args, i, tmp, offs;
+ sljit_s32 i, tmp, base, offset;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 saved_arg_count = 0;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 arg_count = 0;
+#endif
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1)
+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
+ compiler->local_size = local_size;
+
FAIL_IF(push_inst(compiler, MFLR | D(0)));
- offs = -(sljit_s32)(sizeof(sljit_sw));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--) {
- offs -= (sljit_s32)(sizeof(sljit_sw));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
+ base = SLJIT_SP;
+ offset = local_size;
+
+ if (local_size <= STACK_MAX_DISTANCE) {
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
+#else
+ FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
+#endif
+ } else {
+ base = TMP_REG1;
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_SP) | A(TMP_REG1) | B(SLJIT_SP)));
+ FAIL_IF(load_immediate(compiler, TMP_REG2, -local_size));
+#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
+ FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
+#else
+ FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(TMP_REG2)));
+#endif
+ local_size = 0;
+ offset = 0;
}
- for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
- offs -= (sljit_s32)(sizeof(sljit_sw));
- FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(SLJIT_SP) | IMM(offs)));
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
}
- SLJIT_ASSERT(offs == -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1));
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, STFD | FS(i) | A(base) | IMM(offset)));
+ }
-#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
- FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
-#else
- FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
-#endif
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(TMP_ZERO) | A(base) | IMM(offset)));
- FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
+ }
- args = get_arg_count(arg_types);
+ for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(i) | A(base) | IMM(offset)));
+ }
- if (args >= 1)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(SLJIT_S0) | B(SLJIT_R0)));
- if (args >= 2)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_R1) | A(SLJIT_S1) | B(SLJIT_R1)));
- if (args >= 3)
- FAIL_IF(push_inst(compiler, OR | S(SLJIT_R2) | A(SLJIT_S2) | B(SLJIT_R2)));
+ FAIL_IF(push_inst(compiler, STACK_STORE | S(0) | A(base) | IMM(local_size + LR_SAVE_OFFSET)));
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_ZERO) | A(0) | 0));
- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
- local_size = (local_size + 15) & ~0xf;
- compiler->local_size = local_size;
+ arg_types >>= SLJIT_ARG_SHIFT;
-#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- if (local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, STWU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
- else {
- FAIL_IF(load_immediate(compiler, 0, -local_size));
- FAIL_IF(push_inst(compiler, STWUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
- }
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ do {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = SLJIT_S0 - saved_arg_count;
+ saved_arg_count++;
+ } else if (arg_count != word_arg_count)
+ tmp = SLJIT_R0 + word_arg_count;
+ else
+ break;
+
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + arg_count) | A(tmp) | B(SLJIT_R0 + arg_count)));
+ } while (0);
#else
- if (local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, STDU | S(SLJIT_SP) | A(SLJIT_SP) | IMM(-local_size)));
- else {
- FAIL_IF(load_immediate(compiler, 0, -local_size));
- FAIL_IF(push_inst(compiler, STDUX | S(SLJIT_SP) | A(SLJIT_SP) | B(0)));
- }
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0 + word_arg_count) | A(SLJIT_S0 - saved_arg_count) | B(SLJIT_R0 + word_arg_count)));
+ saved_arg_count++;
+ }
#endif
+ word_arg_count++;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ arg_count++;
+#endif
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
return SLJIT_SUCCESS;
}
@@ -771,54 +829,74 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1) + SLJIT_LOCALS_OFFSET;
- compiler->local_size = (local_size + 15) & ~0xf;
+ local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1)
+ + GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, sizeof(sljit_f64));
+ compiler->local_size = (local_size + SLJIT_LOCALS_OFFSET + 15) & ~0xf;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
-{
- sljit_s32 i, tmp, offs;
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
+{
+ sljit_s32 i, tmp, base, offset;
+ sljit_s32 local_size = compiler->local_size;
+
+ base = SLJIT_SP;
+ if (local_size > STACK_MAX_DISTANCE) {
+ base = TMP_REG1;
+ if (local_size > 2 * STACK_MAX_DISTANCE + LR_SAVE_OFFSET) {
+ FAIL_IF(push_inst(compiler, STACK_LOAD | D(base) | A(SLJIT_SP) | IMM(0)));
+ local_size = 0;
+ } else {
+ FAIL_IF(push_inst(compiler, ADDI | D(TMP_REG1) | A(SLJIT_SP) | IMM(local_size - STACK_MAX_DISTANCE)));
+ local_size = STACK_MAX_DISTANCE;
+ }
+ }
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ offset = local_size;
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(0) | A(base) | IMM(offset + LR_SAVE_OFFSET)));
- if (compiler->local_size <= SIMM_MAX)
- FAIL_IF(push_inst(compiler, ADDI | D(SLJIT_SP) | A(SLJIT_SP) | IMM(compiler->local_size)));
- else {
- FAIL_IF(load_immediate(compiler, 0, compiler->local_size));
- FAIL_IF(push_inst(compiler, ADD | D(SLJIT_SP) | A(SLJIT_SP) | B(0)));
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
}
-#if (defined SLJIT_PPC_STACK_FRAME_V2 && SLJIT_PPC_STACK_FRAME_V2)
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(2 * sizeof(sljit_sw))));
-#else
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(0) | A(SLJIT_SP) | IMM(sizeof(sljit_sw))));
-#endif
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(push_inst(compiler, LFD | FS(i) | A(base) | IMM(offset)));
+ }
- offs = -(sljit_s32)GET_SAVED_REGISTERS_SIZE(compiler->scratches, compiler->saveds, 1);
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(TMP_ZERO) | A(base) | IMM(offset)));
- tmp = compiler->scratches;
- for (i = SLJIT_FIRST_SAVED_REG; i <= tmp; i++) {
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
- offs += (sljit_s32)(sizeof(sljit_sw));
+ tmp = SLJIT_S0 - compiler->saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
}
- tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = tmp; i <= SLJIT_S0; i++) {
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(i) | A(SLJIT_SP) | IMM(offs)));
- offs += (sljit_s32)(sizeof(sljit_sw));
+ for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
+ offset -= SSIZE_OF(sw);
+ FAIL_IF(push_inst(compiler, STACK_LOAD | S(i) | A(base) | IMM(offset)));
}
- FAIL_IF(push_inst(compiler, STACK_LOAD | D(TMP_ZERO) | A(SLJIT_SP) | IMM(offs)));
- SLJIT_ASSERT(offs == -(sljit_sw)(sizeof(sljit_sw)));
+ push_inst(compiler, MTLR | S(0));
- FAIL_IF(push_inst(compiler, MTLR | S(0)));
- FAIL_IF(push_inst(compiler, BLR));
+ if (local_size > 0)
+ return push_inst(compiler, ADDI | D(SLJIT_SP) | A(base) | IMM(local_size));
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT(base == TMP_REG1);
+ return push_inst(compiler, OR | S(base) | A(SLJIT_SP) | B(base));
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ return push_inst(compiler, BLR);
}
#undef STACK_STORE
@@ -843,11 +921,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
#define ARCH_32_64(a, b) a
#define INST_CODE_AND_DST(inst, flags, reg) \
- ((inst) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
+ ((sljit_ins)(inst) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
#else
#define ARCH_32_64(a, b) b
#define INST_CODE_AND_DST(inst, flags, reg) \
- (((inst) & ~INT_ALIGNED) | (((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
+ (((sljit_ins)(inst) & ~(sljit_ins)INT_ALIGNED) | (sljit_ins)(((flags) & MEM_MASK) <= GPR_REG ? D(reg) : FD(reg)))
#endif
static const sljit_ins data_transfer_insts[64 + 16] = {
@@ -1000,7 +1078,7 @@ static sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 inp_flag
if (argw != 0) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | (argw << 11) | ((31 - argw) << 1)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(arg)) | A(tmp_reg) | ((sljit_ins)argw << 11) | ((31 - (sljit_ins)argw) << 1)));
#else
FAIL_IF(push_inst(compiler, RLDI(tmp_reg, OFFS_REG(arg), argw, 63 - argw, 1)));
#endif
@@ -1073,8 +1151,10 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
sljit_s32 flags = input_flags & (ALT_FORM1 | ALT_FORM2 | ALT_FORM3 | ALT_FORM4 | ALT_FORM5 | ALT_SIGN_EXT | ALT_SET_FLAGS);
/* Destination check. */
- if (SLOW_IS_REG(dst)) {
+ if (FAST_IS_REG(dst)) {
dst_r = dst;
+ /* The REG_DEST is only used by SLJIT_MOV operations, although
+ * it is set for op2 operations with unset destination. */
flags |= REG_DEST;
if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
@@ -1087,8 +1167,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
flags |= REG1_SOURCE;
}
else if (src1 & SLJIT_IMM) {
- FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
- src1_r = TMP_REG1;
+ src1_r = TMP_ZERO;
+ if (src1w != 0) {
+ FAIL_IF(load_immediate(compiler, TMP_REG1, src1w));
+ src1_r = TMP_REG1;
+ }
}
else {
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, src1, src1w, TMP_REG1));
@@ -1104,8 +1187,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
dst_r = src2_r;
}
else if (src2 & SLJIT_IMM) {
- FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
- src2_r = sugg_src2_r;
+ src2_r = TMP_ZERO;
+ if (src2w != 0) {
+ FAIL_IF(load_immediate(compiler, sugg_src2_r, src2w));
+ src2_r = sugg_src2_r;
+ }
}
else {
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, sugg_src2_r, src2, src2w, TMP_REG2));
@@ -1123,7 +1209,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compiler, sljit_s32 op)
{
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- sljit_s32 int_op = op & SLJIT_I32_OP;
+ sljit_s32 int_op = op & SLJIT_32;
#endif
CHECK_ERROR();
@@ -1174,7 +1260,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
sljit_s32 src, sljit_sw srcw)
{
if (!(src & OFFS_REG_MASK)) {
- if (srcw == 0 && (src & REG_MASK) != SLJIT_UNUSED)
+ if (srcw == 0 && (src & REG_MASK))
return push_inst(compiler, DCBT | A(0) | B(src & REG_MASK));
FAIL_IF(load_immediate(compiler, TMP_REG1, srcw));
@@ -1188,7 +1274,7 @@ static sljit_s32 emit_prefetch(struct sljit_compiler *compiler,
return push_inst(compiler, DCBT | A(src & REG_MASK) | B(OFFS_REG(src)));
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | (srcw << 11) | ((31 - srcw) << 1)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(src)) | A(TMP_REG1) | ((sljit_ins)srcw << 11) | ((31 - (sljit_ins)srcw) << 1)));
#else
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(src), srcw, 63 - srcw, 1)));
#endif
@@ -1211,8 +1297,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(src, srcw);
op = GET_OPCODE(op);
- if ((src & SLJIT_IMM) && srcw == 0)
- src = TMP_ZERO;
if (GET_FLAG_TYPE(op_flags) == SLJIT_OVERFLOW)
FAIL_IF(push_inst(compiler, MTXER | S(TMP_ZERO)));
@@ -1223,7 +1307,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
}
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op_flags & SLJIT_I32_OP) {
+ if (op_flags & SLJIT_32) {
if (op < SLJIT_NOT) {
if (src & SLJIT_MEM) {
if (op == SLJIT_MOV_S32)
@@ -1245,11 +1329,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
switch (op) {
case SLJIT_MOV:
- case SLJIT_MOV_P:
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
#endif
+ case SLJIT_MOV_P:
return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
@@ -1257,6 +1342,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return EMIT_MOV(SLJIT_MOV_U32, INT_DATA, (sljit_u32));
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
return EMIT_MOV(SLJIT_MOV_S32, INT_DATA | SIGNED_DATA, (sljit_s32));
#endif
@@ -1275,12 +1361,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_NOT:
return emit_op(compiler, SLJIT_NOT, flags, dst, dstw, TMP_REG1, 0, src, srcw);
- case SLJIT_NEG:
- return emit_op(compiler, SLJIT_NEG, flags | (GET_FLAG_TYPE(op_flags) ? ALT_FORM1 : 0), dst, dstw, TMP_REG1, 0, src, srcw);
-
case SLJIT_CLZ:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_I32_OP) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
+ return emit_op(compiler, SLJIT_CLZ, flags | (!(op_flags & SLJIT_32) ? 0 : ALT_FORM1), dst, dstw, TMP_REG1, 0, src, srcw);
#else
return emit_op(compiler, SLJIT_CLZ, flags, dst, dstw, TMP_REG1, 0, src, srcw);
#endif
@@ -1306,7 +1389,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#endif
#define TEST_UH_IMM(src, srcw) \
- (((src) & SLJIT_IMM) && !((srcw) & ~0xffff0000))
+ (((src) & SLJIT_IMM) && !((srcw) & ~(sljit_sw)0xffff0000))
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define TEST_ADD_IMM(src, srcw) \
@@ -1327,13 +1410,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define TEST_ADD_FORM1(op) \
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
- || (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z | SLJIT_SET_CARRY))
+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z | SLJIT_SET_CARRY))
#define TEST_SUB_FORM2(op) \
((GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) \
- || (op & (SLJIT_I32_OP | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_I32_OP | SLJIT_SET_Z))
+ || (op & (SLJIT_32 | SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_32 | SLJIT_SET_Z))
#define TEST_SUB_FORM3(op) \
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW \
- || (op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z))
+ || (op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z))
#else
#define TEST_ADD_FORM1(op) \
(GET_FLAG_TYPE(op) == SLJIT_OVERFLOW)
@@ -1351,21 +1434,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 flags = HAS_FLAGS(op) ? ALT_SET_FLAGS : 0;
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
- if ((src1 & SLJIT_IMM) && src1w == 0)
- src1 = TMP_ZERO;
- if ((src2 & SLJIT_IMM) && src2w == 0)
- src2 = TMP_ZERO;
-
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op & SLJIT_I32_OP) {
+ if (op & SLJIT_32) {
/* Most operations expect sign extended arguments. */
flags |= INT_DATA | SIGNED_DATA;
if (src1 & SLJIT_IMM)
@@ -1381,45 +1456,47 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+
if (TEST_ADD_FORM1(op))
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
if (!HAS_FLAGS(op) && ((src1 | src2) & SLJIT_IMM)) {
if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffff;
+ compiler->imm = (sljit_ins)src1w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src2, src2w)) {
- compiler->imm = (src2w >> 16) & 0xffff;
+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SH_IMM(src1, src1w)) {
- compiler->imm = (src1w >> 16) & 0xffff;
+ compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffffffff;
+ compiler->imm = (sljit_ins)src2w & 0xffffffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_ADD_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffffffff;
+ compiler->imm = (sljit_ins)src1w & 0xffffffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if ((op & (SLJIT_I32_OP | SLJIT_SET_Z)) == (SLJIT_I32_OP | SLJIT_SET_Z)) {
+ if ((op & (SLJIT_32 | SLJIT_SET_Z)) == (SLJIT_32 | SLJIT_SET_Z)) {
if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffff;
+ compiler->imm = (sljit_ins)src1w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4 | ALT_FORM5, dst, dstw, src2, src2w, TMP_REG2, 0);
}
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
@@ -1427,39 +1504,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
#endif
if (HAS_FLAGS(op)) {
if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffff;
+ compiler->imm = (sljit_ins)src1w & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
return emit_op(compiler, SLJIT_ADD, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
return emit_op(compiler, SLJIT_ADDC, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+
if (GET_FLAG_TYPE(op) >= SLJIT_LESS && GET_FLAG_TYPE(op) <= SLJIT_LESS_EQUAL) {
- if (dst == SLJIT_UNUSED) {
+ if (dst == TMP_REG2) {
if (TEST_UL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1, dst, dstw, src1, src1w, src2, src2w);
}
if ((src2 & SLJIT_IMM) && src2w >= 0 && src2w <= (SIMM_MAX + 1)) {
- compiler->imm = src2w;
+ compiler->imm = (sljit_ins)src2w;
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM1 | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
}
- if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
+ if (dst == TMP_REG2 && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2, dst, dstw, src1, src1w, src2, src2w);
@@ -1467,7 +1547,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
if (TEST_SUB_FORM2(op)) {
if ((src2 & SLJIT_IMM) && src2w >= -SIMM_MAX && src2w <= SIMM_MAX) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM3 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, src2, src2w);
@@ -1477,45 +1557,46 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM3, dst, dstw, src1, src1w, src2, src2w);
if (TEST_SL_IMM(src2, -src2w)) {
- compiler->imm = (-src2w) & 0xffff;
+ compiler->imm = (sljit_ins)(-src2w) & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | (!HAS_FLAGS(op) ? ALT_FORM2 : ALT_FORM3), dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w) && !(op & SLJIT_SET_Z)) {
- compiler->imm = src1w & 0xffff;
+ compiler->imm = (sljit_ins)src1w & 0xffff;
return emit_op(compiler, SLJIT_SUB, flags | ALT_FORM4, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (!HAS_FLAGS(op)) {
if (TEST_SH_IMM(src2, -src2w)) {
- compiler->imm = ((-src2w) >> 16) & 0xffff;
+ compiler->imm = (sljit_ins)((-src2w) >> 16) & 0xffff;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
/* Range between -1 and -32768 is covered above. */
if (TEST_ADD_IMM(src2, -src2w)) {
- compiler->imm = -src2w & 0xffffffff;
+ compiler->imm = (sljit_ins)-src2w;
return emit_op(compiler, SLJIT_ADD, flags | ALT_FORM2 | ALT_FORM4, dst, dstw, src1, src1w, TMP_REG2, 0);
}
}
- /* We know ALT_SIGN_EXT is set if it is an SLJIT_I32_OP on 64 bit systems. */
+ /* We know ALT_SIGN_EXT is set if it is an SLJIT_32 on 64 bit systems. */
return emit_op(compiler, SLJIT_SUB, flags | ((GET_FLAG_TYPE(op) == GET_FLAG_TYPE(SLJIT_SET_CARRY)) ? ALT_FORM5 : 0), dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
return emit_op(compiler, SLJIT_SUBC, flags, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_MUL:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op & SLJIT_I32_OP)
+ if (op & SLJIT_32)
flags |= ALT_FORM2;
#endif
if (!HAS_FLAGS(op)) {
if (TEST_SL_IMM(src2, src2w)) {
- compiler->imm = src2w & 0xffff;
+ compiler->imm = (sljit_ins)src2w & 0xffff;
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_SL_IMM(src1, src1w)) {
- compiler->imm = src1w & 0xffff;
+ compiler->imm = (sljit_ins)src1w & 0xffff;
return emit_op(compiler, SLJIT_MUL, flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
@@ -1529,30 +1610,30 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
/* Commutative unsigned operations. */
if (!HAS_FLAGS(op) || GET_OPCODE(op) == SLJIT_AND) {
if (TEST_UL_IMM(src2, src2w)) {
- compiler->imm = src2w;
+ compiler->imm = (sljit_ins)src2w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UL_IMM(src1, src1w)) {
- compiler->imm = src1w;
+ compiler->imm = (sljit_ins)src1w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src2, src2w, TMP_REG2, 0);
}
if (TEST_UH_IMM(src2, src2w)) {
- compiler->imm = (src2w >> 16) & 0xffff;
+ compiler->imm = (sljit_ins)(src2w >> 16) & 0xffff;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UH_IMM(src1, src1w)) {
- compiler->imm = (src1w >> 16) & 0xffff;
+ compiler->imm = (sljit_ins)(src1w >> 16) & 0xffff;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM2, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
- if (GET_OPCODE(op) != SLJIT_AND && GET_OPCODE(op) != SLJIT_AND) {
- /* Unlike or and xor, and resets unwanted bits as well. */
+ if (GET_OPCODE(op) != SLJIT_AND) {
+ /* Unlike or and xor, the and resets unwanted bits as well. */
if (TEST_UI_IMM(src2, src2w)) {
- compiler->imm = src2w;
+ compiler->imm = (sljit_ins)src2w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src1, src1w, TMP_REG2, 0);
}
if (TEST_UI_IMM(src1, src1w)) {
- compiler->imm = src1w;
+ compiler->imm = (sljit_ins)src1w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM3, dst, dstw, src2, src2w, TMP_REG2, 0);
}
}
@@ -1562,11 +1643,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
case SLJIT_LSHR:
case SLJIT_ASHR:
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- if (op & SLJIT_I32_OP)
+ if (op & SLJIT_32)
flags |= ALT_FORM2;
#endif
if (src2 & SLJIT_IMM) {
- compiler->imm = src2w;
+ compiler->imm = (sljit_ins)src2w;
return emit_op(compiler, GET_OPCODE(op), flags | ALT_FORM1, dst, dstw, src1, src1w, TMP_REG2, 0);
}
return emit_op(compiler, GET_OPCODE(op), flags, dst, dstw, src1, src1w, src2, src2w);
@@ -1575,6 +1656,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
+}
+
#undef TEST_ADD_FORM1
#undef TEST_SUB_FORM2
#undef TEST_SUB_FORM3
@@ -1621,7 +1716,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1633,8 +1728,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 6))
-#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
+#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_32) >> 6))
+#define SELECT_FOP(op, single, double) ((sljit_ins)((op & SLJIT_32) ? single : double))
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
#define FLOAT_TMP_MEM_OFFSET (6 * sizeof(sljit_sw))
@@ -1688,7 +1783,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
dstw &= 0x3;
if (dstw) {
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
- FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | (dstw << 11) | ((31 - dstw) << 1)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(OFFS_REG(dst)) | A(TMP_REG1) | ((sljit_ins)dstw << 11) | ((31 - (sljit_ins)dstw) << 1)));
#else
FAIL_IF(push_inst(compiler, RLDI(TMP_REG1, OFFS_REG(dst), dstw, 63 - dstw, 1)));
#endif
@@ -1745,7 +1840,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
- if (op & SLJIT_F32_OP)
+ if (op & SLJIT_32)
return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
return SLJIT_SUCCESS;
@@ -1755,7 +1850,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
sljit_s32 invert_sign = 1;
if (src & SLJIT_IMM) {
- FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ 0x80000000));
+ FAIL_IF(load_immediate(compiler, TMP_REG1, srcw ^ (sljit_sw)0x80000000));
src = TMP_REG1;
invert_sign = 0;
}
@@ -1783,7 +1878,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
if (dst & SLJIT_MEM)
return emit_op_mem(compiler, FLOAT_DATA(op), TMP_FREG1, dst, dstw, TMP_REG1);
- if (op & SLJIT_F32_OP)
+ if (op & SLJIT_32)
return push_inst(compiler, FRSP | FD(dst_r) | FB(dst_r));
return SLJIT_SUCCESS;
@@ -1815,11 +1910,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
CHECK_ERROR();
- SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x4), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -1830,8 +1925,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
switch (GET_OPCODE(op)) {
case SLJIT_CONV_F64_FROM_F32:
- op ^= SLJIT_F32_OP;
- if (op & SLJIT_F32_OP) {
+ op ^= SLJIT_32;
+ if (op & SLJIT_32) {
FAIL_IF(push_inst(compiler, FRSP | FD(dst_r) | FB(src)));
break;
}
@@ -1946,12 +2041,22 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label* sljit_emit_label(struct sljit_compi
return label;
}
-static sljit_ins get_bo_bi_flags(sljit_s32 type)
+static sljit_ins get_bo_bi_flags(struct sljit_compiler *compiler, sljit_s32 type)
{
switch (type) {
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (4 << 21) | (2 << 16);
+ /* fallthrough */
+
case SLJIT_EQUAL:
return (12 << 21) | (2 << 16);
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (12 << 21) | (2 << 16);
+ /* fallthrough */
+
case SLJIT_NOT_EQUAL:
return (4 << 21) | (2 << 16);
@@ -2015,15 +2120,18 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_jump(compiler, type));
- bo_bi_flags = get_bo_bi_flags(type & 0xff);
+ bo_bi_flags = get_bo_bi_flags(compiler, type & 0xff);
if (!bo_bi_flags)
return NULL;
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF(!jump);
- set_jump(jump, compiler, type & SLJIT_REWRITABLE_JUMP);
+ set_jump(jump, compiler, (sljit_u32)type & SLJIT_REWRITABLE_JUMP);
type &= 0xff;
+ if (type == SLJIT_CARRY || type == SLJIT_NOT_CARRY)
+ PTR_FAIL_IF(push_inst(compiler, ADDE | RC(ALT_SET_FLAGS) | D(TMP_REG1) | A(TMP_ZERO) | B(TMP_ZERO)));
+
/* In PPC, we don't need to touch the arguments. */
if (type < SLJIT_JUMP)
jump->flags |= IS_COND;
@@ -2049,6 +2157,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
#endif
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
@@ -2068,25 +2181,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (FAST_IS_REG(src)) {
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
- if (type >= SLJIT_CALL) {
+ if (type >= SLJIT_CALL && src != TMP_CALL_REG) {
FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
src_r = TMP_CALL_REG;
}
else
src_r = src;
-#else
+#else /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
src_r = src;
-#endif
+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
} else if (src & SLJIT_IMM) {
/* These jumps are converted to jump/call instructions when possible. */
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR);
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
+
#if (defined SLJIT_PASS_ENTRY_ADDR_TO_CALL && SLJIT_PASS_ENTRY_ADDR_TO_CALL)
if (type >= SLJIT_CALL)
jump->flags |= IS_CALL;
-#endif
+#endif /* SLJIT_PASS_ENTRY_ADDR_TO_CALL */
+
FAIL_IF(emit_const(compiler, TMP_CALL_REG, 0));
src_r = TMP_CALL_REG;
}
@@ -2108,13 +2223,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
if (src & SLJIT_MEM) {
ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_CALL_REG, 0, TMP_REG1, 0, src, srcw));
src = TMP_CALL_REG;
}
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
+ FAIL_IF(push_inst(compiler, OR | S(src) | A(TMP_CALL_REG) | B(src)));
+ src = TMP_CALL_REG;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP;
+ }
+
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
FAIL_IF(call_with_args(compiler, arg_types, &src));
#endif
@@ -2130,20 +2255,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
sljit_s32 dst, sljit_sw dstw,
sljit_s32 type)
{
- sljit_s32 reg, input_flags, cr_bit, invert;
+ sljit_s32 reg, invert;
+ sljit_u32 bit, from_xer;
sljit_s32 saved_op = op;
sljit_sw saved_dstw = dstw;
+#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
+ sljit_s32 input_flags = ((op & SLJIT_32) || op == SLJIT_MOV32) ? INT_DATA : WORD_DATA;
+#else
+ sljit_s32 input_flags = WORD_DATA;
+#endif
CHECK_ERROR();
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
ADJUST_LOCAL_OFFSET(dst, dstw);
-#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
- input_flags = (op & SLJIT_I32_OP) ? INT_DATA : WORD_DATA;
-#else
- input_flags = WORD_DATA;
-#endif
-
op = GET_OPCODE(op);
reg = (op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2;
@@ -2151,7 +2276,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
FAIL_IF(emit_op_mem(compiler, input_flags | LOAD_DATA, TMP_REG1, dst, dstw, TMP_REG1));
invert = 0;
- cr_bit = 0;
+ bit = 0;
+ from_xer = 0;
switch (type & 0xff) {
case SLJIT_LESS:
@@ -2165,66 +2291,80 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
case SLJIT_GREATER:
case SLJIT_SIG_GREATER:
- cr_bit = 1;
+ bit = 1;
break;
case SLJIT_LESS_EQUAL:
case SLJIT_SIG_LESS_EQUAL:
- cr_bit = 1;
+ bit = 1;
invert = 1;
break;
case SLJIT_EQUAL:
- cr_bit = 2;
+ bit = 2;
break;
case SLJIT_NOT_EQUAL:
- cr_bit = 2;
+ bit = 2;
invert = 1;
break;
case SLJIT_OVERFLOW:
- cr_bit = 3;
+ from_xer = 1;
+ bit = 1;
break;
case SLJIT_NOT_OVERFLOW:
- cr_bit = 3;
+ from_xer = 1;
+ bit = 1;
invert = 1;
break;
+ case SLJIT_CARRY:
+ from_xer = 1;
+ bit = 2;
+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB) != 0;
+ break;
+
+ case SLJIT_NOT_CARRY:
+ from_xer = 1;
+ bit = 2;
+ invert = (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD) != 0;
+ break;
+
case SLJIT_LESS_F64:
- cr_bit = 4 + 0;
+ bit = 4 + 0;
break;
case SLJIT_GREATER_EQUAL_F64:
- cr_bit = 4 + 0;
+ bit = 4 + 0;
invert = 1;
break;
case SLJIT_GREATER_F64:
- cr_bit = 4 + 1;
+ bit = 4 + 1;
break;
case SLJIT_LESS_EQUAL_F64:
- cr_bit = 4 + 1;
+ bit = 4 + 1;
invert = 1;
break;
case SLJIT_EQUAL_F64:
- cr_bit = 4 + 2;
+ bit = 4 + 2;
break;
case SLJIT_NOT_EQUAL_F64:
- cr_bit = 4 + 2;
+ bit = 4 + 2;
invert = 1;
break;
case SLJIT_UNORDERED_F64:
- cr_bit = 4 + 3;
+ bit = 4 + 3;
break;
case SLJIT_ORDERED_F64:
- cr_bit = 4 + 3;
+ bit = 4 + 3;
invert = 1;
break;
@@ -2233,8 +2373,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
break;
}
- FAIL_IF(push_inst(compiler, MFCR | D(reg)));
- FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + (cr_bit)) << 11) | (31 << 6) | (31 << 1)));
+ FAIL_IF(push_inst(compiler, (from_xer ? MFXER : MFCR) | D(reg)));
+ FAIL_IF(push_inst(compiler, RLWINM | S(reg) | A(reg) | ((1 + bit) << 11) | (31 << 6) | (31 << 1)));
if (invert)
FAIL_IF(push_inst(compiler, XORI | S(reg) | A(reg) | 0x1));
@@ -2283,19 +2423,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_mem(struct sljit_compiler *compile
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
#endif
mem_flags = WORD_DATA;
break;
#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64)
case SLJIT_MOV_U32:
+ case SLJIT_MOV32:
mem_flags = INT_DATA;
break;
case SLJIT_MOV_S32:
mem_flags = INT_DATA;
- if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_I32_OP)) {
+ if (!(type & SLJIT_MEM_STORE) && !(type & SLJIT_32)) {
if (mem & OFFS_REG_MASK)
mem_flags |= SIGNED_DATA;
else
@@ -2436,7 +2578,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label* sljit_emit_put_label(struct slj
#if (defined SLJIT_CONFIG_PPC_32 && SLJIT_CONFIG_PPC_32)
PTR_FAIL_IF(emit_const(compiler, dst_r, 0));
#else
- PTR_FAIL_IF(push_inst(compiler, dst_r));
+ PTR_FAIL_IF(push_inst(compiler, (sljit_ins)dst_r));
compiler->size += 4;
#endif
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeS390X.c b/thirdparty/pcre2/src/sljit/sljitNativeS390X.c
index 716491ec72..8eef910c42 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeS390X.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeS390X.c
@@ -44,6 +44,9 @@ typedef sljit_uw sljit_ins;
/* Instruction tags (most significant halfword). */
static const sljit_ins sljit_ins_const = (sljit_ins)1 << 48;
+#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2)
+#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3)
+
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 4] = {
0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 0, 1
};
@@ -97,20 +100,37 @@ static const sljit_gpr r15 = 15; /* reg_map[SLJIT_NUMBER_OF_REGISTERS + 1]: stac
* link register doesn't need to change
*/
+/* When reg cannot be unused. */
+#define IS_GPR_REG(reg) ((reg > 0) && (reg) <= SLJIT_SP)
+
/* Link registers. The normal link register is r14, but since
we use that for flags we need to use r0 instead to do fast
calls so that flags are preserved. */
static const sljit_gpr link_r = 14; /* r14 */
static const sljit_gpr fast_link_r = 0; /* r0 */
-/* Flag register layout:
+#define TMP_FREG1 (0)
+
+static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
+ 1, 0, 2, 4, 6, 3, 5, 7, 15, 14, 13, 12, 11, 10, 9, 8,
+};
+
+#define R0A(r) (r)
+#define R4A(r) ((r) << 4)
+#define R8A(r) ((r) << 8)
+#define R12A(r) ((r) << 12)
+#define R16A(r) ((r) << 16)
+#define R20A(r) ((r) << 20)
+#define R28A(r) ((r) << 28)
+#define R32A(r) ((r) << 32)
+#define R36A(r) ((r) << 36)
- 0 32 33 34 36 64
- +---------------+---+---+-------+-------+
- | ZERO | 0 | 0 | C C |///////|
- +---------------+---+---+-------+-------+
-*/
-static const sljit_gpr flag_r = 14; /* r14 */
+#define R0(r) ((sljit_ins)reg_map[r])
+
+#define F0(r) ((sljit_ins)freg_map[r])
+#define F4(r) (R4A((sljit_ins)freg_map[r]))
+#define F20(r) (R20A((sljit_ins)freg_map[r]))
+#define F36(r) (R36A((sljit_ins)freg_map[r]))
struct sljit_s390x_const {
struct sljit_const const_; /* must be first */
@@ -124,19 +144,25 @@ static SLJIT_INLINE sljit_gpr gpr(sljit_s32 r)
return reg_map[r];
}
+static SLJIT_INLINE sljit_gpr fgpr(sljit_s32 r)
+{
+ SLJIT_ASSERT(r >= 0 && r < (sljit_s32)(sizeof(freg_map) / sizeof(freg_map[0])));
+ return freg_map[r];
+}
+
/* Size of instruction in bytes. Tags must already be cleared. */
static SLJIT_INLINE sljit_uw sizeof_ins(sljit_ins ins)
{
/* keep faulting instructions */
if (ins == 0)
- return 2;
+ return 2;
if ((ins & 0x00000000ffffL) == ins)
- return 2;
+ return 2;
if ((ins & 0x0000ffffffffL) == ins)
- return 4;
+ return 4;
if ((ins & 0xffffffffffffL) == ins)
- return 6;
+ return 6;
SLJIT_UNREACHABLE();
return (sljit_uw)-1;
@@ -172,7 +198,8 @@ static sljit_s32 encode_inst(void **ptr, sljit_ins ins)
}
#define SLJIT_ADD_SUB_NO_COMPARE(status_flags_state) \
- (((status_flags_state) & (SLJIT_CURRENT_FLAGS_ADD_SUB | SLJIT_CURRENT_FLAGS_COMPARE)) == SLJIT_CURRENT_FLAGS_ADD_SUB)
+ (((status_flags_state) & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)) \
+ && !((status_flags_state) & SLJIT_CURRENT_FLAGS_COMPARE))
/* Map the given type to a 4-bit condition code mask. */
static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 type) {
@@ -191,6 +218,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
return (cc0 | cc3);
return (cc0 | cc2);
}
+ /* fallthrough */
case SLJIT_EQUAL_F64:
return cc0;
@@ -204,6 +232,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
return (cc1 | cc2);
return (cc1 | cc3);
}
+ /* fallthrough */
case SLJIT_NOT_EQUAL_F64:
return (cc1 | cc2 | cc3);
@@ -228,10 +257,20 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_LESS_F64:
return cc1;
+ case SLJIT_NOT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (cc2 | cc3);
+ /* fallthrough */
+
case SLJIT_SIG_LESS_EQUAL:
case SLJIT_LESS_EQUAL_F64:
return (cc0 | cc1);
+ case SLJIT_CARRY:
+ if (compiler->status_flags_state & SLJIT_CURRENT_FLAGS_SUB)
+ return (cc0 | cc1);
+ /* fallthrough */
+
case SLJIT_SIG_GREATER:
/* Overflow is considered greater, see SLJIT_SUB. */
return cc2 | cc3;
@@ -242,6 +281,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_OVERFLOW:
if (compiler->status_flags_state & SLJIT_SET_Z)
return (cc2 | cc3);
+ /* fallthrough */
case SLJIT_UNORDERED_F64:
return cc3;
@@ -249,6 +289,7 @@ static SLJIT_INLINE sljit_u8 get_cc(struct sljit_compiler *compiler, sljit_s32 t
case SLJIT_NOT_OVERFLOW:
if (compiler->status_flags_state & SLJIT_SET_Z)
return (cc0 | cc1);
+ /* fallthrough */
case SLJIT_ORDERED_F64:
return (cc0 | cc1 | cc2);
@@ -444,7 +485,7 @@ SLJIT_S390X_RR(or, 0x1600)
#define SLJIT_S390X_RRE(name, pattern) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src) \
{ \
- return (pattern) | ((dst & 0xf) << 4) | (src & 0xf); \
+ return (pattern) | R4A(dst) | R0A(src); \
}
/* AND */
@@ -504,7 +545,7 @@ SLJIT_S390X_RRE(sgr, 0xb9090000)
#define SLJIT_S390X_RIA(name, pattern, imm_type) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \
{ \
- return (pattern) | ((reg & 0xf) << 20) | (imm & 0xffff); \
+ return (pattern) | R20A(reg) | (imm & 0xffff); \
}
/* ADD HALFWORD IMMEDIATE */
@@ -534,7 +575,7 @@ SLJIT_S390X_RIA(oilh, 0xa50a0000, sljit_u16)
SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, imm_type imm) \
{ \
SLJIT_ASSERT(have_eimm()); \
- return (pattern) | ((sljit_ins)(reg & 0xf) << 36) | (imm & 0xffffffff); \
+ return (pattern) | R36A(reg) | ((sljit_ins)imm & 0xffffffffu); \
}
/* ADD IMMEDIATE */
@@ -567,17 +608,11 @@ SLJIT_S390X_RILA(slfi, 0xc20500000000, sljit_u32)
/* RX-a form instructions */
#define SLJIT_S390X_RXA(name, pattern) \
-SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_u16 d, sljit_gpr x, sljit_gpr b) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \
{ \
- sljit_ins ri, xi, bi, di; \
-\
SLJIT_ASSERT((d & 0xfff) == d); \
- ri = (sljit_ins)(r & 0xf) << 20; \
- xi = (sljit_ins)(x & 0xf) << 16; \
- bi = (sljit_ins)(b & 0xf) << 12; \
- di = (sljit_ins)(d & 0xfff); \
\
- return (pattern) | ri | xi | bi | di; \
+ return (pattern) | R20A(r) | R16A(x) | R12A(b) | (sljit_ins)(d & 0xfff); \
}
/* LOAD */
@@ -607,15 +642,9 @@ SLJIT_S390X_RXA(sth, 0x40000000)
#define SLJIT_S390X_RXYA(name, pattern, cond) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b) \
{ \
- sljit_ins ri, xi, bi, di; \
-\
SLJIT_ASSERT(cond); \
- ri = (sljit_ins)(r & 0xf) << 36; \
- xi = (sljit_ins)(x & 0xf) << 32; \
- bi = (sljit_ins)(b & 0xf) << 28; \
- di = disp_s20(d); \
\
- return (pattern) | ri | xi | bi | di; \
+ return (pattern) | R36A(r) | R32A(x) | R28A(b) | disp_s20(d); \
}
/* LOAD */
@@ -660,17 +689,11 @@ SLJIT_S390X_RXYA(sthy, 0xe30000000070, have_ldisp())
/* RSY-a instructions */
#define SLJIT_S390X_RSYA(name, pattern, cond) \
-SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_sw d, sljit_gpr b) \
+SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_s32 d, sljit_gpr b) \
{ \
- sljit_ins r1, r3, b2, d2; \
-\
SLJIT_ASSERT(cond); \
- r1 = (sljit_ins)(dst & 0xf) << 36; \
- r3 = (sljit_ins)(src & 0xf) << 32; \
- b2 = (sljit_ins)(b & 0xf) << 28; \
- d2 = disp_s20(d); \
\
- return (pattern) | r1 | r3 | b2 | d2; \
+ return (pattern) | R36A(dst) | R32A(src) | R28A(b) | disp_s20(d); \
}
/* LOAD MULTIPLE */
@@ -691,16 +714,14 @@ SLJIT_S390X_RSYA(stmg, 0xeb0000000024, 1)
#define SLJIT_S390X_RIEF(name, pattern) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_u8 start, sljit_u8 end, sljit_u8 rot) \
{ \
- sljit_ins r1, r2, i3, i4, i5; \
+ sljit_ins i3, i4, i5; \
\
SLJIT_ASSERT(have_genext()); \
- r1 = (sljit_ins)(dst & 0xf) << 36; \
- r2 = (sljit_ins)(src & 0xf) << 32; \
i3 = (sljit_ins)start << 24; \
i4 = (sljit_ins)end << 16; \
i5 = (sljit_ins)rot << 8; \
\
- return (pattern) | r1 | r2 | i3 | i4 | i5; \
+ return (pattern) | R36A(dst & 0xf) | R32A(src & 0xf) | i3 | i4 | i5; \
}
/* ROTATE THEN AND SELECTED BITS */
@@ -728,14 +749,12 @@ SLJIT_S390X_RIEF(risbhg, 0xec000000005d)
#define SLJIT_S390X_RRFC(name, pattern) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr dst, sljit_gpr src, sljit_uw mask) \
{ \
- sljit_ins r1, r2, m3; \
+ sljit_ins m3; \
\
SLJIT_ASSERT(have_lscond1()); \
- r1 = (sljit_ins)(dst & 0xf) << 4; \
- r2 = (sljit_ins)(src & 0xf); \
m3 = (sljit_ins)(mask & 0xf) << 12; \
\
- return (pattern) | m3 | r1 | r2; \
+ return (pattern) | m3 | R4A(dst) | R0A(src); \
}
/* LOAD HALFWORD IMMEDIATE ON CONDITION */
@@ -748,14 +767,13 @@ SLJIT_S390X_RRFC(locgr, 0xb9e20000)
#define SLJIT_S390X_RIEG(name, pattern) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw imm, sljit_uw mask) \
{ \
- sljit_ins r1, m3, i2; \
+ sljit_ins m3, i2; \
\
SLJIT_ASSERT(have_lscond2()); \
- r1 = (sljit_ins)(reg & 0xf) << 36; \
m3 = (sljit_ins)(mask & 0xf) << 32; \
i2 = (sljit_ins)(imm & 0xffffL) << 16; \
\
- return (pattern) | r1 | m3 | i2; \
+ return (pattern) | R36A(reg) | m3 | i2; \
}
/* LOAD HALFWORD IMMEDIATE ON CONDITION */
@@ -767,13 +785,9 @@ SLJIT_S390X_RIEG(locghi, 0xec0000000046)
#define SLJIT_S390X_RILB(name, pattern, cond) \
SLJIT_S390X_INSTRUCTION(name, sljit_gpr reg, sljit_sw ri) \
{ \
- sljit_ins r1, ri2; \
-\
SLJIT_ASSERT(cond); \
- r1 = (sljit_ins)(reg & 0xf) << 36; \
- ri2 = (sljit_ins)(ri & 0xffffffff); \
\
- return (pattern) | r1 | ri2; \
+ return (pattern) | R36A(reg) | (sljit_ins)(ri & 0xffffffff); \
}
/* BRANCH RELATIVE AND SAVE LONG */
@@ -808,22 +822,20 @@ SLJIT_S390X_INSTRUCTION(brcl, sljit_uw mask, sljit_sw target)
SLJIT_S390X_INSTRUCTION(flogr, sljit_gpr dst, sljit_gpr src)
{
- sljit_ins r1 = ((sljit_ins)dst & 0xf) << 8;
- sljit_ins r2 = ((sljit_ins)src & 0xf);
SLJIT_ASSERT(have_eimm());
- return 0xb9830000 | r1 | r2;
+ return 0xb9830000 | R8A(dst) | R0A(src);
}
/* INSERT PROGRAM MASK */
SLJIT_S390X_INSTRUCTION(ipm, sljit_gpr dst)
{
- return 0xb2220000 | ((sljit_ins)(dst & 0xf) << 4);
+ return 0xb2220000 | R4A(dst);
}
/* SET PROGRAM MASK */
SLJIT_S390X_INSTRUCTION(spm, sljit_gpr dst)
{
- return 0x0400 | ((sljit_ins)(dst & 0xf) << 4);
+ return 0x0400 | R4A(dst);
}
/* ROTATE THEN INSERT SELECTED BITS HIGH (ZERO) */
@@ -842,12 +854,12 @@ static sljit_s32 update_zero_overflow(struct sljit_compiler *compiler, sljit_s32
1 (non-zero and no overflow) : unchanged
2 (zero and overflow) : decreased by 1
3 (non-zero and overflow) : decreased by 1 if non-zero */
- FAIL_IF(push_inst(compiler, brc(0xc, 2 + 2 + ((op & SLJIT_I32_OP) ? 1 : 2) + 2 + 3 + 1)));
- FAIL_IF(push_inst(compiler, ipm(flag_r)));
- FAIL_IF(push_inst(compiler, (op & SLJIT_I32_OP) ? or(dst_r, dst_r) : ogr(dst_r, dst_r)));
+ FAIL_IF(push_inst(compiler, brc(0xc, 2 + 2 + ((op & SLJIT_32) ? 1 : 2) + 2 + 3 + 1)));
+ FAIL_IF(push_inst(compiler, ipm(tmp1)));
+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r)));
FAIL_IF(push_inst(compiler, brc(0x8, 2 + 3)));
- FAIL_IF(push_inst(compiler, slfi(flag_r, 0x10000000)));
- FAIL_IF(push_inst(compiler, spm(flag_r)));
+ FAIL_IF(push_inst(compiler, slfi(tmp1, 0x10000000)));
+ FAIL_IF(push_inst(compiler, spm(tmp1)));
return SLJIT_SUCCESS;
}
@@ -858,16 +870,16 @@ static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr t
if (is_s16(v))
return push_inst(compiler, lghi(target, (sljit_s16)v));
- if ((sljit_uw)v == (v & 0x000000000000ffffU))
+ if (((sljit_uw)v & ~(sljit_uw)0x000000000000ffff) == 0)
return push_inst(compiler, llill(target, (sljit_u16)v));
- if ((sljit_uw)v == (v & 0x00000000ffff0000U))
+ if (((sljit_uw)v & ~(sljit_uw)0x00000000ffff0000) == 0)
return push_inst(compiler, llilh(target, (sljit_u16)(v >> 16)));
- if ((sljit_uw)v == (v & 0x0000ffff00000000U))
+ if (((sljit_uw)v & ~(sljit_uw)0x0000ffff00000000) == 0)
return push_inst(compiler, llihl(target, (sljit_u16)(v >> 32)));
- if ((sljit_uw)v == (v & 0xffff000000000000U))
+ if (((sljit_uw)v & ~(sljit_uw)0xffff000000000000) == 0)
return push_inst(compiler, llihh(target, (sljit_u16)(v >> 48)));
/* 6 byte instructions (requires extended immediate facility) */
@@ -875,15 +887,16 @@ static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr t
if (is_s32(v))
return push_inst(compiler, lgfi(target, (sljit_s32)v));
- if ((sljit_uw)v == (v & 0x00000000ffffffffU))
+ if (((sljit_uw)v >> 32) == 0)
return push_inst(compiler, llilf(target, (sljit_u32)v));
- if ((sljit_uw)v == (v & 0xffffffff00000000U))
- return push_inst(compiler, llihf(target, (sljit_u32)(v >> 32)));
+ if (((sljit_uw)v << 32) == 0)
+ return push_inst(compiler, llihf(target, (sljit_u32)((sljit_uw)v >> 32)));
FAIL_IF(push_inst(compiler, llilf(target, (sljit_u32)v)));
return push_inst(compiler, iihf(target, (sljit_u32)(v >> 32)));
}
+
/* TODO(mundaym): instruction sequences that don't use extended immediates */
abort();
}
@@ -891,7 +904,7 @@ static sljit_s32 push_load_imm_inst(struct sljit_compiler *compiler, sljit_gpr t
struct addr {
sljit_gpr base;
sljit_gpr index;
- sljit_sw offset;
+ sljit_s32 offset;
};
/* transform memory operand into D(X,B) form with a signed 20-bit offset */
@@ -911,7 +924,7 @@ static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler,
if (off != 0) {
/* shift and put the result into tmp */
SLJIT_ASSERT(0 <= off && off < 64);
- FAIL_IF(push_inst(compiler, sllg(tmp, index, off, 0)));
+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));
index = tmp;
off = 0; /* clear offset */
}
@@ -923,7 +936,7 @@ static sljit_s32 make_addr_bxy(struct sljit_compiler *compiler,
}
addr->base = base;
addr->index = index;
- addr->offset = off;
+ addr->offset = (sljit_s32)off;
return SLJIT_SUCCESS;
}
@@ -944,7 +957,7 @@ static sljit_s32 make_addr_bx(struct sljit_compiler *compiler,
if (off != 0) {
/* shift and put the result into tmp */
SLJIT_ASSERT(0 <= off && off < 64);
- FAIL_IF(push_inst(compiler, sllg(tmp, index, off, 0)));
+ FAIL_IF(push_inst(compiler, sllg(tmp, index, (sljit_s32)off, 0)));
index = tmp;
off = 0; /* clear offset */
}
@@ -956,7 +969,7 @@ static sljit_s32 make_addr_bx(struct sljit_compiler *compiler,
}
addr->base = base;
addr->index = index;
- addr->offset = off;
+ addr->offset = (sljit_s32)off;
return SLJIT_SUCCESS;
}
@@ -1014,16 +1027,16 @@ static sljit_s32 emit_move(struct sljit_compiler *compiler,
sljit_gpr dst_r,
sljit_s32 src, sljit_sw srcw)
{
- SLJIT_ASSERT(!SLOW_IS_REG(src) || dst_r != gpr(src & REG_MASK));
+ SLJIT_ASSERT(!IS_GPR_REG(src) || dst_r != gpr(src & REG_MASK));
if (src & SLJIT_IMM)
return push_load_imm_inst(compiler, dst_r, srcw);
if (src & SLJIT_MEM)
- return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_I32_OP) != 0);
+ return load_word(compiler, dst_r, src, srcw, (compiler->mode & SLJIT_32) != 0);
sljit_gpr src_r = gpr(src & REG_MASK);
- return push_inst(compiler, (compiler->mode & SLJIT_I32_OP) ? lr(dst_r, src_r) : lgr(dst_r, src_r));
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, src_r) : lgr(dst_r, src_r));
}
static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,
@@ -1035,8 +1048,8 @@ static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,
sljit_gpr src_r = tmp1;
sljit_s32 needs_move = 1;
- if (SLOW_IS_REG(dst)) {
- dst_r = gpr(dst & REG_MASK);
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
if (dst == src1)
needs_move = 0;
@@ -1050,17 +1063,32 @@ static sljit_s32 emit_rr(struct sljit_compiler *compiler, sljit_ins ins,
FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
if (FAST_IS_REG(src2))
- src_r = gpr(src2 & REG_MASK);
+ src_r = gpr(src2);
else
FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
- FAIL_IF(push_inst(compiler, ins | (dst_r << 4) | src_r));
+ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | R0A(src_r)));
if (needs_move != 2)
return SLJIT_SUCCESS;
dst_r = gpr(dst & REG_MASK);
- return push_inst(compiler, (compiler->mode & SLJIT_I32_OP) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
+}
+
+static sljit_s32 emit_rr1(struct sljit_compiler *compiler, sljit_ins ins,
+ sljit_s32 dst,
+ sljit_s32 src1, sljit_sw src1w)
+{
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ sljit_gpr src_r = tmp1;
+
+ if (FAST_IS_REG(src1))
+ src_r = gpr(src1);
+ else
+ FAIL_IF(emit_move(compiler, tmp1, src1, src1w));
+
+ return push_inst(compiler, ins | R4A(dst_r) | R0A(src_r));
}
static sljit_s32 emit_rrf(struct sljit_compiler *compiler, sljit_ins ins,
@@ -1068,21 +1096,21 @@ static sljit_s32 emit_rrf(struct sljit_compiler *compiler, sljit_ins ins,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_gpr dst_r = SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
sljit_gpr src1_r = tmp0;
sljit_gpr src2_r = tmp1;
if (FAST_IS_REG(src1))
- src1_r = gpr(src1 & REG_MASK);
+ src1_r = gpr(src1);
else
FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
if (FAST_IS_REG(src2))
- src2_r = gpr(src2 & REG_MASK);
+ src2_r = gpr(src2);
else
FAIL_IF(emit_move(compiler, tmp1, src2, src2w));
- return push_inst(compiler, ins | (dst_r << 4) | src1_r | (src2_r << 12));
+ return push_inst(compiler, ins | R4A(dst_r) | R0A(src1_r) | R12A(src2_r));
}
typedef enum {
@@ -1099,8 +1127,8 @@ static sljit_s32 emit_ri(struct sljit_compiler *compiler, sljit_ins ins,
sljit_gpr dst_r = tmp0;
sljit_s32 needs_move = 1;
- if (SLOW_IS_REG(dst)) {
- dst_r = gpr(dst & REG_MASK);
+ if (FAST_IS_REG(dst)) {
+ dst_r = gpr(dst);
if (dst == src1)
needs_move = 0;
@@ -1110,8 +1138,8 @@ static sljit_s32 emit_ri(struct sljit_compiler *compiler, sljit_ins ins,
FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
if (type == RIL_A)
- return push_inst(compiler, ins | (dst_r << 36) | (src2w & 0xffffffff));
- return push_inst(compiler, ins | (dst_r << 20) | (src2w & 0xffff));
+ return push_inst(compiler, ins | R36A(dst_r) | (src2w & 0xffffffff));
+ return push_inst(compiler, ins | R20A(dst_r) | (src2w & 0xffff));
}
static sljit_s32 emit_rie_d(struct sljit_compiler *compiler, sljit_ins ins,
@@ -1119,15 +1147,15 @@ static sljit_s32 emit_rie_d(struct sljit_compiler *compiler, sljit_ins ins,
sljit_s32 src1, sljit_sw src1w,
sljit_sw src2w)
{
- sljit_gpr dst_r = SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
sljit_gpr src_r = tmp0;
- if (!SLOW_IS_REG(src1))
+ if (!FAST_IS_REG(src1))
FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
else
src_r = gpr(src1 & REG_MASK);
- return push_inst(compiler, ins | (dst_r << 36) | (src_r << 32) | (src2w & 0xffff) << 16);
+ return push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | (sljit_ins)(src2w & 0xffff) << 16);
}
typedef enum {
@@ -1147,7 +1175,7 @@ static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,
SLJIT_ASSERT(src2 & SLJIT_MEM);
- if (SLOW_IS_REG(dst)) {
+ if (FAST_IS_REG(dst)) {
dst_r = gpr(dst);
if (dst == src1)
@@ -1183,9 +1211,9 @@ static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,
}
if (type == RX_A)
- ins |= (dst_r << 20) | (index << 16) | (base << 12) | src2w;
+ ins |= R20A(dst_r) | R16A(index) | R12A(base) | (sljit_ins)src2w;
else
- ins |= (dst_r << 36) | (index << 32) | (base << 28) | disp_s20(src2w);
+ ins |= R36A(dst_r) | R32A(index) | R28A(base) | disp_s20((sljit_s32)src2w);
FAIL_IF(push_inst(compiler, ins));
@@ -1193,7 +1221,7 @@ static sljit_s32 emit_rx(struct sljit_compiler *compiler, sljit_ins ins,
return SLJIT_SUCCESS;
dst_r = gpr(dst);
- return push_inst(compiler, (compiler->mode & SLJIT_I32_OP) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
+ return push_inst(compiler, (compiler->mode & SLJIT_32) ? lr(dst_r, tmp0) : lgr(dst_r, tmp0));
}
static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins,
@@ -1226,7 +1254,7 @@ static sljit_s32 emit_siy(struct sljit_compiler *compiler, sljit_ins ins,
else
dst_r = gpr(dst & REG_MASK);
- return push_inst(compiler, ins | ((srcw & 0xff) << 32) | (dst_r << 28) | disp_s20(dstw));
+ return push_inst(compiler, ins | ((sljit_ins)(srcw & 0xff) << 32) | R28A(dst_r) | disp_s20((sljit_s32)dstw));
}
struct ins_forms {
@@ -1240,7 +1268,7 @@ struct ins_forms {
};
static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
@@ -1250,7 +1278,7 @@ static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct
if ((src1 | src2) & SLJIT_MEM) {
sljit_ins ins12, ins20;
- if (mode & SLJIT_I32_OP) {
+ if (mode & SLJIT_32) {
ins12 = forms->op;
ins20 = forms->op_y;
}
@@ -1297,7 +1325,7 @@ static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct
}
}
- if (mode & SLJIT_I32_OP) {
+ if (mode & SLJIT_32) {
ins = forms->op_r;
ins_k = forms->op_rk;
}
@@ -1308,7 +1336,7 @@ static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct
SLJIT_ASSERT(ins != 0 || ins_k != 0);
- if (ins && SLOW_IS_REG(dst)) {
+ if (ins && FAST_IS_REG(dst)) {
if (dst == src1)
return emit_rr(compiler, ins, dst, src1, src1w, src2, src2w);
@@ -1323,7 +1351,7 @@ static sljit_s32 emit_commutative(struct sljit_compiler *compiler, const struct
}
static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const struct ins_forms *forms,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
@@ -1333,7 +1361,7 @@ static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const str
if (src2 & SLJIT_MEM) {
sljit_ins ins12, ins20;
- if (mode & SLJIT_I32_OP) {
+ if (mode & SLJIT_32) {
ins12 = forms->op;
ins20 = forms->op_y;
}
@@ -1354,10 +1382,10 @@ static sljit_s32 emit_non_commutative(struct sljit_compiler *compiler, const str
return emit_rx(compiler, ins20, dst, src1, src1w, src2, src2w, RXY_A);
}
- ins = (mode & SLJIT_I32_OP) ? forms->op_rk : forms->op_grk;
+ ins = (mode & SLJIT_32) ? forms->op_rk : forms->op_grk;
- if (ins == 0 || (SLOW_IS_REG(dst) && dst == src1))
- return emit_rr(compiler, (mode & SLJIT_I32_OP) ? forms->op_r : forms->op_gr, dst, src1, src1w, src2, src2w);
+ if (ins == 0 || (FAST_IS_REG(dst) && dst == src1))
+ return emit_rr(compiler, (mode & SLJIT_32) ? forms->op_r : forms->op_gr, dst, src1, src1w, src2, src2w);
return emit_rrf(compiler, ins, dst, src1, src1w, src2, src2w);
}
@@ -1376,9 +1404,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
struct sljit_memory_fragment *buf;
void *code, *code_ptr;
sljit_uw *pool, *pool_ptr;
-
- sljit_uw source;
- sljit_sw offset; /* TODO(carenas): only need 32 bit */
+ sljit_sw source, offset; /* TODO(carenas): only need 32 bit */
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_generate_code(compiler));
@@ -1489,38 +1515,41 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
ins &= ~sljit_ins_const;
/* update instruction with relative address of constant */
- source = (sljit_uw)code_ptr;
- offset = (sljit_uw)pool_ptr - source;
+ source = (sljit_sw)code_ptr;
+ offset = (sljit_sw)pool_ptr - source;
+
SLJIT_ASSERT(!(offset & 1));
offset >>= 1; /* halfword (not byte) offset */
SLJIT_ASSERT(is_s32(offset));
+
ins |= (sljit_ins)offset & 0xffffffff;
/* update address */
const_->const_.addr = (sljit_uw)pool_ptr;
/* store initial value into pool and update pool address */
- *(pool_ptr++) = const_->init_value;
+ *(pool_ptr++) = (sljit_uw)const_->init_value;
/* move to next constant */
const_ = (struct sljit_s390x_const *)const_->const_.next;
}
if (jump && jump->addr == j) {
- sljit_sw target = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ sljit_sw target = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
if ((jump->flags & SLJIT_REWRITABLE_JUMP) || (jump->flags & JUMP_ADDR)) {
jump->addr = (sljit_uw)pool_ptr;
/* load address into tmp1 */
- source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- offset = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+
SLJIT_ASSERT(!(offset & 1));
offset >>= 1;
SLJIT_ASSERT(is_s32(offset));
- encode_inst(&code_ptr,
- lgrl(tmp1, offset & 0xffffffff));
+
+ encode_inst(&code_ptr, lgrl(tmp1, offset & 0xffffffff));
/* store jump target into pool and update pool address */
- *(pool_ptr++) = target;
+ *(pool_ptr++) = (sljit_uw)target;
/* branch to tmp1 */
sljit_ins op = (ins >> 32) & 0xf;
@@ -1538,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
else {
jump->addr = (sljit_uw)code_ptr + 2;
- source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
offset = target - source;
/* offset must be halfword aligned */
@@ -1552,14 +1581,14 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = jump->next;
}
if (put_label && put_label->addr == j) {
- source = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
+ source = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
SLJIT_ASSERT(put_label->label);
put_label->addr = (sljit_uw)code_ptr;
/* store target into pool */
*pool_ptr = put_label->label->addr;
- offset = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
+ offset = (sljit_sw)SLJIT_ADD_EXEC_OFFSET(pool_ptr, executable_offset) - source;
pool_ptr++;
SLJIT_ASSERT(!(offset & 1));
@@ -1594,7 +1623,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_CMOV:
return have_lscond1() ? 1 : 0;
case SLJIT_HAS_FPU:
- return 0;
+ return 1;
}
return 0;
}
@@ -1607,36 +1636,67 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args = get_arg_count(arg_types);
- sljit_sw frame_size;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 offset, i, tmp;
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- /* saved registers go in callee allocated save area */
- compiler->local_size = (local_size + 0xf) & ~0xf;
- frame_size = compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE;
+ /* Saved registers are stored in callee allocated save area. */
+ SLJIT_ASSERT(gpr(SLJIT_FIRST_SAVED_REG) == r6 && gpr(SLJIT_S0) == r13);
- FAIL_IF(push_inst(compiler, stmg(r6, r15, r6 * sizeof(sljit_sw), r15))); /* save registers TODO(MGM): optimize */
- if (frame_size != 0) {
- if (is_s16(-frame_size))
- FAIL_IF(push_inst(compiler, aghi(r15, -((sljit_s16)frame_size))));
- else if (is_s32(-frame_size))
- FAIL_IF(push_inst(compiler, agfi(r15, -((sljit_s32)frame_size))));
- else {
- FAIL_IF(push_load_imm_inst(compiler, tmp1, -frame_size));
- FAIL_IF(push_inst(compiler, la(r15, 0, tmp1, r15)));
+ offset = 2 * SSIZE_OF(sw);
+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {
+ FAIL_IF(push_inst(compiler, stmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */
+ offset += 9 * SSIZE_OF(sw);
+ } else {
+ if (scratches == SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, stg(r6, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, stmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));
+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);
}
+
+ if (saveds == 0) {
+ FAIL_IF(push_inst(compiler, stg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, stmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));
+ offset += (saveds + 1) * SSIZE_OF(sw);
+ }
+ }
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(push_inst(compiler, 0x60000000 /* std */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
}
- if (args >= 1)
- FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0), gpr(SLJIT_R0))));
- if (args >= 2)
- FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S1), gpr(SLJIT_R1))));
- if (args >= 3)
- FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S2), gpr(SLJIT_R2))));
- SLJIT_ASSERT(args < 4);
+ local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;
+ compiler->local_size = local_size;
+
+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(-local_size)));
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ tmp = 0;
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ FAIL_IF(push_inst(compiler, lgr(gpr(SLJIT_S0 - tmp), gpr(SLJIT_R0 + word_arg_count))));
+ tmp++;
+ }
+ word_arg_count++;
+ }
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
return SLJIT_SUCCESS;
}
@@ -1649,37 +1709,67 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
- /* TODO(mundaym): stack space for saved floating point registers */
- compiler->local_size = (local_size + 0xf) & ~0xf;
+ compiler->local_size = (local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + 0xf) & ~0xf;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
{
- sljit_sw size;
- sljit_gpr end;
+ sljit_s32 offset, i, tmp;
+ sljit_s32 local_size = compiler->local_size;
+ sljit_s32 saveds = compiler->saveds;
+ sljit_s32 scratches = compiler->scratches;
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+ if (is_u12(local_size))
+ FAIL_IF(push_inst(compiler, 0x41000000 /* ly */ | R20A(r15) | R12A(r15) | (sljit_ins)local_size));
+ else
+ FAIL_IF(push_inst(compiler, 0xe30000000071 /* lay */ | R36A(r15) | R28A(r15) | disp_s20(local_size)));
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ offset = 2 * SSIZE_OF(sw);
+ if (saveds + scratches >= SLJIT_NUMBER_OF_REGISTERS) {
+ FAIL_IF(push_inst(compiler, lmg(r6, r14, offset, r15))); /* save registers TODO(MGM): optimize */
+ offset += 9 * SSIZE_OF(sw);
+ } else {
+ if (scratches == SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, lg(r6, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else if (scratches > SLJIT_FIRST_SAVED_REG) {
+ FAIL_IF(push_inst(compiler, lmg(r6, r6 + (sljit_gpr)(scratches - SLJIT_FIRST_SAVED_REG), offset, r15)));
+ offset += (scratches - (SLJIT_FIRST_SAVED_REG - 1)) * SSIZE_OF(sw);
+ }
- size = compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE + (r6 * sizeof(sljit_sw));
- if (!is_s20(size)) {
- FAIL_IF(push_load_imm_inst(compiler, tmp1, compiler->local_size + SLJIT_S390X_DEFAULT_STACK_FRAME_SIZE));
- FAIL_IF(push_inst(compiler, la(r15, 0, tmp1, r15)));
- size = r6 * sizeof(sljit_sw);
- end = r14; /* r15 has been restored already */
+ if (saveds == 0) {
+ FAIL_IF(push_inst(compiler, lg(r14, offset, 0, r15)));
+ offset += SSIZE_OF(sw);
+ } else {
+ FAIL_IF(push_inst(compiler, lmg(r14 - (sljit_gpr)saveds, r14, offset, r15)));
+ offset += (saveds + 1) * SSIZE_OF(sw);
+ }
}
- else
- end = r15;
- FAIL_IF(push_inst(compiler, lmg(r6, end, size, r15))); /* restore registers TODO(MGM): optimize */
- FAIL_IF(push_inst(compiler, br(r14))); /* return */
+ tmp = SLJIT_FS0 - compiler->fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
+
+ for (i = compiler->fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ FAIL_IF(push_inst(compiler, 0x68000000 /* ld */ | F20(i) | R12A(r15) | (sljit_ins)offset));
+ offset += SSIZE_OF(sw);
+ }
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ return push_inst(compiler, br(r14)); /* return */
+}
+
/* --------------------------------------------------------------------- */
/* Operators */
/* --------------------------------------------------------------------- */
@@ -1692,7 +1782,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
CHECK_ERROR();
CHECK(check_sljit_emit_op0(compiler, op));
- op = GET_OPCODE(op) | (op & SLJIT_I32_OP);
+ op = GET_OPCODE(op) | (op & SLJIT_32);
switch (op) {
case SLJIT_BREAKPOINT:
/* The following invalid instruction is emitted by gdb. */
@@ -1786,17 +1876,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src, srcw);
- if ((dst == SLJIT_UNUSED) && !HAS_FLAGS(op)) {
- /* TODO(carenas): implement prefetch? */
- return SLJIT_SUCCESS;
- }
-
if (opcode >= SLJIT_MOV && opcode <= SLJIT_MOV_P) {
/* LOAD REGISTER */
if (FAST_IS_REG(dst) && FAST_IS_REG(src)) {
dst_r = gpr(dst);
src_r = gpr(src);
- switch (opcode | (op & SLJIT_I32_OP)) {
+ switch (opcode | (op & SLJIT_32)) {
/* 32-bit */
case SLJIT_MOV32_U8:
ins = llcr(dst_r, src_r);
@@ -1811,6 +1896,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ins = lhr(dst_r, src_r);
break;
case SLJIT_MOV32:
+ if (dst_r == src_r)
+ return SLJIT_SUCCESS;
ins = lr(dst_r, src_r);
break;
/* 64-bit */
@@ -1834,11 +1921,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
break;
case SLJIT_MOV:
case SLJIT_MOV_P:
+ if (dst_r == src_r)
+ return SLJIT_SUCCESS;
ins = lgr(dst_r, src_r);
break;
default:
ins = 0;
SLJIT_UNREACHABLE();
+ break;
}
FAIL_IF(push_inst(compiler, ins));
return SLJIT_SUCCESS;
@@ -1862,6 +1952,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
srcw = (sljit_sw)((sljit_u32)(srcw));
break;
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
srcw = (sljit_sw)((sljit_s32)(srcw));
break;
}
@@ -1875,7 +1966,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
FAIL_IF(make_addr_bxy(compiler, &mem, src, srcw, tmp1));
/* TODO(carenas): convert all calls below to LEVAL */
- switch (opcode | (op & SLJIT_I32_OP)) {
+ switch (opcode | (op & SLJIT_32)) {
case SLJIT_MOV32_U8:
ins = llc(reg, mem.offset, mem.index, mem.base);
break;
@@ -1914,7 +2005,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
ins = lg(reg, mem.offset, mem.index, mem.base);
break;
default:
+ ins = 0;
SLJIT_UNREACHABLE();
+ break;
}
FAIL_IF(push_inst(compiler, ins));
return SLJIT_SUCCESS;
@@ -1940,6 +2033,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
WHEN2(is_u12(mem.offset), sth, sthy));
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
return push_inst(compiler,
WHEN2(is_u12(mem.offset), st, sty));
case SLJIT_MOV_P:
@@ -1972,6 +2066,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
EVAL(sthy, tmp0, mem));
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
FAIL_IF(push_inst(compiler,
EVAL(ly, tmp0, mem)));
FAIL_IF(make_addr_bxy(compiler, &mem, dst, dstw, tmp1));
@@ -1994,15 +2089,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
SLJIT_ASSERT((src & SLJIT_IMM) == 0); /* no immediates */
- dst_r = SLOW_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0;
+ dst_r = FAST_IS_REG(dst) ? gpr(REG_MASK & dst) : tmp0;
src_r = FAST_IS_REG(src) ? gpr(REG_MASK & src) : tmp0;
if (src & SLJIT_MEM)
- FAIL_IF(load_word(compiler, src_r, src, srcw, src & SLJIT_I32_OP));
+ FAIL_IF(load_word(compiler, src_r, src, srcw, src & SLJIT_32));
compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);
/* TODO(mundaym): optimize loads and stores */
- switch (opcode | (op & SLJIT_I32_OP)) {
+ switch (opcode | (op & SLJIT_32)) {
case SLJIT_NOT:
/* emulate ~x with x^-1 */
FAIL_IF(push_load_imm_inst(compiler, tmp1, -1));
@@ -2014,7 +2109,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_NOT32:
/* emulate ~x with x^-1 */
if (have_eimm())
- FAIL_IF(push_inst(compiler, xilf(dst_r, -1)));
+ FAIL_IF(push_inst(compiler, xilf(dst_r, 0xffffffff)));
else {
FAIL_IF(push_load_imm_inst(compiler, tmp1, -1));
if (src_r != dst_r)
@@ -2023,14 +2118,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
FAIL_IF(push_inst(compiler, xr(dst_r, tmp1)));
}
break;
- case SLJIT_NEG:
- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD_SUB;
- FAIL_IF(push_inst(compiler, lcgr(dst_r, src_r)));
- break;
- case SLJIT_NEG32:
- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD_SUB;
- FAIL_IF(push_inst(compiler, lcr(dst_r, src_r)));
- break;
case SLJIT_CLZ:
if (have_eimm()) {
FAIL_IF(push_inst(compiler, flogr(tmp0, src_r))); /* clobbers tmp1 */
@@ -2059,8 +2146,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
FAIL_IF(update_zero_overflow(compiler, op, dst_r));
/* TODO(carenas): doesn't need FAIL_IF */
- if ((dst != SLJIT_UNUSED) && (dst & SLJIT_MEM))
- FAIL_IF(store_word(compiler, dst_r, dst, dstw, op & SLJIT_I32_OP));
+ if (dst & SLJIT_MEM)
+ FAIL_IF(store_word(compiler, dst_r, dst, dstw, op & SLJIT_32));
return SLJIT_SUCCESS;
}
@@ -2084,20 +2171,6 @@ static SLJIT_INLINE int is_shift(sljit_s32 op) {
return (v == SLJIT_SHL || v == SLJIT_ASHR || v == SLJIT_LSHR) ? 1 : 0;
}
-static SLJIT_INLINE int sets_signed_flag(sljit_s32 op)
-{
- switch (GET_FLAG_TYPE(op)) {
- case SLJIT_OVERFLOW:
- case SLJIT_NOT_OVERFLOW:
- case SLJIT_SIG_LESS:
- case SLJIT_SIG_LESS_EQUAL:
- case SLJIT_SIG_GREATER:
- case SLJIT_SIG_GREATER_EQUAL:
- return 1;
- }
- return 0;
-}
-
static const struct ins_forms add_forms = {
0x1a00, /* ar */
0xb9080000, /* agr */
@@ -2131,24 +2204,24 @@ static sljit_s32 sljit_emit_add(struct sljit_compiler *compiler, sljit_s32 op,
if (src2 & SLJIT_IMM) {
if (!sets_zero_overflow && is_s8(src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {
if (sets_overflow)
- ins = (op & SLJIT_I32_OP) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
else
- ins = (op & SLJIT_I32_OP) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
return emit_siy(compiler, ins, dst, dstw, src2w);
}
if (is_s16(src2w)) {
if (sets_overflow)
- ins = (op & SLJIT_I32_OP) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
else
- ins = (op & SLJIT_I32_OP) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, src2w));
goto done;
}
if (!sets_overflow) {
- if ((op & SLJIT_I32_OP) || is_u32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20b00000000 /* alfi */ : 0xc20a00000000 /* algfi */;
+ if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20b00000000 /* alfi */ : 0xc20a00000000 /* algfi */;
FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
goto done;
}
@@ -2157,22 +2230,22 @@ static sljit_s32 sljit_emit_add(struct sljit_compiler *compiler, sljit_s32 op,
goto done;
}
}
- else if ((op & SLJIT_I32_OP) || is_s32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
+ else if ((op & SLJIT_32) || is_s32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
goto done;
}
}
forms = sets_overflow ? &add_forms : &logical_add_forms;
- FAIL_IF(emit_commutative(compiler, forms, dst, dstw, src1, src1w, src2, src2w));
+ FAIL_IF(emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w));
done:
if (sets_zero_overflow)
- FAIL_IF(update_zero_overflow(compiler, op, SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0));
+ FAIL_IF(update_zero_overflow(compiler, op, FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0));
if (dst & SLJIT_MEM)
- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
return SLJIT_SUCCESS;
}
@@ -2202,78 +2275,85 @@ static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- int sets_signed = sets_signed_flag(op);
+ sljit_s32 flag_type = GET_FLAG_TYPE(op);
+ int sets_signed = (flag_type >= SLJIT_SIG_LESS && flag_type <= SLJIT_NOT_OVERFLOW);
int sets_zero_overflow = (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == (SLJIT_SET_Z | SLJIT_SET_OVERFLOW);
const struct ins_forms *forms;
sljit_ins ins;
- if (dst == SLJIT_UNUSED && GET_FLAG_TYPE(op) <= SLJIT_SIG_LESS_EQUAL) {
- int compare_signed = GET_FLAG_TYPE(op) >= SLJIT_SIG_LESS;
+ if (dst == (sljit_s32)tmp0 && flag_type <= SLJIT_SIG_LESS_EQUAL) {
+ int compare_signed = flag_type >= SLJIT_SIG_LESS;
compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_COMPARE;
if (src2 & SLJIT_IMM) {
if (compare_signed || ((op & VARIABLE_FLAG_MASK) == 0 && is_s32(src2w)))
{
- if ((op & SLJIT_I32_OP) || is_s32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;
+ if ((op & SLJIT_32) || is_s32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20d00000000 /* cfi */ : 0xc20c00000000 /* cgfi */;
return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);
}
}
else {
- if ((op & SLJIT_I32_OP) || is_u32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;
+ if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20f00000000 /* clfi */ : 0xc20e00000000 /* clgfi */;
return emit_ri(compiler, ins, src1, src1, src1w, src2w, RIL_A);
}
if (is_s16(src2w))
- return emit_rie_d(compiler, 0xec00000000db /* alghsik */, SLJIT_UNUSED, src1, src1w, src2w);
+ return emit_rie_d(compiler, 0xec00000000db /* alghsik */, (sljit_s32)tmp0, src1, src1w, src2w);
}
}
else if (src2 & SLJIT_MEM) {
- if ((op & SLJIT_I32_OP) && ((src2 & OFFS_REG_MASK) || is_u12(src2w))) {
+ if ((op & SLJIT_32) && ((src2 & OFFS_REG_MASK) || is_u12(src2w))) {
ins = compare_signed ? 0x59000000 /* c */ : 0x55000000 /* cl */;
return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RX_A);
}
if (compare_signed)
- ins = (op & SLJIT_I32_OP) ? 0xe30000000059 /* cy */ : 0xe30000000020 /* cg */;
+ ins = (op & SLJIT_32) ? 0xe30000000059 /* cy */ : 0xe30000000020 /* cg */;
else
- ins = (op & SLJIT_I32_OP) ? 0xe30000000055 /* cly */ : 0xe30000000021 /* clg */;
+ ins = (op & SLJIT_32) ? 0xe30000000055 /* cly */ : 0xe30000000021 /* clg */;
return emit_rx(compiler, ins, src1, src1, src1w, src2, src2w, RXY_A);
}
if (compare_signed)
- ins = (op & SLJIT_I32_OP) ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;
+ ins = (op & SLJIT_32) ? 0x1900 /* cr */ : 0xb9200000 /* cgr */;
else
- ins = (op & SLJIT_I32_OP) ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;
+ ins = (op & SLJIT_32) ? 0x1500 /* clr */ : 0xb9210000 /* clgr */;
return emit_rr(compiler, ins, src1, src1, src1w, src2, src2w);
}
+ if (src1 == SLJIT_IMM && src1w == 0 && (flag_type == 0 || sets_signed)) {
+ ins = (op & SLJIT_32) ? 0x1300 /* lcr */ : 0xb9030000 /* lcgr */;
+ FAIL_IF(emit_rr1(compiler, ins, dst, src2, src2w));
+ goto done;
+ }
+
if (src2 & SLJIT_IMM) {
sljit_sw neg_src2w = -src2w;
if (sets_signed || neg_src2w != 0 || (op & (SLJIT_SET_Z | VARIABLE_FLAG_MASK)) == 0) {
if (!sets_zero_overflow && is_s8(neg_src2w) && (src1 & SLJIT_MEM) && (dst == src1 && dstw == src1w)) {
if (sets_signed)
- ins = (op & SLJIT_I32_OP) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
+ ins = (op & SLJIT_32) ? 0xeb000000006a /* asi */ : 0xeb000000007a /* agsi */;
else
- ins = (op & SLJIT_I32_OP) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
+ ins = (op & SLJIT_32) ? 0xeb000000006e /* alsi */ : 0xeb000000007e /* algsi */;
return emit_siy(compiler, ins, dst, dstw, neg_src2w);
}
if (is_s16(neg_src2w)) {
if (sets_signed)
- ins = (op & SLJIT_I32_OP) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
+ ins = (op & SLJIT_32) ? 0xec00000000d8 /* ahik */ : 0xec00000000d9 /* aghik */;
else
- ins = (op & SLJIT_I32_OP) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
+ ins = (op & SLJIT_32) ? 0xec00000000da /* alhsik */ : 0xec00000000db /* alghsik */;
FAIL_IF(emit_rie_d(compiler, ins, dst, src1, src1w, neg_src2w));
goto done;
}
}
if (!sets_signed) {
- if ((op & SLJIT_I32_OP) || is_u32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20500000000 /* slfi */ : 0xc20400000000 /* slgfi */;
+ if ((op & SLJIT_32) || is_u32(src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20500000000 /* slfi */ : 0xc20400000000 /* slgfi */;
FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A));
goto done;
}
@@ -2282,19 +2362,19 @@ static sljit_s32 sljit_emit_sub(struct sljit_compiler *compiler, sljit_s32 op,
goto done;
}
}
- else if ((op & SLJIT_I32_OP) || is_s32(neg_src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
+ else if ((op & SLJIT_32) || is_s32(neg_src2w)) {
+ ins = (op & SLJIT_32) ? 0xc20900000000 /* afi */ : 0xc20800000000 /* agfi */;
FAIL_IF(emit_ri(compiler, ins, dst, src1, src1w, neg_src2w, RIL_A));
goto done;
}
}
forms = sets_signed ? &sub_forms : &logical_sub_forms;
- FAIL_IF(emit_non_commutative(compiler, forms, dst, dstw, src1, src1w, src2, src2w));
+ FAIL_IF(emit_non_commutative(compiler, forms, dst, src1, src1w, src2, src2w));
done:
if (sets_signed) {
- sljit_gpr dst_r = SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
if ((op & VARIABLE_FLAG_MASK) != SLJIT_SET_OVERFLOW) {
/* In case of overflow, the sign bit of the two source operands must be different, and
@@ -2303,14 +2383,14 @@ done:
The -result operation sets the corrent sign, because the result cannot be zero.
The overflow is considered greater, since the result must be equal to INT_MIN so its sign bit is set. */
FAIL_IF(push_inst(compiler, brc(0xe, 2 + 2)));
- FAIL_IF(push_inst(compiler, (op & SLJIT_I32_OP) ? lcr(tmp1, dst_r) : lcgr(tmp1, dst_r)));
+ FAIL_IF(push_inst(compiler, (op & SLJIT_32) ? lcr(tmp1, dst_r) : lcgr(tmp1, dst_r)));
}
else if (op & SLJIT_SET_Z)
FAIL_IF(update_zero_overflow(compiler, op, dst_r));
}
if (dst & SLJIT_MEM)
- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
return SLJIT_SUCCESS;
}
@@ -2336,7 +2416,7 @@ static const struct ins_forms multiply_overflow_forms = {
};
static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32 op,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
@@ -2351,29 +2431,29 @@ static sljit_s32 sljit_emit_multiply(struct sljit_compiler *compiler, sljit_s32
}
FAIL_IF(push_inst(compiler, aih(tmp0, 1)));
FAIL_IF(push_inst(compiler, nihf(tmp0, ~1U)));
- FAIL_IF(push_inst(compiler, ipm(flag_r)));
- FAIL_IF(push_inst(compiler, oilh(flag_r, 0x2000))); */
+ FAIL_IF(push_inst(compiler, ipm(tmp1)));
+ FAIL_IF(push_inst(compiler, oilh(tmp1, 0x2000))); */
- return emit_commutative(compiler, &multiply_overflow_forms, dst, dstw, src1, src1w, src2, src2w);
+ return emit_commutative(compiler, &multiply_overflow_forms, dst, src1, src1w, src2, src2w);
}
if (src2 & SLJIT_IMM) {
if (is_s16(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */;
+ ins = (op & SLJIT_32) ? 0xa70c0000 /* mhi */ : 0xa70d0000 /* mghi */;
return emit_ri(compiler, ins, dst, src1, src1w, src2w, RI_A);
}
if (is_s32(src2w)) {
- ins = (op & SLJIT_I32_OP) ? 0xc20100000000 /* msfi */ : 0xc20000000000 /* msgfi */;
+ ins = (op & SLJIT_32) ? 0xc20100000000 /* msfi */ : 0xc20000000000 /* msgfi */;
return emit_ri(compiler, ins, dst, src1, src1w, src2w, RIL_A);
}
}
- return emit_commutative(compiler, &multiply_forms, dst, dstw, src1, src1w, src2, src2w);
+ return emit_commutative(compiler, &multiply_forms, dst, src1, src1w, src2, src2w);
}
static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s32 type,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_uw imm, sljit_s32 count16)
{
@@ -2381,7 +2461,7 @@ static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s
sljit_gpr dst_r = tmp0;
sljit_s32 needs_move = 1;
- if (SLOW_IS_REG(dst)) {
+ if (IS_GPR_REG(dst)) {
dst_r = gpr(dst & REG_MASK);
if (dst == src1)
needs_move = 0;
@@ -2391,38 +2471,38 @@ static sljit_s32 sljit_emit_bitwise_imm(struct sljit_compiler *compiler, sljit_s
FAIL_IF(emit_move(compiler, dst_r, src1, src1w));
if (type == SLJIT_AND) {
- if (!(mode & SLJIT_I32_OP))
- FAIL_IF(push_inst(compiler, 0xc00a00000000 /* nihf */ | (dst_r << 36) | (imm >> 32)));
- return push_inst(compiler, 0xc00b00000000 /* nilf */ | (dst_r << 36) | (imm & 0xffffffff));
+ if (!(mode & SLJIT_32))
+ FAIL_IF(push_inst(compiler, 0xc00a00000000 /* nihf */ | R36A(dst_r) | (imm >> 32)));
+ return push_inst(compiler, 0xc00b00000000 /* nilf */ | R36A(dst_r) | (imm & 0xffffffff));
}
else if (type == SLJIT_OR) {
if (count16 >= 3) {
- FAIL_IF(push_inst(compiler, 0xc00c00000000 /* oihf */ | (dst_r << 36) | (imm >> 32)));
- return push_inst(compiler, 0xc00d00000000 /* oilf */ | (dst_r << 36) | (imm & 0xffffffff));
+ FAIL_IF(push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32)));
+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));
}
if (count16 >= 2) {
if ((imm & 0x00000000ffffffffull) == 0)
- return push_inst(compiler, 0xc00c00000000 /* oihf */ | (dst_r << 36) | (imm >> 32));
+ return push_inst(compiler, 0xc00c00000000 /* oihf */ | R36A(dst_r) | (imm >> 32));
if ((imm & 0xffffffff00000000ull) == 0)
- return push_inst(compiler, 0xc00d00000000 /* oilf */ | (dst_r << 36) | (imm & 0xffffffff));
+ return push_inst(compiler, 0xc00d00000000 /* oilf */ | R36A(dst_r) | (imm & 0xffffffff));
}
if ((imm & 0xffff000000000000ull) != 0)
- FAIL_IF(push_inst(compiler, 0xa5080000 /* oihh */ | (dst_r << 20) | (imm >> 48)));
+ FAIL_IF(push_inst(compiler, 0xa5080000 /* oihh */ | R20A(dst_r) | (imm >> 48)));
if ((imm & 0x0000ffff00000000ull) != 0)
- FAIL_IF(push_inst(compiler, 0xa5090000 /* oihl */ | (dst_r << 20) | ((imm >> 32) & 0xffff)));
+ FAIL_IF(push_inst(compiler, 0xa5090000 /* oihl */ | R20A(dst_r) | ((imm >> 32) & 0xffff)));
if ((imm & 0x00000000ffff0000ull) != 0)
- FAIL_IF(push_inst(compiler, 0xa50a0000 /* oilh */ | (dst_r << 20) | ((imm >> 16) & 0xffff)));
+ FAIL_IF(push_inst(compiler, 0xa50a0000 /* oilh */ | R20A(dst_r) | ((imm >> 16) & 0xffff)));
if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
- return push_inst(compiler, 0xa50b0000 /* oill */ | (dst_r << 20) | (imm & 0xffff));
+ return push_inst(compiler, 0xa50b0000 /* oill */ | R20A(dst_r) | (imm & 0xffff));
return SLJIT_SUCCESS;
}
if ((imm & 0xffffffff00000000ull) != 0)
- FAIL_IF(push_inst(compiler, 0xc00600000000 /* xihf */ | (dst_r << 36) | (imm >> 32)));
+ FAIL_IF(push_inst(compiler, 0xc00600000000 /* xihf */ | R36A(dst_r) | (imm >> 32)));
if ((imm & 0x00000000ffffffffull) != 0 || imm == 0)
- return push_inst(compiler, 0xc00700000000 /* xilf */ | (dst_r << 36) | (imm & 0xffffffff));
+ return push_inst(compiler, 0xc00700000000 /* xilf */ | R36A(dst_r) | (imm & 0xffffffff));
return SLJIT_SUCCESS;
}
@@ -2457,18 +2537,18 @@ static const struct ins_forms bitwise_xor_forms = {
};
static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 op,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
sljit_s32 type = GET_OPCODE(op);
const struct ins_forms *forms;
- if ((src2 & SLJIT_IMM) && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == SLJIT_UNUSED))) {
+ if ((src2 & SLJIT_IMM) && (!(op & SLJIT_SET_Z) || (type == SLJIT_AND && dst == (sljit_s32)tmp0))) {
sljit_s32 count16 = 0;
sljit_uw imm = (sljit_uw)src2w;
- if (op & SLJIT_I32_OP)
+ if (op & SLJIT_32)
imm &= 0xffffffffull;
if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
@@ -2480,7 +2560,7 @@ static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 o
if ((imm & 0xffff000000000000ull) != 0)
count16++;
- if (type == SLJIT_AND && dst == SLJIT_UNUSED && count16 == 1) {
+ if (type == SLJIT_AND && dst == (sljit_s32)tmp0 && count16 == 1) {
sljit_gpr src_r = tmp0;
if (FAST_IS_REG(src1))
@@ -2489,16 +2569,16 @@ static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 o
FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
if ((imm & 0x000000000000ffffull) != 0 || imm == 0)
- return push_inst(compiler, 0xa7010000 | (src_r << 20) | imm);
+ return push_inst(compiler, 0xa7010000 | R20A(src_r) | imm);
if ((imm & 0x00000000ffff0000ull) != 0)
- return push_inst(compiler, 0xa7000000 | (src_r << 20) | (imm >> 16));
+ return push_inst(compiler, 0xa7000000 | R20A(src_r) | (imm >> 16));
if ((imm & 0x0000ffff00000000ull) != 0)
- return push_inst(compiler, 0xa7030000 | (src_r << 20) | (imm >> 32));
- return push_inst(compiler, 0xa7020000 | (src_r << 20) | (imm >> 48));
+ return push_inst(compiler, 0xa7030000 | R20A(src_r) | (imm >> 32));
+ return push_inst(compiler, 0xa7020000 | R20A(src_r) | (imm >> 48));
}
if (!(op & SLJIT_SET_Z))
- return sljit_emit_bitwise_imm(compiler, type, dst, dstw, src1, src1w, imm, count16);
+ return sljit_emit_bitwise_imm(compiler, type, dst, src1, src1w, imm, count16);
}
if (type == SLJIT_AND)
@@ -2508,16 +2588,16 @@ static sljit_s32 sljit_emit_bitwise(struct sljit_compiler *compiler, sljit_s32 o
else
forms = &bitwise_xor_forms;
- return emit_commutative(compiler, forms, dst, dstw, src1, src1w, src2, src2w);
+ return emit_commutative(compiler, forms, dst, src1, src1w, src2, src2w);
}
static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,
- sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 dst,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
sljit_s32 type = GET_OPCODE(op);
- sljit_gpr dst_r = SLOW_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
+ sljit_gpr dst_r = FAST_IS_REG(dst) ? gpr(dst & REG_MASK) : tmp0;
sljit_gpr src_r = tmp0;
sljit_gpr base_r = tmp0;
sljit_ins imm = 0;
@@ -2529,7 +2609,7 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,
FAIL_IF(emit_move(compiler, tmp0, src1, src1w));
if (src2 & SLJIT_IMM)
- imm = src2w & ((op & SLJIT_I32_OP) ? 0x1f : 0x3f);
+ imm = (sljit_ins)(src2w & ((op & SLJIT_32) ? 0x1f : 0x3f));
else if (FAST_IS_REG(src2))
base_r = gpr(src2 & REG_MASK);
else {
@@ -2537,7 +2617,7 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,
base_r = tmp1;
}
- if ((op & SLJIT_I32_OP) && dst_r == src_r) {
+ if ((op & SLJIT_32) && dst_r == src_r) {
if (type == SLJIT_SHL)
ins = 0x89000000 /* sll */;
else if (type == SLJIT_LSHR)
@@ -2545,21 +2625,21 @@ static sljit_s32 sljit_emit_shift(struct sljit_compiler *compiler, sljit_s32 op,
else
ins = 0x8a000000 /* sra */;
- FAIL_IF(push_inst(compiler, ins | (dst_r << 20) | (base_r << 12) | imm));
+ FAIL_IF(push_inst(compiler, ins | R20A(dst_r) | R12A(base_r) | imm));
}
else {
if (type == SLJIT_SHL)
- ins = (op & SLJIT_I32_OP) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */;
+ ins = (op & SLJIT_32) ? 0xeb00000000df /* sllk */ : 0xeb000000000d /* sllg */;
else if (type == SLJIT_LSHR)
- ins = (op & SLJIT_I32_OP) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */;
+ ins = (op & SLJIT_32) ? 0xeb00000000de /* srlk */ : 0xeb000000000c /* srlg */;
else
- ins = (op & SLJIT_I32_OP) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */;
+ ins = (op & SLJIT_32) ? 0xeb00000000dc /* srak */ : 0xeb000000000a /* srag */;
- FAIL_IF(push_inst(compiler, ins | (dst_r << 36) | (src_r << 32) | (base_r << 28) | (imm << 16)));
+ FAIL_IF(push_inst(compiler, ins | R36A(dst_r) | R32A(src_r) | R28A(base_r) | (imm << 16)));
}
if ((op & SLJIT_SET_Z) && type != SLJIT_ASHR)
- return push_inst(compiler, (op & SLJIT_I32_OP) ? or(dst_r, dst_r) : ogr(dst_r, dst_r));
+ return push_inst(compiler, (op & SLJIT_32) ? or(dst_r, dst_r) : ogr(dst_r, dst_r));
return SLJIT_SUCCESS;
}
@@ -2590,20 +2670,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src2, sljit_sw src2w)
{
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
- compiler->mode = op & SLJIT_I32_OP;
+ compiler->mode = op & SLJIT_32;
compiler->status_flags_state = op & (VARIABLE_FLAG_MASK | SLJIT_SET_Z);
- if (GET_OPCODE(op) >= SLJIT_ADD || GET_OPCODE(op) <= SLJIT_SUBC)
- compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD_SUB;
-
if (is_commutative(op) && (src1 & SLJIT_IMM) && !(src2 & SLJIT_IMM)) {
src1 ^= src2;
src2 ^= src1;
@@ -2616,39 +2690,57 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;
return sljit_emit_add(compiler, op, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_ADDC:
- FAIL_IF(emit_commutative(compiler, &addc_forms, dst, dstw, src1, src1w, src2, src2w));
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_ADD;
+ FAIL_IF(emit_commutative(compiler, &addc_forms, dst, src1, src1w, src2, src2w));
if (dst & SLJIT_MEM)
- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
return SLJIT_SUCCESS;
case SLJIT_SUB:
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;
return sljit_emit_sub(compiler, op, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
- FAIL_IF(emit_non_commutative(compiler, &subc_forms, dst, dstw, src1, src1w, src2, src2w));
+ compiler->status_flags_state |= SLJIT_CURRENT_FLAGS_SUB;
+ FAIL_IF(emit_non_commutative(compiler, &subc_forms, dst, src1, src1w, src2, src2w));
if (dst & SLJIT_MEM)
- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
return SLJIT_SUCCESS;
case SLJIT_MUL:
- FAIL_IF(sljit_emit_multiply(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ FAIL_IF(sljit_emit_multiply(compiler, op, dst, src1, src1w, src2, src2w));
break;
case SLJIT_AND:
case SLJIT_OR:
case SLJIT_XOR:
- FAIL_IF(sljit_emit_bitwise(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ FAIL_IF(sljit_emit_bitwise(compiler, op, dst, src1, src1w, src2, src2w));
break;
case SLJIT_SHL:
case SLJIT_LSHR:
case SLJIT_ASHR:
- FAIL_IF(sljit_emit_shift(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ FAIL_IF(sljit_emit_shift(compiler, op, dst, src1, src1w, src2, src2w));
break;
}
if (dst & SLJIT_MEM)
- return store_word(compiler, tmp0, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, tmp0, dst, dstw, op & SLJIT_32);
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, (sljit_s32)tmp0, 0, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(
struct sljit_compiler *compiler,
sljit_s32 op, sljit_s32 src, sljit_sw srcw)
@@ -2686,17 +2778,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_register_index(reg));
- return gpr(reg);
+ return (sljit_s32)gpr(reg);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
{
CHECK_REG_INDEX(check_sljit_get_float_register_index(reg));
- abort();
+ return (sljit_s32)fgpr(reg);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
sljit_ins ins = 0;
@@ -2711,21 +2803,254 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
+#define FLOAT_LOAD 0
+#define FLOAT_STORE 1
+
+static sljit_s32 float_mem(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 reg,
+ sljit_s32 mem, sljit_sw memw)
+{
+ struct addr addr;
+ sljit_ins ins;
+
+ SLJIT_ASSERT(mem & SLJIT_MEM);
+
+ if ((mem & OFFS_REG_MASK) || is_u12(memw) || !is_s20(memw)) {
+ FAIL_IF(make_addr_bx(compiler, &addr, mem, memw, tmp1));
+
+ if (op & FLOAT_STORE)
+ ins = (op & SLJIT_32) ? 0x70000000 /* ste */ : 0x60000000 /* std */;
+ else
+ ins = (op & SLJIT_32) ? 0x78000000 /* le */ : 0x68000000 /* ld */;
+
+ return push_inst(compiler, ins | F20(reg) | R16A(addr.index) | R12A(addr.base) | (sljit_ins)addr.offset);
+ }
+
+ FAIL_IF(make_addr_bxy(compiler, &addr, mem, memw, tmp1));
+
+ if (op & FLOAT_STORE)
+ ins = (op & SLJIT_32) ? 0xed0000000066 /* stey */ : 0xed0000000067 /* stdy */;
+ else
+ ins = (op & SLJIT_32) ? 0xed0000000064 /* ley */ : 0xed0000000065 /* ldy */;
+
+ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | disp_s20(addr.offset));
+}
+
+static sljit_s32 emit_float(struct sljit_compiler *compiler, sljit_ins ins_r, sljit_ins ins,
+ sljit_s32 reg,
+ sljit_s32 src, sljit_sw srcw)
+{
+ struct addr addr;
+
+ if (!(src & SLJIT_MEM))
+ return push_inst(compiler, ins_r | F4(reg) | F0(src));
+
+ FAIL_IF(make_addr_bx(compiler, &addr, src, srcw, tmp1));
+ return push_inst(compiler, ins | F36(reg) | R32A(addr.index) | R28A(addr.base) | ((sljit_ins)addr.offset << 16));
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_ins dst_r = FAST_IS_REG(dst) ? gpr(dst) : tmp0;
+ sljit_ins ins;
+
+ if (src & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src, srcw));
+ src = TMP_FREG1;
+ }
+
+ /* M3 is set to 5 */
+ if (GET_OPCODE(op) == SLJIT_CONV_SW_FROM_F64)
+ ins = (op & SLJIT_32) ? 0xb3a85000 /* cgebr */ : 0xb3a95000 /* cgdbr */;
+ else
+ ins = (op & SLJIT_32) ? 0xb3985000 /* cfebr */ : 0xb3995000 /* cfdbr */;
+
+ FAIL_IF(push_inst(compiler, ins | R4A(dst_r) | F0(src)));
+
+ if (dst & SLJIT_MEM)
+ return store_word(compiler, dst_r, dst, dstw, GET_OPCODE(op) >= SLJIT_CONV_S32_FROM_F64);
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 dst, sljit_sw dstw,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+ sljit_ins ins;
+
+ if (src & SLJIT_IMM) {
+ FAIL_IF(push_load_imm_inst(compiler, tmp0, srcw));
+ src = (sljit_s32)tmp0;
+ }
+ else if (src & SLJIT_MEM) {
+ FAIL_IF(load_word(compiler, tmp0, src, srcw, GET_OPCODE(op) >= SLJIT_CONV_F64_FROM_S32));
+ src = (sljit_s32)tmp0;
+ }
+
+ if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_SW)
+ ins = (op & SLJIT_32) ? 0xb3a40000 /* cegbr */ : 0xb3a50000 /* cdgbr */;
+ else
+ ins = (op & SLJIT_32) ? 0xb3940000 /* cefbr */ : 0xb3950000 /* cdfbr */;
+
+ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | R0(src)));
+
+ if (dst & SLJIT_MEM)
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);
+
+ return SLJIT_SUCCESS;
+}
+
+static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_ins ins_r, ins;
+
+ if (src1 & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), TMP_FREG1, src1, src1w));
+ src1 = TMP_FREG1;
+ }
+
+ if (op & SLJIT_32) {
+ ins_r = 0xb3090000 /* cebr */;
+ ins = 0xed0000000009 /* ceb */;
+ } else {
+ ins_r = 0xb3190000 /* cdbr */;
+ ins = 0xed0000000019 /* cdb */;
+ }
+
+ return emit_float(compiler, ins_r, ins, src1, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
+ sljit_s32 dst_r;
+ sljit_ins ins;
+
CHECK_ERROR();
- abort();
+
+ SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
+
+ dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
+
+ if (op == SLJIT_CONV_F64_FROM_F32)
+ FAIL_IF(emit_float(compiler, 0xb3040000 /* ldebr */, 0xed0000000004 /* ldeb */, dst_r, src, srcw));
+ else {
+ if (src & SLJIT_MEM) {
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op == SLJIT_CONV_F32_FROM_F64 ? 0 : (op & SLJIT_32)), dst_r, src, srcw));
+ src = dst_r;
+ }
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_MOV_F64:
+ if (FAST_IS_REG(dst)) {
+ if (dst == src)
+ return SLJIT_SUCCESS;
+
+ ins = (op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */;
+ break;
+ }
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), src, dst, dstw);
+ case SLJIT_CONV_F64_FROM_F32:
+ /* Only SLJIT_CONV_F32_FROM_F64. */
+ ins = 0xb3440000 /* ledbr */;
+ break;
+ case SLJIT_NEG_F64:
+ ins = (op & SLJIT_32) ? 0xb3030000 /* lcebr */ : 0xb3130000 /* lcdbr */;
+ break;
+ default:
+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_ABS_F64);
+ ins = (op & SLJIT_32) ? 0xb3000000 /* lpebr */ : 0xb3100000 /* lpdbr */;
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, ins | F4(dst_r) | F0(src)));
+ }
+
+ if (!(dst & SLJIT_MEM))
+ return SLJIT_SUCCESS;
+
+ SLJIT_ASSERT(dst_r == TMP_FREG1);
+
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);
}
+#define FLOAT_MOV(op, dst_r, src_r) \
+ (((op & SLJIT_32) ? 0x3800 /* ler */ : 0x2800 /* ldr */) | F4(dst_r) | F0(src_r))
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
+ sljit_s32 dst_r = TMP_FREG1;
+ sljit_ins ins_r, ins;
+
CHECK_ERROR();
- abort();
+ CHECK(check_sljit_emit_fop2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ ADJUST_LOCAL_OFFSET(dst, dstw);
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ do {
+ if (FAST_IS_REG(dst)) {
+ dst_r = dst;
+
+ if (dst == src1)
+ break;
+
+ if (dst == src2) {
+ if (GET_OPCODE(op) == SLJIT_ADD_F64 || GET_OPCODE(op) == SLJIT_MUL_F64) {
+ src2 = src1;
+ src2w = src1w;
+ src1 = dst;
+ break;
+ }
+
+ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, TMP_FREG1, src2)));
+ src2 = TMP_FREG1;
+ }
+ }
+
+ if (src1 & SLJIT_MEM)
+ FAIL_IF(float_mem(compiler, FLOAT_LOAD | (op & SLJIT_32), dst_r, src1, src1w));
+ else
+ FAIL_IF(push_inst(compiler, FLOAT_MOV(op, dst_r, src1)));
+ } while (0);
+
+ switch (GET_OPCODE(op)) {
+ case SLJIT_ADD_F64:
+ ins_r = (op & SLJIT_32) ? 0xb30a0000 /* aebr */ : 0xb31a0000 /* adbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000a /* aeb */ : 0xed000000001a /* adb */;
+ break;
+ case SLJIT_SUB_F64:
+ ins_r = (op & SLJIT_32) ? 0xb30b0000 /* sebr */ : 0xb31b0000 /* sdbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000b /* seb */ : 0xed000000001b /* sdb */;
+ break;
+ case SLJIT_MUL_F64:
+ ins_r = (op & SLJIT_32) ? 0xb3170000 /* meebr */ : 0xb31c0000 /* mdbr */;
+ ins = (op & SLJIT_32) ? 0xed0000000017 /* meeb */ : 0xed000000001c /* mdb */;
+ break;
+ default:
+ SLJIT_ASSERT(GET_OPCODE(op) == SLJIT_DIV_F64);
+ ins_r = (op & SLJIT_32) ? 0xb30d0000 /* debr */ : 0xb31d0000 /* ddbr */;
+ ins = (op & SLJIT_32) ? 0xed000000000d /* deb */ : 0xed000000001d /* ddb */;
+ break;
+ }
+
+ FAIL_IF(emit_float(compiler, ins_r, ins, dst_r, src2, src2w));
+
+ if (dst & SLJIT_MEM)
+ return float_mem(compiler, FLOAT_STORE | (op & SLJIT_32), TMP_FREG1, dst, dstw);
+
+ SLJIT_ASSERT(dst_r != TMP_FREG1);
+ return SLJIT_SUCCESS;
}
/* --------------------------------------------------------------------- */
@@ -2795,6 +3120,11 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
@@ -2809,14 +3139,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_ijump(compiler, type, src, srcw));
- ADJUST_LOCAL_OFFSET(src, srcw);
if (src & SLJIT_IMM) {
SLJIT_ASSERT(!(srcw & 1)); /* target address must be even */
FAIL_IF(push_load_imm_inst(compiler, src_r, srcw));
}
- else if (src & SLJIT_MEM)
+ else if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
FAIL_IF(load_word(compiler, src_r, src, srcw, 0 /* 64-bit */));
+ }
/* emit jump instruction */
if (type >= SLJIT_FAST_CALL)
@@ -2832,6 +3163,24 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+ SLJIT_ASSERT(gpr(TMP_REG2) == tmp1);
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ FAIL_IF(load_word(compiler, tmp1, src, srcw, 0 /* 64-bit */));
+ src = TMP_REG2;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
+ FAIL_IF(push_inst(compiler, lgr(tmp1, gpr(src))));
+ src = TMP_REG2;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP;
+ }
+
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
@@ -2859,11 +3208,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
/* dst is also source operand */
if (dst & SLJIT_MEM)
- FAIL_IF(load_word(compiler, dst_r, dst, dstw, op & SLJIT_I32_OP));
+ FAIL_IF(load_word(compiler, dst_r, dst, dstw, op & SLJIT_32));
break;
+ case SLJIT_MOV32:
+ op |= SLJIT_32;
+ /* fallthrough */
case SLJIT_MOV:
- case (SLJIT_MOV32 & ~SLJIT_I32_OP):
/* can write straight into destination */
loc_r = dst_r;
break;
@@ -2876,7 +3227,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
if (have_lscond2()) {
FAIL_IF(push_load_imm_inst(compiler, loc_r, 0));
FAIL_IF(push_inst(compiler,
- WHEN2(op & SLJIT_I32_OP, lochi, locghi)));
+ WHEN2(op & SLJIT_32, lochi, locghi)));
} else {
/* TODO(mundaym): no load/store-on-condition 2 facility (ipm? branch-and-set?) */
abort();
@@ -2888,22 +3239,22 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
#define LEVAL(i) i(dst_r, loc_r)
case SLJIT_AND:
FAIL_IF(push_inst(compiler,
- WHEN2(op & SLJIT_I32_OP, nr, ngr)));
+ WHEN2(op & SLJIT_32, nr, ngr)));
break;
case SLJIT_OR:
FAIL_IF(push_inst(compiler,
- WHEN2(op & SLJIT_I32_OP, or, ogr)));
+ WHEN2(op & SLJIT_32, or, ogr)));
break;
case SLJIT_XOR:
FAIL_IF(push_inst(compiler,
- WHEN2(op & SLJIT_I32_OP, xr, xgr)));
+ WHEN2(op & SLJIT_32, xr, xgr)));
break;
#undef LEVAL
}
/* store result to memory if required */
if (dst & SLJIT_MEM)
- return store_word(compiler, dst_r, dst, dstw, op & SLJIT_I32_OP);
+ return store_word(compiler, dst_r, dst, dstw, (op & SLJIT_32));
return SLJIT_SUCCESS;
}
@@ -2913,7 +3264,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
sljit_s32 src, sljit_sw srcw)
{
sljit_u8 mask = get_cc(compiler, type & 0xff);
- sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_I32_OP);
+ sljit_gpr dst_r = gpr(dst_reg & ~SLJIT_32);
sljit_gpr src_r = FAST_IS_REG(src) ? gpr(src) : tmp0;
CHECK_ERROR();
@@ -2927,7 +3278,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
#define LEVAL(i) i(dst_r, src_r, mask)
if (have_lscond1())
return push_inst(compiler,
- WHEN2(dst_reg & SLJIT_I32_OP, locr, locgr));
+ WHEN2(dst_reg & SLJIT_32, locr, locgr));
#undef LEVAL
@@ -2991,7 +3342,7 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
SLJIT_API_FUNC_ATTRIBUTE struct sljit_put_label *sljit_emit_put_label(
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
index 28886405af..218992b355 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_32.c
@@ -35,16 +35,13 @@ static sljit_s32 load_immediate(struct sljit_compiler *compiler, sljit_s32 dst,
#define ARG2(flags, src2) ((flags & SRC2_IMM) ? IMM(src2) : S2(src2))
-static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_u32 flags,
sljit_s32 dst, sljit_s32 src1, sljit_sw src2)
{
SLJIT_COMPILE_ASSERT(ICC_IS_SET == SET_FLAGS, icc_is_set_and_set_flags_must_be_the_same);
switch (op) {
case SLJIT_MOV:
- case SLJIT_MOV_U32:
- case SLJIT_MOV_S32:
- case SLJIT_MOV_P:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
if (dst != src2)
return push_inst(compiler, OR | D(dst) | S1(0) | S2(src2), DR(dst));
@@ -59,8 +56,7 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(24), DR(dst)));
return push_inst(compiler, SRA | D(dst) | S1(dst) | IMM(24), DR(dst));
}
- else if (dst != src2)
- SLJIT_UNREACHABLE();
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_MOV_U16:
@@ -70,13 +66,12 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src2) | IMM(16), DR(dst)));
return push_inst(compiler, (op == SLJIT_MOV_S16 ? SRA : SRL) | D(dst) | S1(dst) | IMM(16), DR(dst));
}
- else if (dst != src2)
- SLJIT_UNREACHABLE();
+ SLJIT_ASSERT(dst == src2);
return SLJIT_SUCCESS;
case SLJIT_NOT:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
- return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DR(dst) | (flags & SET_FLAGS));
+ return push_inst(compiler, XNOR | (flags & SET_FLAGS) | D(dst) | S1(0) | S2(src2), DRF(dst, flags));
case SLJIT_CLZ:
SLJIT_ASSERT(src1 == TMP_REG1 && !(flags & SRC2_IMM));
@@ -89,22 +84,24 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
/* Loop. */
FAIL_IF(push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(0), SET_FLAGS));
FAIL_IF(push_inst(compiler, SLL | D(TMP_REG1) | S1(TMP_REG1) | IMM(1), DR(TMP_REG1)));
- FAIL_IF(push_inst(compiler, BICC | DA(0xe) | (-2 & DISP_MASK), UNMOVABLE_INS));
+ FAIL_IF(push_inst(compiler, BICC | DA(0xe) | ((sljit_ins)-2 & DISP_MASK), UNMOVABLE_INS));
return push_inst(compiler, ADD | D(dst) | S1(dst) | IMM(1), UNMOVABLE_INS);
case SLJIT_ADD:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return push_inst(compiler, ADD | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_ADDC:
- return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD;
+ return push_inst(compiler, ADDC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_SUB:
- compiler->status_flags_state = SLJIT_CURRENT_FLAGS_ADD_SUB;
- return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return push_inst(compiler, SUB | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_SUBC:
- return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ compiler->status_flags_state = SLJIT_CURRENT_FLAGS_SUB;
+ return push_inst(compiler, SUBC | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_MUL:
compiler->status_flags_state = 0;
@@ -116,13 +113,13 @@ static SLJIT_INLINE sljit_s32 emit_single_op(struct sljit_compiler *compiler, sl
return push_inst(compiler, SUB | SET_FLAGS | D(0) | S1(TMP_REG1) | S2(TMP_LINK), MOVABLE_INS | SET_FLAGS);
case SLJIT_AND:
- return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ return push_inst(compiler, AND | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_OR:
- return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ return push_inst(compiler, OR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_XOR:
- return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst) | (flags & SET_FLAGS));
+ return push_inst(compiler, XOR | (flags & SET_FLAGS) | D(dst) | S1(src1) | ARG2(flags, src2), DRF(dst, flags));
case SLJIT_SHL:
FAIL_IF(push_inst(compiler, SLL | D(dst) | S1(src1) | ARG2(flags, src2), DR(dst)));
@@ -147,7 +144,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
sljit_s32 word_reg_index = 8;
sljit_s32 float_arg_index = 1;
sljit_s32 double_arg_count = 0;
- sljit_s32 float_offset = (16 + 6) * sizeof(sljit_sw);
+ sljit_u32 float_offset = (16 + 6) * sizeof(sljit_sw);
sljit_s32 types = 0;
sljit_s32 reg = 0;
sljit_s32 move_to_tmp2 = 0;
@@ -155,18 +152,12 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
if (src)
reg = reg_map[*src & REG_MASK];
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- float_arg_index++;
- if (reg_index == reg)
- move_to_tmp2 = 1;
- reg_index++;
- break;
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
float_arg_index++;
double_arg_count++;
@@ -174,36 +165,37 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
move_to_tmp2 = 1;
reg_index += 2;
break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_index++;
+ if (reg_index == reg)
+ move_to_tmp2 = 1;
+ reg_index++;
+ break;
default:
- if (reg_index != word_reg_index && reg_index < 14 && reg_index == reg)
+ if (reg_index != word_reg_index && reg_index == reg)
move_to_tmp2 = 1;
reg_index++;
word_reg_index++;
break;
}
- if (move_to_tmp2) {
- move_to_tmp2 = 0;
- if (reg < 14)
- FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));
- *src = TMP_REG1;
- }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
- arg_types >>= SLJIT_DEF_SHIFT;
+ if (move_to_tmp2) {
+ if (reg < 14)
+ FAIL_IF(push_inst(compiler, OR | D(TMP_REG1) | S1(0) | S2A(reg), DR(TMP_REG1)));
+ *src = TMP_REG1;
}
arg_types = types;
while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- float_arg_index--;
- FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
- float_offset -= sizeof(sljit_f64);
- break;
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
float_arg_index--;
if (float_arg_index == 4 && double_arg_count == 4) {
+ /* The address is not doubleword aligned, so two instructions are required to store the double. */
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM((16 + 7) * sizeof(sljit_sw)), MOVABLE_INS));
FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | (1 << 25) | S1(SLJIT_SP) | IMM((16 + 8) * sizeof(sljit_sw)), MOVABLE_INS));
}
@@ -211,36 +203,41 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
FAIL_IF(push_inst(compiler, STDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
float_offset -= sizeof(sljit_f64);
break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_index--;
+ FAIL_IF(push_inst(compiler, STF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ float_offset -= sizeof(sljit_f64);
+ break;
default:
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
float_offset = (16 + 6) * sizeof(sljit_sw);
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- reg_index--;
- if (reg_index < 14)
- FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
- float_offset -= sizeof(sljit_f64);
- break;
+ switch (types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
reg_index -= 2;
if (reg_index < 14) {
if ((reg_index & 0x1) != 0) {
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
- if (reg_index < 13)
+ if (reg_index < 8 + 6 - 1)
FAIL_IF(push_inst(compiler, LDUW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), reg_index + 1));
}
- else
+ else
FAIL_IF(push_inst(compiler, LDD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
}
float_offset -= sizeof(sljit_f64);
break;
+ case SLJIT_ARG_TYPE_F32:
+ reg_index--;
+ if (reg_index < 8 + 6)
+ FAIL_IF(push_inst(compiler, LDUW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), reg_index));
+ float_offset -= sizeof(sljit_f64);
+ break;
default:
reg_index--;
word_reg_index--;
@@ -254,7 +251,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -282,5 +279,5 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_constant, sljit_sw executable_offset)
{
- sljit_set_jump_addr(addr, new_constant, executable_offset);
+ sljit_set_jump_addr(addr, (sljit_uw)new_constant, executable_offset);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
index e833f09d7a..c8d19e16c6 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeSPARC_common.c
@@ -98,36 +98,37 @@ static void sparc_cache_flush(sljit_ins *from, sljit_ins *to)
#define TMP_FREG2 (SLJIT_NUMBER_OF_FLOAT_REGISTERS + 2)
static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = {
- 0, 8, 9, 10, 11, 29, 28, 27, 23, 22, 21, 20, 19, 18, 17, 16, 26, 25, 24, 14, 1, 12, 13, 15
+ 0, 8, 9, 10, 11, 23, 22, 21, 20, 19, 18, 17, 16, 29, 28, 27, 26, 25, 24, 14, 1, 12, 13, 15
};
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
- 0, 0, 2, 4, 6, 8, 10, 12, 14
+ 0, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30
};
/* --------------------------------------------------------------------- */
/* Instrucion forms */
/* --------------------------------------------------------------------- */
-#define D(d) (reg_map[d] << 25)
-#define FD(d) (freg_map[d] << 25)
-#define FDN(d) ((freg_map[d] | 0x1) << 25)
-#define DA(d) ((d) << 25)
-#define S1(s1) (reg_map[s1] << 14)
-#define FS1(s1) (freg_map[s1] << 14)
-#define S1A(s1) ((s1) << 14)
-#define S2(s2) (reg_map[s2])
-#define FS2(s2) (freg_map[s2])
-#define FS2N(s2) (freg_map[s2] | 0x1)
-#define S2A(s2) (s2)
+#define D(d) ((sljit_ins)reg_map[d] << 25)
+#define FD(d) ((sljit_ins)freg_map[d] << 25)
+#define FDN(d) (((sljit_ins)freg_map[d] | 0x1) << 25)
+#define DA(d) ((sljit_ins)(d) << 25)
+#define S1(s1) ((sljit_ins)reg_map[s1] << 14)
+#define FS1(s1) ((sljit_ins)freg_map[s1] << 14)
+#define S1A(s1) ((sljit_ins)(s1) << 14)
+#define S2(s2) ((sljit_ins)reg_map[s2])
+#define FS2(s2) ((sljit_ins)freg_map[s2])
+#define FS2N(s2) ((sljit_ins)freg_map[s2] | 0x1)
+#define S2A(s2) ((sljit_ins)(s2))
#define IMM_ARG 0x2000
-#define DOP(op) ((op) << 5)
-#define IMM(imm) (((imm) & 0x1fff) | IMM_ARG)
+#define DOP(op) ((sljit_ins)(op) << 5)
+#define IMM(imm) (((sljit_ins)(imm) & 0x1fff) | IMM_ARG)
#define DR(dr) (reg_map[dr])
-#define OPC1(opcode) ((opcode) << 30)
-#define OPC2(opcode) ((opcode) << 22)
-#define OPC3(opcode) ((opcode) << 19)
+#define DRF(dr, flags) ((sljit_s32)(reg_map[dr] | ((flags) & SET_FLAGS)))
+#define OPC1(opcode) ((sljit_ins)(opcode) << 30)
+#define OPC2(opcode) ((sljit_ins)(opcode) << 22)
+#define OPC3(opcode) ((sljit_ins)(opcode) << 19)
#define SET_FLAGS OPC3(0x10)
#define ADD (OPC1(0x2) | OPC3(0x00))
@@ -156,6 +157,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define FSUBS (OPC1(0x2) | OPC3(0x34) | DOP(0x45))
#define JMPL (OPC1(0x2) | OPC3(0x38))
#define LDD (OPC1(0x3) | OPC3(0x03))
+#define LDDF (OPC1(0x3) | OPC3(0x23))
+#define LDF (OPC1(0x3) | OPC3(0x20))
#define LDUW (OPC1(0x3) | OPC3(0x00))
#define NOP (OPC1(0x0) | OPC2(0x04))
#define OR (OPC1(0x2) | OPC3(0x02))
@@ -170,6 +173,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#define SRAX (OPC1(0x2) | OPC3(0x27) | (1 << 12))
#define SRL (OPC1(0x2) | OPC3(0x26))
#define SRLX (OPC1(0x2) | OPC3(0x26) | (1 << 12))
+#define STD (OPC1(0x3) | OPC3(0x07))
#define STDF (OPC1(0x3) | OPC3(0x27))
#define STF (OPC1(0x3) | OPC3(0x24))
#define STW (OPC1(0x3) | OPC3(0x04))
@@ -183,7 +187,7 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 3] = {
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
#define MAX_DISP (0x1fffff)
#define MIN_DISP (-0x200000)
-#define DISP_MASK (0x3fffff)
+#define DISP_MASK ((sljit_ins)0x3fffff)
#define BICC (OPC1(0x0) | OPC2(0x2))
#define FBFCC (OPC1(0x0) | OPC2(0x6))
@@ -274,7 +278,7 @@ static SLJIT_INLINE sljit_ins* detect_jump_type(struct sljit_jump *jump, sljit_i
}
}
- diff += sizeof(sljit_ins);
+ diff += SSIZE_OF(ins);
if (diff <= MAX_DISP && diff >= MIN_DISP) {
jump->flags |= PATCH_B;
@@ -300,7 +304,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_uw word_count;
sljit_uw next_addr;
sljit_sw executable_offset;
- sljit_uw addr;
+ sljit_sw addr;
struct sljit_label *label;
struct sljit_jump *jump;
@@ -340,7 +344,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
/* Just recording the address. */
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
if (jump && jump->addr == word_count) {
@@ -373,7 +377,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
if (label && label->size == word_count) {
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
}
@@ -386,27 +390,27 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
do {
- addr = (jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target;
+ addr = (sljit_sw)((jump->flags & JUMP_LABEL) ? jump->u.label->addr : jump->u.target);
buf_ptr = (sljit_ins *)jump->addr;
if (jump->flags & PATCH_CALL) {
- addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
- SLJIT_ASSERT((sljit_sw)addr <= 0x1fffffff && (sljit_sw)addr >= -0x20000000);
- buf_ptr[0] = CALL | (addr & 0x3fffffff);
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= 0x1fffffff && addr >= -0x20000000);
+ buf_ptr[0] = CALL | ((sljit_ins)addr & 0x3fffffff);
break;
}
if (jump->flags & PATCH_B) {
- addr = (sljit_sw)(addr - (sljit_uw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
- SLJIT_ASSERT((sljit_sw)addr <= MAX_DISP && (sljit_sw)addr >= MIN_DISP);
- buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | (addr & DISP_MASK);
+ addr = (addr - (sljit_sw)SLJIT_ADD_EXEC_OFFSET(buf_ptr, executable_offset)) >> 2;
+ SLJIT_ASSERT(addr <= MAX_DISP && addr >= MIN_DISP);
+ buf_ptr[0] = (buf_ptr[0] & ~DISP_MASK) | ((sljit_ins)addr & DISP_MASK);
break;
}
/* Set the fields of immediate loads. */
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
SLJIT_ASSERT(((buf_ptr[0] & 0xc1cfffff) == 0x01000000) && ((buf_ptr[1] & 0xc1f83fff) == 0x80102000));
- buf_ptr[0] |= (addr >> 10) & 0x3fffff;
- buf_ptr[1] |= addr & 0x3ff;
+ buf_ptr[0] |= (sljit_ins)(addr >> 10) & 0x3fffff;
+ buf_ptr[1] |= (sljit_ins)addr & 0x3ff;
#else
#error "Implementation required"
#endif
@@ -416,7 +420,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
put_label = compiler->put_labels;
while (put_label) {
- addr = put_label->label->addr;
+ addr = (sljit_sw)put_label->label->addr;
buf_ptr = (sljit_ins *)put_label->addr;
#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
@@ -431,7 +435,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = (code_ptr - code) * sizeof(sljit_ins);
+ compiler->executable_size = (sljit_uw)(code_ptr - code) * sizeof(sljit_ins);
code = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
code_ptr = (sljit_ins *)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
@@ -487,13 +491,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#define ALT_KEEP_CACHE 0x00040
#define CUMULATIVE_OP 0x00080
#define IMM_OP 0x00100
-#define SRC2_IMM 0x00200
+#define MOVE_OP 0x00200
+#define SRC2_IMM 0x00400
-#define REG_DEST 0x00400
-#define REG2_SOURCE 0x00800
-#define SLOW_SRC1 0x01000
-#define SLOW_SRC2 0x02000
-#define SLOW_DEST 0x04000
+#define REG_DEST 0x00800
+#define REG2_SOURCE 0x01000
+#define SLOW_SRC1 0x02000
+#define SLOW_SRC2 0x04000
+#define SLOW_DEST 0x08000
/* SET_FLAGS (0x10 << 19) also belong here! */
@@ -507,6 +512,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
+ sljit_s32 reg_index, types, tmp;
+ sljit_u32 float_offset, args_offset;
+ sljit_s32 saved_arg_index, scratch_arg_index, float_arg_index;
+
CHECK_ERROR();
CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
@@ -514,7 +523,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
local_size = (local_size + SLJIT_LOCALS_OFFSET + 7) & ~0x7;
compiler->local_size = local_size;
- if (local_size <= SIMM_MAX) {
+ if (local_size <= -SIMM_MIN) {
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | IMM(-local_size), UNMOVABLE_INS));
}
else {
@@ -522,7 +531,88 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
FAIL_IF(push_inst(compiler, SAVE | D(SLJIT_SP) | S1(SLJIT_SP) | S2(TMP_REG1), UNMOVABLE_INS));
}
- /* Arguments are in their appropriate registers. */
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ types = arg_types;
+ float_offset = 16 * sizeof(sljit_sw);
+ reg_index = 24;
+
+ while (types && reg_index < 24 + 6) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (reg_index & 0x1) {
+ FAIL_IF(push_inst(compiler, STW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ if (reg_index >= 24 + 6 - 1)
+ break;
+ FAIL_IF(push_inst(compiler, STW | DA(reg_index + 1) | S1(SLJIT_SP) | IMM(float_offset + sizeof(sljit_sw)), MOVABLE_INS));
+ } else
+ FAIL_IF(push_inst(compiler, STD | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+
+ float_offset += sizeof(sljit_f64);
+ reg_index++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ FAIL_IF(push_inst(compiler, STW | DA(reg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ float_offset += sizeof(sljit_f64);
+ break;
+ }
+
+ reg_index++;
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ args_offset = (16 + 1 + 6) * sizeof(sljit_sw);
+ float_offset = 16 * sizeof(sljit_sw);
+ reg_index = 24;
+ saved_arg_index = 24;
+ scratch_arg_index = 8 - 1;
+ float_arg_index = 1;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ if (reg_index < 24 + 6 - 1) {
+ FAIL_IF(push_inst(compiler, LDDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ } else if (reg_index < 24 + 6) {
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | (1 << 25) | S1A(30) | IMM(args_offset), MOVABLE_INS));
+ } else {
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1A(30) | IMM(args_offset), MOVABLE_INS));
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | (1 << 25) | S1A(30) | IMM(args_offset + sizeof(sljit_sw)), MOVABLE_INS));
+ }
+
+ float_arg_index++;
+ float_offset += sizeof(sljit_f64);
+ reg_index++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ if (reg_index < 24 + 6)
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1(SLJIT_SP) | IMM(float_offset), MOVABLE_INS));
+ else
+ FAIL_IF(push_inst(compiler, LDF | FD(float_arg_index) | S1A(30) | IMM(args_offset), MOVABLE_INS));
+ float_arg_index++;
+ float_offset += sizeof(sljit_f64);
+ break;
+ default:
+ scratch_arg_index++;
+
+ if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ tmp = saved_arg_index++;
+ if (tmp == reg_index)
+ break;
+ } else
+ tmp = scratch_arg_index;
+
+ if (reg_index < 24 + 6)
+ FAIL_IF(push_inst(compiler, OR | DA(tmp) | S1(0) | S2A(reg_index), tmp));
+ else
+ FAIL_IF(push_inst(compiler, LDUW | DA(tmp) | S1A(30) | IMM(args_offset), tmp));
+ break;
+ }
+
+ reg_index++;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
return SLJIT_SUCCESS;
}
@@ -539,12 +629,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ FAIL_IF(push_inst(compiler, JMPL | D(0) | S1A(31) | IMM(8), UNMOVABLE_INS));
+ return push_inst(compiler, RESTORE | D(SLJIT_R0) | S1(SLJIT_R0) | S2(0), UNMOVABLE_INS);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
{
CHECK_ERROR();
CHECK(check_sljit_emit_return(compiler, op, src, srcw));
- if (op != SLJIT_MOV || !FAST_IS_REG(src)) {
+ if (TYPE_CAST_NEEDED(op) || !FAST_IS_REG(src)) {
FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
src = SLJIT_R0;
}
@@ -591,7 +690,7 @@ static const sljit_ins data_transfer_insts[16 + 4] = {
#undef ARCH_32_64
/* Can perform an operation using at most 1 instruction. */
-static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+static sljit_s32 getput_arg_fast(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
SLJIT_ASSERT(arg & SLJIT_MEM);
@@ -632,7 +731,7 @@ static sljit_s32 can_cache(sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, slj
}
/* Emit the necessary instructions. See can_cache above. */
-static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
+static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw, sljit_s32 next_arg, sljit_sw next_argw)
{
sljit_s32 base, arg2, delay_slot;
sljit_ins dest;
@@ -660,7 +759,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
arg2 = reg;
else /* It must be a mov operation, so tmp1 must be free to use. */
arg2 = TMP_REG1;
- FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | argw, DR(arg2)));
+ FAIL_IF(push_inst(compiler, SLL_W | D(arg2) | S1(OFFS_REG(arg)) | IMM_ARG | (sljit_ins)argw, DR(arg2)));
}
}
else {
@@ -692,7 +791,7 @@ static sljit_s32 getput_arg(struct sljit_compiler *compiler, sljit_s32 flags, sl
return push_inst(compiler, data_transfer_insts[flags & MEM_MASK] | dest | S1(base) | S2(arg2), delay_slot);
}
-static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
+static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg, sljit_sw argw)
{
if (getput_arg_fast(compiler, flags, reg, arg, argw))
return compiler->error;
@@ -701,14 +800,14 @@ static SLJIT_INLINE sljit_s32 emit_op_mem(struct sljit_compiler *compiler, sljit
return getput_arg(compiler, flags, reg, arg, argw, 0, 0);
}
-static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_s32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
+static SLJIT_INLINE sljit_s32 emit_op_mem2(struct sljit_compiler *compiler, sljit_u32 flags, sljit_s32 reg, sljit_s32 arg1, sljit_sw arg1w, sljit_s32 arg2, sljit_sw arg2w)
{
if (getput_arg_fast(compiler, flags, reg, arg1, arg1w))
return compiler->error;
return getput_arg(compiler, flags, reg, arg1, arg1w, arg2, arg2w);
}
-static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 flags,
+static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_u32 flags,
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
@@ -727,11 +826,11 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
compiler->cache_argw = 0;
}
- if (dst != SLJIT_UNUSED) {
+ if (dst != TMP_REG2) {
if (FAST_IS_REG(dst)) {
dst_r = dst;
flags |= REG_DEST;
- if (op >= SLJIT_MOV && op <= SLJIT_MOV_P)
+ if (flags & MOVE_OP)
sugg_src2_r = dst_r;
}
else if ((dst & SLJIT_MEM) && !getput_arg_fast(compiler, flags | ARG_TEST, TMP_REG1, dst, dstw))
@@ -782,7 +881,7 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
if (FAST_IS_REG(src2)) {
src2_r = src2;
flags |= REG2_SOURCE;
- if (!(flags & REG_DEST) && op >= SLJIT_MOV && op <= SLJIT_MOV_P)
+ if ((flags & (REG_DEST | MOVE_OP)) == MOVE_OP)
dst_r = src2_r;
}
else if (src2 & SLJIT_IMM) {
@@ -793,8 +892,12 @@ static sljit_s32 emit_op(struct sljit_compiler *compiler, sljit_s32 op, sljit_s3
}
else {
src2_r = 0;
- if ((op >= SLJIT_MOV && op <= SLJIT_MOV_P) && (dst & SLJIT_MEM))
- dst_r = 0;
+ if (flags & MOVE_OP) {
+ if (dst & SLJIT_MEM)
+ dst_r = 0;
+ else
+ op = SLJIT_MOV;
+ }
}
}
}
@@ -888,7 +991,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
sljit_s32 dst, sljit_sw dstw,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_u32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw));
@@ -898,33 +1001,29 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
op = GET_OPCODE(op);
switch (op) {
case SLJIT_MOV:
- case SLJIT_MOV_P:
- return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
-
+#if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32)
case SLJIT_MOV_U32:
- return emit_op(compiler, SLJIT_MOV_U32, flags | INT_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
-
case SLJIT_MOV_S32:
- return emit_op(compiler, SLJIT_MOV_S32, flags | INT_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, srcw);
+ case SLJIT_MOV32:
+#endif
+ case SLJIT_MOV_P:
+ return emit_op(compiler, SLJIT_MOV, flags | WORD_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, srcw);
case SLJIT_MOV_U8:
- return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_U8, flags | BYTE_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u8)srcw : srcw);
case SLJIT_MOV_S8:
- return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_S8, flags | BYTE_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s8)srcw : srcw);
case SLJIT_MOV_U16:
- return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_U16, flags | HALF_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_u16)srcw : srcw);
case SLJIT_MOV_S16:
- return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
+ return emit_op(compiler, SLJIT_MOV_S16, flags | HALF_DATA | SIGNED_DATA | MOVE_OP, dst, dstw, TMP_REG1, 0, src, (src & SLJIT_IMM) ? (sljit_s16)srcw : srcw);
case SLJIT_NOT:
case SLJIT_CLZ:
return emit_op(compiler, op, flags, dst, dstw, TMP_REG1, 0, src, srcw);
-
- case SLJIT_NEG:
- return emit_op(compiler, SLJIT_SUB, flags | IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw);
}
return SLJIT_SUCCESS;
@@ -935,17 +1034,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src1, sljit_sw src1w,
sljit_s32 src2, sljit_sw src2w)
{
- sljit_s32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_u32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
-
op = GET_OPCODE(op);
switch (op) {
case SLJIT_ADD:
@@ -975,6 +1071,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG2, 0, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -1015,7 +1125,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
CHECK_ERROR();
CHECK(check_sljit_emit_op_custom(compiler, instruction, size));
@@ -1027,8 +1137,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* Floating point operators */
/* --------------------------------------------------------------------- */
-#define FLOAT_DATA(op) (DOUBLE_DATA | ((op & SLJIT_F32_OP) >> 7))
-#define SELECT_FOP(op, single, double) ((op & SLJIT_F32_OP) ? single : double)
+#define FLOAT_DATA(op) ((sljit_ins)DOUBLE_DATA | (((sljit_ins)(op) & SLJIT_32) >> 7))
+#define SELECT_FOP(op, single, double) ((op & SLJIT_32) ? single : double)
#define FLOAT_TMP_MEM_OFFSET (22 * sizeof(sljit_sw))
static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_compiler *compiler, sljit_s32 op,
@@ -1108,11 +1218,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
compiler->cache_arg = 0;
compiler->cache_argw = 0;
- SLJIT_COMPILE_ASSERT((SLJIT_F32_OP == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
+ SLJIT_COMPILE_ASSERT((SLJIT_32 == 0x100) && !(DOUBLE_DATA & 0x2), float_transfer_bit_error);
SELECT_FOP1_OPERATION_WITH_CHECKS(compiler, op, dst, dstw, src, srcw);
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32)
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
dst_r = FAST_IS_REG(dst) ? dst : TMP_FREG1;
@@ -1126,7 +1236,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
if (src != dst_r) {
if (dst_r != TMP_FREG1) {
FAIL_IF(push_inst(compiler, FMOVS | FD(dst_r) | FS2(src), MOVABLE_INS));
- if (!(op & SLJIT_F32_OP))
+ if (!(op & SLJIT_32))
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
}
else
@@ -1135,17 +1245,17 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
break;
case SLJIT_NEG_F64:
FAIL_IF(push_inst(compiler, FNEGS | FD(dst_r) | FS2(src), MOVABLE_INS));
- if (dst_r != src && !(op & SLJIT_F32_OP))
+ if (dst_r != src && !(op & SLJIT_32))
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
break;
case SLJIT_ABS_F64:
FAIL_IF(push_inst(compiler, FABSS | FD(dst_r) | FS2(src), MOVABLE_INS));
- if (dst_r != src && !(op & SLJIT_F32_OP))
+ if (dst_r != src && !(op & SLJIT_32))
FAIL_IF(push_inst(compiler, FMOVS | FDN(dst_r) | FS2N(src), MOVABLE_INS));
break;
case SLJIT_CONV_F64_FROM_F32:
FAIL_IF(push_inst(compiler, SELECT_FOP(op, FSTOD, FDTOS) | FD(dst_r) | FS2(src), MOVABLE_INS));
- op ^= SLJIT_F32_OP;
+ op ^= SLJIT_32;
break;
}
@@ -1288,10 +1398,12 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
case SLJIT_LESS:
case SLJIT_GREATER_F64: /* Unordered. */
+ case SLJIT_CARRY:
return DA(0x5);
case SLJIT_GREATER_EQUAL:
case SLJIT_LESS_EQUAL_F64:
+ case SLJIT_NOT_CARRY:
return DA(0xd);
case SLJIT_GREATER:
@@ -1315,15 +1427,17 @@ static sljit_ins get_cc(struct sljit_compiler *compiler, sljit_s32 type)
return DA(0x2);
case SLJIT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return DA(0x9);
+ /* fallthrough */
case SLJIT_UNORDERED_F64:
return DA(0x7);
case SLJIT_NOT_OVERFLOW:
- if (!(compiler->status_flags_state & SLJIT_CURRENT_FLAGS_ADD_SUB))
+ if (!(compiler->status_flags_state & (SLJIT_CURRENT_FLAGS_ADD | SLJIT_CURRENT_FLAGS_SUB)))
return DA(0x1);
+ /* fallthrough */
case SLJIT_ORDERED_F64:
return DA(0xf);
@@ -1412,7 +1526,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF(!jump);
set_jump(jump, compiler, JUMP_ADDR);
- jump->u.target = srcw;
+ jump->u.target = (sljit_uw)srcw;
if ((compiler->delay_slot & DST_INS_MASK) != UNMOVABLE_INS)
jump->flags |= IS_MOVABLE;
@@ -1460,7 +1574,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
sljit_s32 dst, sljit_sw dstw,
sljit_s32 type)
{
- sljit_s32 reg, flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
+ sljit_s32 reg;
+ sljit_u32 flags = HAS_FLAGS(op) ? SET_FLAGS : 0;
CHECK_ERROR();
CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, type));
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
index 79a7e8bba5..b9a7b39789 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_32.c
@@ -26,6 +26,10 @@
/* x86 32-bit arch dependent functions. */
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, sljit_sw imm)
{
sljit_u8 *inst;
@@ -38,314 +42,8 @@ static sljit_s32 emit_do_imm(struct sljit_compiler *compiler, sljit_u8 opcode, s
return SLJIT_SUCCESS;
}
-static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
-{
- sljit_s32 type = jump->flags >> TYPE_SHIFT;
-
- if (type == SLJIT_JUMP) {
- *code_ptr++ = JMP_i32;
- jump->addr++;
- }
- else if (type >= SLJIT_FAST_CALL) {
- *code_ptr++ = CALL_i32;
- jump->addr++;
- }
- else {
- *code_ptr++ = GROUP_0F;
- *code_ptr++ = get_jump_code(type);
- jump->addr += 2;
- }
-
- if (jump->flags & JUMP_LABEL)
- jump->flags |= PATCH_MW;
- else
- sljit_unaligned_store_sw(code_ptr, jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset);
- code_ptr += 4;
-
- return code_ptr;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
-{
- sljit_s32 args, size;
- sljit_u8 *inst;
-
- CHECK_ERROR();
- CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
- set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
-
- /* Emit ENDBR32 at function entry if needed. */
- FAIL_IF(emit_endbranch(compiler));
-
- args = get_arg_count(arg_types);
- compiler->args = args;
-
- /* [esp+0] for saving temporaries and function calls. */
- compiler->stack_tmp_size = 2 * sizeof(sljit_sw);
-
-#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (scratches > 3)
- compiler->stack_tmp_size = 3 * sizeof(sljit_sw);
-#endif
-
- compiler->saveds_offset = compiler->stack_tmp_size;
- if (scratches > 3)
- compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
-
- compiler->locals_offset = compiler->saveds_offset;
-
- if (saveds > 3)
- compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
-
- if (options & SLJIT_F64_ALIGNMENT)
- compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
-
- size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);
-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- size += (args > 0 ? (args * 2) : 0) + (args > 2 ? 2 : 0);
-#else
- size += (args > 0 ? (2 + args * 3) : 0);
-#endif
- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!inst);
-
- INC_SIZE(size);
- PUSH_REG(reg_map[TMP_REG1]);
-#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (args > 0) {
- *inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[TMP_REG1] << 3) | 0x4 /* esp */;
- }
-#endif
- if (saveds > 2 || scratches > 9)
- PUSH_REG(reg_map[SLJIT_S2]);
- if (saveds > 1 || scratches > 10)
- PUSH_REG(reg_map[SLJIT_S1]);
- if (saveds > 0 || scratches > 11)
- PUSH_REG(reg_map[SLJIT_S0]);
-
-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (args > 0) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_REG | (reg_map[SLJIT_S0] << 3) | reg_map[SLJIT_R2];
- inst += 2;
- }
- if (args > 1) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_REG | (reg_map[SLJIT_S1] << 3) | reg_map[SLJIT_R1];
- inst += 2;
- }
- if (args > 2) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | 0x4 /* esp */;
- inst[2] = 0x24;
- inst[3] = sizeof(sljit_sw) * (3 + 2); /* saveds >= 3 as well. */
- }
-#else
- if (args > 0) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_DISP8 | (reg_map[SLJIT_S0] << 3) | reg_map[TMP_REG1];
- inst[2] = sizeof(sljit_sw) * 2;
- inst += 3;
- }
- if (args > 1) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_DISP8 | (reg_map[SLJIT_S1] << 3) | reg_map[TMP_REG1];
- inst[2] = sizeof(sljit_sw) * 3;
- inst += 3;
- }
- if (args > 2) {
- inst[0] = MOV_r_rm;
- inst[1] = MOD_DISP8 | (reg_map[SLJIT_S2] << 3) | reg_map[TMP_REG1];
- inst[2] = sizeof(sljit_sw) * 4;
- }
-#endif
-
- SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
-
-#if defined(__APPLE__)
- /* Ignore pushed registers and SLJIT_LOCALS_OFFSET when computing the aligned local size. */
- saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
- local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
-#else
- if (options & SLJIT_F64_ALIGNMENT)
- local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
- else
- local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
-#endif
-
- compiler->local_size = local_size;
-
-#ifdef _WIN32
- if (local_size > 0) {
- if (local_size <= 4 * 4096) {
- if (local_size > 4096)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096);
- if (local_size > 2 * 4096)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
- if (local_size > 3 * 4096)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
- }
- else {
- EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);
- EMIT_MOV(compiler, SLJIT_R1, 0, SLJIT_IMM, (local_size - 1) >> 12);
-
- SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);
-
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_R0), -4096);
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_R1, 0, SLJIT_R1, 0, SLJIT_IMM, 1));
-
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
- FAIL_IF(!inst);
-
- INC_SIZE(2);
- inst[0] = JNE_i8;
- inst[1] = (sljit_s8) -16;
- }
-
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
- }
-#endif
-
- SLJIT_ASSERT(local_size > 0);
-
-#if !defined(__APPLE__)
- if (options & SLJIT_F64_ALIGNMENT) {
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_SP, 0);
-
- /* Some space might allocated during sljit_grow_stack() above on WIN32. */
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size + sizeof(sljit_sw)));
-
-#if defined _WIN32 && !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (compiler->local_size > 1024)
- FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
- TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, sizeof(sljit_sw)));
-#endif
-
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 6);
- FAIL_IF(!inst);
-
- INC_SIZE(6);
- inst[0] = GROUP_BINARY_81;
- inst[1] = MOD_REG | AND | reg_map[SLJIT_SP];
- sljit_unaligned_store_sw(inst + 2, ~(sizeof(sljit_f64) - 1));
-
- /* The real local size must be used. */
- return emit_mov(compiler, SLJIT_MEM1(SLJIT_SP), compiler->local_size, TMP_REG1, 0);
- }
-#endif
- return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size);
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
- sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
- sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
-{
- CHECK_ERROR();
- CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
- set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
-
- compiler->args = get_arg_count(arg_types);
-
- /* [esp+0] for saving temporaries and function calls. */
- compiler->stack_tmp_size = 2 * sizeof(sljit_sw);
-
-#if !(defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (scratches > 3)
- compiler->stack_tmp_size = 3 * sizeof(sljit_sw);
-#endif
-
- compiler->saveds_offset = compiler->stack_tmp_size;
- if (scratches > 3)
- compiler->saveds_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * sizeof(sljit_sw);
-
- compiler->locals_offset = compiler->saveds_offset;
-
- if (saveds > 3)
- compiler->locals_offset += (saveds - 3) * sizeof(sljit_sw);
-
- if (options & SLJIT_F64_ALIGNMENT)
- compiler->locals_offset = (compiler->locals_offset + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1);
-
-#if defined(__APPLE__)
- saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * sizeof(sljit_uw);
- compiler->local_size = ((SLJIT_LOCALS_OFFSET + saveds + local_size + 15) & ~15) - saveds;
-#else
- if (options & SLJIT_F64_ALIGNMENT)
- compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_f64) - 1) & ~(sizeof(sljit_f64) - 1));
- else
- compiler->local_size = SLJIT_LOCALS_OFFSET + ((local_size + sizeof(sljit_sw) - 1) & ~(sizeof(sljit_sw) - 1));
-#endif
- return SLJIT_SUCCESS;
-}
-
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
-{
- sljit_s32 size;
- sljit_u8 *inst;
-
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
- SLJIT_ASSERT(compiler->args >= 0);
-
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
-
- SLJIT_ASSERT(compiler->local_size > 0);
-
-#if !defined(__APPLE__)
- if (compiler->options & SLJIT_F64_ALIGNMENT)
- EMIT_MOV(compiler, SLJIT_SP, 0, SLJIT_MEM1(SLJIT_SP), compiler->local_size)
- else
- FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
-#else
- FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, compiler->local_size));
-#endif
-
- size = 2 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) +
- (compiler->saveds <= 3 ? compiler->saveds : 3);
-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (compiler->args > 2)
- size += 2;
-#endif
- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!inst);
-
- INC_SIZE(size);
-
- if (compiler->saveds > 0 || compiler->scratches > 11)
- POP_REG(reg_map[SLJIT_S0]);
- if (compiler->saveds > 1 || compiler->scratches > 10)
- POP_REG(reg_map[SLJIT_S1]);
- if (compiler->saveds > 2 || compiler->scratches > 9)
- POP_REG(reg_map[SLJIT_S2]);
- POP_REG(reg_map[TMP_REG1]);
-#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
- if (compiler->args > 2)
- RET_I16(sizeof(sljit_sw));
- else
- RET();
-#else
- RET();
-#endif
-
- return SLJIT_SUCCESS;
-}
-
-/* --------------------------------------------------------------------- */
-/* Operators */
-/* --------------------------------------------------------------------- */
-
/* Size contains the flags as well. */
-static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,
/* The register or immediate operand. */
sljit_s32 a, sljit_sw imma,
/* The general operand (not immediate). */
@@ -353,8 +51,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
{
sljit_u8 *inst;
sljit_u8 *buf_ptr;
- sljit_s32 flags = size & ~0xf;
- sljit_s32 inst_size;
+ sljit_u8 reg_map_b;
+ sljit_uw flags = size;
+ sljit_uw inst_size;
/* Both cannot be switched on. */
SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
@@ -367,8 +66,6 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
&& (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
&& (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
- /* We don't support (%ebp). */
- SLJIT_ASSERT(!(b & SLJIT_MEM) || immb || reg_map[b & REG_MASK] != 5);
size &= 0xf;
inst_size = size;
@@ -381,7 +78,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
/* Calculate size of b. */
inst_size += 1; /* mod r/m byte. */
if (b & SLJIT_MEM) {
- if ((b & REG_MASK) == SLJIT_UNUSED)
+ if (!(b & REG_MASK))
inst_size += sizeof(sljit_sw);
else if (immb != 0 && !(b & OFFS_REG_MASK)) {
/* Immediate operand. */
@@ -390,11 +87,13 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
else
inst_size += sizeof(sljit_sw);
}
+ else if (reg_map[b & REG_MASK] == 5)
+ inst_size += sizeof(sljit_s8);
if ((b & REG_MASK) == SLJIT_SP && !(b & OFFS_REG_MASK))
b |= TO_OFFS_REG(SLJIT_SP);
- if ((b & OFFS_REG_MASK) != SLJIT_UNUSED)
+ if (b & OFFS_REG_MASK)
inst_size += 1; /* SIB byte. */
}
@@ -445,9 +144,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (a & SLJIT_IMM)
*buf_ptr = 0;
else if (!(flags & EX86_SSE2_OP1))
- *buf_ptr = reg_map[a] << 3;
+ *buf_ptr = U8(reg_map[a] << 3);
else
- *buf_ptr = a << 3;
+ *buf_ptr = U8(a << 3);
}
else {
if (a & SLJIT_IMM) {
@@ -460,27 +159,30 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
*buf_ptr = 0;
}
- if (!(b & SLJIT_MEM))
- *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_map[b] : b);
- else if ((b & REG_MASK) != SLJIT_UNUSED) {
- if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
- if (immb != 0) {
+ if (!(b & SLJIT_MEM)) {
+ *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_map[b] : b));
+ buf_ptr++;
+ } else if (b & REG_MASK) {
+ reg_map_b = reg_map[b & REG_MASK];
+
+ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_map_b == 5) {
+ if (immb != 0 || reg_map_b == 5) {
if (immb <= 127 && immb >= -128)
*buf_ptr |= 0x40;
else
*buf_ptr |= 0x80;
}
- if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
- *buf_ptr++ |= reg_map[b & REG_MASK];
+ if (!(b & OFFS_REG_MASK))
+ *buf_ptr++ |= reg_map_b;
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3);
+ *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3));
}
- if (immb != 0) {
+ if (immb != 0 || reg_map_b == 5) {
if (immb <= 127 && immb >= -128)
- *buf_ptr++ = immb; /* 8 bit displacement. */
+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */
else {
sljit_unaligned_store_sw(buf_ptr, immb); /* 32 bit displacement. */
buf_ptr += sizeof(sljit_sw);
@@ -489,7 +191,7 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
}
else {
*buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_map[b & REG_MASK] | (reg_map[OFFS_REG(b)] << 3) | (immb << 6);
+ *buf_ptr++ = U8(reg_map_b | (reg_map[OFFS_REG(b)] << 3) | (immb << 6));
}
}
else {
@@ -500,9 +202,9 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
if (a & SLJIT_IMM) {
if (flags & EX86_BYTE_ARG)
- *buf_ptr = imma;
+ *buf_ptr = U8(imma);
else if (flags & EX86_HALF_ARG)
- sljit_unaligned_store_s16(buf_ptr, imma);
+ sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);
else if (!(flags & EX86_SHIFT_INS))
sljit_unaligned_store_sw(buf_ptr, imma);
}
@@ -511,34 +213,449 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
}
/* --------------------------------------------------------------------- */
-/* Call / return instructions */
+/* Enter / return */
/* --------------------------------------------------------------------- */
+static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_sw executable_offset)
+{
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
+
+ if (type == SLJIT_JUMP) {
+ *code_ptr++ = JMP_i32;
+ jump->addr++;
+ }
+ else if (type >= SLJIT_FAST_CALL) {
+ *code_ptr++ = CALL_i32;
+ jump->addr++;
+ }
+ else {
+ *code_ptr++ = GROUP_0F;
+ *code_ptr++ = get_jump_code(type);
+ jump->addr += 2;
+ }
+
+ if (jump->flags & JUMP_LABEL)
+ jump->flags |= PATCH_MW;
+ else
+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)(jump->u.target - (jump->addr + 4) - (sljit_uw)executable_offset));
+ code_ptr += 4;
+
+ return code_ptr;
+}
+
+#define ENTER_R2_USED 0x00001
+#define ENTER_R2_TO_S 0x00002
+#define ENTER_R2_TO_R0 0x00004
+#define ENTER_R1_TO_S 0x00008
+#define ENTER_TMP_TO_R4 0x00010
+#define ENTER_TMP_TO_S 0x00020
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
+{
+ sljit_s32 word_arg_count, saved_arg_count, float_arg_count;
+ sljit_s32 size, locals_offset, args_size, types, status;
+ sljit_u8 *inst;
+#ifdef _WIN32
+ sljit_s32 r2_offset = -1;
+#endif
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
+ set_emit_enter(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
+
+ /* Emit ENDBR32 at function entry if needed. */
+ FAIL_IF(emit_endbranch(compiler));
+
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+ types = arg_types;
+ word_arg_count = 0;
+ saved_arg_count = 0;
+ float_arg_count = 0;
+ args_size = SSIZE_OF(sw);
+ status = 0;
+ while (types) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_load(compiler, 0, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));
+ args_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_load(compiler, 1, float_arg_count, SLJIT_MEM1(SLJIT_SP), args_size));
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+
+ if (!(types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ saved_arg_count++;
+ if (saved_arg_count == 4)
+ status |= ENTER_TMP_TO_S;
+ } else {
+ if (word_arg_count == 4)
+ status |= ENTER_TMP_TO_R4;
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (word_arg_count == 3)
+ status |= ENTER_R2_USED;
+#endif
+ }
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (word_arg_count <= 2 && !(options & SLJIT_ENTER_CDECL))
+ break;
+#endif
+
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ args_size -= SSIZE_OF(sw);
+ compiler->args_size = args_size;
+
+ /* [esp+0] for saving temporaries and function calls. */
+ locals_offset = 2 * SSIZE_OF(sw);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if ((options & SLJIT_ENTER_CDECL) && scratches >= 3)
+ locals_offset = 4 * SSIZE_OF(sw);
+#else
+ if (scratches >= 3)
+ locals_offset = 4 * SSIZE_OF(sw);
+#endif
+
+ compiler->scratches_offset = locals_offset;
+
+ if (scratches > 3)
+ locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw);
+
+ if (saveds > 3)
+ locals_offset += (saveds - 3) * SSIZE_OF(sw);
+
+ compiler->locals_offset = locals_offset;
+
+ size = 1 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3);
+ inst = (sljit_u8*)ensure_buf(compiler, (sljit_uw)(size + 1));
+ FAIL_IF(!inst);
+
+ INC_SIZE((sljit_uw)size);
+ PUSH_REG(reg_map[TMP_REG1]);
+ if (saveds > 2 || scratches > 9)
+ PUSH_REG(reg_map[SLJIT_S2]);
+ if (saveds > 1 || scratches > 10)
+ PUSH_REG(reg_map[SLJIT_S1]);
+ if (saveds > 0 || scratches > 11)
+ PUSH_REG(reg_map[SLJIT_S0]);
+
+ size *= SSIZE_OF(sw);
+
+ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S))
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), args_size + size);
-static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
+ size += SSIZE_OF(sw);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(options & SLJIT_ENTER_CDECL))
+ size += args_size;
+#endif
+
+ local_size = ((locals_offset + local_size + size + 0xf) & ~0xf) - size;
+ compiler->local_size = local_size;
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(options & SLJIT_ENTER_CDECL))
+ size -= args_size;
+#endif
+
+ word_arg_count = 0;
+ saved_arg_count = 0;
+ args_size = size;
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+ word_arg_count++;
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(options & SLJIT_ENTER_CDECL) && word_arg_count <= 2) {
+ if (word_arg_count == 1) {
+ if (status & ENTER_R2_USED) {
+ EMIT_MOV(compiler, (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) ? SLJIT_R0 : SLJIT_S0, 0, SLJIT_R2, 0);
+ } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ status |= ENTER_R2_TO_S;
+ saved_arg_count++;
+ } else
+ status |= ENTER_R2_TO_R0;
+ } else if (!(arg_types & SLJIT_ARG_TYPE_SCRATCH_REG)) {
+ status |= ENTER_R1_TO_S;
+ saved_arg_count++;
+ }
+ break;
+ }
+#endif
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ SLJIT_ASSERT(word_arg_count <= 3 || (status & ENTER_TMP_TO_R4));
+
+ if (word_arg_count <= 3) {
+#ifdef _WIN32
+ if (word_arg_count == 3 && local_size > 4 * 4096)
+ r2_offset = local_size + args_size;
+ else
+#endif
+ EMIT_MOV(compiler, word_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);
+ }
+ } else {
+ SLJIT_ASSERT(saved_arg_count <= 3 || (status & ENTER_TMP_TO_S));
+
+ if (saved_arg_count <= 3)
+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_MEM1(SLJIT_SP), args_size);
+ saved_arg_count++;
+ }
+ args_size += SSIZE_OF(sw);
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(options & SLJIT_ENTER_CDECL)) {
+ if (status & ENTER_R2_TO_R0)
+ EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_R2, 0);
+
+ saved_arg_count = 0;
+ if (status & ENTER_R2_TO_S) {
+ EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_R2, 0);
+ saved_arg_count++;
+ }
+
+ if (status & ENTER_R1_TO_S)
+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, SLJIT_R1, 0);
+ }
+#endif
+
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET > 0);
+
+#ifdef _WIN32
+ SLJIT_ASSERT(r2_offset == -1 || local_size > 4 * 4096);
+
+ if (local_size > 4096) {
+ if (local_size <= 4 * 4096) {
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+
+ if (local_size > 2 * 4096)
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 2);
+ if (local_size > 3 * 4096)
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
+ }
+ else {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_IMM, local_size >> 12);
+
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
+ FAIL_IF(!inst);
+
+ INC_SIZE(2);
+ inst[0] = LOOP_i8;
+ inst[1] = (sljit_u8)-16;
+ local_size &= 0xfff;
+ }
+ }
+
+ if (local_size > 0) {
+ BINARY_IMM32(OR, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
+ }
+
+ if (r2_offset != -1)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);
+
+#else /* !_WIN32 */
+
+ SLJIT_ASSERT(local_size > 0);
+
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
+
+#endif /* _WIN32 */
+
+ if (status & (ENTER_TMP_TO_R4 | ENTER_TMP_TO_S)) {
+ size = (status & ENTER_TMP_TO_R4) ? compiler->scratches_offset : compiler->locals_offset - SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), size, TMP_REG1, 0);
+ }
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *compiler,
+ sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
+ sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 stack_size = 0;
+ sljit_s32 args_size, locals_offset;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
sljit_s32 word_arg_count = 0;
+#endif
- arg_types >>= SLJIT_DEF_SHIFT;
+ CHECK_ERROR();
+ CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
+ set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ args_size = 0;
while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ break;
case SLJIT_ARG_TYPE_F32:
- stack_size += sizeof(sljit_f32);
+ args_size += SSIZE_OF(f32);
+ break;
+ default:
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (word_arg_count >= 2)
+ args_size += SSIZE_OF(sw);
+ word_arg_count++;
+#else
+ args_size += SSIZE_OF(sw);
+#endif
break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ compiler->args_size = args_size;
+
+ /* [esp+0] for saving temporaries and function calls. */
+ locals_offset = 2 * SSIZE_OF(sw);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if ((options & SLJIT_ENTER_CDECL) && scratches >= 3)
+ locals_offset = 4 * SSIZE_OF(sw);
+#else
+ if (scratches >= 3)
+ locals_offset = 4 * SSIZE_OF(sw);
+#endif
+
+ compiler->scratches_offset = locals_offset;
+
+ if (scratches > 3)
+ locals_offset += ((scratches > (3 + 6)) ? 6 : (scratches - 3)) * SSIZE_OF(sw);
+
+ if (saveds > 3)
+ locals_offset += (saveds - 3) * SSIZE_OF(sw);
+
+ compiler->locals_offset = locals_offset;
+
+ saveds = (2 + (scratches > 9 ? (scratches - 9) : 0) + (saveds <= 3 ? saveds : 3)) * SSIZE_OF(sw);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(options & SLJIT_ENTER_CDECL))
+ saveds += args_size;
+#endif
+
+ compiler->local_size = ((locals_offset + local_size + saveds + 0xf) & ~0xf) - saveds;
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
+{
+ sljit_uw size;
+ sljit_u8 *inst;
+
+ size = (sljit_uw)(1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) +
+ (compiler->saveds <= 3 ? compiler->saveds : 3));
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+
+ INC_SIZE(size);
+
+ if (compiler->saveds > 0 || compiler->scratches > 11)
+ POP_REG(reg_map[SLJIT_S0]);
+ if (compiler->saveds > 1 || compiler->scratches > 10)
+ POP_REG(reg_map[SLJIT_S1]);
+ if (compiler->saveds > 2 || compiler->scratches > 9)
+ POP_REG(reg_map[SLJIT_S2]);
+ POP_REG(reg_map[TMP_REG1]);
+
+ return SLJIT_SUCCESS;
+}
+
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
+{
+ sljit_uw size;
+ sljit_u8 *inst;
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
+
+ SLJIT_ASSERT(compiler->args_size >= 0);
+ SLJIT_ASSERT(compiler->local_size > 0);
+
+ BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0);
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+
+ size = 1;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL))
+ size = 3;
+#endif
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
+ FAIL_IF(!inst);
+
+ INC_SIZE(size);
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (compiler->args_size > 0 && !(compiler->options & SLJIT_ENTER_CDECL)) {
+ RET_I16(U8(compiler->args_size));
+ return SLJIT_SUCCESS;
+ }
+#endif
+
+ RET();
+ return SLJIT_SUCCESS;
+}
+
+/* --------------------------------------------------------------------- */
+/* Call / return instructions */
+/* --------------------------------------------------------------------- */
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+
+static sljit_sw c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
+{
+ sljit_sw stack_size = 0;
+ sljit_s32 word_arg_count = 0;
+
+ arg_types >>= SLJIT_ARG_SHIFT;
+
+ while (arg_types) {
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
- stack_size += sizeof(sljit_f64);
+ stack_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ stack_size += SSIZE_OF(f32);
break;
default:
word_arg_count++;
if (word_arg_count > 2)
- stack_size += sizeof(sljit_sw);
+ stack_size += SSIZE_OF(sw);
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
if (word_arg_count_ptr)
@@ -548,12 +665,12 @@ static sljit_s32 c_fast_call_get_stack_size(sljit_s32 arg_types, sljit_s32 *word
}
static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
- sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args)
+ sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count, sljit_s32 swap_args)
{
sljit_u8 *inst;
sljit_s32 float_arg_count;
- if (stack_size == sizeof(sljit_sw) && word_arg_count == 3) {
+ if (stack_size == SSIZE_OF(sw) && word_arg_count == 3) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
@@ -561,41 +678,40 @@ static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
}
else if (stack_size > 0) {
if (word_arg_count >= 4)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
+ BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);
stack_size = 0;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
word_arg_count = 0;
float_arg_count = 0;
while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- float_arg_count++;
- FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
- stack_size += sizeof(sljit_f32);
- break;
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
float_arg_count++;
FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
- stack_size += sizeof(sljit_f64);
+ stack_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
+ stack_size += SSIZE_OF(f32);
break;
default:
word_arg_count++;
if (word_arg_count == 3) {
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, SLJIT_R2, 0);
- stack_size += sizeof(sljit_sw);
+ stack_size += SSIZE_OF(sw);
}
else if (word_arg_count == 4) {
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, TMP_REG1, 0);
- stack_size += sizeof(sljit_sw);
+ stack_size += SSIZE_OF(sw);
}
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
}
@@ -605,7 +721,7 @@ static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
FAIL_IF(!inst);
INC_SIZE(1);
- *inst++ = XCHG_EAX_r | reg_map[SLJIT_R2];
+ *inst++ = U8(XCHG_EAX_r | reg_map[SLJIT_R2]);
}
else {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
@@ -613,7 +729,7 @@ static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
INC_SIZE(2);
*inst++ = MOV_r_rm;
- *inst++ = MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0];
+ *inst++ = U8(MOD_REG | (reg_map[SLJIT_R2] << 3) | reg_map[SLJIT_R0]);
}
}
@@ -624,77 +740,73 @@ static sljit_s32 c_fast_call_with_args(struct sljit_compiler *compiler,
static sljit_s32 cdecl_call_get_stack_size(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *word_arg_count_ptr)
{
- sljit_s32 stack_size = 0;
+ sljit_sw stack_size = 0;
sljit_s32 word_arg_count = 0;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- stack_size += sizeof(sljit_f32);
- break;
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
- stack_size += sizeof(sljit_f64);
+ stack_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ stack_size += SSIZE_OF(f32);
break;
default:
word_arg_count++;
- stack_size += sizeof(sljit_sw);
+ stack_size += SSIZE_OF(sw);
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
if (word_arg_count_ptr)
*word_arg_count_ptr = word_arg_count;
- if (stack_size <= compiler->stack_tmp_size)
+ if (stack_size <= compiler->scratches_offset)
return 0;
-#if defined(__APPLE__)
- return ((stack_size - compiler->stack_tmp_size + 15) & ~15);
-#else
- return stack_size - compiler->stack_tmp_size;
-#endif
+ return ((stack_size - compiler->scratches_offset + 0xf) & ~0xf);
}
static sljit_s32 cdecl_call_with_args(struct sljit_compiler *compiler,
- sljit_s32 arg_types, sljit_s32 stack_size, sljit_s32 word_arg_count)
+ sljit_s32 arg_types, sljit_sw stack_size, sljit_s32 word_arg_count)
{
sljit_s32 float_arg_count = 0;
+ sljit_u8 *inst;
if (word_arg_count >= 4)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->saveds_offset - sizeof(sljit_sw));
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);
if (stack_size > 0)
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
+ BINARY_IMM32(SUB, stack_size, SLJIT_SP, 0);
stack_size = 0;
word_arg_count = 0;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
- float_arg_count++;
- FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
- stack_size += sizeof(sljit_f32);
- break;
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
float_arg_count++;
FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
- stack_size += sizeof(sljit_f64);
+ stack_size += SSIZE_OF(f64);
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ float_arg_count++;
+ FAIL_IF(emit_sse2_store(compiler, 1, SLJIT_MEM1(SLJIT_SP), stack_size, float_arg_count));
+ stack_size += SSIZE_OF(f32);
break;
default:
word_arg_count++;
EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size, (word_arg_count >= 4) ? TMP_REG1 : word_arg_count, 0);
- stack_size += sizeof(sljit_sw);
+ stack_size += SSIZE_OF(sw);
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -707,13 +819,12 @@ static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,
sljit_s32 single;
if (stack_size > 0)
- FAIL_IF(emit_cum_binary(compiler, BINARY_OPCODE(ADD),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, stack_size));
+ BINARY_IMM32(ADD, stack_size, SLJIT_SP, 0);
- if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)
return SLJIT_SUCCESS;
- single = ((arg_types & SLJIT_DEF_MASK) == SLJIT_ARG_TYPE_F32);
+ single = ((arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 3);
FAIL_IF(!inst);
@@ -725,16 +836,399 @@ static sljit_s32 post_call_with_args(struct sljit_compiler *compiler,
return emit_sse2_load(compiler, single, SLJIT_FR0, SLJIT_MEM1(SLJIT_SP), 0);
}
+static sljit_s32 tail_call_with_args(struct sljit_compiler *compiler,
+ sljit_s32 *extra_space, sljit_s32 arg_types,
+ sljit_s32 src, sljit_sw srcw)
+{
+ sljit_sw args_size, prev_args_size, saved_regs_size;
+ sljit_sw types, word_arg_count, float_arg_count;
+ sljit_sw stack_size, prev_stack_size, min_size, offset;
+ sljit_sw word_arg4_offset;
+ sljit_u8 r2_offset = 0;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ sljit_u8 fast_call = (*extra_space & 0xff) == SLJIT_CALL;
+#endif
+ sljit_u8* inst;
+
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ CHECK_EXTRA_REGS(src, srcw, (void)0);
+
+ saved_regs_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)
+ + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);
+
+ word_arg_count = 0;
+ float_arg_count = 0;
+ arg_types >>= SLJIT_ARG_SHIFT;
+ types = 0;
+ args_size = 0;
+
+ while (arg_types != 0) {
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
+
+ switch (arg_types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ args_size += SSIZE_OF(f64);
+ float_arg_count++;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ args_size += SSIZE_OF(f32);
+ float_arg_count++;
+ break;
+ default:
+ word_arg_count++;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!fast_call || word_arg_count > 2)
+ args_size += SSIZE_OF(sw);
+#else
+ args_size += SSIZE_OF(sw);
+#endif
+ break;
+ }
+ arg_types >>= SLJIT_ARG_SHIFT;
+ }
+
+ if (args_size <= compiler->args_size
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ && (!(compiler->options & SLJIT_ENTER_CDECL) || args_size == 0 || !fast_call)
+#endif /* SLJIT_X86_32_FASTCALL */
+ && 1) {
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ *extra_space = fast_call ? 0 : args_size;
+ prev_args_size = compiler->args_size;
+ stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size;
+#else /* !SLJIT_X86_32_FASTCALL */
+ *extra_space = 0;
+ stack_size = args_size + SSIZE_OF(sw) + saved_regs_size;
+#endif /* SLJIT_X86_32_FASTCALL */
+
+ offset = stack_size + compiler->local_size;
+
+ if (!(src & SLJIT_IMM) && src != SLJIT_R0) {
+ if (word_arg_count >= 1) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
+ r2_offset = sizeof(sljit_sw);
+ }
+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);
+ }
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(compiler->options & SLJIT_ENTER_CDECL)) {
+ if (!fast_call)
+ offset -= SSIZE_OF(sw);
+
+ if (word_arg_count >= 3) {
+ word_arg4_offset = SSIZE_OF(sw);
+
+ if (word_arg_count + float_arg_count >= 4) {
+ word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(sw);
+ if ((types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F64)
+ word_arg4_offset = SSIZE_OF(sw) + SSIZE_OF(f64);
+ }
+
+ /* In cdecl mode, at least one more word value must
+ * be present on the stack before the return address. */
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - word_arg4_offset, SLJIT_R2, 0);
+ }
+
+ if (fast_call) {
+ if (args_size < prev_args_size) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size - SSIZE_OF(sw));
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset - args_size - SSIZE_OF(sw), SLJIT_R2, 0);
+ }
+ } else if (prev_args_size > 0) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset - prev_args_size);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ }
+ }
+#endif /* SLJIT_X86_32_FASTCALL */
+
+ while (types != 0) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ offset -= SSIZE_OF(f32);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ default:
+ switch (word_arg_count) {
+ case 1:
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (fast_call) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0);
+ break;
+ }
+#endif
+ offset -= SSIZE_OF(sw);
+ if (r2_offset != 0) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ } else
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);
+ break;
+ case 2:
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (fast_call)
+ break;
+#endif
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);
+ break;
+ case 3:
+ offset -= SSIZE_OF(sw);
+ break;
+ case 4:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), compiler->scratches_offset);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ break;
+ }
+ word_arg_count--;
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+ BINARY_IMM32(ADD, compiler->local_size, SLJIT_SP, 0);
+ FAIL_IF(emit_stack_frame_release(compiler));
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (args_size < prev_args_size)
+ BINARY_IMM32(ADD, prev_args_size - args_size, SLJIT_SP, 0);
+#endif
+
+ return SLJIT_SUCCESS;
+ }
+
+ stack_size = args_size + SSIZE_OF(sw);
+
+ if (word_arg_count >= 1 && !(src & SLJIT_IMM) && src != SLJIT_R0) {
+ r2_offset = SSIZE_OF(sw);
+ stack_size += SSIZE_OF(sw);
+ }
+
+ if (word_arg_count >= 3)
+ stack_size += SSIZE_OF(sw);
+
+ prev_args_size = 0;
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (!(compiler->options & SLJIT_ENTER_CDECL))
+ prev_args_size = compiler->args_size;
+#endif
+
+ prev_stack_size = prev_args_size + SSIZE_OF(sw) + saved_regs_size;
+ min_size = prev_stack_size + compiler->local_size;
+
+ word_arg4_offset = compiler->scratches_offset;
+
+ if (stack_size > min_size) {
+ BINARY_IMM32(SUB, stack_size - min_size, SLJIT_SP, 0);
+ if (src == SLJIT_MEM1(SLJIT_SP))
+ srcw += stack_size - min_size;
+ word_arg4_offset += stack_size - min_size;
+ }
+ else
+ stack_size = min_size;
+
+ if (word_arg_count >= 3) {
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), r2_offset, SLJIT_R2, 0);
+
+ if (word_arg_count >= 4)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), word_arg4_offset);
+ }
+
+ if (!(src & SLJIT_IMM) && src != SLJIT_R0) {
+ if (word_arg_count >= 1) {
+ SLJIT_ASSERT(r2_offset == sizeof(sljit_sw));
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, SLJIT_R0, 0);
+ }
+ EMIT_MOV(compiler, SLJIT_R0, 0, src, srcw);
+ }
+
+ /* Restore saved registers. */
+ offset = stack_size - prev_args_size - 2 * SSIZE_OF(sw);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), offset);
+
+ if (compiler->saveds > 2 || compiler->scratches > 9) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S2, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+ if (compiler->saveds > 1 || compiler->scratches > 10) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S1, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+ if (compiler->saveds > 0 || compiler->scratches > 11) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_S0, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ }
+
+ /* Copy fourth argument and return address. */
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (fast_call) {
+ offset = stack_size;
+ *extra_space = 0;
+
+ if (word_arg_count >= 4 && prev_args_size == 0) {
+ offset -= SSIZE_OF(sw);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
+
+ SLJIT_ASSERT(args_size != prev_args_size);
+ } else {
+ if (word_arg_count >= 4) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ }
+
+ if (args_size != prev_args_size)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw));
+ }
+
+ if (args_size != prev_args_size)
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - args_size - SSIZE_OF(sw), SLJIT_R2, 0);
+ } else {
+#endif /* SLJIT_X86_32_FASTCALL */
+ offset = stack_size - SSIZE_OF(sw);
+ *extra_space = args_size;
+
+ if (word_arg_count >= 4 && prev_args_size == SSIZE_OF(sw)) {
+ offset -= SSIZE_OF(sw);
+ inst = emit_x86_instruction(compiler, 1, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), offset);
+ FAIL_IF(!inst);
+ *inst = XCHG_r_rm;
+
+ SLJIT_ASSERT(prev_args_size > 0);
+ } else {
+ if (word_arg_count >= 4) {
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ }
+
+ if (prev_args_size > 0)
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), stack_size - prev_args_size - SSIZE_OF(sw));
+ }
+
+ /* Copy return address. */
+ if (prev_args_size > 0)
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), stack_size - SSIZE_OF(sw), SLJIT_R2, 0);
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ }
+#endif /* SLJIT_X86_32_FASTCALL */
+
+ while (types != 0) {
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
+ offset -= SSIZE_OF(f64);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ case SLJIT_ARG_TYPE_F32:
+ offset -= SSIZE_OF(f32);
+ FAIL_IF(emit_sse2_store(compiler, 0, SLJIT_MEM1(SLJIT_SP), offset, float_arg_count));
+ float_arg_count--;
+ break;
+ default:
+ switch (word_arg_count) {
+ case 1:
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (fast_call) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, r2_offset != 0 ? SLJIT_MEM1(SLJIT_SP) : SLJIT_R0, 0);
+ break;
+ }
+#endif
+ offset -= SSIZE_OF(sw);
+ if (r2_offset != 0) {
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), 0);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ } else
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R0, 0);
+ break;
+ case 2:
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ if (fast_call)
+ break;
+#endif
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R1, 0);
+ break;
+ case 3:
+ offset -= SSIZE_OF(sw);
+ EMIT_MOV(compiler, SLJIT_R2, 0, SLJIT_MEM1(SLJIT_SP), r2_offset);
+ EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), offset, SLJIT_R2, 0);
+ break;
+ }
+ word_arg_count--;
+ break;
+ }
+ types >>= SLJIT_ARG_SHIFT;
+ }
+
+#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
+ /* Skip return address. */
+ if (fast_call)
+ offset -= SSIZE_OF(sw);
+#endif
+
+ SLJIT_ASSERT(offset >= 0);
+
+ if (offset == 0)
+ return SLJIT_SUCCESS;
+
+ BINARY_IMM32(ADD, offset, SLJIT_SP, 0);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_s32 emit_tail_call_end(struct sljit_compiler *compiler, sljit_s32 extra_space)
+{
+ /* Called when stack consumption cannot be reduced to 0. */
+ sljit_u8 *inst;
+
+ BINARY_IMM32(ADD, extra_space, SLJIT_SP, 0);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ RET();
+
+ return SLJIT_SUCCESS;
+}
+
SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compiler *compiler, sljit_s32 type,
sljit_s32 arg_types)
{
struct sljit_jump *jump;
- sljit_s32 stack_size = 0;
+ sljit_sw stack_size = 0;
sljit_s32 word_arg_count;
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
+ if (type & SLJIT_CALL_RETURN) {
+ stack_size = type;
+ PTR_FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, SLJIT_IMM, 0));
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+
+ if (stack_size == 0) {
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ return sljit_emit_jump(compiler, type);
+ }
+
+ jump = sljit_emit_jump(compiler, type);
+ PTR_FAIL_IF(jump == NULL);
+
+ PTR_FAIL_IF(emit_tail_call_end(compiler, stack_size));
+ return jump;
+ }
+
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
if ((type & 0xff) == SLJIT_CALL) {
stack_size = c_fast_call_get_stack_size(arg_types, &word_arg_count);
@@ -772,7 +1266,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
sljit_s32 arg_types,
sljit_s32 src, sljit_sw srcw)
{
- sljit_s32 stack_size = 0;
+ sljit_sw stack_size = 0;
sljit_s32 word_arg_count;
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
sljit_s32 swap_args;
@@ -781,6 +1275,27 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
+ if (type & SLJIT_CALL_RETURN) {
+ stack_size = type;
+ FAIL_IF(tail_call_with_args(compiler, &stack_size, arg_types, src, srcw));
+
+ if (!(src & SLJIT_IMM)) {
+ src = SLJIT_R0;
+ srcw = 0;
+ }
+
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+
+ if (stack_size == 0)
+ return sljit_emit_ijump(compiler, SLJIT_JUMP, src, srcw);
+
+ FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
+ return emit_tail_call_end(compiler, stack_size);
+ }
+
#if (defined SLJIT_X86_32_FASTCALL && SLJIT_X86_32_FASTCALL)
SLJIT_ASSERT(reg_map[SLJIT_R0] == 0 && reg_map[SLJIT_R2] == 1 && SLJIT_R0 == 1 && SLJIT_R2 == 3);
@@ -800,7 +1315,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
FAIL_IF(c_fast_call_with_args(compiler, arg_types, stack_size, word_arg_count, swap_args));
- compiler->saveds_offset += stack_size;
+ compiler->scratches_offset += stack_size;
compiler->locals_offset += stack_size;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -809,7 +1324,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
#endif
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
- compiler->saveds_offset -= stack_size;
+ compiler->scratches_offset -= stack_size;
compiler->locals_offset -= stack_size;
return post_call_with_args(compiler, arg_types, 0);
@@ -819,7 +1334,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
stack_size = cdecl_call_get_stack_size(compiler, arg_types, &word_arg_count);
FAIL_IF(cdecl_call_with_args(compiler, arg_types, stack_size, word_arg_count));
- compiler->saveds_offset += stack_size;
+ compiler->scratches_offset += stack_size;
compiler->locals_offset += stack_size;
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
@@ -828,7 +1343,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
#endif
FAIL_IF(sljit_emit_ijump(compiler, type, src, srcw));
- compiler->saveds_offset -= stack_size;
+ compiler->scratches_offset -= stack_size;
compiler->locals_offset -= stack_size;
return post_call_with_args(compiler, arg_types, stack_size);
@@ -844,10 +1359,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK_EXTRA_REGS(dst, dstw, (void)0);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- dst = TMP_REG1;
-
if (FAST_IS_REG(dst)) {
/* Unused dest is possible here. */
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
@@ -895,34 +1406,18 @@ static sljit_s32 emit_fast_return(struct sljit_compiler *compiler, sljit_s32 src
static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
{
- sljit_s32 size, saved_size;
- sljit_s32 has_f64_aligment;
+ sljit_sw size;
/* Don't adjust shadow stack if it isn't enabled. */
- if (!cpu_has_shadow_stack ())
+ if (!cpu_has_shadow_stack())
return SLJIT_SUCCESS;
- SLJIT_ASSERT(compiler->args >= 0);
+ SLJIT_ASSERT(compiler->args_size >= 0);
SLJIT_ASSERT(compiler->local_size > 0);
-#if !defined(__APPLE__)
- has_f64_aligment = compiler->options & SLJIT_F64_ALIGNMENT;
-#else
- has_f64_aligment = 0;
-#endif
-
size = compiler->local_size;
- saved_size = (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0) + (compiler->saveds <= 3 ? compiler->saveds : 3)) * sizeof(sljit_uw);
- if (has_f64_aligment) {
- /* mov TMP_REG1, [esp + local_size]. */
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), size);
- /* mov TMP_REG1, [TMP_REG1+ saved_size]. */
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), saved_size);
- /* Move return address to [esp]. */
- EMIT_MOV(compiler, SLJIT_MEM1(SLJIT_SP), 0, TMP_REG1, 0);
- size = 0;
- } else
- size += saved_size;
-
- return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);
+ size += (1 + (compiler->scratches > 9 ? (compiler->scratches - 9) : 0)
+ + (compiler->saveds <= 3 ? compiler->saveds : 3)) * SSIZE_OF(sw);
+
+ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
index e85b56a61a..f37df6e1bf 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_64.c
@@ -26,6 +26,10 @@
/* x86 64-bit arch dependent functions. */
+/* --------------------------------------------------------------------- */
+/* Operators */
+/* --------------------------------------------------------------------- */
+
static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg, sljit_sw imm)
{
sljit_u8 *inst;
@@ -34,14 +38,246 @@ static sljit_s32 emit_load_imm64(struct sljit_compiler *compiler, sljit_s32 reg,
FAIL_IF(!inst);
INC_SIZE(2 + sizeof(sljit_sw));
*inst++ = REX_W | ((reg_map[reg] <= 7) ? 0 : REX_B);
- *inst++ = MOV_r_i32 + (reg_map[reg] & 0x7);
+ *inst++ = U8(MOV_r_i32 | (reg_map[reg] & 0x7));
sljit_unaligned_store_sw(inst, imm);
return SLJIT_SUCCESS;
}
+static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)
+{
+ sljit_u8 *inst;
+ sljit_uw length = (rex ? 2 : 1) + sizeof(sljit_s32);
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + length);
+ FAIL_IF(!inst);
+ INC_SIZE(length);
+ if (rex)
+ *inst++ = rex;
+ *inst++ = opcode;
+ sljit_unaligned_store_s32(inst, (sljit_s32)imm);
+ return SLJIT_SUCCESS;
+}
+
+static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_uw size,
+ /* The register or immediate operand. */
+ sljit_s32 a, sljit_sw imma,
+ /* The general operand (not immediate). */
+ sljit_s32 b, sljit_sw immb)
+{
+ sljit_u8 *inst;
+ sljit_u8 *buf_ptr;
+ sljit_u8 rex = 0;
+ sljit_u8 reg_lmap_b;
+ sljit_uw flags = size;
+ sljit_uw inst_size;
+
+ /* The immediate operand must be 32 bit. */
+ SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
+ /* Both cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
+ /* Size flags not allowed for typed instructions. */
+ SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
+ /* Both size flags cannot be switched on. */
+ SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
+ /* SSE2 and immediate is not possible. */
+ SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
+ SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
+ && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
+ && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
+
+ size &= 0xf;
+ inst_size = size;
+
+ if (!compiler->mode32 && !(flags & EX86_NO_REXW))
+ rex |= REX_W;
+ else if (flags & EX86_REX)
+ rex |= REX;
+
+ if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
+ inst_size++;
+ if (flags & EX86_PREF_66)
+ inst_size++;
+
+ /* Calculate size of b. */
+ inst_size += 1; /* mod r/m byte. */
+ if (b & SLJIT_MEM) {
+ if (!(b & OFFS_REG_MASK)) {
+ if (NOT_HALFWORD(immb)) {
+ PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
+ immb = 0;
+ if (b & REG_MASK)
+ b |= TO_OFFS_REG(TMP_REG2);
+ else
+ b |= TMP_REG2;
+ }
+ else if (reg_lmap[b & REG_MASK] == 4)
+ b |= TO_OFFS_REG(SLJIT_SP);
+ }
+
+ if (!(b & REG_MASK))
+ inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
+ else {
+ if (reg_map[b & REG_MASK] >= 8)
+ rex |= REX_B;
+
+ if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
+ /* Immediate operand. */
+ if (immb <= 127 && immb >= -128)
+ inst_size += sizeof(sljit_s8);
+ else
+ inst_size += sizeof(sljit_s32);
+ }
+ else if (reg_lmap[b & REG_MASK] == 5)
+ inst_size += sizeof(sljit_s8);
+
+ if (b & OFFS_REG_MASK) {
+ inst_size += 1; /* SIB byte. */
+ if (reg_map[OFFS_REG(b)] >= 8)
+ rex |= REX_X;
+ }
+ }
+ }
+ else if (!(flags & EX86_SSE2_OP2)) {
+ if (reg_map[b] >= 8)
+ rex |= REX_B;
+ }
+ else if (freg_map[b] >= 8)
+ rex |= REX_B;
+
+ if (a & SLJIT_IMM) {
+ if (flags & EX86_BIN_INS) {
+ if (imma <= 127 && imma >= -128) {
+ inst_size += 1;
+ flags |= EX86_BYTE_ARG;
+ } else
+ inst_size += 4;
+ }
+ else if (flags & EX86_SHIFT_INS) {
+ imma &= compiler->mode32 ? 0x1f : 0x3f;
+ if (imma != 1) {
+ inst_size ++;
+ flags |= EX86_BYTE_ARG;
+ }
+ } else if (flags & EX86_BYTE_ARG)
+ inst_size++;
+ else if (flags & EX86_HALF_ARG)
+ inst_size += sizeof(short);
+ else
+ inst_size += sizeof(sljit_s32);
+ }
+ else {
+ SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
+ /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
+ if (!(flags & EX86_SSE2_OP1)) {
+ if (reg_map[a] >= 8)
+ rex |= REX_R;
+ }
+ else if (freg_map[a] >= 8)
+ rex |= REX_R;
+ }
+
+ if (rex)
+ inst_size++;
+
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
+ PTR_FAIL_IF(!inst);
+
+ /* Encoding the byte. */
+ INC_SIZE(inst_size);
+ if (flags & EX86_PREF_F2)
+ *inst++ = 0xf2;
+ if (flags & EX86_PREF_F3)
+ *inst++ = 0xf3;
+ if (flags & EX86_PREF_66)
+ *inst++ = 0x66;
+ if (rex)
+ *inst++ = rex;
+ buf_ptr = inst + size;
+
+ /* Encode mod/rm byte. */
+ if (!(flags & EX86_SHIFT_INS)) {
+ if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
+ *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
+
+ if (a & SLJIT_IMM)
+ *buf_ptr = 0;
+ else if (!(flags & EX86_SSE2_OP1))
+ *buf_ptr = U8(reg_lmap[a] << 3);
+ else
+ *buf_ptr = U8(freg_lmap[a] << 3);
+ }
+ else {
+ if (a & SLJIT_IMM) {
+ if (imma == 1)
+ *inst = GROUP_SHIFT_1;
+ else
+ *inst = GROUP_SHIFT_N;
+ } else
+ *inst = GROUP_SHIFT_CL;
+ *buf_ptr = 0;
+ }
+
+ if (!(b & SLJIT_MEM)) {
+ *buf_ptr = U8(*buf_ptr | MOD_REG | (!(flags & EX86_SSE2_OP2) ? reg_lmap[b] : freg_lmap[b]));
+ buf_ptr++;
+ } else if (b & REG_MASK) {
+ reg_lmap_b = reg_lmap[b & REG_MASK];
+
+ if (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP) || reg_lmap_b == 5) {
+ if (immb != 0 || reg_lmap_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr |= 0x40;
+ else
+ *buf_ptr |= 0x80;
+ }
+
+ if (!(b & OFFS_REG_MASK))
+ *buf_ptr++ |= reg_lmap_b;
+ else {
+ *buf_ptr++ |= 0x04;
+ *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3));
+ }
+
+ if (immb != 0 || reg_lmap_b == 5) {
+ if (immb <= 127 && immb >= -128)
+ *buf_ptr++ = U8(immb); /* 8 bit displacement. */
+ else {
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_s32);
+ }
+ }
+ }
+ else {
+ *buf_ptr++ |= 0x04;
+ *buf_ptr++ = U8(reg_lmap_b | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6));
+ }
+ }
+ else {
+ *buf_ptr++ |= 0x04;
+ *buf_ptr++ = 0x25;
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)immb); /* 32 bit displacement. */
+ buf_ptr += sizeof(sljit_s32);
+ }
+
+ if (a & SLJIT_IMM) {
+ if (flags & EX86_BYTE_ARG)
+ *buf_ptr = U8(imma);
+ else if (flags & EX86_HALF_ARG)
+ sljit_unaligned_store_s16(buf_ptr, (sljit_s16)imma);
+ else if (!(flags & EX86_SHIFT_INS))
+ sljit_unaligned_store_s32(buf_ptr, (sljit_s32)imma);
+ }
+
+ return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
+}
+
+/* --------------------------------------------------------------------- */
+/* Enter / return */
+/* --------------------------------------------------------------------- */
+
static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr)
{
- sljit_s32 type = jump->flags >> TYPE_SHIFT;
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
int short_addr = !(jump->flags & SLJIT_REWRITABLE_JUMP) && !(jump->flags & JUMP_LABEL) && (jump->u.target <= 0xffffffff);
@@ -50,7 +286,7 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
if (type < SLJIT_JUMP) {
/* Invert type. */
- *code_ptr++ = get_jump_code(type ^ 0x1) - 0x10;
+ *code_ptr++ = U8(get_jump_code(type ^ 0x1) - 0x10);
*code_ptr++ = short_addr ? (6 + 3) : (10 + 3);
}
@@ -63,13 +299,13 @@ static sljit_u8* generate_far_jump_code(struct sljit_jump *jump, sljit_u8 *code_
else if (short_addr)
sljit_unaligned_store_s32(code_ptr, (sljit_s32)jump->u.target);
else
- sljit_unaligned_store_sw(code_ptr, jump->u.target);
+ sljit_unaligned_store_sw(code_ptr, (sljit_sw)jump->u.target);
code_ptr += short_addr ? sizeof(sljit_s32) : sizeof(sljit_sw);
*code_ptr++ = REX_B;
*code_ptr++ = GROUP_FF;
- *code_ptr++ = MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2];
+ *code_ptr++ = U8(MOD_REG | (type >= SLJIT_FAST_CALL ? CALL_rm : JMP_rm) | reg_lmap[TMP_REG2]);
return code_ptr;
}
@@ -90,7 +326,7 @@ static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, slji
SLJIT_ASSERT((code_ptr[1] & 0xf8) == MOV_r_i32);
if ((code_ptr[0] & 0x07) != 0) {
- code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x08);
+ code_ptr[0] = U8(code_ptr[0] & ~0x08);
code_ptr += 2 + sizeof(sljit_s32);
}
else {
@@ -114,9 +350,9 @@ static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, slji
SLJIT_ASSERT(code_ptr[1] == MOV_rm_r);
- code_ptr[0] = (sljit_u8)(code_ptr[0] & ~0x4);
+ code_ptr[0] = U8(code_ptr[0] & ~0x4);
code_ptr[1] = MOV_rm_i32;
- code_ptr[2] = (sljit_u8)(code_ptr[2] & ~(0x7 << 3));
+ code_ptr[2] = U8(code_ptr[2] & ~(0x7 << 3));
code_ptr = (sljit_u8*)(put_label->addr - (2 + sizeof(sljit_uw)) + sizeof(sljit_s32));
put_label->addr = (sljit_uw)code_ptr;
@@ -128,7 +364,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 args, i, tmp, size, saved_register_size;
+ sljit_uw size;
+ sljit_s32 word_arg_count = 0;
+ sljit_s32 saved_arg_count = 0;
+ sljit_s32 saved_regs_size, tmp, i;
+#ifdef _WIN64
+ sljit_s32 saved_float_regs_size;
+ sljit_s32 saved_float_regs_offset = 0;
+ sljit_s32 float_arg_count = 0;
+#endif /* _WIN64 */
sljit_u8 *inst;
CHECK_ERROR();
@@ -140,19 +384,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
compiler->mode32 = 0;
-#ifdef _WIN64
- /* Two/four register slots for parameters plus space for xmm6 register if needed. */
- if (fscratches >= 6 || fsaveds >= 1)
- compiler->locals_offset = 6 * sizeof(sljit_sw);
- else
- compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
-#endif
-
/* Including the return address saved by the call instruction. */
- saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
- for (i = SLJIT_S0; i >= tmp; i--) {
+ tmp = SLJIT_S0 - saveds;
+ for (i = SLJIT_S0; i > tmp; i--) {
size = reg_map[i] >= 8 ? 2 : 1;
inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
FAIL_IF(!inst);
@@ -172,55 +408,75 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
PUSH_REG(reg_lmap[i]);
}
- args = get_arg_count(arg_types);
+#ifdef _WIN64
+ local_size += SLJIT_LOCALS_OFFSET;
+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
- if (args > 0) {
- size = args * 3;
- inst = (sljit_u8*)ensure_buf(compiler, 1 + size);
- FAIL_IF(!inst);
+ if (saved_float_regs_size > 0) {
+ saved_float_regs_offset = ((local_size + 0xf) & ~0xf);
+ local_size = saved_float_regs_offset + saved_float_regs_size;
+ }
+#else /* !_WIN64 */
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);
+#endif /* _WIN64 */
- INC_SIZE(size);
+ arg_types >>= SLJIT_ARG_SHIFT;
+ while (arg_types > 0) {
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64) {
+ tmp = 0;
#ifndef _WIN64
- if (args > 0) {
- inst[0] = REX_W;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x7 /* rdi */;
- inst += 3;
- }
- if (args > 1) {
- inst[0] = REX_W | REX_R;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_lmap[SLJIT_S1] << 3) | 0x6 /* rsi */;
- inst += 3;
- }
- if (args > 2) {
- inst[0] = REX_W | REX_R;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_lmap[SLJIT_S2] << 3) | 0x2 /* rdx */;
- }
-#else
- if (args > 0) {
- inst[0] = REX_W;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_map[SLJIT_S0] << 3) | 0x1 /* rcx */;
- inst += 3;
- }
- if (args > 1) {
- inst[0] = REX_W;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_map[SLJIT_S1] << 3) | 0x2 /* rdx */;
- inst += 3;
- }
- if (args > 2) {
- inst[0] = REX_W | REX_B;
- inst[1] = MOV_r_rm;
- inst[2] = MOD_REG | (reg_map[SLJIT_S2] << 3) | 0x0 /* r8 */;
+ switch (word_arg_count) {
+ case 0:
+ tmp = SLJIT_R2;
+ break;
+ case 1:
+ tmp = SLJIT_R1;
+ break;
+ case 2:
+ tmp = TMP_REG1;
+ break;
+ default:
+ tmp = SLJIT_R3;
+ break;
+ }
+#else /* !_WIN64 */
+ switch (word_arg_count + float_arg_count) {
+ case 0:
+ tmp = SLJIT_R3;
+ break;
+ case 1:
+ tmp = SLJIT_R1;
+ break;
+ case 2:
+ tmp = SLJIT_R2;
+ break;
+ default:
+ tmp = TMP_REG1;
+ break;
+ }
+#endif /* _WIN64 */
+ if (arg_types & SLJIT_ARG_TYPE_SCRATCH_REG) {
+ if (tmp != SLJIT_R0 + word_arg_count)
+ EMIT_MOV(compiler, SLJIT_R0 + word_arg_count, 0, tmp, 0);
+ } else {
+ EMIT_MOV(compiler, SLJIT_S0 - saved_arg_count, 0, tmp, 0);
+ saved_arg_count++;
+ }
+ word_arg_count++;
+ } else {
+#ifdef _WIN64
+ SLJIT_COMPILE_ASSERT(SLJIT_FR0 == 1, float_register_index_start);
+ float_arg_count++;
+ if (float_arg_count != float_arg_count + word_arg_count)
+ FAIL_IF(emit_sse2_load(compiler, (arg_types & SLJIT_ARG_MASK) == SLJIT_ARG_TYPE_F32,
+ float_arg_count, float_arg_count + word_arg_count, 0));
+#endif /* _WIN64 */
}
-#endif
+ arg_types >>= SLJIT_ARG_SHIFT;
}
- local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
+ local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;
compiler->local_size = local_size;
#ifdef _WIN64
@@ -234,44 +490,49 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_enter(struct sljit_compiler *compi
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -4096 * 3);
}
else {
- EMIT_MOV(compiler, SLJIT_R0, 0, SLJIT_SP, 0);
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, (local_size - 1) >> 12);
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, local_size >> 12);
- SLJIT_ASSERT (reg_map[SLJIT_R0] == 0);
-
- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_R0), -4096);
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_IMM, 4096));
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- TMP_REG1, 0, TMP_REG1, 0, SLJIT_IMM, 1));
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_MEM1(SLJIT_SP), -4096);
+ BINARY_IMM32(SUB, 4096, SLJIT_SP, 0);
+ BINARY_IMM32(SUB, 1, TMP_REG1, 0);
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2);
FAIL_IF(!inst);
INC_SIZE(2);
inst[0] = JNE_i8;
- inst[1] = (sljit_s8) -19;
+ inst[1] = (sljit_u8)-21;
+ local_size &= 0xfff;
}
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
+ if (local_size > 0)
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(SLJIT_SP), -local_size);
}
-#endif
+#endif /* _WIN64 */
- if (local_size > 0) {
- FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
- SLJIT_SP, 0, SLJIT_SP, 0, SLJIT_IMM, local_size));
- }
+ if (local_size > 0)
+ BINARY_IMM32(SUB, local_size, SLJIT_SP, 0);
#ifdef _WIN64
- /* Save xmm6 register: movaps [rsp + 0x20], xmm6 */
- if (fscratches >= 6 || fsaveds >= 1) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!inst);
- INC_SIZE(5);
- *inst++ = GROUP_0F;
- sljit_unaligned_store_s32(inst, 0x20247429);
+ if (saved_float_regs_size > 0) {
+ compiler->mode32 = 1;
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
+ *inst++ = GROUP_0F;
+ *inst = MOVAPS_xm_x;
+ saved_float_regs_offset += 16;
+ }
+
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
+ *inst++ = GROUP_0F;
+ *inst = MOVAPS_xm_x;
+ saved_float_regs_offset += 16;
+ }
}
-#endif
+#endif /* _WIN64 */
return SLJIT_SUCCESS;
}
@@ -280,46 +541,65 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_set_context(struct sljit_compiler *comp
sljit_s32 options, sljit_s32 arg_types, sljit_s32 scratches, sljit_s32 saveds,
sljit_s32 fscratches, sljit_s32 fsaveds, sljit_s32 local_size)
{
- sljit_s32 saved_register_size;
+ sljit_s32 saved_regs_size;
+#ifdef _WIN64
+ sljit_s32 saved_float_regs_size;
+#endif /* _WIN64 */
CHECK_ERROR();
CHECK(check_sljit_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size));
set_set_context(compiler, options, arg_types, scratches, saveds, fscratches, fsaveds, local_size);
#ifdef _WIN64
- /* Two/four register slots for parameters plus space for xmm6 register if needed. */
- if (fscratches >= 6 || fsaveds >= 1)
- compiler->locals_offset = 6 * sizeof(sljit_sw);
- else
- compiler->locals_offset = ((scratches > 2) ? 4 : 2) * sizeof(sljit_sw);
-#endif
+ local_size += SLJIT_LOCALS_OFFSET;
+ saved_float_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
+
+ if (saved_float_regs_size > 0)
+ local_size = ((local_size + 0xf) & ~0xf) + saved_float_regs_size;
+#else /* !_WIN64 */
+ SLJIT_ASSERT(SLJIT_LOCALS_OFFSET == 0);
+#endif /* _WIN64 */
/* Including the return address saved by the call instruction. */
- saved_register_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
- compiler->local_size = ((local_size + SLJIT_LOCALS_OFFSET + saved_register_size + 15) & ~15) - saved_register_size;
+ saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1);
+ compiler->local_size = ((local_size + saved_regs_size + 0xf) & ~0xf) - saved_regs_size;
return SLJIT_SUCCESS;
}
-SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *compiler, sljit_s32 op, sljit_s32 src, sljit_sw srcw)
+static sljit_s32 emit_stack_frame_release(struct sljit_compiler *compiler)
{
- sljit_s32 i, tmp, size;
+ sljit_uw size;
+ sljit_s32 i, tmp;
sljit_u8 *inst;
+#ifdef _WIN64
+ sljit_s32 saved_float_regs_offset;
+ sljit_s32 fscratches = compiler->fscratches;
+ sljit_s32 fsaveds = compiler->fsaveds;
+#endif /* _WIN64 */
- CHECK_ERROR();
- CHECK(check_sljit_emit_return(compiler, op, src, srcw));
+#ifdef _WIN64
+ saved_float_regs_offset = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 16);
- FAIL_IF(emit_mov_before_return(compiler, op, src, srcw));
+ if (saved_float_regs_offset > 0) {
+ compiler->mode32 = 1;
+ saved_float_regs_offset = (compiler->local_size - saved_float_regs_offset) & ~0xf;
+
+ tmp = SLJIT_FS0 - fsaveds;
+ for (i = SLJIT_FS0; i > tmp; i--) {
+ inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
+ *inst++ = GROUP_0F;
+ *inst = MOVAPS_x_xm;
+ saved_float_regs_offset += 16;
+ }
-#ifdef _WIN64
- /* Restore xmm6 register: movaps xmm6, [rsp + 0x20] */
- if (compiler->fscratches >= 6 || compiler->fsaveds >= 1) {
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 5);
- FAIL_IF(!inst);
- INC_SIZE(5);
- *inst++ = GROUP_0F;
- sljit_unaligned_store_s32(inst, 0x20247428);
+ for (i = fscratches; i >= SLJIT_FIRST_SAVED_FLOAT_REG; i--) {
+ inst = emit_x86_instruction(compiler, 2 | EX86_SSE2, i, 0, SLJIT_MEM1(SLJIT_SP), saved_float_regs_offset);
+ *inst++ = GROUP_0F;
+ *inst = MOVAPS_x_xm;
+ saved_float_regs_offset += 16;
+ }
}
-#endif
+#endif /* _WIN64 */
if (compiler->local_size > 0) {
if (compiler->local_size <= 127) {
@@ -329,7 +609,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
*inst++ = REX_W;
*inst++ = GROUP_BINARY_83;
*inst++ = MOD_REG | ADD | 4;
- *inst = compiler->local_size;
+ *inst = U8(compiler->local_size);
}
else {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 7);
@@ -364,243 +644,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return(struct sljit_compiler *comp
POP_REG(reg_lmap[i]);
}
- inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
- FAIL_IF(!inst);
- INC_SIZE(1);
- RET();
- return SLJIT_SUCCESS;
-}
-
-/* --------------------------------------------------------------------- */
-/* Operators */
-/* --------------------------------------------------------------------- */
-
-static sljit_s32 emit_do_imm32(struct sljit_compiler *compiler, sljit_u8 rex, sljit_u8 opcode, sljit_sw imm)
-{
- sljit_u8 *inst;
- sljit_s32 length = 1 + (rex ? 1 : 0) + sizeof(sljit_s32);
-
- inst = (sljit_u8*)ensure_buf(compiler, 1 + length);
- FAIL_IF(!inst);
- INC_SIZE(length);
- if (rex)
- *inst++ = rex;
- *inst++ = opcode;
- sljit_unaligned_store_s32(inst, imm);
return SLJIT_SUCCESS;
}
-static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32 size,
- /* The register or immediate operand. */
- sljit_s32 a, sljit_sw imma,
- /* The general operand (not immediate). */
- sljit_s32 b, sljit_sw immb)
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_return_void(struct sljit_compiler *compiler)
{
sljit_u8 *inst;
- sljit_u8 *buf_ptr;
- sljit_u8 rex = 0;
- sljit_s32 flags = size & ~0xf;
- sljit_s32 inst_size;
-
- /* The immediate operand must be 32 bit. */
- SLJIT_ASSERT(!(a & SLJIT_IMM) || compiler->mode32 || IS_HALFWORD(imma));
- /* Both cannot be switched on. */
- SLJIT_ASSERT((flags & (EX86_BIN_INS | EX86_SHIFT_INS)) != (EX86_BIN_INS | EX86_SHIFT_INS));
- /* Size flags not allowed for typed instructions. */
- SLJIT_ASSERT(!(flags & (EX86_BIN_INS | EX86_SHIFT_INS)) || (flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) == 0);
- /* Both size flags cannot be switched on. */
- SLJIT_ASSERT((flags & (EX86_BYTE_ARG | EX86_HALF_ARG)) != (EX86_BYTE_ARG | EX86_HALF_ARG));
- /* SSE2 and immediate is not possible. */
- SLJIT_ASSERT(!(a & SLJIT_IMM) || !(flags & EX86_SSE2));
- SLJIT_ASSERT((flags & (EX86_PREF_F2 | EX86_PREF_F3)) != (EX86_PREF_F2 | EX86_PREF_F3)
- && (flags & (EX86_PREF_F2 | EX86_PREF_66)) != (EX86_PREF_F2 | EX86_PREF_66)
- && (flags & (EX86_PREF_F3 | EX86_PREF_66)) != (EX86_PREF_F3 | EX86_PREF_66));
-
- size &= 0xf;
- inst_size = size;
-
- if (!compiler->mode32 && !(flags & EX86_NO_REXW))
- rex |= REX_W;
- else if (flags & EX86_REX)
- rex |= REX;
-
- if (flags & (EX86_PREF_F2 | EX86_PREF_F3))
- inst_size++;
- if (flags & EX86_PREF_66)
- inst_size++;
-
- /* Calculate size of b. */
- inst_size += 1; /* mod r/m byte. */
- if (b & SLJIT_MEM) {
- if (!(b & OFFS_REG_MASK)) {
- if (NOT_HALFWORD(immb)) {
- PTR_FAIL_IF(emit_load_imm64(compiler, TMP_REG2, immb));
- immb = 0;
- if (b & REG_MASK)
- b |= TO_OFFS_REG(TMP_REG2);
- else
- b |= TMP_REG2;
- }
- else if (reg_lmap[b & REG_MASK] == 4)
- b |= TO_OFFS_REG(SLJIT_SP);
- }
-
- if ((b & REG_MASK) == SLJIT_UNUSED)
- inst_size += 1 + sizeof(sljit_s32); /* SIB byte required to avoid RIP based addressing. */
- else {
- if (reg_map[b & REG_MASK] >= 8)
- rex |= REX_B;
-
- if (immb != 0 && (!(b & OFFS_REG_MASK) || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP))) {
- /* Immediate operand. */
- if (immb <= 127 && immb >= -128)
- inst_size += sizeof(sljit_s8);
- else
- inst_size += sizeof(sljit_s32);
- }
- else if (reg_lmap[b & REG_MASK] == 5)
- inst_size += sizeof(sljit_s8);
-
- if ((b & OFFS_REG_MASK) != SLJIT_UNUSED) {
- inst_size += 1; /* SIB byte. */
- if (reg_map[OFFS_REG(b)] >= 8)
- rex |= REX_X;
- }
- }
- }
- else if (!(flags & EX86_SSE2_OP2)) {
- if (reg_map[b] >= 8)
- rex |= REX_B;
- }
- else if (freg_map[b] >= 8)
- rex |= REX_B;
-
- if (a & SLJIT_IMM) {
- if (flags & EX86_BIN_INS) {
- if (imma <= 127 && imma >= -128) {
- inst_size += 1;
- flags |= EX86_BYTE_ARG;
- } else
- inst_size += 4;
- }
- else if (flags & EX86_SHIFT_INS) {
- imma &= compiler->mode32 ? 0x1f : 0x3f;
- if (imma != 1) {
- inst_size ++;
- flags |= EX86_BYTE_ARG;
- }
- } else if (flags & EX86_BYTE_ARG)
- inst_size++;
- else if (flags & EX86_HALF_ARG)
- inst_size += sizeof(short);
- else
- inst_size += sizeof(sljit_s32);
- }
- else {
- SLJIT_ASSERT(!(flags & EX86_SHIFT_INS) || a == SLJIT_PREF_SHIFT_REG);
- /* reg_map[SLJIT_PREF_SHIFT_REG] is less than 8. */
- if (!(flags & EX86_SSE2_OP1)) {
- if (reg_map[a] >= 8)
- rex |= REX_R;
- }
- else if (freg_map[a] >= 8)
- rex |= REX_R;
- }
-
- if (rex)
- inst_size++;
-
- inst = (sljit_u8*)ensure_buf(compiler, 1 + inst_size);
- PTR_FAIL_IF(!inst);
-
- /* Encoding the byte. */
- INC_SIZE(inst_size);
- if (flags & EX86_PREF_F2)
- *inst++ = 0xf2;
- if (flags & EX86_PREF_F3)
- *inst++ = 0xf3;
- if (flags & EX86_PREF_66)
- *inst++ = 0x66;
- if (rex)
- *inst++ = rex;
- buf_ptr = inst + size;
-
- /* Encode mod/rm byte. */
- if (!(flags & EX86_SHIFT_INS)) {
- if ((flags & EX86_BIN_INS) && (a & SLJIT_IMM))
- *inst = (flags & EX86_BYTE_ARG) ? GROUP_BINARY_83 : GROUP_BINARY_81;
- if (a & SLJIT_IMM)
- *buf_ptr = 0;
- else if (!(flags & EX86_SSE2_OP1))
- *buf_ptr = reg_lmap[a] << 3;
- else
- *buf_ptr = freg_lmap[a] << 3;
- }
- else {
- if (a & SLJIT_IMM) {
- if (imma == 1)
- *inst = GROUP_SHIFT_1;
- else
- *inst = GROUP_SHIFT_N;
- } else
- *inst = GROUP_SHIFT_CL;
- *buf_ptr = 0;
- }
-
- if (!(b & SLJIT_MEM))
- *buf_ptr++ |= MOD_REG + ((!(flags & EX86_SSE2_OP2)) ? reg_lmap[b] : freg_lmap[b]);
- else if ((b & REG_MASK) != SLJIT_UNUSED) {
- if ((b & OFFS_REG_MASK) == SLJIT_UNUSED || (b & OFFS_REG_MASK) == TO_OFFS_REG(SLJIT_SP)) {
- if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
- if (immb <= 127 && immb >= -128)
- *buf_ptr |= 0x40;
- else
- *buf_ptr |= 0x80;
- }
-
- if ((b & OFFS_REG_MASK) == SLJIT_UNUSED)
- *buf_ptr++ |= reg_lmap[b & REG_MASK];
- else {
- *buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3);
- }
-
- if (immb != 0 || reg_lmap[b & REG_MASK] == 5) {
- if (immb <= 127 && immb >= -128)
- *buf_ptr++ = immb; /* 8 bit displacement. */
- else {
- sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
- buf_ptr += sizeof(sljit_s32);
- }
- }
- }
- else {
- if (reg_lmap[b & REG_MASK] == 5)
- *buf_ptr |= 0x40;
- *buf_ptr++ |= 0x04;
- *buf_ptr++ = reg_lmap[b & REG_MASK] | (reg_lmap[OFFS_REG(b)] << 3) | (immb << 6);
- if (reg_lmap[b & REG_MASK] == 5)
- *buf_ptr++ = 0;
- }
- }
- else {
- *buf_ptr++ |= 0x04;
- *buf_ptr++ = 0x25;
- sljit_unaligned_store_s32(buf_ptr, immb); /* 32 bit displacement. */
- buf_ptr += sizeof(sljit_s32);
- }
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_return_void(compiler));
- if (a & SLJIT_IMM) {
- if (flags & EX86_BYTE_ARG)
- *buf_ptr = imma;
- else if (flags & EX86_HALF_ARG)
- sljit_unaligned_store_s16(buf_ptr, imma);
- else if (!(flags & EX86_SHIFT_INS))
- sljit_unaligned_store_s32(buf_ptr, imma);
- }
+ FAIL_IF(emit_stack_frame_release(compiler));
- return !(flags & EX86_SHIFT_INS) ? inst : (inst + 1);
+ inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
+ FAIL_IF(!inst);
+ INC_SIZE(1);
+ RET();
+ return SLJIT_SUCCESS;
}
/* --------------------------------------------------------------------- */
@@ -609,43 +669,38 @@ static sljit_u8* emit_x86_instruction(struct sljit_compiler *compiler, sljit_s32
#ifndef _WIN64
-static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)
{
sljit_s32 src = src_ptr ? (*src_ptr) : 0;
sljit_s32 word_arg_count = 0;
SLJIT_ASSERT(reg_map[SLJIT_R1] == 6 && reg_map[SLJIT_R3] == 1 && reg_map[TMP_REG1] == 2);
-
- compiler->mode32 = 0;
+ SLJIT_ASSERT(!(src & SLJIT_MEM));
/* Remove return value. */
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- if ((arg_types & SLJIT_DEF_MASK) < SLJIT_ARG_TYPE_F32)
+ if ((arg_types & SLJIT_ARG_MASK) < SLJIT_ARG_TYPE_F64)
word_arg_count++;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
if (word_arg_count == 0)
return SLJIT_SUCCESS;
- if (src & SLJIT_MEM) {
- ADJUST_LOCAL_OFFSET(src, srcw);
- EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
- *src_ptr = TMP_REG2;
+ if (word_arg_count >= 3) {
+ if (src == SLJIT_R2)
+ *src_ptr = TMP_REG1;
+ EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);
}
- else if (src == SLJIT_R2 && word_arg_count >= SLJIT_R2)
- *src_ptr = TMP_REG1;
- if (word_arg_count >= 3)
- EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R2, 0);
return emit_mov(compiler, SLJIT_R2, 0, SLJIT_R0, 0);
}
#else
-static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr, sljit_sw srcw)
+static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_types, sljit_s32 *src_ptr)
{
sljit_s32 src = src_ptr ? (*src_ptr) : 0;
sljit_s32 arg_count = 0;
@@ -656,16 +711,16 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
static sljit_u8 word_arg_regs[5] = { 0, SLJIT_R3, SLJIT_R1, SLJIT_R2, TMP_REG1 };
SLJIT_ASSERT(reg_map[SLJIT_R3] == 1 && reg_map[SLJIT_R1] == 2 && reg_map[SLJIT_R2] == 8 && reg_map[TMP_REG1] == 9);
+ SLJIT_ASSERT(!(src & SLJIT_MEM));
- compiler->mode32 = 0;
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
while (arg_types) {
- types = (types << SLJIT_DEF_SHIFT) | (arg_types & SLJIT_DEF_MASK);
+ types = (types << SLJIT_ARG_SHIFT) | (arg_types & SLJIT_ARG_MASK);
- switch (arg_types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (arg_types & SLJIT_ARG_MASK) {
case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
arg_count++;
float_arg_count++;
@@ -687,29 +742,23 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- arg_types >>= SLJIT_DEF_SHIFT;
+ arg_types >>= SLJIT_ARG_SHIFT;
}
if (!data_trandfer)
return SLJIT_SUCCESS;
- if (src & SLJIT_MEM) {
- ADJUST_LOCAL_OFFSET(src, srcw);
- EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
- *src_ptr = TMP_REG2;
- }
-
while (types) {
- switch (types & SLJIT_DEF_MASK) {
- case SLJIT_ARG_TYPE_F32:
+ switch (types & SLJIT_ARG_MASK) {
+ case SLJIT_ARG_TYPE_F64:
if (arg_count != float_arg_count)
- FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));
+ FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));
arg_count--;
float_arg_count--;
break;
- case SLJIT_ARG_TYPE_F64:
+ case SLJIT_ARG_TYPE_F32:
if (arg_count != float_arg_count)
- FAIL_IF(emit_sse2_load(compiler, 0, arg_count, float_arg_count, 0));
+ FAIL_IF(emit_sse2_load(compiler, 1, arg_count, float_arg_count, 0));
arg_count--;
float_arg_count--;
break;
@@ -721,7 +770,7 @@ static sljit_s32 call_with_args(struct sljit_compiler *compiler, sljit_s32 arg_t
break;
}
- types >>= SLJIT_DEF_SHIFT;
+ types >>= SLJIT_ARG_SHIFT;
}
return SLJIT_SUCCESS;
@@ -735,13 +784,19 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_call(struct sljit_compile
CHECK_ERROR_PTR();
CHECK_PTR(check_sljit_emit_call(compiler, type, arg_types));
- PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL, 0));
+ compiler->mode32 = 0;
+
+ PTR_FAIL_IF(call_with_args(compiler, arg_types, NULL));
+
+ if (type & SLJIT_CALL_RETURN) {
+ PTR_FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP | (type & SLJIT_REWRITABLE_JUMP);
+ }
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
compiler->skip_checks = 1;
#endif
-
return sljit_emit_jump(compiler, type);
}
@@ -752,7 +807,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_icall(struct sljit_compiler *compi
CHECK_ERROR();
CHECK(check_sljit_emit_icall(compiler, type, arg_types, src, srcw));
- FAIL_IF(call_with_args(compiler, arg_types, &src, srcw));
+ compiler->mode32 = 0;
+
+ if (src & SLJIT_MEM) {
+ ADJUST_LOCAL_OFFSET(src, srcw);
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
+ }
+
+ if (type & SLJIT_CALL_RETURN) {
+ if (src >= SLJIT_FIRST_SAVED_REG && src <= SLJIT_S0) {
+ EMIT_MOV(compiler, TMP_REG2, 0, src, srcw);
+ src = TMP_REG2;
+ }
+
+ FAIL_IF(emit_stack_frame_release(compiler));
+ type = SLJIT_JUMP;
+ }
+
+ FAIL_IF(call_with_args(compiler, arg_types, &src));
#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
|| (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
@@ -770,10 +843,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fast_enter(struct sljit_compiler *
CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw));
ADJUST_LOCAL_OFFSET(dst, dstw);
- /* For UNUSED dst. Uncommon, but possible. */
- if (dst == SLJIT_UNUSED)
- dst = TMP_REG1;
-
if (FAST_IS_REG(dst)) {
if (reg_map[dst] < 8) {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
@@ -850,9 +919,6 @@ static sljit_s32 emit_mov_int(struct sljit_compiler *compiler, sljit_s32 sign,
compiler->mode32 = 0;
- if (dst == SLJIT_UNUSED && !(src & SLJIT_MEM))
- return SLJIT_SUCCESS; /* Empty instruction. */
-
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
if (sign || ((sljit_uw)srcw <= 0x7fffffff)) {
@@ -903,16 +969,16 @@ static sljit_s32 skip_frames_before_return(struct sljit_compiler *compiler)
sljit_s32 tmp, size;
/* Don't adjust shadow stack if it isn't enabled. */
- if (!cpu_has_shadow_stack ())
+ if (!cpu_has_shadow_stack())
return SLJIT_SUCCESS;
size = compiler->local_size;
tmp = compiler->scratches;
if (tmp >= SLJIT_FIRST_SAVED_REG)
- size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * sizeof(sljit_uw);
+ size += (tmp - SLJIT_FIRST_SAVED_REG + 1) * SSIZE_OF(sw);
tmp = compiler->saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - compiler->saveds) : SLJIT_FIRST_SAVED_REG;
if (SLJIT_S0 >= tmp)
- size += (SLJIT_S0 - tmp + 1) * sizeof(sljit_uw);
+ size += (SLJIT_S0 - tmp + 1) * SSIZE_OF(sw);
- return adjust_shadow_stack(compiler, SLJIT_UNUSED, 0, SLJIT_SP, size);
+ return adjust_shadow_stack(compiler, SLJIT_MEM1(SLJIT_SP), size);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
index 515d98aefd..c7dd9be8fd 100644
--- a/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
+++ b/thirdparty/pcre2/src/sljit/sljitNativeX86_common.c
@@ -65,6 +65,8 @@ SLJIT_API_FUNC_ATTRIBUTE const char* sljit_get_platform_name(void)
15 - R15
*/
+#define TMP_FREG (0)
+
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
/* Last register + 1. */
@@ -77,9 +79,9 @@ static const sljit_u8 reg_map[SLJIT_NUMBER_OF_REGISTERS + 3] = {
#define CHECK_EXTRA_REGS(p, w, do) \
if (p >= SLJIT_R3 && p <= SLJIT_S3) { \
if (p <= compiler->scratches) \
- w = compiler->saveds_offset - ((p) - SLJIT_R2) * (sljit_sw)sizeof(sljit_sw); \
+ w = compiler->scratches_offset + ((p) - SLJIT_R3) * SSIZE_OF(sw); \
else \
- w = compiler->locals_offset + ((p) - SLJIT_S2) * (sljit_sw)sizeof(sljit_sw); \
+ w = compiler->locals_offset + ((p) - SLJIT_S2) * SSIZE_OF(sw); \
p = SLJIT_MEM1(SLJIT_SP); \
do; \
}
@@ -115,11 +117,11 @@ static const sljit_u8 reg_lmap[SLJIT_NUMBER_OF_REGISTERS + 4] = {
/* Args: xmm0-xmm3 */
static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
- 4, 0, 1, 2, 3, 5, 6
+ 4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
};
/* low-map. freg_map & 0x7. */
static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
- 4, 0, 1, 2, 3, 5, 6
+ 4, 0, 1, 2, 3, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7
};
#define REX_W 0x48
@@ -143,7 +145,8 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
#endif /* SLJIT_CONFIG_X86_32 */
-#define TMP_FREG (0)
+#define U8(v) ((sljit_u8)(v))
+
/* Size flags for emit_x86_instruction: */
#define EX86_BIN_INS 0x0010
@@ -205,12 +208,15 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
#define JMP_i32 0xe9
#define JMP_rm (/* GROUP_FF */ 4 << 3)
#define LEA_r_m 0x8d
+#define LOOP_i8 0xe2
#define MOV_r_rm 0x8b
#define MOV_r_i32 0xb8
#define MOV_rm_r 0x89
#define MOV_rm_i32 0xc7
#define MOV_rm8_i8 0xc6
#define MOV_rm8_r8 0x88
+#define MOVAPS_x_xm 0x28
+#define MOVAPS_xm_x 0x29
#define MOVSD_x_xm 0x10
#define MOVSD_xm_x 0x11
#define MOVSXD_r_rm 0x63
@@ -274,14 +280,12 @@ static const sljit_u8 freg_lmap[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 1] = {
#define MOD_REG 0xc0
#define MOD_DISP8 0x40
-#define INC_SIZE(s) (*inst++ = (s), compiler->size += (s))
+#define INC_SIZE(s) (*inst++ = U8(s), compiler->size += (s))
-#define PUSH_REG(r) (*inst++ = (PUSH_r + (r)))
-#define POP_REG(r) (*inst++ = (POP_r + (r)))
-#define RET() (*inst++ = (RET_near))
-#define RET_I16(n) (*inst++ = (RET_i16), *inst++ = n, *inst++ = 0)
-/* r32, r/m32 */
-#define MOV_RM(mod, reg, rm) (*inst++ = (MOV_r_rm), *inst++ = (mod) << 6 | (reg) << 3 | (rm))
+#define PUSH_REG(r) (*inst++ = U8(PUSH_r + (r)))
+#define POP_REG(r) (*inst++ = U8(POP_r + (r)))
+#define RET() (*inst++ = RET_near)
+#define RET_I16(n) (*inst++ = RET_i16, *inst++ = U8(n), *inst++ = 0)
/* Multithreading does not affect these static variables, since they store
built-in CPU features. Therefore they can be overwritten by different threads
@@ -371,7 +375,7 @@ static void get_cpu_features(void)
cpu_has_cmov = (features >> 15) & 0x1;
}
-static sljit_u8 get_jump_code(sljit_s32 type)
+static sljit_u8 get_jump_code(sljit_uw type)
{
switch (type) {
case SLJIT_EQUAL:
@@ -383,10 +387,12 @@ static sljit_u8 get_jump_code(sljit_s32 type)
return 0x85 /* jne */;
case SLJIT_LESS:
+ case SLJIT_CARRY:
case SLJIT_LESS_F64:
return 0x82 /* jc */;
case SLJIT_GREATER_EQUAL:
+ case SLJIT_NOT_CARRY:
case SLJIT_GREATER_EQUAL_F64:
return 0x83 /* jae */;
@@ -434,14 +440,14 @@ static sljit_u8* generate_put_label_code(struct sljit_put_label *put_label, slji
static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code_ptr, sljit_u8 *code, sljit_sw executable_offset)
{
- sljit_s32 type = jump->flags >> TYPE_SHIFT;
+ sljit_uw type = jump->flags >> TYPE_SHIFT;
sljit_s32 short_jump;
sljit_uw label_addr;
if (jump->flags & JUMP_LABEL)
label_addr = (sljit_uw)(code + jump->u.label->size);
else
- label_addr = jump->u.target - executable_offset;
+ label_addr = jump->u.target - (sljit_uw)executable_offset;
short_jump = (sljit_sw)(label_addr - (jump->addr + 2)) >= -128 && (sljit_sw)(label_addr - (jump->addr + 2)) <= 127;
@@ -463,7 +469,7 @@ static sljit_u8* generate_near_jump_code(struct sljit_jump *jump, sljit_u8 *code
jump->addr++;
}
else if (short_jump) {
- *code_ptr++ = get_jump_code(type) - 0x10;
+ *code_ptr++ = U8(get_jump_code(type) - 0x10);
jump->addr++;
}
else {
@@ -492,7 +498,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
sljit_u8 *buf_end;
sljit_u8 len;
sljit_sw executable_offset;
- sljit_sw jump_addr;
+ sljit_uw jump_addr;
struct sljit_label *label;
struct sljit_jump *jump;
@@ -530,7 +536,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
switch (*buf_ptr) {
case 0:
label->addr = (sljit_uw)SLJIT_ADD_EXEC_OFFSET(code_ptr, executable_offset);
- label->size = code_ptr - code;
+ label->size = (sljit_uw)(code_ptr - code);
label = label->next;
break;
case 1:
@@ -575,11 +581,11 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
jump = compiler->jumps;
while (jump) {
- jump_addr = jump->addr + executable_offset;
+ jump_addr = jump->addr + (sljit_uw)executable_offset;
if (jump->flags & PATCH_MB) {
SLJIT_ASSERT((sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) >= -128 && (sljit_sw)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8))) <= 127);
- *(sljit_u8*)jump->addr = (sljit_u8)(jump->u.label->addr - (jump_addr + sizeof(sljit_s8)));
+ *(sljit_u8*)jump->addr = U8(jump->u.label->addr - (jump_addr + sizeof(sljit_s8)));
} else if (jump->flags & PATCH_MW) {
if (jump->flags & JUMP_LABEL) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -600,7 +606,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
else if (jump->flags & PATCH_MD)
- sljit_unaligned_store_sw((void*)jump->addr, jump->u.label->addr);
+ sljit_unaligned_store_sw((void*)jump->addr, (sljit_sw)jump->u.label->addr);
#endif
jump = jump->next;
@@ -626,7 +632,7 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil
compiler->error = SLJIT_ERR_COMPILED;
compiler->executable_offset = executable_offset;
- compiler->executable_size = code_ptr - code;
+ compiler->executable_size = (sljit_uw)(code_ptr - code);
code = (sljit_u8*)SLJIT_ADD_EXEC_OFFSET(code, executable_offset);
@@ -682,17 +688,40 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
#define BINARY_OPCODE(opcode) (((opcode ## _EAX_i32) << 24) | ((opcode ## _r_rm) << 16) | ((opcode ## _rm_r) << 8) | (opcode))
-static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
- sljit_u32 op_types,
- sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src1, sljit_sw src1w,
- sljit_s32 src2, sljit_sw src2w);
+#define BINARY_IMM32(op_imm, immw, arg, argw) \
+ do { \
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
+ FAIL_IF(!inst); \
+ *(inst + 1) |= (op_imm); \
+ } while (0)
-static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
- sljit_u32 op_types,
- sljit_s32 dst, sljit_sw dstw,
- sljit_s32 src1, sljit_sw src1w,
- sljit_s32 src2, sljit_sw src2w);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
+ do { \
+ if (IS_HALFWORD(immw) || compiler->mode32) { \
+ BINARY_IMM32(op_imm, immw, arg, argw); \
+ } \
+ else { \
+ FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \
+ inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
+ FAIL_IF(!inst); \
+ *inst = (op_mr); \
+ } \
+ } while (0)
+
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
+
+#else /* !SLJIT_CONFIG_X86_64 */
+
+#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
+ BINARY_IMM32(op_imm, immw, arg, argw)
+
+#define BINARY_EAX_IMM(op_eax_imm, immw) \
+ FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
+
+#endif /* SLJIT_CONFIG_X86_64 */
static sljit_s32 emit_mov(struct sljit_compiler *compiler,
sljit_s32 dst, sljit_sw dstw,
@@ -795,7 +824,7 @@ static SLJIT_INLINE sljit_s32 cpu_has_shadow_stack(void)
}
static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compiler,
- sljit_s32 src, sljit_sw srcw, sljit_s32 base, sljit_sw disp)
+ sljit_s32 src, sljit_sw srcw)
{
#if (defined SLJIT_CONFIG_X86_CET && SLJIT_CONFIG_X86_CET) && defined (__SHSTK__)
sljit_u8 *inst, *jz_after_cmp_inst;
@@ -821,12 +850,6 @@ static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compile
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_MEM1(TMP_REG1), 0);
#endif /* SLJIT_CONFIG_X86_32 */
- if (src == SLJIT_UNUSED) {
- /* Return address is on stack. */
- src = SLJIT_MEM1(base);
- srcw = disp;
- }
-
/* Compare return address against TMP_REG1. */
FAIL_IF(emit_cmp_binary (compiler, TMP_REG1, 0, src, srcw));
@@ -861,8 +884,6 @@ static SLJIT_INLINE sljit_s32 adjust_shadow_stack(struct sljit_compiler *compile
SLJIT_UNUSED_ARG(compiler);
SLJIT_UNUSED_ARG(src);
SLJIT_UNUSED_ARG(srcw);
- SLJIT_UNUSED_ARG(base);
- SLJIT_UNUSED_ARG(disp);
#endif /* SLJIT_CONFIG_X86_CET && __SHSTK__ */
return SLJIT_SUCCESS;
}
@@ -879,8 +900,6 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
{
sljit_u8* inst;
- SLJIT_ASSERT(dst != SLJIT_UNUSED);
-
if (FAST_IS_REG(src)) {
inst = emit_x86_instruction(compiler, 1, src, 0, dst, dstw);
FAIL_IF(!inst);
@@ -890,14 +909,14 @@ static sljit_s32 emit_mov(struct sljit_compiler *compiler,
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
#else
if (!compiler->mode32) {
if (NOT_HALFWORD(srcw))
return emit_load_imm64(compiler, dst, srcw);
}
else
- return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, MOV_r_i32 + reg_lmap[dst], srcw);
+ return emit_do_imm32(compiler, (reg_map[dst] >= 8) ? REX_B : 0, U8(MOV_r_i32 | reg_lmap[dst]), srcw);
#endif
}
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
@@ -938,7 +957,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
{
sljit_u8 *inst;
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- sljit_s32 size;
+ sljit_uw size;
#endif
CHECK_ERROR();
@@ -975,7 +994,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
&& reg_map[SLJIT_R1] < 7
&& reg_map[TMP_REG1] == 2);
#endif
- compiler->mode32 = op & SLJIT_I32_OP;
+ compiler->mode32 = op & SLJIT_32;
#endif
SLJIT_COMPILE_ASSERT((SLJIT_DIVMOD_UW & 0x2) == 0 && SLJIT_DIV_UW - 0x2 == SLJIT_DIVMOD_UW, bad_div_opcode_assignments);
@@ -1084,7 +1103,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op0(struct sljit_compiler *compile
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1); \
FAIL_IF(!inst); \
INC_SIZE(1); \
- *inst = (prefix); \
+ *inst = U8(prefix); \
} while (0)
static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
@@ -1104,7 +1123,7 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
#else
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
FAIL_IF(!inst);
@@ -1134,7 +1153,7 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
else if (FAST_IS_REG(src) && reg_map[src] >= 4) {
/* src, dst are registers. */
- SLJIT_ASSERT(SLOW_IS_REG(dst));
+ SLJIT_ASSERT(FAST_IS_REG(dst));
if (reg_map[dst] < 4) {
if (dst != src)
EMIT_MOV(compiler, dst, 0, src, 0);
@@ -1193,7 +1212,7 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
}
if (work_r == SLJIT_R0) {
- ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
+ ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]);
}
else {
inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
@@ -1206,7 +1225,7 @@ static sljit_s32 emit_mov_byte(struct sljit_compiler *compiler, sljit_s32 sign,
*inst = MOV_rm8_r8;
if (work_r == SLJIT_R0) {
- ENCODE_PREFIX(XCHG_EAX_r + reg_map[TMP_REG1]);
+ ENCODE_PREFIX(XCHG_EAX_r | reg_map[TMP_REG1]);
}
else {
inst = emit_x86_instruction(compiler, 1, work_r, 0, dst_r, 0);
@@ -1267,7 +1286,7 @@ static sljit_s32 emit_mov_half(struct sljit_compiler *compiler, sljit_s32 sign,
if (src & SLJIT_IMM) {
if (FAST_IS_REG(dst)) {
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- return emit_do_imm(compiler, MOV_r_i32 + reg_map[dst], srcw);
+ return emit_do_imm(compiler, MOV_r_i32 | reg_map[dst], srcw);
#else
inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, srcw, dst, 0);
FAIL_IF(!inst);
@@ -1316,9 +1335,6 @@ static sljit_s32 emit_unary(struct sljit_compiler *compiler, sljit_u8 opcode,
return SLJIT_SUCCESS;
}
- if (SLJIT_UNLIKELY(dst == SLJIT_UNUSED))
- dst = TMP_REG1;
-
if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
@@ -1343,9 +1359,6 @@ static sljit_s32 emit_not_with_flags(struct sljit_compiler *compiler,
{
sljit_u8* inst;
- if (dst == SLJIT_UNUSED)
- dst = TMP_REG1;
-
if (FAST_IS_REG(dst)) {
EMIT_MOV(compiler, dst, 0, src, srcw);
inst = emit_x86_instruction(compiler, 1, 0, 0, dst, 0);
@@ -1412,7 +1425,7 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, 31, dst_r, 0);
#else
if (cpu_has_cmov) {
- EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31));
+ EMIT_MOV(compiler, TMP_REG2, 0, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31));
inst = emit_x86_instruction(compiler, 2, dst_r, 0, TMP_REG2, 0);
FAIL_IF(!inst);
@@ -1420,9 +1433,9 @@ static sljit_s32 emit_clz(struct sljit_compiler *compiler, sljit_s32 op_flags,
*inst = CMOVE_r_rm;
}
else
- FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? (64 + 63) : (32 + 31)));
+ FAIL_IF(sljit_emit_cmov_generic(compiler, SLJIT_EQUAL, dst_r, SLJIT_IMM, !(op_flags & SLJIT_32) ? (64 + 63) : (32 + 31)));
- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_I32_OP) ? 63 : 31, dst_r, 0);
+ inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, !(op_flags & SLJIT_32) ? 63 : 31, dst_r, 0);
#endif
FAIL_IF(!inst);
@@ -1450,7 +1463,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
CHECK_EXTRA_REGS(dst, dstw, dst_is_ereg = 1);
CHECK_EXTRA_REGS(src, srcw, (void)0);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = op_flags & SLJIT_I32_OP;
+ compiler->mode32 = op_flags & SLJIT_32;
#endif
op = GET_OPCODE(op);
@@ -1465,8 +1478,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
- if (op_flags & SLJIT_I32_OP) {
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ if (op_flags & SLJIT_32) {
if (src & SLJIT_MEM) {
if (op == SLJIT_MOV_S32)
op = SLJIT_MOV_U32;
@@ -1475,8 +1488,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
if (op == SLJIT_MOV_U32)
op = SLJIT_MOV_S32;
}
-#endif
}
+#endif
if (src & SLJIT_IMM) {
switch (op) {
@@ -1520,8 +1533,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
case SLJIT_MOV_U32:
case SLJIT_MOV_S32:
+ case SLJIT_MOV32:
#endif
- FAIL_IF(emit_mov(compiler, dst, dstw, src, srcw));
+ EMIT_MOV(compiler, dst, dstw, src, srcw);
break;
case SLJIT_MOV_U8:
FAIL_IF(emit_mov_byte(compiler, 0, dst, dstw, src, srcw));
@@ -1542,6 +1556,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
case SLJIT_MOV_S32:
FAIL_IF(emit_mov_int(compiler, 1, dst, dstw, src, srcw));
break;
+ case SLJIT_MOV32:
+ compiler->mode32 = 1;
+ EMIT_MOV(compiler, dst, dstw, src, srcw);
+ compiler->mode32 = 0;
+ break;
#endif
}
@@ -1558,9 +1577,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return emit_not_with_flags(compiler, dst, dstw, src, srcw);
return emit_unary(compiler, NOT_rm, dst, dstw, src, srcw);
- case SLJIT_NEG:
- return emit_unary(compiler, NEG_rm, dst, dstw, src, srcw);
-
case SLJIT_CLZ:
return emit_clz(compiler, op_flags, dst, dstw, src, srcw);
}
@@ -1568,36 +1584,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op1(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
-#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
-
-#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
- if (IS_HALFWORD(immw) || compiler->mode32) { \
- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
- FAIL_IF(!inst); \
- *(inst + 1) |= (op_imm); \
- } \
- else { \
- FAIL_IF(emit_load_imm64(compiler, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, immw)); \
- inst = emit_x86_instruction(compiler, 1, (arg == TMP_REG1) ? TMP_REG2 : TMP_REG1, 0, arg, argw); \
- FAIL_IF(!inst); \
- *inst = (op_mr); \
- }
-
-#define BINARY_EAX_IMM(op_eax_imm, immw) \
- FAIL_IF(emit_do_imm32(compiler, (!compiler->mode32) ? REX_W : 0, (op_eax_imm), immw))
-
-#else
-
-#define BINARY_IMM(op_imm, op_mr, immw, arg, argw) \
- inst = emit_x86_instruction(compiler, 1 | EX86_BIN_INS, SLJIT_IMM, immw, arg, argw); \
- FAIL_IF(!inst); \
- *(inst + 1) |= (op_imm);
-
-#define BINARY_EAX_IMM(op_eax_imm, immw) \
- FAIL_IF(emit_do_imm(compiler, (op_eax_imm), immw))
-
-#endif
-
static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
sljit_u32 op_types,
sljit_s32 dst, sljit_sw dstw,
@@ -1605,23 +1591,10 @@ static sljit_s32 emit_cum_binary(struct sljit_compiler *compiler,
sljit_s32 src2, sljit_sw src2w)
{
sljit_u8* inst;
- sljit_u8 op_eax_imm = (op_types >> 24);
- sljit_u8 op_rm = (op_types >> 16) & 0xff;
- sljit_u8 op_mr = (op_types >> 8) & 0xff;
- sljit_u8 op_imm = op_types & 0xff;
-
- if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
- if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
- }
- else {
- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
- FAIL_IF(!inst);
- *inst = op_rm;
- }
- return SLJIT_SUCCESS;
- }
+ sljit_u8 op_eax_imm = U8(op_types >> 24);
+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);
+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);
+ sljit_u8 op_imm = U8(op_types & 0xff);
if (dst == src1 && dstw == src1w) {
if (src2 & SLJIT_IMM) {
@@ -1725,23 +1698,10 @@ static sljit_s32 emit_non_cum_binary(struct sljit_compiler *compiler,
sljit_s32 src2, sljit_sw src2w)
{
sljit_u8* inst;
- sljit_u8 op_eax_imm = (op_types >> 24);
- sljit_u8 op_rm = (op_types >> 16) & 0xff;
- sljit_u8 op_mr = (op_types >> 8) & 0xff;
- sljit_u8 op_imm = op_types & 0xff;
-
- if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
- if (src2 & SLJIT_IMM) {
- BINARY_IMM(op_imm, op_mr, src2w, TMP_REG1, 0);
- }
- else {
- inst = emit_x86_instruction(compiler, 1, TMP_REG1, 0, src2, src2w);
- FAIL_IF(!inst);
- *inst = op_rm;
- }
- return SLJIT_SUCCESS;
- }
+ sljit_u8 op_eax_imm = U8(op_types >> 24);
+ sljit_u8 op_rm = U8((op_types >> 16) & 0xff);
+ sljit_u8 op_mr = U8((op_types >> 8) & 0xff);
+ sljit_u8 op_imm = U8(op_types & 0xff);
if (dst == src1 && dstw == src1w) {
if (src2 & SLJIT_IMM) {
@@ -1810,9 +1770,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
sljit_s32 src2, sljit_sw src2w)
{
sljit_u8* inst;
- sljit_s32 dst_r;
-
- dst_r = SLOW_IS_REG(dst) ? dst : TMP_REG1;
+ sljit_s32 dst_r = FAST_IS_REG(dst) ? dst : TMP_REG1;
/* Register destination. */
if (dst_r == src1 && !(src2 & SLJIT_IMM)) {
@@ -1841,7 +1799,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
- *inst = (sljit_s8)src1w;
+ *inst = U8(src1w);
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
else {
@@ -1884,7 +1842,7 @@ static sljit_s32 emit_mul(struct sljit_compiler *compiler,
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1);
FAIL_IF(!inst);
INC_SIZE(1);
- *inst = (sljit_s8)src2w;
+ *inst = U8(src2w);
}
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
else {
@@ -2167,13 +2125,6 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
*inst |= mode;
return SLJIT_SUCCESS;
}
- if (dst == SLJIT_UNUSED) {
- EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
- inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, src2, src2w, TMP_REG1, 0);
- FAIL_IF(!inst);
- *inst |= mode;
- return SLJIT_SUCCESS;
- }
if (dst == SLJIT_PREF_SHIFT_REG && src2 == SLJIT_PREF_SHIFT_REG) {
EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w);
inst = emit_x86_instruction(compiler, 1 | EX86_SHIFT_INS, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
@@ -2206,7 +2157,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
*inst |= mode;
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG1, 0);
}
- else if (SLOW_IS_REG(dst) && dst != src2 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
+ else if (FAST_IS_REG(dst) && dst != src2 && dst != TMP_REG1 && !ADDRESSING_DEPENDS_ON(src2, dst)) {
if (src1 != dst)
EMIT_MOV(compiler, dst, 0, src1, src1w);
EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_PREF_SHIFT_REG, 0);
@@ -2235,7 +2186,7 @@ static sljit_s32 emit_shift(struct sljit_compiler *compiler,
*inst |= mode;
EMIT_MOV(compiler, SLJIT_PREF_SHIFT_REG, 0, TMP_REG2, 0);
#endif
- if (dst != SLJIT_UNUSED)
+ if (dst != TMP_REG1)
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
}
@@ -2273,7 +2224,7 @@ static sljit_s32 emit_shift_with_flags(struct sljit_compiler *compiler,
FAIL_IF(emit_shift(compiler, mode, dst, dstw, src1, src1w, src2, src2w));
if (FAST_IS_REG(dst))
- return emit_cmp_binary(compiler, (dst == SLJIT_UNUSED) ? TMP_REG1 : dst, dstw, SLJIT_IMM, 0);
+ return emit_cmp_binary(compiler, dst, dstw, SLJIT_IMM, 0);
return SLJIT_SUCCESS;
}
@@ -2283,7 +2234,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
sljit_s32 src2, sljit_sw src2w)
{
CHECK_ERROR();
- CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w));
+ CHECK(check_sljit_emit_op2(compiler, op, 0, dst, dstw, src1, src1w, src2, src2w));
ADJUST_LOCAL_OFFSET(dst, dstw);
ADJUST_LOCAL_OFFSET(src1, src1w);
ADJUST_LOCAL_OFFSET(src2, src2w);
@@ -2292,11 +2243,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
CHECK_EXTRA_REGS(src1, src1w, (void)0);
CHECK_EXTRA_REGS(src2, src2w, (void)0);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = op & SLJIT_I32_OP;
+ compiler->mode32 = op & SLJIT_32;
#endif
- if (dst == SLJIT_UNUSED && !HAS_FLAGS(op))
- return SLJIT_SUCCESS;
+ SLJIT_ASSERT(dst != TMP_REG1 || HAS_FLAGS(op));
switch (GET_OPCODE(op)) {
case SLJIT_ADD:
@@ -2310,17 +2260,18 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return emit_cum_binary(compiler, BINARY_OPCODE(ADC),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUB:
+ if (src1 == SLJIT_IMM && src1w == 0)
+ return emit_unary(compiler, NEG_rm, dst, dstw, src2, src2w);
+
if (!HAS_FLAGS(op)) {
if ((src2 & SLJIT_IMM) && emit_lea_binary(compiler, dst, dstw, src1, src1w, SLJIT_IMM, -src2w) != SLJIT_ERR_UNSUPPORTED)
return compiler->error;
- if (SLOW_IS_REG(dst) && src2 == dst) {
+ if (FAST_IS_REG(dst) && src2 == dst) {
FAIL_IF(emit_non_cum_binary(compiler, BINARY_OPCODE(SUB), dst, 0, dst, 0, src1, src1w));
return emit_unary(compiler, NEG_rm, dst, 0, dst, 0);
}
}
- if (dst == SLJIT_UNUSED)
- return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
return emit_non_cum_binary(compiler, BINARY_OPCODE(SUB),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_SUBC:
@@ -2329,8 +2280,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
case SLJIT_MUL:
return emit_mul(compiler, dst, dstw, src1, src1w, src2, src2w);
case SLJIT_AND:
- if (dst == SLJIT_UNUSED)
- return emit_test_binary(compiler, src1, src1w, src2, src2w);
return emit_cum_binary(compiler, BINARY_OPCODE(AND),
dst, dstw, src1, src1w, src2, src2w);
case SLJIT_OR:
@@ -2353,6 +2302,38 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2(struct sljit_compiler *compile
return SLJIT_SUCCESS;
}
+SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op2u(struct sljit_compiler *compiler, sljit_s32 op,
+ sljit_s32 src1, sljit_sw src1w,
+ sljit_s32 src2, sljit_sw src2w)
+{
+ sljit_s32 opcode = GET_OPCODE(op);
+
+ CHECK_ERROR();
+ CHECK(check_sljit_emit_op2(compiler, op, 1, 0, 0, src1, src1w, src2, src2w));
+
+ if (opcode != SLJIT_SUB && opcode != SLJIT_AND) {
+#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) \
+ || (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS)
+ compiler->skip_checks = 1;
+#endif
+ return sljit_emit_op2(compiler, op, TMP_REG1, 0, src1, src1w, src2, src2w);
+ }
+
+ ADJUST_LOCAL_OFFSET(src1, src1w);
+ ADJUST_LOCAL_OFFSET(src2, src2w);
+
+ CHECK_EXTRA_REGS(src1, src1w, (void)0);
+ CHECK_EXTRA_REGS(src2, src2w, (void)0);
+#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
+ compiler->mode32 = op & SLJIT_32;
+#endif
+
+ if (opcode == SLJIT_SUB) {
+ return emit_cmp_binary(compiler, src1, src1w, src2, src2w);
+ }
+ return emit_test_binary(compiler, src1, src1w, src2, src2w);
+}
+
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *compiler, sljit_s32 op,
sljit_s32 src, sljit_sw srcw)
{
@@ -2369,7 +2350,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_src(struct sljit_compiler *comp
/* Don't adjust shadow stack if it isn't enabled. */
if (!cpu_has_shadow_stack ())
return SLJIT_SUCCESS;
- return adjust_shadow_stack(compiler, src, srcw, SLJIT_UNUSED, 0);
+ return adjust_shadow_stack(compiler, src, srcw);
case SLJIT_PREFETCH_L1:
case SLJIT_PREFETCH_L2:
case SLJIT_PREFETCH_L3:
@@ -2401,7 +2382,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_get_float_register_index(sljit_s32 reg)
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *compiler,
- void *instruction, sljit_s32 size)
+ void *instruction, sljit_u32 size)
{
sljit_u8 *inst;
@@ -2420,13 +2401,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_custom(struct sljit_compiler *c
/* --------------------------------------------------------------------- */
/* Alignment(3) + 4 * 16 bytes. */
-static sljit_s32 sse2_data[3 + (4 * 4)];
-static sljit_s32 *sse2_buffer;
+static sljit_u32 sse2_data[3 + (4 * 4)];
+static sljit_u32 *sse2_buffer;
static void init_compiler(void)
{
/* Align to 16 bytes. */
- sse2_buffer = (sljit_s32*)(((sljit_uw)sse2_data + 15) & ~0xf);
+ sse2_buffer = (sljit_u32*)(((sljit_uw)sse2_data + 15) & ~(sljit_uw)0xf);
/* Single precision constants (each constant is 16 byte long). */
sse2_buffer[0] = 0x80000000;
@@ -2486,7 +2467,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_sw_from_f64(struct sljit_comp
compiler->mode32 = 0;
#endif
- inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP2, dst_r, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
*inst = CVTTSD2SI_r_xm;
@@ -2518,7 +2499,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
srcw = 0;
}
- inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_F32_OP) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);
+ inst = emit_x86_instruction(compiler, 2 | ((op & SLJIT_32) ? EX86_PREF_F3 : EX86_PREF_F2) | EX86_SSE2_OP1, dst_r, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
*inst = CVTSI2SD_x_rm;
@@ -2527,7 +2508,7 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_conv_f64_from_sw(struct sljit_comp
compiler->mode32 = 1;
#endif
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
@@ -2536,11 +2517,11 @@ static SLJIT_INLINE sljit_s32 sljit_emit_fop1_cmp(struct sljit_compiler *compile
sljit_s32 src2, sljit_sw src2w)
{
if (!FAST_IS_REG(src1)) {
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
src1 = TMP_FREG;
}
- return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_F32_OP), src1, src2, src2w);
+ return emit_sse2_logic(compiler, UCOMISD_x_xm, !(op & SLJIT_32), src1, src2, src2w);
}
SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compiler, sljit_s32 op,
@@ -2558,11 +2539,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
if (GET_OPCODE(op) == SLJIT_MOV_F64) {
if (FAST_IS_REG(dst))
- return emit_sse2_load(compiler, op & SLJIT_F32_OP, dst, src, srcw);
+ return emit_sse2_load(compiler, op & SLJIT_32, dst, src, srcw);
if (FAST_IS_REG(src))
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, src);
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src, srcw));
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, src);
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src, srcw));
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
}
if (GET_OPCODE(op) == SLJIT_CONV_F64_FROM_F32) {
@@ -2571,41 +2552,41 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop1(struct sljit_compiler *compil
/* We overwrite the high bits of source. From SLJIT point of view,
this is not an issue.
Note: In SSE3, we could also use MOVDDUP and MOVSLDUP. */
- FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_F32_OP, src, src, 0));
+ FAIL_IF(emit_sse2_logic(compiler, UNPCKLPD_x_xm, op & SLJIT_32, src, src, 0));
}
else {
- FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_F32_OP), TMP_FREG, src, srcw));
+ FAIL_IF(emit_sse2_load(compiler, !(op & SLJIT_32), TMP_FREG, src, srcw));
src = TMP_FREG;
}
- FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_F32_OP, dst_r, src, 0));
+ FAIL_IF(emit_sse2_logic(compiler, CVTPD2PS_x_xm, op & SLJIT_32, dst_r, src, 0));
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
if (FAST_IS_REG(dst)) {
dst_r = dst;
if (dst != src)
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw));
}
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src, srcw));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src, srcw));
}
switch (GET_OPCODE(op)) {
case SLJIT_NEG_F64:
- FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer : sse2_buffer + 8)));
+ FAIL_IF(emit_sse2_logic(compiler, XORPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer : sse2_buffer + 8)));
break;
case SLJIT_ABS_F64:
- FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_F32_OP ? sse2_buffer + 4 : sse2_buffer + 12)));
+ FAIL_IF(emit_sse2_logic(compiler, ANDPD_x_xm, 1, dst_r, SLJIT_MEM0(), (sljit_sw)(op & SLJIT_32 ? sse2_buffer + 4 : sse2_buffer + 12)));
break;
}
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
@@ -2636,37 +2617,37 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_fop2(struct sljit_compiler *compil
src2w = src1w;
}
else if (dst != src2)
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, dst_r, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, dst_r, src1, src1w));
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
}
}
else {
dst_r = TMP_FREG;
- FAIL_IF(emit_sse2_load(compiler, op & SLJIT_F32_OP, TMP_FREG, src1, src1w));
+ FAIL_IF(emit_sse2_load(compiler, op & SLJIT_32, TMP_FREG, src1, src1w));
}
switch (GET_OPCODE(op)) {
case SLJIT_ADD_F64:
- FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
+ FAIL_IF(emit_sse2(compiler, ADDSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));
break;
case SLJIT_SUB_F64:
- FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
+ FAIL_IF(emit_sse2(compiler, SUBSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));
break;
case SLJIT_MUL_F64:
- FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
+ FAIL_IF(emit_sse2(compiler, MULSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));
break;
case SLJIT_DIV_F64:
- FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_F32_OP, dst_r, src2, src2w));
+ FAIL_IF(emit_sse2(compiler, DIVSD_x_xm, op & SLJIT_32, dst_r, src2, src2w));
break;
}
if (dst_r == TMP_FREG)
- return emit_sse2_store(compiler, op & SLJIT_F32_OP, dst, dstw, TMP_FREG);
+ return emit_sse2_store(compiler, op & SLJIT_32, dst, dstw, TMP_FREG);
return SLJIT_SUCCESS;
}
@@ -2708,7 +2689,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump* sljit_emit_jump(struct sljit_compile
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
PTR_FAIL_IF_NULL(jump);
- set_jump(jump, compiler, (type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT));
+ set_jump(jump, compiler, (sljit_u32)((type & SLJIT_REWRITABLE_JUMP) | ((type & 0xff) << TYPE_SHIFT)));
type &= 0xff;
/* Worst case size. */
@@ -2740,8 +2721,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
if (src == SLJIT_IMM) {
jump = (struct sljit_jump*)ensure_abuf(compiler, sizeof(struct sljit_jump));
FAIL_IF_NULL(jump);
- set_jump(jump, compiler, JUMP_ADDR | (type << TYPE_SHIFT));
- jump->u.target = srcw;
+ set_jump(jump, compiler, (sljit_u32)(JUMP_ADDR | (type << TYPE_SHIFT)));
+ jump->u.target = (sljit_uw)srcw;
/* Worst case size. */
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
@@ -2764,7 +2745,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_ijump(struct sljit_compiler *compi
inst = emit_x86_instruction(compiler, 1, 0, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_FF;
- *inst |= (type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm;
+ *inst = U8(*inst | ((type >= SLJIT_FAST_CALL) ? CALL_rm : JMP_rm));
}
return SLJIT_SUCCESS;
}
@@ -2790,7 +2771,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
type &= 0xff;
/* setcc = jcc + 0x10. */
- cond_set = get_jump_code(type) + 0x10;
+ cond_set = U8(get_jump_code((sljit_uw)type) + 0x10);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
if (GET_OPCODE(op) == SLJIT_OR && !GET_ALL_FLAGS(op) && FAST_IS_REG(dst)) {
@@ -2802,9 +2783,9 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
*inst++ = GROUP_0F;
*inst++ = cond_set;
*inst++ = MOD_REG | reg_lmap[TMP_REG1];
- *inst++ = REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B);
+ *inst++ = U8(REX | (reg_map[TMP_REG1] <= 7 ? 0 : REX_R) | (reg_map[dst] <= 7 ? 0 : REX_B));
*inst++ = OR_rm8_r8;
- *inst++ = MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst];
+ *inst++ = U8(MOD_REG | (reg_lmap[TMP_REG1] << 3) | reg_lmap[dst]);
return SLJIT_SUCCESS;
}
@@ -2822,7 +2803,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
/* The movzx instruction does not affect flags. */
*inst++ = GROUP_0F;
*inst++ = MOVZX_r_rm8;
- *inst = MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg];
+ *inst = U8(MOD_REG | (reg_lmap[reg] << 3) | reg_lmap[reg]);
if (reg != TMP_REG1)
return SLJIT_SUCCESS;
@@ -2849,11 +2830,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
/* Set low byte to conditional flag. */
*inst++ = GROUP_0F;
*inst++ = cond_set;
- *inst++ = MOD_REG | reg_map[dst];
+ *inst++ = U8(MOD_REG | reg_map[dst]);
*inst++ = GROUP_0F;
*inst++ = MOVZX_r_rm8;
- *inst = MOD_REG | (reg_map[dst] << 3) | reg_map[dst];
+ *inst = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[dst]);
return SLJIT_SUCCESS;
}
@@ -2872,15 +2853,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
*inst++ = GROUP_0F;
/* cmovcc = setcc - 0x50. */
- *inst++ = cond_set - 0x50;
- *inst++ = MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1];
+ *inst++ = U8(cond_set - 0x50);
+ *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | reg_map[TMP_REG1]);
return SLJIT_SUCCESS;
}
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 3 + 1);
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
/* Set al to conditional flag. */
*inst++ = GROUP_0F;
*inst++ = cond_set;
@@ -2888,8 +2869,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
*inst++ = GROUP_0F;
*inst++ = MOVZX_r_rm8;
- *inst++ = MOD_REG | (reg_map[dst] << 3) | 0 /* eax */;
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(MOD_REG | (reg_map[dst] << 3) | 0 /* eax */);
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
return SLJIT_SUCCESS;
}
@@ -2901,13 +2882,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 2 + 1);
/* Set low register to conditional flag. */
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
*inst++ = GROUP_0F;
*inst++ = cond_set;
*inst++ = MOD_REG | 0 /* eax */;
*inst++ = OR_rm8_r8;
*inst++ = MOD_REG | (0 /* eax */ << 3) | reg_map[dst];
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
}
else {
inst = (sljit_u8*)ensure_buf(compiler, 1 + 2 + 3 + 2 + 2);
@@ -2915,14 +2896,14 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
INC_SIZE(2 + 3 + 2 + 2);
/* Set low register to conditional flag. */
*inst++ = XCHG_r_rm;
- *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];
+ *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]);
*inst++ = GROUP_0F;
*inst++ = cond_set;
*inst++ = MOD_REG | 1 /* ecx */;
*inst++ = OR_rm8_r8;
*inst++ = MOD_REG | (1 /* ecx */ << 3) | 0 /* eax */;
*inst++ = XCHG_r_rm;
- *inst++ = MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1];
+ *inst++ = U8(MOD_REG | (1 /* ecx */ << 3) | reg_map[TMP_REG1]);
}
return SLJIT_SUCCESS;
}
@@ -2931,7 +2912,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
inst = (sljit_u8*)ensure_buf(compiler, 1 + 1 + 3 + 3 + 1);
FAIL_IF(!inst);
INC_SIZE(1 + 3 + 3 + 1);
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
/* Set al to conditional flag. */
*inst++ = GROUP_0F;
*inst++ = cond_set;
@@ -2941,7 +2922,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_op_flags(struct sljit_compiler *co
*inst++ = MOVZX_r_rm8;
*inst++ = MOD_REG | (0 << 3) /* eax */ | 0 /* eax */;
- *inst++ = XCHG_EAX_r + reg_map[TMP_REG1];
+ *inst++ = U8(XCHG_EAX_r | reg_map[TMP_REG1]);
if (GET_OPCODE(op) < SLJIT_ADD)
return emit_mov(compiler, dst, dstw, TMP_REG1, 0);
@@ -2964,7 +2945,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
CHECK(check_sljit_emit_cmov(compiler, type, dst_reg, src, srcw));
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- dst_reg &= ~SLJIT_I32_OP;
+ dst_reg &= ~SLJIT_32;
if (!sljit_has_cpu_feature(SLJIT_HAS_CMOV) || (dst_reg >= SLJIT_R3 && dst_reg <= SLJIT_S3))
return sljit_emit_cmov_generic(compiler, type, dst_reg, src, srcw);
@@ -2977,8 +2958,8 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
CHECK_EXTRA_REGS(src, srcw, (void)0);
#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
- compiler->mode32 = dst_reg & SLJIT_I32_OP;
- dst_reg &= ~SLJIT_I32_OP;
+ compiler->mode32 = dst_reg & SLJIT_32;
+ dst_reg &= ~SLJIT_32;
#endif
if (SLJIT_UNLIKELY(src & SLJIT_IMM)) {
@@ -2990,7 +2971,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_emit_cmov(struct sljit_compiler *compil
inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw);
FAIL_IF(!inst);
*inst++ = GROUP_0F;
- *inst = get_jump_code(type & 0xff) - 0x40;
+ *inst = U8(get_jump_code(type & 0xff) - 0x40);
return SLJIT_SUCCESS;
}
@@ -3123,9 +3104,9 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_jump_addr(sljit_uw addr, sljit_uw new_ta
SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 0);
#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32)
- sljit_unaligned_store_sw((void*)addr, new_target - (addr + 4) - (sljit_uw)executable_offset);
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)(new_target - (addr + 4) - (sljit_uw)executable_offset));
#else
- sljit_unaligned_store_sw((void*)addr, (sljit_sw) new_target);
+ sljit_unaligned_store_sw((void*)addr, (sljit_sw)new_target);
#endif
SLJIT_UPDATE_WX_FLAGS((void*)addr, (void*)(addr + sizeof(sljit_uw)), 1);
}
diff --git a/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c
index 147175afa6..915411fbed 100644
--- a/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c
+++ b/thirdparty/pcre2/src/sljit/sljitProtExecAllocator.c
@@ -66,7 +66,7 @@
/* --------------------------------------------------------------------- */
/* 64 KByte. */
-#define CHUNK_SIZE 0x10000
+#define CHUNK_SIZE (sljit_uw)0x10000
struct chunk_header {
void *executable;
@@ -194,7 +194,7 @@ static SLJIT_INLINE struct chunk_header* alloc_chunk(sljit_uw size)
if (fd == -1)
return NULL;
- if (ftruncate(fd, size)) {
+ if (ftruncate(fd, (off_t)size)) {
close(fd);
return NULL;
}
@@ -281,7 +281,7 @@ struct free_block {
#define AS_FREE_BLOCK(base, offset) \
((struct free_block*)(((sljit_u8*)base) + offset))
#define MEM_START(base) ((void*)((base) + 1))
-#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7) & ~7)
+#define ALIGN_SIZE(size) (((size) + sizeof(struct block_header) + 7u) & ~(sljit_uw)7)
static struct free_block* free_blocks;
static sljit_uw allocated_size;
diff --git a/thirdparty/pcre2/src/sljit/sljitUtils.c b/thirdparty/pcre2/src/sljit/sljitUtils.c
index 9bce714735..967593b157 100644
--- a/thirdparty/pcre2/src/sljit/sljitUtils.c
+++ b/thirdparty/pcre2/src/sljit/sljitUtils.c
@@ -131,12 +131,12 @@ static SLJIT_INLINE int open_dev_zero(void)
#ifdef _WIN32
-static SLJIT_INLINE sljit_sw get_page_alignment(void) {
+static SLJIT_INLINE sljit_uw get_page_alignment(void) {
SYSTEM_INFO si;
- static sljit_sw sljit_page_align;
+ static sljit_uw sljit_page_align = 0;
if (!sljit_page_align) {
GetSystemInfo(&si);
- sljit_page_align = si.dwPageSize - 1;
+ sljit_page_align = (sljit_uw)si.dwPageSize - 1;
}
return sljit_page_align;
}
@@ -145,18 +145,21 @@ static SLJIT_INLINE sljit_sw get_page_alignment(void) {
#include <unistd.h>
-static SLJIT_INLINE sljit_sw get_page_alignment(void) {
- static sljit_sw sljit_page_align = -1;
- if (sljit_page_align < 0) {
+static SLJIT_INLINE sljit_uw get_page_alignment(void) {
+ static sljit_uw sljit_page_align = 0;
+
+ sljit_sw align;
+
+ if (!sljit_page_align) {
#ifdef _SC_PAGESIZE
- sljit_page_align = sysconf(_SC_PAGESIZE);
+ align = sysconf(_SC_PAGESIZE);
#else
- sljit_page_align = getpagesize();
+ align = getpagesize();
#endif
/* Should never happen. */
- if (sljit_page_align < 0)
- sljit_page_align = 4096;
- sljit_page_align--;
+ if (align < 0)
+ align = 4096;
+ sljit_page_align = (sljit_uw)align - 1;
}
return sljit_page_align;
}
@@ -227,7 +230,7 @@ SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *st
SLJIT_API_FUNC_ATTRIBUTE void SLJIT_FUNC sljit_free_stack(struct sljit_stack *stack, void *allocator_data)
{
SLJIT_UNUSED_ARG(allocator_data);
- munmap((void*)stack->min_start, stack->end - stack->min_start);
+ munmap((void*)stack->min_start, (size_t)(stack->end - stack->min_start));
SLJIT_FREE(stack, allocator_data);
}
@@ -237,7 +240,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_stack* SLJIT_FUNC sljit_allocate_stack(slj
{
struct sljit_stack *stack;
void *ptr;
- sljit_sw page_align;
+ sljit_uw page_align;
SLJIT_UNUSED_ARG(allocator_data);
@@ -295,7 +298,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_u8 *SLJIT_FUNC sljit_stack_resize(struct sljit_st
#if defined _WIN32 || defined(POSIX_MADV_DONTNEED)
sljit_uw aligned_old_start;
sljit_uw aligned_new_start;
- sljit_sw page_align;
+ sljit_uw page_align;
#endif
if ((new_start < stack->min_start) || (new_start >= stack->end))
diff --git a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
index e436af9a01..071278d659 100644
--- a/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
+++ b/thirdparty/recastnavigation/Recast/Include/RecastAlloc.h
@@ -22,7 +22,7 @@
#include <stddef.h>
#include <stdint.h>
-#include <RecastAssert.h>
+#include "RecastAssert.h"
/// Provides hint values to the memory allocator on how long the
/// memory is expected to be used.
@@ -106,6 +106,8 @@ class rcVectorBase {
// Creates an array of the given size, copies all of this vector's data into it, and returns it.
T* allocate_and_copy(rcSizeType size);
void resize_impl(rcSizeType size, const T* value);
+ // Requires: min_capacity > m_cap.
+ rcSizeType get_new_capacity(rcSizeType min_capacity);
public:
typedef rcSizeType size_type;
typedef T value_type;
@@ -196,8 +198,7 @@ void rcVectorBase<T, H>::push_back(const T& value) {
return;
}
- rcAssert(RC_SIZE_MAX / 2 >= m_size);
- rcSizeType new_cap = m_size ? 2*m_size : 1;
+ const rcSizeType new_cap = get_new_capacity(m_cap + 1);
T* data = allocate_and_copy(new_cap);
// construct between allocate and destroy+free in case value is
// in this vector.
@@ -208,25 +209,44 @@ void rcVectorBase<T, H>::push_back(const T& value) {
rcFree(m_data);
m_data = data;
}
+
+template <typename T, rcAllocHint H>
+rcSizeType rcVectorBase<T, H>::get_new_capacity(rcSizeType min_capacity) {
+ rcAssert(min_capacity <= RC_SIZE_MAX);
+ if (rcUnlikely(m_cap >= RC_SIZE_MAX / 2))
+ return RC_SIZE_MAX;
+ return 2 * m_cap > min_capacity ? 2 * m_cap : min_capacity;
+}
+
template <typename T, rcAllocHint H>
void rcVectorBase<T, H>::resize_impl(rcSizeType size, const T* value) {
if (size < m_size) {
destroy_range(size, m_size);
m_size = size;
} else if (size > m_size) {
- T* new_data = allocate_and_copy(size);
- // We defer deconstructing/freeing old data until after constructing
- // new elements in case "value" is there.
- if (value) {
- construct_range(new_data + m_size, new_data + size, *value);
+ if (size <= m_cap) {
+ if (value) {
+ construct_range(m_data + m_size, m_data + size, *value);
+ } else {
+ construct_range(m_data + m_size, m_data + size);
+ }
+ m_size = size;
} else {
- construct_range(new_data + m_size, new_data + size);
+ const rcSizeType new_cap = get_new_capacity(size);
+ T* new_data = allocate_and_copy(new_cap);
+ // We defer deconstructing/freeing old data until after constructing
+ // new elements in case "value" is there.
+ if (value) {
+ construct_range(new_data + m_size, new_data + size, *value);
+ } else {
+ construct_range(new_data + m_size, new_data + size);
+ }
+ destroy_range(0, m_size);
+ rcFree(m_data);
+ m_data = new_data;
+ m_cap = new_cap;
+ m_size = size;
}
- destroy_range(0, m_size);
- rcFree(m_data);
- m_data = new_data;
- m_cap = size;
- m_size = size;
}
}
template <typename T, rcAllocHint H>
@@ -303,6 +323,7 @@ public:
rcIntArray(int n) : m_impl(n, 0) {}
void push(int item) { m_impl.push_back(item); }
void resize(int size) { m_impl.resize(size); }
+ void clear() { m_impl.clear(); }
int pop()
{
int v = m_impl.back();
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp b/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
index 6574c11b6b..1293d4fbde 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastContour.cpp
@@ -921,8 +921,8 @@ bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf,
continue;
const unsigned char area = chf.areas[i];
- verts.resize(0);
- simplified.resize(0);
+ verts.clear();
+ simplified.clear();
ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE);
walkContour(x, y, i, chf, flags, verts);
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
index 9a423cab8a..1999200c1a 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastMeshDetail.cpp
@@ -653,8 +653,8 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
for (int i = 0; i < nin; ++i)
rcVcopy(&verts[i*3], &in[i*3]);
- edges.resize(0);
- tris.resize(0);
+ edges.clear();
+ tris.clear();
const float cs = chf.cs;
const float ics = 1.0f/cs;
@@ -803,7 +803,7 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
int x1 = (int)ceilf(bmax[0]/sampleDist);
int z0 = (int)floorf(bmin[2]/sampleDist);
int z1 = (int)ceilf(bmax[2]/sampleDist);
- samples.resize(0);
+ samples.clear();
for (int z = z0; z < z1; ++z)
{
for (int x = x0; x < x1; ++x)
@@ -864,8 +864,8 @@ static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin,
// Create new triangulation.
// TODO: Incremental add instead of full rebuild.
- edges.resize(0);
- tris.resize(0);
+ edges.clear();
+ tris.clear();
delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges);
}
}
@@ -935,7 +935,7 @@ static void seedArrayWithPolyCenter(rcContext* ctx, const rcCompactHeightfield&
pcy /= npoly;
// Use seeds array as a stack for DFS
- array.resize(0);
+ array.clear();
array.push(startCellX);
array.push(startCellY);
array.push(startSpanIndex);
@@ -1001,7 +1001,7 @@ static void seedArrayWithPolyCenter(rcContext* ctx, const rcCompactHeightfield&
rcSwap(dirs[directDir], dirs[3]);
}
- array.resize(0);
+ array.clear();
// getHeightData seeds are given in coordinates with borders
array.push(cx+bs);
array.push(cy+bs);
@@ -1030,7 +1030,7 @@ static void getHeightData(rcContext* ctx, const rcCompactHeightfield& chf,
// Note: Reads to the compact heightfield are offset by border size (bs)
// since border size offset is already removed from the polymesh vertices.
- queue.resize(0);
+ queue.clear();
// Set all heights to RC_UNSET_HEIGHT.
memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height);
diff --git a/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp b/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
index e1fc0ee788..48318688bc 100644
--- a/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
+++ b/thirdparty/recastnavigation/Recast/Source/RecastRegion.cpp
@@ -650,7 +650,7 @@ static bool mergeRegions(rcRegion& rega, rcRegion& regb)
return false;
// Merge neighbours.
- rega.connections.resize(0);
+ rega.connections.clear();
for (int i = 0, ni = acon.size(); i < ni-1; ++i)
rega.connections.push(acon[(insa+1+i) % ni]);
@@ -876,8 +876,8 @@ static bool mergeAndFilterRegions(rcContext* ctx, int minRegionArea, int mergeRe
// Also keep track of the regions connects to a tile border.
bool connectsToBorder = false;
int spanCount = 0;
- stack.resize(0);
- trace.resize(0);
+ stack.clear();
+ trace.clear();
reg.visited = true;
stack.push(i);
@@ -1068,7 +1068,7 @@ static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea,
{
const rcCompactCell& c = chf.cells[x+y*w];
- lregs.resize(0);
+ lregs.clear();
for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i)
{
@@ -1139,7 +1139,7 @@ static bool mergeAndFilterLayerRegions(rcContext* ctx, int minRegionArea,
// Start search.
root.id = layerId;
- stack.resize(0);
+ stack.clear();
stack.push(i);
while (stack.size() > 0)
diff --git a/thirdparty/rvo2/API.h b/thirdparty/rvo2/API.h
deleted file mode 100644
index c64efb452c..0000000000
--- a/thirdparty/rvo2/API.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * API.h
- * RVO2-3D Library
- *
- * Copyright 2008 University of North Carolina at Chapel Hill
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Please send all bug reports to <geom@cs.unc.edu>.
- *
- * The authors may be contacted via:
- *
- * Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
- * Dept. of Computer Science
- * 201 S. Columbia St.
- * Frederick P. Brooks, Jr. Computer Science Bldg.
- * Chapel Hill, N.C. 27599-3175
- * United States of America
- *
- * <http://gamma.cs.unc.edu/RVO2/>
- */
-
-/**
- * \file API.h
- * \brief Contains definitions related to Microsoft Windows.
- */
-
-#ifndef RVO_API_H_
-#define RVO_API_H_
-
-// -- GODOT start --
-#define RVO_API
-// -- GODOT end --
-
-#endif /* RVO_API_H_ */
diff --git a/thirdparty/rvo2/Agent.cpp b/thirdparty/rvo2/Agent.cpp
index 851d780758..b35eee9c12 100644
--- a/thirdparty/rvo2/Agent.cpp
+++ b/thirdparty/rvo2/Agent.cpp
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,40 +27,40 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
#include "Agent.h"
-#include <algorithm>
#include <cmath>
+#include <algorithm>
#include "Definitions.h"
#include "KdTree.h"
namespace RVO {
-/**
+ /**
* \brief A sufficiently small positive number.
*/
-const float RVO_EPSILON = 0.00001f;
+ const float RVO3D_EPSILON = 0.00001f;
-/**
+ /**
* \brief Defines a directed line.
*/
-class Line {
-public:
- /**
+ class Line {
+ public:
+ /**
* \brief The direction of the directed line.
*/
- Vector3 direction;
+ Vector3 direction;
- /**
+ /**
* \brief A point on the directed line.
*/
- Vector3 point;
-};
+ Vector3 point;
+ };
-/**
+ /**
* \brief Solves a one-dimensional linear program on a specified line subject to linear constraints defined by planes and a spherical constraint.
* \param planes Planes defining the linear constraints.
* \param planeNo The plane on which the line lies.
@@ -71,9 +71,9 @@ public:
* \param result A reference to the result of the linear program.
* \return True if successful.
*/
-bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+ bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
-/**
+ /**
* \brief Solves a two-dimensional linear program on a specified plane subject to linear constraints defined by planes and a spherical constraint.
* \param planes Planes defining the linear constraints.
* \param planeNo The plane on which the 2-d linear program is solved
@@ -83,9 +83,9 @@ bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line
* \param result A reference to the result of the linear program.
* \return True if successful.
*/
-bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+ bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
-/**
+ /**
* \brief Solves a three-dimensional linear program subject to linear constraints defined by planes and a spherical constraint.
* \param planes Planes defining the linear constraints.
* \param radius The radius of the spherical constraint.
@@ -94,332 +94,352 @@ bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radi
* \param result A reference to the result of the linear program.
* \return The number of the plane it fails on, and the number of planes if successful.
*/
-size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
+ size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result);
-/**
+ /**
* \brief Solves a four-dimensional linear program subject to linear constraints defined by planes and a spherical constraint.
* \param planes Planes defining the linear constraints.
* \param beginPlane The plane on which the 3-d linear program failed.
* \param radius The radius of the spherical constraint.
* \param result A reference to the result of the linear program.
*/
-void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result);
+ void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result);
-Agent::Agent() :
- id_(0), maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f), ignore_y_(false) {}
+ Agent::Agent() : id_(0), maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f), ignore_y_(false) { }
-void Agent::computeNeighbors(KdTree *kdTree_) {
- agentNeighbors_.clear();
- if (maxNeighbors_ > 0) {
- kdTree_->computeAgentNeighbors(this, neighborDist_ * neighborDist_);
- }
-}
+ void Agent::computeNeighbors(KdTree *kdTree_)
+ {
+ agentNeighbors_.clear();
+ if (maxNeighbors_ > 0) {
+ kdTree_->computeAgentNeighbors(this, neighborDist_ * neighborDist_);
+ }
+ }
+ void Agent::computeNewVelocity(float timeStep)
+ {
+ orcaPlanes_.clear();
+ const float invTimeHorizon = 1.0f / timeHorizon_;
+
+ /* Create agent ORCA planes. */
+ for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
+ const Agent *const other = agentNeighbors_[i].second;
+
+ Vector3 relativePosition = other->position_ - position_;
+ Vector3 relativeVelocity = velocity_ - other->velocity_;
+ const float combinedRadius = radius_ + other->radius_;
+
+ // This is a Godot feature that allow the agents to avoid the collision
+ // by moving only on the horizontal plane relative to the player velocity.
+ if (ignore_y_) {
+ // Skip if these are in two different heights
#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
-void Agent::computeNewVelocity(float timeStep) {
- orcaPlanes_.clear();
- const float invTimeHorizon = 1.0f / timeHorizon_;
-
- /* Create agent ORCA planes. */
- for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
- const Agent *const other = agentNeighbors_[i].second;
-
- Vector3 relativePosition = other->position_ - position_;
- Vector3 relativeVelocity = velocity_ - other->velocity_;
- const float combinedRadius = radius_ + other->radius_;
-
- // This is a Godot feature that allow the agents to avoid the collision
- // by moving only on the horizontal plane relative to the player velocity.
- if (ignore_y_) {
- // Skip if these are in two different heights
- if (ABS(relativePosition[1]) > combinedRadius * 2) {
- continue;
- }
- relativePosition[1] = 0;
- relativeVelocity[1] = 0;
- }
-
- const float distSq = absSq(relativePosition);
- const float combinedRadiusSq = sqr(combinedRadius);
-
- Plane plane;
- Vector3 u;
-
- if (distSq > combinedRadiusSq) {
- /* No collision. */
- const Vector3 w = relativeVelocity - invTimeHorizon * relativePosition;
- /* Vector from cutoff center to relative velocity. */
- const float wLengthSq = absSq(w);
-
- const float dotProduct = w * relativePosition;
-
- if (dotProduct < 0.0f && sqr(dotProduct) > combinedRadiusSq * wLengthSq) {
- /* Project on cut-off circle. */
- const float wLength = std::sqrt(wLengthSq);
- const Vector3 unitW = w / wLength;
-
- plane.normal = unitW;
- u = (combinedRadius * invTimeHorizon - wLength) * unitW;
- } else {
- /* Project on cone. */
- const float a = distSq;
- const float b = relativePosition * relativeVelocity;
- const float c = absSq(relativeVelocity) - absSq(cross(relativePosition, relativeVelocity)) / (distSq - combinedRadiusSq);
- const float t = (b + std::sqrt(sqr(b) - a * c)) / a;
- const Vector3 w = relativeVelocity - t * relativePosition;
+ if (ABS(relativePosition[1]) > combinedRadius * 2) {
+ continue;
+ }
+ relativePosition[1] = 0;
+ relativeVelocity[1] = 0;
+ }
+
+ const float distSq = absSq(relativePosition);
+ const float combinedRadiusSq = sqr(combinedRadius);
+
+ Plane plane;
+ Vector3 u;
+
+ if (distSq > combinedRadiusSq) {
+ /* No collision. */
+ const Vector3 w = relativeVelocity - invTimeHorizon * relativePosition;
+ /* Vector from cutoff center to relative velocity. */
+ const float wLengthSq = absSq(w);
+
+ const float dotProduct = w * relativePosition;
+
+ if (dotProduct < 0.0f && sqr(dotProduct) > combinedRadiusSq * wLengthSq) {
+ /* Project on cut-off circle. */
+ const float wLength = std::sqrt(wLengthSq);
+ const Vector3 unitW = w / wLength;
+
+ plane.normal = unitW;
+ u = (combinedRadius * invTimeHorizon - wLength) * unitW;
+ }
+ else {
+ /* Project on cone. */
+ const float a = distSq;
+ const float b = relativePosition * relativeVelocity;
+ const float c = absSq(relativeVelocity) - absSq(cross(relativePosition, relativeVelocity)) / (distSq - combinedRadiusSq);
+ const float t = (b + std::sqrt(sqr(b) - a * c)) / a;
+ const Vector3 ww = relativeVelocity - t * relativePosition;
+ const float wwLength = abs(ww);
+ const Vector3 unitWW = ww / wwLength;
+
+ plane.normal = unitWW;
+ u = (combinedRadius * t - wwLength) * unitWW;
+ }
+ }
+ else {
+ /* Collision. */
+ const float invTimeStep = 1.0f / timeStep;
+ const Vector3 w = relativeVelocity - invTimeStep * relativePosition;
const float wLength = abs(w);
const Vector3 unitW = w / wLength;
plane.normal = unitW;
- u = (combinedRadius * t - wLength) * unitW;
+ u = (combinedRadius * invTimeStep - wLength) * unitW;
}
- } else {
- /* Collision. */
- const float invTimeStep = 1.0f / timeStep;
- const Vector3 w = relativeVelocity - invTimeStep * relativePosition;
- const float wLength = abs(w);
- const Vector3 unitW = w / wLength;
-
- plane.normal = unitW;
- u = (combinedRadius * invTimeStep - wLength) * unitW;
- }
- plane.point = velocity_ + 0.5f * u;
- orcaPlanes_.push_back(plane);
- }
+ plane.point = velocity_ + 0.5f * u;
+ orcaPlanes_.push_back(plane);
+ }
- const size_t planeFail = linearProgram3(orcaPlanes_, maxSpeed_, prefVelocity_, false, newVelocity_);
+ const size_t planeFail = linearProgram3(orcaPlanes_, maxSpeed_, prefVelocity_, false, newVelocity_);
- if (planeFail < orcaPlanes_.size()) {
- linearProgram4(orcaPlanes_, planeFail, maxSpeed_, newVelocity_);
- }
+ if (planeFail < orcaPlanes_.size()) {
+ linearProgram4(orcaPlanes_, planeFail, maxSpeed_, newVelocity_);
+ }
- if (ignore_y_) {
- // Not 100% necessary, but better to have.
- newVelocity_[1] = prefVelocity_[1];
- }
-}
+ if (ignore_y_) {
+ // Not 100% necessary, but better to have.
+ newVelocity_[1] = prefVelocity_[1];
+ }
+ }
-void Agent::insertAgentNeighbor(const Agent *agent, float &rangeSq) {
- if (this != agent) {
- const float distSq = absSq(position_ - agent->position_);
+ void Agent::insertAgentNeighbor(const Agent *agent, float &rangeSq)
+ {
+ if (this != agent) {
+ const float distSq = absSq(position_ - agent->position_);
- if (distSq < rangeSq) {
- if (agentNeighbors_.size() < maxNeighbors_) {
- agentNeighbors_.push_back(std::make_pair(distSq, agent));
- }
+ if (distSq < rangeSq) {
+ if (agentNeighbors_.size() < maxNeighbors_) {
+ agentNeighbors_.push_back(std::make_pair(distSq, agent));
+ }
- size_t i = agentNeighbors_.size() - 1;
+ size_t i = agentNeighbors_.size() - 1;
- while (i != 0 && distSq < agentNeighbors_[i - 1].first) {
- agentNeighbors_[i] = agentNeighbors_[i - 1];
- --i;
- }
+ while (i != 0 && distSq < agentNeighbors_[i - 1].first) {
+ agentNeighbors_[i] = agentNeighbors_[i - 1];
+ --i;
+ }
- agentNeighbors_[i] = std::make_pair(distSq, agent);
+ agentNeighbors_[i] = std::make_pair(distSq, agent);
- if (agentNeighbors_.size() == maxNeighbors_) {
- rangeSq = agentNeighbors_.back().first;
+ if (agentNeighbors_.size() == maxNeighbors_) {
+ rangeSq = agentNeighbors_.back().first;
+ }
}
}
}
-}
-bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
- const float dotProduct = line.point * line.direction;
- const float discriminant = sqr(dotProduct) + sqr(radius) - absSq(line.point);
-
- if (discriminant < 0.0f) {
- /* Max speed sphere fully invalidates line. */
- return false;
- }
-
- const float sqrtDiscriminant = std::sqrt(discriminant);
- float tLeft = -dotProduct - sqrtDiscriminant;
- float tRight = -dotProduct + sqrtDiscriminant;
-
- for (size_t i = 0; i < planeNo; ++i) {
- const float numerator = (planes[i].point - line.point) * planes[i].normal;
- const float denominator = line.direction * planes[i].normal;
-
- if (sqr(denominator) <= RVO_EPSILON) {
- /* Lines line is (almost) parallel to plane i. */
- if (numerator > 0.0f) {
- return false;
- } else {
- continue;
+ bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result)
+ {
+ const float dotProduct = line.point * line.direction;
+ const float discriminant = sqr(dotProduct) + sqr(radius) - absSq(line.point);
+
+ if (discriminant < 0.0f) {
+ /* Max speed sphere fully invalidates line. */
+ return false;
+ }
+
+ const float sqrtDiscriminant = std::sqrt(discriminant);
+ float tLeft = -dotProduct - sqrtDiscriminant;
+ float tRight = -dotProduct + sqrtDiscriminant;
+
+ for (size_t i = 0; i < planeNo; ++i) {
+ const float numerator = (planes[i].point - line.point) * planes[i].normal;
+ const float denominator = line.direction * planes[i].normal;
+
+ if (sqr(denominator) <= RVO3D_EPSILON) {
+ /* Lines line is (almost) parallel to plane i. */
+ if (numerator > 0.0f) {
+ return false;
+ }
+ else {
+ continue;
+ }
}
- }
- const float t = numerator / denominator;
+ const float t = numerator / denominator;
- if (denominator >= 0.0f) {
- /* Plane i bounds line on the left. */
- tLeft = std::max(tLeft, t);
- } else {
- /* Plane i bounds line on the right. */
- tRight = std::min(tRight, t);
+ if (denominator >= 0.0f) {
+ /* Plane i bounds line on the left. */
+ tLeft = std::max(tLeft, t);
+ }
+ else {
+ /* Plane i bounds line on the right. */
+ tRight = std::min(tRight, t);
+ }
+
+ if (tLeft > tRight) {
+ return false;
+ }
}
- if (tLeft > tRight) {
- return false;
+ if (directionOpt) {
+ /* Optimize direction. */
+ if (optVelocity * line.direction > 0.0f) {
+ /* Take right extreme. */
+ result = line.point + tRight * line.direction;
+ }
+ else {
+ /* Take left extreme. */
+ result = line.point + tLeft * line.direction;
+ }
}
- }
-
- if (directionOpt) {
- /* Optimize direction. */
- if (optVelocity * line.direction > 0.0f) {
- /* Take right extreme. */
- result = line.point + tRight * line.direction;
- } else {
- /* Take left extreme. */
- result = line.point + tLeft * line.direction;
+ else {
+ /* Optimize closest point. */
+ const float t = line.direction * (optVelocity - line.point);
+
+ if (t < tLeft) {
+ result = line.point + tLeft * line.direction;
+ }
+ else if (t > tRight) {
+ result = line.point + tRight * line.direction;
+ }
+ else {
+ result = line.point + t * line.direction;
+ }
}
- } else {
- /* Optimize closest point. */
- const float t = line.direction * (optVelocity - line.point);
-
- if (t < tLeft) {
- result = line.point + tLeft * line.direction;
- } else if (t > tRight) {
- result = line.point + tRight * line.direction;
- } else {
- result = line.point + t * line.direction;
- }
- }
- return true;
-}
+ return true;
+ }
-bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
- const float planeDist = planes[planeNo].point * planes[planeNo].normal;
- const float planeDistSq = sqr(planeDist);
- const float radiusSq = sqr(radius);
+ bool linearProgram2(const std::vector<Plane> &planes, size_t planeNo, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result)
+ {
+ const float planeDist = planes[planeNo].point * planes[planeNo].normal;
+ const float planeDistSq = sqr(planeDist);
+ const float radiusSq = sqr(radius);
- if (planeDistSq > radiusSq) {
- /* Max speed sphere fully invalidates plane planeNo. */
- return false;
- }
+ if (planeDistSq > radiusSq) {
+ /* Max speed sphere fully invalidates plane planeNo. */
+ return false;
+ }
- const float planeRadiusSq = radiusSq - planeDistSq;
+ const float planeRadiusSq = radiusSq - planeDistSq;
- const Vector3 planeCenter = planeDist * planes[planeNo].normal;
+ const Vector3 planeCenter = planeDist * planes[planeNo].normal;
- if (directionOpt) {
- /* Project direction optVelocity on plane planeNo. */
- const Vector3 planeOptVelocity = optVelocity - (optVelocity * planes[planeNo].normal) * planes[planeNo].normal;
- const float planeOptVelocityLengthSq = absSq(planeOptVelocity);
+ if (directionOpt) {
+ /* Project direction optVelocity on plane planeNo. */
+ const Vector3 planeOptVelocity = optVelocity - (optVelocity * planes[planeNo].normal) * planes[planeNo].normal;
+ const float planeOptVelocityLengthSq = absSq(planeOptVelocity);
- if (planeOptVelocityLengthSq <= RVO_EPSILON) {
- result = planeCenter;
- } else {
- result = planeCenter + std::sqrt(planeRadiusSq / planeOptVelocityLengthSq) * planeOptVelocity;
+ if (planeOptVelocityLengthSq <= RVO3D_EPSILON) {
+ result = planeCenter;
+ }
+ else {
+ result = planeCenter + std::sqrt(planeRadiusSq / planeOptVelocityLengthSq) * planeOptVelocity;
+ }
}
- } else {
- /* Project point optVelocity on plane planeNo. */
- result = optVelocity + ((planes[planeNo].point - optVelocity) * planes[planeNo].normal) * planes[planeNo].normal;
-
- /* If outside planeCircle, project on planeCircle. */
- if (absSq(result) > radiusSq) {
- const Vector3 planeResult = result - planeCenter;
- const float planeResultLengthSq = absSq(planeResult);
- result = planeCenter + std::sqrt(planeRadiusSq / planeResultLengthSq) * planeResult;
+ else {
+ /* Project point optVelocity on plane planeNo. */
+ result = optVelocity + ((planes[planeNo].point - optVelocity) * planes[planeNo].normal) * planes[planeNo].normal;
+
+ /* If outside planeCircle, project on planeCircle. */
+ if (absSq(result) > radiusSq) {
+ const Vector3 planeResult = result - planeCenter;
+ const float planeResultLengthSq = absSq(planeResult);
+ result = planeCenter + std::sqrt(planeRadiusSq / planeResultLengthSq) * planeResult;
+ }
}
- }
-
- for (size_t i = 0; i < planeNo; ++i) {
- if (planes[i].normal * (planes[i].point - result) > 0.0f) {
- /* Result does not satisfy constraint i. Compute new optimal result. */
- /* Compute intersection line of plane i and plane planeNo. */
- Vector3 crossProduct = cross(planes[i].normal, planes[planeNo].normal);
-
- if (absSq(crossProduct) <= RVO_EPSILON) {
- /* Planes planeNo and i are (almost) parallel, and plane i fully invalidates plane planeNo. */
- return false;
- }
-
- Line line;
- line.direction = normalize(crossProduct);
- const Vector3 lineNormal = cross(line.direction, planes[planeNo].normal);
- line.point = planes[planeNo].point + (((planes[i].point - planes[planeNo].point) * planes[i].normal) / (lineNormal * planes[i].normal)) * lineNormal;
-
- if (!linearProgram1(planes, i, line, radius, optVelocity, directionOpt, result)) {
- return false;
+
+ for (size_t i = 0; i < planeNo; ++i) {
+ if (planes[i].normal * (planes[i].point - result) > 0.0f) {
+ /* Result does not satisfy constraint i. Compute new optimal result. */
+ /* Compute intersection line of plane i and plane planeNo. */
+ Vector3 crossProduct = cross(planes[i].normal, planes[planeNo].normal);
+
+ if (absSq(crossProduct) <= RVO3D_EPSILON) {
+ /* Planes planeNo and i are (almost) parallel, and plane i fully invalidates plane planeNo. */
+ return false;
+ }
+
+ Line line;
+ line.direction = normalize(crossProduct);
+ const Vector3 lineNormal = cross(line.direction, planes[planeNo].normal);
+ line.point = planes[planeNo].point + (((planes[i].point - planes[planeNo].point) * planes[i].normal) / (lineNormal * planes[i].normal)) * lineNormal;
+
+ if (!linearProgram1(planes, i, line, radius, optVelocity, directionOpt, result)) {
+ return false;
+ }
}
}
+
+ return true;
}
- return true;
-}
+ size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result)
+ {
+ if (directionOpt) {
+ /* Optimize direction. Note that the optimization velocity is of unit length in this case. */
+ result = optVelocity * radius;
+ }
+ else if (absSq(optVelocity) > sqr(radius)) {
+ /* Optimize closest point and outside circle. */
+ result = normalize(optVelocity) * radius;
+ }
+ else {
+ /* Optimize closest point and inside circle. */
+ result = optVelocity;
+ }
+
+ for (size_t i = 0; i < planes.size(); ++i) {
+ if (planes[i].normal * (planes[i].point - result) > 0.0f) {
+ /* Result does not satisfy constraint i. Compute new optimal result. */
+ const Vector3 tempResult = result;
-size_t linearProgram3(const std::vector<Plane> &planes, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result) {
- if (directionOpt) {
- /* Optimize direction. Note that the optimization velocity is of unit length in this case. */
- result = optVelocity * radius;
- } else if (absSq(optVelocity) > sqr(radius)) {
- /* Optimize closest point and outside circle. */
- result = normalize(optVelocity) * radius;
- } else {
- /* Optimize closest point and inside circle. */
- result = optVelocity;
- }
-
- for (size_t i = 0; i < planes.size(); ++i) {
- if (planes[i].normal * (planes[i].point - result) > 0.0f) {
- /* Result does not satisfy constraint i. Compute new optimal result. */
- const Vector3 tempResult = result;
-
- if (!linearProgram2(planes, i, radius, optVelocity, directionOpt, result)) {
- result = tempResult;
- return i;
+ if (!linearProgram2(planes, i, radius, optVelocity, directionOpt, result)) {
+ result = tempResult;
+ return i;
+ }
}
}
- }
- return planes.size();
-}
+ return planes.size();
+ }
-void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result) {
- float distance = 0.0f;
-
- for (size_t i = beginPlane; i < planes.size(); ++i) {
- if (planes[i].normal * (planes[i].point - result) > distance) {
- /* Result does not satisfy constraint of plane i. */
- std::vector<Plane> projPlanes;
-
- for (size_t j = 0; j < i; ++j) {
- Plane plane;
-
- const Vector3 crossProduct = cross(planes[j].normal, planes[i].normal);
-
- if (absSq(crossProduct) <= RVO_EPSILON) {
- /* Plane i and plane j are (almost) parallel. */
- if (planes[i].normal * planes[j].normal > 0.0f) {
- /* Plane i and plane j point in the same direction. */
- continue;
- } else {
- /* Plane i and plane j point in opposite direction. */
- plane.point = 0.5f * (planes[i].point + planes[j].point);
- }
- } else {
- /* Plane.point is point on line of intersection between plane i and plane j. */
- const Vector3 lineNormal = cross(crossProduct, planes[i].normal);
- plane.point = planes[i].point + (((planes[j].point - planes[i].point) * planes[j].normal) / (lineNormal * planes[j].normal)) * lineNormal;
+ void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result)
+ {
+ float distance = 0.0f;
+
+ for (size_t i = beginPlane; i < planes.size(); ++i) {
+ if (planes[i].normal * (planes[i].point - result) > distance) {
+ /* Result does not satisfy constraint of plane i. */
+ std::vector<Plane> projPlanes;
+
+ for (size_t j = 0; j < i; ++j) {
+ Plane plane;
+
+ const Vector3 crossProduct = cross(planes[j].normal, planes[i].normal);
+
+ if (absSq(crossProduct) <= RVO3D_EPSILON) {
+ /* Plane i and plane j are (almost) parallel. */
+ if (planes[i].normal * planes[j].normal > 0.0f) {
+ /* Plane i and plane j point in the same direction. */
+ continue;
+ }
+ else {
+ /* Plane i and plane j point in opposite direction. */
+ plane.point = 0.5f * (planes[i].point + planes[j].point);
+ }
+ }
+ else {
+ /* Plane.point is point on line of intersection between plane i and plane j. */
+ const Vector3 lineNormal = cross(crossProduct, planes[i].normal);
+ plane.point = planes[i].point + (((planes[j].point - planes[i].point) * planes[j].normal) / (lineNormal * planes[j].normal)) * lineNormal;
+ }
+
+ plane.normal = normalize(planes[j].normal - planes[i].normal);
+ projPlanes.push_back(plane);
}
- plane.normal = normalize(planes[j].normal - planes[i].normal);
- projPlanes.push_back(plane);
- }
+ const Vector3 tempResult = result;
- const Vector3 tempResult = result;
+ if (linearProgram3(projPlanes, radius, planes[i].normal, true, result) < projPlanes.size()) {
+ /* This should in principle not happen. The result is by definition already in the feasible region of this linear program. If it fails, it is due to small floating point error, and the current result is kept. */
+ result = tempResult;
+ }
- if (linearProgram3(projPlanes, radius, planes[i].normal, true, result) < projPlanes.size()) {
- /* This should in principle not happen. The result is by definition already in the feasible region of this linear program. If it fails, it is due to small floating point error, and the current result is kept. */
- result = tempResult;
+ distance = planes[i].normal * (planes[i].point - result);
}
-
- distance = planes[i].normal * (planes[i].point - result);
- }
+ }
}
}
-} // namespace RVO
diff --git a/thirdparty/rvo2/Agent.h b/thirdparty/rvo2/Agent.h
index 16f75a08f6..45fbead2f5 100644
--- a/thirdparty/rvo2/Agent.h
+++ b/thirdparty/rvo2/Agent.h
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,17 +27,15 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
/**
* \file Agent.h
* \brief Contains the Agent class.
*/
-#ifndef RVO_AGENT_H_
-#define RVO_AGENT_H_
-
-#include "API.h"
+#ifndef RVO3D_AGENT_H_
+#define RVO3D_AGENT_H_
#include <cstddef>
#include <utility>
@@ -53,69 +51,68 @@
// - Moved the `Plane` class here.
// - Added a new parameter `ignore_y_` in the `Agent`. This parameter is used to control a godot feature that allows to avoid collisions by moving on the horizontal plane.
namespace RVO {
-/**
- * \brief Defines a plane.
- */
-class Plane {
-public:
- /**
- * \brief A point on the plane.
- */
- Vector3 point;
-
- /**
- * \brief The normal to the plane.
- */
- Vector3 normal;
-};
+ /**
+ * \brief Defines a plane.
+ */
+ class Plane {
+ public:
+ /**
+ * \brief A point on the plane.
+ */
+ Vector3 point;
-/**
- * \brief Defines an agent in the simulation.
- */
-class Agent {
+ /**
+ * \brief The normal to the plane.
+ */
+ Vector3 normal;
+ };
-public:
- /**
+ /**
+ * \brief Defines an agent in the simulation.
+ */
+ class Agent {
+ public:
+ /**
* \brief Constructs an agent instance.
* \param sim The simulator instance.
*/
- explicit Agent();
+ explicit Agent();
- /**
+ /**
* \brief Computes the neighbors of this agent.
*/
- void computeNeighbors(class KdTree *kdTree_);
+ void computeNeighbors(class KdTree *kdTree_);
- /**
+ /**
* \brief Computes the new velocity of this agent.
*/
- void computeNewVelocity(float timeStep);
+ void computeNewVelocity(float timeStep);
- /**
+ /**
* \brief Inserts an agent neighbor into the set of neighbors of this agent.
* \param agent A pointer to the agent to be inserted.
* \param rangeSq The squared range around this agent.
*/
- void insertAgentNeighbor(const Agent *agent, float &rangeSq);
+ void insertAgentNeighbor(const Agent *agent, float &rangeSq);
- Vector3 newVelocity_;
- Vector3 position_;
- Vector3 prefVelocity_;
- Vector3 velocity_;
- size_t id_;
- size_t maxNeighbors_;
- float maxSpeed_;
- float neighborDist_;
- float radius_;
- float timeHorizon_;
- std::vector<std::pair<float, const Agent *> > agentNeighbors_;
- std::vector<Plane> orcaPlanes_;
- /// This is a godot feature that allows the Agent to avoid collision by mooving
- /// on the horizontal plane.
- bool ignore_y_;
+ Vector3 newVelocity_;
+ Vector3 position_;
+ Vector3 prefVelocity_;
+ Vector3 velocity_;
+ size_t id_;
+ size_t maxNeighbors_;
+ float maxSpeed_;
+ float neighborDist_;
+ float radius_;
+ float timeHorizon_;
+ std::vector<std::pair<float, const Agent *> > agentNeighbors_;
+ std::vector<Plane> orcaPlanes_;
+ /// This is a godot feature that allows the Agent to avoid collision by mooving
+ /// on the horizontal plane.
+ bool ignore_y_;
- friend class KdTree;
-};
-} // namespace RVO
+ friend class KdTree;
+ };
+}
-#endif /* RVO_AGENT_H_ */
+#endif /* RVO3D_AGENT_H_ */
diff --git a/thirdparty/rvo2/Definitions.h b/thirdparty/rvo2/Definitions.h
index a73aca9908..707d3c897f 100644
--- a/thirdparty/rvo2/Definitions.h
+++ b/thirdparty/rvo2/Definitions.h
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,7 +27,7 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
/**
@@ -35,10 +35,8 @@
* \brief Contains functions and constants used in multiple classes.
*/
-#ifndef RVO_DEFINITIONS_H_
-#define RVO_DEFINITIONS_H_
-
-#include "API.h"
+#ifndef RVO3D_DEFINITIONS_H_
+#define RVO3D_DEFINITIONS_H_
namespace RVO {
/**
@@ -52,4 +50,4 @@ namespace RVO {
}
}
-#endif /* RVO_DEFINITIONS_H_ */
+#endif /* RVO3D_DEFINITIONS_H_ */
diff --git a/thirdparty/rvo2/KdTree.cpp b/thirdparty/rvo2/KdTree.cpp
index bc224614f0..c857f299df 100644
--- a/thirdparty/rvo2/KdTree.cpp
+++ b/thirdparty/rvo2/KdTree.cpp
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,7 +27,7 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
#include "KdTree.h"
@@ -38,115 +38,123 @@
#include "Definitions.h"
namespace RVO {
-const size_t RVO_MAX_LEAF_SIZE = 10;
+ const size_t RVO3D_MAX_LEAF_SIZE = 10;
-KdTree::KdTree() {}
+ KdTree::KdTree() { }
-void KdTree::buildAgentTree(std::vector<Agent *> agents) {
- agents_.swap(agents);
+ void KdTree::buildAgentTree(std::vector<Agent *> agents)
+ {
+ agents_.swap(agents);
- if (!agents_.empty()) {
- agentTree_.resize(2 * agents_.size() - 1);
- buildAgentTreeRecursive(0, agents_.size(), 0);
+ if (!agents_.empty()) {
+ agentTree_.resize(2 * agents_.size() - 1);
+ buildAgentTreeRecursive(0, agents_.size(), 0);
+ }
}
-}
-void KdTree::buildAgentTreeRecursive(size_t begin, size_t end, size_t node) {
- agentTree_[node].begin = begin;
- agentTree_[node].end = end;
- agentTree_[node].minCoord = agents_[begin]->position_;
- agentTree_[node].maxCoord = agents_[begin]->position_;
-
- for (size_t i = begin + 1; i < end; ++i) {
- agentTree_[node].maxCoord[0] = std::max(agentTree_[node].maxCoord[0], agents_[i]->position_.x());
- agentTree_[node].minCoord[0] = std::min(agentTree_[node].minCoord[0], agents_[i]->position_.x());
- agentTree_[node].maxCoord[1] = std::max(agentTree_[node].maxCoord[1], agents_[i]->position_.y());
- agentTree_[node].minCoord[1] = std::min(agentTree_[node].minCoord[1], agents_[i]->position_.y());
- agentTree_[node].maxCoord[2] = std::max(agentTree_[node].maxCoord[2], agents_[i]->position_.z());
- agentTree_[node].minCoord[2] = std::min(agentTree_[node].minCoord[2], agents_[i]->position_.z());
- }
-
- if (end - begin > RVO_MAX_LEAF_SIZE) {
- /* No leaf node. */
- size_t coord;
-
- if (agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] && agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
- coord = 0;
- } else if (agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
- coord = 1;
- } else {
- coord = 2;
- }
-
- const float splitValue = 0.5f * (agentTree_[node].maxCoord[coord] + agentTree_[node].minCoord[coord]);
-
- size_t left = begin;
-
- size_t right = end;
-
- while (left < right) {
- while (left < right && agents_[left]->position_[coord] < splitValue) {
- ++left;
- }
-
- while (right > left && agents_[right - 1]->position_[coord] >= splitValue) {
- --right;
+ void KdTree::buildAgentTreeRecursive(size_t begin, size_t end, size_t node)
+ {
+ agentTree_[node].begin = begin;
+ agentTree_[node].end = end;
+ agentTree_[node].minCoord = agents_[begin]->position_;
+ agentTree_[node].maxCoord = agents_[begin]->position_;
+
+ for (size_t i = begin + 1; i < end; ++i) {
+ agentTree_[node].maxCoord[0] = std::max(agentTree_[node].maxCoord[0], agents_[i]->position_.x());
+ agentTree_[node].minCoord[0] = std::min(agentTree_[node].minCoord[0], agents_[i]->position_.x());
+ agentTree_[node].maxCoord[1] = std::max(agentTree_[node].maxCoord[1], agents_[i]->position_.y());
+ agentTree_[node].minCoord[1] = std::min(agentTree_[node].minCoord[1], agents_[i]->position_.y());
+ agentTree_[node].maxCoord[2] = std::max(agentTree_[node].maxCoord[2], agents_[i]->position_.z());
+ agentTree_[node].minCoord[2] = std::min(agentTree_[node].minCoord[2], agents_[i]->position_.z());
+ }
+
+ if (end - begin > RVO3D_MAX_LEAF_SIZE) {
+ /* No leaf node. */
+ size_t coord;
+
+ if (agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] && agentTree_[node].maxCoord[0] - agentTree_[node].minCoord[0] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
+ coord = 0;
+ }
+ else if (agentTree_[node].maxCoord[1] - agentTree_[node].minCoord[1] > agentTree_[node].maxCoord[2] - agentTree_[node].minCoord[2]) {
+ coord = 1;
+ }
+ else {
+ coord = 2;
}
- if (left < right) {
- std::swap(agents_[left], agents_[right - 1]);
- ++left;
- --right;
+ const float splitValue = 0.5f * (agentTree_[node].maxCoord[coord] + agentTree_[node].minCoord[coord]);
+
+ size_t left = begin;
+
+ size_t right = end;
+
+ while (left < right) {
+ while (left < right && agents_[left]->position_[coord] < splitValue) {
+ ++left;
+ }
+
+ while (right > left && agents_[right - 1]->position_[coord] >= splitValue) {
+ --right;
+ }
+
+ if (left < right) {
+ std::swap(agents_[left], agents_[right - 1]);
+ ++left;
+ --right;
+ }
}
- }
- size_t leftSize = left - begin;
+ size_t leftSize = left - begin;
- if (leftSize == 0) {
- ++leftSize;
- ++left;
- ++right;
- }
+ if (leftSize == 0) {
+ ++leftSize;
+ ++left;
+ ++right;
+ }
- agentTree_[node].left = node + 1;
- agentTree_[node].right = node + 2 * leftSize;
+ agentTree_[node].left = node + 1;
+ agentTree_[node].right = node + 2 * leftSize;
- buildAgentTreeRecursive(begin, left, agentTree_[node].left);
- buildAgentTreeRecursive(left, end, agentTree_[node].right);
+ buildAgentTreeRecursive(begin, left, agentTree_[node].left);
+ buildAgentTreeRecursive(left, end, agentTree_[node].right);
+ }
}
-}
-void KdTree::computeAgentNeighbors(Agent *agent, float rangeSq) const {
- queryAgentTreeRecursive(agent, rangeSq, 0);
-}
+ void KdTree::computeAgentNeighbors(Agent *agent, float rangeSq) const
+ {
+ queryAgentTreeRecursive(agent, rangeSq, 0);
+ }
-void KdTree::queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const {
- if (agentTree_[node].end - agentTree_[node].begin <= RVO_MAX_LEAF_SIZE) {
- for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
- agent->insertAgentNeighbor(agents_[i], rangeSq);
+ void KdTree::queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const
+ {
+ if (agentTree_[node].end - agentTree_[node].begin <= RVO3D_MAX_LEAF_SIZE) {
+ for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
+ agent->insertAgentNeighbor(agents_[i], rangeSq);
+ }
}
- } else {
- const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].left].maxCoord[2]));
+ else {
+ const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].left].maxCoord[2]));
- const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].right].maxCoord[2]));
+ const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[0] - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxCoord[0])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[1] - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxCoord[1])) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minCoord[2] - agent->position_.z())) + sqr(std::max(0.0f, agent->position_.z() - agentTree_[agentTree_[node].right].maxCoord[2]));
- if (distSqLeft < distSqRight) {
- if (distSqLeft < rangeSq) {
- queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+ if (distSqLeft < distSqRight) {
+ if (distSqLeft < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+ if (distSqRight < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
+ }
+ }
+ }
+ else {
if (distSqRight < rangeSq) {
queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
- }
- }
- } else {
- if (distSqRight < rangeSq) {
- queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
-
- if (distSqLeft < rangeSq) {
- queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+
+ if (distSqLeft < rangeSq) {
+ queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
+ }
}
}
}
}
}
-} // namespace RVO
diff --git a/thirdparty/rvo2/KdTree.h b/thirdparty/rvo2/KdTree.h
index 1dbad00ea4..69d8920ce0 100644
--- a/thirdparty/rvo2/KdTree.h
+++ b/thirdparty/rvo2/KdTree.h
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,16 +27,14 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
/**
* \file KdTree.h
* \brief Contains the KdTree class.
*/
-#ifndef RVO_KD_TREE_H_
-#define RVO_KD_TREE_H_
-
-#include "API.h"
+#ifndef RVO3D_KD_TREE_H_
+#define RVO3D_KD_TREE_H_
#include <cstddef>
#include <vector>
@@ -47,78 +45,78 @@
// - Removed `sim_`.
// - KdTree things are public
namespace RVO {
-class Agent;
-class RVOSimulator;
+ class Agent;
+ class RVOSimulator;
-/**
+ /**
* \brief Defines <i>k</i>d-trees for agents in the simulation.
*/
-class KdTree {
-public:
- /**
+ class KdTree {
+ public:
+ /**
* \brief Defines an agent <i>k</i>d-tree node.
*/
- class AgentTreeNode {
- public:
- /**
+ class AgentTreeNode {
+ public:
+ /**
* \brief The beginning node number.
*/
- size_t begin;
+ size_t begin;
- /**
+ /**
* \brief The ending node number.
*/
- size_t end;
+ size_t end;
- /**
+ /**
* \brief The left node number.
*/
- size_t left;
+ size_t left;
- /**
+ /**
* \brief The right node number.
*/
- size_t right;
+ size_t right;
- /**
+ /**
* \brief The maximum coordinates.
*/
- Vector3 maxCoord;
+ Vector3 maxCoord;
- /**
+ /**
* \brief The minimum coordinates.
*/
- Vector3 minCoord;
- };
+ Vector3 minCoord;
+ };
- /**
+ /**
* \brief Constructs a <i>k</i>d-tree instance.
* \param sim The simulator instance.
*/
- explicit KdTree();
+ explicit KdTree();
- /**
+ /**
* \brief Builds an agent <i>k</i>d-tree.
*/
- void buildAgentTree(std::vector<Agent *> agents);
+ void buildAgentTree(std::vector<Agent *> agents);
- void buildAgentTreeRecursive(size_t begin, size_t end, size_t node);
+ void buildAgentTreeRecursive(size_t begin, size_t end, size_t node);
- /**
+ /**
* \brief Computes the agent neighbors of the specified agent.
* \param agent A pointer to the agent for which agent neighbors are to be computed.
* \param rangeSq The squared range around the agent.
*/
- void computeAgentNeighbors(Agent *agent, float rangeSq) const;
+ void computeAgentNeighbors(Agent *agent, float rangeSq) const;
- void queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const;
+ void queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const;
- std::vector<Agent *> agents_;
- std::vector<AgentTreeNode> agentTree_;
+ std::vector<Agent *> agents_;
+ std::vector<AgentTreeNode> agentTree_;
- friend class Agent;
- friend class RVOSimulator;
-};
-} // namespace RVO
+ friend class Agent;
+ friend class RVOSimulator;
+ };
+}
-#endif /* RVO_KD_TREE_H_ */
+#endif /* RVO3D_KD_TREE_H_ */
diff --git a/thirdparty/rvo2/README.md b/thirdparty/rvo2/README.md
deleted file mode 100644
index 96af597cb6..0000000000
--- a/thirdparty/rvo2/README.md
+++ /dev/null
@@ -1,32 +0,0 @@
-Optimal Reciprocal Collision Avoidance in Three Dimensions
-==========================================================
-
-<http://gamma.cs.unc.edu/RVO2/>
-
-[![Build Status](https://travis-ci.org/snape/RVO2-3D.png?branch=master)](https://travis-ci.org/snape/RVO2-3D)
-[![Build status](https://ci.appveyor.com/api/projects/status/ov8ec3igv588wpx7/branch/master?svg=true)](https://ci.appveyor.com/project/snape/rvo2-3d)
-
-Copyright 2008 University of North Carolina at Chapel Hill
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-<http://www.apache.org/licenses/LICENSE-2.0>
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-Please send all bug reports to [geom@cs.unc.edu](mailto:geom@cs.unc.edu).
-
-The authors may be contacted via:
-
-Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, and Dinesh Manocha
-Dept. of Computer Science
-201 S. Columbia St.
-Frederick P. Brooks, Jr. Computer Science Bldg.
-Chapel Hill, N.C. 27599-3175
-United States of America
diff --git a/thirdparty/rvo2/Vector3.h b/thirdparty/rvo2/Vector3.h
index 8c8835c865..f44e311f29 100644
--- a/thirdparty/rvo2/Vector3.h
+++ b/thirdparty/rvo2/Vector3.h
@@ -8,7 +8,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,32 +27,32 @@
* Chapel Hill, N.C. 27599-3175
* United States of America
*
- * <http://gamma.cs.unc.edu/RVO2/>
+ * <https://gamma.cs.unc.edu/RVO2/>
*/
/**
* \file Vector3.h
* \brief Contains the Vector3 class.
*/
-#ifndef RVO_VECTOR3_H_
-#define RVO_VECTOR3_H_
-
-#include "API.h"
+#ifndef RVO3D_VECTOR3_H_
+#define RVO3D_VECTOR3_H_
#include <cmath>
#include <cstddef>
#include <ostream>
+#define RVO3D_EXPORT
+
namespace RVO {
/**
* \brief Defines a three-dimensional vector.
*/
- class Vector3 {
+ class RVO3D_EXPORT Vector3 {
public:
/**
* \brief Constructs and initializes a three-dimensional vector instance to zero.
*/
- RVO_API inline Vector3()
+ inline Vector3()
{
val_[0] = 0.0f;
val_[1] = 0.0f;
@@ -63,7 +63,7 @@ namespace RVO {
* \brief Constructs and initializes a three-dimensional vector from the specified three-element array.
* \param val The three-element array containing the xyz-coordinates.
*/
- RVO_API inline explicit Vector3(const float val[3])
+ inline explicit Vector3(const float val[3])
{
val_[0] = val[0];
val_[1] = val[1];
@@ -76,7 +76,7 @@ namespace RVO {
* \param y The y-coordinate of the three-dimensional vector.
* \param z The z-coordinate of the three-dimensional vector.
*/
- RVO_API inline Vector3(float x, float y, float z)
+ inline Vector3(float x, float y, float z)
{
val_[0] = x;
val_[1] = y;
@@ -87,39 +87,39 @@ namespace RVO {
* \brief Returns the x-coordinate of this three-dimensional vector.
* \return The x-coordinate of the three-dimensional vector.
*/
- RVO_API inline float x() const { return val_[0]; }
+ inline float x() const { return val_[0]; }
/**
* \brief Returns the y-coordinate of this three-dimensional vector.
* \return The y-coordinate of the three-dimensional vector.
*/
- RVO_API inline float y() const { return val_[1]; }
+ inline float y() const { return val_[1]; }
/**
* \brief Returns the z-coordinate of this three-dimensional vector.
* \return The z-coordinate of the three-dimensional vector.
*/
- RVO_API inline float z() const { return val_[2]; }
+ inline float z() const { return val_[2]; }
/**
* \brief Returns the specified coordinate of this three-dimensional vector.
* \param i The coordinate that should be returned (0 <= i < 3).
* \return The specified coordinate of the three-dimensional vector.
*/
- RVO_API inline float operator[](size_t i) const { return val_[i]; }
+ inline float operator[](size_t i) const { return val_[i]; }
/**
* \brief Returns a reference to the specified coordinate of this three-dimensional vector.
* \param i The coordinate to which a reference should be returned (0 <= i < 3).
* \return A reference to the specified coordinate of the three-dimensional vector.
*/
- RVO_API inline float &operator[](size_t i) { return val_[i]; }
+ inline float &operator[](size_t i) { return val_[i]; }
/**
* \brief Computes the negation of this three-dimensional vector.
* \return The negation of this three-dimensional vector.
*/
- RVO_API inline Vector3 operator-() const
+ inline Vector3 operator-() const
{
return Vector3(-val_[0], -val_[1], -val_[2]);
}
@@ -129,7 +129,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the dot product should be computed.
* \return The dot product of this three-dimensional vector with a specified three-dimensional vector.
*/
- RVO_API inline float operator*(const Vector3 &vector) const
+ inline float operator*(const Vector3 &vector) const
{
return val_[0] * vector[0] + val_[1] * vector[1] + val_[2] * vector[2];
}
@@ -139,7 +139,7 @@ namespace RVO {
* \param scalar The scalar value with which the scalar multiplication should be computed.
* \return The scalar multiplication of this three-dimensional vector with a specified scalar value.
*/
- RVO_API inline Vector3 operator*(float scalar) const
+ inline Vector3 operator*(float scalar) const
{
return Vector3(val_[0] * scalar, val_[1] * scalar, val_[2] * scalar);
}
@@ -149,7 +149,7 @@ namespace RVO {
* \param scalar The scalar value with which the scalar division should be computed.
* \return The scalar division of this three-dimensional vector with a specified scalar value.
*/
- RVO_API inline Vector3 operator/(float scalar) const
+ inline Vector3 operator/(float scalar) const
{
const float invScalar = 1.0f / scalar;
@@ -161,7 +161,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the vector sum should be computed.
* \return The vector sum of this three-dimensional vector with a specified three-dimensional vector.
*/
- RVO_API inline Vector3 operator+(const Vector3 &vector) const
+ inline Vector3 operator+(const Vector3 &vector) const
{
return Vector3(val_[0] + vector[0], val_[1] + vector[1], val_[2] + vector[2]);
}
@@ -171,7 +171,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the vector difference should be computed.
* \return The vector difference of this three-dimensional vector with a specified three-dimensional vector.
*/
- RVO_API inline Vector3 operator-(const Vector3 &vector) const
+ inline Vector3 operator-(const Vector3 &vector) const
{
return Vector3(val_[0] - vector[0], val_[1] - vector[1], val_[2] - vector[2]);
}
@@ -181,7 +181,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which to test for equality.
* \return True if the three-dimensional vectors are equal.
*/
- RVO_API inline bool operator==(const Vector3 &vector) const
+ inline bool operator==(const Vector3 &vector) const
{
return val_[0] == vector[0] && val_[1] == vector[1] && val_[2] == vector[2];
}
@@ -191,7 +191,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which to test for inequality.
* \return True if the three-dimensional vectors are not equal.
*/
- RVO_API inline bool operator!=(const Vector3 &vector) const
+ inline bool operator!=(const Vector3 &vector) const
{
return val_[0] != vector[0] || val_[1] != vector[1] || val_[2] != vector[2];
}
@@ -201,7 +201,7 @@ namespace RVO {
* \param scalar The scalar value with which the scalar multiplication should be computed.
* \return A reference to this three-dimensional vector.
*/
- RVO_API inline Vector3 &operator*=(float scalar)
+ inline Vector3 &operator*=(float scalar)
{
val_[0] *= scalar;
val_[1] *= scalar;
@@ -215,7 +215,7 @@ namespace RVO {
* \param scalar The scalar value with which the scalar division should be computed.
* \return A reference to this three-dimensional vector.
*/
- RVO_API inline Vector3 &operator/=(float scalar)
+ inline Vector3 &operator/=(float scalar)
{
const float invScalar = 1.0f / scalar;
@@ -232,7 +232,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the vector sum should be computed.
* \return A reference to this three-dimensional vector.
*/
- RVO_API inline Vector3 &operator+=(const Vector3 &vector)
+ inline Vector3 &operator+=(const Vector3 &vector)
{
val_[0] += vector[0];
val_[1] += vector[1];
@@ -246,7 +246,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the vector difference should be computed.
* \return A reference to this three-dimensional vector.
*/
- RVO_API inline Vector3 &operator-=(const Vector3 &vector)
+ inline Vector3 &operator-=(const Vector3 &vector)
{
val_[0] -= vector[0];
val_[1] -= vector[1];
@@ -267,7 +267,7 @@ namespace RVO {
* \param vector The three-dimensional vector with which the scalar multiplication should be computed.
* \return The scalar multiplication of the three-dimensional vector with the scalar value.
*/
- inline Vector3 operator*(float scalar, const Vector3 &vector)
+ RVO3D_EXPORT inline Vector3 operator*(float scalar, const Vector3 &vector)
{
return Vector3(scalar * vector[0], scalar * vector[1], scalar * vector[2]);
}
@@ -279,7 +279,7 @@ namespace RVO {
* \param vector2 The second vector with which the cross product should be computed.
* \return The cross product of the two specified vectors.
*/
- inline Vector3 cross(const Vector3 &vector1, const Vector3 &vector2)
+ RVO3D_EXPORT inline Vector3 cross(const Vector3 &vector1, const Vector3 &vector2)
{
return Vector3(vector1[1] * vector2[2] - vector1[2] * vector2[1], vector1[2] * vector2[0] - vector1[0] * vector2[2], vector1[0] * vector2[1] - vector1[1] * vector2[0]);
}
@@ -291,7 +291,7 @@ namespace RVO {
* \param vector The three-dimensional vector which to insert into the output stream.
* \return A reference to the output stream.
*/
- inline std::ostream &operator<<(std::ostream &os, const Vector3 &vector)
+ RVO3D_EXPORT inline std::ostream &operator<<(std::ostream &os, const Vector3 &vector)
{
os << "(" << vector[0] << "," << vector[1] << "," << vector[2] << ")";
@@ -304,7 +304,7 @@ namespace RVO {
* \param vector The three-dimensional vector whose length is to be computed.
* \return The length of the three-dimensional vector.
*/
- inline float abs(const Vector3 &vector)
+ RVO3D_EXPORT inline float abs(const Vector3 &vector)
{
return std::sqrt(vector * vector);
}
@@ -315,7 +315,7 @@ namespace RVO {
* \param vector The three-dimensional vector whose squared length is to be computed.
* \return The squared length of the three-dimensional vector.
*/
- inline float absSq(const Vector3 &vector)
+ RVO3D_EXPORT inline float absSq(const Vector3 &vector)
{
return vector * vector;
}
@@ -326,7 +326,7 @@ namespace RVO {
* \param vector The three-dimensional vector whose normalization is to be computed.
* \return The normalization of the three-dimensional vector.
*/
- inline Vector3 normalize(const Vector3 &vector)
+ RVO3D_EXPORT inline Vector3 normalize(const Vector3 &vector)
{
return vector / abs(vector);
}
diff --git a/thirdparty/rvo2/patches/rvo2-godot-changes.patch b/thirdparty/rvo2/patches/rvo2-godot-changes.patch
new file mode 100644
index 0000000000..16dbc203ed
--- /dev/null
+++ b/thirdparty/rvo2/patches/rvo2-godot-changes.patch
@@ -0,0 +1,282 @@
+diff --git a/thirdparty/rvo2/Agent.cpp b/thirdparty/rvo2/Agent.cpp
+index 5e49a3554c..b35eee9c12 100644
+--- a/thirdparty/rvo2/Agent.cpp
++++ b/thirdparty/rvo2/Agent.cpp
+@@ -105,18 +105,17 @@ namespace RVO {
+ */
+ void linearProgram4(const std::vector<Plane> &planes, size_t beginPlane, float radius, Vector3 &result);
+
+- Agent::Agent(RVOSimulator *sim) : sim_(sim), id_(0), maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f) { }
++ Agent::Agent() : id_(0), maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f), ignore_y_(false) { }
+
+- void Agent::computeNeighbors()
++ void Agent::computeNeighbors(KdTree *kdTree_)
+ {
+ agentNeighbors_.clear();
+-
+ if (maxNeighbors_ > 0) {
+- sim_->kdTree_->computeAgentNeighbors(this, neighborDist_ * neighborDist_);
++ kdTree_->computeAgentNeighbors(this, neighborDist_ * neighborDist_);
+ }
+ }
+
+- void Agent::computeNewVelocity()
++ void Agent::computeNewVelocity(float timeStep)
+ {
+ orcaPlanes_.clear();
+ const float invTimeHorizon = 1.0f / timeHorizon_;
+@@ -124,10 +123,24 @@ namespace RVO {
+ /* Create agent ORCA planes. */
+ for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
+ const Agent *const other = agentNeighbors_[i].second;
+- const Vector3 relativePosition = other->position_ - position_;
+- const Vector3 relativeVelocity = velocity_ - other->velocity_;
+- const float distSq = absSq(relativePosition);
++
++ Vector3 relativePosition = other->position_ - position_;
++ Vector3 relativeVelocity = velocity_ - other->velocity_;
+ const float combinedRadius = radius_ + other->radius_;
++
++ // This is a Godot feature that allow the agents to avoid the collision
++ // by moving only on the horizontal plane relative to the player velocity.
++ if (ignore_y_) {
++ // Skip if these are in two different heights
++#define ABS(m_v) (((m_v) < 0) ? (-(m_v)) : (m_v))
++ if (ABS(relativePosition[1]) > combinedRadius * 2) {
++ continue;
++ }
++ relativePosition[1] = 0;
++ relativeVelocity[1] = 0;
++ }
++
++ const float distSq = absSq(relativePosition);
+ const float combinedRadiusSq = sqr(combinedRadius);
+
+ Plane plane;
+@@ -165,7 +178,7 @@ namespace RVO {
+ }
+ else {
+ /* Collision. */
+- const float invTimeStep = 1.0f / sim_->timeStep_;
++ const float invTimeStep = 1.0f / timeStep;
+ const Vector3 w = relativeVelocity - invTimeStep * relativePosition;
+ const float wLength = abs(w);
+ const Vector3 unitW = w / wLength;
+@@ -183,6 +196,11 @@ namespace RVO {
+ if (planeFail < orcaPlanes_.size()) {
+ linearProgram4(orcaPlanes_, planeFail, maxSpeed_, newVelocity_);
+ }
++
++ if (ignore_y_) {
++ // Not 100% necessary, but better to have.
++ newVelocity_[1] = prefVelocity_[1];
++ }
+ }
+
+ void Agent::insertAgentNeighbor(const Agent *agent, float &rangeSq)
+@@ -211,12 +229,6 @@ namespace RVO {
+ }
+ }
+
+- void Agent::update()
+- {
+- velocity_ = newVelocity_;
+- position_ += velocity_ * sim_->timeStep_;
+- }
+-
+ bool linearProgram1(const std::vector<Plane> &planes, size_t planeNo, const Line &line, float radius, const Vector3 &optVelocity, bool directionOpt, Vector3 &result)
+ {
+ const float dotProduct = line.point * line.direction;
+diff --git a/thirdparty/rvo2/Agent.h b/thirdparty/rvo2/Agent.h
+index d3922ec645..45fbead2f5 100644
+--- a/thirdparty/rvo2/Agent.h
++++ b/thirdparty/rvo2/Agent.h
+@@ -41,30 +41,52 @@
+ #include <utility>
+ #include <vector>
+
+-#include "RVOSimulator.h"
+ #include "Vector3.h"
+
++// Note: Slightly modified to work better in Godot.
++// - The agent can be created by anyone.
++// - The simulator pointer is removed.
++// - The update function is removed.
++// - The compute velocity function now need the timeStep.
++// - Moved the `Plane` class here.
++// - Added a new parameter `ignore_y_` in the `Agent`. This parameter is used to control a godot feature that allows to avoid collisions by moving on the horizontal plane.
+ namespace RVO {
++ /**
++ * \brief Defines a plane.
++ */
++ class Plane {
++ public:
++ /**
++ * \brief A point on the plane.
++ */
++ Vector3 point;
++
++ /**
++ * \brief The normal to the plane.
++ */
++ Vector3 normal;
++ };
++
+ /**
+ * \brief Defines an agent in the simulation.
+ */
+ class Agent {
+- private:
++ public:
+ /**
+ * \brief Constructs an agent instance.
+ * \param sim The simulator instance.
+ */
+- explicit Agent(RVOSimulator *sim);
++ explicit Agent();
+
+ /**
+ * \brief Computes the neighbors of this agent.
+ */
+- void computeNeighbors();
++ void computeNeighbors(class KdTree *kdTree_);
+
+ /**
+ * \brief Computes the new velocity of this agent.
+ */
+- void computeNewVelocity();
++ void computeNewVelocity(float timeStep);
+
+ /**
+ * \brief Inserts an agent neighbor into the set of neighbors of this agent.
+@@ -73,16 +95,10 @@ namespace RVO {
+ */
+ void insertAgentNeighbor(const Agent *agent, float &rangeSq);
+
+- /**
+- * \brief Updates the three-dimensional position and three-dimensional velocity of this agent.
+- */
+- void update();
+-
+ Vector3 newVelocity_;
+ Vector3 position_;
+ Vector3 prefVelocity_;
+ Vector3 velocity_;
+- RVOSimulator *sim_;
+ size_t id_;
+ size_t maxNeighbors_;
+ float maxSpeed_;
+@@ -91,9 +107,11 @@ namespace RVO {
+ float timeHorizon_;
+ std::vector<std::pair<float, const Agent *> > agentNeighbors_;
+ std::vector<Plane> orcaPlanes_;
++ /// This is a godot feature that allows the Agent to avoid collision by mooving
++ /// on the horizontal plane.
++ bool ignore_y_;
+
+ friend class KdTree;
+- friend class RVOSimulator;
+ };
+ }
+
+diff --git a/thirdparty/rvo2/KdTree.cpp b/thirdparty/rvo2/KdTree.cpp
+index 5e9e9777a6..c857f299df 100644
+--- a/thirdparty/rvo2/KdTree.cpp
++++ b/thirdparty/rvo2/KdTree.cpp
+@@ -36,16 +36,15 @@
+
+ #include "Agent.h"
+ #include "Definitions.h"
+-#include "RVOSimulator.h"
+
+ namespace RVO {
+ const size_t RVO3D_MAX_LEAF_SIZE = 10;
+
+- KdTree::KdTree(RVOSimulator *sim) : sim_(sim) { }
++ KdTree::KdTree() { }
+
+- void KdTree::buildAgentTree()
++ void KdTree::buildAgentTree(std::vector<Agent *> agents)
+ {
+- agents_ = sim_->agents_;
++ agents_.swap(agents);
+
+ if (!agents_.empty()) {
+ agentTree_.resize(2 * agents_.size() - 1);
+diff --git a/thirdparty/rvo2/KdTree.h b/thirdparty/rvo2/KdTree.h
+index a09384c20f..69d8920ce0 100644
+--- a/thirdparty/rvo2/KdTree.h
++++ b/thirdparty/rvo2/KdTree.h
+@@ -41,6 +41,9 @@
+
+ #include "Vector3.h"
+
++// Note: Slightly modified to work better with Godot.
++// - Removed `sim_`.
++// - KdTree things are public
+ namespace RVO {
+ class Agent;
+ class RVOSimulator;
+@@ -49,7 +52,7 @@ namespace RVO {
+ * \brief Defines <i>k</i>d-trees for agents in the simulation.
+ */
+ class KdTree {
+- private:
++ public:
+ /**
+ * \brief Defines an agent <i>k</i>d-tree node.
+ */
+@@ -90,12 +93,12 @@ namespace RVO {
+ * \brief Constructs a <i>k</i>d-tree instance.
+ * \param sim The simulator instance.
+ */
+- explicit KdTree(RVOSimulator *sim);
++ explicit KdTree();
+
+ /**
+ * \brief Builds an agent <i>k</i>d-tree.
+ */
+- void buildAgentTree();
++ void buildAgentTree(std::vector<Agent *> agents);
+
+ void buildAgentTreeRecursive(size_t begin, size_t end, size_t node);
+
+@@ -110,7 +113,6 @@ namespace RVO {
+
+ std::vector<Agent *> agents_;
+ std::vector<AgentTreeNode> agentTree_;
+- RVOSimulator *sim_;
+
+ friend class Agent;
+ friend class RVOSimulator;
+diff --git a/thirdparty/rvo2/Vector3.h b/thirdparty/rvo2/Vector3.h
+index 6c3223bb87..f44e311f29 100644
+--- a/thirdparty/rvo2/Vector3.h
++++ b/thirdparty/rvo2/Vector3.h
+@@ -41,7 +41,7 @@
+ #include <cstddef>
+ #include <ostream>
+
+-#include "Export.h"
++#define RVO3D_EXPORT
+
+ namespace RVO {
+ /**
+@@ -59,17 +59,6 @@ namespace RVO {
+ val_[2] = 0.0f;
+ }
+
+- /**
+- * \brief Constructs and initializes a three-dimensional vector from the specified three-dimensional vector.
+- * \param vector The three-dimensional vector containing the xyz-coordinates.
+- */
+- inline Vector3(const Vector3 &vector)
+- {
+- val_[0] = vector[0];
+- val_[1] = vector[1];
+- val_[2] = vector[2];
+- }
+-
+ /**
+ * \brief Constructs and initializes a three-dimensional vector from the specified three-element array.
+ * \param val The three-element array containing the xyz-coordinates.
diff --git a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
index c15736e255..ae81f141c4 100644
--- a/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
+++ b/thirdparty/spirv-reflect/include/spirv/unified1/spirv.h
@@ -70,6 +70,7 @@ typedef enum SpvSourceLanguage_ {
SpvSourceLanguageOpenCL_CPP = 4,
SpvSourceLanguageHLSL = 5,
SpvSourceLanguageCPP_for_OpenCL = 6,
+ SpvSourceLanguageSYCL = 7,
SpvSourceLanguageMax = 0x7fffffff,
} SpvSourceLanguage;
@@ -184,6 +185,7 @@ typedef enum SpvExecutionMode_ {
SpvExecutionModeNoGlobalOffsetINTEL = 5895,
SpvExecutionModeNumSIMDWorkitemsINTEL = 5896,
SpvExecutionModeSchedulerTargetFmaxMhzINTEL = 5903,
+ SpvExecutionModeNamedBarrierCountINTEL = 6417,
SpvExecutionModeMax = 0x7fffffff,
} SpvExecutionMode;
@@ -546,6 +548,8 @@ typedef enum SpvDecoration_ {
SpvDecorationPrefetchINTEL = 5902,
SpvDecorationStallEnableINTEL = 5905,
SpvDecorationFuseLoopsInFunctionINTEL = 5907,
+ SpvDecorationAliasScopeINTEL = 5914,
+ SpvDecorationNoAliasINTEL = 5915,
SpvDecorationBufferLocationINTEL = 5921,
SpvDecorationIOPipeStorageINTEL = 5944,
SpvDecorationFunctionFloatingPointModeINTEL = 6080,
@@ -677,6 +681,7 @@ typedef enum SpvBuiltIn_ {
SpvBuiltInSMCountNV = 5375,
SpvBuiltInWarpIDNV = 5376,
SpvBuiltInSMIDNV = 5377,
+ SpvBuiltInCullMaskKHR = 6021,
SpvBuiltInMax = 0x7fffffff,
} SpvBuiltIn;
@@ -804,6 +809,8 @@ typedef enum SpvMemoryAccessShift_ {
SpvMemoryAccessMakePointerVisibleKHRShift = 4,
SpvMemoryAccessNonPrivatePointerShift = 5,
SpvMemoryAccessNonPrivatePointerKHRShift = 5,
+ SpvMemoryAccessAliasScopeINTELMaskShift = 16,
+ SpvMemoryAccessNoAliasINTELMaskShift = 17,
SpvMemoryAccessMax = 0x7fffffff,
} SpvMemoryAccessShift;
@@ -818,6 +825,8 @@ typedef enum SpvMemoryAccessMask_ {
SpvMemoryAccessMakePointerVisibleKHRMask = 0x00000010,
SpvMemoryAccessNonPrivatePointerMask = 0x00000020,
SpvMemoryAccessNonPrivatePointerKHRMask = 0x00000020,
+ SpvMemoryAccessAliasScopeINTELMaskMask = 0x00010000,
+ SpvMemoryAccessNoAliasINTELMaskMask = 0x00020000,
} SpvMemoryAccessMask;
typedef enum SpvScope_ {
@@ -1059,6 +1068,7 @@ typedef enum SpvCapability_ {
SpvCapabilityFPGAMemoryAccessesINTEL = 5898,
SpvCapabilityFPGAClusterAttributesINTEL = 5904,
SpvCapabilityLoopFuseINTEL = 5906,
+ SpvCapabilityMemoryAccessAliasingINTEL = 5910,
SpvCapabilityFPGABufferLocationINTEL = 5920,
SpvCapabilityArbitraryPrecisionFixedPointINTEL = 5922,
SpvCapabilityUSMStorageClassesINTEL = 5935,
@@ -1073,13 +1083,17 @@ typedef enum SpvCapability_ {
SpvCapabilityDotProductInput4x8BitPackedKHR = 6018,
SpvCapabilityDotProduct = 6019,
SpvCapabilityDotProductKHR = 6019,
+ SpvCapabilityRayCullMaskKHR = 6020,
SpvCapabilityBitInstructions = 6025,
+ SpvCapabilityGroupNonUniformRotateKHR = 6026,
SpvCapabilityAtomicFloat32AddEXT = 6033,
SpvCapabilityAtomicFloat64AddEXT = 6034,
SpvCapabilityLongConstantCompositeINTEL = 6089,
SpvCapabilityOptNoneINTEL = 6094,
SpvCapabilityAtomicFloat16AddEXT = 6095,
SpvCapabilityDebugInfoModuleINTEL = 6114,
+ SpvCapabilitySplitBarrierINTEL = 6141,
+ SpvCapabilityGroupUniformArithmeticKHR = 6400,
SpvCapabilityMax = 0x7fffffff,
} SpvCapability;
@@ -1535,6 +1549,7 @@ typedef enum SpvOp_ {
SpvOpSubgroupAllKHR = 4428,
SpvOpSubgroupAnyKHR = 4429,
SpvOpSubgroupAllEqualKHR = 4430,
+ SpvOpGroupNonUniformRotateKHR = 4431,
SpvOpSubgroupReadInvocationKHR = 4432,
SpvOpTraceRayKHR = 4445,
SpvOpExecuteCallableKHR = 4446,
@@ -1801,6 +1816,9 @@ typedef enum SpvOp_ {
SpvOpArbitraryFloatPowRINTEL = 5881,
SpvOpArbitraryFloatPowNINTEL = 5882,
SpvOpLoopControlINTEL = 5887,
+ SpvOpAliasDomainDeclINTEL = 5911,
+ SpvOpAliasScopeDeclINTEL = 5912,
+ SpvOpAliasScopeListDeclINTEL = 5913,
SpvOpFixedSqrtINTEL = 5923,
SpvOpFixedRecipINTEL = 5924,
SpvOpFixedRsqrtINTEL = 5925,
@@ -1839,10 +1857,23 @@ typedef enum SpvOp_ {
SpvOpTypeStructContinuedINTEL = 6090,
SpvOpConstantCompositeContinuedINTEL = 6091,
SpvOpSpecConstantCompositeContinuedINTEL = 6092,
+ SpvOpControlBarrierArriveINTEL = 6142,
+ SpvOpControlBarrierWaitINTEL = 6143,
+ SpvOpGroupIMulKHR = 6401,
+ SpvOpGroupFMulKHR = 6402,
+ SpvOpGroupBitwiseAndKHR = 6403,
+ SpvOpGroupBitwiseOrKHR = 6404,
+ SpvOpGroupBitwiseXorKHR = 6405,
+ SpvOpGroupLogicalAndKHR = 6406,
+ SpvOpGroupLogicalOrKHR = 6407,
+ SpvOpGroupLogicalXorKHR = 6408,
SpvOpMax = 0x7fffffff,
} SpvOp;
#ifdef SPV_ENABLE_UTILITY_CODE
+#ifndef __cplusplus
+#include <stdbool.h>
+#endif
inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultType) {
*hasResult = *hasResultType = false;
switch (opcode) {
@@ -2197,6 +2228,7 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpSubgroupAllKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupAnyKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupAllEqualKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupNonUniformRotateKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpSubgroupReadInvocationKHR: *hasResult = true; *hasResultType = true; break;
case SpvOpTraceRayKHR: *hasResult = false; *hasResultType = false; break;
case SpvOpExecuteCallableKHR: *hasResult = false; *hasResultType = false; break;
@@ -2452,6 +2484,9 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpArbitraryFloatPowRINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpArbitraryFloatPowNINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpLoopControlINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpAliasDomainDeclINTEL: *hasResult = true; *hasResultType = false; break;
+ case SpvOpAliasScopeDeclINTEL: *hasResult = true; *hasResultType = false; break;
+ case SpvOpAliasScopeListDeclINTEL: *hasResult = true; *hasResultType = false; break;
case SpvOpFixedSqrtINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpFixedRecipINTEL: *hasResult = true; *hasResultType = true; break;
case SpvOpFixedRsqrtINTEL: *hasResult = true; *hasResultType = true; break;
@@ -2490,9 +2525,18 @@ inline void SpvHasResultAndType(SpvOp opcode, bool *hasResult, bool *hasResultTy
case SpvOpTypeStructContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case SpvOpConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
case SpvOpSpecConstantCompositeContinuedINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpControlBarrierArriveINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpControlBarrierWaitINTEL: *hasResult = false; *hasResultType = false; break;
+ case SpvOpGroupIMulKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupFMulKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseAndKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseOrKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupBitwiseXorKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalAndKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalOrKHR: *hasResult = true; *hasResultType = true; break;
+ case SpvOpGroupLogicalXorKHR: *hasResult = true; *hasResultType = true; break;
}
}
#endif /* SPV_ENABLE_UTILITY_CODE */
#endif
-
diff --git a/thirdparty/spirv-reflect/patches/specialization-constants.patch b/thirdparty/spirv-reflect/patches/specialization-constants.patch
index 9bb5f97cd3..99815c9162 100644
--- a/thirdparty/spirv-reflect/patches/specialization-constants.patch
+++ b/thirdparty/spirv-reflect/patches/specialization-constants.patch
@@ -1,8 +1,8 @@
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
-index e9b11bf495..f181df5fa2 100644
+index cdcf3ca663..c174ae1900 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
-@@ -125,6 +125,9 @@ typedef struct SpvReflectPrvDecorations {
+@@ -126,6 +126,9 @@ typedef struct SpvReflectPrvDecorations {
SpvReflectPrvNumberDecoration location;
SpvReflectPrvNumberDecoration offset;
SpvReflectPrvNumberDecoration uav_counter_buffer;
@@ -12,7 +12,7 @@ index e9b11bf495..f181df5fa2 100644
SpvReflectPrvStringDecoration semantic;
uint32_t array_stride;
uint32_t matrix_stride;
-@@ -631,6 +634,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -639,6 +642,9 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
p_parser->nodes[i].decorations.offset.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.uav_counter_buffer.value = (uint32_t)INVALID_VALUE;
p_parser->nodes[i].decorations.built_in = (SpvBuiltIn)INVALID_VALUE;
@@ -22,7 +22,7 @@ index e9b11bf495..f181df5fa2 100644
}
// Mark source file id node
p_parser->source_file_id = (uint32_t)INVALID_VALUE;
-@@ -821,10 +827,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -829,10 +835,16 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
CHECKED_READU32(p_parser, p_node->word_offset + 2, p_node->result_id);
}
break;
@@ -41,7 +41,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvOpSpecConstantComposite:
case SpvOpSpecConstantOp: {
CHECKED_READU32(p_parser, p_node->word_offset + 1, p_node->result_type_id);
-@@ -856,7 +868,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
+@@ -864,7 +876,7 @@ static SpvReflectResult ParseNodes(SpvReflectPrvParser* p_parser)
CHECKED_READU32(p_parser, p_node->word_offset + 3, p_access_chain->base_id);
//
// SPIRV_ACCESS_CHAIN_INDEX_OFFSET (4) is the number of words up until the first index:
@@ -50,7 +50,7 @@ index e9b11bf495..f181df5fa2 100644
//
p_access_chain->index_count = (node_word_count - SPIRV_ACCESS_CHAIN_INDEX_OFFSET);
if (p_access_chain->index_count > 0) {
-@@ -1338,6 +1350,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
+@@ -1346,6 +1358,9 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
skip = true;
}
break;
@@ -60,7 +60,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvDecorationRelaxedPrecision:
case SpvDecorationBlock:
case SpvDecorationBufferBlock:
-@@ -1481,7 +1496,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
+@@ -1495,7 +1510,14 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
p_target_decorations->input_attachment_index.word_offset = word_offset;
}
break;
@@ -76,7 +76,7 @@ index e9b11bf495..f181df5fa2 100644
case SpvReflectDecorationHlslCounterBufferGOOGLE: {
uint32_t word_offset = p_node->word_offset + member_offset+ 3;
CHECKED_READU32(p_parser, word_offset, p_target_decorations->uav_counter_buffer.value);
-@@ -1789,6 +1811,13 @@ static SpvReflectResult ParseType(
+@@ -1803,6 +1825,13 @@ static SpvReflectResult ParseType(
p_type->type_flags |= SPV_REFLECT_TYPE_FLAG_EXTERNAL_ACCELERATION_STRUCTURE;
}
break;
@@ -90,7 +90,7 @@ index e9b11bf495..f181df5fa2 100644
}
if (result == SPV_REFLECT_RESULT_SUCCESS) {
-@@ -3269,6 +3298,69 @@ static SpvReflectResult ParseExecutionModes(
+@@ -3332,6 +3361,69 @@ static SpvReflectResult ParseExecutionModes(
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -160,7 +160,7 @@ index e9b11bf495..f181df5fa2 100644
static SpvReflectResult ParsePushConstantBlocks(
SpvReflectPrvParser* p_parser,
SpvReflectShaderModule* p_module)
-@@ -3650,6 +3742,12 @@ static SpvReflectResult CreateShaderModule(
+@@ -3717,6 +3809,12 @@ static SpvReflectResult CreateShaderModule(
result = ParsePushConstantBlocks(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
}
@@ -173,8 +173,8 @@ index e9b11bf495..f181df5fa2 100644
if (result == SPV_REFLECT_RESULT_SUCCESS) {
result = ParseEntryPoints(&parser, p_module);
SPV_REFLECT_ASSERT(result == SPV_REFLECT_RESULT_SUCCESS);
-@@ -3807,6 +3905,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
- SafeFree(p_entry->used_push_constants);
+@@ -3875,6 +3973,9 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
+ SafeFree(p_entry->execution_modes);
}
SafeFree(p_module->entry_points);
+// -- GODOT begin --
@@ -183,7 +183,7 @@ index e9b11bf495..f181df5fa2 100644
// Push constants
for (size_t i = 0; i < p_module->push_constant_block_count; ++i) {
-@@ -4077,6 +4178,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
+@@ -4145,6 +4246,38 @@ SpvReflectResult spvReflectEnumerateEntryPointInterfaceVariables(
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -223,10 +223,10 @@ index e9b11bf495..f181df5fa2 100644
const SpvReflectShaderModule* p_module,
uint32_t* p_count,
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
-index e9e4c40755..948533d3c0 100644
+index 02b81613a1..02850f8811 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
-@@ -323,6 +323,28 @@ typedef struct SpvReflectTypeDescription {
+@@ -329,6 +329,28 @@ typedef struct SpvReflectTypeDescription {
struct SpvReflectTypeDescription* members;
} SpvReflectTypeDescription;
@@ -255,7 +255,7 @@ index e9e4c40755..948533d3c0 100644
/*! @struct SpvReflectInterfaceVariable
-@@ -472,6 +494,10 @@ typedef struct SpvReflectShaderModule {
+@@ -483,6 +505,10 @@ typedef struct SpvReflectShaderModule {
SpvReflectInterfaceVariable* interface_variables; // Uses value(s) from first entry point
uint32_t push_constant_block_count; // Uses value(s) from first entry point
SpvReflectBlockVariable* push_constant_blocks; // Uses value(s) from first entry point
@@ -266,7 +266,7 @@ index e9e4c40755..948533d3c0 100644
struct Internal {
SpvReflectModuleFlags module_flags;
-@@ -744,6 +770,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
+@@ -755,6 +781,33 @@ SpvReflectResult spvReflectEnumerateInputVariables(
SpvReflectInterfaceVariable** pp_variables
);
diff --git a/thirdparty/spirv-reflect/spirv_reflect.c b/thirdparty/spirv-reflect/spirv_reflect.c
index f181df5fa2..c174ae1900 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.c
+++ b/thirdparty/spirv-reflect/spirv_reflect.c
@@ -119,6 +119,7 @@ typedef struct SpvReflectPrvDecorations {
bool is_noperspective;
bool is_flat;
bool is_non_writable;
+ bool is_non_readable;
SpvReflectPrvNumberDecoration set;
SpvReflectPrvNumberDecoration binding;
SpvReflectPrvNumberDecoration input_attachment_index;
@@ -306,7 +307,12 @@ static SpvReflectResult IntersectSortedUint32(
size_t* res_size
)
{
+ *pp_res = NULL;
*res_size = 0;
+ if (IsNull(p_arr0) || IsNull(p_arr1)) {
+ return SPV_REFLECT_RESULT_SUCCESS;
+ }
+
const uint32_t* arr0_end = p_arr0 + arr0_size;
const uint32_t* arr1_end = p_arr1 + arr1_size;
@@ -324,7 +330,6 @@ static SpvReflectResult IntersectSortedUint32(
}
}
- *pp_res = NULL;
if (*res_size > 0) {
*pp_res = (uint32_t*)calloc(*res_size, sizeof(**pp_res));
if (IsNull(*pp_res)) {
@@ -488,6 +493,9 @@ static SpvReflectDecorationFlags ApplyDecorations(const SpvReflectPrvDecorations
if (p_decoration_fields->is_non_writable) {
decorations |= SPV_REFLECT_DECORATION_NON_WRITABLE;
}
+ if (p_decoration_fields->is_non_readable) {
+ decorations |= SPV_REFLECT_DECORATION_NON_READABLE;
+ }
return decorations;
}
@@ -1364,6 +1372,7 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
case SpvDecorationNoPerspective:
case SpvDecorationFlat:
case SpvDecorationNonWritable:
+ case SpvDecorationNonReadable:
case SpvDecorationLocation:
case SpvDecorationBinding:
case SpvDecorationDescriptorSet:
@@ -1462,6 +1471,11 @@ static SpvReflectResult ParseDecorations(SpvReflectPrvParser* p_parser)
}
break;
+ case SpvDecorationNonReadable: {
+ p_target_decorations->is_non_readable = true;
+ }
+ break;
+
case SpvDecorationLocation: {
uint32_t word_offset = p_node->word_offset + member_offset + 3;
CHECKED_READU32(p_parser, word_offset, p_target_decorations->location.value);
@@ -1970,6 +1984,7 @@ static SpvReflectResult ParseDescriptorBindings(
p_descriptor->count = 1;
p_descriptor->uav_counter_id = p_node->decorations.uav_counter_buffer.value;
p_descriptor->type_description = p_type;
+ p_descriptor->decoration_flags = ApplyDecorations(&p_node->decorations);
// If this is in the StorageBuffer storage class, it's for sure a storage
// buffer descriptor. We need to handle this case earlier because in SPIR-V
@@ -3208,8 +3223,8 @@ static SpvReflectResult ParseExecutionModes(
// Read entry point id
uint32_t entry_point_id = 0;
CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);
-
- // Find entry point
+
+ // Find entry point
SpvReflectEntryPoint* p_entry_point = NULL;
for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
if (p_module->entry_points[entry_point_idx].id == entry_point_id) {
@@ -3221,7 +3236,7 @@ static SpvReflectResult ParseExecutionModes(
if (IsNull(p_entry_point)) {
return SPV_REFLECT_RESULT_ERROR_SPIRV_INVALID_ENTRY_POINT;
}
-
+
// Read execution mode
uint32_t execution_mode = (uint32_t)INVALID_VALUE;
CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);
@@ -3288,12 +3303,60 @@ static SpvReflectResult ParseExecutionModes(
case SpvExecutionModeLocalSizeId:
case SpvExecutionModeLocalSizeHintId:
case SpvExecutionModePostDepthCoverage:
+ case SpvExecutionModeDenormPreserve:
+ case SpvExecutionModeDenormFlushToZero:
+ case SpvExecutionModeSignedZeroInfNanPreserve:
+ case SpvExecutionModeRoundingModeRTE:
+ case SpvExecutionModeRoundingModeRTZ:
case SpvExecutionModeStencilRefReplacingEXT:
+ case SpvExecutionModeOutputLinesNV:
case SpvExecutionModeOutputPrimitivesNV:
case SpvExecutionModeOutputTrianglesNV:
break;
}
+ p_entry_point->execution_mode_count++;
+ }
+ uint32_t* indices = (uint32_t*)calloc(p_module->entry_point_count, sizeof(indices));
+ if (IsNull(indices)) {
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
}
+ for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
+ SpvReflectEntryPoint* p_entry_point = &p_module->entry_points[entry_point_idx];
+ p_entry_point->execution_modes =
+ (SpvExecutionMode*)calloc(p_entry_point->execution_mode_count, sizeof(*p_entry_point->execution_modes));
+ if (IsNull(p_entry_point->execution_modes)) {
+ SafeFree(indices);
+ return SPV_REFLECT_RESULT_ERROR_ALLOC_FAILED;
+ }
+ }
+
+ for (size_t node_idx = 0; node_idx < p_parser->node_count; ++node_idx) {
+ SpvReflectPrvNode* p_node = &(p_parser->nodes[node_idx]);
+ if (p_node->op != SpvOpExecutionMode) {
+ continue;
+ }
+
+ // Read entry point id
+ uint32_t entry_point_id = 0;
+ CHECKED_READU32(p_parser, p_node->word_offset + 1, entry_point_id);
+
+ // Find entry point
+ SpvReflectEntryPoint* p_entry_point = NULL;
+ uint32_t* idx = NULL;
+ for (size_t entry_point_idx = 0; entry_point_idx < p_module->entry_point_count; ++entry_point_idx) {
+ if (p_module->entry_points[entry_point_idx].id == entry_point_id) {
+ p_entry_point = &p_module->entry_points[entry_point_idx];
+ idx = &indices[entry_point_idx];
+ break;
+ }
+ }
+
+ // Read execution mode
+ uint32_t execution_mode = (uint32_t)INVALID_VALUE;
+ CHECKED_READU32(p_parser, p_node->word_offset + 2, execution_mode);
+ p_entry_point->execution_modes[(*idx)++] = (SpvExecutionMode)execution_mode;
+ }
+ SafeFree(indices);
}
return SPV_REFLECT_RESULT_SUCCESS;
}
@@ -3649,7 +3712,11 @@ static SpvReflectResult CreateShaderModule(
if (flags & SPV_REFLECT_MODULE_FLAG_NO_COPY) {
// Set internal size and pointer to args passed in
p_module->_internal->spirv_size = size;
+#if defined(__cplusplus)
+ p_module->_internal->spirv_code = const_cast<uint32_t*>(static_cast<const uint32_t*>(p_code)); // cast that const away
+#else
p_module->_internal->spirv_code = (void*)p_code; // cast that const away
+#endif
p_module->_internal->spirv_word_count = (uint32_t)(size / SPIRV_WORD_SIZE);
}
else {
@@ -3903,6 +3970,7 @@ void spvReflectDestroyShaderModule(SpvReflectShaderModule* p_module)
SafeFree(p_entry->interface_variables);
SafeFree(p_entry->used_uniforms);
SafeFree(p_entry->used_push_constants);
+ SafeFree(p_entry->execution_modes);
}
SafeFree(p_module->entry_points);
// -- GODOT begin --
@@ -5093,6 +5161,7 @@ const char* spvReflectSourceLanguage(SpvSourceLanguage source_lang)
case SpvSourceLanguageOpenCL_CPP : return "OpenCL_CPP";
case SpvSourceLanguageHLSL : return "HLSL";
case SpvSourceLanguageCPP_for_OpenCL : return "CPP_for_OpenCL";
+ case SpvSourceLanguageSYCL : return "SYCL";
case SpvSourceLanguageMax:
break;
}
diff --git a/thirdparty/spirv-reflect/spirv_reflect.h b/thirdparty/spirv-reflect/spirv_reflect.h
index 948533d3c0..02850f8811 100644
--- a/thirdparty/spirv-reflect/spirv_reflect.h
+++ b/thirdparty/spirv-reflect/spirv_reflect.h
@@ -30,7 +30,12 @@ VERSION HISTORY
#ifndef SPIRV_REFLECT_H
#define SPIRV_REFLECT_H
+#if defined(SPIRV_REFLECT_USE_SYSTEM_SPIRV_H)
+#include <spirv/unified1/spirv.h>
+#else
#include "./include/spirv/unified1/spirv.h"
+#endif
+
#include <stdint.h>
#include <string.h>
@@ -139,6 +144,7 @@ typedef enum SpvReflectDecorationFlagBits {
SPV_REFLECT_DECORATION_FLAT = 0x00000040,
SPV_REFLECT_DECORATION_NON_WRITABLE = 0x00000080,
SPV_REFLECT_DECORATION_RELAXED_PRECISION = 0x00000100,
+ SPV_REFLECT_DECORATION_NON_READABLE = 0x00000200,
} SpvReflectDecorationFlagBits;
typedef uint32_t SpvReflectDecorationFlags;
@@ -422,6 +428,8 @@ typedef struct SpvReflectDescriptorBinding {
uint32_t binding;
uint32_t set;
} word_offset;
+
+ SpvReflectDecorationFlags decoration_flags;
} SpvReflectDescriptorBinding;
/*! @struct SpvReflectDescriptorSet
@@ -458,6 +466,9 @@ typedef struct SpvReflectEntryPoint {
uint32_t used_push_constant_count;
uint32_t* used_push_constants;
+ uint32_t execution_mode_count;
+ SpvExecutionMode* execution_modes;
+
struct LocalSize {
uint32_t x;
uint32_t y;
diff --git a/thirdparty/thorvg/AUTHORS b/thirdparty/thorvg/AUTHORS
index ec06c49118..0f8ba2dd7d 100644
--- a/thirdparty/thorvg/AUTHORS
+++ b/thirdparty/thorvg/AUTHORS
@@ -1,4 +1,4 @@
-Hermet Park <chuneon.park@samsung.com>
+Hermet Park <hermetpark@gmail.com>
Prudhvi Raj Vasireddi <prudhvi.raj@samsung.com>
Junsu Choi <jsuya.choi@samsung.com>
Pranay Samanta <pranay.ks@samsung.com>
diff --git a/thirdparty/thorvg/LICENSE b/thirdparty/thorvg/LICENSE
index b096b0888e..2f0361a864 100644
--- a/thirdparty/thorvg/LICENSE
+++ b/thirdparty/thorvg/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2020 - 2021 notice for the ThorVG Project (see AUTHORS)
+Copyright (c) 2020 - 2022 notice for the ThorVG Project (see AUTHORS)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
diff --git a/thirdparty/thorvg/inc/config.h b/thirdparty/thorvg/inc/config.h
index 41e8f6dafa..879b70442b 100644
--- a/thirdparty/thorvg/inc/config.h
+++ b/thirdparty/thorvg/inc/config.h
@@ -13,5 +13,5 @@
#define THORVG_JPG_LOADER_SUPPORT 1
-#define THORVG_VERSION_STRING "0.7.1"
+#define THORVG_VERSION_STRING "0.8.1"
#endif
diff --git a/thirdparty/thorvg/inc/thorvg.h b/thirdparty/thorvg/inc/thorvg.h
index e542d36555..b08356d9d5 100644
--- a/thirdparty/thorvg/inc/thorvg.h
+++ b/thirdparty/thorvg/inc/thorvg.h
@@ -145,8 +145,9 @@ enum class TVG_EXPORT CompositeMethod
{
None = 0, ///< No composition is applied.
ClipPath, ///< The intersection of the source and the target is determined and only the resulting pixels from the source are rendered.
- AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which intersects with the target is visible.
- InvAlphaMask ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which is not covered by the target is visible.
+ AlphaMask, ///< The pixels of the source and the target are alpha blended. As a result, only the part of the source, which alpha intersects with the target is visible.
+ InvAlphaMask, ///< The pixels of the source and the complement to the target's pixels are alpha blended. As a result, only the part of the source which alpha is not covered by the target is visible.
+ LumaMask ///< @BETA_API The source pixels are converted to the grayscale (luma value) and alpha blended with the target. As a result, only the part of the source, which intersects with the target is visible.
};
/**
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
index e0ffc1fb97..47b0cb83f5 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwCommon.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -99,9 +99,9 @@ struct SwSize
struct SwOutline
{
SwPoint* pts; //the outline's points
- uint16_t ptsCnt; //number of points in the glyph
- uint16_t reservedPtsCnt;
- uint16_t* cntrs; //the contour end points
+ uint32_t ptsCnt; //number of points in the glyph
+ uint32_t reservedPtsCnt;
+ uint32_t* cntrs; //the contour end points
uint16_t cntrsCnt; //number of contours in glyph
uint16_t reservedCntrsCnt;
uint8_t* types; //curve type
@@ -235,6 +235,7 @@ struct SwImage
struct SwBlender
{
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+ uint32_t (*lumaValue)(uint32_t c);
};
struct SwCompositor;
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
index 0bf051c17f..bba6f26a0b 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwFill.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
index f9974d9847..c02e28b432 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwImage.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -46,7 +46,7 @@ static bool _genOutline(SwImage* image, const Matrix* transform, SwMpool* mpool,
if (outline->reservedCntrsCnt < 1) {
outline->reservedCntrsCnt = 1;
- outline->cntrs = static_cast<uint16_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint16_t)));
+ outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, outline->reservedCntrsCnt * sizeof(uint32_t)));
outline->closed = static_cast<bool*>(realloc(outline->closed, outline->reservedCntrsCnt * sizeof(bool)));
outline->closed[0] = true;
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
index 7a3529bd69..ced66ae35c 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMath.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -499,4 +499,4 @@ bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, S
renderRegion.max.y = (yMax + 63) >> 6;
}
return mathClipBBox(clipRegion, renderRegion);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
index a44be85bbb..d2962e6d8d 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwMemPool.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -153,4 +153,4 @@ bool mpoolTerm(SwMpool* mpool)
free(mpool);
return true;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
index 56bc2f77dc..810df8d435 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,6 +19,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
+
+#ifdef _WIN32
+ #include <malloc.h>
+#elif defined(__FreeBSD__)
+ #include <stdlib.h>
+#else
+ #include <alloca.h>
+#endif
+
#include "tvgMath.h"
#include "tvgRender.h"
#include "tvgSwCommon.h"
@@ -47,6 +56,18 @@ static inline uint32_t _ialpha(uint32_t c)
}
+static inline uint32_t _abgrLumaValue(uint32_t c)
+{
+ return ((((c&0xff)*54) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B
+}
+
+
+static inline uint32_t _argbLumaValue(uint32_t c)
+{
+ return ((((c&0xff)*19) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R
+}
+
+
static inline uint32_t _abgrJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
return (a << 24 | b << 16 | g << 8 | r);
@@ -139,7 +160,7 @@ static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
+ auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h; ++y) {
auto dst = &buffer[y * surface->stride];
@@ -173,6 +194,8 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color
return _rasterMaskedRect(surface, region, color, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterMaskedRect(surface, region, color, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterMaskedRect(surface, region, color, surface->blender.lumaValue);
}
} else {
if (opacity == 255) {
@@ -246,6 +269,8 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8
return _rasterMaskedRle(surface, rle, color, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterMaskedRle(surface, rle, color, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterMaskedRle(surface, rle, color, surface->blender.lumaValue);
}
} else {
if (opacity == 255) {
@@ -275,6 +300,8 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.lumaValue);
}
} else {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
@@ -494,12 +521,16 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
}
}
} else {
@@ -616,12 +647,16 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32
return _rasterDirectMaskedRleRGBAImage(surface, image, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.lumaValue);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.lumaValue);
}
}
} else {
@@ -643,6 +678,8 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterTexmapPolygon(surface, image, transform, &region, opacity, surface->blender.lumaValue);
}
} else {
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, nullptr);
@@ -832,12 +869,16 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue);
}
}
} else {
@@ -861,7 +902,7 @@ static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* imag
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
+ auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer;
@@ -888,7 +929,7 @@ static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
auto w2 = static_cast<uint32_t>(region.max.x - region.min.x);
auto sbuffer = image->data + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox);
- auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
+ auto cbuffer = surface->compositor->image.data + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer
for (uint32_t y = 0; y < h2; ++y) {
auto dst = buffer;
@@ -952,12 +993,16 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB
return _rasterDirectMaskedRGBAImage(surface, image, region, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.lumaValue);
}
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.lumaValue);
}
}
} else {
@@ -1062,6 +1107,8 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region,
return _rasterLinearGradientMaskedRect(surface, region, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
}
} else {
if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill);
@@ -1166,6 +1213,8 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c
return _rasterLinearGradientMaskedRle(surface, rle, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
}
} else {
if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill);
@@ -1253,6 +1302,8 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
return _rasterRadialGradientMaskedRect(surface, region, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.lumaValue);
}
} else {
if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill);
@@ -1356,6 +1407,8 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c
return _rasterRadialGradientMaskedRle(surface, rle, fill, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha);
+ } else if (surface->compositor->method == CompositeMethod::LumaMask) {
+ return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue);
}
} else {
if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill);
@@ -1385,8 +1438,10 @@ bool rasterCompositor(SwSurface* surface)
{
if (surface->cs == SwCanvas::ABGR8888 || surface->cs == SwCanvas::ABGR8888_STRAIGHT) {
surface->blender.join = _abgrJoin;
+ surface->blender.lumaValue = _abgrLumaValue;
} else if (surface->cs == SwCanvas::ARGB8888 || surface->cs == SwCanvas::ARGB8888_STRAIGHT) {
surface->blender.join = _argbJoin;
+ surface->blender.lumaValue = _argbLumaValue;
} else {
//What Color Space ???
return false;
@@ -1500,4 +1555,4 @@ bool rasterImage(SwSurface* surface, SwImage* image, const Matrix* transform, co
//TODO: case: _rasterGrayscaleImage()
//TODO: case: _rasterAlphaImage()
return _rasterRGBAImage(surface, image, transform, bbox, opacity);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
index 1d6552f3e9..7a129a3a80 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterAvx.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
index 6d60957eb9..de6b35fd64 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterC.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -61,4 +61,4 @@ static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& regi
}
}
return true;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
index c74a6b309c..a4b3cdaeb2 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterNeon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,8 +26,8 @@
static inline uint8x8_t ALPHA_BLEND(uint8x8_t c, uint8x8_t a)
{
- uint16x8_t t = vmull_u8(c, a);
- return vshrn_n_u16(t, 8);
+ uint16x8_t t = vmull_u8(c, a);
+ return vshrn_n_u16(t, 8);
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
index 2cf9fb4e93..abb57d7c45 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmap.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -599,4 +599,4 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
_rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod, aaSpans);
return _apply(surface, aaSpans);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
index e96307c874..f31ea1eb97 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRasterTexmapInternal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
index c75e73760e..c3872f3207 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -19,11 +19,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
-#include <math.h>
+#include "tvgMath.h"
#include "tvgSwCommon.h"
#include "tvgTaskScheduler.h"
#include "tvgSwRenderer.h"
-#include "tvgMath.h"
/************************************************************************/
/* Internal Class Implementation */
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
index 3f883ac409..574d9d488f 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRenderer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
index b41e48b7ca..63e7fc9447 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRle.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1040,4 +1040,4 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip)
_replaceClipSpan(rle, spans, spansEnd - spans);
TVGLOG("SW_ENGINE", "Using ClipRect!");
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
index 7b49c232b1..e5b540bcc3 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwShape.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -64,7 +64,7 @@ static bool _growOutlineContour(SwOutline& outline, uint32_t n)
{
if (outline.reservedCntrsCnt >= outline.cntrsCnt + n) return false;
outline.reservedCntrsCnt = outline.cntrsCnt + n;
- outline.cntrs = static_cast<uint16_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint16_t)));
+ outline.cntrs = static_cast<uint32_t*>(realloc(outline.cntrs, outline.reservedCntrsCnt * sizeof(uint32_t)));
return true;
}
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
index c0cfc1be26..be4392740e 100644
--- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
+++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwStroke.cpp
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+/*
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -780,7 +780,7 @@ static void _exportBorderOutline(const SwStroke& stroke, SwOutline* outline, uin
auto src = border->tags;
auto tags = outline->types + outline->ptsCnt;
auto cntrs = outline->cntrs + outline->cntrsCnt;
- uint16_t idx = outline->ptsCnt;
+ auto idx = outline->ptsCnt;
while (cnt > 0) {
@@ -921,7 +921,7 @@ SwOutline* strokeExportOutline(SwStroke* stroke, SwMpool* mpool, unsigned tid)
outline->reservedPtsCnt = ptsCnt;
}
if (outline->reservedCntrsCnt < cntrsCnt) {
- outline->cntrs = static_cast<uint16_t*>(realloc(outline->cntrs, sizeof(uint16_t) * cntrsCnt));
+ outline->cntrs = static_cast<uint32_t*>(realloc(outline->cntrs, sizeof(uint32_t) * cntrsCnt));
outline->reservedCntrsCnt = cntrsCnt;
}
diff --git a/thirdparty/thorvg/src/lib/tvgAccessor.cpp b/thirdparty/thorvg/src/lib/tvgAccessor.cpp
index 085c8a3cbc..092c8b0731 100644
--- a/thirdparty/thorvg/src/lib/tvgAccessor.cpp
+++ b/thirdparty/thorvg/src/lib/tvgAccessor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -81,4 +81,4 @@ Accessor::Accessor()
unique_ptr<Accessor> Accessor::gen() noexcept
{
return unique_ptr<Accessor>(new Accessor);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgArray.h b/thirdparty/thorvg/src/lib/tvgArray.h
index d04e68e73c..04ddbaee2b 100644
--- a/thirdparty/thorvg/src/lib/tvgArray.h
+++ b/thirdparty/thorvg/src/lib/tvgArray.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgBezier.cpp b/thirdparty/thorvg/src/lib/tvgBezier.cpp
index 2290afa728..95e2055943 100644
--- a/thirdparty/thorvg/src/lib/tvgBezier.cpp
+++ b/thirdparty/thorvg/src/lib/tvgBezier.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgBezier.h b/thirdparty/thorvg/src/lib/tvgBezier.h
index 866e39148e..7d7c84e34e 100644
--- a/thirdparty/thorvg/src/lib/tvgBezier.h
+++ b/thirdparty/thorvg/src/lib/tvgBezier.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgBinaryDesc.h b/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
index 30ba2d5a29..f139def470 100644
--- a/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
+++ b/thirdparty/thorvg/src/lib/tvgBinaryDesc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgCanvas.cpp b/thirdparty/thorvg/src/lib/tvgCanvas.cpp
index bb42441c62..e8529e47c2 100644
--- a/thirdparty/thorvg/src/lib/tvgCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgCanvasImpl.h b/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
index 848c03aaed..0adec8fa52 100644
--- a/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgCanvasImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgCommon.h b/thirdparty/thorvg/src/lib/tvgCommon.h
index b1c586188c..1d66f2e1a2 100644
--- a/thirdparty/thorvg/src/lib/tvgCommon.h
+++ b/thirdparty/thorvg/src/lib/tvgCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgFill.cpp b/thirdparty/thorvg/src/lib/tvgFill.cpp
index 4bfb93c102..eecf239cee 100644
--- a/thirdparty/thorvg/src/lib/tvgFill.cpp
+++ b/thirdparty/thorvg/src/lib/tvgFill.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -112,4 +112,4 @@ Fill* Fill::duplicate() const noexcept
uint32_t Fill::identifier() const noexcept
{
return pImpl->id;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgFill.h b/thirdparty/thorvg/src/lib/tvgFill.h
index 912091f8cb..fff2475c4f 100644
--- a/thirdparty/thorvg/src/lib/tvgFill.h
+++ b/thirdparty/thorvg/src/lib/tvgFill.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp b/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
index 3a88b6d799..56feb69541 100644
--- a/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgGlCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgInitializer.cpp b/thirdparty/thorvg/src/lib/tvgInitializer.cpp
index 83ec50be95..42997c3493 100644
--- a/thirdparty/thorvg/src/lib/tvgInitializer.cpp
+++ b/thirdparty/thorvg/src/lib/tvgInitializer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h b/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
index 10b55a536d..8e566acb72 100644
--- a/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
+++ b/thirdparty/thorvg/src/lib/tvgIteratorAccessor.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp b/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
index 6ec7ddab20..df34af3aa1 100644
--- a/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLinearGradient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLoadModule.h b/thirdparty/thorvg/src/lib/tvgLoadModule.h
index 0c34ecbf6a..bfcc165f31 100644
--- a/thirdparty/thorvg/src/lib/tvgLoadModule.h
+++ b/thirdparty/thorvg/src/lib/tvgLoadModule.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLoader.cpp b/thirdparty/thorvg/src/lib/tvgLoader.cpp
index fb93e0faec..991c260159 100644
--- a/thirdparty/thorvg/src/lib/tvgLoader.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLoader.h b/thirdparty/thorvg/src/lib/tvgLoader.h
index 8ba3c139fa..ab32f89a2f 100644
--- a/thirdparty/thorvg/src/lib/tvgLoader.h
+++ b/thirdparty/thorvg/src/lib/tvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLzw.cpp b/thirdparty/thorvg/src/lib/tvgLzw.cpp
index 0049c89962..1aaf37831a 100644
--- a/thirdparty/thorvg/src/lib/tvgLzw.cpp
+++ b/thirdparty/thorvg/src/lib/tvgLzw.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgLzw.h b/thirdparty/thorvg/src/lib/tvgLzw.h
index 3fdb439a02..8e165bdb34 100644
--- a/thirdparty/thorvg/src/lib/tvgLzw.h
+++ b/thirdparty/thorvg/src/lib/tvgLzw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +22,12 @@
#ifndef _TVG_LZW_H_
#define _TVG_LZW_H_
+#include <cstdint>
+
namespace tvg
{
uint8_t* lzwEncode(const uint8_t* uncompressed, uint32_t uncompressedSizeBytes, uint32_t* compressedSizeBytes, uint32_t* compressedSizeBits);
uint8_t* lzwDecode(const uint8_t* compressed, uint32_t compressedSizeBytes, uint32_t compressedSizeBits, uint32_t uncompressedSizeBytes);
}
-#endif //_TVG_LZW_H \ No newline at end of file
+#endif //_TVG_LZW_H
diff --git a/thirdparty/thorvg/src/lib/tvgMath.h b/thirdparty/thorvg/src/lib/tvgMath.h
index 423fb6eb1b..6120216d74 100644
--- a/thirdparty/thorvg/src/lib/tvgMath.h
+++ b/thirdparty/thorvg/src/lib/tvgMath.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgPaint.cpp b/thirdparty/thorvg/src/lib/tvgPaint.cpp
index 30e82fbc60..d0e908ddf2 100644
--- a/thirdparty/thorvg/src/lib/tvgPaint.cpp
+++ b/thirdparty/thorvg/src/lib/tvgPaint.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -79,8 +79,8 @@ static bool _compFastTrack(Paint* cmpTarget, const RenderTransform* pTransform,
viewport.x = static_cast<int32_t>(v1.x);
viewport.y = static_cast<int32_t>(v1.y);
- viewport.w = static_cast<int32_t>(v2.x - v1.x + 0.5f);
- viewport.h = static_cast<int32_t>(v2.y - v1.y + 0.5f);
+ viewport.w = static_cast<int32_t>(ceil(v2.x - viewport.x));
+ viewport.h = static_cast<int32_t>(ceil(v2.y - viewport.y));
if (viewport.w < 0) viewport.w = 0;
if (viewport.h < 0) viewport.h = 0;
@@ -404,4 +404,4 @@ uint8_t Paint::opacity() const noexcept
uint32_t Paint::identifier() const noexcept
{
return pImpl->id;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgPaint.h b/thirdparty/thorvg/src/lib/tvgPaint.h
index 4003bdbeac..c170559a37 100644
--- a/thirdparty/thorvg/src/lib/tvgPaint.h
+++ b/thirdparty/thorvg/src/lib/tvgPaint.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgPicture.cpp b/thirdparty/thorvg/src/lib/tvgPicture.cpp
index 1d9776363c..1e04e25435 100644
--- a/thirdparty/thorvg/src/lib/tvgPicture.cpp
+++ b/thirdparty/thorvg/src/lib/tvgPicture.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -118,4 +118,4 @@ const uint32_t* Picture::data(uint32_t* w, uint32_t* h) const noexcept
}
if (pImpl->surface) return pImpl->surface->buffer;
else return nullptr;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgPictureImpl.h b/thirdparty/thorvg/src/lib/tvgPictureImpl.h
index 00e8aa6dd9..b2e097d400 100644
--- a/thirdparty/thorvg/src/lib/tvgPictureImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgPictureImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp b/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
index 42a83461e3..7f4e1d7e17 100644
--- a/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
+++ b/thirdparty/thorvg/src/lib/tvgRadialGradient.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -94,4 +94,4 @@ unique_ptr<RadialGradient> RadialGradient::gen() noexcept
uint32_t RadialGradient::identifier() noexcept
{
return TVG_CLASS_ID_RADIAL;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgRender.cpp b/thirdparty/thorvg/src/lib/tvgRender.cpp
index a48075dd04..90f0917e6b 100644
--- a/thirdparty/thorvg/src/lib/tvgRender.cpp
+++ b/thirdparty/thorvg/src/lib/tvgRender.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -70,4 +70,4 @@ RenderTransform::RenderTransform()
RenderTransform::RenderTransform(const RenderTransform* lhs, const RenderTransform* rhs)
{
m = mathMultiply(&lhs->m, &rhs->m);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgRender.h b/thirdparty/thorvg/src/lib/tvgRender.h
index f927947aa6..ed66f393da 100644
--- a/thirdparty/thorvg/src/lib/tvgRender.h
+++ b/thirdparty/thorvg/src/lib/tvgRender.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgSaveModule.h b/thirdparty/thorvg/src/lib/tvgSaveModule.h
index 2a0f427f11..3531662fdd 100644
--- a/thirdparty/thorvg/src/lib/tvgSaveModule.h
+++ b/thirdparty/thorvg/src/lib/tvgSaveModule.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgSaver.cpp b/thirdparty/thorvg/src/lib/tvgSaver.cpp
index 1a3e8614a6..e71953700c 100644
--- a/thirdparty/thorvg/src/lib/tvgSaver.cpp
+++ b/thirdparty/thorvg/src/lib/tvgSaver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgScene.cpp b/thirdparty/thorvg/src/lib/tvgScene.cpp
index 4b2f77dde9..0beec47b38 100644
--- a/thirdparty/thorvg/src/lib/tvgScene.cpp
+++ b/thirdparty/thorvg/src/lib/tvgScene.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -73,4 +73,4 @@ Result Scene::clear(bool free) noexcept
pImpl->clear(free);
return Result::Success;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgSceneImpl.h b/thirdparty/thorvg/src/lib/tvgSceneImpl.h
index de94a66e2f..6a7614c667 100644
--- a/thirdparty/thorvg/src/lib/tvgSceneImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgSceneImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgShape.cpp b/thirdparty/thorvg/src/lib/tvgShape.cpp
index 8db5635932..e57f2eafb2 100644
--- a/thirdparty/thorvg/src/lib/tvgShape.cpp
+++ b/thirdparty/thorvg/src/lib/tvgShape.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -424,4 +424,4 @@ Result Shape::fill(FillRule r) noexcept
FillRule Shape::fillRule() const noexcept
{
return pImpl->rule;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgShapeImpl.h b/thirdparty/thorvg/src/lib/tvgShapeImpl.h
index dcf4e6e954..738b21ed70 100644
--- a/thirdparty/thorvg/src/lib/tvgShapeImpl.h
+++ b/thirdparty/thorvg/src/lib/tvgShapeImpl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp b/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
index f7a03b819c..b5cae424f7 100644
--- a/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
+++ b/thirdparty/thorvg/src/lib/tvgSwCanvas.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -102,4 +102,4 @@ unique_ptr<SwCanvas> SwCanvas::gen() noexcept
return unique_ptr<SwCanvas>(new SwCanvas);
#endif
return nullptr;
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp b/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
index 780127b87b..8c07dc3859 100644
--- a/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
+++ b/thirdparty/thorvg/src/lib/tvgTaskScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/lib/tvgTaskScheduler.h b/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
index f30bdf9a8f..163e387f29 100644
--- a/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
+++ b/thirdparty/thorvg/src/lib/tvgTaskScheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp
index 6f9416b69c..522c3c71a6 100644
--- a/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.h b/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.h
index 7d35e57d72..3f82af8003 100644
--- a/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.h
+++ b/thirdparty/thorvg/src/loaders/external_jpg/tvgJpgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
index c3d281482a..05db65cb23 100644
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -93,7 +93,10 @@ bool PngLoader::read()
png_image_free(image);
return false;
}
- if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) return false;
+ if (!png_image_finish_read(image, NULL, buffer, 0, NULL)) {
+ free(buffer);
+ return false;
+ }
content = reinterpret_cast<uint32_t*>(buffer);
_premultiply(reinterpret_cast<uint32_t*>(buffer), image->width, image->height);
diff --git a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
index b42537c73f..8beff0a3b3 100644
--- a/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
+++ b/thirdparty/thorvg/src/loaders/external_png/tvgPngLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
index f27881da42..ffdef3004c 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -134,4 +134,4 @@ void JpgLoader::run(unsigned tid)
image = nullptr;
}
image = jpgdDecompress(decoder);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
index 39732dbc3a..d6b886cb29 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
index 4ccc5788d5..dacd45ed03 100644
--- a/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
+++ b/thirdparty/thorvg/src/loaders/jpg/tvgJpgd.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -382,8 +382,8 @@ struct Row
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- const int tmp0 = (ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
- const int tmp1 = (ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
+ const int tmp0 = static_cast<unsigned int>(ACCESS_COL(0) + ACCESS_COL(4)) << CONST_BITS;
+ const int tmp1 = static_cast<unsigned int>(ACCESS_COL(0) - ACCESS_COL(4)) << CONST_BITS;
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
@@ -461,8 +461,8 @@ struct Col
const int tmp2 = z1 + MULTIPLY(z3, - FIX_1_847759065);
const int tmp3 = z1 + MULTIPLY(z2, FIX_0_765366865);
- const int tmp0 = (ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
- const int tmp1 = (ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
+ const int tmp0 = static_cast<unsigned int>(ACCESS_ROW(0) + ACCESS_ROW(4)) << CONST_BITS;
+ const int tmp1 = static_cast<unsigned int>(ACCESS_ROW(0) - ACCESS_ROW(4)) << CONST_BITS;
const int tmp10 = tmp0 + tmp3, tmp13 = tmp0 - tmp3, tmp11 = tmp1 + tmp2, tmp12 = tmp1 - tmp2;
@@ -2557,7 +2557,7 @@ void jpeg_decoder::decode_block_dc_first(jpeg_decoder *pD, int component_id, int
s = JPGD_HUFF_EXTEND(r, s);
}
pD->m_last_dc_val[component_id] = (s += pD->m_last_dc_val[component_id]);
- p[0] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
+ p[0] = static_cast<jpgd_block_t>(static_cast<unsigned int>(s) << pD->m_successive_low);
}
@@ -2588,7 +2588,7 @@ void jpeg_decoder::decode_block_ac_first(jpeg_decoder *pD, int component_id, int
if ((k += r) > 63) pD->stop_decoding(JPGD_DECODE_ERROR);
r = pD->get_bits_no_markers(s);
s = JPGD_HUFF_EXTEND(r, s);
- p[g_ZAG[k]] = static_cast<jpgd_block_t>(s << pD->m_successive_low);
+ p[g_ZAG[k]] = static_cast<jpgd_block_t>(static_cast<unsigned int>(s) << pD->m_successive_low);
} else {
if (r == 15) {
if ((k += 15) > 63) pD->stop_decoding(JPGD_DECODE_ERROR);
@@ -2607,7 +2607,7 @@ void jpeg_decoder::decode_block_ac_refine(jpeg_decoder *pD, int component_id, in
{
int s, k, r;
int p1 = 1 << pD->m_successive_low;
- int m1 = (-1) << pD->m_successive_low;
+ int m1 = static_cast<unsigned int>(-1) << pD->m_successive_low;
jpgd_block_t *p = pD->coeff_buf_getp(pD->m_ac_coeffs[component_id], block_x, block_y);
JPGD_ASSERT(pD->m_spectral_end <= 63);
diff --git a/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp b/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp
index f2dfa02875..eaed025c54 100644
--- a/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp
+++ b/thirdparty/thorvg/src/loaders/png/tvgLodePng.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -2644,4 +2644,4 @@ void lodepng_state_cleanup(LodePNGState* state)
{
lodepng_color_mode_cleanup(&state->info_raw);
lodepng_info_cleanup(&state->info_png);
-} \ No newline at end of file
+}
diff --git a/thirdparty/thorvg/src/loaders/png/tvgLodePng.h b/thirdparty/thorvg/src/loaders/png/tvgLodePng.h
index 02e1feeec5..0cdac7cbea 100644
--- a/thirdparty/thorvg/src/loaders/png/tvgLodePng.h
+++ b/thirdparty/thorvg/src/loaders/png/tvgLodePng.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -171,4 +171,4 @@ void lodepng_state_cleanup(LodePNGState* state);
unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, LodePNGState* state, const unsigned char* in, size_t insize);
unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, const unsigned char* in, size_t insize);
-#endif //_TVG_LODEPNG_H_ \ No newline at end of file
+#endif //_TVG_LODEPNG_H_
diff --git a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp
index 3cc08e902b..3e293176b7 100644
--- a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h
index 34dbeed012..8f07f6418f 100644
--- a/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h
+++ b/thirdparty/thorvg/src/loaders/png/tvgPngLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
index d7d425b119..2da399d8c3 100644
--- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
index 20fa332981..e4f3423b41 100644
--- a/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
+++ b/thirdparty/thorvg/src/loaders/raw/tvgRawLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
new file mode 100644
index 0000000000..8f46b62ce9
--- /dev/null
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "tvgSvgCssStyle.h"
+
+#include <cstring>
+
+/************************************************************************/
+/* Internal Class Implementation */
+/************************************************************************/
+
+static void _copyStyle(SvgStyleProperty* to, const SvgStyleProperty* from)
+{
+ if (from == nullptr) return;
+ //Copy the properties of 'from' only if they were explicitly set (not the default ones).
+ if (from->curColorSet && !((int)to->flags & (int)SvgStyleFlags::Color)) {
+ to->color = from->color;
+ to->curColorSet = true;
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Color);
+ }
+ //Fill
+ if (((int)from->fill.flags & (int)SvgFillFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Fill)) {
+ to->fill.paint.color = from->fill.paint.color;
+ to->fill.paint.none = from->fill.paint.none;
+ to->fill.paint.curColor = from->fill.paint.curColor;
+ if (from->fill.paint.url) to->fill.paint.url = strdup(from->fill.paint.url);
+ to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Paint);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Fill);
+ }
+ if (((int)from->fill.flags & (int)SvgFillFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::FillOpacity)) {
+ to->fill.opacity = from->fill.opacity;
+ to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::Opacity);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillOpacity);
+ }
+ if (((int)from->fill.flags & (int)SvgFillFlags::FillRule) && !((int)to->flags & (int)SvgStyleFlags::FillRule)) {
+ to->fill.fillRule = from->fill.fillRule;
+ to->fill.flags = (SvgFillFlags)((int)to->fill.flags | (int)SvgFillFlags::FillRule);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::FillRule);
+ }
+ //Stroke
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Paint) && !((int)to->flags & (int)SvgStyleFlags::Stroke)) {
+ to->stroke.paint.color = from->stroke.paint.color;
+ to->stroke.paint.none = from->stroke.paint.none;
+ to->stroke.paint.curColor = from->stroke.paint.curColor;
+ if (from->stroke.paint.url) to->stroke.paint.url = strdup(from->stroke.paint.url);
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Paint);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Stroke);
+ }
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Opacity) && !((int)to->flags & (int)SvgStyleFlags::StrokeOpacity)) {
+ to->stroke.opacity = from->stroke.opacity;
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Opacity);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeOpacity);
+ }
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Width) && !((int)to->flags & (int)SvgStyleFlags::StrokeWidth)) {
+ to->stroke.width = from->stroke.width;
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Width);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeWidth);
+ }
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Dash) && !((int)to->flags & (int)SvgStyleFlags::StrokeDashArray)) {
+ if (from->stroke.dash.array.count > 0) {
+ to->stroke.dash.array.clear();
+ to->stroke.dash.array.reserve(from->stroke.dash.array.count);
+ for (uint32_t i = 0; i < from->stroke.dash.array.count; ++i) {
+ to->stroke.dash.array.push(from->stroke.dash.array.data[i]);
+ }
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Dash);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeDashArray);
+ }
+ }
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Cap) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineCap)) {
+ to->stroke.cap = from->stroke.cap;
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Cap);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineCap);
+ }
+ if (((int)from->stroke.flags & (int)SvgStrokeFlags::Join) && !((int)to->flags & (int)SvgStyleFlags::StrokeLineJoin)) {
+ to->stroke.join = from->stroke.join;
+ to->stroke.flags = (SvgStrokeFlags)((int)to->stroke.flags | (int)SvgStrokeFlags::Join);
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::StrokeLineJoin);
+ }
+ //Opacity
+ //TODO: it can be set to be 255 and shouldn't be changed by attribute 'opacity'
+ if (from->opacity < 255 && !((int)to->flags & (int)SvgStyleFlags::Opacity)) {
+ to->opacity = from->opacity;
+ to->flags = (SvgStyleFlags)((int)to->flags | (int)SvgStyleFlags::Opacity);
+ }
+}
+
+
+/************************************************************************/
+/* External Class Implementation */
+/************************************************************************/
+
+void cssCopyStyleAttr(SvgNode* to, const SvgNode* from)
+{
+ //Copy matrix attribute
+ if (from->transform && !((int)to->style->flags & (int)SvgStyleFlags::Transform)) {
+ to->transform = (Matrix*)malloc(sizeof(Matrix));
+ if (to->transform) {
+ *to->transform = *from->transform;
+ to->style->flags = (SvgStyleFlags)((int)to->style->flags | (int)SvgStyleFlags::Transform);
+ }
+ }
+ //Copy style attribute
+ _copyStyle(to->style, from->style);
+
+ if (from->style->clipPath.url) to->style->clipPath.url = strdup(from->style->clipPath.url);
+ if (from->style->mask.url) to->style->mask.url = strdup(from->style->mask.url);
+}
+
+
+SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type)
+{
+ if (!style) return nullptr;
+
+ auto child = style->child.data;
+ for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
+ if ((*child)->type == type) {
+ if ((!title && !(*child)->id) || (title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
+ }
+ }
+ return nullptr;
+}
+
+
+SvgNode* cssFindStyleNode(const SvgNode* style, const char* title)
+{
+ if (!style) return nullptr;
+
+ auto child = style->child.data;
+ for (uint32_t i = 0; i < style->child.count; ++i, ++child) {
+ if ((*child)->type == SvgNodeType::CssStyle) {
+ if ((title && (*child)->id && !strcmp((*child)->id, title))) return (*child);
+ }
+ }
+ return nullptr;
+}
+
+
+void cssUpdateStyle(SvgNode* doc, SvgNode* style)
+{
+ if (doc->child.count > 0) {
+ auto child = doc->child.data;
+ for (uint32_t i = 0; i < doc->child.count; ++i, ++child) {
+ if (auto cssNode = cssFindStyleNode(style, nullptr, (*child)->type)) {
+ cssCopyStyleAttr(*child, cssNode);
+ }
+ if (auto cssNode = cssFindStyleNode(style, nullptr)) {
+ cssCopyStyleAttr(*child, cssNode);
+ }
+ cssUpdateStyle(*child, style);
+ }
+ }
+}
+
+
+void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style)
+{
+ for (uint32_t i = 0; i < postponeds.count; ++i) {
+ auto nodeIdPair = postponeds.data[i];
+
+ //css styling: tag.name has higher priority than .name
+ if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id, nodeIdPair.node->type)) {
+ cssCopyStyleAttr(nodeIdPair.node, cssNode);
+ }
+ if (auto cssNode = cssFindStyleNode(style, nodeIdPair.id)) {
+ cssCopyStyleAttr(nodeIdPair.node, cssNode);
+ }
+ }
+}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h
new file mode 100644
index 0000000000..66477c1a32
--- /dev/null
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgCssStyle.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _TVG_SVG_CSS_STYLE_H_
+#define _TVG_SVG_CSS_STYLE_H_
+
+#include "tvgSvgLoaderCommon.h"
+
+void cssCopyStyleAttr(SvgNode* to, const SvgNode* from);
+SvgNode* cssFindStyleNode(const SvgNode* style, const char* title, SvgNodeType type);
+SvgNode* cssFindStyleNode(const SvgNode* style, const char* title);
+void cssUpdateStyle(SvgNode* doc, SvgNode* style);
+void cssApplyStyleToPostponeds(Array<SvgNodeIdPair>& postponeds, SvgNode* style);
+
+#endif //_TVG_SVG_CSS_STYLE_H_
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
index 08b3308165..42bfd4de70 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -60,6 +60,8 @@
#include "tvgSvgLoader.h"
#include "tvgSvgSceneBuilder.h"
#include "tvgSvgUtil.h"
+#include "tvgSvgCssStyle.h"
+#include "tvgMath.h"
/************************************************************************/
/* Internal Class Implementation */
@@ -75,11 +77,10 @@
#define PX_PER_MM 3.779528f //1 in = 25.4 mm -> PX_PER_IN/25.4
#define PX_PER_CM 37.79528f //1 in = 2.54 cm -> PX_PER_IN/2.54
-
-typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength);
+typedef bool (*parseAttributes)(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
+typedef SvgNode* (*FactoryMethod)(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func);
typedef SvgStyleGradient* (*GradientFactoryMethod)(SvgLoaderData* loader, const char* buf, unsigned bufLength);
-
static char* _skipSpace(const char* str, const char* end)
{
while (((end && str < end) || (!end && *str != '\0')) && isspace(*str)) {
@@ -200,6 +201,14 @@ static int _toOpacity(const char* str)
}
+static SvgMaskType _toMaskType(const char* str)
+{
+ if (!strcmp(str, "Alpha")) return SvgMaskType::Alpha;
+
+ return SvgMaskType::Luminance;
+}
+
+
#define _PARSE_TAG(Type, Name, Name1, Tags_Array, Default) \
static Type _to##Name1(const char* str) \
{ \
@@ -328,7 +337,10 @@ static unsigned char _parserColor(const char* value, char** end)
r = svgUtilStrtof(value, end);
*end = _skipSpace(*end, nullptr);
- if (**end == '%') r = 255 * r / 100;
+ if (**end == '%') {
+ r = 255 * r / 100;
+ (*end)++;
+ }
*end = _skipSpace(*end, nullptr);
if (r < 0 || r > 255) {
@@ -726,6 +738,12 @@ error:
}
+static void _postpone(Array<SvgNodeIdPair>& nodes, SvgNode *node, char* id)
+{
+ nodes.push({node, id});
+}
+
+
/*
// TODO - remove?
static constexpr struct
@@ -786,14 +804,12 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "preserveAspectRatio")) {
if (!strcmp(value, "none")) doc->preserveAspect = false;
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
- }
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
#ifdef THORVG_LOG_ENABLED
- else if ((!strcmp(key, "x") || !strcmp(key, "y")) && fabsf(svgUtilStrtof(value, nullptr)) > FLT_EPSILON) {
+ } else if ((!strcmp(key, "x") || !strcmp(key, "y")) && fabsf(svgUtilStrtof(value, nullptr)) > FLT_EPSILON) {
TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value);
- }
#endif
- else {
+ } else {
return _parseStyleAttr(loader, key, value, false);
}
return true;
@@ -922,6 +938,12 @@ static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, con
}
+static void _handleMaskTypeAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
+{
+ node->node.mask.type = _toMaskType(value);
+}
+
+
static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value)
{
//TODO : The display attribute can have various values as well as "none".
@@ -933,6 +955,29 @@ static void _handleDisplayAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node,
}
+static void _handleCssClassAttr(SvgLoaderData* loader, SvgNode* node, const char* value)
+{
+ auto cssClass = &node->style->cssClass;
+
+ if (*cssClass && value) free(*cssClass);
+ *cssClass = _copyId(value);
+
+ bool cssClassFound = false;
+
+ //css styling: tag.name has higher priority than .name
+ if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass, node->type)) {
+ cssClassFound = true;
+ cssCopyStyleAttr(node, cssNode);
+ }
+ if (auto cssNode = cssFindStyleNode(loader->cssStyle, *cssClass)) {
+ cssClassFound = true;
+ cssCopyStyleAttr(node, cssNode);
+ }
+
+ if (!cssClassFound) _postpone(loader->nodesToStyle, node, *cssClass);
+}
+
+
typedef void (*styleMethod)(SvgLoaderData* loader, SvgNode* node, const char* value);
#define STYLE_DEF(Name, Name1, Flag) { #Name, sizeof(#Name), _handle##Name1##Attr, Flag }
@@ -959,6 +1004,7 @@ static constexpr struct
STYLE_DEF(transform, Transform, SvgStyleFlags::Transform),
STYLE_DEF(clip-path, ClipPath, SvgStyleFlags::ClipPath),
STYLE_DEF(mask, Mask, SvgStyleFlags::Mask),
+ STYLE_DEF(mask-type, MaskType, SvgStyleFlags::MaskType),
STYLE_DEF(display, Display, SvgStyleFlags::Display)
};
@@ -1006,12 +1052,14 @@ static bool _attrParseGNode(void* data, const char* key, const char* value)
SvgNode* node = loader->svgParse->node;
if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1030,17 +1078,19 @@ static bool _attrParseClipPathNode(void* data, const char* key, const char* valu
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node;
- SvgCompositeNode* comp = &(node->node.comp);
+ SvgClipNode* clip = &(node->node.clip);
if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "clipPathUnits")) {
- if (!strcmp(value, "objectBoundingBox")) comp->userSpace = false;
+ if (!strcmp(value, "objectBoundingBox")) clip->userSpace = false;
} else {
return _parseStyleAttr(loader, key, value, false);
}
@@ -1052,17 +1102,21 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
SvgNode* node = loader->svgParse->node;
- SvgCompositeNode* comp = &(node->node.comp);
+ SvgMaskNode* mask = &(node->node.mask);
if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "transform")) {
node->transform = _parseTransformationMatrix(value);
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "maskContentUnits")) {
- if (!strcmp(value, "objectBoundingBox")) comp->userSpace = false;
+ if (!strcmp(value, "objectBoundingBox")) mask->userSpace = false;
+ } else if (!strcmp(key, "mask-type")) {
+ mask->type = _toMaskType(value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
@@ -1070,6 +1124,49 @@ static bool _attrParseMaskNode(void* data, const char* key, const char* value)
}
+static bool _attrParseCssStyleNode(void* data, const char* key, const char* value)
+{
+ SvgLoaderData* loader = (SvgLoaderData*)data;
+ SvgNode* node = loader->svgParse->node;
+
+ if (!strcmp(key, "id")) {
+ if (node->id && value) free(node->id);
+ node->id = _copyId(value);
+ } else {
+ return _parseStyleAttr(loader, key, value, false);
+ }
+ return true;
+}
+
+
+static bool _attrParseSymbolNode(void* data, const char* key, const char* value)
+{
+ SvgLoaderData* loader = (SvgLoaderData*)data;
+ SvgNode* node = loader->svgParse->node;
+ SvgSymbolNode* symbol = &(node->node.symbol);
+
+ if (!strcmp(key, "viewBox")) {
+ if (!_parseNumber(&value, &symbol->vx) || !_parseNumber(&value, &symbol->vy)) return false;
+ if (!_parseNumber(&value, &symbol->vw) || !_parseNumber(&value, &symbol->vh)) return false;
+ symbol->hasViewBox = true;
+ } else if (!strcmp(key, "width")) {
+ symbol->w = _toFloat(loader->svgParse, value, SvgParserLengthType::Horizontal);
+ symbol->hasWidth = true;
+ } else if (!strcmp(key, "height")) {
+ symbol->h = _toFloat(loader->svgParse, value, SvgParserLengthType::Vertical);
+ symbol->hasHeight = true;
+ } else if (!strcmp(key, "preserveAspectRatio")) {
+ if (!strcmp(value, "none")) symbol->preserveAspect = false;
+ } else if (!strcmp(key, "overflow")) {
+ if (!strcmp(value, "visible")) symbol->overflowVisible = true;
+ } else {
+ return _attrParseGNode(data, key, value);
+ }
+
+ return true;
+}
+
+
static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
{
SvgNode* node = (SvgNode*)calloc(1, sizeof(SvgNode));
@@ -1121,7 +1218,7 @@ static SvgNode* _createNode(SvgNode* parent, SvgNodeType type)
}
-static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED SvgNode* parent, const char* buf, unsigned bufLength, TVG_UNUSED parseAttributes func)
{
if (loader->def && loader->doc->node.doc.defs) return loader->def;
SvgNode* node = _createNode(nullptr, SvgNodeType::Defs);
@@ -1132,17 +1229,17 @@ static SvgNode* _createDefsNode(TVG_UNUSED SvgLoaderData* loader, TVG_UNUSED Svg
}
-static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createGNode(TVG_UNUSED SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::G);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseGNode, loader);
+ func(buf, bufLength, _attrParseGNode, loader);
return loader->svgParse->node;
}
-static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Doc);
if (!loader->svgParse->node) return nullptr;
@@ -1152,7 +1249,7 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
loader->svgParse->global.h = 0;
doc->preserveAspect = true;
- simpleXmlParseAttributes(buf, bufLength, _attrParseSvgNode, loader);
+ func(buf, bufLength, _attrParseSvgNode, loader);
if (loader->svgParse->global.w == 0) {
if (doc->w < FLT_EPSILON) loader->svgParse->global.w = 1;
@@ -1167,32 +1264,66 @@ static SvgNode* _createSvgNode(SvgLoaderData* loader, SvgNode* parent, const cha
}
-static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, TVG_UNUSED const char* buf, TVG_UNUSED unsigned bufLength)
+static SvgNode* _createMaskNode(SvgLoaderData* loader, SvgNode* parent, TVG_UNUSED const char* buf, TVG_UNUSED unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Mask);
if (!loader->svgParse->node) return nullptr;
- loader->svgParse->node->node.comp.userSpace = true;
+ loader->svgParse->node->node.mask.userSpace = true;
+ loader->svgParse->node->node.mask.type = SvgMaskType::Luminance;
- simpleXmlParseAttributes(buf, bufLength, _attrParseMaskNode, loader);
+ func(buf, bufLength, _attrParseMaskNode, loader);
return loader->svgParse->node;
}
-static SvgNode* _createClipPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createClipPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::ClipPath);
if (!loader->svgParse->node) return nullptr;
loader->svgParse->node->display = false;
- loader->svgParse->node->node.comp.userSpace = true;
+ loader->svgParse->node->node.clip.userSpace = true;
+
+ func(buf, bufLength, _attrParseClipPathNode, loader);
+
+ return loader->svgParse->node;
+}
+
+
+static SvgNode* _createCssStyleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
+{
+ loader->svgParse->node = _createNode(parent, SvgNodeType::CssStyle);
+ if (!loader->svgParse->node) return nullptr;
+
+ func(buf, bufLength, _attrParseCssStyleNode, loader);
+
+ return loader->svgParse->node;
+}
+
+
+static SvgNode* _createSymbolNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
+{
+ loader->svgParse->node = _createNode(parent, SvgNodeType::Symbol);
+ if (!loader->svgParse->node) return nullptr;
+
+ loader->svgParse->node->display = false;
+ loader->svgParse->node->node.symbol.preserveAspect = true;
+ loader->svgParse->node->node.symbol.overflowVisible = false;
+
+ loader->svgParse->node->node.symbol.hasViewBox = false;
+ loader->svgParse->node->node.symbol.hasWidth = false;
+ loader->svgParse->node->node.symbol.hasHeight = false;
+ loader->svgParse->node->node.symbol.vx = 0.0f;
+ loader->svgParse->node->node.symbol.vy = 0.0f;
- simpleXmlParseAttributes(buf, bufLength, _attrParseClipPathNode, loader);
+ func(buf, bufLength, _attrParseSymbolNode, loader);
return loader->svgParse->node;
}
+
static bool _attrParsePathNode(void* data, const char* key, const char* value)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
@@ -1203,7 +1334,7 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
//Temporary: need to copy
path->path = _copyId(value);
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1211,6 +1342,8 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
@@ -1218,13 +1351,13 @@ static bool _attrParsePathNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createPathNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Path);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParsePathNode, loader);
+ func(buf, bufLength, _attrParsePathNode, loader);
return loader->svgParse->node;
}
@@ -1263,7 +1396,7 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
}
if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1271,6 +1404,8 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
@@ -1278,13 +1413,13 @@ static bool _attrParseCircleNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createCircleNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Circle);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseCircleNode, loader);
+ func(buf, bufLength, _attrParseCircleNode, loader);
return loader->svgParse->node;
}
@@ -1325,8 +1460,10 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value
if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1338,13 +1475,13 @@ static bool _attrParseEllipseNode(void* data, const char* key, const char* value
}
-static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createEllipseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Ellipse);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseEllipseNode, loader);
+ func(buf, bufLength, _attrParseEllipseNode, loader);
return loader->svgParse->node;
}
@@ -1400,7 +1537,7 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
if (!strcmp(key, "points")) {
return _attrParsePolygonPoints(value, &polygon->points, &polygon->pointsCount);
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1408,6 +1545,8 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else {
return _parseStyleAttr(loader, key, value, false);
}
@@ -1415,24 +1554,24 @@ static bool _attrParsePolygonNode(void* data, const char* key, const char* value
}
-static SvgNode* _createPolygonNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createPolygonNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Polygon);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader);
+ func(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node;
}
-static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createPolylineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Polyline);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParsePolygonNode, loader);
+ func(buf, bufLength, _attrParsePolygonNode, loader);
return loader->svgParse->node;
}
@@ -1482,8 +1621,10 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value)
if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) {
- ret = simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ ret = simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1496,7 +1637,7 @@ static bool _attrParseRectNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Rect);
@@ -1504,7 +1645,7 @@ static SvgNode* _createRectNode(SvgLoaderData* loader, SvgNode* parent, const ch
loader->svgParse->node->node.rect.hasRx = loader->svgParse->node->node.rect.hasRy = false;
- simpleXmlParseAttributes(buf, bufLength, _attrParseRectNode, loader);
+ func(buf, bufLength, _attrParseRectNode, loader);
return loader->svgParse->node;
}
@@ -1545,8 +1686,10 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value)
if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
@@ -1558,13 +1701,13 @@ static bool _attrParseLineNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createLineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createLineNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Line);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseLineNode, loader);
+ func(buf, bufLength, _attrParseLineNode, loader);
return loader->svgParse->node;
}
@@ -1616,12 +1759,16 @@ static bool _attrParseImageNode(void* data, const char* key, const char* value)
} else if (!strcmp(key, "id")) {
if (node->id && value) free(node->id);
node->id = _copyId(value);
+ } else if (!strcmp(key, "class")) {
+ _handleCssClassAttr(loader, node, value);
} else if (!strcmp(key, "style")) {
- return simpleXmlParseW3CAttribute(value, _parseStyleAttr, loader);
+ return simpleXmlParseW3CAttribute(value, strlen(value), _parseStyleAttr, loader);
} else if (!strcmp(key, "clip-path")) {
_handleClipPathAttr(loader, node, value);
} else if (!strcmp(key, "mask")) {
_handleMaskAttr(loader, node, value);
+ } else if (!strcmp(key, "transform")) {
+ node->transform = _parseTransformationMatrix(value);
} else {
return _parseStyleAttr(loader, key, value);
}
@@ -1629,13 +1776,13 @@ static bool _attrParseImageNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createImageNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Image);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseImageNode, loader);
+ func(buf, bufLength, _attrParseImageNode, loader);
return loader->svgParse->node;
}
@@ -1941,12 +2088,6 @@ static void _cloneNode(SvgNode* from, SvgNode* parent, int depth)
}
-static void _postponeCloneNode(SvgLoaderData* loader, SvgNode *node, char* id)
-{
- loader->cloneNodes.push({node, id});
-}
-
-
static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
{
for (uint32_t i = 0; i < cloneNodes->count; ++i) {
@@ -1955,6 +2096,9 @@ static void _clonePostponedNodes(Array<SvgNodeIdPair>* cloneNodes, SvgNode* doc)
auto nodeFrom = _findChildById(defs, nodeIdPair.id);
if (!nodeFrom) nodeFrom = _findChildById(doc, nodeIdPair.id);
_cloneNode(nodeFrom, nodeIdPair.node, 0);
+ if (nodeFrom && nodeFrom->type == SvgNodeType::Symbol && nodeIdPair.node->type == SvgNodeType::Use) {
+ nodeIdPair.node->node.use.symbol = nodeFrom;
+ }
free(nodeIdPair.id);
}
}
@@ -1967,10 +2111,10 @@ static constexpr struct
int sz;
size_t offset;
} useTags[] = {
- {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgRectNode, x)},
- {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgRectNode, y)},
- {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgRectNode, w)},
- {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgRectNode, h)}
+ {"x", SvgParserLengthType::Horizontal, sizeof("x"), offsetof(SvgUseNode, x)},
+ {"y", SvgParserLengthType::Vertical, sizeof("y"), offsetof(SvgUseNode, y)},
+ {"width", SvgParserLengthType::Horizontal, sizeof("width"), offsetof(SvgUseNode, w)},
+ {"height", SvgParserLengthType::Vertical, sizeof("height"), offsetof(SvgUseNode, h)}
};
@@ -1986,6 +2130,10 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
for (unsigned int i = 0; i < sizeof(useTags) / sizeof(useTags[0]); i++) {
if (useTags[i].sz - 1 == sz && !strncmp(useTags[i].tag, key, sz)) {
*((float*)(array + useTags[i].offset)) = _toFloat(loader->svgParse, value, useTags[i].type);
+
+ if (useTags[i].offset == offsetof(SvgUseNode, w)) use->isWidthSet = true;
+ else if (useTags[i].offset == offsetof(SvgUseNode, h)) use->isHeightSet = true;
+
return true;
}
}
@@ -1996,12 +2144,13 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
nodeFrom = _findChildById(defs, id);
if (nodeFrom) {
_cloneNode(nodeFrom, node, 0);
+ if (nodeFrom->type == SvgNodeType::Symbol) use->symbol = nodeFrom;
free(id);
} else {
//some svg export software include <defs> element at the end of the file
//if so the 'from' element won't be found now and we have to repeat finding
//after the whole file is parsed
- _postponeCloneNode(loader, node, id);
+ _postpone(loader->cloneNodes, node, id);
}
} else {
return _attrParseGNode(data, key, value);
@@ -2010,16 +2159,20 @@ static bool _attrParseUseNode(void* data, const char* key, const char* value)
}
-static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength)
+static SvgNode* _createUseNode(SvgLoaderData* loader, SvgNode* parent, const char* buf, unsigned bufLength, parseAttributes func)
{
loader->svgParse->node = _createNode(parent, SvgNodeType::Use);
if (!loader->svgParse->node) return nullptr;
- simpleXmlParseAttributes(buf, bufLength, _attrParseUseNode, loader);
+ loader->svgParse->node->node.use.isWidthSet = false;
+ loader->svgParse->node->node.use.isHeightSet = false;
+
+ func(buf, bufLength, _attrParseUseNode, loader);
return loader->svgParse->node;
}
+
//TODO: Implement 'text' primitive
static constexpr struct
{
@@ -2049,7 +2202,9 @@ static constexpr struct
{"g", sizeof("g"), _createGNode},
{"svg", sizeof("svg"), _createSvgNode},
{"mask", sizeof("mask"), _createMaskNode},
- {"clipPath", sizeof("clipPath"), _createClipPathNode}
+ {"clipPath", sizeof("clipPath"), _createClipPathNode},
+ {"style", sizeof("style"), _createCssStyleNode},
+ {"symbol", sizeof("symbol"), _createSymbolNode}
};
@@ -2204,8 +2359,8 @@ static bool _attrParseRadialGradientNode(void* data, const char* key, const char
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value);
- } else if (!strcmp(key, "gradientUnits") && !strcmp(value, "userSpaceOnUse")) {
- grad->userSpace = true;
+ } else if (!strcmp(key, "gradientUnits")) {
+ if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
} else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value);
} else {
@@ -2291,7 +2446,7 @@ static bool _attrParseStops(void* data, const char* key, const char* value)
_toColor(value, &stop->r, &stop->g, &stop->b, nullptr);
}
} else if (!strcmp(key, "style")) {
- simpleXmlParseW3CAttribute(value, _attrParseStopsStyle, data);
+ simpleXmlParseW3CAttribute(value, strlen(value), _attrParseStopsStyle, data);
} else {
return false;
}
@@ -2394,8 +2549,8 @@ static bool _attrParseLinearGradientNode(void* data, const char* key, const char
} else if (!strcmp(key, "href") || !strcmp(key, "xlink:href")) {
if (grad->ref && value) free(grad->ref);
grad->ref = _idFromHref(value);
- } else if (!strcmp(key, "gradientUnits") && !strcmp(value, "userSpaceOnUse")) {
- grad->userSpace = true;
+ } else if (!strcmp(key, "gradientUnits")) {
+ if (!strcmp(value, "userSpaceOnUse")) grad->userSpace = true;
} else if (!strcmp(key, "gradientTransform")) {
grad->transform = _parseTransformationMatrix(value);
} else {
@@ -2479,11 +2634,13 @@ static constexpr struct
{"svg", sizeof("svg")},
{"defs", sizeof("defs")},
{"mask", sizeof("mask")},
- {"clipPath", sizeof("clipPath")}
+ {"clipPath", sizeof("clipPath")},
+ {"style", sizeof("style")},
+ {"symbol", sizeof("symbol")}
};
-static void _svgLoaderParerXmlClose(SvgLoaderData* loader, const char* content)
+static void _svgLoaderParserXmlClose(SvgLoaderData* loader, const char* content)
{
content = _skipSpace(content, nullptr);
@@ -2531,13 +2688,20 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
if (empty) return;
if (!loader->doc) {
if (strcmp(tagName, "svg")) return; //Not a valid svg document
- node = method(loader, nullptr, attrs, attrsLength);
+ node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->doc = node;
} else {
if (!strcmp(tagName, "svg")) return; //Already loaded <svg>(SvgNodeType::Doc) tag
if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1];
else parent = loader->doc;
- node = method(loader, parent, attrs, attrsLength);
+ if (!strcmp(tagName, "style")) {
+ node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
+ loader->cssStyle = node;
+ loader->doc->node.doc.style = node;
+ loader->style = true;
+ } else {
+ node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
+ }
}
if (!node) return;
@@ -2547,7 +2711,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
} else if ((method = _findGraphicsFactory(tagName))) {
if (loader->stack.count > 0) parent = loader->stack.data[loader->stack.count - 1];
else parent = loader->doc;
- node = method(loader, parent, attrs, attrsLength);
+ node = method(loader, parent, attrs, attrsLength, simpleXmlParseAttributes);
} else if ((gradientMethod = _findGradientFactory(tagName))) {
SvgStyleGradient* gradient;
gradient = gradientMethod(loader, attrs, attrsLength);
@@ -2570,6 +2734,7 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
}
/* default value for opacity */
loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255};
+ loader->svgParse->flags = SvgStopStyleFlags::StopDefault;
simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader);
loader->latestGradient->stops.push(loader->svgParse->gradStop);
} else if (!isIgnoreUnsupportedLogElements(tagName)) {
@@ -2578,6 +2743,42 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content,
}
+static void _svgLoaderParserXmlCssStyle(SvgLoaderData* loader, const char* content, unsigned int length)
+{
+ char* tag;
+ char* name;
+ const char* attrs = nullptr;
+ unsigned int attrsLength = 0;
+
+ FactoryMethod method;
+ GradientFactoryMethod gradientMethod;
+ SvgNode *node = nullptr;
+
+ while (auto next = simpleXmlParseCSSAttribute(content, length, &tag, &name, &attrs, &attrsLength)) {
+ if ((method = _findGroupFactory(tag))) {
+ if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
+ } else if ((method = _findGraphicsFactory(tag))) {
+ if ((node = method(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
+ } else if ((gradientMethod = _findGradientFactory(tag))) {
+ TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
+ } else if (!strcmp(tag, "stop")) {
+ TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
+ } else if (!strcmp(tag, "all")) {
+ if ((node = _createCssStyleNode(loader, loader->cssStyle, attrs, attrsLength, simpleXmlParseW3CAttribute))) node->id = _copyId(name);
+ } else if (!isIgnoreUnsupportedLogElements(tag)) {
+ TVGLOG("SVG", "Unsupported elements used in the internal CSS style sheets [Elements: %s]", tag);
+ }
+
+ length -= next - content;
+ content = next;
+
+ free(tag);
+ free(name);
+ }
+ loader->style = false;
+}
+
+
static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content, unsigned int length)
{
SvgLoaderData* loader = (SvgLoaderData*)data;
@@ -2592,11 +2793,14 @@ static bool _svgLoaderParser(void* data, SimpleXMLType type, const char* content
break;
}
case SimpleXMLType::Close: {
- _svgLoaderParerXmlClose(loader, content);
+ _svgLoaderParserXmlClose(loader, content);
break;
}
case SimpleXMLType::Data:
- case SimpleXMLType::CData:
+ case SimpleXMLType::CData: {
+ if (loader->style) _svgLoaderParserXmlCssStyle(loader, content, length);
+ break;
+ }
case SimpleXMLType::DoctypeChild: {
break;
}
@@ -2619,7 +2823,7 @@ static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node)
#ifdef THORVG_LOG_ENABLED
auto type = simpleXmlNodeTypeToString(node->type);
- if (!node->display && node->type != SvgNodeType::ClipPath) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type);
+ if (!node->display && node->type != SvgNodeType::ClipPath && node->type != SvgNodeType::Symbol) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type);
if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type);
if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type);
@@ -2674,7 +2878,7 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const
auto gradList = gradients->data;
for (uint32_t i = 0; i < gradients->count; ++i) {
- if (!strcmp((*gradList)->id, id)) {
+ if ((*gradList)->id && !strcmp((*gradList)->id, id)) {
result = _cloneGradient(*gradList);
break;
}
@@ -2684,7 +2888,7 @@ static SvgStyleGradient* _gradientDup(Array<SvgStyleGradient*>* gradients, const
if (result && result->ref) {
gradList = gradients->data;
for (uint32_t i = 0; i < gradients->count; ++i) {
- if (!strcmp((*gradList)->id, result->ref)) {
+ if ((*gradList)->id && !strcmp((*gradList)->id, result->ref)) {
if (result->stops.count == 0) _cloneGradStops(result->stops, (*gradList)->stops);
//TODO: Properly inherit other property
break;
@@ -2749,6 +2953,7 @@ static void _freeNodeStyle(SvgStyleProperty* style)
//style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode.
free(style->clipPath.url);
free(style->mask.url);
+ free(style->cssClass);
if (style->fill.paint.gradient) {
style->fill.paint.gradient->clear();
@@ -2793,6 +2998,7 @@ static void _freeNode(SvgNode* node)
}
case SvgNodeType::Doc: {
_freeNode(node->node.doc.defs);
+ _freeNode(node->node.doc.style);
break;
}
case SvgNodeType::Defs: {
@@ -2846,7 +3052,7 @@ static bool _svgLoaderParserForValidCheckXmlOpen(SvgLoaderData* loader, const ch
if ((method = _findGroupFactory(tagName))) {
if (!loader->doc) {
if (strcmp(tagName, "svg")) return true; //Not a valid svg document
- node = method(loader, nullptr, attrs, attrsLength);
+ node = method(loader, nullptr, attrs, attrsLength, simpleXmlParseAttributes);
loader->doc = node;
loader->stack.push(node);
return false;
@@ -2906,16 +3112,20 @@ void SvgLoader::run(unsigned tid)
if (!simpleXmlParse(content, size, true, _svgLoaderParser, &(loaderData))) return;
if (loaderData.doc) {
- _updateStyle(loaderData.doc, nullptr);
auto defs = loaderData.doc->node.doc.defs;
- _updateComposite(loaderData.doc, loaderData.doc);
- if (defs) _updateComposite(loaderData.doc, defs);
+ if (loaderData.nodesToStyle.count > 0) cssApplyStyleToPostponeds(loaderData.nodesToStyle, loaderData.cssStyle);
+ if (loaderData.cssStyle) cssUpdateStyle(loaderData.doc, loaderData.cssStyle);
if (loaderData.cloneNodes.count > 0) _clonePostponedNodes(&loaderData.cloneNodes, loaderData.doc);
+ _updateComposite(loaderData.doc, loaderData.doc);
+ if (defs) _updateComposite(loaderData.doc, defs);
+
if (loaderData.gradients.count > 0) _updateGradient(loaderData.doc, &loaderData.gradients);
if (defs) _updateGradient(loaderData.doc, &defs->node.defs.gradients);
+
+ _updateStyle(loaderData.doc, nullptr);
}
root = svgSceneBuild(loaderData.doc, vx, vy, vw, vh, w, h, preserveAspect, svgPath);
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
index 468f05801d..093fb671b3 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
index cceef915f0..dc9ed558c3 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgLoaderCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -51,6 +51,8 @@ enum class SvgNodeType
Video,
ClipPath,
Mask,
+ CssStyle,
+ Symbol,
Unknown
};
@@ -111,7 +113,8 @@ enum class SvgStyleFlags
Transform = 0x800,
ClipPath = 0x1000,
Mask = 0x2000,
- Display = 0x4000
+ MaskType = 0x4000,
+ Display = 0x8000
};
enum class SvgStopStyleFlags
@@ -127,6 +130,12 @@ enum class SvgFillRule
OddEven = 1
};
+enum class SvgMaskType
+{
+ Luminance = 0,
+ Alpha
+};
+
//Length type to recalculate %, pt, pc, mm, cm etc
enum class SvgParserLengthType
{
@@ -145,6 +154,7 @@ struct SvgDocNode
float vw;
float vh;
SvgNode* defs;
+ SvgNode* style;
bool preserveAspect;
};
@@ -157,12 +167,25 @@ struct SvgDefsNode
Array<SvgStyleGradient*> gradients;
};
+struct SvgSymbolNode
+{
+ float w, h;
+ float vx, vy, vw, vh;
+ bool preserveAspect;
+ bool overflowVisible;
+ bool hasViewBox;
+ bool hasWidth;
+ bool hasHeight;
+};
+
struct SvgUseNode
{
float x, y, w, h;
+ bool isWidthSet;
+ bool isHeightSet;
+ SvgNode* symbol;
};
-
struct SvgEllipseNode
{
float cx;
@@ -215,11 +238,21 @@ struct SvgPolygonNode
float* points;
};
-struct SvgCompositeNode
+struct SvgClipNode
{
bool userSpace;
};
+struct SvgMaskNode
+{
+ SvgMaskType type;
+ bool userSpace;
+};
+
+struct SvgCssStyleNode
+{
+};
+
struct SvgLinearGradient
{
float x1;
@@ -328,6 +361,7 @@ struct SvgStyleProperty
int opacity;
SvgColor color;
bool curColorSet;
+ char* cssClass;
SvgStyleFlags flags;
};
@@ -352,7 +386,10 @@ struct SvgNode
SvgPathNode path;
SvgLineNode line;
SvgImageNode image;
- SvgCompositeNode comp;
+ SvgMaskNode mask;
+ SvgClipNode clip;
+ SvgCssStyleNode cssStyle;
+ SvgSymbolNode symbol;
} node;
bool display;
~SvgNode();
@@ -384,15 +421,18 @@ struct SvgNodeIdPair
struct SvgLoaderData
{
- Array<SvgNode *> stack = {nullptr, 0, 0};
+ Array<SvgNode*> stack = {nullptr, 0, 0};
SvgNode* doc = nullptr;
SvgNode* def = nullptr;
+ SvgNode* cssStyle = nullptr;
Array<SvgStyleGradient*> gradients;
SvgStyleGradient* latestGradient = nullptr; //For stops
SvgParser* svgParse = nullptr;
Array<SvgNodeIdPair> cloneNodes;
+ Array<SvgNodeIdPair> nodesToStyle;
int level = 0;
bool result = false;
+ bool style = false;
};
/*
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
index 32685ee620..a09a2797d0 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
index 7f26c4a213..8f5f9035dc 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgPath.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
index ae17634f31..a3f34fd46b 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -68,12 +68,12 @@ struct Box
static bool _appendShape(SvgNode* node, Shape* shape, const Box& vBox, const string& svgPath);
-static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask);
+static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite = nullptr);
static inline bool _isGroupType(SvgNodeType type)
{
- if (type == SvgNodeType::Doc || type == SvgNodeType::G || type == SvgNodeType::Use || type == SvgNodeType::ClipPath) return true;
+ if (type == SvgNodeType::Doc || type == SvgNodeType::G || type == SvgNodeType::Use || type == SvgNodeType::ClipPath || type == SvgNodeType::Symbol) return true;
return false;
}
@@ -276,15 +276,21 @@ static void _applyComposition(Paint* paint, const SvgNode* node, const Box& vBox
Composition can be applied recursively if its children nodes have composition target to this one. */
if (node->style->mask.applying) {
TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?");
- } else {
+ } else {
auto compNode = node->style->mask.node;
if (compNode && compNode->child.count > 0) {
node->style->mask.applying = true;
- auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true);
+ bool isMaskWhite = true;
+ auto comp = _sceneBuildHelper(compNode, vBox, svgPath, true, &isMaskWhite);
if (comp) {
if (node->transform) comp->transform(*node->transform);
- paint->composite(move(comp), CompositeMethod::AlphaMask);
+
+ if (compNode->node.mask.type == SvgMaskType::Luminance && !isMaskWhite) {
+ paint->composite(move(comp), CompositeMethod::LumaMask);
+ } else {
+ paint->composite(move(comp), CompositeMethod::AlphaMask);
+ }
}
node->style->mask.applying = false;
@@ -534,57 +540,139 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, const Box& vBox, con
string imagePath = href;
if (strncmp(href, "/", 1)) {
auto last = svgPath.find_last_of("/");
- imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1 )) + imagePath;
+ imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath;
}
if (picture->load(imagePath) != Result::Success) return nullptr;
}
float w, h;
+ Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) {
auto sx = node->node.image.w / w;
auto sy = node->node.image.h / h;
- Matrix m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
- picture->transform(m);
+ m = {sx, 0, node->node.image.x, 0, sy, node->node.image.y, 0, 0, 1};
}
+ if (node->transform) m = mathMultiply(node->transform, &m);
+ picture->transform(m);
_applyComposition(picture.get(), node, vBox, svgPath);
return picture;
}
-static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath)
+static unique_ptr<Scene> _useBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool* isMaskWhite)
{
- auto scene = _sceneBuildHelper(node, vBox, svgPath, false);
+ unique_ptr<Scene> finalScene;
+ auto scene = _sceneBuildHelper(node, vBox, svgPath, false, isMaskWhite);
+
+ // mUseTransform = mUseTransform * mTranslate
+ Matrix mUseTransform = {1, 0, 0, 0, 1, 0, 0, 0, 1};
+ if (node->transform) mUseTransform = *node->transform;
if (node->node.use.x != 0.0f || node->node.use.y != 0.0f) {
- scene->translate(node->node.use.x, node->node.use.y);
+ Matrix mTranslate = {1, 0, node->node.use.x, 0, 1, node->node.use.y, 0, 0, 1};
+ mUseTransform = mathMultiply(&mUseTransform, &mTranslate);
}
- if (node->node.use.w > 0.0f && node->node.use.h > 0.0f) {
- //TODO: handle width/height properties
+
+ if (node->node.use.symbol) {
+ auto symbol = node->node.use.symbol->node.symbol;
+
+ auto width = (symbol.hasWidth ? symbol.w : vBox.w);
+ if (node->node.use.isWidthSet) width = node->node.use.w;
+ auto height = (symbol.hasHeight ? symbol.h : vBox.h);;
+ if (node->node.use.isHeightSet) height = node->node.use.h;
+ auto vw = (symbol.hasViewBox ? symbol.vw : width);
+ auto vh = (symbol.hasViewBox ? symbol.vh : height);
+
+ Matrix mViewBox = {1, 0, 0, 0, 1, 0, 0, 0, 1};
+ if ((!mathEqual(width, vw) || !mathEqual(height, vh)) && vw > 0 && vh > 0) {
+ auto sx = width / vw;
+ auto sy = height / vh;
+ if (symbol.preserveAspect) {
+ if (sx < sy) sy = sx;
+ else sx = sy;
+ }
+
+ auto tvx = symbol.vx * sx;
+ auto tvy = symbol.vy * sy;
+ auto tvw = vw * sx;
+ auto tvh = vh * sy;
+ tvy -= (symbol.h - tvh) * 0.5f;
+ tvx -= (symbol.w - tvw) * 0.5f;
+ mViewBox = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
+ } else if (!mathZero(symbol.vx) || !mathZero(symbol.vy)) {
+ mViewBox = {1, 0, -symbol.vx, 0, 1, -symbol.vy, 0, 0, 1};
+ }
+
+ // mSceneTransform = mUseTransform * mSymbolTransform * mViewBox
+ Matrix mSceneTransform = mViewBox;
+ if (node->node.use.symbol->transform) {
+ mSceneTransform = mathMultiply(node->node.use.symbol->transform, &mViewBox);
+ }
+ mSceneTransform = mathMultiply(&mUseTransform, &mSceneTransform);
+ scene->transform(mSceneTransform);
+
+ if (node->node.use.symbol->node.symbol.overflowVisible) {
+ finalScene = move(scene);
+ } else {
+ auto viewBoxClip = Shape::gen();
+ viewBoxClip->appendRect(0, 0, width, height, 0, 0);
+
+ // mClipTransform = mUseTransform * mSymbolTransform
+ Matrix mClipTransform = mUseTransform;
+ if (node->node.use.symbol->transform) {
+ mClipTransform = mathMultiply(&mUseTransform, node->node.use.symbol->transform);
+ }
+ viewBoxClip->transform(mClipTransform);
+
+ auto compositeLayer = Scene::gen();
+ compositeLayer->composite(move(viewBoxClip), CompositeMethod::ClipPath);
+ compositeLayer->push(move(scene));
+
+ auto root = Scene::gen();
+ root->push(move(compositeLayer));
+
+ finalScene = move(root);
+ }
+ } else {
+ if (!mathIdentity((const Matrix*)(&mUseTransform))) scene->transform(mUseTransform);
+ finalScene = move(scene);
}
- return scene;
+
+ return finalScene;
}
-static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask)
+static unique_ptr<Scene> _sceneBuildHelper(const SvgNode* node, const Box& vBox, const string& svgPath, bool mask, bool* isMaskWhite)
{
if (_isGroupType(node->type) || mask) {
auto scene = Scene::gen();
- if (!mask && node->transform) scene->transform(*node->transform);
+ // For a Symbol node, the viewBox transformation has to be applied first - see _useBuildHelper()
+ if (!mask && node->transform && node->type != SvgNodeType::Symbol) scene->transform(*node->transform);
if (node->display && node->style->opacity != 0) {
auto child = node->child.data;
for (uint32_t i = 0; i < node->child.count; ++i, ++child) {
if (_isGroupType((*child)->type)) {
if ((*child)->type == SvgNodeType::Use)
- scene->push(_useBuildHelper(*child, vBox, svgPath));
+ scene->push(_useBuildHelper(*child, vBox, svgPath, isMaskWhite));
else
- scene->push(_sceneBuildHelper(*child, vBox, svgPath, false));
+ scene->push(_sceneBuildHelper(*child, vBox, svgPath, false, isMaskWhite));
} else if ((*child)->type == SvgNodeType::Image) {
auto image = _imageBuildHelper(*child, vBox, svgPath);
if (image) scene->push(move(image));
} else if ((*child)->type != SvgNodeType::Mask) {
auto shape = _shapeBuildHelper(*child, vBox, svgPath);
- if (shape) scene->push(move(shape));
+ if (shape) {
+ if (isMaskWhite) {
+ uint8_t r, g, b;
+ shape->fillColor(&r, &g, &b, nullptr);
+ if (shape->fill() || r < 255 || g < 255 || b < 255 || shape->strokeFill() ||
+ (shape->strokeColor(&r, &g, &b, nullptr) == Result::Success && (r < 255 || g < 255 || b < 255))) {
+ *isMaskWhite = false;
+ }
+ }
+ scene->push(move(shape));
+ }
}
}
_applyComposition(scene.get(), node, vBox, svgPath);
@@ -620,17 +708,13 @@ unique_ptr<Scene> svgSceneBuild(SvgNode* node, float vx, float vy, float vw, flo
auto tvy = vy * scale;
auto tvw = vw * scale;
auto tvh = vh * scale;
- if (vw > vh) tvy -= (h - tvh) * 0.5f;
- else tvx -= (w - tvw) * 0.5f;
+ tvx -= (w - tvw) * 0.5f;
+ tvy -= (h - tvh) * 0.5f;
docNode->translate(-tvx, -tvy);
} else {
//Align
auto tvx = vx * sx;
auto tvy = vy * sy;
- auto tvw = vw * sx;
- auto tvh = vh * sy;
- if (tvw > tvh) tvy -= (h - tvh) * 0.5f;
- else tvx -= (w - tvw) * 0.5f;
Matrix m = {sx, 0, -tvx, 0, sy, -tvy, 0, 0, 1};
docNode->transform(m);
}
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
index 4232aca612..cecbbf02a8 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgSceneBuilder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
index 9f269b29a2..1f1fe2a718 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
index 4320cfed4e..b5e6e1bdb2 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgSvgUtil.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
index ee199da231..d7c51bdc30 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
+++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,8 @@
#ifdef _WIN32
#include <malloc.h>
+#elif defined(__FreeBSD__)
+ #include <stdlib.h>
#else
#include <alloca.h>
#endif
@@ -236,6 +238,14 @@ static SimpleXMLType _getXMLType(const char* itr, const char* itrEnd, size_t &to
}
+static char* _strndup(const char* src, unsigned len)
+{
+ auto ret = (char*)malloc(len + 1);
+ if (!ret) return nullptr;
+ ret[len] = '\0';
+ return (char*)memcpy(ret, src, len);
+}
+
/************************************************************************/
/* External Class Implementation */
/************************************************************************/
@@ -264,6 +274,7 @@ const char* simpleXmlNodeTypeToString(TVG_UNUSED SvgNodeType type)
"Video",
"ClipPath",
"Mask",
+ "Symbol",
"Unknown",
};
return TYPE_NAMES[(int) type];
@@ -450,7 +461,7 @@ bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb
}
-bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data)
+bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data)
{
const char* end;
char* key;
@@ -459,7 +470,7 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
if (!buf) return false;
- end = buf + strlen(buf);
+ end = buf + bufLength;
key = (char*)alloca(end - buf + 1);
val = (char*)alloca(end - buf + 1);
@@ -468,6 +479,11 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
do {
char* sep = (char*)strchr(buf, ':');
next = (char*)strchr(buf, ';');
+ if (sep >= end) {
+ next = nullptr;
+ sep = nullptr;
+ }
+ if (next >= end) next = nullptr;
key[0] = '\0';
val[0] = '\0';
@@ -509,6 +525,47 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons
}
+/*
+ * Supported formats:
+ * tag {}, .name {}, tag.name{}
+ */
+const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength)
+{
+ if (!buf) return nullptr;
+
+ *tag = *name = nullptr;
+ *attrsLength = 0;
+
+ auto itr = _simpleXmlSkipWhiteSpace(buf, buf + bufLength);
+ auto itrEnd = (const char*)memchr(buf, '{', bufLength);
+
+ if (!itrEnd || itr == itrEnd) return nullptr;
+
+ auto nextElement = (const char*)memchr(itrEnd, '}', bufLength - (itrEnd - buf));
+ if (!nextElement) return nullptr;
+
+ *attrs = itrEnd + 1;
+ *attrsLength = nextElement - *attrs;
+
+ const char *p;
+
+ itrEnd = _simpleXmlUnskipWhiteSpace(itrEnd, itr);
+ if (*(itrEnd - 1) == '.') return nullptr;
+
+ for (p = itr; p < itrEnd; p++) {
+ if (*p == '.') break;
+ }
+
+ if (p == itr) *tag = strdup("all");
+ else *tag = _strndup(itr, p - itr);
+
+ if (p == itrEnd) *name = nullptr;
+ else *name = _strndup(p + 1, itrEnd - p - 1);
+
+ return (nextElement ? nextElement + 1 : nullptr);
+}
+
+
const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength)
{
const char *itr = buf, *itrEnd = buf + bufLength;
diff --git a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
index d96a631528..e2761ca8da 100644
--- a/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
+++ b/thirdparty/thorvg/src/loaders/svg/tvgXmlParser.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2020 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,7 +32,7 @@ const int xmlEntityLength[] = {6, 6, 6, 5, 4, 4, 6, 6};
enum class SimpleXMLType
{
Open = 0, //!< \<tag attribute="value"\>
- OpenEmpty, //!< \<tag attribute="value" /\>
+ OpenEmpty, //!< \<tag attribute="value" /\>
Close, //!< \</tag\>
Data, //!< tag text data
CData, //!< \<![cdata[something]]\>
@@ -41,16 +41,17 @@ enum class SimpleXMLType
Doctype, //!< \<!doctype html
Comment, //!< \<!-- something --\>
Ignored, //!< whatever is ignored by parser, like whitespace
- DoctypeChild //!< \<!doctype_child
+ DoctypeChild //!< \<!doctype_child
};
typedef bool (*simpleXMLCb)(void* data, SimpleXMLType type, const char* content, unsigned int length);
typedef bool (*simpleXMLAttributeCb)(void* data, const char* key, const char* value);
-bool simpleXmlParseAttributes(const char* buf, unsigned buflen, simpleXMLAttributeCb func, const void* data);
-bool simpleXmlParse(const char* buf, unsigned buflen, bool strip, simpleXMLCb func, const void* data);
-bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data);
-const char *simpleXmlFindAttributesTag(const char* buf, unsigned buflen);
+bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
+bool simpleXmlParse(const char* buf, unsigned bufLength, bool strip, simpleXMLCb func, const void* data);
+bool simpleXmlParseW3CAttribute(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data);
+const char* simpleXmlParseCSSAttribute(const char* buf, unsigned bufLength, char** tag, char** name, const char** attrs, unsigned* attrsLength);
+const char* simpleXmlFindAttributesTag(const char* buf, unsigned bufLength);
bool isIgnoreUnsupportedLogElements(const char* tagName);
const char* simpleXmlNodeTypeToString(SvgNodeType type);
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
index b0364b1055..66de860aaa 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgBinInterpreter.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,6 +23,8 @@
#ifdef _WIN32
#include <malloc.h>
+#elif defined(__FreeBSD__)
+ #include <stdlib.h>
#else
#include <alloca.h>
#endif
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h b/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
index e7c3eba488..a0762d0fcc 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgCommon.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -51,4 +51,4 @@ public:
};
-#endif //_TVG_TVG_COMMON_H_ \ No newline at end of file
+#endif //_TVG_TVG_COMMON_H_
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
index d7f3184435..95d629d1f6 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
index d276ded33a..3ae841aa85 100644
--- a/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
+++ b/thirdparty/thorvg/src/loaders/tvg/tvgTvgLoader.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
index 9dd57e5a89..fca313b430 100644
--- a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
+++ b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,6 +28,8 @@
#ifdef _WIN32
#include <malloc.h>
+#elif defined(__FreeBSD__)
+ #include <stdlib.h>
#else
#include <alloca.h>
#endif
diff --git a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
index 27186b5d4a..4acb35e76a 100644
--- a/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
+++ b/thirdparty/thorvg/src/savers/tvg/tvgTvgSaver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2021 - 2022 Samsung Electronics Co., Ltd. All rights reserved.
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/thirdparty/thorvg/update-thorvg.sh b/thirdparty/thorvg/update-thorvg.sh
index ce3d5eed1c..a3b73a7135 100755
--- a/thirdparty/thorvg/update-thorvg.sh
+++ b/thirdparty/thorvg/update-thorvg.sh
@@ -1,6 +1,6 @@
-VERSION=0.7.1
+VERSION=0.8.1
rm -rf AUTHORS inc LICENSE src *.zip
-curl -L -O https://github.com/Samsung/thorvg/archive/refs/tags/v$VERSION.zip
+curl -L -O https://github.com/Samsung/thorvg/archive/$VERSION.zip
bsdtar --strip-components=1 -xvf *.zip
rm *.zip
rm -rf .github docs pc res test tools .git* *.md *.txt wasm_build.sh
diff --git a/thirdparty/vhacd/0006-fix-gcc13.patch b/thirdparty/vhacd/0006-fix-gcc13.patch
new file mode 100644
index 0000000000..954ac4556d
--- /dev/null
+++ b/thirdparty/vhacd/0006-fix-gcc13.patch
@@ -0,0 +1,15 @@
+diff --git a/thirdparty/vhacd/inc/vhacdICHull.h b/thirdparty/vhacd/inc/vhacdICHull.h
+index 132bdcfb3e..925584cf52 100644
+--- a/thirdparty/vhacd/inc/vhacdICHull.h
++++ b/thirdparty/vhacd/inc/vhacdICHull.h
+@@ -18,6 +18,10 @@
+ #include "vhacdManifoldMesh.h"
+ #include "vhacdVector.h"
+
++// -- GODOT start --
++#include <cstdint>
++// -- GODOT end --
++
+ namespace VHACD {
+ //! Incremental Convex Hull algorithm (cf. http://cs.smith.edu/~orourke/books/ftp.html ).
+ enum ICHullError {
diff --git a/thirdparty/vhacd/inc/vhacdICHull.h b/thirdparty/vhacd/inc/vhacdICHull.h
index 132bdcfb3e..925584cf52 100644
--- a/thirdparty/vhacd/inc/vhacdICHull.h
+++ b/thirdparty/vhacd/inc/vhacdICHull.h
@@ -18,6 +18,10 @@
#include "vhacdManifoldMesh.h"
#include "vhacdVector.h"
+// -- GODOT start --
+#include <cstdint>
+// -- GODOT end --
+
namespace VHACD {
//! Incremental Convex Hull algorithm (cf. http://cs.smith.edu/~orourke/books/ftp.html ).
enum ICHullError {
diff --git a/thirdparty/volk/volk.c b/thirdparty/volk/volk.c
index bb8b928326..c3383ee41d 100644
--- a/thirdparty/volk/volk.c
+++ b/thirdparty/volk/volk.c
@@ -176,6 +176,9 @@ static void volkGenLoadInstance(void* context, PFN_vkVoidFunction (*load)(void*,
vkGetPhysicalDeviceQueueFamilyProperties2 = (PFN_vkGetPhysicalDeviceQueueFamilyProperties2)load(context, "vkGetPhysicalDeviceQueueFamilyProperties2");
vkGetPhysicalDeviceSparseImageFormatProperties2 = (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2)load(context, "vkGetPhysicalDeviceSparseImageFormatProperties2");
#endif /* defined(VK_VERSION_1_1) */
+#if defined(VK_VERSION_1_3)
+ vkGetPhysicalDeviceToolProperties = (PFN_vkGetPhysicalDeviceToolProperties)load(context, "vkGetPhysicalDeviceToolProperties");
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_EXT_acquire_drm_display)
vkAcquireDrmDisplayEXT = (PFN_vkAcquireDrmDisplayEXT)load(context, "vkAcquireDrmDisplayEXT");
vkGetDrmDisplayEXT = (PFN_vkGetDrmDisplayEXT)load(context, "vkGetDrmDisplayEXT");
@@ -503,6 +506,44 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c
vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore");
vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores");
#endif /* defined(VK_VERSION_1_2) */
+#if defined(VK_VERSION_1_3)
+ vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering");
+ vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2");
+ vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2");
+ vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2");
+ vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2");
+ vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2");
+ vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2");
+ vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering");
+ vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2");
+ vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2");
+ vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2");
+ vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode");
+ vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable");
+ vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable");
+ vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp");
+ vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable");
+ vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable");
+ vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2");
+ vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace");
+ vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable");
+ vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology");
+ vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable");
+ vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount");
+ vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp");
+ vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable");
+ vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount");
+ vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2");
+ vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2");
+ vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot");
+ vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot");
+ vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements");
+ vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements");
+ vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements");
+ vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData");
+ vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2");
+ vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData");
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_AMD_buffer_marker)
vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD");
#endif /* defined(VK_AMD_buffer_marker) */
@@ -593,6 +634,9 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c
vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT");
vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT");
#endif /* defined(VK_EXT_multi_draw) */
+#if defined(VK_EXT_pageable_device_local_memory)
+ vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT");
+#endif /* defined(VK_EXT_pageable_device_local_memory) */
#if defined(VK_EXT_private_data)
vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT");
vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT");
@@ -619,6 +663,13 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c
#if defined(VK_EXT_vertex_input_dynamic_state)
vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT");
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
+#if defined(VK_FUCHSIA_buffer_collection)
+ vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA");
+ vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA");
+ vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA");
+ vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA");
+ vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA");
+#endif /* defined(VK_FUCHSIA_buffer_collection) */
#if defined(VK_FUCHSIA_external_memory)
vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA");
vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA");
@@ -714,6 +765,10 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c
vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR");
vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR");
#endif /* defined(VK_KHR_draw_indirect_count) */
+#if defined(VK_KHR_dynamic_rendering)
+ vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR");
+ vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR");
+#endif /* defined(VK_KHR_dynamic_rendering) */
#if defined(VK_KHR_external_fence_fd)
vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR");
vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR");
@@ -752,6 +807,11 @@ static void volkGenLoadDevice(void* context, PFN_vkVoidFunction (*load)(void*, c
#if defined(VK_KHR_maintenance3)
vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR");
#endif /* defined(VK_KHR_maintenance3) */
+#if defined(VK_KHR_maintenance4)
+ vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR");
+ vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR");
+ vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR");
+#endif /* defined(VK_KHR_maintenance4) */
#if defined(VK_KHR_performance_query)
vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR");
vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR");
@@ -1063,6 +1123,44 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context,
table->vkSignalSemaphore = (PFN_vkSignalSemaphore)load(context, "vkSignalSemaphore");
table->vkWaitSemaphores = (PFN_vkWaitSemaphores)load(context, "vkWaitSemaphores");
#endif /* defined(VK_VERSION_1_2) */
+#if defined(VK_VERSION_1_3)
+ table->vkCmdBeginRendering = (PFN_vkCmdBeginRendering)load(context, "vkCmdBeginRendering");
+ table->vkCmdBindVertexBuffers2 = (PFN_vkCmdBindVertexBuffers2)load(context, "vkCmdBindVertexBuffers2");
+ table->vkCmdBlitImage2 = (PFN_vkCmdBlitImage2)load(context, "vkCmdBlitImage2");
+ table->vkCmdCopyBuffer2 = (PFN_vkCmdCopyBuffer2)load(context, "vkCmdCopyBuffer2");
+ table->vkCmdCopyBufferToImage2 = (PFN_vkCmdCopyBufferToImage2)load(context, "vkCmdCopyBufferToImage2");
+ table->vkCmdCopyImage2 = (PFN_vkCmdCopyImage2)load(context, "vkCmdCopyImage2");
+ table->vkCmdCopyImageToBuffer2 = (PFN_vkCmdCopyImageToBuffer2)load(context, "vkCmdCopyImageToBuffer2");
+ table->vkCmdEndRendering = (PFN_vkCmdEndRendering)load(context, "vkCmdEndRendering");
+ table->vkCmdPipelineBarrier2 = (PFN_vkCmdPipelineBarrier2)load(context, "vkCmdPipelineBarrier2");
+ table->vkCmdResetEvent2 = (PFN_vkCmdResetEvent2)load(context, "vkCmdResetEvent2");
+ table->vkCmdResolveImage2 = (PFN_vkCmdResolveImage2)load(context, "vkCmdResolveImage2");
+ table->vkCmdSetCullMode = (PFN_vkCmdSetCullMode)load(context, "vkCmdSetCullMode");
+ table->vkCmdSetDepthBiasEnable = (PFN_vkCmdSetDepthBiasEnable)load(context, "vkCmdSetDepthBiasEnable");
+ table->vkCmdSetDepthBoundsTestEnable = (PFN_vkCmdSetDepthBoundsTestEnable)load(context, "vkCmdSetDepthBoundsTestEnable");
+ table->vkCmdSetDepthCompareOp = (PFN_vkCmdSetDepthCompareOp)load(context, "vkCmdSetDepthCompareOp");
+ table->vkCmdSetDepthTestEnable = (PFN_vkCmdSetDepthTestEnable)load(context, "vkCmdSetDepthTestEnable");
+ table->vkCmdSetDepthWriteEnable = (PFN_vkCmdSetDepthWriteEnable)load(context, "vkCmdSetDepthWriteEnable");
+ table->vkCmdSetEvent2 = (PFN_vkCmdSetEvent2)load(context, "vkCmdSetEvent2");
+ table->vkCmdSetFrontFace = (PFN_vkCmdSetFrontFace)load(context, "vkCmdSetFrontFace");
+ table->vkCmdSetPrimitiveRestartEnable = (PFN_vkCmdSetPrimitiveRestartEnable)load(context, "vkCmdSetPrimitiveRestartEnable");
+ table->vkCmdSetPrimitiveTopology = (PFN_vkCmdSetPrimitiveTopology)load(context, "vkCmdSetPrimitiveTopology");
+ table->vkCmdSetRasterizerDiscardEnable = (PFN_vkCmdSetRasterizerDiscardEnable)load(context, "vkCmdSetRasterizerDiscardEnable");
+ table->vkCmdSetScissorWithCount = (PFN_vkCmdSetScissorWithCount)load(context, "vkCmdSetScissorWithCount");
+ table->vkCmdSetStencilOp = (PFN_vkCmdSetStencilOp)load(context, "vkCmdSetStencilOp");
+ table->vkCmdSetStencilTestEnable = (PFN_vkCmdSetStencilTestEnable)load(context, "vkCmdSetStencilTestEnable");
+ table->vkCmdSetViewportWithCount = (PFN_vkCmdSetViewportWithCount)load(context, "vkCmdSetViewportWithCount");
+ table->vkCmdWaitEvents2 = (PFN_vkCmdWaitEvents2)load(context, "vkCmdWaitEvents2");
+ table->vkCmdWriteTimestamp2 = (PFN_vkCmdWriteTimestamp2)load(context, "vkCmdWriteTimestamp2");
+ table->vkCreatePrivateDataSlot = (PFN_vkCreatePrivateDataSlot)load(context, "vkCreatePrivateDataSlot");
+ table->vkDestroyPrivateDataSlot = (PFN_vkDestroyPrivateDataSlot)load(context, "vkDestroyPrivateDataSlot");
+ table->vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)load(context, "vkGetDeviceBufferMemoryRequirements");
+ table->vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)load(context, "vkGetDeviceImageMemoryRequirements");
+ table->vkGetDeviceImageSparseMemoryRequirements = (PFN_vkGetDeviceImageSparseMemoryRequirements)load(context, "vkGetDeviceImageSparseMemoryRequirements");
+ table->vkGetPrivateData = (PFN_vkGetPrivateData)load(context, "vkGetPrivateData");
+ table->vkQueueSubmit2 = (PFN_vkQueueSubmit2)load(context, "vkQueueSubmit2");
+ table->vkSetPrivateData = (PFN_vkSetPrivateData)load(context, "vkSetPrivateData");
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_AMD_buffer_marker)
table->vkCmdWriteBufferMarkerAMD = (PFN_vkCmdWriteBufferMarkerAMD)load(context, "vkCmdWriteBufferMarkerAMD");
#endif /* defined(VK_AMD_buffer_marker) */
@@ -1153,6 +1251,9 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context,
table->vkCmdDrawMultiEXT = (PFN_vkCmdDrawMultiEXT)load(context, "vkCmdDrawMultiEXT");
table->vkCmdDrawMultiIndexedEXT = (PFN_vkCmdDrawMultiIndexedEXT)load(context, "vkCmdDrawMultiIndexedEXT");
#endif /* defined(VK_EXT_multi_draw) */
+#if defined(VK_EXT_pageable_device_local_memory)
+ table->vkSetDeviceMemoryPriorityEXT = (PFN_vkSetDeviceMemoryPriorityEXT)load(context, "vkSetDeviceMemoryPriorityEXT");
+#endif /* defined(VK_EXT_pageable_device_local_memory) */
#if defined(VK_EXT_private_data)
table->vkCreatePrivateDataSlotEXT = (PFN_vkCreatePrivateDataSlotEXT)load(context, "vkCreatePrivateDataSlotEXT");
table->vkDestroyPrivateDataSlotEXT = (PFN_vkDestroyPrivateDataSlotEXT)load(context, "vkDestroyPrivateDataSlotEXT");
@@ -1179,6 +1280,13 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context,
#if defined(VK_EXT_vertex_input_dynamic_state)
table->vkCmdSetVertexInputEXT = (PFN_vkCmdSetVertexInputEXT)load(context, "vkCmdSetVertexInputEXT");
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
+#if defined(VK_FUCHSIA_buffer_collection)
+ table->vkCreateBufferCollectionFUCHSIA = (PFN_vkCreateBufferCollectionFUCHSIA)load(context, "vkCreateBufferCollectionFUCHSIA");
+ table->vkDestroyBufferCollectionFUCHSIA = (PFN_vkDestroyBufferCollectionFUCHSIA)load(context, "vkDestroyBufferCollectionFUCHSIA");
+ table->vkGetBufferCollectionPropertiesFUCHSIA = (PFN_vkGetBufferCollectionPropertiesFUCHSIA)load(context, "vkGetBufferCollectionPropertiesFUCHSIA");
+ table->vkSetBufferCollectionBufferConstraintsFUCHSIA = (PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA)load(context, "vkSetBufferCollectionBufferConstraintsFUCHSIA");
+ table->vkSetBufferCollectionImageConstraintsFUCHSIA = (PFN_vkSetBufferCollectionImageConstraintsFUCHSIA)load(context, "vkSetBufferCollectionImageConstraintsFUCHSIA");
+#endif /* defined(VK_FUCHSIA_buffer_collection) */
#if defined(VK_FUCHSIA_external_memory)
table->vkGetMemoryZirconHandleFUCHSIA = (PFN_vkGetMemoryZirconHandleFUCHSIA)load(context, "vkGetMemoryZirconHandleFUCHSIA");
table->vkGetMemoryZirconHandlePropertiesFUCHSIA = (PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA)load(context, "vkGetMemoryZirconHandlePropertiesFUCHSIA");
@@ -1274,6 +1382,10 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context,
table->vkCmdDrawIndexedIndirectCountKHR = (PFN_vkCmdDrawIndexedIndirectCountKHR)load(context, "vkCmdDrawIndexedIndirectCountKHR");
table->vkCmdDrawIndirectCountKHR = (PFN_vkCmdDrawIndirectCountKHR)load(context, "vkCmdDrawIndirectCountKHR");
#endif /* defined(VK_KHR_draw_indirect_count) */
+#if defined(VK_KHR_dynamic_rendering)
+ table->vkCmdBeginRenderingKHR = (PFN_vkCmdBeginRenderingKHR)load(context, "vkCmdBeginRenderingKHR");
+ table->vkCmdEndRenderingKHR = (PFN_vkCmdEndRenderingKHR)load(context, "vkCmdEndRenderingKHR");
+#endif /* defined(VK_KHR_dynamic_rendering) */
#if defined(VK_KHR_external_fence_fd)
table->vkGetFenceFdKHR = (PFN_vkGetFenceFdKHR)load(context, "vkGetFenceFdKHR");
table->vkImportFenceFdKHR = (PFN_vkImportFenceFdKHR)load(context, "vkImportFenceFdKHR");
@@ -1312,6 +1424,11 @@ static void volkGenLoadDeviceTable(struct VolkDeviceTable* table, void* context,
#if defined(VK_KHR_maintenance3)
table->vkGetDescriptorSetLayoutSupportKHR = (PFN_vkGetDescriptorSetLayoutSupportKHR)load(context, "vkGetDescriptorSetLayoutSupportKHR");
#endif /* defined(VK_KHR_maintenance3) */
+#if defined(VK_KHR_maintenance4)
+ table->vkGetDeviceBufferMemoryRequirementsKHR = (PFN_vkGetDeviceBufferMemoryRequirementsKHR)load(context, "vkGetDeviceBufferMemoryRequirementsKHR");
+ table->vkGetDeviceImageMemoryRequirementsKHR = (PFN_vkGetDeviceImageMemoryRequirementsKHR)load(context, "vkGetDeviceImageMemoryRequirementsKHR");
+ table->vkGetDeviceImageSparseMemoryRequirementsKHR = (PFN_vkGetDeviceImageSparseMemoryRequirementsKHR)load(context, "vkGetDeviceImageSparseMemoryRequirementsKHR");
+#endif /* defined(VK_KHR_maintenance4) */
#if defined(VK_KHR_performance_query)
table->vkAcquireProfilingLockKHR = (PFN_vkAcquireProfilingLockKHR)load(context, "vkAcquireProfilingLockKHR");
table->vkReleaseProfilingLockKHR = (PFN_vkReleaseProfilingLockKHR)load(context, "vkReleaseProfilingLockKHR");
@@ -1658,6 +1775,45 @@ PFN_vkResetQueryPool vkResetQueryPool;
PFN_vkSignalSemaphore vkSignalSemaphore;
PFN_vkWaitSemaphores vkWaitSemaphores;
#endif /* defined(VK_VERSION_1_2) */
+#if defined(VK_VERSION_1_3)
+PFN_vkCmdBeginRendering vkCmdBeginRendering;
+PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2;
+PFN_vkCmdBlitImage2 vkCmdBlitImage2;
+PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2;
+PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2;
+PFN_vkCmdCopyImage2 vkCmdCopyImage2;
+PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2;
+PFN_vkCmdEndRendering vkCmdEndRendering;
+PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2;
+PFN_vkCmdResetEvent2 vkCmdResetEvent2;
+PFN_vkCmdResolveImage2 vkCmdResolveImage2;
+PFN_vkCmdSetCullMode vkCmdSetCullMode;
+PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable;
+PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable;
+PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp;
+PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable;
+PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable;
+PFN_vkCmdSetEvent2 vkCmdSetEvent2;
+PFN_vkCmdSetFrontFace vkCmdSetFrontFace;
+PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable;
+PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology;
+PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable;
+PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount;
+PFN_vkCmdSetStencilOp vkCmdSetStencilOp;
+PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable;
+PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount;
+PFN_vkCmdWaitEvents2 vkCmdWaitEvents2;
+PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2;
+PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot;
+PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot;
+PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements;
+PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements;
+PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements;
+PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties;
+PFN_vkGetPrivateData vkGetPrivateData;
+PFN_vkQueueSubmit2 vkQueueSubmit2;
+PFN_vkSetPrivateData vkSetPrivateData;
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_AMD_buffer_marker)
PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD;
#endif /* defined(VK_AMD_buffer_marker) */
@@ -1792,6 +1948,9 @@ PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT;
PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT;
#endif /* defined(VK_EXT_multi_draw) */
+#if defined(VK_EXT_pageable_device_local_memory)
+PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT;
+#endif /* defined(VK_EXT_pageable_device_local_memory) */
#if defined(VK_EXT_private_data)
PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
@@ -1822,6 +1981,13 @@ PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT;
#if defined(VK_EXT_vertex_input_dynamic_state)
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
+#if defined(VK_FUCHSIA_buffer_collection)
+PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA;
+PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA;
+PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA;
+PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA;
+PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA;
+#endif /* defined(VK_FUCHSIA_buffer_collection) */
#if defined(VK_FUCHSIA_external_memory)
PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA;
PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA;
@@ -1938,6 +2104,10 @@ PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR;
PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR;
PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR;
#endif /* defined(VK_KHR_draw_indirect_count) */
+#if defined(VK_KHR_dynamic_rendering)
+PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR;
+PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR;
+#endif /* defined(VK_KHR_dynamic_rendering) */
#if defined(VK_KHR_external_fence_capabilities)
PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR;
#endif /* defined(VK_KHR_external_fence_capabilities) */
@@ -2005,6 +2175,11 @@ PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR;
#if defined(VK_KHR_maintenance3)
PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
#endif /* defined(VK_KHR_maintenance3) */
+#if defined(VK_KHR_maintenance4)
+PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR;
+PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR;
+PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR;
+#endif /* defined(VK_KHR_maintenance4) */
#if defined(VK_KHR_performance_query)
PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR;
PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
diff --git a/thirdparty/volk/volk.h b/thirdparty/volk/volk.h
index 2e292ca114..cdeedfc5ff 100644
--- a/thirdparty/volk/volk.h
+++ b/thirdparty/volk/volk.h
@@ -15,7 +15,7 @@
#endif
/* VOLK_GENERATE_VERSION_DEFINE */
-#define VOLK_HEADER_VERSION 190
+#define VOLK_HEADER_VERSION 204
/* VOLK_GENERATE_VERSION_DEFINE */
#ifndef VK_NO_PROTOTYPES
@@ -285,6 +285,44 @@ struct VolkDeviceTable
PFN_vkSignalSemaphore vkSignalSemaphore;
PFN_vkWaitSemaphores vkWaitSemaphores;
#endif /* defined(VK_VERSION_1_2) */
+#if defined(VK_VERSION_1_3)
+ PFN_vkCmdBeginRendering vkCmdBeginRendering;
+ PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2;
+ PFN_vkCmdBlitImage2 vkCmdBlitImage2;
+ PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2;
+ PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2;
+ PFN_vkCmdCopyImage2 vkCmdCopyImage2;
+ PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2;
+ PFN_vkCmdEndRendering vkCmdEndRendering;
+ PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2;
+ PFN_vkCmdResetEvent2 vkCmdResetEvent2;
+ PFN_vkCmdResolveImage2 vkCmdResolveImage2;
+ PFN_vkCmdSetCullMode vkCmdSetCullMode;
+ PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable;
+ PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable;
+ PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp;
+ PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable;
+ PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable;
+ PFN_vkCmdSetEvent2 vkCmdSetEvent2;
+ PFN_vkCmdSetFrontFace vkCmdSetFrontFace;
+ PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable;
+ PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology;
+ PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable;
+ PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount;
+ PFN_vkCmdSetStencilOp vkCmdSetStencilOp;
+ PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable;
+ PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount;
+ PFN_vkCmdWaitEvents2 vkCmdWaitEvents2;
+ PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2;
+ PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot;
+ PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot;
+ PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements;
+ PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements;
+ PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements;
+ PFN_vkGetPrivateData vkGetPrivateData;
+ PFN_vkQueueSubmit2 vkQueueSubmit2;
+ PFN_vkSetPrivateData vkSetPrivateData;
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_AMD_buffer_marker)
PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD;
#endif /* defined(VK_AMD_buffer_marker) */
@@ -375,6 +413,9 @@ struct VolkDeviceTable
PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT;
PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT;
#endif /* defined(VK_EXT_multi_draw) */
+#if defined(VK_EXT_pageable_device_local_memory)
+ PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT;
+#endif /* defined(VK_EXT_pageable_device_local_memory) */
#if defined(VK_EXT_private_data)
PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
@@ -401,6 +442,13 @@ struct VolkDeviceTable
#if defined(VK_EXT_vertex_input_dynamic_state)
PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
+#if defined(VK_FUCHSIA_buffer_collection)
+ PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA;
+ PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA;
+ PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA;
+ PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA;
+ PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA;
+#endif /* defined(VK_FUCHSIA_buffer_collection) */
#if defined(VK_FUCHSIA_external_memory)
PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA;
PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA;
@@ -496,6 +544,10 @@ struct VolkDeviceTable
PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR;
PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR;
#endif /* defined(VK_KHR_draw_indirect_count) */
+#if defined(VK_KHR_dynamic_rendering)
+ PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR;
+ PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR;
+#endif /* defined(VK_KHR_dynamic_rendering) */
#if defined(VK_KHR_external_fence_fd)
PFN_vkGetFenceFdKHR vkGetFenceFdKHR;
PFN_vkImportFenceFdKHR vkImportFenceFdKHR;
@@ -534,6 +586,11 @@ struct VolkDeviceTable
#if defined(VK_KHR_maintenance3)
PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
#endif /* defined(VK_KHR_maintenance3) */
+#if defined(VK_KHR_maintenance4)
+ PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR;
+ PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR;
+ PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR;
+#endif /* defined(VK_KHR_maintenance4) */
#if defined(VK_KHR_performance_query)
PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR;
PFN_vkReleaseProfilingLockKHR vkReleaseProfilingLockKHR;
@@ -872,6 +929,45 @@ extern PFN_vkResetQueryPool vkResetQueryPool;
extern PFN_vkSignalSemaphore vkSignalSemaphore;
extern PFN_vkWaitSemaphores vkWaitSemaphores;
#endif /* defined(VK_VERSION_1_2) */
+#if defined(VK_VERSION_1_3)
+extern PFN_vkCmdBeginRendering vkCmdBeginRendering;
+extern PFN_vkCmdBindVertexBuffers2 vkCmdBindVertexBuffers2;
+extern PFN_vkCmdBlitImage2 vkCmdBlitImage2;
+extern PFN_vkCmdCopyBuffer2 vkCmdCopyBuffer2;
+extern PFN_vkCmdCopyBufferToImage2 vkCmdCopyBufferToImage2;
+extern PFN_vkCmdCopyImage2 vkCmdCopyImage2;
+extern PFN_vkCmdCopyImageToBuffer2 vkCmdCopyImageToBuffer2;
+extern PFN_vkCmdEndRendering vkCmdEndRendering;
+extern PFN_vkCmdPipelineBarrier2 vkCmdPipelineBarrier2;
+extern PFN_vkCmdResetEvent2 vkCmdResetEvent2;
+extern PFN_vkCmdResolveImage2 vkCmdResolveImage2;
+extern PFN_vkCmdSetCullMode vkCmdSetCullMode;
+extern PFN_vkCmdSetDepthBiasEnable vkCmdSetDepthBiasEnable;
+extern PFN_vkCmdSetDepthBoundsTestEnable vkCmdSetDepthBoundsTestEnable;
+extern PFN_vkCmdSetDepthCompareOp vkCmdSetDepthCompareOp;
+extern PFN_vkCmdSetDepthTestEnable vkCmdSetDepthTestEnable;
+extern PFN_vkCmdSetDepthWriteEnable vkCmdSetDepthWriteEnable;
+extern PFN_vkCmdSetEvent2 vkCmdSetEvent2;
+extern PFN_vkCmdSetFrontFace vkCmdSetFrontFace;
+extern PFN_vkCmdSetPrimitiveRestartEnable vkCmdSetPrimitiveRestartEnable;
+extern PFN_vkCmdSetPrimitiveTopology vkCmdSetPrimitiveTopology;
+extern PFN_vkCmdSetRasterizerDiscardEnable vkCmdSetRasterizerDiscardEnable;
+extern PFN_vkCmdSetScissorWithCount vkCmdSetScissorWithCount;
+extern PFN_vkCmdSetStencilOp vkCmdSetStencilOp;
+extern PFN_vkCmdSetStencilTestEnable vkCmdSetStencilTestEnable;
+extern PFN_vkCmdSetViewportWithCount vkCmdSetViewportWithCount;
+extern PFN_vkCmdWaitEvents2 vkCmdWaitEvents2;
+extern PFN_vkCmdWriteTimestamp2 vkCmdWriteTimestamp2;
+extern PFN_vkCreatePrivateDataSlot vkCreatePrivateDataSlot;
+extern PFN_vkDestroyPrivateDataSlot vkDestroyPrivateDataSlot;
+extern PFN_vkGetDeviceBufferMemoryRequirements vkGetDeviceBufferMemoryRequirements;
+extern PFN_vkGetDeviceImageMemoryRequirements vkGetDeviceImageMemoryRequirements;
+extern PFN_vkGetDeviceImageSparseMemoryRequirements vkGetDeviceImageSparseMemoryRequirements;
+extern PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties;
+extern PFN_vkGetPrivateData vkGetPrivateData;
+extern PFN_vkQueueSubmit2 vkQueueSubmit2;
+extern PFN_vkSetPrivateData vkSetPrivateData;
+#endif /* defined(VK_VERSION_1_3) */
#if defined(VK_AMD_buffer_marker)
extern PFN_vkCmdWriteBufferMarkerAMD vkCmdWriteBufferMarkerAMD;
#endif /* defined(VK_AMD_buffer_marker) */
@@ -1006,6 +1102,9 @@ extern PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
extern PFN_vkCmdDrawMultiEXT vkCmdDrawMultiEXT;
extern PFN_vkCmdDrawMultiIndexedEXT vkCmdDrawMultiIndexedEXT;
#endif /* defined(VK_EXT_multi_draw) */
+#if defined(VK_EXT_pageable_device_local_memory)
+extern PFN_vkSetDeviceMemoryPriorityEXT vkSetDeviceMemoryPriorityEXT;
+#endif /* defined(VK_EXT_pageable_device_local_memory) */
#if defined(VK_EXT_private_data)
extern PFN_vkCreatePrivateDataSlotEXT vkCreatePrivateDataSlotEXT;
extern PFN_vkDestroyPrivateDataSlotEXT vkDestroyPrivateDataSlotEXT;
@@ -1036,6 +1135,13 @@ extern PFN_vkMergeValidationCachesEXT vkMergeValidationCachesEXT;
#if defined(VK_EXT_vertex_input_dynamic_state)
extern PFN_vkCmdSetVertexInputEXT vkCmdSetVertexInputEXT;
#endif /* defined(VK_EXT_vertex_input_dynamic_state) */
+#if defined(VK_FUCHSIA_buffer_collection)
+extern PFN_vkCreateBufferCollectionFUCHSIA vkCreateBufferCollectionFUCHSIA;
+extern PFN_vkDestroyBufferCollectionFUCHSIA vkDestroyBufferCollectionFUCHSIA;
+extern PFN_vkGetBufferCollectionPropertiesFUCHSIA vkGetBufferCollectionPropertiesFUCHSIA;
+extern PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA vkSetBufferCollectionBufferConstraintsFUCHSIA;
+extern PFN_vkSetBufferCollectionImageConstraintsFUCHSIA vkSetBufferCollectionImageConstraintsFUCHSIA;
+#endif /* defined(VK_FUCHSIA_buffer_collection) */
#if defined(VK_FUCHSIA_external_memory)
extern PFN_vkGetMemoryZirconHandleFUCHSIA vkGetMemoryZirconHandleFUCHSIA;
extern PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA vkGetMemoryZirconHandlePropertiesFUCHSIA;
@@ -1152,6 +1258,10 @@ extern PFN_vkCreateSharedSwapchainsKHR vkCreateSharedSwapchainsKHR;
extern PFN_vkCmdDrawIndexedIndirectCountKHR vkCmdDrawIndexedIndirectCountKHR;
extern PFN_vkCmdDrawIndirectCountKHR vkCmdDrawIndirectCountKHR;
#endif /* defined(VK_KHR_draw_indirect_count) */
+#if defined(VK_KHR_dynamic_rendering)
+extern PFN_vkCmdBeginRenderingKHR vkCmdBeginRenderingKHR;
+extern PFN_vkCmdEndRenderingKHR vkCmdEndRenderingKHR;
+#endif /* defined(VK_KHR_dynamic_rendering) */
#if defined(VK_KHR_external_fence_capabilities)
extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR vkGetPhysicalDeviceExternalFencePropertiesKHR;
#endif /* defined(VK_KHR_external_fence_capabilities) */
@@ -1219,6 +1329,11 @@ extern PFN_vkTrimCommandPoolKHR vkTrimCommandPoolKHR;
#if defined(VK_KHR_maintenance3)
extern PFN_vkGetDescriptorSetLayoutSupportKHR vkGetDescriptorSetLayoutSupportKHR;
#endif /* defined(VK_KHR_maintenance3) */
+#if defined(VK_KHR_maintenance4)
+extern PFN_vkGetDeviceBufferMemoryRequirementsKHR vkGetDeviceBufferMemoryRequirementsKHR;
+extern PFN_vkGetDeviceImageMemoryRequirementsKHR vkGetDeviceImageMemoryRequirementsKHR;
+extern PFN_vkGetDeviceImageSparseMemoryRequirementsKHR vkGetDeviceImageSparseMemoryRequirementsKHR;
+#endif /* defined(VK_KHR_maintenance4) */
#if defined(VK_KHR_performance_query)
extern PFN_vkAcquireProfilingLockKHR vkAcquireProfilingLockKHR;
extern PFN_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR;
diff --git a/thirdparty/vulkan/patches/VMA-use-volk.patch b/thirdparty/vulkan/patches/VMA-use-volk.patch
index 81bfcccd89..eebe0c1bc3 100644
--- a/thirdparty/vulkan/patches/VMA-use-volk.patch
+++ b/thirdparty/vulkan/patches/VMA-use-volk.patch
@@ -1,9 +1,9 @@
diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h
-index 65d6243419..9890f20f7c 100644
+index 44affc5ca4..d96f2dacc0 100644
--- a/thirdparty/vulkan/vk_mem_alloc.h
+++ b/thirdparty/vulkan/vk_mem_alloc.h
-@@ -2063,7 +2063,11 @@ available through VmaAllocatorCreateInfo::pRecordSettings.
- #endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES
+@@ -127,7 +127,11 @@ extern "C" {
+ #endif
#ifndef VULKAN_H_
- #include <vulkan/vulkan.h>
diff --git a/thirdparty/vulkan/vk_mem_alloc.h b/thirdparty/vulkan/vk_mem_alloc.h
index 9890f20f7c..184ee005d8 100644
--- a/thirdparty/vulkan/vk_mem_alloc.h
+++ b/thirdparty/vulkan/vk_mem_alloc.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved.
+// Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -25,12 +25,12 @@
/** \mainpage Vulkan Memory Allocator
-<b>Version 3.0.0-development</b> (2021-06-21)
+<b>Version 3.0.1 (2022-05-26)</b>
-Copyright (c) 2017-2021 Advanced Micro Devices, Inc. All rights reserved. \n
+Copyright (c) 2017-2022 Advanced Micro Devices, Inc. All rights reserved. \n
License: MIT
-Documentation of all members: vk_mem_alloc.h
+<b>API documentation divided into groups:</b> [Modules](modules.html)
\section main_table_of_contents Table of contents
@@ -49,7 +49,6 @@ Documentation of all members: vk_mem_alloc.h
- [Mapping functions](@ref memory_mapping_mapping_functions)
- [Persistently mapped memory](@ref memory_mapping_persistently_mapped_memory)
- [Cache flush and invalidate](@ref memory_mapping_cache_control)
- - [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable)
- \subpage staying_within_budget
- [Querying for budget](@ref staying_within_budget_querying_for_budget)
- [Controlling memory usage](@ref staying_within_budget_controlling_memory_usage)
@@ -61,1976 +60,93 @@ Documentation of all members: vk_mem_alloc.h
- [Stack](@ref linear_algorithm_stack)
- [Double stack](@ref linear_algorithm_double_stack)
- [Ring buffer](@ref linear_algorithm_ring_buffer)
- - [Buddy allocation algorithm](@ref buddy_algorithm)
- \subpage defragmentation
- - [Defragmenting CPU memory](@ref defragmentation_cpu)
- - [Defragmenting GPU memory](@ref defragmentation_gpu)
- - [Additional notes](@ref defragmentation_additional_notes)
- - [Writing custom allocation algorithm](@ref defragmentation_custom_algorithm)
- - \subpage lost_allocations
- \subpage statistics
- [Numeric statistics](@ref statistics_numeric_statistics)
- [JSON dump](@ref statistics_json_dump)
- \subpage allocation_annotation
- [Allocation user data](@ref allocation_user_data)
- [Allocation names](@ref allocation_names)
+ - \subpage virtual_allocator
- \subpage debugging_memory_usage
- [Memory initialization](@ref debugging_memory_usage_initialization)
- [Margins](@ref debugging_memory_usage_margins)
- [Corruption detection](@ref debugging_memory_usage_corruption_detection)
- - \subpage record_and_replay
+ - \subpage opengl_interop
- \subpage usage_patterns
- - [Common mistakes](@ref usage_patterns_common_mistakes)
- - [Simple patterns](@ref usage_patterns_simple)
- - [Advanced patterns](@ref usage_patterns_advanced)
+ - [GPU-only resource](@ref usage_patterns_gpu_only)
+ - [Staging copy for upload](@ref usage_patterns_staging_copy_upload)
+ - [Readback](@ref usage_patterns_readback)
+ - [Advanced data uploading](@ref usage_patterns_advanced_data_uploading)
+ - [Other use cases](@ref usage_patterns_other_use_cases)
- \subpage configuration
- [Pointers to Vulkan functions](@ref config_Vulkan_functions)
- [Custom host memory allocator](@ref custom_memory_allocator)
- [Device memory allocation callbacks](@ref allocation_callbacks)
- [Device heap memory limit](@ref heap_memory_limit)
- - \subpage vk_khr_dedicated_allocation
- - \subpage enabling_buffer_device_address
- - \subpage vk_amd_device_coherent_memory
+- <b>Extension support</b>
+ - \subpage vk_khr_dedicated_allocation
+ - \subpage enabling_buffer_device_address
+ - \subpage vk_ext_memory_priority
+ - \subpage vk_amd_device_coherent_memory
- \subpage general_considerations
- [Thread safety](@ref general_considerations_thread_safety)
+ - [Versioning and compatibility](@ref general_considerations_versioning_and_compatibility)
- [Validation layer warnings](@ref general_considerations_validation_layer_warnings)
- [Allocation algorithm](@ref general_considerations_allocation_algorithm)
- [Features not supported](@ref general_considerations_features_not_supported)
\section main_see_also See also
-- [Product page on GPUOpen](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
-- [Source repository on GitHub](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+- [**Product page on GPUOpen**](https://gpuopen.com/gaming-product/vulkan-memory-allocator/)
+- [**Source repository on GitHub**](https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator)
+\defgroup group_init Library initialization
+\brief API elements related to the initialization and management of the entire library, especially #VmaAllocator object.
+\defgroup group_alloc Memory allocation
-\page quick_start Quick start
-
-\section quick_start_project_setup Project setup
-
-Vulkan Memory Allocator comes in form of a "stb-style" single header file.
-You don't need to build it as a separate library project.
-You can add this file directly to your project and submit it to code repository next to your other source files.
-
-"Single header" doesn't mean that everything is contained in C/C++ declarations,
-like it tends to be in case of inline functions or C++ templates.
-It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.
-If you don't do it properly, you will get linker errors.
-
-To do it properly:
-
--# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library.
- This includes declarations of all members of the library.
--# In exactly one CPP file define following macro before this include.
- It enables also internal definitions.
-
-\code
-#define VMA_IMPLEMENTATION
-#include "vk_mem_alloc.h"
-\endcode
-
-It may be a good idea to create dedicated CPP file just for this purpose.
-
-Note on language: This library is written in C++, but has C-compatible interface.
-Thus you can include and use vk_mem_alloc.h in C or C++ code, but full
-implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.
-
-Please note that this library includes header `<vulkan/vulkan.h>`, which in turn
-includes `<windows.h>` on Windows. If you need some specific macros defined
-before including these headers (like `WIN32_LEAN_AND_MEAN` or
-`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define
-them before every `#include` of this library.
-
-You may need to configure the way you import Vulkan functions.
-
-- By default, VMA assumes you you link statically with Vulkan API. If this is not the case,
- `#define VMA_STATIC_VULKAN_FUNCTIONS 0` before `#include` of the VMA implementation and use another way.
-- You can `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1` and make sure `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` globals are defined.
- All the remaining Vulkan functions will be fetched automatically.
-- Finally, you can provide your own pointers to all Vulkan functions needed by VMA using structure member
- VmaAllocatorCreateInfo::pVulkanFunctions, if you fetched them in some custom way e.g. using some loader like [Volk](https://github.com/zeux/volk).
-
-
-\section quick_start_initialization Initialization
-
-At program startup:
-
--# Initialize Vulkan to have `VkPhysicalDevice`, `VkDevice` and `VkInstance` object.
--# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by
- calling vmaCreateAllocator().
-
-\code
-VmaAllocatorCreateInfo allocatorInfo = {};
-allocatorInfo.vulkanApiVersion = VK_API_VERSION_1_2;
-allocatorInfo.physicalDevice = physicalDevice;
-allocatorInfo.device = device;
-allocatorInfo.instance = instance;
-
-VmaAllocator allocator;
-vmaCreateAllocator(&allocatorInfo, &allocator);
-\endcode
-
-Only members `physicalDevice`, `device`, `instance` are required.
-However, you should inform the library which Vulkan version do you use by setting
-VmaAllocatorCreateInfo::vulkanApiVersion and which extensions did you enable
-by setting VmaAllocatorCreateInfo::flags (like #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT for VK_KHR_buffer_device_address).
-Otherwise, VMA would use only features of Vulkan 1.0 core with no extensions.
-
-
-\section quick_start_resource_allocation Resource allocation
-
-When you want to create a buffer or image:
-
--# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.
--# Fill VmaAllocationCreateInfo structure.
--# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory
- already allocated and bound to it.
-
-\code
-VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufferInfo.size = 65536;
-bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-VmaAllocationCreateInfo allocInfo = {};
-allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-
-VkBuffer buffer;
-VmaAllocation allocation;
-vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
-\endcode
-
-Don't forget to destroy your objects when no longer needed:
-
-\code
-vmaDestroyBuffer(allocator, buffer, allocation);
-vmaDestroyAllocator(allocator);
-\endcode
-
-
-\page choosing_memory_type Choosing memory type
-
-Physical devices in Vulkan support various combinations of memory heaps and
-types. Help with choosing correct and optimal memory type for your specific
-resource is one of the key features of this library. You can use it by filling
-appropriate members of VmaAllocationCreateInfo structure, as described below.
-You can also combine multiple methods.
-
--# If you just want to find memory type index that meets your requirements, you
- can use function: vmaFindMemoryTypeIndex(), vmaFindMemoryTypeIndexForBufferInfo(),
- vmaFindMemoryTypeIndexForImageInfo().
--# If you want to allocate a region of device memory without association with any
- specific image or buffer, you can use function vmaAllocateMemory(). Usage of
- this function is not recommended and usually not needed.
- vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once,
- which may be useful for sparse binding.
--# If you already have a buffer or an image created, you want to allocate memory
- for it and then you will bind it yourself, you can use function
- vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().
- For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory()
- or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2().
--# If you want to create a buffer or an image, allocate memory for it and bind
- them together, all in one call, you can use function vmaCreateBuffer(),
- vmaCreateImage(). This is the easiest and recommended way to use this library.
-
-When using 3. or 4., the library internally queries Vulkan for memory types
-supported for that buffer or image (function `vkGetBufferMemoryRequirements()`)
-and uses only one of these types.
-
-If no memory type can be found that meets all the requirements, these functions
-return `VK_ERROR_FEATURE_NOT_PRESENT`.
-
-You can leave VmaAllocationCreateInfo structure completely filled with zeros.
-It means no requirements are specified for memory type.
-It is valid, although not very useful.
-
-\section choosing_memory_type_usage Usage
-
-The easiest way to specify memory requirements is to fill member
-VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.
-It defines high level, common usage types.
-For more details, see description of this enum.
-
-For example, if you want to create a uniform buffer that will be filled using
-transfer only once or infrequently and used for rendering every frame, you can
-do it using following code:
-
-\code
-VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufferInfo.size = 65536;
-bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-VmaAllocationCreateInfo allocInfo = {};
-allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-
-VkBuffer buffer;
-VmaAllocation allocation;
-vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
-\endcode
-
-\section choosing_memory_type_required_preferred_flags Required and preferred flags
-
-You can specify more detailed requirements by filling members
-VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags
-with a combination of bits from enum `VkMemoryPropertyFlags`. For example,
-if you want to create a buffer that will be persistently mapped on host (so it
-must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,
-use following code:
-
-\code
-VmaAllocationCreateInfo allocInfo = {};
-allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
-allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
-allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
-
-VkBuffer buffer;
-VmaAllocation allocation;
-vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
-\endcode
-
-A memory type is chosen that has all the required flags and as many preferred
-flags set as possible.
-
-If you use VmaAllocationCreateInfo::usage, it is just internally converted to
-a set of required and preferred flags.
-
-\section choosing_memory_type_explicit_memory_types Explicit memory types
-
-If you inspected memory types available on the physical device and you have
-a preference for memory types that you want to use, you can fill member
-VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set
-means that a memory type with that index is allowed to be used for the
-allocation. Special value 0, just like `UINT32_MAX`, means there are no
-restrictions to memory type index.
-
-Please note that this member is NOT just a memory type index.
-Still you can use it to choose just one, specific memory type.
-For example, if you already determined that your buffer should be created in
-memory type 2, use following code:
-
-\code
-uint32_t memoryTypeIndex = 2;
-
-VmaAllocationCreateInfo allocInfo = {};
-allocInfo.memoryTypeBits = 1u << memoryTypeIndex;
-
-VkBuffer buffer;
-VmaAllocation allocation;
-vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
-\endcode
-
-
-\section choosing_memory_type_custom_memory_pools Custom memory pools
-
-If you allocate from custom memory pool, all the ways of specifying memory
-requirements described above are not applicable and the aforementioned members
-of VmaAllocationCreateInfo structure are ignored. Memory type is selected
-explicitly when creating the pool and then used to make all the allocations from
-that pool. For further details, see \ref custom_memory_pools.
-
-\section choosing_memory_type_dedicated_allocations Dedicated allocations
-
-Memory for allocations is reserved out of larger block of `VkDeviceMemory`
-allocated from Vulkan internally. That's the main feature of this whole library.
-You can still request a separate memory block to be created for an allocation,
-just like you would do in a trivial solution without using any allocator.
-In that case, a buffer or image is always bound to that memory at offset 0.
-This is called a "dedicated allocation".
-You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
-The library can also internally decide to use dedicated allocation in some cases, e.g.:
-
-- When the size of the allocation is large.
-- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled
- and it reports that dedicated allocation is required or recommended for the resource.
-- When allocation of next big memory block fails due to not enough device memory,
- but allocation with the exact requested size succeeds.
-
-
-\page memory_mapping Memory mapping
-
-To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,
-to be able to read from it or write to it in CPU code.
-Mapping is possible only of memory allocated from a memory type that has
-`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.
-Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.
-You can use them directly with memory allocated by this library,
-but it is not recommended because of following issue:
-Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.
-This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.
-Because of this, Vulkan Memory Allocator provides following facilities:
-
-\section memory_mapping_mapping_functions Mapping functions
-
-The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().
-They are safer and more convenient to use than standard Vulkan functions.
-You can map an allocation multiple times simultaneously - mapping is reference-counted internally.
-You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.
-The way it's implemented is that the library always maps entire memory block, not just region of the allocation.
-For further details, see description of vmaMapMemory() function.
-Example:
-
-\code
-// Having these objects initialized:
-
-struct ConstantBuffer
-{
- ...
-};
-ConstantBuffer constantBufferData;
-
-VmaAllocator allocator;
-VkBuffer constantBuffer;
-VmaAllocation constantBufferAllocation;
-
-// You can map and fill your buffer using following code:
-
-void* mappedData;
-vmaMapMemory(allocator, constantBufferAllocation, &mappedData);
-memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
-vmaUnmapMemory(allocator, constantBufferAllocation);
-\endcode
-
-When mapping, you may see a warning from Vulkan validation layer similar to this one:
-
-<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>
-
-It happens because the library maps entire `VkDeviceMemory` block, where different
-types of images and buffers may end up together, especially on GPUs with unified memory like Intel.
-You can safely ignore it if you are sure you access only memory of the intended
-object that you wanted to map.
-
-
-\section memory_mapping_persistently_mapped_memory Persistently mapped memory
-
-Kepping your memory persistently mapped is generally OK in Vulkan.
-You don't need to unmap it before using its data on the GPU.
-The library provides a special feature designed for that:
-Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in
-VmaAllocationCreateInfo::flags stay mapped all the time,
-so you can just access CPU pointer to it any time
-without a need to call any "map" or "unmap" function.
-Example:
-
-\code
-VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufCreateInfo.size = sizeof(ConstantBuffer);
-bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
-allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
-
-VkBuffer buf;
-VmaAllocation alloc;
-VmaAllocationInfo allocInfo;
-vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
-
-// Buffer is already mapped. You can access its memory.
-memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
-\endcode
-
-There are some exceptions though, when you should consider mapping memory only for a short period of time:
-
-- When operating system is Windows 7 or 8.x (Windows 10 is not affected because it uses WDDM2),
- device is discrete AMD GPU,
- and memory type is the special 256 MiB pool of `DEVICE_LOCAL + HOST_VISIBLE` memory
- (selected when you use #VMA_MEMORY_USAGE_CPU_TO_GPU),
- then whenever a memory block allocated from this memory type stays mapped
- for the time of any call to `vkQueueSubmit()` or `vkQueuePresentKHR()`, this
- block is migrated by WDDM to system RAM, which degrades performance. It doesn't
- matter if that particular memory block is actually used by the command buffer
- being submitted.
-- Keeping many large memory blocks mapped may impact performance or stability of some debugging tools.
-
-\section memory_mapping_cache_control Cache flush and invalidate
-
-Memory in Vulkan doesn't need to be unmapped before using it on GPU,
-but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
-you need to manually **invalidate** cache before reading of mapped pointer
-and **flush** cache after writing to mapped pointer.
-Map/unmap operations don't do that automatically.
-Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
-`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
-functions that refer to given allocation object: vmaFlushAllocation(),
-vmaInvalidateAllocation(),
-or multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations().
-
-Regions of memory specified for flush/invalidate must be aligned to
-`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
-In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
-within blocks are aligned to this value, so their offsets are always multiply of
-`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
-
-Please note that memory allocated with #VMA_MEMORY_USAGE_CPU_ONLY is guaranteed to be `HOST_COHERENT`.
-
-Also, Windows drivers from all 3 **PC** GPU vendors (AMD, Intel, NVIDIA)
-currently provide `HOST_COHERENT` flag on all memory types that are
-`HOST_VISIBLE`, so on this platform you may not need to bother.
-
-\section memory_mapping_finding_if_memory_mappable Finding out if memory is mappable
-
-It may happen that your allocation ends up in memory that is `HOST_VISIBLE` (available for mapping)
-despite it wasn't explicitly requested.
-For example, application may work on integrated graphics with unified memory (like Intel) or
-allocation from video memory might have failed, so the library chose system memory as fallback.
-
-You can detect this case and map such allocation to access its memory on CPU directly,
-instead of launching a transfer operation.
-In order to do that: inspect `allocInfo.memoryType`, call vmaGetMemoryTypeProperties(),
-and look for `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag in properties of that memory type.
-
-\code
-VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufCreateInfo.size = sizeof(ConstantBuffer);
-bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
-
-VkBuffer buf;
-VmaAllocation alloc;
-VmaAllocationInfo allocInfo;
-vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
-
-VkMemoryPropertyFlags memFlags;
-vmaGetMemoryTypeProperties(allocator, allocInfo.memoryType, &memFlags);
-if((memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
-{
- // Allocation ended up in mappable memory. You can map it and access it directly.
- void* mappedData;
- vmaMapMemory(allocator, alloc, &mappedData);
- memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
- vmaUnmapMemory(allocator, alloc);
-}
-else
-{
- // Allocation ended up in non-mappable memory.
- // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
-}
-\endcode
-
-You can even use #VMA_ALLOCATION_CREATE_MAPPED_BIT flag while creating allocations
-that are not necessarily `HOST_VISIBLE` (e.g. using #VMA_MEMORY_USAGE_GPU_ONLY).
-If the allocation ends up in memory type that is `HOST_VISIBLE`, it will be persistently mapped and you can use it directly.
-If not, the flag is just ignored.
-Example:
-
-\code
-VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufCreateInfo.size = sizeof(ConstantBuffer);
-bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-allocCreateInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT;
-
-VkBuffer buf;
-VmaAllocation alloc;
-VmaAllocationInfo allocInfo;
-vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
-
-if(allocInfo.pMappedData != nullptr)
-{
- // Allocation ended up in mappable memory.
- // It's persistently mapped. You can access it directly.
- memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
-}
-else
-{
- // Allocation ended up in non-mappable memory.
- // You need to create CPU-side buffer in VMA_MEMORY_USAGE_CPU_ONLY and make a transfer.
-}
-\endcode
-
-
-\page staying_within_budget Staying within budget
-
-When developing a graphics-intensive game or program, it is important to avoid allocating
-more GPU memory than it's physically available. When the memory is over-committed,
-various bad things can happen, depending on the specific GPU, graphics driver, and
-operating system:
-
-- It may just work without any problems.
-- The application may slow down because some memory blocks are moved to system RAM
- and the GPU has to access them through PCI Express bus.
-- A new allocation may take very long time to complete, even few seconds, and possibly
- freeze entire system.
-- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
-- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`
- returned somewhere later.
-
-\section staying_within_budget_querying_for_budget Querying for budget
-
-To query for current memory usage and available budget, use function vmaGetBudget().
-Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.
-
-Please note that this function returns different information and works faster than
-vmaCalculateStats(). vmaGetBudget() can be called every frame or even before every
-allocation, while vmaCalculateStats() is intended to be used rarely,
-only to obtain statistical information, e.g. for debugging purposes.
-
-It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information
-about the budget from Vulkan device. VMA is able to use this extension automatically.
-When not enabled, the allocator behaves same way, but then it estimates current usage
-and available budget based on its internal information and Vulkan memory heap sizes,
-which may be less precise. In order to use this extension:
-
-1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2
- required by it are available and enable them. Please note that the first is a device
- extension and the second is instance extension!
-2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object.
-3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from
- Vulkan inside of it to avoid overhead of querying it with every allocation.
-
-\section staying_within_budget_controlling_memory_usage Controlling memory usage
-
-There are many ways in which you can try to stay within the budget.
-
-First, when making new allocation requires allocating a new memory block, the library
-tries not to exceed the budget automatically. If a block with default recommended size
-(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even
-dedicated memory for just this resource.
-
-If the size of the requested resource plus current memory usage is more than the
-budget, by default the library still tries to create it, leaving it to the Vulkan
-implementation whether the allocation succeeds or fails. You can change this behavior
-by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
-not made if it would exceed the budget or if the budget is already exceeded.
-Some other allocations become lost instead to make room for it, if the mechanism of
-[lost allocations](@ref lost_allocations) is used.
-If that is not possible, the allocation fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
-Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
-when creating resources that are not essential for the application (e.g. the texture
-of a specific object) and not to pass it when creating critically important resources
-(e.g. render targets).
-
-Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure
-a new allocation is created only when it fits inside one of the existing memory blocks.
-If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
-This also ensures that the function call is very fast because it never goes to Vulkan
-to obtain a new block.
-
-Please note that creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount
-set to more than 0 will try to allocate memory blocks without checking whether they
-fit within budget.
-
-
-\page resource_aliasing Resource aliasing (overlap)
-
-New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory
-management, give an opportunity to alias (overlap) multiple resources in the
-same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL).
-It can be useful to save video memory, but it must be used with caution.
-
-For example, if you know the flow of your whole render frame in advance, you
-are going to use some intermediate textures or buffers only during a small range of render passes,
-and you know these ranges don't overlap in time, you can bind these resources to
-the same place in memory, even if they have completely different parameters (width, height, format etc.).
-
-![Resource aliasing (overlap)](../gfx/Aliasing.png)
-
-Such scenario is possible using VMA, but you need to create your images manually.
-Then you need to calculate parameters of an allocation to be made using formula:
-
-- allocation size = max(size of each image)
-- allocation alignment = max(alignment of each image)
-- allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image)
-
-Following example shows two different images bound to the same place in memory,
-allocated to fit largest of them.
-
-\code
-// A 512x512 texture to be sampled.
-VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
-img1CreateInfo.imageType = VK_IMAGE_TYPE_2D;
-img1CreateInfo.extent.width = 512;
-img1CreateInfo.extent.height = 512;
-img1CreateInfo.extent.depth = 1;
-img1CreateInfo.mipLevels = 10;
-img1CreateInfo.arrayLayers = 1;
-img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
-img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
-img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
-img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
-
-// A full screen texture to be used as color attachment.
-VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
-img2CreateInfo.imageType = VK_IMAGE_TYPE_2D;
-img2CreateInfo.extent.width = 1920;
-img2CreateInfo.extent.height = 1080;
-img2CreateInfo.extent.depth = 1;
-img2CreateInfo.mipLevels = 1;
-img2CreateInfo.arrayLayers = 1;
-img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
-img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
-img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
-img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
-img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
-
-VkImage img1;
-res = vkCreateImage(device, &img1CreateInfo, nullptr, &img1);
-VkImage img2;
-res = vkCreateImage(device, &img2CreateInfo, nullptr, &img2);
-
-VkMemoryRequirements img1MemReq;
-vkGetImageMemoryRequirements(device, img1, &img1MemReq);
-VkMemoryRequirements img2MemReq;
-vkGetImageMemoryRequirements(device, img2, &img2MemReq);
-
-VkMemoryRequirements finalMemReq = {};
-finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size);
-finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment);
-finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits;
-// Validate if(finalMemReq.memoryTypeBits != 0)
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-
-VmaAllocation alloc;
-res = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr);
-
-res = vmaBindImageMemory(allocator, alloc, img1);
-res = vmaBindImageMemory(allocator, alloc, img2);
-
-// You can use img1, img2 here, but not at the same time!
-
-vmaFreeMemory(allocator, alloc);
-vkDestroyImage(allocator, img2, nullptr);
-vkDestroyImage(allocator, img1, nullptr);
-\endcode
-
-Remember that using resources that alias in memory requires proper synchronization.
-You need to issue a memory barrier to make sure commands that use `img1` and `img2`
-don't overlap on GPU timeline.
-You also need to treat a resource after aliasing as uninitialized - containing garbage data.
-For example, if you use `img1` and then want to use `img2`, you need to issue
-an image memory barrier for `img2` with `oldLayout` = `VK_IMAGE_LAYOUT_UNDEFINED`.
-
-Additional considerations:
-
-- Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases.
-See chapter 11.8. "Memory Aliasing" of Vulkan specification or `VK_IMAGE_CREATE_ALIAS_BIT` flag.
-- You can create more complex layout where different images and buffers are bound
-at different offsets inside one large allocation. For example, one can imagine
-a big texture used in some render passes, aliasing with a set of many small buffers
-used between in some further passes. To bind a resource at non-zero offset of an allocation,
-use vmaBindBufferMemory2() / vmaBindImageMemory2().
-- Before allocating memory for the resources you want to alias, check `memoryTypeBits`
-returned in memory requirements of each resource to make sure the bits overlap.
-Some GPUs may expose multiple memory types suitable e.g. only for buffers or
-images with `COLOR_ATTACHMENT` usage, so the sets of memory types supported by your
-resources may be disjoint. Aliasing them is not possible in that case.
-
-
-\page custom_memory_pools Custom memory pools
-
-A memory pool contains a number of `VkDeviceMemory` blocks.
-The library automatically creates and manages default pool for each memory type available on the device.
-Default memory pool automatically grows in size.
-Size of allocated blocks is also variable and managed automatically.
-
-You can create custom pool and allocate memory out of it.
-It can be useful if you want to:
-
-- Keep certain kind of allocations separate from others.
-- Enforce particular, fixed size of Vulkan memory blocks.
-- Limit maximum amount of Vulkan memory allocated for that pool.
-- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
-
-To use custom memory pools:
-
--# Fill VmaPoolCreateInfo structure.
--# Call vmaCreatePool() to obtain #VmaPool handle.
--# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
- You don't need to specify any other parameters of this structure, like `usage`.
-
-Example:
-
-\code
-// Create a pool that can have at most 2 blocks, 128 MiB each.
-VmaPoolCreateInfo poolCreateInfo = {};
-poolCreateInfo.memoryTypeIndex = ...
-poolCreateInfo.blockSize = 128ull * 1024 * 1024;
-poolCreateInfo.maxBlockCount = 2;
-
-VmaPool pool;
-vmaCreatePool(allocator, &poolCreateInfo, &pool);
-
-// Allocate a buffer out of it.
-VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-bufCreateInfo.size = 1024;
-bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.pool = pool;
-
-VkBuffer buf;
-VmaAllocation alloc;
-VmaAllocationInfo allocInfo;
-vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
-\endcode
-
-You have to free all allocations made from this pool before destroying it.
-
-\code
-vmaDestroyBuffer(allocator, buf, alloc);
-vmaDestroyPool(allocator, pool);
-\endcode
-
-\section custom_memory_pools_MemTypeIndex Choosing memory type index
-
-When creating a pool, you must explicitly specify memory type index.
-To find the one suitable for your buffers or images, you can use helper functions
-vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().
-You need to provide structures with example parameters of buffers or images
-that you are going to create in that pool.
-
-\code
-VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-exampleBufCreateInfo.size = 1024; // Whatever.
-exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; // Change if needed.
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; // Change if needed.
-
-uint32_t memTypeIndex;
-vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);
-
-VmaPoolCreateInfo poolCreateInfo = {};
-poolCreateInfo.memoryTypeIndex = memTypeIndex;
-// ...
-\endcode
-
-When creating buffers/images allocated in that pool, provide following parameters:
-
-- `VkBufferCreateInfo`: Prefer to pass same parameters as above.
- Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.
- Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers
- or the other way around.
-- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.
- Other members are ignored anyway.
-
-\section linear_algorithm Linear allocation algorithm
-
-Each Vulkan memory block managed by this library has accompanying metadata that
-keeps track of used and unused regions. By default, the metadata structure and
-algorithm tries to find best place for new allocations among free regions to
-optimize memory usage. This way you can allocate and free objects in any order.
-
-![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
-
-Sometimes there is a need to use simpler, linear allocation algorithm. You can
-create custom pool that uses such algorithm by adding flag
-#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
-#VmaPool object. Then an alternative metadata management is used. It always
-creates new allocations after last one and doesn't reuse free regions after
-allocations freed in the middle. It results in better allocation performance and
-less memory consumed by metadata.
-
-![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
-
-With this one flag, you can create a custom pool that can be used in many ways:
-free-at-once, stack, double stack, and ring buffer. See below for details.
-
-\subsection linear_algorithm_free_at_once Free-at-once
-
-In a pool that uses linear algorithm, you still need to free all the allocations
-individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free
-them in any order. New allocations are always made after last one - free space
-in the middle is not reused. However, when you release all the allocation and
-the pool becomes empty, allocation starts from the beginning again. This way you
-can use linear algorithm to speed up creation of allocations that you are going
-to release all at once.
-
-![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
-
-This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
-value that allows multiple memory blocks.
-
-\subsection linear_algorithm_stack Stack
-
-When you free an allocation that was created last, its space can be reused.
-Thanks to this, if you always release allocations in the order opposite to their
-creation (LIFO - Last In First Out), you can achieve behavior of a stack.
-
-![Stack](../gfx/Linear_allocator_4_stack.png)
-
-This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
-value that allows multiple memory blocks.
-
-\subsection linear_algorithm_double_stack Double stack
-
-The space reserved by a custom pool with linear algorithm may be used by two
-stacks:
-
-- First, default one, growing up from offset 0.
-- Second, "upper" one, growing down from the end towards lower offsets.
-
-To make allocation from upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
-to VmaAllocationCreateInfo::flags.
-
-![Double stack](../gfx/Linear_allocator_7_double_stack.png)
-
-Double stack is available only in pools with one memory block -
-VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
-
-When the two stacks' ends meet so there is not enough space between them for a
-new allocation, such allocation fails with usual
-`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
-
-\subsection linear_algorithm_ring_buffer Ring buffer
-
-When you free some allocations from the beginning and there is not enough free space
-for a new one at the end of a pool, allocator's "cursor" wraps around to the
-beginning and starts allocation there. Thanks to this, if you always release
-allocations in the same order as you created them (FIFO - First In First Out),
-you can achieve behavior of a ring buffer / queue.
-
-![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
-
-Pools with linear algorithm support [lost allocations](@ref lost_allocations) when used as ring buffer.
-If there is not enough free space for a new allocation, but existing allocations
-from the front of the queue can become lost, they become lost and the allocation
-succeeds.
-
-![Ring buffer with lost allocations](../gfx/Linear_allocator_6_ring_buffer_lost.png)
-
-Ring buffer is available only in pools with one memory block -
-VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
-
-\section buddy_algorithm Buddy allocation algorithm
-
-There is another allocation algorithm that can be used with custom pools, called
-"buddy". Its internal data structure is based on a tree of blocks, each having
-size that is a power of two and a half of its parent's size. When you want to
-allocate memory of certain size, a free node in the tree is located. If it's too
-large, it is recursively split into two halves (called "buddies"). However, if
-requested allocation size is not a power of two, the size of a tree node is
-aligned up to the nearest power of two and the remaining space is wasted. When
-two buddy nodes become free, they are merged back into one larger node.
-
-![Buddy allocator](../gfx/Buddy_allocator.png)
-
-The advantage of buddy allocation algorithm over default algorithm is faster
-allocation and deallocation, as well as smaller external fragmentation. The
-disadvantage is more wasted space (internal fragmentation).
-
-For more information, please read ["Buddy memory allocation" on Wikipedia](https://en.wikipedia.org/wiki/Buddy_memory_allocation)
-or other sources that describe this concept in general.
-
-To use buddy allocation algorithm with a custom pool, add flag
-#VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
-#VmaPool object.
-
-Several limitations apply to pools that use buddy algorithm:
-
-- It is recommended to use VmaPoolCreateInfo::blockSize that is a power of two.
- Otherwise, only largest power of two smaller than the size is used for
- allocations. The remaining space always stays unused.
-- [Margins](@ref debugging_memory_usage_margins) and
- [corruption detection](@ref debugging_memory_usage_corruption_detection)
- don't work in such pools.
-- [Lost allocations](@ref lost_allocations) don't work in such pools. You can
- use them, but they never become lost. Support may be added in the future.
-- [Defragmentation](@ref defragmentation) doesn't work with allocations made from
- such pool.
-
-\page defragmentation Defragmentation
-
-Interleaved allocations and deallocations of many objects of varying size can
-cause fragmentation over time, which can lead to a situation where the library is unable
-to find a continuous range of free memory for a new allocation despite there is
-enough free space, just scattered across many small free ranges between existing
-allocations.
-
-To mitigate this problem, you can use defragmentation feature:
-structure #VmaDefragmentationInfo2, function vmaDefragmentationBegin(), vmaDefragmentationEnd().
-Given set of allocations,
-this function can move them to compact used memory, ensure more continuous free
-space and possibly also free some `VkDeviceMemory` blocks.
-
-What the defragmentation does is:
-
-- Updates #VmaAllocation objects to point to new `VkDeviceMemory` and offset.
- After allocation has been moved, its VmaAllocationInfo::deviceMemory and/or
- VmaAllocationInfo::offset changes. You must query them again using
- vmaGetAllocationInfo() if you need them.
-- Moves actual data in memory.
-
-What it doesn't do, so you need to do it yourself:
-
-- Recreate buffers and images that were bound to allocations that were defragmented and
- bind them with their new places in memory.
- You must use `vkDestroyBuffer()`, `vkDestroyImage()`,
- `vkCreateBuffer()`, `vkCreateImage()`, vmaBindBufferMemory(), vmaBindImageMemory()
- for that purpose and NOT vmaDestroyBuffer(),
- vmaDestroyImage(), vmaCreateBuffer(), vmaCreateImage(), because you don't need to
- destroy or create allocation objects!
-- Recreate views and update descriptors that point to these buffers and images.
-
-\section defragmentation_cpu Defragmenting CPU memory
-
-Following example demonstrates how you can run defragmentation on CPU.
-Only allocations created in memory types that are `HOST_VISIBLE` can be defragmented.
-Others are ignored.
-
-The way it works is:
-
-- It temporarily maps entire memory blocks when necessary.
-- It moves data using `memmove()` function.
-
-\code
-// Given following variables already initialized:
-VkDevice device;
-VmaAllocator allocator;
-std::vector<VkBuffer> buffers;
-std::vector<VmaAllocation> allocations;
-
-
-const uint32_t allocCount = (uint32_t)allocations.size();
-std::vector<VkBool32> allocationsChanged(allocCount);
-
-VmaDefragmentationInfo2 defragInfo = {};
-defragInfo.allocationCount = allocCount;
-defragInfo.pAllocations = allocations.data();
-defragInfo.pAllocationsChanged = allocationsChanged.data();
-defragInfo.maxCpuBytesToMove = VK_WHOLE_SIZE; // No limit.
-defragInfo.maxCpuAllocationsToMove = UINT32_MAX; // No limit.
-
-VmaDefragmentationContext defragCtx;
-vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
-vmaDefragmentationEnd(allocator, defragCtx);
-
-for(uint32_t i = 0; i < allocCount; ++i)
-{
- if(allocationsChanged[i])
- {
- // Destroy buffer that is immutably bound to memory region which is no longer valid.
- vkDestroyBuffer(device, buffers[i], nullptr);
-
- // Create new buffer with same parameters.
- VkBufferCreateInfo bufferInfo = ...;
- vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
-
- // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
-
- // Bind new buffer to new memory region. Data contained in it is already moved.
- VmaAllocationInfo allocInfo;
- vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
- vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
- }
-}
-\endcode
-
-Setting VmaDefragmentationInfo2::pAllocationsChanged is optional.
-This output array tells whether particular allocation in VmaDefragmentationInfo2::pAllocations at the same index
-has been modified during defragmentation.
-You can pass null, but you then need to query every allocation passed to defragmentation
-for new parameters using vmaGetAllocationInfo() if you might need to recreate and rebind a buffer or image associated with it.
-
-If you use [Custom memory pools](@ref choosing_memory_type_custom_memory_pools),
-you can fill VmaDefragmentationInfo2::poolCount and VmaDefragmentationInfo2::pPools
-instead of VmaDefragmentationInfo2::allocationCount and VmaDefragmentationInfo2::pAllocations
-to defragment all allocations in given pools.
-You cannot use VmaDefragmentationInfo2::pAllocationsChanged in that case.
-You can also combine both methods.
-
-\section defragmentation_gpu Defragmenting GPU memory
-
-It is also possible to defragment allocations created in memory types that are not `HOST_VISIBLE`.
-To do that, you need to pass a command buffer that meets requirements as described in
-VmaDefragmentationInfo2::commandBuffer. The way it works is:
-
-- It creates temporary buffers and binds them to entire memory blocks when necessary.
-- It issues `vkCmdCopyBuffer()` to passed command buffer.
-
-Example:
-
-\code
-// Given following variables already initialized:
-VkDevice device;
-VmaAllocator allocator;
-VkCommandBuffer commandBuffer;
-std::vector<VkBuffer> buffers;
-std::vector<VmaAllocation> allocations;
-
-
-const uint32_t allocCount = (uint32_t)allocations.size();
-std::vector<VkBool32> allocationsChanged(allocCount);
+\brief API elements related to the allocation, deallocation, and management of Vulkan memory, buffers, images.
+Most basic ones being: vmaCreateBuffer(), vmaCreateImage().
-VkCommandBufferBeginInfo cmdBufBeginInfo = ...;
-vkBeginCommandBuffer(commandBuffer, &cmdBufBeginInfo);
+\defgroup group_virtual Virtual allocator
-VmaDefragmentationInfo2 defragInfo = {};
-defragInfo.allocationCount = allocCount;
-defragInfo.pAllocations = allocations.data();
-defragInfo.pAllocationsChanged = allocationsChanged.data();
-defragInfo.maxGpuBytesToMove = VK_WHOLE_SIZE; // Notice it's "GPU" this time.
-defragInfo.maxGpuAllocationsToMove = UINT32_MAX; // Notice it's "GPU" this time.
-defragInfo.commandBuffer = commandBuffer;
+\brief API elements related to the mechanism of \ref virtual_allocator - using the core allocation algorithm
+for user-defined purpose without allocating any real GPU memory.
-VmaDefragmentationContext defragCtx;
-vmaDefragmentationBegin(allocator, &defragInfo, nullptr, &defragCtx);
-
-vkEndCommandBuffer(commandBuffer);
-
-// Submit commandBuffer.
-// Wait for a fence that ensures commandBuffer execution finished.
-
-vmaDefragmentationEnd(allocator, defragCtx);
-
-for(uint32_t i = 0; i < allocCount; ++i)
-{
- if(allocationsChanged[i])
- {
- // Destroy buffer that is immutably bound to memory region which is no longer valid.
- vkDestroyBuffer(device, buffers[i], nullptr);
-
- // Create new buffer with same parameters.
- VkBufferCreateInfo bufferInfo = ...;
- vkCreateBuffer(device, &bufferInfo, nullptr, &buffers[i]);
-
- // You can make dummy call to vkGetBufferMemoryRequirements here to silence validation layer warning.
-
- // Bind new buffer to new memory region. Data contained in it is already moved.
- VmaAllocationInfo allocInfo;
- vmaGetAllocationInfo(allocator, allocations[i], &allocInfo);
- vmaBindBufferMemory(allocator, allocations[i], buffers[i]);
- }
-}
-\endcode
-
-You can combine these two methods by specifying non-zero `maxGpu*` as well as `maxCpu*` parameters.
-The library automatically chooses best method to defragment each memory pool.
-
-You may try not to block your entire program to wait until defragmentation finishes,
-but do it in the background, as long as you carefully fullfill requirements described
-in function vmaDefragmentationBegin().
-
-\section defragmentation_additional_notes Additional notes
-
-It is only legal to defragment allocations bound to:
-
-- buffers
-- images created with `VK_IMAGE_CREATE_ALIAS_BIT`, `VK_IMAGE_TILING_LINEAR`, and
- being currently in `VK_IMAGE_LAYOUT_GENERAL` or `VK_IMAGE_LAYOUT_PREINITIALIZED`.
-
-Defragmentation of images created with `VK_IMAGE_TILING_OPTIMAL` or in any other
-layout may give undefined results.
-
-If you defragment allocations bound to images, new images to be bound to new
-memory region after defragmentation should be created with `VK_IMAGE_LAYOUT_PREINITIALIZED`
-and then transitioned to their original layout from before defragmentation if
-needed using an image memory barrier.
-
-While using defragmentation, you may experience validation layer warnings, which you just need to ignore.
-See [Validation layer warnings](@ref general_considerations_validation_layer_warnings).
-
-Please don't expect memory to be fully compacted after defragmentation.
-Algorithms inside are based on some heuristics that try to maximize number of Vulkan
-memory blocks to make totally empty to release them, as well as to maximize continuous
-empty space inside remaining blocks, while minimizing the number and size of allocations that
-need to be moved. Some fragmentation may still remain - this is normal.
-
-\section defragmentation_custom_algorithm Writing custom defragmentation algorithm
-
-If you want to implement your own, custom defragmentation algorithm,
-there is infrastructure prepared for that,
-but it is not exposed through the library API - you need to hack its source code.
-Here are steps needed to do this:
-
--# Main thing you need to do is to define your own class derived from base abstract
- class `VmaDefragmentationAlgorithm` and implement your version of its pure virtual methods.
- See definition and comments of this class for details.
--# Your code needs to interact with device memory block metadata.
- If you need more access to its data than it's provided by its public interface,
- declare your new class as a friend class e.g. in class `VmaBlockMetadata_Generic`.
--# If you want to create a flag that would enable your algorithm or pass some additional
- flags to configure it, add them to `VmaDefragmentationFlagBits` and use them in
- VmaDefragmentationInfo2::flags.
--# Modify function `VmaBlockVectorDefragmentationContext::Begin` to create object
- of your new class whenever needed.
-
-
-\page lost_allocations Lost allocations
-
-If your game oversubscribes video memory, if may work OK in previous-generation
-graphics APIs (DirectX 9, 10, 11, OpenGL) because resources are automatically
-paged to system RAM. In Vulkan you can't do it because when you run out of
-memory, an allocation just fails. If you have more data (e.g. textures) that can
-fit into VRAM and you don't need it all at once, you may want to upload them to
-GPU on demand and "push out" ones that are not used for a long time to make room
-for the new ones, effectively using VRAM (or a cartain memory pool) as a form of
-cache. Vulkan Memory Allocator can help you with that by supporting a concept of
-"lost allocations".
-
-To create an allocation that can become lost, include #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT
-flag in VmaAllocationCreateInfo::flags. Before using a buffer or image bound to
-such allocation in every new frame, you need to query it if it's not lost.
-To check it, call vmaTouchAllocation().
-If the allocation is lost, you should not use it or buffer/image bound to it.
-You mustn't forget to destroy this allocation and this buffer/image.
-vmaGetAllocationInfo() can also be used for checking status of the allocation.
-Allocation is lost when returned VmaAllocationInfo::deviceMemory == `VK_NULL_HANDLE`.
-
-To create an allocation that can make some other allocations lost to make room
-for it, use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag. You will
-usually use both flags #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT and
-#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT at the same time.
-
-Warning! Current implementation uses quite naive, brute force algorithm,
-which can make allocation calls that use #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT
-flag quite slow. A new, more optimal algorithm and data structure to speed this
-up is planned for the future.
-
-<b>Q: When interleaving creation of new allocations with usage of existing ones,
-how do you make sure that an allocation won't become lost while it's used in the
-current frame?</b>
-
-It is ensured because vmaTouchAllocation() / vmaGetAllocationInfo() not only returns allocation
-status/parameters and checks whether it's not lost, but when it's not, it also
-atomically marks it as used in the current frame, which makes it impossible to
-become lost in that frame. It uses lockless algorithm, so it works fast and
-doesn't involve locking any internal mutex.
-
-<b>Q: What if my allocation may still be in use by the GPU when it's rendering a
-previous frame while I already submit new frame on the CPU?</b>
-
-You can make sure that allocations "touched" by vmaTouchAllocation() / vmaGetAllocationInfo() will not
-become lost for a number of additional frames back from the current one by
-specifying this number as VmaAllocatorCreateInfo::frameInUseCount (for default
-memory pool) and VmaPoolCreateInfo::frameInUseCount (for custom pool).
-
-<b>Q: How do you inform the library when new frame starts?</b>
-
-You need to call function vmaSetCurrentFrameIndex().
-
-Example code:
-
-\code
-struct MyBuffer
-{
- VkBuffer m_Buf = nullptr;
- VmaAllocation m_Alloc = nullptr;
-
- // Called when the buffer is really needed in the current frame.
- void EnsureBuffer();
-};
-
-void MyBuffer::EnsureBuffer()
-{
- // Buffer has been created.
- if(m_Buf != VK_NULL_HANDLE)
- {
- // Check if its allocation is not lost + mark it as used in current frame.
- if(vmaTouchAllocation(allocator, m_Alloc))
- {
- // It's all OK - safe to use m_Buf.
- return;
- }
- }
-
- // Buffer not yet exists or lost - destroy and recreate it.
-
- vmaDestroyBuffer(allocator, m_Buf, m_Alloc);
-
- VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
- bufCreateInfo.size = 1024;
- bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-
- VmaAllocationCreateInfo allocCreateInfo = {};
- allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
- allocCreateInfo.flags = VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT |
- VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
-
- vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &m_Buf, &m_Alloc, nullptr);
-}
-\endcode
-
-When using lost allocations, you may see some Vulkan validation layer warnings
-about overlapping regions of memory bound to different kinds of buffers and
-images. This is still valid as long as you implement proper handling of lost
-allocations (like in the example above) and don't use them.
-
-You can create an allocation that is already in lost state from the beginning using function
-vmaCreateLostAllocation(). It may be useful if you need a "dummy" allocation that is not null.
-
-You can call function vmaMakePoolAllocationsLost() to set all eligible allocations
-in a specified custom pool to lost state.
-Allocations that have been "touched" in current frame or VmaPoolCreateInfo::frameInUseCount frames back
-cannot become lost.
-
-<b>Q: Can I touch allocation that cannot become lost?</b>
-
-Yes, although it has no visible effect.
-Calls to vmaGetAllocationInfo() and vmaTouchAllocation() update last use frame index
-also for allocations that cannot become lost, but the only way to observe it is to dump
-internal allocator state using vmaBuildStatsString().
-You can use this feature for debugging purposes to explicitly mark allocations that you use
-in current frame and then analyze JSON dump to see for how long each allocation stays unused.
-
-
-\page statistics Statistics
-
-This library contains functions that return information about its internal state,
-especially the amount of memory allocated from Vulkan.
-Please keep in mind that these functions need to traverse all internal data structures
-to gather these information, so they may be quite time-consuming.
-Don't call them too often.
-
-\section statistics_numeric_statistics Numeric statistics
-
-You can query for overall statistics of the allocator using function vmaCalculateStats().
-Information are returned using structure #VmaStats.
-It contains #VmaStatInfo - number of allocated blocks, number of allocations
-(occupied ranges in these blocks), number of unused (free) ranges in these blocks,
-number of bytes used and unused (but still allocated from Vulkan) and other information.
-They are summed across memory heaps, memory types and total for whole allocator.
-
-You can query for statistics of a custom pool using function vmaGetPoolStats().
-Information are returned using structure #VmaPoolStats.
-
-You can query for information about specific allocation using function vmaGetAllocationInfo().
-It fill structure #VmaAllocationInfo.
-
-\section statistics_json_dump JSON dump
-
-You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().
-The result is guaranteed to be correct JSON.
-It uses ANSI encoding.
-Any strings provided by user (see [Allocation names](@ref allocation_names))
-are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,
-this JSON string can be treated as using this encoding.
-It must be freed using function vmaFreeStatsString().
-
-The format of this JSON string is not part of official documentation of the library,
-but it will not change in backward-incompatible way without increasing library major version number
-and appropriate mention in changelog.
-
-The JSON string contains all the data that can be obtained using vmaCalculateStats().
-It can also contain detailed map of allocated memory blocks and their regions -
-free and occupied by allocations.
-This allows e.g. to visualize the memory or assess fragmentation.
-
-
-\page allocation_annotation Allocation names and user data
-
-\section allocation_user_data Allocation user data
-
-You can annotate allocations with your own information, e.g. for debugging purposes.
-To do that, fill VmaAllocationCreateInfo::pUserData field when creating
-an allocation. It's an opaque `void*` pointer. You can use it e.g. as a pointer,
-some handle, index, key, ordinal number or any other value that would associate
-the allocation with your custom metadata.
-
-\code
-VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
-// Fill bufferInfo...
-
-MyBufferMetadata* pMetadata = CreateBufferMetadata();
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-allocCreateInfo.pUserData = pMetadata;
-
-VkBuffer buffer;
-VmaAllocation allocation;
-vmaCreateBuffer(allocator, &bufferInfo, &allocCreateInfo, &buffer, &allocation, nullptr);
-\endcode
-
-The pointer may be later retrieved as VmaAllocationInfo::pUserData:
-
-\code
-VmaAllocationInfo allocInfo;
-vmaGetAllocationInfo(allocator, allocation, &allocInfo);
-MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;
-\endcode
-
-It can also be changed using function vmaSetAllocationUserData().
-
-Values of (non-zero) allocations' `pUserData` are printed in JSON report created by
-vmaBuildStatsString(), in hexadecimal form.
-
-\section allocation_names Allocation names
-
-There is alternative mode available where `pUserData` pointer is used to point to
-a null-terminated string, giving a name to the allocation. To use this mode,
-set #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT flag in VmaAllocationCreateInfo::flags.
-Then `pUserData` passed as VmaAllocationCreateInfo::pUserData or argument to
-vmaSetAllocationUserData() must be either null or pointer to a null-terminated string.
-The library creates internal copy of the string, so the pointer you pass doesn't need
-to be valid for whole lifetime of the allocation. You can free it after the call.
-
-\code
-VkImageCreateInfo imageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
-// Fill imageInfo...
-
-std::string imageName = "Texture: ";
-imageName += fileName;
-
-VmaAllocationCreateInfo allocCreateInfo = {};
-allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
-allocCreateInfo.flags = VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT;
-allocCreateInfo.pUserData = imageName.c_str();
-
-VkImage image;
-VmaAllocation allocation;
-vmaCreateImage(allocator, &imageInfo, &allocCreateInfo, &image, &allocation, nullptr);
-\endcode
-
-The value of `pUserData` pointer of the allocation will be different than the one
-you passed when setting allocation's name - pointing to a buffer managed
-internally that holds copy of the string.
-
-\code
-VmaAllocationInfo allocInfo;
-vmaGetAllocationInfo(allocator, allocation, &allocInfo);
-const char* imageName = (const char*)allocInfo.pUserData;
-printf("Image name: %s\n", imageName);
-\endcode
-
-That string is also printed in JSON report created by vmaBuildStatsString().
-
-\note Passing string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it.
-You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.
-
-
-\page debugging_memory_usage Debugging incorrect memory usage
-
-If you suspect a bug with memory usage, like usage of uninitialized memory or
-memory being overwritten out of bounds of an allocation,
-you can use debug features of this library to verify this.
-
-\section debugging_memory_usage_initialization Memory initialization
-
-If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
-you can enable automatic memory initialization to verify this.
-To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
-
-\code
-#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
-#include "vk_mem_alloc.h"
-\endcode
-
-It makes memory of all new allocations initialized to bit pattern `0xDCDCDCDC`.
-Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
-Memory is automatically mapped and unmapped if necessary.
-
-If you find these values while debugging your program, good chances are that you incorrectly
-read Vulkan memory that is allocated but not initialized, or already freed, respectively.
-
-Memory initialization works only with memory types that are `HOST_VISIBLE`.
-It works also with dedicated allocations.
-It doesn't work with allocations created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
-as they cannot be mapped.
-
-\section debugging_memory_usage_margins Margins
-
-By default, allocations are laid out in memory blocks next to each other if possible
-(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).
-
-![Allocations without margin](../gfx/Margins_1.png)
-
-Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified
-number of bytes as a margin before and after every allocation.
-
-\code
-#define VMA_DEBUG_MARGIN 16
-#include "vk_mem_alloc.h"
-\endcode
-
-![Allocations with margin](../gfx/Margins_2.png)
-
-If your bug goes away after enabling margins, it means it may be caused by memory
-being overwritten outside of allocation boundaries. It is not 100% certain though.
-Change in application behavior may also be caused by different order and distribution
-of allocations across memory blocks after margins are applied.
-
-The margin is applied also before first and after last allocation in a block.
-It may occur only once between two adjacent allocations.
-
-Margins work with all types of memory.
-
-Margin is applied only to allocations made out of memory blocks and not to dedicated
-allocations, which have their own memory block of specific size.
-It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag
-or those automatically decided to put into dedicated allocations, e.g. due to its
-large size or recommended by VK_KHR_dedicated_allocation extension.
-Margins are also not active in custom pools created with #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag.
-
-Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
-
-Note that enabling margins increases memory usage and fragmentation.
-
-\section debugging_memory_usage_corruption_detection Corruption detection
-
-You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation
-of contents of the margins.
-
-\code
-#define VMA_DEBUG_MARGIN 16
-#define VMA_DEBUG_DETECT_CORRUPTION 1
-#include "vk_mem_alloc.h"
-\endcode
-
-When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`
-(it must be multiply of 4) before and after every allocation is filled with a magic number.
-This idea is also know as "canary".
-Memory is automatically mapped and unmapped if necessary.
-
-This number is validated automatically when the allocation is destroyed.
-If it's not equal to the expected value, `VMA_ASSERT()` is executed.
-It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,
-which indicates a serious bug.
-
-You can also explicitly request checking margins of all allocations in all memory blocks
-that belong to specified memory types by using function vmaCheckCorruption(),
-or in memory blocks that belong to specified custom pool, by using function
-vmaCheckPoolCorruption().
-
-Margin validation (corruption detection) works only for memory types that are
-`HOST_VISIBLE` and `HOST_COHERENT`.
-
-
-\page record_and_replay Record and replay
-
-\section record_and_replay_introduction Introduction
-
-While using the library, sequence of calls to its functions together with their
-parameters can be recorded to a file and later replayed using standalone player
-application. It can be useful to:
-
-- Test correctness - check if same sequence of calls will not cause crash or
- failures on a target platform.
-- Gather statistics - see number of allocations, peak memory usage, number of
- calls etc.
-- Benchmark performance - see how much time it takes to replay the whole
- sequence.
-
-\section record_and_replay_usage Usage
-
-Recording functionality is disabled by default.
-To enable it, define following macro before every include of this library:
-
-\code
-#define VMA_RECORDING_ENABLED 1
-\endcode
-
-<b>To record sequence of calls to a file:</b> Fill in
-VmaAllocatorCreateInfo::pRecordSettings member while creating #VmaAllocator
-object. File is opened and written during whole lifetime of the allocator.
-
-<b>To replay file:</b> Use VmaReplay - standalone command-line program.
-Precompiled binary can be found in "bin" directory.
-Its source can be found in "src/VmaReplay" directory.
-Its project is generated by Premake.
-Command line syntax is printed when the program is launched without parameters.
-Basic usage:
-
- VmaReplay.exe MyRecording.csv
-
-<b>Documentation of file format</b> can be found in file: "docs/Recording file format.md".
-It's a human-readable, text file in CSV format (Comma Separated Values).
-
-\section record_and_replay_additional_considerations Additional considerations
-
-- Replaying file that was recorded on a different GPU (with different parameters
- like `bufferImageGranularity`, `nonCoherentAtomSize`, and especially different
- set of memory heaps and types) may give different performance and memory usage
- results, as well as issue some warnings and errors.
-- Current implementation of recording in VMA, as well as VmaReplay application, is
- coded and tested only on Windows. Inclusion of recording code is driven by
- `VMA_RECORDING_ENABLED` macro. Support for other platforms should be easy to
- add. Contributions are welcomed.
-
-
-\page usage_patterns Recommended usage patterns
-
-See also slides from talk:
-[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)
-
-
-\section usage_patterns_common_mistakes Common mistakes
-
-<b>Use of CPU_TO_GPU instead of CPU_ONLY memory</b>
-
-#VMA_MEMORY_USAGE_CPU_TO_GPU is recommended only for resources that will be
-mapped and written by the CPU, as well as read directly by the GPU - like some
-buffers or textures updated every frame (dynamic). If you create a staging copy
-of a resource to be written by CPU and then used as a source of transfer to
-another resource placed in the GPU memory, that staging resource should be
-created with #VMA_MEMORY_USAGE_CPU_ONLY. Please read the descriptions of these
-enums carefully for details.
-
-<b>Unnecessary use of custom pools</b>
-
-\ref custom_memory_pools may be useful for special purposes - when you want to
-keep certain type of resources separate e.g. to reserve minimum amount of memory
-for them, limit maximum amount of memory they can occupy, or make some of them
-push out the other through the mechanism of \ref lost_allocations. For most
-resources this is not needed and so it is not recommended to create #VmaPool
-objects and allocations out of them. Allocating from the default pool is sufficient.
-
-\section usage_patterns_simple Simple patterns
-
-\subsection usage_patterns_simple_render_targets Render targets
-
-<b>When:</b>
-Any resources that you frequently write and read on GPU,
-e.g. images used as color attachments (aka "render targets"), depth-stencil attachments,
-images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").
-
-<b>What to do:</b>
-Create them in video memory that is fastest to access from GPU using
-#VMA_MEMORY_USAGE_GPU_ONLY.
-
-Consider using [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension
-and/or manually creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
-especially if they are large or if you plan to destroy and recreate them e.g. when
-display resolution changes.
-Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.
-
-\subsection usage_patterns_simple_immutable_resources Immutable resources
-
-<b>When:</b>
-Any resources that you fill on CPU only once (aka "immutable") or infrequently
-and then read frequently on GPU,
-e.g. textures, vertex and index buffers, constant buffers that don't change often.
-
-<b>What to do:</b>
-Create them in video memory that is fastest to access from GPU using
-#VMA_MEMORY_USAGE_GPU_ONLY.
-
-To initialize content of such resource, create a CPU-side (aka "staging") copy of it
-in system memory - #VMA_MEMORY_USAGE_CPU_ONLY, map it, fill it,
-and submit a transfer from it to the GPU resource.
-You can keep the staging copy if you need it for another upload transfer in the future.
-If you don't, you can destroy it or reuse this buffer for uploading different resource
-after the transfer finishes.
-
-Prefer to create just buffers in system memory rather than images, even for uploading textures.
-Use `vkCmdCopyBufferToImage()`.
-Dont use images with `VK_IMAGE_TILING_LINEAR`.
-
-\subsection usage_patterns_dynamic_resources Dynamic resources
-
-<b>When:</b>
-Any resources that change frequently (aka "dynamic"), e.g. every frame or every draw call,
-written on CPU, read on GPU.
-
-<b>What to do:</b>
-Create them using #VMA_MEMORY_USAGE_CPU_TO_GPU.
-You can map it and write to it directly on CPU, as well as read from it on GPU.
-
-This is a more complex situation. Different solutions are possible,
-and the best one depends on specific GPU type, but you can use this simple approach for the start.
-Prefer to write to such resource sequentially (e.g. using `memcpy`).
-Don't perform random access or any reads from it on CPU, as it may be very slow.
-Also note that textures written directly from the host through a mapped pointer need to be in LINEAR not OPTIMAL layout.
-
-\subsection usage_patterns_readback Readback
-
-<b>When:</b>
-Resources that contain data written by GPU that you want to read back on CPU,
-e.g. results of some computations.
-
-<b>What to do:</b>
-Create them using #VMA_MEMORY_USAGE_GPU_TO_CPU.
-You can write to them directly on GPU, as well as map and read them on CPU.
-
-\section usage_patterns_advanced Advanced patterns
-
-\subsection usage_patterns_integrated_graphics Detecting integrated graphics
-
-You can support integrated graphics (like Intel HD Graphics, AMD APU) better
-by detecting it in Vulkan.
-To do it, call `vkGetPhysicalDeviceProperties()`, inspect
-`VkPhysicalDeviceProperties::deviceType` and look for `VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU`.
-When you find it, you can assume that memory is unified and all memory types are comparably fast
-to access from GPU, regardless of `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
-
-You can then sum up sizes of all available memory heaps and treat them as useful for
-your GPU resources, instead of only `DEVICE_LOCAL` ones.
-You can also prefer to create your resources in memory types that are `HOST_VISIBLE` to map them
-directly instead of submitting explicit transfer (see below).
-
-\subsection usage_patterns_direct_vs_transfer Direct access versus transfer
-
-For resources that you frequently write on CPU and read on GPU, many solutions are possible:
-
--# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
- second copy in system memory using #VMA_MEMORY_USAGE_CPU_ONLY and submit explicit transfer each time.
--# Create just a single copy using #VMA_MEMORY_USAGE_CPU_TO_GPU, map it and fill it on CPU,
- read it directly on GPU.
--# Create just a single copy using #VMA_MEMORY_USAGE_CPU_ONLY, map it and fill it on CPU,
- read it directly on GPU.
-
-Which solution is the most efficient depends on your resource and especially on the GPU.
-It is best to measure it and then make the decision.
-Some general recommendations:
-
-- On integrated graphics use (2) or (3) to avoid unnecessary time and memory overhead
- related to using a second copy and making transfer.
-- For small resources (e.g. constant buffers) use (2).
- Discrete AMD cards have special 256 MiB pool of video memory that is directly mappable.
- Even if the resource ends up in system memory, its data may be cached on GPU after first
- fetch over PCIe bus.
-- For larger resources (e.g. textures), decide between (1) and (2).
- You may want to differentiate NVIDIA and AMD, e.g. by looking for memory type that is
- both `DEVICE_LOCAL` and `HOST_VISIBLE`. When you find it, use (2), otherwise use (1).
-
-Similarly, for resources that you frequently write on GPU and read on CPU, multiple
-solutions are possible:
-
--# Create one copy in video memory using #VMA_MEMORY_USAGE_GPU_ONLY,
- second copy in system memory using #VMA_MEMORY_USAGE_GPU_TO_CPU and submit explicit tranfer each time.
--# Create just single copy using #VMA_MEMORY_USAGE_GPU_TO_CPU, write to it directly on GPU,
- map it and read it on CPU.
-
-You should take some measurements to decide which option is faster in case of your specific
-resource.
-
-Note that textures accessed directly from the host through a mapped pointer need to be in LINEAR layout,
-which may slow down their usage on the device.
-Textures accessed only by the device and transfer operations can use OPTIMAL layout.
-
-If you don't want to specialize your code for specific types of GPUs, you can still make
-an simple optimization for cases when your resource ends up in mappable memory to use it
-directly in this case instead of creating CPU-side staging copy.
-For details see [Finding out if memory is mappable](@ref memory_mapping_finding_if_memory_mappable).
-
-
-\page configuration Configuration
-
-Please check "CONFIGURATION SECTION" in the code to find macros that you can define
-before each include of this file or change directly in this file to provide
-your own implementation of basic facilities like assert, `min()` and `max()` functions,
-mutex, atomic etc.
-The library uses its own implementation of containers by default, but you can switch to using
-STL containers instead.
-
-For example, define `VMA_ASSERT(expr)` before including the library to provide
-custom implementation of the assertion, compatible with your project.
-By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
-and empty otherwise.
-
-\section config_Vulkan_functions Pointers to Vulkan functions
-
-There are multiple ways to import pointers to Vulkan functions in the library.
-In the simplest case you don't need to do anything.
-If the compilation or linking of your program or the initialization of the #VmaAllocator
-doesn't work for you, you can try to reconfigure it.
-
-First, the allocator tries to fetch pointers to Vulkan functions linked statically,
-like this:
-
-\code
-m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
-\endcode
-
-If you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`.
-
-Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions.
-You can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or
-by using a helper library like [volk](https://github.com/zeux/volk).
-
-Third, VMA tries to fetch remaining pointers that are still null by calling
-`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own.
-If you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`.
-
-Finally, all the function pointers required by the library (considering selected
-Vulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null.
-
-
-\section custom_memory_allocator Custom host memory allocator
-
-If you use custom allocator for CPU memory rather than default operator `new`
-and `delete` from C++, you can make this library using your allocator as well
-by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
-functions will be passed to Vulkan, as well as used by the library itself to
-make any CPU-side allocations.
-
-\section allocation_callbacks Device memory allocation callbacks
-
-The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
-You can setup callbacks to be informed about these calls, e.g. for the purpose
-of gathering some statistics. To do it, fill optional member
-VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
-
-\section heap_memory_limit Device heap memory limit
-
-When device memory of certain heap runs out of free space, new allocations may
-fail (returning error code) or they may succeed, silently pushing some existing
-memory blocks from GPU VRAM to system RAM (which degrades performance). This
-behavior is implementation-dependent - it depends on GPU vendor and graphics
-driver.
-
-On AMD cards it can be controlled while creating Vulkan device object by using
-VK_AMD_memory_overallocation_behavior extension, if available.
-
-Alternatively, if you want to test how your program behaves with limited amount of Vulkan device
-memory available without switching your graphics card to one that really has
-smaller VRAM, you can use a feature of this library intended for this purpose.
-To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
-
-
-
-\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation
-
-VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve
-performance on some GPUs. It augments Vulkan API with possibility to query
-driver whether it prefers particular buffer or image to have its own, dedicated
-allocation (separate `VkDeviceMemory` block) for better efficiency - to be able
-to do some internal optimizations.
-
-The extension is supported by this library. It will be used automatically when
-enabled. To enable it:
-
-1 . When creating Vulkan device, check if following 2 device extensions are
-supported (call `vkEnumerateDeviceExtensionProperties()`).
-If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).
-
-- VK_KHR_get_memory_requirements2
-- VK_KHR_dedicated_allocation
-
-If you enabled these extensions:
-
-2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating
-your #VmaAllocator`to inform the library that you enabled required extensions
-and you want the library to use them.
-
-\code
-allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
-
-vmaCreateAllocator(&allocatorInfo, &allocator);
-\endcode
-
-That's all. The extension will be automatically used whenever you create a
-buffer using vmaCreateBuffer() or image using vmaCreateImage().
-
-When using the extension together with Vulkan Validation Layer, you will receive
-warnings like this:
-
- vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer.
-
-It is OK, you should just ignore it. It happens because you use function
-`vkGetBufferMemoryRequirements2KHR()` instead of standard
-`vkGetBufferMemoryRequirements()`, while the validation layer seems to be
-unaware of it.
-
-To learn more about this extension, see:
-
-- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap50.html#VK_KHR_dedicated_allocation)
-- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)
-
-
-
-\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory
-
-VK_AMD_device_coherent_memory is a device extension that enables access to
-additional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and
-`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for
-allocation of buffers intended for writing "breadcrumb markers" in between passes
-or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases.
-
-When the extension is available but has not been enabled, Vulkan physical device
-still exposes those memory types, but their usage is forbidden. VMA automatically
-takes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt
-to allocate memory of such type is made.
-
-If you want to use this extension in connection with VMA, follow these steps:
-
-\section vk_amd_device_coherent_memory_initialization Initialization
-
-1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
-Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_AMD_device_coherent_memory".
-
-2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
-Attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
-Check if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true.
-
-3) While creating device with `vkCreateDevice`, enable this extension - add "VK_AMD_device_coherent_memory"
-to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
-
-4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
-Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
-Enable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to
-`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`.
-
-5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
-have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
-to VmaAllocatorCreateInfo::flags.
-
-\section vk_amd_device_coherent_memory_usage Usage
-
-After following steps described above, you can create VMA allocations and custom pools
-out of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible
-devices. There are multiple ways to do it, for example:
-
-- You can request or prefer to allocate out of such memory types by adding
- `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags
- or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with
- other ways of \ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage.
-- If you manually found memory type index to use for this purpose, force allocation
- from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1u << index`.
-
-\section vk_amd_device_coherent_memory_more_information More information
-
-To learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap44.html#VK_AMD_device_coherent_memory)
-
-Example use of this extension can be found in the code of the sample and test suite
-accompanying this library.
-
-
-\page enabling_buffer_device_address Enabling buffer device address
-
-Device extension VK_KHR_buffer_device_address
-allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code.
-It is promoted to core Vulkan 1.2.
-
-If you want to use this feature in connection with VMA, follow these steps:
-
-\section enabling_buffer_device_address_initialization Initialization
-
-1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
-Check if the extension is supported - if returned array of `VkExtensionProperties` contains
-"VK_KHR_buffer_device_address".
-
-2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
-Attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
-Check if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures*::bufferDeviceAddress` is true.
-
-3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add
-"VK_KHR_buffer_device_address" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
-
-4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
-Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
-Enable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to
-`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`.
-
-5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
-have enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
-to VmaAllocatorCreateInfo::flags.
-
-\section enabling_buffer_device_address_usage Usage
-
-After following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA.
-The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to
-allocated memory blocks wherever it might be needed.
-
-Please note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`.
-The second part of this functionality related to "capture and replay" is not supported,
-as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage.
-
-\section enabling_buffer_device_address_more_information More information
-
-To learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address)
-
-Example use of this extension can be found in the code of the sample and test suite
-accompanying this library.
-
-\page general_considerations General considerations
-
-\section general_considerations_thread_safety Thread safety
-
-- The library has no global state, so separate #VmaAllocator objects can be used
- independently.
- There should be no need to create multiple such objects though - one per `VkDevice` is enough.
-- By default, all calls to functions that take #VmaAllocator as first parameter
- are safe to call from multiple threads simultaneously because they are
- synchronized internally when needed.
-- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
- flag, calls to functions that take such #VmaAllocator object must be
- synchronized externally.
-- Access to a #VmaAllocation object must be externally synchronized. For example,
- you must not call vmaGetAllocationInfo() and vmaMapMemory() from different
- threads at the same time if you pass the same #VmaAllocation object to these
- functions.
-
-\section general_considerations_validation_layer_warnings Validation layer warnings
-
-When using this library, you can meet following types of warnings issued by
-Vulkan validation layer. They don't necessarily indicate a bug, so you may need
-to just ignore them.
-
-- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*
- - It happens when VK_KHR_dedicated_allocation extension is enabled.
- `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.
-- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*
- - It happens when you map a buffer or image, because the library maps entire
- `VkDeviceMemory` block, where different types of images and buffers may end
- up together, especially on GPUs with unified memory like Intel.
-- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*
- - It happens when you use lost allocations, and a new image or buffer is
- created in place of an existing object that became lost.
- - It may happen also when you use [defragmentation](@ref defragmentation).
-
-\section general_considerations_allocation_algorithm Allocation algorithm
-
-The library uses following algorithm for allocation, in order:
-
--# Try to find free range of memory in existing blocks.
--# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.
--# If failed, try to create such block with size/2, size/4, size/8.
--# If failed and #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag was
- specified, try to find space in existing blocks, possilby making some other
- allocations lost.
--# If failed, try to allocate separate `VkDeviceMemory` for this allocation,
- just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
--# If failed, choose other memory type that meets the requirements specified in
- VmaAllocationCreateInfo and go to point 1.
--# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
-
-\section general_considerations_features_not_supported Features not supported
-
-Features deliberately excluded from the scope of this library:
-
-- Data transfer. Uploading (streaming) and downloading data of buffers and images
- between CPU and GPU memory and related synchronization is responsibility of the user.
- Defining some "texture" object that would automatically stream its data from a
- staging copy in CPU memory to GPU memory would rather be a feature of another,
- higher-level library implemented on top of VMA.
-- Allocations for imported/exported external memory. They tend to require
- explicit memory type index and dedicated allocation anyway, so they don't
- interact with main features of this library. Such special purpose allocations
- should be made manually, using `vkCreateBuffer()` and `vkAllocateMemory()`.
-- Sub-allocation of parts of one large buffer. Although recommended as a good practice,
- it is the user's responsibility to implement such logic on top of VMA.
-- Recreation of buffers and images. Although the library has functions for
- buffer and image creation (vmaCreateBuffer(), vmaCreateImage()), you need to
- recreate these objects yourself after defragmentation. That's because the big
- structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in
- #VmaAllocation object.
-- Handling CPU memory allocation failures. When dynamically creating small C++
- objects in CPU memory (not Vulkan memory), allocation failures are not checked
- and handled gracefully, because that would complicate code significantly and
- is usually not needed in desktop PC applications anyway.
- Success of an allocation is just checked with an assert.
-- Code free of any compiler warnings. Maintaining the library to compile and
- work correctly on so many different platforms is hard enough. Being free of
- any warnings, on any version of any compiler, is simply not feasible.
-- This is a C++ library with C interface.
- Bindings or ports to any other programming languages are welcomed as external projects and
- are not going to be included into this repository.
+\defgroup group_stats Statistics
+\brief API elements that query current status of the allocator, from memory usage, budget, to full dump of the internal state in JSON format.
+See documentation chapter: \ref statistics.
*/
+
#ifdef __cplusplus
extern "C" {
#endif
-/*
-Define this macro to 0/1 to disable/enable support for recording functionality,
-available through VmaAllocatorCreateInfo::pRecordSettings.
-*/
-#ifndef VMA_RECORDING_ENABLED
- #define VMA_RECORDING_ENABLED 0
+#ifndef VULKAN_H_
+ #ifdef USE_VOLK
+ #include <volk.h>
+ #else
+ #include <vulkan/vulkan.h>
+ #endif
#endif
-#if !defined(NOMINMAX) && defined(VMA_IMPLEMENTATION)
- #define NOMINMAX // For windows.h
+// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC,
+// where AAA = major, BBB = minor, CCC = patch.
+// If you want to use version > 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion.
+#if !defined(VMA_VULKAN_VERSION)
+ #if defined(VK_VERSION_1_3)
+ #define VMA_VULKAN_VERSION 1003000
+ #elif defined(VK_VERSION_1_2)
+ #define VMA_VULKAN_VERSION 1002000
+ #elif defined(VK_VERSION_1_1)
+ #define VMA_VULKAN_VERSION 1001000
+ #else
+ #define VMA_VULKAN_VERSION 1000000
+ #endif
#endif
#if defined(__ANDROID__) && defined(VK_NO_PROTOTYPES) && VMA_STATIC_VULKAN_FUNCTIONS
@@ -2062,27 +178,6 @@ available through VmaAllocatorCreateInfo::pRecordSettings.
#endif // #if VMA_VULKAN_VERSION >= 1001000
#endif // #if defined(__ANDROID__) && VMA_STATIC_VULKAN_FUNCTIONS && VK_NO_PROTOTYPES
-#ifndef VULKAN_H_
- #ifdef USE_VOLK
- #include <volk.h>
- #else
- #include <vulkan/vulkan.h>
- #endif
-#endif
-
-// Define this macro to declare maximum supported Vulkan version in format AAABBBCCC,
-// where AAA = major, BBB = minor, CCC = patch.
-// If you want to use version > 1.0, it still needs to be enabled via VmaAllocatorCreateInfo::vulkanApiVersion.
-#if !defined(VMA_VULKAN_VERSION)
- #if defined(VK_VERSION_1_2)
- #define VMA_VULKAN_VERSION 1002000
- #elif defined(VK_VERSION_1_1)
- #define VMA_VULKAN_VERSION 1001000
- #else
- #define VMA_VULKAN_VERSION 1000000
- #endif
-#endif
-
#if !defined(VMA_DEDICATED_ALLOCATION)
#if VK_KHR_get_memory_requirements2 && VK_KHR_dedicated_allocation
#define VMA_DEDICATED_ALLOCATION 1
@@ -2199,50 +294,29 @@ available through VmaAllocatorCreateInfo::pRecordSettings.
#endif
#endif
-/** \struct VmaAllocator
-\brief Represents main object of this library initialized.
-
-Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.
-Call function vmaDestroyAllocator() to destroy it.
-
-It is recommended to create just one object of this type per `VkDevice` object,
-right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.
-*/
-VK_DEFINE_HANDLE(VmaAllocator)
-
-/// Callback function called after successful vkAllocateMemory.
-typedef void (VKAPI_PTR *PFN_vmaAllocateDeviceMemoryFunction)(
- VmaAllocator VMA_NOT_NULL allocator,
- uint32_t memoryType,
- VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,
- VkDeviceSize size,
- void* VMA_NULLABLE pUserData);
-/// Callback function called before vkFreeMemory.
-typedef void (VKAPI_PTR *PFN_vmaFreeDeviceMemoryFunction)(
- VmaAllocator VMA_NOT_NULL allocator,
- uint32_t memoryType,
- VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,
- VkDeviceSize size,
- void* VMA_NULLABLE pUserData);
+#ifndef VMA_STATS_STRING_ENABLED
+ #define VMA_STATS_STRING_ENABLED 1
+#endif
-/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// INTERFACE
+//
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
-Provided for informative purpose, e.g. to gather statistics about number of
-allocations or total amount of memory allocated in Vulkan.
+// Sections for managing code placement in file, only for development purposes e.g. for convenient folding inside an IDE.
+#ifndef _VMA_ENUM_DECLARATIONS
-Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+/**
+\addtogroup group_init
+@{
*/
-typedef struct VmaDeviceMemoryCallbacks {
- /// Optional, can be null.
- PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate;
- /// Optional, can be null.
- PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree;
- /// Optional, can be null.
- void* VMA_NULLABLE pUserData;
-} VmaDeviceMemoryCallbacks;
/// Flags for created #VmaAllocator.
-typedef enum VmaAllocatorCreateFlagBits {
+typedef enum VmaAllocatorCreateFlagBits
+{
/** \brief Allocator and all objects created from it will not be synchronized internally, so you must guarantee they are used from only one thread at a time or synchronized externally by you.
Using this flag may increase performance because internal mutexes are not used.
@@ -2251,7 +325,7 @@ typedef enum VmaAllocatorCreateFlagBits {
/** \brief Enables usage of VK_KHR_dedicated_allocation extension.
The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
- When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+ When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
Using this extension will automatically allocate dedicated blocks of memory for
some buffers and images instead of suballocating place for them out of bigger
@@ -2277,7 +351,7 @@ typedef enum VmaAllocatorCreateFlagBits {
Enables usage of VK_KHR_bind_memory2 extension.
The flag works only if VmaAllocatorCreateInfo::vulkanApiVersion `== VK_API_VERSION_1_0`.
- When it's `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
+ When it is `VK_API_VERSION_1_1`, the flag is ignored because the extension has been promoted to Vulkan 1.1.
You may set this flag only if you found out that this device extension is supported,
you enabled it while creating Vulkan device passed as VmaAllocatorCreateInfo::device,
@@ -2356,13 +430,536 @@ typedef enum VmaAllocatorCreateFlagBits {
VMA_ALLOCATOR_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
} VmaAllocatorCreateFlagBits;
+/// See #VmaAllocatorCreateFlagBits.
typedef VkFlags VmaAllocatorCreateFlags;
+/** @} */
+
+/**
+\addtogroup group_alloc
+@{
+*/
+
+/// \brief Intended usage of the allocated memory.
+typedef enum VmaMemoryUsage
+{
+ /** No intended memory usage specified.
+ Use other members of VmaAllocationCreateInfo to specify your requirements.
+ */
+ VMA_MEMORY_USAGE_UNKNOWN = 0,
+ /**
+ \deprecated Obsolete, preserved for backward compatibility.
+ Prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+ */
+ VMA_MEMORY_USAGE_GPU_ONLY = 1,
+ /**
+ \deprecated Obsolete, preserved for backward compatibility.
+ Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`.
+ */
+ VMA_MEMORY_USAGE_CPU_ONLY = 2,
+ /**
+ \deprecated Obsolete, preserved for backward compatibility.
+ Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+ */
+ VMA_MEMORY_USAGE_CPU_TO_GPU = 3,
+ /**
+ \deprecated Obsolete, preserved for backward compatibility.
+ Guarantees `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`, prefers `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`.
+ */
+ VMA_MEMORY_USAGE_GPU_TO_CPU = 4,
+ /**
+ \deprecated Obsolete, preserved for backward compatibility.
+ Prefers not `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+ */
+ VMA_MEMORY_USAGE_CPU_COPY = 5,
+ /**
+ Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`.
+ Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.
+
+ Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.
+
+ Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+ */
+ VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6,
+ /**
+ Selects best memory type automatically.
+ This flag is recommended for most common use cases.
+
+ When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
+ you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
+ in VmaAllocationCreateInfo::flags.
+
+ It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
+ vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
+ and not with generic memory allocation functions.
+ */
+ VMA_MEMORY_USAGE_AUTO = 7,
+ /**
+ Selects best memory type automatically with preference for GPU (device) memory.
+
+ When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
+ you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
+ in VmaAllocationCreateInfo::flags.
+
+ It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
+ vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
+ and not with generic memory allocation functions.
+ */
+ VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE = 8,
+ /**
+ Selects best memory type automatically with preference for CPU (host) memory.
+
+ When using this flag, if you want to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT),
+ you must pass one of the flags: #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
+ in VmaAllocationCreateInfo::flags.
+
+ It can be used only with functions that let the library know `VkBufferCreateInfo` or `VkImageCreateInfo`, e.g.
+ vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo()
+ and not with generic memory allocation functions.
+ */
+ VMA_MEMORY_USAGE_AUTO_PREFER_HOST = 9,
+
+ VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF
+} VmaMemoryUsage;
+
+/// Flags to be passed as VmaAllocationCreateInfo::flags.
+typedef enum VmaAllocationCreateFlagBits
+{
+ /** \brief Set this flag if the allocation should have its own memory block.
+
+ Use it for special, big resources, like fullscreen images used as attachments.
+ */
+ VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,
+
+ /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.
+
+ If new allocation cannot be placed in any of the existing blocks, allocation
+ fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+ You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and
+ #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.
+ */
+ VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,
+ /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
+
+ Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
+
+ It is valid to use this flag for allocation made from memory type that is not
+ `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
+ useful if you need an allocation that is efficient to use on GPU
+ (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
+ support it (e.g. Intel GPU).
+ */
+ VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
+ /** \deprecated Preserved for backward compatibility. Consider using vmaSetAllocationName() instead.
+
+ Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
+ null-terminated string. Instead of copying pointer value, a local copy of the
+ string is made and stored in allocation's `pName`. The string is automatically
+ freed together with the allocation. It is also used in vmaBuildStatsString().
+ */
+ VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
+ /** Allocation will be created from upper stack in a double stack pool.
+
+ This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.
+ */
+ VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
+ /** Create both buffer/image and allocation, but don't bind them together.
+ It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
+ The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage().
+ Otherwise it is ignored.
+
+ If you want to make sure the new buffer/image is not tied to the new memory allocation
+ through `VkMemoryDedicatedAllocateInfoKHR` structure in case the allocation ends up in its own memory block,
+ use also flag #VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT.
+ */
+ VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080,
+ /** Create allocation only if additional device memory required for it, if any, won't exceed
+ memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+ */
+ VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
+ /** \brief Set this flag if the allocated memory will have aliasing resources.
+
+ Usage of this flag prevents supplying `VkMemoryDedicatedAllocateInfoKHR` when #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT is specified.
+ Otherwise created dedicated memory will not be suitable for aliasing resources, resulting in Vulkan Validation Layer errors.
+ */
+ VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT = 0x00000200,
+ /**
+ Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
+
+ - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
+ you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
+ - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
+ This includes allocations created in \ref custom_memory_pools.
+
+ Declares that mapped memory will only be written sequentially, e.g. using `memcpy()` or a loop writing number-by-number,
+ never read or accessed randomly, so a memory type can be selected that is uncached and write-combined.
+
+ \warning Violating this declaration may work correctly, but will likely be very slow.
+ Watch out for implicit reads introduced by doing e.g. `pMappedData[i] += x;`
+ Better prepare your data in a local variable and `memcpy()` it to the mapped pointer all at once.
+ */
+ VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT = 0x00000400,
+ /**
+ Requests possibility to map the allocation (using vmaMapMemory() or #VMA_ALLOCATION_CREATE_MAPPED_BIT).
+
+ - If you use #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` value,
+ you must use this flag to be able to map the allocation. Otherwise, mapping is incorrect.
+ - If you use other value of #VmaMemoryUsage, this flag is ignored and mapping is always possible in memory types that are `HOST_VISIBLE`.
+ This includes allocations created in \ref custom_memory_pools.
+
+ Declares that mapped memory can be read, written, and accessed in random order,
+ so a `HOST_CACHED` memory type is required.
+ */
+ VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT = 0x00000800,
+ /**
+ Together with #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT,
+ it says that despite request for host access, a not-`HOST_VISIBLE` memory type can be selected
+ if it may improve performance.
+
+ By using this flag, you declare that you will check if the allocation ended up in a `HOST_VISIBLE` memory type
+ (e.g. using vmaGetAllocationMemoryProperties()) and if not, you will create some "staging" buffer and
+ issue an explicit transfer to write/read your data.
+ To prepare for this possibility, don't forget to add appropriate flags like
+ `VK_BUFFER_USAGE_TRANSFER_DST_BIT`, `VK_BUFFER_USAGE_TRANSFER_SRC_BIT` to the parameters of created buffer or image.
+ */
+ VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT = 0x00001000,
+ /** Allocation strategy that chooses smallest possible free range for the allocation
+ to minimize memory usage and fragmentation, possibly at the expense of allocation time.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = 0x00010000,
+ /** Allocation strategy that chooses first suitable free range for the allocation -
+ not necessarily in terms of the smallest offset but the one that is easiest and fastest to find
+ to minimize allocation time, possibly at the expense of allocation quality.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = 0x00020000,
+ /** Allocation strategy that chooses always the lowest offset in available space.
+ This is not the most efficient strategy but achieves highly packed data.
+ Used internally by defragmentation, not recomended in typical usage.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = 0x00040000,
+ /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,
+ /** Alias to #VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,
+ /** A bit mask to extract only `STRATEGY` bits from entire set of flags.
+ */
+ VMA_ALLOCATION_CREATE_STRATEGY_MASK =
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT |
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
+
+ VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaAllocationCreateFlagBits;
+/// See #VmaAllocationCreateFlagBits.
+typedef VkFlags VmaAllocationCreateFlags;
+
+/// Flags to be passed as VmaPoolCreateInfo::flags.
+typedef enum VmaPoolCreateFlagBits
+{
+ /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
+
+ This is an optional optimization flag.
+
+ If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
+ vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
+ knows exact type of your allocations so it can handle Buffer-Image Granularity
+ in the optimal way.
+
+ If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),
+ exact type of such allocations is not known, so allocator must be conservative
+ in handling Buffer-Image Granularity, which can lead to suboptimal allocation
+ (wasted memory). In that case, if you can make sure you always allocate only
+ buffers and linear images or only optimal images out of this pool, use this flag
+ to make allocator disregard Buffer-Image Granularity and so make allocations
+ faster and more optimal.
+ */
+ VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
+
+ /** \brief Enables alternative, linear allocation algorithm in this pool.
+
+ Specify this flag to enable linear allocation algorithm, which always creates
+ new allocations after last one and doesn't reuse space from allocations freed in
+ between. It trades memory consumption for simplified algorithm and data
+ structure, which has better performance and uses less memory for metadata.
+
+ By using this flag, you can achieve behavior of free-at-once, stack,
+ ring buffer, and double stack.
+ For details, see documentation chapter \ref linear_algorithm.
+ */
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
+
+ /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.
+ */
+ VMA_POOL_CREATE_ALGORITHM_MASK =
+ VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT,
+
+ VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaPoolCreateFlagBits;
+/// Flags to be passed as VmaPoolCreateInfo::flags. See #VmaPoolCreateFlagBits.
+typedef VkFlags VmaPoolCreateFlags;
+
+/// Flags to be passed as VmaDefragmentationInfo::flags.
+typedef enum VmaDefragmentationFlagBits
+{
+ /* \brief Use simple but fast algorithm for defragmentation.
+ May not achieve best results but will require least time to compute and least allocations to copy.
+ */
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT = 0x1,
+ /* \brief Default defragmentation algorithm, applied also when no `ALGORITHM` flag is specified.
+ Offers a balance between defragmentation quality and the amount of allocations and bytes that need to be moved.
+ */
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT = 0x2,
+ /* \brief Perform full defragmentation of memory.
+ Can result in notably more time to compute and allocations to copy, but will achieve best memory packing.
+ */
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT = 0x4,
+ /** \brief Use the most roboust algorithm at the cost of time to compute and number of copies to make.
+ Only available when bufferImageGranularity is greater than 1, since it aims to reduce
+ alignment issues between different types of resources.
+ Otherwise falls back to same behavior as #VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT.
+ */
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT = 0x8,
+
+ /// A bit mask to extract only `ALGORITHM` bits from entire set of flags.
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK =
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT |
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT |
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT |
+ VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT,
+
+ VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaDefragmentationFlagBits;
+/// See #VmaDefragmentationFlagBits.
+typedef VkFlags VmaDefragmentationFlags;
+
+/// Operation performed on single defragmentation move. See structure #VmaDefragmentationMove.
+typedef enum VmaDefragmentationMoveOperation
+{
+ /// Buffer/image has been recreated at `dstTmpAllocation`, data has been copied, old buffer/image has been destroyed. `srcAllocation` should be changed to point to the new place. This is the default value set by vmaBeginDefragmentationPass().
+ VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY = 0,
+ /// Set this value if you cannot move the allocation. New place reserved at `dstTmpAllocation` will be freed. `srcAllocation` will remain unchanged.
+ VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE = 1,
+ /// Set this value if you decide to abandon the allocation and you destroyed the buffer/image. New place reserved at `dstTmpAllocation` will be freed, along with `srcAllocation`, which will be destroyed.
+ VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY = 2,
+} VmaDefragmentationMoveOperation;
+
+/** @} */
+
+/**
+\addtogroup group_virtual
+@{
+*/
+
+/// Flags to be passed as VmaVirtualBlockCreateInfo::flags.
+typedef enum VmaVirtualBlockCreateFlagBits
+{
+ /** \brief Enables alternative, linear allocation algorithm in this virtual block.
+
+ Specify this flag to enable linear allocation algorithm, which always creates
+ new allocations after last one and doesn't reuse space from allocations freed in
+ between. It trades memory consumption for simplified algorithm and data
+ structure, which has better performance and uses less memory for metadata.
+
+ By using this flag, you can achieve behavior of free-at-once, stack,
+ ring buffer, and double stack.
+ For details, see documentation chapter \ref linear_algorithm.
+ */
+ VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT = 0x00000001,
+
+ /** \brief Bit mask to extract only `ALGORITHM` bits from entire set of flags.
+ */
+ VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK =
+ VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT,
+
+ VMA_VIRTUAL_BLOCK_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaVirtualBlockCreateFlagBits;
+/// Flags to be passed as VmaVirtualBlockCreateInfo::flags. See #VmaVirtualBlockCreateFlagBits.
+typedef VkFlags VmaVirtualBlockCreateFlags;
+
+/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags.
+typedef enum VmaVirtualAllocationCreateFlagBits
+{
+ /** \brief Allocation will be created from upper stack in a double stack pool.
+
+ This flag is only allowed for virtual blocks created with #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT flag.
+ */
+ VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT,
+ /** \brief Allocation strategy that tries to minimize memory usage.
+ */
+ VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT,
+ /** \brief Allocation strategy that tries to minimize allocation time.
+ */
+ VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT,
+ /** Allocation strategy that chooses always the lowest offset in available space.
+ This is not the most efficient strategy but achieves highly packed data.
+ */
+ VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT = VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
+ /** \brief A bit mask to extract only `STRATEGY` bits from entire set of flags.
+
+ These strategy flags are binary compatible with equivalent flags in #VmaAllocationCreateFlagBits.
+ */
+ VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK = VMA_ALLOCATION_CREATE_STRATEGY_MASK,
+
+ VMA_VIRTUAL_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
+} VmaVirtualAllocationCreateFlagBits;
+/// Flags to be passed as VmaVirtualAllocationCreateInfo::flags. See #VmaVirtualAllocationCreateFlagBits.
+typedef VkFlags VmaVirtualAllocationCreateFlags;
+
+/** @} */
+
+#endif // _VMA_ENUM_DECLARATIONS
+
+#ifndef _VMA_DATA_TYPES_DECLARATIONS
+
+/**
+\addtogroup group_init
+@{ */
+
+/** \struct VmaAllocator
+\brief Represents main object of this library initialized.
+
+Fill structure #VmaAllocatorCreateInfo and call function vmaCreateAllocator() to create it.
+Call function vmaDestroyAllocator() to destroy it.
+
+It is recommended to create just one object of this type per `VkDevice` object,
+right after Vulkan is initialized and keep it alive until before Vulkan device is destroyed.
+*/
+VK_DEFINE_HANDLE(VmaAllocator)
+
+/** @} */
+
+/**
+\addtogroup group_alloc
+@{
+*/
+
+/** \struct VmaPool
+\brief Represents custom memory pool
+
+Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.
+Call function vmaDestroyPool() to destroy it.
+
+For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).
+*/
+VK_DEFINE_HANDLE(VmaPool)
+
+/** \struct VmaAllocation
+\brief Represents single memory allocation.
+
+It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type
+plus unique offset.
+
+There are multiple ways to create such object.
+You need to fill structure VmaAllocationCreateInfo.
+For more information see [Choosing memory type](@ref choosing_memory_type).
+
+Although the library provides convenience functions that create Vulkan buffer or image,
+allocate memory for it and bind them together,
+binding of the allocation to a buffer or an image is out of scope of the allocation itself.
+Allocation object can exist without buffer/image bound,
+binding can be done manually by the user, and destruction of it can be done
+independently of destruction of the allocation.
+
+The object also remembers its size and some other information.
+To retrieve this information, use function vmaGetAllocationInfo() and inspect
+returned structure VmaAllocationInfo.
+*/
+VK_DEFINE_HANDLE(VmaAllocation)
+
+/** \struct VmaDefragmentationContext
+\brief An opaque object that represents started defragmentation process.
+
+Fill structure #VmaDefragmentationInfo and call function vmaBeginDefragmentation() to create it.
+Call function vmaEndDefragmentation() to destroy it.
+*/
+VK_DEFINE_HANDLE(VmaDefragmentationContext)
+
+/** @} */
+
+/**
+\addtogroup group_virtual
+@{
+*/
+
+/** \struct VmaVirtualAllocation
+\brief Represents single memory allocation done inside VmaVirtualBlock.
+
+Use it as a unique identifier to virtual allocation within the single block.
+
+Use value `VK_NULL_HANDLE` to represent a null/invalid allocation.
+*/
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaVirtualAllocation);
+
+/** @} */
+
+/**
+\addtogroup group_virtual
+@{
+*/
+
+/** \struct VmaVirtualBlock
+\brief Handle to a virtual block object that allows to use core allocation algorithm without allocating any real GPU memory.
+
+Fill in #VmaVirtualBlockCreateInfo structure and use vmaCreateVirtualBlock() to create it. Use vmaDestroyVirtualBlock() to destroy it.
+For more information, see documentation chapter \ref virtual_allocator.
+
+This object is not thread-safe - should not be used from multiple threads simultaneously, must be synchronized externally.
+*/
+VK_DEFINE_HANDLE(VmaVirtualBlock)
+
+/** @} */
+
+/**
+\addtogroup group_init
+@{
+*/
+
+/// Callback function called after successful vkAllocateMemory.
+typedef void (VKAPI_PTR* PFN_vmaAllocateDeviceMemoryFunction)(
+ VmaAllocator VMA_NOT_NULL allocator,
+ uint32_t memoryType,
+ VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,
+ VkDeviceSize size,
+ void* VMA_NULLABLE pUserData);
+
+/// Callback function called before vkFreeMemory.
+typedef void (VKAPI_PTR* PFN_vmaFreeDeviceMemoryFunction)(
+ VmaAllocator VMA_NOT_NULL allocator,
+ uint32_t memoryType,
+ VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory,
+ VkDeviceSize size,
+ void* VMA_NULLABLE pUserData);
+
+/** \brief Set of callbacks that the library will call for `vkAllocateMemory` and `vkFreeMemory`.
+
+Provided for informative purpose, e.g. to gather statistics about number of
+allocations or total amount of memory allocated in Vulkan.
+
+Used in VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+*/
+typedef struct VmaDeviceMemoryCallbacks
+{
+ /// Optional, can be null.
+ PFN_vmaAllocateDeviceMemoryFunction VMA_NULLABLE pfnAllocate;
+ /// Optional, can be null.
+ PFN_vmaFreeDeviceMemoryFunction VMA_NULLABLE pfnFree;
+ /// Optional, can be null.
+ void* VMA_NULLABLE pUserData;
+} VmaDeviceMemoryCallbacks;
+
/** \brief Pointers to some Vulkan functions - a subset used by the library.
Used in VmaAllocatorCreateInfo::pVulkanFunctions.
*/
-typedef struct VmaVulkanFunctions {
+typedef struct VmaVulkanFunctions
+{
+ /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS.
+ PFN_vkGetInstanceProcAddr VMA_NULLABLE vkGetInstanceProcAddr;
+ /// Required when using VMA_DYNAMIC_VULKAN_FUNCTIONS.
+ PFN_vkGetDeviceProcAddr VMA_NULLABLE vkGetDeviceProcAddr;
PFN_vkGetPhysicalDeviceProperties VMA_NULLABLE vkGetPhysicalDeviceProperties;
PFN_vkGetPhysicalDeviceMemoryProperties VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties;
PFN_vkAllocateMemory VMA_NULLABLE vkAllocateMemory;
@@ -2381,46 +978,28 @@ typedef struct VmaVulkanFunctions {
PFN_vkDestroyImage VMA_NULLABLE vkDestroyImage;
PFN_vkCmdCopyBuffer VMA_NULLABLE vkCmdCopyBuffer;
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
+ /// Fetch "vkGetBufferMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetBufferMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetBufferMemoryRequirements2KHR VMA_NULLABLE vkGetBufferMemoryRequirements2KHR;
+ /// Fetch "vkGetImageMemoryRequirements2" on Vulkan >= 1.1, fetch "vkGetImageMemoryRequirements2KHR" when using VK_KHR_dedicated_allocation extension.
PFN_vkGetImageMemoryRequirements2KHR VMA_NULLABLE vkGetImageMemoryRequirements2KHR;
#endif
#if VMA_BIND_MEMORY2 || VMA_VULKAN_VERSION >= 1001000
+ /// Fetch "vkBindBufferMemory2" on Vulkan >= 1.1, fetch "vkBindBufferMemory2KHR" when using VK_KHR_bind_memory2 extension.
PFN_vkBindBufferMemory2KHR VMA_NULLABLE vkBindBufferMemory2KHR;
+ /// Fetch "vkBindImageMemory2" on Vulkan >= 1.1, fetch "vkBindImageMemory2KHR" when using VK_KHR_bind_memory2 extension.
PFN_vkBindImageMemory2KHR VMA_NULLABLE vkBindImageMemory2KHR;
#endif
#if VMA_MEMORY_BUDGET || VMA_VULKAN_VERSION >= 1001000
PFN_vkGetPhysicalDeviceMemoryProperties2KHR VMA_NULLABLE vkGetPhysicalDeviceMemoryProperties2KHR;
#endif
+#if VMA_VULKAN_VERSION >= 1003000
+ /// Fetch from "vkGetDeviceBufferMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceBufferMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
+ PFN_vkGetDeviceBufferMemoryRequirements VMA_NULLABLE vkGetDeviceBufferMemoryRequirements;
+ /// Fetch from "vkGetDeviceImageMemoryRequirements" on Vulkan >= 1.3, but you can also fetch it from "vkGetDeviceImageMemoryRequirementsKHR" if you enabled extension VK_KHR_maintenance4.
+ PFN_vkGetDeviceImageMemoryRequirements VMA_NULLABLE vkGetDeviceImageMemoryRequirements;
+#endif
} VmaVulkanFunctions;
-/// Flags to be used in VmaRecordSettings::flags.
-typedef enum VmaRecordFlagBits {
- /** \brief Enables flush after recording every function call.
-
- Enable it if you expect your application to crash, which may leave recording file truncated.
- It may degrade performance though.
- */
- VMA_RECORD_FLUSH_AFTER_CALL_BIT = 0x00000001,
-
- VMA_RECORD_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VmaRecordFlagBits;
-typedef VkFlags VmaRecordFlags;
-
-/// Parameters for recording calls to VMA functions. To be used in VmaAllocatorCreateInfo::pRecordSettings.
-typedef struct VmaRecordSettings
-{
- /// Flags for recording. Use #VmaRecordFlagBits enum.
- VmaRecordFlags flags;
- /** \brief Path to the file that should be written by the recording.
-
- Suggested extension: "csv".
- If the file already exists, it will be overwritten.
- It will be opened for the whole time #VmaAllocator object is alive.
- If opening this file fails, creation of the whole allocator object fails.
- */
- const char* VMA_NOT_NULL pFilePath;
-} VmaRecordSettings;
-
/// Description of a Allocator to be created.
typedef struct VmaAllocatorCreateInfo
{
@@ -2441,20 +1020,6 @@ typedef struct VmaAllocatorCreateInfo
/// Informative callbacks for `vkAllocateMemory`, `vkFreeMemory`. Optional.
/** Optional, can be null. */
const VmaDeviceMemoryCallbacks* VMA_NULLABLE pDeviceMemoryCallbacks;
- /** \brief Maximum number of additional frames that are in use at the same time as current frame.
-
- This value is used only when you make allocations with
- VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
- lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
-
- For example, if you double-buffer your command buffers, so resources used for
- rendering in previous frame may still be in use by the GPU at the moment you
- allocate resources needed for the current frame, set this value to 1.
-
- If you want to allow any allocations other than used in the current frame to
- become lost, set this value to 0.
- */
- uint32_t frameInUseCount;
/** \brief Either null or a pointer to an array of limits on maximum number of bytes that can be allocated out of particular Vulkan memory heap.
If not NULL, it must be a pointer to an array of
@@ -2486,13 +1051,6 @@ typedef struct VmaAllocatorCreateInfo
For details see [Pointers to Vulkan functions](@ref config_Vulkan_functions).
*/
const VmaVulkanFunctions* VMA_NULLABLE pVulkanFunctions;
- /** \brief Parameters for recording of VMA calls. Can be null.
-
- If not null, it enables recording of calls to VMA functions to a file.
- If support for recording is not enabled using `VMA_RECORDING_ENABLED` macro,
- creation of the allocator object fails with `VK_ERROR_FEATURE_NOT_PRESENT`.
- */
- const VmaRecordSettings* VMA_NULLABLE pRecordSettings;
/** \brief Handle to Vulkan instance object.
Starting from version 3.0.0 this member is no longer optional, it must be set!
@@ -2503,7 +1061,7 @@ typedef struct VmaAllocatorCreateInfo
It must be a value in the format as created by macro `VK_MAKE_VERSION` or a constant like: `VK_API_VERSION_1_1`, `VK_API_VERSION_1_0`.
The patch version number specified is ignored. Only the major and minor versions are considered.
It must be less or equal (preferably equal) to value as passed to `vkCreateInstance` as `VkApplicationInfo::apiVersion`.
- Only versions 1.0, 1.1, 1.2 are supported by the current implementation.
+ Only versions 1.0, 1.1, 1.2, 1.3 are supported by the current implementation.
Leaving it initialized to zero is equivalent to `VK_API_VERSION_1_0`.
*/
uint32_t vulkanApiVersion;
@@ -2521,17 +1079,7 @@ typedef struct VmaAllocatorCreateInfo
#endif // #if VMA_EXTERNAL_MEMORY
} VmaAllocatorCreateInfo;
-/// Creates Allocator object.
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
- const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo,
- VmaAllocator VMA_NULLABLE * VMA_NOT_NULL pAllocator);
-
-/// Destroys allocator object.
-VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
- VmaAllocator VMA_NULLABLE allocator);
-
-/** \brief Information about existing #VmaAllocator object.
-*/
+/// Information about existing #VmaAllocator object.
typedef struct VmaAllocatorInfo
{
/** \brief Handle to Vulkan instance object.
@@ -2551,404 +1099,566 @@ typedef struct VmaAllocatorInfo
VkDevice VMA_NOT_NULL device;
} VmaAllocatorInfo;
-/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc.
-
-It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to
-`VkPhysicalDevice`, `VkDevice` etc. every time using this function.
-*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(VmaAllocator VMA_NOT_NULL allocator, VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo);
+/** @} */
/**
-PhysicalDeviceProperties are fetched from physicalDevice by the allocator.
-You can access it here, without fetching it again on your own.
+\addtogroup group_stats
+@{
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
- VmaAllocator VMA_NOT_NULL allocator,
- const VkPhysicalDeviceProperties* VMA_NULLABLE * VMA_NOT_NULL ppPhysicalDeviceProperties);
-/**
-PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.
-You can access it here, without fetching it again on your own.
+/** \brief Calculated statistics of memory usage e.g. in a specific memory type, heap, custom pool, or total.
+
+These are fast to calculate.
+See functions: vmaGetHeapBudgets(), vmaGetPoolStatistics().
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
- VmaAllocator VMA_NOT_NULL allocator,
- const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE * VMA_NOT_NULL ppPhysicalDeviceMemoryProperties);
+typedef struct VmaStatistics
+{
+ /** \brief Number of `VkDeviceMemory` objects - Vulkan memory blocks allocated.
+ */
+ uint32_t blockCount;
+ /** \brief Number of #VmaAllocation objects allocated.
-/**
-\brief Given Memory Type Index, returns Property Flags of this memory type.
+ Dedicated allocations have their own blocks, so each one adds 1 to `allocationCount` as well as `blockCount`.
+ */
+ uint32_t allocationCount;
+ /** \brief Number of bytes allocated in `VkDeviceMemory` blocks.
-This is just a convenience function. Same information can be obtained using
-vmaGetMemoryProperties().
-*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
- VmaAllocator VMA_NOT_NULL allocator,
- uint32_t memoryTypeIndex,
- VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
+ \note To avoid confusion, please be aware that what Vulkan calls an "allocation" - a whole `VkDeviceMemory` object
+ (e.g. as in `VkPhysicalDeviceLimits::maxMemoryAllocationCount`) is called a "block" in VMA, while VMA calls
+ "allocation" a #VmaAllocation object that represents a memory region sub-allocated from such block, usually for a single buffer or image.
+ */
+ VkDeviceSize blockBytes;
+ /** \brief Total number of bytes occupied by all #VmaAllocation objects.
-/** \brief Sets index of the current frame.
+ Always less or equal than `blockBytes`.
+ Difference `(blockBytes - allocationBytes)` is the amount of memory allocated from Vulkan
+ but unused by any #VmaAllocation.
+ */
+ VkDeviceSize allocationBytes;
+} VmaStatistics;
-This function must be used if you make allocations with
-#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT and
-#VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flags to inform the allocator
-when a new frame begins. Allocations queried using vmaGetAllocationInfo() cannot
-become lost in the current frame.
-*/
-VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
- VmaAllocator VMA_NOT_NULL allocator,
- uint32_t frameIndex);
+/** \brief More detailed statistics than #VmaStatistics.
+
+These are slower to calculate. Use for debugging purposes.
+See functions: vmaCalculateStatistics(), vmaCalculatePoolStatistics().
-/** \brief Calculated statistics of memory usage in entire allocator.
+Previous version of the statistics API provided averages, but they have been removed
+because they can be easily calculated as:
+
+\code
+VkDeviceSize allocationSizeAvg = detailedStats.statistics.allocationBytes / detailedStats.statistics.allocationCount;
+VkDeviceSize unusedBytes = detailedStats.statistics.blockBytes - detailedStats.statistics.allocationBytes;
+VkDeviceSize unusedRangeSizeAvg = unusedBytes / detailedStats.unusedRangeCount;
+\endcode
*/
-typedef struct VmaStatInfo
+typedef struct VmaDetailedStatistics
{
- /// Number of `VkDeviceMemory` Vulkan memory blocks allocated.
- uint32_t blockCount;
- /// Number of #VmaAllocation allocation objects allocated.
- uint32_t allocationCount;
+ /// Basic statistics.
+ VmaStatistics statistics;
/// Number of free ranges of memory between allocations.
uint32_t unusedRangeCount;
- /// Total number of bytes occupied by all allocations.
- VkDeviceSize usedBytes;
- /// Total number of bytes occupied by unused ranges.
- VkDeviceSize unusedBytes;
- VkDeviceSize allocationSizeMin, allocationSizeAvg, allocationSizeMax;
- VkDeviceSize unusedRangeSizeMin, unusedRangeSizeAvg, unusedRangeSizeMax;
-} VmaStatInfo;
-
-/// General statistics from current state of Allocator.
-typedef struct VmaStats
-{
- VmaStatInfo memoryType[VK_MAX_MEMORY_TYPES];
- VmaStatInfo memoryHeap[VK_MAX_MEMORY_HEAPS];
- VmaStatInfo total;
-} VmaStats;
-
-/** \brief Retrieves statistics from current state of the Allocator.
+ /// Smallest allocation size. `VK_WHOLE_SIZE` if there are 0 allocations.
+ VkDeviceSize allocationSizeMin;
+ /// Largest allocation size. 0 if there are 0 allocations.
+ VkDeviceSize allocationSizeMax;
+ /// Smallest empty range size. `VK_WHOLE_SIZE` if there are 0 empty ranges.
+ VkDeviceSize unusedRangeSizeMin;
+ /// Largest empty range size. 0 if there are 0 empty ranges.
+ VkDeviceSize unusedRangeSizeMax;
+} VmaDetailedStatistics;
-This function is called "calculate" not "get" because it has to traverse all
-internal data structures, so it may be quite slow. For faster but more brief statistics
-suitable to be called every frame or every allocation, use vmaGetBudget().
+/** \brief General statistics from current state of the Allocator -
+total memory usage across all memory heaps and types.
-Note that when using allocator from multiple threads, returned information may immediately
-become outdated.
+These are slower to calculate. Use for debugging purposes.
+See function vmaCalculateStatistics().
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
- VmaAllocator VMA_NOT_NULL allocator,
- VmaStats* VMA_NOT_NULL pStats);
+typedef struct VmaTotalStatistics
+{
+ VmaDetailedStatistics memoryType[VK_MAX_MEMORY_TYPES];
+ VmaDetailedStatistics memoryHeap[VK_MAX_MEMORY_HEAPS];
+ VmaDetailedStatistics total;
+} VmaTotalStatistics;
+
+/** \brief Statistics of current memory usage and available budget for a specific memory heap.
-/** \brief Statistics of current memory usage and available budget, in bytes, for specific memory heap.
+These are fast to calculate.
+See function vmaGetHeapBudgets().
*/
typedef struct VmaBudget
{
- /** \brief Sum size of all `VkDeviceMemory` blocks allocated from particular heap, in bytes.
- */
- VkDeviceSize blockBytes;
-
- /** \brief Sum size of all allocations created in particular heap, in bytes.
-
- Usually less or equal than `blockBytes`.
- Difference `blockBytes - allocationBytes` is the amount of memory allocated but unused -
- available for new allocations or wasted due to fragmentation.
-
- It might be greater than `blockBytes` if there are some allocations in lost state, as they account
- to this value as well.
+ /** \brief Statistics fetched from the library.
*/
- VkDeviceSize allocationBytes;
-
+ VmaStatistics statistics;
/** \brief Estimated current memory usage of the program, in bytes.
- Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+ Fetched from system using VK_EXT_memory_budget extension if enabled.
- It might be different than `blockBytes` (usually higher) due to additional implicit objects
+ It might be different than `statistics.blockBytes` (usually higher) due to additional implicit objects
also occupying the memory, like swapchain, pipelines, descriptor heaps, command buffers, or
`VkDeviceMemory` blocks allocated outside of this library, if any.
*/
VkDeviceSize usage;
-
/** \brief Estimated amount of memory available to the program, in bytes.
- Fetched from system using `VK_EXT_memory_budget` extension if enabled.
+ Fetched from system using VK_EXT_memory_budget extension if enabled.
It might be different (most probably smaller) than `VkMemoryHeap::size[heapIndex]` due to factors
- external to the program, like other programs also consuming system resources.
+ external to the program, decided by the operating system.
Difference `budget - usage` is the amount of additional memory that can probably
be allocated without problems. Exceeding the budget may result in various problems.
*/
VkDeviceSize budget;
} VmaBudget;
-/** \brief Retrieves information about current memory budget for all memory heaps.
+/** @} */
-\param[out] pBudget Must point to array with number of elements at least equal to number of memory heaps in physical device used.
+/**
+\addtogroup group_alloc
+@{
+*/
-This function is called "get" not "calculate" because it is very fast, suitable to be called
-every frame or every allocation. For more detailed statistics use vmaCalculateStats().
+/** \brief Parameters of new #VmaAllocation.
-Note that when using allocator from multiple threads, returned information may immediately
-become outdated.
+To be used with functions like vmaCreateBuffer(), vmaCreateImage(), and many others.
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
- VmaAllocator VMA_NOT_NULL allocator,
- VmaBudget* VMA_NOT_NULL pBudget);
-
-#ifndef VMA_STATS_STRING_ENABLED
-#define VMA_STATS_STRING_ENABLED 1
-#endif
+typedef struct VmaAllocationCreateInfo
+{
+ /// Use #VmaAllocationCreateFlagBits enum.
+ VmaAllocationCreateFlags flags;
+ /** \brief Intended usage of memory.
-#if VMA_STATS_STRING_ENABLED
+ You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.
+ */
+ VmaMemoryUsage usage;
+ /** \brief Flags that must be set in a Memory Type chosen for an allocation.
-/// Builds and returns statistics as string in JSON format.
-/** @param[out] ppStatsString Must be freed using vmaFreeStatsString() function.
-*/
-VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
- VmaAllocator VMA_NOT_NULL allocator,
- char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString,
- VkBool32 detailedMap);
+ Leave 0 if you specify memory requirements in other way. \n
+ If `pool` is not null, this member is ignored.*/
+ VkMemoryPropertyFlags requiredFlags;
+ /** \brief Flags that preferably should be set in a memory type chosen for an allocation.
-VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
- VmaAllocator VMA_NOT_NULL allocator,
- char* VMA_NULLABLE pStatsString);
+ Set to 0 if no additional flags are preferred. \n
+ If `pool` is not null, this member is ignored. */
+ VkMemoryPropertyFlags preferredFlags;
+ /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
-#endif // #if VMA_STATS_STRING_ENABLED
+ Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
+ it meets other requirements specified by this structure, with no further
+ restrictions on memory type index. \n
+ If `pool` is not null, this member is ignored.
+ */
+ uint32_t memoryTypeBits;
+ /** \brief Pool that this allocation should be created in.
-/** \struct VmaPool
-\brief Represents custom memory pool
+ Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
+ `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
+ */
+ VmaPool VMA_NULLABLE pool;
+ /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
-Fill structure VmaPoolCreateInfo and call function vmaCreatePool() to create it.
-Call function vmaDestroyPool() to destroy it.
+ If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
+ null or pointer to a null-terminated string. The string will be then copied to
+ internal buffer, so it doesn't need to be valid after allocation call.
+ */
+ void* VMA_NULLABLE pUserData;
+ /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
-For more information see [Custom memory pools](@ref choosing_memory_type_custom_memory_pools).
-*/
-VK_DEFINE_HANDLE(VmaPool)
+ It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object
+ and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+ Otherwise, it has the priority of a memory block where it is placed and this variable is ignored.
+ */
+ float priority;
+} VmaAllocationCreateInfo;
-typedef enum VmaMemoryUsage
+/// Describes parameter of created #VmaPool.
+typedef struct VmaPoolCreateInfo
{
- /** No intended memory usage specified.
- Use other members of VmaAllocationCreateInfo to specify your requirements.
+ /** \brief Vulkan memory type index to allocate this pool from.
*/
- VMA_MEMORY_USAGE_UNKNOWN = 0,
- /** Memory will be used on device only, so fast access from the device is preferred.
- It usually means device-local GPU (video) memory.
- No need to be mappable on host.
- It is roughly equivalent of `D3D12_HEAP_TYPE_DEFAULT`.
-
- Usage:
+ uint32_t memoryTypeIndex;
+ /** \brief Use combination of #VmaPoolCreateFlagBits.
+ */
+ VmaPoolCreateFlags flags;
+ /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
- - Resources written and read by device, e.g. images used as attachments.
- - Resources transferred from host once (immutable) or infrequently and read by
- device multiple times, e.g. textures to be sampled, vertex buffers, uniform
- (constant) buffers, and majority of other types of resources used on GPU.
+ Specify nonzero to set explicit, constant size of memory blocks used by this
+ pool.
- Allocation may still end up in `HOST_VISIBLE` memory on some implementations.
- In such case, you are free to map it.
- You can use #VMA_ALLOCATION_CREATE_MAPPED_BIT with this usage type.
- */
- VMA_MEMORY_USAGE_GPU_ONLY = 1,
- /** Memory will be mappable on host.
- It usually means CPU (system) memory.
- Guarantees to be `HOST_VISIBLE` and `HOST_COHERENT`.
- CPU access is typically uncached. Writes may be write-combined.
- Resources created in this pool may still be accessible to the device, but access to them can be slow.
- It is roughly equivalent of `D3D12_HEAP_TYPE_UPLOAD`.
-
- Usage: Staging copy of resources used as transfer source.
+ Leave 0 to use default and let the library manage block sizes automatically.
+ Sizes of particular blocks may vary.
+ In this case, the pool will also support dedicated allocations.
*/
- VMA_MEMORY_USAGE_CPU_ONLY = 2,
- /**
- Memory that is both mappable on host (guarantees to be `HOST_VISIBLE`) and preferably fast to access by GPU.
- CPU access is typically uncached. Writes may be write-combined.
+ VkDeviceSize blockSize;
+ /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.
- Usage: Resources written frequently by host (dynamic), read by device. E.g. textures (with LINEAR layout), vertex buffers, uniform buffers updated every frame or every draw call.
+ Set to 0 to have no preallocated blocks and allow the pool be completely empty.
*/
- VMA_MEMORY_USAGE_CPU_TO_GPU = 3,
- /** Memory mappable on host (guarantees to be `HOST_VISIBLE`) and cached.
- It is roughly equivalent of `D3D12_HEAP_TYPE_READBACK`.
+ size_t minBlockCount;
+ /** \brief Maximum number of blocks that can be allocated in this pool. Optional.
- Usage:
+ Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
- - Resources written by device, read by host - results of some computations, e.g. screen capture, average scene luminance for HDR tone mapping.
- - Any resources read or accessed randomly on host, e.g. CPU-side copy of vertex buffer used as source of transfer, but also used for collision detection.
+ Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
+ throughout whole lifetime of this pool.
*/
- VMA_MEMORY_USAGE_GPU_TO_CPU = 4,
- /** CPU memory - memory that is preferably not `DEVICE_LOCAL`, but also not guaranteed to be `HOST_VISIBLE`.
+ size_t maxBlockCount;
+ /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations.
- Usage: Staging copy of resources moved from GPU memory to CPU memory as part
- of custom paging/residency mechanism, to be moved back to GPU memory when needed.
+ It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object.
+ Otherwise, this variable is ignored.
*/
- VMA_MEMORY_USAGE_CPU_COPY = 5,
- /** Lazily allocated GPU memory having `VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT`.
- Exists mostly on mobile platforms. Using it on desktop PC or other GPUs with no such memory type present will fail the allocation.
+ float priority;
+ /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
- Usage: Memory for transient attachment images (color attachments, depth attachments etc.), created with `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`.
+ Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
+ It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,
+ e.g. when doing interop with OpenGL.
+ */
+ VkDeviceSize minAllocationAlignment;
+ /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional.
- Allocations with this usage are always created as dedicated - it implies #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+ Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`.
+ It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`.
+ Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool.
+
+ Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,
+ can be attached automatically by this library when using other, more convenient of its features.
*/
- VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED = 6,
+ void* VMA_NULLABLE pMemoryAllocateNext;
+} VmaPoolCreateInfo;
- VMA_MEMORY_USAGE_MAX_ENUM = 0x7FFFFFFF
-} VmaMemoryUsage;
+/** @} */
-/// Flags to be passed as VmaAllocationCreateInfo::flags.
-typedef enum VmaAllocationCreateFlagBits {
- /** \brief Set this flag if the allocation should have its own memory block.
+/**
+\addtogroup group_alloc
+@{
+*/
- Use it for special, big resources, like fullscreen images used as attachments.
+/// Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
+typedef struct VmaAllocationInfo
+{
+ /** \brief Memory type index that this allocation was allocated from.
- You should not use this flag if VmaAllocationCreateInfo::pool is not null.
+ It never changes.
*/
- VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT = 0x00000001,
-
- /** \brief Set this flag to only try to allocate from existing `VkDeviceMemory` blocks and never create new such block.
+ uint32_t memoryType;
+ /** \brief Handle to Vulkan memory object.
- If new allocation cannot be placed in any of the existing blocks, allocation
- fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+ Same memory object can be shared by multiple allocations.
- You should not use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT and
- #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT at the same time. It makes no sense.
+ It can change after the allocation is moved during \ref defragmentation.
+ */
+ VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory;
+ /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation.
- If VmaAllocationCreateInfo::pool is not null, this flag is implied and ignored. */
- VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT = 0x00000002,
- /** \brief Set this flag to use a memory that will be persistently mapped and retrieve pointer to it.
+ You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function
+ vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,
+ not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation
+ and apply this offset automatically.
- Pointer to mapped memory will be returned through VmaAllocationInfo::pMappedData.
+ It can change after the allocation is moved during \ref defragmentation.
+ */
+ VkDeviceSize offset;
+ /** \brief Size of this allocation, in bytes.
- It is valid to use this flag for allocation made from memory type that is not
- `HOST_VISIBLE`. This flag is then ignored and memory is not mapped. This is
- useful if you need an allocation that is efficient to use on GPU
- (`DEVICE_LOCAL`) and still want to map it directly if possible on platforms that
- support it (e.g. Intel GPU).
+ It never changes.
- You should not use this flag together with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT.
+ \note Allocation size returned in this variable may be greater than the size
+ requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the
+ allocation is accessible for operations on memory e.g. using a pointer after
+ mapping with vmaMapMemory(), but operations on the resource e.g. using
+ `vkCmdCopyBuffer` must be limited to the size of the resource.
*/
- VMA_ALLOCATION_CREATE_MAPPED_BIT = 0x00000004,
- /** Allocation created with this flag can become lost as a result of another
- allocation with #VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT flag, so you
- must check it before use.
-
- To check if allocation is not lost, call vmaGetAllocationInfo() and check if
- VmaAllocationInfo::deviceMemory is not `VK_NULL_HANDLE`.
+ VkDeviceSize size;
+ /** \brief Pointer to the beginning of this allocation as mapped data.
- For details about supporting lost allocations, see Lost Allocations
- chapter of User Guide on Main Page.
+ If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
+ created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null.
- You should not use this flag together with #VMA_ALLOCATION_CREATE_MAPPED_BIT.
+ It can change after call to vmaMapMemory(), vmaUnmapMemory().
+ It can also change after the allocation is moved during \ref defragmentation.
*/
- VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT = 0x00000008,
- /** While creating allocation using this flag, other allocations that were
- created with flag #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT can become lost.
+ void* VMA_NULLABLE pMappedData;
+ /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
- For details about supporting lost allocations, see Lost Allocations
- chapter of User Guide on Main Page.
- */
- VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT = 0x00000010,
- /** Set this flag to treat VmaAllocationCreateInfo::pUserData as pointer to a
- null-terminated string. Instead of copying pointer value, a local copy of the
- string is made and stored in allocation's `pUserData`. The string is automatically
- freed together with the allocation. It is also used in vmaBuildStatsString().
+ It can change after call to vmaSetAllocationUserData() for this allocation.
*/
- VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT = 0x00000020,
- /** Allocation will be created from upper stack in a double stack pool.
+ void* VMA_NULLABLE pUserData;
+ /** \brief Custom allocation name that was set with vmaSetAllocationName().
- This flag is only allowed for custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT flag.
- */
- VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT = 0x00000040,
- /** Create both buffer/image and allocation, but don't bind them together.
- It is useful when you want to bind yourself to do some more advanced binding, e.g. using some extensions.
- The flag is meaningful only with functions that bind by default: vmaCreateBuffer(), vmaCreateImage().
- Otherwise it is ignored.
- */
- VMA_ALLOCATION_CREATE_DONT_BIND_BIT = 0x00000080,
- /** Create allocation only if additional device memory required for it, if any, won't exceed
- memory budget. Otherwise return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+ It can change after call to vmaSetAllocationName() for this allocation.
+
+ Another way to set custom name is to pass it in VmaAllocationCreateInfo::pUserData with
+ additional flag #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT set [DEPRECATED].
*/
- VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT = 0x00000100,
+ const char* VMA_NULLABLE pName;
+} VmaAllocationInfo;
+
+/** \brief Parameters for defragmentation.
+
+To be used with function vmaBeginDefragmentation().
+*/
+typedef struct VmaDefragmentationInfo
+{
+ /// \brief Use combination of #VmaDefragmentationFlagBits.
+ VmaDefragmentationFlags flags;
+ /** \brief Custom pool to be defragmented.
- /** Allocation strategy that chooses smallest possible free range for the
- allocation.
+ If null then default pools will undergo defragmentation process.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT = 0x00010000,
- /** Allocation strategy that chooses biggest possible free range for the
- allocation.
+ VmaPool VMA_NULLABLE pool;
+ /** \brief Maximum numbers of bytes that can be copied during single pass, while moving allocations to different places.
+
+ `0` means no limit.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT = 0x00020000,
- /** Allocation strategy that chooses first suitable free range for the
- allocation.
+ VkDeviceSize maxBytesPerPass;
+ /** \brief Maximum number of allocations that can be moved during single pass to a different place.
- "First" doesn't necessarily means the one with smallest offset in memory,
- but rather the one that is easiest and fastest to find.
+ `0` means no limit.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT = 0x00040000,
+ uint32_t maxAllocationsPerPass;
+} VmaDefragmentationInfo;
- /** Allocation strategy that tries to minimize memory usage.
+/// Single move of an allocation to be done for defragmentation.
+typedef struct VmaDefragmentationMove
+{
+ /// Operation to be performed on the allocation by vmaEndDefragmentationPass(). Default value is #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY. You can modify it.
+ VmaDefragmentationMoveOperation operation;
+ /// Allocation that should be moved.
+ VmaAllocation VMA_NOT_NULL srcAllocation;
+ /** \brief Temporary allocation pointing to destination memory that will replace `srcAllocation`.
+
+ \warning Do not store this allocation in your data structures! It exists only temporarily, for the duration of the defragmentation pass,
+ to be used for binding new buffer/image to the destination memory using e.g. vmaBindBufferMemory().
+ vmaEndDefragmentationPass() will destroy it and make `srcAllocation` point to this memory.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT,
- /** Allocation strategy that tries to minimize allocation time.
+ VmaAllocation VMA_NOT_NULL dstTmpAllocation;
+} VmaDefragmentationMove;
+
+/** \brief Parameters for incremental defragmentation steps.
+
+To be used with function vmaBeginDefragmentationPass().
+*/
+typedef struct VmaDefragmentationPassMoveInfo
+{
+ /// Number of elements in the `pMoves` array.
+ uint32_t moveCount;
+ /** \brief Array of moves to be performed by the user in the current defragmentation pass.
+
+ Pointer to an array of `moveCount` elements, owned by VMA, created in vmaBeginDefragmentationPass(), destroyed in vmaEndDefragmentationPass().
+
+ For each element, you should:
+
+ 1. Create a new buffer/image in the place pointed by VmaDefragmentationMove::dstMemory + VmaDefragmentationMove::dstOffset.
+ 2. Copy data from the VmaDefragmentationMove::srcAllocation e.g. using `vkCmdCopyBuffer`, `vkCmdCopyImage`.
+ 3. Make sure these commands finished executing on the GPU.
+ 4. Destroy the old buffer/image.
+
+ Only then you can finish defragmentation pass by calling vmaEndDefragmentationPass().
+ After this call, the allocation will point to the new place in memory.
+
+ Alternatively, if you cannot move specific allocation, you can set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
+
+ Alternatively, if you decide you want to completely remove the allocation:
+
+ 1. Destroy its buffer/image.
+ 2. Set VmaDefragmentationMove::operation to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY.
+
+ Then, after vmaEndDefragmentationPass() the allocation will be freed.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT = VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
- /** Allocation strategy that tries to minimize memory fragmentation.
+ VmaDefragmentationMove* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(moveCount) pMoves;
+} VmaDefragmentationPassMoveInfo;
+
+/// Statistics returned for defragmentation process in function vmaEndDefragmentation().
+typedef struct VmaDefragmentationStats
+{
+ /// Total number of bytes that have been copied while moving allocations to different places.
+ VkDeviceSize bytesMoved;
+ /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.
+ VkDeviceSize bytesFreed;
+ /// Number of allocations that have been moved to different places.
+ uint32_t allocationsMoved;
+ /// Number of empty `VkDeviceMemory` objects that have been released to the system.
+ uint32_t deviceMemoryBlocksFreed;
+} VmaDefragmentationStats;
+
+/** @} */
+
+/**
+\addtogroup group_virtual
+@{
+*/
+
+/// Parameters of created #VmaVirtualBlock object to be passed to vmaCreateVirtualBlock().
+typedef struct VmaVirtualBlockCreateInfo
+{
+ /** \brief Total size of the virtual block.
+
+ Sizes can be expressed in bytes or any units you want as long as you are consistent in using them.
+ For example, if you allocate from some array of structures, 1 can mean single instance of entire structure.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT = VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT,
+ VkDeviceSize size;
- /** A bit mask to extract only `STRATEGY` bits from entire set of flags.
+ /** \brief Use combination of #VmaVirtualBlockCreateFlagBits.
*/
- VMA_ALLOCATION_CREATE_STRATEGY_MASK =
- VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT |
- VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT |
- VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT,
+ VmaVirtualBlockCreateFlags flags;
- VMA_ALLOCATION_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VmaAllocationCreateFlagBits;
-typedef VkFlags VmaAllocationCreateFlags;
+ /** \brief Custom CPU memory allocation callbacks. Optional.
-typedef struct VmaAllocationCreateInfo
+ Optional, can be null. When specified, they will be used for all CPU-side memory allocations.
+ */
+ const VkAllocationCallbacks* VMA_NULLABLE pAllocationCallbacks;
+} VmaVirtualBlockCreateInfo;
+
+/// Parameters of created virtual allocation to be passed to vmaVirtualAllocate().
+typedef struct VmaVirtualAllocationCreateInfo
{
- /// Use #VmaAllocationCreateFlagBits enum.
- VmaAllocationCreateFlags flags;
- /** \brief Intended usage of memory.
+ /** \brief Size of the allocation.
- You can leave #VMA_MEMORY_USAGE_UNKNOWN if you specify memory requirements in other way. \n
- If `pool` is not null, this member is ignored.
+ Cannot be zero.
*/
- VmaMemoryUsage usage;
- /** \brief Flags that must be set in a Memory Type chosen for an allocation.
+ VkDeviceSize size;
+ /** \brief Required alignment of the allocation. Optional.
- Leave 0 if you specify memory requirements in other way. \n
- If `pool` is not null, this member is ignored.*/
- VkMemoryPropertyFlags requiredFlags;
- /** \brief Flags that preferably should be set in a memory type chosen for an allocation.
+ Must be power of two. Special value 0 has the same meaning as 1 - means no special alignment is required, so allocation can start at any offset.
+ */
+ VkDeviceSize alignment;
+ /** \brief Use combination of #VmaVirtualAllocationCreateFlagBits.
+ */
+ VmaVirtualAllocationCreateFlags flags;
+ /** \brief Custom pointer to be associated with the allocation. Optional.
- Set to 0 if no additional flags are preferred. \n
- If `pool` is not null, this member is ignored. */
- VkMemoryPropertyFlags preferredFlags;
- /** \brief Bitmask containing one bit set for every memory type acceptable for this allocation.
+ It can be any value and can be used for user-defined purposes. It can be fetched or changed later.
+ */
+ void* VMA_NULLABLE pUserData;
+} VmaVirtualAllocationCreateInfo;
- Value 0 is equivalent to `UINT32_MAX` - it means any memory type is accepted if
- it meets other requirements specified by this structure, with no further
- restrictions on memory type index. \n
- If `pool` is not null, this member is ignored.
+/// Parameters of an existing virtual allocation, returned by vmaGetVirtualAllocationInfo().
+typedef struct VmaVirtualAllocationInfo
+{
+ /** \brief Offset of the allocation.
+
+ Offset at which the allocation was made.
*/
- uint32_t memoryTypeBits;
- /** \brief Pool that this allocation should be created in.
+ VkDeviceSize offset;
+ /** \brief Size of the allocation.
- Leave `VK_NULL_HANDLE` to allocate from default pool. If not null, members:
- `usage`, `requiredFlags`, `preferredFlags`, `memoryTypeBits` are ignored.
+ Same value as passed in VmaVirtualAllocationCreateInfo::size.
*/
- VmaPool VMA_NULLABLE pool;
- /** \brief Custom general-purpose pointer that will be stored in #VmaAllocation, can be read as VmaAllocationInfo::pUserData and changed using vmaSetAllocationUserData().
+ VkDeviceSize size;
+ /** \brief Custom pointer associated with the allocation.
- If #VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is used, it must be either
- null or pointer to a null-terminated string. The string will be then copied to
- internal buffer, so it doesn't need to be valid after allocation call.
+ Same value as passed in VmaVirtualAllocationCreateInfo::pUserData or to vmaSetVirtualAllocationUserData().
*/
void* VMA_NULLABLE pUserData;
- /** \brief A floating-point value between 0 and 1, indicating the priority of the allocation relative to other memory allocations.
+} VmaVirtualAllocationInfo;
- It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object
- and this allocation ends up as dedicated or is explicitly forced as dedicated using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
- Otherwise, it has the priority of a memory block where it is placed and this variable is ignored.
- */
- float priority;
-} VmaAllocationCreateInfo;
+/** @} */
+
+#endif // _VMA_DATA_TYPES_DECLARATIONS
+
+#ifndef _VMA_FUNCTION_HEADERS
+
+/**
+\addtogroup group_init
+@{
+*/
+
+/// Creates #VmaAllocator object.
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
+ const VmaAllocatorCreateInfo* VMA_NOT_NULL pCreateInfo,
+ VmaAllocator VMA_NULLABLE* VMA_NOT_NULL pAllocator);
+
+/// Destroys allocator object.
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
+ VmaAllocator VMA_NULLABLE allocator);
+
+/** \brief Returns information about existing #VmaAllocator object - handle to Vulkan device etc.
+
+It might be useful if you want to keep just the #VmaAllocator handle and fetch other required handles to
+`VkPhysicalDevice`, `VkDevice` etc. every time using this function.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocatorInfo(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocatorInfo* VMA_NOT_NULL pAllocatorInfo);
+
+/**
+PhysicalDeviceProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPhysicalDeviceProperties(
+ VmaAllocator VMA_NOT_NULL allocator,
+ const VkPhysicalDeviceProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceProperties);
+
+/**
+PhysicalDeviceMemoryProperties are fetched from physicalDevice by the allocator.
+You can access it here, without fetching it again on your own.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryProperties(
+ VmaAllocator VMA_NOT_NULL allocator,
+ const VkPhysicalDeviceMemoryProperties* VMA_NULLABLE* VMA_NOT_NULL ppPhysicalDeviceMemoryProperties);
+
+/**
+\brief Given Memory Type Index, returns Property Flags of this memory type.
+
+This is just a convenience function. Same information can be obtained using
+vmaGetMemoryProperties().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetMemoryTypeProperties(
+ VmaAllocator VMA_NOT_NULL allocator,
+ uint32_t memoryTypeIndex,
+ VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
+
+/** \brief Sets index of the current frame.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
+ VmaAllocator VMA_NOT_NULL allocator,
+ uint32_t frameIndex);
+
+/** @} */
+
+/**
+\addtogroup group_stats
+@{
+*/
+
+/** \brief Retrieves statistics from current state of the Allocator.
+
+This function is called "calculate" not "get" because it has to traverse all
+internal data structures, so it may be quite slow. Use it for debugging purposes.
+For faster but more brief statistics suitable to be called every frame or every allocation,
+use vmaGetHeapBudgets().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaTotalStatistics* VMA_NOT_NULL pStats);
+
+/** \brief Retrieves information about current memory usage and budget for all memory heaps.
+
+\param allocator
+\param[out] pBudgets Must point to array with number of elements at least equal to number of memory heaps in physical device used.
+
+This function is called "get" not "calculate" because it is very fast, suitable to be called
+every frame or every allocation. For more detailed statistics use vmaCalculateStatistics().
+
+Note that when using allocator from multiple threads, returned information may immediately
+become outdated.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaBudget* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL("VkPhysicalDeviceMemoryProperties::memoryHeapCount") pBudgets);
+
+/** @} */
+
+/**
+\addtogroup group_alloc
+@{
+*/
/**
\brief Helps to find memoryTypeIndex, given memoryTypeBits and VmaAllocationCreateInfo.
@@ -2977,12 +1687,6 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
It internally creates a temporary, dummy buffer that never has memory bound.
-It is just a convenience function, equivalent to calling:
-
-- `vkCreateBuffer`
-- `vkGetBufferMemoryRequirements`
-- `vmaFindMemoryTypeIndex`
-- `vkDestroyBuffer`
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
VmaAllocator VMA_NOT_NULL allocator,
@@ -2995,12 +1699,6 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
It can be useful e.g. to determine value to be used as VmaPoolCreateInfo::memoryTypeIndex.
It internally creates a temporary, dummy image that never has memory bound.
-It is just a convenience function, equivalent to calling:
-
-- `vkCreateImage`
-- `vkGetImageMemoryRequirements`
-- `vmaFindMemoryTypeIndex`
-- `vkDestroyImage`
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
VmaAllocator VMA_NOT_NULL allocator,
@@ -3008,172 +1706,16 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,
uint32_t* VMA_NOT_NULL pMemoryTypeIndex);
-/// Flags to be passed as VmaPoolCreateInfo::flags.
-typedef enum VmaPoolCreateFlagBits {
- /** \brief Use this flag if you always allocate only buffers and linear images or only optimal images out of this pool and so Buffer-Image Granularity can be ignored.
-
- This is an optional optimization flag.
-
- If you always allocate using vmaCreateBuffer(), vmaCreateImage(),
- vmaAllocateMemoryForBuffer(), then you don't need to use it because allocator
- knows exact type of your allocations so it can handle Buffer-Image Granularity
- in the optimal way.
-
- If you also allocate using vmaAllocateMemoryForImage() or vmaAllocateMemory(),
- exact type of such allocations is not known, so allocator must be conservative
- in handling Buffer-Image Granularity, which can lead to suboptimal allocation
- (wasted memory). In that case, if you can make sure you always allocate only
- buffers and linear images or only optimal images out of this pool, use this flag
- to make allocator disregard Buffer-Image Granularity and so make allocations
- faster and more optimal.
- */
- VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT = 0x00000002,
-
- /** \brief Enables alternative, linear allocation algorithm in this pool.
-
- Specify this flag to enable linear allocation algorithm, which always creates
- new allocations after last one and doesn't reuse space from allocations freed in
- between. It trades memory consumption for simplified algorithm and data
- structure, which has better performance and uses less memory for metadata.
-
- By using this flag, you can achieve behavior of free-at-once, stack,
- ring buffer, and double stack. For details, see documentation chapter
- \ref linear_algorithm.
-
- When using this flag, you must specify VmaPoolCreateInfo::maxBlockCount == 1 (or 0 for default).
-
- For more details, see [Linear allocation algorithm](@ref linear_algorithm).
- */
- VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT = 0x00000004,
-
- /** \brief Enables alternative, buddy allocation algorithm in this pool.
-
- It operates on a tree of blocks, each having size that is a power of two and
- a half of its parent's size. Comparing to default algorithm, this one provides
- faster allocation and deallocation and decreased external fragmentation,
- at the expense of more memory wasted (internal fragmentation).
-
- For more details, see [Buddy allocation algorithm](@ref buddy_algorithm).
- */
- VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT = 0x00000008,
-
- /** Bit mask to extract only `ALGORITHM` bits from entire set of flags.
- */
- VMA_POOL_CREATE_ALGORITHM_MASK =
- VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT |
- VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT,
-
- VMA_POOL_CREATE_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VmaPoolCreateFlagBits;
-typedef VkFlags VmaPoolCreateFlags;
-
-/** \brief Describes parameter of created #VmaPool.
-*/
-typedef struct VmaPoolCreateInfo {
- /** \brief Vulkan memory type index to allocate this pool from.
- */
- uint32_t memoryTypeIndex;
- /** \brief Use combination of #VmaPoolCreateFlagBits.
- */
- VmaPoolCreateFlags flags;
- /** \brief Size of a single `VkDeviceMemory` block to be allocated as part of this pool, in bytes. Optional.
-
- Specify nonzero to set explicit, constant size of memory blocks used by this
- pool.
-
- Leave 0 to use default and let the library manage block sizes automatically.
- Sizes of particular blocks may vary.
- */
- VkDeviceSize blockSize;
- /** \brief Minimum number of blocks to be always allocated in this pool, even if they stay empty.
-
- Set to 0 to have no preallocated blocks and allow the pool be completely empty.
- */
- size_t minBlockCount;
- /** \brief Maximum number of blocks that can be allocated in this pool. Optional.
-
- Set to 0 to use default, which is `SIZE_MAX`, which means no limit.
-
- Set to same value as VmaPoolCreateInfo::minBlockCount to have fixed amount of memory allocated
- throughout whole lifetime of this pool.
- */
- size_t maxBlockCount;
- /** \brief Maximum number of additional frames that are in use at the same time as current frame.
-
- This value is used only when you make allocations with
- #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocation cannot become
- lost if allocation.lastUseFrameIndex >= allocator.currentFrameIndex - frameInUseCount.
-
- For example, if you double-buffer your command buffers, so resources used for
- rendering in previous frame may still be in use by the GPU at the moment you
- allocate resources needed for the current frame, set this value to 1.
-
- If you want to allow any allocations other than used in the current frame to
- become lost, set this value to 0.
- */
- uint32_t frameInUseCount;
- /** \brief A floating-point value between 0 and 1, indicating the priority of the allocations in this pool relative to other memory allocations.
-
- It is used only when #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT flag was used during creation of the #VmaAllocator object.
- Otherwise, this variable is ignored.
- */
- float priority;
- /** \brief Additional minimum alignment to be used for all allocations created from this pool. Can be 0.
-
- Leave 0 (default) not to impose any additional alignment. If not 0, it must be a power of two.
- It can be useful in cases where alignment returned by Vulkan by functions like `vkGetBufferMemoryRequirements` is not enough,
- e.g. when doing interop with OpenGL.
- */
- VkDeviceSize minAllocationAlignment;
- /** \brief Additional `pNext` chain to be attached to `VkMemoryAllocateInfo` used for every allocation made by this pool. Optional.
-
- Optional, can be null. If not null, it must point to a `pNext` chain of structures that can be attached to `VkMemoryAllocateInfo`.
- It can be useful for special needs such as adding `VkExportMemoryAllocateInfoKHR`.
- Structures pointed by this member must remain alive and unchanged for the whole lifetime of the custom pool.
-
- Please note that some structures, e.g. `VkMemoryPriorityAllocateInfoEXT`, `VkMemoryDedicatedAllocateInfoKHR`,
- can be attached automatically by this library when using other, more convenient of its features.
- */
- void* VMA_NULLABLE pMemoryAllocateNext;
-} VmaPoolCreateInfo;
-
-/** \brief Describes parameter of existing #VmaPool.
-*/
-typedef struct VmaPoolStats {
- /** \brief Total amount of `VkDeviceMemory` allocated from Vulkan for this pool, in bytes.
- */
- VkDeviceSize size;
- /** \brief Total number of bytes in the pool not used by any #VmaAllocation.
- */
- VkDeviceSize unusedSize;
- /** \brief Number of #VmaAllocation objects created from this pool that were not destroyed or lost.
- */
- size_t allocationCount;
- /** \brief Number of continuous memory ranges in the pool not used by any #VmaAllocation.
- */
- size_t unusedRangeCount;
- /** \brief Size of the largest continuous free memory region available for new allocation.
-
- Making a new allocation of that size is not guaranteed to succeed because of
- possible additional margin required to respect alignment and buffer/image
- granularity.
- */
- VkDeviceSize unusedRangeSizeMax;
- /** \brief Number of `VkDeviceMemory` blocks allocated for this pool.
- */
- size_t blockCount;
-} VmaPoolStats;
-
/** \brief Allocates Vulkan device memory and creates #VmaPool object.
-@param allocator Allocator object.
-@param pCreateInfo Parameters of pool to create.
-@param[out] pPool Handle to created pool.
+\param allocator Allocator object.
+\param pCreateInfo Parameters of pool to create.
+\param[out] pPool Handle to created pool.
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
VmaAllocator VMA_NOT_NULL allocator,
const VmaPoolCreateInfo* VMA_NOT_NULL pCreateInfo,
- VmaPool VMA_NULLABLE * VMA_NOT_NULL pPool);
+ VmaPool VMA_NULLABLE* VMA_NOT_NULL pPool);
/** \brief Destroys #VmaPool object and frees Vulkan device memory.
*/
@@ -3181,27 +1723,41 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
VmaAllocator VMA_NOT_NULL allocator,
VmaPool VMA_NULLABLE pool);
+/** @} */
+
+/**
+\addtogroup group_stats
+@{
+*/
+
/** \brief Retrieves statistics of existing #VmaPool object.
-@param allocator Allocator object.
-@param pool Pool object.
-@param[out] pPoolStats Statistics of specified pool.
+\param allocator Allocator object.
+\param pool Pool object.
+\param[out] pPoolStats Statistics of specified pool.
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
VmaAllocator VMA_NOT_NULL allocator,
VmaPool VMA_NOT_NULL pool,
- VmaPoolStats* VMA_NOT_NULL pPoolStats);
+ VmaStatistics* VMA_NOT_NULL pPoolStats);
-/** \brief Marks all allocations in given pool as lost if they are not used in current frame or VmaPoolCreateInfo::frameInUseCount back from now.
+/** \brief Retrieves detailed statistics of existing #VmaPool object.
-@param allocator Allocator object.
-@param pool Pool.
-@param[out] pLostAllocationCount Number of allocations marked as lost. Optional - pass null if you don't need this information.
+\param allocator Allocator object.
+\param pool Pool object.
+\param[out] pPoolStats Statistics of specified pool.
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics(
VmaAllocator VMA_NOT_NULL allocator,
VmaPool VMA_NOT_NULL pool,
- size_t* VMA_NULLABLE pLostAllocationCount);
+ VmaDetailedStatistics* VMA_NOT_NULL pPoolStats);
+
+/** @} */
+
+/**
+\addtogroup group_alloc
+@{
+*/
/** \brief Checks magic number in margins around all allocations in given memory pool in search for corruptions.
@@ -3213,11 +1769,13 @@ Possible return values:
- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for specified pool.
- `VK_SUCCESS` - corruption detection has been performed and succeeded.
-- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations.
`VMA_ASSERT` is also fired in that case.
- Other value: Error returned by Vulkan, e.g. memory mapping failure.
*/
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator VMA_NOT_NULL allocator, VmaPool VMA_NOT_NULL pool);
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaPool VMA_NOT_NULL pool);
/** \brief Retrieves name of a custom pool.
@@ -3228,7 +1786,7 @@ destroyed or its name is changed using vmaSetPoolName().
VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolName(
VmaAllocator VMA_NOT_NULL allocator,
VmaPool VMA_NOT_NULL pool,
- const char* VMA_NULLABLE * VMA_NOT_NULL ppName);
+ const char* VMA_NULLABLE* VMA_NOT_NULL ppName);
/** \brief Sets name of a custom pool.
@@ -3240,90 +1798,13 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
VmaPool VMA_NOT_NULL pool,
const char* VMA_NULLABLE pName);
-/** \struct VmaAllocation
-\brief Represents single memory allocation.
-
-It may be either dedicated block of `VkDeviceMemory` or a specific region of a bigger block of this type
-plus unique offset.
-
-There are multiple ways to create such object.
-You need to fill structure VmaAllocationCreateInfo.
-For more information see [Choosing memory type](@ref choosing_memory_type).
-
-Although the library provides convenience functions that create Vulkan buffer or image,
-allocate memory for it and bind them together,
-binding of the allocation to a buffer or an image is out of scope of the allocation itself.
-Allocation object can exist without buffer/image bound,
-binding can be done manually by the user, and destruction of it can be done
-independently of destruction of the allocation.
-
-The object also remembers its size and some other information.
-To retrieve this information, use function vmaGetAllocationInfo() and inspect
-returned structure VmaAllocationInfo.
-
-Some kinds allocations can be in lost state.
-For more information, see [Lost allocations](@ref lost_allocations).
-*/
-VK_DEFINE_HANDLE(VmaAllocation)
-
-/** \brief Parameters of #VmaAllocation objects, that can be retrieved using function vmaGetAllocationInfo().
-*/
-typedef struct VmaAllocationInfo {
- /** \brief Memory type index that this allocation was allocated from.
-
- It never changes.
- */
- uint32_t memoryType;
- /** \brief Handle to Vulkan memory object.
-
- Same memory object can be shared by multiple allocations.
-
- It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
-
- If the allocation is lost, it is equal to `VK_NULL_HANDLE`.
- */
- VkDeviceMemory VMA_NULLABLE_NON_DISPATCHABLE deviceMemory;
- /** \brief Offset in `VkDeviceMemory` object to the beginning of this allocation, in bytes. `(deviceMemory, offset)` pair is unique to this allocation.
-
- You usually don't need to use this offset. If you create a buffer or an image together with the allocation using e.g. function
- vmaCreateBuffer(), vmaCreateImage(), functions that operate on these resources refer to the beginning of the buffer or image,
- not entire device memory block. Functions like vmaMapMemory(), vmaBindBufferMemory() also refer to the beginning of the allocation
- and apply this offset automatically.
-
- It can change after call to vmaDefragment() if this allocation is passed to the function, or if allocation is lost.
- */
- VkDeviceSize offset;
- /** \brief Size of this allocation, in bytes.
-
- It never changes, unless allocation is lost.
-
- \note Allocation size returned in this variable may be greater than the size
- requested for the resource e.g. as `VkBufferCreateInfo::size`. Whole size of the
- allocation is accessible for operations on memory e.g. using a pointer after
- mapping with vmaMapMemory(), but operations on the resource e.g. using
- `vkCmdCopyBuffer` must be limited to the size of the resource.
- */
- VkDeviceSize size;
- /** \brief Pointer to the beginning of this allocation as mapped data.
-
- If the allocation hasn't been mapped using vmaMapMemory() and hasn't been
- created with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag, this value is null.
-
- It can change after call to vmaMapMemory(), vmaUnmapMemory().
- It can also change after call to vmaDefragment() if this allocation is passed to the function.
- */
- void* VMA_NULLABLE pMappedData;
- /** \brief Custom general-purpose pointer that was passed as VmaAllocationCreateInfo::pUserData or set using vmaSetAllocationUserData().
-
- It can change after call to vmaSetAllocationUserData() for this allocation.
- */
- void* VMA_NULLABLE pUserData;
-} VmaAllocationInfo;
-
/** \brief General purpose memory allocation.
-@param[out] pAllocation Handle to allocated memory.
-@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+\param allocator
+\param pVkMemoryRequirements
+\param pCreateInfo
+\param[out] pAllocation Handle to allocated memory.
+\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
@@ -3334,17 +1815,17 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
VmaAllocator VMA_NOT_NULL allocator,
const VkMemoryRequirements* VMA_NOT_NULL pVkMemoryRequirements,
const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
/** \brief General purpose memory allocation for multiple allocation objects at once.
-@param allocator Allocator object.
-@param pVkMemoryRequirements Memory requirements for each allocation.
-@param pCreateInfo Creation parameters for each alloction.
-@param allocationCount Number of allocations to make.
-@param[out] pAllocations Pointer to array that will be filled with handles to created allocations.
-@param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.
+\param allocator Allocator object.
+\param pVkMemoryRequirements Memory requirements for each allocation.
+\param pCreateInfo Creation parameters for each allocation.
+\param allocationCount Number of allocations to make.
+\param[out] pAllocations Pointer to array that will be filled with handles to created allocations.
+\param[out] pAllocationInfo Optional. Pointer to array that will be filled with parameters of created allocations.
You should free the memory using vmaFreeMemory() or vmaFreeMemoryPages().
@@ -3361,28 +1842,49 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
const VkMemoryRequirements* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pVkMemoryRequirements,
const VmaAllocationCreateInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pCreateInfo,
size_t allocationCount,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations,
VmaAllocationInfo* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationInfo);
-/**
-@param[out] pAllocation Handle to allocated memory.
-@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+/** \brief Allocates memory suitable for given `VkBuffer`.
+
+\param allocator
+\param buffer
+\param pCreateInfo
+\param[out] pAllocation Handle to allocated memory.
+\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
-You should free the memory using vmaFreeMemory().
+It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindBufferMemory().
+
+This is a special-purpose function. In most cases you should use vmaCreateBuffer().
+
+You must free the allocation using vmaFreeMemory() when no longer needed.
*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
VmaAllocator VMA_NOT_NULL allocator,
VkBuffer VMA_NOT_NULL_NON_DISPATCHABLE buffer,
const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
-/// Function similar to vmaAllocateMemoryForBuffer().
+/** \brief Allocates memory suitable for given `VkImage`.
+
+\param allocator
+\param image
+\param pCreateInfo
+\param[out] pAllocation Handle to allocated memory.
+\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+
+It only creates #VmaAllocation. To bind the memory to the buffer, use vmaBindImageMemory().
+
+This is a special-purpose function. In most cases you should use vmaCreateImage().
+
+You must free the allocation using vmaFreeMemory() when no longer needed.
+*/
VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
VmaAllocator VMA_NOT_NULL allocator,
VkImage VMA_NOT_NULL_NON_DISPATCHABLE image,
const VmaAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
/** \brief Frees memory previously allocated using vmaAllocateMemory(), vmaAllocateMemoryForBuffer(), or vmaAllocateMemoryForImage().
@@ -3406,58 +1908,27 @@ Passing `VK_NULL_HANDLE` as elements of `pAllocations` array is valid. Such entr
VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
VmaAllocator VMA_NOT_NULL allocator,
size_t allocationCount,
- const VmaAllocation VMA_NULLABLE * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations);
+ const VmaAllocation VMA_NULLABLE* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations);
-/** \brief Returns current information about specified allocation and atomically marks it as used in current frame.
+/** \brief Returns current information about specified allocation.
Current paramteres of given allocation are returned in `pAllocationInfo`.
-This function also atomically "touches" allocation - marks it as used in current frame,
-just like vmaTouchAllocation().
-If the allocation is in lost state, `pAllocationInfo->deviceMemory == VK_NULL_HANDLE`.
-
-Although this function uses atomics and doesn't lock any mutex, so it should be quite efficient,
-you can avoid calling it too often.
-
-- You can retrieve same VmaAllocationInfo structure while creating your resource, from function
- vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change
- (e.g. due to defragmentation or allocation becoming lost).
-- If you just want to check if allocation is not lost, vmaTouchAllocation() will work faster.
+Although this function doesn't lock any mutex, so it should be quite efficient,
+you should avoid calling it too often.
+You can retrieve same VmaAllocationInfo structure while creating your resource, from function
+vmaCreateBuffer(), vmaCreateImage(). You can remember it if you are sure parameters don't change
+(e.g. due to defragmentation).
*/
VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
VmaAllocator VMA_NOT_NULL allocator,
VmaAllocation VMA_NOT_NULL allocation,
VmaAllocationInfo* VMA_NOT_NULL pAllocationInfo);
-/** \brief Returns `VK_TRUE` if allocation is not lost and atomically marks it as used in current frame.
-
-If the allocation has been created with #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
-this function returns `VK_TRUE` if it's not in lost state, so it can still be used.
-It then also atomically "touches" the allocation - marks it as used in current frame,
-so that you can be sure it won't become lost in current frame or next `frameInUseCount` frames.
-
-If the allocation is in lost state, the function returns `VK_FALSE`.
-Memory of such allocation, as well as buffer or image bound to it, should not be used.
-Lost allocation and the buffer/image still need to be destroyed.
-
-If the allocation has been created without #VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag,
-this function always returns `VK_TRUE`.
-*/
-VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
- VmaAllocator VMA_NOT_NULL allocator,
- VmaAllocation VMA_NOT_NULL allocation);
-
/** \brief Sets pUserData in given allocation to new value.
-If the allocation was created with VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT,
-pUserData must be either null, or pointer to a null-terminated string. The function
-makes local copy of the string and sets it as allocation's `pUserData`. String
-passed as pUserData doesn't need to be valid for whole lifetime of the allocation -
-you can free it after this call. String previously pointed by allocation's
-pUserData is freed from memory.
-
-If the flag was not used, the value of pointer `pUserData` is just copied to
-allocation's `pUserData`. It is opaque, so you can use it however you want - e.g.
+The value of pointer `pUserData` is copied to allocation's `pUserData`.
+It is opaque, so you can use it however you want - e.g.
as a pointer, ordinal number or some handle to you own data.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
@@ -3465,27 +1936,40 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
VmaAllocation VMA_NOT_NULL allocation,
void* VMA_NULLABLE pUserData);
-/** \brief Creates new allocation that is in lost state from the beginning.
+/** \brief Sets pName in given allocation to new value.
-It can be useful if you need a dummy, non-null allocation.
+`pName` must be either null, or pointer to a null-terminated string. The function
+makes local copy of the string and sets it as allocation's `pName`. String
+passed as pName doesn't need to be valid for whole lifetime of the allocation -
+you can free it after this call. String previously pointed by allocation's
+`pName` is freed from memory.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const char* VMA_NULLABLE pName);
-You still need to destroy created object using vmaFreeMemory().
+/**
+\brief Given an allocation, returns Property Flags of its memory type.
-Returned allocation is not tied to any specific memory pool or memory type and
-not bound to any image or buffer. It has size = 0. It cannot be turned into
-a real, non-empty allocation.
+This is just a convenience function. Same information can be obtained using
+vmaGetAllocationInfo() + vmaGetMemoryProperties().
*/
-VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
VmaAllocator VMA_NOT_NULL allocator,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation);
+ VmaAllocation VMA_NOT_NULL allocation,
+ VkMemoryPropertyFlags* VMA_NOT_NULL pFlags);
/** \brief Maps memory represented by given allocation and returns pointer to it.
Maps memory represented by given allocation to make it accessible to CPU code.
When succeeded, `*ppData` contains pointer to first byte of this memory.
-If the allocation is part of bigger `VkDeviceMemory` block, the pointer is
-correctly offsetted to the beginning of region assigned to this particular
-allocation.
+
+\warning
+If the allocation is part of a bigger `VkDeviceMemory` block, returned pointer is
+correctly offsetted to the beginning of region assigned to this particular allocation.
+Unlike the result of `vkMapMemory`, it points to the allocation, not to the beginning of the whole block.
+You should not add VmaAllocationInfo::offset to it!
Mapping is internally reference-counted and synchronized, so despite raw Vulkan
function `vkMapMemory()` cannot be used to map same block of `VkDeviceMemory`
@@ -3509,10 +1993,6 @@ vmaMapMemory(). You must not call vmaUnmapMemory() additional time to free the
This function fails when used on allocation made in memory type that is not
`HOST_VISIBLE`.
-This function always fails when called for allocation that was created with
-#VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT flag. Such allocations cannot be
-mapped.
-
This function doesn't automatically flush or invalidate caches.
If the allocation is made from a memory types that is not `HOST_COHERENT`,
you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as required by Vulkan specification.
@@ -3520,7 +2000,7 @@ you also need to use vmaInvalidateAllocation() / vmaFlushAllocation(), as requir
VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
VmaAllocator VMA_NOT_NULL allocator,
VmaAllocation VMA_NOT_NULL allocation,
- void* VMA_NULLABLE * VMA_NOT_NULL ppData);
+ void* VMA_NULLABLE* VMA_NOT_NULL ppData);
/** \brief Unmaps memory represented by given allocation, mapped previously using vmaMapMemory().
@@ -3605,7 +2085,7 @@ called, otherwise `VK_SUCCESS`.
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations(
VmaAllocator VMA_NOT_NULL allocator,
uint32_t allocationCount,
- const VmaAllocation VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,
+ const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets,
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes);
@@ -3626,13 +2106,14 @@ called, otherwise `VK_SUCCESS`.
VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations(
VmaAllocator VMA_NOT_NULL allocator,
uint32_t allocationCount,
- const VmaAllocation VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,
+ const VmaAllocation VMA_NOT_NULL* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) allocations,
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) offsets,
const VkDeviceSize* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) sizes);
/** \brief Checks magic number in margins around all allocations in given memory types (in both default and custom pools) in search for corruptions.
-@param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.
+\param allocator
+\param memoryTypeBits Bit mask, where each bit set means that a memory type with that index should be checked.
Corruption detection is enabled only when `VMA_DEBUG_DETECT_CORRUPTION` macro is defined to nonzero,
`VMA_DEBUG_MARGIN` is defined to nonzero and only for memory types that are
@@ -3642,248 +2123,81 @@ Possible return values:
- `VK_ERROR_FEATURE_NOT_PRESENT` - corruption detection is not enabled for any of specified memory types.
- `VK_SUCCESS` - corruption detection has been performed and succeeded.
-- `VK_ERROR_VALIDATION_FAILED_EXT` - corruption detection has been performed and found memory corruptions around one of the allocations.
+- `VK_ERROR_UNKNOWN` - corruption detection has been performed and found memory corruptions around one of the allocations.
`VMA_ASSERT` is also fired in that case.
- Other value: Error returned by Vulkan, e.g. memory mapping failure.
*/
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator VMA_NOT_NULL allocator, uint32_t memoryTypeBits);
-
-/** \struct VmaDefragmentationContext
-\brief Represents Opaque object that represents started defragmentation process.
-
-Fill structure #VmaDefragmentationInfo2 and call function vmaDefragmentationBegin() to create it.
-Call function vmaDefragmentationEnd() to destroy it.
-*/
-VK_DEFINE_HANDLE(VmaDefragmentationContext)
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(
+ VmaAllocator VMA_NOT_NULL allocator,
+ uint32_t memoryTypeBits);
-/// Flags to be used in vmaDefragmentationBegin(). None at the moment. Reserved for future use.
-typedef enum VmaDefragmentationFlagBits {
- VMA_DEFRAGMENTATION_FLAG_INCREMENTAL = 0x1,
- VMA_DEFRAGMENTATION_FLAG_BITS_MAX_ENUM = 0x7FFFFFFF
-} VmaDefragmentationFlagBits;
-typedef VkFlags VmaDefragmentationFlags;
+/** \brief Begins defragmentation process.
-/** \brief Parameters for defragmentation.
+\param allocator Allocator object.
+\param pInfo Structure filled with parameters of defragmentation.
+\param[out] pContext Context object that must be passed to vmaEndDefragmentation() to finish defragmentation.
+\returns
+- `VK_SUCCESS` if defragmentation can begin.
+- `VK_ERROR_FEATURE_NOT_PRESENT` if defragmentation is not supported.
-To be used with function vmaDefragmentationBegin().
+For more information about defragmentation, see documentation chapter:
+[Defragmentation](@ref defragmentation).
*/
-typedef struct VmaDefragmentationInfo2 {
- /** \brief Reserved for future use. Should be 0.
- */
- VmaDefragmentationFlags flags;
- /** \brief Number of allocations in `pAllocations` array.
- */
- uint32_t allocationCount;
- /** \brief Pointer to array of allocations that can be defragmented.
-
- The array should have `allocationCount` elements.
- The array should not contain nulls.
- Elements in the array should be unique - same allocation cannot occur twice.
- It is safe to pass allocations that are in the lost state - they are ignored.
- All allocations not present in this array are considered non-moveable during this defragmentation.
- */
- const VmaAllocation VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations;
- /** \brief Optional, output. Pointer to array that will be filled with information whether the allocation at certain index has been changed during defragmentation.
-
- The array should have `allocationCount` elements.
- You can pass null if you are not interested in this information.
- */
- VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged;
- /** \brief Numer of pools in `pPools` array.
- */
- uint32_t poolCount;
- /** \brief Either null or pointer to array of pools to be defragmented.
-
- All the allocations in the specified pools can be moved during defragmentation
- and there is no way to check if they were really moved as in `pAllocationsChanged`,
- so you must query all the allocations in all these pools for new `VkDeviceMemory`
- and offset using vmaGetAllocationInfo() if you might need to recreate buffers
- and images bound to them.
-
- The array should have `poolCount` elements.
- The array should not contain nulls.
- Elements in the array should be unique - same pool cannot occur twice.
-
- Using this array is equivalent to specifying all allocations from the pools in `pAllocations`.
- It might be more efficient.
- */
- const VmaPool VMA_NOT_NULL * VMA_NULLABLE VMA_LEN_IF_NOT_NULL(poolCount) pPools;
- /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on CPU side, like `memcpy()`, `memmove()`.
-
- `VK_WHOLE_SIZE` means no limit.
- */
- VkDeviceSize maxCpuBytesToMove;
- /** \brief Maximum number of allocations that can be moved to a different place using transfers on CPU side, like `memcpy()`, `memmove()`.
-
- `UINT32_MAX` means no limit.
- */
- uint32_t maxCpuAllocationsToMove;
- /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places using transfers on GPU side, posted to `commandBuffer`.
-
- `VK_WHOLE_SIZE` means no limit.
- */
- VkDeviceSize maxGpuBytesToMove;
- /** \brief Maximum number of allocations that can be moved to a different place using transfers on GPU side, posted to `commandBuffer`.
-
- `UINT32_MAX` means no limit.
- */
- uint32_t maxGpuAllocationsToMove;
- /** \brief Optional. Command buffer where GPU copy commands will be posted.
-
- If not null, it must be a valid command buffer handle that supports Transfer queue type.
- It must be in the recording state and outside of a render pass instance.
- You need to submit it and make sure it finished execution before calling vmaDefragmentationEnd().
-
- Passing null means that only CPU defragmentation will be performed.
- */
- VkCommandBuffer VMA_NULLABLE commandBuffer;
-} VmaDefragmentationInfo2;
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation(
+ VmaAllocator VMA_NOT_NULL allocator,
+ const VmaDefragmentationInfo* VMA_NOT_NULL pInfo,
+ VmaDefragmentationContext VMA_NULLABLE* VMA_NOT_NULL pContext);
-typedef struct VmaDefragmentationPassMoveInfo {
- VmaAllocation VMA_NOT_NULL allocation;
- VkDeviceMemory VMA_NOT_NULL_NON_DISPATCHABLE memory;
- VkDeviceSize offset;
-} VmaDefragmentationPassMoveInfo;
+/** \brief Ends defragmentation process.
-/** \brief Parameters for incremental defragmentation steps.
+\param allocator Allocator object.
+\param context Context object that has been created by vmaBeginDefragmentation().
+\param[out] pStats Optional stats for the defragmentation. Can be null.
-To be used with function vmaBeginDefragmentationPass().
+Use this function to finish defragmentation started by vmaBeginDefragmentation().
*/
-typedef struct VmaDefragmentationPassInfo {
- uint32_t moveCount;
- VmaDefragmentationPassMoveInfo* VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(moveCount) pMoves;
-} VmaDefragmentationPassInfo;
-
-/** \brief Deprecated. Optional configuration parameters to be passed to function vmaDefragment().
-
-\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
+VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaDefragmentationContext VMA_NOT_NULL context,
+ VmaDefragmentationStats* VMA_NULLABLE pStats);
+
+/** \brief Starts single defragmentation pass.
+
+\param allocator Allocator object.
+\param context Context object that has been created by vmaBeginDefragmentation().
+\param[out] pPassInfo Computed informations for current pass.
+\returns
+- `VK_SUCCESS` if no more moves are possible. Then you can omit call to vmaEndDefragmentationPass() and simply end whole defragmentation.
+- `VK_INCOMPLETE` if there are pending moves returned in `pPassInfo`. You need to perform them, call vmaEndDefragmentationPass(),
+ and then preferably try another pass with vmaBeginDefragmentationPass().
*/
-typedef struct VmaDefragmentationInfo {
- /** \brief Maximum total numbers of bytes that can be copied while moving allocations to different places.
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaDefragmentationContext VMA_NOT_NULL context,
+ VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo);
- Default is `VK_WHOLE_SIZE`, which means no limit.
- */
- VkDeviceSize maxBytesToMove;
- /** \brief Maximum number of allocations that can be moved to different place.
+/** \brief Ends single defragmentation pass.
- Default is `UINT32_MAX`, which means no limit.
- */
- uint32_t maxAllocationsToMove;
-} VmaDefragmentationInfo;
+\param allocator Allocator object.
+\param context Context object that has been created by vmaBeginDefragmentation().
+\param pPassInfo Computed informations for current pass filled by vmaBeginDefragmentationPass() and possibly modified by you.
-/** \brief Statistics returned by function vmaDefragment(). */
-typedef struct VmaDefragmentationStats {
- /// Total number of bytes that have been copied while moving allocations to different places.
- VkDeviceSize bytesMoved;
- /// Total number of bytes that have been released to the system by freeing empty `VkDeviceMemory` objects.
- VkDeviceSize bytesFreed;
- /// Number of allocations that have been moved to different places.
- uint32_t allocationsMoved;
- /// Number of empty `VkDeviceMemory` objects that have been released to the system.
- uint32_t deviceMemoryBlocksFreed;
-} VmaDefragmentationStats;
+Returns `VK_SUCCESS` if no more moves are possible or `VK_INCOMPLETE` if more defragmentations are possible.
-/** \brief Begins defragmentation process.
+Ends incremental defragmentation pass and commits all defragmentation moves from `pPassInfo`.
+After this call:
-@param allocator Allocator object.
-@param pInfo Structure filled with parameters of defragmentation.
-@param[out] pStats Optional. Statistics of defragmentation. You can pass null if you are not interested in this information.
-@param[out] pContext Context object that must be passed to vmaDefragmentationEnd() to finish defragmentation.
-@return `VK_SUCCESS` and `*pContext == null` if defragmentation finished within this function call. `VK_NOT_READY` and `*pContext != null` if defragmentation has been started and you need to call vmaDefragmentationEnd() to finish it. Negative value in case of error.
-
-Use this function instead of old, deprecated vmaDefragment().
-
-Warning! Between the call to vmaDefragmentationBegin() and vmaDefragmentationEnd():
-
-- You should not use any of allocations passed as `pInfo->pAllocations` or
- any allocations that belong to pools passed as `pInfo->pPools`,
- including calling vmaGetAllocationInfo(), vmaTouchAllocation(), or access
- their data.
-- Some mutexes protecting internal data structures may be locked, so trying to
- make or free any allocations, bind buffers or images, map memory, or launch
- another simultaneous defragmentation in between may cause stall (when done on
- another thread) or deadlock (when done on the same thread), unless you are
- 100% sure that defragmented allocations are in different pools.
-- Information returned via `pStats` and `pInfo->pAllocationsChanged` are undefined.
- They become valid after call to vmaDefragmentationEnd().
-- If `pInfo->commandBuffer` is not null, you must submit that command buffer
- and make sure it finished execution before calling vmaDefragmentationEnd().
-
-For more information and important limitations regarding defragmentation, see documentation chapter:
-[Defragmentation](@ref defragmentation).
-*/
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
- VmaAllocator VMA_NOT_NULL allocator,
- const VmaDefragmentationInfo2* VMA_NOT_NULL pInfo,
- VmaDefragmentationStats* VMA_NULLABLE pStats,
- VmaDefragmentationContext VMA_NULLABLE * VMA_NOT_NULL pContext);
+- Allocations at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY
+ (which is the default) will be pointing to the new destination place.
+- Allocation at `pPassInfo[i].srcAllocation` that had `pPassInfo[i].operation ==` #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY
+ will be freed.
-/** \brief Ends defragmentation process.
-
-Use this function to finish defragmentation started by vmaDefragmentationBegin().
-It is safe to pass `context == null`. The function then does nothing.
+If no more moves are possible you can end whole defragmentation.
*/
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
- VmaAllocator VMA_NOT_NULL allocator,
- VmaDefragmentationContext VMA_NULLABLE context);
-
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(
- VmaAllocator VMA_NOT_NULL allocator,
- VmaDefragmentationContext VMA_NULLABLE context,
- VmaDefragmentationPassInfo* VMA_NOT_NULL pInfo
-);
VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(
VmaAllocator VMA_NOT_NULL allocator,
- VmaDefragmentationContext VMA_NULLABLE context
-);
-
-/** \brief Deprecated. Compacts memory by moving allocations.
-
-@param pAllocations Array of allocations that can be moved during this compation.
-@param allocationCount Number of elements in pAllocations and pAllocationsChanged arrays.
-@param[out] pAllocationsChanged Array of boolean values that will indicate whether matching allocation in pAllocations array has been moved. This parameter is optional. Pass null if you don't need this information.
-@param pDefragmentationInfo Configuration parameters. Optional - pass null to use default values.
-@param[out] pDefragmentationStats Statistics returned by the function. Optional - pass null if you don't need this information.
-@return `VK_SUCCESS` if completed, negative error code in case of error.
-
-\deprecated This is a part of the old interface. It is recommended to use structure #VmaDefragmentationInfo2 and function vmaDefragmentationBegin() instead.
-
-This function works by moving allocations to different places (different
-`VkDeviceMemory` objects and/or different offsets) in order to optimize memory
-usage. Only allocations that are in `pAllocations` array can be moved. All other
-allocations are considered nonmovable in this call. Basic rules:
-
-- Only allocations made in memory types that have
- `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` and `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT`
- flags can be compacted. You may pass other allocations but it makes no sense -
- these will never be moved.
-- Custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT or
- #VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT flag are not defragmented. Allocations
- passed to this function that come from such pools are ignored.
-- Allocations created with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT or
- created as dedicated allocations for any other reason are also ignored.
-- Both allocations made with or without #VMA_ALLOCATION_CREATE_MAPPED_BIT
- flag can be compacted. If not persistently mapped, memory will be mapped
- temporarily inside this function if needed.
-- You must not pass same #VmaAllocation object multiple times in `pAllocations` array.
-
-The function also frees empty `VkDeviceMemory` blocks.
-
-Warning: This function may be time-consuming, so you shouldn't call it too often
-(like after every resource creation/destruction).
-You can call it on special occasions (like when reloading a game level or
-when you just destroyed a lot of objects). Calling it every frame may be OK, but
-you should measure that on your platform.
-
-For more information, see [Defragmentation](@ref defragmentation) chapter.
-*/
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
- VmaAllocator VMA_NOT_NULL allocator,
- const VmaAllocation VMA_NOT_NULL * VMA_NOT_NULL VMA_LEN_IF_NOT_NULL(allocationCount) pAllocations,
- size_t allocationCount,
- VkBool32* VMA_NULLABLE VMA_LEN_IF_NOT_NULL(allocationCount) pAllocationsChanged,
- const VmaDefragmentationInfo* VMA_NULLABLE pDefragmentationInfo,
- VmaDefragmentationStats* VMA_NULLABLE pDefragmentationStats);
+ VmaDefragmentationContext VMA_NOT_NULL context,
+ VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo);
/** \brief Binds buffer to allocation.
@@ -3904,8 +2218,11 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
/** \brief Binds buffer to allocation with additional parameters.
-@param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
-@param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null.
+\param allocator
+\param allocation
+\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
+\param buffer
+\param pNext A chain of structures to be attached to `VkBindBufferMemoryInfoKHR` structure used internally. Normally it should be null.
This function is similar to vmaBindBufferMemory(), but it provides additional parameters.
@@ -3938,8 +2255,11 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory(
/** \brief Binds image to allocation with additional parameters.
-@param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
-@param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
+\param allocator
+\param allocation
+\param allocationLocalOffset Additional offset to be added while binding, relative to the beginning of the `allocation`. Normally it should be 0.
+\param image
+\param pNext A chain of structures to be attached to `VkBindImageMemoryInfoKHR` structure used internally. Normally it should be null.
This function is similar to vmaBindImageMemory(), but it provides additional parameters.
@@ -3953,10 +2273,14 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindImageMemory2(
VkImage VMA_NOT_NULL_NON_DISPATCHABLE image,
const void* VMA_NULLABLE pNext);
-/**
-@param[out] pBuffer Buffer that was created.
-@param[out] pAllocation Allocation that was created.
-@param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
+/** \brief Creates a new `VkBuffer`, allocates and binds memory for it.
+
+\param allocator
+\param pBufferCreateInfo
+\param pAllocationCreateInfo
+\param[out] pBuffer Buffer that was created.
+\param[out] pAllocation Allocation that was created.
+\param[out] pAllocationInfo Optional. Information about allocated memory. It can be later fetched using function vmaGetAllocationInfo().
This function automatically:
@@ -3965,7 +2289,7 @@ This function automatically:
-# Binds the buffer with the memory.
If any of these operations fail, buffer and allocation are not created,
-returned value is negative error code, *pBuffer and *pAllocation are null.
+returned value is negative error code, `*pBuffer` and `*pAllocation` are null.
If the function succeeded, you must destroy both buffer and allocation when you
no longer need them using either convenience function vmaDestroyBuffer() or
@@ -3974,8 +2298,8 @@ separately, using `vkDestroyBuffer()` and vmaFreeMemory().
If #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag was used,
VK_KHR_dedicated_allocation extension is used internally to query driver whether
it requires or prefers the new buffer to have dedicated allocation. If yes,
-and if dedicated allocation is possible (VmaAllocationCreateInfo::pool is null
-and #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated
+and if dedicated allocation is possible
+(#VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT is not used), it creates dedicated
allocation for this buffer, just like when using
#VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
@@ -3987,10 +2311,50 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
VmaAllocator VMA_NOT_NULL allocator,
const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,
const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,
- VkBuffer VMA_NULLABLE_NON_DISPATCHABLE * VMA_NOT_NULL pBuffer,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation,
+ VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
+/** \brief Creates a buffer with additional minimum alignment.
+
+Similar to vmaCreateBuffer() but provides additional parameter `minAlignment` which allows to specify custom,
+minimum alignment to be used when placing the buffer inside a larger memory block, which may be needed e.g.
+for interop with OpenGL.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment(
+ VmaAllocator VMA_NOT_NULL allocator,
+ const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,
+ const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,
+ VkDeviceSize minAlignment,
+ VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
+ VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
+
+/** \brief Creates a new `VkBuffer`, binds already created memory for it.
+
+\param allocator
+\param allocation Allocation that provides memory to be used for binding new buffer to it.
+\param pBufferCreateInfo
+\param[out] pBuffer Buffer that was created.
+
+This function automatically:
+
+-# Creates buffer.
+-# Binds the buffer with the supplied memory.
+
+If any of these operations fail, buffer is not created,
+returned value is negative error code and `*pBuffer` is null.
+
+If the function succeeded, you must destroy the buffer when you
+no longer need it using `vkDestroyBuffer()`. If you want to also destroy the corresponding
+allocation you can use convenience function vmaDestroyBuffer().
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,
+ VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer);
+
/** \brief Destroys Vulkan buffer and frees allocated memory.
This is just a convenience function equivalent to:
@@ -4000,7 +2364,7 @@ vkDestroyBuffer(device, buffer, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
-It it safe to pass null as buffer and/or allocation.
+It is safe to pass null as buffer and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
VmaAllocator VMA_NOT_NULL allocator,
@@ -4012,10 +2376,17 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
VmaAllocator VMA_NOT_NULL allocator,
const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,
const VmaAllocationCreateInfo* VMA_NOT_NULL pAllocationCreateInfo,
- VkImage VMA_NULLABLE_NON_DISPATCHABLE * VMA_NOT_NULL pImage,
- VmaAllocation VMA_NULLABLE * VMA_NOT_NULL pAllocation,
+ VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage,
+ VmaAllocation VMA_NULLABLE* VMA_NOT_NULL pAllocation,
VmaAllocationInfo* VMA_NULLABLE pAllocationInfo);
+/// Function similar to vmaCreateAliasingBuffer().
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,
+ VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage);
+
/** \brief Destroys Vulkan image and frees allocated memory.
This is just a convenience function equivalent to:
@@ -4025,19 +2396,171 @@ vkDestroyImage(device, image, allocationCallbacks);
vmaFreeMemory(allocator, allocation);
\endcode
-It it safe to pass null as image and/or allocation.
+It is safe to pass null as image and/or allocation.
*/
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
VmaAllocator VMA_NOT_NULL allocator,
VkImage VMA_NULLABLE_NON_DISPATCHABLE image,
VmaAllocation VMA_NULLABLE allocation);
+/** @} */
+
+/**
+\addtogroup group_virtual
+@{
+*/
+
+/** \brief Creates new #VmaVirtualBlock object.
+
+\param pCreateInfo Parameters for creation.
+\param[out] pVirtualBlock Returned virtual block object or `VMA_NULL` if creation failed.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock(
+ const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo,
+ VmaVirtualBlock VMA_NULLABLE* VMA_NOT_NULL pVirtualBlock);
+
+/** \brief Destroys #VmaVirtualBlock object.
+
+Please note that you should consciously handle virtual allocations that could remain unfreed in the block.
+You should either free them individually using vmaVirtualFree() or call vmaClearVirtualBlock()
+if you are sure this is what you want. If you do neither, an assert is called.
+
+If you keep pointers to some additional metadata associated with your virtual allocations in their `pUserData`,
+don't forget to free them.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(
+ VmaVirtualBlock VMA_NULLABLE virtualBlock);
+
+/** \brief Returns true of the #VmaVirtualBlock is empty - contains 0 virtual allocations and has all its space available for new allocations.
+*/
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock);
+
+/** \brief Returns information about a specific virtual allocation within a virtual block, like its size and `pUserData` pointer.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo);
+
+/** \brief Allocates new virtual allocation inside given #VmaVirtualBlock.
+
+If the allocation fails due to not enough free space available, `VK_ERROR_OUT_OF_DEVICE_MEMORY` is returned
+(despite the function doesn't ever allocate actual GPU memory).
+`pAllocation` is then set to `VK_NULL_HANDLE` and `pOffset`, if not null, it set to `UINT64_MAX`.
+
+\param virtualBlock Virtual block
+\param pCreateInfo Parameters for the allocation
+\param[out] pAllocation Returned handle of the new allocation
+\param[out] pOffset Returned offset of the new allocation. Optional, can be null.
+*/
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo,
+ VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation,
+ VkDeviceSize* VMA_NULLABLE pOffset);
+
+/** \brief Frees virtual allocation inside given #VmaVirtualBlock.
+
+It is correct to call this function with `allocation == VK_NULL_HANDLE` - it does nothing.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation);
+
+/** \brief Frees all virtual allocations inside given #VmaVirtualBlock.
+
+You must either call this function or free each virtual allocation individually with vmaVirtualFree()
+before destroying a virtual block. Otherwise, an assert is called.
+
+If you keep pointer to some additional metadata associated with your virtual allocation in its `pUserData`,
+don't forget to free it as well.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock);
+
+/** \brief Changes custom pointer associated with given virtual allocation.
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation,
+ void* VMA_NULLABLE pUserData);
+
+/** \brief Calculates and returns statistics about virtual allocations and memory usage in given #VmaVirtualBlock.
+
+This function is fast to call. For more detailed statistics, see vmaCalculateVirtualBlockStatistics().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaStatistics* VMA_NOT_NULL pStats);
+
+/** \brief Calculates and returns detailed statistics about virtual allocations and memory usage in given #VmaVirtualBlock.
+
+This function is slow to call. Use for debugging purposes.
+For less detailed statistics, see vmaGetVirtualBlockStatistics().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaDetailedStatistics* VMA_NOT_NULL pStats);
+
+/** @} */
+
+#if VMA_STATS_STRING_ENABLED
+/**
+\addtogroup group_stats
+@{
+*/
+
+/** \brief Builds and returns a null-terminated string in JSON format with information about given #VmaVirtualBlock.
+\param virtualBlock Virtual block.
+\param[out] ppStatsString Returned string.
+\param detailedMap Pass `VK_FALSE` to only obtain statistics as returned by vmaCalculateVirtualBlockStatistics(). Pass `VK_TRUE` to also obtain full list of allocations and free spaces.
+
+Returned string must be freed using vmaFreeVirtualBlockStatsString().
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString,
+ VkBool32 detailedMap);
+
+/// Frees a string returned by vmaBuildVirtualBlockStatsString().
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(
+ VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ char* VMA_NULLABLE pStatsString);
+
+/** \brief Builds and returns statistics as a null-terminated string in JSON format.
+\param allocator
+\param[out] ppStatsString Must be freed using vmaFreeStatsString() function.
+\param detailedMap
+*/
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
+ VmaAllocator VMA_NOT_NULL allocator,
+ char* VMA_NULLABLE* VMA_NOT_NULL ppStatsString,
+ VkBool32 detailedMap);
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
+ VmaAllocator VMA_NOT_NULL allocator,
+ char* VMA_NULLABLE pStatsString);
+
+/** @} */
+
+#endif // VMA_STATS_STRING_ENABLED
+
+#endif // _VMA_FUNCTION_HEADERS
+
#ifdef __cplusplus
}
#endif
#endif // AMD_VULKAN_MEMORY_ALLOCATOR_H
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// IMPLEMENTATION
+//
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
// For Visual Studio IntelliSense.
#if defined(__cplusplus) && defined(__INTELLISENSE__)
#define VMA_IMPLEMENTATION
@@ -4050,15 +2573,13 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
#include <cstdlib>
#include <cstring>
#include <utility>
+#include <type_traits>
-#if VMA_RECORDING_ENABLED
- #include <chrono>
- #if defined(_WIN32)
- #include <windows.h>
- #else
- #include <sstream>
- #include <thread>
- #endif
+#ifdef _MSC_VER
+ #include <intrin.h> // For functions like __popcnt, _BitScanForward etc.
+#endif
+#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
+ #include <bit> // For std::popcount
#endif
/*******************************************************************************
@@ -4067,6 +2588,7 @@ CONFIGURATION SECTION
Define some of these macros before each #include of this header or change them
here if you need other then default behavior depending on your environment.
*/
+#ifndef _VMA_CONFIGURATION
/*
Define this macro to 1 to make the library fetch pointers to Vulkan functions
@@ -4082,29 +2604,14 @@ internally, like:
Define this macro to 1 to make the library fetch pointers to Vulkan functions
internally, like:
- vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(m_hDevice, vkAllocateMemory);
+ vulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkGetDeviceProcAddr(device, "vkAllocateMemory");
+
+To use this feature in new versions of VMA you now have to pass
+VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as
+VmaAllocatorCreateInfo::pVulkanFunctions. Other members can be null.
*/
#if !defined(VMA_DYNAMIC_VULKAN_FUNCTIONS)
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
- #if defined(VK_NO_PROTOTYPES)
- extern PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
- extern PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
- #endif
-#endif
-
-// Define this macro to 1 to make the library use STL containers instead of its own implementation.
-//#define VMA_USE_STL_CONTAINERS 1
-
-/* Set this macro to 1 to make the library including and using STL containers:
-std::pair, std::vector, std::list, std::unordered_map.
-
-Set it to 0 or undefined to make the library using its own implementation of
-the containers.
-*/
-#if VMA_USE_STL_CONTAINERS
- #define VMA_USE_STL_VECTOR 1
- #define VMA_USE_STL_UNORDERED_MAP 1
- #define VMA_USE_STL_LIST 1
#endif
#ifndef VMA_USE_STL_SHARED_MUTEX
@@ -4112,8 +2619,7 @@ the containers.
#if __cplusplus >= 201703L
#define VMA_USE_STL_SHARED_MUTEX 1
// Visual studio defines __cplusplus properly only when passed additional parameter: /Zc:__cplusplus
- // Otherwise it's always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.
- // See: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
+ // Otherwise it is always 199711L, despite shared_mutex works since Visual Studio 2015 Update 2.
#elif defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023918 && __cplusplus == 199711L && _MSVC_LANG >= 201703L
#define VMA_USE_STL_SHARED_MUTEX 1
#else
@@ -4122,28 +2628,33 @@ the containers.
#endif
/*
-THESE INCLUDES ARE NOT ENABLED BY DEFAULT.
-Library has its own container implementation.
-*/
-#if VMA_USE_STL_VECTOR
- #include <vector>
-#endif
+Define this macro to include custom header files without having to edit this file directly, e.g.:
-#if VMA_USE_STL_UNORDERED_MAP
- #include <unordered_map>
-#endif
+ // Inside of "my_vma_configuration_user_includes.h":
-#if VMA_USE_STL_LIST
- #include <list>
-#endif
+ #include "my_custom_assert.h" // for MY_CUSTOM_ASSERT
+ #include "my_custom_min.h" // for my_custom_min
+ #include <algorithm>
+ #include <mutex>
-/*
-Following headers are used in this CONFIGURATION section only, so feel free to
+ // Inside a different file, which includes "vk_mem_alloc.h":
+
+ #define VMA_CONFIGURATION_USER_INCLUDES_H "my_vma_configuration_user_includes.h"
+ #define VMA_ASSERT(expr) MY_CUSTOM_ASSERT(expr)
+ #define VMA_MIN(v1, v2) (my_custom_min(v1, v2))
+ #include "vk_mem_alloc.h"
+ ...
+
+The following headers are used in this CONFIGURATION section only, so feel free to
remove them if not needed.
*/
-#include <cassert> // for assert
-#include <algorithm> // for min, max
-#include <mutex>
+#if !defined(VMA_CONFIGURATION_USER_INCLUDES_H)
+ #include <cassert> // for assert
+ #include <algorithm> // for min, max
+ #include <mutex>
+#else
+ #include VMA_CONFIGURATION_USER_INCLUDES_H
+#endif
#ifndef VMA_NULL
// Value used as null pointer. Define it to e.g.: nullptr, NULL, 0, (void*)0.
@@ -4171,18 +2682,21 @@ static void* vma_aligned_alloc(size_t alignment, size_t size)
static void* vma_aligned_alloc(size_t alignment, size_t size)
{
-#if defined(__APPLE__) && (defined(MAC_OS_X_VERSION_10_16) || defined(__IPHONE_14_0))
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_16 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
- // For C++14, usr/include/malloc/_malloc.h declares aligned_alloc()) only
- // with the MacOSX11.0 SDK in Xcode 12 (which is what adds
- // MAC_OS_X_VERSION_10_16), even though the function is marked
- // availabe for 10.15. That's why the preprocessor checks for 10.16 but
- // the __builtin_available checks for 10.15.
- // People who use C++17 could call aligned_alloc with the 10.15 SDK already.
- if (__builtin_available(macOS 10.15, iOS 13, *))
- return aligned_alloc(alignment, size);
-#endif
-#endif
+ // Unfortunately, aligned_alloc causes VMA to crash due to it returning null pointers. (At least under 11.4)
+ // Therefore, for now disable this specific exception until a proper solution is found.
+ //#if defined(__APPLE__) && (defined(MAC_OS_X_VERSION_10_16) || defined(__IPHONE_14_0))
+ //#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_16 || __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
+ // // For C++14, usr/include/malloc/_malloc.h declares aligned_alloc()) only
+ // // with the MacOSX11.0 SDK in Xcode 12 (which is what adds
+ // // MAC_OS_X_VERSION_10_16), even though the function is marked
+ // // availabe for 10.15. That is why the preprocessor checks for 10.16 but
+ // // the __builtin_available checks for 10.15.
+ // // People who use C++17 could call aligned_alloc with the 10.15 SDK already.
+ // if (__builtin_available(macOS 10.15, iOS 13, *))
+ // return aligned_alloc(alignment, size);
+ //#endif
+ //#endif
+
// alignment must be >= sizeof(void*)
if(alignment < sizeof(void*))
{
@@ -4259,12 +2773,27 @@ static void vma_aligned_free(void* VMA_NULLABLE ptr)
#endif
#endif
+#ifndef VMA_COUNT_BITS_SET
+ // Returns number of bits set to 1 in (v)
+ #define VMA_COUNT_BITS_SET(v) VmaCountBitsSet(v)
+#endif
+
+#ifndef VMA_BITSCAN_LSB
+ // Scans integer for index of first nonzero value from the Least Significant Bit (LSB). If mask is 0 then returns UINT8_MAX
+ #define VMA_BITSCAN_LSB(mask) VmaBitScanLSB(mask)
+#endif
+
+#ifndef VMA_BITSCAN_MSB
+ // Scans integer for index of first nonzero value from the Most Significant Bit (MSB). If mask is 0 then returns UINT8_MAX
+ #define VMA_BITSCAN_MSB(mask) VmaBitScanMSB(mask)
+#endif
+
#ifndef VMA_MIN
- #define VMA_MIN(v1, v2) (std::min((v1), (v2)))
+ #define VMA_MIN(v1, v2) ((std::min)((v1), (v2)))
#endif
#ifndef VMA_MAX
- #define VMA_MAX(v1, v2) (std::max((v1), (v2)))
+ #define VMA_MAX(v1, v2) ((std::max)((v1), (v2)))
#endif
#ifndef VMA_SWAP
@@ -4402,7 +2931,7 @@ If providing your own implementation, you need to implement a subset of std::ato
#ifndef VMA_DEBUG_MARGIN
/**
- Minimum margin before and after every allocation, in bytes.
+ Minimum margin after every allocation, in bytes.
Set nonzero for debugging purposes only.
*/
#define VMA_DEBUG_MARGIN (0)
@@ -4419,7 +2948,7 @@ If providing your own implementation, you need to implement a subset of std::ato
#ifndef VMA_DEBUG_DETECT_CORRUPTION
/**
Define this macro to 1 together with non-zero value of VMA_DEBUG_MARGIN to
- enable writing magic value to the margin before and after every allocation and
+ enable writing magic value to the margin after every allocation and
validating it, so that memory corruptions (out-of-bounds writes) are detected.
*/
#define VMA_DEBUG_DETECT_CORRUPTION (0)
@@ -4459,6 +2988,17 @@ If providing your own implementation, you need to implement a subset of std::ato
#define VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE (256ull * 1024 * 1024)
#endif
+/*
+Mapping hysteresis is a logic that launches when vmaMapMemory/vmaUnmapMemory is called
+or a persistently mapped allocation is created and destroyed several times in a row.
+It keeps additional +1 mapping of a device memory block to prevent calling actual
+vkMapMemory/vkUnmapMemory too many times, which may improve performance and help
+tools like RenderDOc.
+*/
+#ifndef VMA_MAPPING_HYSTERESIS_ENABLED
+ #define VMA_MAPPING_HYSTERESIS_ENABLED 1
+#endif
+
#ifndef VMA_CLASS_NO_COPY
#define VMA_CLASS_NO_COPY(className) \
private: \
@@ -4466,38 +3006,281 @@ If providing your own implementation, you need to implement a subset of std::ato
className& operator=(const className&) = delete;
#endif
-static const uint32_t VMA_FRAME_INDEX_LOST = UINT32_MAX;
-
-// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.
-static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;
-
-static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC;
-static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;
+#define VMA_VALIDATE(cond) do { if(!(cond)) { \
+ VMA_ASSERT(0 && "Validation failed: " #cond); \
+ return false; \
+ } } while(false)
/*******************************************************************************
END OF CONFIGURATION
*/
+#endif // _VMA_CONFIGURATION
-// # Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants.
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_CREATED = 0xDC;
+static const uint8_t VMA_ALLOCATION_FILL_PATTERN_DESTROYED = 0xEF;
+// Decimal 2139416166, float NaN, little-endian binary 66 E6 84 7F.
+static const uint32_t VMA_CORRUPTION_DETECTION_MAGIC_VALUE = 0x7F84E666;
+
+// Copy of some Vulkan definitions so we don't need to check their existence just to handle few constants.
static const uint32_t VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY = 0x00000040;
static const uint32_t VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY = 0x00000080;
static const uint32_t VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY = 0x00020000;
-
+static const uint32_t VK_IMAGE_CREATE_DISJOINT_BIT_COPY = 0x00000200;
+static const int32_t VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY = 1000158000;
static const uint32_t VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET = 0x10000000u;
+static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
+static const uint32_t VMA_VENDOR_ID_AMD = 4098;
+
+// This one is tricky. Vulkan specification defines this code as available since
+// Vulkan 1.0, but doesn't actually define it in Vulkan SDK earlier than 1.2.131.
+// See pull request #207.
+#define VK_ERROR_UNKNOWN_COPY ((VkResult)-13)
-static VkAllocationCallbacks VmaEmptyAllocationCallbacks = {
- VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };
-// Returns number of bits set to 1 in (v).
+#if VMA_STATS_STRING_ENABLED
+// Correspond to values of enum VmaSuballocationType.
+static const char* VMA_SUBALLOCATION_TYPE_NAMES[] =
+{
+ "FREE",
+ "UNKNOWN",
+ "BUFFER",
+ "IMAGE_UNKNOWN",
+ "IMAGE_LINEAR",
+ "IMAGE_OPTIMAL",
+};
+#endif
+
+static VkAllocationCallbacks VmaEmptyAllocationCallbacks =
+ { VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL, VMA_NULL };
+
+
+#ifndef _VMA_ENUM_DECLARATIONS
+
+enum VmaSuballocationType
+{
+ VMA_SUBALLOCATION_TYPE_FREE = 0,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
+ VMA_SUBALLOCATION_TYPE_BUFFER = 2,
+ VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
+ VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
+ VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
+ VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+};
+
+enum VMA_CACHE_OPERATION
+{
+ VMA_CACHE_FLUSH,
+ VMA_CACHE_INVALIDATE
+};
+
+enum class VmaAllocationRequestType
+{
+ Normal,
+ TLSF,
+ // Used by "Linear" algorithm.
+ UpperAddress,
+ EndOf1st,
+ EndOf2nd,
+};
+
+#endif // _VMA_ENUM_DECLARATIONS
+
+#ifndef _VMA_FORWARD_DECLARATIONS
+// Opaque handle used by allocation algorithms to identify single allocation in any conforming way.
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VmaAllocHandle);
+
+struct VmaMutexLock;
+struct VmaMutexLockRead;
+struct VmaMutexLockWrite;
+
+template<typename T>
+struct AtomicTransactionalIncrement;
+
+template<typename T>
+struct VmaStlAllocator;
+
+template<typename T, typename AllocatorT>
+class VmaVector;
+
+template<typename T, typename AllocatorT, size_t N>
+class VmaSmallVector;
+
+template<typename T>
+class VmaPoolAllocator;
+
+template<typename T>
+struct VmaListItem;
+
+template<typename T>
+class VmaRawList;
+
+template<typename T, typename AllocatorT>
+class VmaList;
+
+template<typename ItemTypeTraits>
+class VmaIntrusiveLinkedList;
+
+// Unused in this version
+#if 0
+template<typename T1, typename T2>
+struct VmaPair;
+template<typename FirstT, typename SecondT>
+struct VmaPairFirstLess;
+
+template<typename KeyT, typename ValueT>
+class VmaMap;
+#endif
+
+#if VMA_STATS_STRING_ENABLED
+class VmaStringBuilder;
+class VmaJsonWriter;
+#endif
+
+class VmaDeviceMemoryBlock;
+
+struct VmaDedicatedAllocationListItemTraits;
+class VmaDedicatedAllocationList;
+
+struct VmaSuballocation;
+struct VmaSuballocationOffsetLess;
+struct VmaSuballocationOffsetGreater;
+struct VmaSuballocationItemSizeLess;
+
+typedef VmaList<VmaSuballocation, VmaStlAllocator<VmaSuballocation>> VmaSuballocationList;
+
+struct VmaAllocationRequest;
+
+class VmaBlockMetadata;
+class VmaBlockMetadata_Linear;
+class VmaBlockMetadata_TLSF;
+
+class VmaBlockVector;
+
+struct VmaPoolListItemTraits;
+
+struct VmaCurrentBudgetData;
+
+class VmaAllocationObjectAllocator;
+
+#endif // _VMA_FORWARD_DECLARATIONS
+
+
+#ifndef _VMA_FUNCTIONS
+
+/*
+Returns number of bits set to 1 in (v).
+
+On specific platforms and compilers you can use instrinsics like:
+
+Visual Studio:
+ return __popcnt(v);
+GCC, Clang:
+ return static_cast<uint32_t>(__builtin_popcount(v));
+
+Define macro VMA_COUNT_BITS_SET to provide your optimized implementation.
+But you need to check in runtime whether user's CPU supports these, as some old processors don't.
+*/
static inline uint32_t VmaCountBitsSet(uint32_t v)
{
+#if __cplusplus >= 202002L || _MSVC_LANG >= 202002L // C++20
+ return std::popcount(v);
+#else
uint32_t c = v - ((v >> 1) & 0x55555555);
- c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
- c = ((c >> 4) + c) & 0x0F0F0F0F;
- c = ((c >> 8) + c) & 0x00FF00FF;
+ c = ((c >> 2) & 0x33333333) + (c & 0x33333333);
+ c = ((c >> 4) + c) & 0x0F0F0F0F;
+ c = ((c >> 8) + c) & 0x00FF00FF;
c = ((c >> 16) + c) & 0x0000FFFF;
return c;
+#endif
+}
+
+static inline uint8_t VmaBitScanLSB(uint64_t mask)
+{
+#if defined(_MSC_VER) && defined(_WIN64)
+ unsigned long pos;
+ if (_BitScanForward64(&pos, mask))
+ return static_cast<uint8_t>(pos);
+ return UINT8_MAX;
+#elif defined __GNUC__ || defined __clang__
+ return static_cast<uint8_t>(__builtin_ffsll(mask)) - 1U;
+#else
+ uint8_t pos = 0;
+ uint64_t bit = 1;
+ do
+ {
+ if (mask & bit)
+ return pos;
+ bit <<= 1;
+ } while (pos++ < 63);
+ return UINT8_MAX;
+#endif
+}
+
+static inline uint8_t VmaBitScanLSB(uint32_t mask)
+{
+#ifdef _MSC_VER
+ unsigned long pos;
+ if (_BitScanForward(&pos, mask))
+ return static_cast<uint8_t>(pos);
+ return UINT8_MAX;
+#elif defined __GNUC__ || defined __clang__
+ return static_cast<uint8_t>(__builtin_ffs(mask)) - 1U;
+#else
+ uint8_t pos = 0;
+ uint32_t bit = 1;
+ do
+ {
+ if (mask & bit)
+ return pos;
+ bit <<= 1;
+ } while (pos++ < 31);
+ return UINT8_MAX;
+#endif
+}
+
+static inline uint8_t VmaBitScanMSB(uint64_t mask)
+{
+#if defined(_MSC_VER) && defined(_WIN64)
+ unsigned long pos;
+ if (_BitScanReverse64(&pos, mask))
+ return static_cast<uint8_t>(pos);
+#elif defined __GNUC__ || defined __clang__
+ if (mask)
+ return 63 - static_cast<uint8_t>(__builtin_clzll(mask));
+#else
+ uint8_t pos = 63;
+ uint64_t bit = 1ULL << 63;
+ do
+ {
+ if (mask & bit)
+ return pos;
+ bit >>= 1;
+ } while (pos-- > 0);
+#endif
+ return UINT8_MAX;
+}
+
+static inline uint8_t VmaBitScanMSB(uint32_t mask)
+{
+#ifdef _MSC_VER
+ unsigned long pos;
+ if (_BitScanReverse(&pos, mask))
+ return static_cast<uint8_t>(pos);
+#elif defined __GNUC__ || defined __clang__
+ if (mask)
+ return 31 - static_cast<uint8_t>(__builtin_clz(mask));
+#else
+ uint8_t pos = 31;
+ uint32_t bit = 1UL << 31;
+ do
+ {
+ if (mask & bit)
+ return pos;
+ bit >>= 1;
+ } while (pos-- > 0);
+#endif
+ return UINT8_MAX;
}
/*
@@ -4508,7 +3291,7 @@ For 0 returns true.
template <typename T>
inline bool VmaIsPow2(T x)
{
- return (x & (x-1)) == 0;
+ return (x & (x - 1)) == 0;
}
// Aligns given value up to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 16.
@@ -4519,6 +3302,7 @@ static inline T VmaAlignUp(T val, T alignment)
VMA_HEAVY_ASSERT(VmaIsPow2(alignment));
return (val + alignment - 1) & ~(alignment - 1);
}
+
// Aligns given value down to nearest multiply of align value. For example: VmaAlignUp(11, 8) = 8.
// Use types like uint32_t, uint64_t as T.
template <typename T>
@@ -4535,6 +3319,13 @@ static inline T VmaRoundDiv(T x, T y)
return (x + (y / (T)2)) / y;
}
+// Divide by 'y' and round up to nearest integer.
+template <typename T>
+static inline T VmaDivideRoundingUp(T x, T y)
+{
+ return (x + y - (T)1) / y;
+}
+
// Returns smallest power of 2 greater or equal to v.
static inline uint32_t VmaNextPow2(uint32_t v)
{
@@ -4547,6 +3338,7 @@ static inline uint32_t VmaNextPow2(uint32_t v)
v++;
return v;
}
+
static inline uint64_t VmaNextPow2(uint64_t v)
{
v--;
@@ -4571,6 +3363,7 @@ static inline uint32_t VmaPrevPow2(uint32_t v)
v = v ^ (v >> 1);
return v;
}
+
static inline uint64_t VmaPrevPow2(uint64_t v)
{
v |= v >> 1;
@@ -4588,66 +3381,6 @@ static inline bool VmaStrIsEmpty(const char* pStr)
return pStr == VMA_NULL || *pStr == '\0';
}
-#if VMA_STATS_STRING_ENABLED
-
-static const char* VmaAlgorithmToStr(uint32_t algorithm)
-{
- switch(algorithm)
- {
- case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
- return "Linear";
- case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
- return "Buddy";
- case 0:
- return "Default";
- default:
- VMA_ASSERT(0);
- return "";
- }
-}
-
-#endif // #if VMA_STATS_STRING_ENABLED
-
-#ifndef VMA_SORT
-
-template<typename Iterator, typename Compare>
-Iterator VmaQuickSortPartition(Iterator beg, Iterator end, Compare cmp)
-{
- Iterator centerValue = end; --centerValue;
- Iterator insertIndex = beg;
- for(Iterator memTypeIndex = beg; memTypeIndex < centerValue; ++memTypeIndex)
- {
- if(cmp(*memTypeIndex, *centerValue))
- {
- if(insertIndex != memTypeIndex)
- {
- VMA_SWAP(*memTypeIndex, *insertIndex);
- }
- ++insertIndex;
- }
- }
- if(insertIndex != centerValue)
- {
- VMA_SWAP(*insertIndex, *centerValue);
- }
- return insertIndex;
-}
-
-template<typename Iterator, typename Compare>
-void VmaQuickSort(Iterator beg, Iterator end, Compare cmp)
-{
- if(beg < end)
- {
- Iterator it = VmaQuickSortPartition<Iterator, Compare>(beg, end, cmp);
- VmaQuickSort<Iterator, Compare>(beg, it, cmp);
- VmaQuickSort<Iterator, Compare>(it + 1, end, cmp);
- }
-}
-
-#define VMA_SORT(beg, end, cmp) VmaQuickSort(beg, end, cmp)
-
-#endif // #ifndef VMA_SORT
-
/*
Returns true if two memory blocks occupy overlapping pages.
ResourceA must be in less memory offset than ResourceB.
@@ -4669,17 +3402,6 @@ static inline bool VmaBlocksOnSamePage(
return resourceAEndPage == resourceBStartPage;
}
-enum VmaSuballocationType
-{
- VMA_SUBALLOCATION_TYPE_FREE = 0,
- VMA_SUBALLOCATION_TYPE_UNKNOWN = 1,
- VMA_SUBALLOCATION_TYPE_BUFFER = 2,
- VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN = 3,
- VMA_SUBALLOCATION_TYPE_IMAGE_LINEAR = 4,
- VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL = 5,
- VMA_SUBALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
-};
-
/*
Returns true if given suballocation types could conflict and must respect
VkPhysicalDeviceLimits::bufferImageGranularity. They conflict if one is buffer
@@ -4690,12 +3412,12 @@ static inline bool VmaIsBufferImageGranularityConflict(
VmaSuballocationType suballocType1,
VmaSuballocationType suballocType2)
{
- if(suballocType1 > suballocType2)
+ if (suballocType1 > suballocType2)
{
VMA_SWAP(suballocType1, suballocType2);
}
- switch(suballocType1)
+ switch (suballocType1)
{
case VMA_SUBALLOCATION_TYPE_FREE:
return false;
@@ -4726,7 +3448,7 @@ static void VmaWriteMagicValue(void* pData, VkDeviceSize offset)
#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
uint32_t* pDst = (uint32_t*)((char*)pData + offset);
const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
- for(size_t i = 0; i < numberCount; ++i, ++pDst)
+ for (size_t i = 0; i < numberCount; ++i, ++pDst)
{
*pDst = VMA_CORRUPTION_DETECTION_MAGIC_VALUE;
}
@@ -4740,9 +3462,9 @@ static bool VmaValidateMagicValue(const void* pData, VkDeviceSize offset)
#if VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_DETECT_CORRUPTION
const uint32_t* pSrc = (const uint32_t*)((const char*)pData + offset);
const size_t numberCount = VMA_DEBUG_MARGIN / sizeof(uint32_t);
- for(size_t i = 0; i < numberCount; ++i, ++pSrc)
+ for (size_t i = 0; i < numberCount; ++i, ++pSrc)
{
- if(*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
+ if (*pSrc != VMA_CORRUPTION_DETECTION_MAGIC_VALUE)
{
return false;
}
@@ -4763,55 +3485,6 @@ static void VmaFillGpuDefragmentationBufferCreateInfo(VkBufferCreateInfo& outBuf
outBufCreateInfo.size = (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE; // Example size.
}
-// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
-struct VmaMutexLock
-{
- VMA_CLASS_NO_COPY(VmaMutexLock)
-public:
- VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) :
- m_pMutex(useMutex ? &mutex : VMA_NULL)
- { if(m_pMutex) { m_pMutex->Lock(); } }
- ~VmaMutexLock()
- { if(m_pMutex) { m_pMutex->Unlock(); } }
-private:
- VMA_MUTEX* m_pMutex;
-};
-
-// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.
-struct VmaMutexLockRead
-{
- VMA_CLASS_NO_COPY(VmaMutexLockRead)
-public:
- VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :
- m_pMutex(useMutex ? &mutex : VMA_NULL)
- { if(m_pMutex) { m_pMutex->LockRead(); } }
- ~VmaMutexLockRead() { if(m_pMutex) { m_pMutex->UnlockRead(); } }
-private:
- VMA_RW_MUTEX* m_pMutex;
-};
-
-// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.
-struct VmaMutexLockWrite
-{
- VMA_CLASS_NO_COPY(VmaMutexLockWrite)
-public:
- VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex) :
- m_pMutex(useMutex ? &mutex : VMA_NULL)
- { if(m_pMutex) { m_pMutex->LockWrite(); } }
- ~VmaMutexLockWrite() { if(m_pMutex) { m_pMutex->UnlockWrite(); } }
-private:
- VMA_RW_MUTEX* m_pMutex;
-};
-
-#if VMA_DEBUG_GLOBAL_MUTEX
- static VMA_MUTEX gDebugGlobalMutex;
- #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);
-#else
- #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#endif
-
-// Minimum size of a free suballocation to register it in the free suballocation collection.
-static const VkDeviceSize VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER = 16;
/*
Performs binary search and returns iterator to first element that is greater or
@@ -4823,13 +3496,13 @@ Returned value is the found element, if present in the collection or place where
new element with value (key) should be inserted.
*/
template <typename CmpLess, typename IterT, typename KeyT>
-static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT &key, const CmpLess& cmp)
+static IterT VmaBinaryFindFirstNotLess(IterT beg, IterT end, const KeyT& key, const CmpLess& cmp)
{
size_t down = 0, up = (end - beg);
- while(down < up)
+ while (down < up)
{
const size_t mid = down + (up - down) / 2; // Overflow-safe midpoint calculation
- if(cmp(*(beg+mid), key))
+ if (cmp(*(beg + mid), key))
{
down = mid + 1;
}
@@ -4846,7 +3519,7 @@ IterT VmaBinaryFindSorted(const IterT& beg, const IterT& end, const KeyT& value,
{
IterT it = VmaBinaryFindFirstNotLess<CmpLess, IterT, KeyT>(
beg, end, value, cmp);
- if(it == end ||
+ if (it == end ||
(!cmp(*it, value) && !cmp(value, *it)))
{
return it;
@@ -4862,16 +3535,16 @@ T must be pointer type, e.g. VmaAllocation, VmaPool.
template<typename T>
static bool VmaValidatePointerArray(uint32_t count, const T* arr)
{
- for(uint32_t i = 0; i < count; ++i)
+ for (uint32_t i = 0; i < count; ++i)
{
const T iPtr = arr[i];
- if(iPtr == VMA_NULL)
+ if (iPtr == VMA_NULL)
{
return false;
}
- for(uint32_t j = i + 1; j < count; ++j)
+ for (uint32_t j = i + 1; j < count; ++j)
{
- if(iPtr == arr[j])
+ if (iPtr == arr[j])
{
return false;
}
@@ -4887,13 +3560,161 @@ static inline void VmaPnextChainPushFront(MainT* mainStruct, NewT* newStruct)
mainStruct->pNext = newStruct;
}
+// This is the main algorithm that guides the selection of a memory type best for an allocation -
+// converts usage to required/preferred/not preferred flags.
+static bool FindMemoryPreferences(
+ bool isIntegratedGPU,
+ const VmaAllocationCreateInfo& allocCreateInfo,
+ VkFlags bufImgUsage, // VkBufferCreateInfo::usage or VkImageCreateInfo::usage. UINT32_MAX if unknown.
+ VkMemoryPropertyFlags& outRequiredFlags,
+ VkMemoryPropertyFlags& outPreferredFlags,
+ VkMemoryPropertyFlags& outNotPreferredFlags)
+{
+ outRequiredFlags = allocCreateInfo.requiredFlags;
+ outPreferredFlags = allocCreateInfo.preferredFlags;
+ outNotPreferredFlags = 0;
+
+ switch(allocCreateInfo.usage)
+ {
+ case VMA_MEMORY_USAGE_UNKNOWN:
+ break;
+ case VMA_MEMORY_USAGE_GPU_ONLY:
+ if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_CPU_ONLY:
+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ break;
+ case VMA_MEMORY_USAGE_CPU_TO_GPU:
+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ if(!isIntegratedGPU || (outPreferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ {
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ case VMA_MEMORY_USAGE_GPU_TO_CPU:
+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ outPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ break;
+ case VMA_MEMORY_USAGE_CPU_COPY:
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ break;
+ case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:
+ outRequiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
+ break;
+ case VMA_MEMORY_USAGE_AUTO:
+ case VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE:
+ case VMA_MEMORY_USAGE_AUTO_PREFER_HOST:
+ {
+ if(bufImgUsage == UINT32_MAX)
+ {
+ VMA_ASSERT(0 && "VMA_MEMORY_USAGE_AUTO* values can only be used with functions like vmaCreateBuffer, vmaCreateImage so that the details of the created resource are known.");
+ return false;
+ }
+ // This relies on values of VK_IMAGE_USAGE_TRANSFER* being the same VK_BUFFER_IMAGE_TRANSFER*.
+ const bool deviceAccess = (bufImgUsage & ~(VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT)) != 0;
+ const bool hostAccessSequentialWrite = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT) != 0;
+ const bool hostAccessRandom = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) != 0;
+ const bool hostAccessAllowTransferInstead = (allocCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) != 0;
+ const bool preferDevice = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
+ const bool preferHost = allocCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST;
+
+ // CPU random access - e.g. a buffer written to or transferred from GPU to read back on CPU.
+ if(hostAccessRandom)
+ {
+ if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost)
+ {
+ // Nice if it will end up in HOST_VISIBLE, but more importantly prefer DEVICE_LOCAL.
+ // Omitting HOST_VISIBLE here is intentional.
+ // In case there is DEVICE_LOCAL | HOST_VISIBLE | HOST_CACHED, it will pick that one.
+ // Otherwise, this will give same weight to DEVICE_LOCAL as HOST_VISIBLE | HOST_CACHED and select the former if occurs first on the list.
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ }
+ else
+ {
+ // Always CPU memory, cached.
+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+ }
+ }
+ // CPU sequential write - may be CPU or host-visible GPU memory, uncached and write-combined.
+ else if(hostAccessSequentialWrite)
+ {
+ // Want uncached and write-combined.
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+
+ if(!isIntegratedGPU && deviceAccess && hostAccessAllowTransferInstead && !preferHost)
+ {
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ }
+ else
+ {
+ outRequiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ // Direct GPU access, CPU sequential write (e.g. a dynamic uniform buffer updated every frame)
+ if(deviceAccess)
+ {
+ // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose GPU memory.
+ if(preferHost)
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ else
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ // GPU no direct access, CPU sequential write (e.g. an upload buffer to be transferred to the GPU)
+ else
+ {
+ // Could go to CPU memory or GPU BAR/unified. Up to the user to decide. If no preference, choose CPU memory.
+ if(preferDevice)
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ else
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ }
+ }
+ // No CPU access
+ else
+ {
+ // GPU access, no CPU access (e.g. a color attachment image) - prefer GPU memory
+ if(deviceAccess)
+ {
+ // ...unless there is a clear preference from the user not to do so.
+ if(preferHost)
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ else
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ // No direct GPU access, no CPU access, just transfers.
+ // It may be staging copy intended for e.g. preserving image for next frame (then better GPU memory) or
+ // a "swap file" copy to free some GPU memory (then better CPU memory).
+ // Up to the user to decide. If no preferece, assume the former and choose GPU memory.
+ if(preferHost)
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ else
+ outPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ }
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
+ }
+
+ // Avoid DEVICE_COHERENT unless explicitly requested.
+ if(((allocCreateInfo.requiredFlags | allocCreateInfo.preferredFlags) &
+ (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0)
+ {
+ outNotPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY;
+ }
+
+ return true;
+}
+
////////////////////////////////////////////////////////////////////////////////
// Memory allocation
static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t size, size_t alignment)
{
void* result = VMA_NULL;
- if((pAllocationCallbacks != VMA_NULL) &&
+ if ((pAllocationCallbacks != VMA_NULL) &&
(pAllocationCallbacks->pfnAllocation != VMA_NULL))
{
result = (*pAllocationCallbacks->pfnAllocation)(
@@ -4912,7 +3733,7 @@ static void* VmaMalloc(const VkAllocationCallbacks* pAllocationCallbacks, size_t
static void VmaFree(const VkAllocationCallbacks* pAllocationCallbacks, void* ptr)
{
- if((pAllocationCallbacks != VMA_NULL) &&
+ if ((pAllocationCallbacks != VMA_NULL) &&
(pAllocationCallbacks->pfnFree != VMA_NULL))
{
(*pAllocationCallbacks->pfnFree)(pAllocationCallbacks->pUserData, ptr);
@@ -4949,9 +3770,9 @@ static void vma_delete(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr
template<typename T>
static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks, T* ptr, size_t count)
{
- if(ptr != VMA_NULL)
+ if (ptr != VMA_NULL)
{
- for(size_t i = count; i--; )
+ for (size_t i = count; i--; )
{
ptr[i].~T();
}
@@ -4961,302 +3782,437 @@ static void vma_delete_array(const VkAllocationCallbacks* pAllocationCallbacks,
static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr)
{
- if(srcStr != VMA_NULL)
+ if (srcStr != VMA_NULL)
{
const size_t len = strlen(srcStr);
char* const result = vma_new_array(allocs, char, len + 1);
memcpy(result, srcStr, len + 1);
return result;
}
- else
+ return VMA_NULL;
+}
+
+#if VMA_STATS_STRING_ENABLED
+static char* VmaCreateStringCopy(const VkAllocationCallbacks* allocs, const char* srcStr, size_t strLen)
+{
+ if (srcStr != VMA_NULL)
{
- return VMA_NULL;
+ char* const result = vma_new_array(allocs, char, strLen + 1);
+ memcpy(result, srcStr, strLen);
+ result[strLen] = '\0';
+ return result;
}
+ return VMA_NULL;
}
+#endif // VMA_STATS_STRING_ENABLED
static void VmaFreeString(const VkAllocationCallbacks* allocs, char* str)
{
- if(str != VMA_NULL)
+ if (str != VMA_NULL)
{
const size_t len = strlen(str);
vma_delete_array(allocs, str, len + 1);
}
}
-// STL-compatible allocator.
-template<typename T>
-class VmaStlAllocator
+template<typename CmpLess, typename VectorT>
+size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)
{
-public:
- const VkAllocationCallbacks* const m_pCallbacks;
- typedef T value_type;
-
- VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) { }
- template<typename U> VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) { }
-
- T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
- void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }
+ const size_t indexToInsert = VmaBinaryFindFirstNotLess(
+ vector.data(),
+ vector.data() + vector.size(),
+ value,
+ CmpLess()) - vector.data();
+ VmaVectorInsert(vector, indexToInsert, value);
+ return indexToInsert;
+}
- template<typename U>
- bool operator==(const VmaStlAllocator<U>& rhs) const
- {
- return m_pCallbacks == rhs.m_pCallbacks;
- }
- template<typename U>
- bool operator!=(const VmaStlAllocator<U>& rhs) const
+template<typename CmpLess, typename VectorT>
+bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)
+{
+ CmpLess comparator;
+ typename VectorT::iterator it = VmaBinaryFindFirstNotLess(
+ vector.begin(),
+ vector.end(),
+ value,
+ comparator);
+ if ((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))
{
- return m_pCallbacks != rhs.m_pCallbacks;
+ size_t indexToRemove = it - vector.begin();
+ VmaVectorRemove(vector, indexToRemove);
+ return true;
}
+ return false;
+}
+#endif // _VMA_FUNCTIONS
- VmaStlAllocator& operator=(const VmaStlAllocator& x) = delete;
- VmaStlAllocator(const VmaStlAllocator&) = default;
-};
+#ifndef _VMA_STATISTICS_FUNCTIONS
-#if VMA_USE_STL_VECTOR
+static void VmaClearStatistics(VmaStatistics& outStats)
+{
+ outStats.blockCount = 0;
+ outStats.allocationCount = 0;
+ outStats.blockBytes = 0;
+ outStats.allocationBytes = 0;
+}
-#define VmaVector std::vector
+static void VmaAddStatistics(VmaStatistics& inoutStats, const VmaStatistics& src)
+{
+ inoutStats.blockCount += src.blockCount;
+ inoutStats.allocationCount += src.allocationCount;
+ inoutStats.blockBytes += src.blockBytes;
+ inoutStats.allocationBytes += src.allocationBytes;
+}
-template<typename T, typename allocatorT>
-static void VmaVectorInsert(std::vector<T, allocatorT>& vec, size_t index, const T& item)
+static void VmaClearDetailedStatistics(VmaDetailedStatistics& outStats)
{
- vec.insert(vec.begin() + index, item);
+ VmaClearStatistics(outStats.statistics);
+ outStats.unusedRangeCount = 0;
+ outStats.allocationSizeMin = VK_WHOLE_SIZE;
+ outStats.allocationSizeMax = 0;
+ outStats.unusedRangeSizeMin = VK_WHOLE_SIZE;
+ outStats.unusedRangeSizeMax = 0;
}
-template<typename T, typename allocatorT>
-static void VmaVectorRemove(std::vector<T, allocatorT>& vec, size_t index)
+static void VmaAddDetailedStatisticsAllocation(VmaDetailedStatistics& inoutStats, VkDeviceSize size)
{
- vec.erase(vec.begin() + index);
+ inoutStats.statistics.allocationCount++;
+ inoutStats.statistics.allocationBytes += size;
+ inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, size);
+ inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, size);
}
-#else // #if VMA_USE_STL_VECTOR
+static void VmaAddDetailedStatisticsUnusedRange(VmaDetailedStatistics& inoutStats, VkDeviceSize size)
+{
+ inoutStats.unusedRangeCount++;
+ inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, size);
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, size);
+}
-/* Class with interface compatible with subset of std::vector.
-T must be POD because constructors and destructors are not called and memcpy is
-used for these objects. */
-template<typename T, typename AllocatorT>
-class VmaVector
+static void VmaAddDetailedStatistics(VmaDetailedStatistics& inoutStats, const VmaDetailedStatistics& src)
{
+ VmaAddStatistics(inoutStats.statistics, src.statistics);
+ inoutStats.unusedRangeCount += src.unusedRangeCount;
+ inoutStats.allocationSizeMin = VMA_MIN(inoutStats.allocationSizeMin, src.allocationSizeMin);
+ inoutStats.allocationSizeMax = VMA_MAX(inoutStats.allocationSizeMax, src.allocationSizeMax);
+ inoutStats.unusedRangeSizeMin = VMA_MIN(inoutStats.unusedRangeSizeMin, src.unusedRangeSizeMin);
+ inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, src.unusedRangeSizeMax);
+}
+
+#endif // _VMA_STATISTICS_FUNCTIONS
+
+#ifndef _VMA_MUTEX_LOCK
+// Helper RAII class to lock a mutex in constructor and unlock it in destructor (at the end of scope).
+struct VmaMutexLock
+{
+ VMA_CLASS_NO_COPY(VmaMutexLock)
public:
- typedef T value_type;
+ VmaMutexLock(VMA_MUTEX& mutex, bool useMutex = true) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
+ {
+ if (m_pMutex) { m_pMutex->Lock(); }
+ }
+ ~VmaMutexLock() { if (m_pMutex) { m_pMutex->Unlock(); } }
+
+private:
+ VMA_MUTEX* m_pMutex;
+};
- VmaVector(const AllocatorT& allocator) :
- m_Allocator(allocator),
- m_pArray(VMA_NULL),
- m_Count(0),
- m_Capacity(0)
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for reading.
+struct VmaMutexLockRead
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockRead)
+public:
+ VmaMutexLockRead(VMA_RW_MUTEX& mutex, bool useMutex) :
+ m_pMutex(useMutex ? &mutex : VMA_NULL)
{
+ if (m_pMutex) { m_pMutex->LockRead(); }
}
+ ~VmaMutexLockRead() { if (m_pMutex) { m_pMutex->UnlockRead(); } }
- VmaVector(size_t count, const AllocatorT& allocator) :
- m_Allocator(allocator),
- m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),
- m_Count(count),
- m_Capacity(count)
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
+
+// Helper RAII class to lock a RW mutex in constructor and unlock it in destructor (at the end of scope), for writing.
+struct VmaMutexLockWrite
+{
+ VMA_CLASS_NO_COPY(VmaMutexLockWrite)
+public:
+ VmaMutexLockWrite(VMA_RW_MUTEX& mutex, bool useMutex)
+ : m_pMutex(useMutex ? &mutex : VMA_NULL)
{
+ if (m_pMutex) { m_pMutex->LockWrite(); }
}
+ ~VmaMutexLockWrite() { if (m_pMutex) { m_pMutex->UnlockWrite(); } }
- // This version of the constructor is here for compatibility with pre-C++14 std::vector.
- // value is unused.
- VmaVector(size_t count, const T& value, const AllocatorT& allocator)
- : VmaVector(count, allocator) {}
+private:
+ VMA_RW_MUTEX* m_pMutex;
+};
- VmaVector(const VmaVector<T, AllocatorT>& src) :
- m_Allocator(src.m_Allocator),
- m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),
- m_Count(src.m_Count),
- m_Capacity(src.m_Count)
+#if VMA_DEBUG_GLOBAL_MUTEX
+ static VMA_MUTEX gDebugGlobalMutex;
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK VmaMutexLock debugGlobalMutexLock(gDebugGlobalMutex, true);
+#else
+ #define VMA_DEBUG_GLOBAL_MUTEX_LOCK
+#endif
+#endif // _VMA_MUTEX_LOCK
+
+#ifndef _VMA_ATOMIC_TRANSACTIONAL_INCREMENT
+// An object that increments given atomic but decrements it back in the destructor unless Commit() is called.
+template<typename T>
+struct AtomicTransactionalIncrement
+{
+public:
+ typedef std::atomic<T> AtomicT;
+
+ ~AtomicTransactionalIncrement()
{
- if(m_Count != 0)
- {
- memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));
- }
+ if(m_Atomic)
+ --(*m_Atomic);
}
- ~VmaVector()
+ void Commit() { m_Atomic = nullptr; }
+ T Increment(AtomicT* atomic)
{
- VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Atomic = atomic;
+ return m_Atomic->fetch_add(1);
}
- VmaVector& operator=(const VmaVector<T, AllocatorT>& rhs)
+private:
+ AtomicT* m_Atomic = nullptr;
+};
+#endif // _VMA_ATOMIC_TRANSACTIONAL_INCREMENT
+
+#ifndef _VMA_STL_ALLOCATOR
+// STL-compatible allocator.
+template<typename T>
+struct VmaStlAllocator
+{
+ const VkAllocationCallbacks* const m_pCallbacks;
+ typedef T value_type;
+
+ VmaStlAllocator(const VkAllocationCallbacks* pCallbacks) : m_pCallbacks(pCallbacks) {}
+ template<typename U>
+ VmaStlAllocator(const VmaStlAllocator<U>& src) : m_pCallbacks(src.m_pCallbacks) {}
+ VmaStlAllocator(const VmaStlAllocator&) = default;
+ VmaStlAllocator& operator=(const VmaStlAllocator&) = delete;
+
+ T* allocate(size_t n) { return VmaAllocateArray<T>(m_pCallbacks, n); }
+ void deallocate(T* p, size_t n) { VmaFree(m_pCallbacks, p); }
+
+ template<typename U>
+ bool operator==(const VmaStlAllocator<U>& rhs) const
{
- if(&rhs != this)
- {
- resize(rhs.m_Count);
- if(m_Count != 0)
- {
- memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));
- }
- }
- return *this;
+ return m_pCallbacks == rhs.m_pCallbacks;
+ }
+ template<typename U>
+ bool operator!=(const VmaStlAllocator<U>& rhs) const
+ {
+ return m_pCallbacks != rhs.m_pCallbacks;
}
+};
+#endif // _VMA_STL_ALLOCATOR
+
+#ifndef _VMA_VECTOR
+/* Class with interface compatible with subset of std::vector.
+T must be POD because constructors and destructors are not called and memcpy is
+used for these objects. */
+template<typename T, typename AllocatorT>
+class VmaVector
+{
+public:
+ typedef T value_type;
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ VmaVector(const AllocatorT& allocator);
+ VmaVector(size_t count, const AllocatorT& allocator);
+ // This version of the constructor is here for compatibility with pre-C++14 std::vector.
+ // value is unused.
+ VmaVector(size_t count, const T& value, const AllocatorT& allocator) : VmaVector(count, allocator) {}
+ VmaVector(const VmaVector<T, AllocatorT>& src);
+ VmaVector& operator=(const VmaVector& rhs);
+ ~VmaVector() { VmaFree(m_Allocator.m_pCallbacks, m_pArray); }
bool empty() const { return m_Count == 0; }
size_t size() const { return m_Count; }
T* data() { return m_pArray; }
+ T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; }
+ T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; }
const T* data() const { return m_pArray; }
+ const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[0]; }
+ const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return m_pArray[m_Count - 1]; }
- T& operator[](size_t index)
- {
- VMA_HEAVY_ASSERT(index < m_Count);
- return m_pArray[index];
- }
- const T& operator[](size_t index) const
- {
- VMA_HEAVY_ASSERT(index < m_Count);
- return m_pArray[index];
- }
+ iterator begin() { return m_pArray; }
+ iterator end() { return m_pArray + m_Count; }
+ const_iterator cbegin() const { return m_pArray; }
+ const_iterator cend() const { return m_pArray + m_Count; }
+ const_iterator begin() const { return cbegin(); }
+ const_iterator end() const { return cend(); }
- T& front()
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return m_pArray[0];
- }
- const T& front() const
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return m_pArray[0];
- }
- T& back()
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return m_pArray[m_Count - 1];
- }
- const T& back() const
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return m_pArray[m_Count - 1];
- }
+ void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); }
+ void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); }
+ void push_front(const T& src) { insert(0, src); }
- void reserve(size_t newCapacity, bool freeMemory = false)
- {
- newCapacity = VMA_MAX(newCapacity, m_Count);
+ void push_back(const T& src);
+ void reserve(size_t newCapacity, bool freeMemory = false);
+ void resize(size_t newCount);
+ void clear() { resize(0); }
+ void shrink_to_fit();
+ void insert(size_t index, const T& src);
+ void remove(size_t index);
- if((newCapacity < m_Capacity) && !freeMemory)
- {
- newCapacity = m_Capacity;
- }
+ T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; }
+ const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return m_pArray[index]; }
- if(newCapacity != m_Capacity)
- {
- T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;
- if(m_Count != 0)
- {
- memcpy(newArray, m_pArray, m_Count * sizeof(T));
- }
- VmaFree(m_Allocator.m_pCallbacks, m_pArray);
- m_Capacity = newCapacity;
- m_pArray = newArray;
- }
+private:
+ AllocatorT m_Allocator;
+ T* m_pArray;
+ size_t m_Count;
+ size_t m_Capacity;
+};
+
+#ifndef _VMA_VECTOR_FUNCTIONS
+template<typename T, typename AllocatorT>
+VmaVector<T, AllocatorT>::VmaVector(const AllocatorT& allocator)
+ : m_Allocator(allocator),
+ m_pArray(VMA_NULL),
+ m_Count(0),
+ m_Capacity(0) {}
+
+template<typename T, typename AllocatorT>
+VmaVector<T, AllocatorT>::VmaVector(size_t count, const AllocatorT& allocator)
+ : m_Allocator(allocator),
+ m_pArray(count ? (T*)VmaAllocateArray<T>(allocator.m_pCallbacks, count) : VMA_NULL),
+ m_Count(count),
+ m_Capacity(count) {}
+
+template<typename T, typename AllocatorT>
+VmaVector<T, AllocatorT>::VmaVector(const VmaVector& src)
+ : m_Allocator(src.m_Allocator),
+ m_pArray(src.m_Count ? (T*)VmaAllocateArray<T>(src.m_Allocator.m_pCallbacks, src.m_Count) : VMA_NULL),
+ m_Count(src.m_Count),
+ m_Capacity(src.m_Count)
+{
+ if (m_Count != 0)
+ {
+ memcpy(m_pArray, src.m_pArray, m_Count * sizeof(T));
}
+}
- void resize(size_t newCount)
+template<typename T, typename AllocatorT>
+VmaVector<T, AllocatorT>& VmaVector<T, AllocatorT>::operator=(const VmaVector& rhs)
+{
+ if (&rhs != this)
{
- size_t newCapacity = m_Capacity;
- if(newCount > m_Capacity)
+ resize(rhs.m_Count);
+ if (m_Count != 0)
{
- newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));
+ memcpy(m_pArray, rhs.m_pArray, m_Count * sizeof(T));
}
+ }
+ return *this;
+}
- if(newCapacity != m_Capacity)
- {
- T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;
- const size_t elementsToCopy = VMA_MIN(m_Count, newCount);
- if(elementsToCopy != 0)
- {
- memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));
- }
- VmaFree(m_Allocator.m_pCallbacks, m_pArray);
- m_Capacity = newCapacity;
- m_pArray = newArray;
- }
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::push_back(const T& src)
+{
+ const size_t newIndex = size();
+ resize(newIndex + 1);
+ m_pArray[newIndex] = src;
+}
- m_Count = newCount;
- }
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::reserve(size_t newCapacity, bool freeMemory)
+{
+ newCapacity = VMA_MAX(newCapacity, m_Count);
- void clear()
+ if ((newCapacity < m_Capacity) && !freeMemory)
{
- resize(0);
+ newCapacity = m_Capacity;
}
- void shrink_to_fit()
+ if (newCapacity != m_Capacity)
{
- if(m_Capacity > m_Count)
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator, newCapacity) : VMA_NULL;
+ if (m_Count != 0)
{
- T* newArray = VMA_NULL;
- if(m_Count > 0)
- {
- newArray = VmaAllocateArray<T>(m_Allocator.m_pCallbacks, m_Count);
- memcpy(newArray, m_pArray, m_Count * sizeof(T));
- }
- VmaFree(m_Allocator.m_pCallbacks, m_pArray);
- m_Capacity = m_Count;
- m_pArray = newArray;
+ memcpy(newArray, m_pArray, m_Count * sizeof(T));
}
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
}
+}
- void insert(size_t index, const T& src)
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::resize(size_t newCount)
+{
+ size_t newCapacity = m_Capacity;
+ if (newCount > m_Capacity)
{
- VMA_HEAVY_ASSERT(index <= m_Count);
- const size_t oldCount = size();
- resize(oldCount + 1);
- if(index < oldCount)
- {
- memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));
- }
- m_pArray[index] = src;
+ newCapacity = VMA_MAX(newCount, VMA_MAX(m_Capacity * 3 / 2, (size_t)8));
}
- void remove(size_t index)
+ if (newCapacity != m_Capacity)
{
- VMA_HEAVY_ASSERT(index < m_Count);
- const size_t oldCount = size();
- if(index < oldCount - 1)
+ T* const newArray = newCapacity ? VmaAllocateArray<T>(m_Allocator.m_pCallbacks, newCapacity) : VMA_NULL;
+ const size_t elementsToCopy = VMA_MIN(m_Count, newCount);
+ if (elementsToCopy != 0)
{
- memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));
+ memcpy(newArray, m_pArray, elementsToCopy * sizeof(T));
}
- resize(oldCount - 1);
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = newCapacity;
+ m_pArray = newArray;
}
- void push_back(const T& src)
- {
- const size_t newIndex = size();
- resize(newIndex + 1);
- m_pArray[newIndex] = src;
- }
+ m_Count = newCount;
+}
- void pop_back()
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::shrink_to_fit()
+{
+ if (m_Capacity > m_Count)
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- resize(size() - 1);
+ T* newArray = VMA_NULL;
+ if (m_Count > 0)
+ {
+ newArray = VmaAllocateArray<T>(m_Allocator.m_pCallbacks, m_Count);
+ memcpy(newArray, m_pArray, m_Count * sizeof(T));
+ }
+ VmaFree(m_Allocator.m_pCallbacks, m_pArray);
+ m_Capacity = m_Count;
+ m_pArray = newArray;
}
+}
- void push_front(const T& src)
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::insert(size_t index, const T& src)
+{
+ VMA_HEAVY_ASSERT(index <= m_Count);
+ const size_t oldCount = size();
+ resize(oldCount + 1);
+ if (index < oldCount)
{
- insert(0, src);
+ memmove(m_pArray + (index + 1), m_pArray + index, (oldCount - index) * sizeof(T));
}
+ m_pArray[index] = src;
+}
- void pop_front()
+template<typename T, typename AllocatorT>
+void VmaVector<T, AllocatorT>::remove(size_t index)
+{
+ VMA_HEAVY_ASSERT(index < m_Count);
+ const size_t oldCount = size();
+ if (index < oldCount - 1)
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- remove(0);
+ memmove(m_pArray + index, m_pArray + (index + 1), (oldCount - index - 1) * sizeof(T));
}
-
- typedef T* iterator;
- typedef const T* const_iterator;
-
- iterator begin() { return m_pArray; }
- iterator end() { return m_pArray + m_Count; }
- const_iterator cbegin() const { return m_pArray; }
- const_iterator cend() const { return m_pArray + m_Count; }
- const_iterator begin() const { return cbegin(); }
- const_iterator end() const { return cend(); }
-
-private:
- AllocatorT m_Allocator;
- T* m_pArray;
- size_t m_Count;
- size_t m_Capacity;
-};
+ resize(oldCount - 1);
+}
+#endif // _VMA_VECTOR_FUNCTIONS
template<typename T, typename allocatorT>
static void VmaVectorInsert(VmaVector<T, allocatorT>& vec, size_t index, const T& item)
@@ -5269,42 +4225,9 @@ static void VmaVectorRemove(VmaVector<T, allocatorT>& vec, size_t index)
{
vec.remove(index);
}
+#endif // _VMA_VECTOR
-#endif // #if VMA_USE_STL_VECTOR
-
-template<typename CmpLess, typename VectorT>
-size_t VmaVectorInsertSorted(VectorT& vector, const typename VectorT::value_type& value)
-{
- const size_t indexToInsert = VmaBinaryFindFirstNotLess(
- vector.data(),
- vector.data() + vector.size(),
- value,
- CmpLess()) - vector.data();
- VmaVectorInsert(vector, indexToInsert, value);
- return indexToInsert;
-}
-
-template<typename CmpLess, typename VectorT>
-bool VmaVectorRemoveSorted(VectorT& vector, const typename VectorT::value_type& value)
-{
- CmpLess comparator;
- typename VectorT::iterator it = VmaBinaryFindFirstNotLess(
- vector.begin(),
- vector.end(),
- value,
- comparator);
- if((it != vector.end()) && !comparator(*it, value) && !comparator(value, *it))
- {
- size_t indexToRemove = it - vector.begin();
- VmaVectorRemove(vector, indexToRemove);
- return true;
- }
- return false;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// class VmaSmallVector
-
+#ifndef _VMA_SMALL_VECTOR
/*
This is a vector (a variable-sized array), optimized for the case when the array is small.
@@ -5312,180 +4235,155 @@ It contains some number of elements in-place, which allows it to avoid heap allo
when the actual number of elements is below that threshold. This allows normal "small"
cases to be fast without losing generality for large inputs.
*/
-
template<typename T, typename AllocatorT, size_t N>
class VmaSmallVector
{
public:
typedef T value_type;
+ typedef T* iterator;
- VmaSmallVector(const AllocatorT& allocator) :
- m_Count(0),
- m_DynamicArray(allocator)
- {
- }
- VmaSmallVector(size_t count, const AllocatorT& allocator) :
- m_Count(count),
- m_DynamicArray(count > N ? count : 0, allocator)
- {
- }
+ VmaSmallVector(const AllocatorT& allocator);
+ VmaSmallVector(size_t count, const AllocatorT& allocator);
template<typename SrcT, typename SrcAllocatorT, size_t SrcN>
- VmaSmallVector(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>& src) = delete;
+ VmaSmallVector(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>&) = delete;
template<typename SrcT, typename SrcAllocatorT, size_t SrcN>
- VmaSmallVector<T, AllocatorT, N>& operator=(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>& rhs) = delete;
+ VmaSmallVector<T, AllocatorT, N>& operator=(const VmaSmallVector<SrcT, SrcAllocatorT, SrcN>&) = delete;
+ ~VmaSmallVector() = default;
bool empty() const { return m_Count == 0; }
size_t size() const { return m_Count; }
T* data() { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; }
+ T& front() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; }
+ T& back() { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; }
const T* data() const { return m_Count > N ? m_DynamicArray.data() : m_StaticArray; }
+ const T& front() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[0]; }
+ const T& back() const { VMA_HEAVY_ASSERT(m_Count > 0); return data()[m_Count - 1]; }
- T& operator[](size_t index)
- {
- VMA_HEAVY_ASSERT(index < m_Count);
- return data()[index];
- }
- const T& operator[](size_t index) const
- {
- VMA_HEAVY_ASSERT(index < m_Count);
- return data()[index];
- }
+ iterator begin() { return data(); }
+ iterator end() { return data() + m_Count; }
- T& front()
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return data()[0];
- }
- const T& front() const
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return data()[0];
- }
- T& back()
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return data()[m_Count - 1];
- }
- const T& back() const
- {
- VMA_HEAVY_ASSERT(m_Count > 0);
- return data()[m_Count - 1];
- }
+ void pop_front() { VMA_HEAVY_ASSERT(m_Count > 0); remove(0); }
+ void pop_back() { VMA_HEAVY_ASSERT(m_Count > 0); resize(size() - 1); }
+ void push_front(const T& src) { insert(0, src); }
- void resize(size_t newCount, bool freeMemory = false)
- {
- if(newCount > N && m_Count > N)
- {
- // Any direction, staying in m_DynamicArray
- m_DynamicArray.resize(newCount);
- if(freeMemory)
- {
- m_DynamicArray.shrink_to_fit();
- }
- }
- else if(newCount > N && m_Count <= N)
- {
- // Growing, moving from m_StaticArray to m_DynamicArray
- m_DynamicArray.resize(newCount);
- if(m_Count > 0)
- {
- memcpy(m_DynamicArray.data(), m_StaticArray, m_Count * sizeof(T));
- }
- }
- else if(newCount <= N && m_Count > N)
- {
- // Shrinking, moving from m_DynamicArray to m_StaticArray
- if(newCount > 0)
- {
- memcpy(m_StaticArray, m_DynamicArray.data(), newCount * sizeof(T));
- }
- m_DynamicArray.resize(0);
- if(freeMemory)
- {
- m_DynamicArray.shrink_to_fit();
- }
- }
- else
- {
- // Any direction, staying in m_StaticArray - nothing to do here
- }
- m_Count = newCount;
- }
+ void push_back(const T& src);
+ void resize(size_t newCount, bool freeMemory = false);
+ void clear(bool freeMemory = false);
+ void insert(size_t index, const T& src);
+ void remove(size_t index);
- void clear(bool freeMemory = false)
+ T& operator[](size_t index) { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; }
+ const T& operator[](size_t index) const { VMA_HEAVY_ASSERT(index < m_Count); return data()[index]; }
+
+private:
+ size_t m_Count;
+ T m_StaticArray[N]; // Used when m_Size <= N
+ VmaVector<T, AllocatorT> m_DynamicArray; // Used when m_Size > N
+};
+
+#ifndef _VMA_SMALL_VECTOR_FUNCTIONS
+template<typename T, typename AllocatorT, size_t N>
+VmaSmallVector<T, AllocatorT, N>::VmaSmallVector(const AllocatorT& allocator)
+ : m_Count(0),
+ m_DynamicArray(allocator) {}
+
+template<typename T, typename AllocatorT, size_t N>
+VmaSmallVector<T, AllocatorT, N>::VmaSmallVector(size_t count, const AllocatorT& allocator)
+ : m_Count(count),
+ m_DynamicArray(count > N ? count : 0, allocator) {}
+
+template<typename T, typename AllocatorT, size_t N>
+void VmaSmallVector<T, AllocatorT, N>::push_back(const T& src)
+{
+ const size_t newIndex = size();
+ resize(newIndex + 1);
+ data()[newIndex] = src;
+}
+
+template<typename T, typename AllocatorT, size_t N>
+void VmaSmallVector<T, AllocatorT, N>::resize(size_t newCount, bool freeMemory)
+{
+ if (newCount > N && m_Count > N)
{
- m_DynamicArray.clear();
- if(freeMemory)
+ // Any direction, staying in m_DynamicArray
+ m_DynamicArray.resize(newCount);
+ if (freeMemory)
{
m_DynamicArray.shrink_to_fit();
}
- m_Count = 0;
}
-
- void insert(size_t index, const T& src)
+ else if (newCount > N && m_Count <= N)
{
- VMA_HEAVY_ASSERT(index <= m_Count);
- const size_t oldCount = size();
- resize(oldCount + 1);
- T* const dataPtr = data();
- if(index < oldCount)
+ // Growing, moving from m_StaticArray to m_DynamicArray
+ m_DynamicArray.resize(newCount);
+ if (m_Count > 0)
{
- // I know, this could be more optimal for case where memmove can be memcpy directly from m_StaticArray to m_DynamicArray.
- memmove(dataPtr + (index + 1), dataPtr + index, (oldCount - index) * sizeof(T));
+ memcpy(m_DynamicArray.data(), m_StaticArray, m_Count * sizeof(T));
}
- dataPtr[index] = src;
}
-
- void remove(size_t index)
+ else if (newCount <= N && m_Count > N)
{
- VMA_HEAVY_ASSERT(index < m_Count);
- const size_t oldCount = size();
- if(index < oldCount - 1)
+ // Shrinking, moving from m_DynamicArray to m_StaticArray
+ if (newCount > 0)
{
- // I know, this could be more optimal for case where memmove can be memcpy directly from m_DynamicArray to m_StaticArray.
- T* const dataPtr = data();
- memmove(dataPtr + index, dataPtr + (index + 1), (oldCount - index - 1) * sizeof(T));
+ memcpy(m_StaticArray, m_DynamicArray.data(), newCount * sizeof(T));
+ }
+ m_DynamicArray.resize(0);
+ if (freeMemory)
+ {
+ m_DynamicArray.shrink_to_fit();
}
- resize(oldCount - 1);
}
-
- void push_back(const T& src)
+ else
{
- const size_t newIndex = size();
- resize(newIndex + 1);
- data()[newIndex] = src;
+ // Any direction, staying in m_StaticArray - nothing to do here
}
+ m_Count = newCount;
+}
- void pop_back()
+template<typename T, typename AllocatorT, size_t N>
+void VmaSmallVector<T, AllocatorT, N>::clear(bool freeMemory)
+{
+ m_DynamicArray.clear();
+ if (freeMemory)
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- resize(size() - 1);
+ m_DynamicArray.shrink_to_fit();
}
+ m_Count = 0;
+}
- void push_front(const T& src)
+template<typename T, typename AllocatorT, size_t N>
+void VmaSmallVector<T, AllocatorT, N>::insert(size_t index, const T& src)
+{
+ VMA_HEAVY_ASSERT(index <= m_Count);
+ const size_t oldCount = size();
+ resize(oldCount + 1);
+ T* const dataPtr = data();
+ if (index < oldCount)
{
- insert(0, src);
+ // I know, this could be more optimal for case where memmove can be memcpy directly from m_StaticArray to m_DynamicArray.
+ memmove(dataPtr + (index + 1), dataPtr + index, (oldCount - index) * sizeof(T));
}
+ dataPtr[index] = src;
+}
- void pop_front()
+template<typename T, typename AllocatorT, size_t N>
+void VmaSmallVector<T, AllocatorT, N>::remove(size_t index)
+{
+ VMA_HEAVY_ASSERT(index < m_Count);
+ const size_t oldCount = size();
+ if (index < oldCount - 1)
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- remove(0);
+ // I know, this could be more optimal for case where memmove can be memcpy directly from m_DynamicArray to m_StaticArray.
+ T* const dataPtr = data();
+ memmove(dataPtr + index, dataPtr + (index + 1), (oldCount - index - 1) * sizeof(T));
}
+ resize(oldCount - 1);
+}
+#endif // _VMA_SMALL_VECTOR_FUNCTIONS
+#endif // _VMA_SMALL_VECTOR
- typedef T* iterator;
-
- iterator begin() { return data(); }
- iterator end() { return data() + m_Count; }
-
-private:
- size_t m_Count;
- T m_StaticArray[N]; // Used when m_Size <= N
- VmaVector<T, AllocatorT> m_DynamicArray; // Used when m_Size > N
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// class VmaPoolAllocator
-
+#ifndef _VMA_POOL_ALLOCATOR
/*
Allocator for objects of type T using a list of arrays (pools) to speed up
allocation. Number of elements that can be allocated is not bounded because
@@ -5498,7 +4396,7 @@ class VmaPoolAllocator
public:
VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity);
~VmaPoolAllocator();
- template<typename... Types> T* Alloc(Types... args);
+ template<typename... Types> T* Alloc(Types&&... args);
void Free(T* ptr);
private:
@@ -5507,7 +4405,6 @@ private:
uint32_t NextFreeIndex;
alignas(T) char Value[sizeof(T)];
};
-
struct ItemBlock
{
Item* pItems;
@@ -5517,14 +4414,15 @@ private:
const VkAllocationCallbacks* m_pAllocationCallbacks;
const uint32_t m_FirstBlockCapacity;
- VmaVector< ItemBlock, VmaStlAllocator<ItemBlock> > m_ItemBlocks;
+ VmaVector<ItemBlock, VmaStlAllocator<ItemBlock>> m_ItemBlocks;
ItemBlock& CreateNewBlock();
};
+#ifndef _VMA_POOL_ALLOCATOR_FUNCTIONS
template<typename T>
-VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity) :
- m_pAllocationCallbacks(pAllocationCallbacks),
+VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCallbacks, uint32_t firstBlockCapacity)
+ : m_pAllocationCallbacks(pAllocationCallbacks),
m_FirstBlockCapacity(firstBlockCapacity),
m_ItemBlocks(VmaStlAllocator<ItemBlock>(pAllocationCallbacks))
{
@@ -5534,19 +4432,19 @@ VmaPoolAllocator<T>::VmaPoolAllocator(const VkAllocationCallbacks* pAllocationCa
template<typename T>
VmaPoolAllocator<T>::~VmaPoolAllocator()
{
- for(size_t i = m_ItemBlocks.size(); i--; )
+ for (size_t i = m_ItemBlocks.size(); i--;)
vma_delete_array(m_pAllocationCallbacks, m_ItemBlocks[i].pItems, m_ItemBlocks[i].Capacity);
m_ItemBlocks.clear();
}
template<typename T>
-template<typename... Types> T* VmaPoolAllocator<T>::Alloc(Types... args)
+template<typename... Types> T* VmaPoolAllocator<T>::Alloc(Types&&... args)
{
- for(size_t i = m_ItemBlocks.size(); i--; )
+ for (size_t i = m_ItemBlocks.size(); i--; )
{
ItemBlock& block = m_ItemBlocks[i];
// This block has some free items: Use first one.
- if(block.FirstFreeIndex != UINT32_MAX)
+ if (block.FirstFreeIndex != UINT32_MAX)
{
Item* const pItem = &block.pItems[block.FirstFreeIndex];
block.FirstFreeIndex = pItem->NextFreeIndex;
@@ -5561,7 +4459,7 @@ template<typename... Types> T* VmaPoolAllocator<T>::Alloc(Types... args)
Item* const pItem = &newBlock.pItems[0];
newBlock.FirstFreeIndex = pItem->NextFreeIndex;
T* result = (T*)&pItem->Value;
- new(result)T(std::forward<Types>(args)...); // Explicit constructor call.
+ new(result) T(std::forward<Types>(args)...); // Explicit constructor call.
return result;
}
@@ -5569,7 +4467,7 @@ template<typename T>
void VmaPoolAllocator<T>::Free(T* ptr)
{
// Search all memory blocks to find ptr.
- for(size_t i = m_ItemBlocks.size(); i--; )
+ for (size_t i = m_ItemBlocks.size(); i--; )
{
ItemBlock& block = m_ItemBlocks[i];
@@ -5578,7 +4476,7 @@ void VmaPoolAllocator<T>::Free(T* ptr)
memcpy(&pItemPtr, &ptr, sizeof(pItemPtr));
// Check if pItemPtr is in address range of this block.
- if((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))
+ if ((pItemPtr >= block.pItems) && (pItemPtr < block.pItems + block.Capacity))
{
ptr->~T(); // Explicit destructor call.
const uint32_t index = static_cast<uint32_t>(pItemPtr - block.pItems);
@@ -5596,29 +4494,25 @@ typename VmaPoolAllocator<T>::ItemBlock& VmaPoolAllocator<T>::CreateNewBlock()
const uint32_t newBlockCapacity = m_ItemBlocks.empty() ?
m_FirstBlockCapacity : m_ItemBlocks.back().Capacity * 3 / 2;
- const ItemBlock newBlock = {
+ const ItemBlock newBlock =
+ {
vma_new_array(m_pAllocationCallbacks, Item, newBlockCapacity),
newBlockCapacity,
- 0 };
+ 0
+ };
m_ItemBlocks.push_back(newBlock);
// Setup singly-linked list of all free items in this block.
- for(uint32_t i = 0; i < newBlockCapacity - 1; ++i)
+ for (uint32_t i = 0; i < newBlockCapacity - 1; ++i)
newBlock.pItems[i].NextFreeIndex = i + 1;
newBlock.pItems[newBlockCapacity - 1].NextFreeIndex = UINT32_MAX;
return m_ItemBlocks.back();
}
+#endif // _VMA_POOL_ALLOCATOR_FUNCTIONS
+#endif // _VMA_POOL_ALLOCATOR
-////////////////////////////////////////////////////////////////////////////////
-// class VmaRawList, VmaList
-
-#if VMA_USE_STL_LIST
-
-#define VmaList std::list
-
-#else // #if VMA_USE_STL_LIST
-
+#ifndef _VMA_RAW_LIST
template<typename T>
struct VmaListItem
{
@@ -5636,32 +4530,33 @@ public:
typedef VmaListItem<T> ItemType;
VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks);
- ~VmaRawList();
- void Clear();
+ // Intentionally not calling Clear, because that would be unnecessary
+ // computations to return all items to m_ItemAllocator as free.
+ ~VmaRawList() = default;
size_t GetCount() const { return m_Count; }
bool IsEmpty() const { return m_Count == 0; }
ItemType* Front() { return m_pFront; }
- const ItemType* Front() const { return m_pFront; }
ItemType* Back() { return m_pBack; }
+ const ItemType* Front() const { return m_pFront; }
const ItemType* Back() const { return m_pBack; }
- ItemType* PushBack();
ItemType* PushFront();
- ItemType* PushBack(const T& value);
+ ItemType* PushBack();
ItemType* PushFront(const T& value);
- void PopBack();
+ ItemType* PushBack(const T& value);
void PopFront();
+ void PopBack();
// Item can be null - it means PushBack.
ItemType* InsertBefore(ItemType* pItem);
// Item can be null - it means PushFront.
ItemType* InsertAfter(ItemType* pItem);
-
ItemType* InsertBefore(ItemType* pItem, const T& value);
ItemType* InsertAfter(ItemType* pItem, const T& value);
+ void Clear();
void Remove(ItemType* pItem);
private:
@@ -5672,39 +4567,35 @@ private:
size_t m_Count;
};
+#ifndef _VMA_RAW_LIST_FUNCTIONS
template<typename T>
-VmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks) :
- m_pAllocationCallbacks(pAllocationCallbacks),
+VmaRawList<T>::VmaRawList(const VkAllocationCallbacks* pAllocationCallbacks)
+ : m_pAllocationCallbacks(pAllocationCallbacks),
m_ItemAllocator(pAllocationCallbacks, 128),
m_pFront(VMA_NULL),
m_pBack(VMA_NULL),
- m_Count(0)
-{
-}
-
-template<typename T>
-VmaRawList<T>::~VmaRawList()
-{
- // Intentionally not calling Clear, because that would be unnecessary
- // computations to return all items to m_ItemAllocator as free.
-}
+ m_Count(0) {}
template<typename T>
-void VmaRawList<T>::Clear()
+VmaListItem<T>* VmaRawList<T>::PushFront()
{
- if(IsEmpty() == false)
+ ItemType* const pNewItem = m_ItemAllocator.Alloc();
+ pNewItem->pPrev = VMA_NULL;
+ if (IsEmpty())
{
- ItemType* pItem = m_pBack;
- while(pItem != VMA_NULL)
- {
- ItemType* const pPrevItem = pItem->pPrev;
- m_ItemAllocator.Free(pItem);
- pItem = pPrevItem;
- }
- m_pFront = VMA_NULL;
- m_pBack = VMA_NULL;
- m_Count = 0;
+ pNewItem->pNext = VMA_NULL;
+ m_pFront = pNewItem;
+ m_pBack = pNewItem;
+ m_Count = 1;
+ }
+ else
+ {
+ pNewItem->pNext = m_pFront;
+ m_pFront->pPrev = pNewItem;
+ m_pFront = pNewItem;
+ ++m_Count;
}
+ return pNewItem;
}
template<typename T>
@@ -5730,24 +4621,10 @@ VmaListItem<T>* VmaRawList<T>::PushBack()
}
template<typename T>
-VmaListItem<T>* VmaRawList<T>::PushFront()
+VmaListItem<T>* VmaRawList<T>::PushFront(const T& value)
{
- ItemType* const pNewItem = m_ItemAllocator.Alloc();
- pNewItem->pPrev = VMA_NULL;
- if(IsEmpty())
- {
- pNewItem->pNext = VMA_NULL;
- m_pFront = pNewItem;
- m_pBack = pNewItem;
- m_Count = 1;
- }
- else
- {
- pNewItem->pNext = m_pFront;
- m_pFront->pPrev = pNewItem;
- m_pFront = pNewItem;
- ++m_Count;
- }
+ ItemType* const pNewItem = PushFront();
+ pNewItem->Value = value;
return pNewItem;
}
@@ -5760,11 +4637,18 @@ VmaListItem<T>* VmaRawList<T>::PushBack(const T& value)
}
template<typename T>
-VmaListItem<T>* VmaRawList<T>::PushFront(const T& value)
+void VmaRawList<T>::PopFront()
{
- ItemType* const pNewItem = PushFront();
- pNewItem->Value = value;
- return pNewItem;
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const pFrontItem = m_pFront;
+ ItemType* const pNextItem = pFrontItem->pNext;
+ if (pNextItem != VMA_NULL)
+ {
+ pNextItem->pPrev = VMA_NULL;
+ }
+ m_pFront = pNextItem;
+ m_ItemAllocator.Free(pFrontItem);
+ --m_Count;
}
template<typename T>
@@ -5783,18 +4667,21 @@ void VmaRawList<T>::PopBack()
}
template<typename T>
-void VmaRawList<T>::PopFront()
+void VmaRawList<T>::Clear()
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- ItemType* const pFrontItem = m_pFront;
- ItemType* const pNextItem = pFrontItem->pNext;
- if(pNextItem != VMA_NULL)
+ if (IsEmpty() == false)
{
- pNextItem->pPrev = VMA_NULL;
+ ItemType* pItem = m_pBack;
+ while (pItem != VMA_NULL)
+ {
+ ItemType* const pPrevItem = pItem->pPrev;
+ m_ItemAllocator.Free(pItem);
+ pItem = pPrevItem;
+ }
+ m_pFront = VMA_NULL;
+ m_pBack = VMA_NULL;
+ m_Count = 0;
}
- m_pFront = pNextItem;
- m_ItemAllocator.Free(pFrontItem);
- --m_Count;
}
template<typename T>
@@ -5894,173 +4781,129 @@ VmaListItem<T>* VmaRawList<T>::InsertAfter(ItemType* pItem, const T& value)
newItem->Value = value;
return newItem;
}
+#endif // _VMA_RAW_LIST_FUNCTIONS
+#endif // _VMA_RAW_LIST
+#ifndef _VMA_LIST
template<typename T, typename AllocatorT>
class VmaList
{
VMA_CLASS_NO_COPY(VmaList)
public:
+ class reverse_iterator;
+ class const_iterator;
+ class const_reverse_iterator;
+
class iterator
{
+ friend class const_iterator;
+ friend class VmaList<T, AllocatorT>;
public:
- iterator() :
- m_pList(VMA_NULL),
- m_pItem(VMA_NULL)
- {
- }
+ iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}
+ iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
- T& operator*() const
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- return m_pItem->Value;
- }
- T* operator->() const
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- return &m_pItem->Value;
- }
+ T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }
+ T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }
- iterator& operator++()
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- m_pItem = m_pItem->pNext;
- return *this;
- }
- iterator& operator--()
- {
- if(m_pItem != VMA_NULL)
- {
- m_pItem = m_pItem->pPrev;
- }
- else
- {
- VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
- m_pItem = m_pList->Back();
- }
- return *this;
- }
+ bool operator==(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }
+ bool operator!=(const iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }
- iterator operator++(int)
- {
- iterator result = *this;
- ++*this;
- return result;
- }
- iterator operator--(int)
- {
- iterator result = *this;
- --*this;
- return result;
- }
+ iterator operator++(int) { iterator result = *this; ++*this; return result; }
+ iterator operator--(int) { iterator result = *this; --*this; return result; }
- bool operator==(const iterator& rhs) const
- {
- VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
- return m_pItem == rhs.m_pItem;
- }
- bool operator!=(const iterator& rhs) const
- {
- VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
- return m_pItem != rhs.m_pItem;
- }
+ iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; }
+ iterator& operator--();
private:
VmaRawList<T>* m_pList;
VmaListItem<T>* m_pItem;
- iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) :
- m_pList(pList),
- m_pItem(pItem)
- {
- }
-
- friend class VmaList<T, AllocatorT>;
+ iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}
};
+ class reverse_iterator
+ {
+ friend class const_reverse_iterator;
+ friend class VmaList<T, AllocatorT>;
+ public:
+ reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}
+ reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
+
+ T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }
+ T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }
+
+ bool operator==(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }
+ bool operator!=(const reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }
+
+ reverse_iterator operator++(int) { reverse_iterator result = *this; ++* this; return result; }
+ reverse_iterator operator--(int) { reverse_iterator result = *this; --* this; return result; }
+
+ reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; }
+ reverse_iterator& operator--();
+
+ private:
+ VmaRawList<T>* m_pList;
+ VmaListItem<T>* m_pItem;
+ reverse_iterator(VmaRawList<T>* pList, VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}
+ };
class const_iterator
{
+ friend class VmaList<T, AllocatorT>;
public:
- const_iterator() :
- m_pList(VMA_NULL),
- m_pItem(VMA_NULL)
- {
- }
+ const_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}
+ const_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
+ const_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
- const_iterator(const iterator& src) :
- m_pList(src.m_pList),
- m_pItem(src.m_pItem)
- {
- }
+ iterator drop_const() { return { const_cast<VmaRawList<T>*>(m_pList), const_cast<VmaListItem<T>*>(m_pItem) }; }
- const T& operator*() const
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- return m_pItem->Value;
- }
- const T* operator->() const
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- return &m_pItem->Value;
- }
+ const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }
+ const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }
- const_iterator& operator++()
- {
- VMA_HEAVY_ASSERT(m_pItem != VMA_NULL);
- m_pItem = m_pItem->pNext;
- return *this;
- }
- const_iterator& operator--()
- {
- if(m_pItem != VMA_NULL)
- {
- m_pItem = m_pItem->pPrev;
- }
- else
- {
- VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
- m_pItem = m_pList->Back();
- }
- return *this;
- }
+ bool operator==(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }
+ bool operator!=(const const_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }
- const_iterator operator++(int)
- {
- const_iterator result = *this;
- ++*this;
- return result;
- }
- const_iterator operator--(int)
- {
- const_iterator result = *this;
- --*this;
- return result;
- }
+ const_iterator operator++(int) { const_iterator result = *this; ++* this; return result; }
+ const_iterator operator--(int) { const_iterator result = *this; --* this; return result; }
- bool operator==(const const_iterator& rhs) const
- {
- VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
- return m_pItem == rhs.m_pItem;
- }
- bool operator!=(const const_iterator& rhs) const
- {
- VMA_HEAVY_ASSERT(m_pList == rhs.m_pList);
- return m_pItem != rhs.m_pItem;
- }
+ const_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pNext; return *this; }
+ const_iterator& operator--();
private:
- const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) :
- m_pList(pList),
- m_pItem(pItem)
- {
- }
-
const VmaRawList<T>* m_pList;
const VmaListItem<T>* m_pItem;
+ const_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}
+ };
+ class const_reverse_iterator
+ {
friend class VmaList<T, AllocatorT>;
+ public:
+ const_reverse_iterator() : m_pList(VMA_NULL), m_pItem(VMA_NULL) {}
+ const_reverse_iterator(const reverse_iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
+ const_reverse_iterator(const iterator& src) : m_pList(src.m_pList), m_pItem(src.m_pItem) {}
+
+ reverse_iterator drop_const() { return { const_cast<VmaRawList<T>*>(m_pList), const_cast<VmaListItem<T>*>(m_pItem) }; }
+
+ const T& operator*() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return m_pItem->Value; }
+ const T* operator->() const { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); return &m_pItem->Value; }
+
+ bool operator==(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem == rhs.m_pItem; }
+ bool operator!=(const const_reverse_iterator& rhs) const { VMA_HEAVY_ASSERT(m_pList == rhs.m_pList); return m_pItem != rhs.m_pItem; }
+
+ const_reverse_iterator operator++(int) { const_reverse_iterator result = *this; ++* this; return result; }
+ const_reverse_iterator operator--(int) { const_reverse_iterator result = *this; --* this; return result; }
+
+ const_reverse_iterator& operator++() { VMA_HEAVY_ASSERT(m_pItem != VMA_NULL); m_pItem = m_pItem->pPrev; return *this; }
+ const_reverse_iterator& operator--();
+
+ private:
+ const VmaRawList<T>* m_pList;
+ const VmaListItem<T>* m_pItem;
+
+ const_reverse_iterator(const VmaRawList<T>* pList, const VmaListItem<T>* pItem) : m_pList(pList), m_pItem(pItem) {}
};
- VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) { }
+ VmaList(const AllocatorT& allocator) : m_RawList(allocator.m_pCallbacks) {}
bool empty() const { return m_RawList.IsEmpty(); }
size_t size() const { return m_RawList.GetCount(); }
@@ -6074,20 +4917,89 @@ public:
const_iterator begin() const { return cbegin(); }
const_iterator end() const { return cend(); }
- void clear() { m_RawList.Clear(); }
+ reverse_iterator rbegin() { return reverse_iterator(&m_RawList, m_RawList.Back()); }
+ reverse_iterator rend() { return reverse_iterator(&m_RawList, VMA_NULL); }
+
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(&m_RawList, m_RawList.Back()); }
+ const_reverse_iterator crend() const { return const_reverse_iterator(&m_RawList, VMA_NULL); }
+
+ const_reverse_iterator rbegin() const { return crbegin(); }
+ const_reverse_iterator rend() const { return crend(); }
+
void push_back(const T& value) { m_RawList.PushBack(value); }
- void erase(iterator it) { m_RawList.Remove(it.m_pItem); }
iterator insert(iterator it, const T& value) { return iterator(&m_RawList, m_RawList.InsertBefore(it.m_pItem, value)); }
+ void clear() { m_RawList.Clear(); }
+ void erase(iterator it) { m_RawList.Remove(it.m_pItem); }
+
private:
VmaRawList<T> m_RawList;
};
-#endif // #if VMA_USE_STL_LIST
+#ifndef _VMA_LIST_FUNCTIONS
+template<typename T, typename AllocatorT>
+typename VmaList<T, AllocatorT>::iterator& VmaList<T, AllocatorT>::iterator::operator--()
+{
+ if (m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+}
-////////////////////////////////////////////////////////////////////////////////
-// class VmaIntrusiveLinkedList
+template<typename T, typename AllocatorT>
+typename VmaList<T, AllocatorT>::reverse_iterator& VmaList<T, AllocatorT>::reverse_iterator::operator--()
+{
+ if (m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pNext;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Front();
+ }
+ return *this;
+}
+template<typename T, typename AllocatorT>
+typename VmaList<T, AllocatorT>::const_iterator& VmaList<T, AllocatorT>::const_iterator::operator--()
+{
+ if (m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pPrev;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+}
+
+template<typename T, typename AllocatorT>
+typename VmaList<T, AllocatorT>::const_reverse_iterator& VmaList<T, AllocatorT>::const_reverse_iterator::operator--()
+{
+ if (m_pItem != VMA_NULL)
+ {
+ m_pItem = m_pItem->pNext;
+ }
+ else
+ {
+ VMA_HEAVY_ASSERT(!m_pList->IsEmpty());
+ m_pItem = m_pList->Back();
+ }
+ return *this;
+}
+#endif // _VMA_LIST_FUNCTIONS
+#endif // _VMA_LIST
+
+#ifndef _VMA_INTRUSIVE_LINKED_LIST
/*
Expected interface of ItemTypeTraits:
struct MyItemTypeTraits
@@ -6106,226 +5018,264 @@ public:
typedef typename ItemTypeTraits::ItemType ItemType;
static ItemType* GetPrev(const ItemType* item) { return ItemTypeTraits::GetPrev(item); }
static ItemType* GetNext(const ItemType* item) { return ItemTypeTraits::GetNext(item); }
+
// Movable, not copyable.
- VmaIntrusiveLinkedList() { }
- VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList<ItemTypeTraits>& src) = delete;
- VmaIntrusiveLinkedList(VmaIntrusiveLinkedList<ItemTypeTraits>&& src) :
- m_Front(src.m_Front), m_Back(src.m_Back), m_Count(src.m_Count)
+ VmaIntrusiveLinkedList() = default;
+ VmaIntrusiveLinkedList(VmaIntrusiveLinkedList && src);
+ VmaIntrusiveLinkedList(const VmaIntrusiveLinkedList&) = delete;
+ VmaIntrusiveLinkedList& operator=(VmaIntrusiveLinkedList&& src);
+ VmaIntrusiveLinkedList& operator=(const VmaIntrusiveLinkedList&) = delete;
+ ~VmaIntrusiveLinkedList() { VMA_HEAVY_ASSERT(IsEmpty()); }
+
+ size_t GetCount() const { return m_Count; }
+ bool IsEmpty() const { return m_Count == 0; }
+ ItemType* Front() { return m_Front; }
+ ItemType* Back() { return m_Back; }
+ const ItemType* Front() const { return m_Front; }
+ const ItemType* Back() const { return m_Back; }
+
+ void PushBack(ItemType* item);
+ void PushFront(ItemType* item);
+ ItemType* PopBack();
+ ItemType* PopFront();
+
+ // MyItem can be null - it means PushBack.
+ void InsertBefore(ItemType* existingItem, ItemType* newItem);
+ // MyItem can be null - it means PushFront.
+ void InsertAfter(ItemType* existingItem, ItemType* newItem);
+ void Remove(ItemType* item);
+ void RemoveAll();
+
+private:
+ ItemType* m_Front = VMA_NULL;
+ ItemType* m_Back = VMA_NULL;
+ size_t m_Count = 0;
+};
+
+#ifndef _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS
+template<typename ItemTypeTraits>
+VmaIntrusiveLinkedList<ItemTypeTraits>::VmaIntrusiveLinkedList(VmaIntrusiveLinkedList&& src)
+ : m_Front(src.m_Front), m_Back(src.m_Back), m_Count(src.m_Count)
+{
+ src.m_Front = src.m_Back = VMA_NULL;
+ src.m_Count = 0;
+}
+
+template<typename ItemTypeTraits>
+VmaIntrusiveLinkedList<ItemTypeTraits>& VmaIntrusiveLinkedList<ItemTypeTraits>::operator=(VmaIntrusiveLinkedList&& src)
+{
+ if (&src != this)
{
+ VMA_HEAVY_ASSERT(IsEmpty());
+ m_Front = src.m_Front;
+ m_Back = src.m_Back;
+ m_Count = src.m_Count;
src.m_Front = src.m_Back = VMA_NULL;
src.m_Count = 0;
}
- ~VmaIntrusiveLinkedList()
+ return *this;
+}
+
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::PushBack(ItemType* item)
+{
+ VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);
+ if (IsEmpty())
{
- VMA_HEAVY_ASSERT(IsEmpty());
+ m_Front = item;
+ m_Back = item;
+ m_Count = 1;
}
- VmaIntrusiveLinkedList<ItemTypeTraits>& operator=(const VmaIntrusiveLinkedList<ItemTypeTraits>& src) = delete;
- VmaIntrusiveLinkedList<ItemTypeTraits>& operator=(VmaIntrusiveLinkedList<ItemTypeTraits>&& src)
+ else
{
- if(&src != this)
- {
- VMA_HEAVY_ASSERT(IsEmpty());
- m_Front = src.m_Front;
- m_Back = src.m_Back;
- m_Count = src.m_Count;
- src.m_Front = src.m_Back = VMA_NULL;
- src.m_Count = 0;
- }
- return *this;
+ ItemTypeTraits::AccessPrev(item) = m_Back;
+ ItemTypeTraits::AccessNext(m_Back) = item;
+ m_Back = item;
+ ++m_Count;
}
- void RemoveAll()
+}
+
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::PushFront(ItemType* item)
+{
+ VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);
+ if (IsEmpty())
{
- if(!IsEmpty())
- {
- ItemType* item = m_Back;
- while(item != VMA_NULL)
- {
- ItemType* const prevItem = ItemTypeTraits::AccessPrev(item);
- ItemTypeTraits::AccessPrev(item) = VMA_NULL;
- ItemTypeTraits::AccessNext(item) = VMA_NULL;
- item = prevItem;
- }
- m_Front = VMA_NULL;
- m_Back = VMA_NULL;
- m_Count = 0;
- }
+ m_Front = item;
+ m_Back = item;
+ m_Count = 1;
}
- size_t GetCount() const { return m_Count; }
- bool IsEmpty() const { return m_Count == 0; }
- ItemType* Front() { return m_Front; }
- const ItemType* Front() const { return m_Front; }
- ItemType* Back() { return m_Back; }
- const ItemType* Back() const { return m_Back; }
- void PushBack(ItemType* item)
+ else
{
- VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);
- if(IsEmpty())
+ ItemTypeTraits::AccessNext(item) = m_Front;
+ ItemTypeTraits::AccessPrev(m_Front) = item;
+ m_Front = item;
+ ++m_Count;
+ }
+}
+
+template<typename ItemTypeTraits>
+typename VmaIntrusiveLinkedList<ItemTypeTraits>::ItemType* VmaIntrusiveLinkedList<ItemTypeTraits>::PopBack()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const backItem = m_Back;
+ ItemType* const prevItem = ItemTypeTraits::GetPrev(backItem);
+ if (prevItem != VMA_NULL)
+ {
+ ItemTypeTraits::AccessNext(prevItem) = VMA_NULL;
+ }
+ m_Back = prevItem;
+ --m_Count;
+ ItemTypeTraits::AccessPrev(backItem) = VMA_NULL;
+ ItemTypeTraits::AccessNext(backItem) = VMA_NULL;
+ return backItem;
+}
+
+template<typename ItemTypeTraits>
+typename VmaIntrusiveLinkedList<ItemTypeTraits>::ItemType* VmaIntrusiveLinkedList<ItemTypeTraits>::PopFront()
+{
+ VMA_HEAVY_ASSERT(m_Count > 0);
+ ItemType* const frontItem = m_Front;
+ ItemType* const nextItem = ItemTypeTraits::GetNext(frontItem);
+ if (nextItem != VMA_NULL)
+ {
+ ItemTypeTraits::AccessPrev(nextItem) = VMA_NULL;
+ }
+ m_Front = nextItem;
+ --m_Count;
+ ItemTypeTraits::AccessPrev(frontItem) = VMA_NULL;
+ ItemTypeTraits::AccessNext(frontItem) = VMA_NULL;
+ return frontItem;
+}
+
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::InsertBefore(ItemType* existingItem, ItemType* newItem)
+{
+ VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);
+ if (existingItem != VMA_NULL)
+ {
+ ItemType* const prevItem = ItemTypeTraits::GetPrev(existingItem);
+ ItemTypeTraits::AccessPrev(newItem) = prevItem;
+ ItemTypeTraits::AccessNext(newItem) = existingItem;
+ ItemTypeTraits::AccessPrev(existingItem) = newItem;
+ if (prevItem != VMA_NULL)
{
- m_Front = item;
- m_Back = item;
- m_Count = 1;
+ ItemTypeTraits::AccessNext(prevItem) = newItem;
}
else
{
- ItemTypeTraits::AccessPrev(item) = m_Back;
- ItemTypeTraits::AccessNext(m_Back) = item;
- m_Back = item;
- ++m_Count;
+ VMA_HEAVY_ASSERT(m_Front == existingItem);
+ m_Front = newItem;
}
+ ++m_Count;
}
- void PushFront(ItemType* item)
+ else
+ PushBack(newItem);
+}
+
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::InsertAfter(ItemType* existingItem, ItemType* newItem)
+{
+ VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);
+ if (existingItem != VMA_NULL)
{
- VMA_HEAVY_ASSERT(ItemTypeTraits::GetPrev(item) == VMA_NULL && ItemTypeTraits::GetNext(item) == VMA_NULL);
- if(IsEmpty())
+ ItemType* const nextItem = ItemTypeTraits::GetNext(existingItem);
+ ItemTypeTraits::AccessNext(newItem) = nextItem;
+ ItemTypeTraits::AccessPrev(newItem) = existingItem;
+ ItemTypeTraits::AccessNext(existingItem) = newItem;
+ if (nextItem != VMA_NULL)
{
- m_Front = item;
- m_Back = item;
- m_Count = 1;
+ ItemTypeTraits::AccessPrev(nextItem) = newItem;
}
else
{
- ItemTypeTraits::AccessNext(item) = m_Front;
- ItemTypeTraits::AccessPrev(m_Front) = item;
- m_Front = item;
- ++m_Count;
+ VMA_HEAVY_ASSERT(m_Back == existingItem);
+ m_Back = newItem;
}
+ ++m_Count;
}
- ItemType* PopBack()
+ else
+ return PushFront(newItem);
+}
+
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::Remove(ItemType* item)
+{
+ VMA_HEAVY_ASSERT(item != VMA_NULL && m_Count > 0);
+ if (ItemTypeTraits::GetPrev(item) != VMA_NULL)
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- ItemType* const backItem = m_Back;
- ItemType* const prevItem = ItemTypeTraits::GetPrev(backItem);
- if(prevItem != VMA_NULL)
- {
- ItemTypeTraits::AccessNext(prevItem) = VMA_NULL;
- }
- m_Back = prevItem;
- --m_Count;
- ItemTypeTraits::AccessPrev(backItem) = VMA_NULL;
- ItemTypeTraits::AccessNext(backItem) = VMA_NULL;
- return backItem;
+ ItemTypeTraits::AccessNext(ItemTypeTraits::AccessPrev(item)) = ItemTypeTraits::GetNext(item);
}
- ItemType* PopFront()
+ else
{
- VMA_HEAVY_ASSERT(m_Count > 0);
- ItemType* const frontItem = m_Front;
- ItemType* const nextItem = ItemTypeTraits::GetNext(frontItem);
- if(nextItem != VMA_NULL)
- {
- ItemTypeTraits::AccessPrev(nextItem) = VMA_NULL;
- }
- m_Front = nextItem;
- --m_Count;
- ItemTypeTraits::AccessPrev(frontItem) = VMA_NULL;
- ItemTypeTraits::AccessNext(frontItem) = VMA_NULL;
- return frontItem;
+ VMA_HEAVY_ASSERT(m_Front == item);
+ m_Front = ItemTypeTraits::GetNext(item);
}
- // MyItem can be null - it means PushBack.
- void InsertBefore(ItemType* existingItem, ItemType* newItem)
+ if (ItemTypeTraits::GetNext(item) != VMA_NULL)
{
- VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);
- if(existingItem != VMA_NULL)
- {
- ItemType* const prevItem = ItemTypeTraits::GetPrev(existingItem);
- ItemTypeTraits::AccessPrev(newItem) = prevItem;
- ItemTypeTraits::AccessNext(newItem) = existingItem;
- ItemTypeTraits::AccessPrev(existingItem) = newItem;
- if(prevItem != VMA_NULL)
- {
- ItemTypeTraits::AccessNext(prevItem) = newItem;
- }
- else
- {
- VMA_HEAVY_ASSERT(m_Front == existingItem);
- m_Front = newItem;
- }
- ++m_Count;
- }
- else
- PushBack(newItem);
+ ItemTypeTraits::AccessPrev(ItemTypeTraits::AccessNext(item)) = ItemTypeTraits::GetPrev(item);
}
- // MyItem can be null - it means PushFront.
- void InsertAfter(ItemType* existingItem, ItemType* newItem)
+ else
{
- VMA_HEAVY_ASSERT(newItem != VMA_NULL && ItemTypeTraits::GetPrev(newItem) == VMA_NULL && ItemTypeTraits::GetNext(newItem) == VMA_NULL);
- if(existingItem != VMA_NULL)
- {
- ItemType* const nextItem = ItemTypeTraits::GetNext(existingItem);
- ItemTypeTraits::AccessNext(newItem) = nextItem;
- ItemTypeTraits::AccessPrev(newItem) = existingItem;
- ItemTypeTraits::AccessNext(existingItem) = newItem;
- if(nextItem != VMA_NULL)
- {
- ItemTypeTraits::AccessPrev(nextItem) = newItem;
- }
- else
- {
- VMA_HEAVY_ASSERT(m_Back == existingItem);
- m_Back = newItem;
- }
- ++m_Count;
- }
- else
- return PushFront(newItem);
+ VMA_HEAVY_ASSERT(m_Back == item);
+ m_Back = ItemTypeTraits::GetPrev(item);
}
- void Remove(ItemType* item)
- {
- VMA_HEAVY_ASSERT(item != VMA_NULL && m_Count > 0);
- if(ItemTypeTraits::GetPrev(item) != VMA_NULL)
- {
- ItemTypeTraits::AccessNext(ItemTypeTraits::AccessPrev(item)) = ItemTypeTraits::GetNext(item);
- }
- else
- {
- VMA_HEAVY_ASSERT(m_Front == item);
- m_Front = ItemTypeTraits::GetNext(item);
- }
+ ItemTypeTraits::AccessPrev(item) = VMA_NULL;
+ ItemTypeTraits::AccessNext(item) = VMA_NULL;
+ --m_Count;
+}
- if(ItemTypeTraits::GetNext(item) != VMA_NULL)
- {
- ItemTypeTraits::AccessPrev(ItemTypeTraits::AccessNext(item)) = ItemTypeTraits::GetPrev(item);
- }
- else
+template<typename ItemTypeTraits>
+void VmaIntrusiveLinkedList<ItemTypeTraits>::RemoveAll()
+{
+ if (!IsEmpty())
+ {
+ ItemType* item = m_Back;
+ while (item != VMA_NULL)
{
- VMA_HEAVY_ASSERT(m_Back == item);
- m_Back = ItemTypeTraits::GetPrev(item);
+ ItemType* const prevItem = ItemTypeTraits::AccessPrev(item);
+ ItemTypeTraits::AccessPrev(item) = VMA_NULL;
+ ItemTypeTraits::AccessNext(item) = VMA_NULL;
+ item = prevItem;
}
- ItemTypeTraits::AccessPrev(item) = VMA_NULL;
- ItemTypeTraits::AccessNext(item) = VMA_NULL;
- --m_Count;
+ m_Front = VMA_NULL;
+ m_Back = VMA_NULL;
+ m_Count = 0;
}
-private:
- ItemType* m_Front = VMA_NULL;
- ItemType* m_Back = VMA_NULL;
- size_t m_Count = 0;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// class VmaMap
+}
+#endif // _VMA_INTRUSIVE_LINKED_LIST_FUNCTIONS
+#endif // _VMA_INTRUSIVE_LINKED_LIST
// Unused in this version.
#if 0
-#if VMA_USE_STL_UNORDERED_MAP
-
-#define VmaPair std::pair
-
-#define VMA_MAP_TYPE(KeyT, ValueT) \
- std::unordered_map< KeyT, ValueT, std::hash<KeyT>, std::equal_to<KeyT>, VmaStlAllocator< std::pair<KeyT, ValueT> > >
-
-#else // #if VMA_USE_STL_UNORDERED_MAP
-
+#ifndef _VMA_PAIR
template<typename T1, typename T2>
struct VmaPair
{
T1 first;
T2 second;
- VmaPair() : first(), second() { }
- VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) { }
+ VmaPair() : first(), second() {}
+ VmaPair(const T1& firstSrc, const T2& secondSrc) : first(firstSrc), second(secondSrc) {}
+};
+
+template<typename FirstT, typename SecondT>
+struct VmaPairFirstLess
+{
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const
+ {
+ return lhs.first < rhs.first;
+ }
+ bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const
+ {
+ return lhs.first < rhsFirst;
+ }
};
+#endif // _VMA_PAIR
+#ifndef _VMA_MAP
/* Class compatible with subset of interface of std::unordered_map.
KeyT, ValueT must be POD because they will be stored in VmaVector.
*/
@@ -6336,34 +5286,21 @@ public:
typedef VmaPair<KeyT, ValueT> PairType;
typedef PairType* iterator;
- VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) { }
+ VmaMap(const VmaStlAllocator<PairType>& allocator) : m_Vector(allocator) {}
iterator begin() { return m_Vector.begin(); }
iterator end() { return m_Vector.end(); }
+ size_t size() { return m_Vector.size(); }
void insert(const PairType& pair);
iterator find(const KeyT& key);
void erase(iterator it);
private:
- VmaVector< PairType, VmaStlAllocator<PairType> > m_Vector;
-};
-
-#define VMA_MAP_TYPE(KeyT, ValueT) VmaMap<KeyT, ValueT>
-
-template<typename FirstT, typename SecondT>
-struct VmaPairFirstLess
-{
- bool operator()(const VmaPair<FirstT, SecondT>& lhs, const VmaPair<FirstT, SecondT>& rhs) const
- {
- return lhs.first < rhs.first;
- }
- bool operator()(const VmaPair<FirstT, SecondT>& lhs, const FirstT& rhsFirst) const
- {
- return lhs.first < rhsFirst;
- }
+ VmaVector< PairType, VmaStlAllocator<PairType>> m_Vector;
};
+#ifndef _VMA_MAP_FUNCTIONS
template<typename KeyT, typename ValueT>
void VmaMap<KeyT, ValueT>::insert(const PairType& pair)
{
@@ -6383,7 +5320,7 @@ VmaPair<KeyT, ValueT>* VmaMap<KeyT, ValueT>::find(const KeyT& key)
m_Vector.data() + m_Vector.size(),
key,
VmaPairFirstLess<KeyT, ValueT>());
- if((it != m_Vector.end()) && (it->first == key))
+ if ((it != m_Vector.end()) && (it->first == key))
{
return it;
}
@@ -6398,2215 +5335,37 @@ void VmaMap<KeyT, ValueT>::erase(iterator it)
{
VmaVectorRemove(m_Vector, it - m_Vector.begin());
}
-
-#endif // #if VMA_USE_STL_UNORDERED_MAP
+#endif // _VMA_MAP_FUNCTIONS
+#endif // _VMA_MAP
#endif // #if 0
-////////////////////////////////////////////////////////////////////////////////
-
-class VmaDeviceMemoryBlock;
-
-enum VMA_CACHE_OPERATION { VMA_CACHE_FLUSH, VMA_CACHE_INVALIDATE };
-
-struct VmaAllocation_T
-{
-private:
- static const uint8_t MAP_COUNT_FLAG_PERSISTENT_MAP = 0x80;
-
- enum FLAGS
- {
- FLAG_USER_DATA_STRING = 0x01,
- };
-
-public:
- enum ALLOCATION_TYPE
- {
- ALLOCATION_TYPE_NONE,
- ALLOCATION_TYPE_BLOCK,
- ALLOCATION_TYPE_DEDICATED,
- };
-
- /*
- This struct is allocated using VmaPoolAllocator.
- */
-
- VmaAllocation_T(uint32_t currentFrameIndex, bool userDataString) :
- m_Alignment{1},
- m_Size{0},
- m_pUserData{VMA_NULL},
- m_LastUseFrameIndex{currentFrameIndex},
- m_MemoryTypeIndex{0},
- m_Type{(uint8_t)ALLOCATION_TYPE_NONE},
- m_SuballocationType{(uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN},
- m_MapCount{0},
- m_Flags{userDataString ? (uint8_t)FLAG_USER_DATA_STRING : (uint8_t)0}
- {
-#if VMA_STATS_STRING_ENABLED
- m_CreationFrameIndex = currentFrameIndex;
- m_BufferImageUsage = 0;
-#endif
- }
-
- ~VmaAllocation_T()
- {
- VMA_ASSERT((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) == 0 && "Allocation was not unmapped before destruction.");
-
- // Check if owned string was freed.
- VMA_ASSERT(m_pUserData == VMA_NULL);
- }
-
- void InitBlockAllocation(
- VmaDeviceMemoryBlock* block,
- VkDeviceSize offset,
- VkDeviceSize alignment,
- VkDeviceSize size,
- uint32_t memoryTypeIndex,
- VmaSuballocationType suballocationType,
- bool mapped,
- bool canBecomeLost)
- {
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
- VMA_ASSERT(block != VMA_NULL);
- m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
- m_Alignment = alignment;
- m_Size = size;
- m_MemoryTypeIndex = memoryTypeIndex;
- m_MapCount = mapped ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
- m_SuballocationType = (uint8_t)suballocationType;
- m_BlockAllocation.m_Block = block;
- m_BlockAllocation.m_Offset = offset;
- m_BlockAllocation.m_CanBecomeLost = canBecomeLost;
- }
-
- void InitLost()
- {
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
- VMA_ASSERT(m_LastUseFrameIndex.load() == VMA_FRAME_INDEX_LOST);
- m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
- m_MemoryTypeIndex = 0;
- m_BlockAllocation.m_Block = VMA_NULL;
- m_BlockAllocation.m_Offset = 0;
- m_BlockAllocation.m_CanBecomeLost = true;
- }
-
- void ChangeBlockAllocation(
- VmaAllocator hAllocator,
- VmaDeviceMemoryBlock* block,
- VkDeviceSize offset);
-
- void ChangeOffset(VkDeviceSize newOffset);
-
- // pMappedData not null means allocation is created with MAPPED flag.
- void InitDedicatedAllocation(
- uint32_t memoryTypeIndex,
- VkDeviceMemory hMemory,
- VmaSuballocationType suballocationType,
- void* pMappedData,
- VkDeviceSize size)
- {
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
- VMA_ASSERT(hMemory != VK_NULL_HANDLE);
- m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;
- m_Alignment = 0;
- m_Size = size;
- m_MemoryTypeIndex = memoryTypeIndex;
- m_SuballocationType = (uint8_t)suballocationType;
- m_MapCount = (pMappedData != VMA_NULL) ? MAP_COUNT_FLAG_PERSISTENT_MAP : 0;
- m_DedicatedAllocation.m_hMemory = hMemory;
- m_DedicatedAllocation.m_pMappedData = pMappedData;
- m_DedicatedAllocation.m_Prev = VMA_NULL;
- m_DedicatedAllocation.m_Next = VMA_NULL;
- }
-
- ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
- VkDeviceSize GetAlignment() const { return m_Alignment; }
- VkDeviceSize GetSize() const { return m_Size; }
- bool IsUserDataString() const { return (m_Flags & FLAG_USER_DATA_STRING) != 0; }
- void* GetUserData() const { return m_pUserData; }
- void SetUserData(VmaAllocator hAllocator, void* pUserData);
- VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }
-
- VmaDeviceMemoryBlock* GetBlock() const
- {
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
- return m_BlockAllocation.m_Block;
- }
- VkDeviceSize GetOffset() const;
- VkDeviceMemory GetMemory() const;
- uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
- bool IsPersistentMap() const { return (m_MapCount & MAP_COUNT_FLAG_PERSISTENT_MAP) != 0; }
- void* GetMappedData() const;
- bool CanBecomeLost() const;
-
- uint32_t GetLastUseFrameIndex() const
- {
- return m_LastUseFrameIndex.load();
- }
- bool CompareExchangeLastUseFrameIndex(uint32_t& expected, uint32_t desired)
- {
- return m_LastUseFrameIndex.compare_exchange_weak(expected, desired);
- }
- /*
- - If hAllocation.LastUseFrameIndex + frameInUseCount < allocator.CurrentFrameIndex,
- makes it lost by setting LastUseFrameIndex = VMA_FRAME_INDEX_LOST and returns true.
- - Else, returns false.
-
- If hAllocation is already lost, assert - you should not call it then.
- If hAllocation was not created with CAN_BECOME_LOST_BIT, assert.
- */
- bool MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
-
- void DedicatedAllocCalcStatsInfo(VmaStatInfo& outInfo)
- {
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_DEDICATED);
- outInfo.blockCount = 1;
- outInfo.allocationCount = 1;
- outInfo.unusedRangeCount = 0;
- outInfo.usedBytes = m_Size;
- outInfo.unusedBytes = 0;
- outInfo.allocationSizeMin = outInfo.allocationSizeMax = m_Size;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMax = 0;
- }
-
- void BlockAllocMap();
- void BlockAllocUnmap();
- VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);
- void DedicatedAllocUnmap(VmaAllocator hAllocator);
-
-#if VMA_STATS_STRING_ENABLED
- uint32_t GetCreationFrameIndex() const { return m_CreationFrameIndex; }
- uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }
-
- void InitBufferImageUsage(uint32_t bufferImageUsage)
- {
- VMA_ASSERT(m_BufferImageUsage == 0);
- m_BufferImageUsage = bufferImageUsage;
- }
-
- void PrintParameters(class VmaJsonWriter& json) const;
-#endif
-
-private:
- VkDeviceSize m_Alignment;
- VkDeviceSize m_Size;
- void* m_pUserData;
- VMA_ATOMIC_UINT32 m_LastUseFrameIndex;
- uint32_t m_MemoryTypeIndex;
- uint8_t m_Type; // ALLOCATION_TYPE
- uint8_t m_SuballocationType; // VmaSuballocationType
- // Bit 0x80 is set when allocation was created with VMA_ALLOCATION_CREATE_MAPPED_BIT.
- // Bits with mask 0x7F are reference counter for vmaMapMemory()/vmaUnmapMemory().
- uint8_t m_MapCount;
- uint8_t m_Flags; // enum FLAGS
-
- // Allocation out of VmaDeviceMemoryBlock.
- struct BlockAllocation
- {
- VmaDeviceMemoryBlock* m_Block;
- VkDeviceSize m_Offset;
- bool m_CanBecomeLost;
- };
-
- // Allocation for an object that has its own private VkDeviceMemory.
- struct DedicatedAllocation
- {
- VkDeviceMemory m_hMemory;
- void* m_pMappedData; // Not null means memory is mapped.
- VmaAllocation_T* m_Prev;
- VmaAllocation_T* m_Next;
- };
-
- union
- {
- // Allocation out of VmaDeviceMemoryBlock.
- BlockAllocation m_BlockAllocation;
- // Allocation for an object that has its own private VkDeviceMemory.
- DedicatedAllocation m_DedicatedAllocation;
- };
-
-#if VMA_STATS_STRING_ENABLED
- uint32_t m_CreationFrameIndex;
- uint32_t m_BufferImageUsage; // 0 if unknown.
-#endif
-
- void FreeUserDataString(VmaAllocator hAllocator);
-
- friend struct VmaDedicatedAllocationListItemTraits;
-};
-
-struct VmaDedicatedAllocationListItemTraits
-{
- typedef VmaAllocation_T ItemType;
- static ItemType* GetPrev(const ItemType* item)
- {
- VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
- return item->m_DedicatedAllocation.m_Prev;
- }
- static ItemType* GetNext(const ItemType* item)
- {
- VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
- return item->m_DedicatedAllocation.m_Next;
- }
- static ItemType*& AccessPrev(ItemType* item)
- {
- VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
- return item->m_DedicatedAllocation.m_Prev;
- }
- static ItemType*& AccessNext(ItemType* item){
- VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
- return item->m_DedicatedAllocation.m_Next;
- }
-};
-
-/*
-Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as
-allocated memory block or free.
-*/
-struct VmaSuballocation
-{
- VkDeviceSize offset;
- VkDeviceSize size;
- VmaAllocation hAllocation;
- VmaSuballocationType type;
-};
-
-// Comparator for offsets.
-struct VmaSuballocationOffsetLess
-{
- bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
- {
- return lhs.offset < rhs.offset;
- }
-};
-struct VmaSuballocationOffsetGreater
-{
- bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
- {
- return lhs.offset > rhs.offset;
- }
-};
-
-typedef VmaList< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > VmaSuballocationList;
-
-// Cost of one additional allocation lost, as equivalent in bytes.
-static const VkDeviceSize VMA_LOST_ALLOCATION_COST = 1048576;
-
-enum class VmaAllocationRequestType
-{
- Normal,
- // Used by "Linear" algorithm.
- UpperAddress,
- EndOf1st,
- EndOf2nd,
-};
-
-/*
-Parameters of planned allocation inside a VmaDeviceMemoryBlock.
-
-If canMakeOtherLost was false:
-- item points to a FREE suballocation.
-- itemsToMakeLostCount is 0.
-
-If canMakeOtherLost was true:
-- item points to first of sequence of suballocations, which are either FREE,
- or point to VmaAllocations that can become lost.
-- itemsToMakeLostCount is the number of VmaAllocations that need to be made lost for
- the requested allocation to succeed.
-*/
-struct VmaAllocationRequest
-{
- VkDeviceSize offset;
- VkDeviceSize sumFreeSize; // Sum size of free items that overlap with proposed allocation.
- VkDeviceSize sumItemSize; // Sum size of items to make lost that overlap with proposed allocation.
- VmaSuballocationList::iterator item;
- size_t itemsToMakeLostCount;
- void* customData;
- VmaAllocationRequestType type;
-
- VkDeviceSize CalcCost() const
- {
- return sumItemSize + itemsToMakeLostCount * VMA_LOST_ALLOCATION_COST;
- }
-};
-
-/*
-Data structure used for bookkeeping of allocations and unused ranges of memory
-in a single VkDeviceMemory block.
-*/
-class VmaBlockMetadata
-{
-public:
- VmaBlockMetadata(VmaAllocator hAllocator);
- virtual ~VmaBlockMetadata() { }
- virtual void Init(VkDeviceSize size) { m_Size = size; }
-
- // Validates all data structures inside this object. If not valid, returns false.
- virtual bool Validate() const = 0;
- VkDeviceSize GetSize() const { return m_Size; }
- virtual size_t GetAllocationCount() const = 0;
- virtual VkDeviceSize GetSumFreeSize() const = 0;
- virtual VkDeviceSize GetUnusedRangeSizeMax() const = 0;
- // Returns true if this block is empty - contains only single free suballocation.
- virtual bool IsEmpty() const = 0;
-
- virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const = 0;
- // Shouldn't modify blockCount.
- virtual void AddPoolStats(VmaPoolStats& inoutStats) const = 0;
-
-#if VMA_STATS_STRING_ENABLED
- virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
-#endif
-
- // Tries to find a place for suballocation with given parameters inside this block.
- // If succeeded, fills pAllocationRequest and returns true.
- // If failed, returns false.
- virtual bool CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- bool upperAddress,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest) = 0;
-
- virtual bool MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest) = 0;
-
- virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount) = 0;
-
- virtual VkResult CheckCorruption(const void* pBlockData) = 0;
-
- // Makes actual allocation based on request. Request must already be checked and valid.
- virtual void Alloc(
- const VmaAllocationRequest& request,
- VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation) = 0;
-
- // Frees suballocation assigned to given memory region.
- virtual void Free(const VmaAllocation allocation) = 0;
- virtual void FreeAtOffset(VkDeviceSize offset) = 0;
-
-protected:
- const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
-
-#if VMA_STATS_STRING_ENABLED
- void PrintDetailedMap_Begin(class VmaJsonWriter& json,
- VkDeviceSize unusedBytes,
- size_t allocationCount,
- size_t unusedRangeCount) const;
- void PrintDetailedMap_Allocation(class VmaJsonWriter& json,
- VkDeviceSize offset,
- VmaAllocation hAllocation) const;
- void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
- VkDeviceSize offset,
- VkDeviceSize size) const;
- void PrintDetailedMap_End(class VmaJsonWriter& json) const;
-#endif
-
-private:
- VkDeviceSize m_Size;
- const VkAllocationCallbacks* m_pAllocationCallbacks;
-};
-
-#define VMA_VALIDATE(cond) do { if(!(cond)) { \
- VMA_ASSERT(0 && "Validation failed: " #cond); \
- return false; \
- } } while(false)
-
-class VmaBlockMetadata_Generic : public VmaBlockMetadata
-{
- VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
-public:
- VmaBlockMetadata_Generic(VmaAllocator hAllocator);
- virtual ~VmaBlockMetadata_Generic();
- virtual void Init(VkDeviceSize size);
-
- virtual bool Validate() const;
- virtual size_t GetAllocationCount() const { return m_Suballocations.size() - m_FreeCount; }
- virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
- virtual VkDeviceSize GetUnusedRangeSizeMax() const;
- virtual bool IsEmpty() const;
-
- virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
- virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
-
-#if VMA_STATS_STRING_ENABLED
- virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
-#endif
-
- virtual bool CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- bool upperAddress,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual bool MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
-
- virtual VkResult CheckCorruption(const void* pBlockData);
-
- virtual void Alloc(
- const VmaAllocationRequest& request,
- VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation);
-
- virtual void Free(const VmaAllocation allocation);
- virtual void FreeAtOffset(VkDeviceSize offset);
-
- ////////////////////////////////////////////////////////////////////////////////
- // For defragmentation
-
- bool IsBufferImageGranularityConflictPossible(
- VkDeviceSize bufferImageGranularity,
- VmaSuballocationType& inOutPrevSuballocType) const;
-
-private:
- friend class VmaDefragmentationAlgorithm_Generic;
- friend class VmaDefragmentationAlgorithm_Fast;
-
- uint32_t m_FreeCount;
- VkDeviceSize m_SumFreeSize;
- VmaSuballocationList m_Suballocations;
- // Suballocations that are free and have size greater than certain threshold.
- // Sorted by size, ascending.
- VmaVector< VmaSuballocationList::iterator, VmaStlAllocator< VmaSuballocationList::iterator > > m_FreeSuballocationsBySize;
-
- bool ValidateFreeSuballocationList() const;
-
- // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
- // If yes, fills pOffset and returns true. If no, returns false.
- bool CheckAllocation(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- VmaSuballocationType allocType,
- VmaSuballocationList::const_iterator suballocItem,
- bool canMakeOtherLost,
- VkDeviceSize* pOffset,
- size_t* itemsToMakeLostCount,
- VkDeviceSize* pSumFreeSize,
- VkDeviceSize* pSumItemSize) const;
- // Given free suballocation, it merges it with following one, which must also be free.
- void MergeFreeWithNext(VmaSuballocationList::iterator item);
- // Releases given suballocation, making it free.
- // Merges it with adjacent free suballocations if applicable.
- // Returns iterator to new free suballocation at this place.
- VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);
- // Given free suballocation, it inserts it into sorted list of
- // m_FreeSuballocationsBySize if it's suitable.
- void RegisterFreeSuballocation(VmaSuballocationList::iterator item);
- // Given free suballocation, it removes it from sorted list of
- // m_FreeSuballocationsBySize if it's suitable.
- void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);
-};
-
-/*
-Allocations and their references in internal data structure look like this:
-
-if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):
-
- 0 +-------+
- | |
- | |
- | |
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount]
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount + 1]
- +-------+
- | ... |
- +-------+
- | Alloc | 1st[1st.size() - 1]
- +-------+
- | |
- | |
- | |
-GetSize() +-------+
-
-if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):
-
- 0 +-------+
- | Alloc | 2nd[0]
- +-------+
- | Alloc | 2nd[1]
- +-------+
- | ... |
- +-------+
- | Alloc | 2nd[2nd.size() - 1]
- +-------+
- | |
- | |
- | |
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount]
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount + 1]
- +-------+
- | ... |
- +-------+
- | Alloc | 1st[1st.size() - 1]
- +-------+
- | |
-GetSize() +-------+
-
-if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):
-
- 0 +-------+
- | |
- | |
- | |
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount]
- +-------+
- | Alloc | 1st[m_1stNullItemsBeginCount + 1]
- +-------+
- | ... |
- +-------+
- | Alloc | 1st[1st.size() - 1]
- +-------+
- | |
- | |
- | |
- +-------+
- | Alloc | 2nd[2nd.size() - 1]
- +-------+
- | ... |
- +-------+
- | Alloc | 2nd[1]
- +-------+
- | Alloc | 2nd[0]
-GetSize() +-------+
-
-*/
-class VmaBlockMetadata_Linear : public VmaBlockMetadata
-{
- VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)
-public:
- VmaBlockMetadata_Linear(VmaAllocator hAllocator);
- virtual ~VmaBlockMetadata_Linear();
- virtual void Init(VkDeviceSize size);
-
- virtual bool Validate() const;
- virtual size_t GetAllocationCount() const;
- virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize; }
- virtual VkDeviceSize GetUnusedRangeSizeMax() const;
- virtual bool IsEmpty() const { return GetAllocationCount() == 0; }
-
- virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
- virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
-
-#if VMA_STATS_STRING_ENABLED
- virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
-#endif
-
- virtual bool CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- bool upperAddress,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual bool MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
-
- virtual VkResult CheckCorruption(const void* pBlockData);
-
- virtual void Alloc(
- const VmaAllocationRequest& request,
- VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation);
-
- virtual void Free(const VmaAllocation allocation);
- virtual void FreeAtOffset(VkDeviceSize offset);
-
-private:
- /*
- There are two suballocation vectors, used in ping-pong way.
- The one with index m_1stVectorIndex is called 1st.
- The one with index (m_1stVectorIndex ^ 1) is called 2nd.
- 2nd can be non-empty only when 1st is not empty.
- When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.
- */
- typedef VmaVector< VmaSuballocation, VmaStlAllocator<VmaSuballocation> > SuballocationVectorType;
-
- enum SECOND_VECTOR_MODE
- {
- SECOND_VECTOR_EMPTY,
- /*
- Suballocations in 2nd vector are created later than the ones in 1st, but they
- all have smaller offset.
- */
- SECOND_VECTOR_RING_BUFFER,
- /*
- Suballocations in 2nd vector are upper side of double stack.
- They all have offsets higher than those in 1st vector.
- Top of this stack means smaller offsets, but higher indices in this vector.
- */
- SECOND_VECTOR_DOUBLE_STACK,
- };
-
- VkDeviceSize m_SumFreeSize;
- SuballocationVectorType m_Suballocations0, m_Suballocations1;
- uint32_t m_1stVectorIndex;
- SECOND_VECTOR_MODE m_2ndVectorMode;
-
- SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
- SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
- const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
- const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
-
- // Number of items in 1st vector with hAllocation = null at the beginning.
- size_t m_1stNullItemsBeginCount;
- // Number of other items in 1st vector with hAllocation = null somewhere in the middle.
- size_t m_1stNullItemsMiddleCount;
- // Number of items in 2nd vector with hAllocation = null.
- size_t m_2ndNullItemsCount;
-
- bool ShouldCompact1st() const;
- void CleanupAfterFree();
-
- bool CreateAllocationRequest_LowerAddress(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest);
- bool CreateAllocationRequest_UpperAddress(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest);
-};
-
-/*
-- GetSize() is the original size of allocated memory block.
-- m_UsableSize is this size aligned down to a power of two.
- All allocations and calculations happen relative to m_UsableSize.
-- GetUnusableSize() is the difference between them.
- It is reported as separate, unused range, not available for allocations.
-
-Node at level 0 has size = m_UsableSize.
-Each next level contains nodes with size 2 times smaller than current level.
-m_LevelCount is the maximum number of levels to use in the current object.
-*/
-class VmaBlockMetadata_Buddy : public VmaBlockMetadata
-{
- VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
-public:
- VmaBlockMetadata_Buddy(VmaAllocator hAllocator);
- virtual ~VmaBlockMetadata_Buddy();
- virtual void Init(VkDeviceSize size);
-
- virtual bool Validate() const;
- virtual size_t GetAllocationCount() const { return m_AllocationCount; }
- virtual VkDeviceSize GetSumFreeSize() const { return m_SumFreeSize + GetUnusableSize(); }
- virtual VkDeviceSize GetUnusedRangeSizeMax() const;
- virtual bool IsEmpty() const { return m_Root->type == Node::TYPE_FREE; }
-
- virtual void CalcAllocationStatInfo(VmaStatInfo& outInfo) const;
- virtual void AddPoolStats(VmaPoolStats& inoutStats) const;
-
-#if VMA_STATS_STRING_ENABLED
- virtual void PrintDetailedMap(class VmaJsonWriter& json) const;
-#endif
-
- virtual bool CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- bool upperAddress,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual bool MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest);
-
- virtual uint32_t MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount);
-
- virtual VkResult CheckCorruption(const void* pBlockData) { return VK_ERROR_FEATURE_NOT_PRESENT; }
-
- virtual void Alloc(
- const VmaAllocationRequest& request,
- VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation);
-
- virtual void Free(const VmaAllocation allocation) { FreeAtOffset(allocation, allocation->GetOffset()); }
- virtual void FreeAtOffset(VkDeviceSize offset) { FreeAtOffset(VMA_NULL, offset); }
-
-private:
- static const VkDeviceSize MIN_NODE_SIZE = 32;
- static const size_t MAX_LEVELS = 30;
-
- struct ValidationContext
- {
- size_t calculatedAllocationCount;
- size_t calculatedFreeCount;
- VkDeviceSize calculatedSumFreeSize;
-
- ValidationContext() :
- calculatedAllocationCount(0),
- calculatedFreeCount(0),
- calculatedSumFreeSize(0) { }
- };
-
- struct Node
- {
- VkDeviceSize offset;
- enum TYPE
- {
- TYPE_FREE,
- TYPE_ALLOCATION,
- TYPE_SPLIT,
- TYPE_COUNT
- } type;
- Node* parent;
- Node* buddy;
-
- union
- {
- struct
- {
- Node* prev;
- Node* next;
- } free;
- struct
- {
- VmaAllocation alloc;
- } allocation;
- struct
- {
- Node* leftChild;
- } split;
- };
- };
-
- // Size of the memory block aligned down to a power of two.
- VkDeviceSize m_UsableSize;
- uint32_t m_LevelCount;
-
- Node* m_Root;
- struct {
- Node* front;
- Node* back;
- } m_FreeList[MAX_LEVELS];
- // Number of nodes in the tree with type == TYPE_ALLOCATION.
- size_t m_AllocationCount;
- // Number of nodes in the tree with type == TYPE_FREE.
- size_t m_FreeCount;
- // This includes space wasted due to internal fragmentation. Doesn't include unusable size.
- VkDeviceSize m_SumFreeSize;
-
- VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }
- void DeleteNode(Node* node);
- bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
- uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
- inline VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
- // Alloc passed just for validation. Can be null.
- void FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset);
- void CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const;
- // Adds node to the front of FreeList at given level.
- // node->type must be FREE.
- // node->free.prev, next can be undefined.
- void AddToFreeListFront(uint32_t level, Node* node);
- // Removes node from FreeList at given level.
- // node->type must be FREE.
- // node->free.prev, next stay untouched.
- void RemoveFromFreeList(uint32_t level, Node* node);
-
-#if VMA_STATS_STRING_ENABLED
- void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;
-#endif
-};
-
-struct VmaBlockVector;
-
-/*
-Represents a single block of device memory (`VkDeviceMemory`) with all the
-data about its regions (aka suballocations, #VmaAllocation), assigned and free.
-
-Thread-safety: This class must be externally synchronized.
-*/
-class VmaDeviceMemoryBlock
-{
- VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
-public:
- VmaBlockMetadata* m_pMetadata;
-
- VmaDeviceMemoryBlock(VmaAllocator hAllocator);
-
- ~VmaDeviceMemoryBlock()
- {
- VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped.");
- VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
- }
-
- // Always call after construction.
- void Init(
- VmaAllocator hAllocator,
- VmaBlockVector* parentBlockVector,
- VmaPool hParentPool,
- uint32_t newMemoryTypeIndex,
- VkDeviceMemory newMemory,
- VkDeviceSize newSize,
- uint32_t id,
- uint32_t algorithm);
- // Always call before destruction.
- void Destroy(VmaAllocator allocator);
-
- VmaBlockVector* GetParentBlockVector() const { return m_ParentBlockVector; }
- VmaPool GetParentPool() const { return m_hParentPool; }
- VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
- uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
- uint32_t GetId() const { return m_Id; }
- void* GetMappedData() const { return m_pMappedData; }
-
- // Validates all data structures inside this object. If not valid, returns false.
- bool Validate() const;
-
- VkResult CheckCorruption(VmaAllocator hAllocator);
-
- // ppData can be null.
- VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);
- void Unmap(VmaAllocator hAllocator, uint32_t count);
-
- VkResult WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
- VkResult ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
-
- VkResult BindBufferMemory(
- const VmaAllocator hAllocator,
- const VmaAllocation hAllocation,
- VkDeviceSize allocationLocalOffset,
- VkBuffer hBuffer,
- const void* pNext);
- VkResult BindImageMemory(
- const VmaAllocator hAllocator,
- const VmaAllocation hAllocation,
- VkDeviceSize allocationLocalOffset,
- VkImage hImage,
- const void* pNext);
-
-private:
- VmaBlockVector* m_ParentBlockVector = VMA_NULL;
- VmaPool m_hParentPool = VK_NULL_HANDLE; // VK_NULL_HANDLE if not belongs to custom pool.
- uint32_t m_MemoryTypeIndex = UINT32_MAX;
- uint32_t m_Id = 0;
- VkDeviceMemory m_hMemory = VK_NULL_HANDLE;
-
- /*
- Protects access to m_hMemory so it's not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
- Also protects m_MapCount, m_pMappedData.
- Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
- */
- VMA_MUTEX m_Mutex;
- uint32_t m_MapCount = 0;
- void* m_pMappedData = VMA_NULL;
-};
-
-struct VmaDefragmentationMove
-{
- size_t srcBlockIndex;
- size_t dstBlockIndex;
- VkDeviceSize srcOffset;
- VkDeviceSize dstOffset;
- VkDeviceSize size;
- VmaAllocation hAllocation;
- VmaDeviceMemoryBlock* pSrcBlock;
- VmaDeviceMemoryBlock* pDstBlock;
-};
-
-class VmaDefragmentationAlgorithm;
-
-/*
-Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific
-Vulkan memory type.
-
-Synchronized internally with a mutex.
-*/
-struct VmaBlockVector
-{
- VMA_CLASS_NO_COPY(VmaBlockVector)
-public:
- VmaBlockVector(
- VmaAllocator hAllocator,
- VmaPool hParentPool,
- uint32_t memoryTypeIndex,
- VkDeviceSize preferredBlockSize,
- size_t minBlockCount,
- size_t maxBlockCount,
- VkDeviceSize bufferImageGranularity,
- uint32_t frameInUseCount,
- bool explicitBlockSize,
- uint32_t algorithm,
- float priority,
- VkDeviceSize minAllocationAlignment,
- void* pMemoryAllocateNext);
- ~VmaBlockVector();
-
- VkResult CreateMinBlocks();
-
- VmaAllocator GetAllocator() const { return m_hAllocator; }
- VmaPool GetParentPool() const { return m_hParentPool; }
- bool IsCustomPool() const { return m_hParentPool != VMA_NULL; }
- uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
- VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
- VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
- uint32_t GetFrameInUseCount() const { return m_FrameInUseCount; }
- uint32_t GetAlgorithm() const { return m_Algorithm; }
-
- void GetPoolStats(VmaPoolStats* pStats);
-
- bool IsEmpty();
- bool IsCorruptionDetectionEnabled() const;
-
- VkResult Allocate(
- uint32_t currentFrameIndex,
- VkDeviceSize size,
- VkDeviceSize alignment,
- const VmaAllocationCreateInfo& createInfo,
- VmaSuballocationType suballocType,
- size_t allocationCount,
- VmaAllocation* pAllocations);
-
- void Free(const VmaAllocation hAllocation);
-
- // Adds statistics of this BlockVector to pStats.
- void AddStats(VmaStats* pStats);
-
-#if VMA_STATS_STRING_ENABLED
- void PrintDetailedMap(class VmaJsonWriter& json);
-#endif
-
- void MakePoolAllocationsLost(
- uint32_t currentFrameIndex,
- size_t* pLostAllocationCount);
- VkResult CheckCorruption();
-
- // Saves results in pCtx->res.
- void Defragment(
- class VmaBlockVectorDefragmentationContext* pCtx,
- VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags,
- VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
- VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
- VkCommandBuffer commandBuffer);
- void DefragmentationEnd(
- class VmaBlockVectorDefragmentationContext* pCtx,
- uint32_t flags,
- VmaDefragmentationStats* pStats);
-
- uint32_t ProcessDefragmentations(
- class VmaBlockVectorDefragmentationContext *pCtx,
- VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves);
-
- void CommitDefragmentations(
- class VmaBlockVectorDefragmentationContext *pCtx,
- VmaDefragmentationStats* pStats);
-
- ////////////////////////////////////////////////////////////////////////////////
- // To be used only while the m_Mutex is locked. Used during defragmentation.
-
- size_t GetBlockCount() const { return m_Blocks.size(); }
- VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }
- size_t CalcAllocationCount() const;
- bool IsBufferImageGranularityConflictPossible() const;
-
-private:
- friend class VmaDefragmentationAlgorithm_Generic;
-
- const VmaAllocator m_hAllocator;
- const VmaPool m_hParentPool;
- const uint32_t m_MemoryTypeIndex;
- const VkDeviceSize m_PreferredBlockSize;
- const size_t m_MinBlockCount;
- const size_t m_MaxBlockCount;
- const VkDeviceSize m_BufferImageGranularity;
- const uint32_t m_FrameInUseCount;
- const bool m_ExplicitBlockSize;
- const uint32_t m_Algorithm;
- const float m_Priority;
- const VkDeviceSize m_MinAllocationAlignment;
- void* const m_pMemoryAllocateNext;
- VMA_RW_MUTEX m_Mutex;
-
- /* There can be at most one allocation that is completely empty (except when minBlockCount > 0) -
- a hysteresis to avoid pessimistic case of alternating creation and destruction of a VkDeviceMemory. */
- bool m_HasEmptyBlock;
- // Incrementally sorted by sumFreeSize, ascending.
- VmaVector< VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*> > m_Blocks;
- uint32_t m_NextBlockId;
-
- VkDeviceSize CalcMaxBlockSize() const;
-
- // Finds and removes given block from vector.
- void Remove(VmaDeviceMemoryBlock* pBlock);
-
- // Performs single step in sorting m_Blocks. They may not be fully sorted
- // after this call.
- void IncrementallySortBlocks();
-
- VkResult AllocatePage(
- uint32_t currentFrameIndex,
- VkDeviceSize size,
- VkDeviceSize alignment,
- const VmaAllocationCreateInfo& createInfo,
- VmaSuballocationType suballocType,
- VmaAllocation* pAllocation);
-
- // To be used only without CAN_MAKE_OTHER_LOST flag.
- VkResult AllocateFromBlock(
- VmaDeviceMemoryBlock* pBlock,
- uint32_t currentFrameIndex,
- VkDeviceSize size,
- VkDeviceSize alignment,
- VmaAllocationCreateFlags allocFlags,
- void* pUserData,
- VmaSuballocationType suballocType,
- uint32_t strategy,
- VmaAllocation* pAllocation);
-
- VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);
-
- // Saves result to pCtx->res.
- void ApplyDefragmentationMovesCpu(
- class VmaBlockVectorDefragmentationContext* pDefragCtx,
- const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves);
- // Saves result to pCtx->res.
- void ApplyDefragmentationMovesGpu(
- class VmaBlockVectorDefragmentationContext* pDefragCtx,
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkCommandBuffer commandBuffer);
-
- /*
- Used during defragmentation. pDefragmentationStats is optional. It's in/out
- - updated with new data.
- */
- void FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats);
-
- void UpdateHasEmptyBlock();
-};
-
-struct VmaPool_T
-{
- VMA_CLASS_NO_COPY(VmaPool_T)
-public:
- VmaBlockVector m_BlockVector;
-
- VmaPool_T(
- VmaAllocator hAllocator,
- const VmaPoolCreateInfo& createInfo,
- VkDeviceSize preferredBlockSize);
- ~VmaPool_T();
-
- uint32_t GetId() const { return m_Id; }
- void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
-
- const char* GetName() const { return m_Name; }
- void SetName(const char* pName);
-
-#if VMA_STATS_STRING_ENABLED
- //void PrintDetailedMap(class VmaStringBuilder& sb);
-#endif
-
-private:
- uint32_t m_Id;
- char* m_Name;
- VmaPool_T* m_PrevPool = VMA_NULL;
- VmaPool_T* m_NextPool = VMA_NULL;
- friend struct VmaPoolListItemTraits;
-};
-
-struct VmaPoolListItemTraits
-{
- typedef VmaPool_T ItemType;
- static ItemType* GetPrev(const ItemType* item) { return item->m_PrevPool; }
- static ItemType* GetNext(const ItemType* item) { return item->m_NextPool; }
- static ItemType*& AccessPrev(ItemType* item) { return item->m_PrevPool; }
- static ItemType*& AccessNext(ItemType* item) { return item->m_NextPool; }
-};
-
-/*
-Performs defragmentation:
-
-- Updates `pBlockVector->m_pMetadata`.
-- Updates allocations by calling ChangeBlockAllocation() or ChangeOffset().
-- Does not move actual data, only returns requested moves as `moves`.
-*/
-class VmaDefragmentationAlgorithm
-{
- VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm)
-public:
- VmaDefragmentationAlgorithm(
- VmaAllocator hAllocator,
- VmaBlockVector* pBlockVector,
- uint32_t currentFrameIndex) :
- m_hAllocator(hAllocator),
- m_pBlockVector(pBlockVector),
- m_CurrentFrameIndex(currentFrameIndex)
- {
- }
- virtual ~VmaDefragmentationAlgorithm()
- {
- }
-
- virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) = 0;
- virtual void AddAll() = 0;
-
- virtual VkResult Defragment(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- VmaDefragmentationFlags flags) = 0;
-
- virtual VkDeviceSize GetBytesMoved() const = 0;
- virtual uint32_t GetAllocationsMoved() const = 0;
-
-protected:
- VmaAllocator const m_hAllocator;
- VmaBlockVector* const m_pBlockVector;
- const uint32_t m_CurrentFrameIndex;
-
- struct AllocationInfo
- {
- VmaAllocation m_hAllocation;
- VkBool32* m_pChanged;
-
- AllocationInfo() :
- m_hAllocation(VK_NULL_HANDLE),
- m_pChanged(VMA_NULL)
- {
- }
- AllocationInfo(VmaAllocation hAlloc, VkBool32* pChanged) :
- m_hAllocation(hAlloc),
- m_pChanged(pChanged)
- {
- }
- };
-};
-
-class VmaDefragmentationAlgorithm_Generic : public VmaDefragmentationAlgorithm
-{
- VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Generic)
-public:
- VmaDefragmentationAlgorithm_Generic(
- VmaAllocator hAllocator,
- VmaBlockVector* pBlockVector,
- uint32_t currentFrameIndex,
- bool overlappingMoveSupported);
- virtual ~VmaDefragmentationAlgorithm_Generic();
-
- virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
- virtual void AddAll() { m_AllAllocations = true; }
-
- virtual VkResult Defragment(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- VmaDefragmentationFlags flags);
-
- virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
- virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
-
-private:
- uint32_t m_AllocationCount;
- bool m_AllAllocations;
-
- VkDeviceSize m_BytesMoved;
- uint32_t m_AllocationsMoved;
-
- struct AllocationInfoSizeGreater
- {
- bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
- {
- return lhs.m_hAllocation->GetSize() > rhs.m_hAllocation->GetSize();
- }
- };
-
- struct AllocationInfoOffsetGreater
- {
- bool operator()(const AllocationInfo& lhs, const AllocationInfo& rhs) const
- {
- return lhs.m_hAllocation->GetOffset() > rhs.m_hAllocation->GetOffset();
- }
- };
-
- struct BlockInfo
- {
- size_t m_OriginalBlockIndex;
- VmaDeviceMemoryBlock* m_pBlock;
- bool m_HasNonMovableAllocations;
- VmaVector< AllocationInfo, VmaStlAllocator<AllocationInfo> > m_Allocations;
-
- BlockInfo(const VkAllocationCallbacks* pAllocationCallbacks) :
- m_OriginalBlockIndex(SIZE_MAX),
- m_pBlock(VMA_NULL),
- m_HasNonMovableAllocations(true),
- m_Allocations(pAllocationCallbacks)
- {
- }
-
- void CalcHasNonMovableAllocations()
- {
- const size_t blockAllocCount = m_pBlock->m_pMetadata->GetAllocationCount();
- const size_t defragmentAllocCount = m_Allocations.size();
- m_HasNonMovableAllocations = blockAllocCount != defragmentAllocCount;
- }
-
- void SortAllocationsBySizeDescending()
- {
- VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoSizeGreater());
- }
-
- void SortAllocationsByOffsetDescending()
- {
- VMA_SORT(m_Allocations.begin(), m_Allocations.end(), AllocationInfoOffsetGreater());
- }
- };
-
- struct BlockPointerLess
- {
- bool operator()(const BlockInfo* pLhsBlockInfo, const VmaDeviceMemoryBlock* pRhsBlock) const
- {
- return pLhsBlockInfo->m_pBlock < pRhsBlock;
- }
- bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
- {
- return pLhsBlockInfo->m_pBlock < pRhsBlockInfo->m_pBlock;
- }
- };
-
- // 1. Blocks with some non-movable allocations go first.
- // 2. Blocks with smaller sumFreeSize go first.
- struct BlockInfoCompareMoveDestination
- {
- bool operator()(const BlockInfo* pLhsBlockInfo, const BlockInfo* pRhsBlockInfo) const
- {
- if(pLhsBlockInfo->m_HasNonMovableAllocations && !pRhsBlockInfo->m_HasNonMovableAllocations)
- {
- return true;
- }
- if(!pLhsBlockInfo->m_HasNonMovableAllocations && pRhsBlockInfo->m_HasNonMovableAllocations)
- {
- return false;
- }
- if(pLhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize() < pRhsBlockInfo->m_pBlock->m_pMetadata->GetSumFreeSize())
- {
- return true;
- }
- return false;
- }
- };
-
- typedef VmaVector< BlockInfo*, VmaStlAllocator<BlockInfo*> > BlockInfoVector;
- BlockInfoVector m_Blocks;
-
- VkResult DefragmentRound(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- bool freeOldAllocations);
-
- size_t CalcBlocksWithNonMovableCount() const;
-
- static bool MoveMakesSense(
- size_t dstBlockIndex, VkDeviceSize dstOffset,
- size_t srcBlockIndex, VkDeviceSize srcOffset);
-};
-
-class VmaDefragmentationAlgorithm_Fast : public VmaDefragmentationAlgorithm
-{
- VMA_CLASS_NO_COPY(VmaDefragmentationAlgorithm_Fast)
-public:
- VmaDefragmentationAlgorithm_Fast(
- VmaAllocator hAllocator,
- VmaBlockVector* pBlockVector,
- uint32_t currentFrameIndex,
- bool overlappingMoveSupported);
- virtual ~VmaDefragmentationAlgorithm_Fast();
-
- virtual void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged) { ++m_AllocationCount; }
- virtual void AddAll() { m_AllAllocations = true; }
-
- virtual VkResult Defragment(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- VmaDefragmentationFlags flags);
-
- virtual VkDeviceSize GetBytesMoved() const { return m_BytesMoved; }
- virtual uint32_t GetAllocationsMoved() const { return m_AllocationsMoved; }
-
-private:
- struct BlockInfo
- {
- size_t origBlockIndex;
- };
-
- class FreeSpaceDatabase
- {
- public:
- FreeSpaceDatabase()
- {
- FreeSpace s = {};
- s.blockInfoIndex = SIZE_MAX;
- for(size_t i = 0; i < MAX_COUNT; ++i)
- {
- m_FreeSpaces[i] = s;
- }
- }
-
- void Register(size_t blockInfoIndex, VkDeviceSize offset, VkDeviceSize size)
- {
- if(size < VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
- {
- return;
- }
-
- // Find first invalid or the smallest structure.
- size_t bestIndex = SIZE_MAX;
- for(size_t i = 0; i < MAX_COUNT; ++i)
- {
- // Empty structure.
- if(m_FreeSpaces[i].blockInfoIndex == SIZE_MAX)
- {
- bestIndex = i;
- break;
- }
- if(m_FreeSpaces[i].size < size &&
- (bestIndex == SIZE_MAX || m_FreeSpaces[bestIndex].size > m_FreeSpaces[i].size))
- {
- bestIndex = i;
- }
- }
-
- if(bestIndex != SIZE_MAX)
- {
- m_FreeSpaces[bestIndex].blockInfoIndex = blockInfoIndex;
- m_FreeSpaces[bestIndex].offset = offset;
- m_FreeSpaces[bestIndex].size = size;
- }
- }
-
- bool Fetch(VkDeviceSize alignment, VkDeviceSize size,
- size_t& outBlockInfoIndex, VkDeviceSize& outDstOffset)
- {
- size_t bestIndex = SIZE_MAX;
- VkDeviceSize bestFreeSpaceAfter = 0;
- for(size_t i = 0; i < MAX_COUNT; ++i)
- {
- // Structure is valid.
- if(m_FreeSpaces[i].blockInfoIndex != SIZE_MAX)
- {
- const VkDeviceSize dstOffset = VmaAlignUp(m_FreeSpaces[i].offset, alignment);
- // Allocation fits into this structure.
- if(dstOffset + size <= m_FreeSpaces[i].offset + m_FreeSpaces[i].size)
- {
- const VkDeviceSize freeSpaceAfter = (m_FreeSpaces[i].offset + m_FreeSpaces[i].size) -
- (dstOffset + size);
- if(bestIndex == SIZE_MAX || freeSpaceAfter > bestFreeSpaceAfter)
- {
- bestIndex = i;
- bestFreeSpaceAfter = freeSpaceAfter;
- }
- }
- }
- }
-
- if(bestIndex != SIZE_MAX)
- {
- outBlockInfoIndex = m_FreeSpaces[bestIndex].blockInfoIndex;
- outDstOffset = VmaAlignUp(m_FreeSpaces[bestIndex].offset, alignment);
-
- if(bestFreeSpaceAfter >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
- {
- // Leave this structure for remaining empty space.
- const VkDeviceSize alignmentPlusSize = (outDstOffset - m_FreeSpaces[bestIndex].offset) + size;
- m_FreeSpaces[bestIndex].offset += alignmentPlusSize;
- m_FreeSpaces[bestIndex].size -= alignmentPlusSize;
- }
- else
- {
- // This structure becomes invalid.
- m_FreeSpaces[bestIndex].blockInfoIndex = SIZE_MAX;
- }
-
- return true;
- }
-
- return false;
- }
-
- private:
- static const size_t MAX_COUNT = 4;
-
- struct FreeSpace
- {
- size_t blockInfoIndex; // SIZE_MAX means this structure is invalid.
- VkDeviceSize offset;
- VkDeviceSize size;
- } m_FreeSpaces[MAX_COUNT];
- };
-
- const bool m_OverlappingMoveSupported;
-
- uint32_t m_AllocationCount;
- bool m_AllAllocations;
-
- VkDeviceSize m_BytesMoved;
- uint32_t m_AllocationsMoved;
-
- VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> > m_BlockInfos;
-
- void PreprocessMetadata();
- void PostprocessMetadata();
- void InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc);
-};
-
-struct VmaBlockDefragmentationContext
-{
- enum BLOCK_FLAG
- {
- BLOCK_FLAG_USED = 0x00000001,
- };
- uint32_t flags;
- VkBuffer hBuffer;
-};
-
-class VmaBlockVectorDefragmentationContext
-{
- VMA_CLASS_NO_COPY(VmaBlockVectorDefragmentationContext)
-public:
- VkResult res;
- bool mutexLocked;
- VmaVector< VmaBlockDefragmentationContext, VmaStlAllocator<VmaBlockDefragmentationContext> > blockContexts;
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> > defragmentationMoves;
- uint32_t defragmentationMovesProcessed;
- uint32_t defragmentationMovesCommitted;
- bool hasDefragmentationPlan;
-
- VmaBlockVectorDefragmentationContext(
- VmaAllocator hAllocator,
- VmaPool hCustomPool, // Optional.
- VmaBlockVector* pBlockVector,
- uint32_t currFrameIndex);
- ~VmaBlockVectorDefragmentationContext();
-
- VmaPool GetCustomPool() const { return m_hCustomPool; }
- VmaBlockVector* GetBlockVector() const { return m_pBlockVector; }
- VmaDefragmentationAlgorithm* GetAlgorithm() const { return m_pAlgorithm; }
-
- void AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged);
- void AddAll() { m_AllAllocations = true; }
-
- void Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags);
-
-private:
- const VmaAllocator m_hAllocator;
- // Null if not from custom pool.
- const VmaPool m_hCustomPool;
- // Redundant, for convenience not to fetch from m_hCustomPool->m_BlockVector or m_hAllocator->m_pBlockVectors.
- VmaBlockVector* const m_pBlockVector;
- const uint32_t m_CurrFrameIndex;
- // Owner of this object.
- VmaDefragmentationAlgorithm* m_pAlgorithm;
-
- struct AllocInfo
- {
- VmaAllocation hAlloc;
- VkBool32* pChanged;
- };
- // Used between constructor and Begin.
- VmaVector< AllocInfo, VmaStlAllocator<AllocInfo> > m_Allocations;
- bool m_AllAllocations;
-};
-
-struct VmaDefragmentationContext_T
-{
-private:
- VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)
-public:
- VmaDefragmentationContext_T(
- VmaAllocator hAllocator,
- uint32_t currFrameIndex,
- uint32_t flags,
- VmaDefragmentationStats* pStats);
- ~VmaDefragmentationContext_T();
-
- void AddPools(uint32_t poolCount, const VmaPool* pPools);
- void AddAllocations(
- uint32_t allocationCount,
- const VmaAllocation* pAllocations,
- VkBool32* pAllocationsChanged);
-
- /*
- Returns:
- - `VK_SUCCESS` if succeeded and object can be destroyed immediately.
- - `VK_NOT_READY` if succeeded but the object must remain alive until vmaDefragmentationEnd().
- - Negative value if error occurred and object can be destroyed immediately.
- */
- VkResult Defragment(
- VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
- VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
- VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags);
-
- VkResult DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo);
- VkResult DefragmentPassEnd();
-
-private:
- const VmaAllocator m_hAllocator;
- const uint32_t m_CurrFrameIndex;
- const uint32_t m_Flags;
- VmaDefragmentationStats* const m_pStats;
-
- VkDeviceSize m_MaxCpuBytesToMove;
- uint32_t m_MaxCpuAllocationsToMove;
- VkDeviceSize m_MaxGpuBytesToMove;
- uint32_t m_MaxGpuAllocationsToMove;
-
- // Owner of these objects.
- VmaBlockVectorDefragmentationContext* m_DefaultPoolContexts[VK_MAX_MEMORY_TYPES];
- // Owner of these objects.
- VmaVector< VmaBlockVectorDefragmentationContext*, VmaStlAllocator<VmaBlockVectorDefragmentationContext*> > m_CustomPoolContexts;
-};
-
-#if VMA_RECORDING_ENABLED
-
-class VmaRecorder
-{
-public:
- VmaRecorder();
- VkResult Init(const VmaRecordSettings& settings, bool useMutex);
- void WriteConfiguration(
- const VkPhysicalDeviceProperties& devProps,
- const VkPhysicalDeviceMemoryProperties& memProps,
- uint32_t vulkanApiVersion,
- bool dedicatedAllocationExtensionEnabled,
- bool bindMemory2ExtensionEnabled,
- bool memoryBudgetExtensionEnabled,
- bool deviceCoherentMemoryExtensionEnabled);
- ~VmaRecorder();
-
- void RecordCreateAllocator(uint32_t frameIndex);
- void RecordDestroyAllocator(uint32_t frameIndex);
- void RecordCreatePool(uint32_t frameIndex,
- const VmaPoolCreateInfo& createInfo,
- VmaPool pool);
- void RecordDestroyPool(uint32_t frameIndex, VmaPool pool);
- void RecordAllocateMemory(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation);
- void RecordAllocateMemoryPages(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- const VmaAllocationCreateInfo& createInfo,
- uint64_t allocationCount,
- const VmaAllocation* pAllocations);
- void RecordAllocateMemoryForBuffer(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation);
- void RecordAllocateMemoryForImage(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation);
- void RecordFreeMemory(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordFreeMemoryPages(uint32_t frameIndex,
- uint64_t allocationCount,
- const VmaAllocation* pAllocations);
- void RecordSetAllocationUserData(uint32_t frameIndex,
- VmaAllocation allocation,
- const void* pUserData);
- void RecordCreateLostAllocation(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordMapMemory(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordUnmapMemory(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordFlushAllocation(uint32_t frameIndex,
- VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
- void RecordInvalidateAllocation(uint32_t frameIndex,
- VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size);
- void RecordCreateBuffer(uint32_t frameIndex,
- const VkBufferCreateInfo& bufCreateInfo,
- const VmaAllocationCreateInfo& allocCreateInfo,
- VmaAllocation allocation);
- void RecordCreateImage(uint32_t frameIndex,
- const VkImageCreateInfo& imageCreateInfo,
- const VmaAllocationCreateInfo& allocCreateInfo,
- VmaAllocation allocation);
- void RecordDestroyBuffer(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordDestroyImage(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordTouchAllocation(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordGetAllocationInfo(uint32_t frameIndex,
- VmaAllocation allocation);
- void RecordMakePoolAllocationsLost(uint32_t frameIndex,
- VmaPool pool);
- void RecordDefragmentationBegin(uint32_t frameIndex,
- const VmaDefragmentationInfo2& info,
- VmaDefragmentationContext ctx);
- void RecordDefragmentationEnd(uint32_t frameIndex,
- VmaDefragmentationContext ctx);
- void RecordSetPoolName(uint32_t frameIndex,
- VmaPool pool,
- const char* name);
-
-private:
- struct CallParams
- {
- uint32_t threadId;
- double time;
- };
-
- class UserDataString
- {
- public:
- UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData);
- const char* GetString() const { return m_Str; }
-
- private:
- char m_PtrStr[17];
- const char* m_Str;
- };
-
- bool m_UseMutex;
- VmaRecordFlags m_Flags;
- FILE* m_File;
- VMA_MUTEX m_FileMutex;
- std::chrono::time_point<std::chrono::high_resolution_clock> m_RecordingStartTime;
-
- void GetBasicParams(CallParams& outParams);
-
- // T must be a pointer type, e.g. VmaAllocation, VmaPool.
- template<typename T>
- void PrintPointerList(uint64_t count, const T* pItems)
- {
- if(count)
- {
- fprintf(m_File, "%p", pItems[0]);
- for(uint64_t i = 1; i < count; ++i)
- {
- fprintf(m_File, " %p", pItems[i]);
- }
- }
- }
-
- void PrintPointerList(uint64_t count, const VmaAllocation* pItems);
- void Flush();
-};
-
-#endif // #if VMA_RECORDING_ENABLED
-
-/*
-Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.
-*/
-class VmaAllocationObjectAllocator
-{
- VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)
-public:
- VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks);
-
- template<typename... Types> VmaAllocation Allocate(Types... args);
- void Free(VmaAllocation hAlloc);
-
-private:
- VMA_MUTEX m_Mutex;
- VmaPoolAllocator<VmaAllocation_T> m_Allocator;
-};
-
-struct VmaCurrentBudgetData
-{
- VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];
- VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];
-
-#if VMA_MEMORY_BUDGET
- VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;
- VMA_RW_MUTEX m_BudgetMutex;
- uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];
- uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];
- uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];
-#endif // #if VMA_MEMORY_BUDGET
-
- VmaCurrentBudgetData()
- {
- for(uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex)
- {
- m_BlockBytes[heapIndex] = 0;
- m_AllocationBytes[heapIndex] = 0;
-#if VMA_MEMORY_BUDGET
- m_VulkanUsage[heapIndex] = 0;
- m_VulkanBudget[heapIndex] = 0;
- m_BlockBytesAtBudgetFetch[heapIndex] = 0;
-#endif
- }
-
-#if VMA_MEMORY_BUDGET
- m_OperationsSinceBudgetFetch = 0;
-#endif
- }
-
- void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
- {
- m_AllocationBytes[heapIndex] += allocationSize;
-#if VMA_MEMORY_BUDGET
- ++m_OperationsSinceBudgetFetch;
-#endif
- }
-
- void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
- {
- VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize); // DELME
- m_AllocationBytes[heapIndex] -= allocationSize;
-#if VMA_MEMORY_BUDGET
- ++m_OperationsSinceBudgetFetch;
-#endif
- }
-};
-
-// Main allocator object.
-struct VmaAllocator_T
-{
- VMA_CLASS_NO_COPY(VmaAllocator_T)
-public:
- bool m_UseMutex;
- uint32_t m_VulkanApiVersion;
- bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
- bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
- bool m_UseExtMemoryBudget;
- bool m_UseAmdDeviceCoherentMemory;
- bool m_UseKhrBufferDeviceAddress;
- bool m_UseExtMemoryPriority;
- VkDevice m_hDevice;
- VkInstance m_hInstance;
- bool m_AllocationCallbacksSpecified;
- VkAllocationCallbacks m_AllocationCallbacks;
- VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;
- VmaAllocationObjectAllocator m_AllocationObjectAllocator;
-
- // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.
- uint32_t m_HeapSizeLimitMask;
-
- VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
- VkPhysicalDeviceMemoryProperties m_MemProps;
-
- // Default pools.
- VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
- VmaBlockVector* m_pSmallBufferBlockVectors[VK_MAX_MEMORY_TYPES];
-
- typedef VmaIntrusiveLinkedList<VmaDedicatedAllocationListItemTraits> DedicatedAllocationLinkedList;
- DedicatedAllocationLinkedList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];
- VMA_RW_MUTEX m_DedicatedAllocationsMutex[VK_MAX_MEMORY_TYPES];
-
- VmaCurrentBudgetData m_Budget;
- VMA_ATOMIC_UINT32 m_DeviceMemoryCount; // Total number of VkDeviceMemory objects.
-
- VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
- VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);
- ~VmaAllocator_T();
-
- const VkAllocationCallbacks* GetAllocationCallbacks() const
- {
- return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : 0;
- }
- const VmaVulkanFunctions& GetVulkanFunctions() const
- {
- return m_VulkanFunctions;
- }
-
- VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; }
-
- VkDeviceSize GetBufferImageGranularity() const
- {
- return VMA_MAX(
- static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
- m_PhysicalDeviceProperties.limits.bufferImageGranularity);
- }
-
- uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }
- uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }
-
- uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const
- {
- VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
- return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
- }
- // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
- bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
- {
- return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
- VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
- }
- // Minimum alignment for all allocations in specific memory type.
- VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
- {
- return IsMemoryTypeNonCoherent(memTypeIndex) ?
- VMA_MAX((VkDeviceSize)VMA_MIN_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
- (VkDeviceSize)VMA_MIN_ALIGNMENT;
- }
-
- bool IsIntegratedGpu() const
- {
- return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
- }
-
- uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; }
-
-#if VMA_RECORDING_ENABLED
- VmaRecorder* GetRecorder() const { return m_pRecorder; }
-#endif
-
- void GetBufferMemoryRequirements(
- VkBuffer hBuffer,
- VkMemoryRequirements& memReq,
- bool& requiresDedicatedAllocation,
- bool& prefersDedicatedAllocation) const;
- void GetImageMemoryRequirements(
- VkImage hImage,
- VkMemoryRequirements& memReq,
- bool& requiresDedicatedAllocation,
- bool& prefersDedicatedAllocation) const;
-
- // Main allocation function.
- VkResult AllocateMemory(
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage, // UINT32_MAX when unknown.
- VkImage dedicatedImage,
- const VmaAllocationCreateInfo& createInfo,
- VmaSuballocationType suballocType,
- size_t allocationCount,
- VmaAllocation* pAllocations);
-
- // Main deallocation function.
- void FreeMemory(
- size_t allocationCount,
- const VmaAllocation* pAllocations);
-
- void CalculateStats(VmaStats* pStats);
-
- void GetBudget(
- VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount);
-
-#if VMA_STATS_STRING_ENABLED
- void PrintDetailedMap(class VmaJsonWriter& json);
-#endif
-
- VkResult DefragmentationBegin(
- const VmaDefragmentationInfo2& info,
- VmaDefragmentationStats* pStats,
- VmaDefragmentationContext* pContext);
- VkResult DefragmentationEnd(
- VmaDefragmentationContext context);
-
- VkResult DefragmentationPassBegin(
- VmaDefragmentationPassInfo* pInfo,
- VmaDefragmentationContext context);
- VkResult DefragmentationPassEnd(
- VmaDefragmentationContext context);
-
- void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);
- bool TouchAllocation(VmaAllocation hAllocation);
-
- VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);
- void DestroyPool(VmaPool pool);
- void GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats);
-
- void SetCurrentFrameIndex(uint32_t frameIndex);
- uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
-
- void MakePoolAllocationsLost(
- VmaPool hPool,
- size_t* pLostAllocationCount);
- VkResult CheckPoolCorruption(VmaPool hPool);
- VkResult CheckCorruption(uint32_t memoryTypeBits);
-
- void CreateLostAllocation(VmaAllocation* pAllocation);
-
- // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.
- VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
- // Call to Vulkan function vkFreeMemory with accompanying bookkeeping.
- void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
- // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.
- VkResult BindVulkanBuffer(
- VkDeviceMemory memory,
- VkDeviceSize memoryOffset,
- VkBuffer buffer,
- const void* pNext);
- // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.
- VkResult BindVulkanImage(
- VkDeviceMemory memory,
- VkDeviceSize memoryOffset,
- VkImage image,
- const void* pNext);
-
- VkResult Map(VmaAllocation hAllocation, void** ppData);
- void Unmap(VmaAllocation hAllocation);
-
- VkResult BindBufferMemory(
- VmaAllocation hAllocation,
- VkDeviceSize allocationLocalOffset,
- VkBuffer hBuffer,
- const void* pNext);
- VkResult BindImageMemory(
- VmaAllocation hAllocation,
- VkDeviceSize allocationLocalOffset,
- VkImage hImage,
- const void* pNext);
-
- VkResult FlushOrInvalidateAllocation(
- VmaAllocation hAllocation,
- VkDeviceSize offset, VkDeviceSize size,
- VMA_CACHE_OPERATION op);
- VkResult FlushOrInvalidateAllocations(
- uint32_t allocationCount,
- const VmaAllocation* allocations,
- const VkDeviceSize* offsets, const VkDeviceSize* sizes,
- VMA_CACHE_OPERATION op);
-
- void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
-
- /*
- Returns bit mask of memory types that can support defragmentation on GPU as
- they support creation of required buffer for copy operations.
- */
- uint32_t GetGpuDefragmentationMemoryTypeBits();
-
-#if VMA_EXTERNAL_MEMORY
- VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const
- {
- return m_TypeExternalMemoryHandleTypes[memTypeIndex];
- }
-#endif // #if VMA_EXTERNAL_MEMORY
-
-private:
- VkDeviceSize m_PreferredLargeHeapBlockSize;
-
- VkPhysicalDevice m_PhysicalDevice;
- VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
- VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.
-#if VMA_EXTERNAL_MEMORY
- VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES];
-#endif // #if VMA_EXTERNAL_MEMORY
-
- VMA_RW_MUTEX m_PoolsMutex;
- typedef VmaIntrusiveLinkedList<VmaPoolListItemTraits> PoolList;
- // Protected by m_PoolsMutex.
- PoolList m_Pools;
- uint32_t m_NextPoolId;
-
- VmaVulkanFunctions m_VulkanFunctions;
-
- // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types.
- uint32_t m_GlobalMemoryTypeBits;
-
-#if VMA_RECORDING_ENABLED
- VmaRecorder* m_pRecorder;
-#endif
-
- void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);
-
-#if VMA_STATIC_VULKAN_FUNCTIONS == 1
- void ImportVulkanFunctions_Static();
-#endif
-
- void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions);
-
-#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1
- void ImportVulkanFunctions_Dynamic();
-#endif
-
- void ValidateVulkanFunctions();
-
- VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
-
- VkResult AllocateMemoryOfType(
- VkDeviceSize size,
- VkDeviceSize alignment,
- bool dedicatedAllocation,
- VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage,
- VkImage dedicatedImage,
- const VmaAllocationCreateInfo& createInfo,
- uint32_t memTypeIndex,
- VmaSuballocationType suballocType,
- size_t allocationCount,
- VmaAllocation* pAllocations);
-
- // Helper function only to be used inside AllocateDedicatedMemory.
- VkResult AllocateDedicatedMemoryPage(
- VkDeviceSize size,
- VmaSuballocationType suballocType,
- uint32_t memTypeIndex,
- const VkMemoryAllocateInfo& allocInfo,
- bool map,
- bool isUserDataString,
- void* pUserData,
- VmaAllocation* pAllocation);
-
- // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.
- VkResult AllocateDedicatedMemory(
- VkDeviceSize size,
- VmaSuballocationType suballocType,
- uint32_t memTypeIndex,
- bool withinBudget,
- bool map,
- bool isUserDataString,
- void* pUserData,
- float priority,
- VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage,
- VkImage dedicatedImage,
- size_t allocationCount,
- VmaAllocation* pAllocations);
-
- void FreeDedicatedMemory(const VmaAllocation allocation);
-
- /*
- Calculates and returns bit mask of memory types that can support defragmentation
- on GPU as they support creation of required buffer for copy operations.
- */
- uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;
-
- uint32_t CalculateGlobalMemoryTypeBits() const;
-
- bool GetFlushOrInvalidateRange(
- VmaAllocation allocation,
- VkDeviceSize offset, VkDeviceSize size,
- VkMappedMemoryRange& outRange) const;
-
-#if VMA_MEMORY_BUDGET
- void UpdateVulkanBudget();
-#endif // #if VMA_MEMORY_BUDGET
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Memory allocation #2 after VmaAllocator_T definition
-
-static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)
-{
- return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);
-}
-
-static void VmaFree(VmaAllocator hAllocator, void* ptr)
-{
- VmaFree(&hAllocator->m_AllocationCallbacks, ptr);
-}
-
-template<typename T>
-static T* VmaAllocate(VmaAllocator hAllocator)
-{
- return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));
-}
-
-template<typename T>
-static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)
-{
- return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));
-}
-
-template<typename T>
-static void vma_delete(VmaAllocator hAllocator, T* ptr)
-{
- if(ptr != VMA_NULL)
- {
- ptr->~T();
- VmaFree(hAllocator, ptr);
- }
-}
-
-template<typename T>
-static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)
-{
- if(ptr != VMA_NULL)
- {
- for(size_t i = count; i--; )
- ptr[i].~T();
- VmaFree(hAllocator, ptr);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaStringBuilder
-
-#if VMA_STATS_STRING_ENABLED
-
+#if !defined(_VMA_STRING_BUILDER) && VMA_STATS_STRING_ENABLED
class VmaStringBuilder
{
public:
- VmaStringBuilder(VmaAllocator alloc) : m_Data(VmaStlAllocator<char>(alloc->GetAllocationCallbacks())) { }
+ VmaStringBuilder(const VkAllocationCallbacks* allocationCallbacks) : m_Data(VmaStlAllocator<char>(allocationCallbacks)) {}
+ ~VmaStringBuilder() = default;
+
size_t GetLength() const { return m_Data.size(); }
const char* GetData() const { return m_Data.data(); }
-
+ void AddNewLine() { Add('\n'); }
void Add(char ch) { m_Data.push_back(ch); }
+
void Add(const char* pStr);
- void AddNewLine() { Add('\n'); }
void AddNumber(uint32_t num);
void AddNumber(uint64_t num);
void AddPointer(const void* ptr);
private:
- VmaVector< char, VmaStlAllocator<char> > m_Data;
+ VmaVector<char, VmaStlAllocator<char>> m_Data;
};
+#ifndef _VMA_STRING_BUILDER_FUNCTIONS
void VmaStringBuilder::Add(const char* pStr)
{
const size_t strLen = strlen(pStr);
- if(strLen > 0)
+ if (strLen > 0)
{
const size_t oldCount = m_Data.size();
m_Data.resize(oldCount + strLen);
@@ -8618,13 +5377,12 @@ void VmaStringBuilder::AddNumber(uint32_t num)
{
char buf[11];
buf[10] = '\0';
- char *p = &buf[10];
+ char* p = &buf[10];
do
{
*--p = '0' + (num % 10);
num /= 10;
- }
- while(num);
+ } while (num);
Add(p);
}
@@ -8632,13 +5390,12 @@ void VmaStringBuilder::AddNumber(uint64_t num)
{
char buf[21];
buf[20] = '\0';
- char *p = &buf[20];
+ char* p = &buf[20];
do
{
*--p = '0' + (num % 10);
num /= 10;
- }
- while(num);
+ } while (num);
Add(p);
}
@@ -8648,43 +5405,67 @@ void VmaStringBuilder::AddPointer(const void* ptr)
VmaPtrToStr(buf, sizeof(buf), ptr);
Add(buf);
}
+#endif //_VMA_STRING_BUILDER_FUNCTIONS
+#endif // _VMA_STRING_BUILDER
-#endif // #if VMA_STATS_STRING_ENABLED
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaJsonWriter
-
-#if VMA_STATS_STRING_ENABLED
-
+#if !defined(_VMA_JSON_WRITER) && VMA_STATS_STRING_ENABLED
+/*
+Allows to conveniently build a correct JSON document to be written to the
+VmaStringBuilder passed to the constructor.
+*/
class VmaJsonWriter
{
VMA_CLASS_NO_COPY(VmaJsonWriter)
public:
+ // sb - string builder to write the document to. Must remain alive for the whole lifetime of this object.
VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb);
~VmaJsonWriter();
+ // Begins object by writing "{".
+ // Inside an object, you must call pairs of WriteString and a value, e.g.:
+ // j.BeginObject(true); j.WriteString("A"); j.WriteNumber(1); j.WriteString("B"); j.WriteNumber(2); j.EndObject();
+ // Will write: { "A": 1, "B": 2 }
void BeginObject(bool singleLine = false);
+ // Ends object by writing "}".
void EndObject();
+ // Begins array by writing "[".
+ // Inside an array, you can write a sequence of any values.
void BeginArray(bool singleLine = false);
+ // Ends array by writing "[".
void EndArray();
+ // Writes a string value inside "".
+ // pStr can contain any ANSI characters, including '"', new line etc. - they will be properly escaped.
void WriteString(const char* pStr);
+
+ // Begins writing a string value.
+ // Call BeginString, ContinueString, ContinueString, ..., EndString instead of
+ // WriteString to conveniently build the string content incrementally, made of
+ // parts including numbers.
void BeginString(const char* pStr = VMA_NULL);
+ // Posts next part of an open string.
void ContinueString(const char* pStr);
+ // Posts next part of an open string. The number is converted to decimal characters.
void ContinueString(uint32_t n);
void ContinueString(uint64_t n);
+ void ContinueString_Size(size_t n);
+ // Posts next part of an open string. Pointer value is converted to characters
+ // using "%p" formatting - shown as hexadecimal number, e.g.: 000000081276Ad00
void ContinueString_Pointer(const void* ptr);
+ // Ends writing a string value by writing '"'.
void EndString(const char* pStr = VMA_NULL);
+ // Writes a number value.
void WriteNumber(uint32_t n);
void WriteNumber(uint64_t n);
+ void WriteSize(size_t n);
+ // Writes a boolean value - false or true.
void WriteBool(bool b);
+ // Writes a null value.
void WriteNull();
private:
- static const char* const INDENT;
-
enum COLLECTION_TYPE
{
COLLECTION_TYPE_OBJECT,
@@ -8697,22 +5478,27 @@ private:
bool singleLineMode;
};
+ static const char* const INDENT;
+
VmaStringBuilder& m_SB;
VmaVector< StackItem, VmaStlAllocator<StackItem> > m_Stack;
bool m_InsideString;
+ // Write size_t for less than 64bits
+ void WriteSize(size_t n, std::integral_constant<bool, false>) { m_SB.AddNumber(static_cast<uint32_t>(n)); }
+ // Write size_t for 64bits
+ void WriteSize(size_t n, std::integral_constant<bool, true>) { m_SB.AddNumber(static_cast<uint64_t>(n)); }
+
void BeginValue(bool isString);
void WriteIndent(bool oneLess = false);
};
-
const char* const VmaJsonWriter::INDENT = " ";
-VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb) :
- m_SB(sb),
+#ifndef _VMA_JSON_WRITER_FUNCTIONS
+VmaJsonWriter::VmaJsonWriter(const VkAllocationCallbacks* pAllocationCallbacks, VmaStringBuilder& sb)
+ : m_SB(sb),
m_Stack(VmaStlAllocator<StackItem>(pAllocationCallbacks)),
- m_InsideString(false)
-{
-}
+ m_InsideString(false) {}
VmaJsonWriter::~VmaJsonWriter()
{
@@ -8783,7 +5569,7 @@ void VmaJsonWriter::BeginString(const char* pStr)
BeginValue(true);
m_SB.Add('"');
m_InsideString = true;
- if(pStr != VMA_NULL && pStr[0] != '\0')
+ if (pStr != VMA_NULL && pStr[0] != '\0')
{
ContinueString(pStr);
}
@@ -8794,22 +5580,22 @@ void VmaJsonWriter::ContinueString(const char* pStr)
VMA_ASSERT(m_InsideString);
const size_t strLen = strlen(pStr);
- for(size_t i = 0; i < strLen; ++i)
+ for (size_t i = 0; i < strLen; ++i)
{
char ch = pStr[i];
- if(ch == '\\')
+ if (ch == '\\')
{
m_SB.Add("\\\\");
}
- else if(ch == '"')
+ else if (ch == '"')
{
m_SB.Add("\\\"");
}
- else if(ch >= 32)
+ else if (ch >= 32)
{
m_SB.Add(ch);
}
- else switch(ch)
+ else switch (ch)
{
case '\b':
m_SB.Add("\\b");
@@ -8845,6 +5631,14 @@ void VmaJsonWriter::ContinueString(uint64_t n)
m_SB.AddNumber(n);
}
+void VmaJsonWriter::ContinueString_Size(size_t n)
+{
+ VMA_ASSERT(m_InsideString);
+ // Fix for AppleClang incorrect type casting
+ // TODO: Change to if constexpr when C++17 used as minimal standard
+ WriteSize(n, std::is_same<size_t, uint64_t>{});
+}
+
void VmaJsonWriter::ContinueString_Pointer(const void* ptr)
{
VMA_ASSERT(m_InsideString);
@@ -8854,7 +5648,7 @@ void VmaJsonWriter::ContinueString_Pointer(const void* ptr)
void VmaJsonWriter::EndString(const char* pStr)
{
VMA_ASSERT(m_InsideString);
- if(pStr != VMA_NULL && pStr[0] != '\0')
+ if (pStr != VMA_NULL && pStr[0] != '\0')
{
ContinueString(pStr);
}
@@ -8876,6 +5670,15 @@ void VmaJsonWriter::WriteNumber(uint64_t n)
m_SB.AddNumber(n);
}
+void VmaJsonWriter::WriteSize(size_t n)
+{
+ VMA_ASSERT(!m_InsideString);
+ BeginValue(false);
+ // Fix for AppleClang incorrect type casting
+ // TODO: Change to if constexpr when C++17 used as minimal standard
+ WriteSize(n, std::is_same<size_t, uint64_t>{});
+}
+
void VmaJsonWriter::WriteBool(bool b)
{
VMA_ASSERT(!m_InsideString);
@@ -8892,21 +5695,21 @@ void VmaJsonWriter::WriteNull()
void VmaJsonWriter::BeginValue(bool isString)
{
- if(!m_Stack.empty())
+ if (!m_Stack.empty())
{
StackItem& currItem = m_Stack.back();
- if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ if (currItem.type == COLLECTION_TYPE_OBJECT &&
currItem.valueCount % 2 == 0)
{
VMA_ASSERT(isString);
}
- if(currItem.type == COLLECTION_TYPE_OBJECT &&
+ if (currItem.type == COLLECTION_TYPE_OBJECT &&
currItem.valueCount % 2 != 0)
{
m_SB.Add(": ");
}
- else if(currItem.valueCount > 0)
+ else if (currItem.valueCount > 0)
{
m_SB.Add(", ");
WriteIndent();
@@ -8921,435 +5724,751 @@ void VmaJsonWriter::BeginValue(bool isString)
void VmaJsonWriter::WriteIndent(bool oneLess)
{
- if(!m_Stack.empty() && !m_Stack.back().singleLineMode)
+ if (!m_Stack.empty() && !m_Stack.back().singleLineMode)
{
m_SB.AddNewLine();
size_t count = m_Stack.size();
- if(count > 0 && oneLess)
+ if (count > 0 && oneLess)
{
--count;
}
- for(size_t i = 0; i < count; ++i)
+ for (size_t i = 0; i < count; ++i)
{
m_SB.Add(INDENT);
}
}
}
+#endif // _VMA_JSON_WRITER_FUNCTIONS
-#endif // #if VMA_STATS_STRING_ENABLED
-
-////////////////////////////////////////////////////////////////////////////////
-
-void VmaAllocation_T::SetUserData(VmaAllocator hAllocator, void* pUserData)
+static void VmaPrintDetailedStatistics(VmaJsonWriter& json, const VmaDetailedStatistics& stat)
{
- if(IsUserDataString())
- {
- VMA_ASSERT(pUserData == VMA_NULL || pUserData != m_pUserData);
+ json.BeginObject();
- FreeUserDataString(hAllocator);
+ json.WriteString("BlockCount");
+ json.WriteNumber(stat.statistics.blockCount);
+ json.WriteString("BlockBytes");
+ json.WriteNumber(stat.statistics.blockBytes);
+ json.WriteString("AllocationCount");
+ json.WriteNumber(stat.statistics.allocationCount);
+ json.WriteString("AllocationBytes");
+ json.WriteNumber(stat.statistics.allocationBytes);
+ json.WriteString("UnusedRangeCount");
+ json.WriteNumber(stat.unusedRangeCount);
- if(pUserData != VMA_NULL)
- {
- m_pUserData = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), (const char*)pUserData);
- }
+ if (stat.statistics.allocationCount > 1)
+ {
+ json.WriteString("AllocationSizeMin");
+ json.WriteNumber(stat.allocationSizeMin);
+ json.WriteString("AllocationSizeMax");
+ json.WriteNumber(stat.allocationSizeMax);
}
- else
+ if (stat.unusedRangeCount > 1)
{
- m_pUserData = pUserData;
+ json.WriteString("UnusedRangeSizeMin");
+ json.WriteNumber(stat.unusedRangeSizeMin);
+ json.WriteString("UnusedRangeSizeMax");
+ json.WriteNumber(stat.unusedRangeSizeMax);
}
+ json.EndObject();
}
+#endif // _VMA_JSON_WRITER
-void VmaAllocation_T::ChangeBlockAllocation(
- VmaAllocator hAllocator,
- VmaDeviceMemoryBlock* block,
- VkDeviceSize offset)
+#ifndef _VMA_MAPPING_HYSTERESIS
+
+class VmaMappingHysteresis
{
- VMA_ASSERT(block != VMA_NULL);
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ VMA_CLASS_NO_COPY(VmaMappingHysteresis)
+public:
+ VmaMappingHysteresis() = default;
+
+ uint32_t GetExtraMapping() const { return m_ExtraMapping; }
- // Move mapping reference counter from old block to new block.
- if(block != m_BlockAllocation.m_Block)
+ // Call when Map was called.
+ // Returns true if switched to extra +1 mapping reference count.
+ bool PostMap()
{
- uint32_t mapRefCount = m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP;
- if(IsPersistentMap())
- ++mapRefCount;
- m_BlockAllocation.m_Block->Unmap(hAllocator, mapRefCount);
- block->Map(hAllocator, mapRefCount, VMA_NULL);
+#if VMA_MAPPING_HYSTERESIS_ENABLED
+ if(m_ExtraMapping == 0)
+ {
+ ++m_MajorCounter;
+ if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING)
+ {
+ m_ExtraMapping = 1;
+ m_MajorCounter = 0;
+ m_MinorCounter = 0;
+ return true;
+ }
+ }
+ else // m_ExtraMapping == 1
+ PostMinorCounter();
+#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED
+ return false;
}
- m_BlockAllocation.m_Block = block;
- m_BlockAllocation.m_Offset = offset;
-}
-
-void VmaAllocation_T::ChangeOffset(VkDeviceSize newOffset)
-{
- VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
- m_BlockAllocation.m_Offset = newOffset;
-}
-
-VkDeviceSize VmaAllocation_T::GetOffset() const
-{
- switch(m_Type)
+ // Call when Unmap was called.
+ void PostUnmap()
{
- case ALLOCATION_TYPE_BLOCK:
- return m_BlockAllocation.m_Offset;
- case ALLOCATION_TYPE_DEDICATED:
- return 0;
- default:
- VMA_ASSERT(0);
- return 0;
+#if VMA_MAPPING_HYSTERESIS_ENABLED
+ if(m_ExtraMapping == 0)
+ ++m_MajorCounter;
+ else // m_ExtraMapping == 1
+ PostMinorCounter();
+#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED
}
-}
-VkDeviceMemory VmaAllocation_T::GetMemory() const
-{
- switch(m_Type)
+ // Call when allocation was made from the memory block.
+ void PostAlloc()
{
- case ALLOCATION_TYPE_BLOCK:
- return m_BlockAllocation.m_Block->GetDeviceMemory();
- case ALLOCATION_TYPE_DEDICATED:
- return m_DedicatedAllocation.m_hMemory;
- default:
- VMA_ASSERT(0);
- return VK_NULL_HANDLE;
+#if VMA_MAPPING_HYSTERESIS_ENABLED
+ if(m_ExtraMapping == 1)
+ ++m_MajorCounter;
+ else // m_ExtraMapping == 0
+ PostMinorCounter();
+#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED
}
-}
-void* VmaAllocation_T::GetMappedData() const
-{
- switch(m_Type)
+ // Call when allocation was freed from the memory block.
+ // Returns true if switched to extra -1 mapping reference count.
+ bool PostFree()
{
- case ALLOCATION_TYPE_BLOCK:
- if(m_MapCount != 0)
+#if VMA_MAPPING_HYSTERESIS_ENABLED
+ if(m_ExtraMapping == 1)
{
- void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();
- VMA_ASSERT(pBlockData != VMA_NULL);
- return (char*)pBlockData + m_BlockAllocation.m_Offset;
- }
- else
- {
- return VMA_NULL;
+ ++m_MajorCounter;
+ if(m_MajorCounter >= COUNTER_MIN_EXTRA_MAPPING &&
+ m_MajorCounter > m_MinorCounter + 1)
+ {
+ m_ExtraMapping = 0;
+ m_MajorCounter = 0;
+ m_MinorCounter = 0;
+ return true;
+ }
}
- break;
- case ALLOCATION_TYPE_DEDICATED:
- VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0));
- return m_DedicatedAllocation.m_pMappedData;
- default:
- VMA_ASSERT(0);
- return VMA_NULL;
- }
-}
-
-bool VmaAllocation_T::CanBecomeLost() const
-{
- switch(m_Type)
- {
- case ALLOCATION_TYPE_BLOCK:
- return m_BlockAllocation.m_CanBecomeLost;
- case ALLOCATION_TYPE_DEDICATED:
- return false;
- default:
- VMA_ASSERT(0);
+ else // m_ExtraMapping == 0
+ PostMinorCounter();
+#endif // #if VMA_MAPPING_HYSTERESIS_ENABLED
return false;
}
-}
-bool VmaAllocation_T::MakeLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
-{
- VMA_ASSERT(CanBecomeLost());
+private:
+ static const int32_t COUNTER_MIN_EXTRA_MAPPING = 7;
- /*
- Warning: This is a carefully designed algorithm.
- Do not modify unless you really know what you're doing :)
- */
- uint32_t localLastUseFrameIndex = GetLastUseFrameIndex();
- for(;;)
+ uint32_t m_MinorCounter = 0;
+ uint32_t m_MajorCounter = 0;
+ uint32_t m_ExtraMapping = 0; // 0 or 1.
+
+ void PostMinorCounter()
{
- if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
+ if(m_MinorCounter < m_MajorCounter)
{
- VMA_ASSERT(0);
- return false;
+ ++m_MinorCounter;
}
- else if(localLastUseFrameIndex + frameInUseCount >= currentFrameIndex)
+ else if(m_MajorCounter > 0)
{
- return false;
- }
- else // Last use time earlier than current time.
- {
- if(CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, VMA_FRAME_INDEX_LOST))
- {
- // Setting hAllocation.LastUseFrameIndex atomic to VMA_FRAME_INDEX_LOST is enough to mark it as LOST.
- // Calling code just needs to unregister this allocation in owning VmaDeviceMemoryBlock.
- return true;
- }
+ --m_MajorCounter;
+ --m_MinorCounter;
}
}
-}
+};
-#if VMA_STATS_STRING_ENABLED
+#endif // _VMA_MAPPING_HYSTERESIS
-// Correspond to values of enum VmaSuballocationType.
-static const char* VMA_SUBALLOCATION_TYPE_NAMES[] = {
- "FREE",
- "UNKNOWN",
- "BUFFER",
- "IMAGE_UNKNOWN",
- "IMAGE_LINEAR",
- "IMAGE_OPTIMAL",
+#ifndef _VMA_DEVICE_MEMORY_BLOCK
+/*
+Represents a single block of device memory (`VkDeviceMemory`) with all the
+data about its regions (aka suballocations, #VmaAllocation), assigned and free.
+
+Thread-safety:
+- Access to m_pMetadata must be externally synchronized.
+- Map, Unmap, Bind* are synchronized internally.
+*/
+class VmaDeviceMemoryBlock
+{
+ VMA_CLASS_NO_COPY(VmaDeviceMemoryBlock)
+public:
+ VmaBlockMetadata* m_pMetadata;
+
+ VmaDeviceMemoryBlock(VmaAllocator hAllocator);
+ ~VmaDeviceMemoryBlock();
+
+ // Always call after construction.
+ void Init(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t newMemoryTypeIndex,
+ VkDeviceMemory newMemory,
+ VkDeviceSize newSize,
+ uint32_t id,
+ uint32_t algorithm,
+ VkDeviceSize bufferImageGranularity);
+ // Always call before destruction.
+ void Destroy(VmaAllocator allocator);
+
+ VmaPool GetParentPool() const { return m_hParentPool; }
+ VkDeviceMemory GetDeviceMemory() const { return m_hMemory; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ uint32_t GetId() const { return m_Id; }
+ void* GetMappedData() const { return m_pMappedData; }
+ uint32_t GetMapRefCount() const { return m_MapCount; }
+
+ // Call when allocation/free was made from m_pMetadata.
+ // Used for m_MappingHysteresis.
+ void PostAlloc() { m_MappingHysteresis.PostAlloc(); }
+ void PostFree(VmaAllocator hAllocator);
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ bool Validate() const;
+ VkResult CheckCorruption(VmaAllocator hAllocator);
+
+ // ppData can be null.
+ VkResult Map(VmaAllocator hAllocator, uint32_t count, void** ppData);
+ void Unmap(VmaAllocator hAllocator, uint32_t count);
+
+ VkResult WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+ VkResult ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize);
+
+ VkResult BindBufferMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext);
+ VkResult BindImageMemory(
+ const VmaAllocator hAllocator,
+ const VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext);
+
+private:
+ VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
+ uint32_t m_MemoryTypeIndex;
+ uint32_t m_Id;
+ VkDeviceMemory m_hMemory;
+
+ /*
+ Protects access to m_hMemory so it is not used by multiple threads simultaneously, e.g. vkMapMemory, vkBindBufferMemory.
+ Also protects m_MapCount, m_pMappedData.
+ Allocations, deallocations, any change in m_pMetadata is protected by parent's VmaBlockVector::m_Mutex.
+ */
+ VMA_MUTEX m_MapAndBindMutex;
+ VmaMappingHysteresis m_MappingHysteresis;
+ uint32_t m_MapCount;
+ void* m_pMappedData;
};
+#endif // _VMA_DEVICE_MEMORY_BLOCK
-void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
+#ifndef _VMA_ALLOCATION_T
+struct VmaAllocation_T
{
- json.WriteString("Type");
- json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);
+ friend struct VmaDedicatedAllocationListItemTraits;
- json.WriteString("Size");
- json.WriteNumber(m_Size);
+ enum FLAGS
+ {
+ FLAG_PERSISTENT_MAP = 0x01,
+ FLAG_MAPPING_ALLOWED = 0x02,
+ };
- if(m_pUserData != VMA_NULL)
+public:
+ enum ALLOCATION_TYPE
{
- json.WriteString("UserData");
- if(IsUserDataString())
- {
- json.WriteString((const char*)m_pUserData);
- }
- else
- {
- json.BeginString();
- json.ContinueString_Pointer(m_pUserData);
- json.EndString();
- }
- }
+ ALLOCATION_TYPE_NONE,
+ ALLOCATION_TYPE_BLOCK,
+ ALLOCATION_TYPE_DEDICATED,
+ };
- json.WriteString("CreationFrameIndex");
- json.WriteNumber(m_CreationFrameIndex);
+ // This struct is allocated using VmaPoolAllocator.
+ VmaAllocation_T(bool mappingAllowed);
+ ~VmaAllocation_T();
- json.WriteString("LastUseFrameIndex");
- json.WriteNumber(GetLastUseFrameIndex());
+ void InitBlockAllocation(
+ VmaDeviceMemoryBlock* block,
+ VmaAllocHandle allocHandle,
+ VkDeviceSize alignment,
+ VkDeviceSize size,
+ uint32_t memoryTypeIndex,
+ VmaSuballocationType suballocationType,
+ bool mapped);
+ // pMappedData not null means allocation is created with MAPPED flag.
+ void InitDedicatedAllocation(
+ VmaPool hParentPool,
+ uint32_t memoryTypeIndex,
+ VkDeviceMemory hMemory,
+ VmaSuballocationType suballocationType,
+ void* pMappedData,
+ VkDeviceSize size);
- if(m_BufferImageUsage != 0)
- {
- json.WriteString("Usage");
- json.WriteNumber(m_BufferImageUsage);
- }
-}
+ ALLOCATION_TYPE GetType() const { return (ALLOCATION_TYPE)m_Type; }
+ VkDeviceSize GetAlignment() const { return m_Alignment; }
+ VkDeviceSize GetSize() const { return m_Size; }
+ void* GetUserData() const { return m_pUserData; }
+ const char* GetName() const { return m_pName; }
+ VmaSuballocationType GetSuballocationType() const { return (VmaSuballocationType)m_SuballocationType; }
+
+ VmaDeviceMemoryBlock* GetBlock() const { VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK); return m_BlockAllocation.m_Block; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ bool IsPersistentMap() const { return (m_Flags & FLAG_PERSISTENT_MAP) != 0; }
+ bool IsMappingAllowed() const { return (m_Flags & FLAG_MAPPING_ALLOWED) != 0; }
+
+ void SetUserData(VmaAllocator hAllocator, void* pUserData) { m_pUserData = pUserData; }
+ void SetName(VmaAllocator hAllocator, const char* pName);
+ void FreeName(VmaAllocator hAllocator);
+ uint8_t SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation);
+ VmaAllocHandle GetAllocHandle() const;
+ VkDeviceSize GetOffset() const;
+ VmaPool GetParentPool() const;
+ VkDeviceMemory GetMemory() const;
+ void* GetMappedData() const;
+
+ void BlockAllocMap();
+ void BlockAllocUnmap();
+ VkResult DedicatedAllocMap(VmaAllocator hAllocator, void** ppData);
+ void DedicatedAllocUnmap(VmaAllocator hAllocator);
+
+#if VMA_STATS_STRING_ENABLED
+ uint32_t GetBufferImageUsage() const { return m_BufferImageUsage; }
+ void InitBufferImageUsage(uint32_t bufferImageUsage);
+ void PrintParameters(class VmaJsonWriter& json) const;
#endif
-void VmaAllocation_T::FreeUserDataString(VmaAllocator hAllocator)
-{
- VMA_ASSERT(IsUserDataString());
- VmaFreeString(hAllocator->GetAllocationCallbacks(), (char*)m_pUserData);
- m_pUserData = VMA_NULL;
-}
+private:
+ // Allocation out of VmaDeviceMemoryBlock.
+ struct BlockAllocation
+ {
+ VmaDeviceMemoryBlock* m_Block;
+ VmaAllocHandle m_AllocHandle;
+ };
+ // Allocation for an object that has its own private VkDeviceMemory.
+ struct DedicatedAllocation
+ {
+ VmaPool m_hParentPool; // VK_NULL_HANDLE if not belongs to custom pool.
+ VkDeviceMemory m_hMemory;
+ void* m_pMappedData; // Not null means memory is mapped.
+ VmaAllocation_T* m_Prev;
+ VmaAllocation_T* m_Next;
+ };
+ union
+ {
+ // Allocation out of VmaDeviceMemoryBlock.
+ BlockAllocation m_BlockAllocation;
+ // Allocation for an object that has its own private VkDeviceMemory.
+ DedicatedAllocation m_DedicatedAllocation;
+ };
-void VmaAllocation_T::BlockAllocMap()
+ VkDeviceSize m_Alignment;
+ VkDeviceSize m_Size;
+ void* m_pUserData;
+ char* m_pName;
+ uint32_t m_MemoryTypeIndex;
+ uint8_t m_Type; // ALLOCATION_TYPE
+ uint8_t m_SuballocationType; // VmaSuballocationType
+ // Reference counter for vmaMapMemory()/vmaUnmapMemory().
+ uint8_t m_MapCount;
+ uint8_t m_Flags; // enum FLAGS
+#if VMA_STATS_STRING_ENABLED
+ uint32_t m_BufferImageUsage; // 0 if unknown.
+#endif
+};
+#endif // _VMA_ALLOCATION_T
+
+#ifndef _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS
+struct VmaDedicatedAllocationListItemTraits
{
- VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+ typedef VmaAllocation_T ItemType;
- if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
+ static ItemType* GetPrev(const ItemType* item)
{
- ++m_MapCount;
+ VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+ return item->m_DedicatedAllocation.m_Prev;
}
- else
+ static ItemType* GetNext(const ItemType* item)
{
- VMA_ASSERT(0 && "Allocation mapped too many times simultaneously.");
+ VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+ return item->m_DedicatedAllocation.m_Next;
}
-}
-
-void VmaAllocation_T::BlockAllocUnmap()
-{
- VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
-
- if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ static ItemType*& AccessPrev(ItemType* item)
{
- --m_MapCount;
+ VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+ return item->m_DedicatedAllocation.m_Prev;
}
- else
+ static ItemType*& AccessNext(ItemType* item)
{
- VMA_ASSERT(0 && "Unmapping allocation not previously mapped.");
+ VMA_HEAVY_ASSERT(item->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
+ return item->m_DedicatedAllocation.m_Next;
}
-}
+};
+#endif // _VMA_DEDICATED_ALLOCATION_LIST_ITEM_TRAITS
-VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)
+#ifndef _VMA_DEDICATED_ALLOCATION_LIST
+/*
+Stores linked list of VmaAllocation_T objects.
+Thread-safe, synchronized internally.
+*/
+class VmaDedicatedAllocationList
{
- VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+public:
+ VmaDedicatedAllocationList() {}
+ ~VmaDedicatedAllocationList();
+
+ void Init(bool useMutex) { m_UseMutex = useMutex; }
+ bool Validate();
+
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats);
+ void AddStatistics(VmaStatistics& inoutStats);
+#if VMA_STATS_STRING_ENABLED
+ // Writes JSON array with the list of allocations.
+ void BuildStatsString(VmaJsonWriter& json);
+#endif
+
+ bool IsEmpty();
+ void Register(VmaAllocation alloc);
+ void Unregister(VmaAllocation alloc);
+
+private:
+ typedef VmaIntrusiveLinkedList<VmaDedicatedAllocationListItemTraits> DedicatedAllocationLinkedList;
+
+ bool m_UseMutex = true;
+ VMA_RW_MUTEX m_Mutex;
+ DedicatedAllocationLinkedList m_AllocationList;
+};
+
+#ifndef _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS
+
+VmaDedicatedAllocationList::~VmaDedicatedAllocationList()
+{
+ VMA_HEAVY_ASSERT(Validate());
- if(m_MapCount != 0)
+ if (!m_AllocationList.IsEmpty())
{
- if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) < 0x7F)
- {
- VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
- *ppData = m_DedicatedAllocation.m_pMappedData;
- ++m_MapCount;
- return VK_SUCCESS;
- }
- else
- {
- VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously.");
- return VK_ERROR_MEMORY_MAP_FAILED;
- }
+ VMA_ASSERT(false && "Unfreed dedicated allocations found!");
}
- else
+}
+
+bool VmaDedicatedAllocationList::Validate()
+{
+ const size_t declaredCount = m_AllocationList.GetCount();
+ size_t actualCount = 0;
+ VmaMutexLockRead lock(m_Mutex, m_UseMutex);
+ for (VmaAllocation alloc = m_AllocationList.Front();
+ alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc))
{
- VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
- hAllocator->m_hDevice,
- m_DedicatedAllocation.m_hMemory,
- 0, // offset
- VK_WHOLE_SIZE,
- 0, // flags
- ppData);
- if(result == VK_SUCCESS)
- {
- m_DedicatedAllocation.m_pMappedData = *ppData;
- m_MapCount = 1;
- }
- return result;
+ ++actualCount;
}
+ VMA_VALIDATE(actualCount == declaredCount);
+
+ return true;
}
-void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
+void VmaDedicatedAllocationList::AddDetailedStatistics(VmaDetailedStatistics& inoutStats)
{
- VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
-
- if((m_MapCount & ~MAP_COUNT_FLAG_PERSISTENT_MAP) != 0)
+ for(auto* item = m_AllocationList.Front(); item != nullptr; item = DedicatedAllocationLinkedList::GetNext(item))
{
- --m_MapCount;
- if(m_MapCount == 0)
- {
- m_DedicatedAllocation.m_pMappedData = VMA_NULL;
- (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
- hAllocator->m_hDevice,
- m_DedicatedAllocation.m_hMemory);
- }
+ const VkDeviceSize size = item->GetSize();
+ inoutStats.statistics.blockCount++;
+ inoutStats.statistics.blockBytes += size;
+ VmaAddDetailedStatisticsAllocation(inoutStats, item->GetSize());
}
- else
+}
+
+void VmaDedicatedAllocationList::AddStatistics(VmaStatistics& inoutStats)
+{
+ VmaMutexLockRead lock(m_Mutex, m_UseMutex);
+
+ const uint32_t allocCount = (uint32_t)m_AllocationList.GetCount();
+ inoutStats.blockCount += allocCount;
+ inoutStats.allocationCount += allocCount;
+
+ for(auto* item = m_AllocationList.Front(); item != nullptr; item = DedicatedAllocationLinkedList::GetNext(item))
{
- VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped.");
+ const VkDeviceSize size = item->GetSize();
+ inoutStats.blockBytes += size;
+ inoutStats.allocationBytes += size;
}
}
#if VMA_STATS_STRING_ENABLED
-
-static void VmaPrintStatInfo(VmaJsonWriter& json, const VmaStatInfo& stat)
+void VmaDedicatedAllocationList::BuildStatsString(VmaJsonWriter& json)
{
- json.BeginObject();
-
- json.WriteString("Blocks");
- json.WriteNumber(stat.blockCount);
+ VmaMutexLockRead lock(m_Mutex, m_UseMutex);
+ json.BeginArray();
+ for (VmaAllocation alloc = m_AllocationList.Front();
+ alloc != VMA_NULL; alloc = m_AllocationList.GetNext(alloc))
+ {
+ json.BeginObject(true);
+ alloc->PrintParameters(json);
+ json.EndObject();
+ }
+ json.EndArray();
+}
+#endif // VMA_STATS_STRING_ENABLED
- json.WriteString("Allocations");
- json.WriteNumber(stat.allocationCount);
+bool VmaDedicatedAllocationList::IsEmpty()
+{
+ VmaMutexLockRead lock(m_Mutex, m_UseMutex);
+ return m_AllocationList.IsEmpty();
+}
- json.WriteString("UnusedRanges");
- json.WriteNumber(stat.unusedRangeCount);
+void VmaDedicatedAllocationList::Register(VmaAllocation alloc)
+{
+ VmaMutexLockWrite lock(m_Mutex, m_UseMutex);
+ m_AllocationList.PushBack(alloc);
+}
- json.WriteString("UsedBytes");
- json.WriteNumber(stat.usedBytes);
+void VmaDedicatedAllocationList::Unregister(VmaAllocation alloc)
+{
+ VmaMutexLockWrite lock(m_Mutex, m_UseMutex);
+ m_AllocationList.Remove(alloc);
+}
+#endif // _VMA_DEDICATED_ALLOCATION_LIST_FUNCTIONS
+#endif // _VMA_DEDICATED_ALLOCATION_LIST
- json.WriteString("UnusedBytes");
- json.WriteNumber(stat.unusedBytes);
+#ifndef _VMA_SUBALLOCATION
+/*
+Represents a region of VmaDeviceMemoryBlock that is either assigned and returned as
+allocated memory block or free.
+*/
+struct VmaSuballocation
+{
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ void* userData;
+ VmaSuballocationType type;
+};
- if(stat.allocationCount > 1)
+// Comparator for offsets.
+struct VmaSuballocationOffsetLess
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
{
- json.WriteString("AllocationSize");
- json.BeginObject(true);
- json.WriteString("Min");
- json.WriteNumber(stat.allocationSizeMin);
- json.WriteString("Avg");
- json.WriteNumber(stat.allocationSizeAvg);
- json.WriteString("Max");
- json.WriteNumber(stat.allocationSizeMax);
- json.EndObject();
+ return lhs.offset < rhs.offset;
}
+};
- if(stat.unusedRangeCount > 1)
+struct VmaSuballocationOffsetGreater
+{
+ bool operator()(const VmaSuballocation& lhs, const VmaSuballocation& rhs) const
{
- json.WriteString("UnusedRangeSize");
- json.BeginObject(true);
- json.WriteString("Min");
- json.WriteNumber(stat.unusedRangeSizeMin);
- json.WriteString("Avg");
- json.WriteNumber(stat.unusedRangeSizeAvg);
- json.WriteString("Max");
- json.WriteNumber(stat.unusedRangeSizeMax);
- json.EndObject();
+ return lhs.offset > rhs.offset;
}
-
- json.EndObject();
-}
-
-#endif // #if VMA_STATS_STRING_ENABLED
+};
struct VmaSuballocationItemSizeLess
{
- bool operator()(
- const VmaSuballocationList::iterator lhs,
+ bool operator()(const VmaSuballocationList::iterator lhs,
const VmaSuballocationList::iterator rhs) const
{
return lhs->size < rhs->size;
}
- bool operator()(
- const VmaSuballocationList::iterator lhs,
+
+ bool operator()(const VmaSuballocationList::iterator lhs,
VkDeviceSize rhsSize) const
{
return lhs->size < rhsSize;
}
};
+#endif // _VMA_SUBALLOCATION
+#ifndef _VMA_ALLOCATION_REQUEST
+/*
+Parameters of planned allocation inside a VmaDeviceMemoryBlock.
+item points to a FREE suballocation.
+*/
+struct VmaAllocationRequest
+{
+ VmaAllocHandle allocHandle;
+ VkDeviceSize size;
+ VmaSuballocationList::iterator item;
+ void* customData;
+ uint64_t algorithmData;
+ VmaAllocationRequestType type;
+};
+#endif // _VMA_ALLOCATION_REQUEST
-////////////////////////////////////////////////////////////////////////////////
-// class VmaBlockMetadata
+#ifndef _VMA_BLOCK_METADATA
+/*
+Data structure used for bookkeeping of allocations and unused ranges of memory
+in a single VkDeviceMemory block.
+*/
+class VmaBlockMetadata
+{
+public:
+ // pAllocationCallbacks, if not null, must be owned externally - alive and unchanged for the whole lifetime of this object.
+ VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual);
+ virtual ~VmaBlockMetadata() = default;
+
+ virtual void Init(VkDeviceSize size) { m_Size = size; }
+ bool IsVirtual() const { return m_IsVirtual; }
+ VkDeviceSize GetSize() const { return m_Size; }
+
+ // Validates all data structures inside this object. If not valid, returns false.
+ virtual bool Validate() const = 0;
+ virtual size_t GetAllocationCount() const = 0;
+ virtual size_t GetFreeRegionsCount() const = 0;
+ virtual VkDeviceSize GetSumFreeSize() const = 0;
+ // Returns true if this block is empty - contains only single free suballocation.
+ virtual bool IsEmpty() const = 0;
+ virtual void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) = 0;
+ virtual VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const = 0;
+ virtual void* GetAllocationUserData(VmaAllocHandle allocHandle) const = 0;
+
+ virtual VmaAllocHandle GetAllocationListBegin() const = 0;
+ virtual VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const = 0;
+ virtual VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const = 0;
+
+ // Shouldn't modify blockCount.
+ virtual void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const = 0;
+ virtual void AddStatistics(VmaStatistics& inoutStats) const = 0;
+
+#if VMA_STATS_STRING_ENABLED
+ virtual void PrintDetailedMap(class VmaJsonWriter& json) const = 0;
+#endif
+
+ // Tries to find a place for suballocation with given parameters inside this block.
+ // If succeeded, fills pAllocationRequest and returns true.
+ // If failed, returns false.
+ virtual bool CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ // Always one of VMA_ALLOCATION_CREATE_STRATEGY_* or VMA_ALLOCATION_INTERNAL_STRATEGY_* flags.
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) = 0;
+
+ virtual VkResult CheckCorruption(const void* pBlockData) = 0;
+
+ // Makes actual allocation based on request. Request must already be checked and valid.
+ virtual void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData) = 0;
+
+ // Frees suballocation assigned to given memory region.
+ virtual void Free(VmaAllocHandle allocHandle) = 0;
+
+ // Frees all allocations.
+ // Careful! Don't call it if there are VmaAllocation objects owned by userData of cleared allocations!
+ virtual void Clear() = 0;
+
+ virtual void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) = 0;
+ virtual void DebugLogAllAllocations() const = 0;
-VmaBlockMetadata::VmaBlockMetadata(VmaAllocator hAllocator) :
- m_Size(0),
- m_pAllocationCallbacks(hAllocator->GetAllocationCallbacks())
+protected:
+ const VkAllocationCallbacks* GetAllocationCallbacks() const { return m_pAllocationCallbacks; }
+ VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
+ VkDeviceSize GetDebugMargin() const { return IsVirtual() ? 0 : VMA_DEBUG_MARGIN; }
+
+ void DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const;
+#if VMA_STATS_STRING_ENABLED
+ // mapRefCount == UINT32_MAX means unspecified.
+ void PrintDetailedMap_Begin(class VmaJsonWriter& json,
+ VkDeviceSize unusedBytes,
+ size_t allocationCount,
+ size_t unusedRangeCount) const;
+ void PrintDetailedMap_Allocation(class VmaJsonWriter& json,
+ VkDeviceSize offset, VkDeviceSize size, void* userData) const;
+ void PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
+ VkDeviceSize offset,
+ VkDeviceSize size) const;
+ void PrintDetailedMap_End(class VmaJsonWriter& json) const;
+#endif
+
+private:
+ VkDeviceSize m_Size;
+ const VkAllocationCallbacks* m_pAllocationCallbacks;
+ const VkDeviceSize m_BufferImageGranularity;
+ const bool m_IsVirtual;
+};
+
+#ifndef _VMA_BLOCK_METADATA_FUNCTIONS
+VmaBlockMetadata::VmaBlockMetadata(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual)
+ : m_Size(0),
+ m_pAllocationCallbacks(pAllocationCallbacks),
+ m_BufferImageGranularity(bufferImageGranularity),
+ m_IsVirtual(isVirtual) {}
+
+void VmaBlockMetadata::DebugLogAllocation(VkDeviceSize offset, VkDeviceSize size, void* userData) const
{
-}
+ if (IsVirtual())
+ {
+ VMA_DEBUG_LOG("UNFREED VIRTUAL ALLOCATION; Offset: %llu; Size: %llu; UserData: %p", offset, size, userData);
+ }
+ else
+ {
+ VMA_ASSERT(userData != VMA_NULL);
+ VmaAllocation allocation = reinterpret_cast<VmaAllocation>(userData);
+
+ userData = allocation->GetUserData();
+ const char* name = allocation->GetName();
#if VMA_STATS_STRING_ENABLED
+ VMA_DEBUG_LOG("UNFREED ALLOCATION; Offset: %llu; Size: %llu; UserData: %p; Name: %s; Type: %s; Usage: %u",
+ offset, size, userData, name ? name : "vma_empty",
+ VMA_SUBALLOCATION_TYPE_NAMES[allocation->GetSuballocationType()],
+ allocation->GetBufferImageUsage());
+#else
+ VMA_DEBUG_LOG("UNFREED ALLOCATION; Offset: %llu; Size: %llu; UserData: %p; Name: %s; Type: %u",
+ offset, size, userData, name ? name : "vma_empty",
+ (uint32_t)allocation->GetSuballocationType());
+#endif // VMA_STATS_STRING_ENABLED
+ }
+
+}
+#if VMA_STATS_STRING_ENABLED
void VmaBlockMetadata::PrintDetailedMap_Begin(class VmaJsonWriter& json,
- VkDeviceSize unusedBytes,
- size_t allocationCount,
- size_t unusedRangeCount) const
+ VkDeviceSize unusedBytes, size_t allocationCount, size_t unusedRangeCount) const
{
- json.BeginObject();
-
json.WriteString("TotalBytes");
json.WriteNumber(GetSize());
json.WriteString("UnusedBytes");
- json.WriteNumber(unusedBytes);
+ json.WriteSize(unusedBytes);
json.WriteString("Allocations");
- json.WriteNumber((uint64_t)allocationCount);
+ json.WriteSize(allocationCount);
json.WriteString("UnusedRanges");
- json.WriteNumber((uint64_t)unusedRangeCount);
+ json.WriteSize(unusedRangeCount);
json.WriteString("Suballocations");
json.BeginArray();
}
void VmaBlockMetadata::PrintDetailedMap_Allocation(class VmaJsonWriter& json,
- VkDeviceSize offset,
- VmaAllocation hAllocation) const
+ VkDeviceSize offset, VkDeviceSize size, void* userData) const
{
json.BeginObject(true);
json.WriteString("Offset");
json.WriteNumber(offset);
- hAllocation->PrintParameters(json);
+ if (IsVirtual())
+ {
+ json.WriteString("Size");
+ json.WriteNumber(size);
+ if (userData)
+ {
+ json.WriteString("CustomData");
+ json.BeginString();
+ json.ContinueString_Pointer(userData);
+ json.EndString();
+ }
+ }
+ else
+ {
+ ((VmaAllocation)userData)->PrintParameters(json);
+ }
json.EndObject();
}
void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
- VkDeviceSize offset,
- VkDeviceSize size) const
+ VkDeviceSize offset, VkDeviceSize size) const
{
json.BeginObject(true);
@@ -9368,26 +6487,340 @@ void VmaBlockMetadata::PrintDetailedMap_UnusedRange(class VmaJsonWriter& json,
void VmaBlockMetadata::PrintDetailedMap_End(class VmaJsonWriter& json) const
{
json.EndArray();
- json.EndObject();
}
+#endif // VMA_STATS_STRING_ENABLED
+#endif // _VMA_BLOCK_METADATA_FUNCTIONS
+#endif // _VMA_BLOCK_METADATA
-#endif // #if VMA_STATS_STRING_ENABLED
+#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY
+// Before deleting object of this class remember to call 'Destroy()'
+class VmaBlockBufferImageGranularity final
+{
+public:
+ struct ValidationContext
+ {
+ const VkAllocationCallbacks* allocCallbacks;
+ uint16_t* pageAllocs;
+ };
-////////////////////////////////////////////////////////////////////////////////
-// class VmaBlockMetadata_Generic
+ VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity);
+ ~VmaBlockBufferImageGranularity();
-VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(VmaAllocator hAllocator) :
- VmaBlockMetadata(hAllocator),
- m_FreeCount(0),
- m_SumFreeSize(0),
- m_Suballocations(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
- m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(hAllocator->GetAllocationCallbacks()))
+ bool IsEnabled() const { return m_BufferImageGranularity > MAX_LOW_BUFFER_IMAGE_GRANULARITY; }
+
+ void Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size);
+ // Before destroying object you must call free it's memory
+ void Destroy(const VkAllocationCallbacks* pAllocationCallbacks);
+
+ void RoundupAllocRequest(VmaSuballocationType allocType,
+ VkDeviceSize& inOutAllocSize,
+ VkDeviceSize& inOutAllocAlignment) const;
+
+ bool CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,
+ VkDeviceSize allocSize,
+ VkDeviceSize blockOffset,
+ VkDeviceSize blockSize,
+ VmaSuballocationType allocType) const;
+
+ void AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size);
+ void FreePages(VkDeviceSize offset, VkDeviceSize size);
+ void Clear();
+
+ ValidationContext StartValidation(const VkAllocationCallbacks* pAllocationCallbacks,
+ bool isVirutal) const;
+ bool Validate(ValidationContext& ctx, VkDeviceSize offset, VkDeviceSize size) const;
+ bool FinishValidation(ValidationContext& ctx) const;
+
+private:
+ static const uint16_t MAX_LOW_BUFFER_IMAGE_GRANULARITY = 256;
+
+ struct RegionInfo
+ {
+ uint8_t allocType;
+ uint16_t allocCount;
+ };
+
+ VkDeviceSize m_BufferImageGranularity;
+ uint32_t m_RegionCount;
+ RegionInfo* m_RegionInfo;
+
+ uint32_t GetStartPage(VkDeviceSize offset) const { return OffsetToPageIndex(offset & ~(m_BufferImageGranularity - 1)); }
+ uint32_t GetEndPage(VkDeviceSize offset, VkDeviceSize size) const { return OffsetToPageIndex((offset + size - 1) & ~(m_BufferImageGranularity - 1)); }
+
+ uint32_t OffsetToPageIndex(VkDeviceSize offset) const;
+ void AllocPage(RegionInfo& page, uint8_t allocType);
+};
+
+#ifndef _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS
+VmaBlockBufferImageGranularity::VmaBlockBufferImageGranularity(VkDeviceSize bufferImageGranularity)
+ : m_BufferImageGranularity(bufferImageGranularity),
+ m_RegionCount(0),
+ m_RegionInfo(VMA_NULL) {}
+
+VmaBlockBufferImageGranularity::~VmaBlockBufferImageGranularity()
+{
+ VMA_ASSERT(m_RegionInfo == VMA_NULL && "Free not called before destroying object!");
+}
+
+void VmaBlockBufferImageGranularity::Init(const VkAllocationCallbacks* pAllocationCallbacks, VkDeviceSize size)
+{
+ if (IsEnabled())
+ {
+ m_RegionCount = static_cast<uint32_t>(VmaDivideRoundingUp(size, m_BufferImageGranularity));
+ m_RegionInfo = vma_new_array(pAllocationCallbacks, RegionInfo, m_RegionCount);
+ memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo));
+ }
+}
+
+void VmaBlockBufferImageGranularity::Destroy(const VkAllocationCallbacks* pAllocationCallbacks)
+{
+ if (m_RegionInfo)
+ {
+ vma_delete_array(pAllocationCallbacks, m_RegionInfo, m_RegionCount);
+ m_RegionInfo = VMA_NULL;
+ }
+}
+
+void VmaBlockBufferImageGranularity::RoundupAllocRequest(VmaSuballocationType allocType,
+ VkDeviceSize& inOutAllocSize,
+ VkDeviceSize& inOutAllocAlignment) const
+{
+ if (m_BufferImageGranularity > 1 &&
+ m_BufferImageGranularity <= MAX_LOW_BUFFER_IMAGE_GRANULARITY)
+ {
+ if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
+ allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)
+ {
+ inOutAllocAlignment = VMA_MAX(inOutAllocAlignment, m_BufferImageGranularity);
+ inOutAllocSize = VmaAlignUp(inOutAllocSize, m_BufferImageGranularity);
+ }
+ }
+}
+
+bool VmaBlockBufferImageGranularity::CheckConflictAndAlignUp(VkDeviceSize& inOutAllocOffset,
+ VkDeviceSize allocSize,
+ VkDeviceSize blockOffset,
+ VkDeviceSize blockSize,
+ VmaSuballocationType allocType) const
+{
+ if (IsEnabled())
+ {
+ uint32_t startPage = GetStartPage(inOutAllocOffset);
+ if (m_RegionInfo[startPage].allocCount > 0 &&
+ VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[startPage].allocType), allocType))
+ {
+ inOutAllocOffset = VmaAlignUp(inOutAllocOffset, m_BufferImageGranularity);
+ if (blockSize < allocSize + inOutAllocOffset - blockOffset)
+ return true;
+ ++startPage;
+ }
+ uint32_t endPage = GetEndPage(inOutAllocOffset, allocSize);
+ if (endPage != startPage &&
+ m_RegionInfo[endPage].allocCount > 0 &&
+ VmaIsBufferImageGranularityConflict(static_cast<VmaSuballocationType>(m_RegionInfo[endPage].allocType), allocType))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void VmaBlockBufferImageGranularity::AllocPages(uint8_t allocType, VkDeviceSize offset, VkDeviceSize size)
+{
+ if (IsEnabled())
+ {
+ uint32_t startPage = GetStartPage(offset);
+ AllocPage(m_RegionInfo[startPage], allocType);
+
+ uint32_t endPage = GetEndPage(offset, size);
+ if (startPage != endPage)
+ AllocPage(m_RegionInfo[endPage], allocType);
+ }
+}
+
+void VmaBlockBufferImageGranularity::FreePages(VkDeviceSize offset, VkDeviceSize size)
+{
+ if (IsEnabled())
+ {
+ uint32_t startPage = GetStartPage(offset);
+ --m_RegionInfo[startPage].allocCount;
+ if (m_RegionInfo[startPage].allocCount == 0)
+ m_RegionInfo[startPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
+ uint32_t endPage = GetEndPage(offset, size);
+ if (startPage != endPage)
+ {
+ --m_RegionInfo[endPage].allocCount;
+ if (m_RegionInfo[endPage].allocCount == 0)
+ m_RegionInfo[endPage].allocType = VMA_SUBALLOCATION_TYPE_FREE;
+ }
+ }
+}
+
+void VmaBlockBufferImageGranularity::Clear()
+{
+ if (m_RegionInfo)
+ memset(m_RegionInfo, 0, m_RegionCount * sizeof(RegionInfo));
+}
+
+VmaBlockBufferImageGranularity::ValidationContext VmaBlockBufferImageGranularity::StartValidation(
+ const VkAllocationCallbacks* pAllocationCallbacks, bool isVirutal) const
+{
+ ValidationContext ctx{ pAllocationCallbacks, VMA_NULL };
+ if (!isVirutal && IsEnabled())
+ {
+ ctx.pageAllocs = vma_new_array(pAllocationCallbacks, uint16_t, m_RegionCount);
+ memset(ctx.pageAllocs, 0, m_RegionCount * sizeof(uint16_t));
+ }
+ return ctx;
+}
+
+bool VmaBlockBufferImageGranularity::Validate(ValidationContext& ctx,
+ VkDeviceSize offset, VkDeviceSize size) const
+{
+ if (IsEnabled())
+ {
+ uint32_t start = GetStartPage(offset);
+ ++ctx.pageAllocs[start];
+ VMA_VALIDATE(m_RegionInfo[start].allocCount > 0);
+
+ uint32_t end = GetEndPage(offset, size);
+ if (start != end)
+ {
+ ++ctx.pageAllocs[end];
+ VMA_VALIDATE(m_RegionInfo[end].allocCount > 0);
+ }
+ }
+ return true;
+}
+
+bool VmaBlockBufferImageGranularity::FinishValidation(ValidationContext& ctx) const
+{
+ // Check proper page structure
+ if (IsEnabled())
+ {
+ VMA_ASSERT(ctx.pageAllocs != VMA_NULL && "Validation context not initialized!");
+
+ for (uint32_t page = 0; page < m_RegionCount; ++page)
+ {
+ VMA_VALIDATE(ctx.pageAllocs[page] == m_RegionInfo[page].allocCount);
+ }
+ vma_delete_array(ctx.allocCallbacks, ctx.pageAllocs, m_RegionCount);
+ ctx.pageAllocs = VMA_NULL;
+ }
+ return true;
+}
+
+uint32_t VmaBlockBufferImageGranularity::OffsetToPageIndex(VkDeviceSize offset) const
{
+ return static_cast<uint32_t>(offset >> VMA_BITSCAN_MSB(m_BufferImageGranularity));
}
-VmaBlockMetadata_Generic::~VmaBlockMetadata_Generic()
+void VmaBlockBufferImageGranularity::AllocPage(RegionInfo& page, uint8_t allocType)
{
+ // When current alloc type is free then it can be overriden by new type
+ if (page.allocCount == 0 || (page.allocCount > 0 && page.allocType == VMA_SUBALLOCATION_TYPE_FREE))
+ page.allocType = allocType;
+
+ ++page.allocCount;
}
+#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY_FUNCTIONS
+#endif // _VMA_BLOCK_BUFFER_IMAGE_GRANULARITY
+
+#if 0
+#ifndef _VMA_BLOCK_METADATA_GENERIC
+class VmaBlockMetadata_Generic : public VmaBlockMetadata
+{
+ friend class VmaDefragmentationAlgorithm_Generic;
+ friend class VmaDefragmentationAlgorithm_Fast;
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Generic)
+public:
+ VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual);
+ virtual ~VmaBlockMetadata_Generic() = default;
+
+ size_t GetAllocationCount() const override { return m_Suballocations.size() - m_FreeCount; }
+ VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; }
+ bool IsEmpty() const override { return (m_Suballocations.size() == 1) && (m_FreeCount == 1); }
+ void Free(VmaAllocHandle allocHandle) override { FreeSuballocation(FindAtOffset((VkDeviceSize)allocHandle - 1)); }
+ VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; };
+
+ void Init(VkDeviceSize size) override;
+ bool Validate() const override;
+
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;
+ void AddStatistics(VmaStatistics& inoutStats) const override;
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const override;
+#endif
+
+ bool CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) override;
+
+ VkResult CheckCorruption(const void* pBlockData) override;
+
+ void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData) override;
+
+ void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;
+ void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;
+ VmaAllocHandle GetAllocationListBegin() const override;
+ VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;
+ void Clear() override;
+ void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;
+ void DebugLogAllAllocations() const override;
+
+private:
+ uint32_t m_FreeCount;
+ VkDeviceSize m_SumFreeSize;
+ VmaSuballocationList m_Suballocations;
+ // Suballocations that are free. Sorted by size, ascending.
+ VmaVector<VmaSuballocationList::iterator, VmaStlAllocator<VmaSuballocationList::iterator>> m_FreeSuballocationsBySize;
+
+ VkDeviceSize AlignAllocationSize(VkDeviceSize size) const { return IsVirtual() ? size : VmaAlignUp(size, (VkDeviceSize)16); }
+
+ VmaSuballocationList::iterator FindAtOffset(VkDeviceSize offset) const;
+ bool ValidateFreeSuballocationList() const;
+
+ // Checks if requested suballocation with given parameters can be placed in given pFreeSuballocItem.
+ // If yes, fills pOffset and returns true. If no, returns false.
+ bool CheckAllocation(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaSuballocationList::const_iterator suballocItem,
+ VmaAllocHandle* pAllocHandle) const;
+
+ // Given free suballocation, it merges it with following one, which must also be free.
+ void MergeFreeWithNext(VmaSuballocationList::iterator item);
+ // Releases given suballocation, making it free.
+ // Merges it with adjacent free suballocations if applicable.
+ // Returns iterator to new free suballocation at this place.
+ VmaSuballocationList::iterator FreeSuballocation(VmaSuballocationList::iterator suballocItem);
+ // Given free suballocation, it inserts it into sorted list of
+ // m_FreeSuballocationsBySize if it is suitable.
+ void RegisterFreeSuballocation(VmaSuballocationList::iterator item);
+ // Given free suballocation, it removes it from sorted list of
+ // m_FreeSuballocationsBySize if it is suitable.
+ void UnregisterFreeSuballocation(VmaSuballocationList::iterator item);
+};
+
+#ifndef _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS
+VmaBlockMetadata_Generic::VmaBlockMetadata_Generic(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual)
+ : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),
+ m_FreeCount(0),
+ m_SumFreeSize(0),
+ m_Suballocations(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),
+ m_FreeSuballocationsBySize(VmaStlAllocator<VmaSuballocationList::iterator>(pAllocationCallbacks)) {}
void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
{
@@ -9400,13 +6833,9 @@ void VmaBlockMetadata_Generic::Init(VkDeviceSize size)
suballoc.offset = 0;
suballoc.size = size;
suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- suballoc.hAllocation = VK_NULL_HANDLE;
- VMA_ASSERT(size > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
m_Suballocations.push_back(suballoc);
- VmaSuballocationList::iterator suballocItem = m_Suballocations.end();
- --suballocItem;
- m_FreeSuballocationsBySize.push_back(suballocItem);
+ m_FreeSuballocationsBySize.push_back(m_Suballocations.begin());
}
bool VmaBlockMetadata_Generic::Validate() const
@@ -9425,7 +6854,9 @@ bool VmaBlockMetadata_Generic::Validate() const
// True if previous visited suballocation was free.
bool prevFree = false;
- for(const auto& subAlloc : m_Suballocations)
+ const VkDeviceSize debugMargin = GetDebugMargin();
+
+ for (const auto& subAlloc : m_Suballocations)
{
// Actual offset of this suballocation doesn't match expected one.
VMA_VALIDATE(subAlloc.offset == calculatedOffset);
@@ -9434,27 +6865,31 @@ bool VmaBlockMetadata_Generic::Validate() const
// Two adjacent free suballocations are invalid. They should be merged.
VMA_VALIDATE(!prevFree || !currFree);
- VMA_VALIDATE(currFree == (subAlloc.hAllocation == VK_NULL_HANDLE));
+ VmaAllocation alloc = (VmaAllocation)subAlloc.userData;
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));
+ }
- if(currFree)
+ if (currFree)
{
calculatedSumFreeSize += subAlloc.size;
++calculatedFreeCount;
- if(subAlloc.size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
- {
- ++freeSuballocationsToRegister;
- }
+ ++freeSuballocationsToRegister;
// Margin required between allocations - every free space must be at least that large.
- VMA_VALIDATE(subAlloc.size >= VMA_DEBUG_MARGIN);
+ VMA_VALIDATE(subAlloc.size >= debugMargin);
}
else
{
- VMA_VALIDATE(subAlloc.hAllocation->GetOffset() == subAlloc.offset);
- VMA_VALIDATE(subAlloc.hAllocation->GetSize() == subAlloc.size);
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == subAlloc.offset + 1);
+ VMA_VALIDATE(alloc->GetSize() == subAlloc.size);
+ }
// Margin required between allocations - previous allocation must be free.
- VMA_VALIDATE(VMA_DEBUG_MARGIN == 0 || prevFree);
+ VMA_VALIDATE(debugMargin == 0 || prevFree);
}
calculatedOffset += subAlloc.size;
@@ -9466,7 +6901,7 @@ bool VmaBlockMetadata_Generic::Validate() const
VMA_VALIDATE(m_FreeSuballocationsBySize.size() == freeSuballocationsToRegister);
VkDeviceSize lastSize = 0;
- for(size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
+ for (size_t i = 0; i < m_FreeSuballocationsBySize.size(); ++i)
{
VmaSuballocationList::iterator suballocItem = m_FreeSuballocationsBySize[i];
@@ -9487,101 +6922,59 @@ bool VmaBlockMetadata_Generic::Validate() const
return true;
}
-VkDeviceSize VmaBlockMetadata_Generic::GetUnusedRangeSizeMax() const
+void VmaBlockMetadata_Generic::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const
{
- if(!m_FreeSuballocationsBySize.empty())
- {
- return m_FreeSuballocationsBySize.back()->size;
- }
- else
- {
- return 0;
- }
-}
-
-bool VmaBlockMetadata_Generic::IsEmpty() const
-{
- return (m_Suballocations.size() == 1) && (m_FreeCount == 1);
-}
-
-void VmaBlockMetadata_Generic::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
-{
- outInfo.blockCount = 1;
-
const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
- outInfo.allocationCount = rangeCount - m_FreeCount;
- outInfo.unusedRangeCount = m_FreeCount;
-
- outInfo.unusedBytes = m_SumFreeSize;
- outInfo.usedBytes = GetSize() - outInfo.unusedBytes;
+ inoutStats.statistics.blockCount++;
+ inoutStats.statistics.blockBytes += GetSize();
- outInfo.allocationSizeMin = UINT64_MAX;
- outInfo.allocationSizeMax = 0;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMax = 0;
-
- for(const auto& suballoc : m_Suballocations)
+ for (const auto& suballoc : m_Suballocations)
{
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
- {
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, suballoc.size);
- }
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);
else
- {
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, suballoc.size);
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, suballoc.size);
- }
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, suballoc.size);
}
}
-void VmaBlockMetadata_Generic::AddPoolStats(VmaPoolStats& inoutStats) const
+void VmaBlockMetadata_Generic::AddStatistics(VmaStatistics& inoutStats) const
{
- const uint32_t rangeCount = (uint32_t)m_Suballocations.size();
-
- inoutStats.size += GetSize();
- inoutStats.unusedSize += m_SumFreeSize;
- inoutStats.allocationCount += rangeCount - m_FreeCount;
- inoutStats.unusedRangeCount += m_FreeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
+ inoutStats.blockCount++;
+ inoutStats.allocationCount += (uint32_t)m_Suballocations.size() - m_FreeCount;
+ inoutStats.blockBytes += GetSize();
+ inoutStats.allocationBytes += GetSize() - m_SumFreeSize;
}
#if VMA_STATS_STRING_ENABLED
-
-void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json) const
+void VmaBlockMetadata_Generic::PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const
{
PrintDetailedMap_Begin(json,
m_SumFreeSize, // unusedBytes
m_Suballocations.size() - (size_t)m_FreeCount, // allocationCount
- m_FreeCount); // unusedRangeCount
+ m_FreeCount, // unusedRangeCount
+ mapRefCount);
- size_t i = 0;
- for(const auto& suballoc : m_Suballocations)
+ for (const auto& suballoc : m_Suballocations)
{
- if(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
+ if (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
{
PrintDetailedMap_UnusedRange(json, suballoc.offset, suballoc.size);
}
else
{
- PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);
}
}
PrintDetailedMap_End(json);
}
-
-#endif // #if VMA_STATS_STRING_ENABLED
+#endif // VMA_STATS_STRING_ENABLED
bool VmaBlockMetadata_Generic::CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
bool upperAddress,
VmaSuballocationType allocType,
- bool canMakeOtherLost,
uint32_t strategy,
VmaAllocationRequest* pAllocationRequest)
{
@@ -9591,92 +6984,77 @@ bool VmaBlockMetadata_Generic::CreateAllocationRequest(
VMA_ASSERT(pAllocationRequest != VMA_NULL);
VMA_HEAVY_ASSERT(Validate());
+ allocSize = AlignAllocationSize(allocSize);
+
pAllocationRequest->type = VmaAllocationRequestType::Normal;
+ pAllocationRequest->size = allocSize;
- // There is not enough total free space in this block to fullfill the request: Early return.
- if(canMakeOtherLost == false &&
- m_SumFreeSize < allocSize + 2 * VMA_DEBUG_MARGIN)
+ const VkDeviceSize debugMargin = GetDebugMargin();
+
+ // There is not enough total free space in this block to fulfill the request: Early return.
+ if (m_SumFreeSize < allocSize + debugMargin)
{
return false;
}
// New algorithm, efficiently searching freeSuballocationsBySize.
const size_t freeSuballocCount = m_FreeSuballocationsBySize.size();
- if(freeSuballocCount > 0)
+ if (freeSuballocCount > 0)
{
- if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ if (strategy == 0 ||
+ strategy == VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT)
{
- // Find first free suballocation with size not less than allocSize + 2 * VMA_DEBUG_MARGIN.
+ // Find first free suballocation with size not less than allocSize + debugMargin.
VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
m_FreeSuballocationsBySize.data(),
m_FreeSuballocationsBySize.data() + freeSuballocCount,
- allocSize + 2 * VMA_DEBUG_MARGIN,
+ allocSize + debugMargin,
VmaSuballocationItemSizeLess());
size_t index = it - m_FreeSuballocationsBySize.data();
- for(; index < freeSuballocCount; ++index)
+ for (; index < freeSuballocCount; ++index)
{
- if(CheckAllocation(
- currentFrameIndex,
- frameInUseCount,
- bufferImageGranularity,
+ if (CheckAllocation(
allocSize,
allocAlignment,
allocType,
m_FreeSuballocationsBySize[index],
- false, // canMakeOtherLost
- &pAllocationRequest->offset,
- &pAllocationRequest->itemsToMakeLostCount,
- &pAllocationRequest->sumFreeSize,
- &pAllocationRequest->sumItemSize))
+ &pAllocationRequest->allocHandle))
{
pAllocationRequest->item = m_FreeSuballocationsBySize[index];
return true;
}
}
}
- else if(strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)
+ else if (strategy == VMA_ALLOCATION_INTERNAL_STRATEGY_MIN_OFFSET)
{
- for(VmaSuballocationList::iterator it = m_Suballocations.begin();
+ for (VmaSuballocationList::iterator it = m_Suballocations.begin();
it != m_Suballocations.end();
++it)
{
- if(it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(
- currentFrameIndex,
- frameInUseCount,
- bufferImageGranularity,
+ if (it->type == VMA_SUBALLOCATION_TYPE_FREE && CheckAllocation(
allocSize,
allocAlignment,
allocType,
it,
- false, // canMakeOtherLost
- &pAllocationRequest->offset,
- &pAllocationRequest->itemsToMakeLostCount,
- &pAllocationRequest->sumFreeSize,
- &pAllocationRequest->sumItemSize))
+ &pAllocationRequest->allocHandle))
{
pAllocationRequest->item = it;
return true;
}
}
}
- else // WORST_FIT, FIRST_FIT
+ else
{
+ VMA_ASSERT(strategy & (VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT | VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT ));
// Search staring from biggest suballocations.
- for(size_t index = freeSuballocCount; index--; )
+ for (size_t index = freeSuballocCount; index--; )
{
- if(CheckAllocation(
- currentFrameIndex,
- frameInUseCount,
- bufferImageGranularity,
+ if (CheckAllocation(
allocSize,
allocAlignment,
allocType,
m_FreeSuballocationsBySize[index],
- false, // canMakeOtherLost
- &pAllocationRequest->offset,
- &pAllocationRequest->itemsToMakeLostCount,
- &pAllocationRequest->sumFreeSize,
- &pAllocationRequest->sumItemSize))
+ &pAllocationRequest->allocHandle))
{
pAllocationRequest->item = m_FreeSuballocationsBySize[index];
return true;
@@ -9685,123 +7063,19 @@ bool VmaBlockMetadata_Generic::CreateAllocationRequest(
}
}
- if(canMakeOtherLost)
- {
- // Brute-force algorithm. TODO: Come up with something better.
-
- bool found = false;
- VmaAllocationRequest tmpAllocRequest = {};
- tmpAllocRequest.type = VmaAllocationRequestType::Normal;
- for(VmaSuballocationList::iterator suballocIt = m_Suballocations.begin();
- suballocIt != m_Suballocations.end();
- ++suballocIt)
- {
- if(suballocIt->type == VMA_SUBALLOCATION_TYPE_FREE ||
- suballocIt->hAllocation->CanBecomeLost())
- {
- if(CheckAllocation(
- currentFrameIndex,
- frameInUseCount,
- bufferImageGranularity,
- allocSize,
- allocAlignment,
- allocType,
- suballocIt,
- canMakeOtherLost,
- &tmpAllocRequest.offset,
- &tmpAllocRequest.itemsToMakeLostCount,
- &tmpAllocRequest.sumFreeSize,
- &tmpAllocRequest.sumItemSize))
- {
- if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
- {
- *pAllocationRequest = tmpAllocRequest;
- pAllocationRequest->item = suballocIt;
- break;
- }
- if(!found || tmpAllocRequest.CalcCost() < pAllocationRequest->CalcCost())
- {
- *pAllocationRequest = tmpAllocRequest;
- pAllocationRequest->item = suballocIt;
- found = true;
- }
- }
- }
- }
-
- return found;
- }
-
return false;
}
-bool VmaBlockMetadata_Generic::MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest)
-{
- VMA_ASSERT(pAllocationRequest && pAllocationRequest->type == VmaAllocationRequestType::Normal);
-
- while(pAllocationRequest->itemsToMakeLostCount > 0)
- {
- if(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE)
- {
- ++pAllocationRequest->item;
- }
- VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
- VMA_ASSERT(pAllocationRequest->item->hAllocation != VK_NULL_HANDLE);
- VMA_ASSERT(pAllocationRequest->item->hAllocation->CanBecomeLost());
- if(pAllocationRequest->item->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
- {
- pAllocationRequest->item = FreeSuballocation(pAllocationRequest->item);
- --pAllocationRequest->itemsToMakeLostCount;
- }
- else
- {
- return false;
- }
- }
-
- VMA_HEAVY_ASSERT(Validate());
- VMA_ASSERT(pAllocationRequest->item != m_Suballocations.end());
- VMA_ASSERT(pAllocationRequest->item->type == VMA_SUBALLOCATION_TYPE_FREE);
-
- return true;
-}
-
-uint32_t VmaBlockMetadata_Generic::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
-{
- uint32_t lostAllocationCount = 0;
- for(VmaSuballocationList::iterator it = m_Suballocations.begin();
- it != m_Suballocations.end();
- ++it)
- {
- if(it->type != VMA_SUBALLOCATION_TYPE_FREE &&
- it->hAllocation->CanBecomeLost() &&
- it->hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
- {
- it = FreeSuballocation(it);
- ++lostAllocationCount;
- }
- }
- return lostAllocationCount;
-}
-
VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
{
- for(auto& suballoc : m_Suballocations)
+ for (auto& suballoc : m_Suballocations)
{
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
{
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
- {
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
{
VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ return VK_ERROR_UNKNOWN_COPY;
}
}
}
@@ -9812,34 +7086,34 @@ VkResult VmaBlockMetadata_Generic::CheckCorruption(const void* pBlockData)
void VmaBlockMetadata_Generic::Alloc(
const VmaAllocationRequest& request,
VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation)
+ void* userData)
{
VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
VMA_ASSERT(request.item != m_Suballocations.end());
VmaSuballocation& suballoc = *request.item;
// Given suballocation is a free block.
VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
+
// Given offset is inside this suballocation.
- VMA_ASSERT(request.offset >= suballoc.offset);
- const VkDeviceSize paddingBegin = request.offset - suballoc.offset;
- VMA_ASSERT(suballoc.size >= paddingBegin + allocSize);
- const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - allocSize;
+ VMA_ASSERT((VkDeviceSize)request.allocHandle - 1 >= suballoc.offset);
+ const VkDeviceSize paddingBegin = (VkDeviceSize)request.allocHandle - suballoc.offset - 1;
+ VMA_ASSERT(suballoc.size >= paddingBegin + request.size);
+ const VkDeviceSize paddingEnd = suballoc.size - paddingBegin - request.size;
// Unregister this free suballocation from m_FreeSuballocationsBySize and update
// it to become used.
UnregisterFreeSuballocation(request.item);
- suballoc.offset = request.offset;
- suballoc.size = allocSize;
+ suballoc.offset = (VkDeviceSize)request.allocHandle - 1;
+ suballoc.size = request.size;
suballoc.type = type;
- suballoc.hAllocation = hAllocation;
+ suballoc.userData = userData;
// If there are any free bytes remaining at the end, insert new free suballocation after current one.
- if(paddingEnd)
+ if (paddingEnd)
{
VmaSuballocation paddingSuballoc = {};
- paddingSuballoc.offset = request.offset + allocSize;
+ paddingSuballoc.offset = suballoc.offset + suballoc.size;
paddingSuballoc.size = paddingEnd;
paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
VmaSuballocationList::iterator next = request.item;
@@ -9850,10 +7124,10 @@ void VmaBlockMetadata_Generic::Alloc(
}
// If there are any free bytes remaining at the beginning, insert new free suballocation before current one.
- if(paddingBegin)
+ if (paddingBegin)
{
VmaSuballocation paddingSuballoc = {};
- paddingSuballoc.offset = request.offset - paddingBegin;
+ paddingSuballoc.offset = suballoc.offset - paddingBegin;
paddingSuballoc.size = paddingBegin;
paddingSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
const VmaSuballocationList::iterator paddingBeginItem =
@@ -9863,59 +7137,130 @@ void VmaBlockMetadata_Generic::Alloc(
// Update totals.
m_FreeCount = m_FreeCount - 1;
- if(paddingBegin > 0)
+ if (paddingBegin > 0)
{
++m_FreeCount;
}
- if(paddingEnd > 0)
+ if (paddingEnd > 0)
{
++m_FreeCount;
}
- m_SumFreeSize -= allocSize;
+ m_SumFreeSize -= request.size;
}
-void VmaBlockMetadata_Generic::Free(const VmaAllocation allocation)
+void VmaBlockMetadata_Generic::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
{
- for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
- suballocItem != m_Suballocations.end();
- ++suballocItem)
+ outInfo.offset = (VkDeviceSize)allocHandle - 1;
+ const VmaSuballocation& suballoc = *FindAtOffset(outInfo.offset);
+ outInfo.size = suballoc.size;
+ outInfo.pUserData = suballoc.userData;
+}
+
+void* VmaBlockMetadata_Generic::GetAllocationUserData(VmaAllocHandle allocHandle) const
+{
+ return FindAtOffset((VkDeviceSize)allocHandle - 1)->userData;
+}
+
+VmaAllocHandle VmaBlockMetadata_Generic::GetAllocationListBegin() const
+{
+ if (IsEmpty())
+ return VK_NULL_HANDLE;
+
+ for (const auto& suballoc : m_Suballocations)
{
- VmaSuballocation& suballoc = *suballocItem;
- if(suballoc.hAllocation == allocation)
- {
- FreeSuballocation(suballocItem);
- VMA_HEAVY_ASSERT(Validate());
- return;
- }
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ return (VmaAllocHandle)(suballoc.offset + 1);
+ }
+ VMA_ASSERT(false && "Should contain at least 1 allocation!");
+ return VK_NULL_HANDLE;
+}
+
+VmaAllocHandle VmaBlockMetadata_Generic::GetNextAllocation(VmaAllocHandle prevAlloc) const
+{
+ VmaSuballocationList::const_iterator prev = FindAtOffset((VkDeviceSize)prevAlloc - 1);
+
+ for (VmaSuballocationList::const_iterator it = ++prev; it != m_Suballocations.end(); ++it)
+ {
+ if (it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ return (VmaAllocHandle)(it->offset + 1);
+ }
+ return VK_NULL_HANDLE;
+}
+
+void VmaBlockMetadata_Generic::Clear()
+{
+ const VkDeviceSize size = GetSize();
+
+ VMA_ASSERT(IsVirtual());
+ m_FreeCount = 1;
+ m_SumFreeSize = size;
+ m_Suballocations.clear();
+ m_FreeSuballocationsBySize.clear();
+
+ VmaSuballocation suballoc = {};
+ suballoc.offset = 0;
+ suballoc.size = size;
+ suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ m_Suballocations.push_back(suballoc);
+
+ m_FreeSuballocationsBySize.push_back(m_Suballocations.begin());
+}
+
+void VmaBlockMetadata_Generic::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
+{
+ VmaSuballocation& suballoc = *FindAtOffset((VkDeviceSize)allocHandle - 1);
+ suballoc.userData = userData;
+}
+
+void VmaBlockMetadata_Generic::DebugLogAllAllocations() const
+{
+ for (const auto& suballoc : m_Suballocations)
+ {
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ DebugLogAllocation(suballoc.offset, suballoc.size, suballoc.userData);
}
- VMA_ASSERT(0 && "Not found!");
}
-void VmaBlockMetadata_Generic::FreeAtOffset(VkDeviceSize offset)
+VmaSuballocationList::iterator VmaBlockMetadata_Generic::FindAtOffset(VkDeviceSize offset) const
{
- for(VmaSuballocationList::iterator suballocItem = m_Suballocations.begin();
- suballocItem != m_Suballocations.end();
- ++suballocItem)
+ VMA_HEAVY_ASSERT(!m_Suballocations.empty());
+ const VkDeviceSize last = m_Suballocations.rbegin()->offset;
+ if (last == offset)
+ return m_Suballocations.rbegin().drop_const();
+ const VkDeviceSize first = m_Suballocations.begin()->offset;
+ if (first == offset)
+ return m_Suballocations.begin().drop_const();
+
+ const size_t suballocCount = m_Suballocations.size();
+ const VkDeviceSize step = (last - first + m_Suballocations.begin()->size) / suballocCount;
+ auto findSuballocation = [&](auto begin, auto end) -> VmaSuballocationList::iterator
{
- VmaSuballocation& suballoc = *suballocItem;
- if(suballoc.offset == offset)
+ for (auto suballocItem = begin;
+ suballocItem != end;
+ ++suballocItem)
{
- FreeSuballocation(suballocItem);
- return;
+ if (suballocItem->offset == offset)
+ return suballocItem.drop_const();
}
+ VMA_ASSERT(false && "Not found!");
+ return m_Suballocations.end().drop_const();
+ };
+ // If requested offset is closer to the end of range, search from the end
+ if (offset - first > suballocCount * step / 2)
+ {
+ return findSuballocation(m_Suballocations.rbegin(), m_Suballocations.rend());
}
- VMA_ASSERT(0 && "Not found!");
+ return findSuballocation(m_Suballocations.begin(), m_Suballocations.end());
}
bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
{
VkDeviceSize lastSize = 0;
- for(size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
+ for (size_t i = 0, count = m_FreeSuballocationsBySize.size(); i < count; ++i)
{
const VmaSuballocationList::iterator it = m_FreeSuballocationsBySize[i];
VMA_VALIDATE(it->type == VMA_SUBALLOCATION_TYPE_FREE);
- VMA_VALIDATE(it->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER);
VMA_VALIDATE(it->size >= lastSize);
lastSize = it->size;
}
@@ -9923,276 +7268,105 @@ bool VmaBlockMetadata_Generic::ValidateFreeSuballocationList() const
}
bool VmaBlockMetadata_Generic::CheckAllocation(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
VmaSuballocationType allocType,
VmaSuballocationList::const_iterator suballocItem,
- bool canMakeOtherLost,
- VkDeviceSize* pOffset,
- size_t* itemsToMakeLostCount,
- VkDeviceSize* pSumFreeSize,
- VkDeviceSize* pSumItemSize) const
+ VmaAllocHandle* pAllocHandle) const
{
VMA_ASSERT(allocSize > 0);
VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
VMA_ASSERT(suballocItem != m_Suballocations.cend());
- VMA_ASSERT(pOffset != VMA_NULL);
+ VMA_ASSERT(pAllocHandle != VMA_NULL);
- *itemsToMakeLostCount = 0;
- *pSumFreeSize = 0;
- *pSumItemSize = 0;
+ const VkDeviceSize debugMargin = GetDebugMargin();
+ const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();
- if(canMakeOtherLost)
- {
- if(suballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
- {
- *pSumFreeSize = suballocItem->size;
- }
- else
- {
- if(suballocItem->hAllocation->CanBecomeLost() &&
- suballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
- {
- ++*itemsToMakeLostCount;
- *pSumItemSize = suballocItem->size;
- }
- else
- {
- return false;
- }
- }
+ const VmaSuballocation& suballoc = *suballocItem;
+ VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
- // Remaining size is too small for this request: Early return.
- if(GetSize() - suballocItem->offset < allocSize)
- {
- return false;
- }
+ // Size of this suballocation is too small for this request: Early return.
+ if (suballoc.size < allocSize)
+ {
+ return false;
+ }
- // Start from offset equal to beginning of this suballocation.
- *pOffset = suballocItem->offset;
+ // Start from offset equal to beginning of this suballocation.
+ VkDeviceSize offset = suballoc.offset + (suballocItem == m_Suballocations.cbegin() ? 0 : GetDebugMargin());
- // Apply VMA_DEBUG_MARGIN at the beginning.
- if(VMA_DEBUG_MARGIN > 0)
- {
- *pOffset += VMA_DEBUG_MARGIN;
- }
+ // Apply debugMargin from the end of previous alloc.
+ if (debugMargin > 0)
+ {
+ offset += debugMargin;
+ }
- // Apply alignment.
- *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+ // Apply alignment.
+ offset = VmaAlignUp(offset, allocAlignment);
- // Check previous suballocations for BufferImageGranularity conflicts.
- // Make bigger alignment if necessary.
- if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)
+ {
+ bool bufferImageGranularityConflict = false;
+ VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
+ while (prevSuballocItem != m_Suballocations.cbegin())
{
- bool bufferImageGranularityConflict = false;
- VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
- while(prevSuballocItem != m_Suballocations.cbegin())
+ --prevSuballocItem;
+ const VmaSuballocation& prevSuballoc = *prevSuballocItem;
+ if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, offset, bufferImageGranularity))
{
- --prevSuballocItem;
- const VmaSuballocation& prevSuballoc = *prevSuballocItem;
- if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
{
- if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
- {
- bufferImageGranularityConflict = true;
- break;
- }
- }
- else
- // Already on previous page.
+ bufferImageGranularityConflict = true;
break;
- }
- if(bufferImageGranularityConflict)
- {
- *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
- }
- }
-
- // Now that we have final *pOffset, check if we are past suballocItem.
- // If yes, return false - this function should be called for another suballocItem as starting point.
- if(*pOffset >= suballocItem->offset + suballocItem->size)
- {
- return false;
- }
-
- // Calculate padding at the beginning based on current offset.
- const VkDeviceSize paddingBegin = *pOffset - suballocItem->offset;
-
- // Calculate required margin at the end.
- const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
-
- const VkDeviceSize totalSize = paddingBegin + allocSize + requiredEndMargin;
- // Another early return check.
- if(suballocItem->offset + totalSize > GetSize())
- {
- return false;
- }
-
- // Advance lastSuballocItem until desired size is reached.
- // Update itemsToMakeLostCount.
- VmaSuballocationList::const_iterator lastSuballocItem = suballocItem;
- if(totalSize > suballocItem->size)
- {
- VkDeviceSize remainingSize = totalSize - suballocItem->size;
- while(remainingSize > 0)
- {
- ++lastSuballocItem;
- if(lastSuballocItem == m_Suballocations.cend())
- {
- return false;
- }
- if(lastSuballocItem->type == VMA_SUBALLOCATION_TYPE_FREE)
- {
- *pSumFreeSize += lastSuballocItem->size;
}
- else
- {
- VMA_ASSERT(lastSuballocItem->hAllocation != VK_NULL_HANDLE);
- if(lastSuballocItem->hAllocation->CanBecomeLost() &&
- lastSuballocItem->hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
- {
- ++*itemsToMakeLostCount;
- *pSumItemSize += lastSuballocItem->size;
- }
- else
- {
- return false;
- }
- }
- remainingSize = (lastSuballocItem->size < remainingSize) ?
- remainingSize - lastSuballocItem->size : 0;
}
+ else
+ // Already on previous page.
+ break;
}
-
- // Check next suballocations for BufferImageGranularity conflicts.
- // If conflict exists, we must mark more allocations lost or fail.
- if(allocSize % bufferImageGranularity || *pOffset % bufferImageGranularity)
+ if (bufferImageGranularityConflict)
{
- VmaSuballocationList::const_iterator nextSuballocItem = lastSuballocItem;
- ++nextSuballocItem;
- while(nextSuballocItem != m_Suballocations.cend())
- {
- const VmaSuballocation& nextSuballoc = *nextSuballocItem;
- if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
- {
- if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
- {
- VMA_ASSERT(nextSuballoc.hAllocation != VK_NULL_HANDLE);
- if(nextSuballoc.hAllocation->CanBecomeLost() &&
- nextSuballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
- {
- ++*itemsToMakeLostCount;
- }
- else
- {
- return false;
- }
- }
- }
- else
- {
- // Already on next page.
- break;
- }
- ++nextSuballocItem;
- }
+ offset = VmaAlignUp(offset, bufferImageGranularity);
}
}
- else
- {
- const VmaSuballocation& suballoc = *suballocItem;
- VMA_ASSERT(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
-
- *pSumFreeSize = suballoc.size;
-
- // Size of this suballocation is too small for this request: Early return.
- if(suballoc.size < allocSize)
- {
- return false;
- }
-
- // Start from offset equal to beginning of this suballocation.
- *pOffset = suballoc.offset;
- // Apply VMA_DEBUG_MARGIN at the beginning.
- if(VMA_DEBUG_MARGIN > 0)
- {
- *pOffset += VMA_DEBUG_MARGIN;
- }
+ // Calculate padding at the beginning based on current offset.
+ const VkDeviceSize paddingBegin = offset - suballoc.offset;
- // Apply alignment.
- *pOffset = VmaAlignUp(*pOffset, allocAlignment);
+ // Fail if requested size plus margin after is bigger than size of this suballocation.
+ if (paddingBegin + allocSize + debugMargin > suballoc.size)
+ {
+ return false;
+ }
- // Check previous suballocations for BufferImageGranularity conflicts.
- // Make bigger alignment if necessary.
- if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment)
+ // Check next suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if (allocSize % bufferImageGranularity || offset % bufferImageGranularity)
+ {
+ VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
+ ++nextSuballocItem;
+ while (nextSuballocItem != m_Suballocations.cend())
{
- bool bufferImageGranularityConflict = false;
- VmaSuballocationList::const_iterator prevSuballocItem = suballocItem;
- while(prevSuballocItem != m_Suballocations.cbegin())
+ const VmaSuballocation& nextSuballoc = *nextSuballocItem;
+ if (VmaBlocksOnSamePage(offset, allocSize, nextSuballoc.offset, bufferImageGranularity))
{
- --prevSuballocItem;
- const VmaSuballocation& prevSuballoc = *prevSuballocItem;
- if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, *pOffset, bufferImageGranularity))
+ if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
{
- if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
- {
- bufferImageGranularityConflict = true;
- break;
- }
+ return false;
}
- else
- // Already on previous page.
- break;
}
- if(bufferImageGranularityConflict)
+ else
{
- *pOffset = VmaAlignUp(*pOffset, bufferImageGranularity);
+ // Already on next page.
+ break;
}
- }
-
- // Calculate padding at the beginning based on current offset.
- const VkDeviceSize paddingBegin = *pOffset - suballoc.offset;
-
- // Calculate required margin at the end.
- const VkDeviceSize requiredEndMargin = VMA_DEBUG_MARGIN;
-
- // Fail if requested size plus margin before and after is bigger than size of this suballocation.
- if(paddingBegin + allocSize + requiredEndMargin > suballoc.size)
- {
- return false;
- }
-
- // Check next suballocations for BufferImageGranularity conflicts.
- // If conflict exists, allocation cannot be made here.
- if(allocSize % bufferImageGranularity || *pOffset % bufferImageGranularity)
- {
- VmaSuballocationList::const_iterator nextSuballocItem = suballocItem;
++nextSuballocItem;
- while(nextSuballocItem != m_Suballocations.cend())
- {
- const VmaSuballocation& nextSuballoc = *nextSuballocItem;
- if(VmaBlocksOnSamePage(*pOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
- {
- if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
- {
- return false;
- }
- }
- else
- {
- // Already on next page.
- break;
- }
- ++nextSuballocItem;
- }
}
}
- // All tests passed: Success. pOffset is already filled.
+ *pAllocHandle = (VmaAllocHandle)(offset + 1);
+ // All tests passed: Success. pAllocHandle is already filled.
return true;
}
@@ -10216,7 +7390,7 @@ VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSu
// Change this suballocation to be marked as free.
VmaSuballocation& suballoc = *suballocItem;
suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- suballoc.hAllocation = VK_NULL_HANDLE;
+ suballoc.userData = VMA_NULL;
// Update totals.
++m_FreeCount;
@@ -10228,28 +7402,28 @@ VmaSuballocationList::iterator VmaBlockMetadata_Generic::FreeSuballocation(VmaSu
VmaSuballocationList::iterator nextItem = suballocItem;
++nextItem;
- if((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))
+ if ((nextItem != m_Suballocations.end()) && (nextItem->type == VMA_SUBALLOCATION_TYPE_FREE))
{
mergeWithNext = true;
}
VmaSuballocationList::iterator prevItem = suballocItem;
- if(suballocItem != m_Suballocations.begin())
+ if (suballocItem != m_Suballocations.begin())
{
--prevItem;
- if(prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)
+ if (prevItem->type == VMA_SUBALLOCATION_TYPE_FREE)
{
mergeWithPrev = true;
}
}
- if(mergeWithNext)
+ if (mergeWithNext)
{
UnregisterFreeSuballocation(nextItem);
MergeFreeWithNext(suballocItem);
}
- if(mergeWithPrev)
+ if (mergeWithPrev)
{
UnregisterFreeSuballocation(prevItem);
MergeFreeWithNext(prevItem);
@@ -10272,22 +7446,18 @@ void VmaBlockMetadata_Generic::RegisterFreeSuballocation(VmaSuballocationList::i
// this function, depending on what do you want to check.
VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
- if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ if (m_FreeSuballocationsBySize.empty())
{
- if(m_FreeSuballocationsBySize.empty())
- {
- m_FreeSuballocationsBySize.push_back(item);
- }
- else
- {
- VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);
- }
+ m_FreeSuballocationsBySize.push_back(item);
+ }
+ else
+ {
+ VmaVectorInsertSorted<VmaSuballocationItemSizeLess>(m_FreeSuballocationsBySize, item);
}
//VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
}
-
void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList::iterator item)
{
VMA_ASSERT(item->type == VMA_SUBALLOCATION_TYPE_FREE);
@@ -10297,77 +7467,230 @@ void VmaBlockMetadata_Generic::UnregisterFreeSuballocation(VmaSuballocationList:
// this function, depending on what do you want to check.
VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
- if(item->size >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
+ m_FreeSuballocationsBySize.data(),
+ m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
+ item,
+ VmaSuballocationItemSizeLess());
+ for (size_t index = it - m_FreeSuballocationsBySize.data();
+ index < m_FreeSuballocationsBySize.size();
+ ++index)
{
- VmaSuballocationList::iterator* const it = VmaBinaryFindFirstNotLess(
- m_FreeSuballocationsBySize.data(),
- m_FreeSuballocationsBySize.data() + m_FreeSuballocationsBySize.size(),
- item,
- VmaSuballocationItemSizeLess());
- for(size_t index = it - m_FreeSuballocationsBySize.data();
- index < m_FreeSuballocationsBySize.size();
- ++index)
+ if (m_FreeSuballocationsBySize[index] == item)
{
- if(m_FreeSuballocationsBySize[index] == item)
- {
- VmaVectorRemove(m_FreeSuballocationsBySize, index);
- return;
- }
- VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
+ VmaVectorRemove(m_FreeSuballocationsBySize, index);
+ return;
}
- VMA_ASSERT(0 && "Not found.");
+ VMA_ASSERT((m_FreeSuballocationsBySize[index]->size == item->size) && "Not found.");
}
+ VMA_ASSERT(0 && "Not found.");
//VMA_HEAVY_ASSERT(ValidateFreeSuballocationList());
}
+#endif // _VMA_BLOCK_METADATA_GENERIC_FUNCTIONS
+#endif // _VMA_BLOCK_METADATA_GENERIC
+#endif // #if 0
-bool VmaBlockMetadata_Generic::IsBufferImageGranularityConflictPossible(
- VkDeviceSize bufferImageGranularity,
- VmaSuballocationType& inOutPrevSuballocType) const
+#ifndef _VMA_BLOCK_METADATA_LINEAR
+/*
+Allocations and their references in internal data structure look like this:
+
+if(m_2ndVectorMode == SECOND_VECTOR_EMPTY):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER):
+
+ 0 +-------+
+ | Alloc | 2nd[0]
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+GetSize() +-------+
+
+if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK):
+
+ 0 +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount]
+ +-------+
+ | Alloc | 1st[m_1stNullItemsBeginCount + 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 1st[1st.size() - 1]
+ +-------+
+ | |
+ | |
+ | |
+ +-------+
+ | Alloc | 2nd[2nd.size() - 1]
+ +-------+
+ | ... |
+ +-------+
+ | Alloc | 2nd[1]
+ +-------+
+ | Alloc | 2nd[0]
+GetSize() +-------+
+
+*/
+class VmaBlockMetadata_Linear : public VmaBlockMetadata
{
- if(bufferImageGranularity == 1 || IsEmpty())
- {
- return false;
- }
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Linear)
+public:
+ VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual);
+ virtual ~VmaBlockMetadata_Linear() = default;
+
+ VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize; }
+ bool IsEmpty() const override { return GetAllocationCount() == 0; }
+ VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; };
+
+ void Init(VkDeviceSize size) override;
+ bool Validate() const override;
+ size_t GetAllocationCount() const override;
+ size_t GetFreeRegionsCount() const override;
+
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;
+ void AddStatistics(VmaStatistics& inoutStats) const override;
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json) const override;
+#endif
+
+ bool CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) override;
+
+ VkResult CheckCorruption(const void* pBlockData) override;
+
+ void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData) override;
+
+ void Free(VmaAllocHandle allocHandle) override;
+ void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;
+ void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;
+ VmaAllocHandle GetAllocationListBegin() const override;
+ VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;
+ VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override;
+ void Clear() override;
+ void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;
+ void DebugLogAllAllocations() const override;
- VkDeviceSize minAlignment = VK_WHOLE_SIZE;
- bool typeConflictFound = false;
- for(const auto& suballoc : m_Suballocations)
+private:
+ /*
+ There are two suballocation vectors, used in ping-pong way.
+ The one with index m_1stVectorIndex is called 1st.
+ The one with index (m_1stVectorIndex ^ 1) is called 2nd.
+ 2nd can be non-empty only when 1st is not empty.
+ When 2nd is not empty, m_2ndVectorMode indicates its mode of operation.
+ */
+ typedef VmaVector<VmaSuballocation, VmaStlAllocator<VmaSuballocation>> SuballocationVectorType;
+
+ enum SECOND_VECTOR_MODE
{
- const VmaSuballocationType suballocType = suballoc.type;
- if(suballocType != VMA_SUBALLOCATION_TYPE_FREE)
- {
- minAlignment = VMA_MIN(minAlignment, suballoc.hAllocation->GetAlignment());
- if(VmaIsBufferImageGranularityConflict(inOutPrevSuballocType, suballocType))
- {
- typeConflictFound = true;
- }
- inOutPrevSuballocType = suballocType;
- }
- }
+ SECOND_VECTOR_EMPTY,
+ /*
+ Suballocations in 2nd vector are created later than the ones in 1st, but they
+ all have smaller offset.
+ */
+ SECOND_VECTOR_RING_BUFFER,
+ /*
+ Suballocations in 2nd vector are upper side of double stack.
+ They all have offsets higher than those in 1st vector.
+ Top of this stack means smaller offsets, but higher indices in this vector.
+ */
+ SECOND_VECTOR_DOUBLE_STACK,
+ };
- return typeConflictFound || minAlignment >= bufferImageGranularity;
-}
+ VkDeviceSize m_SumFreeSize;
+ SuballocationVectorType m_Suballocations0, m_Suballocations1;
+ uint32_t m_1stVectorIndex;
+ SECOND_VECTOR_MODE m_2ndVectorMode;
+ // Number of items in 1st vector with hAllocation = null at the beginning.
+ size_t m_1stNullItemsBeginCount;
+ // Number of other items in 1st vector with hAllocation = null somewhere in the middle.
+ size_t m_1stNullItemsMiddleCount;
+ // Number of items in 2nd vector with hAllocation = null.
+ size_t m_2ndNullItemsCount;
-////////////////////////////////////////////////////////////////////////////////
-// class VmaBlockMetadata_Linear
+ SuballocationVectorType& AccessSuballocations1st() { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ SuballocationVectorType& AccessSuballocations2nd() { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+ const SuballocationVectorType& AccessSuballocations1st() const { return m_1stVectorIndex ? m_Suballocations1 : m_Suballocations0; }
+ const SuballocationVectorType& AccessSuballocations2nd() const { return m_1stVectorIndex ? m_Suballocations0 : m_Suballocations1; }
+
+ VmaSuballocation& FindSuballocation(VkDeviceSize offset) const;
+ bool ShouldCompact1st() const;
+ void CleanupAfterFree();
-VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(VmaAllocator hAllocator) :
- VmaBlockMetadata(hAllocator),
+ bool CreateAllocationRequest_LowerAddress(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+ bool CreateAllocationRequest_UpperAddress(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest);
+};
+
+#ifndef _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS
+VmaBlockMetadata_Linear::VmaBlockMetadata_Linear(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual)
+ : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),
m_SumFreeSize(0),
- m_Suballocations0(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
- m_Suballocations1(VmaStlAllocator<VmaSuballocation>(hAllocator->GetAllocationCallbacks())),
+ m_Suballocations0(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),
+ m_Suballocations1(VmaStlAllocator<VmaSuballocation>(pAllocationCallbacks)),
m_1stVectorIndex(0),
m_2ndVectorMode(SECOND_VECTOR_EMPTY),
m_1stNullItemsBeginCount(0),
m_1stNullItemsMiddleCount(0),
- m_2ndNullItemsCount(0)
-{
-}
-
-VmaBlockMetadata_Linear::~VmaBlockMetadata_Linear()
-{
-}
+ m_2ndNullItemsCount(0) {}
void VmaBlockMetadata_Linear::Init(VkDeviceSize size)
{
@@ -10385,17 +7708,17 @@ bool VmaBlockMetadata_Linear::Validate() const
suballocations2nd.empty() ||
m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER);
- if(!suballocations1st.empty())
+ if (!suballocations1st.empty())
{
// Null item at the beginning should be accounted into m_1stNullItemsBeginCount.
- VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].hAllocation != VK_NULL_HANDLE);
+ VMA_VALIDATE(suballocations1st[m_1stNullItemsBeginCount].type != VMA_SUBALLOCATION_TYPE_FREE);
// Null item at the end should be just pop_back().
- VMA_VALIDATE(suballocations1st.back().hAllocation != VK_NULL_HANDLE);
+ VMA_VALIDATE(suballocations1st.back().type != VMA_SUBALLOCATION_TYPE_FREE);
}
- if(!suballocations2nd.empty())
+ if (!suballocations2nd.empty())
{
// Null item at the end should be just pop_back().
- VMA_VALIDATE(suballocations2nd.back().hAllocation != VK_NULL_HANDLE);
+ VMA_VALIDATE(suballocations2nd.back().type != VMA_SUBALLOCATION_TYPE_FREE);
}
VMA_VALIDATE(m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount <= suballocations1st.size());
@@ -10403,24 +7726,32 @@ bool VmaBlockMetadata_Linear::Validate() const
VkDeviceSize sumUsedSize = 0;
const size_t suballoc1stCount = suballocations1st.size();
- VkDeviceSize offset = VMA_DEBUG_MARGIN;
+ const VkDeviceSize debugMargin = GetDebugMargin();
+ VkDeviceSize offset = 0;
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
const size_t suballoc2ndCount = suballocations2nd.size();
size_t nullItem2ndCount = 0;
- for(size_t i = 0; i < suballoc2ndCount; ++i)
+ for (size_t i = 0; i < suballoc2ndCount; ++i)
{
const VmaSuballocation& suballoc = suballocations2nd[i];
const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
- VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VmaAllocation const alloc = (VmaAllocation)suballoc.userData;
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));
+ }
VMA_VALIDATE(suballoc.offset >= offset);
- if(!currFree)
+ if (!currFree)
{
- VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
- VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);
+ VMA_VALIDATE(alloc->GetSize() == suballoc.size);
+ }
sumUsedSize += suballoc.size;
}
else
@@ -10428,34 +7759,41 @@ bool VmaBlockMetadata_Linear::Validate() const
++nullItem2ndCount;
}
- offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ offset = suballoc.offset + suballoc.size + debugMargin;
}
VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
}
- for(size_t i = 0; i < m_1stNullItemsBeginCount; ++i)
+ for (size_t i = 0; i < m_1stNullItemsBeginCount; ++i)
{
const VmaSuballocation& suballoc = suballocations1st[i];
VMA_VALIDATE(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE &&
- suballoc.hAllocation == VK_NULL_HANDLE);
+ suballoc.userData == VMA_NULL);
}
size_t nullItem1stCount = m_1stNullItemsBeginCount;
- for(size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)
+ for (size_t i = m_1stNullItemsBeginCount; i < suballoc1stCount; ++i)
{
const VmaSuballocation& suballoc = suballocations1st[i];
const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
- VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VmaAllocation const alloc = (VmaAllocation)suballoc.userData;
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));
+ }
VMA_VALIDATE(suballoc.offset >= offset);
VMA_VALIDATE(i >= m_1stNullItemsBeginCount || currFree);
- if(!currFree)
+ if (!currFree)
{
- VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
- VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);
+ VMA_VALIDATE(alloc->GetSize() == suballoc.size);
+ }
sumUsedSize += suballoc.size;
}
else
@@ -10463,26 +7801,33 @@ bool VmaBlockMetadata_Linear::Validate() const
++nullItem1stCount;
}
- offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ offset = suballoc.offset + suballoc.size + debugMargin;
}
VMA_VALIDATE(nullItem1stCount == m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount);
- if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
const size_t suballoc2ndCount = suballocations2nd.size();
size_t nullItem2ndCount = 0;
- for(size_t i = suballoc2ndCount; i--; )
+ for (size_t i = suballoc2ndCount; i--; )
{
const VmaSuballocation& suballoc = suballocations2nd[i];
const bool currFree = (suballoc.type == VMA_SUBALLOCATION_TYPE_FREE);
- VMA_VALIDATE(currFree == (suballoc.hAllocation == VK_NULL_HANDLE));
+ VmaAllocation const alloc = (VmaAllocation)suballoc.userData;
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(currFree == (alloc == VK_NULL_HANDLE));
+ }
VMA_VALIDATE(suballoc.offset >= offset);
- if(!currFree)
+ if (!currFree)
{
- VMA_VALIDATE(suballoc.hAllocation->GetOffset() == suballoc.offset);
- VMA_VALIDATE(suballoc.hAllocation->GetSize() == suballoc.size);
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE((VkDeviceSize)alloc->GetAllocHandle() == suballoc.offset + 1);
+ VMA_VALIDATE(alloc->GetSize() == suballoc.size);
+ }
sumUsedSize += suballoc.size;
}
else
@@ -10490,7 +7835,7 @@ bool VmaBlockMetadata_Linear::Validate() const
++nullItem2ndCount;
}
- offset = suballoc.offset + suballoc.size + VMA_DEBUG_MARGIN;
+ offset = suballoc.offset + suballoc.size + debugMargin;
}
VMA_VALIDATE(nullItem2ndCount == m_2ndNullItemsCount);
@@ -10504,75 +7849,18 @@ bool VmaBlockMetadata_Linear::Validate() const
size_t VmaBlockMetadata_Linear::GetAllocationCount() const
{
- return AccessSuballocations1st().size() - (m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount) +
+ return AccessSuballocations1st().size() - m_1stNullItemsBeginCount - m_1stNullItemsMiddleCount +
AccessSuballocations2nd().size() - m_2ndNullItemsCount;
}
-VkDeviceSize VmaBlockMetadata_Linear::GetUnusedRangeSizeMax() const
+size_t VmaBlockMetadata_Linear::GetFreeRegionsCount() const
{
- const VkDeviceSize size = GetSize();
-
- /*
- We don't consider gaps inside allocation vectors with freed allocations because
- they are not suitable for reuse in linear allocator. We consider only space that
- is available for new allocations.
- */
- if(IsEmpty())
- {
- return size;
- }
-
- const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
-
- switch(m_2ndVectorMode)
- {
- case SECOND_VECTOR_EMPTY:
- /*
- Available space is after end of 1st, as well as before beginning of 1st (which
- would make it a ring buffer).
- */
- {
- const size_t suballocations1stCount = suballocations1st.size();
- VMA_ASSERT(suballocations1stCount > m_1stNullItemsBeginCount);
- const VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
- const VmaSuballocation& lastSuballoc = suballocations1st[suballocations1stCount - 1];
- return VMA_MAX(
- firstSuballoc.offset,
- size - (lastSuballoc.offset + lastSuballoc.size));
- }
- break;
-
- case SECOND_VECTOR_RING_BUFFER:
- /*
- Available space is only between end of 2nd and beginning of 1st.
- */
- {
- const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- const VmaSuballocation& lastSuballoc2nd = suballocations2nd.back();
- const VmaSuballocation& firstSuballoc1st = suballocations1st[m_1stNullItemsBeginCount];
- return firstSuballoc1st.offset - (lastSuballoc2nd.offset + lastSuballoc2nd.size);
- }
- break;
-
- case SECOND_VECTOR_DOUBLE_STACK:
- /*
- Available space is only between end of 1st and top of 2nd.
- */
- {
- const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- const VmaSuballocation& topSuballoc2nd = suballocations2nd.back();
- const VmaSuballocation& lastSuballoc1st = suballocations1st.back();
- return topSuballoc2nd.offset - (lastSuballoc1st.offset + lastSuballoc1st.size);
- }
- break;
-
- default:
- VMA_ASSERT(0);
- return 0;
- }
+ // Function only used for defragmentation, which is disabled for this algorithm
+ VMA_ASSERT(0);
+ return SIZE_MAX;
}
-void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
+void VmaBlockMetadata_Linear::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const
{
const VkDeviceSize size = GetSize();
const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
@@ -10580,51 +7868,40 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
const size_t suballoc1stCount = suballocations1st.size();
const size_t suballoc2ndCount = suballocations2nd.size();
- outInfo.blockCount = 1;
- outInfo.allocationCount = (uint32_t)GetAllocationCount();
- outInfo.unusedRangeCount = 0;
- outInfo.usedBytes = 0;
- outInfo.allocationSizeMin = UINT64_MAX;
- outInfo.allocationSizeMax = 0;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMax = 0;
+ inoutStats.statistics.blockCount++;
+ inoutStats.statistics.blockBytes += size;
VkDeviceSize lastOffset = 0;
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
size_t nextAlloc2ndIndex = 0;
- while(lastOffset < freeSpace2ndTo1stEnd)
+ while (lastOffset < freeSpace2ndTo1stEnd)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc2ndIndex < suballoc2ndCount &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
++nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex < suballoc2ndCount)
+ if (nextAlloc2ndIndex < suballoc2ndCount)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -10634,14 +7911,11 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
else
{
// There is free space from lastOffset to freeSpace2ndTo1stEnd.
- if(lastOffset < freeSpace2ndTo1stEnd)
+ if (lastOffset < freeSpace2ndTo1stEnd)
{
const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
- }
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
+ }
// End of loop.
lastOffset = freeSpace2ndTo1stEnd;
@@ -10652,36 +7926,31 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
const VkDeviceSize freeSpace1stTo2ndEnd =
m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
- while(lastOffset < freeSpace1stTo2ndEnd)
+ while (lastOffset < freeSpace1stTo2ndEnd)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc1stIndex < suballoc1stCount &&
- suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)
{
++nextAlloc1stIndex;
}
// Found non-null allocation.
- if(nextAlloc1stIndex < suballoc1stCount)
+ if (nextAlloc1stIndex < suballoc1stCount)
{
const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -10691,53 +7960,45 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
else
{
// There is free space from lastOffset to freeSpace1stTo2ndEnd.
- if(lastOffset < freeSpace1stTo2ndEnd)
+ if (lastOffset < freeSpace1stTo2ndEnd)
{
const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
- }
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
+ }
// End of loop.
lastOffset = freeSpace1stTo2ndEnd;
}
}
- if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
- while(lastOffset < size)
+ while (lastOffset < size)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc2ndIndex != SIZE_MAX &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
--nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex != SIZE_MAX)
+ if (nextAlloc2ndIndex != SIZE_MAX)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
}
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- outInfo.usedBytes += suballoc.size;
- outInfo.allocationSizeMin = VMA_MIN(outInfo.allocationSizeMin, suballoc.size);
- outInfo.allocationSizeMax = VMA_MIN(outInfo.allocationSizeMax, suballoc.size);
+ VmaAddDetailedStatisticsAllocation(inoutStats, suballoc.size);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -10747,25 +8008,20 @@ void VmaBlockMetadata_Linear::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
else
{
// There is free space from lastOffset to size.
- if(lastOffset < size)
+ if (lastOffset < size)
{
const VkDeviceSize unusedRangeSize = size - lastOffset;
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusedRangeSize);
- outInfo.unusedRangeSizeMax = VMA_MIN(outInfo.unusedRangeSizeMax, unusedRangeSize);
- }
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusedRangeSize);
+ }
// End of loop.
lastOffset = size;
}
}
}
-
- outInfo.unusedBytes = size - outInfo.usedBytes;
}
-void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
+void VmaBlockMetadata_Linear::AddStatistics(VmaStatistics& inoutStats) const
{
const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
@@ -10773,36 +8029,35 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
const size_t suballoc1stCount = suballocations1st.size();
const size_t suballoc2ndCount = suballocations2nd.size();
- inoutStats.size += size;
+ inoutStats.blockCount++;
+ inoutStats.blockBytes += size;
+ inoutStats.allocationBytes += size - m_SumFreeSize;
VkDeviceSize lastOffset = 0;
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
size_t nextAlloc2ndIndex = m_1stNullItemsBeginCount;
- while(lastOffset < freeSpace2ndTo1stEnd)
+ while (lastOffset < freeSpace2ndTo1stEnd)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex < suballoc2ndCount &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
++nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex < suballoc2ndCount)
+ if (nextAlloc2ndIndex < suballoc2ndCount)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// 2. Process this allocation.
@@ -10816,13 +8071,10 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
// We are at the end.
else
{
- if(lastOffset < freeSpace2ndTo1stEnd)
+ if (lastOffset < freeSpace2ndTo1stEnd)
{
// There is free space from lastOffset to freeSpace2ndTo1stEnd.
const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// End of loop.
@@ -10834,28 +8086,25 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
size_t nextAlloc1stIndex = m_1stNullItemsBeginCount;
const VkDeviceSize freeSpace1stTo2ndEnd =
m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
- while(lastOffset < freeSpace1stTo2ndEnd)
+ while (lastOffset < freeSpace1stTo2ndEnd)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc1stIndex < suballoc1stCount &&
- suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)
{
++nextAlloc1stIndex;
}
// Found non-null allocation.
- if(nextAlloc1stIndex < suballoc1stCount)
+ if (nextAlloc1stIndex < suballoc1stCount)
{
const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// 2. Process this allocation.
@@ -10869,13 +8118,10 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
// We are at the end.
else
{
- if(lastOffset < freeSpace1stTo2ndEnd)
+ if (lastOffset < freeSpace1stTo2ndEnd)
{
// There is free space from lastOffset to freeSpace1stTo2ndEnd.
const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// End of loop.
@@ -10883,31 +8129,28 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
}
}
- if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
- while(lastOffset < size)
+ while (lastOffset < size)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex != SIZE_MAX &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
--nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex != SIZE_MAX)
+ if (nextAlloc2ndIndex != SIZE_MAX)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// 2. Process this allocation.
@@ -10921,13 +8164,10 @@ void VmaBlockMetadata_Linear::AddPoolStats(VmaPoolStats& inoutStats) const
// We are at the end.
else
{
- if(lastOffset < size)
+ if (lastOffset < size)
{
// There is free space from lastOffset to size.
const VkDeviceSize unusedRangeSize = size - lastOffset;
- inoutStats.unusedSize += unusedRangeSize;
- ++inoutStats.unusedRangeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, unusedRangeSize);
}
// End of loop.
@@ -10954,26 +8194,26 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
VkDeviceSize lastOffset = 0;
size_t alloc2ndCount = 0;
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
size_t nextAlloc2ndIndex = 0;
- while(lastOffset < freeSpace2ndTo1stEnd)
+ while (lastOffset < freeSpace2ndTo1stEnd)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex < suballoc2ndCount &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
++nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex < suballoc2ndCount)
+ if (nextAlloc2ndIndex < suballoc2ndCount)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
++unusedRangeCount;
@@ -10991,7 +8231,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < freeSpace2ndTo1stEnd)
+ if (lastOffset < freeSpace2ndTo1stEnd)
{
// There is free space from lastOffset to freeSpace2ndTo1stEnd.
++unusedRangeCount;
@@ -11007,22 +8247,22 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
size_t alloc1stCount = 0;
const VkDeviceSize freeSpace1stTo2ndEnd =
m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ? suballocations2nd.back().offset : size;
- while(lastOffset < freeSpace1stTo2ndEnd)
+ while (lastOffset < freeSpace1stTo2ndEnd)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc1stIndex < suballoc1stCount &&
- suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)
{
++nextAlloc1stIndex;
}
// Found non-null allocation.
- if(nextAlloc1stIndex < suballoc1stCount)
+ if (nextAlloc1stIndex < suballoc1stCount)
{
const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
++unusedRangeCount;
@@ -11040,7 +8280,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < size)
+ if (lastOffset < size)
{
// There is free space from lastOffset to freeSpace1stTo2ndEnd.
++unusedRangeCount;
@@ -11051,25 +8291,25 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
}
}
- if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
- while(lastOffset < size)
+ while (lastOffset < size)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex != SIZE_MAX &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
--nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex != SIZE_MAX)
+ if (nextAlloc2ndIndex != SIZE_MAX)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
++unusedRangeCount;
@@ -11087,7 +8327,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < size)
+ if (lastOffset < size)
{
// There is free space from lastOffset to size.
++unusedRangeCount;
@@ -11105,26 +8345,26 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// SECOND PASS
lastOffset = 0;
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
const VkDeviceSize freeSpace2ndTo1stEnd = suballocations1st[m_1stNullItemsBeginCount].offset;
size_t nextAlloc2ndIndex = 0;
- while(lastOffset < freeSpace2ndTo1stEnd)
+ while (lastOffset < freeSpace2ndTo1stEnd)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex < suballoc2ndCount &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex < suballoc2ndCount &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
++nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex < suballoc2ndCount)
+ if (nextAlloc2ndIndex < suballoc2ndCount)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
@@ -11133,7 +8373,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -11142,7 +8382,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < freeSpace2ndTo1stEnd)
+ if (lastOffset < freeSpace2ndTo1stEnd)
{
// There is free space from lastOffset to freeSpace2ndTo1stEnd.
const VkDeviceSize unusedRangeSize = freeSpace2ndTo1stEnd - lastOffset;
@@ -11156,22 +8396,22 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
}
nextAlloc1stIndex = m_1stNullItemsBeginCount;
- while(lastOffset < freeSpace1stTo2ndEnd)
+ while (lastOffset < freeSpace1stTo2ndEnd)
{
// Find next non-null allocation or move nextAllocIndex to the end.
- while(nextAlloc1stIndex < suballoc1stCount &&
- suballocations1st[nextAlloc1stIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc1stIndex < suballoc1stCount &&
+ suballocations1st[nextAlloc1stIndex].userData == VMA_NULL)
{
++nextAlloc1stIndex;
}
// Found non-null allocation.
- if(nextAlloc1stIndex < suballoc1stCount)
+ if (nextAlloc1stIndex < suballoc1stCount)
{
const VmaSuballocation& suballoc = suballocations1st[nextAlloc1stIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
@@ -11180,7 +8420,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -11189,7 +8429,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < freeSpace1stTo2ndEnd)
+ if (lastOffset < freeSpace1stTo2ndEnd)
{
// There is free space from lastOffset to freeSpace1stTo2ndEnd.
const VkDeviceSize unusedRangeSize = freeSpace1stTo2ndEnd - lastOffset;
@@ -11201,25 +8441,25 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
}
}
- if(m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
size_t nextAlloc2ndIndex = suballocations2nd.size() - 1;
- while(lastOffset < size)
+ while (lastOffset < size)
{
// Find next non-null allocation or move nextAlloc2ndIndex to the end.
- while(nextAlloc2ndIndex != SIZE_MAX &&
- suballocations2nd[nextAlloc2ndIndex].hAllocation == VK_NULL_HANDLE)
+ while (nextAlloc2ndIndex != SIZE_MAX &&
+ suballocations2nd[nextAlloc2ndIndex].userData == VMA_NULL)
{
--nextAlloc2ndIndex;
}
// Found non-null allocation.
- if(nextAlloc2ndIndex != SIZE_MAX)
+ if (nextAlloc2ndIndex != SIZE_MAX)
{
const VmaSuballocation& suballoc = suballocations2nd[nextAlloc2ndIndex];
// 1. Process free space before this allocation.
- if(lastOffset < suballoc.offset)
+ if (lastOffset < suballoc.offset)
{
// There is free space from lastOffset to suballoc.offset.
const VkDeviceSize unusedRangeSize = suballoc.offset - lastOffset;
@@ -11228,7 +8468,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// 2. Process this allocation.
// There is allocation with suballoc.offset, suballoc.size.
- PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.hAllocation);
+ PrintDetailedMap_Allocation(json, suballoc.offset, suballoc.size, suballoc.userData);
// 3. Prepare for next iteration.
lastOffset = suballoc.offset + suballoc.size;
@@ -11237,7 +8477,7 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
// We are at the end.
else
{
- if(lastOffset < size)
+ if (lastOffset < size)
{
// There is free space from lastOffset to size.
const VkDeviceSize unusedRangeSize = size - lastOffset;
@@ -11252,17 +8492,13 @@ void VmaBlockMetadata_Linear::PrintDetailedMap(class VmaJsonWriter& json) const
PrintDetailedMap_End(json);
}
-#endif // #if VMA_STATS_STRING_ENABLED
+#endif // VMA_STATS_STRING_ENABLED
bool VmaBlockMetadata_Linear::CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
bool upperAddress,
VmaSuballocationType allocType,
- bool canMakeOtherLost,
uint32_t strategy,
VmaAllocationRequest* pAllocationRequest)
{
@@ -11270,184 +8506,460 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest(
VMA_ASSERT(allocType != VMA_SUBALLOCATION_TYPE_FREE);
VMA_ASSERT(pAllocationRequest != VMA_NULL);
VMA_HEAVY_ASSERT(Validate());
+ pAllocationRequest->size = allocSize;
return upperAddress ?
CreateAllocationRequest_UpperAddress(
- currentFrameIndex, frameInUseCount, bufferImageGranularity,
- allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest) :
+ allocSize, allocAlignment, allocType, strategy, pAllocationRequest) :
CreateAllocationRequest_LowerAddress(
- currentFrameIndex, frameInUseCount, bufferImageGranularity,
- allocSize, allocAlignment, allocType, canMakeOtherLost, strategy, pAllocationRequest);
+ allocSize, allocAlignment, allocType, strategy, pAllocationRequest);
}
-bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
- VkDeviceSize allocSize,
- VkDeviceSize allocAlignment,
- VmaSuballocationType allocType,
- bool canMakeOtherLost,
- uint32_t strategy,
- VmaAllocationRequest* pAllocationRequest)
+VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)
{
- const VkDeviceSize size = GetSize();
+ VMA_ASSERT(!IsVirtual());
SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for (size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations1st[i];
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_UNKNOWN_COPY;
+ }
+ }
+ }
+
SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for (size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ {
+ const VmaSuballocation& suballoc = suballocations2nd[i];
+ if (suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ if (!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_UNKNOWN_COPY;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+void VmaBlockMetadata_Linear::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData)
+{
+ const VkDeviceSize offset = (VkDeviceSize)request.allocHandle - 1;
+ const VmaSuballocation newSuballoc = { offset, request.size, userData, type };
+
+ switch (request.type)
{
- VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.");
- return false;
+ case VmaAllocationRequestType::UpperAddress:
+ {
+ VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&
+ "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.");
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ suballocations2nd.push_back(newSuballoc);
+ m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;
}
+ break;
+ case VmaAllocationRequestType::EndOf1st:
+ {
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- // Try to allocate before 2nd.back(), or end of block if 2nd.empty().
- if(allocSize > size)
+ VMA_ASSERT(suballocations1st.empty() ||
+ offset >= suballocations1st.back().offset + suballocations1st.back().size);
+ // Check if it fits before the end of the block.
+ VMA_ASSERT(offset + request.size <= GetSize());
+
+ suballocations1st.push_back(newSuballoc);
+ }
+ break;
+ case VmaAllocationRequestType::EndOf2nd:
{
- return false;
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.
+ VMA_ASSERT(!suballocations1st.empty() &&
+ offset + request.size <= suballocations1st[m_1stNullItemsBeginCount].offset);
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ switch (m_2ndVectorMode)
+ {
+ case SECOND_VECTOR_EMPTY:
+ // First allocation from second part ring buffer.
+ VMA_ASSERT(suballocations2nd.empty());
+ m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;
+ break;
+ case SECOND_VECTOR_RING_BUFFER:
+ // 2-part ring buffer is already started.
+ VMA_ASSERT(!suballocations2nd.empty());
+ break;
+ case SECOND_VECTOR_DOUBLE_STACK:
+ VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.");
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+
+ suballocations2nd.push_back(newSuballoc);
+ }
+ break;
+ default:
+ VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR.");
}
- VkDeviceSize resultBaseOffset = size - allocSize;
- if(!suballocations2nd.empty())
+
+ m_SumFreeSize -= newSuballoc.size;
+}
+
+void VmaBlockMetadata_Linear::Free(VmaAllocHandle allocHandle)
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ VkDeviceSize offset = (VkDeviceSize)allocHandle - 1;
+
+ if (!suballocations1st.empty())
{
- const VmaSuballocation& lastSuballoc = suballocations2nd.back();
- resultBaseOffset = lastSuballoc.offset - allocSize;
- if(allocSize > lastSuballoc.offset)
+ // First allocation: Mark it as next empty at the beginning.
+ VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
+ if (firstSuballoc.offset == offset)
{
- return false;
+ firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
+ firstSuballoc.userData = VMA_NULL;
+ m_SumFreeSize += firstSuballoc.size;
+ ++m_1stNullItemsBeginCount;
+ CleanupAfterFree();
+ return;
}
}
- // Start from offset equal to end of free space.
- VkDeviceSize resultOffset = resultBaseOffset;
+ // Last allocation in 2-part ring buffer or top of upper stack (same logic).
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||
+ m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ {
+ VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ if (lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations2nd.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+ // Last allocation in 1st vector.
+ else if (m_2ndVectorMode == SECOND_VECTOR_EMPTY)
+ {
+ VmaSuballocation& lastSuballoc = suballocations1st.back();
+ if (lastSuballoc.offset == offset)
+ {
+ m_SumFreeSize += lastSuballoc.size;
+ suballocations1st.pop_back();
+ CleanupAfterFree();
+ return;
+ }
+ }
+
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
- // Apply VMA_DEBUG_MARGIN at the end.
- if(VMA_DEBUG_MARGIN > 0)
+ // Item from the middle of 1st vector.
{
- if(resultOffset < VMA_DEBUG_MARGIN)
+ const SuballocationVectorType::iterator it = VmaBinaryFindSorted(
+ suballocations1st.begin() + m_1stNullItemsBeginCount,
+ suballocations1st.end(),
+ refSuballoc,
+ VmaSuballocationOffsetLess());
+ if (it != suballocations1st.end())
{
- return false;
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->userData = VMA_NULL;
+ ++m_1stNullItemsMiddleCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
}
- resultOffset -= VMA_DEBUG_MARGIN;
}
- // Apply alignment.
- resultOffset = VmaAlignDown(resultOffset, allocAlignment);
+ if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)
+ {
+ // Item from the middle of 2nd vector.
+ const SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());
+ if (it != suballocations2nd.end())
+ {
+ it->type = VMA_SUBALLOCATION_TYPE_FREE;
+ it->userData = VMA_NULL;
+ ++m_2ndNullItemsCount;
+ m_SumFreeSize += it->size;
+ CleanupAfterFree();
+ return;
+ }
+ }
- // Check next suballocations from 2nd for BufferImageGranularity conflicts.
- // Make bigger alignment if necessary.
- if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())
+ VMA_ASSERT(0 && "Allocation to free not found in linear allocator!");
+}
+
+void VmaBlockMetadata_Linear::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
+{
+ outInfo.offset = (VkDeviceSize)allocHandle - 1;
+ VmaSuballocation& suballoc = FindSuballocation(outInfo.offset);
+ outInfo.size = suballoc.size;
+ outInfo.pUserData = suballoc.userData;
+}
+
+void* VmaBlockMetadata_Linear::GetAllocationUserData(VmaAllocHandle allocHandle) const
+{
+ return FindSuballocation((VkDeviceSize)allocHandle - 1).userData;
+}
+
+VmaAllocHandle VmaBlockMetadata_Linear::GetAllocationListBegin() const
+{
+ // Function only used for defragmentation, which is disabled for this algorithm
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+}
+
+VmaAllocHandle VmaBlockMetadata_Linear::GetNextAllocation(VmaAllocHandle prevAlloc) const
+{
+ // Function only used for defragmentation, which is disabled for this algorithm
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+}
+
+VkDeviceSize VmaBlockMetadata_Linear::GetNextFreeRegionSize(VmaAllocHandle alloc) const
+{
+ // Function only used for defragmentation, which is disabled for this algorithm
+ VMA_ASSERT(0);
+ return 0;
+}
+
+void VmaBlockMetadata_Linear::Clear()
+{
+ m_SumFreeSize = GetSize();
+ m_Suballocations0.clear();
+ m_Suballocations1.clear();
+ // Leaving m_1stVectorIndex unchanged - it doesn't matter.
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ m_2ndNullItemsCount = 0;
+}
+
+void VmaBlockMetadata_Linear::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
+{
+ VmaSuballocation& suballoc = FindSuballocation((VkDeviceSize)allocHandle - 1);
+ suballoc.userData = userData;
+}
+
+void VmaBlockMetadata_Linear::DebugLogAllAllocations() const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ for (auto it = suballocations1st.begin() + m_1stNullItemsBeginCount; it != suballocations1st.end(); ++it)
+ if (it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ DebugLogAllocation(it->offset, it->size, it->userData);
+
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ for (auto it = suballocations2nd.begin(); it != suballocations2nd.end(); ++it)
+ if (it->type != VMA_SUBALLOCATION_TYPE_FREE)
+ DebugLogAllocation(it->offset, it->size, it->userData);
+}
+
+VmaSuballocation& VmaBlockMetadata_Linear::FindSuballocation(VkDeviceSize offset) const
+{
+ const SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ const SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ VmaSuballocation refSuballoc;
+ refSuballoc.offset = offset;
+ // Rest of members stays uninitialized intentionally for better performance.
+
+ // Item from the 1st vector.
{
- bool bufferImageGranularityConflict = false;
- for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ SuballocationVectorType::const_iterator it = VmaBinaryFindSorted(
+ suballocations1st.begin() + m_1stNullItemsBeginCount,
+ suballocations1st.end(),
+ refSuballoc,
+ VmaSuballocationOffsetLess());
+ if (it != suballocations1st.end())
{
- const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
- if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
- {
- if(VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))
- {
- bufferImageGranularityConflict = true;
- break;
- }
- }
- else
- // Already on previous page.
- break;
+ return const_cast<VmaSuballocation&>(*it);
}
- if(bufferImageGranularityConflict)
+ }
+
+ if (m_2ndVectorMode != SECOND_VECTOR_EMPTY)
+ {
+ // Rest of members stays uninitialized intentionally for better performance.
+ SuballocationVectorType::const_iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :
+ VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());
+ if (it != suballocations2nd.end())
{
- resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);
+ return const_cast<VmaSuballocation&>(*it);
}
}
- // There is enough free space.
- const VkDeviceSize endOf1st = !suballocations1st.empty() ?
- suballocations1st.back().offset + suballocations1st.back().size :
- 0;
- if(endOf1st + VMA_DEBUG_MARGIN <= resultOffset)
+ VMA_ASSERT(0 && "Allocation not found in linear allocator!");
+ return const_cast<VmaSuballocation&>(suballocations1st.back()); // Should never occur.
+}
+
+bool VmaBlockMetadata_Linear::ShouldCompact1st() const
+{
+ const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ const size_t suballocCount = AccessSuballocations1st().size();
+ return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;
+}
+
+void VmaBlockMetadata_Linear::CleanupAfterFree()
+{
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+
+ if (IsEmpty())
{
- // Check previous suballocations for BufferImageGranularity conflicts.
- // If conflict exists, allocation cannot be made here.
- if(bufferImageGranularity > 1)
+ suballocations1st.clear();
+ suballocations2nd.clear();
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
+ m_2ndNullItemsCount = 0;
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+ else
+ {
+ const size_t suballoc1stCount = suballocations1st.size();
+ const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
+ VMA_ASSERT(nullItem1stCount <= suballoc1stCount);
+
+ // Find more null items at the beginning of 1st vector.
+ while (m_1stNullItemsBeginCount < suballoc1stCount &&
+ suballocations1st[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+
+ // Find more null items at the end of 1st vector.
+ while (m_1stNullItemsMiddleCount > 0 &&
+ suballocations1st.back().type == VMA_SUBALLOCATION_TYPE_FREE)
{
- for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ --m_1stNullItemsMiddleCount;
+ suballocations1st.pop_back();
+ }
+
+ // Find more null items at the end of 2nd vector.
+ while (m_2ndNullItemsCount > 0 &&
+ suballocations2nd.back().type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ --m_2ndNullItemsCount;
+ suballocations2nd.pop_back();
+ }
+
+ // Find more null items at the beginning of 2nd vector.
+ while (m_2ndNullItemsCount > 0 &&
+ suballocations2nd[0].type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ --m_2ndNullItemsCount;
+ VmaVectorRemove(suballocations2nd, 0);
+ }
+
+ if (ShouldCompact1st())
+ {
+ const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;
+ size_t srcIndex = m_1stNullItemsBeginCount;
+ for (size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)
{
- const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
- if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ while (suballocations1st[srcIndex].type == VMA_SUBALLOCATION_TYPE_FREE)
{
- if(VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))
- {
- return false;
- }
+ ++srcIndex;
}
- else
+ if (dstIndex != srcIndex)
{
- // Already on next page.
- break;
+ suballocations1st[dstIndex] = suballocations1st[srcIndex];
}
+ ++srcIndex;
}
+ suballocations1st.resize(nonNullItemCount);
+ m_1stNullItemsBeginCount = 0;
+ m_1stNullItemsMiddleCount = 0;
}
- // All tests passed: Success.
- pAllocationRequest->offset = resultOffset;
- pAllocationRequest->sumFreeSize = resultBaseOffset + allocSize - endOf1st;
- pAllocationRequest->sumItemSize = 0;
- // pAllocationRequest->item unused.
- pAllocationRequest->itemsToMakeLostCount = 0;
- pAllocationRequest->type = VmaAllocationRequestType::UpperAddress;
- return true;
+ // 2nd vector became empty.
+ if (suballocations2nd.empty())
+ {
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ }
+
+ // 1st vector became empty.
+ if (suballocations1st.size() - m_1stNullItemsBeginCount == 0)
+ {
+ suballocations1st.clear();
+ m_1stNullItemsBeginCount = 0;
+
+ if (!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ {
+ // Swap 1st with 2nd. Now 2nd is empty.
+ m_2ndVectorMode = SECOND_VECTOR_EMPTY;
+ m_1stNullItemsMiddleCount = m_2ndNullItemsCount;
+ while (m_1stNullItemsBeginCount < suballocations2nd.size() &&
+ suballocations2nd[m_1stNullItemsBeginCount].type == VMA_SUBALLOCATION_TYPE_FREE)
+ {
+ ++m_1stNullItemsBeginCount;
+ --m_1stNullItemsMiddleCount;
+ }
+ m_2ndNullItemsCount = 0;
+ m_1stVectorIndex ^= 1;
+ }
+ }
}
- return false;
+ VMA_HEAVY_ASSERT(Validate());
}
bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
VmaSuballocationType allocType,
- bool canMakeOtherLost,
uint32_t strategy,
VmaAllocationRequest* pAllocationRequest)
{
- const VkDeviceSize size = GetSize();
+ const VkDeviceSize blockSize = GetSize();
+ const VkDeviceSize debugMargin = GetDebugMargin();
+ const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();
SuballocationVectorType& suballocations1st = AccessSuballocations1st();
SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
// Try to allocate at the end of 1st vector.
VkDeviceSize resultBaseOffset = 0;
- if(!suballocations1st.empty())
+ if (!suballocations1st.empty())
{
const VmaSuballocation& lastSuballoc = suballocations1st.back();
- resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin;
}
// Start from offset equal to beginning of free space.
VkDeviceSize resultOffset = resultBaseOffset;
- // Apply VMA_DEBUG_MARGIN at the beginning.
- if(VMA_DEBUG_MARGIN > 0)
- {
- resultOffset += VMA_DEBUG_MARGIN;
- }
-
// Apply alignment.
resultOffset = VmaAlignUp(resultOffset, allocAlignment);
// Check previous suballocations for BufferImageGranularity conflicts.
// Make bigger alignment if necessary.
- if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations1st.empty())
+ if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations1st.empty())
{
bool bufferImageGranularityConflict = false;
- for(size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
+ for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
{
const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
- if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
{
- if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
{
bufferImageGranularityConflict = true;
break;
@@ -11457,28 +8969,28 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
// Already on previous page.
break;
}
- if(bufferImageGranularityConflict)
+ if (bufferImageGranularityConflict)
{
resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
}
}
const VkDeviceSize freeSpaceEnd = m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK ?
- suballocations2nd.back().offset : size;
+ suballocations2nd.back().offset : blockSize;
// There is enough free space at the end after alignment.
- if(resultOffset + allocSize + VMA_DEBUG_MARGIN <= freeSpaceEnd)
+ if (resultOffset + allocSize + debugMargin <= freeSpaceEnd)
{
// Check next suballocations for BufferImageGranularity conflicts.
// If conflict exists, allocation cannot be made here.
- if((allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
+ if ((allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity) && m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
{
- for(size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
+ for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
{
const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
- if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
{
- if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
{
return false;
}
@@ -11492,52 +9004,43 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
}
// All tests passed: Success.
- pAllocationRequest->offset = resultOffset;
- pAllocationRequest->sumFreeSize = freeSpaceEnd - resultBaseOffset;
- pAllocationRequest->sumItemSize = 0;
+ pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);
// pAllocationRequest->item, customData unused.
pAllocationRequest->type = VmaAllocationRequestType::EndOf1st;
- pAllocationRequest->itemsToMakeLostCount = 0;
return true;
}
}
// Wrap-around to end of 2nd vector. Try to allocate there, watching for the
// beginning of 1st vector as the end of free space.
- if(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
+ if (m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
VMA_ASSERT(!suballocations1st.empty());
VkDeviceSize resultBaseOffset = 0;
- if(!suballocations2nd.empty())
+ if (!suballocations2nd.empty())
{
const VmaSuballocation& lastSuballoc = suballocations2nd.back();
- resultBaseOffset = lastSuballoc.offset + lastSuballoc.size;
+ resultBaseOffset = lastSuballoc.offset + lastSuballoc.size + debugMargin;
}
// Start from offset equal to beginning of free space.
VkDeviceSize resultOffset = resultBaseOffset;
- // Apply VMA_DEBUG_MARGIN at the beginning.
- if(VMA_DEBUG_MARGIN > 0)
- {
- resultOffset += VMA_DEBUG_MARGIN;
- }
-
// Apply alignment.
resultOffset = VmaAlignUp(resultOffset, allocAlignment);
// Check previous suballocations for BufferImageGranularity conflicts.
// Make bigger alignment if necessary.
- if(bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())
+ if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())
{
bool bufferImageGranularityConflict = false;
- for(size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )
+ for (size_t prevSuballocIndex = suballocations2nd.size(); prevSuballocIndex--; )
{
const VmaSuballocation& prevSuballoc = suballocations2nd[prevSuballocIndex];
- if(VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
{
- if(VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
+ if (VmaIsBufferImageGranularityConflict(prevSuballoc.type, allocType))
{
bufferImageGranularityConflict = true;
break;
@@ -11547,102 +9050,30 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
// Already on previous page.
break;
}
- if(bufferImageGranularityConflict)
+ if (bufferImageGranularityConflict)
{
resultOffset = VmaAlignUp(resultOffset, bufferImageGranularity);
}
}
- pAllocationRequest->itemsToMakeLostCount = 0;
- pAllocationRequest->sumItemSize = 0;
size_t index1st = m_1stNullItemsBeginCount;
- if(canMakeOtherLost)
- {
- while(index1st < suballocations1st.size() &&
- resultOffset + allocSize + VMA_DEBUG_MARGIN > suballocations1st[index1st].offset)
- {
- // Next colliding allocation at the beginning of 1st vector found. Try to make it lost.
- const VmaSuballocation& suballoc = suballocations1st[index1st];
- if(suballoc.type == VMA_SUBALLOCATION_TYPE_FREE)
- {
- // No problem.
- }
- else
- {
- VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
- if(suballoc.hAllocation->CanBecomeLost() &&
- suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
- {
- ++pAllocationRequest->itemsToMakeLostCount;
- pAllocationRequest->sumItemSize += suballoc.size;
- }
- else
- {
- return false;
- }
- }
- ++index1st;
- }
-
- // Check next suballocations for BufferImageGranularity conflicts.
- // If conflict exists, we must mark more allocations lost or fail.
- if(allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity)
- {
- while(index1st < suballocations1st.size())
- {
- const VmaSuballocation& suballoc = suballocations1st[index1st];
- if(VmaBlocksOnSamePage(resultOffset, allocSize, suballoc.offset, bufferImageGranularity))
- {
- if(suballoc.hAllocation != VK_NULL_HANDLE)
- {
- // Not checking actual VmaIsBufferImageGranularityConflict(allocType, suballoc.type).
- if(suballoc.hAllocation->CanBecomeLost() &&
- suballoc.hAllocation->GetLastUseFrameIndex() + frameInUseCount < currentFrameIndex)
- {
- ++pAllocationRequest->itemsToMakeLostCount;
- pAllocationRequest->sumItemSize += suballoc.size;
- }
- else
- {
- return false;
- }
- }
- }
- else
- {
- // Already on next page.
- break;
- }
- ++index1st;
- }
- }
-
- // Special case: There is not enough room at the end for this allocation, even after making all from the 1st lost.
- if(index1st == suballocations1st.size() &&
- resultOffset + allocSize + VMA_DEBUG_MARGIN > size)
- {
- // TODO: This is a known bug that it's not yet implemented and the allocation is failing.
- VMA_DEBUG_LOG("Unsupported special case in custom pool with linear allocation algorithm used as ring buffer with allocations that can be lost.");
- }
- }
-
// There is enough free space at the end after alignment.
- if((index1st == suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= size) ||
- (index1st < suballocations1st.size() && resultOffset + allocSize + VMA_DEBUG_MARGIN <= suballocations1st[index1st].offset))
+ if ((index1st == suballocations1st.size() && resultOffset + allocSize + debugMargin <= blockSize) ||
+ (index1st < suballocations1st.size() && resultOffset + allocSize + debugMargin <= suballocations1st[index1st].offset))
{
// Check next suballocations for BufferImageGranularity conflicts.
// If conflict exists, allocation cannot be made here.
- if(allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity)
+ if (allocSize % bufferImageGranularity || resultOffset % bufferImageGranularity)
{
- for(size_t nextSuballocIndex = index1st;
+ for (size_t nextSuballocIndex = index1st;
nextSuballocIndex < suballocations1st.size();
nextSuballocIndex++)
{
const VmaSuballocation& nextSuballoc = suballocations1st[nextSuballocIndex];
- if(VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
+ if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
{
- if(VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
+ if (VmaIsBufferImageGranularityConflict(allocType, nextSuballoc.type))
{
return false;
}
@@ -11656,11 +9087,7 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
}
// All tests passed: Success.
- pAllocationRequest->offset = resultOffset;
- pAllocationRequest->sumFreeSize =
- (index1st < suballocations1st.size() ? suballocations1st[index1st].offset : size)
- - resultBaseOffset
- - pAllocationRequest->sumItemSize;
+ pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);
pAllocationRequest->type = VmaAllocationRequestType::EndOf2nd;
// pAllocationRequest->item, customData unused.
return true;
@@ -11670,437 +9097,278 @@ bool VmaBlockMetadata_Linear::CreateAllocationRequest_LowerAddress(
return false;
}
-bool VmaBlockMetadata_Linear::MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
+bool VmaBlockMetadata_Linear::CreateAllocationRequest_UpperAddress(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
VmaAllocationRequest* pAllocationRequest)
{
- if(pAllocationRequest->itemsToMakeLostCount == 0)
- {
- return true;
- }
-
- VMA_ASSERT(m_2ndVectorMode == SECOND_VECTOR_EMPTY || m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER);
+ const VkDeviceSize blockSize = GetSize();
+ const VkDeviceSize bufferImageGranularity = GetBufferImageGranularity();
+ SuballocationVectorType& suballocations1st = AccessSuballocations1st();
+ SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- // We always start from 1st.
- SuballocationVectorType* suballocations = &AccessSuballocations1st();
- size_t index = m_1stNullItemsBeginCount;
- size_t madeLostCount = 0;
- while(madeLostCount < pAllocationRequest->itemsToMakeLostCount)
+ if (m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
{
- if(index == suballocations->size())
- {
- index = 0;
- // If we get to the end of 1st, we wrap around to beginning of 2nd of 1st.
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
- {
- suballocations = &AccessSuballocations2nd();
- }
- // else: m_2ndVectorMode == SECOND_VECTOR_EMPTY:
- // suballocations continues pointing at AccessSuballocations1st().
- VMA_ASSERT(!suballocations->empty());
- }
- VmaSuballocation& suballoc = (*suballocations)[index];
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
- {
- VMA_ASSERT(suballoc.hAllocation != VK_NULL_HANDLE);
- VMA_ASSERT(suballoc.hAllocation->CanBecomeLost());
- if(suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
- {
- suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- suballoc.hAllocation = VK_NULL_HANDLE;
- m_SumFreeSize += suballoc.size;
- if(suballocations == &AccessSuballocations1st())
- {
- ++m_1stNullItemsMiddleCount;
- }
- else
- {
- ++m_2ndNullItemsCount;
- }
- ++madeLostCount;
- }
- else
- {
- return false;
- }
- }
- ++index;
+ VMA_ASSERT(0 && "Trying to use pool with linear algorithm as double stack, while it is already being used as ring buffer.");
+ return false;
}
- CleanupAfterFree();
- //VMA_HEAVY_ASSERT(Validate()); // Already called by CleanupAfterFree().
-
- return true;
-}
-
-uint32_t VmaBlockMetadata_Linear::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
-{
- uint32_t lostAllocationCount = 0;
-
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ // Try to allocate before 2nd.back(), or end of block if 2nd.empty().
+ if (allocSize > blockSize)
{
- VmaSuballocation& suballoc = suballocations1st[i];
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
- suballoc.hAllocation->CanBecomeLost() &&
- suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
- {
- suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- suballoc.hAllocation = VK_NULL_HANDLE;
- ++m_1stNullItemsMiddleCount;
- m_SumFreeSize += suballoc.size;
- ++lostAllocationCount;
- }
+ return false;
}
-
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ VkDeviceSize resultBaseOffset = blockSize - allocSize;
+ if (!suballocations2nd.empty())
{
- VmaSuballocation& suballoc = suballocations2nd[i];
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE &&
- suballoc.hAllocation->CanBecomeLost() &&
- suballoc.hAllocation->MakeLost(currentFrameIndex, frameInUseCount))
+ const VmaSuballocation& lastSuballoc = suballocations2nd.back();
+ resultBaseOffset = lastSuballoc.offset - allocSize;
+ if (allocSize > lastSuballoc.offset)
{
- suballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- suballoc.hAllocation = VK_NULL_HANDLE;
- ++m_2ndNullItemsCount;
- m_SumFreeSize += suballoc.size;
- ++lostAllocationCount;
+ return false;
}
}
- if(lostAllocationCount)
- {
- CleanupAfterFree();
- }
+ // Start from offset equal to end of free space.
+ VkDeviceSize resultOffset = resultBaseOffset;
- return lostAllocationCount;
-}
+ const VkDeviceSize debugMargin = GetDebugMargin();
-VkResult VmaBlockMetadata_Linear::CheckCorruption(const void* pBlockData)
-{
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- for(size_t i = m_1stNullItemsBeginCount, count = suballocations1st.size(); i < count; ++i)
+ // Apply debugMargin at the end.
+ if (debugMargin > 0)
{
- const VmaSuballocation& suballoc = suballocations1st[i];
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ if (resultOffset < debugMargin)
{
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
- {
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
- {
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
+ return false;
}
+ resultOffset -= debugMargin;
}
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- for(size_t i = 0, count = suballocations2nd.size(); i < count; ++i)
+ // Apply alignment.
+ resultOffset = VmaAlignDown(resultOffset, allocAlignment);
+
+ // Check next suballocations from 2nd for BufferImageGranularity conflicts.
+ // Make bigger alignment if necessary.
+ if (bufferImageGranularity > 1 && bufferImageGranularity != allocAlignment && !suballocations2nd.empty())
{
- const VmaSuballocation& suballoc = suballocations2nd[i];
- if(suballoc.type != VMA_SUBALLOCATION_TYPE_FREE)
+ bool bufferImageGranularityConflict = false;
+ for (size_t nextSuballocIndex = suballocations2nd.size(); nextSuballocIndex--; )
{
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset - VMA_DEBUG_MARGIN))
- {
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
- if(!VmaValidateMagicValue(pBlockData, suballoc.offset + suballoc.size))
+ const VmaSuballocation& nextSuballoc = suballocations2nd[nextSuballocIndex];
+ if (VmaBlocksOnSamePage(resultOffset, allocSize, nextSuballoc.offset, bufferImageGranularity))
{
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ if (VmaIsBufferImageGranularityConflict(nextSuballoc.type, allocType))
+ {
+ bufferImageGranularityConflict = true;
+ break;
+ }
}
+ else
+ // Already on previous page.
+ break;
}
- }
-
- return VK_SUCCESS;
-}
-
-void VmaBlockMetadata_Linear::Alloc(
- const VmaAllocationRequest& request,
- VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation)
-{
- const VmaSuballocation newSuballoc = { request.offset, allocSize, hAllocation, type };
-
- switch(request.type)
- {
- case VmaAllocationRequestType::UpperAddress:
+ if (bufferImageGranularityConflict)
{
- VMA_ASSERT(m_2ndVectorMode != SECOND_VECTOR_RING_BUFFER &&
- "CRITICAL ERROR: Trying to use linear allocator as double stack while it was already used as ring buffer.");
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
- suballocations2nd.push_back(newSuballoc);
- m_2ndVectorMode = SECOND_VECTOR_DOUBLE_STACK;
+ resultOffset = VmaAlignDown(resultOffset, bufferImageGranularity);
}
- break;
- case VmaAllocationRequestType::EndOf1st:
- {
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
-
- VMA_ASSERT(suballocations1st.empty() ||
- request.offset >= suballocations1st.back().offset + suballocations1st.back().size);
- // Check if it fits before the end of the block.
- VMA_ASSERT(request.offset + allocSize <= GetSize());
+ }
- suballocations1st.push_back(newSuballoc);
- }
- break;
- case VmaAllocationRequestType::EndOf2nd:
+ // There is enough free space.
+ const VkDeviceSize endOf1st = !suballocations1st.empty() ?
+ suballocations1st.back().offset + suballocations1st.back().size :
+ 0;
+ if (endOf1st + debugMargin <= resultOffset)
+ {
+ // Check previous suballocations for BufferImageGranularity conflicts.
+ // If conflict exists, allocation cannot be made here.
+ if (bufferImageGranularity > 1)
{
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- // New allocation at the end of 2-part ring buffer, so before first allocation from 1st vector.
- VMA_ASSERT(!suballocations1st.empty() &&
- request.offset + allocSize <= suballocations1st[m_1stNullItemsBeginCount].offset);
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
-
- switch(m_2ndVectorMode)
+ for (size_t prevSuballocIndex = suballocations1st.size(); prevSuballocIndex--; )
{
- case SECOND_VECTOR_EMPTY:
- // First allocation from second part ring buffer.
- VMA_ASSERT(suballocations2nd.empty());
- m_2ndVectorMode = SECOND_VECTOR_RING_BUFFER;
- break;
- case SECOND_VECTOR_RING_BUFFER:
- // 2-part ring buffer is already started.
- VMA_ASSERT(!suballocations2nd.empty());
- break;
- case SECOND_VECTOR_DOUBLE_STACK:
- VMA_ASSERT(0 && "CRITICAL ERROR: Trying to use linear allocator as ring buffer while it was already used as double stack.");
- break;
- default:
- VMA_ASSERT(0);
+ const VmaSuballocation& prevSuballoc = suballocations1st[prevSuballocIndex];
+ if (VmaBlocksOnSamePage(prevSuballoc.offset, prevSuballoc.size, resultOffset, bufferImageGranularity))
+ {
+ if (VmaIsBufferImageGranularityConflict(allocType, prevSuballoc.type))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ // Already on next page.
+ break;
+ }
}
-
- suballocations2nd.push_back(newSuballoc);
}
- break;
- default:
- VMA_ASSERT(0 && "CRITICAL INTERNAL ERROR.");
+
+ // All tests passed: Success.
+ pAllocationRequest->allocHandle = (VmaAllocHandle)(resultOffset + 1);
+ // pAllocationRequest->item unused.
+ pAllocationRequest->type = VmaAllocationRequestType::UpperAddress;
+ return true;
}
- m_SumFreeSize -= newSuballoc.size;
+ return false;
}
+#endif // _VMA_BLOCK_METADATA_LINEAR_FUNCTIONS
+#endif // _VMA_BLOCK_METADATA_LINEAR
-void VmaBlockMetadata_Linear::Free(const VmaAllocation allocation)
-{
- FreeAtOffset(allocation->GetOffset());
-}
+#if 0
+#ifndef _VMA_BLOCK_METADATA_BUDDY
+/*
+- GetSize() is the original size of allocated memory block.
+- m_UsableSize is this size aligned down to a power of two.
+ All allocations and calculations happen relative to m_UsableSize.
+- GetUnusableSize() is the difference between them.
+ It is reported as separate, unused range, not available for allocations.
-void VmaBlockMetadata_Linear::FreeAtOffset(VkDeviceSize offset)
+Node at level 0 has size = m_UsableSize.
+Each next level contains nodes with size 2 times smaller than current level.
+m_LevelCount is the maximum number of levels to use in the current object.
+*/
+class VmaBlockMetadata_Buddy : public VmaBlockMetadata
{
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_Buddy)
+public:
+ VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual);
+ virtual ~VmaBlockMetadata_Buddy();
- if(!suballocations1st.empty())
- {
- // First allocation: Mark it as next empty at the beginning.
- VmaSuballocation& firstSuballoc = suballocations1st[m_1stNullItemsBeginCount];
- if(firstSuballoc.offset == offset)
- {
- firstSuballoc.type = VMA_SUBALLOCATION_TYPE_FREE;
- firstSuballoc.hAllocation = VK_NULL_HANDLE;
- m_SumFreeSize += firstSuballoc.size;
- ++m_1stNullItemsBeginCount;
- CleanupAfterFree();
- return;
- }
- }
+ size_t GetAllocationCount() const override { return m_AllocationCount; }
+ VkDeviceSize GetSumFreeSize() const override { return m_SumFreeSize + GetUnusableSize(); }
+ bool IsEmpty() const override { return m_Root->type == Node::TYPE_FREE; }
+ VkResult CheckCorruption(const void* pBlockData) override { return VK_ERROR_FEATURE_NOT_PRESENT; }
+ VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return (VkDeviceSize)allocHandle - 1; };
+ void DebugLogAllAllocations() const override { DebugLogAllAllocationNode(m_Root, 0); }
- // Last allocation in 2-part ring buffer or top of upper stack (same logic).
- if(m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ||
- m_2ndVectorMode == SECOND_VECTOR_DOUBLE_STACK)
- {
- VmaSuballocation& lastSuballoc = suballocations2nd.back();
- if(lastSuballoc.offset == offset)
- {
- m_SumFreeSize += lastSuballoc.size;
- suballocations2nd.pop_back();
- CleanupAfterFree();
- return;
- }
- }
- // Last allocation in 1st vector.
- else if(m_2ndVectorMode == SECOND_VECTOR_EMPTY)
- {
- VmaSuballocation& lastSuballoc = suballocations1st.back();
- if(lastSuballoc.offset == offset)
- {
- m_SumFreeSize += lastSuballoc.size;
- suballocations1st.pop_back();
- CleanupAfterFree();
- return;
- }
- }
+ void Init(VkDeviceSize size) override;
+ bool Validate() const override;
- // Item from the middle of 1st vector.
- {
- VmaSuballocation refSuballoc;
- refSuballoc.offset = offset;
- // Rest of members stays uninitialized intentionally for better performance.
- SuballocationVectorType::iterator it = VmaBinaryFindSorted(
- suballocations1st.begin() + m_1stNullItemsBeginCount,
- suballocations1st.end(),
- refSuballoc,
- VmaSuballocationOffsetLess());
- if(it != suballocations1st.end())
- {
- it->type = VMA_SUBALLOCATION_TYPE_FREE;
- it->hAllocation = VK_NULL_HANDLE;
- ++m_1stNullItemsMiddleCount;
- m_SumFreeSize += it->size;
- CleanupAfterFree();
- return;
- }
- }
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;
+ void AddStatistics(VmaStatistics& inoutStats) const override;
- if(m_2ndVectorMode != SECOND_VECTOR_EMPTY)
- {
- // Item from the middle of 2nd vector.
- VmaSuballocation refSuballoc;
- refSuballoc.offset = offset;
- // Rest of members stays uninitialized intentionally for better performance.
- SuballocationVectorType::iterator it = m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER ?
- VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetLess()) :
- VmaBinaryFindSorted(suballocations2nd.begin(), suballocations2nd.end(), refSuballoc, VmaSuballocationOffsetGreater());
- if(it != suballocations2nd.end())
- {
- it->type = VMA_SUBALLOCATION_TYPE_FREE;
- it->hAllocation = VK_NULL_HANDLE;
- ++m_2ndNullItemsCount;
- m_SumFreeSize += it->size;
- CleanupAfterFree();
- return;
- }
- }
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const override;
+#endif
- VMA_ASSERT(0 && "Allocation to free not found in linear allocator!");
-}
+ bool CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) override;
-bool VmaBlockMetadata_Linear::ShouldCompact1st() const
-{
- const size_t nullItemCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
- const size_t suballocCount = AccessSuballocations1st().size();
- return suballocCount > 32 && nullItemCount * 2 >= (suballocCount - nullItemCount) * 3;
-}
+ void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData) override;
-void VmaBlockMetadata_Linear::CleanupAfterFree()
-{
- SuballocationVectorType& suballocations1st = AccessSuballocations1st();
- SuballocationVectorType& suballocations2nd = AccessSuballocations2nd();
+ void Free(VmaAllocHandle allocHandle) override;
+ void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;
+ void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;
+ VmaAllocHandle GetAllocationListBegin() const override;
+ VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;
+ void Clear() override;
+ void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;
- if(IsEmpty())
+private:
+ static const size_t MAX_LEVELS = 48;
+
+ struct ValidationContext
{
- suballocations1st.clear();
- suballocations2nd.clear();
- m_1stNullItemsBeginCount = 0;
- m_1stNullItemsMiddleCount = 0;
- m_2ndNullItemsCount = 0;
- m_2ndVectorMode = SECOND_VECTOR_EMPTY;
- }
- else
+ size_t calculatedAllocationCount = 0;
+ size_t calculatedFreeCount = 0;
+ VkDeviceSize calculatedSumFreeSize = 0;
+ };
+ struct Node
{
- const size_t suballoc1stCount = suballocations1st.size();
- const size_t nullItem1stCount = m_1stNullItemsBeginCount + m_1stNullItemsMiddleCount;
- VMA_ASSERT(nullItem1stCount <= suballoc1stCount);
-
- // Find more null items at the beginning of 1st vector.
- while(m_1stNullItemsBeginCount < suballoc1stCount &&
- suballocations1st[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
- {
- ++m_1stNullItemsBeginCount;
- --m_1stNullItemsMiddleCount;
- }
-
- // Find more null items at the end of 1st vector.
- while(m_1stNullItemsMiddleCount > 0 &&
- suballocations1st.back().hAllocation == VK_NULL_HANDLE)
+ VkDeviceSize offset;
+ enum TYPE
{
- --m_1stNullItemsMiddleCount;
- suballocations1st.pop_back();
- }
+ TYPE_FREE,
+ TYPE_ALLOCATION,
+ TYPE_SPLIT,
+ TYPE_COUNT
+ } type;
+ Node* parent;
+ Node* buddy;
- // Find more null items at the end of 2nd vector.
- while(m_2ndNullItemsCount > 0 &&
- suballocations2nd.back().hAllocation == VK_NULL_HANDLE)
+ union
{
- --m_2ndNullItemsCount;
- suballocations2nd.pop_back();
- }
+ struct
+ {
+ Node* prev;
+ Node* next;
+ } free;
+ struct
+ {
+ void* userData;
+ } allocation;
+ struct
+ {
+ Node* leftChild;
+ } split;
+ };
+ };
- // Find more null items at the beginning of 2nd vector.
- while(m_2ndNullItemsCount > 0 &&
- suballocations2nd[0].hAllocation == VK_NULL_HANDLE)
- {
- --m_2ndNullItemsCount;
- VmaVectorRemove(suballocations2nd, 0);
- }
+ // Size of the memory block aligned down to a power of two.
+ VkDeviceSize m_UsableSize;
+ uint32_t m_LevelCount;
+ VmaPoolAllocator<Node> m_NodeAllocator;
+ Node* m_Root;
+ struct
+ {
+ Node* front;
+ Node* back;
+ } m_FreeList[MAX_LEVELS];
- if(ShouldCompact1st())
- {
- const size_t nonNullItemCount = suballoc1stCount - nullItem1stCount;
- size_t srcIndex = m_1stNullItemsBeginCount;
- for(size_t dstIndex = 0; dstIndex < nonNullItemCount; ++dstIndex)
- {
- while(suballocations1st[srcIndex].hAllocation == VK_NULL_HANDLE)
- {
- ++srcIndex;
- }
- if(dstIndex != srcIndex)
- {
- suballocations1st[dstIndex] = suballocations1st[srcIndex];
- }
- ++srcIndex;
- }
- suballocations1st.resize(nonNullItemCount);
- m_1stNullItemsBeginCount = 0;
- m_1stNullItemsMiddleCount = 0;
- }
+ // Number of nodes in the tree with type == TYPE_ALLOCATION.
+ size_t m_AllocationCount;
+ // Number of nodes in the tree with type == TYPE_FREE.
+ size_t m_FreeCount;
+ // Doesn't include space wasted due to internal fragmentation - allocation sizes are just aligned up to node sizes.
+ // Doesn't include unusable size.
+ VkDeviceSize m_SumFreeSize;
- // 2nd vector became empty.
- if(suballocations2nd.empty())
- {
- m_2ndVectorMode = SECOND_VECTOR_EMPTY;
- }
+ VkDeviceSize GetUnusableSize() const { return GetSize() - m_UsableSize; }
+ VkDeviceSize LevelToNodeSize(uint32_t level) const { return m_UsableSize >> level; }
- // 1st vector became empty.
- if(suballocations1st.size() - m_1stNullItemsBeginCount == 0)
+ VkDeviceSize AlignAllocationSize(VkDeviceSize size) const
+ {
+ if (!IsVirtual())
{
- suballocations1st.clear();
- m_1stNullItemsBeginCount = 0;
-
- if(!suballocations2nd.empty() && m_2ndVectorMode == SECOND_VECTOR_RING_BUFFER)
- {
- // Swap 1st with 2nd. Now 2nd is empty.
- m_2ndVectorMode = SECOND_VECTOR_EMPTY;
- m_1stNullItemsMiddleCount = m_2ndNullItemsCount;
- while(m_1stNullItemsBeginCount < suballocations2nd.size() &&
- suballocations2nd[m_1stNullItemsBeginCount].hAllocation == VK_NULL_HANDLE)
- {
- ++m_1stNullItemsBeginCount;
- --m_1stNullItemsMiddleCount;
- }
- m_2ndNullItemsCount = 0;
- m_1stVectorIndex ^= 1;
- }
+ size = VmaAlignUp(size, (VkDeviceSize)16);
}
+ return VmaNextPow2(size);
}
+ Node* FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel) const;
+ void DeleteNodeChildren(Node* node);
+ bool ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const;
+ uint32_t AllocSizeToLevel(VkDeviceSize allocSize) const;
+ void AddNodeToDetailedStatistics(VmaDetailedStatistics& inoutStats, const Node* node, VkDeviceSize levelNodeSize) const;
+ // Adds node to the front of FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next can be undefined.
+ void AddToFreeListFront(uint32_t level, Node* node);
+ // Removes node from FreeList at given level.
+ // node->type must be FREE.
+ // node->free.prev, next stay untouched.
+ void RemoveFromFreeList(uint32_t level, Node* node);
+ void DebugLogAllAllocationNode(Node* node, uint32_t level) const;
- VMA_HEAVY_ASSERT(Validate());
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// class VmaBlockMetadata_Buddy
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const;
+#endif
+};
-VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) :
- VmaBlockMetadata(hAllocator),
+#ifndef _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS
+VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual)
+ : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),
+ m_NodeAllocator(pAllocationCallbacks, 32), // firstBlockCapacity
m_Root(VMA_NULL),
m_AllocationCount(0),
m_FreeCount(1),
@@ -12111,7 +9379,8 @@ VmaBlockMetadata_Buddy::VmaBlockMetadata_Buddy(VmaAllocator hAllocator) :
VmaBlockMetadata_Buddy::~VmaBlockMetadata_Buddy()
{
- DeleteNode(m_Root);
+ DeleteNodeChildren(m_Root);
+ m_NodeAllocator.Free(m_Root);
}
void VmaBlockMetadata_Buddy::Init(VkDeviceSize size)
@@ -12122,14 +9391,15 @@ void VmaBlockMetadata_Buddy::Init(VkDeviceSize size)
m_SumFreeSize = m_UsableSize;
// Calculate m_LevelCount.
+ const VkDeviceSize minNodeSize = IsVirtual() ? 1 : 16;
m_LevelCount = 1;
- while(m_LevelCount < MAX_LEVELS &&
- LevelToNodeSize(m_LevelCount) >= MIN_NODE_SIZE)
+ while (m_LevelCount < MAX_LEVELS &&
+ LevelToNodeSize(m_LevelCount) >= minNodeSize)
{
++m_LevelCount;
}
- Node* rootNode = vma_new(GetAllocationCallbacks(), Node)();
+ Node* rootNode = m_NodeAllocator.Alloc();
rootNode->offset = 0;
rootNode->type = Node::TYPE_FREE;
rootNode->parent = VMA_NULL;
@@ -12143,7 +9413,7 @@ bool VmaBlockMetadata_Buddy::Validate() const
{
// Validate tree.
ValidationContext ctx;
- if(!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))
+ if (!ValidateNode(ctx, VMA_NULL, m_Root, 0, LevelToNodeSize(0)))
{
VMA_VALIDATE(false && "ValidateNode failed.");
}
@@ -12151,18 +9421,18 @@ bool VmaBlockMetadata_Buddy::Validate() const
VMA_VALIDATE(m_SumFreeSize == ctx.calculatedSumFreeSize);
// Validate free node lists.
- for(uint32_t level = 0; level < m_LevelCount; ++level)
+ for (uint32_t level = 0; level < m_LevelCount; ++level)
{
VMA_VALIDATE(m_FreeList[level].front == VMA_NULL ||
m_FreeList[level].front->free.prev == VMA_NULL);
- for(Node* node = m_FreeList[level].front;
+ for (Node* node = m_FreeList[level].front;
node != VMA_NULL;
node = node->free.next)
{
VMA_VALIDATE(node->type == Node::TYPE_FREE);
- if(node->free.next == VMA_NULL)
+ if (node->free.next == VMA_NULL)
{
VMA_VALIDATE(m_FreeList[level].back == node);
}
@@ -12174,7 +9444,7 @@ bool VmaBlockMetadata_Buddy::Validate() const
}
// Validate that free lists ar higher levels are empty.
- for(uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)
+ for (uint32_t level = m_LevelCount; level < MAX_LEVELS; ++level)
{
VMA_VALIDATE(m_FreeList[level].front == VMA_NULL && m_FreeList[level].back == VMA_NULL);
}
@@ -12182,77 +9452,44 @@ bool VmaBlockMetadata_Buddy::Validate() const
return true;
}
-VkDeviceSize VmaBlockMetadata_Buddy::GetUnusedRangeSizeMax() const
+void VmaBlockMetadata_Buddy::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const
{
- for(uint32_t level = 0; level < m_LevelCount; ++level)
- {
- if(m_FreeList[level].front != VMA_NULL)
- {
- return LevelToNodeSize(level);
- }
- }
- return 0;
-}
-
-void VmaBlockMetadata_Buddy::CalcAllocationStatInfo(VmaStatInfo& outInfo) const
-{
- const VkDeviceSize unusableSize = GetUnusableSize();
+ inoutStats.statistics.blockCount++;
+ inoutStats.statistics.blockBytes += GetSize();
- outInfo.blockCount = 1;
+ AddNodeToDetailedStatistics(inoutStats, m_Root, LevelToNodeSize(0));
- outInfo.allocationCount = outInfo.unusedRangeCount = 0;
- outInfo.usedBytes = outInfo.unusedBytes = 0;
-
- outInfo.allocationSizeMax = outInfo.unusedRangeSizeMax = 0;
- outInfo.allocationSizeMin = outInfo.unusedRangeSizeMin = UINT64_MAX;
- outInfo.allocationSizeAvg = outInfo.unusedRangeSizeAvg = 0; // Unused.
-
- CalcAllocationStatInfoNode(outInfo, m_Root, LevelToNodeSize(0));
-
- if(unusableSize > 0)
- {
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusableSize;
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusableSize);
- outInfo.unusedRangeSizeMin = VMA_MIN(outInfo.unusedRangeSizeMin, unusableSize);
- }
+ const VkDeviceSize unusableSize = GetUnusableSize();
+ if (unusableSize > 0)
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, unusableSize);
}
-void VmaBlockMetadata_Buddy::AddPoolStats(VmaPoolStats& inoutStats) const
+void VmaBlockMetadata_Buddy::AddStatistics(VmaStatistics& inoutStats) const
{
- const VkDeviceSize unusableSize = GetUnusableSize();
-
- inoutStats.size += GetSize();
- inoutStats.unusedSize += m_SumFreeSize + unusableSize;
- inoutStats.allocationCount += m_AllocationCount;
- inoutStats.unusedRangeCount += m_FreeCount;
- inoutStats.unusedRangeSizeMax = VMA_MAX(inoutStats.unusedRangeSizeMax, GetUnusedRangeSizeMax());
-
- if(unusableSize > 0)
- {
- ++inoutStats.unusedRangeCount;
- // Not updating inoutStats.unusedRangeSizeMax with unusableSize because this space is not available for allocations.
- }
+ inoutStats.blockCount++;
+ inoutStats.allocationCount += (uint32_t)m_AllocationCount;
+ inoutStats.blockBytes += GetSize();
+ inoutStats.allocationBytes += GetSize() - m_SumFreeSize;
}
#if VMA_STATS_STRING_ENABLED
-
-void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
+void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json, uint32_t mapRefCount) const
{
- // TODO optimize
- VmaStatInfo stat;
- CalcAllocationStatInfo(stat);
+ VmaDetailedStatistics stats;
+ VmaClearDetailedStatistics(stats);
+ AddDetailedStatistics(stats);
PrintDetailedMap_Begin(
json,
- stat.unusedBytes,
- stat.allocationCount,
- stat.unusedRangeCount);
+ stats.statistics.blockBytes - stats.statistics.allocationBytes,
+ stats.statistics.allocationCount,
+ stats.unusedRangeCount,
+ mapRefCount);
PrintDetailedMapNode(json, m_Root, LevelToNodeSize(0));
const VkDeviceSize unusableSize = GetUnusableSize();
- if(unusableSize > 0)
+ if (unusableSize > 0)
{
PrintDetailedMap_UnusedRange(json,
m_UsableSize, // offset
@@ -12261,52 +9498,47 @@ void VmaBlockMetadata_Buddy::PrintDetailedMap(class VmaJsonWriter& json) const
PrintDetailedMap_End(json);
}
-
-#endif // #if VMA_STATS_STRING_ENABLED
+#endif // VMA_STATS_STRING_ENABLED
bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VkDeviceSize bufferImageGranularity,
VkDeviceSize allocSize,
VkDeviceSize allocAlignment,
bool upperAddress,
VmaSuballocationType allocType,
- bool canMakeOtherLost,
uint32_t strategy,
VmaAllocationRequest* pAllocationRequest)
{
VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
+ allocSize = AlignAllocationSize(allocSize);
+
// Simple way to respect bufferImageGranularity. May be optimized some day.
// Whenever it might be an OPTIMAL image...
- if(allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
+ if (allocType == VMA_SUBALLOCATION_TYPE_UNKNOWN ||
allocType == VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN ||
allocType == VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL)
{
- allocAlignment = VMA_MAX(allocAlignment, bufferImageGranularity);
- allocSize = VMA_MAX(allocSize, bufferImageGranularity);
+ allocAlignment = VMA_MAX(allocAlignment, GetBufferImageGranularity());
+ allocSize = VmaAlignUp(allocSize, GetBufferImageGranularity());
}
- if(allocSize > m_UsableSize)
+ if (allocSize > m_UsableSize)
{
return false;
}
const uint32_t targetLevel = AllocSizeToLevel(allocSize);
- for(uint32_t level = targetLevel + 1; level--; )
+ for (uint32_t level = targetLevel; level--; )
{
- for(Node* freeNode = m_FreeList[level].front;
+ for (Node* freeNode = m_FreeList[level].front;
freeNode != VMA_NULL;
freeNode = freeNode->free.next)
{
- if(freeNode->offset % allocAlignment == 0)
+ if (freeNode->offset % allocAlignment == 0)
{
pAllocationRequest->type = VmaAllocationRequestType::Normal;
- pAllocationRequest->offset = freeNode->offset;
- pAllocationRequest->sumFreeSize = LevelToNodeSize(level);
- pAllocationRequest->sumItemSize = 0;
- pAllocationRequest->itemsToMakeLostCount = 0;
+ pAllocationRequest->allocHandle = (VmaAllocHandle)(freeNode->offset + 1);
+ pAllocationRequest->size = allocSize;
pAllocationRequest->customData = (void*)(uintptr_t)level;
return true;
}
@@ -12316,48 +9548,27 @@ bool VmaBlockMetadata_Buddy::CreateAllocationRequest(
return false;
}
-bool VmaBlockMetadata_Buddy::MakeRequestedAllocationsLost(
- uint32_t currentFrameIndex,
- uint32_t frameInUseCount,
- VmaAllocationRequest* pAllocationRequest)
-{
- /*
- Lost allocations are not supported in buddy allocator at the moment.
- Support might be added in the future.
- */
- return pAllocationRequest->itemsToMakeLostCount == 0;
-}
-
-uint32_t VmaBlockMetadata_Buddy::MakeAllocationsLost(uint32_t currentFrameIndex, uint32_t frameInUseCount)
-{
- /*
- Lost allocations are not supported in buddy allocator at the moment.
- Support might be added in the future.
- */
- return 0;
-}
-
void VmaBlockMetadata_Buddy::Alloc(
const VmaAllocationRequest& request,
VmaSuballocationType type,
- VkDeviceSize allocSize,
- VmaAllocation hAllocation)
+ void* userData)
{
VMA_ASSERT(request.type == VmaAllocationRequestType::Normal);
- const uint32_t targetLevel = AllocSizeToLevel(allocSize);
+ const uint32_t targetLevel = AllocSizeToLevel(request.size);
uint32_t currLevel = (uint32_t)(uintptr_t)request.customData;
Node* currNode = m_FreeList[currLevel].front;
VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
- while(currNode->offset != request.offset)
+ const VkDeviceSize offset = (VkDeviceSize)request.allocHandle - 1;
+ while (currNode->offset != offset)
{
currNode = currNode->free.next;
VMA_ASSERT(currNode != VMA_NULL && currNode->type == Node::TYPE_FREE);
}
// Go down, splitting free nodes.
- while(currLevel < targetLevel)
+ while (currLevel < targetLevel)
{
// currNode is already first free node at currLevel.
// Remove it from list of free nodes at this currLevel.
@@ -12366,8 +9577,8 @@ void VmaBlockMetadata_Buddy::Alloc(
const uint32_t childrenLevel = currLevel + 1;
// Create two free sub-nodes.
- Node* leftChild = vma_new(GetAllocationCallbacks(), Node)();
- Node* rightChild = vma_new(GetAllocationCallbacks(), Node)();
+ Node* leftChild = m_NodeAllocator.Alloc();
+ Node* rightChild = m_NodeAllocator.Alloc();
leftChild->offset = currNode->offset;
leftChild->type = Node::TYPE_FREE;
@@ -12388,13 +9599,12 @@ void VmaBlockMetadata_Buddy::Alloc(
AddToFreeListFront(childrenLevel, leftChild);
++m_FreeCount;
- //m_SumFreeSize -= LevelToNodeSize(currLevel) % 2; // Useful only when level node sizes can be non power of 2.
++currLevel;
currNode = m_FreeList[currLevel].front;
/*
We can be sure that currNode, as left child of node previously split,
- also fullfills the alignment requirement.
+ also fulfills the alignment requirement.
*/
}
@@ -12406,22 +9616,93 @@ void VmaBlockMetadata_Buddy::Alloc(
// Convert to allocation node.
currNode->type = Node::TYPE_ALLOCATION;
- currNode->allocation.alloc = hAllocation;
+ currNode->allocation.userData = userData;
++m_AllocationCount;
--m_FreeCount;
- m_SumFreeSize -= allocSize;
+ m_SumFreeSize -= request.size;
+}
+
+void VmaBlockMetadata_Buddy::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
+{
+ uint32_t level = 0;
+ outInfo.offset = (VkDeviceSize)allocHandle - 1;
+ const Node* const node = FindAllocationNode(outInfo.offset, level);
+ outInfo.size = LevelToNodeSize(level);
+ outInfo.pUserData = node->allocation.userData;
+}
+
+void* VmaBlockMetadata_Buddy::GetAllocationUserData(VmaAllocHandle allocHandle) const
+{
+ uint32_t level = 0;
+ const Node* const node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);
+ return node->allocation.userData;
+}
+
+VmaAllocHandle VmaBlockMetadata_Buddy::GetAllocationListBegin() const
+{
+ // Function only used for defragmentation, which is disabled for this algorithm
+ return VK_NULL_HANDLE;
}
-void VmaBlockMetadata_Buddy::DeleteNode(Node* node)
+VmaAllocHandle VmaBlockMetadata_Buddy::GetNextAllocation(VmaAllocHandle prevAlloc) const
{
- if(node->type == Node::TYPE_SPLIT)
+ // Function only used for defragmentation, which is disabled for this algorithm
+ return VK_NULL_HANDLE;
+}
+
+void VmaBlockMetadata_Buddy::DeleteNodeChildren(Node* node)
+{
+ if (node->type == Node::TYPE_SPLIT)
{
- DeleteNode(node->split.leftChild->buddy);
- DeleteNode(node->split.leftChild);
+ DeleteNodeChildren(node->split.leftChild->buddy);
+ DeleteNodeChildren(node->split.leftChild);
+ const VkAllocationCallbacks* allocationCallbacks = GetAllocationCallbacks();
+ m_NodeAllocator.Free(node->split.leftChild->buddy);
+ m_NodeAllocator.Free(node->split.leftChild);
}
+}
+
+void VmaBlockMetadata_Buddy::Clear()
+{
+ DeleteNodeChildren(m_Root);
+ m_Root->type = Node::TYPE_FREE;
+ m_AllocationCount = 0;
+ m_FreeCount = 1;
+ m_SumFreeSize = m_UsableSize;
+}
- vma_delete(GetAllocationCallbacks(), node);
+void VmaBlockMetadata_Buddy::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
+{
+ uint32_t level = 0;
+ Node* const node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);
+ node->allocation.userData = userData;
+}
+
+VmaBlockMetadata_Buddy::Node* VmaBlockMetadata_Buddy::FindAllocationNode(VkDeviceSize offset, uint32_t& outLevel) const
+{
+ Node* node = m_Root;
+ VkDeviceSize nodeOffset = 0;
+ outLevel = 0;
+ VkDeviceSize levelNodeSize = LevelToNodeSize(0);
+ while (node->type == Node::TYPE_SPLIT)
+ {
+ const VkDeviceSize nextLevelNodeSize = levelNodeSize >> 1;
+ if (offset < nodeOffset + nextLevelNodeSize)
+ {
+ node = node->split.leftChild;
+ }
+ else
+ {
+ node = node->split.leftChild->buddy;
+ nodeOffset += nextLevelNodeSize;
+ }
+ ++outLevel;
+ levelNodeSize = nextLevelNodeSize;
+ }
+
+ VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);
+ return node;
}
bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* parent, const Node* curr, uint32_t level, VkDeviceSize levelNodeSize) const
@@ -12430,7 +9711,7 @@ bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* pa
VMA_VALIDATE(curr->parent == parent);
VMA_VALIDATE((curr->buddy == VMA_NULL) == (parent == VMA_NULL));
VMA_VALIDATE(curr->buddy == VMA_NULL || curr->buddy->buddy == curr);
- switch(curr->type)
+ switch (curr->type)
{
case Node::TYPE_FREE:
// curr->free.prev, next are validated separately.
@@ -12439,28 +9720,30 @@ bool VmaBlockMetadata_Buddy::ValidateNode(ValidationContext& ctx, const Node* pa
break;
case Node::TYPE_ALLOCATION:
++ctx.calculatedAllocationCount;
- ctx.calculatedSumFreeSize += levelNodeSize - curr->allocation.alloc->GetSize();
- VMA_VALIDATE(curr->allocation.alloc != VK_NULL_HANDLE);
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(curr->allocation.userData != VMA_NULL);
+ }
break;
case Node::TYPE_SPLIT:
+ {
+ const uint32_t childrenLevel = level + 1;
+ const VkDeviceSize childrenLevelNodeSize = levelNodeSize >> 1;
+ const Node* const leftChild = curr->split.leftChild;
+ VMA_VALIDATE(leftChild != VMA_NULL);
+ VMA_VALIDATE(leftChild->offset == curr->offset);
+ if (!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))
{
- const uint32_t childrenLevel = level + 1;
- const VkDeviceSize childrenLevelNodeSize = levelNodeSize / 2;
- const Node* const leftChild = curr->split.leftChild;
- VMA_VALIDATE(leftChild != VMA_NULL);
- VMA_VALIDATE(leftChild->offset == curr->offset);
- if(!ValidateNode(ctx, curr, leftChild, childrenLevel, childrenLevelNodeSize))
- {
- VMA_VALIDATE(false && "ValidateNode for left child failed.");
- }
- const Node* const rightChild = leftChild->buddy;
- VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);
- if(!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))
- {
- VMA_VALIDATE(false && "ValidateNode for right child failed.");
- }
+ VMA_VALIDATE(false && "ValidateNode for left child failed.");
}
- break;
+ const Node* const rightChild = leftChild->buddy;
+ VMA_VALIDATE(rightChild->offset == curr->offset + childrenLevelNodeSize);
+ if (!ValidateNode(ctx, curr, rightChild, childrenLevel, childrenLevelNodeSize))
+ {
+ VMA_VALIDATE(false && "ValidateNode for right child failed.");
+ }
+ }
+ break;
default:
return false;
}
@@ -12474,103 +9757,63 @@ uint32_t VmaBlockMetadata_Buddy::AllocSizeToLevel(VkDeviceSize allocSize) const
uint32_t level = 0;
VkDeviceSize currLevelNodeSize = m_UsableSize;
VkDeviceSize nextLevelNodeSize = currLevelNodeSize >> 1;
- while(allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)
+ while (allocSize <= nextLevelNodeSize && level + 1 < m_LevelCount)
{
++level;
- currLevelNodeSize = nextLevelNodeSize;
- nextLevelNodeSize = currLevelNodeSize >> 1;
+ currLevelNodeSize >>= 1;
+ nextLevelNodeSize >>= 1;
}
return level;
}
-void VmaBlockMetadata_Buddy::FreeAtOffset(VmaAllocation alloc, VkDeviceSize offset)
+void VmaBlockMetadata_Buddy::Free(VmaAllocHandle allocHandle)
{
- // Find node and level.
- Node* node = m_Root;
- VkDeviceSize nodeOffset = 0;
uint32_t level = 0;
- VkDeviceSize levelNodeSize = LevelToNodeSize(0);
- while(node->type == Node::TYPE_SPLIT)
- {
- const VkDeviceSize nextLevelSize = levelNodeSize >> 1;
- if(offset < nodeOffset + nextLevelSize)
- {
- node = node->split.leftChild;
- }
- else
- {
- node = node->split.leftChild->buddy;
- nodeOffset += nextLevelSize;
- }
- ++level;
- levelNodeSize = nextLevelSize;
- }
-
- VMA_ASSERT(node != VMA_NULL && node->type == Node::TYPE_ALLOCATION);
- VMA_ASSERT(alloc == VK_NULL_HANDLE || node->allocation.alloc == alloc);
+ Node* node = FindAllocationNode((VkDeviceSize)allocHandle - 1, level);
++m_FreeCount;
--m_AllocationCount;
- m_SumFreeSize += alloc->GetSize();
+ m_SumFreeSize += LevelToNodeSize(level);
node->type = Node::TYPE_FREE;
// Join free nodes if possible.
- while(level > 0 && node->buddy->type == Node::TYPE_FREE)
+ while (level > 0 && node->buddy->type == Node::TYPE_FREE)
{
RemoveFromFreeList(level, node->buddy);
Node* const parent = node->parent;
- vma_delete(GetAllocationCallbacks(), node->buddy);
- vma_delete(GetAllocationCallbacks(), node);
+ m_NodeAllocator.Free(node->buddy);
+ m_NodeAllocator.Free(node);
parent->type = Node::TYPE_FREE;
node = parent;
--level;
- //m_SumFreeSize += LevelToNodeSize(level) % 2; // Useful only when level node sizes can be non power of 2.
--m_FreeCount;
}
AddToFreeListFront(level, node);
}
-void VmaBlockMetadata_Buddy::CalcAllocationStatInfoNode(VmaStatInfo& outInfo, const Node* node, VkDeviceSize levelNodeSize) const
+void VmaBlockMetadata_Buddy::AddNodeToDetailedStatistics(VmaDetailedStatistics& inoutStats, const Node* node, VkDeviceSize levelNodeSize) const
{
- switch(node->type)
+ switch (node->type)
{
case Node::TYPE_FREE:
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += levelNodeSize;
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, levelNodeSize);
- outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, levelNodeSize);
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, levelNodeSize);
break;
case Node::TYPE_ALLOCATION:
- {
- const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
- ++outInfo.allocationCount;
- outInfo.usedBytes += allocSize;
- outInfo.allocationSizeMax = VMA_MAX(outInfo.allocationSizeMax, allocSize);
- outInfo.allocationSizeMin = VMA_MAX(outInfo.allocationSizeMin, allocSize);
-
- const VkDeviceSize unusedRangeSize = levelNodeSize - allocSize;
- if(unusedRangeSize > 0)
- {
- ++outInfo.unusedRangeCount;
- outInfo.unusedBytes += unusedRangeSize;
- outInfo.unusedRangeSizeMax = VMA_MAX(outInfo.unusedRangeSizeMax, unusedRangeSize);
- outInfo.unusedRangeSizeMin = VMA_MAX(outInfo.unusedRangeSizeMin, unusedRangeSize);
- }
- }
+ VmaAddDetailedStatisticsAllocation(inoutStats, levelNodeSize);
break;
case Node::TYPE_SPLIT:
- {
- const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
- const Node* const leftChild = node->split.leftChild;
- CalcAllocationStatInfoNode(outInfo, leftChild, childrenNodeSize);
- const Node* const rightChild = leftChild->buddy;
- CalcAllocationStatInfoNode(outInfo, rightChild, childrenNodeSize);
- }
- break;
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ AddNodeToDetailedStatistics(inoutStats, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ AddNodeToDetailedStatistics(inoutStats, rightChild, childrenNodeSize);
+ }
+ break;
default:
VMA_ASSERT(0);
}
@@ -12582,7 +9825,7 @@ void VmaBlockMetadata_Buddy::AddToFreeListFront(uint32_t level, Node* node)
// List is empty.
Node* const frontNode = m_FreeList[level].front;
- if(frontNode == VMA_NULL)
+ if (frontNode == VMA_NULL)
{
VMA_ASSERT(m_FreeList[level].back == VMA_NULL);
node->free.prev = node->free.next = VMA_NULL;
@@ -12603,7 +9846,7 @@ void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
VMA_ASSERT(m_FreeList[level].front != VMA_NULL);
// It is at the front.
- if(node->free.prev == VMA_NULL)
+ if (node->free.prev == VMA_NULL)
{
VMA_ASSERT(m_FreeList[level].front == node);
m_FreeList[level].front = node->free.next;
@@ -12616,7 +9859,7 @@ void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
}
// It is at the back.
- if(node->free.next == VMA_NULL)
+ if (node->free.next == VMA_NULL)
{
VMA_ASSERT(m_FreeList[level].back == node);
m_FreeList[level].back = node->free.prev;
@@ -12629,85 +9872,1894 @@ void VmaBlockMetadata_Buddy::RemoveFromFreeList(uint32_t level, Node* node)
}
}
+void VmaBlockMetadata_Buddy::DebugLogAllAllocationNode(Node* node, uint32_t level) const
+{
+ switch (node->type)
+ {
+ case Node::TYPE_FREE:
+ break;
+ case Node::TYPE_ALLOCATION:
+ DebugLogAllocation(node->offset, LevelToNodeSize(level), node->allocation.userData);
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ ++level;
+ DebugLogAllAllocationNode(node->split.leftChild, level);
+ DebugLogAllAllocationNode(node->split.leftChild->buddy, level);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+
#if VMA_STATS_STRING_ENABLED
void VmaBlockMetadata_Buddy::PrintDetailedMapNode(class VmaJsonWriter& json, const Node* node, VkDeviceSize levelNodeSize) const
{
- switch(node->type)
+ switch (node->type)
{
case Node::TYPE_FREE:
PrintDetailedMap_UnusedRange(json, node->offset, levelNodeSize);
break;
case Node::TYPE_ALLOCATION:
+ PrintDetailedMap_Allocation(json, node->offset, levelNodeSize, node->allocation.userData);
+ break;
+ case Node::TYPE_SPLIT:
+ {
+ const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
+ const Node* const leftChild = node->split.leftChild;
+ PrintDetailedMapNode(json, leftChild, childrenNodeSize);
+ const Node* const rightChild = leftChild->buddy;
+ PrintDetailedMapNode(json, rightChild, childrenNodeSize);
+ }
+ break;
+ default:
+ VMA_ASSERT(0);
+ }
+}
+#endif // VMA_STATS_STRING_ENABLED
+#endif // _VMA_BLOCK_METADATA_BUDDY_FUNCTIONS
+#endif // _VMA_BLOCK_METADATA_BUDDY
+#endif // #if 0
+
+#ifndef _VMA_BLOCK_METADATA_TLSF
+// To not search current larger region if first allocation won't succeed and skip to smaller range
+// use with VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT as strategy in CreateAllocationRequest().
+// When fragmentation and reusal of previous blocks doesn't matter then use with
+// VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT for fastest alloc time possible.
+class VmaBlockMetadata_TLSF : public VmaBlockMetadata
+{
+ VMA_CLASS_NO_COPY(VmaBlockMetadata_TLSF)
+public:
+ VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual);
+ virtual ~VmaBlockMetadata_TLSF();
+
+ size_t GetAllocationCount() const override { return m_AllocCount; }
+ size_t GetFreeRegionsCount() const override { return m_BlocksFreeCount + 1; }
+ VkDeviceSize GetSumFreeSize() const override { return m_BlocksFreeSize + m_NullBlock->size; }
+ bool IsEmpty() const override { return m_NullBlock->offset == 0; }
+ VkDeviceSize GetAllocationOffset(VmaAllocHandle allocHandle) const override { return ((Block*)allocHandle)->offset; };
+
+ void Init(VkDeviceSize size) override;
+ bool Validate() const override;
+
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const override;
+ void AddStatistics(VmaStatistics& inoutStats) const override;
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json) const override;
+#endif
+
+ bool CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest) override;
+
+ VkResult CheckCorruption(const void* pBlockData) override;
+ void Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData) override;
+
+ void Free(VmaAllocHandle allocHandle) override;
+ void GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo) override;
+ void* GetAllocationUserData(VmaAllocHandle allocHandle) const override;
+ VmaAllocHandle GetAllocationListBegin() const override;
+ VmaAllocHandle GetNextAllocation(VmaAllocHandle prevAlloc) const override;
+ VkDeviceSize GetNextFreeRegionSize(VmaAllocHandle alloc) const override;
+ void Clear() override;
+ void SetAllocationUserData(VmaAllocHandle allocHandle, void* userData) override;
+ void DebugLogAllAllocations() const override;
+
+private:
+ // According to original paper it should be preferable 4 or 5:
+ // M. Masmano, I. Ripoll, A. Crespo, and J. Real "TLSF: a New Dynamic Memory Allocator for Real-Time Systems"
+ // http://www.gii.upv.es/tlsf/files/ecrts04_tlsf.pdf
+ static const uint8_t SECOND_LEVEL_INDEX = 5;
+ static const uint16_t SMALL_BUFFER_SIZE = 256;
+ static const uint32_t INITIAL_BLOCK_ALLOC_COUNT = 16;
+ static const uint8_t MEMORY_CLASS_SHIFT = 7;
+ static const uint8_t MAX_MEMORY_CLASSES = 65 - MEMORY_CLASS_SHIFT;
+
+ class Block
+ {
+ public:
+ VkDeviceSize offset;
+ VkDeviceSize size;
+ Block* prevPhysical;
+ Block* nextPhysical;
+
+ void MarkFree() { prevFree = VMA_NULL; }
+ void MarkTaken() { prevFree = this; }
+ bool IsFree() const { return prevFree != this; }
+ void*& UserData() { VMA_HEAVY_ASSERT(!IsFree()); return userData; }
+ Block*& PrevFree() { return prevFree; }
+ Block*& NextFree() { VMA_HEAVY_ASSERT(IsFree()); return nextFree; }
+
+ private:
+ Block* prevFree; // Address of the same block here indicates that block is taken
+ union
{
- PrintDetailedMap_Allocation(json, node->offset, node->allocation.alloc);
- const VkDeviceSize allocSize = node->allocation.alloc->GetSize();
- if(allocSize < levelNodeSize)
+ Block* nextFree;
+ void* userData;
+ };
+ };
+
+ size_t m_AllocCount;
+ // Total number of free blocks besides null block
+ size_t m_BlocksFreeCount;
+ // Total size of free blocks excluding null block
+ VkDeviceSize m_BlocksFreeSize;
+ uint32_t m_IsFreeBitmap;
+ uint8_t m_MemoryClasses;
+ uint32_t m_InnerIsFreeBitmap[MAX_MEMORY_CLASSES];
+ uint32_t m_ListsCount;
+ /*
+ * 0: 0-3 lists for small buffers
+ * 1+: 0-(2^SLI-1) lists for normal buffers
+ */
+ Block** m_FreeList;
+ VmaPoolAllocator<Block> m_BlockAllocator;
+ Block* m_NullBlock;
+ VmaBlockBufferImageGranularity m_GranularityHandler;
+
+ uint8_t SizeToMemoryClass(VkDeviceSize size) const;
+ uint16_t SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const;
+ uint32_t GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const;
+ uint32_t GetListIndex(VkDeviceSize size) const;
+
+ void RemoveFreeBlock(Block* block);
+ void InsertFreeBlock(Block* block);
+ void MergeBlock(Block* block, Block* prev);
+
+ Block* FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const;
+ bool CheckBlock(
+ Block& block,
+ uint32_t listIndex,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaAllocationRequest* pAllocationRequest);
+};
+
+#ifndef _VMA_BLOCK_METADATA_TLSF_FUNCTIONS
+VmaBlockMetadata_TLSF::VmaBlockMetadata_TLSF(const VkAllocationCallbacks* pAllocationCallbacks,
+ VkDeviceSize bufferImageGranularity, bool isVirtual)
+ : VmaBlockMetadata(pAllocationCallbacks, bufferImageGranularity, isVirtual),
+ m_AllocCount(0),
+ m_BlocksFreeCount(0),
+ m_BlocksFreeSize(0),
+ m_IsFreeBitmap(0),
+ m_MemoryClasses(0),
+ m_ListsCount(0),
+ m_FreeList(VMA_NULL),
+ m_BlockAllocator(pAllocationCallbacks, INITIAL_BLOCK_ALLOC_COUNT),
+ m_NullBlock(VMA_NULL),
+ m_GranularityHandler(bufferImageGranularity) {}
+
+VmaBlockMetadata_TLSF::~VmaBlockMetadata_TLSF()
+{
+ if (m_FreeList)
+ vma_delete_array(GetAllocationCallbacks(), m_FreeList, m_ListsCount);
+ m_GranularityHandler.Destroy(GetAllocationCallbacks());
+}
+
+void VmaBlockMetadata_TLSF::Init(VkDeviceSize size)
+{
+ VmaBlockMetadata::Init(size);
+
+ if (!IsVirtual())
+ m_GranularityHandler.Init(GetAllocationCallbacks(), size);
+
+ m_NullBlock = m_BlockAllocator.Alloc();
+ m_NullBlock->size = size;
+ m_NullBlock->offset = 0;
+ m_NullBlock->prevPhysical = VMA_NULL;
+ m_NullBlock->nextPhysical = VMA_NULL;
+ m_NullBlock->MarkFree();
+ m_NullBlock->NextFree() = VMA_NULL;
+ m_NullBlock->PrevFree() = VMA_NULL;
+ uint8_t memoryClass = SizeToMemoryClass(size);
+ uint16_t sli = SizeToSecondIndex(size, memoryClass);
+ m_ListsCount = (memoryClass == 0 ? 0 : (memoryClass - 1) * (1UL << SECOND_LEVEL_INDEX) + sli) + 1;
+ if (IsVirtual())
+ m_ListsCount += 1UL << SECOND_LEVEL_INDEX;
+ else
+ m_ListsCount += 4;
+
+ m_MemoryClasses = memoryClass + 2;
+ memset(m_InnerIsFreeBitmap, 0, MAX_MEMORY_CLASSES * sizeof(uint32_t));
+
+ m_FreeList = vma_new_array(GetAllocationCallbacks(), Block*, m_ListsCount);
+ memset(m_FreeList, 0, m_ListsCount * sizeof(Block*));
+}
+
+bool VmaBlockMetadata_TLSF::Validate() const
+{
+ VMA_VALIDATE(GetSumFreeSize() <= GetSize());
+
+ VkDeviceSize calculatedSize = m_NullBlock->size;
+ VkDeviceSize calculatedFreeSize = m_NullBlock->size;
+ size_t allocCount = 0;
+ size_t freeCount = 0;
+
+ // Check integrity of free lists
+ for (uint32_t list = 0; list < m_ListsCount; ++list)
+ {
+ Block* block = m_FreeList[list];
+ if (block != VMA_NULL)
+ {
+ VMA_VALIDATE(block->IsFree());
+ VMA_VALIDATE(block->PrevFree() == VMA_NULL);
+ while (block->NextFree())
{
- PrintDetailedMap_UnusedRange(json, node->offset + allocSize, levelNodeSize - allocSize);
+ VMA_VALIDATE(block->NextFree()->IsFree());
+ VMA_VALIDATE(block->NextFree()->PrevFree() == block);
+ block = block->NextFree();
}
}
- break;
- case Node::TYPE_SPLIT:
+ }
+
+ VkDeviceSize nextOffset = m_NullBlock->offset;
+ auto validateCtx = m_GranularityHandler.StartValidation(GetAllocationCallbacks(), IsVirtual());
+
+ VMA_VALIDATE(m_NullBlock->nextPhysical == VMA_NULL);
+ if (m_NullBlock->prevPhysical)
+ {
+ VMA_VALIDATE(m_NullBlock->prevPhysical->nextPhysical == m_NullBlock);
+ }
+ // Check all blocks
+ for (Block* prev = m_NullBlock->prevPhysical; prev != VMA_NULL; prev = prev->prevPhysical)
+ {
+ VMA_VALIDATE(prev->offset + prev->size == nextOffset);
+ nextOffset = prev->offset;
+ calculatedSize += prev->size;
+
+ uint32_t listIndex = GetListIndex(prev->size);
+ if (prev->IsFree())
{
- const VkDeviceSize childrenNodeSize = levelNodeSize / 2;
- const Node* const leftChild = node->split.leftChild;
- PrintDetailedMapNode(json, leftChild, childrenNodeSize);
- const Node* const rightChild = leftChild->buddy;
- PrintDetailedMapNode(json, rightChild, childrenNodeSize);
+ ++freeCount;
+ // Check if free block belongs to free list
+ Block* freeBlock = m_FreeList[listIndex];
+ VMA_VALIDATE(freeBlock != VMA_NULL);
+
+ bool found = false;
+ do
+ {
+ if (freeBlock == prev)
+ found = true;
+
+ freeBlock = freeBlock->NextFree();
+ } while (!found && freeBlock != VMA_NULL);
+
+ VMA_VALIDATE(found);
+ calculatedFreeSize += prev->size;
}
- break;
+ else
+ {
+ ++allocCount;
+ // Check if taken block is not on a free list
+ Block* freeBlock = m_FreeList[listIndex];
+ while (freeBlock)
+ {
+ VMA_VALIDATE(freeBlock != prev);
+ freeBlock = freeBlock->NextFree();
+ }
+
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(m_GranularityHandler.Validate(validateCtx, prev->offset, prev->size));
+ }
+ }
+
+ if (prev->prevPhysical)
+ {
+ VMA_VALIDATE(prev->prevPhysical->nextPhysical == prev);
+ }
+ }
+
+ if (!IsVirtual())
+ {
+ VMA_VALIDATE(m_GranularityHandler.FinishValidation(validateCtx));
+ }
+
+ VMA_VALIDATE(nextOffset == 0);
+ VMA_VALIDATE(calculatedSize == GetSize());
+ VMA_VALIDATE(calculatedFreeSize == GetSumFreeSize());
+ VMA_VALIDATE(allocCount == m_AllocCount);
+ VMA_VALIDATE(freeCount == m_BlocksFreeCount);
+
+ return true;
+}
+
+void VmaBlockMetadata_TLSF::AddDetailedStatistics(VmaDetailedStatistics& inoutStats) const
+{
+ inoutStats.statistics.blockCount++;
+ inoutStats.statistics.blockBytes += GetSize();
+ if (m_NullBlock->size > 0)
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, m_NullBlock->size);
+
+ for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
+ {
+ if (block->IsFree())
+ VmaAddDetailedStatisticsUnusedRange(inoutStats, block->size);
+ else
+ VmaAddDetailedStatisticsAllocation(inoutStats, block->size);
+ }
+}
+
+void VmaBlockMetadata_TLSF::AddStatistics(VmaStatistics& inoutStats) const
+{
+ inoutStats.blockCount++;
+ inoutStats.allocationCount += (uint32_t)m_AllocCount;
+ inoutStats.blockBytes += GetSize();
+ inoutStats.allocationBytes += GetSize() - GetSumFreeSize();
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockMetadata_TLSF::PrintDetailedMap(class VmaJsonWriter& json) const
+{
+ size_t blockCount = m_AllocCount + m_BlocksFreeCount;
+ VmaStlAllocator<Block*> allocator(GetAllocationCallbacks());
+ VmaVector<Block*, VmaStlAllocator<Block*>> blockList(blockCount, allocator);
+
+ size_t i = blockCount;
+ for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
+ {
+ blockList[--i] = block;
+ }
+ VMA_ASSERT(i == 0);
+
+ VmaDetailedStatistics stats;
+ VmaClearDetailedStatistics(stats);
+ AddDetailedStatistics(stats);
+
+ PrintDetailedMap_Begin(json,
+ stats.statistics.blockBytes - stats.statistics.allocationBytes,
+ stats.statistics.allocationCount,
+ stats.unusedRangeCount);
+
+ for (; i < blockCount; ++i)
+ {
+ Block* block = blockList[i];
+ if (block->IsFree())
+ PrintDetailedMap_UnusedRange(json, block->offset, block->size);
+ else
+ PrintDetailedMap_Allocation(json, block->offset, block->size, block->UserData());
+ }
+ if (m_NullBlock->size > 0)
+ PrintDetailedMap_UnusedRange(json, m_NullBlock->offset, m_NullBlock->size);
+
+ PrintDetailedMap_End(json);
+}
+#endif
+
+bool VmaBlockMetadata_TLSF::CreateAllocationRequest(
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ bool upperAddress,
+ VmaSuballocationType allocType,
+ uint32_t strategy,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(allocSize > 0 && "Cannot allocate empty block!");
+ VMA_ASSERT(!upperAddress && "VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT can be used only with linear algorithm.");
+
+ // For small granularity round up
+ if (!IsVirtual())
+ m_GranularityHandler.RoundupAllocRequest(allocType, allocSize, allocAlignment);
+
+ allocSize += GetDebugMargin();
+ // Quick check for too small pool
+ if (allocSize > GetSumFreeSize())
+ return false;
+
+ // If no free blocks in pool then check only null block
+ if (m_BlocksFreeCount == 0)
+ return CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest);
+
+ // Round up to the next block
+ VkDeviceSize sizeForNextList = allocSize;
+ VkDeviceSize smallSizeStep = SMALL_BUFFER_SIZE / (IsVirtual() ? 1 << SECOND_LEVEL_INDEX : 4);
+ if (allocSize > SMALL_BUFFER_SIZE)
+ {
+ sizeForNextList += (1ULL << (VMA_BITSCAN_MSB(allocSize) - SECOND_LEVEL_INDEX));
+ }
+ else if (allocSize > SMALL_BUFFER_SIZE - smallSizeStep)
+ sizeForNextList = SMALL_BUFFER_SIZE + 1;
+ else
+ sizeForNextList += smallSizeStep;
+
+ uint32_t nextListIndex = 0;
+ uint32_t prevListIndex = 0;
+ Block* nextListBlock = VMA_NULL;
+ Block* prevListBlock = VMA_NULL;
+
+ // Check blocks according to strategies
+ if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT)
+ {
+ // Quick check for larger block first
+ nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);
+ if (nextListBlock != VMA_NULL && CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+
+ // If not fitted then null block
+ if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+
+ // Null block failed, search larger bucket
+ while (nextListBlock)
+ {
+ if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ nextListBlock = nextListBlock->NextFree();
+ }
+
+ // Failed again, check best fit bucket
+ prevListBlock = FindFreeBlock(allocSize, prevListIndex);
+ while (prevListBlock)
+ {
+ if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ prevListBlock = prevListBlock->NextFree();
+ }
+ }
+ else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT)
+ {
+ // Check best fit bucket
+ prevListBlock = FindFreeBlock(allocSize, prevListIndex);
+ while (prevListBlock)
+ {
+ if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ prevListBlock = prevListBlock->NextFree();
+ }
+
+ // If failed check null block
+ if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+
+ // Check larger bucket
+ nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);
+ while (nextListBlock)
+ {
+ if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ nextListBlock = nextListBlock->NextFree();
+ }
+ }
+ else if (strategy & VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT )
+ {
+ // Perform search from the start
+ VmaStlAllocator<Block*> allocator(GetAllocationCallbacks());
+ VmaVector<Block*, VmaStlAllocator<Block*>> blockList(m_BlocksFreeCount, allocator);
+
+ size_t i = m_BlocksFreeCount;
+ for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
+ {
+ if (block->IsFree() && block->size >= allocSize)
+ blockList[--i] = block;
+ }
+
+ for (; i < m_BlocksFreeCount; ++i)
+ {
+ Block& block = *blockList[i];
+ if (CheckBlock(block, GetListIndex(block.size), allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ }
+
+ // If failed check null block
+ if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+
+ // Whole range searched, no more memory
+ return false;
+ }
+ else
+ {
+ // Check larger bucket
+ nextListBlock = FindFreeBlock(sizeForNextList, nextListIndex);
+ while (nextListBlock)
+ {
+ if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ nextListBlock = nextListBlock->NextFree();
+ }
+
+ // If failed check null block
+ if (CheckBlock(*m_NullBlock, m_ListsCount, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+
+ // Check best fit bucket
+ prevListBlock = FindFreeBlock(allocSize, prevListIndex);
+ while (prevListBlock)
+ {
+ if (CheckBlock(*prevListBlock, prevListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ prevListBlock = prevListBlock->NextFree();
+ }
+ }
+
+ // Worst case, full search has to be done
+ while (++nextListIndex < m_ListsCount)
+ {
+ nextListBlock = m_FreeList[nextListIndex];
+ while (nextListBlock)
+ {
+ if (CheckBlock(*nextListBlock, nextListIndex, allocSize, allocAlignment, allocType, pAllocationRequest))
+ return true;
+ nextListBlock = nextListBlock->NextFree();
+ }
+ }
+
+ // No more memory sadly
+ return false;
+}
+
+VkResult VmaBlockMetadata_TLSF::CheckCorruption(const void* pBlockData)
+{
+ for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
+ {
+ if (!block->IsFree())
+ {
+ if (!VmaValidateMagicValue(pBlockData, block->offset + block->size))
+ {
+ VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER VALIDATED ALLOCATION!");
+ return VK_ERROR_UNKNOWN_COPY;
+ }
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+void VmaBlockMetadata_TLSF::Alloc(
+ const VmaAllocationRequest& request,
+ VmaSuballocationType type,
+ void* userData)
+{
+ VMA_ASSERT(request.type == VmaAllocationRequestType::TLSF);
+
+ // Get block and pop it from the free list
+ Block* currentBlock = (Block*)request.allocHandle;
+ VkDeviceSize offset = request.algorithmData;
+ VMA_ASSERT(currentBlock != VMA_NULL);
+ VMA_ASSERT(currentBlock->offset <= offset);
+
+ if (currentBlock != m_NullBlock)
+ RemoveFreeBlock(currentBlock);
+
+ VkDeviceSize debugMargin = GetDebugMargin();
+ VkDeviceSize misssingAlignment = offset - currentBlock->offset;
+
+ // Append missing alignment to prev block or create new one
+ if (misssingAlignment)
+ {
+ Block* prevBlock = currentBlock->prevPhysical;
+ VMA_ASSERT(prevBlock != VMA_NULL && "There should be no missing alignment at offset 0!");
+
+ if (prevBlock->IsFree() && prevBlock->size != debugMargin)
+ {
+ uint32_t oldList = GetListIndex(prevBlock->size);
+ prevBlock->size += misssingAlignment;
+ // Check if new size crosses list bucket
+ if (oldList != GetListIndex(prevBlock->size))
+ {
+ prevBlock->size -= misssingAlignment;
+ RemoveFreeBlock(prevBlock);
+ prevBlock->size += misssingAlignment;
+ InsertFreeBlock(prevBlock);
+ }
+ else
+ m_BlocksFreeSize += misssingAlignment;
+ }
+ else
+ {
+ Block* newBlock = m_BlockAllocator.Alloc();
+ currentBlock->prevPhysical = newBlock;
+ prevBlock->nextPhysical = newBlock;
+ newBlock->prevPhysical = prevBlock;
+ newBlock->nextPhysical = currentBlock;
+ newBlock->size = misssingAlignment;
+ newBlock->offset = currentBlock->offset;
+ newBlock->MarkTaken();
+
+ InsertFreeBlock(newBlock);
+ }
+
+ currentBlock->size -= misssingAlignment;
+ currentBlock->offset += misssingAlignment;
+ }
+
+ VkDeviceSize size = request.size + debugMargin;
+ if (currentBlock->size == size)
+ {
+ if (currentBlock == m_NullBlock)
+ {
+ // Setup new null block
+ m_NullBlock = m_BlockAllocator.Alloc();
+ m_NullBlock->size = 0;
+ m_NullBlock->offset = currentBlock->offset + size;
+ m_NullBlock->prevPhysical = currentBlock;
+ m_NullBlock->nextPhysical = VMA_NULL;
+ m_NullBlock->MarkFree();
+ m_NullBlock->PrevFree() = VMA_NULL;
+ m_NullBlock->NextFree() = VMA_NULL;
+ currentBlock->nextPhysical = m_NullBlock;
+ currentBlock->MarkTaken();
+ }
+ }
+ else
+ {
+ VMA_ASSERT(currentBlock->size > size && "Proper block already found, shouldn't find smaller one!");
+
+ // Create new free block
+ Block* newBlock = m_BlockAllocator.Alloc();
+ newBlock->size = currentBlock->size - size;
+ newBlock->offset = currentBlock->offset + size;
+ newBlock->prevPhysical = currentBlock;
+ newBlock->nextPhysical = currentBlock->nextPhysical;
+ currentBlock->nextPhysical = newBlock;
+ currentBlock->size = size;
+
+ if (currentBlock == m_NullBlock)
+ {
+ m_NullBlock = newBlock;
+ m_NullBlock->MarkFree();
+ m_NullBlock->NextFree() = VMA_NULL;
+ m_NullBlock->PrevFree() = VMA_NULL;
+ currentBlock->MarkTaken();
+ }
+ else
+ {
+ newBlock->nextPhysical->prevPhysical = newBlock;
+ newBlock->MarkTaken();
+ InsertFreeBlock(newBlock);
+ }
+ }
+ currentBlock->UserData() = userData;
+
+ if (debugMargin > 0)
+ {
+ currentBlock->size -= debugMargin;
+ Block* newBlock = m_BlockAllocator.Alloc();
+ newBlock->size = debugMargin;
+ newBlock->offset = currentBlock->offset + currentBlock->size;
+ newBlock->prevPhysical = currentBlock;
+ newBlock->nextPhysical = currentBlock->nextPhysical;
+ newBlock->MarkTaken();
+ currentBlock->nextPhysical->prevPhysical = newBlock;
+ currentBlock->nextPhysical = newBlock;
+ InsertFreeBlock(newBlock);
+ }
+
+ if (!IsVirtual())
+ m_GranularityHandler.AllocPages((uint8_t)(uintptr_t)request.customData,
+ currentBlock->offset, currentBlock->size);
+ ++m_AllocCount;
+}
+
+void VmaBlockMetadata_TLSF::Free(VmaAllocHandle allocHandle)
+{
+ Block* block = (Block*)allocHandle;
+ Block* next = block->nextPhysical;
+ VMA_ASSERT(!block->IsFree() && "Block is already free!");
+
+ if (!IsVirtual())
+ m_GranularityHandler.FreePages(block->offset, block->size);
+ --m_AllocCount;
+
+ VkDeviceSize debugMargin = GetDebugMargin();
+ if (debugMargin > 0)
+ {
+ RemoveFreeBlock(next);
+ MergeBlock(next, block);
+ block = next;
+ next = next->nextPhysical;
+ }
+
+ // Try merging
+ Block* prev = block->prevPhysical;
+ if (prev != VMA_NULL && prev->IsFree() && prev->size != debugMargin)
+ {
+ RemoveFreeBlock(prev);
+ MergeBlock(block, prev);
+ }
+
+ if (!next->IsFree())
+ InsertFreeBlock(block);
+ else if (next == m_NullBlock)
+ MergeBlock(m_NullBlock, block);
+ else
+ {
+ RemoveFreeBlock(next);
+ MergeBlock(next, block);
+ InsertFreeBlock(next);
+ }
+}
+
+void VmaBlockMetadata_TLSF::GetAllocationInfo(VmaAllocHandle allocHandle, VmaVirtualAllocationInfo& outInfo)
+{
+ Block* block = (Block*)allocHandle;
+ VMA_ASSERT(!block->IsFree() && "Cannot get allocation info for free block!");
+ outInfo.offset = block->offset;
+ outInfo.size = block->size;
+ outInfo.pUserData = block->UserData();
+}
+
+void* VmaBlockMetadata_TLSF::GetAllocationUserData(VmaAllocHandle allocHandle) const
+{
+ Block* block = (Block*)allocHandle;
+ VMA_ASSERT(!block->IsFree() && "Cannot get user data for free block!");
+ return block->UserData();
+}
+
+VmaAllocHandle VmaBlockMetadata_TLSF::GetAllocationListBegin() const
+{
+ if (m_AllocCount == 0)
+ return VK_NULL_HANDLE;
+
+ for (Block* block = m_NullBlock->prevPhysical; block; block = block->prevPhysical)
+ {
+ if (!block->IsFree())
+ return (VmaAllocHandle)block;
+ }
+ VMA_ASSERT(false && "If m_AllocCount > 0 then should find any allocation!");
+ return VK_NULL_HANDLE;
+}
+
+VmaAllocHandle VmaBlockMetadata_TLSF::GetNextAllocation(VmaAllocHandle prevAlloc) const
+{
+ Block* startBlock = (Block*)prevAlloc;
+ VMA_ASSERT(!startBlock->IsFree() && "Incorrect block!");
+
+ for (Block* block = startBlock->prevPhysical; block; block = block->prevPhysical)
+ {
+ if (!block->IsFree())
+ return (VmaAllocHandle)block;
+ }
+ return VK_NULL_HANDLE;
+}
+
+VkDeviceSize VmaBlockMetadata_TLSF::GetNextFreeRegionSize(VmaAllocHandle alloc) const
+{
+ Block* block = (Block*)alloc;
+ VMA_ASSERT(!block->IsFree() && "Incorrect block!");
+
+ if (block->prevPhysical)
+ return block->prevPhysical->IsFree() ? block->prevPhysical->size : 0;
+ return 0;
+}
+
+void VmaBlockMetadata_TLSF::Clear()
+{
+ m_AllocCount = 0;
+ m_BlocksFreeCount = 0;
+ m_BlocksFreeSize = 0;
+ m_IsFreeBitmap = 0;
+ m_NullBlock->offset = 0;
+ m_NullBlock->size = GetSize();
+ Block* block = m_NullBlock->prevPhysical;
+ m_NullBlock->prevPhysical = VMA_NULL;
+ while (block)
+ {
+ Block* prev = block->prevPhysical;
+ m_BlockAllocator.Free(block);
+ block = prev;
+ }
+ memset(m_FreeList, 0, m_ListsCount * sizeof(Block*));
+ memset(m_InnerIsFreeBitmap, 0, m_MemoryClasses * sizeof(uint32_t));
+ m_GranularityHandler.Clear();
+}
+
+void VmaBlockMetadata_TLSF::SetAllocationUserData(VmaAllocHandle allocHandle, void* userData)
+{
+ Block* block = (Block*)allocHandle;
+ VMA_ASSERT(!block->IsFree() && "Trying to set user data for not allocated block!");
+ block->UserData() = userData;
+}
+
+void VmaBlockMetadata_TLSF::DebugLogAllAllocations() const
+{
+ for (Block* block = m_NullBlock->prevPhysical; block != VMA_NULL; block = block->prevPhysical)
+ if (!block->IsFree())
+ DebugLogAllocation(block->offset, block->size, block->UserData());
+}
+
+uint8_t VmaBlockMetadata_TLSF::SizeToMemoryClass(VkDeviceSize size) const
+{
+ if (size > SMALL_BUFFER_SIZE)
+ return VMA_BITSCAN_MSB(size) - MEMORY_CLASS_SHIFT;
+ return 0;
+}
+
+uint16_t VmaBlockMetadata_TLSF::SizeToSecondIndex(VkDeviceSize size, uint8_t memoryClass) const
+{
+ if (memoryClass == 0)
+ {
+ if (IsVirtual())
+ return static_cast<uint16_t>((size - 1) / 8);
+ else
+ return static_cast<uint16_t>((size - 1) / 64);
+ }
+ return static_cast<uint16_t>((size >> (memoryClass + MEMORY_CLASS_SHIFT - SECOND_LEVEL_INDEX)) ^ (1U << SECOND_LEVEL_INDEX));
+}
+
+uint32_t VmaBlockMetadata_TLSF::GetListIndex(uint8_t memoryClass, uint16_t secondIndex) const
+{
+ if (memoryClass == 0)
+ return secondIndex;
+
+ const uint32_t index = static_cast<uint32_t>(memoryClass - 1) * (1 << SECOND_LEVEL_INDEX) + secondIndex;
+ if (IsVirtual())
+ return index + (1 << SECOND_LEVEL_INDEX);
+ else
+ return index + 4;
+}
+
+uint32_t VmaBlockMetadata_TLSF::GetListIndex(VkDeviceSize size) const
+{
+ uint8_t memoryClass = SizeToMemoryClass(size);
+ return GetListIndex(memoryClass, SizeToSecondIndex(size, memoryClass));
+}
+
+void VmaBlockMetadata_TLSF::RemoveFreeBlock(Block* block)
+{
+ VMA_ASSERT(block != m_NullBlock);
+ VMA_ASSERT(block->IsFree());
+
+ if (block->NextFree() != VMA_NULL)
+ block->NextFree()->PrevFree() = block->PrevFree();
+ if (block->PrevFree() != VMA_NULL)
+ block->PrevFree()->NextFree() = block->NextFree();
+ else
+ {
+ uint8_t memClass = SizeToMemoryClass(block->size);
+ uint16_t secondIndex = SizeToSecondIndex(block->size, memClass);
+ uint32_t index = GetListIndex(memClass, secondIndex);
+ VMA_ASSERT(m_FreeList[index] == block);
+ m_FreeList[index] = block->NextFree();
+ if (block->NextFree() == VMA_NULL)
+ {
+ m_InnerIsFreeBitmap[memClass] &= ~(1U << secondIndex);
+ if (m_InnerIsFreeBitmap[memClass] == 0)
+ m_IsFreeBitmap &= ~(1UL << memClass);
+ }
+ }
+ block->MarkTaken();
+ block->UserData() = VMA_NULL;
+ --m_BlocksFreeCount;
+ m_BlocksFreeSize -= block->size;
+}
+
+void VmaBlockMetadata_TLSF::InsertFreeBlock(Block* block)
+{
+ VMA_ASSERT(block != m_NullBlock);
+ VMA_ASSERT(!block->IsFree() && "Cannot insert block twice!");
+
+ uint8_t memClass = SizeToMemoryClass(block->size);
+ uint16_t secondIndex = SizeToSecondIndex(block->size, memClass);
+ uint32_t index = GetListIndex(memClass, secondIndex);
+ VMA_ASSERT(index < m_ListsCount);
+ block->PrevFree() = VMA_NULL;
+ block->NextFree() = m_FreeList[index];
+ m_FreeList[index] = block;
+ if (block->NextFree() != VMA_NULL)
+ block->NextFree()->PrevFree() = block;
+ else
+ {
+ m_InnerIsFreeBitmap[memClass] |= 1U << secondIndex;
+ m_IsFreeBitmap |= 1UL << memClass;
+ }
+ ++m_BlocksFreeCount;
+ m_BlocksFreeSize += block->size;
+}
+
+void VmaBlockMetadata_TLSF::MergeBlock(Block* block, Block* prev)
+{
+ VMA_ASSERT(block->prevPhysical == prev && "Cannot merge seperate physical regions!");
+ VMA_ASSERT(!prev->IsFree() && "Cannot merge block that belongs to free list!");
+
+ block->offset = prev->offset;
+ block->size += prev->size;
+ block->prevPhysical = prev->prevPhysical;
+ if (block->prevPhysical)
+ block->prevPhysical->nextPhysical = block;
+ m_BlockAllocator.Free(prev);
+}
+
+VmaBlockMetadata_TLSF::Block* VmaBlockMetadata_TLSF::FindFreeBlock(VkDeviceSize size, uint32_t& listIndex) const
+{
+ uint8_t memoryClass = SizeToMemoryClass(size);
+ uint32_t innerFreeMap = m_InnerIsFreeBitmap[memoryClass] & (~0U << SizeToSecondIndex(size, memoryClass));
+ if (!innerFreeMap)
+ {
+ // Check higher levels for avaiable blocks
+ uint32_t freeMap = m_IsFreeBitmap & (~0UL << (memoryClass + 1));
+ if (!freeMap)
+ return VMA_NULL; // No more memory avaible
+
+ // Find lowest free region
+ memoryClass = VMA_BITSCAN_LSB(freeMap);
+ innerFreeMap = m_InnerIsFreeBitmap[memoryClass];
+ VMA_ASSERT(innerFreeMap != 0);
+ }
+ // Find lowest free subregion
+ listIndex = GetListIndex(memoryClass, VMA_BITSCAN_LSB(innerFreeMap));
+ VMA_ASSERT(m_FreeList[listIndex]);
+ return m_FreeList[listIndex];
+}
+
+bool VmaBlockMetadata_TLSF::CheckBlock(
+ Block& block,
+ uint32_t listIndex,
+ VkDeviceSize allocSize,
+ VkDeviceSize allocAlignment,
+ VmaSuballocationType allocType,
+ VmaAllocationRequest* pAllocationRequest)
+{
+ VMA_ASSERT(block.IsFree() && "Block is already taken!");
+
+ VkDeviceSize alignedOffset = VmaAlignUp(block.offset, allocAlignment);
+ if (block.size < allocSize + alignedOffset - block.offset)
+ return false;
+
+ // Check for granularity conflicts
+ if (!IsVirtual() &&
+ m_GranularityHandler.CheckConflictAndAlignUp(alignedOffset, allocSize, block.offset, block.size, allocType))
+ return false;
+
+ // Alloc successful
+ pAllocationRequest->type = VmaAllocationRequestType::TLSF;
+ pAllocationRequest->allocHandle = (VmaAllocHandle)&block;
+ pAllocationRequest->size = allocSize - GetDebugMargin();
+ pAllocationRequest->customData = (void*)allocType;
+ pAllocationRequest->algorithmData = alignedOffset;
+
+ // Place block at the start of list if it's normal block
+ if (listIndex != m_ListsCount && block.PrevFree())
+ {
+ block.PrevFree()->NextFree() = block.NextFree();
+ if (block.NextFree())
+ block.NextFree()->PrevFree() = block.PrevFree();
+ block.PrevFree() = VMA_NULL;
+ block.NextFree() = m_FreeList[listIndex];
+ m_FreeList[listIndex] = &block;
+ if (block.NextFree())
+ block.NextFree()->PrevFree() = &block;
+ }
+
+ return true;
+}
+#endif // _VMA_BLOCK_METADATA_TLSF_FUNCTIONS
+#endif // _VMA_BLOCK_METADATA_TLSF
+
+#ifndef _VMA_BLOCK_VECTOR
+/*
+Sequence of VmaDeviceMemoryBlock. Represents memory blocks allocated for a specific
+Vulkan memory type.
+
+Synchronized internally with a mutex.
+*/
+class VmaBlockVector
+{
+ friend struct VmaDefragmentationContext_T;
+ VMA_CLASS_NO_COPY(VmaBlockVector)
+public:
+ VmaBlockVector(
+ VmaAllocator hAllocator,
+ VmaPool hParentPool,
+ uint32_t memoryTypeIndex,
+ VkDeviceSize preferredBlockSize,
+ size_t minBlockCount,
+ size_t maxBlockCount,
+ VkDeviceSize bufferImageGranularity,
+ bool explicitBlockSize,
+ uint32_t algorithm,
+ float priority,
+ VkDeviceSize minAllocationAlignment,
+ void* pMemoryAllocateNext);
+ ~VmaBlockVector();
+
+ VmaAllocator GetAllocator() const { return m_hAllocator; }
+ VmaPool GetParentPool() const { return m_hParentPool; }
+ bool IsCustomPool() const { return m_hParentPool != VMA_NULL; }
+ uint32_t GetMemoryTypeIndex() const { return m_MemoryTypeIndex; }
+ VkDeviceSize GetPreferredBlockSize() const { return m_PreferredBlockSize; }
+ VkDeviceSize GetBufferImageGranularity() const { return m_BufferImageGranularity; }
+ uint32_t GetAlgorithm() const { return m_Algorithm; }
+ bool HasExplicitBlockSize() const { return m_ExplicitBlockSize; }
+ float GetPriority() const { return m_Priority; }
+ const void* GetAllocationNextPtr() const { return m_pMemoryAllocateNext; }
+ // To be used only while the m_Mutex is locked. Used during defragmentation.
+ size_t GetBlockCount() const { return m_Blocks.size(); }
+ // To be used only while the m_Mutex is locked. Used during defragmentation.
+ VmaDeviceMemoryBlock* GetBlock(size_t index) const { return m_Blocks[index]; }
+ VMA_RW_MUTEX &GetMutex() { return m_Mutex; }
+
+ VkResult CreateMinBlocks();
+ void AddStatistics(VmaStatistics& inoutStats);
+ void AddDetailedStatistics(VmaDetailedStatistics& inoutStats);
+ bool IsEmpty();
+ bool IsCorruptionDetectionEnabled() const;
+
+ VkResult Allocate(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ void Free(const VmaAllocation hAllocation);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ VkResult CheckCorruption();
+
+private:
+ const VmaAllocator m_hAllocator;
+ const VmaPool m_hParentPool;
+ const uint32_t m_MemoryTypeIndex;
+ const VkDeviceSize m_PreferredBlockSize;
+ const size_t m_MinBlockCount;
+ const size_t m_MaxBlockCount;
+ const VkDeviceSize m_BufferImageGranularity;
+ const bool m_ExplicitBlockSize;
+ const uint32_t m_Algorithm;
+ const float m_Priority;
+ const VkDeviceSize m_MinAllocationAlignment;
+
+ void* const m_pMemoryAllocateNext;
+ VMA_RW_MUTEX m_Mutex;
+ // Incrementally sorted by sumFreeSize, ascending.
+ VmaVector<VmaDeviceMemoryBlock*, VmaStlAllocator<VmaDeviceMemoryBlock*>> m_Blocks;
+ uint32_t m_NextBlockId;
+ bool m_IncrementalSort = true;
+
+ void SetIncrementalSort(bool val) { m_IncrementalSort = val; }
+
+ VkDeviceSize CalcMaxBlockSize() const;
+ // Finds and removes given block from vector.
+ void Remove(VmaDeviceMemoryBlock* pBlock);
+ // Performs single step in sorting m_Blocks. They may not be fully sorted
+ // after this call.
+ void IncrementallySortBlocks();
+ void SortByFreeSize();
+
+ VkResult AllocatePage(
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation);
+
+ VkResult AllocateFromBlock(
+ VmaDeviceMemoryBlock* pBlock,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ uint32_t strategy,
+ VmaAllocation* pAllocation);
+
+ VkResult CommitAllocationRequest(
+ VmaAllocationRequest& allocRequest,
+ VmaDeviceMemoryBlock* pBlock,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation);
+
+ VkResult CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex);
+ bool HasEmptyBlock();
+};
+#endif // _VMA_BLOCK_VECTOR
+
+#ifndef _VMA_DEFRAGMENTATION_CONTEXT
+struct VmaDefragmentationContext_T
+{
+ VMA_CLASS_NO_COPY(VmaDefragmentationContext_T)
+public:
+ VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ const VmaDefragmentationInfo& info);
+ ~VmaDefragmentationContext_T();
+
+ void GetStats(VmaDefragmentationStats& outStats) { outStats = m_GlobalStats; }
+
+ VkResult DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo);
+ VkResult DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo);
+
+private:
+ // Max number of allocations to ignore due to size constraints before ending single pass
+ static const uint8_t MAX_ALLOCS_TO_IGNORE = 16;
+ enum class CounterStatus { Pass, Ignore, End };
+
+ struct FragmentedBlock
+ {
+ uint32_t data;
+ VmaDeviceMemoryBlock* block;
+ };
+ struct StateBalanced
+ {
+ VkDeviceSize avgFreeSize = 0;
+ VkDeviceSize avgAllocSize = UINT64_MAX;
+ };
+ struct StateExtensive
+ {
+ enum class Operation : uint8_t
+ {
+ FindFreeBlockBuffer, FindFreeBlockTexture, FindFreeBlockAll,
+ MoveBuffers, MoveTextures, MoveAll,
+ Cleanup, Done
+ };
+
+ Operation operation = Operation::FindFreeBlockTexture;
+ size_t firstFreeBlock = SIZE_MAX;
+ };
+ struct MoveAllocationData
+ {
+ VkDeviceSize size;
+ VkDeviceSize alignment;
+ VmaSuballocationType type;
+ VmaAllocationCreateFlags flags;
+ VmaDefragmentationMove move = {};
+ };
+
+ const VkDeviceSize m_MaxPassBytes;
+ const uint32_t m_MaxPassAllocations;
+
+ VmaStlAllocator<VmaDefragmentationMove> m_MoveAllocator;
+ VmaVector<VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove>> m_Moves;
+
+ uint8_t m_IgnoredAllocs = 0;
+ uint32_t m_Algorithm;
+ uint32_t m_BlockVectorCount;
+ VmaBlockVector* m_PoolBlockVector;
+ VmaBlockVector** m_pBlockVectors;
+ size_t m_ImmovableBlockCount = 0;
+ VmaDefragmentationStats m_GlobalStats = { 0 };
+ VmaDefragmentationStats m_PassStats = { 0 };
+ void* m_AlgorithmState = VMA_NULL;
+
+ static MoveAllocationData GetMoveData(VmaAllocHandle handle, VmaBlockMetadata* metadata);
+ CounterStatus CheckCounters(VkDeviceSize bytes);
+ bool IncrementCounters(VkDeviceSize bytes);
+ bool ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block);
+ bool AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector);
+
+ bool ComputeDefragmentation(VmaBlockVector& vector, size_t index);
+ bool ComputeDefragmentation_Fast(VmaBlockVector& vector);
+ bool ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update);
+ bool ComputeDefragmentation_Full(VmaBlockVector& vector);
+ bool ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index);
+
+ void UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state);
+ bool MoveDataToFreeBlocks(VmaSuballocationType currentType,
+ VmaBlockVector& vector, size_t firstFreeBlock,
+ bool& texturePresent, bool& bufferPresent, bool& otherPresent);
+};
+#endif // _VMA_DEFRAGMENTATION_CONTEXT
+
+#ifndef _VMA_POOL_T
+struct VmaPool_T
+{
+ friend struct VmaPoolListItemTraits;
+ VMA_CLASS_NO_COPY(VmaPool_T)
+public:
+ VmaBlockVector m_BlockVector;
+ VmaDedicatedAllocationList m_DedicatedAllocations;
+
+ VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize);
+ ~VmaPool_T();
+
+ uint32_t GetId() const { return m_Id; }
+ void SetId(uint32_t id) { VMA_ASSERT(m_Id == 0); m_Id = id; }
+
+ const char* GetName() const { return m_Name; }
+ void SetName(const char* pName);
+
+#if VMA_STATS_STRING_ENABLED
+ //void PrintDetailedMap(class VmaStringBuilder& sb);
+#endif
+
+private:
+ uint32_t m_Id;
+ char* m_Name;
+ VmaPool_T* m_PrevPool = VMA_NULL;
+ VmaPool_T* m_NextPool = VMA_NULL;
+};
+
+struct VmaPoolListItemTraits
+{
+ typedef VmaPool_T ItemType;
+
+ static ItemType* GetPrev(const ItemType* item) { return item->m_PrevPool; }
+ static ItemType* GetNext(const ItemType* item) { return item->m_NextPool; }
+ static ItemType*& AccessPrev(ItemType* item) { return item->m_PrevPool; }
+ static ItemType*& AccessNext(ItemType* item) { return item->m_NextPool; }
+};
+#endif // _VMA_POOL_T
+
+#ifndef _VMA_CURRENT_BUDGET_DATA
+struct VmaCurrentBudgetData
+{
+ VMA_ATOMIC_UINT32 m_BlockCount[VK_MAX_MEMORY_HEAPS];
+ VMA_ATOMIC_UINT32 m_AllocationCount[VK_MAX_MEMORY_HEAPS];
+ VMA_ATOMIC_UINT64 m_BlockBytes[VK_MAX_MEMORY_HEAPS];
+ VMA_ATOMIC_UINT64 m_AllocationBytes[VK_MAX_MEMORY_HEAPS];
+
+#if VMA_MEMORY_BUDGET
+ VMA_ATOMIC_UINT32 m_OperationsSinceBudgetFetch;
+ VMA_RW_MUTEX m_BudgetMutex;
+ uint64_t m_VulkanUsage[VK_MAX_MEMORY_HEAPS];
+ uint64_t m_VulkanBudget[VK_MAX_MEMORY_HEAPS];
+ uint64_t m_BlockBytesAtBudgetFetch[VK_MAX_MEMORY_HEAPS];
+#endif // VMA_MEMORY_BUDGET
+
+ VmaCurrentBudgetData();
+
+ void AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize);
+ void RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize);
+};
+
+#ifndef _VMA_CURRENT_BUDGET_DATA_FUNCTIONS
+VmaCurrentBudgetData::VmaCurrentBudgetData()
+{
+ for (uint32_t heapIndex = 0; heapIndex < VK_MAX_MEMORY_HEAPS; ++heapIndex)
+ {
+ m_BlockCount[heapIndex] = 0;
+ m_AllocationCount[heapIndex] = 0;
+ m_BlockBytes[heapIndex] = 0;
+ m_AllocationBytes[heapIndex] = 0;
+#if VMA_MEMORY_BUDGET
+ m_VulkanUsage[heapIndex] = 0;
+ m_VulkanBudget[heapIndex] = 0;
+ m_BlockBytesAtBudgetFetch[heapIndex] = 0;
+#endif
+ }
+
+#if VMA_MEMORY_BUDGET
+ m_OperationsSinceBudgetFetch = 0;
+#endif
+}
+
+void VmaCurrentBudgetData::AddAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+{
+ m_AllocationBytes[heapIndex] += allocationSize;
+ ++m_AllocationCount[heapIndex];
+#if VMA_MEMORY_BUDGET
+ ++m_OperationsSinceBudgetFetch;
+#endif
+}
+
+void VmaCurrentBudgetData::RemoveAllocation(uint32_t heapIndex, VkDeviceSize allocationSize)
+{
+ VMA_ASSERT(m_AllocationBytes[heapIndex] >= allocationSize);
+ m_AllocationBytes[heapIndex] -= allocationSize;
+ VMA_ASSERT(m_AllocationCount[heapIndex] > 0);
+ --m_AllocationCount[heapIndex];
+#if VMA_MEMORY_BUDGET
+ ++m_OperationsSinceBudgetFetch;
+#endif
+}
+#endif // _VMA_CURRENT_BUDGET_DATA_FUNCTIONS
+#endif // _VMA_CURRENT_BUDGET_DATA
+
+#ifndef _VMA_ALLOCATION_OBJECT_ALLOCATOR
+/*
+Thread-safe wrapper over VmaPoolAllocator free list, for allocation of VmaAllocation_T objects.
+*/
+class VmaAllocationObjectAllocator
+{
+ VMA_CLASS_NO_COPY(VmaAllocationObjectAllocator)
+public:
+ VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks)
+ : m_Allocator(pAllocationCallbacks, 1024) {}
+
+ template<typename... Types> VmaAllocation Allocate(Types&&... args);
+ void Free(VmaAllocation hAlloc);
+
+private:
+ VMA_MUTEX m_Mutex;
+ VmaPoolAllocator<VmaAllocation_T> m_Allocator;
+};
+
+template<typename... Types>
+VmaAllocation VmaAllocationObjectAllocator::Allocate(Types&&... args)
+{
+ VmaMutexLock mutexLock(m_Mutex);
+ return m_Allocator.Alloc<Types...>(std::forward<Types>(args)...);
+}
+
+void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc)
+{
+ VmaMutexLock mutexLock(m_Mutex);
+ m_Allocator.Free(hAlloc);
+}
+#endif // _VMA_ALLOCATION_OBJECT_ALLOCATOR
+
+#ifndef _VMA_VIRTUAL_BLOCK_T
+struct VmaVirtualBlock_T
+{
+ VMA_CLASS_NO_COPY(VmaVirtualBlock_T)
+public:
+ const bool m_AllocationCallbacksSpecified;
+ const VkAllocationCallbacks m_AllocationCallbacks;
+
+ VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo);
+ ~VmaVirtualBlock_T();
+
+ VkResult Init() { return VK_SUCCESS; }
+ bool IsEmpty() const { return m_Metadata->IsEmpty(); }
+ void Free(VmaVirtualAllocation allocation) { m_Metadata->Free((VmaAllocHandle)allocation); }
+ void SetAllocationUserData(VmaVirtualAllocation allocation, void* userData) { m_Metadata->SetAllocationUserData((VmaAllocHandle)allocation, userData); }
+ void Clear() { m_Metadata->Clear(); }
+
+ const VkAllocationCallbacks* GetAllocationCallbacks() const;
+ void GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo);
+ VkResult Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation,
+ VkDeviceSize* outOffset);
+ void GetStatistics(VmaStatistics& outStats) const;
+ void CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const;
+#if VMA_STATS_STRING_ENABLED
+ void BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const;
+#endif
+
+private:
+ VmaBlockMetadata* m_Metadata;
+};
+
+#ifndef _VMA_VIRTUAL_BLOCK_T_FUNCTIONS
+VmaVirtualBlock_T::VmaVirtualBlock_T(const VmaVirtualBlockCreateInfo& createInfo)
+ : m_AllocationCallbacksSpecified(createInfo.pAllocationCallbacks != VMA_NULL),
+ m_AllocationCallbacks(createInfo.pAllocationCallbacks != VMA_NULL ? *createInfo.pAllocationCallbacks : VmaEmptyAllocationCallbacks)
+{
+ const uint32_t algorithm = createInfo.flags & VMA_VIRTUAL_BLOCK_CREATE_ALGORITHM_MASK;
+ switch (algorithm)
+ {
default:
VMA_ASSERT(0);
+ case 0:
+ m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_TLSF)(VK_NULL_HANDLE, 1, true);
+ break;
+ case VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT:
+ m_Metadata = vma_new(GetAllocationCallbacks(), VmaBlockMetadata_Linear)(VK_NULL_HANDLE, 1, true);
+ break;
}
+
+ m_Metadata->Init(createInfo.size);
}
-#endif // #if VMA_STATS_STRING_ENABLED
+VmaVirtualBlock_T::~VmaVirtualBlock_T()
+{
+ // Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations
+ if (!m_Metadata->IsEmpty())
+ m_Metadata->DebugLogAllAllocations();
+ // This is the most important assert in the entire library.
+ // Hitting it means you have some memory leak - unreleased virtual allocations.
+ VMA_ASSERT(m_Metadata->IsEmpty() && "Some virtual allocations were not freed before destruction of this virtual block!");
+
+ vma_delete(GetAllocationCallbacks(), m_Metadata);
+}
-////////////////////////////////////////////////////////////////////////////////
-// class VmaDeviceMemoryBlock
+const VkAllocationCallbacks* VmaVirtualBlock_T::GetAllocationCallbacks() const
+{
+ return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;
+}
+
+void VmaVirtualBlock_T::GetAllocationInfo(VmaVirtualAllocation allocation, VmaVirtualAllocationInfo& outInfo)
+{
+ m_Metadata->GetAllocationInfo((VmaAllocHandle)allocation, outInfo);
+}
+
+VkResult VmaVirtualBlock_T::Allocate(const VmaVirtualAllocationCreateInfo& createInfo, VmaVirtualAllocation& outAllocation,
+ VkDeviceSize* outOffset)
+{
+ VmaAllocationRequest request = {};
+ if (m_Metadata->CreateAllocationRequest(
+ createInfo.size, // allocSize
+ VMA_MAX(createInfo.alignment, (VkDeviceSize)1), // allocAlignment
+ (createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0, // upperAddress
+ VMA_SUBALLOCATION_TYPE_UNKNOWN, // allocType - unimportant
+ createInfo.flags & VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MASK, // strategy
+ &request))
+ {
+ m_Metadata->Alloc(request,
+ VMA_SUBALLOCATION_TYPE_UNKNOWN, // type - unimportant
+ createInfo.pUserData);
+ outAllocation = (VmaVirtualAllocation)request.allocHandle;
+ if(outOffset)
+ *outOffset = m_Metadata->GetAllocationOffset(request.allocHandle);
+ return VK_SUCCESS;
+ }
+ outAllocation = (VmaVirtualAllocation)VK_NULL_HANDLE;
+ if (outOffset)
+ *outOffset = UINT64_MAX;
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
+
+void VmaVirtualBlock_T::GetStatistics(VmaStatistics& outStats) const
+{
+ VmaClearStatistics(outStats);
+ m_Metadata->AddStatistics(outStats);
+}
+
+void VmaVirtualBlock_T::CalculateDetailedStatistics(VmaDetailedStatistics& outStats) const
+{
+ VmaClearDetailedStatistics(outStats);
+ m_Metadata->AddDetailedStatistics(outStats);
+}
+
+#if VMA_STATS_STRING_ENABLED
+void VmaVirtualBlock_T::BuildStatsString(bool detailedMap, VmaStringBuilder& sb) const
+{
+ VmaJsonWriter json(GetAllocationCallbacks(), sb);
+ json.BeginObject();
+
+ VmaDetailedStatistics stats;
+ CalculateDetailedStatistics(stats);
+
+ json.WriteString("Stats");
+ VmaPrintDetailedStatistics(json, stats);
+
+ if (detailedMap)
+ {
+ json.WriteString("Details");
+ json.BeginObject();
+ m_Metadata->PrintDetailedMap(json);
+ json.EndObject();
+ }
+
+ json.EndObject();
+}
+#endif // VMA_STATS_STRING_ENABLED
+#endif // _VMA_VIRTUAL_BLOCK_T_FUNCTIONS
+#endif // _VMA_VIRTUAL_BLOCK_T
+
+
+// Main allocator object.
+struct VmaAllocator_T
+{
+ VMA_CLASS_NO_COPY(VmaAllocator_T)
+public:
+ bool m_UseMutex;
+ uint32_t m_VulkanApiVersion;
+ bool m_UseKhrDedicatedAllocation; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+ bool m_UseKhrBindMemory2; // Can be set only if m_VulkanApiVersion < VK_MAKE_VERSION(1, 1, 0).
+ bool m_UseExtMemoryBudget;
+ bool m_UseAmdDeviceCoherentMemory;
+ bool m_UseKhrBufferDeviceAddress;
+ bool m_UseExtMemoryPriority;
+ VkDevice m_hDevice;
+ VkInstance m_hInstance;
+ bool m_AllocationCallbacksSpecified;
+ VkAllocationCallbacks m_AllocationCallbacks;
+ VmaDeviceMemoryCallbacks m_DeviceMemoryCallbacks;
+ VmaAllocationObjectAllocator m_AllocationObjectAllocator;
+
+ // Each bit (1 << i) is set if HeapSizeLimit is enabled for that heap, so cannot allocate more than the heap size.
+ uint32_t m_HeapSizeLimitMask;
+
+ VkPhysicalDeviceProperties m_PhysicalDeviceProperties;
+ VkPhysicalDeviceMemoryProperties m_MemProps;
+
+ // Default pools.
+ VmaBlockVector* m_pBlockVectors[VK_MAX_MEMORY_TYPES];
+ VmaDedicatedAllocationList m_DedicatedAllocations[VK_MAX_MEMORY_TYPES];
+
+ VmaCurrentBudgetData m_Budget;
+ VMA_ATOMIC_UINT32 m_DeviceMemoryCount; // Total number of VkDeviceMemory objects.
+
+ VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo);
+ VkResult Init(const VmaAllocatorCreateInfo* pCreateInfo);
+ ~VmaAllocator_T();
+
+ const VkAllocationCallbacks* GetAllocationCallbacks() const
+ {
+ return m_AllocationCallbacksSpecified ? &m_AllocationCallbacks : VMA_NULL;
+ }
+ const VmaVulkanFunctions& GetVulkanFunctions() const
+ {
+ return m_VulkanFunctions;
+ }
+
+ VkPhysicalDevice GetPhysicalDevice() const { return m_PhysicalDevice; }
+
+ VkDeviceSize GetBufferImageGranularity() const
+ {
+ return VMA_MAX(
+ static_cast<VkDeviceSize>(VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY),
+ m_PhysicalDeviceProperties.limits.bufferImageGranularity);
+ }
+
+ uint32_t GetMemoryHeapCount() const { return m_MemProps.memoryHeapCount; }
+ uint32_t GetMemoryTypeCount() const { return m_MemProps.memoryTypeCount; }
+ uint32_t MemoryTypeIndexToHeapIndex(uint32_t memTypeIndex) const
+ {
+ VMA_ASSERT(memTypeIndex < m_MemProps.memoryTypeCount);
+ return m_MemProps.memoryTypes[memTypeIndex].heapIndex;
+ }
+ // True when specific memory type is HOST_VISIBLE but not HOST_COHERENT.
+ bool IsMemoryTypeNonCoherent(uint32_t memTypeIndex) const
+ {
+ return (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) ==
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+ }
+ // Minimum alignment for all allocations in specific memory type.
+ VkDeviceSize GetMemoryTypeMinAlignment(uint32_t memTypeIndex) const
+ {
+ return IsMemoryTypeNonCoherent(memTypeIndex) ?
+ VMA_MAX((VkDeviceSize)VMA_MIN_ALIGNMENT, m_PhysicalDeviceProperties.limits.nonCoherentAtomSize) :
+ (VkDeviceSize)VMA_MIN_ALIGNMENT;
+ }
+
+ bool IsIntegratedGpu() const
+ {
+ return m_PhysicalDeviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
+ }
+
+ uint32_t GetGlobalMemoryTypeBits() const { return m_GlobalMemoryTypeBits; }
+
+ void GetBufferMemoryRequirements(
+ VkBuffer hBuffer,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+ void GetImageMemoryRequirements(
+ VkImage hImage,
+ VkMemoryRequirements& memReq,
+ bool& requiresDedicatedAllocation,
+ bool& prefersDedicatedAllocation) const;
+ VkResult FindMemoryTypeIndex(
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkFlags bufImgUsage, // VkBufferCreateInfo::usage or VkImageCreateInfo::usage. UINT32_MAX if unknown.
+ uint32_t* pMemoryTypeIndex) const;
+
+ // Main allocation function.
+ VkResult AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage, // UINT32_MAX if unknown.
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Main deallocation function.
+ void FreeMemory(
+ size_t allocationCount,
+ const VmaAllocation* pAllocations);
+
+ void CalculateStatistics(VmaTotalStatistics* pStats);
+
+ void GetHeapBudgets(
+ VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount);
+
+#if VMA_STATS_STRING_ENABLED
+ void PrintDetailedMap(class VmaJsonWriter& json);
+#endif
+
+ void GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo);
+
+ VkResult CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool);
+ void DestroyPool(VmaPool pool);
+ void GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats);
+ void CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats);
+
+ void SetCurrentFrameIndex(uint32_t frameIndex);
+ uint32_t GetCurrentFrameIndex() const { return m_CurrentFrameIndex.load(); }
+
+ VkResult CheckPoolCorruption(VmaPool hPool);
+ VkResult CheckCorruption(uint32_t memoryTypeBits);
+
+ // Call to Vulkan function vkAllocateMemory with accompanying bookkeeping.
+ VkResult AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory);
+ // Call to Vulkan function vkFreeMemory with accompanying bookkeeping.
+ void FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, VkDeviceMemory hMemory);
+ // Call to Vulkan function vkBindBufferMemory or vkBindBufferMemory2KHR.
+ VkResult BindVulkanBuffer(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkBuffer buffer,
+ const void* pNext);
+ // Call to Vulkan function vkBindImageMemory or vkBindImageMemory2KHR.
+ VkResult BindVulkanImage(
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset,
+ VkImage image,
+ const void* pNext);
+
+ VkResult Map(VmaAllocation hAllocation, void** ppData);
+ void Unmap(VmaAllocation hAllocation);
+
+ VkResult BindBufferMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkBuffer hBuffer,
+ const void* pNext);
+ VkResult BindImageMemory(
+ VmaAllocation hAllocation,
+ VkDeviceSize allocationLocalOffset,
+ VkImage hImage,
+ const void* pNext);
+
+ VkResult FlushOrInvalidateAllocation(
+ VmaAllocation hAllocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VMA_CACHE_OPERATION op);
+ VkResult FlushOrInvalidateAllocations(
+ uint32_t allocationCount,
+ const VmaAllocation* allocations,
+ const VkDeviceSize* offsets, const VkDeviceSize* sizes,
+ VMA_CACHE_OPERATION op);
+
+ void FillAllocation(const VmaAllocation hAllocation, uint8_t pattern);
+
+ /*
+ Returns bit mask of memory types that can support defragmentation on GPU as
+ they support creation of required buffer for copy operations.
+ */
+ uint32_t GetGpuDefragmentationMemoryTypeBits();
+
+#if VMA_EXTERNAL_MEMORY
+ VkExternalMemoryHandleTypeFlagsKHR GetExternalMemoryHandleTypeFlags(uint32_t memTypeIndex) const
+ {
+ return m_TypeExternalMemoryHandleTypes[memTypeIndex];
+ }
+#endif // #if VMA_EXTERNAL_MEMORY
+
+private:
+ VkDeviceSize m_PreferredLargeHeapBlockSize;
+
+ VkPhysicalDevice m_PhysicalDevice;
+ VMA_ATOMIC_UINT32 m_CurrentFrameIndex;
+ VMA_ATOMIC_UINT32 m_GpuDefragmentationMemoryTypeBits; // UINT32_MAX means uninitialized.
+#if VMA_EXTERNAL_MEMORY
+ VkExternalMemoryHandleTypeFlagsKHR m_TypeExternalMemoryHandleTypes[VK_MAX_MEMORY_TYPES];
+#endif // #if VMA_EXTERNAL_MEMORY
+
+ VMA_RW_MUTEX m_PoolsMutex;
+ typedef VmaIntrusiveLinkedList<VmaPoolListItemTraits> PoolList;
+ // Protected by m_PoolsMutex.
+ PoolList m_Pools;
+ uint32_t m_NextPoolId;
+
+ VmaVulkanFunctions m_VulkanFunctions;
+
+ // Global bit mask AND-ed with any memoryTypeBits to disallow certain memory types.
+ uint32_t m_GlobalMemoryTypeBits;
+
+ void ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunctions);
+
+#if VMA_STATIC_VULKAN_FUNCTIONS == 1
+ void ImportVulkanFunctions_Static();
+#endif
+
+ void ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions);
+
+#if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1
+ void ImportVulkanFunctions_Dynamic();
+#endif
+
+ void ValidateVulkanFunctions();
+
+ VkDeviceSize CalcPreferredBlockSize(uint32_t memTypeIndex);
+
+ VkResult AllocateMemoryOfType(
+ VmaPool pool,
+ VkDeviceSize size,
+ VkDeviceSize alignment,
+ bool dedicatedPreferred,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage,
+ const VmaAllocationCreateInfo& createInfo,
+ uint32_t memTypeIndex,
+ VmaSuballocationType suballocType,
+ VmaDedicatedAllocationList& dedicatedAllocations,
+ VmaBlockVector& blockVector,
+ size_t allocationCount,
+ VmaAllocation* pAllocations);
+
+ // Helper function only to be used inside AllocateDedicatedMemory.
+ VkResult AllocateDedicatedMemoryPage(
+ VmaPool pool,
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ uint32_t memTypeIndex,
+ const VkMemoryAllocateInfo& allocInfo,
+ bool map,
+ bool isUserDataString,
+ bool isMappingAllowed,
+ void* pUserData,
+ VmaAllocation* pAllocation);
+
+ // Allocates and registers new VkDeviceMemory specifically for dedicated allocations.
+ VkResult AllocateDedicatedMemory(
+ VmaPool pool,
+ VkDeviceSize size,
+ VmaSuballocationType suballocType,
+ VmaDedicatedAllocationList& dedicatedAllocations,
+ uint32_t memTypeIndex,
+ bool map,
+ bool isUserDataString,
+ bool isMappingAllowed,
+ bool canAliasMemory,
+ void* pUserData,
+ float priority,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage,
+ size_t allocationCount,
+ VmaAllocation* pAllocations,
+ const void* pNextChain = nullptr);
+
+ void FreeDedicatedMemory(const VmaAllocation allocation);
+
+ VkResult CalcMemTypeParams(
+ VmaAllocationCreateInfo& outCreateInfo,
+ uint32_t memTypeIndex,
+ VkDeviceSize size,
+ size_t allocationCount);
+ VkResult CalcAllocationParams(
+ VmaAllocationCreateInfo& outCreateInfo,
+ bool dedicatedRequired,
+ bool dedicatedPreferred);
+
+ /*
+ Calculates and returns bit mask of memory types that can support defragmentation
+ on GPU as they support creation of required buffer for copy operations.
+ */
+ uint32_t CalculateGpuDefragmentationMemoryTypeBits() const;
+ uint32_t CalculateGlobalMemoryTypeBits() const;
+
+ bool GetFlushOrInvalidateRange(
+ VmaAllocation allocation,
+ VkDeviceSize offset, VkDeviceSize size,
+ VkMappedMemoryRange& outRange) const;
+
+#if VMA_MEMORY_BUDGET
+ void UpdateVulkanBudget();
+#endif // #if VMA_MEMORY_BUDGET
+};
+
+
+#ifndef _VMA_MEMORY_FUNCTIONS
+static void* VmaMalloc(VmaAllocator hAllocator, size_t size, size_t alignment)
+{
+ return VmaMalloc(&hAllocator->m_AllocationCallbacks, size, alignment);
+}
+
+static void VmaFree(VmaAllocator hAllocator, void* ptr)
+{
+ VmaFree(&hAllocator->m_AllocationCallbacks, ptr);
+}
+
+template<typename T>
+static T* VmaAllocate(VmaAllocator hAllocator)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T), VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static T* VmaAllocateArray(VmaAllocator hAllocator, size_t count)
+{
+ return (T*)VmaMalloc(hAllocator, sizeof(T) * count, VMA_ALIGN_OF(T));
+}
+
+template<typename T>
+static void vma_delete(VmaAllocator hAllocator, T* ptr)
+{
+ if(ptr != VMA_NULL)
+ {
+ ptr->~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+
+template<typename T>
+static void vma_delete_array(VmaAllocator hAllocator, T* ptr, size_t count)
+{
+ if(ptr != VMA_NULL)
+ {
+ for(size_t i = count; i--; )
+ ptr[i].~T();
+ VmaFree(hAllocator, ptr);
+ }
+}
+#endif // _VMA_MEMORY_FUNCTIONS
+
+#ifndef _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
VmaDeviceMemoryBlock::VmaDeviceMemoryBlock(VmaAllocator hAllocator)
+ : m_pMetadata(VMA_NULL),
+ m_MemoryTypeIndex(UINT32_MAX),
+ m_Id(0),
+ m_hMemory(VK_NULL_HANDLE),
+ m_MapCount(0),
+ m_pMappedData(VMA_NULL) {}
+
+VmaDeviceMemoryBlock::~VmaDeviceMemoryBlock()
{
+ VMA_ASSERT(m_MapCount == 0 && "VkDeviceMemory block is being destroyed while it is still mapped.");
+ VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
}
void VmaDeviceMemoryBlock::Init(
VmaAllocator hAllocator,
- VmaBlockVector* parentBlockVector,
VmaPool hParentPool,
uint32_t newMemoryTypeIndex,
VkDeviceMemory newMemory,
VkDeviceSize newSize,
uint32_t id,
- uint32_t algorithm)
+ uint32_t algorithm,
+ VkDeviceSize bufferImageGranularity)
{
- VMA_ASSERT(parentBlockVector != VMA_NULL);
VMA_ASSERT(m_hMemory == VK_NULL_HANDLE);
- m_ParentBlockVector = parentBlockVector;
m_hParentPool = hParentPool;
m_MemoryTypeIndex = newMemoryTypeIndex;
m_Id = id;
m_hMemory = newMemory;
- switch(algorithm)
+ switch (algorithm)
{
case VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT:
- m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator);
- break;
- case VMA_POOL_CREATE_BUDDY_ALGORITHM_BIT:
- m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Buddy)(hAllocator);
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Linear)(hAllocator->GetAllocationCallbacks(),
+ bufferImageGranularity, false); // isVirtual
break;
default:
VMA_ASSERT(0);
// Fall-through.
case 0:
- m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_Generic)(hAllocator);
+ m_pMetadata = vma_new(hAllocator, VmaBlockMetadata_TLSF)(hAllocator->GetAllocationCallbacks(),
+ bufferImageGranularity, false); // isVirtual
}
m_pMetadata->Init(newSize);
}
void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
{
+ // Define macro VMA_DEBUG_LOG to receive the list of the unfreed allocations
+ if (!m_pMetadata->IsEmpty())
+ m_pMetadata->DebugLogAllAllocations();
// This is the most important assert in the entire library.
// Hitting it means you have some memory leak - unreleased VmaAllocation objects.
VMA_ASSERT(m_pMetadata->IsEmpty() && "Some allocations were not freed before destruction of this memory block!");
@@ -12720,6 +11772,19 @@ void VmaDeviceMemoryBlock::Destroy(VmaAllocator allocator)
m_pMetadata = VMA_NULL;
}
+void VmaDeviceMemoryBlock::PostFree(VmaAllocator hAllocator)
+{
+ if(m_MappingHysteresis.PostFree())
+ {
+ VMA_ASSERT(m_MappingHysteresis.GetExtraMapping() == 0);
+ if (m_MapCount == 0)
+ {
+ m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
+ }
+ }
+}
+
bool VmaDeviceMemoryBlock::Validate() const
{
VMA_VALIDATE((m_hMemory != VK_NULL_HANDLE) &&
@@ -12732,7 +11797,7 @@ VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
{
void* pData = nullptr;
VkResult res = Map(hAllocator, 1, &pData);
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
return res;
}
@@ -12746,17 +11811,19 @@ VkResult VmaDeviceMemoryBlock::CheckCorruption(VmaAllocator hAllocator)
VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void** ppData)
{
- if(count == 0)
+ if (count == 0)
{
return VK_SUCCESS;
}
- VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
- if(m_MapCount != 0)
+ VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
+ const uint32_t oldTotalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping();
+ m_MappingHysteresis.PostMap();
+ if (oldTotalMapCount != 0)
{
m_MapCount += count;
VMA_ASSERT(m_pMappedData != VMA_NULL);
- if(ppData != VMA_NULL)
+ if (ppData != VMA_NULL)
{
*ppData = m_pMappedData;
}
@@ -12771,9 +11838,9 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void
VK_WHOLE_SIZE,
0, // flags
&m_pMappedData);
- if(result == VK_SUCCESS)
+ if (result == VK_SUCCESS)
{
- if(ppData != VMA_NULL)
+ if (ppData != VMA_NULL)
{
*ppData = m_pMappedData;
}
@@ -12785,20 +11852,22 @@ VkResult VmaDeviceMemoryBlock::Map(VmaAllocator hAllocator, uint32_t count, void
void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
{
- if(count == 0)
+ if (count == 0)
{
return;
}
- VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
- if(m_MapCount >= count)
+ VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
+ if (m_MapCount >= count)
{
m_MapCount -= count;
- if(m_MapCount == 0)
+ const uint32_t totalMapCount = m_MapCount + m_MappingHysteresis.GetExtraMapping();
+ if (totalMapCount == 0)
{
m_pMappedData = VMA_NULL;
(*hAllocator->GetVulkanFunctions().vkUnmapMemory)(hAllocator->m_hDevice, m_hMemory);
}
+ m_MappingHysteresis.PostUnmap();
}
else
{
@@ -12806,49 +11875,40 @@ void VmaDeviceMemoryBlock::Unmap(VmaAllocator hAllocator, uint32_t count)
}
}
-VkResult VmaDeviceMemoryBlock::WriteMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+VkResult VmaDeviceMemoryBlock::WriteMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
{
VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
- VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
void* pData;
VkResult res = Map(hAllocator, 1, &pData);
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
return res;
}
- VmaWriteMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN);
VmaWriteMagicValue(pData, allocOffset + allocSize);
Unmap(hAllocator, 1);
-
return VK_SUCCESS;
}
-VkResult VmaDeviceMemoryBlock::ValidateMagicValueAroundAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
+VkResult VmaDeviceMemoryBlock::ValidateMagicValueAfterAllocation(VmaAllocator hAllocator, VkDeviceSize allocOffset, VkDeviceSize allocSize)
{
VMA_ASSERT(VMA_DEBUG_MARGIN > 0 && VMA_DEBUG_MARGIN % 4 == 0 && VMA_DEBUG_DETECT_CORRUPTION);
- VMA_ASSERT(allocOffset >= VMA_DEBUG_MARGIN);
void* pData;
VkResult res = Map(hAllocator, 1, &pData);
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
return res;
}
- if(!VmaValidateMagicValue(pData, allocOffset - VMA_DEBUG_MARGIN))
- {
- VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED BEFORE FREED ALLOCATION!");
- }
- else if(!VmaValidateMagicValue(pData, allocOffset + allocSize))
+ if (!VmaValidateMagicValue(pData, allocOffset + allocSize))
{
VMA_ASSERT(0 && "MEMORY CORRUPTION DETECTED AFTER FREED ALLOCATION!");
}
Unmap(hAllocator, 1);
-
return VK_SUCCESS;
}
@@ -12865,7 +11925,7 @@ VkResult VmaDeviceMemoryBlock::BindBufferMemory(
"Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
// This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
- VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
return hAllocator->BindVulkanBuffer(m_hMemory, memoryOffset, hBuffer, pNext);
}
@@ -12882,86 +11942,332 @@ VkResult VmaDeviceMemoryBlock::BindImageMemory(
"Invalid allocationLocalOffset. Did you forget that this offset is relative to the beginning of the allocation, not the whole memory block?");
const VkDeviceSize memoryOffset = hAllocation->GetOffset() + allocationLocalOffset;
// This lock is important so that we don't call vkBind... and/or vkMap... simultaneously on the same VkDeviceMemory from multiple threads.
- VmaMutexLock lock(m_Mutex, hAllocator->m_UseMutex);
+ VmaMutexLock lock(m_MapAndBindMutex, hAllocator->m_UseMutex);
return hAllocator->BindVulkanImage(m_hMemory, memoryOffset, hImage, pNext);
}
+#endif // _VMA_DEVICE_MEMORY_BLOCK_FUNCTIONS
-static void InitStatInfo(VmaStatInfo& outInfo)
+#ifndef _VMA_ALLOCATION_T_FUNCTIONS
+VmaAllocation_T::VmaAllocation_T(bool mappingAllowed)
+ : m_Alignment{ 1 },
+ m_Size{ 0 },
+ m_pUserData{ VMA_NULL },
+ m_pName{ VMA_NULL },
+ m_MemoryTypeIndex{ 0 },
+ m_Type{ (uint8_t)ALLOCATION_TYPE_NONE },
+ m_SuballocationType{ (uint8_t)VMA_SUBALLOCATION_TYPE_UNKNOWN },
+ m_MapCount{ 0 },
+ m_Flags{ 0 }
{
- memset(&outInfo, 0, sizeof(outInfo));
- outInfo.allocationSizeMin = UINT64_MAX;
- outInfo.unusedRangeSizeMin = UINT64_MAX;
+ if(mappingAllowed)
+ m_Flags |= (uint8_t)FLAG_MAPPING_ALLOWED;
+
+#if VMA_STATS_STRING_ENABLED
+ m_BufferImageUsage = 0;
+#endif
}
-// Adds statistics srcInfo into inoutInfo, like: inoutInfo += srcInfo.
-static void VmaAddStatInfo(VmaStatInfo& inoutInfo, const VmaStatInfo& srcInfo)
+VmaAllocation_T::~VmaAllocation_T()
{
- inoutInfo.blockCount += srcInfo.blockCount;
- inoutInfo.allocationCount += srcInfo.allocationCount;
- inoutInfo.unusedRangeCount += srcInfo.unusedRangeCount;
- inoutInfo.usedBytes += srcInfo.usedBytes;
- inoutInfo.unusedBytes += srcInfo.unusedBytes;
- inoutInfo.allocationSizeMin = VMA_MIN(inoutInfo.allocationSizeMin, srcInfo.allocationSizeMin);
- inoutInfo.allocationSizeMax = VMA_MAX(inoutInfo.allocationSizeMax, srcInfo.allocationSizeMax);
- inoutInfo.unusedRangeSizeMin = VMA_MIN(inoutInfo.unusedRangeSizeMin, srcInfo.unusedRangeSizeMin);
- inoutInfo.unusedRangeSizeMax = VMA_MAX(inoutInfo.unusedRangeSizeMax, srcInfo.unusedRangeSizeMax);
+ VMA_ASSERT(m_MapCount == 0 && "Allocation was not unmapped before destruction.");
+
+ // Check if owned string was freed.
+ VMA_ASSERT(m_pName == VMA_NULL);
}
-static void VmaPostprocessCalcStatInfo(VmaStatInfo& inoutInfo)
+void VmaAllocation_T::InitBlockAllocation(
+ VmaDeviceMemoryBlock* block,
+ VmaAllocHandle allocHandle,
+ VkDeviceSize alignment,
+ VkDeviceSize size,
+ uint32_t memoryTypeIndex,
+ VmaSuballocationType suballocationType,
+ bool mapped)
{
- inoutInfo.allocationSizeAvg = (inoutInfo.allocationCount > 0) ?
- VmaRoundDiv<VkDeviceSize>(inoutInfo.usedBytes, inoutInfo.allocationCount) : 0;
- inoutInfo.unusedRangeSizeAvg = (inoutInfo.unusedRangeCount > 0) ?
- VmaRoundDiv<VkDeviceSize>(inoutInfo.unusedBytes, inoutInfo.unusedRangeCount) : 0;
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(block != VMA_NULL);
+ m_Type = (uint8_t)ALLOCATION_TYPE_BLOCK;
+ m_Alignment = alignment;
+ m_Size = size;
+ m_MemoryTypeIndex = memoryTypeIndex;
+ if(mapped)
+ {
+ VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
+ m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
+ }
+ m_SuballocationType = (uint8_t)suballocationType;
+ m_BlockAllocation.m_Block = block;
+ m_BlockAllocation.m_AllocHandle = allocHandle;
}
-VmaPool_T::VmaPool_T(
- VmaAllocator hAllocator,
- const VmaPoolCreateInfo& createInfo,
- VkDeviceSize preferredBlockSize) :
- m_BlockVector(
- hAllocator,
- this, // hParentPool
- createInfo.memoryTypeIndex,
- createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
- createInfo.minBlockCount,
- createInfo.maxBlockCount,
- (createInfo.flags & VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
- createInfo.frameInUseCount,
- createInfo.blockSize != 0, // explicitBlockSize
- createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
- createInfo.priority,
- VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment),
- createInfo.pMemoryAllocateNext),
- m_Id(0),
- m_Name(VMA_NULL)
+void VmaAllocation_T::InitDedicatedAllocation(
+ VmaPool hParentPool,
+ uint32_t memoryTypeIndex,
+ VkDeviceMemory hMemory,
+ VmaSuballocationType suballocationType,
+ void* pMappedData,
+ VkDeviceSize size)
{
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_NONE);
+ VMA_ASSERT(hMemory != VK_NULL_HANDLE);
+ m_Type = (uint8_t)ALLOCATION_TYPE_DEDICATED;
+ m_Alignment = 0;
+ m_Size = size;
+ m_MemoryTypeIndex = memoryTypeIndex;
+ m_SuballocationType = (uint8_t)suballocationType;
+ if(pMappedData != VMA_NULL)
+ {
+ VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
+ m_Flags |= (uint8_t)FLAG_PERSISTENT_MAP;
+ }
+ m_DedicatedAllocation.m_hParentPool = hParentPool;
+ m_DedicatedAllocation.m_hMemory = hMemory;
+ m_DedicatedAllocation.m_pMappedData = pMappedData;
+ m_DedicatedAllocation.m_Prev = VMA_NULL;
+ m_DedicatedAllocation.m_Next = VMA_NULL;
}
-VmaPool_T::~VmaPool_T()
+void VmaAllocation_T::SetName(VmaAllocator hAllocator, const char* pName)
{
- VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);
+ VMA_ASSERT(pName == VMA_NULL || pName != m_pName);
+
+ FreeName(hAllocator);
+
+ if (pName != VMA_NULL)
+ m_pName = VmaCreateStringCopy(hAllocator->GetAllocationCallbacks(), pName);
}
-void VmaPool_T::SetName(const char* pName)
+uint8_t VmaAllocation_T::SwapBlockAllocation(VmaAllocator hAllocator, VmaAllocation allocation)
{
- const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
- VmaFreeString(allocs, m_Name);
+ VMA_ASSERT(allocation != VMA_NULL);
+ VMA_ASSERT(m_Type == ALLOCATION_TYPE_BLOCK);
+ VMA_ASSERT(allocation->m_Type == ALLOCATION_TYPE_BLOCK);
+
+ if (m_MapCount != 0)
+ m_BlockAllocation.m_Block->Unmap(hAllocator, m_MapCount);
+
+ m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, allocation);
+ VMA_SWAP(m_BlockAllocation, allocation->m_BlockAllocation);
+ m_BlockAllocation.m_Block->m_pMetadata->SetAllocationUserData(m_BlockAllocation.m_AllocHandle, this);
- if(pName != VMA_NULL)
+#if VMA_STATS_STRING_ENABLED
+ VMA_SWAP(m_BufferImageUsage, allocation->m_BufferImageUsage);
+#endif
+ return m_MapCount;
+}
+
+VmaAllocHandle VmaAllocation_T::GetAllocHandle() const
+{
+ switch (m_Type)
{
- m_Name = VmaCreateStringCopy(allocs, pName);
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_AllocHandle;
+ case ALLOCATION_TYPE_DEDICATED:
+ return VK_NULL_HANDLE;
+ default:
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+ }
+}
+
+VkDeviceSize VmaAllocation_T::GetOffset() const
+{
+ switch (m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->m_pMetadata->GetAllocationOffset(m_BlockAllocation.m_AllocHandle);
+ case ALLOCATION_TYPE_DEDICATED:
+ return 0;
+ default:
+ VMA_ASSERT(0);
+ return 0;
+ }
+}
+
+VmaPool VmaAllocation_T::GetParentPool() const
+{
+ switch (m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->GetParentPool();
+ case ALLOCATION_TYPE_DEDICATED:
+ return m_DedicatedAllocation.m_hParentPool;
+ default:
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+ }
+}
+
+VkDeviceMemory VmaAllocation_T::GetMemory() const
+{
+ switch (m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ return m_BlockAllocation.m_Block->GetDeviceMemory();
+ case ALLOCATION_TYPE_DEDICATED:
+ return m_DedicatedAllocation.m_hMemory;
+ default:
+ VMA_ASSERT(0);
+ return VK_NULL_HANDLE;
+ }
+}
+
+void* VmaAllocation_T::GetMappedData() const
+{
+ switch (m_Type)
+ {
+ case ALLOCATION_TYPE_BLOCK:
+ if (m_MapCount != 0 || IsPersistentMap())
+ {
+ void* pBlockData = m_BlockAllocation.m_Block->GetMappedData();
+ VMA_ASSERT(pBlockData != VMA_NULL);
+ return (char*)pBlockData + GetOffset();
+ }
+ else
+ {
+ return VMA_NULL;
+ }
+ break;
+ case ALLOCATION_TYPE_DEDICATED:
+ VMA_ASSERT((m_DedicatedAllocation.m_pMappedData != VMA_NULL) == (m_MapCount != 0 || IsPersistentMap()));
+ return m_DedicatedAllocation.m_pMappedData;
+ default:
+ VMA_ASSERT(0);
+ return VMA_NULL;
+ }
+}
+
+void VmaAllocation_T::BlockAllocMap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+ VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
+
+ if (m_MapCount < 0xFF)
+ {
+ ++m_MapCount;
}
else
{
- m_Name = VMA_NULL;
+ VMA_ASSERT(0 && "Allocation mapped too many times simultaneously.");
+ }
+}
+
+void VmaAllocation_T::BlockAllocUnmap()
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_BLOCK);
+
+ if (m_MapCount > 0)
+ {
+ --m_MapCount;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping allocation not previously mapped.");
+ }
+}
+
+VkResult VmaAllocation_T::DedicatedAllocMap(VmaAllocator hAllocator, void** ppData)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+ VMA_ASSERT(IsMappingAllowed() && "Mapping is not allowed on this allocation! Please use one of the new VMA_ALLOCATION_CREATE_HOST_ACCESS_* flags when creating it.");
+
+ if (m_MapCount != 0 || IsPersistentMap())
+ {
+ if (m_MapCount < 0xFF)
+ {
+ VMA_ASSERT(m_DedicatedAllocation.m_pMappedData != VMA_NULL);
+ *ppData = m_DedicatedAllocation.m_pMappedData;
+ ++m_MapCount;
+ return VK_SUCCESS;
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Dedicated allocation mapped too many times simultaneously.");
+ return VK_ERROR_MEMORY_MAP_FAILED;
+ }
+ }
+ else
+ {
+ VkResult result = (*hAllocator->GetVulkanFunctions().vkMapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory,
+ 0, // offset
+ VK_WHOLE_SIZE,
+ 0, // flags
+ ppData);
+ if (result == VK_SUCCESS)
+ {
+ m_DedicatedAllocation.m_pMappedData = *ppData;
+ m_MapCount = 1;
+ }
+ return result;
+ }
+}
+
+void VmaAllocation_T::DedicatedAllocUnmap(VmaAllocator hAllocator)
+{
+ VMA_ASSERT(GetType() == ALLOCATION_TYPE_DEDICATED);
+
+ if (m_MapCount > 0)
+ {
+ --m_MapCount;
+ if (m_MapCount == 0 && !IsPersistentMap())
+ {
+ m_DedicatedAllocation.m_pMappedData = VMA_NULL;
+ (*hAllocator->GetVulkanFunctions().vkUnmapMemory)(
+ hAllocator->m_hDevice,
+ m_DedicatedAllocation.m_hMemory);
+ }
+ }
+ else
+ {
+ VMA_ASSERT(0 && "Unmapping dedicated allocation not previously mapped.");
}
}
#if VMA_STATS_STRING_ENABLED
+void VmaAllocation_T::InitBufferImageUsage(uint32_t bufferImageUsage)
+{
+ VMA_ASSERT(m_BufferImageUsage == 0);
+ m_BufferImageUsage = bufferImageUsage;
+}
+
+void VmaAllocation_T::PrintParameters(class VmaJsonWriter& json) const
+{
+ json.WriteString("Type");
+ json.WriteString(VMA_SUBALLOCATION_TYPE_NAMES[m_SuballocationType]);
-#endif // #if VMA_STATS_STRING_ENABLED
+ json.WriteString("Size");
+ json.WriteNumber(m_Size);
+ json.WriteString("Usage");
+ json.WriteNumber(m_BufferImageUsage);
+
+ if (m_pUserData != VMA_NULL)
+ {
+ json.WriteString("CustomData");
+ json.BeginString();
+ json.ContinueString_Pointer(m_pUserData);
+ json.EndString();
+ }
+ if (m_pName != VMA_NULL)
+ {
+ json.WriteString("Name");
+ json.WriteString(m_pName);
+ }
+}
+#endif // VMA_STATS_STRING_ENABLED
+void VmaAllocation_T::FreeName(VmaAllocator hAllocator)
+{
+ if(m_pName)
+ {
+ VmaFreeString(hAllocator->GetAllocationCallbacks(), m_pName);
+ m_pName = VMA_NULL;
+ }
+}
+#endif // _VMA_ALLOCATION_T_FUNCTIONS
+
+#ifndef _VMA_BLOCK_VECTOR_FUNCTIONS
VmaBlockVector::VmaBlockVector(
VmaAllocator hAllocator,
VmaPool hParentPool,
@@ -12970,34 +12276,29 @@ VmaBlockVector::VmaBlockVector(
size_t minBlockCount,
size_t maxBlockCount,
VkDeviceSize bufferImageGranularity,
- uint32_t frameInUseCount,
bool explicitBlockSize,
uint32_t algorithm,
float priority,
VkDeviceSize minAllocationAlignment,
- void* pMemoryAllocateNext) :
- m_hAllocator(hAllocator),
+ void* pMemoryAllocateNext)
+ : m_hAllocator(hAllocator),
m_hParentPool(hParentPool),
m_MemoryTypeIndex(memoryTypeIndex),
m_PreferredBlockSize(preferredBlockSize),
m_MinBlockCount(minBlockCount),
m_MaxBlockCount(maxBlockCount),
m_BufferImageGranularity(bufferImageGranularity),
- m_FrameInUseCount(frameInUseCount),
m_ExplicitBlockSize(explicitBlockSize),
m_Algorithm(algorithm),
m_Priority(priority),
m_MinAllocationAlignment(minAllocationAlignment),
m_pMemoryAllocateNext(pMemoryAllocateNext),
- m_HasEmptyBlock(false),
m_Blocks(VmaStlAllocator<VmaDeviceMemoryBlock*>(hAllocator->GetAllocationCallbacks())),
- m_NextBlockId(0)
-{
-}
+ m_NextBlockId(0) {}
VmaBlockVector::~VmaBlockVector()
{
- for(size_t i = m_Blocks.size(); i--; )
+ for (size_t i = m_Blocks.size(); i--; )
{
m_Blocks[i]->Destroy(m_hAllocator);
vma_delete(m_hAllocator, m_Blocks[i]);
@@ -13006,10 +12307,10 @@ VmaBlockVector::~VmaBlockVector()
VkResult VmaBlockVector::CreateMinBlocks()
{
- for(size_t i = 0; i < m_MinBlockCount; ++i)
+ for (size_t i = 0; i < m_MinBlockCount; ++i)
{
VkResult res = CreateBlock(m_PreferredBlockSize, VMA_NULL);
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
return res;
}
@@ -13017,25 +12318,31 @@ VkResult VmaBlockVector::CreateMinBlocks()
return VK_SUCCESS;
}
-void VmaBlockVector::GetPoolStats(VmaPoolStats* pStats)
+void VmaBlockVector::AddStatistics(VmaStatistics& inoutStats)
{
VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
const size_t blockCount = m_Blocks.size();
+ for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ pBlock->m_pMetadata->AddStatistics(inoutStats);
+ }
+}
- pStats->size = 0;
- pStats->unusedSize = 0;
- pStats->allocationCount = 0;
- pStats->unusedRangeCount = 0;
- pStats->unusedRangeSizeMax = 0;
- pStats->blockCount = blockCount;
+void VmaBlockVector::AddDetailedStatistics(VmaDetailedStatistics& inoutStats)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
- for(uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ const size_t blockCount = m_Blocks.size();
+ for (uint32_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
{
const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
VMA_ASSERT(pBlock);
VMA_HEAVY_ASSERT(pBlock->Validate());
- pBlock->m_pMetadata->AddPoolStats(*pStats);
+ pBlock->m_pMetadata->AddDetailedStatistics(inoutStats);
}
}
@@ -13054,10 +12361,7 @@ bool VmaBlockVector::IsCorruptionDetectionEnabled() const
(m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & requiredMemFlags) == requiredMemFlags;
}
-static const uint32_t VMA_ALLOCATION_TRY_COUNT = 32;
-
VkResult VmaBlockVector::Allocate(
- uint32_t currentFrameIndex,
VkDeviceSize size,
VkDeviceSize alignment,
const VmaAllocationCreateInfo& createInfo,
@@ -13070,7 +12374,7 @@ VkResult VmaBlockVector::Allocate(
alignment = VMA_MAX(alignment, m_MinAllocationAlignment);
- if(IsCorruptionDetectionEnabled())
+ if (IsCorruptionDetectionEnabled())
{
size = VmaAlignUp<VkDeviceSize>(size, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
alignment = VmaAlignUp<VkDeviceSize>(alignment, sizeof(VMA_CORRUPTION_DETECTION_MAGIC_VALUE));
@@ -13078,33 +12382,26 @@ VkResult VmaBlockVector::Allocate(
{
VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
- for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
+ for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
{
res = AllocatePage(
- currentFrameIndex,
size,
alignment,
createInfo,
suballocType,
pAllocations + allocIndex);
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
break;
}
}
}
- if(res != VK_SUCCESS)
+ if (res != VK_SUCCESS)
{
// Free all already created allocations.
- const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
- while(allocIndex--)
- {
- VmaAllocation_T* const alloc = pAllocations[allocIndex];
- const VkDeviceSize allocSize = alloc->GetSize();
- Free(alloc);
- m_hAllocator->m_Budget.RemoveAllocation(heapIndex, allocSize);
- }
+ while (allocIndex--)
+ Free(pAllocations[allocIndex]);
memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
}
@@ -13112,7 +12409,6 @@ VkResult VmaBlockVector::Allocate(
}
VkResult VmaBlockVector::AllocatePage(
- uint32_t currentFrameIndex,
VkDeviceSize size,
VkDeviceSize alignment,
const VmaAllocationCreateInfo& createInfo,
@@ -13120,387 +12416,211 @@ VkResult VmaBlockVector::AllocatePage(
VmaAllocation* pAllocation)
{
const bool isUpperAddress = (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
- bool canMakeOtherLost = (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) != 0;
- const bool mapped = (createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
- const bool isUserDataString = (createInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
VkDeviceSize freeMemory;
{
const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
VmaBudget heapBudget = {};
- m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+ m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1);
freeMemory = (heapBudget.usage < heapBudget.budget) ? (heapBudget.budget - heapBudget.usage) : 0;
}
- const bool canFallbackToDedicated = !IsCustomPool();
+ const bool canFallbackToDedicated = !HasExplicitBlockSize() &&
+ (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0;
const bool canCreateNewBlock =
((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0) &&
(m_Blocks.size() < m_MaxBlockCount) &&
(freeMemory >= size || !canFallbackToDedicated);
uint32_t strategy = createInfo.flags & VMA_ALLOCATION_CREATE_STRATEGY_MASK;
- // If linearAlgorithm is used, canMakeOtherLost is available only when used as ring buffer.
- // Which in turn is available only when maxBlockCount = 1.
- if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT && m_MaxBlockCount > 1)
- {
- canMakeOtherLost = false;
- }
-
// Upper address can only be used with linear allocator and within single memory block.
- if(isUpperAddress &&
+ if (isUpperAddress &&
(m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT || m_MaxBlockCount > 1))
{
return VK_ERROR_FEATURE_NOT_PRESENT;
}
- // Validate strategy.
- switch(strategy)
- {
- case 0:
- strategy = VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT;
- break;
- case VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT:
- case VMA_ALLOCATION_CREATE_STRATEGY_WORST_FIT_BIT:
- case VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT:
- break;
- default:
- return VK_ERROR_FEATURE_NOT_PRESENT;
- }
-
// Early reject: requested allocation size is larger that maximum block size for this block vector.
- if(size + 2 * VMA_DEBUG_MARGIN > m_PreferredBlockSize)
+ if (size + VMA_DEBUG_MARGIN > m_PreferredBlockSize)
{
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
- /*
- Under certain condition, this whole section can be skipped for optimization, so
- we move on directly to trying to allocate with canMakeOtherLost. That's the case
- e.g. for custom pools with linear algorithm.
- */
- if(!canMakeOtherLost || canCreateNewBlock)
+ // 1. Search existing allocations. Try to allocate.
+ if (m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
{
- // 1. Search existing allocations. Try to allocate without making other allocations lost.
- VmaAllocationCreateFlags allocFlagsCopy = createInfo.flags;
- allocFlagsCopy &= ~VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT;
-
- if(m_Algorithm == VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ // Use only last block.
+ if (!m_Blocks.empty())
{
- // Use only last block.
- if(!m_Blocks.empty())
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(
+ pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);
+ if (res == VK_SUCCESS)
{
- VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks.back();
- VMA_ASSERT(pCurrBlock);
- VkResult res = AllocateFromBlock(
- pCurrBlock,
- currentFrameIndex,
- size,
- alignment,
- allocFlagsCopy,
- createInfo.pUserData,
- suballocType,
- strategy,
- pAllocation);
- if(res == VK_SUCCESS)
- {
- VMA_DEBUG_LOG(" Returned from last block #%u", pCurrBlock->GetId());
- return VK_SUCCESS;
- }
+ VMA_DEBUG_LOG(" Returned from last block #%u", pCurrBlock->GetId());
+ IncrementallySortBlocks();
+ return VK_SUCCESS;
}
}
- else
+ }
+ else
+ {
+ if (strategy != VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT) // MIN_MEMORY or default
{
- if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ const bool isHostVisible =
+ (m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+ if(isHostVisible)
{
- // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
- for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ const bool isMappingAllowed = (createInfo.flags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0;
+ /*
+ For non-mappable allocations, check blocks that are not mapped first.
+ For mappable allocations, check blocks that are already mapped first.
+ This way, having many blocks, we will separate mappable and non-mappable allocations,
+ hopefully limiting the number of blocks that are mapped, which will help tools like RenderDoc.
+ */
+ for(size_t mappingI = 0; mappingI < 2; ++mappingI)
{
- VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pCurrBlock);
- VkResult res = AllocateFromBlock(
- pCurrBlock,
- currentFrameIndex,
- size,
- alignment,
- allocFlagsCopy,
- createInfo.pUserData,
- suballocType,
- strategy,
- pAllocation);
- if(res == VK_SUCCESS)
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
{
- VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
- return VK_SUCCESS;
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ const bool isBlockMapped = pCurrBlock->GetMappedData() != VMA_NULL;
+ if((mappingI == 0) == (isMappingAllowed == isBlockMapped))
+ {
+ VkResult res = AllocateFromBlock(
+ pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);
+ if (res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
+ IncrementallySortBlocks();
+ return VK_SUCCESS;
+ }
+ }
}
}
}
- else // WORST_FIT, FIRST_FIT
+ else
{
- // Backward order in m_Blocks - prefer blocks with largest amount of free space.
- for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
+ for (size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
{
VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
VMA_ASSERT(pCurrBlock);
VkResult res = AllocateFromBlock(
- pCurrBlock,
- currentFrameIndex,
- size,
- alignment,
- allocFlagsCopy,
- createInfo.pUserData,
- suballocType,
- strategy,
- pAllocation);
- if(res == VK_SUCCESS)
+ pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);
+ if (res == VK_SUCCESS)
{
VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
+ IncrementallySortBlocks();
return VK_SUCCESS;
}
}
}
}
-
- // 2. Try to create new block.
- if(canCreateNewBlock)
+ else // VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT
{
- // Calculate optimal size for new block.
- VkDeviceSize newBlockSize = m_PreferredBlockSize;
- uint32_t newBlockSizeShift = 0;
- const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
-
- if(!m_ExplicitBlockSize)
+ // Backward order in m_Blocks - prefer blocks with largest amount of free space.
+ for (size_t blockIndex = m_Blocks.size(); blockIndex--; )
{
- // Allocate 1/8, 1/4, 1/2 as first blocks.
- const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
- for(uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
+ VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pCurrBlock);
+ VkResult res = AllocateFromBlock(pCurrBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);
+ if (res == VK_SUCCESS)
{
- const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
- if(smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
- {
- newBlockSize = smallerNewBlockSize;
- ++newBlockSizeShift;
- }
- else
- {
- break;
- }
+ VMA_DEBUG_LOG(" Returned from existing block #%u", pCurrBlock->GetId());
+ IncrementallySortBlocks();
+ return VK_SUCCESS;
}
}
+ }
+ }
- size_t newBlockIndex = 0;
- VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
- CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
- // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
- if(!m_ExplicitBlockSize)
- {
- while(res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
- {
- const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
- if(smallerNewBlockSize >= size)
- {
- newBlockSize = smallerNewBlockSize;
- ++newBlockSizeShift;
- res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
- CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
- else
- {
- break;
- }
- }
- }
+ // 2. Try to create new block.
+ if (canCreateNewBlock)
+ {
+ // Calculate optimal size for new block.
+ VkDeviceSize newBlockSize = m_PreferredBlockSize;
+ uint32_t newBlockSizeShift = 0;
+ const uint32_t NEW_BLOCK_SIZE_SHIFT_MAX = 3;
- if(res == VK_SUCCESS)
+ if (!m_ExplicitBlockSize)
+ {
+ // Allocate 1/8, 1/4, 1/2 as first blocks.
+ const VkDeviceSize maxExistingBlockSize = CalcMaxBlockSize();
+ for (uint32_t i = 0; i < NEW_BLOCK_SIZE_SHIFT_MAX; ++i)
{
- VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
- VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
-
- res = AllocateFromBlock(
- pBlock,
- currentFrameIndex,
- size,
- alignment,
- allocFlagsCopy,
- createInfo.pUserData,
- suballocType,
- strategy,
- pAllocation);
- if(res == VK_SUCCESS)
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if (smallerNewBlockSize > maxExistingBlockSize && smallerNewBlockSize >= size * 2)
{
- VMA_DEBUG_LOG(" Created new block #%u Size=%llu", pBlock->GetId(), newBlockSize);
- return VK_SUCCESS;
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
}
else
{
- // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ break;
}
}
}
- }
- // 3. Try to allocate from existing blocks with making other allocations lost.
- if(canMakeOtherLost)
- {
- uint32_t tryIndex = 0;
- for(; tryIndex < VMA_ALLOCATION_TRY_COUNT; ++tryIndex)
+ size_t newBlockIndex = 0;
+ VkResult res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+ CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ // Allocation of this size failed? Try 1/2, 1/4, 1/8 of m_PreferredBlockSize.
+ if (!m_ExplicitBlockSize)
{
- VmaDeviceMemoryBlock* pBestRequestBlock = VMA_NULL;
- VmaAllocationRequest bestRequest = {};
- VkDeviceSize bestRequestCost = VK_WHOLE_SIZE;
-
- // 1. Search existing allocations.
- if(strategy == VMA_ALLOCATION_CREATE_STRATEGY_BEST_FIT_BIT)
+ while (res < 0 && newBlockSizeShift < NEW_BLOCK_SIZE_SHIFT_MAX)
{
- // Forward order in m_Blocks - prefer blocks with smallest amount of free space.
- for(size_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex )
+ const VkDeviceSize smallerNewBlockSize = newBlockSize / 2;
+ if (smallerNewBlockSize >= size)
{
- VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pCurrBlock);
- VmaAllocationRequest currRequest = {};
- if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
- currentFrameIndex,
- m_FrameInUseCount,
- m_BufferImageGranularity,
- size,
- alignment,
- (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
- suballocType,
- canMakeOtherLost,
- strategy,
- &currRequest))
- {
- const VkDeviceSize currRequestCost = currRequest.CalcCost();
- if(pBestRequestBlock == VMA_NULL ||
- currRequestCost < bestRequestCost)
- {
- pBestRequestBlock = pCurrBlock;
- bestRequest = currRequest;
- bestRequestCost = currRequestCost;
-
- if(bestRequestCost == 0)
- {
- break;
- }
- }
- }
+ newBlockSize = smallerNewBlockSize;
+ ++newBlockSizeShift;
+ res = (newBlockSize <= freeMemory || !canFallbackToDedicated) ?
+ CreateBlock(newBlockSize, &newBlockIndex) : VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
- }
- else // WORST_FIT, FIRST_FIT
- {
- // Backward order in m_Blocks - prefer blocks with largest amount of free space.
- for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ else
{
- VmaDeviceMemoryBlock* const pCurrBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pCurrBlock);
- VmaAllocationRequest currRequest = {};
- if(pCurrBlock->m_pMetadata->CreateAllocationRequest(
- currentFrameIndex,
- m_FrameInUseCount,
- m_BufferImageGranularity,
- size,
- alignment,
- (createInfo.flags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0,
- suballocType,
- canMakeOtherLost,
- strategy,
- &currRequest))
- {
- const VkDeviceSize currRequestCost = currRequest.CalcCost();
- if(pBestRequestBlock == VMA_NULL ||
- currRequestCost < bestRequestCost ||
- strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
- {
- pBestRequestBlock = pCurrBlock;
- bestRequest = currRequest;
- bestRequestCost = currRequestCost;
-
- if(bestRequestCost == 0 ||
- strategy == VMA_ALLOCATION_CREATE_STRATEGY_FIRST_FIT_BIT)
- {
- break;
- }
- }
- }
+ break;
}
}
+ }
- if(pBestRequestBlock != VMA_NULL)
- {
- if(mapped)
- {
- VkResult res = pBestRequestBlock->Map(m_hAllocator, 1, VMA_NULL);
- if(res != VK_SUCCESS)
- {
- return res;
- }
- }
+ if (res == VK_SUCCESS)
+ {
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[newBlockIndex];
+ VMA_ASSERT(pBlock->m_pMetadata->GetSize() >= size);
- if(pBestRequestBlock->m_pMetadata->MakeRequestedAllocationsLost(
- currentFrameIndex,
- m_FrameInUseCount,
- &bestRequest))
- {
- // Allocate from this pBlock.
- *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);
- pBestRequestBlock->m_pMetadata->Alloc(bestRequest, suballocType, size, *pAllocation);
- UpdateHasEmptyBlock();
- (*pAllocation)->InitBlockAllocation(
- pBestRequestBlock,
- bestRequest.offset,
- alignment,
- size,
- m_MemoryTypeIndex,
- suballocType,
- mapped,
- (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
- VMA_HEAVY_ASSERT(pBestRequestBlock->Validate());
- VMA_DEBUG_LOG(" Returned from existing block");
- (*pAllocation)->SetUserData(m_hAllocator, createInfo.pUserData);
- m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
- if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
- {
- m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
- }
- if(IsCorruptionDetectionEnabled())
- {
- VkResult res = pBestRequestBlock->WriteMagicValueAroundAllocation(m_hAllocator, bestRequest.offset, size);
- VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
- }
- return VK_SUCCESS;
- }
- // else: Some allocations must have been touched while we are here. Next try.
+ res = AllocateFromBlock(
+ pBlock, size, alignment, createInfo.flags, createInfo.pUserData, suballocType, strategy, pAllocation);
+ if (res == VK_SUCCESS)
+ {
+ VMA_DEBUG_LOG(" Created new block #%u Size=%llu", pBlock->GetId(), newBlockSize);
+ IncrementallySortBlocks();
+ return VK_SUCCESS;
}
else
{
- // Could not find place in any of the blocks - break outer loop.
- break;
+ // Allocation from new block failed, possibly due to VMA_DEBUG_MARGIN or alignment.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
}
- /* Maximum number of tries exceeded - a very unlike event when many other
- threads are simultaneously touching allocations making it impossible to make
- lost at the same time as we try to allocate. */
- if(tryIndex == VMA_ALLOCATION_TRY_COUNT)
- {
- return VK_ERROR_TOO_MANY_OBJECTS;
- }
}
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
-void VmaBlockVector::Free(
- const VmaAllocation hAllocation)
+void VmaBlockVector::Free(const VmaAllocation hAllocation)
{
- VMA_ASSERT(hAllocation->GetBlock()->GetParentBlockVector() == this);
-
VmaDeviceMemoryBlock* pBlockToDelete = VMA_NULL;
bool budgetExceeded = false;
{
const uint32_t heapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex);
VmaBudget heapBudget = {};
- m_hAllocator->GetBudget(&heapBudget, heapIndex, 1);
+ m_hAllocator->GetHeapBudgets(&heapBudget, heapIndex, 1);
budgetExceeded = heapBudget.usage >= heapBudget.budget;
}
@@ -13510,67 +12630,71 @@ void VmaBlockVector::Free(
VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
- if(IsCorruptionDetectionEnabled())
+ if (IsCorruptionDetectionEnabled())
{
- VkResult res = pBlock->ValidateMagicValueAroundAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
+ VkResult res = pBlock->ValidateMagicValueAfterAllocation(m_hAllocator, hAllocation->GetOffset(), hAllocation->GetSize());
VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to validate magic value.");
}
- if(hAllocation->IsPersistentMap())
+ if (hAllocation->IsPersistentMap())
{
pBlock->Unmap(m_hAllocator, 1);
}
- pBlock->m_pMetadata->Free(hAllocation);
+ const bool hadEmptyBlockBeforeFree = HasEmptyBlock();
+ pBlock->m_pMetadata->Free(hAllocation->GetAllocHandle());
+ pBlock->PostFree(m_hAllocator);
VMA_HEAVY_ASSERT(pBlock->Validate());
VMA_DEBUG_LOG(" Freed from MemoryTypeIndex=%u", m_MemoryTypeIndex);
const bool canDeleteBlock = m_Blocks.size() > m_MinBlockCount;
// pBlock became empty after this deallocation.
- if(pBlock->m_pMetadata->IsEmpty())
+ if (pBlock->m_pMetadata->IsEmpty())
{
- // Already has empty block. We don't want to have two, so delete this one.
- if((m_HasEmptyBlock || budgetExceeded) && canDeleteBlock)
+ // Already had empty block. We don't want to have two, so delete this one.
+ if ((hadEmptyBlockBeforeFree || budgetExceeded) && canDeleteBlock)
{
pBlockToDelete = pBlock;
Remove(pBlock);
}
- // else: We now have an empty block - leave it.
+ // else: We now have one empty block - leave it. A hysteresis to avoid allocating whole block back and forth.
}
// pBlock didn't become empty, but we have another empty block - find and free that one.
// (This is optional, heuristics.)
- else if(m_HasEmptyBlock && canDeleteBlock)
+ else if (hadEmptyBlockBeforeFree && canDeleteBlock)
{
VmaDeviceMemoryBlock* pLastBlock = m_Blocks.back();
- if(pLastBlock->m_pMetadata->IsEmpty())
+ if (pLastBlock->m_pMetadata->IsEmpty())
{
pBlockToDelete = pLastBlock;
m_Blocks.pop_back();
}
}
- UpdateHasEmptyBlock();
IncrementallySortBlocks();
}
// Destruction of a free block. Deferred until this point, outside of mutex
// lock, for performance reason.
- if(pBlockToDelete != VMA_NULL)
+ if (pBlockToDelete != VMA_NULL)
{
- VMA_DEBUG_LOG(" Deleted empty block");
+ VMA_DEBUG_LOG(" Deleted empty block #%u", pBlockToDelete->GetId());
pBlockToDelete->Destroy(m_hAllocator);
vma_delete(m_hAllocator, pBlockToDelete);
}
+
+ m_hAllocator->m_Budget.RemoveAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), hAllocation->GetSize());
+ m_hAllocator->m_AllocationObjectAllocator.Free(hAllocation);
}
VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
{
VkDeviceSize result = 0;
- for(size_t i = m_Blocks.size(); i--; )
+ for (size_t i = m_Blocks.size(); i--; )
{
result = VMA_MAX(result, m_Blocks[i]->m_pMetadata->GetSize());
- if(result >= m_PreferredBlockSize)
+ if (result >= m_PreferredBlockSize)
{
break;
}
@@ -13580,9 +12704,9 @@ VkDeviceSize VmaBlockVector::CalcMaxBlockSize() const
void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
{
- for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
{
- if(m_Blocks[blockIndex] == pBlock)
+ if (m_Blocks[blockIndex] == pBlock)
{
VmaVectorRemove(m_Blocks, blockIndex);
return;
@@ -13593,12 +12717,14 @@ void VmaBlockVector::Remove(VmaDeviceMemoryBlock* pBlock)
void VmaBlockVector::IncrementallySortBlocks()
{
- if(m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ if (!m_IncrementalSort)
+ return;
+ if (m_Algorithm != VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
{
// Bubble sort only until first swap.
- for(size_t i = 1; i < m_Blocks.size(); ++i)
+ for (size_t i = 1; i < m_Blocks.size(); ++i)
{
- if(m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
+ if (m_Blocks[i - 1]->m_pMetadata->GetSumFreeSize() > m_Blocks[i]->m_pMetadata->GetSumFreeSize())
{
VMA_SWAP(m_Blocks[i - 1], m_Blocks[i]);
return;
@@ -13607,9 +12733,17 @@ void VmaBlockVector::IncrementallySortBlocks()
}
}
+void VmaBlockVector::SortByFreeSize()
+{
+ VMA_SORT(m_Blocks.begin(), m_Blocks.end(),
+ [](VmaDeviceMemoryBlock* b1, VmaDeviceMemoryBlock* b2) -> bool
+ {
+ return b1->m_pMetadata->GetSumFreeSize() < b2->m_pMetadata->GetSumFreeSize();
+ });
+}
+
VkResult VmaBlockVector::AllocateFromBlock(
VmaDeviceMemoryBlock* pBlock,
- uint32_t currentFrameIndex,
VkDeviceSize size,
VkDeviceSize alignment,
VmaAllocationCreateFlags allocFlags,
@@ -13618,63 +12752,73 @@ VkResult VmaBlockVector::AllocateFromBlock(
uint32_t strategy,
VmaAllocation* pAllocation)
{
- VMA_ASSERT((allocFlags & VMA_ALLOCATION_CREATE_CAN_MAKE_OTHER_LOST_BIT) == 0);
const bool isUpperAddress = (allocFlags & VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT) != 0;
- const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
- const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
VmaAllocationRequest currRequest = {};
- if(pBlock->m_pMetadata->CreateAllocationRequest(
- currentFrameIndex,
- m_FrameInUseCount,
- m_BufferImageGranularity,
+ if (pBlock->m_pMetadata->CreateAllocationRequest(
size,
alignment,
isUpperAddress,
suballocType,
- false, // canMakeOtherLost
strategy,
&currRequest))
{
- // Allocate from pCurrBlock.
- VMA_ASSERT(currRequest.itemsToMakeLostCount == 0);
+ return CommitAllocationRequest(currRequest, pBlock, alignment, allocFlags, pUserData, suballocType, pAllocation);
+ }
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+}
- if(mapped)
+VkResult VmaBlockVector::CommitAllocationRequest(
+ VmaAllocationRequest& allocRequest,
+ VmaDeviceMemoryBlock* pBlock,
+ VkDeviceSize alignment,
+ VmaAllocationCreateFlags allocFlags,
+ void* pUserData,
+ VmaSuballocationType suballocType,
+ VmaAllocation* pAllocation)
+{
+ const bool mapped = (allocFlags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0;
+ const bool isUserDataString = (allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0;
+ const bool isMappingAllowed = (allocFlags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0;
+
+ pBlock->PostAlloc();
+ // Allocate from pCurrBlock.
+ if (mapped)
+ {
+ VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);
+ if (res != VK_SUCCESS)
{
- VkResult res = pBlock->Map(m_hAllocator, 1, VMA_NULL);
- if(res != VK_SUCCESS)
- {
- return res;
- }
+ return res;
}
+ }
- *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(currentFrameIndex, isUserDataString);
- pBlock->m_pMetadata->Alloc(currRequest, suballocType, size, *pAllocation);
- UpdateHasEmptyBlock();
- (*pAllocation)->InitBlockAllocation(
- pBlock,
- currRequest.offset,
- alignment,
- size,
- m_MemoryTypeIndex,
- suballocType,
- mapped,
- (allocFlags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0);
- VMA_HEAVY_ASSERT(pBlock->Validate());
+ *pAllocation = m_hAllocator->m_AllocationObjectAllocator.Allocate(isMappingAllowed);
+ pBlock->m_pMetadata->Alloc(allocRequest, suballocType, *pAllocation);
+ (*pAllocation)->InitBlockAllocation(
+ pBlock,
+ allocRequest.allocHandle,
+ alignment,
+ allocRequest.size, // Not size, as actual allocation size may be larger than requested!
+ m_MemoryTypeIndex,
+ suballocType,
+ mapped);
+ VMA_HEAVY_ASSERT(pBlock->Validate());
+ if (isUserDataString)
+ (*pAllocation)->SetName(m_hAllocator, (const char*)pUserData);
+ else
(*pAllocation)->SetUserData(m_hAllocator, pUserData);
- m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), size);
- if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
- {
- m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
- }
- if(IsCorruptionDetectionEnabled())
- {
- VkResult res = pBlock->WriteMagicValueAroundAllocation(m_hAllocator, currRequest.offset, size);
- VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
- }
- return VK_SUCCESS;
+ m_hAllocator->m_Budget.AddAllocation(m_hAllocator->MemoryTypeIndexToHeapIndex(m_MemoryTypeIndex), allocRequest.size);
+ if (VMA_DEBUG_INITIALIZE_ALLOCATIONS)
+ {
+ m_hAllocator->FillAllocation(*pAllocation, VMA_ALLOCATION_FILL_PATTERN_CREATED);
}
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ if (IsCorruptionDetectionEnabled())
+ {
+ VkResult res = pBlock->WriteMagicValueAfterAllocation(m_hAllocator, (*pAllocation)->GetOffset(), allocRequest.size);
+ VMA_ASSERT(res == VK_SUCCESS && "Couldn't map block memory to write magic value.");
+ }
+ return VK_SUCCESS;
}
VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIndex)
@@ -13687,35 +12831,36 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
#if VMA_BUFFER_DEVICE_ADDRESS
// Every standalone block can potentially contain a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT - always enable the feature.
VkMemoryAllocateFlagsInfoKHR allocFlagsInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR };
- if(m_hAllocator->m_UseKhrBufferDeviceAddress)
+ if (m_hAllocator->m_UseKhrBufferDeviceAddress)
{
allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
VmaPnextChainPushFront(&allocInfo, &allocFlagsInfo);
}
-#endif // #if VMA_BUFFER_DEVICE_ADDRESS
+#endif // VMA_BUFFER_DEVICE_ADDRESS
#if VMA_MEMORY_PRIORITY
VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT };
- if(m_hAllocator->m_UseExtMemoryPriority)
+ if (m_hAllocator->m_UseExtMemoryPriority)
{
+ VMA_ASSERT(m_Priority >= 0.f && m_Priority <= 1.f);
priorityInfo.priority = m_Priority;
VmaPnextChainPushFront(&allocInfo, &priorityInfo);
}
-#endif // #if VMA_MEMORY_PRIORITY
+#endif // VMA_MEMORY_PRIORITY
#if VMA_EXTERNAL_MEMORY
// Attach VkExportMemoryAllocateInfoKHR if necessary.
VkExportMemoryAllocateInfoKHR exportMemoryAllocInfo = { VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR };
exportMemoryAllocInfo.handleTypes = m_hAllocator->GetExternalMemoryHandleTypeFlags(m_MemoryTypeIndex);
- if(exportMemoryAllocInfo.handleTypes != 0)
+ if (exportMemoryAllocInfo.handleTypes != 0)
{
VmaPnextChainPushFront(&allocInfo, &exportMemoryAllocInfo);
}
-#endif // #if VMA_EXTERNAL_MEMORY
+#endif // VMA_EXTERNAL_MEMORY
VkDeviceMemory mem = VK_NULL_HANDLE;
VkResult res = m_hAllocator->AllocateVulkanMemory(&allocInfo, &mem);
- if(res < 0)
+ if (res < 0)
{
return res;
}
@@ -13726,16 +12871,16 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
VmaDeviceMemoryBlock* const pBlock = vma_new(m_hAllocator, VmaDeviceMemoryBlock)(m_hAllocator);
pBlock->Init(
m_hAllocator,
- this, // parentBlockVector
m_hParentPool,
m_MemoryTypeIndex,
mem,
allocInfo.allocationSize,
m_NextBlockId++,
- m_Algorithm);
+ m_Algorithm,
+ m_BufferImageGranularity);
m_Blocks.push_back(pBlock);
- if(pNewBlockIndex != VMA_NULL)
+ if (pNewBlockIndex != VMA_NULL)
{
*pNewBlockIndex = m_Blocks.size() - 1;
}
@@ -13743,2327 +12888,1087 @@ VkResult VmaBlockVector::CreateBlock(VkDeviceSize blockSize, size_t* pNewBlockIn
return VK_SUCCESS;
}
-void VmaBlockVector::ApplyDefragmentationMovesCpu(
- class VmaBlockVectorDefragmentationContext* pDefragCtx,
- const VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves)
+bool VmaBlockVector::HasEmptyBlock()
{
- const size_t blockCount = m_Blocks.size();
- const bool isNonCoherent = m_hAllocator->IsMemoryTypeNonCoherent(m_MemoryTypeIndex);
-
- enum BLOCK_FLAG
- {
- BLOCK_FLAG_USED = 0x00000001,
- BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION = 0x00000002,
- };
-
- struct BlockInfo
- {
- uint32_t flags;
- void* pMappedData;
- };
- VmaVector< BlockInfo, VmaStlAllocator<BlockInfo> >
- blockInfo(blockCount, BlockInfo(), VmaStlAllocator<BlockInfo>(m_hAllocator->GetAllocationCallbacks()));
- memset(blockInfo.data(), 0, blockCount * sizeof(BlockInfo));
-
- // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
- const size_t moveCount = moves.size();
- for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ for (size_t index = 0, count = m_Blocks.size(); index < count; ++index)
{
- const VmaDefragmentationMove& move = moves[moveIndex];
- blockInfo[move.srcBlockIndex].flags |= BLOCK_FLAG_USED;
- blockInfo[move.dstBlockIndex].flags |= BLOCK_FLAG_USED;
- }
-
- VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
-
- // Go over all blocks. Get mapped pointer or map if necessary.
- for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
- {
- BlockInfo& currBlockInfo = blockInfo[blockIndex];
- VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
- if((currBlockInfo.flags & BLOCK_FLAG_USED) != 0)
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[index];
+ if (pBlock->m_pMetadata->IsEmpty())
{
- currBlockInfo.pMappedData = pBlock->GetMappedData();
- // It is not originally mapped - map it.
- if(currBlockInfo.pMappedData == VMA_NULL)
- {
- pDefragCtx->res = pBlock->Map(m_hAllocator, 1, &currBlockInfo.pMappedData);
- if(pDefragCtx->res == VK_SUCCESS)
- {
- currBlockInfo.flags |= BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION;
- }
- }
+ return true;
}
}
+ return false;
+}
- // Go over all moves. Do actual data transfer.
- if(pDefragCtx->res == VK_SUCCESS)
- {
- const VkDeviceSize nonCoherentAtomSize = m_hAllocator->m_PhysicalDeviceProperties.limits.nonCoherentAtomSize;
- VkMappedMemoryRange memRange = { VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE };
-
- for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
- {
- const VmaDefragmentationMove& move = moves[moveIndex];
-
- const BlockInfo& srcBlockInfo = blockInfo[move.srcBlockIndex];
- const BlockInfo& dstBlockInfo = blockInfo[move.dstBlockIndex];
+#if VMA_STATS_STRING_ENABLED
+void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
+{
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
- VMA_ASSERT(srcBlockInfo.pMappedData && dstBlockInfo.pMappedData);
- // Invalidate source.
- if(isNonCoherent)
- {
- VmaDeviceMemoryBlock* const pSrcBlock = m_Blocks[move.srcBlockIndex];
- memRange.memory = pSrcBlock->GetDeviceMemory();
- memRange.offset = VmaAlignDown(move.srcOffset, nonCoherentAtomSize);
- memRange.size = VMA_MIN(
- VmaAlignUp(move.size + (move.srcOffset - memRange.offset), nonCoherentAtomSize),
- pSrcBlock->m_pMetadata->GetSize() - memRange.offset);
- (*m_hAllocator->GetVulkanFunctions().vkInvalidateMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
- }
+ json.BeginObject();
+ for (size_t i = 0; i < m_Blocks.size(); ++i)
+ {
+ json.BeginString();
+ json.ContinueString(m_Blocks[i]->GetId());
+ json.EndString();
- // THE PLACE WHERE ACTUAL DATA COPY HAPPENS.
- memmove(
- reinterpret_cast<char*>(dstBlockInfo.pMappedData) + move.dstOffset,
- reinterpret_cast<char*>(srcBlockInfo.pMappedData) + move.srcOffset,
- static_cast<size_t>(move.size));
+ json.BeginObject();
+ json.WriteString("MapRefCount");
+ json.WriteNumber(m_Blocks[i]->GetMapRefCount());
- if(IsCorruptionDetectionEnabled())
- {
- VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset - VMA_DEBUG_MARGIN);
- VmaWriteMagicValue(dstBlockInfo.pMappedData, move.dstOffset + move.size);
- }
+ m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
+ json.EndObject();
+ }
+ json.EndObject();
+}
+#endif // VMA_STATS_STRING_ENABLED
- // Flush destination.
- if(isNonCoherent)
- {
- VmaDeviceMemoryBlock* const pDstBlock = m_Blocks[move.dstBlockIndex];
- memRange.memory = pDstBlock->GetDeviceMemory();
- memRange.offset = VmaAlignDown(move.dstOffset, nonCoherentAtomSize);
- memRange.size = VMA_MIN(
- VmaAlignUp(move.size + (move.dstOffset - memRange.offset), nonCoherentAtomSize),
- pDstBlock->m_pMetadata->GetSize() - memRange.offset);
- (*m_hAllocator->GetVulkanFunctions().vkFlushMappedMemoryRanges)(m_hAllocator->m_hDevice, 1, &memRange);
- }
- }
+VkResult VmaBlockVector::CheckCorruption()
+{
+ if (!IsCorruptionDetectionEnabled())
+ {
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
- // Go over all blocks in reverse order. Unmap those that were mapped just for defragmentation.
- // Regardless of pCtx->res == VK_SUCCESS.
- for(size_t blockIndex = blockCount; blockIndex--; )
+ VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
+ for (uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
{
- const BlockInfo& currBlockInfo = blockInfo[blockIndex];
- if((currBlockInfo.flags & BLOCK_FLAG_MAPPED_FOR_DEFRAGMENTATION) != 0)
+ VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
+ VMA_ASSERT(pBlock);
+ VkResult res = pBlock->CheckCorruption(m_hAllocator);
+ if (res != VK_SUCCESS)
{
- VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
- pBlock->Unmap(m_hAllocator, 1);
+ return res;
}
}
+ return VK_SUCCESS;
}
-void VmaBlockVector::ApplyDefragmentationMovesGpu(
- class VmaBlockVectorDefragmentationContext* pDefragCtx,
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkCommandBuffer commandBuffer)
-{
- const size_t blockCount = m_Blocks.size();
+#endif // _VMA_BLOCK_VECTOR_FUNCTIONS
- pDefragCtx->blockContexts.resize(blockCount);
- memset(pDefragCtx->blockContexts.data(), 0, blockCount * sizeof(VmaBlockDefragmentationContext));
+#ifndef _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS
+VmaDefragmentationContext_T::VmaDefragmentationContext_T(
+ VmaAllocator hAllocator,
+ const VmaDefragmentationInfo& info)
+ : m_MaxPassBytes(info.maxBytesPerPass == 0 ? VK_WHOLE_SIZE : info.maxBytesPerPass),
+ m_MaxPassAllocations(info.maxAllocationsPerPass == 0 ? UINT32_MAX : info.maxAllocationsPerPass),
+ m_MoveAllocator(hAllocator->GetAllocationCallbacks()),
+ m_Moves(m_MoveAllocator)
+{
+ m_Algorithm = info.flags & VMA_DEFRAGMENTATION_FLAG_ALGORITHM_MASK;
- // Go over all moves. Mark blocks that are used with BLOCK_FLAG_USED.
- const size_t moveCount = moves.size();
- for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ if (info.pool != VMA_NULL)
{
- const VmaDefragmentationMove& move = moves[moveIndex];
-
- //if(move.type == VMA_ALLOCATION_TYPE_UNKNOWN)
- {
- // Old school move still require us to map the whole block
- pDefragCtx->blockContexts[move.srcBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
- pDefragCtx->blockContexts[move.dstBlockIndex].flags |= VmaBlockDefragmentationContext::BLOCK_FLAG_USED;
- }
+ m_BlockVectorCount = 1;
+ m_PoolBlockVector = &info.pool->m_BlockVector;
+ m_pBlockVectors = &m_PoolBlockVector;
+ m_PoolBlockVector->SetIncrementalSort(false);
+ m_PoolBlockVector->SortByFreeSize();
}
-
- VMA_ASSERT(pDefragCtx->res == VK_SUCCESS);
-
- // Go over all blocks. Create and bind buffer for whole block if necessary.
+ else
{
- VkBufferCreateInfo bufCreateInfo;
- VmaFillGpuDefragmentationBufferCreateInfo(bufCreateInfo);
-
- for(size_t blockIndex = 0; pDefragCtx->res == VK_SUCCESS && blockIndex < blockCount; ++blockIndex)
+ m_BlockVectorCount = hAllocator->GetMemoryTypeCount();
+ m_PoolBlockVector = VMA_NULL;
+ m_pBlockVectors = hAllocator->m_pBlockVectors;
+ for (uint32_t i = 0; i < m_BlockVectorCount; ++i)
{
- VmaBlockDefragmentationContext& currBlockCtx = pDefragCtx->blockContexts[blockIndex];
- VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
- if((currBlockCtx.flags & VmaBlockDefragmentationContext::BLOCK_FLAG_USED) != 0)
+ VmaBlockVector* vector = m_pBlockVectors[i];
+ if (vector != VMA_NULL)
{
- bufCreateInfo.size = pBlock->m_pMetadata->GetSize();
- pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkCreateBuffer)(
- m_hAllocator->m_hDevice, &bufCreateInfo, m_hAllocator->GetAllocationCallbacks(), &currBlockCtx.hBuffer);
- if(pDefragCtx->res == VK_SUCCESS)
- {
- pDefragCtx->res = (*m_hAllocator->GetVulkanFunctions().vkBindBufferMemory)(
- m_hAllocator->m_hDevice, currBlockCtx.hBuffer, pBlock->GetDeviceMemory(), 0);
- }
+ vector->SetIncrementalSort(false);
+ vector->SortByFreeSize();
}
}
}
- // Go over all moves. Post data transfer commands to command buffer.
- if(pDefragCtx->res == VK_SUCCESS)
+ switch (m_Algorithm)
+ {
+ case 0: // Default algorithm
+ m_Algorithm = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT;
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:
{
- for(size_t moveIndex = 0; moveIndex < moveCount; ++moveIndex)
+ m_AlgorithmState = vma_new_array(hAllocator, StateBalanced, m_BlockVectorCount);
+ break;
+ }
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:
+ {
+ if (hAllocator->GetBufferImageGranularity() > 1)
{
- const VmaDefragmentationMove& move = moves[moveIndex];
-
- const VmaBlockDefragmentationContext& srcBlockCtx = pDefragCtx->blockContexts[move.srcBlockIndex];
- const VmaBlockDefragmentationContext& dstBlockCtx = pDefragCtx->blockContexts[move.dstBlockIndex];
-
- VMA_ASSERT(srcBlockCtx.hBuffer && dstBlockCtx.hBuffer);
-
- VkBufferCopy region = {
- move.srcOffset,
- move.dstOffset,
- move.size };
- (*m_hAllocator->GetVulkanFunctions().vkCmdCopyBuffer)(
- commandBuffer, srcBlockCtx.hBuffer, dstBlockCtx.hBuffer, 1, &region);
+ m_AlgorithmState = vma_new_array(hAllocator, StateExtensive, m_BlockVectorCount);
}
+ break;
}
-
- // Save buffers to defrag context for later destruction.
- if(pDefragCtx->res == VK_SUCCESS && moveCount > 0)
- {
- pDefragCtx->res = VK_NOT_READY;
}
}
-void VmaBlockVector::FreeEmptyBlocks(VmaDefragmentationStats* pDefragmentationStats)
+VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
{
- for(size_t blockIndex = m_Blocks.size(); blockIndex--; )
+ if (m_PoolBlockVector != VMA_NULL)
+ {
+ m_PoolBlockVector->SetIncrementalSort(true);
+ }
+ else
{
- VmaDeviceMemoryBlock* pBlock = m_Blocks[blockIndex];
- if(pBlock->m_pMetadata->IsEmpty())
+ for (uint32_t i = 0; i < m_BlockVectorCount; ++i)
{
- if(m_Blocks.size() > m_MinBlockCount)
- {
- if(pDefragmentationStats != VMA_NULL)
- {
- ++pDefragmentationStats->deviceMemoryBlocksFreed;
- pDefragmentationStats->bytesFreed += pBlock->m_pMetadata->GetSize();
- }
-
- VmaVectorRemove(m_Blocks, blockIndex);
- pBlock->Destroy(m_hAllocator);
- vma_delete(m_hAllocator, pBlock);
- }
- else
- {
- break;
- }
+ VmaBlockVector* vector = m_pBlockVectors[i];
+ if (vector != VMA_NULL)
+ vector->SetIncrementalSort(true);
}
}
- UpdateHasEmptyBlock();
-}
-void VmaBlockVector::UpdateHasEmptyBlock()
-{
- m_HasEmptyBlock = false;
- for(size_t index = 0, count = m_Blocks.size(); index < count; ++index)
+ if (m_AlgorithmState)
{
- VmaDeviceMemoryBlock* const pBlock = m_Blocks[index];
- if(pBlock->m_pMetadata->IsEmpty())
+ switch (m_Algorithm)
{
- m_HasEmptyBlock = true;
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:
+ vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast<StateBalanced*>(m_AlgorithmState), m_BlockVectorCount);
+ break;
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:
+ vma_delete_array(m_MoveAllocator.m_pCallbacks, reinterpret_cast<StateExtensive*>(m_AlgorithmState), m_BlockVectorCount);
break;
+ default:
+ VMA_ASSERT(0);
}
}
}
-#if VMA_STATS_STRING_ENABLED
-
-void VmaBlockVector::PrintDetailedMap(class VmaJsonWriter& json)
+VkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassMoveInfo& moveInfo)
{
- VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
-
- json.BeginObject();
-
- if(IsCustomPool())
+ if (m_PoolBlockVector != VMA_NULL)
{
- const char* poolName = m_hParentPool->GetName();
- if(poolName != VMA_NULL && poolName[0] != '\0')
- {
- json.WriteString("Name");
- json.WriteString(poolName);
- }
-
- json.WriteString("MemoryTypeIndex");
- json.WriteNumber(m_MemoryTypeIndex);
-
- json.WriteString("BlockSize");
- json.WriteNumber(m_PreferredBlockSize);
-
- json.WriteString("BlockCount");
- json.BeginObject(true);
- if(m_MinBlockCount > 0)
- {
- json.WriteString("Min");
- json.WriteNumber((uint64_t)m_MinBlockCount);
- }
- if(m_MaxBlockCount < SIZE_MAX)
- {
- json.WriteString("Max");
- json.WriteNumber((uint64_t)m_MaxBlockCount);
- }
- json.WriteString("Cur");
- json.WriteNumber((uint64_t)m_Blocks.size());
- json.EndObject();
-
- if(m_FrameInUseCount > 0)
- {
- json.WriteString("FrameInUseCount");
- json.WriteNumber(m_FrameInUseCount);
- }
+ VmaMutexLockWrite lock(m_PoolBlockVector->GetMutex(), m_PoolBlockVector->GetAllocator()->m_UseMutex);
- if(m_Algorithm != 0)
- {
- json.WriteString("Algorithm");
- json.WriteString(VmaAlgorithmToStr(m_Algorithm));
- }
+ if (m_PoolBlockVector->GetBlockCount() > 1)
+ ComputeDefragmentation(*m_PoolBlockVector, 0);
+ else if (m_PoolBlockVector->GetBlockCount() == 1)
+ ReallocWithinBlock(*m_PoolBlockVector, m_PoolBlockVector->GetBlock(0));
}
else
{
- json.WriteString("PreferredBlockSize");
- json.WriteNumber(m_PreferredBlockSize);
+ for (uint32_t i = 0; i < m_BlockVectorCount; ++i)
+ {
+ if (m_pBlockVectors[i] != VMA_NULL)
+ {
+ VmaMutexLockWrite lock(m_pBlockVectors[i]->GetMutex(), m_pBlockVectors[i]->GetAllocator()->m_UseMutex);
+
+ if (m_pBlockVectors[i]->GetBlockCount() > 1)
+ {
+ if (ComputeDefragmentation(*m_pBlockVectors[i], i))
+ break;
+ }
+ else if (m_pBlockVectors[i]->GetBlockCount() == 1)
+ {
+ if (ReallocWithinBlock(*m_pBlockVectors[i], m_pBlockVectors[i]->GetBlock(0)))
+ break;
+ }
+ }
+ }
}
- json.WriteString("Blocks");
- json.BeginObject();
- for(size_t i = 0; i < m_Blocks.size(); ++i)
+ moveInfo.moveCount = static_cast<uint32_t>(m_Moves.size());
+ if (moveInfo.moveCount > 0)
{
- json.BeginString();
- json.ContinueString(m_Blocks[i]->GetId());
- json.EndString();
-
- m_Blocks[i]->m_pMetadata->PrintDetailedMap(json);
+ moveInfo.pMoves = m_Moves.data();
+ return VK_INCOMPLETE;
}
- json.EndObject();
- json.EndObject();
+ moveInfo.pMoves = VMA_NULL;
+ return VK_SUCCESS;
}
-#endif // #if VMA_STATS_STRING_ENABLED
-
-void VmaBlockVector::Defragment(
- class VmaBlockVectorDefragmentationContext* pCtx,
- VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags,
- VkDeviceSize& maxCpuBytesToMove, uint32_t& maxCpuAllocationsToMove,
- VkDeviceSize& maxGpuBytesToMove, uint32_t& maxGpuAllocationsToMove,
- VkCommandBuffer commandBuffer)
+VkResult VmaDefragmentationContext_T::DefragmentPassEnd(VmaDefragmentationPassMoveInfo& moveInfo)
{
- pCtx->res = VK_SUCCESS;
-
- const VkMemoryPropertyFlags memPropFlags =
- m_hAllocator->m_MemProps.memoryTypes[m_MemoryTypeIndex].propertyFlags;
- const bool isHostVisible = (memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0;
+ VMA_ASSERT(moveInfo.moveCount > 0 ? moveInfo.pMoves != VMA_NULL : true);
- const bool canDefragmentOnCpu = maxCpuBytesToMove > 0 && maxCpuAllocationsToMove > 0 &&
- isHostVisible;
- const bool canDefragmentOnGpu = maxGpuBytesToMove > 0 && maxGpuAllocationsToMove > 0 &&
- !IsCorruptionDetectionEnabled() &&
- ((1u << m_MemoryTypeIndex) & m_hAllocator->GetGpuDefragmentationMemoryTypeBits()) != 0;
+ VkResult result = VK_SUCCESS;
+ VmaStlAllocator<FragmentedBlock> blockAllocator(m_MoveAllocator.m_pCallbacks);
+ VmaVector<FragmentedBlock, VmaStlAllocator<FragmentedBlock>> immovableBlocks(blockAllocator);
+ VmaVector<FragmentedBlock, VmaStlAllocator<FragmentedBlock>> mappedBlocks(blockAllocator);
- // There are options to defragment this memory type.
- if(canDefragmentOnCpu || canDefragmentOnGpu)
+ VmaAllocator allocator = VMA_NULL;
+ for (uint32_t i = 0; i < moveInfo.moveCount; ++i)
{
- bool defragmentOnGpu;
- // There is only one option to defragment this memory type.
- if(canDefragmentOnGpu != canDefragmentOnCpu)
+ VmaDefragmentationMove& move = moveInfo.pMoves[i];
+ size_t prevCount = 0, currentCount = 0;
+ VkDeviceSize freedBlockSize = 0;
+
+ uint32_t vectorIndex;
+ VmaBlockVector* vector;
+ if (m_PoolBlockVector != VMA_NULL)
{
- defragmentOnGpu = canDefragmentOnGpu;
+ vectorIndex = 0;
+ vector = m_PoolBlockVector;
}
- // Both options are available: Heuristics to choose the best one.
else
{
- defragmentOnGpu = (memPropFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0 ||
- m_hAllocator->IsIntegratedGpu();
+ vectorIndex = move.srcAllocation->GetMemoryTypeIndex();
+ vector = m_pBlockVectors[vectorIndex];
+ VMA_ASSERT(vector != VMA_NULL);
}
- bool overlappingMoveSupported = !defragmentOnGpu;
-
- if(m_hAllocator->m_UseMutex)
+ switch (move.operation)
{
- if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
+ case VMA_DEFRAGMENTATION_MOVE_OPERATION_COPY:
+ {
+ uint8_t mapCount = move.srcAllocation->SwapBlockAllocation(vector->m_hAllocator, move.dstTmpAllocation);
+ if (mapCount > 0)
{
- if(!m_Mutex.TryLockWrite())
+ allocator = vector->m_hAllocator;
+ VmaDeviceMemoryBlock* newMapBlock = move.srcAllocation->GetBlock();
+ bool notPresent = true;
+ for (FragmentedBlock& block : mappedBlocks)
{
- pCtx->res = VK_ERROR_INITIALIZATION_FAILED;
- return;
+ if (block.block == newMapBlock)
+ {
+ notPresent = false;
+ block.data += mapCount;
+ break;
+ }
}
+ if (notPresent)
+ mappedBlocks.push_back({ mapCount, newMapBlock });
}
- else
- {
- m_Mutex.LockWrite();
- pCtx->mutexLocked = true;
- }
- }
-
- pCtx->Begin(overlappingMoveSupported, flags);
- // Defragment.
-
- const VkDeviceSize maxBytesToMove = defragmentOnGpu ? maxGpuBytesToMove : maxCpuBytesToMove;
- const uint32_t maxAllocationsToMove = defragmentOnGpu ? maxGpuAllocationsToMove : maxCpuAllocationsToMove;
- pCtx->res = pCtx->GetAlgorithm()->Defragment(pCtx->defragmentationMoves, maxBytesToMove, maxAllocationsToMove, flags);
-
- // Accumulate statistics.
- if(pStats != VMA_NULL)
- {
- const VkDeviceSize bytesMoved = pCtx->GetAlgorithm()->GetBytesMoved();
- const uint32_t allocationsMoved = pCtx->GetAlgorithm()->GetAllocationsMoved();
- pStats->bytesMoved += bytesMoved;
- pStats->allocationsMoved += allocationsMoved;
- VMA_ASSERT(bytesMoved <= maxBytesToMove);
- VMA_ASSERT(allocationsMoved <= maxAllocationsToMove);
- if(defragmentOnGpu)
+ // Scope for locks, Free have it's own lock
{
- maxGpuBytesToMove -= bytesMoved;
- maxGpuAllocationsToMove -= allocationsMoved;
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ prevCount = vector->GetBlockCount();
+ freedBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize();
}
- else
+ vector->Free(move.dstTmpAllocation);
{
- maxCpuBytesToMove -= bytesMoved;
- maxCpuAllocationsToMove -= allocationsMoved;
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ currentCount = vector->GetBlockCount();
}
- }
- if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
+ result = VK_INCOMPLETE;
+ break;
+ }
+ case VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE:
{
- if(m_hAllocator->m_UseMutex)
- m_Mutex.UnlockWrite();
-
- if(pCtx->res >= VK_SUCCESS && !pCtx->defragmentationMoves.empty())
- pCtx->res = VK_NOT_READY;
+ m_PassStats.bytesMoved -= move.srcAllocation->GetSize();
+ --m_PassStats.allocationsMoved;
+ vector->Free(move.dstTmpAllocation);
- return;
+ VmaDeviceMemoryBlock* newBlock = move.srcAllocation->GetBlock();
+ bool notPresent = true;
+ for (const FragmentedBlock& block : immovableBlocks)
+ {
+ if (block.block == newBlock)
+ {
+ notPresent = false;
+ break;
+ }
+ }
+ if (notPresent)
+ immovableBlocks.push_back({ vectorIndex, newBlock });
+ break;
}
-
- if(pCtx->res >= VK_SUCCESS)
+ case VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY:
{
- if(defragmentOnGpu)
+ m_PassStats.bytesMoved -= move.srcAllocation->GetSize();
+ --m_PassStats.allocationsMoved;
+ // Scope for locks, Free have it's own lock
{
- ApplyDefragmentationMovesGpu(pCtx, pCtx->defragmentationMoves, commandBuffer);
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ prevCount = vector->GetBlockCount();
+ freedBlockSize = move.srcAllocation->GetBlock()->m_pMetadata->GetSize();
}
- else
+ vector->Free(move.srcAllocation);
{
- ApplyDefragmentationMovesCpu(pCtx, pCtx->defragmentationMoves);
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ currentCount = vector->GetBlockCount();
}
- }
- }
-}
-
-void VmaBlockVector::DefragmentationEnd(
- class VmaBlockVectorDefragmentationContext* pCtx,
- uint32_t flags,
- VmaDefragmentationStats* pStats)
-{
- if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL && m_hAllocator->m_UseMutex)
- {
- VMA_ASSERT(pCtx->mutexLocked == false);
-
- // Incremental defragmentation doesn't hold the lock, so when we enter here we don't actually have any
- // lock protecting us. Since we mutate state here, we have to take the lock out now
- m_Mutex.LockWrite();
- pCtx->mutexLocked = true;
- }
+ freedBlockSize *= prevCount - currentCount;
- // If the mutex isn't locked we didn't do any work and there is nothing to delete.
- if(pCtx->mutexLocked || !m_hAllocator->m_UseMutex)
- {
- // Destroy buffers.
- for(size_t blockIndex = pCtx->blockContexts.size(); blockIndex--;)
- {
- VmaBlockDefragmentationContext &blockCtx = pCtx->blockContexts[blockIndex];
- if(blockCtx.hBuffer)
+ VkDeviceSize dstBlockSize;
+ {
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ dstBlockSize = move.dstTmpAllocation->GetBlock()->m_pMetadata->GetSize();
+ }
+ vector->Free(move.dstTmpAllocation);
{
- (*m_hAllocator->GetVulkanFunctions().vkDestroyBuffer)(m_hAllocator->m_hDevice, blockCtx.hBuffer, m_hAllocator->GetAllocationCallbacks());
+ VmaMutexLockRead lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
+ freedBlockSize += dstBlockSize * (currentCount - vector->GetBlockCount());
+ currentCount = vector->GetBlockCount();
}
+
+ result = VK_INCOMPLETE;
+ break;
+ }
+ default:
+ VMA_ASSERT(0);
}
- if(pCtx->res >= VK_SUCCESS)
+ if (prevCount > currentCount)
{
- FreeEmptyBlocks(pStats);
+ size_t freedBlocks = prevCount - currentCount;
+ m_PassStats.deviceMemoryBlocksFreed += static_cast<uint32_t>(freedBlocks);
+ m_PassStats.bytesFreed += freedBlockSize;
}
- }
- if(pCtx->mutexLocked)
- {
- VMA_ASSERT(m_hAllocator->m_UseMutex);
- m_Mutex.UnlockWrite();
+ switch (m_Algorithm)
+ {
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:
+ {
+ if (m_AlgorithmState != VMA_NULL)
+ {
+ // Avoid unnecessary tries to allocate when new free block is avaiable
+ StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[vectorIndex];
+ if (state.firstFreeBlock != SIZE_MAX)
+ {
+ const size_t diff = prevCount - currentCount;
+ if (state.firstFreeBlock >= diff)
+ {
+ state.firstFreeBlock -= diff;
+ if (state.firstFreeBlock != 0)
+ state.firstFreeBlock -= vector->GetBlock(state.firstFreeBlock - 1)->m_pMetadata->IsEmpty();
+ }
+ else
+ state.firstFreeBlock = 0;
+ }
+ }
+ }
+ }
}
-}
+ moveInfo.moveCount = 0;
+ moveInfo.pMoves = VMA_NULL;
+ m_Moves.clear();
-uint32_t VmaBlockVector::ProcessDefragmentations(
- class VmaBlockVectorDefragmentationContext *pCtx,
- VmaDefragmentationPassMoveInfo* pMove, uint32_t maxMoves)
-{
- VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
-
- const uint32_t moveCount = VMA_MIN(uint32_t(pCtx->defragmentationMoves.size()) - pCtx->defragmentationMovesProcessed, maxMoves);
+ // Update stats
+ m_GlobalStats.allocationsMoved += m_PassStats.allocationsMoved;
+ m_GlobalStats.bytesFreed += m_PassStats.bytesFreed;
+ m_GlobalStats.bytesMoved += m_PassStats.bytesMoved;
+ m_GlobalStats.deviceMemoryBlocksFreed += m_PassStats.deviceMemoryBlocksFreed;
+ m_PassStats = { 0 };
- for(uint32_t i = 0; i < moveCount; ++ i)
+ // Move blocks with immovable allocations according to algorithm
+ if (immovableBlocks.size() > 0)
{
- VmaDefragmentationMove& move = pCtx->defragmentationMoves[pCtx->defragmentationMovesProcessed + i];
-
- pMove->allocation = move.hAllocation;
- pMove->memory = move.pDstBlock->GetDeviceMemory();
- pMove->offset = move.dstOffset;
-
- ++ pMove;
- }
-
- pCtx->defragmentationMovesProcessed += moveCount;
-
- return moveCount;
-}
-
-void VmaBlockVector::CommitDefragmentations(
- class VmaBlockVectorDefragmentationContext *pCtx,
- VmaDefragmentationStats* pStats)
-{
- VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
+ switch (m_Algorithm)
+ {
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:
+ {
+ if (m_AlgorithmState != VMA_NULL)
+ {
+ bool swapped = false;
+ // Move to the start of free blocks range
+ for (const FragmentedBlock& block : immovableBlocks)
+ {
+ StateExtensive& state = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[block.data];
+ if (state.operation != StateExtensive::Operation::Cleanup)
+ {
+ VmaBlockVector* vector = m_pBlockVectors[block.data];
+ VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
- for(uint32_t i = pCtx->defragmentationMovesCommitted; i < pCtx->defragmentationMovesProcessed; ++ i)
- {
- const VmaDefragmentationMove &move = pCtx->defragmentationMoves[i];
+ for (size_t i = 0, count = vector->GetBlockCount() - m_ImmovableBlockCount; i < count; ++i)
+ {
+ if (vector->GetBlock(i) == block.block)
+ {
+ VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[vector->GetBlockCount() - ++m_ImmovableBlockCount]);
+ if (state.firstFreeBlock != SIZE_MAX)
+ {
+ if (i + 1 < state.firstFreeBlock)
+ {
+ if (state.firstFreeBlock > 1)
+ VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[--state.firstFreeBlock]);
+ else
+ --state.firstFreeBlock;
+ }
+ }
+ swapped = true;
+ break;
+ }
+ }
+ }
+ }
+ if (swapped)
+ result = VK_INCOMPLETE;
+ break;
+ }
+ }
+ default:
+ {
+ // Move to the begining
+ for (const FragmentedBlock& block : immovableBlocks)
+ {
+ VmaBlockVector* vector = m_pBlockVectors[block.data];
+ VmaMutexLockWrite lock(vector->GetMutex(), vector->GetAllocator()->m_UseMutex);
- move.pSrcBlock->m_pMetadata->FreeAtOffset(move.srcOffset);
- move.hAllocation->ChangeBlockAllocation(m_hAllocator, move.pDstBlock, move.dstOffset);
+ for (size_t i = m_ImmovableBlockCount; i < vector->GetBlockCount(); ++i)
+ {
+ if (vector->GetBlock(i) == block.block)
+ {
+ VMA_SWAP(vector->m_Blocks[i], vector->m_Blocks[m_ImmovableBlockCount++]);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
}
- pCtx->defragmentationMovesCommitted = pCtx->defragmentationMovesProcessed;
- FreeEmptyBlocks(pStats);
-}
-
-size_t VmaBlockVector::CalcAllocationCount() const
-{
- size_t result = 0;
- for(size_t i = 0; i < m_Blocks.size(); ++i)
+ // Bulk-map destination blocks
+ for (const FragmentedBlock& block : mappedBlocks)
{
- result += m_Blocks[i]->m_pMetadata->GetAllocationCount();
+ VkResult res = block.block->Map(allocator, block.data, VMA_NULL);
+ VMA_ASSERT(res == VK_SUCCESS);
}
return result;
}
-bool VmaBlockVector::IsBufferImageGranularityConflictPossible() const
+bool VmaDefragmentationContext_T::ComputeDefragmentation(VmaBlockVector& vector, size_t index)
{
- if(m_BufferImageGranularity == 1)
- {
- return false;
- }
- VmaSuballocationType lastSuballocType = VMA_SUBALLOCATION_TYPE_FREE;
- for(size_t i = 0, count = m_Blocks.size(); i < count; ++i)
+ switch (m_Algorithm)
{
- VmaDeviceMemoryBlock* const pBlock = m_Blocks[i];
- VMA_ASSERT(m_Algorithm == 0);
- VmaBlockMetadata_Generic* const pMetadata = (VmaBlockMetadata_Generic*)pBlock->m_pMetadata;
- if(pMetadata->IsBufferImageGranularityConflictPossible(m_BufferImageGranularity, lastSuballocType))
- {
- return true;
- }
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT:
+ return ComputeDefragmentation_Fast(vector);
+ default:
+ VMA_ASSERT(0);
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_BALANCED_BIT:
+ return ComputeDefragmentation_Balanced(vector, index, true);
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FULL_BIT:
+ return ComputeDefragmentation_Full(vector);
+ case VMA_DEFRAGMENTATION_FLAG_ALGORITHM_EXTENSIVE_BIT:
+ return ComputeDefragmentation_Extensive(vector, index);
}
- return false;
}
-void VmaBlockVector::MakePoolAllocationsLost(
- uint32_t currentFrameIndex,
- size_t* pLostAllocationCount)
+VmaDefragmentationContext_T::MoveAllocationData VmaDefragmentationContext_T::GetMoveData(
+ VmaAllocHandle handle, VmaBlockMetadata* metadata)
{
- VmaMutexLockWrite lock(m_Mutex, m_hAllocator->m_UseMutex);
- size_t lostAllocationCount = 0;
- for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
- {
- VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pBlock);
- lostAllocationCount += pBlock->m_pMetadata->MakeAllocationsLost(currentFrameIndex, m_FrameInUseCount);
- }
- if(pLostAllocationCount != VMA_NULL)
- {
- *pLostAllocationCount = lostAllocationCount;
- }
-}
+ MoveAllocationData moveData;
+ moveData.move.srcAllocation = (VmaAllocation)metadata->GetAllocationUserData(handle);
+ moveData.size = moveData.move.srcAllocation->GetSize();
+ moveData.alignment = moveData.move.srcAllocation->GetAlignment();
+ moveData.type = moveData.move.srcAllocation->GetSuballocationType();
+ moveData.flags = 0;
-VkResult VmaBlockVector::CheckCorruption()
-{
- if(!IsCorruptionDetectionEnabled())
- {
- return VK_ERROR_FEATURE_NOT_PRESENT;
- }
+ if (moveData.move.srcAllocation->IsPersistentMap())
+ moveData.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ if (moveData.move.srcAllocation->IsMappingAllowed())
+ moveData.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
- VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
- for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
- {
- VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pBlock);
- VkResult res = pBlock->CheckCorruption(m_hAllocator);
- if(res != VK_SUCCESS)
- {
- return res;
- }
- }
- return VK_SUCCESS;
+ return moveData;
}
-void VmaBlockVector::AddStats(VmaStats* pStats)
+VmaDefragmentationContext_T::CounterStatus VmaDefragmentationContext_T::CheckCounters(VkDeviceSize bytes)
{
- const uint32_t memTypeIndex = m_MemoryTypeIndex;
- const uint32_t memHeapIndex = m_hAllocator->MemoryTypeIndexToHeapIndex(memTypeIndex);
-
- VmaMutexLockRead lock(m_Mutex, m_hAllocator->m_UseMutex);
-
- for(uint32_t blockIndex = 0; blockIndex < m_Blocks.size(); ++blockIndex)
+ // Ignore allocation if will exceed max size for copy
+ if (m_PassStats.bytesMoved + bytes > m_MaxPassBytes)
{
- const VmaDeviceMemoryBlock* const pBlock = m_Blocks[blockIndex];
- VMA_ASSERT(pBlock);
- VMA_HEAVY_ASSERT(pBlock->Validate());
- VmaStatInfo allocationStatInfo;
- pBlock->m_pMetadata->CalcAllocationStatInfo(allocationStatInfo);
- VmaAddStatInfo(pStats->total, allocationStatInfo);
- VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
- VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
+ if (++m_IgnoredAllocs < MAX_ALLOCS_TO_IGNORE)
+ return CounterStatus::Ignore;
+ else
+ return CounterStatus::End;
}
+ return CounterStatus::Pass;
}
-////////////////////////////////////////////////////////////////////////////////
-// VmaDefragmentationAlgorithm_Generic members definition
-
-VmaDefragmentationAlgorithm_Generic::VmaDefragmentationAlgorithm_Generic(
- VmaAllocator hAllocator,
- VmaBlockVector* pBlockVector,
- uint32_t currentFrameIndex,
- bool overlappingMoveSupported) :
- VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
- m_AllocationCount(0),
- m_AllAllocations(false),
- m_BytesMoved(0),
- m_AllocationsMoved(0),
- m_Blocks(VmaStlAllocator<BlockInfo*>(hAllocator->GetAllocationCallbacks()))
+bool VmaDefragmentationContext_T::IncrementCounters(VkDeviceSize bytes)
{
- // Create block info for each block.
- const size_t blockCount = m_pBlockVector->m_Blocks.size();
- for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ m_PassStats.bytesMoved += bytes;
+ // Early return when max found
+ if (++m_PassStats.allocationsMoved >= m_MaxPassAllocations || m_PassStats.bytesMoved >= m_MaxPassBytes)
{
- BlockInfo* pBlockInfo = vma_new(m_hAllocator, BlockInfo)(m_hAllocator->GetAllocationCallbacks());
- pBlockInfo->m_OriginalBlockIndex = blockIndex;
- pBlockInfo->m_pBlock = m_pBlockVector->m_Blocks[blockIndex];
- m_Blocks.push_back(pBlockInfo);
+ VMA_ASSERT(m_PassStats.allocationsMoved == m_MaxPassAllocations ||
+ m_PassStats.bytesMoved == m_MaxPassBytes && "Exceeded maximal pass threshold!");
+ return true;
}
-
- // Sort them by m_pBlock pointer value.
- VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockPointerLess());
+ return false;
}
-VmaDefragmentationAlgorithm_Generic::~VmaDefragmentationAlgorithm_Generic()
+bool VmaDefragmentationContext_T::ReallocWithinBlock(VmaBlockVector& vector, VmaDeviceMemoryBlock* block)
{
- for(size_t i = m_Blocks.size(); i--; )
- {
- vma_delete(m_hAllocator, m_Blocks[i]);
- }
-}
+ VmaBlockMetadata* metadata = block->m_pMetadata;
-void VmaDefragmentationAlgorithm_Generic::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
-{
- // Now as we are inside VmaBlockVector::m_Mutex, we can make final check if this allocation was not lost.
- if(hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST)
+ for (VmaAllocHandle handle = metadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = metadata->GetNextAllocation(handle))
{
- VmaDeviceMemoryBlock* pBlock = hAlloc->GetBlock();
- BlockInfoVector::iterator it = VmaBinaryFindFirstNotLess(m_Blocks.begin(), m_Blocks.end(), pBlock, BlockPointerLess());
- if(it != m_Blocks.end() && (*it)->m_pBlock == pBlock)
- {
- AllocationInfo allocInfo = AllocationInfo(hAlloc, pChanged);
- (*it)->m_Allocations.push_back(allocInfo);
- }
- else
+ MoveAllocationData moveData = GetMoveData(handle, metadata);
+ // Ignore newly created allocations by defragmentation algorithm
+ if (moveData.move.srcAllocation->GetUserData() == this)
+ continue;
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
{
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
VMA_ASSERT(0);
+ case CounterStatus::Pass:
+ break;
}
- ++m_AllocationCount;
- }
-}
-
-VkResult VmaDefragmentationAlgorithm_Generic::DefragmentRound(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- bool freeOldAllocations)
-{
- if(m_Blocks.empty())
- {
- return VK_SUCCESS;
- }
-
- // This is a choice based on research.
- // Option 1:
- uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT;
- // Option 2:
- //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT;
- // Option 3:
- //uint32_t strategy = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT;
-
- size_t srcBlockMinIndex = 0;
- // When FAST_ALGORITHM, move allocations from only last out of blocks that contain non-movable allocations.
- /*
- if(m_AlgorithmFlags & VMA_DEFRAGMENTATION_FAST_ALGORITHM_BIT)
- {
- const size_t blocksWithNonMovableCount = CalcBlocksWithNonMovableCount();
- if(blocksWithNonMovableCount > 0)
- {
- srcBlockMinIndex = blocksWithNonMovableCount - 1;
- }
- }
- */
-
- size_t srcBlockIndex = m_Blocks.size() - 1;
- size_t srcAllocIndex = SIZE_MAX;
- for(;;)
- {
- // 1. Find next allocation to move.
- // 1.1. Start from last to first m_Blocks - they are sorted from most "destination" to most "source".
- // 1.2. Then start from last to first m_Allocations.
- while(srcAllocIndex >= m_Blocks[srcBlockIndex]->m_Allocations.size())
- {
- if(m_Blocks[srcBlockIndex]->m_Allocations.empty())
- {
- // Finished: no more allocations to process.
- if(srcBlockIndex == srcBlockMinIndex)
- {
- return VK_SUCCESS;
- }
- else
- {
- --srcBlockIndex;
- srcAllocIndex = SIZE_MAX;
- }
- }
- else
- {
- srcAllocIndex = m_Blocks[srcBlockIndex]->m_Allocations.size() - 1;
- }
- }
-
- BlockInfo* pSrcBlockInfo = m_Blocks[srcBlockIndex];
- AllocationInfo& allocInfo = pSrcBlockInfo->m_Allocations[srcAllocIndex];
-
- const VkDeviceSize size = allocInfo.m_hAllocation->GetSize();
- const VkDeviceSize srcOffset = allocInfo.m_hAllocation->GetOffset();
- const VkDeviceSize alignment = allocInfo.m_hAllocation->GetAlignment();
- const VmaSuballocationType suballocType = allocInfo.m_hAllocation->GetSuballocationType();
-
- // 2. Try to find new place for this allocation in preceding or current block.
- for(size_t dstBlockIndex = 0; dstBlockIndex <= srcBlockIndex; ++dstBlockIndex)
+ VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();
+ if (offset != 0 && metadata->GetSumFreeSize() >= moveData.size)
{
- BlockInfo* pDstBlockInfo = m_Blocks[dstBlockIndex];
- VmaAllocationRequest dstAllocRequest;
- if(pDstBlockInfo->m_pBlock->m_pMetadata->CreateAllocationRequest(
- m_CurrentFrameIndex,
- m_pBlockVector->GetFrameInUseCount(),
- m_pBlockVector->GetBufferImageGranularity(),
- size,
- alignment,
- false, // upperAddress
- suballocType,
- false, // canMakeOtherLost
- strategy,
- &dstAllocRequest) &&
- MoveMakesSense(
- dstBlockIndex, dstAllocRequest.offset, srcBlockIndex, srcOffset))
+ VmaAllocationRequest request = {};
+ if (metadata->CreateAllocationRequest(
+ moveData.size,
+ moveData.alignment,
+ false,
+ moveData.type,
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
+ &request))
{
- VMA_ASSERT(dstAllocRequest.itemsToMakeLostCount == 0);
-
- // Reached limit on number of allocations or bytes to move.
- if((m_AllocationsMoved + 1 > maxAllocationsToMove) ||
- (m_BytesMoved + size > maxBytesToMove))
+ if (metadata->GetAllocationOffset(request.allocHandle) < offset)
{
- return VK_SUCCESS;
- }
-
- VmaDefragmentationMove move = {};
- move.srcBlockIndex = pSrcBlockInfo->m_OriginalBlockIndex;
- move.dstBlockIndex = pDstBlockInfo->m_OriginalBlockIndex;
- move.srcOffset = srcOffset;
- move.dstOffset = dstAllocRequest.offset;
- move.size = size;
- move.hAllocation = allocInfo.m_hAllocation;
- move.pSrcBlock = pSrcBlockInfo->m_pBlock;
- move.pDstBlock = pDstBlockInfo->m_pBlock;
-
- moves.push_back(move);
-
- pDstBlockInfo->m_pBlock->m_pMetadata->Alloc(
- dstAllocRequest,
- suballocType,
- size,
- allocInfo.m_hAllocation);
-
- if(freeOldAllocations)
- {
- pSrcBlockInfo->m_pBlock->m_pMetadata->FreeAtOffset(srcOffset);
- allocInfo.m_hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlockInfo->m_pBlock, dstAllocRequest.offset);
- }
-
- if(allocInfo.m_pChanged != VMA_NULL)
- {
- *allocInfo.m_pChanged = VK_TRUE;
+ if (vector.CommitAllocationRequest(
+ request,
+ block,
+ moveData.alignment,
+ moveData.flags,
+ this,
+ moveData.type,
+ &moveData.move.dstTmpAllocation) == VK_SUCCESS)
+ {
+ m_Moves.push_back(moveData.move);
+ if (IncrementCounters(moveData.size))
+ return true;
+ }
}
-
- ++m_AllocationsMoved;
- m_BytesMoved += size;
-
- VmaVectorRemove(pSrcBlockInfo->m_Allocations, srcAllocIndex);
-
- break;
- }
- }
-
- // If not processed, this allocInfo remains in pBlockInfo->m_Allocations for next round.
-
- if(srcAllocIndex > 0)
- {
- --srcAllocIndex;
- }
- else
- {
- if(srcBlockIndex > 0)
- {
- --srcBlockIndex;
- srcAllocIndex = SIZE_MAX;
- }
- else
- {
- return VK_SUCCESS;
}
}
}
+ return false;
}
-size_t VmaDefragmentationAlgorithm_Generic::CalcBlocksWithNonMovableCount() const
+bool VmaDefragmentationContext_T::AllocInOtherBlock(size_t start, size_t end, MoveAllocationData& data, VmaBlockVector& vector)
{
- size_t result = 0;
- for(size_t i = 0; i < m_Blocks.size(); ++i)
+ for (; start < end; ++start)
{
- if(m_Blocks[i]->m_HasNonMovableAllocations)
+ VmaDeviceMemoryBlock* dstBlock = vector.GetBlock(start);
+ if (dstBlock->m_pMetadata->GetSumFreeSize() >= data.size)
{
- ++result;
+ if (vector.AllocateFromBlock(dstBlock,
+ data.size,
+ data.alignment,
+ data.flags,
+ this,
+ data.type,
+ 0,
+ &data.move.dstTmpAllocation) == VK_SUCCESS)
+ {
+ m_Moves.push_back(data.move);
+ if (IncrementCounters(data.size))
+ return true;
+ break;
+ }
}
}
- return result;
+ return false;
}
-VkResult VmaDefragmentationAlgorithm_Generic::Defragment(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- VmaDefragmentationFlags flags)
+bool VmaDefragmentationContext_T::ComputeDefragmentation_Fast(VmaBlockVector& vector)
{
- if(!m_AllAllocations && m_AllocationCount == 0)
- {
- return VK_SUCCESS;
- }
+ // Move only between blocks
- const size_t blockCount = m_Blocks.size();
- for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ // Go through allocations in last blocks and try to fit them inside first ones
+ for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)
{
- BlockInfo* pBlockInfo = m_Blocks[blockIndex];
+ VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata;
- if(m_AllAllocations)
+ for (VmaAllocHandle handle = metadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = metadata->GetNextAllocation(handle))
{
- VmaBlockMetadata_Generic* pMetadata = (VmaBlockMetadata_Generic*)pBlockInfo->m_pBlock->m_pMetadata;
- for(VmaSuballocationList::const_iterator it = pMetadata->m_Suballocations.begin();
- it != pMetadata->m_Suballocations.end();
- ++it)
+ MoveAllocationData moveData = GetMoveData(handle, metadata);
+ // Ignore newly created allocations by defragmentation algorithm
+ if (moveData.move.srcAllocation->GetUserData() == this)
+ continue;
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
{
- if(it->type != VMA_SUBALLOCATION_TYPE_FREE)
- {
- AllocationInfo allocInfo = AllocationInfo(it->hAllocation, VMA_NULL);
- pBlockInfo->m_Allocations.push_back(allocInfo);
- }
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
+ VMA_ASSERT(0);
+ case CounterStatus::Pass:
+ break;
}
- }
-
- pBlockInfo->CalcHasNonMovableAllocations();
-
- // This is a choice based on research.
- // Option 1:
- pBlockInfo->SortAllocationsByOffsetDescending();
- // Option 2:
- //pBlockInfo->SortAllocationsBySizeDescending();
- }
-
- // Sort m_Blocks this time by the main criterium, from most "destination" to most "source" blocks.
- VMA_SORT(m_Blocks.begin(), m_Blocks.end(), BlockInfoCompareMoveDestination());
-
- // This is a choice based on research.
- const uint32_t roundCount = 2;
- // Execute defragmentation rounds (the main part).
- VkResult result = VK_SUCCESS;
- for(uint32_t round = 0; (round < roundCount) && (result == VK_SUCCESS); ++round)
- {
- result = DefragmentRound(moves, maxBytesToMove, maxAllocationsToMove, !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL));
- }
-
- return result;
-}
-
-bool VmaDefragmentationAlgorithm_Generic::MoveMakesSense(
- size_t dstBlockIndex, VkDeviceSize dstOffset,
- size_t srcBlockIndex, VkDeviceSize srcOffset)
-{
- if(dstBlockIndex < srcBlockIndex)
- {
- return true;
- }
- if(dstBlockIndex > srcBlockIndex)
- {
- return false;
- }
- if(dstOffset < srcOffset)
- {
- return true;
+ // Check all previous blocks for free space
+ if (AllocInOtherBlock(0, i, moveData, vector))
+ return true;
+ }
}
return false;
}
-////////////////////////////////////////////////////////////////////////////////
-// VmaDefragmentationAlgorithm_Fast
-
-VmaDefragmentationAlgorithm_Fast::VmaDefragmentationAlgorithm_Fast(
- VmaAllocator hAllocator,
- VmaBlockVector* pBlockVector,
- uint32_t currentFrameIndex,
- bool overlappingMoveSupported) :
- VmaDefragmentationAlgorithm(hAllocator, pBlockVector, currentFrameIndex),
- m_OverlappingMoveSupported(overlappingMoveSupported),
- m_AllocationCount(0),
- m_AllAllocations(false),
- m_BytesMoved(0),
- m_AllocationsMoved(0),
- m_BlockInfos(VmaStlAllocator<BlockInfo>(hAllocator->GetAllocationCallbacks()))
-{
- VMA_ASSERT(VMA_DEBUG_MARGIN == 0);
-
-}
-
-VmaDefragmentationAlgorithm_Fast::~VmaDefragmentationAlgorithm_Fast()
+bool VmaDefragmentationContext_T::ComputeDefragmentation_Balanced(VmaBlockVector& vector, size_t index, bool update)
{
-}
-
-VkResult VmaDefragmentationAlgorithm_Fast::Defragment(
- VmaVector< VmaDefragmentationMove, VmaStlAllocator<VmaDefragmentationMove> >& moves,
- VkDeviceSize maxBytesToMove,
- uint32_t maxAllocationsToMove,
- VmaDefragmentationFlags flags)
-{
- VMA_ASSERT(m_AllAllocations || m_pBlockVector->CalcAllocationCount() == m_AllocationCount);
-
- const size_t blockCount = m_pBlockVector->GetBlockCount();
- if(blockCount == 0 || maxBytesToMove == 0 || maxAllocationsToMove == 0)
- {
- return VK_SUCCESS;
- }
-
- PreprocessMetadata();
+ // Go over every allocation and try to fit it in previous blocks at lowest offsets,
+ // if not possible: realloc within single block to minimize offset (exclude offset == 0),
+ // but only if there are noticable gaps between them (some heuristic, ex. average size of allocation in block)
+ VMA_ASSERT(m_AlgorithmState != VMA_NULL);
- // Sort blocks in order from most destination.
+ StateBalanced& vectorState = reinterpret_cast<StateBalanced*>(m_AlgorithmState)[index];
+ if (update && vectorState.avgAllocSize == UINT64_MAX)
+ UpdateVectorStatistics(vector, vectorState);
- m_BlockInfos.resize(blockCount);
- for(size_t i = 0; i < blockCount; ++i)
+ const size_t startMoveCount = m_Moves.size();
+ VkDeviceSize minimalFreeRegion = vectorState.avgFreeSize / 2;
+ for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)
{
- m_BlockInfos[i].origBlockIndex = i;
- }
-
- VMA_SORT(m_BlockInfos.begin(), m_BlockInfos.end(), [this](const BlockInfo& lhs, const BlockInfo& rhs) -> bool {
- return m_pBlockVector->GetBlock(lhs.origBlockIndex)->m_pMetadata->GetSumFreeSize() <
- m_pBlockVector->GetBlock(rhs.origBlockIndex)->m_pMetadata->GetSumFreeSize();
- });
-
- // THE MAIN ALGORITHM
-
- FreeSpaceDatabase freeSpaceDb;
+ VmaDeviceMemoryBlock* block = vector.GetBlock(i);
+ VmaBlockMetadata* metadata = block->m_pMetadata;
+ VkDeviceSize prevFreeRegionSize = 0;
- size_t dstBlockInfoIndex = 0;
- size_t dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
- VmaDeviceMemoryBlock* pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
- VmaBlockMetadata_Generic* pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
- VkDeviceSize dstBlockSize = pDstMetadata->GetSize();
- VkDeviceSize dstOffset = 0;
-
- bool end = false;
- for(size_t srcBlockInfoIndex = 0; !end && srcBlockInfoIndex < blockCount; ++srcBlockInfoIndex)
- {
- const size_t srcOrigBlockIndex = m_BlockInfos[srcBlockInfoIndex].origBlockIndex;
- VmaDeviceMemoryBlock* const pSrcBlock = m_pBlockVector->GetBlock(srcOrigBlockIndex);
- VmaBlockMetadata_Generic* const pSrcMetadata = (VmaBlockMetadata_Generic*)pSrcBlock->m_pMetadata;
- for(VmaSuballocationList::iterator srcSuballocIt = pSrcMetadata->m_Suballocations.begin();
- !end && srcSuballocIt != pSrcMetadata->m_Suballocations.end(); )
+ for (VmaAllocHandle handle = metadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = metadata->GetNextAllocation(handle))
{
- VmaAllocation_T* const pAlloc = srcSuballocIt->hAllocation;
- const VkDeviceSize srcAllocAlignment = pAlloc->GetAlignment();
- const VkDeviceSize srcAllocSize = srcSuballocIt->size;
- if(m_AllocationsMoved == maxAllocationsToMove ||
- m_BytesMoved + srcAllocSize > maxBytesToMove)
+ MoveAllocationData moveData = GetMoveData(handle, metadata);
+ // Ignore newly created allocations by defragmentation algorithm
+ if (moveData.move.srcAllocation->GetUserData() == this)
+ continue;
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
{
- end = true;
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
+ VMA_ASSERT(0);
+ case CounterStatus::Pass:
break;
}
- const VkDeviceSize srcAllocOffset = srcSuballocIt->offset;
-
- VmaDefragmentationMove move = {};
- // Try to place it in one of free spaces from the database.
- size_t freeSpaceInfoIndex;
- VkDeviceSize dstAllocOffset;
- if(freeSpaceDb.Fetch(srcAllocAlignment, srcAllocSize,
- freeSpaceInfoIndex, dstAllocOffset))
- {
- size_t freeSpaceOrigBlockIndex = m_BlockInfos[freeSpaceInfoIndex].origBlockIndex;
- VmaDeviceMemoryBlock* pFreeSpaceBlock = m_pBlockVector->GetBlock(freeSpaceOrigBlockIndex);
- VmaBlockMetadata_Generic* pFreeSpaceMetadata = (VmaBlockMetadata_Generic*)pFreeSpaceBlock->m_pMetadata;
-
- // Same block
- if(freeSpaceInfoIndex == srcBlockInfoIndex)
- {
- VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
-
- // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
-
- VmaSuballocation suballoc = *srcSuballocIt;
- suballoc.offset = dstAllocOffset;
- suballoc.hAllocation->ChangeOffset(dstAllocOffset);
- m_BytesMoved += srcAllocSize;
- ++m_AllocationsMoved;
- VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
- ++nextSuballocIt;
- pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
- srcSuballocIt = nextSuballocIt;
-
- InsertSuballoc(pFreeSpaceMetadata, suballoc);
-
- move.srcBlockIndex = srcOrigBlockIndex;
- move.dstBlockIndex = freeSpaceOrigBlockIndex;
- move.srcOffset = srcAllocOffset;
- move.dstOffset = dstAllocOffset;
- move.size = srcAllocSize;
-
- moves.push_back(move);
- }
- // Different block
- else
- {
- // MOVE OPTION 2: Move the allocation to a different block.
-
- VMA_ASSERT(freeSpaceInfoIndex < srcBlockInfoIndex);
-
- VmaSuballocation suballoc = *srcSuballocIt;
- suballoc.offset = dstAllocOffset;
- suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pFreeSpaceBlock, dstAllocOffset);
- m_BytesMoved += srcAllocSize;
- ++m_AllocationsMoved;
-
- VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
- ++nextSuballocIt;
- pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
- srcSuballocIt = nextSuballocIt;
-
- InsertSuballoc(pFreeSpaceMetadata, suballoc);
-
- move.srcBlockIndex = srcOrigBlockIndex;
- move.dstBlockIndex = freeSpaceOrigBlockIndex;
- move.srcOffset = srcAllocOffset;
- move.dstOffset = dstAllocOffset;
- move.size = srcAllocSize;
+ // Check all previous blocks for free space
+ const size_t prevMoveCount = m_Moves.size();
+ if (AllocInOtherBlock(0, i, moveData, vector))
+ return true;
- moves.push_back(move);
- }
- }
- else
+ VkDeviceSize nextFreeRegionSize = metadata->GetNextFreeRegionSize(handle);
+ // If no room found then realloc within block for lower offset
+ VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();
+ if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size)
{
- dstAllocOffset = VmaAlignUp(dstOffset, srcAllocAlignment);
-
- // If the allocation doesn't fit before the end of dstBlock, forward to next block.
- while(dstBlockInfoIndex < srcBlockInfoIndex &&
- dstAllocOffset + srcAllocSize > dstBlockSize)
+ // Check if realloc will make sense
+ if (prevFreeRegionSize >= minimalFreeRegion ||
+ nextFreeRegionSize >= minimalFreeRegion ||
+ moveData.size <= vectorState.avgFreeSize ||
+ moveData.size <= vectorState.avgAllocSize)
{
- // But before that, register remaining free space at the end of dst block.
- freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, dstBlockSize - dstOffset);
-
- ++dstBlockInfoIndex;
- dstOrigBlockIndex = m_BlockInfos[dstBlockInfoIndex].origBlockIndex;
- pDstBlock = m_pBlockVector->GetBlock(dstOrigBlockIndex);
- pDstMetadata = (VmaBlockMetadata_Generic*)pDstBlock->m_pMetadata;
- dstBlockSize = pDstMetadata->GetSize();
- dstOffset = 0;
- dstAllocOffset = 0;
- }
-
- // Same block
- if(dstBlockInfoIndex == srcBlockInfoIndex)
- {
- VMA_ASSERT(dstAllocOffset <= srcAllocOffset);
-
- const bool overlap = dstAllocOffset + srcAllocSize > srcAllocOffset;
-
- bool skipOver = overlap;
- if(overlap && m_OverlappingMoveSupported && dstAllocOffset < srcAllocOffset)
+ VmaAllocationRequest request = {};
+ if (metadata->CreateAllocationRequest(
+ moveData.size,
+ moveData.alignment,
+ false,
+ moveData.type,
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
+ &request))
{
- // If destination and source place overlap, skip if it would move it
- // by only < 1/64 of its size.
- skipOver = (srcAllocOffset - dstAllocOffset) * 64 < srcAllocSize;
- }
-
- if(skipOver)
- {
- freeSpaceDb.Register(dstBlockInfoIndex, dstOffset, srcAllocOffset - dstOffset);
-
- dstOffset = srcAllocOffset + srcAllocSize;
- ++srcSuballocIt;
- }
- // MOVE OPTION 1: Move the allocation inside the same block by decreasing offset.
- else
- {
- srcSuballocIt->offset = dstAllocOffset;
- srcSuballocIt->hAllocation->ChangeOffset(dstAllocOffset);
- dstOffset = dstAllocOffset + srcAllocSize;
- m_BytesMoved += srcAllocSize;
- ++m_AllocationsMoved;
- ++srcSuballocIt;
-
- move.srcBlockIndex = srcOrigBlockIndex;
- move.dstBlockIndex = dstOrigBlockIndex;
- move.srcOffset = srcAllocOffset;
- move.dstOffset = dstAllocOffset;
- move.size = srcAllocSize;
-
- moves.push_back(move);
+ if (metadata->GetAllocationOffset(request.allocHandle) < offset)
+ {
+ if (vector.CommitAllocationRequest(
+ request,
+ block,
+ moveData.alignment,
+ moveData.flags,
+ this,
+ moveData.type,
+ &moveData.move.dstTmpAllocation) == VK_SUCCESS)
+ {
+ m_Moves.push_back(moveData.move);
+ if (IncrementCounters(moveData.size))
+ return true;
+ }
+ }
}
}
- // Different block
- else
- {
- // MOVE OPTION 2: Move the allocation to a different block.
-
- VMA_ASSERT(dstBlockInfoIndex < srcBlockInfoIndex);
- VMA_ASSERT(dstAllocOffset + srcAllocSize <= dstBlockSize);
-
- VmaSuballocation suballoc = *srcSuballocIt;
- suballoc.offset = dstAllocOffset;
- suballoc.hAllocation->ChangeBlockAllocation(m_hAllocator, pDstBlock, dstAllocOffset);
- dstOffset = dstAllocOffset + srcAllocSize;
- m_BytesMoved += srcAllocSize;
- ++m_AllocationsMoved;
-
- VmaSuballocationList::iterator nextSuballocIt = srcSuballocIt;
- ++nextSuballocIt;
- pSrcMetadata->m_Suballocations.erase(srcSuballocIt);
- srcSuballocIt = nextSuballocIt;
-
- pDstMetadata->m_Suballocations.push_back(suballoc);
-
- move.srcBlockIndex = srcOrigBlockIndex;
- move.dstBlockIndex = dstOrigBlockIndex;
- move.srcOffset = srcAllocOffset;
- move.dstOffset = dstAllocOffset;
- move.size = srcAllocSize;
-
- moves.push_back(move);
- }
}
+ prevFreeRegionSize = nextFreeRegionSize;
}
}
- m_BlockInfos.clear();
-
- PostprocessMetadata();
-
- return VK_SUCCESS;
-}
-
-void VmaDefragmentationAlgorithm_Fast::PreprocessMetadata()
-{
- const size_t blockCount = m_pBlockVector->GetBlockCount();
- for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ // No moves perfomed, update statistics to current vector state
+ if (startMoveCount == m_Moves.size() && !update)
{
- VmaBlockMetadata_Generic* const pMetadata =
- (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
- pMetadata->m_FreeCount = 0;
- pMetadata->m_SumFreeSize = pMetadata->GetSize();
- pMetadata->m_FreeSuballocationsBySize.clear();
- for(VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
- it != pMetadata->m_Suballocations.end(); )
- {
- if(it->type == VMA_SUBALLOCATION_TYPE_FREE)
- {
- VmaSuballocationList::iterator nextIt = it;
- ++nextIt;
- pMetadata->m_Suballocations.erase(it);
- it = nextIt;
- }
- else
- {
- ++it;
- }
- }
+ vectorState.avgAllocSize = UINT64_MAX;
+ return ComputeDefragmentation_Balanced(vector, index, false);
}
+ return false;
}
-void VmaDefragmentationAlgorithm_Fast::PostprocessMetadata()
+bool VmaDefragmentationContext_T::ComputeDefragmentation_Full(VmaBlockVector& vector)
{
- const size_t blockCount = m_pBlockVector->GetBlockCount();
- for(size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ // Go over every allocation and try to fit it in previous blocks at lowest offsets,
+ // if not possible: realloc within single block to minimize offset (exclude offset == 0)
+
+ for (size_t i = vector.GetBlockCount() - 1; i > m_ImmovableBlockCount; --i)
{
- VmaBlockMetadata_Generic* const pMetadata =
- (VmaBlockMetadata_Generic*)m_pBlockVector->GetBlock(blockIndex)->m_pMetadata;
- const VkDeviceSize blockSize = pMetadata->GetSize();
+ VmaDeviceMemoryBlock* block = vector.GetBlock(i);
+ VmaBlockMetadata* metadata = block->m_pMetadata;
- // No allocations in this block - entire area is free.
- if(pMetadata->m_Suballocations.empty())
- {
- pMetadata->m_FreeCount = 1;
- //pMetadata->m_SumFreeSize is already set to blockSize.
- VmaSuballocation suballoc = {
- 0, // offset
- blockSize, // size
- VMA_NULL, // hAllocation
- VMA_SUBALLOCATION_TYPE_FREE };
- pMetadata->m_Suballocations.push_back(suballoc);
- pMetadata->RegisterFreeSuballocation(pMetadata->m_Suballocations.begin());
- }
- // There are some allocations in this block.
- else
+ for (VmaAllocHandle handle = metadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = metadata->GetNextAllocation(handle))
{
- VkDeviceSize offset = 0;
- VmaSuballocationList::iterator it;
- for(it = pMetadata->m_Suballocations.begin();
- it != pMetadata->m_Suballocations.end();
- ++it)
+ MoveAllocationData moveData = GetMoveData(handle, metadata);
+ // Ignore newly created allocations by defragmentation algorithm
+ if (moveData.move.srcAllocation->GetUserData() == this)
+ continue;
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
{
- VMA_ASSERT(it->type != VMA_SUBALLOCATION_TYPE_FREE);
- VMA_ASSERT(it->offset >= offset);
-
- // Need to insert preceding free space.
- if(it->offset > offset)
- {
- ++pMetadata->m_FreeCount;
- const VkDeviceSize freeSize = it->offset - offset;
- VmaSuballocation suballoc = {
- offset, // offset
- freeSize, // size
- VMA_NULL, // hAllocation
- VMA_SUBALLOCATION_TYPE_FREE };
- VmaSuballocationList::iterator precedingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
- if(freeSize >= VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
- {
- pMetadata->m_FreeSuballocationsBySize.push_back(precedingFreeIt);
- }
- }
-
- pMetadata->m_SumFreeSize -= it->size;
- offset = it->offset + it->size;
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
+ VMA_ASSERT(0);
+ case CounterStatus::Pass:
+ break;
}
- // Need to insert trailing free space.
- if(offset < blockSize)
+ // Check all previous blocks for free space
+ const size_t prevMoveCount = m_Moves.size();
+ if (AllocInOtherBlock(0, i, moveData, vector))
+ return true;
+
+ // If no room found then realloc within block for lower offset
+ VkDeviceSize offset = moveData.move.srcAllocation->GetOffset();
+ if (prevMoveCount == m_Moves.size() && offset != 0 && metadata->GetSumFreeSize() >= moveData.size)
{
- ++pMetadata->m_FreeCount;
- const VkDeviceSize freeSize = blockSize - offset;
- VmaSuballocation suballoc = {
- offset, // offset
- freeSize, // size
- VMA_NULL, // hAllocation
- VMA_SUBALLOCATION_TYPE_FREE };
- VMA_ASSERT(it == pMetadata->m_Suballocations.end());
- VmaSuballocationList::iterator trailingFreeIt = pMetadata->m_Suballocations.insert(it, suballoc);
- if(freeSize > VMA_MIN_FREE_SUBALLOCATION_SIZE_TO_REGISTER)
+ VmaAllocationRequest request = {};
+ if (metadata->CreateAllocationRequest(
+ moveData.size,
+ moveData.alignment,
+ false,
+ moveData.type,
+ VMA_ALLOCATION_CREATE_STRATEGY_MIN_OFFSET_BIT,
+ &request))
{
- pMetadata->m_FreeSuballocationsBySize.push_back(trailingFreeIt);
+ if (metadata->GetAllocationOffset(request.allocHandle) < offset)
+ {
+ if (vector.CommitAllocationRequest(
+ request,
+ block,
+ moveData.alignment,
+ moveData.flags,
+ this,
+ moveData.type,
+ &moveData.move.dstTmpAllocation) == VK_SUCCESS)
+ {
+ m_Moves.push_back(moveData.move);
+ if (IncrementCounters(moveData.size))
+ return true;
+ }
+ }
}
}
-
- VMA_SORT(
- pMetadata->m_FreeSuballocationsBySize.begin(),
- pMetadata->m_FreeSuballocationsBySize.end(),
- VmaSuballocationItemSizeLess());
}
-
- VMA_HEAVY_ASSERT(pMetadata->Validate());
}
+ return false;
}
-void VmaDefragmentationAlgorithm_Fast::InsertSuballoc(VmaBlockMetadata_Generic* pMetadata, const VmaSuballocation& suballoc)
-{
- // TODO: Optimize somehow. Remember iterator instead of searching for it linearly.
- VmaSuballocationList::iterator it = pMetadata->m_Suballocations.begin();
- while(it != pMetadata->m_Suballocations.end())
- {
- if(it->offset < suballoc.offset)
- {
- ++it;
- }
- }
- pMetadata->m_Suballocations.insert(it, suballoc);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaBlockVectorDefragmentationContext
-
-VmaBlockVectorDefragmentationContext::VmaBlockVectorDefragmentationContext(
- VmaAllocator hAllocator,
- VmaPool hCustomPool,
- VmaBlockVector* pBlockVector,
- uint32_t currFrameIndex) :
- res(VK_SUCCESS),
- mutexLocked(false),
- blockContexts(VmaStlAllocator<VmaBlockDefragmentationContext>(hAllocator->GetAllocationCallbacks())),
- defragmentationMoves(VmaStlAllocator<VmaDefragmentationMove>(hAllocator->GetAllocationCallbacks())),
- defragmentationMovesProcessed(0),
- defragmentationMovesCommitted(0),
- hasDefragmentationPlan(0),
- m_hAllocator(hAllocator),
- m_hCustomPool(hCustomPool),
- m_pBlockVector(pBlockVector),
- m_CurrFrameIndex(currFrameIndex),
- m_pAlgorithm(VMA_NULL),
- m_Allocations(VmaStlAllocator<AllocInfo>(hAllocator->GetAllocationCallbacks())),
- m_AllAllocations(false)
-{
-}
-
-VmaBlockVectorDefragmentationContext::~VmaBlockVectorDefragmentationContext()
+bool VmaDefragmentationContext_T::ComputeDefragmentation_Extensive(VmaBlockVector& vector, size_t index)
{
- vma_delete(m_hAllocator, m_pAlgorithm);
-}
+ // First free single block, then populate it to the brim, then free another block, and so on
-void VmaBlockVectorDefragmentationContext::AddAllocation(VmaAllocation hAlloc, VkBool32* pChanged)
-{
- AllocInfo info = { hAlloc, pChanged };
- m_Allocations.push_back(info);
-}
+ // Fallback to previous algorithm since without granularity conflicts it can achieve max packing
+ if (vector.m_BufferImageGranularity == 1)
+ return ComputeDefragmentation_Full(vector);
-void VmaBlockVectorDefragmentationContext::Begin(bool overlappingMoveSupported, VmaDefragmentationFlags flags)
-{
- const bool allAllocations = m_AllAllocations ||
- m_Allocations.size() == m_pBlockVector->CalcAllocationCount();
+ VMA_ASSERT(m_AlgorithmState != VMA_NULL);
- /********************************
- HERE IS THE CHOICE OF DEFRAGMENTATION ALGORITHM.
- ********************************/
+ StateExtensive& vectorState = reinterpret_cast<StateExtensive*>(m_AlgorithmState)[index];
- /*
- Fast algorithm is supported only when certain criteria are met:
- - VMA_DEBUG_MARGIN is 0.
- - All allocations in this block vector are moveable.
- - There is no possibility of image/buffer granularity conflict.
- - The defragmentation is not incremental
- */
- if(VMA_DEBUG_MARGIN == 0 &&
- allAllocations &&
- !m_pBlockVector->IsBufferImageGranularityConflictPossible() &&
- !(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL))
- {
- m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Fast)(
- m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
- }
- else
+ bool texturePresent = false, bufferPresent = false, otherPresent = false;
+ switch (vectorState.operation)
{
- m_pAlgorithm = vma_new(m_hAllocator, VmaDefragmentationAlgorithm_Generic)(
- m_hAllocator, m_pBlockVector, m_CurrFrameIndex, overlappingMoveSupported);
- }
-
- if(allAllocations)
- {
- m_pAlgorithm->AddAll();
- }
- else
+ case StateExtensive::Operation::Done: // Vector defragmented
+ return false;
+ case StateExtensive::Operation::FindFreeBlockBuffer:
+ case StateExtensive::Operation::FindFreeBlockTexture:
+ case StateExtensive::Operation::FindFreeBlockAll:
{
- for(size_t i = 0, count = m_Allocations.size(); i < count; ++i)
+ // No more blocks to free, just perform fast realloc and move to cleanup
+ if (vectorState.firstFreeBlock == 0)
{
- m_pAlgorithm->AddAllocation(m_Allocations[i].hAlloc, m_Allocations[i].pChanged);
+ vectorState.operation = StateExtensive::Operation::Cleanup;
+ return ComputeDefragmentation_Fast(vector);
}
- }
-}
-////////////////////////////////////////////////////////////////////////////////
-// VmaDefragmentationContext
+ // No free blocks, have to clear last one
+ size_t last = (vectorState.firstFreeBlock == SIZE_MAX ? vector.GetBlockCount() : vectorState.firstFreeBlock) - 1;
+ VmaBlockMetadata* freeMetadata = vector.GetBlock(last)->m_pMetadata;
-VmaDefragmentationContext_T::VmaDefragmentationContext_T(
- VmaAllocator hAllocator,
- uint32_t currFrameIndex,
- uint32_t flags,
- VmaDefragmentationStats* pStats) :
- m_hAllocator(hAllocator),
- m_CurrFrameIndex(currFrameIndex),
- m_Flags(flags),
- m_pStats(pStats),
- m_CustomPoolContexts(VmaStlAllocator<VmaBlockVectorDefragmentationContext*>(hAllocator->GetAllocationCallbacks()))
-{
- memset(m_DefaultPoolContexts, 0, sizeof(m_DefaultPoolContexts));
-}
-
-VmaDefragmentationContext_T::~VmaDefragmentationContext_T()
-{
- for(size_t i = m_CustomPoolContexts.size(); i--; )
- {
- VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[i];
- pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);
- vma_delete(m_hAllocator, pBlockVectorCtx);
- }
- for(size_t i = m_hAllocator->m_MemProps.memoryTypeCount; i--; )
- {
- VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[i];
- if(pBlockVectorCtx)
- {
- pBlockVectorCtx->GetBlockVector()->DefragmentationEnd(pBlockVectorCtx, m_Flags, m_pStats);
- vma_delete(m_hAllocator, pBlockVectorCtx);
- }
- }
-}
-
-void VmaDefragmentationContext_T::AddPools(uint32_t poolCount, const VmaPool* pPools)
-{
- for(uint32_t poolIndex = 0; poolIndex < poolCount; ++poolIndex)
- {
- VmaPool pool = pPools[poolIndex];
- VMA_ASSERT(pool);
- // Pools with algorithm other than default are not defragmented.
- if(pool->m_BlockVector.GetAlgorithm() == 0)
+ const size_t prevMoveCount = m_Moves.size();
+ for (VmaAllocHandle handle = freeMetadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = freeMetadata->GetNextAllocation(handle))
{
- VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
-
- for(size_t i = m_CustomPoolContexts.size(); i--; )
+ MoveAllocationData moveData = GetMoveData(handle, freeMetadata);
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
{
- if(m_CustomPoolContexts[i]->GetCustomPool() == pool)
- {
- pBlockVectorDefragCtx = m_CustomPoolContexts[i];
- break;
- }
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
+ VMA_ASSERT(0);
+ case CounterStatus::Pass:
+ break;
}
- if(!pBlockVectorDefragCtx)
+ // Check all previous blocks for free space
+ if (AllocInOtherBlock(0, last, moveData, vector))
{
- pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
- m_hAllocator,
- pool,
- &pool->m_BlockVector,
- m_CurrFrameIndex);
- m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
+ // Full clear performed already
+ if (prevMoveCount != m_Moves.size() && freeMetadata->GetNextAllocation(handle) == VK_NULL_HANDLE)
+ reinterpret_cast<size_t*>(m_AlgorithmState)[index] = last;
+ return true;
}
-
- pBlockVectorDefragCtx->AddAll();
}
- }
-}
-void VmaDefragmentationContext_T::AddAllocations(
- uint32_t allocationCount,
- const VmaAllocation* pAllocations,
- VkBool32* pAllocationsChanged)
-{
- // Dispatch pAllocations among defragmentators. Create them when necessary.
- for(uint32_t allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
- {
- const VmaAllocation hAlloc = pAllocations[allocIndex];
- VMA_ASSERT(hAlloc);
- // DedicatedAlloc cannot be defragmented.
- if((hAlloc->GetType() == VmaAllocation_T::ALLOCATION_TYPE_BLOCK) &&
- // Lost allocation cannot be defragmented.
- (hAlloc->GetLastUseFrameIndex() != VMA_FRAME_INDEX_LOST))
+ if (prevMoveCount == m_Moves.size())
{
- VmaBlockVectorDefragmentationContext* pBlockVectorDefragCtx = VMA_NULL;
-
- const VmaPool hAllocPool = hAlloc->GetBlock()->GetParentPool();
- // This allocation belongs to custom pool.
- if(hAllocPool != VK_NULL_HANDLE)
+ // Cannot perform full clear, have to move data in other blocks around
+ if (last != 0)
{
- // Pools with algorithm other than default are not defragmented.
- if(hAllocPool->m_BlockVector.GetAlgorithm() == 0)
+ for (size_t i = last - 1; i; --i)
{
- for(size_t i = m_CustomPoolContexts.size(); i--; )
- {
- if(m_CustomPoolContexts[i]->GetCustomPool() == hAllocPool)
- {
- pBlockVectorDefragCtx = m_CustomPoolContexts[i];
- break;
- }
- }
- if(!pBlockVectorDefragCtx)
- {
- pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
- m_hAllocator,
- hAllocPool,
- &hAllocPool->m_BlockVector,
- m_CurrFrameIndex);
- m_CustomPoolContexts.push_back(pBlockVectorDefragCtx);
- }
- }
- }
- // This allocation belongs to default pool.
- else
- {
- const uint32_t memTypeIndex = hAlloc->GetMemoryTypeIndex();
- pBlockVectorDefragCtx = m_DefaultPoolContexts[memTypeIndex];
- if(!pBlockVectorDefragCtx)
- {
- pBlockVectorDefragCtx = vma_new(m_hAllocator, VmaBlockVectorDefragmentationContext)(
- m_hAllocator,
- VMA_NULL, // hCustomPool
- m_hAllocator->m_pBlockVectors[memTypeIndex],
- m_CurrFrameIndex);
- m_DefaultPoolContexts[memTypeIndex] = pBlockVectorDefragCtx;
+ if (ReallocWithinBlock(vector, vector.GetBlock(i)))
+ return true;
}
}
- if(pBlockVectorDefragCtx)
+ if (prevMoveCount == m_Moves.size())
{
- VkBool32* const pChanged = (pAllocationsChanged != VMA_NULL) ?
- &pAllocationsChanged[allocIndex] : VMA_NULL;
- pBlockVectorDefragCtx->AddAllocation(hAlloc, pChanged);
+ // No possible reallocs within blocks, try to move them around fast
+ return ComputeDefragmentation_Fast(vector);
}
}
- }
-}
-
-VkResult VmaDefragmentationContext_T::Defragment(
- VkDeviceSize maxCpuBytesToMove, uint32_t maxCpuAllocationsToMove,
- VkDeviceSize maxGpuBytesToMove, uint32_t maxGpuAllocationsToMove,
- VkCommandBuffer commandBuffer, VmaDefragmentationStats* pStats, VmaDefragmentationFlags flags)
-{
- if(pStats)
- {
- memset(pStats, 0, sizeof(VmaDefragmentationStats));
- }
-
- if(flags & VMA_DEFRAGMENTATION_FLAG_INCREMENTAL)
- {
- // For incremental defragmetnations, we just earmark how much we can move
- // The real meat is in the defragmentation steps
- m_MaxCpuBytesToMove = maxCpuBytesToMove;
- m_MaxCpuAllocationsToMove = maxCpuAllocationsToMove;
-
- m_MaxGpuBytesToMove = maxGpuBytesToMove;
- m_MaxGpuAllocationsToMove = maxGpuAllocationsToMove;
-
- if(m_MaxCpuBytesToMove == 0 && m_MaxCpuAllocationsToMove == 0 &&
- m_MaxGpuBytesToMove == 0 && m_MaxGpuAllocationsToMove == 0)
- return VK_SUCCESS;
-
- return VK_NOT_READY;
- }
-
- if(commandBuffer == VK_NULL_HANDLE)
- {
- maxGpuBytesToMove = 0;
- maxGpuAllocationsToMove = 0;
- }
-
- VkResult res = VK_SUCCESS;
-
- // Process default pools.
- for(uint32_t memTypeIndex = 0;
- memTypeIndex < m_hAllocator->GetMemoryTypeCount() && res >= VK_SUCCESS;
- ++memTypeIndex)
- {
- VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
- if(pBlockVectorCtx)
- {
- VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
- pBlockVectorCtx->GetBlockVector()->Defragment(
- pBlockVectorCtx,
- pStats, flags,
- maxCpuBytesToMove, maxCpuAllocationsToMove,
- maxGpuBytesToMove, maxGpuAllocationsToMove,
- commandBuffer);
- if(pBlockVectorCtx->res != VK_SUCCESS)
+ else
+ {
+ switch (vectorState.operation)
{
- res = pBlockVectorCtx->res;
+ case StateExtensive::Operation::FindFreeBlockBuffer:
+ vectorState.operation = StateExtensive::Operation::MoveBuffers;
+ break;
+ default:
+ VMA_ASSERT(0);
+ case StateExtensive::Operation::FindFreeBlockTexture:
+ vectorState.operation = StateExtensive::Operation::MoveTextures;
+ break;
+ case StateExtensive::Operation::FindFreeBlockAll:
+ vectorState.operation = StateExtensive::Operation::MoveAll;
+ break;
}
+ vectorState.firstFreeBlock = last;
+ // Nothing done, block found without reallocations, can perform another reallocs in same pass
+ return ComputeDefragmentation_Extensive(vector, index);
}
+ break;
}
-
- // Process custom pools.
- for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
- customCtxIndex < customCtxCount && res >= VK_SUCCESS;
- ++customCtxIndex)
+ case StateExtensive::Operation::MoveTextures:
{
- VmaBlockVectorDefragmentationContext* pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
- VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
- pBlockVectorCtx->GetBlockVector()->Defragment(
- pBlockVectorCtx,
- pStats, flags,
- maxCpuBytesToMove, maxCpuAllocationsToMove,
- maxGpuBytesToMove, maxGpuAllocationsToMove,
- commandBuffer);
- if(pBlockVectorCtx->res != VK_SUCCESS)
+ if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL, vector,
+ vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))
{
- res = pBlockVectorCtx->res;
- }
- }
-
- return res;
-}
-
-VkResult VmaDefragmentationContext_T::DefragmentPassBegin(VmaDefragmentationPassInfo* pInfo)
-{
- VmaDefragmentationPassMoveInfo* pCurrentMove = pInfo->pMoves;
- uint32_t movesLeft = pInfo->moveCount;
-
- // Process default pools.
- for(uint32_t memTypeIndex = 0;
- memTypeIndex < m_hAllocator->GetMemoryTypeCount();
- ++memTypeIndex)
- {
- VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
- if(pBlockVectorCtx)
- {
- VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
-
- if(!pBlockVectorCtx->hasDefragmentationPlan)
+ if (texturePresent)
{
- pBlockVectorCtx->GetBlockVector()->Defragment(
- pBlockVectorCtx,
- m_pStats, m_Flags,
- m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,
- m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,
- VK_NULL_HANDLE);
-
- if(pBlockVectorCtx->res < VK_SUCCESS)
- continue;
-
- pBlockVectorCtx->hasDefragmentationPlan = true;
+ vectorState.operation = StateExtensive::Operation::FindFreeBlockTexture;
+ return ComputeDefragmentation_Extensive(vector, index);
}
- const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations(
- pBlockVectorCtx,
- pCurrentMove, movesLeft);
+ if (!bufferPresent && !otherPresent)
+ {
+ vectorState.operation = StateExtensive::Operation::Cleanup;
+ break;
+ }
- movesLeft -= processed;
- pCurrentMove += processed;
+ // No more textures to move, check buffers
+ vectorState.operation = StateExtensive::Operation::MoveBuffers;
+ bufferPresent = false;
+ otherPresent = false;
}
+ else
+ break;
}
-
- // Process custom pools.
- for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
- customCtxIndex < customCtxCount;
- ++customCtxIndex)
+ case StateExtensive::Operation::MoveBuffers:
{
- VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
- VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
-
- if(!pBlockVectorCtx->hasDefragmentationPlan)
+ if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_BUFFER, vector,
+ vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))
{
- pBlockVectorCtx->GetBlockVector()->Defragment(
- pBlockVectorCtx,
- m_pStats, m_Flags,
- m_MaxCpuBytesToMove, m_MaxCpuAllocationsToMove,
- m_MaxGpuBytesToMove, m_MaxGpuAllocationsToMove,
- VK_NULL_HANDLE);
+ if (bufferPresent)
+ {
+ vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer;
+ return ComputeDefragmentation_Extensive(vector, index);
+ }
- if(pBlockVectorCtx->res < VK_SUCCESS)
- continue;
+ if (!otherPresent)
+ {
+ vectorState.operation = StateExtensive::Operation::Cleanup;
+ break;
+ }
- pBlockVectorCtx->hasDefragmentationPlan = true;
+ // No more buffers to move, check all others
+ vectorState.operation = StateExtensive::Operation::MoveAll;
+ otherPresent = false;
}
-
- const uint32_t processed = pBlockVectorCtx->GetBlockVector()->ProcessDefragmentations(
- pBlockVectorCtx,
- pCurrentMove, movesLeft);
-
- movesLeft -= processed;
- pCurrentMove += processed;
+ else
+ break;
}
-
- pInfo->moveCount = pInfo->moveCount - movesLeft;
-
- return VK_SUCCESS;
-}
-VkResult VmaDefragmentationContext_T::DefragmentPassEnd()
-{
- VkResult res = VK_SUCCESS;
-
- // Process default pools.
- for(uint32_t memTypeIndex = 0;
- memTypeIndex < m_hAllocator->GetMemoryTypeCount();
- ++memTypeIndex)
+ case StateExtensive::Operation::MoveAll:
{
- VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_DefaultPoolContexts[memTypeIndex];
- if(pBlockVectorCtx)
+ if (MoveDataToFreeBlocks(VMA_SUBALLOCATION_TYPE_FREE, vector,
+ vectorState.firstFreeBlock, texturePresent, bufferPresent, otherPresent))
{
- VMA_ASSERT(pBlockVectorCtx->GetBlockVector());
-
- if(!pBlockVectorCtx->hasDefragmentationPlan)
+ if (otherPresent)
{
- res = VK_NOT_READY;
- continue;
+ vectorState.operation = StateExtensive::Operation::FindFreeBlockBuffer;
+ return ComputeDefragmentation_Extensive(vector, index);
}
-
- pBlockVectorCtx->GetBlockVector()->CommitDefragmentations(
- pBlockVectorCtx, m_pStats);
-
- if(pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted)
- res = VK_NOT_READY;
+ // Everything moved
+ vectorState.operation = StateExtensive::Operation::Cleanup;
}
+ break;
+ }
+ case StateExtensive::Operation::Cleanup:
+ // Cleanup is handled below so that other operations may reuse the cleanup code. This case is here to prevent the unhandled enum value warning (C4062).
+ break;
}
- // Process custom pools.
- for(size_t customCtxIndex = 0, customCtxCount = m_CustomPoolContexts.size();
- customCtxIndex < customCtxCount;
- ++customCtxIndex)
+ if (vectorState.operation == StateExtensive::Operation::Cleanup)
{
- VmaBlockVectorDefragmentationContext *pBlockVectorCtx = m_CustomPoolContexts[customCtxIndex];
- VMA_ASSERT(pBlockVectorCtx && pBlockVectorCtx->GetBlockVector());
-
- if(!pBlockVectorCtx->hasDefragmentationPlan)
+ // All other work done, pack data in blocks even tighter if possible
+ const size_t prevMoveCount = m_Moves.size();
+ for (size_t i = 0; i < vector.GetBlockCount(); ++i)
{
- res = VK_NOT_READY;
- continue;
+ if (ReallocWithinBlock(vector, vector.GetBlock(i)))
+ return true;
}
- pBlockVectorCtx->GetBlockVector()->CommitDefragmentations(
- pBlockVectorCtx, m_pStats);
-
- if(pBlockVectorCtx->defragmentationMoves.size() != pBlockVectorCtx->defragmentationMovesCommitted)
- res = VK_NOT_READY;
+ if (prevMoveCount == m_Moves.size())
+ vectorState.operation = StateExtensive::Operation::Done;
}
-
- return res;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaRecorder
-
-#if VMA_RECORDING_ENABLED
-
-VmaRecorder::VmaRecorder() :
- m_UseMutex(true),
- m_Flags(0),
- m_File(VMA_NULL),
- m_RecordingStartTime(std::chrono::high_resolution_clock::now())
-{
+ return false;
}
-VkResult VmaRecorder::Init(const VmaRecordSettings& settings, bool useMutex)
+void VmaDefragmentationContext_T::UpdateVectorStatistics(VmaBlockVector& vector, StateBalanced& state)
{
- m_UseMutex = useMutex;
- m_Flags = settings.flags;
+ size_t allocCount = 0;
+ size_t freeCount = 0;
+ state.avgFreeSize = 0;
+ state.avgAllocSize = 0;
-#if defined(_WIN32)
- // Open file for writing.
- errno_t err = fopen_s(&m_File, settings.pFilePath, "wb");
-
- if(err != 0)
+ for (size_t i = 0; i < vector.GetBlockCount(); ++i)
{
- return VK_ERROR_INITIALIZATION_FAILED;
- }
-#else
- // Open file for writing.
- m_File = fopen(settings.pFilePath, "wb");
+ VmaBlockMetadata* metadata = vector.GetBlock(i)->m_pMetadata;
- if(m_File == 0)
- {
- return VK_ERROR_INITIALIZATION_FAILED;
+ allocCount += metadata->GetAllocationCount();
+ freeCount += metadata->GetFreeRegionsCount();
+ state.avgFreeSize += metadata->GetSumFreeSize();
+ state.avgAllocSize += metadata->GetSize();
}
-#endif
- // Write header.
- fprintf(m_File, "%s\n", "Vulkan Memory Allocator,Calls recording");
- fprintf(m_File, "%s\n", "1,8");
-
- return VK_SUCCESS;
+ state.avgAllocSize = (state.avgAllocSize - state.avgFreeSize) / allocCount;
+ state.avgFreeSize /= freeCount;
}
-VmaRecorder::~VmaRecorder()
+bool VmaDefragmentationContext_T::MoveDataToFreeBlocks(VmaSuballocationType currentType,
+ VmaBlockVector& vector, size_t firstFreeBlock,
+ bool& texturePresent, bool& bufferPresent, bool& otherPresent)
{
- if(m_File != VMA_NULL)
+ const size_t prevMoveCount = m_Moves.size();
+ for (size_t i = firstFreeBlock ; i;)
{
- fclose(m_File);
- }
-}
-
-void VmaRecorder::RecordCreateAllocator(uint32_t frameIndex)
-{
- CallParams callParams;
- GetBasicParams(callParams);
+ VmaDeviceMemoryBlock* block = vector.GetBlock(--i);
+ VmaBlockMetadata* metadata = block->m_pMetadata;
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaCreateAllocator\n", callParams.threadId, callParams.time, frameIndex);
- Flush();
-}
+ for (VmaAllocHandle handle = metadata->GetAllocationListBegin();
+ handle != VK_NULL_HANDLE;
+ handle = metadata->GetNextAllocation(handle))
+ {
+ MoveAllocationData moveData = GetMoveData(handle, metadata);
+ // Ignore newly created allocations by defragmentation algorithm
+ if (moveData.move.srcAllocation->GetUserData() == this)
+ continue;
+ switch (CheckCounters(moveData.move.srcAllocation->GetSize()))
+ {
+ case CounterStatus::Ignore:
+ continue;
+ case CounterStatus::End:
+ return true;
+ default:
+ VMA_ASSERT(0);
+ case CounterStatus::Pass:
+ break;
+ }
-void VmaRecorder::RecordDestroyAllocator(uint32_t frameIndex)
-{
- CallParams callParams;
- GetBasicParams(callParams);
+ // Move only single type of resources at once
+ if (!VmaIsBufferImageGranularityConflict(moveData.type, currentType))
+ {
+ // Try to fit allocation into free blocks
+ if (AllocInOtherBlock(firstFreeBlock, vector.GetBlockCount(), moveData, vector))
+ return false;
+ }
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDestroyAllocator\n", callParams.threadId, callParams.time, frameIndex);
- Flush();
+ if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_IMAGE_OPTIMAL))
+ texturePresent = true;
+ else if (!VmaIsBufferImageGranularityConflict(moveData.type, VMA_SUBALLOCATION_TYPE_BUFFER))
+ bufferPresent = true;
+ else
+ otherPresent = true;
+ }
+ }
+ return prevMoveCount == m_Moves.size();
}
+#endif // _VMA_DEFRAGMENTATION_CONTEXT_FUNCTIONS
-void VmaRecorder::RecordCreatePool(uint32_t frameIndex, const VmaPoolCreateInfo& createInfo, VmaPool pool)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaCreatePool,%u,%u,%llu,%llu,%llu,%u,%p\n", callParams.threadId, callParams.time, frameIndex,
+#ifndef _VMA_POOL_T_FUNCTIONS
+VmaPool_T::VmaPool_T(
+ VmaAllocator hAllocator,
+ const VmaPoolCreateInfo& createInfo,
+ VkDeviceSize preferredBlockSize)
+ : m_BlockVector(
+ hAllocator,
+ this, // hParentPool
createInfo.memoryTypeIndex,
- createInfo.flags,
- createInfo.blockSize,
- (uint64_t)createInfo.minBlockCount,
- (uint64_t)createInfo.maxBlockCount,
- createInfo.frameInUseCount,
- pool);
- Flush();
-}
-
-void VmaRecorder::RecordDestroyPool(uint32_t frameIndex, VmaPool pool)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDestroyPool,%p\n", callParams.threadId, callParams.time, frameIndex,
- pool);
- Flush();
-}
-
-void VmaRecorder::RecordAllocateMemory(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemory,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- vkMemReq.size,
- vkMemReq.alignment,
- vkMemReq.memoryTypeBits,
- createInfo.flags,
- createInfo.usage,
- createInfo.requiredFlags,
- createInfo.preferredFlags,
- createInfo.memoryTypeBits,
- createInfo.pool,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordAllocateMemoryPages(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- const VmaAllocationCreateInfo& createInfo,
- uint64_t allocationCount,
- const VmaAllocation* pAllocations)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryPages,%llu,%llu,%u,%u,%u,%u,%u,%u,%p,", callParams.threadId, callParams.time, frameIndex,
- vkMemReq.size,
- vkMemReq.alignment,
- vkMemReq.memoryTypeBits,
- createInfo.flags,
- createInfo.usage,
- createInfo.requiredFlags,
- createInfo.preferredFlags,
- createInfo.memoryTypeBits,
- createInfo.pool);
- PrintPointerList(allocationCount, pAllocations);
- fprintf(m_File, ",%s\n", userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordAllocateMemoryForBuffer(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForBuffer,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- vkMemReq.size,
- vkMemReq.alignment,
- vkMemReq.memoryTypeBits,
- requiresDedicatedAllocation ? 1 : 0,
- prefersDedicatedAllocation ? 1 : 0,
- createInfo.flags,
- createInfo.usage,
- createInfo.requiredFlags,
- createInfo.preferredFlags,
- createInfo.memoryTypeBits,
- createInfo.pool,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordAllocateMemoryForImage(uint32_t frameIndex,
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- const VmaAllocationCreateInfo& createInfo,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(createInfo.flags, createInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaAllocateMemoryForImage,%llu,%llu,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- vkMemReq.size,
- vkMemReq.alignment,
- vkMemReq.memoryTypeBits,
- requiresDedicatedAllocation ? 1 : 0,
- prefersDedicatedAllocation ? 1 : 0,
- createInfo.flags,
- createInfo.usage,
- createInfo.requiredFlags,
- createInfo.preferredFlags,
- createInfo.memoryTypeBits,
- createInfo.pool,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordFreeMemory(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaFreeMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordFreeMemoryPages(uint32_t frameIndex,
- uint64_t allocationCount,
- const VmaAllocation* pAllocations)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaFreeMemoryPages,", callParams.threadId, callParams.time, frameIndex);
- PrintPointerList(allocationCount, pAllocations);
- fprintf(m_File, "\n");
- Flush();
-}
-
-void VmaRecorder::RecordSetAllocationUserData(uint32_t frameIndex,
- VmaAllocation allocation,
- const void* pUserData)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(
- allocation->IsUserDataString() ? VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT : 0,
- pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaSetAllocationUserData,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordCreateLostAllocation(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaCreateLostAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordMapMemory(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaMapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordUnmapMemory(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaUnmapMemory,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordFlushAllocation(uint32_t frameIndex,
- VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaFlushAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
- allocation,
- offset,
- size);
- Flush();
-}
-
-void VmaRecorder::RecordInvalidateAllocation(uint32_t frameIndex,
- VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaInvalidateAllocation,%p,%llu,%llu\n", callParams.threadId, callParams.time, frameIndex,
- allocation,
- offset,
- size);
- Flush();
-}
-
-void VmaRecorder::RecordCreateBuffer(uint32_t frameIndex,
- const VkBufferCreateInfo& bufCreateInfo,
- const VmaAllocationCreateInfo& allocCreateInfo,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaCreateBuffer,%u,%llu,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- bufCreateInfo.flags,
- bufCreateInfo.size,
- bufCreateInfo.usage,
- bufCreateInfo.sharingMode,
- allocCreateInfo.flags,
- allocCreateInfo.usage,
- allocCreateInfo.requiredFlags,
- allocCreateInfo.preferredFlags,
- allocCreateInfo.memoryTypeBits,
- allocCreateInfo.pool,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordCreateImage(uint32_t frameIndex,
- const VkImageCreateInfo& imageCreateInfo,
- const VmaAllocationCreateInfo& allocCreateInfo,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- UserDataString userDataStr(allocCreateInfo.flags, allocCreateInfo.pUserData);
- fprintf(m_File, "%u,%.3f,%u,vmaCreateImage,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%p,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- imageCreateInfo.flags,
- imageCreateInfo.imageType,
- imageCreateInfo.format,
- imageCreateInfo.extent.width,
- imageCreateInfo.extent.height,
- imageCreateInfo.extent.depth,
- imageCreateInfo.mipLevels,
- imageCreateInfo.arrayLayers,
- imageCreateInfo.samples,
- imageCreateInfo.tiling,
- imageCreateInfo.usage,
- imageCreateInfo.sharingMode,
- imageCreateInfo.initialLayout,
- allocCreateInfo.flags,
- allocCreateInfo.usage,
- allocCreateInfo.requiredFlags,
- allocCreateInfo.preferredFlags,
- allocCreateInfo.memoryTypeBits,
- allocCreateInfo.pool,
- allocation,
- userDataStr.GetString());
- Flush();
-}
-
-void VmaRecorder::RecordDestroyBuffer(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDestroyBuffer,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordDestroyImage(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDestroyImage,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordTouchAllocation(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaTouchAllocation,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordGetAllocationInfo(uint32_t frameIndex,
- VmaAllocation allocation)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaGetAllocationInfo,%p\n", callParams.threadId, callParams.time, frameIndex,
- allocation);
- Flush();
-}
-
-void VmaRecorder::RecordMakePoolAllocationsLost(uint32_t frameIndex,
- VmaPool pool)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaMakePoolAllocationsLost,%p\n", callParams.threadId, callParams.time, frameIndex,
- pool);
- Flush();
-}
-
-void VmaRecorder::RecordDefragmentationBegin(uint32_t frameIndex,
- const VmaDefragmentationInfo2& info,
- VmaDefragmentationContext ctx)
-{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationBegin,%u,", callParams.threadId, callParams.time, frameIndex,
- info.flags);
- PrintPointerList(info.allocationCount, info.pAllocations);
- fprintf(m_File, ",");
- PrintPointerList(info.poolCount, info.pPools);
- fprintf(m_File, ",%llu,%u,%llu,%u,%p,%p\n",
- info.maxCpuBytesToMove,
- info.maxCpuAllocationsToMove,
- info.maxGpuBytesToMove,
- info.maxGpuAllocationsToMove,
- info.commandBuffer,
- ctx);
- Flush();
-}
+ createInfo.blockSize != 0 ? createInfo.blockSize : preferredBlockSize,
+ createInfo.minBlockCount,
+ createInfo.maxBlockCount,
+ (createInfo.flags& VMA_POOL_CREATE_IGNORE_BUFFER_IMAGE_GRANULARITY_BIT) != 0 ? 1 : hAllocator->GetBufferImageGranularity(),
+ createInfo.blockSize != 0, // explicitBlockSize
+ createInfo.flags & VMA_POOL_CREATE_ALGORITHM_MASK, // algorithm
+ createInfo.priority,
+ VMA_MAX(hAllocator->GetMemoryTypeMinAlignment(createInfo.memoryTypeIndex), createInfo.minAllocationAlignment),
+ createInfo.pMemoryAllocateNext),
+ m_Id(0),
+ m_Name(VMA_NULL) {}
-void VmaRecorder::RecordDefragmentationEnd(uint32_t frameIndex,
- VmaDefragmentationContext ctx)
+VmaPool_T::~VmaPool_T()
{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaDefragmentationEnd,%p\n", callParams.threadId, callParams.time, frameIndex,
- ctx);
- Flush();
+ VMA_ASSERT(m_PrevPool == VMA_NULL && m_NextPool == VMA_NULL);
}
-void VmaRecorder::RecordSetPoolName(uint32_t frameIndex,
- VmaPool pool,
- const char* name)
+void VmaPool_T::SetName(const char* pName)
{
- CallParams callParams;
- GetBasicParams(callParams);
-
- VmaMutexLock lock(m_FileMutex, m_UseMutex);
- fprintf(m_File, "%u,%.3f,%u,vmaSetPoolName,%p,%s\n", callParams.threadId, callParams.time, frameIndex,
- pool, name != VMA_NULL ? name : "");
- Flush();
-}
+ const VkAllocationCallbacks* allocs = m_BlockVector.GetAllocator()->GetAllocationCallbacks();
+ VmaFreeString(allocs, m_Name);
-VmaRecorder::UserDataString::UserDataString(VmaAllocationCreateFlags allocFlags, const void* pUserData)
-{
- if(pUserData != VMA_NULL)
+ if (pName != VMA_NULL)
{
- if((allocFlags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0)
- {
- m_Str = (const char*)pUserData;
- }
- else
- {
- // If VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT is not specified, convert the string's memory address to a string and store it.
- snprintf(m_PtrStr, 17, "%p", pUserData);
- m_Str = m_PtrStr;
- }
+ m_Name = VmaCreateStringCopy(allocs, pName);
}
else
{
- m_Str = "";
- }
-}
-
-void VmaRecorder::WriteConfiguration(
- const VkPhysicalDeviceProperties& devProps,
- const VkPhysicalDeviceMemoryProperties& memProps,
- uint32_t vulkanApiVersion,
- bool dedicatedAllocationExtensionEnabled,
- bool bindMemory2ExtensionEnabled,
- bool memoryBudgetExtensionEnabled,
- bool deviceCoherentMemoryExtensionEnabled)
-{
- fprintf(m_File, "Config,Begin\n");
-
- fprintf(m_File, "VulkanApiVersion,%u,%u\n", VK_VERSION_MAJOR(vulkanApiVersion), VK_VERSION_MINOR(vulkanApiVersion));
-
- fprintf(m_File, "PhysicalDevice,apiVersion,%u\n", devProps.apiVersion);
- fprintf(m_File, "PhysicalDevice,driverVersion,%u\n", devProps.driverVersion);
- fprintf(m_File, "PhysicalDevice,vendorID,%u\n", devProps.vendorID);
- fprintf(m_File, "PhysicalDevice,deviceID,%u\n", devProps.deviceID);
- fprintf(m_File, "PhysicalDevice,deviceType,%u\n", devProps.deviceType);
- fprintf(m_File, "PhysicalDevice,deviceName,%s\n", devProps.deviceName);
-
- fprintf(m_File, "PhysicalDeviceLimits,maxMemoryAllocationCount,%u\n", devProps.limits.maxMemoryAllocationCount);
- fprintf(m_File, "PhysicalDeviceLimits,bufferImageGranularity,%llu\n", devProps.limits.bufferImageGranularity);
- fprintf(m_File, "PhysicalDeviceLimits,nonCoherentAtomSize,%llu\n", devProps.limits.nonCoherentAtomSize);
-
- fprintf(m_File, "PhysicalDeviceMemory,HeapCount,%u\n", memProps.memoryHeapCount);
- for(uint32_t i = 0; i < memProps.memoryHeapCount; ++i)
- {
- fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,size,%llu\n", i, memProps.memoryHeaps[i].size);
- fprintf(m_File, "PhysicalDeviceMemory,Heap,%u,flags,%u\n", i, memProps.memoryHeaps[i].flags);
- }
- fprintf(m_File, "PhysicalDeviceMemory,TypeCount,%u\n", memProps.memoryTypeCount);
- for(uint32_t i = 0; i < memProps.memoryTypeCount; ++i)
- {
- fprintf(m_File, "PhysicalDeviceMemory,Type,%u,heapIndex,%u\n", i, memProps.memoryTypes[i].heapIndex);
- fprintf(m_File, "PhysicalDeviceMemory,Type,%u,propertyFlags,%u\n", i, memProps.memoryTypes[i].propertyFlags);
- }
-
- fprintf(m_File, "Extension,VK_KHR_dedicated_allocation,%u\n", dedicatedAllocationExtensionEnabled ? 1 : 0);
- fprintf(m_File, "Extension,VK_KHR_bind_memory2,%u\n", bindMemory2ExtensionEnabled ? 1 : 0);
- fprintf(m_File, "Extension,VK_EXT_memory_budget,%u\n", memoryBudgetExtensionEnabled ? 1 : 0);
- fprintf(m_File, "Extension,VK_AMD_device_coherent_memory,%u\n", deviceCoherentMemoryExtensionEnabled ? 1 : 0);
-
- fprintf(m_File, "Macro,VMA_DEBUG_ALWAYS_DEDICATED_MEMORY,%u\n", VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ? 1 : 0);
- fprintf(m_File, "Macro,VMA_MIN_ALIGNMENT,%llu\n", (VkDeviceSize)VMA_MIN_ALIGNMENT);
- fprintf(m_File, "Macro,VMA_DEBUG_MARGIN,%llu\n", (VkDeviceSize)VMA_DEBUG_MARGIN);
- fprintf(m_File, "Macro,VMA_DEBUG_INITIALIZE_ALLOCATIONS,%u\n", VMA_DEBUG_INITIALIZE_ALLOCATIONS ? 1 : 0);
- fprintf(m_File, "Macro,VMA_DEBUG_DETECT_CORRUPTION,%u\n", VMA_DEBUG_DETECT_CORRUPTION ? 1 : 0);
- fprintf(m_File, "Macro,VMA_DEBUG_GLOBAL_MUTEX,%u\n", VMA_DEBUG_GLOBAL_MUTEX ? 1 : 0);
- fprintf(m_File, "Macro,VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY,%llu\n", (VkDeviceSize)VMA_DEBUG_MIN_BUFFER_IMAGE_GRANULARITY);
- fprintf(m_File, "Macro,VMA_SMALL_HEAP_MAX_SIZE,%llu\n", (VkDeviceSize)VMA_SMALL_HEAP_MAX_SIZE);
- fprintf(m_File, "Macro,VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE,%llu\n", (VkDeviceSize)VMA_DEFAULT_LARGE_HEAP_BLOCK_SIZE);
-
- fprintf(m_File, "Config,End\n");
-}
-
-void VmaRecorder::GetBasicParams(CallParams& outParams)
-{
- #if defined(_WIN32)
- outParams.threadId = GetCurrentThreadId();
- #else
- // Use C++11 features to get thread id and convert it to uint32_t.
- // There is room for optimization since sstream is quite slow.
- // Is there a better way to convert std::this_thread::get_id() to uint32_t?
- std::thread::id thread_id = std::this_thread::get_id();
- std::stringstream thread_id_to_string_converter;
- thread_id_to_string_converter << thread_id;
- std::string thread_id_as_string = thread_id_to_string_converter.str();
- outParams.threadId = static_cast<uint32_t>(std::stoi(thread_id_as_string.c_str()));
- #endif
-
- auto current_time = std::chrono::high_resolution_clock::now();
-
- outParams.time = std::chrono::duration<double, std::chrono::seconds::period>(current_time - m_RecordingStartTime).count();
-}
-
-void VmaRecorder::PrintPointerList(uint64_t count, const VmaAllocation* pItems)
-{
- if(count)
- {
- fprintf(m_File, "%p", pItems[0]);
- for(uint64_t i = 1; i < count; ++i)
- {
- fprintf(m_File, " %p", pItems[i]);
- }
- }
-}
-
-void VmaRecorder::Flush()
-{
- if((m_Flags & VMA_RECORD_FLUSH_AFTER_CALL_BIT) != 0)
- {
- fflush(m_File);
+ m_Name = VMA_NULL;
}
}
+#endif // _VMA_POOL_T_FUNCTIONS
-#endif // #if VMA_RECORDING_ENABLED
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaAllocationObjectAllocator
-
-VmaAllocationObjectAllocator::VmaAllocationObjectAllocator(const VkAllocationCallbacks* pAllocationCallbacks) :
- m_Allocator(pAllocationCallbacks, 1024)
-{
-}
-
-template<typename... Types> VmaAllocation VmaAllocationObjectAllocator::Allocate(Types... args)
-{
- VmaMutexLock mutexLock(m_Mutex);
- return m_Allocator.Alloc<Types...>(std::forward<Types>(args)...);
-}
-
-void VmaAllocationObjectAllocator::Free(VmaAllocation hAlloc)
-{
- VmaMutexLock mutexLock(m_Mutex);
- m_Allocator.Free(hAlloc);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// VmaAllocator_T
-
+#ifndef _VMA_ALLOCATOR_T_FUNCTIONS
VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_UseMutex((pCreateInfo->flags & VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) == 0),
m_VulkanApiVersion(pCreateInfo->vulkanApiVersion != 0 ? pCreateInfo->vulkanApiVersion : VK_API_VERSION_1_0),
@@ -16083,13 +13988,9 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
m_DeviceMemoryCount(0),
m_PreferredLargeHeapBlockSize(0),
m_PhysicalDevice(pCreateInfo->physicalDevice),
- m_CurrentFrameIndex(0),
m_GpuDefragmentationMemoryTypeBits(UINT32_MAX),
m_NextPoolId(0),
m_GlobalMemoryTypeBits(UINT32_MAX)
-#if VMA_RECORDING_ENABLED
- ,m_pRecorder(VMA_NULL)
-#endif
{
if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{
@@ -16156,7 +14057,6 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
memset(&m_MemProps, 0, sizeof(m_MemProps));
memset(&m_pBlockVectors, 0, sizeof(m_pBlockVectors));
- memset(&m_pSmallBufferBlockVectors, 0, sizeof(m_pSmallBufferBlockVectors));
memset(&m_VulkanFunctions, 0, sizeof(m_VulkanFunctions));
#if VMA_EXTERNAL_MEMORY
@@ -16211,38 +14111,26 @@ VmaAllocator_T::VmaAllocator_T(const VmaAllocatorCreateInfo* pCreateInfo) :
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
- const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
-
- m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
- this,
- VK_NULL_HANDLE, // hParentPool
- memTypeIndex,
- preferredBlockSize,
- 0,
- SIZE_MAX,
- GetBufferImageGranularity(),
- pCreateInfo->frameInUseCount,
- false, // explicitBlockSize
- false, // linearAlgorithm
- 0.5f, // priority (0.5 is the default per Vulkan spec)
- GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment
- VMA_NULL); // // pMemoryAllocateNext
- m_pSmallBufferBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
- this,
- VK_NULL_HANDLE, // hParentPool
- memTypeIndex,
- preferredBlockSize,
- 0,
- SIZE_MAX,
- 1, // bufferImageGranularity forced to 1 !!!
- pCreateInfo->frameInUseCount,
- false, // explicitBlockSize
- false, // linearAlgorithm
- 0.5f, // priority (0.5 is the default per Vulkan spec)
- GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment
- VMA_NULL); // // pMemoryAllocateNext
- // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
- // becase minBlockCount is 0.
+ // Create only supported types
+ if((m_GlobalMemoryTypeBits & (1u << memTypeIndex)) != 0)
+ {
+ const VkDeviceSize preferredBlockSize = CalcPreferredBlockSize(memTypeIndex);
+ m_pBlockVectors[memTypeIndex] = vma_new(this, VmaBlockVector)(
+ this,
+ VK_NULL_HANDLE, // hParentPool
+ memTypeIndex,
+ preferredBlockSize,
+ 0,
+ SIZE_MAX,
+ GetBufferImageGranularity(),
+ false, // explicitBlockSize
+ 0, // algorithm
+ 0.5f, // priority (0.5 is the default per Vulkan spec)
+ GetMemoryTypeMinAlignment(memTypeIndex), // minAllocationAlignment
+ VMA_NULL); // // pMemoryAllocateNext
+ // No need to call m_pBlockVectors[memTypeIndex][blockVectorTypeIndex]->CreateMinBlocks here,
+ // becase minBlockCount is 0.
+ }
}
}
@@ -16250,31 +14138,6 @@ VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)
{
VkResult res = VK_SUCCESS;
- if(pCreateInfo->pRecordSettings != VMA_NULL &&
- !VmaStrIsEmpty(pCreateInfo->pRecordSettings->pFilePath))
- {
-#if VMA_RECORDING_ENABLED
- m_pRecorder = vma_new(this, VmaRecorder)();
- res = m_pRecorder->Init(*pCreateInfo->pRecordSettings, m_UseMutex);
- if(res != VK_SUCCESS)
- {
- return res;
- }
- m_pRecorder->WriteConfiguration(
- m_PhysicalDeviceProperties,
- m_MemProps,
- m_VulkanApiVersion,
- m_UseKhrDedicatedAllocation,
- m_UseKhrBindMemory2,
- m_UseExtMemoryBudget,
- m_UseAmdDeviceCoherentMemory);
- m_pRecorder->RecordCreateAllocator(GetCurrentFrameIndex());
-#else
- VMA_ASSERT(0 && "VmaAllocatorCreateInfo::pRecordSettings used, but not supported due to VMA_RECORDING_ENABLED not defined to 1.");
- return VK_ERROR_FEATURE_NOT_PRESENT;
-#endif
- }
-
#if VMA_MEMORY_BUDGET
if(m_UseExtMemoryBudget)
{
@@ -16287,24 +14150,10 @@ VkResult VmaAllocator_T::Init(const VmaAllocatorCreateInfo* pCreateInfo)
VmaAllocator_T::~VmaAllocator_T()
{
-#if VMA_RECORDING_ENABLED
- if(m_pRecorder != VMA_NULL)
- {
- m_pRecorder->RecordDestroyAllocator(GetCurrentFrameIndex());
- vma_delete(this, m_pRecorder);
- }
-#endif
-
VMA_ASSERT(m_Pools.IsEmpty());
for(size_t memTypeIndex = GetMemoryTypeCount(); memTypeIndex--; )
{
- if(!m_DedicatedAllocations[memTypeIndex].IsEmpty())
- {
- VMA_ASSERT(0 && "Unfreed dedicated allocations found.");
- }
-
- vma_delete(this, m_pSmallBufferBlockVectors[memTypeIndex]);
vma_delete(this, m_pBlockVectors[memTypeIndex]);
}
}
@@ -16332,6 +14181,8 @@ void VmaAllocator_T::ImportVulkanFunctions(const VmaVulkanFunctions* pVulkanFunc
void VmaAllocator_T::ImportVulkanFunctions_Static()
{
// Vulkan 1.0
+ m_VulkanFunctions.vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr;
+ m_VulkanFunctions.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)vkGetDeviceProcAddr;
m_VulkanFunctions.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)vkGetPhysicalDeviceProperties;
m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)vkGetPhysicalDeviceMemoryProperties;
m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
@@ -16361,9 +14212,17 @@ void VmaAllocator_T::ImportVulkanFunctions_Static()
m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR = (PFN_vkGetPhysicalDeviceMemoryProperties2)vkGetPhysicalDeviceMemoryProperties2;
}
#endif
+
+#if VMA_VULKAN_VERSION >= 1003000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
+ {
+ m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements = (PFN_vkGetDeviceBufferMemoryRequirements)vkGetDeviceBufferMemoryRequirements;
+ m_VulkanFunctions.vkGetDeviceImageMemoryRequirements = (PFN_vkGetDeviceImageMemoryRequirements)vkGetDeviceImageMemoryRequirements;
+ }
+#endif
}
-#endif // #if VMA_STATIC_VULKAN_FUNCTIONS == 1
+#endif // VMA_STATIC_VULKAN_FUNCTIONS == 1
void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVulkanFunctions)
{
@@ -16372,6 +14231,8 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
#define VMA_COPY_IF_NOT_NULL(funcName) \
if(pVulkanFunctions->funcName != VMA_NULL) m_VulkanFunctions.funcName = pVulkanFunctions->funcName;
+ VMA_COPY_IF_NOT_NULL(vkGetInstanceProcAddr);
+ VMA_COPY_IF_NOT_NULL(vkGetDeviceProcAddr);
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceProperties);
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties);
VMA_COPY_IF_NOT_NULL(vkAllocateMemory);
@@ -16404,6 +14265,11 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
VMA_COPY_IF_NOT_NULL(vkGetPhysicalDeviceMemoryProperties2KHR);
#endif
+#if VMA_VULKAN_VERSION >= 1003000
+ VMA_COPY_IF_NOT_NULL(vkGetDeviceBufferMemoryRequirements);
+ VMA_COPY_IF_NOT_NULL(vkGetDeviceImageMemoryRequirements);
+#endif
+
#undef VMA_COPY_IF_NOT_NULL
}
@@ -16411,14 +14277,19 @@ void VmaAllocator_T::ImportVulkanFunctions_Custom(const VmaVulkanFunctions* pVul
void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
{
+ VMA_ASSERT(m_VulkanFunctions.vkGetInstanceProcAddr && m_VulkanFunctions.vkGetDeviceProcAddr &&
+ "To use VMA_DYNAMIC_VULKAN_FUNCTIONS in new versions of VMA you now have to pass "
+ "VmaVulkanFunctions::vkGetInstanceProcAddr and vkGetDeviceProcAddr as VmaAllocatorCreateInfo::pVulkanFunctions. "
+ "Other members can be null.");
+
#define VMA_FETCH_INSTANCE_FUNC(memberName, functionPointerType, functionNameString) \
if(m_VulkanFunctions.memberName == VMA_NULL) \
m_VulkanFunctions.memberName = \
- (functionPointerType)vkGetInstanceProcAddr(m_hInstance, functionNameString);
+ (functionPointerType)m_VulkanFunctions.vkGetInstanceProcAddr(m_hInstance, functionNameString);
#define VMA_FETCH_DEVICE_FUNC(memberName, functionPointerType, functionNameString) \
if(m_VulkanFunctions.memberName == VMA_NULL) \
m_VulkanFunctions.memberName = \
- (functionPointerType)vkGetDeviceProcAddr(m_hDevice, functionNameString);
+ (functionPointerType)m_VulkanFunctions.vkGetDeviceProcAddr(m_hDevice, functionNameString);
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceProperties, PFN_vkGetPhysicalDeviceProperties, "vkGetPhysicalDeviceProperties");
VMA_FETCH_INSTANCE_FUNC(vkGetPhysicalDeviceMemoryProperties, PFN_vkGetPhysicalDeviceMemoryProperties, "vkGetPhysicalDeviceMemoryProperties");
@@ -16472,11 +14343,19 @@ void VmaAllocator_T::ImportVulkanFunctions_Dynamic()
}
#endif // #if VMA_MEMORY_BUDGET
+#if VMA_VULKAN_VERSION >= 1003000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
+ {
+ VMA_FETCH_DEVICE_FUNC(vkGetDeviceBufferMemoryRequirements, PFN_vkGetDeviceBufferMemoryRequirements, "vkGetDeviceBufferMemoryRequirements");
+ VMA_FETCH_DEVICE_FUNC(vkGetDeviceImageMemoryRequirements, PFN_vkGetDeviceImageMemoryRequirements, "vkGetDeviceImageMemoryRequirements");
+ }
+#endif
+
#undef VMA_FETCH_DEVICE_FUNC
#undef VMA_FETCH_INSTANCE_FUNC
}
-#endif // #if VMA_DYNAMIC_VULKAN_FUNCTIONS == 1
+#endif // VMA_DYNAMIC_VULKAN_FUNCTIONS == 1
void VmaAllocator_T::ValidateVulkanFunctions()
{
@@ -16520,6 +14399,14 @@ void VmaAllocator_T::ValidateVulkanFunctions()
VMA_ASSERT(m_VulkanFunctions.vkGetPhysicalDeviceMemoryProperties2KHR != VMA_NULL);
}
#endif
+
+#if VMA_VULKAN_VERSION >= 1003000
+ if(m_VulkanApiVersion >= VK_MAKE_VERSION(1, 3, 0))
+ {
+ VMA_ASSERT(m_VulkanFunctions.vkGetDeviceBufferMemoryRequirements != VMA_NULL);
+ VMA_ASSERT(m_VulkanFunctions.vkGetDeviceImageMemoryRequirements != VMA_NULL);
+ }
+#endif
}
VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
@@ -16531,15 +14418,18 @@ VkDeviceSize VmaAllocator_T::CalcPreferredBlockSize(uint32_t memTypeIndex)
}
VkResult VmaAllocator_T::AllocateMemoryOfType(
+ VmaPool pool,
VkDeviceSize size,
VkDeviceSize alignment,
- bool dedicatedAllocation,
+ bool dedicatedPreferred,
VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage,
VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage,
const VmaAllocationCreateInfo& createInfo,
uint32_t memTypeIndex,
VmaSuballocationType suballocType,
+ VmaDedicatedAllocationList& dedicatedAllocations,
+ VmaBlockVector& blockVector,
size_t allocationCount,
VmaAllocation* pAllocations)
{
@@ -16547,165 +14437,175 @@ VkResult VmaAllocator_T::AllocateMemoryOfType(
VMA_DEBUG_LOG(" AllocateMemory: MemoryTypeIndex=%u, AllocationCount=%zu, Size=%llu", memTypeIndex, allocationCount, size);
VmaAllocationCreateInfo finalCreateInfo = createInfo;
+ VkResult res = CalcMemTypeParams(
+ finalCreateInfo,
+ memTypeIndex,
+ size,
+ allocationCount);
+ if(res != VK_SUCCESS)
+ return res;
- // If memory type is not HOST_VISIBLE, disable MAPPED.
- if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
- (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
{
- finalCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ return AllocateDedicatedMemory(
+ pool,
+ size,
+ suballocType,
+ dedicatedAllocations,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ (finalCreateInfo.flags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,
+ finalCreateInfo.pUserData,
+ finalCreateInfo.priority,
+ dedicatedBuffer,
+ dedicatedImage,
+ dedicatedBufferImageUsage,
+ allocationCount,
+ pAllocations,
+ blockVector.GetAllocationNextPtr());
}
- // If memory is lazily allocated, it should be always dedicated.
- if(finalCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED)
+ else
{
- finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
- }
+ const bool canAllocateDedicated =
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
+ (pool == VK_NULL_HANDLE || !blockVector.HasExplicitBlockSize());
- bool isSmallBuffer = dedicatedBuffer != VK_NULL_HANDLE && size <= 4096; // TODO
- VmaBlockVector* const blockVector = isSmallBuffer ? m_pSmallBufferBlockVectors[memTypeIndex] : m_pBlockVectors[memTypeIndex];
- VMA_ASSERT(blockVector);
+ if(canAllocateDedicated)
+ {
+ // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
+ if(size > blockVector.GetPreferredBlockSize() / 2)
+ {
+ dedicatedPreferred = true;
+ }
+ // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget,
+ // which can quickly deplete maxMemoryAllocationCount: Don't prefer dedicated allocations when above
+ // 3/4 of the maximum allocation count.
+ if(m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4)
+ {
+ dedicatedPreferred = false;
+ }
- const VkDeviceSize preferredBlockSize = blockVector->GetPreferredBlockSize();
- bool preferDedicatedMemory =
- VMA_DEBUG_ALWAYS_DEDICATED_MEMORY ||
- dedicatedAllocation ||
- // Heuristics: Allocate dedicated memory if requested size if greater than half of preferred block size.
- size > preferredBlockSize / 2;
+ if(dedicatedPreferred)
+ {
+ res = AllocateDedicatedMemory(
+ pool,
+ size,
+ suballocType,
+ dedicatedAllocations,
+ memTypeIndex,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ (finalCreateInfo.flags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,
+ finalCreateInfo.pUserData,
+ finalCreateInfo.priority,
+ dedicatedBuffer,
+ dedicatedImage,
+ dedicatedBufferImageUsage,
+ allocationCount,
+ pAllocations,
+ blockVector.GetAllocationNextPtr());
+ if(res == VK_SUCCESS)
+ {
+ // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
+ VMA_DEBUG_LOG(" Allocated as DedicatedMemory");
+ return VK_SUCCESS;
+ }
+ }
+ }
- if(preferDedicatedMemory &&
- (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) == 0 &&
- finalCreateInfo.pool == VK_NULL_HANDLE)
- {
- finalCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
- }
+ res = blockVector.Allocate(
+ size,
+ alignment,
+ finalCreateInfo,
+ suballocType,
+ allocationCount,
+ pAllocations);
+ if(res == VK_SUCCESS)
+ return VK_SUCCESS;
- if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
- {
- if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ // Try dedicated memory.
+ if(canAllocateDedicated && !dedicatedPreferred)
{
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
- else
- {
- return AllocateDedicatedMemory(
+ res = AllocateDedicatedMemory(
+ pool,
size,
suballocType,
+ dedicatedAllocations,
memTypeIndex,
- (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
(finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
+ (finalCreateInfo.flags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0,
+ (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_CAN_ALIAS_BIT) != 0,
finalCreateInfo.pUserData,
finalCreateInfo.priority,
dedicatedBuffer,
- dedicatedBufferUsage,
dedicatedImage,
+ dedicatedBufferImageUsage,
allocationCount,
- pAllocations);
- }
- }
- else
- {
- VkResult res = blockVector->Allocate(
- m_CurrentFrameIndex.load(),
- size,
- alignment,
- finalCreateInfo,
- suballocType,
- allocationCount,
- pAllocations);
- if(res == VK_SUCCESS)
- {
- return res;
- }
-
- // 5. Try dedicated memory.
- if((finalCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
- {
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
-
- // Protection against creating each allocation as dedicated when we reach or exceed heap size/budget,
- // which can quickly deplete maxMemoryAllocationCount: Don't try dedicated allocations when above
- // 3/4 of the maximum allocation count.
- if(m_DeviceMemoryCount.load() > m_PhysicalDeviceProperties.limits.maxMemoryAllocationCount * 3 / 4)
- {
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
-
- res = AllocateDedicatedMemory(
- size,
- suballocType,
- memTypeIndex,
- (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0,
- (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0,
- (finalCreateInfo.flags & VMA_ALLOCATION_CREATE_USER_DATA_COPY_STRING_BIT) != 0,
- finalCreateInfo.pUserData,
- finalCreateInfo.priority,
- dedicatedBuffer,
- dedicatedBufferUsage,
- dedicatedImage,
- allocationCount,
- pAllocations);
- if(res == VK_SUCCESS)
- {
- // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
- VMA_DEBUG_LOG(" Allocated as DedicatedMemory");
- return VK_SUCCESS;
- }
- else
- {
- // Everything failed: Return error code.
- VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
- return res;
+ pAllocations,
+ blockVector.GetAllocationNextPtr());
+ if(res == VK_SUCCESS)
+ {
+ // Succeeded: AllocateDedicatedMemory function already filld pMemory, nothing more to do here.
+ VMA_DEBUG_LOG(" Allocated as DedicatedMemory");
+ return VK_SUCCESS;
+ }
}
+ // Everything failed: Return error code.
+ VMA_DEBUG_LOG(" vkAllocateMemory FAILED");
+ return res;
}
}
VkResult VmaAllocator_T::AllocateDedicatedMemory(
+ VmaPool pool,
VkDeviceSize size,
VmaSuballocationType suballocType,
+ VmaDedicatedAllocationList& dedicatedAllocations,
uint32_t memTypeIndex,
- bool withinBudget,
bool map,
bool isUserDataString,
+ bool isMappingAllowed,
+ bool canAliasMemory,
void* pUserData,
float priority,
VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage,
VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage,
size_t allocationCount,
- VmaAllocation* pAllocations)
+ VmaAllocation* pAllocations,
+ const void* pNextChain)
{
VMA_ASSERT(allocationCount > 0 && pAllocations);
- if(withinBudget)
- {
- const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
- VmaBudget heapBudget = {};
- GetBudget(&heapBudget, heapIndex, 1);
- if(heapBudget.usage + size * allocationCount > heapBudget.budget)
- {
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
- }
-
VkMemoryAllocateInfo allocInfo = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
allocInfo.memoryTypeIndex = memTypeIndex;
allocInfo.allocationSize = size;
+ allocInfo.pNext = pNextChain;
#if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
VkMemoryDedicatedAllocateInfoKHR dedicatedAllocInfo = { VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR };
- if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
+ if(!canAliasMemory)
{
- if(dedicatedBuffer != VK_NULL_HANDLE)
+ if(m_UseKhrDedicatedAllocation || m_VulkanApiVersion >= VK_MAKE_VERSION(1, 1, 0))
{
- VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
- dedicatedAllocInfo.buffer = dedicatedBuffer;
- VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
- }
- else if(dedicatedImage != VK_NULL_HANDLE)
- {
- dedicatedAllocInfo.image = dedicatedImage;
- VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
+ if(dedicatedBuffer != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(dedicatedImage == VK_NULL_HANDLE);
+ dedicatedAllocInfo.buffer = dedicatedBuffer;
+ VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
+ }
+ else if(dedicatedImage != VK_NULL_HANDLE)
+ {
+ dedicatedAllocInfo.image = dedicatedImage;
+ VmaPnextChainPushFront(&allocInfo, &dedicatedAllocInfo);
+ }
}
}
#endif // #if VMA_DEDICATED_ALLOCATION || VMA_VULKAN_VERSION >= 1001000
@@ -16717,8 +14617,8 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
bool canContainBufferWithDeviceAddress = true;
if(dedicatedBuffer != VK_NULL_HANDLE)
{
- canContainBufferWithDeviceAddress = dedicatedBufferUsage == UINT32_MAX || // Usage flags unknown
- (dedicatedBufferUsage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0;
+ canContainBufferWithDeviceAddress = dedicatedBufferImageUsage == UINT32_MAX || // Usage flags unknown
+ (dedicatedBufferImageUsage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) != 0;
}
else if(dedicatedImage != VK_NULL_HANDLE)
{
@@ -16736,6 +14636,7 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
VkMemoryPriorityAllocateInfoEXT priorityInfo = { VK_STRUCTURE_TYPE_MEMORY_PRIORITY_ALLOCATE_INFO_EXT };
if(m_UseExtMemoryPriority)
{
+ VMA_ASSERT(priority >= 0.f && priority <= 1.f);
priorityInfo.priority = priority;
VmaPnextChainPushFront(&allocInfo, &priorityInfo);
}
@@ -16756,12 +14657,14 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
{
res = AllocateDedicatedMemoryPage(
+ pool,
size,
suballocType,
memTypeIndex,
allocInfo,
map,
isUserDataString,
+ isMappingAllowed,
pUserData,
pAllocations + allocIndex);
if(res != VK_SUCCESS)
@@ -16772,16 +14675,10 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
if(res == VK_SUCCESS)
{
- // Register them in m_DedicatedAllocations.
+ for (allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
{
- VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
- DedicatedAllocationLinkedList& dedicatedAllocations = m_DedicatedAllocations[memTypeIndex];
- for(allocIndex = 0; allocIndex < allocationCount; ++allocIndex)
- {
- dedicatedAllocations.PushBack(pAllocations[allocIndex]);
- }
+ dedicatedAllocations.Register(pAllocations[allocIndex]);
}
-
VMA_DEBUG_LOG(" Allocated DedicatedMemory Count=%zu, MemoryTypeIndex=#%u", allocationCount, memTypeIndex);
}
else
@@ -16804,7 +14701,6 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
FreeVulkanMemory(memTypeIndex, currAlloc->GetSize(), hMemory);
m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), currAlloc->GetSize());
- currAlloc->SetUserData(this, VMA_NULL);
m_AllocationObjectAllocator.Free(currAlloc);
}
@@ -16815,12 +14711,14 @@ VkResult VmaAllocator_T::AllocateDedicatedMemory(
}
VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
+ VmaPool pool,
VkDeviceSize size,
VmaSuballocationType suballocType,
uint32_t memTypeIndex,
const VkMemoryAllocateInfo& allocInfo,
bool map,
bool isUserDataString,
+ bool isMappingAllowed,
void* pUserData,
VmaAllocation* pAllocation)
{
@@ -16850,9 +14748,12 @@ VkResult VmaAllocator_T::AllocateDedicatedMemoryPage(
}
}
- *pAllocation = m_AllocationObjectAllocator.Allocate(m_CurrentFrameIndex.load(), isUserDataString);
- (*pAllocation)->InitDedicatedAllocation(memTypeIndex, hMemory, suballocType, pMappedData, size);
- (*pAllocation)->SetUserData(this, pUserData);
+ *pAllocation = m_AllocationObjectAllocator.Allocate(isMappingAllowed);
+ (*pAllocation)->InitDedicatedAllocation(pool, memTypeIndex, hMemory, suballocType, pMappedData, size);
+ if (isUserDataString)
+ (*pAllocation)->SetName(this, (const char*)pUserData);
+ else
+ (*pAllocation)->SetUserData(this, pUserData);
m_Budget.AddAllocation(MemoryTypeIndexToHeapIndex(memTypeIndex), size);
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
{
@@ -16926,74 +14827,200 @@ void VmaAllocator_T::GetImageMemoryRequirements(
}
}
-VkResult VmaAllocator_T::AllocateMemory(
- const VkMemoryRequirements& vkMemReq,
- bool requiresDedicatedAllocation,
- bool prefersDedicatedAllocation,
- VkBuffer dedicatedBuffer,
- VkBufferUsageFlags dedicatedBufferUsage,
- VkImage dedicatedImage,
- const VmaAllocationCreateInfo& createInfo,
- VmaSuballocationType suballocType,
- size_t allocationCount,
- VmaAllocation* pAllocations)
+VkResult VmaAllocator_T::FindMemoryTypeIndex(
+ uint32_t memoryTypeBits,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkFlags bufImgUsage,
+ uint32_t* pMemoryTypeIndex) const
{
- memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+ memoryTypeBits &= GetGlobalMemoryTypeBits();
- VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));
+ if(pAllocationCreateInfo->memoryTypeBits != 0)
+ {
+ memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;
+ }
- if(vkMemReq.size == 0)
+ VkMemoryPropertyFlags requiredFlags = 0, preferredFlags = 0, notPreferredFlags = 0;
+ if(!FindMemoryPreferences(
+ IsIntegratedGpu(),
+ *pAllocationCreateInfo,
+ bufImgUsage,
+ requiredFlags, preferredFlags, notPreferredFlags))
{
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
- if((createInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
- (createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+
+ *pMemoryTypeIndex = UINT32_MAX;
+ uint32_t minCost = UINT32_MAX;
+ for(uint32_t memTypeIndex = 0, memTypeBit = 1;
+ memTypeIndex < GetMemoryTypeCount();
+ ++memTypeIndex, memTypeBit <<= 1)
{
- VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.");
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ // This memory type is acceptable according to memoryTypeBits bitmask.
+ if((memTypeBit & memoryTypeBits) != 0)
+ {
+ const VkMemoryPropertyFlags currFlags =
+ m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
+ // This memory type contains requiredFlags.
+ if((requiredFlags & ~currFlags) == 0)
+ {
+ // Calculate cost as number of bits from preferredFlags not present in this memory type.
+ uint32_t currCost = VMA_COUNT_BITS_SET(preferredFlags & ~currFlags) +
+ VMA_COUNT_BITS_SET(currFlags & notPreferredFlags);
+ // Remember memory type with lowest cost.
+ if(currCost < minCost)
+ {
+ *pMemoryTypeIndex = memTypeIndex;
+ if(currCost == 0)
+ {
+ return VK_SUCCESS;
+ }
+ minCost = currCost;
+ }
+ }
+ }
}
- if((createInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
- (createInfo.flags & VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT) != 0)
+ return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;
+}
+
+VkResult VmaAllocator_T::CalcMemTypeParams(
+ VmaAllocationCreateInfo& inoutCreateInfo,
+ uint32_t memTypeIndex,
+ VkDeviceSize size,
+ size_t allocationCount)
+{
+ // If memory type is not HOST_VISIBLE, disable MAPPED.
+ if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
+ (m_MemProps.memoryTypes[memTypeIndex].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
{
- VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_MAPPED_BIT together with VMA_ALLOCATION_CREATE_CAN_BECOME_LOST_BIT is invalid.");
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ inoutCreateInfo.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
}
- if(requiresDedicatedAllocation)
+
+ if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
+ (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT) != 0)
{
- if((createInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
+ VmaBudget heapBudget = {};
+ GetHeapBudgets(&heapBudget, heapIndex, 1);
+ if(heapBudget.usage + size * allocationCount > heapBudget.budget)
{
- VMA_ASSERT(0 && "VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT specified while dedicated allocation is required.");
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
- if(createInfo.pool != VK_NULL_HANDLE)
+ }
+ return VK_SUCCESS;
+}
+
+VkResult VmaAllocator_T::CalcAllocationParams(
+ VmaAllocationCreateInfo& inoutCreateInfo,
+ bool dedicatedRequired,
+ bool dedicatedPreferred)
+{
+ VMA_ASSERT((inoutCreateInfo.flags &
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) !=
+ (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT) &&
+ "Specifying both flags VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT and VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT is incorrect.");
+ VMA_ASSERT((((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT) == 0 ||
+ (inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0)) &&
+ "Specifying VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT requires also VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.");
+ if(inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE || inoutCreateInfo.usage == VMA_MEMORY_USAGE_AUTO_PREFER_HOST)
+ {
+ if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0)
{
- VMA_ASSERT(0 && "Pool specified while dedicated allocation is required.");
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ VMA_ASSERT((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) != 0 &&
+ "When using VMA_ALLOCATION_CREATE_MAPPED_BIT and usage = VMA_MEMORY_USAGE_AUTO*, you must also specify VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.");
}
}
- if((createInfo.pool != VK_NULL_HANDLE) &&
- ((createInfo.flags & (VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT)) != 0))
+
+ // If memory is lazily allocated, it should be always dedicated.
+ if(dedicatedRequired ||
+ inoutCreateInfo.usage == VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED)
{
- VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT when pool != null is invalid.");
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
}
- if(createInfo.pool != VK_NULL_HANDLE)
+ if(inoutCreateInfo.pool != VK_NULL_HANDLE)
{
- VmaAllocationCreateInfo createInfoForPool = createInfo;
- // If memory type is not HOST_VISIBLE, disable MAPPED.
- if((createInfoForPool.flags & VMA_ALLOCATION_CREATE_MAPPED_BIT) != 0 &&
- (m_MemProps.memoryTypes[createInfo.pool->m_BlockVector.GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
+ if(inoutCreateInfo.pool->m_BlockVector.HasExplicitBlockSize() &&
+ (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0)
{
- createInfoForPool.flags &= ~VMA_ALLOCATION_CREATE_MAPPED_BIT;
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT while current custom pool doesn't support dedicated allocations.");
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
+ inoutCreateInfo.priority = inoutCreateInfo.pool->m_BlockVector.GetPriority();
+ }
+
+ if((inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT) != 0 &&
+ (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ VMA_ASSERT(0 && "Specifying VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT together with VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT makes no sense.");
+ return VK_ERROR_FEATURE_NOT_PRESENT;
+ }
+
+ if(VMA_DEBUG_ALWAYS_DEDICATED_MEMORY &&
+ (inoutCreateInfo.flags & VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT) != 0)
+ {
+ inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+ }
+
+ // Non-auto USAGE values imply HOST_ACCESS flags.
+ // And so does VMA_MEMORY_USAGE_UNKNOWN because it is used with custom pools.
+ // Which specific flag is used doesn't matter. They change things only when used with VMA_MEMORY_USAGE_AUTO*.
+ // Otherwise they just protect from assert on mapping.
+ if(inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO &&
+ inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE &&
+ inoutCreateInfo.usage != VMA_MEMORY_USAGE_AUTO_PREFER_HOST)
+ {
+ if((inoutCreateInfo.flags & (VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT)) == 0)
+ {
+ inoutCreateInfo.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
+ }
+ }
+
+ return VK_SUCCESS;
+}
+
+VkResult VmaAllocator_T::AllocateMemory(
+ const VkMemoryRequirements& vkMemReq,
+ bool requiresDedicatedAllocation,
+ bool prefersDedicatedAllocation,
+ VkBuffer dedicatedBuffer,
+ VkImage dedicatedImage,
+ VkFlags dedicatedBufferImageUsage,
+ const VmaAllocationCreateInfo& createInfo,
+ VmaSuballocationType suballocType,
+ size_t allocationCount,
+ VmaAllocation* pAllocations)
+{
+ memset(pAllocations, 0, sizeof(VmaAllocation) * allocationCount);
+
+ VMA_ASSERT(VmaIsPow2(vkMemReq.alignment));
+
+ if(vkMemReq.size == 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ VmaAllocationCreateInfo createInfoFinal = createInfo;
+ VkResult res = CalcAllocationParams(createInfoFinal, requiresDedicatedAllocation, prefersDedicatedAllocation);
+ if(res != VK_SUCCESS)
+ return res;
- return createInfo.pool->m_BlockVector.Allocate(
- m_CurrentFrameIndex.load(),
+ if(createInfoFinal.pool != VK_NULL_HANDLE)
+ {
+ VmaBlockVector& blockVector = createInfoFinal.pool->m_BlockVector;
+ return AllocateMemoryOfType(
+ createInfoFinal.pool,
vkMemReq.size,
vkMemReq.alignment,
- createInfoForPool,
+ prefersDedicatedAllocation,
+ dedicatedBuffer,
+ dedicatedImage,
+ dedicatedBufferImageUsage,
+ createInfoFinal,
+ blockVector.GetMemoryTypeIndex(),
suballocType,
+ createInfoFinal.pool->m_DedicatedAllocations,
+ blockVector,
allocationCount,
pAllocations);
}
@@ -17002,68 +15029,42 @@ VkResult VmaAllocator_T::AllocateMemory(
// Bit mask of memory Vulkan types acceptable for this allocation.
uint32_t memoryTypeBits = vkMemReq.memoryTypeBits;
uint32_t memTypeIndex = UINT32_MAX;
- VkResult res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
- if(res == VK_SUCCESS)
+ res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex);
+ // Can't find any single memory type matching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
+ if(res != VK_SUCCESS)
+ return res;
+ do
{
+ VmaBlockVector* blockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(blockVector && "Trying to use unsupported memory type!");
res = AllocateMemoryOfType(
+ VK_NULL_HANDLE,
vkMemReq.size,
vkMemReq.alignment,
requiresDedicatedAllocation || prefersDedicatedAllocation,
dedicatedBuffer,
- dedicatedBufferUsage,
dedicatedImage,
- createInfo,
+ dedicatedBufferImageUsage,
+ createInfoFinal,
memTypeIndex,
suballocType,
+ m_DedicatedAllocations[memTypeIndex],
+ *blockVector,
allocationCount,
pAllocations);
- // Succeeded on first try.
+ // Allocation succeeded
if(res == VK_SUCCESS)
- {
- return res;
- }
- // Allocation from this memory type failed. Try other compatible memory types.
- else
- {
- for(;;)
- {
- // Remove old memTypeIndex from list of possibilities.
- memoryTypeBits &= ~(1u << memTypeIndex);
- // Find alternative memTypeIndex.
- res = vmaFindMemoryTypeIndex(this, memoryTypeBits, &createInfo, &memTypeIndex);
- if(res == VK_SUCCESS)
- {
- res = AllocateMemoryOfType(
- vkMemReq.size,
- vkMemReq.alignment,
- requiresDedicatedAllocation || prefersDedicatedAllocation,
- dedicatedBuffer,
- dedicatedBufferUsage,
- dedicatedImage,
- createInfo,
- memTypeIndex,
- suballocType,
- allocationCount,
- pAllocations);
- // Allocation from this alternative memory type succeeded.
- if(res == VK_SUCCESS)
- {
- return res;
- }
- // else: Allocation from this memory type failed. Try next one - next loop iteration.
- }
- // No other matching memory type index could be found.
- else
- {
- // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
- }
- }
- }
- // Can't find any single memory type maching requirements. res is VK_ERROR_FEATURE_NOT_PRESENT.
- else
- return res;
+ return VK_SUCCESS;
+
+ // Remove old memTypeIndex from list of possibilities.
+ memoryTypeBits &= ~(1u << memTypeIndex);
+ // Find alternative memTypeIndex.
+ res = FindMemoryTypeIndex(memoryTypeBits, &createInfoFinal, dedicatedBufferImageUsage, &memTypeIndex);
+ } while(res == VK_SUCCESS);
+
+ // No other matching memory type index could be found.
+ // Not returning res, which is VK_ERROR_FEATURE_NOT_PRESENT, because we already failed to allocate once.
+ return VK_ERROR_OUT_OF_DEVICE_MEMORY;
}
}
@@ -17079,65 +15080,57 @@ void VmaAllocator_T::FreeMemory(
if(allocation != VK_NULL_HANDLE)
{
- if(TouchAllocation(allocation))
+ if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
{
- if(VMA_DEBUG_INITIALIZE_ALLOCATIONS)
- {
- FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
- }
+ FillAllocation(allocation, VMA_ALLOCATION_FILL_PATTERN_DESTROYED);
+ }
+
+ allocation->FreeName(this);
- switch(allocation->GetType())
+ switch(allocation->GetType())
+ {
+ case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
{
- case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
+ VmaBlockVector* pBlockVector = VMA_NULL;
+ VmaPool hPool = allocation->GetParentPool();
+ if(hPool != VK_NULL_HANDLE)
{
- VmaBlockVector* pBlockVector = VMA_NULL;
- VmaPool hPool = allocation->GetBlock()->GetParentPool();
- if(hPool != VK_NULL_HANDLE)
- {
- pBlockVector = &hPool->m_BlockVector;
- }
- else
- {
- pBlockVector = allocation->GetBlock()->GetParentBlockVector();
- }
- pBlockVector->Free(allocation);
+ pBlockVector = &hPool->m_BlockVector;
}
- break;
- case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
- FreeDedicatedMemory(allocation);
- break;
- default:
- VMA_ASSERT(0);
+ else
+ {
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ pBlockVector = m_pBlockVectors[memTypeIndex];
+ VMA_ASSERT(pBlockVector && "Trying to free memory of unsupported type!");
+ }
+ pBlockVector->Free(allocation);
}
+ break;
+ case VmaAllocation_T::ALLOCATION_TYPE_DEDICATED:
+ FreeDedicatedMemory(allocation);
+ break;
+ default:
+ VMA_ASSERT(0);
}
-
- // Do this regardless of whether the allocation is lost. Lost allocations still account to Budget.AllocationBytes.
- m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
- allocation->SetUserData(this, VMA_NULL);
- m_AllocationObjectAllocator.Free(allocation);
}
}
}
-void VmaAllocator_T::CalculateStats(VmaStats* pStats)
+void VmaAllocator_T::CalculateStatistics(VmaTotalStatistics* pStats)
{
// Initialize.
- InitStatInfo(pStats->total);
- for(size_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
- InitStatInfo(pStats->memoryType[i]);
- for(size_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
- InitStatInfo(pStats->memoryHeap[i]);
+ VmaClearDetailedStatistics(pStats->total);
+ for(uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i)
+ VmaClearDetailedStatistics(pStats->memoryType[i]);
+ for(uint32_t i = 0; i < VK_MAX_MEMORY_HEAPS; ++i)
+ VmaClearDetailedStatistics(pStats->memoryHeap[i]);
// Process default pools.
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
- VMA_ASSERT(pBlockVector);
- pBlockVector->AddStats(pStats);
-
- VmaBlockVector* const pSmallBufferBlockVector = m_pSmallBufferBlockVectors[memTypeIndex];
- VMA_ASSERT(pSmallBufferBlockVector);
- pSmallBufferBlockVector->AddStats(pStats);
+ if (pBlockVector != VMA_NULL)
+ pBlockVector->AddDetailedStatistics(pStats->memoryType[memTypeIndex]);
}
// Process custom pools.
@@ -17145,36 +15138,37 @@ void VmaAllocator_T::CalculateStats(VmaStats* pStats)
VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
{
- pool->m_BlockVector.AddStats(pStats);
+ VmaBlockVector& blockVector = pool->m_BlockVector;
+ const uint32_t memTypeIndex = blockVector.GetMemoryTypeIndex();
+ blockVector.AddDetailedStatistics(pStats->memoryType[memTypeIndex]);
+ pool->m_DedicatedAllocations.AddDetailedStatistics(pStats->memoryType[memTypeIndex]);
}
}
// Process dedicated allocations.
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
- const uint32_t memHeapIndex = MemoryTypeIndexToHeapIndex(memTypeIndex);
- VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
- DedicatedAllocationLinkedList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex];
- for(VmaAllocation alloc = dedicatedAllocList.Front();
- alloc != VMA_NULL; alloc = dedicatedAllocList.GetNext(alloc))
- {
- VmaStatInfo allocationStatInfo;
- alloc->DedicatedAllocCalcStatsInfo(allocationStatInfo);
- VmaAddStatInfo(pStats->total, allocationStatInfo);
- VmaAddStatInfo(pStats->memoryType[memTypeIndex], allocationStatInfo);
- VmaAddStatInfo(pStats->memoryHeap[memHeapIndex], allocationStatInfo);
- }
+ m_DedicatedAllocations[memTypeIndex].AddDetailedStatistics(pStats->memoryType[memTypeIndex]);
}
- // Postprocess.
- VmaPostprocessCalcStatInfo(pStats->total);
- for(size_t i = 0; i < GetMemoryTypeCount(); ++i)
- VmaPostprocessCalcStatInfo(pStats->memoryType[i]);
- for(size_t i = 0; i < GetMemoryHeapCount(); ++i)
- VmaPostprocessCalcStatInfo(pStats->memoryHeap[i]);
+ // Sum from memory types to memory heaps.
+ for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ {
+ const uint32_t memHeapIndex = m_MemProps.memoryTypes[memTypeIndex].heapIndex;
+ VmaAddDetailedStatistics(pStats->memoryHeap[memHeapIndex], pStats->memoryType[memTypeIndex]);
+ }
+
+ // Sum from memory heaps to total.
+ for(uint32_t memHeapIndex = 0; memHeapIndex < GetMemoryHeapCount(); ++memHeapIndex)
+ VmaAddDetailedStatistics(pStats->total, pStats->memoryHeap[memHeapIndex]);
+
+ VMA_ASSERT(pStats->total.statistics.allocationCount == 0 ||
+ pStats->total.allocationSizeMax >= pStats->total.allocationSizeMin);
+ VMA_ASSERT(pStats->total.unusedRangeCount == 0 ||
+ pStats->total.unusedRangeSizeMax >= pStats->total.unusedRangeSizeMin);
}
-void VmaAllocator_T::GetBudget(VmaBudget* outBudget, uint32_t firstHeap, uint32_t heapCount)
+void VmaAllocator_T::GetHeapBudgets(VmaBudget* outBudgets, uint32_t firstHeap, uint32_t heapCount)
{
#if VMA_MEMORY_BUDGET
if(m_UseExtMemoryBudget)
@@ -17182,225 +15176,63 @@ void VmaAllocator_T::GetBudget(VmaBudget* outBudget, uint32_t firstHeap, uint32_
if(m_Budget.m_OperationsSinceBudgetFetch < 30)
{
VmaMutexLockRead lockRead(m_Budget.m_BudgetMutex, m_UseMutex);
- for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+ for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets)
{
const uint32_t heapIndex = firstHeap + i;
- outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
- outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+ outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex];
+ outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex];
+ outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex];
+ outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
- if(m_Budget.m_VulkanUsage[heapIndex] + outBudget->blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])
+ if(m_Budget.m_VulkanUsage[heapIndex] + outBudgets->statistics.blockBytes > m_Budget.m_BlockBytesAtBudgetFetch[heapIndex])
{
- outBudget->usage = m_Budget.m_VulkanUsage[heapIndex] +
- outBudget->blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];
+ outBudgets->usage = m_Budget.m_VulkanUsage[heapIndex] +
+ outBudgets->statistics.blockBytes - m_Budget.m_BlockBytesAtBudgetFetch[heapIndex];
}
else
{
- outBudget->usage = 0;
+ outBudgets->usage = 0;
}
// Have to take MIN with heap size because explicit HeapSizeLimit is included in it.
- outBudget->budget = VMA_MIN(
+ outBudgets->budget = VMA_MIN(
m_Budget.m_VulkanBudget[heapIndex], m_MemProps.memoryHeaps[heapIndex].size);
}
}
else
{
UpdateVulkanBudget(); // Outside of mutex lock
- GetBudget(outBudget, firstHeap, heapCount); // Recursion
+ GetHeapBudgets(outBudgets, firstHeap, heapCount); // Recursion
}
}
else
#endif
{
- for(uint32_t i = 0; i < heapCount; ++i, ++outBudget)
+ for(uint32_t i = 0; i < heapCount; ++i, ++outBudgets)
{
const uint32_t heapIndex = firstHeap + i;
- outBudget->blockBytes = m_Budget.m_BlockBytes[heapIndex];
- outBudget->allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
+ outBudgets->statistics.blockCount = m_Budget.m_BlockCount[heapIndex];
+ outBudgets->statistics.allocationCount = m_Budget.m_AllocationCount[heapIndex];
+ outBudgets->statistics.blockBytes = m_Budget.m_BlockBytes[heapIndex];
+ outBudgets->statistics.allocationBytes = m_Budget.m_AllocationBytes[heapIndex];
- outBudget->usage = outBudget->blockBytes;
- outBudget->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.
+ outBudgets->usage = outBudgets->statistics.blockBytes;
+ outBudgets->budget = m_MemProps.memoryHeaps[heapIndex].size * 8 / 10; // 80% heuristics.
}
}
}
-static const uint32_t VMA_VENDOR_ID_AMD = 4098;
-
-VkResult VmaAllocator_T::DefragmentationBegin(
- const VmaDefragmentationInfo2& info,
- VmaDefragmentationStats* pStats,
- VmaDefragmentationContext* pContext)
-{
- if(info.pAllocationsChanged != VMA_NULL)
- {
- memset(info.pAllocationsChanged, 0, info.allocationCount * sizeof(VkBool32));
- }
-
- *pContext = vma_new(this, VmaDefragmentationContext_T)(
- this, m_CurrentFrameIndex.load(), info.flags, pStats);
-
- (*pContext)->AddPools(info.poolCount, info.pPools);
- (*pContext)->AddAllocations(
- info.allocationCount, info.pAllocations, info.pAllocationsChanged);
-
- VkResult res = (*pContext)->Defragment(
- info.maxCpuBytesToMove, info.maxCpuAllocationsToMove,
- info.maxGpuBytesToMove, info.maxGpuAllocationsToMove,
- info.commandBuffer, pStats, info.flags);
-
- if(res != VK_NOT_READY)
- {
- vma_delete(this, *pContext);
- *pContext = VMA_NULL;
- }
-
- return res;
-}
-
-VkResult VmaAllocator_T::DefragmentationEnd(
- VmaDefragmentationContext context)
-{
- vma_delete(this, context);
- return VK_SUCCESS;
-}
-
-VkResult VmaAllocator_T::DefragmentationPassBegin(
- VmaDefragmentationPassInfo* pInfo,
- VmaDefragmentationContext context)
-{
- return context->DefragmentPassBegin(pInfo);
-}
-VkResult VmaAllocator_T::DefragmentationPassEnd(
- VmaDefragmentationContext context)
-{
- return context->DefragmentPassEnd();
-
-}
-
void VmaAllocator_T::GetAllocationInfo(VmaAllocation hAllocation, VmaAllocationInfo* pAllocationInfo)
{
- if(hAllocation->CanBecomeLost())
- {
- /*
- Warning: This is a carefully designed algorithm.
- Do not modify unless you really know what you're doing :)
- */
- const uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
- uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
- for(;;)
- {
- if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
- {
- pAllocationInfo->memoryType = UINT32_MAX;
- pAllocationInfo->deviceMemory = VK_NULL_HANDLE;
- pAllocationInfo->offset = 0;
- pAllocationInfo->size = hAllocation->GetSize();
- pAllocationInfo->pMappedData = VMA_NULL;
- pAllocationInfo->pUserData = hAllocation->GetUserData();
- return;
- }
- else if(localLastUseFrameIndex == localCurrFrameIndex)
- {
- pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
- pAllocationInfo->deviceMemory = hAllocation->GetMemory();
- pAllocationInfo->offset = hAllocation->GetOffset();
- pAllocationInfo->size = hAllocation->GetSize();
- pAllocationInfo->pMappedData = VMA_NULL;
- pAllocationInfo->pUserData = hAllocation->GetUserData();
- return;
- }
- else // Last use time earlier than current time.
- {
- if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
- {
- localLastUseFrameIndex = localCurrFrameIndex;
- }
- }
- }
- }
- else
- {
-#if VMA_STATS_STRING_ENABLED
- uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
- uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
- for(;;)
- {
- VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
- if(localLastUseFrameIndex == localCurrFrameIndex)
- {
- break;
- }
- else // Last use time earlier than current time.
- {
- if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
- {
- localLastUseFrameIndex = localCurrFrameIndex;
- }
- }
- }
-#endif
-
- pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
- pAllocationInfo->deviceMemory = hAllocation->GetMemory();
- pAllocationInfo->offset = hAllocation->GetOffset();
- pAllocationInfo->size = hAllocation->GetSize();
- pAllocationInfo->pMappedData = hAllocation->GetMappedData();
- pAllocationInfo->pUserData = hAllocation->GetUserData();
- }
-}
-
-bool VmaAllocator_T::TouchAllocation(VmaAllocation hAllocation)
-{
- // This is a stripped-down version of VmaAllocator_T::GetAllocationInfo.
- if(hAllocation->CanBecomeLost())
- {
- uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
- uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
- for(;;)
- {
- if(localLastUseFrameIndex == VMA_FRAME_INDEX_LOST)
- {
- return false;
- }
- else if(localLastUseFrameIndex == localCurrFrameIndex)
- {
- return true;
- }
- else // Last use time earlier than current time.
- {
- if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
- {
- localLastUseFrameIndex = localCurrFrameIndex;
- }
- }
- }
- }
- else
- {
-#if VMA_STATS_STRING_ENABLED
- uint32_t localCurrFrameIndex = m_CurrentFrameIndex.load();
- uint32_t localLastUseFrameIndex = hAllocation->GetLastUseFrameIndex();
- for(;;)
- {
- VMA_ASSERT(localLastUseFrameIndex != VMA_FRAME_INDEX_LOST);
- if(localLastUseFrameIndex == localCurrFrameIndex)
- {
- break;
- }
- else // Last use time earlier than current time.
- {
- if(hAllocation->CompareExchangeLastUseFrameIndex(localLastUseFrameIndex, localCurrFrameIndex))
- {
- localLastUseFrameIndex = localCurrFrameIndex;
- }
- }
- }
-#endif
-
- return true;
- }
+ pAllocationInfo->memoryType = hAllocation->GetMemoryTypeIndex();
+ pAllocationInfo->deviceMemory = hAllocation->GetMemory();
+ pAllocationInfo->offset = hAllocation->GetOffset();
+ pAllocationInfo->size = hAllocation->GetSize();
+ pAllocationInfo->pMappedData = hAllocation->GetMappedData();
+ pAllocationInfo->pUserData = hAllocation->GetUserData();
+ pAllocationInfo->pName = hAllocation->GetName();
}
VkResult VmaAllocator_T::CreatePool(const VmaPoolCreateInfo* pCreateInfo, VmaPool* pPool)
@@ -17467,9 +15299,18 @@ void VmaAllocator_T::DestroyPool(VmaPool pool)
vma_delete(this, pool);
}
-void VmaAllocator_T::GetPoolStats(VmaPool pool, VmaPoolStats* pPoolStats)
+void VmaAllocator_T::GetPoolStatistics(VmaPool pool, VmaStatistics* pPoolStats)
+{
+ VmaClearStatistics(*pPoolStats);
+ pool->m_BlockVector.AddStatistics(*pPoolStats);
+ pool->m_DedicatedAllocations.AddStatistics(*pPoolStats);
+}
+
+void VmaAllocator_T::CalculatePoolStatistics(VmaPool pool, VmaDetailedStatistics* pPoolStats)
{
- pool->m_BlockVector.GetPoolStats(pPoolStats);
+ VmaClearDetailedStatistics(*pPoolStats);
+ pool->m_BlockVector.AddDetailedStatistics(*pPoolStats);
+ pool->m_DedicatedAllocations.AddDetailedStatistics(*pPoolStats);
}
void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
@@ -17484,15 +15325,6 @@ void VmaAllocator_T::SetCurrentFrameIndex(uint32_t frameIndex)
#endif // #if VMA_MEMORY_BUDGET
}
-void VmaAllocator_T::MakePoolAllocationsLost(
- VmaPool hPool,
- size_t* pLostAllocationCount)
-{
- hPool->m_BlockVector.MakePoolAllocationsLost(
- m_CurrentFrameIndex.load(),
- pLostAllocationCount);
-}
-
VkResult VmaAllocator_T::CheckPoolCorruption(VmaPool hPool)
{
return hPool->m_BlockVector.CheckCorruption();
@@ -17505,10 +15337,9 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
// Process default pools.
for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
- if(((1u << memTypeIndex) & memoryTypeBits) != 0)
+ VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
+ if(pBlockVector != VMA_NULL)
{
- VmaBlockVector* const pBlockVector = m_pBlockVectors[memTypeIndex];
- VMA_ASSERT(pBlockVector);
VkResult localRes = pBlockVector->CheckCorruption();
switch(localRes)
{
@@ -17548,37 +15379,6 @@ VkResult VmaAllocator_T::CheckCorruption(uint32_t memoryTypeBits)
return finalRes;
}
-void VmaAllocator_T::CreateLostAllocation(VmaAllocation* pAllocation)
-{
- *pAllocation = m_AllocationObjectAllocator.Allocate(VMA_FRAME_INDEX_LOST, false);
- (*pAllocation)->InitLost();
-}
-
-// An object that increments given atomic but decrements it back in the destructor unless Commit() is called.
-template<typename T>
-struct AtomicTransactionalIncrement
-{
-public:
- typedef std::atomic<T> AtomicT;
- ~AtomicTransactionalIncrement()
- {
- if(m_Atomic)
- --(*m_Atomic);
- }
- T Increment(AtomicT* atomic)
- {
- m_Atomic = atomic;
- return m_Atomic->fetch_add(1);
- }
- void Commit()
- {
- m_Atomic = nullptr;
- }
-
-private:
- AtomicT* m_Atomic = nullptr;
-};
-
VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAllocateInfo, VkDeviceMemory* pMemory)
{
AtomicTransactionalIncrement<uint32_t> deviceMemoryCountIncrement;
@@ -17614,6 +15414,7 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc
{
m_Budget.m_BlockBytes[heapIndex] += pAllocateInfo->allocationSize;
}
+ ++m_Budget.m_BlockCount[heapIndex];
// VULKAN CALL vkAllocateMemory.
VkResult res = (*m_VulkanFunctions.vkAllocateMemory)(m_hDevice, pAllocateInfo, GetAllocationCallbacks(), pMemory);
@@ -17634,6 +15435,7 @@ VkResult VmaAllocator_T::AllocateVulkanMemory(const VkMemoryAllocateInfo* pAlloc
}
else
{
+ --m_Budget.m_BlockCount[heapIndex];
m_Budget.m_BlockBytes[heapIndex] -= pAllocateInfo->allocationSize;
}
@@ -17651,7 +15453,9 @@ void VmaAllocator_T::FreeVulkanMemory(uint32_t memoryType, VkDeviceSize size, Vk
// VULKAN CALL vkFreeMemory.
(*m_VulkanFunctions.vkFreeMemory)(m_hDevice, hMemory, GetAllocationCallbacks());
- m_Budget.m_BlockBytes[MemoryTypeIndexToHeapIndex(memoryType)] -= size;
+ const uint32_t heapIndex = MemoryTypeIndexToHeapIndex(memoryType);
+ --m_Budget.m_BlockCount[heapIndex];
+ m_Budget.m_BlockBytes[heapIndex] -= size;
--m_DeviceMemoryCount;
}
@@ -17720,11 +15524,6 @@ VkResult VmaAllocator_T::BindVulkanImage(
VkResult VmaAllocator_T::Map(VmaAllocation hAllocation, void** ppData)
{
- if(hAllocation->CanBecomeLost())
- {
- return VK_ERROR_MEMORY_MAP_FAILED;
- }
-
switch(hAllocation->GetType())
{
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
@@ -17781,7 +15580,7 @@ VkResult VmaAllocator_T::BindBufferMemory(
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
{
VmaDeviceMemoryBlock* const pBlock = hAllocation->GetBlock();
- VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block. Is the allocation lost?");
+ VMA_ASSERT(pBlock && "Binding buffer to allocation that doesn't belong to any block.");
res = pBlock->BindBufferMemory(this, hAllocation, allocationLocalOffset, hBuffer, pNext);
break;
}
@@ -17806,7 +15605,7 @@ VkResult VmaAllocator_T::BindImageMemory(
case VmaAllocation_T::ALLOCATION_TYPE_BLOCK:
{
VmaDeviceMemoryBlock* pBlock = hAllocation->GetBlock();
- VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block. Is the allocation lost?");
+ VMA_ASSERT(pBlock && "Binding image to allocation that doesn't belong to any block.");
res = pBlock->BindImageMemory(this, hAllocation, allocationLocalOffset, hImage, pNext);
break;
}
@@ -17888,10 +15687,16 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
VMA_ASSERT(allocation && allocation->GetType() == VmaAllocation_T::ALLOCATION_TYPE_DEDICATED);
const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ VmaPool parentPool = allocation->GetParentPool();
+ if(parentPool == VK_NULL_HANDLE)
{
- VmaMutexLockWrite lock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
- DedicatedAllocationLinkedList& dedicatedAllocations = m_DedicatedAllocations[memTypeIndex];
- dedicatedAllocations.Remove(allocation);
+ // Default pool
+ m_DedicatedAllocations[memTypeIndex].Unregister(allocation);
+ }
+ else
+ {
+ // Custom pool
+ parentPool->m_DedicatedAllocations.Unregister(allocation);
}
VkDeviceMemory hMemory = allocation->GetMemory();
@@ -17908,6 +15713,9 @@ void VmaAllocator_T::FreeDedicatedMemory(const VmaAllocation allocation)
FreeVulkanMemory(memTypeIndex, allocation->GetSize(), hMemory);
+ m_Budget.RemoveAllocation(MemoryTypeIndexToHeapIndex(allocation->GetMemoryTypeIndex()), allocation->GetSize());
+ m_AllocationObjectAllocator.Free(allocation);
+
VMA_DEBUG_LOG(" Freed DedicatedMemory MemoryTypeIndex=%u", memTypeIndex);
}
@@ -18022,7 +15830,6 @@ bool VmaAllocator_T::GetFlushOrInvalidateRange(
}
#if VMA_MEMORY_BUDGET
-
void VmaAllocator_T::UpdateVulkanBudget()
{
VMA_ASSERT(m_UseExtMemoryBudget);
@@ -18060,13 +15867,12 @@ void VmaAllocator_T::UpdateVulkanBudget()
m_Budget.m_OperationsSinceBudgetFetch = 0;
}
}
-
-#endif // #if VMA_MEMORY_BUDGET
+#endif // VMA_MEMORY_BUDGET
void VmaAllocator_T::FillAllocation(const VmaAllocation hAllocation, uint8_t pattern)
{
if(VMA_DEBUG_INITIALIZE_ALLOCATIONS &&
- !hAllocation->CanBecomeLost() &&
+ hAllocation->IsMappingAllowed() &&
(m_MemProps.memoryTypes[hAllocation->GetMemoryTypeIndex()].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
void* pData = VMA_NULL;
@@ -18096,134 +15902,114 @@ uint32_t VmaAllocator_T::GetGpuDefragmentationMemoryTypeBits()
}
#if VMA_STATS_STRING_ENABLED
-
void VmaAllocator_T::PrintDetailedMap(VmaJsonWriter& json)
{
- bool dedicatedAllocationsStarted = false;
- for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ json.WriteString("DefaultPools");
+ json.BeginObject();
{
- VmaMutexLockRead dedicatedAllocationsLock(m_DedicatedAllocationsMutex[memTypeIndex], m_UseMutex);
- DedicatedAllocationLinkedList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex];
- if(!dedicatedAllocList.IsEmpty())
+ for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
- if(dedicatedAllocationsStarted == false)
+ VmaBlockVector* pBlockVector = m_pBlockVectors[memTypeIndex];
+ VmaDedicatedAllocationList& dedicatedAllocList = m_DedicatedAllocations[memTypeIndex];
+ if (pBlockVector != VMA_NULL)
{
- dedicatedAllocationsStarted = true;
- json.WriteString("DedicatedAllocations");
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
json.BeginObject();
- }
-
- json.BeginString("Type ");
- json.ContinueString(memTypeIndex);
- json.EndString();
+ {
+ json.WriteString("PreferredBlockSize");
+ json.WriteNumber(pBlockVector->GetPreferredBlockSize());
- json.BeginArray();
+ json.WriteString("Blocks");
+ pBlockVector->PrintDetailedMap(json);
- for(VmaAllocation alloc = dedicatedAllocList.Front();
- alloc != VMA_NULL; alloc = dedicatedAllocList.GetNext(alloc))
- {
- json.BeginObject(true);
- alloc->PrintParameters(json);
+ json.WriteString("DedicatedAllocations");
+ dedicatedAllocList.BuildStatsString(json);
+ }
json.EndObject();
}
-
- json.EndArray();
}
}
- if(dedicatedAllocationsStarted)
- {
- json.EndObject();
- }
+ json.EndObject();
- // Default pools
+ json.WriteString("CustomPools");
+ json.BeginObject();
{
- bool allocationsStarted = false;
- for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
+ VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
+ if (!m_Pools.IsEmpty())
{
- if(m_pBlockVectors[memTypeIndex]->IsEmpty() == false)
+ for (uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
{
- if(allocationsStarted == false)
+ bool displayType = true;
+ size_t index = 0;
+ for (VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
{
- allocationsStarted = true;
- json.WriteString("DefaultPools");
- json.BeginObject();
- }
-
- json.BeginString("Type ");
- json.ContinueString(memTypeIndex);
- json.EndString();
-
- m_pBlockVectors[memTypeIndex]->PrintDetailedMap(json);
- }
- }
- if(allocationsStarted)
- {
- json.EndObject();
- }
- }
+ VmaBlockVector& blockVector = pool->m_BlockVector;
+ if (blockVector.GetMemoryTypeIndex() == memTypeIndex)
+ {
+ if (displayType)
+ {
+ json.BeginString("Type ");
+ json.ContinueString(memTypeIndex);
+ json.EndString();
+ json.BeginArray();
+ displayType = false;
+ }
- // Small buffer pools
- {
- bool allocationsStarted = false;
- for(uint32_t memTypeIndex = 0; memTypeIndex < GetMemoryTypeCount(); ++memTypeIndex)
- {
- if(m_pSmallBufferBlockVectors[memTypeIndex]->IsEmpty() == false)
- {
- if(allocationsStarted == false)
- {
- allocationsStarted = true;
- json.WriteString("SmallBufferPools");
- json.BeginObject();
- }
+ json.BeginObject();
+ {
+ json.WriteString("Name");
+ json.BeginString();
+ json.ContinueString_Size(index++);
+ if (pool->GetName())
+ {
+ json.ContinueString(" - ");
+ json.ContinueString(pool->GetName());
+ }
+ json.EndString();
- json.BeginString("Type ");
- json.ContinueString(memTypeIndex);
- json.EndString();
+ json.WriteString("PreferredBlockSize");
+ json.WriteNumber(blockVector.GetPreferredBlockSize());
- m_pSmallBufferBlockVectors[memTypeIndex]->PrintDetailedMap(json);
- }
- }
- if(allocationsStarted)
- {
- json.EndObject();
- }
- }
+ json.WriteString("Blocks");
+ blockVector.PrintDetailedMap(json);
- // Custom pools
- {
- VmaMutexLockRead lock(m_PoolsMutex, m_UseMutex);
- if(!m_Pools.IsEmpty())
- {
- json.WriteString("Pools");
- json.BeginObject();
- for(VmaPool pool = m_Pools.Front(); pool != VMA_NULL; pool = m_Pools.GetNext(pool))
- {
- json.BeginString();
- json.ContinueString(pool->GetId());
- json.EndString();
+ json.WriteString("DedicatedAllocations");
+ pool->m_DedicatedAllocations.BuildStatsString(json);
+ }
+ json.EndObject();
+ }
+ }
- pool->m_BlockVector.PrintDetailedMap(json);
+ if (!displayType)
+ json.EndArray();
}
- json.EndObject();
}
}
+ json.EndObject();
}
+#endif // VMA_STATS_STRING_ENABLED
+#endif // _VMA_ALLOCATOR_T_FUNCTIONS
-#endif // #if VMA_STATS_STRING_ENABLED
-
-////////////////////////////////////////////////////////////////////////////////
-// Public interface
+#ifndef _VMA_PUBLIC_INTERFACE
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAllocator(
const VmaAllocatorCreateInfo* pCreateInfo,
VmaAllocator* pAllocator)
{
VMA_ASSERT(pCreateInfo && pAllocator);
VMA_ASSERT(pCreateInfo->vulkanApiVersion == 0 ||
- (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 2));
+ (VK_VERSION_MAJOR(pCreateInfo->vulkanApiVersion) == 1 && VK_VERSION_MINOR(pCreateInfo->vulkanApiVersion) <= 3));
VMA_DEBUG_LOG("vmaCreateAllocator");
*pAllocator = vma_new(pCreateInfo->pAllocationCallbacks, VmaAllocator_T)(pCreateInfo);
- return (*pAllocator)->Init(pCreateInfo);
+ VkResult result = (*pAllocator)->Init(pCreateInfo);
+ if(result < 0)
+ {
+ vma_delete(pCreateInfo->pAllocationCallbacks, *pAllocator);
+ *pAllocator = VK_NULL_HANDLE;
+ }
+ return result;
}
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
@@ -18232,7 +16018,7 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyAllocator(
if(allocator != VK_NULL_HANDLE)
{
VMA_DEBUG_LOG("vmaDestroyAllocator");
- VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks;
+ VkAllocationCallbacks allocationCallbacks = allocator->m_AllocationCallbacks; // Have to copy the callbacks when destroying.
vma_delete(&allocationCallbacks, allocator);
}
}
@@ -18276,29 +16062,28 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetCurrentFrameIndex(
uint32_t frameIndex)
{
VMA_ASSERT(allocator);
- VMA_ASSERT(frameIndex != VMA_FRAME_INDEX_LOST);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
allocator->SetCurrentFrameIndex(frameIndex);
}
-VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStats(
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateStatistics(
VmaAllocator allocator,
- VmaStats* pStats)
+ VmaTotalStatistics* pStats)
{
VMA_ASSERT(allocator && pStats);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- allocator->CalculateStats(pStats);
+ allocator->CalculateStatistics(pStats);
}
-VMA_CALL_PRE void VMA_CALL_POST vmaGetBudget(
+VMA_CALL_PRE void VMA_CALL_POST vmaGetHeapBudgets(
VmaAllocator allocator,
- VmaBudget* pBudget)
+ VmaBudget* pBudgets)
{
- VMA_ASSERT(allocator && pBudget);
+ VMA_ASSERT(allocator && pBudgets);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- allocator->GetBudget(pBudget, 0, allocator->GetMemoryHeapCount());
+ allocator->GetHeapBudgets(pBudgets, 0, allocator->GetMemoryHeapCount());
}
#if VMA_STATS_STRING_ENABLED
@@ -18311,137 +16096,183 @@ VMA_CALL_PRE void VMA_CALL_POST vmaBuildStatsString(
VMA_ASSERT(allocator && ppStatsString);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- VmaStringBuilder sb(allocator);
+ VmaStringBuilder sb(allocator->GetAllocationCallbacks());
{
- VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);
- json.BeginObject();
-
- VmaBudget budget[VK_MAX_MEMORY_HEAPS];
- allocator->GetBudget(budget, 0, allocator->GetMemoryHeapCount());
-
- VmaStats stats;
- allocator->CalculateStats(&stats);
+ VmaBudget budgets[VK_MAX_MEMORY_HEAPS];
+ allocator->GetHeapBudgets(budgets, 0, allocator->GetMemoryHeapCount());
- json.WriteString("Total");
- VmaPrintStatInfo(json, stats.total);
+ VmaTotalStatistics stats;
+ allocator->CalculateStatistics(&stats);
- for(uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)
+ VmaJsonWriter json(allocator->GetAllocationCallbacks(), sb);
+ json.BeginObject();
{
- json.BeginString("Heap ");
- json.ContinueString(heapIndex);
- json.EndString();
+ json.WriteString("General");
json.BeginObject();
+ {
+ const VkPhysicalDeviceProperties& deviceProperties = allocator->m_PhysicalDeviceProperties;
+ const VkPhysicalDeviceMemoryProperties& memoryProperties = allocator->m_MemProps;
- json.WriteString("Size");
- json.WriteNumber(allocator->m_MemProps.memoryHeaps[heapIndex].size);
+ json.WriteString("API");
+ json.WriteString("Vulkan");
- json.WriteString("Flags");
- json.BeginArray(true);
- if((allocator->m_MemProps.memoryHeaps[heapIndex].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
- {
- json.WriteString("DEVICE_LOCAL");
- }
- json.EndArray();
+ json.WriteString("apiVersion");
+ json.BeginString();
+ json.ContinueString(VK_API_VERSION_MAJOR(deviceProperties.apiVersion));
+ json.ContinueString(".");
+ json.ContinueString(VK_API_VERSION_MINOR(deviceProperties.apiVersion));
+ json.ContinueString(".");
+ json.ContinueString(VK_API_VERSION_PATCH(deviceProperties.apiVersion));
+ json.EndString();
- json.WriteString("Budget");
- json.BeginObject();
- {
- json.WriteString("BlockBytes");
- json.WriteNumber(budget[heapIndex].blockBytes);
- json.WriteString("AllocationBytes");
- json.WriteNumber(budget[heapIndex].allocationBytes);
- json.WriteString("Usage");
- json.WriteNumber(budget[heapIndex].usage);
- json.WriteString("Budget");
- json.WriteNumber(budget[heapIndex].budget);
+ json.WriteString("GPU");
+ json.WriteString(deviceProperties.deviceName);
+ json.WriteString("deviceType");
+ json.WriteNumber(static_cast<uint32_t>(deviceProperties.deviceType));
+
+ json.WriteString("maxMemoryAllocationCount");
+ json.WriteNumber(deviceProperties.limits.maxMemoryAllocationCount);
+ json.WriteString("bufferImageGranularity");
+ json.WriteNumber(deviceProperties.limits.bufferImageGranularity);
+ json.WriteString("nonCoherentAtomSize");
+ json.WriteNumber(deviceProperties.limits.nonCoherentAtomSize);
+
+ json.WriteString("memoryHeapCount");
+ json.WriteNumber(memoryProperties.memoryHeapCount);
+ json.WriteString("memoryTypeCount");
+ json.WriteNumber(memoryProperties.memoryTypeCount);
}
json.EndObject();
-
- if(stats.memoryHeap[heapIndex].blockCount > 0)
- {
- json.WriteString("Stats");
- VmaPrintStatInfo(json, stats.memoryHeap[heapIndex]);
- }
-
- for(uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)
+ }
+ {
+ json.WriteString("Total");
+ VmaPrintDetailedStatistics(json, stats.total);
+ }
+ {
+ json.WriteString("MemoryInfo");
+ json.BeginObject();
{
- if(allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)
+ for (uint32_t heapIndex = 0; heapIndex < allocator->GetMemoryHeapCount(); ++heapIndex)
{
- json.BeginString("Type ");
- json.ContinueString(typeIndex);
+ json.BeginString("Heap ");
+ json.ContinueString(heapIndex);
json.EndString();
-
json.BeginObject();
-
- json.WriteString("Flags");
- json.BeginArray(true);
- VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;
- if((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
- {
- json.WriteString("DEVICE_LOCAL");
- }
- if((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
{
- json.WriteString("HOST_VISIBLE");
- }
- if((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
- {
- json.WriteString("HOST_COHERENT");
- }
- if((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
- {
- json.WriteString("HOST_CACHED");
- }
- if((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
- {
- json.WriteString("LAZILY_ALLOCATED");
- }
-#if VMA_VULKAN_VERSION >= 1001000
- if((flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0)
- {
- json.WriteString("PROTECTED");
- }
-#endif // #if VMA_VULKAN_VERSION >= 1001000
-#if VK_AMD_device_coherent_memory
- if((flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY) != 0)
- {
- json.WriteString("DEVICE_COHERENT");
- }
- if((flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY) != 0)
- {
- json.WriteString("DEVICE_UNCACHED");
- }
-#endif // #if VK_AMD_device_coherent_memory
- json.EndArray();
+ const VkMemoryHeap& heapInfo = allocator->m_MemProps.memoryHeaps[heapIndex];
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ {
+ if (heapInfo.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
+ json.WriteString("DEVICE_LOCAL");
+ #if VMA_VULKAN_VERSION >= 1001000
+ if (heapInfo.flags & VK_MEMORY_HEAP_MULTI_INSTANCE_BIT)
+ json.WriteString("MULTI_INSTANCE");
+ #endif
+
+ VkMemoryHeapFlags flags = heapInfo.flags &
+ ~(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
+ #if VMA_VULKAN_VERSION >= 1001000
+ | VK_MEMORY_HEAP_MULTI_INSTANCE_BIT
+ #endif
+ );
+ if (flags != 0)
+ json.WriteNumber(flags);
+ }
+ json.EndArray();
+
+ json.WriteString("Size");
+ json.WriteNumber(heapInfo.size);
+
+ json.WriteString("Budget");
+ json.BeginObject();
+ {
+ json.WriteString("BudgetBytes");
+ json.WriteNumber(budgets[heapIndex].budget);
+ json.WriteString("UsageBytes");
+ json.WriteNumber(budgets[heapIndex].usage);
+ }
+ json.EndObject();
- if(stats.memoryType[typeIndex].blockCount > 0)
- {
json.WriteString("Stats");
- VmaPrintStatInfo(json, stats.memoryType[typeIndex]);
- }
+ VmaPrintDetailedStatistics(json, stats.memoryHeap[heapIndex]);
+
+ json.WriteString("MemoryPools");
+ json.BeginObject();
+ {
+ for (uint32_t typeIndex = 0; typeIndex < allocator->GetMemoryTypeCount(); ++typeIndex)
+ {
+ if (allocator->MemoryTypeIndexToHeapIndex(typeIndex) == heapIndex)
+ {
+ json.BeginString("Type ");
+ json.ContinueString(typeIndex);
+ json.EndString();
+ json.BeginObject();
+ {
+ json.WriteString("Flags");
+ json.BeginArray(true);
+ {
+ VkMemoryPropertyFlags flags = allocator->m_MemProps.memoryTypes[typeIndex].propertyFlags;
+ if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ json.WriteString("DEVICE_LOCAL");
+ if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ json.WriteString("HOST_VISIBLE");
+ if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+ json.WriteString("HOST_COHERENT");
+ if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
+ json.WriteString("HOST_CACHED");
+ if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+ json.WriteString("LAZILY_ALLOCATED");
+ #if VMA_VULKAN_VERSION >= 1001000
+ if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT)
+ json.WriteString("PROTECTED");
+ #endif
+ #if VK_AMD_device_coherent_memory
+ if (flags & VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY)
+ json.WriteString("DEVICE_COHERENT_AMD");
+ if (flags & VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)
+ json.WriteString("DEVICE_UNCACHED_AMD");
+ #endif
+
+ flags &= ~(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
+ #if VMA_VULKAN_VERSION >= 1001000
+ | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
+ #endif
+ #if VK_AMD_device_coherent_memory
+ | VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY
+ | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY
+ #endif
+ | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+ | VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
+ if (flags != 0)
+ json.WriteNumber(flags);
+ }
+ json.EndArray();
+
+ json.WriteString("Stats");
+ VmaPrintDetailedStatistics(json, stats.memoryType[typeIndex]);
+ }
+ json.EndObject();
+ }
+ }
+ }
+ json.EndObject();
+ }
json.EndObject();
}
}
-
json.EndObject();
}
- if(detailedMap == VK_TRUE)
- {
+
+ if (detailedMap == VK_TRUE)
allocator->PrintDetailedMap(json);
- }
json.EndObject();
}
- const size_t len = sb.GetLength();
- char* const pChars = vma_new_array(allocator, char, len + 1);
- if(len > 0)
- {
- memcpy(pChars, sb.GetData(), len);
- }
- pChars[len] = '\0';
- *ppStatsString = pChars;
+ *ppStatsString = VmaCreateStringCopy(allocator->GetAllocationCallbacks(), sb.GetData(), sb.GetLength());
}
VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
@@ -18451,12 +16282,11 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeStatsString(
if(pStatsString != VMA_NULL)
{
VMA_ASSERT(allocator);
- size_t len = strlen(pStatsString);
- vma_delete_array(allocator, pStatsString, len + 1);
+ VmaFreeString(allocator->GetAllocationCallbacks(), pStatsString);
}
}
-#endif // #if VMA_STATS_STRING_ENABLED
+#endif // VMA_STATS_STRING_ENABLED
/*
This function is not protected by any mutex because it just reads immutable data.
@@ -18471,91 +16301,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndex(
VMA_ASSERT(pAllocationCreateInfo != VMA_NULL);
VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
- memoryTypeBits &= allocator->GetGlobalMemoryTypeBits();
-
- if(pAllocationCreateInfo->memoryTypeBits != 0)
- {
- memoryTypeBits &= pAllocationCreateInfo->memoryTypeBits;
- }
-
- uint32_t requiredFlags = pAllocationCreateInfo->requiredFlags;
- uint32_t preferredFlags = pAllocationCreateInfo->preferredFlags;
- uint32_t notPreferredFlags = 0;
-
- // Convert usage to requiredFlags and preferredFlags.
- switch(pAllocationCreateInfo->usage)
- {
- case VMA_MEMORY_USAGE_UNKNOWN:
- break;
- case VMA_MEMORY_USAGE_GPU_ONLY:
- if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
- {
- preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- }
- break;
- case VMA_MEMORY_USAGE_CPU_ONLY:
- requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
- break;
- case VMA_MEMORY_USAGE_CPU_TO_GPU:
- requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
- if(!allocator->IsIntegratedGpu() || (preferredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) == 0)
- {
- preferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- }
- break;
- case VMA_MEMORY_USAGE_GPU_TO_CPU:
- requiredFlags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
- preferredFlags |= VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
- break;
- case VMA_MEMORY_USAGE_CPU_COPY:
- notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- break;
- case VMA_MEMORY_USAGE_GPU_LAZILY_ALLOCATED:
- requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
- break;
- default:
- VMA_ASSERT(0);
- break;
- }
-
- // Avoid DEVICE_COHERENT unless explicitly requested.
- if(((pAllocationCreateInfo->requiredFlags | pAllocationCreateInfo->preferredFlags) &
- (VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD_COPY)) == 0)
- {
- notPreferredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD_COPY;
- }
-
- *pMemoryTypeIndex = UINT32_MAX;
- uint32_t minCost = UINT32_MAX;
- for(uint32_t memTypeIndex = 0, memTypeBit = 1;
- memTypeIndex < allocator->GetMemoryTypeCount();
- ++memTypeIndex, memTypeBit <<= 1)
- {
- // This memory type is acceptable according to memoryTypeBits bitmask.
- if((memTypeBit & memoryTypeBits) != 0)
- {
- const VkMemoryPropertyFlags currFlags =
- allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
- // This memory type contains requiredFlags.
- if((requiredFlags & ~currFlags) == 0)
- {
- // Calculate cost as number of bits from preferredFlags not present in this memory type.
- uint32_t currCost = VmaCountBitsSet(preferredFlags & ~currFlags) +
- VmaCountBitsSet(currFlags & notPreferredFlags);
- // Remember memory type with lowest cost.
- if(currCost < minCost)
- {
- *pMemoryTypeIndex = memTypeIndex;
- if(currCost == 0)
- {
- return VK_SUCCESS;
- }
- minCost = currCost;
- }
- }
- }
- }
- return (*pMemoryTypeIndex != UINT32_MAX) ? VK_SUCCESS : VK_ERROR_FEATURE_NOT_PRESENT;
+ return allocator->FindMemoryTypeIndex(memoryTypeBits, pAllocationCreateInfo, UINT32_MAX, pMemoryTypeIndex);
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
@@ -18570,23 +16316,40 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForBufferInfo(
VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
const VkDevice hDev = allocator->m_hDevice;
- VkBuffer hBuffer = VK_NULL_HANDLE;
- VkResult res = allocator->GetVulkanFunctions().vkCreateBuffer(
- hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);
- if(res == VK_SUCCESS)
+ const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions();
+ VkResult res;
+
+#if VMA_VULKAN_VERSION >= 1003000
+ if(funcs->vkGetDeviceBufferMemoryRequirements)
{
- VkMemoryRequirements memReq = {};
- allocator->GetVulkanFunctions().vkGetBufferMemoryRequirements(
- hDev, hBuffer, &memReq);
+ // Can query straight from VkBufferCreateInfo :)
+ VkDeviceBufferMemoryRequirements devBufMemReq = {VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS};
+ devBufMemReq.pCreateInfo = pBufferCreateInfo;
- res = vmaFindMemoryTypeIndex(
- allocator,
- memReq.memoryTypeBits,
- pAllocationCreateInfo,
- pMemoryTypeIndex);
+ VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
+ (*funcs->vkGetDeviceBufferMemoryRequirements)(hDev, &devBufMemReq, &memReq);
- allocator->GetVulkanFunctions().vkDestroyBuffer(
- hDev, hBuffer, allocator->GetAllocationCallbacks());
+ res = allocator->FindMemoryTypeIndex(
+ memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, pBufferCreateInfo->usage, pMemoryTypeIndex);
+ }
+ else
+#endif // #if VMA_VULKAN_VERSION >= 1003000
+ {
+ // Must create a dummy buffer to query :(
+ VkBuffer hBuffer = VK_NULL_HANDLE;
+ res = funcs->vkCreateBuffer(
+ hDev, pBufferCreateInfo, allocator->GetAllocationCallbacks(), &hBuffer);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ funcs->vkGetBufferMemoryRequirements(hDev, hBuffer, &memReq);
+
+ res = allocator->FindMemoryTypeIndex(
+ memReq.memoryTypeBits, pAllocationCreateInfo, pBufferCreateInfo->usage, pMemoryTypeIndex);
+
+ funcs->vkDestroyBuffer(
+ hDev, hBuffer, allocator->GetAllocationCallbacks());
+ }
}
return res;
}
@@ -18603,23 +16366,42 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFindMemoryTypeIndexForImageInfo(
VMA_ASSERT(pMemoryTypeIndex != VMA_NULL);
const VkDevice hDev = allocator->m_hDevice;
- VkImage hImage = VK_NULL_HANDLE;
- VkResult res = allocator->GetVulkanFunctions().vkCreateImage(
- hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);
- if(res == VK_SUCCESS)
+ const VmaVulkanFunctions* funcs = &allocator->GetVulkanFunctions();
+ VkResult res;
+
+#if VMA_VULKAN_VERSION >= 1003000
+ if(funcs->vkGetDeviceImageMemoryRequirements)
+ {
+ // Can query straight from VkImageCreateInfo :)
+ VkDeviceImageMemoryRequirements devImgMemReq = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS};
+ devImgMemReq.pCreateInfo = pImageCreateInfo;
+ VMA_ASSERT(pImageCreateInfo->tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT_COPY && (pImageCreateInfo->flags & VK_IMAGE_CREATE_DISJOINT_BIT_COPY) == 0 &&
+ "Cannot use this VkImageCreateInfo with vmaFindMemoryTypeIndexForImageInfo as I don't know what to pass as VkDeviceImageMemoryRequirements::planeAspect.");
+
+ VkMemoryRequirements2 memReq = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2};
+ (*funcs->vkGetDeviceImageMemoryRequirements)(hDev, &devImgMemReq, &memReq);
+
+ res = allocator->FindMemoryTypeIndex(
+ memReq.memoryRequirements.memoryTypeBits, pAllocationCreateInfo, pImageCreateInfo->usage, pMemoryTypeIndex);
+ }
+ else
+#endif // #if VMA_VULKAN_VERSION >= 1003000
{
- VkMemoryRequirements memReq = {};
- allocator->GetVulkanFunctions().vkGetImageMemoryRequirements(
- hDev, hImage, &memReq);
+ // Must create a dummy image to query :(
+ VkImage hImage = VK_NULL_HANDLE;
+ res = funcs->vkCreateImage(
+ hDev, pImageCreateInfo, allocator->GetAllocationCallbacks(), &hImage);
+ if(res == VK_SUCCESS)
+ {
+ VkMemoryRequirements memReq = {};
+ funcs->vkGetImageMemoryRequirements(hDev, hImage, &memReq);
- res = vmaFindMemoryTypeIndex(
- allocator,
- memReq.memoryTypeBits,
- pAllocationCreateInfo,
- pMemoryTypeIndex);
+ res = allocator->FindMemoryTypeIndex(
+ memReq.memoryTypeBits, pAllocationCreateInfo, pImageCreateInfo->usage, pMemoryTypeIndex);
- allocator->GetVulkanFunctions().vkDestroyImage(
- hDev, hImage, allocator->GetAllocationCallbacks());
+ funcs->vkDestroyImage(
+ hDev, hImage, allocator->GetAllocationCallbacks());
+ }
}
return res;
}
@@ -18635,16 +16417,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreatePool(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- VkResult res = allocator->CreatePool(pCreateInfo, pPool);
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordCreatePool(allocator->GetCurrentFrameIndex(), *pCreateInfo, *pPool);
- }
-#endif
-
- return res;
+ return allocator->CreatePool(pCreateInfo, pPool);
}
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
@@ -18662,45 +16435,31 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyPool(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordDestroyPool(allocator->GetCurrentFrameIndex(), pool);
- }
-#endif
-
allocator->DestroyPool(pool);
}
-VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStats(
+VMA_CALL_PRE void VMA_CALL_POST vmaGetPoolStatistics(
VmaAllocator allocator,
VmaPool pool,
- VmaPoolStats* pPoolStats)
+ VmaStatistics* pPoolStats)
{
VMA_ASSERT(allocator && pool && pPoolStats);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- allocator->GetPoolStats(pool, pPoolStats);
+ allocator->GetPoolStatistics(pool, pPoolStats);
}
-VMA_CALL_PRE void VMA_CALL_POST vmaMakePoolAllocationsLost(
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculatePoolStatistics(
VmaAllocator allocator,
VmaPool pool,
- size_t* pLostAllocationCount)
+ VmaDetailedStatistics* pPoolStats)
{
- VMA_ASSERT(allocator && pool);
+ VMA_ASSERT(allocator && pool && pPoolStats);
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordMakePoolAllocationsLost(allocator->GetCurrentFrameIndex(), pool);
- }
-#endif
-
- allocator->MakePoolAllocationsLost(pool, pLostAllocationCount);
+ allocator->CalculatePoolStatistics(pool, pPoolStats);
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckPoolCorruption(VmaAllocator allocator, VmaPool pool)
@@ -18740,13 +16499,6 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetPoolName(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
pool->SetName(pName);
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordSetPoolName(allocator->GetCurrentFrameIndex(), pool, pName);
- }
-#endif
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
@@ -18767,24 +16519,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemory(
false, // requiresDedicatedAllocation
false, // prefersDedicatedAllocation
VK_NULL_HANDLE, // dedicatedBuffer
- UINT32_MAX, // dedicatedBufferUsage
VK_NULL_HANDLE, // dedicatedImage
+ UINT32_MAX, // dedicatedBufferImageUsage
*pCreateInfo,
VMA_SUBALLOCATION_TYPE_UNKNOWN,
1, // allocationCount
pAllocation);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordAllocateMemory(
- allocator->GetCurrentFrameIndex(),
- *pVkMemoryRequirements,
- *pCreateInfo,
- *pAllocation);
- }
-#endif
-
if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
{
allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
@@ -18817,25 +16558,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryPages(
false, // requiresDedicatedAllocation
false, // prefersDedicatedAllocation
VK_NULL_HANDLE, // dedicatedBuffer
- UINT32_MAX, // dedicatedBufferUsage
VK_NULL_HANDLE, // dedicatedImage
+ UINT32_MAX, // dedicatedBufferImageUsage
*pCreateInfo,
VMA_SUBALLOCATION_TYPE_UNKNOWN,
allocationCount,
pAllocations);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordAllocateMemoryPages(
- allocator->GetCurrentFrameIndex(),
- *pVkMemoryRequirements,
- *pCreateInfo,
- (uint64_t)allocationCount,
- pAllocations);
- }
-#endif
-
if(pAllocationInfo != VMA_NULL && result == VK_SUCCESS)
{
for(size_t i = 0; i < allocationCount; ++i)
@@ -18872,26 +16601,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForBuffer(
requiresDedicatedAllocation,
prefersDedicatedAllocation,
buffer, // dedicatedBuffer
- UINT32_MAX, // dedicatedBufferUsage
VK_NULL_HANDLE, // dedicatedImage
+ UINT32_MAX, // dedicatedBufferImageUsage
*pCreateInfo,
VMA_SUBALLOCATION_TYPE_BUFFER,
1, // allocationCount
pAllocation);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordAllocateMemoryForBuffer(
- allocator->GetCurrentFrameIndex(),
- vkMemReq,
- requiresDedicatedAllocation,
- prefersDedicatedAllocation,
- *pCreateInfo,
- *pAllocation);
- }
-#endif
-
if(pAllocationInfo && result == VK_SUCCESS)
{
allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
@@ -18924,26 +16640,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaAllocateMemoryForImage(
requiresDedicatedAllocation,
prefersDedicatedAllocation,
VK_NULL_HANDLE, // dedicatedBuffer
- UINT32_MAX, // dedicatedBufferUsage
image, // dedicatedImage
+ UINT32_MAX, // dedicatedBufferImageUsage
*pCreateInfo,
VMA_SUBALLOCATION_TYPE_IMAGE_UNKNOWN,
1, // allocationCount
pAllocation);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordAllocateMemoryForImage(
- allocator->GetCurrentFrameIndex(),
- vkMemReq,
- requiresDedicatedAllocation,
- prefersDedicatedAllocation,
- *pCreateInfo,
- *pAllocation);
- }
-#endif
-
if(pAllocationInfo && result == VK_SUCCESS)
{
allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
@@ -18967,15 +16670,6 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemory(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordFreeMemory(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
allocator->FreeMemory(
1, // allocationCount
&allocation);
@@ -18997,16 +16691,6 @@ VMA_CALL_PRE void VMA_CALL_POST vmaFreeMemoryPages(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordFreeMemoryPages(
- allocator->GetCurrentFrameIndex(),
- (uint64_t)allocationCount,
- pAllocations);
- }
-#endif
-
allocator->FreeMemory(allocationCount, pAllocations);
}
@@ -19019,38 +16703,9 @@ VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationInfo(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordGetAllocationInfo(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
allocator->GetAllocationInfo(allocation, pAllocationInfo);
}
-VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaTouchAllocation(
- VmaAllocator allocator,
- VmaAllocation allocation)
-{
- VMA_ASSERT(allocator && allocation);
-
- VMA_DEBUG_GLOBAL_MUTEX_LOCK
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordTouchAllocation(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
- return allocator->TouchAllocation(allocation);
-}
-
VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
VmaAllocator allocator,
VmaAllocation allocation,
@@ -19061,36 +16716,24 @@ VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationUserData(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
allocation->SetUserData(allocator, pUserData);
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordSetAllocationUserData(
- allocator->GetCurrentFrameIndex(),
- allocation,
- pUserData);
- }
-#endif
}
-VMA_CALL_PRE void VMA_CALL_POST vmaCreateLostAllocation(
- VmaAllocator allocator,
- VmaAllocation* pAllocation)
+VMA_CALL_PRE void VMA_CALL_POST vmaSetAllocationName(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const char* VMA_NULLABLE pName)
{
- VMA_ASSERT(allocator && pAllocation);
-
- VMA_DEBUG_GLOBAL_MUTEX_LOCK;
-
- allocator->CreateLostAllocation(pAllocation);
+ allocation->SetName(allocator, pName);
+}
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordCreateLostAllocation(
- allocator->GetCurrentFrameIndex(),
- *pAllocation);
- }
-#endif
+VMA_CALL_PRE void VMA_CALL_POST vmaGetAllocationMemoryProperties(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ VkMemoryPropertyFlags* VMA_NOT_NULL pFlags)
+{
+ VMA_ASSERT(allocator && allocation && pFlags);
+ const uint32_t memTypeIndex = allocation->GetMemoryTypeIndex();
+ *pFlags = allocator->m_MemProps.memoryTypes[memTypeIndex].propertyFlags;
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
@@ -19102,18 +16745,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaMapMemory(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- VkResult res = allocator->Map(allocation, ppData);
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordMapMemory(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
- return res;
+ return allocator->Map(allocation, ppData);
}
VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
@@ -19124,19 +16756,14 @@ VMA_CALL_PRE void VMA_CALL_POST vmaUnmapMemory(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordUnmapMemory(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
allocator->Unmap(allocation);
}
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize offset,
+ VkDeviceSize size)
{
VMA_ASSERT(allocator && allocation);
@@ -19146,19 +16773,14 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocation(VmaAllocator allocator, V
const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_FLUSH);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordFlushAllocation(
- allocator->GetCurrentFrameIndex(),
- allocation, offset, size);
- }
-#endif
-
return res;
}
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocator, VmaAllocation allocation, VkDeviceSize offset, VkDeviceSize size)
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation(
+ VmaAllocator allocator,
+ VmaAllocation allocation,
+ VkDeviceSize offset,
+ VkDeviceSize size)
{
VMA_ASSERT(allocator && allocation);
@@ -19168,15 +16790,6 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocation(VmaAllocator allocat
const VkResult res = allocator->FlushOrInvalidateAllocation(allocation, offset, size, VMA_CACHE_INVALIDATE);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordInvalidateAllocation(
- allocator->GetCurrentFrameIndex(),
- allocation, offset, size);
- }
-#endif
-
return res;
}
@@ -19202,13 +16815,6 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaFlushAllocations(
const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_FLUSH);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- //TODO
- }
-#endif
-
return res;
}
@@ -19234,17 +16840,12 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaInvalidateAllocations(
const VkResult res = allocator->FlushOrInvalidateAllocations(allocationCount, allocations, offsets, sizes, VMA_CACHE_INVALIDATE);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- //TODO
- }
-#endif
-
return res;
}
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, uint32_t memoryTypeBits)
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(
+ VmaAllocator allocator,
+ uint32_t memoryTypeBits)
{
VMA_ASSERT(allocator);
@@ -19255,139 +16856,70 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCheckCorruption(VmaAllocator allocator, u
return allocator->CheckCorruption(memoryTypeBits);
}
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragment(
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentation(
VmaAllocator allocator,
- const VmaAllocation* pAllocations,
- size_t allocationCount,
- VkBool32* pAllocationsChanged,
- const VmaDefragmentationInfo *pDefragmentationInfo,
- VmaDefragmentationStats* pDefragmentationStats)
-{
- // Deprecated interface, reimplemented using new one.
-
- VmaDefragmentationInfo2 info2 = {};
- info2.allocationCount = (uint32_t)allocationCount;
- info2.pAllocations = pAllocations;
- info2.pAllocationsChanged = pAllocationsChanged;
- if(pDefragmentationInfo != VMA_NULL)
- {
- info2.maxCpuAllocationsToMove = pDefragmentationInfo->maxAllocationsToMove;
- info2.maxCpuBytesToMove = pDefragmentationInfo->maxBytesToMove;
- }
- else
- {
- info2.maxCpuAllocationsToMove = UINT32_MAX;
- info2.maxCpuBytesToMove = VK_WHOLE_SIZE;
- }
- // info2.flags, maxGpuAllocationsToMove, maxGpuBytesToMove, commandBuffer deliberately left zero.
-
- VmaDefragmentationContext ctx;
- VkResult res = vmaDefragmentationBegin(allocator, &info2, pDefragmentationStats, &ctx);
- if(res == VK_NOT_READY)
- {
- res = vmaDefragmentationEnd( allocator, ctx);
- }
- return res;
-}
-
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationBegin(
- VmaAllocator allocator,
- const VmaDefragmentationInfo2* pInfo,
- VmaDefragmentationStats* pStats,
- VmaDefragmentationContext *pContext)
+ const VmaDefragmentationInfo* pInfo,
+ VmaDefragmentationContext* pContext)
{
VMA_ASSERT(allocator && pInfo && pContext);
- // Degenerate case: Nothing to defragment.
- if(pInfo->allocationCount == 0 && pInfo->poolCount == 0)
+ VMA_DEBUG_LOG("vmaBeginDefragmentation");
+
+ if (pInfo->pool != VMA_NULL)
{
- return VK_SUCCESS;
+ // Check if run on supported algorithms
+ if (pInfo->pool->m_BlockVector.GetAlgorithm() & VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT)
+ return VK_ERROR_FEATURE_NOT_PRESENT;
}
- VMA_ASSERT(pInfo->allocationCount == 0 || pInfo->pAllocations != VMA_NULL);
- VMA_ASSERT(pInfo->poolCount == 0 || pInfo->pPools != VMA_NULL);
- VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->allocationCount, pInfo->pAllocations));
- VMA_HEAVY_ASSERT(VmaValidatePointerArray(pInfo->poolCount, pInfo->pPools));
-
- VMA_DEBUG_LOG("vmaDefragmentationBegin");
-
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- VkResult res = allocator->DefragmentationBegin(*pInfo, pStats, pContext);
-
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordDefragmentationBegin(
- allocator->GetCurrentFrameIndex(), *pInfo, *pContext);
- }
-#endif
-
- return res;
+ *pContext = vma_new(allocator, VmaDefragmentationContext_T)(allocator, *pInfo);
+ return VK_SUCCESS;
}
-VMA_CALL_PRE VkResult VMA_CALL_POST vmaDefragmentationEnd(
+VMA_CALL_PRE void VMA_CALL_POST vmaEndDefragmentation(
VmaAllocator allocator,
- VmaDefragmentationContext context)
+ VmaDefragmentationContext context,
+ VmaDefragmentationStats* pStats)
{
- VMA_ASSERT(allocator);
-
- VMA_DEBUG_LOG("vmaDefragmentationEnd");
+ VMA_ASSERT(allocator && context);
- if(context != VK_NULL_HANDLE)
- {
- VMA_DEBUG_GLOBAL_MUTEX_LOCK
+ VMA_DEBUG_LOG("vmaEndDefragmentation");
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordDefragmentationEnd(
- allocator->GetCurrentFrameIndex(), context);
- }
-#endif
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
- return allocator->DefragmentationEnd(context);
- }
- else
- {
- return VK_SUCCESS;
- }
+ if (pStats)
+ context->GetStats(*pStats);
+ vma_delete(allocator, context);
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaBeginDefragmentationPass(
- VmaAllocator allocator,
- VmaDefragmentationContext context,
- VmaDefragmentationPassInfo* pInfo
- )
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaDefragmentationContext VMA_NOT_NULL context,
+ VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo)
{
- VMA_ASSERT(allocator);
- VMA_ASSERT(pInfo);
+ VMA_ASSERT(context && pPassInfo);
VMA_DEBUG_LOG("vmaBeginDefragmentationPass");
VMA_DEBUG_GLOBAL_MUTEX_LOCK
- if(context == VK_NULL_HANDLE)
- {
- pInfo->moveCount = 0;
- return VK_SUCCESS;
- }
-
- return allocator->DefragmentationPassBegin(pInfo, context);
+ return context->DefragmentPassBegin(*pPassInfo);
}
+
VMA_CALL_PRE VkResult VMA_CALL_POST vmaEndDefragmentationPass(
- VmaAllocator allocator,
- VmaDefragmentationContext context)
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaDefragmentationContext VMA_NOT_NULL context,
+ VmaDefragmentationPassMoveInfo* VMA_NOT_NULL pPassInfo)
{
- VMA_ASSERT(allocator);
+ VMA_ASSERT(context && pPassInfo);
VMA_DEBUG_LOG("vmaEndDefragmentationPass");
- VMA_DEBUG_GLOBAL_MUTEX_LOCK
- if(context == VK_NULL_HANDLE)
- return VK_SUCCESS;
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
- return allocator->DefragmentationPassEnd(context);
+ return context->DefragmentPassEnd(*pPassInfo);
}
VMA_CALL_PRE VkResult VMA_CALL_POST vmaBindBufferMemory(
@@ -19462,13 +16994,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
if(pBufferCreateInfo->size == 0)
{
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ return VK_ERROR_INITIALIZATION_FAILED;
}
if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&
!allocator->m_UseKhrBufferDeviceAddress)
{
VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.");
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ return VK_ERROR_INITIALIZATION_FAILED;
}
VMA_DEBUG_LOG("vmaCreateBuffer");
@@ -19499,23 +17031,107 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
requiresDedicatedAllocation,
prefersDedicatedAllocation,
*pBuffer, // dedicatedBuffer
- pBufferCreateInfo->usage, // dedicatedBufferUsage
VK_NULL_HANDLE, // dedicatedImage
+ pBufferCreateInfo->usage, // dedicatedBufferImageUsage
*pAllocationCreateInfo,
VMA_SUBALLOCATION_TYPE_BUFFER,
1, // allocationCount
pAllocation);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
+ if(res >= 0)
{
- allocator->GetRecorder()->RecordCreateBuffer(
- allocator->GetCurrentFrameIndex(),
- *pBufferCreateInfo,
- *pAllocationCreateInfo,
- *pAllocation);
+ // 3. Bind buffer with memory.
+ if((pAllocationCreateInfo->flags & VMA_ALLOCATION_CREATE_DONT_BIND_BIT) == 0)
+ {
+ res = allocator->BindBufferMemory(*pAllocation, 0, *pBuffer, VMA_NULL);
+ }
+ if(res >= 0)
+ {
+ // All steps succeeded.
+ #if VMA_STATS_STRING_ENABLED
+ (*pAllocation)->InitBufferImageUsage(pBufferCreateInfo->usage);
+ #endif
+ if(pAllocationInfo != VMA_NULL)
+ {
+ allocator->GetAllocationInfo(*pAllocation, pAllocationInfo);
+ }
+
+ return VK_SUCCESS;
+ }
+ allocator->FreeMemory(
+ 1, // allocationCount
+ pAllocation);
+ *pAllocation = VK_NULL_HANDLE;
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
}
-#endif
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ *pBuffer = VK_NULL_HANDLE;
+ return res;
+ }
+ return res;
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBufferWithAlignment(
+ VmaAllocator allocator,
+ const VkBufferCreateInfo* pBufferCreateInfo,
+ const VmaAllocationCreateInfo* pAllocationCreateInfo,
+ VkDeviceSize minAlignment,
+ VkBuffer* pBuffer,
+ VmaAllocation* pAllocation,
+ VmaAllocationInfo* pAllocationInfo)
+{
+ VMA_ASSERT(allocator && pBufferCreateInfo && pAllocationCreateInfo && VmaIsPow2(minAlignment) && pBuffer && pAllocation);
+
+ if(pBufferCreateInfo->size == 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ if((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&
+ !allocator->m_UseKhrBufferDeviceAddress)
+ {
+ VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.");
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ VMA_DEBUG_LOG("vmaCreateBufferWithAlignment");
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ *pBuffer = VK_NULL_HANDLE;
+ *pAllocation = VK_NULL_HANDLE;
+
+ // 1. Create VkBuffer.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(
+ allocator->m_hDevice,
+ pBufferCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pBuffer);
+ if(res >= 0)
+ {
+ // 2. vkGetBufferMemoryRequirements.
+ VkMemoryRequirements vkMemReq = {};
+ bool requiresDedicatedAllocation = false;
+ bool prefersDedicatedAllocation = false;
+ allocator->GetBufferMemoryRequirements(*pBuffer, vkMemReq,
+ requiresDedicatedAllocation, prefersDedicatedAllocation);
+
+ // 2a. Include minAlignment
+ vkMemReq.alignment = VMA_MAX(vkMemReq.alignment, minAlignment);
+
+ // 3. Allocate memory using allocator.
+ res = allocator->AllocateMemory(
+ vkMemReq,
+ requiresDedicatedAllocation,
+ prefersDedicatedAllocation,
+ *pBuffer, // dedicatedBuffer
+ VK_NULL_HANDLE, // dedicatedImage
+ pBufferCreateInfo->usage, // dedicatedBufferImageUsage
+ *pAllocationCreateInfo,
+ VMA_SUBALLOCATION_TYPE_BUFFER,
+ 1, // allocationCount
+ pAllocation);
if(res >= 0)
{
@@ -19552,6 +17168,50 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateBuffer(
return res;
}
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingBuffer(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const VkBufferCreateInfo* VMA_NOT_NULL pBufferCreateInfo,
+ VkBuffer VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pBuffer)
+{
+ VMA_ASSERT(allocator && pBufferCreateInfo && pBuffer && allocation);
+
+ VMA_DEBUG_LOG("vmaCreateAliasingBuffer");
+
+ *pBuffer = VK_NULL_HANDLE;
+
+ if (pBufferCreateInfo->size == 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ if ((pBufferCreateInfo->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_COPY) != 0 &&
+ !allocator->m_UseKhrBufferDeviceAddress)
+ {
+ VMA_ASSERT(0 && "Creating a buffer with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT is not valid if VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT was not used.");
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ // 1. Create VkBuffer.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateBuffer)(
+ allocator->m_hDevice,
+ pBufferCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pBuffer);
+ if (res >= 0)
+ {
+ // 2. Bind buffer with memory.
+ res = allocator->BindBufferMemory(allocation, 0, *pBuffer, VMA_NULL);
+ if (res >= 0)
+ {
+ return VK_SUCCESS;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, *pBuffer, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
VmaAllocator allocator,
VkBuffer buffer,
@@ -19568,15 +17228,6 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyBuffer(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordDestroyBuffer(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
if(buffer != VK_NULL_HANDLE)
{
(*allocator->GetVulkanFunctions().vkDestroyBuffer)(allocator->m_hDevice, buffer, allocator->GetAllocationCallbacks());
@@ -19606,7 +17257,7 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
pImageCreateInfo->mipLevels == 0 ||
pImageCreateInfo->arrayLayers == 0)
{
- return VK_ERROR_VALIDATION_FAILED_EXT;
+ return VK_ERROR_INITIALIZATION_FAILED;
}
VMA_DEBUG_LOG("vmaCreateImage");
@@ -19640,24 +17291,13 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
requiresDedicatedAllocation,
prefersDedicatedAllocation,
VK_NULL_HANDLE, // dedicatedBuffer
- UINT32_MAX, // dedicatedBufferUsage
*pImage, // dedicatedImage
+ pImageCreateInfo->usage, // dedicatedBufferImageUsage
*pAllocationCreateInfo,
suballocType,
1, // allocationCount
pAllocation);
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordCreateImage(
- allocator->GetCurrentFrameIndex(),
- *pImageCreateInfo,
- *pAllocationCreateInfo,
- *pAllocation);
- }
-#endif
-
if(res >= 0)
{
// 3. Bind image with memory.
@@ -19693,10 +17333,52 @@ VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateImage(
return res;
}
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateAliasingImage(
+ VmaAllocator VMA_NOT_NULL allocator,
+ VmaAllocation VMA_NOT_NULL allocation,
+ const VkImageCreateInfo* VMA_NOT_NULL pImageCreateInfo,
+ VkImage VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pImage)
+{
+ VMA_ASSERT(allocator && pImageCreateInfo && pImage && allocation);
+
+ *pImage = VK_NULL_HANDLE;
+
+ VMA_DEBUG_LOG("vmaCreateImage");
+
+ if (pImageCreateInfo->extent.width == 0 ||
+ pImageCreateInfo->extent.height == 0 ||
+ pImageCreateInfo->extent.depth == 0 ||
+ pImageCreateInfo->mipLevels == 0 ||
+ pImageCreateInfo->arrayLayers == 0)
+ {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK
+
+ // 1. Create VkImage.
+ VkResult res = (*allocator->GetVulkanFunctions().vkCreateImage)(
+ allocator->m_hDevice,
+ pImageCreateInfo,
+ allocator->GetAllocationCallbacks(),
+ pImage);
+ if (res >= 0)
+ {
+ // 2. Bind image with memory.
+ res = allocator->BindImageMemory(allocation, 0, *pImage, VMA_NULL);
+ if (res >= 0)
+ {
+ return VK_SUCCESS;
+ }
+ (*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, *pImage, allocator->GetAllocationCallbacks());
+ }
+ return res;
+}
+
VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
- VmaAllocator allocator,
- VkImage image,
- VmaAllocation allocation)
+ VmaAllocator VMA_NOT_NULL allocator,
+ VkImage VMA_NULLABLE_NON_DISPATCHABLE image,
+ VmaAllocation VMA_NULLABLE allocation)
{
VMA_ASSERT(allocator);
@@ -19709,15 +17391,6 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
VMA_DEBUG_GLOBAL_MUTEX_LOCK
-#if VMA_RECORDING_ENABLED
- if(allocator->GetRecorder() != VMA_NULL)
- {
- allocator->GetRecorder()->RecordDestroyImage(
- allocator->GetCurrentFrameIndex(),
- allocation);
- }
-#endif
-
if(image != VK_NULL_HANDLE)
{
(*allocator->GetVulkanFunctions().vkDestroyImage)(allocator->m_hDevice, image, allocator->GetAllocationCallbacks());
@@ -19730,4 +17403,2160 @@ VMA_CALL_PRE void VMA_CALL_POST vmaDestroyImage(
}
}
-#endif // #ifdef VMA_IMPLEMENTATION
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaCreateVirtualBlock(
+ const VmaVirtualBlockCreateInfo* VMA_NOT_NULL pCreateInfo,
+ VmaVirtualBlock VMA_NULLABLE * VMA_NOT_NULL pVirtualBlock)
+{
+ VMA_ASSERT(pCreateInfo && pVirtualBlock);
+ VMA_ASSERT(pCreateInfo->size > 0);
+ VMA_DEBUG_LOG("vmaCreateVirtualBlock");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ *pVirtualBlock = vma_new(pCreateInfo->pAllocationCallbacks, VmaVirtualBlock_T)(*pCreateInfo);
+ VkResult res = (*pVirtualBlock)->Init();
+ if(res < 0)
+ {
+ vma_delete(pCreateInfo->pAllocationCallbacks, *pVirtualBlock);
+ *pVirtualBlock = VK_NULL_HANDLE;
+ }
+ return res;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaDestroyVirtualBlock(VmaVirtualBlock VMA_NULLABLE virtualBlock)
+{
+ if(virtualBlock != VK_NULL_HANDLE)
+ {
+ VMA_DEBUG_LOG("vmaDestroyVirtualBlock");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ VkAllocationCallbacks allocationCallbacks = virtualBlock->m_AllocationCallbacks; // Have to copy the callbacks when destroying.
+ vma_delete(&allocationCallbacks, virtualBlock);
+ }
+}
+
+VMA_CALL_PRE VkBool32 VMA_CALL_POST vmaIsVirtualBlockEmpty(VmaVirtualBlock VMA_NOT_NULL virtualBlock)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);
+ VMA_DEBUG_LOG("vmaIsVirtualBlockEmpty");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ return virtualBlock->IsEmpty() ? VK_TRUE : VK_FALSE;
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualAllocationInfo(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, VmaVirtualAllocationInfo* VMA_NOT_NULL pVirtualAllocInfo)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pVirtualAllocInfo != VMA_NULL);
+ VMA_DEBUG_LOG("vmaGetVirtualAllocationInfo");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->GetAllocationInfo(allocation, *pVirtualAllocInfo);
+}
+
+VMA_CALL_PRE VkResult VMA_CALL_POST vmaVirtualAllocate(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ const VmaVirtualAllocationCreateInfo* VMA_NOT_NULL pCreateInfo, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE* VMA_NOT_NULL pAllocation,
+ VkDeviceSize* VMA_NULLABLE pOffset)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pCreateInfo != VMA_NULL && pAllocation != VMA_NULL);
+ VMA_DEBUG_LOG("vmaVirtualAllocate");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ return virtualBlock->Allocate(*pCreateInfo, *pAllocation, pOffset);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaVirtualFree(VmaVirtualBlock VMA_NOT_NULL virtualBlock, VmaVirtualAllocation VMA_NULLABLE_NON_DISPATCHABLE allocation)
+{
+ if(allocation != VK_NULL_HANDLE)
+ {
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);
+ VMA_DEBUG_LOG("vmaVirtualFree");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->Free(allocation);
+ }
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaClearVirtualBlock(VmaVirtualBlock VMA_NOT_NULL virtualBlock)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);
+ VMA_DEBUG_LOG("vmaClearVirtualBlock");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->Clear();
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaSetVirtualAllocationUserData(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaVirtualAllocation VMA_NOT_NULL_NON_DISPATCHABLE allocation, void* VMA_NULLABLE pUserData)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);
+ VMA_DEBUG_LOG("vmaSetVirtualAllocationUserData");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->SetAllocationUserData(allocation, pUserData);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaGetVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaStatistics* VMA_NOT_NULL pStats)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL);
+ VMA_DEBUG_LOG("vmaGetVirtualBlockStatistics");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->GetStatistics(*pStats);
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaCalculateVirtualBlockStatistics(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ VmaDetailedStatistics* VMA_NOT_NULL pStats)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && pStats != VMA_NULL);
+ VMA_DEBUG_LOG("vmaCalculateVirtualBlockStatistics");
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ virtualBlock->CalculateDetailedStatistics(*pStats);
+}
+
+#if VMA_STATS_STRING_ENABLED
+
+VMA_CALL_PRE void VMA_CALL_POST vmaBuildVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ char* VMA_NULLABLE * VMA_NOT_NULL ppStatsString, VkBool32 detailedMap)
+{
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE && ppStatsString != VMA_NULL);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ const VkAllocationCallbacks* allocationCallbacks = virtualBlock->GetAllocationCallbacks();
+ VmaStringBuilder sb(allocationCallbacks);
+ virtualBlock->BuildStatsString(detailedMap != VK_FALSE, sb);
+ *ppStatsString = VmaCreateStringCopy(allocationCallbacks, sb.GetData(), sb.GetLength());
+}
+
+VMA_CALL_PRE void VMA_CALL_POST vmaFreeVirtualBlockStatsString(VmaVirtualBlock VMA_NOT_NULL virtualBlock,
+ char* VMA_NULLABLE pStatsString)
+{
+ if(pStatsString != VMA_NULL)
+ {
+ VMA_ASSERT(virtualBlock != VK_NULL_HANDLE);
+ VMA_DEBUG_GLOBAL_MUTEX_LOCK;
+ VmaFreeString(virtualBlock->GetAllocationCallbacks(), pStatsString);
+ }
+}
+#endif // VMA_STATS_STRING_ENABLED
+#endif // _VMA_PUBLIC_INTERFACE
+#endif // VMA_IMPLEMENTATION
+
+/**
+\page quick_start Quick start
+
+\section quick_start_project_setup Project setup
+
+Vulkan Memory Allocator comes in form of a "stb-style" single header file.
+You don't need to build it as a separate library project.
+You can add this file directly to your project and submit it to code repository next to your other source files.
+
+"Single header" doesn't mean that everything is contained in C/C++ declarations,
+like it tends to be in case of inline functions or C++ templates.
+It means that implementation is bundled with interface in a single file and needs to be extracted using preprocessor macro.
+If you don't do it properly, you will get linker errors.
+
+To do it properly:
+
+-# Include "vk_mem_alloc.h" file in each CPP file where you want to use the library.
+ This includes declarations of all members of the library.
+-# In exactly one CPP file define following macro before this include.
+ It enables also internal definitions.
+
+\code
+#define VMA_IMPLEMENTATION
+#include "vk_mem_alloc.h"
+\endcode
+
+It may be a good idea to create dedicated CPP file just for this purpose.
+
+This library includes header `<vulkan/vulkan.h>`, which in turn
+includes `<windows.h>` on Windows. If you need some specific macros defined
+before including these headers (like `WIN32_LEAN_AND_MEAN` or
+`WINVER` for Windows, `VK_USE_PLATFORM_WIN32_KHR` for Vulkan), you must define
+them before every `#include` of this library.
+
+This library is written in C++, but has C-compatible interface.
+Thus you can include and use vk_mem_alloc.h in C or C++ code, but full
+implementation with `VMA_IMPLEMENTATION` macro must be compiled as C++, NOT as C.
+Some features of C++14 used. STL containers, RTTI, or C++ exceptions are not used.
+
+
+\section quick_start_initialization Initialization
+
+At program startup:
+
+-# Initialize Vulkan to have `VkPhysicalDevice`, `VkDevice` and `VkInstance` object.
+-# Fill VmaAllocatorCreateInfo structure and create #VmaAllocator object by
+ calling vmaCreateAllocator().
+
+Only members `physicalDevice`, `device`, `instance` are required.
+However, you should inform the library which Vulkan version do you use by setting
+VmaAllocatorCreateInfo::vulkanApiVersion and which extensions did you enable
+by setting VmaAllocatorCreateInfo::flags (like #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT for VK_KHR_buffer_device_address).
+Otherwise, VMA would use only features of Vulkan 1.0 core with no extensions.
+
+You may need to configure importing Vulkan functions. There are 3 ways to do this:
+
+-# **If you link with Vulkan static library** (e.g. "vulkan-1.lib" on Windows):
+ - You don't need to do anything.
+ - VMA will use these, as macro `VMA_STATIC_VULKAN_FUNCTIONS` is defined to 1 by default.
+-# **If you want VMA to fetch pointers to Vulkan functions dynamically** using `vkGetInstanceProcAddr`,
+ `vkGetDeviceProcAddr` (this is the option presented in the example below):
+ - Define `VMA_STATIC_VULKAN_FUNCTIONS` to 0, `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 1.
+ - Provide pointers to these two functions via VmaVulkanFunctions::vkGetInstanceProcAddr,
+ VmaVulkanFunctions::vkGetDeviceProcAddr.
+ - The library will fetch pointers to all other functions it needs internally.
+-# **If you fetch pointers to all Vulkan functions in a custom way**, e.g. using some loader like
+ [Volk](https://github.com/zeux/volk):
+ - Define `VMA_STATIC_VULKAN_FUNCTIONS` and `VMA_DYNAMIC_VULKAN_FUNCTIONS` to 0.
+ - Pass these pointers via structure #VmaVulkanFunctions.
+
+\code
+VmaVulkanFunctions vulkanFunctions = {};
+vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
+vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
+
+VmaAllocatorCreateInfo allocatorCreateInfo = {};
+allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
+allocatorCreateInfo.physicalDevice = physicalDevice;
+allocatorCreateInfo.device = device;
+allocatorCreateInfo.instance = instance;
+allocatorCreateInfo.pVulkanFunctions = &vulkanFunctions;
+
+VmaAllocator allocator;
+vmaCreateAllocator(&allocatorCreateInfo, &allocator);
+\endcode
+
+
+\section quick_start_resource_allocation Resource allocation
+
+When you want to create a buffer or image:
+
+-# Fill `VkBufferCreateInfo` / `VkImageCreateInfo` structure.
+-# Fill VmaAllocationCreateInfo structure.
+-# Call vmaCreateBuffer() / vmaCreateImage() to get `VkBuffer`/`VkImage` with memory
+ already allocated and bound to it, plus #VmaAllocation objects that represents its underlying memory.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_AUTO;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+Don't forget to destroy your objects when no longer needed:
+
+\code
+vmaDestroyBuffer(allocator, buffer, allocation);
+vmaDestroyAllocator(allocator);
+\endcode
+
+
+\page choosing_memory_type Choosing memory type
+
+Physical devices in Vulkan support various combinations of memory heaps and
+types. Help with choosing correct and optimal memory type for your specific
+resource is one of the key features of this library. You can use it by filling
+appropriate members of VmaAllocationCreateInfo structure, as described below.
+You can also combine multiple methods.
+
+-# If you just want to find memory type index that meets your requirements, you
+ can use function: vmaFindMemoryTypeIndexForBufferInfo(),
+ vmaFindMemoryTypeIndexForImageInfo(), vmaFindMemoryTypeIndex().
+-# If you want to allocate a region of device memory without association with any
+ specific image or buffer, you can use function vmaAllocateMemory(). Usage of
+ this function is not recommended and usually not needed.
+ vmaAllocateMemoryPages() function is also provided for creating multiple allocations at once,
+ which may be useful for sparse binding.
+-# If you already have a buffer or an image created, you want to allocate memory
+ for it and then you will bind it yourself, you can use function
+ vmaAllocateMemoryForBuffer(), vmaAllocateMemoryForImage().
+ For binding you should use functions: vmaBindBufferMemory(), vmaBindImageMemory()
+ or their extended versions: vmaBindBufferMemory2(), vmaBindImageMemory2().
+-# **This is the easiest and recommended way to use this library:**
+ If you want to create a buffer or an image, allocate memory for it and bind
+ them together, all in one call, you can use function vmaCreateBuffer(),
+ vmaCreateImage().
+
+When using 3. or 4., the library internally queries Vulkan for memory types
+supported for that buffer or image (function `vkGetBufferMemoryRequirements()`)
+and uses only one of these types.
+
+If no memory type can be found that meets all the requirements, these functions
+return `VK_ERROR_FEATURE_NOT_PRESENT`.
+
+You can leave VmaAllocationCreateInfo structure completely filled with zeros.
+It means no requirements are specified for memory type.
+It is valid, although not very useful.
+
+\section choosing_memory_type_usage Usage
+
+The easiest way to specify memory requirements is to fill member
+VmaAllocationCreateInfo::usage using one of the values of enum #VmaMemoryUsage.
+It defines high level, common usage types.
+Since version 3 of the library, it is recommended to use #VMA_MEMORY_USAGE_AUTO to let it select best memory type for your resource automatically.
+
+For example, if you want to create a uniform buffer that will be filled using
+transfer only once or infrequently and then used for rendering every frame as a uniform buffer, you can
+do it using following code. The buffer will most likely end up in a memory type with
+`VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT` to be fast to access by the GPU device.
+
+\code
+VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufferInfo.size = 65536;
+bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.usage = VMA_MEMORY_USAGE_AUTO;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+If you have a preference for putting the resource in GPU (device) memory or CPU (host) memory
+on systems with discrete graphics card that have the memories separate, you can use
+#VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST.
+
+When using `VMA_MEMORY_USAGE_AUTO*` while you want to map the allocated memory,
+you also need to specify one of the host access flags:
+#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.
+This will help the library decide about preferred memory type to ensure it has `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`
+so you can map it.
+
+For example, a staging buffer that will be filled via mapped pointer and then
+used as a source of transfer to the buffer decribed previously can be created like this.
+It will likely and up in a memory type that is `HOST_VISIBLE` and `HOST_COHERENT`
+but not `HOST_CACHED` (meaning uncached, write-combined) and not `DEVICE_LOCAL` (meaning system RAM).
+
+\code
+VkBufferCreateInfo stagingBufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+stagingBufferInfo.size = 65536;
+stagingBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo stagingAllocInfo = {};
+stagingAllocInfo.usage = VMA_MEMORY_USAGE_AUTO;
+stagingAllocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
+
+VkBuffer stagingBuffer;
+VmaAllocation stagingAllocation;
+vmaCreateBuffer(allocator, &stagingBufferInfo, &stagingAllocInfo, &stagingBuffer, &stagingAllocation, nullptr);
+\endcode
+
+For more examples of creating different kinds of resources, see chapter \ref usage_patterns.
+
+Usage values `VMA_MEMORY_USAGE_AUTO*` are legal to use only when the library knows
+about the resource being created by having `VkBufferCreateInfo` / `VkImageCreateInfo` passed,
+so they work with functions like: vmaCreateBuffer(), vmaCreateImage(), vmaFindMemoryTypeIndexForBufferInfo() etc.
+If you allocate raw memory using function vmaAllocateMemory(), you have to use other means of selecting
+memory type, as decribed below.
+
+\note
+Old usage values (`VMA_MEMORY_USAGE_GPU_ONLY`, `VMA_MEMORY_USAGE_CPU_ONLY`,
+`VMA_MEMORY_USAGE_CPU_TO_GPU`, `VMA_MEMORY_USAGE_GPU_TO_CPU`, `VMA_MEMORY_USAGE_CPU_COPY`)
+are still available and work same way as in previous versions of the library
+for backward compatibility, but they are not recommended.
+
+\section choosing_memory_type_required_preferred_flags Required and preferred flags
+
+You can specify more detailed requirements by filling members
+VmaAllocationCreateInfo::requiredFlags and VmaAllocationCreateInfo::preferredFlags
+with a combination of bits from enum `VkMemoryPropertyFlags`. For example,
+if you want to create a buffer that will be persistently mapped on host (so it
+must be `HOST_VISIBLE`) and preferably will also be `HOST_COHERENT` and `HOST_CACHED`,
+use following code:
+
+\code
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
+allocInfo.preferredFlags = VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+allocInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+A memory type is chosen that has all the required flags and as many preferred
+flags set as possible.
+
+Value passed in VmaAllocationCreateInfo::usage is internally converted to a set of required and preferred flags,
+plus some extra "magic" (heuristics).
+
+\section choosing_memory_type_explicit_memory_types Explicit memory types
+
+If you inspected memory types available on the physical device and you have
+a preference for memory types that you want to use, you can fill member
+VmaAllocationCreateInfo::memoryTypeBits. It is a bit mask, where each bit set
+means that a memory type with that index is allowed to be used for the
+allocation. Special value 0, just like `UINT32_MAX`, means there are no
+restrictions to memory type index.
+
+Please note that this member is NOT just a memory type index.
+Still you can use it to choose just one, specific memory type.
+For example, if you already determined that your buffer should be created in
+memory type 2, use following code:
+
+\code
+uint32_t memoryTypeIndex = 2;
+
+VmaAllocationCreateInfo allocInfo = {};
+allocInfo.memoryTypeBits = 1u << memoryTypeIndex;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
+\endcode
+
+
+\section choosing_memory_type_custom_memory_pools Custom memory pools
+
+If you allocate from custom memory pool, all the ways of specifying memory
+requirements described above are not applicable and the aforementioned members
+of VmaAllocationCreateInfo structure are ignored. Memory type is selected
+explicitly when creating the pool and then used to make all the allocations from
+that pool. For further details, see \ref custom_memory_pools.
+
+\section choosing_memory_type_dedicated_allocations Dedicated allocations
+
+Memory for allocations is reserved out of larger block of `VkDeviceMemory`
+allocated from Vulkan internally. That is the main feature of this whole library.
+You can still request a separate memory block to be created for an allocation,
+just like you would do in a trivial solution without using any allocator.
+In that case, a buffer or image is always bound to that memory at offset 0.
+This is called a "dedicated allocation".
+You can explicitly request it by using flag #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+The library can also internally decide to use dedicated allocation in some cases, e.g.:
+
+- When the size of the allocation is large.
+- When [VK_KHR_dedicated_allocation](@ref vk_khr_dedicated_allocation) extension is enabled
+ and it reports that dedicated allocation is required or recommended for the resource.
+- When allocation of next big memory block fails due to not enough device memory,
+ but allocation with the exact requested size succeeds.
+
+
+\page memory_mapping Memory mapping
+
+To "map memory" in Vulkan means to obtain a CPU pointer to `VkDeviceMemory`,
+to be able to read from it or write to it in CPU code.
+Mapping is possible only of memory allocated from a memory type that has
+`VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT` flag.
+Functions `vkMapMemory()`, `vkUnmapMemory()` are designed for this purpose.
+You can use them directly with memory allocated by this library,
+but it is not recommended because of following issue:
+Mapping the same `VkDeviceMemory` block multiple times is illegal - only one mapping at a time is allowed.
+This includes mapping disjoint regions. Mapping is not reference-counted internally by Vulkan.
+Because of this, Vulkan Memory Allocator provides following facilities:
+
+\note If you want to be able to map an allocation, you need to specify one of the flags
+#VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT
+in VmaAllocationCreateInfo::flags. These flags are required for an allocation to be mappable
+when using #VMA_MEMORY_USAGE_AUTO or other `VMA_MEMORY_USAGE_AUTO*` enum values.
+For other usage values they are ignored and every such allocation made in `HOST_VISIBLE` memory type is mappable,
+but they can still be used for consistency.
+
+\section memory_mapping_mapping_functions Mapping functions
+
+The library provides following functions for mapping of a specific #VmaAllocation: vmaMapMemory(), vmaUnmapMemory().
+They are safer and more convenient to use than standard Vulkan functions.
+You can map an allocation multiple times simultaneously - mapping is reference-counted internally.
+You can also map different allocations simultaneously regardless of whether they use the same `VkDeviceMemory` block.
+The way it is implemented is that the library always maps entire memory block, not just region of the allocation.
+For further details, see description of vmaMapMemory() function.
+Example:
+
+\code
+// Having these objects initialized:
+struct ConstantBuffer
+{
+ ...
+};
+ConstantBuffer constantBufferData = ...
+
+VmaAllocator allocator = ...
+VkBuffer constantBuffer = ...
+VmaAllocation constantBufferAllocation = ...
+
+// You can map and fill your buffer using following code:
+
+void* mappedData;
+vmaMapMemory(allocator, constantBufferAllocation, &mappedData);
+memcpy(mappedData, &constantBufferData, sizeof(constantBufferData));
+vmaUnmapMemory(allocator, constantBufferAllocation);
+\endcode
+
+When mapping, you may see a warning from Vulkan validation layer similar to this one:
+
+<i>Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.</i>
+
+It happens because the library maps entire `VkDeviceMemory` block, where different
+types of images and buffers may end up together, especially on GPUs with unified memory like Intel.
+You can safely ignore it if you are sure you access only memory of the intended
+object that you wanted to map.
+
+
+\section memory_mapping_persistently_mapped_memory Persistently mapped memory
+
+Kepping your memory persistently mapped is generally OK in Vulkan.
+You don't need to unmap it before using its data on the GPU.
+The library provides a special feature designed for that:
+Allocations made with #VMA_ALLOCATION_CREATE_MAPPED_BIT flag set in
+VmaAllocationCreateInfo::flags stay mapped all the time,
+so you can just access CPU pointer to it any time
+without a need to call any "map" or "unmap" function.
+Example:
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = sizeof(ConstantBuffer);
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
+ VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+// Buffer is already mapped. You can access its memory.
+memcpy(allocInfo.pMappedData, &constantBufferData, sizeof(constantBufferData));
+\endcode
+
+\note #VMA_ALLOCATION_CREATE_MAPPED_BIT by itself doesn't guarantee that the allocation will end up
+in a mappable memory type.
+For this, you need to also specify #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT or
+#VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.
+#VMA_ALLOCATION_CREATE_MAPPED_BIT only guarantees that if the memory is `HOST_VISIBLE`, the allocation will be mapped on creation.
+For an example of how to make use of this fact, see section \ref usage_patterns_advanced_data_uploading.
+
+\section memory_mapping_cache_control Cache flush and invalidate
+
+Memory in Vulkan doesn't need to be unmapped before using it on GPU,
+but unless a memory types has `VK_MEMORY_PROPERTY_HOST_COHERENT_BIT` flag set,
+you need to manually **invalidate** cache before reading of mapped pointer
+and **flush** cache after writing to mapped pointer.
+Map/unmap operations don't do that automatically.
+Vulkan provides following functions for this purpose `vkFlushMappedMemoryRanges()`,
+`vkInvalidateMappedMemoryRanges()`, but this library provides more convenient
+functions that refer to given allocation object: vmaFlushAllocation(),
+vmaInvalidateAllocation(),
+or multiple objects at once: vmaFlushAllocations(), vmaInvalidateAllocations().
+
+Regions of memory specified for flush/invalidate must be aligned to
+`VkPhysicalDeviceLimits::nonCoherentAtomSize`. This is automatically ensured by the library.
+In any memory type that is `HOST_VISIBLE` but not `HOST_COHERENT`, all allocations
+within blocks are aligned to this value, so their offsets are always multiply of
+`nonCoherentAtomSize` and two different allocations never share same "line" of this size.
+
+Also, Windows drivers from all 3 PC GPU vendors (AMD, Intel, NVIDIA)
+currently provide `HOST_COHERENT` flag on all memory types that are
+`HOST_VISIBLE`, so on PC you may not need to bother.
+
+
+\page staying_within_budget Staying within budget
+
+When developing a graphics-intensive game or program, it is important to avoid allocating
+more GPU memory than it is physically available. When the memory is over-committed,
+various bad things can happen, depending on the specific GPU, graphics driver, and
+operating system:
+
+- It may just work without any problems.
+- The application may slow down because some memory blocks are moved to system RAM
+ and the GPU has to access them through PCI Express bus.
+- A new allocation may take very long time to complete, even few seconds, and possibly
+ freeze entire system.
+- The new allocation may fail with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+- It may even result in GPU crash (TDR), observed as `VK_ERROR_DEVICE_LOST`
+ returned somewhere later.
+
+\section staying_within_budget_querying_for_budget Querying for budget
+
+To query for current memory usage and available budget, use function vmaGetHeapBudgets().
+Returned structure #VmaBudget contains quantities expressed in bytes, per Vulkan memory heap.
+
+Please note that this function returns different information and works faster than
+vmaCalculateStatistics(). vmaGetHeapBudgets() can be called every frame or even before every
+allocation, while vmaCalculateStatistics() is intended to be used rarely,
+only to obtain statistical information, e.g. for debugging purposes.
+
+It is recommended to use <b>VK_EXT_memory_budget</b> device extension to obtain information
+about the budget from Vulkan device. VMA is able to use this extension automatically.
+When not enabled, the allocator behaves same way, but then it estimates current usage
+and available budget based on its internal information and Vulkan memory heap sizes,
+which may be less precise. In order to use this extension:
+
+1. Make sure extensions VK_EXT_memory_budget and VK_KHR_get_physical_device_properties2
+ required by it are available and enable them. Please note that the first is a device
+ extension and the second is instance extension!
+2. Use flag #VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT when creating #VmaAllocator object.
+3. Make sure to call vmaSetCurrentFrameIndex() every frame. Budget is queried from
+ Vulkan inside of it to avoid overhead of querying it with every allocation.
+
+\section staying_within_budget_controlling_memory_usage Controlling memory usage
+
+There are many ways in which you can try to stay within the budget.
+
+First, when making new allocation requires allocating a new memory block, the library
+tries not to exceed the budget automatically. If a block with default recommended size
+(e.g. 256 MB) would go over budget, a smaller block is allocated, possibly even
+dedicated memory for just this resource.
+
+If the size of the requested resource plus current memory usage is more than the
+budget, by default the library still tries to create it, leaving it to the Vulkan
+implementation whether the allocation succeeds or fails. You can change this behavior
+by using #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag. With it, the allocation is
+not made if it would exceed the budget or if the budget is already exceeded.
+VMA then tries to make the allocation from the next eligible Vulkan memory type.
+The all of them fail, the call then fails with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+Example usage pattern may be to pass the #VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT flag
+when creating resources that are not essential for the application (e.g. the texture
+of a specific object) and not to pass it when creating critically important resources
+(e.g. render targets).
+
+On AMD graphics cards there is a custom vendor extension available: <b>VK_AMD_memory_overallocation_behavior</b>
+that allows to control the behavior of the Vulkan implementation in out-of-memory cases -
+whether it should fail with an error code or still allow the allocation.
+Usage of this extension involves only passing extra structure on Vulkan device creation,
+so it is out of scope of this library.
+
+Finally, you can also use #VMA_ALLOCATION_CREATE_NEVER_ALLOCATE_BIT flag to make sure
+a new allocation is created only when it fits inside one of the existing memory blocks.
+If it would require to allocate a new block, if fails instead with `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+This also ensures that the function call is very fast because it never goes to Vulkan
+to obtain a new block.
+
+\note Creating \ref custom_memory_pools with VmaPoolCreateInfo::minBlockCount
+set to more than 0 will currently try to allocate memory blocks without checking whether they
+fit within budget.
+
+
+\page resource_aliasing Resource aliasing (overlap)
+
+New explicit graphics APIs (Vulkan and Direct3D 12), thanks to manual memory
+management, give an opportunity to alias (overlap) multiple resources in the
+same region of memory - a feature not available in the old APIs (Direct3D 11, OpenGL).
+It can be useful to save video memory, but it must be used with caution.
+
+For example, if you know the flow of your whole render frame in advance, you
+are going to use some intermediate textures or buffers only during a small range of render passes,
+and you know these ranges don't overlap in time, you can bind these resources to
+the same place in memory, even if they have completely different parameters (width, height, format etc.).
+
+![Resource aliasing (overlap)](../gfx/Aliasing.png)
+
+Such scenario is possible using VMA, but you need to create your images manually.
+Then you need to calculate parameters of an allocation to be made using formula:
+
+- allocation size = max(size of each image)
+- allocation alignment = max(alignment of each image)
+- allocation memoryTypeBits = bitwise AND(memoryTypeBits of each image)
+
+Following example shows two different images bound to the same place in memory,
+allocated to fit largest of them.
+
+\code
+// A 512x512 texture to be sampled.
+VkImageCreateInfo img1CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+img1CreateInfo.imageType = VK_IMAGE_TYPE_2D;
+img1CreateInfo.extent.width = 512;
+img1CreateInfo.extent.height = 512;
+img1CreateInfo.extent.depth = 1;
+img1CreateInfo.mipLevels = 10;
+img1CreateInfo.arrayLayers = 1;
+img1CreateInfo.format = VK_FORMAT_R8G8B8A8_SRGB;
+img1CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+img1CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+img1CreateInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT;
+img1CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+// A full screen texture to be used as color attachment.
+VkImageCreateInfo img2CreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+img2CreateInfo.imageType = VK_IMAGE_TYPE_2D;
+img2CreateInfo.extent.width = 1920;
+img2CreateInfo.extent.height = 1080;
+img2CreateInfo.extent.depth = 1;
+img2CreateInfo.mipLevels = 1;
+img2CreateInfo.arrayLayers = 1;
+img2CreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+img2CreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+img2CreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+img2CreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+img2CreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+VkImage img1;
+res = vkCreateImage(device, &img1CreateInfo, nullptr, &img1);
+VkImage img2;
+res = vkCreateImage(device, &img2CreateInfo, nullptr, &img2);
+
+VkMemoryRequirements img1MemReq;
+vkGetImageMemoryRequirements(device, img1, &img1MemReq);
+VkMemoryRequirements img2MemReq;
+vkGetImageMemoryRequirements(device, img2, &img2MemReq);
+
+VkMemoryRequirements finalMemReq = {};
+finalMemReq.size = std::max(img1MemReq.size, img2MemReq.size);
+finalMemReq.alignment = std::max(img1MemReq.alignment, img2MemReq.alignment);
+finalMemReq.memoryTypeBits = img1MemReq.memoryTypeBits & img2MemReq.memoryTypeBits;
+// Validate if(finalMemReq.memoryTypeBits != 0)
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+
+VmaAllocation alloc;
+res = vmaAllocateMemory(allocator, &finalMemReq, &allocCreateInfo, &alloc, nullptr);
+
+res = vmaBindImageMemory(allocator, alloc, img1);
+res = vmaBindImageMemory(allocator, alloc, img2);
+
+// You can use img1, img2 here, but not at the same time!
+
+vmaFreeMemory(allocator, alloc);
+vkDestroyImage(allocator, img2, nullptr);
+vkDestroyImage(allocator, img1, nullptr);
+\endcode
+
+Remember that using resources that alias in memory requires proper synchronization.
+You need to issue a memory barrier to make sure commands that use `img1` and `img2`
+don't overlap on GPU timeline.
+You also need to treat a resource after aliasing as uninitialized - containing garbage data.
+For example, if you use `img1` and then want to use `img2`, you need to issue
+an image memory barrier for `img2` with `oldLayout` = `VK_IMAGE_LAYOUT_UNDEFINED`.
+
+Additional considerations:
+
+- Vulkan also allows to interpret contents of memory between aliasing resources consistently in some cases.
+See chapter 11.8. "Memory Aliasing" of Vulkan specification or `VK_IMAGE_CREATE_ALIAS_BIT` flag.
+- You can create more complex layout where different images and buffers are bound
+at different offsets inside one large allocation. For example, one can imagine
+a big texture used in some render passes, aliasing with a set of many small buffers
+used between in some further passes. To bind a resource at non-zero offset in an allocation,
+use vmaBindBufferMemory2() / vmaBindImageMemory2().
+- Before allocating memory for the resources you want to alias, check `memoryTypeBits`
+returned in memory requirements of each resource to make sure the bits overlap.
+Some GPUs may expose multiple memory types suitable e.g. only for buffers or
+images with `COLOR_ATTACHMENT` usage, so the sets of memory types supported by your
+resources may be disjoint. Aliasing them is not possible in that case.
+
+
+\page custom_memory_pools Custom memory pools
+
+A memory pool contains a number of `VkDeviceMemory` blocks.
+The library automatically creates and manages default pool for each memory type available on the device.
+Default memory pool automatically grows in size.
+Size of allocated blocks is also variable and managed automatically.
+
+You can create custom pool and allocate memory out of it.
+It can be useful if you want to:
+
+- Keep certain kind of allocations separate from others.
+- Enforce particular, fixed size of Vulkan memory blocks.
+- Limit maximum amount of Vulkan memory allocated for that pool.
+- Reserve minimum or fixed amount of Vulkan memory always preallocated for that pool.
+- Use extra parameters for a set of your allocations that are available in #VmaPoolCreateInfo but not in
+ #VmaAllocationCreateInfo - e.g., custom minimum alignment, custom `pNext` chain.
+- Perform defragmentation on a specific subset of your allocations.
+
+To use custom memory pools:
+
+-# Fill VmaPoolCreateInfo structure.
+-# Call vmaCreatePool() to obtain #VmaPool handle.
+-# When making an allocation, set VmaAllocationCreateInfo::pool to this handle.
+ You don't need to specify any other parameters of this structure, like `usage`.
+
+Example:
+
+\code
+// Find memoryTypeIndex for the pool.
+VkBufferCreateInfo sampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+sampleBufCreateInfo.size = 0x10000; // Doesn't matter.
+sampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo sampleAllocCreateInfo = {};
+sampleAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+
+uint32_t memTypeIndex;
+VkResult res = vmaFindMemoryTypeIndexForBufferInfo(allocator,
+ &sampleBufCreateInfo, &sampleAllocCreateInfo, &memTypeIndex);
+// Check res...
+
+// Create a pool that can have at most 2 blocks, 128 MiB each.
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = memTypeIndex;
+poolCreateInfo.blockSize = 128ull * 1024 * 1024;
+poolCreateInfo.maxBlockCount = 2;
+
+VmaPool pool;
+res = vmaCreatePool(allocator, &poolCreateInfo, &pool);
+// Check res...
+
+// Allocate a buffer out of it.
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 1024;
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.pool = pool;
+
+VkBuffer buf;
+VmaAllocation alloc;
+res = vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, nullptr);
+// Check res...
+\endcode
+
+You have to free all allocations made from this pool before destroying it.
+
+\code
+vmaDestroyBuffer(allocator, buf, alloc);
+vmaDestroyPool(allocator, pool);
+\endcode
+
+New versions of this library support creating dedicated allocations in custom pools.
+It is supported only when VmaPoolCreateInfo::blockSize = 0.
+To use this feature, set VmaAllocationCreateInfo::pool to the pointer to your custom pool and
+VmaAllocationCreateInfo::flags to #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+
+\note Excessive use of custom pools is a common mistake when using this library.
+Custom pools may be useful for special purposes - when you want to
+keep certain type of resources separate e.g. to reserve minimum amount of memory
+for them or limit maximum amount of memory they can occupy. For most
+resources this is not needed and so it is not recommended to create #VmaPool
+objects and allocations out of them. Allocating from the default pool is sufficient.
+
+
+\section custom_memory_pools_MemTypeIndex Choosing memory type index
+
+When creating a pool, you must explicitly specify memory type index.
+To find the one suitable for your buffers or images, you can use helper functions
+vmaFindMemoryTypeIndexForBufferInfo(), vmaFindMemoryTypeIndexForImageInfo().
+You need to provide structures with example parameters of buffers or images
+that you are going to create in that pool.
+
+\code
+VkBufferCreateInfo exampleBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+exampleBufCreateInfo.size = 1024; // Doesn't matter
+exampleBufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+
+uint32_t memTypeIndex;
+vmaFindMemoryTypeIndexForBufferInfo(allocator, &exampleBufCreateInfo, &allocCreateInfo, &memTypeIndex);
+
+VmaPoolCreateInfo poolCreateInfo = {};
+poolCreateInfo.memoryTypeIndex = memTypeIndex;
+// ...
+\endcode
+
+When creating buffers/images allocated in that pool, provide following parameters:
+
+- `VkBufferCreateInfo`: Prefer to pass same parameters as above.
+ Otherwise you risk creating resources in a memory type that is not suitable for them, which may result in undefined behavior.
+ Using different `VK_BUFFER_USAGE_` flags may work, but you shouldn't create images in a pool intended for buffers
+ or the other way around.
+- VmaAllocationCreateInfo: You don't need to pass same parameters. Fill only `pool` member.
+ Other members are ignored anyway.
+
+\section linear_algorithm Linear allocation algorithm
+
+Each Vulkan memory block managed by this library has accompanying metadata that
+keeps track of used and unused regions. By default, the metadata structure and
+algorithm tries to find best place for new allocations among free regions to
+optimize memory usage. This way you can allocate and free objects in any order.
+
+![Default allocation algorithm](../gfx/Linear_allocator_1_algo_default.png)
+
+Sometimes there is a need to use simpler, linear allocation algorithm. You can
+create custom pool that uses such algorithm by adding flag
+#VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT to VmaPoolCreateInfo::flags while creating
+#VmaPool object. Then an alternative metadata management is used. It always
+creates new allocations after last one and doesn't reuse free regions after
+allocations freed in the middle. It results in better allocation performance and
+less memory consumed by metadata.
+
+![Linear allocation algorithm](../gfx/Linear_allocator_2_algo_linear.png)
+
+With this one flag, you can create a custom pool that can be used in many ways:
+free-at-once, stack, double stack, and ring buffer. See below for details.
+You don't need to specify explicitly which of these options you are going to use - it is detected automatically.
+
+\subsection linear_algorithm_free_at_once Free-at-once
+
+In a pool that uses linear algorithm, you still need to free all the allocations
+individually, e.g. by using vmaFreeMemory() or vmaDestroyBuffer(). You can free
+them in any order. New allocations are always made after last one - free space
+in the middle is not reused. However, when you release all the allocation and
+the pool becomes empty, allocation starts from the beginning again. This way you
+can use linear algorithm to speed up creation of allocations that you are going
+to release all at once.
+
+![Free-at-once](../gfx/Linear_allocator_3_free_at_once.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_stack Stack
+
+When you free an allocation that was created last, its space can be reused.
+Thanks to this, if you always release allocations in the order opposite to their
+creation (LIFO - Last In First Out), you can achieve behavior of a stack.
+
+![Stack](../gfx/Linear_allocator_4_stack.png)
+
+This mode is also available for pools created with VmaPoolCreateInfo::maxBlockCount
+value that allows multiple memory blocks.
+
+\subsection linear_algorithm_double_stack Double stack
+
+The space reserved by a custom pool with linear algorithm may be used by two
+stacks:
+
+- First, default one, growing up from offset 0.
+- Second, "upper" one, growing down from the end towards lower offsets.
+
+To make allocation from the upper stack, add flag #VMA_ALLOCATION_CREATE_UPPER_ADDRESS_BIT
+to VmaAllocationCreateInfo::flags.
+
+![Double stack](../gfx/Linear_allocator_7_double_stack.png)
+
+Double stack is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+When the two stacks' ends meet so there is not enough space between them for a
+new allocation, such allocation fails with usual
+`VK_ERROR_OUT_OF_DEVICE_MEMORY` error.
+
+\subsection linear_algorithm_ring_buffer Ring buffer
+
+When you free some allocations from the beginning and there is not enough free space
+for a new one at the end of a pool, allocator's "cursor" wraps around to the
+beginning and starts allocation there. Thanks to this, if you always release
+allocations in the same order as you created them (FIFO - First In First Out),
+you can achieve behavior of a ring buffer / queue.
+
+![Ring buffer](../gfx/Linear_allocator_5_ring_buffer.png)
+
+Ring buffer is available only in pools with one memory block -
+VmaPoolCreateInfo::maxBlockCount must be 1. Otherwise behavior is undefined.
+
+\note \ref defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT.
+
+
+\page defragmentation Defragmentation
+
+Interleaved allocations and deallocations of many objects of varying size can
+cause fragmentation over time, which can lead to a situation where the library is unable
+to find a continuous range of free memory for a new allocation despite there is
+enough free space, just scattered across many small free ranges between existing
+allocations.
+
+To mitigate this problem, you can use defragmentation feature.
+It doesn't happen automatically though and needs your cooperation,
+because VMA is a low level library that only allocates memory.
+It cannot recreate buffers and images in a new place as it doesn't remember the contents of `VkBufferCreateInfo` / `VkImageCreateInfo` structures.
+It cannot copy their contents as it doesn't record any commands to a command buffer.
+
+Example:
+
+\code
+VmaDefragmentationInfo defragInfo = {};
+defragInfo.pool = myPool;
+defragInfo.flags = VMA_DEFRAGMENTATION_FLAG_ALGORITHM_FAST_BIT;
+
+VmaDefragmentationContext defragCtx;
+VkResult res = vmaBeginDefragmentation(allocator, &defragInfo, &defragCtx);
+// Check res...
+
+for(;;)
+{
+ VmaDefragmentationPassMoveInfo pass;
+ res = vmaBeginDefragmentationPass(allocator, defragCtx, &pass);
+ if(res == VK_SUCCESS)
+ break;
+ else if(res != VK_INCOMPLETE)
+ // Handle error...
+
+ for(uint32_t i = 0; i < pass.moveCount; ++i)
+ {
+ // Inspect pass.pMoves[i].srcAllocation, identify what buffer/image it represents.
+ VmaAllocationInfo allocInfo;
+ vmaGetAllocationInfo(allocator, pMoves[i].srcAllocation, &allocInfo);
+ MyEngineResourceData* resData = (MyEngineResourceData*)allocInfo.pUserData;
+
+ // Recreate and bind this buffer/image at: pass.pMoves[i].dstMemory, pass.pMoves[i].dstOffset.
+ VkImageCreateInfo imgCreateInfo = ...
+ VkImage newImg;
+ res = vkCreateImage(device, &imgCreateInfo, nullptr, &newImg);
+ // Check res...
+ res = vmaBindImageMemory(allocator, pMoves[i].dstTmpAllocation, newImg);
+ // Check res...
+
+ // Issue a vkCmdCopyBuffer/vkCmdCopyImage to copy its content to the new place.
+ vkCmdCopyImage(cmdBuf, resData->img, ..., newImg, ...);
+ }
+
+ // Make sure the copy commands finished executing.
+ vkWaitForFences(...);
+
+ // Destroy old buffers/images bound with pass.pMoves[i].srcAllocation.
+ for(uint32_t i = 0; i < pass.moveCount; ++i)
+ {
+ // ...
+ vkDestroyImage(device, resData->img, nullptr);
+ }
+
+ // Update appropriate descriptors to point to the new places...
+
+ res = vmaEndDefragmentationPass(allocator, defragCtx, &pass);
+ if(res == VK_SUCCESS)
+ break;
+ else if(res != VK_INCOMPLETE)
+ // Handle error...
+}
+
+vmaEndDefragmentation(allocator, defragCtx, nullptr);
+\endcode
+
+Although functions like vmaCreateBuffer(), vmaCreateImage(), vmaDestroyBuffer(), vmaDestroyImage()
+create/destroy an allocation and a buffer/image at once, these are just a shortcut for
+creating the resource, allocating memory, and binding them together.
+Defragmentation works on memory allocations only. You must handle the rest manually.
+Defragmentation is an iterative process that should repreat "passes" as long as related functions
+return `VK_INCOMPLETE` not `VK_SUCCESS`.
+In each pass:
+
+1. vmaBeginDefragmentationPass() function call:
+ - Calculates and returns the list of allocations to be moved in this pass.
+ Note this can be a time-consuming process.
+ - Reserves destination memory for them by creating temporary destination allocations
+ that you can query for their `VkDeviceMemory` + offset using vmaGetAllocationInfo().
+2. Inside the pass, **you should**:
+ - Inspect the returned list of allocations to be moved.
+ - Create new buffers/images and bind them at the returned destination temporary allocations.
+ - Copy data from source to destination resources if necessary.
+ - Destroy the source buffers/images, but NOT their allocations.
+3. vmaEndDefragmentationPass() function call:
+ - Frees the source memory reserved for the allocations that are moved.
+ - Modifies source #VmaAllocation objects that are moved to point to the destination reserved memory.
+ - Frees `VkDeviceMemory` blocks that became empty.
+
+Unlike in previous iterations of the defragmentation API, there is no list of "movable" allocations passed as a parameter.
+Defragmentation algorithm tries to move all suitable allocations.
+You can, however, refuse to move some of them inside a defragmentation pass, by setting
+`pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
+This is not recommended and may result in suboptimal packing of the allocations after defragmentation.
+If you cannot ensure any allocation can be moved, it is better to keep movable allocations separate in a custom pool.
+
+Inside a pass, for each allocation that should be moved:
+
+- You should copy its data from the source to the destination place by calling e.g. `vkCmdCopyBuffer()`, `vkCmdCopyImage()`.
+ - You need to make sure these commands finished executing before destroying the source buffers/images and before calling vmaEndDefragmentationPass().
+- If a resource doesn't contain any meaningful data, e.g. it is a transient color attachment image to be cleared,
+ filled, and used temporarily in each rendering frame, you can just recreate this image
+ without copying its data.
+- If the resource is in `HOST_VISIBLE` and `HOST_CACHED` memory, you can copy its data on the CPU
+ using `memcpy()`.
+- If you cannot move the allocation, you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_IGNORE.
+ This will cancel the move.
+ - vmaEndDefragmentationPass() will then free the destination memory
+ not the source memory of the allocation, leaving it unchanged.
+- If you decide the allocation is unimportant and can be destroyed instead of moved (e.g. it wasn't used for long time),
+ you can set `pass.pMoves[i].operation` to #VMA_DEFRAGMENTATION_MOVE_OPERATION_DESTROY.
+ - vmaEndDefragmentationPass() will then free both source and destination memory, and will destroy the source #VmaAllocation object.
+
+You can defragment a specific custom pool by setting VmaDefragmentationInfo::pool
+(like in the example above) or all the default pools by setting this member to null.
+
+Defragmentation is always performed in each pool separately.
+Allocations are never moved between different Vulkan memory types.
+The size of the destination memory reserved for a moved allocation is the same as the original one.
+Alignment of an allocation as it was determined using `vkGetBufferMemoryRequirements()` etc. is also respected after defragmentation.
+Buffers/images should be recreated with the same `VkBufferCreateInfo` / `VkImageCreateInfo` parameters as the original ones.
+
+You can perform the defragmentation incrementally to limit the number of allocations and bytes to be moved
+in each pass, e.g. to call it in sync with render frames and not to experience too big hitches.
+See members: VmaDefragmentationInfo::maxBytesPerPass, VmaDefragmentationInfo::maxAllocationsPerPass.
+
+It is also safe to perform the defragmentation asynchronously to render frames and other Vulkan and VMA
+usage, possibly from multiple threads, with the exception that allocations
+returned in VmaDefragmentationPassMoveInfo::pMoves shouldn't be destroyed until the defragmentation pass is ended.
+
+<b>Mapping</b> is preserved on allocations that are moved during defragmentation.
+Whether through #VMA_ALLOCATION_CREATE_MAPPED_BIT or vmaMapMemory(), the allocations
+are mapped at their new place. Of course, pointer to the mapped data changes, so it needs to be queried
+using VmaAllocationInfo::pMappedData.
+
+\note Defragmentation is not supported in custom pools created with #VMA_POOL_CREATE_LINEAR_ALGORITHM_BIT.
+
+
+\page statistics Statistics
+
+This library contains several functions that return information about its internal state,
+especially the amount of memory allocated from Vulkan.
+
+\section statistics_numeric_statistics Numeric statistics
+
+If you need to obtain basic statistics about memory usage per heap, together with current budget,
+you can call function vmaGetHeapBudgets() and inspect structure #VmaBudget.
+This is useful to keep track of memory usage and stay withing budget
+(see also \ref staying_within_budget).
+Example:
+
+\code
+uint32_t heapIndex = ...
+
+VmaBudget budgets[VK_MAX_MEMORY_HEAPS];
+vmaGetHeapBudgets(allocator, budgets);
+
+printf("My heap currently has %u allocations taking %llu B,\n",
+ budgets[heapIndex].statistics.allocationCount,
+ budgets[heapIndex].statistics.allocationBytes);
+printf("allocated out of %u Vulkan device memory blocks taking %llu B,\n",
+ budgets[heapIndex].statistics.blockCount,
+ budgets[heapIndex].statistics.blockBytes);
+printf("Vulkan reports total usage %llu B with budget %llu B.\n",
+ budgets[heapIndex].usage,
+ budgets[heapIndex].budget);
+\endcode
+
+You can query for more detailed statistics per memory heap, type, and totals,
+including minimum and maximum allocation size and unused range size,
+by calling function vmaCalculateStatistics() and inspecting structure #VmaTotalStatistics.
+This function is slower though, as it has to traverse all the internal data structures,
+so it should be used only for debugging purposes.
+
+You can query for statistics of a custom pool using function vmaGetPoolStatistics()
+or vmaCalculatePoolStatistics().
+
+You can query for information about a specific allocation using function vmaGetAllocationInfo().
+It fill structure #VmaAllocationInfo.
+
+\section statistics_json_dump JSON dump
+
+You can dump internal state of the allocator to a string in JSON format using function vmaBuildStatsString().
+The result is guaranteed to be correct JSON.
+It uses ANSI encoding.
+Any strings provided by user (see [Allocation names](@ref allocation_names))
+are copied as-is and properly escaped for JSON, so if they use UTF-8, ISO-8859-2 or any other encoding,
+this JSON string can be treated as using this encoding.
+It must be freed using function vmaFreeStatsString().
+
+The format of this JSON string is not part of official documentation of the library,
+but it will not change in backward-incompatible way without increasing library major version number
+and appropriate mention in changelog.
+
+The JSON string contains all the data that can be obtained using vmaCalculateStatistics().
+It can also contain detailed map of allocated memory blocks and their regions -
+free and occupied by allocations.
+This allows e.g. to visualize the memory or assess fragmentation.
+
+
+\page allocation_annotation Allocation names and user data
+
+\section allocation_user_data Allocation user data
+
+You can annotate allocations with your own information, e.g. for debugging purposes.
+To do that, fill VmaAllocationCreateInfo::pUserData field when creating
+an allocation. It is an opaque `void*` pointer. You can use it e.g. as a pointer,
+some handle, index, key, ordinal number or any other value that would associate
+the allocation with your custom metadata.
+It is useful to identify appropriate data structures in your engine given #VmaAllocation,
+e.g. when doing \ref defragmentation.
+
+\code
+VkBufferCreateInfo bufCreateInfo = ...
+
+MyBufferMetadata* pMetadata = CreateBufferMetadata();
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.pUserData = pMetadata;
+
+VkBuffer buffer;
+VmaAllocation allocation;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buffer, &allocation, nullptr);
+\endcode
+
+The pointer may be later retrieved as VmaAllocationInfo::pUserData:
+
+\code
+VmaAllocationInfo allocInfo;
+vmaGetAllocationInfo(allocator, allocation, &allocInfo);
+MyBufferMetadata* pMetadata = (MyBufferMetadata*)allocInfo.pUserData;
+\endcode
+
+It can also be changed using function vmaSetAllocationUserData().
+
+Values of (non-zero) allocations' `pUserData` are printed in JSON report created by
+vmaBuildStatsString() in hexadecimal form.
+
+\section allocation_names Allocation names
+
+An allocation can also carry a null-terminated string, giving a name to the allocation.
+To set it, call vmaSetAllocationName().
+The library creates internal copy of the string, so the pointer you pass doesn't need
+to be valid for whole lifetime of the allocation. You can free it after the call.
+
+\code
+std::string imageName = "Texture: ";
+imageName += fileName;
+vmaSetAllocationName(allocator, allocation, imageName.c_str());
+\endcode
+
+The string can be later retrieved by inspecting VmaAllocationInfo::pName.
+It is also printed in JSON report created by vmaBuildStatsString().
+
+\note Setting string name to VMA allocation doesn't automatically set it to the Vulkan buffer or image created with it.
+You must do it manually using an extension like VK_EXT_debug_utils, which is independent of this library.
+
+
+\page virtual_allocator Virtual allocator
+
+As an extra feature, the core allocation algorithm of the library is exposed through a simple and convenient API of "virtual allocator".
+It doesn't allocate any real GPU memory. It just keeps track of used and free regions of a "virtual block".
+You can use it to allocate your own memory or other objects, even completely unrelated to Vulkan.
+A common use case is sub-allocation of pieces of one large GPU buffer.
+
+\section virtual_allocator_creating_virtual_block Creating virtual block
+
+To use this functionality, there is no main "allocator" object.
+You don't need to have #VmaAllocator object created.
+All you need to do is to create a separate #VmaVirtualBlock object for each block of memory you want to be managed by the allocator:
+
+-# Fill in #VmaVirtualBlockCreateInfo structure.
+-# Call vmaCreateVirtualBlock(). Get new #VmaVirtualBlock object.
+
+Example:
+
+\code
+VmaVirtualBlockCreateInfo blockCreateInfo = {};
+blockCreateInfo.size = 1048576; // 1 MB
+
+VmaVirtualBlock block;
+VkResult res = vmaCreateVirtualBlock(&blockCreateInfo, &block);
+\endcode
+
+\section virtual_allocator_making_virtual_allocations Making virtual allocations
+
+#VmaVirtualBlock object contains internal data structure that keeps track of free and occupied regions
+using the same code as the main Vulkan memory allocator.
+Similarly to #VmaAllocation for standard GPU allocations, there is #VmaVirtualAllocation type
+that represents an opaque handle to an allocation withing the virtual block.
+
+In order to make such allocation:
+
+-# Fill in #VmaVirtualAllocationCreateInfo structure.
+-# Call vmaVirtualAllocate(). Get new #VmaVirtualAllocation object that represents the allocation.
+ You can also receive `VkDeviceSize offset` that was assigned to the allocation.
+
+Example:
+
+\code
+VmaVirtualAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.size = 4096; // 4 KB
+
+VmaVirtualAllocation alloc;
+VkDeviceSize offset;
+res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, &offset);
+if(res == VK_SUCCESS)
+{
+ // Use the 4 KB of your memory starting at offset.
+}
+else
+{
+ // Allocation failed - no space for it could be found. Handle this error!
+}
+\endcode
+
+\section virtual_allocator_deallocation Deallocation
+
+When no longer needed, an allocation can be freed by calling vmaVirtualFree().
+You can only pass to this function an allocation that was previously returned by vmaVirtualAllocate()
+called for the same #VmaVirtualBlock.
+
+When whole block is no longer needed, the block object can be released by calling vmaDestroyVirtualBlock().
+All allocations must be freed before the block is destroyed, which is checked internally by an assert.
+However, if you don't want to call vmaVirtualFree() for each allocation, you can use vmaClearVirtualBlock() to free them all at once -
+a feature not available in normal Vulkan memory allocator. Example:
+
+\code
+vmaVirtualFree(block, alloc);
+vmaDestroyVirtualBlock(block);
+\endcode
+
+\section virtual_allocator_allocation_parameters Allocation parameters
+
+You can attach a custom pointer to each allocation by using vmaSetVirtualAllocationUserData().
+Its default value is null.
+It can be used to store any data that needs to be associated with that allocation - e.g. an index, a handle, or a pointer to some
+larger data structure containing more information. Example:
+
+\code
+struct CustomAllocData
+{
+ std::string m_AllocName;
+};
+CustomAllocData* allocData = new CustomAllocData();
+allocData->m_AllocName = "My allocation 1";
+vmaSetVirtualAllocationUserData(block, alloc, allocData);
+\endcode
+
+The pointer can later be fetched, along with allocation offset and size, by passing the allocation handle to function
+vmaGetVirtualAllocationInfo() and inspecting returned structure #VmaVirtualAllocationInfo.
+If you allocated a new object to be used as the custom pointer, don't forget to delete that object before freeing the allocation!
+Example:
+
+\code
+VmaVirtualAllocationInfo allocInfo;
+vmaGetVirtualAllocationInfo(block, alloc, &allocInfo);
+delete (CustomAllocData*)allocInfo.pUserData;
+
+vmaVirtualFree(block, alloc);
+\endcode
+
+\section virtual_allocator_alignment_and_units Alignment and units
+
+It feels natural to express sizes and offsets in bytes.
+If an offset of an allocation needs to be aligned to a multiply of some number (e.g. 4 bytes), you can fill optional member
+VmaVirtualAllocationCreateInfo::alignment to request it. Example:
+
+\code
+VmaVirtualAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.size = 4096; // 4 KB
+allocCreateInfo.alignment = 4; // Returned offset must be a multiply of 4 B
+
+VmaVirtualAllocation alloc;
+res = vmaVirtualAllocate(block, &allocCreateInfo, &alloc, nullptr);
+\endcode
+
+Alignments of different allocations made from one block may vary.
+However, if all alignments and sizes are always multiply of some size e.g. 4 B or `sizeof(MyDataStruct)`,
+you can express all sizes, alignments, and offsets in multiples of that size instead of individual bytes.
+It might be more convenient, but you need to make sure to use this new unit consistently in all the places:
+
+- VmaVirtualBlockCreateInfo::size
+- VmaVirtualAllocationCreateInfo::size and VmaVirtualAllocationCreateInfo::alignment
+- Using offset returned by vmaVirtualAllocate() or in VmaVirtualAllocationInfo::offset
+
+\section virtual_allocator_statistics Statistics
+
+You can obtain statistics of a virtual block using vmaGetVirtualBlockStatistics()
+(to get brief statistics that are fast to calculate)
+or vmaCalculateVirtualBlockStatistics() (to get more detailed statistics, slower to calculate).
+The functions fill structures #VmaStatistics, #VmaDetailedStatistics respectively - same as used by the normal Vulkan memory allocator.
+Example:
+
+\code
+VmaStatistics stats;
+vmaGetVirtualBlockStatistics(block, &stats);
+printf("My virtual block has %llu bytes used by %u virtual allocations\n",
+ stats.allocationBytes, stats.allocationCount);
+\endcode
+
+You can also request a full list of allocations and free regions as a string in JSON format by calling
+vmaBuildVirtualBlockStatsString().
+Returned string must be later freed using vmaFreeVirtualBlockStatsString().
+The format of this string differs from the one returned by the main Vulkan allocator, but it is similar.
+
+\section virtual_allocator_additional_considerations Additional considerations
+
+The "virtual allocator" functionality is implemented on a level of individual memory blocks.
+Keeping track of a whole collection of blocks, allocating new ones when out of free space,
+deleting empty ones, and deciding which one to try first for a new allocation must be implemented by the user.
+
+Alternative allocation algorithms are supported, just like in custom pools of the real GPU memory.
+See enum #VmaVirtualBlockCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_BLOCK_CREATE_LINEAR_ALGORITHM_BIT).
+You can find their description in chapter \ref custom_memory_pools.
+Allocation strategies are also supported.
+See enum #VmaVirtualAllocationCreateFlagBits to learn how to specify them (e.g. #VMA_VIRTUAL_ALLOCATION_CREATE_STRATEGY_MIN_TIME_BIT).
+
+Following features are supported only by the allocator of the real GPU memory and not by virtual allocations:
+buffer-image granularity, `VMA_DEBUG_MARGIN`, `VMA_MIN_ALIGNMENT`.
+
+
+\page debugging_memory_usage Debugging incorrect memory usage
+
+If you suspect a bug with memory usage, like usage of uninitialized memory or
+memory being overwritten out of bounds of an allocation,
+you can use debug features of this library to verify this.
+
+\section debugging_memory_usage_initialization Memory initialization
+
+If you experience a bug with incorrect and nondeterministic data in your program and you suspect uninitialized memory to be used,
+you can enable automatic memory initialization to verify this.
+To do it, define macro `VMA_DEBUG_INITIALIZE_ALLOCATIONS` to 1.
+
+\code
+#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1
+#include "vk_mem_alloc.h"
+\endcode
+
+It makes memory of new allocations initialized to bit pattern `0xDCDCDCDC`.
+Before an allocation is destroyed, its memory is filled with bit pattern `0xEFEFEFEF`.
+Memory is automatically mapped and unmapped if necessary.
+
+If you find these values while debugging your program, good chances are that you incorrectly
+read Vulkan memory that is allocated but not initialized, or already freed, respectively.
+
+Memory initialization works only with memory types that are `HOST_VISIBLE` and with allocations that can be mapped.
+It works also with dedicated allocations.
+
+\section debugging_memory_usage_margins Margins
+
+By default, allocations are laid out in memory blocks next to each other if possible
+(considering required alignment, `bufferImageGranularity`, and `nonCoherentAtomSize`).
+
+![Allocations without margin](../gfx/Margins_1.png)
+
+Define macro `VMA_DEBUG_MARGIN` to some non-zero value (e.g. 16) to enforce specified
+number of bytes as a margin after every allocation.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#include "vk_mem_alloc.h"
+\endcode
+
+![Allocations with margin](../gfx/Margins_2.png)
+
+If your bug goes away after enabling margins, it means it may be caused by memory
+being overwritten outside of allocation boundaries. It is not 100% certain though.
+Change in application behavior may also be caused by different order and distribution
+of allocations across memory blocks after margins are applied.
+
+Margins work with all types of memory.
+
+Margin is applied only to allocations made out of memory blocks and not to dedicated
+allocations, which have their own memory block of specific size.
+It is thus not applied to allocations made using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT flag
+or those automatically decided to put into dedicated allocations, e.g. due to its
+large size or recommended by VK_KHR_dedicated_allocation extension.
+
+Margins appear in [JSON dump](@ref statistics_json_dump) as part of free space.
+
+Note that enabling margins increases memory usage and fragmentation.
+
+Margins do not apply to \ref virtual_allocator.
+
+\section debugging_memory_usage_corruption_detection Corruption detection
+
+You can additionally define macro `VMA_DEBUG_DETECT_CORRUPTION` to 1 to enable validation
+of contents of the margins.
+
+\code
+#define VMA_DEBUG_MARGIN 16
+#define VMA_DEBUG_DETECT_CORRUPTION 1
+#include "vk_mem_alloc.h"
+\endcode
+
+When this feature is enabled, number of bytes specified as `VMA_DEBUG_MARGIN`
+(it must be multiply of 4) after every allocation is filled with a magic number.
+This idea is also know as "canary".
+Memory is automatically mapped and unmapped if necessary.
+
+This number is validated automatically when the allocation is destroyed.
+If it is not equal to the expected value, `VMA_ASSERT()` is executed.
+It clearly means that either CPU or GPU overwritten the memory outside of boundaries of the allocation,
+which indicates a serious bug.
+
+You can also explicitly request checking margins of all allocations in all memory blocks
+that belong to specified memory types by using function vmaCheckCorruption(),
+or in memory blocks that belong to specified custom pool, by using function
+vmaCheckPoolCorruption().
+
+Margin validation (corruption detection) works only for memory types that are
+`HOST_VISIBLE` and `HOST_COHERENT`.
+
+
+\page opengl_interop OpenGL Interop
+
+VMA provides some features that help with interoperability with OpenGL.
+
+\section opengl_interop_exporting_memory Exporting memory
+
+If you want to attach `VkExportMemoryAllocateInfoKHR` structure to `pNext` chain of memory allocations made by the library:
+
+It is recommended to create \ref custom_memory_pools for such allocations.
+Define and fill in your `VkExportMemoryAllocateInfoKHR` structure and attach it to VmaPoolCreateInfo::pMemoryAllocateNext
+while creating the custom pool.
+Please note that the structure must remain alive and unchanged for the whole lifetime of the #VmaPool,
+not only while creating it, as no copy of the structure is made,
+but its original pointer is used for each allocation instead.
+
+If you want to export all memory allocated by the library from certain memory types,
+also dedicated allocations or other allocations made from default pools,
+an alternative solution is to fill in VmaAllocatorCreateInfo::pTypeExternalMemoryHandleTypes.
+It should point to an array with `VkExternalMemoryHandleTypeFlagsKHR` to be automatically passed by the library
+through `VkExportMemoryAllocateInfoKHR` on each allocation made from a specific memory type.
+Please note that new versions of the library also support dedicated allocations created in custom pools.
+
+You should not mix these two methods in a way that allows to apply both to the same memory type.
+Otherwise, `VkExportMemoryAllocateInfoKHR` structure would be attached twice to the `pNext` chain of `VkMemoryAllocateInfo`.
+
+
+\section opengl_interop_custom_alignment Custom alignment
+
+Buffers or images exported to a different API like OpenGL may require a different alignment,
+higher than the one used by the library automatically, queried from functions like `vkGetBufferMemoryRequirements`.
+To impose such alignment:
+
+It is recommended to create \ref custom_memory_pools for such allocations.
+Set VmaPoolCreateInfo::minAllocationAlignment member to the minimum alignment required for each allocation
+to be made out of this pool.
+The alignment actually used will be the maximum of this member and the alignment returned for the specific buffer or image
+from a function like `vkGetBufferMemoryRequirements`, which is called by VMA automatically.
+
+If you want to create a buffer with a specific minimum alignment out of default pools,
+use special function vmaCreateBufferWithAlignment(), which takes additional parameter `minAlignment`.
+
+Note the problem of alignment affects only resources placed inside bigger `VkDeviceMemory` blocks and not dedicated
+allocations, as these, by definition, always have alignment = 0 because the resource is bound to the beginning of its dedicated block.
+Contrary to Direct3D 12, Vulkan doesn't have a concept of alignment of the entire memory block passed on its allocation.
+
+
+\page usage_patterns Recommended usage patterns
+
+Vulkan gives great flexibility in memory allocation.
+This chapter shows the most common patterns.
+
+See also slides from talk:
+[Sawicki, Adam. Advanced Graphics Techniques Tutorial: Memory management in Vulkan and DX12. Game Developers Conference, 2018](https://www.gdcvault.com/play/1025458/Advanced-Graphics-Techniques-Tutorial-New)
+
+
+\section usage_patterns_gpu_only GPU-only resource
+
+<b>When:</b>
+Any resources that you frequently write and read on GPU,
+e.g. images used as color attachments (aka "render targets"), depth-stencil attachments,
+images/buffers used as storage image/buffer (aka "Unordered Access View (UAV)").
+
+<b>What to do:</b>
+Let the library select the optimal memory type, which will likely have `VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT`.
+
+\code
+VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+imgCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+imgCreateInfo.extent.width = 3840;
+imgCreateInfo.extent.height = 2160;
+imgCreateInfo.extent.depth = 1;
+imgCreateInfo.mipLevels = 1;
+imgCreateInfo.arrayLayers = 1;
+imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+allocCreateInfo.priority = 1.0f;
+
+VkImage img;
+VmaAllocation alloc;
+vmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr);
+\endcode
+
+<b>Also consider:</b>
+Consider creating them as dedicated allocations using #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT,
+especially if they are large or if you plan to destroy and recreate them with different sizes
+e.g. when display resolution changes.
+Prefer to create such resources first and all other GPU resources (like textures and vertex buffers) later.
+When VK_EXT_memory_priority extension is enabled, it is also worth setting high priority to such allocation
+to decrease chances to be evicted to system memory by the operating system.
+
+\section usage_patterns_staging_copy_upload Staging copy for upload
+
+<b>When:</b>
+A "staging" buffer than you want to map and fill from CPU code, then use as a source od transfer
+to some GPU resource.
+
+<b>What to do:</b>
+Use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT.
+Let the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 65536;
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
+ VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+...
+
+memcpy(allocInfo.pMappedData, myData, myDataSize);
+\endcode
+
+<b>Also consider:</b>
+You can map the allocation using vmaMapMemory() or you can create it as persistenly mapped
+using #VMA_ALLOCATION_CREATE_MAPPED_BIT, as in the example above.
+
+
+\section usage_patterns_readback Readback
+
+<b>When:</b>
+Buffers for data written by or transferred from the GPU that you want to read back on the CPU,
+e.g. results of some computations.
+
+<b>What to do:</b>
+Use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT.
+Let the library select the optimal memory type, which will always have `VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT`
+and `VK_MEMORY_PROPERTY_HOST_CACHED_BIT`.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 65536;
+bufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT |
+ VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+...
+
+const float* downloadedData = (const float*)allocInfo.pMappedData;
+\endcode
+
+
+\section usage_patterns_advanced_data_uploading Advanced data uploading
+
+For resources that you frequently write on CPU via mapped pointer and
+freqnently read on GPU e.g. as a uniform buffer (also called "dynamic"), multiple options are possible:
+
+-# Easiest solution is to have one copy of the resource in `HOST_VISIBLE` memory,
+ even if it means system RAM (not `DEVICE_LOCAL`) on systems with a discrete graphics card,
+ and make the device reach out to that resource directly.
+ - Reads performed by the device will then go through PCI Express bus.
+ The performace of this access may be limited, but it may be fine depending on the size
+ of this resource (whether it is small enough to quickly end up in GPU cache) and the sparsity
+ of access.
+-# On systems with unified memory (e.g. AMD APU or Intel integrated graphics, mobile chips),
+ a memory type may be available that is both `HOST_VISIBLE` (available for mapping) and `DEVICE_LOCAL`
+ (fast to access from the GPU). Then, it is likely the best choice for such type of resource.
+-# Systems with a discrete graphics card and separate video memory may or may not expose
+ a memory type that is both `HOST_VISIBLE` and `DEVICE_LOCAL`, also known as Base Address Register (BAR).
+ If they do, it represents a piece of VRAM (or entire VRAM, if ReBAR is enabled in the motherboard BIOS)
+ that is available to CPU for mapping.
+ - Writes performed by the host to that memory go through PCI Express bus.
+ The performance of these writes may be limited, but it may be fine, especially on PCIe 4.0,
+ as long as rules of using uncached and write-combined memory are followed - only sequential writes and no reads.
+-# Finally, you may need or prefer to create a separate copy of the resource in `DEVICE_LOCAL` memory,
+ a separate "staging" copy in `HOST_VISIBLE` memory and perform an explicit transfer command between them.
+
+Thankfully, VMA offers an aid to create and use such resources in the the way optimal
+for the current Vulkan device. To help the library make the best choice,
+use flag #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT together with
+#VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT.
+It will then prefer a memory type that is both `DEVICE_LOCAL` and `HOST_VISIBLE` (integrated memory or BAR),
+but if no such memory type is available or allocation from it fails
+(PC graphics cards have only 256 MB of BAR by default, unless ReBAR is supported and enabled in BIOS),
+it will fall back to `DEVICE_LOCAL` memory for fast GPU access.
+It is then up to you to detect that the allocation ended up in a memory type that is not `HOST_VISIBLE`,
+so you need to create another "staging" allocation and perform explicit transfers.
+
+\code
+VkBufferCreateInfo bufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+bufCreateInfo.size = 65536;
+bufCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
+ VMA_ALLOCATION_CREATE_HOST_ACCESS_ALLOW_TRANSFER_INSTEAD_BIT |
+ VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+VkBuffer buf;
+VmaAllocation alloc;
+VmaAllocationInfo allocInfo;
+vmaCreateBuffer(allocator, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);
+
+VkMemoryPropertyFlags memPropFlags;
+vmaGetAllocationMemoryProperties(allocator, alloc, &memPropFlags);
+
+if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+{
+ // Allocation ended up in a mappable memory and is already mapped - write to it directly.
+
+ // [Executed in runtime]:
+ memcpy(allocInfo.pMappedData, myData, myDataSize);
+}
+else
+{
+ // Allocation ended up in a non-mappable memory - need to transfer.
+ VkBufferCreateInfo stagingBufCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
+ stagingBufCreateInfo.size = 65536;
+ stagingBufCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
+
+ VmaAllocationCreateInfo stagingAllocCreateInfo = {};
+ stagingAllocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+ stagingAllocCreateInfo.flags = VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT |
+ VMA_ALLOCATION_CREATE_MAPPED_BIT;
+
+ VkBuffer stagingBuf;
+ VmaAllocation stagingAlloc;
+ VmaAllocationInfo stagingAllocInfo;
+ vmaCreateBuffer(allocator, &stagingBufCreateInfo, &stagingAllocCreateInfo,
+ &stagingBuf, &stagingAlloc, stagingAllocInfo);
+
+ // [Executed in runtime]:
+ memcpy(stagingAllocInfo.pMappedData, myData, myDataSize);
+ //vkCmdPipelineBarrier: VK_ACCESS_HOST_WRITE_BIT --> VK_ACCESS_TRANSFER_READ_BIT
+ VkBufferCopy bufCopy = {
+ 0, // srcOffset
+ 0, // dstOffset,
+ myDataSize); // size
+ vkCmdCopyBuffer(cmdBuf, stagingBuf, buf, 1, &bufCopy);
+}
+\endcode
+
+\section usage_patterns_other_use_cases Other use cases
+
+Here are some other, less obvious use cases and their recommended settings:
+
+- An image that is used only as transfer source and destination, but it should stay on the device,
+ as it is used to temporarily store a copy of some texture, e.g. from the current to the next frame,
+ for temporal antialiasing or other temporal effects.
+ - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT`
+ - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO
+- An image that is used only as transfer source and destination, but it should be placed
+ in the system RAM despite it doesn't need to be mapped, because it serves as a "swap" copy to evict
+ least recently used textures from VRAM.
+ - Use `VkImageCreateInfo::usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT`
+ - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
+ as VMA needs a hint here to differentiate from the previous case.
+- A buffer that you want to map and write from the CPU, directly read from the GPU
+ (e.g. as a uniform or vertex buffer), but you have a clear preference to place it in device or
+ host memory due to its large size.
+ - Use `VkBufferCreateInfo::usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT`
+ - Use VmaAllocationCreateInfo::usage = #VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE or #VMA_MEMORY_USAGE_AUTO_PREFER_HOST
+ - Use VmaAllocationCreateInfo::flags = #VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT
+
+
+\page configuration Configuration
+
+Please check "CONFIGURATION SECTION" in the code to find macros that you can define
+before each include of this file or change directly in this file to provide
+your own implementation of basic facilities like assert, `min()` and `max()` functions,
+mutex, atomic etc.
+The library uses its own implementation of containers by default, but you can switch to using
+STL containers instead.
+
+For example, define `VMA_ASSERT(expr)` before including the library to provide
+custom implementation of the assertion, compatible with your project.
+By default it is defined to standard C `assert(expr)` in `_DEBUG` configuration
+and empty otherwise.
+
+\section config_Vulkan_functions Pointers to Vulkan functions
+
+There are multiple ways to import pointers to Vulkan functions in the library.
+In the simplest case you don't need to do anything.
+If the compilation or linking of your program or the initialization of the #VmaAllocator
+doesn't work for you, you can try to reconfigure it.
+
+First, the allocator tries to fetch pointers to Vulkan functions linked statically,
+like this:
+
+\code
+m_VulkanFunctions.vkAllocateMemory = (PFN_vkAllocateMemory)vkAllocateMemory;
+\endcode
+
+If you want to disable this feature, set configuration macro: `#define VMA_STATIC_VULKAN_FUNCTIONS 0`.
+
+Second, you can provide the pointers yourself by setting member VmaAllocatorCreateInfo::pVulkanFunctions.
+You can fetch them e.g. using functions `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` or
+by using a helper library like [volk](https://github.com/zeux/volk).
+
+Third, VMA tries to fetch remaining pointers that are still null by calling
+`vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` on its own.
+You need to only fill in VmaVulkanFunctions::vkGetInstanceProcAddr and VmaVulkanFunctions::vkGetDeviceProcAddr.
+Other pointers will be fetched automatically.
+If you want to disable this feature, set configuration macro: `#define VMA_DYNAMIC_VULKAN_FUNCTIONS 0`.
+
+Finally, all the function pointers required by the library (considering selected
+Vulkan version and enabled extensions) are checked with `VMA_ASSERT` if they are not null.
+
+
+\section custom_memory_allocator Custom host memory allocator
+
+If you use custom allocator for CPU memory rather than default operator `new`
+and `delete` from C++, you can make this library using your allocator as well
+by filling optional member VmaAllocatorCreateInfo::pAllocationCallbacks. These
+functions will be passed to Vulkan, as well as used by the library itself to
+make any CPU-side allocations.
+
+\section allocation_callbacks Device memory allocation callbacks
+
+The library makes calls to `vkAllocateMemory()` and `vkFreeMemory()` internally.
+You can setup callbacks to be informed about these calls, e.g. for the purpose
+of gathering some statistics. To do it, fill optional member
+VmaAllocatorCreateInfo::pDeviceMemoryCallbacks.
+
+\section heap_memory_limit Device heap memory limit
+
+When device memory of certain heap runs out of free space, new allocations may
+fail (returning error code) or they may succeed, silently pushing some existing_
+memory blocks from GPU VRAM to system RAM (which degrades performance). This
+behavior is implementation-dependent - it depends on GPU vendor and graphics
+driver.
+
+On AMD cards it can be controlled while creating Vulkan device object by using
+VK_AMD_memory_overallocation_behavior extension, if available.
+
+Alternatively, if you want to test how your program behaves with limited amount of Vulkan device
+memory available without switching your graphics card to one that really has
+smaller VRAM, you can use a feature of this library intended for this purpose.
+To do it, fill optional member VmaAllocatorCreateInfo::pHeapSizeLimit.
+
+
+
+\page vk_khr_dedicated_allocation VK_KHR_dedicated_allocation
+
+VK_KHR_dedicated_allocation is a Vulkan extension which can be used to improve
+performance on some GPUs. It augments Vulkan API with possibility to query
+driver whether it prefers particular buffer or image to have its own, dedicated
+allocation (separate `VkDeviceMemory` block) for better efficiency - to be able
+to do some internal optimizations. The extension is supported by this library.
+It will be used automatically when enabled.
+
+It has been promoted to core Vulkan 1.1, so if you use eligible Vulkan version
+and inform VMA about it by setting VmaAllocatorCreateInfo::vulkanApiVersion,
+you are all set.
+
+Otherwise, if you want to use it as an extension:
+
+1 . When creating Vulkan device, check if following 2 device extensions are
+supported (call `vkEnumerateDeviceExtensionProperties()`).
+If yes, enable them (fill `VkDeviceCreateInfo::ppEnabledExtensionNames`).
+
+- VK_KHR_get_memory_requirements2
+- VK_KHR_dedicated_allocation
+
+If you enabled these extensions:
+
+2 . Use #VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT flag when creating
+your #VmaAllocator to inform the library that you enabled required extensions
+and you want the library to use them.
+
+\code
+allocatorInfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
+
+vmaCreateAllocator(&allocatorInfo, &allocator);
+\endcode
+
+That is all. The extension will be automatically used whenever you create a
+buffer using vmaCreateBuffer() or image using vmaCreateImage().
+
+When using the extension together with Vulkan Validation Layer, you will receive
+warnings like this:
+
+_vkBindBufferMemory(): Binding memory to buffer 0x33 but vkGetBufferMemoryRequirements() has not been called on that buffer._
+
+It is OK, you should just ignore it. It happens because you use function
+`vkGetBufferMemoryRequirements2KHR()` instead of standard
+`vkGetBufferMemoryRequirements()`, while the validation layer seems to be
+unaware of it.
+
+To learn more about this extension, see:
+
+- [VK_KHR_dedicated_allocation in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap50.html#VK_KHR_dedicated_allocation)
+- [VK_KHR_dedicated_allocation unofficial manual](http://asawicki.info/articles/VK_KHR_dedicated_allocation.php5)
+
+
+
+\page vk_ext_memory_priority VK_EXT_memory_priority
+
+VK_EXT_memory_priority is a device extension that allows to pass additional "priority"
+value to Vulkan memory allocations that the implementation may use prefer certain
+buffers and images that are critical for performance to stay in device-local memory
+in cases when the memory is over-subscribed, while some others may be moved to the system memory.
+
+VMA offers convenient usage of this extension.
+If you enable it, you can pass "priority" parameter when creating allocations or custom pools
+and the library automatically passes the value to Vulkan using this extension.
+
+If you want to use this extension in connection with VMA, follow these steps:
+
+\section vk_ext_memory_priority_initialization Initialization
+
+1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
+Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_EXT_memory_priority".
+
+2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
+Attach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
+Check if the device feature is really supported - check if `VkPhysicalDeviceMemoryPriorityFeaturesEXT::memoryPriority` is true.
+
+3) While creating device with `vkCreateDevice`, enable this extension - add "VK_EXT_memory_priority"
+to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
+
+4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
+Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
+Enable this device feature - attach additional structure `VkPhysicalDeviceMemoryPriorityFeaturesEXT` to
+`VkPhysicalDeviceFeatures2::pNext` chain and set its member `memoryPriority` to `VK_TRUE`.
+
+5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
+have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_EXT_MEMORY_PRIORITY_BIT
+to VmaAllocatorCreateInfo::flags.
+
+\section vk_ext_memory_priority_usage Usage
+
+When using this extension, you should initialize following member:
+
+- VmaAllocationCreateInfo::priority when creating a dedicated allocation with #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+- VmaPoolCreateInfo::priority when creating a custom pool.
+
+It should be a floating-point value between `0.0f` and `1.0f`, where recommended default is `0.5f`.
+Memory allocated with higher value can be treated by the Vulkan implementation as higher priority
+and so it can have lower chances of being pushed out to system memory, experiencing degraded performance.
+
+It might be a good idea to create performance-critical resources like color-attachment or depth-stencil images
+as dedicated and set high priority to them. For example:
+
+\code
+VkImageCreateInfo imgCreateInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO };
+imgCreateInfo.imageType = VK_IMAGE_TYPE_2D;
+imgCreateInfo.extent.width = 3840;
+imgCreateInfo.extent.height = 2160;
+imgCreateInfo.extent.depth = 1;
+imgCreateInfo.mipLevels = 1;
+imgCreateInfo.arrayLayers = 1;
+imgCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+imgCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+imgCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+imgCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+imgCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+
+VmaAllocationCreateInfo allocCreateInfo = {};
+allocCreateInfo.usage = VMA_MEMORY_USAGE_AUTO;
+allocCreateInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
+allocCreateInfo.priority = 1.0f;
+
+VkImage img;
+VmaAllocation alloc;
+vmaCreateImage(allocator, &imgCreateInfo, &allocCreateInfo, &img, &alloc, nullptr);
+\endcode
+
+`priority` member is ignored in the following situations:
+
+- Allocations created in custom pools: They inherit the priority, along with all other allocation parameters
+ from the parametrs passed in #VmaPoolCreateInfo when the pool was created.
+- Allocations created in default pools: They inherit the priority from the parameters
+ VMA used when creating default pools, which means `priority == 0.5f`.
+
+
+\page vk_amd_device_coherent_memory VK_AMD_device_coherent_memory
+
+VK_AMD_device_coherent_memory is a device extension that enables access to
+additional memory types with `VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD` and
+`VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` flag. It is useful mostly for
+allocation of buffers intended for writing "breadcrumb markers" in between passes
+or draw calls, which in turn are useful for debugging GPU crash/hang/TDR cases.
+
+When the extension is available but has not been enabled, Vulkan physical device
+still exposes those memory types, but their usage is forbidden. VMA automatically
+takes care of that - it returns `VK_ERROR_FEATURE_NOT_PRESENT` when an attempt
+to allocate memory of such type is made.
+
+If you want to use this extension in connection with VMA, follow these steps:
+
+\section vk_amd_device_coherent_memory_initialization Initialization
+
+1) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
+Check if the extension is supported - if returned array of `VkExtensionProperties` contains "VK_AMD_device_coherent_memory".
+
+2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
+Attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
+Check if the device feature is really supported - check if `VkPhysicalDeviceCoherentMemoryFeaturesAMD::deviceCoherentMemory` is true.
+
+3) While creating device with `vkCreateDevice`, enable this extension - add "VK_AMD_device_coherent_memory"
+to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
+
+4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
+Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
+Enable this device feature - attach additional structure `VkPhysicalDeviceCoherentMemoryFeaturesAMD` to
+`VkPhysicalDeviceFeatures2::pNext` and set its member `deviceCoherentMemory` to `VK_TRUE`.
+
+5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
+have enabled this extension and feature - add #VMA_ALLOCATOR_CREATE_AMD_DEVICE_COHERENT_MEMORY_BIT
+to VmaAllocatorCreateInfo::flags.
+
+\section vk_amd_device_coherent_memory_usage Usage
+
+After following steps described above, you can create VMA allocations and custom pools
+out of the special `DEVICE_COHERENT` and `DEVICE_UNCACHED` memory types on eligible
+devices. There are multiple ways to do it, for example:
+
+- You can request or prefer to allocate out of such memory types by adding
+ `VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD` to VmaAllocationCreateInfo::requiredFlags
+ or VmaAllocationCreateInfo::preferredFlags. Those flags can be freely mixed with
+ other ways of \ref choosing_memory_type, like setting VmaAllocationCreateInfo::usage.
+- If you manually found memory type index to use for this purpose, force allocation
+ from this specific index by setting VmaAllocationCreateInfo::memoryTypeBits `= 1u << index`.
+
+\section vk_amd_device_coherent_memory_more_information More information
+
+To learn more about this extension, see [VK_AMD_device_coherent_memory in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_AMD_device_coherent_memory.html)
+
+Example use of this extension can be found in the code of the sample and test suite
+accompanying this library.
+
+
+\page enabling_buffer_device_address Enabling buffer device address
+
+Device extension VK_KHR_buffer_device_address
+allow to fetch raw GPU pointer to a buffer and pass it for usage in a shader code.
+It has been promoted to core Vulkan 1.2.
+
+If you want to use this feature in connection with VMA, follow these steps:
+
+\section enabling_buffer_device_address_initialization Initialization
+
+1) (For Vulkan version < 1.2) Call `vkEnumerateDeviceExtensionProperties` for the physical device.
+Check if the extension is supported - if returned array of `VkExtensionProperties` contains
+"VK_KHR_buffer_device_address".
+
+2) Call `vkGetPhysicalDeviceFeatures2` for the physical device instead of old `vkGetPhysicalDeviceFeatures`.
+Attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to `VkPhysicalDeviceFeatures2::pNext` to be returned.
+Check if the device feature is really supported - check if `VkPhysicalDeviceBufferDeviceAddressFeatures::bufferDeviceAddress` is true.
+
+3) (For Vulkan version < 1.2) While creating device with `vkCreateDevice`, enable this extension - add
+"VK_KHR_buffer_device_address" to the list passed as `VkDeviceCreateInfo::ppEnabledExtensionNames`.
+
+4) While creating the device, also don't set `VkDeviceCreateInfo::pEnabledFeatures`.
+Fill in `VkPhysicalDeviceFeatures2` structure instead and pass it as `VkDeviceCreateInfo::pNext`.
+Enable this device feature - attach additional structure `VkPhysicalDeviceBufferDeviceAddressFeatures*` to
+`VkPhysicalDeviceFeatures2::pNext` and set its member `bufferDeviceAddress` to `VK_TRUE`.
+
+5) While creating #VmaAllocator with vmaCreateAllocator() inform VMA that you
+have enabled this feature - add #VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT
+to VmaAllocatorCreateInfo::flags.
+
+\section enabling_buffer_device_address_usage Usage
+
+After following steps described above, you can create buffers with `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*` using VMA.
+The library automatically adds `VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT*` to
+allocated memory blocks wherever it might be needed.
+
+Please note that the library supports only `VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT*`.
+The second part of this functionality related to "capture and replay" is not supported,
+as it is intended for usage in debugging tools like RenderDoc, not in everyday Vulkan usage.
+
+\section enabling_buffer_device_address_more_information More information
+
+To learn more about this extension, see [VK_KHR_buffer_device_address in Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap46.html#VK_KHR_buffer_device_address)
+
+Example use of this extension can be found in the code of the sample and test suite
+accompanying this library.
+
+\page general_considerations General considerations
+
+\section general_considerations_thread_safety Thread safety
+
+- The library has no global state, so separate #VmaAllocator objects can be used
+ independently.
+ There should be no need to create multiple such objects though - one per `VkDevice` is enough.
+- By default, all calls to functions that take #VmaAllocator as first parameter
+ are safe to call from multiple threads simultaneously because they are
+ synchronized internally when needed.
+ This includes allocation and deallocation from default memory pool, as well as custom #VmaPool.
+- When the allocator is created with #VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT
+ flag, calls to functions that take such #VmaAllocator object must be
+ synchronized externally.
+- Access to a #VmaAllocation object must be externally synchronized. For example,
+ you must not call vmaGetAllocationInfo() and vmaMapMemory() from different
+ threads at the same time if you pass the same #VmaAllocation object to these
+ functions.
+- #VmaVirtualBlock is not safe to be used from multiple threads simultaneously.
+
+\section general_considerations_versioning_and_compatibility Versioning and compatibility
+
+The library uses [**Semantic Versioning**](https://semver.org/),
+which means version numbers follow convention: Major.Minor.Patch (e.g. 2.3.0), where:
+
+- Incremented Patch version means a release is backward- and forward-compatible,
+ introducing only some internal improvements, bug fixes, optimizations etc.
+ or changes that are out of scope of the official API described in this documentation.
+- Incremented Minor version means a release is backward-compatible,
+ so existing code that uses the library should continue to work, while some new
+ symbols could have been added: new structures, functions, new values in existing
+ enums and bit flags, new structure members, but not new function parameters.
+- Incrementing Major version means a release could break some backward compatibility.
+
+All changes between official releases are documented in file "CHANGELOG.md".
+
+\warning Backward compatiblity is considered on the level of C++ source code, not binary linkage.
+Adding new members to existing structures is treated as backward compatible if initializing
+the new members to binary zero results in the old behavior.
+You should always fully initialize all library structures to zeros and not rely on their
+exact binary size.
+
+\section general_considerations_validation_layer_warnings Validation layer warnings
+
+When using this library, you can meet following types of warnings issued by
+Vulkan validation layer. They don't necessarily indicate a bug, so you may need
+to just ignore them.
+
+- *vkBindBufferMemory(): Binding memory to buffer 0xeb8e4 but vkGetBufferMemoryRequirements() has not been called on that buffer.*
+ - It happens when VK_KHR_dedicated_allocation extension is enabled.
+ `vkGetBufferMemoryRequirements2KHR` function is used instead, while validation layer seems to be unaware of it.
+- *Mapping an image with layout VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL can result in undefined behavior if this memory is used by the device. Only GENERAL or PREINITIALIZED should be used.*
+ - It happens when you map a buffer or image, because the library maps entire
+ `VkDeviceMemory` block, where different types of images and buffers may end
+ up together, especially on GPUs with unified memory like Intel.
+- *Non-linear image 0xebc91 is aliased with linear buffer 0xeb8e4 which may indicate a bug.*
+ - It may happen when you use [defragmentation](@ref defragmentation).
+
+\section general_considerations_allocation_algorithm Allocation algorithm
+
+The library uses following algorithm for allocation, in order:
+
+-# Try to find free range of memory in existing blocks.
+-# If failed, try to create a new block of `VkDeviceMemory`, with preferred block size.
+-# If failed, try to create such block with size / 2, size / 4, size / 8.
+-# If failed, try to allocate separate `VkDeviceMemory` for this allocation,
+ just like when you use #VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT.
+-# If failed, choose other memory type that meets the requirements specified in
+ VmaAllocationCreateInfo and go to point 1.
+-# If failed, return `VK_ERROR_OUT_OF_DEVICE_MEMORY`.
+
+\section general_considerations_features_not_supported Features not supported
+
+Features deliberately excluded from the scope of this library:
+
+-# **Data transfer.** Uploading (streaming) and downloading data of buffers and images
+ between CPU and GPU memory and related synchronization is responsibility of the user.
+ Defining some "texture" object that would automatically stream its data from a
+ staging copy in CPU memory to GPU memory would rather be a feature of another,
+ higher-level library implemented on top of VMA.
+ VMA doesn't record any commands to a `VkCommandBuffer`. It just allocates memory.
+-# **Recreation of buffers and images.** Although the library has functions for
+ buffer and image creation: vmaCreateBuffer(), vmaCreateImage(), you need to
+ recreate these objects yourself after defragmentation. That is because the big
+ structures `VkBufferCreateInfo`, `VkImageCreateInfo` are not stored in
+ #VmaAllocation object.
+-# **Handling CPU memory allocation failures.** When dynamically creating small C++
+ objects in CPU memory (not Vulkan memory), allocation failures are not checked
+ and handled gracefully, because that would complicate code significantly and
+ is usually not needed in desktop PC applications anyway.
+ Success of an allocation is just checked with an assert.
+-# **Code free of any compiler warnings.** Maintaining the library to compile and
+ work correctly on so many different platforms is hard enough. Being free of
+ any warnings, on any version of any compiler, is simply not feasible.
+ There are many preprocessor macros that make some variables unused, function parameters unreferenced,
+ or conditional expressions constant in some configurations.
+ The code of this library should not be bigger or more complicated just to silence these warnings.
+ It is recommended to disable such warnings instead.
+-# This is a C++ library with C interface. **Bindings or ports to any other programming languages** are welcome as external projects but
+ are not going to be included into this repository.
+*/
diff --git a/thirdparty/xatlas/xatlas.cpp b/thirdparty/xatlas/xatlas.cpp
index d92ef1a83a..5c5c57ecab 100644
--- a/thirdparty/xatlas/xatlas.cpp
+++ b/thirdparty/xatlas/xatlas.cpp
@@ -4753,13 +4753,10 @@ public:
Vector2 *v = m_vertexBuffers[m_activeVertexBuffer];
v[m_numVertices] = v[0];
m_area = 0;
- float centroidx = 0, centroidy = 0;
for (uint32_t k = 0; k < m_numVertices; k++) {
// http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
float f = v[k].x * v[k + 1].y - v[k + 1].x * v[k].y;
m_area += f;
- centroidx += f * (v[k].x + v[k + 1].x);
- centroidy += f * (v[k].y + v[k + 1].y);
}
m_area = 0.5f * fabsf(m_area);
}
@@ -9089,7 +9086,6 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH
const uint32_t kMaxWarnings = 50;
uint32_t warningCount = 0;
internal::Array<uint32_t> triIndices;
- uint32_t firstFaceIndex = 0;
internal::Triangulator triangulator;
for (uint32_t face = 0; face < faceCount; face++) {
// Decode face indices.
@@ -9199,7 +9195,6 @@ AddMeshError AddMesh(Atlas *atlas, const MeshDecl &meshDecl, uint32_t meshCountH
for (uint32_t i = 0; i < triIndices.size(); i++)
meshPolygonMapping->triangleToPolygonIndicesMap.push_back(triIndices[i]);
}
- firstFaceIndex += faceVertexCount;
}
if (warningCount > kMaxWarnings)
XA_PRINT(" %u additional warnings truncated\n", warningCount - kMaxWarnings);
diff --git a/thirdparty/zlib/crc32.c b/thirdparty/zlib/crc32.c
index 9580440c0e..a1bdce5c23 100644
--- a/thirdparty/zlib/crc32.c
+++ b/thirdparty/zlib/crc32.c
@@ -1,12 +1,10 @@
/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
- * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
- * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
- * tables for updating the shift register in one step with three exclusive-ors
- * instead of four steps with four exclusive-ors. This results in about a
- * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ * This interleaved implementation of a CRC makes use of pipelined multiple
+ * arithmetic-logic units, commonly found in modern CPU cores. It is due to
+ * Kadatch and Jenkins (2010). See doc/crc-doc.1.0.pdf in this distribution.
*/
/* @(#) $Id$ */
@@ -14,11 +12,12 @@
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
- of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
+ of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
- DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h.
+ MAKECRCH can be #defined to write out crc32.h. A main() routine is also
+ produced, so that this one source file can be compiled to an executable.
*/
#ifdef MAKECRCH
@@ -28,415 +27,1090 @@
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
-#include "zutil.h" /* for STDC and FAR definitions */
+#include "zutil.h" /* for Z_U4, Z_U8, z_crc_t, and FAR definitions */
-/* Definitions for doing the crc four data bytes at a time. */
-#if !defined(NOBYFOUR) && defined(Z_U4)
-# define BYFOUR
+ /*
+ A CRC of a message is computed on N braids of words in the message, where
+ each word consists of W bytes (4 or 8). If N is 3, for example, then three
+ running sparse CRCs are calculated respectively on each braid, at these
+ indices in the array of words: 0, 3, 6, ..., 1, 4, 7, ..., and 2, 5, 8, ...
+ This is done starting at a word boundary, and continues until as many blocks
+ of N * W bytes as are available have been processed. The results are combined
+ into a single CRC at the end. For this code, N must be in the range 1..6 and
+ W must be 4 or 8. The upper limit on N can be increased if desired by adding
+ more #if blocks, extending the patterns apparent in the code. In addition,
+ crc32.h would need to be regenerated, if the maximum N value is increased.
+
+ N and W are chosen empirically by benchmarking the execution time on a given
+ processor. The choices for N and W below were based on testing on Intel Kaby
+ Lake i7, AMD Ryzen 7, ARM Cortex-A57, Sparc64-VII, PowerPC POWER9, and MIPS64
+ Octeon II processors. The Intel, AMD, and ARM processors were all fastest
+ with N=5, W=8. The Sparc, PowerPC, and MIPS64 were all fastest at N=5, W=4.
+ They were all tested with either gcc or clang, all using the -O3 optimization
+ level. Your mileage may vary.
+ */
+
+/* Define N */
+#ifdef Z_TESTN
+# define N Z_TESTN
+#else
+# define N 5
+#endif
+#if N < 1 || N > 6
+# error N must be in 1..6
#endif
-#ifdef BYFOUR
- local unsigned long crc32_little OF((unsigned long,
- const unsigned char FAR *, z_size_t));
- local unsigned long crc32_big OF((unsigned long,
- const unsigned char FAR *, z_size_t));
-# define TBLS 8
+
+/*
+ z_crc_t must be at least 32 bits. z_word_t must be at least as long as
+ z_crc_t. It is assumed here that z_word_t is either 32 bits or 64 bits, and
+ that bytes are eight bits.
+ */
+
+/*
+ Define W and the associated z_word_t type. If W is not defined, then a
+ braided calculation is not used, and the associated tables and code are not
+ compiled.
+ */
+#ifdef Z_TESTW
+# if Z_TESTW-1 != -1
+# define W Z_TESTW
+# endif
#else
-# define TBLS 1
-#endif /* BYFOUR */
+# ifdef MAKECRCH
+# define W 8 /* required for MAKECRCH */
+# else
+# if defined(__x86_64__) || defined(__aarch64__)
+# define W 8
+# else
+# define W 4
+# endif
+# endif
+#endif
+#ifdef W
+# if W == 8 && defined(Z_U8)
+ typedef Z_U8 z_word_t;
+# elif defined(Z_U4)
+# undef W
+# define W 4
+ typedef Z_U4 z_word_t;
+# else
+# undef W
+# endif
+#endif
-/* Local functions for crc concatenation */
-local unsigned long gf2_matrix_times OF((unsigned long *mat,
- unsigned long vec));
-local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
-local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2));
+/* Local functions. */
+local z_crc_t multmodp OF((z_crc_t a, z_crc_t b));
+local z_crc_t x2nmodp OF((z_off64_t n, unsigned k));
+/* If available, use the ARM processor CRC32 instruction. */
+#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) && W == 8
+# define ARMCRC32
+#endif
+
+#if defined(W) && (!defined(ARMCRC32) || defined(DYNAMIC_CRC_TABLE))
+/*
+ Swap the bytes in a z_word_t to convert between little and big endian. Any
+ self-respecting compiler will optimize this to a single machine byte-swap
+ instruction, if one is available. This assumes that word_t is either 32 bits
+ or 64 bits.
+ */
+local z_word_t byte_swap(word)
+ z_word_t word;
+{
+# if W == 8
+ return
+ (word & 0xff00000000000000) >> 56 |
+ (word & 0xff000000000000) >> 40 |
+ (word & 0xff0000000000) >> 24 |
+ (word & 0xff00000000) >> 8 |
+ (word & 0xff000000) << 8 |
+ (word & 0xff0000) << 24 |
+ (word & 0xff00) << 40 |
+ (word & 0xff) << 56;
+# else /* W == 4 */
+ return
+ (word & 0xff000000) >> 24 |
+ (word & 0xff0000) >> 8 |
+ (word & 0xff00) << 8 |
+ (word & 0xff) << 24;
+# endif
+}
+#endif
+
+/* CRC polynomial. */
+#define POLY 0xedb88320 /* p(x) reflected, with x^32 implied */
#ifdef DYNAMIC_CRC_TABLE
-local volatile int crc_table_empty = 1;
-local z_crc_t FAR crc_table[TBLS][256];
+local z_crc_t FAR crc_table[256];
+local z_crc_t FAR x2n_table[32];
local void make_crc_table OF((void));
+#ifdef W
+ local z_word_t FAR crc_big_table[256];
+ local z_crc_t FAR crc_braid_table[W][256];
+ local z_word_t FAR crc_braid_big_table[W][256];
+ local void braid OF((z_crc_t [][256], z_word_t [][256], int, int));
+#endif
#ifdef MAKECRCH
- local void write_table OF((FILE *, const z_crc_t FAR *));
+ local void write_table OF((FILE *, const z_crc_t FAR *, int));
+ local void write_table32hi OF((FILE *, const z_word_t FAR *, int));
+ local void write_table64 OF((FILE *, const z_word_t FAR *, int));
#endif /* MAKECRCH */
+
+/*
+ Define a once() function depending on the availability of atomics. If this is
+ compiled with DYNAMIC_CRC_TABLE defined, and if CRCs will be computed in
+ multiple threads, and if atomics are not available, then get_crc_table() must
+ be called to initialize the tables and must return before any threads are
+ allowed to compute or combine CRCs.
+ */
+
+/* Definition of once functionality. */
+typedef struct once_s once_t;
+local void once OF((once_t *, void (*)(void)));
+
+/* Check for the availability of atomics. */
+#if defined(__STDC__) && __STDC_VERSION__ >= 201112L && \
+ !defined(__STDC_NO_ATOMICS__)
+
+#include <stdatomic.h>
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ atomic_flag begun;
+ atomic_int done;
+};
+#define ONCE_INIT {ATOMIC_FLAG_INIT, 0}
+
+/*
+ Run the provided init() function exactly once, even if multiple threads
+ invoke once() at the same time. The state must be a once_t initialized with
+ ONCE_INIT.
+ */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!atomic_load(&state->done)) {
+ if (atomic_flag_test_and_set(&state->begun))
+ while (!atomic_load(&state->done))
+ ;
+ else {
+ init();
+ atomic_store(&state->done, 1);
+ }
+ }
+}
+
+#else /* no atomics */
+
+/* Structure for once(), which must be initialized with ONCE_INIT. */
+struct once_s {
+ volatile int begun;
+ volatile int done;
+};
+#define ONCE_INIT {0, 0}
+
+/* Test and set. Alas, not atomic, but tries to minimize the period of
+ vulnerability. */
+local int test_and_set OF((int volatile *));
+local int test_and_set(flag)
+ int volatile *flag;
+{
+ int was;
+
+ was = *flag;
+ *flag = 1;
+ return was;
+}
+
+/* Run the provided init() function once. This is not thread-safe. */
+local void once(state, init)
+ once_t *state;
+ void (*init)(void);
+{
+ if (!state->done) {
+ if (test_and_set(&state->begun))
+ while (!state->done)
+ ;
+ else {
+ init();
+ state->done = 1;
+ }
+ }
+}
+
+#endif
+
+/* State for once(). */
+local once_t made = ONCE_INIT;
+
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
- with the lowest powers in the most significant bit. Then adding polynomials
+ with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
- one. If we call the above polynomial p, and represent a byte as the
+ one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
- byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+ byte 0xb1 is the polynomial x^7+x^3+x^2+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
- taking the remainder. The register is initialized to zero, and for each
+ taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
- x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
- x (which is shifting right by one and adding x^32 mod p if the bit shifted
- out is a one). We start with the highest power (least significant bit) of
- q and repeat for all eight bits of q.
-
- The first table is simply the CRC of all possible eight bit values. This is
- all the information needed to generate CRCs on data a byte at a time for all
- combinations of CRC register values and incoming bytes. The remaining tables
- allow for word-at-a-time CRC calculation for both big-endian and little-
- endian machines, where a word is four bytes.
-*/
+ x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by x
+ (which is shifting right by one and adding x^32 mod p if the bit shifted out
+ is a one). We start with the highest power (least significant bit) of q and
+ repeat for all eight bits of q.
+
+ The table is simply the CRC of all possible eight bit values. This is all the
+ information needed to generate CRCs on data a byte at a time for all
+ combinations of CRC register values and incoming bytes.
+ */
+
local void make_crc_table()
{
- z_crc_t c;
- int n, k;
- z_crc_t poly; /* polynomial exclusive-or pattern */
- /* terms of polynomial defining this crc (except x^32): */
- static volatile int first = 1; /* flag to limit concurrent making */
- static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
- /* See if another task is already doing this (not thread-safe, but better
- than nothing -- significantly reduces duration of vulnerability in
- case the advice about DYNAMIC_CRC_TABLE is ignored) */
- if (first) {
- first = 0;
-
- /* make exclusive-or pattern from polynomial (0xedb88320UL) */
- poly = 0;
- for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++)
- poly |= (z_crc_t)1 << (31 - p[n]);
-
- /* generate a crc for every 8-bit value */
- for (n = 0; n < 256; n++) {
- c = (z_crc_t)n;
- for (k = 0; k < 8; k++)
- c = c & 1 ? poly ^ (c >> 1) : c >> 1;
- crc_table[0][n] = c;
- }
+ unsigned i, j, n;
+ z_crc_t p;
-#ifdef BYFOUR
- /* generate crc for each value followed by one, two, and three zeros,
- and then the byte reversal of those as well as the first table */
- for (n = 0; n < 256; n++) {
- c = crc_table[0][n];
- crc_table[4][n] = ZSWAP32(c);
- for (k = 1; k < 4; k++) {
- c = crc_table[0][c & 0xff] ^ (c >> 8);
- crc_table[k][n] = c;
- crc_table[k + 4][n] = ZSWAP32(c);
- }
- }
-#endif /* BYFOUR */
-
- crc_table_empty = 0;
- }
- else { /* not first */
- /* wait for the other guy to finish (not efficient, but rare) */
- while (crc_table_empty)
- ;
+ /* initialize the CRC of bytes tables */
+ for (i = 0; i < 256; i++) {
+ p = i;
+ for (j = 0; j < 8; j++)
+ p = p & 1 ? (p >> 1) ^ POLY : p >> 1;
+ crc_table[i] = p;
+#ifdef W
+ crc_big_table[i] = byte_swap(p);
+#endif
}
+ /* initialize the x^2^n mod p(x) table */
+ p = (z_crc_t)1 << 30; /* x^1 */
+ x2n_table[0] = p;
+ for (n = 1; n < 32; n++)
+ x2n_table[n] = p = multmodp(p, p);
+
+#ifdef W
+ /* initialize the braiding tables -- needs x2n_table[] */
+ braid(crc_braid_table, crc_braid_big_table, N, W);
+#endif
+
#ifdef MAKECRCH
- /* write out CRC tables to crc32.h */
{
+ /*
+ The crc32.h header file contains tables for both 32-bit and 64-bit
+ z_word_t's, and so requires a 64-bit type be available. In that case,
+ z_word_t must be defined to be 64-bits. This code then also generates
+ and writes out the tables for the case that z_word_t is 32 bits.
+ */
+#if !defined(W) || W != 8
+# error Need a 64-bit integer type in order to generate crc32.h.
+#endif
FILE *out;
+ int k, n;
+ z_crc_t ltl[8][256];
+ z_word_t big[8][256];
out = fopen("crc32.h", "w");
if (out == NULL) return;
- fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
- fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
- fprintf(out, "local const z_crc_t FAR ");
- fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
- write_table(out, crc_table[0]);
-# ifdef BYFOUR
- fprintf(out, "#ifdef BYFOUR\n");
- for (k = 1; k < 8; k++) {
- fprintf(out, " },\n {\n");
- write_table(out, crc_table[k]);
+
+ /* write out little-endian CRC table to crc32.h */
+ fprintf(out,
+ "/* crc32.h -- tables for rapid CRC calculation\n"
+ " * Generated automatically by crc32.c\n */\n"
+ "\n"
+ "local const z_crc_t FAR crc_table[] = {\n"
+ " ");
+ write_table(out, crc_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#ifdef W\n"
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table64(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n");
+
+ /* write out big-endian CRC table for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_word_t FAR crc_big_table[] = {\n"
+ " ");
+ write_table32hi(out, crc_big_table, 256);
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n");
+
+ /* write out braid tables for each value of N */
+ for (n = 1; n <= 6; n++) {
+ fprintf(out,
+ "\n"
+ "#if N == %d\n", n);
+
+ /* compute braid tables for this N and 64-bit word_t */
+ braid(ltl, big, n, 8);
+
+ /* write out braid tables for 64-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#if W == 8\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 8; k++) {
+ fprintf(out, " {");
+ write_table64(out, big[k], 256);
+ fprintf(out, "}%s", k < 7 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n");
+
+ /* compute braid tables for this N and 32-bit word_t */
+ braid(ltl, big, n, 4);
+
+ /* write out braid tables for 32-bit z_word_t to crc32.h */
+ fprintf(out,
+ "\n"
+ "#else /* W == 4 */\n"
+ "\n"
+ "local const z_crc_t FAR crc_braid_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table(out, ltl[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "local const z_word_t FAR crc_braid_big_table[][256] = {\n");
+ for (k = 0; k < 4; k++) {
+ fprintf(out, " {");
+ write_table32hi(out, big[k], 256);
+ fprintf(out, "}%s", k < 3 ? ",\n" : "");
+ }
+ fprintf(out,
+ "};\n"
+ "\n"
+ "#endif\n"
+ "\n"
+ "#endif\n");
}
- fprintf(out, "#endif\n");
-# endif /* BYFOUR */
- fprintf(out, " }\n};\n");
+ fprintf(out,
+ "\n"
+ "#endif\n");
+
+ /* write out zeros operator table to crc32.h */
+ fprintf(out,
+ "\n"
+ "local const z_crc_t FAR x2n_table[] = {\n"
+ " ");
+ write_table(out, x2n_table, 32);
+ fprintf(out,
+ "};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
-local void write_table(out, table)
+
+/*
+ Write the 32-bit values in table[0..k-1] to out, five per line in
+ hexadecimal separated by commas.
+ */
+local void write_table(out, table, k)
FILE *out;
const z_crc_t FAR *table;
+ int k;
{
int n;
- for (n = 0; n < 256; n++)
- fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ",
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
(unsigned long)(table[n]),
- n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
}
+
+/*
+ Write the high 32-bits of each value in table[0..k-1] to out, five per line
+ in hexadecimal separated by commas.
+ */
+local void write_table32hi(out, table, k)
+FILE *out;
+const z_word_t FAR *table;
+int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%08lx%s", n == 0 || n % 5 ? "" : " ",
+ (unsigned long)(table[n] >> 32),
+ n == k - 1 ? "" : (n % 5 == 4 ? ",\n" : ", "));
+}
+
+/*
+ Write the 64-bit values in table[0..k-1] to out, three per line in
+ hexadecimal separated by commas. This assumes that if there is a 64-bit
+ type, then there is also a long long integer type, and it is at least 64
+ bits. If not, then the type cast and format string can be adjusted
+ accordingly.
+ */
+local void write_table64(out, table, k)
+ FILE *out;
+ const z_word_t FAR *table;
+ int k;
+{
+ int n;
+
+ for (n = 0; n < k; n++)
+ fprintf(out, "%s0x%016llx%s", n == 0 || n % 3 ? "" : " ",
+ (unsigned long long)(table[n]),
+ n == k - 1 ? "" : (n % 3 == 2 ? ",\n" : ", "));
+}
+
+/* Actually do the deed. */
+int main()
+{
+ make_crc_table();
+ return 0;
+}
+
#endif /* MAKECRCH */
+#ifdef W
+/*
+ Generate the little and big-endian braid tables for the given n and z_word_t
+ size w. Each array must have room for w blocks of 256 elements.
+ */
+local void braid(ltl, big, n, w)
+ z_crc_t ltl[][256];
+ z_word_t big[][256];
+ int n;
+ int w;
+{
+ int k;
+ z_crc_t i, p, q;
+ for (k = 0; k < w; k++) {
+ p = x2nmodp((n * w + 3 - k) << 3, 0);
+ ltl[k][0] = 0;
+ big[w - 1 - k][0] = 0;
+ for (i = 1; i < 256; i++) {
+ ltl[k][i] = q = multmodp(i << 24, p);
+ big[w - 1 - k][i] = byte_swap(q);
+ }
+ }
+}
+#endif
+
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
- * Tables of CRC-32s of all single-byte values, made by make_crc_table().
+ * Tables for byte-wise and braided CRC-32 calculations, and a table of powers
+ * of x for combining CRC-32s, all made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
+/* ========================================================================
+ * Routines used for CRC calculation. Some are also required for the table
+ * generation above.
+ */
+
+/*
+ Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC polynomial,
+ reflected. For speed, this requires that a not be zero.
+ */
+local z_crc_t multmodp(a, b)
+ z_crc_t a;
+ z_crc_t b;
+{
+ z_crc_t m, p;
+
+ m = (z_crc_t)1 << 31;
+ p = 0;
+ for (;;) {
+ if (a & m) {
+ p ^= b;
+ if ((a & (m - 1)) == 0)
+ break;
+ }
+ m >>= 1;
+ b = b & 1 ? (b >> 1) ^ POLY : b >> 1;
+ }
+ return p;
+}
+
+/*
+ Return x^(n * 2^k) modulo p(x). Requires that x2n_table[] has been
+ initialized.
+ */
+local z_crc_t x2nmodp(n, k)
+ z_off64_t n;
+ unsigned k;
+{
+ z_crc_t p;
+
+ p = (z_crc_t)1 << 31; /* x^0 == 1 */
+ while (n) {
+ if (n & 1)
+ p = multmodp(x2n_table[k & 31], p);
+ n >>= 1;
+ k++;
+ }
+ return p;
+}
+
/* =========================================================================
- * This function can be used by asm versions of crc32()
+ * This function can be used by asm versions of crc32(), and to force the
+ * generation of the CRC tables in a threaded application.
*/
const z_crc_t FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
- if (crc_table_empty)
- make_crc_table();
+ once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
return (const z_crc_t FAR *)crc_table;
}
-/* ========================================================================= */
-#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
-#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
+/* =========================================================================
+ * Use ARM machine instructions if available. This will compute the CRC about
+ * ten times faster than the braided calculation. This code does not check for
+ * the presence of the CRC instruction at run time. __ARM_FEATURE_CRC32 will
+ * only be defined if the compilation specifies an ARM processor architecture
+ * that has the instructions. For example, compiling with -march=armv8.1-a or
+ * -march=armv8-a+crc, or -march=native if the compile machine has the crc32
+ * instructions.
+ */
+#ifdef ARMCRC32
+
+/*
+ Constants empirically determined to maximize speed. These values are from
+ measurements on a Cortex-A57. Your mileage may vary.
+ */
+#define Z_BATCH 3990 /* number of words in a batch */
+#define Z_BATCH_ZEROS 0xa10d3d0c /* computed from Z_BATCH = 3990 */
+#define Z_BATCH_MIN 800 /* fewest words in a final batch */
-/* ========================================================================= */
unsigned long ZEXPORT crc32_z(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
z_size_t len;
{
- if (buf == Z_NULL) return 0UL;
+ z_crc_t val;
+ z_word_t crc1, crc2;
+ const z_word_t *word;
+ z_word_t val0, val1, val2;
+ z_size_t last, last2, i;
+ z_size_t num;
+
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
#ifdef DYNAMIC_CRC_TABLE
- if (crc_table_empty)
- make_crc_table();
+ once(&made, make_crc_table);
#endif /* DYNAMIC_CRC_TABLE */
-#ifdef BYFOUR
- if (sizeof(void *) == sizeof(ptrdiff_t)) {
- z_crc_t endian;
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
- endian = 1;
- if (*((unsigned char *)(&endian)))
- return crc32_little(crc, buf, len);
- else
- return crc32_big(crc, buf, len);
+ /* Compute the CRC up to a word boundary. */
+ while (len && ((z_size_t)buf & 7) != 0) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
}
-#endif /* BYFOUR */
- crc = crc ^ 0xffffffffUL;
- while (len >= 8) {
- DO8;
- len -= 8;
+
+ /* Prepare to compute the CRC on full 64-bit words word[0..num-1]. */
+ word = (z_word_t const *)buf;
+ num = len >> 3;
+ len &= 7;
+
+ /* Do three interleaved CRCs to realize the throughput of one crc32x
+ instruction per cycle. Each CRC is calcuated on Z_BATCH words. The three
+ CRCs are combined into a single CRC after each set of batches. */
+ while (num >= 3 * Z_BATCH) {
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < Z_BATCH; i++) {
+ val0 = word[i];
+ val1 = word[i + Z_BATCH];
+ val2 = word[i + 2 * Z_BATCH];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * Z_BATCH;
+ num -= 3 * Z_BATCH;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc1;
+ crc = multmodp(Z_BATCH_ZEROS, crc) ^ crc2;
}
- if (len) do {
- DO1;
- } while (--len);
- return crc ^ 0xffffffffUL;
-}
-/* ========================================================================= */
-unsigned long ZEXPORT crc32(crc, buf, len)
- unsigned long crc;
- const unsigned char FAR *buf;
- uInt len;
-{
- return crc32_z(crc, buf, len);
+ /* Do one last smaller batch with the remaining words, if there are enough
+ to pay for the combination of CRCs. */
+ last = num / 3;
+ if (last >= Z_BATCH_MIN) {
+ last2 = last << 1;
+ crc1 = 0;
+ crc2 = 0;
+ for (i = 0; i < last; i++) {
+ val0 = word[i];
+ val1 = word[i + last];
+ val2 = word[i + last2];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc1) : "r"(val1));
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc2) : "r"(val2));
+ }
+ word += 3 * last;
+ num -= 3 * last;
+ val = x2nmodp(last, 6);
+ crc = multmodp(val, crc) ^ crc1;
+ crc = multmodp(val, crc) ^ crc2;
+ }
+
+ /* Compute the CRC on any remaining words. */
+ for (i = 0; i < num; i++) {
+ val0 = word[i];
+ __asm__ volatile("crc32x %w0, %w0, %x1" : "+r"(crc) : "r"(val0));
+ }
+ word += num;
+
+ /* Complete the CRC on any remaining bytes. */
+ buf = (const unsigned char FAR *)word;
+ while (len) {
+ len--;
+ val = *buf++;
+ __asm__ volatile("crc32b %w0, %w0, %w1" : "+r"(crc) : "r"(val));
+ }
+
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
}
-#ifdef BYFOUR
+#else
+
+#ifdef W
/*
- This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit
- integer pointer type. This violates the strict aliasing rule, where a
- compiler can assume, for optimization purposes, that two pointers to
- fundamentally different types won't ever point to the same memory. This can
- manifest as a problem only if one of the pointers is written to. This code
- only reads from those pointers. So long as this code remains isolated in
- this compilation unit, there won't be a problem. For this reason, this code
- should not be copied and pasted into a compilation unit in which other code
- writes to the buffer that is passed to these routines.
+ Return the CRC of the W bytes in the word_t data, taking the
+ least-significant byte of the word as the first byte of data, without any pre
+ or post conditioning. This is used to combine the CRCs of each braid.
*/
+local z_crc_t crc_word(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data >> 8) ^ crc_table[data & 0xff];
+ return (z_crc_t)data;
+}
-/* ========================================================================= */
-#define DOLIT4 c ^= *buf4++; \
- c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
- crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
-#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
+local z_word_t crc_word_big(data)
+ z_word_t data;
+{
+ int k;
+ for (k = 0; k < W; k++)
+ data = (data << 8) ^
+ crc_big_table[(data >> ((W - 1) << 3)) & 0xff];
+ return data;
+}
+
+#endif
/* ========================================================================= */
-local unsigned long crc32_little(crc, buf, len)
+unsigned long ZEXPORT crc32_z(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
z_size_t len;
{
- register z_crc_t c;
- register const z_crc_t FAR *buf4;
+ /* Return initial CRC, if requested. */
+ if (buf == Z_NULL) return 0;
- c = (z_crc_t)crc;
- c = ~c;
- while (len && ((ptrdiff_t)buf & 3)) {
- c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
- len--;
- }
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
- buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
- while (len >= 32) {
- DOLIT32;
- len -= 32;
- }
- while (len >= 4) {
- DOLIT4;
- len -= 4;
- }
- buf = (const unsigned char FAR *)buf4;
+ /* Pre-condition the CRC */
+ crc ^= 0xffffffff;
- if (len) do {
- c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
- } while (--len);
- c = ~c;
- return (unsigned long)c;
-}
+#ifdef W
-/* ========================================================================= */
-#define DOBIG4 c ^= *buf4++; \
- c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
- crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
-#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
+ /* If provided enough bytes, do a braided CRC calculation. */
+ if (len >= N * W + W - 1) {
+ z_size_t blks;
+ z_word_t const *words;
+ unsigned endian;
+ int k;
-/* ========================================================================= */
-local unsigned long crc32_big(crc, buf, len)
- unsigned long crc;
- const unsigned char FAR *buf;
- z_size_t len;
-{
- register z_crc_t c;
- register const z_crc_t FAR *buf4;
+ /* Compute the CRC up to a z_word_t boundary. */
+ while (len && ((z_size_t)buf & (W - 1)) != 0) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ }
- c = ZSWAP32((z_crc_t)crc);
- c = ~c;
- while (len && ((ptrdiff_t)buf & 3)) {
- c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
- len--;
+ /* Compute the CRC on as many N z_word_t blocks as are available. */
+ blks = len / (N * W);
+ len -= blks * N * W;
+ words = (z_word_t const *)buf;
+
+ /* Do endian check at execution time instead of compile time, since ARM
+ processors can change the endianess at execution time. If the
+ compiler knows what the endianess will be, it can optimize out the
+ check and the unused branch. */
+ endian = 1;
+ if (*(unsigned char *)&endian) {
+ /* Little endian. */
+
+ z_crc_t crc0;
+ z_word_t word0;
+#if N > 1
+ z_crc_t crc1;
+ z_word_t word1;
+#if N > 2
+ z_crc_t crc2;
+ z_word_t word2;
+#if N > 3
+ z_crc_t crc3;
+ z_word_t word3;
+#if N > 4
+ z_crc_t crc4;
+ z_word_t word4;
+#if N > 5
+ z_crc_t crc5;
+ z_word_t word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = crc;
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ crc = crc_word(crc0 ^ words[0]);
+#if N > 1
+ crc = crc_word(crc1 ^ words[1] ^ crc);
+#if N > 2
+ crc = crc_word(crc2 ^ words[2] ^ crc);
+#if N > 3
+ crc = crc_word(crc3 ^ words[3] ^ crc);
+#if N > 4
+ crc = crc_word(crc4 ^ words[4] ^ crc);
+#if N > 5
+ crc = crc_word(crc5 ^ words[5] ^ crc);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ }
+ else {
+ /* Big endian. */
+
+ z_word_t crc0, word0, comb;
+#if N > 1
+ z_word_t crc1, word1;
+#if N > 2
+ z_word_t crc2, word2;
+#if N > 3
+ z_word_t crc3, word3;
+#if N > 4
+ z_word_t crc4, word4;
+#if N > 5
+ z_word_t crc5, word5;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /* Initialize the CRC for each braid. */
+ crc0 = byte_swap(crc);
+#if N > 1
+ crc1 = 0;
+#if N > 2
+ crc2 = 0;
+#if N > 3
+ crc3 = 0;
+#if N > 4
+ crc4 = 0;
+#if N > 5
+ crc5 = 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+
+ /*
+ Process the first blks-1 blocks, computing the CRCs on each braid
+ independently.
+ */
+ while (--blks) {
+ /* Load the word for each braid into registers. */
+ word0 = crc0 ^ words[0];
+#if N > 1
+ word1 = crc1 ^ words[1];
+#if N > 2
+ word2 = crc2 ^ words[2];
+#if N > 3
+ word3 = crc3 ^ words[3];
+#if N > 4
+ word4 = crc4 ^ words[4];
+#if N > 5
+ word5 = crc5 ^ words[5];
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+
+ /* Compute and update the CRC for each word. The loop should
+ get unrolled. */
+ crc0 = crc_braid_big_table[0][word0 & 0xff];
+#if N > 1
+ crc1 = crc_braid_big_table[0][word1 & 0xff];
+#if N > 2
+ crc2 = crc_braid_big_table[0][word2 & 0xff];
+#if N > 3
+ crc3 = crc_braid_big_table[0][word3 & 0xff];
+#if N > 4
+ crc4 = crc_braid_big_table[0][word4 & 0xff];
+#if N > 5
+ crc5 = crc_braid_big_table[0][word5 & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ for (k = 1; k < W; k++) {
+ crc0 ^= crc_braid_big_table[k][(word0 >> (k << 3)) & 0xff];
+#if N > 1
+ crc1 ^= crc_braid_big_table[k][(word1 >> (k << 3)) & 0xff];
+#if N > 2
+ crc2 ^= crc_braid_big_table[k][(word2 >> (k << 3)) & 0xff];
+#if N > 3
+ crc3 ^= crc_braid_big_table[k][(word3 >> (k << 3)) & 0xff];
+#if N > 4
+ crc4 ^= crc_braid_big_table[k][(word4 >> (k << 3)) & 0xff];
+#if N > 5
+ crc5 ^= crc_braid_big_table[k][(word5 >> (k << 3)) & 0xff];
+#endif
+#endif
+#endif
+#endif
+#endif
+ }
+ }
+
+ /*
+ Process the last block, combining the CRCs of the N braids at the
+ same time.
+ */
+ comb = crc_word_big(crc0 ^ words[0]);
+#if N > 1
+ comb = crc_word_big(crc1 ^ words[1] ^ comb);
+#if N > 2
+ comb = crc_word_big(crc2 ^ words[2] ^ comb);
+#if N > 3
+ comb = crc_word_big(crc3 ^ words[3] ^ comb);
+#if N > 4
+ comb = crc_word_big(crc4 ^ words[4] ^ comb);
+#if N > 5
+ comb = crc_word_big(crc5 ^ words[5] ^ comb);
+#endif
+#endif
+#endif
+#endif
+#endif
+ words += N;
+ crc = byte_swap(comb);
+ }
+
+ /*
+ Update the pointer to the remaining bytes to process.
+ */
+ buf = (unsigned char const *)words;
}
- buf4 = (const z_crc_t FAR *)(const void FAR *)buf;
- while (len >= 32) {
- DOBIG32;
- len -= 32;
+#endif /* W */
+
+ /* Complete the computation of the CRC on any remaining bytes. */
+ while (len >= 8) {
+ len -= 8;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
}
- while (len >= 4) {
- DOBIG4;
- len -= 4;
+ while (len) {
+ len--;
+ crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
}
- buf = (const unsigned char FAR *)buf4;
- if (len) do {
- c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
- } while (--len);
- c = ~c;
- return (unsigned long)(ZSWAP32(c));
+ /* Return the CRC, post-conditioned. */
+ return crc ^ 0xffffffff;
}
-#endif /* BYFOUR */
-
-#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
+#endif
/* ========================================================================= */
-local unsigned long gf2_matrix_times(mat, vec)
- unsigned long *mat;
- unsigned long vec;
+unsigned long ZEXPORT crc32(crc, buf, len)
+ unsigned long crc;
+ const unsigned char FAR *buf;
+ uInt len;
{
- unsigned long sum;
-
- sum = 0;
- while (vec) {
- if (vec & 1)
- sum ^= *mat;
- vec >>= 1;
- mat++;
- }
- return sum;
+ return crc32_z(crc, buf, len);
}
/* ========================================================================= */
-local void gf2_matrix_square(square, mat)
- unsigned long *square;
- unsigned long *mat;
+uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+ uLong crc1;
+ uLong crc2;
+ z_off64_t len2;
{
- int n;
-
- for (n = 0; n < GF2_DIM; n++)
- square[n] = gf2_matrix_times(mat, mat[n]);
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return multmodp(x2nmodp(len2, 3), crc1) ^ crc2;
}
/* ========================================================================= */
-local uLong crc32_combine_(crc1, crc2, len2)
+uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
- z_off64_t len2;
+ z_off_t len2;
{
- int n;
- unsigned long row;
- unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
- unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
-
- /* degenerate case (also disallow negative lengths) */
- if (len2 <= 0)
- return crc1;
-
- /* put operator for one zero bit in odd */
- odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
- row = 1;
- for (n = 1; n < GF2_DIM; n++) {
- odd[n] = row;
- row <<= 1;
- }
+ return crc32_combine64(crc1, crc2, len2);
+}
- /* put operator for two zero bits in even */
- gf2_matrix_square(even, odd);
-
- /* put operator for four zero bits in odd */
- gf2_matrix_square(odd, even);
-
- /* apply len2 zeros to crc1 (first square will put the operator for one
- zero byte, eight zero bits, in even) */
- do {
- /* apply zeros operator for this bit of len2 */
- gf2_matrix_square(even, odd);
- if (len2 & 1)
- crc1 = gf2_matrix_times(even, crc1);
- len2 >>= 1;
-
- /* if no more bits set, then done */
- if (len2 == 0)
- break;
-
- /* another iteration of the loop with odd and even swapped */
- gf2_matrix_square(odd, even);
- if (len2 & 1)
- crc1 = gf2_matrix_times(odd, crc1);
- len2 >>= 1;
-
- /* if no more bits set, then done */
- } while (len2 != 0);
-
- /* return combined crc */
- crc1 ^= crc2;
- return crc1;
+/* ========================================================================= */
+uLong ZEXPORT crc32_combine_gen64(len2)
+ z_off64_t len2;
+{
+#ifdef DYNAMIC_CRC_TABLE
+ once(&made, make_crc_table);
+#endif /* DYNAMIC_CRC_TABLE */
+ return x2nmodp(len2, 3);
}
/* ========================================================================= */
-uLong ZEXPORT crc32_combine(crc1, crc2, len2)
- uLong crc1;
- uLong crc2;
+uLong ZEXPORT crc32_combine_gen(len2)
z_off_t len2;
{
- return crc32_combine_(crc1, crc2, len2);
+ return crc32_combine_gen64(len2);
}
-uLong ZEXPORT crc32_combine64(crc1, crc2, len2)
+/* ========================================================================= */
+uLong crc32_combine_op(crc1, crc2, op)
uLong crc1;
uLong crc2;
- z_off64_t len2;
+ uLong op;
{
- return crc32_combine_(crc1, crc2, len2);
+ return multmodp(op, crc1) ^ crc2;
}
diff --git a/thirdparty/zlib/crc32.h b/thirdparty/zlib/crc32.h
index 9e0c778102..137df68d61 100644
--- a/thirdparty/zlib/crc32.h
+++ b/thirdparty/zlib/crc32.h
@@ -2,440 +2,9445 @@
* Generated automatically by crc32.c
*/
-local const z_crc_t FAR crc_table[TBLS][256] =
-{
- {
- 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
- 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
- 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
- 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
- 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
- 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
- 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
- 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
- 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
- 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
- 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
- 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
- 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
- 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
- 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
- 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
- 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
- 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
- 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
- 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
- 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
- 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
- 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
- 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
- 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
- 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
- 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
- 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
- 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
- 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
- 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
- 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
- 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
- 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
- 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
- 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
- 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
- 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
- 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
- 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
- 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
- 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
- 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
- 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
- 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
- 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
- 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
- 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
- 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
- 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
- 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
- 0x2d02ef8dUL
-#ifdef BYFOUR
- },
- {
- 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
- 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
- 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
- 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
- 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
- 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
- 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
- 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
- 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
- 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
- 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
- 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
- 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
- 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
- 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
- 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
- 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
- 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
- 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
- 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
- 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
- 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
- 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
- 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
- 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
- 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
- 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
- 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
- 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
- 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
- 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
- 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
- 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
- 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
- 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
- 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
- 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
- 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
- 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
- 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
- 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
- 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
- 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
- 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
- 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
- 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
- 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
- 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
- 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
- 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
- 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
- 0x9324fd72UL
- },
- {
- 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
- 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
- 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
- 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
- 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
- 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
- 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
- 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
- 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
- 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
- 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
- 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
- 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
- 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
- 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
- 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
- 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
- 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
- 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
- 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
- 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
- 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
- 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
- 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
- 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
- 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
- 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
- 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
- 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
- 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
- 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
- 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
- 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
- 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
- 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
- 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
- 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
- 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
- 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
- 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
- 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
- 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
- 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
- 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
- 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
- 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
- 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
- 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
- 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
- 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
- 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
- 0xbe9834edUL
- },
- {
- 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
- 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
- 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
- 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
- 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
- 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
- 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
- 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
- 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
- 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
- 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
- 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
- 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
- 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
- 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
- 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
- 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
- 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
- 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
- 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
- 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
- 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
- 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
- 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
- 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
- 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
- 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
- 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
- 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
- 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
- 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
- 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
- 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
- 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
- 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
- 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
- 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
- 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
- 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
- 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
- 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
- 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
- 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
- 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
- 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
- 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
- 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
- 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
- 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
- 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
- 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
- 0xde0506f1UL
- },
- {
- 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
- 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
- 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
- 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
- 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
- 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
- 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
- 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
- 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
- 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
- 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
- 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
- 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
- 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
- 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
- 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
- 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
- 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
- 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
- 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
- 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
- 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
- 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
- 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
- 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
- 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
- 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
- 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
- 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
- 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
- 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
- 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
- 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
- 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
- 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
- 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
- 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
- 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
- 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
- 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
- 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
- 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
- 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
- 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
- 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
- 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
- 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
- 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
- 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
- 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
- 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
- 0x8def022dUL
- },
- {
- 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
- 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
- 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
- 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
- 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
- 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
- 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
- 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
- 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
- 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
- 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
- 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
- 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
- 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
- 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
- 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
- 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
- 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
- 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
- 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
- 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
- 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
- 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
- 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
- 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
- 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
- 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
- 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
- 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
- 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
- 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
- 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
- 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
- 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
- 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
- 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
- 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
- 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
- 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
- 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
- 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
- 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
- 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
- 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
- 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
- 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
- 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
- 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
- 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
- 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
- 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
- 0x72fd2493UL
- },
- {
- 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
- 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
- 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
- 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
- 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
- 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
- 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
- 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
- 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
- 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
- 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
- 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
- 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
- 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
- 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
- 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
- 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
- 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
- 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
- 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
- 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
- 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
- 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
- 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
- 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
- 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
- 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
- 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
- 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
- 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
- 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
- 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
- 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
- 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
- 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
- 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
- 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
- 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
- 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
- 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
- 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
- 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
- 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
- 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
- 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
- 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
- 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
- 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
- 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
- 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
- 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
- 0xed3498beUL
- },
- {
- 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
- 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
- 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
- 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
- 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
- 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
- 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
- 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
- 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
- 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
- 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
- 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
- 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
- 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
- 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
- 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
- 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
- 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
- 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
- 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
- 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
- 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
- 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
- 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
- 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
- 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
- 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
- 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
- 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
- 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
- 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
- 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
- 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
- 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
- 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
- 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
- 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
- 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
- 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
- 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
- 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
- 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
- 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
- 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
- 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
- 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
- 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
- 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
- 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
- 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
- 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
- 0xf10605deUL
+local const z_crc_t FAR crc_table[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d};
+
+#ifdef W
+
+#if W == 8
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000};
+
+#else /* W == 4 */
+
+local const z_word_t FAR crc_big_table[] = {
+ 0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d};
+
+#endif
+
+#if N == 1
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c},
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x9630077700000000, 0x2c610eee00000000,
+ 0xba51099900000000, 0x19c46d0700000000, 0x8ff46a7000000000,
+ 0x35a563e900000000, 0xa395649e00000000, 0x3288db0e00000000,
+ 0xa4b8dc7900000000, 0x1ee9d5e000000000, 0x88d9d29700000000,
+ 0x2b4cb60900000000, 0xbd7cb17e00000000, 0x072db8e700000000,
+ 0x911dbf9000000000, 0x6410b71d00000000, 0xf220b06a00000000,
+ 0x4871b9f300000000, 0xde41be8400000000, 0x7dd4da1a00000000,
+ 0xebe4dd6d00000000, 0x51b5d4f400000000, 0xc785d38300000000,
+ 0x56986c1300000000, 0xc0a86b6400000000, 0x7af962fd00000000,
+ 0xecc9658a00000000, 0x4f5c011400000000, 0xd96c066300000000,
+ 0x633d0ffa00000000, 0xf50d088d00000000, 0xc8206e3b00000000,
+ 0x5e10694c00000000, 0xe44160d500000000, 0x727167a200000000,
+ 0xd1e4033c00000000, 0x47d4044b00000000, 0xfd850dd200000000,
+ 0x6bb50aa500000000, 0xfaa8b53500000000, 0x6c98b24200000000,
+ 0xd6c9bbdb00000000, 0x40f9bcac00000000, 0xe36cd83200000000,
+ 0x755cdf4500000000, 0xcf0dd6dc00000000, 0x593dd1ab00000000,
+ 0xac30d92600000000, 0x3a00de5100000000, 0x8051d7c800000000,
+ 0x1661d0bf00000000, 0xb5f4b42100000000, 0x23c4b35600000000,
+ 0x9995bacf00000000, 0x0fa5bdb800000000, 0x9eb8022800000000,
+ 0x0888055f00000000, 0xb2d90cc600000000, 0x24e90bb100000000,
+ 0x877c6f2f00000000, 0x114c685800000000, 0xab1d61c100000000,
+ 0x3d2d66b600000000, 0x9041dc7600000000, 0x0671db0100000000,
+ 0xbc20d29800000000, 0x2a10d5ef00000000, 0x8985b17100000000,
+ 0x1fb5b60600000000, 0xa5e4bf9f00000000, 0x33d4b8e800000000,
+ 0xa2c9077800000000, 0x34f9000f00000000, 0x8ea8099600000000,
+ 0x18980ee100000000, 0xbb0d6a7f00000000, 0x2d3d6d0800000000,
+ 0x976c649100000000, 0x015c63e600000000, 0xf4516b6b00000000,
+ 0x62616c1c00000000, 0xd830658500000000, 0x4e0062f200000000,
+ 0xed95066c00000000, 0x7ba5011b00000000, 0xc1f4088200000000,
+ 0x57c40ff500000000, 0xc6d9b06500000000, 0x50e9b71200000000,
+ 0xeab8be8b00000000, 0x7c88b9fc00000000, 0xdf1ddd6200000000,
+ 0x492dda1500000000, 0xf37cd38c00000000, 0x654cd4fb00000000,
+ 0x5861b24d00000000, 0xce51b53a00000000, 0x7400bca300000000,
+ 0xe230bbd400000000, 0x41a5df4a00000000, 0xd795d83d00000000,
+ 0x6dc4d1a400000000, 0xfbf4d6d300000000, 0x6ae9694300000000,
+ 0xfcd96e3400000000, 0x468867ad00000000, 0xd0b860da00000000,
+ 0x732d044400000000, 0xe51d033300000000, 0x5f4c0aaa00000000,
+ 0xc97c0ddd00000000, 0x3c71055000000000, 0xaa41022700000000,
+ 0x10100bbe00000000, 0x86200cc900000000, 0x25b5685700000000,
+ 0xb3856f2000000000, 0x09d466b900000000, 0x9fe461ce00000000,
+ 0x0ef9de5e00000000, 0x98c9d92900000000, 0x2298d0b000000000,
+ 0xb4a8d7c700000000, 0x173db35900000000, 0x810db42e00000000,
+ 0x3b5cbdb700000000, 0xad6cbac000000000, 0x2083b8ed00000000,
+ 0xb6b3bf9a00000000, 0x0ce2b60300000000, 0x9ad2b17400000000,
+ 0x3947d5ea00000000, 0xaf77d29d00000000, 0x1526db0400000000,
+ 0x8316dc7300000000, 0x120b63e300000000, 0x843b649400000000,
+ 0x3e6a6d0d00000000, 0xa85a6a7a00000000, 0x0bcf0ee400000000,
+ 0x9dff099300000000, 0x27ae000a00000000, 0xb19e077d00000000,
+ 0x44930ff000000000, 0xd2a3088700000000, 0x68f2011e00000000,
+ 0xfec2066900000000, 0x5d5762f700000000, 0xcb67658000000000,
+ 0x71366c1900000000, 0xe7066b6e00000000, 0x761bd4fe00000000,
+ 0xe02bd38900000000, 0x5a7ada1000000000, 0xcc4add6700000000,
+ 0x6fdfb9f900000000, 0xf9efbe8e00000000, 0x43beb71700000000,
+ 0xd58eb06000000000, 0xe8a3d6d600000000, 0x7e93d1a100000000,
+ 0xc4c2d83800000000, 0x52f2df4f00000000, 0xf167bbd100000000,
+ 0x6757bca600000000, 0xdd06b53f00000000, 0x4b36b24800000000,
+ 0xda2b0dd800000000, 0x4c1b0aaf00000000, 0xf64a033600000000,
+ 0x607a044100000000, 0xc3ef60df00000000, 0x55df67a800000000,
+ 0xef8e6e3100000000, 0x79be694600000000, 0x8cb361cb00000000,
+ 0x1a8366bc00000000, 0xa0d26f2500000000, 0x36e2685200000000,
+ 0x95770ccc00000000, 0x03470bbb00000000, 0xb916022200000000,
+ 0x2f26055500000000, 0xbe3bbac500000000, 0x280bbdb200000000,
+ 0x925ab42b00000000, 0x046ab35c00000000, 0xa7ffd7c200000000,
+ 0x31cfd0b500000000, 0x8b9ed92c00000000, 0x1daede5b00000000,
+ 0xb0c2649b00000000, 0x26f263ec00000000, 0x9ca36a7500000000,
+ 0x0a936d0200000000, 0xa906099c00000000, 0x3f360eeb00000000,
+ 0x8567077200000000, 0x1357000500000000, 0x824abf9500000000,
+ 0x147ab8e200000000, 0xae2bb17b00000000, 0x381bb60c00000000,
+ 0x9b8ed29200000000, 0x0dbed5e500000000, 0xb7efdc7c00000000,
+ 0x21dfdb0b00000000, 0xd4d2d38600000000, 0x42e2d4f100000000,
+ 0xf8b3dd6800000000, 0x6e83da1f00000000, 0xcd16be8100000000,
+ 0x5b26b9f600000000, 0xe177b06f00000000, 0x7747b71800000000,
+ 0xe65a088800000000, 0x706a0fff00000000, 0xca3b066600000000,
+ 0x5c0b011100000000, 0xff9e658f00000000, 0x69ae62f800000000,
+ 0xd3ff6b6100000000, 0x45cf6c1600000000, 0x78e20aa000000000,
+ 0xeed20dd700000000, 0x5483044e00000000, 0xc2b3033900000000,
+ 0x612667a700000000, 0xf71660d000000000, 0x4d47694900000000,
+ 0xdb776e3e00000000, 0x4a6ad1ae00000000, 0xdc5ad6d900000000,
+ 0x660bdf4000000000, 0xf03bd83700000000, 0x53aebca900000000,
+ 0xc59ebbde00000000, 0x7fcfb24700000000, 0xe9ffb53000000000,
+ 0x1cf2bdbd00000000, 0x8ac2baca00000000, 0x3093b35300000000,
+ 0xa6a3b42400000000, 0x0536d0ba00000000, 0x9306d7cd00000000,
+ 0x2957de5400000000, 0xbf67d92300000000, 0x2e7a66b300000000,
+ 0xb84a61c400000000, 0x021b685d00000000, 0x942b6f2a00000000,
+ 0x37be0bb400000000, 0xa18e0cc300000000, 0x1bdf055a00000000,
+ 0x8def022d00000000},
+ {0x0000000000000000, 0x41311b1900000000, 0x8262363200000000,
+ 0xc3532d2b00000000, 0x04c56c6400000000, 0x45f4777d00000000,
+ 0x86a75a5600000000, 0xc796414f00000000, 0x088ad9c800000000,
+ 0x49bbc2d100000000, 0x8ae8effa00000000, 0xcbd9f4e300000000,
+ 0x0c4fb5ac00000000, 0x4d7eaeb500000000, 0x8e2d839e00000000,
+ 0xcf1c988700000000, 0x5112c24a00000000, 0x1023d95300000000,
+ 0xd370f47800000000, 0x9241ef6100000000, 0x55d7ae2e00000000,
+ 0x14e6b53700000000, 0xd7b5981c00000000, 0x9684830500000000,
+ 0x59981b8200000000, 0x18a9009b00000000, 0xdbfa2db000000000,
+ 0x9acb36a900000000, 0x5d5d77e600000000, 0x1c6c6cff00000000,
+ 0xdf3f41d400000000, 0x9e0e5acd00000000, 0xa224849500000000,
+ 0xe3159f8c00000000, 0x2046b2a700000000, 0x6177a9be00000000,
+ 0xa6e1e8f100000000, 0xe7d0f3e800000000, 0x2483dec300000000,
+ 0x65b2c5da00000000, 0xaaae5d5d00000000, 0xeb9f464400000000,
+ 0x28cc6b6f00000000, 0x69fd707600000000, 0xae6b313900000000,
+ 0xef5a2a2000000000, 0x2c09070b00000000, 0x6d381c1200000000,
+ 0xf33646df00000000, 0xb2075dc600000000, 0x715470ed00000000,
+ 0x30656bf400000000, 0xf7f32abb00000000, 0xb6c231a200000000,
+ 0x75911c8900000000, 0x34a0079000000000, 0xfbbc9f1700000000,
+ 0xba8d840e00000000, 0x79dea92500000000, 0x38efb23c00000000,
+ 0xff79f37300000000, 0xbe48e86a00000000, 0x7d1bc54100000000,
+ 0x3c2ade5800000000, 0x054f79f000000000, 0x447e62e900000000,
+ 0x872d4fc200000000, 0xc61c54db00000000, 0x018a159400000000,
+ 0x40bb0e8d00000000, 0x83e823a600000000, 0xc2d938bf00000000,
+ 0x0dc5a03800000000, 0x4cf4bb2100000000, 0x8fa7960a00000000,
+ 0xce968d1300000000, 0x0900cc5c00000000, 0x4831d74500000000,
+ 0x8b62fa6e00000000, 0xca53e17700000000, 0x545dbbba00000000,
+ 0x156ca0a300000000, 0xd63f8d8800000000, 0x970e969100000000,
+ 0x5098d7de00000000, 0x11a9ccc700000000, 0xd2fae1ec00000000,
+ 0x93cbfaf500000000, 0x5cd7627200000000, 0x1de6796b00000000,
+ 0xdeb5544000000000, 0x9f844f5900000000, 0x58120e1600000000,
+ 0x1923150f00000000, 0xda70382400000000, 0x9b41233d00000000,
+ 0xa76bfd6500000000, 0xe65ae67c00000000, 0x2509cb5700000000,
+ 0x6438d04e00000000, 0xa3ae910100000000, 0xe29f8a1800000000,
+ 0x21cca73300000000, 0x60fdbc2a00000000, 0xafe124ad00000000,
+ 0xeed03fb400000000, 0x2d83129f00000000, 0x6cb2098600000000,
+ 0xab2448c900000000, 0xea1553d000000000, 0x29467efb00000000,
+ 0x687765e200000000, 0xf6793f2f00000000, 0xb748243600000000,
+ 0x741b091d00000000, 0x352a120400000000, 0xf2bc534b00000000,
+ 0xb38d485200000000, 0x70de657900000000, 0x31ef7e6000000000,
+ 0xfef3e6e700000000, 0xbfc2fdfe00000000, 0x7c91d0d500000000,
+ 0x3da0cbcc00000000, 0xfa368a8300000000, 0xbb07919a00000000,
+ 0x7854bcb100000000, 0x3965a7a800000000, 0x4b98833b00000000,
+ 0x0aa9982200000000, 0xc9fab50900000000, 0x88cbae1000000000,
+ 0x4f5def5f00000000, 0x0e6cf44600000000, 0xcd3fd96d00000000,
+ 0x8c0ec27400000000, 0x43125af300000000, 0x022341ea00000000,
+ 0xc1706cc100000000, 0x804177d800000000, 0x47d7369700000000,
+ 0x06e62d8e00000000, 0xc5b500a500000000, 0x84841bbc00000000,
+ 0x1a8a417100000000, 0x5bbb5a6800000000, 0x98e8774300000000,
+ 0xd9d96c5a00000000, 0x1e4f2d1500000000, 0x5f7e360c00000000,
+ 0x9c2d1b2700000000, 0xdd1c003e00000000, 0x120098b900000000,
+ 0x533183a000000000, 0x9062ae8b00000000, 0xd153b59200000000,
+ 0x16c5f4dd00000000, 0x57f4efc400000000, 0x94a7c2ef00000000,
+ 0xd596d9f600000000, 0xe9bc07ae00000000, 0xa88d1cb700000000,
+ 0x6bde319c00000000, 0x2aef2a8500000000, 0xed796bca00000000,
+ 0xac4870d300000000, 0x6f1b5df800000000, 0x2e2a46e100000000,
+ 0xe136de6600000000, 0xa007c57f00000000, 0x6354e85400000000,
+ 0x2265f34d00000000, 0xe5f3b20200000000, 0xa4c2a91b00000000,
+ 0x6791843000000000, 0x26a09f2900000000, 0xb8aec5e400000000,
+ 0xf99fdefd00000000, 0x3accf3d600000000, 0x7bfde8cf00000000,
+ 0xbc6ba98000000000, 0xfd5ab29900000000, 0x3e099fb200000000,
+ 0x7f3884ab00000000, 0xb0241c2c00000000, 0xf115073500000000,
+ 0x32462a1e00000000, 0x7377310700000000, 0xb4e1704800000000,
+ 0xf5d06b5100000000, 0x3683467a00000000, 0x77b25d6300000000,
+ 0x4ed7facb00000000, 0x0fe6e1d200000000, 0xccb5ccf900000000,
+ 0x8d84d7e000000000, 0x4a1296af00000000, 0x0b238db600000000,
+ 0xc870a09d00000000, 0x8941bb8400000000, 0x465d230300000000,
+ 0x076c381a00000000, 0xc43f153100000000, 0x850e0e2800000000,
+ 0x42984f6700000000, 0x03a9547e00000000, 0xc0fa795500000000,
+ 0x81cb624c00000000, 0x1fc5388100000000, 0x5ef4239800000000,
+ 0x9da70eb300000000, 0xdc9615aa00000000, 0x1b0054e500000000,
+ 0x5a314ffc00000000, 0x996262d700000000, 0xd85379ce00000000,
+ 0x174fe14900000000, 0x567efa5000000000, 0x952dd77b00000000,
+ 0xd41ccc6200000000, 0x138a8d2d00000000, 0x52bb963400000000,
+ 0x91e8bb1f00000000, 0xd0d9a00600000000, 0xecf37e5e00000000,
+ 0xadc2654700000000, 0x6e91486c00000000, 0x2fa0537500000000,
+ 0xe836123a00000000, 0xa907092300000000, 0x6a54240800000000,
+ 0x2b653f1100000000, 0xe479a79600000000, 0xa548bc8f00000000,
+ 0x661b91a400000000, 0x272a8abd00000000, 0xe0bccbf200000000,
+ 0xa18dd0eb00000000, 0x62defdc000000000, 0x23efe6d900000000,
+ 0xbde1bc1400000000, 0xfcd0a70d00000000, 0x3f838a2600000000,
+ 0x7eb2913f00000000, 0xb924d07000000000, 0xf815cb6900000000,
+ 0x3b46e64200000000, 0x7a77fd5b00000000, 0xb56b65dc00000000,
+ 0xf45a7ec500000000, 0x370953ee00000000, 0x763848f700000000,
+ 0xb1ae09b800000000, 0xf09f12a100000000, 0x33cc3f8a00000000,
+ 0x72fd249300000000},
+ {0x0000000000000000, 0x376ac20100000000, 0x6ed4840300000000,
+ 0x59be460200000000, 0xdca8090700000000, 0xebc2cb0600000000,
+ 0xb27c8d0400000000, 0x85164f0500000000, 0xb851130e00000000,
+ 0x8f3bd10f00000000, 0xd685970d00000000, 0xe1ef550c00000000,
+ 0x64f91a0900000000, 0x5393d80800000000, 0x0a2d9e0a00000000,
+ 0x3d475c0b00000000, 0x70a3261c00000000, 0x47c9e41d00000000,
+ 0x1e77a21f00000000, 0x291d601e00000000, 0xac0b2f1b00000000,
+ 0x9b61ed1a00000000, 0xc2dfab1800000000, 0xf5b5691900000000,
+ 0xc8f2351200000000, 0xff98f71300000000, 0xa626b11100000000,
+ 0x914c731000000000, 0x145a3c1500000000, 0x2330fe1400000000,
+ 0x7a8eb81600000000, 0x4de47a1700000000, 0xe0464d3800000000,
+ 0xd72c8f3900000000, 0x8e92c93b00000000, 0xb9f80b3a00000000,
+ 0x3cee443f00000000, 0x0b84863e00000000, 0x523ac03c00000000,
+ 0x6550023d00000000, 0x58175e3600000000, 0x6f7d9c3700000000,
+ 0x36c3da3500000000, 0x01a9183400000000, 0x84bf573100000000,
+ 0xb3d5953000000000, 0xea6bd33200000000, 0xdd01113300000000,
+ 0x90e56b2400000000, 0xa78fa92500000000, 0xfe31ef2700000000,
+ 0xc95b2d2600000000, 0x4c4d622300000000, 0x7b27a02200000000,
+ 0x2299e62000000000, 0x15f3242100000000, 0x28b4782a00000000,
+ 0x1fdeba2b00000000, 0x4660fc2900000000, 0x710a3e2800000000,
+ 0xf41c712d00000000, 0xc376b32c00000000, 0x9ac8f52e00000000,
+ 0xada2372f00000000, 0xc08d9a7000000000, 0xf7e7587100000000,
+ 0xae591e7300000000, 0x9933dc7200000000, 0x1c25937700000000,
+ 0x2b4f517600000000, 0x72f1177400000000, 0x459bd57500000000,
+ 0x78dc897e00000000, 0x4fb64b7f00000000, 0x16080d7d00000000,
+ 0x2162cf7c00000000, 0xa474807900000000, 0x931e427800000000,
+ 0xcaa0047a00000000, 0xfdcac67b00000000, 0xb02ebc6c00000000,
+ 0x87447e6d00000000, 0xdefa386f00000000, 0xe990fa6e00000000,
+ 0x6c86b56b00000000, 0x5bec776a00000000, 0x0252316800000000,
+ 0x3538f36900000000, 0x087faf6200000000, 0x3f156d6300000000,
+ 0x66ab2b6100000000, 0x51c1e96000000000, 0xd4d7a66500000000,
+ 0xe3bd646400000000, 0xba03226600000000, 0x8d69e06700000000,
+ 0x20cbd74800000000, 0x17a1154900000000, 0x4e1f534b00000000,
+ 0x7975914a00000000, 0xfc63de4f00000000, 0xcb091c4e00000000,
+ 0x92b75a4c00000000, 0xa5dd984d00000000, 0x989ac44600000000,
+ 0xaff0064700000000, 0xf64e404500000000, 0xc124824400000000,
+ 0x4432cd4100000000, 0x73580f4000000000, 0x2ae6494200000000,
+ 0x1d8c8b4300000000, 0x5068f15400000000, 0x6702335500000000,
+ 0x3ebc755700000000, 0x09d6b75600000000, 0x8cc0f85300000000,
+ 0xbbaa3a5200000000, 0xe2147c5000000000, 0xd57ebe5100000000,
+ 0xe839e25a00000000, 0xdf53205b00000000, 0x86ed665900000000,
+ 0xb187a45800000000, 0x3491eb5d00000000, 0x03fb295c00000000,
+ 0x5a456f5e00000000, 0x6d2fad5f00000000, 0x801b35e100000000,
+ 0xb771f7e000000000, 0xeecfb1e200000000, 0xd9a573e300000000,
+ 0x5cb33ce600000000, 0x6bd9fee700000000, 0x3267b8e500000000,
+ 0x050d7ae400000000, 0x384a26ef00000000, 0x0f20e4ee00000000,
+ 0x569ea2ec00000000, 0x61f460ed00000000, 0xe4e22fe800000000,
+ 0xd388ede900000000, 0x8a36abeb00000000, 0xbd5c69ea00000000,
+ 0xf0b813fd00000000, 0xc7d2d1fc00000000, 0x9e6c97fe00000000,
+ 0xa90655ff00000000, 0x2c101afa00000000, 0x1b7ad8fb00000000,
+ 0x42c49ef900000000, 0x75ae5cf800000000, 0x48e900f300000000,
+ 0x7f83c2f200000000, 0x263d84f000000000, 0x115746f100000000,
+ 0x944109f400000000, 0xa32bcbf500000000, 0xfa958df700000000,
+ 0xcdff4ff600000000, 0x605d78d900000000, 0x5737bad800000000,
+ 0x0e89fcda00000000, 0x39e33edb00000000, 0xbcf571de00000000,
+ 0x8b9fb3df00000000, 0xd221f5dd00000000, 0xe54b37dc00000000,
+ 0xd80c6bd700000000, 0xef66a9d600000000, 0xb6d8efd400000000,
+ 0x81b22dd500000000, 0x04a462d000000000, 0x33cea0d100000000,
+ 0x6a70e6d300000000, 0x5d1a24d200000000, 0x10fe5ec500000000,
+ 0x27949cc400000000, 0x7e2adac600000000, 0x494018c700000000,
+ 0xcc5657c200000000, 0xfb3c95c300000000, 0xa282d3c100000000,
+ 0x95e811c000000000, 0xa8af4dcb00000000, 0x9fc58fca00000000,
+ 0xc67bc9c800000000, 0xf1110bc900000000, 0x740744cc00000000,
+ 0x436d86cd00000000, 0x1ad3c0cf00000000, 0x2db902ce00000000,
+ 0x4096af9100000000, 0x77fc6d9000000000, 0x2e422b9200000000,
+ 0x1928e99300000000, 0x9c3ea69600000000, 0xab54649700000000,
+ 0xf2ea229500000000, 0xc580e09400000000, 0xf8c7bc9f00000000,
+ 0xcfad7e9e00000000, 0x9613389c00000000, 0xa179fa9d00000000,
+ 0x246fb59800000000, 0x1305779900000000, 0x4abb319b00000000,
+ 0x7dd1f39a00000000, 0x3035898d00000000, 0x075f4b8c00000000,
+ 0x5ee10d8e00000000, 0x698bcf8f00000000, 0xec9d808a00000000,
+ 0xdbf7428b00000000, 0x8249048900000000, 0xb523c68800000000,
+ 0x88649a8300000000, 0xbf0e588200000000, 0xe6b01e8000000000,
+ 0xd1dadc8100000000, 0x54cc938400000000, 0x63a6518500000000,
+ 0x3a18178700000000, 0x0d72d58600000000, 0xa0d0e2a900000000,
+ 0x97ba20a800000000, 0xce0466aa00000000, 0xf96ea4ab00000000,
+ 0x7c78ebae00000000, 0x4b1229af00000000, 0x12ac6fad00000000,
+ 0x25c6adac00000000, 0x1881f1a700000000, 0x2feb33a600000000,
+ 0x765575a400000000, 0x413fb7a500000000, 0xc429f8a000000000,
+ 0xf3433aa100000000, 0xaafd7ca300000000, 0x9d97bea200000000,
+ 0xd073c4b500000000, 0xe71906b400000000, 0xbea740b600000000,
+ 0x89cd82b700000000, 0x0cdbcdb200000000, 0x3bb10fb300000000,
+ 0x620f49b100000000, 0x55658bb000000000, 0x6822d7bb00000000,
+ 0x5f4815ba00000000, 0x06f653b800000000, 0x319c91b900000000,
+ 0xb48adebc00000000, 0x83e01cbd00000000, 0xda5e5abf00000000,
+ 0xed3498be00000000},
+ {0x0000000000000000, 0x6567bcb800000000, 0x8bc809aa00000000,
+ 0xeeafb51200000000, 0x5797628f00000000, 0x32f0de3700000000,
+ 0xdc5f6b2500000000, 0xb938d79d00000000, 0xef28b4c500000000,
+ 0x8a4f087d00000000, 0x64e0bd6f00000000, 0x018701d700000000,
+ 0xb8bfd64a00000000, 0xddd86af200000000, 0x3377dfe000000000,
+ 0x5610635800000000, 0x9f57195000000000, 0xfa30a5e800000000,
+ 0x149f10fa00000000, 0x71f8ac4200000000, 0xc8c07bdf00000000,
+ 0xada7c76700000000, 0x4308727500000000, 0x266fcecd00000000,
+ 0x707fad9500000000, 0x1518112d00000000, 0xfbb7a43f00000000,
+ 0x9ed0188700000000, 0x27e8cf1a00000000, 0x428f73a200000000,
+ 0xac20c6b000000000, 0xc9477a0800000000, 0x3eaf32a000000000,
+ 0x5bc88e1800000000, 0xb5673b0a00000000, 0xd00087b200000000,
+ 0x6938502f00000000, 0x0c5fec9700000000, 0xe2f0598500000000,
+ 0x8797e53d00000000, 0xd187866500000000, 0xb4e03add00000000,
+ 0x5a4f8fcf00000000, 0x3f28337700000000, 0x8610e4ea00000000,
+ 0xe377585200000000, 0x0dd8ed4000000000, 0x68bf51f800000000,
+ 0xa1f82bf000000000, 0xc49f974800000000, 0x2a30225a00000000,
+ 0x4f579ee200000000, 0xf66f497f00000000, 0x9308f5c700000000,
+ 0x7da740d500000000, 0x18c0fc6d00000000, 0x4ed09f3500000000,
+ 0x2bb7238d00000000, 0xc518969f00000000, 0xa07f2a2700000000,
+ 0x1947fdba00000000, 0x7c20410200000000, 0x928ff41000000000,
+ 0xf7e848a800000000, 0x3d58149b00000000, 0x583fa82300000000,
+ 0xb6901d3100000000, 0xd3f7a18900000000, 0x6acf761400000000,
+ 0x0fa8caac00000000, 0xe1077fbe00000000, 0x8460c30600000000,
+ 0xd270a05e00000000, 0xb7171ce600000000, 0x59b8a9f400000000,
+ 0x3cdf154c00000000, 0x85e7c2d100000000, 0xe0807e6900000000,
+ 0x0e2fcb7b00000000, 0x6b4877c300000000, 0xa20f0dcb00000000,
+ 0xc768b17300000000, 0x29c7046100000000, 0x4ca0b8d900000000,
+ 0xf5986f4400000000, 0x90ffd3fc00000000, 0x7e5066ee00000000,
+ 0x1b37da5600000000, 0x4d27b90e00000000, 0x284005b600000000,
+ 0xc6efb0a400000000, 0xa3880c1c00000000, 0x1ab0db8100000000,
+ 0x7fd7673900000000, 0x9178d22b00000000, 0xf41f6e9300000000,
+ 0x03f7263b00000000, 0x66909a8300000000, 0x883f2f9100000000,
+ 0xed58932900000000, 0x546044b400000000, 0x3107f80c00000000,
+ 0xdfa84d1e00000000, 0xbacff1a600000000, 0xecdf92fe00000000,
+ 0x89b82e4600000000, 0x67179b5400000000, 0x027027ec00000000,
+ 0xbb48f07100000000, 0xde2f4cc900000000, 0x3080f9db00000000,
+ 0x55e7456300000000, 0x9ca03f6b00000000, 0xf9c783d300000000,
+ 0x176836c100000000, 0x720f8a7900000000, 0xcb375de400000000,
+ 0xae50e15c00000000, 0x40ff544e00000000, 0x2598e8f600000000,
+ 0x73888bae00000000, 0x16ef371600000000, 0xf840820400000000,
+ 0x9d273ebc00000000, 0x241fe92100000000, 0x4178559900000000,
+ 0xafd7e08b00000000, 0xcab05c3300000000, 0x3bb659ed00000000,
+ 0x5ed1e55500000000, 0xb07e504700000000, 0xd519ecff00000000,
+ 0x6c213b6200000000, 0x094687da00000000, 0xe7e932c800000000,
+ 0x828e8e7000000000, 0xd49eed2800000000, 0xb1f9519000000000,
+ 0x5f56e48200000000, 0x3a31583a00000000, 0x83098fa700000000,
+ 0xe66e331f00000000, 0x08c1860d00000000, 0x6da63ab500000000,
+ 0xa4e140bd00000000, 0xc186fc0500000000, 0x2f29491700000000,
+ 0x4a4ef5af00000000, 0xf376223200000000, 0x96119e8a00000000,
+ 0x78be2b9800000000, 0x1dd9972000000000, 0x4bc9f47800000000,
+ 0x2eae48c000000000, 0xc001fdd200000000, 0xa566416a00000000,
+ 0x1c5e96f700000000, 0x79392a4f00000000, 0x97969f5d00000000,
+ 0xf2f123e500000000, 0x05196b4d00000000, 0x607ed7f500000000,
+ 0x8ed162e700000000, 0xebb6de5f00000000, 0x528e09c200000000,
+ 0x37e9b57a00000000, 0xd946006800000000, 0xbc21bcd000000000,
+ 0xea31df8800000000, 0x8f56633000000000, 0x61f9d62200000000,
+ 0x049e6a9a00000000, 0xbda6bd0700000000, 0xd8c101bf00000000,
+ 0x366eb4ad00000000, 0x5309081500000000, 0x9a4e721d00000000,
+ 0xff29cea500000000, 0x11867bb700000000, 0x74e1c70f00000000,
+ 0xcdd9109200000000, 0xa8beac2a00000000, 0x4611193800000000,
+ 0x2376a58000000000, 0x7566c6d800000000, 0x10017a6000000000,
+ 0xfeaecf7200000000, 0x9bc973ca00000000, 0x22f1a45700000000,
+ 0x479618ef00000000, 0xa939adfd00000000, 0xcc5e114500000000,
+ 0x06ee4d7600000000, 0x6389f1ce00000000, 0x8d2644dc00000000,
+ 0xe841f86400000000, 0x51792ff900000000, 0x341e934100000000,
+ 0xdab1265300000000, 0xbfd69aeb00000000, 0xe9c6f9b300000000,
+ 0x8ca1450b00000000, 0x620ef01900000000, 0x07694ca100000000,
+ 0xbe519b3c00000000, 0xdb36278400000000, 0x3599929600000000,
+ 0x50fe2e2e00000000, 0x99b9542600000000, 0xfcdee89e00000000,
+ 0x12715d8c00000000, 0x7716e13400000000, 0xce2e36a900000000,
+ 0xab498a1100000000, 0x45e63f0300000000, 0x208183bb00000000,
+ 0x7691e0e300000000, 0x13f65c5b00000000, 0xfd59e94900000000,
+ 0x983e55f100000000, 0x2106826c00000000, 0x44613ed400000000,
+ 0xaace8bc600000000, 0xcfa9377e00000000, 0x38417fd600000000,
+ 0x5d26c36e00000000, 0xb389767c00000000, 0xd6eecac400000000,
+ 0x6fd61d5900000000, 0x0ab1a1e100000000, 0xe41e14f300000000,
+ 0x8179a84b00000000, 0xd769cb1300000000, 0xb20e77ab00000000,
+ 0x5ca1c2b900000000, 0x39c67e0100000000, 0x80fea99c00000000,
+ 0xe599152400000000, 0x0b36a03600000000, 0x6e511c8e00000000,
+ 0xa716668600000000, 0xc271da3e00000000, 0x2cde6f2c00000000,
+ 0x49b9d39400000000, 0xf081040900000000, 0x95e6b8b100000000,
+ 0x7b490da300000000, 0x1e2eb11b00000000, 0x483ed24300000000,
+ 0x2d596efb00000000, 0xc3f6dbe900000000, 0xa691675100000000,
+ 0x1fa9b0cc00000000, 0x7ace0c7400000000, 0x9461b96600000000,
+ 0xf10605de00000000},
+ {0x0000000000000000, 0xb029603d00000000, 0x6053c07a00000000,
+ 0xd07aa04700000000, 0xc0a680f500000000, 0x708fe0c800000000,
+ 0xa0f5408f00000000, 0x10dc20b200000000, 0xc14b703000000000,
+ 0x7162100d00000000, 0xa118b04a00000000, 0x1131d07700000000,
+ 0x01edf0c500000000, 0xb1c490f800000000, 0x61be30bf00000000,
+ 0xd197508200000000, 0x8297e06000000000, 0x32be805d00000000,
+ 0xe2c4201a00000000, 0x52ed402700000000, 0x4231609500000000,
+ 0xf21800a800000000, 0x2262a0ef00000000, 0x924bc0d200000000,
+ 0x43dc905000000000, 0xf3f5f06d00000000, 0x238f502a00000000,
+ 0x93a6301700000000, 0x837a10a500000000, 0x3353709800000000,
+ 0xe329d0df00000000, 0x5300b0e200000000, 0x042fc1c100000000,
+ 0xb406a1fc00000000, 0x647c01bb00000000, 0xd455618600000000,
+ 0xc489413400000000, 0x74a0210900000000, 0xa4da814e00000000,
+ 0x14f3e17300000000, 0xc564b1f100000000, 0x754dd1cc00000000,
+ 0xa537718b00000000, 0x151e11b600000000, 0x05c2310400000000,
+ 0xb5eb513900000000, 0x6591f17e00000000, 0xd5b8914300000000,
+ 0x86b821a100000000, 0x3691419c00000000, 0xe6ebe1db00000000,
+ 0x56c281e600000000, 0x461ea15400000000, 0xf637c16900000000,
+ 0x264d612e00000000, 0x9664011300000000, 0x47f3519100000000,
+ 0xf7da31ac00000000, 0x27a091eb00000000, 0x9789f1d600000000,
+ 0x8755d16400000000, 0x377cb15900000000, 0xe706111e00000000,
+ 0x572f712300000000, 0x4958f35800000000, 0xf971936500000000,
+ 0x290b332200000000, 0x9922531f00000000, 0x89fe73ad00000000,
+ 0x39d7139000000000, 0xe9adb3d700000000, 0x5984d3ea00000000,
+ 0x8813836800000000, 0x383ae35500000000, 0xe840431200000000,
+ 0x5869232f00000000, 0x48b5039d00000000, 0xf89c63a000000000,
+ 0x28e6c3e700000000, 0x98cfa3da00000000, 0xcbcf133800000000,
+ 0x7be6730500000000, 0xab9cd34200000000, 0x1bb5b37f00000000,
+ 0x0b6993cd00000000, 0xbb40f3f000000000, 0x6b3a53b700000000,
+ 0xdb13338a00000000, 0x0a84630800000000, 0xbaad033500000000,
+ 0x6ad7a37200000000, 0xdafec34f00000000, 0xca22e3fd00000000,
+ 0x7a0b83c000000000, 0xaa71238700000000, 0x1a5843ba00000000,
+ 0x4d77329900000000, 0xfd5e52a400000000, 0x2d24f2e300000000,
+ 0x9d0d92de00000000, 0x8dd1b26c00000000, 0x3df8d25100000000,
+ 0xed82721600000000, 0x5dab122b00000000, 0x8c3c42a900000000,
+ 0x3c15229400000000, 0xec6f82d300000000, 0x5c46e2ee00000000,
+ 0x4c9ac25c00000000, 0xfcb3a26100000000, 0x2cc9022600000000,
+ 0x9ce0621b00000000, 0xcfe0d2f900000000, 0x7fc9b2c400000000,
+ 0xafb3128300000000, 0x1f9a72be00000000, 0x0f46520c00000000,
+ 0xbf6f323100000000, 0x6f15927600000000, 0xdf3cf24b00000000,
+ 0x0eaba2c900000000, 0xbe82c2f400000000, 0x6ef862b300000000,
+ 0xded1028e00000000, 0xce0d223c00000000, 0x7e24420100000000,
+ 0xae5ee24600000000, 0x1e77827b00000000, 0x92b0e6b100000000,
+ 0x2299868c00000000, 0xf2e326cb00000000, 0x42ca46f600000000,
+ 0x5216664400000000, 0xe23f067900000000, 0x3245a63e00000000,
+ 0x826cc60300000000, 0x53fb968100000000, 0xe3d2f6bc00000000,
+ 0x33a856fb00000000, 0x838136c600000000, 0x935d167400000000,
+ 0x2374764900000000, 0xf30ed60e00000000, 0x4327b63300000000,
+ 0x102706d100000000, 0xa00e66ec00000000, 0x7074c6ab00000000,
+ 0xc05da69600000000, 0xd081862400000000, 0x60a8e61900000000,
+ 0xb0d2465e00000000, 0x00fb266300000000, 0xd16c76e100000000,
+ 0x614516dc00000000, 0xb13fb69b00000000, 0x0116d6a600000000,
+ 0x11caf61400000000, 0xa1e3962900000000, 0x7199366e00000000,
+ 0xc1b0565300000000, 0x969f277000000000, 0x26b6474d00000000,
+ 0xf6cce70a00000000, 0x46e5873700000000, 0x5639a78500000000,
+ 0xe610c7b800000000, 0x366a67ff00000000, 0x864307c200000000,
+ 0x57d4574000000000, 0xe7fd377d00000000, 0x3787973a00000000,
+ 0x87aef70700000000, 0x9772d7b500000000, 0x275bb78800000000,
+ 0xf72117cf00000000, 0x470877f200000000, 0x1408c71000000000,
+ 0xa421a72d00000000, 0x745b076a00000000, 0xc472675700000000,
+ 0xd4ae47e500000000, 0x648727d800000000, 0xb4fd879f00000000,
+ 0x04d4e7a200000000, 0xd543b72000000000, 0x656ad71d00000000,
+ 0xb510775a00000000, 0x0539176700000000, 0x15e537d500000000,
+ 0xa5cc57e800000000, 0x75b6f7af00000000, 0xc59f979200000000,
+ 0xdbe815e900000000, 0x6bc175d400000000, 0xbbbbd59300000000,
+ 0x0b92b5ae00000000, 0x1b4e951c00000000, 0xab67f52100000000,
+ 0x7b1d556600000000, 0xcb34355b00000000, 0x1aa365d900000000,
+ 0xaa8a05e400000000, 0x7af0a5a300000000, 0xcad9c59e00000000,
+ 0xda05e52c00000000, 0x6a2c851100000000, 0xba56255600000000,
+ 0x0a7f456b00000000, 0x597ff58900000000, 0xe95695b400000000,
+ 0x392c35f300000000, 0x890555ce00000000, 0x99d9757c00000000,
+ 0x29f0154100000000, 0xf98ab50600000000, 0x49a3d53b00000000,
+ 0x983485b900000000, 0x281de58400000000, 0xf86745c300000000,
+ 0x484e25fe00000000, 0x5892054c00000000, 0xe8bb657100000000,
+ 0x38c1c53600000000, 0x88e8a50b00000000, 0xdfc7d42800000000,
+ 0x6feeb41500000000, 0xbf94145200000000, 0x0fbd746f00000000,
+ 0x1f6154dd00000000, 0xaf4834e000000000, 0x7f3294a700000000,
+ 0xcf1bf49a00000000, 0x1e8ca41800000000, 0xaea5c42500000000,
+ 0x7edf646200000000, 0xcef6045f00000000, 0xde2a24ed00000000,
+ 0x6e0344d000000000, 0xbe79e49700000000, 0x0e5084aa00000000,
+ 0x5d50344800000000, 0xed79547500000000, 0x3d03f43200000000,
+ 0x8d2a940f00000000, 0x9df6b4bd00000000, 0x2ddfd48000000000,
+ 0xfda574c700000000, 0x4d8c14fa00000000, 0x9c1b447800000000,
+ 0x2c32244500000000, 0xfc48840200000000, 0x4c61e43f00000000,
+ 0x5cbdc48d00000000, 0xec94a4b000000000, 0x3cee04f700000000,
+ 0x8cc764ca00000000},
+ {0x0000000000000000, 0xa5d35ccb00000000, 0x0ba1c84d00000000,
+ 0xae72948600000000, 0x1642919b00000000, 0xb391cd5000000000,
+ 0x1de359d600000000, 0xb830051d00000000, 0x6d8253ec00000000,
+ 0xc8510f2700000000, 0x66239ba100000000, 0xc3f0c76a00000000,
+ 0x7bc0c27700000000, 0xde139ebc00000000, 0x70610a3a00000000,
+ 0xd5b256f100000000, 0x9b02d60300000000, 0x3ed18ac800000000,
+ 0x90a31e4e00000000, 0x3570428500000000, 0x8d40479800000000,
+ 0x28931b5300000000, 0x86e18fd500000000, 0x2332d31e00000000,
+ 0xf68085ef00000000, 0x5353d92400000000, 0xfd214da200000000,
+ 0x58f2116900000000, 0xe0c2147400000000, 0x451148bf00000000,
+ 0xeb63dc3900000000, 0x4eb080f200000000, 0x3605ac0700000000,
+ 0x93d6f0cc00000000, 0x3da4644a00000000, 0x9877388100000000,
+ 0x20473d9c00000000, 0x8594615700000000, 0x2be6f5d100000000,
+ 0x8e35a91a00000000, 0x5b87ffeb00000000, 0xfe54a32000000000,
+ 0x502637a600000000, 0xf5f56b6d00000000, 0x4dc56e7000000000,
+ 0xe81632bb00000000, 0x4664a63d00000000, 0xe3b7faf600000000,
+ 0xad077a0400000000, 0x08d426cf00000000, 0xa6a6b24900000000,
+ 0x0375ee8200000000, 0xbb45eb9f00000000, 0x1e96b75400000000,
+ 0xb0e423d200000000, 0x15377f1900000000, 0xc08529e800000000,
+ 0x6556752300000000, 0xcb24e1a500000000, 0x6ef7bd6e00000000,
+ 0xd6c7b87300000000, 0x7314e4b800000000, 0xdd66703e00000000,
+ 0x78b52cf500000000, 0x6c0a580f00000000, 0xc9d904c400000000,
+ 0x67ab904200000000, 0xc278cc8900000000, 0x7a48c99400000000,
+ 0xdf9b955f00000000, 0x71e901d900000000, 0xd43a5d1200000000,
+ 0x01880be300000000, 0xa45b572800000000, 0x0a29c3ae00000000,
+ 0xaffa9f6500000000, 0x17ca9a7800000000, 0xb219c6b300000000,
+ 0x1c6b523500000000, 0xb9b80efe00000000, 0xf7088e0c00000000,
+ 0x52dbd2c700000000, 0xfca9464100000000, 0x597a1a8a00000000,
+ 0xe14a1f9700000000, 0x4499435c00000000, 0xeaebd7da00000000,
+ 0x4f388b1100000000, 0x9a8adde000000000, 0x3f59812b00000000,
+ 0x912b15ad00000000, 0x34f8496600000000, 0x8cc84c7b00000000,
+ 0x291b10b000000000, 0x8769843600000000, 0x22bad8fd00000000,
+ 0x5a0ff40800000000, 0xffdca8c300000000, 0x51ae3c4500000000,
+ 0xf47d608e00000000, 0x4c4d659300000000, 0xe99e395800000000,
+ 0x47ecadde00000000, 0xe23ff11500000000, 0x378da7e400000000,
+ 0x925efb2f00000000, 0x3c2c6fa900000000, 0x99ff336200000000,
+ 0x21cf367f00000000, 0x841c6ab400000000, 0x2a6efe3200000000,
+ 0x8fbda2f900000000, 0xc10d220b00000000, 0x64de7ec000000000,
+ 0xcaacea4600000000, 0x6f7fb68d00000000, 0xd74fb39000000000,
+ 0x729cef5b00000000, 0xdcee7bdd00000000, 0x793d271600000000,
+ 0xac8f71e700000000, 0x095c2d2c00000000, 0xa72eb9aa00000000,
+ 0x02fde56100000000, 0xbacde07c00000000, 0x1f1ebcb700000000,
+ 0xb16c283100000000, 0x14bf74fa00000000, 0xd814b01e00000000,
+ 0x7dc7ecd500000000, 0xd3b5785300000000, 0x7666249800000000,
+ 0xce56218500000000, 0x6b857d4e00000000, 0xc5f7e9c800000000,
+ 0x6024b50300000000, 0xb596e3f200000000, 0x1045bf3900000000,
+ 0xbe372bbf00000000, 0x1be4777400000000, 0xa3d4726900000000,
+ 0x06072ea200000000, 0xa875ba2400000000, 0x0da6e6ef00000000,
+ 0x4316661d00000000, 0xe6c53ad600000000, 0x48b7ae5000000000,
+ 0xed64f29b00000000, 0x5554f78600000000, 0xf087ab4d00000000,
+ 0x5ef53fcb00000000, 0xfb26630000000000, 0x2e9435f100000000,
+ 0x8b47693a00000000, 0x2535fdbc00000000, 0x80e6a17700000000,
+ 0x38d6a46a00000000, 0x9d05f8a100000000, 0x33776c2700000000,
+ 0x96a430ec00000000, 0xee111c1900000000, 0x4bc240d200000000,
+ 0xe5b0d45400000000, 0x4063889f00000000, 0xf8538d8200000000,
+ 0x5d80d14900000000, 0xf3f245cf00000000, 0x5621190400000000,
+ 0x83934ff500000000, 0x2640133e00000000, 0x883287b800000000,
+ 0x2de1db7300000000, 0x95d1de6e00000000, 0x300282a500000000,
+ 0x9e70162300000000, 0x3ba34ae800000000, 0x7513ca1a00000000,
+ 0xd0c096d100000000, 0x7eb2025700000000, 0xdb615e9c00000000,
+ 0x63515b8100000000, 0xc682074a00000000, 0x68f093cc00000000,
+ 0xcd23cf0700000000, 0x189199f600000000, 0xbd42c53d00000000,
+ 0x133051bb00000000, 0xb6e30d7000000000, 0x0ed3086d00000000,
+ 0xab0054a600000000, 0x0572c02000000000, 0xa0a19ceb00000000,
+ 0xb41ee81100000000, 0x11cdb4da00000000, 0xbfbf205c00000000,
+ 0x1a6c7c9700000000, 0xa25c798a00000000, 0x078f254100000000,
+ 0xa9fdb1c700000000, 0x0c2eed0c00000000, 0xd99cbbfd00000000,
+ 0x7c4fe73600000000, 0xd23d73b000000000, 0x77ee2f7b00000000,
+ 0xcfde2a6600000000, 0x6a0d76ad00000000, 0xc47fe22b00000000,
+ 0x61acbee000000000, 0x2f1c3e1200000000, 0x8acf62d900000000,
+ 0x24bdf65f00000000, 0x816eaa9400000000, 0x395eaf8900000000,
+ 0x9c8df34200000000, 0x32ff67c400000000, 0x972c3b0f00000000,
+ 0x429e6dfe00000000, 0xe74d313500000000, 0x493fa5b300000000,
+ 0xececf97800000000, 0x54dcfc6500000000, 0xf10fa0ae00000000,
+ 0x5f7d342800000000, 0xfaae68e300000000, 0x821b441600000000,
+ 0x27c818dd00000000, 0x89ba8c5b00000000, 0x2c69d09000000000,
+ 0x9459d58d00000000, 0x318a894600000000, 0x9ff81dc000000000,
+ 0x3a2b410b00000000, 0xef9917fa00000000, 0x4a4a4b3100000000,
+ 0xe438dfb700000000, 0x41eb837c00000000, 0xf9db866100000000,
+ 0x5c08daaa00000000, 0xf27a4e2c00000000, 0x57a912e700000000,
+ 0x1919921500000000, 0xbccacede00000000, 0x12b85a5800000000,
+ 0xb76b069300000000, 0x0f5b038e00000000, 0xaa885f4500000000,
+ 0x04facbc300000000, 0xa129970800000000, 0x749bc1f900000000,
+ 0xd1489d3200000000, 0x7f3a09b400000000, 0xdae9557f00000000,
+ 0x62d9506200000000, 0xc70a0ca900000000, 0x6978982f00000000,
+ 0xccabc4e400000000},
+ {0x0000000000000000, 0xb40b77a600000000, 0x29119f9700000000,
+ 0x9d1ae83100000000, 0x13244ff400000000, 0xa72f385200000000,
+ 0x3a35d06300000000, 0x8e3ea7c500000000, 0x674eef3300000000,
+ 0xd345989500000000, 0x4e5f70a400000000, 0xfa54070200000000,
+ 0x746aa0c700000000, 0xc061d76100000000, 0x5d7b3f5000000000,
+ 0xe97048f600000000, 0xce9cde6700000000, 0x7a97a9c100000000,
+ 0xe78d41f000000000, 0x5386365600000000, 0xddb8919300000000,
+ 0x69b3e63500000000, 0xf4a90e0400000000, 0x40a279a200000000,
+ 0xa9d2315400000000, 0x1dd946f200000000, 0x80c3aec300000000,
+ 0x34c8d96500000000, 0xbaf67ea000000000, 0x0efd090600000000,
+ 0x93e7e13700000000, 0x27ec969100000000, 0x9c39bdcf00000000,
+ 0x2832ca6900000000, 0xb528225800000000, 0x012355fe00000000,
+ 0x8f1df23b00000000, 0x3b16859d00000000, 0xa60c6dac00000000,
+ 0x12071a0a00000000, 0xfb7752fc00000000, 0x4f7c255a00000000,
+ 0xd266cd6b00000000, 0x666dbacd00000000, 0xe8531d0800000000,
+ 0x5c586aae00000000, 0xc142829f00000000, 0x7549f53900000000,
+ 0x52a563a800000000, 0xe6ae140e00000000, 0x7bb4fc3f00000000,
+ 0xcfbf8b9900000000, 0x41812c5c00000000, 0xf58a5bfa00000000,
+ 0x6890b3cb00000000, 0xdc9bc46d00000000, 0x35eb8c9b00000000,
+ 0x81e0fb3d00000000, 0x1cfa130c00000000, 0xa8f164aa00000000,
+ 0x26cfc36f00000000, 0x92c4b4c900000000, 0x0fde5cf800000000,
+ 0xbbd52b5e00000000, 0x79750b4400000000, 0xcd7e7ce200000000,
+ 0x506494d300000000, 0xe46fe37500000000, 0x6a5144b000000000,
+ 0xde5a331600000000, 0x4340db2700000000, 0xf74bac8100000000,
+ 0x1e3be47700000000, 0xaa3093d100000000, 0x372a7be000000000,
+ 0x83210c4600000000, 0x0d1fab8300000000, 0xb914dc2500000000,
+ 0x240e341400000000, 0x900543b200000000, 0xb7e9d52300000000,
+ 0x03e2a28500000000, 0x9ef84ab400000000, 0x2af33d1200000000,
+ 0xa4cd9ad700000000, 0x10c6ed7100000000, 0x8ddc054000000000,
+ 0x39d772e600000000, 0xd0a73a1000000000, 0x64ac4db600000000,
+ 0xf9b6a58700000000, 0x4dbdd22100000000, 0xc38375e400000000,
+ 0x7788024200000000, 0xea92ea7300000000, 0x5e999dd500000000,
+ 0xe54cb68b00000000, 0x5147c12d00000000, 0xcc5d291c00000000,
+ 0x78565eba00000000, 0xf668f97f00000000, 0x42638ed900000000,
+ 0xdf7966e800000000, 0x6b72114e00000000, 0x820259b800000000,
+ 0x36092e1e00000000, 0xab13c62f00000000, 0x1f18b18900000000,
+ 0x9126164c00000000, 0x252d61ea00000000, 0xb83789db00000000,
+ 0x0c3cfe7d00000000, 0x2bd068ec00000000, 0x9fdb1f4a00000000,
+ 0x02c1f77b00000000, 0xb6ca80dd00000000, 0x38f4271800000000,
+ 0x8cff50be00000000, 0x11e5b88f00000000, 0xa5eecf2900000000,
+ 0x4c9e87df00000000, 0xf895f07900000000, 0x658f184800000000,
+ 0xd1846fee00000000, 0x5fbac82b00000000, 0xebb1bf8d00000000,
+ 0x76ab57bc00000000, 0xc2a0201a00000000, 0xf2ea168800000000,
+ 0x46e1612e00000000, 0xdbfb891f00000000, 0x6ff0feb900000000,
+ 0xe1ce597c00000000, 0x55c52eda00000000, 0xc8dfc6eb00000000,
+ 0x7cd4b14d00000000, 0x95a4f9bb00000000, 0x21af8e1d00000000,
+ 0xbcb5662c00000000, 0x08be118a00000000, 0x8680b64f00000000,
+ 0x328bc1e900000000, 0xaf9129d800000000, 0x1b9a5e7e00000000,
+ 0x3c76c8ef00000000, 0x887dbf4900000000, 0x1567577800000000,
+ 0xa16c20de00000000, 0x2f52871b00000000, 0x9b59f0bd00000000,
+ 0x0643188c00000000, 0xb2486f2a00000000, 0x5b3827dc00000000,
+ 0xef33507a00000000, 0x7229b84b00000000, 0xc622cfed00000000,
+ 0x481c682800000000, 0xfc171f8e00000000, 0x610df7bf00000000,
+ 0xd506801900000000, 0x6ed3ab4700000000, 0xdad8dce100000000,
+ 0x47c234d000000000, 0xf3c9437600000000, 0x7df7e4b300000000,
+ 0xc9fc931500000000, 0x54e67b2400000000, 0xe0ed0c8200000000,
+ 0x099d447400000000, 0xbd9633d200000000, 0x208cdbe300000000,
+ 0x9487ac4500000000, 0x1ab90b8000000000, 0xaeb27c2600000000,
+ 0x33a8941700000000, 0x87a3e3b100000000, 0xa04f752000000000,
+ 0x1444028600000000, 0x895eeab700000000, 0x3d559d1100000000,
+ 0xb36b3ad400000000, 0x07604d7200000000, 0x9a7aa54300000000,
+ 0x2e71d2e500000000, 0xc7019a1300000000, 0x730aedb500000000,
+ 0xee10058400000000, 0x5a1b722200000000, 0xd425d5e700000000,
+ 0x602ea24100000000, 0xfd344a7000000000, 0x493f3dd600000000,
+ 0x8b9f1dcc00000000, 0x3f946a6a00000000, 0xa28e825b00000000,
+ 0x1685f5fd00000000, 0x98bb523800000000, 0x2cb0259e00000000,
+ 0xb1aacdaf00000000, 0x05a1ba0900000000, 0xecd1f2ff00000000,
+ 0x58da855900000000, 0xc5c06d6800000000, 0x71cb1ace00000000,
+ 0xfff5bd0b00000000, 0x4bfecaad00000000, 0xd6e4229c00000000,
+ 0x62ef553a00000000, 0x4503c3ab00000000, 0xf108b40d00000000,
+ 0x6c125c3c00000000, 0xd8192b9a00000000, 0x56278c5f00000000,
+ 0xe22cfbf900000000, 0x7f3613c800000000, 0xcb3d646e00000000,
+ 0x224d2c9800000000, 0x96465b3e00000000, 0x0b5cb30f00000000,
+ 0xbf57c4a900000000, 0x3169636c00000000, 0x856214ca00000000,
+ 0x1878fcfb00000000, 0xac738b5d00000000, 0x17a6a00300000000,
+ 0xa3add7a500000000, 0x3eb73f9400000000, 0x8abc483200000000,
+ 0x0482eff700000000, 0xb089985100000000, 0x2d93706000000000,
+ 0x999807c600000000, 0x70e84f3000000000, 0xc4e3389600000000,
+ 0x59f9d0a700000000, 0xedf2a70100000000, 0x63cc00c400000000,
+ 0xd7c7776200000000, 0x4add9f5300000000, 0xfed6e8f500000000,
+ 0xd93a7e6400000000, 0x6d3109c200000000, 0xf02be1f300000000,
+ 0x4420965500000000, 0xca1e319000000000, 0x7e15463600000000,
+ 0xe30fae0700000000, 0x5704d9a100000000, 0xbe74915700000000,
+ 0x0a7fe6f100000000, 0x97650ec000000000, 0x236e796600000000,
+ 0xad50dea300000000, 0x195ba90500000000, 0x8441413400000000,
+ 0x304a369200000000},
+ {0x0000000000000000, 0x9e00aacc00000000, 0x7d07254200000000,
+ 0xe3078f8e00000000, 0xfa0e4a8400000000, 0x640ee04800000000,
+ 0x87096fc600000000, 0x1909c50a00000000, 0xb51be5d300000000,
+ 0x2b1b4f1f00000000, 0xc81cc09100000000, 0x561c6a5d00000000,
+ 0x4f15af5700000000, 0xd115059b00000000, 0x32128a1500000000,
+ 0xac1220d900000000, 0x2b31bb7c00000000, 0xb53111b000000000,
+ 0x56369e3e00000000, 0xc83634f200000000, 0xd13ff1f800000000,
+ 0x4f3f5b3400000000, 0xac38d4ba00000000, 0x32387e7600000000,
+ 0x9e2a5eaf00000000, 0x002af46300000000, 0xe32d7bed00000000,
+ 0x7d2dd12100000000, 0x6424142b00000000, 0xfa24bee700000000,
+ 0x1923316900000000, 0x87239ba500000000, 0x566276f900000000,
+ 0xc862dc3500000000, 0x2b6553bb00000000, 0xb565f97700000000,
+ 0xac6c3c7d00000000, 0x326c96b100000000, 0xd16b193f00000000,
+ 0x4f6bb3f300000000, 0xe379932a00000000, 0x7d7939e600000000,
+ 0x9e7eb66800000000, 0x007e1ca400000000, 0x1977d9ae00000000,
+ 0x8777736200000000, 0x6470fcec00000000, 0xfa70562000000000,
+ 0x7d53cd8500000000, 0xe353674900000000, 0x0054e8c700000000,
+ 0x9e54420b00000000, 0x875d870100000000, 0x195d2dcd00000000,
+ 0xfa5aa24300000000, 0x645a088f00000000, 0xc848285600000000,
+ 0x5648829a00000000, 0xb54f0d1400000000, 0x2b4fa7d800000000,
+ 0x324662d200000000, 0xac46c81e00000000, 0x4f41479000000000,
+ 0xd141ed5c00000000, 0xedc29d2900000000, 0x73c237e500000000,
+ 0x90c5b86b00000000, 0x0ec512a700000000, 0x17ccd7ad00000000,
+ 0x89cc7d6100000000, 0x6acbf2ef00000000, 0xf4cb582300000000,
+ 0x58d978fa00000000, 0xc6d9d23600000000, 0x25de5db800000000,
+ 0xbbdef77400000000, 0xa2d7327e00000000, 0x3cd798b200000000,
+ 0xdfd0173c00000000, 0x41d0bdf000000000, 0xc6f3265500000000,
+ 0x58f38c9900000000, 0xbbf4031700000000, 0x25f4a9db00000000,
+ 0x3cfd6cd100000000, 0xa2fdc61d00000000, 0x41fa499300000000,
+ 0xdffae35f00000000, 0x73e8c38600000000, 0xede8694a00000000,
+ 0x0eefe6c400000000, 0x90ef4c0800000000, 0x89e6890200000000,
+ 0x17e623ce00000000, 0xf4e1ac4000000000, 0x6ae1068c00000000,
+ 0xbba0ebd000000000, 0x25a0411c00000000, 0xc6a7ce9200000000,
+ 0x58a7645e00000000, 0x41aea15400000000, 0xdfae0b9800000000,
+ 0x3ca9841600000000, 0xa2a92eda00000000, 0x0ebb0e0300000000,
+ 0x90bba4cf00000000, 0x73bc2b4100000000, 0xedbc818d00000000,
+ 0xf4b5448700000000, 0x6ab5ee4b00000000, 0x89b261c500000000,
+ 0x17b2cb0900000000, 0x909150ac00000000, 0x0e91fa6000000000,
+ 0xed9675ee00000000, 0x7396df2200000000, 0x6a9f1a2800000000,
+ 0xf49fb0e400000000, 0x17983f6a00000000, 0x899895a600000000,
+ 0x258ab57f00000000, 0xbb8a1fb300000000, 0x588d903d00000000,
+ 0xc68d3af100000000, 0xdf84fffb00000000, 0x4184553700000000,
+ 0xa283dab900000000, 0x3c83707500000000, 0xda853b5300000000,
+ 0x4485919f00000000, 0xa7821e1100000000, 0x3982b4dd00000000,
+ 0x208b71d700000000, 0xbe8bdb1b00000000, 0x5d8c549500000000,
+ 0xc38cfe5900000000, 0x6f9ede8000000000, 0xf19e744c00000000,
+ 0x1299fbc200000000, 0x8c99510e00000000, 0x9590940400000000,
+ 0x0b903ec800000000, 0xe897b14600000000, 0x76971b8a00000000,
+ 0xf1b4802f00000000, 0x6fb42ae300000000, 0x8cb3a56d00000000,
+ 0x12b30fa100000000, 0x0bbacaab00000000, 0x95ba606700000000,
+ 0x76bdefe900000000, 0xe8bd452500000000, 0x44af65fc00000000,
+ 0xdaafcf3000000000, 0x39a840be00000000, 0xa7a8ea7200000000,
+ 0xbea12f7800000000, 0x20a185b400000000, 0xc3a60a3a00000000,
+ 0x5da6a0f600000000, 0x8ce74daa00000000, 0x12e7e76600000000,
+ 0xf1e068e800000000, 0x6fe0c22400000000, 0x76e9072e00000000,
+ 0xe8e9ade200000000, 0x0bee226c00000000, 0x95ee88a000000000,
+ 0x39fca87900000000, 0xa7fc02b500000000, 0x44fb8d3b00000000,
+ 0xdafb27f700000000, 0xc3f2e2fd00000000, 0x5df2483100000000,
+ 0xbef5c7bf00000000, 0x20f56d7300000000, 0xa7d6f6d600000000,
+ 0x39d65c1a00000000, 0xdad1d39400000000, 0x44d1795800000000,
+ 0x5dd8bc5200000000, 0xc3d8169e00000000, 0x20df991000000000,
+ 0xbedf33dc00000000, 0x12cd130500000000, 0x8ccdb9c900000000,
+ 0x6fca364700000000, 0xf1ca9c8b00000000, 0xe8c3598100000000,
+ 0x76c3f34d00000000, 0x95c47cc300000000, 0x0bc4d60f00000000,
+ 0x3747a67a00000000, 0xa9470cb600000000, 0x4a40833800000000,
+ 0xd44029f400000000, 0xcd49ecfe00000000, 0x5349463200000000,
+ 0xb04ec9bc00000000, 0x2e4e637000000000, 0x825c43a900000000,
+ 0x1c5ce96500000000, 0xff5b66eb00000000, 0x615bcc2700000000,
+ 0x7852092d00000000, 0xe652a3e100000000, 0x05552c6f00000000,
+ 0x9b5586a300000000, 0x1c761d0600000000, 0x8276b7ca00000000,
+ 0x6171384400000000, 0xff71928800000000, 0xe678578200000000,
+ 0x7878fd4e00000000, 0x9b7f72c000000000, 0x057fd80c00000000,
+ 0xa96df8d500000000, 0x376d521900000000, 0xd46add9700000000,
+ 0x4a6a775b00000000, 0x5363b25100000000, 0xcd63189d00000000,
+ 0x2e64971300000000, 0xb0643ddf00000000, 0x6125d08300000000,
+ 0xff257a4f00000000, 0x1c22f5c100000000, 0x82225f0d00000000,
+ 0x9b2b9a0700000000, 0x052b30cb00000000, 0xe62cbf4500000000,
+ 0x782c158900000000, 0xd43e355000000000, 0x4a3e9f9c00000000,
+ 0xa939101200000000, 0x3739bade00000000, 0x2e307fd400000000,
+ 0xb030d51800000000, 0x53375a9600000000, 0xcd37f05a00000000,
+ 0x4a146bff00000000, 0xd414c13300000000, 0x37134ebd00000000,
+ 0xa913e47100000000, 0xb01a217b00000000, 0x2e1a8bb700000000,
+ 0xcd1d043900000000, 0x531daef500000000, 0xff0f8e2c00000000,
+ 0x610f24e000000000, 0x8208ab6e00000000, 0x1c0801a200000000,
+ 0x0501c4a800000000, 0x9b016e6400000000, 0x7806e1ea00000000,
+ 0xe6064b2600000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, 0x8f629757,
+ 0x37def032, 0x256b5fdc, 0x9dd738b9, 0xc5b428ef, 0x7d084f8a,
+ 0x6fbde064, 0xd7018701, 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733,
+ 0x58631056, 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
+ 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, 0x95ad7f70,
+ 0x2d111815, 0x3fa4b7fb, 0x8718d09e, 0x1acfe827, 0xa2738f42,
+ 0xb0c620ac, 0x087a47c9, 0xa032af3e, 0x188ec85b, 0x0a3b67b5,
+ 0xb28700d0, 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
+ 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, 0xeae41086,
+ 0x525877e3, 0x40edd80d, 0xf851bf68, 0xf02bf8a1, 0x48979fc4,
+ 0x5a22302a, 0xe29e574f, 0x7f496ff6, 0xc7f50893, 0xd540a77d,
+ 0x6dfcc018, 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
+ 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, 0x9b14583d,
+ 0x23a83f58, 0x311d90b6, 0x89a1f7d3, 0x1476cf6a, 0xaccaa80f,
+ 0xbe7f07e1, 0x06c36084, 0x5ea070d2, 0xe61c17b7, 0xf4a9b859,
+ 0x4c15df3c, 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
+ 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, 0x446f98f5,
+ 0xfcd3ff90, 0xee66507e, 0x56da371b, 0x0eb9274d, 0xb6054028,
+ 0xa4b0efc6, 0x1c0c88a3, 0x81dbb01a, 0x3967d77f, 0x2bd27891,
+ 0x936e1ff4, 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
+ 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, 0xfe92dfec,
+ 0x462eb889, 0x549b1767, 0xec277002, 0x71f048bb, 0xc94c2fde,
+ 0xdbf98030, 0x6345e755, 0x6b3fa09c, 0xd383c7f9, 0xc1366817,
+ 0x798a0f72, 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
+ 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, 0x21e91f24,
+ 0x99557841, 0x8be0d7af, 0x335cb0ca, 0xed59b63b, 0x55e5d15e,
+ 0x47507eb0, 0xffec19d5, 0x623b216c, 0xda874609, 0xc832e9e7,
+ 0x708e8e82, 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
+ 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, 0xbd40e1a4,
+ 0x05fc86c1, 0x1749292f, 0xaff54e4a, 0x322276f3, 0x8a9e1196,
+ 0x982bbe78, 0x2097d91d, 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0,
+ 0x6a4166a5, 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
+ 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, 0xc2098e52,
+ 0x7ab5e937, 0x680046d9, 0xd0bc21bc, 0x88df31ea, 0x3063568f,
+ 0x22d6f961, 0x9a6a9e04, 0x07bda6bd, 0xbf01c1d8, 0xadb46e36,
+ 0x15080953, 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
+ 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, 0xd8c66675,
+ 0x607a0110, 0x72cfaefe, 0xca73c99b, 0x57a4f122, 0xef189647,
+ 0xfdad39a9, 0x45115ecc, 0x764dee06, 0xcef18963, 0xdc44268d,
+ 0x64f841e8, 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
+ 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, 0x3c9b51be,
+ 0x842736db, 0x96929935, 0x2e2efe50, 0x2654b999, 0x9ee8defc,
+ 0x8c5d7112, 0x34e11677, 0xa9362ece, 0x118a49ab, 0x033fe645,
+ 0xbb838120, 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
+ 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, 0xd67f4138,
+ 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, 0x591dd66f, 0xe1a1b10a,
+ 0xf3141ee4, 0x4ba87981, 0x13cb69d7, 0xab770eb2, 0xb9c2a15c,
+ 0x017ec639, 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
+ 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, 0x090481f0,
+ 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, 0x43d23e48, 0xfb6e592d,
+ 0xe9dbf6c3, 0x516791a6, 0xccb0a91f, 0x740cce7a, 0x66b96194,
+ 0xde0506f1},
+ {0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, 0x0709a8dc,
+ 0x06cbc2eb, 0x048d7cb2, 0x054f1685, 0x0e1351b8, 0x0fd13b8f,
+ 0x0d9785d6, 0x0c55efe1, 0x091af964, 0x08d89353, 0x0a9e2d0a,
+ 0x0b5c473d, 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
+ 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, 0x1235f2c8,
+ 0x13f798ff, 0x11b126a6, 0x10734c91, 0x153c5a14, 0x14fe3023,
+ 0x16b88e7a, 0x177ae44d, 0x384d46e0, 0x398f2cd7, 0x3bc9928e,
+ 0x3a0bf8b9, 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
+ 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, 0x3157bf84,
+ 0x3095d5b3, 0x32d36bea, 0x331101dd, 0x246be590, 0x25a98fa7,
+ 0x27ef31fe, 0x262d5bc9, 0x23624d4c, 0x22a0277b, 0x20e69922,
+ 0x2124f315, 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
+ 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, 0x709a8dc0,
+ 0x7158e7f7, 0x731e59ae, 0x72dc3399, 0x7793251c, 0x76514f2b,
+ 0x7417f172, 0x75d59b45, 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816,
+ 0x7ccf6221, 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
+ 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, 0x6bb5866c,
+ 0x6a77ec5b, 0x68315202, 0x69f33835, 0x62af7f08, 0x636d153f,
+ 0x612bab66, 0x60e9c151, 0x65a6d7d4, 0x6464bde3, 0x662203ba,
+ 0x67e0698d, 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
+ 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, 0x46c49a98,
+ 0x4706f0af, 0x45404ef6, 0x448224c1, 0x41cd3244, 0x400f5873,
+ 0x4249e62a, 0x438b8c1d, 0x54f16850, 0x55330267, 0x5775bc3e,
+ 0x56b7d609, 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
+ 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, 0x5deb9134,
+ 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, 0xe1351b80, 0xe0f771b7,
+ 0xe2b1cfee, 0xe373a5d9, 0xe63cb35c, 0xe7fed96b, 0xe5b86732,
+ 0xe47a0d05, 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
+ 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, 0xfd13b8f0,
+ 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, 0xfa1a102c, 0xfbd87a1b,
+ 0xf99ec442, 0xf85cae75, 0xf300e948, 0xf2c2837f, 0xf0843d26,
+ 0xf1465711, 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
+ 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, 0xde71f5bc,
+ 0xdfb39f8b, 0xddf521d2, 0xdc374be5, 0xd76b0cd8, 0xd6a966ef,
+ 0xd4efd8b6, 0xd52db281, 0xd062a404, 0xd1a0ce33, 0xd3e6706a,
+ 0xd2241a5d, 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
+ 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, 0xcb4dafa8,
+ 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, 0xcc440774, 0xcd866d43,
+ 0xcfc0d31a, 0xce02b92d, 0x91af9640, 0x906dfc77, 0x922b422e,
+ 0x93e92819, 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
+ 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, 0x98b56f24,
+ 0x99770513, 0x9b31bb4a, 0x9af3d17d, 0x8d893530, 0x8c4b5f07,
+ 0x8e0de15e, 0x8fcf8b69, 0x8a809dec, 0x8b42f7db, 0x89044982,
+ 0x88c623b5, 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
+ 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, 0xa9e2d0a0,
+ 0xa820ba97, 0xaa6604ce, 0xaba46ef9, 0xaeeb787c, 0xaf29124b,
+ 0xad6fac12, 0xacadc625, 0xa7f18118, 0xa633eb2f, 0xa4755576,
+ 0xa5b73f41, 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
+ 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, 0xb2cddb0c,
+ 0xb30fb13b, 0xb1490f62, 0xb08b6555, 0xbbd72268, 0xba15485f,
+ 0xb853f606, 0xb9919c31, 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda,
+ 0xbe9834ed},
+ {0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, 0x646cc504,
+ 0x7d77f445, 0x565aa786, 0x4f4196c7, 0xc8d98a08, 0xd1c2bb49,
+ 0xfaefe88a, 0xe3f4d9cb, 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e,
+ 0x87981ccf, 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
+ 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, 0x821b9859,
+ 0x9b00a918, 0xb02dfadb, 0xa936cb9a, 0xe6775d5d, 0xff6c6c1c,
+ 0xd4413fdf, 0xcd5a0e9e, 0x958424a2, 0x8c9f15e3, 0xa7b24620,
+ 0xbea97761, 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
+ 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, 0x39316bae,
+ 0x202a5aef, 0x0b07092c, 0x121c386d, 0xdf4636f3, 0xc65d07b2,
+ 0xed705471, 0xf46b6530, 0xbb2af3f7, 0xa231c2b6, 0x891c9175,
+ 0x9007a034, 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
+ 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, 0xf0794f05,
+ 0xe9627e44, 0xc24f2d87, 0xdb541cc6, 0x94158a01, 0x8d0ebb40,
+ 0xa623e883, 0xbf38d9c2, 0x38a0c50d, 0x21bbf44c, 0x0a96a78f,
+ 0x138d96ce, 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
+ 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, 0xded79850,
+ 0xc7cca911, 0xece1fad2, 0xf5facb93, 0x7262d75c, 0x6b79e61d,
+ 0x4054b5de, 0x594f849f, 0x160e1258, 0x0f152319, 0x243870da,
+ 0x3d23419b, 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
+ 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, 0xad24e1af,
+ 0xb43fd0ee, 0x9f12832d, 0x8609b26c, 0xc94824ab, 0xd05315ea,
+ 0xfb7e4629, 0xe2657768, 0x2f3f79f6, 0x362448b7, 0x1d091b74,
+ 0x04122a35, 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
+ 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, 0x838a36fa,
+ 0x9a9107bb, 0xb1bc5478, 0xa8a76539, 0x3b83984b, 0x2298a90a,
+ 0x09b5fac9, 0x10aecb88, 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd,
+ 0x74c20e8c, 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
+ 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, 0x71418a1a,
+ 0x685abb5b, 0x4377e898, 0x5a6cd9d9, 0x152d4f1e, 0x0c367e5f,
+ 0x271b2d9c, 0x3e001cdd, 0xb9980012, 0xa0833153, 0x8bae6290,
+ 0x92b553d1, 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
+ 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, 0xca6b79ed,
+ 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, 0x66de36e1, 0x7fc507a0,
+ 0x54e85463, 0x4df36522, 0x02b2f3e5, 0x1ba9c2a4, 0x30849167,
+ 0x299fa026, 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
+ 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, 0x2c1c24b0,
+ 0x350715f1, 0x1e2a4632, 0x07317773, 0x4870e1b4, 0x516bd0f5,
+ 0x7a468336, 0x635db277, 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc,
+ 0xe0d7848d, 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
+ 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, 0x674f9842,
+ 0x7e54a903, 0x5579fac0, 0x4c62cb81, 0x8138c51f, 0x9823f45e,
+ 0xb30ea79d, 0xaa1596dc, 0xe554001b, 0xfc4f315a, 0xd7626299,
+ 0xce7953d8, 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
+ 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, 0x5e7ef3ec,
+ 0x4765c2ad, 0x6c48916e, 0x7553a02f, 0x3a1236e8, 0x230907a9,
+ 0x0824546a, 0x113f652b, 0x96a779e4, 0x8fbc48a5, 0xa4911b66,
+ 0xbd8a2a27, 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
+ 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, 0x70d024b9,
+ 0x69cb15f8, 0x42e6463b, 0x5bfd777a, 0xdc656bb5, 0xc57e5af4,
+ 0xee530937, 0xf7483876, 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33,
+ 0x9324fd72},
+ {0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x96300777, 0x2c610eee, 0xba510999, 0x19c46d07,
+ 0x8ff46a70, 0x35a563e9, 0xa395649e, 0x3288db0e, 0xa4b8dc79,
+ 0x1ee9d5e0, 0x88d9d297, 0x2b4cb609, 0xbd7cb17e, 0x072db8e7,
+ 0x911dbf90, 0x6410b71d, 0xf220b06a, 0x4871b9f3, 0xde41be84,
+ 0x7dd4da1a, 0xebe4dd6d, 0x51b5d4f4, 0xc785d383, 0x56986c13,
+ 0xc0a86b64, 0x7af962fd, 0xecc9658a, 0x4f5c0114, 0xd96c0663,
+ 0x633d0ffa, 0xf50d088d, 0xc8206e3b, 0x5e10694c, 0xe44160d5,
+ 0x727167a2, 0xd1e4033c, 0x47d4044b, 0xfd850dd2, 0x6bb50aa5,
+ 0xfaa8b535, 0x6c98b242, 0xd6c9bbdb, 0x40f9bcac, 0xe36cd832,
+ 0x755cdf45, 0xcf0dd6dc, 0x593dd1ab, 0xac30d926, 0x3a00de51,
+ 0x8051d7c8, 0x1661d0bf, 0xb5f4b421, 0x23c4b356, 0x9995bacf,
+ 0x0fa5bdb8, 0x9eb80228, 0x0888055f, 0xb2d90cc6, 0x24e90bb1,
+ 0x877c6f2f, 0x114c6858, 0xab1d61c1, 0x3d2d66b6, 0x9041dc76,
+ 0x0671db01, 0xbc20d298, 0x2a10d5ef, 0x8985b171, 0x1fb5b606,
+ 0xa5e4bf9f, 0x33d4b8e8, 0xa2c90778, 0x34f9000f, 0x8ea80996,
+ 0x18980ee1, 0xbb0d6a7f, 0x2d3d6d08, 0x976c6491, 0x015c63e6,
+ 0xf4516b6b, 0x62616c1c, 0xd8306585, 0x4e0062f2, 0xed95066c,
+ 0x7ba5011b, 0xc1f40882, 0x57c40ff5, 0xc6d9b065, 0x50e9b712,
+ 0xeab8be8b, 0x7c88b9fc, 0xdf1ddd62, 0x492dda15, 0xf37cd38c,
+ 0x654cd4fb, 0x5861b24d, 0xce51b53a, 0x7400bca3, 0xe230bbd4,
+ 0x41a5df4a, 0xd795d83d, 0x6dc4d1a4, 0xfbf4d6d3, 0x6ae96943,
+ 0xfcd96e34, 0x468867ad, 0xd0b860da, 0x732d0444, 0xe51d0333,
+ 0x5f4c0aaa, 0xc97c0ddd, 0x3c710550, 0xaa410227, 0x10100bbe,
+ 0x86200cc9, 0x25b56857, 0xb3856f20, 0x09d466b9, 0x9fe461ce,
+ 0x0ef9de5e, 0x98c9d929, 0x2298d0b0, 0xb4a8d7c7, 0x173db359,
+ 0x810db42e, 0x3b5cbdb7, 0xad6cbac0, 0x2083b8ed, 0xb6b3bf9a,
+ 0x0ce2b603, 0x9ad2b174, 0x3947d5ea, 0xaf77d29d, 0x1526db04,
+ 0x8316dc73, 0x120b63e3, 0x843b6494, 0x3e6a6d0d, 0xa85a6a7a,
+ 0x0bcf0ee4, 0x9dff0993, 0x27ae000a, 0xb19e077d, 0x44930ff0,
+ 0xd2a30887, 0x68f2011e, 0xfec20669, 0x5d5762f7, 0xcb676580,
+ 0x71366c19, 0xe7066b6e, 0x761bd4fe, 0xe02bd389, 0x5a7ada10,
+ 0xcc4add67, 0x6fdfb9f9, 0xf9efbe8e, 0x43beb717, 0xd58eb060,
+ 0xe8a3d6d6, 0x7e93d1a1, 0xc4c2d838, 0x52f2df4f, 0xf167bbd1,
+ 0x6757bca6, 0xdd06b53f, 0x4b36b248, 0xda2b0dd8, 0x4c1b0aaf,
+ 0xf64a0336, 0x607a0441, 0xc3ef60df, 0x55df67a8, 0xef8e6e31,
+ 0x79be6946, 0x8cb361cb, 0x1a8366bc, 0xa0d26f25, 0x36e26852,
+ 0x95770ccc, 0x03470bbb, 0xb9160222, 0x2f260555, 0xbe3bbac5,
+ 0x280bbdb2, 0x925ab42b, 0x046ab35c, 0xa7ffd7c2, 0x31cfd0b5,
+ 0x8b9ed92c, 0x1daede5b, 0xb0c2649b, 0x26f263ec, 0x9ca36a75,
+ 0x0a936d02, 0xa906099c, 0x3f360eeb, 0x85670772, 0x13570005,
+ 0x824abf95, 0x147ab8e2, 0xae2bb17b, 0x381bb60c, 0x9b8ed292,
+ 0x0dbed5e5, 0xb7efdc7c, 0x21dfdb0b, 0xd4d2d386, 0x42e2d4f1,
+ 0xf8b3dd68, 0x6e83da1f, 0xcd16be81, 0x5b26b9f6, 0xe177b06f,
+ 0x7747b718, 0xe65a0888, 0x706a0fff, 0xca3b0666, 0x5c0b0111,
+ 0xff9e658f, 0x69ae62f8, 0xd3ff6b61, 0x45cf6c16, 0x78e20aa0,
+ 0xeed20dd7, 0x5483044e, 0xc2b30339, 0x612667a7, 0xf71660d0,
+ 0x4d476949, 0xdb776e3e, 0x4a6ad1ae, 0xdc5ad6d9, 0x660bdf40,
+ 0xf03bd837, 0x53aebca9, 0xc59ebbde, 0x7fcfb247, 0xe9ffb530,
+ 0x1cf2bdbd, 0x8ac2baca, 0x3093b353, 0xa6a3b424, 0x0536d0ba,
+ 0x9306d7cd, 0x2957de54, 0xbf67d923, 0x2e7a66b3, 0xb84a61c4,
+ 0x021b685d, 0x942b6f2a, 0x37be0bb4, 0xa18e0cc3, 0x1bdf055a,
+ 0x8def022d},
+ {0x00000000, 0x41311b19, 0x82623632, 0xc3532d2b, 0x04c56c64,
+ 0x45f4777d, 0x86a75a56, 0xc796414f, 0x088ad9c8, 0x49bbc2d1,
+ 0x8ae8effa, 0xcbd9f4e3, 0x0c4fb5ac, 0x4d7eaeb5, 0x8e2d839e,
+ 0xcf1c9887, 0x5112c24a, 0x1023d953, 0xd370f478, 0x9241ef61,
+ 0x55d7ae2e, 0x14e6b537, 0xd7b5981c, 0x96848305, 0x59981b82,
+ 0x18a9009b, 0xdbfa2db0, 0x9acb36a9, 0x5d5d77e6, 0x1c6c6cff,
+ 0xdf3f41d4, 0x9e0e5acd, 0xa2248495, 0xe3159f8c, 0x2046b2a7,
+ 0x6177a9be, 0xa6e1e8f1, 0xe7d0f3e8, 0x2483dec3, 0x65b2c5da,
+ 0xaaae5d5d, 0xeb9f4644, 0x28cc6b6f, 0x69fd7076, 0xae6b3139,
+ 0xef5a2a20, 0x2c09070b, 0x6d381c12, 0xf33646df, 0xb2075dc6,
+ 0x715470ed, 0x30656bf4, 0xf7f32abb, 0xb6c231a2, 0x75911c89,
+ 0x34a00790, 0xfbbc9f17, 0xba8d840e, 0x79dea925, 0x38efb23c,
+ 0xff79f373, 0xbe48e86a, 0x7d1bc541, 0x3c2ade58, 0x054f79f0,
+ 0x447e62e9, 0x872d4fc2, 0xc61c54db, 0x018a1594, 0x40bb0e8d,
+ 0x83e823a6, 0xc2d938bf, 0x0dc5a038, 0x4cf4bb21, 0x8fa7960a,
+ 0xce968d13, 0x0900cc5c, 0x4831d745, 0x8b62fa6e, 0xca53e177,
+ 0x545dbbba, 0x156ca0a3, 0xd63f8d88, 0x970e9691, 0x5098d7de,
+ 0x11a9ccc7, 0xd2fae1ec, 0x93cbfaf5, 0x5cd76272, 0x1de6796b,
+ 0xdeb55440, 0x9f844f59, 0x58120e16, 0x1923150f, 0xda703824,
+ 0x9b41233d, 0xa76bfd65, 0xe65ae67c, 0x2509cb57, 0x6438d04e,
+ 0xa3ae9101, 0xe29f8a18, 0x21cca733, 0x60fdbc2a, 0xafe124ad,
+ 0xeed03fb4, 0x2d83129f, 0x6cb20986, 0xab2448c9, 0xea1553d0,
+ 0x29467efb, 0x687765e2, 0xf6793f2f, 0xb7482436, 0x741b091d,
+ 0x352a1204, 0xf2bc534b, 0xb38d4852, 0x70de6579, 0x31ef7e60,
+ 0xfef3e6e7, 0xbfc2fdfe, 0x7c91d0d5, 0x3da0cbcc, 0xfa368a83,
+ 0xbb07919a, 0x7854bcb1, 0x3965a7a8, 0x4b98833b, 0x0aa99822,
+ 0xc9fab509, 0x88cbae10, 0x4f5def5f, 0x0e6cf446, 0xcd3fd96d,
+ 0x8c0ec274, 0x43125af3, 0x022341ea, 0xc1706cc1, 0x804177d8,
+ 0x47d73697, 0x06e62d8e, 0xc5b500a5, 0x84841bbc, 0x1a8a4171,
+ 0x5bbb5a68, 0x98e87743, 0xd9d96c5a, 0x1e4f2d15, 0x5f7e360c,
+ 0x9c2d1b27, 0xdd1c003e, 0x120098b9, 0x533183a0, 0x9062ae8b,
+ 0xd153b592, 0x16c5f4dd, 0x57f4efc4, 0x94a7c2ef, 0xd596d9f6,
+ 0xe9bc07ae, 0xa88d1cb7, 0x6bde319c, 0x2aef2a85, 0xed796bca,
+ 0xac4870d3, 0x6f1b5df8, 0x2e2a46e1, 0xe136de66, 0xa007c57f,
+ 0x6354e854, 0x2265f34d, 0xe5f3b202, 0xa4c2a91b, 0x67918430,
+ 0x26a09f29, 0xb8aec5e4, 0xf99fdefd, 0x3accf3d6, 0x7bfde8cf,
+ 0xbc6ba980, 0xfd5ab299, 0x3e099fb2, 0x7f3884ab, 0xb0241c2c,
+ 0xf1150735, 0x32462a1e, 0x73773107, 0xb4e17048, 0xf5d06b51,
+ 0x3683467a, 0x77b25d63, 0x4ed7facb, 0x0fe6e1d2, 0xccb5ccf9,
+ 0x8d84d7e0, 0x4a1296af, 0x0b238db6, 0xc870a09d, 0x8941bb84,
+ 0x465d2303, 0x076c381a, 0xc43f1531, 0x850e0e28, 0x42984f67,
+ 0x03a9547e, 0xc0fa7955, 0x81cb624c, 0x1fc53881, 0x5ef42398,
+ 0x9da70eb3, 0xdc9615aa, 0x1b0054e5, 0x5a314ffc, 0x996262d7,
+ 0xd85379ce, 0x174fe149, 0x567efa50, 0x952dd77b, 0xd41ccc62,
+ 0x138a8d2d, 0x52bb9634, 0x91e8bb1f, 0xd0d9a006, 0xecf37e5e,
+ 0xadc26547, 0x6e91486c, 0x2fa05375, 0xe836123a, 0xa9070923,
+ 0x6a542408, 0x2b653f11, 0xe479a796, 0xa548bc8f, 0x661b91a4,
+ 0x272a8abd, 0xe0bccbf2, 0xa18dd0eb, 0x62defdc0, 0x23efe6d9,
+ 0xbde1bc14, 0xfcd0a70d, 0x3f838a26, 0x7eb2913f, 0xb924d070,
+ 0xf815cb69, 0x3b46e642, 0x7a77fd5b, 0xb56b65dc, 0xf45a7ec5,
+ 0x370953ee, 0x763848f7, 0xb1ae09b8, 0xf09f12a1, 0x33cc3f8a,
+ 0x72fd2493},
+ {0x00000000, 0x376ac201, 0x6ed48403, 0x59be4602, 0xdca80907,
+ 0xebc2cb06, 0xb27c8d04, 0x85164f05, 0xb851130e, 0x8f3bd10f,
+ 0xd685970d, 0xe1ef550c, 0x64f91a09, 0x5393d808, 0x0a2d9e0a,
+ 0x3d475c0b, 0x70a3261c, 0x47c9e41d, 0x1e77a21f, 0x291d601e,
+ 0xac0b2f1b, 0x9b61ed1a, 0xc2dfab18, 0xf5b56919, 0xc8f23512,
+ 0xff98f713, 0xa626b111, 0x914c7310, 0x145a3c15, 0x2330fe14,
+ 0x7a8eb816, 0x4de47a17, 0xe0464d38, 0xd72c8f39, 0x8e92c93b,
+ 0xb9f80b3a, 0x3cee443f, 0x0b84863e, 0x523ac03c, 0x6550023d,
+ 0x58175e36, 0x6f7d9c37, 0x36c3da35, 0x01a91834, 0x84bf5731,
+ 0xb3d59530, 0xea6bd332, 0xdd011133, 0x90e56b24, 0xa78fa925,
+ 0xfe31ef27, 0xc95b2d26, 0x4c4d6223, 0x7b27a022, 0x2299e620,
+ 0x15f32421, 0x28b4782a, 0x1fdeba2b, 0x4660fc29, 0x710a3e28,
+ 0xf41c712d, 0xc376b32c, 0x9ac8f52e, 0xada2372f, 0xc08d9a70,
+ 0xf7e75871, 0xae591e73, 0x9933dc72, 0x1c259377, 0x2b4f5176,
+ 0x72f11774, 0x459bd575, 0x78dc897e, 0x4fb64b7f, 0x16080d7d,
+ 0x2162cf7c, 0xa4748079, 0x931e4278, 0xcaa0047a, 0xfdcac67b,
+ 0xb02ebc6c, 0x87447e6d, 0xdefa386f, 0xe990fa6e, 0x6c86b56b,
+ 0x5bec776a, 0x02523168, 0x3538f369, 0x087faf62, 0x3f156d63,
+ 0x66ab2b61, 0x51c1e960, 0xd4d7a665, 0xe3bd6464, 0xba032266,
+ 0x8d69e067, 0x20cbd748, 0x17a11549, 0x4e1f534b, 0x7975914a,
+ 0xfc63de4f, 0xcb091c4e, 0x92b75a4c, 0xa5dd984d, 0x989ac446,
+ 0xaff00647, 0xf64e4045, 0xc1248244, 0x4432cd41, 0x73580f40,
+ 0x2ae64942, 0x1d8c8b43, 0x5068f154, 0x67023355, 0x3ebc7557,
+ 0x09d6b756, 0x8cc0f853, 0xbbaa3a52, 0xe2147c50, 0xd57ebe51,
+ 0xe839e25a, 0xdf53205b, 0x86ed6659, 0xb187a458, 0x3491eb5d,
+ 0x03fb295c, 0x5a456f5e, 0x6d2fad5f, 0x801b35e1, 0xb771f7e0,
+ 0xeecfb1e2, 0xd9a573e3, 0x5cb33ce6, 0x6bd9fee7, 0x3267b8e5,
+ 0x050d7ae4, 0x384a26ef, 0x0f20e4ee, 0x569ea2ec, 0x61f460ed,
+ 0xe4e22fe8, 0xd388ede9, 0x8a36abeb, 0xbd5c69ea, 0xf0b813fd,
+ 0xc7d2d1fc, 0x9e6c97fe, 0xa90655ff, 0x2c101afa, 0x1b7ad8fb,
+ 0x42c49ef9, 0x75ae5cf8, 0x48e900f3, 0x7f83c2f2, 0x263d84f0,
+ 0x115746f1, 0x944109f4, 0xa32bcbf5, 0xfa958df7, 0xcdff4ff6,
+ 0x605d78d9, 0x5737bad8, 0x0e89fcda, 0x39e33edb, 0xbcf571de,
+ 0x8b9fb3df, 0xd221f5dd, 0xe54b37dc, 0xd80c6bd7, 0xef66a9d6,
+ 0xb6d8efd4, 0x81b22dd5, 0x04a462d0, 0x33cea0d1, 0x6a70e6d3,
+ 0x5d1a24d2, 0x10fe5ec5, 0x27949cc4, 0x7e2adac6, 0x494018c7,
+ 0xcc5657c2, 0xfb3c95c3, 0xa282d3c1, 0x95e811c0, 0xa8af4dcb,
+ 0x9fc58fca, 0xc67bc9c8, 0xf1110bc9, 0x740744cc, 0x436d86cd,
+ 0x1ad3c0cf, 0x2db902ce, 0x4096af91, 0x77fc6d90, 0x2e422b92,
+ 0x1928e993, 0x9c3ea696, 0xab546497, 0xf2ea2295, 0xc580e094,
+ 0xf8c7bc9f, 0xcfad7e9e, 0x9613389c, 0xa179fa9d, 0x246fb598,
+ 0x13057799, 0x4abb319b, 0x7dd1f39a, 0x3035898d, 0x075f4b8c,
+ 0x5ee10d8e, 0x698bcf8f, 0xec9d808a, 0xdbf7428b, 0x82490489,
+ 0xb523c688, 0x88649a83, 0xbf0e5882, 0xe6b01e80, 0xd1dadc81,
+ 0x54cc9384, 0x63a65185, 0x3a181787, 0x0d72d586, 0xa0d0e2a9,
+ 0x97ba20a8, 0xce0466aa, 0xf96ea4ab, 0x7c78ebae, 0x4b1229af,
+ 0x12ac6fad, 0x25c6adac, 0x1881f1a7, 0x2feb33a6, 0x765575a4,
+ 0x413fb7a5, 0xc429f8a0, 0xf3433aa1, 0xaafd7ca3, 0x9d97bea2,
+ 0xd073c4b5, 0xe71906b4, 0xbea740b6, 0x89cd82b7, 0x0cdbcdb2,
+ 0x3bb10fb3, 0x620f49b1, 0x55658bb0, 0x6822d7bb, 0x5f4815ba,
+ 0x06f653b8, 0x319c91b9, 0xb48adebc, 0x83e01cbd, 0xda5e5abf,
+ 0xed3498be},
+ {0x00000000, 0x6567bcb8, 0x8bc809aa, 0xeeafb512, 0x5797628f,
+ 0x32f0de37, 0xdc5f6b25, 0xb938d79d, 0xef28b4c5, 0x8a4f087d,
+ 0x64e0bd6f, 0x018701d7, 0xb8bfd64a, 0xddd86af2, 0x3377dfe0,
+ 0x56106358, 0x9f571950, 0xfa30a5e8, 0x149f10fa, 0x71f8ac42,
+ 0xc8c07bdf, 0xada7c767, 0x43087275, 0x266fcecd, 0x707fad95,
+ 0x1518112d, 0xfbb7a43f, 0x9ed01887, 0x27e8cf1a, 0x428f73a2,
+ 0xac20c6b0, 0xc9477a08, 0x3eaf32a0, 0x5bc88e18, 0xb5673b0a,
+ 0xd00087b2, 0x6938502f, 0x0c5fec97, 0xe2f05985, 0x8797e53d,
+ 0xd1878665, 0xb4e03add, 0x5a4f8fcf, 0x3f283377, 0x8610e4ea,
+ 0xe3775852, 0x0dd8ed40, 0x68bf51f8, 0xa1f82bf0, 0xc49f9748,
+ 0x2a30225a, 0x4f579ee2, 0xf66f497f, 0x9308f5c7, 0x7da740d5,
+ 0x18c0fc6d, 0x4ed09f35, 0x2bb7238d, 0xc518969f, 0xa07f2a27,
+ 0x1947fdba, 0x7c204102, 0x928ff410, 0xf7e848a8, 0x3d58149b,
+ 0x583fa823, 0xb6901d31, 0xd3f7a189, 0x6acf7614, 0x0fa8caac,
+ 0xe1077fbe, 0x8460c306, 0xd270a05e, 0xb7171ce6, 0x59b8a9f4,
+ 0x3cdf154c, 0x85e7c2d1, 0xe0807e69, 0x0e2fcb7b, 0x6b4877c3,
+ 0xa20f0dcb, 0xc768b173, 0x29c70461, 0x4ca0b8d9, 0xf5986f44,
+ 0x90ffd3fc, 0x7e5066ee, 0x1b37da56, 0x4d27b90e, 0x284005b6,
+ 0xc6efb0a4, 0xa3880c1c, 0x1ab0db81, 0x7fd76739, 0x9178d22b,
+ 0xf41f6e93, 0x03f7263b, 0x66909a83, 0x883f2f91, 0xed589329,
+ 0x546044b4, 0x3107f80c, 0xdfa84d1e, 0xbacff1a6, 0xecdf92fe,
+ 0x89b82e46, 0x67179b54, 0x027027ec, 0xbb48f071, 0xde2f4cc9,
+ 0x3080f9db, 0x55e74563, 0x9ca03f6b, 0xf9c783d3, 0x176836c1,
+ 0x720f8a79, 0xcb375de4, 0xae50e15c, 0x40ff544e, 0x2598e8f6,
+ 0x73888bae, 0x16ef3716, 0xf8408204, 0x9d273ebc, 0x241fe921,
+ 0x41785599, 0xafd7e08b, 0xcab05c33, 0x3bb659ed, 0x5ed1e555,
+ 0xb07e5047, 0xd519ecff, 0x6c213b62, 0x094687da, 0xe7e932c8,
+ 0x828e8e70, 0xd49eed28, 0xb1f95190, 0x5f56e482, 0x3a31583a,
+ 0x83098fa7, 0xe66e331f, 0x08c1860d, 0x6da63ab5, 0xa4e140bd,
+ 0xc186fc05, 0x2f294917, 0x4a4ef5af, 0xf3762232, 0x96119e8a,
+ 0x78be2b98, 0x1dd99720, 0x4bc9f478, 0x2eae48c0, 0xc001fdd2,
+ 0xa566416a, 0x1c5e96f7, 0x79392a4f, 0x97969f5d, 0xf2f123e5,
+ 0x05196b4d, 0x607ed7f5, 0x8ed162e7, 0xebb6de5f, 0x528e09c2,
+ 0x37e9b57a, 0xd9460068, 0xbc21bcd0, 0xea31df88, 0x8f566330,
+ 0x61f9d622, 0x049e6a9a, 0xbda6bd07, 0xd8c101bf, 0x366eb4ad,
+ 0x53090815, 0x9a4e721d, 0xff29cea5, 0x11867bb7, 0x74e1c70f,
+ 0xcdd91092, 0xa8beac2a, 0x46111938, 0x2376a580, 0x7566c6d8,
+ 0x10017a60, 0xfeaecf72, 0x9bc973ca, 0x22f1a457, 0x479618ef,
+ 0xa939adfd, 0xcc5e1145, 0x06ee4d76, 0x6389f1ce, 0x8d2644dc,
+ 0xe841f864, 0x51792ff9, 0x341e9341, 0xdab12653, 0xbfd69aeb,
+ 0xe9c6f9b3, 0x8ca1450b, 0x620ef019, 0x07694ca1, 0xbe519b3c,
+ 0xdb362784, 0x35999296, 0x50fe2e2e, 0x99b95426, 0xfcdee89e,
+ 0x12715d8c, 0x7716e134, 0xce2e36a9, 0xab498a11, 0x45e63f03,
+ 0x208183bb, 0x7691e0e3, 0x13f65c5b, 0xfd59e949, 0x983e55f1,
+ 0x2106826c, 0x44613ed4, 0xaace8bc6, 0xcfa9377e, 0x38417fd6,
+ 0x5d26c36e, 0xb389767c, 0xd6eecac4, 0x6fd61d59, 0x0ab1a1e1,
+ 0xe41e14f3, 0x8179a84b, 0xd769cb13, 0xb20e77ab, 0x5ca1c2b9,
+ 0x39c67e01, 0x80fea99c, 0xe5991524, 0x0b36a036, 0x6e511c8e,
+ 0xa7166686, 0xc271da3e, 0x2cde6f2c, 0x49b9d394, 0xf0810409,
+ 0x95e6b8b1, 0x7b490da3, 0x1e2eb11b, 0x483ed243, 0x2d596efb,
+ 0xc3f6dbe9, 0xa6916751, 0x1fa9b0cc, 0x7ace0c74, 0x9461b966,
+ 0xf10605de}};
+
+#endif
+
+#endif
+
+#if N == 2
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6},
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43147b1700000000, 0x8628f62e00000000,
+ 0xc53c8d3900000000, 0x0c51ec5d00000000, 0x4f45974a00000000,
+ 0x8a791a7300000000, 0xc96d616400000000, 0x18a2d8bb00000000,
+ 0x5bb6a3ac00000000, 0x9e8a2e9500000000, 0xdd9e558200000000,
+ 0x14f334e600000000, 0x57e74ff100000000, 0x92dbc2c800000000,
+ 0xd1cfb9df00000000, 0x7142c0ac00000000, 0x3256bbbb00000000,
+ 0xf76a368200000000, 0xb47e4d9500000000, 0x7d132cf100000000,
+ 0x3e0757e600000000, 0xfb3bdadf00000000, 0xb82fa1c800000000,
+ 0x69e0181700000000, 0x2af4630000000000, 0xefc8ee3900000000,
+ 0xacdc952e00000000, 0x65b1f44a00000000, 0x26a58f5d00000000,
+ 0xe399026400000000, 0xa08d797300000000, 0xa382f18200000000,
+ 0xe0968a9500000000, 0x25aa07ac00000000, 0x66be7cbb00000000,
+ 0xafd31ddf00000000, 0xecc766c800000000, 0x29fbebf100000000,
+ 0x6aef90e600000000, 0xbb20293900000000, 0xf834522e00000000,
+ 0x3d08df1700000000, 0x7e1ca40000000000, 0xb771c56400000000,
+ 0xf465be7300000000, 0x3159334a00000000, 0x724d485d00000000,
+ 0xd2c0312e00000000, 0x91d44a3900000000, 0x54e8c70000000000,
+ 0x17fcbc1700000000, 0xde91dd7300000000, 0x9d85a66400000000,
+ 0x58b92b5d00000000, 0x1bad504a00000000, 0xca62e99500000000,
+ 0x8976928200000000, 0x4c4a1fbb00000000, 0x0f5e64ac00000000,
+ 0xc63305c800000000, 0x85277edf00000000, 0x401bf3e600000000,
+ 0x030f88f100000000, 0x070392de00000000, 0x4417e9c900000000,
+ 0x812b64f000000000, 0xc23f1fe700000000, 0x0b527e8300000000,
+ 0x4846059400000000, 0x8d7a88ad00000000, 0xce6ef3ba00000000,
+ 0x1fa14a6500000000, 0x5cb5317200000000, 0x9989bc4b00000000,
+ 0xda9dc75c00000000, 0x13f0a63800000000, 0x50e4dd2f00000000,
+ 0x95d8501600000000, 0xd6cc2b0100000000, 0x7641527200000000,
+ 0x3555296500000000, 0xf069a45c00000000, 0xb37ddf4b00000000,
+ 0x7a10be2f00000000, 0x3904c53800000000, 0xfc38480100000000,
+ 0xbf2c331600000000, 0x6ee38ac900000000, 0x2df7f1de00000000,
+ 0xe8cb7ce700000000, 0xabdf07f000000000, 0x62b2669400000000,
+ 0x21a61d8300000000, 0xe49a90ba00000000, 0xa78eebad00000000,
+ 0xa481635c00000000, 0xe795184b00000000, 0x22a9957200000000,
+ 0x61bdee6500000000, 0xa8d08f0100000000, 0xebc4f41600000000,
+ 0x2ef8792f00000000, 0x6dec023800000000, 0xbc23bbe700000000,
+ 0xff37c0f000000000, 0x3a0b4dc900000000, 0x791f36de00000000,
+ 0xb07257ba00000000, 0xf3662cad00000000, 0x365aa19400000000,
+ 0x754eda8300000000, 0xd5c3a3f000000000, 0x96d7d8e700000000,
+ 0x53eb55de00000000, 0x10ff2ec900000000, 0xd9924fad00000000,
+ 0x9a8634ba00000000, 0x5fbab98300000000, 0x1caec29400000000,
+ 0xcd617b4b00000000, 0x8e75005c00000000, 0x4b498d6500000000,
+ 0x085df67200000000, 0xc130971600000000, 0x8224ec0100000000,
+ 0x4718613800000000, 0x040c1a2f00000000, 0x4f00556600000000,
+ 0x0c142e7100000000, 0xc928a34800000000, 0x8a3cd85f00000000,
+ 0x4351b93b00000000, 0x0045c22c00000000, 0xc5794f1500000000,
+ 0x866d340200000000, 0x57a28ddd00000000, 0x14b6f6ca00000000,
+ 0xd18a7bf300000000, 0x929e00e400000000, 0x5bf3618000000000,
+ 0x18e71a9700000000, 0xdddb97ae00000000, 0x9ecfecb900000000,
+ 0x3e4295ca00000000, 0x7d56eedd00000000, 0xb86a63e400000000,
+ 0xfb7e18f300000000, 0x3213799700000000, 0x7107028000000000,
+ 0xb43b8fb900000000, 0xf72ff4ae00000000, 0x26e04d7100000000,
+ 0x65f4366600000000, 0xa0c8bb5f00000000, 0xe3dcc04800000000,
+ 0x2ab1a12c00000000, 0x69a5da3b00000000, 0xac99570200000000,
+ 0xef8d2c1500000000, 0xec82a4e400000000, 0xaf96dff300000000,
+ 0x6aaa52ca00000000, 0x29be29dd00000000, 0xe0d348b900000000,
+ 0xa3c733ae00000000, 0x66fbbe9700000000, 0x25efc58000000000,
+ 0xf4207c5f00000000, 0xb734074800000000, 0x72088a7100000000,
+ 0x311cf16600000000, 0xf871900200000000, 0xbb65eb1500000000,
+ 0x7e59662c00000000, 0x3d4d1d3b00000000, 0x9dc0644800000000,
+ 0xded41f5f00000000, 0x1be8926600000000, 0x58fce97100000000,
+ 0x9191881500000000, 0xd285f30200000000, 0x17b97e3b00000000,
+ 0x54ad052c00000000, 0x8562bcf300000000, 0xc676c7e400000000,
+ 0x034a4add00000000, 0x405e31ca00000000, 0x893350ae00000000,
+ 0xca272bb900000000, 0x0f1ba68000000000, 0x4c0fdd9700000000,
+ 0x4803c7b800000000, 0x0b17bcaf00000000, 0xce2b319600000000,
+ 0x8d3f4a8100000000, 0x44522be500000000, 0x074650f200000000,
+ 0xc27addcb00000000, 0x816ea6dc00000000, 0x50a11f0300000000,
+ 0x13b5641400000000, 0xd689e92d00000000, 0x959d923a00000000,
+ 0x5cf0f35e00000000, 0x1fe4884900000000, 0xdad8057000000000,
+ 0x99cc7e6700000000, 0x3941071400000000, 0x7a557c0300000000,
+ 0xbf69f13a00000000, 0xfc7d8a2d00000000, 0x3510eb4900000000,
+ 0x7604905e00000000, 0xb3381d6700000000, 0xf02c667000000000,
+ 0x21e3dfaf00000000, 0x62f7a4b800000000, 0xa7cb298100000000,
+ 0xe4df529600000000, 0x2db233f200000000, 0x6ea648e500000000,
+ 0xab9ac5dc00000000, 0xe88ebecb00000000, 0xeb81363a00000000,
+ 0xa8954d2d00000000, 0x6da9c01400000000, 0x2ebdbb0300000000,
+ 0xe7d0da6700000000, 0xa4c4a17000000000, 0x61f82c4900000000,
+ 0x22ec575e00000000, 0xf323ee8100000000, 0xb037959600000000,
+ 0x750b18af00000000, 0x361f63b800000000, 0xff7202dc00000000,
+ 0xbc6679cb00000000, 0x795af4f200000000, 0x3a4e8fe500000000,
+ 0x9ac3f69600000000, 0xd9d78d8100000000, 0x1ceb00b800000000,
+ 0x5fff7baf00000000, 0x96921acb00000000, 0xd58661dc00000000,
+ 0x10baece500000000, 0x53ae97f200000000, 0x82612e2d00000000,
+ 0xc175553a00000000, 0x0449d80300000000, 0x475da31400000000,
+ 0x8e30c27000000000, 0xcd24b96700000000, 0x0818345e00000000,
+ 0x4b0c4f4900000000},
+ {0x0000000000000000, 0x3e6bc2ef00000000, 0x3dd0f50400000000,
+ 0x03bb37eb00000000, 0x7aa0eb0900000000, 0x44cb29e600000000,
+ 0x47701e0d00000000, 0x791bdce200000000, 0xf440d71300000000,
+ 0xca2b15fc00000000, 0xc990221700000000, 0xf7fbe0f800000000,
+ 0x8ee03c1a00000000, 0xb08bfef500000000, 0xb330c91e00000000,
+ 0x8d5b0bf100000000, 0xe881ae2700000000, 0xd6ea6cc800000000,
+ 0xd5515b2300000000, 0xeb3a99cc00000000, 0x9221452e00000000,
+ 0xac4a87c100000000, 0xaff1b02a00000000, 0x919a72c500000000,
+ 0x1cc1793400000000, 0x22aabbdb00000000, 0x21118c3000000000,
+ 0x1f7a4edf00000000, 0x6661923d00000000, 0x580a50d200000000,
+ 0x5bb1673900000000, 0x65daa5d600000000, 0xd0035d4f00000000,
+ 0xee689fa000000000, 0xedd3a84b00000000, 0xd3b86aa400000000,
+ 0xaaa3b64600000000, 0x94c874a900000000, 0x9773434200000000,
+ 0xa91881ad00000000, 0x24438a5c00000000, 0x1a2848b300000000,
+ 0x19937f5800000000, 0x27f8bdb700000000, 0x5ee3615500000000,
+ 0x6088a3ba00000000, 0x6333945100000000, 0x5d5856be00000000,
+ 0x3882f36800000000, 0x06e9318700000000, 0x0552066c00000000,
+ 0x3b39c48300000000, 0x4222186100000000, 0x7c49da8e00000000,
+ 0x7ff2ed6500000000, 0x41992f8a00000000, 0xccc2247b00000000,
+ 0xf2a9e69400000000, 0xf112d17f00000000, 0xcf79139000000000,
+ 0xb662cf7200000000, 0x88090d9d00000000, 0x8bb23a7600000000,
+ 0xb5d9f89900000000, 0xa007ba9e00000000, 0x9e6c787100000000,
+ 0x9dd74f9a00000000, 0xa3bc8d7500000000, 0xdaa7519700000000,
+ 0xe4cc937800000000, 0xe777a49300000000, 0xd91c667c00000000,
+ 0x54476d8d00000000, 0x6a2caf6200000000, 0x6997988900000000,
+ 0x57fc5a6600000000, 0x2ee7868400000000, 0x108c446b00000000,
+ 0x1337738000000000, 0x2d5cb16f00000000, 0x488614b900000000,
+ 0x76edd65600000000, 0x7556e1bd00000000, 0x4b3d235200000000,
+ 0x3226ffb000000000, 0x0c4d3d5f00000000, 0x0ff60ab400000000,
+ 0x319dc85b00000000, 0xbcc6c3aa00000000, 0x82ad014500000000,
+ 0x811636ae00000000, 0xbf7df44100000000, 0xc66628a300000000,
+ 0xf80dea4c00000000, 0xfbb6dda700000000, 0xc5dd1f4800000000,
+ 0x7004e7d100000000, 0x4e6f253e00000000, 0x4dd412d500000000,
+ 0x73bfd03a00000000, 0x0aa40cd800000000, 0x34cfce3700000000,
+ 0x3774f9dc00000000, 0x091f3b3300000000, 0x844430c200000000,
+ 0xba2ff22d00000000, 0xb994c5c600000000, 0x87ff072900000000,
+ 0xfee4dbcb00000000, 0xc08f192400000000, 0xc3342ecf00000000,
+ 0xfd5fec2000000000, 0x988549f600000000, 0xa6ee8b1900000000,
+ 0xa555bcf200000000, 0x9b3e7e1d00000000, 0xe225a2ff00000000,
+ 0xdc4e601000000000, 0xdff557fb00000000, 0xe19e951400000000,
+ 0x6cc59ee500000000, 0x52ae5c0a00000000, 0x51156be100000000,
+ 0x6f7ea90e00000000, 0x166575ec00000000, 0x280eb70300000000,
+ 0x2bb580e800000000, 0x15de420700000000, 0x010905e600000000,
+ 0x3f62c70900000000, 0x3cd9f0e200000000, 0x02b2320d00000000,
+ 0x7ba9eeef00000000, 0x45c22c0000000000, 0x46791beb00000000,
+ 0x7812d90400000000, 0xf549d2f500000000, 0xcb22101a00000000,
+ 0xc89927f100000000, 0xf6f2e51e00000000, 0x8fe939fc00000000,
+ 0xb182fb1300000000, 0xb239ccf800000000, 0x8c520e1700000000,
+ 0xe988abc100000000, 0xd7e3692e00000000, 0xd4585ec500000000,
+ 0xea339c2a00000000, 0x932840c800000000, 0xad43822700000000,
+ 0xaef8b5cc00000000, 0x9093772300000000, 0x1dc87cd200000000,
+ 0x23a3be3d00000000, 0x201889d600000000, 0x1e734b3900000000,
+ 0x676897db00000000, 0x5903553400000000, 0x5ab862df00000000,
+ 0x64d3a03000000000, 0xd10a58a900000000, 0xef619a4600000000,
+ 0xecdaadad00000000, 0xd2b16f4200000000, 0xabaab3a000000000,
+ 0x95c1714f00000000, 0x967a46a400000000, 0xa811844b00000000,
+ 0x254a8fba00000000, 0x1b214d5500000000, 0x189a7abe00000000,
+ 0x26f1b85100000000, 0x5fea64b300000000, 0x6181a65c00000000,
+ 0x623a91b700000000, 0x5c51535800000000, 0x398bf68e00000000,
+ 0x07e0346100000000, 0x045b038a00000000, 0x3a30c16500000000,
+ 0x432b1d8700000000, 0x7d40df6800000000, 0x7efbe88300000000,
+ 0x40902a6c00000000, 0xcdcb219d00000000, 0xf3a0e37200000000,
+ 0xf01bd49900000000, 0xce70167600000000, 0xb76bca9400000000,
+ 0x8900087b00000000, 0x8abb3f9000000000, 0xb4d0fd7f00000000,
+ 0xa10ebf7800000000, 0x9f657d9700000000, 0x9cde4a7c00000000,
+ 0xa2b5889300000000, 0xdbae547100000000, 0xe5c5969e00000000,
+ 0xe67ea17500000000, 0xd815639a00000000, 0x554e686b00000000,
+ 0x6b25aa8400000000, 0x689e9d6f00000000, 0x56f55f8000000000,
+ 0x2fee836200000000, 0x1185418d00000000, 0x123e766600000000,
+ 0x2c55b48900000000, 0x498f115f00000000, 0x77e4d3b000000000,
+ 0x745fe45b00000000, 0x4a3426b400000000, 0x332ffa5600000000,
+ 0x0d4438b900000000, 0x0eff0f5200000000, 0x3094cdbd00000000,
+ 0xbdcfc64c00000000, 0x83a404a300000000, 0x801f334800000000,
+ 0xbe74f1a700000000, 0xc76f2d4500000000, 0xf904efaa00000000,
+ 0xfabfd84100000000, 0xc4d41aae00000000, 0x710de23700000000,
+ 0x4f6620d800000000, 0x4cdd173300000000, 0x72b6d5dc00000000,
+ 0x0bad093e00000000, 0x35c6cbd100000000, 0x367dfc3a00000000,
+ 0x08163ed500000000, 0x854d352400000000, 0xbb26f7cb00000000,
+ 0xb89dc02000000000, 0x86f602cf00000000, 0xffedde2d00000000,
+ 0xc1861cc200000000, 0xc23d2b2900000000, 0xfc56e9c600000000,
+ 0x998c4c1000000000, 0xa7e78eff00000000, 0xa45cb91400000000,
+ 0x9a377bfb00000000, 0xe32ca71900000000, 0xdd4765f600000000,
+ 0xdefc521d00000000, 0xe09790f200000000, 0x6dcc9b0300000000,
+ 0x53a759ec00000000, 0x501c6e0700000000, 0x6e77ace800000000,
+ 0x176c700a00000000, 0x2907b2e500000000, 0x2abc850e00000000,
+ 0x14d747e100000000},
+ {0x0000000000000000, 0xc0df8ec100000000, 0xc1b96c5800000000,
+ 0x0166e29900000000, 0x8273d9b000000000, 0x42ac577100000000,
+ 0x43cab5e800000000, 0x83153b2900000000, 0x45e1c3ba00000000,
+ 0x853e4d7b00000000, 0x8458afe200000000, 0x4487212300000000,
+ 0xc7921a0a00000000, 0x074d94cb00000000, 0x062b765200000000,
+ 0xc6f4f89300000000, 0xcbc4f6ae00000000, 0x0b1b786f00000000,
+ 0x0a7d9af600000000, 0xcaa2143700000000, 0x49b72f1e00000000,
+ 0x8968a1df00000000, 0x880e434600000000, 0x48d1cd8700000000,
+ 0x8e25351400000000, 0x4efabbd500000000, 0x4f9c594c00000000,
+ 0x8f43d78d00000000, 0x0c56eca400000000, 0xcc89626500000000,
+ 0xcdef80fc00000000, 0x0d300e3d00000000, 0xd78f9c8600000000,
+ 0x1750124700000000, 0x1636f0de00000000, 0xd6e97e1f00000000,
+ 0x55fc453600000000, 0x9523cbf700000000, 0x9445296e00000000,
+ 0x549aa7af00000000, 0x926e5f3c00000000, 0x52b1d1fd00000000,
+ 0x53d7336400000000, 0x9308bda500000000, 0x101d868c00000000,
+ 0xd0c2084d00000000, 0xd1a4ead400000000, 0x117b641500000000,
+ 0x1c4b6a2800000000, 0xdc94e4e900000000, 0xddf2067000000000,
+ 0x1d2d88b100000000, 0x9e38b39800000000, 0x5ee73d5900000000,
+ 0x5f81dfc000000000, 0x9f5e510100000000, 0x59aaa99200000000,
+ 0x9975275300000000, 0x9813c5ca00000000, 0x58cc4b0b00000000,
+ 0xdbd9702200000000, 0x1b06fee300000000, 0x1a601c7a00000000,
+ 0xdabf92bb00000000, 0xef1948d600000000, 0x2fc6c61700000000,
+ 0x2ea0248e00000000, 0xee7faa4f00000000, 0x6d6a916600000000,
+ 0xadb51fa700000000, 0xacd3fd3e00000000, 0x6c0c73ff00000000,
+ 0xaaf88b6c00000000, 0x6a2705ad00000000, 0x6b41e73400000000,
+ 0xab9e69f500000000, 0x288b52dc00000000, 0xe854dc1d00000000,
+ 0xe9323e8400000000, 0x29edb04500000000, 0x24ddbe7800000000,
+ 0xe40230b900000000, 0xe564d22000000000, 0x25bb5ce100000000,
+ 0xa6ae67c800000000, 0x6671e90900000000, 0x67170b9000000000,
+ 0xa7c8855100000000, 0x613c7dc200000000, 0xa1e3f30300000000,
+ 0xa085119a00000000, 0x605a9f5b00000000, 0xe34fa47200000000,
+ 0x23902ab300000000, 0x22f6c82a00000000, 0xe22946eb00000000,
+ 0x3896d45000000000, 0xf8495a9100000000, 0xf92fb80800000000,
+ 0x39f036c900000000, 0xbae50de000000000, 0x7a3a832100000000,
+ 0x7b5c61b800000000, 0xbb83ef7900000000, 0x7d7717ea00000000,
+ 0xbda8992b00000000, 0xbcce7bb200000000, 0x7c11f57300000000,
+ 0xff04ce5a00000000, 0x3fdb409b00000000, 0x3ebda20200000000,
+ 0xfe622cc300000000, 0xf35222fe00000000, 0x338dac3f00000000,
+ 0x32eb4ea600000000, 0xf234c06700000000, 0x7121fb4e00000000,
+ 0xb1fe758f00000000, 0xb098971600000000, 0x704719d700000000,
+ 0xb6b3e14400000000, 0x766c6f8500000000, 0x770a8d1c00000000,
+ 0xb7d503dd00000000, 0x34c038f400000000, 0xf41fb63500000000,
+ 0xf57954ac00000000, 0x35a6da6d00000000, 0x9f35e17700000000,
+ 0x5fea6fb600000000, 0x5e8c8d2f00000000, 0x9e5303ee00000000,
+ 0x1d4638c700000000, 0xdd99b60600000000, 0xdcff549f00000000,
+ 0x1c20da5e00000000, 0xdad422cd00000000, 0x1a0bac0c00000000,
+ 0x1b6d4e9500000000, 0xdbb2c05400000000, 0x58a7fb7d00000000,
+ 0x987875bc00000000, 0x991e972500000000, 0x59c119e400000000,
+ 0x54f117d900000000, 0x942e991800000000, 0x95487b8100000000,
+ 0x5597f54000000000, 0xd682ce6900000000, 0x165d40a800000000,
+ 0x173ba23100000000, 0xd7e42cf000000000, 0x1110d46300000000,
+ 0xd1cf5aa200000000, 0xd0a9b83b00000000, 0x107636fa00000000,
+ 0x93630dd300000000, 0x53bc831200000000, 0x52da618b00000000,
+ 0x9205ef4a00000000, 0x48ba7df100000000, 0x8865f33000000000,
+ 0x890311a900000000, 0x49dc9f6800000000, 0xcac9a44100000000,
+ 0x0a162a8000000000, 0x0b70c81900000000, 0xcbaf46d800000000,
+ 0x0d5bbe4b00000000, 0xcd84308a00000000, 0xcce2d21300000000,
+ 0x0c3d5cd200000000, 0x8f2867fb00000000, 0x4ff7e93a00000000,
+ 0x4e910ba300000000, 0x8e4e856200000000, 0x837e8b5f00000000,
+ 0x43a1059e00000000, 0x42c7e70700000000, 0x821869c600000000,
+ 0x010d52ef00000000, 0xc1d2dc2e00000000, 0xc0b43eb700000000,
+ 0x006bb07600000000, 0xc69f48e500000000, 0x0640c62400000000,
+ 0x072624bd00000000, 0xc7f9aa7c00000000, 0x44ec915500000000,
+ 0x84331f9400000000, 0x8555fd0d00000000, 0x458a73cc00000000,
+ 0x702ca9a100000000, 0xb0f3276000000000, 0xb195c5f900000000,
+ 0x714a4b3800000000, 0xf25f701100000000, 0x3280fed000000000,
+ 0x33e61c4900000000, 0xf339928800000000, 0x35cd6a1b00000000,
+ 0xf512e4da00000000, 0xf474064300000000, 0x34ab888200000000,
+ 0xb7beb3ab00000000, 0x77613d6a00000000, 0x7607dff300000000,
+ 0xb6d8513200000000, 0xbbe85f0f00000000, 0x7b37d1ce00000000,
+ 0x7a51335700000000, 0xba8ebd9600000000, 0x399b86bf00000000,
+ 0xf944087e00000000, 0xf822eae700000000, 0x38fd642600000000,
+ 0xfe099cb500000000, 0x3ed6127400000000, 0x3fb0f0ed00000000,
+ 0xff6f7e2c00000000, 0x7c7a450500000000, 0xbca5cbc400000000,
+ 0xbdc3295d00000000, 0x7d1ca79c00000000, 0xa7a3352700000000,
+ 0x677cbbe600000000, 0x661a597f00000000, 0xa6c5d7be00000000,
+ 0x25d0ec9700000000, 0xe50f625600000000, 0xe46980cf00000000,
+ 0x24b60e0e00000000, 0xe242f69d00000000, 0x229d785c00000000,
+ 0x23fb9ac500000000, 0xe324140400000000, 0x60312f2d00000000,
+ 0xa0eea1ec00000000, 0xa188437500000000, 0x6157cdb400000000,
+ 0x6c67c38900000000, 0xacb84d4800000000, 0xaddeafd100000000,
+ 0x6d01211000000000, 0xee141a3900000000, 0x2ecb94f800000000,
+ 0x2fad766100000000, 0xef72f8a000000000, 0x2986003300000000,
+ 0xe9598ef200000000, 0xe83f6c6b00000000, 0x28e0e2aa00000000,
+ 0xabf5d98300000000, 0x6b2a574200000000, 0x6a4cb5db00000000,
+ 0xaa933b1a00000000},
+ {0x0000000000000000, 0x6f4ca59b00000000, 0x9f9e3bec00000000,
+ 0xf0d29e7700000000, 0x7f3b060300000000, 0x1077a39800000000,
+ 0xe0a53def00000000, 0x8fe9987400000000, 0xfe760c0600000000,
+ 0x913aa99d00000000, 0x61e837ea00000000, 0x0ea4927100000000,
+ 0x814d0a0500000000, 0xee01af9e00000000, 0x1ed331e900000000,
+ 0x719f947200000000, 0xfced180c00000000, 0x93a1bd9700000000,
+ 0x637323e000000000, 0x0c3f867b00000000, 0x83d61e0f00000000,
+ 0xec9abb9400000000, 0x1c4825e300000000, 0x7304807800000000,
+ 0x029b140a00000000, 0x6dd7b19100000000, 0x9d052fe600000000,
+ 0xf2498a7d00000000, 0x7da0120900000000, 0x12ecb79200000000,
+ 0xe23e29e500000000, 0x8d728c7e00000000, 0xf8db311800000000,
+ 0x9797948300000000, 0x67450af400000000, 0x0809af6f00000000,
+ 0x87e0371b00000000, 0xe8ac928000000000, 0x187e0cf700000000,
+ 0x7732a96c00000000, 0x06ad3d1e00000000, 0x69e1988500000000,
+ 0x993306f200000000, 0xf67fa36900000000, 0x79963b1d00000000,
+ 0x16da9e8600000000, 0xe60800f100000000, 0x8944a56a00000000,
+ 0x0436291400000000, 0x6b7a8c8f00000000, 0x9ba812f800000000,
+ 0xf4e4b76300000000, 0x7b0d2f1700000000, 0x14418a8c00000000,
+ 0xe49314fb00000000, 0x8bdfb16000000000, 0xfa40251200000000,
+ 0x950c808900000000, 0x65de1efe00000000, 0x0a92bb6500000000,
+ 0x857b231100000000, 0xea37868a00000000, 0x1ae518fd00000000,
+ 0x75a9bd6600000000, 0xf0b7633000000000, 0x9ffbc6ab00000000,
+ 0x6f2958dc00000000, 0x0065fd4700000000, 0x8f8c653300000000,
+ 0xe0c0c0a800000000, 0x10125edf00000000, 0x7f5efb4400000000,
+ 0x0ec16f3600000000, 0x618dcaad00000000, 0x915f54da00000000,
+ 0xfe13f14100000000, 0x71fa693500000000, 0x1eb6ccae00000000,
+ 0xee6452d900000000, 0x8128f74200000000, 0x0c5a7b3c00000000,
+ 0x6316dea700000000, 0x93c440d000000000, 0xfc88e54b00000000,
+ 0x73617d3f00000000, 0x1c2dd8a400000000, 0xecff46d300000000,
+ 0x83b3e34800000000, 0xf22c773a00000000, 0x9d60d2a100000000,
+ 0x6db24cd600000000, 0x02fee94d00000000, 0x8d17713900000000,
+ 0xe25bd4a200000000, 0x12894ad500000000, 0x7dc5ef4e00000000,
+ 0x086c522800000000, 0x6720f7b300000000, 0x97f269c400000000,
+ 0xf8becc5f00000000, 0x7757542b00000000, 0x181bf1b000000000,
+ 0xe8c96fc700000000, 0x8785ca5c00000000, 0xf61a5e2e00000000,
+ 0x9956fbb500000000, 0x698465c200000000, 0x06c8c05900000000,
+ 0x8921582d00000000, 0xe66dfdb600000000, 0x16bf63c100000000,
+ 0x79f3c65a00000000, 0xf4814a2400000000, 0x9bcdefbf00000000,
+ 0x6b1f71c800000000, 0x0453d45300000000, 0x8bba4c2700000000,
+ 0xe4f6e9bc00000000, 0x142477cb00000000, 0x7b68d25000000000,
+ 0x0af7462200000000, 0x65bbe3b900000000, 0x95697dce00000000,
+ 0xfa25d85500000000, 0x75cc402100000000, 0x1a80e5ba00000000,
+ 0xea527bcd00000000, 0x851ede5600000000, 0xe06fc76000000000,
+ 0x8f2362fb00000000, 0x7ff1fc8c00000000, 0x10bd591700000000,
+ 0x9f54c16300000000, 0xf01864f800000000, 0x00cafa8f00000000,
+ 0x6f865f1400000000, 0x1e19cb6600000000, 0x71556efd00000000,
+ 0x8187f08a00000000, 0xeecb551100000000, 0x6122cd6500000000,
+ 0x0e6e68fe00000000, 0xfebcf68900000000, 0x91f0531200000000,
+ 0x1c82df6c00000000, 0x73ce7af700000000, 0x831ce48000000000,
+ 0xec50411b00000000, 0x63b9d96f00000000, 0x0cf57cf400000000,
+ 0xfc27e28300000000, 0x936b471800000000, 0xe2f4d36a00000000,
+ 0x8db876f100000000, 0x7d6ae88600000000, 0x12264d1d00000000,
+ 0x9dcfd56900000000, 0xf28370f200000000, 0x0251ee8500000000,
+ 0x6d1d4b1e00000000, 0x18b4f67800000000, 0x77f853e300000000,
+ 0x872acd9400000000, 0xe866680f00000000, 0x678ff07b00000000,
+ 0x08c355e000000000, 0xf811cb9700000000, 0x975d6e0c00000000,
+ 0xe6c2fa7e00000000, 0x898e5fe500000000, 0x795cc19200000000,
+ 0x1610640900000000, 0x99f9fc7d00000000, 0xf6b559e600000000,
+ 0x0667c79100000000, 0x692b620a00000000, 0xe459ee7400000000,
+ 0x8b154bef00000000, 0x7bc7d59800000000, 0x148b700300000000,
+ 0x9b62e87700000000, 0xf42e4dec00000000, 0x04fcd39b00000000,
+ 0x6bb0760000000000, 0x1a2fe27200000000, 0x756347e900000000,
+ 0x85b1d99e00000000, 0xeafd7c0500000000, 0x6514e47100000000,
+ 0x0a5841ea00000000, 0xfa8adf9d00000000, 0x95c67a0600000000,
+ 0x10d8a45000000000, 0x7f9401cb00000000, 0x8f469fbc00000000,
+ 0xe00a3a2700000000, 0x6fe3a25300000000, 0x00af07c800000000,
+ 0xf07d99bf00000000, 0x9f313c2400000000, 0xeeaea85600000000,
+ 0x81e20dcd00000000, 0x713093ba00000000, 0x1e7c362100000000,
+ 0x9195ae5500000000, 0xfed90bce00000000, 0x0e0b95b900000000,
+ 0x6147302200000000, 0xec35bc5c00000000, 0x837919c700000000,
+ 0x73ab87b000000000, 0x1ce7222b00000000, 0x930eba5f00000000,
+ 0xfc421fc400000000, 0x0c9081b300000000, 0x63dc242800000000,
+ 0x1243b05a00000000, 0x7d0f15c100000000, 0x8ddd8bb600000000,
+ 0xe2912e2d00000000, 0x6d78b65900000000, 0x023413c200000000,
+ 0xf2e68db500000000, 0x9daa282e00000000, 0xe803954800000000,
+ 0x874f30d300000000, 0x779daea400000000, 0x18d10b3f00000000,
+ 0x9738934b00000000, 0xf87436d000000000, 0x08a6a8a700000000,
+ 0x67ea0d3c00000000, 0x1675994e00000000, 0x79393cd500000000,
+ 0x89eba2a200000000, 0xe6a7073900000000, 0x694e9f4d00000000,
+ 0x06023ad600000000, 0xf6d0a4a100000000, 0x999c013a00000000,
+ 0x14ee8d4400000000, 0x7ba228df00000000, 0x8b70b6a800000000,
+ 0xe43c133300000000, 0x6bd58b4700000000, 0x04992edc00000000,
+ 0xf44bb0ab00000000, 0x9b07153000000000, 0xea98814200000000,
+ 0x85d424d900000000, 0x7506baae00000000, 0x1a4a1f3500000000,
+ 0x95a3874100000000, 0xfaef22da00000000, 0x0a3dbcad00000000,
+ 0x6571193600000000},
+ {0x0000000000000000, 0x85d996dd00000000, 0x4bb55c6000000000,
+ 0xce6ccabd00000000, 0x966ab9c000000000, 0x13b32f1d00000000,
+ 0xdddfe5a000000000, 0x5806737d00000000, 0x6dd3035a00000000,
+ 0xe80a958700000000, 0x26665f3a00000000, 0xa3bfc9e700000000,
+ 0xfbb9ba9a00000000, 0x7e602c4700000000, 0xb00ce6fa00000000,
+ 0x35d5702700000000, 0xdaa607b400000000, 0x5f7f916900000000,
+ 0x91135bd400000000, 0x14cacd0900000000, 0x4cccbe7400000000,
+ 0xc91528a900000000, 0x0779e21400000000, 0x82a074c900000000,
+ 0xb77504ee00000000, 0x32ac923300000000, 0xfcc0588e00000000,
+ 0x7919ce5300000000, 0x211fbd2e00000000, 0xa4c62bf300000000,
+ 0x6aaae14e00000000, 0xef73779300000000, 0xf54b7eb300000000,
+ 0x7092e86e00000000, 0xbefe22d300000000, 0x3b27b40e00000000,
+ 0x6321c77300000000, 0xe6f851ae00000000, 0x28949b1300000000,
+ 0xad4d0dce00000000, 0x98987de900000000, 0x1d41eb3400000000,
+ 0xd32d218900000000, 0x56f4b75400000000, 0x0ef2c42900000000,
+ 0x8b2b52f400000000, 0x4547984900000000, 0xc09e0e9400000000,
+ 0x2fed790700000000, 0xaa34efda00000000, 0x6458256700000000,
+ 0xe181b3ba00000000, 0xb987c0c700000000, 0x3c5e561a00000000,
+ 0xf2329ca700000000, 0x77eb0a7a00000000, 0x423e7a5d00000000,
+ 0xc7e7ec8000000000, 0x098b263d00000000, 0x8c52b0e000000000,
+ 0xd454c39d00000000, 0x518d554000000000, 0x9fe19ffd00000000,
+ 0x1a38092000000000, 0xab918dbd00000000, 0x2e481b6000000000,
+ 0xe024d1dd00000000, 0x65fd470000000000, 0x3dfb347d00000000,
+ 0xb822a2a000000000, 0x764e681d00000000, 0xf397fec000000000,
+ 0xc6428ee700000000, 0x439b183a00000000, 0x8df7d28700000000,
+ 0x082e445a00000000, 0x5028372700000000, 0xd5f1a1fa00000000,
+ 0x1b9d6b4700000000, 0x9e44fd9a00000000, 0x71378a0900000000,
+ 0xf4ee1cd400000000, 0x3a82d66900000000, 0xbf5b40b400000000,
+ 0xe75d33c900000000, 0x6284a51400000000, 0xace86fa900000000,
+ 0x2931f97400000000, 0x1ce4895300000000, 0x993d1f8e00000000,
+ 0x5751d53300000000, 0xd28843ee00000000, 0x8a8e309300000000,
+ 0x0f57a64e00000000, 0xc13b6cf300000000, 0x44e2fa2e00000000,
+ 0x5edaf30e00000000, 0xdb0365d300000000, 0x156faf6e00000000,
+ 0x90b639b300000000, 0xc8b04ace00000000, 0x4d69dc1300000000,
+ 0x830516ae00000000, 0x06dc807300000000, 0x3309f05400000000,
+ 0xb6d0668900000000, 0x78bcac3400000000, 0xfd653ae900000000,
+ 0xa563499400000000, 0x20badf4900000000, 0xeed615f400000000,
+ 0x6b0f832900000000, 0x847cf4ba00000000, 0x01a5626700000000,
+ 0xcfc9a8da00000000, 0x4a103e0700000000, 0x12164d7a00000000,
+ 0x97cfdba700000000, 0x59a3111a00000000, 0xdc7a87c700000000,
+ 0xe9aff7e000000000, 0x6c76613d00000000, 0xa21aab8000000000,
+ 0x27c33d5d00000000, 0x7fc54e2000000000, 0xfa1cd8fd00000000,
+ 0x3470124000000000, 0xb1a9849d00000000, 0x17256aa000000000,
+ 0x92fcfc7d00000000, 0x5c9036c000000000, 0xd949a01d00000000,
+ 0x814fd36000000000, 0x049645bd00000000, 0xcafa8f0000000000,
+ 0x4f2319dd00000000, 0x7af669fa00000000, 0xff2fff2700000000,
+ 0x3143359a00000000, 0xb49aa34700000000, 0xec9cd03a00000000,
+ 0x694546e700000000, 0xa7298c5a00000000, 0x22f01a8700000000,
+ 0xcd836d1400000000, 0x485afbc900000000, 0x8636317400000000,
+ 0x03efa7a900000000, 0x5be9d4d400000000, 0xde30420900000000,
+ 0x105c88b400000000, 0x95851e6900000000, 0xa0506e4e00000000,
+ 0x2589f89300000000, 0xebe5322e00000000, 0x6e3ca4f300000000,
+ 0x363ad78e00000000, 0xb3e3415300000000, 0x7d8f8bee00000000,
+ 0xf8561d3300000000, 0xe26e141300000000, 0x67b782ce00000000,
+ 0xa9db487300000000, 0x2c02deae00000000, 0x7404add300000000,
+ 0xf1dd3b0e00000000, 0x3fb1f1b300000000, 0xba68676e00000000,
+ 0x8fbd174900000000, 0x0a64819400000000, 0xc4084b2900000000,
+ 0x41d1ddf400000000, 0x19d7ae8900000000, 0x9c0e385400000000,
+ 0x5262f2e900000000, 0xd7bb643400000000, 0x38c813a700000000,
+ 0xbd11857a00000000, 0x737d4fc700000000, 0xf6a4d91a00000000,
+ 0xaea2aa6700000000, 0x2b7b3cba00000000, 0xe517f60700000000,
+ 0x60ce60da00000000, 0x551b10fd00000000, 0xd0c2862000000000,
+ 0x1eae4c9d00000000, 0x9b77da4000000000, 0xc371a93d00000000,
+ 0x46a83fe000000000, 0x88c4f55d00000000, 0x0d1d638000000000,
+ 0xbcb4e71d00000000, 0x396d71c000000000, 0xf701bb7d00000000,
+ 0x72d82da000000000, 0x2ade5edd00000000, 0xaf07c80000000000,
+ 0x616b02bd00000000, 0xe4b2946000000000, 0xd167e44700000000,
+ 0x54be729a00000000, 0x9ad2b82700000000, 0x1f0b2efa00000000,
+ 0x470d5d8700000000, 0xc2d4cb5a00000000, 0x0cb801e700000000,
+ 0x8961973a00000000, 0x6612e0a900000000, 0xe3cb767400000000,
+ 0x2da7bcc900000000, 0xa87e2a1400000000, 0xf078596900000000,
+ 0x75a1cfb400000000, 0xbbcd050900000000, 0x3e1493d400000000,
+ 0x0bc1e3f300000000, 0x8e18752e00000000, 0x4074bf9300000000,
+ 0xc5ad294e00000000, 0x9dab5a3300000000, 0x1872ccee00000000,
+ 0xd61e065300000000, 0x53c7908e00000000, 0x49ff99ae00000000,
+ 0xcc260f7300000000, 0x024ac5ce00000000, 0x8793531300000000,
+ 0xdf95206e00000000, 0x5a4cb6b300000000, 0x94207c0e00000000,
+ 0x11f9ead300000000, 0x242c9af400000000, 0xa1f50c2900000000,
+ 0x6f99c69400000000, 0xea40504900000000, 0xb246233400000000,
+ 0x379fb5e900000000, 0xf9f37f5400000000, 0x7c2ae98900000000,
+ 0x93599e1a00000000, 0x168008c700000000, 0xd8ecc27a00000000,
+ 0x5d3554a700000000, 0x053327da00000000, 0x80eab10700000000,
+ 0x4e867bba00000000, 0xcb5fed6700000000, 0xfe8a9d4000000000,
+ 0x7b530b9d00000000, 0xb53fc12000000000, 0x30e657fd00000000,
+ 0x68e0248000000000, 0xed39b25d00000000, 0x235578e000000000,
+ 0xa68cee3d00000000},
+ {0x0000000000000000, 0x76e10f9d00000000, 0xadc46ee100000000,
+ 0xdb25617c00000000, 0x1b8fac1900000000, 0x6d6ea38400000000,
+ 0xb64bc2f800000000, 0xc0aacd6500000000, 0x361e593300000000,
+ 0x40ff56ae00000000, 0x9bda37d200000000, 0xed3b384f00000000,
+ 0x2d91f52a00000000, 0x5b70fab700000000, 0x80559bcb00000000,
+ 0xf6b4945600000000, 0x6c3cb26600000000, 0x1addbdfb00000000,
+ 0xc1f8dc8700000000, 0xb719d31a00000000, 0x77b31e7f00000000,
+ 0x015211e200000000, 0xda77709e00000000, 0xac967f0300000000,
+ 0x5a22eb5500000000, 0x2cc3e4c800000000, 0xf7e685b400000000,
+ 0x81078a2900000000, 0x41ad474c00000000, 0x374c48d100000000,
+ 0xec6929ad00000000, 0x9a88263000000000, 0xd87864cd00000000,
+ 0xae996b5000000000, 0x75bc0a2c00000000, 0x035d05b100000000,
+ 0xc3f7c8d400000000, 0xb516c74900000000, 0x6e33a63500000000,
+ 0x18d2a9a800000000, 0xee663dfe00000000, 0x9887326300000000,
+ 0x43a2531f00000000, 0x35435c8200000000, 0xf5e991e700000000,
+ 0x83089e7a00000000, 0x582dff0600000000, 0x2eccf09b00000000,
+ 0xb444d6ab00000000, 0xc2a5d93600000000, 0x1980b84a00000000,
+ 0x6f61b7d700000000, 0xafcb7ab200000000, 0xd92a752f00000000,
+ 0x020f145300000000, 0x74ee1bce00000000, 0x825a8f9800000000,
+ 0xf4bb800500000000, 0x2f9ee17900000000, 0x597feee400000000,
+ 0x99d5238100000000, 0xef342c1c00000000, 0x34114d6000000000,
+ 0x42f042fd00000000, 0xf1f7b94100000000, 0x8716b6dc00000000,
+ 0x5c33d7a000000000, 0x2ad2d83d00000000, 0xea78155800000000,
+ 0x9c991ac500000000, 0x47bc7bb900000000, 0x315d742400000000,
+ 0xc7e9e07200000000, 0xb108efef00000000, 0x6a2d8e9300000000,
+ 0x1ccc810e00000000, 0xdc664c6b00000000, 0xaa8743f600000000,
+ 0x71a2228a00000000, 0x07432d1700000000, 0x9dcb0b2700000000,
+ 0xeb2a04ba00000000, 0x300f65c600000000, 0x46ee6a5b00000000,
+ 0x8644a73e00000000, 0xf0a5a8a300000000, 0x2b80c9df00000000,
+ 0x5d61c64200000000, 0xabd5521400000000, 0xdd345d8900000000,
+ 0x06113cf500000000, 0x70f0336800000000, 0xb05afe0d00000000,
+ 0xc6bbf19000000000, 0x1d9e90ec00000000, 0x6b7f9f7100000000,
+ 0x298fdd8c00000000, 0x5f6ed21100000000, 0x844bb36d00000000,
+ 0xf2aabcf000000000, 0x3200719500000000, 0x44e17e0800000000,
+ 0x9fc41f7400000000, 0xe92510e900000000, 0x1f9184bf00000000,
+ 0x69708b2200000000, 0xb255ea5e00000000, 0xc4b4e5c300000000,
+ 0x041e28a600000000, 0x72ff273b00000000, 0xa9da464700000000,
+ 0xdf3b49da00000000, 0x45b36fea00000000, 0x3352607700000000,
+ 0xe877010b00000000, 0x9e960e9600000000, 0x5e3cc3f300000000,
+ 0x28ddcc6e00000000, 0xf3f8ad1200000000, 0x8519a28f00000000,
+ 0x73ad36d900000000, 0x054c394400000000, 0xde69583800000000,
+ 0xa88857a500000000, 0x68229ac000000000, 0x1ec3955d00000000,
+ 0xc5e6f42100000000, 0xb307fbbc00000000, 0xe2ef738300000000,
+ 0x940e7c1e00000000, 0x4f2b1d6200000000, 0x39ca12ff00000000,
+ 0xf960df9a00000000, 0x8f81d00700000000, 0x54a4b17b00000000,
+ 0x2245bee600000000, 0xd4f12ab000000000, 0xa210252d00000000,
+ 0x7935445100000000, 0x0fd44bcc00000000, 0xcf7e86a900000000,
+ 0xb99f893400000000, 0x62bae84800000000, 0x145be7d500000000,
+ 0x8ed3c1e500000000, 0xf832ce7800000000, 0x2317af0400000000,
+ 0x55f6a09900000000, 0x955c6dfc00000000, 0xe3bd626100000000,
+ 0x3898031d00000000, 0x4e790c8000000000, 0xb8cd98d600000000,
+ 0xce2c974b00000000, 0x1509f63700000000, 0x63e8f9aa00000000,
+ 0xa34234cf00000000, 0xd5a33b5200000000, 0x0e865a2e00000000,
+ 0x786755b300000000, 0x3a97174e00000000, 0x4c7618d300000000,
+ 0x975379af00000000, 0xe1b2763200000000, 0x2118bb5700000000,
+ 0x57f9b4ca00000000, 0x8cdcd5b600000000, 0xfa3dda2b00000000,
+ 0x0c894e7d00000000, 0x7a6841e000000000, 0xa14d209c00000000,
+ 0xd7ac2f0100000000, 0x1706e26400000000, 0x61e7edf900000000,
+ 0xbac28c8500000000, 0xcc23831800000000, 0x56aba52800000000,
+ 0x204aaab500000000, 0xfb6fcbc900000000, 0x8d8ec45400000000,
+ 0x4d24093100000000, 0x3bc506ac00000000, 0xe0e067d000000000,
+ 0x9601684d00000000, 0x60b5fc1b00000000, 0x1654f38600000000,
+ 0xcd7192fa00000000, 0xbb909d6700000000, 0x7b3a500200000000,
+ 0x0ddb5f9f00000000, 0xd6fe3ee300000000, 0xa01f317e00000000,
+ 0x1318cac200000000, 0x65f9c55f00000000, 0xbedca42300000000,
+ 0xc83dabbe00000000, 0x089766db00000000, 0x7e76694600000000,
+ 0xa553083a00000000, 0xd3b207a700000000, 0x250693f100000000,
+ 0x53e79c6c00000000, 0x88c2fd1000000000, 0xfe23f28d00000000,
+ 0x3e893fe800000000, 0x4868307500000000, 0x934d510900000000,
+ 0xe5ac5e9400000000, 0x7f2478a400000000, 0x09c5773900000000,
+ 0xd2e0164500000000, 0xa40119d800000000, 0x64abd4bd00000000,
+ 0x124adb2000000000, 0xc96fba5c00000000, 0xbf8eb5c100000000,
+ 0x493a219700000000, 0x3fdb2e0a00000000, 0xe4fe4f7600000000,
+ 0x921f40eb00000000, 0x52b58d8e00000000, 0x2454821300000000,
+ 0xff71e36f00000000, 0x8990ecf200000000, 0xcb60ae0f00000000,
+ 0xbd81a19200000000, 0x66a4c0ee00000000, 0x1045cf7300000000,
+ 0xd0ef021600000000, 0xa60e0d8b00000000, 0x7d2b6cf700000000,
+ 0x0bca636a00000000, 0xfd7ef73c00000000, 0x8b9ff8a100000000,
+ 0x50ba99dd00000000, 0x265b964000000000, 0xe6f15b2500000000,
+ 0x901054b800000000, 0x4b3535c400000000, 0x3dd43a5900000000,
+ 0xa75c1c6900000000, 0xd1bd13f400000000, 0x0a98728800000000,
+ 0x7c797d1500000000, 0xbcd3b07000000000, 0xca32bfed00000000,
+ 0x1117de9100000000, 0x67f6d10c00000000, 0x9142455a00000000,
+ 0xe7a34ac700000000, 0x3c862bbb00000000, 0x4a67242600000000,
+ 0x8acde94300000000, 0xfc2ce6de00000000, 0x270987a200000000,
+ 0x51e8883f00000000},
+ {0x0000000000000000, 0xe8dbfbb900000000, 0x91b186a800000000,
+ 0x796a7d1100000000, 0x63657c8a00000000, 0x8bbe873300000000,
+ 0xf2d4fa2200000000, 0x1a0f019b00000000, 0x87cc89cf00000000,
+ 0x6f17727600000000, 0x167d0f6700000000, 0xfea6f4de00000000,
+ 0xe4a9f54500000000, 0x0c720efc00000000, 0x751873ed00000000,
+ 0x9dc3885400000000, 0x4f9f624400000000, 0xa74499fd00000000,
+ 0xde2ee4ec00000000, 0x36f51f5500000000, 0x2cfa1ece00000000,
+ 0xc421e57700000000, 0xbd4b986600000000, 0x559063df00000000,
+ 0xc853eb8b00000000, 0x2088103200000000, 0x59e26d2300000000,
+ 0xb139969a00000000, 0xab36970100000000, 0x43ed6cb800000000,
+ 0x3a8711a900000000, 0xd25cea1000000000, 0x9e3ec58800000000,
+ 0x76e53e3100000000, 0x0f8f432000000000, 0xe754b89900000000,
+ 0xfd5bb90200000000, 0x158042bb00000000, 0x6cea3faa00000000,
+ 0x8431c41300000000, 0x19f24c4700000000, 0xf129b7fe00000000,
+ 0x8843caef00000000, 0x6098315600000000, 0x7a9730cd00000000,
+ 0x924ccb7400000000, 0xeb26b66500000000, 0x03fd4ddc00000000,
+ 0xd1a1a7cc00000000, 0x397a5c7500000000, 0x4010216400000000,
+ 0xa8cbdadd00000000, 0xb2c4db4600000000, 0x5a1f20ff00000000,
+ 0x23755dee00000000, 0xcbaea65700000000, 0x566d2e0300000000,
+ 0xbeb6d5ba00000000, 0xc7dca8ab00000000, 0x2f07531200000000,
+ 0x3508528900000000, 0xddd3a93000000000, 0xa4b9d42100000000,
+ 0x4c622f9800000000, 0x7d7bfbca00000000, 0x95a0007300000000,
+ 0xecca7d6200000000, 0x041186db00000000, 0x1e1e874000000000,
+ 0xf6c57cf900000000, 0x8faf01e800000000, 0x6774fa5100000000,
+ 0xfab7720500000000, 0x126c89bc00000000, 0x6b06f4ad00000000,
+ 0x83dd0f1400000000, 0x99d20e8f00000000, 0x7109f53600000000,
+ 0x0863882700000000, 0xe0b8739e00000000, 0x32e4998e00000000,
+ 0xda3f623700000000, 0xa3551f2600000000, 0x4b8ee49f00000000,
+ 0x5181e50400000000, 0xb95a1ebd00000000, 0xc03063ac00000000,
+ 0x28eb981500000000, 0xb528104100000000, 0x5df3ebf800000000,
+ 0x249996e900000000, 0xcc426d5000000000, 0xd64d6ccb00000000,
+ 0x3e96977200000000, 0x47fcea6300000000, 0xaf2711da00000000,
+ 0xe3453e4200000000, 0x0b9ec5fb00000000, 0x72f4b8ea00000000,
+ 0x9a2f435300000000, 0x802042c800000000, 0x68fbb97100000000,
+ 0x1191c46000000000, 0xf94a3fd900000000, 0x6489b78d00000000,
+ 0x8c524c3400000000, 0xf538312500000000, 0x1de3ca9c00000000,
+ 0x07eccb0700000000, 0xef3730be00000000, 0x965d4daf00000000,
+ 0x7e86b61600000000, 0xacda5c0600000000, 0x4401a7bf00000000,
+ 0x3d6bdaae00000000, 0xd5b0211700000000, 0xcfbf208c00000000,
+ 0x2764db3500000000, 0x5e0ea62400000000, 0xb6d55d9d00000000,
+ 0x2b16d5c900000000, 0xc3cd2e7000000000, 0xbaa7536100000000,
+ 0x527ca8d800000000, 0x4873a94300000000, 0xa0a852fa00000000,
+ 0xd9c22feb00000000, 0x3119d45200000000, 0xbbf0874e00000000,
+ 0x532b7cf700000000, 0x2a4101e600000000, 0xc29afa5f00000000,
+ 0xd895fbc400000000, 0x304e007d00000000, 0x49247d6c00000000,
+ 0xa1ff86d500000000, 0x3c3c0e8100000000, 0xd4e7f53800000000,
+ 0xad8d882900000000, 0x4556739000000000, 0x5f59720b00000000,
+ 0xb78289b200000000, 0xcee8f4a300000000, 0x26330f1a00000000,
+ 0xf46fe50a00000000, 0x1cb41eb300000000, 0x65de63a200000000,
+ 0x8d05981b00000000, 0x970a998000000000, 0x7fd1623900000000,
+ 0x06bb1f2800000000, 0xee60e49100000000, 0x73a36cc500000000,
+ 0x9b78977c00000000, 0xe212ea6d00000000, 0x0ac911d400000000,
+ 0x10c6104f00000000, 0xf81debf600000000, 0x817796e700000000,
+ 0x69ac6d5e00000000, 0x25ce42c600000000, 0xcd15b97f00000000,
+ 0xb47fc46e00000000, 0x5ca43fd700000000, 0x46ab3e4c00000000,
+ 0xae70c5f500000000, 0xd71ab8e400000000, 0x3fc1435d00000000,
+ 0xa202cb0900000000, 0x4ad930b000000000, 0x33b34da100000000,
+ 0xdb68b61800000000, 0xc167b78300000000, 0x29bc4c3a00000000,
+ 0x50d6312b00000000, 0xb80dca9200000000, 0x6a51208200000000,
+ 0x828adb3b00000000, 0xfbe0a62a00000000, 0x133b5d9300000000,
+ 0x09345c0800000000, 0xe1efa7b100000000, 0x9885daa000000000,
+ 0x705e211900000000, 0xed9da94d00000000, 0x054652f400000000,
+ 0x7c2c2fe500000000, 0x94f7d45c00000000, 0x8ef8d5c700000000,
+ 0x66232e7e00000000, 0x1f49536f00000000, 0xf792a8d600000000,
+ 0xc68b7c8400000000, 0x2e50873d00000000, 0x573afa2c00000000,
+ 0xbfe1019500000000, 0xa5ee000e00000000, 0x4d35fbb700000000,
+ 0x345f86a600000000, 0xdc847d1f00000000, 0x4147f54b00000000,
+ 0xa99c0ef200000000, 0xd0f673e300000000, 0x382d885a00000000,
+ 0x222289c100000000, 0xcaf9727800000000, 0xb3930f6900000000,
+ 0x5b48f4d000000000, 0x89141ec000000000, 0x61cfe57900000000,
+ 0x18a5986800000000, 0xf07e63d100000000, 0xea71624a00000000,
+ 0x02aa99f300000000, 0x7bc0e4e200000000, 0x931b1f5b00000000,
+ 0x0ed8970f00000000, 0xe6036cb600000000, 0x9f6911a700000000,
+ 0x77b2ea1e00000000, 0x6dbdeb8500000000, 0x8566103c00000000,
+ 0xfc0c6d2d00000000, 0x14d7969400000000, 0x58b5b90c00000000,
+ 0xb06e42b500000000, 0xc9043fa400000000, 0x21dfc41d00000000,
+ 0x3bd0c58600000000, 0xd30b3e3f00000000, 0xaa61432e00000000,
+ 0x42bab89700000000, 0xdf7930c300000000, 0x37a2cb7a00000000,
+ 0x4ec8b66b00000000, 0xa6134dd200000000, 0xbc1c4c4900000000,
+ 0x54c7b7f000000000, 0x2dadcae100000000, 0xc576315800000000,
+ 0x172adb4800000000, 0xfff120f100000000, 0x869b5de000000000,
+ 0x6e40a65900000000, 0x744fa7c200000000, 0x9c945c7b00000000,
+ 0xe5fe216a00000000, 0x0d25dad300000000, 0x90e6528700000000,
+ 0x783da93e00000000, 0x0157d42f00000000, 0xe98c2f9600000000,
+ 0xf3832e0d00000000, 0x1b58d5b400000000, 0x6232a8a500000000,
+ 0x8ae9531c00000000},
+ {0x0000000000000000, 0x919168ae00000000, 0x6325a08700000000,
+ 0xf2b4c82900000000, 0x874c31d400000000, 0x16dd597a00000000,
+ 0xe469915300000000, 0x75f8f9fd00000000, 0x4f9f137300000000,
+ 0xde0e7bdd00000000, 0x2cbab3f400000000, 0xbd2bdb5a00000000,
+ 0xc8d322a700000000, 0x59424a0900000000, 0xabf6822000000000,
+ 0x3a67ea8e00000000, 0x9e3e27e600000000, 0x0faf4f4800000000,
+ 0xfd1b876100000000, 0x6c8aefcf00000000, 0x1972163200000000,
+ 0x88e37e9c00000000, 0x7a57b6b500000000, 0xebc6de1b00000000,
+ 0xd1a1349500000000, 0x40305c3b00000000, 0xb284941200000000,
+ 0x2315fcbc00000000, 0x56ed054100000000, 0xc77c6def00000000,
+ 0x35c8a5c600000000, 0xa459cd6800000000, 0x7d7b3f1700000000,
+ 0xecea57b900000000, 0x1e5e9f9000000000, 0x8fcff73e00000000,
+ 0xfa370ec300000000, 0x6ba6666d00000000, 0x9912ae4400000000,
+ 0x0883c6ea00000000, 0x32e42c6400000000, 0xa37544ca00000000,
+ 0x51c18ce300000000, 0xc050e44d00000000, 0xb5a81db000000000,
+ 0x2439751e00000000, 0xd68dbd3700000000, 0x471cd59900000000,
+ 0xe34518f100000000, 0x72d4705f00000000, 0x8060b87600000000,
+ 0x11f1d0d800000000, 0x6409292500000000, 0xf598418b00000000,
+ 0x072c89a200000000, 0x96bde10c00000000, 0xacda0b8200000000,
+ 0x3d4b632c00000000, 0xcfffab0500000000, 0x5e6ec3ab00000000,
+ 0x2b963a5600000000, 0xba0752f800000000, 0x48b39ad100000000,
+ 0xd922f27f00000000, 0xfaf67e2e00000000, 0x6b67168000000000,
+ 0x99d3dea900000000, 0x0842b60700000000, 0x7dba4ffa00000000,
+ 0xec2b275400000000, 0x1e9fef7d00000000, 0x8f0e87d300000000,
+ 0xb5696d5d00000000, 0x24f805f300000000, 0xd64ccdda00000000,
+ 0x47dda57400000000, 0x32255c8900000000, 0xa3b4342700000000,
+ 0x5100fc0e00000000, 0xc09194a000000000, 0x64c859c800000000,
+ 0xf559316600000000, 0x07edf94f00000000, 0x967c91e100000000,
+ 0xe384681c00000000, 0x721500b200000000, 0x80a1c89b00000000,
+ 0x1130a03500000000, 0x2b574abb00000000, 0xbac6221500000000,
+ 0x4872ea3c00000000, 0xd9e3829200000000, 0xac1b7b6f00000000,
+ 0x3d8a13c100000000, 0xcf3edbe800000000, 0x5eafb34600000000,
+ 0x878d413900000000, 0x161c299700000000, 0xe4a8e1be00000000,
+ 0x7539891000000000, 0x00c170ed00000000, 0x9150184300000000,
+ 0x63e4d06a00000000, 0xf275b8c400000000, 0xc812524a00000000,
+ 0x59833ae400000000, 0xab37f2cd00000000, 0x3aa69a6300000000,
+ 0x4f5e639e00000000, 0xdecf0b3000000000, 0x2c7bc31900000000,
+ 0xbdeaabb700000000, 0x19b366df00000000, 0x88220e7100000000,
+ 0x7a96c65800000000, 0xeb07aef600000000, 0x9eff570b00000000,
+ 0x0f6e3fa500000000, 0xfddaf78c00000000, 0x6c4b9f2200000000,
+ 0x562c75ac00000000, 0xc7bd1d0200000000, 0x3509d52b00000000,
+ 0xa498bd8500000000, 0xd160447800000000, 0x40f12cd600000000,
+ 0xb245e4ff00000000, 0x23d48c5100000000, 0xf4edfd5c00000000,
+ 0x657c95f200000000, 0x97c85ddb00000000, 0x0659357500000000,
+ 0x73a1cc8800000000, 0xe230a42600000000, 0x10846c0f00000000,
+ 0x811504a100000000, 0xbb72ee2f00000000, 0x2ae3868100000000,
+ 0xd8574ea800000000, 0x49c6260600000000, 0x3c3edffb00000000,
+ 0xadafb75500000000, 0x5f1b7f7c00000000, 0xce8a17d200000000,
+ 0x6ad3daba00000000, 0xfb42b21400000000, 0x09f67a3d00000000,
+ 0x9867129300000000, 0xed9feb6e00000000, 0x7c0e83c000000000,
+ 0x8eba4be900000000, 0x1f2b234700000000, 0x254cc9c900000000,
+ 0xb4dda16700000000, 0x4669694e00000000, 0xd7f801e000000000,
+ 0xa200f81d00000000, 0x339190b300000000, 0xc125589a00000000,
+ 0x50b4303400000000, 0x8996c24b00000000, 0x1807aae500000000,
+ 0xeab362cc00000000, 0x7b220a6200000000, 0x0edaf39f00000000,
+ 0x9f4b9b3100000000, 0x6dff531800000000, 0xfc6e3bb600000000,
+ 0xc609d13800000000, 0x5798b99600000000, 0xa52c71bf00000000,
+ 0x34bd191100000000, 0x4145e0ec00000000, 0xd0d4884200000000,
+ 0x2260406b00000000, 0xb3f128c500000000, 0x17a8e5ad00000000,
+ 0x86398d0300000000, 0x748d452a00000000, 0xe51c2d8400000000,
+ 0x90e4d47900000000, 0x0175bcd700000000, 0xf3c174fe00000000,
+ 0x62501c5000000000, 0x5837f6de00000000, 0xc9a69e7000000000,
+ 0x3b12565900000000, 0xaa833ef700000000, 0xdf7bc70a00000000,
+ 0x4eeaafa400000000, 0xbc5e678d00000000, 0x2dcf0f2300000000,
+ 0x0e1b837200000000, 0x9f8aebdc00000000, 0x6d3e23f500000000,
+ 0xfcaf4b5b00000000, 0x8957b2a600000000, 0x18c6da0800000000,
+ 0xea72122100000000, 0x7be37a8f00000000, 0x4184900100000000,
+ 0xd015f8af00000000, 0x22a1308600000000, 0xb330582800000000,
+ 0xc6c8a1d500000000, 0x5759c97b00000000, 0xa5ed015200000000,
+ 0x347c69fc00000000, 0x9025a49400000000, 0x01b4cc3a00000000,
+ 0xf300041300000000, 0x62916cbd00000000, 0x1769954000000000,
+ 0x86f8fdee00000000, 0x744c35c700000000, 0xe5dd5d6900000000,
+ 0xdfbab7e700000000, 0x4e2bdf4900000000, 0xbc9f176000000000,
+ 0x2d0e7fce00000000, 0x58f6863300000000, 0xc967ee9d00000000,
+ 0x3bd326b400000000, 0xaa424e1a00000000, 0x7360bc6500000000,
+ 0xe2f1d4cb00000000, 0x10451ce200000000, 0x81d4744c00000000,
+ 0xf42c8db100000000, 0x65bde51f00000000, 0x97092d3600000000,
+ 0x0698459800000000, 0x3cffaf1600000000, 0xad6ec7b800000000,
+ 0x5fda0f9100000000, 0xce4b673f00000000, 0xbbb39ec200000000,
+ 0x2a22f66c00000000, 0xd8963e4500000000, 0x490756eb00000000,
+ 0xed5e9b8300000000, 0x7ccff32d00000000, 0x8e7b3b0400000000,
+ 0x1fea53aa00000000, 0x6a12aa5700000000, 0xfb83c2f900000000,
+ 0x09370ad000000000, 0x98a6627e00000000, 0xa2c188f000000000,
+ 0x3350e05e00000000, 0xc1e4287700000000, 0x507540d900000000,
+ 0x258db92400000000, 0xb41cd18a00000000, 0x46a819a300000000,
+ 0xd739710d00000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xccaa009e, 0x4225077d, 0x8e8f07e3, 0x844a0efa,
+ 0x48e00e64, 0xc66f0987, 0x0ac50919, 0xd3e51bb5, 0x1f4f1b2b,
+ 0x91c01cc8, 0x5d6a1c56, 0x57af154f, 0x9b0515d1, 0x158a1232,
+ 0xd92012ac, 0x7cbb312b, 0xb01131b5, 0x3e9e3656, 0xf23436c8,
+ 0xf8f13fd1, 0x345b3f4f, 0xbad438ac, 0x767e3832, 0xaf5e2a9e,
+ 0x63f42a00, 0xed7b2de3, 0x21d12d7d, 0x2b142464, 0xe7be24fa,
+ 0x69312319, 0xa59b2387, 0xf9766256, 0x35dc62c8, 0xbb53652b,
+ 0x77f965b5, 0x7d3c6cac, 0xb1966c32, 0x3f196bd1, 0xf3b36b4f,
+ 0x2a9379e3, 0xe639797d, 0x68b67e9e, 0xa41c7e00, 0xaed97719,
+ 0x62737787, 0xecfc7064, 0x205670fa, 0x85cd537d, 0x496753e3,
+ 0xc7e85400, 0x0b42549e, 0x01875d87, 0xcd2d5d19, 0x43a25afa,
+ 0x8f085a64, 0x562848c8, 0x9a824856, 0x140d4fb5, 0xd8a74f2b,
+ 0xd2624632, 0x1ec846ac, 0x9047414f, 0x5ced41d1, 0x299dc2ed,
+ 0xe537c273, 0x6bb8c590, 0xa712c50e, 0xadd7cc17, 0x617dcc89,
+ 0xeff2cb6a, 0x2358cbf4, 0xfa78d958, 0x36d2d9c6, 0xb85dde25,
+ 0x74f7debb, 0x7e32d7a2, 0xb298d73c, 0x3c17d0df, 0xf0bdd041,
+ 0x5526f3c6, 0x998cf358, 0x1703f4bb, 0xdba9f425, 0xd16cfd3c,
+ 0x1dc6fda2, 0x9349fa41, 0x5fe3fadf, 0x86c3e873, 0x4a69e8ed,
+ 0xc4e6ef0e, 0x084cef90, 0x0289e689, 0xce23e617, 0x40ace1f4,
+ 0x8c06e16a, 0xd0eba0bb, 0x1c41a025, 0x92cea7c6, 0x5e64a758,
+ 0x54a1ae41, 0x980baedf, 0x1684a93c, 0xda2ea9a2, 0x030ebb0e,
+ 0xcfa4bb90, 0x412bbc73, 0x8d81bced, 0x8744b5f4, 0x4beeb56a,
+ 0xc561b289, 0x09cbb217, 0xac509190, 0x60fa910e, 0xee7596ed,
+ 0x22df9673, 0x281a9f6a, 0xe4b09ff4, 0x6a3f9817, 0xa6959889,
+ 0x7fb58a25, 0xb31f8abb, 0x3d908d58, 0xf13a8dc6, 0xfbff84df,
+ 0x37558441, 0xb9da83a2, 0x7570833c, 0x533b85da, 0x9f918544,
+ 0x111e82a7, 0xddb48239, 0xd7718b20, 0x1bdb8bbe, 0x95548c5d,
+ 0x59fe8cc3, 0x80de9e6f, 0x4c749ef1, 0xc2fb9912, 0x0e51998c,
+ 0x04949095, 0xc83e900b, 0x46b197e8, 0x8a1b9776, 0x2f80b4f1,
+ 0xe32ab46f, 0x6da5b38c, 0xa10fb312, 0xabcaba0b, 0x6760ba95,
+ 0xe9efbd76, 0x2545bde8, 0xfc65af44, 0x30cfafda, 0xbe40a839,
+ 0x72eaa8a7, 0x782fa1be, 0xb485a120, 0x3a0aa6c3, 0xf6a0a65d,
+ 0xaa4de78c, 0x66e7e712, 0xe868e0f1, 0x24c2e06f, 0x2e07e976,
+ 0xe2ade9e8, 0x6c22ee0b, 0xa088ee95, 0x79a8fc39, 0xb502fca7,
+ 0x3b8dfb44, 0xf727fbda, 0xfde2f2c3, 0x3148f25d, 0xbfc7f5be,
+ 0x736df520, 0xd6f6d6a7, 0x1a5cd639, 0x94d3d1da, 0x5879d144,
+ 0x52bcd85d, 0x9e16d8c3, 0x1099df20, 0xdc33dfbe, 0x0513cd12,
+ 0xc9b9cd8c, 0x4736ca6f, 0x8b9ccaf1, 0x8159c3e8, 0x4df3c376,
+ 0xc37cc495, 0x0fd6c40b, 0x7aa64737, 0xb60c47a9, 0x3883404a,
+ 0xf42940d4, 0xfeec49cd, 0x32464953, 0xbcc94eb0, 0x70634e2e,
+ 0xa9435c82, 0x65e95c1c, 0xeb665bff, 0x27cc5b61, 0x2d095278,
+ 0xe1a352e6, 0x6f2c5505, 0xa386559b, 0x061d761c, 0xcab77682,
+ 0x44387161, 0x889271ff, 0x825778e6, 0x4efd7878, 0xc0727f9b,
+ 0x0cd87f05, 0xd5f86da9, 0x19526d37, 0x97dd6ad4, 0x5b776a4a,
+ 0x51b26353, 0x9d1863cd, 0x1397642e, 0xdf3d64b0, 0x83d02561,
+ 0x4f7a25ff, 0xc1f5221c, 0x0d5f2282, 0x079a2b9b, 0xcb302b05,
+ 0x45bf2ce6, 0x89152c78, 0x50353ed4, 0x9c9f3e4a, 0x121039a9,
+ 0xdeba3937, 0xd47f302e, 0x18d530b0, 0x965a3753, 0x5af037cd,
+ 0xff6b144a, 0x33c114d4, 0xbd4e1337, 0x71e413a9, 0x7b211ab0,
+ 0xb78b1a2e, 0x39041dcd, 0xf5ae1d53, 0x2c8e0fff, 0xe0240f61,
+ 0x6eab0882, 0xa201081c, 0xa8c40105, 0x646e019b, 0xeae10678,
+ 0x264b06e6},
+ {0x00000000, 0xa6770bb4, 0x979f1129, 0x31e81a9d, 0xf44f2413,
+ 0x52382fa7, 0x63d0353a, 0xc5a73e8e, 0x33ef4e67, 0x959845d3,
+ 0xa4705f4e, 0x020754fa, 0xc7a06a74, 0x61d761c0, 0x503f7b5d,
+ 0xf64870e9, 0x67de9cce, 0xc1a9977a, 0xf0418de7, 0x56368653,
+ 0x9391b8dd, 0x35e6b369, 0x040ea9f4, 0xa279a240, 0x5431d2a9,
+ 0xf246d91d, 0xc3aec380, 0x65d9c834, 0xa07ef6ba, 0x0609fd0e,
+ 0x37e1e793, 0x9196ec27, 0xcfbd399c, 0x69ca3228, 0x582228b5,
+ 0xfe552301, 0x3bf21d8f, 0x9d85163b, 0xac6d0ca6, 0x0a1a0712,
+ 0xfc5277fb, 0x5a257c4f, 0x6bcd66d2, 0xcdba6d66, 0x081d53e8,
+ 0xae6a585c, 0x9f8242c1, 0x39f54975, 0xa863a552, 0x0e14aee6,
+ 0x3ffcb47b, 0x998bbfcf, 0x5c2c8141, 0xfa5b8af5, 0xcbb39068,
+ 0x6dc49bdc, 0x9b8ceb35, 0x3dfbe081, 0x0c13fa1c, 0xaa64f1a8,
+ 0x6fc3cf26, 0xc9b4c492, 0xf85cde0f, 0x5e2bd5bb, 0x440b7579,
+ 0xe27c7ecd, 0xd3946450, 0x75e36fe4, 0xb044516a, 0x16335ade,
+ 0x27db4043, 0x81ac4bf7, 0x77e43b1e, 0xd19330aa, 0xe07b2a37,
+ 0x460c2183, 0x83ab1f0d, 0x25dc14b9, 0x14340e24, 0xb2430590,
+ 0x23d5e9b7, 0x85a2e203, 0xb44af89e, 0x123df32a, 0xd79acda4,
+ 0x71edc610, 0x4005dc8d, 0xe672d739, 0x103aa7d0, 0xb64dac64,
+ 0x87a5b6f9, 0x21d2bd4d, 0xe47583c3, 0x42028877, 0x73ea92ea,
+ 0xd59d995e, 0x8bb64ce5, 0x2dc14751, 0x1c295dcc, 0xba5e5678,
+ 0x7ff968f6, 0xd98e6342, 0xe86679df, 0x4e11726b, 0xb8590282,
+ 0x1e2e0936, 0x2fc613ab, 0x89b1181f, 0x4c162691, 0xea612d25,
+ 0xdb8937b8, 0x7dfe3c0c, 0xec68d02b, 0x4a1fdb9f, 0x7bf7c102,
+ 0xdd80cab6, 0x1827f438, 0xbe50ff8c, 0x8fb8e511, 0x29cfeea5,
+ 0xdf879e4c, 0x79f095f8, 0x48188f65, 0xee6f84d1, 0x2bc8ba5f,
+ 0x8dbfb1eb, 0xbc57ab76, 0x1a20a0c2, 0x8816eaf2, 0x2e61e146,
+ 0x1f89fbdb, 0xb9fef06f, 0x7c59cee1, 0xda2ec555, 0xebc6dfc8,
+ 0x4db1d47c, 0xbbf9a495, 0x1d8eaf21, 0x2c66b5bc, 0x8a11be08,
+ 0x4fb68086, 0xe9c18b32, 0xd82991af, 0x7e5e9a1b, 0xefc8763c,
+ 0x49bf7d88, 0x78576715, 0xde206ca1, 0x1b87522f, 0xbdf0599b,
+ 0x8c184306, 0x2a6f48b2, 0xdc27385b, 0x7a5033ef, 0x4bb82972,
+ 0xedcf22c6, 0x28681c48, 0x8e1f17fc, 0xbff70d61, 0x198006d5,
+ 0x47abd36e, 0xe1dcd8da, 0xd034c247, 0x7643c9f3, 0xb3e4f77d,
+ 0x1593fcc9, 0x247be654, 0x820cede0, 0x74449d09, 0xd23396bd,
+ 0xe3db8c20, 0x45ac8794, 0x800bb91a, 0x267cb2ae, 0x1794a833,
+ 0xb1e3a387, 0x20754fa0, 0x86024414, 0xb7ea5e89, 0x119d553d,
+ 0xd43a6bb3, 0x724d6007, 0x43a57a9a, 0xe5d2712e, 0x139a01c7,
+ 0xb5ed0a73, 0x840510ee, 0x22721b5a, 0xe7d525d4, 0x41a22e60,
+ 0x704a34fd, 0xd63d3f49, 0xcc1d9f8b, 0x6a6a943f, 0x5b828ea2,
+ 0xfdf58516, 0x3852bb98, 0x9e25b02c, 0xafcdaab1, 0x09baa105,
+ 0xfff2d1ec, 0x5985da58, 0x686dc0c5, 0xce1acb71, 0x0bbdf5ff,
+ 0xadcafe4b, 0x9c22e4d6, 0x3a55ef62, 0xabc30345, 0x0db408f1,
+ 0x3c5c126c, 0x9a2b19d8, 0x5f8c2756, 0xf9fb2ce2, 0xc813367f,
+ 0x6e643dcb, 0x982c4d22, 0x3e5b4696, 0x0fb35c0b, 0xa9c457bf,
+ 0x6c636931, 0xca146285, 0xfbfc7818, 0x5d8b73ac, 0x03a0a617,
+ 0xa5d7ada3, 0x943fb73e, 0x3248bc8a, 0xf7ef8204, 0x519889b0,
+ 0x6070932d, 0xc6079899, 0x304fe870, 0x9638e3c4, 0xa7d0f959,
+ 0x01a7f2ed, 0xc400cc63, 0x6277c7d7, 0x539fdd4a, 0xf5e8d6fe,
+ 0x647e3ad9, 0xc209316d, 0xf3e12bf0, 0x55962044, 0x90311eca,
+ 0x3646157e, 0x07ae0fe3, 0xa1d90457, 0x579174be, 0xf1e67f0a,
+ 0xc00e6597, 0x66796e23, 0xa3de50ad, 0x05a95b19, 0x34414184,
+ 0x92364a30},
+ {0x00000000, 0xcb5cd3a5, 0x4dc8a10b, 0x869472ae, 0x9b914216,
+ 0x50cd91b3, 0xd659e31d, 0x1d0530b8, 0xec53826d, 0x270f51c8,
+ 0xa19b2366, 0x6ac7f0c3, 0x77c2c07b, 0xbc9e13de, 0x3a0a6170,
+ 0xf156b2d5, 0x03d6029b, 0xc88ad13e, 0x4e1ea390, 0x85427035,
+ 0x9847408d, 0x531b9328, 0xd58fe186, 0x1ed33223, 0xef8580f6,
+ 0x24d95353, 0xa24d21fd, 0x6911f258, 0x7414c2e0, 0xbf481145,
+ 0x39dc63eb, 0xf280b04e, 0x07ac0536, 0xccf0d693, 0x4a64a43d,
+ 0x81387798, 0x9c3d4720, 0x57619485, 0xd1f5e62b, 0x1aa9358e,
+ 0xebff875b, 0x20a354fe, 0xa6372650, 0x6d6bf5f5, 0x706ec54d,
+ 0xbb3216e8, 0x3da66446, 0xf6fab7e3, 0x047a07ad, 0xcf26d408,
+ 0x49b2a6a6, 0x82ee7503, 0x9feb45bb, 0x54b7961e, 0xd223e4b0,
+ 0x197f3715, 0xe82985c0, 0x23755665, 0xa5e124cb, 0x6ebdf76e,
+ 0x73b8c7d6, 0xb8e41473, 0x3e7066dd, 0xf52cb578, 0x0f580a6c,
+ 0xc404d9c9, 0x4290ab67, 0x89cc78c2, 0x94c9487a, 0x5f959bdf,
+ 0xd901e971, 0x125d3ad4, 0xe30b8801, 0x28575ba4, 0xaec3290a,
+ 0x659ffaaf, 0x789aca17, 0xb3c619b2, 0x35526b1c, 0xfe0eb8b9,
+ 0x0c8e08f7, 0xc7d2db52, 0x4146a9fc, 0x8a1a7a59, 0x971f4ae1,
+ 0x5c439944, 0xdad7ebea, 0x118b384f, 0xe0dd8a9a, 0x2b81593f,
+ 0xad152b91, 0x6649f834, 0x7b4cc88c, 0xb0101b29, 0x36846987,
+ 0xfdd8ba22, 0x08f40f5a, 0xc3a8dcff, 0x453cae51, 0x8e607df4,
+ 0x93654d4c, 0x58399ee9, 0xdeadec47, 0x15f13fe2, 0xe4a78d37,
+ 0x2ffb5e92, 0xa96f2c3c, 0x6233ff99, 0x7f36cf21, 0xb46a1c84,
+ 0x32fe6e2a, 0xf9a2bd8f, 0x0b220dc1, 0xc07ede64, 0x46eaacca,
+ 0x8db67f6f, 0x90b34fd7, 0x5bef9c72, 0xdd7beedc, 0x16273d79,
+ 0xe7718fac, 0x2c2d5c09, 0xaab92ea7, 0x61e5fd02, 0x7ce0cdba,
+ 0xb7bc1e1f, 0x31286cb1, 0xfa74bf14, 0x1eb014d8, 0xd5ecc77d,
+ 0x5378b5d3, 0x98246676, 0x852156ce, 0x4e7d856b, 0xc8e9f7c5,
+ 0x03b52460, 0xf2e396b5, 0x39bf4510, 0xbf2b37be, 0x7477e41b,
+ 0x6972d4a3, 0xa22e0706, 0x24ba75a8, 0xefe6a60d, 0x1d661643,
+ 0xd63ac5e6, 0x50aeb748, 0x9bf264ed, 0x86f75455, 0x4dab87f0,
+ 0xcb3ff55e, 0x006326fb, 0xf135942e, 0x3a69478b, 0xbcfd3525,
+ 0x77a1e680, 0x6aa4d638, 0xa1f8059d, 0x276c7733, 0xec30a496,
+ 0x191c11ee, 0xd240c24b, 0x54d4b0e5, 0x9f886340, 0x828d53f8,
+ 0x49d1805d, 0xcf45f2f3, 0x04192156, 0xf54f9383, 0x3e134026,
+ 0xb8873288, 0x73dbe12d, 0x6eded195, 0xa5820230, 0x2316709e,
+ 0xe84aa33b, 0x1aca1375, 0xd196c0d0, 0x5702b27e, 0x9c5e61db,
+ 0x815b5163, 0x4a0782c6, 0xcc93f068, 0x07cf23cd, 0xf6999118,
+ 0x3dc542bd, 0xbb513013, 0x700de3b6, 0x6d08d30e, 0xa65400ab,
+ 0x20c07205, 0xeb9ca1a0, 0x11e81eb4, 0xdab4cd11, 0x5c20bfbf,
+ 0x977c6c1a, 0x8a795ca2, 0x41258f07, 0xc7b1fda9, 0x0ced2e0c,
+ 0xfdbb9cd9, 0x36e74f7c, 0xb0733dd2, 0x7b2fee77, 0x662adecf,
+ 0xad760d6a, 0x2be27fc4, 0xe0beac61, 0x123e1c2f, 0xd962cf8a,
+ 0x5ff6bd24, 0x94aa6e81, 0x89af5e39, 0x42f38d9c, 0xc467ff32,
+ 0x0f3b2c97, 0xfe6d9e42, 0x35314de7, 0xb3a53f49, 0x78f9ecec,
+ 0x65fcdc54, 0xaea00ff1, 0x28347d5f, 0xe368aefa, 0x16441b82,
+ 0xdd18c827, 0x5b8cba89, 0x90d0692c, 0x8dd55994, 0x46898a31,
+ 0xc01df89f, 0x0b412b3a, 0xfa1799ef, 0x314b4a4a, 0xb7df38e4,
+ 0x7c83eb41, 0x6186dbf9, 0xaada085c, 0x2c4e7af2, 0xe712a957,
+ 0x15921919, 0xdececabc, 0x585ab812, 0x93066bb7, 0x8e035b0f,
+ 0x455f88aa, 0xc3cbfa04, 0x089729a1, 0xf9c19b74, 0x329d48d1,
+ 0xb4093a7f, 0x7f55e9da, 0x6250d962, 0xa90c0ac7, 0x2f987869,
+ 0xe4c4abcc},
+ {0x00000000, 0x3d6029b0, 0x7ac05360, 0x47a07ad0, 0xf580a6c0,
+ 0xc8e08f70, 0x8f40f5a0, 0xb220dc10, 0x30704bc1, 0x0d106271,
+ 0x4ab018a1, 0x77d03111, 0xc5f0ed01, 0xf890c4b1, 0xbf30be61,
+ 0x825097d1, 0x60e09782, 0x5d80be32, 0x1a20c4e2, 0x2740ed52,
+ 0x95603142, 0xa80018f2, 0xefa06222, 0xd2c04b92, 0x5090dc43,
+ 0x6df0f5f3, 0x2a508f23, 0x1730a693, 0xa5107a83, 0x98705333,
+ 0xdfd029e3, 0xe2b00053, 0xc1c12f04, 0xfca106b4, 0xbb017c64,
+ 0x866155d4, 0x344189c4, 0x0921a074, 0x4e81daa4, 0x73e1f314,
+ 0xf1b164c5, 0xccd14d75, 0x8b7137a5, 0xb6111e15, 0x0431c205,
+ 0x3951ebb5, 0x7ef19165, 0x4391b8d5, 0xa121b886, 0x9c419136,
+ 0xdbe1ebe6, 0xe681c256, 0x54a11e46, 0x69c137f6, 0x2e614d26,
+ 0x13016496, 0x9151f347, 0xac31daf7, 0xeb91a027, 0xd6f18997,
+ 0x64d15587, 0x59b17c37, 0x1e1106e7, 0x23712f57, 0x58f35849,
+ 0x659371f9, 0x22330b29, 0x1f532299, 0xad73fe89, 0x9013d739,
+ 0xd7b3ade9, 0xead38459, 0x68831388, 0x55e33a38, 0x124340e8,
+ 0x2f236958, 0x9d03b548, 0xa0639cf8, 0xe7c3e628, 0xdaa3cf98,
+ 0x3813cfcb, 0x0573e67b, 0x42d39cab, 0x7fb3b51b, 0xcd93690b,
+ 0xf0f340bb, 0xb7533a6b, 0x8a3313db, 0x0863840a, 0x3503adba,
+ 0x72a3d76a, 0x4fc3feda, 0xfde322ca, 0xc0830b7a, 0x872371aa,
+ 0xba43581a, 0x9932774d, 0xa4525efd, 0xe3f2242d, 0xde920d9d,
+ 0x6cb2d18d, 0x51d2f83d, 0x167282ed, 0x2b12ab5d, 0xa9423c8c,
+ 0x9422153c, 0xd3826fec, 0xeee2465c, 0x5cc29a4c, 0x61a2b3fc,
+ 0x2602c92c, 0x1b62e09c, 0xf9d2e0cf, 0xc4b2c97f, 0x8312b3af,
+ 0xbe729a1f, 0x0c52460f, 0x31326fbf, 0x7692156f, 0x4bf23cdf,
+ 0xc9a2ab0e, 0xf4c282be, 0xb362f86e, 0x8e02d1de, 0x3c220dce,
+ 0x0142247e, 0x46e25eae, 0x7b82771e, 0xb1e6b092, 0x8c869922,
+ 0xcb26e3f2, 0xf646ca42, 0x44661652, 0x79063fe2, 0x3ea64532,
+ 0x03c66c82, 0x8196fb53, 0xbcf6d2e3, 0xfb56a833, 0xc6368183,
+ 0x74165d93, 0x49767423, 0x0ed60ef3, 0x33b62743, 0xd1062710,
+ 0xec660ea0, 0xabc67470, 0x96a65dc0, 0x248681d0, 0x19e6a860,
+ 0x5e46d2b0, 0x6326fb00, 0xe1766cd1, 0xdc164561, 0x9bb63fb1,
+ 0xa6d61601, 0x14f6ca11, 0x2996e3a1, 0x6e369971, 0x5356b0c1,
+ 0x70279f96, 0x4d47b626, 0x0ae7ccf6, 0x3787e546, 0x85a73956,
+ 0xb8c710e6, 0xff676a36, 0xc2074386, 0x4057d457, 0x7d37fde7,
+ 0x3a978737, 0x07f7ae87, 0xb5d77297, 0x88b75b27, 0xcf1721f7,
+ 0xf2770847, 0x10c70814, 0x2da721a4, 0x6a075b74, 0x576772c4,
+ 0xe547aed4, 0xd8278764, 0x9f87fdb4, 0xa2e7d404, 0x20b743d5,
+ 0x1dd76a65, 0x5a7710b5, 0x67173905, 0xd537e515, 0xe857cca5,
+ 0xaff7b675, 0x92979fc5, 0xe915e8db, 0xd475c16b, 0x93d5bbbb,
+ 0xaeb5920b, 0x1c954e1b, 0x21f567ab, 0x66551d7b, 0x5b3534cb,
+ 0xd965a31a, 0xe4058aaa, 0xa3a5f07a, 0x9ec5d9ca, 0x2ce505da,
+ 0x11852c6a, 0x562556ba, 0x6b457f0a, 0x89f57f59, 0xb49556e9,
+ 0xf3352c39, 0xce550589, 0x7c75d999, 0x4115f029, 0x06b58af9,
+ 0x3bd5a349, 0xb9853498, 0x84e51d28, 0xc34567f8, 0xfe254e48,
+ 0x4c059258, 0x7165bbe8, 0x36c5c138, 0x0ba5e888, 0x28d4c7df,
+ 0x15b4ee6f, 0x521494bf, 0x6f74bd0f, 0xdd54611f, 0xe03448af,
+ 0xa794327f, 0x9af41bcf, 0x18a48c1e, 0x25c4a5ae, 0x6264df7e,
+ 0x5f04f6ce, 0xed242ade, 0xd044036e, 0x97e479be, 0xaa84500e,
+ 0x4834505d, 0x755479ed, 0x32f4033d, 0x0f942a8d, 0xbdb4f69d,
+ 0x80d4df2d, 0xc774a5fd, 0xfa148c4d, 0x78441b9c, 0x4524322c,
+ 0x028448fc, 0x3fe4614c, 0x8dc4bd5c, 0xb0a494ec, 0xf704ee3c,
+ 0xca64c78c}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0xb029603d, 0x6053c07a, 0xd07aa047, 0xc0a680f5,
+ 0x708fe0c8, 0xa0f5408f, 0x10dc20b2, 0xc14b7030, 0x7162100d,
+ 0xa118b04a, 0x1131d077, 0x01edf0c5, 0xb1c490f8, 0x61be30bf,
+ 0xd1975082, 0x8297e060, 0x32be805d, 0xe2c4201a, 0x52ed4027,
+ 0x42316095, 0xf21800a8, 0x2262a0ef, 0x924bc0d2, 0x43dc9050,
+ 0xf3f5f06d, 0x238f502a, 0x93a63017, 0x837a10a5, 0x33537098,
+ 0xe329d0df, 0x5300b0e2, 0x042fc1c1, 0xb406a1fc, 0x647c01bb,
+ 0xd4556186, 0xc4894134, 0x74a02109, 0xa4da814e, 0x14f3e173,
+ 0xc564b1f1, 0x754dd1cc, 0xa537718b, 0x151e11b6, 0x05c23104,
+ 0xb5eb5139, 0x6591f17e, 0xd5b89143, 0x86b821a1, 0x3691419c,
+ 0xe6ebe1db, 0x56c281e6, 0x461ea154, 0xf637c169, 0x264d612e,
+ 0x96640113, 0x47f35191, 0xf7da31ac, 0x27a091eb, 0x9789f1d6,
+ 0x8755d164, 0x377cb159, 0xe706111e, 0x572f7123, 0x4958f358,
+ 0xf9719365, 0x290b3322, 0x9922531f, 0x89fe73ad, 0x39d71390,
+ 0xe9adb3d7, 0x5984d3ea, 0x88138368, 0x383ae355, 0xe8404312,
+ 0x5869232f, 0x48b5039d, 0xf89c63a0, 0x28e6c3e7, 0x98cfa3da,
+ 0xcbcf1338, 0x7be67305, 0xab9cd342, 0x1bb5b37f, 0x0b6993cd,
+ 0xbb40f3f0, 0x6b3a53b7, 0xdb13338a, 0x0a846308, 0xbaad0335,
+ 0x6ad7a372, 0xdafec34f, 0xca22e3fd, 0x7a0b83c0, 0xaa712387,
+ 0x1a5843ba, 0x4d773299, 0xfd5e52a4, 0x2d24f2e3, 0x9d0d92de,
+ 0x8dd1b26c, 0x3df8d251, 0xed827216, 0x5dab122b, 0x8c3c42a9,
+ 0x3c152294, 0xec6f82d3, 0x5c46e2ee, 0x4c9ac25c, 0xfcb3a261,
+ 0x2cc90226, 0x9ce0621b, 0xcfe0d2f9, 0x7fc9b2c4, 0xafb31283,
+ 0x1f9a72be, 0x0f46520c, 0xbf6f3231, 0x6f159276, 0xdf3cf24b,
+ 0x0eaba2c9, 0xbe82c2f4, 0x6ef862b3, 0xded1028e, 0xce0d223c,
+ 0x7e244201, 0xae5ee246, 0x1e77827b, 0x92b0e6b1, 0x2299868c,
+ 0xf2e326cb, 0x42ca46f6, 0x52166644, 0xe23f0679, 0x3245a63e,
+ 0x826cc603, 0x53fb9681, 0xe3d2f6bc, 0x33a856fb, 0x838136c6,
+ 0x935d1674, 0x23747649, 0xf30ed60e, 0x4327b633, 0x102706d1,
+ 0xa00e66ec, 0x7074c6ab, 0xc05da696, 0xd0818624, 0x60a8e619,
+ 0xb0d2465e, 0x00fb2663, 0xd16c76e1, 0x614516dc, 0xb13fb69b,
+ 0x0116d6a6, 0x11caf614, 0xa1e39629, 0x7199366e, 0xc1b05653,
+ 0x969f2770, 0x26b6474d, 0xf6cce70a, 0x46e58737, 0x5639a785,
+ 0xe610c7b8, 0x366a67ff, 0x864307c2, 0x57d45740, 0xe7fd377d,
+ 0x3787973a, 0x87aef707, 0x9772d7b5, 0x275bb788, 0xf72117cf,
+ 0x470877f2, 0x1408c710, 0xa421a72d, 0x745b076a, 0xc4726757,
+ 0xd4ae47e5, 0x648727d8, 0xb4fd879f, 0x04d4e7a2, 0xd543b720,
+ 0x656ad71d, 0xb510775a, 0x05391767, 0x15e537d5, 0xa5cc57e8,
+ 0x75b6f7af, 0xc59f9792, 0xdbe815e9, 0x6bc175d4, 0xbbbbd593,
+ 0x0b92b5ae, 0x1b4e951c, 0xab67f521, 0x7b1d5566, 0xcb34355b,
+ 0x1aa365d9, 0xaa8a05e4, 0x7af0a5a3, 0xcad9c59e, 0xda05e52c,
+ 0x6a2c8511, 0xba562556, 0x0a7f456b, 0x597ff589, 0xe95695b4,
+ 0x392c35f3, 0x890555ce, 0x99d9757c, 0x29f01541, 0xf98ab506,
+ 0x49a3d53b, 0x983485b9, 0x281de584, 0xf86745c3, 0x484e25fe,
+ 0x5892054c, 0xe8bb6571, 0x38c1c536, 0x88e8a50b, 0xdfc7d428,
+ 0x6feeb415, 0xbf941452, 0x0fbd746f, 0x1f6154dd, 0xaf4834e0,
+ 0x7f3294a7, 0xcf1bf49a, 0x1e8ca418, 0xaea5c425, 0x7edf6462,
+ 0xcef6045f, 0xde2a24ed, 0x6e0344d0, 0xbe79e497, 0x0e5084aa,
+ 0x5d503448, 0xed795475, 0x3d03f432, 0x8d2a940f, 0x9df6b4bd,
+ 0x2ddfd480, 0xfda574c7, 0x4d8c14fa, 0x9c1b4478, 0x2c322445,
+ 0xfc488402, 0x4c61e43f, 0x5cbdc48d, 0xec94a4b0, 0x3cee04f7,
+ 0x8cc764ca},
+ {0x00000000, 0xa5d35ccb, 0x0ba1c84d, 0xae729486, 0x1642919b,
+ 0xb391cd50, 0x1de359d6, 0xb830051d, 0x6d8253ec, 0xc8510f27,
+ 0x66239ba1, 0xc3f0c76a, 0x7bc0c277, 0xde139ebc, 0x70610a3a,
+ 0xd5b256f1, 0x9b02d603, 0x3ed18ac8, 0x90a31e4e, 0x35704285,
+ 0x8d404798, 0x28931b53, 0x86e18fd5, 0x2332d31e, 0xf68085ef,
+ 0x5353d924, 0xfd214da2, 0x58f21169, 0xe0c21474, 0x451148bf,
+ 0xeb63dc39, 0x4eb080f2, 0x3605ac07, 0x93d6f0cc, 0x3da4644a,
+ 0x98773881, 0x20473d9c, 0x85946157, 0x2be6f5d1, 0x8e35a91a,
+ 0x5b87ffeb, 0xfe54a320, 0x502637a6, 0xf5f56b6d, 0x4dc56e70,
+ 0xe81632bb, 0x4664a63d, 0xe3b7faf6, 0xad077a04, 0x08d426cf,
+ 0xa6a6b249, 0x0375ee82, 0xbb45eb9f, 0x1e96b754, 0xb0e423d2,
+ 0x15377f19, 0xc08529e8, 0x65567523, 0xcb24e1a5, 0x6ef7bd6e,
+ 0xd6c7b873, 0x7314e4b8, 0xdd66703e, 0x78b52cf5, 0x6c0a580f,
+ 0xc9d904c4, 0x67ab9042, 0xc278cc89, 0x7a48c994, 0xdf9b955f,
+ 0x71e901d9, 0xd43a5d12, 0x01880be3, 0xa45b5728, 0x0a29c3ae,
+ 0xaffa9f65, 0x17ca9a78, 0xb219c6b3, 0x1c6b5235, 0xb9b80efe,
+ 0xf7088e0c, 0x52dbd2c7, 0xfca94641, 0x597a1a8a, 0xe14a1f97,
+ 0x4499435c, 0xeaebd7da, 0x4f388b11, 0x9a8adde0, 0x3f59812b,
+ 0x912b15ad, 0x34f84966, 0x8cc84c7b, 0x291b10b0, 0x87698436,
+ 0x22bad8fd, 0x5a0ff408, 0xffdca8c3, 0x51ae3c45, 0xf47d608e,
+ 0x4c4d6593, 0xe99e3958, 0x47ecadde, 0xe23ff115, 0x378da7e4,
+ 0x925efb2f, 0x3c2c6fa9, 0x99ff3362, 0x21cf367f, 0x841c6ab4,
+ 0x2a6efe32, 0x8fbda2f9, 0xc10d220b, 0x64de7ec0, 0xcaacea46,
+ 0x6f7fb68d, 0xd74fb390, 0x729cef5b, 0xdcee7bdd, 0x793d2716,
+ 0xac8f71e7, 0x095c2d2c, 0xa72eb9aa, 0x02fde561, 0xbacde07c,
+ 0x1f1ebcb7, 0xb16c2831, 0x14bf74fa, 0xd814b01e, 0x7dc7ecd5,
+ 0xd3b57853, 0x76662498, 0xce562185, 0x6b857d4e, 0xc5f7e9c8,
+ 0x6024b503, 0xb596e3f2, 0x1045bf39, 0xbe372bbf, 0x1be47774,
+ 0xa3d47269, 0x06072ea2, 0xa875ba24, 0x0da6e6ef, 0x4316661d,
+ 0xe6c53ad6, 0x48b7ae50, 0xed64f29b, 0x5554f786, 0xf087ab4d,
+ 0x5ef53fcb, 0xfb266300, 0x2e9435f1, 0x8b47693a, 0x2535fdbc,
+ 0x80e6a177, 0x38d6a46a, 0x9d05f8a1, 0x33776c27, 0x96a430ec,
+ 0xee111c19, 0x4bc240d2, 0xe5b0d454, 0x4063889f, 0xf8538d82,
+ 0x5d80d149, 0xf3f245cf, 0x56211904, 0x83934ff5, 0x2640133e,
+ 0x883287b8, 0x2de1db73, 0x95d1de6e, 0x300282a5, 0x9e701623,
+ 0x3ba34ae8, 0x7513ca1a, 0xd0c096d1, 0x7eb20257, 0xdb615e9c,
+ 0x63515b81, 0xc682074a, 0x68f093cc, 0xcd23cf07, 0x189199f6,
+ 0xbd42c53d, 0x133051bb, 0xb6e30d70, 0x0ed3086d, 0xab0054a6,
+ 0x0572c020, 0xa0a19ceb, 0xb41ee811, 0x11cdb4da, 0xbfbf205c,
+ 0x1a6c7c97, 0xa25c798a, 0x078f2541, 0xa9fdb1c7, 0x0c2eed0c,
+ 0xd99cbbfd, 0x7c4fe736, 0xd23d73b0, 0x77ee2f7b, 0xcfde2a66,
+ 0x6a0d76ad, 0xc47fe22b, 0x61acbee0, 0x2f1c3e12, 0x8acf62d9,
+ 0x24bdf65f, 0x816eaa94, 0x395eaf89, 0x9c8df342, 0x32ff67c4,
+ 0x972c3b0f, 0x429e6dfe, 0xe74d3135, 0x493fa5b3, 0xececf978,
+ 0x54dcfc65, 0xf10fa0ae, 0x5f7d3428, 0xfaae68e3, 0x821b4416,
+ 0x27c818dd, 0x89ba8c5b, 0x2c69d090, 0x9459d58d, 0x318a8946,
+ 0x9ff81dc0, 0x3a2b410b, 0xef9917fa, 0x4a4a4b31, 0xe438dfb7,
+ 0x41eb837c, 0xf9db8661, 0x5c08daaa, 0xf27a4e2c, 0x57a912e7,
+ 0x19199215, 0xbccacede, 0x12b85a58, 0xb76b0693, 0x0f5b038e,
+ 0xaa885f45, 0x04facbc3, 0xa1299708, 0x749bc1f9, 0xd1489d32,
+ 0x7f3a09b4, 0xdae9557f, 0x62d95062, 0xc70a0ca9, 0x6978982f,
+ 0xccabc4e4},
+ {0x00000000, 0xb40b77a6, 0x29119f97, 0x9d1ae831, 0x13244ff4,
+ 0xa72f3852, 0x3a35d063, 0x8e3ea7c5, 0x674eef33, 0xd3459895,
+ 0x4e5f70a4, 0xfa540702, 0x746aa0c7, 0xc061d761, 0x5d7b3f50,
+ 0xe97048f6, 0xce9cde67, 0x7a97a9c1, 0xe78d41f0, 0x53863656,
+ 0xddb89193, 0x69b3e635, 0xf4a90e04, 0x40a279a2, 0xa9d23154,
+ 0x1dd946f2, 0x80c3aec3, 0x34c8d965, 0xbaf67ea0, 0x0efd0906,
+ 0x93e7e137, 0x27ec9691, 0x9c39bdcf, 0x2832ca69, 0xb5282258,
+ 0x012355fe, 0x8f1df23b, 0x3b16859d, 0xa60c6dac, 0x12071a0a,
+ 0xfb7752fc, 0x4f7c255a, 0xd266cd6b, 0x666dbacd, 0xe8531d08,
+ 0x5c586aae, 0xc142829f, 0x7549f539, 0x52a563a8, 0xe6ae140e,
+ 0x7bb4fc3f, 0xcfbf8b99, 0x41812c5c, 0xf58a5bfa, 0x6890b3cb,
+ 0xdc9bc46d, 0x35eb8c9b, 0x81e0fb3d, 0x1cfa130c, 0xa8f164aa,
+ 0x26cfc36f, 0x92c4b4c9, 0x0fde5cf8, 0xbbd52b5e, 0x79750b44,
+ 0xcd7e7ce2, 0x506494d3, 0xe46fe375, 0x6a5144b0, 0xde5a3316,
+ 0x4340db27, 0xf74bac81, 0x1e3be477, 0xaa3093d1, 0x372a7be0,
+ 0x83210c46, 0x0d1fab83, 0xb914dc25, 0x240e3414, 0x900543b2,
+ 0xb7e9d523, 0x03e2a285, 0x9ef84ab4, 0x2af33d12, 0xa4cd9ad7,
+ 0x10c6ed71, 0x8ddc0540, 0x39d772e6, 0xd0a73a10, 0x64ac4db6,
+ 0xf9b6a587, 0x4dbdd221, 0xc38375e4, 0x77880242, 0xea92ea73,
+ 0x5e999dd5, 0xe54cb68b, 0x5147c12d, 0xcc5d291c, 0x78565eba,
+ 0xf668f97f, 0x42638ed9, 0xdf7966e8, 0x6b72114e, 0x820259b8,
+ 0x36092e1e, 0xab13c62f, 0x1f18b189, 0x9126164c, 0x252d61ea,
+ 0xb83789db, 0x0c3cfe7d, 0x2bd068ec, 0x9fdb1f4a, 0x02c1f77b,
+ 0xb6ca80dd, 0x38f42718, 0x8cff50be, 0x11e5b88f, 0xa5eecf29,
+ 0x4c9e87df, 0xf895f079, 0x658f1848, 0xd1846fee, 0x5fbac82b,
+ 0xebb1bf8d, 0x76ab57bc, 0xc2a0201a, 0xf2ea1688, 0x46e1612e,
+ 0xdbfb891f, 0x6ff0feb9, 0xe1ce597c, 0x55c52eda, 0xc8dfc6eb,
+ 0x7cd4b14d, 0x95a4f9bb, 0x21af8e1d, 0xbcb5662c, 0x08be118a,
+ 0x8680b64f, 0x328bc1e9, 0xaf9129d8, 0x1b9a5e7e, 0x3c76c8ef,
+ 0x887dbf49, 0x15675778, 0xa16c20de, 0x2f52871b, 0x9b59f0bd,
+ 0x0643188c, 0xb2486f2a, 0x5b3827dc, 0xef33507a, 0x7229b84b,
+ 0xc622cfed, 0x481c6828, 0xfc171f8e, 0x610df7bf, 0xd5068019,
+ 0x6ed3ab47, 0xdad8dce1, 0x47c234d0, 0xf3c94376, 0x7df7e4b3,
+ 0xc9fc9315, 0x54e67b24, 0xe0ed0c82, 0x099d4474, 0xbd9633d2,
+ 0x208cdbe3, 0x9487ac45, 0x1ab90b80, 0xaeb27c26, 0x33a89417,
+ 0x87a3e3b1, 0xa04f7520, 0x14440286, 0x895eeab7, 0x3d559d11,
+ 0xb36b3ad4, 0x07604d72, 0x9a7aa543, 0x2e71d2e5, 0xc7019a13,
+ 0x730aedb5, 0xee100584, 0x5a1b7222, 0xd425d5e7, 0x602ea241,
+ 0xfd344a70, 0x493f3dd6, 0x8b9f1dcc, 0x3f946a6a, 0xa28e825b,
+ 0x1685f5fd, 0x98bb5238, 0x2cb0259e, 0xb1aacdaf, 0x05a1ba09,
+ 0xecd1f2ff, 0x58da8559, 0xc5c06d68, 0x71cb1ace, 0xfff5bd0b,
+ 0x4bfecaad, 0xd6e4229c, 0x62ef553a, 0x4503c3ab, 0xf108b40d,
+ 0x6c125c3c, 0xd8192b9a, 0x56278c5f, 0xe22cfbf9, 0x7f3613c8,
+ 0xcb3d646e, 0x224d2c98, 0x96465b3e, 0x0b5cb30f, 0xbf57c4a9,
+ 0x3169636c, 0x856214ca, 0x1878fcfb, 0xac738b5d, 0x17a6a003,
+ 0xa3add7a5, 0x3eb73f94, 0x8abc4832, 0x0482eff7, 0xb0899851,
+ 0x2d937060, 0x999807c6, 0x70e84f30, 0xc4e33896, 0x59f9d0a7,
+ 0xedf2a701, 0x63cc00c4, 0xd7c77762, 0x4add9f53, 0xfed6e8f5,
+ 0xd93a7e64, 0x6d3109c2, 0xf02be1f3, 0x44209655, 0xca1e3190,
+ 0x7e154636, 0xe30fae07, 0x5704d9a1, 0xbe749157, 0x0a7fe6f1,
+ 0x97650ec0, 0x236e7966, 0xad50dea3, 0x195ba905, 0x84414134,
+ 0x304a3692},
+ {0x00000000, 0x9e00aacc, 0x7d072542, 0xe3078f8e, 0xfa0e4a84,
+ 0x640ee048, 0x87096fc6, 0x1909c50a, 0xb51be5d3, 0x2b1b4f1f,
+ 0xc81cc091, 0x561c6a5d, 0x4f15af57, 0xd115059b, 0x32128a15,
+ 0xac1220d9, 0x2b31bb7c, 0xb53111b0, 0x56369e3e, 0xc83634f2,
+ 0xd13ff1f8, 0x4f3f5b34, 0xac38d4ba, 0x32387e76, 0x9e2a5eaf,
+ 0x002af463, 0xe32d7bed, 0x7d2dd121, 0x6424142b, 0xfa24bee7,
+ 0x19233169, 0x87239ba5, 0x566276f9, 0xc862dc35, 0x2b6553bb,
+ 0xb565f977, 0xac6c3c7d, 0x326c96b1, 0xd16b193f, 0x4f6bb3f3,
+ 0xe379932a, 0x7d7939e6, 0x9e7eb668, 0x007e1ca4, 0x1977d9ae,
+ 0x87777362, 0x6470fcec, 0xfa705620, 0x7d53cd85, 0xe3536749,
+ 0x0054e8c7, 0x9e54420b, 0x875d8701, 0x195d2dcd, 0xfa5aa243,
+ 0x645a088f, 0xc8482856, 0x5648829a, 0xb54f0d14, 0x2b4fa7d8,
+ 0x324662d2, 0xac46c81e, 0x4f414790, 0xd141ed5c, 0xedc29d29,
+ 0x73c237e5, 0x90c5b86b, 0x0ec512a7, 0x17ccd7ad, 0x89cc7d61,
+ 0x6acbf2ef, 0xf4cb5823, 0x58d978fa, 0xc6d9d236, 0x25de5db8,
+ 0xbbdef774, 0xa2d7327e, 0x3cd798b2, 0xdfd0173c, 0x41d0bdf0,
+ 0xc6f32655, 0x58f38c99, 0xbbf40317, 0x25f4a9db, 0x3cfd6cd1,
+ 0xa2fdc61d, 0x41fa4993, 0xdffae35f, 0x73e8c386, 0xede8694a,
+ 0x0eefe6c4, 0x90ef4c08, 0x89e68902, 0x17e623ce, 0xf4e1ac40,
+ 0x6ae1068c, 0xbba0ebd0, 0x25a0411c, 0xc6a7ce92, 0x58a7645e,
+ 0x41aea154, 0xdfae0b98, 0x3ca98416, 0xa2a92eda, 0x0ebb0e03,
+ 0x90bba4cf, 0x73bc2b41, 0xedbc818d, 0xf4b54487, 0x6ab5ee4b,
+ 0x89b261c5, 0x17b2cb09, 0x909150ac, 0x0e91fa60, 0xed9675ee,
+ 0x7396df22, 0x6a9f1a28, 0xf49fb0e4, 0x17983f6a, 0x899895a6,
+ 0x258ab57f, 0xbb8a1fb3, 0x588d903d, 0xc68d3af1, 0xdf84fffb,
+ 0x41845537, 0xa283dab9, 0x3c837075, 0xda853b53, 0x4485919f,
+ 0xa7821e11, 0x3982b4dd, 0x208b71d7, 0xbe8bdb1b, 0x5d8c5495,
+ 0xc38cfe59, 0x6f9ede80, 0xf19e744c, 0x1299fbc2, 0x8c99510e,
+ 0x95909404, 0x0b903ec8, 0xe897b146, 0x76971b8a, 0xf1b4802f,
+ 0x6fb42ae3, 0x8cb3a56d, 0x12b30fa1, 0x0bbacaab, 0x95ba6067,
+ 0x76bdefe9, 0xe8bd4525, 0x44af65fc, 0xdaafcf30, 0x39a840be,
+ 0xa7a8ea72, 0xbea12f78, 0x20a185b4, 0xc3a60a3a, 0x5da6a0f6,
+ 0x8ce74daa, 0x12e7e766, 0xf1e068e8, 0x6fe0c224, 0x76e9072e,
+ 0xe8e9ade2, 0x0bee226c, 0x95ee88a0, 0x39fca879, 0xa7fc02b5,
+ 0x44fb8d3b, 0xdafb27f7, 0xc3f2e2fd, 0x5df24831, 0xbef5c7bf,
+ 0x20f56d73, 0xa7d6f6d6, 0x39d65c1a, 0xdad1d394, 0x44d17958,
+ 0x5dd8bc52, 0xc3d8169e, 0x20df9910, 0xbedf33dc, 0x12cd1305,
+ 0x8ccdb9c9, 0x6fca3647, 0xf1ca9c8b, 0xe8c35981, 0x76c3f34d,
+ 0x95c47cc3, 0x0bc4d60f, 0x3747a67a, 0xa9470cb6, 0x4a408338,
+ 0xd44029f4, 0xcd49ecfe, 0x53494632, 0xb04ec9bc, 0x2e4e6370,
+ 0x825c43a9, 0x1c5ce965, 0xff5b66eb, 0x615bcc27, 0x7852092d,
+ 0xe652a3e1, 0x05552c6f, 0x9b5586a3, 0x1c761d06, 0x8276b7ca,
+ 0x61713844, 0xff719288, 0xe6785782, 0x7878fd4e, 0x9b7f72c0,
+ 0x057fd80c, 0xa96df8d5, 0x376d5219, 0xd46add97, 0x4a6a775b,
+ 0x5363b251, 0xcd63189d, 0x2e649713, 0xb0643ddf, 0x6125d083,
+ 0xff257a4f, 0x1c22f5c1, 0x82225f0d, 0x9b2b9a07, 0x052b30cb,
+ 0xe62cbf45, 0x782c1589, 0xd43e3550, 0x4a3e9f9c, 0xa9391012,
+ 0x3739bade, 0x2e307fd4, 0xb030d518, 0x53375a96, 0xcd37f05a,
+ 0x4a146bff, 0xd414c133, 0x37134ebd, 0xa913e471, 0xb01a217b,
+ 0x2e1a8bb7, 0xcd1d0439, 0x531daef5, 0xff0f8e2c, 0x610f24e0,
+ 0x8208ab6e, 0x1c0801a2, 0x0501c4a8, 0x9b016e64, 0x7806e1ea,
+ 0xe6064b26}};
+
#endif
- }
-};
+
+#endif
+
+#if N == 3
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848},
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x43cba68700000000, 0xc7903cd400000000,
+ 0x845b9a5300000000, 0xcf27087300000000, 0x8cecaef400000000,
+ 0x08b734a700000000, 0x4b7c922000000000, 0x9e4f10e600000000,
+ 0xdd84b66100000000, 0x59df2c3200000000, 0x1a148ab500000000,
+ 0x5168189500000000, 0x12a3be1200000000, 0x96f8244100000000,
+ 0xd53382c600000000, 0x7d99511700000000, 0x3e52f79000000000,
+ 0xba096dc300000000, 0xf9c2cb4400000000, 0xb2be596400000000,
+ 0xf175ffe300000000, 0x752e65b000000000, 0x36e5c33700000000,
+ 0xe3d641f100000000, 0xa01de77600000000, 0x24467d2500000000,
+ 0x678ddba200000000, 0x2cf1498200000000, 0x6f3aef0500000000,
+ 0xeb61755600000000, 0xa8aad3d100000000, 0xfa32a32e00000000,
+ 0xb9f905a900000000, 0x3da29ffa00000000, 0x7e69397d00000000,
+ 0x3515ab5d00000000, 0x76de0dda00000000, 0xf285978900000000,
+ 0xb14e310e00000000, 0x647db3c800000000, 0x27b6154f00000000,
+ 0xa3ed8f1c00000000, 0xe026299b00000000, 0xab5abbbb00000000,
+ 0xe8911d3c00000000, 0x6cca876f00000000, 0x2f0121e800000000,
+ 0x87abf23900000000, 0xc46054be00000000, 0x403bceed00000000,
+ 0x03f0686a00000000, 0x488cfa4a00000000, 0x0b475ccd00000000,
+ 0x8f1cc69e00000000, 0xccd7601900000000, 0x19e4e2df00000000,
+ 0x5a2f445800000000, 0xde74de0b00000000, 0x9dbf788c00000000,
+ 0xd6c3eaac00000000, 0x95084c2b00000000, 0x1153d67800000000,
+ 0x529870ff00000000, 0xf465465d00000000, 0xb7aee0da00000000,
+ 0x33f57a8900000000, 0x703edc0e00000000, 0x3b424e2e00000000,
+ 0x7889e8a900000000, 0xfcd272fa00000000, 0xbf19d47d00000000,
+ 0x6a2a56bb00000000, 0x29e1f03c00000000, 0xadba6a6f00000000,
+ 0xee71cce800000000, 0xa50d5ec800000000, 0xe6c6f84f00000000,
+ 0x629d621c00000000, 0x2156c49b00000000, 0x89fc174a00000000,
+ 0xca37b1cd00000000, 0x4e6c2b9e00000000, 0x0da78d1900000000,
+ 0x46db1f3900000000, 0x0510b9be00000000, 0x814b23ed00000000,
+ 0xc280856a00000000, 0x17b307ac00000000, 0x5478a12b00000000,
+ 0xd0233b7800000000, 0x93e89dff00000000, 0xd8940fdf00000000,
+ 0x9b5fa95800000000, 0x1f04330b00000000, 0x5ccf958c00000000,
+ 0x0e57e57300000000, 0x4d9c43f400000000, 0xc9c7d9a700000000,
+ 0x8a0c7f2000000000, 0xc170ed0000000000, 0x82bb4b8700000000,
+ 0x06e0d1d400000000, 0x452b775300000000, 0x9018f59500000000,
+ 0xd3d3531200000000, 0x5788c94100000000, 0x14436fc600000000,
+ 0x5f3ffde600000000, 0x1cf45b6100000000, 0x98afc13200000000,
+ 0xdb6467b500000000, 0x73ceb46400000000, 0x300512e300000000,
+ 0xb45e88b000000000, 0xf7952e3700000000, 0xbce9bc1700000000,
+ 0xff221a9000000000, 0x7b7980c300000000, 0x38b2264400000000,
+ 0xed81a48200000000, 0xae4a020500000000, 0x2a11985600000000,
+ 0x69da3ed100000000, 0x22a6acf100000000, 0x616d0a7600000000,
+ 0xe536902500000000, 0xa6fd36a200000000, 0xe8cb8cba00000000,
+ 0xab002a3d00000000, 0x2f5bb06e00000000, 0x6c9016e900000000,
+ 0x27ec84c900000000, 0x6427224e00000000, 0xe07cb81d00000000,
+ 0xa3b71e9a00000000, 0x76849c5c00000000, 0x354f3adb00000000,
+ 0xb114a08800000000, 0xf2df060f00000000, 0xb9a3942f00000000,
+ 0xfa6832a800000000, 0x7e33a8fb00000000, 0x3df80e7c00000000,
+ 0x9552ddad00000000, 0xd6997b2a00000000, 0x52c2e17900000000,
+ 0x110947fe00000000, 0x5a75d5de00000000, 0x19be735900000000,
+ 0x9de5e90a00000000, 0xde2e4f8d00000000, 0x0b1dcd4b00000000,
+ 0x48d66bcc00000000, 0xcc8df19f00000000, 0x8f46571800000000,
+ 0xc43ac53800000000, 0x87f163bf00000000, 0x03aaf9ec00000000,
+ 0x40615f6b00000000, 0x12f92f9400000000, 0x5132891300000000,
+ 0xd569134000000000, 0x96a2b5c700000000, 0xddde27e700000000,
+ 0x9e15816000000000, 0x1a4e1b3300000000, 0x5985bdb400000000,
+ 0x8cb63f7200000000, 0xcf7d99f500000000, 0x4b2603a600000000,
+ 0x08eda52100000000, 0x4391370100000000, 0x005a918600000000,
+ 0x84010bd500000000, 0xc7caad5200000000, 0x6f607e8300000000,
+ 0x2cabd80400000000, 0xa8f0425700000000, 0xeb3be4d000000000,
+ 0xa04776f000000000, 0xe38cd07700000000, 0x67d74a2400000000,
+ 0x241ceca300000000, 0xf12f6e6500000000, 0xb2e4c8e200000000,
+ 0x36bf52b100000000, 0x7574f43600000000, 0x3e08661600000000,
+ 0x7dc3c09100000000, 0xf9985ac200000000, 0xba53fc4500000000,
+ 0x1caecae700000000, 0x5f656c6000000000, 0xdb3ef63300000000,
+ 0x98f550b400000000, 0xd389c29400000000, 0x9042641300000000,
+ 0x1419fe4000000000, 0x57d258c700000000, 0x82e1da0100000000,
+ 0xc12a7c8600000000, 0x4571e6d500000000, 0x06ba405200000000,
+ 0x4dc6d27200000000, 0x0e0d74f500000000, 0x8a56eea600000000,
+ 0xc99d482100000000, 0x61379bf000000000, 0x22fc3d7700000000,
+ 0xa6a7a72400000000, 0xe56c01a300000000, 0xae10938300000000,
+ 0xeddb350400000000, 0x6980af5700000000, 0x2a4b09d000000000,
+ 0xff788b1600000000, 0xbcb32d9100000000, 0x38e8b7c200000000,
+ 0x7b23114500000000, 0x305f836500000000, 0x739425e200000000,
+ 0xf7cfbfb100000000, 0xb404193600000000, 0xe69c69c900000000,
+ 0xa557cf4e00000000, 0x210c551d00000000, 0x62c7f39a00000000,
+ 0x29bb61ba00000000, 0x6a70c73d00000000, 0xee2b5d6e00000000,
+ 0xade0fbe900000000, 0x78d3792f00000000, 0x3b18dfa800000000,
+ 0xbf4345fb00000000, 0xfc88e37c00000000, 0xb7f4715c00000000,
+ 0xf43fd7db00000000, 0x70644d8800000000, 0x33afeb0f00000000,
+ 0x9b0538de00000000, 0xd8ce9e5900000000, 0x5c95040a00000000,
+ 0x1f5ea28d00000000, 0x542230ad00000000, 0x17e9962a00000000,
+ 0x93b20c7900000000, 0xd079aafe00000000, 0x054a283800000000,
+ 0x46818ebf00000000, 0xc2da14ec00000000, 0x8111b26b00000000,
+ 0xca6d204b00000000, 0x89a686cc00000000, 0x0dfd1c9f00000000,
+ 0x4e36ba1800000000},
+ {0x0000000000000000, 0xe1b652ef00000000, 0x836bd40500000000,
+ 0x62dd86ea00000000, 0x06d7a80b00000000, 0xe761fae400000000,
+ 0x85bc7c0e00000000, 0x640a2ee100000000, 0x0cae511700000000,
+ 0xed1803f800000000, 0x8fc5851200000000, 0x6e73d7fd00000000,
+ 0x0a79f91c00000000, 0xebcfabf300000000, 0x89122d1900000000,
+ 0x68a47ff600000000, 0x185ca32e00000000, 0xf9eaf1c100000000,
+ 0x9b37772b00000000, 0x7a8125c400000000, 0x1e8b0b2500000000,
+ 0xff3d59ca00000000, 0x9de0df2000000000, 0x7c568dcf00000000,
+ 0x14f2f23900000000, 0xf544a0d600000000, 0x9799263c00000000,
+ 0x762f74d300000000, 0x12255a3200000000, 0xf39308dd00000000,
+ 0x914e8e3700000000, 0x70f8dcd800000000, 0x30b8465d00000000,
+ 0xd10e14b200000000, 0xb3d3925800000000, 0x5265c0b700000000,
+ 0x366fee5600000000, 0xd7d9bcb900000000, 0xb5043a5300000000,
+ 0x54b268bc00000000, 0x3c16174a00000000, 0xdda045a500000000,
+ 0xbf7dc34f00000000, 0x5ecb91a000000000, 0x3ac1bf4100000000,
+ 0xdb77edae00000000, 0xb9aa6b4400000000, 0x581c39ab00000000,
+ 0x28e4e57300000000, 0xc952b79c00000000, 0xab8f317600000000,
+ 0x4a39639900000000, 0x2e334d7800000000, 0xcf851f9700000000,
+ 0xad58997d00000000, 0x4ceecb9200000000, 0x244ab46400000000,
+ 0xc5fce68b00000000, 0xa721606100000000, 0x4697328e00000000,
+ 0x229d1c6f00000000, 0xc32b4e8000000000, 0xa1f6c86a00000000,
+ 0x40409a8500000000, 0x60708dba00000000, 0x81c6df5500000000,
+ 0xe31b59bf00000000, 0x02ad0b5000000000, 0x66a725b100000000,
+ 0x8711775e00000000, 0xe5ccf1b400000000, 0x047aa35b00000000,
+ 0x6cdedcad00000000, 0x8d688e4200000000, 0xefb508a800000000,
+ 0x0e035a4700000000, 0x6a0974a600000000, 0x8bbf264900000000,
+ 0xe962a0a300000000, 0x08d4f24c00000000, 0x782c2e9400000000,
+ 0x999a7c7b00000000, 0xfb47fa9100000000, 0x1af1a87e00000000,
+ 0x7efb869f00000000, 0x9f4dd47000000000, 0xfd90529a00000000,
+ 0x1c26007500000000, 0x74827f8300000000, 0x95342d6c00000000,
+ 0xf7e9ab8600000000, 0x165ff96900000000, 0x7255d78800000000,
+ 0x93e3856700000000, 0xf13e038d00000000, 0x1088516200000000,
+ 0x50c8cbe700000000, 0xb17e990800000000, 0xd3a31fe200000000,
+ 0x32154d0d00000000, 0x561f63ec00000000, 0xb7a9310300000000,
+ 0xd574b7e900000000, 0x34c2e50600000000, 0x5c669af000000000,
+ 0xbdd0c81f00000000, 0xdf0d4ef500000000, 0x3ebb1c1a00000000,
+ 0x5ab132fb00000000, 0xbb07601400000000, 0xd9dae6fe00000000,
+ 0x386cb41100000000, 0x489468c900000000, 0xa9223a2600000000,
+ 0xcbffbccc00000000, 0x2a49ee2300000000, 0x4e43c0c200000000,
+ 0xaff5922d00000000, 0xcd2814c700000000, 0x2c9e462800000000,
+ 0x443a39de00000000, 0xa58c6b3100000000, 0xc751eddb00000000,
+ 0x26e7bf3400000000, 0x42ed91d500000000, 0xa35bc33a00000000,
+ 0xc18645d000000000, 0x2030173f00000000, 0x81e66bae00000000,
+ 0x6050394100000000, 0x028dbfab00000000, 0xe33bed4400000000,
+ 0x8731c3a500000000, 0x6687914a00000000, 0x045a17a000000000,
+ 0xe5ec454f00000000, 0x8d483ab900000000, 0x6cfe685600000000,
+ 0x0e23eebc00000000, 0xef95bc5300000000, 0x8b9f92b200000000,
+ 0x6a29c05d00000000, 0x08f446b700000000, 0xe942145800000000,
+ 0x99bac88000000000, 0x780c9a6f00000000, 0x1ad11c8500000000,
+ 0xfb674e6a00000000, 0x9f6d608b00000000, 0x7edb326400000000,
+ 0x1c06b48e00000000, 0xfdb0e66100000000, 0x9514999700000000,
+ 0x74a2cb7800000000, 0x167f4d9200000000, 0xf7c91f7d00000000,
+ 0x93c3319c00000000, 0x7275637300000000, 0x10a8e59900000000,
+ 0xf11eb77600000000, 0xb15e2df300000000, 0x50e87f1c00000000,
+ 0x3235f9f600000000, 0xd383ab1900000000, 0xb78985f800000000,
+ 0x563fd71700000000, 0x34e251fd00000000, 0xd554031200000000,
+ 0xbdf07ce400000000, 0x5c462e0b00000000, 0x3e9ba8e100000000,
+ 0xdf2dfa0e00000000, 0xbb27d4ef00000000, 0x5a91860000000000,
+ 0x384c00ea00000000, 0xd9fa520500000000, 0xa9028edd00000000,
+ 0x48b4dc3200000000, 0x2a695ad800000000, 0xcbdf083700000000,
+ 0xafd526d600000000, 0x4e63743900000000, 0x2cbef2d300000000,
+ 0xcd08a03c00000000, 0xa5acdfca00000000, 0x441a8d2500000000,
+ 0x26c70bcf00000000, 0xc771592000000000, 0xa37b77c100000000,
+ 0x42cd252e00000000, 0x2010a3c400000000, 0xc1a6f12b00000000,
+ 0xe196e61400000000, 0x0020b4fb00000000, 0x62fd321100000000,
+ 0x834b60fe00000000, 0xe7414e1f00000000, 0x06f71cf000000000,
+ 0x642a9a1a00000000, 0x859cc8f500000000, 0xed38b70300000000,
+ 0x0c8ee5ec00000000, 0x6e53630600000000, 0x8fe531e900000000,
+ 0xebef1f0800000000, 0x0a594de700000000, 0x6884cb0d00000000,
+ 0x893299e200000000, 0xf9ca453a00000000, 0x187c17d500000000,
+ 0x7aa1913f00000000, 0x9b17c3d000000000, 0xff1ded3100000000,
+ 0x1eabbfde00000000, 0x7c76393400000000, 0x9dc06bdb00000000,
+ 0xf564142d00000000, 0x14d246c200000000, 0x760fc02800000000,
+ 0x97b992c700000000, 0xf3b3bc2600000000, 0x1205eec900000000,
+ 0x70d8682300000000, 0x916e3acc00000000, 0xd12ea04900000000,
+ 0x3098f2a600000000, 0x5245744c00000000, 0xb3f326a300000000,
+ 0xd7f9084200000000, 0x364f5aad00000000, 0x5492dc4700000000,
+ 0xb5248ea800000000, 0xdd80f15e00000000, 0x3c36a3b100000000,
+ 0x5eeb255b00000000, 0xbf5d77b400000000, 0xdb57595500000000,
+ 0x3ae10bba00000000, 0x583c8d5000000000, 0xb98adfbf00000000,
+ 0xc972036700000000, 0x28c4518800000000, 0x4a19d76200000000,
+ 0xabaf858d00000000, 0xcfa5ab6c00000000, 0x2e13f98300000000,
+ 0x4cce7f6900000000, 0xad782d8600000000, 0xc5dc527000000000,
+ 0x246a009f00000000, 0x46b7867500000000, 0xa701d49a00000000,
+ 0xc30bfa7b00000000, 0x22bda89400000000, 0x40602e7e00000000,
+ 0xa1d67c9100000000},
+ {0x0000000000000000, 0x5880e2d700000000, 0xf106b47400000000,
+ 0xa98656a300000000, 0xe20d68e900000000, 0xba8d8a3e00000000,
+ 0x130bdc9d00000000, 0x4b8b3e4a00000000, 0x851da10900000000,
+ 0xdd9d43de00000000, 0x741b157d00000000, 0x2c9bf7aa00000000,
+ 0x6710c9e000000000, 0x3f902b3700000000, 0x96167d9400000000,
+ 0xce969f4300000000, 0x0a3b421300000000, 0x52bba0c400000000,
+ 0xfb3df66700000000, 0xa3bd14b000000000, 0xe8362afa00000000,
+ 0xb0b6c82d00000000, 0x19309e8e00000000, 0x41b07c5900000000,
+ 0x8f26e31a00000000, 0xd7a601cd00000000, 0x7e20576e00000000,
+ 0x26a0b5b900000000, 0x6d2b8bf300000000, 0x35ab692400000000,
+ 0x9c2d3f8700000000, 0xc4addd5000000000, 0x1476842600000000,
+ 0x4cf666f100000000, 0xe570305200000000, 0xbdf0d28500000000,
+ 0xf67beccf00000000, 0xaefb0e1800000000, 0x077d58bb00000000,
+ 0x5ffdba6c00000000, 0x916b252f00000000, 0xc9ebc7f800000000,
+ 0x606d915b00000000, 0x38ed738c00000000, 0x73664dc600000000,
+ 0x2be6af1100000000, 0x8260f9b200000000, 0xdae01b6500000000,
+ 0x1e4dc63500000000, 0x46cd24e200000000, 0xef4b724100000000,
+ 0xb7cb909600000000, 0xfc40aedc00000000, 0xa4c04c0b00000000,
+ 0x0d461aa800000000, 0x55c6f87f00000000, 0x9b50673c00000000,
+ 0xc3d085eb00000000, 0x6a56d34800000000, 0x32d6319f00000000,
+ 0x795d0fd500000000, 0x21dded0200000000, 0x885bbba100000000,
+ 0xd0db597600000000, 0x28ec084d00000000, 0x706cea9a00000000,
+ 0xd9eabc3900000000, 0x816a5eee00000000, 0xcae160a400000000,
+ 0x9261827300000000, 0x3be7d4d000000000, 0x6367360700000000,
+ 0xadf1a94400000000, 0xf5714b9300000000, 0x5cf71d3000000000,
+ 0x0477ffe700000000, 0x4ffcc1ad00000000, 0x177c237a00000000,
+ 0xbefa75d900000000, 0xe67a970e00000000, 0x22d74a5e00000000,
+ 0x7a57a88900000000, 0xd3d1fe2a00000000, 0x8b511cfd00000000,
+ 0xc0da22b700000000, 0x985ac06000000000, 0x31dc96c300000000,
+ 0x695c741400000000, 0xa7caeb5700000000, 0xff4a098000000000,
+ 0x56cc5f2300000000, 0x0e4cbdf400000000, 0x45c783be00000000,
+ 0x1d47616900000000, 0xb4c137ca00000000, 0xec41d51d00000000,
+ 0x3c9a8c6b00000000, 0x641a6ebc00000000, 0xcd9c381f00000000,
+ 0x951cdac800000000, 0xde97e48200000000, 0x8617065500000000,
+ 0x2f9150f600000000, 0x7711b22100000000, 0xb9872d6200000000,
+ 0xe107cfb500000000, 0x4881991600000000, 0x10017bc100000000,
+ 0x5b8a458b00000000, 0x030aa75c00000000, 0xaa8cf1ff00000000,
+ 0xf20c132800000000, 0x36a1ce7800000000, 0x6e212caf00000000,
+ 0xc7a77a0c00000000, 0x9f2798db00000000, 0xd4aca69100000000,
+ 0x8c2c444600000000, 0x25aa12e500000000, 0x7d2af03200000000,
+ 0xb3bc6f7100000000, 0xeb3c8da600000000, 0x42badb0500000000,
+ 0x1a3a39d200000000, 0x51b1079800000000, 0x0931e54f00000000,
+ 0xa0b7b3ec00000000, 0xf837513b00000000, 0x50d8119a00000000,
+ 0x0858f34d00000000, 0xa1dea5ee00000000, 0xf95e473900000000,
+ 0xb2d5797300000000, 0xea559ba400000000, 0x43d3cd0700000000,
+ 0x1b532fd000000000, 0xd5c5b09300000000, 0x8d45524400000000,
+ 0x24c304e700000000, 0x7c43e63000000000, 0x37c8d87a00000000,
+ 0x6f483aad00000000, 0xc6ce6c0e00000000, 0x9e4e8ed900000000,
+ 0x5ae3538900000000, 0x0263b15e00000000, 0xabe5e7fd00000000,
+ 0xf365052a00000000, 0xb8ee3b6000000000, 0xe06ed9b700000000,
+ 0x49e88f1400000000, 0x11686dc300000000, 0xdffef28000000000,
+ 0x877e105700000000, 0x2ef846f400000000, 0x7678a42300000000,
+ 0x3df39a6900000000, 0x657378be00000000, 0xccf52e1d00000000,
+ 0x9475ccca00000000, 0x44ae95bc00000000, 0x1c2e776b00000000,
+ 0xb5a821c800000000, 0xed28c31f00000000, 0xa6a3fd5500000000,
+ 0xfe231f8200000000, 0x57a5492100000000, 0x0f25abf600000000,
+ 0xc1b334b500000000, 0x9933d66200000000, 0x30b580c100000000,
+ 0x6835621600000000, 0x23be5c5c00000000, 0x7b3ebe8b00000000,
+ 0xd2b8e82800000000, 0x8a380aff00000000, 0x4e95d7af00000000,
+ 0x1615357800000000, 0xbf9363db00000000, 0xe713810c00000000,
+ 0xac98bf4600000000, 0xf4185d9100000000, 0x5d9e0b3200000000,
+ 0x051ee9e500000000, 0xcb8876a600000000, 0x9308947100000000,
+ 0x3a8ec2d200000000, 0x620e200500000000, 0x29851e4f00000000,
+ 0x7105fc9800000000, 0xd883aa3b00000000, 0x800348ec00000000,
+ 0x783419d700000000, 0x20b4fb0000000000, 0x8932ada300000000,
+ 0xd1b24f7400000000, 0x9a39713e00000000, 0xc2b993e900000000,
+ 0x6b3fc54a00000000, 0x33bf279d00000000, 0xfd29b8de00000000,
+ 0xa5a95a0900000000, 0x0c2f0caa00000000, 0x54afee7d00000000,
+ 0x1f24d03700000000, 0x47a432e000000000, 0xee22644300000000,
+ 0xb6a2869400000000, 0x720f5bc400000000, 0x2a8fb91300000000,
+ 0x8309efb000000000, 0xdb890d6700000000, 0x9002332d00000000,
+ 0xc882d1fa00000000, 0x6104875900000000, 0x3984658e00000000,
+ 0xf712facd00000000, 0xaf92181a00000000, 0x06144eb900000000,
+ 0x5e94ac6e00000000, 0x151f922400000000, 0x4d9f70f300000000,
+ 0xe419265000000000, 0xbc99c48700000000, 0x6c429df100000000,
+ 0x34c27f2600000000, 0x9d44298500000000, 0xc5c4cb5200000000,
+ 0x8e4ff51800000000, 0xd6cf17cf00000000, 0x7f49416c00000000,
+ 0x27c9a3bb00000000, 0xe95f3cf800000000, 0xb1dfde2f00000000,
+ 0x1859888c00000000, 0x40d96a5b00000000, 0x0b52541100000000,
+ 0x53d2b6c600000000, 0xfa54e06500000000, 0xa2d402b200000000,
+ 0x6679dfe200000000, 0x3ef93d3500000000, 0x977f6b9600000000,
+ 0xcfff894100000000, 0x8474b70b00000000, 0xdcf455dc00000000,
+ 0x7572037f00000000, 0x2df2e1a800000000, 0xe3647eeb00000000,
+ 0xbbe49c3c00000000, 0x1262ca9f00000000, 0x4ae2284800000000,
+ 0x0169160200000000, 0x59e9f4d500000000, 0xf06fa27600000000,
+ 0xa8ef40a100000000},
+ {0x0000000000000000, 0x463b676500000000, 0x8c76ceca00000000,
+ 0xca4da9af00000000, 0x59ebed4e00000000, 0x1fd08a2b00000000,
+ 0xd59d238400000000, 0x93a644e100000000, 0xb2d6db9d00000000,
+ 0xf4edbcf800000000, 0x3ea0155700000000, 0x789b723200000000,
+ 0xeb3d36d300000000, 0xad0651b600000000, 0x674bf81900000000,
+ 0x21709f7c00000000, 0x25abc6e000000000, 0x6390a18500000000,
+ 0xa9dd082a00000000, 0xefe66f4f00000000, 0x7c402bae00000000,
+ 0x3a7b4ccb00000000, 0xf036e56400000000, 0xb60d820100000000,
+ 0x977d1d7d00000000, 0xd1467a1800000000, 0x1b0bd3b700000000,
+ 0x5d30b4d200000000, 0xce96f03300000000, 0x88ad975600000000,
+ 0x42e03ef900000000, 0x04db599c00000000, 0x0b50fc1a00000000,
+ 0x4d6b9b7f00000000, 0x872632d000000000, 0xc11d55b500000000,
+ 0x52bb115400000000, 0x1480763100000000, 0xdecddf9e00000000,
+ 0x98f6b8fb00000000, 0xb986278700000000, 0xffbd40e200000000,
+ 0x35f0e94d00000000, 0x73cb8e2800000000, 0xe06dcac900000000,
+ 0xa656adac00000000, 0x6c1b040300000000, 0x2a20636600000000,
+ 0x2efb3afa00000000, 0x68c05d9f00000000, 0xa28df43000000000,
+ 0xe4b6935500000000, 0x7710d7b400000000, 0x312bb0d100000000,
+ 0xfb66197e00000000, 0xbd5d7e1b00000000, 0x9c2de16700000000,
+ 0xda16860200000000, 0x105b2fad00000000, 0x566048c800000000,
+ 0xc5c60c2900000000, 0x83fd6b4c00000000, 0x49b0c2e300000000,
+ 0x0f8ba58600000000, 0x16a0f83500000000, 0x509b9f5000000000,
+ 0x9ad636ff00000000, 0xdced519a00000000, 0x4f4b157b00000000,
+ 0x0970721e00000000, 0xc33ddbb100000000, 0x8506bcd400000000,
+ 0xa47623a800000000, 0xe24d44cd00000000, 0x2800ed6200000000,
+ 0x6e3b8a0700000000, 0xfd9dcee600000000, 0xbba6a98300000000,
+ 0x71eb002c00000000, 0x37d0674900000000, 0x330b3ed500000000,
+ 0x753059b000000000, 0xbf7df01f00000000, 0xf946977a00000000,
+ 0x6ae0d39b00000000, 0x2cdbb4fe00000000, 0xe6961d5100000000,
+ 0xa0ad7a3400000000, 0x81dde54800000000, 0xc7e6822d00000000,
+ 0x0dab2b8200000000, 0x4b904ce700000000, 0xd836080600000000,
+ 0x9e0d6f6300000000, 0x5440c6cc00000000, 0x127ba1a900000000,
+ 0x1df0042f00000000, 0x5bcb634a00000000, 0x9186cae500000000,
+ 0xd7bdad8000000000, 0x441be96100000000, 0x02208e0400000000,
+ 0xc86d27ab00000000, 0x8e5640ce00000000, 0xaf26dfb200000000,
+ 0xe91db8d700000000, 0x2350117800000000, 0x656b761d00000000,
+ 0xf6cd32fc00000000, 0xb0f6559900000000, 0x7abbfc3600000000,
+ 0x3c809b5300000000, 0x385bc2cf00000000, 0x7e60a5aa00000000,
+ 0xb42d0c0500000000, 0xf2166b6000000000, 0x61b02f8100000000,
+ 0x278b48e400000000, 0xedc6e14b00000000, 0xabfd862e00000000,
+ 0x8a8d195200000000, 0xccb67e3700000000, 0x06fbd79800000000,
+ 0x40c0b0fd00000000, 0xd366f41c00000000, 0x955d937900000000,
+ 0x5f103ad600000000, 0x192b5db300000000, 0x2c40f16b00000000,
+ 0x6a7b960e00000000, 0xa0363fa100000000, 0xe60d58c400000000,
+ 0x75ab1c2500000000, 0x33907b4000000000, 0xf9ddd2ef00000000,
+ 0xbfe6b58a00000000, 0x9e962af600000000, 0xd8ad4d9300000000,
+ 0x12e0e43c00000000, 0x54db835900000000, 0xc77dc7b800000000,
+ 0x8146a0dd00000000, 0x4b0b097200000000, 0x0d306e1700000000,
+ 0x09eb378b00000000, 0x4fd050ee00000000, 0x859df94100000000,
+ 0xc3a69e2400000000, 0x5000dac500000000, 0x163bbda000000000,
+ 0xdc76140f00000000, 0x9a4d736a00000000, 0xbb3dec1600000000,
+ 0xfd068b7300000000, 0x374b22dc00000000, 0x717045b900000000,
+ 0xe2d6015800000000, 0xa4ed663d00000000, 0x6ea0cf9200000000,
+ 0x289ba8f700000000, 0x27100d7100000000, 0x612b6a1400000000,
+ 0xab66c3bb00000000, 0xed5da4de00000000, 0x7efbe03f00000000,
+ 0x38c0875a00000000, 0xf28d2ef500000000, 0xb4b6499000000000,
+ 0x95c6d6ec00000000, 0xd3fdb18900000000, 0x19b0182600000000,
+ 0x5f8b7f4300000000, 0xcc2d3ba200000000, 0x8a165cc700000000,
+ 0x405bf56800000000, 0x0660920d00000000, 0x02bbcb9100000000,
+ 0x4480acf400000000, 0x8ecd055b00000000, 0xc8f6623e00000000,
+ 0x5b5026df00000000, 0x1d6b41ba00000000, 0xd726e81500000000,
+ 0x911d8f7000000000, 0xb06d100c00000000, 0xf656776900000000,
+ 0x3c1bdec600000000, 0x7a20b9a300000000, 0xe986fd4200000000,
+ 0xafbd9a2700000000, 0x65f0338800000000, 0x23cb54ed00000000,
+ 0x3ae0095e00000000, 0x7cdb6e3b00000000, 0xb696c79400000000,
+ 0xf0ada0f100000000, 0x630be41000000000, 0x2530837500000000,
+ 0xef7d2ada00000000, 0xa9464dbf00000000, 0x8836d2c300000000,
+ 0xce0db5a600000000, 0x04401c0900000000, 0x427b7b6c00000000,
+ 0xd1dd3f8d00000000, 0x97e658e800000000, 0x5dabf14700000000,
+ 0x1b90962200000000, 0x1f4bcfbe00000000, 0x5970a8db00000000,
+ 0x933d017400000000, 0xd506661100000000, 0x46a022f000000000,
+ 0x009b459500000000, 0xcad6ec3a00000000, 0x8ced8b5f00000000,
+ 0xad9d142300000000, 0xeba6734600000000, 0x21ebdae900000000,
+ 0x67d0bd8c00000000, 0xf476f96d00000000, 0xb24d9e0800000000,
+ 0x780037a700000000, 0x3e3b50c200000000, 0x31b0f54400000000,
+ 0x778b922100000000, 0xbdc63b8e00000000, 0xfbfd5ceb00000000,
+ 0x685b180a00000000, 0x2e607f6f00000000, 0xe42dd6c000000000,
+ 0xa216b1a500000000, 0x83662ed900000000, 0xc55d49bc00000000,
+ 0x0f10e01300000000, 0x492b877600000000, 0xda8dc39700000000,
+ 0x9cb6a4f200000000, 0x56fb0d5d00000000, 0x10c06a3800000000,
+ 0x141b33a400000000, 0x522054c100000000, 0x986dfd6e00000000,
+ 0xde569a0b00000000, 0x4df0deea00000000, 0x0bcbb98f00000000,
+ 0xc186102000000000, 0x87bd774500000000, 0xa6cde83900000000,
+ 0xe0f68f5c00000000, 0x2abb26f300000000, 0x6c80419600000000,
+ 0xff26057700000000, 0xb91d621200000000, 0x7350cbbd00000000,
+ 0x356bacd800000000},
+ {0x0000000000000000, 0x9e83da9f00000000, 0x7d01c4e400000000,
+ 0xe3821e7b00000000, 0xbb04f91200000000, 0x2587238d00000000,
+ 0xc6053df600000000, 0x5886e76900000000, 0x7609f22500000000,
+ 0xe88a28ba00000000, 0x0b0836c100000000, 0x958bec5e00000000,
+ 0xcd0d0b3700000000, 0x538ed1a800000000, 0xb00ccfd300000000,
+ 0x2e8f154c00000000, 0xec12e44b00000000, 0x72913ed400000000,
+ 0x911320af00000000, 0x0f90fa3000000000, 0x57161d5900000000,
+ 0xc995c7c600000000, 0x2a17d9bd00000000, 0xb494032200000000,
+ 0x9a1b166e00000000, 0x0498ccf100000000, 0xe71ad28a00000000,
+ 0x7999081500000000, 0x211fef7c00000000, 0xbf9c35e300000000,
+ 0x5c1e2b9800000000, 0xc29df10700000000, 0xd825c89700000000,
+ 0x46a6120800000000, 0xa5240c7300000000, 0x3ba7d6ec00000000,
+ 0x6321318500000000, 0xfda2eb1a00000000, 0x1e20f56100000000,
+ 0x80a32ffe00000000, 0xae2c3ab200000000, 0x30afe02d00000000,
+ 0xd32dfe5600000000, 0x4dae24c900000000, 0x1528c3a000000000,
+ 0x8bab193f00000000, 0x6829074400000000, 0xf6aadddb00000000,
+ 0x34372cdc00000000, 0xaab4f64300000000, 0x4936e83800000000,
+ 0xd7b532a700000000, 0x8f33d5ce00000000, 0x11b00f5100000000,
+ 0xf232112a00000000, 0x6cb1cbb500000000, 0x423edef900000000,
+ 0xdcbd046600000000, 0x3f3f1a1d00000000, 0xa1bcc08200000000,
+ 0xf93a27eb00000000, 0x67b9fd7400000000, 0x843be30f00000000,
+ 0x1ab8399000000000, 0xf14de1f400000000, 0x6fce3b6b00000000,
+ 0x8c4c251000000000, 0x12cfff8f00000000, 0x4a4918e600000000,
+ 0xd4cac27900000000, 0x3748dc0200000000, 0xa9cb069d00000000,
+ 0x874413d100000000, 0x19c7c94e00000000, 0xfa45d73500000000,
+ 0x64c60daa00000000, 0x3c40eac300000000, 0xa2c3305c00000000,
+ 0x41412e2700000000, 0xdfc2f4b800000000, 0x1d5f05bf00000000,
+ 0x83dcdf2000000000, 0x605ec15b00000000, 0xfedd1bc400000000,
+ 0xa65bfcad00000000, 0x38d8263200000000, 0xdb5a384900000000,
+ 0x45d9e2d600000000, 0x6b56f79a00000000, 0xf5d52d0500000000,
+ 0x1657337e00000000, 0x88d4e9e100000000, 0xd0520e8800000000,
+ 0x4ed1d41700000000, 0xad53ca6c00000000, 0x33d010f300000000,
+ 0x2968296300000000, 0xb7ebf3fc00000000, 0x5469ed8700000000,
+ 0xcaea371800000000, 0x926cd07100000000, 0x0cef0aee00000000,
+ 0xef6d149500000000, 0x71eece0a00000000, 0x5f61db4600000000,
+ 0xc1e201d900000000, 0x22601fa200000000, 0xbce3c53d00000000,
+ 0xe465225400000000, 0x7ae6f8cb00000000, 0x9964e6b000000000,
+ 0x07e73c2f00000000, 0xc57acd2800000000, 0x5bf917b700000000,
+ 0xb87b09cc00000000, 0x26f8d35300000000, 0x7e7e343a00000000,
+ 0xe0fdeea500000000, 0x037ff0de00000000, 0x9dfc2a4100000000,
+ 0xb3733f0d00000000, 0x2df0e59200000000, 0xce72fbe900000000,
+ 0x50f1217600000000, 0x0877c61f00000000, 0x96f41c8000000000,
+ 0x757602fb00000000, 0xebf5d86400000000, 0xa39db33200000000,
+ 0x3d1e69ad00000000, 0xde9c77d600000000, 0x401fad4900000000,
+ 0x18994a2000000000, 0x861a90bf00000000, 0x65988ec400000000,
+ 0xfb1b545b00000000, 0xd594411700000000, 0x4b179b8800000000,
+ 0xa89585f300000000, 0x36165f6c00000000, 0x6e90b80500000000,
+ 0xf013629a00000000, 0x13917ce100000000, 0x8d12a67e00000000,
+ 0x4f8f577900000000, 0xd10c8de600000000, 0x328e939d00000000,
+ 0xac0d490200000000, 0xf48bae6b00000000, 0x6a0874f400000000,
+ 0x898a6a8f00000000, 0x1709b01000000000, 0x3986a55c00000000,
+ 0xa7057fc300000000, 0x448761b800000000, 0xda04bb2700000000,
+ 0x82825c4e00000000, 0x1c0186d100000000, 0xff8398aa00000000,
+ 0x6100423500000000, 0x7bb87ba500000000, 0xe53ba13a00000000,
+ 0x06b9bf4100000000, 0x983a65de00000000, 0xc0bc82b700000000,
+ 0x5e3f582800000000, 0xbdbd465300000000, 0x233e9ccc00000000,
+ 0x0db1898000000000, 0x9332531f00000000, 0x70b04d6400000000,
+ 0xee3397fb00000000, 0xb6b5709200000000, 0x2836aa0d00000000,
+ 0xcbb4b47600000000, 0x55376ee900000000, 0x97aa9fee00000000,
+ 0x0929457100000000, 0xeaab5b0a00000000, 0x7428819500000000,
+ 0x2cae66fc00000000, 0xb22dbc6300000000, 0x51afa21800000000,
+ 0xcf2c788700000000, 0xe1a36dcb00000000, 0x7f20b75400000000,
+ 0x9ca2a92f00000000, 0x022173b000000000, 0x5aa794d900000000,
+ 0xc4244e4600000000, 0x27a6503d00000000, 0xb9258aa200000000,
+ 0x52d052c600000000, 0xcc53885900000000, 0x2fd1962200000000,
+ 0xb1524cbd00000000, 0xe9d4abd400000000, 0x7757714b00000000,
+ 0x94d56f3000000000, 0x0a56b5af00000000, 0x24d9a0e300000000,
+ 0xba5a7a7c00000000, 0x59d8640700000000, 0xc75bbe9800000000,
+ 0x9fdd59f100000000, 0x015e836e00000000, 0xe2dc9d1500000000,
+ 0x7c5f478a00000000, 0xbec2b68d00000000, 0x20416c1200000000,
+ 0xc3c3726900000000, 0x5d40a8f600000000, 0x05c64f9f00000000,
+ 0x9b45950000000000, 0x78c78b7b00000000, 0xe64451e400000000,
+ 0xc8cb44a800000000, 0x56489e3700000000, 0xb5ca804c00000000,
+ 0x2b495ad300000000, 0x73cfbdba00000000, 0xed4c672500000000,
+ 0x0ece795e00000000, 0x904da3c100000000, 0x8af59a5100000000,
+ 0x147640ce00000000, 0xf7f45eb500000000, 0x6977842a00000000,
+ 0x31f1634300000000, 0xaf72b9dc00000000, 0x4cf0a7a700000000,
+ 0xd2737d3800000000, 0xfcfc687400000000, 0x627fb2eb00000000,
+ 0x81fdac9000000000, 0x1f7e760f00000000, 0x47f8916600000000,
+ 0xd97b4bf900000000, 0x3af9558200000000, 0xa47a8f1d00000000,
+ 0x66e77e1a00000000, 0xf864a48500000000, 0x1be6bafe00000000,
+ 0x8565606100000000, 0xdde3870800000000, 0x43605d9700000000,
+ 0xa0e243ec00000000, 0x3e61997300000000, 0x10ee8c3f00000000,
+ 0x8e6d56a000000000, 0x6def48db00000000, 0xf36c924400000000,
+ 0xabea752d00000000, 0x3569afb200000000, 0xd6ebb1c900000000,
+ 0x48686b5600000000},
+ {0x0000000000000000, 0xc064281700000000, 0x80c9502e00000000,
+ 0x40ad783900000000, 0x0093a15c00000000, 0xc0f7894b00000000,
+ 0x805af17200000000, 0x403ed96500000000, 0x002643b900000000,
+ 0xc0426bae00000000, 0x80ef139700000000, 0x408b3b8000000000,
+ 0x00b5e2e500000000, 0xc0d1caf200000000, 0x807cb2cb00000000,
+ 0x40189adc00000000, 0x414af7a900000000, 0x812edfbe00000000,
+ 0xc183a78700000000, 0x01e78f9000000000, 0x41d956f500000000,
+ 0x81bd7ee200000000, 0xc11006db00000000, 0x01742ecc00000000,
+ 0x416cb41000000000, 0x81089c0700000000, 0xc1a5e43e00000000,
+ 0x01c1cc2900000000, 0x41ff154c00000000, 0x819b3d5b00000000,
+ 0xc136456200000000, 0x01526d7500000000, 0xc3929f8800000000,
+ 0x03f6b79f00000000, 0x435bcfa600000000, 0x833fe7b100000000,
+ 0xc3013ed400000000, 0x036516c300000000, 0x43c86efa00000000,
+ 0x83ac46ed00000000, 0xc3b4dc3100000000, 0x03d0f42600000000,
+ 0x437d8c1f00000000, 0x8319a40800000000, 0xc3277d6d00000000,
+ 0x0343557a00000000, 0x43ee2d4300000000, 0x838a055400000000,
+ 0x82d8682100000000, 0x42bc403600000000, 0x0211380f00000000,
+ 0xc275101800000000, 0x824bc97d00000000, 0x422fe16a00000000,
+ 0x0282995300000000, 0xc2e6b14400000000, 0x82fe2b9800000000,
+ 0x429a038f00000000, 0x02377bb600000000, 0xc25353a100000000,
+ 0x826d8ac400000000, 0x4209a2d300000000, 0x02a4daea00000000,
+ 0xc2c0f2fd00000000, 0xc7234eca00000000, 0x074766dd00000000,
+ 0x47ea1ee400000000, 0x878e36f300000000, 0xc7b0ef9600000000,
+ 0x07d4c78100000000, 0x4779bfb800000000, 0x871d97af00000000,
+ 0xc7050d7300000000, 0x0761256400000000, 0x47cc5d5d00000000,
+ 0x87a8754a00000000, 0xc796ac2f00000000, 0x07f2843800000000,
+ 0x475ffc0100000000, 0x873bd41600000000, 0x8669b96300000000,
+ 0x460d917400000000, 0x06a0e94d00000000, 0xc6c4c15a00000000,
+ 0x86fa183f00000000, 0x469e302800000000, 0x0633481100000000,
+ 0xc657600600000000, 0x864ffada00000000, 0x462bd2cd00000000,
+ 0x0686aaf400000000, 0xc6e282e300000000, 0x86dc5b8600000000,
+ 0x46b8739100000000, 0x06150ba800000000, 0xc67123bf00000000,
+ 0x04b1d14200000000, 0xc4d5f95500000000, 0x8478816c00000000,
+ 0x441ca97b00000000, 0x0422701e00000000, 0xc446580900000000,
+ 0x84eb203000000000, 0x448f082700000000, 0x049792fb00000000,
+ 0xc4f3baec00000000, 0x845ec2d500000000, 0x443aeac200000000,
+ 0x040433a700000000, 0xc4601bb000000000, 0x84cd638900000000,
+ 0x44a94b9e00000000, 0x45fb26eb00000000, 0x859f0efc00000000,
+ 0xc53276c500000000, 0x05565ed200000000, 0x456887b700000000,
+ 0x850cafa000000000, 0xc5a1d79900000000, 0x05c5ff8e00000000,
+ 0x45dd655200000000, 0x85b94d4500000000, 0xc514357c00000000,
+ 0x05701d6b00000000, 0x454ec40e00000000, 0x852aec1900000000,
+ 0xc587942000000000, 0x05e3bc3700000000, 0xcf41ed4f00000000,
+ 0x0f25c55800000000, 0x4f88bd6100000000, 0x8fec957600000000,
+ 0xcfd24c1300000000, 0x0fb6640400000000, 0x4f1b1c3d00000000,
+ 0x8f7f342a00000000, 0xcf67aef600000000, 0x0f0386e100000000,
+ 0x4faefed800000000, 0x8fcad6cf00000000, 0xcff40faa00000000,
+ 0x0f9027bd00000000, 0x4f3d5f8400000000, 0x8f59779300000000,
+ 0x8e0b1ae600000000, 0x4e6f32f100000000, 0x0ec24ac800000000,
+ 0xcea662df00000000, 0x8e98bbba00000000, 0x4efc93ad00000000,
+ 0x0e51eb9400000000, 0xce35c38300000000, 0x8e2d595f00000000,
+ 0x4e49714800000000, 0x0ee4097100000000, 0xce80216600000000,
+ 0x8ebef80300000000, 0x4edad01400000000, 0x0e77a82d00000000,
+ 0xce13803a00000000, 0x0cd372c700000000, 0xccb75ad000000000,
+ 0x8c1a22e900000000, 0x4c7e0afe00000000, 0x0c40d39b00000000,
+ 0xcc24fb8c00000000, 0x8c8983b500000000, 0x4cedaba200000000,
+ 0x0cf5317e00000000, 0xcc91196900000000, 0x8c3c615000000000,
+ 0x4c58494700000000, 0x0c66902200000000, 0xcc02b83500000000,
+ 0x8cafc00c00000000, 0x4ccbe81b00000000, 0x4d99856e00000000,
+ 0x8dfdad7900000000, 0xcd50d54000000000, 0x0d34fd5700000000,
+ 0x4d0a243200000000, 0x8d6e0c2500000000, 0xcdc3741c00000000,
+ 0x0da75c0b00000000, 0x4dbfc6d700000000, 0x8ddbeec000000000,
+ 0xcd7696f900000000, 0x0d12beee00000000, 0x4d2c678b00000000,
+ 0x8d484f9c00000000, 0xcde537a500000000, 0x0d811fb200000000,
+ 0x0862a38500000000, 0xc8068b9200000000, 0x88abf3ab00000000,
+ 0x48cfdbbc00000000, 0x08f102d900000000, 0xc8952ace00000000,
+ 0x883852f700000000, 0x485c7ae000000000, 0x0844e03c00000000,
+ 0xc820c82b00000000, 0x888db01200000000, 0x48e9980500000000,
+ 0x08d7416000000000, 0xc8b3697700000000, 0x881e114e00000000,
+ 0x487a395900000000, 0x4928542c00000000, 0x894c7c3b00000000,
+ 0xc9e1040200000000, 0x09852c1500000000, 0x49bbf57000000000,
+ 0x89dfdd6700000000, 0xc972a55e00000000, 0x09168d4900000000,
+ 0x490e179500000000, 0x896a3f8200000000, 0xc9c747bb00000000,
+ 0x09a36fac00000000, 0x499db6c900000000, 0x89f99ede00000000,
+ 0xc954e6e700000000, 0x0930cef000000000, 0xcbf03c0d00000000,
+ 0x0b94141a00000000, 0x4b396c2300000000, 0x8b5d443400000000,
+ 0xcb639d5100000000, 0x0b07b54600000000, 0x4baacd7f00000000,
+ 0x8bcee56800000000, 0xcbd67fb400000000, 0x0bb257a300000000,
+ 0x4b1f2f9a00000000, 0x8b7b078d00000000, 0xcb45dee800000000,
+ 0x0b21f6ff00000000, 0x4b8c8ec600000000, 0x8be8a6d100000000,
+ 0x8abacba400000000, 0x4adee3b300000000, 0x0a739b8a00000000,
+ 0xca17b39d00000000, 0x8a296af800000000, 0x4a4d42ef00000000,
+ 0x0ae03ad600000000, 0xca8412c100000000, 0x8a9c881d00000000,
+ 0x4af8a00a00000000, 0x0a55d83300000000, 0xca31f02400000000,
+ 0x8a0f294100000000, 0x4a6b015600000000, 0x0ac6796f00000000,
+ 0xcaa2517800000000},
+ {0x0000000000000000, 0xd4ea739b00000000, 0xe9d396ed00000000,
+ 0x3d39e57600000000, 0x93a15c0000000000, 0x474b2f9b00000000,
+ 0x7a72caed00000000, 0xae98b97600000000, 0x2643b90000000000,
+ 0xf2a9ca9b00000000, 0xcf902fed00000000, 0x1b7a5c7600000000,
+ 0xb5e2e50000000000, 0x6108969b00000000, 0x5c3173ed00000000,
+ 0x88db007600000000, 0x4c86720100000000, 0x986c019a00000000,
+ 0xa555e4ec00000000, 0x71bf977700000000, 0xdf272e0100000000,
+ 0x0bcd5d9a00000000, 0x36f4b8ec00000000, 0xe21ecb7700000000,
+ 0x6ac5cb0100000000, 0xbe2fb89a00000000, 0x83165dec00000000,
+ 0x57fc2e7700000000, 0xf964970100000000, 0x2d8ee49a00000000,
+ 0x10b701ec00000000, 0xc45d727700000000, 0x980ce50200000000,
+ 0x4ce6969900000000, 0x71df73ef00000000, 0xa535007400000000,
+ 0x0badb90200000000, 0xdf47ca9900000000, 0xe27e2fef00000000,
+ 0x36945c7400000000, 0xbe4f5c0200000000, 0x6aa52f9900000000,
+ 0x579ccaef00000000, 0x8376b97400000000, 0x2dee000200000000,
+ 0xf904739900000000, 0xc43d96ef00000000, 0x10d7e57400000000,
+ 0xd48a970300000000, 0x0060e49800000000, 0x3d5901ee00000000,
+ 0xe9b3727500000000, 0x472bcb0300000000, 0x93c1b89800000000,
+ 0xaef85dee00000000, 0x7a122e7500000000, 0xf2c92e0300000000,
+ 0x26235d9800000000, 0x1b1ab8ee00000000, 0xcff0cb7500000000,
+ 0x6168720300000000, 0xb582019800000000, 0x88bbe4ee00000000,
+ 0x5c51977500000000, 0x3019ca0500000000, 0xe4f3b99e00000000,
+ 0xd9ca5ce800000000, 0x0d202f7300000000, 0xa3b8960500000000,
+ 0x7752e59e00000000, 0x4a6b00e800000000, 0x9e81737300000000,
+ 0x165a730500000000, 0xc2b0009e00000000, 0xff89e5e800000000,
+ 0x2b63967300000000, 0x85fb2f0500000000, 0x51115c9e00000000,
+ 0x6c28b9e800000000, 0xb8c2ca7300000000, 0x7c9fb80400000000,
+ 0xa875cb9f00000000, 0x954c2ee900000000, 0x41a65d7200000000,
+ 0xef3ee40400000000, 0x3bd4979f00000000, 0x06ed72e900000000,
+ 0xd207017200000000, 0x5adc010400000000, 0x8e36729f00000000,
+ 0xb30f97e900000000, 0x67e5e47200000000, 0xc97d5d0400000000,
+ 0x1d972e9f00000000, 0x20aecbe900000000, 0xf444b87200000000,
+ 0xa8152f0700000000, 0x7cff5c9c00000000, 0x41c6b9ea00000000,
+ 0x952cca7100000000, 0x3bb4730700000000, 0xef5e009c00000000,
+ 0xd267e5ea00000000, 0x068d967100000000, 0x8e56960700000000,
+ 0x5abce59c00000000, 0x678500ea00000000, 0xb36f737100000000,
+ 0x1df7ca0700000000, 0xc91db99c00000000, 0xf4245cea00000000,
+ 0x20ce2f7100000000, 0xe4935d0600000000, 0x30792e9d00000000,
+ 0x0d40cbeb00000000, 0xd9aab87000000000, 0x7732010600000000,
+ 0xa3d8729d00000000, 0x9ee197eb00000000, 0x4a0be47000000000,
+ 0xc2d0e40600000000, 0x163a979d00000000, 0x2b0372eb00000000,
+ 0xffe9017000000000, 0x5171b80600000000, 0x859bcb9d00000000,
+ 0xb8a22eeb00000000, 0x6c485d7000000000, 0x6032940b00000000,
+ 0xb4d8e79000000000, 0x89e102e600000000, 0x5d0b717d00000000,
+ 0xf393c80b00000000, 0x2779bb9000000000, 0x1a405ee600000000,
+ 0xceaa2d7d00000000, 0x46712d0b00000000, 0x929b5e9000000000,
+ 0xafa2bbe600000000, 0x7b48c87d00000000, 0xd5d0710b00000000,
+ 0x013a029000000000, 0x3c03e7e600000000, 0xe8e9947d00000000,
+ 0x2cb4e60a00000000, 0xf85e959100000000, 0xc56770e700000000,
+ 0x118d037c00000000, 0xbf15ba0a00000000, 0x6bffc99100000000,
+ 0x56c62ce700000000, 0x822c5f7c00000000, 0x0af75f0a00000000,
+ 0xde1d2c9100000000, 0xe324c9e700000000, 0x37ceba7c00000000,
+ 0x9956030a00000000, 0x4dbc709100000000, 0x708595e700000000,
+ 0xa46fe67c00000000, 0xf83e710900000000, 0x2cd4029200000000,
+ 0x11ede7e400000000, 0xc507947f00000000, 0x6b9f2d0900000000,
+ 0xbf755e9200000000, 0x824cbbe400000000, 0x56a6c87f00000000,
+ 0xde7dc80900000000, 0x0a97bb9200000000, 0x37ae5ee400000000,
+ 0xe3442d7f00000000, 0x4ddc940900000000, 0x9936e79200000000,
+ 0xa40f02e400000000, 0x70e5717f00000000, 0xb4b8030800000000,
+ 0x6052709300000000, 0x5d6b95e500000000, 0x8981e67e00000000,
+ 0x27195f0800000000, 0xf3f32c9300000000, 0xcecac9e500000000,
+ 0x1a20ba7e00000000, 0x92fbba0800000000, 0x4611c99300000000,
+ 0x7b282ce500000000, 0xafc25f7e00000000, 0x015ae60800000000,
+ 0xd5b0959300000000, 0xe88970e500000000, 0x3c63037e00000000,
+ 0x502b5e0e00000000, 0x84c12d9500000000, 0xb9f8c8e300000000,
+ 0x6d12bb7800000000, 0xc38a020e00000000, 0x1760719500000000,
+ 0x2a5994e300000000, 0xfeb3e77800000000, 0x7668e70e00000000,
+ 0xa282949500000000, 0x9fbb71e300000000, 0x4b51027800000000,
+ 0xe5c9bb0e00000000, 0x3123c89500000000, 0x0c1a2de300000000,
+ 0xd8f05e7800000000, 0x1cad2c0f00000000, 0xc8475f9400000000,
+ 0xf57ebae200000000, 0x2194c97900000000, 0x8f0c700f00000000,
+ 0x5be6039400000000, 0x66dfe6e200000000, 0xb235957900000000,
+ 0x3aee950f00000000, 0xee04e69400000000, 0xd33d03e200000000,
+ 0x07d7707900000000, 0xa94fc90f00000000, 0x7da5ba9400000000,
+ 0x409c5fe200000000, 0x94762c7900000000, 0xc827bb0c00000000,
+ 0x1ccdc89700000000, 0x21f42de100000000, 0xf51e5e7a00000000,
+ 0x5b86e70c00000000, 0x8f6c949700000000, 0xb25571e100000000,
+ 0x66bf027a00000000, 0xee64020c00000000, 0x3a8e719700000000,
+ 0x07b794e100000000, 0xd35de77a00000000, 0x7dc55e0c00000000,
+ 0xa92f2d9700000000, 0x9416c8e100000000, 0x40fcbb7a00000000,
+ 0x84a1c90d00000000, 0x504bba9600000000, 0x6d725fe000000000,
+ 0xb9982c7b00000000, 0x1700950d00000000, 0xc3eae69600000000,
+ 0xfed303e000000000, 0x2a39707b00000000, 0xa2e2700d00000000,
+ 0x7608039600000000, 0x4b31e6e000000000, 0x9fdb957b00000000,
+ 0x31432c0d00000000, 0xe5a95f9600000000, 0xd890bae000000000,
+ 0x0c7ac97b00000000},
+ {0x0000000000000000, 0x2765258100000000, 0x0fcc3bd900000000,
+ 0x28a91e5800000000, 0x5f9e066900000000, 0x78fb23e800000000,
+ 0x50523db000000000, 0x7737183100000000, 0xbe3c0dd200000000,
+ 0x9959285300000000, 0xb1f0360b00000000, 0x9695138a00000000,
+ 0xe1a20bbb00000000, 0xc6c72e3a00000000, 0xee6e306200000000,
+ 0xc90b15e300000000, 0x3d7f6b7f00000000, 0x1a1a4efe00000000,
+ 0x32b350a600000000, 0x15d6752700000000, 0x62e16d1600000000,
+ 0x4584489700000000, 0x6d2d56cf00000000, 0x4a48734e00000000,
+ 0x834366ad00000000, 0xa426432c00000000, 0x8c8f5d7400000000,
+ 0xabea78f500000000, 0xdcdd60c400000000, 0xfbb8454500000000,
+ 0xd3115b1d00000000, 0xf4747e9c00000000, 0x7afed6fe00000000,
+ 0x5d9bf37f00000000, 0x7532ed2700000000, 0x5257c8a600000000,
+ 0x2560d09700000000, 0x0205f51600000000, 0x2aaceb4e00000000,
+ 0x0dc9cecf00000000, 0xc4c2db2c00000000, 0xe3a7fead00000000,
+ 0xcb0ee0f500000000, 0xec6bc57400000000, 0x9b5cdd4500000000,
+ 0xbc39f8c400000000, 0x9490e69c00000000, 0xb3f5c31d00000000,
+ 0x4781bd8100000000, 0x60e4980000000000, 0x484d865800000000,
+ 0x6f28a3d900000000, 0x181fbbe800000000, 0x3f7a9e6900000000,
+ 0x17d3803100000000, 0x30b6a5b000000000, 0xf9bdb05300000000,
+ 0xded895d200000000, 0xf6718b8a00000000, 0xd114ae0b00000000,
+ 0xa623b63a00000000, 0x814693bb00000000, 0xa9ef8de300000000,
+ 0x8e8aa86200000000, 0xb5fadc2600000000, 0x929ff9a700000000,
+ 0xba36e7ff00000000, 0x9d53c27e00000000, 0xea64da4f00000000,
+ 0xcd01ffce00000000, 0xe5a8e19600000000, 0xc2cdc41700000000,
+ 0x0bc6d1f400000000, 0x2ca3f47500000000, 0x040aea2d00000000,
+ 0x236fcfac00000000, 0x5458d79d00000000, 0x733df21c00000000,
+ 0x5b94ec4400000000, 0x7cf1c9c500000000, 0x8885b75900000000,
+ 0xafe092d800000000, 0x87498c8000000000, 0xa02ca90100000000,
+ 0xd71bb13000000000, 0xf07e94b100000000, 0xd8d78ae900000000,
+ 0xffb2af6800000000, 0x36b9ba8b00000000, 0x11dc9f0a00000000,
+ 0x3975815200000000, 0x1e10a4d300000000, 0x6927bce200000000,
+ 0x4e42996300000000, 0x66eb873b00000000, 0x418ea2ba00000000,
+ 0xcf040ad800000000, 0xe8612f5900000000, 0xc0c8310100000000,
+ 0xe7ad148000000000, 0x909a0cb100000000, 0xb7ff293000000000,
+ 0x9f56376800000000, 0xb83312e900000000, 0x7138070a00000000,
+ 0x565d228b00000000, 0x7ef43cd300000000, 0x5991195200000000,
+ 0x2ea6016300000000, 0x09c324e200000000, 0x216a3aba00000000,
+ 0x060f1f3b00000000, 0xf27b61a700000000, 0xd51e442600000000,
+ 0xfdb75a7e00000000, 0xdad27fff00000000, 0xade567ce00000000,
+ 0x8a80424f00000000, 0xa2295c1700000000, 0x854c799600000000,
+ 0x4c476c7500000000, 0x6b2249f400000000, 0x438b57ac00000000,
+ 0x64ee722d00000000, 0x13d96a1c00000000, 0x34bc4f9d00000000,
+ 0x1c1551c500000000, 0x3b70744400000000, 0x6af5b94d00000000,
+ 0x4d909ccc00000000, 0x6539829400000000, 0x425ca71500000000,
+ 0x356bbf2400000000, 0x120e9aa500000000, 0x3aa784fd00000000,
+ 0x1dc2a17c00000000, 0xd4c9b49f00000000, 0xf3ac911e00000000,
+ 0xdb058f4600000000, 0xfc60aac700000000, 0x8b57b2f600000000,
+ 0xac32977700000000, 0x849b892f00000000, 0xa3feacae00000000,
+ 0x578ad23200000000, 0x70eff7b300000000, 0x5846e9eb00000000,
+ 0x7f23cc6a00000000, 0x0814d45b00000000, 0x2f71f1da00000000,
+ 0x07d8ef8200000000, 0x20bdca0300000000, 0xe9b6dfe000000000,
+ 0xced3fa6100000000, 0xe67ae43900000000, 0xc11fc1b800000000,
+ 0xb628d98900000000, 0x914dfc0800000000, 0xb9e4e25000000000,
+ 0x9e81c7d100000000, 0x100b6fb300000000, 0x376e4a3200000000,
+ 0x1fc7546a00000000, 0x38a271eb00000000, 0x4f9569da00000000,
+ 0x68f04c5b00000000, 0x4059520300000000, 0x673c778200000000,
+ 0xae37626100000000, 0x895247e000000000, 0xa1fb59b800000000,
+ 0x869e7c3900000000, 0xf1a9640800000000, 0xd6cc418900000000,
+ 0xfe655fd100000000, 0xd9007a5000000000, 0x2d7404cc00000000,
+ 0x0a11214d00000000, 0x22b83f1500000000, 0x05dd1a9400000000,
+ 0x72ea02a500000000, 0x558f272400000000, 0x7d26397c00000000,
+ 0x5a431cfd00000000, 0x9348091e00000000, 0xb42d2c9f00000000,
+ 0x9c8432c700000000, 0xbbe1174600000000, 0xccd60f7700000000,
+ 0xebb32af600000000, 0xc31a34ae00000000, 0xe47f112f00000000,
+ 0xdf0f656b00000000, 0xf86a40ea00000000, 0xd0c35eb200000000,
+ 0xf7a67b3300000000, 0x8091630200000000, 0xa7f4468300000000,
+ 0x8f5d58db00000000, 0xa8387d5a00000000, 0x613368b900000000,
+ 0x46564d3800000000, 0x6eff536000000000, 0x499a76e100000000,
+ 0x3ead6ed000000000, 0x19c84b5100000000, 0x3161550900000000,
+ 0x1604708800000000, 0xe2700e1400000000, 0xc5152b9500000000,
+ 0xedbc35cd00000000, 0xcad9104c00000000, 0xbdee087d00000000,
+ 0x9a8b2dfc00000000, 0xb22233a400000000, 0x9547162500000000,
+ 0x5c4c03c600000000, 0x7b29264700000000, 0x5380381f00000000,
+ 0x74e51d9e00000000, 0x03d205af00000000, 0x24b7202e00000000,
+ 0x0c1e3e7600000000, 0x2b7b1bf700000000, 0xa5f1b39500000000,
+ 0x8294961400000000, 0xaa3d884c00000000, 0x8d58adcd00000000,
+ 0xfa6fb5fc00000000, 0xdd0a907d00000000, 0xf5a38e2500000000,
+ 0xd2c6aba400000000, 0x1bcdbe4700000000, 0x3ca89bc600000000,
+ 0x1401859e00000000, 0x3364a01f00000000, 0x4453b82e00000000,
+ 0x63369daf00000000, 0x4b9f83f700000000, 0x6cfaa67600000000,
+ 0x988ed8ea00000000, 0xbfebfd6b00000000, 0x9742e33300000000,
+ 0xb027c6b200000000, 0xc710de8300000000, 0xe075fb0200000000,
+ 0xc8dce55a00000000, 0xefb9c0db00000000, 0x26b2d53800000000,
+ 0x01d7f0b900000000, 0x297eeee100000000, 0x0e1bcb6000000000,
+ 0x792cd35100000000, 0x5e49f6d000000000, 0x76e0e88800000000,
+ 0x5185cd0900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x9ba54c6f, 0xec3b9e9f, 0x779ed2f0, 0x03063b7f,
+ 0x98a37710, 0xef3da5e0, 0x7498e98f, 0x060c76fe, 0x9da93a91,
+ 0xea37e861, 0x7192a40e, 0x050a4d81, 0x9eaf01ee, 0xe931d31e,
+ 0x72949f71, 0x0c18edfc, 0x97bda193, 0xe0237363, 0x7b863f0c,
+ 0x0f1ed683, 0x94bb9aec, 0xe325481c, 0x78800473, 0x0a149b02,
+ 0x91b1d76d, 0xe62f059d, 0x7d8a49f2, 0x0912a07d, 0x92b7ec12,
+ 0xe5293ee2, 0x7e8c728d, 0x1831dbf8, 0x83949797, 0xf40a4567,
+ 0x6faf0908, 0x1b37e087, 0x8092ace8, 0xf70c7e18, 0x6ca93277,
+ 0x1e3dad06, 0x8598e169, 0xf2063399, 0x69a37ff6, 0x1d3b9679,
+ 0x869eda16, 0xf10008e6, 0x6aa54489, 0x14293604, 0x8f8c7a6b,
+ 0xf812a89b, 0x63b7e4f4, 0x172f0d7b, 0x8c8a4114, 0xfb1493e4,
+ 0x60b1df8b, 0x122540fa, 0x89800c95, 0xfe1ede65, 0x65bb920a,
+ 0x11237b85, 0x8a8637ea, 0xfd18e51a, 0x66bda975, 0x3063b7f0,
+ 0xabc6fb9f, 0xdc58296f, 0x47fd6500, 0x33658c8f, 0xa8c0c0e0,
+ 0xdf5e1210, 0x44fb5e7f, 0x366fc10e, 0xadca8d61, 0xda545f91,
+ 0x41f113fe, 0x3569fa71, 0xaeccb61e, 0xd95264ee, 0x42f72881,
+ 0x3c7b5a0c, 0xa7de1663, 0xd040c493, 0x4be588fc, 0x3f7d6173,
+ 0xa4d82d1c, 0xd346ffec, 0x48e3b383, 0x3a772cf2, 0xa1d2609d,
+ 0xd64cb26d, 0x4de9fe02, 0x3971178d, 0xa2d45be2, 0xd54a8912,
+ 0x4eefc57d, 0x28526c08, 0xb3f72067, 0xc469f297, 0x5fccbef8,
+ 0x2b545777, 0xb0f11b18, 0xc76fc9e8, 0x5cca8587, 0x2e5e1af6,
+ 0xb5fb5699, 0xc2658469, 0x59c0c806, 0x2d582189, 0xb6fd6de6,
+ 0xc163bf16, 0x5ac6f379, 0x244a81f4, 0xbfefcd9b, 0xc8711f6b,
+ 0x53d45304, 0x274cba8b, 0xbce9f6e4, 0xcb772414, 0x50d2687b,
+ 0x2246f70a, 0xb9e3bb65, 0xce7d6995, 0x55d825fa, 0x2140cc75,
+ 0xbae5801a, 0xcd7b52ea, 0x56de1e85, 0x60c76fe0, 0xfb62238f,
+ 0x8cfcf17f, 0x1759bd10, 0x63c1549f, 0xf86418f0, 0x8ffaca00,
+ 0x145f866f, 0x66cb191e, 0xfd6e5571, 0x8af08781, 0x1155cbee,
+ 0x65cd2261, 0xfe686e0e, 0x89f6bcfe, 0x1253f091, 0x6cdf821c,
+ 0xf77ace73, 0x80e41c83, 0x1b4150ec, 0x6fd9b963, 0xf47cf50c,
+ 0x83e227fc, 0x18476b93, 0x6ad3f4e2, 0xf176b88d, 0x86e86a7d,
+ 0x1d4d2612, 0x69d5cf9d, 0xf27083f2, 0x85ee5102, 0x1e4b1d6d,
+ 0x78f6b418, 0xe353f877, 0x94cd2a87, 0x0f6866e8, 0x7bf08f67,
+ 0xe055c308, 0x97cb11f8, 0x0c6e5d97, 0x7efac2e6, 0xe55f8e89,
+ 0x92c15c79, 0x09641016, 0x7dfcf999, 0xe659b5f6, 0x91c76706,
+ 0x0a622b69, 0x74ee59e4, 0xef4b158b, 0x98d5c77b, 0x03708b14,
+ 0x77e8629b, 0xec4d2ef4, 0x9bd3fc04, 0x0076b06b, 0x72e22f1a,
+ 0xe9476375, 0x9ed9b185, 0x057cfdea, 0x71e41465, 0xea41580a,
+ 0x9ddf8afa, 0x067ac695, 0x50a4d810, 0xcb01947f, 0xbc9f468f,
+ 0x273a0ae0, 0x53a2e36f, 0xc807af00, 0xbf997df0, 0x243c319f,
+ 0x56a8aeee, 0xcd0de281, 0xba933071, 0x21367c1e, 0x55ae9591,
+ 0xce0bd9fe, 0xb9950b0e, 0x22304761, 0x5cbc35ec, 0xc7197983,
+ 0xb087ab73, 0x2b22e71c, 0x5fba0e93, 0xc41f42fc, 0xb381900c,
+ 0x2824dc63, 0x5ab04312, 0xc1150f7d, 0xb68bdd8d, 0x2d2e91e2,
+ 0x59b6786d, 0xc2133402, 0xb58de6f2, 0x2e28aa9d, 0x489503e8,
+ 0xd3304f87, 0xa4ae9d77, 0x3f0bd118, 0x4b933897, 0xd03674f8,
+ 0xa7a8a608, 0x3c0dea67, 0x4e997516, 0xd53c3979, 0xa2a2eb89,
+ 0x3907a7e6, 0x4d9f4e69, 0xd63a0206, 0xa1a4d0f6, 0x3a019c99,
+ 0x448dee14, 0xdf28a27b, 0xa8b6708b, 0x33133ce4, 0x478bd56b,
+ 0xdc2e9904, 0xabb04bf4, 0x3015079b, 0x428198ea, 0xd924d485,
+ 0xaeba0675, 0x351f4a1a, 0x4187a395, 0xda22effa, 0xadbc3d0a,
+ 0x36197165},
+ {0x00000000, 0xc18edfc0, 0x586cb9c1, 0x99e26601, 0xb0d97382,
+ 0x7157ac42, 0xe8b5ca43, 0x293b1583, 0xbac3e145, 0x7b4d3e85,
+ 0xe2af5884, 0x23218744, 0x0a1a92c7, 0xcb944d07, 0x52762b06,
+ 0x93f8f4c6, 0xaef6c4cb, 0x6f781b0b, 0xf69a7d0a, 0x3714a2ca,
+ 0x1e2fb749, 0xdfa16889, 0x46430e88, 0x87cdd148, 0x1435258e,
+ 0xd5bbfa4e, 0x4c599c4f, 0x8dd7438f, 0xa4ec560c, 0x656289cc,
+ 0xfc80efcd, 0x3d0e300d, 0x869c8fd7, 0x47125017, 0xdef03616,
+ 0x1f7ee9d6, 0x3645fc55, 0xf7cb2395, 0x6e294594, 0xafa79a54,
+ 0x3c5f6e92, 0xfdd1b152, 0x6433d753, 0xa5bd0893, 0x8c861d10,
+ 0x4d08c2d0, 0xd4eaa4d1, 0x15647b11, 0x286a4b1c, 0xe9e494dc,
+ 0x7006f2dd, 0xb1882d1d, 0x98b3389e, 0x593de75e, 0xc0df815f,
+ 0x01515e9f, 0x92a9aa59, 0x53277599, 0xcac51398, 0x0b4bcc58,
+ 0x2270d9db, 0xe3fe061b, 0x7a1c601a, 0xbb92bfda, 0xd64819ef,
+ 0x17c6c62f, 0x8e24a02e, 0x4faa7fee, 0x66916a6d, 0xa71fb5ad,
+ 0x3efdd3ac, 0xff730c6c, 0x6c8bf8aa, 0xad05276a, 0x34e7416b,
+ 0xf5699eab, 0xdc528b28, 0x1ddc54e8, 0x843e32e9, 0x45b0ed29,
+ 0x78bedd24, 0xb93002e4, 0x20d264e5, 0xe15cbb25, 0xc867aea6,
+ 0x09e97166, 0x900b1767, 0x5185c8a7, 0xc27d3c61, 0x03f3e3a1,
+ 0x9a1185a0, 0x5b9f5a60, 0x72a44fe3, 0xb32a9023, 0x2ac8f622,
+ 0xeb4629e2, 0x50d49638, 0x915a49f8, 0x08b82ff9, 0xc936f039,
+ 0xe00de5ba, 0x21833a7a, 0xb8615c7b, 0x79ef83bb, 0xea17777d,
+ 0x2b99a8bd, 0xb27bcebc, 0x73f5117c, 0x5ace04ff, 0x9b40db3f,
+ 0x02a2bd3e, 0xc32c62fe, 0xfe2252f3, 0x3fac8d33, 0xa64eeb32,
+ 0x67c034f2, 0x4efb2171, 0x8f75feb1, 0x169798b0, 0xd7194770,
+ 0x44e1b3b6, 0x856f6c76, 0x1c8d0a77, 0xdd03d5b7, 0xf438c034,
+ 0x35b61ff4, 0xac5479f5, 0x6ddaa635, 0x77e1359f, 0xb66fea5f,
+ 0x2f8d8c5e, 0xee03539e, 0xc738461d, 0x06b699dd, 0x9f54ffdc,
+ 0x5eda201c, 0xcd22d4da, 0x0cac0b1a, 0x954e6d1b, 0x54c0b2db,
+ 0x7dfba758, 0xbc757898, 0x25971e99, 0xe419c159, 0xd917f154,
+ 0x18992e94, 0x817b4895, 0x40f59755, 0x69ce82d6, 0xa8405d16,
+ 0x31a23b17, 0xf02ce4d7, 0x63d41011, 0xa25acfd1, 0x3bb8a9d0,
+ 0xfa367610, 0xd30d6393, 0x1283bc53, 0x8b61da52, 0x4aef0592,
+ 0xf17dba48, 0x30f36588, 0xa9110389, 0x689fdc49, 0x41a4c9ca,
+ 0x802a160a, 0x19c8700b, 0xd846afcb, 0x4bbe5b0d, 0x8a3084cd,
+ 0x13d2e2cc, 0xd25c3d0c, 0xfb67288f, 0x3ae9f74f, 0xa30b914e,
+ 0x62854e8e, 0x5f8b7e83, 0x9e05a143, 0x07e7c742, 0xc6691882,
+ 0xef520d01, 0x2edcd2c1, 0xb73eb4c0, 0x76b06b00, 0xe5489fc6,
+ 0x24c64006, 0xbd242607, 0x7caaf9c7, 0x5591ec44, 0x941f3384,
+ 0x0dfd5585, 0xcc738a45, 0xa1a92c70, 0x6027f3b0, 0xf9c595b1,
+ 0x384b4a71, 0x11705ff2, 0xd0fe8032, 0x491ce633, 0x889239f3,
+ 0x1b6acd35, 0xdae412f5, 0x430674f4, 0x8288ab34, 0xabb3beb7,
+ 0x6a3d6177, 0xf3df0776, 0x3251d8b6, 0x0f5fe8bb, 0xced1377b,
+ 0x5733517a, 0x96bd8eba, 0xbf869b39, 0x7e0844f9, 0xe7ea22f8,
+ 0x2664fd38, 0xb59c09fe, 0x7412d63e, 0xedf0b03f, 0x2c7e6fff,
+ 0x05457a7c, 0xc4cba5bc, 0x5d29c3bd, 0x9ca71c7d, 0x2735a3a7,
+ 0xe6bb7c67, 0x7f591a66, 0xbed7c5a6, 0x97ecd025, 0x56620fe5,
+ 0xcf8069e4, 0x0e0eb624, 0x9df642e2, 0x5c789d22, 0xc59afb23,
+ 0x041424e3, 0x2d2f3160, 0xeca1eea0, 0x754388a1, 0xb4cd5761,
+ 0x89c3676c, 0x484db8ac, 0xd1afdead, 0x1021016d, 0x391a14ee,
+ 0xf894cb2e, 0x6176ad2f, 0xa0f872ef, 0x33008629, 0xf28e59e9,
+ 0x6b6c3fe8, 0xaae2e028, 0x83d9f5ab, 0x42572a6b, 0xdbb54c6a,
+ 0x1a3b93aa},
+ {0x00000000, 0xefc26b3e, 0x04f5d03d, 0xeb37bb03, 0x09eba07a,
+ 0xe629cb44, 0x0d1e7047, 0xe2dc1b79, 0x13d740f4, 0xfc152bca,
+ 0x172290c9, 0xf8e0fbf7, 0x1a3ce08e, 0xf5fe8bb0, 0x1ec930b3,
+ 0xf10b5b8d, 0x27ae81e8, 0xc86cead6, 0x235b51d5, 0xcc993aeb,
+ 0x2e452192, 0xc1874aac, 0x2ab0f1af, 0xc5729a91, 0x3479c11c,
+ 0xdbbbaa22, 0x308c1121, 0xdf4e7a1f, 0x3d926166, 0xd2500a58,
+ 0x3967b15b, 0xd6a5da65, 0x4f5d03d0, 0xa09f68ee, 0x4ba8d3ed,
+ 0xa46ab8d3, 0x46b6a3aa, 0xa974c894, 0x42437397, 0xad8118a9,
+ 0x5c8a4324, 0xb348281a, 0x587f9319, 0xb7bdf827, 0x5561e35e,
+ 0xbaa38860, 0x51943363, 0xbe56585d, 0x68f38238, 0x8731e906,
+ 0x6c065205, 0x83c4393b, 0x61182242, 0x8eda497c, 0x65edf27f,
+ 0x8a2f9941, 0x7b24c2cc, 0x94e6a9f2, 0x7fd112f1, 0x901379cf,
+ 0x72cf62b6, 0x9d0d0988, 0x763ab28b, 0x99f8d9b5, 0x9eba07a0,
+ 0x71786c9e, 0x9a4fd79d, 0x758dbca3, 0x9751a7da, 0x7893cce4,
+ 0x93a477e7, 0x7c661cd9, 0x8d6d4754, 0x62af2c6a, 0x89989769,
+ 0x665afc57, 0x8486e72e, 0x6b448c10, 0x80733713, 0x6fb15c2d,
+ 0xb9148648, 0x56d6ed76, 0xbde15675, 0x52233d4b, 0xb0ff2632,
+ 0x5f3d4d0c, 0xb40af60f, 0x5bc89d31, 0xaac3c6bc, 0x4501ad82,
+ 0xae361681, 0x41f47dbf, 0xa32866c6, 0x4cea0df8, 0xa7ddb6fb,
+ 0x481fddc5, 0xd1e70470, 0x3e256f4e, 0xd512d44d, 0x3ad0bf73,
+ 0xd80ca40a, 0x37cecf34, 0xdcf97437, 0x333b1f09, 0xc2304484,
+ 0x2df22fba, 0xc6c594b9, 0x2907ff87, 0xcbdbe4fe, 0x24198fc0,
+ 0xcf2e34c3, 0x20ec5ffd, 0xf6498598, 0x198beea6, 0xf2bc55a5,
+ 0x1d7e3e9b, 0xffa225e2, 0x10604edc, 0xfb57f5df, 0x14959ee1,
+ 0xe59ec56c, 0x0a5cae52, 0xe16b1551, 0x0ea97e6f, 0xec756516,
+ 0x03b70e28, 0xe880b52b, 0x0742de15, 0xe6050901, 0x09c7623f,
+ 0xe2f0d93c, 0x0d32b202, 0xefeea97b, 0x002cc245, 0xeb1b7946,
+ 0x04d91278, 0xf5d249f5, 0x1a1022cb, 0xf12799c8, 0x1ee5f2f6,
+ 0xfc39e98f, 0x13fb82b1, 0xf8cc39b2, 0x170e528c, 0xc1ab88e9,
+ 0x2e69e3d7, 0xc55e58d4, 0x2a9c33ea, 0xc8402893, 0x278243ad,
+ 0xccb5f8ae, 0x23779390, 0xd27cc81d, 0x3dbea323, 0xd6891820,
+ 0x394b731e, 0xdb976867, 0x34550359, 0xdf62b85a, 0x30a0d364,
+ 0xa9580ad1, 0x469a61ef, 0xadaddaec, 0x426fb1d2, 0xa0b3aaab,
+ 0x4f71c195, 0xa4467a96, 0x4b8411a8, 0xba8f4a25, 0x554d211b,
+ 0xbe7a9a18, 0x51b8f126, 0xb364ea5f, 0x5ca68161, 0xb7913a62,
+ 0x5853515c, 0x8ef68b39, 0x6134e007, 0x8a035b04, 0x65c1303a,
+ 0x871d2b43, 0x68df407d, 0x83e8fb7e, 0x6c2a9040, 0x9d21cbcd,
+ 0x72e3a0f3, 0x99d41bf0, 0x761670ce, 0x94ca6bb7, 0x7b080089,
+ 0x903fbb8a, 0x7ffdd0b4, 0x78bf0ea1, 0x977d659f, 0x7c4ade9c,
+ 0x9388b5a2, 0x7154aedb, 0x9e96c5e5, 0x75a17ee6, 0x9a6315d8,
+ 0x6b684e55, 0x84aa256b, 0x6f9d9e68, 0x805ff556, 0x6283ee2f,
+ 0x8d418511, 0x66763e12, 0x89b4552c, 0x5f118f49, 0xb0d3e477,
+ 0x5be45f74, 0xb426344a, 0x56fa2f33, 0xb938440d, 0x520fff0e,
+ 0xbdcd9430, 0x4cc6cfbd, 0xa304a483, 0x48331f80, 0xa7f174be,
+ 0x452d6fc7, 0xaaef04f9, 0x41d8bffa, 0xae1ad4c4, 0x37e20d71,
+ 0xd820664f, 0x3317dd4c, 0xdcd5b672, 0x3e09ad0b, 0xd1cbc635,
+ 0x3afc7d36, 0xd53e1608, 0x24354d85, 0xcbf726bb, 0x20c09db8,
+ 0xcf02f686, 0x2ddeedff, 0xc21c86c1, 0x292b3dc2, 0xc6e956fc,
+ 0x104c8c99, 0xff8ee7a7, 0x14b95ca4, 0xfb7b379a, 0x19a72ce3,
+ 0xf66547dd, 0x1d52fcde, 0xf29097e0, 0x039bcc6d, 0xec59a753,
+ 0x076e1c50, 0xe8ac776e, 0x0a706c17, 0xe5b20729, 0x0e85bc2a,
+ 0xe147d714},
+ {0x00000000, 0x177b1443, 0x2ef62886, 0x398d3cc5, 0x5dec510c,
+ 0x4a97454f, 0x731a798a, 0x64616dc9, 0xbbd8a218, 0xaca3b65b,
+ 0x952e8a9e, 0x82559edd, 0xe634f314, 0xf14fe757, 0xc8c2db92,
+ 0xdfb9cfd1, 0xacc04271, 0xbbbb5632, 0x82366af7, 0x954d7eb4,
+ 0xf12c137d, 0xe657073e, 0xdfda3bfb, 0xc8a12fb8, 0x1718e069,
+ 0x0063f42a, 0x39eec8ef, 0x2e95dcac, 0x4af4b165, 0x5d8fa526,
+ 0x640299e3, 0x73798da0, 0x82f182a3, 0x958a96e0, 0xac07aa25,
+ 0xbb7cbe66, 0xdf1dd3af, 0xc866c7ec, 0xf1ebfb29, 0xe690ef6a,
+ 0x392920bb, 0x2e5234f8, 0x17df083d, 0x00a41c7e, 0x64c571b7,
+ 0x73be65f4, 0x4a335931, 0x5d484d72, 0x2e31c0d2, 0x394ad491,
+ 0x00c7e854, 0x17bcfc17, 0x73dd91de, 0x64a6859d, 0x5d2bb958,
+ 0x4a50ad1b, 0x95e962ca, 0x82927689, 0xbb1f4a4c, 0xac645e0f,
+ 0xc80533c6, 0xdf7e2785, 0xe6f31b40, 0xf1880f03, 0xde920307,
+ 0xc9e91744, 0xf0642b81, 0xe71f3fc2, 0x837e520b, 0x94054648,
+ 0xad887a8d, 0xbaf36ece, 0x654aa11f, 0x7231b55c, 0x4bbc8999,
+ 0x5cc79dda, 0x38a6f013, 0x2fdde450, 0x1650d895, 0x012bccd6,
+ 0x72524176, 0x65295535, 0x5ca469f0, 0x4bdf7db3, 0x2fbe107a,
+ 0x38c50439, 0x014838fc, 0x16332cbf, 0xc98ae36e, 0xdef1f72d,
+ 0xe77ccbe8, 0xf007dfab, 0x9466b262, 0x831da621, 0xba909ae4,
+ 0xadeb8ea7, 0x5c6381a4, 0x4b1895e7, 0x7295a922, 0x65eebd61,
+ 0x018fd0a8, 0x16f4c4eb, 0x2f79f82e, 0x3802ec6d, 0xe7bb23bc,
+ 0xf0c037ff, 0xc94d0b3a, 0xde361f79, 0xba5772b0, 0xad2c66f3,
+ 0x94a15a36, 0x83da4e75, 0xf0a3c3d5, 0xe7d8d796, 0xde55eb53,
+ 0xc92eff10, 0xad4f92d9, 0xba34869a, 0x83b9ba5f, 0x94c2ae1c,
+ 0x4b7b61cd, 0x5c00758e, 0x658d494b, 0x72f65d08, 0x169730c1,
+ 0x01ec2482, 0x38611847, 0x2f1a0c04, 0x6655004f, 0x712e140c,
+ 0x48a328c9, 0x5fd83c8a, 0x3bb95143, 0x2cc24500, 0x154f79c5,
+ 0x02346d86, 0xdd8da257, 0xcaf6b614, 0xf37b8ad1, 0xe4009e92,
+ 0x8061f35b, 0x971ae718, 0xae97dbdd, 0xb9eccf9e, 0xca95423e,
+ 0xddee567d, 0xe4636ab8, 0xf3187efb, 0x97791332, 0x80020771,
+ 0xb98f3bb4, 0xaef42ff7, 0x714de026, 0x6636f465, 0x5fbbc8a0,
+ 0x48c0dce3, 0x2ca1b12a, 0x3bdaa569, 0x025799ac, 0x152c8def,
+ 0xe4a482ec, 0xf3df96af, 0xca52aa6a, 0xdd29be29, 0xb948d3e0,
+ 0xae33c7a3, 0x97befb66, 0x80c5ef25, 0x5f7c20f4, 0x480734b7,
+ 0x718a0872, 0x66f11c31, 0x029071f8, 0x15eb65bb, 0x2c66597e,
+ 0x3b1d4d3d, 0x4864c09d, 0x5f1fd4de, 0x6692e81b, 0x71e9fc58,
+ 0x15889191, 0x02f385d2, 0x3b7eb917, 0x2c05ad54, 0xf3bc6285,
+ 0xe4c776c6, 0xdd4a4a03, 0xca315e40, 0xae503389, 0xb92b27ca,
+ 0x80a61b0f, 0x97dd0f4c, 0xb8c70348, 0xafbc170b, 0x96312bce,
+ 0x814a3f8d, 0xe52b5244, 0xf2504607, 0xcbdd7ac2, 0xdca66e81,
+ 0x031fa150, 0x1464b513, 0x2de989d6, 0x3a929d95, 0x5ef3f05c,
+ 0x4988e41f, 0x7005d8da, 0x677ecc99, 0x14074139, 0x037c557a,
+ 0x3af169bf, 0x2d8a7dfc, 0x49eb1035, 0x5e900476, 0x671d38b3,
+ 0x70662cf0, 0xafdfe321, 0xb8a4f762, 0x8129cba7, 0x9652dfe4,
+ 0xf233b22d, 0xe548a66e, 0xdcc59aab, 0xcbbe8ee8, 0x3a3681eb,
+ 0x2d4d95a8, 0x14c0a96d, 0x03bbbd2e, 0x67dad0e7, 0x70a1c4a4,
+ 0x492cf861, 0x5e57ec22, 0x81ee23f3, 0x969537b0, 0xaf180b75,
+ 0xb8631f36, 0xdc0272ff, 0xcb7966bc, 0xf2f45a79, 0xe58f4e3a,
+ 0x96f6c39a, 0x818dd7d9, 0xb800eb1c, 0xaf7bff5f, 0xcb1a9296,
+ 0xdc6186d5, 0xe5ecba10, 0xf297ae53, 0x2d2e6182, 0x3a5575c1,
+ 0x03d84904, 0x14a35d47, 0x70c2308e, 0x67b924cd, 0x5e341808,
+ 0x494f0c4b}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43147b17, 0x8628f62e, 0xc53c8d39, 0x0c51ec5d,
+ 0x4f45974a, 0x8a791a73, 0xc96d6164, 0x18a2d8bb, 0x5bb6a3ac,
+ 0x9e8a2e95, 0xdd9e5582, 0x14f334e6, 0x57e74ff1, 0x92dbc2c8,
+ 0xd1cfb9df, 0x7142c0ac, 0x3256bbbb, 0xf76a3682, 0xb47e4d95,
+ 0x7d132cf1, 0x3e0757e6, 0xfb3bdadf, 0xb82fa1c8, 0x69e01817,
+ 0x2af46300, 0xefc8ee39, 0xacdc952e, 0x65b1f44a, 0x26a58f5d,
+ 0xe3990264, 0xa08d7973, 0xa382f182, 0xe0968a95, 0x25aa07ac,
+ 0x66be7cbb, 0xafd31ddf, 0xecc766c8, 0x29fbebf1, 0x6aef90e6,
+ 0xbb202939, 0xf834522e, 0x3d08df17, 0x7e1ca400, 0xb771c564,
+ 0xf465be73, 0x3159334a, 0x724d485d, 0xd2c0312e, 0x91d44a39,
+ 0x54e8c700, 0x17fcbc17, 0xde91dd73, 0x9d85a664, 0x58b92b5d,
+ 0x1bad504a, 0xca62e995, 0x89769282, 0x4c4a1fbb, 0x0f5e64ac,
+ 0xc63305c8, 0x85277edf, 0x401bf3e6, 0x030f88f1, 0x070392de,
+ 0x4417e9c9, 0x812b64f0, 0xc23f1fe7, 0x0b527e83, 0x48460594,
+ 0x8d7a88ad, 0xce6ef3ba, 0x1fa14a65, 0x5cb53172, 0x9989bc4b,
+ 0xda9dc75c, 0x13f0a638, 0x50e4dd2f, 0x95d85016, 0xd6cc2b01,
+ 0x76415272, 0x35552965, 0xf069a45c, 0xb37ddf4b, 0x7a10be2f,
+ 0x3904c538, 0xfc384801, 0xbf2c3316, 0x6ee38ac9, 0x2df7f1de,
+ 0xe8cb7ce7, 0xabdf07f0, 0x62b26694, 0x21a61d83, 0xe49a90ba,
+ 0xa78eebad, 0xa481635c, 0xe795184b, 0x22a99572, 0x61bdee65,
+ 0xa8d08f01, 0xebc4f416, 0x2ef8792f, 0x6dec0238, 0xbc23bbe7,
+ 0xff37c0f0, 0x3a0b4dc9, 0x791f36de, 0xb07257ba, 0xf3662cad,
+ 0x365aa194, 0x754eda83, 0xd5c3a3f0, 0x96d7d8e7, 0x53eb55de,
+ 0x10ff2ec9, 0xd9924fad, 0x9a8634ba, 0x5fbab983, 0x1caec294,
+ 0xcd617b4b, 0x8e75005c, 0x4b498d65, 0x085df672, 0xc1309716,
+ 0x8224ec01, 0x47186138, 0x040c1a2f, 0x4f005566, 0x0c142e71,
+ 0xc928a348, 0x8a3cd85f, 0x4351b93b, 0x0045c22c, 0xc5794f15,
+ 0x866d3402, 0x57a28ddd, 0x14b6f6ca, 0xd18a7bf3, 0x929e00e4,
+ 0x5bf36180, 0x18e71a97, 0xdddb97ae, 0x9ecfecb9, 0x3e4295ca,
+ 0x7d56eedd, 0xb86a63e4, 0xfb7e18f3, 0x32137997, 0x71070280,
+ 0xb43b8fb9, 0xf72ff4ae, 0x26e04d71, 0x65f43666, 0xa0c8bb5f,
+ 0xe3dcc048, 0x2ab1a12c, 0x69a5da3b, 0xac995702, 0xef8d2c15,
+ 0xec82a4e4, 0xaf96dff3, 0x6aaa52ca, 0x29be29dd, 0xe0d348b9,
+ 0xa3c733ae, 0x66fbbe97, 0x25efc580, 0xf4207c5f, 0xb7340748,
+ 0x72088a71, 0x311cf166, 0xf8719002, 0xbb65eb15, 0x7e59662c,
+ 0x3d4d1d3b, 0x9dc06448, 0xded41f5f, 0x1be89266, 0x58fce971,
+ 0x91918815, 0xd285f302, 0x17b97e3b, 0x54ad052c, 0x8562bcf3,
+ 0xc676c7e4, 0x034a4add, 0x405e31ca, 0x893350ae, 0xca272bb9,
+ 0x0f1ba680, 0x4c0fdd97, 0x4803c7b8, 0x0b17bcaf, 0xce2b3196,
+ 0x8d3f4a81, 0x44522be5, 0x074650f2, 0xc27addcb, 0x816ea6dc,
+ 0x50a11f03, 0x13b56414, 0xd689e92d, 0x959d923a, 0x5cf0f35e,
+ 0x1fe48849, 0xdad80570, 0x99cc7e67, 0x39410714, 0x7a557c03,
+ 0xbf69f13a, 0xfc7d8a2d, 0x3510eb49, 0x7604905e, 0xb3381d67,
+ 0xf02c6670, 0x21e3dfaf, 0x62f7a4b8, 0xa7cb2981, 0xe4df5296,
+ 0x2db233f2, 0x6ea648e5, 0xab9ac5dc, 0xe88ebecb, 0xeb81363a,
+ 0xa8954d2d, 0x6da9c014, 0x2ebdbb03, 0xe7d0da67, 0xa4c4a170,
+ 0x61f82c49, 0x22ec575e, 0xf323ee81, 0xb0379596, 0x750b18af,
+ 0x361f63b8, 0xff7202dc, 0xbc6679cb, 0x795af4f2, 0x3a4e8fe5,
+ 0x9ac3f696, 0xd9d78d81, 0x1ceb00b8, 0x5fff7baf, 0x96921acb,
+ 0xd58661dc, 0x10baece5, 0x53ae97f2, 0x82612e2d, 0xc175553a,
+ 0x0449d803, 0x475da314, 0x8e30c270, 0xcd24b967, 0x0818345e,
+ 0x4b0c4f49},
+ {0x00000000, 0x3e6bc2ef, 0x3dd0f504, 0x03bb37eb, 0x7aa0eb09,
+ 0x44cb29e6, 0x47701e0d, 0x791bdce2, 0xf440d713, 0xca2b15fc,
+ 0xc9902217, 0xf7fbe0f8, 0x8ee03c1a, 0xb08bfef5, 0xb330c91e,
+ 0x8d5b0bf1, 0xe881ae27, 0xd6ea6cc8, 0xd5515b23, 0xeb3a99cc,
+ 0x9221452e, 0xac4a87c1, 0xaff1b02a, 0x919a72c5, 0x1cc17934,
+ 0x22aabbdb, 0x21118c30, 0x1f7a4edf, 0x6661923d, 0x580a50d2,
+ 0x5bb16739, 0x65daa5d6, 0xd0035d4f, 0xee689fa0, 0xedd3a84b,
+ 0xd3b86aa4, 0xaaa3b646, 0x94c874a9, 0x97734342, 0xa91881ad,
+ 0x24438a5c, 0x1a2848b3, 0x19937f58, 0x27f8bdb7, 0x5ee36155,
+ 0x6088a3ba, 0x63339451, 0x5d5856be, 0x3882f368, 0x06e93187,
+ 0x0552066c, 0x3b39c483, 0x42221861, 0x7c49da8e, 0x7ff2ed65,
+ 0x41992f8a, 0xccc2247b, 0xf2a9e694, 0xf112d17f, 0xcf791390,
+ 0xb662cf72, 0x88090d9d, 0x8bb23a76, 0xb5d9f899, 0xa007ba9e,
+ 0x9e6c7871, 0x9dd74f9a, 0xa3bc8d75, 0xdaa75197, 0xe4cc9378,
+ 0xe777a493, 0xd91c667c, 0x54476d8d, 0x6a2caf62, 0x69979889,
+ 0x57fc5a66, 0x2ee78684, 0x108c446b, 0x13377380, 0x2d5cb16f,
+ 0x488614b9, 0x76edd656, 0x7556e1bd, 0x4b3d2352, 0x3226ffb0,
+ 0x0c4d3d5f, 0x0ff60ab4, 0x319dc85b, 0xbcc6c3aa, 0x82ad0145,
+ 0x811636ae, 0xbf7df441, 0xc66628a3, 0xf80dea4c, 0xfbb6dda7,
+ 0xc5dd1f48, 0x7004e7d1, 0x4e6f253e, 0x4dd412d5, 0x73bfd03a,
+ 0x0aa40cd8, 0x34cfce37, 0x3774f9dc, 0x091f3b33, 0x844430c2,
+ 0xba2ff22d, 0xb994c5c6, 0x87ff0729, 0xfee4dbcb, 0xc08f1924,
+ 0xc3342ecf, 0xfd5fec20, 0x988549f6, 0xa6ee8b19, 0xa555bcf2,
+ 0x9b3e7e1d, 0xe225a2ff, 0xdc4e6010, 0xdff557fb, 0xe19e9514,
+ 0x6cc59ee5, 0x52ae5c0a, 0x51156be1, 0x6f7ea90e, 0x166575ec,
+ 0x280eb703, 0x2bb580e8, 0x15de4207, 0x010905e6, 0x3f62c709,
+ 0x3cd9f0e2, 0x02b2320d, 0x7ba9eeef, 0x45c22c00, 0x46791beb,
+ 0x7812d904, 0xf549d2f5, 0xcb22101a, 0xc89927f1, 0xf6f2e51e,
+ 0x8fe939fc, 0xb182fb13, 0xb239ccf8, 0x8c520e17, 0xe988abc1,
+ 0xd7e3692e, 0xd4585ec5, 0xea339c2a, 0x932840c8, 0xad438227,
+ 0xaef8b5cc, 0x90937723, 0x1dc87cd2, 0x23a3be3d, 0x201889d6,
+ 0x1e734b39, 0x676897db, 0x59035534, 0x5ab862df, 0x64d3a030,
+ 0xd10a58a9, 0xef619a46, 0xecdaadad, 0xd2b16f42, 0xabaab3a0,
+ 0x95c1714f, 0x967a46a4, 0xa811844b, 0x254a8fba, 0x1b214d55,
+ 0x189a7abe, 0x26f1b851, 0x5fea64b3, 0x6181a65c, 0x623a91b7,
+ 0x5c515358, 0x398bf68e, 0x07e03461, 0x045b038a, 0x3a30c165,
+ 0x432b1d87, 0x7d40df68, 0x7efbe883, 0x40902a6c, 0xcdcb219d,
+ 0xf3a0e372, 0xf01bd499, 0xce701676, 0xb76bca94, 0x8900087b,
+ 0x8abb3f90, 0xb4d0fd7f, 0xa10ebf78, 0x9f657d97, 0x9cde4a7c,
+ 0xa2b58893, 0xdbae5471, 0xe5c5969e, 0xe67ea175, 0xd815639a,
+ 0x554e686b, 0x6b25aa84, 0x689e9d6f, 0x56f55f80, 0x2fee8362,
+ 0x1185418d, 0x123e7666, 0x2c55b489, 0x498f115f, 0x77e4d3b0,
+ 0x745fe45b, 0x4a3426b4, 0x332ffa56, 0x0d4438b9, 0x0eff0f52,
+ 0x3094cdbd, 0xbdcfc64c, 0x83a404a3, 0x801f3348, 0xbe74f1a7,
+ 0xc76f2d45, 0xf904efaa, 0xfabfd841, 0xc4d41aae, 0x710de237,
+ 0x4f6620d8, 0x4cdd1733, 0x72b6d5dc, 0x0bad093e, 0x35c6cbd1,
+ 0x367dfc3a, 0x08163ed5, 0x854d3524, 0xbb26f7cb, 0xb89dc020,
+ 0x86f602cf, 0xffedde2d, 0xc1861cc2, 0xc23d2b29, 0xfc56e9c6,
+ 0x998c4c10, 0xa7e78eff, 0xa45cb914, 0x9a377bfb, 0xe32ca719,
+ 0xdd4765f6, 0xdefc521d, 0xe09790f2, 0x6dcc9b03, 0x53a759ec,
+ 0x501c6e07, 0x6e77ace8, 0x176c700a, 0x2907b2e5, 0x2abc850e,
+ 0x14d747e1},
+ {0x00000000, 0xc0df8ec1, 0xc1b96c58, 0x0166e299, 0x8273d9b0,
+ 0x42ac5771, 0x43cab5e8, 0x83153b29, 0x45e1c3ba, 0x853e4d7b,
+ 0x8458afe2, 0x44872123, 0xc7921a0a, 0x074d94cb, 0x062b7652,
+ 0xc6f4f893, 0xcbc4f6ae, 0x0b1b786f, 0x0a7d9af6, 0xcaa21437,
+ 0x49b72f1e, 0x8968a1df, 0x880e4346, 0x48d1cd87, 0x8e253514,
+ 0x4efabbd5, 0x4f9c594c, 0x8f43d78d, 0x0c56eca4, 0xcc896265,
+ 0xcdef80fc, 0x0d300e3d, 0xd78f9c86, 0x17501247, 0x1636f0de,
+ 0xd6e97e1f, 0x55fc4536, 0x9523cbf7, 0x9445296e, 0x549aa7af,
+ 0x926e5f3c, 0x52b1d1fd, 0x53d73364, 0x9308bda5, 0x101d868c,
+ 0xd0c2084d, 0xd1a4ead4, 0x117b6415, 0x1c4b6a28, 0xdc94e4e9,
+ 0xddf20670, 0x1d2d88b1, 0x9e38b398, 0x5ee73d59, 0x5f81dfc0,
+ 0x9f5e5101, 0x59aaa992, 0x99752753, 0x9813c5ca, 0x58cc4b0b,
+ 0xdbd97022, 0x1b06fee3, 0x1a601c7a, 0xdabf92bb, 0xef1948d6,
+ 0x2fc6c617, 0x2ea0248e, 0xee7faa4f, 0x6d6a9166, 0xadb51fa7,
+ 0xacd3fd3e, 0x6c0c73ff, 0xaaf88b6c, 0x6a2705ad, 0x6b41e734,
+ 0xab9e69f5, 0x288b52dc, 0xe854dc1d, 0xe9323e84, 0x29edb045,
+ 0x24ddbe78, 0xe40230b9, 0xe564d220, 0x25bb5ce1, 0xa6ae67c8,
+ 0x6671e909, 0x67170b90, 0xa7c88551, 0x613c7dc2, 0xa1e3f303,
+ 0xa085119a, 0x605a9f5b, 0xe34fa472, 0x23902ab3, 0x22f6c82a,
+ 0xe22946eb, 0x3896d450, 0xf8495a91, 0xf92fb808, 0x39f036c9,
+ 0xbae50de0, 0x7a3a8321, 0x7b5c61b8, 0xbb83ef79, 0x7d7717ea,
+ 0xbda8992b, 0xbcce7bb2, 0x7c11f573, 0xff04ce5a, 0x3fdb409b,
+ 0x3ebda202, 0xfe622cc3, 0xf35222fe, 0x338dac3f, 0x32eb4ea6,
+ 0xf234c067, 0x7121fb4e, 0xb1fe758f, 0xb0989716, 0x704719d7,
+ 0xb6b3e144, 0x766c6f85, 0x770a8d1c, 0xb7d503dd, 0x34c038f4,
+ 0xf41fb635, 0xf57954ac, 0x35a6da6d, 0x9f35e177, 0x5fea6fb6,
+ 0x5e8c8d2f, 0x9e5303ee, 0x1d4638c7, 0xdd99b606, 0xdcff549f,
+ 0x1c20da5e, 0xdad422cd, 0x1a0bac0c, 0x1b6d4e95, 0xdbb2c054,
+ 0x58a7fb7d, 0x987875bc, 0x991e9725, 0x59c119e4, 0x54f117d9,
+ 0x942e9918, 0x95487b81, 0x5597f540, 0xd682ce69, 0x165d40a8,
+ 0x173ba231, 0xd7e42cf0, 0x1110d463, 0xd1cf5aa2, 0xd0a9b83b,
+ 0x107636fa, 0x93630dd3, 0x53bc8312, 0x52da618b, 0x9205ef4a,
+ 0x48ba7df1, 0x8865f330, 0x890311a9, 0x49dc9f68, 0xcac9a441,
+ 0x0a162a80, 0x0b70c819, 0xcbaf46d8, 0x0d5bbe4b, 0xcd84308a,
+ 0xcce2d213, 0x0c3d5cd2, 0x8f2867fb, 0x4ff7e93a, 0x4e910ba3,
+ 0x8e4e8562, 0x837e8b5f, 0x43a1059e, 0x42c7e707, 0x821869c6,
+ 0x010d52ef, 0xc1d2dc2e, 0xc0b43eb7, 0x006bb076, 0xc69f48e5,
+ 0x0640c624, 0x072624bd, 0xc7f9aa7c, 0x44ec9155, 0x84331f94,
+ 0x8555fd0d, 0x458a73cc, 0x702ca9a1, 0xb0f32760, 0xb195c5f9,
+ 0x714a4b38, 0xf25f7011, 0x3280fed0, 0x33e61c49, 0xf3399288,
+ 0x35cd6a1b, 0xf512e4da, 0xf4740643, 0x34ab8882, 0xb7beb3ab,
+ 0x77613d6a, 0x7607dff3, 0xb6d85132, 0xbbe85f0f, 0x7b37d1ce,
+ 0x7a513357, 0xba8ebd96, 0x399b86bf, 0xf944087e, 0xf822eae7,
+ 0x38fd6426, 0xfe099cb5, 0x3ed61274, 0x3fb0f0ed, 0xff6f7e2c,
+ 0x7c7a4505, 0xbca5cbc4, 0xbdc3295d, 0x7d1ca79c, 0xa7a33527,
+ 0x677cbbe6, 0x661a597f, 0xa6c5d7be, 0x25d0ec97, 0xe50f6256,
+ 0xe46980cf, 0x24b60e0e, 0xe242f69d, 0x229d785c, 0x23fb9ac5,
+ 0xe3241404, 0x60312f2d, 0xa0eea1ec, 0xa1884375, 0x6157cdb4,
+ 0x6c67c389, 0xacb84d48, 0xaddeafd1, 0x6d012110, 0xee141a39,
+ 0x2ecb94f8, 0x2fad7661, 0xef72f8a0, 0x29860033, 0xe9598ef2,
+ 0xe83f6c6b, 0x28e0e2aa, 0xabf5d983, 0x6b2a5742, 0x6a4cb5db,
+ 0xaa933b1a},
+ {0x00000000, 0x6f4ca59b, 0x9f9e3bec, 0xf0d29e77, 0x7f3b0603,
+ 0x1077a398, 0xe0a53def, 0x8fe99874, 0xfe760c06, 0x913aa99d,
+ 0x61e837ea, 0x0ea49271, 0x814d0a05, 0xee01af9e, 0x1ed331e9,
+ 0x719f9472, 0xfced180c, 0x93a1bd97, 0x637323e0, 0x0c3f867b,
+ 0x83d61e0f, 0xec9abb94, 0x1c4825e3, 0x73048078, 0x029b140a,
+ 0x6dd7b191, 0x9d052fe6, 0xf2498a7d, 0x7da01209, 0x12ecb792,
+ 0xe23e29e5, 0x8d728c7e, 0xf8db3118, 0x97979483, 0x67450af4,
+ 0x0809af6f, 0x87e0371b, 0xe8ac9280, 0x187e0cf7, 0x7732a96c,
+ 0x06ad3d1e, 0x69e19885, 0x993306f2, 0xf67fa369, 0x79963b1d,
+ 0x16da9e86, 0xe60800f1, 0x8944a56a, 0x04362914, 0x6b7a8c8f,
+ 0x9ba812f8, 0xf4e4b763, 0x7b0d2f17, 0x14418a8c, 0xe49314fb,
+ 0x8bdfb160, 0xfa402512, 0x950c8089, 0x65de1efe, 0x0a92bb65,
+ 0x857b2311, 0xea37868a, 0x1ae518fd, 0x75a9bd66, 0xf0b76330,
+ 0x9ffbc6ab, 0x6f2958dc, 0x0065fd47, 0x8f8c6533, 0xe0c0c0a8,
+ 0x10125edf, 0x7f5efb44, 0x0ec16f36, 0x618dcaad, 0x915f54da,
+ 0xfe13f141, 0x71fa6935, 0x1eb6ccae, 0xee6452d9, 0x8128f742,
+ 0x0c5a7b3c, 0x6316dea7, 0x93c440d0, 0xfc88e54b, 0x73617d3f,
+ 0x1c2dd8a4, 0xecff46d3, 0x83b3e348, 0xf22c773a, 0x9d60d2a1,
+ 0x6db24cd6, 0x02fee94d, 0x8d177139, 0xe25bd4a2, 0x12894ad5,
+ 0x7dc5ef4e, 0x086c5228, 0x6720f7b3, 0x97f269c4, 0xf8becc5f,
+ 0x7757542b, 0x181bf1b0, 0xe8c96fc7, 0x8785ca5c, 0xf61a5e2e,
+ 0x9956fbb5, 0x698465c2, 0x06c8c059, 0x8921582d, 0xe66dfdb6,
+ 0x16bf63c1, 0x79f3c65a, 0xf4814a24, 0x9bcdefbf, 0x6b1f71c8,
+ 0x0453d453, 0x8bba4c27, 0xe4f6e9bc, 0x142477cb, 0x7b68d250,
+ 0x0af74622, 0x65bbe3b9, 0x95697dce, 0xfa25d855, 0x75cc4021,
+ 0x1a80e5ba, 0xea527bcd, 0x851ede56, 0xe06fc760, 0x8f2362fb,
+ 0x7ff1fc8c, 0x10bd5917, 0x9f54c163, 0xf01864f8, 0x00cafa8f,
+ 0x6f865f14, 0x1e19cb66, 0x71556efd, 0x8187f08a, 0xeecb5511,
+ 0x6122cd65, 0x0e6e68fe, 0xfebcf689, 0x91f05312, 0x1c82df6c,
+ 0x73ce7af7, 0x831ce480, 0xec50411b, 0x63b9d96f, 0x0cf57cf4,
+ 0xfc27e283, 0x936b4718, 0xe2f4d36a, 0x8db876f1, 0x7d6ae886,
+ 0x12264d1d, 0x9dcfd569, 0xf28370f2, 0x0251ee85, 0x6d1d4b1e,
+ 0x18b4f678, 0x77f853e3, 0x872acd94, 0xe866680f, 0x678ff07b,
+ 0x08c355e0, 0xf811cb97, 0x975d6e0c, 0xe6c2fa7e, 0x898e5fe5,
+ 0x795cc192, 0x16106409, 0x99f9fc7d, 0xf6b559e6, 0x0667c791,
+ 0x692b620a, 0xe459ee74, 0x8b154bef, 0x7bc7d598, 0x148b7003,
+ 0x9b62e877, 0xf42e4dec, 0x04fcd39b, 0x6bb07600, 0x1a2fe272,
+ 0x756347e9, 0x85b1d99e, 0xeafd7c05, 0x6514e471, 0x0a5841ea,
+ 0xfa8adf9d, 0x95c67a06, 0x10d8a450, 0x7f9401cb, 0x8f469fbc,
+ 0xe00a3a27, 0x6fe3a253, 0x00af07c8, 0xf07d99bf, 0x9f313c24,
+ 0xeeaea856, 0x81e20dcd, 0x713093ba, 0x1e7c3621, 0x9195ae55,
+ 0xfed90bce, 0x0e0b95b9, 0x61473022, 0xec35bc5c, 0x837919c7,
+ 0x73ab87b0, 0x1ce7222b, 0x930eba5f, 0xfc421fc4, 0x0c9081b3,
+ 0x63dc2428, 0x1243b05a, 0x7d0f15c1, 0x8ddd8bb6, 0xe2912e2d,
+ 0x6d78b659, 0x023413c2, 0xf2e68db5, 0x9daa282e, 0xe8039548,
+ 0x874f30d3, 0x779daea4, 0x18d10b3f, 0x9738934b, 0xf87436d0,
+ 0x08a6a8a7, 0x67ea0d3c, 0x1675994e, 0x79393cd5, 0x89eba2a2,
+ 0xe6a70739, 0x694e9f4d, 0x06023ad6, 0xf6d0a4a1, 0x999c013a,
+ 0x14ee8d44, 0x7ba228df, 0x8b70b6a8, 0xe43c1333, 0x6bd58b47,
+ 0x04992edc, 0xf44bb0ab, 0x9b071530, 0xea988142, 0x85d424d9,
+ 0x7506baae, 0x1a4a1f35, 0x95a38741, 0xfaef22da, 0x0a3dbcad,
+ 0x65711936}};
+
+#endif
+
+#endif
+
+#if N == 4
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xf1da05aa, 0x38c50d15, 0xc91f08bf, 0x718a1a2a,
+ 0x80501f80, 0x494f173f, 0xb8951295, 0xe3143454, 0x12ce31fe,
+ 0xdbd13941, 0x2a0b3ceb, 0x929e2e7e, 0x63442bd4, 0xaa5b236b,
+ 0x5b8126c1, 0x1d596ee9, 0xec836b43, 0x259c63fc, 0xd4466656,
+ 0x6cd374c3, 0x9d097169, 0x541679d6, 0xa5cc7c7c, 0xfe4d5abd,
+ 0x0f975f17, 0xc68857a8, 0x37525202, 0x8fc74097, 0x7e1d453d,
+ 0xb7024d82, 0x46d84828, 0x3ab2ddd2, 0xcb68d878, 0x0277d0c7,
+ 0xf3add56d, 0x4b38c7f8, 0xbae2c252, 0x73fdcaed, 0x8227cf47,
+ 0xd9a6e986, 0x287cec2c, 0xe163e493, 0x10b9e139, 0xa82cf3ac,
+ 0x59f6f606, 0x90e9feb9, 0x6133fb13, 0x27ebb33b, 0xd631b691,
+ 0x1f2ebe2e, 0xeef4bb84, 0x5661a911, 0xa7bbacbb, 0x6ea4a404,
+ 0x9f7ea1ae, 0xc4ff876f, 0x352582c5, 0xfc3a8a7a, 0x0de08fd0,
+ 0xb5759d45, 0x44af98ef, 0x8db09050, 0x7c6a95fa, 0x7565bba4,
+ 0x84bfbe0e, 0x4da0b6b1, 0xbc7ab31b, 0x04efa18e, 0xf535a424,
+ 0x3c2aac9b, 0xcdf0a931, 0x96718ff0, 0x67ab8a5a, 0xaeb482e5,
+ 0x5f6e874f, 0xe7fb95da, 0x16219070, 0xdf3e98cf, 0x2ee49d65,
+ 0x683cd54d, 0x99e6d0e7, 0x50f9d858, 0xa123ddf2, 0x19b6cf67,
+ 0xe86ccacd, 0x2173c272, 0xd0a9c7d8, 0x8b28e119, 0x7af2e4b3,
+ 0xb3edec0c, 0x4237e9a6, 0xfaa2fb33, 0x0b78fe99, 0xc267f626,
+ 0x33bdf38c, 0x4fd76676, 0xbe0d63dc, 0x77126b63, 0x86c86ec9,
+ 0x3e5d7c5c, 0xcf8779f6, 0x06987149, 0xf74274e3, 0xacc35222,
+ 0x5d195788, 0x94065f37, 0x65dc5a9d, 0xdd494808, 0x2c934da2,
+ 0xe58c451d, 0x145640b7, 0x528e089f, 0xa3540d35, 0x6a4b058a,
+ 0x9b910020, 0x230412b5, 0xd2de171f, 0x1bc11fa0, 0xea1b1a0a,
+ 0xb19a3ccb, 0x40403961, 0x895f31de, 0x78853474, 0xc01026e1,
+ 0x31ca234b, 0xf8d52bf4, 0x090f2e5e, 0xeacb7748, 0x1b1172e2,
+ 0xd20e7a5d, 0x23d47ff7, 0x9b416d62, 0x6a9b68c8, 0xa3846077,
+ 0x525e65dd, 0x09df431c, 0xf80546b6, 0x311a4e09, 0xc0c04ba3,
+ 0x78555936, 0x898f5c9c, 0x40905423, 0xb14a5189, 0xf79219a1,
+ 0x06481c0b, 0xcf5714b4, 0x3e8d111e, 0x8618038b, 0x77c20621,
+ 0xbedd0e9e, 0x4f070b34, 0x14862df5, 0xe55c285f, 0x2c4320e0,
+ 0xdd99254a, 0x650c37df, 0x94d63275, 0x5dc93aca, 0xac133f60,
+ 0xd079aa9a, 0x21a3af30, 0xe8bca78f, 0x1966a225, 0xa1f3b0b0,
+ 0x5029b51a, 0x9936bda5, 0x68ecb80f, 0x336d9ece, 0xc2b79b64,
+ 0x0ba893db, 0xfa729671, 0x42e784e4, 0xb33d814e, 0x7a2289f1,
+ 0x8bf88c5b, 0xcd20c473, 0x3cfac1d9, 0xf5e5c966, 0x043fcccc,
+ 0xbcaade59, 0x4d70dbf3, 0x846fd34c, 0x75b5d6e6, 0x2e34f027,
+ 0xdfeef58d, 0x16f1fd32, 0xe72bf898, 0x5fbeea0d, 0xae64efa7,
+ 0x677be718, 0x96a1e2b2, 0x9faeccec, 0x6e74c946, 0xa76bc1f9,
+ 0x56b1c453, 0xee24d6c6, 0x1ffed36c, 0xd6e1dbd3, 0x273bde79,
+ 0x7cbaf8b8, 0x8d60fd12, 0x447ff5ad, 0xb5a5f007, 0x0d30e292,
+ 0xfceae738, 0x35f5ef87, 0xc42fea2d, 0x82f7a205, 0x732da7af,
+ 0xba32af10, 0x4be8aaba, 0xf37db82f, 0x02a7bd85, 0xcbb8b53a,
+ 0x3a62b090, 0x61e39651, 0x903993fb, 0x59269b44, 0xa8fc9eee,
+ 0x10698c7b, 0xe1b389d1, 0x28ac816e, 0xd97684c4, 0xa51c113e,
+ 0x54c61494, 0x9dd91c2b, 0x6c031981, 0xd4960b14, 0x254c0ebe,
+ 0xec530601, 0x1d8903ab, 0x4608256a, 0xb7d220c0, 0x7ecd287f,
+ 0x8f172dd5, 0x37823f40, 0xc6583aea, 0x0f473255, 0xfe9d37ff,
+ 0xb8457fd7, 0x499f7a7d, 0x808072c2, 0x715a7768, 0xc9cf65fd,
+ 0x38156057, 0xf10a68e8, 0x00d06d42, 0x5b514b83, 0xaa8b4e29,
+ 0x63944696, 0x924e433c, 0x2adb51a9, 0xdb015403, 0x121e5cbc,
+ 0xe3c45916},
+ {0x00000000, 0x0ee7e8d1, 0x1dcfd1a2, 0x13283973, 0x3b9fa344,
+ 0x35784b95, 0x265072e6, 0x28b79a37, 0x773f4688, 0x79d8ae59,
+ 0x6af0972a, 0x64177ffb, 0x4ca0e5cc, 0x42470d1d, 0x516f346e,
+ 0x5f88dcbf, 0xee7e8d10, 0xe09965c1, 0xf3b15cb2, 0xfd56b463,
+ 0xd5e12e54, 0xdb06c685, 0xc82efff6, 0xc6c91727, 0x9941cb98,
+ 0x97a62349, 0x848e1a3a, 0x8a69f2eb, 0xa2de68dc, 0xac39800d,
+ 0xbf11b97e, 0xb1f651af, 0x078c1c61, 0x096bf4b0, 0x1a43cdc3,
+ 0x14a42512, 0x3c13bf25, 0x32f457f4, 0x21dc6e87, 0x2f3b8656,
+ 0x70b35ae9, 0x7e54b238, 0x6d7c8b4b, 0x639b639a, 0x4b2cf9ad,
+ 0x45cb117c, 0x56e3280f, 0x5804c0de, 0xe9f29171, 0xe71579a0,
+ 0xf43d40d3, 0xfadaa802, 0xd26d3235, 0xdc8adae4, 0xcfa2e397,
+ 0xc1450b46, 0x9ecdd7f9, 0x902a3f28, 0x8302065b, 0x8de5ee8a,
+ 0xa55274bd, 0xabb59c6c, 0xb89da51f, 0xb67a4dce, 0x0f1838c2,
+ 0x01ffd013, 0x12d7e960, 0x1c3001b1, 0x34879b86, 0x3a607357,
+ 0x29484a24, 0x27afa2f5, 0x78277e4a, 0x76c0969b, 0x65e8afe8,
+ 0x6b0f4739, 0x43b8dd0e, 0x4d5f35df, 0x5e770cac, 0x5090e47d,
+ 0xe166b5d2, 0xef815d03, 0xfca96470, 0xf24e8ca1, 0xdaf91696,
+ 0xd41efe47, 0xc736c734, 0xc9d12fe5, 0x9659f35a, 0x98be1b8b,
+ 0x8b9622f8, 0x8571ca29, 0xadc6501e, 0xa321b8cf, 0xb00981bc,
+ 0xbeee696d, 0x089424a3, 0x0673cc72, 0x155bf501, 0x1bbc1dd0,
+ 0x330b87e7, 0x3dec6f36, 0x2ec45645, 0x2023be94, 0x7fab622b,
+ 0x714c8afa, 0x6264b389, 0x6c835b58, 0x4434c16f, 0x4ad329be,
+ 0x59fb10cd, 0x571cf81c, 0xe6eaa9b3, 0xe80d4162, 0xfb257811,
+ 0xf5c290c0, 0xdd750af7, 0xd392e226, 0xc0badb55, 0xce5d3384,
+ 0x91d5ef3b, 0x9f3207ea, 0x8c1a3e99, 0x82fdd648, 0xaa4a4c7f,
+ 0xa4ada4ae, 0xb7859ddd, 0xb962750c, 0x1e307184, 0x10d79955,
+ 0x03ffa026, 0x0d1848f7, 0x25afd2c0, 0x2b483a11, 0x38600362,
+ 0x3687ebb3, 0x690f370c, 0x67e8dfdd, 0x74c0e6ae, 0x7a270e7f,
+ 0x52909448, 0x5c777c99, 0x4f5f45ea, 0x41b8ad3b, 0xf04efc94,
+ 0xfea91445, 0xed812d36, 0xe366c5e7, 0xcbd15fd0, 0xc536b701,
+ 0xd61e8e72, 0xd8f966a3, 0x8771ba1c, 0x899652cd, 0x9abe6bbe,
+ 0x9459836f, 0xbcee1958, 0xb209f189, 0xa121c8fa, 0xafc6202b,
+ 0x19bc6de5, 0x175b8534, 0x0473bc47, 0x0a945496, 0x2223cea1,
+ 0x2cc42670, 0x3fec1f03, 0x310bf7d2, 0x6e832b6d, 0x6064c3bc,
+ 0x734cfacf, 0x7dab121e, 0x551c8829, 0x5bfb60f8, 0x48d3598b,
+ 0x4634b15a, 0xf7c2e0f5, 0xf9250824, 0xea0d3157, 0xe4ead986,
+ 0xcc5d43b1, 0xc2baab60, 0xd1929213, 0xdf757ac2, 0x80fda67d,
+ 0x8e1a4eac, 0x9d3277df, 0x93d59f0e, 0xbb620539, 0xb585ede8,
+ 0xa6add49b, 0xa84a3c4a, 0x11284946, 0x1fcfa197, 0x0ce798e4,
+ 0x02007035, 0x2ab7ea02, 0x245002d3, 0x37783ba0, 0x399fd371,
+ 0x66170fce, 0x68f0e71f, 0x7bd8de6c, 0x753f36bd, 0x5d88ac8a,
+ 0x536f445b, 0x40477d28, 0x4ea095f9, 0xff56c456, 0xf1b12c87,
+ 0xe29915f4, 0xec7efd25, 0xc4c96712, 0xca2e8fc3, 0xd906b6b0,
+ 0xd7e15e61, 0x886982de, 0x868e6a0f, 0x95a6537c, 0x9b41bbad,
+ 0xb3f6219a, 0xbd11c94b, 0xae39f038, 0xa0de18e9, 0x16a45527,
+ 0x1843bdf6, 0x0b6b8485, 0x058c6c54, 0x2d3bf663, 0x23dc1eb2,
+ 0x30f427c1, 0x3e13cf10, 0x619b13af, 0x6f7cfb7e, 0x7c54c20d,
+ 0x72b32adc, 0x5a04b0eb, 0x54e3583a, 0x47cb6149, 0x492c8998,
+ 0xf8dad837, 0xf63d30e6, 0xe5150995, 0xebf2e144, 0xc3457b73,
+ 0xcda293a2, 0xde8aaad1, 0xd06d4200, 0x8fe59ebf, 0x8102766e,
+ 0x922a4f1d, 0x9ccda7cc, 0xb47a3dfb, 0xba9dd52a, 0xa9b5ec59,
+ 0xa7520488},
+ {0x00000000, 0x3c60e308, 0x78c1c610, 0x44a12518, 0xf1838c20,
+ 0xcde36f28, 0x89424a30, 0xb522a938, 0x38761e01, 0x0416fd09,
+ 0x40b7d811, 0x7cd73b19, 0xc9f59221, 0xf5957129, 0xb1345431,
+ 0x8d54b739, 0x70ec3c02, 0x4c8cdf0a, 0x082dfa12, 0x344d191a,
+ 0x816fb022, 0xbd0f532a, 0xf9ae7632, 0xc5ce953a, 0x489a2203,
+ 0x74fac10b, 0x305be413, 0x0c3b071b, 0xb919ae23, 0x85794d2b,
+ 0xc1d86833, 0xfdb88b3b, 0xe1d87804, 0xddb89b0c, 0x9919be14,
+ 0xa5795d1c, 0x105bf424, 0x2c3b172c, 0x689a3234, 0x54fad13c,
+ 0xd9ae6605, 0xe5ce850d, 0xa16fa015, 0x9d0f431d, 0x282dea25,
+ 0x144d092d, 0x50ec2c35, 0x6c8ccf3d, 0x91344406, 0xad54a70e,
+ 0xe9f58216, 0xd595611e, 0x60b7c826, 0x5cd72b2e, 0x18760e36,
+ 0x2416ed3e, 0xa9425a07, 0x9522b90f, 0xd1839c17, 0xede37f1f,
+ 0x58c1d627, 0x64a1352f, 0x20001037, 0x1c60f33f, 0x18c1f649,
+ 0x24a11541, 0x60003059, 0x5c60d351, 0xe9427a69, 0xd5229961,
+ 0x9183bc79, 0xade35f71, 0x20b7e848, 0x1cd70b40, 0x58762e58,
+ 0x6416cd50, 0xd1346468, 0xed548760, 0xa9f5a278, 0x95954170,
+ 0x682dca4b, 0x544d2943, 0x10ec0c5b, 0x2c8cef53, 0x99ae466b,
+ 0xa5cea563, 0xe16f807b, 0xdd0f6373, 0x505bd44a, 0x6c3b3742,
+ 0x289a125a, 0x14faf152, 0xa1d8586a, 0x9db8bb62, 0xd9199e7a,
+ 0xe5797d72, 0xf9198e4d, 0xc5796d45, 0x81d8485d, 0xbdb8ab55,
+ 0x089a026d, 0x34fae165, 0x705bc47d, 0x4c3b2775, 0xc16f904c,
+ 0xfd0f7344, 0xb9ae565c, 0x85ceb554, 0x30ec1c6c, 0x0c8cff64,
+ 0x482dda7c, 0x744d3974, 0x89f5b24f, 0xb5955147, 0xf134745f,
+ 0xcd549757, 0x78763e6f, 0x4416dd67, 0x00b7f87f, 0x3cd71b77,
+ 0xb183ac4e, 0x8de34f46, 0xc9426a5e, 0xf5228956, 0x4000206e,
+ 0x7c60c366, 0x38c1e67e, 0x04a10576, 0x3183ec92, 0x0de30f9a,
+ 0x49422a82, 0x7522c98a, 0xc00060b2, 0xfc6083ba, 0xb8c1a6a2,
+ 0x84a145aa, 0x09f5f293, 0x3595119b, 0x71343483, 0x4d54d78b,
+ 0xf8767eb3, 0xc4169dbb, 0x80b7b8a3, 0xbcd75bab, 0x416fd090,
+ 0x7d0f3398, 0x39ae1680, 0x05cef588, 0xb0ec5cb0, 0x8c8cbfb8,
+ 0xc82d9aa0, 0xf44d79a8, 0x7919ce91, 0x45792d99, 0x01d80881,
+ 0x3db8eb89, 0x889a42b1, 0xb4faa1b9, 0xf05b84a1, 0xcc3b67a9,
+ 0xd05b9496, 0xec3b779e, 0xa89a5286, 0x94fab18e, 0x21d818b6,
+ 0x1db8fbbe, 0x5919dea6, 0x65793dae, 0xe82d8a97, 0xd44d699f,
+ 0x90ec4c87, 0xac8caf8f, 0x19ae06b7, 0x25cee5bf, 0x616fc0a7,
+ 0x5d0f23af, 0xa0b7a894, 0x9cd74b9c, 0xd8766e84, 0xe4168d8c,
+ 0x513424b4, 0x6d54c7bc, 0x29f5e2a4, 0x159501ac, 0x98c1b695,
+ 0xa4a1559d, 0xe0007085, 0xdc60938d, 0x69423ab5, 0x5522d9bd,
+ 0x1183fca5, 0x2de31fad, 0x29421adb, 0x1522f9d3, 0x5183dccb,
+ 0x6de33fc3, 0xd8c196fb, 0xe4a175f3, 0xa00050eb, 0x9c60b3e3,
+ 0x113404da, 0x2d54e7d2, 0x69f5c2ca, 0x559521c2, 0xe0b788fa,
+ 0xdcd76bf2, 0x98764eea, 0xa416ade2, 0x59ae26d9, 0x65cec5d1,
+ 0x216fe0c9, 0x1d0f03c1, 0xa82daaf9, 0x944d49f1, 0xd0ec6ce9,
+ 0xec8c8fe1, 0x61d838d8, 0x5db8dbd0, 0x1919fec8, 0x25791dc0,
+ 0x905bb4f8, 0xac3b57f0, 0xe89a72e8, 0xd4fa91e0, 0xc89a62df,
+ 0xf4fa81d7, 0xb05ba4cf, 0x8c3b47c7, 0x3919eeff, 0x05790df7,
+ 0x41d828ef, 0x7db8cbe7, 0xf0ec7cde, 0xcc8c9fd6, 0x882dbace,
+ 0xb44d59c6, 0x016ff0fe, 0x3d0f13f6, 0x79ae36ee, 0x45ced5e6,
+ 0xb8765edd, 0x8416bdd5, 0xc0b798cd, 0xfcd77bc5, 0x49f5d2fd,
+ 0x759531f5, 0x313414ed, 0x0d54f7e5, 0x800040dc, 0xbc60a3d4,
+ 0xf8c186cc, 0xc4a165c4, 0x7183ccfc, 0x4de32ff4, 0x09420aec,
+ 0x3522e9e4},
+ {0x00000000, 0x6307d924, 0xc60fb248, 0xa5086b6c, 0x576e62d1,
+ 0x3469bbf5, 0x9161d099, 0xf26609bd, 0xaedcc5a2, 0xcddb1c86,
+ 0x68d377ea, 0x0bd4aece, 0xf9b2a773, 0x9ab57e57, 0x3fbd153b,
+ 0x5cbacc1f, 0x86c88d05, 0xe5cf5421, 0x40c73f4d, 0x23c0e669,
+ 0xd1a6efd4, 0xb2a136f0, 0x17a95d9c, 0x74ae84b8, 0x281448a7,
+ 0x4b139183, 0xee1bfaef, 0x8d1c23cb, 0x7f7a2a76, 0x1c7df352,
+ 0xb975983e, 0xda72411a, 0xd6e01c4b, 0xb5e7c56f, 0x10efae03,
+ 0x73e87727, 0x818e7e9a, 0xe289a7be, 0x4781ccd2, 0x248615f6,
+ 0x783cd9e9, 0x1b3b00cd, 0xbe336ba1, 0xdd34b285, 0x2f52bb38,
+ 0x4c55621c, 0xe95d0970, 0x8a5ad054, 0x5028914e, 0x332f486a,
+ 0x96272306, 0xf520fa22, 0x0746f39f, 0x64412abb, 0xc14941d7,
+ 0xa24e98f3, 0xfef454ec, 0x9df38dc8, 0x38fbe6a4, 0x5bfc3f80,
+ 0xa99a363d, 0xca9def19, 0x6f958475, 0x0c925d51, 0x76b13ed7,
+ 0x15b6e7f3, 0xb0be8c9f, 0xd3b955bb, 0x21df5c06, 0x42d88522,
+ 0xe7d0ee4e, 0x84d7376a, 0xd86dfb75, 0xbb6a2251, 0x1e62493d,
+ 0x7d659019, 0x8f0399a4, 0xec044080, 0x490c2bec, 0x2a0bf2c8,
+ 0xf079b3d2, 0x937e6af6, 0x3676019a, 0x5571d8be, 0xa717d103,
+ 0xc4100827, 0x6118634b, 0x021fba6f, 0x5ea57670, 0x3da2af54,
+ 0x98aac438, 0xfbad1d1c, 0x09cb14a1, 0x6acccd85, 0xcfc4a6e9,
+ 0xacc37fcd, 0xa051229c, 0xc356fbb8, 0x665e90d4, 0x055949f0,
+ 0xf73f404d, 0x94389969, 0x3130f205, 0x52372b21, 0x0e8de73e,
+ 0x6d8a3e1a, 0xc8825576, 0xab858c52, 0x59e385ef, 0x3ae45ccb,
+ 0x9fec37a7, 0xfcebee83, 0x2699af99, 0x459e76bd, 0xe0961dd1,
+ 0x8391c4f5, 0x71f7cd48, 0x12f0146c, 0xb7f87f00, 0xd4ffa624,
+ 0x88456a3b, 0xeb42b31f, 0x4e4ad873, 0x2d4d0157, 0xdf2b08ea,
+ 0xbc2cd1ce, 0x1924baa2, 0x7a236386, 0xed627dae, 0x8e65a48a,
+ 0x2b6dcfe6, 0x486a16c2, 0xba0c1f7f, 0xd90bc65b, 0x7c03ad37,
+ 0x1f047413, 0x43beb80c, 0x20b96128, 0x85b10a44, 0xe6b6d360,
+ 0x14d0dadd, 0x77d703f9, 0xd2df6895, 0xb1d8b1b1, 0x6baaf0ab,
+ 0x08ad298f, 0xada542e3, 0xcea29bc7, 0x3cc4927a, 0x5fc34b5e,
+ 0xfacb2032, 0x99ccf916, 0xc5763509, 0xa671ec2d, 0x03798741,
+ 0x607e5e65, 0x921857d8, 0xf11f8efc, 0x5417e590, 0x37103cb4,
+ 0x3b8261e5, 0x5885b8c1, 0xfd8dd3ad, 0x9e8a0a89, 0x6cec0334,
+ 0x0febda10, 0xaae3b17c, 0xc9e46858, 0x955ea447, 0xf6597d63,
+ 0x5351160f, 0x3056cf2b, 0xc230c696, 0xa1371fb2, 0x043f74de,
+ 0x6738adfa, 0xbd4aece0, 0xde4d35c4, 0x7b455ea8, 0x1842878c,
+ 0xea248e31, 0x89235715, 0x2c2b3c79, 0x4f2ce55d, 0x13962942,
+ 0x7091f066, 0xd5999b0a, 0xb69e422e, 0x44f84b93, 0x27ff92b7,
+ 0x82f7f9db, 0xe1f020ff, 0x9bd34379, 0xf8d49a5d, 0x5ddcf131,
+ 0x3edb2815, 0xccbd21a8, 0xafbaf88c, 0x0ab293e0, 0x69b54ac4,
+ 0x350f86db, 0x56085fff, 0xf3003493, 0x9007edb7, 0x6261e40a,
+ 0x01663d2e, 0xa46e5642, 0xc7698f66, 0x1d1bce7c, 0x7e1c1758,
+ 0xdb147c34, 0xb813a510, 0x4a75acad, 0x29727589, 0x8c7a1ee5,
+ 0xef7dc7c1, 0xb3c70bde, 0xd0c0d2fa, 0x75c8b996, 0x16cf60b2,
+ 0xe4a9690f, 0x87aeb02b, 0x22a6db47, 0x41a10263, 0x4d335f32,
+ 0x2e348616, 0x8b3ced7a, 0xe83b345e, 0x1a5d3de3, 0x795ae4c7,
+ 0xdc528fab, 0xbf55568f, 0xe3ef9a90, 0x80e843b4, 0x25e028d8,
+ 0x46e7f1fc, 0xb481f841, 0xd7862165, 0x728e4a09, 0x1189932d,
+ 0xcbfbd237, 0xa8fc0b13, 0x0df4607f, 0x6ef3b95b, 0x9c95b0e6,
+ 0xff9269c2, 0x5a9a02ae, 0x399ddb8a, 0x65271795, 0x0620ceb1,
+ 0xa328a5dd, 0xc02f7cf9, 0x32497544, 0x514eac60, 0xf446c70c,
+ 0x97411e28},
+ {0x00000000, 0x01b5fd1d, 0x036bfa3a, 0x02de0727, 0x06d7f474,
+ 0x07620969, 0x05bc0e4e, 0x0409f353, 0x0dafe8e8, 0x0c1a15f5,
+ 0x0ec412d2, 0x0f71efcf, 0x0b781c9c, 0x0acde181, 0x0813e6a6,
+ 0x09a61bbb, 0x1b5fd1d0, 0x1aea2ccd, 0x18342bea, 0x1981d6f7,
+ 0x1d8825a4, 0x1c3dd8b9, 0x1ee3df9e, 0x1f562283, 0x16f03938,
+ 0x1745c425, 0x159bc302, 0x142e3e1f, 0x1027cd4c, 0x11923051,
+ 0x134c3776, 0x12f9ca6b, 0x36bfa3a0, 0x370a5ebd, 0x35d4599a,
+ 0x3461a487, 0x306857d4, 0x31ddaac9, 0x3303adee, 0x32b650f3,
+ 0x3b104b48, 0x3aa5b655, 0x387bb172, 0x39ce4c6f, 0x3dc7bf3c,
+ 0x3c724221, 0x3eac4506, 0x3f19b81b, 0x2de07270, 0x2c558f6d,
+ 0x2e8b884a, 0x2f3e7557, 0x2b378604, 0x2a827b19, 0x285c7c3e,
+ 0x29e98123, 0x204f9a98, 0x21fa6785, 0x232460a2, 0x22919dbf,
+ 0x26986eec, 0x272d93f1, 0x25f394d6, 0x244669cb, 0x6d7f4740,
+ 0x6ccaba5d, 0x6e14bd7a, 0x6fa14067, 0x6ba8b334, 0x6a1d4e29,
+ 0x68c3490e, 0x6976b413, 0x60d0afa8, 0x616552b5, 0x63bb5592,
+ 0x620ea88f, 0x66075bdc, 0x67b2a6c1, 0x656ca1e6, 0x64d95cfb,
+ 0x76209690, 0x77956b8d, 0x754b6caa, 0x74fe91b7, 0x70f762e4,
+ 0x71429ff9, 0x739c98de, 0x722965c3, 0x7b8f7e78, 0x7a3a8365,
+ 0x78e48442, 0x7951795f, 0x7d588a0c, 0x7ced7711, 0x7e337036,
+ 0x7f868d2b, 0x5bc0e4e0, 0x5a7519fd, 0x58ab1eda, 0x591ee3c7,
+ 0x5d171094, 0x5ca2ed89, 0x5e7ceaae, 0x5fc917b3, 0x566f0c08,
+ 0x57daf115, 0x5504f632, 0x54b10b2f, 0x50b8f87c, 0x510d0561,
+ 0x53d30246, 0x5266ff5b, 0x409f3530, 0x412ac82d, 0x43f4cf0a,
+ 0x42413217, 0x4648c144, 0x47fd3c59, 0x45233b7e, 0x4496c663,
+ 0x4d30ddd8, 0x4c8520c5, 0x4e5b27e2, 0x4feedaff, 0x4be729ac,
+ 0x4a52d4b1, 0x488cd396, 0x49392e8b, 0xdafe8e80, 0xdb4b739d,
+ 0xd99574ba, 0xd82089a7, 0xdc297af4, 0xdd9c87e9, 0xdf4280ce,
+ 0xdef77dd3, 0xd7516668, 0xd6e49b75, 0xd43a9c52, 0xd58f614f,
+ 0xd186921c, 0xd0336f01, 0xd2ed6826, 0xd358953b, 0xc1a15f50,
+ 0xc014a24d, 0xc2caa56a, 0xc37f5877, 0xc776ab24, 0xc6c35639,
+ 0xc41d511e, 0xc5a8ac03, 0xcc0eb7b8, 0xcdbb4aa5, 0xcf654d82,
+ 0xced0b09f, 0xcad943cc, 0xcb6cbed1, 0xc9b2b9f6, 0xc80744eb,
+ 0xec412d20, 0xedf4d03d, 0xef2ad71a, 0xee9f2a07, 0xea96d954,
+ 0xeb232449, 0xe9fd236e, 0xe848de73, 0xe1eec5c8, 0xe05b38d5,
+ 0xe2853ff2, 0xe330c2ef, 0xe73931bc, 0xe68ccca1, 0xe452cb86,
+ 0xe5e7369b, 0xf71efcf0, 0xf6ab01ed, 0xf47506ca, 0xf5c0fbd7,
+ 0xf1c90884, 0xf07cf599, 0xf2a2f2be, 0xf3170fa3, 0xfab11418,
+ 0xfb04e905, 0xf9daee22, 0xf86f133f, 0xfc66e06c, 0xfdd31d71,
+ 0xff0d1a56, 0xfeb8e74b, 0xb781c9c0, 0xb63434dd, 0xb4ea33fa,
+ 0xb55fcee7, 0xb1563db4, 0xb0e3c0a9, 0xb23dc78e, 0xb3883a93,
+ 0xba2e2128, 0xbb9bdc35, 0xb945db12, 0xb8f0260f, 0xbcf9d55c,
+ 0xbd4c2841, 0xbf922f66, 0xbe27d27b, 0xacde1810, 0xad6be50d,
+ 0xafb5e22a, 0xae001f37, 0xaa09ec64, 0xabbc1179, 0xa962165e,
+ 0xa8d7eb43, 0xa171f0f8, 0xa0c40de5, 0xa21a0ac2, 0xa3aff7df,
+ 0xa7a6048c, 0xa613f991, 0xa4cdfeb6, 0xa57803ab, 0x813e6a60,
+ 0x808b977d, 0x8255905a, 0x83e06d47, 0x87e99e14, 0x865c6309,
+ 0x8482642e, 0x85379933, 0x8c918288, 0x8d247f95, 0x8ffa78b2,
+ 0x8e4f85af, 0x8a4676fc, 0x8bf38be1, 0x892d8cc6, 0x889871db,
+ 0x9a61bbb0, 0x9bd446ad, 0x990a418a, 0x98bfbc97, 0x9cb64fc4,
+ 0x9d03b2d9, 0x9fddb5fe, 0x9e6848e3, 0x97ce5358, 0x967bae45,
+ 0x94a5a962, 0x9510547f, 0x9119a72c, 0x90ac5a31, 0x92725d16,
+ 0x93c7a00b},
+ {0x00000000, 0x6e8c1b41, 0xdd183682, 0xb3942dc3, 0x61416b45,
+ 0x0fcd7004, 0xbc595dc7, 0xd2d54686, 0xc282d68a, 0xac0ecdcb,
+ 0x1f9ae008, 0x7116fb49, 0xa3c3bdcf, 0xcd4fa68e, 0x7edb8b4d,
+ 0x1057900c, 0x5e74ab55, 0x30f8b014, 0x836c9dd7, 0xede08696,
+ 0x3f35c010, 0x51b9db51, 0xe22df692, 0x8ca1edd3, 0x9cf67ddf,
+ 0xf27a669e, 0x41ee4b5d, 0x2f62501c, 0xfdb7169a, 0x933b0ddb,
+ 0x20af2018, 0x4e233b59, 0xbce956aa, 0xd2654deb, 0x61f16028,
+ 0x0f7d7b69, 0xdda83def, 0xb32426ae, 0x00b00b6d, 0x6e3c102c,
+ 0x7e6b8020, 0x10e79b61, 0xa373b6a2, 0xcdffade3, 0x1f2aeb65,
+ 0x71a6f024, 0xc232dde7, 0xacbec6a6, 0xe29dfdff, 0x8c11e6be,
+ 0x3f85cb7d, 0x5109d03c, 0x83dc96ba, 0xed508dfb, 0x5ec4a038,
+ 0x3048bb79, 0x201f2b75, 0x4e933034, 0xfd071df7, 0x938b06b6,
+ 0x415e4030, 0x2fd25b71, 0x9c4676b2, 0xf2ca6df3, 0xa2a3ab15,
+ 0xcc2fb054, 0x7fbb9d97, 0x113786d6, 0xc3e2c050, 0xad6edb11,
+ 0x1efaf6d2, 0x7076ed93, 0x60217d9f, 0x0ead66de, 0xbd394b1d,
+ 0xd3b5505c, 0x016016da, 0x6fec0d9b, 0xdc782058, 0xb2f43b19,
+ 0xfcd70040, 0x925b1b01, 0x21cf36c2, 0x4f432d83, 0x9d966b05,
+ 0xf31a7044, 0x408e5d87, 0x2e0246c6, 0x3e55d6ca, 0x50d9cd8b,
+ 0xe34de048, 0x8dc1fb09, 0x5f14bd8f, 0x3198a6ce, 0x820c8b0d,
+ 0xec80904c, 0x1e4afdbf, 0x70c6e6fe, 0xc352cb3d, 0xadded07c,
+ 0x7f0b96fa, 0x11878dbb, 0xa213a078, 0xcc9fbb39, 0xdcc82b35,
+ 0xb2443074, 0x01d01db7, 0x6f5c06f6, 0xbd894070, 0xd3055b31,
+ 0x609176f2, 0x0e1d6db3, 0x403e56ea, 0x2eb24dab, 0x9d266068,
+ 0xf3aa7b29, 0x217f3daf, 0x4ff326ee, 0xfc670b2d, 0x92eb106c,
+ 0x82bc8060, 0xec309b21, 0x5fa4b6e2, 0x3128ada3, 0xe3fdeb25,
+ 0x8d71f064, 0x3ee5dda7, 0x5069c6e6, 0x9e36506b, 0xf0ba4b2a,
+ 0x432e66e9, 0x2da27da8, 0xff773b2e, 0x91fb206f, 0x226f0dac,
+ 0x4ce316ed, 0x5cb486e1, 0x32389da0, 0x81acb063, 0xef20ab22,
+ 0x3df5eda4, 0x5379f6e5, 0xe0eddb26, 0x8e61c067, 0xc042fb3e,
+ 0xaecee07f, 0x1d5acdbc, 0x73d6d6fd, 0xa103907b, 0xcf8f8b3a,
+ 0x7c1ba6f9, 0x1297bdb8, 0x02c02db4, 0x6c4c36f5, 0xdfd81b36,
+ 0xb1540077, 0x638146f1, 0x0d0d5db0, 0xbe997073, 0xd0156b32,
+ 0x22df06c1, 0x4c531d80, 0xffc73043, 0x914b2b02, 0x439e6d84,
+ 0x2d1276c5, 0x9e865b06, 0xf00a4047, 0xe05dd04b, 0x8ed1cb0a,
+ 0x3d45e6c9, 0x53c9fd88, 0x811cbb0e, 0xef90a04f, 0x5c048d8c,
+ 0x328896cd, 0x7cabad94, 0x1227b6d5, 0xa1b39b16, 0xcf3f8057,
+ 0x1deac6d1, 0x7366dd90, 0xc0f2f053, 0xae7eeb12, 0xbe297b1e,
+ 0xd0a5605f, 0x63314d9c, 0x0dbd56dd, 0xdf68105b, 0xb1e40b1a,
+ 0x027026d9, 0x6cfc3d98, 0x3c95fb7e, 0x5219e03f, 0xe18dcdfc,
+ 0x8f01d6bd, 0x5dd4903b, 0x33588b7a, 0x80cca6b9, 0xee40bdf8,
+ 0xfe172df4, 0x909b36b5, 0x230f1b76, 0x4d830037, 0x9f5646b1,
+ 0xf1da5df0, 0x424e7033, 0x2cc26b72, 0x62e1502b, 0x0c6d4b6a,
+ 0xbff966a9, 0xd1757de8, 0x03a03b6e, 0x6d2c202f, 0xdeb80dec,
+ 0xb03416ad, 0xa06386a1, 0xceef9de0, 0x7d7bb023, 0x13f7ab62,
+ 0xc122ede4, 0xafaef6a5, 0x1c3adb66, 0x72b6c027, 0x807cadd4,
+ 0xeef0b695, 0x5d649b56, 0x33e88017, 0xe13dc691, 0x8fb1ddd0,
+ 0x3c25f013, 0x52a9eb52, 0x42fe7b5e, 0x2c72601f, 0x9fe64ddc,
+ 0xf16a569d, 0x23bf101b, 0x4d330b5a, 0xfea72699, 0x902b3dd8,
+ 0xde080681, 0xb0841dc0, 0x03103003, 0x6d9c2b42, 0xbf496dc4,
+ 0xd1c57685, 0x62515b46, 0x0cdd4007, 0x1c8ad00b, 0x7206cb4a,
+ 0xc192e689, 0xaf1efdc8, 0x7dcbbb4e, 0x1347a00f, 0xa0d38dcc,
+ 0xce5f968d},
+ {0x00000000, 0xe71da697, 0x154a4b6f, 0xf257edf8, 0x2a9496de,
+ 0xcd893049, 0x3fdeddb1, 0xd8c37b26, 0x55292dbc, 0xb2348b2b,
+ 0x406366d3, 0xa77ec044, 0x7fbdbb62, 0x98a01df5, 0x6af7f00d,
+ 0x8dea569a, 0xaa525b78, 0x4d4ffdef, 0xbf181017, 0x5805b680,
+ 0x80c6cda6, 0x67db6b31, 0x958c86c9, 0x7291205e, 0xff7b76c4,
+ 0x1866d053, 0xea313dab, 0x0d2c9b3c, 0xd5efe01a, 0x32f2468d,
+ 0xc0a5ab75, 0x27b80de2, 0x8fd5b0b1, 0x68c81626, 0x9a9ffbde,
+ 0x7d825d49, 0xa541266f, 0x425c80f8, 0xb00b6d00, 0x5716cb97,
+ 0xdafc9d0d, 0x3de13b9a, 0xcfb6d662, 0x28ab70f5, 0xf0680bd3,
+ 0x1775ad44, 0xe52240bc, 0x023fe62b, 0x2587ebc9, 0xc29a4d5e,
+ 0x30cda0a6, 0xd7d00631, 0x0f137d17, 0xe80edb80, 0x1a593678,
+ 0xfd4490ef, 0x70aec675, 0x97b360e2, 0x65e48d1a, 0x82f92b8d,
+ 0x5a3a50ab, 0xbd27f63c, 0x4f701bc4, 0xa86dbd53, 0xc4da6723,
+ 0x23c7c1b4, 0xd1902c4c, 0x368d8adb, 0xee4ef1fd, 0x0953576a,
+ 0xfb04ba92, 0x1c191c05, 0x91f34a9f, 0x76eeec08, 0x84b901f0,
+ 0x63a4a767, 0xbb67dc41, 0x5c7a7ad6, 0xae2d972e, 0x493031b9,
+ 0x6e883c5b, 0x89959acc, 0x7bc27734, 0x9cdfd1a3, 0x441caa85,
+ 0xa3010c12, 0x5156e1ea, 0xb64b477d, 0x3ba111e7, 0xdcbcb770,
+ 0x2eeb5a88, 0xc9f6fc1f, 0x11358739, 0xf62821ae, 0x047fcc56,
+ 0xe3626ac1, 0x4b0fd792, 0xac127105, 0x5e459cfd, 0xb9583a6a,
+ 0x619b414c, 0x8686e7db, 0x74d10a23, 0x93ccacb4, 0x1e26fa2e,
+ 0xf93b5cb9, 0x0b6cb141, 0xec7117d6, 0x34b26cf0, 0xd3afca67,
+ 0x21f8279f, 0xc6e58108, 0xe15d8cea, 0x06402a7d, 0xf417c785,
+ 0x130a6112, 0xcbc91a34, 0x2cd4bca3, 0xde83515b, 0x399ef7cc,
+ 0xb474a156, 0x536907c1, 0xa13eea39, 0x46234cae, 0x9ee03788,
+ 0x79fd911f, 0x8baa7ce7, 0x6cb7da70, 0x52c5c807, 0xb5d86e90,
+ 0x478f8368, 0xa09225ff, 0x78515ed9, 0x9f4cf84e, 0x6d1b15b6,
+ 0x8a06b321, 0x07ece5bb, 0xe0f1432c, 0x12a6aed4, 0xf5bb0843,
+ 0x2d787365, 0xca65d5f2, 0x3832380a, 0xdf2f9e9d, 0xf897937f,
+ 0x1f8a35e8, 0xedddd810, 0x0ac07e87, 0xd20305a1, 0x351ea336,
+ 0xc7494ece, 0x2054e859, 0xadbebec3, 0x4aa31854, 0xb8f4f5ac,
+ 0x5fe9533b, 0x872a281d, 0x60378e8a, 0x92606372, 0x757dc5e5,
+ 0xdd1078b6, 0x3a0dde21, 0xc85a33d9, 0x2f47954e, 0xf784ee68,
+ 0x109948ff, 0xe2cea507, 0x05d30390, 0x8839550a, 0x6f24f39d,
+ 0x9d731e65, 0x7a6eb8f2, 0xa2adc3d4, 0x45b06543, 0xb7e788bb,
+ 0x50fa2e2c, 0x774223ce, 0x905f8559, 0x620868a1, 0x8515ce36,
+ 0x5dd6b510, 0xbacb1387, 0x489cfe7f, 0xaf8158e8, 0x226b0e72,
+ 0xc576a8e5, 0x3721451d, 0xd03ce38a, 0x08ff98ac, 0xefe23e3b,
+ 0x1db5d3c3, 0xfaa87554, 0x961faf24, 0x710209b3, 0x8355e44b,
+ 0x644842dc, 0xbc8b39fa, 0x5b969f6d, 0xa9c17295, 0x4edcd402,
+ 0xc3368298, 0x242b240f, 0xd67cc9f7, 0x31616f60, 0xe9a21446,
+ 0x0ebfb2d1, 0xfce85f29, 0x1bf5f9be, 0x3c4df45c, 0xdb5052cb,
+ 0x2907bf33, 0xce1a19a4, 0x16d96282, 0xf1c4c415, 0x039329ed,
+ 0xe48e8f7a, 0x6964d9e0, 0x8e797f77, 0x7c2e928f, 0x9b333418,
+ 0x43f04f3e, 0xa4ede9a9, 0x56ba0451, 0xb1a7a2c6, 0x19ca1f95,
+ 0xfed7b902, 0x0c8054fa, 0xeb9df26d, 0x335e894b, 0xd4432fdc,
+ 0x2614c224, 0xc10964b3, 0x4ce33229, 0xabfe94be, 0x59a97946,
+ 0xbeb4dfd1, 0x6677a4f7, 0x816a0260, 0x733def98, 0x9420490f,
+ 0xb39844ed, 0x5485e27a, 0xa6d20f82, 0x41cfa915, 0x990cd233,
+ 0x7e1174a4, 0x8c46995c, 0x6b5b3fcb, 0xe6b16951, 0x01accfc6,
+ 0xf3fb223e, 0x14e684a9, 0xcc25ff8f, 0x2b385918, 0xd96fb4e0,
+ 0x3e721277},
+ {0x00000000, 0xa58b900e, 0x9066265d, 0x35edb653, 0xfbbd4afb,
+ 0x5e36daf5, 0x6bdb6ca6, 0xce50fca8, 0x2c0b93b7, 0x898003b9,
+ 0xbc6db5ea, 0x19e625e4, 0xd7b6d94c, 0x723d4942, 0x47d0ff11,
+ 0xe25b6f1f, 0x5817276e, 0xfd9cb760, 0xc8710133, 0x6dfa913d,
+ 0xa3aa6d95, 0x0621fd9b, 0x33cc4bc8, 0x9647dbc6, 0x741cb4d9,
+ 0xd19724d7, 0xe47a9284, 0x41f1028a, 0x8fa1fe22, 0x2a2a6e2c,
+ 0x1fc7d87f, 0xba4c4871, 0xb02e4edc, 0x15a5ded2, 0x20486881,
+ 0x85c3f88f, 0x4b930427, 0xee189429, 0xdbf5227a, 0x7e7eb274,
+ 0x9c25dd6b, 0x39ae4d65, 0x0c43fb36, 0xa9c86b38, 0x67989790,
+ 0xc213079e, 0xf7feb1cd, 0x527521c3, 0xe83969b2, 0x4db2f9bc,
+ 0x785f4fef, 0xddd4dfe1, 0x13842349, 0xb60fb347, 0x83e20514,
+ 0x2669951a, 0xc432fa05, 0x61b96a0b, 0x5454dc58, 0xf1df4c56,
+ 0x3f8fb0fe, 0x9a0420f0, 0xafe996a3, 0x0a6206ad, 0xbb2d9bf9,
+ 0x1ea60bf7, 0x2b4bbda4, 0x8ec02daa, 0x4090d102, 0xe51b410c,
+ 0xd0f6f75f, 0x757d6751, 0x9726084e, 0x32ad9840, 0x07402e13,
+ 0xa2cbbe1d, 0x6c9b42b5, 0xc910d2bb, 0xfcfd64e8, 0x5976f4e6,
+ 0xe33abc97, 0x46b12c99, 0x735c9aca, 0xd6d70ac4, 0x1887f66c,
+ 0xbd0c6662, 0x88e1d031, 0x2d6a403f, 0xcf312f20, 0x6ababf2e,
+ 0x5f57097d, 0xfadc9973, 0x348c65db, 0x9107f5d5, 0xa4ea4386,
+ 0x0161d388, 0x0b03d525, 0xae88452b, 0x9b65f378, 0x3eee6376,
+ 0xf0be9fde, 0x55350fd0, 0x60d8b983, 0xc553298d, 0x27084692,
+ 0x8283d69c, 0xb76e60cf, 0x12e5f0c1, 0xdcb50c69, 0x793e9c67,
+ 0x4cd32a34, 0xe958ba3a, 0x5314f24b, 0xf69f6245, 0xc372d416,
+ 0x66f94418, 0xa8a9b8b0, 0x0d2228be, 0x38cf9eed, 0x9d440ee3,
+ 0x7f1f61fc, 0xda94f1f2, 0xef7947a1, 0x4af2d7af, 0x84a22b07,
+ 0x2129bb09, 0x14c40d5a, 0xb14f9d54, 0xad2a31b3, 0x08a1a1bd,
+ 0x3d4c17ee, 0x98c787e0, 0x56977b48, 0xf31ceb46, 0xc6f15d15,
+ 0x637acd1b, 0x8121a204, 0x24aa320a, 0x11478459, 0xb4cc1457,
+ 0x7a9ce8ff, 0xdf1778f1, 0xeafacea2, 0x4f715eac, 0xf53d16dd,
+ 0x50b686d3, 0x655b3080, 0xc0d0a08e, 0x0e805c26, 0xab0bcc28,
+ 0x9ee67a7b, 0x3b6dea75, 0xd936856a, 0x7cbd1564, 0x4950a337,
+ 0xecdb3339, 0x228bcf91, 0x87005f9f, 0xb2ede9cc, 0x176679c2,
+ 0x1d047f6f, 0xb88fef61, 0x8d625932, 0x28e9c93c, 0xe6b93594,
+ 0x4332a59a, 0x76df13c9, 0xd35483c7, 0x310fecd8, 0x94847cd6,
+ 0xa169ca85, 0x04e25a8b, 0xcab2a623, 0x6f39362d, 0x5ad4807e,
+ 0xff5f1070, 0x45135801, 0xe098c80f, 0xd5757e5c, 0x70feee52,
+ 0xbeae12fa, 0x1b2582f4, 0x2ec834a7, 0x8b43a4a9, 0x6918cbb6,
+ 0xcc935bb8, 0xf97eedeb, 0x5cf57de5, 0x92a5814d, 0x372e1143,
+ 0x02c3a710, 0xa748371e, 0x1607aa4a, 0xb38c3a44, 0x86618c17,
+ 0x23ea1c19, 0xedbae0b1, 0x483170bf, 0x7ddcc6ec, 0xd85756e2,
+ 0x3a0c39fd, 0x9f87a9f3, 0xaa6a1fa0, 0x0fe18fae, 0xc1b17306,
+ 0x643ae308, 0x51d7555b, 0xf45cc555, 0x4e108d24, 0xeb9b1d2a,
+ 0xde76ab79, 0x7bfd3b77, 0xb5adc7df, 0x102657d1, 0x25cbe182,
+ 0x8040718c, 0x621b1e93, 0xc7908e9d, 0xf27d38ce, 0x57f6a8c0,
+ 0x99a65468, 0x3c2dc466, 0x09c07235, 0xac4be23b, 0xa629e496,
+ 0x03a27498, 0x364fc2cb, 0x93c452c5, 0x5d94ae6d, 0xf81f3e63,
+ 0xcdf28830, 0x6879183e, 0x8a227721, 0x2fa9e72f, 0x1a44517c,
+ 0xbfcfc172, 0x719f3dda, 0xd414add4, 0xe1f91b87, 0x44728b89,
+ 0xfe3ec3f8, 0x5bb553f6, 0x6e58e5a5, 0xcbd375ab, 0x05838903,
+ 0xa008190d, 0x95e5af5e, 0x306e3f50, 0xd235504f, 0x77bec041,
+ 0x42537612, 0xe7d8e61c, 0x29881ab4, 0x8c038aba, 0xb9ee3ce9,
+ 0x1c65ace7}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0x0e908ba500000000, 0x5d26669000000000,
+ 0x53b6ed3500000000, 0xfb4abdfb00000000, 0xf5da365e00000000,
+ 0xa66cdb6b00000000, 0xa8fc50ce00000000, 0xb7930b2c00000000,
+ 0xb903808900000000, 0xeab56dbc00000000, 0xe425e61900000000,
+ 0x4cd9b6d700000000, 0x42493d7200000000, 0x11ffd04700000000,
+ 0x1f6f5be200000000, 0x6e27175800000000, 0x60b79cfd00000000,
+ 0x330171c800000000, 0x3d91fa6d00000000, 0x956daaa300000000,
+ 0x9bfd210600000000, 0xc84bcc3300000000, 0xc6db479600000000,
+ 0xd9b41c7400000000, 0xd72497d100000000, 0x84927ae400000000,
+ 0x8a02f14100000000, 0x22fea18f00000000, 0x2c6e2a2a00000000,
+ 0x7fd8c71f00000000, 0x71484cba00000000, 0xdc4e2eb000000000,
+ 0xd2dea51500000000, 0x8168482000000000, 0x8ff8c38500000000,
+ 0x2704934b00000000, 0x299418ee00000000, 0x7a22f5db00000000,
+ 0x74b27e7e00000000, 0x6bdd259c00000000, 0x654dae3900000000,
+ 0x36fb430c00000000, 0x386bc8a900000000, 0x9097986700000000,
+ 0x9e0713c200000000, 0xcdb1fef700000000, 0xc321755200000000,
+ 0xb26939e800000000, 0xbcf9b24d00000000, 0xef4f5f7800000000,
+ 0xe1dfd4dd00000000, 0x4923841300000000, 0x47b30fb600000000,
+ 0x1405e28300000000, 0x1a95692600000000, 0x05fa32c400000000,
+ 0x0b6ab96100000000, 0x58dc545400000000, 0x564cdff100000000,
+ 0xfeb08f3f00000000, 0xf020049a00000000, 0xa396e9af00000000,
+ 0xad06620a00000000, 0xf99b2dbb00000000, 0xf70ba61e00000000,
+ 0xa4bd4b2b00000000, 0xaa2dc08e00000000, 0x02d1904000000000,
+ 0x0c411be500000000, 0x5ff7f6d000000000, 0x51677d7500000000,
+ 0x4e08269700000000, 0x4098ad3200000000, 0x132e400700000000,
+ 0x1dbecba200000000, 0xb5429b6c00000000, 0xbbd210c900000000,
+ 0xe864fdfc00000000, 0xe6f4765900000000, 0x97bc3ae300000000,
+ 0x992cb14600000000, 0xca9a5c7300000000, 0xc40ad7d600000000,
+ 0x6cf6871800000000, 0x62660cbd00000000, 0x31d0e18800000000,
+ 0x3f406a2d00000000, 0x202f31cf00000000, 0x2ebfba6a00000000,
+ 0x7d09575f00000000, 0x7399dcfa00000000, 0xdb658c3400000000,
+ 0xd5f5079100000000, 0x8643eaa400000000, 0x88d3610100000000,
+ 0x25d5030b00000000, 0x2b4588ae00000000, 0x78f3659b00000000,
+ 0x7663ee3e00000000, 0xde9fbef000000000, 0xd00f355500000000,
+ 0x83b9d86000000000, 0x8d2953c500000000, 0x9246082700000000,
+ 0x9cd6838200000000, 0xcf606eb700000000, 0xc1f0e51200000000,
+ 0x690cb5dc00000000, 0x679c3e7900000000, 0x342ad34c00000000,
+ 0x3aba58e900000000, 0x4bf2145300000000, 0x45629ff600000000,
+ 0x16d472c300000000, 0x1844f96600000000, 0xb0b8a9a800000000,
+ 0xbe28220d00000000, 0xed9ecf3800000000, 0xe30e449d00000000,
+ 0xfc611f7f00000000, 0xf2f194da00000000, 0xa14779ef00000000,
+ 0xafd7f24a00000000, 0x072ba28400000000, 0x09bb292100000000,
+ 0x5a0dc41400000000, 0x549d4fb100000000, 0xb3312aad00000000,
+ 0xbda1a10800000000, 0xee174c3d00000000, 0xe087c79800000000,
+ 0x487b975600000000, 0x46eb1cf300000000, 0x155df1c600000000,
+ 0x1bcd7a6300000000, 0x04a2218100000000, 0x0a32aa2400000000,
+ 0x5984471100000000, 0x5714ccb400000000, 0xffe89c7a00000000,
+ 0xf17817df00000000, 0xa2cefaea00000000, 0xac5e714f00000000,
+ 0xdd163df500000000, 0xd386b65000000000, 0x80305b6500000000,
+ 0x8ea0d0c000000000, 0x265c800e00000000, 0x28cc0bab00000000,
+ 0x7b7ae69e00000000, 0x75ea6d3b00000000, 0x6a8536d900000000,
+ 0x6415bd7c00000000, 0x37a3504900000000, 0x3933dbec00000000,
+ 0x91cf8b2200000000, 0x9f5f008700000000, 0xcce9edb200000000,
+ 0xc279661700000000, 0x6f7f041d00000000, 0x61ef8fb800000000,
+ 0x3259628d00000000, 0x3cc9e92800000000, 0x9435b9e600000000,
+ 0x9aa5324300000000, 0xc913df7600000000, 0xc78354d300000000,
+ 0xd8ec0f3100000000, 0xd67c849400000000, 0x85ca69a100000000,
+ 0x8b5ae20400000000, 0x23a6b2ca00000000, 0x2d36396f00000000,
+ 0x7e80d45a00000000, 0x70105fff00000000, 0x0158134500000000,
+ 0x0fc898e000000000, 0x5c7e75d500000000, 0x52eefe7000000000,
+ 0xfa12aebe00000000, 0xf482251b00000000, 0xa734c82e00000000,
+ 0xa9a4438b00000000, 0xb6cb186900000000, 0xb85b93cc00000000,
+ 0xebed7ef900000000, 0xe57df55c00000000, 0x4d81a59200000000,
+ 0x43112e3700000000, 0x10a7c30200000000, 0x1e3748a700000000,
+ 0x4aaa071600000000, 0x443a8cb300000000, 0x178c618600000000,
+ 0x191cea2300000000, 0xb1e0baed00000000, 0xbf70314800000000,
+ 0xecc6dc7d00000000, 0xe25657d800000000, 0xfd390c3a00000000,
+ 0xf3a9879f00000000, 0xa01f6aaa00000000, 0xae8fe10f00000000,
+ 0x0673b1c100000000, 0x08e33a6400000000, 0x5b55d75100000000,
+ 0x55c55cf400000000, 0x248d104e00000000, 0x2a1d9beb00000000,
+ 0x79ab76de00000000, 0x773bfd7b00000000, 0xdfc7adb500000000,
+ 0xd157261000000000, 0x82e1cb2500000000, 0x8c71408000000000,
+ 0x931e1b6200000000, 0x9d8e90c700000000, 0xce387df200000000,
+ 0xc0a8f65700000000, 0x6854a69900000000, 0x66c42d3c00000000,
+ 0x3572c00900000000, 0x3be24bac00000000, 0x96e429a600000000,
+ 0x9874a20300000000, 0xcbc24f3600000000, 0xc552c49300000000,
+ 0x6dae945d00000000, 0x633e1ff800000000, 0x3088f2cd00000000,
+ 0x3e18796800000000, 0x2177228a00000000, 0x2fe7a92f00000000,
+ 0x7c51441a00000000, 0x72c1cfbf00000000, 0xda3d9f7100000000,
+ 0xd4ad14d400000000, 0x871bf9e100000000, 0x898b724400000000,
+ 0xf8c33efe00000000, 0xf653b55b00000000, 0xa5e5586e00000000,
+ 0xab75d3cb00000000, 0x0389830500000000, 0x0d1908a000000000,
+ 0x5eafe59500000000, 0x503f6e3000000000, 0x4f5035d200000000,
+ 0x41c0be7700000000, 0x1276534200000000, 0x1ce6d8e700000000,
+ 0xb41a882900000000, 0xba8a038c00000000, 0xe93ceeb900000000,
+ 0xe7ac651c00000000},
+ {0x0000000000000000, 0x97a61de700000000, 0x6f4b4a1500000000,
+ 0xf8ed57f200000000, 0xde96942a00000000, 0x493089cd00000000,
+ 0xb1ddde3f00000000, 0x267bc3d800000000, 0xbc2d295500000000,
+ 0x2b8b34b200000000, 0xd366634000000000, 0x44c07ea700000000,
+ 0x62bbbd7f00000000, 0xf51da09800000000, 0x0df0f76a00000000,
+ 0x9a56ea8d00000000, 0x785b52aa00000000, 0xeffd4f4d00000000,
+ 0x171018bf00000000, 0x80b6055800000000, 0xa6cdc68000000000,
+ 0x316bdb6700000000, 0xc9868c9500000000, 0x5e20917200000000,
+ 0xc4767bff00000000, 0x53d0661800000000, 0xab3d31ea00000000,
+ 0x3c9b2c0d00000000, 0x1ae0efd500000000, 0x8d46f23200000000,
+ 0x75aba5c000000000, 0xe20db82700000000, 0xb1b0d58f00000000,
+ 0x2616c86800000000, 0xdefb9f9a00000000, 0x495d827d00000000,
+ 0x6f2641a500000000, 0xf8805c4200000000, 0x006d0bb000000000,
+ 0x97cb165700000000, 0x0d9dfcda00000000, 0x9a3be13d00000000,
+ 0x62d6b6cf00000000, 0xf570ab2800000000, 0xd30b68f000000000,
+ 0x44ad751700000000, 0xbc4022e500000000, 0x2be63f0200000000,
+ 0xc9eb872500000000, 0x5e4d9ac200000000, 0xa6a0cd3000000000,
+ 0x3106d0d700000000, 0x177d130f00000000, 0x80db0ee800000000,
+ 0x7836591a00000000, 0xef9044fd00000000, 0x75c6ae7000000000,
+ 0xe260b39700000000, 0x1a8de46500000000, 0x8d2bf98200000000,
+ 0xab503a5a00000000, 0x3cf627bd00000000, 0xc41b704f00000000,
+ 0x53bd6da800000000, 0x2367dac400000000, 0xb4c1c72300000000,
+ 0x4c2c90d100000000, 0xdb8a8d3600000000, 0xfdf14eee00000000,
+ 0x6a57530900000000, 0x92ba04fb00000000, 0x051c191c00000000,
+ 0x9f4af39100000000, 0x08ecee7600000000, 0xf001b98400000000,
+ 0x67a7a46300000000, 0x41dc67bb00000000, 0xd67a7a5c00000000,
+ 0x2e972dae00000000, 0xb931304900000000, 0x5b3c886e00000000,
+ 0xcc9a958900000000, 0x3477c27b00000000, 0xa3d1df9c00000000,
+ 0x85aa1c4400000000, 0x120c01a300000000, 0xeae1565100000000,
+ 0x7d474bb600000000, 0xe711a13b00000000, 0x70b7bcdc00000000,
+ 0x885aeb2e00000000, 0x1ffcf6c900000000, 0x3987351100000000,
+ 0xae2128f600000000, 0x56cc7f0400000000, 0xc16a62e300000000,
+ 0x92d70f4b00000000, 0x057112ac00000000, 0xfd9c455e00000000,
+ 0x6a3a58b900000000, 0x4c419b6100000000, 0xdbe7868600000000,
+ 0x230ad17400000000, 0xb4accc9300000000, 0x2efa261e00000000,
+ 0xb95c3bf900000000, 0x41b16c0b00000000, 0xd61771ec00000000,
+ 0xf06cb23400000000, 0x67caafd300000000, 0x9f27f82100000000,
+ 0x0881e5c600000000, 0xea8c5de100000000, 0x7d2a400600000000,
+ 0x85c717f400000000, 0x12610a1300000000, 0x341ac9cb00000000,
+ 0xa3bcd42c00000000, 0x5b5183de00000000, 0xccf79e3900000000,
+ 0x56a174b400000000, 0xc107695300000000, 0x39ea3ea100000000,
+ 0xae4c234600000000, 0x8837e09e00000000, 0x1f91fd7900000000,
+ 0xe77caa8b00000000, 0x70dab76c00000000, 0x07c8c55200000000,
+ 0x906ed8b500000000, 0x68838f4700000000, 0xff2592a000000000,
+ 0xd95e517800000000, 0x4ef84c9f00000000, 0xb6151b6d00000000,
+ 0x21b3068a00000000, 0xbbe5ec0700000000, 0x2c43f1e000000000,
+ 0xd4aea61200000000, 0x4308bbf500000000, 0x6573782d00000000,
+ 0xf2d565ca00000000, 0x0a38323800000000, 0x9d9e2fdf00000000,
+ 0x7f9397f800000000, 0xe8358a1f00000000, 0x10d8dded00000000,
+ 0x877ec00a00000000, 0xa10503d200000000, 0x36a31e3500000000,
+ 0xce4e49c700000000, 0x59e8542000000000, 0xc3bebead00000000,
+ 0x5418a34a00000000, 0xacf5f4b800000000, 0x3b53e95f00000000,
+ 0x1d282a8700000000, 0x8a8e376000000000, 0x7263609200000000,
+ 0xe5c57d7500000000, 0xb67810dd00000000, 0x21de0d3a00000000,
+ 0xd9335ac800000000, 0x4e95472f00000000, 0x68ee84f700000000,
+ 0xff48991000000000, 0x07a5cee200000000, 0x9003d30500000000,
+ 0x0a55398800000000, 0x9df3246f00000000, 0x651e739d00000000,
+ 0xf2b86e7a00000000, 0xd4c3ada200000000, 0x4365b04500000000,
+ 0xbb88e7b700000000, 0x2c2efa5000000000, 0xce23427700000000,
+ 0x59855f9000000000, 0xa168086200000000, 0x36ce158500000000,
+ 0x10b5d65d00000000, 0x8713cbba00000000, 0x7ffe9c4800000000,
+ 0xe85881af00000000, 0x720e6b2200000000, 0xe5a876c500000000,
+ 0x1d45213700000000, 0x8ae33cd000000000, 0xac98ff0800000000,
+ 0x3b3ee2ef00000000, 0xc3d3b51d00000000, 0x5475a8fa00000000,
+ 0x24af1f9600000000, 0xb309027100000000, 0x4be4558300000000,
+ 0xdc42486400000000, 0xfa398bbc00000000, 0x6d9f965b00000000,
+ 0x9572c1a900000000, 0x02d4dc4e00000000, 0x988236c300000000,
+ 0x0f242b2400000000, 0xf7c97cd600000000, 0x606f613100000000,
+ 0x4614a2e900000000, 0xd1b2bf0e00000000, 0x295fe8fc00000000,
+ 0xbef9f51b00000000, 0x5cf44d3c00000000, 0xcb5250db00000000,
+ 0x33bf072900000000, 0xa4191ace00000000, 0x8262d91600000000,
+ 0x15c4c4f100000000, 0xed29930300000000, 0x7a8f8ee400000000,
+ 0xe0d9646900000000, 0x777f798e00000000, 0x8f922e7c00000000,
+ 0x1834339b00000000, 0x3e4ff04300000000, 0xa9e9eda400000000,
+ 0x5104ba5600000000, 0xc6a2a7b100000000, 0x951fca1900000000,
+ 0x02b9d7fe00000000, 0xfa54800c00000000, 0x6df29deb00000000,
+ 0x4b895e3300000000, 0xdc2f43d400000000, 0x24c2142600000000,
+ 0xb36409c100000000, 0x2932e34c00000000, 0xbe94feab00000000,
+ 0x4679a95900000000, 0xd1dfb4be00000000, 0xf7a4776600000000,
+ 0x60026a8100000000, 0x98ef3d7300000000, 0x0f49209400000000,
+ 0xed4498b300000000, 0x7ae2855400000000, 0x820fd2a600000000,
+ 0x15a9cf4100000000, 0x33d20c9900000000, 0xa474117e00000000,
+ 0x5c99468c00000000, 0xcb3f5b6b00000000, 0x5169b1e600000000,
+ 0xc6cfac0100000000, 0x3e22fbf300000000, 0xa984e61400000000,
+ 0x8fff25cc00000000, 0x1859382b00000000, 0xe0b46fd900000000,
+ 0x7712723e00000000},
+ {0x0000000000000000, 0x411b8c6e00000000, 0x823618dd00000000,
+ 0xc32d94b300000000, 0x456b416100000000, 0x0470cd0f00000000,
+ 0xc75d59bc00000000, 0x8646d5d200000000, 0x8ad682c200000000,
+ 0xcbcd0eac00000000, 0x08e09a1f00000000, 0x49fb167100000000,
+ 0xcfbdc3a300000000, 0x8ea64fcd00000000, 0x4d8bdb7e00000000,
+ 0x0c90571000000000, 0x55ab745e00000000, 0x14b0f83000000000,
+ 0xd79d6c8300000000, 0x9686e0ed00000000, 0x10c0353f00000000,
+ 0x51dbb95100000000, 0x92f62de200000000, 0xd3eda18c00000000,
+ 0xdf7df69c00000000, 0x9e667af200000000, 0x5d4bee4100000000,
+ 0x1c50622f00000000, 0x9a16b7fd00000000, 0xdb0d3b9300000000,
+ 0x1820af2000000000, 0x593b234e00000000, 0xaa56e9bc00000000,
+ 0xeb4d65d200000000, 0x2860f16100000000, 0x697b7d0f00000000,
+ 0xef3da8dd00000000, 0xae2624b300000000, 0x6d0bb00000000000,
+ 0x2c103c6e00000000, 0x20806b7e00000000, 0x619be71000000000,
+ 0xa2b673a300000000, 0xe3adffcd00000000, 0x65eb2a1f00000000,
+ 0x24f0a67100000000, 0xe7dd32c200000000, 0xa6c6beac00000000,
+ 0xfffd9de200000000, 0xbee6118c00000000, 0x7dcb853f00000000,
+ 0x3cd0095100000000, 0xba96dc8300000000, 0xfb8d50ed00000000,
+ 0x38a0c45e00000000, 0x79bb483000000000, 0x752b1f2000000000,
+ 0x3430934e00000000, 0xf71d07fd00000000, 0xb6068b9300000000,
+ 0x30405e4100000000, 0x715bd22f00000000, 0xb276469c00000000,
+ 0xf36dcaf200000000, 0x15aba3a200000000, 0x54b02fcc00000000,
+ 0x979dbb7f00000000, 0xd686371100000000, 0x50c0e2c300000000,
+ 0x11db6ead00000000, 0xd2f6fa1e00000000, 0x93ed767000000000,
+ 0x9f7d216000000000, 0xde66ad0e00000000, 0x1d4b39bd00000000,
+ 0x5c50b5d300000000, 0xda16600100000000, 0x9b0dec6f00000000,
+ 0x582078dc00000000, 0x193bf4b200000000, 0x4000d7fc00000000,
+ 0x011b5b9200000000, 0xc236cf2100000000, 0x832d434f00000000,
+ 0x056b969d00000000, 0x44701af300000000, 0x875d8e4000000000,
+ 0xc646022e00000000, 0xcad6553e00000000, 0x8bcdd95000000000,
+ 0x48e04de300000000, 0x09fbc18d00000000, 0x8fbd145f00000000,
+ 0xcea6983100000000, 0x0d8b0c8200000000, 0x4c9080ec00000000,
+ 0xbffd4a1e00000000, 0xfee6c67000000000, 0x3dcb52c300000000,
+ 0x7cd0dead00000000, 0xfa960b7f00000000, 0xbb8d871100000000,
+ 0x78a013a200000000, 0x39bb9fcc00000000, 0x352bc8dc00000000,
+ 0x743044b200000000, 0xb71dd00100000000, 0xf6065c6f00000000,
+ 0x704089bd00000000, 0x315b05d300000000, 0xf276916000000000,
+ 0xb36d1d0e00000000, 0xea563e4000000000, 0xab4db22e00000000,
+ 0x6860269d00000000, 0x297baaf300000000, 0xaf3d7f2100000000,
+ 0xee26f34f00000000, 0x2d0b67fc00000000, 0x6c10eb9200000000,
+ 0x6080bc8200000000, 0x219b30ec00000000, 0xe2b6a45f00000000,
+ 0xa3ad283100000000, 0x25ebfde300000000, 0x64f0718d00000000,
+ 0xa7dde53e00000000, 0xe6c6695000000000, 0x6b50369e00000000,
+ 0x2a4bbaf000000000, 0xe9662e4300000000, 0xa87da22d00000000,
+ 0x2e3b77ff00000000, 0x6f20fb9100000000, 0xac0d6f2200000000,
+ 0xed16e34c00000000, 0xe186b45c00000000, 0xa09d383200000000,
+ 0x63b0ac8100000000, 0x22ab20ef00000000, 0xa4edf53d00000000,
+ 0xe5f6795300000000, 0x26dbede000000000, 0x67c0618e00000000,
+ 0x3efb42c000000000, 0x7fe0ceae00000000, 0xbccd5a1d00000000,
+ 0xfdd6d67300000000, 0x7b9003a100000000, 0x3a8b8fcf00000000,
+ 0xf9a61b7c00000000, 0xb8bd971200000000, 0xb42dc00200000000,
+ 0xf5364c6c00000000, 0x361bd8df00000000, 0x770054b100000000,
+ 0xf146816300000000, 0xb05d0d0d00000000, 0x737099be00000000,
+ 0x326b15d000000000, 0xc106df2200000000, 0x801d534c00000000,
+ 0x4330c7ff00000000, 0x022b4b9100000000, 0x846d9e4300000000,
+ 0xc576122d00000000, 0x065b869e00000000, 0x47400af000000000,
+ 0x4bd05de000000000, 0x0acbd18e00000000, 0xc9e6453d00000000,
+ 0x88fdc95300000000, 0x0ebb1c8100000000, 0x4fa090ef00000000,
+ 0x8c8d045c00000000, 0xcd96883200000000, 0x94adab7c00000000,
+ 0xd5b6271200000000, 0x169bb3a100000000, 0x57803fcf00000000,
+ 0xd1c6ea1d00000000, 0x90dd667300000000, 0x53f0f2c000000000,
+ 0x12eb7eae00000000, 0x1e7b29be00000000, 0x5f60a5d000000000,
+ 0x9c4d316300000000, 0xdd56bd0d00000000, 0x5b1068df00000000,
+ 0x1a0be4b100000000, 0xd926700200000000, 0x983dfc6c00000000,
+ 0x7efb953c00000000, 0x3fe0195200000000, 0xfccd8de100000000,
+ 0xbdd6018f00000000, 0x3b90d45d00000000, 0x7a8b583300000000,
+ 0xb9a6cc8000000000, 0xf8bd40ee00000000, 0xf42d17fe00000000,
+ 0xb5369b9000000000, 0x761b0f2300000000, 0x3700834d00000000,
+ 0xb146569f00000000, 0xf05ddaf100000000, 0x33704e4200000000,
+ 0x726bc22c00000000, 0x2b50e16200000000, 0x6a4b6d0c00000000,
+ 0xa966f9bf00000000, 0xe87d75d100000000, 0x6e3ba00300000000,
+ 0x2f202c6d00000000, 0xec0db8de00000000, 0xad1634b000000000,
+ 0xa18663a000000000, 0xe09defce00000000, 0x23b07b7d00000000,
+ 0x62abf71300000000, 0xe4ed22c100000000, 0xa5f6aeaf00000000,
+ 0x66db3a1c00000000, 0x27c0b67200000000, 0xd4ad7c8000000000,
+ 0x95b6f0ee00000000, 0x569b645d00000000, 0x1780e83300000000,
+ 0x91c63de100000000, 0xd0ddb18f00000000, 0x13f0253c00000000,
+ 0x52eba95200000000, 0x5e7bfe4200000000, 0x1f60722c00000000,
+ 0xdc4de69f00000000, 0x9d566af100000000, 0x1b10bf2300000000,
+ 0x5a0b334d00000000, 0x9926a7fe00000000, 0xd83d2b9000000000,
+ 0x810608de00000000, 0xc01d84b000000000, 0x0330100300000000,
+ 0x422b9c6d00000000, 0xc46d49bf00000000, 0x8576c5d100000000,
+ 0x465b516200000000, 0x0740dd0c00000000, 0x0bd08a1c00000000,
+ 0x4acb067200000000, 0x89e692c100000000, 0xc8fd1eaf00000000,
+ 0x4ebbcb7d00000000, 0x0fa0471300000000, 0xcc8dd3a000000000,
+ 0x8d965fce00000000},
+ {0x0000000000000000, 0x1dfdb50100000000, 0x3afa6b0300000000,
+ 0x2707de0200000000, 0x74f4d70600000000, 0x6909620700000000,
+ 0x4e0ebc0500000000, 0x53f3090400000000, 0xe8e8af0d00000000,
+ 0xf5151a0c00000000, 0xd212c40e00000000, 0xcfef710f00000000,
+ 0x9c1c780b00000000, 0x81e1cd0a00000000, 0xa6e6130800000000,
+ 0xbb1ba60900000000, 0xd0d15f1b00000000, 0xcd2cea1a00000000,
+ 0xea2b341800000000, 0xf7d6811900000000, 0xa425881d00000000,
+ 0xb9d83d1c00000000, 0x9edfe31e00000000, 0x8322561f00000000,
+ 0x3839f01600000000, 0x25c4451700000000, 0x02c39b1500000000,
+ 0x1f3e2e1400000000, 0x4ccd271000000000, 0x5130921100000000,
+ 0x76374c1300000000, 0x6bcaf91200000000, 0xa0a3bf3600000000,
+ 0xbd5e0a3700000000, 0x9a59d43500000000, 0x87a4613400000000,
+ 0xd457683000000000, 0xc9aadd3100000000, 0xeead033300000000,
+ 0xf350b63200000000, 0x484b103b00000000, 0x55b6a53a00000000,
+ 0x72b17b3800000000, 0x6f4cce3900000000, 0x3cbfc73d00000000,
+ 0x2142723c00000000, 0x0645ac3e00000000, 0x1bb8193f00000000,
+ 0x7072e02d00000000, 0x6d8f552c00000000, 0x4a888b2e00000000,
+ 0x57753e2f00000000, 0x0486372b00000000, 0x197b822a00000000,
+ 0x3e7c5c2800000000, 0x2381e92900000000, 0x989a4f2000000000,
+ 0x8567fa2100000000, 0xa260242300000000, 0xbf9d912200000000,
+ 0xec6e982600000000, 0xf1932d2700000000, 0xd694f32500000000,
+ 0xcb69462400000000, 0x40477f6d00000000, 0x5dbaca6c00000000,
+ 0x7abd146e00000000, 0x6740a16f00000000, 0x34b3a86b00000000,
+ 0x294e1d6a00000000, 0x0e49c36800000000, 0x13b4766900000000,
+ 0xa8afd06000000000, 0xb552656100000000, 0x9255bb6300000000,
+ 0x8fa80e6200000000, 0xdc5b076600000000, 0xc1a6b26700000000,
+ 0xe6a16c6500000000, 0xfb5cd96400000000, 0x9096207600000000,
+ 0x8d6b957700000000, 0xaa6c4b7500000000, 0xb791fe7400000000,
+ 0xe462f77000000000, 0xf99f427100000000, 0xde989c7300000000,
+ 0xc365297200000000, 0x787e8f7b00000000, 0x65833a7a00000000,
+ 0x4284e47800000000, 0x5f79517900000000, 0x0c8a587d00000000,
+ 0x1177ed7c00000000, 0x3670337e00000000, 0x2b8d867f00000000,
+ 0xe0e4c05b00000000, 0xfd19755a00000000, 0xda1eab5800000000,
+ 0xc7e31e5900000000, 0x9410175d00000000, 0x89eda25c00000000,
+ 0xaeea7c5e00000000, 0xb317c95f00000000, 0x080c6f5600000000,
+ 0x15f1da5700000000, 0x32f6045500000000, 0x2f0bb15400000000,
+ 0x7cf8b85000000000, 0x61050d5100000000, 0x4602d35300000000,
+ 0x5bff665200000000, 0x30359f4000000000, 0x2dc82a4100000000,
+ 0x0acff44300000000, 0x1732414200000000, 0x44c1484600000000,
+ 0x593cfd4700000000, 0x7e3b234500000000, 0x63c6964400000000,
+ 0xd8dd304d00000000, 0xc520854c00000000, 0xe2275b4e00000000,
+ 0xffdaee4f00000000, 0xac29e74b00000000, 0xb1d4524a00000000,
+ 0x96d38c4800000000, 0x8b2e394900000000, 0x808efeda00000000,
+ 0x9d734bdb00000000, 0xba7495d900000000, 0xa78920d800000000,
+ 0xf47a29dc00000000, 0xe9879cdd00000000, 0xce8042df00000000,
+ 0xd37df7de00000000, 0x686651d700000000, 0x759be4d600000000,
+ 0x529c3ad400000000, 0x4f618fd500000000, 0x1c9286d100000000,
+ 0x016f33d000000000, 0x2668edd200000000, 0x3b9558d300000000,
+ 0x505fa1c100000000, 0x4da214c000000000, 0x6aa5cac200000000,
+ 0x77587fc300000000, 0x24ab76c700000000, 0x3956c3c600000000,
+ 0x1e511dc400000000, 0x03aca8c500000000, 0xb8b70ecc00000000,
+ 0xa54abbcd00000000, 0x824d65cf00000000, 0x9fb0d0ce00000000,
+ 0xcc43d9ca00000000, 0xd1be6ccb00000000, 0xf6b9b2c900000000,
+ 0xeb4407c800000000, 0x202d41ec00000000, 0x3dd0f4ed00000000,
+ 0x1ad72aef00000000, 0x072a9fee00000000, 0x54d996ea00000000,
+ 0x492423eb00000000, 0x6e23fde900000000, 0x73de48e800000000,
+ 0xc8c5eee100000000, 0xd5385be000000000, 0xf23f85e200000000,
+ 0xefc230e300000000, 0xbc3139e700000000, 0xa1cc8ce600000000,
+ 0x86cb52e400000000, 0x9b36e7e500000000, 0xf0fc1ef700000000,
+ 0xed01abf600000000, 0xca0675f400000000, 0xd7fbc0f500000000,
+ 0x8408c9f100000000, 0x99f57cf000000000, 0xbef2a2f200000000,
+ 0xa30f17f300000000, 0x1814b1fa00000000, 0x05e904fb00000000,
+ 0x22eedaf900000000, 0x3f136ff800000000, 0x6ce066fc00000000,
+ 0x711dd3fd00000000, 0x561a0dff00000000, 0x4be7b8fe00000000,
+ 0xc0c981b700000000, 0xdd3434b600000000, 0xfa33eab400000000,
+ 0xe7ce5fb500000000, 0xb43d56b100000000, 0xa9c0e3b000000000,
+ 0x8ec73db200000000, 0x933a88b300000000, 0x28212eba00000000,
+ 0x35dc9bbb00000000, 0x12db45b900000000, 0x0f26f0b800000000,
+ 0x5cd5f9bc00000000, 0x41284cbd00000000, 0x662f92bf00000000,
+ 0x7bd227be00000000, 0x1018deac00000000, 0x0de56bad00000000,
+ 0x2ae2b5af00000000, 0x371f00ae00000000, 0x64ec09aa00000000,
+ 0x7911bcab00000000, 0x5e1662a900000000, 0x43ebd7a800000000,
+ 0xf8f071a100000000, 0xe50dc4a000000000, 0xc20a1aa200000000,
+ 0xdff7afa300000000, 0x8c04a6a700000000, 0x91f913a600000000,
+ 0xb6fecda400000000, 0xab0378a500000000, 0x606a3e8100000000,
+ 0x7d978b8000000000, 0x5a90558200000000, 0x476de08300000000,
+ 0x149ee98700000000, 0x09635c8600000000, 0x2e64828400000000,
+ 0x3399378500000000, 0x8882918c00000000, 0x957f248d00000000,
+ 0xb278fa8f00000000, 0xaf854f8e00000000, 0xfc76468a00000000,
+ 0xe18bf38b00000000, 0xc68c2d8900000000, 0xdb71988800000000,
+ 0xb0bb619a00000000, 0xad46d49b00000000, 0x8a410a9900000000,
+ 0x97bcbf9800000000, 0xc44fb69c00000000, 0xd9b2039d00000000,
+ 0xfeb5dd9f00000000, 0xe348689e00000000, 0x5853ce9700000000,
+ 0x45ae7b9600000000, 0x62a9a59400000000, 0x7f54109500000000,
+ 0x2ca7199100000000, 0x315aac9000000000, 0x165d729200000000,
+ 0x0ba0c79300000000},
+ {0x0000000000000000, 0x24d9076300000000, 0x48b20fc600000000,
+ 0x6c6b08a500000000, 0xd1626e5700000000, 0xf5bb693400000000,
+ 0x99d0619100000000, 0xbd0966f200000000, 0xa2c5dcae00000000,
+ 0x861cdbcd00000000, 0xea77d36800000000, 0xceaed40b00000000,
+ 0x73a7b2f900000000, 0x577eb59a00000000, 0x3b15bd3f00000000,
+ 0x1fccba5c00000000, 0x058dc88600000000, 0x2154cfe500000000,
+ 0x4d3fc74000000000, 0x69e6c02300000000, 0xd4efa6d100000000,
+ 0xf036a1b200000000, 0x9c5da91700000000, 0xb884ae7400000000,
+ 0xa748142800000000, 0x8391134b00000000, 0xeffa1bee00000000,
+ 0xcb231c8d00000000, 0x762a7a7f00000000, 0x52f37d1c00000000,
+ 0x3e9875b900000000, 0x1a4172da00000000, 0x4b1ce0d600000000,
+ 0x6fc5e7b500000000, 0x03aeef1000000000, 0x2777e87300000000,
+ 0x9a7e8e8100000000, 0xbea789e200000000, 0xd2cc814700000000,
+ 0xf615862400000000, 0xe9d93c7800000000, 0xcd003b1b00000000,
+ 0xa16b33be00000000, 0x85b234dd00000000, 0x38bb522f00000000,
+ 0x1c62554c00000000, 0x70095de900000000, 0x54d05a8a00000000,
+ 0x4e91285000000000, 0x6a482f3300000000, 0x0623279600000000,
+ 0x22fa20f500000000, 0x9ff3460700000000, 0xbb2a416400000000,
+ 0xd74149c100000000, 0xf3984ea200000000, 0xec54f4fe00000000,
+ 0xc88df39d00000000, 0xa4e6fb3800000000, 0x803ffc5b00000000,
+ 0x3d369aa900000000, 0x19ef9dca00000000, 0x7584956f00000000,
+ 0x515d920c00000000, 0xd73eb17600000000, 0xf3e7b61500000000,
+ 0x9f8cbeb000000000, 0xbb55b9d300000000, 0x065cdf2100000000,
+ 0x2285d84200000000, 0x4eeed0e700000000, 0x6a37d78400000000,
+ 0x75fb6dd800000000, 0x51226abb00000000, 0x3d49621e00000000,
+ 0x1990657d00000000, 0xa499038f00000000, 0x804004ec00000000,
+ 0xec2b0c4900000000, 0xc8f20b2a00000000, 0xd2b379f000000000,
+ 0xf66a7e9300000000, 0x9a01763600000000, 0xbed8715500000000,
+ 0x03d117a700000000, 0x270810c400000000, 0x4b63186100000000,
+ 0x6fba1f0200000000, 0x7076a55e00000000, 0x54afa23d00000000,
+ 0x38c4aa9800000000, 0x1c1dadfb00000000, 0xa114cb0900000000,
+ 0x85cdcc6a00000000, 0xe9a6c4cf00000000, 0xcd7fc3ac00000000,
+ 0x9c2251a000000000, 0xb8fb56c300000000, 0xd4905e6600000000,
+ 0xf049590500000000, 0x4d403ff700000000, 0x6999389400000000,
+ 0x05f2303100000000, 0x212b375200000000, 0x3ee78d0e00000000,
+ 0x1a3e8a6d00000000, 0x765582c800000000, 0x528c85ab00000000,
+ 0xef85e35900000000, 0xcb5ce43a00000000, 0xa737ec9f00000000,
+ 0x83eeebfc00000000, 0x99af992600000000, 0xbd769e4500000000,
+ 0xd11d96e000000000, 0xf5c4918300000000, 0x48cdf77100000000,
+ 0x6c14f01200000000, 0x007ff8b700000000, 0x24a6ffd400000000,
+ 0x3b6a458800000000, 0x1fb342eb00000000, 0x73d84a4e00000000,
+ 0x57014d2d00000000, 0xea082bdf00000000, 0xced12cbc00000000,
+ 0xa2ba241900000000, 0x8663237a00000000, 0xae7d62ed00000000,
+ 0x8aa4658e00000000, 0xe6cf6d2b00000000, 0xc2166a4800000000,
+ 0x7f1f0cba00000000, 0x5bc60bd900000000, 0x37ad037c00000000,
+ 0x1374041f00000000, 0x0cb8be4300000000, 0x2861b92000000000,
+ 0x440ab18500000000, 0x60d3b6e600000000, 0xdddad01400000000,
+ 0xf903d77700000000, 0x9568dfd200000000, 0xb1b1d8b100000000,
+ 0xabf0aa6b00000000, 0x8f29ad0800000000, 0xe342a5ad00000000,
+ 0xc79ba2ce00000000, 0x7a92c43c00000000, 0x5e4bc35f00000000,
+ 0x3220cbfa00000000, 0x16f9cc9900000000, 0x093576c500000000,
+ 0x2dec71a600000000, 0x4187790300000000, 0x655e7e6000000000,
+ 0xd857189200000000, 0xfc8e1ff100000000, 0x90e5175400000000,
+ 0xb43c103700000000, 0xe561823b00000000, 0xc1b8855800000000,
+ 0xadd38dfd00000000, 0x890a8a9e00000000, 0x3403ec6c00000000,
+ 0x10daeb0f00000000, 0x7cb1e3aa00000000, 0x5868e4c900000000,
+ 0x47a45e9500000000, 0x637d59f600000000, 0x0f16515300000000,
+ 0x2bcf563000000000, 0x96c630c200000000, 0xb21f37a100000000,
+ 0xde743f0400000000, 0xfaad386700000000, 0xe0ec4abd00000000,
+ 0xc4354dde00000000, 0xa85e457b00000000, 0x8c87421800000000,
+ 0x318e24ea00000000, 0x1557238900000000, 0x793c2b2c00000000,
+ 0x5de52c4f00000000, 0x4229961300000000, 0x66f0917000000000,
+ 0x0a9b99d500000000, 0x2e429eb600000000, 0x934bf84400000000,
+ 0xb792ff2700000000, 0xdbf9f78200000000, 0xff20f0e100000000,
+ 0x7943d39b00000000, 0x5d9ad4f800000000, 0x31f1dc5d00000000,
+ 0x1528db3e00000000, 0xa821bdcc00000000, 0x8cf8baaf00000000,
+ 0xe093b20a00000000, 0xc44ab56900000000, 0xdb860f3500000000,
+ 0xff5f085600000000, 0x933400f300000000, 0xb7ed079000000000,
+ 0x0ae4616200000000, 0x2e3d660100000000, 0x42566ea400000000,
+ 0x668f69c700000000, 0x7cce1b1d00000000, 0x58171c7e00000000,
+ 0x347c14db00000000, 0x10a513b800000000, 0xadac754a00000000,
+ 0x8975722900000000, 0xe51e7a8c00000000, 0xc1c77def00000000,
+ 0xde0bc7b300000000, 0xfad2c0d000000000, 0x96b9c87500000000,
+ 0xb260cf1600000000, 0x0f69a9e400000000, 0x2bb0ae8700000000,
+ 0x47dba62200000000, 0x6302a14100000000, 0x325f334d00000000,
+ 0x1686342e00000000, 0x7aed3c8b00000000, 0x5e343be800000000,
+ 0xe33d5d1a00000000, 0xc7e45a7900000000, 0xab8f52dc00000000,
+ 0x8f5655bf00000000, 0x909aefe300000000, 0xb443e88000000000,
+ 0xd828e02500000000, 0xfcf1e74600000000, 0x41f881b400000000,
+ 0x652186d700000000, 0x094a8e7200000000, 0x2d93891100000000,
+ 0x37d2fbcb00000000, 0x130bfca800000000, 0x7f60f40d00000000,
+ 0x5bb9f36e00000000, 0xe6b0959c00000000, 0xc26992ff00000000,
+ 0xae029a5a00000000, 0x8adb9d3900000000, 0x9517276500000000,
+ 0xb1ce200600000000, 0xdda528a300000000, 0xf97c2fc000000000,
+ 0x4475493200000000, 0x60ac4e5100000000, 0x0cc746f400000000,
+ 0x281e419700000000},
+ {0x0000000000000000, 0x08e3603c00000000, 0x10c6c17800000000,
+ 0x1825a14400000000, 0x208c83f100000000, 0x286fe3cd00000000,
+ 0x304a428900000000, 0x38a922b500000000, 0x011e763800000000,
+ 0x09fd160400000000, 0x11d8b74000000000, 0x193bd77c00000000,
+ 0x2192f5c900000000, 0x297195f500000000, 0x315434b100000000,
+ 0x39b7548d00000000, 0x023cec7000000000, 0x0adf8c4c00000000,
+ 0x12fa2d0800000000, 0x1a194d3400000000, 0x22b06f8100000000,
+ 0x2a530fbd00000000, 0x3276aef900000000, 0x3a95cec500000000,
+ 0x03229a4800000000, 0x0bc1fa7400000000, 0x13e45b3000000000,
+ 0x1b073b0c00000000, 0x23ae19b900000000, 0x2b4d798500000000,
+ 0x3368d8c100000000, 0x3b8bb8fd00000000, 0x0478d8e100000000,
+ 0x0c9bb8dd00000000, 0x14be199900000000, 0x1c5d79a500000000,
+ 0x24f45b1000000000, 0x2c173b2c00000000, 0x34329a6800000000,
+ 0x3cd1fa5400000000, 0x0566aed900000000, 0x0d85cee500000000,
+ 0x15a06fa100000000, 0x1d430f9d00000000, 0x25ea2d2800000000,
+ 0x2d094d1400000000, 0x352cec5000000000, 0x3dcf8c6c00000000,
+ 0x0644349100000000, 0x0ea754ad00000000, 0x1682f5e900000000,
+ 0x1e6195d500000000, 0x26c8b76000000000, 0x2e2bd75c00000000,
+ 0x360e761800000000, 0x3eed162400000000, 0x075a42a900000000,
+ 0x0fb9229500000000, 0x179c83d100000000, 0x1f7fe3ed00000000,
+ 0x27d6c15800000000, 0x2f35a16400000000, 0x3710002000000000,
+ 0x3ff3601c00000000, 0x49f6c11800000000, 0x4115a12400000000,
+ 0x5930006000000000, 0x51d3605c00000000, 0x697a42e900000000,
+ 0x619922d500000000, 0x79bc839100000000, 0x715fe3ad00000000,
+ 0x48e8b72000000000, 0x400bd71c00000000, 0x582e765800000000,
+ 0x50cd166400000000, 0x686434d100000000, 0x608754ed00000000,
+ 0x78a2f5a900000000, 0x7041959500000000, 0x4bca2d6800000000,
+ 0x43294d5400000000, 0x5b0cec1000000000, 0x53ef8c2c00000000,
+ 0x6b46ae9900000000, 0x63a5cea500000000, 0x7b806fe100000000,
+ 0x73630fdd00000000, 0x4ad45b5000000000, 0x42373b6c00000000,
+ 0x5a129a2800000000, 0x52f1fa1400000000, 0x6a58d8a100000000,
+ 0x62bbb89d00000000, 0x7a9e19d900000000, 0x727d79e500000000,
+ 0x4d8e19f900000000, 0x456d79c500000000, 0x5d48d88100000000,
+ 0x55abb8bd00000000, 0x6d029a0800000000, 0x65e1fa3400000000,
+ 0x7dc45b7000000000, 0x75273b4c00000000, 0x4c906fc100000000,
+ 0x44730ffd00000000, 0x5c56aeb900000000, 0x54b5ce8500000000,
+ 0x6c1cec3000000000, 0x64ff8c0c00000000, 0x7cda2d4800000000,
+ 0x74394d7400000000, 0x4fb2f58900000000, 0x475195b500000000,
+ 0x5f7434f100000000, 0x579754cd00000000, 0x6f3e767800000000,
+ 0x67dd164400000000, 0x7ff8b70000000000, 0x771bd73c00000000,
+ 0x4eac83b100000000, 0x464fe38d00000000, 0x5e6a42c900000000,
+ 0x568922f500000000, 0x6e20004000000000, 0x66c3607c00000000,
+ 0x7ee6c13800000000, 0x7605a10400000000, 0x92ec833100000000,
+ 0x9a0fe30d00000000, 0x822a424900000000, 0x8ac9227500000000,
+ 0xb26000c000000000, 0xba8360fc00000000, 0xa2a6c1b800000000,
+ 0xaa45a18400000000, 0x93f2f50900000000, 0x9b11953500000000,
+ 0x8334347100000000, 0x8bd7544d00000000, 0xb37e76f800000000,
+ 0xbb9d16c400000000, 0xa3b8b78000000000, 0xab5bd7bc00000000,
+ 0x90d06f4100000000, 0x98330f7d00000000, 0x8016ae3900000000,
+ 0x88f5ce0500000000, 0xb05cecb000000000, 0xb8bf8c8c00000000,
+ 0xa09a2dc800000000, 0xa8794df400000000, 0x91ce197900000000,
+ 0x992d794500000000, 0x8108d80100000000, 0x89ebb83d00000000,
+ 0xb1429a8800000000, 0xb9a1fab400000000, 0xa1845bf000000000,
+ 0xa9673bcc00000000, 0x96945bd000000000, 0x9e773bec00000000,
+ 0x86529aa800000000, 0x8eb1fa9400000000, 0xb618d82100000000,
+ 0xbefbb81d00000000, 0xa6de195900000000, 0xae3d796500000000,
+ 0x978a2de800000000, 0x9f694dd400000000, 0x874cec9000000000,
+ 0x8faf8cac00000000, 0xb706ae1900000000, 0xbfe5ce2500000000,
+ 0xa7c06f6100000000, 0xaf230f5d00000000, 0x94a8b7a000000000,
+ 0x9c4bd79c00000000, 0x846e76d800000000, 0x8c8d16e400000000,
+ 0xb424345100000000, 0xbcc7546d00000000, 0xa4e2f52900000000,
+ 0xac01951500000000, 0x95b6c19800000000, 0x9d55a1a400000000,
+ 0x857000e000000000, 0x8d9360dc00000000, 0xb53a426900000000,
+ 0xbdd9225500000000, 0xa5fc831100000000, 0xad1fe32d00000000,
+ 0xdb1a422900000000, 0xd3f9221500000000, 0xcbdc835100000000,
+ 0xc33fe36d00000000, 0xfb96c1d800000000, 0xf375a1e400000000,
+ 0xeb5000a000000000, 0xe3b3609c00000000, 0xda04341100000000,
+ 0xd2e7542d00000000, 0xcac2f56900000000, 0xc221955500000000,
+ 0xfa88b7e000000000, 0xf26bd7dc00000000, 0xea4e769800000000,
+ 0xe2ad16a400000000, 0xd926ae5900000000, 0xd1c5ce6500000000,
+ 0xc9e06f2100000000, 0xc1030f1d00000000, 0xf9aa2da800000000,
+ 0xf1494d9400000000, 0xe96cecd000000000, 0xe18f8cec00000000,
+ 0xd838d86100000000, 0xd0dbb85d00000000, 0xc8fe191900000000,
+ 0xc01d792500000000, 0xf8b45b9000000000, 0xf0573bac00000000,
+ 0xe8729ae800000000, 0xe091fad400000000, 0xdf629ac800000000,
+ 0xd781faf400000000, 0xcfa45bb000000000, 0xc7473b8c00000000,
+ 0xffee193900000000, 0xf70d790500000000, 0xef28d84100000000,
+ 0xe7cbb87d00000000, 0xde7cecf000000000, 0xd69f8ccc00000000,
+ 0xceba2d8800000000, 0xc6594db400000000, 0xfef06f0100000000,
+ 0xf6130f3d00000000, 0xee36ae7900000000, 0xe6d5ce4500000000,
+ 0xdd5e76b800000000, 0xd5bd168400000000, 0xcd98b7c000000000,
+ 0xc57bd7fc00000000, 0xfdd2f54900000000, 0xf531957500000000,
+ 0xed14343100000000, 0xe5f7540d00000000, 0xdc40008000000000,
+ 0xd4a360bc00000000, 0xcc86c1f800000000, 0xc465a1c400000000,
+ 0xfccc837100000000, 0xf42fe34d00000000, 0xec0a420900000000,
+ 0xe4e9223500000000},
+ {0x0000000000000000, 0xd1e8e70e00000000, 0xa2d1cf1d00000000,
+ 0x7339281300000000, 0x44a39f3b00000000, 0x954b783500000000,
+ 0xe672502600000000, 0x379ab72800000000, 0x88463f7700000000,
+ 0x59aed87900000000, 0x2a97f06a00000000, 0xfb7f176400000000,
+ 0xcce5a04c00000000, 0x1d0d474200000000, 0x6e346f5100000000,
+ 0xbfdc885f00000000, 0x108d7eee00000000, 0xc16599e000000000,
+ 0xb25cb1f300000000, 0x63b456fd00000000, 0x542ee1d500000000,
+ 0x85c606db00000000, 0xf6ff2ec800000000, 0x2717c9c600000000,
+ 0x98cb419900000000, 0x4923a69700000000, 0x3a1a8e8400000000,
+ 0xebf2698a00000000, 0xdc68dea200000000, 0x0d8039ac00000000,
+ 0x7eb911bf00000000, 0xaf51f6b100000000, 0x611c8c0700000000,
+ 0xb0f46b0900000000, 0xc3cd431a00000000, 0x1225a41400000000,
+ 0x25bf133c00000000, 0xf457f43200000000, 0x876edc2100000000,
+ 0x56863b2f00000000, 0xe95ab37000000000, 0x38b2547e00000000,
+ 0x4b8b7c6d00000000, 0x9a639b6300000000, 0xadf92c4b00000000,
+ 0x7c11cb4500000000, 0x0f28e35600000000, 0xdec0045800000000,
+ 0x7191f2e900000000, 0xa07915e700000000, 0xd3403df400000000,
+ 0x02a8dafa00000000, 0x35326dd200000000, 0xe4da8adc00000000,
+ 0x97e3a2cf00000000, 0x460b45c100000000, 0xf9d7cd9e00000000,
+ 0x283f2a9000000000, 0x5b06028300000000, 0x8aeee58d00000000,
+ 0xbd7452a500000000, 0x6c9cb5ab00000000, 0x1fa59db800000000,
+ 0xce4d7ab600000000, 0xc238180f00000000, 0x13d0ff0100000000,
+ 0x60e9d71200000000, 0xb101301c00000000, 0x869b873400000000,
+ 0x5773603a00000000, 0x244a482900000000, 0xf5a2af2700000000,
+ 0x4a7e277800000000, 0x9b96c07600000000, 0xe8afe86500000000,
+ 0x39470f6b00000000, 0x0eddb84300000000, 0xdf355f4d00000000,
+ 0xac0c775e00000000, 0x7de4905000000000, 0xd2b566e100000000,
+ 0x035d81ef00000000, 0x7064a9fc00000000, 0xa18c4ef200000000,
+ 0x9616f9da00000000, 0x47fe1ed400000000, 0x34c736c700000000,
+ 0xe52fd1c900000000, 0x5af3599600000000, 0x8b1bbe9800000000,
+ 0xf822968b00000000, 0x29ca718500000000, 0x1e50c6ad00000000,
+ 0xcfb821a300000000, 0xbc8109b000000000, 0x6d69eebe00000000,
+ 0xa324940800000000, 0x72cc730600000000, 0x01f55b1500000000,
+ 0xd01dbc1b00000000, 0xe7870b3300000000, 0x366fec3d00000000,
+ 0x4556c42e00000000, 0x94be232000000000, 0x2b62ab7f00000000,
+ 0xfa8a4c7100000000, 0x89b3646200000000, 0x585b836c00000000,
+ 0x6fc1344400000000, 0xbe29d34a00000000, 0xcd10fb5900000000,
+ 0x1cf81c5700000000, 0xb3a9eae600000000, 0x62410de800000000,
+ 0x117825fb00000000, 0xc090c2f500000000, 0xf70a75dd00000000,
+ 0x26e292d300000000, 0x55dbbac000000000, 0x84335dce00000000,
+ 0x3befd59100000000, 0xea07329f00000000, 0x993e1a8c00000000,
+ 0x48d6fd8200000000, 0x7f4c4aaa00000000, 0xaea4ada400000000,
+ 0xdd9d85b700000000, 0x0c7562b900000000, 0x8471301e00000000,
+ 0x5599d71000000000, 0x26a0ff0300000000, 0xf748180d00000000,
+ 0xc0d2af2500000000, 0x113a482b00000000, 0x6203603800000000,
+ 0xb3eb873600000000, 0x0c370f6900000000, 0xdddfe86700000000,
+ 0xaee6c07400000000, 0x7f0e277a00000000, 0x4894905200000000,
+ 0x997c775c00000000, 0xea455f4f00000000, 0x3badb84100000000,
+ 0x94fc4ef000000000, 0x4514a9fe00000000, 0x362d81ed00000000,
+ 0xe7c566e300000000, 0xd05fd1cb00000000, 0x01b736c500000000,
+ 0x728e1ed600000000, 0xa366f9d800000000, 0x1cba718700000000,
+ 0xcd52968900000000, 0xbe6bbe9a00000000, 0x6f83599400000000,
+ 0x5819eebc00000000, 0x89f109b200000000, 0xfac821a100000000,
+ 0x2b20c6af00000000, 0xe56dbc1900000000, 0x34855b1700000000,
+ 0x47bc730400000000, 0x9654940a00000000, 0xa1ce232200000000,
+ 0x7026c42c00000000, 0x031fec3f00000000, 0xd2f70b3100000000,
+ 0x6d2b836e00000000, 0xbcc3646000000000, 0xcffa4c7300000000,
+ 0x1e12ab7d00000000, 0x29881c5500000000, 0xf860fb5b00000000,
+ 0x8b59d34800000000, 0x5ab1344600000000, 0xf5e0c2f700000000,
+ 0x240825f900000000, 0x57310dea00000000, 0x86d9eae400000000,
+ 0xb1435dcc00000000, 0x60abbac200000000, 0x139292d100000000,
+ 0xc27a75df00000000, 0x7da6fd8000000000, 0xac4e1a8e00000000,
+ 0xdf77329d00000000, 0x0e9fd59300000000, 0x390562bb00000000,
+ 0xe8ed85b500000000, 0x9bd4ada600000000, 0x4a3c4aa800000000,
+ 0x4649281100000000, 0x97a1cf1f00000000, 0xe498e70c00000000,
+ 0x3570000200000000, 0x02eab72a00000000, 0xd302502400000000,
+ 0xa03b783700000000, 0x71d39f3900000000, 0xce0f176600000000,
+ 0x1fe7f06800000000, 0x6cded87b00000000, 0xbd363f7500000000,
+ 0x8aac885d00000000, 0x5b446f5300000000, 0x287d474000000000,
+ 0xf995a04e00000000, 0x56c456ff00000000, 0x872cb1f100000000,
+ 0xf41599e200000000, 0x25fd7eec00000000, 0x1267c9c400000000,
+ 0xc38f2eca00000000, 0xb0b606d900000000, 0x615ee1d700000000,
+ 0xde82698800000000, 0x0f6a8e8600000000, 0x7c53a69500000000,
+ 0xadbb419b00000000, 0x9a21f6b300000000, 0x4bc911bd00000000,
+ 0x38f039ae00000000, 0xe918dea000000000, 0x2755a41600000000,
+ 0xf6bd431800000000, 0x85846b0b00000000, 0x546c8c0500000000,
+ 0x63f63b2d00000000, 0xb21edc2300000000, 0xc127f43000000000,
+ 0x10cf133e00000000, 0xaf139b6100000000, 0x7efb7c6f00000000,
+ 0x0dc2547c00000000, 0xdc2ab37200000000, 0xebb0045a00000000,
+ 0x3a58e35400000000, 0x4961cb4700000000, 0x98892c4900000000,
+ 0x37d8daf800000000, 0xe6303df600000000, 0x950915e500000000,
+ 0x44e1f2eb00000000, 0x737b45c300000000, 0xa293a2cd00000000,
+ 0xd1aa8ade00000000, 0x00426dd000000000, 0xbf9ee58f00000000,
+ 0x6e76028100000000, 0x1d4f2a9200000000, 0xcca7cd9c00000000,
+ 0xfb3d7ab400000000, 0x2ad59dba00000000, 0x59ecb5a900000000,
+ 0x880452a700000000},
+ {0x0000000000000000, 0xaa05daf100000000, 0x150dc53800000000,
+ 0xbf081fc900000000, 0x2a1a8a7100000000, 0x801f508000000000,
+ 0x3f174f4900000000, 0x951295b800000000, 0x543414e300000000,
+ 0xfe31ce1200000000, 0x4139d1db00000000, 0xeb3c0b2a00000000,
+ 0x7e2e9e9200000000, 0xd42b446300000000, 0x6b235baa00000000,
+ 0xc126815b00000000, 0xe96e591d00000000, 0x436b83ec00000000,
+ 0xfc639c2500000000, 0x566646d400000000, 0xc374d36c00000000,
+ 0x6971099d00000000, 0xd679165400000000, 0x7c7ccca500000000,
+ 0xbd5a4dfe00000000, 0x175f970f00000000, 0xa85788c600000000,
+ 0x0252523700000000, 0x9740c78f00000000, 0x3d451d7e00000000,
+ 0x824d02b700000000, 0x2848d84600000000, 0xd2ddb23a00000000,
+ 0x78d868cb00000000, 0xc7d0770200000000, 0x6dd5adf300000000,
+ 0xf8c7384b00000000, 0x52c2e2ba00000000, 0xedcafd7300000000,
+ 0x47cf278200000000, 0x86e9a6d900000000, 0x2cec7c2800000000,
+ 0x93e463e100000000, 0x39e1b91000000000, 0xacf32ca800000000,
+ 0x06f6f65900000000, 0xb9fee99000000000, 0x13fb336100000000,
+ 0x3bb3eb2700000000, 0x91b631d600000000, 0x2ebe2e1f00000000,
+ 0x84bbf4ee00000000, 0x11a9615600000000, 0xbbacbba700000000,
+ 0x04a4a46e00000000, 0xaea17e9f00000000, 0x6f87ffc400000000,
+ 0xc582253500000000, 0x7a8a3afc00000000, 0xd08fe00d00000000,
+ 0x459d75b500000000, 0xef98af4400000000, 0x5090b08d00000000,
+ 0xfa956a7c00000000, 0xa4bb657500000000, 0x0ebebf8400000000,
+ 0xb1b6a04d00000000, 0x1bb37abc00000000, 0x8ea1ef0400000000,
+ 0x24a435f500000000, 0x9bac2a3c00000000, 0x31a9f0cd00000000,
+ 0xf08f719600000000, 0x5a8aab6700000000, 0xe582b4ae00000000,
+ 0x4f876e5f00000000, 0xda95fbe700000000, 0x7090211600000000,
+ 0xcf983edf00000000, 0x659de42e00000000, 0x4dd53c6800000000,
+ 0xe7d0e69900000000, 0x58d8f95000000000, 0xf2dd23a100000000,
+ 0x67cfb61900000000, 0xcdca6ce800000000, 0x72c2732100000000,
+ 0xd8c7a9d000000000, 0x19e1288b00000000, 0xb3e4f27a00000000,
+ 0x0cecedb300000000, 0xa6e9374200000000, 0x33fba2fa00000000,
+ 0x99fe780b00000000, 0x26f667c200000000, 0x8cf3bd3300000000,
+ 0x7666d74f00000000, 0xdc630dbe00000000, 0x636b127700000000,
+ 0xc96ec88600000000, 0x5c7c5d3e00000000, 0xf67987cf00000000,
+ 0x4971980600000000, 0xe37442f700000000, 0x2252c3ac00000000,
+ 0x8857195d00000000, 0x375f069400000000, 0x9d5adc6500000000,
+ 0x084849dd00000000, 0xa24d932c00000000, 0x1d458ce500000000,
+ 0xb740561400000000, 0x9f088e5200000000, 0x350d54a300000000,
+ 0x8a054b6a00000000, 0x2000919b00000000, 0xb512042300000000,
+ 0x1f17ded200000000, 0xa01fc11b00000000, 0x0a1a1bea00000000,
+ 0xcb3c9ab100000000, 0x6139404000000000, 0xde315f8900000000,
+ 0x7434857800000000, 0xe12610c000000000, 0x4b23ca3100000000,
+ 0xf42bd5f800000000, 0x5e2e0f0900000000, 0x4877cbea00000000,
+ 0xe272111b00000000, 0x5d7a0ed200000000, 0xf77fd42300000000,
+ 0x626d419b00000000, 0xc8689b6a00000000, 0x776084a300000000,
+ 0xdd655e5200000000, 0x1c43df0900000000, 0xb64605f800000000,
+ 0x094e1a3100000000, 0xa34bc0c000000000, 0x3659557800000000,
+ 0x9c5c8f8900000000, 0x2354904000000000, 0x89514ab100000000,
+ 0xa11992f700000000, 0x0b1c480600000000, 0xb41457cf00000000,
+ 0x1e118d3e00000000, 0x8b03188600000000, 0x2106c27700000000,
+ 0x9e0eddbe00000000, 0x340b074f00000000, 0xf52d861400000000,
+ 0x5f285ce500000000, 0xe020432c00000000, 0x4a2599dd00000000,
+ 0xdf370c6500000000, 0x7532d69400000000, 0xca3ac95d00000000,
+ 0x603f13ac00000000, 0x9aaa79d000000000, 0x30afa32100000000,
+ 0x8fa7bce800000000, 0x25a2661900000000, 0xb0b0f3a100000000,
+ 0x1ab5295000000000, 0xa5bd369900000000, 0x0fb8ec6800000000,
+ 0xce9e6d3300000000, 0x649bb7c200000000, 0xdb93a80b00000000,
+ 0x719672fa00000000, 0xe484e74200000000, 0x4e813db300000000,
+ 0xf189227a00000000, 0x5b8cf88b00000000, 0x73c420cd00000000,
+ 0xd9c1fa3c00000000, 0x66c9e5f500000000, 0xcccc3f0400000000,
+ 0x59deaabc00000000, 0xf3db704d00000000, 0x4cd36f8400000000,
+ 0xe6d6b57500000000, 0x27f0342e00000000, 0x8df5eedf00000000,
+ 0x32fdf11600000000, 0x98f82be700000000, 0x0deabe5f00000000,
+ 0xa7ef64ae00000000, 0x18e77b6700000000, 0xb2e2a19600000000,
+ 0xecccae9f00000000, 0x46c9746e00000000, 0xf9c16ba700000000,
+ 0x53c4b15600000000, 0xc6d624ee00000000, 0x6cd3fe1f00000000,
+ 0xd3dbe1d600000000, 0x79de3b2700000000, 0xb8f8ba7c00000000,
+ 0x12fd608d00000000, 0xadf57f4400000000, 0x07f0a5b500000000,
+ 0x92e2300d00000000, 0x38e7eafc00000000, 0x87eff53500000000,
+ 0x2dea2fc400000000, 0x05a2f78200000000, 0xafa72d7300000000,
+ 0x10af32ba00000000, 0xbaaae84b00000000, 0x2fb87df300000000,
+ 0x85bda70200000000, 0x3ab5b8cb00000000, 0x90b0623a00000000,
+ 0x5196e36100000000, 0xfb93399000000000, 0x449b265900000000,
+ 0xee9efca800000000, 0x7b8c691000000000, 0xd189b3e100000000,
+ 0x6e81ac2800000000, 0xc48476d900000000, 0x3e111ca500000000,
+ 0x9414c65400000000, 0x2b1cd99d00000000, 0x8119036c00000000,
+ 0x140b96d400000000, 0xbe0e4c2500000000, 0x010653ec00000000,
+ 0xab03891d00000000, 0x6a25084600000000, 0xc020d2b700000000,
+ 0x7f28cd7e00000000, 0xd52d178f00000000, 0x403f823700000000,
+ 0xea3a58c600000000, 0x5532470f00000000, 0xff379dfe00000000,
+ 0xd77f45b800000000, 0x7d7a9f4900000000, 0xc272808000000000,
+ 0x68775a7100000000, 0xfd65cfc900000000, 0x5760153800000000,
+ 0xe8680af100000000, 0x426dd00000000000, 0x834b515b00000000,
+ 0x294e8baa00000000, 0x9646946300000000, 0x3c434e9200000000,
+ 0xa951db2a00000000, 0x035401db00000000, 0xbc5c1e1200000000,
+ 0x1659c4e300000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xae689191, 0x87a02563, 0x29c8b4f2, 0xd4314c87,
+ 0x7a59dd16, 0x539169e4, 0xfdf9f875, 0x73139f4f, 0xdd7b0ede,
+ 0xf4b3ba2c, 0x5adb2bbd, 0xa722d3c8, 0x094a4259, 0x2082f6ab,
+ 0x8eea673a, 0xe6273e9e, 0x484faf0f, 0x61871bfd, 0xcfef8a6c,
+ 0x32167219, 0x9c7ee388, 0xb5b6577a, 0x1bdec6eb, 0x9534a1d1,
+ 0x3b5c3040, 0x129484b2, 0xbcfc1523, 0x4105ed56, 0xef6d7cc7,
+ 0xc6a5c835, 0x68cd59a4, 0x173f7b7d, 0xb957eaec, 0x909f5e1e,
+ 0x3ef7cf8f, 0xc30e37fa, 0x6d66a66b, 0x44ae1299, 0xeac68308,
+ 0x642ce432, 0xca4475a3, 0xe38cc151, 0x4de450c0, 0xb01da8b5,
+ 0x1e753924, 0x37bd8dd6, 0x99d51c47, 0xf11845e3, 0x5f70d472,
+ 0x76b86080, 0xd8d0f111, 0x25290964, 0x8b4198f5, 0xa2892c07,
+ 0x0ce1bd96, 0x820bdaac, 0x2c634b3d, 0x05abffcf, 0xabc36e5e,
+ 0x563a962b, 0xf85207ba, 0xd19ab348, 0x7ff222d9, 0x2e7ef6fa,
+ 0x8016676b, 0xa9ded399, 0x07b64208, 0xfa4fba7d, 0x54272bec,
+ 0x7def9f1e, 0xd3870e8f, 0x5d6d69b5, 0xf305f824, 0xdacd4cd6,
+ 0x74a5dd47, 0x895c2532, 0x2734b4a3, 0x0efc0051, 0xa09491c0,
+ 0xc859c864, 0x663159f5, 0x4ff9ed07, 0xe1917c96, 0x1c6884e3,
+ 0xb2001572, 0x9bc8a180, 0x35a03011, 0xbb4a572b, 0x1522c6ba,
+ 0x3cea7248, 0x9282e3d9, 0x6f7b1bac, 0xc1138a3d, 0xe8db3ecf,
+ 0x46b3af5e, 0x39418d87, 0x97291c16, 0xbee1a8e4, 0x10893975,
+ 0xed70c100, 0x43185091, 0x6ad0e463, 0xc4b875f2, 0x4a5212c8,
+ 0xe43a8359, 0xcdf237ab, 0x639aa63a, 0x9e635e4f, 0x300bcfde,
+ 0x19c37b2c, 0xb7abeabd, 0xdf66b319, 0x710e2288, 0x58c6967a,
+ 0xf6ae07eb, 0x0b57ff9e, 0xa53f6e0f, 0x8cf7dafd, 0x229f4b6c,
+ 0xac752c56, 0x021dbdc7, 0x2bd50935, 0x85bd98a4, 0x784460d1,
+ 0xd62cf140, 0xffe445b2, 0x518cd423, 0x5cfdedf4, 0xf2957c65,
+ 0xdb5dc897, 0x75355906, 0x88cca173, 0x26a430e2, 0x0f6c8410,
+ 0xa1041581, 0x2fee72bb, 0x8186e32a, 0xa84e57d8, 0x0626c649,
+ 0xfbdf3e3c, 0x55b7afad, 0x7c7f1b5f, 0xd2178ace, 0xbadad36a,
+ 0x14b242fb, 0x3d7af609, 0x93126798, 0x6eeb9fed, 0xc0830e7c,
+ 0xe94bba8e, 0x47232b1f, 0xc9c94c25, 0x67a1ddb4, 0x4e696946,
+ 0xe001f8d7, 0x1df800a2, 0xb3909133, 0x9a5825c1, 0x3430b450,
+ 0x4bc29689, 0xe5aa0718, 0xcc62b3ea, 0x620a227b, 0x9ff3da0e,
+ 0x319b4b9f, 0x1853ff6d, 0xb63b6efc, 0x38d109c6, 0x96b99857,
+ 0xbf712ca5, 0x1119bd34, 0xece04541, 0x4288d4d0, 0x6b406022,
+ 0xc528f1b3, 0xade5a817, 0x038d3986, 0x2a458d74, 0x842d1ce5,
+ 0x79d4e490, 0xd7bc7501, 0xfe74c1f3, 0x501c5062, 0xdef63758,
+ 0x709ea6c9, 0x5956123b, 0xf73e83aa, 0x0ac77bdf, 0xa4afea4e,
+ 0x8d675ebc, 0x230fcf2d, 0x72831b0e, 0xdceb8a9f, 0xf5233e6d,
+ 0x5b4baffc, 0xa6b25789, 0x08dac618, 0x211272ea, 0x8f7ae37b,
+ 0x01908441, 0xaff815d0, 0x8630a122, 0x285830b3, 0xd5a1c8c6,
+ 0x7bc95957, 0x5201eda5, 0xfc697c34, 0x94a42590, 0x3accb401,
+ 0x130400f3, 0xbd6c9162, 0x40956917, 0xeefdf886, 0xc7354c74,
+ 0x695ddde5, 0xe7b7badf, 0x49df2b4e, 0x60179fbc, 0xce7f0e2d,
+ 0x3386f658, 0x9dee67c9, 0xb426d33b, 0x1a4e42aa, 0x65bc6073,
+ 0xcbd4f1e2, 0xe21c4510, 0x4c74d481, 0xb18d2cf4, 0x1fe5bd65,
+ 0x362d0997, 0x98459806, 0x16afff3c, 0xb8c76ead, 0x910fda5f,
+ 0x3f674bce, 0xc29eb3bb, 0x6cf6222a, 0x453e96d8, 0xeb560749,
+ 0x839b5eed, 0x2df3cf7c, 0x043b7b8e, 0xaa53ea1f, 0x57aa126a,
+ 0xf9c283fb, 0xd00a3709, 0x7e62a698, 0xf088c1a2, 0x5ee05033,
+ 0x7728e4c1, 0xd9407550, 0x24b98d25, 0x8ad11cb4, 0xa319a846,
+ 0x0d7139d7},
+ {0x00000000, 0xb9fbdbe8, 0xa886b191, 0x117d6a79, 0x8a7c6563,
+ 0x3387be8b, 0x22fad4f2, 0x9b010f1a, 0xcf89cc87, 0x7672176f,
+ 0x670f7d16, 0xdef4a6fe, 0x45f5a9e4, 0xfc0e720c, 0xed731875,
+ 0x5488c39d, 0x44629f4f, 0xfd9944a7, 0xece42ede, 0x551ff536,
+ 0xce1efa2c, 0x77e521c4, 0x66984bbd, 0xdf639055, 0x8beb53c8,
+ 0x32108820, 0x236de259, 0x9a9639b1, 0x019736ab, 0xb86ced43,
+ 0xa911873a, 0x10ea5cd2, 0x88c53e9e, 0x313ee576, 0x20438f0f,
+ 0x99b854e7, 0x02b95bfd, 0xbb428015, 0xaa3fea6c, 0x13c43184,
+ 0x474cf219, 0xfeb729f1, 0xefca4388, 0x56319860, 0xcd30977a,
+ 0x74cb4c92, 0x65b626eb, 0xdc4dfd03, 0xcca7a1d1, 0x755c7a39,
+ 0x64211040, 0xdddacba8, 0x46dbc4b2, 0xff201f5a, 0xee5d7523,
+ 0x57a6aecb, 0x032e6d56, 0xbad5b6be, 0xaba8dcc7, 0x1253072f,
+ 0x89520835, 0x30a9d3dd, 0x21d4b9a4, 0x982f624c, 0xcafb7b7d,
+ 0x7300a095, 0x627dcaec, 0xdb861104, 0x40871e1e, 0xf97cc5f6,
+ 0xe801af8f, 0x51fa7467, 0x0572b7fa, 0xbc896c12, 0xadf4066b,
+ 0x140fdd83, 0x8f0ed299, 0x36f50971, 0x27886308, 0x9e73b8e0,
+ 0x8e99e432, 0x37623fda, 0x261f55a3, 0x9fe48e4b, 0x04e58151,
+ 0xbd1e5ab9, 0xac6330c0, 0x1598eb28, 0x411028b5, 0xf8ebf35d,
+ 0xe9969924, 0x506d42cc, 0xcb6c4dd6, 0x7297963e, 0x63eafc47,
+ 0xda1127af, 0x423e45e3, 0xfbc59e0b, 0xeab8f472, 0x53432f9a,
+ 0xc8422080, 0x71b9fb68, 0x60c49111, 0xd93f4af9, 0x8db78964,
+ 0x344c528c, 0x253138f5, 0x9ccae31d, 0x07cbec07, 0xbe3037ef,
+ 0xaf4d5d96, 0x16b6867e, 0x065cdaac, 0xbfa70144, 0xaeda6b3d,
+ 0x1721b0d5, 0x8c20bfcf, 0x35db6427, 0x24a60e5e, 0x9d5dd5b6,
+ 0xc9d5162b, 0x702ecdc3, 0x6153a7ba, 0xd8a87c52, 0x43a97348,
+ 0xfa52a8a0, 0xeb2fc2d9, 0x52d41931, 0x4e87f0bb, 0xf77c2b53,
+ 0xe601412a, 0x5ffa9ac2, 0xc4fb95d8, 0x7d004e30, 0x6c7d2449,
+ 0xd586ffa1, 0x810e3c3c, 0x38f5e7d4, 0x29888dad, 0x90735645,
+ 0x0b72595f, 0xb28982b7, 0xa3f4e8ce, 0x1a0f3326, 0x0ae56ff4,
+ 0xb31eb41c, 0xa263de65, 0x1b98058d, 0x80990a97, 0x3962d17f,
+ 0x281fbb06, 0x91e460ee, 0xc56ca373, 0x7c97789b, 0x6dea12e2,
+ 0xd411c90a, 0x4f10c610, 0xf6eb1df8, 0xe7967781, 0x5e6dac69,
+ 0xc642ce25, 0x7fb915cd, 0x6ec47fb4, 0xd73fa45c, 0x4c3eab46,
+ 0xf5c570ae, 0xe4b81ad7, 0x5d43c13f, 0x09cb02a2, 0xb030d94a,
+ 0xa14db333, 0x18b668db, 0x83b767c1, 0x3a4cbc29, 0x2b31d650,
+ 0x92ca0db8, 0x8220516a, 0x3bdb8a82, 0x2aa6e0fb, 0x935d3b13,
+ 0x085c3409, 0xb1a7efe1, 0xa0da8598, 0x19215e70, 0x4da99ded,
+ 0xf4524605, 0xe52f2c7c, 0x5cd4f794, 0xc7d5f88e, 0x7e2e2366,
+ 0x6f53491f, 0xd6a892f7, 0x847c8bc6, 0x3d87502e, 0x2cfa3a57,
+ 0x9501e1bf, 0x0e00eea5, 0xb7fb354d, 0xa6865f34, 0x1f7d84dc,
+ 0x4bf54741, 0xf20e9ca9, 0xe373f6d0, 0x5a882d38, 0xc1892222,
+ 0x7872f9ca, 0x690f93b3, 0xd0f4485b, 0xc01e1489, 0x79e5cf61,
+ 0x6898a518, 0xd1637ef0, 0x4a6271ea, 0xf399aa02, 0xe2e4c07b,
+ 0x5b1f1b93, 0x0f97d80e, 0xb66c03e6, 0xa711699f, 0x1eeab277,
+ 0x85ebbd6d, 0x3c106685, 0x2d6d0cfc, 0x9496d714, 0x0cb9b558,
+ 0xb5426eb0, 0xa43f04c9, 0x1dc4df21, 0x86c5d03b, 0x3f3e0bd3,
+ 0x2e4361aa, 0x97b8ba42, 0xc33079df, 0x7acba237, 0x6bb6c84e,
+ 0xd24d13a6, 0x494c1cbc, 0xf0b7c754, 0xe1caad2d, 0x583176c5,
+ 0x48db2a17, 0xf120f1ff, 0xe05d9b86, 0x59a6406e, 0xc2a74f74,
+ 0x7b5c949c, 0x6a21fee5, 0xd3da250d, 0x8752e690, 0x3ea93d78,
+ 0x2fd45701, 0x962f8ce9, 0x0d2e83f3, 0xb4d5581b, 0xa5a83262,
+ 0x1c53e98a},
+ {0x00000000, 0x9d0fe176, 0xe16ec4ad, 0x7c6125db, 0x19ac8f1b,
+ 0x84a36e6d, 0xf8c24bb6, 0x65cdaac0, 0x33591e36, 0xae56ff40,
+ 0xd237da9b, 0x4f383bed, 0x2af5912d, 0xb7fa705b, 0xcb9b5580,
+ 0x5694b4f6, 0x66b23c6c, 0xfbbddd1a, 0x87dcf8c1, 0x1ad319b7,
+ 0x7f1eb377, 0xe2115201, 0x9e7077da, 0x037f96ac, 0x55eb225a,
+ 0xc8e4c32c, 0xb485e6f7, 0x298a0781, 0x4c47ad41, 0xd1484c37,
+ 0xad2969ec, 0x3026889a, 0xcd6478d8, 0x506b99ae, 0x2c0abc75,
+ 0xb1055d03, 0xd4c8f7c3, 0x49c716b5, 0x35a6336e, 0xa8a9d218,
+ 0xfe3d66ee, 0x63328798, 0x1f53a243, 0x825c4335, 0xe791e9f5,
+ 0x7a9e0883, 0x06ff2d58, 0x9bf0cc2e, 0xabd644b4, 0x36d9a5c2,
+ 0x4ab88019, 0xd7b7616f, 0xb27acbaf, 0x2f752ad9, 0x53140f02,
+ 0xce1bee74, 0x988f5a82, 0x0580bbf4, 0x79e19e2f, 0xe4ee7f59,
+ 0x8123d599, 0x1c2c34ef, 0x604d1134, 0xfd42f042, 0x41b9f7f1,
+ 0xdcb61687, 0xa0d7335c, 0x3dd8d22a, 0x581578ea, 0xc51a999c,
+ 0xb97bbc47, 0x24745d31, 0x72e0e9c7, 0xefef08b1, 0x938e2d6a,
+ 0x0e81cc1c, 0x6b4c66dc, 0xf64387aa, 0x8a22a271, 0x172d4307,
+ 0x270bcb9d, 0xba042aeb, 0xc6650f30, 0x5b6aee46, 0x3ea74486,
+ 0xa3a8a5f0, 0xdfc9802b, 0x42c6615d, 0x1452d5ab, 0x895d34dd,
+ 0xf53c1106, 0x6833f070, 0x0dfe5ab0, 0x90f1bbc6, 0xec909e1d,
+ 0x719f7f6b, 0x8cdd8f29, 0x11d26e5f, 0x6db34b84, 0xf0bcaaf2,
+ 0x95710032, 0x087ee144, 0x741fc49f, 0xe91025e9, 0xbf84911f,
+ 0x228b7069, 0x5eea55b2, 0xc3e5b4c4, 0xa6281e04, 0x3b27ff72,
+ 0x4746daa9, 0xda493bdf, 0xea6fb345, 0x77605233, 0x0b0177e8,
+ 0x960e969e, 0xf3c33c5e, 0x6eccdd28, 0x12adf8f3, 0x8fa21985,
+ 0xd936ad73, 0x44394c05, 0x385869de, 0xa55788a8, 0xc09a2268,
+ 0x5d95c31e, 0x21f4e6c5, 0xbcfb07b3, 0x8373efe2, 0x1e7c0e94,
+ 0x621d2b4f, 0xff12ca39, 0x9adf60f9, 0x07d0818f, 0x7bb1a454,
+ 0xe6be4522, 0xb02af1d4, 0x2d2510a2, 0x51443579, 0xcc4bd40f,
+ 0xa9867ecf, 0x34899fb9, 0x48e8ba62, 0xd5e75b14, 0xe5c1d38e,
+ 0x78ce32f8, 0x04af1723, 0x99a0f655, 0xfc6d5c95, 0x6162bde3,
+ 0x1d039838, 0x800c794e, 0xd698cdb8, 0x4b972cce, 0x37f60915,
+ 0xaaf9e863, 0xcf3442a3, 0x523ba3d5, 0x2e5a860e, 0xb3556778,
+ 0x4e17973a, 0xd318764c, 0xaf795397, 0x3276b2e1, 0x57bb1821,
+ 0xcab4f957, 0xb6d5dc8c, 0x2bda3dfa, 0x7d4e890c, 0xe041687a,
+ 0x9c204da1, 0x012facd7, 0x64e20617, 0xf9ede761, 0x858cc2ba,
+ 0x188323cc, 0x28a5ab56, 0xb5aa4a20, 0xc9cb6ffb, 0x54c48e8d,
+ 0x3109244d, 0xac06c53b, 0xd067e0e0, 0x4d680196, 0x1bfcb560,
+ 0x86f35416, 0xfa9271cd, 0x679d90bb, 0x02503a7b, 0x9f5fdb0d,
+ 0xe33efed6, 0x7e311fa0, 0xc2ca1813, 0x5fc5f965, 0x23a4dcbe,
+ 0xbeab3dc8, 0xdb669708, 0x4669767e, 0x3a0853a5, 0xa707b2d3,
+ 0xf1930625, 0x6c9ce753, 0x10fdc288, 0x8df223fe, 0xe83f893e,
+ 0x75306848, 0x09514d93, 0x945eace5, 0xa478247f, 0x3977c509,
+ 0x4516e0d2, 0xd81901a4, 0xbdd4ab64, 0x20db4a12, 0x5cba6fc9,
+ 0xc1b58ebf, 0x97213a49, 0x0a2edb3f, 0x764ffee4, 0xeb401f92,
+ 0x8e8db552, 0x13825424, 0x6fe371ff, 0xf2ec9089, 0x0fae60cb,
+ 0x92a181bd, 0xeec0a466, 0x73cf4510, 0x1602efd0, 0x8b0d0ea6,
+ 0xf76c2b7d, 0x6a63ca0b, 0x3cf77efd, 0xa1f89f8b, 0xdd99ba50,
+ 0x40965b26, 0x255bf1e6, 0xb8541090, 0xc435354b, 0x593ad43d,
+ 0x691c5ca7, 0xf413bdd1, 0x8872980a, 0x157d797c, 0x70b0d3bc,
+ 0xedbf32ca, 0x91de1711, 0x0cd1f667, 0x5a454291, 0xc74aa3e7,
+ 0xbb2b863c, 0x2624674a, 0x43e9cd8a, 0xdee62cfc, 0xa2870927,
+ 0x3f88e851},
+ {0x00000000, 0xdd96d985, 0x605cb54b, 0xbdca6cce, 0xc0b96a96,
+ 0x1d2fb313, 0xa0e5dfdd, 0x7d730658, 0x5a03d36d, 0x87950ae8,
+ 0x3a5f6626, 0xe7c9bfa3, 0x9abab9fb, 0x472c607e, 0xfae60cb0,
+ 0x2770d535, 0xb407a6da, 0x69917f5f, 0xd45b1391, 0x09cdca14,
+ 0x74becc4c, 0xa92815c9, 0x14e27907, 0xc974a082, 0xee0475b7,
+ 0x3392ac32, 0x8e58c0fc, 0x53ce1979, 0x2ebd1f21, 0xf32bc6a4,
+ 0x4ee1aa6a, 0x937773ef, 0xb37e4bf5, 0x6ee89270, 0xd322febe,
+ 0x0eb4273b, 0x73c72163, 0xae51f8e6, 0x139b9428, 0xce0d4dad,
+ 0xe97d9898, 0x34eb411d, 0x89212dd3, 0x54b7f456, 0x29c4f20e,
+ 0xf4522b8b, 0x49984745, 0x940e9ec0, 0x0779ed2f, 0xdaef34aa,
+ 0x67255864, 0xbab381e1, 0xc7c087b9, 0x1a565e3c, 0xa79c32f2,
+ 0x7a0aeb77, 0x5d7a3e42, 0x80ece7c7, 0x3d268b09, 0xe0b0528c,
+ 0x9dc354d4, 0x40558d51, 0xfd9fe19f, 0x2009381a, 0xbd8d91ab,
+ 0x601b482e, 0xddd124e0, 0x0047fd65, 0x7d34fb3d, 0xa0a222b8,
+ 0x1d684e76, 0xc0fe97f3, 0xe78e42c6, 0x3a189b43, 0x87d2f78d,
+ 0x5a442e08, 0x27372850, 0xfaa1f1d5, 0x476b9d1b, 0x9afd449e,
+ 0x098a3771, 0xd41ceef4, 0x69d6823a, 0xb4405bbf, 0xc9335de7,
+ 0x14a58462, 0xa96fe8ac, 0x74f93129, 0x5389e41c, 0x8e1f3d99,
+ 0x33d55157, 0xee4388d2, 0x93308e8a, 0x4ea6570f, 0xf36c3bc1,
+ 0x2efae244, 0x0ef3da5e, 0xd36503db, 0x6eaf6f15, 0xb339b690,
+ 0xce4ab0c8, 0x13dc694d, 0xae160583, 0x7380dc06, 0x54f00933,
+ 0x8966d0b6, 0x34acbc78, 0xe93a65fd, 0x944963a5, 0x49dfba20,
+ 0xf415d6ee, 0x29830f6b, 0xbaf47c84, 0x6762a501, 0xdaa8c9cf,
+ 0x073e104a, 0x7a4d1612, 0xa7dbcf97, 0x1a11a359, 0xc7877adc,
+ 0xe0f7afe9, 0x3d61766c, 0x80ab1aa2, 0x5d3dc327, 0x204ec57f,
+ 0xfdd81cfa, 0x40127034, 0x9d84a9b1, 0xa06a2517, 0x7dfcfc92,
+ 0xc036905c, 0x1da049d9, 0x60d34f81, 0xbd459604, 0x008ffaca,
+ 0xdd19234f, 0xfa69f67a, 0x27ff2fff, 0x9a354331, 0x47a39ab4,
+ 0x3ad09cec, 0xe7464569, 0x5a8c29a7, 0x871af022, 0x146d83cd,
+ 0xc9fb5a48, 0x74313686, 0xa9a7ef03, 0xd4d4e95b, 0x094230de,
+ 0xb4885c10, 0x691e8595, 0x4e6e50a0, 0x93f88925, 0x2e32e5eb,
+ 0xf3a43c6e, 0x8ed73a36, 0x5341e3b3, 0xee8b8f7d, 0x331d56f8,
+ 0x13146ee2, 0xce82b767, 0x7348dba9, 0xaede022c, 0xd3ad0474,
+ 0x0e3bddf1, 0xb3f1b13f, 0x6e6768ba, 0x4917bd8f, 0x9481640a,
+ 0x294b08c4, 0xf4ddd141, 0x89aed719, 0x54380e9c, 0xe9f26252,
+ 0x3464bbd7, 0xa713c838, 0x7a8511bd, 0xc74f7d73, 0x1ad9a4f6,
+ 0x67aaa2ae, 0xba3c7b2b, 0x07f617e5, 0xda60ce60, 0xfd101b55,
+ 0x2086c2d0, 0x9d4cae1e, 0x40da779b, 0x3da971c3, 0xe03fa846,
+ 0x5df5c488, 0x80631d0d, 0x1de7b4bc, 0xc0716d39, 0x7dbb01f7,
+ 0xa02dd872, 0xdd5ede2a, 0x00c807af, 0xbd026b61, 0x6094b2e4,
+ 0x47e467d1, 0x9a72be54, 0x27b8d29a, 0xfa2e0b1f, 0x875d0d47,
+ 0x5acbd4c2, 0xe701b80c, 0x3a976189, 0xa9e01266, 0x7476cbe3,
+ 0xc9bca72d, 0x142a7ea8, 0x695978f0, 0xb4cfa175, 0x0905cdbb,
+ 0xd493143e, 0xf3e3c10b, 0x2e75188e, 0x93bf7440, 0x4e29adc5,
+ 0x335aab9d, 0xeecc7218, 0x53061ed6, 0x8e90c753, 0xae99ff49,
+ 0x730f26cc, 0xcec54a02, 0x13539387, 0x6e2095df, 0xb3b64c5a,
+ 0x0e7c2094, 0xd3eaf911, 0xf49a2c24, 0x290cf5a1, 0x94c6996f,
+ 0x495040ea, 0x342346b2, 0xe9b59f37, 0x547ff3f9, 0x89e92a7c,
+ 0x1a9e5993, 0xc7088016, 0x7ac2ecd8, 0xa754355d, 0xda273305,
+ 0x07b1ea80, 0xba7b864e, 0x67ed5fcb, 0x409d8afe, 0x9d0b537b,
+ 0x20c13fb5, 0xfd57e630, 0x8024e068, 0x5db239ed, 0xe0785523,
+ 0x3dee8ca6}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x85d996dd, 0x4bb55c60, 0xce6ccabd, 0x966ab9c0,
+ 0x13b32f1d, 0xdddfe5a0, 0x5806737d, 0x6dd3035a, 0xe80a9587,
+ 0x26665f3a, 0xa3bfc9e7, 0xfbb9ba9a, 0x7e602c47, 0xb00ce6fa,
+ 0x35d57027, 0xdaa607b4, 0x5f7f9169, 0x91135bd4, 0x14cacd09,
+ 0x4cccbe74, 0xc91528a9, 0x0779e214, 0x82a074c9, 0xb77504ee,
+ 0x32ac9233, 0xfcc0588e, 0x7919ce53, 0x211fbd2e, 0xa4c62bf3,
+ 0x6aaae14e, 0xef737793, 0xf54b7eb3, 0x7092e86e, 0xbefe22d3,
+ 0x3b27b40e, 0x6321c773, 0xe6f851ae, 0x28949b13, 0xad4d0dce,
+ 0x98987de9, 0x1d41eb34, 0xd32d2189, 0x56f4b754, 0x0ef2c429,
+ 0x8b2b52f4, 0x45479849, 0xc09e0e94, 0x2fed7907, 0xaa34efda,
+ 0x64582567, 0xe181b3ba, 0xb987c0c7, 0x3c5e561a, 0xf2329ca7,
+ 0x77eb0a7a, 0x423e7a5d, 0xc7e7ec80, 0x098b263d, 0x8c52b0e0,
+ 0xd454c39d, 0x518d5540, 0x9fe19ffd, 0x1a380920, 0xab918dbd,
+ 0x2e481b60, 0xe024d1dd, 0x65fd4700, 0x3dfb347d, 0xb822a2a0,
+ 0x764e681d, 0xf397fec0, 0xc6428ee7, 0x439b183a, 0x8df7d287,
+ 0x082e445a, 0x50283727, 0xd5f1a1fa, 0x1b9d6b47, 0x9e44fd9a,
+ 0x71378a09, 0xf4ee1cd4, 0x3a82d669, 0xbf5b40b4, 0xe75d33c9,
+ 0x6284a514, 0xace86fa9, 0x2931f974, 0x1ce48953, 0x993d1f8e,
+ 0x5751d533, 0xd28843ee, 0x8a8e3093, 0x0f57a64e, 0xc13b6cf3,
+ 0x44e2fa2e, 0x5edaf30e, 0xdb0365d3, 0x156faf6e, 0x90b639b3,
+ 0xc8b04ace, 0x4d69dc13, 0x830516ae, 0x06dc8073, 0x3309f054,
+ 0xb6d06689, 0x78bcac34, 0xfd653ae9, 0xa5634994, 0x20badf49,
+ 0xeed615f4, 0x6b0f8329, 0x847cf4ba, 0x01a56267, 0xcfc9a8da,
+ 0x4a103e07, 0x12164d7a, 0x97cfdba7, 0x59a3111a, 0xdc7a87c7,
+ 0xe9aff7e0, 0x6c76613d, 0xa21aab80, 0x27c33d5d, 0x7fc54e20,
+ 0xfa1cd8fd, 0x34701240, 0xb1a9849d, 0x17256aa0, 0x92fcfc7d,
+ 0x5c9036c0, 0xd949a01d, 0x814fd360, 0x049645bd, 0xcafa8f00,
+ 0x4f2319dd, 0x7af669fa, 0xff2fff27, 0x3143359a, 0xb49aa347,
+ 0xec9cd03a, 0x694546e7, 0xa7298c5a, 0x22f01a87, 0xcd836d14,
+ 0x485afbc9, 0x86363174, 0x03efa7a9, 0x5be9d4d4, 0xde304209,
+ 0x105c88b4, 0x95851e69, 0xa0506e4e, 0x2589f893, 0xebe5322e,
+ 0x6e3ca4f3, 0x363ad78e, 0xb3e34153, 0x7d8f8bee, 0xf8561d33,
+ 0xe26e1413, 0x67b782ce, 0xa9db4873, 0x2c02deae, 0x7404add3,
+ 0xf1dd3b0e, 0x3fb1f1b3, 0xba68676e, 0x8fbd1749, 0x0a648194,
+ 0xc4084b29, 0x41d1ddf4, 0x19d7ae89, 0x9c0e3854, 0x5262f2e9,
+ 0xd7bb6434, 0x38c813a7, 0xbd11857a, 0x737d4fc7, 0xf6a4d91a,
+ 0xaea2aa67, 0x2b7b3cba, 0xe517f607, 0x60ce60da, 0x551b10fd,
+ 0xd0c28620, 0x1eae4c9d, 0x9b77da40, 0xc371a93d, 0x46a83fe0,
+ 0x88c4f55d, 0x0d1d6380, 0xbcb4e71d, 0x396d71c0, 0xf701bb7d,
+ 0x72d82da0, 0x2ade5edd, 0xaf07c800, 0x616b02bd, 0xe4b29460,
+ 0xd167e447, 0x54be729a, 0x9ad2b827, 0x1f0b2efa, 0x470d5d87,
+ 0xc2d4cb5a, 0x0cb801e7, 0x8961973a, 0x6612e0a9, 0xe3cb7674,
+ 0x2da7bcc9, 0xa87e2a14, 0xf0785969, 0x75a1cfb4, 0xbbcd0509,
+ 0x3e1493d4, 0x0bc1e3f3, 0x8e18752e, 0x4074bf93, 0xc5ad294e,
+ 0x9dab5a33, 0x1872ccee, 0xd61e0653, 0x53c7908e, 0x49ff99ae,
+ 0xcc260f73, 0x024ac5ce, 0x87935313, 0xdf95206e, 0x5a4cb6b3,
+ 0x94207c0e, 0x11f9ead3, 0x242c9af4, 0xa1f50c29, 0x6f99c694,
+ 0xea405049, 0xb2462334, 0x379fb5e9, 0xf9f37f54, 0x7c2ae989,
+ 0x93599e1a, 0x168008c7, 0xd8ecc27a, 0x5d3554a7, 0x053327da,
+ 0x80eab107, 0x4e867bba, 0xcb5fed67, 0xfe8a9d40, 0x7b530b9d,
+ 0xb53fc120, 0x30e657fd, 0x68e02480, 0xed39b25d, 0x235578e0,
+ 0xa68cee3d},
+ {0x00000000, 0x76e10f9d, 0xadc46ee1, 0xdb25617c, 0x1b8fac19,
+ 0x6d6ea384, 0xb64bc2f8, 0xc0aacd65, 0x361e5933, 0x40ff56ae,
+ 0x9bda37d2, 0xed3b384f, 0x2d91f52a, 0x5b70fab7, 0x80559bcb,
+ 0xf6b49456, 0x6c3cb266, 0x1addbdfb, 0xc1f8dc87, 0xb719d31a,
+ 0x77b31e7f, 0x015211e2, 0xda77709e, 0xac967f03, 0x5a22eb55,
+ 0x2cc3e4c8, 0xf7e685b4, 0x81078a29, 0x41ad474c, 0x374c48d1,
+ 0xec6929ad, 0x9a882630, 0xd87864cd, 0xae996b50, 0x75bc0a2c,
+ 0x035d05b1, 0xc3f7c8d4, 0xb516c749, 0x6e33a635, 0x18d2a9a8,
+ 0xee663dfe, 0x98873263, 0x43a2531f, 0x35435c82, 0xf5e991e7,
+ 0x83089e7a, 0x582dff06, 0x2eccf09b, 0xb444d6ab, 0xc2a5d936,
+ 0x1980b84a, 0x6f61b7d7, 0xafcb7ab2, 0xd92a752f, 0x020f1453,
+ 0x74ee1bce, 0x825a8f98, 0xf4bb8005, 0x2f9ee179, 0x597feee4,
+ 0x99d52381, 0xef342c1c, 0x34114d60, 0x42f042fd, 0xf1f7b941,
+ 0x8716b6dc, 0x5c33d7a0, 0x2ad2d83d, 0xea781558, 0x9c991ac5,
+ 0x47bc7bb9, 0x315d7424, 0xc7e9e072, 0xb108efef, 0x6a2d8e93,
+ 0x1ccc810e, 0xdc664c6b, 0xaa8743f6, 0x71a2228a, 0x07432d17,
+ 0x9dcb0b27, 0xeb2a04ba, 0x300f65c6, 0x46ee6a5b, 0x8644a73e,
+ 0xf0a5a8a3, 0x2b80c9df, 0x5d61c642, 0xabd55214, 0xdd345d89,
+ 0x06113cf5, 0x70f03368, 0xb05afe0d, 0xc6bbf190, 0x1d9e90ec,
+ 0x6b7f9f71, 0x298fdd8c, 0x5f6ed211, 0x844bb36d, 0xf2aabcf0,
+ 0x32007195, 0x44e17e08, 0x9fc41f74, 0xe92510e9, 0x1f9184bf,
+ 0x69708b22, 0xb255ea5e, 0xc4b4e5c3, 0x041e28a6, 0x72ff273b,
+ 0xa9da4647, 0xdf3b49da, 0x45b36fea, 0x33526077, 0xe877010b,
+ 0x9e960e96, 0x5e3cc3f3, 0x28ddcc6e, 0xf3f8ad12, 0x8519a28f,
+ 0x73ad36d9, 0x054c3944, 0xde695838, 0xa88857a5, 0x68229ac0,
+ 0x1ec3955d, 0xc5e6f421, 0xb307fbbc, 0xe2ef7383, 0x940e7c1e,
+ 0x4f2b1d62, 0x39ca12ff, 0xf960df9a, 0x8f81d007, 0x54a4b17b,
+ 0x2245bee6, 0xd4f12ab0, 0xa210252d, 0x79354451, 0x0fd44bcc,
+ 0xcf7e86a9, 0xb99f8934, 0x62bae848, 0x145be7d5, 0x8ed3c1e5,
+ 0xf832ce78, 0x2317af04, 0x55f6a099, 0x955c6dfc, 0xe3bd6261,
+ 0x3898031d, 0x4e790c80, 0xb8cd98d6, 0xce2c974b, 0x1509f637,
+ 0x63e8f9aa, 0xa34234cf, 0xd5a33b52, 0x0e865a2e, 0x786755b3,
+ 0x3a97174e, 0x4c7618d3, 0x975379af, 0xe1b27632, 0x2118bb57,
+ 0x57f9b4ca, 0x8cdcd5b6, 0xfa3dda2b, 0x0c894e7d, 0x7a6841e0,
+ 0xa14d209c, 0xd7ac2f01, 0x1706e264, 0x61e7edf9, 0xbac28c85,
+ 0xcc238318, 0x56aba528, 0x204aaab5, 0xfb6fcbc9, 0x8d8ec454,
+ 0x4d240931, 0x3bc506ac, 0xe0e067d0, 0x9601684d, 0x60b5fc1b,
+ 0x1654f386, 0xcd7192fa, 0xbb909d67, 0x7b3a5002, 0x0ddb5f9f,
+ 0xd6fe3ee3, 0xa01f317e, 0x1318cac2, 0x65f9c55f, 0xbedca423,
+ 0xc83dabbe, 0x089766db, 0x7e766946, 0xa553083a, 0xd3b207a7,
+ 0x250693f1, 0x53e79c6c, 0x88c2fd10, 0xfe23f28d, 0x3e893fe8,
+ 0x48683075, 0x934d5109, 0xe5ac5e94, 0x7f2478a4, 0x09c57739,
+ 0xd2e01645, 0xa40119d8, 0x64abd4bd, 0x124adb20, 0xc96fba5c,
+ 0xbf8eb5c1, 0x493a2197, 0x3fdb2e0a, 0xe4fe4f76, 0x921f40eb,
+ 0x52b58d8e, 0x24548213, 0xff71e36f, 0x8990ecf2, 0xcb60ae0f,
+ 0xbd81a192, 0x66a4c0ee, 0x1045cf73, 0xd0ef0216, 0xa60e0d8b,
+ 0x7d2b6cf7, 0x0bca636a, 0xfd7ef73c, 0x8b9ff8a1, 0x50ba99dd,
+ 0x265b9640, 0xe6f15b25, 0x901054b8, 0x4b3535c4, 0x3dd43a59,
+ 0xa75c1c69, 0xd1bd13f4, 0x0a987288, 0x7c797d15, 0xbcd3b070,
+ 0xca32bfed, 0x1117de91, 0x67f6d10c, 0x9142455a, 0xe7a34ac7,
+ 0x3c862bbb, 0x4a672426, 0x8acde943, 0xfc2ce6de, 0x270987a2,
+ 0x51e8883f},
+ {0x00000000, 0xe8dbfbb9, 0x91b186a8, 0x796a7d11, 0x63657c8a,
+ 0x8bbe8733, 0xf2d4fa22, 0x1a0f019b, 0x87cc89cf, 0x6f177276,
+ 0x167d0f67, 0xfea6f4de, 0xe4a9f545, 0x0c720efc, 0x751873ed,
+ 0x9dc38854, 0x4f9f6244, 0xa74499fd, 0xde2ee4ec, 0x36f51f55,
+ 0x2cfa1ece, 0xc421e577, 0xbd4b9866, 0x559063df, 0xc853eb8b,
+ 0x20881032, 0x59e26d23, 0xb139969a, 0xab369701, 0x43ed6cb8,
+ 0x3a8711a9, 0xd25cea10, 0x9e3ec588, 0x76e53e31, 0x0f8f4320,
+ 0xe754b899, 0xfd5bb902, 0x158042bb, 0x6cea3faa, 0x8431c413,
+ 0x19f24c47, 0xf129b7fe, 0x8843caef, 0x60983156, 0x7a9730cd,
+ 0x924ccb74, 0xeb26b665, 0x03fd4ddc, 0xd1a1a7cc, 0x397a5c75,
+ 0x40102164, 0xa8cbdadd, 0xb2c4db46, 0x5a1f20ff, 0x23755dee,
+ 0xcbaea657, 0x566d2e03, 0xbeb6d5ba, 0xc7dca8ab, 0x2f075312,
+ 0x35085289, 0xddd3a930, 0xa4b9d421, 0x4c622f98, 0x7d7bfbca,
+ 0x95a00073, 0xecca7d62, 0x041186db, 0x1e1e8740, 0xf6c57cf9,
+ 0x8faf01e8, 0x6774fa51, 0xfab77205, 0x126c89bc, 0x6b06f4ad,
+ 0x83dd0f14, 0x99d20e8f, 0x7109f536, 0x08638827, 0xe0b8739e,
+ 0x32e4998e, 0xda3f6237, 0xa3551f26, 0x4b8ee49f, 0x5181e504,
+ 0xb95a1ebd, 0xc03063ac, 0x28eb9815, 0xb5281041, 0x5df3ebf8,
+ 0x249996e9, 0xcc426d50, 0xd64d6ccb, 0x3e969772, 0x47fcea63,
+ 0xaf2711da, 0xe3453e42, 0x0b9ec5fb, 0x72f4b8ea, 0x9a2f4353,
+ 0x802042c8, 0x68fbb971, 0x1191c460, 0xf94a3fd9, 0x6489b78d,
+ 0x8c524c34, 0xf5383125, 0x1de3ca9c, 0x07eccb07, 0xef3730be,
+ 0x965d4daf, 0x7e86b616, 0xacda5c06, 0x4401a7bf, 0x3d6bdaae,
+ 0xd5b02117, 0xcfbf208c, 0x2764db35, 0x5e0ea624, 0xb6d55d9d,
+ 0x2b16d5c9, 0xc3cd2e70, 0xbaa75361, 0x527ca8d8, 0x4873a943,
+ 0xa0a852fa, 0xd9c22feb, 0x3119d452, 0xbbf0874e, 0x532b7cf7,
+ 0x2a4101e6, 0xc29afa5f, 0xd895fbc4, 0x304e007d, 0x49247d6c,
+ 0xa1ff86d5, 0x3c3c0e81, 0xd4e7f538, 0xad8d8829, 0x45567390,
+ 0x5f59720b, 0xb78289b2, 0xcee8f4a3, 0x26330f1a, 0xf46fe50a,
+ 0x1cb41eb3, 0x65de63a2, 0x8d05981b, 0x970a9980, 0x7fd16239,
+ 0x06bb1f28, 0xee60e491, 0x73a36cc5, 0x9b78977c, 0xe212ea6d,
+ 0x0ac911d4, 0x10c6104f, 0xf81debf6, 0x817796e7, 0x69ac6d5e,
+ 0x25ce42c6, 0xcd15b97f, 0xb47fc46e, 0x5ca43fd7, 0x46ab3e4c,
+ 0xae70c5f5, 0xd71ab8e4, 0x3fc1435d, 0xa202cb09, 0x4ad930b0,
+ 0x33b34da1, 0xdb68b618, 0xc167b783, 0x29bc4c3a, 0x50d6312b,
+ 0xb80dca92, 0x6a512082, 0x828adb3b, 0xfbe0a62a, 0x133b5d93,
+ 0x09345c08, 0xe1efa7b1, 0x9885daa0, 0x705e2119, 0xed9da94d,
+ 0x054652f4, 0x7c2c2fe5, 0x94f7d45c, 0x8ef8d5c7, 0x66232e7e,
+ 0x1f49536f, 0xf792a8d6, 0xc68b7c84, 0x2e50873d, 0x573afa2c,
+ 0xbfe10195, 0xa5ee000e, 0x4d35fbb7, 0x345f86a6, 0xdc847d1f,
+ 0x4147f54b, 0xa99c0ef2, 0xd0f673e3, 0x382d885a, 0x222289c1,
+ 0xcaf97278, 0xb3930f69, 0x5b48f4d0, 0x89141ec0, 0x61cfe579,
+ 0x18a59868, 0xf07e63d1, 0xea71624a, 0x02aa99f3, 0x7bc0e4e2,
+ 0x931b1f5b, 0x0ed8970f, 0xe6036cb6, 0x9f6911a7, 0x77b2ea1e,
+ 0x6dbdeb85, 0x8566103c, 0xfc0c6d2d, 0x14d79694, 0x58b5b90c,
+ 0xb06e42b5, 0xc9043fa4, 0x21dfc41d, 0x3bd0c586, 0xd30b3e3f,
+ 0xaa61432e, 0x42bab897, 0xdf7930c3, 0x37a2cb7a, 0x4ec8b66b,
+ 0xa6134dd2, 0xbc1c4c49, 0x54c7b7f0, 0x2dadcae1, 0xc5763158,
+ 0x172adb48, 0xfff120f1, 0x869b5de0, 0x6e40a659, 0x744fa7c2,
+ 0x9c945c7b, 0xe5fe216a, 0x0d25dad3, 0x90e65287, 0x783da93e,
+ 0x0157d42f, 0xe98c2f96, 0xf3832e0d, 0x1b58d5b4, 0x6232a8a5,
+ 0x8ae9531c},
+ {0x00000000, 0x919168ae, 0x6325a087, 0xf2b4c829, 0x874c31d4,
+ 0x16dd597a, 0xe4699153, 0x75f8f9fd, 0x4f9f1373, 0xde0e7bdd,
+ 0x2cbab3f4, 0xbd2bdb5a, 0xc8d322a7, 0x59424a09, 0xabf68220,
+ 0x3a67ea8e, 0x9e3e27e6, 0x0faf4f48, 0xfd1b8761, 0x6c8aefcf,
+ 0x19721632, 0x88e37e9c, 0x7a57b6b5, 0xebc6de1b, 0xd1a13495,
+ 0x40305c3b, 0xb2849412, 0x2315fcbc, 0x56ed0541, 0xc77c6def,
+ 0x35c8a5c6, 0xa459cd68, 0x7d7b3f17, 0xecea57b9, 0x1e5e9f90,
+ 0x8fcff73e, 0xfa370ec3, 0x6ba6666d, 0x9912ae44, 0x0883c6ea,
+ 0x32e42c64, 0xa37544ca, 0x51c18ce3, 0xc050e44d, 0xb5a81db0,
+ 0x2439751e, 0xd68dbd37, 0x471cd599, 0xe34518f1, 0x72d4705f,
+ 0x8060b876, 0x11f1d0d8, 0x64092925, 0xf598418b, 0x072c89a2,
+ 0x96bde10c, 0xacda0b82, 0x3d4b632c, 0xcfffab05, 0x5e6ec3ab,
+ 0x2b963a56, 0xba0752f8, 0x48b39ad1, 0xd922f27f, 0xfaf67e2e,
+ 0x6b671680, 0x99d3dea9, 0x0842b607, 0x7dba4ffa, 0xec2b2754,
+ 0x1e9fef7d, 0x8f0e87d3, 0xb5696d5d, 0x24f805f3, 0xd64ccdda,
+ 0x47dda574, 0x32255c89, 0xa3b43427, 0x5100fc0e, 0xc09194a0,
+ 0x64c859c8, 0xf5593166, 0x07edf94f, 0x967c91e1, 0xe384681c,
+ 0x721500b2, 0x80a1c89b, 0x1130a035, 0x2b574abb, 0xbac62215,
+ 0x4872ea3c, 0xd9e38292, 0xac1b7b6f, 0x3d8a13c1, 0xcf3edbe8,
+ 0x5eafb346, 0x878d4139, 0x161c2997, 0xe4a8e1be, 0x75398910,
+ 0x00c170ed, 0x91501843, 0x63e4d06a, 0xf275b8c4, 0xc812524a,
+ 0x59833ae4, 0xab37f2cd, 0x3aa69a63, 0x4f5e639e, 0xdecf0b30,
+ 0x2c7bc319, 0xbdeaabb7, 0x19b366df, 0x88220e71, 0x7a96c658,
+ 0xeb07aef6, 0x9eff570b, 0x0f6e3fa5, 0xfddaf78c, 0x6c4b9f22,
+ 0x562c75ac, 0xc7bd1d02, 0x3509d52b, 0xa498bd85, 0xd1604478,
+ 0x40f12cd6, 0xb245e4ff, 0x23d48c51, 0xf4edfd5c, 0x657c95f2,
+ 0x97c85ddb, 0x06593575, 0x73a1cc88, 0xe230a426, 0x10846c0f,
+ 0x811504a1, 0xbb72ee2f, 0x2ae38681, 0xd8574ea8, 0x49c62606,
+ 0x3c3edffb, 0xadafb755, 0x5f1b7f7c, 0xce8a17d2, 0x6ad3daba,
+ 0xfb42b214, 0x09f67a3d, 0x98671293, 0xed9feb6e, 0x7c0e83c0,
+ 0x8eba4be9, 0x1f2b2347, 0x254cc9c9, 0xb4dda167, 0x4669694e,
+ 0xd7f801e0, 0xa200f81d, 0x339190b3, 0xc125589a, 0x50b43034,
+ 0x8996c24b, 0x1807aae5, 0xeab362cc, 0x7b220a62, 0x0edaf39f,
+ 0x9f4b9b31, 0x6dff5318, 0xfc6e3bb6, 0xc609d138, 0x5798b996,
+ 0xa52c71bf, 0x34bd1911, 0x4145e0ec, 0xd0d48842, 0x2260406b,
+ 0xb3f128c5, 0x17a8e5ad, 0x86398d03, 0x748d452a, 0xe51c2d84,
+ 0x90e4d479, 0x0175bcd7, 0xf3c174fe, 0x62501c50, 0x5837f6de,
+ 0xc9a69e70, 0x3b125659, 0xaa833ef7, 0xdf7bc70a, 0x4eeaafa4,
+ 0xbc5e678d, 0x2dcf0f23, 0x0e1b8372, 0x9f8aebdc, 0x6d3e23f5,
+ 0xfcaf4b5b, 0x8957b2a6, 0x18c6da08, 0xea721221, 0x7be37a8f,
+ 0x41849001, 0xd015f8af, 0x22a13086, 0xb3305828, 0xc6c8a1d5,
+ 0x5759c97b, 0xa5ed0152, 0x347c69fc, 0x9025a494, 0x01b4cc3a,
+ 0xf3000413, 0x62916cbd, 0x17699540, 0x86f8fdee, 0x744c35c7,
+ 0xe5dd5d69, 0xdfbab7e7, 0x4e2bdf49, 0xbc9f1760, 0x2d0e7fce,
+ 0x58f68633, 0xc967ee9d, 0x3bd326b4, 0xaa424e1a, 0x7360bc65,
+ 0xe2f1d4cb, 0x10451ce2, 0x81d4744c, 0xf42c8db1, 0x65bde51f,
+ 0x97092d36, 0x06984598, 0x3cffaf16, 0xad6ec7b8, 0x5fda0f91,
+ 0xce4b673f, 0xbbb39ec2, 0x2a22f66c, 0xd8963e45, 0x490756eb,
+ 0xed5e9b83, 0x7ccff32d, 0x8e7b3b04, 0x1fea53aa, 0x6a12aa57,
+ 0xfb83c2f9, 0x09370ad0, 0x98a6627e, 0xa2c188f0, 0x3350e05e,
+ 0xc1e42877, 0x507540d9, 0x258db924, 0xb41cd18a, 0x46a819a3,
+ 0xd739710d}};
+
+#endif
+
+#endif
+
+#if N == 5
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0xaf449247, 0x85f822cf, 0x2abcb088, 0xd08143df,
+ 0x7fc5d198, 0x55796110, 0xfa3df357, 0x7a7381ff, 0xd53713b8,
+ 0xff8ba330, 0x50cf3177, 0xaaf2c220, 0x05b65067, 0x2f0ae0ef,
+ 0x804e72a8, 0xf4e703fe, 0x5ba391b9, 0x711f2131, 0xde5bb376,
+ 0x24664021, 0x8b22d266, 0xa19e62ee, 0x0edaf0a9, 0x8e948201,
+ 0x21d01046, 0x0b6ca0ce, 0xa4283289, 0x5e15c1de, 0xf1515399,
+ 0xdbede311, 0x74a97156, 0x32bf01bd, 0x9dfb93fa, 0xb7472372,
+ 0x1803b135, 0xe23e4262, 0x4d7ad025, 0x67c660ad, 0xc882f2ea,
+ 0x48cc8042, 0xe7881205, 0xcd34a28d, 0x627030ca, 0x984dc39d,
+ 0x370951da, 0x1db5e152, 0xb2f17315, 0xc6580243, 0x691c9004,
+ 0x43a0208c, 0xece4b2cb, 0x16d9419c, 0xb99dd3db, 0x93216353,
+ 0x3c65f114, 0xbc2b83bc, 0x136f11fb, 0x39d3a173, 0x96973334,
+ 0x6caac063, 0xc3ee5224, 0xe952e2ac, 0x461670eb, 0x657e037a,
+ 0xca3a913d, 0xe08621b5, 0x4fc2b3f2, 0xb5ff40a5, 0x1abbd2e2,
+ 0x3007626a, 0x9f43f02d, 0x1f0d8285, 0xb04910c2, 0x9af5a04a,
+ 0x35b1320d, 0xcf8cc15a, 0x60c8531d, 0x4a74e395, 0xe53071d2,
+ 0x91990084, 0x3edd92c3, 0x1461224b, 0xbb25b00c, 0x4118435b,
+ 0xee5cd11c, 0xc4e06194, 0x6ba4f3d3, 0xebea817b, 0x44ae133c,
+ 0x6e12a3b4, 0xc15631f3, 0x3b6bc2a4, 0x942f50e3, 0xbe93e06b,
+ 0x11d7722c, 0x57c102c7, 0xf8859080, 0xd2392008, 0x7d7db24f,
+ 0x87404118, 0x2804d35f, 0x02b863d7, 0xadfcf190, 0x2db28338,
+ 0x82f6117f, 0xa84aa1f7, 0x070e33b0, 0xfd33c0e7, 0x527752a0,
+ 0x78cbe228, 0xd78f706f, 0xa3260139, 0x0c62937e, 0x26de23f6,
+ 0x899ab1b1, 0x73a742e6, 0xdce3d0a1, 0xf65f6029, 0x591bf26e,
+ 0xd95580c6, 0x76111281, 0x5cada209, 0xf3e9304e, 0x09d4c319,
+ 0xa690515e, 0x8c2ce1d6, 0x23687391, 0xcafc06f4, 0x65b894b3,
+ 0x4f04243b, 0xe040b67c, 0x1a7d452b, 0xb539d76c, 0x9f8567e4,
+ 0x30c1f5a3, 0xb08f870b, 0x1fcb154c, 0x3577a5c4, 0x9a333783,
+ 0x600ec4d4, 0xcf4a5693, 0xe5f6e61b, 0x4ab2745c, 0x3e1b050a,
+ 0x915f974d, 0xbbe327c5, 0x14a7b582, 0xee9a46d5, 0x41ded492,
+ 0x6b62641a, 0xc426f65d, 0x446884f5, 0xeb2c16b2, 0xc190a63a,
+ 0x6ed4347d, 0x94e9c72a, 0x3bad556d, 0x1111e5e5, 0xbe5577a2,
+ 0xf8430749, 0x5707950e, 0x7dbb2586, 0xd2ffb7c1, 0x28c24496,
+ 0x8786d6d1, 0xad3a6659, 0x027ef41e, 0x823086b6, 0x2d7414f1,
+ 0x07c8a479, 0xa88c363e, 0x52b1c569, 0xfdf5572e, 0xd749e7a6,
+ 0x780d75e1, 0x0ca404b7, 0xa3e096f0, 0x895c2678, 0x2618b43f,
+ 0xdc254768, 0x7361d52f, 0x59dd65a7, 0xf699f7e0, 0x76d78548,
+ 0xd993170f, 0xf32fa787, 0x5c6b35c0, 0xa656c697, 0x091254d0,
+ 0x23aee458, 0x8cea761f, 0xaf82058e, 0x00c697c9, 0x2a7a2741,
+ 0x853eb506, 0x7f034651, 0xd047d416, 0xfafb649e, 0x55bff6d9,
+ 0xd5f18471, 0x7ab51636, 0x5009a6be, 0xff4d34f9, 0x0570c7ae,
+ 0xaa3455e9, 0x8088e561, 0x2fcc7726, 0x5b650670, 0xf4219437,
+ 0xde9d24bf, 0x71d9b6f8, 0x8be445af, 0x24a0d7e8, 0x0e1c6760,
+ 0xa158f527, 0x2116878f, 0x8e5215c8, 0xa4eea540, 0x0baa3707,
+ 0xf197c450, 0x5ed35617, 0x746fe69f, 0xdb2b74d8, 0x9d3d0433,
+ 0x32799674, 0x18c526fc, 0xb781b4bb, 0x4dbc47ec, 0xe2f8d5ab,
+ 0xc8446523, 0x6700f764, 0xe74e85cc, 0x480a178b, 0x62b6a703,
+ 0xcdf23544, 0x37cfc613, 0x988b5454, 0xb237e4dc, 0x1d73769b,
+ 0x69da07cd, 0xc69e958a, 0xec222502, 0x4366b745, 0xb95b4412,
+ 0x161fd655, 0x3ca366dd, 0x93e7f49a, 0x13a98632, 0xbced1475,
+ 0x9651a4fd, 0x391536ba, 0xc328c5ed, 0x6c6c57aa, 0x46d0e722,
+ 0xe9947565},
+ {0x00000000, 0x4e890ba9, 0x9d121752, 0xd39b1cfb, 0xe15528e5,
+ 0xafdc234c, 0x7c473fb7, 0x32ce341e, 0x19db578b, 0x57525c22,
+ 0x84c940d9, 0xca404b70, 0xf88e7f6e, 0xb60774c7, 0x659c683c,
+ 0x2b156395, 0x33b6af16, 0x7d3fa4bf, 0xaea4b844, 0xe02db3ed,
+ 0xd2e387f3, 0x9c6a8c5a, 0x4ff190a1, 0x01789b08, 0x2a6df89d,
+ 0x64e4f334, 0xb77fefcf, 0xf9f6e466, 0xcb38d078, 0x85b1dbd1,
+ 0x562ac72a, 0x18a3cc83, 0x676d5e2c, 0x29e45585, 0xfa7f497e,
+ 0xb4f642d7, 0x863876c9, 0xc8b17d60, 0x1b2a619b, 0x55a36a32,
+ 0x7eb609a7, 0x303f020e, 0xe3a41ef5, 0xad2d155c, 0x9fe32142,
+ 0xd16a2aeb, 0x02f13610, 0x4c783db9, 0x54dbf13a, 0x1a52fa93,
+ 0xc9c9e668, 0x8740edc1, 0xb58ed9df, 0xfb07d276, 0x289cce8d,
+ 0x6615c524, 0x4d00a6b1, 0x0389ad18, 0xd012b1e3, 0x9e9bba4a,
+ 0xac558e54, 0xe2dc85fd, 0x31479906, 0x7fce92af, 0xcedabc58,
+ 0x8053b7f1, 0x53c8ab0a, 0x1d41a0a3, 0x2f8f94bd, 0x61069f14,
+ 0xb29d83ef, 0xfc148846, 0xd701ebd3, 0x9988e07a, 0x4a13fc81,
+ 0x049af728, 0x3654c336, 0x78ddc89f, 0xab46d464, 0xe5cfdfcd,
+ 0xfd6c134e, 0xb3e518e7, 0x607e041c, 0x2ef70fb5, 0x1c393bab,
+ 0x52b03002, 0x812b2cf9, 0xcfa22750, 0xe4b744c5, 0xaa3e4f6c,
+ 0x79a55397, 0x372c583e, 0x05e26c20, 0x4b6b6789, 0x98f07b72,
+ 0xd67970db, 0xa9b7e274, 0xe73ee9dd, 0x34a5f526, 0x7a2cfe8f,
+ 0x48e2ca91, 0x066bc138, 0xd5f0ddc3, 0x9b79d66a, 0xb06cb5ff,
+ 0xfee5be56, 0x2d7ea2ad, 0x63f7a904, 0x51399d1a, 0x1fb096b3,
+ 0xcc2b8a48, 0x82a281e1, 0x9a014d62, 0xd48846cb, 0x07135a30,
+ 0x499a5199, 0x7b546587, 0x35dd6e2e, 0xe64672d5, 0xa8cf797c,
+ 0x83da1ae9, 0xcd531140, 0x1ec80dbb, 0x50410612, 0x628f320c,
+ 0x2c0639a5, 0xff9d255e, 0xb1142ef7, 0x46c47ef1, 0x084d7558,
+ 0xdbd669a3, 0x955f620a, 0xa7915614, 0xe9185dbd, 0x3a834146,
+ 0x740a4aef, 0x5f1f297a, 0x119622d3, 0xc20d3e28, 0x8c843581,
+ 0xbe4a019f, 0xf0c30a36, 0x235816cd, 0x6dd11d64, 0x7572d1e7,
+ 0x3bfbda4e, 0xe860c6b5, 0xa6e9cd1c, 0x9427f902, 0xdaaef2ab,
+ 0x0935ee50, 0x47bce5f9, 0x6ca9866c, 0x22208dc5, 0xf1bb913e,
+ 0xbf329a97, 0x8dfcae89, 0xc375a520, 0x10eeb9db, 0x5e67b272,
+ 0x21a920dd, 0x6f202b74, 0xbcbb378f, 0xf2323c26, 0xc0fc0838,
+ 0x8e750391, 0x5dee1f6a, 0x136714c3, 0x38727756, 0x76fb7cff,
+ 0xa5606004, 0xebe96bad, 0xd9275fb3, 0x97ae541a, 0x443548e1,
+ 0x0abc4348, 0x121f8fcb, 0x5c968462, 0x8f0d9899, 0xc1849330,
+ 0xf34aa72e, 0xbdc3ac87, 0x6e58b07c, 0x20d1bbd5, 0x0bc4d840,
+ 0x454dd3e9, 0x96d6cf12, 0xd85fc4bb, 0xea91f0a5, 0xa418fb0c,
+ 0x7783e7f7, 0x390aec5e, 0x881ec2a9, 0xc697c900, 0x150cd5fb,
+ 0x5b85de52, 0x694bea4c, 0x27c2e1e5, 0xf459fd1e, 0xbad0f6b7,
+ 0x91c59522, 0xdf4c9e8b, 0x0cd78270, 0x425e89d9, 0x7090bdc7,
+ 0x3e19b66e, 0xed82aa95, 0xa30ba13c, 0xbba86dbf, 0xf5216616,
+ 0x26ba7aed, 0x68337144, 0x5afd455a, 0x14744ef3, 0xc7ef5208,
+ 0x896659a1, 0xa2733a34, 0xecfa319d, 0x3f612d66, 0x71e826cf,
+ 0x432612d1, 0x0daf1978, 0xde340583, 0x90bd0e2a, 0xef739c85,
+ 0xa1fa972c, 0x72618bd7, 0x3ce8807e, 0x0e26b460, 0x40afbfc9,
+ 0x9334a332, 0xddbda89b, 0xf6a8cb0e, 0xb821c0a7, 0x6bbadc5c,
+ 0x2533d7f5, 0x17fde3eb, 0x5974e842, 0x8aeff4b9, 0xc466ff10,
+ 0xdcc53393, 0x924c383a, 0x41d724c1, 0x0f5e2f68, 0x3d901b76,
+ 0x731910df, 0xa0820c24, 0xee0b078d, 0xc51e6418, 0x8b976fb1,
+ 0x580c734a, 0x168578e3, 0x244b4cfd, 0x6ac24754, 0xb9595baf,
+ 0xf7d05006},
+ {0x00000000, 0x8d88fde2, 0xc060fd85, 0x4de80067, 0x5bb0fd4b,
+ 0xd63800a9, 0x9bd000ce, 0x1658fd2c, 0xb761fa96, 0x3ae90774,
+ 0x77010713, 0xfa89faf1, 0xecd107dd, 0x6159fa3f, 0x2cb1fa58,
+ 0xa13907ba, 0xb5b2f36d, 0x383a0e8f, 0x75d20ee8, 0xf85af30a,
+ 0xee020e26, 0x638af3c4, 0x2e62f3a3, 0xa3ea0e41, 0x02d309fb,
+ 0x8f5bf419, 0xc2b3f47e, 0x4f3b099c, 0x5963f4b0, 0xd4eb0952,
+ 0x99030935, 0x148bf4d7, 0xb014e09b, 0x3d9c1d79, 0x70741d1e,
+ 0xfdfce0fc, 0xeba41dd0, 0x662ce032, 0x2bc4e055, 0xa64c1db7,
+ 0x07751a0d, 0x8afde7ef, 0xc715e788, 0x4a9d1a6a, 0x5cc5e746,
+ 0xd14d1aa4, 0x9ca51ac3, 0x112de721, 0x05a613f6, 0x882eee14,
+ 0xc5c6ee73, 0x484e1391, 0x5e16eebd, 0xd39e135f, 0x9e761338,
+ 0x13feeeda, 0xb2c7e960, 0x3f4f1482, 0x72a714e5, 0xff2fe907,
+ 0xe977142b, 0x64ffe9c9, 0x2917e9ae, 0xa49f144c, 0xbb58c777,
+ 0x36d03a95, 0x7b383af2, 0xf6b0c710, 0xe0e83a3c, 0x6d60c7de,
+ 0x2088c7b9, 0xad003a5b, 0x0c393de1, 0x81b1c003, 0xcc59c064,
+ 0x41d13d86, 0x5789c0aa, 0xda013d48, 0x97e93d2f, 0x1a61c0cd,
+ 0x0eea341a, 0x8362c9f8, 0xce8ac99f, 0x4302347d, 0x555ac951,
+ 0xd8d234b3, 0x953a34d4, 0x18b2c936, 0xb98bce8c, 0x3403336e,
+ 0x79eb3309, 0xf463ceeb, 0xe23b33c7, 0x6fb3ce25, 0x225bce42,
+ 0xafd333a0, 0x0b4c27ec, 0x86c4da0e, 0xcb2cda69, 0x46a4278b,
+ 0x50fcdaa7, 0xdd742745, 0x909c2722, 0x1d14dac0, 0xbc2ddd7a,
+ 0x31a52098, 0x7c4d20ff, 0xf1c5dd1d, 0xe79d2031, 0x6a15ddd3,
+ 0x27fdddb4, 0xaa752056, 0xbefed481, 0x33762963, 0x7e9e2904,
+ 0xf316d4e6, 0xe54e29ca, 0x68c6d428, 0x252ed44f, 0xa8a629ad,
+ 0x099f2e17, 0x8417d3f5, 0xc9ffd392, 0x44772e70, 0x522fd35c,
+ 0xdfa72ebe, 0x924f2ed9, 0x1fc7d33b, 0xadc088af, 0x2048754d,
+ 0x6da0752a, 0xe02888c8, 0xf67075e4, 0x7bf88806, 0x36108861,
+ 0xbb987583, 0x1aa17239, 0x97298fdb, 0xdac18fbc, 0x5749725e,
+ 0x41118f72, 0xcc997290, 0x817172f7, 0x0cf98f15, 0x18727bc2,
+ 0x95fa8620, 0xd8128647, 0x559a7ba5, 0x43c28689, 0xce4a7b6b,
+ 0x83a27b0c, 0x0e2a86ee, 0xaf138154, 0x229b7cb6, 0x6f737cd1,
+ 0xe2fb8133, 0xf4a37c1f, 0x792b81fd, 0x34c3819a, 0xb94b7c78,
+ 0x1dd46834, 0x905c95d6, 0xddb495b1, 0x503c6853, 0x4664957f,
+ 0xcbec689d, 0x860468fa, 0x0b8c9518, 0xaab592a2, 0x273d6f40,
+ 0x6ad56f27, 0xe75d92c5, 0xf1056fe9, 0x7c8d920b, 0x3165926c,
+ 0xbced6f8e, 0xa8669b59, 0x25ee66bb, 0x680666dc, 0xe58e9b3e,
+ 0xf3d66612, 0x7e5e9bf0, 0x33b69b97, 0xbe3e6675, 0x1f0761cf,
+ 0x928f9c2d, 0xdf679c4a, 0x52ef61a8, 0x44b79c84, 0xc93f6166,
+ 0x84d76101, 0x095f9ce3, 0x16984fd8, 0x9b10b23a, 0xd6f8b25d,
+ 0x5b704fbf, 0x4d28b293, 0xc0a04f71, 0x8d484f16, 0x00c0b2f4,
+ 0xa1f9b54e, 0x2c7148ac, 0x619948cb, 0xec11b529, 0xfa494805,
+ 0x77c1b5e7, 0x3a29b580, 0xb7a14862, 0xa32abcb5, 0x2ea24157,
+ 0x634a4130, 0xeec2bcd2, 0xf89a41fe, 0x7512bc1c, 0x38fabc7b,
+ 0xb5724199, 0x144b4623, 0x99c3bbc1, 0xd42bbba6, 0x59a34644,
+ 0x4ffbbb68, 0xc273468a, 0x8f9b46ed, 0x0213bb0f, 0xa68caf43,
+ 0x2b0452a1, 0x66ec52c6, 0xeb64af24, 0xfd3c5208, 0x70b4afea,
+ 0x3d5caf8d, 0xb0d4526f, 0x11ed55d5, 0x9c65a837, 0xd18da850,
+ 0x5c0555b2, 0x4a5da89e, 0xc7d5557c, 0x8a3d551b, 0x07b5a8f9,
+ 0x133e5c2e, 0x9eb6a1cc, 0xd35ea1ab, 0x5ed65c49, 0x488ea165,
+ 0xc5065c87, 0x88ee5ce0, 0x0566a102, 0xa45fa6b8, 0x29d75b5a,
+ 0x643f5b3d, 0xe9b7a6df, 0xffef5bf3, 0x7267a611, 0x3f8fa676,
+ 0xb2075b94},
+ {0x00000000, 0x80f0171f, 0xda91287f, 0x5a613f60, 0x6e5356bf,
+ 0xeea341a0, 0xb4c27ec0, 0x343269df, 0xdca6ad7e, 0x5c56ba61,
+ 0x06378501, 0x86c7921e, 0xb2f5fbc1, 0x3205ecde, 0x6864d3be,
+ 0xe894c4a1, 0x623c5cbd, 0xe2cc4ba2, 0xb8ad74c2, 0x385d63dd,
+ 0x0c6f0a02, 0x8c9f1d1d, 0xd6fe227d, 0x560e3562, 0xbe9af1c3,
+ 0x3e6ae6dc, 0x640bd9bc, 0xe4fbcea3, 0xd0c9a77c, 0x5039b063,
+ 0x0a588f03, 0x8aa8981c, 0xc478b97a, 0x4488ae65, 0x1ee99105,
+ 0x9e19861a, 0xaa2befc5, 0x2adbf8da, 0x70bac7ba, 0xf04ad0a5,
+ 0x18de1404, 0x982e031b, 0xc24f3c7b, 0x42bf2b64, 0x768d42bb,
+ 0xf67d55a4, 0xac1c6ac4, 0x2cec7ddb, 0xa644e5c7, 0x26b4f2d8,
+ 0x7cd5cdb8, 0xfc25daa7, 0xc817b378, 0x48e7a467, 0x12869b07,
+ 0x92768c18, 0x7ae248b9, 0xfa125fa6, 0xa07360c6, 0x208377d9,
+ 0x14b11e06, 0x94410919, 0xce203679, 0x4ed02166, 0x538074b5,
+ 0xd37063aa, 0x89115cca, 0x09e14bd5, 0x3dd3220a, 0xbd233515,
+ 0xe7420a75, 0x67b21d6a, 0x8f26d9cb, 0x0fd6ced4, 0x55b7f1b4,
+ 0xd547e6ab, 0xe1758f74, 0x6185986b, 0x3be4a70b, 0xbb14b014,
+ 0x31bc2808, 0xb14c3f17, 0xeb2d0077, 0x6bdd1768, 0x5fef7eb7,
+ 0xdf1f69a8, 0x857e56c8, 0x058e41d7, 0xed1a8576, 0x6dea9269,
+ 0x378bad09, 0xb77bba16, 0x8349d3c9, 0x03b9c4d6, 0x59d8fbb6,
+ 0xd928eca9, 0x97f8cdcf, 0x1708dad0, 0x4d69e5b0, 0xcd99f2af,
+ 0xf9ab9b70, 0x795b8c6f, 0x233ab30f, 0xa3caa410, 0x4b5e60b1,
+ 0xcbae77ae, 0x91cf48ce, 0x113f5fd1, 0x250d360e, 0xa5fd2111,
+ 0xff9c1e71, 0x7f6c096e, 0xf5c49172, 0x7534866d, 0x2f55b90d,
+ 0xafa5ae12, 0x9b97c7cd, 0x1b67d0d2, 0x4106efb2, 0xc1f6f8ad,
+ 0x29623c0c, 0xa9922b13, 0xf3f31473, 0x7303036c, 0x47316ab3,
+ 0xc7c17dac, 0x9da042cc, 0x1d5055d3, 0xa700e96a, 0x27f0fe75,
+ 0x7d91c115, 0xfd61d60a, 0xc953bfd5, 0x49a3a8ca, 0x13c297aa,
+ 0x933280b5, 0x7ba64414, 0xfb56530b, 0xa1376c6b, 0x21c77b74,
+ 0x15f512ab, 0x950505b4, 0xcf643ad4, 0x4f942dcb, 0xc53cb5d7,
+ 0x45cca2c8, 0x1fad9da8, 0x9f5d8ab7, 0xab6fe368, 0x2b9ff477,
+ 0x71fecb17, 0xf10edc08, 0x199a18a9, 0x996a0fb6, 0xc30b30d6,
+ 0x43fb27c9, 0x77c94e16, 0xf7395909, 0xad586669, 0x2da87176,
+ 0x63785010, 0xe388470f, 0xb9e9786f, 0x39196f70, 0x0d2b06af,
+ 0x8ddb11b0, 0xd7ba2ed0, 0x574a39cf, 0xbfdefd6e, 0x3f2eea71,
+ 0x654fd511, 0xe5bfc20e, 0xd18dabd1, 0x517dbcce, 0x0b1c83ae,
+ 0x8bec94b1, 0x01440cad, 0x81b41bb2, 0xdbd524d2, 0x5b2533cd,
+ 0x6f175a12, 0xefe74d0d, 0xb586726d, 0x35766572, 0xdde2a1d3,
+ 0x5d12b6cc, 0x077389ac, 0x87839eb3, 0xb3b1f76c, 0x3341e073,
+ 0x6920df13, 0xe9d0c80c, 0xf4809ddf, 0x74708ac0, 0x2e11b5a0,
+ 0xaee1a2bf, 0x9ad3cb60, 0x1a23dc7f, 0x4042e31f, 0xc0b2f400,
+ 0x282630a1, 0xa8d627be, 0xf2b718de, 0x72470fc1, 0x4675661e,
+ 0xc6857101, 0x9ce44e61, 0x1c14597e, 0x96bcc162, 0x164cd67d,
+ 0x4c2de91d, 0xccddfe02, 0xf8ef97dd, 0x781f80c2, 0x227ebfa2,
+ 0xa28ea8bd, 0x4a1a6c1c, 0xcaea7b03, 0x908b4463, 0x107b537c,
+ 0x24493aa3, 0xa4b92dbc, 0xfed812dc, 0x7e2805c3, 0x30f824a5,
+ 0xb00833ba, 0xea690cda, 0x6a991bc5, 0x5eab721a, 0xde5b6505,
+ 0x843a5a65, 0x04ca4d7a, 0xec5e89db, 0x6cae9ec4, 0x36cfa1a4,
+ 0xb63fb6bb, 0x820ddf64, 0x02fdc87b, 0x589cf71b, 0xd86ce004,
+ 0x52c47818, 0xd2346f07, 0x88555067, 0x08a54778, 0x3c972ea7,
+ 0xbc6739b8, 0xe60606d8, 0x66f611c7, 0x8e62d566, 0x0e92c279,
+ 0x54f3fd19, 0xd403ea06, 0xe03183d9, 0x60c194c6, 0x3aa0aba6,
+ 0xba50bcb9},
+ {0x00000000, 0x9570d495, 0xf190af6b, 0x64e07bfe, 0x38505897,
+ 0xad208c02, 0xc9c0f7fc, 0x5cb02369, 0x70a0b12e, 0xe5d065bb,
+ 0x81301e45, 0x1440cad0, 0x48f0e9b9, 0xdd803d2c, 0xb96046d2,
+ 0x2c109247, 0xe141625c, 0x7431b6c9, 0x10d1cd37, 0x85a119a2,
+ 0xd9113acb, 0x4c61ee5e, 0x288195a0, 0xbdf14135, 0x91e1d372,
+ 0x049107e7, 0x60717c19, 0xf501a88c, 0xa9b18be5, 0x3cc15f70,
+ 0x5821248e, 0xcd51f01b, 0x19f3c2f9, 0x8c83166c, 0xe8636d92,
+ 0x7d13b907, 0x21a39a6e, 0xb4d34efb, 0xd0333505, 0x4543e190,
+ 0x695373d7, 0xfc23a742, 0x98c3dcbc, 0x0db30829, 0x51032b40,
+ 0xc473ffd5, 0xa093842b, 0x35e350be, 0xf8b2a0a5, 0x6dc27430,
+ 0x09220fce, 0x9c52db5b, 0xc0e2f832, 0x55922ca7, 0x31725759,
+ 0xa40283cc, 0x8812118b, 0x1d62c51e, 0x7982bee0, 0xecf26a75,
+ 0xb042491c, 0x25329d89, 0x41d2e677, 0xd4a232e2, 0x33e785f2,
+ 0xa6975167, 0xc2772a99, 0x5707fe0c, 0x0bb7dd65, 0x9ec709f0,
+ 0xfa27720e, 0x6f57a69b, 0x434734dc, 0xd637e049, 0xb2d79bb7,
+ 0x27a74f22, 0x7b176c4b, 0xee67b8de, 0x8a87c320, 0x1ff717b5,
+ 0xd2a6e7ae, 0x47d6333b, 0x233648c5, 0xb6469c50, 0xeaf6bf39,
+ 0x7f866bac, 0x1b661052, 0x8e16c4c7, 0xa2065680, 0x37768215,
+ 0x5396f9eb, 0xc6e62d7e, 0x9a560e17, 0x0f26da82, 0x6bc6a17c,
+ 0xfeb675e9, 0x2a14470b, 0xbf64939e, 0xdb84e860, 0x4ef43cf5,
+ 0x12441f9c, 0x8734cb09, 0xe3d4b0f7, 0x76a46462, 0x5ab4f625,
+ 0xcfc422b0, 0xab24594e, 0x3e548ddb, 0x62e4aeb2, 0xf7947a27,
+ 0x937401d9, 0x0604d54c, 0xcb552557, 0x5e25f1c2, 0x3ac58a3c,
+ 0xafb55ea9, 0xf3057dc0, 0x6675a955, 0x0295d2ab, 0x97e5063e,
+ 0xbbf59479, 0x2e8540ec, 0x4a653b12, 0xdf15ef87, 0x83a5ccee,
+ 0x16d5187b, 0x72356385, 0xe745b710, 0x67cf0be4, 0xf2bfdf71,
+ 0x965fa48f, 0x032f701a, 0x5f9f5373, 0xcaef87e6, 0xae0ffc18,
+ 0x3b7f288d, 0x176fbaca, 0x821f6e5f, 0xe6ff15a1, 0x738fc134,
+ 0x2f3fe25d, 0xba4f36c8, 0xdeaf4d36, 0x4bdf99a3, 0x868e69b8,
+ 0x13febd2d, 0x771ec6d3, 0xe26e1246, 0xbede312f, 0x2baee5ba,
+ 0x4f4e9e44, 0xda3e4ad1, 0xf62ed896, 0x635e0c03, 0x07be77fd,
+ 0x92cea368, 0xce7e8001, 0x5b0e5494, 0x3fee2f6a, 0xaa9efbff,
+ 0x7e3cc91d, 0xeb4c1d88, 0x8fac6676, 0x1adcb2e3, 0x466c918a,
+ 0xd31c451f, 0xb7fc3ee1, 0x228cea74, 0x0e9c7833, 0x9becaca6,
+ 0xff0cd758, 0x6a7c03cd, 0x36cc20a4, 0xa3bcf431, 0xc75c8fcf,
+ 0x522c5b5a, 0x9f7dab41, 0x0a0d7fd4, 0x6eed042a, 0xfb9dd0bf,
+ 0xa72df3d6, 0x325d2743, 0x56bd5cbd, 0xc3cd8828, 0xefdd1a6f,
+ 0x7aadcefa, 0x1e4db504, 0x8b3d6191, 0xd78d42f8, 0x42fd966d,
+ 0x261ded93, 0xb36d3906, 0x54288e16, 0xc1585a83, 0xa5b8217d,
+ 0x30c8f5e8, 0x6c78d681, 0xf9080214, 0x9de879ea, 0x0898ad7f,
+ 0x24883f38, 0xb1f8ebad, 0xd5189053, 0x406844c6, 0x1cd867af,
+ 0x89a8b33a, 0xed48c8c4, 0x78381c51, 0xb569ec4a, 0x201938df,
+ 0x44f94321, 0xd18997b4, 0x8d39b4dd, 0x18496048, 0x7ca91bb6,
+ 0xe9d9cf23, 0xc5c95d64, 0x50b989f1, 0x3459f20f, 0xa129269a,
+ 0xfd9905f3, 0x68e9d166, 0x0c09aa98, 0x99797e0d, 0x4ddb4cef,
+ 0xd8ab987a, 0xbc4be384, 0x293b3711, 0x758b1478, 0xe0fbc0ed,
+ 0x841bbb13, 0x116b6f86, 0x3d7bfdc1, 0xa80b2954, 0xcceb52aa,
+ 0x599b863f, 0x052ba556, 0x905b71c3, 0xf4bb0a3d, 0x61cbdea8,
+ 0xac9a2eb3, 0x39eafa26, 0x5d0a81d8, 0xc87a554d, 0x94ca7624,
+ 0x01baa2b1, 0x655ad94f, 0xf02a0dda, 0xdc3a9f9d, 0x494a4b08,
+ 0x2daa30f6, 0xb8dae463, 0xe46ac70a, 0x711a139f, 0x15fa6861,
+ 0x808abcf4},
+ {0x00000000, 0xcf9e17c8, 0x444d29d1, 0x8bd33e19, 0x889a53a2,
+ 0x4704446a, 0xccd77a73, 0x03496dbb, 0xca45a105, 0x05dbb6cd,
+ 0x8e0888d4, 0x41969f1c, 0x42dff2a7, 0x8d41e56f, 0x0692db76,
+ 0xc90cccbe, 0x4ffa444b, 0x80645383, 0x0bb76d9a, 0xc4297a52,
+ 0xc76017e9, 0x08fe0021, 0x832d3e38, 0x4cb329f0, 0x85bfe54e,
+ 0x4a21f286, 0xc1f2cc9f, 0x0e6cdb57, 0x0d25b6ec, 0xc2bba124,
+ 0x49689f3d, 0x86f688f5, 0x9ff48896, 0x506a9f5e, 0xdbb9a147,
+ 0x1427b68f, 0x176edb34, 0xd8f0ccfc, 0x5323f2e5, 0x9cbde52d,
+ 0x55b12993, 0x9a2f3e5b, 0x11fc0042, 0xde62178a, 0xdd2b7a31,
+ 0x12b56df9, 0x996653e0, 0x56f84428, 0xd00eccdd, 0x1f90db15,
+ 0x9443e50c, 0x5bddf2c4, 0x58949f7f, 0x970a88b7, 0x1cd9b6ae,
+ 0xd347a166, 0x1a4b6dd8, 0xd5d57a10, 0x5e064409, 0x919853c1,
+ 0x92d13e7a, 0x5d4f29b2, 0xd69c17ab, 0x19020063, 0xe498176d,
+ 0x2b0600a5, 0xa0d53ebc, 0x6f4b2974, 0x6c0244cf, 0xa39c5307,
+ 0x284f6d1e, 0xe7d17ad6, 0x2eddb668, 0xe143a1a0, 0x6a909fb9,
+ 0xa50e8871, 0xa647e5ca, 0x69d9f202, 0xe20acc1b, 0x2d94dbd3,
+ 0xab625326, 0x64fc44ee, 0xef2f7af7, 0x20b16d3f, 0x23f80084,
+ 0xec66174c, 0x67b52955, 0xa82b3e9d, 0x6127f223, 0xaeb9e5eb,
+ 0x256adbf2, 0xeaf4cc3a, 0xe9bda181, 0x2623b649, 0xadf08850,
+ 0x626e9f98, 0x7b6c9ffb, 0xb4f28833, 0x3f21b62a, 0xf0bfa1e2,
+ 0xf3f6cc59, 0x3c68db91, 0xb7bbe588, 0x7825f240, 0xb1293efe,
+ 0x7eb72936, 0xf564172f, 0x3afa00e7, 0x39b36d5c, 0xf62d7a94,
+ 0x7dfe448d, 0xb2605345, 0x3496dbb0, 0xfb08cc78, 0x70dbf261,
+ 0xbf45e5a9, 0xbc0c8812, 0x73929fda, 0xf841a1c3, 0x37dfb60b,
+ 0xfed37ab5, 0x314d6d7d, 0xba9e5364, 0x750044ac, 0x76492917,
+ 0xb9d73edf, 0x320400c6, 0xfd9a170e, 0x1241289b, 0xdddf3f53,
+ 0x560c014a, 0x99921682, 0x9adb7b39, 0x55456cf1, 0xde9652e8,
+ 0x11084520, 0xd804899e, 0x179a9e56, 0x9c49a04f, 0x53d7b787,
+ 0x509eda3c, 0x9f00cdf4, 0x14d3f3ed, 0xdb4de425, 0x5dbb6cd0,
+ 0x92257b18, 0x19f64501, 0xd66852c9, 0xd5213f72, 0x1abf28ba,
+ 0x916c16a3, 0x5ef2016b, 0x97fecdd5, 0x5860da1d, 0xd3b3e404,
+ 0x1c2df3cc, 0x1f649e77, 0xd0fa89bf, 0x5b29b7a6, 0x94b7a06e,
+ 0x8db5a00d, 0x422bb7c5, 0xc9f889dc, 0x06669e14, 0x052ff3af,
+ 0xcab1e467, 0x4162da7e, 0x8efccdb6, 0x47f00108, 0x886e16c0,
+ 0x03bd28d9, 0xcc233f11, 0xcf6a52aa, 0x00f44562, 0x8b277b7b,
+ 0x44b96cb3, 0xc24fe446, 0x0dd1f38e, 0x8602cd97, 0x499cda5f,
+ 0x4ad5b7e4, 0x854ba02c, 0x0e989e35, 0xc10689fd, 0x080a4543,
+ 0xc794528b, 0x4c476c92, 0x83d97b5a, 0x809016e1, 0x4f0e0129,
+ 0xc4dd3f30, 0x0b4328f8, 0xf6d93ff6, 0x3947283e, 0xb2941627,
+ 0x7d0a01ef, 0x7e436c54, 0xb1dd7b9c, 0x3a0e4585, 0xf590524d,
+ 0x3c9c9ef3, 0xf302893b, 0x78d1b722, 0xb74fa0ea, 0xb406cd51,
+ 0x7b98da99, 0xf04be480, 0x3fd5f348, 0xb9237bbd, 0x76bd6c75,
+ 0xfd6e526c, 0x32f045a4, 0x31b9281f, 0xfe273fd7, 0x75f401ce,
+ 0xba6a1606, 0x7366dab8, 0xbcf8cd70, 0x372bf369, 0xf8b5e4a1,
+ 0xfbfc891a, 0x34629ed2, 0xbfb1a0cb, 0x702fb703, 0x692db760,
+ 0xa6b3a0a8, 0x2d609eb1, 0xe2fe8979, 0xe1b7e4c2, 0x2e29f30a,
+ 0xa5facd13, 0x6a64dadb, 0xa3681665, 0x6cf601ad, 0xe7253fb4,
+ 0x28bb287c, 0x2bf245c7, 0xe46c520f, 0x6fbf6c16, 0xa0217bde,
+ 0x26d7f32b, 0xe949e4e3, 0x629adafa, 0xad04cd32, 0xae4da089,
+ 0x61d3b741, 0xea008958, 0x259e9e90, 0xec92522e, 0x230c45e6,
+ 0xa8df7bff, 0x67416c37, 0x6408018c, 0xab961644, 0x2045285d,
+ 0xefdb3f95},
+ {0x00000000, 0x24825136, 0x4904a26c, 0x6d86f35a, 0x920944d8,
+ 0xb68b15ee, 0xdb0de6b4, 0xff8fb782, 0xff638ff1, 0xdbe1dec7,
+ 0xb6672d9d, 0x92e57cab, 0x6d6acb29, 0x49e89a1f, 0x246e6945,
+ 0x00ec3873, 0x25b619a3, 0x01344895, 0x6cb2bbcf, 0x4830eaf9,
+ 0xb7bf5d7b, 0x933d0c4d, 0xfebbff17, 0xda39ae21, 0xdad59652,
+ 0xfe57c764, 0x93d1343e, 0xb7536508, 0x48dcd28a, 0x6c5e83bc,
+ 0x01d870e6, 0x255a21d0, 0x4b6c3346, 0x6fee6270, 0x0268912a,
+ 0x26eac01c, 0xd965779e, 0xfde726a8, 0x9061d5f2, 0xb4e384c4,
+ 0xb40fbcb7, 0x908ded81, 0xfd0b1edb, 0xd9894fed, 0x2606f86f,
+ 0x0284a959, 0x6f025a03, 0x4b800b35, 0x6eda2ae5, 0x4a587bd3,
+ 0x27de8889, 0x035cd9bf, 0xfcd36e3d, 0xd8513f0b, 0xb5d7cc51,
+ 0x91559d67, 0x91b9a514, 0xb53bf422, 0xd8bd0778, 0xfc3f564e,
+ 0x03b0e1cc, 0x2732b0fa, 0x4ab443a0, 0x6e361296, 0x96d8668c,
+ 0xb25a37ba, 0xdfdcc4e0, 0xfb5e95d6, 0x04d12254, 0x20537362,
+ 0x4dd58038, 0x6957d10e, 0x69bbe97d, 0x4d39b84b, 0x20bf4b11,
+ 0x043d1a27, 0xfbb2ada5, 0xdf30fc93, 0xb2b60fc9, 0x96345eff,
+ 0xb36e7f2f, 0x97ec2e19, 0xfa6add43, 0xdee88c75, 0x21673bf7,
+ 0x05e56ac1, 0x6863999b, 0x4ce1c8ad, 0x4c0df0de, 0x688fa1e8,
+ 0x050952b2, 0x218b0384, 0xde04b406, 0xfa86e530, 0x9700166a,
+ 0xb382475c, 0xddb455ca, 0xf93604fc, 0x94b0f7a6, 0xb032a690,
+ 0x4fbd1112, 0x6b3f4024, 0x06b9b37e, 0x223be248, 0x22d7da3b,
+ 0x06558b0d, 0x6bd37857, 0x4f512961, 0xb0de9ee3, 0x945ccfd5,
+ 0xf9da3c8f, 0xdd586db9, 0xf8024c69, 0xdc801d5f, 0xb106ee05,
+ 0x9584bf33, 0x6a0b08b1, 0x4e895987, 0x230faadd, 0x078dfbeb,
+ 0x0761c398, 0x23e392ae, 0x4e6561f4, 0x6ae730c2, 0x95688740,
+ 0xb1ead676, 0xdc6c252c, 0xf8ee741a, 0xf6c1cb59, 0xd2439a6f,
+ 0xbfc56935, 0x9b473803, 0x64c88f81, 0x404adeb7, 0x2dcc2ded,
+ 0x094e7cdb, 0x09a244a8, 0x2d20159e, 0x40a6e6c4, 0x6424b7f2,
+ 0x9bab0070, 0xbf295146, 0xd2afa21c, 0xf62df32a, 0xd377d2fa,
+ 0xf7f583cc, 0x9a737096, 0xbef121a0, 0x417e9622, 0x65fcc714,
+ 0x087a344e, 0x2cf86578, 0x2c145d0b, 0x08960c3d, 0x6510ff67,
+ 0x4192ae51, 0xbe1d19d3, 0x9a9f48e5, 0xf719bbbf, 0xd39bea89,
+ 0xbdadf81f, 0x992fa929, 0xf4a95a73, 0xd02b0b45, 0x2fa4bcc7,
+ 0x0b26edf1, 0x66a01eab, 0x42224f9d, 0x42ce77ee, 0x664c26d8,
+ 0x0bcad582, 0x2f4884b4, 0xd0c73336, 0xf4456200, 0x99c3915a,
+ 0xbd41c06c, 0x981be1bc, 0xbc99b08a, 0xd11f43d0, 0xf59d12e6,
+ 0x0a12a564, 0x2e90f452, 0x43160708, 0x6794563e, 0x67786e4d,
+ 0x43fa3f7b, 0x2e7ccc21, 0x0afe9d17, 0xf5712a95, 0xd1f37ba3,
+ 0xbc7588f9, 0x98f7d9cf, 0x6019add5, 0x449bfce3, 0x291d0fb9,
+ 0x0d9f5e8f, 0xf210e90d, 0xd692b83b, 0xbb144b61, 0x9f961a57,
+ 0x9f7a2224, 0xbbf87312, 0xd67e8048, 0xf2fcd17e, 0x0d7366fc,
+ 0x29f137ca, 0x4477c490, 0x60f595a6, 0x45afb476, 0x612de540,
+ 0x0cab161a, 0x2829472c, 0xd7a6f0ae, 0xf324a198, 0x9ea252c2,
+ 0xba2003f4, 0xbacc3b87, 0x9e4e6ab1, 0xf3c899eb, 0xd74ac8dd,
+ 0x28c57f5f, 0x0c472e69, 0x61c1dd33, 0x45438c05, 0x2b759e93,
+ 0x0ff7cfa5, 0x62713cff, 0x46f36dc9, 0xb97cda4b, 0x9dfe8b7d,
+ 0xf0787827, 0xd4fa2911, 0xd4161162, 0xf0944054, 0x9d12b30e,
+ 0xb990e238, 0x461f55ba, 0x629d048c, 0x0f1bf7d6, 0x2b99a6e0,
+ 0x0ec38730, 0x2a41d606, 0x47c7255c, 0x6345746a, 0x9ccac3e8,
+ 0xb84892de, 0xd5ce6184, 0xf14c30b2, 0xf1a008c1, 0xd52259f7,
+ 0xb8a4aaad, 0x9c26fb9b, 0x63a94c19, 0x472b1d2f, 0x2aadee75,
+ 0x0e2fbf43},
+ {0x00000000, 0x36f290f3, 0x6de521e6, 0x5b17b115, 0xdbca43cc,
+ 0xed38d33f, 0xb62f622a, 0x80ddf2d9, 0x6ce581d9, 0x5a17112a,
+ 0x0100a03f, 0x37f230cc, 0xb72fc215, 0x81dd52e6, 0xdacae3f3,
+ 0xec387300, 0xd9cb03b2, 0xef399341, 0xb42e2254, 0x82dcb2a7,
+ 0x0201407e, 0x34f3d08d, 0x6fe46198, 0x5916f16b, 0xb52e826b,
+ 0x83dc1298, 0xd8cba38d, 0xee39337e, 0x6ee4c1a7, 0x58165154,
+ 0x0301e041, 0x35f370b2, 0x68e70125, 0x5e1591d6, 0x050220c3,
+ 0x33f0b030, 0xb32d42e9, 0x85dfd21a, 0xdec8630f, 0xe83af3fc,
+ 0x040280fc, 0x32f0100f, 0x69e7a11a, 0x5f1531e9, 0xdfc8c330,
+ 0xe93a53c3, 0xb22de2d6, 0x84df7225, 0xb12c0297, 0x87de9264,
+ 0xdcc92371, 0xea3bb382, 0x6ae6415b, 0x5c14d1a8, 0x070360bd,
+ 0x31f1f04e, 0xddc9834e, 0xeb3b13bd, 0xb02ca2a8, 0x86de325b,
+ 0x0603c082, 0x30f15071, 0x6be6e164, 0x5d147197, 0xd1ce024a,
+ 0xe73c92b9, 0xbc2b23ac, 0x8ad9b35f, 0x0a044186, 0x3cf6d175,
+ 0x67e16060, 0x5113f093, 0xbd2b8393, 0x8bd91360, 0xd0cea275,
+ 0xe63c3286, 0x66e1c05f, 0x501350ac, 0x0b04e1b9, 0x3df6714a,
+ 0x080501f8, 0x3ef7910b, 0x65e0201e, 0x5312b0ed, 0xd3cf4234,
+ 0xe53dd2c7, 0xbe2a63d2, 0x88d8f321, 0x64e08021, 0x521210d2,
+ 0x0905a1c7, 0x3ff73134, 0xbf2ac3ed, 0x89d8531e, 0xd2cfe20b,
+ 0xe43d72f8, 0xb929036f, 0x8fdb939c, 0xd4cc2289, 0xe23eb27a,
+ 0x62e340a3, 0x5411d050, 0x0f066145, 0x39f4f1b6, 0xd5cc82b6,
+ 0xe33e1245, 0xb829a350, 0x8edb33a3, 0x0e06c17a, 0x38f45189,
+ 0x63e3e09c, 0x5511706f, 0x60e200dd, 0x5610902e, 0x0d07213b,
+ 0x3bf5b1c8, 0xbb284311, 0x8ddad3e2, 0xd6cd62f7, 0xe03ff204,
+ 0x0c078104, 0x3af511f7, 0x61e2a0e2, 0x57103011, 0xd7cdc2c8,
+ 0xe13f523b, 0xba28e32e, 0x8cda73dd, 0x78ed02d5, 0x4e1f9226,
+ 0x15082333, 0x23fab3c0, 0xa3274119, 0x95d5d1ea, 0xcec260ff,
+ 0xf830f00c, 0x1408830c, 0x22fa13ff, 0x79eda2ea, 0x4f1f3219,
+ 0xcfc2c0c0, 0xf9305033, 0xa227e126, 0x94d571d5, 0xa1260167,
+ 0x97d49194, 0xccc32081, 0xfa31b072, 0x7aec42ab, 0x4c1ed258,
+ 0x1709634d, 0x21fbf3be, 0xcdc380be, 0xfb31104d, 0xa026a158,
+ 0x96d431ab, 0x1609c372, 0x20fb5381, 0x7bece294, 0x4d1e7267,
+ 0x100a03f0, 0x26f89303, 0x7def2216, 0x4b1db2e5, 0xcbc0403c,
+ 0xfd32d0cf, 0xa62561da, 0x90d7f129, 0x7cef8229, 0x4a1d12da,
+ 0x110aa3cf, 0x27f8333c, 0xa725c1e5, 0x91d75116, 0xcac0e003,
+ 0xfc3270f0, 0xc9c10042, 0xff3390b1, 0xa42421a4, 0x92d6b157,
+ 0x120b438e, 0x24f9d37d, 0x7fee6268, 0x491cf29b, 0xa524819b,
+ 0x93d61168, 0xc8c1a07d, 0xfe33308e, 0x7eeec257, 0x481c52a4,
+ 0x130be3b1, 0x25f97342, 0xa923009f, 0x9fd1906c, 0xc4c62179,
+ 0xf234b18a, 0x72e94353, 0x441bd3a0, 0x1f0c62b5, 0x29fef246,
+ 0xc5c68146, 0xf33411b5, 0xa823a0a0, 0x9ed13053, 0x1e0cc28a,
+ 0x28fe5279, 0x73e9e36c, 0x451b739f, 0x70e8032d, 0x461a93de,
+ 0x1d0d22cb, 0x2bffb238, 0xab2240e1, 0x9dd0d012, 0xc6c76107,
+ 0xf035f1f4, 0x1c0d82f4, 0x2aff1207, 0x71e8a312, 0x471a33e1,
+ 0xc7c7c138, 0xf13551cb, 0xaa22e0de, 0x9cd0702d, 0xc1c401ba,
+ 0xf7369149, 0xac21205c, 0x9ad3b0af, 0x1a0e4276, 0x2cfcd285,
+ 0x77eb6390, 0x4119f363, 0xad218063, 0x9bd31090, 0xc0c4a185,
+ 0xf6363176, 0x76ebc3af, 0x4019535c, 0x1b0ee249, 0x2dfc72ba,
+ 0x180f0208, 0x2efd92fb, 0x75ea23ee, 0x4318b31d, 0xc3c541c4,
+ 0xf537d137, 0xae206022, 0x98d2f0d1, 0x74ea83d1, 0x42181322,
+ 0x190fa237, 0x2ffd32c4, 0xaf20c01d, 0x99d250ee, 0xc2c5e1fb,
+ 0xf4377108}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xf390f23600000000, 0xe621e56d00000000,
+ 0x15b1175b00000000, 0xcc43cadb00000000, 0x3fd338ed00000000,
+ 0x2a622fb600000000, 0xd9f2dd8000000000, 0xd981e56c00000000,
+ 0x2a11175a00000000, 0x3fa0000100000000, 0xcc30f23700000000,
+ 0x15c22fb700000000, 0xe652dd8100000000, 0xf3e3cada00000000,
+ 0x007338ec00000000, 0xb203cbd900000000, 0x419339ef00000000,
+ 0x54222eb400000000, 0xa7b2dc8200000000, 0x7e40010200000000,
+ 0x8dd0f33400000000, 0x9861e46f00000000, 0x6bf1165900000000,
+ 0x6b822eb500000000, 0x9812dc8300000000, 0x8da3cbd800000000,
+ 0x7e3339ee00000000, 0xa7c1e46e00000000, 0x5451165800000000,
+ 0x41e0010300000000, 0xb270f33500000000, 0x2501e76800000000,
+ 0xd691155e00000000, 0xc320020500000000, 0x30b0f03300000000,
+ 0xe9422db300000000, 0x1ad2df8500000000, 0x0f63c8de00000000,
+ 0xfcf33ae800000000, 0xfc80020400000000, 0x0f10f03200000000,
+ 0x1aa1e76900000000, 0xe931155f00000000, 0x30c3c8df00000000,
+ 0xc3533ae900000000, 0xd6e22db200000000, 0x2572df8400000000,
+ 0x97022cb100000000, 0x6492de8700000000, 0x7123c9dc00000000,
+ 0x82b33bea00000000, 0x5b41e66a00000000, 0xa8d1145c00000000,
+ 0xbd60030700000000, 0x4ef0f13100000000, 0x4e83c9dd00000000,
+ 0xbd133beb00000000, 0xa8a22cb000000000, 0x5b32de8600000000,
+ 0x82c0030600000000, 0x7150f13000000000, 0x64e1e66b00000000,
+ 0x9771145d00000000, 0x4a02ced100000000, 0xb9923ce700000000,
+ 0xac232bbc00000000, 0x5fb3d98a00000000, 0x8641040a00000000,
+ 0x75d1f63c00000000, 0x6060e16700000000, 0x93f0135100000000,
+ 0x93832bbd00000000, 0x6013d98b00000000, 0x75a2ced000000000,
+ 0x86323ce600000000, 0x5fc0e16600000000, 0xac50135000000000,
+ 0xb9e1040b00000000, 0x4a71f63d00000000, 0xf801050800000000,
+ 0x0b91f73e00000000, 0x1e20e06500000000, 0xedb0125300000000,
+ 0x3442cfd300000000, 0xc7d23de500000000, 0xd2632abe00000000,
+ 0x21f3d88800000000, 0x2180e06400000000, 0xd210125200000000,
+ 0xc7a1050900000000, 0x3431f73f00000000, 0xedc32abf00000000,
+ 0x1e53d88900000000, 0x0be2cfd200000000, 0xf8723de400000000,
+ 0x6f0329b900000000, 0x9c93db8f00000000, 0x8922ccd400000000,
+ 0x7ab23ee200000000, 0xa340e36200000000, 0x50d0115400000000,
+ 0x4561060f00000000, 0xb6f1f43900000000, 0xb682ccd500000000,
+ 0x45123ee300000000, 0x50a329b800000000, 0xa333db8e00000000,
+ 0x7ac1060e00000000, 0x8951f43800000000, 0x9ce0e36300000000,
+ 0x6f70115500000000, 0xdd00e26000000000, 0x2e90105600000000,
+ 0x3b21070d00000000, 0xc8b1f53b00000000, 0x114328bb00000000,
+ 0xe2d3da8d00000000, 0xf762cdd600000000, 0x04f23fe000000000,
+ 0x0481070c00000000, 0xf711f53a00000000, 0xe2a0e26100000000,
+ 0x1130105700000000, 0xc8c2cdd700000000, 0x3b523fe100000000,
+ 0x2ee328ba00000000, 0xdd73da8c00000000, 0xd502ed7800000000,
+ 0x26921f4e00000000, 0x3323081500000000, 0xc0b3fa2300000000,
+ 0x194127a300000000, 0xead1d59500000000, 0xff60c2ce00000000,
+ 0x0cf030f800000000, 0x0c83081400000000, 0xff13fa2200000000,
+ 0xeaa2ed7900000000, 0x19321f4f00000000, 0xc0c0c2cf00000000,
+ 0x335030f900000000, 0x26e127a200000000, 0xd571d59400000000,
+ 0x670126a100000000, 0x9491d49700000000, 0x8120c3cc00000000,
+ 0x72b031fa00000000, 0xab42ec7a00000000, 0x58d21e4c00000000,
+ 0x4d63091700000000, 0xbef3fb2100000000, 0xbe80c3cd00000000,
+ 0x4d1031fb00000000, 0x58a126a000000000, 0xab31d49600000000,
+ 0x72c3091600000000, 0x8153fb2000000000, 0x94e2ec7b00000000,
+ 0x67721e4d00000000, 0xf0030a1000000000, 0x0393f82600000000,
+ 0x1622ef7d00000000, 0xe5b21d4b00000000, 0x3c40c0cb00000000,
+ 0xcfd032fd00000000, 0xda6125a600000000, 0x29f1d79000000000,
+ 0x2982ef7c00000000, 0xda121d4a00000000, 0xcfa30a1100000000,
+ 0x3c33f82700000000, 0xe5c125a700000000, 0x1651d79100000000,
+ 0x03e0c0ca00000000, 0xf07032fc00000000, 0x4200c1c900000000,
+ 0xb19033ff00000000, 0xa42124a400000000, 0x57b1d69200000000,
+ 0x8e430b1200000000, 0x7dd3f92400000000, 0x6862ee7f00000000,
+ 0x9bf21c4900000000, 0x9b8124a500000000, 0x6811d69300000000,
+ 0x7da0c1c800000000, 0x8e3033fe00000000, 0x57c2ee7e00000000,
+ 0xa4521c4800000000, 0xb1e30b1300000000, 0x4273f92500000000,
+ 0x9f0023a900000000, 0x6c90d19f00000000, 0x7921c6c400000000,
+ 0x8ab134f200000000, 0x5343e97200000000, 0xa0d31b4400000000,
+ 0xb5620c1f00000000, 0x46f2fe2900000000, 0x4681c6c500000000,
+ 0xb51134f300000000, 0xa0a023a800000000, 0x5330d19e00000000,
+ 0x8ac20c1e00000000, 0x7952fe2800000000, 0x6ce3e97300000000,
+ 0x9f731b4500000000, 0x2d03e87000000000, 0xde931a4600000000,
+ 0xcb220d1d00000000, 0x38b2ff2b00000000, 0xe14022ab00000000,
+ 0x12d0d09d00000000, 0x0761c7c600000000, 0xf4f135f000000000,
+ 0xf4820d1c00000000, 0x0712ff2a00000000, 0x12a3e87100000000,
+ 0xe1331a4700000000, 0x38c1c7c700000000, 0xcb5135f100000000,
+ 0xdee022aa00000000, 0x2d70d09c00000000, 0xba01c4c100000000,
+ 0x499136f700000000, 0x5c2021ac00000000, 0xafb0d39a00000000,
+ 0x76420e1a00000000, 0x85d2fc2c00000000, 0x9063eb7700000000,
+ 0x63f3194100000000, 0x638021ad00000000, 0x9010d39b00000000,
+ 0x85a1c4c000000000, 0x763136f600000000, 0xafc3eb7600000000,
+ 0x5c53194000000000, 0x49e20e1b00000000, 0xba72fc2d00000000,
+ 0x08020f1800000000, 0xfb92fd2e00000000, 0xee23ea7500000000,
+ 0x1db3184300000000, 0xc441c5c300000000, 0x37d137f500000000,
+ 0x226020ae00000000, 0xd1f0d29800000000, 0xd183ea7400000000,
+ 0x2213184200000000, 0x37a20f1900000000, 0xc432fd2f00000000,
+ 0x1dc020af00000000, 0xee50d29900000000, 0xfbe1c5c200000000,
+ 0x087137f400000000},
+ {0x0000000000000000, 0x3651822400000000, 0x6ca2044900000000,
+ 0x5af3866d00000000, 0xd844099200000000, 0xee158bb600000000,
+ 0xb4e60ddb00000000, 0x82b78fff00000000, 0xf18f63ff00000000,
+ 0xc7dee1db00000000, 0x9d2d67b600000000, 0xab7ce59200000000,
+ 0x29cb6a6d00000000, 0x1f9ae84900000000, 0x45696e2400000000,
+ 0x7338ec0000000000, 0xa319b62500000000, 0x9548340100000000,
+ 0xcfbbb26c00000000, 0xf9ea304800000000, 0x7b5dbfb700000000,
+ 0x4d0c3d9300000000, 0x17ffbbfe00000000, 0x21ae39da00000000,
+ 0x5296d5da00000000, 0x64c757fe00000000, 0x3e34d19300000000,
+ 0x086553b700000000, 0x8ad2dc4800000000, 0xbc835e6c00000000,
+ 0xe670d80100000000, 0xd0215a2500000000, 0x46336c4b00000000,
+ 0x7062ee6f00000000, 0x2a91680200000000, 0x1cc0ea2600000000,
+ 0x9e7765d900000000, 0xa826e7fd00000000, 0xf2d5619000000000,
+ 0xc484e3b400000000, 0xb7bc0fb400000000, 0x81ed8d9000000000,
+ 0xdb1e0bfd00000000, 0xed4f89d900000000, 0x6ff8062600000000,
+ 0x59a9840200000000, 0x035a026f00000000, 0x350b804b00000000,
+ 0xe52ada6e00000000, 0xd37b584a00000000, 0x8988de2700000000,
+ 0xbfd95c0300000000, 0x3d6ed3fc00000000, 0x0b3f51d800000000,
+ 0x51ccd7b500000000, 0x679d559100000000, 0x14a5b99100000000,
+ 0x22f43bb500000000, 0x7807bdd800000000, 0x4e563ffc00000000,
+ 0xcce1b00300000000, 0xfab0322700000000, 0xa043b44a00000000,
+ 0x9612366e00000000, 0x8c66d89600000000, 0xba375ab200000000,
+ 0xe0c4dcdf00000000, 0xd6955efb00000000, 0x5422d10400000000,
+ 0x6273532000000000, 0x3880d54d00000000, 0x0ed1576900000000,
+ 0x7de9bb6900000000, 0x4bb8394d00000000, 0x114bbf2000000000,
+ 0x271a3d0400000000, 0xa5adb2fb00000000, 0x93fc30df00000000,
+ 0xc90fb6b200000000, 0xff5e349600000000, 0x2f7f6eb300000000,
+ 0x192eec9700000000, 0x43dd6afa00000000, 0x758ce8de00000000,
+ 0xf73b672100000000, 0xc16ae50500000000, 0x9b99636800000000,
+ 0xadc8e14c00000000, 0xdef00d4c00000000, 0xe8a18f6800000000,
+ 0xb252090500000000, 0x84038b2100000000, 0x06b404de00000000,
+ 0x30e586fa00000000, 0x6a16009700000000, 0x5c4782b300000000,
+ 0xca55b4dd00000000, 0xfc0436f900000000, 0xa6f7b09400000000,
+ 0x90a632b000000000, 0x1211bd4f00000000, 0x24403f6b00000000,
+ 0x7eb3b90600000000, 0x48e23b2200000000, 0x3bdad72200000000,
+ 0x0d8b550600000000, 0x5778d36b00000000, 0x6129514f00000000,
+ 0xe39edeb000000000, 0xd5cf5c9400000000, 0x8f3cdaf900000000,
+ 0xb96d58dd00000000, 0x694c02f800000000, 0x5f1d80dc00000000,
+ 0x05ee06b100000000, 0x33bf849500000000, 0xb1080b6a00000000,
+ 0x8759894e00000000, 0xddaa0f2300000000, 0xebfb8d0700000000,
+ 0x98c3610700000000, 0xae92e32300000000, 0xf461654e00000000,
+ 0xc230e76a00000000, 0x4087689500000000, 0x76d6eab100000000,
+ 0x2c256cdc00000000, 0x1a74eef800000000, 0x59cbc1f600000000,
+ 0x6f9a43d200000000, 0x3569c5bf00000000, 0x0338479b00000000,
+ 0x818fc86400000000, 0xb7de4a4000000000, 0xed2dcc2d00000000,
+ 0xdb7c4e0900000000, 0xa844a20900000000, 0x9e15202d00000000,
+ 0xc4e6a64000000000, 0xf2b7246400000000, 0x7000ab9b00000000,
+ 0x465129bf00000000, 0x1ca2afd200000000, 0x2af32df600000000,
+ 0xfad277d300000000, 0xcc83f5f700000000, 0x9670739a00000000,
+ 0xa021f1be00000000, 0x22967e4100000000, 0x14c7fc6500000000,
+ 0x4e347a0800000000, 0x7865f82c00000000, 0x0b5d142c00000000,
+ 0x3d0c960800000000, 0x67ff106500000000, 0x51ae924100000000,
+ 0xd3191dbe00000000, 0xe5489f9a00000000, 0xbfbb19f700000000,
+ 0x89ea9bd300000000, 0x1ff8adbd00000000, 0x29a92f9900000000,
+ 0x735aa9f400000000, 0x450b2bd000000000, 0xc7bca42f00000000,
+ 0xf1ed260b00000000, 0xab1ea06600000000, 0x9d4f224200000000,
+ 0xee77ce4200000000, 0xd8264c6600000000, 0x82d5ca0b00000000,
+ 0xb484482f00000000, 0x3633c7d000000000, 0x006245f400000000,
+ 0x5a91c39900000000, 0x6cc041bd00000000, 0xbce11b9800000000,
+ 0x8ab099bc00000000, 0xd0431fd100000000, 0xe6129df500000000,
+ 0x64a5120a00000000, 0x52f4902e00000000, 0x0807164300000000,
+ 0x3e56946700000000, 0x4d6e786700000000, 0x7b3ffa4300000000,
+ 0x21cc7c2e00000000, 0x179dfe0a00000000, 0x952a71f500000000,
+ 0xa37bf3d100000000, 0xf98875bc00000000, 0xcfd9f79800000000,
+ 0xd5ad196000000000, 0xe3fc9b4400000000, 0xb90f1d2900000000,
+ 0x8f5e9f0d00000000, 0x0de910f200000000, 0x3bb892d600000000,
+ 0x614b14bb00000000, 0x571a969f00000000, 0x24227a9f00000000,
+ 0x1273f8bb00000000, 0x48807ed600000000, 0x7ed1fcf200000000,
+ 0xfc66730d00000000, 0xca37f12900000000, 0x90c4774400000000,
+ 0xa695f56000000000, 0x76b4af4500000000, 0x40e52d6100000000,
+ 0x1a16ab0c00000000, 0x2c47292800000000, 0xaef0a6d700000000,
+ 0x98a124f300000000, 0xc252a29e00000000, 0xf40320ba00000000,
+ 0x873bccba00000000, 0xb16a4e9e00000000, 0xeb99c8f300000000,
+ 0xddc84ad700000000, 0x5f7fc52800000000, 0x692e470c00000000,
+ 0x33ddc16100000000, 0x058c434500000000, 0x939e752b00000000,
+ 0xa5cff70f00000000, 0xff3c716200000000, 0xc96df34600000000,
+ 0x4bda7cb900000000, 0x7d8bfe9d00000000, 0x277878f000000000,
+ 0x1129fad400000000, 0x621116d400000000, 0x544094f000000000,
+ 0x0eb3129d00000000, 0x38e290b900000000, 0xba551f4600000000,
+ 0x8c049d6200000000, 0xd6f71b0f00000000, 0xe0a6992b00000000,
+ 0x3087c30e00000000, 0x06d6412a00000000, 0x5c25c74700000000,
+ 0x6a74456300000000, 0xe8c3ca9c00000000, 0xde9248b800000000,
+ 0x8461ced500000000, 0xb2304cf100000000, 0xc108a0f100000000,
+ 0xf75922d500000000, 0xadaaa4b800000000, 0x9bfb269c00000000,
+ 0x194ca96300000000, 0x2f1d2b4700000000, 0x75eead2a00000000,
+ 0x43bf2f0e00000000},
+ {0x0000000000000000, 0xc8179ecf00000000, 0xd1294d4400000000,
+ 0x193ed38b00000000, 0xa2539a8800000000, 0x6a44044700000000,
+ 0x737ad7cc00000000, 0xbb6d490300000000, 0x05a145ca00000000,
+ 0xcdb6db0500000000, 0xd488088e00000000, 0x1c9f964100000000,
+ 0xa7f2df4200000000, 0x6fe5418d00000000, 0x76db920600000000,
+ 0xbecc0cc900000000, 0x4b44fa4f00000000, 0x8353648000000000,
+ 0x9a6db70b00000000, 0x527a29c400000000, 0xe91760c700000000,
+ 0x2100fe0800000000, 0x383e2d8300000000, 0xf029b34c00000000,
+ 0x4ee5bf8500000000, 0x86f2214a00000000, 0x9fccf2c100000000,
+ 0x57db6c0e00000000, 0xecb6250d00000000, 0x24a1bbc200000000,
+ 0x3d9f684900000000, 0xf588f68600000000, 0x9688f49f00000000,
+ 0x5e9f6a5000000000, 0x47a1b9db00000000, 0x8fb6271400000000,
+ 0x34db6e1700000000, 0xfcccf0d800000000, 0xe5f2235300000000,
+ 0x2de5bd9c00000000, 0x9329b15500000000, 0x5b3e2f9a00000000,
+ 0x4200fc1100000000, 0x8a1762de00000000, 0x317a2bdd00000000,
+ 0xf96db51200000000, 0xe053669900000000, 0x2844f85600000000,
+ 0xddcc0ed000000000, 0x15db901f00000000, 0x0ce5439400000000,
+ 0xc4f2dd5b00000000, 0x7f9f945800000000, 0xb7880a9700000000,
+ 0xaeb6d91c00000000, 0x66a147d300000000, 0xd86d4b1a00000000,
+ 0x107ad5d500000000, 0x0944065e00000000, 0xc153989100000000,
+ 0x7a3ed19200000000, 0xb2294f5d00000000, 0xab179cd600000000,
+ 0x6300021900000000, 0x6d1798e400000000, 0xa500062b00000000,
+ 0xbc3ed5a000000000, 0x74294b6f00000000, 0xcf44026c00000000,
+ 0x07539ca300000000, 0x1e6d4f2800000000, 0xd67ad1e700000000,
+ 0x68b6dd2e00000000, 0xa0a143e100000000, 0xb99f906a00000000,
+ 0x71880ea500000000, 0xcae547a600000000, 0x02f2d96900000000,
+ 0x1bcc0ae200000000, 0xd3db942d00000000, 0x265362ab00000000,
+ 0xee44fc6400000000, 0xf77a2fef00000000, 0x3f6db12000000000,
+ 0x8400f82300000000, 0x4c1766ec00000000, 0x5529b56700000000,
+ 0x9d3e2ba800000000, 0x23f2276100000000, 0xebe5b9ae00000000,
+ 0xf2db6a2500000000, 0x3accf4ea00000000, 0x81a1bde900000000,
+ 0x49b6232600000000, 0x5088f0ad00000000, 0x989f6e6200000000,
+ 0xfb9f6c7b00000000, 0x3388f2b400000000, 0x2ab6213f00000000,
+ 0xe2a1bff000000000, 0x59ccf6f300000000, 0x91db683c00000000,
+ 0x88e5bbb700000000, 0x40f2257800000000, 0xfe3e29b100000000,
+ 0x3629b77e00000000, 0x2f1764f500000000, 0xe700fa3a00000000,
+ 0x5c6db33900000000, 0x947a2df600000000, 0x8d44fe7d00000000,
+ 0x455360b200000000, 0xb0db963400000000, 0x78cc08fb00000000,
+ 0x61f2db7000000000, 0xa9e545bf00000000, 0x12880cbc00000000,
+ 0xda9f927300000000, 0xc3a141f800000000, 0x0bb6df3700000000,
+ 0xb57ad3fe00000000, 0x7d6d4d3100000000, 0x64539eba00000000,
+ 0xac44007500000000, 0x1729497600000000, 0xdf3ed7b900000000,
+ 0xc600043200000000, 0x0e179afd00000000, 0x9b28411200000000,
+ 0x533fdfdd00000000, 0x4a010c5600000000, 0x8216929900000000,
+ 0x397bdb9a00000000, 0xf16c455500000000, 0xe85296de00000000,
+ 0x2045081100000000, 0x9e8904d800000000, 0x569e9a1700000000,
+ 0x4fa0499c00000000, 0x87b7d75300000000, 0x3cda9e5000000000,
+ 0xf4cd009f00000000, 0xedf3d31400000000, 0x25e44ddb00000000,
+ 0xd06cbb5d00000000, 0x187b259200000000, 0x0145f61900000000,
+ 0xc95268d600000000, 0x723f21d500000000, 0xba28bf1a00000000,
+ 0xa3166c9100000000, 0x6b01f25e00000000, 0xd5cdfe9700000000,
+ 0x1dda605800000000, 0x04e4b3d300000000, 0xccf32d1c00000000,
+ 0x779e641f00000000, 0xbf89fad000000000, 0xa6b7295b00000000,
+ 0x6ea0b79400000000, 0x0da0b58d00000000, 0xc5b72b4200000000,
+ 0xdc89f8c900000000, 0x149e660600000000, 0xaff32f0500000000,
+ 0x67e4b1ca00000000, 0x7eda624100000000, 0xb6cdfc8e00000000,
+ 0x0801f04700000000, 0xc0166e8800000000, 0xd928bd0300000000,
+ 0x113f23cc00000000, 0xaa526acf00000000, 0x6245f40000000000,
+ 0x7b7b278b00000000, 0xb36cb94400000000, 0x46e44fc200000000,
+ 0x8ef3d10d00000000, 0x97cd028600000000, 0x5fda9c4900000000,
+ 0xe4b7d54a00000000, 0x2ca04b8500000000, 0x359e980e00000000,
+ 0xfd8906c100000000, 0x43450a0800000000, 0x8b5294c700000000,
+ 0x926c474c00000000, 0x5a7bd98300000000, 0xe116908000000000,
+ 0x29010e4f00000000, 0x303fddc400000000, 0xf828430b00000000,
+ 0xf63fd9f600000000, 0x3e28473900000000, 0x271694b200000000,
+ 0xef010a7d00000000, 0x546c437e00000000, 0x9c7bddb100000000,
+ 0x85450e3a00000000, 0x4d5290f500000000, 0xf39e9c3c00000000,
+ 0x3b8902f300000000, 0x22b7d17800000000, 0xeaa04fb700000000,
+ 0x51cd06b400000000, 0x99da987b00000000, 0x80e44bf000000000,
+ 0x48f3d53f00000000, 0xbd7b23b900000000, 0x756cbd7600000000,
+ 0x6c526efd00000000, 0xa445f03200000000, 0x1f28b93100000000,
+ 0xd73f27fe00000000, 0xce01f47500000000, 0x06166aba00000000,
+ 0xb8da667300000000, 0x70cdf8bc00000000, 0x69f32b3700000000,
+ 0xa1e4b5f800000000, 0x1a89fcfb00000000, 0xd29e623400000000,
+ 0xcba0b1bf00000000, 0x03b72f7000000000, 0x60b72d6900000000,
+ 0xa8a0b3a600000000, 0xb19e602d00000000, 0x7989fee200000000,
+ 0xc2e4b7e100000000, 0x0af3292e00000000, 0x13cdfaa500000000,
+ 0xdbda646a00000000, 0x651668a300000000, 0xad01f66c00000000,
+ 0xb43f25e700000000, 0x7c28bb2800000000, 0xc745f22b00000000,
+ 0x0f526ce400000000, 0x166cbf6f00000000, 0xde7b21a000000000,
+ 0x2bf3d72600000000, 0xe3e449e900000000, 0xfada9a6200000000,
+ 0x32cd04ad00000000, 0x89a04dae00000000, 0x41b7d36100000000,
+ 0x588900ea00000000, 0x909e9e2500000000, 0x2e5292ec00000000,
+ 0xe6450c2300000000, 0xff7bdfa800000000, 0x376c416700000000,
+ 0x8c01086400000000, 0x441696ab00000000, 0x5d28452000000000,
+ 0x953fdbef00000000},
+ {0x0000000000000000, 0x95d4709500000000, 0x6baf90f100000000,
+ 0xfe7be06400000000, 0x9758503800000000, 0x028c20ad00000000,
+ 0xfcf7c0c900000000, 0x6923b05c00000000, 0x2eb1a07000000000,
+ 0xbb65d0e500000000, 0x451e308100000000, 0xd0ca401400000000,
+ 0xb9e9f04800000000, 0x2c3d80dd00000000, 0xd24660b900000000,
+ 0x4792102c00000000, 0x5c6241e100000000, 0xc9b6317400000000,
+ 0x37cdd11000000000, 0xa219a18500000000, 0xcb3a11d900000000,
+ 0x5eee614c00000000, 0xa095812800000000, 0x3541f1bd00000000,
+ 0x72d3e19100000000, 0xe707910400000000, 0x197c716000000000,
+ 0x8ca801f500000000, 0xe58bb1a900000000, 0x705fc13c00000000,
+ 0x8e24215800000000, 0x1bf051cd00000000, 0xf9c2f31900000000,
+ 0x6c16838c00000000, 0x926d63e800000000, 0x07b9137d00000000,
+ 0x6e9aa32100000000, 0xfb4ed3b400000000, 0x053533d000000000,
+ 0x90e1434500000000, 0xd773536900000000, 0x42a723fc00000000,
+ 0xbcdcc39800000000, 0x2908b30d00000000, 0x402b035100000000,
+ 0xd5ff73c400000000, 0x2b8493a000000000, 0xbe50e33500000000,
+ 0xa5a0b2f800000000, 0x3074c26d00000000, 0xce0f220900000000,
+ 0x5bdb529c00000000, 0x32f8e2c000000000, 0xa72c925500000000,
+ 0x5957723100000000, 0xcc8302a400000000, 0x8b11128800000000,
+ 0x1ec5621d00000000, 0xe0be827900000000, 0x756af2ec00000000,
+ 0x1c4942b000000000, 0x899d322500000000, 0x77e6d24100000000,
+ 0xe232a2d400000000, 0xf285e73300000000, 0x675197a600000000,
+ 0x992a77c200000000, 0x0cfe075700000000, 0x65ddb70b00000000,
+ 0xf009c79e00000000, 0x0e7227fa00000000, 0x9ba6576f00000000,
+ 0xdc34474300000000, 0x49e037d600000000, 0xb79bd7b200000000,
+ 0x224fa72700000000, 0x4b6c177b00000000, 0xdeb867ee00000000,
+ 0x20c3878a00000000, 0xb517f71f00000000, 0xaee7a6d200000000,
+ 0x3b33d64700000000, 0xc548362300000000, 0x509c46b600000000,
+ 0x39bff6ea00000000, 0xac6b867f00000000, 0x5210661b00000000,
+ 0xc7c4168e00000000, 0x805606a200000000, 0x1582763700000000,
+ 0xebf9965300000000, 0x7e2de6c600000000, 0x170e569a00000000,
+ 0x82da260f00000000, 0x7ca1c66b00000000, 0xe975b6fe00000000,
+ 0x0b47142a00000000, 0x9e9364bf00000000, 0x60e884db00000000,
+ 0xf53cf44e00000000, 0x9c1f441200000000, 0x09cb348700000000,
+ 0xf7b0d4e300000000, 0x6264a47600000000, 0x25f6b45a00000000,
+ 0xb022c4cf00000000, 0x4e5924ab00000000, 0xdb8d543e00000000,
+ 0xb2aee46200000000, 0x277a94f700000000, 0xd901749300000000,
+ 0x4cd5040600000000, 0x572555cb00000000, 0xc2f1255e00000000,
+ 0x3c8ac53a00000000, 0xa95eb5af00000000, 0xc07d05f300000000,
+ 0x55a9756600000000, 0xabd2950200000000, 0x3e06e59700000000,
+ 0x7994f5bb00000000, 0xec40852e00000000, 0x123b654a00000000,
+ 0x87ef15df00000000, 0xeecca58300000000, 0x7b18d51600000000,
+ 0x8563357200000000, 0x10b745e700000000, 0xe40bcf6700000000,
+ 0x71dfbff200000000, 0x8fa45f9600000000, 0x1a702f0300000000,
+ 0x73539f5f00000000, 0xe687efca00000000, 0x18fc0fae00000000,
+ 0x8d287f3b00000000, 0xcaba6f1700000000, 0x5f6e1f8200000000,
+ 0xa115ffe600000000, 0x34c18f7300000000, 0x5de23f2f00000000,
+ 0xc8364fba00000000, 0x364dafde00000000, 0xa399df4b00000000,
+ 0xb8698e8600000000, 0x2dbdfe1300000000, 0xd3c61e7700000000,
+ 0x46126ee200000000, 0x2f31debe00000000, 0xbae5ae2b00000000,
+ 0x449e4e4f00000000, 0xd14a3eda00000000, 0x96d82ef600000000,
+ 0x030c5e6300000000, 0xfd77be0700000000, 0x68a3ce9200000000,
+ 0x01807ece00000000, 0x94540e5b00000000, 0x6a2fee3f00000000,
+ 0xfffb9eaa00000000, 0x1dc93c7e00000000, 0x881d4ceb00000000,
+ 0x7666ac8f00000000, 0xe3b2dc1a00000000, 0x8a916c4600000000,
+ 0x1f451cd300000000, 0xe13efcb700000000, 0x74ea8c2200000000,
+ 0x33789c0e00000000, 0xa6acec9b00000000, 0x58d70cff00000000,
+ 0xcd037c6a00000000, 0xa420cc3600000000, 0x31f4bca300000000,
+ 0xcf8f5cc700000000, 0x5a5b2c5200000000, 0x41ab7d9f00000000,
+ 0xd47f0d0a00000000, 0x2a04ed6e00000000, 0xbfd09dfb00000000,
+ 0xd6f32da700000000, 0x43275d3200000000, 0xbd5cbd5600000000,
+ 0x2888cdc300000000, 0x6f1addef00000000, 0xfacead7a00000000,
+ 0x04b54d1e00000000, 0x91613d8b00000000, 0xf8428dd700000000,
+ 0x6d96fd4200000000, 0x93ed1d2600000000, 0x06396db300000000,
+ 0x168e285400000000, 0x835a58c100000000, 0x7d21b8a500000000,
+ 0xe8f5c83000000000, 0x81d6786c00000000, 0x140208f900000000,
+ 0xea79e89d00000000, 0x7fad980800000000, 0x383f882400000000,
+ 0xadebf8b100000000, 0x539018d500000000, 0xc644684000000000,
+ 0xaf67d81c00000000, 0x3ab3a88900000000, 0xc4c848ed00000000,
+ 0x511c387800000000, 0x4aec69b500000000, 0xdf38192000000000,
+ 0x2143f94400000000, 0xb49789d100000000, 0xddb4398d00000000,
+ 0x4860491800000000, 0xb61ba97c00000000, 0x23cfd9e900000000,
+ 0x645dc9c500000000, 0xf189b95000000000, 0x0ff2593400000000,
+ 0x9a2629a100000000, 0xf30599fd00000000, 0x66d1e96800000000,
+ 0x98aa090c00000000, 0x0d7e799900000000, 0xef4cdb4d00000000,
+ 0x7a98abd800000000, 0x84e34bbc00000000, 0x11373b2900000000,
+ 0x78148b7500000000, 0xedc0fbe000000000, 0x13bb1b8400000000,
+ 0x866f6b1100000000, 0xc1fd7b3d00000000, 0x54290ba800000000,
+ 0xaa52ebcc00000000, 0x3f869b5900000000, 0x56a52b0500000000,
+ 0xc3715b9000000000, 0x3d0abbf400000000, 0xa8decb6100000000,
+ 0xb32e9aac00000000, 0x26faea3900000000, 0xd8810a5d00000000,
+ 0x4d557ac800000000, 0x2476ca9400000000, 0xb1a2ba0100000000,
+ 0x4fd95a6500000000, 0xda0d2af000000000, 0x9d9f3adc00000000,
+ 0x084b4a4900000000, 0xf630aa2d00000000, 0x63e4dab800000000,
+ 0x0ac76ae400000000, 0x9f131a7100000000, 0x6168fa1500000000,
+ 0xf4bc8a8000000000},
+ {0x0000000000000000, 0x1f17f08000000000, 0x7f2891da00000000,
+ 0x603f615a00000000, 0xbf56536e00000000, 0xa041a3ee00000000,
+ 0xc07ec2b400000000, 0xdf69323400000000, 0x7eada6dc00000000,
+ 0x61ba565c00000000, 0x0185370600000000, 0x1e92c78600000000,
+ 0xc1fbf5b200000000, 0xdeec053200000000, 0xbed3646800000000,
+ 0xa1c494e800000000, 0xbd5c3c6200000000, 0xa24bcce200000000,
+ 0xc274adb800000000, 0xdd635d3800000000, 0x020a6f0c00000000,
+ 0x1d1d9f8c00000000, 0x7d22fed600000000, 0x62350e5600000000,
+ 0xc3f19abe00000000, 0xdce66a3e00000000, 0xbcd90b6400000000,
+ 0xa3cefbe400000000, 0x7ca7c9d000000000, 0x63b0395000000000,
+ 0x038f580a00000000, 0x1c98a88a00000000, 0x7ab978c400000000,
+ 0x65ae884400000000, 0x0591e91e00000000, 0x1a86199e00000000,
+ 0xc5ef2baa00000000, 0xdaf8db2a00000000, 0xbac7ba7000000000,
+ 0xa5d04af000000000, 0x0414de1800000000, 0x1b032e9800000000,
+ 0x7b3c4fc200000000, 0x642bbf4200000000, 0xbb428d7600000000,
+ 0xa4557df600000000, 0xc46a1cac00000000, 0xdb7dec2c00000000,
+ 0xc7e544a600000000, 0xd8f2b42600000000, 0xb8cdd57c00000000,
+ 0xa7da25fc00000000, 0x78b317c800000000, 0x67a4e74800000000,
+ 0x079b861200000000, 0x188c769200000000, 0xb948e27a00000000,
+ 0xa65f12fa00000000, 0xc66073a000000000, 0xd977832000000000,
+ 0x061eb11400000000, 0x1909419400000000, 0x793620ce00000000,
+ 0x6621d04e00000000, 0xb574805300000000, 0xaa6370d300000000,
+ 0xca5c118900000000, 0xd54be10900000000, 0x0a22d33d00000000,
+ 0x153523bd00000000, 0x750a42e700000000, 0x6a1db26700000000,
+ 0xcbd9268f00000000, 0xd4ced60f00000000, 0xb4f1b75500000000,
+ 0xabe647d500000000, 0x748f75e100000000, 0x6b98856100000000,
+ 0x0ba7e43b00000000, 0x14b014bb00000000, 0x0828bc3100000000,
+ 0x173f4cb100000000, 0x77002deb00000000, 0x6817dd6b00000000,
+ 0xb77eef5f00000000, 0xa8691fdf00000000, 0xc8567e8500000000,
+ 0xd7418e0500000000, 0x76851aed00000000, 0x6992ea6d00000000,
+ 0x09ad8b3700000000, 0x16ba7bb700000000, 0xc9d3498300000000,
+ 0xd6c4b90300000000, 0xb6fbd85900000000, 0xa9ec28d900000000,
+ 0xcfcdf89700000000, 0xd0da081700000000, 0xb0e5694d00000000,
+ 0xaff299cd00000000, 0x709babf900000000, 0x6f8c5b7900000000,
+ 0x0fb33a2300000000, 0x10a4caa300000000, 0xb1605e4b00000000,
+ 0xae77aecb00000000, 0xce48cf9100000000, 0xd15f3f1100000000,
+ 0x0e360d2500000000, 0x1121fda500000000, 0x711e9cff00000000,
+ 0x6e096c7f00000000, 0x7291c4f500000000, 0x6d86347500000000,
+ 0x0db9552f00000000, 0x12aea5af00000000, 0xcdc7979b00000000,
+ 0xd2d0671b00000000, 0xb2ef064100000000, 0xadf8f6c100000000,
+ 0x0c3c622900000000, 0x132b92a900000000, 0x7314f3f300000000,
+ 0x6c03037300000000, 0xb36a314700000000, 0xac7dc1c700000000,
+ 0xcc42a09d00000000, 0xd355501d00000000, 0x6ae900a700000000,
+ 0x75fef02700000000, 0x15c1917d00000000, 0x0ad661fd00000000,
+ 0xd5bf53c900000000, 0xcaa8a34900000000, 0xaa97c21300000000,
+ 0xb580329300000000, 0x1444a67b00000000, 0x0b5356fb00000000,
+ 0x6b6c37a100000000, 0x747bc72100000000, 0xab12f51500000000,
+ 0xb405059500000000, 0xd43a64cf00000000, 0xcb2d944f00000000,
+ 0xd7b53cc500000000, 0xc8a2cc4500000000, 0xa89dad1f00000000,
+ 0xb78a5d9f00000000, 0x68e36fab00000000, 0x77f49f2b00000000,
+ 0x17cbfe7100000000, 0x08dc0ef100000000, 0xa9189a1900000000,
+ 0xb60f6a9900000000, 0xd6300bc300000000, 0xc927fb4300000000,
+ 0x164ec97700000000, 0x095939f700000000, 0x696658ad00000000,
+ 0x7671a82d00000000, 0x1050786300000000, 0x0f4788e300000000,
+ 0x6f78e9b900000000, 0x706f193900000000, 0xaf062b0d00000000,
+ 0xb011db8d00000000, 0xd02ebad700000000, 0xcf394a5700000000,
+ 0x6efddebf00000000, 0x71ea2e3f00000000, 0x11d54f6500000000,
+ 0x0ec2bfe500000000, 0xd1ab8dd100000000, 0xcebc7d5100000000,
+ 0xae831c0b00000000, 0xb194ec8b00000000, 0xad0c440100000000,
+ 0xb21bb48100000000, 0xd224d5db00000000, 0xcd33255b00000000,
+ 0x125a176f00000000, 0x0d4de7ef00000000, 0x6d7286b500000000,
+ 0x7265763500000000, 0xd3a1e2dd00000000, 0xccb6125d00000000,
+ 0xac89730700000000, 0xb39e838700000000, 0x6cf7b1b300000000,
+ 0x73e0413300000000, 0x13df206900000000, 0x0cc8d0e900000000,
+ 0xdf9d80f400000000, 0xc08a707400000000, 0xa0b5112e00000000,
+ 0xbfa2e1ae00000000, 0x60cbd39a00000000, 0x7fdc231a00000000,
+ 0x1fe3424000000000, 0x00f4b2c000000000, 0xa130262800000000,
+ 0xbe27d6a800000000, 0xde18b7f200000000, 0xc10f477200000000,
+ 0x1e66754600000000, 0x017185c600000000, 0x614ee49c00000000,
+ 0x7e59141c00000000, 0x62c1bc9600000000, 0x7dd64c1600000000,
+ 0x1de92d4c00000000, 0x02feddcc00000000, 0xdd97eff800000000,
+ 0xc2801f7800000000, 0xa2bf7e2200000000, 0xbda88ea200000000,
+ 0x1c6c1a4a00000000, 0x037beaca00000000, 0x63448b9000000000,
+ 0x7c537b1000000000, 0xa33a492400000000, 0xbc2db9a400000000,
+ 0xdc12d8fe00000000, 0xc305287e00000000, 0xa524f83000000000,
+ 0xba3308b000000000, 0xda0c69ea00000000, 0xc51b996a00000000,
+ 0x1a72ab5e00000000, 0x05655bde00000000, 0x655a3a8400000000,
+ 0x7a4dca0400000000, 0xdb895eec00000000, 0xc49eae6c00000000,
+ 0xa4a1cf3600000000, 0xbbb63fb600000000, 0x64df0d8200000000,
+ 0x7bc8fd0200000000, 0x1bf79c5800000000, 0x04e06cd800000000,
+ 0x1878c45200000000, 0x076f34d200000000, 0x6750558800000000,
+ 0x7847a50800000000, 0xa72e973c00000000, 0xb83967bc00000000,
+ 0xd80606e600000000, 0xc711f66600000000, 0x66d5628e00000000,
+ 0x79c2920e00000000, 0x19fdf35400000000, 0x06ea03d400000000,
+ 0xd98331e000000000, 0xc694c16000000000, 0xa6aba03a00000000,
+ 0xb9bc50ba00000000},
+ {0x0000000000000000, 0xe2fd888d00000000, 0x85fd60c000000000,
+ 0x6700e84d00000000, 0x4bfdb05b00000000, 0xa90038d600000000,
+ 0xce00d09b00000000, 0x2cfd581600000000, 0x96fa61b700000000,
+ 0x7407e93a00000000, 0x1307017700000000, 0xf1fa89fa00000000,
+ 0xdd07d1ec00000000, 0x3ffa596100000000, 0x58fab12c00000000,
+ 0xba0739a100000000, 0x6df3b2b500000000, 0x8f0e3a3800000000,
+ 0xe80ed27500000000, 0x0af35af800000000, 0x260e02ee00000000,
+ 0xc4f38a6300000000, 0xa3f3622e00000000, 0x410eeaa300000000,
+ 0xfb09d30200000000, 0x19f45b8f00000000, 0x7ef4b3c200000000,
+ 0x9c093b4f00000000, 0xb0f4635900000000, 0x5209ebd400000000,
+ 0x3509039900000000, 0xd7f48b1400000000, 0x9be014b000000000,
+ 0x791d9c3d00000000, 0x1e1d747000000000, 0xfce0fcfd00000000,
+ 0xd01da4eb00000000, 0x32e02c6600000000, 0x55e0c42b00000000,
+ 0xb71d4ca600000000, 0x0d1a750700000000, 0xefe7fd8a00000000,
+ 0x88e715c700000000, 0x6a1a9d4a00000000, 0x46e7c55c00000000,
+ 0xa41a4dd100000000, 0xc31aa59c00000000, 0x21e72d1100000000,
+ 0xf613a60500000000, 0x14ee2e8800000000, 0x73eec6c500000000,
+ 0x91134e4800000000, 0xbdee165e00000000, 0x5f139ed300000000,
+ 0x3813769e00000000, 0xdaeefe1300000000, 0x60e9c7b200000000,
+ 0x82144f3f00000000, 0xe514a77200000000, 0x07e92fff00000000,
+ 0x2b1477e900000000, 0xc9e9ff6400000000, 0xaee9172900000000,
+ 0x4c149fa400000000, 0x77c758bb00000000, 0x953ad03600000000,
+ 0xf23a387b00000000, 0x10c7b0f600000000, 0x3c3ae8e000000000,
+ 0xdec7606d00000000, 0xb9c7882000000000, 0x5b3a00ad00000000,
+ 0xe13d390c00000000, 0x03c0b18100000000, 0x64c059cc00000000,
+ 0x863dd14100000000, 0xaac0895700000000, 0x483d01da00000000,
+ 0x2f3de99700000000, 0xcdc0611a00000000, 0x1a34ea0e00000000,
+ 0xf8c9628300000000, 0x9fc98ace00000000, 0x7d34024300000000,
+ 0x51c95a5500000000, 0xb334d2d800000000, 0xd4343a9500000000,
+ 0x36c9b21800000000, 0x8cce8bb900000000, 0x6e33033400000000,
+ 0x0933eb7900000000, 0xebce63f400000000, 0xc7333be200000000,
+ 0x25ceb36f00000000, 0x42ce5b2200000000, 0xa033d3af00000000,
+ 0xec274c0b00000000, 0x0edac48600000000, 0x69da2ccb00000000,
+ 0x8b27a44600000000, 0xa7dafc5000000000, 0x452774dd00000000,
+ 0x22279c9000000000, 0xc0da141d00000000, 0x7add2dbc00000000,
+ 0x9820a53100000000, 0xff204d7c00000000, 0x1dddc5f100000000,
+ 0x31209de700000000, 0xd3dd156a00000000, 0xb4ddfd2700000000,
+ 0x562075aa00000000, 0x81d4febe00000000, 0x6329763300000000,
+ 0x04299e7e00000000, 0xe6d416f300000000, 0xca294ee500000000,
+ 0x28d4c66800000000, 0x4fd42e2500000000, 0xad29a6a800000000,
+ 0x172e9f0900000000, 0xf5d3178400000000, 0x92d3ffc900000000,
+ 0x702e774400000000, 0x5cd32f5200000000, 0xbe2ea7df00000000,
+ 0xd92e4f9200000000, 0x3bd3c71f00000000, 0xaf88c0ad00000000,
+ 0x4d75482000000000, 0x2a75a06d00000000, 0xc88828e000000000,
+ 0xe47570f600000000, 0x0688f87b00000000, 0x6188103600000000,
+ 0x837598bb00000000, 0x3972a11a00000000, 0xdb8f299700000000,
+ 0xbc8fc1da00000000, 0x5e72495700000000, 0x728f114100000000,
+ 0x907299cc00000000, 0xf772718100000000, 0x158ff90c00000000,
+ 0xc27b721800000000, 0x2086fa9500000000, 0x478612d800000000,
+ 0xa57b9a5500000000, 0x8986c24300000000, 0x6b7b4ace00000000,
+ 0x0c7ba28300000000, 0xee862a0e00000000, 0x548113af00000000,
+ 0xb67c9b2200000000, 0xd17c736f00000000, 0x3381fbe200000000,
+ 0x1f7ca3f400000000, 0xfd812b7900000000, 0x9a81c33400000000,
+ 0x787c4bb900000000, 0x3468d41d00000000, 0xd6955c9000000000,
+ 0xb195b4dd00000000, 0x53683c5000000000, 0x7f95644600000000,
+ 0x9d68eccb00000000, 0xfa68048600000000, 0x18958c0b00000000,
+ 0xa292b5aa00000000, 0x406f3d2700000000, 0x276fd56a00000000,
+ 0xc5925de700000000, 0xe96f05f100000000, 0x0b928d7c00000000,
+ 0x6c92653100000000, 0x8e6fedbc00000000, 0x599b66a800000000,
+ 0xbb66ee2500000000, 0xdc66066800000000, 0x3e9b8ee500000000,
+ 0x1266d6f300000000, 0xf09b5e7e00000000, 0x979bb63300000000,
+ 0x75663ebe00000000, 0xcf61071f00000000, 0x2d9c8f9200000000,
+ 0x4a9c67df00000000, 0xa861ef5200000000, 0x849cb74400000000,
+ 0x66613fc900000000, 0x0161d78400000000, 0xe39c5f0900000000,
+ 0xd84f981600000000, 0x3ab2109b00000000, 0x5db2f8d600000000,
+ 0xbf4f705b00000000, 0x93b2284d00000000, 0x714fa0c000000000,
+ 0x164f488d00000000, 0xf4b2c00000000000, 0x4eb5f9a100000000,
+ 0xac48712c00000000, 0xcb48996100000000, 0x29b511ec00000000,
+ 0x054849fa00000000, 0xe7b5c17700000000, 0x80b5293a00000000,
+ 0x6248a1b700000000, 0xb5bc2aa300000000, 0x5741a22e00000000,
+ 0x30414a6300000000, 0xd2bcc2ee00000000, 0xfe419af800000000,
+ 0x1cbc127500000000, 0x7bbcfa3800000000, 0x994172b500000000,
+ 0x23464b1400000000, 0xc1bbc39900000000, 0xa6bb2bd400000000,
+ 0x4446a35900000000, 0x68bbfb4f00000000, 0x8a4673c200000000,
+ 0xed469b8f00000000, 0x0fbb130200000000, 0x43af8ca600000000,
+ 0xa152042b00000000, 0xc652ec6600000000, 0x24af64eb00000000,
+ 0x08523cfd00000000, 0xeaafb47000000000, 0x8daf5c3d00000000,
+ 0x6f52d4b000000000, 0xd555ed1100000000, 0x37a8659c00000000,
+ 0x50a88dd100000000, 0xb255055c00000000, 0x9ea85d4a00000000,
+ 0x7c55d5c700000000, 0x1b553d8a00000000, 0xf9a8b50700000000,
+ 0x2e5c3e1300000000, 0xcca1b69e00000000, 0xaba15ed300000000,
+ 0x495cd65e00000000, 0x65a18e4800000000, 0x875c06c500000000,
+ 0xe05cee8800000000, 0x02a1660500000000, 0xb8a65fa400000000,
+ 0x5a5bd72900000000, 0x3d5b3f6400000000, 0xdfa6b7e900000000,
+ 0xf35befff00000000, 0x11a6677200000000, 0x76a68f3f00000000,
+ 0x945b07b200000000},
+ {0x0000000000000000, 0xa90b894e00000000, 0x5217129d00000000,
+ 0xfb1c9bd300000000, 0xe52855e100000000, 0x4c23dcaf00000000,
+ 0xb73f477c00000000, 0x1e34ce3200000000, 0x8b57db1900000000,
+ 0x225c525700000000, 0xd940c98400000000, 0x704b40ca00000000,
+ 0x6e7f8ef800000000, 0xc77407b600000000, 0x3c689c6500000000,
+ 0x9563152b00000000, 0x16afb63300000000, 0xbfa43f7d00000000,
+ 0x44b8a4ae00000000, 0xedb32de000000000, 0xf387e3d200000000,
+ 0x5a8c6a9c00000000, 0xa190f14f00000000, 0x089b780100000000,
+ 0x9df86d2a00000000, 0x34f3e46400000000, 0xcfef7fb700000000,
+ 0x66e4f6f900000000, 0x78d038cb00000000, 0xd1dbb18500000000,
+ 0x2ac72a5600000000, 0x83cca31800000000, 0x2c5e6d6700000000,
+ 0x8555e42900000000, 0x7e497ffa00000000, 0xd742f6b400000000,
+ 0xc976388600000000, 0x607db1c800000000, 0x9b612a1b00000000,
+ 0x326aa35500000000, 0xa709b67e00000000, 0x0e023f3000000000,
+ 0xf51ea4e300000000, 0x5c152dad00000000, 0x4221e39f00000000,
+ 0xeb2a6ad100000000, 0x1036f10200000000, 0xb93d784c00000000,
+ 0x3af1db5400000000, 0x93fa521a00000000, 0x68e6c9c900000000,
+ 0xc1ed408700000000, 0xdfd98eb500000000, 0x76d207fb00000000,
+ 0x8dce9c2800000000, 0x24c5156600000000, 0xb1a6004d00000000,
+ 0x18ad890300000000, 0xe3b112d000000000, 0x4aba9b9e00000000,
+ 0x548e55ac00000000, 0xfd85dce200000000, 0x0699473100000000,
+ 0xaf92ce7f00000000, 0x58bcdace00000000, 0xf1b7538000000000,
+ 0x0aabc85300000000, 0xa3a0411d00000000, 0xbd948f2f00000000,
+ 0x149f066100000000, 0xef839db200000000, 0x468814fc00000000,
+ 0xd3eb01d700000000, 0x7ae0889900000000, 0x81fc134a00000000,
+ 0x28f79a0400000000, 0x36c3543600000000, 0x9fc8dd7800000000,
+ 0x64d446ab00000000, 0xcddfcfe500000000, 0x4e136cfd00000000,
+ 0xe718e5b300000000, 0x1c047e6000000000, 0xb50ff72e00000000,
+ 0xab3b391c00000000, 0x0230b05200000000, 0xf92c2b8100000000,
+ 0x5027a2cf00000000, 0xc544b7e400000000, 0x6c4f3eaa00000000,
+ 0x9753a57900000000, 0x3e582c3700000000, 0x206ce20500000000,
+ 0x89676b4b00000000, 0x727bf09800000000, 0xdb7079d600000000,
+ 0x74e2b7a900000000, 0xdde93ee700000000, 0x26f5a53400000000,
+ 0x8ffe2c7a00000000, 0x91cae24800000000, 0x38c16b0600000000,
+ 0xc3ddf0d500000000, 0x6ad6799b00000000, 0xffb56cb000000000,
+ 0x56bee5fe00000000, 0xada27e2d00000000, 0x04a9f76300000000,
+ 0x1a9d395100000000, 0xb396b01f00000000, 0x488a2bcc00000000,
+ 0xe181a28200000000, 0x624d019a00000000, 0xcb4688d400000000,
+ 0x305a130700000000, 0x99519a4900000000, 0x8765547b00000000,
+ 0x2e6edd3500000000, 0xd57246e600000000, 0x7c79cfa800000000,
+ 0xe91ada8300000000, 0x401153cd00000000, 0xbb0dc81e00000000,
+ 0x1206415000000000, 0x0c328f6200000000, 0xa539062c00000000,
+ 0x5e259dff00000000, 0xf72e14b100000000, 0xf17ec44600000000,
+ 0x58754d0800000000, 0xa369d6db00000000, 0x0a625f9500000000,
+ 0x145691a700000000, 0xbd5d18e900000000, 0x4641833a00000000,
+ 0xef4a0a7400000000, 0x7a291f5f00000000, 0xd322961100000000,
+ 0x283e0dc200000000, 0x8135848c00000000, 0x9f014abe00000000,
+ 0x360ac3f000000000, 0xcd16582300000000, 0x641dd16d00000000,
+ 0xe7d1727500000000, 0x4edafb3b00000000, 0xb5c660e800000000,
+ 0x1ccde9a600000000, 0x02f9279400000000, 0xabf2aeda00000000,
+ 0x50ee350900000000, 0xf9e5bc4700000000, 0x6c86a96c00000000,
+ 0xc58d202200000000, 0x3e91bbf100000000, 0x979a32bf00000000,
+ 0x89aefc8d00000000, 0x20a575c300000000, 0xdbb9ee1000000000,
+ 0x72b2675e00000000, 0xdd20a92100000000, 0x742b206f00000000,
+ 0x8f37bbbc00000000, 0x263c32f200000000, 0x3808fcc000000000,
+ 0x9103758e00000000, 0x6a1fee5d00000000, 0xc314671300000000,
+ 0x5677723800000000, 0xff7cfb7600000000, 0x046060a500000000,
+ 0xad6be9eb00000000, 0xb35f27d900000000, 0x1a54ae9700000000,
+ 0xe148354400000000, 0x4843bc0a00000000, 0xcb8f1f1200000000,
+ 0x6284965c00000000, 0x99980d8f00000000, 0x309384c100000000,
+ 0x2ea74af300000000, 0x87acc3bd00000000, 0x7cb0586e00000000,
+ 0xd5bbd12000000000, 0x40d8c40b00000000, 0xe9d34d4500000000,
+ 0x12cfd69600000000, 0xbbc45fd800000000, 0xa5f091ea00000000,
+ 0x0cfb18a400000000, 0xf7e7837700000000, 0x5eec0a3900000000,
+ 0xa9c21e8800000000, 0x00c997c600000000, 0xfbd50c1500000000,
+ 0x52de855b00000000, 0x4cea4b6900000000, 0xe5e1c22700000000,
+ 0x1efd59f400000000, 0xb7f6d0ba00000000, 0x2295c59100000000,
+ 0x8b9e4cdf00000000, 0x7082d70c00000000, 0xd9895e4200000000,
+ 0xc7bd907000000000, 0x6eb6193e00000000, 0x95aa82ed00000000,
+ 0x3ca10ba300000000, 0xbf6da8bb00000000, 0x166621f500000000,
+ 0xed7aba2600000000, 0x4471336800000000, 0x5a45fd5a00000000,
+ 0xf34e741400000000, 0x0852efc700000000, 0xa159668900000000,
+ 0x343a73a200000000, 0x9d31faec00000000, 0x662d613f00000000,
+ 0xcf26e87100000000, 0xd112264300000000, 0x7819af0d00000000,
+ 0x830534de00000000, 0x2a0ebd9000000000, 0x859c73ef00000000,
+ 0x2c97faa100000000, 0xd78b617200000000, 0x7e80e83c00000000,
+ 0x60b4260e00000000, 0xc9bfaf4000000000, 0x32a3349300000000,
+ 0x9ba8bddd00000000, 0x0ecba8f600000000, 0xa7c021b800000000,
+ 0x5cdcba6b00000000, 0xf5d7332500000000, 0xebe3fd1700000000,
+ 0x42e8745900000000, 0xb9f4ef8a00000000, 0x10ff66c400000000,
+ 0x9333c5dc00000000, 0x3a384c9200000000, 0xc124d74100000000,
+ 0x682f5e0f00000000, 0x761b903d00000000, 0xdf10197300000000,
+ 0x240c82a000000000, 0x8d070bee00000000, 0x18641ec500000000,
+ 0xb16f978b00000000, 0x4a730c5800000000, 0xe378851600000000,
+ 0xfd4c4b2400000000, 0x5447c26a00000000, 0xaf5b59b900000000,
+ 0x0650d0f700000000},
+ {0x0000000000000000, 0x479244af00000000, 0xcf22f88500000000,
+ 0x88b0bc2a00000000, 0xdf4381d000000000, 0x98d1c57f00000000,
+ 0x1061795500000000, 0x57f33dfa00000000, 0xff81737a00000000,
+ 0xb81337d500000000, 0x30a38bff00000000, 0x7731cf5000000000,
+ 0x20c2f2aa00000000, 0x6750b60500000000, 0xefe00a2f00000000,
+ 0xa8724e8000000000, 0xfe03e7f400000000, 0xb991a35b00000000,
+ 0x31211f7100000000, 0x76b35bde00000000, 0x2140662400000000,
+ 0x66d2228b00000000, 0xee629ea100000000, 0xa9f0da0e00000000,
+ 0x0182948e00000000, 0x4610d02100000000, 0xcea06c0b00000000,
+ 0x893228a400000000, 0xdec1155e00000000, 0x995351f100000000,
+ 0x11e3eddb00000000, 0x5671a97400000000, 0xbd01bf3200000000,
+ 0xfa93fb9d00000000, 0x722347b700000000, 0x35b1031800000000,
+ 0x62423ee200000000, 0x25d07a4d00000000, 0xad60c66700000000,
+ 0xeaf282c800000000, 0x4280cc4800000000, 0x051288e700000000,
+ 0x8da234cd00000000, 0xca30706200000000, 0x9dc34d9800000000,
+ 0xda51093700000000, 0x52e1b51d00000000, 0x1573f1b200000000,
+ 0x430258c600000000, 0x04901c6900000000, 0x8c20a04300000000,
+ 0xcbb2e4ec00000000, 0x9c41d91600000000, 0xdbd39db900000000,
+ 0x5363219300000000, 0x14f1653c00000000, 0xbc832bbc00000000,
+ 0xfb116f1300000000, 0x73a1d33900000000, 0x3433979600000000,
+ 0x63c0aa6c00000000, 0x2452eec300000000, 0xace252e900000000,
+ 0xeb70164600000000, 0x7a037e6500000000, 0x3d913aca00000000,
+ 0xb52186e000000000, 0xf2b3c24f00000000, 0xa540ffb500000000,
+ 0xe2d2bb1a00000000, 0x6a62073000000000, 0x2df0439f00000000,
+ 0x85820d1f00000000, 0xc21049b000000000, 0x4aa0f59a00000000,
+ 0x0d32b13500000000, 0x5ac18ccf00000000, 0x1d53c86000000000,
+ 0x95e3744a00000000, 0xd27130e500000000, 0x8400999100000000,
+ 0xc392dd3e00000000, 0x4b22611400000000, 0x0cb025bb00000000,
+ 0x5b43184100000000, 0x1cd15cee00000000, 0x9461e0c400000000,
+ 0xd3f3a46b00000000, 0x7b81eaeb00000000, 0x3c13ae4400000000,
+ 0xb4a3126e00000000, 0xf33156c100000000, 0xa4c26b3b00000000,
+ 0xe3502f9400000000, 0x6be093be00000000, 0x2c72d71100000000,
+ 0xc702c15700000000, 0x809085f800000000, 0x082039d200000000,
+ 0x4fb27d7d00000000, 0x1841408700000000, 0x5fd3042800000000,
+ 0xd763b80200000000, 0x90f1fcad00000000, 0x3883b22d00000000,
+ 0x7f11f68200000000, 0xf7a14aa800000000, 0xb0330e0700000000,
+ 0xe7c033fd00000000, 0xa052775200000000, 0x28e2cb7800000000,
+ 0x6f708fd700000000, 0x390126a300000000, 0x7e93620c00000000,
+ 0xf623de2600000000, 0xb1b19a8900000000, 0xe642a77300000000,
+ 0xa1d0e3dc00000000, 0x29605ff600000000, 0x6ef21b5900000000,
+ 0xc68055d900000000, 0x8112117600000000, 0x09a2ad5c00000000,
+ 0x4e30e9f300000000, 0x19c3d40900000000, 0x5e5190a600000000,
+ 0xd6e12c8c00000000, 0x9173682300000000, 0xf406fcca00000000,
+ 0xb394b86500000000, 0x3b24044f00000000, 0x7cb640e000000000,
+ 0x2b457d1a00000000, 0x6cd739b500000000, 0xe467859f00000000,
+ 0xa3f5c13000000000, 0x0b878fb000000000, 0x4c15cb1f00000000,
+ 0xc4a5773500000000, 0x8337339a00000000, 0xd4c40e6000000000,
+ 0x93564acf00000000, 0x1be6f6e500000000, 0x5c74b24a00000000,
+ 0x0a051b3e00000000, 0x4d975f9100000000, 0xc527e3bb00000000,
+ 0x82b5a71400000000, 0xd5469aee00000000, 0x92d4de4100000000,
+ 0x1a64626b00000000, 0x5df626c400000000, 0xf584684400000000,
+ 0xb2162ceb00000000, 0x3aa690c100000000, 0x7d34d46e00000000,
+ 0x2ac7e99400000000, 0x6d55ad3b00000000, 0xe5e5111100000000,
+ 0xa27755be00000000, 0x490743f800000000, 0x0e95075700000000,
+ 0x8625bb7d00000000, 0xc1b7ffd200000000, 0x9644c22800000000,
+ 0xd1d6868700000000, 0x59663aad00000000, 0x1ef47e0200000000,
+ 0xb686308200000000, 0xf114742d00000000, 0x79a4c80700000000,
+ 0x3e368ca800000000, 0x69c5b15200000000, 0x2e57f5fd00000000,
+ 0xa6e749d700000000, 0xe1750d7800000000, 0xb704a40c00000000,
+ 0xf096e0a300000000, 0x78265c8900000000, 0x3fb4182600000000,
+ 0x684725dc00000000, 0x2fd5617300000000, 0xa765dd5900000000,
+ 0xe0f799f600000000, 0x4885d77600000000, 0x0f1793d900000000,
+ 0x87a72ff300000000, 0xc0356b5c00000000, 0x97c656a600000000,
+ 0xd054120900000000, 0x58e4ae2300000000, 0x1f76ea8c00000000,
+ 0x8e0582af00000000, 0xc997c60000000000, 0x41277a2a00000000,
+ 0x06b53e8500000000, 0x5146037f00000000, 0x16d447d000000000,
+ 0x9e64fbfa00000000, 0xd9f6bf5500000000, 0x7184f1d500000000,
+ 0x3616b57a00000000, 0xbea6095000000000, 0xf9344dff00000000,
+ 0xaec7700500000000, 0xe95534aa00000000, 0x61e5888000000000,
+ 0x2677cc2f00000000, 0x7006655b00000000, 0x379421f400000000,
+ 0xbf249dde00000000, 0xf8b6d97100000000, 0xaf45e48b00000000,
+ 0xe8d7a02400000000, 0x60671c0e00000000, 0x27f558a100000000,
+ 0x8f87162100000000, 0xc815528e00000000, 0x40a5eea400000000,
+ 0x0737aa0b00000000, 0x50c497f100000000, 0x1756d35e00000000,
+ 0x9fe66f7400000000, 0xd8742bdb00000000, 0x33043d9d00000000,
+ 0x7496793200000000, 0xfc26c51800000000, 0xbbb481b700000000,
+ 0xec47bc4d00000000, 0xabd5f8e200000000, 0x236544c800000000,
+ 0x64f7006700000000, 0xcc854ee700000000, 0x8b170a4800000000,
+ 0x03a7b66200000000, 0x4435f2cd00000000, 0x13c6cf3700000000,
+ 0x54548b9800000000, 0xdce437b200000000, 0x9b76731d00000000,
+ 0xcd07da6900000000, 0x8a959ec600000000, 0x022522ec00000000,
+ 0x45b7664300000000, 0x12445bb900000000, 0x55d61f1600000000,
+ 0xdd66a33c00000000, 0x9af4e79300000000, 0x3286a91300000000,
+ 0x7514edbc00000000, 0xfda4519600000000, 0xba36153900000000,
+ 0xedc528c300000000, 0xaa576c6c00000000, 0x22e7d04600000000,
+ 0x657594e900000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x65673b46, 0xcace768c, 0xafa94dca, 0x4eedeb59,
+ 0x2b8ad01f, 0x84239dd5, 0xe144a693, 0x9ddbd6b2, 0xf8bcedf4,
+ 0x5715a03e, 0x32729b78, 0xd3363deb, 0xb65106ad, 0x19f84b67,
+ 0x7c9f7021, 0xe0c6ab25, 0x85a19063, 0x2a08dda9, 0x4f6fe6ef,
+ 0xae2b407c, 0xcb4c7b3a, 0x64e536f0, 0x01820db6, 0x7d1d7d97,
+ 0x187a46d1, 0xb7d30b1b, 0xd2b4305d, 0x33f096ce, 0x5697ad88,
+ 0xf93ee042, 0x9c59db04, 0x1afc500b, 0x7f9b6b4d, 0xd0322687,
+ 0xb5551dc1, 0x5411bb52, 0x31768014, 0x9edfcdde, 0xfbb8f698,
+ 0x872786b9, 0xe240bdff, 0x4de9f035, 0x288ecb73, 0xc9ca6de0,
+ 0xacad56a6, 0x03041b6c, 0x6663202a, 0xfa3afb2e, 0x9f5dc068,
+ 0x30f48da2, 0x5593b6e4, 0xb4d71077, 0xd1b02b31, 0x7e1966fb,
+ 0x1b7e5dbd, 0x67e12d9c, 0x028616da, 0xad2f5b10, 0xc8486056,
+ 0x290cc6c5, 0x4c6bfd83, 0xe3c2b049, 0x86a58b0f, 0x35f8a016,
+ 0x509f9b50, 0xff36d69a, 0x9a51eddc, 0x7b154b4f, 0x1e727009,
+ 0xb1db3dc3, 0xd4bc0685, 0xa82376a4, 0xcd444de2, 0x62ed0028,
+ 0x078a3b6e, 0xe6ce9dfd, 0x83a9a6bb, 0x2c00eb71, 0x4967d037,
+ 0xd53e0b33, 0xb0593075, 0x1ff07dbf, 0x7a9746f9, 0x9bd3e06a,
+ 0xfeb4db2c, 0x511d96e6, 0x347aada0, 0x48e5dd81, 0x2d82e6c7,
+ 0x822bab0d, 0xe74c904b, 0x060836d8, 0x636f0d9e, 0xccc64054,
+ 0xa9a17b12, 0x2f04f01d, 0x4a63cb5b, 0xe5ca8691, 0x80adbdd7,
+ 0x61e91b44, 0x048e2002, 0xab276dc8, 0xce40568e, 0xb2df26af,
+ 0xd7b81de9, 0x78115023, 0x1d766b65, 0xfc32cdf6, 0x9955f6b0,
+ 0x36fcbb7a, 0x539b803c, 0xcfc25b38, 0xaaa5607e, 0x050c2db4,
+ 0x606b16f2, 0x812fb061, 0xe4488b27, 0x4be1c6ed, 0x2e86fdab,
+ 0x52198d8a, 0x377eb6cc, 0x98d7fb06, 0xfdb0c040, 0x1cf466d3,
+ 0x79935d95, 0xd63a105f, 0xb35d2b19, 0x6bf1402c, 0x0e967b6a,
+ 0xa13f36a0, 0xc4580de6, 0x251cab75, 0x407b9033, 0xefd2ddf9,
+ 0x8ab5e6bf, 0xf62a969e, 0x934dadd8, 0x3ce4e012, 0x5983db54,
+ 0xb8c77dc7, 0xdda04681, 0x72090b4b, 0x176e300d, 0x8b37eb09,
+ 0xee50d04f, 0x41f99d85, 0x249ea6c3, 0xc5da0050, 0xa0bd3b16,
+ 0x0f1476dc, 0x6a734d9a, 0x16ec3dbb, 0x738b06fd, 0xdc224b37,
+ 0xb9457071, 0x5801d6e2, 0x3d66eda4, 0x92cfa06e, 0xf7a89b28,
+ 0x710d1027, 0x146a2b61, 0xbbc366ab, 0xdea45ded, 0x3fe0fb7e,
+ 0x5a87c038, 0xf52e8df2, 0x9049b6b4, 0xecd6c695, 0x89b1fdd3,
+ 0x2618b019, 0x437f8b5f, 0xa23b2dcc, 0xc75c168a, 0x68f55b40,
+ 0x0d926006, 0x91cbbb02, 0xf4ac8044, 0x5b05cd8e, 0x3e62f6c8,
+ 0xdf26505b, 0xba416b1d, 0x15e826d7, 0x708f1d91, 0x0c106db0,
+ 0x697756f6, 0xc6de1b3c, 0xa3b9207a, 0x42fd86e9, 0x279abdaf,
+ 0x8833f065, 0xed54cb23, 0x5e09e03a, 0x3b6edb7c, 0x94c796b6,
+ 0xf1a0adf0, 0x10e40b63, 0x75833025, 0xda2a7def, 0xbf4d46a9,
+ 0xc3d23688, 0xa6b50dce, 0x091c4004, 0x6c7b7b42, 0x8d3fddd1,
+ 0xe858e697, 0x47f1ab5d, 0x2296901b, 0xbecf4b1f, 0xdba87059,
+ 0x74013d93, 0x116606d5, 0xf022a046, 0x95459b00, 0x3aecd6ca,
+ 0x5f8bed8c, 0x23149dad, 0x4673a6eb, 0xe9daeb21, 0x8cbdd067,
+ 0x6df976f4, 0x089e4db2, 0xa7370078, 0xc2503b3e, 0x44f5b031,
+ 0x21928b77, 0x8e3bc6bd, 0xeb5cfdfb, 0x0a185b68, 0x6f7f602e,
+ 0xc0d62de4, 0xa5b116a2, 0xd92e6683, 0xbc495dc5, 0x13e0100f,
+ 0x76872b49, 0x97c38dda, 0xf2a4b69c, 0x5d0dfb56, 0x386ac010,
+ 0xa4331b14, 0xc1542052, 0x6efd6d98, 0x0b9a56de, 0xeadef04d,
+ 0x8fb9cb0b, 0x201086c1, 0x4577bd87, 0x39e8cda6, 0x5c8ff6e0,
+ 0xf326bb2a, 0x9641806c, 0x770526ff, 0x12621db9, 0xbdcb5073,
+ 0xd8ac6b35},
+ {0x00000000, 0xd7e28058, 0x74b406f1, 0xa35686a9, 0xe9680de2,
+ 0x3e8a8dba, 0x9ddc0b13, 0x4a3e8b4b, 0x09a11d85, 0xde439ddd,
+ 0x7d151b74, 0xaaf79b2c, 0xe0c91067, 0x372b903f, 0x947d1696,
+ 0x439f96ce, 0x13423b0a, 0xc4a0bb52, 0x67f63dfb, 0xb014bda3,
+ 0xfa2a36e8, 0x2dc8b6b0, 0x8e9e3019, 0x597cb041, 0x1ae3268f,
+ 0xcd01a6d7, 0x6e57207e, 0xb9b5a026, 0xf38b2b6d, 0x2469ab35,
+ 0x873f2d9c, 0x50ddadc4, 0x26847614, 0xf166f64c, 0x523070e5,
+ 0x85d2f0bd, 0xcfec7bf6, 0x180efbae, 0xbb587d07, 0x6cbafd5f,
+ 0x2f256b91, 0xf8c7ebc9, 0x5b916d60, 0x8c73ed38, 0xc64d6673,
+ 0x11afe62b, 0xb2f96082, 0x651be0da, 0x35c64d1e, 0xe224cd46,
+ 0x41724bef, 0x9690cbb7, 0xdcae40fc, 0x0b4cc0a4, 0xa81a460d,
+ 0x7ff8c655, 0x3c67509b, 0xeb85d0c3, 0x48d3566a, 0x9f31d632,
+ 0xd50f5d79, 0x02eddd21, 0xa1bb5b88, 0x7659dbd0, 0x4d08ec28,
+ 0x9aea6c70, 0x39bcead9, 0xee5e6a81, 0xa460e1ca, 0x73826192,
+ 0xd0d4e73b, 0x07366763, 0x44a9f1ad, 0x934b71f5, 0x301df75c,
+ 0xe7ff7704, 0xadc1fc4f, 0x7a237c17, 0xd975fabe, 0x0e977ae6,
+ 0x5e4ad722, 0x89a8577a, 0x2afed1d3, 0xfd1c518b, 0xb722dac0,
+ 0x60c05a98, 0xc396dc31, 0x14745c69, 0x57ebcaa7, 0x80094aff,
+ 0x235fcc56, 0xf4bd4c0e, 0xbe83c745, 0x6961471d, 0xca37c1b4,
+ 0x1dd541ec, 0x6b8c9a3c, 0xbc6e1a64, 0x1f389ccd, 0xc8da1c95,
+ 0x82e497de, 0x55061786, 0xf650912f, 0x21b21177, 0x622d87b9,
+ 0xb5cf07e1, 0x16998148, 0xc17b0110, 0x8b458a5b, 0x5ca70a03,
+ 0xfff18caa, 0x28130cf2, 0x78cea136, 0xaf2c216e, 0x0c7aa7c7,
+ 0xdb98279f, 0x91a6acd4, 0x46442c8c, 0xe512aa25, 0x32f02a7d,
+ 0x716fbcb3, 0xa68d3ceb, 0x05dbba42, 0xd2393a1a, 0x9807b151,
+ 0x4fe53109, 0xecb3b7a0, 0x3b5137f8, 0x9a11d850, 0x4df35808,
+ 0xeea5dea1, 0x39475ef9, 0x7379d5b2, 0xa49b55ea, 0x07cdd343,
+ 0xd02f531b, 0x93b0c5d5, 0x4452458d, 0xe704c324, 0x30e6437c,
+ 0x7ad8c837, 0xad3a486f, 0x0e6ccec6, 0xd98e4e9e, 0x8953e35a,
+ 0x5eb16302, 0xfde7e5ab, 0x2a0565f3, 0x603beeb8, 0xb7d96ee0,
+ 0x148fe849, 0xc36d6811, 0x80f2fedf, 0x57107e87, 0xf446f82e,
+ 0x23a47876, 0x699af33d, 0xbe787365, 0x1d2ef5cc, 0xcacc7594,
+ 0xbc95ae44, 0x6b772e1c, 0xc821a8b5, 0x1fc328ed, 0x55fda3a6,
+ 0x821f23fe, 0x2149a557, 0xf6ab250f, 0xb534b3c1, 0x62d63399,
+ 0xc180b530, 0x16623568, 0x5c5cbe23, 0x8bbe3e7b, 0x28e8b8d2,
+ 0xff0a388a, 0xafd7954e, 0x78351516, 0xdb6393bf, 0x0c8113e7,
+ 0x46bf98ac, 0x915d18f4, 0x320b9e5d, 0xe5e91e05, 0xa67688cb,
+ 0x71940893, 0xd2c28e3a, 0x05200e62, 0x4f1e8529, 0x98fc0571,
+ 0x3baa83d8, 0xec480380, 0xd7193478, 0x00fbb420, 0xa3ad3289,
+ 0x744fb2d1, 0x3e71399a, 0xe993b9c2, 0x4ac53f6b, 0x9d27bf33,
+ 0xdeb829fd, 0x095aa9a5, 0xaa0c2f0c, 0x7deeaf54, 0x37d0241f,
+ 0xe032a447, 0x436422ee, 0x9486a2b6, 0xc45b0f72, 0x13b98f2a,
+ 0xb0ef0983, 0x670d89db, 0x2d330290, 0xfad182c8, 0x59870461,
+ 0x8e658439, 0xcdfa12f7, 0x1a1892af, 0xb94e1406, 0x6eac945e,
+ 0x24921f15, 0xf3709f4d, 0x502619e4, 0x87c499bc, 0xf19d426c,
+ 0x267fc234, 0x8529449d, 0x52cbc4c5, 0x18f54f8e, 0xcf17cfd6,
+ 0x6c41497f, 0xbba3c927, 0xf83c5fe9, 0x2fdedfb1, 0x8c885918,
+ 0x5b6ad940, 0x1154520b, 0xc6b6d253, 0x65e054fa, 0xb202d4a2,
+ 0xe2df7966, 0x353df93e, 0x966b7f97, 0x4189ffcf, 0x0bb77484,
+ 0xdc55f4dc, 0x7f037275, 0xa8e1f22d, 0xeb7e64e3, 0x3c9ce4bb,
+ 0x9fca6212, 0x4828e24a, 0x02166901, 0xd5f4e959, 0x76a26ff0,
+ 0xa140efa8},
+ {0x00000000, 0xef52b6e1, 0x05d46b83, 0xea86dd62, 0x0ba8d706,
+ 0xe4fa61e7, 0x0e7cbc85, 0xe12e0a64, 0x1751ae0c, 0xf80318ed,
+ 0x1285c58f, 0xfdd7736e, 0x1cf9790a, 0xf3abcfeb, 0x192d1289,
+ 0xf67fa468, 0x2ea35c18, 0xc1f1eaf9, 0x2b77379b, 0xc425817a,
+ 0x250b8b1e, 0xca593dff, 0x20dfe09d, 0xcf8d567c, 0x39f2f214,
+ 0xd6a044f5, 0x3c269997, 0xd3742f76, 0x325a2512, 0xdd0893f3,
+ 0x378e4e91, 0xd8dcf870, 0x5d46b830, 0xb2140ed1, 0x5892d3b3,
+ 0xb7c06552, 0x56ee6f36, 0xb9bcd9d7, 0x533a04b5, 0xbc68b254,
+ 0x4a17163c, 0xa545a0dd, 0x4fc37dbf, 0xa091cb5e, 0x41bfc13a,
+ 0xaeed77db, 0x446baab9, 0xab391c58, 0x73e5e428, 0x9cb752c9,
+ 0x76318fab, 0x9963394a, 0x784d332e, 0x971f85cf, 0x7d9958ad,
+ 0x92cbee4c, 0x64b44a24, 0x8be6fcc5, 0x616021a7, 0x8e329746,
+ 0x6f1c9d22, 0x804e2bc3, 0x6ac8f6a1, 0x859a4040, 0xba8d7060,
+ 0x55dfc681, 0xbf591be3, 0x500bad02, 0xb125a766, 0x5e771187,
+ 0xb4f1cce5, 0x5ba37a04, 0xaddcde6c, 0x428e688d, 0xa808b5ef,
+ 0x475a030e, 0xa674096a, 0x4926bf8b, 0xa3a062e9, 0x4cf2d408,
+ 0x942e2c78, 0x7b7c9a99, 0x91fa47fb, 0x7ea8f11a, 0x9f86fb7e,
+ 0x70d44d9f, 0x9a5290fd, 0x7500261c, 0x837f8274, 0x6c2d3495,
+ 0x86abe9f7, 0x69f95f16, 0x88d75572, 0x6785e393, 0x8d033ef1,
+ 0x62518810, 0xe7cbc850, 0x08997eb1, 0xe21fa3d3, 0x0d4d1532,
+ 0xec631f56, 0x0331a9b7, 0xe9b774d5, 0x06e5c234, 0xf09a665c,
+ 0x1fc8d0bd, 0xf54e0ddf, 0x1a1cbb3e, 0xfb32b15a, 0x146007bb,
+ 0xfee6dad9, 0x11b46c38, 0xc9689448, 0x263a22a9, 0xccbcffcb,
+ 0x23ee492a, 0xc2c0434e, 0x2d92f5af, 0xc71428cd, 0x28469e2c,
+ 0xde393a44, 0x316b8ca5, 0xdbed51c7, 0x34bfe726, 0xd591ed42,
+ 0x3ac35ba3, 0xd04586c1, 0x3f173020, 0xae6be681, 0x41395060,
+ 0xabbf8d02, 0x44ed3be3, 0xa5c33187, 0x4a918766, 0xa0175a04,
+ 0x4f45ece5, 0xb93a488d, 0x5668fe6c, 0xbcee230e, 0x53bc95ef,
+ 0xb2929f8b, 0x5dc0296a, 0xb746f408, 0x581442e9, 0x80c8ba99,
+ 0x6f9a0c78, 0x851cd11a, 0x6a4e67fb, 0x8b606d9f, 0x6432db7e,
+ 0x8eb4061c, 0x61e6b0fd, 0x97991495, 0x78cba274, 0x924d7f16,
+ 0x7d1fc9f7, 0x9c31c393, 0x73637572, 0x99e5a810, 0x76b71ef1,
+ 0xf32d5eb1, 0x1c7fe850, 0xf6f93532, 0x19ab83d3, 0xf88589b7,
+ 0x17d73f56, 0xfd51e234, 0x120354d5, 0xe47cf0bd, 0x0b2e465c,
+ 0xe1a89b3e, 0x0efa2ddf, 0xefd427bb, 0x0086915a, 0xea004c38,
+ 0x0552fad9, 0xdd8e02a9, 0x32dcb448, 0xd85a692a, 0x3708dfcb,
+ 0xd626d5af, 0x3974634e, 0xd3f2be2c, 0x3ca008cd, 0xcadfaca5,
+ 0x258d1a44, 0xcf0bc726, 0x205971c7, 0xc1777ba3, 0x2e25cd42,
+ 0xc4a31020, 0x2bf1a6c1, 0x14e696e1, 0xfbb42000, 0x1132fd62,
+ 0xfe604b83, 0x1f4e41e7, 0xf01cf706, 0x1a9a2a64, 0xf5c89c85,
+ 0x03b738ed, 0xece58e0c, 0x0663536e, 0xe931e58f, 0x081fefeb,
+ 0xe74d590a, 0x0dcb8468, 0xe2993289, 0x3a45caf9, 0xd5177c18,
+ 0x3f91a17a, 0xd0c3179b, 0x31ed1dff, 0xdebfab1e, 0x3439767c,
+ 0xdb6bc09d, 0x2d1464f5, 0xc246d214, 0x28c00f76, 0xc792b997,
+ 0x26bcb3f3, 0xc9ee0512, 0x2368d870, 0xcc3a6e91, 0x49a02ed1,
+ 0xa6f29830, 0x4c744552, 0xa326f3b3, 0x4208f9d7, 0xad5a4f36,
+ 0x47dc9254, 0xa88e24b5, 0x5ef180dd, 0xb1a3363c, 0x5b25eb5e,
+ 0xb4775dbf, 0x555957db, 0xba0be13a, 0x508d3c58, 0xbfdf8ab9,
+ 0x670372c9, 0x8851c428, 0x62d7194a, 0x8d85afab, 0x6caba5cf,
+ 0x83f9132e, 0x697fce4c, 0x862d78ad, 0x7052dcc5, 0x9f006a24,
+ 0x7586b746, 0x9ad401a7, 0x7bfa0bc3, 0x94a8bd22, 0x7e2e6040,
+ 0x917cd6a1},
+ {0x00000000, 0x87a6cb43, 0xd43c90c7, 0x539a5b84, 0x730827cf,
+ 0xf4aeec8c, 0xa734b708, 0x20927c4b, 0xe6104f9e, 0x61b684dd,
+ 0x322cdf59, 0xb58a141a, 0x95186851, 0x12bea312, 0x4124f896,
+ 0xc68233d5, 0x1751997d, 0x90f7523e, 0xc36d09ba, 0x44cbc2f9,
+ 0x6459beb2, 0xe3ff75f1, 0xb0652e75, 0x37c3e536, 0xf141d6e3,
+ 0x76e71da0, 0x257d4624, 0xa2db8d67, 0x8249f12c, 0x05ef3a6f,
+ 0x567561eb, 0xd1d3aaa8, 0x2ea332fa, 0xa905f9b9, 0xfa9fa23d,
+ 0x7d39697e, 0x5dab1535, 0xda0dde76, 0x899785f2, 0x0e314eb1,
+ 0xc8b37d64, 0x4f15b627, 0x1c8feda3, 0x9b2926e0, 0xbbbb5aab,
+ 0x3c1d91e8, 0x6f87ca6c, 0xe821012f, 0x39f2ab87, 0xbe5460c4,
+ 0xedce3b40, 0x6a68f003, 0x4afa8c48, 0xcd5c470b, 0x9ec61c8f,
+ 0x1960d7cc, 0xdfe2e419, 0x58442f5a, 0x0bde74de, 0x8c78bf9d,
+ 0xaceac3d6, 0x2b4c0895, 0x78d65311, 0xff709852, 0x5d4665f4,
+ 0xdae0aeb7, 0x897af533, 0x0edc3e70, 0x2e4e423b, 0xa9e88978,
+ 0xfa72d2fc, 0x7dd419bf, 0xbb562a6a, 0x3cf0e129, 0x6f6abaad,
+ 0xe8cc71ee, 0xc85e0da5, 0x4ff8c6e6, 0x1c629d62, 0x9bc45621,
+ 0x4a17fc89, 0xcdb137ca, 0x9e2b6c4e, 0x198da70d, 0x391fdb46,
+ 0xbeb91005, 0xed234b81, 0x6a8580c2, 0xac07b317, 0x2ba17854,
+ 0x783b23d0, 0xff9de893, 0xdf0f94d8, 0x58a95f9b, 0x0b33041f,
+ 0x8c95cf5c, 0x73e5570e, 0xf4439c4d, 0xa7d9c7c9, 0x207f0c8a,
+ 0x00ed70c1, 0x874bbb82, 0xd4d1e006, 0x53772b45, 0x95f51890,
+ 0x1253d3d3, 0x41c98857, 0xc66f4314, 0xe6fd3f5f, 0x615bf41c,
+ 0x32c1af98, 0xb56764db, 0x64b4ce73, 0xe3120530, 0xb0885eb4,
+ 0x372e95f7, 0x17bce9bc, 0x901a22ff, 0xc380797b, 0x4426b238,
+ 0x82a481ed, 0x05024aae, 0x5698112a, 0xd13eda69, 0xf1aca622,
+ 0x760a6d61, 0x259036e5, 0xa236fda6, 0xba8ccbe8, 0x3d2a00ab,
+ 0x6eb05b2f, 0xe916906c, 0xc984ec27, 0x4e222764, 0x1db87ce0,
+ 0x9a1eb7a3, 0x5c9c8476, 0xdb3a4f35, 0x88a014b1, 0x0f06dff2,
+ 0x2f94a3b9, 0xa83268fa, 0xfba8337e, 0x7c0ef83d, 0xaddd5295,
+ 0x2a7b99d6, 0x79e1c252, 0xfe470911, 0xded5755a, 0x5973be19,
+ 0x0ae9e59d, 0x8d4f2ede, 0x4bcd1d0b, 0xcc6bd648, 0x9ff18dcc,
+ 0x1857468f, 0x38c53ac4, 0xbf63f187, 0xecf9aa03, 0x6b5f6140,
+ 0x942ff912, 0x13893251, 0x401369d5, 0xc7b5a296, 0xe727dedd,
+ 0x6081159e, 0x331b4e1a, 0xb4bd8559, 0x723fb68c, 0xf5997dcf,
+ 0xa603264b, 0x21a5ed08, 0x01379143, 0x86915a00, 0xd50b0184,
+ 0x52adcac7, 0x837e606f, 0x04d8ab2c, 0x5742f0a8, 0xd0e43beb,
+ 0xf07647a0, 0x77d08ce3, 0x244ad767, 0xa3ec1c24, 0x656e2ff1,
+ 0xe2c8e4b2, 0xb152bf36, 0x36f47475, 0x1666083e, 0x91c0c37d,
+ 0xc25a98f9, 0x45fc53ba, 0xe7caae1c, 0x606c655f, 0x33f63edb,
+ 0xb450f598, 0x94c289d3, 0x13644290, 0x40fe1914, 0xc758d257,
+ 0x01dae182, 0x867c2ac1, 0xd5e67145, 0x5240ba06, 0x72d2c64d,
+ 0xf5740d0e, 0xa6ee568a, 0x21489dc9, 0xf09b3761, 0x773dfc22,
+ 0x24a7a7a6, 0xa3016ce5, 0x839310ae, 0x0435dbed, 0x57af8069,
+ 0xd0094b2a, 0x168b78ff, 0x912db3bc, 0xc2b7e838, 0x4511237b,
+ 0x65835f30, 0xe2259473, 0xb1bfcff7, 0x361904b4, 0xc9699ce6,
+ 0x4ecf57a5, 0x1d550c21, 0x9af3c762, 0xba61bb29, 0x3dc7706a,
+ 0x6e5d2bee, 0xe9fbe0ad, 0x2f79d378, 0xa8df183b, 0xfb4543bf,
+ 0x7ce388fc, 0x5c71f4b7, 0xdbd73ff4, 0x884d6470, 0x0febaf33,
+ 0xde38059b, 0x599eced8, 0x0a04955c, 0x8da25e1f, 0xad302254,
+ 0x2a96e917, 0x790cb293, 0xfeaa79d0, 0x38284a05, 0xbf8e8146,
+ 0xec14dac2, 0x6bb21181, 0x4b206dca, 0xcc86a689, 0x9f1cfd0d,
+ 0x18ba364e}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x43cba687, 0xc7903cd4, 0x845b9a53, 0xcf270873,
+ 0x8cecaef4, 0x08b734a7, 0x4b7c9220, 0x9e4f10e6, 0xdd84b661,
+ 0x59df2c32, 0x1a148ab5, 0x51681895, 0x12a3be12, 0x96f82441,
+ 0xd53382c6, 0x7d995117, 0x3e52f790, 0xba096dc3, 0xf9c2cb44,
+ 0xb2be5964, 0xf175ffe3, 0x752e65b0, 0x36e5c337, 0xe3d641f1,
+ 0xa01de776, 0x24467d25, 0x678ddba2, 0x2cf14982, 0x6f3aef05,
+ 0xeb617556, 0xa8aad3d1, 0xfa32a32e, 0xb9f905a9, 0x3da29ffa,
+ 0x7e69397d, 0x3515ab5d, 0x76de0dda, 0xf2859789, 0xb14e310e,
+ 0x647db3c8, 0x27b6154f, 0xa3ed8f1c, 0xe026299b, 0xab5abbbb,
+ 0xe8911d3c, 0x6cca876f, 0x2f0121e8, 0x87abf239, 0xc46054be,
+ 0x403bceed, 0x03f0686a, 0x488cfa4a, 0x0b475ccd, 0x8f1cc69e,
+ 0xccd76019, 0x19e4e2df, 0x5a2f4458, 0xde74de0b, 0x9dbf788c,
+ 0xd6c3eaac, 0x95084c2b, 0x1153d678, 0x529870ff, 0xf465465d,
+ 0xb7aee0da, 0x33f57a89, 0x703edc0e, 0x3b424e2e, 0x7889e8a9,
+ 0xfcd272fa, 0xbf19d47d, 0x6a2a56bb, 0x29e1f03c, 0xadba6a6f,
+ 0xee71cce8, 0xa50d5ec8, 0xe6c6f84f, 0x629d621c, 0x2156c49b,
+ 0x89fc174a, 0xca37b1cd, 0x4e6c2b9e, 0x0da78d19, 0x46db1f39,
+ 0x0510b9be, 0x814b23ed, 0xc280856a, 0x17b307ac, 0x5478a12b,
+ 0xd0233b78, 0x93e89dff, 0xd8940fdf, 0x9b5fa958, 0x1f04330b,
+ 0x5ccf958c, 0x0e57e573, 0x4d9c43f4, 0xc9c7d9a7, 0x8a0c7f20,
+ 0xc170ed00, 0x82bb4b87, 0x06e0d1d4, 0x452b7753, 0x9018f595,
+ 0xd3d35312, 0x5788c941, 0x14436fc6, 0x5f3ffde6, 0x1cf45b61,
+ 0x98afc132, 0xdb6467b5, 0x73ceb464, 0x300512e3, 0xb45e88b0,
+ 0xf7952e37, 0xbce9bc17, 0xff221a90, 0x7b7980c3, 0x38b22644,
+ 0xed81a482, 0xae4a0205, 0x2a119856, 0x69da3ed1, 0x22a6acf1,
+ 0x616d0a76, 0xe5369025, 0xa6fd36a2, 0xe8cb8cba, 0xab002a3d,
+ 0x2f5bb06e, 0x6c9016e9, 0x27ec84c9, 0x6427224e, 0xe07cb81d,
+ 0xa3b71e9a, 0x76849c5c, 0x354f3adb, 0xb114a088, 0xf2df060f,
+ 0xb9a3942f, 0xfa6832a8, 0x7e33a8fb, 0x3df80e7c, 0x9552ddad,
+ 0xd6997b2a, 0x52c2e179, 0x110947fe, 0x5a75d5de, 0x19be7359,
+ 0x9de5e90a, 0xde2e4f8d, 0x0b1dcd4b, 0x48d66bcc, 0xcc8df19f,
+ 0x8f465718, 0xc43ac538, 0x87f163bf, 0x03aaf9ec, 0x40615f6b,
+ 0x12f92f94, 0x51328913, 0xd5691340, 0x96a2b5c7, 0xddde27e7,
+ 0x9e158160, 0x1a4e1b33, 0x5985bdb4, 0x8cb63f72, 0xcf7d99f5,
+ 0x4b2603a6, 0x08eda521, 0x43913701, 0x005a9186, 0x84010bd5,
+ 0xc7caad52, 0x6f607e83, 0x2cabd804, 0xa8f04257, 0xeb3be4d0,
+ 0xa04776f0, 0xe38cd077, 0x67d74a24, 0x241ceca3, 0xf12f6e65,
+ 0xb2e4c8e2, 0x36bf52b1, 0x7574f436, 0x3e086616, 0x7dc3c091,
+ 0xf9985ac2, 0xba53fc45, 0x1caecae7, 0x5f656c60, 0xdb3ef633,
+ 0x98f550b4, 0xd389c294, 0x90426413, 0x1419fe40, 0x57d258c7,
+ 0x82e1da01, 0xc12a7c86, 0x4571e6d5, 0x06ba4052, 0x4dc6d272,
+ 0x0e0d74f5, 0x8a56eea6, 0xc99d4821, 0x61379bf0, 0x22fc3d77,
+ 0xa6a7a724, 0xe56c01a3, 0xae109383, 0xeddb3504, 0x6980af57,
+ 0x2a4b09d0, 0xff788b16, 0xbcb32d91, 0x38e8b7c2, 0x7b231145,
+ 0x305f8365, 0x739425e2, 0xf7cfbfb1, 0xb4041936, 0xe69c69c9,
+ 0xa557cf4e, 0x210c551d, 0x62c7f39a, 0x29bb61ba, 0x6a70c73d,
+ 0xee2b5d6e, 0xade0fbe9, 0x78d3792f, 0x3b18dfa8, 0xbf4345fb,
+ 0xfc88e37c, 0xb7f4715c, 0xf43fd7db, 0x70644d88, 0x33afeb0f,
+ 0x9b0538de, 0xd8ce9e59, 0x5c95040a, 0x1f5ea28d, 0x542230ad,
+ 0x17e9962a, 0x93b20c79, 0xd079aafe, 0x054a2838, 0x46818ebf,
+ 0xc2da14ec, 0x8111b26b, 0xca6d204b, 0x89a686cc, 0x0dfd1c9f,
+ 0x4e36ba18},
+ {0x00000000, 0xe1b652ef, 0x836bd405, 0x62dd86ea, 0x06d7a80b,
+ 0xe761fae4, 0x85bc7c0e, 0x640a2ee1, 0x0cae5117, 0xed1803f8,
+ 0x8fc58512, 0x6e73d7fd, 0x0a79f91c, 0xebcfabf3, 0x89122d19,
+ 0x68a47ff6, 0x185ca32e, 0xf9eaf1c1, 0x9b37772b, 0x7a8125c4,
+ 0x1e8b0b25, 0xff3d59ca, 0x9de0df20, 0x7c568dcf, 0x14f2f239,
+ 0xf544a0d6, 0x9799263c, 0x762f74d3, 0x12255a32, 0xf39308dd,
+ 0x914e8e37, 0x70f8dcd8, 0x30b8465d, 0xd10e14b2, 0xb3d39258,
+ 0x5265c0b7, 0x366fee56, 0xd7d9bcb9, 0xb5043a53, 0x54b268bc,
+ 0x3c16174a, 0xdda045a5, 0xbf7dc34f, 0x5ecb91a0, 0x3ac1bf41,
+ 0xdb77edae, 0xb9aa6b44, 0x581c39ab, 0x28e4e573, 0xc952b79c,
+ 0xab8f3176, 0x4a396399, 0x2e334d78, 0xcf851f97, 0xad58997d,
+ 0x4ceecb92, 0x244ab464, 0xc5fce68b, 0xa7216061, 0x4697328e,
+ 0x229d1c6f, 0xc32b4e80, 0xa1f6c86a, 0x40409a85, 0x60708dba,
+ 0x81c6df55, 0xe31b59bf, 0x02ad0b50, 0x66a725b1, 0x8711775e,
+ 0xe5ccf1b4, 0x047aa35b, 0x6cdedcad, 0x8d688e42, 0xefb508a8,
+ 0x0e035a47, 0x6a0974a6, 0x8bbf2649, 0xe962a0a3, 0x08d4f24c,
+ 0x782c2e94, 0x999a7c7b, 0xfb47fa91, 0x1af1a87e, 0x7efb869f,
+ 0x9f4dd470, 0xfd90529a, 0x1c260075, 0x74827f83, 0x95342d6c,
+ 0xf7e9ab86, 0x165ff969, 0x7255d788, 0x93e38567, 0xf13e038d,
+ 0x10885162, 0x50c8cbe7, 0xb17e9908, 0xd3a31fe2, 0x32154d0d,
+ 0x561f63ec, 0xb7a93103, 0xd574b7e9, 0x34c2e506, 0x5c669af0,
+ 0xbdd0c81f, 0xdf0d4ef5, 0x3ebb1c1a, 0x5ab132fb, 0xbb076014,
+ 0xd9dae6fe, 0x386cb411, 0x489468c9, 0xa9223a26, 0xcbffbccc,
+ 0x2a49ee23, 0x4e43c0c2, 0xaff5922d, 0xcd2814c7, 0x2c9e4628,
+ 0x443a39de, 0xa58c6b31, 0xc751eddb, 0x26e7bf34, 0x42ed91d5,
+ 0xa35bc33a, 0xc18645d0, 0x2030173f, 0x81e66bae, 0x60503941,
+ 0x028dbfab, 0xe33bed44, 0x8731c3a5, 0x6687914a, 0x045a17a0,
+ 0xe5ec454f, 0x8d483ab9, 0x6cfe6856, 0x0e23eebc, 0xef95bc53,
+ 0x8b9f92b2, 0x6a29c05d, 0x08f446b7, 0xe9421458, 0x99bac880,
+ 0x780c9a6f, 0x1ad11c85, 0xfb674e6a, 0x9f6d608b, 0x7edb3264,
+ 0x1c06b48e, 0xfdb0e661, 0x95149997, 0x74a2cb78, 0x167f4d92,
+ 0xf7c91f7d, 0x93c3319c, 0x72756373, 0x10a8e599, 0xf11eb776,
+ 0xb15e2df3, 0x50e87f1c, 0x3235f9f6, 0xd383ab19, 0xb78985f8,
+ 0x563fd717, 0x34e251fd, 0xd5540312, 0xbdf07ce4, 0x5c462e0b,
+ 0x3e9ba8e1, 0xdf2dfa0e, 0xbb27d4ef, 0x5a918600, 0x384c00ea,
+ 0xd9fa5205, 0xa9028edd, 0x48b4dc32, 0x2a695ad8, 0xcbdf0837,
+ 0xafd526d6, 0x4e637439, 0x2cbef2d3, 0xcd08a03c, 0xa5acdfca,
+ 0x441a8d25, 0x26c70bcf, 0xc7715920, 0xa37b77c1, 0x42cd252e,
+ 0x2010a3c4, 0xc1a6f12b, 0xe196e614, 0x0020b4fb, 0x62fd3211,
+ 0x834b60fe, 0xe7414e1f, 0x06f71cf0, 0x642a9a1a, 0x859cc8f5,
+ 0xed38b703, 0x0c8ee5ec, 0x6e536306, 0x8fe531e9, 0xebef1f08,
+ 0x0a594de7, 0x6884cb0d, 0x893299e2, 0xf9ca453a, 0x187c17d5,
+ 0x7aa1913f, 0x9b17c3d0, 0xff1ded31, 0x1eabbfde, 0x7c763934,
+ 0x9dc06bdb, 0xf564142d, 0x14d246c2, 0x760fc028, 0x97b992c7,
+ 0xf3b3bc26, 0x1205eec9, 0x70d86823, 0x916e3acc, 0xd12ea049,
+ 0x3098f2a6, 0x5245744c, 0xb3f326a3, 0xd7f90842, 0x364f5aad,
+ 0x5492dc47, 0xb5248ea8, 0xdd80f15e, 0x3c36a3b1, 0x5eeb255b,
+ 0xbf5d77b4, 0xdb575955, 0x3ae10bba, 0x583c8d50, 0xb98adfbf,
+ 0xc9720367, 0x28c45188, 0x4a19d762, 0xabaf858d, 0xcfa5ab6c,
+ 0x2e13f983, 0x4cce7f69, 0xad782d86, 0xc5dc5270, 0x246a009f,
+ 0x46b78675, 0xa701d49a, 0xc30bfa7b, 0x22bda894, 0x40602e7e,
+ 0xa1d67c91},
+ {0x00000000, 0x5880e2d7, 0xf106b474, 0xa98656a3, 0xe20d68e9,
+ 0xba8d8a3e, 0x130bdc9d, 0x4b8b3e4a, 0x851da109, 0xdd9d43de,
+ 0x741b157d, 0x2c9bf7aa, 0x6710c9e0, 0x3f902b37, 0x96167d94,
+ 0xce969f43, 0x0a3b4213, 0x52bba0c4, 0xfb3df667, 0xa3bd14b0,
+ 0xe8362afa, 0xb0b6c82d, 0x19309e8e, 0x41b07c59, 0x8f26e31a,
+ 0xd7a601cd, 0x7e20576e, 0x26a0b5b9, 0x6d2b8bf3, 0x35ab6924,
+ 0x9c2d3f87, 0xc4addd50, 0x14768426, 0x4cf666f1, 0xe5703052,
+ 0xbdf0d285, 0xf67beccf, 0xaefb0e18, 0x077d58bb, 0x5ffdba6c,
+ 0x916b252f, 0xc9ebc7f8, 0x606d915b, 0x38ed738c, 0x73664dc6,
+ 0x2be6af11, 0x8260f9b2, 0xdae01b65, 0x1e4dc635, 0x46cd24e2,
+ 0xef4b7241, 0xb7cb9096, 0xfc40aedc, 0xa4c04c0b, 0x0d461aa8,
+ 0x55c6f87f, 0x9b50673c, 0xc3d085eb, 0x6a56d348, 0x32d6319f,
+ 0x795d0fd5, 0x21dded02, 0x885bbba1, 0xd0db5976, 0x28ec084d,
+ 0x706cea9a, 0xd9eabc39, 0x816a5eee, 0xcae160a4, 0x92618273,
+ 0x3be7d4d0, 0x63673607, 0xadf1a944, 0xf5714b93, 0x5cf71d30,
+ 0x0477ffe7, 0x4ffcc1ad, 0x177c237a, 0xbefa75d9, 0xe67a970e,
+ 0x22d74a5e, 0x7a57a889, 0xd3d1fe2a, 0x8b511cfd, 0xc0da22b7,
+ 0x985ac060, 0x31dc96c3, 0x695c7414, 0xa7caeb57, 0xff4a0980,
+ 0x56cc5f23, 0x0e4cbdf4, 0x45c783be, 0x1d476169, 0xb4c137ca,
+ 0xec41d51d, 0x3c9a8c6b, 0x641a6ebc, 0xcd9c381f, 0x951cdac8,
+ 0xde97e482, 0x86170655, 0x2f9150f6, 0x7711b221, 0xb9872d62,
+ 0xe107cfb5, 0x48819916, 0x10017bc1, 0x5b8a458b, 0x030aa75c,
+ 0xaa8cf1ff, 0xf20c1328, 0x36a1ce78, 0x6e212caf, 0xc7a77a0c,
+ 0x9f2798db, 0xd4aca691, 0x8c2c4446, 0x25aa12e5, 0x7d2af032,
+ 0xb3bc6f71, 0xeb3c8da6, 0x42badb05, 0x1a3a39d2, 0x51b10798,
+ 0x0931e54f, 0xa0b7b3ec, 0xf837513b, 0x50d8119a, 0x0858f34d,
+ 0xa1dea5ee, 0xf95e4739, 0xb2d57973, 0xea559ba4, 0x43d3cd07,
+ 0x1b532fd0, 0xd5c5b093, 0x8d455244, 0x24c304e7, 0x7c43e630,
+ 0x37c8d87a, 0x6f483aad, 0xc6ce6c0e, 0x9e4e8ed9, 0x5ae35389,
+ 0x0263b15e, 0xabe5e7fd, 0xf365052a, 0xb8ee3b60, 0xe06ed9b7,
+ 0x49e88f14, 0x11686dc3, 0xdffef280, 0x877e1057, 0x2ef846f4,
+ 0x7678a423, 0x3df39a69, 0x657378be, 0xccf52e1d, 0x9475ccca,
+ 0x44ae95bc, 0x1c2e776b, 0xb5a821c8, 0xed28c31f, 0xa6a3fd55,
+ 0xfe231f82, 0x57a54921, 0x0f25abf6, 0xc1b334b5, 0x9933d662,
+ 0x30b580c1, 0x68356216, 0x23be5c5c, 0x7b3ebe8b, 0xd2b8e828,
+ 0x8a380aff, 0x4e95d7af, 0x16153578, 0xbf9363db, 0xe713810c,
+ 0xac98bf46, 0xf4185d91, 0x5d9e0b32, 0x051ee9e5, 0xcb8876a6,
+ 0x93089471, 0x3a8ec2d2, 0x620e2005, 0x29851e4f, 0x7105fc98,
+ 0xd883aa3b, 0x800348ec, 0x783419d7, 0x20b4fb00, 0x8932ada3,
+ 0xd1b24f74, 0x9a39713e, 0xc2b993e9, 0x6b3fc54a, 0x33bf279d,
+ 0xfd29b8de, 0xa5a95a09, 0x0c2f0caa, 0x54afee7d, 0x1f24d037,
+ 0x47a432e0, 0xee226443, 0xb6a28694, 0x720f5bc4, 0x2a8fb913,
+ 0x8309efb0, 0xdb890d67, 0x9002332d, 0xc882d1fa, 0x61048759,
+ 0x3984658e, 0xf712facd, 0xaf92181a, 0x06144eb9, 0x5e94ac6e,
+ 0x151f9224, 0x4d9f70f3, 0xe4192650, 0xbc99c487, 0x6c429df1,
+ 0x34c27f26, 0x9d442985, 0xc5c4cb52, 0x8e4ff518, 0xd6cf17cf,
+ 0x7f49416c, 0x27c9a3bb, 0xe95f3cf8, 0xb1dfde2f, 0x1859888c,
+ 0x40d96a5b, 0x0b525411, 0x53d2b6c6, 0xfa54e065, 0xa2d402b2,
+ 0x6679dfe2, 0x3ef93d35, 0x977f6b96, 0xcfff8941, 0x8474b70b,
+ 0xdcf455dc, 0x7572037f, 0x2df2e1a8, 0xe3647eeb, 0xbbe49c3c,
+ 0x1262ca9f, 0x4ae22848, 0x01691602, 0x59e9f4d5, 0xf06fa276,
+ 0xa8ef40a1},
+ {0x00000000, 0x463b6765, 0x8c76ceca, 0xca4da9af, 0x59ebed4e,
+ 0x1fd08a2b, 0xd59d2384, 0x93a644e1, 0xb2d6db9d, 0xf4edbcf8,
+ 0x3ea01557, 0x789b7232, 0xeb3d36d3, 0xad0651b6, 0x674bf819,
+ 0x21709f7c, 0x25abc6e0, 0x6390a185, 0xa9dd082a, 0xefe66f4f,
+ 0x7c402bae, 0x3a7b4ccb, 0xf036e564, 0xb60d8201, 0x977d1d7d,
+ 0xd1467a18, 0x1b0bd3b7, 0x5d30b4d2, 0xce96f033, 0x88ad9756,
+ 0x42e03ef9, 0x04db599c, 0x0b50fc1a, 0x4d6b9b7f, 0x872632d0,
+ 0xc11d55b5, 0x52bb1154, 0x14807631, 0xdecddf9e, 0x98f6b8fb,
+ 0xb9862787, 0xffbd40e2, 0x35f0e94d, 0x73cb8e28, 0xe06dcac9,
+ 0xa656adac, 0x6c1b0403, 0x2a206366, 0x2efb3afa, 0x68c05d9f,
+ 0xa28df430, 0xe4b69355, 0x7710d7b4, 0x312bb0d1, 0xfb66197e,
+ 0xbd5d7e1b, 0x9c2de167, 0xda168602, 0x105b2fad, 0x566048c8,
+ 0xc5c60c29, 0x83fd6b4c, 0x49b0c2e3, 0x0f8ba586, 0x16a0f835,
+ 0x509b9f50, 0x9ad636ff, 0xdced519a, 0x4f4b157b, 0x0970721e,
+ 0xc33ddbb1, 0x8506bcd4, 0xa47623a8, 0xe24d44cd, 0x2800ed62,
+ 0x6e3b8a07, 0xfd9dcee6, 0xbba6a983, 0x71eb002c, 0x37d06749,
+ 0x330b3ed5, 0x753059b0, 0xbf7df01f, 0xf946977a, 0x6ae0d39b,
+ 0x2cdbb4fe, 0xe6961d51, 0xa0ad7a34, 0x81dde548, 0xc7e6822d,
+ 0x0dab2b82, 0x4b904ce7, 0xd8360806, 0x9e0d6f63, 0x5440c6cc,
+ 0x127ba1a9, 0x1df0042f, 0x5bcb634a, 0x9186cae5, 0xd7bdad80,
+ 0x441be961, 0x02208e04, 0xc86d27ab, 0x8e5640ce, 0xaf26dfb2,
+ 0xe91db8d7, 0x23501178, 0x656b761d, 0xf6cd32fc, 0xb0f65599,
+ 0x7abbfc36, 0x3c809b53, 0x385bc2cf, 0x7e60a5aa, 0xb42d0c05,
+ 0xf2166b60, 0x61b02f81, 0x278b48e4, 0xedc6e14b, 0xabfd862e,
+ 0x8a8d1952, 0xccb67e37, 0x06fbd798, 0x40c0b0fd, 0xd366f41c,
+ 0x955d9379, 0x5f103ad6, 0x192b5db3, 0x2c40f16b, 0x6a7b960e,
+ 0xa0363fa1, 0xe60d58c4, 0x75ab1c25, 0x33907b40, 0xf9ddd2ef,
+ 0xbfe6b58a, 0x9e962af6, 0xd8ad4d93, 0x12e0e43c, 0x54db8359,
+ 0xc77dc7b8, 0x8146a0dd, 0x4b0b0972, 0x0d306e17, 0x09eb378b,
+ 0x4fd050ee, 0x859df941, 0xc3a69e24, 0x5000dac5, 0x163bbda0,
+ 0xdc76140f, 0x9a4d736a, 0xbb3dec16, 0xfd068b73, 0x374b22dc,
+ 0x717045b9, 0xe2d60158, 0xa4ed663d, 0x6ea0cf92, 0x289ba8f7,
+ 0x27100d71, 0x612b6a14, 0xab66c3bb, 0xed5da4de, 0x7efbe03f,
+ 0x38c0875a, 0xf28d2ef5, 0xb4b64990, 0x95c6d6ec, 0xd3fdb189,
+ 0x19b01826, 0x5f8b7f43, 0xcc2d3ba2, 0x8a165cc7, 0x405bf568,
+ 0x0660920d, 0x02bbcb91, 0x4480acf4, 0x8ecd055b, 0xc8f6623e,
+ 0x5b5026df, 0x1d6b41ba, 0xd726e815, 0x911d8f70, 0xb06d100c,
+ 0xf6567769, 0x3c1bdec6, 0x7a20b9a3, 0xe986fd42, 0xafbd9a27,
+ 0x65f03388, 0x23cb54ed, 0x3ae0095e, 0x7cdb6e3b, 0xb696c794,
+ 0xf0ada0f1, 0x630be410, 0x25308375, 0xef7d2ada, 0xa9464dbf,
+ 0x8836d2c3, 0xce0db5a6, 0x04401c09, 0x427b7b6c, 0xd1dd3f8d,
+ 0x97e658e8, 0x5dabf147, 0x1b909622, 0x1f4bcfbe, 0x5970a8db,
+ 0x933d0174, 0xd5066611, 0x46a022f0, 0x009b4595, 0xcad6ec3a,
+ 0x8ced8b5f, 0xad9d1423, 0xeba67346, 0x21ebdae9, 0x67d0bd8c,
+ 0xf476f96d, 0xb24d9e08, 0x780037a7, 0x3e3b50c2, 0x31b0f544,
+ 0x778b9221, 0xbdc63b8e, 0xfbfd5ceb, 0x685b180a, 0x2e607f6f,
+ 0xe42dd6c0, 0xa216b1a5, 0x83662ed9, 0xc55d49bc, 0x0f10e013,
+ 0x492b8776, 0xda8dc397, 0x9cb6a4f2, 0x56fb0d5d, 0x10c06a38,
+ 0x141b33a4, 0x522054c1, 0x986dfd6e, 0xde569a0b, 0x4df0deea,
+ 0x0bcbb98f, 0xc1861020, 0x87bd7745, 0xa6cde839, 0xe0f68f5c,
+ 0x2abb26f3, 0x6c804196, 0xff260577, 0xb91d6212, 0x7350cbbd,
+ 0x356bacd8}};
+
+#endif
+
+#endif
+
+#if N == 6
+
+#if W == 8
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x3db1ecdc, 0x7b63d9b8, 0x46d23564, 0xf6c7b370,
+ 0xcb765fac, 0x8da46ac8, 0xb0158614, 0x36fe60a1, 0x0b4f8c7d,
+ 0x4d9db919, 0x702c55c5, 0xc039d3d1, 0xfd883f0d, 0xbb5a0a69,
+ 0x86ebe6b5, 0x6dfcc142, 0x504d2d9e, 0x169f18fa, 0x2b2ef426,
+ 0x9b3b7232, 0xa68a9eee, 0xe058ab8a, 0xdde94756, 0x5b02a1e3,
+ 0x66b34d3f, 0x2061785b, 0x1dd09487, 0xadc51293, 0x9074fe4f,
+ 0xd6a6cb2b, 0xeb1727f7, 0xdbf98284, 0xe6486e58, 0xa09a5b3c,
+ 0x9d2bb7e0, 0x2d3e31f4, 0x108fdd28, 0x565de84c, 0x6bec0490,
+ 0xed07e225, 0xd0b60ef9, 0x96643b9d, 0xabd5d741, 0x1bc05155,
+ 0x2671bd89, 0x60a388ed, 0x5d126431, 0xb60543c6, 0x8bb4af1a,
+ 0xcd669a7e, 0xf0d776a2, 0x40c2f0b6, 0x7d731c6a, 0x3ba1290e,
+ 0x0610c5d2, 0x80fb2367, 0xbd4acfbb, 0xfb98fadf, 0xc6291603,
+ 0x763c9017, 0x4b8d7ccb, 0x0d5f49af, 0x30eea573, 0x6c820349,
+ 0x5133ef95, 0x17e1daf1, 0x2a50362d, 0x9a45b039, 0xa7f45ce5,
+ 0xe1266981, 0xdc97855d, 0x5a7c63e8, 0x67cd8f34, 0x211fba50,
+ 0x1cae568c, 0xacbbd098, 0x910a3c44, 0xd7d80920, 0xea69e5fc,
+ 0x017ec20b, 0x3ccf2ed7, 0x7a1d1bb3, 0x47acf76f, 0xf7b9717b,
+ 0xca089da7, 0x8cdaa8c3, 0xb16b441f, 0x3780a2aa, 0x0a314e76,
+ 0x4ce37b12, 0x715297ce, 0xc14711da, 0xfcf6fd06, 0xba24c862,
+ 0x879524be, 0xb77b81cd, 0x8aca6d11, 0xcc185875, 0xf1a9b4a9,
+ 0x41bc32bd, 0x7c0dde61, 0x3adfeb05, 0x076e07d9, 0x8185e16c,
+ 0xbc340db0, 0xfae638d4, 0xc757d408, 0x7742521c, 0x4af3bec0,
+ 0x0c218ba4, 0x31906778, 0xda87408f, 0xe736ac53, 0xa1e49937,
+ 0x9c5575eb, 0x2c40f3ff, 0x11f11f23, 0x57232a47, 0x6a92c69b,
+ 0xec79202e, 0xd1c8ccf2, 0x971af996, 0xaaab154a, 0x1abe935e,
+ 0x270f7f82, 0x61dd4ae6, 0x5c6ca63a, 0xd9040692, 0xe4b5ea4e,
+ 0xa267df2a, 0x9fd633f6, 0x2fc3b5e2, 0x1272593e, 0x54a06c5a,
+ 0x69118086, 0xeffa6633, 0xd24b8aef, 0x9499bf8b, 0xa9285357,
+ 0x193dd543, 0x248c399f, 0x625e0cfb, 0x5fefe027, 0xb4f8c7d0,
+ 0x89492b0c, 0xcf9b1e68, 0xf22af2b4, 0x423f74a0, 0x7f8e987c,
+ 0x395cad18, 0x04ed41c4, 0x8206a771, 0xbfb74bad, 0xf9657ec9,
+ 0xc4d49215, 0x74c11401, 0x4970f8dd, 0x0fa2cdb9, 0x32132165,
+ 0x02fd8416, 0x3f4c68ca, 0x799e5dae, 0x442fb172, 0xf43a3766,
+ 0xc98bdbba, 0x8f59eede, 0xb2e80202, 0x3403e4b7, 0x09b2086b,
+ 0x4f603d0f, 0x72d1d1d3, 0xc2c457c7, 0xff75bb1b, 0xb9a78e7f,
+ 0x841662a3, 0x6f014554, 0x52b0a988, 0x14629cec, 0x29d37030,
+ 0x99c6f624, 0xa4771af8, 0xe2a52f9c, 0xdf14c340, 0x59ff25f5,
+ 0x644ec929, 0x229cfc4d, 0x1f2d1091, 0xaf389685, 0x92897a59,
+ 0xd45b4f3d, 0xe9eaa3e1, 0xb58605db, 0x8837e907, 0xcee5dc63,
+ 0xf35430bf, 0x4341b6ab, 0x7ef05a77, 0x38226f13, 0x059383cf,
+ 0x8378657a, 0xbec989a6, 0xf81bbcc2, 0xc5aa501e, 0x75bfd60a,
+ 0x480e3ad6, 0x0edc0fb2, 0x336de36e, 0xd87ac499, 0xe5cb2845,
+ 0xa3191d21, 0x9ea8f1fd, 0x2ebd77e9, 0x130c9b35, 0x55deae51,
+ 0x686f428d, 0xee84a438, 0xd33548e4, 0x95e77d80, 0xa856915c,
+ 0x18431748, 0x25f2fb94, 0x6320cef0, 0x5e91222c, 0x6e7f875f,
+ 0x53ce6b83, 0x151c5ee7, 0x28adb23b, 0x98b8342f, 0xa509d8f3,
+ 0xe3dbed97, 0xde6a014b, 0x5881e7fe, 0x65300b22, 0x23e23e46,
+ 0x1e53d29a, 0xae46548e, 0x93f7b852, 0xd5258d36, 0xe89461ea,
+ 0x0383461d, 0x3e32aac1, 0x78e09fa5, 0x45517379, 0xf544f56d,
+ 0xc8f519b1, 0x8e272cd5, 0xb396c009, 0x357d26bc, 0x08ccca60,
+ 0x4e1eff04, 0x73af13d8, 0xc3ba95cc, 0xfe0b7910, 0xb8d94c74,
+ 0x8568a0a8},
+ {0x00000000, 0x69790b65, 0xd2f216ca, 0xbb8b1daf, 0x7e952bd5,
+ 0x17ec20b0, 0xac673d1f, 0xc51e367a, 0xfd2a57aa, 0x94535ccf,
+ 0x2fd84160, 0x46a14a05, 0x83bf7c7f, 0xeac6771a, 0x514d6ab5,
+ 0x383461d0, 0x2125a915, 0x485ca270, 0xf3d7bfdf, 0x9aaeb4ba,
+ 0x5fb082c0, 0x36c989a5, 0x8d42940a, 0xe43b9f6f, 0xdc0ffebf,
+ 0xb576f5da, 0x0efde875, 0x6784e310, 0xa29ad56a, 0xcbe3de0f,
+ 0x7068c3a0, 0x1911c8c5, 0x424b522a, 0x2b32594f, 0x90b944e0,
+ 0xf9c04f85, 0x3cde79ff, 0x55a7729a, 0xee2c6f35, 0x87556450,
+ 0xbf610580, 0xd6180ee5, 0x6d93134a, 0x04ea182f, 0xc1f42e55,
+ 0xa88d2530, 0x1306389f, 0x7a7f33fa, 0x636efb3f, 0x0a17f05a,
+ 0xb19cedf5, 0xd8e5e690, 0x1dfbd0ea, 0x7482db8f, 0xcf09c620,
+ 0xa670cd45, 0x9e44ac95, 0xf73da7f0, 0x4cb6ba5f, 0x25cfb13a,
+ 0xe0d18740, 0x89a88c25, 0x3223918a, 0x5b5a9aef, 0x8496a454,
+ 0xedefaf31, 0x5664b29e, 0x3f1db9fb, 0xfa038f81, 0x937a84e4,
+ 0x28f1994b, 0x4188922e, 0x79bcf3fe, 0x10c5f89b, 0xab4ee534,
+ 0xc237ee51, 0x0729d82b, 0x6e50d34e, 0xd5dbcee1, 0xbca2c584,
+ 0xa5b30d41, 0xccca0624, 0x77411b8b, 0x1e3810ee, 0xdb262694,
+ 0xb25f2df1, 0x09d4305e, 0x60ad3b3b, 0x58995aeb, 0x31e0518e,
+ 0x8a6b4c21, 0xe3124744, 0x260c713e, 0x4f757a5b, 0xf4fe67f4,
+ 0x9d876c91, 0xc6ddf67e, 0xafa4fd1b, 0x142fe0b4, 0x7d56ebd1,
+ 0xb848ddab, 0xd131d6ce, 0x6abacb61, 0x03c3c004, 0x3bf7a1d4,
+ 0x528eaab1, 0xe905b71e, 0x807cbc7b, 0x45628a01, 0x2c1b8164,
+ 0x97909ccb, 0xfee997ae, 0xe7f85f6b, 0x8e81540e, 0x350a49a1,
+ 0x5c7342c4, 0x996d74be, 0xf0147fdb, 0x4b9f6274, 0x22e66911,
+ 0x1ad208c1, 0x73ab03a4, 0xc8201e0b, 0xa159156e, 0x64472314,
+ 0x0d3e2871, 0xb6b535de, 0xdfcc3ebb, 0xd25c4ee9, 0xbb25458c,
+ 0x00ae5823, 0x69d75346, 0xacc9653c, 0xc5b06e59, 0x7e3b73f6,
+ 0x17427893, 0x2f761943, 0x460f1226, 0xfd840f89, 0x94fd04ec,
+ 0x51e33296, 0x389a39f3, 0x8311245c, 0xea682f39, 0xf379e7fc,
+ 0x9a00ec99, 0x218bf136, 0x48f2fa53, 0x8deccc29, 0xe495c74c,
+ 0x5f1edae3, 0x3667d186, 0x0e53b056, 0x672abb33, 0xdca1a69c,
+ 0xb5d8adf9, 0x70c69b83, 0x19bf90e6, 0xa2348d49, 0xcb4d862c,
+ 0x90171cc3, 0xf96e17a6, 0x42e50a09, 0x2b9c016c, 0xee823716,
+ 0x87fb3c73, 0x3c7021dc, 0x55092ab9, 0x6d3d4b69, 0x0444400c,
+ 0xbfcf5da3, 0xd6b656c6, 0x13a860bc, 0x7ad16bd9, 0xc15a7676,
+ 0xa8237d13, 0xb132b5d6, 0xd84bbeb3, 0x63c0a31c, 0x0ab9a879,
+ 0xcfa79e03, 0xa6de9566, 0x1d5588c9, 0x742c83ac, 0x4c18e27c,
+ 0x2561e919, 0x9eeaf4b6, 0xf793ffd3, 0x328dc9a9, 0x5bf4c2cc,
+ 0xe07fdf63, 0x8906d406, 0x56caeabd, 0x3fb3e1d8, 0x8438fc77,
+ 0xed41f712, 0x285fc168, 0x4126ca0d, 0xfaadd7a2, 0x93d4dcc7,
+ 0xabe0bd17, 0xc299b672, 0x7912abdd, 0x106ba0b8, 0xd57596c2,
+ 0xbc0c9da7, 0x07878008, 0x6efe8b6d, 0x77ef43a8, 0x1e9648cd,
+ 0xa51d5562, 0xcc645e07, 0x097a687d, 0x60036318, 0xdb887eb7,
+ 0xb2f175d2, 0x8ac51402, 0xe3bc1f67, 0x583702c8, 0x314e09ad,
+ 0xf4503fd7, 0x9d2934b2, 0x26a2291d, 0x4fdb2278, 0x1481b897,
+ 0x7df8b3f2, 0xc673ae5d, 0xaf0aa538, 0x6a149342, 0x036d9827,
+ 0xb8e68588, 0xd19f8eed, 0xe9abef3d, 0x80d2e458, 0x3b59f9f7,
+ 0x5220f292, 0x973ec4e8, 0xfe47cf8d, 0x45ccd222, 0x2cb5d947,
+ 0x35a41182, 0x5cdd1ae7, 0xe7560748, 0x8e2f0c2d, 0x4b313a57,
+ 0x22483132, 0x99c32c9d, 0xf0ba27f8, 0xc88e4628, 0xa1f74d4d,
+ 0x1a7c50e2, 0x73055b87, 0xb61b6dfd, 0xdf626698, 0x64e97b37,
+ 0x0d907052},
+ {0x00000000, 0x7fc99b93, 0xff933726, 0x805aacb5, 0x2457680d,
+ 0x5b9ef39e, 0xdbc45f2b, 0xa40dc4b8, 0x48aed01a, 0x37674b89,
+ 0xb73de73c, 0xc8f47caf, 0x6cf9b817, 0x13302384, 0x936a8f31,
+ 0xeca314a2, 0x915da034, 0xee943ba7, 0x6ece9712, 0x11070c81,
+ 0xb50ac839, 0xcac353aa, 0x4a99ff1f, 0x3550648c, 0xd9f3702e,
+ 0xa63aebbd, 0x26604708, 0x59a9dc9b, 0xfda41823, 0x826d83b0,
+ 0x02372f05, 0x7dfeb496, 0xf9ca4629, 0x8603ddba, 0x0659710f,
+ 0x7990ea9c, 0xdd9d2e24, 0xa254b5b7, 0x220e1902, 0x5dc78291,
+ 0xb1649633, 0xcead0da0, 0x4ef7a115, 0x313e3a86, 0x9533fe3e,
+ 0xeafa65ad, 0x6aa0c918, 0x1569528b, 0x6897e61d, 0x175e7d8e,
+ 0x9704d13b, 0xe8cd4aa8, 0x4cc08e10, 0x33091583, 0xb353b936,
+ 0xcc9a22a5, 0x20393607, 0x5ff0ad94, 0xdfaa0121, 0xa0639ab2,
+ 0x046e5e0a, 0x7ba7c599, 0xfbfd692c, 0x8434f2bf, 0x28e58a13,
+ 0x572c1180, 0xd776bd35, 0xa8bf26a6, 0x0cb2e21e, 0x737b798d,
+ 0xf321d538, 0x8ce84eab, 0x604b5a09, 0x1f82c19a, 0x9fd86d2f,
+ 0xe011f6bc, 0x441c3204, 0x3bd5a997, 0xbb8f0522, 0xc4469eb1,
+ 0xb9b82a27, 0xc671b1b4, 0x462b1d01, 0x39e28692, 0x9def422a,
+ 0xe226d9b9, 0x627c750c, 0x1db5ee9f, 0xf116fa3d, 0x8edf61ae,
+ 0x0e85cd1b, 0x714c5688, 0xd5419230, 0xaa8809a3, 0x2ad2a516,
+ 0x551b3e85, 0xd12fcc3a, 0xaee657a9, 0x2ebcfb1c, 0x5175608f,
+ 0xf578a437, 0x8ab13fa4, 0x0aeb9311, 0x75220882, 0x99811c20,
+ 0xe64887b3, 0x66122b06, 0x19dbb095, 0xbdd6742d, 0xc21fefbe,
+ 0x4245430b, 0x3d8cd898, 0x40726c0e, 0x3fbbf79d, 0xbfe15b28,
+ 0xc028c0bb, 0x64250403, 0x1bec9f90, 0x9bb63325, 0xe47fa8b6,
+ 0x08dcbc14, 0x77152787, 0xf74f8b32, 0x888610a1, 0x2c8bd419,
+ 0x53424f8a, 0xd318e33f, 0xacd178ac, 0x51cb1426, 0x2e028fb5,
+ 0xae582300, 0xd191b893, 0x759c7c2b, 0x0a55e7b8, 0x8a0f4b0d,
+ 0xf5c6d09e, 0x1965c43c, 0x66ac5faf, 0xe6f6f31a, 0x993f6889,
+ 0x3d32ac31, 0x42fb37a2, 0xc2a19b17, 0xbd680084, 0xc096b412,
+ 0xbf5f2f81, 0x3f058334, 0x40cc18a7, 0xe4c1dc1f, 0x9b08478c,
+ 0x1b52eb39, 0x649b70aa, 0x88386408, 0xf7f1ff9b, 0x77ab532e,
+ 0x0862c8bd, 0xac6f0c05, 0xd3a69796, 0x53fc3b23, 0x2c35a0b0,
+ 0xa801520f, 0xd7c8c99c, 0x57926529, 0x285bfeba, 0x8c563a02,
+ 0xf39fa191, 0x73c50d24, 0x0c0c96b7, 0xe0af8215, 0x9f661986,
+ 0x1f3cb533, 0x60f52ea0, 0xc4f8ea18, 0xbb31718b, 0x3b6bdd3e,
+ 0x44a246ad, 0x395cf23b, 0x469569a8, 0xc6cfc51d, 0xb9065e8e,
+ 0x1d0b9a36, 0x62c201a5, 0xe298ad10, 0x9d513683, 0x71f22221,
+ 0x0e3bb9b2, 0x8e611507, 0xf1a88e94, 0x55a54a2c, 0x2a6cd1bf,
+ 0xaa367d0a, 0xd5ffe699, 0x792e9e35, 0x06e705a6, 0x86bda913,
+ 0xf9743280, 0x5d79f638, 0x22b06dab, 0xa2eac11e, 0xdd235a8d,
+ 0x31804e2f, 0x4e49d5bc, 0xce137909, 0xb1dae29a, 0x15d72622,
+ 0x6a1ebdb1, 0xea441104, 0x958d8a97, 0xe8733e01, 0x97baa592,
+ 0x17e00927, 0x682992b4, 0xcc24560c, 0xb3edcd9f, 0x33b7612a,
+ 0x4c7efab9, 0xa0ddee1b, 0xdf147588, 0x5f4ed93d, 0x208742ae,
+ 0x848a8616, 0xfb431d85, 0x7b19b130, 0x04d02aa3, 0x80e4d81c,
+ 0xff2d438f, 0x7f77ef3a, 0x00be74a9, 0xa4b3b011, 0xdb7a2b82,
+ 0x5b208737, 0x24e91ca4, 0xc84a0806, 0xb7839395, 0x37d93f20,
+ 0x4810a4b3, 0xec1d600b, 0x93d4fb98, 0x138e572d, 0x6c47ccbe,
+ 0x11b97828, 0x6e70e3bb, 0xee2a4f0e, 0x91e3d49d, 0x35ee1025,
+ 0x4a278bb6, 0xca7d2703, 0xb5b4bc90, 0x5917a832, 0x26de33a1,
+ 0xa6849f14, 0xd94d0487, 0x7d40c03f, 0x02895bac, 0x82d3f719,
+ 0xfd1a6c8a},
+ {0x00000000, 0xa396284c, 0x9c5d56d9, 0x3fcb7e95, 0xe3cbabf3,
+ 0x405d83bf, 0x7f96fd2a, 0xdc00d566, 0x1ce651a7, 0xbf7079eb,
+ 0x80bb077e, 0x232d2f32, 0xff2dfa54, 0x5cbbd218, 0x6370ac8d,
+ 0xc0e684c1, 0x39cca34e, 0x9a5a8b02, 0xa591f597, 0x0607dddb,
+ 0xda0708bd, 0x799120f1, 0x465a5e64, 0xe5cc7628, 0x252af2e9,
+ 0x86bcdaa5, 0xb977a430, 0x1ae18c7c, 0xc6e1591a, 0x65777156,
+ 0x5abc0fc3, 0xf92a278f, 0x7399469c, 0xd00f6ed0, 0xefc41045,
+ 0x4c523809, 0x9052ed6f, 0x33c4c523, 0x0c0fbbb6, 0xaf9993fa,
+ 0x6f7f173b, 0xcce93f77, 0xf32241e2, 0x50b469ae, 0x8cb4bcc8,
+ 0x2f229484, 0x10e9ea11, 0xb37fc25d, 0x4a55e5d2, 0xe9c3cd9e,
+ 0xd608b30b, 0x759e9b47, 0xa99e4e21, 0x0a08666d, 0x35c318f8,
+ 0x965530b4, 0x56b3b475, 0xf5259c39, 0xcaeee2ac, 0x6978cae0,
+ 0xb5781f86, 0x16ee37ca, 0x2925495f, 0x8ab36113, 0xe7328d38,
+ 0x44a4a574, 0x7b6fdbe1, 0xd8f9f3ad, 0x04f926cb, 0xa76f0e87,
+ 0x98a47012, 0x3b32585e, 0xfbd4dc9f, 0x5842f4d3, 0x67898a46,
+ 0xc41fa20a, 0x181f776c, 0xbb895f20, 0x844221b5, 0x27d409f9,
+ 0xdefe2e76, 0x7d68063a, 0x42a378af, 0xe13550e3, 0x3d358585,
+ 0x9ea3adc9, 0xa168d35c, 0x02fefb10, 0xc2187fd1, 0x618e579d,
+ 0x5e452908, 0xfdd30144, 0x21d3d422, 0x8245fc6e, 0xbd8e82fb,
+ 0x1e18aab7, 0x94abcba4, 0x373de3e8, 0x08f69d7d, 0xab60b531,
+ 0x77606057, 0xd4f6481b, 0xeb3d368e, 0x48ab1ec2, 0x884d9a03,
+ 0x2bdbb24f, 0x1410ccda, 0xb786e496, 0x6b8631f0, 0xc81019bc,
+ 0xf7db6729, 0x544d4f65, 0xad6768ea, 0x0ef140a6, 0x313a3e33,
+ 0x92ac167f, 0x4eacc319, 0xed3aeb55, 0xd2f195c0, 0x7167bd8c,
+ 0xb181394d, 0x12171101, 0x2ddc6f94, 0x8e4a47d8, 0x524a92be,
+ 0xf1dcbaf2, 0xce17c467, 0x6d81ec2b, 0x15141c31, 0xb682347d,
+ 0x89494ae8, 0x2adf62a4, 0xf6dfb7c2, 0x55499f8e, 0x6a82e11b,
+ 0xc914c957, 0x09f24d96, 0xaa6465da, 0x95af1b4f, 0x36393303,
+ 0xea39e665, 0x49afce29, 0x7664b0bc, 0xd5f298f0, 0x2cd8bf7f,
+ 0x8f4e9733, 0xb085e9a6, 0x1313c1ea, 0xcf13148c, 0x6c853cc0,
+ 0x534e4255, 0xf0d86a19, 0x303eeed8, 0x93a8c694, 0xac63b801,
+ 0x0ff5904d, 0xd3f5452b, 0x70636d67, 0x4fa813f2, 0xec3e3bbe,
+ 0x668d5aad, 0xc51b72e1, 0xfad00c74, 0x59462438, 0x8546f15e,
+ 0x26d0d912, 0x191ba787, 0xba8d8fcb, 0x7a6b0b0a, 0xd9fd2346,
+ 0xe6365dd3, 0x45a0759f, 0x99a0a0f9, 0x3a3688b5, 0x05fdf620,
+ 0xa66bde6c, 0x5f41f9e3, 0xfcd7d1af, 0xc31caf3a, 0x608a8776,
+ 0xbc8a5210, 0x1f1c7a5c, 0x20d704c9, 0x83412c85, 0x43a7a844,
+ 0xe0318008, 0xdffafe9d, 0x7c6cd6d1, 0xa06c03b7, 0x03fa2bfb,
+ 0x3c31556e, 0x9fa77d22, 0xf2269109, 0x51b0b945, 0x6e7bc7d0,
+ 0xcdedef9c, 0x11ed3afa, 0xb27b12b6, 0x8db06c23, 0x2e26446f,
+ 0xeec0c0ae, 0x4d56e8e2, 0x729d9677, 0xd10bbe3b, 0x0d0b6b5d,
+ 0xae9d4311, 0x91563d84, 0x32c015c8, 0xcbea3247, 0x687c1a0b,
+ 0x57b7649e, 0xf4214cd2, 0x282199b4, 0x8bb7b1f8, 0xb47ccf6d,
+ 0x17eae721, 0xd70c63e0, 0x749a4bac, 0x4b513539, 0xe8c71d75,
+ 0x34c7c813, 0x9751e05f, 0xa89a9eca, 0x0b0cb686, 0x81bfd795,
+ 0x2229ffd9, 0x1de2814c, 0xbe74a900, 0x62747c66, 0xc1e2542a,
+ 0xfe292abf, 0x5dbf02f3, 0x9d598632, 0x3ecfae7e, 0x0104d0eb,
+ 0xa292f8a7, 0x7e922dc1, 0xdd04058d, 0xe2cf7b18, 0x41595354,
+ 0xb87374db, 0x1be55c97, 0x242e2202, 0x87b80a4e, 0x5bb8df28,
+ 0xf82ef764, 0xc7e589f1, 0x6473a1bd, 0xa495257c, 0x07030d30,
+ 0x38c873a5, 0x9b5e5be9, 0x475e8e8f, 0xe4c8a6c3, 0xdb03d856,
+ 0x7895f01a},
+ {0x00000000, 0x2a283862, 0x545070c4, 0x7e7848a6, 0xa8a0e188,
+ 0x8288d9ea, 0xfcf0914c, 0xd6d8a92e, 0x8a30c551, 0xa018fd33,
+ 0xde60b595, 0xf4488df7, 0x229024d9, 0x08b81cbb, 0x76c0541d,
+ 0x5ce86c7f, 0xcf108ce3, 0xe538b481, 0x9b40fc27, 0xb168c445,
+ 0x67b06d6b, 0x4d985509, 0x33e01daf, 0x19c825cd, 0x452049b2,
+ 0x6f0871d0, 0x11703976, 0x3b580114, 0xed80a83a, 0xc7a89058,
+ 0xb9d0d8fe, 0x93f8e09c, 0x45501f87, 0x6f7827e5, 0x11006f43,
+ 0x3b285721, 0xedf0fe0f, 0xc7d8c66d, 0xb9a08ecb, 0x9388b6a9,
+ 0xcf60dad6, 0xe548e2b4, 0x9b30aa12, 0xb1189270, 0x67c03b5e,
+ 0x4de8033c, 0x33904b9a, 0x19b873f8, 0x8a409364, 0xa068ab06,
+ 0xde10e3a0, 0xf438dbc2, 0x22e072ec, 0x08c84a8e, 0x76b00228,
+ 0x5c983a4a, 0x00705635, 0x2a586e57, 0x542026f1, 0x7e081e93,
+ 0xa8d0b7bd, 0x82f88fdf, 0xfc80c779, 0xd6a8ff1b, 0x8aa03f0e,
+ 0xa088076c, 0xdef04fca, 0xf4d877a8, 0x2200de86, 0x0828e6e4,
+ 0x7650ae42, 0x5c789620, 0x0090fa5f, 0x2ab8c23d, 0x54c08a9b,
+ 0x7ee8b2f9, 0xa8301bd7, 0x821823b5, 0xfc606b13, 0xd6485371,
+ 0x45b0b3ed, 0x6f988b8f, 0x11e0c329, 0x3bc8fb4b, 0xed105265,
+ 0xc7386a07, 0xb94022a1, 0x93681ac3, 0xcf8076bc, 0xe5a84ede,
+ 0x9bd00678, 0xb1f83e1a, 0x67209734, 0x4d08af56, 0x3370e7f0,
+ 0x1958df92, 0xcff02089, 0xe5d818eb, 0x9ba0504d, 0xb188682f,
+ 0x6750c101, 0x4d78f963, 0x3300b1c5, 0x192889a7, 0x45c0e5d8,
+ 0x6fe8ddba, 0x1190951c, 0x3bb8ad7e, 0xed600450, 0xc7483c32,
+ 0xb9307494, 0x93184cf6, 0x00e0ac6a, 0x2ac89408, 0x54b0dcae,
+ 0x7e98e4cc, 0xa8404de2, 0x82687580, 0xfc103d26, 0xd6380544,
+ 0x8ad0693b, 0xa0f85159, 0xde8019ff, 0xf4a8219d, 0x227088b3,
+ 0x0858b0d1, 0x7620f877, 0x5c08c015, 0xce31785d, 0xe419403f,
+ 0x9a610899, 0xb04930fb, 0x669199d5, 0x4cb9a1b7, 0x32c1e911,
+ 0x18e9d173, 0x4401bd0c, 0x6e29856e, 0x1051cdc8, 0x3a79f5aa,
+ 0xeca15c84, 0xc68964e6, 0xb8f12c40, 0x92d91422, 0x0121f4be,
+ 0x2b09ccdc, 0x5571847a, 0x7f59bc18, 0xa9811536, 0x83a92d54,
+ 0xfdd165f2, 0xd7f95d90, 0x8b1131ef, 0xa139098d, 0xdf41412b,
+ 0xf5697949, 0x23b1d067, 0x0999e805, 0x77e1a0a3, 0x5dc998c1,
+ 0x8b6167da, 0xa1495fb8, 0xdf31171e, 0xf5192f7c, 0x23c18652,
+ 0x09e9be30, 0x7791f696, 0x5db9cef4, 0x0151a28b, 0x2b799ae9,
+ 0x5501d24f, 0x7f29ea2d, 0xa9f14303, 0x83d97b61, 0xfda133c7,
+ 0xd7890ba5, 0x4471eb39, 0x6e59d35b, 0x10219bfd, 0x3a09a39f,
+ 0xecd10ab1, 0xc6f932d3, 0xb8817a75, 0x92a94217, 0xce412e68,
+ 0xe469160a, 0x9a115eac, 0xb03966ce, 0x66e1cfe0, 0x4cc9f782,
+ 0x32b1bf24, 0x18998746, 0x44914753, 0x6eb97f31, 0x10c13797,
+ 0x3ae90ff5, 0xec31a6db, 0xc6199eb9, 0xb861d61f, 0x9249ee7d,
+ 0xcea18202, 0xe489ba60, 0x9af1f2c6, 0xb0d9caa4, 0x6601638a,
+ 0x4c295be8, 0x3251134e, 0x18792b2c, 0x8b81cbb0, 0xa1a9f3d2,
+ 0xdfd1bb74, 0xf5f98316, 0x23212a38, 0x0909125a, 0x77715afc,
+ 0x5d59629e, 0x01b10ee1, 0x2b993683, 0x55e17e25, 0x7fc94647,
+ 0xa911ef69, 0x8339d70b, 0xfd419fad, 0xd769a7cf, 0x01c158d4,
+ 0x2be960b6, 0x55912810, 0x7fb91072, 0xa961b95c, 0x8349813e,
+ 0xfd31c998, 0xd719f1fa, 0x8bf19d85, 0xa1d9a5e7, 0xdfa1ed41,
+ 0xf589d523, 0x23517c0d, 0x0979446f, 0x77010cc9, 0x5d2934ab,
+ 0xced1d437, 0xe4f9ec55, 0x9a81a4f3, 0xb0a99c91, 0x667135bf,
+ 0x4c590ddd, 0x3221457b, 0x18097d19, 0x44e11166, 0x6ec92904,
+ 0x10b161a2, 0x3a9959c0, 0xec41f0ee, 0xc669c88c, 0xb811802a,
+ 0x9239b848},
+ {0x00000000, 0x4713f6fb, 0x8e27edf6, 0xc9341b0d, 0xc73eddad,
+ 0x802d2b56, 0x4919305b, 0x0e0ac6a0, 0x550cbd1b, 0x121f4be0,
+ 0xdb2b50ed, 0x9c38a616, 0x923260b6, 0xd521964d, 0x1c158d40,
+ 0x5b067bbb, 0xaa197a36, 0xed0a8ccd, 0x243e97c0, 0x632d613b,
+ 0x6d27a79b, 0x2a345160, 0xe3004a6d, 0xa413bc96, 0xff15c72d,
+ 0xb80631d6, 0x71322adb, 0x3621dc20, 0x382b1a80, 0x7f38ec7b,
+ 0xb60cf776, 0xf11f018d, 0x8f43f22d, 0xc85004d6, 0x01641fdb,
+ 0x4677e920, 0x487d2f80, 0x0f6ed97b, 0xc65ac276, 0x8149348d,
+ 0xda4f4f36, 0x9d5cb9cd, 0x5468a2c0, 0x137b543b, 0x1d71929b,
+ 0x5a626460, 0x93567f6d, 0xd4458996, 0x255a881b, 0x62497ee0,
+ 0xab7d65ed, 0xec6e9316, 0xe26455b6, 0xa577a34d, 0x6c43b840,
+ 0x2b504ebb, 0x70563500, 0x3745c3fb, 0xfe71d8f6, 0xb9622e0d,
+ 0xb768e8ad, 0xf07b1e56, 0x394f055b, 0x7e5cf3a0, 0xc5f6e21b,
+ 0x82e514e0, 0x4bd10fed, 0x0cc2f916, 0x02c83fb6, 0x45dbc94d,
+ 0x8cefd240, 0xcbfc24bb, 0x90fa5f00, 0xd7e9a9fb, 0x1eddb2f6,
+ 0x59ce440d, 0x57c482ad, 0x10d77456, 0xd9e36f5b, 0x9ef099a0,
+ 0x6fef982d, 0x28fc6ed6, 0xe1c875db, 0xa6db8320, 0xa8d14580,
+ 0xefc2b37b, 0x26f6a876, 0x61e55e8d, 0x3ae32536, 0x7df0d3cd,
+ 0xb4c4c8c0, 0xf3d73e3b, 0xfdddf89b, 0xbace0e60, 0x73fa156d,
+ 0x34e9e396, 0x4ab51036, 0x0da6e6cd, 0xc492fdc0, 0x83810b3b,
+ 0x8d8bcd9b, 0xca983b60, 0x03ac206d, 0x44bfd696, 0x1fb9ad2d,
+ 0x58aa5bd6, 0x919e40db, 0xd68db620, 0xd8877080, 0x9f94867b,
+ 0x56a09d76, 0x11b36b8d, 0xe0ac6a00, 0xa7bf9cfb, 0x6e8b87f6,
+ 0x2998710d, 0x2792b7ad, 0x60814156, 0xa9b55a5b, 0xeea6aca0,
+ 0xb5a0d71b, 0xf2b321e0, 0x3b873aed, 0x7c94cc16, 0x729e0ab6,
+ 0x358dfc4d, 0xfcb9e740, 0xbbaa11bb, 0x509cc277, 0x178f348c,
+ 0xdebb2f81, 0x99a8d97a, 0x97a21fda, 0xd0b1e921, 0x1985f22c,
+ 0x5e9604d7, 0x05907f6c, 0x42838997, 0x8bb7929a, 0xcca46461,
+ 0xc2aea2c1, 0x85bd543a, 0x4c894f37, 0x0b9ab9cc, 0xfa85b841,
+ 0xbd964eba, 0x74a255b7, 0x33b1a34c, 0x3dbb65ec, 0x7aa89317,
+ 0xb39c881a, 0xf48f7ee1, 0xaf89055a, 0xe89af3a1, 0x21aee8ac,
+ 0x66bd1e57, 0x68b7d8f7, 0x2fa42e0c, 0xe6903501, 0xa183c3fa,
+ 0xdfdf305a, 0x98ccc6a1, 0x51f8ddac, 0x16eb2b57, 0x18e1edf7,
+ 0x5ff21b0c, 0x96c60001, 0xd1d5f6fa, 0x8ad38d41, 0xcdc07bba,
+ 0x04f460b7, 0x43e7964c, 0x4ded50ec, 0x0afea617, 0xc3cabd1a,
+ 0x84d94be1, 0x75c64a6c, 0x32d5bc97, 0xfbe1a79a, 0xbcf25161,
+ 0xb2f897c1, 0xf5eb613a, 0x3cdf7a37, 0x7bcc8ccc, 0x20caf777,
+ 0x67d9018c, 0xaeed1a81, 0xe9feec7a, 0xe7f42ada, 0xa0e7dc21,
+ 0x69d3c72c, 0x2ec031d7, 0x956a206c, 0xd279d697, 0x1b4dcd9a,
+ 0x5c5e3b61, 0x5254fdc1, 0x15470b3a, 0xdc731037, 0x9b60e6cc,
+ 0xc0669d77, 0x87756b8c, 0x4e417081, 0x0952867a, 0x075840da,
+ 0x404bb621, 0x897fad2c, 0xce6c5bd7, 0x3f735a5a, 0x7860aca1,
+ 0xb154b7ac, 0xf6474157, 0xf84d87f7, 0xbf5e710c, 0x766a6a01,
+ 0x31799cfa, 0x6a7fe741, 0x2d6c11ba, 0xe4580ab7, 0xa34bfc4c,
+ 0xad413aec, 0xea52cc17, 0x2366d71a, 0x647521e1, 0x1a29d241,
+ 0x5d3a24ba, 0x940e3fb7, 0xd31dc94c, 0xdd170fec, 0x9a04f917,
+ 0x5330e21a, 0x142314e1, 0x4f256f5a, 0x083699a1, 0xc10282ac,
+ 0x86117457, 0x881bb2f7, 0xcf08440c, 0x063c5f01, 0x412fa9fa,
+ 0xb030a877, 0xf7235e8c, 0x3e174581, 0x7904b37a, 0x770e75da,
+ 0x301d8321, 0xf929982c, 0xbe3a6ed7, 0xe53c156c, 0xa22fe397,
+ 0x6b1bf89a, 0x2c080e61, 0x2202c8c1, 0x65113e3a, 0xac252537,
+ 0xeb36d3cc},
+ {0x00000000, 0xa13984ee, 0x99020f9d, 0x383b8b73, 0xe975197b,
+ 0x484c9d95, 0x707716e6, 0xd14e9208, 0x099b34b7, 0xa8a2b059,
+ 0x90993b2a, 0x31a0bfc4, 0xe0ee2dcc, 0x41d7a922, 0x79ec2251,
+ 0xd8d5a6bf, 0x1336696e, 0xb20fed80, 0x8a3466f3, 0x2b0de21d,
+ 0xfa437015, 0x5b7af4fb, 0x63417f88, 0xc278fb66, 0x1aad5dd9,
+ 0xbb94d937, 0x83af5244, 0x2296d6aa, 0xf3d844a2, 0x52e1c04c,
+ 0x6ada4b3f, 0xcbe3cfd1, 0x266cd2dc, 0x87555632, 0xbf6edd41,
+ 0x1e5759af, 0xcf19cba7, 0x6e204f49, 0x561bc43a, 0xf72240d4,
+ 0x2ff7e66b, 0x8ece6285, 0xb6f5e9f6, 0x17cc6d18, 0xc682ff10,
+ 0x67bb7bfe, 0x5f80f08d, 0xfeb97463, 0x355abbb2, 0x94633f5c,
+ 0xac58b42f, 0x0d6130c1, 0xdc2fa2c9, 0x7d162627, 0x452dad54,
+ 0xe41429ba, 0x3cc18f05, 0x9df80beb, 0xa5c38098, 0x04fa0476,
+ 0xd5b4967e, 0x748d1290, 0x4cb699e3, 0xed8f1d0d, 0x4cd9a5b8,
+ 0xede02156, 0xd5dbaa25, 0x74e22ecb, 0xa5acbcc3, 0x0495382d,
+ 0x3caeb35e, 0x9d9737b0, 0x4542910f, 0xe47b15e1, 0xdc409e92,
+ 0x7d791a7c, 0xac378874, 0x0d0e0c9a, 0x353587e9, 0x940c0307,
+ 0x5fefccd6, 0xfed64838, 0xc6edc34b, 0x67d447a5, 0xb69ad5ad,
+ 0x17a35143, 0x2f98da30, 0x8ea15ede, 0x5674f861, 0xf74d7c8f,
+ 0xcf76f7fc, 0x6e4f7312, 0xbf01e11a, 0x1e3865f4, 0x2603ee87,
+ 0x873a6a69, 0x6ab57764, 0xcb8cf38a, 0xf3b778f9, 0x528efc17,
+ 0x83c06e1f, 0x22f9eaf1, 0x1ac26182, 0xbbfbe56c, 0x632e43d3,
+ 0xc217c73d, 0xfa2c4c4e, 0x5b15c8a0, 0x8a5b5aa8, 0x2b62de46,
+ 0x13595535, 0xb260d1db, 0x79831e0a, 0xd8ba9ae4, 0xe0811197,
+ 0x41b89579, 0x90f60771, 0x31cf839f, 0x09f408ec, 0xa8cd8c02,
+ 0x70182abd, 0xd121ae53, 0xe91a2520, 0x4823a1ce, 0x996d33c6,
+ 0x3854b728, 0x006f3c5b, 0xa156b8b5, 0x99b34b70, 0x388acf9e,
+ 0x00b144ed, 0xa188c003, 0x70c6520b, 0xd1ffd6e5, 0xe9c45d96,
+ 0x48fdd978, 0x90287fc7, 0x3111fb29, 0x092a705a, 0xa813f4b4,
+ 0x795d66bc, 0xd864e252, 0xe05f6921, 0x4166edcf, 0x8a85221e,
+ 0x2bbca6f0, 0x13872d83, 0xb2bea96d, 0x63f03b65, 0xc2c9bf8b,
+ 0xfaf234f8, 0x5bcbb016, 0x831e16a9, 0x22279247, 0x1a1c1934,
+ 0xbb259dda, 0x6a6b0fd2, 0xcb528b3c, 0xf369004f, 0x525084a1,
+ 0xbfdf99ac, 0x1ee61d42, 0x26dd9631, 0x87e412df, 0x56aa80d7,
+ 0xf7930439, 0xcfa88f4a, 0x6e910ba4, 0xb644ad1b, 0x177d29f5,
+ 0x2f46a286, 0x8e7f2668, 0x5f31b460, 0xfe08308e, 0xc633bbfd,
+ 0x670a3f13, 0xace9f0c2, 0x0dd0742c, 0x35ebff5f, 0x94d27bb1,
+ 0x459ce9b9, 0xe4a56d57, 0xdc9ee624, 0x7da762ca, 0xa572c475,
+ 0x044b409b, 0x3c70cbe8, 0x9d494f06, 0x4c07dd0e, 0xed3e59e0,
+ 0xd505d293, 0x743c567d, 0xd56aeec8, 0x74536a26, 0x4c68e155,
+ 0xed5165bb, 0x3c1ff7b3, 0x9d26735d, 0xa51df82e, 0x04247cc0,
+ 0xdcf1da7f, 0x7dc85e91, 0x45f3d5e2, 0xe4ca510c, 0x3584c304,
+ 0x94bd47ea, 0xac86cc99, 0x0dbf4877, 0xc65c87a6, 0x67650348,
+ 0x5f5e883b, 0xfe670cd5, 0x2f299edd, 0x8e101a33, 0xb62b9140,
+ 0x171215ae, 0xcfc7b311, 0x6efe37ff, 0x56c5bc8c, 0xf7fc3862,
+ 0x26b2aa6a, 0x878b2e84, 0xbfb0a5f7, 0x1e892119, 0xf3063c14,
+ 0x523fb8fa, 0x6a043389, 0xcb3db767, 0x1a73256f, 0xbb4aa181,
+ 0x83712af2, 0x2248ae1c, 0xfa9d08a3, 0x5ba48c4d, 0x639f073e,
+ 0xc2a683d0, 0x13e811d8, 0xb2d19536, 0x8aea1e45, 0x2bd39aab,
+ 0xe030557a, 0x4109d194, 0x79325ae7, 0xd80bde09, 0x09454c01,
+ 0xa87cc8ef, 0x9047439c, 0x317ec772, 0xe9ab61cd, 0x4892e523,
+ 0x70a96e50, 0xd190eabe, 0x00de78b6, 0xa1e7fc58, 0x99dc772b,
+ 0x38e5f3c5},
+ {0x00000000, 0xe81790a1, 0x0b5e2703, 0xe349b7a2, 0x16bc4e06,
+ 0xfeabdea7, 0x1de26905, 0xf5f5f9a4, 0x2d789c0c, 0xc56f0cad,
+ 0x2626bb0f, 0xce312bae, 0x3bc4d20a, 0xd3d342ab, 0x309af509,
+ 0xd88d65a8, 0x5af13818, 0xb2e6a8b9, 0x51af1f1b, 0xb9b88fba,
+ 0x4c4d761e, 0xa45ae6bf, 0x4713511d, 0xaf04c1bc, 0x7789a414,
+ 0x9f9e34b5, 0x7cd78317, 0x94c013b6, 0x6135ea12, 0x89227ab3,
+ 0x6a6bcd11, 0x827c5db0, 0xb5e27030, 0x5df5e091, 0xbebc5733,
+ 0x56abc792, 0xa35e3e36, 0x4b49ae97, 0xa8001935, 0x40178994,
+ 0x989aec3c, 0x708d7c9d, 0x93c4cb3f, 0x7bd35b9e, 0x8e26a23a,
+ 0x6631329b, 0x85788539, 0x6d6f1598, 0xef134828, 0x0704d889,
+ 0xe44d6f2b, 0x0c5aff8a, 0xf9af062e, 0x11b8968f, 0xf2f1212d,
+ 0x1ae6b18c, 0xc26bd424, 0x2a7c4485, 0xc935f327, 0x21226386,
+ 0xd4d79a22, 0x3cc00a83, 0xdf89bd21, 0x379e2d80, 0xb0b5e621,
+ 0x58a27680, 0xbbebc122, 0x53fc5183, 0xa609a827, 0x4e1e3886,
+ 0xad578f24, 0x45401f85, 0x9dcd7a2d, 0x75daea8c, 0x96935d2e,
+ 0x7e84cd8f, 0x8b71342b, 0x6366a48a, 0x802f1328, 0x68388389,
+ 0xea44de39, 0x02534e98, 0xe11af93a, 0x090d699b, 0xfcf8903f,
+ 0x14ef009e, 0xf7a6b73c, 0x1fb1279d, 0xc73c4235, 0x2f2bd294,
+ 0xcc626536, 0x2475f597, 0xd1800c33, 0x39979c92, 0xdade2b30,
+ 0x32c9bb91, 0x05579611, 0xed4006b0, 0x0e09b112, 0xe61e21b3,
+ 0x13ebd817, 0xfbfc48b6, 0x18b5ff14, 0xf0a26fb5, 0x282f0a1d,
+ 0xc0389abc, 0x23712d1e, 0xcb66bdbf, 0x3e93441b, 0xd684d4ba,
+ 0x35cd6318, 0xdddaf3b9, 0x5fa6ae09, 0xb7b13ea8, 0x54f8890a,
+ 0xbcef19ab, 0x491ae00f, 0xa10d70ae, 0x4244c70c, 0xaa5357ad,
+ 0x72de3205, 0x9ac9a2a4, 0x79801506, 0x919785a7, 0x64627c03,
+ 0x8c75eca2, 0x6f3c5b00, 0x872bcba1, 0xba1aca03, 0x520d5aa2,
+ 0xb144ed00, 0x59537da1, 0xaca68405, 0x44b114a4, 0xa7f8a306,
+ 0x4fef33a7, 0x9762560f, 0x7f75c6ae, 0x9c3c710c, 0x742be1ad,
+ 0x81de1809, 0x69c988a8, 0x8a803f0a, 0x6297afab, 0xe0ebf21b,
+ 0x08fc62ba, 0xebb5d518, 0x03a245b9, 0xf657bc1d, 0x1e402cbc,
+ 0xfd099b1e, 0x151e0bbf, 0xcd936e17, 0x2584feb6, 0xc6cd4914,
+ 0x2edad9b5, 0xdb2f2011, 0x3338b0b0, 0xd0710712, 0x386697b3,
+ 0x0ff8ba33, 0xe7ef2a92, 0x04a69d30, 0xecb10d91, 0x1944f435,
+ 0xf1536494, 0x121ad336, 0xfa0d4397, 0x2280263f, 0xca97b69e,
+ 0x29de013c, 0xc1c9919d, 0x343c6839, 0xdc2bf898, 0x3f624f3a,
+ 0xd775df9b, 0x5509822b, 0xbd1e128a, 0x5e57a528, 0xb6403589,
+ 0x43b5cc2d, 0xaba25c8c, 0x48ebeb2e, 0xa0fc7b8f, 0x78711e27,
+ 0x90668e86, 0x732f3924, 0x9b38a985, 0x6ecd5021, 0x86dac080,
+ 0x65937722, 0x8d84e783, 0x0aaf2c22, 0xe2b8bc83, 0x01f10b21,
+ 0xe9e69b80, 0x1c136224, 0xf404f285, 0x174d4527, 0xff5ad586,
+ 0x27d7b02e, 0xcfc0208f, 0x2c89972d, 0xc49e078c, 0x316bfe28,
+ 0xd97c6e89, 0x3a35d92b, 0xd222498a, 0x505e143a, 0xb849849b,
+ 0x5b003339, 0xb317a398, 0x46e25a3c, 0xaef5ca9d, 0x4dbc7d3f,
+ 0xa5abed9e, 0x7d268836, 0x95311897, 0x7678af35, 0x9e6f3f94,
+ 0x6b9ac630, 0x838d5691, 0x60c4e133, 0x88d37192, 0xbf4d5c12,
+ 0x575accb3, 0xb4137b11, 0x5c04ebb0, 0xa9f11214, 0x41e682b5,
+ 0xa2af3517, 0x4ab8a5b6, 0x9235c01e, 0x7a2250bf, 0x996be71d,
+ 0x717c77bc, 0x84898e18, 0x6c9e1eb9, 0x8fd7a91b, 0x67c039ba,
+ 0xe5bc640a, 0x0dabf4ab, 0xeee24309, 0x06f5d3a8, 0xf3002a0c,
+ 0x1b17baad, 0xf85e0d0f, 0x10499dae, 0xc8c4f806, 0x20d368a7,
+ 0xc39adf05, 0x2b8d4fa4, 0xde78b600, 0x366f26a1, 0xd5269103,
+ 0x3d3101a2}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x0000000000000000, 0xa19017e800000000, 0x03275e0b00000000,
+ 0xa2b749e300000000, 0x064ebc1600000000, 0xa7deabfe00000000,
+ 0x0569e21d00000000, 0xa4f9f5f500000000, 0x0c9c782d00000000,
+ 0xad0c6fc500000000, 0x0fbb262600000000, 0xae2b31ce00000000,
+ 0x0ad2c43b00000000, 0xab42d3d300000000, 0x09f59a3000000000,
+ 0xa8658dd800000000, 0x1838f15a00000000, 0xb9a8e6b200000000,
+ 0x1b1faf5100000000, 0xba8fb8b900000000, 0x1e764d4c00000000,
+ 0xbfe65aa400000000, 0x1d51134700000000, 0xbcc104af00000000,
+ 0x14a4897700000000, 0xb5349e9f00000000, 0x1783d77c00000000,
+ 0xb613c09400000000, 0x12ea356100000000, 0xb37a228900000000,
+ 0x11cd6b6a00000000, 0xb05d7c8200000000, 0x3070e2b500000000,
+ 0x91e0f55d00000000, 0x3357bcbe00000000, 0x92c7ab5600000000,
+ 0x363e5ea300000000, 0x97ae494b00000000, 0x351900a800000000,
+ 0x9489174000000000, 0x3cec9a9800000000, 0x9d7c8d7000000000,
+ 0x3fcbc49300000000, 0x9e5bd37b00000000, 0x3aa2268e00000000,
+ 0x9b32316600000000, 0x3985788500000000, 0x98156f6d00000000,
+ 0x284813ef00000000, 0x89d8040700000000, 0x2b6f4de400000000,
+ 0x8aff5a0c00000000, 0x2e06aff900000000, 0x8f96b81100000000,
+ 0x2d21f1f200000000, 0x8cb1e61a00000000, 0x24d46bc200000000,
+ 0x85447c2a00000000, 0x27f335c900000000, 0x8663222100000000,
+ 0x229ad7d400000000, 0x830ac03c00000000, 0x21bd89df00000000,
+ 0x802d9e3700000000, 0x21e6b5b000000000, 0x8076a25800000000,
+ 0x22c1ebbb00000000, 0x8351fc5300000000, 0x27a809a600000000,
+ 0x86381e4e00000000, 0x248f57ad00000000, 0x851f404500000000,
+ 0x2d7acd9d00000000, 0x8ceada7500000000, 0x2e5d939600000000,
+ 0x8fcd847e00000000, 0x2b34718b00000000, 0x8aa4666300000000,
+ 0x28132f8000000000, 0x8983386800000000, 0x39de44ea00000000,
+ 0x984e530200000000, 0x3af91ae100000000, 0x9b690d0900000000,
+ 0x3f90f8fc00000000, 0x9e00ef1400000000, 0x3cb7a6f700000000,
+ 0x9d27b11f00000000, 0x35423cc700000000, 0x94d22b2f00000000,
+ 0x366562cc00000000, 0x97f5752400000000, 0x330c80d100000000,
+ 0x929c973900000000, 0x302bdeda00000000, 0x91bbc93200000000,
+ 0x1196570500000000, 0xb00640ed00000000, 0x12b1090e00000000,
+ 0xb3211ee600000000, 0x17d8eb1300000000, 0xb648fcfb00000000,
+ 0x14ffb51800000000, 0xb56fa2f000000000, 0x1d0a2f2800000000,
+ 0xbc9a38c000000000, 0x1e2d712300000000, 0xbfbd66cb00000000,
+ 0x1b44933e00000000, 0xbad484d600000000, 0x1863cd3500000000,
+ 0xb9f3dadd00000000, 0x09aea65f00000000, 0xa83eb1b700000000,
+ 0x0a89f85400000000, 0xab19efbc00000000, 0x0fe01a4900000000,
+ 0xae700da100000000, 0x0cc7444200000000, 0xad5753aa00000000,
+ 0x0532de7200000000, 0xa4a2c99a00000000, 0x0615807900000000,
+ 0xa785979100000000, 0x037c626400000000, 0xa2ec758c00000000,
+ 0x005b3c6f00000000, 0xa1cb2b8700000000, 0x03ca1aba00000000,
+ 0xa25a0d5200000000, 0x00ed44b100000000, 0xa17d535900000000,
+ 0x0584a6ac00000000, 0xa414b14400000000, 0x06a3f8a700000000,
+ 0xa733ef4f00000000, 0x0f56629700000000, 0xaec6757f00000000,
+ 0x0c713c9c00000000, 0xade12b7400000000, 0x0918de8100000000,
+ 0xa888c96900000000, 0x0a3f808a00000000, 0xabaf976200000000,
+ 0x1bf2ebe000000000, 0xba62fc0800000000, 0x18d5b5eb00000000,
+ 0xb945a20300000000, 0x1dbc57f600000000, 0xbc2c401e00000000,
+ 0x1e9b09fd00000000, 0xbf0b1e1500000000, 0x176e93cd00000000,
+ 0xb6fe842500000000, 0x1449cdc600000000, 0xb5d9da2e00000000,
+ 0x11202fdb00000000, 0xb0b0383300000000, 0x120771d000000000,
+ 0xb397663800000000, 0x33baf80f00000000, 0x922aefe700000000,
+ 0x309da60400000000, 0x910db1ec00000000, 0x35f4441900000000,
+ 0x946453f100000000, 0x36d31a1200000000, 0x97430dfa00000000,
+ 0x3f26802200000000, 0x9eb697ca00000000, 0x3c01de2900000000,
+ 0x9d91c9c100000000, 0x39683c3400000000, 0x98f82bdc00000000,
+ 0x3a4f623f00000000, 0x9bdf75d700000000, 0x2b82095500000000,
+ 0x8a121ebd00000000, 0x28a5575e00000000, 0x893540b600000000,
+ 0x2dccb54300000000, 0x8c5ca2ab00000000, 0x2eebeb4800000000,
+ 0x8f7bfca000000000, 0x271e717800000000, 0x868e669000000000,
+ 0x24392f7300000000, 0x85a9389b00000000, 0x2150cd6e00000000,
+ 0x80c0da8600000000, 0x2277936500000000, 0x83e7848d00000000,
+ 0x222caf0a00000000, 0x83bcb8e200000000, 0x210bf10100000000,
+ 0x809be6e900000000, 0x2462131c00000000, 0x85f204f400000000,
+ 0x27454d1700000000, 0x86d55aff00000000, 0x2eb0d72700000000,
+ 0x8f20c0cf00000000, 0x2d97892c00000000, 0x8c079ec400000000,
+ 0x28fe6b3100000000, 0x896e7cd900000000, 0x2bd9353a00000000,
+ 0x8a4922d200000000, 0x3a145e5000000000, 0x9b8449b800000000,
+ 0x3933005b00000000, 0x98a317b300000000, 0x3c5ae24600000000,
+ 0x9dcaf5ae00000000, 0x3f7dbc4d00000000, 0x9eedaba500000000,
+ 0x3688267d00000000, 0x9718319500000000, 0x35af787600000000,
+ 0x943f6f9e00000000, 0x30c69a6b00000000, 0x91568d8300000000,
+ 0x33e1c46000000000, 0x9271d38800000000, 0x125c4dbf00000000,
+ 0xb3cc5a5700000000, 0x117b13b400000000, 0xb0eb045c00000000,
+ 0x1412f1a900000000, 0xb582e64100000000, 0x1735afa200000000,
+ 0xb6a5b84a00000000, 0x1ec0359200000000, 0xbf50227a00000000,
+ 0x1de76b9900000000, 0xbc777c7100000000, 0x188e898400000000,
+ 0xb91e9e6c00000000, 0x1ba9d78f00000000, 0xba39c06700000000,
+ 0x0a64bce500000000, 0xabf4ab0d00000000, 0x0943e2ee00000000,
+ 0xa8d3f50600000000, 0x0c2a00f300000000, 0xadba171b00000000,
+ 0x0f0d5ef800000000, 0xae9d491000000000, 0x06f8c4c800000000,
+ 0xa768d32000000000, 0x05df9ac300000000, 0xa44f8d2b00000000,
+ 0x00b678de00000000, 0xa1266f3600000000, 0x039126d500000000,
+ 0xa201313d00000000},
+ {0x0000000000000000, 0xee8439a100000000, 0x9d0f029900000000,
+ 0x738b3b3800000000, 0x7b1975e900000000, 0x959d4c4800000000,
+ 0xe616777000000000, 0x08924ed100000000, 0xb7349b0900000000,
+ 0x59b0a2a800000000, 0x2a3b999000000000, 0xc4bfa03100000000,
+ 0xcc2deee000000000, 0x22a9d74100000000, 0x5122ec7900000000,
+ 0xbfa6d5d800000000, 0x6e69361300000000, 0x80ed0fb200000000,
+ 0xf366348a00000000, 0x1de20d2b00000000, 0x157043fa00000000,
+ 0xfbf47a5b00000000, 0x887f416300000000, 0x66fb78c200000000,
+ 0xd95dad1a00000000, 0x37d994bb00000000, 0x4452af8300000000,
+ 0xaad6962200000000, 0xa244d8f300000000, 0x4cc0e15200000000,
+ 0x3f4bda6a00000000, 0xd1cfe3cb00000000, 0xdcd26c2600000000,
+ 0x3256558700000000, 0x41dd6ebf00000000, 0xaf59571e00000000,
+ 0xa7cb19cf00000000, 0x494f206e00000000, 0x3ac41b5600000000,
+ 0xd44022f700000000, 0x6be6f72f00000000, 0x8562ce8e00000000,
+ 0xf6e9f5b600000000, 0x186dcc1700000000, 0x10ff82c600000000,
+ 0xfe7bbb6700000000, 0x8df0805f00000000, 0x6374b9fe00000000,
+ 0xb2bb5a3500000000, 0x5c3f639400000000, 0x2fb458ac00000000,
+ 0xc130610d00000000, 0xc9a22fdc00000000, 0x2726167d00000000,
+ 0x54ad2d4500000000, 0xba2914e400000000, 0x058fc13c00000000,
+ 0xeb0bf89d00000000, 0x9880c3a500000000, 0x7604fa0400000000,
+ 0x7e96b4d500000000, 0x90128d7400000000, 0xe399b64c00000000,
+ 0x0d1d8fed00000000, 0xb8a5d94c00000000, 0x5621e0ed00000000,
+ 0x25aadbd500000000, 0xcb2ee27400000000, 0xc3bcaca500000000,
+ 0x2d38950400000000, 0x5eb3ae3c00000000, 0xb037979d00000000,
+ 0x0f91424500000000, 0xe1157be400000000, 0x929e40dc00000000,
+ 0x7c1a797d00000000, 0x748837ac00000000, 0x9a0c0e0d00000000,
+ 0xe987353500000000, 0x07030c9400000000, 0xd6ccef5f00000000,
+ 0x3848d6fe00000000, 0x4bc3edc600000000, 0xa547d46700000000,
+ 0xadd59ab600000000, 0x4351a31700000000, 0x30da982f00000000,
+ 0xde5ea18e00000000, 0x61f8745600000000, 0x8f7c4df700000000,
+ 0xfcf776cf00000000, 0x12734f6e00000000, 0x1ae101bf00000000,
+ 0xf465381e00000000, 0x87ee032600000000, 0x696a3a8700000000,
+ 0x6477b56a00000000, 0x8af38ccb00000000, 0xf978b7f300000000,
+ 0x17fc8e5200000000, 0x1f6ec08300000000, 0xf1eaf92200000000,
+ 0x8261c21a00000000, 0x6ce5fbbb00000000, 0xd3432e6300000000,
+ 0x3dc717c200000000, 0x4e4c2cfa00000000, 0xa0c8155b00000000,
+ 0xa85a5b8a00000000, 0x46de622b00000000, 0x3555591300000000,
+ 0xdbd160b200000000, 0x0a1e837900000000, 0xe49abad800000000,
+ 0x971181e000000000, 0x7995b84100000000, 0x7107f69000000000,
+ 0x9f83cf3100000000, 0xec08f40900000000, 0x028ccda800000000,
+ 0xbd2a187000000000, 0x53ae21d100000000, 0x20251ae900000000,
+ 0xcea1234800000000, 0xc6336d9900000000, 0x28b7543800000000,
+ 0x5b3c6f0000000000, 0xb5b856a100000000, 0x704bb39900000000,
+ 0x9ecf8a3800000000, 0xed44b10000000000, 0x03c088a100000000,
+ 0x0b52c67000000000, 0xe5d6ffd100000000, 0x965dc4e900000000,
+ 0x78d9fd4800000000, 0xc77f289000000000, 0x29fb113100000000,
+ 0x5a702a0900000000, 0xb4f413a800000000, 0xbc665d7900000000,
+ 0x52e264d800000000, 0x21695fe000000000, 0xcfed664100000000,
+ 0x1e22858a00000000, 0xf0a6bc2b00000000, 0x832d871300000000,
+ 0x6da9beb200000000, 0x653bf06300000000, 0x8bbfc9c200000000,
+ 0xf834f2fa00000000, 0x16b0cb5b00000000, 0xa9161e8300000000,
+ 0x4792272200000000, 0x34191c1a00000000, 0xda9d25bb00000000,
+ 0xd20f6b6a00000000, 0x3c8b52cb00000000, 0x4f0069f300000000,
+ 0xa184505200000000, 0xac99dfbf00000000, 0x421de61e00000000,
+ 0x3196dd2600000000, 0xdf12e48700000000, 0xd780aa5600000000,
+ 0x390493f700000000, 0x4a8fa8cf00000000, 0xa40b916e00000000,
+ 0x1bad44b600000000, 0xf5297d1700000000, 0x86a2462f00000000,
+ 0x68267f8e00000000, 0x60b4315f00000000, 0x8e3008fe00000000,
+ 0xfdbb33c600000000, 0x133f0a6700000000, 0xc2f0e9ac00000000,
+ 0x2c74d00d00000000, 0x5fffeb3500000000, 0xb17bd29400000000,
+ 0xb9e99c4500000000, 0x576da5e400000000, 0x24e69edc00000000,
+ 0xca62a77d00000000, 0x75c472a500000000, 0x9b404b0400000000,
+ 0xe8cb703c00000000, 0x064f499d00000000, 0x0edd074c00000000,
+ 0xe0593eed00000000, 0x93d205d500000000, 0x7d563c7400000000,
+ 0xc8ee6ad500000000, 0x266a537400000000, 0x55e1684c00000000,
+ 0xbb6551ed00000000, 0xb3f71f3c00000000, 0x5d73269d00000000,
+ 0x2ef81da500000000, 0xc07c240400000000, 0x7fdaf1dc00000000,
+ 0x915ec87d00000000, 0xe2d5f34500000000, 0x0c51cae400000000,
+ 0x04c3843500000000, 0xea47bd9400000000, 0x99cc86ac00000000,
+ 0x7748bf0d00000000, 0xa6875cc600000000, 0x4803656700000000,
+ 0x3b885e5f00000000, 0xd50c67fe00000000, 0xdd9e292f00000000,
+ 0x331a108e00000000, 0x40912bb600000000, 0xae15121700000000,
+ 0x11b3c7cf00000000, 0xff37fe6e00000000, 0x8cbcc55600000000,
+ 0x6238fcf700000000, 0x6aaab22600000000, 0x842e8b8700000000,
+ 0xf7a5b0bf00000000, 0x1921891e00000000, 0x143c06f300000000,
+ 0xfab83f5200000000, 0x8933046a00000000, 0x67b73dcb00000000,
+ 0x6f25731a00000000, 0x81a14abb00000000, 0xf22a718300000000,
+ 0x1cae482200000000, 0xa3089dfa00000000, 0x4d8ca45b00000000,
+ 0x3e079f6300000000, 0xd083a6c200000000, 0xd811e81300000000,
+ 0x3695d1b200000000, 0x451eea8a00000000, 0xab9ad32b00000000,
+ 0x7a5530e000000000, 0x94d1094100000000, 0xe75a327900000000,
+ 0x09de0bd800000000, 0x014c450900000000, 0xefc87ca800000000,
+ 0x9c43479000000000, 0x72c77e3100000000, 0xcd61abe900000000,
+ 0x23e5924800000000, 0x506ea97000000000, 0xbeea90d100000000,
+ 0xb678de0000000000, 0x58fce7a100000000, 0x2b77dc9900000000,
+ 0xc5f3e53800000000},
+ {0x0000000000000000, 0xfbf6134700000000, 0xf6ed278e00000000,
+ 0x0d1b34c900000000, 0xaddd3ec700000000, 0x562b2d8000000000,
+ 0x5b30194900000000, 0xa0c60a0e00000000, 0x1bbd0c5500000000,
+ 0xe04b1f1200000000, 0xed502bdb00000000, 0x16a6389c00000000,
+ 0xb660329200000000, 0x4d9621d500000000, 0x408d151c00000000,
+ 0xbb7b065b00000000, 0x367a19aa00000000, 0xcd8c0aed00000000,
+ 0xc0973e2400000000, 0x3b612d6300000000, 0x9ba7276d00000000,
+ 0x6051342a00000000, 0x6d4a00e300000000, 0x96bc13a400000000,
+ 0x2dc715ff00000000, 0xd63106b800000000, 0xdb2a327100000000,
+ 0x20dc213600000000, 0x801a2b3800000000, 0x7bec387f00000000,
+ 0x76f70cb600000000, 0x8d011ff100000000, 0x2df2438f00000000,
+ 0xd60450c800000000, 0xdb1f640100000000, 0x20e9774600000000,
+ 0x802f7d4800000000, 0x7bd96e0f00000000, 0x76c25ac600000000,
+ 0x8d34498100000000, 0x364f4fda00000000, 0xcdb95c9d00000000,
+ 0xc0a2685400000000, 0x3b547b1300000000, 0x9b92711d00000000,
+ 0x6064625a00000000, 0x6d7f569300000000, 0x968945d400000000,
+ 0x1b885a2500000000, 0xe07e496200000000, 0xed657dab00000000,
+ 0x16936eec00000000, 0xb65564e200000000, 0x4da377a500000000,
+ 0x40b8436c00000000, 0xbb4e502b00000000, 0x0035567000000000,
+ 0xfbc3453700000000, 0xf6d871fe00000000, 0x0d2e62b900000000,
+ 0xade868b700000000, 0x561e7bf000000000, 0x5b054f3900000000,
+ 0xa0f35c7e00000000, 0x1be2f6c500000000, 0xe014e58200000000,
+ 0xed0fd14b00000000, 0x16f9c20c00000000, 0xb63fc80200000000,
+ 0x4dc9db4500000000, 0x40d2ef8c00000000, 0xbb24fccb00000000,
+ 0x005ffa9000000000, 0xfba9e9d700000000, 0xf6b2dd1e00000000,
+ 0x0d44ce5900000000, 0xad82c45700000000, 0x5674d71000000000,
+ 0x5b6fe3d900000000, 0xa099f09e00000000, 0x2d98ef6f00000000,
+ 0xd66efc2800000000, 0xdb75c8e100000000, 0x2083dba600000000,
+ 0x8045d1a800000000, 0x7bb3c2ef00000000, 0x76a8f62600000000,
+ 0x8d5ee56100000000, 0x3625e33a00000000, 0xcdd3f07d00000000,
+ 0xc0c8c4b400000000, 0x3b3ed7f300000000, 0x9bf8ddfd00000000,
+ 0x600eceba00000000, 0x6d15fa7300000000, 0x96e3e93400000000,
+ 0x3610b54a00000000, 0xcde6a60d00000000, 0xc0fd92c400000000,
+ 0x3b0b818300000000, 0x9bcd8b8d00000000, 0x603b98ca00000000,
+ 0x6d20ac0300000000, 0x96d6bf4400000000, 0x2dadb91f00000000,
+ 0xd65baa5800000000, 0xdb409e9100000000, 0x20b68dd600000000,
+ 0x807087d800000000, 0x7b86949f00000000, 0x769da05600000000,
+ 0x8d6bb31100000000, 0x006aace000000000, 0xfb9cbfa700000000,
+ 0xf6878b6e00000000, 0x0d71982900000000, 0xadb7922700000000,
+ 0x5641816000000000, 0x5b5ab5a900000000, 0xa0aca6ee00000000,
+ 0x1bd7a0b500000000, 0xe021b3f200000000, 0xed3a873b00000000,
+ 0x16cc947c00000000, 0xb60a9e7200000000, 0x4dfc8d3500000000,
+ 0x40e7b9fc00000000, 0xbb11aabb00000000, 0x77c29c5000000000,
+ 0x8c348f1700000000, 0x812fbbde00000000, 0x7ad9a89900000000,
+ 0xda1fa29700000000, 0x21e9b1d000000000, 0x2cf2851900000000,
+ 0xd704965e00000000, 0x6c7f900500000000, 0x9789834200000000,
+ 0x9a92b78b00000000, 0x6164a4cc00000000, 0xc1a2aec200000000,
+ 0x3a54bd8500000000, 0x374f894c00000000, 0xccb99a0b00000000,
+ 0x41b885fa00000000, 0xba4e96bd00000000, 0xb755a27400000000,
+ 0x4ca3b13300000000, 0xec65bb3d00000000, 0x1793a87a00000000,
+ 0x1a889cb300000000, 0xe17e8ff400000000, 0x5a0589af00000000,
+ 0xa1f39ae800000000, 0xace8ae2100000000, 0x571ebd6600000000,
+ 0xf7d8b76800000000, 0x0c2ea42f00000000, 0x013590e600000000,
+ 0xfac383a100000000, 0x5a30dfdf00000000, 0xa1c6cc9800000000,
+ 0xacddf85100000000, 0x572beb1600000000, 0xf7ede11800000000,
+ 0x0c1bf25f00000000, 0x0100c69600000000, 0xfaf6d5d100000000,
+ 0x418dd38a00000000, 0xba7bc0cd00000000, 0xb760f40400000000,
+ 0x4c96e74300000000, 0xec50ed4d00000000, 0x17a6fe0a00000000,
+ 0x1abdcac300000000, 0xe14bd98400000000, 0x6c4ac67500000000,
+ 0x97bcd53200000000, 0x9aa7e1fb00000000, 0x6151f2bc00000000,
+ 0xc197f8b200000000, 0x3a61ebf500000000, 0x377adf3c00000000,
+ 0xcc8ccc7b00000000, 0x77f7ca2000000000, 0x8c01d96700000000,
+ 0x811aedae00000000, 0x7aecfee900000000, 0xda2af4e700000000,
+ 0x21dce7a000000000, 0x2cc7d36900000000, 0xd731c02e00000000,
+ 0x6c206a9500000000, 0x97d679d200000000, 0x9acd4d1b00000000,
+ 0x613b5e5c00000000, 0xc1fd545200000000, 0x3a0b471500000000,
+ 0x371073dc00000000, 0xcce6609b00000000, 0x779d66c000000000,
+ 0x8c6b758700000000, 0x8170414e00000000, 0x7a86520900000000,
+ 0xda40580700000000, 0x21b64b4000000000, 0x2cad7f8900000000,
+ 0xd75b6cce00000000, 0x5a5a733f00000000, 0xa1ac607800000000,
+ 0xacb754b100000000, 0x574147f600000000, 0xf7874df800000000,
+ 0x0c715ebf00000000, 0x016a6a7600000000, 0xfa9c793100000000,
+ 0x41e77f6a00000000, 0xba116c2d00000000, 0xb70a58e400000000,
+ 0x4cfc4ba300000000, 0xec3a41ad00000000, 0x17cc52ea00000000,
+ 0x1ad7662300000000, 0xe121756400000000, 0x41d2291a00000000,
+ 0xba243a5d00000000, 0xb73f0e9400000000, 0x4cc91dd300000000,
+ 0xec0f17dd00000000, 0x17f9049a00000000, 0x1ae2305300000000,
+ 0xe114231400000000, 0x5a6f254f00000000, 0xa199360800000000,
+ 0xac8202c100000000, 0x5774118600000000, 0xf7b21b8800000000,
+ 0x0c4408cf00000000, 0x015f3c0600000000, 0xfaa92f4100000000,
+ 0x77a830b000000000, 0x8c5e23f700000000, 0x8145173e00000000,
+ 0x7ab3047900000000, 0xda750e7700000000, 0x21831d3000000000,
+ 0x2c9829f900000000, 0xd76e3abe00000000, 0x6c153ce500000000,
+ 0x97e32fa200000000, 0x9af81b6b00000000, 0x610e082c00000000,
+ 0xc1c8022200000000, 0x3a3e116500000000, 0x372525ac00000000,
+ 0xccd336eb00000000},
+ {0x0000000000000000, 0x6238282a00000000, 0xc470505400000000,
+ 0xa648787e00000000, 0x88e1a0a800000000, 0xead9888200000000,
+ 0x4c91f0fc00000000, 0x2ea9d8d600000000, 0x51c5308a00000000,
+ 0x33fd18a000000000, 0x95b560de00000000, 0xf78d48f400000000,
+ 0xd924902200000000, 0xbb1cb80800000000, 0x1d54c07600000000,
+ 0x7f6ce85c00000000, 0xe38c10cf00000000, 0x81b438e500000000,
+ 0x27fc409b00000000, 0x45c468b100000000, 0x6b6db06700000000,
+ 0x0955984d00000000, 0xaf1de03300000000, 0xcd25c81900000000,
+ 0xb249204500000000, 0xd071086f00000000, 0x7639701100000000,
+ 0x1401583b00000000, 0x3aa880ed00000000, 0x5890a8c700000000,
+ 0xfed8d0b900000000, 0x9ce0f89300000000, 0x871f504500000000,
+ 0xe527786f00000000, 0x436f001100000000, 0x2157283b00000000,
+ 0x0ffef0ed00000000, 0x6dc6d8c700000000, 0xcb8ea0b900000000,
+ 0xa9b6889300000000, 0xd6da60cf00000000, 0xb4e248e500000000,
+ 0x12aa309b00000000, 0x709218b100000000, 0x5e3bc06700000000,
+ 0x3c03e84d00000000, 0x9a4b903300000000, 0xf873b81900000000,
+ 0x6493408a00000000, 0x06ab68a000000000, 0xa0e310de00000000,
+ 0xc2db38f400000000, 0xec72e02200000000, 0x8e4ac80800000000,
+ 0x2802b07600000000, 0x4a3a985c00000000, 0x3556700000000000,
+ 0x576e582a00000000, 0xf126205400000000, 0x931e087e00000000,
+ 0xbdb7d0a800000000, 0xdf8ff88200000000, 0x79c780fc00000000,
+ 0x1bffa8d600000000, 0x0e3fa08a00000000, 0x6c0788a000000000,
+ 0xca4ff0de00000000, 0xa877d8f400000000, 0x86de002200000000,
+ 0xe4e6280800000000, 0x42ae507600000000, 0x2096785c00000000,
+ 0x5ffa900000000000, 0x3dc2b82a00000000, 0x9b8ac05400000000,
+ 0xf9b2e87e00000000, 0xd71b30a800000000, 0xb523188200000000,
+ 0x136b60fc00000000, 0x715348d600000000, 0xedb3b04500000000,
+ 0x8f8b986f00000000, 0x29c3e01100000000, 0x4bfbc83b00000000,
+ 0x655210ed00000000, 0x076a38c700000000, 0xa12240b900000000,
+ 0xc31a689300000000, 0xbc7680cf00000000, 0xde4ea8e500000000,
+ 0x7806d09b00000000, 0x1a3ef8b100000000, 0x3497206700000000,
+ 0x56af084d00000000, 0xf0e7703300000000, 0x92df581900000000,
+ 0x8920f0cf00000000, 0xeb18d8e500000000, 0x4d50a09b00000000,
+ 0x2f6888b100000000, 0x01c1506700000000, 0x63f9784d00000000,
+ 0xc5b1003300000000, 0xa789281900000000, 0xd8e5c04500000000,
+ 0xbadde86f00000000, 0x1c95901100000000, 0x7eadb83b00000000,
+ 0x500460ed00000000, 0x323c48c700000000, 0x947430b900000000,
+ 0xf64c189300000000, 0x6aace00000000000, 0x0894c82a00000000,
+ 0xaedcb05400000000, 0xcce4987e00000000, 0xe24d40a800000000,
+ 0x8075688200000000, 0x263d10fc00000000, 0x440538d600000000,
+ 0x3b69d08a00000000, 0x5951f8a000000000, 0xff1980de00000000,
+ 0x9d21a8f400000000, 0xb388702200000000, 0xd1b0580800000000,
+ 0x77f8207600000000, 0x15c0085c00000000, 0x5d7831ce00000000,
+ 0x3f4019e400000000, 0x9908619a00000000, 0xfb3049b000000000,
+ 0xd599916600000000, 0xb7a1b94c00000000, 0x11e9c13200000000,
+ 0x73d1e91800000000, 0x0cbd014400000000, 0x6e85296e00000000,
+ 0xc8cd511000000000, 0xaaf5793a00000000, 0x845ca1ec00000000,
+ 0xe66489c600000000, 0x402cf1b800000000, 0x2214d99200000000,
+ 0xbef4210100000000, 0xdccc092b00000000, 0x7a84715500000000,
+ 0x18bc597f00000000, 0x361581a900000000, 0x542da98300000000,
+ 0xf265d1fd00000000, 0x905df9d700000000, 0xef31118b00000000,
+ 0x8d0939a100000000, 0x2b4141df00000000, 0x497969f500000000,
+ 0x67d0b12300000000, 0x05e8990900000000, 0xa3a0e17700000000,
+ 0xc198c95d00000000, 0xda67618b00000000, 0xb85f49a100000000,
+ 0x1e1731df00000000, 0x7c2f19f500000000, 0x5286c12300000000,
+ 0x30bee90900000000, 0x96f6917700000000, 0xf4ceb95d00000000,
+ 0x8ba2510100000000, 0xe99a792b00000000, 0x4fd2015500000000,
+ 0x2dea297f00000000, 0x0343f1a900000000, 0x617bd98300000000,
+ 0xc733a1fd00000000, 0xa50b89d700000000, 0x39eb714400000000,
+ 0x5bd3596e00000000, 0xfd9b211000000000, 0x9fa3093a00000000,
+ 0xb10ad1ec00000000, 0xd332f9c600000000, 0x757a81b800000000,
+ 0x1742a99200000000, 0x682e41ce00000000, 0x0a1669e400000000,
+ 0xac5e119a00000000, 0xce6639b000000000, 0xe0cfe16600000000,
+ 0x82f7c94c00000000, 0x24bfb13200000000, 0x4687991800000000,
+ 0x5347914400000000, 0x317fb96e00000000, 0x9737c11000000000,
+ 0xf50fe93a00000000, 0xdba631ec00000000, 0xb99e19c600000000,
+ 0x1fd661b800000000, 0x7dee499200000000, 0x0282a1ce00000000,
+ 0x60ba89e400000000, 0xc6f2f19a00000000, 0xa4cad9b000000000,
+ 0x8a63016600000000, 0xe85b294c00000000, 0x4e13513200000000,
+ 0x2c2b791800000000, 0xb0cb818b00000000, 0xd2f3a9a100000000,
+ 0x74bbd1df00000000, 0x1683f9f500000000, 0x382a212300000000,
+ 0x5a12090900000000, 0xfc5a717700000000, 0x9e62595d00000000,
+ 0xe10eb10100000000, 0x8336992b00000000, 0x257ee15500000000,
+ 0x4746c97f00000000, 0x69ef11a900000000, 0x0bd7398300000000,
+ 0xad9f41fd00000000, 0xcfa769d700000000, 0xd458c10100000000,
+ 0xb660e92b00000000, 0x1028915500000000, 0x7210b97f00000000,
+ 0x5cb961a900000000, 0x3e81498300000000, 0x98c931fd00000000,
+ 0xfaf119d700000000, 0x859df18b00000000, 0xe7a5d9a100000000,
+ 0x41eda1df00000000, 0x23d589f500000000, 0x0d7c512300000000,
+ 0x6f44790900000000, 0xc90c017700000000, 0xab34295d00000000,
+ 0x37d4d1ce00000000, 0x55ecf9e400000000, 0xf3a4819a00000000,
+ 0x919ca9b000000000, 0xbf35716600000000, 0xdd0d594c00000000,
+ 0x7b45213200000000, 0x197d091800000000, 0x6611e14400000000,
+ 0x0429c96e00000000, 0xa261b11000000000, 0xc059993a00000000,
+ 0xeef041ec00000000, 0x8cc869c600000000, 0x2a8011b800000000,
+ 0x48b8399200000000},
+ {0x0000000000000000, 0x4c2896a300000000, 0xd9565d9c00000000,
+ 0x957ecb3f00000000, 0xf3abcbe300000000, 0xbf835d4000000000,
+ 0x2afd967f00000000, 0x66d500dc00000000, 0xa751e61c00000000,
+ 0xeb7970bf00000000, 0x7e07bb8000000000, 0x322f2d2300000000,
+ 0x54fa2dff00000000, 0x18d2bb5c00000000, 0x8dac706300000000,
+ 0xc184e6c000000000, 0x4ea3cc3900000000, 0x028b5a9a00000000,
+ 0x97f591a500000000, 0xdbdd070600000000, 0xbd0807da00000000,
+ 0xf120917900000000, 0x645e5a4600000000, 0x2876cce500000000,
+ 0xe9f22a2500000000, 0xa5dabc8600000000, 0x30a477b900000000,
+ 0x7c8ce11a00000000, 0x1a59e1c600000000, 0x5671776500000000,
+ 0xc30fbc5a00000000, 0x8f272af900000000, 0x9c46997300000000,
+ 0xd06e0fd000000000, 0x4510c4ef00000000, 0x0938524c00000000,
+ 0x6fed529000000000, 0x23c5c43300000000, 0xb6bb0f0c00000000,
+ 0xfa9399af00000000, 0x3b177f6f00000000, 0x773fe9cc00000000,
+ 0xe24122f300000000, 0xae69b45000000000, 0xc8bcb48c00000000,
+ 0x8494222f00000000, 0x11eae91000000000, 0x5dc27fb300000000,
+ 0xd2e5554a00000000, 0x9ecdc3e900000000, 0x0bb308d600000000,
+ 0x479b9e7500000000, 0x214e9ea900000000, 0x6d66080a00000000,
+ 0xf818c33500000000, 0xb430559600000000, 0x75b4b35600000000,
+ 0x399c25f500000000, 0xace2eeca00000000, 0xe0ca786900000000,
+ 0x861f78b500000000, 0xca37ee1600000000, 0x5f49252900000000,
+ 0x1361b38a00000000, 0x388d32e700000000, 0x74a5a44400000000,
+ 0xe1db6f7b00000000, 0xadf3f9d800000000, 0xcb26f90400000000,
+ 0x870e6fa700000000, 0x1270a49800000000, 0x5e58323b00000000,
+ 0x9fdcd4fb00000000, 0xd3f4425800000000, 0x468a896700000000,
+ 0x0aa21fc400000000, 0x6c771f1800000000, 0x205f89bb00000000,
+ 0xb521428400000000, 0xf909d42700000000, 0x762efede00000000,
+ 0x3a06687d00000000, 0xaf78a34200000000, 0xe35035e100000000,
+ 0x8585353d00000000, 0xc9ada39e00000000, 0x5cd368a100000000,
+ 0x10fbfe0200000000, 0xd17f18c200000000, 0x9d578e6100000000,
+ 0x0829455e00000000, 0x4401d3fd00000000, 0x22d4d32100000000,
+ 0x6efc458200000000, 0xfb828ebd00000000, 0xb7aa181e00000000,
+ 0xa4cbab9400000000, 0xe8e33d3700000000, 0x7d9df60800000000,
+ 0x31b560ab00000000, 0x5760607700000000, 0x1b48f6d400000000,
+ 0x8e363deb00000000, 0xc21eab4800000000, 0x039a4d8800000000,
+ 0x4fb2db2b00000000, 0xdacc101400000000, 0x96e486b700000000,
+ 0xf031866b00000000, 0xbc1910c800000000, 0x2967dbf700000000,
+ 0x654f4d5400000000, 0xea6867ad00000000, 0xa640f10e00000000,
+ 0x333e3a3100000000, 0x7f16ac9200000000, 0x19c3ac4e00000000,
+ 0x55eb3aed00000000, 0xc095f1d200000000, 0x8cbd677100000000,
+ 0x4d3981b100000000, 0x0111171200000000, 0x946fdc2d00000000,
+ 0xd8474a8e00000000, 0xbe924a5200000000, 0xf2badcf100000000,
+ 0x67c417ce00000000, 0x2bec816d00000000, 0x311c141500000000,
+ 0x7d3482b600000000, 0xe84a498900000000, 0xa462df2a00000000,
+ 0xc2b7dff600000000, 0x8e9f495500000000, 0x1be1826a00000000,
+ 0x57c914c900000000, 0x964df20900000000, 0xda6564aa00000000,
+ 0x4f1baf9500000000, 0x0333393600000000, 0x65e639ea00000000,
+ 0x29ceaf4900000000, 0xbcb0647600000000, 0xf098f2d500000000,
+ 0x7fbfd82c00000000, 0x33974e8f00000000, 0xa6e985b000000000,
+ 0xeac1131300000000, 0x8c1413cf00000000, 0xc03c856c00000000,
+ 0x55424e5300000000, 0x196ad8f000000000, 0xd8ee3e3000000000,
+ 0x94c6a89300000000, 0x01b863ac00000000, 0x4d90f50f00000000,
+ 0x2b45f5d300000000, 0x676d637000000000, 0xf213a84f00000000,
+ 0xbe3b3eec00000000, 0xad5a8d6600000000, 0xe1721bc500000000,
+ 0x740cd0fa00000000, 0x3824465900000000, 0x5ef1468500000000,
+ 0x12d9d02600000000, 0x87a71b1900000000, 0xcb8f8dba00000000,
+ 0x0a0b6b7a00000000, 0x4623fdd900000000, 0xd35d36e600000000,
+ 0x9f75a04500000000, 0xf9a0a09900000000, 0xb588363a00000000,
+ 0x20f6fd0500000000, 0x6cde6ba600000000, 0xe3f9415f00000000,
+ 0xafd1d7fc00000000, 0x3aaf1cc300000000, 0x76878a6000000000,
+ 0x10528abc00000000, 0x5c7a1c1f00000000, 0xc904d72000000000,
+ 0x852c418300000000, 0x44a8a74300000000, 0x088031e000000000,
+ 0x9dfefadf00000000, 0xd1d66c7c00000000, 0xb7036ca000000000,
+ 0xfb2bfa0300000000, 0x6e55313c00000000, 0x227da79f00000000,
+ 0x099126f200000000, 0x45b9b05100000000, 0xd0c77b6e00000000,
+ 0x9cefedcd00000000, 0xfa3aed1100000000, 0xb6127bb200000000,
+ 0x236cb08d00000000, 0x6f44262e00000000, 0xaec0c0ee00000000,
+ 0xe2e8564d00000000, 0x77969d7200000000, 0x3bbe0bd100000000,
+ 0x5d6b0b0d00000000, 0x11439dae00000000, 0x843d569100000000,
+ 0xc815c03200000000, 0x4732eacb00000000, 0x0b1a7c6800000000,
+ 0x9e64b75700000000, 0xd24c21f400000000, 0xb499212800000000,
+ 0xf8b1b78b00000000, 0x6dcf7cb400000000, 0x21e7ea1700000000,
+ 0xe0630cd700000000, 0xac4b9a7400000000, 0x3935514b00000000,
+ 0x751dc7e800000000, 0x13c8c73400000000, 0x5fe0519700000000,
+ 0xca9e9aa800000000, 0x86b60c0b00000000, 0x95d7bf8100000000,
+ 0xd9ff292200000000, 0x4c81e21d00000000, 0x00a974be00000000,
+ 0x667c746200000000, 0x2a54e2c100000000, 0xbf2a29fe00000000,
+ 0xf302bf5d00000000, 0x3286599d00000000, 0x7eaecf3e00000000,
+ 0xebd0040100000000, 0xa7f892a200000000, 0xc12d927e00000000,
+ 0x8d0504dd00000000, 0x187bcfe200000000, 0x5453594100000000,
+ 0xdb7473b800000000, 0x975ce51b00000000, 0x02222e2400000000,
+ 0x4e0ab88700000000, 0x28dfb85b00000000, 0x64f72ef800000000,
+ 0xf189e5c700000000, 0xbda1736400000000, 0x7c2595a400000000,
+ 0x300d030700000000, 0xa573c83800000000, 0xe95b5e9b00000000,
+ 0x8f8e5e4700000000, 0xc3a6c8e400000000, 0x56d803db00000000,
+ 0x1af0957800000000},
+ {0x0000000000000000, 0x939bc97f00000000, 0x263793ff00000000,
+ 0xb5ac5a8000000000, 0x0d68572400000000, 0x9ef39e5b00000000,
+ 0x2b5fc4db00000000, 0xb8c40da400000000, 0x1ad0ae4800000000,
+ 0x894b673700000000, 0x3ce73db700000000, 0xaf7cf4c800000000,
+ 0x17b8f96c00000000, 0x8423301300000000, 0x318f6a9300000000,
+ 0xa214a3ec00000000, 0x34a05d9100000000, 0xa73b94ee00000000,
+ 0x1297ce6e00000000, 0x810c071100000000, 0x39c80ab500000000,
+ 0xaa53c3ca00000000, 0x1fff994a00000000, 0x8c64503500000000,
+ 0x2e70f3d900000000, 0xbdeb3aa600000000, 0x0847602600000000,
+ 0x9bdca95900000000, 0x2318a4fd00000000, 0xb0836d8200000000,
+ 0x052f370200000000, 0x96b4fe7d00000000, 0x2946caf900000000,
+ 0xbadd038600000000, 0x0f71590600000000, 0x9cea907900000000,
+ 0x242e9ddd00000000, 0xb7b554a200000000, 0x02190e2200000000,
+ 0x9182c75d00000000, 0x339664b100000000, 0xa00dadce00000000,
+ 0x15a1f74e00000000, 0x863a3e3100000000, 0x3efe339500000000,
+ 0xad65faea00000000, 0x18c9a06a00000000, 0x8b52691500000000,
+ 0x1de6976800000000, 0x8e7d5e1700000000, 0x3bd1049700000000,
+ 0xa84acde800000000, 0x108ec04c00000000, 0x8315093300000000,
+ 0x36b953b300000000, 0xa5229acc00000000, 0x0736392000000000,
+ 0x94adf05f00000000, 0x2101aadf00000000, 0xb29a63a000000000,
+ 0x0a5e6e0400000000, 0x99c5a77b00000000, 0x2c69fdfb00000000,
+ 0xbff2348400000000, 0x138ae52800000000, 0x80112c5700000000,
+ 0x35bd76d700000000, 0xa626bfa800000000, 0x1ee2b20c00000000,
+ 0x8d797b7300000000, 0x38d521f300000000, 0xab4ee88c00000000,
+ 0x095a4b6000000000, 0x9ac1821f00000000, 0x2f6dd89f00000000,
+ 0xbcf611e000000000, 0x04321c4400000000, 0x97a9d53b00000000,
+ 0x22058fbb00000000, 0xb19e46c400000000, 0x272ab8b900000000,
+ 0xb4b171c600000000, 0x011d2b4600000000, 0x9286e23900000000,
+ 0x2a42ef9d00000000, 0xb9d926e200000000, 0x0c757c6200000000,
+ 0x9feeb51d00000000, 0x3dfa16f100000000, 0xae61df8e00000000,
+ 0x1bcd850e00000000, 0x88564c7100000000, 0x309241d500000000,
+ 0xa30988aa00000000, 0x16a5d22a00000000, 0x853e1b5500000000,
+ 0x3acc2fd100000000, 0xa957e6ae00000000, 0x1cfbbc2e00000000,
+ 0x8f60755100000000, 0x37a478f500000000, 0xa43fb18a00000000,
+ 0x1193eb0a00000000, 0x8208227500000000, 0x201c819900000000,
+ 0xb38748e600000000, 0x062b126600000000, 0x95b0db1900000000,
+ 0x2d74d6bd00000000, 0xbeef1fc200000000, 0x0b43454200000000,
+ 0x98d88c3d00000000, 0x0e6c724000000000, 0x9df7bb3f00000000,
+ 0x285be1bf00000000, 0xbbc028c000000000, 0x0304256400000000,
+ 0x909fec1b00000000, 0x2533b69b00000000, 0xb6a87fe400000000,
+ 0x14bcdc0800000000, 0x8727157700000000, 0x328b4ff700000000,
+ 0xa110868800000000, 0x19d48b2c00000000, 0x8a4f425300000000,
+ 0x3fe318d300000000, 0xac78d1ac00000000, 0x2614cb5100000000,
+ 0xb58f022e00000000, 0x002358ae00000000, 0x93b891d100000000,
+ 0x2b7c9c7500000000, 0xb8e7550a00000000, 0x0d4b0f8a00000000,
+ 0x9ed0c6f500000000, 0x3cc4651900000000, 0xaf5fac6600000000,
+ 0x1af3f6e600000000, 0x89683f9900000000, 0x31ac323d00000000,
+ 0xa237fb4200000000, 0x179ba1c200000000, 0x840068bd00000000,
+ 0x12b496c000000000, 0x812f5fbf00000000, 0x3483053f00000000,
+ 0xa718cc4000000000, 0x1fdcc1e400000000, 0x8c47089b00000000,
+ 0x39eb521b00000000, 0xaa709b6400000000, 0x0864388800000000,
+ 0x9bfff1f700000000, 0x2e53ab7700000000, 0xbdc8620800000000,
+ 0x050c6fac00000000, 0x9697a6d300000000, 0x233bfc5300000000,
+ 0xb0a0352c00000000, 0x0f5201a800000000, 0x9cc9c8d700000000,
+ 0x2965925700000000, 0xbafe5b2800000000, 0x023a568c00000000,
+ 0x91a19ff300000000, 0x240dc57300000000, 0xb7960c0c00000000,
+ 0x1582afe000000000, 0x8619669f00000000, 0x33b53c1f00000000,
+ 0xa02ef56000000000, 0x18eaf8c400000000, 0x8b7131bb00000000,
+ 0x3edd6b3b00000000, 0xad46a24400000000, 0x3bf25c3900000000,
+ 0xa869954600000000, 0x1dc5cfc600000000, 0x8e5e06b900000000,
+ 0x369a0b1d00000000, 0xa501c26200000000, 0x10ad98e200000000,
+ 0x8336519d00000000, 0x2122f27100000000, 0xb2b93b0e00000000,
+ 0x0715618e00000000, 0x948ea8f100000000, 0x2c4aa55500000000,
+ 0xbfd16c2a00000000, 0x0a7d36aa00000000, 0x99e6ffd500000000,
+ 0x359e2e7900000000, 0xa605e70600000000, 0x13a9bd8600000000,
+ 0x803274f900000000, 0x38f6795d00000000, 0xab6db02200000000,
+ 0x1ec1eaa200000000, 0x8d5a23dd00000000, 0x2f4e803100000000,
+ 0xbcd5494e00000000, 0x097913ce00000000, 0x9ae2dab100000000,
+ 0x2226d71500000000, 0xb1bd1e6a00000000, 0x041144ea00000000,
+ 0x978a8d9500000000, 0x013e73e800000000, 0x92a5ba9700000000,
+ 0x2709e01700000000, 0xb492296800000000, 0x0c5624cc00000000,
+ 0x9fcdedb300000000, 0x2a61b73300000000, 0xb9fa7e4c00000000,
+ 0x1beedda000000000, 0x887514df00000000, 0x3dd94e5f00000000,
+ 0xae42872000000000, 0x16868a8400000000, 0x851d43fb00000000,
+ 0x30b1197b00000000, 0xa32ad00400000000, 0x1cd8e48000000000,
+ 0x8f432dff00000000, 0x3aef777f00000000, 0xa974be0000000000,
+ 0x11b0b3a400000000, 0x822b7adb00000000, 0x3787205b00000000,
+ 0xa41ce92400000000, 0x06084ac800000000, 0x959383b700000000,
+ 0x203fd93700000000, 0xb3a4104800000000, 0x0b601dec00000000,
+ 0x98fbd49300000000, 0x2d578e1300000000, 0xbecc476c00000000,
+ 0x2878b91100000000, 0xbbe3706e00000000, 0x0e4f2aee00000000,
+ 0x9dd4e39100000000, 0x2510ee3500000000, 0xb68b274a00000000,
+ 0x03277dca00000000, 0x90bcb4b500000000, 0x32a8175900000000,
+ 0xa133de2600000000, 0x149f84a600000000, 0x87044dd900000000,
+ 0x3fc0407d00000000, 0xac5b890200000000, 0x19f7d38200000000,
+ 0x8a6c1afd00000000},
+ {0x0000000000000000, 0x650b796900000000, 0xca16f2d200000000,
+ 0xaf1d8bbb00000000, 0xd52b957e00000000, 0xb020ec1700000000,
+ 0x1f3d67ac00000000, 0x7a361ec500000000, 0xaa572afd00000000,
+ 0xcf5c539400000000, 0x6041d82f00000000, 0x054aa14600000000,
+ 0x7f7cbf8300000000, 0x1a77c6ea00000000, 0xb56a4d5100000000,
+ 0xd061343800000000, 0x15a9252100000000, 0x70a25c4800000000,
+ 0xdfbfd7f300000000, 0xbab4ae9a00000000, 0xc082b05f00000000,
+ 0xa589c93600000000, 0x0a94428d00000000, 0x6f9f3be400000000,
+ 0xbffe0fdc00000000, 0xdaf576b500000000, 0x75e8fd0e00000000,
+ 0x10e3846700000000, 0x6ad59aa200000000, 0x0fdee3cb00000000,
+ 0xa0c3687000000000, 0xc5c8111900000000, 0x2a524b4200000000,
+ 0x4f59322b00000000, 0xe044b99000000000, 0x854fc0f900000000,
+ 0xff79de3c00000000, 0x9a72a75500000000, 0x356f2cee00000000,
+ 0x5064558700000000, 0x800561bf00000000, 0xe50e18d600000000,
+ 0x4a13936d00000000, 0x2f18ea0400000000, 0x552ef4c100000000,
+ 0x30258da800000000, 0x9f38061300000000, 0xfa337f7a00000000,
+ 0x3ffb6e6300000000, 0x5af0170a00000000, 0xf5ed9cb100000000,
+ 0x90e6e5d800000000, 0xead0fb1d00000000, 0x8fdb827400000000,
+ 0x20c609cf00000000, 0x45cd70a600000000, 0x95ac449e00000000,
+ 0xf0a73df700000000, 0x5fbab64c00000000, 0x3ab1cf2500000000,
+ 0x4087d1e000000000, 0x258ca88900000000, 0x8a91233200000000,
+ 0xef9a5a5b00000000, 0x54a4968400000000, 0x31afefed00000000,
+ 0x9eb2645600000000, 0xfbb91d3f00000000, 0x818f03fa00000000,
+ 0xe4847a9300000000, 0x4b99f12800000000, 0x2e92884100000000,
+ 0xfef3bc7900000000, 0x9bf8c51000000000, 0x34e54eab00000000,
+ 0x51ee37c200000000, 0x2bd8290700000000, 0x4ed3506e00000000,
+ 0xe1cedbd500000000, 0x84c5a2bc00000000, 0x410db3a500000000,
+ 0x2406cacc00000000, 0x8b1b417700000000, 0xee10381e00000000,
+ 0x942626db00000000, 0xf12d5fb200000000, 0x5e30d40900000000,
+ 0x3b3bad6000000000, 0xeb5a995800000000, 0x8e51e03100000000,
+ 0x214c6b8a00000000, 0x444712e300000000, 0x3e710c2600000000,
+ 0x5b7a754f00000000, 0xf467fef400000000, 0x916c879d00000000,
+ 0x7ef6ddc600000000, 0x1bfda4af00000000, 0xb4e02f1400000000,
+ 0xd1eb567d00000000, 0xabdd48b800000000, 0xced631d100000000,
+ 0x61cbba6a00000000, 0x04c0c30300000000, 0xd4a1f73b00000000,
+ 0xb1aa8e5200000000, 0x1eb705e900000000, 0x7bbc7c8000000000,
+ 0x018a624500000000, 0x64811b2c00000000, 0xcb9c909700000000,
+ 0xae97e9fe00000000, 0x6b5ff8e700000000, 0x0e54818e00000000,
+ 0xa1490a3500000000, 0xc442735c00000000, 0xbe746d9900000000,
+ 0xdb7f14f000000000, 0x74629f4b00000000, 0x1169e62200000000,
+ 0xc108d21a00000000, 0xa403ab7300000000, 0x0b1e20c800000000,
+ 0x6e1559a100000000, 0x1423476400000000, 0x71283e0d00000000,
+ 0xde35b5b600000000, 0xbb3eccdf00000000, 0xe94e5cd200000000,
+ 0x8c4525bb00000000, 0x2358ae0000000000, 0x4653d76900000000,
+ 0x3c65c9ac00000000, 0x596eb0c500000000, 0xf6733b7e00000000,
+ 0x9378421700000000, 0x4319762f00000000, 0x26120f4600000000,
+ 0x890f84fd00000000, 0xec04fd9400000000, 0x9632e35100000000,
+ 0xf3399a3800000000, 0x5c24118300000000, 0x392f68ea00000000,
+ 0xfce779f300000000, 0x99ec009a00000000, 0x36f18b2100000000,
+ 0x53faf24800000000, 0x29ccec8d00000000, 0x4cc795e400000000,
+ 0xe3da1e5f00000000, 0x86d1673600000000, 0x56b0530e00000000,
+ 0x33bb2a6700000000, 0x9ca6a1dc00000000, 0xf9add8b500000000,
+ 0x839bc67000000000, 0xe690bf1900000000, 0x498d34a200000000,
+ 0x2c864dcb00000000, 0xc31c179000000000, 0xa6176ef900000000,
+ 0x090ae54200000000, 0x6c019c2b00000000, 0x163782ee00000000,
+ 0x733cfb8700000000, 0xdc21703c00000000, 0xb92a095500000000,
+ 0x694b3d6d00000000, 0x0c40440400000000, 0xa35dcfbf00000000,
+ 0xc656b6d600000000, 0xbc60a81300000000, 0xd96bd17a00000000,
+ 0x76765ac100000000, 0x137d23a800000000, 0xd6b532b100000000,
+ 0xb3be4bd800000000, 0x1ca3c06300000000, 0x79a8b90a00000000,
+ 0x039ea7cf00000000, 0x6695dea600000000, 0xc988551d00000000,
+ 0xac832c7400000000, 0x7ce2184c00000000, 0x19e9612500000000,
+ 0xb6f4ea9e00000000, 0xd3ff93f700000000, 0xa9c98d3200000000,
+ 0xccc2f45b00000000, 0x63df7fe000000000, 0x06d4068900000000,
+ 0xbdeaca5600000000, 0xd8e1b33f00000000, 0x77fc388400000000,
+ 0x12f741ed00000000, 0x68c15f2800000000, 0x0dca264100000000,
+ 0xa2d7adfa00000000, 0xc7dcd49300000000, 0x17bde0ab00000000,
+ 0x72b699c200000000, 0xddab127900000000, 0xb8a06b1000000000,
+ 0xc29675d500000000, 0xa79d0cbc00000000, 0x0880870700000000,
+ 0x6d8bfe6e00000000, 0xa843ef7700000000, 0xcd48961e00000000,
+ 0x62551da500000000, 0x075e64cc00000000, 0x7d687a0900000000,
+ 0x1863036000000000, 0xb77e88db00000000, 0xd275f1b200000000,
+ 0x0214c58a00000000, 0x671fbce300000000, 0xc802375800000000,
+ 0xad094e3100000000, 0xd73f50f400000000, 0xb234299d00000000,
+ 0x1d29a22600000000, 0x7822db4f00000000, 0x97b8811400000000,
+ 0xf2b3f87d00000000, 0x5dae73c600000000, 0x38a50aaf00000000,
+ 0x4293146a00000000, 0x27986d0300000000, 0x8885e6b800000000,
+ 0xed8e9fd100000000, 0x3defabe900000000, 0x58e4d28000000000,
+ 0xf7f9593b00000000, 0x92f2205200000000, 0xe8c43e9700000000,
+ 0x8dcf47fe00000000, 0x22d2cc4500000000, 0x47d9b52c00000000,
+ 0x8211a43500000000, 0xe71add5c00000000, 0x480756e700000000,
+ 0x2d0c2f8e00000000, 0x573a314b00000000, 0x3231482200000000,
+ 0x9d2cc39900000000, 0xf827baf000000000, 0x28468ec800000000,
+ 0x4d4df7a100000000, 0xe2507c1a00000000, 0x875b057300000000,
+ 0xfd6d1bb600000000, 0x986662df00000000, 0x377be96400000000,
+ 0x5270900d00000000},
+ {0x0000000000000000, 0xdcecb13d00000000, 0xb8d9637b00000000,
+ 0x6435d24600000000, 0x70b3c7f600000000, 0xac5f76cb00000000,
+ 0xc86aa48d00000000, 0x148615b000000000, 0xa160fe3600000000,
+ 0x7d8c4f0b00000000, 0x19b99d4d00000000, 0xc5552c7000000000,
+ 0xd1d339c000000000, 0x0d3f88fd00000000, 0x690a5abb00000000,
+ 0xb5e6eb8600000000, 0x42c1fc6d00000000, 0x9e2d4d5000000000,
+ 0xfa189f1600000000, 0x26f42e2b00000000, 0x32723b9b00000000,
+ 0xee9e8aa600000000, 0x8aab58e000000000, 0x5647e9dd00000000,
+ 0xe3a1025b00000000, 0x3f4db36600000000, 0x5b78612000000000,
+ 0x8794d01d00000000, 0x9312c5ad00000000, 0x4ffe749000000000,
+ 0x2bcba6d600000000, 0xf72717eb00000000, 0x8482f9db00000000,
+ 0x586e48e600000000, 0x3c5b9aa000000000, 0xe0b72b9d00000000,
+ 0xf4313e2d00000000, 0x28dd8f1000000000, 0x4ce85d5600000000,
+ 0x9004ec6b00000000, 0x25e207ed00000000, 0xf90eb6d000000000,
+ 0x9d3b649600000000, 0x41d7d5ab00000000, 0x5551c01b00000000,
+ 0x89bd712600000000, 0xed88a36000000000, 0x3164125d00000000,
+ 0xc64305b600000000, 0x1aafb48b00000000, 0x7e9a66cd00000000,
+ 0xa276d7f000000000, 0xb6f0c24000000000, 0x6a1c737d00000000,
+ 0x0e29a13b00000000, 0xd2c5100600000000, 0x6723fb8000000000,
+ 0xbbcf4abd00000000, 0xdffa98fb00000000, 0x031629c600000000,
+ 0x17903c7600000000, 0xcb7c8d4b00000000, 0xaf495f0d00000000,
+ 0x73a5ee3000000000, 0x4903826c00000000, 0x95ef335100000000,
+ 0xf1dae11700000000, 0x2d36502a00000000, 0x39b0459a00000000,
+ 0xe55cf4a700000000, 0x816926e100000000, 0x5d8597dc00000000,
+ 0xe8637c5a00000000, 0x348fcd6700000000, 0x50ba1f2100000000,
+ 0x8c56ae1c00000000, 0x98d0bbac00000000, 0x443c0a9100000000,
+ 0x2009d8d700000000, 0xfce569ea00000000, 0x0bc27e0100000000,
+ 0xd72ecf3c00000000, 0xb31b1d7a00000000, 0x6ff7ac4700000000,
+ 0x7b71b9f700000000, 0xa79d08ca00000000, 0xc3a8da8c00000000,
+ 0x1f446bb100000000, 0xaaa2803700000000, 0x764e310a00000000,
+ 0x127be34c00000000, 0xce97527100000000, 0xda1147c100000000,
+ 0x06fdf6fc00000000, 0x62c824ba00000000, 0xbe24958700000000,
+ 0xcd817bb700000000, 0x116dca8a00000000, 0x755818cc00000000,
+ 0xa9b4a9f100000000, 0xbd32bc4100000000, 0x61de0d7c00000000,
+ 0x05ebdf3a00000000, 0xd9076e0700000000, 0x6ce1858100000000,
+ 0xb00d34bc00000000, 0xd438e6fa00000000, 0x08d457c700000000,
+ 0x1c52427700000000, 0xc0bef34a00000000, 0xa48b210c00000000,
+ 0x7867903100000000, 0x8f4087da00000000, 0x53ac36e700000000,
+ 0x3799e4a100000000, 0xeb75559c00000000, 0xfff3402c00000000,
+ 0x231ff11100000000, 0x472a235700000000, 0x9bc6926a00000000,
+ 0x2e2079ec00000000, 0xf2ccc8d100000000, 0x96f91a9700000000,
+ 0x4a15abaa00000000, 0x5e93be1a00000000, 0x827f0f2700000000,
+ 0xe64add6100000000, 0x3aa66c5c00000000, 0x920604d900000000,
+ 0x4eeab5e400000000, 0x2adf67a200000000, 0xf633d69f00000000,
+ 0xe2b5c32f00000000, 0x3e59721200000000, 0x5a6ca05400000000,
+ 0x8680116900000000, 0x3366faef00000000, 0xef8a4bd200000000,
+ 0x8bbf999400000000, 0x575328a900000000, 0x43d53d1900000000,
+ 0x9f398c2400000000, 0xfb0c5e6200000000, 0x27e0ef5f00000000,
+ 0xd0c7f8b400000000, 0x0c2b498900000000, 0x681e9bcf00000000,
+ 0xb4f22af200000000, 0xa0743f4200000000, 0x7c988e7f00000000,
+ 0x18ad5c3900000000, 0xc441ed0400000000, 0x71a7068200000000,
+ 0xad4bb7bf00000000, 0xc97e65f900000000, 0x1592d4c400000000,
+ 0x0114c17400000000, 0xddf8704900000000, 0xb9cda20f00000000,
+ 0x6521133200000000, 0x1684fd0200000000, 0xca684c3f00000000,
+ 0xae5d9e7900000000, 0x72b12f4400000000, 0x66373af400000000,
+ 0xbadb8bc900000000, 0xdeee598f00000000, 0x0202e8b200000000,
+ 0xb7e4033400000000, 0x6b08b20900000000, 0x0f3d604f00000000,
+ 0xd3d1d17200000000, 0xc757c4c200000000, 0x1bbb75ff00000000,
+ 0x7f8ea7b900000000, 0xa362168400000000, 0x5445016f00000000,
+ 0x88a9b05200000000, 0xec9c621400000000, 0x3070d32900000000,
+ 0x24f6c69900000000, 0xf81a77a400000000, 0x9c2fa5e200000000,
+ 0x40c314df00000000, 0xf525ff5900000000, 0x29c94e6400000000,
+ 0x4dfc9c2200000000, 0x91102d1f00000000, 0x859638af00000000,
+ 0x597a899200000000, 0x3d4f5bd400000000, 0xe1a3eae900000000,
+ 0xdb0586b500000000, 0x07e9378800000000, 0x63dce5ce00000000,
+ 0xbf3054f300000000, 0xabb6414300000000, 0x775af07e00000000,
+ 0x136f223800000000, 0xcf83930500000000, 0x7a65788300000000,
+ 0xa689c9be00000000, 0xc2bc1bf800000000, 0x1e50aac500000000,
+ 0x0ad6bf7500000000, 0xd63a0e4800000000, 0xb20fdc0e00000000,
+ 0x6ee36d3300000000, 0x99c47ad800000000, 0x4528cbe500000000,
+ 0x211d19a300000000, 0xfdf1a89e00000000, 0xe977bd2e00000000,
+ 0x359b0c1300000000, 0x51aede5500000000, 0x8d426f6800000000,
+ 0x38a484ee00000000, 0xe44835d300000000, 0x807de79500000000,
+ 0x5c9156a800000000, 0x4817431800000000, 0x94fbf22500000000,
+ 0xf0ce206300000000, 0x2c22915e00000000, 0x5f877f6e00000000,
+ 0x836bce5300000000, 0xe75e1c1500000000, 0x3bb2ad2800000000,
+ 0x2f34b89800000000, 0xf3d809a500000000, 0x97eddbe300000000,
+ 0x4b016ade00000000, 0xfee7815800000000, 0x220b306500000000,
+ 0x463ee22300000000, 0x9ad2531e00000000, 0x8e5446ae00000000,
+ 0x52b8f79300000000, 0x368d25d500000000, 0xea6194e800000000,
+ 0x1d46830300000000, 0xc1aa323e00000000, 0xa59fe07800000000,
+ 0x7973514500000000, 0x6df544f500000000, 0xb119f5c800000000,
+ 0xd52c278e00000000, 0x09c096b300000000, 0xbc267d3500000000,
+ 0x60cacc0800000000, 0x04ff1e4e00000000, 0xd813af7300000000,
+ 0xcc95bac300000000, 0x10790bfe00000000, 0x744cd9b800000000,
+ 0xa8a0688500000000}};
+
+#else /* W == 4 */
+
+local const z_crc_t FAR crc_braid_table[][256] = {
+ {0x00000000, 0x81256527, 0xd93bcc0f, 0x581ea928, 0x69069e5f,
+ 0xe823fb78, 0xb03d5250, 0x31183777, 0xd20d3cbe, 0x53285999,
+ 0x0b36f0b1, 0x8a139596, 0xbb0ba2e1, 0x3a2ec7c6, 0x62306eee,
+ 0xe3150bc9, 0x7f6b7f3d, 0xfe4e1a1a, 0xa650b332, 0x2775d615,
+ 0x166de162, 0x97488445, 0xcf562d6d, 0x4e73484a, 0xad664383,
+ 0x2c4326a4, 0x745d8f8c, 0xf578eaab, 0xc460dddc, 0x4545b8fb,
+ 0x1d5b11d3, 0x9c7e74f4, 0xfed6fe7a, 0x7ff39b5d, 0x27ed3275,
+ 0xa6c85752, 0x97d06025, 0x16f50502, 0x4eebac2a, 0xcfcec90d,
+ 0x2cdbc2c4, 0xadfea7e3, 0xf5e00ecb, 0x74c56bec, 0x45dd5c9b,
+ 0xc4f839bc, 0x9ce69094, 0x1dc3f5b3, 0x81bd8147, 0x0098e460,
+ 0x58864d48, 0xd9a3286f, 0xe8bb1f18, 0x699e7a3f, 0x3180d317,
+ 0xb0a5b630, 0x53b0bdf9, 0xd295d8de, 0x8a8b71f6, 0x0bae14d1,
+ 0x3ab623a6, 0xbb934681, 0xe38defa9, 0x62a88a8e, 0x26dcfab5,
+ 0xa7f99f92, 0xffe736ba, 0x7ec2539d, 0x4fda64ea, 0xceff01cd,
+ 0x96e1a8e5, 0x17c4cdc2, 0xf4d1c60b, 0x75f4a32c, 0x2dea0a04,
+ 0xaccf6f23, 0x9dd75854, 0x1cf23d73, 0x44ec945b, 0xc5c9f17c,
+ 0x59b78588, 0xd892e0af, 0x808c4987, 0x01a92ca0, 0x30b11bd7,
+ 0xb1947ef0, 0xe98ad7d8, 0x68afb2ff, 0x8bbab936, 0x0a9fdc11,
+ 0x52817539, 0xd3a4101e, 0xe2bc2769, 0x6399424e, 0x3b87eb66,
+ 0xbaa28e41, 0xd80a04cf, 0x592f61e8, 0x0131c8c0, 0x8014ade7,
+ 0xb10c9a90, 0x3029ffb7, 0x6837569f, 0xe91233b8, 0x0a073871,
+ 0x8b225d56, 0xd33cf47e, 0x52199159, 0x6301a62e, 0xe224c309,
+ 0xba3a6a21, 0x3b1f0f06, 0xa7617bf2, 0x26441ed5, 0x7e5ab7fd,
+ 0xff7fd2da, 0xce67e5ad, 0x4f42808a, 0x175c29a2, 0x96794c85,
+ 0x756c474c, 0xf449226b, 0xac578b43, 0x2d72ee64, 0x1c6ad913,
+ 0x9d4fbc34, 0xc551151c, 0x4474703b, 0x4db9f56a, 0xcc9c904d,
+ 0x94823965, 0x15a75c42, 0x24bf6b35, 0xa59a0e12, 0xfd84a73a,
+ 0x7ca1c21d, 0x9fb4c9d4, 0x1e91acf3, 0x468f05db, 0xc7aa60fc,
+ 0xf6b2578b, 0x779732ac, 0x2f899b84, 0xaeacfea3, 0x32d28a57,
+ 0xb3f7ef70, 0xebe94658, 0x6acc237f, 0x5bd41408, 0xdaf1712f,
+ 0x82efd807, 0x03cabd20, 0xe0dfb6e9, 0x61fad3ce, 0x39e47ae6,
+ 0xb8c11fc1, 0x89d928b6, 0x08fc4d91, 0x50e2e4b9, 0xd1c7819e,
+ 0xb36f0b10, 0x324a6e37, 0x6a54c71f, 0xeb71a238, 0xda69954f,
+ 0x5b4cf068, 0x03525940, 0x82773c67, 0x616237ae, 0xe0475289,
+ 0xb859fba1, 0x397c9e86, 0x0864a9f1, 0x8941ccd6, 0xd15f65fe,
+ 0x507a00d9, 0xcc04742d, 0x4d21110a, 0x153fb822, 0x941add05,
+ 0xa502ea72, 0x24278f55, 0x7c39267d, 0xfd1c435a, 0x1e094893,
+ 0x9f2c2db4, 0xc732849c, 0x4617e1bb, 0x770fd6cc, 0xf62ab3eb,
+ 0xae341ac3, 0x2f117fe4, 0x6b650fdf, 0xea406af8, 0xb25ec3d0,
+ 0x337ba6f7, 0x02639180, 0x8346f4a7, 0xdb585d8f, 0x5a7d38a8,
+ 0xb9683361, 0x384d5646, 0x6053ff6e, 0xe1769a49, 0xd06ead3e,
+ 0x514bc819, 0x09556131, 0x88700416, 0x140e70e2, 0x952b15c5,
+ 0xcd35bced, 0x4c10d9ca, 0x7d08eebd, 0xfc2d8b9a, 0xa43322b2,
+ 0x25164795, 0xc6034c5c, 0x4726297b, 0x1f388053, 0x9e1de574,
+ 0xaf05d203, 0x2e20b724, 0x763e1e0c, 0xf71b7b2b, 0x95b3f1a5,
+ 0x14969482, 0x4c883daa, 0xcdad588d, 0xfcb56ffa, 0x7d900add,
+ 0x258ea3f5, 0xa4abc6d2, 0x47becd1b, 0xc69ba83c, 0x9e850114,
+ 0x1fa06433, 0x2eb85344, 0xaf9d3663, 0xf7839f4b, 0x76a6fa6c,
+ 0xead88e98, 0x6bfdebbf, 0x33e34297, 0xb2c627b0, 0x83de10c7,
+ 0x02fb75e0, 0x5ae5dcc8, 0xdbc0b9ef, 0x38d5b226, 0xb9f0d701,
+ 0xe1ee7e29, 0x60cb1b0e, 0x51d32c79, 0xd0f6495e, 0x88e8e076,
+ 0x09cd8551},
+ {0x00000000, 0x9b73ead4, 0xed96d3e9, 0x76e5393d, 0x005ca193,
+ 0x9b2f4b47, 0xedca727a, 0x76b998ae, 0x00b94326, 0x9bcaa9f2,
+ 0xed2f90cf, 0x765c7a1b, 0x00e5e2b5, 0x9b960861, 0xed73315c,
+ 0x7600db88, 0x0172864c, 0x9a016c98, 0xece455a5, 0x7797bf71,
+ 0x012e27df, 0x9a5dcd0b, 0xecb8f436, 0x77cb1ee2, 0x01cbc56a,
+ 0x9ab82fbe, 0xec5d1683, 0x772efc57, 0x019764f9, 0x9ae48e2d,
+ 0xec01b710, 0x77725dc4, 0x02e50c98, 0x9996e64c, 0xef73df71,
+ 0x740035a5, 0x02b9ad0b, 0x99ca47df, 0xef2f7ee2, 0x745c9436,
+ 0x025c4fbe, 0x992fa56a, 0xefca9c57, 0x74b97683, 0x0200ee2d,
+ 0x997304f9, 0xef963dc4, 0x74e5d710, 0x03978ad4, 0x98e46000,
+ 0xee01593d, 0x7572b3e9, 0x03cb2b47, 0x98b8c193, 0xee5df8ae,
+ 0x752e127a, 0x032ec9f2, 0x985d2326, 0xeeb81a1b, 0x75cbf0cf,
+ 0x03726861, 0x980182b5, 0xeee4bb88, 0x7597515c, 0x05ca1930,
+ 0x9eb9f3e4, 0xe85ccad9, 0x732f200d, 0x0596b8a3, 0x9ee55277,
+ 0xe8006b4a, 0x7373819e, 0x05735a16, 0x9e00b0c2, 0xe8e589ff,
+ 0x7396632b, 0x052ffb85, 0x9e5c1151, 0xe8b9286c, 0x73cac2b8,
+ 0x04b89f7c, 0x9fcb75a8, 0xe92e4c95, 0x725da641, 0x04e43eef,
+ 0x9f97d43b, 0xe972ed06, 0x720107d2, 0x0401dc5a, 0x9f72368e,
+ 0xe9970fb3, 0x72e4e567, 0x045d7dc9, 0x9f2e971d, 0xe9cbae20,
+ 0x72b844f4, 0x072f15a8, 0x9c5cff7c, 0xeab9c641, 0x71ca2c95,
+ 0x0773b43b, 0x9c005eef, 0xeae567d2, 0x71968d06, 0x0796568e,
+ 0x9ce5bc5a, 0xea008567, 0x71736fb3, 0x07caf71d, 0x9cb91dc9,
+ 0xea5c24f4, 0x712fce20, 0x065d93e4, 0x9d2e7930, 0xebcb400d,
+ 0x70b8aad9, 0x06013277, 0x9d72d8a3, 0xeb97e19e, 0x70e40b4a,
+ 0x06e4d0c2, 0x9d973a16, 0xeb72032b, 0x7001e9ff, 0x06b87151,
+ 0x9dcb9b85, 0xeb2ea2b8, 0x705d486c, 0x0b943260, 0x90e7d8b4,
+ 0xe602e189, 0x7d710b5d, 0x0bc893f3, 0x90bb7927, 0xe65e401a,
+ 0x7d2daace, 0x0b2d7146, 0x905e9b92, 0xe6bba2af, 0x7dc8487b,
+ 0x0b71d0d5, 0x90023a01, 0xe6e7033c, 0x7d94e9e8, 0x0ae6b42c,
+ 0x91955ef8, 0xe77067c5, 0x7c038d11, 0x0aba15bf, 0x91c9ff6b,
+ 0xe72cc656, 0x7c5f2c82, 0x0a5ff70a, 0x912c1dde, 0xe7c924e3,
+ 0x7cbace37, 0x0a035699, 0x9170bc4d, 0xe7958570, 0x7ce66fa4,
+ 0x09713ef8, 0x9202d42c, 0xe4e7ed11, 0x7f9407c5, 0x092d9f6b,
+ 0x925e75bf, 0xe4bb4c82, 0x7fc8a656, 0x09c87dde, 0x92bb970a,
+ 0xe45eae37, 0x7f2d44e3, 0x0994dc4d, 0x92e73699, 0xe4020fa4,
+ 0x7f71e570, 0x0803b8b4, 0x93705260, 0xe5956b5d, 0x7ee68189,
+ 0x085f1927, 0x932cf3f3, 0xe5c9cace, 0x7eba201a, 0x08bafb92,
+ 0x93c91146, 0xe52c287b, 0x7e5fc2af, 0x08e65a01, 0x9395b0d5,
+ 0xe57089e8, 0x7e03633c, 0x0e5e2b50, 0x952dc184, 0xe3c8f8b9,
+ 0x78bb126d, 0x0e028ac3, 0x95716017, 0xe394592a, 0x78e7b3fe,
+ 0x0ee76876, 0x959482a2, 0xe371bb9f, 0x7802514b, 0x0ebbc9e5,
+ 0x95c82331, 0xe32d1a0c, 0x785ef0d8, 0x0f2cad1c, 0x945f47c8,
+ 0xe2ba7ef5, 0x79c99421, 0x0f700c8f, 0x9403e65b, 0xe2e6df66,
+ 0x799535b2, 0x0f95ee3a, 0x94e604ee, 0xe2033dd3, 0x7970d707,
+ 0x0fc94fa9, 0x94baa57d, 0xe25f9c40, 0x792c7694, 0x0cbb27c8,
+ 0x97c8cd1c, 0xe12df421, 0x7a5e1ef5, 0x0ce7865b, 0x97946c8f,
+ 0xe17155b2, 0x7a02bf66, 0x0c0264ee, 0x97718e3a, 0xe194b707,
+ 0x7ae75dd3, 0x0c5ec57d, 0x972d2fa9, 0xe1c81694, 0x7abbfc40,
+ 0x0dc9a184, 0x96ba4b50, 0xe05f726d, 0x7b2c98b9, 0x0d950017,
+ 0x96e6eac3, 0xe003d3fe, 0x7b70392a, 0x0d70e2a2, 0x96030876,
+ 0xe0e6314b, 0x7b95db9f, 0x0d2c4331, 0x965fa9e5, 0xe0ba90d8,
+ 0x7bc97a0c},
+ {0x00000000, 0x172864c0, 0x2e50c980, 0x3978ad40, 0x5ca19300,
+ 0x4b89f7c0, 0x72f15a80, 0x65d93e40, 0xb9432600, 0xae6b42c0,
+ 0x9713ef80, 0x803b8b40, 0xe5e2b500, 0xf2cad1c0, 0xcbb27c80,
+ 0xdc9a1840, 0xa9f74a41, 0xbedf2e81, 0x87a783c1, 0x908fe701,
+ 0xf556d941, 0xe27ebd81, 0xdb0610c1, 0xcc2e7401, 0x10b46c41,
+ 0x079c0881, 0x3ee4a5c1, 0x29ccc101, 0x4c15ff41, 0x5b3d9b81,
+ 0x624536c1, 0x756d5201, 0x889f92c3, 0x9fb7f603, 0xa6cf5b43,
+ 0xb1e73f83, 0xd43e01c3, 0xc3166503, 0xfa6ec843, 0xed46ac83,
+ 0x31dcb4c3, 0x26f4d003, 0x1f8c7d43, 0x08a41983, 0x6d7d27c3,
+ 0x7a554303, 0x432dee43, 0x54058a83, 0x2168d882, 0x3640bc42,
+ 0x0f381102, 0x181075c2, 0x7dc94b82, 0x6ae12f42, 0x53998202,
+ 0x44b1e6c2, 0x982bfe82, 0x8f039a42, 0xb67b3702, 0xa15353c2,
+ 0xc48a6d82, 0xd3a20942, 0xeadaa402, 0xfdf2c0c2, 0xca4e23c7,
+ 0xdd664707, 0xe41eea47, 0xf3368e87, 0x96efb0c7, 0x81c7d407,
+ 0xb8bf7947, 0xaf971d87, 0x730d05c7, 0x64256107, 0x5d5dcc47,
+ 0x4a75a887, 0x2fac96c7, 0x3884f207, 0x01fc5f47, 0x16d43b87,
+ 0x63b96986, 0x74910d46, 0x4de9a006, 0x5ac1c4c6, 0x3f18fa86,
+ 0x28309e46, 0x11483306, 0x066057c6, 0xdafa4f86, 0xcdd22b46,
+ 0xf4aa8606, 0xe382e2c6, 0x865bdc86, 0x9173b846, 0xa80b1506,
+ 0xbf2371c6, 0x42d1b104, 0x55f9d5c4, 0x6c817884, 0x7ba91c44,
+ 0x1e702204, 0x095846c4, 0x3020eb84, 0x27088f44, 0xfb929704,
+ 0xecbaf3c4, 0xd5c25e84, 0xc2ea3a44, 0xa7330404, 0xb01b60c4,
+ 0x8963cd84, 0x9e4ba944, 0xeb26fb45, 0xfc0e9f85, 0xc57632c5,
+ 0xd25e5605, 0xb7876845, 0xa0af0c85, 0x99d7a1c5, 0x8effc505,
+ 0x5265dd45, 0x454db985, 0x7c3514c5, 0x6b1d7005, 0x0ec44e45,
+ 0x19ec2a85, 0x209487c5, 0x37bce305, 0x4fed41cf, 0x58c5250f,
+ 0x61bd884f, 0x7695ec8f, 0x134cd2cf, 0x0464b60f, 0x3d1c1b4f,
+ 0x2a347f8f, 0xf6ae67cf, 0xe186030f, 0xd8feae4f, 0xcfd6ca8f,
+ 0xaa0ff4cf, 0xbd27900f, 0x845f3d4f, 0x9377598f, 0xe61a0b8e,
+ 0xf1326f4e, 0xc84ac20e, 0xdf62a6ce, 0xbabb988e, 0xad93fc4e,
+ 0x94eb510e, 0x83c335ce, 0x5f592d8e, 0x4871494e, 0x7109e40e,
+ 0x662180ce, 0x03f8be8e, 0x14d0da4e, 0x2da8770e, 0x3a8013ce,
+ 0xc772d30c, 0xd05ab7cc, 0xe9221a8c, 0xfe0a7e4c, 0x9bd3400c,
+ 0x8cfb24cc, 0xb583898c, 0xa2abed4c, 0x7e31f50c, 0x691991cc,
+ 0x50613c8c, 0x4749584c, 0x2290660c, 0x35b802cc, 0x0cc0af8c,
+ 0x1be8cb4c, 0x6e85994d, 0x79adfd8d, 0x40d550cd, 0x57fd340d,
+ 0x32240a4d, 0x250c6e8d, 0x1c74c3cd, 0x0b5ca70d, 0xd7c6bf4d,
+ 0xc0eedb8d, 0xf99676cd, 0xeebe120d, 0x8b672c4d, 0x9c4f488d,
+ 0xa537e5cd, 0xb21f810d, 0x85a36208, 0x928b06c8, 0xabf3ab88,
+ 0xbcdbcf48, 0xd902f108, 0xce2a95c8, 0xf7523888, 0xe07a5c48,
+ 0x3ce04408, 0x2bc820c8, 0x12b08d88, 0x0598e948, 0x6041d708,
+ 0x7769b3c8, 0x4e111e88, 0x59397a48, 0x2c542849, 0x3b7c4c89,
+ 0x0204e1c9, 0x152c8509, 0x70f5bb49, 0x67dddf89, 0x5ea572c9,
+ 0x498d1609, 0x95170e49, 0x823f6a89, 0xbb47c7c9, 0xac6fa309,
+ 0xc9b69d49, 0xde9ef989, 0xe7e654c9, 0xf0ce3009, 0x0d3cf0cb,
+ 0x1a14940b, 0x236c394b, 0x34445d8b, 0x519d63cb, 0x46b5070b,
+ 0x7fcdaa4b, 0x68e5ce8b, 0xb47fd6cb, 0xa357b20b, 0x9a2f1f4b,
+ 0x8d077b8b, 0xe8de45cb, 0xfff6210b, 0xc68e8c4b, 0xd1a6e88b,
+ 0xa4cbba8a, 0xb3e3de4a, 0x8a9b730a, 0x9db317ca, 0xf86a298a,
+ 0xef424d4a, 0xd63ae00a, 0xc11284ca, 0x1d889c8a, 0x0aa0f84a,
+ 0x33d8550a, 0x24f031ca, 0x41290f8a, 0x56016b4a, 0x6f79c60a,
+ 0x7851a2ca},
+ {0x00000000, 0x9fda839e, 0xe4c4017d, 0x7b1e82e3, 0x12f904bb,
+ 0x8d238725, 0xf63d05c6, 0x69e78658, 0x25f20976, 0xba288ae8,
+ 0xc136080b, 0x5eec8b95, 0x370b0dcd, 0xa8d18e53, 0xd3cf0cb0,
+ 0x4c158f2e, 0x4be412ec, 0xd43e9172, 0xaf201391, 0x30fa900f,
+ 0x591d1657, 0xc6c795c9, 0xbdd9172a, 0x220394b4, 0x6e161b9a,
+ 0xf1cc9804, 0x8ad21ae7, 0x15089979, 0x7cef1f21, 0xe3359cbf,
+ 0x982b1e5c, 0x07f19dc2, 0x97c825d8, 0x0812a646, 0x730c24a5,
+ 0xecd6a73b, 0x85312163, 0x1aeba2fd, 0x61f5201e, 0xfe2fa380,
+ 0xb23a2cae, 0x2de0af30, 0x56fe2dd3, 0xc924ae4d, 0xa0c32815,
+ 0x3f19ab8b, 0x44072968, 0xdbddaaf6, 0xdc2c3734, 0x43f6b4aa,
+ 0x38e83649, 0xa732b5d7, 0xced5338f, 0x510fb011, 0x2a1132f2,
+ 0xb5cbb16c, 0xf9de3e42, 0x6604bddc, 0x1d1a3f3f, 0x82c0bca1,
+ 0xeb273af9, 0x74fdb967, 0x0fe33b84, 0x9039b81a, 0xf4e14df1,
+ 0x6b3bce6f, 0x10254c8c, 0x8fffcf12, 0xe618494a, 0x79c2cad4,
+ 0x02dc4837, 0x9d06cba9, 0xd1134487, 0x4ec9c719, 0x35d745fa,
+ 0xaa0dc664, 0xc3ea403c, 0x5c30c3a2, 0x272e4141, 0xb8f4c2df,
+ 0xbf055f1d, 0x20dfdc83, 0x5bc15e60, 0xc41bddfe, 0xadfc5ba6,
+ 0x3226d838, 0x49385adb, 0xd6e2d945, 0x9af7566b, 0x052dd5f5,
+ 0x7e335716, 0xe1e9d488, 0x880e52d0, 0x17d4d14e, 0x6cca53ad,
+ 0xf310d033, 0x63296829, 0xfcf3ebb7, 0x87ed6954, 0x1837eaca,
+ 0x71d06c92, 0xee0aef0c, 0x95146def, 0x0aceee71, 0x46db615f,
+ 0xd901e2c1, 0xa21f6022, 0x3dc5e3bc, 0x542265e4, 0xcbf8e67a,
+ 0xb0e66499, 0x2f3ce707, 0x28cd7ac5, 0xb717f95b, 0xcc097bb8,
+ 0x53d3f826, 0x3a347e7e, 0xa5eefde0, 0xdef07f03, 0x412afc9d,
+ 0x0d3f73b3, 0x92e5f02d, 0xe9fb72ce, 0x7621f150, 0x1fc67708,
+ 0x801cf496, 0xfb027675, 0x64d8f5eb, 0x32b39da3, 0xad691e3d,
+ 0xd6779cde, 0x49ad1f40, 0x204a9918, 0xbf901a86, 0xc48e9865,
+ 0x5b541bfb, 0x174194d5, 0x889b174b, 0xf38595a8, 0x6c5f1636,
+ 0x05b8906e, 0x9a6213f0, 0xe17c9113, 0x7ea6128d, 0x79578f4f,
+ 0xe68d0cd1, 0x9d938e32, 0x02490dac, 0x6bae8bf4, 0xf474086a,
+ 0x8f6a8a89, 0x10b00917, 0x5ca58639, 0xc37f05a7, 0xb8618744,
+ 0x27bb04da, 0x4e5c8282, 0xd186011c, 0xaa9883ff, 0x35420061,
+ 0xa57bb87b, 0x3aa13be5, 0x41bfb906, 0xde653a98, 0xb782bcc0,
+ 0x28583f5e, 0x5346bdbd, 0xcc9c3e23, 0x8089b10d, 0x1f533293,
+ 0x644db070, 0xfb9733ee, 0x9270b5b6, 0x0daa3628, 0x76b4b4cb,
+ 0xe96e3755, 0xee9faa97, 0x71452909, 0x0a5babea, 0x95812874,
+ 0xfc66ae2c, 0x63bc2db2, 0x18a2af51, 0x87782ccf, 0xcb6da3e1,
+ 0x54b7207f, 0x2fa9a29c, 0xb0732102, 0xd994a75a, 0x464e24c4,
+ 0x3d50a627, 0xa28a25b9, 0xc652d052, 0x598853cc, 0x2296d12f,
+ 0xbd4c52b1, 0xd4abd4e9, 0x4b715777, 0x306fd594, 0xafb5560a,
+ 0xe3a0d924, 0x7c7a5aba, 0x0764d859, 0x98be5bc7, 0xf159dd9f,
+ 0x6e835e01, 0x159ddce2, 0x8a475f7c, 0x8db6c2be, 0x126c4120,
+ 0x6972c3c3, 0xf6a8405d, 0x9f4fc605, 0x0095459b, 0x7b8bc778,
+ 0xe45144e6, 0xa844cbc8, 0x379e4856, 0x4c80cab5, 0xd35a492b,
+ 0xbabdcf73, 0x25674ced, 0x5e79ce0e, 0xc1a34d90, 0x519af58a,
+ 0xce407614, 0xb55ef4f7, 0x2a847769, 0x4363f131, 0xdcb972af,
+ 0xa7a7f04c, 0x387d73d2, 0x7468fcfc, 0xebb27f62, 0x90acfd81,
+ 0x0f767e1f, 0x6691f847, 0xf94b7bd9, 0x8255f93a, 0x1d8f7aa4,
+ 0x1a7ee766, 0x85a464f8, 0xfebae61b, 0x61606585, 0x0887e3dd,
+ 0x975d6043, 0xec43e2a0, 0x7399613e, 0x3f8cee10, 0xa0566d8e,
+ 0xdb48ef6d, 0x44926cf3, 0x2d75eaab, 0xb2af6935, 0xc9b1ebd6,
+ 0x566b6848}};
+
+local const z_word_t FAR crc_braid_big_table[][256] = {
+ {0x00000000, 0x9e83da9f, 0x7d01c4e4, 0xe3821e7b, 0xbb04f912,
+ 0x2587238d, 0xc6053df6, 0x5886e769, 0x7609f225, 0xe88a28ba,
+ 0x0b0836c1, 0x958bec5e, 0xcd0d0b37, 0x538ed1a8, 0xb00ccfd3,
+ 0x2e8f154c, 0xec12e44b, 0x72913ed4, 0x911320af, 0x0f90fa30,
+ 0x57161d59, 0xc995c7c6, 0x2a17d9bd, 0xb4940322, 0x9a1b166e,
+ 0x0498ccf1, 0xe71ad28a, 0x79990815, 0x211fef7c, 0xbf9c35e3,
+ 0x5c1e2b98, 0xc29df107, 0xd825c897, 0x46a61208, 0xa5240c73,
+ 0x3ba7d6ec, 0x63213185, 0xfda2eb1a, 0x1e20f561, 0x80a32ffe,
+ 0xae2c3ab2, 0x30afe02d, 0xd32dfe56, 0x4dae24c9, 0x1528c3a0,
+ 0x8bab193f, 0x68290744, 0xf6aadddb, 0x34372cdc, 0xaab4f643,
+ 0x4936e838, 0xd7b532a7, 0x8f33d5ce, 0x11b00f51, 0xf232112a,
+ 0x6cb1cbb5, 0x423edef9, 0xdcbd0466, 0x3f3f1a1d, 0xa1bcc082,
+ 0xf93a27eb, 0x67b9fd74, 0x843be30f, 0x1ab83990, 0xf14de1f4,
+ 0x6fce3b6b, 0x8c4c2510, 0x12cfff8f, 0x4a4918e6, 0xd4cac279,
+ 0x3748dc02, 0xa9cb069d, 0x874413d1, 0x19c7c94e, 0xfa45d735,
+ 0x64c60daa, 0x3c40eac3, 0xa2c3305c, 0x41412e27, 0xdfc2f4b8,
+ 0x1d5f05bf, 0x83dcdf20, 0x605ec15b, 0xfedd1bc4, 0xa65bfcad,
+ 0x38d82632, 0xdb5a3849, 0x45d9e2d6, 0x6b56f79a, 0xf5d52d05,
+ 0x1657337e, 0x88d4e9e1, 0xd0520e88, 0x4ed1d417, 0xad53ca6c,
+ 0x33d010f3, 0x29682963, 0xb7ebf3fc, 0x5469ed87, 0xcaea3718,
+ 0x926cd071, 0x0cef0aee, 0xef6d1495, 0x71eece0a, 0x5f61db46,
+ 0xc1e201d9, 0x22601fa2, 0xbce3c53d, 0xe4652254, 0x7ae6f8cb,
+ 0x9964e6b0, 0x07e73c2f, 0xc57acd28, 0x5bf917b7, 0xb87b09cc,
+ 0x26f8d353, 0x7e7e343a, 0xe0fdeea5, 0x037ff0de, 0x9dfc2a41,
+ 0xb3733f0d, 0x2df0e592, 0xce72fbe9, 0x50f12176, 0x0877c61f,
+ 0x96f41c80, 0x757602fb, 0xebf5d864, 0xa39db332, 0x3d1e69ad,
+ 0xde9c77d6, 0x401fad49, 0x18994a20, 0x861a90bf, 0x65988ec4,
+ 0xfb1b545b, 0xd5944117, 0x4b179b88, 0xa89585f3, 0x36165f6c,
+ 0x6e90b805, 0xf013629a, 0x13917ce1, 0x8d12a67e, 0x4f8f5779,
+ 0xd10c8de6, 0x328e939d, 0xac0d4902, 0xf48bae6b, 0x6a0874f4,
+ 0x898a6a8f, 0x1709b010, 0x3986a55c, 0xa7057fc3, 0x448761b8,
+ 0xda04bb27, 0x82825c4e, 0x1c0186d1, 0xff8398aa, 0x61004235,
+ 0x7bb87ba5, 0xe53ba13a, 0x06b9bf41, 0x983a65de, 0xc0bc82b7,
+ 0x5e3f5828, 0xbdbd4653, 0x233e9ccc, 0x0db18980, 0x9332531f,
+ 0x70b04d64, 0xee3397fb, 0xb6b57092, 0x2836aa0d, 0xcbb4b476,
+ 0x55376ee9, 0x97aa9fee, 0x09294571, 0xeaab5b0a, 0x74288195,
+ 0x2cae66fc, 0xb22dbc63, 0x51afa218, 0xcf2c7887, 0xe1a36dcb,
+ 0x7f20b754, 0x9ca2a92f, 0x022173b0, 0x5aa794d9, 0xc4244e46,
+ 0x27a6503d, 0xb9258aa2, 0x52d052c6, 0xcc538859, 0x2fd19622,
+ 0xb1524cbd, 0xe9d4abd4, 0x7757714b, 0x94d56f30, 0x0a56b5af,
+ 0x24d9a0e3, 0xba5a7a7c, 0x59d86407, 0xc75bbe98, 0x9fdd59f1,
+ 0x015e836e, 0xe2dc9d15, 0x7c5f478a, 0xbec2b68d, 0x20416c12,
+ 0xc3c37269, 0x5d40a8f6, 0x05c64f9f, 0x9b459500, 0x78c78b7b,
+ 0xe64451e4, 0xc8cb44a8, 0x56489e37, 0xb5ca804c, 0x2b495ad3,
+ 0x73cfbdba, 0xed4c6725, 0x0ece795e, 0x904da3c1, 0x8af59a51,
+ 0x147640ce, 0xf7f45eb5, 0x6977842a, 0x31f16343, 0xaf72b9dc,
+ 0x4cf0a7a7, 0xd2737d38, 0xfcfc6874, 0x627fb2eb, 0x81fdac90,
+ 0x1f7e760f, 0x47f89166, 0xd97b4bf9, 0x3af95582, 0xa47a8f1d,
+ 0x66e77e1a, 0xf864a485, 0x1be6bafe, 0x85656061, 0xdde38708,
+ 0x43605d97, 0xa0e243ec, 0x3e619973, 0x10ee8c3f, 0x8e6d56a0,
+ 0x6def48db, 0xf36c9244, 0xabea752d, 0x3569afb2, 0xd6ebb1c9,
+ 0x48686b56},
+ {0x00000000, 0xc0642817, 0x80c9502e, 0x40ad7839, 0x0093a15c,
+ 0xc0f7894b, 0x805af172, 0x403ed965, 0x002643b9, 0xc0426bae,
+ 0x80ef1397, 0x408b3b80, 0x00b5e2e5, 0xc0d1caf2, 0x807cb2cb,
+ 0x40189adc, 0x414af7a9, 0x812edfbe, 0xc183a787, 0x01e78f90,
+ 0x41d956f5, 0x81bd7ee2, 0xc11006db, 0x01742ecc, 0x416cb410,
+ 0x81089c07, 0xc1a5e43e, 0x01c1cc29, 0x41ff154c, 0x819b3d5b,
+ 0xc1364562, 0x01526d75, 0xc3929f88, 0x03f6b79f, 0x435bcfa6,
+ 0x833fe7b1, 0xc3013ed4, 0x036516c3, 0x43c86efa, 0x83ac46ed,
+ 0xc3b4dc31, 0x03d0f426, 0x437d8c1f, 0x8319a408, 0xc3277d6d,
+ 0x0343557a, 0x43ee2d43, 0x838a0554, 0x82d86821, 0x42bc4036,
+ 0x0211380f, 0xc2751018, 0x824bc97d, 0x422fe16a, 0x02829953,
+ 0xc2e6b144, 0x82fe2b98, 0x429a038f, 0x02377bb6, 0xc25353a1,
+ 0x826d8ac4, 0x4209a2d3, 0x02a4daea, 0xc2c0f2fd, 0xc7234eca,
+ 0x074766dd, 0x47ea1ee4, 0x878e36f3, 0xc7b0ef96, 0x07d4c781,
+ 0x4779bfb8, 0x871d97af, 0xc7050d73, 0x07612564, 0x47cc5d5d,
+ 0x87a8754a, 0xc796ac2f, 0x07f28438, 0x475ffc01, 0x873bd416,
+ 0x8669b963, 0x460d9174, 0x06a0e94d, 0xc6c4c15a, 0x86fa183f,
+ 0x469e3028, 0x06334811, 0xc6576006, 0x864ffada, 0x462bd2cd,
+ 0x0686aaf4, 0xc6e282e3, 0x86dc5b86, 0x46b87391, 0x06150ba8,
+ 0xc67123bf, 0x04b1d142, 0xc4d5f955, 0x8478816c, 0x441ca97b,
+ 0x0422701e, 0xc4465809, 0x84eb2030, 0x448f0827, 0x049792fb,
+ 0xc4f3baec, 0x845ec2d5, 0x443aeac2, 0x040433a7, 0xc4601bb0,
+ 0x84cd6389, 0x44a94b9e, 0x45fb26eb, 0x859f0efc, 0xc53276c5,
+ 0x05565ed2, 0x456887b7, 0x850cafa0, 0xc5a1d799, 0x05c5ff8e,
+ 0x45dd6552, 0x85b94d45, 0xc514357c, 0x05701d6b, 0x454ec40e,
+ 0x852aec19, 0xc5879420, 0x05e3bc37, 0xcf41ed4f, 0x0f25c558,
+ 0x4f88bd61, 0x8fec9576, 0xcfd24c13, 0x0fb66404, 0x4f1b1c3d,
+ 0x8f7f342a, 0xcf67aef6, 0x0f0386e1, 0x4faefed8, 0x8fcad6cf,
+ 0xcff40faa, 0x0f9027bd, 0x4f3d5f84, 0x8f597793, 0x8e0b1ae6,
+ 0x4e6f32f1, 0x0ec24ac8, 0xcea662df, 0x8e98bbba, 0x4efc93ad,
+ 0x0e51eb94, 0xce35c383, 0x8e2d595f, 0x4e497148, 0x0ee40971,
+ 0xce802166, 0x8ebef803, 0x4edad014, 0x0e77a82d, 0xce13803a,
+ 0x0cd372c7, 0xccb75ad0, 0x8c1a22e9, 0x4c7e0afe, 0x0c40d39b,
+ 0xcc24fb8c, 0x8c8983b5, 0x4cedaba2, 0x0cf5317e, 0xcc911969,
+ 0x8c3c6150, 0x4c584947, 0x0c669022, 0xcc02b835, 0x8cafc00c,
+ 0x4ccbe81b, 0x4d99856e, 0x8dfdad79, 0xcd50d540, 0x0d34fd57,
+ 0x4d0a2432, 0x8d6e0c25, 0xcdc3741c, 0x0da75c0b, 0x4dbfc6d7,
+ 0x8ddbeec0, 0xcd7696f9, 0x0d12beee, 0x4d2c678b, 0x8d484f9c,
+ 0xcde537a5, 0x0d811fb2, 0x0862a385, 0xc8068b92, 0x88abf3ab,
+ 0x48cfdbbc, 0x08f102d9, 0xc8952ace, 0x883852f7, 0x485c7ae0,
+ 0x0844e03c, 0xc820c82b, 0x888db012, 0x48e99805, 0x08d74160,
+ 0xc8b36977, 0x881e114e, 0x487a3959, 0x4928542c, 0x894c7c3b,
+ 0xc9e10402, 0x09852c15, 0x49bbf570, 0x89dfdd67, 0xc972a55e,
+ 0x09168d49, 0x490e1795, 0x896a3f82, 0xc9c747bb, 0x09a36fac,
+ 0x499db6c9, 0x89f99ede, 0xc954e6e7, 0x0930cef0, 0xcbf03c0d,
+ 0x0b94141a, 0x4b396c23, 0x8b5d4434, 0xcb639d51, 0x0b07b546,
+ 0x4baacd7f, 0x8bcee568, 0xcbd67fb4, 0x0bb257a3, 0x4b1f2f9a,
+ 0x8b7b078d, 0xcb45dee8, 0x0b21f6ff, 0x4b8c8ec6, 0x8be8a6d1,
+ 0x8abacba4, 0x4adee3b3, 0x0a739b8a, 0xca17b39d, 0x8a296af8,
+ 0x4a4d42ef, 0x0ae03ad6, 0xca8412c1, 0x8a9c881d, 0x4af8a00a,
+ 0x0a55d833, 0xca31f024, 0x8a0f2941, 0x4a6b0156, 0x0ac6796f,
+ 0xcaa25178},
+ {0x00000000, 0xd4ea739b, 0xe9d396ed, 0x3d39e576, 0x93a15c00,
+ 0x474b2f9b, 0x7a72caed, 0xae98b976, 0x2643b900, 0xf2a9ca9b,
+ 0xcf902fed, 0x1b7a5c76, 0xb5e2e500, 0x6108969b, 0x5c3173ed,
+ 0x88db0076, 0x4c867201, 0x986c019a, 0xa555e4ec, 0x71bf9777,
+ 0xdf272e01, 0x0bcd5d9a, 0x36f4b8ec, 0xe21ecb77, 0x6ac5cb01,
+ 0xbe2fb89a, 0x83165dec, 0x57fc2e77, 0xf9649701, 0x2d8ee49a,
+ 0x10b701ec, 0xc45d7277, 0x980ce502, 0x4ce69699, 0x71df73ef,
+ 0xa5350074, 0x0badb902, 0xdf47ca99, 0xe27e2fef, 0x36945c74,
+ 0xbe4f5c02, 0x6aa52f99, 0x579ccaef, 0x8376b974, 0x2dee0002,
+ 0xf9047399, 0xc43d96ef, 0x10d7e574, 0xd48a9703, 0x0060e498,
+ 0x3d5901ee, 0xe9b37275, 0x472bcb03, 0x93c1b898, 0xaef85dee,
+ 0x7a122e75, 0xf2c92e03, 0x26235d98, 0x1b1ab8ee, 0xcff0cb75,
+ 0x61687203, 0xb5820198, 0x88bbe4ee, 0x5c519775, 0x3019ca05,
+ 0xe4f3b99e, 0xd9ca5ce8, 0x0d202f73, 0xa3b89605, 0x7752e59e,
+ 0x4a6b00e8, 0x9e817373, 0x165a7305, 0xc2b0009e, 0xff89e5e8,
+ 0x2b639673, 0x85fb2f05, 0x51115c9e, 0x6c28b9e8, 0xb8c2ca73,
+ 0x7c9fb804, 0xa875cb9f, 0x954c2ee9, 0x41a65d72, 0xef3ee404,
+ 0x3bd4979f, 0x06ed72e9, 0xd2070172, 0x5adc0104, 0x8e36729f,
+ 0xb30f97e9, 0x67e5e472, 0xc97d5d04, 0x1d972e9f, 0x20aecbe9,
+ 0xf444b872, 0xa8152f07, 0x7cff5c9c, 0x41c6b9ea, 0x952cca71,
+ 0x3bb47307, 0xef5e009c, 0xd267e5ea, 0x068d9671, 0x8e569607,
+ 0x5abce59c, 0x678500ea, 0xb36f7371, 0x1df7ca07, 0xc91db99c,
+ 0xf4245cea, 0x20ce2f71, 0xe4935d06, 0x30792e9d, 0x0d40cbeb,
+ 0xd9aab870, 0x77320106, 0xa3d8729d, 0x9ee197eb, 0x4a0be470,
+ 0xc2d0e406, 0x163a979d, 0x2b0372eb, 0xffe90170, 0x5171b806,
+ 0x859bcb9d, 0xb8a22eeb, 0x6c485d70, 0x6032940b, 0xb4d8e790,
+ 0x89e102e6, 0x5d0b717d, 0xf393c80b, 0x2779bb90, 0x1a405ee6,
+ 0xceaa2d7d, 0x46712d0b, 0x929b5e90, 0xafa2bbe6, 0x7b48c87d,
+ 0xd5d0710b, 0x013a0290, 0x3c03e7e6, 0xe8e9947d, 0x2cb4e60a,
+ 0xf85e9591, 0xc56770e7, 0x118d037c, 0xbf15ba0a, 0x6bffc991,
+ 0x56c62ce7, 0x822c5f7c, 0x0af75f0a, 0xde1d2c91, 0xe324c9e7,
+ 0x37ceba7c, 0x9956030a, 0x4dbc7091, 0x708595e7, 0xa46fe67c,
+ 0xf83e7109, 0x2cd40292, 0x11ede7e4, 0xc507947f, 0x6b9f2d09,
+ 0xbf755e92, 0x824cbbe4, 0x56a6c87f, 0xde7dc809, 0x0a97bb92,
+ 0x37ae5ee4, 0xe3442d7f, 0x4ddc9409, 0x9936e792, 0xa40f02e4,
+ 0x70e5717f, 0xb4b80308, 0x60527093, 0x5d6b95e5, 0x8981e67e,
+ 0x27195f08, 0xf3f32c93, 0xcecac9e5, 0x1a20ba7e, 0x92fbba08,
+ 0x4611c993, 0x7b282ce5, 0xafc25f7e, 0x015ae608, 0xd5b09593,
+ 0xe88970e5, 0x3c63037e, 0x502b5e0e, 0x84c12d95, 0xb9f8c8e3,
+ 0x6d12bb78, 0xc38a020e, 0x17607195, 0x2a5994e3, 0xfeb3e778,
+ 0x7668e70e, 0xa2829495, 0x9fbb71e3, 0x4b510278, 0xe5c9bb0e,
+ 0x3123c895, 0x0c1a2de3, 0xd8f05e78, 0x1cad2c0f, 0xc8475f94,
+ 0xf57ebae2, 0x2194c979, 0x8f0c700f, 0x5be60394, 0x66dfe6e2,
+ 0xb2359579, 0x3aee950f, 0xee04e694, 0xd33d03e2, 0x07d77079,
+ 0xa94fc90f, 0x7da5ba94, 0x409c5fe2, 0x94762c79, 0xc827bb0c,
+ 0x1ccdc897, 0x21f42de1, 0xf51e5e7a, 0x5b86e70c, 0x8f6c9497,
+ 0xb25571e1, 0x66bf027a, 0xee64020c, 0x3a8e7197, 0x07b794e1,
+ 0xd35de77a, 0x7dc55e0c, 0xa92f2d97, 0x9416c8e1, 0x40fcbb7a,
+ 0x84a1c90d, 0x504bba96, 0x6d725fe0, 0xb9982c7b, 0x1700950d,
+ 0xc3eae696, 0xfed303e0, 0x2a39707b, 0xa2e2700d, 0x76080396,
+ 0x4b31e6e0, 0x9fdb957b, 0x31432c0d, 0xe5a95f96, 0xd890bae0,
+ 0x0c7ac97b},
+ {0x00000000, 0x27652581, 0x0fcc3bd9, 0x28a91e58, 0x5f9e0669,
+ 0x78fb23e8, 0x50523db0, 0x77371831, 0xbe3c0dd2, 0x99592853,
+ 0xb1f0360b, 0x9695138a, 0xe1a20bbb, 0xc6c72e3a, 0xee6e3062,
+ 0xc90b15e3, 0x3d7f6b7f, 0x1a1a4efe, 0x32b350a6, 0x15d67527,
+ 0x62e16d16, 0x45844897, 0x6d2d56cf, 0x4a48734e, 0x834366ad,
+ 0xa426432c, 0x8c8f5d74, 0xabea78f5, 0xdcdd60c4, 0xfbb84545,
+ 0xd3115b1d, 0xf4747e9c, 0x7afed6fe, 0x5d9bf37f, 0x7532ed27,
+ 0x5257c8a6, 0x2560d097, 0x0205f516, 0x2aaceb4e, 0x0dc9cecf,
+ 0xc4c2db2c, 0xe3a7fead, 0xcb0ee0f5, 0xec6bc574, 0x9b5cdd45,
+ 0xbc39f8c4, 0x9490e69c, 0xb3f5c31d, 0x4781bd81, 0x60e49800,
+ 0x484d8658, 0x6f28a3d9, 0x181fbbe8, 0x3f7a9e69, 0x17d38031,
+ 0x30b6a5b0, 0xf9bdb053, 0xded895d2, 0xf6718b8a, 0xd114ae0b,
+ 0xa623b63a, 0x814693bb, 0xa9ef8de3, 0x8e8aa862, 0xb5fadc26,
+ 0x929ff9a7, 0xba36e7ff, 0x9d53c27e, 0xea64da4f, 0xcd01ffce,
+ 0xe5a8e196, 0xc2cdc417, 0x0bc6d1f4, 0x2ca3f475, 0x040aea2d,
+ 0x236fcfac, 0x5458d79d, 0x733df21c, 0x5b94ec44, 0x7cf1c9c5,
+ 0x8885b759, 0xafe092d8, 0x87498c80, 0xa02ca901, 0xd71bb130,
+ 0xf07e94b1, 0xd8d78ae9, 0xffb2af68, 0x36b9ba8b, 0x11dc9f0a,
+ 0x39758152, 0x1e10a4d3, 0x6927bce2, 0x4e429963, 0x66eb873b,
+ 0x418ea2ba, 0xcf040ad8, 0xe8612f59, 0xc0c83101, 0xe7ad1480,
+ 0x909a0cb1, 0xb7ff2930, 0x9f563768, 0xb83312e9, 0x7138070a,
+ 0x565d228b, 0x7ef43cd3, 0x59911952, 0x2ea60163, 0x09c324e2,
+ 0x216a3aba, 0x060f1f3b, 0xf27b61a7, 0xd51e4426, 0xfdb75a7e,
+ 0xdad27fff, 0xade567ce, 0x8a80424f, 0xa2295c17, 0x854c7996,
+ 0x4c476c75, 0x6b2249f4, 0x438b57ac, 0x64ee722d, 0x13d96a1c,
+ 0x34bc4f9d, 0x1c1551c5, 0x3b707444, 0x6af5b94d, 0x4d909ccc,
+ 0x65398294, 0x425ca715, 0x356bbf24, 0x120e9aa5, 0x3aa784fd,
+ 0x1dc2a17c, 0xd4c9b49f, 0xf3ac911e, 0xdb058f46, 0xfc60aac7,
+ 0x8b57b2f6, 0xac329777, 0x849b892f, 0xa3feacae, 0x578ad232,
+ 0x70eff7b3, 0x5846e9eb, 0x7f23cc6a, 0x0814d45b, 0x2f71f1da,
+ 0x07d8ef82, 0x20bdca03, 0xe9b6dfe0, 0xced3fa61, 0xe67ae439,
+ 0xc11fc1b8, 0xb628d989, 0x914dfc08, 0xb9e4e250, 0x9e81c7d1,
+ 0x100b6fb3, 0x376e4a32, 0x1fc7546a, 0x38a271eb, 0x4f9569da,
+ 0x68f04c5b, 0x40595203, 0x673c7782, 0xae376261, 0x895247e0,
+ 0xa1fb59b8, 0x869e7c39, 0xf1a96408, 0xd6cc4189, 0xfe655fd1,
+ 0xd9007a50, 0x2d7404cc, 0x0a11214d, 0x22b83f15, 0x05dd1a94,
+ 0x72ea02a5, 0x558f2724, 0x7d26397c, 0x5a431cfd, 0x9348091e,
+ 0xb42d2c9f, 0x9c8432c7, 0xbbe11746, 0xccd60f77, 0xebb32af6,
+ 0xc31a34ae, 0xe47f112f, 0xdf0f656b, 0xf86a40ea, 0xd0c35eb2,
+ 0xf7a67b33, 0x80916302, 0xa7f44683, 0x8f5d58db, 0xa8387d5a,
+ 0x613368b9, 0x46564d38, 0x6eff5360, 0x499a76e1, 0x3ead6ed0,
+ 0x19c84b51, 0x31615509, 0x16047088, 0xe2700e14, 0xc5152b95,
+ 0xedbc35cd, 0xcad9104c, 0xbdee087d, 0x9a8b2dfc, 0xb22233a4,
+ 0x95471625, 0x5c4c03c6, 0x7b292647, 0x5380381f, 0x74e51d9e,
+ 0x03d205af, 0x24b7202e, 0x0c1e3e76, 0x2b7b1bf7, 0xa5f1b395,
+ 0x82949614, 0xaa3d884c, 0x8d58adcd, 0xfa6fb5fc, 0xdd0a907d,
+ 0xf5a38e25, 0xd2c6aba4, 0x1bcdbe47, 0x3ca89bc6, 0x1401859e,
+ 0x3364a01f, 0x4453b82e, 0x63369daf, 0x4b9f83f7, 0x6cfaa676,
+ 0x988ed8ea, 0xbfebfd6b, 0x9742e333, 0xb027c6b2, 0xc710de83,
+ 0xe075fb02, 0xc8dce55a, 0xefb9c0db, 0x26b2d538, 0x01d7f0b9,
+ 0x297eeee1, 0x0e1bcb60, 0x792cd351, 0x5e49f6d0, 0x76e0e888,
+ 0x5185cd09}};
+
+#endif
+
+#endif
+
+#endif
+
+local const z_crc_t FAR x2n_table[] = {
+ 0x40000000, 0x20000000, 0x08000000, 0x00800000, 0x00008000,
+ 0xedb88320, 0xb1e6b092, 0xa06a2517, 0xed627dae, 0x88d14467,
+ 0xd7bbfe6a, 0xec447f11, 0x8e7ea170, 0x6427800e, 0x4d47bae0,
+ 0x09fe548f, 0x83852d0f, 0x30362f1a, 0x7b5a9cc3, 0x31fec169,
+ 0x9fec022a, 0x6c8dedc4, 0x15d6874d, 0x5fde7a4e, 0xbad90e37,
+ 0x2e4e5eef, 0x4eaba214, 0xa8a472c0, 0x429a969e, 0x148d302a,
+ 0xc40ba6d0, 0xc4e22c3c};
diff --git a/thirdparty/zlib/deflate.c b/thirdparty/zlib/deflate.c
index 1ec761448d..799fb93cc0 100644
--- a/thirdparty/zlib/deflate.c
+++ b/thirdparty/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ * Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.2.11 Copyright 1995-2017 Jean-loup Gailly and Mark Adler ";
+ " deflate 1.2.12 Copyright 1995-2022 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -190,8 +190,11 @@ local const config configuration_table[10] = {
* prev[] will be initialized on the fly.
*/
#define CLEAR_HASH(s) \
- s->head[s->hash_size-1] = NIL; \
- zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+ do { \
+ s->head[s->hash_size-1] = NIL; \
+ zmemzero((Bytef *)s->head, \
+ (unsigned)(s->hash_size-1)*sizeof(*s->head)); \
+ } while (0)
/* ===========================================================================
* Slide the hash table when sliding the window down (could be avoided with 32
@@ -252,11 +255,6 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
int wrap = 1;
static const char my_version[] = ZLIB_VERSION;
- ushf *overlay;
- /* We overlay pending_buf and d_buf+l_buf. This works since the average
- * output size for (length,distance) codes is <= 24 bits.
- */
-
if (version == Z_NULL || version[0] != my_version[0] ||
stream_size != sizeof(z_stream)) {
return Z_VERSION_ERROR;
@@ -326,9 +324,47 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
- overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
- s->pending_buf = (uchf *) overlay;
- s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+ /* We overlay pending_buf and sym_buf. This works since the average size
+ * for length/distance pairs over any compressed block is assured to be 31
+ * bits or less.
+ *
+ * Analysis: The longest fixed codes are a length code of 8 bits plus 5
+ * extra bits, for lengths 131 to 257. The longest fixed distance codes are
+ * 5 bits plus 13 extra bits, for distances 16385 to 32768. The longest
+ * possible fixed-codes length/distance pair is then 31 bits total.
+ *
+ * sym_buf starts one-fourth of the way into pending_buf. So there are
+ * three bytes in sym_buf for every four bytes in pending_buf. Each symbol
+ * in sym_buf is three bytes -- two for the distance and one for the
+ * literal/length. As each symbol is consumed, the pointer to the next
+ * sym_buf value to read moves forward three bytes. From that symbol, up to
+ * 31 bits are written to pending_buf. The closest the written pending_buf
+ * bits gets to the next sym_buf symbol to read is just before the last
+ * code is written. At that time, 31*(n-2) bits have been written, just
+ * after 24*(n-2) bits have been consumed from sym_buf. sym_buf starts at
+ * 8*n bits into pending_buf. (Note that the symbol buffer fills when n-1
+ * symbols are written.) The closest the writing gets to what is unread is
+ * then n+14 bits. Here n is lit_bufsize, which is 16384 by default, and
+ * can range from 128 to 32768.
+ *
+ * Therefore, at a minimum, there are 142 bits of space between what is
+ * written and what is read in the overlain buffers, so the symbols cannot
+ * be overwritten by the compressed data. That space is actually 139 bits,
+ * due to the three-bit fixed-code block header.
+ *
+ * That covers the case where either Z_FIXED is specified, forcing fixed
+ * codes, or when the use of fixed codes is chosen, because that choice
+ * results in a smaller compressed block than dynamic codes. That latter
+ * condition then assures that the above analysis also covers all dynamic
+ * blocks. A dynamic-code block will only be chosen to be emitted if it has
+ * fewer bits than a fixed-code block would for the same set of symbols.
+ * Therefore its average symbol length is assured to be less than 31. So
+ * the compressed data for a dynamic block also cannot overwrite the
+ * symbols from which it is being constructed.
+ */
+
+ s->pending_buf = (uchf *) ZALLOC(strm, s->lit_bufsize, 4);
+ s->pending_buf_size = (ulg)s->lit_bufsize * 4;
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL ||
s->pending_buf == Z_NULL) {
@@ -337,8 +373,12 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
deflateEnd (strm);
return Z_MEM_ERROR;
}
- s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
- s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+ s->sym_buf = s->pending_buf + s->lit_bufsize;
+ s->sym_end = (s->lit_bufsize - 1) * 3;
+ /* We avoid equality with lit_bufsize*3 because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
s->level = level;
s->strategy = strategy;
@@ -488,13 +528,13 @@ int ZEXPORT deflateResetKeep (strm)
#ifdef GZIP
s->wrap == 2 ? GZIP_STATE :
#endif
- s->wrap ? INIT_STATE : BUSY_STATE;
+ INIT_STATE;
strm->adler =
#ifdef GZIP
s->wrap == 2 ? crc32(0L, Z_NULL, 0) :
#endif
adler32(0L, Z_NULL, 0);
- s->last_flush = Z_NO_FLUSH;
+ s->last_flush = -2;
_tr_init(s);
@@ -549,7 +589,8 @@ int ZEXPORT deflatePrime (strm, bits, value)
if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
s = strm->state;
- if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3))
+ if (bits < 0 || bits > 16 ||
+ s->sym_buf < s->pending_out + ((Buf_size + 7) >> 3))
return Z_BUF_ERROR;
do {
put = Buf_size - s->bi_valid;
@@ -587,12 +628,12 @@ int ZEXPORT deflateParams(strm, level, strategy)
func = configuration_table[s->level].func;
if ((strategy != s->strategy || func != configuration_table[level].func) &&
- s->high_water) {
+ s->last_flush != -2) {
/* Flush the last buffer: */
int err = deflate(strm, Z_BLOCK);
if (err == Z_STREAM_ERROR)
return err;
- if (strm->avail_out == 0)
+ if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
return Z_BUF_ERROR;
}
if (s->level != level) {
@@ -811,6 +852,8 @@ int ZEXPORT deflate (strm, flush)
}
/* Write the header */
+ if (s->status == INIT_STATE && s->wrap == 0)
+ s->status = BUSY_STATE;
if (s->status == INIT_STATE) {
/* zlib header */
uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
@@ -1108,7 +1151,6 @@ int ZEXPORT deflateCopy (dest, source)
#else
deflate_state *ds;
deflate_state *ss;
- ushf *overlay;
if (deflateStateCheck(source) || dest == Z_NULL) {
@@ -1128,8 +1170,7 @@ int ZEXPORT deflateCopy (dest, source)
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos));
ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos));
- overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2);
- ds->pending_buf = (uchf *) overlay;
+ ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL ||
ds->pending_buf == Z_NULL) {
@@ -1143,8 +1184,7 @@ int ZEXPORT deflateCopy (dest, source)
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
- ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
- ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+ ds->sym_buf = ds->pending_buf + ds->lit_bufsize;
ds->l_desc.dyn_tree = ds->dyn_ltree;
ds->d_desc.dyn_tree = ds->dyn_dtree;
@@ -1513,6 +1553,8 @@ local void fill_window(s)
s->match_start -= wsize;
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
s->block_start -= (long) wsize;
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
slide_hash(s);
more += wsize;
}
@@ -1742,6 +1784,7 @@ local block_state deflate_stored(s, flush)
s->matches = 2; /* clear hash */
zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size);
s->strstart = s->w_size;
+ s->insert = s->strstart;
}
else {
if (s->window_size - s->strstart <= used) {
@@ -1750,12 +1793,14 @@ local block_state deflate_stored(s, flush)
zmemcpy(s->window, s->window + s->w_size, s->strstart);
if (s->matches < 2)
s->matches++; /* add a pending slide_hash() */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
}
zmemcpy(s->window + s->strstart, s->strm->next_in - used, used);
s->strstart += used;
+ s->insert += MIN(used, s->w_size - s->insert);
}
s->block_start = s->strstart;
- s->insert += MIN(used, s->w_size - s->insert);
}
if (s->high_water < s->strstart)
s->high_water = s->strstart;
@@ -1770,7 +1815,7 @@ local block_state deflate_stored(s, flush)
return block_done;
/* Fill the window with any remaining input. */
- have = s->window_size - s->strstart - 1;
+ have = s->window_size - s->strstart;
if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) {
/* Slide the window down. */
s->block_start -= s->w_size;
@@ -1779,12 +1824,15 @@ local block_state deflate_stored(s, flush)
if (s->matches < 2)
s->matches++; /* add a pending slide_hash() */
have += s->w_size; /* more space now */
+ if (s->insert > s->strstart)
+ s->insert = s->strstart;
}
if (have > s->strm->avail_in)
have = s->strm->avail_in;
if (have) {
read_buf(s->strm, s->window + s->strstart, have);
s->strstart += have;
+ s->insert += MIN(have, s->w_size - s->insert);
}
if (s->high_water < s->strstart)
s->high_water = s->strstart;
@@ -1912,7 +1960,7 @@ local block_state deflate_fast(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2043,7 +2091,7 @@ local block_state deflate_slow(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2118,7 +2166,7 @@ local block_state deflate_rle(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
@@ -2157,7 +2205,7 @@ local block_state deflate_huff(s, flush)
FLUSH_BLOCK(s, 1);
return finish_done;
}
- if (s->last_lit)
+ if (s->sym_next)
FLUSH_BLOCK(s, 0);
return block_done;
}
diff --git a/thirdparty/zlib/deflate.h b/thirdparty/zlib/deflate.h
index 23ecdd312b..17c226113b 100644
--- a/thirdparty/zlib/deflate.h
+++ b/thirdparty/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2016 Jean-loup Gailly
+ * Copyright (C) 1995-2018 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -217,7 +217,7 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency
*/
- uchf *l_buf; /* buffer for literals or lengths */
+ uchf *sym_buf; /* buffer for distances and literals/lengths */
uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for
@@ -239,13 +239,8 @@ typedef struct internal_state {
* - I can't count above 4
*/
- uInt last_lit; /* running index in l_buf */
-
- ushf *d_buf;
- /* Buffer for distances. To simplify the code, d_buf and l_buf have
- * the same number of elements. To use different lengths, an extra flag
- * array would be necessary.
- */
+ uInt sym_next; /* running index in sym_buf */
+ uInt sym_end; /* symbol table full when sym_next reaches this */
ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */
@@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
# define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \
- s->d_buf[s->last_lit] = 0; \
- s->l_buf[s->last_lit++] = cc; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = 0; \
+ s->sym_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \
- flush = (s->last_lit == s->lit_bufsize-1); \
+ flush = (s->sym_next == s->sym_end); \
}
# define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \
ush dist = (ush)(distance); \
- s->d_buf[s->last_lit] = dist; \
- s->l_buf[s->last_lit++] = len; \
+ s->sym_buf[s->sym_next++] = dist; \
+ s->sym_buf[s->sym_next++] = dist >> 8; \
+ s->sym_buf[s->sym_next++] = len; \
dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \
- flush = (s->last_lit == s->lit_bufsize-1); \
+ flush = (s->sym_next == s->sym_end); \
}
#else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)
diff --git a/thirdparty/zlib/gzguts.h b/thirdparty/zlib/gzguts.h
index 990a4d2514..57faf37165 100644
--- a/thirdparty/zlib/gzguts.h
+++ b/thirdparty/zlib/gzguts.h
@@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -39,7 +39,7 @@
# include <io.h>
#endif
-#if defined(_WIN32) || defined(__CYGWIN__)
+#if defined(_WIN32)
# define WIDECHAR
#endif
@@ -190,6 +190,7 @@ typedef struct {
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
+ int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
diff --git a/thirdparty/zlib/gzlib.c b/thirdparty/zlib/gzlib.c
index 4105e6aff9..dddaf26873 100644
--- a/thirdparty/zlib/gzlib.c
+++ b/thirdparty/zlib/gzlib.c
@@ -1,11 +1,11 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
- * Copyright (C) 2004-2017 Mark Adler
+ * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
-#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
+#if defined(_WIN32) && !defined(__BORLANDC__)
# define LSEEK _lseeki64
#else
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
@@ -81,6 +81,8 @@ local void gz_reset(state)
state->past = 0; /* have not read past end yet */
state->how = LOOK; /* look for gzip header */
}
+ else /* for writing ... */
+ state->reset = 0; /* no deflateReset pending */
state->seek = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */
state->x.pos = 0; /* no uncompressed data yet */
@@ -397,7 +399,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) {
- ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
+ ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
if (ret == -1)
return -1;
state->x.have = 0;
diff --git a/thirdparty/zlib/gzread.c b/thirdparty/zlib/gzread.c
index 956b91ea7d..884c9bfe4c 100644
--- a/thirdparty/zlib/gzread.c
+++ b/thirdparty/zlib/gzread.c
@@ -1,5 +1,5 @@
/* gzread.c -- zlib functions for reading gzip files
- * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
+ * Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -314,9 +314,9 @@ local z_size_t gz_read(state, buf, len)
got = 0;
do {
/* set n to the maximum amount of len that fits in an unsigned int */
- n = -1;
+ n = (unsigned)-1;
if (n > len)
- n = len;
+ n = (unsigned)len;
/* first just try copying data from the output buffer */
if (state->x.have) {
@@ -397,7 +397,7 @@ int ZEXPORT gzread(file, buf, len)
}
/* read len or fewer bytes to buf */
- len = gz_read(state, buf, len);
+ len = (unsigned)gz_read(state, buf, len);
/* check for an error */
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
@@ -447,7 +447,6 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
int ZEXPORT gzgetc(file)
gzFile file;
{
- int ret;
unsigned char buf[1];
gz_statep state;
@@ -469,8 +468,7 @@ int ZEXPORT gzgetc(file)
}
/* nothing there -- try gz_read() */
- ret = gz_read(state, buf, 1);
- return ret < 1 ? -1 : buf[0];
+ return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
}
int ZEXPORT gzgetc_(file)
diff --git a/thirdparty/zlib/gzwrite.c b/thirdparty/zlib/gzwrite.c
index c7b5651d70..a8ffc8f53d 100644
--- a/thirdparty/zlib/gzwrite.c
+++ b/thirdparty/zlib/gzwrite.c
@@ -1,5 +1,5 @@
/* gzwrite.c -- zlib functions for writing gzip files
- * Copyright (C) 2004-2017 Mark Adler
+ * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -97,6 +97,15 @@ local int gz_comp(state, flush)
return 0;
}
+ /* check for a pending reset */
+ if (state->reset) {
+ /* don't start a new gzip member unless there is data to write */
+ if (strm->avail_in == 0)
+ return 0;
+ deflateReset(strm);
+ state->reset = 0;
+ }
+
/* run deflate() on provided input until it produces no more output */
ret = Z_OK;
do {
@@ -134,7 +143,7 @@ local int gz_comp(state, flush)
/* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH)
- deflateReset(strm);
+ state->reset = 1;
/* all done, no errors */
return 0;
@@ -209,7 +218,7 @@ local z_size_t gz_write(state, buf, len)
state->in);
copy = state->size - have;
if (copy > len)
- copy = len;
+ copy = (unsigned)len;
memcpy(state->in + have, buf, copy);
state->strm.avail_in += copy;
state->x.pos += copy;
@@ -229,7 +238,7 @@ local z_size_t gz_write(state, buf, len)
do {
unsigned n = (unsigned)-1;
if (n > len)
- n = len;
+ n = (unsigned)len;
state->strm.avail_in = n;
state->x.pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1)
@@ -349,12 +358,11 @@ int ZEXPORT gzputc(file, c)
}
/* -- see zlib.h -- */
-int ZEXPORT gzputs(file, str)
+int ZEXPORT gzputs(file, s)
gzFile file;
- const char *str;
+ const char *s;
{
- int ret;
- z_size_t len;
+ z_size_t len, put;
gz_statep state;
/* get internal structure */
@@ -367,9 +375,13 @@ int ZEXPORT gzputs(file, str)
return -1;
/* write string */
- len = strlen(str);
- ret = gz_write(state, str, len);
- return ret == 0 && len != 0 ? -1 : ret;
+ len = strlen(s);
+ if ((int)len < 0 || (unsigned)len != len) {
+ gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
+ return -1;
+ }
+ put = gz_write(state, s, len);
+ return put < len ? -1 : (int)len;
}
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
@@ -441,7 +453,7 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err;
- memcpy(state->in, state->in + state->size, left);
+ memmove(state->in, state->in + state->size, left);
strm->next_in = state->in;
strm->avail_in = left;
}
@@ -540,7 +552,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err;
- memcpy(state->in, state->in + state->size, left);
+ memmove(state->in, state->in + state->size, left);
strm->next_in = state->in;
strm->avail_in = left;
}
diff --git a/thirdparty/zlib/infback.c b/thirdparty/zlib/infback.c
index 59679ecbfc..a390c58e81 100644
--- a/thirdparty/zlib/infback.c
+++ b/thirdparty/zlib/infback.c
@@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -477,6 +477,7 @@ void FAR *out_desc;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;
+ /* fallthrough */
case LEN:
/* use inflate_fast() if we have enough input and output */
diff --git a/thirdparty/zlib/inffast.c b/thirdparty/zlib/inffast.c
index 0dbd1dbc09..1fec7f363f 100644
--- a/thirdparty/zlib/inffast.c
+++ b/thirdparty/zlib/inffast.c
@@ -70,7 +70,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */
- code here; /* retrieved table entry */
+ code const *here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */
@@ -107,20 +107,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = lcode[hold & lmask];
+ here = lcode + (hold & lmask);
dolen:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op == 0) { /* literal */
- Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+ Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
"inflate: literal '%c'\n" :
- "inflate: literal 0x%02x\n", here.val));
- *out++ = (unsigned char)(here.val);
+ "inflate: literal 0x%02x\n", here->val));
+ *out++ = (unsigned char)(here->val);
}
else if (op & 16) { /* length base */
- len = (unsigned)(here.val);
+ len = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (op) {
if (bits < op) {
@@ -138,14 +138,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits;
bits += 8;
}
- here = dcode[hold & dmask];
+ here = dcode + (hold & dmask);
dodist:
- op = (unsigned)(here.bits);
+ op = (unsigned)(here->bits);
hold >>= op;
bits -= op;
- op = (unsigned)(here.op);
+ op = (unsigned)(here->op);
if (op & 16) { /* distance base */
- dist = (unsigned)(here.val);
+ dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */
if (bits < op) {
hold += (unsigned long)(*in++) << bits;
@@ -264,7 +264,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
else if ((op & 64) == 0) { /* 2nd level distance code */
- here = dcode[here.val + (hold & ((1U << op) - 1))];
+ here = dcode + here->val + (hold & ((1U << op) - 1));
goto dodist;
}
else {
@@ -274,7 +274,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
}
}
else if ((op & 64) == 0) { /* 2nd level length code */
- here = lcode[here.val + (hold & ((1U << op) - 1))];
+ here = lcode + here->val + (hold & ((1U << op) - 1));
goto dolen;
}
else if (op & 32) { /* end-of-block */
diff --git a/thirdparty/zlib/inflate.c b/thirdparty/zlib/inflate.c
index ac333e8c2e..7be8c63662 100644
--- a/thirdparty/zlib/inflate.c
+++ b/thirdparty/zlib/inflate.c
@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -130,6 +130,7 @@ z_streamp strm;
state->mode = HEAD;
state->last = 0;
state->havedict = 0;
+ state->flags = -1;
state->dmax = 32768U;
state->head = Z_NULL;
state->hold = 0;
@@ -447,10 +448,10 @@ unsigned copy;
/* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP
-# define UPDATE(check, buf, len) \
+# define UPDATE_CHECK(check, buf, len) \
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else
-# define UPDATE(check, buf, len) adler32(check, buf, len)
+# define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif
/* check macros for header crc */
@@ -670,7 +671,6 @@ int flush;
state->mode = FLAGS;
break;
}
- state->flags = 0; /* expect zlib header */
if (state->head != Z_NULL)
state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */
@@ -697,6 +697,7 @@ int flush;
break;
}
state->dmax = 1U << len;
+ state->flags = 0; /* indicate zlib header */
Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -722,6 +723,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = TIME;
+ /* fallthrough */
case TIME:
NEEDBITS(32);
if (state->head != Z_NULL)
@@ -730,6 +732,7 @@ int flush;
CRC4(state->check, hold);
INITBITS();
state->mode = OS;
+ /* fallthrough */
case OS:
NEEDBITS(16);
if (state->head != Z_NULL) {
@@ -740,6 +743,7 @@ int flush;
CRC2(state->check, hold);
INITBITS();
state->mode = EXLEN;
+ /* fallthrough */
case EXLEN:
if (state->flags & 0x0400) {
NEEDBITS(16);
@@ -753,6 +757,7 @@ int flush;
else if (state->head != Z_NULL)
state->head->extra = Z_NULL;
state->mode = EXTRA;
+ /* fallthrough */
case EXTRA:
if (state->flags & 0x0400) {
copy = state->length;
@@ -775,6 +780,7 @@ int flush;
}
state->length = 0;
state->mode = NAME;
+ /* fallthrough */
case NAME:
if (state->flags & 0x0800) {
if (have == 0) goto inf_leave;
@@ -796,6 +802,7 @@ int flush;
state->head->name = Z_NULL;
state->length = 0;
state->mode = COMMENT;
+ /* fallthrough */
case COMMENT:
if (state->flags & 0x1000) {
if (have == 0) goto inf_leave;
@@ -816,6 +823,7 @@ int flush;
else if (state->head != Z_NULL)
state->head->comment = Z_NULL;
state->mode = HCRC;
+ /* fallthrough */
case HCRC:
if (state->flags & 0x0200) {
NEEDBITS(16);
@@ -839,6 +847,7 @@ int flush;
strm->adler = state->check = ZSWAP32(hold);
INITBITS();
state->mode = DICT;
+ /* fallthrough */
case DICT:
if (state->havedict == 0) {
RESTORE();
@@ -846,8 +855,10 @@ int flush;
}
strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE;
+ /* fallthrough */
case TYPE:
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case TYPEDO:
if (state->last) {
BYTEBITS();
@@ -898,8 +909,10 @@ int flush;
INITBITS();
state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case COPY_:
state->mode = COPY;
+ /* fallthrough */
case COPY:
copy = state->length;
if (copy) {
@@ -935,6 +948,7 @@ int flush;
Tracev((stderr, "inflate: table sizes ok\n"));
state->have = 0;
state->mode = LENLENS;
+ /* fallthrough */
case LENLENS:
while (state->have < state->ncode) {
NEEDBITS(3);
@@ -956,6 +970,7 @@ int flush;
Tracev((stderr, "inflate: code lengths ok\n"));
state->have = 0;
state->mode = CODELENS;
+ /* fallthrough */
case CODELENS:
while (state->have < state->nlen + state->ndist) {
for (;;) {
@@ -1039,8 +1054,10 @@ int flush;
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave;
+ /* fallthrough */
case LEN_:
state->mode = LEN;
+ /* fallthrough */
case LEN:
if (have >= 6 && left >= 258) {
RESTORE();
@@ -1090,6 +1107,7 @@ int flush;
}
state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT;
+ /* fallthrough */
case LENEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1100,6 +1118,7 @@ int flush;
Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length;
state->mode = DIST;
+ /* fallthrough */
case DIST:
for (;;) {
here = state->distcode[BITS(state->distbits)];
@@ -1127,6 +1146,7 @@ int flush;
state->offset = (unsigned)here.val;
state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT;
+ /* fallthrough */
case DISTEXT:
if (state->extra) {
NEEDBITS(state->extra);
@@ -1143,6 +1163,7 @@ int flush;
#endif
Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH;
+ /* fallthrough */
case MATCH:
if (left == 0) goto inf_leave;
copy = out - left;
@@ -1202,7 +1223,7 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, put - out, out);
+ UPDATE_CHECK(state->check, put - out, out);
out = left;
if ((state->wrap & 4) && (
#ifdef GUNZIP
@@ -1218,10 +1239,11 @@ int flush;
}
#ifdef GUNZIP
state->mode = LENGTH;
+ /* fallthrough */
case LENGTH:
if (state->wrap && state->flags) {
NEEDBITS(32);
- if (hold != (state->total & 0xffffffffUL)) {
+ if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
strm->msg = (char *)"incorrect length check";
state->mode = BAD;
break;
@@ -1231,6 +1253,7 @@ int flush;
}
#endif
state->mode = DONE;
+ /* fallthrough */
case DONE:
ret = Z_STREAM_END;
goto inf_leave;
@@ -1240,6 +1263,7 @@ int flush;
case MEM:
return Z_MEM_ERROR;
case SYNC:
+ /* fallthrough */
default:
return Z_STREAM_ERROR;
}
@@ -1265,7 +1289,7 @@ int flush;
state->total += out;
if ((state->wrap & 4) && out)
strm->adler = state->check =
- UPDATE(state->check, strm->next_out - out, out);
+ UPDATE_CHECK(state->check, strm->next_out - out, out);
strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
@@ -1401,6 +1425,7 @@ int ZEXPORT inflateSync(strm)
z_streamp strm;
{
unsigned len; /* number of bytes to look at or looked at */
+ int flags; /* temporary to save header status */
unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state;
@@ -1433,9 +1458,15 @@ z_streamp strm;
/* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR;
+ if (state->flags == -1)
+ state->wrap = 0; /* if no header yet, treat as raw */
+ else
+ state->wrap &= ~4; /* no point in computing a check value now */
+ flags = state->flags;
in = strm->total_in; out = strm->total_out;
inflateReset(strm);
strm->total_in = in; strm->total_out = out;
+ state->flags = flags;
state->mode = TYPE;
return Z_OK;
}
@@ -1531,7 +1562,7 @@ int check;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
- if (check)
+ if (check && state->wrap)
state->wrap |= 4;
else
state->wrap &= ~4;
diff --git a/thirdparty/zlib/inflate.h b/thirdparty/zlib/inflate.h
index a46cce6b6d..f127b6b1fa 100644
--- a/thirdparty/zlib/inflate.h
+++ b/thirdparty/zlib/inflate.h
@@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition
- * Copyright (C) 1995-2016 Mark Adler
+ * Copyright (C) 1995-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -86,7 +86,8 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */
int havedict; /* true if dictionary provided */
- int flags; /* gzip header method and flags (0 if zlib) */
+ int flags; /* gzip header method and flags, 0 if zlib, or
+ -1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */
diff --git a/thirdparty/zlib/inftrees.c b/thirdparty/zlib/inftrees.c
index 2ea08fc13e..09462a740b 100644
--- a/thirdparty/zlib/inftrees.c
+++ b/thirdparty/zlib/inftrees.c
@@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-2017 Mark Adler
+ * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -9,7 +9,7 @@
#define MAXBITS 15
const char inflate_copyright[] =
- " inflate 1.2.11 Copyright 1995-2017 Mark Adler ";
+ " inflate 1.2.12 Copyright 1995-2022 Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -62,7 +62,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
- 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202};
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 199, 202};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
diff --git a/thirdparty/zlib/trees.c b/thirdparty/zlib/trees.c
index 50cf4b4571..f73fd99c37 100644
--- a/thirdparty/zlib/trees.c
+++ b/thirdparty/zlib/trees.c
@@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2017 Jean-loup Gailly
+ * Copyright (C) 1995-2021 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -149,7 +149,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
local void compress_block OF((deflate_state *s, const ct_data *ltree,
const ct_data *dtree));
local int detect_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned value, int length));
+local unsigned bi_reverse OF((unsigned code, int len));
local void bi_windup OF((deflate_state *s));
local void bi_flush OF((deflate_state *s));
@@ -416,7 +416,7 @@ local void init_block(s)
s->dyn_ltree[END_BLOCK].Freq = 1;
s->opt_len = s->static_len = 0L;
- s->last_lit = s->matches = 0;
+ s->sym_next = s->matches = 0;
}
#define SMALLEST 1
@@ -870,7 +870,8 @@ void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last)
bi_windup(s); /* align on byte boundary */
put_short(s, (ush)stored_len);
put_short(s, (ush)~stored_len);
- zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
+ if (stored_len)
+ zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
s->pending += stored_len;
#ifdef ZLIB_DEBUG
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
@@ -947,7 +948,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
- s->last_lit));
+ s->sym_next / 3));
if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
@@ -1016,8 +1017,9 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
unsigned dist; /* distance of matched string */
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */
{
- s->d_buf[s->last_lit] = (ush)dist;
- s->l_buf[s->last_lit++] = (uch)lc;
+ s->sym_buf[s->sym_next++] = dist;
+ s->sym_buf[s->sym_next++] = dist >> 8;
+ s->sym_buf[s->sym_next++] = lc;
if (dist == 0) {
/* lc is the unmatched char */
s->dyn_ltree[lc].Freq++;
@@ -1032,30 +1034,7 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++;
s->dyn_dtree[d_code(dist)].Freq++;
}
-
-#ifdef TRUNCATE_BLOCK
- /* Try to guess if it is profitable to stop the current block here */
- if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
- /* Compute an upper bound for the compressed length */
- ulg out_length = (ulg)s->last_lit*8L;
- ulg in_length = (ulg)((long)s->strstart - s->block_start);
- int dcode;
- for (dcode = 0; dcode < D_CODES; dcode++) {
- out_length += (ulg)s->dyn_dtree[dcode].Freq *
- (5L+extra_dbits[dcode]);
- }
- out_length >>= 3;
- Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
- s->last_lit, in_length, out_length,
- 100L - out_length*100L/in_length));
- if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
- }
-#endif
- return (s->last_lit == s->lit_bufsize-1);
- /* We avoid equality with lit_bufsize because of wraparound at 64K
- * on 16 bit machines and because stored blocks are restricted to
- * 64K-1 bytes.
- */
+ return (s->sym_next == s->sym_end);
}
/* ===========================================================================
@@ -1068,13 +1047,14 @@ local void compress_block(s, ltree, dtree)
{
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
- unsigned lx = 0; /* running index in l_buf */
+ unsigned sx = 0; /* running index in sym_buf */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
- if (s->last_lit != 0) do {
- dist = s->d_buf[lx];
- lc = s->l_buf[lx++];
+ if (s->sym_next != 0) do {
+ dist = s->sym_buf[sx++] & 0xff;
+ dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
+ lc = s->sym_buf[sx++];
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
@@ -1099,11 +1079,10 @@ local void compress_block(s, ltree, dtree)
}
} /* literal or match pair ? */
- /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
- Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
- "pendingBuf overflow");
+ /* Check that the overlay between pending_buf and sym_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
- } while (lx < s->last_lit);
+ } while (sx < s->sym_next);
send_code(s, END_BLOCK, ltree);
}
@@ -1112,9 +1091,9 @@ local void compress_block(s, ltree, dtree)
* Check if the data type is TEXT or BINARY, using the following algorithm:
* - TEXT if the two conditions below are satisfied:
* a) There are no non-portable control characters belonging to the
- * "black list" (0..6, 14..25, 28..31).
+ * "block list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
- * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
@@ -1124,19 +1103,19 @@ local void compress_block(s, ltree, dtree)
local int detect_data_type(s)
deflate_state *s;
{
- /* black_mask is the bit mask of black-listed bytes
+ /* block_mask is the bit mask of block-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
- unsigned long black_mask = 0xf3ffc07fUL;
+ unsigned long block_mask = 0xf3ffc07fUL;
int n;
- /* Check for non-textual ("black-listed") bytes. */
- for (n = 0; n <= 31; n++, black_mask >>= 1)
- if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ /* Check for non-textual ("block-listed") bytes. */
+ for (n = 0; n <= 31; n++, block_mask >>= 1)
+ if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
return Z_BINARY;
- /* Check for textual ("white-listed") bytes. */
+ /* Check for textual ("allow-listed") bytes. */
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|| s->dyn_ltree[13].Freq != 0)
return Z_TEXT;
@@ -1144,7 +1123,7 @@ local int detect_data_type(s)
if (s->dyn_ltree[n].Freq != 0)
return Z_TEXT;
- /* There are no "black-listed" or "white-listed" bytes:
+ /* There are no "block-listed" or "allow-listed" bytes:
* this stream either is empty or has tolerated ("gray-listed") bytes only.
*/
return Z_BINARY;
diff --git a/thirdparty/zlib/zlib.h b/thirdparty/zlib/zlib.h
index f09cdaf1e0..4a98e38bf3 100644
--- a/thirdparty/zlib/zlib.h
+++ b/thirdparty/zlib/zlib.h
@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library
- version 1.2.11, January 15th, 2017
+ version 1.2.12, March 11th, 2022
- Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler
+ Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -37,11 +37,11 @@
extern "C" {
#endif
-#define ZLIB_VERSION "1.2.11"
-#define ZLIB_VERNUM 0x12b0
+#define ZLIB_VERSION "1.2.12"
+#define ZLIB_VERNUM 0x12c0
#define ZLIB_VER_MAJOR 1
#define ZLIB_VER_MINOR 2
-#define ZLIB_VER_REVISION 11
+#define ZLIB_VER_REVISION 12
#define ZLIB_VER_SUBREVISION 0
/*
@@ -543,8 +543,7 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
int strategy));
This is another version of deflateInit with more compression options. The
- fields next_in, zalloc, zfree and opaque must be initialized before by the
- caller.
+ fields zalloc, zfree and opaque must be initialized before by the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
@@ -712,11 +711,12 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
used to switch between compression and straight copy of the input data, or
to switch to a different kind of input data requiring a different strategy.
If the compression approach (which is a function of the level) or the
- strategy is changed, and if any input has been consumed in a previous
- deflate() call, then the input available so far is compressed with the old
- level and strategy using deflate(strm, Z_BLOCK). There are three approaches
- for the compression levels 0, 1..3, and 4..9 respectively. The new level
- and strategy will take effect at the next call of deflate().
+ strategy is changed, and if there have been any deflate() calls since the
+ state was initialized or reset, then the input available so far is
+ compressed with the old level and strategy using deflate(strm, Z_BLOCK).
+ There are three approaches for the compression levels 0, 1..3, and 4..9
+ respectively. The new level and strategy will take effect at the next call
+ of deflate().
If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does
not have enough output space to complete, then the parameter change will not
@@ -865,9 +865,11 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a
CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see
- below), inflate() will not automatically decode concatenated gzip streams.
- inflate() will return Z_STREAM_END at the end of the gzip stream. The state
- would need to be reset to continue decoding a subsequent gzip stream.
+ below), inflate() will *not* automatically decode concatenated gzip members.
+ inflate() will return Z_STREAM_END at the end of the gzip member. The state
+ would need to be reset to continue decoding a subsequent gzip member. This
+ *must* be done if there is more data after a gzip member, in order for the
+ decompression to be compliant with the gzip standard (RFC 1952).
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
@@ -1302,14 +1304,14 @@ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */
/*
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
- Opens a gzip (.gz) file for reading or writing. The mode parameter is as
- in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
- a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
- compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
- for fixed code compression as in "wb9F". (See the description of
- deflateInit2 for more information about the strategy parameter.) 'T' will
- request transparent writing or appending with no compression and not using
- the gzip format.
+ Open the gzip (.gz) file at path for reading and decompressing, or
+ compressing and writing. The mode parameter is as in fopen ("rb" or "wb")
+ but can also include a compression level ("wb9") or a strategy: 'f' for
+ filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h",
+ 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression
+ as in "wb9F". (See the description of deflateInit2 for more information
+ about the strategy parameter.) 'T' will request transparent writing or
+ appending with no compression and not using the gzip format.
"a" can be used instead of "w" to request that the gzip stream that will
be written be appended to the file. "+" will result in an error, since
@@ -1339,9 +1341,9 @@ ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
/*
- gzdopen associates a gzFile with the file descriptor fd. File descriptors
- are obtained from calls like open, dup, creat, pipe or fileno (if the file
- has been previously opened with fopen). The mode parameter is as in gzopen.
+ Associate a gzFile with the file descriptor fd. File descriptors are
+ obtained from calls like open, dup, creat, pipe or fileno (if the file has
+ been previously opened with fopen). The mode parameter is as in gzopen.
The next call of gzclose on the returned gzFile will also close the file
descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
@@ -1362,13 +1364,13 @@ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
/*
- Set the internal buffer size used by this library's functions. The
- default buffer size is 8192 bytes. This function must be called after
- gzopen() or gzdopen(), and before any other calls that read or write the
- file. The buffer memory allocation is always deferred to the first read or
- write. Three times that size in buffer space is allocated. A larger buffer
- size of, for example, 64K or 128K bytes will noticeably increase the speed
- of decompression (reading).
+ Set the internal buffer size used by this library's functions for file to
+ size. The default buffer size is 8192 bytes. This function must be called
+ after gzopen() or gzdopen(), and before any other calls that read or write
+ the file. The buffer memory allocation is always deferred to the first read
+ or write. Three times that size in buffer space is allocated. A larger
+ buffer size of, for example, 64K or 128K bytes will noticeably increase the
+ speed of decompression (reading).
The new buffer size also affects the maximum length for gzprintf().
@@ -1378,9 +1380,9 @@ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
/*
- Dynamically update the compression level or strategy. See the description
- of deflateInit2 for the meaning of these parameters. Previously provided
- data is flushed before the parameter change.
+ Dynamically update the compression level and strategy for file. See the
+ description of deflateInit2 for the meaning of these parameters. Previously
+ provided data is flushed before applying the parameter changes.
gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not
opened for writing, Z_ERRNO if there is an error writing the flushed data,
@@ -1389,7 +1391,7 @@ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
/*
- Reads the given number of uncompressed bytes from the compressed file. If
+ Read and decompress up to len uncompressed bytes from file into buf. If
the input file is not in gzip format, gzread copies the given number of
bytes into the buffer directly from the file.
@@ -1420,11 +1422,11 @@ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
gzFile file));
/*
- Read up to nitems items of size size from file to buf, otherwise operating
- as gzread() does. This duplicates the interface of stdio's fread(), with
- size_t request and return types. If the library defines size_t, then
- z_size_t is identical to size_t. If not, then z_size_t is an unsigned
- integer type that can contain a pointer.
+ Read and decompress up to nitems items of size size from file into buf,
+ otherwise operating as gzread() does. This duplicates the interface of
+ stdio's fread(), with size_t request and return types. If the library
+ defines size_t, then z_size_t is identical to size_t. If not, then z_size_t
+ is an unsigned integer type that can contain a pointer.
gzfread() returns the number of full items read of size size, or zero if
the end of the file was reached and a full item could not be read, or if
@@ -1443,18 +1445,16 @@ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems,
file, reseting and retrying on end-of-file, when size is not 1.
*/
-ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
- voidpc buf, unsigned len));
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
/*
- Writes the given number of uncompressed bytes into the compressed file.
- gzwrite returns the number of uncompressed bytes written or 0 in case of
- error.
+ Compress and write the len uncompressed bytes at buf to file. gzwrite
+ returns the number of uncompressed bytes written or 0 in case of error.
*/
ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
z_size_t nitems, gzFile file));
/*
- gzfwrite() writes nitems items of size size from buf to file, duplicating
+ Compress and write nitems items of size size from buf to file, duplicating
the interface of stdio's fwrite(), with size_t request and return types. If
the library defines size_t, then z_size_t is identical to size_t. If not,
then z_size_t is an unsigned integer type that can contain a pointer.
@@ -1467,22 +1467,22 @@ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size,
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
/*
- Converts, formats, and writes the arguments to the compressed file under
- control of the format string, as in fprintf. gzprintf returns the number of
+ Convert, format, compress, and write the arguments (...) to file under
+ control of the string format, as in fprintf. gzprintf returns the number of
uncompressed bytes actually written, or a negative zlib error code in case
of error. The number of uncompressed bytes written is limited to 8191, or
one less than the buffer size given to gzbuffer(). The caller should assure
that this limit is not exceeded. If it is exceeded, then gzprintf() will
return an error (0) with nothing written. In this case, there may also be a
buffer overflow with unpredictable consequences, which is possible only if
- zlib was compiled with the insecure functions sprintf() or vsprintf()
+ zlib was compiled with the insecure functions sprintf() or vsprintf(),
because the secure snprintf() or vsnprintf() functions were not available.
This can be determined using zlibCompileFlags().
*/
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
/*
- Writes the given null-terminated string to the compressed file, excluding
+ Compress and write the given null-terminated string s to file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
@@ -1490,11 +1490,12 @@ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
/*
- Reads bytes from the compressed file until len-1 characters are read, or a
- newline character is read and transferred to buf, or an end-of-file
- condition is encountered. If any characters are read or if len == 1, the
- string is terminated with a null character. If no characters are read due
- to an end-of-file or len < 1, then the buffer is left untouched.
+ Read and decompress bytes from file into buf, until len-1 characters are
+ read, or until a newline character is read and transferred to buf, or an
+ end-of-file condition is encountered. If any characters are read or if len
+ is one, the string is terminated with a null character. If no characters
+ are read due to an end-of-file or len is less than one, then the buffer is
+ left untouched.
gzgets returns buf which is a null-terminated string, or it returns NULL
for end-of-file or in case of error. If there was an error, the contents at
@@ -1503,13 +1504,13 @@ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
/*
- Writes c, converted to an unsigned char, into the compressed file. gzputc
+ Compress and write c, converted to an unsigned char, into file. gzputc
returns the value that was written, or -1 in case of error.
*/
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
/*
- Reads one byte from the compressed file. gzgetc returns this byte or -1
+ Read and decompress one byte from file. gzgetc returns this byte or -1
in case of end of file or error. This is implemented as a macro for speed.
As such, it does not do all of the checking the other functions do. I.e.
it does not check to see if file is NULL, nor whether the structure file
@@ -1518,8 +1519,8 @@ ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
/*
- Push one character back onto the stream to be read as the first character
- on the next read. At least one character of push-back is allowed.
+ Push c back onto the stream for file to be read as the first character on
+ the next read. At least one character of push-back is always allowed.
gzungetc() returns the character pushed, or -1 on failure. gzungetc() will
fail if c is -1, and may fail if a character has been pushed but not read
yet. If gzungetc is used immediately after gzopen or gzdopen, at least the
@@ -1530,9 +1531,9 @@ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
/*
- Flushes all pending output into the compressed file. The parameter flush
- is as in the deflate() function. The return value is the zlib error number
- (see function gzerror below). gzflush is only permitted when writing.
+ Flush all pending output to file. The parameter flush is as in the
+ deflate() function. The return value is the zlib error number (see function
+ gzerror below). gzflush is only permitted when writing.
If the flush parameter is Z_FINISH, the remaining data is written and the
gzip stream is completed in the output. If gzwrite() is called again, a new
@@ -1547,8 +1548,8 @@ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
z_off_t offset, int whence));
- Sets the starting position for the next gzread or gzwrite on the given
- compressed file. The offset represents a number of bytes in the
+ Set the starting position to offset relative to whence for the next gzread
+ or gzwrite on file. The offset represents a number of bytes in the
uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
@@ -1565,18 +1566,18 @@ ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
/*
- Rewinds the given file. This function is supported only for reading.
+ Rewind file. This function is supported only for reading.
- gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+ gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET).
*/
/*
ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
- Returns the starting position for the next gzread or gzwrite on the given
- compressed file. This position represents a number of bytes in the
- uncompressed data stream, and is zero when starting, even if appending or
- reading a gzip stream from the middle of a file using gzdopen().
+ Return the starting position for the next gzread or gzwrite on file.
+ This position represents a number of bytes in the uncompressed data stream,
+ and is zero when starting, even if appending or reading a gzip stream from
+ the middle of a file using gzdopen().
gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
*/
@@ -1584,22 +1585,22 @@ ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file));
/*
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
- Returns the current offset in the file being read or written. This offset
- includes the count of bytes that precede the gzip stream, for example when
- appending or when using gzdopen() for reading. When reading, the offset
- does not include as yet unused buffered input. This information can be used
- for a progress indicator. On error, gzoffset() returns -1.
+ Return the current compressed (actual) read or write offset of file. This
+ offset includes the count of bytes that precede the gzip stream, for example
+ when appending or when using gzdopen() for reading. When reading, the
+ offset does not include as yet unused buffered input. This information can
+ be used for a progress indicator. On error, gzoffset() returns -1.
*/
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
/*
- Returns true (1) if the end-of-file indicator has been set while reading,
- false (0) otherwise. Note that the end-of-file indicator is set only if the
- read tried to go past the end of the input, but came up short. Therefore,
- just like feof(), gzeof() may return false even if there is no more data to
- read, in the event that the last read request was for the exact number of
- bytes remaining in the input file. This will happen if the input file size
- is an exact multiple of the buffer size.
+ Return true (1) if the end-of-file indicator for file has been set while
+ reading, false (0) otherwise. Note that the end-of-file indicator is set
+ only if the read tried to go past the end of the input, but came up short.
+ Therefore, just like feof(), gzeof() may return false even if there is no
+ more data to read, in the event that the last read request was for the exact
+ number of bytes remaining in the input file. This will happen if the input
+ file size is an exact multiple of the buffer size.
If gzeof() returns true, then the read functions will return no more data,
unless the end-of-file indicator is reset by gzclearerr() and the input file
@@ -1608,7 +1609,7 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
- Returns true (1) if file is being copied directly while reading, or false
+ Return true (1) if file is being copied directly while reading, or false
(0) if file is a gzip stream being decompressed.
If the input file is empty, gzdirect() will return true, since the input
@@ -1629,8 +1630,8 @@ ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/*
- Flushes all pending output if necessary, closes the compressed file and
- deallocates the (de)compression state. Note that once file is closed, you
+ Flush all pending output for file, if necessary, close file and
+ deallocate the (de)compression state. Note that once file is closed, you
cannot call gzerror with file, since its structures have been deallocated.
gzclose must not be called more than once on the same file, just as free
must not be called more than once on the same allocation.
@@ -1654,10 +1655,10 @@ ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
/*
- Returns the error message for the last error which occurred on the given
- compressed file. errnum is set to zlib error number. If an error occurred
- in the file system and not in the compression library, errnum is set to
- Z_ERRNO and the application may consult errno to get the exact error code.
+ Return the error message for the last error which occurred on file.
+ errnum is set to zlib error number. If an error occurred in the file system
+ and not in the compression library, errnum is set to Z_ERRNO and the
+ application may consult errno to get the exact error code.
The application must not modify the returned string. Future calls to
this function may invalidate the previously returned string. If file is
@@ -1670,7 +1671,7 @@ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
/*
- Clears the error and end-of-file flags for file. This is analogous to the
+ Clear the error and end-of-file flags for file. This is analogous to the
clearerr() function in stdio. This is useful for continuing to read a gzip
file that is being written concurrently.
*/
@@ -1688,8 +1689,9 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
/*
Update a running Adler-32 checksum with the bytes buf[0..len-1] and
- return the updated checksum. If buf is Z_NULL, this function returns the
- required initial value for the checksum.
+ return the updated checksum. An Adler-32 value is in the range of a 32-bit
+ unsigned integer. If buf is Z_NULL, this function returns the required
+ initial value for the checksum.
An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed
much faster.
@@ -1722,12 +1724,13 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
negative, the result has no meaning or utility.
*/
-ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
+ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/*
Update a running CRC-32 with the bytes buf[0..len-1] and return the
- updated CRC-32. If buf is Z_NULL, this function returns the required
- initial value for the crc. Pre- and post-conditioning (one's complement) is
- performed within this function so it shouldn't be done by the application.
+ updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer.
+ If buf is Z_NULL, this function returns the required initial value for the
+ crc. Pre- and post-conditioning (one's complement) is performed within this
+ function so it shouldn't be done by the application.
Usage example:
@@ -1739,7 +1742,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
if (crc != original_crc) error();
*/
-ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf,
+ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf,
z_size_t len));
/*
Same as crc32(), but with a size_t length.
@@ -1755,6 +1758,20 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
len2.
*/
+/*
+ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
+
+ Return the operator corresponding to length len2, to be used with
+ crc32_combine_op().
+*/
+
+ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
+/*
+ Give the same result as crc32_combine(), using op in place of len2. op is
+ is generated from len2 by crc32_combine_gen(). This will be faster than
+ crc32_combine() if the generated op is used more than once.
+*/
+
/* various hacks, don't look :) */
@@ -1842,6 +1859,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
#endif
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
@@ -1852,6 +1870,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
# define z_gzoffset z_gzoffset64
# define z_adler32_combine z_adler32_combine64
# define z_crc32_combine z_crc32_combine64
+# define z_crc32_combine_gen z_crc32_combine_gen64
# else
# define gzopen gzopen64
# define gzseek gzseek64
@@ -1859,6 +1878,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
# define gzoffset gzoffset64
# define adler32_combine adler32_combine64
# define crc32_combine crc32_combine64
+# define crc32_combine_gen crc32_combine_gen64
# endif
# ifndef Z_LARGE64
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
@@ -1867,6 +1887,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
# endif
#else
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
@@ -1875,12 +1896,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif
#else /* Z_SOLO */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+ ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif /* !Z_SOLO */
@@ -1893,7 +1916,7 @@ ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int));
ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp));
ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
-#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO)
+#if defined(_WIN32) && !defined(Z_SOLO)
ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path,
const char *mode));
#endif
diff --git a/thirdparty/zlib/zutil.c b/thirdparty/zlib/zutil.c
index a76c6b0c7e..dcab28a0d5 100644
--- a/thirdparty/zlib/zutil.c
+++ b/thirdparty/zlib/zutil.c
@@ -136,8 +136,8 @@ const char * ZEXPORT zError(err)
return ERR_MSG(err);
}
-#if defined(_WIN32_WCE)
- /* The Microsoft C Run-Time Library for Windows CE doesn't have
+#if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
+ /* The older Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used.
*/
diff --git a/thirdparty/zlib/zutil.h b/thirdparty/zlib/zutil.h
index b079ea6a80..d9a20ae1bf 100644
--- a/thirdparty/zlib/zutil.h
+++ b/thirdparty/zlib/zutil.h
@@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library
- * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler
+ * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -29,10 +29,6 @@
# include <stdlib.h>
#endif
-#ifdef Z_SOLO
- typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
-#endif
-
#ifndef local
# define local static
#endif
@@ -46,6 +42,17 @@ typedef unsigned short ush;
typedef ush FAR ushf;
typedef unsigned long ulg;
+#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
+# include <limits.h>
+# if (ULONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long
+# elif (ULLONG_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned long long
+# elif (UINT_MAX == 0xffffffffffffffff)
+# define Z_U8 unsigned
+# endif
+#endif
+
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */
@@ -170,10 +177,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */
-# ifndef _PTRDIFF_T_DEFINED
- typedef int ptrdiff_t;
-# define _PTRDIFF_T_DEFINED
-# endif
# else
# define fdopen(fd,type) _fdopen(fd,type)
# endif
diff --git a/thirdparty/zstd/common/bitstream.h b/thirdparty/zstd/common/bitstream.h
index 2e5a933ad3..84b6062ff3 100644
--- a/thirdparty/zstd/common/bitstream.h
+++ b/thirdparty/zstd/common/bitstream.h
@@ -143,10 +143,16 @@ MEM_STATIC unsigned BIT_highbit32 (U32 val)
{
# if defined(_MSC_VER) /* Visual */
# if STATIC_BMI2 == 1
- return _lzcnt_u32(val) ^ 31;
+ return _lzcnt_u32(val) ^ 31;
# else
- unsigned long r = 0;
- return _BitScanReverse(&r, val) ? (unsigned)r : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanReverse(&r, val);
+ return (unsigned)r;
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# endif
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* Use GCC Intrinsic */
return __builtin_clz (val) ^ 31;
@@ -293,22 +299,22 @@ MEM_STATIC size_t BIT_initDStream(BIT_DStream_t* bitD, const void* srcBuffer, si
switch(srcSize)
{
case 7: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[6]) << (sizeof(bitD->bitContainer)*8 - 16);
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case 6: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[5]) << (sizeof(bitD->bitContainer)*8 - 24);
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case 5: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[4]) << (sizeof(bitD->bitContainer)*8 - 32);
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case 4: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[3]) << 24;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case 3: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[2]) << 16;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case 2: bitD->bitContainer += (size_t)(((const BYTE*)(srcBuffer))[1]) << 8;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
default: break;
}
@@ -332,7 +338,16 @@ MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getMiddleBits(size_t bitContainer, U32 c
U32 const regMask = sizeof(bitContainer)*8 - 1;
/* if start > regMask, bitstream is corrupted, and result is undefined */
assert(nbBits < BIT_MASK_SIZE);
+ /* x86 transform & ((1 << nbBits) - 1) to bzhi instruction, it is better
+ * than accessing memory. When bmi2 instruction is not present, we consider
+ * such cpus old (pre-Haswell, 2013) and their performance is not of that
+ * importance.
+ */
+#if defined(__x86_64__) || defined(_M_X86)
+ return (bitContainer >> (start & regMask)) & ((((U64)1) << nbBits) - 1);
+#else
return (bitContainer >> (start & regMask)) & BIT_mask[nbBits];
+#endif
}
MEM_STATIC FORCE_INLINE_ATTR size_t BIT_getLowerBits(size_t bitContainer, U32 const nbBits)
diff --git a/thirdparty/zstd/common/compiler.h b/thirdparty/zstd/common/compiler.h
index a951d0adea..516930c01e 100644
--- a/thirdparty/zstd/common/compiler.h
+++ b/thirdparty/zstd/common/compiler.h
@@ -11,6 +11,8 @@
#ifndef ZSTD_COMPILER_H
#define ZSTD_COMPILER_H
+#include "portability_macros.h"
+
/*-*******************************************************
* Compiler specifics
*********************************************************/
@@ -40,7 +42,7 @@
/**
On MSVC qsort requires that functions passed into it use the __cdecl calling conversion(CC).
- This explictly marks such functions as __cdecl so that the code will still compile
+ This explicitly marks such functions as __cdecl so that the code will still compile
if a CC other than __cdecl has been made the default.
*/
#if defined(_MSC_VER)
@@ -92,29 +94,17 @@
/* target attribute */
-#ifndef __has_attribute
- #define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
-#endif
#if defined(__GNUC__) || defined(__ICCARM__)
# define TARGET_ATTRIBUTE(target) __attribute__((__target__(target)))
#else
# define TARGET_ATTRIBUTE(target)
#endif
-/* Enable runtime BMI2 dispatch based on the CPU.
- * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
+/* Target attribute for BMI2 dynamic dispatch.
+ * Enable lzcnt, bmi, and bmi2.
+ * We test for bmi1 & bmi2. lzcnt is included in bmi1.
*/
-#ifndef DYNAMIC_BMI2
- #if ((defined(__clang__) && __has_attribute(__target__)) \
- || (defined(__GNUC__) \
- && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
- && (defined(__x86_64__) || defined(_M_X86)) \
- && !defined(__BMI2__)
- # define DYNAMIC_BMI2 1
- #else
- # define DYNAMIC_BMI2 0
- #endif
-#endif
+#define BMI2_TARGET_ATTRIBUTE TARGET_ATTRIBUTE("lzcnt,bmi,bmi2")
/* prefetch
* can be disabled, by declaring NO_PREFETCH build macro */
@@ -150,8 +140,9 @@
}
/* vectorization
- * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax */
-#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__)
+ * older GCC (pre gcc-4.3 picked as the cutoff) uses a different syntax,
+ * and some compilers, like Intel ICC and MCST LCC, do not support it at all. */
+#if !defined(__INTEL_COMPILER) && !defined(__clang__) && defined(__GNUC__) && !defined(__LCC__)
# if (__GNUC__ == 4 && __GNUC_MINOR__ > 3) || (__GNUC__ >= 5)
# define DONT_VECTORIZE __attribute__((optimize("no-tree-vectorize")))
# else
@@ -197,25 +188,91 @@
#define STATIC_BMI2 0
#endif
-/* compat. with non-clang compilers */
-#ifndef __has_builtin
-# define __has_builtin(x) 0
+/* compile time determination of SIMD support */
+#if !defined(ZSTD_NO_INTRINSICS)
+# if defined(__SSE2__) || defined(_M_AMD64) || (defined (_M_IX86) && defined(_M_IX86_FP) && (_M_IX86_FP >= 2))
+# define ZSTD_ARCH_X86_SSE2
+# endif
+# if defined(__ARM_NEON) || defined(_M_ARM64)
+# define ZSTD_ARCH_ARM_NEON
+# endif
+#
+# if defined(ZSTD_ARCH_X86_SSE2)
+# include <emmintrin.h>
+# elif defined(ZSTD_ARCH_ARM_NEON)
+# include <arm_neon.h>
+# endif
#endif
-/* compat. with non-clang compilers */
-#ifndef __has_feature
-# define __has_feature(x) 0
+/* C-language Attributes are added in C23. */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
+# define ZSTD_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
+#else
+# define ZSTD_HAS_C_ATTRIBUTE(x) 0
#endif
-/* detects whether we are being compiled under msan */
-#ifndef ZSTD_MEMORY_SANITIZER
-# if __has_feature(memory_sanitizer)
-# define ZSTD_MEMORY_SANITIZER 1
-# else
-# define ZSTD_MEMORY_SANITIZER 0
-# endif
+/* Only use C++ attributes in C++. Some compilers report support for C++
+ * attributes when compiling with C.
+ */
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+# define ZSTD_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define ZSTD_HAS_CPP_ATTRIBUTE(x) 0
#endif
+/* Define ZSTD_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute.
+ * - C23: https://en.cppreference.com/w/c/language/attributes/fallthrough
+ * - CPP17: https://en.cppreference.com/w/cpp/language/attributes/fallthrough
+ * - Else: __attribute__((__fallthrough__))
+ */
+#ifndef ZSTD_FALLTHROUGH
+# if ZSTD_HAS_C_ATTRIBUTE(fallthrough)
+# define ZSTD_FALLTHROUGH [[fallthrough]]
+# elif ZSTD_HAS_CPP_ATTRIBUTE(fallthrough)
+# define ZSTD_FALLTHROUGH [[fallthrough]]
+# elif __has_attribute(__fallthrough__)
+/* Leading semicolon is to satisfy gcc-11 with -pedantic. Without the semicolon
+ * gcc complains about: a label can only be part of a statement and a declaration is not a statement.
+ */
+# define ZSTD_FALLTHROUGH ; __attribute__((__fallthrough__))
+# else
+# define ZSTD_FALLTHROUGH
+# endif
+#endif
+
+/*-**************************************************************
+* Alignment check
+*****************************************************************/
+
+/* this test was initially positioned in mem.h,
+ * but this file is removed (or replaced) for linux kernel
+ * so it's now hosted in compiler.h,
+ * which remains valid for both user & kernel spaces.
+ */
+
+#ifndef ZSTD_ALIGNOF
+# if defined(__GNUC__) || defined(_MSC_VER)
+/* covers gcc, clang & MSVC */
+/* note : this section must come first, before C11,
+ * due to a limitation in the kernel source generator */
+# define ZSTD_ALIGNOF(T) __alignof(T)
+
+# elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
+/* C11 support */
+# include <stdalign.h>
+# define ZSTD_ALIGNOF(T) alignof(T)
+
+# else
+/* No known support for alignof() - imperfect backup */
+# define ZSTD_ALIGNOF(T) (sizeof(void*) < sizeof(T) ? sizeof(void*) : sizeof(T))
+
+# endif
+#endif /* ZSTD_ALIGNOF */
+
+/*-**************************************************************
+* Sanitizer
+*****************************************************************/
+
#if ZSTD_MEMORY_SANITIZER
/* Not all platforms that support msan provide sanitizers/msan_interface.h.
* We therefore declare the functions we need ourselves, rather than trying to
@@ -237,17 +294,6 @@ void __msan_poison(const volatile void *a, size_t size);
intptr_t __msan_test_shadow(const volatile void *x, size_t size);
#endif
-/* detects whether we are being compiled under asan */
-#ifndef ZSTD_ADDRESS_SANITIZER
-# if __has_feature(address_sanitizer)
-# define ZSTD_ADDRESS_SANITIZER 1
-# elif defined(__SANITIZE_ADDRESS__)
-# define ZSTD_ADDRESS_SANITIZER 1
-# else
-# define ZSTD_ADDRESS_SANITIZER 0
-# endif
-#endif
-
#if ZSTD_ADDRESS_SANITIZER
/* Not all platforms that support asan provide sanitizers/asan_interface.h.
* We therefore declare the functions we need ourselves, rather than trying to
diff --git a/thirdparty/zstd/common/entropy_common.c b/thirdparty/zstd/common/entropy_common.c
index 41cd69566b..4229b40c5e 100644
--- a/thirdparty/zstd/common/entropy_common.c
+++ b/thirdparty/zstd/common/entropy_common.c
@@ -43,8 +43,14 @@ static U32 FSE_ctz(U32 val)
assert(val != 0);
{
# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- return _BitScanForward(&r, val) ? (unsigned)r : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward(&r, val);
+ return (unsigned)r;
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
return __builtin_ctz(val);
# elif defined(__ICCARM__) /* IAR Intrinsic */
@@ -217,7 +223,7 @@ static size_t FSE_readNCount_body_default(
}
#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static size_t FSE_readNCount_body_bmi2(
+BMI2_TARGET_ATTRIBUTE static size_t FSE_readNCount_body_bmi2(
short* normalizedCounter, unsigned* maxSVPtr, unsigned* tableLogPtr,
const void* headerBuffer, size_t hbSize)
{
@@ -299,7 +305,7 @@ HUF_readStats_body(BYTE* huffWeight, size_t hwSize, U32* rankStats,
ZSTD_memset(rankStats, 0, (HUF_TABLELOG_MAX + 1) * sizeof(U32));
weightTotal = 0;
{ U32 n; for (n=0; n<oSize; n++) {
- if (huffWeight[n] >= HUF_TABLELOG_MAX) return ERROR(corruption_detected);
+ if (huffWeight[n] > HUF_TABLELOG_MAX) return ERROR(corruption_detected);
rankStats[huffWeight[n]]++;
weightTotal += (1 << huffWeight[n]) >> 1;
} }
@@ -337,7 +343,7 @@ static size_t HUF_readStats_body_default(BYTE* huffWeight, size_t hwSize, U32* r
}
#if DYNAMIC_BMI2
-static TARGET_ATTRIBUTE("bmi2") size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
+static BMI2_TARGET_ATTRIBUTE size_t HUF_readStats_body_bmi2(BYTE* huffWeight, size_t hwSize, U32* rankStats,
U32* nbSymbolsPtr, U32* tableLogPtr,
const void* src, size_t srcSize,
void* workSpace, size_t wkspSize)
diff --git a/thirdparty/zstd/common/error_private.h b/thirdparty/zstd/common/error_private.h
index 6d8b9f7763..007d81066a 100644
--- a/thirdparty/zstd/common/error_private.h
+++ b/thirdparty/zstd/common/error_private.h
@@ -22,6 +22,8 @@ extern "C" {
* Dependencies
******************************************/
#include "../zstd_errors.h" /* enum list */
+#include "compiler.h"
+#include "debug.h"
#include "zstd_deps.h" /* size_t */
@@ -73,6 +75,83 @@ ERR_STATIC const char* ERR_getErrorName(size_t code)
return ERR_getErrorString(ERR_getErrorCode(code));
}
+/**
+ * Ignore: this is an internal helper.
+ *
+ * This is a helper function to help force C99-correctness during compilation.
+ * Under strict compilation modes, variadic macro arguments can't be empty.
+ * However, variadic function arguments can be. Using a function therefore lets
+ * us statically check that at least one (string) argument was passed,
+ * independent of the compilation flags.
+ */
+static INLINE_KEYWORD UNUSED_ATTR
+void _force_has_format_string(const char *format, ...) {
+ (void)format;
+}
+
+/**
+ * Ignore: this is an internal helper.
+ *
+ * We want to force this function invocation to be syntactically correct, but
+ * we don't want to force runtime evaluation of its arguments.
+ */
+#define _FORCE_HAS_FORMAT_STRING(...) \
+ if (0) { \
+ _force_has_format_string(__VA_ARGS__); \
+ }
+
+#define ERR_QUOTE(str) #str
+
+/**
+ * Return the specified error if the condition evaluates to true.
+ *
+ * In debug modes, prints additional information.
+ * In order to do that (particularly, printing the conditional that failed),
+ * this can't just wrap RETURN_ERROR().
+ */
+#define RETURN_ERROR_IF(cond, err, ...) \
+ if (cond) { \
+ RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
+ __FILE__, __LINE__, ERR_QUOTE(cond), ERR_QUOTE(ERROR(err))); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ }
+
+/**
+ * Unconditionally return the specified error.
+ *
+ * In debug modes, prints additional information.
+ */
+#define RETURN_ERROR(err, ...) \
+ do { \
+ RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
+ __FILE__, __LINE__, ERR_QUOTE(ERROR(err))); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return ERROR(err); \
+ } while(0);
+
+/**
+ * If the provided expression evaluates to an error code, returns that error code.
+ *
+ * In debug modes, prints additional information.
+ */
+#define FORWARD_IF_ERROR(err, ...) \
+ do { \
+ size_t const err_code = (err); \
+ if (ERR_isError(err_code)) { \
+ RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
+ __FILE__, __LINE__, ERR_QUOTE(err), ERR_getErrorName(err_code)); \
+ _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
+ RAWLOG(3, ": " __VA_ARGS__); \
+ RAWLOG(3, "\n"); \
+ return err_code; \
+ } \
+ } while(0);
+
#if defined (__cplusplus)
}
#endif
diff --git a/thirdparty/zstd/common/fse.h b/thirdparty/zstd/common/fse.h
index 19dd4febcd..714bfd3e7f 100644
--- a/thirdparty/zstd/common/fse.h
+++ b/thirdparty/zstd/common/fse.h
@@ -336,8 +336,9 @@ size_t FSE_buildCTable_rle (FSE_CTable* ct, unsigned char symbolValue);
/* FSE_buildCTable_wksp() :
* Same as FSE_buildCTable(), but using an externally allocated scratch buffer (`workSpace`).
* `wkspSize` must be >= `FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog)` of `unsigned`.
+ * See FSE_buildCTable_wksp() for breakdown of workspace usage.
*/
-#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (maxSymbolValue + 2 + (1ull << (tableLog - 2)))
+#define FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog) (((maxSymbolValue + 2) + (1ull << (tableLog)))/2 + sizeof(U64)/sizeof(U32) /* additional 8 bytes for potential table overwrite */)
#define FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) (sizeof(unsigned) * FSE_BUILD_CTABLE_WORKSPACE_SIZE_U32(maxSymbolValue, tableLog))
size_t FSE_buildCTable_wksp(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize);
diff --git a/thirdparty/zstd/common/fse_decompress.c b/thirdparty/zstd/common/fse_decompress.c
index f4ff58fa0a..a5a358015f 100644
--- a/thirdparty/zstd/common/fse_decompress.c
+++ b/thirdparty/zstd/common/fse_decompress.c
@@ -365,7 +365,7 @@ static size_t FSE_decompress_wksp_body_default(void* dst, size_t dstCapacity, co
}
#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
+BMI2_TARGET_ATTRIBUTE static size_t FSE_decompress_wksp_body_bmi2(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, unsigned maxLog, void* workSpace, size_t wkspSize)
{
return FSE_decompress_wksp_body(dst, dstCapacity, cSrc, cSrcSize, maxLog, workSpace, wkspSize, 1);
}
diff --git a/thirdparty/zstd/common/huf.h b/thirdparty/zstd/common/huf.h
index 3d47ced030..85518481ec 100644
--- a/thirdparty/zstd/common/huf.h
+++ b/thirdparty/zstd/common/huf.h
@@ -89,9 +89,9 @@ HUF_PUBLIC_API size_t HUF_compress2 (void* dst, size_t dstCapacity,
/** HUF_compress4X_wksp() :
* Same as HUF_compress2(), but uses externally allocated `workSpace`.
- * `workspace` must have minimum alignment of 4, and be at least as large as HUF_WORKSPACE_SIZE */
-#define HUF_WORKSPACE_SIZE ((6 << 10) + 256)
-#define HUF_WORKSPACE_SIZE_U32 (HUF_WORKSPACE_SIZE / sizeof(U32))
+ * `workspace` must be at least as large as HUF_WORKSPACE_SIZE */
+#define HUF_WORKSPACE_SIZE ((8 << 10) + 512 /* sorting scratch space */)
+#define HUF_WORKSPACE_SIZE_U64 (HUF_WORKSPACE_SIZE / sizeof(U64))
HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned tableLog,
@@ -116,11 +116,11 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
/* *** Constants *** */
-#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_ABSOLUTEMAX_TABLELOG */
+#define HUF_TABLELOG_MAX 12 /* max runtime value of tableLog (due to static allocation); can be modified up to HUF_TABLELOG_ABSOLUTEMAX */
#define HUF_TABLELOG_DEFAULT 11 /* default tableLog value when none specified */
#define HUF_SYMBOLVALUE_MAX 255
-#define HUF_TABLELOG_ABSOLUTEMAX 15 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
+#define HUF_TABLELOG_ABSOLUTEMAX 12 /* absolute limit of HUF_MAX_TABLELOG. Beyond that value, code does not work */
#if (HUF_TABLELOG_MAX > HUF_TABLELOG_ABSOLUTEMAX)
# error "HUF_TABLELOG_MAX is too large !"
#endif
@@ -136,15 +136,11 @@ HUF_PUBLIC_API size_t HUF_compress4X_wksp (void* dst, size_t dstCapacity,
/* static allocation of HUF's Compression Table */
/* this is a private definition, just exposed for allocation and strict aliasing purpose. never EVER access its members directly */
-struct HUF_CElt_s {
- U16 val;
- BYTE nbBits;
-}; /* typedef'd to HUF_CElt */
-typedef struct HUF_CElt_s HUF_CElt; /* consider it an incomplete type */
-#define HUF_CTABLE_SIZE_U32(maxSymbolValue) ((maxSymbolValue)+1) /* Use tables of U32, for proper alignment */
-#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_U32(maxSymbolValue) * sizeof(U32))
+typedef size_t HUF_CElt; /* consider it an incomplete type */
+#define HUF_CTABLE_SIZE_ST(maxSymbolValue) ((maxSymbolValue)+2) /* Use tables of size_t, for proper alignment */
+#define HUF_CTABLE_SIZE(maxSymbolValue) (HUF_CTABLE_SIZE_ST(maxSymbolValue) * sizeof(size_t))
#define HUF_CREATE_STATIC_CTABLE(name, maxSymbolValue) \
- HUF_CElt name[HUF_CTABLE_SIZE_U32(maxSymbolValue)] /* no final ; */
+ HUF_CElt name[HUF_CTABLE_SIZE_ST(maxSymbolValue)] /* no final ; */
/* static allocation of HUF's DTable */
typedef U32 HUF_DTable;
@@ -194,6 +190,7 @@ size_t HUF_buildCTable (HUF_CElt* CTable, const unsigned* count, unsigned maxSym
size_t HUF_writeCTable (void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog);
size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize, const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog, void* workspace, size_t workspaceSize);
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
+size_t HUF_compress4X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue);
@@ -206,12 +203,13 @@ typedef enum {
* Same as HUF_compress4X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
* If it uses hufTable it does not modify hufTable or repeat.
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
- * If preferRepeat then the old table will always be used if valid. */
+ * If preferRepeat then the old table will always be used if valid.
+ * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
size_t HUF_compress4X_repeat(void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned tableLog,
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2, unsigned suspectUncompressible);
/** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
@@ -249,11 +247,10 @@ size_t HUF_readStats_wksp(BYTE* huffWeight, size_t hwSize,
* Loading a CTable saved with HUF_writeCTable() */
size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void* src, size_t srcSize, unsigned *hasZeroWeights);
-/** HUF_getNbBits() :
+/** HUF_getNbBitsFromCTable() :
* Read nbBits from CTable symbolTable, for symbol `symbolValue` presumed <= HUF_SYMBOLVALUE_MAX
- * Note 1 : is not inlined, as HUF_CElt definition is private
- * Note 2 : const void* used, so that it can provide a statically allocated table as argument (which uses type U32) */
-U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue);
+ * Note 1 : is not inlined, as HUF_CElt definition is private */
+U32 HUF_getNbBitsFromCTable(const HUF_CElt* symbolTable, U32 symbolValue);
/*
* HUF_decompress() does the following:
@@ -305,18 +302,20 @@ size_t HUF_decompress4X2_usingDTable(void* dst, size_t maxDstSize, const void* c
/* ====================== */
size_t HUF_compress1X (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog);
-size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U32 unsigned */
+size_t HUF_compress1X_wksp (void* dst, size_t dstSize, const void* src, size_t srcSize, unsigned maxSymbolValue, unsigned tableLog, void* workSpace, size_t wkspSize); /**< `workSpace` must be a table of at least HUF_WORKSPACE_SIZE_U64 U64 */
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable);
+size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2);
/** HUF_compress1X_repeat() :
* Same as HUF_compress1X_wksp(), but considers using hufTable if *repeat != HUF_repeat_none.
* If it uses hufTable it does not modify hufTable or repeat.
* If it doesn't, it sets *repeat = HUF_repeat_none, and it sets hufTable to the table used.
- * If preferRepeat then the old table will always be used if valid. */
+ * If preferRepeat then the old table will always be used if valid.
+ * If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
size_t HUF_compress1X_repeat(void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned tableLog,
void* workSpace, size_t wkspSize, /**< `workSpace` must be aligned on 4-bytes boundaries, `wkspSize` must be >= HUF_WORKSPACE_SIZE */
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2);
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2, unsigned suspectUncompressible);
size_t HUF_decompress1X1 (void* dst, size_t dstSize, const void* cSrc, size_t cSrcSize); /* single-symbol decoder */
#ifndef HUF_FORCE_DECOMPRESS_X1
@@ -354,6 +353,9 @@ size_t HUF_decompress4X_hufOnly_wksp_bmi2(HUF_DTable* dctx, void* dst, size_t ds
#ifndef HUF_FORCE_DECOMPRESS_X2
size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
#endif
+#ifndef HUF_FORCE_DECOMPRESS_X1
+size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t srcSize, void* workSpace, size_t wkspSize, int bmi2);
+#endif
#endif /* HUF_STATIC_LINKING_ONLY */
diff --git a/thirdparty/zstd/common/mem.h b/thirdparty/zstd/common/mem.h
index 9f3b81ab9d..85581c3847 100644
--- a/thirdparty/zstd/common/mem.h
+++ b/thirdparty/zstd/common/mem.h
@@ -51,6 +51,8 @@ extern "C" {
# include <stdint.h> /* intptr_t */
# endif
typedef uint8_t BYTE;
+ typedef uint8_t U8;
+ typedef int8_t S8;
typedef uint16_t U16;
typedef int16_t S16;
typedef uint32_t U32;
@@ -63,6 +65,8 @@ extern "C" {
# error "this implementation requires char to be exactly 8-bit type"
#endif
typedef unsigned char BYTE;
+ typedef unsigned char U8;
+ typedef signed char S8;
#if USHRT_MAX != 65535
# error "this implementation requires short to be exactly 16-bit type"
#endif
@@ -153,8 +157,22 @@ MEM_STATIC unsigned MEM_64bits(void) { return sizeof(size_t)==8; }
MEM_STATIC unsigned MEM_isLittleEndian(void)
{
+#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+ return 1;
+#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+ return 0;
+#elif defined(__clang__) && __LITTLE_ENDIAN__
+ return 1;
+#elif defined(__clang__) && __BIG_ENDIAN__
+ return 0;
+#elif defined(_MSC_VER) && (_M_AMD64 || _M_IX86)
+ return 1;
+#elif defined(__DMC__) && defined(_M_IX86)
+ return 1;
+#else
const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
return one.c[0];
+#endif
}
#if defined(MEM_FORCE_MEMORY_ACCESS) && (MEM_FORCE_MEMORY_ACCESS==2)
diff --git a/thirdparty/zstd/common/pool.c b/thirdparty/zstd/common/pool.c
index ea70b8b65a..2e37cdd73c 100644
--- a/thirdparty/zstd/common/pool.c
+++ b/thirdparty/zstd/common/pool.c
@@ -86,7 +86,7 @@ static void* POOL_thread(void* opaque) {
{ POOL_job const job = ctx->queue[ctx->queueHead];
ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize;
ctx->numThreadsBusy++;
- ctx->queueEmpty = ctx->queueHead == ctx->queueTail;
+ ctx->queueEmpty = (ctx->queueHead == ctx->queueTail);
/* Unlock the mutex, signal a pusher, and run the job */
ZSTD_pthread_cond_signal(&ctx->queuePushCond);
ZSTD_pthread_mutex_unlock(&ctx->queueMutex);
@@ -105,6 +105,7 @@ static void* POOL_thread(void* opaque) {
assert(0); /* Unreachable */
}
+/* ZSTD_createThreadPool() : public access point */
POOL_ctx* ZSTD_createThreadPool(size_t numThreads) {
return POOL_create (numThreads, 0);
}
@@ -114,7 +115,8 @@ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
}
POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize,
- ZSTD_customMem customMem) {
+ ZSTD_customMem customMem)
+{
POOL_ctx* ctx;
/* Check parameters */
if (!numThreads) { return NULL; }
@@ -192,7 +194,7 @@ void ZSTD_freeThreadPool (ZSTD_threadPool* pool) {
POOL_free (pool);
}
-size_t POOL_sizeof(POOL_ctx *ctx) {
+size_t POOL_sizeof(const POOL_ctx* ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
return sizeof(*ctx)
+ ctx->queueSize * sizeof(POOL_job)
@@ -257,7 +259,8 @@ static int isQueueFull(POOL_ctx const* ctx) {
}
-static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
+static void
+POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque)
{
POOL_job const job = {function, opaque};
assert(ctx != NULL);
@@ -313,7 +316,9 @@ POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) {
return POOL_create_advanced(numThreads, queueSize, ZSTD_defaultCMem);
}
-POOL_ctx* POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem) {
+POOL_ctx*
+POOL_create_advanced(size_t numThreads, size_t queueSize, ZSTD_customMem customMem)
+{
(void)numThreads;
(void)queueSize;
(void)customMem;
@@ -341,7 +346,7 @@ int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) {
return 1;
}
-size_t POOL_sizeof(POOL_ctx* ctx) {
+size_t POOL_sizeof(const POOL_ctx* ctx) {
if (ctx==NULL) return 0; /* supports sizeof NULL */
assert(ctx == &g_poolCtx);
return sizeof(*ctx);
diff --git a/thirdparty/zstd/common/pool.h b/thirdparty/zstd/common/pool.h
index e18aa0708f..0ebde1805d 100644
--- a/thirdparty/zstd/common/pool.h
+++ b/thirdparty/zstd/common/pool.h
@@ -53,7 +53,7 @@ int POOL_resize(POOL_ctx* ctx, size_t numThreads);
* @return threadpool memory usage
* note : compatible with NULL (returns 0 in this case)
*/
-size_t POOL_sizeof(POOL_ctx* ctx);
+size_t POOL_sizeof(const POOL_ctx* ctx);
/*! POOL_function :
* The function type that can be added to a thread pool.
@@ -70,7 +70,7 @@ void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque);
/*! POOL_tryAdd() :
- * Add the job `function(opaque)` to thread pool _if_ a worker is available.
+ * Add the job `function(opaque)` to thread pool _if_ a queue slot is available.
* Returns immediately even if not (does not block).
* @return : 1 if successful, 0 if not.
*/
diff --git a/thirdparty/zstd/common/portability_macros.h b/thirdparty/zstd/common/portability_macros.h
new file mode 100644
index 0000000000..2143817f57
--- /dev/null
+++ b/thirdparty/zstd/common/portability_macros.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_PORTABILITY_MACROS_H
+#define ZSTD_PORTABILITY_MACROS_H
+
+/**
+ * This header file contains macro defintions to support portability.
+ * This header is shared between C and ASM code, so it MUST only
+ * contain macro definitions. It MUST not contain any C code.
+ *
+ * This header ONLY defines macros to detect platforms/feature support.
+ *
+ */
+
+
+/* compat. with non-clang compilers */
+#ifndef __has_attribute
+ #define __has_attribute(x) 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+
+/* compat. with non-clang compilers */
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+
+/* detects whether we are being compiled under msan */
+#ifndef ZSTD_MEMORY_SANITIZER
+# if __has_feature(memory_sanitizer)
+# define ZSTD_MEMORY_SANITIZER 1
+# else
+# define ZSTD_MEMORY_SANITIZER 0
+# endif
+#endif
+
+/* detects whether we are being compiled under asan */
+#ifndef ZSTD_ADDRESS_SANITIZER
+# if __has_feature(address_sanitizer)
+# define ZSTD_ADDRESS_SANITIZER 1
+# elif defined(__SANITIZE_ADDRESS__)
+# define ZSTD_ADDRESS_SANITIZER 1
+# else
+# define ZSTD_ADDRESS_SANITIZER 0
+# endif
+#endif
+
+/* detects whether we are being compiled under dfsan */
+#ifndef ZSTD_DATAFLOW_SANITIZER
+# if __has_feature(dataflow_sanitizer)
+# define ZSTD_DATAFLOW_SANITIZER 1
+# else
+# define ZSTD_DATAFLOW_SANITIZER 0
+# endif
+#endif
+
+/* Mark the internal assembly functions as hidden */
+#ifdef __ELF__
+# define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func
+#else
+# define ZSTD_HIDE_ASM_FUNCTION(func)
+#endif
+
+/* Enable runtime BMI2 dispatch based on the CPU.
+ * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
+ */
+#ifndef DYNAMIC_BMI2
+ #if ((defined(__clang__) && __has_attribute(__target__)) \
+ || (defined(__GNUC__) \
+ && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
+ && (defined(__x86_64__) || defined(_M_X64)) \
+ && !defined(__BMI2__)
+ # define DYNAMIC_BMI2 1
+ #else
+ # define DYNAMIC_BMI2 0
+ #endif
+#endif
+
+/**
+ * Only enable assembly for GNUC comptabile compilers,
+ * because other platforms may not support GAS assembly syntax.
+ *
+ * Only enable assembly for Linux / MacOS, other platforms may
+ * work, but they haven't been tested. This could likely be
+ * extended to BSD systems.
+ *
+ * Disable assembly when MSAN is enabled, because MSAN requires
+ * 100% of code to be instrumented to work.
+ */
+#if defined(__GNUC__)
+# if defined(__linux__) || defined(__linux) || defined(__APPLE__)
+# if ZSTD_MEMORY_SANITIZER
+# define ZSTD_ASM_SUPPORTED 0
+# elif ZSTD_DATAFLOW_SANITIZER
+# define ZSTD_ASM_SUPPORTED 0
+# else
+# define ZSTD_ASM_SUPPORTED 1
+# endif
+# else
+# define ZSTD_ASM_SUPPORTED 0
+# endif
+#else
+# define ZSTD_ASM_SUPPORTED 0
+#endif
+
+/**
+ * Determines whether we should enable assembly for x86-64
+ * with BMI2.
+ *
+ * Enable if all of the following conditions hold:
+ * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
+ * - Assembly is supported
+ * - We are compiling for x86-64 and either:
+ * - DYNAMIC_BMI2 is enabled
+ * - BMI2 is supported at compile time
+ */
+#if !defined(ZSTD_DISABLE_ASM) && \
+ ZSTD_ASM_SUPPORTED && \
+ defined(__x86_64__) && \
+ (DYNAMIC_BMI2 || defined(__BMI2__))
+# define ZSTD_ENABLE_ASM_X86_64_BMI2 1
+#else
+# define ZSTD_ENABLE_ASM_X86_64_BMI2 0
+#endif
+
+#endif /* ZSTD_PORTABILITY_MACROS_H */
diff --git a/thirdparty/zstd/common/xxhash.c b/thirdparty/zstd/common/xxhash.c
index 926b33604e..d49497cf1c 100644
--- a/thirdparty/zstd/common/xxhash.c
+++ b/thirdparty/zstd/common/xxhash.c
@@ -5,7 +5,7 @@
* You can contact the author at :
* - xxHash homepage: http://www.xxhash.com
* - xxHash source repository : https://github.com/Cyan4973/xxHash
- *
+ *
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
@@ -13,812 +13,12 @@
*/
-/* *************************************
-* Tuning parameters
-***************************************/
-/*!XXH_FORCE_MEMORY_ACCESS :
- * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
- * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
- * The below switch allow to select different access method for improved performance.
- * Method 0 (default) : use `memcpy()`. Safe and portable.
- * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
- * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
- * Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
- * It can generate buggy code on targets which do not support unaligned memory accesses.
- * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
- * See http://stackoverflow.com/a/32095106/646947 for details.
- * Prefer these methods in priority order (0 > 1 > 2)
- */
-#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
-# if (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
- (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
- defined(__ICCARM__)
-# define XXH_FORCE_MEMORY_ACCESS 1
-# endif
-#endif
-
-/*!XXH_ACCEPT_NULL_INPUT_POINTER :
- * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
- * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
- * By default, this option is disabled. To enable it, uncomment below define :
- */
-/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
-
-/*!XXH_FORCE_NATIVE_FORMAT :
- * By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
- * Results are therefore identical for little-endian and big-endian CPU.
- * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
- * Should endian-independence be of no importance for your application, you may set the #define below to 1,
- * to improve speed for Big-endian CPU.
- * This option has no impact on Little_Endian CPU.
- */
-#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */
-# define XXH_FORCE_NATIVE_FORMAT 0
-#endif
-/*!XXH_FORCE_ALIGN_CHECK :
- * This is a minor performance trick, only useful with lots of very small keys.
- * It means : check for aligned/unaligned input.
- * The check costs one initial branch per hash; set to 0 when the input data
- * is guaranteed to be aligned.
+/*
+ * xxhash.c instantiates functions defined in xxhash.h
*/
-#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
-# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
-# define XXH_FORCE_ALIGN_CHECK 0
-# else
-# define XXH_FORCE_ALIGN_CHECK 1
-# endif
-#endif
-
-/* *************************************
-* Includes & Memory related functions
-***************************************/
-/* Modify the local functions below should you wish to use some other memory routines */
-/* for ZSTD_malloc(), ZSTD_free() */
-#define ZSTD_DEPS_NEED_MALLOC
-#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */
-static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); }
-static void XXH_free (void* p) { ZSTD_free(p); }
-static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); }
+#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */
+#define XXH_IMPLEMENTATION /* access definitions */
-#ifndef XXH_STATIC_LINKING_ONLY
-# define XXH_STATIC_LINKING_ONLY
-#endif
#include "xxhash.h"
-
-
-/* *************************************
-* Compiler Specific Options
-***************************************/
-#include "compiler.h"
-
-
-/* *************************************
-* Basic Types
-***************************************/
-#include "mem.h" /* BYTE, U32, U64, size_t */
-
-#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
-
-/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
-static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
-static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
-
-#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
-
-/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
-/* currently only defined for gcc and icc */
-typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;
-
-static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
-static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
-
-#else
-
-/* portable and safe solution. Generally efficient.
- * see : http://stackoverflow.com/a/32095106/646947
- */
-
-static U32 XXH_read32(const void* memPtr)
-{
- U32 val;
- ZSTD_memcpy(&val, memPtr, sizeof(val));
- return val;
-}
-
-static U64 XXH_read64(const void* memPtr)
-{
- U64 val;
- ZSTD_memcpy(&val, memPtr, sizeof(val));
- return val;
-}
-
-#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
-
-
-/* ****************************************
-* Compiler-specific Functions and Macros
-******************************************/
-#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
-
-/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
-#if defined(_MSC_VER)
-# define XXH_rotl32(x,r) _rotl(x,r)
-# define XXH_rotl64(x,r) _rotl64(x,r)
-#else
-#if defined(__ICCARM__)
-# include <intrinsics.h>
-# define XXH_rotl32(x,r) __ROR(x,(32 - r))
-#else
-# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
-#endif
-# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
-#endif
-
-#if defined(_MSC_VER) /* Visual Studio */
-# define XXH_swap32 _byteswap_ulong
-# define XXH_swap64 _byteswap_uint64
-#elif GCC_VERSION >= 403
-# define XXH_swap32 __builtin_bswap32
-# define XXH_swap64 __builtin_bswap64
-#else
-static U32 XXH_swap32 (U32 x)
-{
- return ((x << 24) & 0xff000000 ) |
- ((x << 8) & 0x00ff0000 ) |
- ((x >> 8) & 0x0000ff00 ) |
- ((x >> 24) & 0x000000ff );
-}
-static U64 XXH_swap64 (U64 x)
-{
- return ((x << 56) & 0xff00000000000000ULL) |
- ((x << 40) & 0x00ff000000000000ULL) |
- ((x << 24) & 0x0000ff0000000000ULL) |
- ((x << 8) & 0x000000ff00000000ULL) |
- ((x >> 8) & 0x00000000ff000000ULL) |
- ((x >> 24) & 0x0000000000ff0000ULL) |
- ((x >> 40) & 0x000000000000ff00ULL) |
- ((x >> 56) & 0x00000000000000ffULL);
-}
-#endif
-
-
-/* *************************************
-* Architecture Macros
-***************************************/
-typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
-
-/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
-#ifndef XXH_CPU_LITTLE_ENDIAN
- static const int g_one = 1;
-# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one))
-#endif
-
-
-/* ***************************
-* Memory reads
-*****************************/
-typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
-
-FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
-{
- if (align==XXH_unaligned)
- return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
- else
- return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
-}
-
-FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
-{
- return XXH_readLE32_align(ptr, endian, XXH_unaligned);
-}
-
-static U32 XXH_readBE32(const void* ptr)
-{
- return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
-}
-
-FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
-{
- if (align==XXH_unaligned)
- return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
- else
- return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
-}
-
-FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
-{
- return XXH_readLE64_align(ptr, endian, XXH_unaligned);
-}
-
-static U64 XXH_readBE64(const void* ptr)
-{
- return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
-}
-
-
-/* *************************************
-* Macros
-***************************************/
-#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
-
-
-/* *************************************
-* Constants
-***************************************/
-static const U32 PRIME32_1 = 2654435761U;
-static const U32 PRIME32_2 = 2246822519U;
-static const U32 PRIME32_3 = 3266489917U;
-static const U32 PRIME32_4 = 668265263U;
-static const U32 PRIME32_5 = 374761393U;
-
-static const U64 PRIME64_1 = 11400714785074694791ULL;
-static const U64 PRIME64_2 = 14029467366897019727ULL;
-static const U64 PRIME64_3 = 1609587929392839161ULL;
-static const U64 PRIME64_4 = 9650029242287828579ULL;
-static const U64 PRIME64_5 = 2870177450012600261ULL;
-
-XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
-
-
-/* **************************
-* Utils
-****************************/
-XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)
-{
- ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
-}
-
-XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)
-{
- ZSTD_memcpy(dstState, srcState, sizeof(*dstState));
-}
-
-
-/* ***************************
-* Simple Hash Functions
-*****************************/
-
-static U32 XXH32_round(U32 seed, U32 input)
-{
- seed += input * PRIME32_2;
- seed = XXH_rotl32(seed, 13);
- seed *= PRIME32_1;
- return seed;
-}
-
-FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
-{
- const BYTE* p = (const BYTE*)input;
- const BYTE* bEnd = p + len;
- U32 h32;
-#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
- if (p==NULL) {
- len=0;
- bEnd=p=(const BYTE*)(size_t)16;
- }
-#endif
-
- if (len>=16) {
- const BYTE* const limit = bEnd - 16;
- U32 v1 = seed + PRIME32_1 + PRIME32_2;
- U32 v2 = seed + PRIME32_2;
- U32 v3 = seed + 0;
- U32 v4 = seed - PRIME32_1;
-
- do {
- v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
- v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
- v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
- v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
- } while (p<=limit);
-
- h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
- } else {
- h32 = seed + PRIME32_5;
- }
-
- h32 += (U32) len;
-
- while (p+4<=bEnd) {
- h32 += XXH_get32bits(p) * PRIME32_3;
- h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
- p+=4;
- }
-
- while (p<bEnd) {
- h32 += (*p) * PRIME32_5;
- h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
- p++;
- }
-
- h32 ^= h32 >> 15;
- h32 *= PRIME32_2;
- h32 ^= h32 >> 13;
- h32 *= PRIME32_3;
- h32 ^= h32 >> 16;
-
- return h32;
-}
-
-
-XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
-{
-#if 0
- /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
- XXH32_CREATESTATE_STATIC(state);
- XXH32_reset(state, seed);
- XXH32_update(state, input, len);
- return XXH32_digest(state);
-#else
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if (XXH_FORCE_ALIGN_CHECK) {
- if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
- else
- return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
- } }
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
- else
- return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
-#endif
-}
-
-
-static U64 XXH64_round(U64 acc, U64 input)
-{
- acc += input * PRIME64_2;
- acc = XXH_rotl64(acc, 31);
- acc *= PRIME64_1;
- return acc;
-}
-
-static U64 XXH64_mergeRound(U64 acc, U64 val)
-{
- val = XXH64_round(0, val);
- acc ^= val;
- acc = acc * PRIME64_1 + PRIME64_4;
- return acc;
-}
-
-FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
-{
- const BYTE* p = (const BYTE*)input;
- const BYTE* const bEnd = p + len;
- U64 h64;
-#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
- if (p==NULL) {
- len=0;
- bEnd=p=(const BYTE*)(size_t)32;
- }
-#endif
-
- if (len>=32) {
- const BYTE* const limit = bEnd - 32;
- U64 v1 = seed + PRIME64_1 + PRIME64_2;
- U64 v2 = seed + PRIME64_2;
- U64 v3 = seed + 0;
- U64 v4 = seed - PRIME64_1;
-
- do {
- v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
- v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
- v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
- v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
- } while (p<=limit);
-
- h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
- h64 = XXH64_mergeRound(h64, v1);
- h64 = XXH64_mergeRound(h64, v2);
- h64 = XXH64_mergeRound(h64, v3);
- h64 = XXH64_mergeRound(h64, v4);
-
- } else {
- h64 = seed + PRIME64_5;
- }
-
- h64 += (U64) len;
-
- while (p+8<=bEnd) {
- U64 const k1 = XXH64_round(0, XXH_get64bits(p));
- h64 ^= k1;
- h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
- p+=8;
- }
-
- if (p+4<=bEnd) {
- h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
- h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
- p+=4;
- }
-
- while (p<bEnd) {
- h64 ^= (*p) * PRIME64_5;
- h64 = XXH_rotl64(h64, 11) * PRIME64_1;
- p++;
- }
-
- h64 ^= h64 >> 33;
- h64 *= PRIME64_2;
- h64 ^= h64 >> 29;
- h64 *= PRIME64_3;
- h64 ^= h64 >> 32;
-
- return h64;
-}
-
-
-XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
-{
-#if 0
- /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
- XXH64_CREATESTATE_STATIC(state);
- XXH64_reset(state, seed);
- XXH64_update(state, input, len);
- return XXH64_digest(state);
-#else
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if (XXH_FORCE_ALIGN_CHECK) {
- if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
- else
- return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
- } }
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
- else
- return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
-#endif
-}
-
-
-/* **************************************************
-* Advanced Hash Functions
-****************************************************/
-
-XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
-{
- return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
-}
-XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
-{
- XXH_free(statePtr);
- return XXH_OK;
-}
-
-XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
-{
- return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
-}
-XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
-{
- XXH_free(statePtr);
- return XXH_OK;
-}
-
-
-/*** Hash feed ***/
-
-XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
-{
- XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
- ZSTD_memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */
- state.v1 = seed + PRIME32_1 + PRIME32_2;
- state.v2 = seed + PRIME32_2;
- state.v3 = seed + 0;
- state.v4 = seed - PRIME32_1;
- ZSTD_memcpy(statePtr, &state, sizeof(state));
- return XXH_OK;
-}
-
-
-XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
-{
- XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
- ZSTD_memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */
- state.v1 = seed + PRIME64_1 + PRIME64_2;
- state.v2 = seed + PRIME64_2;
- state.v3 = seed + 0;
- state.v4 = seed - PRIME64_1;
- ZSTD_memcpy(statePtr, &state, sizeof(state));
- return XXH_OK;
-}
-
-
-FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
-{
- const BYTE* p = (const BYTE*)input;
- const BYTE* const bEnd = p + len;
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
- if (input==NULL) return XXH_ERROR;
-#endif
-
- state->total_len_32 += (unsigned)len;
- state->large_len |= (len>=16) | (state->total_len_32>=16);
-
- if (state->memsize + len < 16) { /* fill in tmp buffer */
- XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
- state->memsize += (unsigned)len;
- return XXH_OK;
- }
-
- if (state->memsize) { /* some data left from previous update */
- XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
- { const U32* p32 = state->mem32;
- state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
- state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
- state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
- state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;
- }
- p += 16-state->memsize;
- state->memsize = 0;
- }
-
- if (p <= bEnd-16) {
- const BYTE* const limit = bEnd - 16;
- U32 v1 = state->v1;
- U32 v2 = state->v2;
- U32 v3 = state->v3;
- U32 v4 = state->v4;
-
- do {
- v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
- v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
- v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
- v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
- } while (p<=limit);
-
- state->v1 = v1;
- state->v2 = v2;
- state->v3 = v3;
- state->v4 = v4;
- }
-
- if (p < bEnd) {
- XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
- state->memsize = (unsigned)(bEnd-p);
- }
-
- return XXH_OK;
-}
-
-XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
-{
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
- else
- return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
-}
-
-
-
-FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
-{
- const BYTE * p = (const BYTE*)state->mem32;
- const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
- U32 h32;
-
- if (state->large_len) {
- h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
- } else {
- h32 = state->v3 /* == seed */ + PRIME32_5;
- }
-
- h32 += state->total_len_32;
-
- while (p+4<=bEnd) {
- h32 += XXH_readLE32(p, endian) * PRIME32_3;
- h32 = XXH_rotl32(h32, 17) * PRIME32_4;
- p+=4;
- }
-
- while (p<bEnd) {
- h32 += (*p) * PRIME32_5;
- h32 = XXH_rotl32(h32, 11) * PRIME32_1;
- p++;
- }
-
- h32 ^= h32 >> 15;
- h32 *= PRIME32_2;
- h32 ^= h32 >> 13;
- h32 *= PRIME32_3;
- h32 ^= h32 >> 16;
-
- return h32;
-}
-
-
-XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
-{
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH32_digest_endian(state_in, XXH_littleEndian);
- else
- return XXH32_digest_endian(state_in, XXH_bigEndian);
-}
-
-
-
-/* **** XXH64 **** */
-
-FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
-{
- const BYTE* p = (const BYTE*)input;
- const BYTE* const bEnd = p + len;
-
-#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
- if (input==NULL) return XXH_ERROR;
-#endif
-
- state->total_len += len;
-
- if (state->memsize + len < 32) { /* fill in tmp buffer */
- if (input != NULL) {
- XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
- }
- state->memsize += (U32)len;
- return XXH_OK;
- }
-
- if (state->memsize) { /* tmp buffer is full */
- XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
- state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
- state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
- state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
- state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
- p += 32-state->memsize;
- state->memsize = 0;
- }
-
- if (p+32 <= bEnd) {
- const BYTE* const limit = bEnd - 32;
- U64 v1 = state->v1;
- U64 v2 = state->v2;
- U64 v3 = state->v3;
- U64 v4 = state->v4;
-
- do {
- v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
- v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
- v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
- v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
- } while (p<=limit);
-
- state->v1 = v1;
- state->v2 = v2;
- state->v3 = v3;
- state->v4 = v4;
- }
-
- if (p < bEnd) {
- XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
- state->memsize = (unsigned)(bEnd-p);
- }
-
- return XXH_OK;
-}
-
-XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
-{
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
- else
- return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
-}
-
-
-
-FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
-{
- const BYTE * p = (const BYTE*)state->mem64;
- const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
- U64 h64;
-
- if (state->total_len >= 32) {
- U64 const v1 = state->v1;
- U64 const v2 = state->v2;
- U64 const v3 = state->v3;
- U64 const v4 = state->v4;
-
- h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
- h64 = XXH64_mergeRound(h64, v1);
- h64 = XXH64_mergeRound(h64, v2);
- h64 = XXH64_mergeRound(h64, v3);
- h64 = XXH64_mergeRound(h64, v4);
- } else {
- h64 = state->v3 + PRIME64_5;
- }
-
- h64 += (U64) state->total_len;
-
- while (p+8<=bEnd) {
- U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
- h64 ^= k1;
- h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
- p+=8;
- }
-
- if (p+4<=bEnd) {
- h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
- h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
- p+=4;
- }
-
- while (p<bEnd) {
- h64 ^= (*p) * PRIME64_5;
- h64 = XXH_rotl64(h64, 11) * PRIME64_1;
- p++;
- }
-
- h64 ^= h64 >> 33;
- h64 *= PRIME64_2;
- h64 ^= h64 >> 29;
- h64 *= PRIME64_3;
- h64 ^= h64 >> 32;
-
- return h64;
-}
-
-
-XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
-{
- XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
-
- if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
- return XXH64_digest_endian(state_in, XXH_littleEndian);
- else
- return XXH64_digest_endian(state_in, XXH_bigEndian);
-}
-
-
-/* **************************
-* Canonical representation
-****************************/
-
-/*! Default XXH result types are basic unsigned 32 and 64 bits.
-* The canonical representation follows human-readable write convention, aka big-endian (large digits first).
-* These functions allow transformation of hash result into and from its canonical format.
-* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.
-*/
-
-XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
-{
- XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
- if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
- ZSTD_memcpy(dst, &hash, sizeof(*dst));
-}
-
-XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
-{
- XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
- if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
- ZSTD_memcpy(dst, &hash, sizeof(*dst));
-}
-
-XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
-{
- return XXH_readBE32(src);
-}
-
-XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
-{
- return XXH_readBE64(src);
-}
diff --git a/thirdparty/zstd/common/xxhash.h b/thirdparty/zstd/common/xxhash.h
index 16c1f1617b..8ebbfdd626 100644
--- a/thirdparty/zstd/common/xxhash.h
+++ b/thirdparty/zstd/common/xxhash.h
@@ -1,20 +1,36 @@
/*
- * xxHash - Extremely Fast Hash algorithm
- * Header File
- * Copyright (c) Yann Collet, Facebook, Inc.
+ * xxHash - Fast Hash algorithm
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ *
+ * You can contact the author at :
+ * - xxHash homepage: http://www.xxhash.com
+ * - xxHash source repository : https://github.com/Cyan4973/xxHash
*
- * You can contact the author at :
- * - xxHash source repository : https://github.com/Cyan4973/xxHash
- *
* This source code is licensed under both the BSD-style license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
-/* Notice extracted from xxHash homepage :
-xxHash is an extremely fast Hash algorithm, running at RAM speed limits.
+#ifndef XXH_NO_XXH3
+# define XXH_NO_XXH3
+#endif
+
+#ifndef XXH_NAMESPACE
+# define XXH_NAMESPACE ZSTD_
+#endif
+
+/*!
+ * @mainpage xxHash
+ *
+ * @file xxhash.h
+ * xxHash prototypes and implementation
+ */
+/* TODO: update */
+/* Notice extracted from xxHash homepage:
+
+xxHash is an extremely fast hash algorithm, running at RAM speed limits.
It also successfully passes all tests from the SMHasher suite.
Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz)
@@ -22,7 +38,7 @@ Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo
Name Speed Q.Score Author
xxHash 5.4 GB/s 10
CrapWow 3.2 GB/s 2 Andrew
-MumurHash 3a 2.7 GB/s 10 Austin Appleby
+MurmurHash 3a 2.7 GB/s 10 Austin Appleby
SpookyHash 2.0 GB/s 10 Bob Jenkins
SBox 1.4 GB/s 9 Bret Mulvey
Lookup3 1.2 GB/s 9 Bob Jenkins
@@ -37,8 +53,13 @@ Q.Score is a measure of quality of the hash function.
It depends on successfully passing SMHasher test set.
10 is a perfect score.
-A 64-bits version, named XXH64, is available since r35.
-It offers much better speed, but for 64-bits applications only.
+Note: SMHasher's CRC32 implementation is not the fastest one.
+Other speed-oriented implementations can be faster,
+especially in combination with PCLMUL instruction:
+https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html?showComment=1552696407071#c3490092340461170735
+
+A 64-bit version, named XXH64, is available since r35.
+It offers much better speed, but for 64-bit applications only.
Name Speed on 64 bits Speed on 32 bits
XXH64 13.8 GB/s 1.9 GB/s
XXH32 6.8 GB/s 6.0 GB/s
@@ -48,33 +69,34 @@ XXH32 6.8 GB/s 6.0 GB/s
extern "C" {
#endif
-#ifndef XXHASH_H_5627135585666179
-#define XXHASH_H_5627135585666179 1
-
-
-/* ****************************
-* Definitions
-******************************/
-#include "zstd_deps.h"
-typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
-
-
/* ****************************
-* API modifier
-******************************/
-/** XXH_PRIVATE_API
-* This is useful if you want to include xxhash functions in `static` mode
-* in order to inline them, and remove their symbol from the public list.
-* Methodology :
-* #define XXH_PRIVATE_API
-* #include "xxhash.h"
-* `xxhash.c` is automatically included.
-* It's not useful to compile and link it as a separate module anymore.
-*/
-#ifdef XXH_PRIVATE_API
-# ifndef XXH_STATIC_LINKING_ONLY
-# define XXH_STATIC_LINKING_ONLY
-# endif
+ * INLINE mode
+ ******************************/
+/*!
+ * XXH_INLINE_ALL (and XXH_PRIVATE_API)
+ * Use these build macros to inline xxhash into the target unit.
+ * Inlining improves performance on small inputs, especially when the length is
+ * expressed as a compile-time constant:
+ *
+ * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html
+ *
+ * It also keeps xxHash symbols private to the unit, so they are not exported.
+ *
+ * Usage:
+ * #define XXH_INLINE_ALL
+ * #include "xxhash.h"
+ *
+ * Do not compile and link xxhash.o as a separate object, as it is not useful.
+ */
+#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \
+ && !defined(XXH_INLINE_ALL_31684351384)
+ /* this section should be traversed only once */
+# define XXH_INLINE_ALL_31684351384
+ /* give access to the advanced API, required to compile implementations */
+# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */
+# define XXH_STATIC_LINKING_ONLY
+ /* make all functions private */
+# undef XXH_PUBLIC_API
# if defined(__GNUC__)
# define XXH_PUBLIC_API static __inline __attribute__((unused))
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
@@ -82,45 +104,205 @@ typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
# elif defined(_MSC_VER)
# define XXH_PUBLIC_API static __inline
# else
-# define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */
+ /* note: this version may generate warnings for unused static functions */
+# define XXH_PUBLIC_API static
# endif
-#else
-# define XXH_PUBLIC_API /* do nothing */
-#endif /* XXH_PRIVATE_API */
-/*!XXH_NAMESPACE, aka Namespace Emulation :
+ /*
+ * This part deals with the special case where a unit wants to inline xxHash,
+ * but "xxhash.h" has previously been included without XXH_INLINE_ALL,
+ * such as part of some previously included *.h header file.
+ * Without further action, the new include would just be ignored,
+ * and functions would effectively _not_ be inlined (silent failure).
+ * The following macros solve this situation by prefixing all inlined names,
+ * avoiding naming collision with previous inclusions.
+ */
+ /* Before that, we unconditionally #undef all symbols,
+ * in case they were already defined with XXH_NAMESPACE.
+ * They will then be redefined for XXH_INLINE_ALL
+ */
+# undef XXH_versionNumber
+ /* XXH32 */
+# undef XXH32
+# undef XXH32_createState
+# undef XXH32_freeState
+# undef XXH32_reset
+# undef XXH32_update
+# undef XXH32_digest
+# undef XXH32_copyState
+# undef XXH32_canonicalFromHash
+# undef XXH32_hashFromCanonical
+ /* XXH64 */
+# undef XXH64
+# undef XXH64_createState
+# undef XXH64_freeState
+# undef XXH64_reset
+# undef XXH64_update
+# undef XXH64_digest
+# undef XXH64_copyState
+# undef XXH64_canonicalFromHash
+# undef XXH64_hashFromCanonical
+ /* XXH3_64bits */
+# undef XXH3_64bits
+# undef XXH3_64bits_withSecret
+# undef XXH3_64bits_withSeed
+# undef XXH3_64bits_withSecretandSeed
+# undef XXH3_createState
+# undef XXH3_freeState
+# undef XXH3_copyState
+# undef XXH3_64bits_reset
+# undef XXH3_64bits_reset_withSeed
+# undef XXH3_64bits_reset_withSecret
+# undef XXH3_64bits_update
+# undef XXH3_64bits_digest
+# undef XXH3_generateSecret
+ /* XXH3_128bits */
+# undef XXH128
+# undef XXH3_128bits
+# undef XXH3_128bits_withSeed
+# undef XXH3_128bits_withSecret
+# undef XXH3_128bits_reset
+# undef XXH3_128bits_reset_withSeed
+# undef XXH3_128bits_reset_withSecret
+# undef XXH3_128bits_reset_withSecretandSeed
+# undef XXH3_128bits_update
+# undef XXH3_128bits_digest
+# undef XXH128_isEqual
+# undef XXH128_cmp
+# undef XXH128_canonicalFromHash
+# undef XXH128_hashFromCanonical
+ /* Finally, free the namespace itself */
+# undef XXH_NAMESPACE
-If you want to include _and expose_ xxHash functions from within your own library,
-but also want to avoid symbol collisions with another library which also includes xxHash,
+ /* employ the namespace for XXH_INLINE_ALL */
+# define XXH_NAMESPACE XXH_INLINE_
+ /*
+ * Some identifiers (enums, type names) are not symbols,
+ * but they must nonetheless be renamed to avoid redeclaration.
+ * Alternative solution: do not redeclare them.
+ * However, this requires some #ifdefs, and has a more dispersed impact.
+ * Meanwhile, renaming can be achieved in a single place.
+ */
+# define XXH_IPREF(Id) XXH_NAMESPACE ## Id
+# define XXH_OK XXH_IPREF(XXH_OK)
+# define XXH_ERROR XXH_IPREF(XXH_ERROR)
+# define XXH_errorcode XXH_IPREF(XXH_errorcode)
+# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t)
+# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t)
+# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t)
+# define XXH32_state_s XXH_IPREF(XXH32_state_s)
+# define XXH32_state_t XXH_IPREF(XXH32_state_t)
+# define XXH64_state_s XXH_IPREF(XXH64_state_s)
+# define XXH64_state_t XXH_IPREF(XXH64_state_t)
+# define XXH3_state_s XXH_IPREF(XXH3_state_s)
+# define XXH3_state_t XXH_IPREF(XXH3_state_t)
+# define XXH128_hash_t XXH_IPREF(XXH128_hash_t)
+ /* Ensure the header is parsed again, even if it was previously included */
+# undef XXHASH_H_5627135585666179
+# undef XXHASH_H_STATIC_13879238742
+#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */
-you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
-with the value of XXH_NAMESPACE (so avoid to keep it NULL and avoid numeric values).
-Note that no change is required within the calling program as long as it includes `xxhash.h` :
-regular symbol name will be automatically translated by this header.
-*/
+
+/* ****************************************************************
+ * Stable API
+ *****************************************************************/
+#ifndef XXHASH_H_5627135585666179
+#define XXHASH_H_5627135585666179 1
+
+
+/*!
+ * @defgroup public Public API
+ * Contains details on the public xxHash functions.
+ * @{
+ */
+/* specific declaration modes for Windows */
+#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)
+# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))
+# ifdef XXH_EXPORT
+# define XXH_PUBLIC_API __declspec(dllexport)
+# elif XXH_IMPORT
+# define XXH_PUBLIC_API __declspec(dllimport)
+# endif
+# else
+# define XXH_PUBLIC_API /* do nothing */
+# endif
+#endif
+
+#ifdef XXH_DOXYGEN
+/*!
+ * @brief Emulate a namespace by transparently prefixing all symbols.
+ *
+ * If you want to include _and expose_ xxHash functions from within your own
+ * library, but also want to avoid symbol collisions with other libraries which
+ * may also include xxHash, you can use XXH_NAMESPACE to automatically prefix
+ * any public symbol from xxhash library with the value of XXH_NAMESPACE
+ * (therefore, avoid empty or numeric values).
+ *
+ * Note that no change is required within the calling program as long as it
+ * includes `xxhash.h`: Regular symbol names will be automatically translated
+ * by this header.
+ */
+# define XXH_NAMESPACE /* YOUR NAME HERE */
+# undef XXH_NAMESPACE
+#endif
+
#ifdef XXH_NAMESPACE
# define XXH_CAT(A,B) A##B
# define XXH_NAME2(A,B) XXH_CAT(A,B)
-# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
-# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
+/* XXH32 */
+# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
-# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
-# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
-# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
-# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
-# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
-# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
-# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
+/* XXH64 */
+# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
+# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
+# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
+# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
+# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
+# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
+# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
+# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
+/* XXH3_64bits */
+# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits)
+# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret)
+# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed)
+# define XXH3_64bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecretandSeed)
+# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState)
+# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState)
+# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState)
+# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset)
+# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed)
+# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret)
+# define XXH3_64bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecretandSeed)
+# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update)
+# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest)
+# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret)
+# define XXH3_generateSecret_fromSeed XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret_fromSeed)
+/* XXH3_128bits */
+# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128)
+# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits)
+# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed)
+# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret)
+# define XXH3_128bits_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecretandSeed)
+# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset)
+# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed)
+# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret)
+# define XXH3_128bits_reset_withSecretandSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecretandSeed)
+# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update)
+# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest)
+# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual)
+# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp)
+# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash)
+# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical)
#endif
@@ -128,156 +310,5375 @@ regular symbol name will be automatically translated by this header.
* Version
***************************************/
#define XXH_VERSION_MAJOR 0
-#define XXH_VERSION_MINOR 6
-#define XXH_VERSION_RELEASE 2
+#define XXH_VERSION_MINOR 8
+#define XXH_VERSION_RELEASE 1
#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
+
+/*!
+ * @brief Obtains the xxHash version.
+ *
+ * This is mostly useful when xxHash is compiled as a shared library,
+ * since the returned value comes from the library, as opposed to header file.
+ *
+ * @return `XXH_VERSION_NUMBER` of the invoked library.
+ */
XXH_PUBLIC_API unsigned XXH_versionNumber (void);
/* ****************************
-* Simple Hash Functions
+* Common basic types
******************************/
-typedef unsigned int XXH32_hash_t;
-typedef unsigned long long XXH64_hash_t;
-
-XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
-XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
-
-/*!
-XXH32() :
- Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
- The memory between input & input+length must be valid (allocated and read-accessible).
- "seed" can be used to alter the result predictably.
- Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s
-XXH64() :
- Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
- "seed" can be used to alter the result predictably.
- This function runs 2x faster on 64-bits systems, but slower on 32-bits systems (see benchmark).
-*/
+#include <stddef.h> /* size_t */
+typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
-/* ****************************
-* Streaming Hash Functions
-******************************/
-typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
-typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
+/*-**********************************************************************
+* 32-bit hash
+************************************************************************/
+#if defined(XXH_DOXYGEN) /* Don't show <stdint.h> include */
+/*!
+ * @brief An unsigned 32-bit integer.
+ *
+ * Not necessarily defined to `uint32_t` but functionally equivalent.
+ */
+typedef uint32_t XXH32_hash_t;
-/*! State allocation, compatible with dynamic libraries */
+#elif !defined (__VMS) \
+ && (defined (__cplusplus) \
+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
+# include <stdint.h>
+ typedef uint32_t XXH32_hash_t;
-XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
-XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
+#else
+# include <limits.h>
+# if UINT_MAX == 0xFFFFFFFFUL
+ typedef unsigned int XXH32_hash_t;
+# else
+# if ULONG_MAX == 0xFFFFFFFFUL
+ typedef unsigned long XXH32_hash_t;
+# else
+# error "unsupported platform: need a 32-bit type"
+# endif
+# endif
+#endif
-XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
-XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
+/*!
+ * @}
+ *
+ * @defgroup xxh32_family XXH32 family
+ * @ingroup public
+ * Contains functions used in the classic 32-bit xxHash algorithm.
+ *
+ * @note
+ * XXH32 is useful for older platforms, with no or poor 64-bit performance.
+ * Note that @ref xxh3_family provides competitive speed
+ * for both 32-bit and 64-bit systems, and offers true 64/128 bit hash results.
+ *
+ * @see @ref xxh64_family, @ref xxh3_family : Other xxHash families
+ * @see @ref xxh32_impl for implementation details
+ * @{
+ */
+
+/*!
+ * @brief Calculates the 32-bit hash of @p input using xxHash32.
+ *
+ * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s
+ *
+ * @param input The block of data to be hashed, at least @p length bytes in size.
+ * @param length The length of @p input, in bytes.
+ * @param seed The 32-bit seed to alter the hash's output predictably.
+ *
+ * @pre
+ * The memory between @p input and @p input + @p length must be valid,
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
+ *
+ * @return The calculated 32-bit hash value.
+ *
+ * @see
+ * XXH64(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128():
+ * Direct equivalents for the other variants of xxHash.
+ * @see
+ * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version.
+ */
+XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed);
+
+/*!
+ * Streaming functions generate the xxHash value from an incremental input.
+ * This method is slower than single-call functions, due to state management.
+ * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized.
+ *
+ * An XXH state must first be allocated using `XXH*_createState()`.
+ *
+ * Start a new hash by initializing the state with a seed using `XXH*_reset()`.
+ *
+ * Then, feed the hash state by calling `XXH*_update()` as many times as necessary.
+ *
+ * The function returns an error code, with 0 meaning OK, and any other value
+ * meaning there is an error.
+ *
+ * Finally, a hash value can be produced anytime, by using `XXH*_digest()`.
+ * This function returns the nn-bits hash as an int or long long.
+ *
+ * It's still possible to continue inserting input into the hash state after a
+ * digest, and generate new hash values later on by invoking `XXH*_digest()`.
+ *
+ * When done, release the state using `XXH*_freeState()`.
+ *
+ * Example code for incrementally hashing a file:
+ * @code{.c}
+ * #include <stdio.h>
+ * #include <xxhash.h>
+ * #define BUFFER_SIZE 256
+ *
+ * // Note: XXH64 and XXH3 use the same interface.
+ * XXH32_hash_t
+ * hashFile(FILE* stream)
+ * {
+ * XXH32_state_t* state;
+ * unsigned char buf[BUFFER_SIZE];
+ * size_t amt;
+ * XXH32_hash_t hash;
+ *
+ * state = XXH32_createState(); // Create a state
+ * assert(state != NULL); // Error check here
+ * XXH32_reset(state, 0xbaad5eed); // Reset state with our seed
+ * while ((amt = fread(buf, 1, sizeof(buf), stream)) != 0) {
+ * XXH32_update(state, buf, amt); // Hash the file in chunks
+ * }
+ * hash = XXH32_digest(state); // Finalize the hash
+ * XXH32_freeState(state); // Clean up
+ * return hash;
+ * }
+ * @endcode
+ */
+/*!
+ * @typedef struct XXH32_state_s XXH32_state_t
+ * @brief The opaque state struct for the XXH32 streaming API.
+ *
+ * @see XXH32_state_s for details.
+ */
+typedef struct XXH32_state_s XXH32_state_t;
+
+/*!
+ * @brief Allocates an @ref XXH32_state_t.
+ *
+ * Must be freed with XXH32_freeState().
+ * @return An allocated XXH32_state_t on success, `NULL` on failure.
+ */
+XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
+/*!
+ * @brief Frees an @ref XXH32_state_t.
+ *
+ * Must be allocated with XXH32_createState().
+ * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState().
+ * @return XXH_OK.
+ */
+XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
+/*!
+ * @brief Copies one @ref XXH32_state_t to another.
+ *
+ * @param dst_state The state to copy to.
+ * @param src_state The state to copy from.
+ * @pre
+ * @p dst_state and @p src_state must not be `NULL` and must not overlap.
+ */
+XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state);
-/* hash streaming */
+/*!
+ * @brief Resets an @ref XXH32_state_t to begin a new hash.
+ *
+ * This function resets and seeds a state. Call it before @ref XXH32_update().
+ *
+ * @param statePtr The state struct to reset.
+ * @param seed The 32-bit seed to alter the hash result predictably.
+ *
+ * @pre
+ * @p statePtr must not be `NULL`.
+ *
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
+ */
+XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed);
-XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
+/*!
+ * @brief Consumes a block of @p input to an @ref XXH32_state_t.
+ *
+ * Call this to incrementally consume blocks of data.
+ *
+ * @param statePtr The state struct to update.
+ * @param input The block of data to be hashed, at least @p length bytes in size.
+ * @param length The length of @p input, in bytes.
+ *
+ * @pre
+ * @p statePtr must not be `NULL`.
+ * @pre
+ * The memory between @p input and @p input + @p length must be valid,
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
+ *
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
+ */
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
+
+/*!
+ * @brief Returns the calculated hash value from an @ref XXH32_state_t.
+ *
+ * @note
+ * Calling XXH32_digest() will not affect @p statePtr, so you can update,
+ * digest, and update again.
+ *
+ * @param statePtr The state struct to calculate the hash from.
+ *
+ * @pre
+ * @p statePtr must not be `NULL`.
+ *
+ * @return The calculated xxHash32 value from that state.
+ */
XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
-XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
-XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
-XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
+/******* Canonical representation *******/
/*
-These functions generate the xxHash of an input provided in multiple segments.
-Note that, for small input, they are slower than single-call functions, due to state management.
-For small input, prefer `XXH32()` and `XXH64()` .
+ * The default return values from XXH functions are unsigned 32 and 64 bit
+ * integers.
+ * This the simplest and fastest format for further post-processing.
+ *
+ * However, this leaves open the question of what is the order on the byte level,
+ * since little and big endian conventions will store the same number differently.
+ *
+ * The canonical representation settles this issue by mandating big-endian
+ * convention, the same convention as human-readable numbers (large digits first).
+ *
+ * When writing hash values to storage, sending them over a network, or printing
+ * them, it's highly recommended to use the canonical representation to ensure
+ * portability across a wider range of systems, present and future.
+ *
+ * The following functions allow transformation of hash values to and from
+ * canonical format.
+ */
+
+/*!
+ * @brief Canonical (big endian) representation of @ref XXH32_hash_t.
+ */
+typedef struct {
+ unsigned char digest[4]; /*!< Hash bytes, big endian */
+} XXH32_canonical_t;
+
+/*!
+ * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t.
+ *
+ * @param dst The @ref XXH32_canonical_t pointer to be stored to.
+ * @param hash The @ref XXH32_hash_t to be converted.
+ *
+ * @pre
+ * @p dst must not be `NULL`.
+ */
+XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
-XXH state must first be allocated, using XXH*_createState() .
+/*!
+ * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t.
+ *
+ * @param src The @ref XXH32_canonical_t to convert.
+ *
+ * @pre
+ * @p src must not be `NULL`.
+ *
+ * @return The converted hash.
+ */
+XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
-Start a new hash by initializing state with a seed, using XXH*_reset().
-Then, feed the hash state by calling XXH*_update() as many times as necessary.
-Obviously, input must be allocated and read accessible.
-The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
+#ifdef __has_attribute
+# define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+# define XXH_HAS_ATTRIBUTE(x) 0
+#endif
-Finally, a hash value can be produced anytime, by using XXH*_digest().
-This function returns the nn-bits hash as an int or long long.
+/* C-language Attributes are added in C23. */
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ > 201710L) && defined(__has_c_attribute)
+# define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
+#else
+# define XXH_HAS_C_ATTRIBUTE(x) 0
+#endif
-It's still possible to continue inserting input into the hash state after a digest,
-and generate some new hashes later on, by calling again XXH*_digest().
+#if defined(__cplusplus) && defined(__has_cpp_attribute)
+# define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define XXH_HAS_CPP_ATTRIBUTE(x) 0
+#endif
-When done, free XXH state space if it was allocated dynamically.
+/*
+Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute
+introduced in CPP17 and C23.
+CPP17 : https://en.cppreference.com/w/cpp/language/attributes/fallthrough
+C23 : https://en.cppreference.com/w/c/language/attributes/fallthrough
*/
+#if XXH_HAS_C_ATTRIBUTE(x)
+# define XXH_FALLTHROUGH [[fallthrough]]
+#elif XXH_HAS_CPP_ATTRIBUTE(x)
+# define XXH_FALLTHROUGH [[fallthrough]]
+#elif XXH_HAS_ATTRIBUTE(__fallthrough__)
+# define XXH_FALLTHROUGH __attribute__ ((fallthrough))
+#else
+# define XXH_FALLTHROUGH
+#endif
+/*!
+ * @}
+ * @ingroup public
+ * @{
+ */
-/* **************************
-* Utils
-****************************/
-#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* ! C99 */
-# define restrict /* disable restrict */
+#ifndef XXH_NO_LONG_LONG
+/*-**********************************************************************
+* 64-bit hash
+************************************************************************/
+#if defined(XXH_DOXYGEN) /* don't include <stdint.h> */
+/*!
+ * @brief An unsigned 64-bit integer.
+ *
+ * Not necessarily defined to `uint64_t` but functionally equivalent.
+ */
+typedef uint64_t XXH64_hash_t;
+#elif !defined (__VMS) \
+ && (defined (__cplusplus) \
+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
+# include <stdint.h>
+ typedef uint64_t XXH64_hash_t;
+#else
+# include <limits.h>
+# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL
+ /* LP64 ABI says uint64_t is unsigned long */
+ typedef unsigned long XXH64_hash_t;
+# else
+ /* the following type must have a width of 64-bit */
+ typedef unsigned long long XXH64_hash_t;
+# endif
#endif
-XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dst_state, const XXH32_state_t* restrict src_state);
-XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dst_state, const XXH64_state_t* restrict src_state);
+/*!
+ * @}
+ *
+ * @defgroup xxh64_family XXH64 family
+ * @ingroup public
+ * @{
+ * Contains functions used in the classic 64-bit xxHash algorithm.
+ *
+ * @note
+ * XXH3 provides competitive speed for both 32-bit and 64-bit systems,
+ * and offers true 64/128 bit hash results.
+ * It provides better speed for systems with vector processing capabilities.
+ */
-/* **************************
-* Canonical representation
-****************************/
-/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
-* The canonical representation uses human-readable write convention, aka big-endian (large digits first).
-* These functions allow transformation of hash result into and from its canonical format.
-* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
-*/
-typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
-typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
+/*!
+ * @brief Calculates the 64-bit hash of @p input using xxHash64.
+ *
+ * This function usually runs faster on 64-bit systems, but slower on 32-bit
+ * systems (see benchmark).
+ *
+ * @param input The block of data to be hashed, at least @p length bytes in size.
+ * @param length The length of @p input, in bytes.
+ * @param seed The 64-bit seed to alter the hash's output predictably.
+ *
+ * @pre
+ * The memory between @p input and @p input + @p length must be valid,
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
+ *
+ * @return The calculated 64-bit hash.
+ *
+ * @see
+ * XXH32(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128():
+ * Direct equivalents for the other variants of xxHash.
+ * @see
+ * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version.
+ */
+XXH_PUBLIC_API XXH64_hash_t XXH64(const void* input, size_t length, XXH64_hash_t seed);
-XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
-XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
+/******* Streaming *******/
+/*!
+ * @brief The opaque state struct for the XXH64 streaming API.
+ *
+ * @see XXH64_state_s for details.
+ */
+typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
+XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
+XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
+XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state);
-XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
+XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, XXH64_hash_t seed);
+XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
+XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
+
+/******* Canonical representation *******/
+typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;
+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
+#ifndef XXH_NO_XXH3
+/*!
+ * @}
+ * ************************************************************************
+ * @defgroup xxh3_family XXH3 family
+ * @ingroup public
+ * @{
+ *
+ * XXH3 is a more recent hash algorithm featuring:
+ * - Improved speed for both small and large inputs
+ * - True 64-bit and 128-bit outputs
+ * - SIMD acceleration
+ * - Improved 32-bit viability
+ *
+ * Speed analysis methodology is explained here:
+ *
+ * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html
+ *
+ * Compared to XXH64, expect XXH3 to run approximately
+ * ~2x faster on large inputs and >3x faster on small ones,
+ * exact differences vary depending on platform.
+ *
+ * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic,
+ * but does not require it.
+ * Any 32-bit and 64-bit targets that can run XXH32 smoothly
+ * can run XXH3 at competitive speeds, even without vector support.
+ * Further details are explained in the implementation.
+ *
+ * Optimized implementations are provided for AVX512, AVX2, SSE2, NEON, POWER8,
+ * ZVector and scalar targets. This can be controlled via the XXH_VECTOR macro.
+ *
+ * XXH3 implementation is portable:
+ * it has a generic C90 formulation that can be compiled on any platform,
+ * all implementations generage exactly the same hash value on all platforms.
+ * Starting from v0.8.0, it's also labelled "stable", meaning that
+ * any future version will also generate the same hash value.
+ *
+ * XXH3 offers 2 variants, _64bits and _128bits.
+ *
+ * When only 64 bits are needed, prefer invoking the _64bits variant, as it
+ * reduces the amount of mixing, resulting in faster speed on small inputs.
+ * It's also generally simpler to manipulate a scalar return type than a struct.
+ *
+ * The API supports one-shot hashing, streaming mode, and custom secrets.
+ */
+
+/*-**********************************************************************
+* XXH3 64-bit variant
+************************************************************************/
+
+/* XXH3_64bits():
+ * default 64-bit variant, using default secret and default seed of 0.
+ * It's the fastest variant. */
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* data, size_t len);
+
+/*
+ * XXH3_64bits_withSeed():
+ * This variant generates a custom secret on the fly
+ * based on default secret altered using the `seed` value.
+ * While this operation is decently fast, note that it's not completely free.
+ * Note: seed==0 produces the same results as XXH3_64bits().
+ */
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, XXH64_hash_t seed);
+
+/*!
+ * The bare minimum size for a custom secret.
+ *
+ * @see
+ * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(),
+ * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret().
+ */
+#define XXH3_SECRET_SIZE_MIN 136
+
+/*
+ * XXH3_64bits_withSecret():
+ * It's possible to provide any blob of bytes as a "secret" to generate the hash.
+ * This makes it more difficult for an external actor to prepare an intentional collision.
+ * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN).
+ * However, the quality of the secret impacts the dispersion of the hash algorithm.
+ * Therefore, the secret _must_ look like a bunch of random bytes.
+ * Avoid "trivial" or structured data such as repeated sequences or a text document.
+ * Whenever in doubt about the "randomness" of the blob of bytes,
+ * consider employing "XXH3_generateSecret()" instead (see below).
+ * It will generate a proper high entropy secret derived from the blob of bytes.
+ * Another advantage of using XXH3_generateSecret() is that
+ * it guarantees that all bits within the initial blob of bytes
+ * will impact every bit of the output.
+ * This is not necessarily the case when using the blob of bytes directly
+ * because, when hashing _small_ inputs, only a portion of the secret is employed.
+ */
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize);
+
+
+/******* Streaming *******/
+/*
+ * Streaming requires state maintenance.
+ * This operation costs memory and CPU.
+ * As a consequence, streaming is slower than one-shot hashing.
+ * For better performance, prefer one-shot functions whenever applicable.
+ */
+
+/*!
+ * @brief The state struct for the XXH3 streaming API.
+ *
+ * @see XXH3_state_s for details.
+ */
+typedef struct XXH3_state_s XXH3_state_t;
+XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void);
+XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr);
+XXH_PUBLIC_API void XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state);
+
+/*
+ * XXH3_64bits_reset():
+ * Initialize with default parameters.
+ * digest will be equivalent to `XXH3_64bits()`.
+ */
+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH3_state_t* statePtr);
+/*
+ * XXH3_64bits_reset_withSeed():
+ * Generate a custom secret from `seed`, and store it into `statePtr`.
+ * digest will be equivalent to `XXH3_64bits_withSeed()`.
+ */
+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed);
+/*
+ * XXH3_64bits_reset_withSecret():
+ * `secret` is referenced, it _must outlive_ the hash streaming session.
+ * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`,
+ * and the quality of produced hash values depends on secret's entropy
+ * (secret's content should look like a bunch of random bytes).
+ * When in doubt about the randomness of a candidate `secret`,
+ * consider employing `XXH3_generateSecret()` instead (see below).
+ */
+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize);
+
+XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH3_state_t* statePtr, const void* input, size_t length);
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* statePtr);
+
+/* note : canonical representation of XXH3 is the same as XXH64
+ * since they both produce XXH64_hash_t values */
+
+
+/*-**********************************************************************
+* XXH3 128-bit variant
+************************************************************************/
+
+/*!
+ * @brief The return value from 128-bit hashes.
+ *
+ * Stored in little endian order, although the fields themselves are in native
+ * endianness.
+ */
+typedef struct {
+ XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */
+ XXH64_hash_t high64; /*!< `value >> 64` */
+} XXH128_hash_t;
+
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* data, size_t len);
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(const void* data, size_t len, XXH64_hash_t seed);
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize);
+
+/******* Streaming *******/
+/*
+ * Streaming requires state maintenance.
+ * This operation costs memory and CPU.
+ * As a consequence, streaming is slower than one-shot hashing.
+ * For better performance, prefer one-shot functions whenever applicable.
+ *
+ * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits().
+ * Use already declared XXH3_createState() and XXH3_freeState().
+ *
+ * All reset and streaming functions have same meaning as their 64-bit counterpart.
+ */
+
+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH3_state_t* statePtr);
+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed);
+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize);
+
+XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH3_state_t* statePtr, const void* input, size_t length);
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* statePtr);
+
+/* Following helper functions make it possible to compare XXH128_hast_t values.
+ * Since XXH128_hash_t is a structure, this capability is not offered by the language.
+ * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */
+
+/*!
+ * XXH128_isEqual():
+ * Return: 1 if `h1` and `h2` are equal, 0 if they are not.
+ */
+XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2);
+
+/*!
+ * XXH128_cmp():
+ *
+ * This comparator is compatible with stdlib's `qsort()`/`bsearch()`.
+ *
+ * return: >0 if *h128_1 > *h128_2
+ * =0 if *h128_1 == *h128_2
+ * <0 if *h128_1 < *h128_2
+ */
+XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2);
+
+
+/******* Canonical representation *******/
+typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;
+XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash);
+XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical(const XXH128_canonical_t* src);
+
+
+#endif /* !XXH_NO_XXH3 */
+#endif /* XXH_NO_LONG_LONG */
+
+/*!
+ * @}
+ */
#endif /* XXHASH_H_5627135585666179 */
-/* ================================================================================================
- This section contains definitions which are not guaranteed to remain stable.
- They may change in future versions, becoming incompatible with a different version of the library.
- They shall only be used with static linking.
- Never use these definitions in association with dynamic linking !
-=================================================================================================== */
-#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXH_STATIC_H_3543687687345)
-#define XXH_STATIC_H_3543687687345
-
-/* These definitions are only meant to allow allocation of XXH state
- statically, on stack, or in a struct for example.
- Do not use members directly. */
-
- struct XXH32_state_s {
- unsigned total_len_32;
- unsigned large_len;
- unsigned v1;
- unsigned v2;
- unsigned v3;
- unsigned v4;
- unsigned mem32[4]; /* buffer defined as U32 for alignment */
- unsigned memsize;
- unsigned reserved; /* never read nor write, will be removed in a future version */
- }; /* typedef'd to XXH32_state_t */
-
- struct XXH64_state_s {
- unsigned long long total_len;
- unsigned long long v1;
- unsigned long long v2;
- unsigned long long v3;
- unsigned long long v4;
- unsigned long long mem64[4]; /* buffer defined as U64 for alignment */
- unsigned memsize;
- unsigned reserved[2]; /* never read nor write, will be removed in a future version */
- }; /* typedef'd to XXH64_state_t */
-
-
-# ifdef XXH_PRIVATE_API
-# include "xxhash.c" /* include xxhash functions as `static`, for inlining */
+#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742)
+#define XXHASH_H_STATIC_13879238742
+/* ****************************************************************************
+ * This section contains declarations which are not guaranteed to remain stable.
+ * They may change in future versions, becoming incompatible with a different
+ * version of the library.
+ * These declarations should only be used with static linking.
+ * Never use them in association with dynamic linking!
+ ***************************************************************************** */
+
+/*
+ * These definitions are only present to allow static allocation
+ * of XXH states, on stack or in a struct, for example.
+ * Never **ever** access their members directly.
+ */
+
+/*!
+ * @internal
+ * @brief Structure for XXH32 streaming API.
+ *
+ * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,
+ * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is
+ * an opaque type. This allows fields to safely be changed.
+ *
+ * Typedef'd to @ref XXH32_state_t.
+ * Do not access the members of this struct directly.
+ * @see XXH64_state_s, XXH3_state_s
+ */
+struct XXH32_state_s {
+ XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */
+ XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */
+ XXH32_hash_t v[4]; /*!< Accumulator lanes */
+ XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */
+ XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */
+ XXH32_hash_t reserved; /*!< Reserved field. Do not read nor write to it. */
+}; /* typedef'd to XXH32_state_t */
+
+
+#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */
+
+/*!
+ * @internal
+ * @brief Structure for XXH64 streaming API.
+ *
+ * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,
+ * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is
+ * an opaque type. This allows fields to safely be changed.
+ *
+ * Typedef'd to @ref XXH64_state_t.
+ * Do not access the members of this struct directly.
+ * @see XXH32_state_s, XXH3_state_s
+ */
+struct XXH64_state_s {
+ XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */
+ XXH64_hash_t v[4]; /*!< Accumulator lanes */
+ XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
+ XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */
+ XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/
+ XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it. */
+}; /* typedef'd to XXH64_state_t */
+
+
+#ifndef XXH_NO_XXH3
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* >= C11 */
+# include <stdalign.h>
+# define XXH_ALIGN(n) alignas(n)
+#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* >= C++11 */
+/* In C++ alignas() is a keyword */
+# define XXH_ALIGN(n) alignas(n)
+#elif defined(__GNUC__)
+# define XXH_ALIGN(n) __attribute__ ((aligned(n)))
+#elif defined(_MSC_VER)
+# define XXH_ALIGN(n) __declspec(align(n))
+#else
+# define XXH_ALIGN(n) /* disabled */
+#endif
+
+/* Old GCC versions only accept the attribute after the type in structures. */
+#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \
+ && ! (defined(__cplusplus) && (__cplusplus >= 201103L)) /* >= C++11 */ \
+ && defined(__GNUC__)
+# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align)
+#else
+# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type
+#endif
+
+/*!
+ * @brief The size of the internal XXH3 buffer.
+ *
+ * This is the optimal update size for incremental hashing.
+ *
+ * @see XXH3_64b_update(), XXH3_128b_update().
+ */
+#define XXH3_INTERNALBUFFER_SIZE 256
+
+/*!
+ * @brief Default size of the secret buffer (and @ref XXH3_kSecret).
+ *
+ * This is the size used in @ref XXH3_kSecret and the seeded functions.
+ *
+ * Not to be confused with @ref XXH3_SECRET_SIZE_MIN.
+ */
+#define XXH3_SECRET_DEFAULT_SIZE 192
+
+/*!
+ * @internal
+ * @brief Structure for XXH3 streaming API.
+ *
+ * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY,
+ * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined.
+ * Otherwise it is an opaque type.
+ * Never use this definition in combination with dynamic library.
+ * This allows fields to safely be changed in the future.
+ *
+ * @note ** This structure has a strict alignment requirement of 64 bytes!! **
+ * Do not allocate this with `malloc()` or `new`,
+ * it will not be sufficiently aligned.
+ * Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack allocation.
+ *
+ * Typedef'd to @ref XXH3_state_t.
+ * Do never access the members of this struct directly.
+ *
+ * @see XXH3_INITSTATE() for stack initialization.
+ * @see XXH3_createState(), XXH3_freeState().
+ * @see XXH32_state_s, XXH64_state_s
+ */
+struct XXH3_state_s {
+ XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]);
+ /*!< The 8 accumulators. Similar to `vN` in @ref XXH32_state_s::v1 and @ref XXH64_state_s */
+ XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]);
+ /*!< Used to store a custom secret generated from a seed. */
+ XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]);
+ /*!< The internal buffer. @see XXH32_state_s::mem32 */
+ XXH32_hash_t bufferedSize;
+ /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */
+ XXH32_hash_t useSeed;
+ /*!< Reserved field. Needed for padding on 64-bit. */
+ size_t nbStripesSoFar;
+ /*!< Number or stripes processed. */
+ XXH64_hash_t totalLen;
+ /*!< Total length hashed. 64-bit even on 32-bit targets. */
+ size_t nbStripesPerBlock;
+ /*!< Number of stripes per block. */
+ size_t secretLimit;
+ /*!< Size of @ref customSecret or @ref extSecret */
+ XXH64_hash_t seed;
+ /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */
+ XXH64_hash_t reserved64;
+ /*!< Reserved field. */
+ const unsigned char* extSecret;
+ /*!< Reference to an external secret for the _withSecret variants, NULL
+ * for other variants. */
+ /* note: there may be some padding at the end due to alignment on 64 bytes */
+}; /* typedef'd to XXH3_state_t */
+
+#undef XXH_ALIGN_MEMBER
+
+/*!
+ * @brief Initializes a stack-allocated `XXH3_state_s`.
+ *
+ * When the @ref XXH3_state_t structure is merely emplaced on stack,
+ * it should be initialized with XXH3_INITSTATE() or a memset()
+ * in case its first reset uses XXH3_NNbits_reset_withSeed().
+ * This init can be omitted if the first reset uses default or _withSecret mode.
+ * This operation isn't necessary when the state is created with XXH3_createState().
+ * Note that this doesn't prepare the state for a streaming operation,
+ * it's still necessary to use XXH3_NNbits_reset*() afterwards.
+ */
+#define XXH3_INITSTATE(XXH3_state_ptr) { (XXH3_state_ptr)->seed = 0; }
+
+
+/* XXH128() :
+ * simple alias to pre-selected XXH3_128bits variant
+ */
+XXH_PUBLIC_API XXH128_hash_t XXH128(const void* data, size_t len, XXH64_hash_t seed);
+
+
+/* === Experimental API === */
+/* Symbols defined below must be considered tied to a specific library version. */
+
+/*
+ * XXH3_generateSecret():
+ *
+ * Derive a high-entropy secret from any user-defined content, named customSeed.
+ * The generated secret can be used in combination with `*_withSecret()` functions.
+ * The `_withSecret()` variants are useful to provide a higher level of protection than 64-bit seed,
+ * as it becomes much more difficult for an external actor to guess how to impact the calculation logic.
+ *
+ * The function accepts as input a custom seed of any length and any content,
+ * and derives from it a high-entropy secret of length @secretSize
+ * into an already allocated buffer @secretBuffer.
+ * @secretSize must be >= XXH3_SECRET_SIZE_MIN
+ *
+ * The generated secret can then be used with any `*_withSecret()` variant.
+ * Functions `XXH3_128bits_withSecret()`, `XXH3_64bits_withSecret()`,
+ * `XXH3_128bits_reset_withSecret()` and `XXH3_64bits_reset_withSecret()`
+ * are part of this list. They all accept a `secret` parameter
+ * which must be large enough for implementation reasons (>= XXH3_SECRET_SIZE_MIN)
+ * _and_ feature very high entropy (consist of random-looking bytes).
+ * These conditions can be a high bar to meet, so
+ * XXH3_generateSecret() can be employed to ensure proper quality.
+ *
+ * customSeed can be anything. It can have any size, even small ones,
+ * and its content can be anything, even "poor entropy" sources such as a bunch of zeroes.
+ * The resulting `secret` will nonetheless provide all required qualities.
+ *
+ * When customSeedSize > 0, supplying NULL as customSeed is undefined behavior.
+ */
+XXH_PUBLIC_API XXH_errorcode XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize);
+
+
+/*
+ * XXH3_generateSecret_fromSeed():
+ *
+ * Generate the same secret as the _withSeed() variants.
+ *
+ * The resulting secret has a length of XXH3_SECRET_DEFAULT_SIZE (necessarily).
+ * @secretBuffer must be already allocated, of size at least XXH3_SECRET_DEFAULT_SIZE bytes.
+ *
+ * The generated secret can be used in combination with
+ *`*_withSecret()` and `_withSecretandSeed()` variants.
+ * This generator is notably useful in combination with `_withSecretandSeed()`,
+ * as a way to emulate a faster `_withSeed()` variant.
+ */
+XXH_PUBLIC_API void XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed);
+
+/*
+ * *_withSecretandSeed() :
+ * These variants generate hash values using either
+ * @seed for "short" keys (< XXH3_MIDSIZE_MAX = 240 bytes)
+ * or @secret for "large" keys (>= XXH3_MIDSIZE_MAX).
+ *
+ * This generally benefits speed, compared to `_withSeed()` or `_withSecret()`.
+ * `_withSeed()` has to generate the secret on the fly for "large" keys.
+ * It's fast, but can be perceptible for "not so large" keys (< 1 KB).
+ * `_withSecret()` has to generate the masks on the fly for "small" keys,
+ * which requires more instructions than _withSeed() variants.
+ * Therefore, _withSecretandSeed variant combines the best of both worlds.
+ *
+ * When @secret has been generated by XXH3_generateSecret_fromSeed(),
+ * this variant produces *exactly* the same results as `_withSeed()` variant,
+ * hence offering only a pure speed benefit on "large" input,
+ * by skipping the need to regenerate the secret for every large input.
+ *
+ * Another usage scenario is to hash the secret to a 64-bit hash value,
+ * for example with XXH3_64bits(), which then becomes the seed,
+ * and then employ both the seed and the secret in _withSecretandSeed().
+ * On top of speed, an added benefit is that each bit in the secret
+ * has a 50% chance to swap each bit in the output,
+ * via its impact to the seed.
+ * This is not guaranteed when using the secret directly in "small data" scenarios,
+ * because only portions of the secret are employed for small data.
+ */
+XXH_PUBLIC_API XXH64_hash_t
+XXH3_64bits_withSecretandSeed(const void* data, size_t len,
+ const void* secret, size_t secretSize,
+ XXH64_hash_t seed);
+
+XXH_PUBLIC_API XXH128_hash_t
+XXH3_128bits_withSecretandSeed(const void* data, size_t len,
+ const void* secret, size_t secretSize,
+ XXH64_hash_t seed64);
+
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr,
+ const void* secret, size_t secretSize,
+ XXH64_hash_t seed64);
+
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr,
+ const void* secret, size_t secretSize,
+ XXH64_hash_t seed64);
+
+
+#endif /* XXH_NO_XXH3 */
+#endif /* XXH_NO_LONG_LONG */
+#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
+# define XXH_IMPLEMENTATION
+#endif
+
+#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */
+
+
+/* ======================================================================== */
+/* ======================================================================== */
+/* ======================================================================== */
+
+
+/*-**********************************************************************
+ * xxHash implementation
+ *-**********************************************************************
+ * xxHash's implementation used to be hosted inside xxhash.c.
+ *
+ * However, inlining requires implementation to be visible to the compiler,
+ * hence be included alongside the header.
+ * Previously, implementation was hosted inside xxhash.c,
+ * which was then #included when inlining was activated.
+ * This construction created issues with a few build and install systems,
+ * as it required xxhash.c to be stored in /include directory.
+ *
+ * xxHash implementation is now directly integrated within xxhash.h.
+ * As a consequence, xxhash.c is no longer needed in /include.
+ *
+ * xxhash.c is still available and is still useful.
+ * In a "normal" setup, when xxhash is not inlined,
+ * xxhash.h only exposes the prototypes and public symbols,
+ * while xxhash.c can be built into an object file xxhash.o
+ * which can then be linked into the final binary.
+ ************************************************************************/
+
+#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \
+ || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387)
+# define XXH_IMPLEM_13a8737387
+
+/* *************************************
+* Tuning parameters
+***************************************/
+
+/*!
+ * @defgroup tuning Tuning parameters
+ * @{
+ *
+ * Various macros to control xxHash's behavior.
+ */
+#ifdef XXH_DOXYGEN
+/*!
+ * @brief Define this to disable 64-bit code.
+ *
+ * Useful if only using the @ref xxh32_family and you have a strict C90 compiler.
+ */
+# define XXH_NO_LONG_LONG
+# undef XXH_NO_LONG_LONG /* don't actually */
+/*!
+ * @brief Controls how unaligned memory is accessed.
+ *
+ * By default, access to unaligned memory is controlled by `memcpy()`, which is
+ * safe and portable.
+ *
+ * Unfortunately, on some target/compiler combinations, the generated assembly
+ * is sub-optimal.
+ *
+ * The below switch allow selection of a different access method
+ * in the search for improved performance.
+ *
+ * @par Possible options:
+ *
+ * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy`
+ * @par
+ * Use `memcpy()`. Safe and portable. Note that most modern compilers will
+ * eliminate the function call and treat it as an unaligned access.
+ *
+ * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((packed))`
+ * @par
+ * Depends on compiler extensions and is therefore not portable.
+ * This method is safe _if_ your compiler supports it,
+ * and *generally* as fast or faster than `memcpy`.
+ *
+ * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast
+ * @par
+ * Casts directly and dereferences. This method doesn't depend on the
+ * compiler, but it violates the C standard as it directly dereferences an
+ * unaligned pointer. It can generate buggy code on targets which do not
+ * support unaligned memory accesses, but in some circumstances, it's the
+ * only known way to get the most performance.
+ *
+ * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift
+ * @par
+ * Also portable. This can generate the best code on old compilers which don't
+ * inline small `memcpy()` calls, and it might also be faster on big-endian
+ * systems which lack a native byteswap instruction. However, some compilers
+ * will emit literal byteshifts even if the target supports unaligned access.
+ * .
+ *
+ * @warning
+ * Methods 1 and 2 rely on implementation-defined behavior. Use these with
+ * care, as what works on one compiler/platform/optimization level may cause
+ * another to read garbage data or even crash.
+ *
+ * See http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html for details.
+ *
+ * Prefer these methods in priority order (0 > 3 > 1 > 2)
+ */
+# define XXH_FORCE_MEMORY_ACCESS 0
+
+/*!
+ * @def XXH_FORCE_ALIGN_CHECK
+ * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32()
+ * and XXH64() only).
+ *
+ * This is an important performance trick for architectures without decent
+ * unaligned memory access performance.
+ *
+ * It checks for input alignment, and when conditions are met, uses a "fast
+ * path" employing direct 32-bit/64-bit reads, resulting in _dramatically
+ * faster_ read speed.
+ *
+ * The check costs one initial branch per hash, which is generally negligible,
+ * but not zero.
+ *
+ * Moreover, it's not useful to generate an additional code path if memory
+ * access uses the same instruction for both aligned and unaligned
+ * addresses (e.g. x86 and aarch64).
+ *
+ * In these cases, the alignment check can be removed by setting this macro to 0.
+ * Then the code will always use unaligned memory access.
+ * Align check is automatically disabled on x86, x64 & arm64,
+ * which are platforms known to offer good unaligned memory accesses performance.
+ *
+ * This option does not affect XXH3 (only XXH32 and XXH64).
+ */
+# define XXH_FORCE_ALIGN_CHECK 0
+
+/*!
+ * @def XXH_NO_INLINE_HINTS
+ * @brief When non-zero, sets all functions to `static`.
+ *
+ * By default, xxHash tries to force the compiler to inline almost all internal
+ * functions.
+ *
+ * This can usually improve performance due to reduced jumping and improved
+ * constant folding, but significantly increases the size of the binary which
+ * might not be favorable.
+ *
+ * Additionally, sometimes the forced inlining can be detrimental to performance,
+ * depending on the architecture.
+ *
+ * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the
+ * compiler full control on whether to inline or not.
+ *
+ * When not optimizing (-O0), optimizing for size (-Os, -Oz), or using
+ * -fno-inline with GCC or Clang, this will automatically be defined.
+ */
+# define XXH_NO_INLINE_HINTS 0
+
+/*!
+ * @def XXH32_ENDJMP
+ * @brief Whether to use a jump for `XXH32_finalize`.
+ *
+ * For performance, `XXH32_finalize` uses multiple branches in the finalizer.
+ * This is generally preferable for performance,
+ * but depending on exact architecture, a jmp may be preferable.
+ *
+ * This setting is only possibly making a difference for very small inputs.
+ */
+# define XXH32_ENDJMP 0
+
+/*!
+ * @internal
+ * @brief Redefines old internal names.
+ *
+ * For compatibility with code that uses xxHash's internals before the names
+ * were changed to improve namespacing. There is no other reason to use this.
+ */
+# define XXH_OLD_NAMES
+# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */
+#endif /* XXH_DOXYGEN */
+/*!
+ * @}
+ */
+
+#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
+ /* prefer __packed__ structures (method 1) for gcc on armv7+ and mips */
+# if !defined(__clang__) && \
+( \
+ (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \
+ ( \
+ defined(__GNUC__) && ( \
+ (defined(__ARM_ARCH) && __ARM_ARCH >= 7) || \
+ ( \
+ defined(__mips__) && \
+ (__mips <= 5 || __mips_isa_rev < 6) && \
+ (!defined(__mips16) || defined(__mips_mips16e2)) \
+ ) \
+ ) \
+ ) \
+)
+# define XXH_FORCE_MEMORY_ACCESS 1
+# endif
+#endif
+
+#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
+# if defined(__i386) || defined(__x86_64__) || defined(__aarch64__) \
+ || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) /* visual */
+# define XXH_FORCE_ALIGN_CHECK 0
+# else
+# define XXH_FORCE_ALIGN_CHECK 1
+# endif
+#endif
+
+#ifndef XXH_NO_INLINE_HINTS
+# if defined(__OPTIMIZE_SIZE__) /* -Os, -Oz */ \
+ || defined(__NO_INLINE__) /* -O0, -fno-inline */
+# define XXH_NO_INLINE_HINTS 1
+# else
+# define XXH_NO_INLINE_HINTS 0
+# endif
+#endif
+
+#ifndef XXH32_ENDJMP
+/* generally preferable for performance */
+# define XXH32_ENDJMP 0
+#endif
+
+/*!
+ * @defgroup impl Implementation
+ * @{
+ */
+
+
+/* *************************************
+* Includes & Memory related functions
+***************************************/
+/* Modify the local functions below should you wish to use some other memory routines */
+/* for ZSTD_malloc(), ZSTD_free() */
+#define ZSTD_DEPS_NEED_MALLOC
+#include "zstd_deps.h" /* size_t, ZSTD_malloc, ZSTD_free, ZSTD_memcpy */
+static void* XXH_malloc(size_t s) { return ZSTD_malloc(s); }
+static void XXH_free (void* p) { ZSTD_free(p); }
+static void* XXH_memcpy(void* dest, const void* src, size_t size) { return ZSTD_memcpy(dest,src,size); }
+
+
+/* *************************************
+* Compiler Specific Options
+***************************************/
+#ifdef _MSC_VER /* Visual Studio warning fix */
+# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
+#endif
+
+#if XXH_NO_INLINE_HINTS /* disable inlining hints */
+# if defined(__GNUC__) || defined(__clang__)
+# define XXH_FORCE_INLINE static __attribute__((unused))
+# else
+# define XXH_FORCE_INLINE static
+# endif
+# define XXH_NO_INLINE static
+/* enable inlining hints */
+#elif defined(__GNUC__) || defined(__clang__)
+# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused))
+# define XXH_NO_INLINE static __attribute__((noinline))
+#elif defined(_MSC_VER) /* Visual Studio */
+# define XXH_FORCE_INLINE static __forceinline
+# define XXH_NO_INLINE static __declspec(noinline)
+#elif defined (__cplusplus) \
+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */
+# define XXH_FORCE_INLINE static inline
+# define XXH_NO_INLINE static
+#else
+# define XXH_FORCE_INLINE static
+# define XXH_NO_INLINE static
+#endif
+
+
+
+/* *************************************
+* Debug
+***************************************/
+/*!
+ * @ingroup tuning
+ * @def XXH_DEBUGLEVEL
+ * @brief Sets the debugging level.
+ *
+ * XXH_DEBUGLEVEL is expected to be defined externally, typically via the
+ * compiler's command line options. The value must be a number.
+ */
+#ifndef XXH_DEBUGLEVEL
+# ifdef DEBUGLEVEL /* backwards compat */
+# define XXH_DEBUGLEVEL DEBUGLEVEL
+# else
+# define XXH_DEBUGLEVEL 0
+# endif
+#endif
+
+#if (XXH_DEBUGLEVEL>=1)
+# include <assert.h> /* note: can still be disabled with NDEBUG */
+# define XXH_ASSERT(c) assert(c)
+#else
+# define XXH_ASSERT(c) ((void)0)
+#endif
+
+/* note: use after variable declarations */
+#ifndef XXH_STATIC_ASSERT
+# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */
+# include <assert.h>
+# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0)
+# elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */
+# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { static_assert((c),m); } while(0)
+# else
+# define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct xxh_sa { char x[(c) ? 1 : -1]; }; } while(0)
+# endif
+# define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c),#c)
+#endif
+
+/*!
+ * @internal
+ * @def XXH_COMPILER_GUARD(var)
+ * @brief Used to prevent unwanted optimizations for @p var.
+ *
+ * It uses an empty GCC inline assembly statement with a register constraint
+ * which forces @p var into a general purpose register (eg eax, ebx, ecx
+ * on x86) and marks it as modified.
+ *
+ * This is used in a few places to avoid unwanted autovectorization (e.g.
+ * XXH32_round()). All vectorization we want is explicit via intrinsics,
+ * and _usually_ isn't wanted elsewhere.
+ *
+ * We also use it to prevent unwanted constant folding for AArch64 in
+ * XXH3_initCustomSecret_scalar().
+ */
+#if defined(__GNUC__) || defined(__clang__)
+# define XXH_COMPILER_GUARD(var) __asm__ __volatile__("" : "+r" (var))
+#else
+# define XXH_COMPILER_GUARD(var) ((void)0)
+#endif
+
+/* *************************************
+* Basic Types
+***************************************/
+#if !defined (__VMS) \
+ && (defined (__cplusplus) \
+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
+# include <stdint.h>
+ typedef uint8_t xxh_u8;
+#else
+ typedef unsigned char xxh_u8;
+#endif
+typedef XXH32_hash_t xxh_u32;
+
+#ifdef XXH_OLD_NAMES
+# define BYTE xxh_u8
+# define U8 xxh_u8
+# define U32 xxh_u32
+#endif
+
+/* *** Memory access *** */
+
+/*!
+ * @internal
+ * @fn xxh_u32 XXH_read32(const void* ptr)
+ * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness.
+ *
+ * Affected by @ref XXH_FORCE_MEMORY_ACCESS.
+ *
+ * @param ptr The pointer to read from.
+ * @return The 32-bit native endian integer from the bytes at @p ptr.
+ */
+
+/*!
+ * @internal
+ * @fn xxh_u32 XXH_readLE32(const void* ptr)
+ * @brief Reads an unaligned 32-bit little endian integer from @p ptr.
+ *
+ * Affected by @ref XXH_FORCE_MEMORY_ACCESS.
+ *
+ * @param ptr The pointer to read from.
+ * @return The 32-bit little endian integer from the bytes at @p ptr.
+ */
+
+/*!
+ * @internal
+ * @fn xxh_u32 XXH_readBE32(const void* ptr)
+ * @brief Reads an unaligned 32-bit big endian integer from @p ptr.
+ *
+ * Affected by @ref XXH_FORCE_MEMORY_ACCESS.
+ *
+ * @param ptr The pointer to read from.
+ * @return The 32-bit big endian integer from the bytes at @p ptr.
+ */
+
+/*!
+ * @internal
+ * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align)
+ * @brief Like @ref XXH_readLE32(), but has an option for aligned reads.
+ *
+ * Affected by @ref XXH_FORCE_MEMORY_ACCESS.
+ * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is
+ * always @ref XXH_alignment::XXH_unaligned.
+ *
+ * @param ptr The pointer to read from.
+ * @param align Whether @p ptr is aligned.
+ * @pre
+ * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte
+ * aligned.
+ * @return The 32-bit little endian integer from the bytes at @p ptr.
+ */
+
+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
+/*
+ * Manual byteshift. Best for old compilers which don't inline memcpy.
+ * We actually directly use XXH_readLE32 and XXH_readBE32.
+ */
+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
+
+/*
+ * Force direct memory access. Only works on CPU which support unaligned memory
+ * access in hardware.
+ */
+static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; }
+
+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
+
+/*
+ * __pack instructions are safer but compiler specific, hence potentially
+ * problematic for some compilers.
+ *
+ * Currently only defined for GCC and ICC.
+ */
+#ifdef XXH_OLD_NAMES
+typedef union { xxh_u32 u32; } __attribute__((packed)) unalign;
+#endif
+static xxh_u32 XXH_read32(const void* ptr)
+{
+ typedef union { xxh_u32 u32; } __attribute__((packed)) xxh_unalign;
+ return ((const xxh_unalign*)ptr)->u32;
+}
+
+#else
+
+/*
+ * Portable and safe solution. Generally efficient.
+ * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
+ */
+static xxh_u32 XXH_read32(const void* memPtr)
+{
+ xxh_u32 val;
+ XXH_memcpy(&val, memPtr, sizeof(val));
+ return val;
+}
+
+#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
+
+
+/* *** Endianness *** */
+
+/*!
+ * @ingroup tuning
+ * @def XXH_CPU_LITTLE_ENDIAN
+ * @brief Whether the target is little endian.
+ *
+ * Defined to 1 if the target is little endian, or 0 if it is big endian.
+ * It can be defined externally, for example on the compiler command line.
+ *
+ * If it is not defined,
+ * a runtime check (which is usually constant folded) is used instead.
+ *
+ * @note
+ * This is not necessarily defined to an integer constant.
+ *
+ * @see XXH_isLittleEndian() for the runtime check.
+ */
+#ifndef XXH_CPU_LITTLE_ENDIAN
+/*
+ * Try to detect endianness automatically, to avoid the nonstandard behavior
+ * in `XXH_isLittleEndian()`
+ */
+# if defined(_WIN32) /* Windows is always little endian */ \
+ || defined(__LITTLE_ENDIAN__) \
+ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+# define XXH_CPU_LITTLE_ENDIAN 1
+# elif defined(__BIG_ENDIAN__) \
+ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define XXH_CPU_LITTLE_ENDIAN 0
+# else
+/*!
+ * @internal
+ * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN.
+ *
+ * Most compilers will constant fold this.
+ */
+static int XXH_isLittleEndian(void)
+{
+ /*
+ * Portable and well-defined behavior.
+ * Don't use static: it is detrimental to performance.
+ */
+ const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 };
+ return one.c[0];
+}
+# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
+# endif
+#endif
+
+
+
+
+/* ****************************************
+* Compiler-specific Functions and Macros
+******************************************/
+#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+
+#ifdef __has_builtin
+# define XXH_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define XXH_HAS_BUILTIN(x) 0
+#endif
+
+/*!
+ * @internal
+ * @def XXH_rotl32(x,r)
+ * @brief 32-bit rotate left.
+ *
+ * @param x The 32-bit integer to be rotated.
+ * @param r The number of bits to rotate.
+ * @pre
+ * @p r > 0 && @p r < 32
+ * @note
+ * @p x and @p r may be evaluated multiple times.
+ * @return The rotated result.
+ */
+#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \
+ && XXH_HAS_BUILTIN(__builtin_rotateleft64)
+# define XXH_rotl32 __builtin_rotateleft32
+# define XXH_rotl64 __builtin_rotateleft64
+/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */
+#elif defined(_MSC_VER)
+# define XXH_rotl32(x,r) _rotl(x,r)
+# define XXH_rotl64(x,r) _rotl64(x,r)
+#else
+# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
+#endif
+
+/*!
+ * @internal
+ * @fn xxh_u32 XXH_swap32(xxh_u32 x)
+ * @brief A 32-bit byteswap.
+ *
+ * @param x The 32-bit integer to byteswap.
+ * @return @p x, byteswapped.
+ */
+#if defined(_MSC_VER) /* Visual Studio */
+# define XXH_swap32 _byteswap_ulong
+#elif XXH_GCC_VERSION >= 403
+# define XXH_swap32 __builtin_bswap32
+#else
+static xxh_u32 XXH_swap32 (xxh_u32 x)
+{
+ return ((x << 24) & 0xff000000 ) |
+ ((x << 8) & 0x00ff0000 ) |
+ ((x >> 8) & 0x0000ff00 ) |
+ ((x >> 24) & 0x000000ff );
+}
+#endif
+
+
+/* ***************************
+* Memory reads
+*****************************/
+
+/*!
+ * @internal
+ * @brief Enum to indicate whether a pointer is aligned.
+ */
+typedef enum {
+ XXH_aligned, /*!< Aligned */
+ XXH_unaligned /*!< Possibly unaligned */
+} XXH_alignment;
+
+/*
+ * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load.
+ *
+ * This is ideal for older compilers which don't inline memcpy.
+ */
+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
+
+XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr)
+{
+ const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
+ return bytePtr[0]
+ | ((xxh_u32)bytePtr[1] << 8)
+ | ((xxh_u32)bytePtr[2] << 16)
+ | ((xxh_u32)bytePtr[3] << 24);
+}
+
+XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr)
+{
+ const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
+ return bytePtr[3]
+ | ((xxh_u32)bytePtr[2] << 8)
+ | ((xxh_u32)bytePtr[1] << 16)
+ | ((xxh_u32)bytePtr[0] << 24);
+}
+
+#else
+XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr)
+{
+ return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
+}
+
+static xxh_u32 XXH_readBE32(const void* ptr)
+{
+ return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
+}
+#endif
+
+XXH_FORCE_INLINE xxh_u32
+XXH_readLE32_align(const void* ptr, XXH_alignment align)
+{
+ if (align==XXH_unaligned) {
+ return XXH_readLE32(ptr);
+ } else {
+ return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr);
+ }
+}
+
+
+/* *************************************
+* Misc
+***************************************/
+/*! @ingroup public */
+XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
+
+
+/* *******************************************************************
+* 32-bit hash functions
+*********************************************************************/
+/*!
+ * @}
+ * @defgroup xxh32_impl XXH32 implementation
+ * @ingroup impl
+ * @{
+ */
+ /* #define instead of static const, to be used as initializers */
+#define XXH_PRIME32_1 0x9E3779B1U /*!< 0b10011110001101110111100110110001 */
+#define XXH_PRIME32_2 0x85EBCA77U /*!< 0b10000101111010111100101001110111 */
+#define XXH_PRIME32_3 0xC2B2AE3DU /*!< 0b11000010101100101010111000111101 */
+#define XXH_PRIME32_4 0x27D4EB2FU /*!< 0b00100111110101001110101100101111 */
+#define XXH_PRIME32_5 0x165667B1U /*!< 0b00010110010101100110011110110001 */
+
+#ifdef XXH_OLD_NAMES
+# define PRIME32_1 XXH_PRIME32_1
+# define PRIME32_2 XXH_PRIME32_2
+# define PRIME32_3 XXH_PRIME32_3
+# define PRIME32_4 XXH_PRIME32_4
+# define PRIME32_5 XXH_PRIME32_5
+#endif
+
+/*!
+ * @internal
+ * @brief Normal stripe processing routine.
+ *
+ * This shuffles the bits so that any bit from @p input impacts several bits in
+ * @p acc.
+ *
+ * @param acc The accumulator lane.
+ * @param input The stripe of input to mix.
+ * @return The mixed accumulator lane.
+ */
+static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)
+{
+ acc += input * XXH_PRIME32_2;
+ acc = XXH_rotl32(acc, 13);
+ acc *= XXH_PRIME32_1;
+#if (defined(__SSE4_1__) || defined(__aarch64__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)
+ /*
+ * UGLY HACK:
+ * A compiler fence is the only thing that prevents GCC and Clang from
+ * autovectorizing the XXH32 loop (pragmas and attributes don't work for some
+ * reason) without globally disabling SSE4.1.
+ *
+ * The reason we want to avoid vectorization is because despite working on
+ * 4 integers at a time, there are multiple factors slowing XXH32 down on
+ * SSE4:
+ * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on
+ * newer chips!) making it slightly slower to multiply four integers at
+ * once compared to four integers independently. Even when pmulld was
+ * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE
+ * just to multiply unless doing a long operation.
+ *
+ * - Four instructions are required to rotate,
+ * movqda tmp, v // not required with VEX encoding
+ * pslld tmp, 13 // tmp <<= 13
+ * psrld v, 19 // x >>= 19
+ * por v, tmp // x |= tmp
+ * compared to one for scalar:
+ * roll v, 13 // reliably fast across the board
+ * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason
+ *
+ * - Instruction level parallelism is actually more beneficial here because
+ * the SIMD actually serializes this operation: While v1 is rotating, v2
+ * can load data, while v3 can multiply. SSE forces them to operate
+ * together.
+ *
+ * This is also enabled on AArch64, as Clang autovectorizes it incorrectly
+ * and it is pointless writing a NEON implementation that is basically the
+ * same speed as scalar for XXH32.
+ */
+ XXH_COMPILER_GUARD(acc);
+#endif
+ return acc;
+}
+
+/*!
+ * @internal
+ * @brief Mixes all bits to finalize the hash.
+ *
+ * The final mix ensures that all input bits have a chance to impact any bit in
+ * the output digest, resulting in an unbiased distribution.
+ *
+ * @param h32 The hash to avalanche.
+ * @return The avalanched hash.
+ */
+static xxh_u32 XXH32_avalanche(xxh_u32 h32)
+{
+ h32 ^= h32 >> 15;
+ h32 *= XXH_PRIME32_2;
+ h32 ^= h32 >> 13;
+ h32 *= XXH_PRIME32_3;
+ h32 ^= h32 >> 16;
+ return(h32);
+}
+
+#define XXH_get32bits(p) XXH_readLE32_align(p, align)
+
+/*!
+ * @internal
+ * @brief Processes the last 0-15 bytes of @p ptr.
+ *
+ * There may be up to 15 bytes remaining to consume from the input.
+ * This final stage will digest them to ensure that all input bytes are present
+ * in the final mix.
+ *
+ * @param h32 The hash to finalize.
+ * @param ptr The pointer to the remaining input.
+ * @param len The remaining length, modulo 16.
+ * @param align Whether @p ptr is aligned.
+ * @return The finalized hash.
+ */
+static xxh_u32
+XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align)
+{
+#define XXH_PROCESS1 do { \
+ h32 += (*ptr++) * XXH_PRIME32_5; \
+ h32 = XXH_rotl32(h32, 11) * XXH_PRIME32_1; \
+} while (0)
+
+#define XXH_PROCESS4 do { \
+ h32 += XXH_get32bits(ptr) * XXH_PRIME32_3; \
+ ptr += 4; \
+ h32 = XXH_rotl32(h32, 17) * XXH_PRIME32_4; \
+} while (0)
+
+ if (ptr==NULL) XXH_ASSERT(len == 0);
+
+ /* Compact rerolled version; generally faster */
+ if (!XXH32_ENDJMP) {
+ len &= 15;
+ while (len >= 4) {
+ XXH_PROCESS4;
+ len -= 4;
+ }
+ while (len > 0) {
+ XXH_PROCESS1;
+ --len;
+ }
+ return XXH32_avalanche(h32);
+ } else {
+ switch(len&15) /* or switch(bEnd - p) */ {
+ case 12: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 8: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 4: XXH_PROCESS4;
+ return XXH32_avalanche(h32);
+
+ case 13: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 9: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 5: XXH_PROCESS4;
+ XXH_PROCESS1;
+ return XXH32_avalanche(h32);
+
+ case 14: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 10: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 6: XXH_PROCESS4;
+ XXH_PROCESS1;
+ XXH_PROCESS1;
+ return XXH32_avalanche(h32);
+
+ case 15: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 11: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 7: XXH_PROCESS4;
+ XXH_FALLTHROUGH;
+ case 3: XXH_PROCESS1;
+ XXH_FALLTHROUGH;
+ case 2: XXH_PROCESS1;
+ XXH_FALLTHROUGH;
+ case 1: XXH_PROCESS1;
+ XXH_FALLTHROUGH;
+ case 0: return XXH32_avalanche(h32);
+ }
+ XXH_ASSERT(0);
+ return h32; /* reaching this point is deemed impossible */
+ }
+}
+
+#ifdef XXH_OLD_NAMES
+# define PROCESS1 XXH_PROCESS1
+# define PROCESS4 XXH_PROCESS4
+#else
+# undef XXH_PROCESS1
+# undef XXH_PROCESS4
+#endif
+
+/*!
+ * @internal
+ * @brief The implementation for @ref XXH32().
+ *
+ * @param input , len , seed Directly passed from @ref XXH32().
+ * @param align Whether @p input is aligned.
+ * @return The calculated hash.
+ */
+XXH_FORCE_INLINE xxh_u32
+XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align)
+{
+ xxh_u32 h32;
+
+ if (input==NULL) XXH_ASSERT(len == 0);
+
+ if (len>=16) {
+ const xxh_u8* const bEnd = input + len;
+ const xxh_u8* const limit = bEnd - 15;
+ xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
+ xxh_u32 v2 = seed + XXH_PRIME32_2;
+ xxh_u32 v3 = seed + 0;
+ xxh_u32 v4 = seed - XXH_PRIME32_1;
+
+ do {
+ v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4;
+ v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4;
+ v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4;
+ v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4;
+ } while (input < limit);
+
+ h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7)
+ + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
+ } else {
+ h32 = seed + XXH_PRIME32_5;
+ }
+
+ h32 += (xxh_u32)len;
+
+ return XXH32_finalize(h32, input, len&15, align);
+}
+
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed)
+{
+#if 0
+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
+ XXH32_state_t state;
+ XXH32_reset(&state, seed);
+ XXH32_update(&state, (const xxh_u8*)input, len);
+ return XXH32_digest(&state);
+#else
+ if (XXH_FORCE_ALIGN_CHECK) {
+ if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
+ return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
+ } }
+
+ return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
+#endif
+}
+
+
+
+/******* Hash streaming *******/
+/*!
+ * @ingroup xxh32_family
+ */
+XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
+{
+ return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
+}
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
+{
+ XXH_free(statePtr);
+ return XXH_OK;
+}
+
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
+{
+ XXH_memcpy(dstState, srcState, sizeof(*dstState));
+}
+
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed)
+{
+ XXH_ASSERT(statePtr != NULL);
+ memset(statePtr, 0, sizeof(*statePtr));
+ statePtr->v[0] = seed + XXH_PRIME32_1 + XXH_PRIME32_2;
+ statePtr->v[1] = seed + XXH_PRIME32_2;
+ statePtr->v[2] = seed + 0;
+ statePtr->v[3] = seed - XXH_PRIME32_1;
+ return XXH_OK;
+}
+
+
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH32_update(XXH32_state_t* state, const void* input, size_t len)
+{
+ if (input==NULL) {
+ XXH_ASSERT(len == 0);
+ return XXH_OK;
+ }
+
+ { const xxh_u8* p = (const xxh_u8*)input;
+ const xxh_u8* const bEnd = p + len;
+
+ state->total_len_32 += (XXH32_hash_t)len;
+ state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));
+
+ if (state->memsize + len < 16) { /* fill in tmp buffer */
+ XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len);
+ state->memsize += (XXH32_hash_t)len;
+ return XXH_OK;
+ }
+
+ if (state->memsize) { /* some data left from previous update */
+ XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize);
+ { const xxh_u32* p32 = state->mem32;
+ state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p32)); p32++;
+ state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p32)); p32++;
+ state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p32)); p32++;
+ state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p32));
+ }
+ p += 16-state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p <= bEnd-16) {
+ const xxh_u8* const limit = bEnd - 16;
+
+ do {
+ state->v[0] = XXH32_round(state->v[0], XXH_readLE32(p)); p+=4;
+ state->v[1] = XXH32_round(state->v[1], XXH_readLE32(p)); p+=4;
+ state->v[2] = XXH32_round(state->v[2], XXH_readLE32(p)); p+=4;
+ state->v[3] = XXH32_round(state->v[3], XXH_readLE32(p)); p+=4;
+ } while (p<=limit);
+
+ }
+
+ if (p < bEnd) {
+ XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
+ state->memsize = (unsigned)(bEnd-p);
+ }
+ }
+
+ return XXH_OK;
+}
+
+
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state)
+{
+ xxh_u32 h32;
+
+ if (state->large_len) {
+ h32 = XXH_rotl32(state->v[0], 1)
+ + XXH_rotl32(state->v[1], 7)
+ + XXH_rotl32(state->v[2], 12)
+ + XXH_rotl32(state->v[3], 18);
+ } else {
+ h32 = state->v[2] /* == seed */ + XXH_PRIME32_5;
+ }
+
+ h32 += state->total_len_32;
+
+ return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned);
+}
+
+
+/******* Canonical representation *******/
+
+/*!
+ * @ingroup xxh32_family
+ * The default return values from XXH functions are unsigned 32 and 64 bit
+ * integers.
+ *
+ * The canonical representation uses big endian convention, the same convention
+ * as human-readable numbers (large digits first).
+ *
+ * This way, hash values can be written into a file or buffer, remaining
+ * comparable across different systems.
+ *
+ * The following functions allow transformation of hash values to and from their
+ * canonical format.
+ */
+XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
+{
+ /* XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); */
+ if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
+ XXH_memcpy(dst, &hash, sizeof(*dst));
+}
+/*! @ingroup xxh32_family */
+XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
+{
+ return XXH_readBE32(src);
+}
+
+
+#ifndef XXH_NO_LONG_LONG
+
+/* *******************************************************************
+* 64-bit hash functions
+*********************************************************************/
+/*!
+ * @}
+ * @ingroup impl
+ * @{
+ */
+/******* Memory access *******/
+
+typedef XXH64_hash_t xxh_u64;
+
+#ifdef XXH_OLD_NAMES
+# define U64 xxh_u64
+#endif
+
+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
+/*
+ * Manual byteshift. Best for old compilers which don't inline memcpy.
+ * We actually directly use XXH_readLE64 and XXH_readBE64.
+ */
+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
+
+/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
+static xxh_u64 XXH_read64(const void* memPtr)
+{
+ return *(const xxh_u64*) memPtr;
+}
+
+#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
+
+/*
+ * __pack instructions are safer, but compiler specific, hence potentially
+ * problematic for some compilers.
+ *
+ * Currently only defined for GCC and ICC.
+ */
+#ifdef XXH_OLD_NAMES
+typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64;
+#endif
+static xxh_u64 XXH_read64(const void* ptr)
+{
+ typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) xxh_unalign64;
+ return ((const xxh_unalign64*)ptr)->u64;
+}
+
+#else
+
+/*
+ * Portable and safe solution. Generally efficient.
+ * see: http://fastcompression.blogspot.com/2015/08/accessing-unaligned-memory.html
+ */
+static xxh_u64 XXH_read64(const void* memPtr)
+{
+ xxh_u64 val;
+ XXH_memcpy(&val, memPtr, sizeof(val));
+ return val;
+}
+
+#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
+
+#if defined(_MSC_VER) /* Visual Studio */
+# define XXH_swap64 _byteswap_uint64
+#elif XXH_GCC_VERSION >= 403
+# define XXH_swap64 __builtin_bswap64
+#else
+static xxh_u64 XXH_swap64(xxh_u64 x)
+{
+ return ((x << 56) & 0xff00000000000000ULL) |
+ ((x << 40) & 0x00ff000000000000ULL) |
+ ((x << 24) & 0x0000ff0000000000ULL) |
+ ((x << 8) & 0x000000ff00000000ULL) |
+ ((x >> 8) & 0x00000000ff000000ULL) |
+ ((x >> 24) & 0x0000000000ff0000ULL) |
+ ((x >> 40) & 0x000000000000ff00ULL) |
+ ((x >> 56) & 0x00000000000000ffULL);
+}
+#endif
+
+
+/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */
+#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3))
+
+XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr)
+{
+ const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
+ return bytePtr[0]
+ | ((xxh_u64)bytePtr[1] << 8)
+ | ((xxh_u64)bytePtr[2] << 16)
+ | ((xxh_u64)bytePtr[3] << 24)
+ | ((xxh_u64)bytePtr[4] << 32)
+ | ((xxh_u64)bytePtr[5] << 40)
+ | ((xxh_u64)bytePtr[6] << 48)
+ | ((xxh_u64)bytePtr[7] << 56);
+}
+
+XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr)
+{
+ const xxh_u8* bytePtr = (const xxh_u8 *)memPtr;
+ return bytePtr[7]
+ | ((xxh_u64)bytePtr[6] << 8)
+ | ((xxh_u64)bytePtr[5] << 16)
+ | ((xxh_u64)bytePtr[4] << 24)
+ | ((xxh_u64)bytePtr[3] << 32)
+ | ((xxh_u64)bytePtr[2] << 40)
+ | ((xxh_u64)bytePtr[1] << 48)
+ | ((xxh_u64)bytePtr[0] << 56);
+}
+
+#else
+XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr)
+{
+ return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
+}
+
+static xxh_u64 XXH_readBE64(const void* ptr)
+{
+ return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
+}
+#endif
+
+XXH_FORCE_INLINE xxh_u64
+XXH_readLE64_align(const void* ptr, XXH_alignment align)
+{
+ if (align==XXH_unaligned)
+ return XXH_readLE64(ptr);
+ else
+ return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr);
+}
+
+
+/******* xxh64 *******/
+/*!
+ * @}
+ * @defgroup xxh64_impl XXH64 implementation
+ * @ingroup impl
+ * @{
+ */
+/* #define rather that static const, to be used as initializers */
+#define XXH_PRIME64_1 0x9E3779B185EBCA87ULL /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */
+#define XXH_PRIME64_2 0xC2B2AE3D27D4EB4FULL /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */
+#define XXH_PRIME64_3 0x165667B19E3779F9ULL /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */
+#define XXH_PRIME64_4 0x85EBCA77C2B2AE63ULL /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */
+#define XXH_PRIME64_5 0x27D4EB2F165667C5ULL /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */
+
+#ifdef XXH_OLD_NAMES
+# define PRIME64_1 XXH_PRIME64_1
+# define PRIME64_2 XXH_PRIME64_2
+# define PRIME64_3 XXH_PRIME64_3
+# define PRIME64_4 XXH_PRIME64_4
+# define PRIME64_5 XXH_PRIME64_5
+#endif
+
+static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input)
+{
+ acc += input * XXH_PRIME64_2;
+ acc = XXH_rotl64(acc, 31);
+ acc *= XXH_PRIME64_1;
+ return acc;
+}
+
+static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val)
+{
+ val = XXH64_round(0, val);
+ acc ^= val;
+ acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4;
+ return acc;
+}
+
+static xxh_u64 XXH64_avalanche(xxh_u64 h64)
+{
+ h64 ^= h64 >> 33;
+ h64 *= XXH_PRIME64_2;
+ h64 ^= h64 >> 29;
+ h64 *= XXH_PRIME64_3;
+ h64 ^= h64 >> 32;
+ return h64;
+}
+
+
+#define XXH_get64bits(p) XXH_readLE64_align(p, align)
+
+static xxh_u64
+XXH64_finalize(xxh_u64 h64, const xxh_u8* ptr, size_t len, XXH_alignment align)
+{
+ if (ptr==NULL) XXH_ASSERT(len == 0);
+ len &= 31;
+ while (len >= 8) {
+ xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr));
+ ptr += 8;
+ h64 ^= k1;
+ h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4;
+ len -= 8;
+ }
+ if (len >= 4) {
+ h64 ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1;
+ ptr += 4;
+ h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3;
+ len -= 4;
+ }
+ while (len > 0) {
+ h64 ^= (*ptr++) * XXH_PRIME64_5;
+ h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1;
+ --len;
+ }
+ return XXH64_avalanche(h64);
+}
+
+#ifdef XXH_OLD_NAMES
+# define PROCESS1_64 XXH_PROCESS1_64
+# define PROCESS4_64 XXH_PROCESS4_64
+# define PROCESS8_64 XXH_PROCESS8_64
+#else
+# undef XXH_PROCESS1_64
+# undef XXH_PROCESS4_64
+# undef XXH_PROCESS8_64
+#endif
+
+XXH_FORCE_INLINE xxh_u64
+XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align)
+{
+ xxh_u64 h64;
+ if (input==NULL) XXH_ASSERT(len == 0);
+
+ if (len>=32) {
+ const xxh_u8* const bEnd = input + len;
+ const xxh_u8* const limit = bEnd - 31;
+ xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
+ xxh_u64 v2 = seed + XXH_PRIME64_2;
+ xxh_u64 v3 = seed + 0;
+ xxh_u64 v4 = seed - XXH_PRIME64_1;
+
+ do {
+ v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8;
+ v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8;
+ v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8;
+ v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8;
+ } while (input<limit);
+
+ h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
+ h64 = XXH64_mergeRound(h64, v1);
+ h64 = XXH64_mergeRound(h64, v2);
+ h64 = XXH64_mergeRound(h64, v3);
+ h64 = XXH64_mergeRound(h64, v4);
+
+ } else {
+ h64 = seed + XXH_PRIME64_5;
+ }
+
+ h64 += (xxh_u64) len;
+
+ return XXH64_finalize(h64, input, len, align);
+}
+
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t len, XXH64_hash_t seed)
+{
+#if 0
+ /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
+ XXH64_state_t state;
+ XXH64_reset(&state, seed);
+ XXH64_update(&state, (const xxh_u8*)input, len);
+ return XXH64_digest(&state);
+#else
+ if (XXH_FORCE_ALIGN_CHECK) {
+ if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
+ return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
+ } }
+
+ return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
+
+#endif
+}
+
+/******* Hash Streaming *******/
+
+/*! @ingroup xxh64_family*/
+XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
+{
+ return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
+}
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
+{
+ XXH_free(statePtr);
+ return XXH_OK;
+}
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState)
+{
+ XXH_memcpy(dstState, srcState, sizeof(*dstState));
+}
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, XXH64_hash_t seed)
+{
+ XXH_ASSERT(statePtr != NULL);
+ memset(statePtr, 0, sizeof(*statePtr));
+ statePtr->v[0] = seed + XXH_PRIME64_1 + XXH_PRIME64_2;
+ statePtr->v[1] = seed + XXH_PRIME64_2;
+ statePtr->v[2] = seed + 0;
+ statePtr->v[3] = seed - XXH_PRIME64_1;
+ return XXH_OK;
+}
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH64_update (XXH64_state_t* state, const void* input, size_t len)
+{
+ if (input==NULL) {
+ XXH_ASSERT(len == 0);
+ return XXH_OK;
+ }
+
+ { const xxh_u8* p = (const xxh_u8*)input;
+ const xxh_u8* const bEnd = p + len;
+
+ state->total_len += len;
+
+ if (state->memsize + len < 32) { /* fill in tmp buffer */
+ XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len);
+ state->memsize += (xxh_u32)len;
+ return XXH_OK;
+ }
+
+ if (state->memsize) { /* tmp buffer is full */
+ XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize);
+ state->v[0] = XXH64_round(state->v[0], XXH_readLE64(state->mem64+0));
+ state->v[1] = XXH64_round(state->v[1], XXH_readLE64(state->mem64+1));
+ state->v[2] = XXH64_round(state->v[2], XXH_readLE64(state->mem64+2));
+ state->v[3] = XXH64_round(state->v[3], XXH_readLE64(state->mem64+3));
+ p += 32 - state->memsize;
+ state->memsize = 0;
+ }
+
+ if (p+32 <= bEnd) {
+ const xxh_u8* const limit = bEnd - 32;
+
+ do {
+ state->v[0] = XXH64_round(state->v[0], XXH_readLE64(p)); p+=8;
+ state->v[1] = XXH64_round(state->v[1], XXH_readLE64(p)); p+=8;
+ state->v[2] = XXH64_round(state->v[2], XXH_readLE64(p)); p+=8;
+ state->v[3] = XXH64_round(state->v[3], XXH_readLE64(p)); p+=8;
+ } while (p<=limit);
+
+ }
+
+ if (p < bEnd) {
+ XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
+ state->memsize = (unsigned)(bEnd-p);
+ }
+ }
+
+ return XXH_OK;
+}
+
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t* state)
+{
+ xxh_u64 h64;
+
+ if (state->total_len >= 32) {
+ h64 = XXH_rotl64(state->v[0], 1) + XXH_rotl64(state->v[1], 7) + XXH_rotl64(state->v[2], 12) + XXH_rotl64(state->v[3], 18);
+ h64 = XXH64_mergeRound(h64, state->v[0]);
+ h64 = XXH64_mergeRound(h64, state->v[1]);
+ h64 = XXH64_mergeRound(h64, state->v[2]);
+ h64 = XXH64_mergeRound(h64, state->v[3]);
+ } else {
+ h64 = state->v[2] /*seed*/ + XXH_PRIME64_5;
+ }
+
+ h64 += (xxh_u64) state->total_len;
+
+ return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned);
+}
+
+
+/******* Canonical representation *******/
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
+{
+ /* XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); */
+ if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
+ XXH_memcpy(dst, &hash, sizeof(*dst));
+}
+
+/*! @ingroup xxh64_family */
+XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
+{
+ return XXH_readBE64(src);
+}
+
+#ifndef XXH_NO_XXH3
+
+/* *********************************************************************
+* XXH3
+* New generation hash designed for speed on small keys and vectorization
+************************************************************************ */
+/*!
+ * @}
+ * @defgroup xxh3_impl XXH3 implementation
+ * @ingroup impl
+ * @{
+ */
+
+/* === Compiler specifics === */
+
+#if ((defined(sun) || defined(__sun)) && __cplusplus) /* Solaris includes __STDC_VERSION__ with C++. Tested with GCC 5.5 */
+# define XXH_RESTRICT /* disable */
+#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */
+# define XXH_RESTRICT restrict
+#else
+/* Note: it might be useful to define __restrict or __restrict__ for some C++ compilers */
+# define XXH_RESTRICT /* disable */
+#endif
+
+#if (defined(__GNUC__) && (__GNUC__ >= 3)) \
+ || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \
+ || defined(__clang__)
+# define XXH_likely(x) __builtin_expect(x, 1)
+# define XXH_unlikely(x) __builtin_expect(x, 0)
+#else
+# define XXH_likely(x) (x)
+# define XXH_unlikely(x) (x)
+#endif
+
+#if defined(__GNUC__) || defined(__clang__)
+# if defined(__ARM_NEON__) || defined(__ARM_NEON) \
+ || defined(__aarch64__) || defined(_M_ARM) \
+ || defined(_M_ARM64) || defined(_M_ARM64EC)
+# define inline __inline__ /* circumvent a clang bug */
+# include <arm_neon.h>
+# undef inline
+# elif defined(__AVX2__)
+# include <immintrin.h>
+# elif defined(__SSE2__)
+# include <emmintrin.h>
# endif
+#endif
+
+#if defined(_MSC_VER)
+# include <intrin.h>
+#endif
+
+/*
+ * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while
+ * remaining a true 64-bit/128-bit hash function.
+ *
+ * This is done by prioritizing a subset of 64-bit operations that can be
+ * emulated without too many steps on the average 32-bit machine.
+ *
+ * For example, these two lines seem similar, and run equally fast on 64-bit:
+ *
+ * xxh_u64 x;
+ * x ^= (x >> 47); // good
+ * x ^= (x >> 13); // bad
+ *
+ * However, to a 32-bit machine, there is a major difference.
+ *
+ * x ^= (x >> 47) looks like this:
+ *
+ * x.lo ^= (x.hi >> (47 - 32));
+ *
+ * while x ^= (x >> 13) looks like this:
+ *
+ * // note: funnel shifts are not usually cheap.
+ * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13));
+ * x.hi ^= (x.hi >> 13);
+ *
+ * The first one is significantly faster than the second, simply because the
+ * shift is larger than 32. This means:
+ * - All the bits we need are in the upper 32 bits, so we can ignore the lower
+ * 32 bits in the shift.
+ * - The shift result will always fit in the lower 32 bits, and therefore,
+ * we can ignore the upper 32 bits in the xor.
+ *
+ * Thanks to this optimization, XXH3 only requires these features to be efficient:
+ *
+ * - Usable unaligned access
+ * - A 32-bit or 64-bit ALU
+ * - If 32-bit, a decent ADC instruction
+ * - A 32 or 64-bit multiply with a 64-bit result
+ * - For the 128-bit variant, a decent byteswap helps short inputs.
+ *
+ * The first two are already required by XXH32, and almost all 32-bit and 64-bit
+ * platforms which can run XXH32 can run XXH3 efficiently.
+ *
+ * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one
+ * notable exception.
+ *
+ * First of all, Thumb-1 lacks support for the UMULL instruction which
+ * performs the important long multiply. This means numerous __aeabi_lmul
+ * calls.
+ *
+ * Second of all, the 8 functional registers are just not enough.
+ * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need
+ * Lo registers, and this shuffling results in thousands more MOVs than A32.
+ *
+ * A32 and T32 don't have this limitation. They can access all 14 registers,
+ * do a 32->64 multiply with UMULL, and the flexible operand allowing free
+ * shifts is helpful, too.
+ *
+ * Therefore, we do a quick sanity check.
+ *
+ * If compiling Thumb-1 for a target which supports ARM instructions, we will
+ * emit a warning, as it is not a "sane" platform to compile for.
+ *
+ * Usually, if this happens, it is because of an accident and you probably need
+ * to specify -march, as you likely meant to compile for a newer architecture.
+ *
+ * Credit: large sections of the vectorial and asm source code paths
+ * have been contributed by @easyaspi314
+ */
+#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM)
+# warning "XXH3 is highly inefficient without ARM or Thumb-2."
+#endif
+
+/* ==========================================
+ * Vectorization detection
+ * ========================================== */
+
+#ifdef XXH_DOXYGEN
+/*!
+ * @ingroup tuning
+ * @brief Overrides the vectorization implementation chosen for XXH3.
+ *
+ * Can be defined to 0 to disable SIMD or any of the values mentioned in
+ * @ref XXH_VECTOR_TYPE.
+ *
+ * If this is not defined, it uses predefined macros to determine the best
+ * implementation.
+ */
+# define XXH_VECTOR XXH_SCALAR
+/*!
+ * @ingroup tuning
+ * @brief Possible values for @ref XXH_VECTOR.
+ *
+ * Note that these are actually implemented as macros.
+ *
+ * If this is not defined, it is detected automatically.
+ * @ref XXH_X86DISPATCH overrides this.
+ */
+enum XXH_VECTOR_TYPE /* fake enum */ {
+ XXH_SCALAR = 0, /*!< Portable scalar version */
+ XXH_SSE2 = 1, /*!<
+ * SSE2 for Pentium 4, Opteron, all x86_64.
+ *
+ * @note SSE2 is also guaranteed on Windows 10, macOS, and
+ * Android x86.
+ */
+ XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */
+ XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */
+ XXH_NEON = 4, /*!< NEON for most ARMv7-A and all AArch64 */
+ XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */
+};
+/*!
+ * @ingroup tuning
+ * @brief Selects the minimum alignment for XXH3's accumulators.
+ *
+ * When using SIMD, this should match the alignment reqired for said vector
+ * type, so, for example, 32 for AVX2.
+ *
+ * Default: Auto detected.
+ */
+# define XXH_ACC_ALIGN 8
+#endif
+
+/* Actual definition */
+#ifndef XXH_DOXYGEN
+# define XXH_SCALAR 0
+# define XXH_SSE2 1
+# define XXH_AVX2 2
+# define XXH_AVX512 3
+# define XXH_NEON 4
+# define XXH_VSX 5
+#endif
+
+#ifndef XXH_VECTOR /* can be defined on command line */
+# if ( \
+ defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \
+ || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \
+ ) && ( \
+ defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \
+ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
+ )
+# define XXH_VECTOR XXH_NEON
+# elif defined(__AVX512F__)
+# define XXH_VECTOR XXH_AVX512
+# elif defined(__AVX2__)
+# define XXH_VECTOR XXH_AVX2
+# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2))
+# define XXH_VECTOR XXH_SSE2
+# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \
+ || (defined(__s390x__) && defined(__VEC__)) \
+ && defined(__GNUC__) /* TODO: IBM XL */
+# define XXH_VECTOR XXH_VSX
+# else
+# define XXH_VECTOR XXH_SCALAR
+# endif
+#endif
+
+/*
+ * Controls the alignment of the accumulator,
+ * for compatibility with aligned vector loads, which are usually faster.
+ */
+#ifndef XXH_ACC_ALIGN
+# if defined(XXH_X86DISPATCH)
+# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */
+# elif XXH_VECTOR == XXH_SCALAR /* scalar */
+# define XXH_ACC_ALIGN 8
+# elif XXH_VECTOR == XXH_SSE2 /* sse2 */
+# define XXH_ACC_ALIGN 16
+# elif XXH_VECTOR == XXH_AVX2 /* avx2 */
+# define XXH_ACC_ALIGN 32
+# elif XXH_VECTOR == XXH_NEON /* neon */
+# define XXH_ACC_ALIGN 16
+# elif XXH_VECTOR == XXH_VSX /* vsx */
+# define XXH_ACC_ALIGN 16
+# elif XXH_VECTOR == XXH_AVX512 /* avx512 */
+# define XXH_ACC_ALIGN 64
+# endif
+#endif
+
+#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \
+ || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512
+# define XXH_SEC_ALIGN XXH_ACC_ALIGN
+#else
+# define XXH_SEC_ALIGN 8
+#endif
+
+/*
+ * UGLY HACK:
+ * GCC usually generates the best code with -O3 for xxHash.
+ *
+ * However, when targeting AVX2, it is overzealous in its unrolling resulting
+ * in code roughly 3/4 the speed of Clang.
+ *
+ * There are other issues, such as GCC splitting _mm256_loadu_si256 into
+ * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which
+ * only applies to Sandy and Ivy Bridge... which don't even support AVX2.
+ *
+ * That is why when compiling the AVX2 version, it is recommended to use either
+ * -O2 -mavx2 -march=haswell
+ * or
+ * -O2 -mavx2 -mno-avx256-split-unaligned-load
+ * for decent performance, or to use Clang instead.
+ *
+ * Fortunately, we can control the first one with a pragma that forces GCC into
+ * -O2, but the other one we can't control without "failed to inline always
+ * inline function due to target mismatch" warnings.
+ */
+#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \
+ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
+ && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */
+# pragma GCC push_options
+# pragma GCC optimize("-O2")
+#endif
+
+
+#if XXH_VECTOR == XXH_NEON
+/*
+ * NEON's setup for vmlal_u32 is a little more complicated than it is on
+ * SSE2, AVX2, and VSX.
+ *
+ * While PMULUDQ and VMULEUW both perform a mask, VMLAL.U32 performs an upcast.
+ *
+ * To do the same operation, the 128-bit 'Q' register needs to be split into
+ * two 64-bit 'D' registers, performing this operation::
+ *
+ * [ a | b ]
+ * | '---------. .--------' |
+ * | x |
+ * | .---------' '--------. |
+ * [ a & 0xFFFFFFFF | b & 0xFFFFFFFF ],[ a >> 32 | b >> 32 ]
+ *
+ * Due to significant changes in aarch64, the fastest method for aarch64 is
+ * completely different than the fastest method for ARMv7-A.
+ *
+ * ARMv7-A treats D registers as unions overlaying Q registers, so modifying
+ * D11 will modify the high half of Q5. This is similar to how modifying AH
+ * will only affect bits 8-15 of AX on x86.
+ *
+ * VZIP takes two registers, and puts even lanes in one register and odd lanes
+ * in the other.
+ *
+ * On ARMv7-A, this strangely modifies both parameters in place instead of
+ * taking the usual 3-operand form.
+ *
+ * Therefore, if we want to do this, we can simply use a D-form VZIP.32 on the
+ * lower and upper halves of the Q register to end up with the high and low
+ * halves where we want - all in one instruction.
+ *
+ * vzip.32 d10, d11 @ d10 = { d10[0], d11[0] }; d11 = { d10[1], d11[1] }
+ *
+ * Unfortunately we need inline assembly for this: Instructions modifying two
+ * registers at once is not possible in GCC or Clang's IR, and they have to
+ * create a copy.
+ *
+ * aarch64 requires a different approach.
+ *
+ * In order to make it easier to write a decent compiler for aarch64, many
+ * quirks were removed, such as conditional execution.
+ *
+ * NEON was also affected by this.
+ *
+ * aarch64 cannot access the high bits of a Q-form register, and writes to a
+ * D-form register zero the high bits, similar to how writes to W-form scalar
+ * registers (or DWORD registers on x86_64) work.
+ *
+ * The formerly free vget_high intrinsics now require a vext (with a few
+ * exceptions)
+ *
+ * Additionally, VZIP was replaced by ZIP1 and ZIP2, which are the equivalent
+ * of PUNPCKL* and PUNPCKH* in SSE, respectively, in order to only modify one
+ * operand.
+ *
+ * The equivalent of the VZIP.32 on the lower and upper halves would be this
+ * mess:
+ *
+ * ext v2.4s, v0.4s, v0.4s, #2 // v2 = { v0[2], v0[3], v0[0], v0[1] }
+ * zip1 v1.2s, v0.2s, v2.2s // v1 = { v0[0], v2[0] }
+ * zip2 v0.2s, v0.2s, v1.2s // v0 = { v0[1], v2[1] }
+ *
+ * Instead, we use a literal downcast, vmovn_u64 (XTN), and vshrn_n_u64 (SHRN):
+ *
+ * shrn v1.2s, v0.2d, #32 // v1 = (uint32x2_t)(v0 >> 32);
+ * xtn v0.2s, v0.2d // v0 = (uint32x2_t)(v0 & 0xFFFFFFFF);
+ *
+ * This is available on ARMv7-A, but is less efficient than a single VZIP.32.
+ */
+
+/*!
+ * Function-like macro:
+ * void XXH_SPLIT_IN_PLACE(uint64x2_t &in, uint32x2_t &outLo, uint32x2_t &outHi)
+ * {
+ * outLo = (uint32x2_t)(in & 0xFFFFFFFF);
+ * outHi = (uint32x2_t)(in >> 32);
+ * in = UNDEFINED;
+ * }
+ */
+# if !defined(XXH_NO_VZIP_HACK) /* define to disable */ \
+ && (defined(__GNUC__) || defined(__clang__)) \
+ && (defined(__arm__) || defined(__thumb__) || defined(_M_ARM))
+# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \
+ do { \
+ /* Undocumented GCC/Clang operand modifier: %e0 = lower D half, %f0 = upper D half */ \
+ /* https://github.com/gcc-mirror/gcc/blob/38cf91e5/gcc/config/arm/arm.c#L22486 */ \
+ /* https://github.com/llvm-mirror/llvm/blob/2c4ca683/lib/Target/ARM/ARMAsmPrinter.cpp#L399 */ \
+ __asm__("vzip.32 %e0, %f0" : "+w" (in)); \
+ (outLo) = vget_low_u32 (vreinterpretq_u32_u64(in)); \
+ (outHi) = vget_high_u32(vreinterpretq_u32_u64(in)); \
+ } while (0)
+# else
+# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \
+ do { \
+ (outLo) = vmovn_u64 (in); \
+ (outHi) = vshrn_n_u64 ((in), 32); \
+ } while (0)
+# endif
+
+/*!
+ * @ingroup tuning
+ * @brief Controls the NEON to scalar ratio for XXH3
+ *
+ * On AArch64 when not optimizing for size, XXH3 will run 6 lanes using NEON and
+ * 2 lanes on scalar by default.
+ *
+ * This can be set to 2, 4, 6, or 8. ARMv7 will default to all 8 NEON lanes, as the
+ * emulated 64-bit arithmetic is too slow.
+ *
+ * Modern ARM CPUs are _very_ sensitive to how their pipelines are used.
+ *
+ * For example, the Cortex-A73 can dispatch 3 micro-ops per cycle, but it can't
+ * have more than 2 NEON (F0/F1) micro-ops. If you are only using NEON instructions,
+ * you are only using 2/3 of the CPU bandwidth.
+ *
+ * This is even more noticable on the more advanced cores like the A76 which
+ * can dispatch 8 micro-ops per cycle, but still only 2 NEON micro-ops at once.
+ *
+ * Therefore, @ref XXH3_NEON_LANES lanes will be processed using NEON, and the
+ * remaining lanes will use scalar instructions. This improves the bandwidth
+ * and also gives the integer pipelines something to do besides twiddling loop
+ * counters and pointers.
+ *
+ * This change benefits CPUs with large micro-op buffers without negatively affecting
+ * other CPUs:
+ *
+ * | Chipset | Dispatch type | NEON only | 6:2 hybrid | Diff. |
+ * |:----------------------|:--------------------|----------:|-----------:|------:|
+ * | Snapdragon 730 (A76) | 2 NEON/8 micro-ops | 8.8 GB/s | 10.1 GB/s | ~16% |
+ * | Snapdragon 835 (A73) | 2 NEON/3 micro-ops | 5.1 GB/s | 5.3 GB/s | ~5% |
+ * | Marvell PXA1928 (A53) | In-order dual-issue | 1.9 GB/s | 1.9 GB/s | 0% |
+ *
+ * It also seems to fix some bad codegen on GCC, making it almost as fast as clang.
+ *
+ * @see XXH3_accumulate_512_neon()
+ */
+# ifndef XXH3_NEON_LANES
+# if (defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) || defined(_M_ARM64EC)) \
+ && !defined(__OPTIMIZE_SIZE__)
+# define XXH3_NEON_LANES 6
+# else
+# define XXH3_NEON_LANES XXH_ACC_NB
+# endif
+# endif
+#endif /* XXH_VECTOR == XXH_NEON */
+
+/*
+ * VSX and Z Vector helpers.
+ *
+ * This is very messy, and any pull requests to clean this up are welcome.
+ *
+ * There are a lot of problems with supporting VSX and s390x, due to
+ * inconsistent intrinsics, spotty coverage, and multiple endiannesses.
+ */
+#if XXH_VECTOR == XXH_VSX
+# if defined(__s390x__)
+# include <s390intrin.h>
+# else
+/* gcc's altivec.h can have the unwanted consequence to unconditionally
+ * #define bool, vector, and pixel keywords,
+ * with bad consequences for programs already using these keywords for other purposes.
+ * The paragraph defining these macros is skipped when __APPLE_ALTIVEC__ is defined.
+ * __APPLE_ALTIVEC__ is _generally_ defined automatically by the compiler,
+ * but it seems that, in some cases, it isn't.
+ * Force the build macro to be defined, so that keywords are not altered.
+ */
+# if defined(__GNUC__) && !defined(__APPLE_ALTIVEC__)
+# define __APPLE_ALTIVEC__
+# endif
+# include <altivec.h>
+# endif
+
+typedef __vector unsigned long long xxh_u64x2;
+typedef __vector unsigned char xxh_u8x16;
+typedef __vector unsigned xxh_u32x4;
+
+# ifndef XXH_VSX_BE
+# if defined(__BIG_ENDIAN__) \
+ || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+# define XXH_VSX_BE 1
+# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__
+# warning "-maltivec=be is not recommended. Please use native endianness."
+# define XXH_VSX_BE 1
+# else
+# define XXH_VSX_BE 0
+# endif
+# endif /* !defined(XXH_VSX_BE) */
+
+# if XXH_VSX_BE
+# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__))
+# define XXH_vec_revb vec_revb
+# else
+/*!
+ * A polyfill for POWER9's vec_revb().
+ */
+XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val)
+{
+ xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
+ 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 };
+ return vec_perm(val, val, vByteSwap);
+}
+# endif
+# endif /* XXH_VSX_BE */
+
+/*!
+ * Performs an unaligned vector load and byte swaps it on big endian.
+ */
+XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr)
+{
+ xxh_u64x2 ret;
+ XXH_memcpy(&ret, ptr, sizeof(xxh_u64x2));
+# if XXH_VSX_BE
+ ret = XXH_vec_revb(ret);
+# endif
+ return ret;
+}
+
+/*
+ * vec_mulo and vec_mule are very problematic intrinsics on PowerPC
+ *
+ * These intrinsics weren't added until GCC 8, despite existing for a while,
+ * and they are endian dependent. Also, their meaning swap depending on version.
+ * */
+# if defined(__s390x__)
+ /* s390x is always big endian, no issue on this platform */
+# define XXH_vec_mulo vec_mulo
+# define XXH_vec_mule vec_mule
+# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw)
+/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */
+# define XXH_vec_mulo __builtin_altivec_vmulouw
+# define XXH_vec_mule __builtin_altivec_vmuleuw
+# else
+/* gcc needs inline assembly */
+/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */
+XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b)
+{
+ xxh_u64x2 result;
+ __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b));
+ return result;
+}
+XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b)
+{
+ xxh_u64x2 result;
+ __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b));
+ return result;
+}
+# endif /* XXH_vec_mulo, XXH_vec_mule */
+#endif /* XXH_VECTOR == XXH_VSX */
+
+
+/* prefetch
+ * can be disabled, by declaring XXH_NO_PREFETCH build macro */
+#if defined(XXH_NO_PREFETCH)
+# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */
+#else
+# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */
+# include <mmintrin.h> /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */
+# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0)
+# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) )
+# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */)
+# else
+# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */
+# endif
+#endif /* XXH_NO_PREFETCH */
+
+
+/* ==========================================
+ * XXH3 default settings
+ * ========================================== */
+
+#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */
+
+#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN)
+# error "default keyset is not large enough"
+#endif
+
+/*! Pseudorandom secret taken directly from FARSH. */
+XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {
+ 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
+ 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
+ 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
+ 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c,
+ 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3,
+ 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8,
+ 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d,
+ 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64,
+ 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb,
+ 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e,
+ 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce,
+ 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
+};
+
+
+#ifdef XXH_OLD_NAMES
+# define kSecret XXH3_kSecret
+#endif
+
+#ifdef XXH_DOXYGEN
+/*!
+ * @brief Calculates a 32-bit to 64-bit long multiply.
+ *
+ * Implemented as a macro.
+ *
+ * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't
+ * need to (but it shouldn't need to anyways, it is about 7 instructions to do
+ * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we
+ * use that instead of the normal method.
+ *
+ * If you are compiling for platforms like Thumb-1 and don't have a better option,
+ * you may also want to write your own long multiply routine here.
+ *
+ * @param x, y Numbers to be multiplied
+ * @return 64-bit product of the low 32 bits of @p x and @p y.
+ */
+XXH_FORCE_INLINE xxh_u64
+XXH_mult32to64(xxh_u64 x, xxh_u64 y)
+{
+ return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF);
+}
+#elif defined(_MSC_VER) && defined(_M_IX86)
+# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y))
+#else
+/*
+ * Downcast + upcast is usually better than masking on older compilers like
+ * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers.
+ *
+ * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands
+ * and perform a full 64x64 multiply -- entirely redundant on 32-bit.
+ */
+# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y))
+#endif
+
+/*!
+ * @brief Calculates a 64->128-bit long multiply.
+ *
+ * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar
+ * version.
+ *
+ * @param lhs , rhs The 64-bit integers to be multiplied
+ * @return The 128-bit result represented in an @ref XXH128_hash_t.
+ */
+static XXH128_hash_t
+XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs)
+{
+ /*
+ * GCC/Clang __uint128_t method.
+ *
+ * On most 64-bit targets, GCC and Clang define a __uint128_t type.
+ * This is usually the best way as it usually uses a native long 64-bit
+ * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64.
+ *
+ * Usually.
+ *
+ * Despite being a 32-bit platform, Clang (and emscripten) define this type
+ * despite not having the arithmetic for it. This results in a laggy
+ * compiler builtin call which calculates a full 128-bit multiply.
+ * In that case it is best to use the portable one.
+ * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677
+ */
+#if (defined(__GNUC__) || defined(__clang__)) && !defined(__wasm__) \
+ && defined(__SIZEOF_INT128__) \
+ || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128)
+
+ __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs;
+ XXH128_hash_t r128;
+ r128.low64 = (xxh_u64)(product);
+ r128.high64 = (xxh_u64)(product >> 64);
+ return r128;
+
+ /*
+ * MSVC for x64's _umul128 method.
+ *
+ * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct);
+ *
+ * This compiles to single operand MUL on x64.
+ */
+#elif (defined(_M_X64) || defined(_M_IA64)) && !defined(_M_ARM64EC)
+
+#ifndef _MSC_VER
+# pragma intrinsic(_umul128)
+#endif
+ xxh_u64 product_high;
+ xxh_u64 const product_low = _umul128(lhs, rhs, &product_high);
+ XXH128_hash_t r128;
+ r128.low64 = product_low;
+ r128.high64 = product_high;
+ return r128;
+
+ /*
+ * MSVC for ARM64's __umulh method.
+ *
+ * This compiles to the same MUL + UMULH as GCC/Clang's __uint128_t method.
+ */
+#elif defined(_M_ARM64) || defined(_M_ARM64EC)
+
+#ifndef _MSC_VER
+# pragma intrinsic(__umulh)
+#endif
+ XXH128_hash_t r128;
+ r128.low64 = lhs * rhs;
+ r128.high64 = __umulh(lhs, rhs);
+ return r128;
+
+#else
+ /*
+ * Portable scalar method. Optimized for 32-bit and 64-bit ALUs.
+ *
+ * This is a fast and simple grade school multiply, which is shown below
+ * with base 10 arithmetic instead of base 0x100000000.
+ *
+ * 9 3 // D2 lhs = 93
+ * x 7 5 // D2 rhs = 75
+ * ----------
+ * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15
+ * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45
+ * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21
+ * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63
+ * ---------
+ * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27
+ * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67
+ * ---------
+ * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975
+ *
+ * The reasons for adding the products like this are:
+ * 1. It avoids manual carry tracking. Just like how
+ * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX.
+ * This avoids a lot of complexity.
+ *
+ * 2. It hints for, and on Clang, compiles to, the powerful UMAAL
+ * instruction available in ARM's Digital Signal Processing extension
+ * in 32-bit ARMv6 and later, which is shown below:
+ *
+ * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm)
+ * {
+ * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm;
+ * *RdLo = (xxh_u32)(product & 0xFFFFFFFF);
+ * *RdHi = (xxh_u32)(product >> 32);
+ * }
+ *
+ * This instruction was designed for efficient long multiplication, and
+ * allows this to be calculated in only 4 instructions at speeds
+ * comparable to some 64-bit ALUs.
+ *
+ * 3. It isn't terrible on other platforms. Usually this will be a couple
+ * of 32-bit ADD/ADCs.
+ */
+
+ /* First calculate all of the cross products. */
+ xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF);
+ xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF);
+ xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32);
+ xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32);
+
+ /* Now add the products together. These will never overflow. */
+ xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi;
+ xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi;
+ xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF);
+
+ XXH128_hash_t r128;
+ r128.low64 = lower;
+ r128.high64 = upper;
+ return r128;
+#endif
+}
+
+/*!
+ * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it.
+ *
+ * The reason for the separate function is to prevent passing too many structs
+ * around by value. This will hopefully inline the multiply, but we don't force it.
+ *
+ * @param lhs , rhs The 64-bit integers to multiply
+ * @return The low 64 bits of the product XOR'd by the high 64 bits.
+ * @see XXH_mult64to128()
+ */
+static xxh_u64
+XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs)
+{
+ XXH128_hash_t product = XXH_mult64to128(lhs, rhs);
+ return product.low64 ^ product.high64;
+}
+
+/*! Seems to produce slightly better code on GCC for some reason. */
+XXH_FORCE_INLINE xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift)
+{
+ XXH_ASSERT(0 <= shift && shift < 64);
+ return v64 ^ (v64 >> shift);
+}
+
+/*
+ * This is a fast avalanche stage,
+ * suitable when input bits are already partially mixed
+ */
+static XXH64_hash_t XXH3_avalanche(xxh_u64 h64)
+{
+ h64 = XXH_xorshift64(h64, 37);
+ h64 *= 0x165667919E3779F9ULL;
+ h64 = XXH_xorshift64(h64, 32);
+ return h64;
+}
+
+/*
+ * This is a stronger avalanche,
+ * inspired by Pelle Evensen's rrmxmx
+ * preferable when input has not been previously mixed
+ */
+static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len)
+{
+ /* this mix is inspired by Pelle Evensen's rrmxmx */
+ h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);
+ h64 *= 0x9FB21C651E98DF25ULL;
+ h64 ^= (h64 >> 35) + len ;
+ h64 *= 0x9FB21C651E98DF25ULL;
+ return XXH_xorshift64(h64, 28);
+}
+
+
+/* ==========================================
+ * Short keys
+ * ==========================================
+ * One of the shortcomings of XXH32 and XXH64 was that their performance was
+ * sub-optimal on short lengths. It used an iterative algorithm which strongly
+ * favored lengths that were a multiple of 4 or 8.
+ *
+ * Instead of iterating over individual inputs, we use a set of single shot
+ * functions which piece together a range of lengths and operate in constant time.
+ *
+ * Additionally, the number of multiplies has been significantly reduced. This
+ * reduces latency, especially when emulating 64-bit multiplies on 32-bit.
+ *
+ * Depending on the platform, this may or may not be faster than XXH32, but it
+ * is almost guaranteed to be faster than XXH64.
+ */
+
+/*
+ * At very short lengths, there isn't enough input to fully hide secrets, or use
+ * the entire secret.
+ *
+ * There is also only a limited amount of mixing we can do before significantly
+ * impacting performance.
+ *
+ * Therefore, we use different sections of the secret and always mix two secret
+ * samples with an XOR. This should have no effect on performance on the
+ * seedless or withSeed variants because everything _should_ be constant folded
+ * by modern compilers.
+ *
+ * The XOR mixing hides individual parts of the secret and increases entropy.
+ *
+ * This adds an extra layer of strength for custom secrets.
+ */
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(1 <= len && len <= 3);
+ XXH_ASSERT(secret != NULL);
+ /*
+ * len = 1: combined = { input[0], 0x01, input[0], input[0] }
+ * len = 2: combined = { input[1], 0x02, input[0], input[1] }
+ * len = 3: combined = { input[2], 0x03, input[0], input[1] }
+ */
+ { xxh_u8 const c1 = input[0];
+ xxh_u8 const c2 = input[len >> 1];
+ xxh_u8 const c3 = input[len - 1];
+ xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24)
+ | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);
+ xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;
+ xxh_u64 const keyed = (xxh_u64)combined ^ bitflip;
+ return XXH64_avalanche(keyed);
+ }
+}
+
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(secret != NULL);
+ XXH_ASSERT(4 <= len && len <= 8);
+ seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;
+ { xxh_u32 const input1 = XXH_readLE32(input);
+ xxh_u32 const input2 = XXH_readLE32(input + len - 4);
+ xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed;
+ xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32);
+ xxh_u64 const keyed = input64 ^ bitflip;
+ return XXH3_rrmxmx(keyed, len);
+ }
+}
+
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(secret != NULL);
+ XXH_ASSERT(9 <= len && len <= 16);
+ { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed;
+ xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed;
+ xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1;
+ xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2;
+ xxh_u64 const acc = len
+ + XXH_swap64(input_lo) + input_hi
+ + XXH3_mul128_fold64(input_lo, input_hi);
+ return XXH3_avalanche(acc);
+ }
+}
+
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(len <= 16);
+ { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed);
+ if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed);
+ if (len) return XXH3_len_1to3_64b(input, len, secret, seed);
+ return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64)));
+ }
+}
+
+/*
+ * DISCLAIMER: There are known *seed-dependent* multicollisions here due to
+ * multiplication by zero, affecting hashes of lengths 17 to 240.
+ *
+ * However, they are very unlikely.
+ *
+ * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all
+ * unseeded non-cryptographic hashes, it does not attempt to defend itself
+ * against specially crafted inputs, only random inputs.
+ *
+ * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes
+ * cancelling out the secret is taken an arbitrary number of times (addressed
+ * in XXH3_accumulate_512), this collision is very unlikely with random inputs
+ * and/or proper seeding:
+ *
+ * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a
+ * function that is only called up to 16 times per hash with up to 240 bytes of
+ * input.
+ *
+ * This is not too bad for a non-cryptographic hash function, especially with
+ * only 64 bit outputs.
+ *
+ * The 128-bit variant (which trades some speed for strength) is NOT affected
+ * by this, although it is always a good idea to use a proper seed if you care
+ * about strength.
+ */
+XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input,
+ const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64)
+{
+#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
+ && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \
+ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */
+ /*
+ * UGLY HACK:
+ * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in
+ * slower code.
+ *
+ * By forcing seed64 into a register, we disrupt the cost model and
+ * cause it to scalarize. See `XXH32_round()`
+ *
+ * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600,
+ * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on
+ * GCC 9.2, despite both emitting scalar code.
+ *
+ * GCC generates much better scalar code than Clang for the rest of XXH3,
+ * which is why finding a more optimal codepath is an interest.
+ */
+ XXH_COMPILER_GUARD(seed64);
+#endif
+ { xxh_u64 const input_lo = XXH_readLE64(input);
+ xxh_u64 const input_hi = XXH_readLE64(input+8);
+ return XXH3_mul128_fold64(
+ input_lo ^ (XXH_readLE64(secret) + seed64),
+ input_hi ^ (XXH_readLE64(secret+8) - seed64)
+ );
+ }
+}
+
+/* For mid range keys, XXH3 uses a Mum-hash variant. */
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH64_hash_t seed)
+{
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
+ XXH_ASSERT(16 < len && len <= 128);
+
+ { xxh_u64 acc = len * XXH_PRIME64_1;
+ if (len > 32) {
+ if (len > 64) {
+ if (len > 96) {
+ acc += XXH3_mix16B(input+48, secret+96, seed);
+ acc += XXH3_mix16B(input+len-64, secret+112, seed);
+ }
+ acc += XXH3_mix16B(input+32, secret+64, seed);
+ acc += XXH3_mix16B(input+len-48, secret+80, seed);
+ }
+ acc += XXH3_mix16B(input+16, secret+32, seed);
+ acc += XXH3_mix16B(input+len-32, secret+48, seed);
+ }
+ acc += XXH3_mix16B(input+0, secret+0, seed);
+ acc += XXH3_mix16B(input+len-16, secret+16, seed);
+
+ return XXH3_avalanche(acc);
+ }
+}
+
+#define XXH3_MIDSIZE_MAX 240
+
+XXH_NO_INLINE XXH64_hash_t
+XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH64_hash_t seed)
+{
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
+ XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);
+
+ #define XXH3_MIDSIZE_STARTOFFSET 3
+ #define XXH3_MIDSIZE_LASTOFFSET 17
+
+ { xxh_u64 acc = len * XXH_PRIME64_1;
+ int const nbRounds = (int)len / 16;
+ int i;
+ for (i=0; i<8; i++) {
+ acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed);
+ }
+ acc = XXH3_avalanche(acc);
+ XXH_ASSERT(nbRounds >= 8);
+#if defined(__clang__) /* Clang */ \
+ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \
+ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */
+ /*
+ * UGLY HACK:
+ * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86.
+ * In everywhere else, it uses scalar code.
+ *
+ * For 64->128-bit multiplies, even if the NEON was 100% optimal, it
+ * would still be slower than UMAAL (see XXH_mult64to128).
+ *
+ * Unfortunately, Clang doesn't handle the long multiplies properly and
+ * converts them to the nonexistent "vmulq_u64" intrinsic, which is then
+ * scalarized into an ugly mess of VMOV.32 instructions.
+ *
+ * This mess is difficult to avoid without turning autovectorization
+ * off completely, but they are usually relatively minor and/or not
+ * worth it to fix.
+ *
+ * This loop is the easiest to fix, as unlike XXH32, this pragma
+ * _actually works_ because it is a loop vectorization instead of an
+ * SLP vectorization.
+ */
+ #pragma clang loop vectorize(disable)
+#endif
+ for (i=8 ; i < nbRounds; i++) {
+ acc += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed);
+ }
+ /* last bytes */
+ acc += XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed);
+ return XXH3_avalanche(acc);
+ }
+}
+
+
+/* ======= Long Keys ======= */
+
+#define XXH_STRIPE_LEN 64
+#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */
+#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64))
+
+#ifdef XXH_OLD_NAMES
+# define STRIPE_LEN XXH_STRIPE_LEN
+# define ACC_NB XXH_ACC_NB
+#endif
+
+XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64)
+{
+ if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64);
+ XXH_memcpy(dst, &v64, sizeof(v64));
+}
+
+/* Several intrinsic functions below are supposed to accept __int64 as argument,
+ * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ .
+ * However, several environments do not define __int64 type,
+ * requiring a workaround.
+ */
+#if !defined (__VMS) \
+ && (defined (__cplusplus) \
+ || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
+ typedef int64_t xxh_i64;
+#else
+ /* the following type must have a width of 64-bit */
+ typedef long long xxh_i64;
+#endif
+
+
+/*
+ * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized.
+ *
+ * It is a hardened version of UMAC, based off of FARSH's implementation.
+ *
+ * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD
+ * implementations, and it is ridiculously fast.
+ *
+ * We harden it by mixing the original input to the accumulators as well as the product.
+ *
+ * This means that in the (relatively likely) case of a multiply by zero, the
+ * original input is preserved.
+ *
+ * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve
+ * cross-pollination, as otherwise the upper and lower halves would be
+ * essentially independent.
+ *
+ * This doesn't matter on 64-bit hashes since they all get merged together in
+ * the end, so we skip the extra step.
+ *
+ * Both XXH3_64bits and XXH3_128bits use this subroutine.
+ */
+
+#if (XXH_VECTOR == XXH_AVX512) \
+ || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0)
+
+#ifndef XXH_TARGET_AVX512
+# define XXH_TARGET_AVX512 /* disable attribute target */
+#endif
+
+XXH_FORCE_INLINE XXH_TARGET_AVX512 void
+XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ __m512i* const xacc = (__m512i *) acc;
+ XXH_ASSERT((((size_t)acc) & 63) == 0);
+ XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));
+
+ {
+ /* data_vec = input[0]; */
+ __m512i const data_vec = _mm512_loadu_si512 (input);
+ /* key_vec = secret[0]; */
+ __m512i const key_vec = _mm512_loadu_si512 (secret);
+ /* data_key = data_vec ^ key_vec; */
+ __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec);
+ /* data_key_lo = data_key >> 32; */
+ __m512i const data_key_lo = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1));
+ /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
+ __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo);
+ /* xacc[0] += swap(data_vec); */
+ __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2));
+ __m512i const sum = _mm512_add_epi64(*xacc, data_swap);
+ /* xacc[0] += product; */
+ *xacc = _mm512_add_epi64(product, sum);
+ }
+}
+
+/*
+ * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing.
+ *
+ * Multiplication isn't perfect, as explained by Google in HighwayHash:
+ *
+ * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to
+ * // varying degrees. In descending order of goodness, bytes
+ * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32.
+ * // As expected, the upper and lower bytes are much worse.
+ *
+ * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291
+ *
+ * Since our algorithm uses a pseudorandom secret to add some variance into the
+ * mix, we don't need to (or want to) mix as often or as much as HighwayHash does.
+ *
+ * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid
+ * extraction.
+ *
+ * Both XXH3_64bits and XXH3_128bits use this subroutine.
+ */
+
+XXH_FORCE_INLINE XXH_TARGET_AVX512 void
+XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 63) == 0);
+ XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i));
+ { __m512i* const xacc = (__m512i*) acc;
+ const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1);
+
+ /* xacc[0] ^= (xacc[0] >> 47) */
+ __m512i const acc_vec = *xacc;
+ __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47);
+ __m512i const data_vec = _mm512_xor_si512 (acc_vec, shifted);
+ /* xacc[0] ^= secret; */
+ __m512i const key_vec = _mm512_loadu_si512 (secret);
+ __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec);
+
+ /* xacc[0] *= XXH_PRIME32_1; */
+ __m512i const data_key_hi = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1));
+ __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32);
+ __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32);
+ *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32));
+ }
+}
+
+XXH_FORCE_INLINE XXH_TARGET_AVX512 void
+XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
+{
+ XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0);
+ XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64);
+ XXH_ASSERT(((size_t)customSecret & 63) == 0);
+ (void)(&XXH_writeLE64);
+ { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i);
+ __m512i const seed = _mm512_mask_set1_epi64(_mm512_set1_epi64((xxh_i64)seed64), 0xAA, (xxh_i64)(0U - seed64));
+
+ const __m512i* const src = (const __m512i*) ((const void*) XXH3_kSecret);
+ __m512i* const dest = ( __m512i*) customSecret;
+ int i;
+ XXH_ASSERT(((size_t)src & 63) == 0); /* control alignment */
+ XXH_ASSERT(((size_t)dest & 63) == 0);
+ for (i=0; i < nbRounds; ++i) {
+ /* GCC has a bug, _mm512_stream_load_si512 accepts 'void*', not 'void const*',
+ * this will warn "discards 'const' qualifier". */
+ union {
+ const __m512i* cp;
+ void* p;
+ } remote_const_void;
+ remote_const_void.cp = src + i;
+ dest[i] = _mm512_add_epi64(_mm512_stream_load_si512(remote_const_void.p), seed);
+ } }
+}
+
+#endif
+
+#if (XXH_VECTOR == XXH_AVX2) \
+ || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0)
+
+#ifndef XXH_TARGET_AVX2
+# define XXH_TARGET_AVX2 /* disable attribute target */
+#endif
+
+XXH_FORCE_INLINE XXH_TARGET_AVX2 void
+XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 31) == 0);
+ { __m256i* const xacc = (__m256i *) acc;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
+ const __m256i* const xinput = (const __m256i *) input;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
+ const __m256i* const xsecret = (const __m256i *) secret;
+
+ size_t i;
+ for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {
+ /* data_vec = xinput[i]; */
+ __m256i const data_vec = _mm256_loadu_si256 (xinput+i);
+ /* key_vec = xsecret[i]; */
+ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i);
+ /* data_key = data_vec ^ key_vec; */
+ __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec);
+ /* data_key_lo = data_key >> 32; */
+ __m256i const data_key_lo = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
+ /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
+ __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo);
+ /* xacc[i] += swap(data_vec); */
+ __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2));
+ __m256i const sum = _mm256_add_epi64(xacc[i], data_swap);
+ /* xacc[i] += product; */
+ xacc[i] = _mm256_add_epi64(product, sum);
+ } }
+}
+
+XXH_FORCE_INLINE XXH_TARGET_AVX2 void
+XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 31) == 0);
+ { __m256i* const xacc = (__m256i*) acc;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */
+ const __m256i* const xsecret = (const __m256i *) secret;
+ const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1);
+
+ size_t i;
+ for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) {
+ /* xacc[i] ^= (xacc[i] >> 47) */
+ __m256i const acc_vec = xacc[i];
+ __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47);
+ __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted);
+ /* xacc[i] ^= xsecret; */
+ __m256i const key_vec = _mm256_loadu_si256 (xsecret+i);
+ __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec);
+
+ /* xacc[i] *= XXH_PRIME32_1; */
+ __m256i const data_key_hi = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
+ __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32);
+ __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32);
+ xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32));
+ }
+ }
+}
+
+XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
+{
+ XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0);
+ XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6);
+ XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64);
+ (void)(&XXH_writeLE64);
+ XXH_PREFETCH(customSecret);
+ { __m256i const seed = _mm256_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64, (xxh_i64)(0U - seed64), (xxh_i64)seed64);
+
+ const __m256i* const src = (const __m256i*) ((const void*) XXH3_kSecret);
+ __m256i* dest = ( __m256i*) customSecret;
+
+# if defined(__GNUC__) || defined(__clang__)
+ /*
+ * On GCC & Clang, marking 'dest' as modified will cause the compiler:
+ * - do not extract the secret from sse registers in the internal loop
+ * - use less common registers, and avoid pushing these reg into stack
+ */
+ XXH_COMPILER_GUARD(dest);
+# endif
+ XXH_ASSERT(((size_t)src & 31) == 0); /* control alignment */
+ XXH_ASSERT(((size_t)dest & 31) == 0);
+
+ /* GCC -O2 need unroll loop manually */
+ dest[0] = _mm256_add_epi64(_mm256_stream_load_si256(src+0), seed);
+ dest[1] = _mm256_add_epi64(_mm256_stream_load_si256(src+1), seed);
+ dest[2] = _mm256_add_epi64(_mm256_stream_load_si256(src+2), seed);
+ dest[3] = _mm256_add_epi64(_mm256_stream_load_si256(src+3), seed);
+ dest[4] = _mm256_add_epi64(_mm256_stream_load_si256(src+4), seed);
+ dest[5] = _mm256_add_epi64(_mm256_stream_load_si256(src+5), seed);
+ }
+}
+
+#endif
+
+/* x86dispatch always generates SSE2 */
+#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH)
+
+#ifndef XXH_TARGET_SSE2
+# define XXH_TARGET_SSE2 /* disable attribute target */
+#endif
+
+XXH_FORCE_INLINE XXH_TARGET_SSE2 void
+XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ /* SSE2 is just a half-scale version of the AVX2 version. */
+ XXH_ASSERT((((size_t)acc) & 15) == 0);
+ { __m128i* const xacc = (__m128i *) acc;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
+ const __m128i* const xinput = (const __m128i *) input;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
+ const __m128i* const xsecret = (const __m128i *) secret;
+
+ size_t i;
+ for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {
+ /* data_vec = xinput[i]; */
+ __m128i const data_vec = _mm_loadu_si128 (xinput+i);
+ /* key_vec = xsecret[i]; */
+ __m128i const key_vec = _mm_loadu_si128 (xsecret+i);
+ /* data_key = data_vec ^ key_vec; */
+ __m128i const data_key = _mm_xor_si128 (data_vec, key_vec);
+ /* data_key_lo = data_key >> 32; */
+ __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
+ /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */
+ __m128i const product = _mm_mul_epu32 (data_key, data_key_lo);
+ /* xacc[i] += swap(data_vec); */
+ __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2));
+ __m128i const sum = _mm_add_epi64(xacc[i], data_swap);
+ /* xacc[i] += product; */
+ xacc[i] = _mm_add_epi64(product, sum);
+ } }
+}
+
+XXH_FORCE_INLINE XXH_TARGET_SSE2 void
+XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 15) == 0);
+ { __m128i* const xacc = (__m128i*) acc;
+ /* Unaligned. This is mainly for pointer arithmetic, and because
+ * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */
+ const __m128i* const xsecret = (const __m128i *) secret;
+ const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1);
+
+ size_t i;
+ for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) {
+ /* xacc[i] ^= (xacc[i] >> 47) */
+ __m128i const acc_vec = xacc[i];
+ __m128i const shifted = _mm_srli_epi64 (acc_vec, 47);
+ __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted);
+ /* xacc[i] ^= xsecret[i]; */
+ __m128i const key_vec = _mm_loadu_si128 (xsecret+i);
+ __m128i const data_key = _mm_xor_si128 (data_vec, key_vec);
+
+ /* xacc[i] *= XXH_PRIME32_1; */
+ __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1));
+ __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32);
+ __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32);
+ xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32));
+ }
+ }
+}
+
+XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
+{
+ XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);
+ (void)(&XXH_writeLE64);
+ { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i);
+
+# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900
+ /* MSVC 32bit mode does not support _mm_set_epi64x before 2015 */
+ XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, (xxh_i64)(0U - seed64) };
+ __m128i const seed = _mm_load_si128((__m128i const*)seed64x2);
+# else
+ __m128i const seed = _mm_set_epi64x((xxh_i64)(0U - seed64), (xxh_i64)seed64);
+# endif
+ int i;
+
+ const void* const src16 = XXH3_kSecret;
+ __m128i* dst16 = (__m128i*) customSecret;
+# if defined(__GNUC__) || defined(__clang__)
+ /*
+ * On GCC & Clang, marking 'dest' as modified will cause the compiler:
+ * - do not extract the secret from sse registers in the internal loop
+ * - use less common registers, and avoid pushing these reg into stack
+ */
+ XXH_COMPILER_GUARD(dst16);
+# endif
+ XXH_ASSERT(((size_t)src16 & 15) == 0); /* control alignment */
+ XXH_ASSERT(((size_t)dst16 & 15) == 0);
+
+ for (i=0; i < nbRounds; ++i) {
+ dst16[i] = _mm_add_epi64(_mm_load_si128((const __m128i *)src16+i), seed);
+ } }
+}
+
+#endif
+
+#if (XXH_VECTOR == XXH_NEON)
+
+/* forward declarations for the scalar routines */
+XXH_FORCE_INLINE void
+XXH3_scalarRound(void* XXH_RESTRICT acc, void const* XXH_RESTRICT input,
+ void const* XXH_RESTRICT secret, size_t lane);
+
+XXH_FORCE_INLINE void
+XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
+ void const* XXH_RESTRICT secret, size_t lane);
+
+/*!
+ * @internal
+ * @brief The bulk processing loop for NEON.
+ *
+ * The NEON code path is actually partially scalar when running on AArch64. This
+ * is to optimize the pipelining and can have up to 15% speedup depending on the
+ * CPU, and it also mitigates some GCC codegen issues.
+ *
+ * @see XXH3_NEON_LANES for configuring this and details about this optimization.
+ */
+XXH_FORCE_INLINE void
+XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 15) == 0);
+ XXH_STATIC_ASSERT(XXH3_NEON_LANES > 0 && XXH3_NEON_LANES <= XXH_ACC_NB && XXH3_NEON_LANES % 2 == 0);
+ {
+ uint64x2_t* const xacc = (uint64x2_t *) acc;
+ /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */
+ uint8_t const* const xinput = (const uint8_t *) input;
+ uint8_t const* const xsecret = (const uint8_t *) secret;
+
+ size_t i;
+ /* NEON for the first few lanes (these loops are normally interleaved) */
+ for (i=0; i < XXH3_NEON_LANES / 2; i++) {
+ /* data_vec = xinput[i]; */
+ uint8x16_t data_vec = vld1q_u8(xinput + (i * 16));
+ /* key_vec = xsecret[i]; */
+ uint8x16_t key_vec = vld1q_u8(xsecret + (i * 16));
+ uint64x2_t data_key;
+ uint32x2_t data_key_lo, data_key_hi;
+ /* xacc[i] += swap(data_vec); */
+ uint64x2_t const data64 = vreinterpretq_u64_u8(data_vec);
+ uint64x2_t const swapped = vextq_u64(data64, data64, 1);
+ xacc[i] = vaddq_u64 (xacc[i], swapped);
+ /* data_key = data_vec ^ key_vec; */
+ data_key = vreinterpretq_u64_u8(veorq_u8(data_vec, key_vec));
+ /* data_key_lo = (uint32x2_t) (data_key & 0xFFFFFFFF);
+ * data_key_hi = (uint32x2_t) (data_key >> 32);
+ * data_key = UNDEFINED; */
+ XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi);
+ /* xacc[i] += (uint64x2_t) data_key_lo * (uint64x2_t) data_key_hi; */
+ xacc[i] = vmlal_u32 (xacc[i], data_key_lo, data_key_hi);
+
+ }
+ /* Scalar for the remainder. This may be a zero iteration loop. */
+ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
+ XXH3_scalarRound(acc, input, secret, i);
+ }
+ }
+}
+
+XXH_FORCE_INLINE void
+XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 15) == 0);
+
+ { uint64x2_t* xacc = (uint64x2_t*) acc;
+ uint8_t const* xsecret = (uint8_t const*) secret;
+ uint32x2_t prime = vdup_n_u32 (XXH_PRIME32_1);
+
+ size_t i;
+ /* NEON for the first few lanes (these loops are normally interleaved) */
+ for (i=0; i < XXH3_NEON_LANES / 2; i++) {
+ /* xacc[i] ^= (xacc[i] >> 47); */
+ uint64x2_t acc_vec = xacc[i];
+ uint64x2_t shifted = vshrq_n_u64 (acc_vec, 47);
+ uint64x2_t data_vec = veorq_u64 (acc_vec, shifted);
+
+ /* xacc[i] ^= xsecret[i]; */
+ uint8x16_t key_vec = vld1q_u8 (xsecret + (i * 16));
+ uint64x2_t data_key = veorq_u64 (data_vec, vreinterpretq_u64_u8(key_vec));
+
+ /* xacc[i] *= XXH_PRIME32_1 */
+ uint32x2_t data_key_lo, data_key_hi;
+ /* data_key_lo = (uint32x2_t) (xacc[i] & 0xFFFFFFFF);
+ * data_key_hi = (uint32x2_t) (xacc[i] >> 32);
+ * xacc[i] = UNDEFINED; */
+ XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi);
+ { /*
+ * prod_hi = (data_key >> 32) * XXH_PRIME32_1;
+ *
+ * Avoid vmul_u32 + vshll_n_u32 since Clang 6 and 7 will
+ * incorrectly "optimize" this:
+ * tmp = vmul_u32(vmovn_u64(a), vmovn_u64(b));
+ * shifted = vshll_n_u32(tmp, 32);
+ * to this:
+ * tmp = "vmulq_u64"(a, b); // no such thing!
+ * shifted = vshlq_n_u64(tmp, 32);
+ *
+ * However, unlike SSE, Clang lacks a 64-bit multiply routine
+ * for NEON, and it scalarizes two 64-bit multiplies instead.
+ *
+ * vmull_u32 has the same timing as vmul_u32, and it avoids
+ * this bug completely.
+ * See https://bugs.llvm.org/show_bug.cgi?id=39967
+ */
+ uint64x2_t prod_hi = vmull_u32 (data_key_hi, prime);
+ /* xacc[i] = prod_hi << 32; */
+ xacc[i] = vshlq_n_u64(prod_hi, 32);
+ /* xacc[i] += (prod_hi & 0xFFFFFFFF) * XXH_PRIME32_1; */
+ xacc[i] = vmlal_u32(xacc[i], data_key_lo, prime);
+ }
+ }
+ /* Scalar for the remainder. This may be a zero iteration loop. */
+ for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
+ XXH3_scalarScrambleRound(acc, secret, i);
+ }
+ }
+}
+
+#endif
+
+#if (XXH_VECTOR == XXH_VSX)
+
+XXH_FORCE_INLINE void
+XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ /* presumed aligned */
+ unsigned int* const xacc = (unsigned int*) acc;
+ xxh_u64x2 const* const xinput = (xxh_u64x2 const*) input; /* no alignment restriction */
+ xxh_u64x2 const* const xsecret = (xxh_u64x2 const*) secret; /* no alignment restriction */
+ xxh_u64x2 const v32 = { 32, 32 };
+ size_t i;
+ for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {
+ /* data_vec = xinput[i]; */
+ xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + i);
+ /* key_vec = xsecret[i]; */
+ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i);
+ xxh_u64x2 const data_key = data_vec ^ key_vec;
+ /* shuffled = (data_key << 32) | (data_key >> 32); */
+ xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32);
+ /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */
+ xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled);
+ /* acc_vec = xacc[i]; */
+ xxh_u64x2 acc_vec = (xxh_u64x2)vec_xl(0, xacc + 4 * i);
+ acc_vec += product;
+
+ /* swap high and low halves */
+#ifdef __s390x__
+ acc_vec += vec_permi(data_vec, data_vec, 2);
+#else
+ acc_vec += vec_xxpermdi(data_vec, data_vec, 2);
+#endif
+ /* xacc[i] = acc_vec; */
+ vec_xst((xxh_u32x4)acc_vec, 0, xacc + 4 * i);
+ }
+}
+
+XXH_FORCE_INLINE void
+XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ XXH_ASSERT((((size_t)acc) & 15) == 0);
+
+ { xxh_u64x2* const xacc = (xxh_u64x2*) acc;
+ const xxh_u64x2* const xsecret = (const xxh_u64x2*) secret;
+ /* constants */
+ xxh_u64x2 const v32 = { 32, 32 };
+ xxh_u64x2 const v47 = { 47, 47 };
+ xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 };
+ size_t i;
+ for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) {
+ /* xacc[i] ^= (xacc[i] >> 47); */
+ xxh_u64x2 const acc_vec = xacc[i];
+ xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47);
+
+ /* xacc[i] ^= xsecret[i]; */
+ xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i);
+ xxh_u64x2 const data_key = data_vec ^ key_vec;
+
+ /* xacc[i] *= XXH_PRIME32_1 */
+ /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */
+ xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime);
+ /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */
+ xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime);
+ xacc[i] = prod_odd + (prod_even << v32);
+ } }
+}
+
+#endif
+
+/* scalar variants - universal */
+
+/*!
+ * @internal
+ * @brief Scalar round for @ref XXH3_accumulate_512_scalar().
+ *
+ * This is extracted to its own function because the NEON path uses a combination
+ * of NEON and scalar.
+ */
+XXH_FORCE_INLINE void
+XXH3_scalarRound(void* XXH_RESTRICT acc,
+ void const* XXH_RESTRICT input,
+ void const* XXH_RESTRICT secret,
+ size_t lane)
+{
+ xxh_u64* xacc = (xxh_u64*) acc;
+ xxh_u8 const* xinput = (xxh_u8 const*) input;
+ xxh_u8 const* xsecret = (xxh_u8 const*) secret;
+ XXH_ASSERT(lane < XXH_ACC_NB);
+ XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0);
+ {
+ xxh_u64 const data_val = XXH_readLE64(xinput + lane * 8);
+ xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + lane * 8);
+ xacc[lane ^ 1] += data_val; /* swap adjacent lanes */
+ xacc[lane] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32);
+ }
+}
+
+/*!
+ * @internal
+ * @brief Processes a 64 byte block of data using the scalar path.
+ */
+XXH_FORCE_INLINE void
+XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc,
+ const void* XXH_RESTRICT input,
+ const void* XXH_RESTRICT secret)
+{
+ size_t i;
+ for (i=0; i < XXH_ACC_NB; i++) {
+ XXH3_scalarRound(acc, input, secret, i);
+ }
+}
+
+/*!
+ * @internal
+ * @brief Scalar scramble step for @ref XXH3_scrambleAcc_scalar().
+ *
+ * This is extracted to its own function because the NEON path uses a combination
+ * of NEON and scalar.
+ */
+XXH_FORCE_INLINE void
+XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
+ void const* XXH_RESTRICT secret,
+ size_t lane)
+{
+ xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */
+ const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */
+ XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0);
+ XXH_ASSERT(lane < XXH_ACC_NB);
+ {
+ xxh_u64 const key64 = XXH_readLE64(xsecret + lane * 8);
+ xxh_u64 acc64 = xacc[lane];
+ acc64 = XXH_xorshift64(acc64, 47);
+ acc64 ^= key64;
+ acc64 *= XXH_PRIME32_1;
+ xacc[lane] = acc64;
+ }
+}
+
+/*!
+ * @internal
+ * @brief Scrambles the accumulators after a large chunk has been read
+ */
+XXH_FORCE_INLINE void
+XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
+{
+ size_t i;
+ for (i=0; i < XXH_ACC_NB; i++) {
+ XXH3_scalarScrambleRound(acc, secret, i);
+ }
+}
-#endif /* XXH_STATIC_LINKING_ONLY && XXH_STATIC_H_3543687687345 */
+XXH_FORCE_INLINE void
+XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
+{
+ /*
+ * We need a separate pointer for the hack below,
+ * which requires a non-const pointer.
+ * Any decent compiler will optimize this out otherwise.
+ */
+ const xxh_u8* kSecretPtr = XXH3_kSecret;
+ XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0);
+
+#if defined(__clang__) && defined(__aarch64__)
+ /*
+ * UGLY HACK:
+ * Clang generates a bunch of MOV/MOVK pairs for aarch64, and they are
+ * placed sequentially, in order, at the top of the unrolled loop.
+ *
+ * While MOVK is great for generating constants (2 cycles for a 64-bit
+ * constant compared to 4 cycles for LDR), it fights for bandwidth with
+ * the arithmetic instructions.
+ *
+ * I L S
+ * MOVK
+ * MOVK
+ * MOVK
+ * MOVK
+ * ADD
+ * SUB STR
+ * STR
+ * By forcing loads from memory (as the asm line causes Clang to assume
+ * that XXH3_kSecretPtr has been changed), the pipelines are used more
+ * efficiently:
+ * I L S
+ * LDR
+ * ADD LDR
+ * SUB STR
+ * STR
+ *
+ * See XXH3_NEON_LANES for details on the pipsline.
+ *
+ * XXH3_64bits_withSeed, len == 256, Snapdragon 835
+ * without hack: 2654.4 MB/s
+ * with hack: 3202.9 MB/s
+ */
+ XXH_COMPILER_GUARD(kSecretPtr);
+#endif
+ /*
+ * Note: in debug mode, this overrides the asm optimization
+ * and Clang will emit MOVK chains again.
+ */
+ XXH_ASSERT(kSecretPtr == XXH3_kSecret);
+
+ { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16;
+ int i;
+ for (i=0; i < nbRounds; i++) {
+ /*
+ * The asm hack causes Clang to assume that kSecretPtr aliases with
+ * customSecret, and on aarch64, this prevented LDP from merging two
+ * loads together for free. Putting the loads together before the stores
+ * properly generates LDP.
+ */
+ xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64;
+ xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64;
+ XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo);
+ XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi);
+ } }
+}
+
+
+typedef void (*XXH3_f_accumulate_512)(void* XXH_RESTRICT, const void*, const void*);
+typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*);
+typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64);
+
+
+#if (XXH_VECTOR == XXH_AVX512)
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_avx512
+#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512
+#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512
+
+#elif (XXH_VECTOR == XXH_AVX2)
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_avx2
+#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2
+#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2
+
+#elif (XXH_VECTOR == XXH_SSE2)
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_sse2
+#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2
+#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2
+
+#elif (XXH_VECTOR == XXH_NEON)
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_neon
+#define XXH3_scrambleAcc XXH3_scrambleAcc_neon
+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
+
+#elif (XXH_VECTOR == XXH_VSX)
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_vsx
+#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx
+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
+
+#else /* scalar */
+
+#define XXH3_accumulate_512 XXH3_accumulate_512_scalar
+#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar
+#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar
+
+#endif
+
+
+
+#ifndef XXH_PREFETCH_DIST
+# ifdef __clang__
+# define XXH_PREFETCH_DIST 320
+# else
+# if (XXH_VECTOR == XXH_AVX512)
+# define XXH_PREFETCH_DIST 512
+# else
+# define XXH_PREFETCH_DIST 384
+# endif
+# endif /* __clang__ */
+#endif /* XXH_PREFETCH_DIST */
+
+/*
+ * XXH3_accumulate()
+ * Loops over XXH3_accumulate_512().
+ * Assumption: nbStripes will not overflow the secret size
+ */
+XXH_FORCE_INLINE void
+XXH3_accumulate( xxh_u64* XXH_RESTRICT acc,
+ const xxh_u8* XXH_RESTRICT input,
+ const xxh_u8* XXH_RESTRICT secret,
+ size_t nbStripes,
+ XXH3_f_accumulate_512 f_acc512)
+{
+ size_t n;
+ for (n = 0; n < nbStripes; n++ ) {
+ const xxh_u8* const in = input + n*XXH_STRIPE_LEN;
+ XXH_PREFETCH(in + XXH_PREFETCH_DIST);
+ f_acc512(acc,
+ in,
+ secret + n*XXH_SECRET_CONSUME_RATE);
+ }
+}
+
+XXH_FORCE_INLINE void
+XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc,
+ const xxh_u8* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble)
+{
+ size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE;
+ size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock;
+ size_t const nb_blocks = (len - 1) / block_len;
+
+ size_t n;
+
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
+
+ for (n = 0; n < nb_blocks; n++) {
+ XXH3_accumulate(acc, input + n*block_len, secret, nbStripesPerBlock, f_acc512);
+ f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN);
+ }
+
+ /* last partial block */
+ XXH_ASSERT(len > XXH_STRIPE_LEN);
+ { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN;
+ XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE));
+ XXH3_accumulate(acc, input + nb_blocks*block_len, secret, nbStripes, f_acc512);
+
+ /* last stripe */
+ { const xxh_u8* const p = input + len - XXH_STRIPE_LEN;
+#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */
+ f_acc512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START);
+ } }
+}
+
+XXH_FORCE_INLINE xxh_u64
+XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret)
+{
+ return XXH3_mul128_fold64(
+ acc[0] ^ XXH_readLE64(secret),
+ acc[1] ^ XXH_readLE64(secret+8) );
+}
+
+static XXH64_hash_t
+XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start)
+{
+ xxh_u64 result64 = start;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++) {
+ result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i);
+#if defined(__clang__) /* Clang */ \
+ && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \
+ && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \
+ && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */
+ /*
+ * UGLY HACK:
+ * Prevent autovectorization on Clang ARMv7-a. Exact same problem as
+ * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b.
+ * XXH3_64bits, len == 256, Snapdragon 835:
+ * without hack: 2063.7 MB/s
+ * with hack: 2560.7 MB/s
+ */
+ XXH_COMPILER_GUARD(result64);
+#endif
+ }
+
+ return XXH3_avalanche(result64);
+}
+
+#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \
+ XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 }
+
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len,
+ const void* XXH_RESTRICT secret, size_t secretSize,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble)
+{
+ XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;
+
+ XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc512, f_scramble);
+
+ /* converge into final hash */
+ XXH_STATIC_ASSERT(sizeof(acc) == 64);
+ /* do not align on 8, so that the secret is different from the accumulator */
+#define XXH_SECRET_MERGEACCS_START 11
+ XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
+ return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1);
+}
+
+/*
+ * It's important for performance to transmit secret's size (when it's static)
+ * so that the compiler can properly optimize the vectorized loop.
+ * This makes a big performance difference for "medium" keys (<1 KB) when using AVX instruction set.
+ */
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
+{
+ (void)seed64;
+ return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+/*
+ * It's preferable for performance that XXH3_hashLong is not inlined,
+ * as it results in a smaller function for small data, easier to the instruction cache.
+ * Note that inside this no_inline function, we do inline the internal loop,
+ * and provide a statically defined secret size to allow optimization of vector loop.
+ */
+XXH_NO_INLINE XXH64_hash_t
+XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen)
+{
+ (void)seed64; (void)secret; (void)secretLen;
+ return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+/*
+ * XXH3_hashLong_64b_withSeed():
+ * Generate a custom key based on alteration of default XXH3_kSecret with the seed,
+ * and then use this key for long mode hashing.
+ *
+ * This operation is decently fast but nonetheless costs a little bit of time.
+ * Try to avoid it whenever possible (typically when seed==0).
+ *
+ * It's important for performance that XXH3_hashLong is not inlined. Not sure
+ * why (uop cache maybe?), but the difference is large and easily measurable.
+ */
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len,
+ XXH64_hash_t seed,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble,
+ XXH3_f_initCustomSecret f_initSec)
+{
+ if (seed == 0)
+ return XXH3_hashLong_64b_internal(input, len,
+ XXH3_kSecret, sizeof(XXH3_kSecret),
+ f_acc512, f_scramble);
+ { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
+ f_initSec(secret, seed);
+ return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret),
+ f_acc512, f_scramble);
+ }
+}
+
+/*
+ * It's important for performance that XXH3_hashLong is not inlined.
+ */
+XXH_NO_INLINE XXH64_hash_t
+XXH3_hashLong_64b_withSeed(const void* input, size_t len,
+ XXH64_hash_t seed, const xxh_u8* secret, size_t secretLen)
+{
+ (void)secret; (void)secretLen;
+ return XXH3_hashLong_64b_withSeed_internal(input, len, seed,
+ XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret);
+}
+
+
+typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t,
+ XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t);
+
+XXH_FORCE_INLINE XXH64_hash_t
+XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,
+ XXH3_hashLong64_f f_hashLong)
+{
+ XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);
+ /*
+ * If an action is to be taken if `secretLen` condition is not respected,
+ * it should be done here.
+ * For now, it's a contract pre-condition.
+ * Adding a check and a branch here would cost performance at every hash.
+ * Also, note that function signature doesn't offer room to return an error.
+ */
+ if (len <= 16)
+ return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);
+ if (len <= 128)
+ return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
+ if (len <= XXH3_MIDSIZE_MAX)
+ return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
+ return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen);
+}
+
+
+/* === Public entry point === */
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* input, size_t len)
+{
+ return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH64_hash_t
+XXH3_64bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize)
+{
+ return XXH3_64bits_internal(input, len, 0, secret, secretSize, XXH3_hashLong_64b_withSecret);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH64_hash_t
+XXH3_64bits_withSeed(const void* input, size_t len, XXH64_hash_t seed)
+{
+ return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed);
+}
+
+XXH_PUBLIC_API XXH64_hash_t
+XXH3_64bits_withSecretandSeed(const void* input, size_t len, const void* secret, size_t secretSize, XXH64_hash_t seed)
+{
+ if (len <= XXH3_MIDSIZE_MAX)
+ return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);
+ return XXH3_hashLong_64b_withSecret(input, len, seed, (const xxh_u8*)secret, secretSize);
+}
+
+
+/* === XXH3 streaming === */
+
+/*
+ * Malloc's a pointer that is always aligned to align.
+ *
+ * This must be freed with `XXH_alignedFree()`.
+ *
+ * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte
+ * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2
+ * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON.
+ *
+ * This underalignment previously caused a rather obvious crash which went
+ * completely unnoticed due to XXH3_createState() not actually being tested.
+ * Credit to RedSpah for noticing this bug.
+ *
+ * The alignment is done manually: Functions like posix_memalign or _mm_malloc
+ * are avoided: To maintain portability, we would have to write a fallback
+ * like this anyways, and besides, testing for the existence of library
+ * functions without relying on external build tools is impossible.
+ *
+ * The method is simple: Overallocate, manually align, and store the offset
+ * to the original behind the returned pointer.
+ *
+ * Align must be a power of 2 and 8 <= align <= 128.
+ */
+static void* XXH_alignedMalloc(size_t s, size_t align)
+{
+ XXH_ASSERT(align <= 128 && align >= 8); /* range check */
+ XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */
+ XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */
+ { /* Overallocate to make room for manual realignment and an offset byte */
+ xxh_u8* base = (xxh_u8*)XXH_malloc(s + align);
+ if (base != NULL) {
+ /*
+ * Get the offset needed to align this pointer.
+ *
+ * Even if the returned pointer is aligned, there will always be
+ * at least one byte to store the offset to the original pointer.
+ */
+ size_t offset = align - ((size_t)base & (align - 1)); /* base % align */
+ /* Add the offset for the now-aligned pointer */
+ xxh_u8* ptr = base + offset;
+
+ XXH_ASSERT((size_t)ptr % align == 0);
+
+ /* Store the offset immediately before the returned pointer. */
+ ptr[-1] = (xxh_u8)offset;
+ return ptr;
+ }
+ return NULL;
+ }
+}
+/*
+ * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass
+ * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout.
+ */
+static void XXH_alignedFree(void* p)
+{
+ if (p != NULL) {
+ xxh_u8* ptr = (xxh_u8*)p;
+ /* Get the offset byte we added in XXH_malloc. */
+ xxh_u8 offset = ptr[-1];
+ /* Free the original malloc'd pointer */
+ xxh_u8* base = ptr - offset;
+ XXH_free(base);
+ }
+}
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)
+{
+ XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);
+ if (state==NULL) return NULL;
+ XXH3_INITSTATE(state);
+ return state;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr)
+{
+ XXH_alignedFree(statePtr);
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API void
+XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state)
+{
+ XXH_memcpy(dst_state, src_state, sizeof(*dst_state));
+}
+
+static void
+XXH3_reset_internal(XXH3_state_t* statePtr,
+ XXH64_hash_t seed,
+ const void* secret, size_t secretSize)
+{
+ size_t const initStart = offsetof(XXH3_state_t, bufferedSize);
+ size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart;
+ XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart);
+ XXH_ASSERT(statePtr != NULL);
+ /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */
+ memset((char*)statePtr + initStart, 0, initLength);
+ statePtr->acc[0] = XXH_PRIME32_3;
+ statePtr->acc[1] = XXH_PRIME64_1;
+ statePtr->acc[2] = XXH_PRIME64_2;
+ statePtr->acc[3] = XXH_PRIME64_3;
+ statePtr->acc[4] = XXH_PRIME64_4;
+ statePtr->acc[5] = XXH_PRIME32_2;
+ statePtr->acc[6] = XXH_PRIME64_5;
+ statePtr->acc[7] = XXH_PRIME32_1;
+ statePtr->seed = seed;
+ statePtr->useSeed = (seed != 0);
+ statePtr->extSecret = (const unsigned char*)secret;
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
+ statePtr->secretLimit = secretSize - XXH_STRIPE_LEN;
+ statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_reset(XXH3_state_t* statePtr)
+{
+ if (statePtr == NULL) return XXH_ERROR;
+ XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize)
+{
+ if (statePtr == NULL) return XXH_ERROR;
+ XXH3_reset_internal(statePtr, 0, secret, secretSize);
+ if (secret == NULL) return XXH_ERROR;
+ if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed)
+{
+ if (statePtr == NULL) return XXH_ERROR;
+ if (seed==0) return XXH3_64bits_reset(statePtr);
+ if ((seed != statePtr->seed) || (statePtr->extSecret != NULL))
+ XXH3_initCustomSecret(statePtr->customSecret, seed);
+ XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed64)
+{
+ if (statePtr == NULL) return XXH_ERROR;
+ if (secret == NULL) return XXH_ERROR;
+ if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
+ XXH3_reset_internal(statePtr, seed64, secret, secretSize);
+ statePtr->useSeed = 1; /* always, even if seed64==0 */
+ return XXH_OK;
+}
+
+/* Note : when XXH3_consumeStripes() is invoked,
+ * there must be a guarantee that at least one more byte must be consumed from input
+ * so that the function can blindly consume all stripes using the "normal" secret segment */
+XXH_FORCE_INLINE void
+XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc,
+ size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock,
+ const xxh_u8* XXH_RESTRICT input, size_t nbStripes,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretLimit,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble)
+{
+ XXH_ASSERT(nbStripes <= nbStripesPerBlock); /* can handle max 1 scramble per invocation */
+ XXH_ASSERT(*nbStripesSoFarPtr < nbStripesPerBlock);
+ if (nbStripesPerBlock - *nbStripesSoFarPtr <= nbStripes) {
+ /* need a scrambling operation */
+ size_t const nbStripesToEndofBlock = nbStripesPerBlock - *nbStripesSoFarPtr;
+ size_t const nbStripesAfterBlock = nbStripes - nbStripesToEndofBlock;
+ XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripesToEndofBlock, f_acc512);
+ f_scramble(acc, secret + secretLimit);
+ XXH3_accumulate(acc, input + nbStripesToEndofBlock * XXH_STRIPE_LEN, secret, nbStripesAfterBlock, f_acc512);
+ *nbStripesSoFarPtr = nbStripesAfterBlock;
+ } else {
+ XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripes, f_acc512);
+ *nbStripesSoFarPtr += nbStripes;
+ }
+}
+
+#ifndef XXH3_STREAM_USE_STACK
+# ifndef __clang__ /* clang doesn't need additional stack space */
+# define XXH3_STREAM_USE_STACK 1
+# endif
+#endif
+/*
+ * Both XXH3_64bits_update and XXH3_128bits_update use this routine.
+ */
+XXH_FORCE_INLINE XXH_errorcode
+XXH3_update(XXH3_state_t* XXH_RESTRICT const state,
+ const xxh_u8* XXH_RESTRICT input, size_t len,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble)
+{
+ if (input==NULL) {
+ XXH_ASSERT(len == 0);
+ return XXH_OK;
+ }
+
+ XXH_ASSERT(state != NULL);
+ { const xxh_u8* const bEnd = input + len;
+ const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
+#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1
+ /* For some reason, gcc and MSVC seem to suffer greatly
+ * when operating accumulators directly into state.
+ * Operating into stack space seems to enable proper optimization.
+ * clang, on the other hand, doesn't seem to need this trick */
+ XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[8]; memcpy(acc, state->acc, sizeof(acc));
+#else
+ xxh_u64* XXH_RESTRICT const acc = state->acc;
+#endif
+ state->totalLen += len;
+ XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE);
+
+ /* small input : just fill in tmp buffer */
+ if (state->bufferedSize + len <= XXH3_INTERNALBUFFER_SIZE) {
+ XXH_memcpy(state->buffer + state->bufferedSize, input, len);
+ state->bufferedSize += (XXH32_hash_t)len;
+ return XXH_OK;
+ }
+
+ /* total input is now > XXH3_INTERNALBUFFER_SIZE */
+ #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN)
+ XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */
+
+ /*
+ * Internal buffer is partially filled (always, except at beginning)
+ * Complete it, then consume it.
+ */
+ if (state->bufferedSize) {
+ size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize;
+ XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize);
+ input += loadSize;
+ XXH3_consumeStripes(acc,
+ &state->nbStripesSoFar, state->nbStripesPerBlock,
+ state->buffer, XXH3_INTERNALBUFFER_STRIPES,
+ secret, state->secretLimit,
+ f_acc512, f_scramble);
+ state->bufferedSize = 0;
+ }
+ XXH_ASSERT(input < bEnd);
+
+ /* large input to consume : ingest per full block */
+ if ((size_t)(bEnd - input) > state->nbStripesPerBlock * XXH_STRIPE_LEN) {
+ size_t nbStripes = (size_t)(bEnd - 1 - input) / XXH_STRIPE_LEN;
+ XXH_ASSERT(state->nbStripesPerBlock >= state->nbStripesSoFar);
+ /* join to current block's end */
+ { size_t const nbStripesToEnd = state->nbStripesPerBlock - state->nbStripesSoFar;
+ XXH_ASSERT(nbStripesToEnd <= nbStripes);
+ XXH3_accumulate(acc, input, secret + state->nbStripesSoFar * XXH_SECRET_CONSUME_RATE, nbStripesToEnd, f_acc512);
+ f_scramble(acc, secret + state->secretLimit);
+ state->nbStripesSoFar = 0;
+ input += nbStripesToEnd * XXH_STRIPE_LEN;
+ nbStripes -= nbStripesToEnd;
+ }
+ /* consume per entire blocks */
+ while(nbStripes >= state->nbStripesPerBlock) {
+ XXH3_accumulate(acc, input, secret, state->nbStripesPerBlock, f_acc512);
+ f_scramble(acc, secret + state->secretLimit);
+ input += state->nbStripesPerBlock * XXH_STRIPE_LEN;
+ nbStripes -= state->nbStripesPerBlock;
+ }
+ /* consume last partial block */
+ XXH3_accumulate(acc, input, secret, nbStripes, f_acc512);
+ input += nbStripes * XXH_STRIPE_LEN;
+ XXH_ASSERT(input < bEnd); /* at least some bytes left */
+ state->nbStripesSoFar = nbStripes;
+ /* buffer predecessor of last partial stripe */
+ XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);
+ XXH_ASSERT(bEnd - input <= XXH_STRIPE_LEN);
+ } else {
+ /* content to consume <= block size */
+ /* Consume input by a multiple of internal buffer size */
+ if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {
+ const xxh_u8* const limit = bEnd - XXH3_INTERNALBUFFER_SIZE;
+ do {
+ XXH3_consumeStripes(acc,
+ &state->nbStripesSoFar, state->nbStripesPerBlock,
+ input, XXH3_INTERNALBUFFER_STRIPES,
+ secret, state->secretLimit,
+ f_acc512, f_scramble);
+ input += XXH3_INTERNALBUFFER_SIZE;
+ } while (input<limit);
+ /* buffer predecessor of last partial stripe */
+ XXH_memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);
+ }
+ }
+
+ /* Some remaining input (always) : buffer it */
+ XXH_ASSERT(input < bEnd);
+ XXH_ASSERT(bEnd - input <= XXH3_INTERNALBUFFER_SIZE);
+ XXH_ASSERT(state->bufferedSize == 0);
+ XXH_memcpy(state->buffer, input, (size_t)(bEnd-input));
+ state->bufferedSize = (XXH32_hash_t)(bEnd-input);
+#if defined(XXH3_STREAM_USE_STACK) && XXH3_STREAM_USE_STACK >= 1
+ /* save stack accumulators into state */
+ memcpy(state->acc, acc, sizeof(acc));
+#endif
+ }
+
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_64bits_update(XXH3_state_t* state, const void* input, size_t len)
+{
+ return XXH3_update(state, (const xxh_u8*)input, len,
+ XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+
+XXH_FORCE_INLINE void
+XXH3_digest_long (XXH64_hash_t* acc,
+ const XXH3_state_t* state,
+ const unsigned char* secret)
+{
+ /*
+ * Digest on a local copy. This way, the state remains unaltered, and it can
+ * continue ingesting more input afterwards.
+ */
+ XXH_memcpy(acc, state->acc, sizeof(state->acc));
+ if (state->bufferedSize >= XXH_STRIPE_LEN) {
+ size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN;
+ size_t nbStripesSoFar = state->nbStripesSoFar;
+ XXH3_consumeStripes(acc,
+ &nbStripesSoFar, state->nbStripesPerBlock,
+ state->buffer, nbStripes,
+ secret, state->secretLimit,
+ XXH3_accumulate_512, XXH3_scrambleAcc);
+ /* last stripe */
+ XXH3_accumulate_512(acc,
+ state->buffer + state->bufferedSize - XXH_STRIPE_LEN,
+ secret + state->secretLimit - XXH_SECRET_LASTACC_START);
+ } else { /* bufferedSize < XXH_STRIPE_LEN */
+ xxh_u8 lastStripe[XXH_STRIPE_LEN];
+ size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize;
+ XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */
+ XXH_memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize);
+ XXH_memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize);
+ XXH3_accumulate_512(acc,
+ lastStripe,
+ secret + state->secretLimit - XXH_SECRET_LASTACC_START);
+ }
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state)
+{
+ const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
+ if (state->totalLen > XXH3_MIDSIZE_MAX) {
+ XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
+ XXH3_digest_long(acc, state, secret);
+ return XXH3_mergeAccs(acc,
+ secret + XXH_SECRET_MERGEACCS_START,
+ (xxh_u64)state->totalLen * XXH_PRIME64_1);
+ }
+ /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */
+ if (state->useSeed)
+ return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
+ return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen),
+ secret, state->secretLimit + XXH_STRIPE_LEN);
+}
+
+
+
+/* ==========================================
+ * XXH3 128 bits (a.k.a XXH128)
+ * ==========================================
+ * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant,
+ * even without counting the significantly larger output size.
+ *
+ * For example, extra steps are taken to avoid the seed-dependent collisions
+ * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B).
+ *
+ * This strength naturally comes at the cost of some speed, especially on short
+ * lengths. Note that longer hashes are about as fast as the 64-bit version
+ * due to it using only a slight modification of the 64-bit loop.
+ *
+ * XXH128 is also more oriented towards 64-bit machines. It is still extremely
+ * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64).
+ */
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ /* A doubled version of 1to3_64b with different constants. */
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(1 <= len && len <= 3);
+ XXH_ASSERT(secret != NULL);
+ /*
+ * len = 1: combinedl = { input[0], 0x01, input[0], input[0] }
+ * len = 2: combinedl = { input[1], 0x02, input[0], input[1] }
+ * len = 3: combinedl = { input[2], 0x03, input[0], input[1] }
+ */
+ { xxh_u8 const c1 = input[0];
+ xxh_u8 const c2 = input[len >> 1];
+ xxh_u8 const c3 = input[len - 1];
+ xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24)
+ | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8);
+ xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13);
+ xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed;
+ xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed;
+ xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl;
+ xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph;
+ XXH128_hash_t h128;
+ h128.low64 = XXH64_avalanche(keyed_lo);
+ h128.high64 = XXH64_avalanche(keyed_hi);
+ return h128;
+ }
+}
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(secret != NULL);
+ XXH_ASSERT(4 <= len && len <= 8);
+ seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32;
+ { xxh_u32 const input_lo = XXH_readLE32(input);
+ xxh_u32 const input_hi = XXH_readLE32(input + len - 4);
+ xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32);
+ xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed;
+ xxh_u64 const keyed = input_64 ^ bitflip;
+
+ /* Shift len to the left to ensure it is even, this avoids even multiplies. */
+ XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2));
+
+ m128.high64 += (m128.low64 << 1);
+ m128.low64 ^= (m128.high64 >> 3);
+
+ m128.low64 = XXH_xorshift64(m128.low64, 35);
+ m128.low64 *= 0x9FB21C651E98DF25ULL;
+ m128.low64 = XXH_xorshift64(m128.low64, 28);
+ m128.high64 = XXH3_avalanche(m128.high64);
+ return m128;
+ }
+}
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(input != NULL);
+ XXH_ASSERT(secret != NULL);
+ XXH_ASSERT(9 <= len && len <= 16);
+ { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed;
+ xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed;
+ xxh_u64 const input_lo = XXH_readLE64(input);
+ xxh_u64 input_hi = XXH_readLE64(input + len - 8);
+ XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1);
+ /*
+ * Put len in the middle of m128 to ensure that the length gets mixed to
+ * both the low and high bits in the 128x64 multiply below.
+ */
+ m128.low64 += (xxh_u64)(len - 1) << 54;
+ input_hi ^= bitfliph;
+ /*
+ * Add the high 32 bits of input_hi to the high 32 bits of m128, then
+ * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to
+ * the high 64 bits of m128.
+ *
+ * The best approach to this operation is different on 32-bit and 64-bit.
+ */
+ if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */
+ /*
+ * 32-bit optimized version, which is more readable.
+ *
+ * On 32-bit, it removes an ADC and delays a dependency between the two
+ * halves of m128.high64, but it generates an extra mask on 64-bit.
+ */
+ m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2);
+ } else {
+ /*
+ * 64-bit optimized (albeit more confusing) version.
+ *
+ * Uses some properties of addition and multiplication to remove the mask:
+ *
+ * Let:
+ * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF)
+ * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000)
+ * c = XXH_PRIME32_2
+ *
+ * a + (b * c)
+ * Inverse Property: x + y - x == y
+ * a + (b * (1 + c - 1))
+ * Distributive Property: x * (y + z) == (x * y) + (x * z)
+ * a + (b * 1) + (b * (c - 1))
+ * Identity Property: x * 1 == x
+ * a + b + (b * (c - 1))
+ *
+ * Substitute a, b, and c:
+ * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
+ *
+ * Since input_hi.hi + input_hi.lo == input_hi, we get this:
+ * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1))
+ */
+ m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1);
+ }
+ /* m128 ^= XXH_swap64(m128 >> 64); */
+ m128.low64 ^= XXH_swap64(m128.high64);
+
+ { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */
+ XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2);
+ h128.high64 += m128.high64 * XXH_PRIME64_2;
+
+ h128.low64 = XXH3_avalanche(h128.low64);
+ h128.high64 = XXH3_avalanche(h128.high64);
+ return h128;
+ } }
+}
+
+/*
+ * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN
+ */
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed)
+{
+ XXH_ASSERT(len <= 16);
+ { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed);
+ if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed);
+ if (len) return XXH3_len_1to3_128b(input, len, secret, seed);
+ { XXH128_hash_t h128;
+ xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72);
+ xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88);
+ h128.low64 = XXH64_avalanche(seed ^ bitflipl);
+ h128.high64 = XXH64_avalanche( seed ^ bitfliph);
+ return h128;
+ } }
+}
+
+/*
+ * A bit slower than XXH3_mix16B, but handles multiply by zero better.
+ */
+XXH_FORCE_INLINE XXH128_hash_t
+XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2,
+ const xxh_u8* secret, XXH64_hash_t seed)
+{
+ acc.low64 += XXH3_mix16B (input_1, secret+0, seed);
+ acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8);
+ acc.high64 += XXH3_mix16B (input_2, secret+16, seed);
+ acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8);
+ return acc;
+}
+
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH64_hash_t seed)
+{
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
+ XXH_ASSERT(16 < len && len <= 128);
+
+ { XXH128_hash_t acc;
+ acc.low64 = len * XXH_PRIME64_1;
+ acc.high64 = 0;
+ if (len > 32) {
+ if (len > 64) {
+ if (len > 96) {
+ acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed);
+ }
+ acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed);
+ }
+ acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed);
+ }
+ acc = XXH128_mix32B(acc, input, input+len-16, secret, seed);
+ { XXH128_hash_t h128;
+ h128.low64 = acc.low64 + acc.high64;
+ h128.high64 = (acc.low64 * XXH_PRIME64_1)
+ + (acc.high64 * XXH_PRIME64_4)
+ + ((len - seed) * XXH_PRIME64_2);
+ h128.low64 = XXH3_avalanche(h128.low64);
+ h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);
+ return h128;
+ }
+ }
+}
+
+XXH_NO_INLINE XXH128_hash_t
+XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH64_hash_t seed)
+{
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
+ XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX);
+
+ { XXH128_hash_t acc;
+ int const nbRounds = (int)len / 32;
+ int i;
+ acc.low64 = len * XXH_PRIME64_1;
+ acc.high64 = 0;
+ for (i=0; i<4; i++) {
+ acc = XXH128_mix32B(acc,
+ input + (32 * i),
+ input + (32 * i) + 16,
+ secret + (32 * i),
+ seed);
+ }
+ acc.low64 = XXH3_avalanche(acc.low64);
+ acc.high64 = XXH3_avalanche(acc.high64);
+ XXH_ASSERT(nbRounds >= 4);
+ for (i=4 ; i < nbRounds; i++) {
+ acc = XXH128_mix32B(acc,
+ input + (32 * i),
+ input + (32 * i) + 16,
+ secret + XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)),
+ seed);
+ }
+ /* last bytes */
+ acc = XXH128_mix32B(acc,
+ input + len - 16,
+ input + len - 32,
+ secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16,
+ 0ULL - seed);
+
+ { XXH128_hash_t h128;
+ h128.low64 = acc.low64 + acc.high64;
+ h128.high64 = (acc.low64 * XXH_PRIME64_1)
+ + (acc.high64 * XXH_PRIME64_4)
+ + ((len - seed) * XXH_PRIME64_2);
+ h128.low64 = XXH3_avalanche(h128.low64);
+ h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64);
+ return h128;
+ }
+ }
+}
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len,
+ const xxh_u8* XXH_RESTRICT secret, size_t secretSize,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble)
+{
+ XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC;
+
+ XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc512, f_scramble);
+
+ /* converge into final hash */
+ XXH_STATIC_ASSERT(sizeof(acc) == 64);
+ XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
+ { XXH128_hash_t h128;
+ h128.low64 = XXH3_mergeAccs(acc,
+ secret + XXH_SECRET_MERGEACCS_START,
+ (xxh_u64)len * XXH_PRIME64_1);
+ h128.high64 = XXH3_mergeAccs(acc,
+ secret + secretSize
+ - sizeof(acc) - XXH_SECRET_MERGEACCS_START,
+ ~((xxh_u64)len * XXH_PRIME64_2));
+ return h128;
+ }
+}
+
+/*
+ * It's important for performance that XXH3_hashLong is not inlined.
+ */
+XXH_NO_INLINE XXH128_hash_t
+XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64,
+ const void* XXH_RESTRICT secret, size_t secretLen)
+{
+ (void)seed64; (void)secret; (void)secretLen;
+ return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret),
+ XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+/*
+ * It's important for performance to pass @secretLen (when it's static)
+ * to the compiler, so that it can properly optimize the vectorized loop.
+ */
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64,
+ const void* XXH_RESTRICT secret, size_t secretLen)
+{
+ (void)seed64;
+ return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen,
+ XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len,
+ XXH64_hash_t seed64,
+ XXH3_f_accumulate_512 f_acc512,
+ XXH3_f_scrambleAcc f_scramble,
+ XXH3_f_initCustomSecret f_initSec)
+{
+ if (seed64 == 0)
+ return XXH3_hashLong_128b_internal(input, len,
+ XXH3_kSecret, sizeof(XXH3_kSecret),
+ f_acc512, f_scramble);
+ { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
+ f_initSec(secret, seed64);
+ return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret),
+ f_acc512, f_scramble);
+ }
+}
+
+/*
+ * It's important for performance that XXH3_hashLong is not inlined.
+ */
+XXH_NO_INLINE XXH128_hash_t
+XXH3_hashLong_128b_withSeed(const void* input, size_t len,
+ XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen)
+{
+ (void)secret; (void)secretLen;
+ return XXH3_hashLong_128b_withSeed_internal(input, len, seed64,
+ XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret);
+}
+
+typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t,
+ XXH64_hash_t, const void* XXH_RESTRICT, size_t);
+
+XXH_FORCE_INLINE XXH128_hash_t
+XXH3_128bits_internal(const void* input, size_t len,
+ XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen,
+ XXH3_hashLong128_f f_hl128)
+{
+ XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN);
+ /*
+ * If an action is to be taken if `secret` conditions are not respected,
+ * it should be done here.
+ * For now, it's a contract pre-condition.
+ * Adding a check and a branch here would cost performance at every hash.
+ */
+ if (len <= 16)
+ return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64);
+ if (len <= 128)
+ return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
+ if (len <= XXH3_MIDSIZE_MAX)
+ return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64);
+ return f_hl128(input, len, seed64, secret, secretLen);
+}
+
+
+/* === Public XXH128 API === */
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* input, size_t len)
+{
+ return XXH3_128bits_internal(input, len, 0,
+ XXH3_kSecret, sizeof(XXH3_kSecret),
+ XXH3_hashLong_128b_default);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t
+XXH3_128bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize)
+{
+ return XXH3_128bits_internal(input, len, 0,
+ (const xxh_u8*)secret, secretSize,
+ XXH3_hashLong_128b_withSecret);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t
+XXH3_128bits_withSeed(const void* input, size_t len, XXH64_hash_t seed)
+{
+ return XXH3_128bits_internal(input, len, seed,
+ XXH3_kSecret, sizeof(XXH3_kSecret),
+ XXH3_hashLong_128b_withSeed);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t
+XXH3_128bits_withSecretandSeed(const void* input, size_t len, const void* secret, size_t secretSize, XXH64_hash_t seed)
+{
+ if (len <= XXH3_MIDSIZE_MAX)
+ return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), NULL);
+ return XXH3_hashLong_128b_withSecret(input, len, seed, secret, secretSize);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t
+XXH128(const void* input, size_t len, XXH64_hash_t seed)
+{
+ return XXH3_128bits_withSeed(input, len, seed);
+}
+
+
+/* === XXH3 128-bit streaming === */
+
+/*
+ * All initialization and update functions are identical to 64-bit streaming variant.
+ * The only difference is the finalization routine.
+ */
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_reset(XXH3_state_t* statePtr)
+{
+ return XXH3_64bits_reset(statePtr);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize)
+{
+ return XXH3_64bits_reset_withSecret(statePtr, secret, secretSize);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed)
+{
+ return XXH3_64bits_reset_withSeed(statePtr, seed);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_reset_withSecretandSeed(XXH3_state_t* statePtr, const void* secret, size_t secretSize, XXH64_hash_t seed)
+{
+ return XXH3_64bits_reset_withSecretandSeed(statePtr, secret, secretSize, seed);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_128bits_update(XXH3_state_t* state, const void* input, size_t len)
+{
+ return XXH3_update(state, (const xxh_u8*)input, len,
+ XXH3_accumulate_512, XXH3_scrambleAcc);
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state)
+{
+ const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
+ if (state->totalLen > XXH3_MIDSIZE_MAX) {
+ XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
+ XXH3_digest_long(acc, state, secret);
+ XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
+ { XXH128_hash_t h128;
+ h128.low64 = XXH3_mergeAccs(acc,
+ secret + XXH_SECRET_MERGEACCS_START,
+ (xxh_u64)state->totalLen * XXH_PRIME64_1);
+ h128.high64 = XXH3_mergeAccs(acc,
+ secret + state->secretLimit + XXH_STRIPE_LEN
+ - sizeof(acc) - XXH_SECRET_MERGEACCS_START,
+ ~((xxh_u64)state->totalLen * XXH_PRIME64_2));
+ return h128;
+ }
+ }
+ /* len <= XXH3_MIDSIZE_MAX : short code */
+ if (state->seed)
+ return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
+ return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen),
+ secret, state->secretLimit + XXH_STRIPE_LEN);
+}
+
+/* 128-bit utility functions */
+
+#include <string.h> /* memcmp, memcpy */
+
+/* return : 1 is equal, 0 if different */
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)
+{
+ /* note : XXH128_hash_t is compact, it has no padding byte */
+ return !(memcmp(&h1, &h2, sizeof(h1)));
+}
+
+/* This prototype is compatible with stdlib's qsort().
+ * return : >0 if *h128_1 > *h128_2
+ * <0 if *h128_1 < *h128_2
+ * =0 if *h128_1 == *h128_2 */
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2)
+{
+ XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1;
+ XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2;
+ int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64);
+ /* note : bets that, in most cases, hash values are different */
+ if (hcmp) return hcmp;
+ return (h1.low64 > h2.low64) - (h2.low64 > h1.low64);
+}
+
+
+/*====== Canonical representation ======*/
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API void
+XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash)
+{
+ XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t));
+ if (XXH_CPU_LITTLE_ENDIAN) {
+ hash.high64 = XXH_swap64(hash.high64);
+ hash.low64 = XXH_swap64(hash.low64);
+ }
+ XXH_memcpy(dst, &hash.high64, sizeof(hash.high64));
+ XXH_memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64));
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH128_hash_t
+XXH128_hashFromCanonical(const XXH128_canonical_t* src)
+{
+ XXH128_hash_t h;
+ h.high64 = XXH_readBE64(src);
+ h.low64 = XXH_readBE64(src->digest + 8);
+ return h;
+}
+
+
+
+/* ==========================================
+ * Secret generators
+ * ==========================================
+ */
+#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x))
+
+XXH_FORCE_INLINE void XXH3_combine16(void* dst, XXH128_hash_t h128)
+{
+ XXH_writeLE64( dst, XXH_readLE64(dst) ^ h128.low64 );
+ XXH_writeLE64( (char*)dst+8, XXH_readLE64((char*)dst+8) ^ h128.high64 );
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API XXH_errorcode
+XXH3_generateSecret(void* secretBuffer, size_t secretSize, const void* customSeed, size_t customSeedSize)
+{
+#if (XXH_DEBUGLEVEL >= 1)
+ XXH_ASSERT(secretBuffer != NULL);
+ XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
+#else
+ /* production mode, assert() are disabled */
+ if (secretBuffer == NULL) return XXH_ERROR;
+ if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
+#endif
+
+ if (customSeedSize == 0) {
+ customSeed = XXH3_kSecret;
+ customSeedSize = XXH_SECRET_DEFAULT_SIZE;
+ }
+#if (XXH_DEBUGLEVEL >= 1)
+ XXH_ASSERT(customSeed != NULL);
+#else
+ if (customSeed == NULL) return XXH_ERROR;
+#endif
+
+ /* Fill secretBuffer with a copy of customSeed - repeat as needed */
+ { size_t pos = 0;
+ while (pos < secretSize) {
+ size_t const toCopy = XXH_MIN((secretSize - pos), customSeedSize);
+ memcpy((char*)secretBuffer + pos, customSeed, toCopy);
+ pos += toCopy;
+ } }
+
+ { size_t const nbSeg16 = secretSize / 16;
+ size_t n;
+ XXH128_canonical_t scrambler;
+ XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0));
+ for (n=0; n<nbSeg16; n++) {
+ XXH128_hash_t const h128 = XXH128(&scrambler, sizeof(scrambler), n);
+ XXH3_combine16((char*)secretBuffer + n*16, h128);
+ }
+ /* last segment */
+ XXH3_combine16((char*)secretBuffer + secretSize - 16, XXH128_hashFromCanonical(&scrambler));
+ }
+ return XXH_OK;
+}
+
+/*! @ingroup xxh3_family */
+XXH_PUBLIC_API void
+XXH3_generateSecret_fromSeed(void* secretBuffer, XXH64_hash_t seed)
+{
+ XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE];
+ XXH3_initCustomSecret(secret, seed);
+ XXH_ASSERT(secretBuffer != NULL);
+ memcpy(secretBuffer, secret, XXH_SECRET_DEFAULT_SIZE);
+}
+
+
+
+/* Pop our optimization override from above */
+#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \
+ && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \
+ && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */
+# pragma GCC pop_options
+#endif
+
+#endif /* XXH_NO_LONG_LONG */
+
+#endif /* XXH_NO_XXH3 */
+
+/*!
+ * @}
+ */
+#endif /* XXH_IMPLEMENTATION */
#if defined (__cplusplus)
diff --git a/thirdparty/zstd/common/zstd_internal.h b/thirdparty/zstd/common/zstd_internal.h
index 68252e987e..e4d36ce090 100644
--- a/thirdparty/zstd/common/zstd_internal.h
+++ b/thirdparty/zstd/common/zstd_internal.h
@@ -19,10 +19,8 @@
/*-*************************************
* Dependencies
***************************************/
-#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
-#include <arm_neon.h>
-#endif
#include "compiler.h"
+#include "cpu.h"
#include "mem.h"
#include "debug.h" /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
#include "error_private.h"
@@ -60,81 +58,7 @@ extern "C" {
#undef MAX
#define MIN(a,b) ((a)<(b) ? (a) : (b))
#define MAX(a,b) ((a)>(b) ? (a) : (b))
-
-/**
- * Ignore: this is an internal helper.
- *
- * This is a helper function to help force C99-correctness during compilation.
- * Under strict compilation modes, variadic macro arguments can't be empty.
- * However, variadic function arguments can be. Using a function therefore lets
- * us statically check that at least one (string) argument was passed,
- * independent of the compilation flags.
- */
-static INLINE_KEYWORD UNUSED_ATTR
-void _force_has_format_string(const char *format, ...) {
- (void)format;
-}
-
-/**
- * Ignore: this is an internal helper.
- *
- * We want to force this function invocation to be syntactically correct, but
- * we don't want to force runtime evaluation of its arguments.
- */
-#define _FORCE_HAS_FORMAT_STRING(...) \
- if (0) { \
- _force_has_format_string(__VA_ARGS__); \
- }
-
-/**
- * Return the specified error if the condition evaluates to true.
- *
- * In debug modes, prints additional information.
- * In order to do that (particularly, printing the conditional that failed),
- * this can't just wrap RETURN_ERROR().
- */
-#define RETURN_ERROR_IF(cond, err, ...) \
- if (cond) { \
- RAWLOG(3, "%s:%d: ERROR!: check %s failed, returning %s", \
- __FILE__, __LINE__, ZSTD_QUOTE(cond), ZSTD_QUOTE(ERROR(err))); \
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
- RAWLOG(3, ": " __VA_ARGS__); \
- RAWLOG(3, "\n"); \
- return ERROR(err); \
- }
-
-/**
- * Unconditionally return the specified error.
- *
- * In debug modes, prints additional information.
- */
-#define RETURN_ERROR(err, ...) \
- do { \
- RAWLOG(3, "%s:%d: ERROR!: unconditional check failed, returning %s", \
- __FILE__, __LINE__, ZSTD_QUOTE(ERROR(err))); \
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
- RAWLOG(3, ": " __VA_ARGS__); \
- RAWLOG(3, "\n"); \
- return ERROR(err); \
- } while(0);
-
-/**
- * If the provided expression evaluates to an error code, returns that error code.
- *
- * In debug modes, prints additional information.
- */
-#define FORWARD_IF_ERROR(err, ...) \
- do { \
- size_t const err_code = (err); \
- if (ERR_isError(err_code)) { \
- RAWLOG(3, "%s:%d: ERROR!: forwarding error in %s: %s", \
- __FILE__, __LINE__, ZSTD_QUOTE(err), ERR_getErrorName(err_code)); \
- _FORCE_HAS_FORMAT_STRING(__VA_ARGS__); \
- RAWLOG(3, ": " __VA_ARGS__); \
- RAWLOG(3, "\n"); \
- return err_code; \
- } \
- } while(0);
+#define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))
/*-*************************************
@@ -143,7 +67,6 @@ void _force_has_format_string(const char *format, ...) {
#define ZSTD_OPT_NUM (1<<12)
#define ZSTD_REP_NUM 3 /* number of repcodes */
-#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
#define KB *(1 <<10)
@@ -195,7 +118,7 @@ typedef enum { set_basic, set_rle, set_compressed, set_repeat } symbolEncodingTy
/* Each table cannot take more than #symbols * FSELog bits */
#define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
-static UNUSED_ATTR const U32 LL_bits[MaxLL+1] = {
+static UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 2, 2, 3, 3,
@@ -212,7 +135,7 @@ static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
#define LL_DEFAULTNORMLOG 6 /* for static allocation */
static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
-static UNUSED_ATTR const U32 ML_bits[MaxML+1] = {
+static UNUSED_ATTR const U8 ML_bits[MaxML+1] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
@@ -247,19 +170,30 @@ static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
* Shared functions to include for inlining
*********************************************/
static void ZSTD_copy8(void* dst, const void* src) {
-#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
+#if defined(ZSTD_ARCH_ARM_NEON)
vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));
#else
ZSTD_memcpy(dst, src, 8);
#endif
}
-
#define COPY8(d,s) { ZSTD_copy8(d,s); d+=8; s+=8; }
+
+/* Need to use memmove here since the literal buffer can now be located within
+ the dst buffer. In circumstances where the op "catches up" to where the
+ literal buffer is, there can be partial overlaps in this call on the final
+ copy if the literal is being shifted by less than 16 bytes. */
static void ZSTD_copy16(void* dst, const void* src) {
-#if !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON)
+#if defined(ZSTD_ARCH_ARM_NEON)
vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
+#elif defined(ZSTD_ARCH_X86_SSE2)
+ _mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));
+#elif defined(__clang__)
+ ZSTD_memmove(dst, src, 16);
#else
- ZSTD_memcpy(dst, src, 16);
+ /* ZSTD_memmove is not inlined properly by gcc */
+ BYTE copy16_buf[16];
+ ZSTD_memcpy(copy16_buf, src, 16);
+ ZSTD_memcpy(dst, copy16_buf, 16);
#endif
}
#define COPY16(d,s) { ZSTD_copy16(d,s); d+=16; s+=16; }
@@ -288,8 +222,6 @@ void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e
BYTE* op = (BYTE*)dst;
BYTE* const oend = op + length;
- assert(diff >= 8 || (ovtype == ZSTD_no_overlap && diff <= -WILDCOPY_VECLEN));
-
if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
/* Handle short offset copies. */
do {
@@ -352,9 +284,9 @@ typedef enum {
* Private declarations
*********************************************/
typedef struct seqDef_s {
- U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */
+ U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */
U16 litLength;
- U16 matchLength;
+ U16 mlBase; /* mlBase == matchLength - MINMATCH */
} seqDef;
/* Controls whether seqStore has a single "long" litLength or matchLength. See seqStore_t. */
@@ -396,7 +328,7 @@ MEM_STATIC ZSTD_sequenceLength ZSTD_getSequenceLength(seqStore_t const* seqStore
{
ZSTD_sequenceLength seqLen;
seqLen.litLength = seq->litLength;
- seqLen.matchLength = seq->matchLength + MINMATCH;
+ seqLen.matchLength = seq->mlBase + MINMATCH;
if (seqStore->longLengthPos == (U32)(seq - seqStore->sequencesStart)) {
if (seqStore->longLengthType == ZSTD_llt_literalLength) {
seqLen.litLength += 0xFFFF;
@@ -436,8 +368,14 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus
# if STATIC_BMI2 == 1
return _lzcnt_u32(val)^31;
# else
- unsigned long r=0;
- return _BitScanReverse(&r, val) ? (unsigned)r : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanReverse(&r, val);
+ return (unsigned)r;
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# endif
# elif defined(__GNUC__) && (__GNUC__ >= 3) /* GCC Intrinsic */
return __builtin_clz (val) ^ 31;
@@ -456,6 +394,63 @@ MEM_STATIC U32 ZSTD_highbit32(U32 val) /* compress, dictBuilder, decodeCorpus
}
}
+/**
+ * Counts the number of trailing zeros of a `size_t`.
+ * Most compilers should support CTZ as a builtin. A backup
+ * implementation is provided if the builtin isn't supported, but
+ * it may not be terribly efficient.
+ */
+MEM_STATIC unsigned ZSTD_countTrailingZeros(size_t val)
+{
+ if (MEM_64bits()) {
+# if defined(_MSC_VER) && defined(_WIN64)
+# if STATIC_BMI2
+ return _tzcnt_u64(val);
+# else
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward64(&r, (U64)val);
+ return (unsigned)r;
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
+# endif
+# elif defined(__GNUC__) && (__GNUC__ >= 4)
+ return __builtin_ctzll((U64)val);
+# else
+ static const int DeBruijnBytePos[64] = { 0, 1, 2, 7, 3, 13, 8, 19,
+ 4, 25, 14, 28, 9, 34, 20, 56,
+ 5, 17, 26, 54, 15, 41, 29, 43,
+ 10, 31, 38, 35, 21, 45, 49, 57,
+ 63, 6, 12, 18, 24, 27, 33, 55,
+ 16, 53, 40, 42, 30, 37, 44, 48,
+ 62, 11, 23, 32, 52, 39, 36, 47,
+ 61, 22, 51, 46, 60, 50, 59, 58 };
+ return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
+# endif
+ } else { /* 32 bits */
+# if defined(_MSC_VER)
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward(&r, (U32)val);
+ return (unsigned)r;
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
+# elif defined(__GNUC__) && (__GNUC__ >= 3)
+ return __builtin_ctz((U32)val);
+# else
+ static const int DeBruijnBytePos[32] = { 0, 1, 28, 2, 29, 14, 24, 3,
+ 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7,
+ 26, 12, 18, 6, 11, 5, 10, 9 };
+ return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
+# endif
+ }
+}
+
/* ZSTD_invalidateRepCodes() :
* ensures next compression will not use repcodes from previous block.
@@ -482,6 +477,14 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
const void* src, size_t srcSize);
+/**
+ * @returns true iff the CPU supports dynamic BMI2 dispatch.
+ */
+MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
+{
+ ZSTD_cpuid_t cpuid = ZSTD_cpuid();
+ return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
+}
#if defined (__cplusplus)
}
diff --git a/thirdparty/zstd/common/zstd_trace.h b/thirdparty/zstd/common/zstd_trace.h
index 2da5640771..f9121f7d8e 100644
--- a/thirdparty/zstd/common/zstd_trace.h
+++ b/thirdparty/zstd/common/zstd_trace.h
@@ -17,10 +17,19 @@ extern "C" {
#include <stddef.h>
-/* weak symbol support */
-#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && defined(__GNUC__) && \
+/* weak symbol support
+ * For now, enable conservatively:
+ * - Only GNUC
+ * - Only ELF
+ * - Only x86-64 and i386
+ * Also, explicitly disable on platforms known not to work so they aren't
+ * forgotten in the future.
+ */
+#if !defined(ZSTD_HAVE_WEAK_SYMBOLS) && \
+ defined(__GNUC__) && defined(__ELF__) && \
+ (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86)) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__MINGW32__) && \
- !defined(__CYGWIN__)
+ !defined(__CYGWIN__) && !defined(_AIX)
# define ZSTD_HAVE_WEAK_SYMBOLS 1
#else
# define ZSTD_HAVE_WEAK_SYMBOLS 0
diff --git a/thirdparty/zstd/compress/clevels.h b/thirdparty/zstd/compress/clevels.h
new file mode 100644
index 0000000000..7ed2e00490
--- /dev/null
+++ b/thirdparty/zstd/compress/clevels.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) Yann Collet, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#ifndef ZSTD_CLEVELS_H
+#define ZSTD_CLEVELS_H
+
+#define ZSTD_STATIC_LINKING_ONLY /* ZSTD_compressionParameters */
+#include "../zstd.h"
+
+/*-===== Pre-defined compression levels =====-*/
+
+#define ZSTD_MAX_CLEVEL 22
+
+#ifdef __GNUC__
+__attribute__((__unused__))
+#endif
+
+static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
+{ /* "default" - for any srcSize > 256 KB */
+ /* W, C, H, S, L, TL, strat */
+ { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
+ { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
+ { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
+ { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
+ { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
+ { 21, 18, 19, 3, 5, 2, ZSTD_greedy }, /* level 5 */
+ { 21, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6 */
+ { 21, 19, 20, 4, 5, 8, ZSTD_lazy }, /* level 7 */
+ { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 8 */
+ { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
+ { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 10 */
+ { 22, 21, 22, 6, 5, 16, ZSTD_lazy2 }, /* level 11 */
+ { 22, 22, 23, 6, 5, 32, ZSTD_lazy2 }, /* level 12 */
+ { 22, 22, 22, 4, 5, 32, ZSTD_btlazy2 }, /* level 13 */
+ { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
+ { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
+ { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */
+ { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */
+ { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */
+ { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */
+ { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */
+ { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */
+ { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */
+},
+{ /* for srcSize <= 256 KB */
+ /* W, C, H, S, L, T, strat */
+ { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
+ { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
+ { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
+ { 18, 16, 17, 3, 5, 2, ZSTD_greedy }, /* level 4.*/
+ { 18, 17, 18, 5, 5, 2, ZSTD_greedy }, /* level 5.*/
+ { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
+ { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
+ { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
+ { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
+ { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
+ { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/
+ { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/
+ { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */
+ { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
+ { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/
+ { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/
+ { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/
+ { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/
+ { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/
+},
+{ /* for srcSize <= 128 KB */
+ /* W, C, H, S, L, T, strat */
+ { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
+ { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
+ { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
+ { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
+ { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
+ { 17, 16, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
+ { 17, 16, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
+ { 17, 16, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
+ { 17, 16, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
+ { 17, 16, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
+ { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */
+ { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */
+ { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/
+ { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
+ { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/
+ { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/
+ { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/
+ { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/
+ { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/
+},
+{ /* for srcSize <= 16 KB */
+ /* W, C, H, S, L, T, strat */
+ { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
+ { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
+ { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
+ { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
+ { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
+ { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
+ { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
+ { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
+ { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
+ { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
+ { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
+ { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
+ { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/
+ { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/
+ { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/
+ { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/
+ { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/
+ { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/
+ { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/
+ { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
+ { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/
+ { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
+ { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
+},
+};
+
+
+
+#endif /* ZSTD_CLEVELS_H */
diff --git a/thirdparty/zstd/compress/fse_compress.c b/thirdparty/zstd/compress/fse_compress.c
index b4297ec88a..5547b4ac09 100644
--- a/thirdparty/zstd/compress/fse_compress.c
+++ b/thirdparty/zstd/compress/fse_compress.c
@@ -75,13 +75,14 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
void* const FSCT = ((U32*)ptr) + 1 /* header */ + (tableLog ? tableSize>>1 : 1) ;
FSE_symbolCompressionTransform* const symbolTT = (FSE_symbolCompressionTransform*) (FSCT);
U32 const step = FSE_TABLESTEP(tableSize);
+ U32 const maxSV1 = maxSymbolValue+1;
- U32* cumul = (U32*)workSpace;
- FSE_FUNCTION_TYPE* tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSymbolValue + 2));
+ U16* cumul = (U16*)workSpace; /* size = maxSV1 */
+ FSE_FUNCTION_TYPE* const tableSymbol = (FSE_FUNCTION_TYPE*)(cumul + (maxSV1+1)); /* size = tableSize */
U32 highThreshold = tableSize-1;
- if ((size_t)workSpace & 3) return ERROR(GENERIC); /* Must be 4 byte aligned */
+ assert(((size_t)workSpace & 1) == 0); /* Must be 2 bytes-aligned */
if (FSE_BUILD_CTABLE_WORKSPACE_SIZE(maxSymbolValue, tableLog) > wkspSize) return ERROR(tableLog_tooLarge);
/* CTable header */
tableU16[-2] = (U16) tableLog;
@@ -98,20 +99,61 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
/* symbol start positions */
{ U32 u;
cumul[0] = 0;
- for (u=1; u <= maxSymbolValue+1; u++) {
+ for (u=1; u <= maxSV1; u++) {
if (normalizedCounter[u-1]==-1) { /* Low proba symbol */
cumul[u] = cumul[u-1] + 1;
tableSymbol[highThreshold--] = (FSE_FUNCTION_TYPE)(u-1);
} else {
- cumul[u] = cumul[u-1] + normalizedCounter[u-1];
+ assert(normalizedCounter[u-1] >= 0);
+ cumul[u] = cumul[u-1] + (U16)normalizedCounter[u-1];
+ assert(cumul[u] >= cumul[u-1]); /* no overflow */
} }
- cumul[maxSymbolValue+1] = tableSize+1;
+ cumul[maxSV1] = (U16)(tableSize+1);
}
/* Spread symbols */
- { U32 position = 0;
+ if (highThreshold == tableSize - 1) {
+ /* Case for no low prob count symbols. Lay down 8 bytes at a time
+ * to reduce branch misses since we are operating on a small block
+ */
+ BYTE* const spread = tableSymbol + tableSize; /* size = tableSize + 8 (may write beyond tableSize) */
+ { U64 const add = 0x0101010101010101ull;
+ size_t pos = 0;
+ U64 sv = 0;
+ U32 s;
+ for (s=0; s<maxSV1; ++s, sv += add) {
+ int i;
+ int const n = normalizedCounter[s];
+ MEM_write64(spread + pos, sv);
+ for (i = 8; i < n; i += 8) {
+ MEM_write64(spread + pos + i, sv);
+ }
+ assert(n>=0);
+ pos += (size_t)n;
+ }
+ }
+ /* Spread symbols across the table. Lack of lowprob symbols means that
+ * we don't need variable sized inner loop, so we can unroll the loop and
+ * reduce branch misses.
+ */
+ { size_t position = 0;
+ size_t s;
+ size_t const unroll = 2; /* Experimentally determined optimal unroll */
+ assert(tableSize % unroll == 0); /* FSE_MIN_TABLELOG is 5 */
+ for (s = 0; s < (size_t)tableSize; s += unroll) {
+ size_t u;
+ for (u = 0; u < unroll; ++u) {
+ size_t const uPosition = (position + (u * step)) & tableMask;
+ tableSymbol[uPosition] = spread[s + u];
+ }
+ position = (position + (unroll * step)) & tableMask;
+ }
+ assert(position == 0); /* Must have initialized all positions */
+ }
+ } else {
+ U32 position = 0;
U32 symbol;
- for (symbol=0; symbol<=maxSymbolValue; symbol++) {
+ for (symbol=0; symbol<maxSV1; symbol++) {
int nbOccurrences;
int const freq = normalizedCounter[symbol];
for (nbOccurrences=0; nbOccurrences<freq; nbOccurrences++) {
@@ -120,7 +162,6 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
while (position > highThreshold)
position = (position + step) & tableMask; /* Low proba area */
} }
-
assert(position==0); /* Must have initialized all positions */
}
@@ -144,16 +185,17 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
case -1:
case 1:
symbolTT[s].deltaNbBits = (tableLog << 16) - (1<<tableLog);
- symbolTT[s].deltaFindState = total - 1;
+ assert(total <= INT_MAX);
+ symbolTT[s].deltaFindState = (int)(total - 1);
total ++;
break;
default :
- {
- U32 const maxBitsOut = tableLog - BIT_highbit32 (normalizedCounter[s]-1);
- U32 const minStatePlus = normalizedCounter[s] << maxBitsOut;
+ assert(normalizedCounter[s] > 1);
+ { U32 const maxBitsOut = tableLog - BIT_highbit32 ((U32)normalizedCounter[s]-1);
+ U32 const minStatePlus = (U32)normalizedCounter[s] << maxBitsOut;
symbolTT[s].deltaNbBits = (maxBitsOut << 16) - minStatePlus;
- symbolTT[s].deltaFindState = total - normalizedCounter[s];
- total += normalizedCounter[s];
+ symbolTT[s].deltaFindState = (int)(total - (unsigned)normalizedCounter[s]);
+ total += (unsigned)normalizedCounter[s];
} } } }
#if 0 /* debug : symbol costs */
@@ -164,32 +206,26 @@ size_t FSE_buildCTable_wksp(FSE_CTable* ct,
symbol, normalizedCounter[symbol],
FSE_getMaxNbBits(symbolTT, symbol),
(double)FSE_bitCost(symbolTT, tableLog, symbol, 8) / 256);
- }
- }
+ } }
#endif
return 0;
}
-#ifndef ZSTD_NO_UNUSED_FUNCTIONS
-size_t FSE_buildCTable(FSE_CTable* ct, const short* normalizedCounter, unsigned maxSymbolValue, unsigned tableLog)
-{
- FSE_FUNCTION_TYPE tableSymbol[FSE_MAX_TABLESIZE]; /* memset() is not necessary, even if static analyzer complain about it */
- return FSE_buildCTable_wksp(ct, normalizedCounter, maxSymbolValue, tableLog, tableSymbol, sizeof(tableSymbol));
-}
-#endif
-
#ifndef FSE_COMMONDEFS_ONLY
-
/*-**************************************************************
* FSE NCount encoding
****************************************************************/
size_t FSE_NCountWriteBound(unsigned maxSymbolValue, unsigned tableLog)
{
- size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog) >> 3) + 3;
+ size_t const maxHeaderSize = (((maxSymbolValue+1) * tableLog
+ + 4 /* bitCount initialized at 4 */
+ + 2 /* first two symbols may use one additional bit each */) / 8)
+ + 1 /* round up to whole nb bytes */
+ + 2 /* additional two bytes for bitstream flush */;
return maxSymbolValue ? maxHeaderSize : FSE_NCOUNTBOUND; /* maxSymbolValue==0 ? use default */
}
diff --git a/thirdparty/zstd/compress/huf_compress.c b/thirdparty/zstd/compress/huf_compress.c
index 485906e678..2b3d6adc2a 100644
--- a/thirdparty/zstd/compress/huf_compress.c
+++ b/thirdparty/zstd/compress/huf_compress.c
@@ -53,6 +53,28 @@ unsigned HUF_optimalTableLog(unsigned maxTableLog, size_t srcSize, unsigned maxS
/* *******************************************************
* HUF : Huffman block compression
*********************************************************/
+#define HUF_WORKSPACE_MAX_ALIGNMENT 8
+
+static void* HUF_alignUpWorkspace(void* workspace, size_t* workspaceSizePtr, size_t align)
+{
+ size_t const mask = align - 1;
+ size_t const rem = (size_t)workspace & mask;
+ size_t const add = (align - rem) & mask;
+ BYTE* const aligned = (BYTE*)workspace + add;
+ assert((align & (align - 1)) == 0); /* pow 2 */
+ assert(align <= HUF_WORKSPACE_MAX_ALIGNMENT);
+ if (*workspaceSizePtr >= add) {
+ assert(add < align);
+ assert(((size_t)aligned & mask) == 0);
+ *workspaceSizePtr -= add;
+ return aligned;
+ } else {
+ *workspaceSizePtr = 0;
+ return NULL;
+ }
+}
+
+
/* HUF_compressWeights() :
* Same as FSE_compress(), but dedicated to huff0's weights compression.
* The use case needs much less stack memory.
@@ -75,7 +97,7 @@ static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightT
unsigned maxSymbolValue = HUF_TABLELOG_MAX;
U32 tableLog = MAX_FSE_TABLELOG_FOR_HUFF_HEADER;
- HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)workspace;
+ HUF_CompressWeightsWksp* wksp = (HUF_CompressWeightsWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));
if (workspaceSize < sizeof(HUF_CompressWeightsWksp)) return ERROR(GENERIC);
@@ -106,6 +128,40 @@ static size_t HUF_compressWeights(void* dst, size_t dstSize, const void* weightT
return (size_t)(op-ostart);
}
+static size_t HUF_getNbBits(HUF_CElt elt)
+{
+ return elt & 0xFF;
+}
+
+static size_t HUF_getNbBitsFast(HUF_CElt elt)
+{
+ return elt;
+}
+
+static size_t HUF_getValue(HUF_CElt elt)
+{
+ return elt & ~0xFF;
+}
+
+static size_t HUF_getValueFast(HUF_CElt elt)
+{
+ return elt;
+}
+
+static void HUF_setNbBits(HUF_CElt* elt, size_t nbBits)
+{
+ assert(nbBits <= HUF_TABLELOG_ABSOLUTEMAX);
+ *elt = nbBits;
+}
+
+static void HUF_setValue(HUF_CElt* elt, size_t value)
+{
+ size_t const nbBits = HUF_getNbBits(*elt);
+ if (nbBits > 0) {
+ assert((value >> nbBits) == 0);
+ *elt |= value << (sizeof(HUF_CElt) * 8 - nbBits);
+ }
+}
typedef struct {
HUF_CompressWeightsWksp wksp;
@@ -117,9 +173,10 @@ size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
const HUF_CElt* CTable, unsigned maxSymbolValue, unsigned huffLog,
void* workspace, size_t workspaceSize)
{
+ HUF_CElt const* const ct = CTable + 1;
BYTE* op = (BYTE*)dst;
U32 n;
- HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)workspace;
+ HUF_WriteCTableWksp* wksp = (HUF_WriteCTableWksp*)HUF_alignUpWorkspace(workspace, &workspaceSize, ZSTD_ALIGNOF(U32));
/* check conditions */
if (workspaceSize < sizeof(HUF_WriteCTableWksp)) return ERROR(GENERIC);
@@ -130,9 +187,10 @@ size_t HUF_writeCTable_wksp(void* dst, size_t maxDstSize,
for (n=1; n<huffLog+1; n++)
wksp->bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
for (n=0; n<maxSymbolValue; n++)
- wksp->huffWeight[n] = wksp->bitsToWeight[CTable[n].nbBits];
+ wksp->huffWeight[n] = wksp->bitsToWeight[HUF_getNbBits(ct[n])];
/* attempt weights compression by FSE */
+ if (maxDstSize < 1) return ERROR(dstSize_tooSmall);
{ CHECK_V_F(hSize, HUF_compressWeights(op+1, maxDstSize-1, wksp->huffWeight, maxSymbolValue, &wksp->wksp, sizeof(wksp->wksp)) );
if ((hSize>1) & (hSize < maxSymbolValue/2)) { /* FSE compressed */
op[0] = (BYTE)hSize;
@@ -166,6 +224,7 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1]; /* large enough for values from 0 to 16 */
U32 tableLog = 0;
U32 nbSymbols = 0;
+ HUF_CElt* const ct = CTable + 1;
/* get symbol weights */
CHECK_V_F(readSize, HUF_readStats(huffWeight, HUF_SYMBOLVALUE_MAX+1, rankVal, &nbSymbols, &tableLog, src, srcSize));
@@ -175,6 +234,8 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
if (tableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
if (nbSymbols > *maxSymbolValuePtr+1) return ERROR(maxSymbolValue_tooSmall);
+ CTable[0] = tableLog;
+
/* Prepare base value per rank */
{ U32 n, nextRankStart = 0;
for (n=1; n<=tableLog; n++) {
@@ -186,13 +247,13 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
/* fill nbBits */
{ U32 n; for (n=0; n<nbSymbols; n++) {
const U32 w = huffWeight[n];
- CTable[n].nbBits = (BYTE)(tableLog + 1 - w) & -(w != 0);
+ HUF_setNbBits(ct + n, (BYTE)(tableLog + 1 - w) & -(w != 0));
} }
/* fill val */
{ U16 nbPerRank[HUF_TABLELOG_MAX+2] = {0}; /* support w=0=>n=tableLog+1 */
U16 valPerRank[HUF_TABLELOG_MAX+2] = {0};
- { U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[CTable[n].nbBits]++; }
+ { U32 n; for (n=0; n<nbSymbols; n++) nbPerRank[HUF_getNbBits(ct[n])]++; }
/* determine stating value per rank */
valPerRank[tableLog+1] = 0; /* for w==0 */
{ U16 min = 0;
@@ -202,18 +263,18 @@ size_t HUF_readCTable (HUF_CElt* CTable, unsigned* maxSymbolValuePtr, const void
min >>= 1;
} }
/* assign value within rank, symbol order */
- { U32 n; for (n=0; n<nbSymbols; n++) CTable[n].val = valPerRank[CTable[n].nbBits]++; }
+ { U32 n; for (n=0; n<nbSymbols; n++) HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++); }
}
*maxSymbolValuePtr = nbSymbols - 1;
return readSize;
}
-U32 HUF_getNbBits(const void* symbolTable, U32 symbolValue)
+U32 HUF_getNbBitsFromCTable(HUF_CElt const* CTable, U32 symbolValue)
{
- const HUF_CElt* table = (const HUF_CElt*)symbolTable;
+ const HUF_CElt* ct = CTable + 1;
assert(symbolValue <= HUF_SYMBOLVALUE_MAX);
- return table[symbolValue].nbBits;
+ return (U32)HUF_getNbBits(ct[symbolValue]);
}
@@ -367,22 +428,118 @@ static U32 HUF_setMaxHeight(nodeElt* huffNode, U32 lastNonNull, U32 maxNbBits)
}
typedef struct {
- U32 base;
- U32 curr;
+ U16 base;
+ U16 curr;
} rankPos;
typedef nodeElt huffNodeTable[HUF_CTABLE_WORKSPACE_SIZE_U32];
-#define RANK_POSITION_TABLE_SIZE 32
+/* Number of buckets available for HUF_sort() */
+#define RANK_POSITION_TABLE_SIZE 192
typedef struct {
huffNodeTable huffNodeTbl;
rankPos rankPosition[RANK_POSITION_TABLE_SIZE];
} HUF_buildCTable_wksp_tables;
+/* RANK_POSITION_DISTINCT_COUNT_CUTOFF == Cutoff point in HUF_sort() buckets for which we use log2 bucketing.
+ * Strategy is to use as many buckets as possible for representing distinct
+ * counts while using the remainder to represent all "large" counts.
+ *
+ * To satisfy this requirement for 192 buckets, we can do the following:
+ * Let buckets 0-166 represent distinct counts of [0, 166]
+ * Let buckets 166 to 192 represent all remaining counts up to RANK_POSITION_MAX_COUNT_LOG using log2 bucketing.
+ */
+#define RANK_POSITION_MAX_COUNT_LOG 32
+#define RANK_POSITION_LOG_BUCKETS_BEGIN (RANK_POSITION_TABLE_SIZE - 1) - RANK_POSITION_MAX_COUNT_LOG - 1 /* == 158 */
+#define RANK_POSITION_DISTINCT_COUNT_CUTOFF RANK_POSITION_LOG_BUCKETS_BEGIN + BIT_highbit32(RANK_POSITION_LOG_BUCKETS_BEGIN) /* == 166 */
+
+/* Return the appropriate bucket index for a given count. See definition of
+ * RANK_POSITION_DISTINCT_COUNT_CUTOFF for explanation of bucketing strategy.
+ */
+static U32 HUF_getIndex(U32 const count) {
+ return (count < RANK_POSITION_DISTINCT_COUNT_CUTOFF)
+ ? count
+ : BIT_highbit32(count) + RANK_POSITION_LOG_BUCKETS_BEGIN;
+}
+
+/* Helper swap function for HUF_quickSortPartition() */
+static void HUF_swapNodes(nodeElt* a, nodeElt* b) {
+ nodeElt tmp = *a;
+ *a = *b;
+ *b = tmp;
+}
+
+/* Returns 0 if the huffNode array is not sorted by descending count */
+MEM_STATIC int HUF_isSorted(nodeElt huffNode[], U32 const maxSymbolValue1) {
+ U32 i;
+ for (i = 1; i < maxSymbolValue1; ++i) {
+ if (huffNode[i].count > huffNode[i-1].count) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* Insertion sort by descending order */
+HINT_INLINE void HUF_insertionSort(nodeElt huffNode[], int const low, int const high) {
+ int i;
+ int const size = high-low+1;
+ huffNode += low;
+ for (i = 1; i < size; ++i) {
+ nodeElt const key = huffNode[i];
+ int j = i - 1;
+ while (j >= 0 && huffNode[j].count < key.count) {
+ huffNode[j + 1] = huffNode[j];
+ j--;
+ }
+ huffNode[j + 1] = key;
+ }
+}
+
+/* Pivot helper function for quicksort. */
+static int HUF_quickSortPartition(nodeElt arr[], int const low, int const high) {
+ /* Simply select rightmost element as pivot. "Better" selectors like
+ * median-of-three don't experimentally appear to have any benefit.
+ */
+ U32 const pivot = arr[high].count;
+ int i = low - 1;
+ int j = low;
+ for ( ; j < high; j++) {
+ if (arr[j].count > pivot) {
+ i++;
+ HUF_swapNodes(&arr[i], &arr[j]);
+ }
+ }
+ HUF_swapNodes(&arr[i + 1], &arr[high]);
+ return i + 1;
+}
+
+/* Classic quicksort by descending with partially iterative calls
+ * to reduce worst case callstack size.
+ */
+static void HUF_simpleQuickSort(nodeElt arr[], int low, int high) {
+ int const kInsertionSortThreshold = 8;
+ if (high - low < kInsertionSortThreshold) {
+ HUF_insertionSort(arr, low, high);
+ return;
+ }
+ while (low < high) {
+ int const idx = HUF_quickSortPartition(arr, low, high);
+ if (idx - low < high - idx) {
+ HUF_simpleQuickSort(arr, low, idx - 1);
+ low = idx + 1;
+ } else {
+ HUF_simpleQuickSort(arr, idx + 1, high);
+ high = idx - 1;
+ }
+ }
+}
+
/**
* HUF_sort():
* Sorts the symbols [0, maxSymbolValue] by count[symbol] in decreasing order.
+ * This is a typical bucket sorting strategy that uses either quicksort or insertion sort to sort each bucket.
*
* @param[out] huffNode Sorted symbols by decreasing count. Only members `.count` and `.byte` are filled.
* Must have (maxSymbolValue + 1) entries.
@@ -390,44 +547,52 @@ typedef struct {
* @param[in] maxSymbolValue Maximum symbol value.
* @param rankPosition This is a scratch workspace. Must have RANK_POSITION_TABLE_SIZE entries.
*/
-static void HUF_sort(nodeElt* huffNode, const unsigned* count, U32 maxSymbolValue, rankPos* rankPosition)
-{
- int n;
- int const maxSymbolValue1 = (int)maxSymbolValue + 1;
+static void HUF_sort(nodeElt huffNode[], const unsigned count[], U32 const maxSymbolValue, rankPos rankPosition[]) {
+ U32 n;
+ U32 const maxSymbolValue1 = maxSymbolValue+1;
/* Compute base and set curr to base.
- * For symbol s let lowerRank = BIT_highbit32(count[n]+1) and rank = lowerRank + 1.
- * Then 2^lowerRank <= count[n]+1 <= 2^rank.
+ * For symbol s let lowerRank = HUF_getIndex(count[n]) and rank = lowerRank + 1.
+ * See HUF_getIndex to see bucketing strategy.
* We attribute each symbol to lowerRank's base value, because we want to know where
* each rank begins in the output, so for rank R we want to count ranks R+1 and above.
*/
ZSTD_memset(rankPosition, 0, sizeof(*rankPosition) * RANK_POSITION_TABLE_SIZE);
for (n = 0; n < maxSymbolValue1; ++n) {
- U32 lowerRank = BIT_highbit32(count[n] + 1);
+ U32 lowerRank = HUF_getIndex(count[n]);
+ assert(lowerRank < RANK_POSITION_TABLE_SIZE - 1);
rankPosition[lowerRank].base++;
}
+
assert(rankPosition[RANK_POSITION_TABLE_SIZE - 1].base == 0);
+ /* Set up the rankPosition table */
for (n = RANK_POSITION_TABLE_SIZE - 1; n > 0; --n) {
rankPosition[n-1].base += rankPosition[n].base;
rankPosition[n-1].curr = rankPosition[n-1].base;
}
- /* Sort */
+
+ /* Insert each symbol into their appropriate bucket, setting up rankPosition table. */
for (n = 0; n < maxSymbolValue1; ++n) {
U32 const c = count[n];
- U32 const r = BIT_highbit32(c+1) + 1;
- U32 pos = rankPosition[r].curr++;
- /* Insert into the correct position in the rank.
- * We have at most 256 symbols, so this insertion should be fine.
- */
- while ((pos > rankPosition[r].base) && (c > huffNode[pos-1].count)) {
- huffNode[pos] = huffNode[pos-1];
- pos--;
- }
+ U32 const r = HUF_getIndex(c) + 1;
+ U32 const pos = rankPosition[r].curr++;
+ assert(pos < maxSymbolValue1);
huffNode[pos].count = c;
huffNode[pos].byte = (BYTE)n;
}
-}
+ /* Sort each bucket. */
+ for (n = RANK_POSITION_DISTINCT_COUNT_CUTOFF; n < RANK_POSITION_TABLE_SIZE - 1; ++n) {
+ U32 const bucketSize = rankPosition[n].curr-rankPosition[n].base;
+ U32 const bucketStartIdx = rankPosition[n].base;
+ if (bucketSize > 1) {
+ assert(bucketStartIdx < maxSymbolValue1);
+ HUF_simpleQuickSort(huffNode + bucketStartIdx, 0, bucketSize-1);
+ }
+ }
+
+ assert(HUF_isSorted(huffNode, maxSymbolValue1));
+}
/** HUF_buildCTable_wksp() :
* Same as HUF_buildCTable(), but using externally allocated scratch buffer.
@@ -490,6 +655,7 @@ static int HUF_buildTree(nodeElt* huffNode, U32 maxSymbolValue)
*/
static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, int nonNullRank, U32 maxSymbolValue, U32 maxNbBits)
{
+ HUF_CElt* const ct = CTable + 1;
/* fill result into ctable (val, nbBits) */
int n;
U16 nbPerRank[HUF_TABLELOG_MAX+1] = {0};
@@ -505,20 +671,20 @@ static void HUF_buildCTableFromTree(HUF_CElt* CTable, nodeElt const* huffNode, i
min >>= 1;
} }
for (n=0; n<alphabetSize; n++)
- CTable[huffNode[n].byte].nbBits = huffNode[n].nbBits; /* push nbBits per symbol, symbol order */
+ HUF_setNbBits(ct + huffNode[n].byte, huffNode[n].nbBits); /* push nbBits per symbol, symbol order */
for (n=0; n<alphabetSize; n++)
- CTable[n].val = valPerRank[CTable[n].nbBits]++; /* assign value within rank, symbol order */
+ HUF_setValue(ct + n, valPerRank[HUF_getNbBits(ct[n])]++); /* assign value within rank, symbol order */
+ CTable[0] = maxNbBits;
}
-size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
+size_t HUF_buildCTable_wksp (HUF_CElt* CTable, const unsigned* count, U32 maxSymbolValue, U32 maxNbBits, void* workSpace, size_t wkspSize)
{
- HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)workSpace;
+ HUF_buildCTable_wksp_tables* const wksp_tables = (HUF_buildCTable_wksp_tables*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(U32));
nodeElt* const huffNode0 = wksp_tables->huffNodeTbl;
nodeElt* const huffNode = huffNode0+1;
int nonNullRank;
/* safety checks */
- if (((size_t)workSpace & 3) != 0) return ERROR(GENERIC); /* must be aligned on 4-bytes boundaries */
if (wkspSize < sizeof(HUF_buildCTable_wksp_tables))
return ERROR(workSpace_tooSmall);
if (maxNbBits == 0) maxNbBits = HUF_TABLELOG_DEFAULT;
@@ -536,96 +702,334 @@ size_t HUF_buildCTable_wksp (HUF_CElt* tree, const unsigned* count, U32 maxSymbo
maxNbBits = HUF_setMaxHeight(huffNode, (U32)nonNullRank, maxNbBits);
if (maxNbBits > HUF_TABLELOG_MAX) return ERROR(GENERIC); /* check fit into table */
- HUF_buildCTableFromTree(tree, huffNode, nonNullRank, maxSymbolValue, maxNbBits);
+ HUF_buildCTableFromTree(CTable, huffNode, nonNullRank, maxSymbolValue, maxNbBits);
return maxNbBits;
}
size_t HUF_estimateCompressedSize(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue)
{
+ HUF_CElt const* ct = CTable + 1;
size_t nbBits = 0;
int s;
for (s = 0; s <= (int)maxSymbolValue; ++s) {
- nbBits += CTable[s].nbBits * count[s];
+ nbBits += HUF_getNbBits(ct[s]) * count[s];
}
return nbBits >> 3;
}
int HUF_validateCTable(const HUF_CElt* CTable, const unsigned* count, unsigned maxSymbolValue) {
+ HUF_CElt const* ct = CTable + 1;
int bad = 0;
int s;
for (s = 0; s <= (int)maxSymbolValue; ++s) {
- bad |= (count[s] != 0) & (CTable[s].nbBits == 0);
+ bad |= (count[s] != 0) & (HUF_getNbBits(ct[s]) == 0);
}
return !bad;
}
size_t HUF_compressBound(size_t size) { return HUF_COMPRESSBOUND(size); }
+/** HUF_CStream_t:
+ * Huffman uses its own BIT_CStream_t implementation.
+ * There are three major differences from BIT_CStream_t:
+ * 1. HUF_addBits() takes a HUF_CElt (size_t) which is
+ * the pair (nbBits, value) in the format:
+ * format:
+ * - Bits [0, 4) = nbBits
+ * - Bits [4, 64 - nbBits) = 0
+ * - Bits [64 - nbBits, 64) = value
+ * 2. The bitContainer is built from the upper bits and
+ * right shifted. E.g. to add a new value of N bits
+ * you right shift the bitContainer by N, then or in
+ * the new value into the N upper bits.
+ * 3. The bitstream has two bit containers. You can add
+ * bits to the second container and merge them into
+ * the first container.
+ */
+
+#define HUF_BITS_IN_CONTAINER (sizeof(size_t) * 8)
+
+typedef struct {
+ size_t bitContainer[2];
+ size_t bitPos[2];
+
+ BYTE* startPtr;
+ BYTE* ptr;
+ BYTE* endPtr;
+} HUF_CStream_t;
+
+/**! HUF_initCStream():
+ * Initializes the bitstream.
+ * @returns 0 or an error code.
+ */
+static size_t HUF_initCStream(HUF_CStream_t* bitC,
+ void* startPtr, size_t dstCapacity)
+{
+ ZSTD_memset(bitC, 0, sizeof(*bitC));
+ bitC->startPtr = (BYTE*)startPtr;
+ bitC->ptr = bitC->startPtr;
+ bitC->endPtr = bitC->startPtr + dstCapacity - sizeof(bitC->bitContainer[0]);
+ if (dstCapacity <= sizeof(bitC->bitContainer[0])) return ERROR(dstSize_tooSmall);
+ return 0;
+}
+
+/*! HUF_addBits():
+ * Adds the symbol stored in HUF_CElt elt to the bitstream.
+ *
+ * @param elt The element we're adding. This is a (nbBits, value) pair.
+ * See the HUF_CStream_t docs for the format.
+ * @param idx Insert into the bitstream at this idx.
+ * @param kFast This is a template parameter. If the bitstream is guaranteed
+ * to have at least 4 unused bits after this call it may be 1,
+ * otherwise it must be 0. HUF_addBits() is faster when fast is set.
+ */
+FORCE_INLINE_TEMPLATE void HUF_addBits(HUF_CStream_t* bitC, HUF_CElt elt, int idx, int kFast)
+{
+ assert(idx <= 1);
+ assert(HUF_getNbBits(elt) <= HUF_TABLELOG_ABSOLUTEMAX);
+ /* This is efficient on x86-64 with BMI2 because shrx
+ * only reads the low 6 bits of the register. The compiler
+ * knows this and elides the mask. When fast is set,
+ * every operation can use the same value loaded from elt.
+ */
+ bitC->bitContainer[idx] >>= HUF_getNbBits(elt);
+ bitC->bitContainer[idx] |= kFast ? HUF_getValueFast(elt) : HUF_getValue(elt);
+ /* We only read the low 8 bits of bitC->bitPos[idx] so it
+ * doesn't matter that the high bits have noise from the value.
+ */
+ bitC->bitPos[idx] += HUF_getNbBitsFast(elt);
+ assert((bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);
+ /* The last 4-bits of elt are dirty if fast is set,
+ * so we must not be overwriting bits that have already been
+ * inserted into the bit container.
+ */
+#if DEBUGLEVEL >= 1
+ {
+ size_t const nbBits = HUF_getNbBits(elt);
+ size_t const dirtyBits = nbBits == 0 ? 0 : BIT_highbit32((U32)nbBits) + 1;
+ (void)dirtyBits;
+ /* Middle bits are 0. */
+ assert(((elt >> dirtyBits) << (dirtyBits + nbBits)) == 0);
+ /* We didn't overwrite any bits in the bit container. */
+ assert(!kFast || (bitC->bitPos[idx] & 0xFF) <= HUF_BITS_IN_CONTAINER);
+ (void)dirtyBits;
+ }
+#endif
+}
+
+FORCE_INLINE_TEMPLATE void HUF_zeroIndex1(HUF_CStream_t* bitC)
+{
+ bitC->bitContainer[1] = 0;
+ bitC->bitPos[1] = 0;
+}
+
+/*! HUF_mergeIndex1() :
+ * Merges the bit container @ index 1 into the bit container @ index 0
+ * and zeros the bit container @ index 1.
+ */
+FORCE_INLINE_TEMPLATE void HUF_mergeIndex1(HUF_CStream_t* bitC)
+{
+ assert((bitC->bitPos[1] & 0xFF) < HUF_BITS_IN_CONTAINER);
+ bitC->bitContainer[0] >>= (bitC->bitPos[1] & 0xFF);
+ bitC->bitContainer[0] |= bitC->bitContainer[1];
+ bitC->bitPos[0] += bitC->bitPos[1];
+ assert((bitC->bitPos[0] & 0xFF) <= HUF_BITS_IN_CONTAINER);
+}
+
+/*! HUF_flushBits() :
+* Flushes the bits in the bit container @ index 0.
+*
+* @post bitPos will be < 8.
+* @param kFast If kFast is set then we must know a-priori that
+* the bit container will not overflow.
+*/
+FORCE_INLINE_TEMPLATE void HUF_flushBits(HUF_CStream_t* bitC, int kFast)
+{
+ /* The upper bits of bitPos are noisy, so we must mask by 0xFF. */
+ size_t const nbBits = bitC->bitPos[0] & 0xFF;
+ size_t const nbBytes = nbBits >> 3;
+ /* The top nbBits bits of bitContainer are the ones we need. */
+ size_t const bitContainer = bitC->bitContainer[0] >> (HUF_BITS_IN_CONTAINER - nbBits);
+ /* Mask bitPos to account for the bytes we consumed. */
+ bitC->bitPos[0] &= 7;
+ assert(nbBits > 0);
+ assert(nbBits <= sizeof(bitC->bitContainer[0]) * 8);
+ assert(bitC->ptr <= bitC->endPtr);
+ MEM_writeLEST(bitC->ptr, bitContainer);
+ bitC->ptr += nbBytes;
+ assert(!kFast || bitC->ptr <= bitC->endPtr);
+ if (!kFast && bitC->ptr > bitC->endPtr) bitC->ptr = bitC->endPtr;
+ /* bitContainer doesn't need to be modified because the leftover
+ * bits are already the top bitPos bits. And we don't care about
+ * noise in the lower values.
+ */
+}
+
+/*! HUF_endMark()
+ * @returns The Huffman stream end mark: A 1-bit value = 1.
+ */
+static HUF_CElt HUF_endMark(void)
+{
+ HUF_CElt endMark;
+ HUF_setNbBits(&endMark, 1);
+ HUF_setValue(&endMark, 1);
+ return endMark;
+}
+
+/*! HUF_closeCStream() :
+ * @return Size of CStream, in bytes,
+ * or 0 if it could not fit into dstBuffer */
+static size_t HUF_closeCStream(HUF_CStream_t* bitC)
+{
+ HUF_addBits(bitC, HUF_endMark(), /* idx */ 0, /* kFast */ 0);
+ HUF_flushBits(bitC, /* kFast */ 0);
+ {
+ size_t const nbBits = bitC->bitPos[0] & 0xFF;
+ if (bitC->ptr >= bitC->endPtr) return 0; /* overflow detected */
+ return (bitC->ptr - bitC->startPtr) + (nbBits > 0);
+ }
+}
+
FORCE_INLINE_TEMPLATE void
-HUF_encodeSymbol(BIT_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable)
+HUF_encodeSymbol(HUF_CStream_t* bitCPtr, U32 symbol, const HUF_CElt* CTable, int idx, int fast)
{
- BIT_addBitsFast(bitCPtr, CTable[symbol].val, CTable[symbol].nbBits);
+ HUF_addBits(bitCPtr, CTable[symbol], idx, fast);
}
-#define HUF_FLUSHBITS(s) BIT_flushBits(s)
+FORCE_INLINE_TEMPLATE void
+HUF_compress1X_usingCTable_internal_body_loop(HUF_CStream_t* bitC,
+ const BYTE* ip, size_t srcSize,
+ const HUF_CElt* ct,
+ int kUnroll, int kFastFlush, int kLastFast)
+{
+ /* Join to kUnroll */
+ int n = (int)srcSize;
+ int rem = n % kUnroll;
+ if (rem > 0) {
+ for (; rem > 0; --rem) {
+ HUF_encodeSymbol(bitC, ip[--n], ct, 0, /* fast */ 0);
+ }
+ HUF_flushBits(bitC, kFastFlush);
+ }
+ assert(n % kUnroll == 0);
+
+ /* Join to 2 * kUnroll */
+ if (n % (2 * kUnroll)) {
+ int u;
+ for (u = 1; u < kUnroll; ++u) {
+ HUF_encodeSymbol(bitC, ip[n - u], ct, 0, 1);
+ }
+ HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, 0, kLastFast);
+ HUF_flushBits(bitC, kFastFlush);
+ n -= kUnroll;
+ }
+ assert(n % (2 * kUnroll) == 0);
+
+ for (; n>0; n-= 2 * kUnroll) {
+ /* Encode kUnroll symbols into the bitstream @ index 0. */
+ int u;
+ for (u = 1; u < kUnroll; ++u) {
+ HUF_encodeSymbol(bitC, ip[n - u], ct, /* idx */ 0, /* fast */ 1);
+ }
+ HUF_encodeSymbol(bitC, ip[n - kUnroll], ct, /* idx */ 0, /* fast */ kLastFast);
+ HUF_flushBits(bitC, kFastFlush);
+ /* Encode kUnroll symbols into the bitstream @ index 1.
+ * This allows us to start filling the bit container
+ * without any data dependencies.
+ */
+ HUF_zeroIndex1(bitC);
+ for (u = 1; u < kUnroll; ++u) {
+ HUF_encodeSymbol(bitC, ip[n - kUnroll - u], ct, /* idx */ 1, /* fast */ 1);
+ }
+ HUF_encodeSymbol(bitC, ip[n - kUnroll - kUnroll], ct, /* idx */ 1, /* fast */ kLastFast);
+ /* Merge bitstream @ index 1 into the bitstream @ index 0 */
+ HUF_mergeIndex1(bitC);
+ HUF_flushBits(bitC, kFastFlush);
+ }
+ assert(n == 0);
+
+}
-#define HUF_FLUSHBITS_1(stream) \
- if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*2+7) HUF_FLUSHBITS(stream)
+/**
+ * Returns a tight upper bound on the output space needed by Huffman
+ * with 8 bytes buffer to handle over-writes. If the output is at least
+ * this large we don't need to do bounds checks during Huffman encoding.
+ */
+static size_t HUF_tightCompressBound(size_t srcSize, size_t tableLog)
+{
+ return ((srcSize * tableLog) >> 3) + 8;
+}
-#define HUF_FLUSHBITS_2(stream) \
- if (sizeof((stream)->bitContainer)*8 < HUF_TABLELOG_MAX*4+7) HUF_FLUSHBITS(stream)
FORCE_INLINE_TEMPLATE size_t
HUF_compress1X_usingCTable_internal_body(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable)
{
+ U32 const tableLog = (U32)CTable[0];
+ HUF_CElt const* ct = CTable + 1;
const BYTE* ip = (const BYTE*) src;
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
- size_t n;
- BIT_CStream_t bitC;
+ HUF_CStream_t bitC;
/* init */
if (dstSize < 8) return 0; /* not enough space to compress */
- { size_t const initErr = BIT_initCStream(&bitC, op, (size_t)(oend-op));
+ { size_t const initErr = HUF_initCStream(&bitC, op, (size_t)(oend-op));
if (HUF_isError(initErr)) return 0; }
- n = srcSize & ~3; /* join to mod 4 */
- switch (srcSize & 3)
- {
- case 3 : HUF_encodeSymbol(&bitC, ip[n+ 2], CTable);
- HUF_FLUSHBITS_2(&bitC);
- /* fall-through */
- case 2 : HUF_encodeSymbol(&bitC, ip[n+ 1], CTable);
- HUF_FLUSHBITS_1(&bitC);
- /* fall-through */
- case 1 : HUF_encodeSymbol(&bitC, ip[n+ 0], CTable);
- HUF_FLUSHBITS(&bitC);
- /* fall-through */
- case 0 : /* fall-through */
- default: break;
- }
-
- for (; n>0; n-=4) { /* note : n&3==0 at this stage */
- HUF_encodeSymbol(&bitC, ip[n- 1], CTable);
- HUF_FLUSHBITS_1(&bitC);
- HUF_encodeSymbol(&bitC, ip[n- 2], CTable);
- HUF_FLUSHBITS_2(&bitC);
- HUF_encodeSymbol(&bitC, ip[n- 3], CTable);
- HUF_FLUSHBITS_1(&bitC);
- HUF_encodeSymbol(&bitC, ip[n- 4], CTable);
- HUF_FLUSHBITS(&bitC);
+ if (dstSize < HUF_tightCompressBound(srcSize, (size_t)tableLog) || tableLog > 11)
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ MEM_32bits() ? 2 : 4, /* kFast */ 0, /* kLastFast */ 0);
+ else {
+ if (MEM_32bits()) {
+ switch (tableLog) {
+ case 11:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 0);
+ break;
+ case 10: ZSTD_FALLTHROUGH;
+ case 9: ZSTD_FALLTHROUGH;
+ case 8:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 2, /* kFastFlush */ 1, /* kLastFast */ 1);
+ break;
+ case 7: ZSTD_FALLTHROUGH;
+ default:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 3, /* kFastFlush */ 1, /* kLastFast */ 1);
+ break;
+ }
+ } else {
+ switch (tableLog) {
+ case 11:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 0);
+ break;
+ case 10:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 5, /* kFastFlush */ 1, /* kLastFast */ 1);
+ break;
+ case 9:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 6, /* kFastFlush */ 1, /* kLastFast */ 0);
+ break;
+ case 8:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 7, /* kFastFlush */ 1, /* kLastFast */ 0);
+ break;
+ case 7:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 8, /* kFastFlush */ 1, /* kLastFast */ 0);
+ break;
+ case 6: ZSTD_FALLTHROUGH;
+ default:
+ HUF_compress1X_usingCTable_internal_body_loop(&bitC, ip, srcSize, ct, /* kUnroll */ 9, /* kFastFlush */ 1, /* kLastFast */ 1);
+ break;
+ }
+ }
}
+ assert(bitC.ptr <= bitC.endPtr);
- return BIT_closeCStream(&bitC);
+ return HUF_closeCStream(&bitC);
}
#if DYNAMIC_BMI2
-static TARGET_ATTRIBUTE("bmi2") size_t
+static BMI2_TARGET_ATTRIBUTE size_t
HUF_compress1X_usingCTable_internal_bmi2(void* dst, size_t dstSize,
const void* src, size_t srcSize,
const HUF_CElt* CTable)
@@ -667,9 +1071,13 @@ HUF_compress1X_usingCTable_internal(void* dst, size_t dstSize,
size_t HUF_compress1X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
{
- return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
+ return HUF_compress1X_usingCTable_bmi2(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
}
+size_t HUF_compress1X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2)
+{
+ return HUF_compress1X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, bmi2);
+}
static size_t
HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
@@ -689,8 +1097,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
assert(op <= oend);
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
- if (cSize==0) return 0;
- assert(cSize <= 65535);
+ if (cSize == 0 || cSize > 65535) return 0;
MEM_writeLE16(ostart, (U16)cSize);
op += cSize;
}
@@ -698,8 +1105,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
ip += segmentSize;
assert(op <= oend);
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
- if (cSize==0) return 0;
- assert(cSize <= 65535);
+ if (cSize == 0 || cSize > 65535) return 0;
MEM_writeLE16(ostart+2, (U16)cSize);
op += cSize;
}
@@ -707,8 +1113,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
ip += segmentSize;
assert(op <= oend);
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, segmentSize, CTable, bmi2) );
- if (cSize==0) return 0;
- assert(cSize <= 65535);
+ if (cSize == 0 || cSize > 65535) return 0;
MEM_writeLE16(ostart+4, (U16)cSize);
op += cSize;
}
@@ -717,7 +1122,7 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
assert(op <= oend);
assert(ip <= iend);
{ CHECK_V_F(cSize, HUF_compress1X_usingCTable_internal(op, (size_t)(oend-op), ip, (size_t)(iend-ip), CTable, bmi2) );
- if (cSize==0) return 0;
+ if (cSize == 0 || cSize > 65535) return 0;
op += cSize;
}
@@ -726,7 +1131,12 @@ HUF_compress4X_usingCTable_internal(void* dst, size_t dstSize,
size_t HUF_compress4X_usingCTable(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable)
{
- return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
+ return HUF_compress4X_usingCTable_bmi2(dst, dstSize, src, srcSize, CTable, /* bmi2 */ 0);
+}
+
+size_t HUF_compress4X_usingCTable_bmi2(void* dst, size_t dstSize, const void* src, size_t srcSize, const HUF_CElt* CTable, int bmi2)
+{
+ return HUF_compress4X_usingCTable_internal(dst, dstSize, src, srcSize, CTable, bmi2);
}
typedef enum { HUF_singleStream, HUF_fourStreams } HUF_nbStreams_e;
@@ -750,35 +1160,38 @@ static size_t HUF_compressCTable_internal(
typedef struct {
unsigned count[HUF_SYMBOLVALUE_MAX + 1];
- HUF_CElt CTable[HUF_SYMBOLVALUE_MAX + 1];
+ HUF_CElt CTable[HUF_CTABLE_SIZE_ST(HUF_SYMBOLVALUE_MAX)];
union {
HUF_buildCTable_wksp_tables buildCTable_wksp;
HUF_WriteCTableWksp writeCTable_wksp;
+ U32 hist_wksp[HIST_WKSP_SIZE_U32];
} wksps;
} HUF_compress_tables_t;
+#define SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE 4096
+#define SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO 10 /* Must be >= 2 */
+
/* HUF_compress_internal() :
* `workSpace_align4` must be aligned on 4-bytes boundaries,
- * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U32 unsigned */
+ * and occupies the same space as a table of HUF_WORKSPACE_SIZE_U64 unsigned */
static size_t
HUF_compress_internal (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
HUF_nbStreams_e nbStreams,
- void* workSpace_align4, size_t wkspSize,
+ void* workSpace, size_t wkspSize,
HUF_CElt* oldHufTable, HUF_repeat* repeat, int preferRepeat,
- const int bmi2)
+ const int bmi2, unsigned suspectUncompressible)
{
- HUF_compress_tables_t* const table = (HUF_compress_tables_t*)workSpace_align4;
+ HUF_compress_tables_t* const table = (HUF_compress_tables_t*)HUF_alignUpWorkspace(workSpace, &wkspSize, ZSTD_ALIGNOF(size_t));
BYTE* const ostart = (BYTE*)dst;
BYTE* const oend = ostart + dstSize;
BYTE* op = ostart;
- HUF_STATIC_ASSERT(sizeof(*table) <= HUF_WORKSPACE_SIZE);
- assert(((size_t)workSpace_align4 & 3) == 0); /* must be aligned on 4-bytes boundaries */
+ HUF_STATIC_ASSERT(sizeof(*table) + HUF_WORKSPACE_MAX_ALIGNMENT <= HUF_WORKSPACE_SIZE);
/* checks & inits */
- if (wkspSize < HUF_WORKSPACE_SIZE) return ERROR(workSpace_tooSmall);
+ if (wkspSize < sizeof(*table)) return ERROR(workSpace_tooSmall);
if (!srcSize) return 0; /* Uncompressed */
if (!dstSize) return 0; /* cannot fit anything within dst budget */
if (srcSize > HUF_BLOCKSIZE_MAX) return ERROR(srcSize_wrong); /* current block size limit */
@@ -794,8 +1207,23 @@ HUF_compress_internal (void* dst, size_t dstSize,
nbStreams, oldHufTable, bmi2);
}
+ /* If uncompressible data is suspected, do a smaller sampling first */
+ DEBUG_STATIC_ASSERT(SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO >= 2);
+ if (suspectUncompressible && srcSize >= (SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE * SUSPECT_INCOMPRESSIBLE_SAMPLE_RATIO)) {
+ size_t largestTotal = 0;
+ { unsigned maxSymbolValueBegin = maxSymbolValue;
+ CHECK_V_F(largestBegin, HIST_count_simple (table->count, &maxSymbolValueBegin, (const BYTE*)src, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );
+ largestTotal += largestBegin;
+ }
+ { unsigned maxSymbolValueEnd = maxSymbolValue;
+ CHECK_V_F(largestEnd, HIST_count_simple (table->count, &maxSymbolValueEnd, (const BYTE*)src + srcSize - SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE, SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) );
+ largestTotal += largestEnd;
+ }
+ if (largestTotal <= ((2 * SUSPECT_INCOMPRESSIBLE_SAMPLE_SIZE) >> 7)+4) return 0; /* heuristic : probably not compressible enough */
+ }
+
/* Scan input and build symbol stats */
- { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, workSpace_align4, wkspSize) );
+ { CHECK_V_F(largest, HIST_count_wksp (table->count, &maxSymbolValue, (const BYTE*)src, srcSize, table->wksps.hist_wksp, sizeof(table->wksps.hist_wksp)) );
if (largest == srcSize) { *ostart = ((const BYTE*)src)[0]; return 1; } /* single symbol, rle */
if (largest <= (srcSize >> 7)+4) return 0; /* heuristic : probably not compressible enough */
}
@@ -820,9 +1248,12 @@ HUF_compress_internal (void* dst, size_t dstSize,
&table->wksps.buildCTable_wksp, sizeof(table->wksps.buildCTable_wksp));
CHECK_F(maxBits);
huffLog = (U32)maxBits;
- /* Zero unused symbols in CTable, so we can check it for validity */
- ZSTD_memset(table->CTable + (maxSymbolValue + 1), 0,
- sizeof(table->CTable) - ((maxSymbolValue + 1) * sizeof(HUF_CElt)));
+ }
+ /* Zero unused symbols in CTable, so we can check it for validity */
+ {
+ size_t const ctableSize = HUF_CTABLE_SIZE_ST(maxSymbolValue);
+ size_t const unusedSize = sizeof(table->CTable) - ctableSize * sizeof(HUF_CElt);
+ ZSTD_memset(table->CTable + ctableSize, 0, unusedSize);
}
/* Write table description header */
@@ -859,19 +1290,20 @@ size_t HUF_compress1X_wksp (void* dst, size_t dstSize,
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, HUF_singleStream,
workSpace, wkspSize,
- NULL, NULL, 0, 0 /*bmi2*/);
+ NULL, NULL, 0, 0 /*bmi2*/, 0);
}
size_t HUF_compress1X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat,
+ int bmi2, unsigned suspectUncompressible)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, HUF_singleStream,
workSpace, wkspSize, hufTable,
- repeat, preferRepeat, bmi2);
+ repeat, preferRepeat, bmi2, suspectUncompressible);
}
/* HUF_compress4X_repeat():
@@ -885,22 +1317,23 @@ size_t HUF_compress4X_wksp (void* dst, size_t dstSize,
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, HUF_fourStreams,
workSpace, wkspSize,
- NULL, NULL, 0, 0 /*bmi2*/);
+ NULL, NULL, 0, 0 /*bmi2*/, 0);
}
/* HUF_compress4X_repeat():
* compress input using 4 streams.
+ * consider skipping quickly
* re-use an existing huffman compression table */
size_t HUF_compress4X_repeat (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog,
void* workSpace, size_t wkspSize,
- HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2)
+ HUF_CElt* hufTable, HUF_repeat* repeat, int preferRepeat, int bmi2, unsigned suspectUncompressible)
{
return HUF_compress_internal(dst, dstSize, src, srcSize,
maxSymbolValue, huffLog, HUF_fourStreams,
workSpace, wkspSize,
- hufTable, repeat, preferRepeat, bmi2);
+ hufTable, repeat, preferRepeat, bmi2, suspectUncompressible);
}
#ifndef ZSTD_NO_UNUSED_FUNCTIONS
@@ -918,7 +1351,7 @@ size_t HUF_compress1X (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
- unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
+ U64 workSpace[HUF_WORKSPACE_SIZE_U64];
return HUF_compress1X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
}
@@ -926,7 +1359,7 @@ size_t HUF_compress2 (void* dst, size_t dstSize,
const void* src, size_t srcSize,
unsigned maxSymbolValue, unsigned huffLog)
{
- unsigned workSpace[HUF_WORKSPACE_SIZE_U32];
+ U64 workSpace[HUF_WORKSPACE_SIZE_U64];
return HUF_compress4X_wksp(dst, dstSize, src, srcSize, maxSymbolValue, huffLog, workSpace, sizeof(workSpace));
}
diff --git a/thirdparty/zstd/compress/zstd_compress.c b/thirdparty/zstd/compress/zstd_compress.c
index b7ee2980a7..f06456af92 100644
--- a/thirdparty/zstd/compress/zstd_compress.c
+++ b/thirdparty/zstd/compress/zstd_compress.c
@@ -12,7 +12,6 @@
* Dependencies
***************************************/
#include "../common/zstd_deps.h" /* INT_MAX, ZSTD_memset, ZSTD_memcpy */
-#include "../common/cpu.h"
#include "../common/mem.h"
#include "hist.h" /* HIST_countFast_wksp */
#define FSE_STATIC_LINKING_ONLY /* FSE_encodeSymbol */
@@ -42,6 +41,18 @@
# define ZSTD_COMPRESS_HEAPMODE 0
#endif
+/*!
+ * ZSTD_HASHLOG3_MAX :
+ * Maximum size of the hash table dedicated to find 3-bytes matches,
+ * in log format, aka 17 => 1 << 17 == 128Ki positions.
+ * This structure is only used in zstd_opt.
+ * Since allocation is centralized for all strategies, it has to be known here.
+ * The actual (selected) size of the hash table is then stored in ZSTD_matchState_t.hashLog3,
+ * so that zstd_opt.c doesn't need to know about this constant.
+ */
+#ifndef ZSTD_HASHLOG3_MAX
+# define ZSTD_HASHLOG3_MAX 17
+#endif
/*-*************************************
* Helper functions
@@ -72,10 +83,10 @@ struct ZSTD_CDict_s {
ZSTD_customMem customMem;
U32 dictID;
int compressionLevel; /* 0 indicates that advanced API was used to select CDict params */
- ZSTD_useRowMatchFinderMode_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use
- * row-based matchfinder. Unless the cdict is reloaded, we will use
- * the same greedy/lazy matchfinder at compression time.
- */
+ ZSTD_paramSwitch_e useRowMatchFinder; /* Indicates whether the CDict was created with params that would use
+ * row-based matchfinder. Unless the cdict is reloaded, we will use
+ * the same greedy/lazy matchfinder at compression time.
+ */
}; /* typedef'd to ZSTD_CDict within "zstd.h" */
ZSTD_CCtx* ZSTD_createCCtx(void)
@@ -88,7 +99,7 @@ static void ZSTD_initCCtx(ZSTD_CCtx* cctx, ZSTD_customMem memManager)
assert(cctx != NULL);
ZSTD_memset(cctx, 0, sizeof(*cctx));
cctx->customMem = memManager;
- cctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
+ cctx->bmi2 = ZSTD_cpuSupportsBmi2();
{ size_t const err = ZSTD_CCtx_reset(cctx, ZSTD_reset_parameters);
assert(!ZSTD_isError(err));
(void)err;
@@ -214,35 +225,42 @@ static int ZSTD_rowMatchFinderSupported(const ZSTD_strategy strategy) {
/* Returns true if the strategy and useRowMatchFinder mode indicate that we will use the row based matchfinder
* for this compression.
*/
-static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_useRowMatchFinderMode_e mode) {
- assert(mode != ZSTD_urm_auto);
- return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_urm_enableRowMatchFinder);
+static int ZSTD_rowMatchFinderUsed(const ZSTD_strategy strategy, const ZSTD_paramSwitch_e mode) {
+ assert(mode != ZSTD_ps_auto);
+ return ZSTD_rowMatchFinderSupported(strategy) && (mode == ZSTD_ps_enable);
}
-/* Returns row matchfinder usage enum given an initial mode and cParams */
-static ZSTD_useRowMatchFinderMode_e ZSTD_resolveRowMatchFinderMode(ZSTD_useRowMatchFinderMode_e mode,
- const ZSTD_compressionParameters* const cParams) {
-#if !defined(ZSTD_NO_INTRINSICS) && (defined(__SSE2__) || defined(__ARM_NEON))
+/* Returns row matchfinder usage given an initial mode and cParams */
+static ZSTD_paramSwitch_e ZSTD_resolveRowMatchFinderMode(ZSTD_paramSwitch_e mode,
+ const ZSTD_compressionParameters* const cParams) {
+#if defined(ZSTD_ARCH_X86_SSE2) || defined(ZSTD_ARCH_ARM_NEON)
int const kHasSIMD128 = 1;
#else
int const kHasSIMD128 = 0;
#endif
- if (mode != ZSTD_urm_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */
- mode = ZSTD_urm_disableRowMatchFinder;
+ if (mode != ZSTD_ps_auto) return mode; /* if requested enabled, but no SIMD, we still will use row matchfinder */
+ mode = ZSTD_ps_disable;
if (!ZSTD_rowMatchFinderSupported(cParams->strategy)) return mode;
if (kHasSIMD128) {
- if (cParams->windowLog > 14) mode = ZSTD_urm_enableRowMatchFinder;
+ if (cParams->windowLog > 14) mode = ZSTD_ps_enable;
} else {
- if (cParams->windowLog > 17) mode = ZSTD_urm_enableRowMatchFinder;
+ if (cParams->windowLog > 17) mode = ZSTD_ps_enable;
}
return mode;
}
+/* Returns block splitter usage (generally speaking, when using slower/stronger compression modes) */
+static ZSTD_paramSwitch_e ZSTD_resolveBlockSplitterMode(ZSTD_paramSwitch_e mode,
+ const ZSTD_compressionParameters* const cParams) {
+ if (mode != ZSTD_ps_auto) return mode;
+ return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17) ? ZSTD_ps_enable : ZSTD_ps_disable;
+}
+
/* Returns 1 if the arguments indicate that we should allocate a chainTable, 0 otherwise */
static int ZSTD_allocateChainTable(const ZSTD_strategy strategy,
- const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const ZSTD_paramSwitch_e useRowMatchFinder,
const U32 forDDSDict) {
- assert(useRowMatchFinder != ZSTD_urm_auto);
+ assert(useRowMatchFinder != ZSTD_ps_auto);
/* We always should allocate a chaintable if we are allocating a matchstate for a DDS dictionary matchstate.
* We do not allocate a chaintable if we are using ZSTD_fast, or are using the row-based matchfinder.
*/
@@ -253,16 +271,10 @@ static int ZSTD_allocateChainTable(const ZSTD_strategy strategy,
* enable long distance matching (wlog >= 27, strategy >= btopt).
* Returns 0 otherwise.
*/
-static U32 ZSTD_CParams_shouldEnableLdm(const ZSTD_compressionParameters* const cParams) {
- return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27;
-}
-
-/* Returns 1 if compression parameters are such that we should
- * enable blockSplitter (wlog >= 17, strategy >= btopt).
- * Returns 0 otherwise.
- */
-static U32 ZSTD_CParams_useBlockSplitter(const ZSTD_compressionParameters* const cParams) {
- return cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 17;
+static ZSTD_paramSwitch_e ZSTD_resolveEnableLdm(ZSTD_paramSwitch_e mode,
+ const ZSTD_compressionParameters* const cParams) {
+ if (mode != ZSTD_ps_auto) return mode;
+ return (cParams->strategy >= ZSTD_btopt && cParams->windowLog >= 27) ? ZSTD_ps_enable : ZSTD_ps_disable;
}
static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
@@ -274,20 +286,13 @@ static ZSTD_CCtx_params ZSTD_makeCCtxParamsFromCParams(
cctxParams.cParams = cParams;
/* Adjust advanced params according to cParams */
- if (ZSTD_CParams_shouldEnableLdm(&cParams)) {
- DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including LDM into cctx params");
- cctxParams.ldmParams.enableLdm = 1;
- /* LDM is enabled by default for optimal parser and window size >= 128MB */
+ cctxParams.ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams.ldmParams.enableLdm, &cParams);
+ if (cctxParams.ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_ldm_adjustParameters(&cctxParams.ldmParams, &cParams);
assert(cctxParams.ldmParams.hashLog >= cctxParams.ldmParams.bucketSizeLog);
assert(cctxParams.ldmParams.hashRateLog < 32);
}
-
- if (ZSTD_CParams_useBlockSplitter(&cParams)) {
- DEBUGLOG(4, "ZSTD_makeCCtxParamsFromCParams(): Including block splitting into cctx params");
- cctxParams.splitBlocks = 1;
- }
-
+ cctxParams.useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams.useBlockSplitter, &cParams);
cctxParams.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams.useRowMatchFinder, &cParams);
assert(!ZSTD_checkCParams(cParams));
return cctxParams;
@@ -348,7 +353,10 @@ static void ZSTD_CCtxParams_init_internal(ZSTD_CCtx_params* cctxParams, ZSTD_par
*/
cctxParams->compressionLevel = compressionLevel;
cctxParams->useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(cctxParams->useRowMatchFinder, &params->cParams);
- DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d", cctxParams->useRowMatchFinder);
+ cctxParams->useBlockSplitter = ZSTD_resolveBlockSplitterMode(cctxParams->useBlockSplitter, &params->cParams);
+ cctxParams->ldmParams.enableLdm = ZSTD_resolveEnableLdm(cctxParams->ldmParams.enableLdm, &params->cParams);
+ DEBUGLOG(4, "ZSTD_CCtxParams_init_internal: useRowMatchFinder=%d, useBlockSplitter=%d ldm=%d",
+ cctxParams->useRowMatchFinder, cctxParams->useBlockSplitter, cctxParams->ldmParams.enableLdm);
}
size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params)
@@ -518,9 +526,9 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
return bounds;
case ZSTD_c_literalCompressionMode:
- ZSTD_STATIC_ASSERT(ZSTD_lcm_auto < ZSTD_lcm_huffman && ZSTD_lcm_huffman < ZSTD_lcm_uncompressed);
- bounds.lowerBound = ZSTD_lcm_auto;
- bounds.upperBound = ZSTD_lcm_uncompressed;
+ ZSTD_STATIC_ASSERT(ZSTD_ps_auto < ZSTD_ps_enable && ZSTD_ps_enable < ZSTD_ps_disable);
+ bounds.lowerBound = (int)ZSTD_ps_auto;
+ bounds.upperBound = (int)ZSTD_ps_disable;
return bounds;
case ZSTD_c_targetCBlockSize:
@@ -549,14 +557,14 @@ ZSTD_bounds ZSTD_cParam_getBounds(ZSTD_cParameter param)
bounds.upperBound = 1;
return bounds;
- case ZSTD_c_splitBlocks:
- bounds.lowerBound = 0;
- bounds.upperBound = 1;
+ case ZSTD_c_useBlockSplitter:
+ bounds.lowerBound = (int)ZSTD_ps_auto;
+ bounds.upperBound = (int)ZSTD_ps_disable;
return bounds;
case ZSTD_c_useRowMatchFinder:
- bounds.lowerBound = (int)ZSTD_urm_auto;
- bounds.upperBound = (int)ZSTD_urm_enableRowMatchFinder;
+ bounds.lowerBound = (int)ZSTD_ps_auto;
+ bounds.upperBound = (int)ZSTD_ps_disable;
return bounds;
case ZSTD_c_deterministicRefPrefix:
@@ -625,7 +633,7 @@ static int ZSTD_isUpdateAuthorized(ZSTD_cParameter param)
case ZSTD_c_stableOutBuffer:
case ZSTD_c_blockDelimiters:
case ZSTD_c_validateSequences:
- case ZSTD_c_splitBlocks:
+ case ZSTD_c_useBlockSplitter:
case ZSTD_c_useRowMatchFinder:
case ZSTD_c_deterministicRefPrefix:
default:
@@ -680,7 +688,7 @@ size_t ZSTD_CCtx_setParameter(ZSTD_CCtx* cctx, ZSTD_cParameter param, int value)
case ZSTD_c_stableOutBuffer:
case ZSTD_c_blockDelimiters:
case ZSTD_c_validateSequences:
- case ZSTD_c_splitBlocks:
+ case ZSTD_c_useBlockSplitter:
case ZSTD_c_useRowMatchFinder:
case ZSTD_c_deterministicRefPrefix:
break;
@@ -780,7 +788,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
}
case ZSTD_c_literalCompressionMode : {
- const ZSTD_literalCompressionMode_e lcm = (ZSTD_literalCompressionMode_e)value;
+ const ZSTD_paramSwitch_e lcm = (ZSTD_paramSwitch_e)value;
BOUNDCHECK(ZSTD_c_literalCompressionMode, lcm);
CCtxParams->literalCompressionMode = lcm;
return CCtxParams->literalCompressionMode;
@@ -835,7 +843,7 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
return CCtxParams->enableDedicatedDictSearch;
case ZSTD_c_enableLongDistanceMatching :
- CCtxParams->ldmParams.enableLdm = (value!=0);
+ CCtxParams->ldmParams.enableLdm = (ZSTD_paramSwitch_e)value;
return CCtxParams->ldmParams.enableLdm;
case ZSTD_c_ldmHashLog :
@@ -857,8 +865,8 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
return CCtxParams->ldmParams.bucketSizeLog;
case ZSTD_c_ldmHashRateLog :
- RETURN_ERROR_IF(value > ZSTD_WINDOWLOG_MAX - ZSTD_HASHLOG_MIN,
- parameter_outOfBound, "Param out of bounds!");
+ if (value!=0) /* 0 ==> default */
+ BOUNDCHECK(ZSTD_c_ldmHashRateLog, value);
CCtxParams->ldmParams.hashRateLog = value;
return CCtxParams->ldmParams.hashRateLog;
@@ -894,14 +902,14 @@ size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* CCtxParams,
CCtxParams->validateSequences = value;
return CCtxParams->validateSequences;
- case ZSTD_c_splitBlocks:
- BOUNDCHECK(ZSTD_c_splitBlocks, value);
- CCtxParams->splitBlocks = value;
- return CCtxParams->splitBlocks;
+ case ZSTD_c_useBlockSplitter:
+ BOUNDCHECK(ZSTD_c_useBlockSplitter, value);
+ CCtxParams->useBlockSplitter = (ZSTD_paramSwitch_e)value;
+ return CCtxParams->useBlockSplitter;
case ZSTD_c_useRowMatchFinder:
BOUNDCHECK(ZSTD_c_useRowMatchFinder, value);
- CCtxParams->useRowMatchFinder = (ZSTD_useRowMatchFinderMode_e)value;
+ CCtxParams->useRowMatchFinder = (ZSTD_paramSwitch_e)value;
return CCtxParams->useRowMatchFinder;
case ZSTD_c_deterministicRefPrefix:
@@ -1032,8 +1040,8 @@ size_t ZSTD_CCtxParams_getParameter(
case ZSTD_c_validateSequences :
*value = (int)CCtxParams->validateSequences;
break;
- case ZSTD_c_splitBlocks :
- *value = (int)CCtxParams->splitBlocks;
+ case ZSTD_c_useBlockSplitter :
+ *value = (int)CCtxParams->useBlockSplitter;
break;
case ZSTD_c_useRowMatchFinder :
*value = (int)CCtxParams->useRowMatchFinder;
@@ -1067,7 +1075,7 @@ size_t ZSTD_CCtx_setParametersUsingCCtxParams(
return 0;
}
-ZSTDLIB_API size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
+size_t ZSTD_CCtx_setPledgedSrcSize(ZSTD_CCtx* cctx, unsigned long long pledgedSrcSize)
{
DEBUGLOG(4, "ZSTD_CCtx_setPledgedSrcSize to %u bytes", (U32)pledgedSrcSize);
RETURN_ERROR_IF(cctx->streamStage != zcss_init, stage_wrong,
@@ -1147,14 +1155,14 @@ size_t ZSTD_CCtx_loadDictionary_advanced(
return 0;
}
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(
+size_t ZSTD_CCtx_loadDictionary_byReference(
ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
{
return ZSTD_CCtx_loadDictionary_advanced(
cctx, dict, dictSize, ZSTD_dlm_byRef, ZSTD_dct_auto);
}
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
+size_t ZSTD_CCtx_loadDictionary(ZSTD_CCtx* cctx, const void* dict, size_t dictSize)
{
return ZSTD_CCtx_loadDictionary_advanced(
cctx, dict, dictSize, ZSTD_dlm_byCopy, ZSTD_dct_auto);
@@ -1324,7 +1332,7 @@ ZSTD_adjustCParams_internal(ZSTD_compressionParameters cPar,
break;
case ZSTD_cpm_createCDict:
/* Assume a small source size when creating a dictionary
- * with an unkown source size.
+ * with an unknown source size.
*/
if (dictSize && srcSize == ZSTD_CONTENTSIZE_UNKNOWN)
srcSize = minSrcSize;
@@ -1398,7 +1406,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
srcSizeHint = CCtxParams->srcSizeHint;
}
cParams = ZSTD_getCParams_internal(CCtxParams->compressionLevel, srcSizeHint, dictSize, mode);
- if (CCtxParams->ldmParams.enableLdm) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
+ if (CCtxParams->ldmParams.enableLdm == ZSTD_ps_enable) cParams.windowLog = ZSTD_LDM_DEFAULT_WINDOW_LOG;
ZSTD_overrideCParams(&cParams, &CCtxParams->cParams);
assert(!ZSTD_checkCParams(cParams));
/* srcSizeHint == 0 means 0 */
@@ -1407,7 +1415,7 @@ ZSTD_compressionParameters ZSTD_getCParamsFromCCtxParams(
static size_t
ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
- const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const ZSTD_paramSwitch_e useRowMatchFinder,
const U32 enableDedicatedDictSearch,
const U32 forCCtx)
{
@@ -1440,7 +1448,7 @@ ZSTD_sizeof_matchState(const ZSTD_compressionParameters* const cParams,
/* tables are guaranteed to be sized in multiples of 64 bytes (or 16 uint32_t) */
ZSTD_STATIC_ASSERT(ZSTD_HASHLOG_MIN >= 4 && ZSTD_WINDOWLOG_MIN >= 4 && ZSTD_CHAINLOG_MIN >= 4);
- assert(useRowMatchFinder != ZSTD_urm_auto);
+ assert(useRowMatchFinder != ZSTD_ps_auto);
DEBUGLOG(4, "chainSize: %u - hSize: %u - h3Size: %u",
(U32)chainSize, (U32)hSize, (U32)h3Size);
@@ -1451,12 +1459,12 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
const ZSTD_compressionParameters* cParams,
const ldmParams_t* ldmParams,
const int isStatic,
- const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const ZSTD_paramSwitch_e useRowMatchFinder,
const size_t buffInSize,
const size_t buffOutSize,
const U64 pledgedSrcSize)
{
- size_t const windowSize = MAX(1, (size_t)MIN(((U64)1 << cParams->windowLog), pledgedSrcSize));
+ size_t const windowSize = (size_t) BOUNDED(1ULL, 1ULL << cParams->windowLog, pledgedSrcSize);
size_t const blockSize = MIN(ZSTD_BLOCKSIZE_MAX, windowSize);
U32 const divider = (cParams->minMatch==3) ? 3 : 4;
size_t const maxNbSeq = blockSize / divider;
@@ -1469,7 +1477,7 @@ static size_t ZSTD_estimateCCtxSize_usingCCtxParams_internal(
size_t const ldmSpace = ZSTD_ldm_getTableSize(*ldmParams);
size_t const maxNbLdmSeq = ZSTD_ldm_getMaxNbSeq(*ldmParams, blockSize);
- size_t const ldmSeqSpace = ldmParams->enableLdm ?
+ size_t const ldmSeqSpace = ldmParams->enableLdm == ZSTD_ps_enable ?
ZSTD_cwksp_aligned_alloc_size(maxNbLdmSeq * sizeof(rawSeq)) : 0;
@@ -1496,8 +1504,8 @@ size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params)
{
ZSTD_compressionParameters const cParams =
ZSTD_getCParamsFromCCtxParams(params, ZSTD_CONTENTSIZE_UNKNOWN, 0, ZSTD_cpm_noAttachDict);
- ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
- &cParams);
+ ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder,
+ &cParams);
RETURN_ERROR_IF(params->nbWorkers > 0, GENERIC, "Estimate CCtx size is supported for single-threaded compression only.");
/* estimateCCtxSize is for one-shot compression. So no buffers should
@@ -1514,9 +1522,9 @@ size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams)
/* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */
size_t noRowCCtxSize;
size_t rowCCtxSize;
- initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder;
+ initialParams.useRowMatchFinder = ZSTD_ps_disable;
noRowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);
- initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder;
+ initialParams.useRowMatchFinder = ZSTD_ps_enable;
rowCCtxSize = ZSTD_estimateCCtxSize_usingCCtxParams(&initialParams);
return MAX(noRowCCtxSize, rowCCtxSize);
} else {
@@ -1561,7 +1569,7 @@ size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params)
size_t const outBuffSize = (params->outBufferMode == ZSTD_bm_buffered)
? ZSTD_compressBound(blockSize) + 1
: 0;
- ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);
+ ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params->useRowMatchFinder, &params->cParams);
return ZSTD_estimateCCtxSize_usingCCtxParams_internal(
&cParams, &params->ldmParams, 1, useRowMatchFinder, inBuffSize, outBuffSize,
@@ -1576,9 +1584,9 @@ size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams)
/* Pick bigger of not using and using row-based matchfinder for greedy and lazy strategies */
size_t noRowCCtxSize;
size_t rowCCtxSize;
- initialParams.useRowMatchFinder = ZSTD_urm_disableRowMatchFinder;
+ initialParams.useRowMatchFinder = ZSTD_ps_disable;
noRowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);
- initialParams.useRowMatchFinder = ZSTD_urm_enableRowMatchFinder;
+ initialParams.useRowMatchFinder = ZSTD_ps_enable;
rowCCtxSize = ZSTD_estimateCStreamSize_usingCCtxParams(&initialParams);
return MAX(noRowCCtxSize, rowCCtxSize);
} else {
@@ -1713,7 +1721,7 @@ static size_t
ZSTD_reset_matchState(ZSTD_matchState_t* ms,
ZSTD_cwksp* ws,
const ZSTD_compressionParameters* cParams,
- const ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ const ZSTD_paramSwitch_e useRowMatchFinder,
const ZSTD_compResetPolicy_e crp,
const ZSTD_indexResetPolicy_e forceResetIndex,
const ZSTD_resetTarget_e forWho)
@@ -1728,7 +1736,7 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
size_t const h3Size = hashLog3 ? ((size_t)1) << hashLog3 : 0;
DEBUGLOG(4, "reset indices : %u", forceResetIndex == ZSTDirp_reset);
- assert(useRowMatchFinder != ZSTD_urm_auto);
+ assert(useRowMatchFinder != ZSTD_ps_auto);
if (forceResetIndex == ZSTDirp_reset) {
ZSTD_window_init(&ms->window);
ZSTD_cwksp_mark_tables_dirty(ws);
@@ -1774,8 +1782,8 @@ ZSTD_reset_matchState(ZSTD_matchState_t* ms,
if (ms->tagTable) ZSTD_memset(ms->tagTable, 0, tagTableSize);
}
{ /* Switch to 32-entry rows if searchLog is 5 (or more) */
- U32 const rowLog = cParams->searchLog < 5 ? 4 : 5;
- assert(cParams->hashLog > rowLog);
+ U32 const rowLog = BOUNDED(4, cParams->searchLog, 6);
+ assert(cParams->hashLog >= rowLog);
ms->rowHashLog = cParams->hashLog - rowLog;
}
}
@@ -1824,8 +1832,8 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
ZSTD_buffered_policy_e const zbuff)
{
ZSTD_cwksp* const ws = &zc->workspace;
- DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d",
- (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder);
+ DEBUGLOG(4, "ZSTD_resetCCtx_internal: pledgedSrcSize=%u, wlog=%u, useRowMatchFinder=%d useBlockSplitter=%d",
+ (U32)pledgedSrcSize, params->cParams.windowLog, (int)params->useRowMatchFinder, (int)params->useBlockSplitter);
assert(!ZSTD_isError(ZSTD_checkCParams(params->cParams)));
zc->isFirstBlock = 1;
@@ -1836,8 +1844,10 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->appliedParams = *params;
params = &zc->appliedParams;
- assert(params->useRowMatchFinder != ZSTD_urm_auto);
- if (params->ldmParams.enableLdm) {
+ assert(params->useRowMatchFinder != ZSTD_ps_auto);
+ assert(params->useBlockSplitter != ZSTD_ps_auto);
+ assert(params->ldmParams.enableLdm != ZSTD_ps_auto);
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
/* Adjust long distance matching parameters */
ZSTD_ldm_adjustParameters(&zc->appliedParams.ldmParams, &params->cParams);
assert(params->ldmParams.hashLog >= params->ldmParams.bucketSizeLog);
@@ -1900,7 +1910,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->blockState.nextCBlock = (ZSTD_compressedBlockState_t*) ZSTD_cwksp_reserve_object(ws, sizeof(ZSTD_compressedBlockState_t));
RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate nextCBlock");
zc->entropyWorkspace = (U32*) ZSTD_cwksp_reserve_object(ws, ENTROPY_WORKSPACE_SIZE);
- RETURN_ERROR_IF(zc->blockState.nextCBlock == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
+ RETURN_ERROR_IF(zc->entropyWorkspace == NULL, memory_allocation, "couldn't allocate entropyWorkspace");
} }
ZSTD_cwksp_clear(ws);
@@ -1937,7 +1947,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->outBuff = (char*)ZSTD_cwksp_reserve_buffer(ws, buffOutSize);
/* ldm bucketOffsets table */
- if (params->ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
/* TODO: avoid memset? */
size_t const numBuckets =
((size_t)1) << (params->ldmParams.hashLog -
@@ -1964,7 +1974,7 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
ZSTD_resetTarget_CCtx), "");
/* ldm hash table */
- if (params->ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
/* TODO: avoid memset? */
size_t const ldmHSize = ((size_t)1) << params->ldmParams.hashLog;
zc->ldmState.hashTable = (ldmEntry_t*)ZSTD_cwksp_reserve_aligned(ws, ldmHSize * sizeof(ldmEntry_t));
@@ -1976,8 +1986,8 @@ static size_t ZSTD_resetCCtx_internal(ZSTD_CCtx* zc,
zc->ldmState.loadedDictEnd = 0;
}
- assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace, resizeWorkspace));
DEBUGLOG(3, "wksp: finished allocating, %zd bytes remain available", ZSTD_cwksp_available_space(ws));
+ assert(ZSTD_cwksp_estimated_space_within_bounds(ws, neededSpace, resizeWorkspace));
zc->initialized = 1;
@@ -2115,7 +2125,7 @@ static size_t ZSTD_resetCCtx_byCopyingCDict(ZSTD_CCtx* cctx,
}
ZSTD_cwksp_mark_tables_dirty(&cctx->workspace);
- assert(params.useRowMatchFinder != ZSTD_urm_auto);
+ assert(params.useRowMatchFinder != ZSTD_ps_auto);
/* copy tables */
{ size_t const chainSize = ZSTD_allocateChainTable(cdict_cParams->strategy, cdict->useRowMatchFinder, 0 /* DDS guaranteed disabled */)
@@ -2209,8 +2219,12 @@ static size_t ZSTD_copyCCtx_internal(ZSTD_CCtx* dstCCtx,
{ ZSTD_CCtx_params params = dstCCtx->requestedParams;
/* Copy only compression parameters related to tables. */
params.cParams = srcCCtx->appliedParams.cParams;
- assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_urm_auto);
+ assert(srcCCtx->appliedParams.useRowMatchFinder != ZSTD_ps_auto);
+ assert(srcCCtx->appliedParams.useBlockSplitter != ZSTD_ps_auto);
+ assert(srcCCtx->appliedParams.ldmParams.enableLdm != ZSTD_ps_auto);
params.useRowMatchFinder = srcCCtx->appliedParams.useRowMatchFinder;
+ params.useBlockSplitter = srcCCtx->appliedParams.useBlockSplitter;
+ params.ldmParams = srcCCtx->appliedParams.ldmParams;
params.fParams = fParams;
ZSTD_resetCCtx_internal(dstCCtx, &params, pledgedSrcSize,
/* loadedDictSize */ 0,
@@ -2296,6 +2310,8 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
int const nbRows = (int)size / ZSTD_ROWSIZE;
int cellNb = 0;
int rowNb;
+ /* Protect special index values < ZSTD_WINDOW_START_INDEX. */
+ U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX;
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
assert(size < (1U<<31)); /* can be casted to int */
@@ -2315,12 +2331,17 @@ ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerVa
for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
int column;
for (column=0; column<ZSTD_ROWSIZE; column++) {
- if (preserveMark) {
- U32 const adder = (table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) ? reducerValue : 0;
- table[cellNb] += adder;
+ U32 newVal;
+ if (preserveMark && table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) {
+ /* This write is pointless, but is required(?) for the compiler
+ * to auto-vectorize the loop. */
+ newVal = ZSTD_DUBT_UNSORTED_MARK;
+ } else if (table[cellNb] < reducerThreshold) {
+ newVal = 0;
+ } else {
+ newVal = table[cellNb] - reducerValue;
}
- if (table[cellNb] < reducerValue) table[cellNb] = 0;
- else table[cellNb] -= reducerValue;
+ table[cellNb] = newVal;
cellNb++;
} }
}
@@ -2375,9 +2396,9 @@ void ZSTD_seqToCodes(const seqStore_t* seqStorePtr)
assert(nbSeq <= seqStorePtr->maxNbSeq);
for (u=0; u<nbSeq; u++) {
U32 const llv = sequences[u].litLength;
- U32 const mlv = sequences[u].matchLength;
+ U32 const mlv = sequences[u].mlBase;
llCodeTable[u] = (BYTE)ZSTD_LLcode(llv);
- ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offset);
+ ofCodeTable[u] = (BYTE)ZSTD_highbit32(sequences[u].offBase);
mlCodeTable[u] = (BYTE)ZSTD_MLcode(mlv);
}
if (seqStorePtr->longLengthType==ZSTD_llt_literalLength)
@@ -2399,11 +2420,13 @@ static int ZSTD_useTargetCBlockSize(const ZSTD_CCtx_params* cctxParams)
/* ZSTD_blockSplitterEnabled():
* Returns if block splitting param is being used
* If used, compression will do best effort to split a block in order to improve compression ratio.
+ * At the time this function is called, the parameter must be finalized.
* Returns 1 if true, 0 otherwise. */
static int ZSTD_blockSplitterEnabled(ZSTD_CCtx_params* cctxParams)
{
- DEBUGLOG(5, "ZSTD_blockSplitterEnabled(splitBlocks=%d)", cctxParams->splitBlocks);
- return (cctxParams->splitBlocks != 0);
+ DEBUGLOG(5, "ZSTD_blockSplitterEnabled (useBlockSplitter=%d)", cctxParams->useBlockSplitter);
+ assert(cctxParams->useBlockSplitter != ZSTD_ps_auto);
+ return (cctxParams->useBlockSplitter == ZSTD_ps_enable);
}
/* Type returned by ZSTD_buildSequencesStatistics containing finalized symbol encoding types
@@ -2546,6 +2569,7 @@ ZSTD_buildSequencesStatistics(seqStore_t* seqStorePtr, size_t nbSeq,
* compresses both literals and sequences
* Returns compressed size of block, or a zstd error.
*/
+#define SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO 20
MEM_STATIC size_t
ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
const ZSTD_entropyCTables_t* prevEntropy,
@@ -2580,15 +2604,19 @@ ZSTD_entropyCompressSeqStore_internal(seqStore_t* seqStorePtr,
/* Compress literals */
{ const BYTE* const literals = seqStorePtr->litStart;
+ size_t const numSequences = seqStorePtr->sequences - seqStorePtr->sequencesStart;
+ size_t const numLiterals = seqStorePtr->lit - seqStorePtr->litStart;
+ /* Base suspicion of uncompressibility on ratio of literals to sequences */
+ unsigned const suspectUncompressible = (numSequences == 0) || (numLiterals / numSequences >= SUSPECT_UNCOMPRESSIBLE_LITERAL_RATIO);
size_t const litSize = (size_t)(seqStorePtr->lit - literals);
size_t const cSize = ZSTD_compressLiterals(
&prevEntropy->huf, &nextEntropy->huf,
cctxParams->cParams.strategy,
- ZSTD_disableLiteralsCompression(cctxParams),
+ ZSTD_literalsCompressionIsDisabled(cctxParams),
op, dstCapacity,
literals, litSize,
entropyWorkspace, entropyWkspSize,
- bmi2);
+ bmi2, suspectUncompressible);
FORWARD_IF_ERROR(cSize, "ZSTD_compressLiterals failed");
assert(cSize <= dstCapacity);
op += cSize;
@@ -2693,7 +2721,7 @@ ZSTD_entropyCompressSeqStore(seqStore_t* seqStorePtr,
/* ZSTD_selectBlockCompressor() :
* Not static, but internal use only (used by long distance matcher)
* assumption : strat is a valid strategy */
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e useRowMatchFinder, ZSTD_dictMode_e dictMode)
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e useRowMatchFinder, ZSTD_dictMode_e dictMode)
{
static const ZSTD_blockCompressor blockCompressor[4][ZSTD_STRATEGY_MAX+1] = {
{ ZSTD_compressBlock_fast /* default for 0 */,
@@ -2758,7 +2786,7 @@ ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRow
ZSTD_compressBlock_lazy2_dedicatedDictSearch_row }
};
DEBUGLOG(4, "Selecting a row-based matchfinder");
- assert(useRowMatchFinder != ZSTD_urm_auto);
+ assert(useRowMatchFinder != ZSTD_ps_auto);
selectedCompressor = rowBasedBlockCompressors[(int)dictMode][(int)strat - (int)ZSTD_greedy];
} else {
selectedCompressor = blockCompressor[(int)dictMode][(int)strat];
@@ -2825,7 +2853,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
zc->blockState.nextCBlock->rep[i] = zc->blockState.prevCBlock->rep[i];
}
if (zc->externSeqStore.pos < zc->externSeqStore.size) {
- assert(!zc->appliedParams.ldmParams.enableLdm);
+ assert(zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_disable);
/* Updates ldmSeqStore.pos */
lastLLSize =
ZSTD_ldm_blockCompress(&zc->externSeqStore,
@@ -2834,7 +2862,7 @@ static size_t ZSTD_buildSeqStore(ZSTD_CCtx* zc, const void* src, size_t srcSize)
zc->appliedParams.useRowMatchFinder,
src, srcSize);
assert(zc->externSeqStore.pos <= zc->externSeqStore.size);
- } else if (zc->appliedParams.ldmParams.enableLdm) {
+ } else if (zc->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {
rawSeqStore_t ldmSeqStore = kNullRawSeqStore;
ldmSeqStore.seq = zc->ldmSequences;
@@ -2882,9 +2910,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
assert(zc->seqCollector.maxSequences >= seqStoreSeqSize + 1);
ZSTD_memcpy(updatedRepcodes.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
for (i = 0; i < seqStoreSeqSize; ++i) {
- U32 rawOffset = seqStoreSeqs[i].offset - ZSTD_REP_NUM;
+ U32 rawOffset = seqStoreSeqs[i].offBase - ZSTD_REP_NUM;
outSeqs[i].litLength = seqStoreSeqs[i].litLength;
- outSeqs[i].matchLength = seqStoreSeqs[i].matchLength + MINMATCH;
+ outSeqs[i].matchLength = seqStoreSeqs[i].mlBase + MINMATCH;
outSeqs[i].rep = 0;
if (i == seqStore->longLengthPos) {
@@ -2895,9 +2923,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
}
}
- if (seqStoreSeqs[i].offset <= ZSTD_REP_NUM) {
+ if (seqStoreSeqs[i].offBase <= ZSTD_REP_NUM) {
/* Derive the correct offset corresponding to a repcode */
- outSeqs[i].rep = seqStoreSeqs[i].offset;
+ outSeqs[i].rep = seqStoreSeqs[i].offBase;
if (outSeqs[i].litLength != 0) {
rawOffset = updatedRepcodes.rep[outSeqs[i].rep - 1];
} else {
@@ -2911,9 +2939,9 @@ static void ZSTD_copyBlockSequences(ZSTD_CCtx* zc)
outSeqs[i].offset = rawOffset;
/* seqStoreSeqs[i].offset == offCode+1, and ZSTD_updateRep() expects offCode
so we provide seqStoreSeqs[i].offset - 1 */
- updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep,
- seqStoreSeqs[i].offset - 1,
- seqStoreSeqs[i].litLength == 0);
+ ZSTD_updateRep(updatedRepcodes.rep,
+ seqStoreSeqs[i].offBase - 1,
+ seqStoreSeqs[i].litLength == 0);
literalsRead += outSeqs[i].litLength;
}
/* Insert last literals (if any exist) in the block as a sequence with ml == off == 0.
@@ -3027,7 +3055,7 @@ static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSi
const ZSTD_hufCTables_t* prevHuf,
ZSTD_hufCTables_t* nextHuf,
ZSTD_hufCTablesMetadata_t* hufMetadata,
- const int disableLiteralsCompression,
+ const int literalsCompressionIsDisabled,
void* workspace, size_t wkspSize)
{
BYTE* const wkspStart = (BYTE*)workspace;
@@ -3045,7 +3073,7 @@ static size_t ZSTD_buildBlockEntropyStats_literals(void* const src, size_t srcSi
/* Prepare nextEntropy assuming reusing the existing table */
ZSTD_memcpy(nextHuf, prevHuf, sizeof(*prevHuf));
- if (disableLiteralsCompression) {
+ if (literalsCompressionIsDisabled) {
DEBUGLOG(5, "set_basic - disabled");
hufMetadata->hType = set_basic;
return 0;
@@ -3192,7 +3220,7 @@ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
ZSTD_buildBlockEntropyStats_literals(seqStorePtr->litStart, litSize,
&prevEntropy->huf, &nextEntropy->huf,
&entropyMetadata->hufMetadata,
- ZSTD_disableLiteralsCompression(cctxParams),
+ ZSTD_literalsCompressionIsDisabled(cctxParams),
workspace, wkspSize);
FORWARD_IF_ERROR(entropyMetadata->hufMetadata.hufDesSize, "ZSTD_buildBlockEntropyStats_literals failed");
entropyMetadata->fseMetadata.fseTablesSize =
@@ -3235,7 +3263,7 @@ static size_t ZSTD_estimateBlockSize_literal(const BYTE* literals, size_t litSiz
static size_t ZSTD_estimateBlockSize_symbolType(symbolEncodingType_e type,
const BYTE* codeTable, size_t nbSeq, unsigned maxCode,
const FSE_CTable* fseCTable,
- const U32* additionalBits,
+ const U8* additionalBits,
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
void* workspace, size_t wkspSize)
{
@@ -3319,19 +3347,20 @@ static size_t ZSTD_estimateBlockSize(const BYTE* literals, size_t litSize,
*
* Returns the estimated compressed size of the seqStore, or a zstd error.
*/
-static size_t ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, const ZSTD_CCtx* zc) {
- ZSTD_entropyCTablesMetadata_t entropyMetadata;
+static size_t ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(seqStore_t* seqStore, ZSTD_CCtx* zc) {
+ ZSTD_entropyCTablesMetadata_t* entropyMetadata = &zc->blockSplitCtx.entropyMetadata;
+ DEBUGLOG(6, "ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize()");
FORWARD_IF_ERROR(ZSTD_buildBlockEntropyStats(seqStore,
&zc->blockState.prevCBlock->entropy,
&zc->blockState.nextCBlock->entropy,
&zc->appliedParams,
- &entropyMetadata,
+ entropyMetadata,
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */), "");
return ZSTD_estimateBlockSize(seqStore->litStart, (size_t)(seqStore->lit - seqStore->litStart),
seqStore->ofCode, seqStore->llCode, seqStore->mlCode,
(size_t)(seqStore->sequences - seqStore->sequencesStart),
- &zc->blockState.nextCBlock->entropy, &entropyMetadata, zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE,
- (int)(entropyMetadata.hufMetadata.hType == set_compressed), 1);
+ &zc->blockState.nextCBlock->entropy, entropyMetadata, zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE,
+ (int)(entropyMetadata->hufMetadata.hType == set_compressed), 1);
}
/* Returns literals bytes represented in a seqStore */
@@ -3356,7 +3385,7 @@ static size_t ZSTD_countSeqStoreMatchBytes(const seqStore_t* const seqStore) {
size_t i;
for (i = 0; i < nbSeqs; ++i) {
seqDef seq = seqStore->sequencesStart[i];
- matchBytes += seq.matchLength + MINMATCH;
+ matchBytes += seq.mlBase + MINMATCH;
if (i == seqStore->longLengthPos && seqStore->longLengthType == ZSTD_llt_matchLength) {
matchBytes += 0x10000;
}
@@ -3405,11 +3434,13 @@ static void ZSTD_deriveSeqStoreChunk(seqStore_t* resultSeqStore,
/**
* Returns the raw offset represented by the combination of offCode, ll0, and repcode history.
- * offCode must be an offCode representing a repcode, therefore in the range of [0, 2].
+ * offCode must represent a repcode in the numeric representation of ZSTD_storeSeq().
*/
-static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0) {
- U32 const adjustedOffCode = offCode + ll0;
- assert(offCode < ZSTD_REP_NUM);
+static U32
+ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32 offCode, const U32 ll0)
+{
+ U32 const adjustedOffCode = STORED_REPCODE(offCode) - 1 + ll0; /* [ 0 - 3 ] */
+ assert(STORED_IS_REPCODE(offCode));
if (adjustedOffCode == ZSTD_REP_NUM) {
/* litlength == 0 and offCode == 2 implies selection of first repcode - 1 */
assert(rep[0] > 0);
@@ -3420,11 +3451,16 @@ static U32 ZSTD_resolveRepcodeToRawOffset(const U32 rep[ZSTD_REP_NUM], const U32
/**
* ZSTD_seqStore_resolveOffCodes() reconciles any possible divergences in offset history that may arise
- * due to emission of RLE/raw blocks that disturb the offset history, and replaces any repcodes within
- * the seqStore that may be invalid.
+ * due to emission of RLE/raw blocks that disturb the offset history,
+ * and replaces any repcodes within the seqStore that may be invalid.
+ *
+ * dRepcodes are updated as would be on the decompression side.
+ * cRepcodes are updated exactly in accordance with the seqStore.
*
- * dRepcodes are updated as would be on the decompression side. cRepcodes are updated exactly in
- * accordance with the seqStore.
+ * Note : this function assumes seq->offBase respects the following numbering scheme :
+ * 0 : invalid
+ * 1-3 : repcode 1-3
+ * 4+ : real_offset+3
*/
static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_t* const cRepcodes,
seqStore_t* const seqStore, U32 const nbSeq) {
@@ -3432,9 +3468,9 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
for (; idx < nbSeq; ++idx) {
seqDef* const seq = seqStore->sequencesStart + idx;
U32 const ll0 = (seq->litLength == 0);
- U32 offCode = seq->offset - 1;
- assert(seq->offset > 0);
- if (offCode <= ZSTD_REP_MOVE) {
+ U32 const offCode = OFFBASE_TO_STORED(seq->offBase);
+ assert(seq->offBase > 0);
+ if (STORED_IS_REPCODE(offCode)) {
U32 const dRawOffset = ZSTD_resolveRepcodeToRawOffset(dRepcodes->rep, offCode, ll0);
U32 const cRawOffset = ZSTD_resolveRepcodeToRawOffset(cRepcodes->rep, offCode, ll0);
/* Adjust simulated decompression repcode history if we come across a mismatch. Replace
@@ -3442,14 +3478,14 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
* repcode history.
*/
if (dRawOffset != cRawOffset) {
- seq->offset = cRawOffset + ZSTD_REP_NUM;
+ seq->offBase = cRawOffset + ZSTD_REP_NUM;
}
}
/* Compression repcode history is always updated with values directly from the unmodified seqStore.
* Decompression repcode history may use modified seq->offset value taken from compression repcode history.
*/
- *dRepcodes = ZSTD_updateRep(dRepcodes->rep, seq->offset - 1, ll0);
- *cRepcodes = ZSTD_updateRep(cRepcodes->rep, offCode, ll0);
+ ZSTD_updateRep(dRepcodes->rep, OFFBASE_TO_STORED(seq->offBase), ll0);
+ ZSTD_updateRep(cRepcodes->rep, offCode, ll0);
}
}
@@ -3458,11 +3494,13 @@ static void ZSTD_seqStore_resolveOffCodes(repcodes_t* const dRepcodes, repcodes_
*
* Returns the total size of that block (including header) or a ZSTD error code.
*/
-static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
- repcodes_t* const dRep, repcodes_t* const cRep,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize,
- U32 lastBlock, U32 isPartition) {
+static size_t
+ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const seqStore,
+ repcodes_t* const dRep, repcodes_t* const cRep,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize,
+ U32 lastBlock, U32 isPartition)
+{
const U32 rleMaxLength = 25;
BYTE* op = (BYTE*)dst;
const BYTE* ip = (const BYTE*)src;
@@ -3471,9 +3509,11 @@ static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const
/* In case of an RLE or raw block, the simulated decompression repcode history must be reset */
repcodes_t const dRepOriginal = *dRep;
+ DEBUGLOG(5, "ZSTD_compressSeqStore_singleBlock");
if (isPartition)
ZSTD_seqStore_resolveOffCodes(dRep, cRep, seqStore, (U32)(seqStore->sequences - seqStore->sequencesStart));
+ RETURN_ERROR_IF(dstCapacity < ZSTD_blockHeaderSize, dstSize_tooSmall, "Block header doesn't fit");
cSeqsSize = ZSTD_entropyCompressSeqStore(seqStore,
&zc->blockState.prevCBlock->entropy, &zc->blockState.nextCBlock->entropy,
&zc->appliedParams,
@@ -3499,9 +3539,6 @@ static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const
return 0;
}
- if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
- zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
-
if (cSeqsSize == 0) {
cSize = ZSTD_noCompressBlock(op, dstCapacity, ip, srcSize, lastBlock);
FORWARD_IF_ERROR(cSize, "Nocompress block failed");
@@ -3518,6 +3555,10 @@ static size_t ZSTD_compressSeqStore_singleBlock(ZSTD_CCtx* zc, seqStore_t* const
cSize = ZSTD_blockHeaderSize + cSeqsSize;
DEBUGLOG(4, "Writing out compressed block, size: %zu", cSize);
}
+
+ if (zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode == FSE_repeat_valid)
+ zc->blockState.prevCBlock->entropy.fse.offcode_repeatMode = FSE_repeat_check;
+
return cSize;
}
@@ -3528,7 +3569,6 @@ typedef struct {
} seqStoreSplits;
#define MIN_SEQUENCES_BLOCK_SPLITTING 300
-#define MAX_NB_SPLITS 196
/* Helper function to perform the recursive search for block splits.
* Estimates the cost of seqStore prior to split, and estimates the cost of splitting the sequences in half.
@@ -3539,29 +3579,33 @@ typedef struct {
* In theory, this means the absolute largest recursion depth is 10 == log2(maxNbSeqInBlock/MIN_SEQUENCES_BLOCK_SPLITTING).
* In practice, recursion depth usually doesn't go beyond 4.
*
- * Furthermore, the number of splits is capped by MAX_NB_SPLITS. At MAX_NB_SPLITS == 196 with the current existing blockSize
+ * Furthermore, the number of splits is capped by ZSTD_MAX_NB_BLOCK_SPLITS. At ZSTD_MAX_NB_BLOCK_SPLITS == 196 with the current existing blockSize
* maximum of 128 KB, this value is actually impossible to reach.
*/
-static void ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
- const ZSTD_CCtx* zc, const seqStore_t* origSeqStore) {
- seqStore_t fullSeqStoreChunk;
- seqStore_t firstHalfSeqStore;
- seqStore_t secondHalfSeqStore;
+static void
+ZSTD_deriveBlockSplitsHelper(seqStoreSplits* splits, size_t startIdx, size_t endIdx,
+ ZSTD_CCtx* zc, const seqStore_t* origSeqStore)
+{
+ seqStore_t* fullSeqStoreChunk = &zc->blockSplitCtx.fullSeqStoreChunk;
+ seqStore_t* firstHalfSeqStore = &zc->blockSplitCtx.firstHalfSeqStore;
+ seqStore_t* secondHalfSeqStore = &zc->blockSplitCtx.secondHalfSeqStore;
size_t estimatedOriginalSize;
size_t estimatedFirstHalfSize;
size_t estimatedSecondHalfSize;
size_t midIdx = (startIdx + endIdx)/2;
- if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= MAX_NB_SPLITS) {
+ if (endIdx - startIdx < MIN_SEQUENCES_BLOCK_SPLITTING || splits->idx >= ZSTD_MAX_NB_BLOCK_SPLITS) {
+ DEBUGLOG(6, "ZSTD_deriveBlockSplitsHelper: Too few sequences");
return;
}
- ZSTD_deriveSeqStoreChunk(&fullSeqStoreChunk, origSeqStore, startIdx, endIdx);
- ZSTD_deriveSeqStoreChunk(&firstHalfSeqStore, origSeqStore, startIdx, midIdx);
- ZSTD_deriveSeqStoreChunk(&secondHalfSeqStore, origSeqStore, midIdx, endIdx);
- estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&fullSeqStoreChunk, zc);
- estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&firstHalfSeqStore, zc);
- estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&secondHalfSeqStore, zc);
- DEBUGLOG(5, "Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu",
+ DEBUGLOG(4, "ZSTD_deriveBlockSplitsHelper: startIdx=%zu endIdx=%zu", startIdx, endIdx);
+ ZSTD_deriveSeqStoreChunk(fullSeqStoreChunk, origSeqStore, startIdx, endIdx);
+ ZSTD_deriveSeqStoreChunk(firstHalfSeqStore, origSeqStore, startIdx, midIdx);
+ ZSTD_deriveSeqStoreChunk(secondHalfSeqStore, origSeqStore, midIdx, endIdx);
+ estimatedOriginalSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(fullSeqStoreChunk, zc);
+ estimatedFirstHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(firstHalfSeqStore, zc);
+ estimatedSecondHalfSize = ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(secondHalfSeqStore, zc);
+ DEBUGLOG(4, "Estimated original block size: %zu -- First half split: %zu -- Second half split: %zu",
estimatedOriginalSize, estimatedFirstHalfSize, estimatedSecondHalfSize);
if (ZSTD_isError(estimatedOriginalSize) || ZSTD_isError(estimatedFirstHalfSize) || ZSTD_isError(estimatedSecondHalfSize)) {
return;
@@ -3596,17 +3640,19 @@ static size_t ZSTD_deriveBlockSplits(ZSTD_CCtx* zc, U32 partitions[], U32 nbSeq)
*
* Returns combined size of all blocks (which includes headers), or a ZSTD error code.
*/
-static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
- const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq) {
+static size_t
+ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, size_t dstCapacity,
+ const void* src, size_t blockSize, U32 lastBlock, U32 nbSeq)
+{
size_t cSize = 0;
const BYTE* ip = (const BYTE*)src;
BYTE* op = (BYTE*)dst;
- U32 partitions[MAX_NB_SPLITS];
size_t i = 0;
size_t srcBytesTotal = 0;
+ U32* partitions = zc->blockSplitCtx.partitions; /* size == ZSTD_MAX_NB_BLOCK_SPLITS */
+ seqStore_t* nextSeqStore = &zc->blockSplitCtx.nextSeqStore;
+ seqStore_t* currSeqStore = &zc->blockSplitCtx.currSeqStore;
size_t numSplits = ZSTD_deriveBlockSplits(zc, partitions, nbSeq);
- seqStore_t nextSeqStore;
- seqStore_t currSeqStore;
/* If a block is split and some partitions are emitted as RLE/uncompressed, then repcode history
* may become invalid. In order to reconcile potentially invalid repcodes, we keep track of two
@@ -3626,6 +3672,7 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
repcodes_t cRep;
ZSTD_memcpy(dRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
ZSTD_memcpy(cRep.rep, zc->blockState.prevCBlock->rep, sizeof(repcodes_t));
+ ZSTD_memset(nextSeqStore, 0, sizeof(seqStore_t));
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock_internal (dstCapacity=%u, dictLimit=%u, nextToUpdate=%u)",
(unsigned)dstCapacity, (unsigned)zc->blockState.matchState.window.dictLimit,
@@ -3643,36 +3690,36 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
return cSizeSingleBlock;
}
- ZSTD_deriveSeqStoreChunk(&currSeqStore, &zc->seqStore, 0, partitions[0]);
+ ZSTD_deriveSeqStoreChunk(currSeqStore, &zc->seqStore, 0, partitions[0]);
for (i = 0; i <= numSplits; ++i) {
size_t srcBytes;
size_t cSizeChunk;
U32 const lastPartition = (i == numSplits);
U32 lastBlockEntireSrc = 0;
- srcBytes = ZSTD_countSeqStoreLiteralsBytes(&currSeqStore) + ZSTD_countSeqStoreMatchBytes(&currSeqStore);
+ srcBytes = ZSTD_countSeqStoreLiteralsBytes(currSeqStore) + ZSTD_countSeqStoreMatchBytes(currSeqStore);
srcBytesTotal += srcBytes;
if (lastPartition) {
/* This is the final partition, need to account for possible last literals */
srcBytes += blockSize - srcBytesTotal;
lastBlockEntireSrc = lastBlock;
} else {
- ZSTD_deriveSeqStoreChunk(&nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]);
+ ZSTD_deriveSeqStoreChunk(nextSeqStore, &zc->seqStore, partitions[i], partitions[i+1]);
}
- cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, &currSeqStore,
+ cSizeChunk = ZSTD_compressSeqStore_singleBlock(zc, currSeqStore,
&dRep, &cRep,
op, dstCapacity,
ip, srcBytes,
lastBlockEntireSrc, 1 /* isPartition */);
- DEBUGLOG(5, "Estimated size: %zu actual size: %zu", ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(&currSeqStore, zc), cSizeChunk);
+ DEBUGLOG(5, "Estimated size: %zu actual size: %zu", ZSTD_buildEntropyStatisticsAndEstimateSubBlockSize(currSeqStore, zc), cSizeChunk);
FORWARD_IF_ERROR(cSizeChunk, "Compressing chunk failed!");
ip += srcBytes;
op += cSizeChunk;
dstCapacity -= cSizeChunk;
cSize += cSizeChunk;
- currSeqStore = nextSeqStore;
+ *currSeqStore = *nextSeqStore;
assert(cSizeChunk <= ZSTD_BLOCKSIZE_MAX + ZSTD_blockHeaderSize);
}
/* cRep and dRep may have diverged during the compression. If so, we use the dRep repcodes
@@ -3682,14 +3729,17 @@ static size_t ZSTD_compressBlock_splitBlock_internal(ZSTD_CCtx* zc, void* dst, s
return cSize;
}
-static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize, U32 lastBlock) {
+static size_t
+ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, U32 lastBlock)
+{
const BYTE* ip = (const BYTE*)src;
BYTE* op = (BYTE*)dst;
U32 nbSeq;
size_t cSize;
DEBUGLOG(4, "ZSTD_compressBlock_splitBlock");
+ assert(zc->appliedParams.useBlockSplitter == ZSTD_ps_enable);
{ const size_t bss = ZSTD_buildSeqStore(zc, src, srcSize);
FORWARD_IF_ERROR(bss, "ZSTD_buildSeqStore failed");
@@ -3704,15 +3754,15 @@ static size_t ZSTD_compressBlock_splitBlock(ZSTD_CCtx* zc,
nbSeq = (U32)(zc->seqStore.sequences - zc->seqStore.sequencesStart);
}
- assert(zc->appliedParams.splitBlocks == 1);
cSize = ZSTD_compressBlock_splitBlock_internal(zc, dst, dstCapacity, src, srcSize, lastBlock, nbSeq);
FORWARD_IF_ERROR(cSize, "Splitting blocks failed!");
return cSize;
}
-static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
- void* dst, size_t dstCapacity,
- const void* src, size_t srcSize, U32 frame)
+static size_t
+ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
+ void* dst, size_t dstCapacity,
+ const void* src, size_t srcSize, U32 frame)
{
/* This the upper bound for the length of an rle block.
* This isn't the actual upper bound. Finding the real threshold
@@ -3746,12 +3796,6 @@ static size_t ZSTD_compressBlock_internal(ZSTD_CCtx* zc,
zc->entropyWorkspace, ENTROPY_WORKSPACE_SIZE /* statically allocated in resetCCtx */,
zc->bmi2);
- if (zc->seqCollector.collectSequences) {
- ZSTD_copyBlockSequences(zc);
- return 0;
- }
-
-
if (frame &&
/* We don't want to emit our first block as a RLE even if it qualifies because
* doing so will cause the decoder (cli only) to throw a "should consume all input error."
@@ -3915,6 +3959,7 @@ static size_t ZSTD_compress_frameChunk(ZSTD_CCtx* cctx,
ZSTD_overflowCorrectIfNeeded(
ms, &cctx->workspace, &cctx->appliedParams, ip, ip + blockSize);
ZSTD_checkDictValidity(&ms->window, ip + blockSize, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
+ ZSTD_window_enforceMaxDist(&ms->window, ip, maxDist, &ms->loadedDictEnd, &ms->dictMatchState);
/* Ensure hash/chain table insertion resumes no sooner than lowlimit */
if (ms->nextToUpdate < ms->window.lowLimit) ms->nextToUpdate = ms->window.lowLimit;
@@ -3991,7 +4036,9 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
if (!singleSegment) op[pos++] = windowLogByte;
switch(dictIDSizeCode)
{
- default: assert(0); /* impossible */
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
case 0 : break;
case 1 : op[pos] = (BYTE)(dictID); pos++; break;
case 2 : MEM_writeLE16(op+pos, (U16)dictID); pos+=2; break;
@@ -3999,7 +4046,9 @@ static size_t ZSTD_writeFrameHeader(void* dst, size_t dstCapacity,
}
switch(fcsCode)
{
- default: assert(0); /* impossible */
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
case 0 : if (singleSegment) op[pos++] = (BYTE)(pledgedSrcSize); break;
case 1 : MEM_writeLE16(op+pos, (U16)(pledgedSrcSize-256)); pos+=2; break;
case 2 : MEM_writeLE32(op+pos, (U32)(pledgedSrcSize)); pos+=4; break;
@@ -4047,7 +4096,7 @@ size_t ZSTD_referenceExternalSequences(ZSTD_CCtx* cctx, rawSeq* seq, size_t nbSe
{
RETURN_ERROR_IF(cctx->stage != ZSTDcs_init, stage_wrong,
"wrong cctx stage");
- RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm,
+ RETURN_ERROR_IF(cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable,
parameter_unsupported,
"incompatible with ldm");
cctx->externSeqStore.seq = seq;
@@ -4088,7 +4137,7 @@ static size_t ZSTD_compressContinue_internal (ZSTD_CCtx* cctx,
ms->forceNonContiguous = 0;
ms->nextToUpdate = ms->window.dictLimit;
}
- if (cctx->appliedParams.ldmParams.enableLdm) {
+ if (cctx->appliedParams.ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_window_update(&cctx->ldmState.window, src, srcSize, /* forceNonContiguous */ 0);
}
@@ -4157,7 +4206,7 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
{
const BYTE* ip = (const BYTE*) src;
const BYTE* const iend = ip + srcSize;
- int const loadLdmDict = params->ldmParams.enableLdm && ls != NULL;
+ int const loadLdmDict = params->ldmParams.enableLdm == ZSTD_ps_enable && ls != NULL;
/* Assert that we the ms params match the params we're being given */
ZSTD_assertEqualCParams(params->cParams, ms->cParams);
@@ -4214,8 +4263,8 @@ static size_t ZSTD_loadDictionaryContent(ZSTD_matchState_t* ms,
assert(ms->chainTable != NULL);
ZSTD_dedicatedDictSearch_lazy_loadDictionary(ms, iend-HASH_READ_SIZE);
} else {
- assert(params->useRowMatchFinder != ZSTD_urm_auto);
- if (params->useRowMatchFinder == ZSTD_urm_enableRowMatchFinder) {
+ assert(params->useRowMatchFinder != ZSTD_ps_auto);
+ if (params->useRowMatchFinder == ZSTD_ps_enable) {
size_t const tagTableSize = ((size_t)1 << params->cParams.hashLog) * sizeof(U16);
ZSTD_memset(ms->tagTable, 0, tagTableSize);
ZSTD_row_update(ms, iend-HASH_READ_SIZE);
@@ -4715,7 +4764,7 @@ size_t ZSTD_estimateCDictSize_advanced(
+ ZSTD_cwksp_alloc_size(HUF_WORKSPACE_SIZE)
/* enableDedicatedDictSearch == 1 ensures that CDict estimation will not be too small
* in case we are using DDS with row-hash. */
- + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams),
+ + ZSTD_sizeof_matchState(&cParams, ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams),
/* enableDedicatedDictSearch */ 1, /* forCCtx */ 0)
+ (dictLoadMethod == ZSTD_dlm_byRef ? 0
: ZSTD_cwksp_alloc_size(ZSTD_cwksp_align(dictSize, sizeof(void *))));
@@ -4792,7 +4841,7 @@ static size_t ZSTD_initCDict_internal(
static ZSTD_CDict* ZSTD_createCDict_advanced_internal(size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_compressionParameters cParams,
- ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ ZSTD_paramSwitch_e useRowMatchFinder,
U32 enableDedicatedDictSearch,
ZSTD_customMem customMem)
{
@@ -4842,7 +4891,7 @@ ZSTD_CDict* ZSTD_createCDict_advanced(const void* dictBuffer, size_t dictSize,
&cctxParams, customMem);
}
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
+ZSTD_CDict* ZSTD_createCDict_advanced2(
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
@@ -4947,7 +4996,7 @@ const ZSTD_CDict* ZSTD_initStaticCDict(
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams)
{
- ZSTD_useRowMatchFinderMode_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_urm_auto, &cParams);
+ ZSTD_paramSwitch_e const useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(ZSTD_ps_auto, &cParams);
/* enableDedicatedDictSearch == 1 ensures matchstate is not too small in case this CDict will be used for DDS + row hash */
size_t const matchStateSize = ZSTD_sizeof_matchState(&cParams, useRowMatchFinder, /* enableDedicatedDictSearch */ 1, /* forCCtx */ 0);
size_t const neededSize = ZSTD_cwksp_alloc_size(sizeof(ZSTD_CDict))
@@ -5403,7 +5452,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream* zcs,
zcs->outBuffFlushedSize = 0;
zcs->streamStage = zcss_flush; /* pass-through to flush stage */
}
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case zcss_flush:
DEBUGLOG(5, "flush stage");
assert(zcs->appliedParams.outBufferMode == ZSTD_bm_buffered);
@@ -5524,17 +5573,8 @@ static size_t ZSTD_CCtx_init_compressStream2(ZSTD_CCtx* cctx,
dictSize, mode);
}
- if (ZSTD_CParams_shouldEnableLdm(&params.cParams)) {
- /* Enable LDM by default for optimal parser and window size >= 128MB */
- DEBUGLOG(4, "LDM enabled by default (window size >= 128MB, strategy >= btopt)");
- params.ldmParams.enableLdm = 1;
- }
-
- if (ZSTD_CParams_useBlockSplitter(&params.cParams)) {
- DEBUGLOG(4, "Block splitter enabled by default (window size >= 128K, strategy >= btopt)");
- params.splitBlocks = 1;
- }
-
+ params.useBlockSplitter = ZSTD_resolveBlockSplitterMode(params.useBlockSplitter, &params.cParams);
+ params.ldmParams.enableLdm = ZSTD_resolveEnableLdm(params.ldmParams.enableLdm, &params.cParams);
params.useRowMatchFinder = ZSTD_resolveRowMatchFinderMode(params.useRowMatchFinder, &params.cParams);
#ifdef ZSTD_MULTITHREAD
@@ -5715,39 +5755,39 @@ typedef struct {
size_t posInSrc; /* Number of bytes given by sequences provided so far */
} ZSTD_sequencePosition;
-/* Returns a ZSTD error code if sequence is not valid */
-static size_t ZSTD_validateSequence(U32 offCode, U32 matchLength,
- size_t posInSrc, U32 windowLog, size_t dictSize, U32 minMatch) {
- size_t offsetBound;
- U32 windowSize = 1 << windowLog;
+/* ZSTD_validateSequence() :
+ * @offCode : is presumed to follow format required by ZSTD_storeSeq()
+ * @returns a ZSTD error code if sequence is not valid
+ */
+static size_t
+ZSTD_validateSequence(U32 offCode, U32 matchLength,
+ size_t posInSrc, U32 windowLog, size_t dictSize)
+{
+ U32 const windowSize = 1 << windowLog;
/* posInSrc represents the amount of data the the decoder would decode up to this point.
* As long as the amount of data decoded is less than or equal to window size, offsets may be
* larger than the total length of output decoded in order to reference the dict, even larger than
* window size. After output surpasses windowSize, we're limited to windowSize offsets again.
*/
- offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
- RETURN_ERROR_IF(offCode > offsetBound + ZSTD_REP_MOVE, corruption_detected, "Offset too large!");
- RETURN_ERROR_IF(matchLength < minMatch, corruption_detected, "Matchlength too small");
+ size_t const offsetBound = posInSrc > windowSize ? (size_t)windowSize : posInSrc + (size_t)dictSize;
+ RETURN_ERROR_IF(offCode > STORE_OFFSET(offsetBound), corruption_detected, "Offset too large!");
+ RETURN_ERROR_IF(matchLength < MINMATCH, corruption_detected, "Matchlength too small");
return 0;
}
/* Returns an offset code, given a sequence's raw offset, the ongoing repcode array, and whether litLength == 0 */
-static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0) {
- U32 offCode = rawOffset + ZSTD_REP_MOVE;
- U32 repCode = 0;
+static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32 ll0)
+{
+ U32 offCode = STORE_OFFSET(rawOffset);
if (!ll0 && rawOffset == rep[0]) {
- repCode = 1;
+ offCode = STORE_REPCODE_1;
} else if (rawOffset == rep[1]) {
- repCode = 2 - ll0;
+ offCode = STORE_REPCODE(2 - ll0);
} else if (rawOffset == rep[2]) {
- repCode = 3 - ll0;
+ offCode = STORE_REPCODE(3 - ll0);
} else if (ll0 && rawOffset == rep[0] - 1) {
- repCode = 3;
- }
- if (repCode) {
- /* ZSTD_storeSeq expects a number in the range [0, 2] to represent a repcode */
- offCode = repCode - 1;
+ offCode = STORE_REPCODE_3;
}
return offCode;
}
@@ -5755,18 +5795,17 @@ static U32 ZSTD_finalizeOffCode(U32 rawOffset, const U32 rep[ZSTD_REP_NUM], U32
/* Returns 0 on success, and a ZSTD_error otherwise. This function scans through an array of
* ZSTD_Sequence, storing the sequences it finds, until it reaches a block delimiter.
*/
-static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
- const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
- const void* src, size_t blockSize) {
+static size_t
+ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx,
+ ZSTD_sequencePosition* seqPos,
+ const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
+ const void* src, size_t blockSize)
+{
U32 idx = seqPos->idx;
BYTE const* ip = (BYTE const*)(src);
const BYTE* const iend = ip + blockSize;
repcodes_t updatedRepcodes;
U32 dictSize;
- U32 litLength;
- U32 matchLength;
- U32 ll0;
- U32 offCode;
if (cctx->cdict) {
dictSize = (U32)cctx->cdict->dictContentSize;
@@ -5777,23 +5816,22 @@ static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZS
}
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
for (; (inSeqs[idx].matchLength != 0 || inSeqs[idx].offset != 0) && idx < inSeqsSize; ++idx) {
- litLength = inSeqs[idx].litLength;
- matchLength = inSeqs[idx].matchLength;
- ll0 = litLength == 0;
- offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
- updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
+ U32 const litLength = inSeqs[idx].litLength;
+ U32 const ll0 = (litLength == 0);
+ U32 const matchLength = inSeqs[idx].matchLength;
+ U32 const offCode = ZSTD_finalizeOffCode(inSeqs[idx].offset, updatedRepcodes.rep, ll0);
+ ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
if (cctx->appliedParams.validateSequences) {
seqPos->posInSrc += litLength + matchLength;
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
- cctx->appliedParams.cParams.windowLog, dictSize,
- cctx->appliedParams.cParams.minMatch),
+ cctx->appliedParams.cParams.windowLog, dictSize),
"Sequence validation failed");
}
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
- ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
+ ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength);
ip += matchLength + litLength;
}
ZSTD_memcpy(cctx->blockState.nextCBlock->rep, updatedRepcodes.rep, sizeof(repcodes_t));
@@ -5820,9 +5858,11 @@ static size_t ZSTD_copySequencesToSeqStoreExplicitBlockDelim(ZSTD_CCtx* cctx, ZS
* avoid splitting a match, or to avoid splitting a match such that it would produce a match
* smaller than MINMATCH. In this case, we return the number of bytes that we didn't read from this block.
*/
-static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
- const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
- const void* src, size_t blockSize) {
+static size_t
+ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
+ const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
+ const void* src, size_t blockSize)
+{
U32 idx = seqPos->idx;
U32 startPosInSequence = seqPos->posInSequence;
U32 endPosInSequence = seqPos->posInSequence + (U32)blockSize;
@@ -5832,10 +5872,6 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
repcodes_t updatedRepcodes;
U32 bytesAdjustment = 0;
U32 finalMatchSplit = 0;
- U32 litLength;
- U32 matchLength;
- U32 rawOffset;
- U32 offCode;
if (cctx->cdict) {
dictSize = cctx->cdict->dictContentSize;
@@ -5849,9 +5885,10 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
ZSTD_memcpy(updatedRepcodes.rep, cctx->blockState.prevCBlock->rep, sizeof(repcodes_t));
while (endPosInSequence && idx < inSeqsSize && !finalMatchSplit) {
const ZSTD_Sequence currSeq = inSeqs[idx];
- litLength = currSeq.litLength;
- matchLength = currSeq.matchLength;
- rawOffset = currSeq.offset;
+ U32 litLength = currSeq.litLength;
+ U32 matchLength = currSeq.matchLength;
+ U32 const rawOffset = currSeq.offset;
+ U32 offCode;
/* Modify the sequence depending on where endPosInSequence lies */
if (endPosInSequence >= currSeq.litLength + currSeq.matchLength) {
@@ -5904,22 +5941,21 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
}
}
/* Check if this offset can be represented with a repcode */
- { U32 ll0 = (litLength == 0);
+ { U32 const ll0 = (litLength == 0);
offCode = ZSTD_finalizeOffCode(rawOffset, updatedRepcodes.rep, ll0);
- updatedRepcodes = ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
+ ZSTD_updateRep(updatedRepcodes.rep, offCode, ll0);
}
if (cctx->appliedParams.validateSequences) {
seqPos->posInSrc += litLength + matchLength;
FORWARD_IF_ERROR(ZSTD_validateSequence(offCode, matchLength, seqPos->posInSrc,
- cctx->appliedParams.cParams.windowLog, dictSize,
- cctx->appliedParams.cParams.minMatch),
+ cctx->appliedParams.cParams.windowLog, dictSize),
"Sequence validation failed");
}
DEBUGLOG(6, "Storing sequence: (of: %u, ml: %u, ll: %u)", offCode, matchLength, litLength);
RETURN_ERROR_IF(idx - seqPos->idx > cctx->seqStore.maxNbSeq, memory_allocation,
"Not enough memory allocated. Try adjusting ZSTD_c_minMatch.");
- ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength - MINMATCH);
+ ZSTD_storeSeq(&cctx->seqStore, litLength, ip, iend, offCode, matchLength);
ip += matchLength + litLength;
}
DEBUGLOG(5, "Ending seq: idx: %u (of: %u ml: %u ll: %u)", idx, inSeqs[idx].offset, inSeqs[idx].matchLength, inSeqs[idx].litLength);
@@ -5944,7 +5980,8 @@ static size_t ZSTD_copySequencesToSeqStoreNoBlockDelim(ZSTD_CCtx* cctx, ZSTD_seq
typedef size_t (*ZSTD_sequenceCopier) (ZSTD_CCtx* cctx, ZSTD_sequencePosition* seqPos,
const ZSTD_Sequence* const inSeqs, size_t inSeqsSize,
const void* src, size_t blockSize);
-static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode) {
+static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode)
+{
ZSTD_sequenceCopier sequenceCopier = NULL;
assert(ZSTD_cParam_withinBounds(ZSTD_c_blockDelimiters, mode));
if (mode == ZSTD_sf_explicitBlockDelimiters) {
@@ -5958,12 +5995,15 @@ static ZSTD_sequenceCopier ZSTD_selectSequenceCopier(ZSTD_sequenceFormat_e mode)
/* Compress, block-by-block, all of the sequences given.
*
- * Returns the cumulative size of all compressed blocks (including their headers), otherwise a ZSTD error.
+ * Returns the cumulative size of all compressed blocks (including their headers),
+ * otherwise a ZSTD error.
*/
-static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
- void* dst, size_t dstCapacity,
- const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
- const void* src, size_t srcSize) {
+static size_t
+ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
+ void* dst, size_t dstCapacity,
+ const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
+ const void* src, size_t srcSize)
+{
size_t cSize = 0;
U32 lastBlock;
size_t blockSize;
@@ -5973,7 +6013,7 @@ static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
BYTE const* ip = (BYTE const*)src;
BYTE* op = (BYTE*)dst;
- ZSTD_sequenceCopier sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
+ ZSTD_sequenceCopier const sequenceCopier = ZSTD_selectSequenceCopier(cctx->appliedParams.blockDelimiters);
DEBUGLOG(4, "ZSTD_compressSequences_internal srcSize: %zu, inSeqsSize: %zu", srcSize, inSeqsSize);
/* Special case: empty frame */
@@ -6073,7 +6113,8 @@ static size_t ZSTD_compressSequences_internal(ZSTD_CCtx* cctx,
size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstCapacity,
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
- const void* src, size_t srcSize) {
+ const void* src, size_t srcSize)
+{
BYTE* op = (BYTE*)dst;
size_t cSize = 0;
size_t compressedBlocksSize = 0;
@@ -6140,119 +6181,12 @@ size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output)
/*-===== Pre-defined compression levels =====-*/
+#include "clevels.h"
-#define ZSTD_MAX_CLEVEL 22
int ZSTD_maxCLevel(void) { return ZSTD_MAX_CLEVEL; }
int ZSTD_minCLevel(void) { return (int)-ZSTD_TARGETLENGTH_MAX; }
int ZSTD_defaultCLevel(void) { return ZSTD_CLEVEL_DEFAULT; }
-static const ZSTD_compressionParameters ZSTD_defaultCParameters[4][ZSTD_MAX_CLEVEL+1] = {
-{ /* "default" - for any srcSize > 256 KB */
- /* W, C, H, S, L, TL, strat */
- { 19, 12, 13, 1, 6, 1, ZSTD_fast }, /* base for negative levels */
- { 19, 13, 14, 1, 7, 0, ZSTD_fast }, /* level 1 */
- { 20, 15, 16, 1, 6, 0, ZSTD_fast }, /* level 2 */
- { 21, 16, 17, 1, 5, 0, ZSTD_dfast }, /* level 3 */
- { 21, 18, 18, 1, 5, 0, ZSTD_dfast }, /* level 4 */
- { 21, 18, 19, 2, 5, 2, ZSTD_greedy }, /* level 5 */
- { 21, 19, 19, 3, 5, 4, ZSTD_greedy }, /* level 6 */
- { 21, 19, 19, 3, 5, 8, ZSTD_lazy }, /* level 7 */
- { 21, 19, 19, 3, 5, 16, ZSTD_lazy2 }, /* level 8 */
- { 21, 19, 20, 4, 5, 16, ZSTD_lazy2 }, /* level 9 */
- { 22, 20, 21, 4, 5, 16, ZSTD_lazy2 }, /* level 10 */
- { 22, 21, 22, 4, 5, 16, ZSTD_lazy2 }, /* level 11 */
- { 22, 21, 22, 5, 5, 16, ZSTD_lazy2 }, /* level 12 */
- { 22, 21, 22, 5, 5, 32, ZSTD_btlazy2 }, /* level 13 */
- { 22, 22, 23, 5, 5, 32, ZSTD_btlazy2 }, /* level 14 */
- { 22, 23, 23, 6, 5, 32, ZSTD_btlazy2 }, /* level 15 */
- { 22, 22, 22, 5, 5, 48, ZSTD_btopt }, /* level 16 */
- { 23, 23, 22, 5, 4, 64, ZSTD_btopt }, /* level 17 */
- { 23, 23, 22, 6, 3, 64, ZSTD_btultra }, /* level 18 */
- { 23, 24, 22, 7, 3,256, ZSTD_btultra2}, /* level 19 */
- { 25, 25, 23, 7, 3,256, ZSTD_btultra2}, /* level 20 */
- { 26, 26, 24, 7, 3,512, ZSTD_btultra2}, /* level 21 */
- { 27, 27, 25, 9, 3,999, ZSTD_btultra2}, /* level 22 */
-},
-{ /* for srcSize <= 256 KB */
- /* W, C, H, S, L, T, strat */
- { 18, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
- { 18, 13, 14, 1, 6, 0, ZSTD_fast }, /* level 1 */
- { 18, 14, 14, 1, 5, 0, ZSTD_dfast }, /* level 2 */
- { 18, 16, 16, 1, 4, 0, ZSTD_dfast }, /* level 3 */
- { 18, 16, 17, 2, 5, 2, ZSTD_greedy }, /* level 4.*/
- { 18, 18, 18, 3, 5, 2, ZSTD_greedy }, /* level 5.*/
- { 18, 18, 19, 3, 5, 4, ZSTD_lazy }, /* level 6.*/
- { 18, 18, 19, 4, 4, 4, ZSTD_lazy }, /* level 7 */
- { 18, 18, 19, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
- { 18, 18, 19, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
- { 18, 18, 19, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
- { 18, 18, 19, 5, 4, 12, ZSTD_btlazy2 }, /* level 11.*/
- { 18, 19, 19, 7, 4, 12, ZSTD_btlazy2 }, /* level 12.*/
- { 18, 18, 19, 4, 4, 16, ZSTD_btopt }, /* level 13 */
- { 18, 18, 19, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
- { 18, 18, 19, 6, 3,128, ZSTD_btopt }, /* level 15.*/
- { 18, 19, 19, 6, 3,128, ZSTD_btultra }, /* level 16.*/
- { 18, 19, 19, 8, 3,256, ZSTD_btultra }, /* level 17.*/
- { 18, 19, 19, 6, 3,128, ZSTD_btultra2}, /* level 18.*/
- { 18, 19, 19, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
- { 18, 19, 19, 10, 3,512, ZSTD_btultra2}, /* level 20.*/
- { 18, 19, 19, 12, 3,512, ZSTD_btultra2}, /* level 21.*/
- { 18, 19, 19, 13, 3,999, ZSTD_btultra2}, /* level 22.*/
-},
-{ /* for srcSize <= 128 KB */
- /* W, C, H, S, L, T, strat */
- { 17, 12, 12, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
- { 17, 12, 13, 1, 6, 0, ZSTD_fast }, /* level 1 */
- { 17, 13, 15, 1, 5, 0, ZSTD_fast }, /* level 2 */
- { 17, 15, 16, 2, 5, 0, ZSTD_dfast }, /* level 3 */
- { 17, 17, 17, 2, 4, 0, ZSTD_dfast }, /* level 4 */
- { 17, 16, 17, 3, 4, 2, ZSTD_greedy }, /* level 5 */
- { 17, 17, 17, 3, 4, 4, ZSTD_lazy }, /* level 6 */
- { 17, 17, 17, 3, 4, 8, ZSTD_lazy2 }, /* level 7 */
- { 17, 17, 17, 4, 4, 8, ZSTD_lazy2 }, /* level 8 */
- { 17, 17, 17, 5, 4, 8, ZSTD_lazy2 }, /* level 9 */
- { 17, 17, 17, 6, 4, 8, ZSTD_lazy2 }, /* level 10 */
- { 17, 17, 17, 5, 4, 8, ZSTD_btlazy2 }, /* level 11 */
- { 17, 18, 17, 7, 4, 12, ZSTD_btlazy2 }, /* level 12 */
- { 17, 18, 17, 3, 4, 12, ZSTD_btopt }, /* level 13.*/
- { 17, 18, 17, 4, 3, 32, ZSTD_btopt }, /* level 14.*/
- { 17, 18, 17, 6, 3,256, ZSTD_btopt }, /* level 15.*/
- { 17, 18, 17, 6, 3,128, ZSTD_btultra }, /* level 16.*/
- { 17, 18, 17, 8, 3,256, ZSTD_btultra }, /* level 17.*/
- { 17, 18, 17, 10, 3,512, ZSTD_btultra }, /* level 18.*/
- { 17, 18, 17, 5, 3,256, ZSTD_btultra2}, /* level 19.*/
- { 17, 18, 17, 7, 3,512, ZSTD_btultra2}, /* level 20.*/
- { 17, 18, 17, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
- { 17, 18, 17, 11, 3,999, ZSTD_btultra2}, /* level 22.*/
-},
-{ /* for srcSize <= 16 KB */
- /* W, C, H, S, L, T, strat */
- { 14, 12, 13, 1, 5, 1, ZSTD_fast }, /* base for negative levels */
- { 14, 14, 15, 1, 5, 0, ZSTD_fast }, /* level 1 */
- { 14, 14, 15, 1, 4, 0, ZSTD_fast }, /* level 2 */
- { 14, 14, 15, 2, 4, 0, ZSTD_dfast }, /* level 3 */
- { 14, 14, 14, 4, 4, 2, ZSTD_greedy }, /* level 4 */
- { 14, 14, 14, 3, 4, 4, ZSTD_lazy }, /* level 5.*/
- { 14, 14, 14, 4, 4, 8, ZSTD_lazy2 }, /* level 6 */
- { 14, 14, 14, 6, 4, 8, ZSTD_lazy2 }, /* level 7 */
- { 14, 14, 14, 8, 4, 8, ZSTD_lazy2 }, /* level 8.*/
- { 14, 15, 14, 5, 4, 8, ZSTD_btlazy2 }, /* level 9.*/
- { 14, 15, 14, 9, 4, 8, ZSTD_btlazy2 }, /* level 10.*/
- { 14, 15, 14, 3, 4, 12, ZSTD_btopt }, /* level 11.*/
- { 14, 15, 14, 4, 3, 24, ZSTD_btopt }, /* level 12.*/
- { 14, 15, 14, 5, 3, 32, ZSTD_btultra }, /* level 13.*/
- { 14, 15, 15, 6, 3, 64, ZSTD_btultra }, /* level 14.*/
- { 14, 15, 15, 7, 3,256, ZSTD_btultra }, /* level 15.*/
- { 14, 15, 15, 5, 3, 48, ZSTD_btultra2}, /* level 16.*/
- { 14, 15, 15, 6, 3,128, ZSTD_btultra2}, /* level 17.*/
- { 14, 15, 15, 7, 3,256, ZSTD_btultra2}, /* level 18.*/
- { 14, 15, 15, 8, 3,256, ZSTD_btultra2}, /* level 19.*/
- { 14, 15, 15, 8, 3,512, ZSTD_btultra2}, /* level 20.*/
- { 14, 15, 15, 9, 3,512, ZSTD_btultra2}, /* level 21.*/
- { 14, 15, 15, 10, 3,999, ZSTD_btultra2}, /* level 22.*/
-},
-};
-
static ZSTD_compressionParameters ZSTD_dedicatedDictSearch_getCParams(int const compressionLevel, size_t const dictSize)
{
ZSTD_compressionParameters cParams = ZSTD_getCParams_internal(compressionLevel, 0, dictSize, ZSTD_cpm_createCDict);
diff --git a/thirdparty/zstd/compress/zstd_compress_internal.h b/thirdparty/zstd/compress/zstd_compress_internal.h
index 3b04fd09f6..c406e794bd 100644
--- a/thirdparty/zstd/compress/zstd_compress_internal.h
+++ b/thirdparty/zstd/compress/zstd_compress_internal.h
@@ -63,7 +63,7 @@ typedef struct {
} ZSTD_localDict;
typedef struct {
- HUF_CElt CTable[HUF_CTABLE_SIZE_U32(255)];
+ HUF_CElt CTable[HUF_CTABLE_SIZE_ST(255)];
HUF_repeat repeatMode;
} ZSTD_hufCTables_t;
@@ -129,7 +129,7 @@ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
*********************************/
typedef struct {
- U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
+ U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */
U32 len; /* Raw length of match */
} ZSTD_match_t;
@@ -179,7 +179,7 @@ typedef struct {
U32 offCodeSumBasePrice; /* to compare to log2(offreq) */
ZSTD_OptPrice_e priceType; /* prices can be determined dynamically, or follow a pre-defined cost structure */
const ZSTD_entropyCTables_t* symbolCosts; /* pre-calculated dictionary statistics */
- ZSTD_literalCompressionMode_e literalCompressionMode;
+ ZSTD_paramSwitch_e literalCompressionMode;
} optState_t;
typedef struct {
@@ -199,6 +199,8 @@ typedef struct {
*/
} ZSTD_window_t;
+#define ZSTD_WINDOW_START_INDEX 2
+
typedef struct ZSTD_matchState_t ZSTD_matchState_t;
#define ZSTD_ROW_HASH_CACHE_SIZE 8 /* Size of prefetching hash cache for row-based matchfinder */
@@ -264,7 +266,7 @@ typedef struct {
} ldmState_t;
typedef struct {
- U32 enableLdm; /* 1 if enable long distance matching */
+ ZSTD_paramSwitch_e enableLdm; /* ZSTD_ps_enable to enable LDM. ZSTD_ps_auto by default */
U32 hashLog; /* Log size of hashTable */
U32 bucketSizeLog; /* Log bucket size for collision resolution, at most 8 */
U32 minMatchLength; /* Minimum match length */
@@ -295,7 +297,7 @@ struct ZSTD_CCtx_params_s {
* There is no guarantee that hint is close to actual source size */
ZSTD_dictAttachPref_e attachDictPref;
- ZSTD_literalCompressionMode_e literalCompressionMode;
+ ZSTD_paramSwitch_e literalCompressionMode;
/* Multithreading: used to pass parameters to mtctx */
int nbWorkers;
@@ -318,10 +320,10 @@ struct ZSTD_CCtx_params_s {
int validateSequences;
/* Block splitting */
- int splitBlocks;
+ ZSTD_paramSwitch_e useBlockSplitter;
/* Param for deciding whether to use row-based matchfinder */
- ZSTD_useRowMatchFinderMode_e useRowMatchFinder;
+ ZSTD_paramSwitch_e useRowMatchFinder;
/* Always load a dictionary in ext-dict mode (not prefix mode)? */
int deterministicRefPrefix;
@@ -343,6 +345,22 @@ typedef enum {
ZSTDb_buffered
} ZSTD_buffered_policy_e;
+/**
+ * Struct that contains all elements of block splitter that should be allocated
+ * in a wksp.
+ */
+#define ZSTD_MAX_NB_BLOCK_SPLITS 196
+typedef struct {
+ seqStore_t fullSeqStoreChunk;
+ seqStore_t firstHalfSeqStore;
+ seqStore_t secondHalfSeqStore;
+ seqStore_t currSeqStore;
+ seqStore_t nextSeqStore;
+
+ U32 partitions[ZSTD_MAX_NB_BLOCK_SPLITS];
+ ZSTD_entropyCTablesMetadata_t entropyMetadata;
+} ZSTD_blockSplitCtx;
+
struct ZSTD_CCtx_s {
ZSTD_compressionStage_e stage;
int cParamsChanged; /* == 1 if cParams(except wlog) or compression level are changed in requestedParams. Triggers transmission of new params to ZSTDMT (if available) then reset to 0. */
@@ -374,7 +392,7 @@ struct ZSTD_CCtx_s {
ZSTD_blockState_t blockState;
U32* entropyWorkspace; /* entropy workspace of ENTROPY_WORKSPACE_SIZE bytes */
- /* Wether we are streaming or not */
+ /* Whether we are streaming or not */
ZSTD_buffered_policy_e bufferedPolicy;
/* streaming */
@@ -408,6 +426,9 @@ struct ZSTD_CCtx_s {
#if ZSTD_TRACE
ZSTD_TraceCtx traceCtx;
#endif
+
+ /* Workspace for block splitter */
+ ZSTD_blockSplitCtx blockSplitCtx;
};
typedef enum { ZSTD_dtlm_fast, ZSTD_dtlm_full } ZSTD_dictTableLoadMethod_e;
@@ -442,7 +463,7 @@ typedef enum {
typedef size_t (*ZSTD_blockCompressor) (
ZSTD_matchState_t* bs, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize);
-ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_useRowMatchFinderMode_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
+ZSTD_blockCompressor ZSTD_selectBlockCompressor(ZSTD_strategy strat, ZSTD_paramSwitch_e rowMatchfinderMode, ZSTD_dictMode_e dictMode);
MEM_STATIC U32 ZSTD_LLcode(U32 litLength)
@@ -476,31 +497,6 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
}
-typedef struct repcodes_s {
- U32 rep[3];
-} repcodes_t;
-
-MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
-{
- repcodes_t newReps;
- if (offset >= ZSTD_REP_NUM) { /* full offset */
- newReps.rep[2] = rep[1];
- newReps.rep[1] = rep[0];
- newReps.rep[0] = offset - ZSTD_REP_MOVE;
- } else { /* repcode */
- U32 const repCode = offset + ll0;
- if (repCode > 0) { /* note : if repCode==0, no change */
- U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
- newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
- newReps.rep[1] = rep[0];
- newReps.rep[0] = currentOffset;
- } else { /* repCode == 0 */
- ZSTD_memcpy(&newReps, rep, sizeof(newReps));
- }
- }
- return newReps;
-}
-
/* ZSTD_cParam_withinBounds:
* @return 1 if value is within cParam bounds,
* 0 otherwise */
@@ -549,17 +545,17 @@ MEM_STATIC size_t ZSTD_minGain(size_t srcSize, ZSTD_strategy strat)
return (srcSize >> minlog) + 2;
}
-MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParams)
+MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxParams)
{
switch (cctxParams->literalCompressionMode) {
- case ZSTD_lcm_huffman:
+ case ZSTD_ps_enable:
return 0;
- case ZSTD_lcm_uncompressed:
+ case ZSTD_ps_disable:
return 1;
default:
assert(0 /* impossible: pre-validated */);
- /* fall-through */
- case ZSTD_lcm_auto:
+ ZSTD_FALLTHROUGH;
+ case ZSTD_ps_auto:
return (cctxParams->cParams.strategy == ZSTD_fast) && (cctxParams->cParams.targetLength > 0);
}
}
@@ -569,7 +565,9 @@ MEM_STATIC int ZSTD_disableLiteralsCompression(const ZSTD_CCtx_params* cctxParam
* Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
* large copies.
*/
-static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) {
+static void
+ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)
+{
assert(iend > ilimit_w);
if (ip <= ilimit_w) {
ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
@@ -579,14 +577,30 @@ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const ie
while (ip < iend) *op++ = *ip++;
}
+#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
+#define STORE_REPCODE_1 STORE_REPCODE(1)
+#define STORE_REPCODE_2 STORE_REPCODE(2)
+#define STORE_REPCODE_3 STORE_REPCODE(3)
+#define STORE_REPCODE(r) (assert((r)>=1), assert((r)<=3), (r)-1)
+#define STORE_OFFSET(o) (assert((o)>0), o + ZSTD_REP_MOVE)
+#define STORED_IS_OFFSET(o) ((o) > ZSTD_REP_MOVE)
+#define STORED_IS_REPCODE(o) ((o) <= ZSTD_REP_MOVE)
+#define STORED_OFFSET(o) (assert(STORED_IS_OFFSET(o)), (o)-ZSTD_REP_MOVE)
+#define STORED_REPCODE(o) (assert(STORED_IS_REPCODE(o)), (o)+1) /* returns ID 1,2,3 */
+#define STORED_TO_OFFBASE(o) ((o)+1)
+#define OFFBASE_TO_STORED(o) ((o)-1)
+
/*! ZSTD_storeSeq() :
- * Store a sequence (litlen, litPtr, offCode and mlBase) into seqStore_t.
- * `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes).
- * `mlBase` : matchLength - MINMATCH
+ * Store a sequence (litlen, litPtr, offCode and matchLength) into seqStore_t.
+ * @offBase_minus1 : Users should use employ macros STORE_REPCODE_X and STORE_OFFSET().
+ * @matchLength : must be >= MINMATCH
* Allowed to overread literals up to litLimit.
*/
-HINT_INLINE UNUSED_ATTR
-void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t mlBase)
+HINT_INLINE UNUSED_ATTR void
+ZSTD_storeSeq(seqStore_t* seqStorePtr,
+ size_t litLength, const BYTE* literals, const BYTE* litLimit,
+ U32 offBase_minus1,
+ size_t matchLength)
{
BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
BYTE const* const litEnd = literals + litLength;
@@ -595,7 +609,7 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
- pos, (U32)litLength, (U32)mlBase+MINMATCH, (U32)offCode);
+ pos, (U32)litLength, (U32)matchLength, (U32)offBase_minus1);
}
#endif
assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
@@ -626,19 +640,59 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
seqStorePtr->sequences[0].litLength = (U16)litLength;
/* match offset */
- seqStorePtr->sequences[0].offset = offCode + 1;
+ seqStorePtr->sequences[0].offBase = STORED_TO_OFFBASE(offBase_minus1);
/* match Length */
- if (mlBase>0xFFFF) {
- assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
- seqStorePtr->longLengthType = ZSTD_llt_matchLength;
- seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
+ assert(matchLength >= MINMATCH);
+ { size_t const mlBase = matchLength - MINMATCH;
+ if (mlBase>0xFFFF) {
+ assert(seqStorePtr->longLengthType == ZSTD_llt_none); /* there can only be a single long length */
+ seqStorePtr->longLengthType = ZSTD_llt_matchLength;
+ seqStorePtr->longLengthPos = (U32)(seqStorePtr->sequences - seqStorePtr->sequencesStart);
+ }
+ seqStorePtr->sequences[0].mlBase = (U16)mlBase;
}
- seqStorePtr->sequences[0].matchLength = (U16)mlBase;
seqStorePtr->sequences++;
}
+/* ZSTD_updateRep() :
+ * updates in-place @rep (array of repeat offsets)
+ * @offBase_minus1 : sum-type, with same numeric representation as ZSTD_storeSeq()
+ */
+MEM_STATIC void
+ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
+{
+ if (STORED_IS_OFFSET(offBase_minus1)) { /* full offset */
+ rep[2] = rep[1];
+ rep[1] = rep[0];
+ rep[0] = STORED_OFFSET(offBase_minus1);
+ } else { /* repcode */
+ U32 const repCode = STORED_REPCODE(offBase_minus1) - 1 + ll0;
+ if (repCode > 0) { /* note : if repCode==0, no change */
+ U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
+ rep[2] = (repCode >= 2) ? rep[1] : rep[2];
+ rep[1] = rep[0];
+ rep[0] = currentOffset;
+ } else { /* repCode == 0 */
+ /* nothing to do */
+ }
+ }
+}
+
+typedef struct repcodes_s {
+ U32 rep[3];
+} repcodes_t;
+
+MEM_STATIC repcodes_t
+ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
+{
+ repcodes_t newReps;
+ ZSTD_memcpy(&newReps, rep, sizeof(newReps));
+ ZSTD_updateRep(newReps.rep, offBase_minus1, ll0);
+ return newReps;
+}
+
/*-*************************************
* Match length counter
@@ -651,8 +705,14 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
# if STATIC_BMI2
return _tzcnt_u64(val) >> 3;
# else
- unsigned long r = 0;
- return _BitScanForward64( &r, (U64)val ) ? (unsigned)(r >> 3) : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward64(&r, (U64)val);
+ return (unsigned)(r >> 3);
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# endif
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_ctzll((U64)val) >> 3);
@@ -669,8 +729,14 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
# endif
} else { /* 32 bits */
# if defined(_MSC_VER)
- unsigned long r=0;
- return _BitScanForward( &r, (U32)val ) ? (unsigned)(r >> 3) : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward(&r, (U32)val);
+ return (unsigned)(r >> 3);
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return (__builtin_ctz((U32)val) >> 3);
# else
@@ -687,8 +753,14 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
# if STATIC_BMI2
return _lzcnt_u64(val) >> 3;
# else
- unsigned long r = 0;
- return _BitScanReverse64(&r, (U64)val) ? (unsigned)(r >> 3) : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanReverse64(&r, (U64)val);
+ return (unsigned)(r >> 3);
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# endif
# elif defined(__GNUC__) && (__GNUC__ >= 4)
return (__builtin_clzll(val) >> 3);
@@ -702,8 +774,14 @@ static unsigned ZSTD_NbCommonBytes (size_t val)
# endif
} else { /* 32 bits */
# if defined(_MSC_VER)
- unsigned long r = 0;
- return _BitScanReverse( &r, (unsigned long)val ) ? (unsigned)(r >> 3) : 0;
+ if (val != 0) {
+ unsigned long r;
+ _BitScanReverse(&r, (unsigned long)val);
+ return (unsigned)(r >> 3);
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
# elif defined(__GNUC__) && (__GNUC__ >= 3)
return (__builtin_clz((U32)val) >> 3);
# else
@@ -884,9 +962,9 @@ MEM_STATIC void ZSTD_window_clear(ZSTD_window_t* window)
MEM_STATIC U32 ZSTD_window_isEmpty(ZSTD_window_t const window)
{
- return window.dictLimit == 1 &&
- window.lowLimit == 1 &&
- (window.nextSrc - window.base) == 1;
+ return window.dictLimit == ZSTD_WINDOW_START_INDEX &&
+ window.lowLimit == ZSTD_WINDOW_START_INDEX &&
+ (window.nextSrc - window.base) == ZSTD_WINDOW_START_INDEX;
}
/**
@@ -937,7 +1015,9 @@ MEM_STATIC U32 ZSTD_window_canOverflowCorrect(ZSTD_window_t const window,
{
U32 const cycleSize = 1u << cycleLog;
U32 const curr = (U32)((BYTE const*)src - window.base);
- U32 const minIndexToOverflowCorrect = cycleSize + MAX(maxDist, cycleSize);
+ U32 const minIndexToOverflowCorrect = cycleSize
+ + MAX(maxDist, cycleSize)
+ + ZSTD_WINDOW_START_INDEX;
/* Adjust the min index to backoff the overflow correction frequency,
* so we don't waste too much CPU in overflow correction. If this
@@ -1012,10 +1092,14 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
U32 const cycleSize = 1u << cycleLog;
U32 const cycleMask = cycleSize - 1;
U32 const curr = (U32)((BYTE const*)src - window->base);
- U32 const currentCycle0 = curr & cycleMask;
- /* Exclude zero so that newCurrent - maxDist >= 1. */
- U32 const currentCycle1 = currentCycle0 == 0 ? cycleSize : currentCycle0;
- U32 const newCurrent = currentCycle1 + MAX(maxDist, cycleSize);
+ U32 const currentCycle = curr & cycleMask;
+ /* Ensure newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX. */
+ U32 const currentCycleCorrection = currentCycle < ZSTD_WINDOW_START_INDEX
+ ? MAX(cycleSize, ZSTD_WINDOW_START_INDEX)
+ : 0;
+ U32 const newCurrent = currentCycle
+ + currentCycleCorrection
+ + MAX(maxDist, cycleSize);
U32 const correction = curr - newCurrent;
/* maxDist must be a power of two so that:
* (newCurrent & cycleMask) == (curr & cycleMask)
@@ -1031,14 +1115,20 @@ MEM_STATIC U32 ZSTD_window_correctOverflow(ZSTD_window_t* window, U32 cycleLog,
window->base += correction;
window->dictBase += correction;
- if (window->lowLimit <= correction) window->lowLimit = 1;
- else window->lowLimit -= correction;
- if (window->dictLimit <= correction) window->dictLimit = 1;
- else window->dictLimit -= correction;
+ if (window->lowLimit < correction + ZSTD_WINDOW_START_INDEX) {
+ window->lowLimit = ZSTD_WINDOW_START_INDEX;
+ } else {
+ window->lowLimit -= correction;
+ }
+ if (window->dictLimit < correction + ZSTD_WINDOW_START_INDEX) {
+ window->dictLimit = ZSTD_WINDOW_START_INDEX;
+ } else {
+ window->dictLimit -= correction;
+ }
/* Ensure we can still reference the full window. */
assert(newCurrent >= maxDist);
- assert(newCurrent - maxDist >= 1);
+ assert(newCurrent - maxDist >= ZSTD_WINDOW_START_INDEX);
/* Ensure that lowLimit and dictLimit didn't underflow. */
assert(window->lowLimit <= newCurrent);
assert(window->dictLimit <= newCurrent);
@@ -1149,11 +1239,12 @@ ZSTD_checkDictValidity(const ZSTD_window_t* window,
MEM_STATIC void ZSTD_window_init(ZSTD_window_t* window) {
ZSTD_memset(window, 0, sizeof(*window));
- window->base = (BYTE const*)"";
- window->dictBase = (BYTE const*)"";
- window->dictLimit = 1; /* start from 1, so that 1st position is valid */
- window->lowLimit = 1; /* it ensures first and later CCtx usages compress the same */
- window->nextSrc = window->base + 1; /* see issue #1241 */
+ window->base = (BYTE const*)" ";
+ window->dictBase = (BYTE const*)" ";
+ ZSTD_STATIC_ASSERT(ZSTD_DUBT_UNSORTED_MARK < ZSTD_WINDOW_START_INDEX); /* Start above ZSTD_DUBT_UNSORTED_MARK */
+ window->dictLimit = ZSTD_WINDOW_START_INDEX; /* start from >0, so that 1st position is valid */
+ window->lowLimit = ZSTD_WINDOW_START_INDEX; /* it ensures first and later CCtx usages compress the same */
+ window->nextSrc = window->base + ZSTD_WINDOW_START_INDEX; /* see issue #1241 */
window->nbOverflowCorrections = 0;
}
@@ -1206,15 +1297,15 @@ MEM_STATIC U32 ZSTD_window_update(ZSTD_window_t* window,
*/
MEM_STATIC U32 ZSTD_getLowestMatchIndex(const ZSTD_matchState_t* ms, U32 curr, unsigned windowLog)
{
- U32 const maxDistance = 1U << windowLog;
- U32 const lowestValid = ms->window.lowLimit;
- U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
- U32 const isDictionary = (ms->loadedDictEnd != 0);
+ U32 const maxDistance = 1U << windowLog;
+ U32 const lowestValid = ms->window.lowLimit;
+ U32 const withinWindow = (curr - lowestValid > maxDistance) ? curr - maxDistance : lowestValid;
+ U32 const isDictionary = (ms->loadedDictEnd != 0);
/* When using a dictionary the entire dictionary is valid if a single byte of the dictionary
* is within the window. We invalidate the dictionary (and set loadedDictEnd to 0) when it isn't
* valid for the entire block. So this check is sufficient to find the lowest valid match index.
*/
- U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
+ U32 const matchLowest = isDictionary ? lowestValid : withinWindow;
return matchLowest;
}
diff --git a/thirdparty/zstd/compress/zstd_compress_literals.c b/thirdparty/zstd/compress/zstd_compress_literals.c
index 008337bb1b..52b0a8059a 100644
--- a/thirdparty/zstd/compress/zstd_compress_literals.c
+++ b/thirdparty/zstd/compress/zstd_compress_literals.c
@@ -73,7 +73,8 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
void* entropyWorkspace, size_t entropyWorkspaceSize,
- const int bmi2)
+ const int bmi2,
+ unsigned suspectUncompressible)
{
size_t const minGain = ZSTD_minGain(srcSize, strategy);
size_t const lhSize = 3 + (srcSize >= 1 KB) + (srcSize >= 16 KB);
@@ -105,11 +106,11 @@ size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
HUF_compress1X_repeat(
ostart+lhSize, dstCapacity-lhSize, src, srcSize,
HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize,
- (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2) :
+ (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2, suspectUncompressible) :
HUF_compress4X_repeat(
ostart+lhSize, dstCapacity-lhSize, src, srcSize,
HUF_SYMBOLVALUE_MAX, HUF_TABLELOG_DEFAULT, entropyWorkspace, entropyWorkspaceSize,
- (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2);
+ (HUF_CElt*)nextHuf->CTable, &repeat, preferRepeat, bmi2, suspectUncompressible);
if (repeat != HUF_repeat_none) {
/* reused the existing table */
DEBUGLOG(5, "Reusing previous huffman table");
diff --git a/thirdparty/zstd/compress/zstd_compress_literals.h b/thirdparty/zstd/compress/zstd_compress_literals.h
index 9904c0cd30..9775fb97cb 100644
--- a/thirdparty/zstd/compress/zstd_compress_literals.h
+++ b/thirdparty/zstd/compress/zstd_compress_literals.h
@@ -18,12 +18,14 @@ size_t ZSTD_noCompressLiterals (void* dst, size_t dstCapacity, const void* src,
size_t ZSTD_compressRleLiteralsBlock (void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+/* If suspectUncompressible then some sampling checks will be run to potentially skip huffman coding */
size_t ZSTD_compressLiterals (ZSTD_hufCTables_t const* prevHuf,
ZSTD_hufCTables_t* nextHuf,
ZSTD_strategy strategy, int disableLiteralCompression,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
void* entropyWorkspace, size_t entropyWorkspaceSize,
- const int bmi2);
+ const int bmi2,
+ unsigned suspectUncompressible);
#endif /* ZSTD_COMPRESS_LITERALS_H */
diff --git a/thirdparty/zstd/compress/zstd_compress_sequences.c b/thirdparty/zstd/compress/zstd_compress_sequences.c
index 611eabdcbb..f1e40af2ea 100644
--- a/thirdparty/zstd/compress/zstd_compress_sequences.c
+++ b/thirdparty/zstd/compress/zstd_compress_sequences.c
@@ -275,10 +275,11 @@ ZSTD_buildCTable(void* dst, size_t dstCapacity,
assert(nbSeq_1 > 1);
assert(entropyWorkspaceSize >= sizeof(ZSTD_BuildCTableWksp));
(void)entropyWorkspaceSize;
- FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "");
- { size_t const NCountSize = FSE_writeNCount(op, oend - op, wksp->norm, max, tableLog); /* overflow protected */
+ FORWARD_IF_ERROR(FSE_normalizeCount(wksp->norm, tableLog, count, nbSeq_1, max, ZSTD_useLowProbCount(nbSeq_1)), "FSE_normalizeCount failed");
+ assert(oend >= op);
+ { size_t const NCountSize = FSE_writeNCount(op, (size_t)(oend - op), wksp->norm, max, tableLog); /* overflow protected */
FORWARD_IF_ERROR(NCountSize, "FSE_writeNCount failed");
- FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), "");
+ FORWARD_IF_ERROR(FSE_buildCTable_wksp(nextCTable, wksp->norm, max, tableLog, wksp->wksp, sizeof(wksp->wksp)), "FSE_buildCTable_wksp failed");
return NCountSize;
}
}
@@ -312,19 +313,19 @@ ZSTD_encodeSequences_body(
FSE_initCState2(&stateLitLength, CTable_LitLength, llCodeTable[nbSeq-1]);
BIT_addBits(&blockStream, sequences[nbSeq-1].litLength, LL_bits[llCodeTable[nbSeq-1]]);
if (MEM_32bits()) BIT_flushBits(&blockStream);
- BIT_addBits(&blockStream, sequences[nbSeq-1].matchLength, ML_bits[mlCodeTable[nbSeq-1]]);
+ BIT_addBits(&blockStream, sequences[nbSeq-1].mlBase, ML_bits[mlCodeTable[nbSeq-1]]);
if (MEM_32bits()) BIT_flushBits(&blockStream);
if (longOffsets) {
U32 const ofBits = ofCodeTable[nbSeq-1];
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
if (extraBits) {
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits);
BIT_flushBits(&blockStream);
}
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits,
ofBits - extraBits);
} else {
- BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
+ BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);
}
BIT_flushBits(&blockStream);
@@ -338,8 +339,8 @@ ZSTD_encodeSequences_body(
U32 const mlBits = ML_bits[mlCode];
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
(unsigned)sequences[n].litLength,
- (unsigned)sequences[n].matchLength + MINMATCH,
- (unsigned)sequences[n].offset);
+ (unsigned)sequences[n].mlBase + MINMATCH,
+ (unsigned)sequences[n].offBase);
/* 32b*/ /* 64b*/
/* (7)*/ /* (7)*/
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
@@ -350,18 +351,18 @@ ZSTD_encodeSequences_body(
BIT_flushBits(&blockStream); /* (7)*/
BIT_addBits(&blockStream, sequences[n].litLength, llBits);
if (MEM_32bits() && ((llBits+mlBits)>24)) BIT_flushBits(&blockStream);
- BIT_addBits(&blockStream, sequences[n].matchLength, mlBits);
+ BIT_addBits(&blockStream, sequences[n].mlBase, mlBits);
if (MEM_32bits() || (ofBits+mlBits+llBits > 56)) BIT_flushBits(&blockStream);
if (longOffsets) {
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
if (extraBits) {
- BIT_addBits(&blockStream, sequences[n].offset, extraBits);
+ BIT_addBits(&blockStream, sequences[n].offBase, extraBits);
BIT_flushBits(&blockStream); /* (7)*/
}
- BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
+ BIT_addBits(&blockStream, sequences[n].offBase >> extraBits,
ofBits - extraBits); /* 31 */
} else {
- BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
+ BIT_addBits(&blockStream, sequences[n].offBase, ofBits); /* 31 */
}
BIT_flushBits(&blockStream); /* (7)*/
DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));
@@ -398,7 +399,7 @@ ZSTD_encodeSequences_default(
#if DYNAMIC_BMI2
-static TARGET_ATTRIBUTE("bmi2") size_t
+static BMI2_TARGET_ATTRIBUTE size_t
ZSTD_encodeSequences_bmi2(
void* dst, size_t dstCapacity,
FSE_CTable const* CTable_MatchLength, BYTE const* mlCodeTable,
diff --git a/thirdparty/zstd/compress/zstd_compress_superblock.c b/thirdparty/zstd/compress/zstd_compress_superblock.c
index e4e45069bc..10e3378577 100644
--- a/thirdparty/zstd/compress/zstd_compress_superblock.c
+++ b/thirdparty/zstd/compress/zstd_compress_superblock.c
@@ -132,6 +132,7 @@ static size_t ZSTD_seqDecompressedSize(seqStore_t const* seqStore, const seqDef*
const seqDef* sp = sstart;
size_t matchLengthSum = 0;
size_t litLengthSum = 0;
+ (void)(litLengthSum); /* suppress unused variable warning on some environments */
while (send-sp > 0) {
ZSTD_sequenceLength const seqLen = ZSTD_getSequenceLength(seqStore, sp);
litLengthSum += seqLen.litLength;
@@ -324,7 +325,7 @@ static size_t ZSTD_estimateSubBlockSize_literal(const BYTE* literals, size_t lit
static size_t ZSTD_estimateSubBlockSize_symbolType(symbolEncodingType_e type,
const BYTE* codeTable, unsigned maxCode,
size_t nbSeq, const FSE_CTable* fseCTable,
- const U32* additionalBits,
+ const U8* additionalBits,
short const* defaultNorm, U32 defaultNormLog, U32 defaultMax,
void* workspace, size_t wkspSize)
{
@@ -474,7 +475,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
/* I think there is an optimization opportunity here.
* Calling ZSTD_estimateSubBlockSize for every sequence can be wasteful
* since it recalculates estimate from scratch.
- * For example, it would recount literal distribution and symbol codes everytime.
+ * For example, it would recount literal distribution and symbol codes every time.
*/
cBlockSizeEstimate = ZSTD_estimateSubBlockSize(lp, litSize, ofCodePtr, llCodePtr, mlCodePtr, seqCount,
&nextCBlock->entropy, entropyMetadata,
@@ -538,7 +539,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
repcodes_t rep;
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
for (seq = sstart; seq < sp; ++seq) {
- rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
+ ZSTD_updateRep(rep.rep, seq->offBase - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
}
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
}
diff --git a/thirdparty/zstd/compress/zstd_cwksp.h b/thirdparty/zstd/compress/zstd_cwksp.h
index 2656d26ca2..dc3f40c80c 100644
--- a/thirdparty/zstd/compress/zstd_cwksp.h
+++ b/thirdparty/zstd/compress/zstd_cwksp.h
@@ -219,7 +219,7 @@ MEM_STATIC size_t ZSTD_cwksp_aligned_alloc_size(size_t size) {
MEM_STATIC size_t ZSTD_cwksp_slack_space_required(void) {
/* For alignment, the wksp will always allocate an additional n_1=[1, 64] bytes
* to align the beginning of tables section, as well as another n_2=[0, 63] bytes
- * to align the beginning of the aligned secion.
+ * to align the beginning of the aligned section.
*
* n_1 + n_2 == 64 bytes if the cwksp is freshly allocated, due to tables and
* aligneds being sized in multiples of 64 bytes.
@@ -243,12 +243,14 @@ MEM_STATIC size_t ZSTD_cwksp_bytes_to_align_ptr(void* ptr, const size_t alignByt
/**
* Internal function. Do not use directly.
- * Reserves the given number of bytes within the aligned/buffer segment of the wksp, which
- * counts from the end of the wksp. (as opposed to the object/table segment)
+ * Reserves the given number of bytes within the aligned/buffer segment of the wksp,
+ * which counts from the end of the wksp (as opposed to the object/table segment).
*
* Returns a pointer to the beginning of that space.
*/
-MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes) {
+MEM_STATIC void*
+ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t const bytes)
+{
void* const alloc = (BYTE*)ws->allocStart - bytes;
void* const bottom = ws->tableEnd;
DEBUGLOG(5, "cwksp: reserving %p %zd bytes, %zd bytes remaining",
@@ -260,6 +262,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t
ws->allocFailed = 1;
return NULL;
}
+ /* the area is reserved from the end of wksp.
+ * If it overlaps with tableValidEnd, it voids guarantees on values' range */
if (alloc < ws->tableValidEnd) {
ws->tableValidEnd = alloc;
}
@@ -269,10 +273,12 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal_buffer_space(ZSTD_cwksp* ws, size_t
/**
* Moves the cwksp to the next phase, and does any necessary allocations.
+ * cwksp initialization must necessarily go through each phase in order.
* Returns a 0 on success, or zstd error
*/
-MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
- ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase) {
+MEM_STATIC size_t
+ZSTD_cwksp_internal_advance_phase(ZSTD_cwksp* ws, ZSTD_cwksp_alloc_phase_e phase)
+{
assert(phase >= ws->phase);
if (phase > ws->phase) {
/* Going from allocating objects to allocating buffers */
@@ -295,15 +301,15 @@ MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
{ /* Align the start of the tables to 64 bytes. Use [0, 63] bytes */
void* const alloc = ws->objectEnd;
size_t const bytesToAlign = ZSTD_cwksp_bytes_to_align_ptr(alloc, ZSTD_CWKSP_ALIGNMENT_BYTES);
- void* const end = (BYTE*)alloc + bytesToAlign;
+ void* const objectEnd = (BYTE*)alloc + bytesToAlign;
DEBUGLOG(5, "reserving table alignment addtl space: %zu", bytesToAlign);
- RETURN_ERROR_IF(end > ws->workspaceEnd, memory_allocation,
+ RETURN_ERROR_IF(objectEnd > ws->workspaceEnd, memory_allocation,
"table phase - alignment initial allocation failed!");
- ws->objectEnd = end;
- ws->tableEnd = end;
- ws->tableValidEnd = end;
- }
- }
+ ws->objectEnd = objectEnd;
+ ws->tableEnd = objectEnd; /* table area starts being empty */
+ if (ws->tableValidEnd < ws->tableEnd) {
+ ws->tableValidEnd = ws->tableEnd;
+ } } }
ws->phase = phase;
ZSTD_cwksp_assert_internal_consistency(ws);
}
@@ -313,15 +319,17 @@ MEM_STATIC size_t ZSTD_cwksp_internal_advance_phase(
/**
* Returns whether this object/buffer/etc was allocated in this workspace.
*/
-MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr) {
+MEM_STATIC int ZSTD_cwksp_owns_buffer(const ZSTD_cwksp* ws, const void* ptr)
+{
return (ptr != NULL) && (ws->workspace <= ptr) && (ptr <= ws->workspaceEnd);
}
/**
* Internal function. Do not use directly.
*/
-MEM_STATIC void* ZSTD_cwksp_reserve_internal(
- ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase) {
+MEM_STATIC void*
+ZSTD_cwksp_reserve_internal(ZSTD_cwksp* ws, size_t bytes, ZSTD_cwksp_alloc_phase_e phase)
+{
void* alloc;
if (ZSTD_isError(ZSTD_cwksp_internal_advance_phase(ws, phase)) || bytes == 0) {
return NULL;
@@ -351,14 +359,16 @@ MEM_STATIC void* ZSTD_cwksp_reserve_internal(
/**
* Reserves and returns unaligned memory.
*/
-MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes) {
+MEM_STATIC BYTE* ZSTD_cwksp_reserve_buffer(ZSTD_cwksp* ws, size_t bytes)
+{
return (BYTE*)ZSTD_cwksp_reserve_internal(ws, bytes, ZSTD_cwksp_alloc_buffers);
}
/**
* Reserves and returns memory sized on and aligned on ZSTD_CWKSP_ALIGNMENT_BYTES (64 bytes).
*/
-MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
+MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes)
+{
void* ptr = ZSTD_cwksp_reserve_internal(ws, ZSTD_cwksp_align(bytes, ZSTD_CWKSP_ALIGNMENT_BYTES),
ZSTD_cwksp_alloc_aligned);
assert(((size_t)ptr & (ZSTD_CWKSP_ALIGNMENT_BYTES-1))== 0);
@@ -370,7 +380,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_aligned(ZSTD_cwksp* ws, size_t bytes) {
* their values remain constrained, allowing us to re-use them without
* memset()-ing them.
*/
-MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
+MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes)
+{
const ZSTD_cwksp_alloc_phase_e phase = ZSTD_cwksp_alloc_aligned;
void* alloc;
void* end;
@@ -408,9 +419,11 @@ MEM_STATIC void* ZSTD_cwksp_reserve_table(ZSTD_cwksp* ws, size_t bytes) {
/**
* Aligned on sizeof(void*).
+ * Note : should happen only once, at workspace first initialization
*/
-MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
- size_t roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));
+MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes)
+{
+ size_t const roundedBytes = ZSTD_cwksp_align(bytes, sizeof(void*));
void* alloc = ws->objectEnd;
void* end = (BYTE*)alloc + roundedBytes;
@@ -419,15 +432,15 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
end = (BYTE *)end + 2 * ZSTD_CWKSP_ASAN_REDZONE_SIZE;
#endif
- DEBUGLOG(5,
+ DEBUGLOG(4,
"cwksp: reserving %p object %zd bytes (rounded to %zd), %zd bytes remaining",
alloc, bytes, roundedBytes, ZSTD_cwksp_available_space(ws) - roundedBytes);
- assert(((size_t)alloc & (sizeof(void*)-1)) == 0);
- assert((bytes & (sizeof(void*)-1)) == 0);
+ assert((size_t)alloc % ZSTD_ALIGNOF(void*) == 0);
+ assert(bytes % ZSTD_ALIGNOF(void*) == 0);
ZSTD_cwksp_assert_internal_consistency(ws);
/* we must be in the first phase, no advance is possible */
if (ws->phase != ZSTD_cwksp_alloc_objects || end > ws->workspaceEnd) {
- DEBUGLOG(4, "cwksp: object alloc failed!");
+ DEBUGLOG(3, "cwksp: object alloc failed!");
ws->allocFailed = 1;
return NULL;
}
@@ -438,7 +451,7 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
#if ZSTD_ADDRESS_SANITIZER && !defined (ZSTD_ASAN_DONT_POISON_WORKSPACE)
/* Move alloc so there's ZSTD_CWKSP_ASAN_REDZONE_SIZE unused space on
* either size. */
- alloc = (BYTE *)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
+ alloc = (BYTE*)alloc + ZSTD_CWKSP_ASAN_REDZONE_SIZE;
if (ws->isStatic == ZSTD_cwksp_dynamic_alloc) {
__asan_unpoison_memory_region(alloc, bytes);
}
@@ -447,7 +460,8 @@ MEM_STATIC void* ZSTD_cwksp_reserve_object(ZSTD_cwksp* ws, size_t bytes) {
return alloc;
}
-MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws) {
+MEM_STATIC void ZSTD_cwksp_mark_tables_dirty(ZSTD_cwksp* ws)
+{
DEBUGLOG(4, "cwksp: ZSTD_cwksp_mark_tables_dirty");
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
diff --git a/thirdparty/zstd/compress/zstd_double_fast.c b/thirdparty/zstd/compress/zstd_double_fast.c
index d0d3a784dd..76933dea26 100644
--- a/thirdparty/zstd/compress/zstd_double_fast.c
+++ b/thirdparty/zstd/compress/zstd_double_fast.c
@@ -48,10 +48,216 @@ void ZSTD_fillDoubleHashTable(ZSTD_matchState_t* ms,
FORCE_INLINE_TEMPLATE
-size_t ZSTD_compressBlock_doubleFast_generic(
+size_t ZSTD_compressBlock_doubleFast_noDict_generic(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ void const* src, size_t srcSize, U32 const mls /* template */)
+{
+ ZSTD_compressionParameters const* cParams = &ms->cParams;
+ U32* const hashLong = ms->hashTable;
+ const U32 hBitsL = cParams->hashLog;
+ U32* const hashSmall = ms->chainTable;
+ const U32 hBitsS = cParams->chainLog;
+ const BYTE* const base = ms->window.base;
+ const BYTE* const istart = (const BYTE*)src;
+ const BYTE* anchor = istart;
+ const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
+ /* presumes that, if there is a dictionary, it must be using Attach mode */
+ const U32 prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);
+ const BYTE* const prefixLowest = base + prefixLowestIndex;
+ const BYTE* const iend = istart + srcSize;
+ const BYTE* const ilimit = iend - HASH_READ_SIZE;
+ U32 offset_1=rep[0], offset_2=rep[1];
+ U32 offsetSaved = 0;
+
+ size_t mLength;
+ U32 offset;
+ U32 curr;
+
+ /* how many positions to search before increasing step size */
+ const size_t kStepIncr = 1 << kSearchStrength;
+ /* the position at which to increment the step size if no match is found */
+ const BYTE* nextStep;
+ size_t step; /* the current step size */
+
+ size_t hl0; /* the long hash at ip */
+ size_t hl1; /* the long hash at ip1 */
+
+ U32 idxl0; /* the long match index for ip */
+ U32 idxl1; /* the long match index for ip1 */
+
+ const BYTE* matchl0; /* the long match for ip */
+ const BYTE* matchs0; /* the short match for ip */
+ const BYTE* matchl1; /* the long match for ip1 */
+
+ const BYTE* ip = istart; /* the current position */
+ const BYTE* ip1; /* the next position */
+
+ DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_noDict_generic");
+
+ /* init */
+ ip += ((ip - prefixLowest) == 0);
+ {
+ U32 const current = (U32)(ip - base);
+ U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, current, cParams->windowLog);
+ U32 const maxRep = current - windowLow;
+ if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
+ if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
+ }
+
+ /* Outer Loop: one iteration per match found and stored */
+ while (1) {
+ step = 1;
+ nextStep = ip + kStepIncr;
+ ip1 = ip + step;
+
+ if (ip1 > ilimit) {
+ goto _cleanup;
+ }
+
+ hl0 = ZSTD_hashPtr(ip, hBitsL, 8);
+ idxl0 = hashLong[hl0];
+ matchl0 = base + idxl0;
+
+ /* Inner Loop: one iteration per search / position */
+ do {
+ const size_t hs0 = ZSTD_hashPtr(ip, hBitsS, mls);
+ const U32 idxs0 = hashSmall[hs0];
+ curr = (U32)(ip-base);
+ matchs0 = base + idxs0;
+
+ hashLong[hl0] = hashSmall[hs0] = curr; /* update hash tables */
+
+ /* check noDict repcode */
+ if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
+ mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
+ ip++;
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
+ goto _match_stored;
+ }
+
+ hl1 = ZSTD_hashPtr(ip1, hBitsL, 8);
+
+ if (idxl0 > prefixLowestIndex) {
+ /* check prefix long match */
+ if (MEM_read64(matchl0) == MEM_read64(ip)) {
+ mLength = ZSTD_count(ip+8, matchl0+8, iend) + 8;
+ offset = (U32)(ip-matchl0);
+ while (((ip>anchor) & (matchl0>prefixLowest)) && (ip[-1] == matchl0[-1])) { ip--; matchl0--; mLength++; } /* catch up */
+ goto _match_found;
+ }
+ }
+
+ idxl1 = hashLong[hl1];
+ matchl1 = base + idxl1;
+
+ if (idxs0 > prefixLowestIndex) {
+ /* check prefix short match */
+ if (MEM_read32(matchs0) == MEM_read32(ip)) {
+ goto _search_next_long;
+ }
+ }
+
+ if (ip1 >= nextStep) {
+ PREFETCH_L1(ip1 + 64);
+ PREFETCH_L1(ip1 + 128);
+ step++;
+ nextStep += kStepIncr;
+ }
+ ip = ip1;
+ ip1 += step;
+
+ hl0 = hl1;
+ idxl0 = idxl1;
+ matchl0 = matchl1;
+ #if defined(__aarch64__)
+ PREFETCH_L1(ip+256);
+ #endif
+ } while (ip1 <= ilimit);
+
+_cleanup:
+ /* save reps for next block */
+ rep[0] = offset_1 ? offset_1 : offsetSaved;
+ rep[1] = offset_2 ? offset_2 : offsetSaved;
+
+ /* Return the last literals size */
+ return (size_t)(iend - anchor);
+
+_search_next_long:
+
+ /* check prefix long +1 match */
+ if (idxl1 > prefixLowestIndex) {
+ if (MEM_read64(matchl1) == MEM_read64(ip1)) {
+ ip = ip1;
+ mLength = ZSTD_count(ip+8, matchl1+8, iend) + 8;
+ offset = (U32)(ip-matchl1);
+ while (((ip>anchor) & (matchl1>prefixLowest)) && (ip[-1] == matchl1[-1])) { ip--; matchl1--; mLength++; } /* catch up */
+ goto _match_found;
+ }
+ }
+
+ /* if no long +1 match, explore the short match we found */
+ mLength = ZSTD_count(ip+4, matchs0+4, iend) + 4;
+ offset = (U32)(ip - matchs0);
+ while (((ip>anchor) & (matchs0>prefixLowest)) && (ip[-1] == matchs0[-1])) { ip--; matchs0--; mLength++; } /* catch up */
+
+ /* fall-through */
+
+_match_found: /* requires ip, offset, mLength */
+ offset_2 = offset_1;
+ offset_1 = offset;
+
+ if (step < 4) {
+ /* It is unsafe to write this value back to the hashtable when ip1 is
+ * greater than or equal to the new ip we will have after we're done
+ * processing this match. Rather than perform that test directly
+ * (ip1 >= ip + mLength), which costs speed in practice, we do a simpler
+ * more predictable test. The minmatch even if we take a short match is
+ * 4 bytes, so as long as step, the distance between ip and ip1
+ * (initially) is less than 4, we know ip1 < new ip. */
+ hashLong[hl1] = (U32)(ip1 - base);
+ }
+
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
+
+_match_stored:
+ /* match found */
+ ip += mLength;
+ anchor = ip;
+
+ if (ip <= ilimit) {
+ /* Complementary insertion */
+ /* done after iLimit test, as candidates could be > iend-8 */
+ { U32 const indexToInsert = curr+2;
+ hashLong[ZSTD_hashPtr(base+indexToInsert, hBitsL, 8)] = indexToInsert;
+ hashLong[ZSTD_hashPtr(ip-2, hBitsL, 8)] = (U32)(ip-2-base);
+ hashSmall[ZSTD_hashPtr(base+indexToInsert, hBitsS, mls)] = indexToInsert;
+ hashSmall[ZSTD_hashPtr(ip-1, hBitsS, mls)] = (U32)(ip-1-base);
+ }
+
+ /* check immediate repcode */
+ while ( (ip <= ilimit)
+ && ( (offset_2>0)
+ & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
+ U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, rLength);
+ ip += rLength;
+ anchor = ip;
+ continue; /* faster when present ... (?) */
+ }
+ }
+ }
+}
+
+
+FORCE_INLINE_TEMPLATE
+size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize,
- U32 const mls /* template */, ZSTD_dictMode_e const dictMode)
+ U32 const mls /* template */)
{
ZSTD_compressionParameters const* cParams = &ms->cParams;
U32* const hashLong = ms->hashTable;
@@ -72,54 +278,30 @@ size_t ZSTD_compressBlock_doubleFast_generic(
U32 offsetSaved = 0;
const ZSTD_matchState_t* const dms = ms->dictMatchState;
- const ZSTD_compressionParameters* const dictCParams =
- dictMode == ZSTD_dictMatchState ?
- &dms->cParams : NULL;
- const U32* const dictHashLong = dictMode == ZSTD_dictMatchState ?
- dms->hashTable : NULL;
- const U32* const dictHashSmall = dictMode == ZSTD_dictMatchState ?
- dms->chainTable : NULL;
- const U32 dictStartIndex = dictMode == ZSTD_dictMatchState ?
- dms->window.dictLimit : 0;
- const BYTE* const dictBase = dictMode == ZSTD_dictMatchState ?
- dms->window.base : NULL;
- const BYTE* const dictStart = dictMode == ZSTD_dictMatchState ?
- dictBase + dictStartIndex : NULL;
- const BYTE* const dictEnd = dictMode == ZSTD_dictMatchState ?
- dms->window.nextSrc : NULL;
- const U32 dictIndexDelta = dictMode == ZSTD_dictMatchState ?
- prefixLowestIndex - (U32)(dictEnd - dictBase) :
- 0;
- const U32 dictHBitsL = dictMode == ZSTD_dictMatchState ?
- dictCParams->hashLog : hBitsL;
- const U32 dictHBitsS = dictMode == ZSTD_dictMatchState ?
- dictCParams->chainLog : hBitsS;
+ const ZSTD_compressionParameters* const dictCParams = &dms->cParams;
+ const U32* const dictHashLong = dms->hashTable;
+ const U32* const dictHashSmall = dms->chainTable;
+ const U32 dictStartIndex = dms->window.dictLimit;
+ const BYTE* const dictBase = dms->window.base;
+ const BYTE* const dictStart = dictBase + dictStartIndex;
+ const BYTE* const dictEnd = dms->window.nextSrc;
+ const U32 dictIndexDelta = prefixLowestIndex - (U32)(dictEnd - dictBase);
+ const U32 dictHBitsL = dictCParams->hashLog;
+ const U32 dictHBitsS = dictCParams->chainLog;
const U32 dictAndPrefixLength = (U32)((ip - prefixLowest) + (dictEnd - dictStart));
- DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_generic");
-
- assert(dictMode == ZSTD_noDict || dictMode == ZSTD_dictMatchState);
+ DEBUGLOG(5, "ZSTD_compressBlock_doubleFast_dictMatchState_generic");
/* if a dictionary is attached, it must be within window range */
- if (dictMode == ZSTD_dictMatchState) {
- assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
- }
+ assert(ms->window.dictLimit + (1U << cParams->windowLog) >= endIndex);
/* init */
ip += (dictAndPrefixLength == 0);
- if (dictMode == ZSTD_noDict) {
- U32 const curr = (U32)(ip - base);
- U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
- U32 const maxRep = curr - windowLow;
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
- }
- if (dictMode == ZSTD_dictMatchState) {
- /* dictMatchState repCode checks don't currently handle repCode == 0
- * disabling. */
- assert(offset_1 <= dictAndPrefixLength);
- assert(offset_2 <= dictAndPrefixLength);
- }
+
+ /* dictMatchState repCode checks don't currently handle repCode == 0
+ * disabling. */
+ assert(offset_1 <= dictAndPrefixLength);
+ assert(offset_2 <= dictAndPrefixLength);
/* Main Search Loop */
while (ip < ilimit) { /* < instead of <=, because repcode check at (ip+1) */
@@ -135,29 +317,18 @@ size_t ZSTD_compressBlock_doubleFast_generic(
const BYTE* matchLong = base + matchIndexL;
const BYTE* match = base + matchIndexS;
const U32 repIndex = curr + 1 - offset_1;
- const BYTE* repMatch = (dictMode == ZSTD_dictMatchState
- && repIndex < prefixLowestIndex) ?
+ const BYTE* repMatch = (repIndex < prefixLowestIndex) ?
dictBase + (repIndex - dictIndexDelta) :
base + repIndex;
hashLong[h2] = hashSmall[h] = curr; /* update hash tables */
- /* check dictMatchState repcode */
- if (dictMode == ZSTD_dictMatchState
- && ((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
+ /* check repcode */
+ if (((U32)((prefixLowestIndex-1) - repIndex) >= 3 /* intentional underflow */)
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
ip++;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
- goto _match_stored;
- }
-
- /* check noDict repcode */
- if ( dictMode == ZSTD_noDict
- && ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1)))) {
- mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
- ip++;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
goto _match_stored;
}
@@ -169,7 +340,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
while (((ip>anchor) & (matchLong>prefixLowest)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
goto _match_found;
}
- } else if (dictMode == ZSTD_dictMatchState) {
+ } else {
/* check dictMatchState long match */
U32 const dictMatchIndexL = dictHashLong[dictHL];
const BYTE* dictMatchL = dictBase + dictMatchIndexL;
@@ -187,7 +358,7 @@ size_t ZSTD_compressBlock_doubleFast_generic(
if (MEM_read32(match) == MEM_read32(ip)) {
goto _search_next_long;
}
- } else if (dictMode == ZSTD_dictMatchState) {
+ } else {
/* check dictMatchState short match */
U32 const dictMatchIndexS = dictHashSmall[dictHS];
match = dictBase + dictMatchIndexS;
@@ -220,7 +391,7 @@ _search_next_long:
while (((ip>anchor) & (matchL3>prefixLowest)) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } /* catch up */
goto _match_found;
}
- } else if (dictMode == ZSTD_dictMatchState) {
+ } else {
/* check dict long +1 match */
U32 const dictMatchIndexL3 = dictHashLong[dictHLNext];
const BYTE* dictMatchL3 = dictBase + dictMatchIndexL3;
@@ -234,7 +405,7 @@ _search_next_long:
} } }
/* if no long +1 match, explore the short match we found */
- if (dictMode == ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) {
+ if (matchIndexS < prefixLowestIndex) {
mLength = ZSTD_count_2segments(ip+4, match+4, iend, dictEnd, prefixLowest) + 4;
offset = (U32)(curr - matchIndexS);
while (((ip>anchor) & (match>dictStart)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
@@ -244,13 +415,11 @@ _search_next_long:
while (((ip>anchor) & (match>prefixLowest)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
}
- /* fall-through */
-
_match_found:
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
_match_stored:
/* match found */
@@ -268,43 +437,27 @@ _match_stored:
}
/* check immediate repcode */
- if (dictMode == ZSTD_dictMatchState) {
- while (ip <= ilimit) {
- U32 const current2 = (U32)(ip-base);
- U32 const repIndex2 = current2 - offset_2;
- const BYTE* repMatch2 = dictMode == ZSTD_dictMatchState
- && repIndex2 < prefixLowestIndex ?
- dictBase + repIndex2 - dictIndexDelta :
- base + repIndex2;
- if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
- && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
- const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
- size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
- U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
- ip += repLength2;
- anchor = ip;
- continue;
- }
- break;
- } }
-
- if (dictMode == ZSTD_noDict) {
- while ( (ip <= ilimit)
- && ( (offset_2>0)
- & (MEM_read32(ip) == MEM_read32(ip - offset_2)) )) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
- hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
- hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength-MINMATCH);
- ip += rLength;
+ while (ip <= ilimit) {
+ U32 const current2 = (U32)(ip-base);
+ U32 const repIndex2 = current2 - offset_2;
+ const BYTE* repMatch2 = repIndex2 < prefixLowestIndex ?
+ dictBase + repIndex2 - dictIndexDelta :
+ base + repIndex2;
+ if ( ((U32)((prefixLowestIndex-1) - (U32)repIndex2) >= 3 /* intentional overflow */)
+ && (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
+ const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
+ size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
+ U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
+ hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
+ hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
+ ip += repLength2;
anchor = ip;
- continue; /* faster when present ... (?) */
- } } }
+ continue;
+ }
+ break;
+ }
+ }
} /* while (ip < ilimit) */
/* save reps for next block */
@@ -315,6 +468,24 @@ _match_stored:
return (size_t)(iend - anchor);
}
+#define ZSTD_GEN_DFAST_FN(dictMode, mls) \
+ static size_t ZSTD_compressBlock_doubleFast_##dictMode##_##mls( \
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
+ void const* src, size_t srcSize) \
+ { \
+ return ZSTD_compressBlock_doubleFast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls); \
+ }
+
+ZSTD_GEN_DFAST_FN(noDict, 4)
+ZSTD_GEN_DFAST_FN(noDict, 5)
+ZSTD_GEN_DFAST_FN(noDict, 6)
+ZSTD_GEN_DFAST_FN(noDict, 7)
+
+ZSTD_GEN_DFAST_FN(dictMatchState, 4)
+ZSTD_GEN_DFAST_FN(dictMatchState, 5)
+ZSTD_GEN_DFAST_FN(dictMatchState, 6)
+ZSTD_GEN_DFAST_FN(dictMatchState, 7)
+
size_t ZSTD_compressBlock_doubleFast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -325,13 +496,13 @@ size_t ZSTD_compressBlock_doubleFast(
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_noDict);
+ return ZSTD_compressBlock_doubleFast_noDict_4(ms, seqStore, rep, src, srcSize);
case 5 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_noDict);
+ return ZSTD_compressBlock_doubleFast_noDict_5(ms, seqStore, rep, src, srcSize);
case 6 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_noDict);
+ return ZSTD_compressBlock_doubleFast_noDict_6(ms, seqStore, rep, src, srcSize);
case 7 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_noDict);
+ return ZSTD_compressBlock_doubleFast_noDict_7(ms, seqStore, rep, src, srcSize);
}
}
@@ -345,13 +516,13 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState(
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 4, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_doubleFast_dictMatchState_4(ms, seqStore, rep, src, srcSize);
case 5 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 5, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_doubleFast_dictMatchState_5(ms, seqStore, rep, src, srcSize);
case 6 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 6, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_doubleFast_dictMatchState_6(ms, seqStore, rep, src, srcSize);
case 7 :
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, 7, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_doubleFast_dictMatchState_7(ms, seqStore, rep, src, srcSize);
}
}
@@ -387,7 +558,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
/* if extDict is invalidated due to maxDistance, switch to "regular" variant */
if (prefixStartIndex == dictStartIndex)
- return ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_noDict);
+ return ZSTD_compressBlock_doubleFast(ms, seqStore, rep, src, srcSize);
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
@@ -409,12 +580,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
hashSmall[hSmall] = hashLong[hLong] = curr; /* update hash table */
if ((((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow : ensure repIndex doesn't overlap dict + prefix */
- & (offset_1 < curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */
+ & (offset_1 <= curr+1 - dictStartIndex)) /* note: we are searching at curr+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
} else {
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
@@ -425,7 +596,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
@@ -450,7 +621,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
}
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
} else {
ip += ((ip-anchor) >> kSearchStrength) + 1;
@@ -477,12 +648,12 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
U32 const repIndex2 = current2 - offset_2;
const BYTE* repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) /* intentional overflow : ensure repIndex2 doesn't overlap dict + prefix */
- & (offset_2 < current2 - dictStartIndex))
+ & (offset_2 <= current2 - dictStartIndex))
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
ip += repLength2;
@@ -500,6 +671,10 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
return (size_t)(iend - anchor);
}
+ZSTD_GEN_DFAST_FN(extDict, 4)
+ZSTD_GEN_DFAST_FN(extDict, 5)
+ZSTD_GEN_DFAST_FN(extDict, 6)
+ZSTD_GEN_DFAST_FN(extDict, 7)
size_t ZSTD_compressBlock_doubleFast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -510,12 +685,12 @@ size_t ZSTD_compressBlock_doubleFast_extDict(
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
+ return ZSTD_compressBlock_doubleFast_extDict_4(ms, seqStore, rep, src, srcSize);
case 5 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
+ return ZSTD_compressBlock_doubleFast_extDict_5(ms, seqStore, rep, src, srcSize);
case 6 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
+ return ZSTD_compressBlock_doubleFast_extDict_6(ms, seqStore, rep, src, srcSize);
case 7 :
- return ZSTD_compressBlock_doubleFast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
+ return ZSTD_compressBlock_doubleFast_extDict_7(ms, seqStore, rep, src, srcSize);
}
}
diff --git a/thirdparty/zstd/compress/zstd_fast.c b/thirdparty/zstd/compress/zstd_fast.c
index 4edc04dccd..802fc31579 100644
--- a/thirdparty/zstd/compress/zstd_fast.c
+++ b/thirdparty/zstd/compress/zstd_fast.c
@@ -43,145 +43,294 @@ void ZSTD_fillHashTable(ZSTD_matchState_t* ms,
}
+/**
+ * If you squint hard enough (and ignore repcodes), the search operation at any
+ * given position is broken into 4 stages:
+ *
+ * 1. Hash (map position to hash value via input read)
+ * 2. Lookup (map hash val to index via hashtable read)
+ * 3. Load (map index to value at that position via input read)
+ * 4. Compare
+ *
+ * Each of these steps involves a memory read at an address which is computed
+ * from the previous step. This means these steps must be sequenced and their
+ * latencies are cumulative.
+ *
+ * Rather than do 1->2->3->4 sequentially for a single position before moving
+ * onto the next, this implementation interleaves these operations across the
+ * next few positions:
+ *
+ * R = Repcode Read & Compare
+ * H = Hash
+ * T = Table Lookup
+ * M = Match Read & Compare
+ *
+ * Pos | Time -->
+ * ----+-------------------
+ * N | ... M
+ * N+1 | ... TM
+ * N+2 | R H T M
+ * N+3 | H TM
+ * N+4 | R H T M
+ * N+5 | H ...
+ * N+6 | R ...
+ *
+ * This is very much analogous to the pipelining of execution in a CPU. And just
+ * like a CPU, we have to dump the pipeline when we find a match (i.e., take a
+ * branch).
+ *
+ * When this happens, we throw away our current state, and do the following prep
+ * to re-enter the loop:
+ *
+ * Pos | Time -->
+ * ----+-------------------
+ * N | H T
+ * N+1 | H
+ *
+ * This is also the work we do at the beginning to enter the loop initially.
+ */
FORCE_INLINE_TEMPLATE size_t
-ZSTD_compressBlock_fast_generic(
+ZSTD_compressBlock_fast_noDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize,
- U32 const mls)
+ U32 const mls, U32 const hasStep)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
U32 const hlog = cParams->hashLog;
/* support stepSize of 0 */
- size_t const stepSize = cParams->targetLength + !(cParams->targetLength) + 1;
+ size_t const stepSize = hasStep ? (cParams->targetLength + !(cParams->targetLength) + 1) : 2;
const BYTE* const base = ms->window.base;
const BYTE* const istart = (const BYTE*)src;
- /* We check ip0 (ip + 0) and ip1 (ip + 1) each loop */
- const BYTE* ip0 = istart;
- const BYTE* ip1;
- const BYTE* anchor = istart;
const U32 endIndex = (U32)((size_t)(istart - base) + srcSize);
const U32 prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog);
const BYTE* const prefixStart = base + prefixStartIndex;
const BYTE* const iend = istart + srcSize;
const BYTE* const ilimit = iend - HASH_READ_SIZE;
- U32 offset_1=rep[0], offset_2=rep[1];
+
+ const BYTE* anchor = istart;
+ const BYTE* ip0 = istart;
+ const BYTE* ip1;
+ const BYTE* ip2;
+ const BYTE* ip3;
+ U32 current0;
+
+ U32 rep_offset1 = rep[0];
+ U32 rep_offset2 = rep[1];
U32 offsetSaved = 0;
- /* init */
+ size_t hash0; /* hash for ip0 */
+ size_t hash1; /* hash for ip1 */
+ U32 idx; /* match idx for ip0 */
+ U32 mval; /* src value at match idx */
+
+ U32 offcode;
+ const BYTE* match0;
+ size_t mLength;
+
+ /* ip0 and ip1 are always adjacent. The targetLength skipping and
+ * uncompressibility acceleration is applied to every other position,
+ * matching the behavior of #1562. step therefore represents the gap
+ * between pairs of positions, from ip0 to ip2 or ip1 to ip3. */
+ size_t step;
+ const BYTE* nextStep;
+ const size_t kStepIncr = (1 << (kSearchStrength - 1));
+
DEBUGLOG(5, "ZSTD_compressBlock_fast_generic");
ip0 += (ip0 == prefixStart);
- ip1 = ip0 + 1;
{ U32 const curr = (U32)(ip0 - base);
U32 const windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog);
U32 const maxRep = curr - windowLow;
- if (offset_2 > maxRep) offsetSaved = offset_2, offset_2 = 0;
- if (offset_1 > maxRep) offsetSaved = offset_1, offset_1 = 0;
+ if (rep_offset2 > maxRep) offsetSaved = rep_offset2, rep_offset2 = 0;
+ if (rep_offset1 > maxRep) offsetSaved = rep_offset1, rep_offset1 = 0;
}
- /* Main Search Loop */
-#ifdef __INTEL_COMPILER
- /* From intel 'The vector pragma indicates that the loop should be
- * vectorized if it is legal to do so'. Can be used together with
- * #pragma ivdep (but have opted to exclude that because intel
- * warns against using it).*/
- #pragma vector always
-#endif
- while (ip1 < ilimit) { /* < instead of <=, because check at ip0+2 */
- size_t mLength;
- BYTE const* ip2 = ip0 + 2;
- size_t const h0 = ZSTD_hashPtr(ip0, hlog, mls);
- U32 const val0 = MEM_read32(ip0);
- size_t const h1 = ZSTD_hashPtr(ip1, hlog, mls);
- U32 const val1 = MEM_read32(ip1);
- U32 const current0 = (U32)(ip0-base);
- U32 const current1 = (U32)(ip1-base);
- U32 const matchIndex0 = hashTable[h0];
- U32 const matchIndex1 = hashTable[h1];
- BYTE const* repMatch = ip2 - offset_1;
- const BYTE* match0 = base + matchIndex0;
- const BYTE* match1 = base + matchIndex1;
- U32 offcode;
-
-#if defined(__aarch64__)
- PREFETCH_L1(ip0+256);
-#endif
-
- hashTable[h0] = current0; /* update hash table */
- hashTable[h1] = current1; /* update hash table */
-
- assert(ip0 + 1 == ip1);
-
- if ((offset_1 > 0) & (MEM_read32(repMatch) == MEM_read32(ip2))) {
- mLength = (ip2[-1] == repMatch[-1]) ? 1 : 0;
- ip0 = ip2 - mLength;
- match0 = repMatch - mLength;
+ /* start each op */
+_start: /* Requires: ip0 */
+
+ step = stepSize;
+ nextStep = ip0 + kStepIncr;
+
+ /* calculate positions, ip0 - anchor == 0, so we skip step calc */
+ ip1 = ip0 + 1;
+ ip2 = ip0 + step;
+ ip3 = ip2 + 1;
+
+ if (ip3 >= ilimit) {
+ goto _cleanup;
+ }
+
+ hash0 = ZSTD_hashPtr(ip0, hlog, mls);
+ hash1 = ZSTD_hashPtr(ip1, hlog, mls);
+
+ idx = hashTable[hash0];
+
+ do {
+ /* load repcode match for ip[2]*/
+ const U32 rval = MEM_read32(ip2 - rep_offset1);
+
+ /* write back hash table entry */
+ current0 = (U32)(ip0 - base);
+ hashTable[hash0] = current0;
+
+ /* check repcode at ip[2] */
+ if ((MEM_read32(ip2) == rval) & (rep_offset1 > 0)) {
+ ip0 = ip2;
+ match0 = ip0 - rep_offset1;
+ mLength = ip0[-1] == match0[-1];
+ ip0 -= mLength;
+ match0 -= mLength;
+ offcode = STORE_REPCODE_1;
mLength += 4;
- offcode = 0;
goto _match;
}
- if ((matchIndex0 > prefixStartIndex) && MEM_read32(match0) == val0) {
- /* found a regular match */
- goto _offset;
+
+ /* load match for ip[0] */
+ if (idx >= prefixStartIndex) {
+ mval = MEM_read32(base + idx);
+ } else {
+ mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */
}
- if ((matchIndex1 > prefixStartIndex) && MEM_read32(match1) == val1) {
- /* found a regular match after one literal */
- ip0 = ip1;
- match0 = match1;
+
+ /* check match at ip[0] */
+ if (MEM_read32(ip0) == mval) {
+ /* found a match! */
goto _offset;
}
- { size_t const step = ((size_t)(ip0-anchor) >> (kSearchStrength - 1)) + stepSize;
- assert(step >= 2);
- ip0 += step;
- ip1 += step;
- continue;
+
+ /* lookup ip[1] */
+ idx = hashTable[hash1];
+
+ /* hash ip[2] */
+ hash0 = hash1;
+ hash1 = ZSTD_hashPtr(ip2, hlog, mls);
+
+ /* advance to next positions */
+ ip0 = ip1;
+ ip1 = ip2;
+ ip2 = ip3;
+
+ /* write back hash table entry */
+ current0 = (U32)(ip0 - base);
+ hashTable[hash0] = current0;
+
+ /* load match for ip[0] */
+ if (idx >= prefixStartIndex) {
+ mval = MEM_read32(base + idx);
+ } else {
+ mval = MEM_read32(ip0) ^ 1; /* guaranteed to not match. */
}
-_offset: /* Requires: ip0, match0 */
- /* Compute the offset code */
- offset_2 = offset_1;
- offset_1 = (U32)(ip0-match0);
- offcode = offset_1 + ZSTD_REP_MOVE;
- mLength = 4;
- /* Count the backwards match length */
- while (((ip0>anchor) & (match0>prefixStart))
- && (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } /* catch up */
-_match: /* Requires: ip0, match0, offcode */
- /* Count the forward length */
- mLength += ZSTD_count(ip0+mLength, match0+mLength, iend);
- ZSTD_storeSeq(seqStore, (size_t)(ip0-anchor), anchor, iend, offcode, mLength-MINMATCH);
- /* match found */
- ip0 += mLength;
- anchor = ip0;
+ /* check match at ip[0] */
+ if (MEM_read32(ip0) == mval) {
+ /* found a match! */
+ goto _offset;
+ }
- if (ip0 <= ilimit) {
- /* Fill Table */
- assert(base+current0+2 > istart); /* check base overflow */
- hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
- hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
-
- if (offset_2 > 0) { /* offset_2==0 means offset_2 is invalidated */
- while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - offset_2)) ) {
- /* store sequence */
- size_t const rLength = ZSTD_count(ip0+4, ip0+4-offset_2, iend) + 4;
- { U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } /* swap offset_2 <=> offset_1 */
- hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
- ip0 += rLength;
- ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, 0 /*offCode*/, rLength-MINMATCH);
- anchor = ip0;
- continue; /* faster when present (confirmed on gcc-8) ... (?) */
- } } }
- ip1 = ip0 + 1;
- }
+ /* lookup ip[1] */
+ idx = hashTable[hash1];
+
+ /* hash ip[2] */
+ hash0 = hash1;
+ hash1 = ZSTD_hashPtr(ip2, hlog, mls);
+
+ /* advance to next positions */
+ ip0 = ip1;
+ ip1 = ip2;
+ ip2 = ip0 + step;
+ ip3 = ip1 + step;
+
+ /* calculate step */
+ if (ip2 >= nextStep) {
+ step++;
+ PREFETCH_L1(ip1 + 64);
+ PREFETCH_L1(ip1 + 128);
+ nextStep += kStepIncr;
+ }
+ } while (ip3 < ilimit);
+
+_cleanup:
+ /* Note that there are probably still a couple positions we could search.
+ * However, it seems to be a meaningful performance hit to try to search
+ * them. So let's not. */
/* save reps for next block */
- rep[0] = offset_1 ? offset_1 : offsetSaved;
- rep[1] = offset_2 ? offset_2 : offsetSaved;
+ rep[0] = rep_offset1 ? rep_offset1 : offsetSaved;
+ rep[1] = rep_offset2 ? rep_offset2 : offsetSaved;
/* Return the last literals size */
return (size_t)(iend - anchor);
+
+_offset: /* Requires: ip0, idx */
+
+ /* Compute the offset code. */
+ match0 = base + idx;
+ rep_offset2 = rep_offset1;
+ rep_offset1 = (U32)(ip0-match0);
+ offcode = STORE_OFFSET(rep_offset1);
+ mLength = 4;
+
+ /* Count the backwards match length. */
+ while (((ip0>anchor) & (match0>prefixStart)) && (ip0[-1] == match0[-1])) {
+ ip0--;
+ match0--;
+ mLength++;
+ }
+
+_match: /* Requires: ip0, match0, offcode */
+
+ /* Count the forward length. */
+ mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend);
+
+ ZSTD_storeSeq(seqStore, (size_t)(ip0 - anchor), anchor, iend, offcode, mLength);
+
+ ip0 += mLength;
+ anchor = ip0;
+
+ /* write next hash table entry */
+ if (ip1 < ip0) {
+ hashTable[hash1] = (U32)(ip1 - base);
+ }
+
+ /* Fill table and check for immediate repcode. */
+ if (ip0 <= ilimit) {
+ /* Fill Table */
+ assert(base+current0+2 > istart); /* check base overflow */
+ hashTable[ZSTD_hashPtr(base+current0+2, hlog, mls)] = current0+2; /* here because current+2 could be > iend-8 */
+ hashTable[ZSTD_hashPtr(ip0-2, hlog, mls)] = (U32)(ip0-2-base);
+
+ if (rep_offset2 > 0) { /* rep_offset2==0 means rep_offset2 is invalidated */
+ while ( (ip0 <= ilimit) && (MEM_read32(ip0) == MEM_read32(ip0 - rep_offset2)) ) {
+ /* store sequence */
+ size_t const rLength = ZSTD_count(ip0+4, ip0+4-rep_offset2, iend) + 4;
+ { U32 const tmpOff = rep_offset2; rep_offset2 = rep_offset1; rep_offset1 = tmpOff; } /* swap rep_offset2 <=> rep_offset1 */
+ hashTable[ZSTD_hashPtr(ip0, hlog, mls)] = (U32)(ip0-base);
+ ip0 += rLength;
+ ZSTD_storeSeq(seqStore, 0 /*litLen*/, anchor, iend, STORE_REPCODE_1, rLength);
+ anchor = ip0;
+ continue; /* faster when present (confirmed on gcc-8) ... (?) */
+ } } }
+
+ goto _start;
}
+#define ZSTD_GEN_FAST_FN(dictMode, mls, step) \
+ static size_t ZSTD_compressBlock_fast_##dictMode##_##mls##_##step( \
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM], \
+ void const* src, size_t srcSize) \
+ { \
+ return ZSTD_compressBlock_fast_##dictMode##_generic(ms, seqStore, rep, src, srcSize, mls, step); \
+ }
+
+ZSTD_GEN_FAST_FN(noDict, 4, 1)
+ZSTD_GEN_FAST_FN(noDict, 5, 1)
+ZSTD_GEN_FAST_FN(noDict, 6, 1)
+ZSTD_GEN_FAST_FN(noDict, 7, 1)
+
+ZSTD_GEN_FAST_FN(noDict, 4, 0)
+ZSTD_GEN_FAST_FN(noDict, 5, 0)
+ZSTD_GEN_FAST_FN(noDict, 6, 0)
+ZSTD_GEN_FAST_FN(noDict, 7, 0)
size_t ZSTD_compressBlock_fast(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -189,24 +338,40 @@ size_t ZSTD_compressBlock_fast(
{
U32 const mls = ms->cParams.minMatch;
assert(ms->dictMatchState == NULL);
- switch(mls)
- {
- default: /* includes case 3 */
- case 4 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 4);
- case 5 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 5);
- case 6 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 6);
- case 7 :
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, 7);
+ if (ms->cParams.targetLength > 1) {
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_fast_noDict_4_1(ms, seqStore, rep, src, srcSize);
+ case 5 :
+ return ZSTD_compressBlock_fast_noDict_5_1(ms, seqStore, rep, src, srcSize);
+ case 6 :
+ return ZSTD_compressBlock_fast_noDict_6_1(ms, seqStore, rep, src, srcSize);
+ case 7 :
+ return ZSTD_compressBlock_fast_noDict_7_1(ms, seqStore, rep, src, srcSize);
+ }
+ } else {
+ switch(mls)
+ {
+ default: /* includes case 3 */
+ case 4 :
+ return ZSTD_compressBlock_fast_noDict_4_0(ms, seqStore, rep, src, srcSize);
+ case 5 :
+ return ZSTD_compressBlock_fast_noDict_5_0(ms, seqStore, rep, src, srcSize);
+ case 6 :
+ return ZSTD_compressBlock_fast_noDict_6_0(ms, seqStore, rep, src, srcSize);
+ case 7 :
+ return ZSTD_compressBlock_fast_noDict_7_0(ms, seqStore, rep, src, srcSize);
+ }
+
}
}
FORCE_INLINE_TEMPLATE
size_t ZSTD_compressBlock_fast_dictMatchState_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- void const* src, size_t srcSize, U32 const mls)
+ void const* src, size_t srcSize, U32 const mls, U32 const hasStep)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
@@ -242,6 +407,8 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
assert(endIndex - prefixStartIndex <= maxDistance);
(void)maxDistance; (void)endIndex; /* these variables are not used when assert() is disabled */
+ (void)hasStep; /* not currently specialized on whether it's accelerated */
+
/* ensure there will be no underflow
* when translating a dict index into a local index */
assert(prefixStartIndex >= (U32)(dictEnd - dictBase));
@@ -272,7 +439,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
ip++;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
} else if ( (matchIndex <= prefixStartIndex) ) {
size_t const dictHash = ZSTD_hashPtr(ip, dictHLog, mls);
U32 const dictMatchIndex = dictHashTable[dictHash];
@@ -292,7 +459,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
} /* catch up */
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
}
} else if (MEM_read32(match) != MEM_read32(ip)) {
/* it's not a match, and we're not going to check the dictionary */
@@ -307,7 +474,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
&& (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
offset_2 = offset_1;
offset_1 = offset;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
}
/* match found */
@@ -332,7 +499,7 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
ip += repLength2;
anchor = ip;
@@ -351,6 +518,12 @@ size_t ZSTD_compressBlock_fast_dictMatchState_generic(
return (size_t)(iend - anchor);
}
+
+ZSTD_GEN_FAST_FN(dictMatchState, 4, 0)
+ZSTD_GEN_FAST_FN(dictMatchState, 5, 0)
+ZSTD_GEN_FAST_FN(dictMatchState, 6, 0)
+ZSTD_GEN_FAST_FN(dictMatchState, 7, 0)
+
size_t ZSTD_compressBlock_fast_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
void const* src, size_t srcSize)
@@ -361,20 +534,20 @@ size_t ZSTD_compressBlock_fast_dictMatchState(
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 4);
+ return ZSTD_compressBlock_fast_dictMatchState_4_0(ms, seqStore, rep, src, srcSize);
case 5 :
- return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 5);
+ return ZSTD_compressBlock_fast_dictMatchState_5_0(ms, seqStore, rep, src, srcSize);
case 6 :
- return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 6);
+ return ZSTD_compressBlock_fast_dictMatchState_6_0(ms, seqStore, rep, src, srcSize);
case 7 :
- return ZSTD_compressBlock_fast_dictMatchState_generic(ms, seqStore, rep, src, srcSize, 7);
+ return ZSTD_compressBlock_fast_dictMatchState_7_0(ms, seqStore, rep, src, srcSize);
}
}
static size_t ZSTD_compressBlock_fast_extDict_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- void const* src, size_t srcSize, U32 const mls)
+ void const* src, size_t srcSize, U32 const mls, U32 const hasStep)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
U32* const hashTable = ms->hashTable;
@@ -398,11 +571,13 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
const BYTE* const ilimit = iend - 8;
U32 offset_1=rep[0], offset_2=rep[1];
+ (void)hasStep; /* not currently specialized on whether it's accelerated */
+
DEBUGLOG(5, "ZSTD_compressBlock_fast_extDict_generic (offset_1=%u)", offset_1);
/* switch to "regular" variant if extDict is invalidated due to maxDistance */
if (prefixStartIndex == dictStartIndex)
- return ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls);
+ return ZSTD_compressBlock_fast(ms, seqStore, rep, src, srcSize);
/* Search Loop */
while (ip < ilimit) { /* < instead of <=, because (ip+1) */
@@ -418,12 +593,12 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
DEBUGLOG(7, "offset_1 = %u , curr = %u", offset_1, curr);
if ( ( ((U32)((prefixStartIndex-1) - repIndex) >= 3) /* intentional underflow */
- & (offset_1 < curr+1 - dictStartIndex) ) /* note: we are searching at curr+1 */
+ & (offset_1 <= curr+1 - dictStartIndex) ) /* note: we are searching at curr+1 */
&& (MEM_read32(repMatch) == MEM_read32(ip+1)) ) {
const BYTE* const repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
size_t const rLength = ZSTD_count_2segments(ip+1 +4, repMatch +4, iend, repMatchEnd, prefixStart) + 4;
ip++;
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, rLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, rLength);
ip += rLength;
anchor = ip;
} else {
@@ -439,7 +614,7 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
size_t mLength = ZSTD_count_2segments(ip+4, match+4, iend, matchEnd, prefixStart) + 4;
while (((ip>anchor) & (match>lowMatchPtr)) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } /* catch up */
offset_2 = offset_1; offset_1 = offset; /* update offset history */
- ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength-MINMATCH);
+ ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
ip += mLength;
anchor = ip;
} }
@@ -453,12 +628,12 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
U32 const current2 = (U32)(ip-base);
U32 const repIndex2 = current2 - offset_2;
const BYTE* const repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : base + repIndex2;
- if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 < curr - dictStartIndex)) /* intentional overflow */
+ if ( (((U32)((prefixStartIndex-1) - repIndex2) >= 3) & (offset_2 <= curr - dictStartIndex)) /* intentional overflow */
&& (MEM_read32(repMatch2) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
{ U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; } /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, 0 /*offcode*/, repLength2-MINMATCH);
+ ZSTD_storeSeq(seqStore, 0 /*litlen*/, anchor, iend, STORE_REPCODE_1, repLength2);
hashTable[ZSTD_hashPtr(ip, hlog, mls)] = current2;
ip += repLength2;
anchor = ip;
@@ -475,6 +650,10 @@ static size_t ZSTD_compressBlock_fast_extDict_generic(
return (size_t)(iend - anchor);
}
+ZSTD_GEN_FAST_FN(extDict, 4, 0)
+ZSTD_GEN_FAST_FN(extDict, 5, 0)
+ZSTD_GEN_FAST_FN(extDict, 6, 0)
+ZSTD_GEN_FAST_FN(extDict, 7, 0)
size_t ZSTD_compressBlock_fast_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
@@ -485,12 +664,12 @@ size_t ZSTD_compressBlock_fast_extDict(
{
default: /* includes case 3 */
case 4 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 4);
+ return ZSTD_compressBlock_fast_extDict_4_0(ms, seqStore, rep, src, srcSize);
case 5 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 5);
+ return ZSTD_compressBlock_fast_extDict_5_0(ms, seqStore, rep, src, srcSize);
case 6 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 6);
+ return ZSTD_compressBlock_fast_extDict_6_0(ms, seqStore, rep, src, srcSize);
case 7 :
- return ZSTD_compressBlock_fast_extDict_generic(ms, seqStore, rep, src, srcSize, 7);
+ return ZSTD_compressBlock_fast_extDict_7_0(ms, seqStore, rep, src, srcSize);
}
}
diff --git a/thirdparty/zstd/compress/zstd_lazy.c b/thirdparty/zstd/compress/zstd_lazy.c
index 3d523e8472..2e38dcb46d 100644
--- a/thirdparty/zstd/compress/zstd_lazy.c
+++ b/thirdparty/zstd/compress/zstd_lazy.c
@@ -61,7 +61,7 @@ ZSTD_updateDUBT(ZSTD_matchState_t* ms,
* assumption : curr >= btlow == (curr - btmask)
* doesn't fail */
static void
-ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
+ZSTD_insertDUBT1(const ZSTD_matchState_t* ms,
U32 curr, const BYTE* inputEnd,
U32 nbCompares, U32 btLow,
const ZSTD_dictMode_e dictMode)
@@ -93,7 +93,7 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
assert(curr >= btLow);
assert(ip < iend); /* condition for ZSTD_count */
- while (nbCompares-- && (matchIndex > windowLow)) {
+ for (; nbCompares && (matchIndex > windowLow); --nbCompares) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
assert(matchIndex < curr);
@@ -151,7 +151,7 @@ ZSTD_insertDUBT1(ZSTD_matchState_t* ms,
static size_t
ZSTD_DUBT_findBetterDictMatch (
- ZSTD_matchState_t* ms,
+ const ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iend,
size_t* offsetPtr,
size_t bestLength,
@@ -185,7 +185,7 @@ ZSTD_DUBT_findBetterDictMatch (
(void)dictMode;
assert(dictMode == ZSTD_dictMatchState);
- while (nbCompares-- && (dictMatchIndex > dictLowLimit)) {
+ for (; nbCompares && (dictMatchIndex > dictLowLimit); --nbCompares) {
U32* const nextPtr = dictBt + 2*(dictMatchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match = dictBase + dictMatchIndex;
@@ -197,8 +197,8 @@ ZSTD_DUBT_findBetterDictMatch (
U32 matchIndex = dictMatchIndex + dictIndexDelta;
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) ) {
DEBUGLOG(9, "ZSTD_DUBT_findBetterDictMatch(%u) : found better match length %u -> %u and offsetCode %u -> %u (dictMatchIndex %u, matchIndex %u)",
- curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, ZSTD_REP_MOVE + curr - matchIndex, dictMatchIndex, matchIndex);
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
+ curr, (U32)bestLength, (U32)matchLength, (U32)*offsetPtr, STORE_OFFSET(curr - matchIndex), dictMatchIndex, matchIndex);
+ bestLength = matchLength, *offsetPtr = STORE_OFFSET(curr - matchIndex);
}
if (ip+matchLength == iend) { /* reached end of input : ip[matchLength] is not valid, no way to know if it's larger or smaller than match */
break; /* drop, to guarantee consistency (miss a little bit of compression) */
@@ -218,7 +218,7 @@ ZSTD_DUBT_findBetterDictMatch (
}
if (bestLength >= MINMATCH) {
- U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ U32 const mIndex = curr - (U32)STORED_OFFSET(*offsetPtr); (void)mIndex;
DEBUGLOG(8, "ZSTD_DUBT_findBetterDictMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
}
@@ -309,7 +309,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
matchIndex = hashTable[h];
hashTable[h] = curr; /* Update Hash Table */
- while (nbCompares-- && (matchIndex > windowLow)) {
+ for (; nbCompares && (matchIndex > windowLow); --nbCompares) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match;
@@ -328,7 +328,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
if ( (4*(int)(matchLength-bestLength)) > (int)(ZSTD_highbit32(curr-matchIndex+1) - ZSTD_highbit32((U32)offsetPtr[0]+1)) )
- bestLength = matchLength, *offsetPtr = ZSTD_REP_MOVE + curr - matchIndex;
+ bestLength = matchLength, *offsetPtr = STORE_OFFSET(curr - matchIndex);
if (ip+matchLength == iend) { /* equal : no way to know if inf or sup */
if (dictMode == ZSTD_dictMatchState) {
nbCompares = 0; /* in addition to avoiding checking any
@@ -357,6 +357,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
*smallerPtr = *largerPtr = 0;
+ assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
if (dictMode == ZSTD_dictMatchState && nbCompares) {
bestLength = ZSTD_DUBT_findBetterDictMatch(
ms, ip, iend,
@@ -367,7 +368,7 @@ ZSTD_DUBT_findBestMatch(ZSTD_matchState_t* ms,
assert(matchEndIdx > curr+8); /* ensure nextToUpdate is increased */
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
if (bestLength >= MINMATCH) {
- U32 const mIndex = curr - ((U32)*offsetPtr - ZSTD_REP_MOVE); (void)mIndex;
+ U32 const mIndex = curr - (U32)STORED_OFFSET(*offsetPtr); (void)mIndex;
DEBUGLOG(8, "ZSTD_DUBT_findBestMatch(%u) : found match of length %u and offsetCode %u (pos %u)",
curr, (U32)bestLength, (U32)*offsetPtr, mIndex);
}
@@ -390,54 +391,6 @@ ZSTD_BtFindBestMatch( ZSTD_matchState_t* ms,
return ZSTD_DUBT_findBestMatch(ms, ip, iLimit, offsetPtr, mls, dictMode);
}
-
-static size_t
-ZSTD_BtFindBestMatch_selectMLS ( ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
- case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
- case 7 :
- case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
- }
-}
-
-
-static size_t ZSTD_BtFindBestMatch_dictMatchState_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
- case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
- case 7 :
- case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
- }
-}
-
-
-static size_t ZSTD_BtFindBestMatch_extDict_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
- case 5 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
- case 7 :
- case 6 : return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
- }
-}
-
/***********************************
* Dedicated dict search
***********************************/
@@ -450,7 +403,7 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const B
U32* const chainTable = ms->chainTable;
U32 const chainSize = 1 << ms->cParams.chainLog;
U32 idx = ms->nextToUpdate;
- U32 const minChain = chainSize < target ? target - chainSize : idx;
+ U32 const minChain = chainSize < target - idx ? target - chainSize : idx;
U32 const bucketSize = 1 << ZSTD_LAZY_DDSS_BUCKET_LOG;
U32 const cacheSize = bucketSize - 1;
U32 const chainAttempts = (1 << ms->cParams.searchLog) - cacheSize;
@@ -464,7 +417,7 @@ void ZSTD_dedicatedDictSearch_lazy_loadDictionary(ZSTD_matchState_t* ms, const B
U32 const hashLog = ms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;
U32* const tmpHashTable = hashTable;
U32* const tmpChainTable = hashTable + ((size_t)1 << hashLog);
- U32 const tmpChainSize = ((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;
+ U32 const tmpChainSize = (U32)((1 << ZSTD_LAZY_DDSS_BUCKET_LOG) - 1) << hashLog;
U32 const tmpMinChain = tmpChainSize < target ? target - tmpChainSize : idx;
U32 hashIdx;
@@ -608,7 +561,7 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
+ *offsetPtr = STORE_OFFSET(curr - (matchIndex + ddsIndexDelta));
if (ip+currentMl == iLimit) {
/* best possible, avoids read overflow on next attempt */
return ml;
@@ -645,7 +598,7 @@ size_t ZSTD_dedicatedDictSearch_lazy_search(size_t* offsetPtr, size_t ml, U32 nb
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - (matchIndex + ddsIndexDelta) + ZSTD_REP_MOVE;
+ *offsetPtr = STORE_OFFSET(curr - (matchIndex + ddsIndexDelta));
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
}
@@ -692,7 +645,7 @@ U32 ZSTD_insertAndFindFirstIndex(ZSTD_matchState_t* ms, const BYTE* ip) {
/* inlining is important to hardwire a hot branch (template emulation) */
FORCE_INLINE_TEMPLATE
-size_t ZSTD_HcFindBestMatch_generic (
+size_t ZSTD_HcFindBestMatch(
ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
@@ -750,7 +703,7 @@ size_t ZSTD_HcFindBestMatch_generic (
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
+ *offsetPtr = STORE_OFFSET(curr - matchIndex);
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
@@ -758,6 +711,7 @@ size_t ZSTD_HcFindBestMatch_generic (
matchIndex = NEXT_IN_CHAIN(matchIndex, chainMask);
}
+ assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
if (dictMode == ZSTD_dedicatedDictSearch) {
ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts, dms,
ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
@@ -784,7 +738,8 @@ size_t ZSTD_HcFindBestMatch_generic (
/* save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
+ assert(curr > matchIndex + dmsIndexDelta);
+ *offsetPtr = STORE_OFFSET(curr - (matchIndex + dmsIndexDelta));
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
@@ -797,310 +752,80 @@ size_t ZSTD_HcFindBestMatch_generic (
return ml;
}
-
-FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_noDict);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_noDict);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_noDict);
- }
-}
-
-
-static size_t ZSTD_HcFindBestMatch_dictMatchState_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dictMatchState);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dictMatchState);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dictMatchState);
- }
-}
-
-
-static size_t ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_dedicatedDictSearch);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_dedicatedDictSearch);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_dedicatedDictSearch);
- }
-}
-
-
-FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, ZSTD_extDict);
- case 5 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, ZSTD_extDict);
- case 7 :
- case 6 : return ZSTD_HcFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, ZSTD_extDict);
- }
-}
-
/* *********************************
* (SIMD) Row-based matchfinder
***********************************/
/* Constants for row-based hash */
-#define ZSTD_ROW_HASH_TAG_OFFSET 1 /* byte offset of hashes in the match state's tagTable from the beginning of a row */
-#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */
+#define ZSTD_ROW_HASH_TAG_OFFSET 16 /* byte offset of hashes in the match state's tagTable from the beginning of a row */
+#define ZSTD_ROW_HASH_TAG_BITS 8 /* nb bits to use for the tag */
#define ZSTD_ROW_HASH_TAG_MASK ((1u << ZSTD_ROW_HASH_TAG_BITS) - 1)
+#define ZSTD_ROW_HASH_MAX_ENTRIES 64 /* absolute maximum number of entries per row, for all configurations */
#define ZSTD_ROW_HASH_CACHE_MASK (ZSTD_ROW_HASH_CACHE_SIZE - 1)
-typedef U32 ZSTD_VecMask; /* Clarifies when we are interacting with a U32 representing a mask of matches */
-
-#if !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) /* SIMD SSE version */
-
-#include <emmintrin.h>
-typedef __m128i ZSTD_Vec128;
-
-/* Returns a 128-bit container with 128-bits from src */
-static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
- return _mm_loadu_si128((ZSTD_Vec128 const*)src);
-}
-
-/* Returns a ZSTD_Vec128 with the byte "val" packed 16 times */
-static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
- return _mm_set1_epi8((char)val);
-}
-
-/* Do byte-by-byte comparison result of x and y. Then collapse 128-bit resultant mask
- * into a 32-bit mask that is the MSB of each byte.
- * */
-static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
- return (ZSTD_VecMask)_mm_movemask_epi8(_mm_cmpeq_epi8(x, y));
-}
-
-typedef struct {
- __m128i fst;
- __m128i snd;
-} ZSTD_Vec256;
-
-static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) {
- ZSTD_Vec256 v;
- v.fst = ZSTD_Vec128_read(ptr);
- v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1);
- return v;
-}
-
-static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
- ZSTD_Vec256 v;
- v.fst = ZSTD_Vec128_set8(val);
- v.snd = ZSTD_Vec128_set8(val);
- return v;
-}
-
-static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
- ZSTD_VecMask fstMask;
- ZSTD_VecMask sndMask;
- fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst);
- sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd);
- return fstMask | (sndMask << 16);
-}
-
-#elif !defined(ZSTD_NO_INTRINSICS) && defined(__ARM_NEON) /* SIMD ARM NEON Version */
-
-#include <arm_neon.h>
-typedef uint8x16_t ZSTD_Vec128;
-
-static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
- return vld1q_u8((const BYTE* const)src);
-}
-
-static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
- return vdupq_n_u8(val);
-}
-
-/* Mimics '_mm_movemask_epi8()' from SSE */
-static U32 ZSTD_vmovmaskq_u8(ZSTD_Vec128 val) {
- /* Shift out everything but the MSB bits in each byte */
- uint16x8_t highBits = vreinterpretq_u16_u8(vshrq_n_u8(val, 7));
- /* Merge the even lanes together with vsra (right shift and add) */
- uint32x4_t paired16 = vreinterpretq_u32_u16(vsraq_n_u16(highBits, highBits, 7));
- uint64x2_t paired32 = vreinterpretq_u64_u32(vsraq_n_u32(paired16, paired16, 14));
- uint8x16_t paired64 = vreinterpretq_u8_u64(vsraq_n_u64(paired32, paired32, 28));
- /* Extract the low 8 bits from each lane, merge */
- return vgetq_lane_u8(paired64, 0) | ((U32)vgetq_lane_u8(paired64, 8) << 8);
-}
-
-static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
- return (ZSTD_VecMask)ZSTD_vmovmaskq_u8(vceqq_u8(x, y));
-}
-
-typedef struct {
- uint8x16_t fst;
- uint8x16_t snd;
-} ZSTD_Vec256;
-
-static ZSTD_Vec256 ZSTD_Vec256_read(const void* const ptr) {
- ZSTD_Vec256 v;
- v.fst = ZSTD_Vec128_read(ptr);
- v.snd = ZSTD_Vec128_read((ZSTD_Vec128 const*)ptr + 1);
- return v;
-}
-
-static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
- ZSTD_Vec256 v;
- v.fst = ZSTD_Vec128_set8(val);
- v.snd = ZSTD_Vec128_set8(val);
- return v;
-}
-
-static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
- ZSTD_VecMask fstMask;
- ZSTD_VecMask sndMask;
- fstMask = ZSTD_Vec128_cmpMask8(x.fst, y.fst);
- sndMask = ZSTD_Vec128_cmpMask8(x.snd, y.snd);
- return fstMask | (sndMask << 16);
-}
-
-#else /* Scalar fallback version */
-
-#define VEC128_NB_SIZE_T (16 / sizeof(size_t))
-typedef struct {
- size_t vec[VEC128_NB_SIZE_T];
-} ZSTD_Vec128;
-
-static ZSTD_Vec128 ZSTD_Vec128_read(const void* const src) {
- ZSTD_Vec128 ret;
- ZSTD_memcpy(ret.vec, src, VEC128_NB_SIZE_T*sizeof(size_t));
- return ret;
-}
-
-static ZSTD_Vec128 ZSTD_Vec128_set8(BYTE val) {
- ZSTD_Vec128 ret = { {0} };
- int startBit = sizeof(size_t) * 8 - 8;
- for (;startBit >= 0; startBit -= 8) {
- unsigned j = 0;
- for (;j < VEC128_NB_SIZE_T; ++j) {
- ret.vec[j] |= ((size_t)val << startBit);
- }
- }
- return ret;
-}
-
-/* Compare x to y, byte by byte, generating a "matches" bitfield */
-static ZSTD_VecMask ZSTD_Vec128_cmpMask8(ZSTD_Vec128 x, ZSTD_Vec128 y) {
- ZSTD_VecMask res = 0;
- unsigned i = 0;
- unsigned l = 0;
- for (; i < VEC128_NB_SIZE_T; ++i) {
- const size_t cmp1 = x.vec[i];
- const size_t cmp2 = y.vec[i];
- unsigned j = 0;
- for (; j < sizeof(size_t); ++j, ++l) {
- if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) {
- res |= ((U32)1 << (j+i*sizeof(size_t)));
- }
- }
- }
- return res;
-}
-
-#define VEC256_NB_SIZE_T 2*VEC128_NB_SIZE_T
-typedef struct {
- size_t vec[VEC256_NB_SIZE_T];
-} ZSTD_Vec256;
-
-static ZSTD_Vec256 ZSTD_Vec256_read(const void* const src) {
- ZSTD_Vec256 ret;
- ZSTD_memcpy(ret.vec, src, VEC256_NB_SIZE_T*sizeof(size_t));
- return ret;
-}
-
-static ZSTD_Vec256 ZSTD_Vec256_set8(BYTE val) {
- ZSTD_Vec256 ret = { {0} };
- int startBit = sizeof(size_t) * 8 - 8;
- for (;startBit >= 0; startBit -= 8) {
- unsigned j = 0;
- for (;j < VEC256_NB_SIZE_T; ++j) {
- ret.vec[j] |= ((size_t)val << startBit);
- }
- }
- return ret;
-}
-
-/* Compare x to y, byte by byte, generating a "matches" bitfield */
-static ZSTD_VecMask ZSTD_Vec256_cmpMask8(ZSTD_Vec256 x, ZSTD_Vec256 y) {
- ZSTD_VecMask res = 0;
- unsigned i = 0;
- unsigned l = 0;
- for (; i < VEC256_NB_SIZE_T; ++i) {
- const size_t cmp1 = x.vec[i];
- const size_t cmp2 = y.vec[i];
- unsigned j = 0;
- for (; j < sizeof(size_t); ++j, ++l) {
- if (((cmp1 >> j*8) & 0xFF) == ((cmp2 >> j*8) & 0xFF)) {
- res |= ((U32)1 << (j+i*sizeof(size_t)));
- }
- }
- }
- return res;
-}
-
-#endif /* !defined(ZSTD_NO_INTRINSICS) && defined(__SSE2__) */
+typedef U64 ZSTD_VecMask; /* Clarifies when we are interacting with a U64 representing a mask of matches */
/* ZSTD_VecMask_next():
* Starting from the LSB, returns the idx of the next non-zero bit.
* Basically counting the nb of trailing zeroes.
*/
static U32 ZSTD_VecMask_next(ZSTD_VecMask val) {
-# if defined(_MSC_VER) /* Visual */
- unsigned long r=0;
- return _BitScanForward(&r, val) ? (U32)r : 0;
-# elif defined(__GNUC__) && (__GNUC__ >= 3)
- return (U32)__builtin_ctz(val);
+ assert(val != 0);
+# if defined(_MSC_VER) && defined(_WIN64)
+ if (val != 0) {
+ unsigned long r;
+ _BitScanForward64(&r, val);
+ return (U32)(r);
+ } else {
+ /* Should not reach this code path */
+ __assume(0);
+ }
+# elif (defined(__GNUC__) && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 4))))
+ if (sizeof(size_t) == 4) {
+ U32 mostSignificantWord = (U32)(val >> 32);
+ U32 leastSignificantWord = (U32)val;
+ if (leastSignificantWord == 0) {
+ return 32 + (U32)__builtin_ctz(mostSignificantWord);
+ } else {
+ return (U32)__builtin_ctz(leastSignificantWord);
+ }
+ } else {
+ return (U32)__builtin_ctzll(val);
+ }
# else
- /* Software ctz version: http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup */
- static const U32 multiplyDeBruijnBitPosition[32] =
- {
- 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
- 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
- };
- return multiplyDeBruijnBitPosition[((U32)((v & -(int)v) * 0x077CB531U)) >> 27];
+ /* Software ctz version: http://aggregate.org/MAGIC/#Trailing%20Zero%20Count
+ * and: https://stackoverflow.com/questions/2709430/count-number-of-bits-in-a-64-bit-long-big-integer
+ */
+ val = ~val & (val - 1ULL); /* Lowest set bit mask */
+ val = val - ((val >> 1) & 0x5555555555555555);
+ val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
+ return (U32)((((val + (val >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
# endif
}
-/* ZSTD_VecMask_rotateRight():
- * Rotates a bitfield to the right by "rotation" bits.
- * If the rotation is greater than totalBits, the returned mask is 0.
+/* ZSTD_rotateRight_*():
+ * Rotates a bitfield to the right by "count" bits.
+ * https://en.wikipedia.org/w/index.php?title=Circular_shift&oldid=991635599#Implementing_circular_shifts
*/
-FORCE_INLINE_TEMPLATE ZSTD_VecMask
-ZSTD_VecMask_rotateRight(ZSTD_VecMask mask, U32 const rotation, U32 const totalBits) {
- if (rotation == 0)
- return mask;
- switch (totalBits) {
- default:
- assert(0);
- case 16:
- return (mask >> rotation) | (U16)(mask << (16 - rotation));
- case 32:
- return (mask >> rotation) | (U32)(mask << (32 - rotation));
- }
+FORCE_INLINE_TEMPLATE
+U64 ZSTD_rotateRight_U64(U64 const value, U32 count) {
+ assert(count < 64);
+ count &= 0x3F; /* for fickle pattern recognition */
+ return (value >> count) | (U64)(value << ((0U - count) & 0x3F));
+}
+
+FORCE_INLINE_TEMPLATE
+U32 ZSTD_rotateRight_U32(U32 const value, U32 count) {
+ assert(count < 32);
+ count &= 0x1F; /* for fickle pattern recognition */
+ return (value >> count) | (U32)(value << ((0U - count) & 0x1F));
+}
+
+FORCE_INLINE_TEMPLATE
+U16 ZSTD_rotateRight_U16(U16 const value, U32 count) {
+ assert(count < 16);
+ count &= 0x0F; /* for fickle pattern recognition */
+ return (value >> count) | (U16)(value << ((0U - count) & 0x0F));
}
/* ZSTD_row_nextIndex():
@@ -1126,20 +851,24 @@ MEM_STATIC int ZSTD_isAligned(void const* ptr, size_t align) {
*/
FORCE_INLINE_TEMPLATE void ZSTD_row_prefetch(U32 const* hashTable, U16 const* tagTable, U32 const relRow, U32 const rowLog) {
PREFETCH_L1(hashTable + relRow);
- if (rowLog == 5) {
+ if (rowLog >= 5) {
PREFETCH_L1(hashTable + relRow + 16);
+ /* Note: prefetching more of the hash table does not appear to be beneficial for 128-entry rows */
}
PREFETCH_L1(tagTable + relRow);
- assert(rowLog == 4 || rowLog == 5);
+ if (rowLog == 6) {
+ PREFETCH_L1(tagTable + relRow + 32);
+ }
+ assert(rowLog == 4 || rowLog == 5 || rowLog == 6);
assert(ZSTD_isAligned(hashTable + relRow, 64)); /* prefetched hash row always 64-byte aligned */
- assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on a multiple of 32 or 64 bytes */
+ assert(ZSTD_isAligned(tagTable + relRow, (size_t)1 << rowLog)); /* prefetched tagRow sits on correct multiple of bytes (32,64,128) */
}
/* ZSTD_row_fillHashCache():
* Fill up the hash cache starting at idx, prefetching up to ZSTD_ROW_HASH_CACHE_SIZE entries,
* but not beyond iLimit.
*/
-static void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base,
+FORCE_INLINE_TEMPLATE void ZSTD_row_fillHashCache(ZSTD_matchState_t* ms, const BYTE* base,
U32 const rowLog, U32 const mls,
U32 idx, const BYTE* const iLimit)
{
@@ -1179,35 +908,65 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_row_nextCachedHash(U32* cache, U32 const* hashTab
}
}
-/* ZSTD_row_update_internal():
- * Inserts the byte at ip into the appropriate position in the hash table.
- * Determines the relative row, and the position within the {16, 32} entry row to insert at.
+/* ZSTD_row_update_internalImpl():
+ * Updates the hash table with positions starting from updateStartIdx until updateEndIdx.
*/
-FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip,
- U32 const mls, U32 const rowLog,
- U32 const rowMask, U32 const useCache)
+FORCE_INLINE_TEMPLATE void ZSTD_row_update_internalImpl(ZSTD_matchState_t* ms,
+ U32 updateStartIdx, U32 const updateEndIdx,
+ U32 const mls, U32 const rowLog,
+ U32 const rowMask, U32 const useCache)
{
U32* const hashTable = ms->hashTable;
U16* const tagTable = ms->tagTable;
U32 const hashLog = ms->rowHashLog;
const BYTE* const base = ms->window.base;
- const U32 target = (U32)(ip - base);
- U32 idx = ms->nextToUpdate;
- DEBUGLOG(6, "ZSTD_row_update_internal(): nextToUpdate=%u, current=%u", idx, target);
- for (; idx < target; ++idx) {
- U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, idx, hashLog, rowLog, mls)
- : (U32)ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
+ DEBUGLOG(6, "ZSTD_row_update_internalImpl(): updateStartIdx=%u, updateEndIdx=%u", updateStartIdx, updateEndIdx);
+ for (; updateStartIdx < updateEndIdx; ++updateStartIdx) {
+ U32 const hash = useCache ? ZSTD_row_nextCachedHash(ms->hashCache, hashTable, tagTable, base, updateStartIdx, hashLog, rowLog, mls)
+ : (U32)ZSTD_hashPtr(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls);
U32 const relRow = (hash >> ZSTD_ROW_HASH_TAG_BITS) << rowLog;
U32* const row = hashTable + relRow;
BYTE* tagRow = (BYTE*)(tagTable + relRow); /* Though tagTable is laid out as a table of U16, each tag is only 1 byte.
Explicit cast allows us to get exact desired position within each row */
U32 const pos = ZSTD_row_nextIndex(tagRow, rowMask);
- assert(hash == ZSTD_hashPtr(base + idx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls));
+ assert(hash == ZSTD_hashPtr(base + updateStartIdx, hashLog + ZSTD_ROW_HASH_TAG_BITS, mls));
((BYTE*)tagRow)[pos + ZSTD_ROW_HASH_TAG_OFFSET] = hash & ZSTD_ROW_HASH_TAG_MASK;
- row[pos] = idx;
+ row[pos] = updateStartIdx;
}
+}
+
+/* ZSTD_row_update_internal():
+ * Inserts the byte at ip into the appropriate position in the hash table, and updates ms->nextToUpdate.
+ * Skips sections of long matches as is necessary.
+ */
+FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const BYTE* ip,
+ U32 const mls, U32 const rowLog,
+ U32 const rowMask, U32 const useCache)
+{
+ U32 idx = ms->nextToUpdate;
+ const BYTE* const base = ms->window.base;
+ const U32 target = (U32)(ip - base);
+ const U32 kSkipThreshold = 384;
+ const U32 kMaxMatchStartPositionsToUpdate = 96;
+ const U32 kMaxMatchEndPositionsToUpdate = 32;
+
+ if (useCache) {
+ /* Only skip positions when using hash cache, i.e.
+ * if we are loading a dict, don't skip anything.
+ * If we decide to skip, then we only update a set number
+ * of positions at the beginning and end of the match.
+ */
+ if (UNLIKELY(target - idx > kSkipThreshold)) {
+ U32 const bound = idx + kMaxMatchStartPositionsToUpdate;
+ ZSTD_row_update_internalImpl(ms, idx, bound, mls, rowLog, rowMask, useCache);
+ idx = target - kMaxMatchEndPositionsToUpdate;
+ ZSTD_row_fillHashCache(ms, base, rowLog, mls, idx, ip+1);
+ }
+ }
+ assert(target >= idx);
+ ZSTD_row_update_internalImpl(ms, idx, target, mls, rowLog, rowMask, useCache);
ms->nextToUpdate = target;
}
@@ -1216,7 +975,7 @@ FORCE_INLINE_TEMPLATE void ZSTD_row_update_internal(ZSTD_matchState_t* ms, const
* processing.
*/
void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) {
- const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
+ const U32 rowLog = BOUNDED(4, ms->cParams.searchLog, 6);
const U32 rowMask = (1u << rowLog) - 1;
const U32 mls = MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */);
@@ -1224,26 +983,131 @@ void ZSTD_row_update(ZSTD_matchState_t* const ms, const BYTE* ip) {
ZSTD_row_update_internal(ms, ip, mls, rowLog, rowMask, 0 /* dont use cache */);
}
+#if defined(ZSTD_ARCH_X86_SSE2)
+FORCE_INLINE_TEMPLATE ZSTD_VecMask
+ZSTD_row_getSSEMask(int nbChunks, const BYTE* const src, const BYTE tag, const U32 head)
+{
+ const __m128i comparisonMask = _mm_set1_epi8((char)tag);
+ int matches[4] = {0};
+ int i;
+ assert(nbChunks == 1 || nbChunks == 2 || nbChunks == 4);
+ for (i=0; i<nbChunks; i++) {
+ const __m128i chunk = _mm_loadu_si128((const __m128i*)(const void*)(src + 16*i));
+ const __m128i equalMask = _mm_cmpeq_epi8(chunk, comparisonMask);
+ matches[i] = _mm_movemask_epi8(equalMask);
+ }
+ if (nbChunks == 1) return ZSTD_rotateRight_U16((U16)matches[0], head);
+ if (nbChunks == 2) return ZSTD_rotateRight_U32((U32)matches[1] << 16 | (U32)matches[0], head);
+ assert(nbChunks == 4);
+ return ZSTD_rotateRight_U64((U64)matches[3] << 48 | (U64)matches[2] << 32 | (U64)matches[1] << 16 | (U64)matches[0], head);
+}
+#endif
+
/* Returns a ZSTD_VecMask (U32) that has the nth bit set to 1 if the newly-computed "tag" matches
* the hash at the nth position in a row of the tagTable.
- */
-FORCE_INLINE_TEMPLATE
-ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries) {
- ZSTD_VecMask matches = 0;
- if (rowEntries == 16) {
- ZSTD_Vec128 hashes = ZSTD_Vec128_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET);
- ZSTD_Vec128 expandedTags = ZSTD_Vec128_set8(tag);
- matches = ZSTD_Vec128_cmpMask8(hashes, expandedTags);
- } else if (rowEntries == 32) {
- ZSTD_Vec256 hashes = ZSTD_Vec256_read(tagRow + ZSTD_ROW_HASH_TAG_OFFSET);
- ZSTD_Vec256 expandedTags = ZSTD_Vec256_set8(tag);
- matches = ZSTD_Vec256_cmpMask8(hashes, expandedTags);
- } else {
- assert(0);
+ * Each row is a circular buffer beginning at the value of "head". So we must rotate the "matches" bitfield
+ * to match up with the actual layout of the entries within the hashTable */
+FORCE_INLINE_TEMPLATE ZSTD_VecMask
+ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, const U32 head, const U32 rowEntries)
+{
+ const BYTE* const src = tagRow + ZSTD_ROW_HASH_TAG_OFFSET;
+ assert((rowEntries == 16) || (rowEntries == 32) || rowEntries == 64);
+ assert(rowEntries <= ZSTD_ROW_HASH_MAX_ENTRIES);
+
+#if defined(ZSTD_ARCH_X86_SSE2)
+
+ return ZSTD_row_getSSEMask(rowEntries / 16, src, tag, head);
+
+#else /* SW or NEON-LE */
+
+# if defined(ZSTD_ARCH_ARM_NEON)
+ /* This NEON path only works for little endian - otherwise use SWAR below */
+ if (MEM_isLittleEndian()) {
+ if (rowEntries == 16) {
+ const uint8x16_t chunk = vld1q_u8(src);
+ const uint16x8_t equalMask = vreinterpretq_u16_u8(vceqq_u8(chunk, vdupq_n_u8(tag)));
+ const uint16x8_t t0 = vshlq_n_u16(equalMask, 7);
+ const uint32x4_t t1 = vreinterpretq_u32_u16(vsriq_n_u16(t0, t0, 14));
+ const uint64x2_t t2 = vreinterpretq_u64_u32(vshrq_n_u32(t1, 14));
+ const uint8x16_t t3 = vreinterpretq_u8_u64(vsraq_n_u64(t2, t2, 28));
+ const U16 hi = (U16)vgetq_lane_u8(t3, 8);
+ const U16 lo = (U16)vgetq_lane_u8(t3, 0);
+ return ZSTD_rotateRight_U16((hi << 8) | lo, head);
+ } else if (rowEntries == 32) {
+ const uint16x8x2_t chunk = vld2q_u16((const U16*)(const void*)src);
+ const uint8x16_t chunk0 = vreinterpretq_u8_u16(chunk.val[0]);
+ const uint8x16_t chunk1 = vreinterpretq_u8_u16(chunk.val[1]);
+ const uint8x16_t equalMask0 = vceqq_u8(chunk0, vdupq_n_u8(tag));
+ const uint8x16_t equalMask1 = vceqq_u8(chunk1, vdupq_n_u8(tag));
+ const int8x8_t pack0 = vqmovn_s16(vreinterpretq_s16_u8(equalMask0));
+ const int8x8_t pack1 = vqmovn_s16(vreinterpretq_s16_u8(equalMask1));
+ const uint8x8_t t0 = vreinterpret_u8_s8(pack0);
+ const uint8x8_t t1 = vreinterpret_u8_s8(pack1);
+ const uint8x8_t t2 = vsri_n_u8(t1, t0, 2);
+ const uint8x8x2_t t3 = vuzp_u8(t2, t0);
+ const uint8x8_t t4 = vsri_n_u8(t3.val[1], t3.val[0], 4);
+ const U32 matches = vget_lane_u32(vreinterpret_u32_u8(t4), 0);
+ return ZSTD_rotateRight_U32(matches, head);
+ } else { /* rowEntries == 64 */
+ const uint8x16x4_t chunk = vld4q_u8(src);
+ const uint8x16_t dup = vdupq_n_u8(tag);
+ const uint8x16_t cmp0 = vceqq_u8(chunk.val[0], dup);
+ const uint8x16_t cmp1 = vceqq_u8(chunk.val[1], dup);
+ const uint8x16_t cmp2 = vceqq_u8(chunk.val[2], dup);
+ const uint8x16_t cmp3 = vceqq_u8(chunk.val[3], dup);
+
+ const uint8x16_t t0 = vsriq_n_u8(cmp1, cmp0, 1);
+ const uint8x16_t t1 = vsriq_n_u8(cmp3, cmp2, 1);
+ const uint8x16_t t2 = vsriq_n_u8(t1, t0, 2);
+ const uint8x16_t t3 = vsriq_n_u8(t2, t2, 4);
+ const uint8x8_t t4 = vshrn_n_u16(vreinterpretq_u16_u8(t3), 4);
+ const U64 matches = vget_lane_u64(vreinterpret_u64_u8(t4), 0);
+ return ZSTD_rotateRight_U64(matches, head);
+ }
}
- /* Each row is a circular buffer beginning at the value of "head". So we must rotate the "matches" bitfield
- to match up with the actual layout of the entries within the hashTable */
- return ZSTD_VecMask_rotateRight(matches, head, rowEntries);
+# endif /* ZSTD_ARCH_ARM_NEON */
+ /* SWAR */
+ { const size_t chunkSize = sizeof(size_t);
+ const size_t shiftAmount = ((chunkSize * 8) - chunkSize);
+ const size_t xFF = ~((size_t)0);
+ const size_t x01 = xFF / 0xFF;
+ const size_t x80 = x01 << 7;
+ const size_t splatChar = tag * x01;
+ ZSTD_VecMask matches = 0;
+ int i = rowEntries - chunkSize;
+ assert((sizeof(size_t) == 4) || (sizeof(size_t) == 8));
+ if (MEM_isLittleEndian()) { /* runtime check so have two loops */
+ const size_t extractMagic = (xFF / 0x7F) >> chunkSize;
+ do {
+ size_t chunk = MEM_readST(&src[i]);
+ chunk ^= splatChar;
+ chunk = (((chunk | x80) - x01) | chunk) & x80;
+ matches <<= chunkSize;
+ matches |= (chunk * extractMagic) >> shiftAmount;
+ i -= chunkSize;
+ } while (i >= 0);
+ } else { /* big endian: reverse bits during extraction */
+ const size_t msb = xFF ^ (xFF >> 1);
+ const size_t extractMagic = (msb / 0x1FF) | msb;
+ do {
+ size_t chunk = MEM_readST(&src[i]);
+ chunk ^= splatChar;
+ chunk = (((chunk | x80) - x01) | chunk) & x80;
+ matches <<= chunkSize;
+ matches |= ((chunk >> 7) * extractMagic) >> shiftAmount;
+ i -= chunkSize;
+ } while (i >= 0);
+ }
+ matches = ~matches;
+ if (rowEntries == 16) {
+ return ZSTD_rotateRight_U16((U16)matches, head);
+ } else if (rowEntries == 32) {
+ return ZSTD_rotateRight_U32((U32)matches, head);
+ } else {
+ return ZSTD_rotateRight_U64((U64)matches, head);
+ }
+ }
+#endif
}
/* The high-level approach of the SIMD row based match finder is as follows:
@@ -1262,7 +1126,7 @@ ZSTD_VecMask ZSTD_row_getMatchMask(const BYTE* const tagRow, const BYTE tag, con
* - Pick the longest match.
*/
FORCE_INLINE_TEMPLATE
-size_t ZSTD_RowFindBestMatch_generic (
+size_t ZSTD_RowFindBestMatch(
ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iLimit,
size_t* offsetPtr,
@@ -1293,11 +1157,13 @@ size_t ZSTD_RowFindBestMatch_generic (
/* DMS/DDS variables that may be referenced laster */
const ZSTD_matchState_t* const dms = ms->dictMatchState;
- size_t ddsIdx;
- U32 ddsExtraAttempts; /* cctx hash tables are limited in searches, but allow extra searches into DDS */
- U32 dmsTag;
- U32* dmsRow;
- BYTE* dmsTagRow;
+
+ /* Initialize the following variables to satisfy static analyzer */
+ size_t ddsIdx = 0;
+ U32 ddsExtraAttempts = 0; /* cctx hash tables are limited in searches, but allow extra searches into DDS */
+ U32 dmsTag = 0;
+ U32* dmsRow = NULL;
+ BYTE* dmsTagRow = NULL;
if (dictMode == ZSTD_dedicatedDictSearch) {
const U32 ddsHashLog = dms->cParams.hashLog - ZSTD_LAZY_DDSS_BUCKET_LOG;
@@ -1329,7 +1195,7 @@ size_t ZSTD_RowFindBestMatch_generic (
U32* const row = hashTable + relRow;
BYTE* tagRow = (BYTE*)(tagTable + relRow);
U32 const head = *tagRow & rowMask;
- U32 matchBuffer[32 /* maximum nb entries per row */];
+ U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];
size_t numMatches = 0;
size_t currMatch = 0;
ZSTD_VecMask matches = ZSTD_row_getMatchMask(tagRow, (BYTE)tag, head, rowEntries);
@@ -1379,12 +1245,13 @@ size_t ZSTD_RowFindBestMatch_generic (
/* Save best solution */
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - matchIndex + ZSTD_REP_MOVE;
+ *offsetPtr = STORE_OFFSET(curr - matchIndex);
if (ip+currentMl == iLimit) break; /* best possible, avoids read overflow on next attempt */
}
}
}
+ assert(nbAttempts <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
if (dictMode == ZSTD_dedicatedDictSearch) {
ml = ZSTD_dedicatedDictSearch_lazy_search(offsetPtr, ml, nbAttempts + ddsExtraAttempts, dms,
ip, iLimit, prefixStart, curr, dictLimit, ddsIdx);
@@ -1397,7 +1264,7 @@ size_t ZSTD_RowFindBestMatch_generic (
const U32 dmsIndexDelta = dictLimit - dmsSize;
{ U32 const head = *dmsTagRow & rowMask;
- U32 matchBuffer[32 /* maximum nb row entries */];
+ U32 matchBuffer[ZSTD_ROW_HASH_MAX_ENTRIES];
size_t numMatches = 0;
size_t currMatch = 0;
ZSTD_VecMask matches = ZSTD_row_getMatchMask(dmsTagRow, (BYTE)dmsTag, head, rowEntries);
@@ -1426,7 +1293,8 @@ size_t ZSTD_RowFindBestMatch_generic (
if (currentMl > ml) {
ml = currentMl;
- *offsetPtr = curr - (matchIndex + dmsIndexDelta) + ZSTD_REP_MOVE;
+ assert(curr > matchIndex + dmsIndexDelta);
+ *offsetPtr = STORE_OFFSET(curr - (matchIndex + dmsIndexDelta));
if (ip+currentMl == iLimit) break;
}
}
@@ -1435,84 +1303,175 @@ size_t ZSTD_RowFindBestMatch_generic (
return ml;
}
-/* Inlining is important to hardwire a hot branch (template emulation) */
-FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectMLS (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- const ZSTD_dictMode_e dictMode, size_t* offsetPtr, const U32 rowLog)
-{
- switch(ms->cParams.minMatch)
- {
- default : /* includes case 3 */
- case 4 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 4, dictMode, rowLog);
- case 5 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 5, dictMode, rowLog);
- case 7 :
- case 6 : return ZSTD_RowFindBestMatch_generic(ms, ip, iLimit, offsetPtr, 6, dictMode, rowLog);
- }
-}
-FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_selectRowLog (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
- switch(cappedSearchLog)
- {
- default :
- case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 4);
- case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_noDict, offsetPtr, 5);
+typedef size_t (*searchMax_f)(
+ ZSTD_matchState_t* ms,
+ const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
+
+/**
+ * This struct contains the functions necessary for lazy to search.
+ * Currently, that is only searchMax. However, it is still valuable to have the
+ * VTable because this makes it easier to add more functions to the VTable later.
+ *
+ * TODO: The start of the search function involves loading and calculating a
+ * bunch of constants from the ZSTD_matchState_t. These computations could be
+ * done in an initialization function, and saved somewhere in the match state.
+ * Then we could pass a pointer to the saved state instead of the match state,
+ * and avoid duplicate computations.
+ *
+ * TODO: Move the match re-winding into searchMax. This improves compression
+ * ratio, and unlocks further simplifications with the next TODO.
+ *
+ * TODO: Try moving the repcode search into searchMax. After the re-winding
+ * and repcode search are in searchMax, there is no more logic in the match
+ * finder loop that requires knowledge about the dictMode. So we should be
+ * able to avoid force inlining it, and we can join the extDict loop with
+ * the single segment loop. It should go in searchMax instead of its own
+ * function to avoid having multiple virtual function calls per search.
+ */
+typedef struct {
+ searchMax_f searchMax;
+} ZSTD_LazyVTable;
+
+#define GEN_ZSTD_BT_VTABLE(dictMode, mls) \
+ static size_t ZSTD_BtFindBestMatch_##dictMode##_##mls( \
+ ZSTD_matchState_t* ms, \
+ const BYTE* ip, const BYTE* const iLimit, \
+ size_t* offsetPtr) \
+ { \
+ assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
+ return ZSTD_BtFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \
+ } \
+ static const ZSTD_LazyVTable ZSTD_BtVTable_##dictMode##_##mls = { \
+ ZSTD_BtFindBestMatch_##dictMode##_##mls \
+ };
+
+#define GEN_ZSTD_HC_VTABLE(dictMode, mls) \
+ static size_t ZSTD_HcFindBestMatch_##dictMode##_##mls( \
+ ZSTD_matchState_t* ms, \
+ const BYTE* ip, const BYTE* const iLimit, \
+ size_t* offsetPtr) \
+ { \
+ assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
+ return ZSTD_HcFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode); \
+ } \
+ static const ZSTD_LazyVTable ZSTD_HcVTable_##dictMode##_##mls = { \
+ ZSTD_HcFindBestMatch_##dictMode##_##mls \
+ };
+
+#define GEN_ZSTD_ROW_VTABLE(dictMode, mls, rowLog) \
+ static size_t ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog( \
+ ZSTD_matchState_t* ms, \
+ const BYTE* ip, const BYTE* const iLimit, \
+ size_t* offsetPtr) \
+ { \
+ assert(MAX(4, MIN(6, ms->cParams.minMatch)) == mls); \
+ assert(MAX(4, MIN(6, ms->cParams.searchLog)) == rowLog); \
+ return ZSTD_RowFindBestMatch(ms, ip, iLimit, offsetPtr, mls, ZSTD_##dictMode, rowLog); \
+ } \
+ static const ZSTD_LazyVTable ZSTD_RowVTable_##dictMode##_##mls##_##rowLog = { \
+ ZSTD_RowFindBestMatch_##dictMode##_##mls##_##rowLog \
+ };
+
+#define ZSTD_FOR_EACH_ROWLOG(X, dictMode, mls) \
+ X(dictMode, mls, 4) \
+ X(dictMode, mls, 5) \
+ X(dictMode, mls, 6)
+
+#define ZSTD_FOR_EACH_MLS_ROWLOG(X, dictMode) \
+ ZSTD_FOR_EACH_ROWLOG(X, dictMode, 4) \
+ ZSTD_FOR_EACH_ROWLOG(X, dictMode, 5) \
+ ZSTD_FOR_EACH_ROWLOG(X, dictMode, 6)
+
+#define ZSTD_FOR_EACH_MLS(X, dictMode) \
+ X(dictMode, 4) \
+ X(dictMode, 5) \
+ X(dictMode, 6)
+
+#define ZSTD_FOR_EACH_DICT_MODE(X, ...) \
+ X(__VA_ARGS__, noDict) \
+ X(__VA_ARGS__, extDict) \
+ X(__VA_ARGS__, dictMatchState) \
+ X(__VA_ARGS__, dedicatedDictSearch)
+
+/* Generate Row VTables for each combination of (dictMode, mls, rowLog) */
+ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS_ROWLOG, GEN_ZSTD_ROW_VTABLE)
+/* Generate Binary Tree VTables for each combination of (dictMode, mls) */
+ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_BT_VTABLE)
+/* Generate Hash Chain VTables for each combination of (dictMode, mls) */
+ZSTD_FOR_EACH_DICT_MODE(ZSTD_FOR_EACH_MLS, GEN_ZSTD_HC_VTABLE)
+
+#define GEN_ZSTD_BT_VTABLE_ARRAY(dictMode) \
+ { \
+ &ZSTD_BtVTable_##dictMode##_4, \
+ &ZSTD_BtVTable_##dictMode##_5, \
+ &ZSTD_BtVTable_##dictMode##_6 \
}
-}
-FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dictMatchState_selectRowLog(
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
- switch(cappedSearchLog)
- {
- default :
- case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 4);
- case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dictMatchState, offsetPtr, 5);
+#define GEN_ZSTD_HC_VTABLE_ARRAY(dictMode) \
+ { \
+ &ZSTD_HcVTable_##dictMode##_4, \
+ &ZSTD_HcVTable_##dictMode##_5, \
+ &ZSTD_HcVTable_##dictMode##_6 \
}
-}
-FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog(
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
- switch(cappedSearchLog)
- {
- default :
- case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 4);
- case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_dedicatedDictSearch, offsetPtr, 5);
+#define GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, mls) \
+ { \
+ &ZSTD_RowVTable_##dictMode##_##mls##_4, \
+ &ZSTD_RowVTable_##dictMode##_##mls##_5, \
+ &ZSTD_RowVTable_##dictMode##_##mls##_6 \
}
-}
-FORCE_INLINE_TEMPLATE size_t ZSTD_RowFindBestMatch_extDict_selectRowLog (
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* const iLimit,
- size_t* offsetPtr)
-{
- const U32 cappedSearchLog = MIN(ms->cParams.searchLog, 5);
- switch(cappedSearchLog)
- {
- default :
- case 4 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 4);
- case 5 : return ZSTD_RowFindBestMatch_selectMLS(ms, ip, iLimit, ZSTD_extDict, offsetPtr, 5);
+#define GEN_ZSTD_ROW_VTABLE_ARRAY(dictMode) \
+ { \
+ GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 4), \
+ GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 5), \
+ GEN_ZSTD_ROW_VTABLE_ARRAY_(dictMode, 6) \
}
-}
+#define GEN_ZSTD_VTABLE_ARRAY(X) \
+ { \
+ X(noDict), \
+ X(extDict), \
+ X(dictMatchState), \
+ X(dedicatedDictSearch) \
+ }
/* *******************************
* Common parser - lazy strategy
*********************************/
typedef enum { search_hashChain=0, search_binaryTree=1, search_rowHash=2 } searchMethod_e;
+/**
+ * This table is indexed first by the four ZSTD_dictMode_e values, and then
+ * by the two searchMethod_e values. NULLs are placed for configurations
+ * that should never occur (extDict modes go to the other implementation
+ * below and there is no DDSS for binary tree search yet).
+ */
+
+static ZSTD_LazyVTable const*
+ZSTD_selectLazyVTable(ZSTD_matchState_t const* ms, searchMethod_e searchMethod, ZSTD_dictMode_e dictMode)
+{
+ /* Fill the Hc/Bt VTable arrays with the right functions for the (dictMode, mls) combination. */
+ ZSTD_LazyVTable const* const hcVTables[4][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_HC_VTABLE_ARRAY);
+ ZSTD_LazyVTable const* const btVTables[4][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_BT_VTABLE_ARRAY);
+ /* Fill the Row VTable array with the right functions for the (dictMode, mls, rowLog) combination. */
+ ZSTD_LazyVTable const* const rowVTables[4][3][3] = GEN_ZSTD_VTABLE_ARRAY(GEN_ZSTD_ROW_VTABLE_ARRAY);
+
+ U32 const mls = MAX(4, MIN(6, ms->cParams.minMatch));
+ U32 const rowLog = MAX(4, MIN(6, ms->cParams.searchLog));
+ switch (searchMethod) {
+ case search_hashChain:
+ return hcVTables[dictMode][mls - 4];
+ case search_binaryTree:
+ return btVTables[dictMode][mls - 4];
+ case search_rowHash:
+ return rowVTables[dictMode][mls - 4][rowLog - 4];
+ default:
+ return NULL;
+ }
+}
+
FORCE_INLINE_TEMPLATE size_t
ZSTD_compressBlock_lazy_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore,
@@ -1525,46 +1484,12 @@ ZSTD_compressBlock_lazy_generic(
const BYTE* ip = istart;
const BYTE* anchor = istart;
const BYTE* const iend = istart + srcSize;
- const BYTE* const ilimit = searchMethod == search_rowHash ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
+ const BYTE* const ilimit = (searchMethod == search_rowHash) ? iend - 8 - ZSTD_ROW_HASH_CACHE_SIZE : iend - 8;
const BYTE* const base = ms->window.base;
const U32 prefixLowestIndex = ms->window.dictLimit;
const BYTE* const prefixLowest = base + prefixLowestIndex;
- const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
- typedef size_t (*searchMax_f)(
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
-
- /**
- * This table is indexed first by the four ZSTD_dictMode_e values, and then
- * by the two searchMethod_e values. NULLs are placed for configurations
- * that should never occur (extDict modes go to the other implementation
- * below and there is no DDSS for binary tree search yet).
- */
- const searchMax_f searchFuncs[4][3] = {
- {
- ZSTD_HcFindBestMatch_selectMLS,
- ZSTD_BtFindBestMatch_selectMLS,
- ZSTD_RowFindBestMatch_selectRowLog
- },
- {
- NULL,
- NULL,
- NULL
- },
- {
- ZSTD_HcFindBestMatch_dictMatchState_selectMLS,
- ZSTD_BtFindBestMatch_dictMatchState_selectMLS,
- ZSTD_RowFindBestMatch_dictMatchState_selectRowLog
- },
- {
- ZSTD_HcFindBestMatch_dedicatedDictSearch_selectMLS,
- NULL,
- ZSTD_RowFindBestMatch_dedicatedDictSearch_selectRowLog
- }
- };
-
- searchMax_f const searchMax = searchFuncs[dictMode][(int)searchMethod];
+ searchMax_f const searchMax = ZSTD_selectLazyVTable(ms, searchMethod, dictMode)->searchMax;
U32 offset_1 = rep[0], offset_2 = rep[1], savedOffset=0;
const int isDMS = dictMode == ZSTD_dictMatchState;
@@ -1599,6 +1524,7 @@ ZSTD_compressBlock_lazy_generic(
}
if (searchMethod == search_rowHash) {
+ const U32 rowLog = MAX(4, MIN(6, ms->cParams.searchLog));
ZSTD_row_fillHashCache(ms, base, rowLog,
MIN(ms->cParams.minMatch, 6 /* mls caps out at 6 */),
ms->nextToUpdate, ilimit);
@@ -1613,8 +1539,9 @@ ZSTD_compressBlock_lazy_generic(
#endif
while (ip < ilimit) {
size_t matchLength=0;
- size_t offset=0;
+ size_t offcode=STORE_REPCODE_1;
const BYTE* start=ip+1;
+ DEBUGLOG(7, "search baseline (depth 0)");
/* check repCode */
if (isDxS) {
@@ -1640,7 +1567,7 @@ ZSTD_compressBlock_lazy_generic(
{ size_t offsetFound = 999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
if (ml2 > matchLength)
- matchLength = ml2, start = ip, offset=offsetFound;
+ matchLength = ml2, start = ip, offcode=offsetFound;
}
if (matchLength < 4) {
@@ -1651,14 +1578,15 @@ ZSTD_compressBlock_lazy_generic(
/* let's try to find a better solution */
if (depth>=1)
while (ip<ilimit) {
+ DEBUGLOG(7, "search depth 1");
ip ++;
if ( (dictMode == ZSTD_noDict)
- && (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ && (offcode) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
int const gain2 = (int)(mlRep * 3);
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((mlRep >= 4) && (gain2 > gain1))
- matchLength = mlRep, offset = 0, start = ip;
+ matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
}
if (isDxS) {
const U32 repIndex = (U32)(ip - base) - offset_1;
@@ -1670,30 +1598,31 @@ ZSTD_compressBlock_lazy_generic(
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
int const gain2 = (int)(mlRep * 3);
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((mlRep >= 4) && (gain2 > gain1))
- matchLength = mlRep, offset = 0, start = ip;
+ matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
}
}
{ size_t offset2=999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
+ matchLength = ml2, offcode = offset2, start = ip;
continue; /* search a better one */
} }
/* let's find an even better one */
if ((depth==2) && (ip<ilimit)) {
+ DEBUGLOG(7, "search depth 2");
ip ++;
if ( (dictMode == ZSTD_noDict)
- && (offset) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
+ && (offcode) && ((offset_1>0) & (MEM_read32(ip) == MEM_read32(ip - offset_1)))) {
size_t const mlRep = ZSTD_count(ip+4, ip+4-offset_1, iend) + 4;
int const gain2 = (int)(mlRep * 4);
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((mlRep >= 4) && (gain2 > gain1))
- matchLength = mlRep, offset = 0, start = ip;
+ matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
}
if (isDxS) {
const U32 repIndex = (U32)(ip - base) - offset_1;
@@ -1705,46 +1634,45 @@ ZSTD_compressBlock_lazy_generic(
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
size_t const mlRep = ZSTD_count_2segments(ip+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
int const gain2 = (int)(mlRep * 4);
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((mlRep >= 4) && (gain2 > gain1))
- matchLength = mlRep, offset = 0, start = ip;
+ matchLength = mlRep, offcode = STORE_REPCODE_1, start = ip;
}
}
{ size_t offset2=999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
+ matchLength = ml2, offcode = offset2, start = ip;
continue;
} } }
break; /* nothing found : store previous solution */
}
/* NOTE:
- * start[-offset+ZSTD_REP_MOVE-1] is undefined behavior.
- * (-offset+ZSTD_REP_MOVE-1) is unsigned, and is added to start, which
- * overflows the pointer, which is undefined behavior.
+ * Pay attention that `start[-value]` can lead to strange undefined behavior
+ * notably if `value` is unsigned, resulting in a large positive `-value`.
*/
/* catch up */
- if (offset) {
+ if (STORED_IS_OFFSET(offcode)) {
if (dictMode == ZSTD_noDict) {
- while ( ((start > anchor) & (start - (offset-ZSTD_REP_MOVE) > prefixLowest))
- && (start[-1] == (start-(offset-ZSTD_REP_MOVE))[-1]) ) /* only search for offset within prefix */
+ while ( ((start > anchor) & (start - STORED_OFFSET(offcode) > prefixLowest))
+ && (start[-1] == (start-STORED_OFFSET(offcode))[-1]) ) /* only search for offset within prefix */
{ start--; matchLength++; }
}
if (isDxS) {
- U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
+ U32 const matchIndex = (U32)((size_t)(start-base) - STORED_OFFSET(offcode));
const BYTE* match = (matchIndex < prefixLowestIndex) ? dictBase + matchIndex - dictIndexDelta : base + matchIndex;
const BYTE* const mStart = (matchIndex < prefixLowestIndex) ? dictLowest : prefixLowest;
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
}
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
+ offset_2 = offset_1; offset_1 = (U32)STORED_OFFSET(offcode);
}
/* store sequence */
_storeSequence:
- { size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH);
+ { size_t const litLength = (size_t)(start - anchor);
+ ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offcode, matchLength);
anchor = ip = start + matchLength;
}
@@ -1760,8 +1688,8 @@ _storeSequence:
&& (MEM_read32(repMatch) == MEM_read32(ip)) ) {
const BYTE* const repEnd2 = repIndex < prefixLowestIndex ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd2, prefixLowest) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset_2 <=> offset_1 */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
+ offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap offset_2 <=> offset_1 */
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
ip += matchLength;
anchor = ip;
continue;
@@ -1775,8 +1703,8 @@ _storeSequence:
&& (MEM_read32(ip) == MEM_read32(ip - offset_2)) ) {
/* store sequence */
matchLength = ZSTD_count(ip+4, ip+4-offset_2, iend) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap repcodes */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
+ offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap repcodes */
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
ip += matchLength;
anchor = ip;
continue; /* faster when present ... (?) */
@@ -1955,15 +1883,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const U32 windowLog = ms->cParams.windowLog;
const U32 rowLog = ms->cParams.searchLog < 5 ? 4 : 5;
- typedef size_t (*searchMax_f)(
- ZSTD_matchState_t* ms,
- const BYTE* ip, const BYTE* iLimit, size_t* offsetPtr);
- const searchMax_f searchFuncs[3] = {
- ZSTD_HcFindBestMatch_extDict_selectMLS,
- ZSTD_BtFindBestMatch_extDict_selectMLS,
- ZSTD_RowFindBestMatch_extDict_selectRowLog
- };
- searchMax_f searchMax = searchFuncs[(int)searchMethod];
+ searchMax_f const searchMax = ZSTD_selectLazyVTable(ms, searchMethod, ZSTD_extDict)->searchMax;
U32 offset_1 = rep[0], offset_2 = rep[1];
DEBUGLOG(5, "ZSTD_compressBlock_lazy_extDict_generic (searchFunc=%u)", (U32)searchMethod);
@@ -1985,7 +1905,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
#endif
while (ip < ilimit) {
size_t matchLength=0;
- size_t offset=0;
+ size_t offcode=STORE_REPCODE_1;
const BYTE* start=ip+1;
U32 curr = (U32)(ip-base);
@@ -1995,7 +1915,7 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow */
- & (offset_1 < curr+1 - windowLow) ) /* note: we are searching at curr+1 */
+ & (offset_1 <= curr+1 - windowLow) ) /* note: we are searching at curr+1 */
if (MEM_read32(ip+1) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
@@ -2007,10 +1927,10 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
{ size_t offsetFound = 999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offsetFound);
if (ml2 > matchLength)
- matchLength = ml2, start = ip, offset=offsetFound;
+ matchLength = ml2, start = ip, offcode=offsetFound;
}
- if (matchLength < 4) {
+ if (matchLength < 4) {
ip += ((ip-anchor) >> kSearchStrength) + 1; /* jump faster over incompressible sections */
continue;
}
@@ -2021,30 +1941,30 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
ip ++;
curr++;
/* check repCode */
- if (offset) {
+ if (offcode) {
const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
const U32 repIndex = (U32)(curr - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
- & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
+ & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
int const gain2 = (int)(repLength * 3);
- int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*3 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((repLength >= 4) && (gain2 > gain1))
- matchLength = repLength, offset = 0, start = ip;
+ matchLength = repLength, offcode = STORE_REPCODE_1, start = ip;
} }
/* search match, depth 1 */
{ size_t offset2=999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 4);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 4);
if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
+ matchLength = ml2, offcode = offset2, start = ip;
continue; /* search a better one */
} }
@@ -2053,48 +1973,48 @@ size_t ZSTD_compressBlock_lazy_extDict_generic(
ip ++;
curr++;
/* check repCode */
- if (offset) {
+ if (offcode) {
const U32 windowLow = ZSTD_getLowestMatchIndex(ms, curr, windowLog);
const U32 repIndex = (U32)(curr - offset_1);
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
- & (offset_1 < curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
+ & (offset_1 <= curr - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
size_t const repLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
int const gain2 = (int)(repLength * 4);
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 1);
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 1);
if ((repLength >= 4) && (gain2 > gain1))
- matchLength = repLength, offset = 0, start = ip;
+ matchLength = repLength, offcode = STORE_REPCODE_1, start = ip;
} }
/* search match, depth 2 */
{ size_t offset2=999999999;
size_t const ml2 = searchMax(ms, ip, iend, &offset2);
- int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)offset2+1)); /* raw approx */
- int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)offset+1) + 7);
+ int const gain2 = (int)(ml2*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offset2))); /* raw approx */
+ int const gain1 = (int)(matchLength*4 - ZSTD_highbit32((U32)STORED_TO_OFFBASE(offcode)) + 7);
if ((ml2 >= 4) && (gain2 > gain1)) {
- matchLength = ml2, offset = offset2, start = ip;
+ matchLength = ml2, offcode = offset2, start = ip;
continue;
} } }
break; /* nothing found : store previous solution */
}
/* catch up */
- if (offset) {
- U32 const matchIndex = (U32)((start-base) - (offset - ZSTD_REP_MOVE));
+ if (STORED_IS_OFFSET(offcode)) {
+ U32 const matchIndex = (U32)((size_t)(start-base) - STORED_OFFSET(offcode));
const BYTE* match = (matchIndex < dictLimit) ? dictBase + matchIndex : base + matchIndex;
const BYTE* const mStart = (matchIndex < dictLimit) ? dictStart : prefixStart;
while ((start>anchor) && (match>mStart) && (start[-1] == match[-1])) { start--; match--; matchLength++; } /* catch up */
- offset_2 = offset_1; offset_1 = (U32)(offset - ZSTD_REP_MOVE);
+ offset_2 = offset_1; offset_1 = (U32)STORED_OFFSET(offcode);
}
/* store sequence */
_storeSequence:
- { size_t const litLength = start - anchor;
- ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offset, matchLength-MINMATCH);
+ { size_t const litLength = (size_t)(start - anchor);
+ ZSTD_storeSeq(seqStore, litLength, anchor, iend, (U32)offcode, matchLength);
anchor = ip = start + matchLength;
}
@@ -2106,13 +2026,13 @@ _storeSequence:
const BYTE* const repBase = repIndex < dictLimit ? dictBase : base;
const BYTE* const repMatch = repBase + repIndex;
if ( ((U32)((dictLimit-1) - repIndex) >= 3) /* intentional overflow : do not test positions overlapping 2 memory segments */
- & (offset_2 < repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
+ & (offset_2 <= repCurrent - windowLow) ) /* equivalent to `curr > repIndex >= windowLow` */
if (MEM_read32(ip) == MEM_read32(repMatch)) {
/* repcode detected we should take it */
const BYTE* const repEnd = repIndex < dictLimit ? dictEnd : iend;
matchLength = ZSTD_count_2segments(ip+4, repMatch+4, iend, repEnd, prefixStart) + 4;
- offset = offset_2; offset_2 = offset_1; offset_1 = (U32)offset; /* swap offset history */
- ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, matchLength-MINMATCH);
+ offcode = offset_2; offset_2 = offset_1; offset_1 = (U32)offcode; /* swap offset history */
+ ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, matchLength);
ip += matchLength;
anchor = ip;
continue; /* faster when present ... (?) */
diff --git a/thirdparty/zstd/compress/zstd_ldm.c b/thirdparty/zstd/compress/zstd_ldm.c
index fa4ebeabd7..f662b2546e 100644
--- a/thirdparty/zstd/compress/zstd_ldm.c
+++ b/thirdparty/zstd/compress/zstd_ldm.c
@@ -159,12 +159,12 @@ size_t ZSTD_ldm_getTableSize(ldmParams_t params)
size_t const ldmBucketSize = ((size_t)1) << (params.hashLog - ldmBucketSizeLog);
size_t const totalSize = ZSTD_cwksp_alloc_size(ldmBucketSize)
+ ZSTD_cwksp_alloc_size(ldmHSize * sizeof(ldmEntry_t));
- return params.enableLdm ? totalSize : 0;
+ return params.enableLdm == ZSTD_ps_enable ? totalSize : 0;
}
size_t ZSTD_ldm_getMaxNbSeq(ldmParams_t params, size_t maxChunkSize)
{
- return params.enableLdm ? (maxChunkSize / params.minMatchLength) : 0;
+ return params.enableLdm == ZSTD_ps_enable ? (maxChunkSize / params.minMatchLength) : 0;
}
/** ZSTD_ldm_getBucket() :
@@ -478,7 +478,7 @@ static size_t ZSTD_ldm_generateSequences_internal(
*/
if (anchor > ip + hashed) {
ZSTD_ldm_gear_reset(&hashState, anchor - minMatchLength, minMatchLength);
- /* Continue the outter loop at anchor (ip + hashed == anchor). */
+ /* Continue the outer loop at anchor (ip + hashed == anchor). */
ip = anchor - hashed;
break;
}
@@ -579,7 +579,9 @@ size_t ZSTD_ldm_generateSequences(
return 0;
}
-void ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch) {
+void
+ZSTD_ldm_skipSequences(rawSeqStore_t* rawSeqStore, size_t srcSize, U32 const minMatch)
+{
while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) {
rawSeq* seq = rawSeqStore->seq + rawSeqStore->pos;
if (srcSize <= seq->litLength) {
@@ -657,7 +659,7 @@ void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ ZSTD_paramSwitch_e useRowMatchFinder,
void const* src, size_t srcSize)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
@@ -709,8 +711,8 @@ size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
rep[0] = sequence.offset;
/* Store the sequence */
ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend,
- sequence.offset + ZSTD_REP_MOVE,
- sequence.matchLength - MINMATCH);
+ STORE_OFFSET(sequence.offset),
+ sequence.matchLength);
ip += sequence.matchLength;
}
}
diff --git a/thirdparty/zstd/compress/zstd_ldm.h b/thirdparty/zstd/compress/zstd_ldm.h
index 393466fa9f..4e68dbf52e 100644
--- a/thirdparty/zstd/compress/zstd_ldm.h
+++ b/thirdparty/zstd/compress/zstd_ldm.h
@@ -66,7 +66,7 @@ size_t ZSTD_ldm_generateSequences(
*/
size_t ZSTD_ldm_blockCompress(rawSeqStore_t* rawSeqStore,
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
- ZSTD_useRowMatchFinderMode_e useRowMatchFinder,
+ ZSTD_paramSwitch_e useRowMatchFinder,
void const* src, size_t srcSize);
/**
diff --git a/thirdparty/zstd/compress/zstd_ldm_geartab.h b/thirdparty/zstd/compress/zstd_ldm_geartab.h
index e5c24d856b..647f865be2 100644
--- a/thirdparty/zstd/compress/zstd_ldm_geartab.h
+++ b/thirdparty/zstd/compress/zstd_ldm_geartab.h
@@ -11,7 +11,10 @@
#ifndef ZSTD_LDM_GEARTAB_H
#define ZSTD_LDM_GEARTAB_H
-static U64 ZSTD_ldm_gearTab[256] = {
+#include "../common/compiler.h" /* UNUSED_ATTR */
+#include "../common/mem.h" /* U64 */
+
+static UNUSED_ATTR const U64 ZSTD_ldm_gearTab[256] = {
0xf5b8f72c5f77775c, 0x84935f266b7ac412, 0xb647ada9ca730ccc,
0xb065bb4b114fb1de, 0x34584e7e8c3a9fd0, 0x4e97e17c6ae26b05,
0x3a03d743bc99a604, 0xcecd042422c4044f, 0x76de76c58524259e,
diff --git a/thirdparty/zstd/compress/zstd_opt.c b/thirdparty/zstd/compress/zstd_opt.c
index 402a7e5c76..1b1ddad428 100644
--- a/thirdparty/zstd/compress/zstd_opt.c
+++ b/thirdparty/zstd/compress/zstd_opt.c
@@ -14,7 +14,6 @@
#define ZSTD_LITFREQ_ADD 2 /* scaling factor for litFreq, so that frequencies adapt faster to new stats */
-#define ZSTD_FREQ_DIV 4 /* log factor when using previous stats to init next stats */
#define ZSTD_MAX_PRICE (1<<30)
#define ZSTD_PREDEF_THRESHOLD 1024 /* if srcSize < ZSTD_PREDEF_THRESHOLD, symbols' cost is assumed static, directly determined by pre-defined distributions */
@@ -24,11 +23,11 @@
* Price functions for optimal parser
***************************************/
-#if 0 /* approximation at bit level */
+#if 0 /* approximation at bit level (for tests) */
# define BITCOST_ACCURACY 0
# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
-# define WEIGHT(stat) ((void)opt, ZSTD_bitWeight(stat))
-#elif 0 /* fractional bit accuracy */
+# define WEIGHT(stat, opt) ((void)opt, ZSTD_bitWeight(stat))
+#elif 0 /* fractional bit accuracy (for tests) */
# define BITCOST_ACCURACY 8
# define BITCOST_MULTIPLIER (1 << BITCOST_ACCURACY)
# define WEIGHT(stat,opt) ((void)opt, ZSTD_fracWeight(stat))
@@ -66,7 +65,7 @@ MEM_STATIC double ZSTD_fCost(U32 price)
static int ZSTD_compressedLiterals(optState_t const* const optPtr)
{
- return optPtr->literalCompressionMode != ZSTD_lcm_uncompressed;
+ return optPtr->literalCompressionMode != ZSTD_ps_disable;
}
static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
@@ -79,25 +78,46 @@ static void ZSTD_setBasePrices(optState_t* optPtr, int optLevel)
}
-/* ZSTD_downscaleStat() :
- * reduce all elements in table by a factor 2^(ZSTD_FREQ_DIV+malus)
- * return the resulting sum of elements */
-static U32 ZSTD_downscaleStat(unsigned* table, U32 lastEltIndex, int malus)
+static U32 sum_u32(const unsigned table[], size_t nbElts)
+{
+ size_t n;
+ U32 total = 0;
+ for (n=0; n<nbElts; n++) {
+ total += table[n];
+ }
+ return total;
+}
+
+static U32 ZSTD_downscaleStats(unsigned* table, U32 lastEltIndex, U32 shift)
{
U32 s, sum=0;
- DEBUGLOG(5, "ZSTD_downscaleStat (nbElts=%u)", (unsigned)lastEltIndex+1);
- assert(ZSTD_FREQ_DIV+malus > 0 && ZSTD_FREQ_DIV+malus < 31);
+ DEBUGLOG(5, "ZSTD_downscaleStats (nbElts=%u, shift=%u)", (unsigned)lastEltIndex+1, (unsigned)shift);
+ assert(shift < 30);
for (s=0; s<lastEltIndex+1; s++) {
- table[s] = 1 + (table[s] >> (ZSTD_FREQ_DIV+malus));
+ table[s] = 1 + (table[s] >> shift);
sum += table[s];
}
return sum;
}
+/* ZSTD_scaleStats() :
+ * reduce all elements in table is sum too large
+ * return the resulting sum of elements */
+static U32 ZSTD_scaleStats(unsigned* table, U32 lastEltIndex, U32 logTarget)
+{
+ U32 const prevsum = sum_u32(table, lastEltIndex+1);
+ U32 const factor = prevsum >> logTarget;
+ DEBUGLOG(5, "ZSTD_scaleStats (nbElts=%u, target=%u)", (unsigned)lastEltIndex+1, (unsigned)logTarget);
+ assert(logTarget < 30);
+ if (factor <= 1) return prevsum;
+ return ZSTD_downscaleStats(table, lastEltIndex, ZSTD_highbit32(factor));
+}
+
/* ZSTD_rescaleFreqs() :
* if first block (detected by optPtr->litLengthSum == 0) : init statistics
* take hints from dictionary if there is one
- * or init from zero, using src for literals stats, or flat 1 for match symbols
+ * and init from zero if there is none,
+ * using src for literals stats, and baseline stats for sequence symbols
* otherwise downscale existing stats, to be used as seed for next block.
*/
static void
@@ -126,7 +146,7 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
optPtr->litSum = 0;
for (lit=0; lit<=MaxLit; lit++) {
U32 const scaleLog = 11; /* scale to 2K */
- U32 const bitCost = HUF_getNbBits(optPtr->symbolCosts->huf.CTable, lit);
+ U32 const bitCost = HUF_getNbBitsFromCTable(optPtr->symbolCosts->huf.CTable, lit);
assert(bitCost <= scaleLog);
optPtr->litFreq[lit] = bitCost ? 1 << (scaleLog-bitCost) : 1 /*minimum to calculate cost*/;
optPtr->litSum += optPtr->litFreq[lit];
@@ -174,14 +194,19 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
if (compressedLiterals) {
unsigned lit = MaxLit;
HIST_count_simple(optPtr->litFreq, &lit, src, srcSize); /* use raw first block to init statistics */
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
+ optPtr->litSum = ZSTD_downscaleStats(optPtr->litFreq, MaxLit, 8);
}
- { unsigned ll;
- for (ll=0; ll<=MaxLL; ll++)
- optPtr->litLengthFreq[ll] = 1;
+ { unsigned const baseLLfreqs[MaxLL+1] = {
+ 4, 2, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1
+ };
+ ZSTD_memcpy(optPtr->litLengthFreq, baseLLfreqs, sizeof(baseLLfreqs));
+ optPtr->litLengthSum = sum_u32(baseLLfreqs, MaxLL+1);
}
- optPtr->litLengthSum = MaxLL+1;
{ unsigned ml;
for (ml=0; ml<=MaxML; ml++)
@@ -189,21 +214,26 @@ ZSTD_rescaleFreqs(optState_t* const optPtr,
}
optPtr->matchLengthSum = MaxML+1;
- { unsigned of;
- for (of=0; of<=MaxOff; of++)
- optPtr->offCodeFreq[of] = 1;
+ { unsigned const baseOFCfreqs[MaxOff+1] = {
+ 6, 2, 1, 1, 2, 3, 4, 4,
+ 4, 3, 2, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+ };
+ ZSTD_memcpy(optPtr->offCodeFreq, baseOFCfreqs, sizeof(baseOFCfreqs));
+ optPtr->offCodeSum = sum_u32(baseOFCfreqs, MaxOff+1);
}
- optPtr->offCodeSum = MaxOff+1;
+
}
} else { /* new block : re-use previous statistics, scaled down */
if (compressedLiterals)
- optPtr->litSum = ZSTD_downscaleStat(optPtr->litFreq, MaxLit, 1);
- optPtr->litLengthSum = ZSTD_downscaleStat(optPtr->litLengthFreq, MaxLL, 0);
- optPtr->matchLengthSum = ZSTD_downscaleStat(optPtr->matchLengthFreq, MaxML, 0);
- optPtr->offCodeSum = ZSTD_downscaleStat(optPtr->offCodeFreq, MaxOff, 0);
+ optPtr->litSum = ZSTD_scaleStats(optPtr->litFreq, MaxLit, 12);
+ optPtr->litLengthSum = ZSTD_scaleStats(optPtr->litLengthFreq, MaxLL, 11);
+ optPtr->matchLengthSum = ZSTD_scaleStats(optPtr->matchLengthFreq, MaxML, 11);
+ optPtr->offCodeSum = ZSTD_scaleStats(optPtr->offCodeFreq, MaxOff, 11);
}
ZSTD_setBasePrices(optPtr, optLevel);
@@ -239,7 +269,16 @@ static U32 ZSTD_rawLiteralsCost(const BYTE* const literals, U32 const litLength,
* cost of literalLength symbol */
static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optPtr, int optLevel)
{
- if (optPtr->priceType == zop_predef) return WEIGHT(litLength, optLevel);
+ assert(litLength <= ZSTD_BLOCKSIZE_MAX);
+ if (optPtr->priceType == zop_predef)
+ return WEIGHT(litLength, optLevel);
+ /* We can't compute the litLength price for sizes >= ZSTD_BLOCKSIZE_MAX
+ * because it isn't representable in the zstd format. So instead just
+ * call it 1 bit more than ZSTD_BLOCKSIZE_MAX - 1. In this case the block
+ * would be all literals.
+ */
+ if (litLength == ZSTD_BLOCKSIZE_MAX)
+ return BITCOST_MULTIPLIER + ZSTD_litLengthPrice(ZSTD_BLOCKSIZE_MAX - 1, optPtr, optLevel);
/* dynamic statistics */
{ U32 const llCode = ZSTD_LLcode(litLength);
@@ -252,15 +291,17 @@ static U32 ZSTD_litLengthPrice(U32 const litLength, const optState_t* const optP
/* ZSTD_getMatchPrice() :
* Provides the cost of the match part (offset + matchLength) of a sequence
* Must be combined with ZSTD_fullLiteralsCost() to get the full cost of a sequence.
- * optLevel: when <2, favors small offset for decompression speed (improved cache efficiency) */
+ * @offcode : expects a scale where 0,1,2 are repcodes 1-3, and 3+ are real_offsets+2
+ * @optLevel: when <2, favors small offset for decompression speed (improved cache efficiency)
+ */
FORCE_INLINE_TEMPLATE U32
-ZSTD_getMatchPrice(U32 const offset,
+ZSTD_getMatchPrice(U32 const offcode,
U32 const matchLength,
const optState_t* const optPtr,
int const optLevel)
{
U32 price;
- U32 const offCode = ZSTD_highbit32(offset+1);
+ U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offcode));
U32 const mlBase = matchLength - MINMATCH;
assert(matchLength >= MINMATCH);
@@ -303,8 +344,8 @@ static void ZSTD_updateStats(optState_t* const optPtr,
optPtr->litLengthSum++;
}
- /* match offset code (0-2=>repCode; 3+=>offset+2) */
- { U32 const offCode = ZSTD_highbit32(offsetCode+1);
+ /* offset code : expected to follow storeSeq() numeric representation */
+ { U32 const offCode = ZSTD_highbit32(STORED_TO_OFFBASE(offsetCode));
assert(offCode <= MaxOff);
optPtr->offCodeFreq[offCode]++;
optPtr->offCodeSum++;
@@ -338,7 +379,7 @@ MEM_STATIC U32 ZSTD_readMINMATCH(const void* memPtr, U32 length)
/* Update hashTable3 up to ip (excluded)
Assumption : always within prefix (i.e. not within extDict) */
-static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
+static U32 ZSTD_insertAndFindFirstIndexHash3 (const ZSTD_matchState_t* ms,
U32* nextToUpdate3,
const BYTE* const ip)
{
@@ -364,11 +405,13 @@ static U32 ZSTD_insertAndFindFirstIndexHash3 (ZSTD_matchState_t* ms,
* Binary Tree search
***************************************/
/** ZSTD_insertBt1() : add one or multiple positions to tree.
- * ip : assumed <= iend-8 .
+ * @param ip assumed <= iend-8 .
+ * @param target The target of ZSTD_updateTree_internal() - we are filling to this position
* @return : nb of positions added */
static U32 ZSTD_insertBt1(
- ZSTD_matchState_t* ms,
+ const ZSTD_matchState_t* ms,
const BYTE* const ip, const BYTE* const iend,
+ U32 const target,
U32 const mls, const int extDict)
{
const ZSTD_compressionParameters* const cParams = &ms->cParams;
@@ -391,7 +434,10 @@ static U32 ZSTD_insertBt1(
U32* smallerPtr = bt + 2*(curr&btMask);
U32* largerPtr = smallerPtr + 1;
U32 dummy32; /* to be nullified at the end */
- U32 const windowLow = ms->window.lowLimit;
+ /* windowLow is based on target because
+ * we only need positions that will be in the window at the end of the tree update.
+ */
+ U32 const windowLow = ZSTD_getLowestMatchIndex(ms, target, cParams->windowLog);
U32 matchEndIdx = curr+8+1;
size_t bestLength = 8;
U32 nbCompares = 1U << cParams->searchLog;
@@ -404,11 +450,12 @@ static U32 ZSTD_insertBt1(
DEBUGLOG(8, "ZSTD_insertBt1 (%u)", curr);
+ assert(curr <= target);
assert(ip <= iend-8); /* required for h calculation */
hashTable[h] = curr; /* Update Hash Table */
assert(windowLow > 0);
- while (nbCompares-- && (matchIndex >= windowLow)) {
+ for (; nbCompares && (matchIndex >= windowLow); --nbCompares) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
assert(matchIndex < curr);
@@ -492,7 +539,7 @@ void ZSTD_updateTree_internal(
idx, target, dictMode);
while(idx < target) {
- U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, mls, dictMode == ZSTD_extDict);
+ U32 const forward = ZSTD_insertBt1(ms, base+idx, iend, target, mls, dictMode == ZSTD_extDict);
assert(idx < (U32)(idx + forward));
idx += forward;
}
@@ -597,7 +644,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
DEBUGLOG(8, "found repCode %u (ll0:%u, offset:%u) of length %u",
repCode, ll0, repOffset, repLen);
bestLength = repLen;
- matches[mnum].off = repCode - ll0;
+ matches[mnum].off = STORE_REPCODE(repCode - ll0 + 1); /* expect value between 1 and 3 */
matches[mnum].len = (U32)repLen;
mnum++;
if ( (repLen > sufficient_len)
@@ -626,7 +673,7 @@ U32 ZSTD_insertBtAndGetAllMatches (
bestLength = mlen;
assert(curr > matchIndex3);
assert(mnum==0); /* no prior solution */
- matches[0].off = (curr - matchIndex3) + ZSTD_REP_MOVE;
+ matches[0].off = STORE_OFFSET(curr - matchIndex3);
matches[0].len = (U32)mlen;
mnum = 1;
if ( (mlen > sufficient_len) |
@@ -635,11 +682,11 @@ U32 ZSTD_insertBtAndGetAllMatches (
return 1;
} } }
/* no dictMatchState lookup: dicts don't have a populated HC3 table */
- }
+ } /* if (mls == 3) */
hashTable[h] = curr; /* Update Hash Table */
- while (nbCompares-- && (matchIndex >= matchLow)) {
+ for (; nbCompares && (matchIndex >= matchLow); --nbCompares) {
U32* const nextPtr = bt + 2*(matchIndex & btMask);
const BYTE* match;
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
@@ -660,20 +707,19 @@ U32 ZSTD_insertBtAndGetAllMatches (
if (matchLength > bestLength) {
DEBUGLOG(8, "found match of length %u at distance %u (offCode=%u)",
- (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
+ (U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
assert(matchEndIdx > matchIndex);
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
bestLength = matchLength;
- matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
+ matches[mnum].off = STORE_OFFSET(curr - matchIndex);
matches[mnum].len = (U32)matchLength;
mnum++;
if ( (matchLength > ZSTD_OPT_NUM)
| (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {
if (dictMode == ZSTD_dictMatchState) nbCompares = 0; /* break should also skip searching dms */
break; /* drop, to preserve bt consistency (miss a little bit of compression) */
- }
- }
+ } }
if (match[matchLength] < ip[matchLength]) {
/* match smaller than current */
@@ -692,12 +738,13 @@ U32 ZSTD_insertBtAndGetAllMatches (
*smallerPtr = *largerPtr = 0;
+ assert(nbCompares <= (1U << ZSTD_SEARCHLOG_MAX)); /* Check we haven't underflowed. */
if (dictMode == ZSTD_dictMatchState && nbCompares) {
size_t const dmsH = ZSTD_hashPtr(ip, dmsHashLog, mls);
U32 dictMatchIndex = dms->hashTable[dmsH];
const U32* const dmsBt = dms->chainTable;
commonLengthSmaller = commonLengthLarger = 0;
- while (nbCompares-- && (dictMatchIndex > dmsLowLimit)) {
+ for (; nbCompares && (dictMatchIndex > dmsLowLimit); --nbCompares) {
const U32* const nextPtr = dmsBt + 2*(dictMatchIndex & dmsBtMask);
size_t matchLength = MIN(commonLengthSmaller, commonLengthLarger); /* guaranteed minimum nb of common bytes */
const BYTE* match = dmsBase + dictMatchIndex;
@@ -708,18 +755,17 @@ U32 ZSTD_insertBtAndGetAllMatches (
if (matchLength > bestLength) {
matchIndex = dictMatchIndex + dmsIndexDelta;
DEBUGLOG(8, "found dms match of length %u at distance %u (offCode=%u)",
- (U32)matchLength, curr - matchIndex, curr - matchIndex + ZSTD_REP_MOVE);
+ (U32)matchLength, curr - matchIndex, STORE_OFFSET(curr - matchIndex));
if (matchLength > matchEndIdx - matchIndex)
matchEndIdx = matchIndex + (U32)matchLength;
bestLength = matchLength;
- matches[mnum].off = (curr - matchIndex) + ZSTD_REP_MOVE;
+ matches[mnum].off = STORE_OFFSET(curr - matchIndex);
matches[mnum].len = (U32)matchLength;
mnum++;
if ( (matchLength > ZSTD_OPT_NUM)
| (ip+matchLength == iLimit) /* equal : no way to know if inf or sup */) {
break; /* drop, to guarantee consistency (miss a little bit of compression) */
- }
- }
+ } }
if (dictMatchIndex <= dmsBtLow) { break; } /* beyond tree size, stop the search */
if (match[matchLength] < ip[matchLength]) {
@@ -729,39 +775,91 @@ U32 ZSTD_insertBtAndGetAllMatches (
/* match is larger than current */
commonLengthLarger = matchLength;
dictMatchIndex = nextPtr[0];
- }
- }
- }
+ } } } /* if (dictMode == ZSTD_dictMatchState) */
assert(matchEndIdx > curr+8);
ms->nextToUpdate = matchEndIdx - 8; /* skip repetitive patterns */
return mnum;
}
-
-FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
- ZSTD_match_t* matches, /* store result (match found, increasing size) in this table */
- ZSTD_matchState_t* ms,
- U32* nextToUpdate3,
- const BYTE* ip, const BYTE* const iHighLimit, const ZSTD_dictMode_e dictMode,
- const U32 rep[ZSTD_REP_NUM],
- U32 const ll0,
- U32 const lengthToBeat)
+typedef U32 (*ZSTD_getAllMatchesFn)(
+ ZSTD_match_t*,
+ ZSTD_matchState_t*,
+ U32*,
+ const BYTE*,
+ const BYTE*,
+ const U32 rep[ZSTD_REP_NUM],
+ U32 const ll0,
+ U32 const lengthToBeat);
+
+FORCE_INLINE_TEMPLATE U32 ZSTD_btGetAllMatches_internal(
+ ZSTD_match_t* matches,
+ ZSTD_matchState_t* ms,
+ U32* nextToUpdate3,
+ const BYTE* ip,
+ const BYTE* const iHighLimit,
+ const U32 rep[ZSTD_REP_NUM],
+ U32 const ll0,
+ U32 const lengthToBeat,
+ const ZSTD_dictMode_e dictMode,
+ const U32 mls)
{
- const ZSTD_compressionParameters* const cParams = &ms->cParams;
- U32 const matchLengthSearch = cParams->minMatch;
- DEBUGLOG(8, "ZSTD_BtGetAllMatches");
- if (ip < ms->window.base + ms->nextToUpdate) return 0; /* skipped area */
- ZSTD_updateTree_internal(ms, ip, iHighLimit, matchLengthSearch, dictMode);
- switch(matchLengthSearch)
- {
- case 3 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 3);
- default :
- case 4 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 4);
- case 5 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 5);
- case 7 :
- case 6 : return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, 6);
+ assert(BOUNDED(3, ms->cParams.minMatch, 6) == mls);
+ DEBUGLOG(8, "ZSTD_BtGetAllMatches(dictMode=%d, mls=%u)", (int)dictMode, mls);
+ if (ip < ms->window.base + ms->nextToUpdate)
+ return 0; /* skipped area */
+ ZSTD_updateTree_internal(ms, ip, iHighLimit, mls, dictMode);
+ return ZSTD_insertBtAndGetAllMatches(matches, ms, nextToUpdate3, ip, iHighLimit, dictMode, rep, ll0, lengthToBeat, mls);
+}
+
+#define ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls) ZSTD_btGetAllMatches_##dictMode##_##mls
+
+#define GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, mls) \
+ static U32 ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, mls)( \
+ ZSTD_match_t* matches, \
+ ZSTD_matchState_t* ms, \
+ U32* nextToUpdate3, \
+ const BYTE* ip, \
+ const BYTE* const iHighLimit, \
+ const U32 rep[ZSTD_REP_NUM], \
+ U32 const ll0, \
+ U32 const lengthToBeat) \
+ { \
+ return ZSTD_btGetAllMatches_internal( \
+ matches, ms, nextToUpdate3, ip, iHighLimit, \
+ rep, ll0, lengthToBeat, ZSTD_##dictMode, mls); \
+ }
+
+#define GEN_ZSTD_BT_GET_ALL_MATCHES(dictMode) \
+ GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 3) \
+ GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 4) \
+ GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 5) \
+ GEN_ZSTD_BT_GET_ALL_MATCHES_(dictMode, 6)
+
+GEN_ZSTD_BT_GET_ALL_MATCHES(noDict)
+GEN_ZSTD_BT_GET_ALL_MATCHES(extDict)
+GEN_ZSTD_BT_GET_ALL_MATCHES(dictMatchState)
+
+#define ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMode) \
+ { \
+ ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 3), \
+ ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 4), \
+ ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 5), \
+ ZSTD_BT_GET_ALL_MATCHES_FN(dictMode, 6) \
}
+
+static ZSTD_getAllMatchesFn
+ZSTD_selectBtGetAllMatches(ZSTD_matchState_t const* ms, ZSTD_dictMode_e const dictMode)
+{
+ ZSTD_getAllMatchesFn const getAllMatchesFns[3][4] = {
+ ZSTD_BT_GET_ALL_MATCHES_ARRAY(noDict),
+ ZSTD_BT_GET_ALL_MATCHES_ARRAY(extDict),
+ ZSTD_BT_GET_ALL_MATCHES_ARRAY(dictMatchState)
+ };
+ U32 const mls = BOUNDED(3, ms->cParams.minMatch, 6);
+ assert((U32)dictMode < 3);
+ assert(mls - 3 < 4);
+ return getAllMatchesFns[(int)dictMode][mls - 3];
}
/*************************
@@ -770,16 +868,18 @@ FORCE_INLINE_TEMPLATE U32 ZSTD_BtGetAllMatches (
/* Struct containing info needed to make decision about ldm inclusion */
typedef struct {
- rawSeqStore_t seqStore; /* External match candidates store for this block */
- U32 startPosInBlock; /* Start position of the current match candidate */
- U32 endPosInBlock; /* End position of the current match candidate */
- U32 offset; /* Offset of the match candidate */
+ rawSeqStore_t seqStore; /* External match candidates store for this block */
+ U32 startPosInBlock; /* Start position of the current match candidate */
+ U32 endPosInBlock; /* End position of the current match candidate */
+ U32 offset; /* Offset of the match candidate */
} ZSTD_optLdm_t;
/* ZSTD_optLdm_skipRawSeqStoreBytes():
- * Moves forward in rawSeqStore by nbBytes, which will update the fields 'pos' and 'posInSequence'.
+ * Moves forward in @rawSeqStore by @nbBytes,
+ * which will update the fields 'pos' and 'posInSequence'.
*/
-static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes) {
+static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t nbBytes)
+{
U32 currPos = (U32)(rawSeqStore->posInSequence + nbBytes);
while (currPos && rawSeqStore->pos < rawSeqStore->size) {
rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos];
@@ -800,8 +900,10 @@ static void ZSTD_optLdm_skipRawSeqStoreBytes(rawSeqStore_t* rawSeqStore, size_t
* Calculates the beginning and end of the next match in the current block.
* Updates 'pos' and 'posInSequence' of the ldmSeqStore.
*/
-static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
- U32 blockBytesRemaining) {
+static void
+ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 currPosInBlock,
+ U32 blockBytesRemaining)
+{
rawSeq currSeq;
U32 currBlockEndPos;
U32 literalsBytesRemaining;
@@ -813,8 +915,8 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
optLdm->endPosInBlock = UINT_MAX;
return;
}
- /* Calculate appropriate bytes left in matchLength and litLength after adjusting
- based on ldmSeqStore->posInSequence */
+ /* Calculate appropriate bytes left in matchLength and litLength
+ * after adjusting based on ldmSeqStore->posInSequence */
currSeq = optLdm->seqStore.seq[optLdm->seqStore.pos];
assert(optLdm->seqStore.posInSequence <= currSeq.litLength + currSeq.matchLength);
currBlockEndPos = currPosInBlock + blockBytesRemaining;
@@ -850,15 +952,16 @@ static void ZSTD_opt_getNextMatchAndUpdateSeqStore(ZSTD_optLdm_t* optLdm, U32 cu
}
/* ZSTD_optLdm_maybeAddMatch():
- * Adds a match if it's long enough, based on it's 'matchStartPosInBlock'
- * and 'matchEndPosInBlock', into 'matches'. Maintains the correct ordering of 'matches'
+ * Adds a match if it's long enough,
+ * based on it's 'matchStartPosInBlock' and 'matchEndPosInBlock',
+ * into 'matches'. Maintains the correct ordering of 'matches'.
*/
static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
- ZSTD_optLdm_t* optLdm, U32 currPosInBlock) {
- U32 posDiff = currPosInBlock - optLdm->startPosInBlock;
+ const ZSTD_optLdm_t* optLdm, U32 currPosInBlock)
+{
+ U32 const posDiff = currPosInBlock - optLdm->startPosInBlock;
/* Note: ZSTD_match_t actually contains offCode and matchLength (before subtracting MINMATCH) */
- U32 candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
- U32 candidateOffCode = optLdm->offset + ZSTD_REP_MOVE;
+ U32 const candidateMatchLength = optLdm->endPosInBlock - optLdm->startPosInBlock - posDiff;
/* Ensure that current block position is not outside of the match */
if (currPosInBlock < optLdm->startPosInBlock
@@ -868,6 +971,7 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
}
if (*nbMatches == 0 || ((candidateMatchLength > matches[*nbMatches-1].len) && *nbMatches < ZSTD_OPT_NUM)) {
+ U32 const candidateOffCode = STORE_OFFSET(optLdm->offset);
DEBUGLOG(6, "ZSTD_optLdm_maybeAddMatch(): Adding ldm candidate match (offCode: %u matchLength %u) at block position=%u",
candidateOffCode, candidateMatchLength, currPosInBlock);
matches[*nbMatches].len = candidateMatchLength;
@@ -879,8 +983,11 @@ static void ZSTD_optLdm_maybeAddMatch(ZSTD_match_t* matches, U32* nbMatches,
/* ZSTD_optLdm_processMatchCandidate():
* Wrapper function to update ldm seq store and call ldm functions as necessary.
*/
-static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_t* matches, U32* nbMatches,
- U32 currPosInBlock, U32 remainingBytes) {
+static void
+ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm,
+ ZSTD_match_t* matches, U32* nbMatches,
+ U32 currPosInBlock, U32 remainingBytes)
+{
if (optLdm->seqStore.size == 0 || optLdm->seqStore.pos >= optLdm->seqStore.size) {
return;
}
@@ -891,19 +998,19 @@ static void ZSTD_optLdm_processMatchCandidate(ZSTD_optLdm_t* optLdm, ZSTD_match_
* at the end of a match from the ldm seq store, and will often be some bytes
* over beyond matchEndPosInBlock. As such, we need to correct for these "overshoots"
*/
- U32 posOvershoot = currPosInBlock - optLdm->endPosInBlock;
+ U32 const posOvershoot = currPosInBlock - optLdm->endPosInBlock;
ZSTD_optLdm_skipRawSeqStoreBytes(&optLdm->seqStore, posOvershoot);
- }
+ }
ZSTD_opt_getNextMatchAndUpdateSeqStore(optLdm, currPosInBlock, remainingBytes);
}
ZSTD_optLdm_maybeAddMatch(matches, nbMatches, optLdm, currPosInBlock);
}
+
/*-*******************************
* Optimal parser
*********************************/
-
static U32 ZSTD_totalLen(ZSTD_optimal_t sol)
{
return sol.litlen + sol.mlen;
@@ -944,6 +1051,8 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
const BYTE* const prefixStart = base + ms->window.dictLimit;
const ZSTD_compressionParameters* const cParams = &ms->cParams;
+ ZSTD_getAllMatchesFn getAllMatches = ZSTD_selectBtGetAllMatches(ms, dictMode);
+
U32 const sufficient_len = MIN(cParams->targetLength, ZSTD_OPT_NUM -1);
U32 const minMatch = (cParams->minMatch == 3) ? 3 : 4;
U32 nextToUpdate3 = ms->nextToUpdate;
@@ -971,7 +1080,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* find first match */
{ U32 const litlen = (U32)(ip - anchor);
U32 const ll0 = !litlen;
- U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, ip, iend, dictMode, rep, ll0, minMatch);
+ U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, ip, iend, rep, ll0, minMatch);
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
(U32)(ip-istart), (U32)(iend - ip));
if (!nbMatches) { ip++; continue; }
@@ -985,18 +1094,18 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
* in every price. We include the literal length to avoid negative
* prices when we subtract the previous literal length.
*/
- opt[0].price = ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
+ opt[0].price = (int)ZSTD_litLengthPrice(litlen, optStatePtr, optLevel);
/* large match -> immediate encoding */
{ U32 const maxML = matches[nbMatches-1].len;
- U32 const maxOffset = matches[nbMatches-1].off;
+ U32 const maxOffcode = matches[nbMatches-1].off;
DEBUGLOG(6, "found %u matches of maxLength=%u and maxOffCode=%u at cPos=%u => start new series",
- nbMatches, maxML, maxOffset, (U32)(ip-prefixStart));
+ nbMatches, maxML, maxOffcode, (U32)(ip-prefixStart));
if (maxML > sufficient_len) {
lastSequence.litlen = litlen;
lastSequence.mlen = maxML;
- lastSequence.off = maxOffset;
+ lastSequence.off = maxOffcode;
DEBUGLOG(6, "large match (%u>%u), immediate encoding",
maxML, sufficient_len);
cur = 0;
@@ -1005,24 +1114,25 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
} }
/* set prices for first matches starting position == 0 */
- { U32 const literalsPrice = opt[0].price + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
+ assert(opt[0].price >= 0);
+ { U32 const literalsPrice = (U32)opt[0].price + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
U32 pos;
U32 matchNb;
for (pos = 1; pos < minMatch; pos++) {
opt[pos].price = ZSTD_MAX_PRICE; /* mlen, litlen and price will be fixed during forward scanning */
}
for (matchNb = 0; matchNb < nbMatches; matchNb++) {
- U32 const offset = matches[matchNb].off;
+ U32 const offcode = matches[matchNb].off;
U32 const end = matches[matchNb].len;
for ( ; pos <= end ; pos++ ) {
- U32 const matchPrice = ZSTD_getMatchPrice(offset, pos, optStatePtr, optLevel);
+ U32 const matchPrice = ZSTD_getMatchPrice(offcode, pos, optStatePtr, optLevel);
U32 const sequencePrice = literalsPrice + matchPrice;
DEBUGLOG(7, "rPos:%u => set initial price : %.2f",
pos, ZSTD_fCost(sequencePrice));
opt[pos].mlen = pos;
- opt[pos].off = offset;
+ opt[pos].off = offcode;
opt[pos].litlen = litlen;
- opt[pos].price = sequencePrice;
+ opt[pos].price = (int)sequencePrice;
} }
last_pos = pos-1;
}
@@ -1037,9 +1147,9 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
/* Fix current position with one literal if cheaper */
{ U32 const litlen = (opt[cur-1].mlen == 0) ? opt[cur-1].litlen + 1 : 1;
int const price = opt[cur-1].price
- + ZSTD_rawLiteralsCost(ip+cur-1, 1, optStatePtr, optLevel)
- + ZSTD_litLengthPrice(litlen, optStatePtr, optLevel)
- - ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel);
+ + (int)ZSTD_rawLiteralsCost(ip+cur-1, 1, optStatePtr, optLevel)
+ + (int)ZSTD_litLengthPrice(litlen, optStatePtr, optLevel)
+ - (int)ZSTD_litLengthPrice(litlen-1, optStatePtr, optLevel);
assert(price < 1000000000); /* overflow check */
if (price <= opt[cur].price) {
DEBUGLOG(7, "cPos:%zi==rPos:%u : better price (%.2f<=%.2f) using literal (ll==%u) (hist:%u,%u,%u)",
@@ -1065,7 +1175,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
assert(cur >= opt[cur].mlen);
if (opt[cur].mlen != 0) {
U32 const prev = cur - opt[cur].mlen;
- repcodes_t newReps = ZSTD_updateRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
+ repcodes_t const newReps = ZSTD_newRep(opt[prev].rep, opt[cur].off, opt[cur].litlen==0);
ZSTD_memcpy(opt[cur].rep, &newReps, sizeof(repcodes_t));
} else {
ZSTD_memcpy(opt[cur].rep, opt[cur - 1].rep, sizeof(repcodes_t));
@@ -1082,11 +1192,12 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
continue; /* skip unpromising positions; about ~+6% speed, -0.01 ratio */
}
+ assert(opt[cur].price >= 0);
{ U32 const ll0 = (opt[cur].mlen != 0);
U32 const litlen = (opt[cur].mlen == 0) ? opt[cur].litlen : 0;
- U32 const previousPrice = opt[cur].price;
+ U32 const previousPrice = (U32)opt[cur].price;
U32 const basePrice = previousPrice + ZSTD_litLengthPrice(0, optStatePtr, optLevel);
- U32 nbMatches = ZSTD_BtGetAllMatches(matches, ms, &nextToUpdate3, inr, iend, dictMode, opt[cur].rep, ll0, minMatch);
+ U32 nbMatches = getAllMatches(matches, ms, &nextToUpdate3, inr, iend, opt[cur].rep, ll0, minMatch);
U32 matchNb;
ZSTD_optLdm_processMatchCandidate(&optLdm, matches, &nbMatches,
@@ -1124,7 +1235,7 @@ ZSTD_compressBlock_opt_generic(ZSTD_matchState_t* ms,
for (mlen = lastML; mlen >= startML; mlen--) { /* scan downward */
U32 const pos = cur + mlen;
- int const price = basePrice + ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
+ int const price = (int)basePrice + (int)ZSTD_getMatchPrice(offset, mlen, optStatePtr, optLevel);
if ((pos > last_pos) || (price < opt[pos].price)) {
DEBUGLOG(7, "rPos:%u (ml=%2u) => new better price (%.2f<%.2f)",
@@ -1154,7 +1265,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
* update them while traversing the sequences.
*/
if (lastSequence.mlen != 0) {
- repcodes_t reps = ZSTD_updateRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
+ repcodes_t const reps = ZSTD_newRep(opt[cur].rep, lastSequence.off, lastSequence.litlen==0);
ZSTD_memcpy(rep, &reps, sizeof(reps));
} else {
ZSTD_memcpy(rep, opt[cur].rep, sizeof(repcodes_t));
@@ -1198,7 +1309,7 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
assert(anchor + llen <= iend);
ZSTD_updateStats(optStatePtr, llen, anchor, offCode, mlen);
- ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen-MINMATCH);
+ ZSTD_storeSeq(seqStore, llen, anchor, iend, offCode, mlen);
anchor += advance;
ip = anchor;
} }
@@ -1210,38 +1321,30 @@ _shortestPath: /* cur, last_pos, best_mlen, best_off have to be set */
return (size_t)(iend - anchor);
}
+static size_t ZSTD_compressBlock_opt0(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)
+{
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /* optLevel */, dictMode);
+}
+
+static size_t ZSTD_compressBlock_opt2(
+ ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
+ const void* src, size_t srcSize, const ZSTD_dictMode_e dictMode)
+{
+ return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /* optLevel */, dictMode);
+}
size_t ZSTD_compressBlock_btopt(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
DEBUGLOG(5, "ZSTD_compressBlock_btopt");
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_noDict);
+ return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
}
-/* used in 2-pass strategy */
-static U32 ZSTD_upscaleStat(unsigned* table, U32 lastEltIndex, int bonus)
-{
- U32 s, sum=0;
- assert(ZSTD_FREQ_DIV+bonus >= 0);
- for (s=0; s<lastEltIndex+1; s++) {
- table[s] <<= ZSTD_FREQ_DIV+bonus;
- table[s]--;
- sum += table[s];
- }
- return sum;
-}
-/* used in 2-pass strategy */
-MEM_STATIC void ZSTD_upscaleStats(optState_t* optPtr)
-{
- if (ZSTD_compressedLiterals(optPtr))
- optPtr->litSum = ZSTD_upscaleStat(optPtr->litFreq, MaxLit, 0);
- optPtr->litLengthSum = ZSTD_upscaleStat(optPtr->litLengthFreq, MaxLL, 0);
- optPtr->matchLengthSum = ZSTD_upscaleStat(optPtr->matchLengthFreq, MaxML, 0);
- optPtr->offCodeSum = ZSTD_upscaleStat(optPtr->offCodeFreq, MaxOff, 0);
-}
/* ZSTD_initStats_ultra():
* make a first compression pass, just to seed stats with more accurate starting values.
@@ -1263,7 +1366,7 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
assert(ms->window.dictLimit == ms->window.lowLimit); /* no dictionary */
assert(ms->window.dictLimit - ms->nextToUpdate <= 1); /* no prefix (note: intentional overflow, defined as 2-complement) */
- ZSTD_compressBlock_opt_generic(ms, seqStore, tmpRep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict); /* generate stats into ms->opt*/
+ ZSTD_compressBlock_opt2(ms, seqStore, tmpRep, src, srcSize, ZSTD_noDict); /* generate stats into ms->opt*/
/* invalidate first scan from history */
ZSTD_resetSeqStore(seqStore);
@@ -1272,8 +1375,6 @@ ZSTD_initStats_ultra(ZSTD_matchState_t* ms,
ms->window.lowLimit = ms->window.dictLimit;
ms->nextToUpdate = ms->window.dictLimit;
- /* re-inforce weight of collected statistics */
- ZSTD_upscaleStats(&ms->opt);
}
size_t ZSTD_compressBlock_btultra(
@@ -1281,7 +1382,7 @@ size_t ZSTD_compressBlock_btultra(
const void* src, size_t srcSize)
{
DEBUGLOG(5, "ZSTD_compressBlock_btultra (srcSize=%zu)", srcSize);
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
+ return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
}
size_t ZSTD_compressBlock_btultra2(
@@ -1309,35 +1410,35 @@ size_t ZSTD_compressBlock_btultra2(
ZSTD_initStats_ultra(ms, seqStore, rep, src, srcSize);
}
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_noDict);
+ return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_noDict);
}
size_t ZSTD_compressBlock_btopt_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);
}
size_t ZSTD_compressBlock_btultra_dictMatchState(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_dictMatchState);
+ return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_dictMatchState);
}
size_t ZSTD_compressBlock_btopt_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 0 /*optLevel*/, ZSTD_extDict);
+ return ZSTD_compressBlock_opt0(ms, seqStore, rep, src, srcSize, ZSTD_extDict);
}
size_t ZSTD_compressBlock_btultra_extDict(
ZSTD_matchState_t* ms, seqStore_t* seqStore, U32 rep[ZSTD_REP_NUM],
const void* src, size_t srcSize)
{
- return ZSTD_compressBlock_opt_generic(ms, seqStore, rep, src, srcSize, 2 /*optLevel*/, ZSTD_extDict);
+ return ZSTD_compressBlock_opt2(ms, seqStore, rep, src, srcSize, ZSTD_extDict);
}
/* note : no btultra2 variant for extDict nor dictMatchState,
diff --git a/thirdparty/zstd/compress/zstdmt_compress.c b/thirdparty/zstd/compress/zstdmt_compress.c
index 22aa3e1245..6bc14b035e 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.c
+++ b/thirdparty/zstd/compress/zstdmt_compress.c
@@ -102,9 +102,8 @@ typedef struct ZSTDMT_bufferPool_s {
buffer_t bTable[1]; /* variable size */
} ZSTDMT_bufferPool;
-static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned nbWorkers, ZSTD_customMem cMem)
+static ZSTDMT_bufferPool* ZSTDMT_createBufferPool(unsigned maxNbBuffers, ZSTD_customMem cMem)
{
- unsigned const maxNbBuffers = 2*nbWorkers + 3;
ZSTDMT_bufferPool* const bufPool = (ZSTDMT_bufferPool*)ZSTD_customCalloc(
sizeof(ZSTDMT_bufferPool) + (maxNbBuffers-1) * sizeof(buffer_t), cMem);
if (bufPool==NULL) return NULL;
@@ -160,9 +159,8 @@ static void ZSTDMT_setBufferSize(ZSTDMT_bufferPool* const bufPool, size_t const
}
-static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, U32 nbWorkers)
+static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool, unsigned maxNbBuffers)
{
- unsigned const maxNbBuffers = 2*nbWorkers + 3;
if (srcBufPool==NULL) return NULL;
if (srcBufPool->totalBuffers >= maxNbBuffers) /* good enough */
return srcBufPool;
@@ -171,7 +169,7 @@ static ZSTDMT_bufferPool* ZSTDMT_expandBufferPool(ZSTDMT_bufferPool* srcBufPool,
size_t const bSize = srcBufPool->bufferSize; /* forward parameters */
ZSTDMT_bufferPool* newBufPool;
ZSTDMT_freeBufferPool(srcBufPool);
- newBufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ newBufPool = ZSTDMT_createBufferPool(maxNbBuffers, cMem);
if (newBufPool==NULL) return newBufPool;
ZSTDMT_setBufferSize(newBufPool, bSize);
return newBufPool;
@@ -263,6 +261,16 @@ static void ZSTDMT_releaseBuffer(ZSTDMT_bufferPool* bufPool, buffer_t buf)
ZSTD_customFree(buf.start, bufPool->cMem);
}
+/* We need 2 output buffers per worker since each dstBuff must be flushed after it is released.
+ * The 3 additional buffers are as follows:
+ * 1 buffer for input loading
+ * 1 buffer for "next input" when submitting current one
+ * 1 buffer stuck in queue */
+#define BUF_POOL_MAX_NB_BUFFERS(nbWorkers) 2*nbWorkers + 3
+
+/* After a worker releases its rawSeqStore, it is immediately ready for reuse.
+ * So we only need one seq buffer per worker. */
+#define SEQ_POOL_MAX_NB_BUFFERS(nbWorkers) nbWorkers
/* ===== Seq Pool Wrapper ====== */
@@ -316,7 +324,7 @@ static void ZSTDMT_setNbSeq(ZSTDMT_seqPool* const seqPool, size_t const nbSeq)
static ZSTDMT_seqPool* ZSTDMT_createSeqPool(unsigned nbWorkers, ZSTD_customMem cMem)
{
- ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ ZSTDMT_seqPool* const seqPool = ZSTDMT_createBufferPool(SEQ_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
if (seqPool == NULL) return NULL;
ZSTDMT_setNbSeq(seqPool, 0);
return seqPool;
@@ -329,7 +337,7 @@ static void ZSTDMT_freeSeqPool(ZSTDMT_seqPool* seqPool)
static ZSTDMT_seqPool* ZSTDMT_expandSeqPool(ZSTDMT_seqPool* pool, U32 nbWorkers)
{
- return ZSTDMT_expandBufferPool(pool, nbWorkers);
+ return ZSTDMT_expandBufferPool(pool, SEQ_POOL_MAX_NB_BUFFERS(nbWorkers));
}
@@ -467,7 +475,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
ZSTD_dictContentType_e dictContentType)
{
/* Adjust parameters */
- if (params.ldmParams.enableLdm) {
+ if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
DEBUGLOG(4, "LDM window size = %u KB", (1U << params.cParams.windowLog) >> 10);
ZSTD_ldm_adjustParameters(&params.ldmParams, &params.cParams);
assert(params.ldmParams.hashLog >= params.ldmParams.bucketSizeLog);
@@ -478,7 +486,7 @@ ZSTDMT_serialState_reset(serialState_t* serialState,
serialState->nextJobID = 0;
if (params.fParams.checksumFlag)
XXH64_reset(&serialState->xxhState, 0);
- if (params.ldmParams.enableLdm) {
+ if (params.ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_customMem cMem = params.customMem;
unsigned const hashLog = params.ldmParams.hashLog;
size_t const hashSize = ((size_t)1 << hashLog) * sizeof(ldmEntry_t);
@@ -564,7 +572,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
/* A future job may error and skip our job */
if (serialState->nextJobID == jobID) {
/* It is now our turn, do any processing necessary */
- if (serialState->params.ldmParams.enableLdm) {
+ if (serialState->params.ldmParams.enableLdm == ZSTD_ps_enable) {
size_t error;
assert(seqStore.seq != NULL && seqStore.pos == 0 &&
seqStore.size == 0 && seqStore.capacity > 0);
@@ -594,7 +602,7 @@ static void ZSTDMT_serialState_update(serialState_t* serialState,
if (seqStore.size > 0) {
size_t const err = ZSTD_referenceExternalSequences(
jobCCtx, seqStore.seq, seqStore.size);
- assert(serialState->params.ldmParams.enableLdm);
+ assert(serialState->params.ldmParams.enableLdm == ZSTD_ps_enable);
assert(!ZSTD_isError(err));
(void)err;
}
@@ -672,7 +680,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
if (dstBuff.start==NULL) JOB_ERROR(ERROR(memory_allocation));
job->dstBuff = dstBuff; /* this value can be read in ZSTDMT_flush, when it copies the whole job */
}
- if (jobParams.ldmParams.enableLdm && rawSeqStore.seq == NULL)
+ if (jobParams.ldmParams.enableLdm == ZSTD_ps_enable && rawSeqStore.seq == NULL)
JOB_ERROR(ERROR(memory_allocation));
/* Don't compute the checksum for chunks, since we compute it externally,
@@ -680,7 +688,7 @@ static void ZSTDMT_compressionJob(void* jobDescription)
*/
if (job->jobID != 0) jobParams.fParams.checksumFlag = 0;
/* Don't run LDM for the chunks, since we handle it externally */
- jobParams.ldmParams.enableLdm = 0;
+ jobParams.ldmParams.enableLdm = ZSTD_ps_disable;
/* Correct nbWorkers to 0. */
jobParams.nbWorkers = 0;
@@ -807,6 +815,15 @@ typedef struct {
static const roundBuff_t kNullRoundBuff = {NULL, 0, 0};
#define RSYNC_LENGTH 32
+/* Don't create chunks smaller than the zstd block size.
+ * This stops us from regressing compression ratio too much,
+ * and ensures our output fits in ZSTD_compressBound().
+ *
+ * If this is shrunk < ZSTD_BLOCKSIZELOG_MIN then
+ * ZSTD_COMPRESSBOUND() will need to be updated.
+ */
+#define RSYNC_MIN_BLOCK_LOG ZSTD_BLOCKSIZELOG_MAX
+#define RSYNC_MIN_BLOCK_SIZE (1<<RSYNC_MIN_BLOCK_LOG)
typedef struct {
U64 hash;
@@ -927,7 +944,7 @@ MEM_STATIC ZSTDMT_CCtx* ZSTDMT_createCCtx_advanced_internal(unsigned nbWorkers,
mtctx->jobs = ZSTDMT_createJobsTable(&nbJobs, cMem);
assert(nbJobs > 0); assert((nbJobs & (nbJobs - 1)) == 0); /* ensure nbJobs is a power of 2 */
mtctx->jobIDMask = nbJobs - 1;
- mtctx->bufPool = ZSTDMT_createBufferPool(nbWorkers, cMem);
+ mtctx->bufPool = ZSTDMT_createBufferPool(BUF_POOL_MAX_NB_BUFFERS(nbWorkers), cMem);
mtctx->cctxPool = ZSTDMT_createCCtxPool(nbWorkers, cMem);
mtctx->seqPool = ZSTDMT_createSeqPool(nbWorkers, cMem);
initError = ZSTDMT_serialState_init(&mtctx->serial);
@@ -1030,7 +1047,7 @@ static size_t ZSTDMT_resize(ZSTDMT_CCtx* mtctx, unsigned nbWorkers)
{
if (POOL_resize(mtctx->factory, nbWorkers)) return ERROR(memory_allocation);
FORWARD_IF_ERROR( ZSTDMT_expandJobsTable(mtctx, nbWorkers) , "");
- mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, nbWorkers);
+ mtctx->bufPool = ZSTDMT_expandBufferPool(mtctx->bufPool, BUF_POOL_MAX_NB_BUFFERS(nbWorkers));
if (mtctx->bufPool == NULL) return ERROR(memory_allocation);
mtctx->cctxPool = ZSTDMT_expandCCtxPool(mtctx->cctxPool, nbWorkers);
if (mtctx->cctxPool == NULL) return ERROR(memory_allocation);
@@ -1135,7 +1152,7 @@ size_t ZSTDMT_toFlushNow(ZSTDMT_CCtx* mtctx)
static unsigned ZSTDMT_computeTargetJobLog(const ZSTD_CCtx_params* params)
{
unsigned jobLog;
- if (params->ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
/* In Long Range Mode, the windowLog is typically oversized.
* In which case, it's preferable to determine the jobSize
* based on cycleLog instead. */
@@ -1179,7 +1196,7 @@ static size_t ZSTDMT_computeOverlapSize(const ZSTD_CCtx_params* params)
int const overlapRLog = 9 - ZSTDMT_overlapLog(params->overlapLog, params->cParams.strategy);
int ovLog = (overlapRLog >= 8) ? 0 : (params->cParams.windowLog - overlapRLog);
assert(0 <= overlapRLog && overlapRLog <= 8);
- if (params->ldmParams.enableLdm) {
+ if (params->ldmParams.enableLdm == ZSTD_ps_enable) {
/* In Long Range Mode, the windowLog is typically oversized.
* In which case, it's preferable to determine the jobSize
* based on chainLog instead.
@@ -1252,6 +1269,9 @@ size_t ZSTDMT_initCStream_internal(
/* Aim for the targetsectionSize as the average job size. */
U32 const jobSizeKB = (U32)(mtctx->targetSectionSize >> 10);
U32 const rsyncBits = (assert(jobSizeKB >= 1), ZSTD_highbit32(jobSizeKB) + 10);
+ /* We refuse to create jobs < RSYNC_MIN_BLOCK_SIZE bytes, so make sure our
+ * expected job size is at least 4x larger. */
+ assert(rsyncBits >= RSYNC_MIN_BLOCK_LOG + 2);
DEBUGLOG(4, "rsyncLog = %u", rsyncBits);
mtctx->rsync.hash = 0;
mtctx->rsync.hitMask = (1ULL << rsyncBits) - 1;
@@ -1263,7 +1283,7 @@ size_t ZSTDMT_initCStream_internal(
ZSTDMT_setBufferSize(mtctx->bufPool, ZSTD_compressBound(mtctx->targetSectionSize));
{
/* If ldm is enabled we need windowSize space. */
- size_t const windowSize = mtctx->params.ldmParams.enableLdm ? (1U << mtctx->params.cParams.windowLog) : 0;
+ size_t const windowSize = mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable ? (1U << mtctx->params.cParams.windowLog) : 0;
/* Two buffers of slack, plus extra space for the overlap
* This is the minimum slack that LDM works with. One extra because
* flush might waste up to targetSectionSize-1 bytes. Another extra
@@ -1538,17 +1558,21 @@ static range_t ZSTDMT_getInputDataInUse(ZSTDMT_CCtx* mtctx)
static int ZSTDMT_isOverlapped(buffer_t buffer, range_t range)
{
BYTE const* const bufferStart = (BYTE const*)buffer.start;
- BYTE const* const bufferEnd = bufferStart + buffer.capacity;
BYTE const* const rangeStart = (BYTE const*)range.start;
- BYTE const* const rangeEnd = range.size != 0 ? rangeStart + range.size : rangeStart;
if (rangeStart == NULL || bufferStart == NULL)
return 0;
- /* Empty ranges cannot overlap */
- if (bufferStart == bufferEnd || rangeStart == rangeEnd)
- return 0;
- return bufferStart < rangeEnd && rangeStart < bufferEnd;
+ {
+ BYTE const* const bufferEnd = bufferStart + buffer.capacity;
+ BYTE const* const rangeEnd = rangeStart + range.size;
+
+ /* Empty ranges cannot overlap */
+ if (bufferStart == bufferEnd || rangeStart == rangeEnd)
+ return 0;
+
+ return bufferStart < rangeEnd && rangeStart < bufferEnd;
+ }
}
static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
@@ -1575,7 +1599,7 @@ static int ZSTDMT_doesOverlapWindow(buffer_t buffer, ZSTD_window_t window)
static void ZSTDMT_waitForLdmComplete(ZSTDMT_CCtx* mtctx, buffer_t buffer)
{
- if (mtctx->params.ldmParams.enableLdm) {
+ if (mtctx->params.ldmParams.enableLdm == ZSTD_ps_enable) {
ZSTD_pthread_mutex_t* mutex = &mtctx->serial.ldmWindowMutex;
DEBUGLOG(5, "ZSTDMT_waitForLdmComplete");
DEBUGLOG(5, "source [0x%zx, 0x%zx)",
@@ -1678,6 +1702,11 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
if (!mtctx->params.rsyncable)
/* Rsync is disabled. */
return syncPoint;
+ if (mtctx->inBuff.filled + input.size - input.pos < RSYNC_MIN_BLOCK_SIZE)
+ /* We don't emit synchronization points if it would produce too small blocks.
+ * We don't have enough input to find a synchronization point, so don't look.
+ */
+ return syncPoint;
if (mtctx->inBuff.filled + syncPoint.toLoad < RSYNC_LENGTH)
/* Not enough to compute the hash.
* We will miss any synchronization points in this RSYNC_LENGTH byte
@@ -1688,10 +1717,28 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
*/
return syncPoint;
/* Initialize the loop variables. */
- if (mtctx->inBuff.filled >= RSYNC_LENGTH) {
- /* We have enough bytes buffered to initialize the hash.
+ if (mtctx->inBuff.filled < RSYNC_MIN_BLOCK_SIZE) {
+ /* We don't need to scan the first RSYNC_MIN_BLOCK_SIZE positions
+ * because they can't possibly be a sync point. So we can start
+ * part way through the input buffer.
+ */
+ pos = RSYNC_MIN_BLOCK_SIZE - mtctx->inBuff.filled;
+ if (pos >= RSYNC_LENGTH) {
+ prev = istart + pos - RSYNC_LENGTH;
+ hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
+ } else {
+ assert(mtctx->inBuff.filled >= RSYNC_LENGTH);
+ prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
+ hash = ZSTD_rollingHash_compute(prev + pos, (RSYNC_LENGTH - pos));
+ hash = ZSTD_rollingHash_append(hash, istart, pos);
+ }
+ } else {
+ /* We have enough bytes buffered to initialize the hash,
+ * and are have processed enough bytes to find a sync point.
* Start scanning at the beginning of the input.
*/
+ assert(mtctx->inBuff.filled >= RSYNC_MIN_BLOCK_SIZE);
+ assert(RSYNC_MIN_BLOCK_SIZE >= RSYNC_LENGTH);
pos = 0;
prev = (BYTE const*)mtctx->inBuff.buffer.start + mtctx->inBuff.filled - RSYNC_LENGTH;
hash = ZSTD_rollingHash_compute(prev, RSYNC_LENGTH);
@@ -1705,16 +1752,6 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
syncPoint.flush = 1;
return syncPoint;
}
- } else {
- /* We don't have enough bytes buffered to initialize the hash, but
- * we know we have at least RSYNC_LENGTH bytes total.
- * Start scanning after the first RSYNC_LENGTH bytes less the bytes
- * already buffered.
- */
- pos = RSYNC_LENGTH - mtctx->inBuff.filled;
- prev = (BYTE const*)mtctx->inBuff.buffer.start - pos;
- hash = ZSTD_rollingHash_compute(mtctx->inBuff.buffer.start, mtctx->inBuff.filled);
- hash = ZSTD_rollingHash_append(hash, istart, pos);
}
/* Starting with the hash of the previous RSYNC_LENGTH bytes, roll
* through the input. If we hit a synchronization point, then cut the
@@ -1726,8 +1763,9 @@ findSynchronizationPoint(ZSTDMT_CCtx const* mtctx, ZSTD_inBuffer const input)
*/
for (; pos < syncPoint.toLoad; ++pos) {
BYTE const toRemove = pos < RSYNC_LENGTH ? prev[pos] : istart[pos - RSYNC_LENGTH];
- /* if (pos >= RSYNC_LENGTH) assert(ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash); */
+ assert(pos < RSYNC_LENGTH || ZSTD_rollingHash_compute(istart + pos - RSYNC_LENGTH, RSYNC_LENGTH) == hash);
hash = ZSTD_rollingHash_rotate(hash, toRemove, istart[pos], primePower);
+ assert(mtctx->inBuff.filled + pos >= RSYNC_MIN_BLOCK_SIZE);
if ((hash & hitMask) == hitMask) {
syncPoint.toLoad = pos + 1;
syncPoint.flush = 1;
diff --git a/thirdparty/zstd/compress/zstdmt_compress.h b/thirdparty/zstd/compress/zstdmt_compress.h
index 2fee2ec745..271eb1ac71 100644
--- a/thirdparty/zstd/compress/zstdmt_compress.h
+++ b/thirdparty/zstd/compress/zstdmt_compress.h
@@ -65,8 +65,11 @@ size_t ZSTDMT_nextInputSizeHint(const ZSTDMT_CCtx* mtctx);
* Private use only. Init streaming operation.
* expects params to be valid.
* must receive dict, or cdict, or none, but not both.
+ * mtctx can be freshly constructed or reused from a prior compression.
+ * If mtctx is reused, memory allocations from the prior compression may not be freed,
+ * even if they are not needed for the current compression.
* @return : 0, or an error code */
-size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* zcs,
+size_t ZSTDMT_initCStream_internal(ZSTDMT_CCtx* mtctx,
const void* dict, size_t dictSize, ZSTD_dictContentType_e dictContentType,
const ZSTD_CDict* cdict,
ZSTD_CCtx_params params, unsigned long long pledgedSrcSize);
diff --git a/thirdparty/zstd/decompress/huf_decompress.c b/thirdparty/zstd/decompress/huf_decompress.c
index b93c9a003b..2027188255 100644
--- a/thirdparty/zstd/decompress/huf_decompress.c
+++ b/thirdparty/zstd/decompress/huf_decompress.c
@@ -22,6 +22,13 @@
#define HUF_STATIC_LINKING_ONLY
#include "../common/huf.h"
#include "../common/error_private.h"
+#include "../common/zstd_internal.h"
+
+/* **************************************************************
+* Constants
+****************************************************************/
+
+#define HUF_DECODER_FAST_TABLELOG 11
/* **************************************************************
* Macros
@@ -36,6 +43,30 @@
#error "Cannot force the use of the X1 and X2 decoders at the same time!"
#endif
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && DYNAMIC_BMI2
+# define HUF_ASM_X86_64_BMI2_ATTRS BMI2_TARGET_ATTRIBUTE
+#else
+# define HUF_ASM_X86_64_BMI2_ATTRS
+#endif
+
+#ifdef __cplusplus
+# define HUF_EXTERN_C extern "C"
+#else
+# define HUF_EXTERN_C
+#endif
+#define HUF_ASM_DECL HUF_EXTERN_C
+
+#if DYNAMIC_BMI2 || (ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
+# define HUF_NEED_BMI2_FUNCTION 1
+#else
+# define HUF_NEED_BMI2_FUNCTION 0
+#endif
+
+#if !(ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__))
+# define HUF_NEED_DEFAULT_FUNCTION 1
+#else
+# define HUF_NEED_DEFAULT_FUNCTION 0
+#endif
/* **************************************************************
* Error Management
@@ -65,7 +96,7 @@
return fn##_body(dst, dstSize, cSrc, cSrcSize, DTable); \
} \
\
- static TARGET_ATTRIBUTE("bmi2") size_t fn##_bmi2( \
+ static BMI2_TARGET_ATTRIBUTE size_t fn##_bmi2( \
void* dst, size_t dstSize, \
const void* cSrc, size_t cSrcSize, \
const HUF_DTable* DTable) \
@@ -107,13 +138,147 @@ static DTableDesc HUF_getDTableDesc(const HUF_DTable* table)
return dtd;
}
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+static size_t HUF_initDStream(BYTE const* ip) {
+ BYTE const lastByte = ip[7];
+ size_t const bitsConsumed = lastByte ? 8 - BIT_highbit32(lastByte) : 0;
+ size_t const value = MEM_readLEST(ip) | 1;
+ assert(bitsConsumed <= 8);
+ return value << bitsConsumed;
+}
+typedef struct {
+ BYTE const* ip[4];
+ BYTE* op[4];
+ U64 bits[4];
+ void const* dt;
+ BYTE const* ilimit;
+ BYTE* oend;
+ BYTE const* iend[4];
+} HUF_DecompressAsmArgs;
+
+/**
+ * Initializes args for the asm decoding loop.
+ * @returns 0 on success
+ * 1 if the fallback implementation should be used.
+ * Or an error code on failure.
+ */
+static size_t HUF_DecompressAsmArgs_init(HUF_DecompressAsmArgs* args, void* dst, size_t dstSize, void const* src, size_t srcSize, const HUF_DTable* DTable)
+{
+ void const* dt = DTable + 1;
+ U32 const dtLog = HUF_getDTableDesc(DTable).tableLog;
+
+ const BYTE* const ilimit = (const BYTE*)src + 6 + 8;
+
+ BYTE* const oend = (BYTE*)dst + dstSize;
+
+ /* The following condition is false on x32 platform,
+ * but HUF_asm is not compatible with this ABI */
+ if (!(MEM_isLittleEndian() && !MEM_32bits())) return 1;
+
+ /* strict minimum : jump table + 1 byte per stream */
+ if (srcSize < 10)
+ return ERROR(corruption_detected);
+
+ /* Must have at least 8 bytes per stream because we don't handle initializing smaller bit containers.
+ * If table log is not correct at this point, fallback to the old decoder.
+ * On small inputs we don't have enough data to trigger the fast loop, so use the old decoder.
+ */
+ if (dtLog != HUF_DECODER_FAST_TABLELOG)
+ return 1;
+
+ /* Read the jump table. */
+ {
+ const BYTE* const istart = (const BYTE*)src;
+ size_t const length1 = MEM_readLE16(istart);
+ size_t const length2 = MEM_readLE16(istart+2);
+ size_t const length3 = MEM_readLE16(istart+4);
+ size_t const length4 = srcSize - (length1 + length2 + length3 + 6);
+ args->iend[0] = istart + 6; /* jumpTable */
+ args->iend[1] = args->iend[0] + length1;
+ args->iend[2] = args->iend[1] + length2;
+ args->iend[3] = args->iend[2] + length3;
+
+ /* HUF_initDStream() requires this, and this small of an input
+ * won't benefit from the ASM loop anyways.
+ * length1 must be >= 16 so that ip[0] >= ilimit before the loop
+ * starts.
+ */
+ if (length1 < 16 || length2 < 8 || length3 < 8 || length4 < 8)
+ return 1;
+ if (length4 > srcSize) return ERROR(corruption_detected); /* overflow */
+ }
+ /* ip[] contains the position that is currently loaded into bits[]. */
+ args->ip[0] = args->iend[1] - sizeof(U64);
+ args->ip[1] = args->iend[2] - sizeof(U64);
+ args->ip[2] = args->iend[3] - sizeof(U64);
+ args->ip[3] = (BYTE const*)src + srcSize - sizeof(U64);
+
+ /* op[] contains the output pointers. */
+ args->op[0] = (BYTE*)dst;
+ args->op[1] = args->op[0] + (dstSize+3)/4;
+ args->op[2] = args->op[1] + (dstSize+3)/4;
+ args->op[3] = args->op[2] + (dstSize+3)/4;
+
+ /* No point to call the ASM loop for tiny outputs. */
+ if (args->op[3] >= oend)
+ return 1;
+
+ /* bits[] is the bit container.
+ * It is read from the MSB down to the LSB.
+ * It is shifted left as it is read, and zeros are
+ * shifted in. After the lowest valid bit a 1 is
+ * set, so that CountTrailingZeros(bits[]) can be used
+ * to count how many bits we've consumed.
+ */
+ args->bits[0] = HUF_initDStream(args->ip[0]);
+ args->bits[1] = HUF_initDStream(args->ip[1]);
+ args->bits[2] = HUF_initDStream(args->ip[2]);
+ args->bits[3] = HUF_initDStream(args->ip[3]);
+
+ /* If ip[] >= ilimit, it is guaranteed to be safe to
+ * reload bits[]. It may be beyond its section, but is
+ * guaranteed to be valid (>= istart).
+ */
+ args->ilimit = ilimit;
+
+ args->oend = oend;
+ args->dt = dt;
+
+ return 0;
+}
+
+static size_t HUF_initRemainingDStream(BIT_DStream_t* bit, HUF_DecompressAsmArgs const* args, int stream, BYTE* segmentEnd)
+{
+ /* Validate that we haven't overwritten. */
+ if (args->op[stream] > segmentEnd)
+ return ERROR(corruption_detected);
+ /* Validate that we haven't read beyond iend[].
+ * Note that ip[] may be < iend[] because the MSB is
+ * the next bit to read, and we may have consumed 100%
+ * of the stream, so down to iend[i] - 8 is valid.
+ */
+ if (args->ip[stream] < args->iend[stream] - 8)
+ return ERROR(corruption_detected);
+
+ /* Construct the BIT_DStream_t. */
+ bit->bitContainer = MEM_readLE64(args->ip[stream]);
+ bit->bitsConsumed = ZSTD_countTrailingZeros((size_t)args->bits[stream]);
+ bit->start = (const char*)args->iend[0];
+ bit->limitPtr = bit->start + sizeof(size_t);
+ bit->ptr = (const char*)args->ip[stream];
+
+ return 0;
+}
+#endif
+
#ifndef HUF_FORCE_DECOMPRESS_X2
/*-***************************/
/* single-symbol decoding */
/*-***************************/
-typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decoding */
+typedef struct { BYTE nbBits; BYTE byte; } HUF_DEltX1; /* single-symbol decoding */
/**
* Packs 4 HUF_DEltX1 structs into a U64. This is used to lay down 4 entries at
@@ -122,14 +287,44 @@ typedef struct { BYTE byte; BYTE nbBits; } HUF_DEltX1; /* single-symbol decodi
static U64 HUF_DEltX1_set4(BYTE symbol, BYTE nbBits) {
U64 D4;
if (MEM_isLittleEndian()) {
- D4 = symbol + (nbBits << 8);
- } else {
D4 = (symbol << 8) + nbBits;
+ } else {
+ D4 = symbol + (nbBits << 8);
}
D4 *= 0x0001000100010001ULL;
return D4;
}
+/**
+ * Increase the tableLog to targetTableLog and rescales the stats.
+ * If tableLog > targetTableLog this is a no-op.
+ * @returns New tableLog
+ */
+static U32 HUF_rescaleStats(BYTE* huffWeight, U32* rankVal, U32 nbSymbols, U32 tableLog, U32 targetTableLog)
+{
+ if (tableLog > targetTableLog)
+ return tableLog;
+ if (tableLog < targetTableLog) {
+ U32 const scale = targetTableLog - tableLog;
+ U32 s;
+ /* Increase the weight for all non-zero probability symbols by scale. */
+ for (s = 0; s < nbSymbols; ++s) {
+ huffWeight[s] += (BYTE)((huffWeight[s] == 0) ? 0 : scale);
+ }
+ /* Update rankVal to reflect the new weights.
+ * All weights except 0 get moved to weight + scale.
+ * Weights [1, scale] are empty.
+ */
+ for (s = targetTableLog; s > scale; --s) {
+ rankVal[s] = rankVal[s - scale];
+ }
+ for (s = scale; s > 0; --s) {
+ rankVal[s] = 0;
+ }
+ }
+ return targetTableLog;
+}
+
typedef struct {
U32 rankVal[HUF_TABLELOG_ABSOLUTEMAX + 1];
U32 rankStart[HUF_TABLELOG_ABSOLUTEMAX + 1];
@@ -162,8 +357,12 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
iSize = HUF_readStats_wksp(wksp->huffWeight, HUF_SYMBOLVALUE_MAX + 1, wksp->rankVal, &nbSymbols, &tableLog, src, srcSize, wksp->statsWksp, sizeof(wksp->statsWksp), bmi2);
if (HUF_isError(iSize)) return iSize;
+
/* Table header */
{ DTableDesc dtd = HUF_getDTableDesc(DTable);
+ U32 const maxTableLog = dtd.maxTableLog + 1;
+ U32 const targetTableLog = MIN(maxTableLog, HUF_DECODER_FAST_TABLELOG);
+ tableLog = HUF_rescaleStats(wksp->huffWeight, wksp->rankVal, nbSymbols, tableLog, targetTableLog);
if (tableLog > (U32)(dtd.maxTableLog+1)) return ERROR(tableLog_tooLarge); /* DTable too small, Huffman tree cannot fit in */
dtd.tableType = 0;
dtd.tableLog = (BYTE)tableLog;
@@ -207,7 +406,7 @@ size_t HUF_readDTableX1_wksp_bmi2(HUF_DTable* DTable, const void* src, size_t sr
/* fill DTable
* We fill all entries of each weight in order.
- * That way length is a constant for each iteration of the outter loop.
+ * That way length is a constant for each iteration of the outer loop.
* We can switch based on the length to a different inner loop which is
* optimized for that particular case.
*/
@@ -304,11 +503,15 @@ HUF_decodeStreamX1(BYTE* p, BIT_DStream_t* const bitDPtr, BYTE* const pEnd, cons
BYTE* const pStart = p;
/* up to 4 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
- HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
+ if ((pEnd - p) > 3) {
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-3)) {
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX1_0(p, bitDPtr);
+ }
+ } else {
+ BIT_reloadDStream(bitDPtr);
}
/* [0-3] symbols remaining */
@@ -388,33 +591,36 @@ HUF_decompress4X1_usingDTable_internal_body(
U32 endSignal = 1;
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
/* up to 16 symbols per loop (4 symbols per stream) in 64-bit mode */
- for ( ; (endSignal) & (op4 < olimit) ; ) {
- HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
- endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
- endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
- endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
- endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
+ if ((size_t)(oend - op4) >= sizeof(size_t)) {
+ for ( ; (endSignal) & (op4 < olimit) ; ) {
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX1_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX1_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX1_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX1_0(op4, &bitD4);
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
+ }
}
/* check corruption */
@@ -440,6 +646,79 @@ HUF_decompress4X1_usingDTable_internal_body(
}
}
+#if HUF_NEED_BMI2_FUNCTION
+static BMI2_TARGET_ATTRIBUTE
+size_t HUF_decompress4X1_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if HUF_NEED_DEFAULT_FUNCTION
+static
+size_t HUF_decompress4X1_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X1_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
+
+static HUF_ASM_X86_64_BMI2_ATTRS
+size_t
+HUF_decompress4X1_usingDTable_internal_bmi2_asm(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable)
+{
+ void const* dt = DTable + 1;
+ const BYTE* const iend = (const BYTE*)cSrc + 6;
+ BYTE* const oend = (BYTE*)dst + dstSize;
+ HUF_DecompressAsmArgs args;
+ {
+ size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
+ FORWARD_IF_ERROR(ret, "Failed to init asm args");
+ if (ret != 0)
+ return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+ }
+
+ assert(args.ip[0] >= args.ilimit);
+ HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop(&args);
+
+ /* Our loop guarantees that ip[] >= ilimit and that we haven't
+ * overwritten any op[].
+ */
+ assert(args.ip[0] >= iend);
+ assert(args.ip[1] >= iend);
+ assert(args.ip[2] >= iend);
+ assert(args.ip[3] >= iend);
+ assert(args.op[3] <= oend);
+ (void)iend;
+
+ /* finish bit streams one by one. */
+ {
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* segmentEnd = (BYTE*)dst;
+ int i;
+ for (i = 0; i < 4; ++i) {
+ BIT_DStream_t bit;
+ if (segmentSize <= (size_t)(oend - segmentEnd))
+ segmentEnd += segmentSize;
+ else
+ segmentEnd = oend;
+ FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
+ /* Decompress and validate that we've produced exactly the expected length. */
+ args.op[i] += HUF_decodeStreamX1(args.op[i], &bit, segmentEnd, (HUF_DEltX1 const*)dt, HUF_DECODER_FAST_TABLELOG);
+ if (args.op[i] != segmentEnd) return ERROR(corruption_detected);
+ }
+ }
+
+ /* decoded size */
+ return dstSize;
+}
+#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
const void *cSrc,
@@ -447,8 +726,28 @@ typedef size_t (*HUF_decompress_usingDTable_t)(void *dst, size_t dstSize,
const HUF_DTable *DTable);
HUF_DGEN(HUF_decompress1X1_usingDTable_internal)
-HUF_DGEN(HUF_decompress4X1_usingDTable_internal)
+static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+# if ZSTD_ENABLE_ASM_X86_64_BMI2
+ return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+# else
+ return HUF_decompress4X1_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+# endif
+ }
+#else
+ (void)bmi2;
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
+ return HUF_decompress4X1_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+#else
+ return HUF_decompress4X1_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
+#endif
+}
size_t HUF_decompress1X1_usingDTable(
@@ -518,106 +817,226 @@ size_t HUF_decompress4X1_DCtx_wksp(HUF_DTable* dctx, void* dst, size_t dstSize,
/* *************************/
typedef struct { U16 sequence; BYTE nbBits; BYTE length; } HUF_DEltX2; /* double-symbols decoding */
-typedef struct { BYTE symbol; BYTE weight; } sortedSymbol_t;
+typedef struct { BYTE symbol; } sortedSymbol_t;
typedef U32 rankValCol_t[HUF_TABLELOG_MAX + 1];
typedef rankValCol_t rankVal_t[HUF_TABLELOG_MAX];
+/**
+ * Constructs a HUF_DEltX2 in a U32.
+ */
+static U32 HUF_buildDEltX2U32(U32 symbol, U32 nbBits, U32 baseSeq, int level)
+{
+ U32 seq;
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, sequence) == 0);
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, nbBits) == 2);
+ DEBUG_STATIC_ASSERT(offsetof(HUF_DEltX2, length) == 3);
+ DEBUG_STATIC_ASSERT(sizeof(HUF_DEltX2) == sizeof(U32));
+ if (MEM_isLittleEndian()) {
+ seq = level == 1 ? symbol : (baseSeq + (symbol << 8));
+ return seq + (nbBits << 16) + ((U32)level << 24);
+ } else {
+ seq = level == 1 ? (symbol << 8) : ((baseSeq << 8) + symbol);
+ return (seq << 16) + (nbBits << 8) + (U32)level;
+ }
+}
-/* HUF_fillDTableX2Level2() :
- * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
-static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 sizeLog, const U32 consumed,
- const U32* rankValOrigin, const int minWeight,
- const sortedSymbol_t* sortedSymbols, const U32 sortedListSize,
- U32 nbBitsBaseline, U16 baseSeq, U32* wksp, size_t wkspSize)
+/**
+ * Constructs a HUF_DEltX2.
+ */
+static HUF_DEltX2 HUF_buildDEltX2(U32 symbol, U32 nbBits, U32 baseSeq, int level)
{
HUF_DEltX2 DElt;
- U32* rankVal = wksp;
+ U32 const val = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
+ DEBUG_STATIC_ASSERT(sizeof(DElt) == sizeof(val));
+ ZSTD_memcpy(&DElt, &val, sizeof(val));
+ return DElt;
+}
- assert(wkspSize >= HUF_TABLELOG_MAX + 1);
- (void)wkspSize;
- /* get pre-calculated rankVal */
- ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
+/**
+ * Constructs 2 HUF_DEltX2s and packs them into a U64.
+ */
+static U64 HUF_buildDEltX2U64(U32 symbol, U32 nbBits, U16 baseSeq, int level)
+{
+ U32 DElt = HUF_buildDEltX2U32(symbol, nbBits, baseSeq, level);
+ return (U64)DElt + ((U64)DElt << 32);
+}
- /* fill skipped values */
- if (minWeight>1) {
- U32 i, skipSize = rankVal[minWeight];
- MEM_writeLE16(&(DElt.sequence), baseSeq);
- DElt.nbBits = (BYTE)(consumed);
- DElt.length = 1;
- for (i = 0; i < skipSize; i++)
- DTable[i] = DElt;
+/**
+ * Fills the DTable rank with all the symbols from [begin, end) that are each
+ * nbBits long.
+ *
+ * @param DTableRank The start of the rank in the DTable.
+ * @param begin The first symbol to fill (inclusive).
+ * @param end The last symbol to fill (exclusive).
+ * @param nbBits Each symbol is nbBits long.
+ * @param tableLog The table log.
+ * @param baseSeq If level == 1 { 0 } else { the first level symbol }
+ * @param level The level in the table. Must be 1 or 2.
+ */
+static void HUF_fillDTableX2ForWeight(
+ HUF_DEltX2* DTableRank,
+ sortedSymbol_t const* begin, sortedSymbol_t const* end,
+ U32 nbBits, U32 tableLog,
+ U16 baseSeq, int const level)
+{
+ U32 const length = 1U << ((tableLog - nbBits) & 0x1F /* quiet static-analyzer */);
+ const sortedSymbol_t* ptr;
+ assert(level >= 1 && level <= 2);
+ switch (length) {
+ case 1:
+ for (ptr = begin; ptr != end; ++ptr) {
+ HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
+ *DTableRank++ = DElt;
+ }
+ break;
+ case 2:
+ for (ptr = begin; ptr != end; ++ptr) {
+ HUF_DEltX2 const DElt = HUF_buildDEltX2(ptr->symbol, nbBits, baseSeq, level);
+ DTableRank[0] = DElt;
+ DTableRank[1] = DElt;
+ DTableRank += 2;
+ }
+ break;
+ case 4:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ DTableRank += 4;
+ }
+ break;
+ case 8:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
+ DTableRank += 8;
+ }
+ break;
+ default:
+ for (ptr = begin; ptr != end; ++ptr) {
+ U64 const DEltX2 = HUF_buildDEltX2U64(ptr->symbol, nbBits, baseSeq, level);
+ HUF_DEltX2* const DTableRankEnd = DTableRank + length;
+ for (; DTableRank != DTableRankEnd; DTableRank += 8) {
+ ZSTD_memcpy(DTableRank + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTableRank + 6, &DEltX2, sizeof(DEltX2));
+ }
+ }
+ break;
}
+}
- /* fill DTable */
- { U32 s; for (s=0; s<sortedListSize; s++) { /* note : sortedSymbols already skipped */
- const U32 symbol = sortedSymbols[s].symbol;
- const U32 weight = sortedSymbols[s].weight;
- const U32 nbBits = nbBitsBaseline - weight;
- const U32 length = 1 << (sizeLog-nbBits);
- const U32 start = rankVal[weight];
- U32 i = start;
- const U32 end = start + length;
-
- MEM_writeLE16(&(DElt.sequence), (U16)(baseSeq + (symbol << 8)));
- DElt.nbBits = (BYTE)(nbBits + consumed);
- DElt.length = 2;
- do { DTable[i++] = DElt; } while (i<end); /* since length >= 1 */
+/* HUF_fillDTableX2Level2() :
+ * `rankValOrigin` must be a table of at least (HUF_TABLELOG_MAX + 1) U32 */
+static void HUF_fillDTableX2Level2(HUF_DEltX2* DTable, U32 targetLog, const U32 consumedBits,
+ const U32* rankVal, const int minWeight, const int maxWeight1,
+ const sortedSymbol_t* sortedSymbols, U32 const* rankStart,
+ U32 nbBitsBaseline, U16 baseSeq)
+{
+ /* Fill skipped values (all positions up to rankVal[minWeight]).
+ * These are positions only get a single symbol because the combined weight
+ * is too large.
+ */
+ if (minWeight>1) {
+ U32 const length = 1U << ((targetLog - consumedBits) & 0x1F /* quiet static-analyzer */);
+ U64 const DEltX2 = HUF_buildDEltX2U64(baseSeq, consumedBits, /* baseSeq */ 0, /* level */ 1);
+ int const skipSize = rankVal[minWeight];
+ assert(length > 1);
+ assert((U32)skipSize < length);
+ switch (length) {
+ case 2:
+ assert(skipSize == 1);
+ ZSTD_memcpy(DTable, &DEltX2, sizeof(DEltX2));
+ break;
+ case 4:
+ assert(skipSize <= 4);
+ ZSTD_memcpy(DTable + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + 2, &DEltX2, sizeof(DEltX2));
+ break;
+ default:
+ {
+ int i;
+ for (i = 0; i < skipSize; i += 8) {
+ ZSTD_memcpy(DTable + i + 0, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 2, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 4, &DEltX2, sizeof(DEltX2));
+ ZSTD_memcpy(DTable + i + 6, &DEltX2, sizeof(DEltX2));
+ }
+ }
+ }
+ }
- rankVal[weight] += length;
- } }
+ /* Fill each of the second level symbols by weight. */
+ {
+ int w;
+ for (w = minWeight; w < maxWeight1; ++w) {
+ int const begin = rankStart[w];
+ int const end = rankStart[w+1];
+ U32 const nbBits = nbBitsBaseline - w;
+ U32 const totalBits = nbBits + consumedBits;
+ HUF_fillDTableX2ForWeight(
+ DTable + rankVal[w],
+ sortedSymbols + begin, sortedSymbols + end,
+ totalBits, targetLog,
+ baseSeq, /* level */ 2);
+ }
+ }
}
-
static void HUF_fillDTableX2(HUF_DEltX2* DTable, const U32 targetLog,
- const sortedSymbol_t* sortedList, const U32 sortedListSize,
+ const sortedSymbol_t* sortedList,
const U32* rankStart, rankVal_t rankValOrigin, const U32 maxWeight,
- const U32 nbBitsBaseline, U32* wksp, size_t wkspSize)
+ const U32 nbBitsBaseline)
{
- U32* rankVal = wksp;
+ U32* const rankVal = rankValOrigin[0];
const int scaleLog = nbBitsBaseline - targetLog; /* note : targetLog >= srcLog, hence scaleLog <= 1 */
const U32 minBits = nbBitsBaseline - maxWeight;
- U32 s;
-
- assert(wkspSize >= HUF_TABLELOG_MAX + 1);
- wksp += HUF_TABLELOG_MAX + 1;
- wkspSize -= HUF_TABLELOG_MAX + 1;
-
- ZSTD_memcpy(rankVal, rankValOrigin, sizeof(U32) * (HUF_TABLELOG_MAX + 1));
-
- /* fill DTable */
- for (s=0; s<sortedListSize; s++) {
- const U16 symbol = sortedList[s].symbol;
- const U32 weight = sortedList[s].weight;
- const U32 nbBits = nbBitsBaseline - weight;
- const U32 start = rankVal[weight];
- const U32 length = 1 << (targetLog-nbBits);
-
- if (targetLog-nbBits >= minBits) { /* enough room for a second symbol */
- U32 sortedRank;
+ int w;
+ int const wEnd = (int)maxWeight + 1;
+
+ /* Fill DTable in order of weight. */
+ for (w = 1; w < wEnd; ++w) {
+ int const begin = (int)rankStart[w];
+ int const end = (int)rankStart[w+1];
+ U32 const nbBits = nbBitsBaseline - w;
+
+ if (targetLog-nbBits >= minBits) {
+ /* Enough room for a second symbol. */
+ int start = rankVal[w];
+ U32 const length = 1U << ((targetLog - nbBits) & 0x1F /* quiet static-analyzer */);
int minWeight = nbBits + scaleLog;
+ int s;
if (minWeight < 1) minWeight = 1;
- sortedRank = rankStart[minWeight];
- HUF_fillDTableX2Level2(DTable+start, targetLog-nbBits, nbBits,
- rankValOrigin[nbBits], minWeight,
- sortedList+sortedRank, sortedListSize-sortedRank,
- nbBitsBaseline, symbol, wksp, wkspSize);
+ /* Fill the DTable for every symbol of weight w.
+ * These symbols get at least 1 second symbol.
+ */
+ for (s = begin; s != end; ++s) {
+ HUF_fillDTableX2Level2(
+ DTable + start, targetLog, nbBits,
+ rankValOrigin[nbBits], minWeight, wEnd,
+ sortedList, rankStart,
+ nbBitsBaseline, sortedList[s].symbol);
+ start += length;
+ }
} else {
- HUF_DEltX2 DElt;
- MEM_writeLE16(&(DElt.sequence), symbol);
- DElt.nbBits = (BYTE)(nbBits);
- DElt.length = 1;
- { U32 const end = start + length;
- U32 u;
- for (u = start; u < end; u++) DTable[u] = DElt;
- } }
- rankVal[weight] += length;
+ /* Only a single symbol. */
+ HUF_fillDTableX2ForWeight(
+ DTable + rankVal[w],
+ sortedList + begin, sortedList + end,
+ nbBits, targetLog,
+ /* baseSeq */ 0, /* level */ 1);
+ }
}
}
typedef struct {
rankValCol_t rankVal[HUF_TABLELOG_MAX];
U32 rankStats[HUF_TABLELOG_MAX + 1];
- U32 rankStart0[HUF_TABLELOG_MAX + 2];
+ U32 rankStart0[HUF_TABLELOG_MAX + 3];
sortedSymbol_t sortedSymbol[HUF_SYMBOLVALUE_MAX + 1];
BYTE weightList[HUF_SYMBOLVALUE_MAX + 1];
U32 calleeWksp[HUF_READ_STATS_WORKSPACE_SIZE_U32];
@@ -627,9 +1046,16 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
const void* src, size_t srcSize,
void* workSpace, size_t wkspSize)
{
- U32 tableLog, maxW, sizeOfSort, nbSymbols;
+ return HUF_readDTableX2_wksp_bmi2(DTable, src, srcSize, workSpace, wkspSize, /* bmi2 */ 0);
+}
+
+size_t HUF_readDTableX2_wksp_bmi2(HUF_DTable* DTable,
+ const void* src, size_t srcSize,
+ void* workSpace, size_t wkspSize, int bmi2)
+{
+ U32 tableLog, maxW, nbSymbols;
DTableDesc dtd = HUF_getDTableDesc(DTable);
- U32 const maxTableLog = dtd.maxTableLog;
+ U32 maxTableLog = dtd.maxTableLog;
size_t iSize;
void* dtPtr = DTable+1; /* force compiler to avoid strict-aliasing */
HUF_DEltX2* const dt = (HUF_DEltX2*)dtPtr;
@@ -647,11 +1073,12 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
if (maxTableLog > HUF_TABLELOG_MAX) return ERROR(tableLog_tooLarge);
/* ZSTD_memset(weightList, 0, sizeof(weightList)); */ /* is not necessary, even though some analyzer complain ... */
- iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), /* bmi2 */ 0);
+ iSize = HUF_readStats_wksp(wksp->weightList, HUF_SYMBOLVALUE_MAX + 1, wksp->rankStats, &nbSymbols, &tableLog, src, srcSize, wksp->calleeWksp, sizeof(wksp->calleeWksp), bmi2);
if (HUF_isError(iSize)) return iSize;
/* check result */
if (tableLog > maxTableLog) return ERROR(tableLog_tooLarge); /* DTable can't fit code depth */
+ if (tableLog <= HUF_DECODER_FAST_TABLELOG && maxTableLog > HUF_DECODER_FAST_TABLELOG) maxTableLog = HUF_DECODER_FAST_TABLELOG;
/* find maxWeight */
for (maxW = tableLog; wksp->rankStats[maxW]==0; maxW--) {} /* necessarily finds a solution before 0 */
@@ -664,7 +1091,7 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
rankStart[w] = curr;
}
rankStart[0] = nextRankStart; /* put all 0w symbols at the end of sorted list*/
- sizeOfSort = nextRankStart;
+ rankStart[maxW+1] = nextRankStart;
}
/* sort symbols by weight */
@@ -673,7 +1100,6 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
U32 const w = wksp->weightList[s];
U32 const r = rankStart[w]++;
wksp->sortedSymbol[r].symbol = (BYTE)s;
- wksp->sortedSymbol[r].weight = (BYTE)w;
}
rankStart[0] = 0; /* forget 0w symbols; this is beginning of weight(1) */
}
@@ -698,10 +1124,9 @@ size_t HUF_readDTableX2_wksp(HUF_DTable* DTable,
} } } }
HUF_fillDTableX2(dt, maxTableLog,
- wksp->sortedSymbol, sizeOfSort,
+ wksp->sortedSymbol,
wksp->rankStart0, wksp->rankVal, maxW,
- tableLog+1,
- wksp->calleeWksp, sizeof(wksp->calleeWksp) / sizeof(U32));
+ tableLog+1);
dtd.tableLog = (BYTE)maxTableLog;
dtd.tableType = 1;
@@ -714,7 +1139,7 @@ FORCE_INLINE_TEMPLATE U32
HUF_decodeSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- ZSTD_memcpy(op, dt+val, 2);
+ ZSTD_memcpy(op, &dt[val].sequence, 2);
BIT_skipBits(DStream, dt[val].nbBits);
return dt[val].length;
}
@@ -723,15 +1148,17 @@ FORCE_INLINE_TEMPLATE U32
HUF_decodeLastSymbolX2(void* op, BIT_DStream_t* DStream, const HUF_DEltX2* dt, const U32 dtLog)
{
size_t const val = BIT_lookBitsFast(DStream, dtLog); /* note : dtLog >= 1 */
- ZSTD_memcpy(op, dt+val, 1);
- if (dt[val].length==1) BIT_skipBits(DStream, dt[val].nbBits);
- else {
+ ZSTD_memcpy(op, &dt[val].sequence, 1);
+ if (dt[val].length==1) {
+ BIT_skipBits(DStream, dt[val].nbBits);
+ } else {
if (DStream->bitsConsumed < (sizeof(DStream->bitContainer)*8)) {
BIT_skipBits(DStream, dt[val].nbBits);
if (DStream->bitsConsumed > (sizeof(DStream->bitContainer)*8))
/* ugly hack; works only because it's the last symbol. Note : can't easily extract nbBits from just this symbol */
DStream->bitsConsumed = (sizeof(DStream->bitContainer)*8);
- } }
+ }
+ }
return 1;
}
@@ -753,19 +1180,37 @@ HUF_decodeStreamX2(BYTE* p, BIT_DStream_t* bitDPtr, BYTE* const pEnd,
BYTE* const pStart = p;
/* up to 8 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ if ((size_t)(pEnd - p) >= sizeof(bitDPtr->bitContainer)) {
+ if (dtLog <= 11 && MEM_64bits()) {
+ /* up to 10 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-9)) {
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+ } else {
+ /* up to 8 symbols at a time */
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p < pEnd-(sizeof(bitDPtr->bitContainer)-1))) {
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_1(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_2(p, bitDPtr);
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ }
+ }
+ } else {
+ BIT_reloadDStream(bitDPtr);
}
/* closer to end : up to 2 symbols at a time */
- while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
+ if ((size_t)(pEnd - p) >= 2) {
+ while ((BIT_reloadDStream(bitDPtr) == BIT_DStream_unfinished) & (p <= pEnd-2))
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr);
- while (p <= pEnd-2)
- HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+ while (p <= pEnd-2)
+ HUF_DECODE_SYMBOLX2_0(p, bitDPtr); /* no need to reload : reached the end of DStream */
+ }
if (p < pEnd)
p += HUF_decodeLastSymbolX2(p, bitDPtr, dt, dtLog);
@@ -799,7 +1244,6 @@ HUF_decompress1X2_usingDTable_internal_body(
/* decoded size */
return dstSize;
}
-
FORCE_INLINE_TEMPLATE size_t
HUF_decompress4X2_usingDTable_internal_body(
void* dst, size_t dstSize,
@@ -841,57 +1285,60 @@ HUF_decompress4X2_usingDTable_internal_body(
U32 const dtLog = dtd.tableLog;
if (length4 > cSrcSize) return ERROR(corruption_detected); /* overflow */
+ if (opStart4 > oend) return ERROR(corruption_detected); /* overflow */
CHECK_F( BIT_initDStream(&bitD1, istart1, length1) );
CHECK_F( BIT_initDStream(&bitD2, istart2, length2) );
CHECK_F( BIT_initDStream(&bitD3, istart3, length3) );
CHECK_F( BIT_initDStream(&bitD4, istart4, length4) );
/* 16-32 symbols per loop (4-8 symbols per stream) */
- for ( ; (endSignal) & (op4 < olimit); ) {
+ if ((size_t)(oend - op4) >= sizeof(size_t)) {
+ for ( ; (endSignal) & (op4 < olimit); ) {
#if defined(__clang__) && (defined(__x86_64__) || defined(__i386__))
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
- endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
- endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
- endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
- endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ endSignal &= BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished;
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ endSignal &= BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished;
+ endSignal &= BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished;
#else
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
- HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
- HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
- HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
- HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
- endSignal = (U32)LIKELY(
- (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
- & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
- & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
- & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_1(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_1(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_1(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_1(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_2(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_2(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_2(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_2(op4, &bitD4);
+ HUF_DECODE_SYMBOLX2_0(op1, &bitD1);
+ HUF_DECODE_SYMBOLX2_0(op2, &bitD2);
+ HUF_DECODE_SYMBOLX2_0(op3, &bitD3);
+ HUF_DECODE_SYMBOLX2_0(op4, &bitD4);
+ endSignal = (U32)LIKELY((U32)
+ (BIT_reloadDStreamFast(&bitD1) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD2) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD3) == BIT_DStream_unfinished)
+ & (BIT_reloadDStreamFast(&bitD4) == BIT_DStream_unfinished));
#endif
+ }
}
/* check corruption */
@@ -915,8 +1362,99 @@ HUF_decompress4X2_usingDTable_internal_body(
}
}
+#if HUF_NEED_BMI2_FUNCTION
+static BMI2_TARGET_ATTRIBUTE
+size_t HUF_decompress4X2_usingDTable_internal_bmi2(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if HUF_NEED_DEFAULT_FUNCTION
+static
+size_t HUF_decompress4X2_usingDTable_internal_default(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable) {
+ return HUF_decompress4X2_usingDTable_internal_body(dst, dstSize, cSrc, cSrcSize, DTable);
+}
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(HUF_DecompressAsmArgs* args) ZSTDLIB_HIDDEN;
+
+static HUF_ASM_X86_64_BMI2_ATTRS size_t
+HUF_decompress4X2_usingDTable_internal_bmi2_asm(
+ void* dst, size_t dstSize,
+ const void* cSrc, size_t cSrcSize,
+ const HUF_DTable* DTable) {
+ void const* dt = DTable + 1;
+ const BYTE* const iend = (const BYTE*)cSrc + 6;
+ BYTE* const oend = (BYTE*)dst + dstSize;
+ HUF_DecompressAsmArgs args;
+ {
+ size_t const ret = HUF_DecompressAsmArgs_init(&args, dst, dstSize, cSrc, cSrcSize, DTable);
+ FORWARD_IF_ERROR(ret, "Failed to init asm args");
+ if (ret != 0)
+ return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+ }
+
+ assert(args.ip[0] >= args.ilimit);
+ HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop(&args);
+
+ /* note : op4 already verified within main loop */
+ assert(args.ip[0] >= iend);
+ assert(args.ip[1] >= iend);
+ assert(args.ip[2] >= iend);
+ assert(args.ip[3] >= iend);
+ assert(args.op[3] <= oend);
+ (void)iend;
+
+ /* finish bitStreams one by one */
+ {
+ size_t const segmentSize = (dstSize+3) / 4;
+ BYTE* segmentEnd = (BYTE*)dst;
+ int i;
+ for (i = 0; i < 4; ++i) {
+ BIT_DStream_t bit;
+ if (segmentSize <= (size_t)(oend - segmentEnd))
+ segmentEnd += segmentSize;
+ else
+ segmentEnd = oend;
+ FORWARD_IF_ERROR(HUF_initRemainingDStream(&bit, &args, i, segmentEnd), "corruption");
+ args.op[i] += HUF_decodeStreamX2(args.op[i], &bit, segmentEnd, (HUF_DEltX2 const*)dt, HUF_DECODER_FAST_TABLELOG);
+ if (args.op[i] != segmentEnd)
+ return ERROR(corruption_detected);
+ }
+ }
+
+ /* decoded size */
+ return dstSize;
+}
+#endif /* ZSTD_ENABLE_ASM_X86_64_BMI2 */
+
+static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize, void const* cSrc,
+ size_t cSrcSize, HUF_DTable const* DTable, int bmi2)
+{
+#if DYNAMIC_BMI2
+ if (bmi2) {
+# if ZSTD_ENABLE_ASM_X86_64_BMI2
+ return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+# else
+ return HUF_decompress4X2_usingDTable_internal_bmi2(dst, dstSize, cSrc, cSrcSize, DTable);
+# endif
+ }
+#else
+ (void)bmi2;
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2 && defined(__BMI2__)
+ return HUF_decompress4X2_usingDTable_internal_bmi2_asm(dst, dstSize, cSrc, cSrcSize, DTable);
+#else
+ return HUF_decompress4X2_usingDTable_internal_default(dst, dstSize, cSrc, cSrcSize, DTable);
+#endif
+}
+
HUF_DGEN(HUF_decompress1X2_usingDTable_internal)
-HUF_DGEN(HUF_decompress4X2_usingDTable_internal)
size_t HUF_decompress1X2_usingDTable(
void* dst, size_t dstSize,
@@ -1025,25 +1563,25 @@ size_t HUF_decompress4X_usingDTable(void* dst, size_t maxDstSize,
#if !defined(HUF_FORCE_DECOMPRESS_X1) && !defined(HUF_FORCE_DECOMPRESS_X2)
typedef struct { U32 tableTime; U32 decode256Time; } algo_time_t;
-static const algo_time_t algoTime[16 /* Quantization */][3 /* single, double, quad */] =
+static const algo_time_t algoTime[16 /* Quantization */][2 /* single, double */] =
{
/* single, double, quad */
- {{0,0}, {1,1}, {2,2}}, /* Q==0 : impossible */
- {{0,0}, {1,1}, {2,2}}, /* Q==1 : impossible */
- {{ 38,130}, {1313, 74}, {2151, 38}}, /* Q == 2 : 12-18% */
- {{ 448,128}, {1353, 74}, {2238, 41}}, /* Q == 3 : 18-25% */
- {{ 556,128}, {1353, 74}, {2238, 47}}, /* Q == 4 : 25-32% */
- {{ 714,128}, {1418, 74}, {2436, 53}}, /* Q == 5 : 32-38% */
- {{ 883,128}, {1437, 74}, {2464, 61}}, /* Q == 6 : 38-44% */
- {{ 897,128}, {1515, 75}, {2622, 68}}, /* Q == 7 : 44-50% */
- {{ 926,128}, {1613, 75}, {2730, 75}}, /* Q == 8 : 50-56% */
- {{ 947,128}, {1729, 77}, {3359, 77}}, /* Q == 9 : 56-62% */
- {{1107,128}, {2083, 81}, {4006, 84}}, /* Q ==10 : 62-69% */
- {{1177,128}, {2379, 87}, {4785, 88}}, /* Q ==11 : 69-75% */
- {{1242,128}, {2415, 93}, {5155, 84}}, /* Q ==12 : 75-81% */
- {{1349,128}, {2644,106}, {5260,106}}, /* Q ==13 : 81-87% */
- {{1455,128}, {2422,124}, {4174,124}}, /* Q ==14 : 87-93% */
- {{ 722,128}, {1891,145}, {1936,146}}, /* Q ==15 : 93-99% */
+ {{0,0}, {1,1}}, /* Q==0 : impossible */
+ {{0,0}, {1,1}}, /* Q==1 : impossible */
+ {{ 150,216}, { 381,119}}, /* Q == 2 : 12-18% */
+ {{ 170,205}, { 514,112}}, /* Q == 3 : 18-25% */
+ {{ 177,199}, { 539,110}}, /* Q == 4 : 25-32% */
+ {{ 197,194}, { 644,107}}, /* Q == 5 : 32-38% */
+ {{ 221,192}, { 735,107}}, /* Q == 6 : 38-44% */
+ {{ 256,189}, { 881,106}}, /* Q == 7 : 44-50% */
+ {{ 359,188}, {1167,109}}, /* Q == 8 : 50-56% */
+ {{ 582,187}, {1570,114}}, /* Q == 9 : 56-62% */
+ {{ 688,187}, {1712,122}}, /* Q ==10 : 62-69% */
+ {{ 825,186}, {1965,136}}, /* Q ==11 : 69-75% */
+ {{ 976,185}, {2131,150}}, /* Q ==12 : 75-81% */
+ {{1180,186}, {2070,175}}, /* Q ==13 : 81-87% */
+ {{1377,185}, {1731,202}}, /* Q ==14 : 87-93% */
+ {{1412,185}, {1695,202}}, /* Q ==15 : 93-99% */
};
#endif
@@ -1070,7 +1608,7 @@ U32 HUF_selectDecoder (size_t dstSize, size_t cSrcSize)
U32 const D256 = (U32)(dstSize >> 8);
U32 const DTime0 = algoTime[Q][0].tableTime + (algoTime[Q][0].decode256Time * D256);
U32 DTime1 = algoTime[Q][1].tableTime + (algoTime[Q][1].decode256Time * D256);
- DTime1 += DTime1 >> 3; /* advantage to algorithm using less memory, to reduce cache eviction */
+ DTime1 += DTime1 >> 5; /* small advantage to algorithm using less memory, to reduce cache eviction */
return DTime1 < DTime0;
}
#endif
diff --git a/thirdparty/zstd/decompress/huf_decompress_amd64.S b/thirdparty/zstd/decompress/huf_decompress_amd64.S
new file mode 100644
index 0000000000..49589cb611
--- /dev/null
+++ b/thirdparty/zstd/decompress/huf_decompress_amd64.S
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under both the BSD-style license (found in the
+ * LICENSE file in the root directory of this source tree) and the GPLv2 (found
+ * in the COPYING file in the root directory of this source tree).
+ * You may select, at your option, one of the above-listed licenses.
+ */
+
+#include "../common/portability_macros.h"
+
+/* Stack marking
+ * ref: https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart
+ */
+#if defined(__ELF__) && defined(__GNUC__)
+.section .note.GNU-stack,"",%progbits
+#endif
+
+#if ZSTD_ENABLE_ASM_X86_64_BMI2
+
+/* Calling convention:
+ *
+ * %rdi contains the first argument: HUF_DecompressAsmArgs*.
+ * %rbp isn't maintained (no frame pointer).
+ * %rsp contains the stack pointer that grows down.
+ * No red-zone is assumed, only addresses >= %rsp are used.
+ * All register contents are preserved.
+ *
+ * TODO: Support Windows calling convention.
+ */
+
+ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
+ZSTD_HIDE_ASM_FUNCTION(HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
+ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop)
+ZSTD_HIDE_ASM_FUNCTION(_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop)
+.global HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
+.global HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
+.global _HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop
+.global _HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop
+.text
+
+/* Sets up register mappings for clarity.
+ * op[], bits[], dtable & ip[0] each get their own register.
+ * ip[1,2,3] & olimit alias var[].
+ * %rax is a scratch register.
+ */
+
+#define op0 rsi
+#define op1 rbx
+#define op2 rcx
+#define op3 rdi
+
+#define ip0 r8
+#define ip1 r9
+#define ip2 r10
+#define ip3 r11
+
+#define bits0 rbp
+#define bits1 rdx
+#define bits2 r12
+#define bits3 r13
+#define dtable r14
+#define olimit r15
+
+/* var[] aliases ip[1,2,3] & olimit
+ * ip[1,2,3] are saved every iteration.
+ * olimit is only used in compute_olimit.
+ */
+#define var0 r15
+#define var1 r9
+#define var2 r10
+#define var3 r11
+
+/* 32-bit var registers */
+#define vard0 r15d
+#define vard1 r9d
+#define vard2 r10d
+#define vard3 r11d
+
+/* Calls X(N) for each stream 0, 1, 2, 3. */
+#define FOR_EACH_STREAM(X) \
+ X(0); \
+ X(1); \
+ X(2); \
+ X(3)
+
+/* Calls X(N, idx) for each stream 0, 1, 2, 3. */
+#define FOR_EACH_STREAM_WITH_INDEX(X, idx) \
+ X(0, idx); \
+ X(1, idx); \
+ X(2, idx); \
+ X(3, idx)
+
+/* Define both _HUF_* & HUF_* symbols because MacOS
+ * C symbols are prefixed with '_' & Linux symbols aren't.
+ */
+_HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
+HUF_decompress4X1_usingDTable_internal_bmi2_asm_loop:
+ /* Save all registers - even if they are callee saved for simplicity. */
+ push %rax
+ push %rbx
+ push %rcx
+ push %rdx
+ push %rbp
+ push %rsi
+ push %rdi
+ push %r8
+ push %r9
+ push %r10
+ push %r11
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ /* Read HUF_DecompressAsmArgs* args from %rax */
+ movq %rdi, %rax
+ movq 0(%rax), %ip0
+ movq 8(%rax), %ip1
+ movq 16(%rax), %ip2
+ movq 24(%rax), %ip3
+ movq 32(%rax), %op0
+ movq 40(%rax), %op1
+ movq 48(%rax), %op2
+ movq 56(%rax), %op3
+ movq 64(%rax), %bits0
+ movq 72(%rax), %bits1
+ movq 80(%rax), %bits2
+ movq 88(%rax), %bits3
+ movq 96(%rax), %dtable
+ push %rax /* argument */
+ push 104(%rax) /* ilimit */
+ push 112(%rax) /* oend */
+ push %olimit /* olimit space */
+
+ subq $24, %rsp
+
+.L_4X1_compute_olimit:
+ /* Computes how many iterations we can do safely
+ * %r15, %rax may be clobbered
+ * rbx, rdx must be saved
+ * op3 & ip0 mustn't be clobbered
+ */
+ movq %rbx, 0(%rsp)
+ movq %rdx, 8(%rsp)
+
+ movq 32(%rsp), %rax /* rax = oend */
+ subq %op3, %rax /* rax = oend - op3 */
+
+ /* r15 = (oend - op3) / 5 */
+ movabsq $-3689348814741910323, %rdx
+ mulq %rdx
+ movq %rdx, %r15
+ shrq $2, %r15
+
+ movq %ip0, %rax /* rax = ip0 */
+ movq 40(%rsp), %rdx /* rdx = ilimit */
+ subq %rdx, %rax /* rax = ip0 - ilimit */
+ movq %rax, %rbx /* rbx = ip0 - ilimit */
+
+ /* rdx = (ip0 - ilimit) / 7 */
+ movabsq $2635249153387078803, %rdx
+ mulq %rdx
+ subq %rdx, %rbx
+ shrq %rbx
+ addq %rbx, %rdx
+ shrq $2, %rdx
+
+ /* r15 = min(%rdx, %r15) */
+ cmpq %rdx, %r15
+ cmova %rdx, %r15
+
+ /* r15 = r15 * 5 */
+ leaq (%r15, %r15, 4), %r15
+
+ /* olimit = op3 + r15 */
+ addq %op3, %olimit
+
+ movq 8(%rsp), %rdx
+ movq 0(%rsp), %rbx
+
+ /* If (op3 + 20 > olimit) */
+ movq %op3, %rax /* rax = op3 */
+ addq $20, %rax /* rax = op3 + 20 */
+ cmpq %rax, %olimit /* op3 + 20 > olimit */
+ jb .L_4X1_exit
+
+ /* If (ip1 < ip0) go to exit */
+ cmpq %ip0, %ip1
+ jb .L_4X1_exit
+
+ /* If (ip2 < ip1) go to exit */
+ cmpq %ip1, %ip2
+ jb .L_4X1_exit
+
+ /* If (ip3 < ip2) go to exit */
+ cmpq %ip2, %ip3
+ jb .L_4X1_exit
+
+/* Reads top 11 bits from bits[n]
+ * Loads dt[bits[n]] into var[n]
+ */
+#define GET_NEXT_DELT(n) \
+ movq $53, %var##n; \
+ shrxq %var##n, %bits##n, %var##n; \
+ movzwl (%dtable,%var##n,2),%vard##n
+
+/* var[n] must contain the DTable entry computed with GET_NEXT_DELT
+ * Moves var[n] to %rax
+ * bits[n] <<= var[n] & 63
+ * op[n][idx] = %rax >> 8
+ * %ah is a way to access bits [8, 16) of %rax
+ */
+#define DECODE_FROM_DELT(n, idx) \
+ movq %var##n, %rax; \
+ shlxq %var##n, %bits##n, %bits##n; \
+ movb %ah, idx(%op##n)
+
+/* Assumes GET_NEXT_DELT has been called.
+ * Calls DECODE_FROM_DELT then GET_NEXT_DELT
+ */
+#define DECODE_AND_GET_NEXT(n, idx) \
+ DECODE_FROM_DELT(n, idx); \
+ GET_NEXT_DELT(n) \
+
+/* // ctz & nbBytes is stored in bits[n]
+ * // nbBits is stored in %rax
+ * ctz = CTZ[bits[n]]
+ * nbBits = ctz & 7
+ * nbBytes = ctz >> 3
+ * op[n] += 5
+ * ip[n] -= nbBytes
+ * // Note: x86-64 is little-endian ==> no bswap
+ * bits[n] = MEM_readST(ip[n]) | 1
+ * bits[n] <<= nbBits
+ */
+#define RELOAD_BITS(n) \
+ bsfq %bits##n, %bits##n; \
+ movq %bits##n, %rax; \
+ andq $7, %rax; \
+ shrq $3, %bits##n; \
+ leaq 5(%op##n), %op##n; \
+ subq %bits##n, %ip##n; \
+ movq (%ip##n), %bits##n; \
+ orq $1, %bits##n; \
+ shlx %rax, %bits##n, %bits##n
+
+ /* Store clobbered variables on the stack */
+ movq %olimit, 24(%rsp)
+ movq %ip1, 0(%rsp)
+ movq %ip2, 8(%rsp)
+ movq %ip3, 16(%rsp)
+
+ /* Call GET_NEXT_DELT for each stream */
+ FOR_EACH_STREAM(GET_NEXT_DELT)
+
+ .p2align 6
+
+.L_4X1_loop_body:
+ /* Decode 5 symbols in each of the 4 streams (20 total)
+ * Must have called GET_NEXT_DELT for each stream
+ */
+ FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 0)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 1)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 2)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE_AND_GET_NEXT, 3)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE_FROM_DELT, 4)
+
+ /* Load ip[1,2,3] from stack (var[] aliases them)
+ * ip[] is needed for RELOAD_BITS
+ * Each will be stored back to the stack after RELOAD
+ */
+ movq 0(%rsp), %ip1
+ movq 8(%rsp), %ip2
+ movq 16(%rsp), %ip3
+
+ /* Reload each stream & fetch the next table entry
+ * to prepare for the next iteration
+ */
+ RELOAD_BITS(0)
+ GET_NEXT_DELT(0)
+
+ RELOAD_BITS(1)
+ movq %ip1, 0(%rsp)
+ GET_NEXT_DELT(1)
+
+ RELOAD_BITS(2)
+ movq %ip2, 8(%rsp)
+ GET_NEXT_DELT(2)
+
+ RELOAD_BITS(3)
+ movq %ip3, 16(%rsp)
+ GET_NEXT_DELT(3)
+
+ /* If op3 < olimit: continue the loop */
+ cmp %op3, 24(%rsp)
+ ja .L_4X1_loop_body
+
+ /* Reload ip[1,2,3] from stack */
+ movq 0(%rsp), %ip1
+ movq 8(%rsp), %ip2
+ movq 16(%rsp), %ip3
+
+ /* Re-compute olimit */
+ jmp .L_4X1_compute_olimit
+
+#undef GET_NEXT_DELT
+#undef DECODE_FROM_DELT
+#undef DECODE
+#undef RELOAD_BITS
+.L_4X1_exit:
+ addq $24, %rsp
+
+ /* Restore stack (oend & olimit) */
+ pop %rax /* olimit */
+ pop %rax /* oend */
+ pop %rax /* ilimit */
+ pop %rax /* arg */
+
+ /* Save ip / op / bits */
+ movq %ip0, 0(%rax)
+ movq %ip1, 8(%rax)
+ movq %ip2, 16(%rax)
+ movq %ip3, 24(%rax)
+ movq %op0, 32(%rax)
+ movq %op1, 40(%rax)
+ movq %op2, 48(%rax)
+ movq %op3, 56(%rax)
+ movq %bits0, 64(%rax)
+ movq %bits1, 72(%rax)
+ movq %bits2, 80(%rax)
+ movq %bits3, 88(%rax)
+
+ /* Restore registers */
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbp
+ pop %rdx
+ pop %rcx
+ pop %rbx
+ pop %rax
+ ret
+
+_HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
+HUF_decompress4X2_usingDTable_internal_bmi2_asm_loop:
+ /* Save all registers - even if they are callee saved for simplicity. */
+ push %rax
+ push %rbx
+ push %rcx
+ push %rdx
+ push %rbp
+ push %rsi
+ push %rdi
+ push %r8
+ push %r9
+ push %r10
+ push %r11
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ movq %rdi, %rax
+ movq 0(%rax), %ip0
+ movq 8(%rax), %ip1
+ movq 16(%rax), %ip2
+ movq 24(%rax), %ip3
+ movq 32(%rax), %op0
+ movq 40(%rax), %op1
+ movq 48(%rax), %op2
+ movq 56(%rax), %op3
+ movq 64(%rax), %bits0
+ movq 72(%rax), %bits1
+ movq 80(%rax), %bits2
+ movq 88(%rax), %bits3
+ movq 96(%rax), %dtable
+ push %rax /* argument */
+ push %rax /* olimit */
+ push 104(%rax) /* ilimit */
+
+ movq 112(%rax), %rax
+ push %rax /* oend3 */
+
+ movq %op3, %rax
+ push %rax /* oend2 */
+
+ movq %op2, %rax
+ push %rax /* oend1 */
+
+ movq %op1, %rax
+ push %rax /* oend0 */
+
+ /* Scratch space */
+ subq $8, %rsp
+
+.L_4X2_compute_olimit:
+ /* Computes how many iterations we can do safely
+ * %r15, %rax may be clobbered
+ * rdx must be saved
+ * op[1,2,3,4] & ip0 mustn't be clobbered
+ */
+ movq %rdx, 0(%rsp)
+
+ /* We can consume up to 7 input bytes each iteration. */
+ movq %ip0, %rax /* rax = ip0 */
+ movq 40(%rsp), %rdx /* rdx = ilimit */
+ subq %rdx, %rax /* rax = ip0 - ilimit */
+ movq %rax, %r15 /* r15 = ip0 - ilimit */
+
+ /* rdx = rax / 7 */
+ movabsq $2635249153387078803, %rdx
+ mulq %rdx
+ subq %rdx, %r15
+ shrq %r15
+ addq %r15, %rdx
+ shrq $2, %rdx
+
+ /* r15 = (ip0 - ilimit) / 7 */
+ movq %rdx, %r15
+
+ movabsq $-3689348814741910323, %rdx
+ movq 8(%rsp), %rax /* rax = oend0 */
+ subq %op0, %rax /* rax = oend0 - op0 */
+ mulq %rdx
+ shrq $3, %rdx /* rdx = rax / 10 */
+
+ /* r15 = min(%rdx, %r15) */
+ cmpq %rdx, %r15
+ cmova %rdx, %r15
+
+ movabsq $-3689348814741910323, %rdx
+ movq 16(%rsp), %rax /* rax = oend1 */
+ subq %op1, %rax /* rax = oend1 - op1 */
+ mulq %rdx
+ shrq $3, %rdx /* rdx = rax / 10 */
+
+ /* r15 = min(%rdx, %r15) */
+ cmpq %rdx, %r15
+ cmova %rdx, %r15
+
+ movabsq $-3689348814741910323, %rdx
+ movq 24(%rsp), %rax /* rax = oend2 */
+ subq %op2, %rax /* rax = oend2 - op2 */
+ mulq %rdx
+ shrq $3, %rdx /* rdx = rax / 10 */
+
+ /* r15 = min(%rdx, %r15) */
+ cmpq %rdx, %r15
+ cmova %rdx, %r15
+
+ movabsq $-3689348814741910323, %rdx
+ movq 32(%rsp), %rax /* rax = oend3 */
+ subq %op3, %rax /* rax = oend3 - op3 */
+ mulq %rdx
+ shrq $3, %rdx /* rdx = rax / 10 */
+
+ /* r15 = min(%rdx, %r15) */
+ cmpq %rdx, %r15
+ cmova %rdx, %r15
+
+ /* olimit = op3 + 5 * r15 */
+ movq %r15, %rax
+ leaq (%op3, %rax, 4), %olimit
+ addq %rax, %olimit
+
+ movq 0(%rsp), %rdx
+
+ /* If (op3 + 10 > olimit) */
+ movq %op3, %rax /* rax = op3 */
+ addq $10, %rax /* rax = op3 + 10 */
+ cmpq %rax, %olimit /* op3 + 10 > olimit */
+ jb .L_4X2_exit
+
+ /* If (ip1 < ip0) go to exit */
+ cmpq %ip0, %ip1
+ jb .L_4X2_exit
+
+ /* If (ip2 < ip1) go to exit */
+ cmpq %ip1, %ip2
+ jb .L_4X2_exit
+
+ /* If (ip3 < ip2) go to exit */
+ cmpq %ip2, %ip3
+ jb .L_4X2_exit
+
+#define DECODE(n, idx) \
+ movq %bits##n, %rax; \
+ shrq $53, %rax; \
+ movzwl 0(%dtable,%rax,4),%r8d; \
+ movzbl 2(%dtable,%rax,4),%r15d; \
+ movzbl 3(%dtable,%rax,4),%eax; \
+ movw %r8w, (%op##n); \
+ shlxq %r15, %bits##n, %bits##n; \
+ addq %rax, %op##n
+
+#define RELOAD_BITS(n) \
+ bsfq %bits##n, %bits##n; \
+ movq %bits##n, %rax; \
+ shrq $3, %bits##n; \
+ andq $7, %rax; \
+ subq %bits##n, %ip##n; \
+ movq (%ip##n), %bits##n; \
+ orq $1, %bits##n; \
+ shlxq %rax, %bits##n, %bits##n
+
+
+ movq %olimit, 48(%rsp)
+
+ .p2align 6
+
+.L_4X2_loop_body:
+ /* We clobber r8, so store it on the stack */
+ movq %r8, 0(%rsp)
+
+ /* Decode 5 symbols from each of the 4 streams (20 symbols total). */
+ FOR_EACH_STREAM_WITH_INDEX(DECODE, 0)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE, 1)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE, 2)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE, 3)
+ FOR_EACH_STREAM_WITH_INDEX(DECODE, 4)
+
+ /* Reload r8 */
+ movq 0(%rsp), %r8
+
+ FOR_EACH_STREAM(RELOAD_BITS)
+
+ cmp %op3, 48(%rsp)
+ ja .L_4X2_loop_body
+ jmp .L_4X2_compute_olimit
+
+#undef DECODE
+#undef RELOAD_BITS
+.L_4X2_exit:
+ addq $8, %rsp
+ /* Restore stack (oend & olimit) */
+ pop %rax /* oend0 */
+ pop %rax /* oend1 */
+ pop %rax /* oend2 */
+ pop %rax /* oend3 */
+ pop %rax /* ilimit */
+ pop %rax /* olimit */
+ pop %rax /* arg */
+
+ /* Save ip / op / bits */
+ movq %ip0, 0(%rax)
+ movq %ip1, 8(%rax)
+ movq %ip2, 16(%rax)
+ movq %ip3, 24(%rax)
+ movq %op0, 32(%rax)
+ movq %op1, 40(%rax)
+ movq %op2, 48(%rax)
+ movq %op3, 56(%rax)
+ movq %bits0, 64(%rax)
+ movq %bits1, 72(%rax)
+ movq %bits2, 80(%rax)
+ movq %bits3, 88(%rax)
+
+ /* Restore registers */
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbp
+ pop %rdx
+ pop %rcx
+ pop %rbx
+ pop %rax
+ ret
+
+#endif
diff --git a/thirdparty/zstd/decompress/zstd_decompress.c b/thirdparty/zstd/decompress/zstd_decompress.c
index 910bc034c0..0031e98cfb 100644
--- a/thirdparty/zstd/decompress/zstd_decompress.c
+++ b/thirdparty/zstd/decompress/zstd_decompress.c
@@ -56,7 +56,6 @@
* Dependencies
*********************************************************/
#include "../common/zstd_deps.h" /* ZSTD_memcpy, ZSTD_memmove, ZSTD_memset */
-#include "../common/cpu.h" /* bmi2 */
#include "../common/mem.h" /* low level memory routines */
#define FSE_STATIC_LINKING_ONLY
#include "../common/fse.h"
@@ -177,12 +176,15 @@ static const ZSTD_DDict* ZSTD_DDictHashSet_getDDict(ZSTD_DDictHashSet* hashSet,
static ZSTD_DDictHashSet* ZSTD_createDDictHashSet(ZSTD_customMem customMem) {
ZSTD_DDictHashSet* ret = (ZSTD_DDictHashSet*)ZSTD_customMalloc(sizeof(ZSTD_DDictHashSet), customMem);
DEBUGLOG(4, "Allocating new hash set");
+ if (!ret)
+ return NULL;
ret->ddictPtrTable = (const ZSTD_DDict**)ZSTD_customCalloc(DDICT_HASHSET_TABLE_BASE_SIZE * sizeof(ZSTD_DDict*), customMem);
- ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
- ret->ddictPtrCount = 0;
- if (!ret || !ret->ddictPtrTable) {
+ if (!ret->ddictPtrTable) {
+ ZSTD_customFree(ret, customMem);
return NULL;
}
+ ret->ddictPtrTableSize = DDICT_HASHSET_TABLE_BASE_SIZE;
+ ret->ddictPtrCount = 0;
return ret;
}
@@ -255,11 +257,15 @@ static void ZSTD_initDCtx_internal(ZSTD_DCtx* dctx)
dctx->inBuffSize = 0;
dctx->outBuffSize = 0;
dctx->streamStage = zdss_init;
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
dctx->legacyContext = NULL;
dctx->previousLegacyVersion = 0;
+#endif
dctx->noForwardProgress = 0;
dctx->oversizedDuration = 0;
- dctx->bmi2 = ZSTD_cpuid_bmi2(ZSTD_cpuid());
+#if DYNAMIC_BMI2
+ dctx->bmi2 = ZSTD_cpuSupportsBmi2();
+#endif
dctx->ddictSet = NULL;
ZSTD_DCtx_resetParameters(dctx);
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
@@ -280,8 +286,7 @@ ZSTD_DCtx* ZSTD_initStaticDCtx(void *workspace, size_t workspaceSize)
return dctx;
}
-ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
-{
+static ZSTD_DCtx* ZSTD_createDCtx_internal(ZSTD_customMem customMem) {
if ((!customMem.customAlloc) ^ (!customMem.customFree)) return NULL;
{ ZSTD_DCtx* const dctx = (ZSTD_DCtx*)ZSTD_customMalloc(sizeof(*dctx), customMem);
@@ -292,10 +297,15 @@ ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
}
}
+ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem)
+{
+ return ZSTD_createDCtx_internal(customMem);
+}
+
ZSTD_DCtx* ZSTD_createDCtx(void)
{
DEBUGLOG(3, "ZSTD_createDCtx");
- return ZSTD_createDCtx_advanced(ZSTD_defaultCMem);
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
}
static void ZSTD_clearDict(ZSTD_DCtx* dctx)
@@ -380,6 +390,19 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size)
return 0;
}
+/*! ZSTD_isSkippableFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
+ * Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
+ */
+unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
+{
+ if (size < ZSTD_FRAMEIDSIZE) return 0;
+ { U32 const magic = MEM_readLE32(buffer);
+ if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1;
+ }
+ return 0;
+}
+
/** ZSTD_frameHeaderSize_internal() :
* srcSize must be large enough to reach header size fields.
* note : only works for formats ZSTD_f_zstd1 and ZSTD_f_zstd1_magicless.
@@ -466,7 +489,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
}
switch(dictIDSizeCode)
{
- default: assert(0); /* impossible */
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
case 0 : break;
case 1 : dictID = ip[pos]; pos++; break;
case 2 : dictID = MEM_readLE16(ip+pos); pos+=2; break;
@@ -474,7 +499,9 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s
}
switch(fcsID)
{
- default: assert(0); /* impossible */
+ default:
+ assert(0); /* impossible */
+ ZSTD_FALLTHROUGH;
case 0 : if (singleSegment) frameContentSize = ip[pos]; break;
case 1 : frameContentSize = MEM_readLE16(ip+pos)+256; break;
case 2 : frameContentSize = MEM_readLE32(ip+pos); break;
@@ -503,7 +530,6 @@ size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t src
return ZSTD_getFrameHeader_advanced(zfhPtr, src, srcSize, ZSTD_f_zstd1);
}
-
/** ZSTD_getFrameContentSize() :
* compatible with legacy mode
* @return : decompressed size of the single frame pointed to be `src` if known, otherwise
@@ -544,6 +570,37 @@ static size_t readSkippableFrameSize(void const* src, size_t srcSize)
}
}
+/*! ZSTD_readSkippableFrame() :
+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
+ * in the magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
+ const void* src, size_t srcSize)
+{
+ U32 const magicNumber = MEM_readLE32(src);
+ size_t skippableFrameSize = readSkippableFrameSize(src, srcSize);
+ size_t skippableContentSize = skippableFrameSize - ZSTD_SKIPPABLEHEADERSIZE;
+
+ /* check input validity */
+ RETURN_ERROR_IF(!ZSTD_isSkippableFrame(src, srcSize), frameParameter_unsupported, "");
+ RETURN_ERROR_IF(skippableFrameSize < ZSTD_SKIPPABLEHEADERSIZE || skippableFrameSize > srcSize, srcSize_wrong, "");
+ RETURN_ERROR_IF(skippableContentSize > dstCapacity, dstSize_tooSmall, "");
+
+ /* deliver payload */
+ if (skippableContentSize > 0 && dst != NULL)
+ ZSTD_memcpy(dst, (const BYTE *)src + ZSTD_SKIPPABLEHEADERSIZE, skippableContentSize);
+ if (magicVariant != NULL)
+ *magicVariant = magicNumber - ZSTD_MAGIC_SKIPPABLE_START;
+ return skippableContentSize;
+}
+
/** ZSTD_findDecompressedSize() :
* compatible with legacy mode
* `srcSize` must be the exact length of some number of ZSTD compressed and/or
@@ -858,7 +915,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx,
switch(blockProperties.blockType)
{
case bt_compressed:
- decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1);
+ decodedSize = ZSTD_decompressBlock_internal(dctx, op, (size_t)(oend-op), ip, cBlockSize, /* frame */ 1, not_streaming);
break;
case bt_raw :
decodedSize = ZSTD_copyRawBlock(op, (size_t)(oend-op), ip, cBlockSize);
@@ -1009,7 +1066,7 @@ static ZSTD_DDict const* ZSTD_getDDict(ZSTD_DCtx* dctx)
switch (dctx->dictUses) {
default:
assert(0 /* Impossible */);
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case ZSTD_dont_use:
ZSTD_clearDict(dctx);
return NULL;
@@ -1031,7 +1088,7 @@ size_t ZSTD_decompress(void* dst, size_t dstCapacity, const void* src, size_t sr
{
#if defined(ZSTD_HEAPMODE) && (ZSTD_HEAPMODE>=1)
size_t regenSize;
- ZSTD_DCtx* const dctx = ZSTD_createDCtx();
+ ZSTD_DCtx* const dctx = ZSTD_createDCtx_internal(ZSTD_defaultCMem);
RETURN_ERROR_IF(dctx==NULL, memory_allocation, "NULL pointer!");
regenSize = ZSTD_decompressDCtx(dctx, dst, dstCapacity, src, srcSize);
ZSTD_freeDCtx(dctx);
@@ -1065,7 +1122,7 @@ static size_t ZSTD_nextSrcSizeToDecompressWithInputSize(ZSTD_DCtx* dctx, size_t
return dctx->expected;
if (dctx->bType != bt_raw)
return dctx->expected;
- return MIN(MAX(inputSize, 1), dctx->expected);
+ return BOUNDED(1, inputSize, dctx->expected);
}
ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
@@ -1073,7 +1130,9 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
{
default: /* should not happen */
assert(0);
+ ZSTD_FALLTHROUGH;
case ZSTDds_getFrameHeaderSize:
+ ZSTD_FALLTHROUGH;
case ZSTDds_decodeFrameHeader:
return ZSTDnit_frameHeader;
case ZSTDds_decodeBlockHeader:
@@ -1085,6 +1144,7 @@ ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx) {
case ZSTDds_checkChecksum:
return ZSTDnit_checksum;
case ZSTDds_decodeSkippableHeader:
+ ZSTD_FALLTHROUGH;
case ZSTDds_skipFrame:
return ZSTDnit_skippableFrame;
}
@@ -1168,7 +1228,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c
{
case bt_compressed:
DEBUGLOG(5, "ZSTD_decompressContinue: case bt_compressed");
- rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1);
+ rSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 1, is_streaming);
dctx->expected = 0; /* Streaming not supported */
break;
case bt_raw :
@@ -1493,7 +1553,7 @@ size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
ZSTD_DStream* ZSTD_createDStream(void)
{
DEBUGLOG(3, "ZSTD_createDStream");
- return ZSTD_createDStream_advanced(ZSTD_defaultCMem);
+ return ZSTD_createDCtx_internal(ZSTD_defaultCMem);
}
ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
@@ -1503,7 +1563,7 @@ ZSTD_DStream* ZSTD_initStaticDStream(void *workspace, size_t workspaceSize)
ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
{
- return ZSTD_createDCtx_advanced(customMem);
+ return ZSTD_createDCtx_internal(customMem);
}
size_t ZSTD_freeDStream(ZSTD_DStream* zds)
@@ -1763,7 +1823,8 @@ size_t ZSTD_sizeof_DStream(const ZSTD_DStream* dctx)
size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize)
{
size_t const blockSize = (size_t) MIN(windowSize, ZSTD_BLOCKSIZE_MAX);
- unsigned long long const neededRBSize = windowSize + blockSize + (WILDCOPY_OVERLENGTH * 2);
+ /* space is needed to store the litbuffer after the output of a given block without stomping the extDict of a previous run, as well as to cover both windows against wildcopy*/
+ unsigned long long const neededRBSize = windowSize + blockSize + ZSTD_BLOCKSIZE_MAX + (WILDCOPY_OVERLENGTH * 2);
unsigned long long const neededSize = MIN(frameContentSize, neededRBSize);
size_t const minRBSize = (size_t) neededSize;
RETURN_ERROR_IF((unsigned long long)minRBSize != neededSize,
@@ -1897,10 +1958,12 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
DEBUGLOG(5, "stage zdss_init => transparent reset ");
zds->streamStage = zdss_loadHeader;
zds->lhSize = zds->inPos = zds->outStart = zds->outEnd = 0;
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
zds->legacyVersion = 0;
+#endif
zds->hostageByte = 0;
zds->expectedOutBuffer = *output;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case zdss_loadHeader :
DEBUGLOG(5, "stage zdss_loadHeader (srcSize : %u)", (U32)(iend - ip));
@@ -2038,7 +2101,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
zds->outBuffSize = neededOutBuffSize;
} } }
zds->streamStage = zdss_read;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case zdss_read:
DEBUGLOG(5, "stage zdss_read");
@@ -2057,7 +2120,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
} }
if (ip==iend) { someMoreWork = 0; break; } /* no more input */
zds->streamStage = zdss_load;
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case zdss_load:
{ size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds);
diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.c b/thirdparty/zstd/decompress/zstd_decompress_block.c
index 349dcdc333..2e44d30d2f 100644
--- a/thirdparty/zstd/decompress/zstd_decompress_block.c
+++ b/thirdparty/zstd/decompress/zstd_decompress_block.c
@@ -69,15 +69,56 @@ size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
}
}
+/* Allocate buffer for literals, either overlapping current dst, or split between dst and litExtraBuffer, or stored entirely within litExtraBuffer */
+static void ZSTD_allocateLiteralsBuffer(ZSTD_DCtx* dctx, void* const dst, const size_t dstCapacity, const size_t litSize,
+ const streaming_operation streaming, const size_t expectedWriteSize, const unsigned splitImmediately)
+{
+ if (streaming == not_streaming && dstCapacity > ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH + litSize + WILDCOPY_OVERLENGTH)
+ {
+ /* room for litbuffer to fit without read faulting */
+ dctx->litBuffer = (BYTE*)dst + ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd = dctx->litBuffer + litSize;
+ dctx->litBufferLocation = ZSTD_in_dst;
+ }
+ else if (litSize > ZSTD_LITBUFFEREXTRASIZE)
+ {
+ /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */
+ if (splitImmediately) {
+ /* won't fit in litExtraBuffer, so it will be split between end of dst and extra buffer */
+ dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd = dctx->litBuffer + litSize - ZSTD_LITBUFFEREXTRASIZE;
+ }
+ else {
+ /* initially this will be stored entirely in dst during huffman decoding, it will partially shifted to litExtraBuffer after */
+ dctx->litBuffer = (BYTE*)dst + expectedWriteSize - litSize;
+ dctx->litBufferEnd = (BYTE*)dst + expectedWriteSize;
+ }
+ dctx->litBufferLocation = ZSTD_split;
+ }
+ else
+ {
+ /* fits entirely within litExtraBuffer, so no split is necessary */
+ dctx->litBuffer = dctx->litExtraBuffer;
+ dctx->litBufferEnd = dctx->litBuffer + litSize;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ }
+}
/* Hidden declaration for fullbench */
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
- const void* src, size_t srcSize);
+ const void* src, size_t srcSize,
+ void* dst, size_t dstCapacity, const streaming_operation streaming);
/*! ZSTD_decodeLiteralsBlock() :
+ * Where it is possible to do so without being stomped by the output during decompression, the literals block will be stored
+ * in the dstBuffer. If there is room to do so, it will be stored in full in the excess dst space after where the current
+ * block will be output. Otherwise it will be stored at the end of the current dst blockspace, with a small portion being
+ * stored in dctx->litExtraBuffer to help keep it "ahead" of the current output write.
+ *
* @return : nb of bytes read from src (< srcSize )
* note : symbol not declared but exposed for fullbench */
size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
- const void* src, size_t srcSize) /* note : srcSize < BLOCKSIZE */
+ const void* src, size_t srcSize, /* note : srcSize < BLOCKSIZE */
+ void* dst, size_t dstCapacity, const streaming_operation streaming)
{
DEBUGLOG(5, "ZSTD_decodeLiteralsBlock");
RETURN_ERROR_IF(srcSize < MIN_CBLOCK_SIZE, corruption_detected, "");
@@ -90,7 +131,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
case set_repeat:
DEBUGLOG(5, "set_repeat flag : re-using stats from previous compressed literals block");
RETURN_ERROR_IF(dctx->litEntropy==0, dictionary_corrupted, "");
- /* fall-through */
+ ZSTD_FALLTHROUGH;
case set_compressed:
RETURN_ERROR_IF(srcSize < 5, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3");
@@ -99,6 +140,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
U32 const lhlCode = (istart[0] >> 2) & 3;
U32 const lhc = MEM_readLE32(istart);
size_t hufSuccess;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
switch(lhlCode)
{
case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
@@ -121,8 +163,11 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
litCSize = (lhc >> 22) + ((size_t)istart[4] << 10);
break;
}
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
RETURN_ERROR_IF(litCSize + lhSize > srcSize, corruption_detected, "");
+ RETURN_ERROR_IF(expectedWriteSize < litSize , dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 0);
/* prefetch huffman table if cold */
if (dctx->ddictIsCold && (litSize > 768 /* heuristic */)) {
@@ -133,11 +178,11 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
if (singleStream) {
hufSuccess = HUF_decompress1X_usingDTable_bmi2(
dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->HUFptr, dctx->bmi2);
+ dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
} else {
hufSuccess = HUF_decompress4X_usingDTable_bmi2(
dctx->litBuffer, litSize, istart+lhSize, litCSize,
- dctx->HUFptr, dctx->bmi2);
+ dctx->HUFptr, ZSTD_DCtx_get_bmi2(dctx));
}
} else {
if (singleStream) {
@@ -150,15 +195,22 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
hufSuccess = HUF_decompress1X1_DCtx_wksp_bmi2(
dctx->entropy.hufTable, dctx->litBuffer, litSize,
istart+lhSize, litCSize, dctx->workspace,
- sizeof(dctx->workspace), dctx->bmi2);
+ sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
#endif
} else {
hufSuccess = HUF_decompress4X_hufOnly_wksp_bmi2(
dctx->entropy.hufTable, dctx->litBuffer, litSize,
istart+lhSize, litCSize, dctx->workspace,
- sizeof(dctx->workspace), dctx->bmi2);
+ sizeof(dctx->workspace), ZSTD_DCtx_get_bmi2(dctx));
}
}
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memcpy(dctx->litExtraBuffer, dctx->litBufferEnd - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memmove(dctx->litBuffer + ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH, dctx->litBuffer, litSize - ZSTD_LITBUFFEREXTRASIZE);
+ dctx->litBuffer += ZSTD_LITBUFFEREXTRASIZE - WILDCOPY_OVERLENGTH;
+ dctx->litBufferEnd -= WILDCOPY_OVERLENGTH;
+ }
RETURN_ERROR_IF(HUF_isError(hufSuccess), corruption_detected, "");
@@ -166,13 +218,13 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
dctx->litSize = litSize;
dctx->litEntropy = 1;
if (litEncType==set_compressed) dctx->HUFptr = dctx->entropy.hufTable;
- ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
return litCSize + lhSize;
}
case set_basic:
{ size_t litSize, lhSize;
U32 const lhlCode = ((istart[0]) >> 2) & 3;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
switch(lhlCode)
{
case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
@@ -189,23 +241,36 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
break;
}
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
+ RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);
if (lhSize+litSize+WILDCOPY_OVERLENGTH > srcSize) { /* risk reading beyond src buffer with wildcopy */
RETURN_ERROR_IF(litSize+lhSize > srcSize, corruption_detected, "");
- ZSTD_memcpy(dctx->litBuffer, istart+lhSize, litSize);
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize - ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memcpy(dctx->litExtraBuffer, istart + lhSize + litSize - ZSTD_LITBUFFEREXTRASIZE, ZSTD_LITBUFFEREXTRASIZE);
+ }
+ else
+ {
+ ZSTD_memcpy(dctx->litBuffer, istart + lhSize, litSize);
+ }
dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize;
- ZSTD_memset(dctx->litBuffer + dctx->litSize, 0, WILDCOPY_OVERLENGTH);
return lhSize+litSize;
}
/* direct reference into compressed stream */
dctx->litPtr = istart+lhSize;
dctx->litSize = litSize;
+ dctx->litBufferEnd = dctx->litPtr + litSize;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
return lhSize+litSize;
}
case set_rle:
{ U32 const lhlCode = ((istart[0]) >> 2) & 3;
size_t litSize, lhSize;
+ size_t expectedWriteSize = MIN(ZSTD_BLOCKSIZE_MAX, dstCapacity);
switch(lhlCode)
{
case 0: case 2: default: /* note : default is impossible, since lhlCode into [0..3] */
@@ -222,8 +287,19 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
RETURN_ERROR_IF(srcSize<4, corruption_detected, "srcSize >= MIN_CBLOCK_SIZE == 3; here we need lhSize+1 = 4");
break;
}
+ RETURN_ERROR_IF(litSize > 0 && dst == NULL, dstSize_tooSmall, "NULL not handled");
RETURN_ERROR_IF(litSize > ZSTD_BLOCKSIZE_MAX, corruption_detected, "");
- ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize + WILDCOPY_OVERLENGTH);
+ RETURN_ERROR_IF(expectedWriteSize < litSize, dstSize_tooSmall, "");
+ ZSTD_allocateLiteralsBuffer(dctx, dst, dstCapacity, litSize, streaming, expectedWriteSize, 1);
+ if (dctx->litBufferLocation == ZSTD_split)
+ {
+ ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize - ZSTD_LITBUFFEREXTRASIZE);
+ ZSTD_memset(dctx->litExtraBuffer, istart[lhSize], ZSTD_LITBUFFEREXTRASIZE);
+ }
+ else
+ {
+ ZSTD_memset(dctx->litBuffer, istart[lhSize], litSize);
+ }
dctx->litPtr = dctx->litBuffer;
dctx->litSize = litSize;
return lhSize+1;
@@ -343,7 +419,7 @@ static const ZSTD_seqSymbol ML_defaultDTable[(1<<ML_DEFAULTNORMLOG)+1] = {
}; /* ML_defaultDTable */
-static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddBits)
+static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U8 nbAddBits)
{
void* ptr = dt;
ZSTD_seqSymbol_header* const DTableH = (ZSTD_seqSymbol_header*)ptr;
@@ -355,7 +431,7 @@ static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddB
cell->nbBits = 0;
cell->nextState = 0;
assert(nbAddBits < 255);
- cell->nbAdditionalBits = (BYTE)nbAddBits;
+ cell->nbAdditionalBits = nbAddBits;
cell->baseValue = baseValue;
}
@@ -367,7 +443,7 @@ static void ZSTD_buildSeqTable_rle(ZSTD_seqSymbol* dt, U32 baseValue, U32 nbAddB
FORCE_INLINE_TEMPLATE
void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
unsigned tableLog, void* wksp, size_t wkspSize)
{
ZSTD_seqSymbol* const tableDecode = dt+1;
@@ -478,7 +554,7 @@ void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
tableDecode[u].nbBits = (BYTE) (tableLog - BIT_highbit32(nextState) );
tableDecode[u].nextState = (U16) ( (nextState << tableDecode[u].nbBits) - tableSize);
assert(nbAdditionalBits[symbol] < 255);
- tableDecode[u].nbAdditionalBits = (BYTE)nbAdditionalBits[symbol];
+ tableDecode[u].nbAdditionalBits = nbAdditionalBits[symbol];
tableDecode[u].baseValue = baseValue[symbol];
}
}
@@ -487,7 +563,7 @@ void ZSTD_buildFSETable_body(ZSTD_seqSymbol* dt,
/* Avoids the FORCE_INLINE of the _body() function. */
static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
unsigned tableLog, void* wksp, size_t wkspSize)
{
ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
@@ -495,9 +571,9 @@ static void ZSTD_buildFSETable_body_default(ZSTD_seqSymbol* dt,
}
#if DYNAMIC_BMI2
-TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,
+BMI2_TARGET_ATTRIBUTE static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
unsigned tableLog, void* wksp, size_t wkspSize)
{
ZSTD_buildFSETable_body(dt, normalizedCounter, maxSymbolValue,
@@ -507,7 +583,7 @@ TARGET_ATTRIBUTE("bmi2") static void ZSTD_buildFSETable_body_bmi2(ZSTD_seqSymbol
void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
unsigned tableLog, void* wksp, size_t wkspSize, int bmi2)
{
#if DYNAMIC_BMI2
@@ -529,7 +605,7 @@ void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymbol** DTablePtr,
symbolEncodingType_e type, unsigned max, U32 maxLog,
const void* src, size_t srcSize,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
const ZSTD_seqSymbol* defaultTable, U32 flagRepeatTable,
int ddictIsCold, int nbSeq, U32* wksp, size_t wkspSize,
int bmi2)
@@ -541,7 +617,7 @@ static size_t ZSTD_buildSeqTable(ZSTD_seqSymbol* DTableSpace, const ZSTD_seqSymb
RETURN_ERROR_IF((*(const BYTE*)src) > max, corruption_detected, "");
{ U32 const symbol = *(const BYTE*)src;
U32 const baseline = baseValue[symbol];
- U32 const nbBits = nbAdditionalBits[symbol];
+ U8 const nbBits = nbAdditionalBits[symbol];
ZSTD_buildSeqTable_rle(DTableSpace, baseline, nbBits);
}
*DTablePtr = DTableSpace;
@@ -620,7 +696,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
LL_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
dctx->workspace, sizeof(dctx->workspace),
- dctx->bmi2);
+ ZSTD_DCtx_get_bmi2(dctx));
RETURN_ERROR_IF(ZSTD_isError(llhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += llhSize;
}
@@ -632,7 +708,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
OF_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
dctx->workspace, sizeof(dctx->workspace),
- dctx->bmi2);
+ ZSTD_DCtx_get_bmi2(dctx));
RETURN_ERROR_IF(ZSTD_isError(ofhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += ofhSize;
}
@@ -644,7 +720,7 @@ size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
ML_defaultDTable, dctx->fseEntropy,
dctx->ddictIsCold, nbSeq,
dctx->workspace, sizeof(dctx->workspace),
- dctx->bmi2);
+ ZSTD_DCtx_get_bmi2(dctx));
RETURN_ERROR_IF(ZSTD_isError(mlhSize), corruption_detected, "ZSTD_buildSeqTable failed");
ip += mlhSize;
}
@@ -713,7 +789,7 @@ HINT_INLINE void ZSTD_overlapCopy8(BYTE** op, BYTE const** ip, size_t offset) {
* - ZSTD_overlap_src_before_dst: The src and dst may overlap and may be any distance apart.
* The src buffer must be before the dst buffer.
*/
-static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {
+static void ZSTD_safecopy(BYTE* op, const BYTE* const oend_w, BYTE const* ip, ptrdiff_t length, ZSTD_overlap_e ovtype) {
ptrdiff_t const diff = op - ip;
BYTE* const oend = op + length;
@@ -729,6 +805,7 @@ static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_
/* Copy 8 bytes and ensure the offset >= 8 when there can be overlap. */
assert(length >= 8);
ZSTD_overlapCopy8(&op, &ip, diff);
+ length -= 8;
assert(op - ip >= 8);
assert(op <= oend);
}
@@ -743,12 +820,35 @@ static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_
assert(oend > oend_w);
ZSTD_wildcopy(op, ip, oend_w - op, ovtype);
ip += oend_w - op;
- op = oend_w;
+ op += oend_w - op;
}
/* Handle the leftovers. */
while (op < oend) *op++ = *ip++;
}
+/* ZSTD_safecopyDstBeforeSrc():
+ * This version allows overlap with dst before src, or handles the non-overlap case with dst after src
+ * Kept separate from more common ZSTD_safecopy case to avoid performance impact to the safecopy common case */
+static void ZSTD_safecopyDstBeforeSrc(BYTE* op, BYTE const* ip, ptrdiff_t length) {
+ ptrdiff_t const diff = op - ip;
+ BYTE* const oend = op + length;
+
+ if (length < 8 || diff > -8) {
+ /* Handle short lengths, close overlaps, and dst not before src. */
+ while (op < oend) *op++ = *ip++;
+ return;
+ }
+
+ if (op <= oend - WILDCOPY_OVERLENGTH && diff < -WILDCOPY_VECLEN) {
+ ZSTD_wildcopy(op, ip, oend - WILDCOPY_OVERLENGTH - op, ZSTD_no_overlap);
+ ip += oend - WILDCOPY_OVERLENGTH - op;
+ op += oend - WILDCOPY_OVERLENGTH - op;
+ }
+
+ /* Handle the leftovers. */
+ while (op < oend) *op++ = *ip++;
+}
+
/* ZSTD_execSequenceEnd():
* This version handles cases that are near the end of the output buffer. It requires
* more careful checks to make sure there is no overflow. By separating out these hard
@@ -759,9 +859,9 @@ static void ZSTD_safecopy(BYTE* op, BYTE* const oend_w, BYTE const* ip, ptrdiff_
*/
FORCE_NOINLINE
size_t ZSTD_execSequenceEnd(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
{
BYTE* const oLitEnd = op + sequence.litLength;
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
@@ -784,27 +884,76 @@ size_t ZSTD_execSequenceEnd(BYTE* op,
if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
/* offset beyond prefix */
RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
- match = dictEnd - (prefixStart-match);
+ match = dictEnd - (prefixStart - match);
if (match + sequence.matchLength <= dictEnd) {
ZSTD_memmove(oLitEnd, match, sequence.matchLength);
return sequenceLength;
}
/* span extDict & currentPrefixSegment */
{ size_t const length1 = dictEnd - match;
- ZSTD_memmove(oLitEnd, match, length1);
- op = oLitEnd + length1;
- sequence.matchLength -= length1;
- match = prefixStart;
- } }
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
+ ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);
+ return sequenceLength;
+}
+
+/* ZSTD_execSequenceEndSplitLitBuffer():
+ * This version is intended to be used during instances where the litBuffer is still split. It is kept separate to avoid performance impact for the good case.
+ */
+FORCE_NOINLINE
+size_t ZSTD_execSequenceEndSplitLitBuffer(BYTE* op,
+ BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+
+ /* bounds checks : careful of address space overflow in 32-bit mode */
+ RETURN_ERROR_IF(sequenceLength > (size_t)(oend - op), dstSize_tooSmall, "last match must fit within dstBuffer");
+ RETURN_ERROR_IF(sequence.litLength > (size_t)(litLimit - *litPtr), corruption_detected, "try to read beyond literal buffer");
+ assert(op < op + sequenceLength);
+ assert(oLitEnd < op + sequenceLength);
+
+ /* copy literals */
+ RETURN_ERROR_IF(op > *litPtr && op < *litPtr + sequence.litLength, dstSize_tooSmall, "output should not catch up to and overwrite literal buffer");
+ ZSTD_safecopyDstBeforeSrc(op, *litPtr, sequence.litLength);
+ op = oLitEnd;
+ *litPtr = iLitEnd;
+
+ /* copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix */
+ RETURN_ERROR_IF(sequence.offset > (size_t)(oLitEnd - virtualStart), corruption_detected, "");
+ match = dictEnd - (prefixStart - match);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
ZSTD_safecopy(op, oend_w, match, sequence.matchLength, ZSTD_overlap_src_before_dst);
return sequenceLength;
}
HINT_INLINE
size_t ZSTD_execSequence(BYTE* op,
- BYTE* const oend, seq_t sequence,
- const BYTE** litPtr, const BYTE* const litLimit,
- const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+ BYTE* const oend, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
{
BYTE* const oLitEnd = op + sequence.litLength;
size_t const sequenceLength = sequence.litLength + sequence.matchLength;
@@ -821,10 +970,102 @@ size_t ZSTD_execSequence(BYTE* op,
* - 32-bit mode and the match length overflows
*/
if (UNLIKELY(
+ iLitEnd > litLimit ||
+ oMatchEnd > oend_w ||
+ (MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))
+ return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
+
+ /* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */
+ assert(op <= oLitEnd /* No overflow */);
+ assert(oLitEnd < oMatchEnd /* Non-zero match & no overflow */);
+ assert(oMatchEnd <= oend /* No underflow */);
+ assert(iLitEnd <= litLimit /* Literal length is in bounds */);
+ assert(oLitEnd <= oend_w /* Can wildcopy literals */);
+ assert(oMatchEnd <= oend_w /* Can wildcopy matches */);
+
+ /* Copy Literals:
+ * Split out litLength <= 16 since it is nearly always true. +1.6% on gcc-9.
+ * We likely don't need the full 32-byte wildcopy.
+ */
+ assert(WILDCOPY_OVERLENGTH >= 16);
+ ZSTD_copy16(op, (*litPtr));
+ if (UNLIKELY(sequence.litLength > 16)) {
+ ZSTD_wildcopy(op + 16, (*litPtr) + 16, sequence.litLength - 16, ZSTD_no_overlap);
+ }
+ op = oLitEnd;
+ *litPtr = iLitEnd; /* update for next sequence */
+
+ /* Copy Match */
+ if (sequence.offset > (size_t)(oLitEnd - prefixStart)) {
+ /* offset beyond prefix -> go into extDict */
+ RETURN_ERROR_IF(UNLIKELY(sequence.offset > (size_t)(oLitEnd - virtualStart)), corruption_detected, "");
+ match = dictEnd + (match - prefixStart);
+ if (match + sequence.matchLength <= dictEnd) {
+ ZSTD_memmove(oLitEnd, match, sequence.matchLength);
+ return sequenceLength;
+ }
+ /* span extDict & currentPrefixSegment */
+ { size_t const length1 = dictEnd - match;
+ ZSTD_memmove(oLitEnd, match, length1);
+ op = oLitEnd + length1;
+ sequence.matchLength -= length1;
+ match = prefixStart;
+ }
+ }
+ /* Match within prefix of 1 or more bytes */
+ assert(op <= oMatchEnd);
+ assert(oMatchEnd <= oend_w);
+ assert(match >= prefixStart);
+ assert(sequence.matchLength >= 1);
+
+ /* Nearly all offsets are >= WILDCOPY_VECLEN bytes, which means we can use wildcopy
+ * without overlap checking.
+ */
+ if (LIKELY(sequence.offset >= WILDCOPY_VECLEN)) {
+ /* We bet on a full wildcopy for matches, since we expect matches to be
+ * longer than literals (in general). In silesia, ~10% of matches are longer
+ * than 16 bytes.
+ */
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength, ZSTD_no_overlap);
+ return sequenceLength;
+ }
+ assert(sequence.offset < WILDCOPY_VECLEN);
+
+ /* Copy 8 bytes and spread the offset to be >= 8. */
+ ZSTD_overlapCopy8(&op, &match, sequence.offset);
+
+ /* If the match length is > 8 bytes, then continue with the wildcopy. */
+ if (sequence.matchLength > 8) {
+ assert(op < oMatchEnd);
+ ZSTD_wildcopy(op, match, (ptrdiff_t)sequence.matchLength - 8, ZSTD_overlap_src_before_dst);
+ }
+ return sequenceLength;
+}
+
+HINT_INLINE
+size_t ZSTD_execSequenceSplitLitBuffer(BYTE* op,
+ BYTE* const oend, const BYTE* const oend_w, seq_t sequence,
+ const BYTE** litPtr, const BYTE* const litLimit,
+ const BYTE* const prefixStart, const BYTE* const virtualStart, const BYTE* const dictEnd)
+{
+ BYTE* const oLitEnd = op + sequence.litLength;
+ size_t const sequenceLength = sequence.litLength + sequence.matchLength;
+ BYTE* const oMatchEnd = op + sequenceLength; /* risk : address space overflow (32-bits) */
+ const BYTE* const iLitEnd = *litPtr + sequence.litLength;
+ const BYTE* match = oLitEnd - sequence.offset;
+
+ assert(op != NULL /* Precondition */);
+ assert(oend_w < oend /* No underflow */);
+ /* Handle edge cases in a slow path:
+ * - Read beyond end of literals
+ * - Match end is within WILDCOPY_OVERLIMIT of oend
+ * - 32-bit mode and the match length overflows
+ */
+ if (UNLIKELY(
iLitEnd > litLimit ||
oMatchEnd > oend_w ||
(MEM_32bits() && (size_t)(oend - op) < sequenceLength + WILDCOPY_OVERLENGTH)))
- return ZSTD_execSequenceEnd(op, oend, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
+ return ZSTD_execSequenceEndSplitLitBuffer(op, oend, oend_w, sequence, litPtr, litLimit, prefixStart, virtualStart, dictEnd);
/* Assumptions (everything else goes into ZSTD_execSequenceEnd()) */
assert(op <= oLitEnd /* No overflow */);
@@ -892,6 +1133,7 @@ size_t ZSTD_execSequence(BYTE* op,
return sequenceLength;
}
+
static void
ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqSymbol* dt)
{
@@ -905,20 +1147,10 @@ ZSTD_initFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, const ZSTD_seqS
}
FORCE_INLINE_TEMPLATE void
-ZSTD_updateFseState(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD)
-{
- ZSTD_seqSymbol const DInfo = DStatePtr->table[DStatePtr->state];
- U32 const nbBits = DInfo.nbBits;
- size_t const lowBits = BIT_readBits(bitD, nbBits);
- DStatePtr->state = DInfo.nextState + lowBits;
-}
-
-FORCE_INLINE_TEMPLATE void
-ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, ZSTD_seqSymbol const DInfo)
+ZSTD_updateFseStateWithDInfo(ZSTD_fseState* DStatePtr, BIT_DStream_t* bitD, U16 nextState, U32 nbBits)
{
- U32 const nbBits = DInfo.nbBits;
size_t const lowBits = BIT_readBits(bitD, nbBits);
- DStatePtr->state = DInfo.nextState + lowBits;
+ DStatePtr->state = nextState + lowBits;
}
/* We need to add at most (ZSTD_WINDOWLOG_MAX_32 - 1) bits to read the maximum
@@ -937,102 +1169,100 @@ FORCE_INLINE_TEMPLATE seq_t
ZSTD_decodeSequence(seqState_t* seqState, const ZSTD_longOffset_e longOffsets)
{
seq_t seq;
- ZSTD_seqSymbol const llDInfo = seqState->stateLL.table[seqState->stateLL.state];
- ZSTD_seqSymbol const mlDInfo = seqState->stateML.table[seqState->stateML.state];
- ZSTD_seqSymbol const ofDInfo = seqState->stateOffb.table[seqState->stateOffb.state];
- U32 const llBase = llDInfo.baseValue;
- U32 const mlBase = mlDInfo.baseValue;
- U32 const ofBase = ofDInfo.baseValue;
- BYTE const llBits = llDInfo.nbAdditionalBits;
- BYTE const mlBits = mlDInfo.nbAdditionalBits;
- BYTE const ofBits = ofDInfo.nbAdditionalBits;
- BYTE const totalBits = llBits+mlBits+ofBits;
-
- /* sequence */
- { size_t offset;
- if (ofBits > 1) {
- ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
- ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
- assert(ofBits <= MaxOff);
- if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
- U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
- offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
- BIT_reloadDStream(&seqState->DStream);
- if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
- assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
- } else {
- offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
- }
- seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
- } else {
- U32 const ll0 = (llBase == 0);
- if (LIKELY((ofBits == 0))) {
- if (LIKELY(!ll0))
- offset = seqState->prevOffset[0];
- else {
- offset = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset;
+ const ZSTD_seqSymbol* const llDInfo = seqState->stateLL.table + seqState->stateLL.state;
+ const ZSTD_seqSymbol* const mlDInfo = seqState->stateML.table + seqState->stateML.state;
+ const ZSTD_seqSymbol* const ofDInfo = seqState->stateOffb.table + seqState->stateOffb.state;
+ seq.matchLength = mlDInfo->baseValue;
+ seq.litLength = llDInfo->baseValue;
+ { U32 const ofBase = ofDInfo->baseValue;
+ BYTE const llBits = llDInfo->nbAdditionalBits;
+ BYTE const mlBits = mlDInfo->nbAdditionalBits;
+ BYTE const ofBits = ofDInfo->nbAdditionalBits;
+ BYTE const totalBits = llBits+mlBits+ofBits;
+
+ U16 const llNext = llDInfo->nextState;
+ U16 const mlNext = mlDInfo->nextState;
+ U16 const ofNext = ofDInfo->nextState;
+ U32 const llnbBits = llDInfo->nbBits;
+ U32 const mlnbBits = mlDInfo->nbBits;
+ U32 const ofnbBits = ofDInfo->nbBits;
+ /*
+ * As gcc has better branch and block analyzers, sometimes it is only
+ * valuable to mark likelyness for clang, it gives around 3-4% of
+ * performance.
+ */
+
+ /* sequence */
+ { size_t offset;
+ #if defined(__clang__)
+ if (LIKELY(ofBits > 1)) {
+ #else
+ if (ofBits > 1) {
+ #endif
+ ZSTD_STATIC_ASSERT(ZSTD_lo_isLongOffset == 1);
+ ZSTD_STATIC_ASSERT(LONG_OFFSETS_MAX_EXTRA_BITS_32 == 5);
+ assert(ofBits <= MaxOff);
+ if (MEM_32bits() && longOffsets && (ofBits >= STREAM_ACCUMULATOR_MIN_32)) {
+ U32 const extraBits = ofBits - MIN(ofBits, 32 - seqState->DStream.bitsConsumed);
+ offset = ofBase + (BIT_readBitsFast(&seqState->DStream, ofBits - extraBits) << extraBits);
+ BIT_reloadDStream(&seqState->DStream);
+ if (extraBits) offset += BIT_readBitsFast(&seqState->DStream, extraBits);
+ assert(extraBits <= LONG_OFFSETS_MAX_EXTRA_BITS_32); /* to avoid another reload */
+ } else {
+ offset = ofBase + BIT_readBitsFast(&seqState->DStream, ofBits/*>0*/); /* <= (ZSTD_WINDOWLOG_MAX-1) bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream);
}
+ seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset;
} else {
- offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
- { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
- temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
- if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
- seqState->prevOffset[1] = seqState->prevOffset[0];
- seqState->prevOffset[0] = offset = temp;
- } } }
- seq.offset = offset;
- }
-
- seq.matchLength = mlBase;
- if (mlBits > 0)
- seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);
-
- if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
- BIT_reloadDStream(&seqState->DStream);
- if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
- BIT_reloadDStream(&seqState->DStream);
- /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
- ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
-
- seq.litLength = llBase;
- if (llBits > 0)
- seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);
-
- if (MEM_32bits())
- BIT_reloadDStream(&seqState->DStream);
-
- DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
- (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
-
- /* ANS state update
- * gcc-9.0.0 does 2.5% worse with ZSTD_updateFseStateWithDInfo().
- * clang-9.2.0 does 7% worse with ZSTD_updateFseState().
- * Naturally it seems like ZSTD_updateFseStateWithDInfo() should be the
- * better option, so it is the default for other compilers. But, if you
- * measure that it is worse, please put up a pull request.
- */
- {
-#if defined(__GNUC__) && !defined(__clang__)
- const int kUseUpdateFseState = 1;
-#else
- const int kUseUpdateFseState = 0;
-#endif
- if (kUseUpdateFseState) {
- ZSTD_updateFseState(&seqState->stateLL, &seqState->DStream); /* <= 9 bits */
- ZSTD_updateFseState(&seqState->stateML, &seqState->DStream); /* <= 9 bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- ZSTD_updateFseState(&seqState->stateOffb, &seqState->DStream); /* <= 8 bits */
- } else {
- ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llDInfo); /* <= 9 bits */
- ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlDInfo); /* <= 9 bits */
- if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
- ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofDInfo); /* <= 8 bits */
+ U32 const ll0 = (llDInfo->baseValue == 0);
+ if (LIKELY((ofBits == 0))) {
+ offset = seqState->prevOffset[ll0];
+ seqState->prevOffset[1] = seqState->prevOffset[!ll0];
+ seqState->prevOffset[0] = offset;
+ } else {
+ offset = ofBase + ll0 + BIT_readBitsFast(&seqState->DStream, 1);
+ { size_t temp = (offset==3) ? seqState->prevOffset[0] - 1 : seqState->prevOffset[offset];
+ temp += !temp; /* 0 is not valid; input is corrupted; force offset to 1 */
+ if (offset != 1) seqState->prevOffset[2] = seqState->prevOffset[1];
+ seqState->prevOffset[1] = seqState->prevOffset[0];
+ seqState->prevOffset[0] = offset = temp;
+ } } }
+ seq.offset = offset;
}
+
+ #if defined(__clang__)
+ if (UNLIKELY(mlBits > 0))
+ #else
+ if (mlBits > 0)
+ #endif
+ seq.matchLength += BIT_readBitsFast(&seqState->DStream, mlBits/*>0*/);
+
+ if (MEM_32bits() && (mlBits+llBits >= STREAM_ACCUMULATOR_MIN_32-LONG_OFFSETS_MAX_EXTRA_BITS_32))
+ BIT_reloadDStream(&seqState->DStream);
+ if (MEM_64bits() && UNLIKELY(totalBits >= STREAM_ACCUMULATOR_MIN_64-(LLFSELog+MLFSELog+OffFSELog)))
+ BIT_reloadDStream(&seqState->DStream);
+ /* Ensure there are enough bits to read the rest of data in 64-bit mode. */
+ ZSTD_STATIC_ASSERT(16+LLFSELog+MLFSELog+OffFSELog < STREAM_ACCUMULATOR_MIN_64);
+
+ #if defined(__clang__)
+ if (UNLIKELY(llBits > 0))
+ #else
+ if (llBits > 0)
+ #endif
+ seq.litLength += BIT_readBitsFast(&seqState->DStream, llBits/*>0*/);
+
+ if (MEM_32bits())
+ BIT_reloadDStream(&seqState->DStream);
+
+ DEBUGLOG(6, "seq: litL=%u, matchL=%u, offset=%u",
+ (U32)seq.litLength, (U32)seq.matchLength, (U32)seq.offset);
+
+ ZSTD_updateFseStateWithDInfo(&seqState->stateLL, &seqState->DStream, llNext, llnbBits); /* <= 9 bits */
+ ZSTD_updateFseStateWithDInfo(&seqState->stateML, &seqState->DStream, mlNext, mlnbBits); /* <= 9 bits */
+ if (MEM_32bits()) BIT_reloadDStream(&seqState->DStream); /* <= 18 bits */
+ ZSTD_updateFseStateWithDInfo(&seqState->stateOffb, &seqState->DStream, ofNext, ofnbBits); /* <= 8 bits */
}
return seq;
@@ -1085,9 +1315,11 @@ MEM_STATIC void ZSTD_assertValidSequence(
#endif
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
+
+
FORCE_INLINE_TEMPLATE size_t
DONT_VECTORIZE
-ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
+ZSTD_decompressSequences_bodySplitLitBuffer( ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
const void* seqStart, size_t seqSize, int nbSeq,
const ZSTD_longOffset_e isLongOffset,
@@ -1099,11 +1331,11 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
BYTE* const oend = ostart + maxDstSize;
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
- const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* litBufferEnd = dctx->litBufferEnd;
const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
const BYTE* const vBase = (const BYTE*) (dctx->virtualStart);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
- DEBUGLOG(5, "ZSTD_decompressSequences_body");
+ DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer");
(void)frame;
/* Regen sequences */
@@ -1124,55 +1356,237 @@ ZSTD_decompressSequences_body( ZSTD_DCtx* dctx,
BIT_DStream_endOfBuffer < BIT_DStream_completed &&
BIT_DStream_completed < BIT_DStream_overflow);
+ /* decompress without overrunning litPtr begins */
+ {
+ seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ /* Align the decompression loop to 32 + 16 bytes.
+ *
+ * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression
+ * speed swings based on the alignment of the decompression loop. This
+ * performance swing is caused by parts of the decompression loop falling
+ * out of the DSB. The entire decompression loop should fit in the DSB,
+ * when it can't we get much worse performance. You can measure if you've
+ * hit the good case or the bad case with this perf command for some
+ * compressed file test.zst:
+ *
+ * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \
+ * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst
+ *
+ * If you see most cycles served out of the MITE you've hit the bad case.
+ * If you see most cycles served out of the DSB you've hit the good case.
+ * If it is pretty even then you may be in an okay case.
+ *
+ * This issue has been reproduced on the following CPUs:
+ * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
+ * Use Instruments->Counters to get DSB/MITE cycles.
+ * I never got performance swings, but I was able to
+ * go from the good case of mostly DSB to half of the
+ * cycles served from MITE.
+ * - Coffeelake: Intel i9-9900k
+ * - Coffeelake: Intel i7-9700k
+ *
+ * I haven't been able to reproduce the instability or DSB misses on any
+ * of the following CPUS:
+ * - Haswell
+ * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH
+ * - Skylake
+ *
+ * Alignment is done for each of the three major decompression loops:
+ * - ZSTD_decompressSequences_bodySplitLitBuffer - presplit section of the literal buffer
+ * - ZSTD_decompressSequences_bodySplitLitBuffer - postsplit section of the literal buffer
+ * - ZSTD_decompressSequences_body
+ * Alignment choices are made to minimize large swings on bad cases and influence on performance
+ * from changes external to this code, rather than to overoptimize on the current commit.
+ *
+ * If you are seeing performance stability this script can help test.
+ * It tests on 4 commits in zstd where I saw performance change.
+ *
+ * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
+ */
#if defined(__GNUC__) && defined(__x86_64__)
- /* Align the decompression loop to 32 + 16 bytes.
- *
- * zstd compiled with gcc-9 on an Intel i9-9900k shows 10% decompression
- * speed swings based on the alignment of the decompression loop. This
- * performance swing is caused by parts of the decompression loop falling
- * out of the DSB. The entire decompression loop should fit in the DSB,
- * when it can't we get much worse performance. You can measure if you've
- * hit the good case or the bad case with this perf command for some
- * compressed file test.zst:
- *
- * perf stat -e cycles -e instructions -e idq.all_dsb_cycles_any_uops \
- * -e idq.all_mite_cycles_any_uops -- ./zstd -tq test.zst
- *
- * If you see most cycles served out of the MITE you've hit the bad case.
- * If you see most cycles served out of the DSB you've hit the good case.
- * If it is pretty even then you may be in an okay case.
- *
- * This issue has been reproduced on the following CPUs:
- * - Kabylake: Macbook Pro (15-inch, 2019) 2.4 GHz Intel Core i9
- * Use Instruments->Counters to get DSB/MITE cycles.
- * I never got performance swings, but I was able to
- * go from the good case of mostly DSB to half of the
- * cycles served from MITE.
- * - Coffeelake: Intel i9-9900k
- * - Coffeelake: Intel i7-9700k
- *
- * I haven't been able to reproduce the instability or DSB misses on any
- * of the following CPUS:
- * - Haswell
- * - Broadwell: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GH
- * - Skylake
- *
- * If you are seeing performance stability this script can help test.
- * It tests on 4 commits in zstd where I saw performance change.
- *
- * https://gist.github.com/terrelln/9889fc06a423fd5ca6e99351564473f4
- */
- __asm__(".p2align 6");
- __asm__("nop");
- __asm__(".p2align 5");
- __asm__("nop");
-# if __GNUC__ >= 9
- /* better for gcc-9 and gcc-10, worse for clang and gcc-8 */
- __asm__(".p2align 3");
+ __asm__(".p2align 6");
+# if __GNUC__ >= 7
+ /* good for gcc-7, gcc-9, and gcc-11 */
+ __asm__("nop");
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 4");
+# if __GNUC__ == 8 || __GNUC__ == 10
+ /* good for gcc-8 and gcc-10 */
+ __asm__("nop");
+ __asm__(".p2align 3");
+# endif
+# endif
+#endif
+
+ /* Handle the initial state where litBuffer is currently split between dst and litExtraBuffer */
+ for (; litPtr + sequence.litLength <= dctx->litBufferEnd; ) {
+ size_t const oneSeqSize = ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence.litLength - WILDCOPY_OVERLENGTH, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
+ BIT_reloadDStream(&(seqState.DStream));
+ sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ }
+
+ /* If there are more sequences, they will need to read literals from litExtraBuffer; copy over the remainder from dst and update litPtr and litEnd */
+ if (nbSeq > 0) {
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequence.litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ {
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (--nbSeq)
+ BIT_reloadDStream(&(seqState.DStream));
+ }
+ }
+ }
+
+ if (nbSeq > 0) /* there is remaining lit from extra buffer */
+ {
+
+#if defined(__GNUC__) && defined(__x86_64__)
+ __asm__(".p2align 6");
+ __asm__("nop");
+# if __GNUC__ != 7
+ /* worse for gcc-7 better for gcc-8, gcc-9, and gcc-10 and clang */
+ __asm__(".p2align 4");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# elif __GNUC__ >= 11
+ __asm__(".p2align 3");
+# else
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 3");
+# endif
+#endif
+
+ for (; ; ) {
+ seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litBufferEnd, prefixStart, vBase, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequence, prefixStart, vBase);
+#endif
+ if (UNLIKELY(ZSTD_isError(oneSeqSize)))
+ return oneSeqSize;
+ DEBUGLOG(6, "regenerated sequence size : %u", (U32)oneSeqSize);
+ op += oneSeqSize;
+ if (UNLIKELY(!--nbSeq))
+ break;
+ BIT_reloadDStream(&(seqState.DStream));
+ }
+ }
+
+ /* check if reached exact end */
+ DEBUGLOG(5, "ZSTD_decompressSequences_bodySplitLitBuffer: after decode loop, remaining nbSeq : %i", nbSeq);
+ RETURN_ERROR_IF(nbSeq, corruption_detected, "");
+ RETURN_ERROR_IF(BIT_reloadDStream(&seqState.DStream) < BIT_DStream_completed, corruption_detected, "");
+ /* save reps for next block */
+ { U32 i; for (i=0; i<ZSTD_REP_NUM; i++) dctx->entropy.rep[i] = (U32)(seqState.prevOffset[i]); }
+ }
+
+ /* last literal segment */
+ if (dctx->litBufferLocation == ZSTD_split) /* split hasn't been reached yet, first get dst then copy litExtraBuffer */
+ {
+ size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memmove(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ }
+ { size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memcpy(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ }
+
+ return op-ostart;
+}
+
+FORCE_INLINE_TEMPLATE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequences_body(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ const BYTE* ip = (const BYTE*)seqStart;
+ const BYTE* const iend = ip + seqSize;
+ BYTE* const ostart = (BYTE*)dst;
+ BYTE* const oend = dctx->litBufferLocation == ZSTD_not_in_dst ? ostart + maxDstSize : dctx->litBuffer;
+ BYTE* op = ostart;
+ const BYTE* litPtr = dctx->litPtr;
+ const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* const prefixStart = (const BYTE*)(dctx->prefixStart);
+ const BYTE* const vBase = (const BYTE*)(dctx->virtualStart);
+ const BYTE* const dictEnd = (const BYTE*)(dctx->dictEnd);
+ DEBUGLOG(5, "ZSTD_decompressSequences_body");
+ (void)frame;
+
+ /* Regen sequences */
+ if (nbSeq) {
+ seqState_t seqState;
+ dctx->fseEntropy = 1;
+ { U32 i; for (i = 0; i < ZSTD_REP_NUM; i++) seqState.prevOffset[i] = dctx->entropy.rep[i]; }
+ RETURN_ERROR_IF(
+ ERR_isError(BIT_initDStream(&seqState.DStream, ip, iend - ip)),
+ corruption_detected, "");
+ ZSTD_initFseState(&seqState.stateLL, &seqState.DStream, dctx->LLTptr);
+ ZSTD_initFseState(&seqState.stateOffb, &seqState.DStream, dctx->OFTptr);
+ ZSTD_initFseState(&seqState.stateML, &seqState.DStream, dctx->MLTptr);
+ assert(dst != NULL);
+
+ ZSTD_STATIC_ASSERT(
+ BIT_DStream_unfinished < BIT_DStream_completed &&
+ BIT_DStream_endOfBuffer < BIT_DStream_completed &&
+ BIT_DStream_completed < BIT_DStream_overflow);
+
+#if defined(__GNUC__) && defined(__x86_64__)
+ __asm__(".p2align 6");
+ __asm__("nop");
+# if __GNUC__ >= 7
+ __asm__(".p2align 5");
+ __asm__("nop");
+ __asm__(".p2align 3");
# else
- __asm__(".p2align 4");
+ __asm__(".p2align 4");
+ __asm__("nop");
+ __asm__(".p2align 3");
# endif
#endif
+
for ( ; ; ) {
seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequence, &litPtr, litEnd, prefixStart, vBase, dictEnd);
@@ -1218,6 +1632,16 @@ ZSTD_decompressSequences_default(ZSTD_DCtx* dctx,
{
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
}
+
+static size_t
+ZSTD_decompressSequencesSplitLitBuffer_default(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
@@ -1250,10 +1674,10 @@ ZSTD_decompressSequencesLong_body(
const BYTE* ip = (const BYTE*)seqStart;
const BYTE* const iend = ip + seqSize;
BYTE* const ostart = (BYTE*)dst;
- BYTE* const oend = ostart + maxDstSize;
+ BYTE* const oend = dctx->litBufferLocation == ZSTD_in_dst ? dctx->litBuffer : ostart + maxDstSize;
BYTE* op = ostart;
const BYTE* litPtr = dctx->litPtr;
- const BYTE* const litEnd = litPtr + dctx->litSize;
+ const BYTE* litBufferEnd = dctx->litBufferEnd;
const BYTE* const prefixStart = (const BYTE*) (dctx->prefixStart);
const BYTE* const dictStart = (const BYTE*) (dctx->virtualStart);
const BYTE* const dictEnd = (const BYTE*) (dctx->dictEnd);
@@ -1289,32 +1713,94 @@ ZSTD_decompressSequencesLong_body(
}
RETURN_ERROR_IF(seqNb<seqAdvance, corruption_detected, "");
- /* decode and decompress */
- for ( ; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb<nbSeq) ; seqNb++) {
- seq_t const sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
- size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
+ /* decompress without stomping litBuffer */
+ for (; (BIT_reloadDStream(&(seqState.DStream)) <= BIT_DStream_completed) && (seqNb < nbSeq); seqNb++) {
+ seq_t sequence = ZSTD_decodeSequence(&seqState, isLongOffset);
+ size_t oneSeqSize;
+
+ if (dctx->litBufferLocation == ZSTD_split && litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength > dctx->litBufferEnd)
+ {
+ /* lit buffer is reaching split point, empty out the first buffer and transition to litExtraBuffer */
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ oneSeqSize = ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
- assert(!ZSTD_isError(oneSeqSize));
- if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb-ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
#endif
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
- sequences[seqNb & STORED_SEQS_MASK] = sequence;
- op += oneSeqSize;
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb & STORED_SEQS_MASK] = sequence;
+ op += oneSeqSize;
+ }
+ else
+ {
+ /* lit buffer is either wholly contained in first or second split, or not split at all*/
+ oneSeqSize = dctx->litBufferLocation == ZSTD_split ?
+ ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK].litLength - WILDCOPY_OVERLENGTH, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :
+ ZSTD_execSequence(op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[(seqNb - ADVANCED_SEQS) & STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+
+ prefetchPos = ZSTD_prefetchMatch(prefetchPos, sequence, prefixStart, dictEnd);
+ sequences[seqNb & STORED_SEQS_MASK] = sequence;
+ op += oneSeqSize;
+ }
}
RETURN_ERROR_IF(seqNb<nbSeq, corruption_detected, "");
/* finish queue */
seqNb -= seqAdvance;
for ( ; seqNb<nbSeq ; seqNb++) {
- size_t const oneSeqSize = ZSTD_execSequence(op, oend, sequences[seqNb&STORED_SEQS_MASK], &litPtr, litEnd, prefixStart, dictStart, dictEnd);
+ seq_t *sequence = &(sequences[seqNb&STORED_SEQS_MASK]);
+ if (dctx->litBufferLocation == ZSTD_split && litPtr + sequence->litLength > dctx->litBufferEnd)
+ {
+ const size_t leftoverLit = dctx->litBufferEnd - litPtr;
+ if (leftoverLit)
+ {
+ RETURN_ERROR_IF(leftoverLit > (size_t)(oend - op), dstSize_tooSmall, "remaining lit must fit within dstBuffer");
+ ZSTD_safecopyDstBeforeSrc(op, litPtr, leftoverLit);
+ sequence->litLength -= leftoverLit;
+ op += leftoverLit;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ dctx->litBufferLocation = ZSTD_not_in_dst;
+ {
+ size_t const oneSeqSize = ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
- assert(!ZSTD_isError(oneSeqSize));
- if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
#endif
- if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
- op += oneSeqSize;
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ }
+ }
+ else
+ {
+ size_t const oneSeqSize = dctx->litBufferLocation == ZSTD_split ?
+ ZSTD_execSequenceSplitLitBuffer(op, oend, litPtr + sequence->litLength - WILDCOPY_OVERLENGTH, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd) :
+ ZSTD_execSequence(op, oend, *sequence, &litPtr, litBufferEnd, prefixStart, dictStart, dictEnd);
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && defined(FUZZING_ASSERT_VALID_SEQUENCE)
+ assert(!ZSTD_isError(oneSeqSize));
+ if (frame) ZSTD_assertValidSequence(dctx, op, oend, sequences[seqNb&STORED_SEQS_MASK], prefixStart, dictStart);
+#endif
+ if (ZSTD_isError(oneSeqSize)) return oneSeqSize;
+ op += oneSeqSize;
+ }
}
/* save reps for next block */
@@ -1322,10 +1808,21 @@ ZSTD_decompressSequencesLong_body(
}
/* last literal segment */
- { size_t const lastLLSize = litEnd - litPtr;
+ if (dctx->litBufferLocation == ZSTD_split) /* first deplete literal buffer in dst, then copy litExtraBuffer */
+ {
+ size_t const lastLLSize = litBufferEnd - litPtr;
+ RETURN_ERROR_IF(lastLLSize > (size_t)(oend - op), dstSize_tooSmall, "");
+ if (op != NULL) {
+ ZSTD_memmove(op, litPtr, lastLLSize);
+ op += lastLLSize;
+ }
+ litPtr = dctx->litExtraBuffer;
+ litBufferEnd = dctx->litExtraBuffer + ZSTD_LITBUFFEREXTRASIZE;
+ }
+ { size_t const lastLLSize = litBufferEnd - litPtr;
RETURN_ERROR_IF(lastLLSize > (size_t)(oend-op), dstSize_tooSmall, "");
if (op != NULL) {
- ZSTD_memcpy(op, litPtr, lastLLSize);
+ ZSTD_memmove(op, litPtr, lastLLSize);
op += lastLLSize;
}
}
@@ -1349,7 +1846,7 @@ ZSTD_decompressSequencesLong_default(ZSTD_DCtx* dctx,
#if DYNAMIC_BMI2
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
-static TARGET_ATTRIBUTE("bmi2") size_t
+static BMI2_TARGET_ATTRIBUTE size_t
DONT_VECTORIZE
ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
@@ -1359,10 +1856,20 @@ ZSTD_decompressSequences_bmi2(ZSTD_DCtx* dctx,
{
return ZSTD_decompressSequences_body(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
}
+static BMI2_TARGET_ATTRIBUTE size_t
+DONT_VECTORIZE
+ZSTD_decompressSequencesSplitLitBuffer_bmi2(ZSTD_DCtx* dctx,
+ void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ return ZSTD_decompressSequences_bodySplitLitBuffer(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_SHORT
-static TARGET_ATTRIBUTE("bmi2") size_t
+static BMI2_TARGET_ATTRIBUTE size_t
ZSTD_decompressSequencesLong_bmi2(ZSTD_DCtx* dctx,
void* dst, size_t maxDstSize,
const void* seqStart, size_t seqSize, int nbSeq,
@@ -1391,11 +1898,25 @@ ZSTD_decompressSequences(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
{
DEBUGLOG(5, "ZSTD_decompressSequences");
#if DYNAMIC_BMI2
- if (dctx->bmi2) {
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
return ZSTD_decompressSequences_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
}
#endif
- return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+ return ZSTD_decompressSequences_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+}
+static size_t
+ZSTD_decompressSequencesSplitLitBuffer(ZSTD_DCtx* dctx, void* dst, size_t maxDstSize,
+ const void* seqStart, size_t seqSize, int nbSeq,
+ const ZSTD_longOffset_e isLongOffset,
+ const int frame)
+{
+ DEBUGLOG(5, "ZSTD_decompressSequencesSplitLitBuffer");
+#if DYNAMIC_BMI2
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
+ return ZSTD_decompressSequencesSplitLitBuffer_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
+ }
+#endif
+ return ZSTD_decompressSequencesSplitLitBuffer_default(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
}
#endif /* ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG */
@@ -1415,7 +1936,7 @@ ZSTD_decompressSequencesLong(ZSTD_DCtx* dctx,
{
DEBUGLOG(5, "ZSTD_decompressSequencesLong");
#if DYNAMIC_BMI2
- if (dctx->bmi2) {
+ if (ZSTD_DCtx_get_bmi2(dctx)) {
return ZSTD_decompressSequencesLong_bmi2(dctx, dst, maxDstSize, seqStart, seqSize, nbSeq, isLongOffset, frame);
}
#endif
@@ -1456,7 +1977,7 @@ ZSTD_getLongOffsetsShare(const ZSTD_seqSymbol* offTable)
size_t
ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
- const void* src, size_t srcSize, const int frame)
+ const void* src, size_t srcSize, const int frame, const streaming_operation streaming)
{ /* blockType == blockCompressed */
const BYTE* ip = (const BYTE*)src;
/* isLongOffset must be true if there are long offsets.
@@ -1471,7 +1992,7 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
RETURN_ERROR_IF(srcSize >= ZSTD_BLOCKSIZE_MAX, srcSize_wrong, "");
/* Decode literals section */
- { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize);
+ { size_t const litCSize = ZSTD_decodeLiteralsBlock(dctx, src, srcSize, dst, dstCapacity, streaming);
DEBUGLOG(5, "ZSTD_decodeLiteralsBlock : %u", (U32)litCSize);
if (ZSTD_isError(litCSize)) return litCSize;
ip += litCSize;
@@ -1519,7 +2040,10 @@ ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
#ifndef ZSTD_FORCE_DECOMPRESS_SEQUENCES_LONG
/* else */
- return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
+ if (dctx->litBufferLocation == ZSTD_split)
+ return ZSTD_decompressSequencesSplitLitBuffer(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
+ else
+ return ZSTD_decompressSequences(dctx, dst, dstCapacity, ip, srcSize, nbSeq, isLongOffset, frame);
#endif
}
}
@@ -1542,7 +2066,7 @@ size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx,
{
size_t dSize;
ZSTD_checkContinuity(dctx, dst, dstCapacity);
- dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0);
+ dSize = ZSTD_decompressBlock_internal(dctx, dst, dstCapacity, src, srcSize, /* frame */ 0, not_streaming);
dctx->previousDstEnd = (char*)dst + dSize;
return dSize;
}
diff --git a/thirdparty/zstd/decompress/zstd_decompress_block.h b/thirdparty/zstd/decompress/zstd_decompress_block.h
index 049a0cd84c..c61a9d0c4b 100644
--- a/thirdparty/zstd/decompress/zstd_decompress_block.h
+++ b/thirdparty/zstd/decompress/zstd_decompress_block.h
@@ -33,6 +33,12 @@
*/
+ /* Streaming state is used to inform allocation of the literal buffer */
+typedef enum {
+ not_streaming = 0,
+ is_streaming = 1
+} streaming_operation;
+
/* ZSTD_decompressBlock_internal() :
* decompress block, starting at `src`,
* into destination buffer `dst`.
@@ -41,7 +47,7 @@
*/
size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
- const void* src, size_t srcSize, const int frame);
+ const void* src, size_t srcSize, const int frame, const streaming_operation streaming);
/* ZSTD_buildFSETable() :
* generate FSE decoding table for one symbol (ll, ml or off)
@@ -54,7 +60,7 @@ size_t ZSTD_decompressBlock_internal(ZSTD_DCtx* dctx,
*/
void ZSTD_buildFSETable(ZSTD_seqSymbol* dt,
const short* normalizedCounter, unsigned maxSymbolValue,
- const U32* baseValue, const U32* nbAdditionalBits,
+ const U32* baseValue, const U8* nbAdditionalBits,
unsigned tableLog, void* wksp, size_t wkspSize,
int bmi2);
diff --git a/thirdparty/zstd/decompress/zstd_decompress_internal.h b/thirdparty/zstd/decompress/zstd_decompress_internal.h
index ebda0c9031..2b5a53850a 100644
--- a/thirdparty/zstd/decompress/zstd_decompress_internal.h
+++ b/thirdparty/zstd/decompress/zstd_decompress_internal.h
@@ -20,7 +20,7 @@
* Dependencies
*********************************************************/
#include "../common/mem.h" /* BYTE, U16, U32 */
-#include "../common/zstd_internal.h" /* ZSTD_seqSymbol */
+#include "../common/zstd_internal.h" /* constants : MaxLL, MaxML, MaxOff, LLFSELog, etc. */
@@ -40,7 +40,7 @@ static UNUSED_ATTR const U32 OF_base[MaxOff+1] = {
0xFFFD, 0x1FFFD, 0x3FFFD, 0x7FFFD, 0xFFFFD, 0x1FFFFD, 0x3FFFFD, 0x7FFFFD,
0xFFFFFD, 0x1FFFFFD, 0x3FFFFFD, 0x7FFFFFD, 0xFFFFFFD, 0x1FFFFFFD, 0x3FFFFFFD, 0x7FFFFFFD };
-static UNUSED_ATTR const U32 OF_bits[MaxOff+1] = {
+static UNUSED_ATTR const U8 OF_bits[MaxOff+1] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23,
@@ -106,6 +106,22 @@ typedef struct {
size_t ddictPtrCount;
} ZSTD_DDictHashSet;
+#ifndef ZSTD_DECODER_INTERNAL_BUFFER
+# define ZSTD_DECODER_INTERNAL_BUFFER (1 << 16)
+#endif
+
+#define ZSTD_LBMIN 64
+#define ZSTD_LBMAX (128 << 10)
+
+/* extra buffer, compensates when dst is not large enough to store litBuffer */
+#define ZSTD_LITBUFFEREXTRASIZE BOUNDED(ZSTD_LBMIN, ZSTD_DECODER_INTERNAL_BUFFER, ZSTD_LBMAX)
+
+typedef enum {
+ ZSTD_not_in_dst = 0, /* Stored entirely within litExtraBuffer */
+ ZSTD_in_dst = 1, /* Stored entirely within dst (in memory after current output write) */
+ ZSTD_split = 2 /* Split between litExtraBuffer and dst */
+} ZSTD_litLocation_e;
+
struct ZSTD_DCtx_s
{
const ZSTD_seqSymbol* LLTptr;
@@ -136,7 +152,9 @@ struct ZSTD_DCtx_s
size_t litSize;
size_t rleSize;
size_t staticSize;
+#if DYNAMIC_BMI2 != 0
int bmi2; /* == 1 if the CPU supports BMI2 and 0 otherwise. CPU support is determined dynamically once per context lifetime. */
+#endif
/* dictionary */
ZSTD_DDict* ddictLocal;
@@ -158,16 +176,21 @@ struct ZSTD_DCtx_s
size_t outStart;
size_t outEnd;
size_t lhSize;
+#if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT>=1)
void* legacyContext;
U32 previousLegacyVersion;
U32 legacyVersion;
+#endif
U32 hostageByte;
int noForwardProgress;
ZSTD_bufferMode_e outBufferMode;
ZSTD_outBuffer expectedOutBuffer;
/* workspace */
- BYTE litBuffer[ZSTD_BLOCKSIZE_MAX + WILDCOPY_OVERLENGTH];
+ BYTE* litBuffer;
+ const BYTE* litBufferEnd;
+ ZSTD_litLocation_e litBufferLocation;
+ BYTE litExtraBuffer[ZSTD_LITBUFFEREXTRASIZE + WILDCOPY_OVERLENGTH]; /* literal buffer can be split between storage within dst and within this scratch buffer */
BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
size_t oversizedDuration;
@@ -183,6 +206,14 @@ struct ZSTD_DCtx_s
#endif
}; /* typedef'd to ZSTD_DCtx within "zstd.h" */
+MEM_STATIC int ZSTD_DCtx_get_bmi2(const struct ZSTD_DCtx_s *dctx) {
+#if DYNAMIC_BMI2 != 0
+ return dctx->bmi2;
+#else
+ (void)dctx;
+ return 0;
+#endif
+}
/*-*******************************************************
* Shared internal functions
diff --git a/thirdparty/zstd/zstd.h b/thirdparty/zstd/zstd.h
index 4651e6c4dc..a88ae7bf8e 100644
--- a/thirdparty/zstd/zstd.h
+++ b/thirdparty/zstd/zstd.h
@@ -20,19 +20,21 @@ extern "C" {
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
-#ifndef ZSTDLIB_VISIBILITY
-# if defined(__GNUC__) && (__GNUC__ >= 4)
-# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default")))
+#ifndef ZSTDLIB_VISIBLE
+# if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__MINGW32__)
+# define ZSTDLIB_VISIBLE __attribute__ ((visibility ("default")))
+# define ZSTDLIB_HIDDEN __attribute__ ((visibility ("hidden")))
# else
-# define ZSTDLIB_VISIBILITY
+# define ZSTDLIB_VISIBLE
+# define ZSTDLIB_HIDDEN
# endif
#endif
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
-# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY
+# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBLE
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
-# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
+# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBLE /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
-# define ZSTDLIB_API ZSTDLIB_VISIBILITY
+# define ZSTDLIB_API ZSTDLIB_VISIBLE
#endif
@@ -72,7 +74,7 @@ extern "C" {
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 5
-#define ZSTD_VERSION_RELEASE 0
+#define ZSTD_VERSION_RELEASE 2
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
/*! ZSTD_versionNumber() :
@@ -247,7 +249,7 @@ ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* dctx,
*
* It's possible to reset all parameters to "default" using ZSTD_CCtx_reset().
*
- * This API supercedes all other "advanced" API entry points in the experimental section.
+ * This API supersedes all other "advanced" API entry points in the experimental section.
* In the future, we expect to remove from experimental API entry points which are redundant with this API.
*/
@@ -417,7 +419,7 @@ typedef enum {
* ZSTD_c_stableOutBuffer
* ZSTD_c_blockDelimiters
* ZSTD_c_validateSequences
- * ZSTD_c_splitBlocks
+ * ZSTD_c_useBlockSplitter
* ZSTD_c_useRowMatchFinder
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly;
@@ -932,7 +934,7 @@ ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
* Advanced dictionary and prefix API (Requires v1.4.0+)
*
* This API allows dictionaries to be used with ZSTD_compress2(),
- * ZSTD_compressStream2(), and ZSTD_decompress(). Dictionaries are sticky, and
+ * ZSTD_compressStream2(), and ZSTD_decompressDCtx(). Dictionaries are sticky, and
* only reset with the context is reset with ZSTD_reset_parameters or
* ZSTD_reset_session_and_parameters. Prefixes are single-use.
******************************************************************************/
@@ -1073,25 +1075,36 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
+/* This can be overridden externally to hide static symbols. */
+#ifndef ZSTDLIB_STATIC_API
+# if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
+# define ZSTDLIB_STATIC_API __declspec(dllexport) ZSTDLIB_VISIBLE
+# elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
+# define ZSTDLIB_STATIC_API __declspec(dllimport) ZSTDLIB_VISIBLE
+# else
+# define ZSTDLIB_STATIC_API ZSTDLIB_VISIBLE
+# endif
+#endif
+
/* Deprecation warnings :
* Should these warnings be a problem, it is generally possible to disable them,
* typically with -Wno-deprecated-declarations for gcc or _CRT_SECURE_NO_WARNINGS in Visual.
* Otherwise, it's also possible to define ZSTD_DISABLE_DEPRECATE_WARNINGS.
*/
#ifdef ZSTD_DISABLE_DEPRECATE_WARNINGS
-# define ZSTD_DEPRECATED(message) ZSTDLIB_API /* disable deprecation warnings */
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API /* disable deprecation warnings */
#else
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
-# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_API
+# define ZSTD_DEPRECATED(message) [[deprecated(message)]] ZSTDLIB_STATIC_API
# elif (defined(GNUC) && (GNUC > 4 || (GNUC == 4 && GNUC_MINOR >= 5))) || defined(__clang__)
-# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated(message)))
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated(message)))
# elif defined(__GNUC__) && (__GNUC__ >= 3)
-# define ZSTD_DEPRECATED(message) ZSTDLIB_API __attribute__((deprecated))
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __attribute__((deprecated))
# elif defined(_MSC_VER)
-# define ZSTD_DEPRECATED(message) ZSTDLIB_API __declspec(deprecated(message))
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API __declspec(deprecated(message))
# else
# pragma message("WARNING: You need to implement ZSTD_DEPRECATED for this compiler")
-# define ZSTD_DEPRECATED(message) ZSTDLIB_API
+# define ZSTD_DEPRECATED(message) ZSTDLIB_STATIC_API
# endif
#endif /* ZSTD_DISABLE_DEPRECATE_WARNINGS */
@@ -1157,9 +1170,6 @@ ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
#define ZSTD_SRCSIZEHINT_MIN 0
#define ZSTD_SRCSIZEHINT_MAX INT_MAX
-/* internal */
-#define ZSTD_HASHLOG3_MAX 17
-
/* --- Advanced types --- */
@@ -1302,10 +1312,14 @@ typedef enum {
} ZSTD_literalCompressionMode_e;
typedef enum {
- ZSTD_urm_auto = 0, /* Automatically determine whether or not we use row matchfinder */
- ZSTD_urm_disableRowMatchFinder = 1, /* Never use row matchfinder */
- ZSTD_urm_enableRowMatchFinder = 2 /* Always use row matchfinder when applicable */
-} ZSTD_useRowMatchFinderMode_e;
+ /* Note: This enum controls features which are conditionally beneficial. Zstd typically will make a final
+ * decision on whether or not to enable the feature (ZSTD_ps_auto), but setting the switch to ZSTD_ps_enable
+ * or ZSTD_ps_disable allow for a force enable/disable the feature.
+ */
+ ZSTD_ps_auto = 0, /* Let the library automatically determine whether the feature shall be enabled */
+ ZSTD_ps_enable = 1, /* Force-enable the feature */
+ ZSTD_ps_disable = 2 /* Do not use the feature */
+} ZSTD_paramSwitch_e;
/***************************************
* Frame size functions
@@ -1332,7 +1346,7 @@ typedef enum {
* note 5 : ZSTD_findDecompressedSize handles multiple frames, and so it must traverse the input to
* read each contained frame header. This is fast as most of the data is skipped,
* however it does mean that all frame data must be present and valid. */
-ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize);
/*! ZSTD_decompressBound() :
* `src` should point to the start of a series of ZSTD encoded and/or skippable frames
@@ -1347,13 +1361,13 @@ ZSTDLIB_API unsigned long long ZSTD_findDecompressedSize(const void* src, size_t
* note 3 : when the decompressed size field isn't available, the upper-bound for that frame is calculated by:
* upper-bound = # blocks * min(128 KB, Window_Size)
*/
-ZSTDLIB_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize);
/*! ZSTD_frameHeaderSize() :
* srcSize must be >= ZSTD_FRAMEHEADERSIZE_PREFIX.
* @return : size of the Frame Header,
* or an error code (if srcSize is too small) */
-ZSTDLIB_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_frameHeaderSize(const void* src, size_t srcSize);
typedef enum {
ZSTD_sf_noBlockDelimiters = 0, /* Representation of ZSTD_Sequence has no block delimiters, sequences only */
@@ -1376,7 +1390,7 @@ typedef enum {
* @return : number of sequences generated
*/
-ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
+ZSTDLIB_STATIC_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
size_t outSeqsSize, const void* src, size_t srcSize);
/*! ZSTD_mergeBlockDelimiters() :
@@ -1390,7 +1404,7 @@ ZSTDLIB_API size_t ZSTD_generateSequences(ZSTD_CCtx* zc, ZSTD_Sequence* outSeqs,
* setting of ZSTD_c_blockDelimiters as ZSTD_sf_noBlockDelimiters
* @return : number of sequences left after merging
*/
-ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
+ZSTDLIB_STATIC_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t seqsSize);
/*! ZSTD_compressSequences() :
* Compress an array of ZSTD_Sequence, generated from the original source buffer, into dst.
@@ -1420,7 +1434,7 @@ ZSTDLIB_API size_t ZSTD_mergeBlockDelimiters(ZSTD_Sequence* sequences, size_t se
* and cannot emit an RLE block that disagrees with the repcode history
* @return : final compressed size or a ZSTD error.
*/
-ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
+ZSTDLIB_STATIC_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size_t dstSize,
const ZSTD_Sequence* inSeqs, size_t inSeqsSize,
const void* src, size_t srcSize);
@@ -1438,9 +1452,29 @@ ZSTDLIB_API size_t ZSTD_compressSequences(ZSTD_CCtx* const cctx, void* dst, size
*
* @return : number of bytes written or a ZSTD error.
*/
-ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
+ZSTDLIB_STATIC_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
const void* src, size_t srcSize, unsigned magicVariant);
+/*! ZSTD_readSkippableFrame() :
+ * Retrieves a zstd skippable frame containing data given by src, and writes it to dst buffer.
+ *
+ * The parameter magicVariant will receive the magicVariant that was supplied when the frame was written,
+ * i.e. magicNumber - ZSTD_MAGIC_SKIPPABLE_START. This can be NULL if the caller is not interested
+ * in the magicVariant.
+ *
+ * Returns an error if destination buffer is not large enough, or if the frame is not skippable.
+ *
+ * @return : number of bytes written or a ZSTD error.
+ */
+ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsigned* magicVariant,
+ const void* src, size_t srcSize);
+
+/*! ZSTD_isSkippableFrame() :
+ * Tells if the content of `buffer` starts with a valid Frame Identifier for a skippable frame.
+ */
+ZSTDLIB_API unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size);
+
+
/***************************************
* Memory management
@@ -1469,10 +1503,10 @@ ZSTDLIB_API size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCapacity,
* Note 2 : only single-threaded compression is supported.
* ZSTD_estimateCCtxSize_usingCCtxParams() will return an error code if ZSTD_c_nbWorkers is >= 1.
*/
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
-ZSTDLIB_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
-ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize(int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCCtxSize_usingCCtxParams(const ZSTD_CCtx_params* params);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDCtxSize(void);
/*! ZSTD_estimateCStreamSize() :
* ZSTD_estimateCStreamSize() will provide a budget large enough for any compression level up to selected one.
@@ -1487,20 +1521,20 @@ ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
* Note : if streaming is init with function ZSTD_init?Stream_usingDict(),
* an internal ?Dict will be created, which additional size is not estimated here.
* In this case, get total size by adding ZSTD_estimate?DictSize */
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
-ZSTDLIB_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
-ZSTDLIB_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
-ZSTDLIB_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize(int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCParams(ZSTD_compressionParameters cParams);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCStreamSize_usingCCtxParams(const ZSTD_CCtx_params* params);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize(size_t windowSize);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDStreamSize_fromFrame(const void* src, size_t srcSize);
/*! ZSTD_estimate?DictSize() :
* ZSTD_estimateCDictSize() will bet that src size is relatively "small", and content is copied, like ZSTD_createCDict().
* ZSTD_estimateCDictSize_advanced() makes it possible to control compression parameters precisely, like ZSTD_createCDict_advanced().
* Note : dictionaries created by reference (`ZSTD_dlm_byRef`) are logically smaller.
*/
-ZSTDLIB_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
-ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize(size_t dictSize, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateCDictSize_advanced(size_t dictSize, ZSTD_compressionParameters cParams, ZSTD_dictLoadMethod_e dictLoadMethod);
+ZSTDLIB_STATIC_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod);
/*! ZSTD_initStatic*() :
* Initialize an object using a pre-allocated fixed-size buffer.
@@ -1523,20 +1557,20 @@ ZSTDLIB_API size_t ZSTD_estimateDDictSize(size_t dictSize, ZSTD_dictLoadMethod_e
* Limitation 2 : static cctx currently not compatible with multi-threading.
* Limitation 3 : static dctx is incompatible with legacy support.
*/
-ZSTDLIB_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
-ZSTDLIB_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
+ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_initStaticCCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_initStaticCStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticCCtx() */
-ZSTDLIB_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
-ZSTDLIB_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
+ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_initStaticDCtx(void* workspace, size_t workspaceSize);
+ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_initStaticDStream(void* workspace, size_t workspaceSize); /**< same as ZSTD_initStaticDCtx() */
-ZSTDLIB_API const ZSTD_CDict* ZSTD_initStaticCDict(
+ZSTDLIB_STATIC_API const ZSTD_CDict* ZSTD_initStaticCDict(
void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams);
-ZSTDLIB_API const ZSTD_DDict* ZSTD_initStaticDDict(
+ZSTDLIB_STATIC_API const ZSTD_DDict* ZSTD_initStaticDDict(
void* workspace, size_t workspaceSize,
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
@@ -1557,44 +1591,44 @@ __attribute__((__unused__))
#endif
ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< this constant defers to stdlib's functions */
-ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
+ZSTDLIB_STATIC_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
ZSTD_compressionParameters cParams,
ZSTD_customMem customMem);
-/* ! Thread pool :
- * These prototypes make it possible to share a thread pool among multiple compression contexts.
- * This can limit resources for applications with multiple threads where each one uses
- * a threaded compression mode (via ZSTD_c_nbWorkers parameter).
- * ZSTD_createThreadPool creates a new thread pool with a given number of threads.
- * Note that the lifetime of such pool must exist while being used.
- * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
- * to use an internal thread pool).
- * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
+/*! Thread pool :
+ * These prototypes make it possible to share a thread pool among multiple compression contexts.
+ * This can limit resources for applications with multiple threads where each one uses
+ * a threaded compression mode (via ZSTD_c_nbWorkers parameter).
+ * ZSTD_createThreadPool creates a new thread pool with a given number of threads.
+ * Note that the lifetime of such pool must exist while being used.
+ * ZSTD_CCtx_refThreadPool assigns a thread pool to a context (use NULL argument value
+ * to use an internal thread pool).
+ * ZSTD_freeThreadPool frees a thread pool, accepts NULL pointer.
*/
typedef struct POOL_ctx_s ZSTD_threadPool;
-ZSTDLIB_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
-ZSTDLIB_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
-ZSTDLIB_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
+ZSTDLIB_STATIC_API ZSTD_threadPool* ZSTD_createThreadPool(size_t numThreads);
+ZSTDLIB_STATIC_API void ZSTD_freeThreadPool (ZSTD_threadPool* pool); /* accept NULL pointer */
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refThreadPool(ZSTD_CCtx* cctx, ZSTD_threadPool* pool);
/*
* This API is temporary and is expected to change or disappear in the future!
*/
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced2(
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_advanced2(
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
const ZSTD_CCtx_params* cctxParams,
ZSTD_customMem customMem);
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
+ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_advanced(
const void* dict, size_t dictSize,
ZSTD_dictLoadMethod_e dictLoadMethod,
ZSTD_dictContentType_e dictContentType,
@@ -1611,22 +1645,22 @@ ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(
* As a consequence, `dictBuffer` **must** outlive CDict,
* and its content must remain unmodified throughout the lifetime of CDict.
* note: equivalent to ZSTD_createCDict_advanced(), with dictLoadMethod==ZSTD_dlm_byRef */
-ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
+ZSTDLIB_STATIC_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_getCParams() :
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
* `estimatedSrcSize` value is optional, select 0 if not known */
-ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
+ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_getParams() :
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
* All fields of `ZSTD_frameParameters` are set to default : contentSize=1, checksum=0, noDictID=0 */
-ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
+ZSTDLIB_STATIC_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_checkCParams() :
* Ensure param values remain within authorized range.
* @return 0 on success, or an error code (can be checked with ZSTD_isError()) */
-ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
+ZSTDLIB_STATIC_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
/*! ZSTD_adjustCParams() :
* optimize params for a given `srcSize` and `dictSize`.
@@ -1634,7 +1668,7 @@ ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
* `dictSize` must be `0` when there is no dictionary.
* cPar can be invalid : all parameters will be clamped within valid range in the @return struct.
* This function never fails (wide contract) */
-ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
+ZSTDLIB_STATIC_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
/*! ZSTD_compress_advanced() :
* Note : this function is now DEPRECATED.
@@ -1662,18 +1696,18 @@ size_t ZSTD_compress_usingCDict_advanced(ZSTD_CCtx* cctx,
/*! ZSTD_CCtx_loadDictionary_byReference() :
* Same as ZSTD_CCtx_loadDictionary(), but dictionary content is referenced, instead of being copied into CCtx.
* It saves some memory, but also requires that `dict` outlives its usage within `cctx` */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_byReference(ZSTD_CCtx* cctx, const void* dict, size_t dictSize);
/*! ZSTD_CCtx_loadDictionary_advanced() :
* Same as ZSTD_CCtx_loadDictionary(), but gives finer control over
* how to load the dictionary (by copy ? by reference ?)
* and how to interpret it (automatic ? force raw mode ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_loadDictionary_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_CCtx_refPrefix_advanced() :
* Same as ZSTD_CCtx_refPrefix(), but gives finer control over
* how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
/* === experimental parameters === */
/* these parameters can be used with ZSTD_setParameter()
@@ -1712,9 +1746,15 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
* See the comments on that enum for an explanation of the feature. */
#define ZSTD_c_forceAttachDict ZSTD_c_experimentalParam4
-/* Controls how the literals are compressed (default is auto).
- * The value must be of type ZSTD_literalCompressionMode_e.
- * See ZSTD_literalCompressionMode_e enum definition for details.
+/* Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never compress literals.
+ * Set to ZSTD_ps_enable to always compress literals. (Note: uncompressed literals
+ * may still be emitted if huffman is not beneficial to use.)
+ *
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * literals compression based on the compression parameters - specifically,
+ * negative compression levels do not use literal compression.
*/
#define ZSTD_c_literalCompressionMode ZSTD_c_experimentalParam5
@@ -1777,7 +1817,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
*
* Note that this means that the CDict tables can no longer be copied into the
* CCtx, so the dict attachment mode ZSTD_dictForceCopy will no longer be
- * useable. The dictionary can only be attached or reloaded.
+ * usable. The dictionary can only be attached or reloaded.
*
* In general, you should expect compression to be faster--sometimes very much
* so--and CDict creation to be slightly slower. Eventually, we will probably
@@ -1866,23 +1906,26 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
*/
#define ZSTD_c_validateSequences ZSTD_c_experimentalParam12
-/* ZSTD_c_splitBlocks
- * Default is 0 == disabled. Set to 1 to enable block splitting.
+/* ZSTD_c_useBlockSplitter
+ * Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never use block splitter.
+ * Set to ZSTD_ps_enable to always use block splitter.
*
- * Will attempt to split blocks in order to improve compression ratio at the cost of speed.
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * block splitting based on the compression parameters.
*/
-#define ZSTD_c_splitBlocks ZSTD_c_experimentalParam13
+#define ZSTD_c_useBlockSplitter ZSTD_c_experimentalParam13
/* ZSTD_c_useRowMatchFinder
- * Default is ZSTD_urm_auto.
- * Controlled with ZSTD_useRowMatchFinderMode_e enum.
+ * Controlled with ZSTD_paramSwitch_e enum.
+ * Default is ZSTD_ps_auto.
+ * Set to ZSTD_ps_disable to never use row-based matchfinder.
+ * Set to ZSTD_ps_enable to force usage of row-based matchfinder.
*
- * By default, in ZSTD_urm_auto, when finalizing the compression parameters, the library
- * will decide at runtime whether to use the row-based matchfinder based on support for SIMD
- * instructions as well as the windowLog.
- *
- * Set to ZSTD_urm_disableRowMatchFinder to never use row-based matchfinder.
- * Set to ZSTD_urm_enableRowMatchFinder to force usage of row-based matchfinder.
+ * By default, in ZSTD_ps_auto, the library will decide at runtime whether to use
+ * the row-based matchfinder based on support for SIMD instructions and the window log.
+ * Note that this only pertains to compression strategies: greedy, lazy, and lazy2
*/
#define ZSTD_c_useRowMatchFinder ZSTD_c_experimentalParam14
@@ -1911,7 +1954,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_refPrefix_advanced(ZSTD_CCtx* cctx, const void* pre
* and store it into int* value.
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter param, int* value);
/*! ZSTD_CCtx_params :
@@ -1931,25 +1974,25 @@ ZSTDLIB_API size_t ZSTD_CCtx_getParameter(const ZSTD_CCtx* cctx, ZSTD_cParameter
* This can be used with ZSTD_estimateCCtxSize_advanced_usingCCtxParams()
* for static allocation of CCtx for single-threaded compression.
*/
-ZSTDLIB_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
-ZSTDLIB_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
+ZSTDLIB_STATIC_API ZSTD_CCtx_params* ZSTD_createCCtxParams(void);
+ZSTDLIB_STATIC_API size_t ZSTD_freeCCtxParams(ZSTD_CCtx_params* params); /* accept NULL pointer */
/*! ZSTD_CCtxParams_reset() :
* Reset params to default values.
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_reset(ZSTD_CCtx_params* params);
/*! ZSTD_CCtxParams_init() :
* Initializes the compression parameters of cctxParams according to
* compression level. All other parameters are reset to their default values.
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init(ZSTD_CCtx_params* cctxParams, int compressionLevel);
/*! ZSTD_CCtxParams_init_advanced() :
* Initializes the compression and frame parameters of cctxParams according to
* params. All other parameters are reset to their default values.
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, ZSTD_parameters params);
/*! ZSTD_CCtxParams_setParameter() : Requires v1.4.0+
* Similar to ZSTD_CCtx_setParameter.
@@ -1959,14 +2002,14 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_init_advanced(ZSTD_CCtx_params* cctxParams, Z
* @result : a code representing success or failure (which can be tested with
* ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_setParameter(ZSTD_CCtx_params* params, ZSTD_cParameter param, int value);
/*! ZSTD_CCtxParams_getParameter() :
* Similar to ZSTD_CCtx_getParameter.
* Get the requested value of one compression parameter, selected by enum ZSTD_cParameter.
* @result : 0, or an error code (which can be tested with ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
+ZSTDLIB_STATIC_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params, ZSTD_cParameter param, int* value);
/*! ZSTD_CCtx_setParametersUsingCCtxParams() :
* Apply a set of ZSTD_CCtx_params to the compression context.
@@ -1975,7 +2018,7 @@ ZSTDLIB_API size_t ZSTD_CCtxParams_getParameter(const ZSTD_CCtx_params* params,
* if nbWorkers>=1, new parameters will be picked up at next job,
* with a few restrictions (windowLog, pledgedSrcSize, nbWorkers, jobSize, and overlapLog are not updated).
*/
-ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
+ZSTDLIB_STATIC_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
ZSTD_CCtx* cctx, const ZSTD_CCtx_params* params);
/*! ZSTD_compressStream2_simpleArgs() :
@@ -1984,7 +2027,7 @@ ZSTDLIB_API size_t ZSTD_CCtx_setParametersUsingCCtxParams(
* This variant might be helpful for binders from dynamic languages
* which have troubles handling structures containing memory pointers.
*/
-ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
+ZSTDLIB_STATIC_API size_t ZSTD_compressStream2_simpleArgs (
ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos,
@@ -2000,33 +2043,33 @@ ZSTDLIB_API size_t ZSTD_compressStream2_simpleArgs (
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
* Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
* Note 3 : Skippable Frame Identifiers are considered valid. */
-ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
+ZSTDLIB_STATIC_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
/*! ZSTD_createDDict_byReference() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* Dictionary content is referenced, and therefore stays in dictBuffer.
* It is important that dictBuffer outlives DDict,
* it must remain read accessible throughout the lifetime of DDict */
-ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
+ZSTDLIB_STATIC_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
/*! ZSTD_DCtx_loadDictionary_byReference() :
* Same as ZSTD_DCtx_loadDictionary(),
* but references `dict` content instead of copying it into `dctx`.
* This saves memory if `dict` remains around.,
* However, it's imperative that `dict` remains accessible (and unmodified) while being used, so it must outlive decompression. */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_byReference(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
/*! ZSTD_DCtx_loadDictionary_advanced() :
* Same as ZSTD_DCtx_loadDictionary(),
* but gives direct control over
* how to load the dictionary (by copy ? by reference ?)
* and how to interpret it (automatic ? force raw mode ? full mode only ?). */
-ZSTDLIB_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_loadDictionary_advanced(ZSTD_DCtx* dctx, const void* dict, size_t dictSize, ZSTD_dictLoadMethod_e dictLoadMethod, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_DCtx_refPrefix_advanced() :
* Same as ZSTD_DCtx_refPrefix(), but gives finer control over
* how to interpret prefix content (automatic ? force raw mode (default) ? full mode only ?) */
-ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* prefix, size_t prefixSize, ZSTD_dictContentType_e dictContentType);
/*! ZSTD_DCtx_setMaxWindowSize() :
* Refuses allocating internal buffers for frames requiring a window size larger than provided limit.
@@ -2035,14 +2078,14 @@ ZSTDLIB_API size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx, const void* pre
* By default, a decompression context accepts all window sizes <= (1 << ZSTD_WINDOWLOG_LIMIT_DEFAULT)
* @return : 0, or an error code (which can be tested using ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_setMaxWindowSize(ZSTD_DCtx* dctx, size_t maxWindowSize);
/*! ZSTD_DCtx_getParameter() :
* Get the requested decompression parameter value, selected by enum ZSTD_dParameter,
* and store it into int* value.
* @return : 0, or an error code (which can be tested with ZSTD_isError()).
*/
-ZSTDLIB_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
+ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value);
/* ZSTD_d_format
* experimental parameter,
@@ -2131,7 +2174,7 @@ size_t ZSTD_DCtx_setFormat(ZSTD_DCtx* dctx, ZSTD_format_e format);
* This can be helpful for binders from dynamic languages
* which have troubles handling structures containing memory pointers.
*/
-ZSTDLIB_API size_t ZSTD_decompressStream_simpleArgs (
+ZSTDLIB_STATIC_API size_t ZSTD_decompressStream_simpleArgs (
ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity, size_t* dstPos,
const void* src, size_t srcSize, size_t* srcPos);
@@ -2205,7 +2248,7 @@ size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs,
* This function is DEPRECATED, and equivalent to:
* ZSTD_CCtx_reset(zcs, ZSTD_reset_session_only);
* ZSTD_CCtx_refCDict(zcs, cdict);
- *
+ *
* note : cdict will just be referenced, and must outlive compression session
* This prototype will generate compilation warnings.
*/
@@ -2270,7 +2313,7 @@ typedef struct {
* Note : (ingested - consumed) is amount of input data buffered internally, not yet compressed.
* Aggregates progression inside active worker threads.
*/
-ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
+ZSTDLIB_STATIC_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx);
/*! ZSTD_toFlushNow() :
* Tell how many bytes are ready to be flushed immediately.
@@ -2285,7 +2328,7 @@ ZSTDLIB_API ZSTD_frameProgression ZSTD_getFrameProgression(const ZSTD_CCtx* cctx
* therefore flush speed is limited by production speed of oldest job
* irrespective of the speed of concurrent (and newer) jobs.
*/
-ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
+ZSTDLIB_STATIC_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
/*===== Advanced Streaming decompression functions =====*/
@@ -2299,7 +2342,7 @@ ZSTDLIB_API size_t ZSTD_toFlushNow(ZSTD_CCtx* cctx);
* note: no dictionary will be used if dict == NULL or dictSize < 8
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
*/
-ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
+ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
/*!
* This function is deprecated, and is equivalent to:
@@ -2310,7 +2353,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dic
* note : ddict is referenced, it must outlive decompression session
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
*/
-ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
+ZSTDLIB_STATIC_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);
/*!
* This function is deprecated, and is equivalent to:
@@ -2320,7 +2363,7 @@ ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDi
* re-use decompression parameters from previous init; saves dictionary loading
* Note : this prototype will be marked as deprecated and generate compilation warnings on reaching v1.5.x
*/
-ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
+ZSTDLIB_STATIC_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
/*********************************************************************
@@ -2362,13 +2405,13 @@ ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds);
*/
/*===== Buffer-less streaming compression functions =====*/
-ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
-ZSTDLIB_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
-ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict); /**< note: fails if cdict==NULL */
+ZSTDLIB_STATIC_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**< note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
-ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/* The ZSTD_compressBegin_advanced() and ZSTD_compressBegin_usingCDict_advanced() are now DEPRECATED and will generate a compiler warning */
ZSTD_DEPRECATED("use advanced API to access custom parameters")
@@ -2465,24 +2508,24 @@ typedef struct {
* @return : 0, `zfhPtr` is correctly filled,
* >0, `srcSize` is too small, value is wanted `srcSize` amount,
* or an error code, which can be tested using ZSTD_isError() */
-ZSTDLIB_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
+ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize); /**< doesn't consume input */
/*! ZSTD_getFrameHeader_advanced() :
* same as ZSTD_getFrameHeader(),
* with added capability to select a format (like ZSTD_f_zstd1_magicless) */
-ZSTDLIB_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
-ZSTDLIB_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
+ZSTDLIB_STATIC_API size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, size_t srcSize, ZSTD_format_e format);
+ZSTDLIB_STATIC_API size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long long frameContentSize); /**< when frame content size is not known, pass in frameContentSize == ZSTD_CONTENTSIZE_UNKNOWN */
-ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
-ZSTDLIB_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBegin_usingDDict(ZSTD_DCtx* dctx, const ZSTD_DDict* ddict);
-ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
-ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/* misc */
-ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
+ZSTDLIB_STATIC_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
-ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
+ZSTDLIB_STATIC_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
@@ -2519,10 +2562,10 @@ ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
*/
/*===== Raw zstd block functions =====*/
-ZSTDLIB_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
-ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
-ZSTDLIB_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
+ZSTDLIB_STATIC_API size_t ZSTD_getBlockSize (const ZSTD_CCtx* cctx);
+ZSTDLIB_STATIC_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
+ZSTDLIB_STATIC_API size_t ZSTD_insertBlock (ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert uncompressed block into `dctx` history. Useful for multi-blocks decompression. */
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */